commit d5046a0dafc4c558e5bd68918d905362711a3455 Author: MacPro Date: Thu Apr 9 15:03:31 2026 -0500 Add StartOS 0.4.0 packaging diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..701cfb1 Binary files /dev/null and b/.DS_Store differ diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..64696e5 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,44 @@ +# User data (never bake personal data into the image) +history/ +config/ +cookies.txt +.env + +# Build artifacts +*.s9pk +image.tar +javascript/ + +# macOS artifacts +.DS_Store +*.command + +# Local dev files (not needed in container) +GET-STARTED.* +build-guide-pdf.py +create-app.sh +setup.sh +Start Summarizer.command +YouTube Summarizer.app/ + +# StartOS packaging files (not part of the app image) +startos/ +start9/ +s9pk.mk +Makefile +package.json +package-lock.json +tsconfig.json +icon.png +icon.svg +LICENSE +CONTRIBUTING.md +README.md + +# Game plan / docs +START9_PACKAGING_GAMEPLAN.md +assets/ABOUT.md + +# Git +.git/ +.github/ diff --git a/.env b/.env new file mode 100644 index 0000000..9890465 --- /dev/null +++ b/.env @@ -0,0 +1,4 @@ +# Paste your Gemini API key here so all devices can use it without entering it manually. +# Get one at https://aistudio.google.com/apikey +GEMINI_API_KEY=AIzaSyCRgBDFOqZ7stlHkIsuLUbxc2Wz1iGqGAE +YT_COOKIES_FROM=firefox \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..dd3ba77 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,62 @@ +# ───────────────────────────────────────────────────────── +# YouTube Summarizer — StartOS 0.4 Docker image +# +# Includes: Node.js 20, Python 3, yt-dlp, ffmpeg +# +# Uses Debian slim (not Alpine) because: +# - yt-dlp's --impersonate chrome requires curl_cffi (compiled C extension) +# - curl_cffi's prebuilt wheels target glibc, not musl +# - Debian is more reliable for pip-installed packages with C deps +# ───────────────────────────────────────────────────────── + +# ── Stage 1: Install Node.js dependencies ────────────────── +FROM node:20-slim AS builder + +WORKDIR /app/server +COPY server/package.json server/package-lock.json* ./ +RUN npm ci --production --ignore-scripts 2>/dev/null || npm install --production --ignore-scripts + +# ── Stage 2: Final runtime image ─────────────────────────── +FROM node:20-slim AS runner + +WORKDIR /app + +# Install runtime dependencies: +# - dumb-init: proper PID 1 signal handling in containers +# - curl: health checks + yt-dlp binary downloads +# - python3 + pip: yt-dlp installation and updates +# - ffmpeg: audio extraction, splitting, and duration detection +# - ca-certificates: HTTPS for YouTube/Gemini API calls +RUN apt-get update && apt-get install -y --no-install-recommends \ + dumb-init \ + curl \ + python3 \ + python3-pip \ + python3-venv \ + ffmpeg \ + ca-certificates \ + && rm -rf /var/lib/apt/lists/* \ + && pip3 install --break-system-packages yt-dlp curl_cffi \ + && yt-dlp --version + +# Copy Node.js app from builder +COPY --from=builder /app/server/node_modules ./server/node_modules/ +COPY server/package.json ./server/ +COPY server/index.js ./server/ +COPY public/ ./public/ +COPY assets/ ./assets/ + +# Copy entrypoint scripts +COPY docker_entrypoint.sh /usr/local/bin/docker_entrypoint.sh +RUN chmod +x /usr/local/bin/docker_entrypoint.sh + +# Create persistent data mount point +RUN mkdir -p /data + +ENV NODE_ENV=production \ + PORT=3001 \ + DATA_DIR=/data + +EXPOSE 3001 + +ENTRYPOINT ["dumb-init", "--", "/usr/local/bin/docker_entrypoint.sh"] diff --git a/GET-STARTED.md b/GET-STARTED.md new file mode 100644 index 0000000..bf8e341 --- /dev/null +++ b/GET-STARTED.md @@ -0,0 +1,198 @@ +# YouTube Transcript Summarizer — Mac Setup Guide + +This is a step-by-step guide to get the app running on your Mac. No prior experience with servers or Terminal needed. + +--- + +## What you're setting up + +This app has two parts: + +1. **A small server** that runs locally on your Mac (not on the internet — only you can access it). It downloads YouTube audio and talks to Google's Gemini AI. +2. **A webpage** you open in your browser that connects to that local server. + +Nothing is uploaded anywhere. Everything runs on your machine. + +--- + +## Where to save the project + +The `youtube-summarizer` folder you downloaded from Cowork can live anywhere, but the conventional place for projects like this on a Mac is: + +``` +~/Projects/youtube-summarizer +``` + +`~` means your home folder (e.g., `/Users/grant`). If you don't have a `Projects` folder yet, you'll create one below. + +**To move the files there:** + +1. Open **Finder** +2. Go to your home folder (press `Cmd + Shift + H`) +3. Create a new folder called `Projects` if you don't have one (right-click → New Folder) +4. Drag the `youtube-summarizer` folder from your Cowork downloads into `Projects` + +You should end up with this structure: + +``` +~/Projects/youtube-summarizer/ +├── public/ +│ └── index.html ← the app you open in your browser +├── server/ +│ ├── index.js ← the backend server code +│ └── package.json ← lists the server's dependencies +├── setup.sh ← automatic setup script +└── GET-STARTED.md ← this file +``` + +--- + +## Step 1: Install Node.js (if you don't have it) + +Node.js is what runs the server. Check if you already have it: + +1. Open **Terminal** (press `Cmd + Space`, type "Terminal", hit Enter) +2. Type this and press Enter: + +```bash +node --version +``` + +- If you see a version number like `v20.11.0` → you're good, skip to Step 2 +- If you see "command not found" → install it: + 1. Go to **https://nodejs.org** + 2. Download the **LTS** version (the green button) + 3. Open the downloaded `.pkg` file and follow the installer + 4. Close and reopen Terminal, then try `node --version` again + +--- + +## Step 2: Run the setup script + +This installs yt-dlp (the YouTube audio downloader) and the server's dependencies. In Terminal: + +```bash +cd ~/Projects/youtube-summarizer +bash setup.sh +``` + +You should see checkmarks for Node.js, yt-dlp, and the server dependencies. If yt-dlp isn't found and can't auto-install, run: + +```bash +brew install yt-dlp +``` + +(If you don't have Homebrew either, install it first from **https://brew.sh** — it's a one-line Terminal command shown on their homepage.) + +--- + +## Step 3: Start the server + +```bash +cd ~/Projects/youtube-summarizer/server +npm start +``` + +You should see: + +``` + YouTube Summarizer API running on http://localhost:3001 + ✓ yt-dlp 2025.x.x (up to date) +``` + +**Leave this Terminal window open.** The server runs as long as this window is open. To stop it later, press `Ctrl + C`. + +--- + +## Step 4: Open the app + +Open the webpage in your browser. The easiest way — open a **new** Terminal tab (`Cmd + T`) and run: + +```bash +open ~/Projects/youtube-summarizer/public/index.html +``` + +Or just double-click `index.html` in Finder. It opens like any webpage. + +--- + +## Step 5: Add your Gemini API key + +1. In the app, click **"Gemini API Settings"** to expand it +2. Paste your Gemini API key into the API Key field +3. Pick a model (the default `gemini-2.0-flash` is fast and cheap) + +**Don't have a key yet?** Get one free: +1. Go to **https://aistudio.google.com/apikey** +2. Sign in with your Google account +3. Click "Create API Key" +4. Copy the key and paste it in the app + +Your key is saved in your browser's localStorage so you don't have to re-enter it each time. + +--- + +## Step 6: Summarize a video + +1. Paste a YouTube URL +2. Click **Summarize** +3. Watch the 3-step pipeline: Download audio → Transcribe → Analyze topics +4. Click any topic section to expand the full transcript with clickable timestamps + +--- + +## Day-to-day usage + +Each time you want to use the app: + +1. Open Terminal +2. Run: +```bash +cd ~/Projects/youtube-summarizer/server && npm start +``` +3. Open `index.html` in your browser (bookmark it for easy access) +4. When done, press `Ctrl + C` in Terminal to stop the server + +That's it. Two commands. + +--- + +## Troubleshooting + +**"Cannot connect to backend at localhost:3001"** +→ The server isn't running. Go back to Step 3. + +**"yt-dlp not installed"** +→ Run `brew install yt-dlp` in Terminal, then restart the server. + +**Download fails or hangs** +→ yt-dlp might be outdated. The app will try to auto-update it, but you can also manually run: +```bash +yt-dlp -U +``` + +**"Gemini API error: 403" or "401"** +→ Your API key is invalid or expired. Get a new one from https://aistudio.google.com/apikey + +**Long videos take a while** +→ Normal. A 1-hour video takes ~30 seconds to download audio, then 30-60 seconds for Gemini to transcribe, then another 10-20 seconds for topic analysis. The app shows live progress. + +--- + +## Optional: Make it even easier to start + +You can create a shortcut so you just double-click to launch everything. In Terminal: + +```bash +cat > ~/Projects/youtube-summarizer/start.command << 'EOF' +#!/bin/bash +cd "$(dirname "$0")/server" +echo "Starting YouTube Summarizer..." +echo "Press Ctrl+C to stop." +echo "" +npm start +EOF +chmod +x ~/Projects/youtube-summarizer/start.command +``` + +Now you have a `start.command` file in the project folder. Double-click it to launch the server — it opens Terminal automatically. Then just open `index.html` in your browser. diff --git a/GET-STARTED.pdf b/GET-STARTED.pdf new file mode 100644 index 0000000..bcf1e36 --- /dev/null +++ b/GET-STARTED.pdf @@ -0,0 +1,194 @@ +%PDF-1.4 +% ReportLab Generated PDF document (opensource) +1 0 obj +<< +/F1 2 0 R /F2 3 0 R /F3 4 0 R +>> +endobj +2 0 obj +<< +/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font +>> +endobj +3 0 obj +<< +/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font +>> +endobj +4 0 obj +<< +/BaseFont /Courier /Encoding /WinAnsiEncoding /Name /F3 /Subtype /Type1 /Type /Font +>> +endobj +5 0 obj +<< +/Contents 15 0 R /MediaBox [ 0 0 612 792 ] /Parent 14 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +6 0 obj +<< +/Contents 16 0 R /MediaBox [ 0 0 612 792 ] /Parent 14 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +7 0 obj +<< +/Contents 17 0 R /MediaBox [ 0 0 612 792 ] /Parent 14 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +8 0 obj +<< +/Contents 18 0 R /MediaBox [ 0 0 612 792 ] /Parent 14 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +9 0 obj +<< +/Contents 19 0 R /MediaBox [ 0 0 612 792 ] /Parent 14 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +10 0 obj +<< +/Contents 20 0 R /MediaBox [ 0 0 612 792 ] /Parent 14 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +11 0 obj +<< +/Contents 21 0 R /MediaBox [ 0 0 612 792 ] /Parent 14 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +12 0 obj +<< +/PageMode /UseNone /Pages 14 0 R /Type /Catalog +>> +endobj +13 0 obj +<< +/Author (\(anonymous\)) /CreationDate (D:20260213152439+00'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20260213152439+00'00') /Producer (ReportLab PDF Library - \(opensource\)) + /Subject (\(unspecified\)) /Title (\(anonymous\)) /Trapped /False +>> +endobj +14 0 obj +<< +/Count 7 /Kids [ 5 0 R 6 0 R 7 0 R 8 0 R 9 0 R 10 0 R 11 0 R ] /Type /Pages +>> +endobj +15 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1395 +>> +stream +Gau0CgN)%,&:N/3lq>Ak@m^Ain`%%-9jDnjeu>&$FN,sF$&Q#\Jd"H@mUYnU?1=RjU1?<)CQBbP"Cf]KF*8@o@,WbU?DALuLCe(d-r:-,$E-<3#iEPSE:VV6Furuj0Q7,KgF"'Il`N5P=,Ag/IHCO7!fI78&F)_Y9`L?"=>'i2MAK9gdSduWc?$/:ItW+Oi@T`?_qF'?&FP;UctpILAd=:?4Wr&*#qQ9km`_fK+$c=)d#\[J+i?7cW:,q\:HNC-n-Bdrf-O\QBe6]+G'4mWK;UVH-uADAk6^[,Q[*Wp!J7S<\\OmQ;u6H5;D\pHi-6:t3G,KTFQ@fjHn5#YajQ_9\U4c*5Vo9QN`Wjg3>N?TV%'V7'/`J3$@#]?_CNtP#piXks"e%@;VcniCS;E8cC[RXTj&e'@NlQ22GqdO@TgqJdFF^=YXuS5EY(9*.=jESjZL_Z''d4&g_]n;(8Imf$8NLX^'B`'4NL]Wn]/n]OP6cYGXr2o<$=)gS`(4L`,-(U!dGE9We+4-]HVcUQ9dOEdLaSrO\$Tqckcefj&?(5@aI6L6^f9*9"E6c8HkG):Q#qD>`fVqgu&`BNBGPJL)Fke@Ti903)#6%\toiK=eVL&8'OrR%=S;eVgHk[T1lUEcY'S=9_6WAD-:u\psJ0d_$9!\:1mO)>`NH3_t).cK\=lKNk1MC](K.('2o_2ft'#gL`"ZefUtG4J[_$76bB%s7;msO8%9s:T\I:ApX%_O7P)Or$[s`I*Nk[?'p0Pom^N@#=C(apY+SS&,/dT1RN?)\VFZ\9:S1Y!?%"O9?2D!J<=@2d8I?5,FhO]G@Gfoh#rSDG.;:uSc"krCY;9_I5L&pQgi[2/9i=8\I5UFnO.KLhH[%c0[lca-BPC3G9+*mu)Pk-P(R`9HGNNTU@uEbk)2k+\4'Ah(ljS.6$rIDh;PAnrCJHN,O4HuQLYe1=?O%K[m7i/F7j!LDRP6D&/7`R@SdECWW?/[,]g/4CmE,8J;hG46S1M,6Mk]@pJcR5!(urA\75Ae2<(Dp'BZiQ1kt'Lbf'%r;"o/`JqR%)Z$?ddT42/u@ep#CKAu1ZnC^?0!`QL..9.1qruH[)UR^l/A'124/4^(Tg7g'OoMn2WGd(b!+[W*_ZeC7aI'EJ&Wendstream +endobj +16 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 294 +>> +stream +Gaqcqb>,u0$q9pdMT]HS*bqY..\-_^&;:ROJ`[2(RSGrn(MUHHHos#8#].VgI-ku$'4O`5WjW0#1p.o+PX*in9P2XI.("44oWtN;R;c$9/iGf[lI#>Q"BXuL2aS/=.a&u,`VDEE9N"LS'Rh\PI:A:)VP&;08jW!VfBRJW!T5Gb0H#3oHRB?q3*\]jTJ'GY@B(=NQZ,#,29O!LbPPZb@$gG?c6^S=Ql^5[kG>&QW$oE:TTB!Znq!UF/L8^ag6Nm";G`N`W~>endstream +endobj +17 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1376 +>> +stream +Gau0C;/bG`&:Vs/(njtRD6U]3(nA&lGF(sLD,Z!8^#qB#Lf41iKX#@&7*>`_:(mFcElq.AcA5_(NII]!@b0/N)^&0N.?(-mW2&8%QmrTrV:$/+)OO1c+E6&`;5Vd;'G9Yqrt5n]8)#*6\iHVl@j0GN20O'u'sj:K2D7LioI[m)aO"EFN%65uBVn;#5TGHZRT$u.T>o(!3$pFuKd6MLpq4##YRgqX33$V/)[_"YqKllcY0"p-,A>]O&fP[rTUC+:lL+!V9"^\9[E'Z=1gn7)2.o1TN6AghY>(]T_hT,[S7r(@>(_t)8MHKC"^Js6j82>LYdn4YY9WjV]Le]V0sY]-&&o9a72V/#][+C%#%%s]Z[`rSaJ:dQYbI1pHTos'>]a?rRfY]6#h@j.C>qGiI]u;g-Q`1g1'-g9-Zo;);[!sohgF9Mkp+fV@Tr4`E)gH<1JCH1ZJB0=_:0c`?5p4p%P)GT]eHmV0;gd%a=B.!-GHC_d">Q&%C>nG`8+t^cL5.cKS@A)J%Sct+]Ugf@G*54oT`E(0ao!p&WiZ"C59p'F5bHE?GRb&LDGnBoZ(+9)I#rV+f<-Jo-&^4(2T;s;fNV<>!:j]tXl+Dl6:nRk99jXc4*$O%s)X@97CV4a&DOAF+*S`7(ae;3+pQZd/Ll=M%Sbhd/k4kk'\m6L$i&oW^g^;r%V\mZnGLa-Y@/h.\5u`$/Q=puGfm41$f)*s6:3afuhIfNX\-Y69K^k23c0WBV6PlP+"2bMtjH#\$h$3%m]=gR:@1mr0EMXQNkMIb7cVgNdXI;HD0[Nfs:rU1'jYq?mX#a)nD+D5a\FA#^p7'@K;>4U:XF>VpO*$g??5go\>TlH-g_2[mV*4-p:9iSTV]$?T?rCQi_Fp0$?Dkf7JMdqSD,N@#(L1pm@a-SpTs(l1,nsjl2rf<:C@j!W6bt#c^6sSJ$b4D9S!AS@L6CM7H$]Y.Z+:$)Hu.89a%4CZi>&o5Q?&D"k9(h5o8uL>Jb3tu4-;abWij+pPi*FC\r3T9iB^55a]iSoCM".R6D55-Ce's,'"rjg]U"kI*Im:8i@%5DGVA>*)M+6.A/$EZRF^k(Y)RSkhU3#'X:?iX6W^+Jf7"0SaWaLUdTV:c4+QoSRrZt7Q'F$V6Ppp4;UJ?IjZIsAhA'o;FK6@CpN@%$PQ(ZcR@.7~>endstream +endobj +18 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 197 +>> +stream +GapXOaUZ0A$q0R[MRfu_KK>p2\:WYW"j&t?;IE9?O>)NUbV=5t8ol0X;X9RTbsIC0)?^t[tWHP"+#1C>h2~>endstream +endobj +19 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1482 +>> +stream +Gatm:?#SIU'Rf_Z\198_/Rhl4Vr`[7m^a/_!]4]B%0cUF89DdN+uP78k<81@muip+/9[b(8K?KA6sZC2Gj`,/J<)?m5Doa(9b-c="@rOg)G&pXOIs?Bq;dSC)-/)`(I775\/_\uI_8bc&U8ceP:Q`q,a#X:XsP!Cm%Yqi2]+Q*^c.C.`5J3QB\#MWKJV>?U&nUT=LINHaM1%?g2-X:^@#g.UtMtp!+$4,R?-7!rOHiJb_Ohu;S-^NnIG'?Cq&g9ZrC`M^;q?FHHe]n,])Z[mn9T2YiQ.b,W1AfY6X='et7%8D`nrgo`D$gHdZ;"p;mf'Vj;m`p<3L8&OT%/ttT0%qS"U,D)1\?(F&CXoq3nPe+s4SYK4@1E]YSInoG>@oGlLS'R),q[NV9.jZH'BG%.Y#$*@_uEbNMd'/QQ7Xc$LVXT[T-o5MGC38mFaITl.BH>*iNYUO,:PQ[@_^:me5g)Zd?W01`OX%7'Bi:f3sI]>N`IlkT/mI3\YXO,(3__@QZkRs3b^ZB.F!P+k%'>?eI3fC]ZW/dC/,8F)6kD!-+aJ$KC9"&T(ti-)SS:+%0DO>MWtE#mO-TTj['/&,BWY1:R3<%DV#(qkV7ahDY%!:Im"#7r-2uKV[:f>R+,7m%V8%>t~>endstream +endobj +20 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 410 +>> +stream +GatUn;,>(P'SYH=/'aWTEEHCF[TB4fR2@^mA$Qp%ieD5W!d2mt0C?1bkE8!L9n6Ko]mM1mOiF'm>W0BW_"Bhobog=Y).='e\.aMh!So76:,6cLNq/QsqSPV=:d?k1]W:;/d&p$+PAJI?BjC7Y^b([FJm6t^C,IJV?*5o8G`,St^+,NSklPI6dn$COPU!#a>>t2UES3W@`AdoLVJHK\o%$aL5G1+-,U7Q=Xi&$/X]H!UUPstEK5G/GV6&uYN(2Gj*u&7`(%">]en0o_LS[.daRfEUjoj!\APcO)Y#*^#.tj1>:p/28f%=_9fknsTd.=:Fo-CEELC\RgHZA]OU"k$?L:6;QqJVs"p+@cT"lg`48GRp-90(8mZ'Ft>,l?ss7)Bendstream +endobj +21 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1025 +>> +stream +Gatm:bAu>q']&X:mV#P,A'k:mLZD_^D5K+W]Z`">KLhIu$j%s[>#?(6p0L"KSMZ5WNZuc))N_Jli1,]-;':,2pg*UocRZO%N<2hJ\cnNK)-!fufBVA!$Tbt(PXu3..I_I"9h)6WPg+4W.krsi?-`+h]gZdlr\FV)5_+-<;8*[5jF0d6p4`PgQj`hBfQ&J(Qin'?q)=e;0@,!3g4R=5$++:AM%hYdr$>%=`Z,A[tC\B&9g,K&R3bRX[%N&IEfM*7^@.W`q$C]XY-Bok5To1F8cTM]$j0nZUm&)nrnbK4@Up$h0V3@()Yk/A[umCXOrp!jeDcB!rA8S_##7*(`G5"J)2=W0k-lHYE0H(OH-NGd]]2SqHCr!kdrFrd0#:Qo8@PUIou4Lm*d%@E77(u&QP_)%ab/r1TP6kU"/AgA@Q7Q2ri.F#4o07f6cnbD;`h3f2%S&YWZEp[Tl[pmK"8lk3.PIqcD%34,On"^>hD;8'?IscDLPe7ed=OUI4gs!K?C^MT#p]i[?EFJ~>endstream +endobj +xref +0 22 +0000000000 65535 f +0000000061 00000 n +0000000112 00000 n +0000000219 00000 n +0000000331 00000 n +0000000436 00000 n +0000000631 00000 n +0000000826 00000 n +0000001021 00000 n +0000001216 00000 n +0000001411 00000 n +0000001607 00000 n +0000001803 00000 n +0000001873 00000 n +0000002154 00000 n +0000002252 00000 n +0000003739 00000 n +0000004124 00000 n +0000005592 00000 n +0000005880 00000 n +0000007454 00000 n +0000007955 00000 n +trailer +<< +/ID +[] +% ReportLab generated PDF document -- digest (opensource) + +/Info 13 0 R +/Root 12 0 R +/Size 22 +>> +startxref +9072 +%%EOF diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..9d2709f --- /dev/null +++ b/LICENSE @@ -0,0 +1,10 @@ +Proprietary License + +Copyright (c) 2026. All rights reserved. + +This software and associated documentation files (the "Software") are +proprietary. Unauthorized copying, modification, distribution, or use +of this Software, via any medium, is strictly prohibited without prior +written permission from the copyright holder. + +The Software is provided "as is", without warranty of any kind. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..944084a --- /dev/null +++ b/Makefile @@ -0,0 +1,2 @@ +# overrides to s9pk.mk must precede the include statement +include s9pk.mk diff --git a/START9_PACKAGING_GAMEPLAN.md b/START9_PACKAGING_GAMEPLAN.md new file mode 100644 index 0000000..3aaf992 --- /dev/null +++ b/START9_PACKAGING_GAMEPLAN.md @@ -0,0 +1,842 @@ +# YouTube Summarizer: StartOS 0.4.0 Packaging Game Plan + +**Date:** April 9, 2026 +**Status:** Feasibility Assessment & Implementation Roadmap +**Target:** StartOS 0.4.0 Beta (s9pk package format) +**Reference:** Workout Log packaging for StartOS 0.3.5 + +--- + +## Executive Summary + +Packaging the YouTube Summarizer for StartOS 0.4.0 is **feasible** but presents unique challenges that a typical web app does not. The app is more than a simple CRUD service -- it downloads audio from YouTube (requiring yt-dlp to always be current), authenticates against YouTube to bypass bot detection, transcribes audio via the Gemini API, and manages podcast RSS feeds. Running this on a headless remote server introduces three core challenges that require thoughtful solutions: + +1. **yt-dlp must stay current** -- YouTube changes its anti-bot signatures regularly, so a stale yt-dlp binary means broken downloads within days or weeks. +2. **YouTube authentication without a local browser** -- The current app relies on cookies from your local browser or a cookies.txt file. A remote server has no browser session. +3. **Server/datacenter IP reputation** -- YouTube is more aggressive about blocking downloads from non-residential IPs. + +All three are solvable. This document lays out the approach for each, plus the full packaging plan. + +--- + +## Table of Contents + +1. [Current App Architecture](#1-current-app-architecture) +2. [What Changes for StartOS](#2-what-changes-for-startos) +3. [Challenge 1: Keeping yt-dlp Updated](#3-challenge-1-keeping-yt-dlp-updated) +4. [Challenge 2: YouTube Authentication on a Headless Server](#4-challenge-2-youtube-authentication-on-a-headless-server) +5. [Challenge 3: Server IP Bot Detection](#5-challenge-3-server-ip-bot-detection) +6. [StartOS 0.4.0 Packaging Structure](#6-startos-040-packaging-structure) +7. [Differences from v0.3.5 Packaging (Workout Log)](#7-differences-from-v035-packaging-workout-log) +8. [Implementation Phases](#8-implementation-phases) +9. [Persistent Data Contract](#9-persistent-data-contract) +10. [Ongoing Maintenance Plan](#10-ongoing-maintenance-plan) +11. [Risk Assessment](#11-risk-assessment) +12. [Multi-User Distribution: API Keys and Clean Installs](#12-multi-user-distribution-api-keys-and-clean-installs) +13. [Appendix A: File-by-File Packaging Checklist](#appendix-a-file-by-file-packaging-checklist) +14. [Appendix B: Reusable Packaging Roadmap for Future Apps](#appendix-b-reusable-packaging-roadmap-for-future-apps) + +--- + +## 1. Current App Architecture + +The YouTube Summarizer is a Node.js application with these components: + +**Backend (server/index.js -- ~1800 lines):** +- Express.js server on port 3001 +- Calls yt-dlp as a child process to download audio from YouTube +- Downloads podcast episodes directly via HTTP +- Uploads audio to Google Gemini File API for transcription +- Runs topic analysis via Gemini (multiple model fallback chain) +- Manages subscriptions (YouTube channels + podcast RSS feeds) +- Auto-queue system: checks subscriptions for new content, queues for approval +- Cookie management: supports cookies.txt file and --cookies-from-browser flag +- yt-dlp auto-update: checks GitHub releases every 24h, updates via self-update / brew / pip +- History storage: JSON files on disk (not a database) +- Health check endpoint at /api/health +- Heartbeat/auto-sleep system (shuts down when no browser connected for 30s) + +**Frontend (public/index.html):** +- Single-page app, served as static files by Express +- Split-screen layout: video embed + topic summaries +- Subscription management UI +- Cookie upload/test UI +- Settings panel for API key and model selection + +**External Dependencies:** +- yt-dlp (system binary, called via child_process) +- ffmpeg (required by yt-dlp for audio extraction) +- Node.js 20+ +- Google Gemini API (requires API key) + +**Data Storage (all in /history/ directory):** +- Individual summary JSON files (one per processed video/podcast) +- subscriptions.json (channel/feed list) +- _meta.json (folder structure for organizing summaries) +- seen-list.json, skip-list.json (dedup tracking) +- auto-queue.json (pending items from subscription checks) +- cookies.txt (YouTube authentication) +- .env (Gemini API key, cookie browser preference) + +--- + +## 2. What Changes for StartOS + +### Things That Work As-Is +- The Express server, Gemini API integration, and frontend are platform-agnostic +- Podcast RSS feed parsing (direct HTTP, no auth needed) +- History/subscription JSON storage +- Health check endpoint + +### Things That Need Adaptation + +| Current Behavior | StartOS Adaptation | +|---|---| +| Runs on macOS with Homebrew | Docker container on Alpine Linux (ARM64) | +| yt-dlp installed via brew | yt-dlp installed via pip in container, self-updates at runtime | +| Cookies from local Firefox/Chrome | cookies.txt uploaded via web UI (already supported) + OAuth2 | +| Auto-sleep when no browser connected | Remove sleep logic; service runs continuously | +| Hardcoded port 3001 | Configurable, default 3001, mapped via StartOS interfaces | +| .env file for config | StartOS config UI (manifest config spec) | +| macOS .app bundle / launcher | Not needed; StartOS manages service lifecycle | +| LAN mode dialog | Not needed; StartOS handles network exposure (Tor + LAN) | + +--- + +## 3. Challenge 1: Keeping yt-dlp Updated + +### The Problem +YouTube frequently changes its download mechanisms and anti-bot measures. A yt-dlp version that works today may stop working within 1-2 weeks. The app already handles this with a multi-strategy auto-update (self-update, brew, pip), but inside a Docker container on StartOS, brew is not available and we need a reliable update path. + +### The Solution: Runtime Self-Update with Persistent Storage + +**Strategy:** +1. Install yt-dlp via pip at Docker **build time** (gives a known-good starting point) +2. Store the yt-dlp binary on the **persistent volume** (`/data/bin/yt-dlp`) so updates survive container restarts +3. On each container start, check if the persistent binary exists and is newer than the built-in one; use whichever is newer +4. The existing auto-update logic runs `yt-dlp -U` (self-update) which writes to the pip site-packages, but we can also add a dedicated update mechanism that downloads the latest binary directly from GitHub releases to `/data/bin/yt-dlp` + +**Implementation in docker_entrypoint.sh:** +```bash +#!/bin/sh +set -eu + +DATA_DIR="/data" +BIN_DIR="$DATA_DIR/bin" +YTDLP_LOCAL="$BIN_DIR/yt-dlp" + +mkdir -p "$BIN_DIR" "$DATA_DIR/history" "$DATA_DIR/config" + +# Use persistent yt-dlp if available, otherwise fall back to system +if [ -x "$YTDLP_LOCAL" ]; then + export PATH="$BIN_DIR:$PATH" + echo "Using persistent yt-dlp: $($YTDLP_LOCAL --version)" +else + echo "Using system yt-dlp: $(yt-dlp --version)" +fi + +# Start the Node.js server +exec node /app/server/index.js +``` + +**Auto-update enhancement in server code:** +- Modify `autoUpdateYtdlp()` to: (1) try `yt-dlp -U`, (2) try `pip install -U yt-dlp`, (3) as a last resort, download the latest binary directly from `https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp` and save to `/data/bin/yt-dlp` +- Add a scheduled check: on server startup and every 12 hours, check for updates +- Expose update status in the health check endpoint so StartOS can surface it + +**Why this works on StartOS:** +- `/data` is the persistent StartOS volume; it survives container restarts and package upgrades +- The container image provides a baseline yt-dlp that works at build time +- Runtime updates keep it fresh without rebuilding the entire package +- If a runtime update breaks something, removing `/data/bin/yt-dlp` reverts to the built-in version + +### Also: ffmpeg +ffmpeg is a build-time dependency (Alpine package `ffmpeg`). It rarely needs updates for this use case, so installing it in the Dockerfile is sufficient. It is updated whenever you rebuild and push a new package version. + +--- + +## 4. Challenge 2: YouTube Authentication on a Headless Server + +### The Problem +YouTube increasingly requires authentication to download content. The current app supports two methods: +1. **cookies.txt file** -- a Netscape-format cookie export from a browser +2. **--cookies-from-browser** -- reads cookies directly from a local browser's cookie store + +On a remote StartOS server, there is no local browser, so method 2 is unavailable. + +### The Solution: Three-Tier Authentication + +**Tier 1: OAuth2 Device Flow (Primary -- Best Option)** + +yt-dlp now supports OAuth2 authentication with a device code flow, which is perfect for headless servers: + +```bash +yt-dlp --username oauth --password '' +``` + +How it works: +- On first use, yt-dlp prints a code and a URL (https://www.google.com/device) +- The user opens that URL on any device (phone, laptop) and enters the code +- A refresh token is cached in yt-dlp's cache directory +- All subsequent downloads use the cached token -- no further interaction needed + +For StartOS integration: +- Mount yt-dlp's cache directory on the persistent volume (`/data/ytdlp-cache/`) +- Add a "Setup YouTube Auth" action in the StartOS manifest that triggers the OAuth flow and displays the device code in the service logs or a dedicated endpoint +- Build a simple UI page in the web frontend that shows the device code and instructions +- The token persists across restarts because it lives on `/data` + +**Tier 2: cookies.txt Upload (Fallback)** + +The app already has a full cookies.txt management system via the web UI: +- Upload endpoint: POST /api/cookies/upload +- Test endpoint: POST /api/cookies/test +- Status endpoint: GET /api/cookies/status +- Delete endpoint: POST /api/cookies/delete + +This works on StartOS as-is. The cookies.txt file should be stored on the persistent volume (`/data/cookies.txt`) instead of the project root. + +**Important caveat:** YouTube cookies expire in approximately 3-5 days. This means the user would need to re-export and re-upload cookies regularly. This is why OAuth2 is the recommended primary method. + +**Tier 3: No Authentication (Limited)** + +Some YouTube content can be downloaded without any authentication. The app already handles this gracefully -- it attempts download without cookies if cookie-based download fails. This will work for some videos but not all, especially age-restricted or bot-flagged content. + +### Implementation Priority +1. Add OAuth2 support to the server code (new endpoint to initiate flow, display code, check status) +2. Move cookies.txt storage to persistent volume +3. Remove --cookies-from-browser logic (not applicable on remote server) +4. Add a clear "Authentication Setup" section in the web UI that guides through OAuth2 first, cookies.txt as backup + +--- + +## 5. Challenge 3: Server IP Bot Detection + +### The Problem +YouTube maintains IP reputation databases. Residential ISP IPs (like your home connection) are generally trusted, but datacenter IPs are frequently flagged. A Start9 server running at home on your residential IP should actually be fine -- this is a significant advantage of self-hosted infrastructure. + +### Assessment: Low Risk for Start9 Home Servers + +**Start9 servers typically run at home on a residential IP.** This means: +- The server's IP is a normal residential ISP address +- YouTube treats these the same as any home computer +- Bot detection is primarily triggered by datacenter/cloud IPs (AWS, GCP, Azure, etc.) +- Rate limiting may still occur with heavy usage, but this is the same as running the app on your Mac + +**When it could be a problem:** +- If you access the Start9 server through a VPN and route yt-dlp traffic through the VPN +- If your ISP uses CGNAT (carrier-grade NAT) which shares IPs with many users +- If you process a very high volume of downloads in a short period + +### Mitigation Strategies (Built Into the App) + +The app already has several mitigations that carry over directly: + +1. **Retry with exponential backoff** -- the download logic already retries with 30s, 60s, 120s delays when rate-limited +2. **Cookie/OAuth authentication** -- authenticated requests are less likely to trigger bot detection +3. **yt-dlp auto-update** -- newer yt-dlp versions include workarounds for the latest YouTube anti-bot measures + +**Additional measures to add for StartOS:** +1. **Rate limiting between downloads** -- when processing auto-queue items from subscriptions, add configurable delays between downloads (e.g., 30-60 seconds between videos) +2. **Download scheduling** -- spread subscription checks and downloads across the day rather than bursting +3. **Proxy support (optional)** -- add a config option for users to specify a SOCKS5 or HTTP proxy if they want to route yt-dlp traffic through a specific connection. This is an advanced option, not required for most users. +4. **Browser impersonation** -- yt-dlp supports `--impersonate chrome` which mimics Chrome's TLS fingerprint. Add this as a default argument. + +### Summary +For a home Start9 server, YouTube bot detection is **not a significant concern**. The residential IP is the same one you'd be using from your Mac. Combined with OAuth2 authentication and yt-dlp staying current, this should work reliably. + +--- + +## 6. StartOS 0.4.0 Packaging Structure + +### Key Changes from 0.3.5 + +StartOS 0.4.0 is a complete rewrite. The major packaging-relevant changes: + +| Aspect | 0.3.5 | 0.4.0 | +|---|---|---| +| Container runtime | Podman | LXC (Linux Containers) | +| Package format | s9pk (same name, different internals) | s9pk with signatures, partial downloads, multi-arch | +| Dev tooling | Shell/make-based | TypeScript SDK available | +| Networking | Tor + LAN | Same, with improved LAN port forwarding | +| Backups | Not compatible across versions | Fresh backups required after migration | + +### Package Files Needed + +Based on the workout-log template and v0.4.0 documentation: + +``` +start9/ + 0.4/ + manifest.yaml # Service metadata, config spec, interfaces + Dockerfile # Multi-stage build for ARM64 + docker_entrypoint.sh # Service startup script + healthcheck.sh # Health check script + Makefile # Build automation + instructions.md # User-facing documentation + LICENSE # License file + icon.png # Service icon + DEPLOY.md # Deploy/sideload instructions +``` + +### Draft manifest.yaml + +```yaml +id: youtube-summarizer +title: YouTube Summarizer +version: 0.1.0.1 +release-notes: >- + Initial StartOS package. YouTube/podcast audio download, + transcription via Gemini, and topic analysis. +license: Proprietary +wrapper-repo: https://github.com/user/youtube-summarizer-startos +upstream-repo: https://github.com/user/youtube-summarizer +support-site: https://github.com/user/youtube-summarizer/issues +marketing-site: https://github.com/user/youtube-summarizer +build: ["make image-arm"] + +description: + short: Download, transcribe, and summarize YouTube videos and podcasts. + long: >- + YouTube Summarizer downloads audio from YouTube videos and podcast feeds, + transcribes them using Google Gemini, and produces structured topic + summaries. Supports subscriptions with automatic new episode detection, + organized history with folders, and a responsive web interface. + +assets: + license: LICENSE + icon: icon.png + instructions: instructions.md + docker-images: image.tar + +main: + type: docker + image: main + entrypoint: docker_entrypoint.sh + args: [] + mounts: + main: /data + +health-checks: + main: + name: API health + success-message: YouTube Summarizer is responding. + type: docker + image: main + entrypoint: healthcheck.sh + args: [] + inject: true + +config: + get: + type: docker + image: main + system: false + entrypoint: sh + args: + - -c + - cat /data/config/startos-config.json 2>/dev/null || echo '{}' + set: + type: docker + image: main + system: false + entrypoint: sh + args: + - -c + - cat > /data/config/startos-config.json + +dependencies: {} + +volumes: + main: + type: data + +interfaces: + main: + name: Web Interface + description: Browser UI for YouTube Summarizer. + tor-config: + port-mapping: + 80: "3001" + lan-config: + 443: + ssl: true + internal: 3001 + ui: true + protocols: [tcp, http, https] + +backup: + create: + type: docker + image: main + system: false + entrypoint: sh + args: + - -c + - | + set -eu + rm -rf /backup/* + cp -a /data/. /backup/ + mounts: + main: /data + BACKUP: /backup + restore: + type: docker + image: main + system: false + entrypoint: sh + args: + - -c + - | + set -eu + cp -a /backup/. /data/ + mounts: + main: /data + BACKUP: /backup + +actions: + update-ytdlp: + name: Update yt-dlp + description: Downloads the latest version of yt-dlp for YouTube compatibility. + warning: This may take a minute. Service will continue running. + implementation: + type: docker + image: main + system: false + entrypoint: sh + args: + - -c + - pip install --upgrade yt-dlp && yt-dlp --version + inject: true +``` + +### Draft Dockerfile + +```dockerfile +FROM node:20-alpine AS builder + +WORKDIR /app + +# Copy server package files and install deps +COPY server/package.json server/package-lock.json ./server/ +RUN cd server && npm ci --production + +# Copy application files +COPY server/index.js ./server/ +COPY public/ ./public/ +COPY assets/ ./assets/ + +FROM node:20-alpine AS runner + +WORKDIR /app + +RUN apk add --no-cache \ + dumb-init \ + curl \ + python3 \ + py3-pip \ + ffmpeg \ + && pip3 install --break-system-packages yt-dlp \ + && addgroup -S appgroup -g 1001 \ + && adduser -S appuser -u 1001 -G appgroup + +# Copy app from builder +COPY --from=builder --chown=appuser:appgroup /app ./ + +# Copy StartOS scripts +COPY start9/0.4/docker_entrypoint.sh /usr/local/bin/docker_entrypoint.sh +COPY start9/0.4/healthcheck.sh /usr/local/bin/healthcheck.sh +RUN chmod +x /usr/local/bin/docker_entrypoint.sh /usr/local/bin/healthcheck.sh + +# Create data directory +RUN mkdir -p /data && chown -R appuser:appgroup /data + +ENV NODE_ENV=production \ + PORT=3001 + +EXPOSE 3001 + +ENTRYPOINT ["dumb-init", "--", "/usr/local/bin/docker_entrypoint.sh"] +``` + +### Draft docker_entrypoint.sh + +```bash +#!/bin/sh +set -eu + +DATA_DIR="/data" +HISTORY_DIR="$DATA_DIR/history" +CONFIG_DIR="$DATA_DIR/config" +BIN_DIR="$DATA_DIR/bin" +CACHE_DIR="$DATA_DIR/ytdlp-cache" +COOKIES_PATH="$DATA_DIR/cookies.txt" + +# Create directory structure +mkdir -p "$HISTORY_DIR" "$CONFIG_DIR" "$BIN_DIR" "$CACHE_DIR" + +# Use persistent yt-dlp binary if it exists and is executable +if [ -x "$BIN_DIR/yt-dlp" ]; then + export PATH="$BIN_DIR:$PATH" +fi + +# Point yt-dlp cache to persistent storage (for OAuth tokens, etc.) +export XDG_CACHE_HOME="$CACHE_DIR" + +# Load config from StartOS config file if it exists +if [ -f "$CONFIG_DIR/startos-config.json" ]; then + # Extract Gemini API key from config + GEMINI_KEY=$(cat "$CONFIG_DIR/startos-config.json" | python3 -c "import sys,json; print(json.load(sys.stdin).get('gemini_api_key',''))" 2>/dev/null || echo "") + if [ -n "$GEMINI_KEY" ]; then + export GEMINI_API_KEY="$GEMINI_KEY" + fi +fi + +# Also check for .env in data dir +if [ -f "$DATA_DIR/.env" ]; then + export $(grep -v '^#' "$DATA_DIR/.env" | xargs) +fi + +export PORT="${PORT:-3001}" +export HOSTNAME="0.0.0.0" + +echo "Starting YouTube Summarizer..." +echo " yt-dlp version: $(yt-dlp --version 2>/dev/null || echo 'not found')" +echo " ffmpeg: $(ffmpeg -version 2>/dev/null | head -1 || echo 'not found')" +echo " Data dir: $DATA_DIR" + +exec node /app/server/index.js +``` + +--- + +## 7. Differences from v0.3.5 Packaging (Workout Log) + +The workout-log package was a relatively straightforward Next.js app with a SQLite database. YouTube Summarizer is significantly more complex: + +| Aspect | Workout Log (0.3.5) | YouTube Summarizer (0.4.0) | +|---|---|---| +| App framework | Next.js + Prisma + SQLite | Express.js + JSON files | +| External binaries | None | yt-dlp, ffmpeg | +| External APIs | None | Google Gemini API | +| Authentication | App-level (user/pass) | YouTube OAuth + cookies | +| Data storage | Single SQLite DB | Multiple JSON files + temp audio | +| Network access | Inbound only | Inbound + outbound (YouTube, Gemini, RSS) | +| Binary updates | None needed | yt-dlp must stay current | +| Temp file management | None | Large audio files downloaded and cleaned up | +| Container size | Small (~100MB) | Larger (~300-500MB with ffmpeg + yt-dlp + Python) | + +### Key Differences in Packaging Approach + +1. **Outbound network access:** The workout-log only needed to accept inbound connections. YouTube Summarizer needs outbound access to YouTube, Google Gemini API, and podcast RSS feeds. StartOS containers have outbound network access by default, so this works, but it's worth verifying in the 0.4.0 LXC environment. + +2. **Larger image size:** Adding Python, pip, yt-dlp, and ffmpeg significantly increases the Docker image. Expect 300-500MB vs. ~100MB for workout-log. This is acceptable but worth minimizing where possible. + +3. **Runtime binary management:** The entrypoint must handle a mutable binary (yt-dlp) that updates at runtime. The workout-log had no such requirement. + +4. **Temporary file cleanup:** Audio files are downloaded to /tmp during processing and should be cleaned up. Need to ensure the container's /tmp has sufficient space or use the persistent volume with cleanup logic. + +5. **Config complexity:** Workout-log had no configuration. YouTube Summarizer needs at minimum a Gemini API key, and optionally proxy settings, download rate limits, and authentication preferences. This maps to the StartOS config spec in the manifest. + +--- + +## 8. Implementation Phases + +### Phase 1: Prepare the App for Headless Operation (Estimated: 1-2 days) + +Code changes to server/index.js before any packaging work: + +1. **Remove auto-sleep logic** -- the heartbeat/sleep system is designed for a desktop app that shuts down when you close the browser. On StartOS, the service should run continuously. + +2. **Move all data paths to a configurable base directory** -- currently paths are relative to the project root. Change to use an environment variable (e.g., `DATA_DIR=/data`) so the persistent volume can be targeted. + +3. **Add OAuth2 authentication flow** -- new endpoints: + - POST /api/auth/oauth/start -- initiates OAuth device flow, returns device code + - GET /api/auth/oauth/status -- checks if OAuth token has been cached + - The web UI gets a new "Authentication" section in Settings + +4. **Enhance yt-dlp update logic for Linux/container** -- remove Homebrew strategy, add direct binary download from GitHub releases as a fallback. + +5. **Add download rate limiting** -- configurable delay between auto-queue downloads (default 30s). + +6. **Add browser impersonation flag** -- pass `--impersonate chrome` to yt-dlp by default when available. + +7. **Remove macOS-specific code** -- the .app bundle creation, osascript dialogs, LAN mode prompt, etc. are not needed. + +### Phase 2: Create the StartOS Package Scaffold (Estimated: 1 day) + +1. Create `start9/0.4/` directory with all packaging files (see Section 6) +2. Write Dockerfile with multi-stage build +3. Write docker_entrypoint.sh +4. Write healthcheck.sh +5. Write manifest.yaml with full config spec +6. Write instructions.md +7. Copy icon.png +8. Create Makefile + +### Phase 3: Build, Test, and Iterate (Estimated: 2-3 days) + +1. Build ARM64 Docker image: `make -C start9/0.4 image-arm` +2. Smoke test locally: + - `docker load -i start9/0.4/image.tar` + - Run container with a volume mount and verify /api/health responds + - Test yt-dlp download of a known video + - Test Gemini API transcription + - Test OAuth flow + - Test subscription check +3. Package with start-sdk: `make -C start9/0.4 package` +4. Sideload on StartOS and test end-to-end: + - Install service + - Set up Gemini API key via config + - Run OAuth authentication + - Process a YouTube video + - Process a podcast episode + - Test subscription auto-discovery + - Test backup/restore +5. Iterate on issues found + +### Phase 4: Documentation and Polish (Estimated: 1 day) + +1. Write comprehensive instructions.md for StartOS users +2. Update DEPLOY.md with StartOS 0.4.0 specific steps +3. Update START9_PACKAGING_LOG.md with the complete process +4. Verify backup/restore works correctly +5. Test yt-dlp auto-update from within the running service +6. Document the config spec clearly + +--- + +## 9. Persistent Data Contract + +Everything under `/data` persists across container restarts and package upgrades: + +``` +/data/ + history/ # All summary JSON files + subscriptions.json # Channel/feed subscriptions + _meta.json # Folder organization + seen-list.json # Dedup tracking + skip-list.json # Deleted item tracking + auto-queue.json # Pending queue items + *.json # Individual summary records + config/ + startos-config.json # StartOS-managed configuration + cookies.txt # YouTube cookie file (if uploaded) + .env # Environment overrides (Gemini key, etc.) + bin/ + yt-dlp # Updated yt-dlp binary (runtime-managed) + ytdlp-cache/ # yt-dlp cache (OAuth tokens, etc.) +``` + +**Migration contract:** Any future package version must preserve this layout. If the schema of JSON files changes, handle migration in the entrypoint script or a dedicated migration step. + +--- + +## 10. Ongoing Maintenance Plan + +### Regular Maintenance (Monthly) + +- **Rebuild and push package** -- even if the app code hasn't changed, rebuilding picks up the latest Alpine packages, Node.js patches, and yt-dlp version at build time +- **Check yt-dlp compatibility** -- verify that the runtime auto-update is working by checking the version via the health endpoint + +### When YouTube Breaks Things + +YouTube periodically makes changes that break yt-dlp. When this happens: + +1. Users can trigger "Update yt-dlp" from StartOS Actions menu +2. If the action doesn't fix it, rebuild and push a new package with the latest yt-dlp +3. If yt-dlp itself hasn't released a fix yet, the nightly build channel may have it -- consider switching the auto-update to use `yt-dlp --update-to nightly` temporarily + +### When StartOS Updates + +- Test the package on new StartOS versions before they're widely deployed +- The 0.4.0 beta may have breaking changes as it stabilizes; pin to specific beta versions during testing +- Keep the wrapper repo and packaging log updated + +### Gemini API Changes + +- The app already handles model fallbacks (tries multiple models) +- Google periodically deprecates Gemini model versions; update the model list in server/index.js when this happens +- API key management is handled via StartOS config, so no package rebuild needed for key rotation + +--- + +## 11. Risk Assessment + +| Risk | Likelihood | Impact | Mitigation | +|---|---|---|---| +| YouTube breaks yt-dlp | High (happens regularly) | Downloads fail until yt-dlp updates | Runtime auto-update + manual action button | +| OAuth tokens expire | Medium | Need to re-authenticate | Clear UI instructions; cookies.txt as backup | +| Gemini API changes/deprecates models | Low-Medium | Transcription fails | Model fallback chain already implemented | +| StartOS 0.4.0 beta has breaking changes | Medium | Package may need rework | Stay on documented APIs; test frequently | +| Docker image too large | Low | Slow install/update | Multi-stage build; Alpine base; minimize layers | +| Container can't reach YouTube (network) | Low (home network) | Downloads fail | StartOS allows outbound; verify in LXC | +| Temp audio files fill disk | Low | Processing fails | Cleanup in /tmp; use TMPDIR on volume if needed | +| cookies.txt expires quickly | High (3-5 days) | Auth fails | OAuth2 as primary; clear messaging about cookie limits | + +--- + +## 12. Multi-User Distribution: API Keys and Clean Installs + +### Gemini API Key Management + +The Gemini API key must never be baked into the Docker image or package. Each user provides their own key after installation. + +**How it works:** + +1. The `.env` file (which contains your personal API key) is excluded from the Docker image via `.dockerignore` +2. On fresh install, the service starts with no API key configured +3. The user enters their key via the StartOS config UI, which writes it to `/data/config/startos-config.json` on the persistent volume +4. The entrypoint script reads this file and sets `GEMINI_API_KEY` as an environment variable before starting the server +5. The web UI settings panel also lets users enter/change the key at any time (this writes to the server's in-memory state and persists to the config file) + +The app already supports this pattern: it reads `GEMINI_API_KEY` from the environment first, then falls back to the `.env` file. On StartOS the environment variable takes precedence, and the `.env` file simply doesn't exist in a fresh install. + +### Clean Installs: No Inherited Data + +The Docker image contains only application code -- no user data. Everything personal lives on the `/data` volume, which starts empty for every new install. This means: + +- No inherited history (processed videos/podcasts) +- No inherited subscriptions +- No inherited cookies or authentication tokens +- No inherited API keys +- No inherited folder organization or skip/seen lists + +**The `.dockerignore` ensures nothing personal leaks into the image:** + +``` +history/ +cookies.txt +.env +*.s9pk +image.tar +node_modules/ +.DS_Store +GET-STARTED.* +build-guide-pdf.py +create-app.sh +setup.sh +Start Summarizer.command +start9/ +``` + +**First-run flow for a new user:** +1. Install the package from StartOS +2. Open service config, enter Gemini API key +3. Open the web UI +4. Set up YouTube OAuth authentication (one-time device code flow) +5. Add subscriptions to channels/feeds they want to follow +6. Start summarizing -- their library builds from scratch + +--- + +## Appendix A: File-by-File Packaging Checklist + +When creating the StartOS package, create/modify these files: + +**New files to create (in start9/0.4/):** + +- [ ] `manifest.yaml` -- set id, title, version, interfaces, config spec, actions, backup +- [ ] `Dockerfile` -- multi-stage build, Alpine, Node 20, Python, yt-dlp, ffmpeg +- [ ] `docker_entrypoint.sh` -- data dir setup, yt-dlp path, env loading, server start +- [ ] `healthcheck.sh` -- curl to /api/health +- [ ] `Makefile` -- image-arm, package, verify, clean targets +- [ ] `instructions.md` -- setup guide, OAuth instructions, cookie upload, troubleshooting +- [ ] `DEPLOY.md` -- build + sideload steps for StartOS 0.4.0 +- [ ] `LICENSE` -- appropriate license file +- [ ] `icon.png` -- app icon (already exists in assets/) + +**App code modifications (in server/index.js):** + +- [ ] Add DATA_DIR environment variable support for all file paths +- [ ] Remove auto-sleep/heartbeat shutdown logic +- [ ] Remove macOS-specific code (osascript, LAN mode, brew update strategy) +- [ ] Add OAuth2 device flow endpoints +- [ ] Add download rate limiting for auto-queue +- [ ] Add --impersonate chrome flag to yt-dlp calls +- [ ] Move cookies.txt path to DATA_DIR +- [ ] Update yt-dlp update strategies for Linux container +- [ ] Add proxy support (optional config) +- [ ] Bind to 0.0.0.0 (currently does this via HOSTNAME env) + +**Documentation updates:** + +- [ ] START9_PACKAGING_LOG.md -- full process documentation (like workout-log) +- [ ] VERSIONING.md -- update with youtube-summarizer version policy +- [ ] 0.4/README.md -- migration notes and packaging intent + +--- + +## Appendix B: Reusable Packaging Roadmap for Future Apps + +This section generalizes the process so it can be reused for packaging any app for StartOS. + +### Step 1: Assess the App + +Before packaging, answer these questions: +1. What language/runtime does the app use? (Determines base Docker image) +2. Does it need external binaries? (yt-dlp, ffmpeg, etc. -- add to Dockerfile) +3. Does it need outbound network access? (API calls, downloads -- verify in StartOS) +4. What is the persistent data? (Database, files, config -- maps to /data volume) +5. Does it have a health endpoint? (Required for StartOS health checks) +6. Does it need configuration? (Maps to StartOS config spec) +7. Does it have any platform-specific code? (macOS, Windows -- must be removed/adapted) + +### Step 2: Create the Wrapper + +1. Copy the template from an existing wrapper (this project or workout-log) +2. Edit manifest.yaml first -- it defines everything +3. Write the Dockerfile -- multi-stage build, Alpine, minimal layers +4. Write docker_entrypoint.sh -- data init, env setup, exec app +5. Write healthcheck.sh -- simple curl to health endpoint +6. Write instructions.md -- user-facing setup guide + +### Step 3: Build and Test Locally + +```bash +# Build ARM64 image +make -C start9/0.4 image-arm + +# Load and test +docker load -i start9/0.4/image.tar +docker run -it --rm -v ./test-data:/data -p 3001:3001 + +# Verify health +curl http://localhost:3001/api/health +``` + +### Step 4: Package and Sideload + +```bash +# Must be in a git repo +git init && git add . && git commit -m "Initial packaging" + +# Build s9pk +make -C start9/0.4 package + +# Verify +make -C start9/0.4 verify + +# Sideload via StartOS web UI +``` + +### Step 5: Document Everything + +- Update START9_PACKAGING_LOG.md with the full process +- Record all issues encountered and how they were resolved +- Note any StartOS version-specific quirks +- Keep the manifest and Dockerfile well-commented + +### Template Variables for New Projects + +| Variable | Description | Example | +|---|---|---| +| `` | StartOS package identifier | `youtube-summarizer` | +| `` | Internal container port | `3001` | +| `` | Persistent volume mount | `/data` | +| `` | Health endpoint path | `/api/health` | +| `` | Absolute path to repo | `/Users/macpro/Projects/youtube-summarizer` | + +--- + +*This document should be updated as the implementation progresses. Each phase completed should be annotated with actual outcomes, issues discovered, and any deviations from the plan.* diff --git a/Start Summarizer.command b/Start Summarizer.command new file mode 100755 index 0000000..2c7208b --- /dev/null +++ b/Start Summarizer.command @@ -0,0 +1,91 @@ +#!/bin/bash +# ───────────────────────────────────────────────────────────── +# YouTube Summarizer — Double-click this file to launch! +# ───────────────────────────────────────────────────────────── + +# Move to the folder where this script lives (the project folder) +cd "$(dirname "$0")" + +clear +echo "============================================" +echo " YouTube Summarizer — Starting up..." +echo "============================================" +echo "" + +# ── Check for Node.js ──────────────────────────────────────── +if ! command -v node &> /dev/null; then + echo "ERROR: Node.js is not installed." + echo "" + echo "To install it, open Terminal and run:" + echo " brew install node" + echo "" + echo "(If you don't have Homebrew, install it first:" + echo " /bin/bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\"" + echo ")" + echo "" + echo "Press any key to close..." + read -n 1 + exit 1 +fi + +# ── Check for yt-dlp ───────────────────────────────────────── +if ! command -v yt-dlp &> /dev/null; then + echo "yt-dlp not found. Installing via Homebrew..." + if command -v brew &> /dev/null; then + brew install yt-dlp + else + echo "ERROR: yt-dlp is not installed and Homebrew is not available." + echo "Install yt-dlp manually: https://github.com/yt-dlp/yt-dlp" + echo "" + echo "Press any key to close..." + read -n 1 + exit 1 + fi +fi + +# ── Install npm dependencies if needed ─────────────────────── +if [ ! -d "server/node_modules" ]; then + echo "First run — installing dependencies..." + cd server + npm install + cd .. + echo "" +fi + +# ── Start the server ───────────────────────────────────────── +echo "Starting server..." +echo "" + +# Start server in the background +cd server +node index.js & +SERVER_PID=$! +cd .. + +# Wait for server to be ready +echo "Waiting for server to start..." +for i in {1..20}; do + if curl -s http://localhost:3001/api/health > /dev/null 2>&1; then + break + fi + sleep 0.5 +done + +# ── Open browser ───────────────────────────────────────────── +echo "" +echo "Opening browser..." +open http://localhost:3001 +echo "" +echo "============================================" +echo " App is running at http://localhost:3001" +echo "============================================" +echo "" +echo "Leave this window open while using the app." +echo "To stop the server, close this window or press Ctrl+C." +echo "" + +# Keep the script running so the server stays alive +# When user closes the terminal window or presses Ctrl+C, clean up +trap "echo ''; echo 'Shutting down server...'; kill $SERVER_PID 2>/dev/null; exit 0" INT TERM + +wait $SERVER_PID diff --git a/assets/ABOUT.md b/assets/ABOUT.md new file mode 100644 index 0000000..b45b9cb --- /dev/null +++ b/assets/ABOUT.md @@ -0,0 +1,18 @@ +# YouTube Summarizer + +Download, transcribe, and summarize YouTube videos and podcast episodes using Google Gemini AI. + +## Features + +- Paste any YouTube URL or podcast RSS feed to get a full transcript with timestamps +- AI-powered topic segmentation and summaries +- Channel and podcast subscriptions with automatic new episode detection +- Background processing queue with configurable delays +- Auto-download toggle per subscription +- Organized history with folders and search +- Multiple Gemini model support +- OAuth2 YouTube authentication for reliable downloads + +## Requirements + +- A Google Gemini API key (free tier available at [aistudio.google.com/apikey](https://aistudio.google.com/apikey)) diff --git a/assets/icon.png b/assets/icon.png new file mode 100644 index 0000000..d326778 Binary files /dev/null and b/assets/icon.png differ diff --git a/build-guide-pdf.py b/build-guide-pdf.py new file mode 100644 index 0000000..0a58426 --- /dev/null +++ b/build-guide-pdf.py @@ -0,0 +1,326 @@ +from reportlab.lib.pagesizes import letter +from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle +from reportlab.lib.colors import HexColor +from reportlab.lib.units import inch +from reportlab.lib.enums import TA_LEFT, TA_CENTER +from reportlab.platypus import ( + SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, + PageBreak, KeepTogether, HRFlowable, Preformatted +) +from reportlab.lib import colors +import os + +OUTPUT = os.path.join(os.path.dirname(__file__), "GET-STARTED.pdf") + +doc = SimpleDocTemplate( + OUTPUT, + pagesize=letter, + topMargin=0.75 * inch, + bottomMargin=0.75 * inch, + leftMargin=0.85 * inch, + rightMargin=0.85 * inch, +) + +styles = getSampleStyleSheet() + +# Custom styles +styles.add(ParagraphStyle( + "DocTitle", parent=styles["Title"], + fontSize=26, leading=32, textColor=HexColor("#0f172a"), + spaceAfter=4, fontName="Helvetica-Bold", +)) +styles.add(ParagraphStyle( + "DocSubtitle", parent=styles["Normal"], + fontSize=13, leading=18, textColor=HexColor("#64748b"), + spaceAfter=24, alignment=TA_CENTER, +)) +styles.add(ParagraphStyle( + "H1", parent=styles["Heading1"], + fontSize=20, leading=26, textColor=HexColor("#0f172a"), + spaceBefore=28, spaceAfter=10, fontName="Helvetica-Bold", +)) +styles.add(ParagraphStyle( + "H2", parent=styles["Heading2"], + fontSize=15, leading=20, textColor=HexColor("#1e293b"), + spaceBefore=20, spaceAfter=8, fontName="Helvetica-Bold", +)) +styles.add(ParagraphStyle( + "Body", parent=styles["Normal"], + fontSize=11, leading=17, textColor=HexColor("#334155"), + spaceAfter=8, fontName="Helvetica", +)) +styles.add(ParagraphStyle( + "BodyBold", parent=styles["Normal"], + fontSize=11, leading=17, textColor=HexColor("#1e293b"), + spaceAfter=8, fontName="Helvetica-Bold", +)) +styles.add(ParagraphStyle( + "CodeBlock", parent=styles["Code"], + fontSize=10, leading=14, textColor=HexColor("#1e293b"), + backColor=HexColor("#f1f5f9"), + fontName="Courier", leftIndent=16, rightIndent=16, + spaceBefore=4, spaceAfter=8, + borderPadding=(8, 8, 8, 8), +)) +styles.add(ParagraphStyle( + "BulletItem", parent=styles["Normal"], + fontSize=11, leading=17, textColor=HexColor("#334155"), + leftIndent=24, bulletIndent=10, spaceAfter=4, + fontName="Helvetica", +)) +styles.add(ParagraphStyle( + "StepNum", parent=styles["Normal"], + fontSize=11, leading=17, textColor=HexColor("#334155"), + leftIndent=24, bulletIndent=4, spaceAfter=4, + fontName="Helvetica", +)) +styles.add(ParagraphStyle( + "Note", parent=styles["Normal"], + fontSize=10, leading=15, textColor=HexColor("#92400e"), + backColor=HexColor("#fffbeb"), + leftIndent=12, rightIndent=12, + spaceBefore=8, spaceAfter=8, + borderPadding=(8, 8, 8, 8), + fontName="Helvetica", +)) +styles.add(ParagraphStyle( + "Link", parent=styles["Normal"], + fontSize=11, leading=17, textColor=HexColor("#2563eb"), + spaceAfter=4, fontName="Helvetica", +)) + +def code_block(text): + """Create a code block with background using Preformatted to preserve newlines.""" + return Preformatted(text, styles["CodeBlock"]) + +def hr(): + return HRFlowable(width="100%", thickness=1, color=HexColor("#e2e8f0"), spaceBefore=12, spaceAfter=12) + +story = [] + +# -- Title -- +story.append(Spacer(1, 40)) +story.append(Paragraph("YouTube Transcript Summarizer", styles["DocTitle"])) +story.append(Paragraph("Mac Setup Guide", styles["DocSubtitle"])) +story.append(hr()) + +# -- What you're setting up -- +story.append(Paragraph("What You're Setting Up", styles["H1"])) +story.append(Paragraph( + "This app has two parts that work together:", + styles["Body"] +)) +story.append(Paragraph( + "1. A small server that runs locally on your Mac (not on the internet -- only you can access it). " + "It downloads YouTube audio and talks to Google's Gemini AI.", + styles["BulletItem"] +)) +story.append(Paragraph( + "2. A webpage that the server hosts in your browser at http://localhost:3001.", + styles["BulletItem"] +)) +story.append(Spacer(1, 4)) +story.append(Paragraph( + "Nothing is uploaded anywhere. Everything runs on your machine.", + styles["BodyBold"] +)) + +# -- Where to save -- +story.append(Paragraph("Where to Save the Project", styles["H1"])) +story.append(Paragraph( + "The youtube-summarizer folder you downloaded can live anywhere, " + "but the standard Mac convention for projects like this is:", + styles["Body"] +)) +story.append(code_block("~/Projects/youtube-summarizer")) +story.append(Paragraph( + "The ~ means your home folder (e.g., /Users/grant). " + "If you don't have a Projects folder yet, you'll create one below.", + styles["Body"] +)) + +story.append(Paragraph("To move the files there:", styles["BodyBold"])) +story.append(Paragraph("1. Open Finder", styles["StepNum"])) +story.append(Paragraph("2. Go to your home folder (press Cmd + Shift + H)", styles["StepNum"])) +story.append(Paragraph("3. Create a new folder called Projects if you don't have one", styles["StepNum"])) +story.append(Paragraph("4. Drag the youtube-summarizer folder from your Cowork downloads into Projects", styles["StepNum"])) + +story.append(Spacer(1, 8)) +story.append(Paragraph("You should end up with this structure:", styles["Body"])) +story.append(code_block( + "~/Projects/youtube-summarizer/\n" + "|-- public/\n" + "| +-- index.html\n" + "|-- server/\n" + "| |-- index.js\n" + "| +-- package.json\n" + "|-- setup.sh\n" + "|-- Start Summarizer.command <-- double-click to launch!\n" + "+-- GET-STARTED.pdf <-- this file" +)) + +# -- Step 1 -- +story.append(PageBreak()) +story.append(Paragraph("Step 1: Install Node.js and yt-dlp", styles["H1"])) +story.append(Paragraph( + "You need two things installed: Node.js (runs the server) and yt-dlp (downloads YouTube audio). " + "The easiest way to install both is with Homebrew.", + styles["Body"] +)) + +story.append(Paragraph("If you don't have Homebrew yet:", styles["BodyBold"])) +story.append(Paragraph("1. Open Terminal (press Cmd + Space, type \"Terminal\", hit Enter)", styles["StepNum"])) +story.append(Paragraph("2. Paste this and press Enter:", styles["StepNum"])) +story.append(code_block('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"')) +story.append(Paragraph("3. Follow the prompts (it may ask for your Mac password)", styles["StepNum"])) + +story.append(Spacer(1, 8)) +story.append(Paragraph("Then install Node.js and yt-dlp:", styles["BodyBold"])) +story.append(code_block("brew install node yt-dlp")) + +story.append(Spacer(1, 4)) +story.append(Paragraph("Verify they're installed:", styles["Body"])) +story.append(code_block("node --version\nyt-dlp --version")) +story.append(Paragraph( + "You should see version numbers for both. If so, you're ready for the next step.", + styles["Body"] +)) + +# -- Step 2 -- +story.append(Paragraph("Step 2: Install Server Dependencies", styles["H1"])) +story.append(Paragraph( + "This is a one-time step. In Terminal, run:", + styles["Body"] +)) +story.append(code_block("cd ~/Projects/youtube-summarizer/server\nnpm install")) +story.append(Paragraph( + "This downloads the JavaScript libraries the server needs. You'll see some output scroll by -- " + "when it finishes and shows you a new prompt, you're done.", + styles["Body"] +)) + +# -- Step 3 -- +story.append(Paragraph("Step 3: Add Your Gemini API Key", styles["H1"])) +story.append(Paragraph("The app needs a Google Gemini API key to transcribe and analyze videos.", styles["Body"])) + +story.append(Spacer(1, 4)) +story.append(Paragraph("Get a free key:", styles["BodyBold"])) +story.append(Paragraph("1. Go to https://aistudio.google.com/apikey", styles["StepNum"])) +story.append(Paragraph("2. Sign in with your Google account", styles["StepNum"])) +story.append(Paragraph("3. Click \"Create API Key\"", styles["StepNum"])) +story.append(Paragraph("4. Copy the key -- you'll paste it in the app after launching", styles["StepNum"])) + +# -- Step 4 -- +story.append(PageBreak()) +story.append(Paragraph("Step 4: Launch the App", styles["H1"])) +story.append(Paragraph( + "This is the fun part. You have two ways to launch:", + styles["Body"] +)) + +story.append(Spacer(1, 4)) +story.append(Paragraph("Option A: Double-click (recommended)", styles["H2"])) +story.append(Paragraph( + "Find Start Summarizer.command in your project folder and double-click it.", + styles["Body"] +)) +story.append(Paragraph( + "The first time, macOS may say the file can't be opened because it's from an unidentified developer. " + "If this happens: right-click the file, choose Open, then click Open in the dialog. " + "You only need to do this once.", + styles["Note"] +)) +story.append(Paragraph( + "A Terminal window will open, the server will start, and your browser will automatically open to the app. " + "That's it!", + styles["Body"] +)) + +story.append(Spacer(1, 8)) +story.append(Paragraph("Option B: Terminal", styles["H2"])) +story.append(Paragraph("If you prefer the command line:", styles["Body"])) +story.append(code_block("cd ~/Projects/youtube-summarizer/server\nnpm start")) +story.append(Paragraph( + "Then open http://localhost:3001 in your browser.", + styles["Body"] +)) + +# -- Step 5 -- +story.append(Spacer(1, 8)) +story.append(Paragraph("Step 5: Summarize a Video", styles["H1"])) +story.append(Paragraph("1. In the app, click \"Gemini API Settings\" and paste your API key", styles["StepNum"])) +story.append(Paragraph("2. Paste a YouTube URL into the main input", styles["StepNum"])) +story.append(Paragraph("3. Click Summarize", styles["StepNum"])) +story.append(Paragraph("4. Watch the 3-step pipeline: Download audio -> Transcribe -> Analyze topics", styles["StepNum"])) +story.append(Paragraph("5. Click any topic section to expand the full transcript with clickable timestamps", styles["StepNum"])) +story.append(Spacer(1, 4)) +story.append(Paragraph( + "Your API key is saved in your browser so you don't have to re-enter it each time.", + styles["Body"] +)) + +# -- Day-to-day -- +story.append(hr()) +story.append(Paragraph("Day-to-Day Usage", styles["H1"])) +story.append(Paragraph( + "After the one-time setup above, here's all you need to do each time:", + styles["Body"] +)) +story.append(Paragraph( + "1. Double-click Start Summarizer.command", + styles["StepNum"] +)) +story.append(Paragraph( + "2. Your browser opens automatically -- paste a YouTube link and go", + styles["StepNum"] +)) +story.append(Paragraph( + "3. When done, close the Terminal window that opened (this stops the server)", + styles["StepNum"] +)) +story.append(Spacer(1, 4)) +story.append(Paragraph("That's it. One double-click.", styles["BodyBold"])) + +# -- Troubleshooting -- +story.append(PageBreak()) +story.append(Paragraph("Troubleshooting", styles["H1"])) + +troubles = [ + ( + "macOS won't open Start Summarizer.command", + "Right-click the file, choose Open, then click Open in the security dialog. " + "This only happens the first time." + ), + ( + "\"Cannot connect to backend at localhost:3001\"", + "The server isn't running. Double-click Start Summarizer.command again." + ), + ( + "\"yt-dlp not installed\"", + "Run brew install yt-dlp in Terminal, then relaunch the app." + ), + ( + "Download fails or hangs", + "yt-dlp might be outdated. Click the \"Update now\" button in the app, or run " + "brew upgrade yt-dlp in Terminal." + ), + ( + "\"Gemini API error: 403\" or \"401\"", + "Your API key is invalid or expired. Get a new one from " + "https://aistudio.google.com/apikey" + ), + ( + "Long videos take a while", + "Normal. A 1-hour video takes ~30 seconds to download, 30-60 seconds for Gemini " + "to transcribe, then 10-20 seconds for topic analysis. The app shows live progress." + ), +] + +for problem, solution in troubles: + story.append(Paragraph(f"{problem}", styles["BodyBold"])) + story.append(Paragraph(solution, styles["BulletItem"])) + story.append(Spacer(1, 6)) + +# Build +doc.build(story) +print(f"PDF created: {OUTPUT}") diff --git a/cookies.txt b/cookies.txt new file mode 100644 index 0000000..4db9178 --- /dev/null +++ b/cookies.txt @@ -0,0 +1,838 @@ +# Netscape HTTP Cookie File +# This file is generated by yt-dlp. Do not edit. + +www.recaptcha.net FALSE /recaptcha TRUE 1780180930 _GRECAPTCHA 09ADiQh0dtDEiRMi5WBdQDNRHouJD94ppMc5_pTy3zyVunQwBbEcKtw1XqCAXn_gkExDi4ugUhCOoddAB10vH5POM +www.google.com FALSE /recaptcha TRUE 1781725220 _GRECAPTCHA 09ABCLyOG6cxagI3Cieygmf8CmIePx8g730YQnA8OgOrFiMW6on8sgc4c6cl3ZekVdq6dZNEKV3slW9ta33n5Z9iM +secure.insightexpressai.com FALSE /adserver TRUE 1786504594 IgniteCookieSync true +.google.com TRUE /verify TRUE 1789498633 SNID ALbZf37S4_CrH7J5UP4bphJFKXefW7V_AFkhVBncLQOAFISyal6NWxMB4che_ZQac_ZeJDJHUECJdI-UcqzC0PO5rYfTy9oILug +.google.com TRUE / TRUE 1789570228 __Secure-ENID 28.SE=R2eukpRLgAoi_g94FwISFIyz_hrGkQy70QU-Qlld5sS9lrIQtgunjeL-JNU-z7HQl2yQJ0F6yqKfFzXlMoBWJicTsjN8GFNiyELINOi5vU9jtD7EwlOIxOxv71AkEzMFVbBaNq1zhDy7rfIDW9BtANnRn-pXkGN9CfeRQn4gdq1xBRNvuBWYoNqcnTYp5LhJwRdP65bdRw +.google.com TRUE / TRUE 1786833884 __Secure-BUCKET COID +.google.com TRUE / TRUE 1786833884 AEC AaJma5vPc7N0Rl8mb8fOV-a7JjrmXzK3VfwniJq_dBv23b_DaBVcU7x8zA +.google.com TRUE / FALSE 1808253661 SID g.a0007whSQ2FTtN3oaH2z5zAUg7rUNnJXuBC-FtNcmf_q4VZxCH6I5yCVYxA-LmPOHRXLgQktwAACgYKASYSARMSFQHGX2MitoydJ2nBzhSIkt8ceGNDPRoVAUF8yKpvGQGXHR2ixssAhIZ7Tlhg0076 +.google.com TRUE / TRUE 1808253661 __Secure-1PSID g.a0007whSQ2FTtN3oaH2z5zAUg7rUNnJXuBC-FtNcmf_q4VZxCH6IIWYz6SgNFiNwCFav4fBlxgACgYKAZgSARMSFQHGX2MiUhFl0FoKqeIalNYwK9r2kRoVAUF8yKquv1J4_ggvLRhNHGom3rco0076 +.google.com TRUE / TRUE 1808253661 __Secure-3PSID g.a0007whSQ2FTtN3oaH2z5zAUg7rUNnJXuBC-FtNcmf_q4VZxCH6Ip1KVQpXe0-3wXj_r0kABhgACgYKAVESARMSFQHGX2MiaYklqIL3lhBMrkEcEBXS5RoVAUF8yKpcc98ulcMv04cCcRloUdNL0076 +.google.com TRUE / FALSE 1808253661 HSID AKxOhbOXvqjOJatr5 +.google.com TRUE / TRUE 1808253661 SSID A4lGYkDwWuxlWMvHl +.google.com TRUE / FALSE 1808253661 APISID MdMQfFFo_4b0Cw2d/Au_xxzGsUXCUZnFia +.google.com TRUE / TRUE 1808253661 SAPISID gAA5ERfoktTnNYkF/A7x17szT_7WqXM9A1 +.google.com TRUE / TRUE 1808253661 __Secure-1PAPISID gAA5ERfoktTnNYkF/A7x17szT_7WqXM9A1 +.google.com TRUE / TRUE 1808253661 __Secure-3PAPISID gAA5ERfoktTnNYkF/A7x17szT_7WqXM9A1 +.google.com TRUE / TRUE 1790880901 NID 530=VZck2xuPHmmWPJE5RehuzIMISpa_iDox0Zh3zpvPk65oDM9Ux4odkGSz1xvlgMD-hc02ehFEliXyGMl1od4-zm3pIl29SHANM8ScGoGvuhUIlkqdgXi2cjC7lpiFf0oMdulG9947fGvqPBUG4WvTqVhqvww7AZ2DGFlK77FUt6AOkfj2l6CtJowDJGcafmu6jE7pw6VACKnOg-X_W2WhjIcSh30wN6HtZCeF_pnwDrtuRjWkDjuhZU9sYSZeXDyPPa6lekXjzwgBegdVTb7aznOCXViTxJdWG8TOwfDhGAcB_RXi0fGeVzRfqQkS-o2UjLkZtWhy1ZPDb699vhn8rGEtYcO-5OhQaf9g8qUnRkJQrtSDZMMtGSdCLey4SQxe1q4uF5Sl9hdMWCk3cAk1pKtm3zjql140Jzb7MOQpgCvgz392qwqwZp05Zi2ZyrdDDol7UIppKQQgEGeT2Gh2d7XJlzU_zS21W1YWF8GvEc801uU_QJ_MGORyghk__TwLfpRsiMRzOCGmxULHQMZqKZum0CrIaW_JOJbBcLeXG3xvb-Sma8Ja7l20dQZN_Sq2J0wx-aZxdNr4mAsYV_a5FnvoosEL3XIGbFRk_eEskDKUDQTnX86ZWpTBpW2wMPQ2mcmRZtRQkeHNyLpM71g-62pB3TBR_XqYuDABI3_xdkJbWgu1TVk9t1-CRpUbxETp2UIes7xTJ7oiusmMOoxX1igZvRnmbQCwhnvOGUZBZ1Ha8c9Uo9orPmMV6N3TFodn9EZu9sqr2yN-2BYUeC3wIOcLNpkygQ +.google.com TRUE / FALSE 1806605701 SIDCC AKEyXzXC7yJXWDKmUNJMRQiH3LhIdsJivlmcAdK81cOTLXy5Z8Pd_WSnHvMeeSK6a0o8yzop +.google.com TRUE / TRUE 1806605701 __Secure-1PSIDCC AKEyXzVfeKdFV0eLw1OkaCBWbw09BtzNgRtQSbrpcfN41eZEdt5ELWZRWXhaFdXl3U9Jxlgl +.google.com TRUE / TRUE 1806605701 __Secure-3PSIDCC AKEyXzXdf2ecDiT04OPnOxH3dHiwXB2bfOSCeHXlFcqz5hKZFHwPGkaeie0FfwqxzqwvwlaG +.docsend.com TRUE /view TRUE 1787106781 dbx_js_analytics_id AABO4ekPMjJgWc5twV879ddvZiBCkhtzHwGoowWv5363VQ +.docsend.com TRUE / TRUE 1787106780 _us_ eyJfcmFpbHMiOnsibWVzc2FnZSI6IkluWnBaWGRsWkNCa2IyTWkiLCJleHAiOm51bGwsInB1ciI6ImNvb2tpZS5fdXNfIn19--d99e89135b29409ec95f7b01021ec543a463b2ba +.docsend.com TRUE / FALSE 1787106781 _ga GA1.2.1299589222.1752546781 +.docsend.com TRUE / FALSE 1787106782 _ga_JPP8SP2PRX GS2.2.s1752546781$o1$g0$t1752546781$j60$l0$h0 +.docsend.com TRUE / FALSE 1775876784 intercom-id-lv6lji7h e901f578-bb42-4566-8776-a2dcc3939b1b +.docsend.com TRUE / FALSE 1775876784 intercom-device-id-lv6lji7h 87e6f252-90d0-47b2-ab31-55527932921e +.docsend.com TRUE / TRUE 1784082794 _v_ k%2BzmVODjr1ktn34Oy5Rj6FwijPhjhBGpWkI33sJ7Bj%2FtpHLVf6p0Taeaxid5jg2zt2mSMii9qw3DrLaqZsBZh1%2Bp8yO%2Fr4j%2Bjm5MHWpwCTM2RlbJ6aj8Sac%3D--l%2FPezHhegs%2Fdy9SM--lGHFKSAFr8z2NZdmHX6FoQ%3D%3D +.liadm.com TRUE /j TRUE 1786540591 lidid b18b6947-1c7c-4b46-a344-36c6d4477e91 +.liadm.com TRUE / TRUE 1802646478 lidid b18b6947-1c7c-4b46-a344-36c6d4477e91 +.linkedin.com TRUE / TRUE 1799622470 bcookie "v=2&78faccf5-3ecd-4d84-8ab6-ef64a3bf747f" +.linkedin.com TRUE / TRUE 1781649297 dfpfpt c83f1ecbd1d74f289955365b5826d8af +.linkedin.com TRUE / FALSE 1783050085 sdui_ver sdui-flagship:0.1.7528+sdui-flagship.production +.linkedin.com TRUE / TRUE 1790346598 liap true +.linkedin.com TRUE / TRUE 1775862470 li_sugr 862c6d25-b5fa-45b5-91de-e013e23d12d0 +m.stripe.com FALSE / TRUE 1808408907 m 0d856586-3227-461d-a492-2fcbb6769537f33d44 +.bing.com TRUE / TRUE 1799780686 MUID 10188FE1CFA1634236249C51CE0F62C0 +.bing.com TRUE / TRUE 1785793502 MSPTC fytp5YpA8Dgp5mtmxchMYfBi46F4ajq3Odc1dbWzvvo +.amazon-adsystem.com TRUE / TRUE 1802646478 ad-privacy 0 +.amazon-adsystem.com TRUE / TRUE 1790896078 ad-id A-mXDgT1iEQ0urAU5Uzkr5k +.adsrvr.org TRUE / TRUE 1799622478 TDID 248c815d-b156-4db9-8a92-46c25764dd54 +.adsrvr.org TRUE / TRUE 1799622478 TDCPM CAESFwoIYXBwbmV4dXMSCwi0sdS11svYPhAFEhkKCnJpZ2h0bWVkaWESCwj6qYye-4rOPBAFEhUKBmdvb2dsZRILCKCmnrXWy9g-EAUSFgoHcnViaWNvbhILCNqij57jqeg-EAUSFQoGY2FzYWxlEgsIoIP2xoaAuz4QBRIXCghwdWJtYXRpYxILCIrZ9saGgLs-EAUSGAoJYmlkc3dpdGNoEgsIlvvKhOSp6D4QBRIUCgV0YXBhZBILCMrOs6Djqeg-EAUSGAoJbW9va2llLXBzEgsI1PONyPeu3j0QBRIbCgxzaGFyZXRocm91Z2gSCwiKgMj2hcDePRAFEhYKB3N2eDl0NTASCwjq7-aI5KnoPhAFEhcKCGxpdmVyYW1wEgsIkoa1_eOp6D4QBRIWCgdibHVla2FpEgsI-Ja-hefv7DwQBRIYCglhZGFkdmlzb3ISCwj2r_mG-a7ePRAFEhkKCmxpdmVpbnRlbnQSCwiamKPt0JzfPhAFEhYKB3lqbjBndXASCwjykoq_1svYPhAFEhYKB3NlbWFzaW8SCwjc-Lq-46noPhAFEhYKB2QwdHJvMWoSCwj6htye35HmPRAFEhIKA2FhbRILCNbqvIfAw5M-EAUSFgoHbGh3Yms1ORILCMqbh8f89Z4-EAUSFgoHYWRkdGhpcxILCKzKgoqB9p4-EAUYASABKAIyCwjA5um1-qnoPhAFOAFaB3N2eDl0NTBgAg.. +.tiktok.com TRUE / TRUE 1799780762 _ttp 2X2TZqZx4A6Bvfb8BIaqfx9Z0a3 +.everesttech.net TRUE / TRUE 1799622471 everest_g_v2 g_surferid~ZTLFuQAAMEMNAAAm +.casalemedia.com TRUE / TRUE 1799622478 CMID ZTLFuNNR.cMSZsiLqmTKvgAA +.casalemedia.com TRUE / TRUE 1775862478 CMPRO 1585 +.casalemedia.com TRUE / TRUE 1799622514 receive-cookie-deprecation 1 +.bidswitch.net TRUE / TRUE 1797620686 tuuid 7b3a0d56-9687-4b59-b959-b7bc82b68d2a +.bidswitch.net TRUE / TRUE 1797620686 tuuid_lu 1766084685 +.mookie1.com TRUE / TRUE 1802214470 id 10595069975717265745 +.mookie1.com TRUE / TRUE 1802214470 mdata 1|10595069975717265745|1697826233608 +.mookie1.com TRUE / TRUE 1802214470 ov e128077993a710de39333b74744f58cb +.scorecardresearch.com TRUE / TRUE 1801782478 UID 10E8f6bc100d2f5646935961697826233 +.scorecardresearch.com TRUE / TRUE 1801782478 XID 10E8f6bc100d2f5646935961697826233 +.openx.net TRUE / TRUE 1799622478 i 3ceaaa71-5ebd-457b-b49c-3cae42bce526|1697826233 +.openx.net TRUE / TRUE 1783481370 receive-cookie-deprecation 1 +.kargo.com TRUE / TRUE 1799622478 ktcid 6e219f4f-0df5-0bff-52c2-a571328f2277 +.pinterest.com TRUE / TRUE 1797620838 ar_debug 1 +.semasio.net TRUE / TRUE 1799622471 SEUNCY CAFD648EEF8CF9CB +.taboola.com TRUE / TRUE 1799622477 t_gid f2df2eab-3a6c-44ab-a01a-6a5636142726-tuctc2c4b3a +.taboola.com TRUE / TRUE 1799622477 t_pt_gid f2df2eab-3a6c-44ab-a01a-6a5636142726-tuctc2c4b3a +.pubmatic.com TRUE / TRUE 1799622478 KADUSERCOOKIE 7EA55DAD-5ED1-42DD-AFF7-96B0187E2FE8 +.pubmatic.com TRUE / TRUE 1775862467 KRTBCOOKIE_153 19420-e4Ku6SuEpe9gja67eIW67HrTpLtgja64eNO-SLLc&KRTB&22979-e4Ku6SuEpe9gja67eIW67HrTpLtgja64eNO-SLLc&KRTB&23462-e4Ku6SuEpe9gja67eIW67HrTpLtgja64eNO-SLLc&KRTB&23661-e4Ku6SuEpe9gja67eIW67HrTpLtgja64eNO-SLLc +.pubmatic.com TRUE / TRUE 1775862467 KRTBCOOKIE_80 16514-CAESEIBxL5SQt0wXrkALugcFNF8&KRTB&22987-CAESEIBxL5SQt0wXrkALugcFNF8&KRTB&23025-CAESEIBxL5SQt0wXrkALugcFNF8&KRTB&23386-CAESEIBxL5SQt0wXrkALugcFNF8 +.pubmatic.com TRUE / TRUE 1775862467 KRTBCOOKIE_740 23053-654168E218FD9BEFFD4A78C3BLIS&KRTB&23460-654168E218FD9BEFFD4A78C3BLIS&KRTB&23518-654168E218FD9BEFFD4A78C3BLIS&KRTB&23654-654168E218FD9BEFFD4A78C3BLIS +.pubmatic.com TRUE / TRUE 1775862467 KRTBCOOKIE_188 3189-bad985e7-8794-4157-b22d-37333612913c-654168d8-5553&KRTB&23418-bad985e7-8794-4157-b22d-37333612913c-654168d8-5553&KRTB&23634-bad985e7-8794-4157-b22d-37333612913c-654168d8-5553 +.pubmatic.com TRUE / TRUE 1775862468 KRTBCOOKIE_57 22776-1446664633062455738&KRTB&23339-1446664633062455738 +.pubmatic.com TRUE / TRUE 1775862468 KRTBCOOKIE_466 16530-7b3a0d56-9687-4b59-b959-b7bc82b68d2a&KRTB&23280-7b3a0d56-9687-4b59-b959-b7bc82b68d2a +.pubmatic.com TRUE / TRUE 1775862468 KRTBCOOKIE_32 11175-AQALN3bf5gd9IQFydVqNAQEBAQEBAQEBAQEBAQEBAJqrK3NY&KRTB&22715-AQALN3bf5gd9IQFydVqNAQEBAQEBAQEBAQEBAQEBAJqrK3NY&KRTB&23519-AQALN3bf5gd9IQFydVqNAQEBAQEBAQEBAQEBAQEBAJqrK3NY&KRTB&23632-AQALN3bf5gd9IQFydVqNAQEBAQEBAQEBAQEBAQEBAJqrK3NY +.pubmatic.com TRUE / TRUE 1775862468 KRTBCOOKIE_377 6810-248c815d-b156-4db9-8a92-46c25764dd54&KRTB&22918-248c815d-b156-4db9-8a92-46c25764dd54&KRTB&22926-248c815d-b156-4db9-8a92-46c25764dd54&KRTB&23031-248c815d-b156-4db9-8a92-46c25764dd54 +.pubmatic.com TRUE / TRUE 1775862468 KRTBCOOKIE_860 16335-Rinil22qUYFi4TknhSNdb2vCVQw&KRTB&23334-Rinil22qUYFi4TknhSNdb2vCVQw&KRTB&23417-Rinil22qUYFi4TknhSNdb2vCVQw&KRTB&23426-Rinil22qUYFi4TknhSNdb2vCVQw +.pubmatic.com TRUE / TRUE 1775862468 KRTBCOOKIE_1278 23329-0925f90d-eabf-4ced-b2b9-cadb9694d5e0&KRTB&23498-0925f90d-eabf-4ced-b2b9-cadb9694d5e0 +.pubmatic.com TRUE / TRUE 1775862468 KRTBCOOKIE_1251 23269-di_deeb83f6ca8243feb00ca&KRTB&23571-di_deeb83f6ca8243feb00ca&KRTB&23677-di_deeb83f6ca8243feb00ca +.pubmatic.com TRUE / TRUE 1775862468 KRTBCOOKIE_1003 22761-4e497f88-782f-11ee-81f8-32482e403c1e&KRTB&23275-4e497f88-782f-11ee-81f8-32482e403c1e +.pubmatic.com TRUE / TRUE 1775862468 KRTBCOOKIE_964 20918-cuid_bb00f223-da8d-11ef-a301-12328e819285&KRTB&23354-cuid_bb00f223-da8d-11ef-a301-12328e819285&KRTB&23415-cuid_bb00f223-da8d-11ef-a301-12328e819285&KRTB&23422-cuid_bb00f223-da8d-11ef-a301-12328e819285 +.pubmatic.com TRUE / TRUE 1775862468 KRTBCOOKIE_18 22947-970314644980085599&KRTB&23796-970314644980085599 +.pubmatic.com TRUE / TRUE 1775862468 KRTBCOOKIE_218 22978-ZTLFuQAAMEMNAAAm&KRTB&23194-ZTLFuQAAMEMNAAAm&KRTB&23209-ZTLFuQAAMEMNAAAm&KRTB&23244-ZTLFuQAAMEMNAAAm +.pubmatic.com TRUE / TRUE 1775862469 SyncRTB4 1769212800%3A81_201_46_234_283_176_238_48_266_7_13_278_166_220_165_231_71_8_196_286_203_56_275_178_240_272_279_22_233_281_250_96_249_214_99_161_282_3_104_55_271_285_21_267_264_54%7C1768608000%3A2_15_223%7C1769299200%3A268%7C1770595200%3A224_273%7C1768435200%3A216%7C1768867200%3A63%7C1773187200%3A69 +.pubmatic.com TRUE / TRUE 1775862469 KRTBCOOKIE_1469 23583-7fafe40b-12f1-414e-b944-2666315f73d5 +.pubmatic.com TRUE / TRUE 1775862469 KRTBCOOKIE_945 19558-83bc6354-0805-4310-befc-80a97066c1a2 +.pubmatic.com TRUE / TRUE 1775862469 KRTBCOOKIE_1513 23789-o08rOa33HNvb&KRTB&23793-o08rOa33HNvb +.pubmatic.com TRUE / TRUE 1775862469 KRTBCOOKIE_469 8273-847260793351&KRTB&23428-847260793351 +.pubmatic.com TRUE / TRUE 1775862469 KRTBCOOKIE_1199 23168-000011CF9CE959F2&KRTB&23175-000011CF9CE959F2 +.pubmatic.com TRUE / TRUE 1775862469 KRTBCOOKIE_1465 23572-A6781448135364746810 +.pubmatic.com TRUE / TRUE 1775862469 KRTBCOOKIE_27 16735-uid:66516793-f126-4800-87d3-3aaaac9ea049 +.pubmatic.com TRUE / TRUE 1775862470 KRTBCOOKIE_1515 23794-6962dbc575e323aa0d79326e&KRTB&23804-6962dbc575e323aa0d79326e +.pubmatic.com TRUE / TRUE 1775862470 KRTBCOOKIE_594 17105-RX-f60793b1-0eef-4ca4-82c5-ee8a3b5cdab9-005&KRTB&17107-RX-f60793b1-0eef-4ca4-82c5-ee8a3b5cdab9-005 +.pubmatic.com TRUE / TRUE 1775862470 DPSync4 1769212800%3A228_245_197_219_226%7C1768089600%3A248%7C1770595200%3A102%7C1768608000%3A164_252 +.pubmatic.com TRUE / TRUE 1775862470 KRTBCOOKIE_699 22727-AADBck7KgtEAABjN509uAw&KRTB&22744-AADBck7KgtEAABjN509uAw&KRTB&23649-AADBck7KgtEAABjN509uAw +.pubmatic.com TRUE / TRUE 1775862478 chkChromeAb67Sec 23 +.intentiq.com TRUE / TRUE 1802646477 IQver 1.9 +.intentiq.com TRUE / TRUE 1802646477 intentIQ 8YNjKdno5A +.intentiq.com TRUE / TRUE 1802646477 IQadv 1704742284384 +.intentiq.com TRUE / TRUE 1802646477 IQPData 1807897868#1768086477519#0#1698785399818 +.zemanta.com TRUE / TRUE 1775862477 zuid B_w-bBKJ2SQ1pcXG69r3 +.bidr.io TRUE / TRUE 1802196478 bito AADBck7KgtEAABjN509uAw +.targeting.unrulymedia.com TRUE / TRUE 1799622478 _rxuuid %7B%22rx_uuid%22%3A%22RX-f60793b1-0eef-4ca4-82c5-ee8a3b5cdab9-005%22%7D +.lijit.com TRUE / TRUE 1799622493 ljt_reader HlHCURZHmnGY_htwRy2qdS7X +.lijit.com TRUE / TRUE 1783480663 _ljtrtb_80 M6CF4TG8-W-J70S +.lijit.com TRUE / TRUE 1783480566 _ljtrtb_58 7EA55DAD-5ED1-42DD-AFF7-96B0187E2FE8 +.lijit.com TRUE / TRUE 1783480583 _ljtrtb_5039 2YGMLNgKe4pU8mA41f8wMksvXS_5pk97WTqA5qysrKa8 +.lijit.com TRUE / TRUE 1783480589 _ljtrtb_27 248c815d-b156-4db9-8a92-46c25764dd54 +.lijit.com TRUE / TRUE 1783480589 _ljtrtb_85 AADBck7KgtEAABjN509uAw +.lijit.com TRUE / TRUE 1783480606 _ljtrtb_1 7289271102826593249 +.lijit.com TRUE / TRUE 1796162270 ljtrtb eJyNVFtTGzsM%2Fi95rmYsW7LlM9OHzYXQBtIzhRLgpWN7vdxDSqAUzpz%2FfuTt%2BQHdh2TXkqzvIvufifeTvyZCwXoTonOMkw8TQbS6ymy8N9ETYrToMZLG2BjUmCtDrBoQiSI5RptqRUbjkHS14pjpg2ZqpQ1IwRkbnTGRnMZs6xqyS6ZnD9FLAMocIcf2E3IRm730NrXccReSIsg9ZNQC6nMESdEC%2BWI5eOp7bugoau7mltNhmbndLxcbG8NGVy%2BX1M02m%2FI8XXT6fJqevG27148fR6TY8Ix%2FHyaxcQ%2FE1vtoHGEQZ4P%2Fn7xrDezF8vhofbWqtPsmDx3hIK%2FHd%2Fuf5yffeXcXw%2Bb0R8c%2F3vZPqyRaFZpgYdExz7s58GKOQHY%2Bh%2B7gICj3qUEJC3uwaLmxkf16DsNoR0YwtQ5AJRGILQy1SnKZS59UAWO4bT866JJQrgLYSwUygpDioErZariqO1FGLXB0Ty7Wt6t%2B%2B8jdb%2FY4%2BkRRLTPkg3ocxQYjzSpGbPJRdOquc955MjEGltFj%2BXNqo8Y59VG4BpAQCQg5QLa2Bxfa3mgjugKeCdV9AWZuEEb9rESdIzRWrOfoLDU%2BzSpjvevMYopmbohNEKSDmXGexbGfhSaRVjXWo6iMMNjsgCUx5BQiBBfLEEqp3Jcx2Wnyl7%2B%2F6UBKJQrDQJn0EUquclZfSuirDpXy10yUvL9%2BogcfZP80zmtkRxp4SeD70LRM2tJYcM4OkFK1kLLPeSi2IOax5Th%2FFENg36qtGPF%2BPCrS1D%2F2swM6XQps4HMwJ2NJk55yYe6HjEPLbLiP1hfnm0%2FdDHAJdnU6HwGpGOMh%2Bv2imQ3e5eWv9c0Nzfbrp%2FXh9UDDz9OyvH68a%2FHGq%2Bvm03IXVlfPemCmt2s28aV7bdEGtrdfFg9nu0MXrzbd%2BxscpbCVsz3Oytft7eH6Md7wLJ%2FCanvWvKem%2F2D7wdaUwSVfgEjfkkEVKbFOFZLVSwieX8qz6kJ6N7RWDTZXCsYNBEjVALHLENV0iD3FYr3UbBopavTD%2B02fjwTuH56MIoYwh8%2Bp8u7%2BPbTvGJb3ac56P%2F37HxcjMs8%3D +.lijit.com TRUE / TRUE 1783480662 _ljtrtb_76 83a84be8-1d8e-4081-a9f6-42e05e2ae989 +.lijit.com TRUE / TRUE 1796162270 _ljtrtb_5 18bshr4m678sr +.lijit.com TRUE / TRUE 1799622478 ljtrtbexp eJxlkDkSQzEIQ%2B%2Fi2gWLWZSrZXL3b3tcfJMS9ECCb3NvHw5NWGpEb%2FIqtbfgVTsETkuOg6uprRpAbCI5JE8nz440JfSWdFtwsUy9PXIU3YpeI9f5nYiQYkEydT8JJ7D5KDfIvQ%2FbnxgugTmPKPmpPIlJK%2BF3pPEHZGlwefRAAURuwPJ91e8B2LtbPQ%3D%3D +.lijit.com TRUE / TRUE 1799622493 3pids "8014:a7bfe61c1f5205b22e34465d03fefacb,,7d5b04e46ff8eaf91bec603bdbc20bba1fa3b4fa,,139c2033b0bb853ae6140cbd2ca1f01d680097a946f9a07139d46987737158b8,,|8100:b734715e576a5b620291c43f3b5a280f,,d97ab4c28d7a42897d04af42610829b0567be6ea,,1b042a61a1412bc36bc3d3631335628355f71e35c3a1ab246d663baa06c947d3,,|8110:a7bfe61c1f5205b22e34465d03fefacb,,7d5b04e46ff8eaf91bec603bdbc20bba1fa3b4fa,,139c2033b0bb853ae6140cbd2ca1f01d680097a946f9a07139d46987737158b8,,|8111:a7bfe61c1f5205b22e34465d03fefacb,,7d5b04e46ff8eaf91bec603bdbc20bba1fa3b4fa,,139c2033b0bb853ae6140cbd2ca1f01d680097a946f9a07139d46987737158b8,,|8105:a7bfe61c1f5205b22e34465d03fefacb,,7d5b04e46ff8eaf91bec603bdbc20bba1fa3b4fa,,139c2033b0bb853ae6140cbd2ca1f01d680097a946f9a07139d46987737158b8,,|8109:a7bfe61c1f5205b22e34465d03fefacb,,7d5b04e46ff8eaf91bec603bdbc20bba1fa3b4fa,,139c2033b0bb853ae6140cbd2ca1f01d680097a946f9a07139d46987737158b8,," +.ad.gt TRUE / TRUE 1783480661 au_id AU1D-0100-001698785414-LEW7MJH6-AH72 +.colossusssp.com TRUE / TRUE 1799622477 gtm_usr e0e12f89-8f68-4849-ae67-396e3605f5b6 +.colossusssp.com TRUE / TRUE 1799622477 lmg_r 66|15|3|10|12|76|11|67|77|101|97 +.sitescout.com TRUE / TRUE 1799622478 ssi bad985e7-8794-4157-b22d-37333612913c#1698785496290 +.blismedia.com TRUE / TRUE 1799626467 b 654168E218FD9BEFFD4A78C3BLIS +.deepintent.com TRUE / TRUE 1802646478 CDIUSER di_deeb83f6ca8243feb00ca +.deepintent.com TRUE / TRUE 1802646478 CDIPARTNERS %7B%221%22%3A%2220231031%22%2C%22129%22%3A%2220250124%22%2C%22131%22%3A%2220240410%22%2C%22132%22%3A%2220260110%22%2C%22136%22%3A%2220240222%22%2C%22108%22%3A%2220260110%22%2C%22140%22%3A%2220250708%22%2C%22141%22%3A%2220260110%22%2C%22142%22%3A%2220260110%22%2C%22143%22%3A%2220250708%22%2C%22112%22%3A%2220240222%22%2C%22113%22%3A%2220240109%22%2C%22145%22%3A%2220250125%22%2C%22114%22%3A%2220240222%22%2C%22146%22%3A%2220250124%22%2C%22147%22%3A%2220250708%22%2C%22149%22%3A%2220260110%22%2C%22150%22%3A%2220250708%22%2C%22152%22%3A%2220240410%22%2C%22121%22%3A%2220240410%22%2C%22122%22%3A%2220250124%22%2C%22126%22%3A%2220250124%22%7D +.adgrx.com TRUE / TRUE 1802214468 ADGRX_UID 4e497f88-782f-11ee-81f8-32482e403c1e +.rfihub.com TRUE / TRUE 1801782477 rud H4sIAAAAAAAA_-MSsjQ3MDY0MTMxsbQwMLAwNbW0FOIz1HX1yLTwC_dy9c33NwAABPBq-iQAAAA +.rfihub.com TRUE / TRUE 1801782477 eud H4sIAAAAAAAA_1WPMU4DQQxFhUSFRIEikYYrDPKM7W-bDlBEA4KARL8hm46CFMA5KCkpU1JyhByBknKPQMWuCNkguXn297O8c5BPj0c3o5P7i3R1dn45f7ydz54g-vA89fH1bjYOpizMQrTY6thMQi1c6b1jODkELmIfHWsOEYUq5-U6D80iaNZzoCjR92a-sC22e1-Q0GfPZiz42lv53CIs42Vg9bTUDK7SrJ5YEvBdClIkj1p9UlVtx45WS07lUAMwxevg12Stpa3y9p-52e8vE5Eshxufumgz_PvMPILLDxiDv-1HAQAA +.w55c.net TRUE / TRUE 1802300871 wfivefivec mVLEl9il1QXWCd5 +beacon.lynx.cognitivlabs.com FALSE / TRUE 1799622468 UID 0925f90d-eabf-4ced-b2b9-cadb9694d5e0 +beacon.lynx.cognitivlabs.com FALSE / TRUE 1799622468 ss 9ASfGcUg1Z%2FWeHvjiO8JiUrpDlWrXPsyV9c83nESnysaEoqoq3htALWD05NYmBxwcGQ8dvArMuP%2FrUwUteqA4ou6MJfDvjloGeeNrp1hxgU%3D +.acuityplatform.com TRUE / TRUE 1799622477 auid 847260793351 +.acuityplatform.com TRUE / TRUE 1799622477 aum OikKAfqbdXNlck1hdGNoQnlVc2VyTWF0Y2hpbmdJZE1hcPqANvqNdXNlck1hdGNoaW5nSWTMkWxhc3REcm9wVGltZU1pbGxpcyUBTWpFJ1W8mGxhc3RTdWNjZXNzZnVsTWF0Y2hNaWxsaXMlAU1qRSdVvI90aGlyZFBhcnR5VXNlcklkIfuANPpCyEMlAUlDDkRIuEQlAUlDDkRIuEVaQ0FFU0VPbzJuT1ZTbG1wUGY4blFXTHk1VlFB+4Ay+kLEQyUBSiY+EUG6RCUBSiY+EUG6RSH7gTIy+kIkrEMlAU1qRSgehkQlAU1qRSgehkVjOTFhNmQ4OTUtNWJiZC00Yzk2LWI0ODQtMWVkYjk2M2ZlZWRj+4EyN/pCJLZDJQFKJjxgXoREJQFKJjxgXoRFV0hsSENVUlpIbW5HWV9odHdSeTJxZFM3WPuBMjP6QiSuQyUBSiY8Zg2IRCUBSiY8Zg2IRVUzNjk4MjUzNjI1MDM0Njc2OTQ2MDQ2+4A4+kLQQyUBSiY+MRS+RCUBSiY+MRS+RSH7gTEw+kLUQyUBSiY9GGySRCUBSiY9GGySRVI3NDUyNjY5MDM0MTc4MzI3Njk0+4EyMfpCJKpDJQFKJj4jaYZEJQFKJj4jaYZFIfuBMzT6QiQBhEMlAUomPlcfrkQlAUomPlcfrkVqUlgtZjYwNzkzYjEtMGVlZi00Y2E0LTgyYzUtZWU4YTNiNWNkYWI5LTAwNfuBNDj6QiQBoEMlAUomQQoxvkQlAUomQQoxvkUh+4E3MvpCJAKQQyUBTWpFKVOWRCUBTWpFKVOWRSH7gTQx+kIkAZJDJQFNTgN/RqhEJQFNTgN/RqhFZTY0NjUxMDE2NDMwMjQ0NTIyMTc0MDIzMDQ4MTg0NjIwMzQ4MDc0+/uGdmVyc2lvbsL7 +.owneriq.net TRUE / TRUE 1786504662 si Q7520753811633417448P +.adx.opera.com TRUE / TRUE 1783480663 UID OPUb598e447ff4b444484a3e5b793c7de50 +.c.appier.net TRUE / TRUE 1799622470 _auid uRFPn0q_B3iJ-ONGdnZBZQ +.clickagy.com TRUE / TRUE 1802646470 cb ZZxNii4CsNrNHhf4fvTcGhok +.sportradarserving.com TRUE / TRUE 1799536067 zuuid 0c453c2e-5e55-4fe3-9049-740eec090ceb +.sportradarserving.com TRUE / TRUE 1799536067 zuuid_k 1 +.sportradarserving.com TRUE / TRUE 1799536067 zuuid_lu 1768086466 +.sportradarserving.com TRUE / TRUE 1799536067 zuuid_k_lu 1768086466 +.mfadsrvr.com TRUE / TRUE 1799622466 tuuid 5e4703f4-14e0-453b-9026-9d49c268eb07 +.mfadsrvr.com TRUE / TRUE 1799622466 tuuid_lu 1768086466 +.mfadsrvr.com TRUE / TRUE 1799622470 ssh !minutemedia=1768086470!bidswitch=1768086467!rise=1768086466!smaato=1737765833!google=1737749553!yieldmo=1737749319!intentiq=1737749112!openweb=1737748827!triplelift=1737748799!onetag=1712791426!taboola=1712791378!sovrn=1708616102!mgid=1704742287 +.creative-serving.com TRUE / TRUE 1799190470 tuuid d76dec14-1b37-413d-9634-f86f69927815 +.creative-serving.com TRUE / TRUE 1799190470 tuuid_lu 1768086470 +.company-target.com TRUE / TRUE 1802300867 tuuid 50772b55-2539-48f4-9792-491248fd76f9 +.company-target.com TRUE / TRUE 1802300867 tuuid_lu 1768086466|eqx:0|ix:-186|rp:-349|tlx:-349 +.mgid.com TRUE / TRUE 1799622477 muidn o08rOa33HNvb +.a-mx.com TRUE / TRUE 1799622477 amdt_t p::1704742288432 +.a-mx.com TRUE / TRUE 1799622477 amuid2 7a9a0eaa-8763-494f-a19c-ff6c08c88f76 +.a-mx.com TRUE / TRUE 1799622477 pamdt_t p::1704742288432 +.a-mx.com TRUE / TRUE 1799622477 pamuid2 7a9a0eaa-8763-494f-a19c-ff6c08c88f76 +.adhaven.com TRUE / TRUE 1786504662 uid 4c_c553ec4a-2731-4d1a-882a-843e046d4c06 +.media.net TRUE / TRUE 1799536071 data-o 276afcb7-5c3a-406c-8d05-8a2894744407~~3 +.media.net TRUE / TRUE 1799622475 data-pbs setstatuscode~~1 +.ctnsnet.com TRUE / TRUE 1799622469 cid 39a120f51a3e40d588e976fbafe13e6f +.betweendigital.com TRUE / TRUE 1799622470 dc was1 +.betweendigital.com TRUE / TRUE 1799622470 tuuid b16f2b86-1f09-5309-b32b-76b7d6b7e147 +.betweendigital.com TRUE / TRUE 1799622470 ut aWLbxgAGJjjwjhvb2mDqv4a1-1UE-S_2NDFWRQ== +.traversedlp.com TRUE / TRUE 1797620838 v1.cookieId s%3A3423a7ae-bcd9-4c3a-8e04-72bd2cbd9b0c.pqvYvjrrzijfWRft1Xi2w9q4NyfAW5Lgf3CLcgU1jjk +.alocdn.com TRUE / TRUE 1783516591 uuid bc8a2178-c61f-4230-b4b4-9c1c65d13081 +.socdm.com TRUE / TRUE 1802646471 SOC ZZ9oQsCo5ugAADzpoEYAAAAA +.sundaysky.com TRUE / TRUE 1802646478 sskyu d6.680b1a7f159a4c48921f356b642f47a9 +.sundaysky.com TRUE / TRUE 1802646478 sskyCreationTime 1704949195932 +.bfmio.com TRUE / TRUE 1799622466 __io_cid 248c815d-b156-4db9-8a92-46c25764dd54 +.bfmio.com TRUE / TRUE 1799622466 __103_cid 7b3a0d56-9687-4b59-b959-b7bc82b68d2a +.bfmio.com TRUE / TRUE 1799622466 __106_cid 248c815d-b156-4db9-8a92-46c25764dd54 +.bfmio.com TRUE / TRUE 1799622466 __168_cid AADBck7KgtEAABjN509uAw +.bfmio.com TRUE / TRUE 1799622466 __147_cid d6.680b1a7f159a4c48921f356b642f47a9 +.undertone.com TRUE / TRUE 1799643429 UID_EXT_46 248c815d-b156-4db9-8a92-46c25764dd54 +.rtb.mx TRUE / TRUE 1799622477 amdt_t p::1708616096070 +.rtb.mx TRUE / TRUE 1799622477 amuid2 7a9a0eaa-8763-494f-a19c-ff6c08c88f76 +.rtb.mx TRUE / TRUE 1799622477 pamdt_t p::1708616096070 +.rtb.mx TRUE / TRUE 1799622477 pamuid2 7a9a0eaa-8763-494f-a19c-ff6c08c88f76 +.onaudience.com TRUE / TRUE 1799622469 cookie 64096b5cf64dd62a +.ml314.com TRUE / TRUE 1783480600 pi 3642252982602432536 +.go.affec.tv TRUE / TRUE 1799622470 ck 65d769bed154af0001cede82 +.go.affec.tv TRUE / TRUE 1775862470 pt eyJhbiI6eyJkdCI6MTc2ODA4NjQ3MCwiaWQiOiIxNDQ2NjY0NjMzMDYyNDU1NzM4IiwibHMiOjE3NjgwODY0NzB9LCJ0dCI6eyJkdCI6MTc2ODA4NjQ3MCwiaWQiOiJKbGplYm1lVDhTWFpQWlFWVHFQdUJ3PT0iLCJscyI6MTc2ODA4NjQ3MH0sInRkIjp7ImR0IjoxNzY4MDg2NDcwLCJpZCI6IjI0OGM4MTVkLWIxNTYtNGRiOS04YTkyLTQ2YzI1NzY0ZGQ1NCIsImxzIjoxNzY4MDg2NDcwfSwidiI6MH0=|1768086470|6b354ac39182a0f3e7e3fa9f9ed0005b01ab7646 +.c.bing.com TRUE / TRUE 1786249799 SRM_B 10188FE1CFA1634236249C51CE0F62C0 +.clarity.ms TRUE / TRUE 1786249800 MUID 10188FE1CFA1634236249C51CE0F62C0 +.alcmpn.com TRUE / TRUE 1799622493 _3ci 4898dc00-f791-11ee-87da-35dab27f2b66 +.onetag-sys.com TRUE / TRUE 1802273212 OTP HTJCyV8vRH5apyIbS4jgTGmh02TGaXE7yVXssIgnxhE +.riverside.fm TRUE / FALSE 1787692546 ajs_anonymous_id 21dd7898-1bfc-402f-b77a-7b431fcb8478 +.riverside.fm TRUE / FALSE 1787243493 cookiehub eyJhbnN3ZXJlZCI6ZmFsc2UsInJldmlzaW9uIjoxLCJkbnQiOmZhbHNlLCJhbGxvd1NhbGUiOnRydWUsImltcGxpY3QiOnRydWUsInJlZ2lvbiI6IkcwIiwidG9rZW4iOiJwanhpdlJGdGpCeWw5bE1UTUxpWHNac3hWTzREdnNXb2c0eWRlYUhZNENlcmgxcmdhWkhaWVFGa3BWN0JTd1JJIiwidGltZXN0YW1wIjoiMjAyNC0wNC0xNlQxNzo1OTo1NC4wNTdaIiwiYWxsQWxsb3dlZCI6dHJ1ZSwiY2F0ZWdvcmllcyI6W10sInZlbmRvcnMiOltdLCJzZXJ2aWNlcyI6W119 +.riverside.fm TRUE / TRUE 1787243493 _zitok e8af6ff1d02a6d1909bc1713290389 +.riverside.fm TRUE / TRUE 1784140212 __stripe_mid 84ab569e-8d4f-4816-a632-04e6d62c32405c3e59 +.riverside.fm TRUE / FALSE 1790267493 _ga GA1.1.1848369474.1713290394 +.riverside.fm TRUE / FALSE 1789403493 _uetvid 21509ba0fc1b11ee99478f310d5b7258 +.riverside.fm TRUE / FALSE 1790716547 _ga_PF9PK8DC9Z GS2.1.s1756156546$o8$g0$t1756156546$j60$l0$h1160639619 +.d.adroll.com TRUE / TRUE 1786072565 __adroll 6cc6d395376a1bb9f56de1a8c78c955f-a_1713364488 +.d.adroll.com TRUE / TRUE 1786072565 receive-cookie-deprecation 1 +.adroll.com TRUE / TRUE 1786072565 __adroll_shared 6cc6d395376a1bb9f56de1a8c78c955f-a_1713364488 +.adroll.com TRUE / TRUE 1786072565 receive-cookie-deprecation 1 +.demdex.net TRUE / TRUE 1783638478 demdex 64651016430244522174023048184620348074 +.demdex.net TRUE / TRUE 1781725180 dextp 21-1-1766173172009|477-1-1766173172826|481-1-1766173173827|843-1-1766173174827|771-1-1766173175829|1957-1-1766173176827|12105-1-1766173177830|575-1-1766173178828|53196-1-1766173179826|121998-1-1766173180825 +.dpm.demdex.net TRUE / TRUE 1783638478 dpm 64651016430244522174023048184620348074 +.go.sonobi.com TRUE / TRUE 1799622514 __uis fee5909e-22fd-42a0-a1fb-e28d64e05182 +.synthesis.com TRUE / FALSE 1775770716 _ga GA1.1.2026762825.1731628556 +.synthesis.com TRUE / FALSE 1775770733 _ga_KQHY76450D GS1.1.1741210716.45.1.1741210732.44.0.0 +.synthesis.com TRUE / FALSE 1775770733 _ga_MJL598MDNX GS1.1.1741210716.45.1.1741210732.44.0.0 +.a-mo.net TRUE / TRUE 1799622514 amuid2 6694de3f-a4e4-4153-be90-38070f322c76 +.a-mo.net TRUE / TRUE 1799622514 pamuid2 6694de3f-a4e4-4153-be90-38070f322c76 +.prebid.a-mo.net TRUE / TRUE 1799622514 sd_amuid2 6694de3f-a4e4-4153-be90-38070f322c76 +.prebid.a-mo.net TRUE / TRUE 1799622514 __amc 2888_1712791451_1768086514 +.prebid.a-mo.net TRUE / TRUE 1799622514 psd_amuid2 6694de3f-a4e4-4153-be90-38070f322c76 +.crwdcntrl.net TRUE / TRUE 1791414601 _cc_id 3cf9e41188988b992aee1510314411e1 +.crwdcntrl.net TRUE / TRUE 1791414601 _cc_dc 0 +.crwdcntrl.net TRUE / TRUE 1791414479 _cc_cc "ACZ4nGNQME5Os0w1MTS0sLC0sEiytDRKTE01NDU0MDY0AYqmGjIAQWbS7XNLHi%2F7wc8AAwJTJr1QZWwrZ%2FjPyMgwEYndhcReMvsAExOE%2FYERLHJh8RwWVJFzRw8xo4rM7tZCFbi39ik3qshhDGMa%2FmuiCsz8cMEcVeTsvR5VVJFLpx6xoYps%2BlOIKvD2oyWqwO%2BNU9CsBgAgHmmA" +.crwdcntrl.net TRUE / TRUE 1791414479 _cc_aud "ABR4nGNgYGDITLp9jgEGmBgYuGaAGFxNn4EkAE3%2BBJg%3D" +.outbrain.com TRUE / TRUE 1775862477 obuid 83bc6354-0805-4310-befc-80a97066c1a2 +.inmobi.com TRUE / TRUE 1799622477 iid ID5-5-1342167a-ef28-4e21-bab5-fd43f14a737a +.inmobi.com TRUE / TRUE 1799622469 gob_cookie YES +.inmobi.com TRUE / TRUE 1775862469 idsp_c d8fbeb2e-e64d-4ded-8362-c043cf92d3c3 +.creativecdn.com TRUE / TRUE 1797620685 g 88s83VQB5MgVwZvDd6Z8_1737748773872 +.creativecdn.com TRUE / TRUE 1797620685 c 88s83VQB5MgVwZvDd6Z8_rvpPdB9Ykz6pEuCHxRxe_1766084684882 +.creativecdn.com TRUE / TRUE 1797620685 ts 1766084684 +.sync.a-mo.net TRUE / TRUE 1799622478 sd_amuid2 6694de3f-a4e4-4153-be90-38070f322c76 +.sync.a-mo.net TRUE / TRUE 1799622478 psd_amuid2 6694de3f-a4e4-4153-be90-38070f322c76 +.smartadserver.com TRUE / TRUE 1800299087 TestIfCookieP ok +.mediawallahscript.com TRUE / TRUE 1800644838 mCookie cc96bf10-da8d-11ef-9bbb-13760a7a1a50 +.mediawallahscript.com TRUE / TRUE 1800644838 mUserCookie %7B%226d7065a93a3c4b7fac2bbe5cf7d31996%22%3A%5B%22a7bfe61c1f5205b22e34465d03fefacb%22%2C%227d5b04e46ff8eaf91bec603bdbc20bba1fa3b4fa%22%2C%22139c2033b0bb853ae6140cbd2ca1f01d680097a946f9a07139d46987737158b8%22%5D%7D +.udmserve.net TRUE / TRUE 1797620686 dt 778C4ACD-EEFB-3BB1-8558-9CE42AFF4D9C +.udmserve.net TRUE / TRUE 1797620686 udmts 1766084685.0 +.ad-stir.com TRUE / TRUE 1797620787 uid 92c9d51d-b1f9-4ed5-aed2-5a64d6d9fcb9 +.a.usbrowserspeed.com TRUE / TRUE 1797620804 tuid e9c2099e-35ab-4932-afa1-aa1367b10f1e +.insightexpressai.com TRUE / TRUE 1783480594 DW 00000000-0000-000b-a862-6a1737752050 +.agkn.com TRUE / TRUE 1799622482 ab 0001%3AE8XKtnaP2Z0ZuSwwKJa%2Fca70CcxR1DZIhCajAiTWekfdmnpivPSPKlV1KU2AScJ9zOSVGGcwbF8s%2FIv51kx8ouEYbisZ%2Bu18RoxCUZYFIqgUvyb6tl9OYN0MbljWX0KC88Xyo%2FN1vB5ndGqjMM95YT%2BDEtG4PxU05hCPTIgfyYxqL7oxpOdAk958wz%2BoN1VWt9qTn81D90opZR%2BdWINFNGAgmGMwaFdtbK%2FTiHgYdXrfSL%2B6UHcDR8bWcMNKyF9KdMJ4uFrtDZXCB3PwyO8u7wByYLoxIbyWxn4fIiiID3LBIL%2FtQyBHrd%2FOio2TxWzDruQ6o1NVPSJY7WzuoJ0oFQ%3D%3D +.agkn.com TRUE / TRUE 1797709222 u C|0EAAAAAAAMNhmpQAA4ABYAQAHAAAAAAIAEU___x4AAAAAAGOFrgAAAAAZJD-mAAAAAAd2kfAAAAAAJKG5lQA +.medialiance.com TRUE / TRUE 1800644702 mCookie 89440e60-dab1-11ef-8ec3-892a738b03da +.medialiance.com TRUE / TRUE 1800644702 mUserCookie %7B%22e5cd834d8052bae2c694ddeaeca6f999%22%3A%5B%22b734715e576a5b620291c43f3b5a280f%22%2C%22d97ab4c28d7a42897d04af42610829b0567be6ea%22%2C%221b042a61a1412bc36bc3d3631335628355f71e35c3a1ab246d663baa06c947d3%22%5D%7D +.contextweb.com TRUE / TRUE 1799190477 V Pv9rW4ongCVL +.contextweb.com TRUE / TRUE 1799622471 pb_rtb_ev 3-1w32|8kt.0.1|7Eb.1.1|8ly.l.1|8px.5|8tI.5|7Nq.5|7Bj.4.CAESEObJmDpmPVBEKUyOQ9zVbuY|8sZ.5.78e498bf-f874-4fc4-90db-ec299869f88b|8dw.5.1|8iH.5|8hH.5|7TY.0|7TZ.0.1|7fJ.5|8fr.5|88e.5|7bq.2bW.1|7br.11C.1|8nM.8.1|7bs.9.1|8fP.5|6zB.1.7b3a0d56-9687-4b59-b959-b7bc82b68d2a|8gU.2bW.1a14e546-92a3-4ee7-a6ad-dc4e8f83d083|80p.2bW.1|8dQ.1.1|7dW.0.1|87G.5|8bO.5|2N.1.AQALN3bf5gd9IQFydVqNAQA8IwEBAQEBAQEBAQEBAQEBAQEB|7GB.8.1|7RY.5|8vg.5.1|8ue.5.78e498bf-f874-4fc4-90db-ec299869f88b|7dN.2bW.AADBck7KgtEAABjN509uAw|4is.1.CAESENz6rsahLafnUk4itvuDrpI|7Xz.5|8rx.1.LNYXWIAC-1G-2KTD|7I7.5|3oy.5.bad985e7-8794-4157-b22d-37333612913c-654168d8-5553|82A.5|8ro.5|8f1.0.A4879159953770555400|86L.5|8i8.2bW.1 +.contextweb.com TRUE / TRUE 1799190477 VP part_Pv9rW4ongCVL +.contextweb.com TRUE / TRUE 1799622471 pb_rtb_ev_part 3-1w32|8kt.0.1|7Eb.1.1|8ly.l.1|8px.5|8tI.5|7Nq.5|7Bj.4.CAESEObJmDpmPVBEKUyOQ9zVbuY|8sZ.5.78e498bf-f874-4fc4-90db-ec299869f88b|8dw.5.1|8iH.5|8hH.5|7TY.0|7TZ.0.1|7fJ.5|8fr.5|88e.5|7bq.2bW.1|7br.11C.1|8nM.8.1|7bs.9.1|8fP.5|6zB.1.7b3a0d56-9687-4b59-b959-b7bc82b68d2a|8gU.2bW.1a14e546-92a3-4ee7-a6ad-dc4e8f83d083|80p.2bW.1|8dQ.1.1|7dW.0.1|87G.5|8bO.5|2N.1.AQALN3bf5gd9IQFydVqNAQA8IwEBAQEBAQEBAQEBAQEBAQEB|7GB.8.1|7RY.5|8vg.5.1|8ue.5.78e498bf-f874-4fc4-90db-ec299869f88b|7dN.2bW.AADBck7KgtEAABjN509uAw|4is.1.CAESENz6rsahLafnUk4itvuDrpI|7Xz.5|8rx.1.LNYXWIAC-1G-2KTD|7I7.5|3oy.5.bad985e7-8794-4157-b22d-37333612913c-654168d8-5553|82A.5|8ro.5|8f1.0.A4879159953770555400|86L.5|8i8.2bW.1 +.trkn.us TRUE / TRUE 1783004736 barometric[cuid] cuid_67946932-4589-41ab-98a0-895e3e2d97a8 +.rubiconproject.com TRUE / TRUE 1799622478 khaos M6CF4TG8-W-J70S +.rubiconproject.com TRUE / TRUE 1799622478 audit 1|tcR/wBEzWcKBeiMwxwaIMJH/wrGgPvJ3EHTCxBIN+XkJG9/P5Pbd26X+G7tBI/pLK4KewJT0BBosa0K79A6XVh3ukALJD0TTOcV4pE4CozChJWL1SayQt/FdJMTEemORX1vKT1ONdRY= +.rubiconproject.com TRUE / TRUE 1799622478 khaos_p M6CF4TG8-W-J70S +.rubiconproject.com TRUE / TRUE 1799622478 audit_p 1|tcR/wBEzWcKBeiMwxwaIMJH/wrGgPvJ3EHTCxBIN+XkJG9/P5Pbd26X+G7tBI/pLK4KewJT0BBosa0K79A6XVh3ukALJD0TTOcV4pE4CozChJWL1SayQt/FdJMTEemORX1vKT1ONdRY= +.rubiconproject.com TRUE / TRUE 1775862478 receive-cookie-deprecation 1 +.turn.com TRUE / TRUE 1783638477 uid 7289271102826593249 +.yieldmo.com TRUE / TRUE 1799622476 yieldmo_id 3eHPvHHbmPHxStMoIXOR%7C1737849600000%7C3724524149782542238%7C3488079986244395387 +.bcbst.com TRUE / FALSE 1776969422 WT_FPC id=23ab50c55541c3198981742409300028:lv=1742409421989:ss=1742409300028 +.unchained.com TRUE / TRUE 1789657964 osano_consentmanager_uuid 59c5c276-5ecc-493b-8730-858eaf3c0a5f +.unchained.com TRUE / TRUE 1789657964 osano_consentmanager rPSs2F3XcQDGXcdQCAI3PxJj_1u57qW_iTlDLyjgVTeNX-uK8InVJC0TTXTwBZ_fQDe5D8H7eSSH-WBNLcwyGO7r7-VKutZLjTTahHSxQgotJZgsxPatac9bLWOQyeah774yEWXH_7wYU2HwtHpLepF3TEH89eLciFtN8TN-s0TOfe4RS0eOoU1eSBl7t3UcmOML_Utx-arUek685WuQRGnaFcEIk_Z8J8-dYEKGyw4Mpp8XqCODSWuEgZVikxUIg5hmrBYZviEdapwxILbVlQ2dL-IiUZM9Say0a6o2Q_1xIxvg-qif3EnY_jBsv7wa6-PGLRQTwwo= +.unchained.com TRUE / FALSE 1792680928 ab.storage.deviceId.5ed20afa-515f-4b9a-a9f1-5cf8769574ef g%3Af2f6ef8d-1172-1d40-a491-ae8efac5929e%7Ce%3Aundefined%7Cc%3A1758117898590%7Cl%3A1758120460258 +.unchained.com TRUE / FALSE 1792680928 ab.storage.userId.5ed20afa-515f-4b9a-a9f1-5cf8769574ef g%3Aeddf5362-4840-44fa-9ea6-cca1c2bfc860%7Ce%3Aundefined%7Cc%3A1758117898588%7Cl%3A1758120460258 +.unchained.com TRUE / FALSE 1792680928 ab.storage.sessionId.5ed20afa-515f-4b9a-a9f1-5cf8769574ef g%3Ab553b88d-0448-ca46-18e3-355394901910%7Ce%3A1758122728118%7Cc%3A1758120460258%7Cl%3A1758120928118 +.my.unchained.com TRUE / TRUE 1789657965 __stripe_mid 7e35a7e6-2671-4130-8964-ccd5ac2894477168e1 +ten31.vc FALSE / FALSE 1777385004 ss_cvr 15a4855b-9c66-4647-a7f8-61aa8b6595be|1730144511490|1731602788023|1742825003097|3 +.www.linkedin.com TRUE / TRUE 1790346598 bscookie "v=1&202503241857592b5ead33-6f67-4547-8ead-51dcfe02910aAQH8ycCs5-tSCgNIGNLairKP-yifEUhF" +.www.linkedin.com TRUE / TRUE 1784050017 li_rm AQG7XdvCSOs9BAAAAZd64ZXVLmo_dWkMhTknsO1hJmw1642__4KUBhOQk-IPq4F333CgLCTedSmyIWVHvkQrz_B0m3jw4uth0WO67p5suv8V2zWX4QuOvwaxukP7Q8EiAFb6y7uUwulv84mX-3OXQiIsENB_-OsLPgk1FgQDVkIDd_LGlSFaPANKLOAK2SKTCaBzkWddFr2ESOryCmjzEtioqeeV9L-rC07LBeuIDhFtB-maFTKp0pxdxqJoHSAo_wiDIZnO3NNTyWU4Qe7tSN6HvaOQ-D7Xepm2MZYdIpRAlkvYkMnKbNSBYyV4CylY0hkzpNvLQgkFnoQsvJUQ9Q +.www.linkedin.com TRUE / TRUE 1790346598 JSESSIONID "ajax:4171029513032656218" +.www.linkedin.com TRUE / TRUE 1784062922 li_ep_auth_context AHVhcHA9c2FsZXNOYXZpZ2F0b3IsYWlkPTI5NTM3MjkzMixpaWQ9Mzg1Mjk1NDQ0LHBpZD00OTE4NTMzNTMsZXhwPTE3NTUxMTg5MjE0NTIsY3VyPXRydWUsc2lkPTE1Mzc4NTAxMTYsY2lkPTIwMTMyMzk2ODMBresxvFmgTpwVa7MvInSzFcXh5Gk +.www.linkedin.com TRUE / TRUE 1790346598 li_at AQEFAHQBAAAAABb-2ykAAAGYCfm4NwAAAZmlVHycTgAAF3VybjpsaTptZW1iZXI6MzI2MTc2NzUyNv3G6zHnnd48jDJY2beVMl5kbCvn2KO6Gdn6NeRn_G1-hCe3g8eT0xMvjx3ANoSIRzueX9tT1VWF6P0UL28EArA3bRzI3uRWKO0tc5JNeNSywAlkv12xcNnKL8C7yGiEw1E01ROKaeK7oSPUkaUVI62vV-0aI0QG2SYtvnIkbiSkn9VGbLBIJnnvxbwrG4S_7A99DQ +.inflightinternet.com TRUE / FALSE 0 rxVisitor 1743863097950UC0EEQA5P7KC2DRQ7BM3GGT4OU23FTM9 +.inflightinternet.com TRUE / FALSE 0 FLIGHT_TRACKER_STORED {%22departureAirportCode%22:%22BNA%22%2C%22destinationAirportCode%22:%22ORD%22%2C%22flightNumber%22:%22SKW6259%22%2C%22departureTime%22:%222026-03-31T16:11:00.00Z%22%2C%22arrivalTime%22:%222026-03-31T17:27:00.00Z%22} +.inflightinternet.com TRUE / FALSE 0 LOGGER_DATA {%22airlineCode%22:%22AAL%22%2C%22flightNumber%22:%22SKW6259%22%2C%22mac%22:%227A:6D:B0:B5:E8:ED%22} +.inflightinternet.com TRUE / FALSE 0 DYNATRACE_THEME default +.inflightinternet.com TRUE / FALSE 0 flightIdentifier {%22tailNumber%22:%22N759EV%22%2C%22departureAirportCode%22:%22KBNA%22%2C%22destinationAirportCode%22:%22KORD%22} +.inflightinternet.com TRUE / FALSE 0 hasActiveInflightSession true +.inflightinternet.com TRUE / FALSE 0 airlineCode aal +.inflightinternet.com TRUE / FALSE 0 dtCookie v_4_srv_21_sn_MME8PSIQ380J5EFVLH66ARG76FJG56J9_perc_100000_ol_0_mul_1_app-3Aa102791a62dd9f00_1_app-3A4eca8c42196ba4a2_1_app-3Aea7c4b59f27d43eb_1_rcs-3Acss_0 +.inflightinternet.com TRUE / FALSE 0 env prodp +.inflightinternet.com TRUE / FALSE 0 loggerData {%22airlineCode%22:%22AAL%22%2C%22flightNumber%22:%22SKW6259%22%2C%22mac%22:%227A:6D:B0:B5:E8:ED%22} +.inflightinternet.com TRUE / FALSE 0 rxvt 1774976057213|1774974154984 +.inflightinternet.com TRUE / FALSE 0 dtSa false%7CC%7C4%7CWI-FI%20PACKAGES%7Cx%7C1774974257207%7C174240510_433%7Chttps%3A%2F%2Fwifi.inflightinternet.com%2Fapp%2Faal%2Fifc%2F%7C%7C%7Cgobrowse%7C +.inflightinternet.com TRUE / FALSE 0 dtPC 21$174206057_810h1p21$174268351_454h1vMFQEHSHFARVKFMKVPWJURICDEAJLMUQW-0e0 +.airbornesecure.inflightinternet.com TRUE / TRUE 1805384898 __stripe_mid 414200e8-7823-41f0-afc8-3f42d2ef439691897d +.paypal.com TRUE / TRUE 1796165169 enforce_policy ccpa +.paypal.com TRUE / TRUE 1779902570 cookie_check yes +.paypal.com TRUE / TRUE 1779902570 d_id 80fb76c2e17a49e1a765a042b42e17241745342570275 +.paypal.com TRUE / FALSE 1796165168 TLTDID 27040534859840361107447354011634 +.paypal.com TRUE / TRUE 1796165182 ts_c vr%3D0658813d1960a5515860f94cfc3d321b%26vt%3Ddc142d6019a0a55100281bbcfb685727 +.paypal.com TRUE / TRUE 1796164903 _iidt CH4Hh6drZWFH8o+y2QON+f528H0a7DM3JGqCL5uu1wpJsHz46R4JUJJOav8LNV5X3jmFJjsXrVbEApq3l5Q8MuB8Cux+nm2vd8NclJ0= +.paypal.com TRUE / TRUE 1799188912 login_email grant.gilliam%40gmail.com +.paypal.com TRUE / TRUE 1799188927 rmuc 9lroqoP1vjt1EudVvIA_HPq_C19q2vzSEp2JWJOfcaqyHnYBt5tu-KrW3yZ1Sy158fuVuI-DZkOS8iS0YI3FQPx-8aqHquZdiOgK0P7QA04z2BfeyxgIAknf0QAAut48NYUq7b2fx26EFIwu2to7DqKzmyw-bVv1zQCz90PXRAzB5iKcEhqY_R3y34GqPCZHXNJE7WX6n9zbwOB3Q2NLy1nqH8G +.paypal.com TRUE / TRUE 1796164928 cookie_prefs T%3D0%2CP%3D1%2CF%3D1%2Ctype%3Dimplicit +.paypal.com TRUE / TRUE 1799189167 ui_experience tokenType%3Dsoftware_token_authenticator%26tokenIdentifier%3DWIquIrjeoFYEfLoCrFjE_dUugfLYs0LhEVfAIg2-XuT4cB6jNZ0ONljYUtZx1kzBMjPbPavKH5ReKg5E +.paypal.com TRUE / TRUE 1796165182 ts vreXpYrS%3D1796165181%26vteXpYrS%3D1764630981%26vr%3D0658813d1960a5515860f94cfc3d321b%26vt%3Ddc142d6019a0a55100281bbcfb685727%26vtyp%3Dreturn +.paypal.com TRUE / TRUE 1799189168 KHcl0EuY7AKSMgfvHl7J5E7hPtK FIfTcfpEkB2i1XvmAN4PP4SeJq5aSSd9DNTO8-_lo5rhvENJIgcciW9fAf8jzsCnPpD2zH2SA-BfXQMh +.paypal.com TRUE / TRUE 1799189168 sc_f gkBt9_7bEOc05CHYIB-CZVSf6hnGCUjMm4o0U1EEZQ5TVg9WJlcdAf0KGbXipy31piIid40JIe5XcYCDZCVIhl4V1qs4AYsE6yb0iG +.paypal.com TRUE / TRUE 1799189168 ddi cQ1FNbgqR-YWLJ15JSTC4edfi7MpfuC5MlVWS4HsWm-ssPIuApHPwVILKObl3lofRerCE1-FEkv9d-OVEHyhVBQqH8cgn3xbgcJnpUkZ1O4wMYh8 +.chase.com TRUE / FALSE 1807901097 v1st 951B54D03A5ADC53 +.chase.com TRUE / TRUE 1776350059 chase_campaign_data SourceCode=OS0001&iq_id= +.chase.com TRUE / FALSE 1807901097 s_vi [CS]v1|951B54D03A5ADC53-423DCF575550D14A[CE] +.chase.com TRUE / TRUE 1807901097 adtoken.chase.com |DYN|S85Tt1LnADdBsXuTfTrS7%2Fbn8yqG9rDCjlio3e%2BMLkhqtNC7mBTfZZt09%2B7uuG%2BaeeedqbPa95IcTyVOkgx5i1DXGkdn9R3kBzVcvy4ErOjUvXQpxD5Cpgcfo8DuGJMc%7CZoQo7mE96ssrsP2JUB%2FjifrYecMgP2Pa%2B7tpIzl%2B6MT2vvJgkyFQgGf%2ByEIopgCi +.chase.com TRUE / FALSE 1807901097 NyJB5Jgn A-IWXeOcAQAAzSp6FikrPh4IyzXygB0y02ND6fi5NRhDkX-8S8Zv9KkNwt9hAWvCVQyucmVTwH9eCOfvosJeCA|1|NO_BIT|c039b4f5bec6e784a132343dce8fcfe170fa321d +.chase.com TRUE / TRUE 1804880699 BRAND_1_0 WEALTH +.chase.com TRUE / TRUE 1804877098 PC_1_0 pfid%3D10383181%7Csegment%3DPAF%7Csegg%3DPAF%7Czip%3D37027-1532%7CECI%3D0346242280%7CAOC%3D6615%2C6653%2C%7Cpm%3DATM%2CCHK%2CCHK%2CSAV%2CBAC%2CBAC%2CALA%2CALS%7CRPC%3D0550%2C0404%2C%7Capc%3D100%2C067%2C080%2C064%2C010%2C%7Clocale%3Den_us%7ClastUpdate%3D2025-04-21%7ClastSent%3D2025-04-21%7Cpod%3D07EA%7Cusrtp%3DPR%7Cpftp%3DPER%7Csc%3DTN%7C +.chase.com TRUE / FALSE 1807901099 AMCV_EA673DFC5A2F19060A495C9C@AdobeOrg 1914845758|MCIDTS|17564|MCMID|78587949278339082538316563911219460485|MCAID|NONE|MCOPTOUT|isoptedout-false|MCAAMLH||MCAAMB||MCCIDH|1019576346|MCSYNCSOP|411-17568|vVersion|2.3.0|TESTPROFILE|false|IsCustom|true +.chase.com TRUE / TRUE 1804880699 _iscpo 07EA +.chase.com TRUE / TRUE 1804880699 DEFAULT_PAGE_1_0 octagonOverviewDashboard +.twitter.com TRUE / TRUE 1782324962 personalization_id "v1_BPqyvG9JD5AM/EiiDpIOTA==" +.twitter.com TRUE / TRUE 1787107244 guest_id_marketing v1%3A175254724421271077 +.twitter.com TRUE / TRUE 1787107244 guest_id_ads v1%3A175254724421271077 +.twitter.com TRUE / TRUE 1787107244 guest_id v1%3A175254724421271077 +.t.co TRUE / TRUE 1782324962 muc_ads f0a4d615-2d82-4018-be9d-fa847c1b1cc5 +.goduke.com TRUE / TRUE 1780040693 visid_incap_3109055 12O3hjvaTjau1Wo/L9c77mHTOGgAAAAAQUIPAAAAAADgd0MG9tKPy5WEPkv2jsF9 +api.phantombuster.com FALSE / TRUE 1784673334 session vMmRJdC83mC7jcKh60wDuoeCT6EE1Q1JrHbQAZadXNE +api.phantombuster.com FALSE / TRUE 1787859447 amplitude_device_id 1750113334053923537236069351 +.disqus.com TRUE / TRUE 1783888531 disqus_unique 1rp6lv2627db3 +.disqus.com TRUE / TRUE 1799622478 zeta-ssp-user-id 1rp6lv2627db3 +.chromewebstore.google.com TRUE / FALSE 1805841466 _ga GA1.1.1914643352.1750113338 +.chromewebstore.google.com TRUE / FALSE 1808253614 _ga_KHZNC1Q6K0 GS2.1.s1773693584$o7$g1$t1773693614$j30$l0$h0 +phantombuster.com FALSE / TRUE 1781650031 CookieConsent {stamp:%27HhuJjYqXCqaOyewhVggQ6Y15nrzwtSUvdW4WnuTUu8garuTH22muNg==%27%2Cnecessary:true%2Cpreferences:false%2Cstatistics:false%2Cmarketing:false%2Cmethod:%27explicit%27%2Cver:1%2Cutc:1750114031149%2Cregion:%27us-47%27} +.linkedin-ei.com TRUE / TRUE 1782431038 bcookie "v=2&b2cebf06-4e82-405b-84a3-620f0d797b85" +.nextlayer.capital TRUE / TRUE 1782160419 _reb2buid 752ba5c6-07cd-49b1-ac28-7508358b0f25-1751056419084 +www.ten31.xyz FALSE / FALSE 1785617475 ss_cvr 9e202335-e808-4d6e-9559-dcf4bdb0f6db|1751057469803|1751057469803|1751057469803|1 +.calendly.com TRUE / TRUE 1783859117 __stripe_mid a5c306c1-a69f-408c-8771-60c5fa5917dd4a27ad +.calendly.com TRUE / TRUE 1783859083 OptanonAlertBoxClosed 2025-07-12T12:24:43.800Z +.calendly.com TRUE / TRUE 1783859083 OptanonConsent isGpcEnabled=0&datestamp=Sat+Jul+12+2025+07%3A24%3A43+GMT-0500+(Central+Daylight+Time)&version=202501.1.0&browserGpcFlag=0&isIABGlobal=false&hosts=&consentId=83e3e526-39d4-462d-a3b9-f7fc0cdd26a0&interactionCount=2&isAnonUser=1&landingPath=NotLandingPage&groups=C0001%3A1%2CC0003%3A1%2CC0002%3A1%2CC0004%3A1&AwaitingReconsent=false&intType=1 +.calendly.com TRUE / FALSE 1783859115 ajs_anonymous_id f1bc62b0-b6b1-4650-9dec-737555e0c0a6 +.calendly.com TRUE / FALSE 1783859115 analytics_session_id 1752323115018 +.calendly.com TRUE / FALSE 1783859115 analytics_session_id.last_access 1752323115018 +.primal.net TRUE / TRUE 1802375175 __stripe_mid 992a6e6e-7e2d-4fc6-808c-34d093472745a9847d +.squarespace.com TRUE / FALSE 1785164736 SS_MID 3055171d-2109-4415-8dc8-67e67ccc9f60 +.squarespace.com TRUE / TRUE 1785974242 IR_PI 20d8783e-56d7-11f0-8c1b-63794422bed6%7C1751414241665 +.squarespace.com TRUE / TRUE 1785248955 SS_ANALYTICS_ID a1a96488-e25b-4653-bd8b-e01cea208d5f +.squarespace.com TRUE / FALSE 1785600940 _scid CACU7iWxruAeEvOr9q2G_PUVUG36W21R +.squarespace.com TRUE / FALSE 1785600941 _sctr 1%7C1751346000000 +.squarespace.com TRUE / FALSE 1786028737 _ga GA1.1.277295834.1751414244 +.squarespace.com TRUE / FALSE 1785164737 _tt_enable_cookie 1 +.squarespace.com TRUE / FALSE 1785164737 _ttp 01JZ46S0AQBRTJZZSZ5J8XDKKJ_.tt.1 +.squarespace.com TRUE / FALSE 1785655435 _scid_r E4CU7iWxruAeEvOr9q2G_PUVUG36W21RsZWTPQ +.squarespace.com TRUE / FALSE 1785164737 _uetvid 21f1067056d711f084c3b9ce4219e763 +.squarespace.com TRUE / FALSE 1785164737 ttcsid_C2ENC2QQV140ORDIO960 1751468737412::x48b425HPqqgdt634mr6.2.1751468737413 +.squarespace.com TRUE / FALSE 1785164737 ttcsid 1751468737412::I-XIdf8s62VM_nUhb1Kc.2.1751468737413 +.squarespace.com TRUE / FALSE 1786917443 _ga_1L8CXRNJCG GS2.1.s1752357442$o3$g0$t1752357442$j60$l0$h0 +.syuh.net TRUE / TRUE 1786028735 brwsr 20d8783e-56d7-11f0-8c1b-63794422bed6 +.support.squarespace.com TRUE / FALSE 1783004737 _pin_unauth dWlkPVptSTNNak5tWkRrdE1tUXpNQzAwWmpRMExUbGpOV1l0Tm1Zd1lXTTJOVGhqTW1ObQ +.adnxs.com TRUE / TRUE 1775862514 uuid2 1446664633062455738 +.adnxs.com TRUE / TRUE 1775862477 anj dTM7k!M40:t9upA#3Rt'X^Fru/+Xdh$X>//ECId2BWai$i]m[A$UBcKbCxr^=6d[wc9RkhB2?Pkz/X#8!VFwEWPvED^aC?429-W18Pqx$sRr6QPL@dv9salD[=0K$O^$+=cHe`9zz0BHZE:Z:EZF0Id%*g0D(36I3l +.adnxs.com TRUE / TRUE 1775862477 uids eyJ0ZW1wVUlEcyI6eyJhZG54cyI6eyJ1aWQiOiIxNDQ2NjY0NjMzMDYyNDU1NzM4IiwiZXhwaXJlcyI6IjIwMjYtMDEtMjRUMjM6MDc6NDkuMDk0MTEwNzE1WiJ9LCJhbXgiOnsidWlkIjoiNjY5NGRlM2YtYTRlNC00MTUzLWJlOTAtMzgwNzBmMzIyYzc2IiwiZXhwaXJlcyI6IjIwMjYtMDEtMjRUMjM6MDc6NTcuMzI4NDE3MDQ0WiJ9LCJydWJpY29uIjp7InVpZCI6IjEiLCJleHBpcmVzIjoiMjAyNi0wNC0xMFQyMzowNzo0N1oifSwiY29ubmVjdGFkIjp7InVpZCI6IjEiLCJleHBpcmVzIjoiMjAyNi0wNC0xMFQyMzowNzo1N1oifX19 +.adnxs.com TRUE / TRUE 1775862514 XANDR_PANID PCf2dRo2AFUKrIDqTJhluM3eM1XLRFlhDROSCoEjPO_Sw3m5nzC-ztQr0_2_onNy6e4tHgdHVNekMcT6peC1QxLqYdSVViNIymGcFz_JA7k. +support.squarespace.com FALSE / FALSE 1786028735 SQSP_HarveyDent {%22aus_live_chat%22:{%22variant%22:%22variant%22%2C%22when%22:%22Wed%2C%2002%20Jul%202025%2015:05:35%20GMT%22}%2C%22autologin-qa%22:{%22variant%22:%22variant%22%2C%22when%22:%22Wed%2C%2002%20Jul%202025%2015:05:35%20GMT%22}%2C%22fullstory_2024%22:{%22variant%22:%22control%22%2C%22when%22:%22Tue%2C%2001%20Jul%202025%2023:57:21%20GMT%22}} +.www.ten31timestamp.com TRUE / TRUE 1783259137 ab_experiment_sampled %22false%22 +.www.ten31timestamp.com TRUE / TRUE 1783259137 ab_testing_id %224951d750-8a99-4bec-be9f-70654cb5e528%22 +.lynalden.com TRUE / FALSE 1786460292 _ga GA1.2.1028841246.1751900292 +.lynalden.com TRUE / FALSE 1786460293 _ga_L92TPRGR2X GS2.2.s1751900292$o1$g0$t1751900292$j60$l0$h0 +.www.lynalden.com TRUE / TRUE 1783436299 __stripe_mid b632f803-daa5-47b6-ac31-677c6d2eaa3c9f9398 +www.gentexcorp.com FALSE / TRUE 1783461745 CookieConsent {stamp:%27K6r5zFH9mn5JntJlZZFzhGRJN4b9yBifDOZtJtW14s06elm6tuanLA==%27%2Cnecessary:true%2Cpreferences:false%2Cstatistics:false%2Cmarketing:false%2Cmethod:%27explicit%27%2Cver:1%2Cutc:1751925745079%2Cregion:%27us-47%27} +.fliphtml5.com TRUE / FALSE 1786485759 first_visit_channel_source {"channel":"","referer":"https://www.gentexcorp.com/ops-core/","page":"https://online.fliphtml5.com/usalo/ngjl/","time":1751925758501,"uuid":"1321c34c-fe88-41b9-918d-bdc107547787"} +.fliphtml5.com TRUE / FALSE 1786485759 _ga GA1.1.2038386891.1751925759 +.fliphtml5.com TRUE / FALSE 1786485760 _ga_DQQGBZ508R GS2.1.s1751925758$o1$g0$t1751925760$j58$l0$h0 +www.atomicdefense.com FALSE / FALSE 1783461903 localization BR +www.atomicdefense.com FALSE / FALSE 1783461791 po_visitor m8eTuYuxWK1s +www.atomicdefense.com FALSE / FALSE 1783461903 _pin_unauth dWlkPVptSTNNak5tWkRrdE1tUXpNQzAwWmpRMExUbGpOV1l0Tm1Zd1lXTTJOVGhqTW1ObQ +www.atomicdefense.com FALSE / FALSE 1783461900 AMP_9bdc728a74 {"deviceId":"f06d75df-1f90-4871-83ca-407a640705fa","sessionId":1751925900780,"lastEventTime":1751925900785,"optOut":false} +www.atomicdefense.com FALSE / FALSE 1783461903 mktz_client %7B%22is_returning%22%3A0%2C%22uid%22%3A%2219038728291293545260%22%2C%22session%22%3A%22sess.2.1065091378.1751925789881%22%2C%22views%22%3A4%2C%22referer_url%22%3A%22https%3A//www.google.com/%22%2C%22referer_domain%22%3A%22www.google.com%22%2C%22referer_type%22%3A%22organic%22%2C%22visits%22%3A1%2C%22landing%22%3A%22https%3A//www.atomicdefense.com/collections/ops-core%3Fsrsltid%3DAfmBOooj_64xdS_VznDSwAnnBIus-V5EU_sm13jPgwNFmBugUYJYlVPZ%22%2C%22enter_at%22%3A%222025-07-7%7C17%3A3%3A9%22%2C%22first_visit%22%3A%222025-07-7%7C17%3A3%3A9%22%2C%22last_visit%22%3A%222025-07-7%7C17%3A3%3A9%22%2C%22last_variation%22%3A%22%22%2C%22utm_source%22%3Afalse%2C%22utm_term%22%3Afalse%2C%22utm_campaign%22%3Afalse%2C%22utm_content%22%3Afalse%2C%22utm_medium%22%3Afalse%2C%22consent%22%3A%22%22%2C%22device_type%22%3A%22desktop%22%2C%22id_website%22%3A%2222272%22%7D +www.atomicdefense.com FALSE / FALSE 1786485904 __kla_id eyJjaWQiOiJOVEUxTWpKbVpqQXRaV0kzTWkwMFltVmlMV0UzTXpBdFpqazFaamMzWW1Sa05tUmkiLCIkcmVmZXJyZXIiOnsidHMiOjE3NTE5MjU3OTIsInZhbHVlIjoiaHR0cHM6Ly93d3cuZ29vZ2xlLmNvbS8iLCJmaXJzdF9wYWdlIjoiaHR0cHM6Ly93d3cuYXRvbWljZGVmZW5zZS5jb20vY29sbGVjdGlvbnMvb3BzLWNvcmU/c3JzbHRpZD1BZm1CT29val82NHhkU19Wem5EU3dBbm5CSXVzLVY1RVVfc20xM2pQZ3dORm1CdWdVWUpZbFZQWiJ9LCIkbGFzdF9yZWZlcnJlciI6eyJ0cyI6MTc1MTkyNTkwNCwidmFsdWUiOiJodHRwczovL3d3dy5nb29nbGUuY29tLyIsImZpcnN0X3BhZ2UiOiJodHRwczovL3d3dy5hdG9taWNkZWZlbnNlLmNvbS9jb2xsZWN0aW9ucy9vcHMtY29yZT9zcnNsdGlkPUFmbUJPb29qXzY0eGRTX1Z6bkRTd0FubkJJdXMtVjVFVV9zbTEzalBnd05GbUJ1Z1VZSllsVlBaIn19 +.atomicdefense.com TRUE / FALSE 1783461789 ig-id ig_5776dfedafb4fbfa5d8a0463ec428fdb482d +.atomicdefense.com TRUE / FALSE 1783461789 ig-fv 1751925789909 +.atomicdefense.com TRUE / FALSE 1783461904 ig-vars {%22redirectedFrom%22:%22%22} +.atomicdefense.com TRUE / FALSE 1783461905 _tracking_consent 3.AMPS_USTN_f_f_zab7AzwiQy-Q8yLtLVc7Sg +.atomicdefense.com TRUE / FALSE 1783483509 _shopify_y 451263ce-612e-4c39-b0fe-443739bf2b16 +.atomicdefense.com TRUE / FALSE 1783461792 _clck ocpdsc%7C2%7Cfxe%7C0%7C2014 +.atomicdefense.com TRUE / FALSE 1786485904 _ga GA1.1.1985663682.1751925793 +.atomicdefense.com TRUE / FALSE 1783461904 ig-pv 4 +.atomicdefense.com TRUE / FALSE 1785621904 _uetvid 2d99def05b7e11f095a86b06a58774de +.atomicdefense.com TRUE / FALSE 1786485971 _ga_DR9XYZYM0N GS2.1.s1751925793$o1$g1$t1751925970$j23$l0$h0 +.atomicdefense.com TRUE / FALSE 1786485971 _ga_RXXREL5ZDN GS2.1.s1751925793$o1$g1$t1751925970$j60$l0$h0 +.shop.app TRUE / TRUE 1783461790 _shop_app_essential :AZfm6hWDAAEA2lpbeXDvhGPE2CP5hEllSYSKvAUDHudOlhmgIiEVVnPR0SjK8iStsKARIED0vfI: +shop.gentexcorp.com FALSE / TRUE 1786485991 fornax_anonymousId 43a7fe87-4464-4364-a9b3-d09c4d9bc2c1 +imgs.signifyd.com FALSE / TRUE 1786485792 thx_guid 02ee0705746ea94abf905302f905850a +imgs.signifyd.com FALSE / TRUE 1786485989 tmx_guid AAyzkeJccLt_C_o4kB4ST4GaYVbg5NQoZFdThM_wef9bqxO5rVGOJT_lY3ZajVHU_V0vj2k-mbu90T98Bfdkh2oEoUFhdQ +.www.atomicdefense.com TRUE / FALSE 1785621904 _ttp 01JZKEM7EB58RNXBEDDN22T99Y_.tt.0 +.www.atomicdefense.com TRUE / FALSE 1785621904 ttcsid_C5D3RI94DV8CDK843CH0 1751925792247::ghM8Tb_9JiqcUXeKz3dd.1.1751925904202 +.www.atomicdefense.com TRUE / FALSE 1785621904 ttcsid 1751925792260::RdbnOzqaRoJcPIMjCNiQ.1.1751925904263 +.imgflip.com TRUE / FALSE 1786505380 _ga GA1.1.1468374004.1751944562 +.imgflip.com TRUE / FALSE 1786504563 _lc2_fpi 9099df4a8854--01jzm0h28krqc9vshh3xhn8bkn +.imgflip.com TRUE / FALSE 1786504563 _lc2_fpi_meta %7B%22w%22%3A1751944562963%7D +.imgflip.com TRUE / TRUE 1783480563 connectId {"ttl":86400000,"lastUsed":1751944563314,"lastSynced":1751944563314} +.imgflip.com TRUE / TRUE 1783480661 _au_1d AU1D-0100-001751944563-69KY1P7C-GVCX +.imgflip.com TRUE / FALSE 1785622660 cto_bundle oUv1S19mSmowTTh0d2pqaWpkb1dmYTVobmdNdVd0aWFMNThOd0lzajdSTDBSOWRaTUI3ZWVrMzQxeCUyQnhvVUoxNkRXOGNvM3VDNDZySFBoeiUyQm5QQnFqT3duaXZhS0Q3WUR5eWp4bjczMWZXSVR4RUVDVjVaYWhyVUhGSzRCb1ozd1VpY2xRMGRkVGVtNGZOVDdIWm5vdUI0cUMlMkZjdDJWMGtMJTJGNlU0YlA2WFlmJTJCb1UySUR3cFZuZmF6JTJCeXhYYXhPeUY4d05OYXZjVE12V1JLV3NIeWVsNUVQQWt3JTNEJTNE +.imgflip.com TRUE / FALSE 1785622660 cto_bidid Lw_CZl95T0FzZWhSd3oxRnNXa0FvcDU2TnZDY3l0S0FLVkJHZURTRiUyQnY4aWpWeiUyQm5CTkpUdXpMQ29lZTBXbk0zSjkzekJCbmtDb2Q0dE42YjE3WTdPRzByMDZHOEx6ZldnZzhSSUVhRlVpb21pc2E0Y2dLanNUVXhxc2R4dWI0M1g3VGRTRE90MjN1WUNwN3psaXpqdEU0dUZRJTNEJTNE +.imgflip.com TRUE / TRUE 1785640563 __gads ID=be74fbe2c6af3547:T=1751944563:RT=1751945371:S=ALNI_Majida08QPOx0983ktIinyR_WTtvw +.imgflip.com TRUE / TRUE 1785640563 __gpi UID=000010f862a6cf50:T=1751944563:RT=1751945371:S=ALNI_MZePD2Obp6lMmzFkvBjgc8EFVzWug +.imgflip.com TRUE / FALSE 1786505372 _ga_DCRTFFEBRL GS2.1.s1751944562$o1$g1$t1751945372$j60$l0$h0 +.imgflip.com TRUE / FALSE 1786505380 _ga_X8YQQMPY4Q GS2.1.s1751944562$o1$g1$t1751945380$j60$l0$h0 +.imgflip.com TRUE / FALSE 1786505380 _ga_FVWZ0RM4DH GS2.1.s1751944594$o1$g1$t1751945380$j60$l0$h0 +imgflip.com FALSE / FALSE 1785640563 usprivacy 1--- +imgflip.com FALSE / FALSE 1786504661 ad_clicker false +imgflip.com FALSE / FALSE 1783480593 mako_fpc_id 3738993d-cd36-4677-b646-6fc049347db8 +.yahoo.com TRUE / TRUE 1799644078 A3 d=AQABBLnFMmUCEMk1D1H8-MekCRhtMCBNsz4FEgEBCAGBL2dXZ9xR0iMA_eMDAAcIucUyZSBNsz4&S=AQAAAoKPGn6r5rWbaNAGTE52Z1o +.seedtag.com TRUE / TRUE 1799622514 st_uid 0197e809-1d28-76fe-bd2e-2a8367a9b191 +.seedtag.com TRUE / TRUE 1799190473 st_cs l+EQxuppf4rbMmxYXoBW58T59pDkRx2pDuf/17SALU9Kr4IZJN0cUVL9qSFzxTAd6H7BITeXLEgmthJP6fQVva7CVfG+zgCuqsD8N5JSlleiKNVn8TIyfg5O8p0Ff5DWk18CTQyrN1LPhrZQsSU26fG2cTnsjPdRDuSZqm3jHyGtWResS77PKvj5IR9wv7KBD9lfFPw+rcj7MYK14NZNBH9zDwhlZ6CQiHVH/gB40SyhhlvVnxvcGGyD2zdLMjJM94XMjgx0JPFSyGm6M1LjRGLCBip0RzrA8awS9XfgBBXD4jkuHKmqnkIY7xibjo/Ef1EjhGjXZ87kZ3+vgJhzGpz+MqoPTBm7G83cnoW8vKyBKWMpPolYLzdcmCokXd0JaiY5HjG/MCVxt21HD6wxD5W8eplRV+Xnf0NNqyhjdw0GVCwnqsOCz+jA8a2vMQJb+1aV3ZRIeIrzFzdAmb9VF4OO3Sf9HsM+Gw/gGcK5cyRXNyNPCh7Bf5DLNA/rVVoHngxiAPkZM/0a5xpk1VxRNNrdFNAXlVHBGMQqQrw2AUvdAZlpdqd3GN+tqhVA5DZTTODKPtehdNzRfse84/OFrTIb77P5m0ZjEOMsRvUNZ/JHJH0dBNWPLTJZ2vQ2GjhW4zX5tIaAAbPjVavGlHCYzbQBbw2rAzVhmJklTv03qxGlunzkDQTPzcx3Tj+m4f2y9x/Kbk3bX8AVX84Se59+swq+7PyNEaqydy37toP4jxkuQoHzVofwsxjsLFA6rwwUN4eTcrg5acgNRAl5VpTv7fi8B3UBXUnAThL1TV+WBBqX25UXrvC5b7lVUIYrpmwlzBkC4t72H2bW7UHw7YcLxLfpcJnP91i+qE0j5Bh0R3A1GV5TXKYU6G83s5Kw7F8s6hx8uL0Xeqz9iOf+Gwk8sr+gk6Hx8SqdTIzbIYDBjYXUR/oIC5hQa7/h0Sg3YldN5JyPc1UWz6GGHtOJknxGmsgfsySZ2KZR9P1j8hF2pnmF1IBV0ijc48jSMVH18gbmB9j0Rqb+QCLFnDa0+eo7m8SMc6Go4Ir3o4DTS4d/WUx7o0+jnVlqZg7BWkQdb2DCuyxTzW+e607oasZCQYzaYpNwyOPZiBbDHu20PMIg2XedEn6dZCM0TKI11NcF2bdI +.seedtag.com TRUE / TRUE 1799190473 st_csd 1768086473030:1768086473030 +.ymmobi.com TRUE / TRUE 1783048602 ym_user_cookie ym_user_5b605628-abd0-48fd-bd12-83c5c527fa56 +.imageresizer.com TRUE / TRUE 1783480605 _au_1d AU1D-0100-001751944605-941OR5IA-XZDN +.imageresizer.com TRUE / TRUE 1785640604 __gads ID=1f9e426ea177e36f:T=1751944604:RT=1751944604:S=ALNI_MbPQ8YWwfAMnZDnSpZTK-1tzXkpSQ +.imageresizer.com TRUE / TRUE 1785640604 __gpi UID=000010f8629bfb1f:T=1751944604:RT=1751944604:S=ALNI_MannLbLSR4mPPaI59X6gzoqBfXaPQ +.imageresizer.com TRUE / FALSE 1783480605 FCNEC %5B%5B%22AKsRol_EONZyLR1QTUgle0ZVzM-n9ByfL6ADfltvoktmT5_GjgRq-XCG1s0xa-hgfjTd-uRi6s_LNCs0l7GI-7ZPGJMD_EwaEXhwaCHyS6nynf6A5dCwHjop7b5xXj7GoDFI1NQZ3SHBWtd-UXkk7eiMAC3kWCCzlA%3D%3D%22%5D%5D +.imageresizer.com TRUE / FALSE 1786504653 _ga_HKYMVDPKL5 GS2.1.s1751944604$o1$g1$t1751944652$j12$l0$h0 +.imageresizer.com TRUE / FALSE 1786504653 _ga_FVWZ0RM4DH GS2.1.s1751944652$o1$g0$t1751944652$j60$l0$h0 +.imageresizer.com TRUE / FALSE 1786504653 _ga GA1.1.375673278.1751944604 +.dotomi.com TRUE / TRUE 1802214483 DotomiUser 735907388364061728$0$1937005452$0$1 +.dotomi.com TRUE / TRUE 1802214483 receive-cookie-deprecation 1 +.tremorhub.com TRUE / TRUE 1786505372 tv_UIGL CAESEASjkMgMQrOFLnFB39UE0C4 +.substack.com TRUE / TRUE 1783516203 ab_experiment_sampled %22false%22 +.substack.com TRUE / TRUE 1783893441 ab_testing_id %2244509386-1a6b-42f4-b509-ab1db0e27257%22 +.substack.com TRUE / FALSE 1783893441 ajs_anonymous_id %227bb0425f-0f94-4e6c-8063-0f20a54752e2%22 +.substack.com TRUE / TRUE 1783516203 cf_clearance aUh6OlZdUfcR60RwE6JMZek1WPAqCm6uDxKFKqPiXog-1751980203-1.2.1.1-kjJYlHkQzvgVBAGX3gDpDTsZ1fH4YGoYbW5gPEh9PL_0ZxL5XuPCe84MnpCCiOgM6PkhHjQwx19CErUhQFVdrbpTu2rhi_uCSi_90idaOy4otuMFWzb3EEao5KHcecVNPa2OK1j4pzW2mgsYrREEItKlOZYEHiWQX2H7KmI25k2au7PEVvLyHuhpETFJ8QXFkezJns.8Foz5YEC6adgVgoEcTN5Ey6qyZmlGaJdPcbQ +bitvocation.substack.com FALSE / FALSE 1783516203 ajs_anonymous_id %227bb0425f-0f94-4e6c-8063-0f20a54752e2%22 +bitvocation.substack.com FALSE / FALSE 1786540205 intro_popup_last_hidden_at 2025-07-08T13:10:04.898Z +.spotify.com TRUE / TRUE 1784809599 sp_t 9b0c39cb0a61c277ad5448d840cfd76f +.onrampbitcoin.com TRUE / FALSE 1786540591 _lc2_fpi 596329408dff--01jzn2whhcz8c8ajjthcwmkdtc +.onrampbitcoin.com TRUE / TRUE 1783084591 _reb2buid 8bd9bd84-1391-4e3d-846c-328b0c081882-1751980590774 +.onrampbitcoin.com TRUE / FALSE 1786540591 _li_ss CgA +.airtable.com TRUE / TRUE 1783633552 brw brw4smjnDVd8Cinv4 +.airtable.com TRUE / FALSE 1785793501 _uetvid f78798d05d0d11f08a6705efe43f47fe +.airtable.com TRUE / FALSE 1783633501 _clck iakk65%7C2%7Cfxg%7C0%7C2016 +.airtable.com TRUE / FALSE 1786657502 _ga GA1.1.882492552.1752097502 +.airtable.com TRUE / FALSE 1786657502 _ga_VJY8J9RFZM GS2.1.s1752097501$o1$g0$t1752097501$j60$l0$h0 +.airtable.com TRUE / FALSE 1786657502 __q_state_bhFVoN1cyFKKDaNW eyJ1dWlkIjoiMzkxNzJkMjUtZjk5OS00YjZhLTljYmUtNTYwNTdiNjQ2YjEyIiwiY29va2llRG9tYWluIjoiYWlydGFibGUuY29tIn0= +.airtable.com TRUE / TRUE 1783719903 acq eyJhY3F1aXNpdGlvbiI6Ilt7XCJwbGF0Zm9ybVwiOlwiZGVza3RvcFwiLFwib3JpZ2luXCI6XCJscFwiLFwidG91Y2hUaW1lXCI6XCIyMDI1LTA3LTA5VDIxOjQ1OjAxLjQzMFpcIixcInJlZmVycmVyXCI6XCJodHRwczovL3d3dy5nb29nbGUuY29tL1wiLFwidXRtX3NvdXJjZVwiOlwiZ29vZ2xlXCIsXCJ1dG1fbWVkaXVtXCI6XCJwYWlkc2VhcmNoXCIsXCJ1dG1fdGVybVwiOlwiYWlydGFibGVcIixcInV0bV9jYW1wYWlnblwiOlwiZGVtYW5kX2JyX2JyYW5kX2FsbF91c19lblwiLFwidXRtX2V4dHJhMlwiOlwiOTM2NDA3NjkxXCIsXCJ1dG1fZXh0cmE1XCI6XCJrd2QtMzI1Mjg5MzIzMTk0XCIsXCJ1dG1fZXh0cmE4XCI6XCJjXCIsXCJ1dG1fZXh0cmExMFwiOlwiNDc3MzU2MDA1NThcIixcInV0bV9leHRyYTlcIjpcIkVBSWFJUW9iQ2hNSTctang1OS13amdNVnhrN19BUjBjQWpXWkVBQVlBU0FBRWdMUTRfRF9Cd0VcIn0se1wicGxhdGZvcm1cIjpcImRlc2t0b3BcIixcIm9yaWdpblwiOlwibG9naW5cIixcInRvdWNoVGltZVwiOlwiMjAyNS0wNy0wOVQyMTo0NTowMi43OTdaXCIsXCJyZWZlcnJlclwiOlwiaHR0cHM6Ly93d3cuYWlydGFibGUuY29tL2xwL2FpLXBzdS1wbHA/dXRtX3NvdXJjZT1nb29nbGUmdXRtX21lZGl1bT1wYWlkc2VhcmNoJnV0bV9leHRyYTU9a3dkLTMyNTI4OTMyMzE5NCZ1dG1fZXh0cmEyPTkzNjQwNzY5MSZ1dG1fZXh0cmExMD00NzczNTYwMDU1OCZjcmVhdGl2ZT03MTk0ODYyMDM5MDgmdXRtX2V4dHJhOD1jJnV0bV90ZXJtPWFpcnRhYmxlJnV0bV9jYW1wYWlnbj1kZW1hbmRfYnJfYnJhbmRfYWxsX3VzX2VuJmdhZF9zb3VyY2U9MSZnYWRfY2FtcGFpZ25pZD05MzY0MDc2OTEmZ2JyYWlkPTBBQUFBQUR6UnFuVXNPTWY4OFlXQ3hmNmlVMUNkcXZ6VXomZ2NsaWQ9RUFJYUlRb2JDaE1JNy1qeDU5LXdqZ01WeGs3X0FSMGNBaldaRUFBWUFTQUFFZ0xRNF9EX0J3RVwifV0ifQ== +.airtable.com TRUE / TRUE 1783719903 acq.sig VbCJhMJQ8qvQpqGFONOWbN1OXlApNf5ntop0TkAw-80 +.airtable.com TRUE / FALSE 1783633503 OptanonConsent isGpcEnabled=0&datestamp=Wed+Jul+09+2025+16%3A45%3A03+GMT-0500+(Central+Daylight+Time)&version=202407.1.0&browserGpcFlag=0&isIABGlobal=false&hosts=&consentId=abc3b4d9-ab2a-43a3-b283-c4af636ff8e5&interactionCount=1&isAnonUser=1&landingPath=NotLandingPage&groups=C0001%3A1%2CSSPD_BG%3A1%2CC0004%3A1%2CC0002%3A1%2CC0007%3A1%2CC0003%3A1&AwaitingReconsent=false +.airtable.com TRUE / FALSE 1783633503 _pxvid f8799d0c-5d0d-11f0-b579-e0c8bc5ee247 +airtable.com FALSE / TRUE 1783719901 __Host-airtable-session eyJzZXNzaW9uSWQiOiJzZXN0TU1qR0R2VmxIZm5BMyIsImNzcmZTZWNyZXQiOiIzVDJRVUhfQXJCd0ZiOVRHZ3E5aElsX0QifQ== +airtable.com FALSE / TRUE 1783719901 __Host-airtable-session.sig Aidk0OW2vbUxWfZB4R4MhZaWcq78REvJPHO8MMRLxI0 +www.airtable.com FALSE / TRUE 1786657501 _gd_visitor cfe31e24-0577-4f24-8a7b-c5b5b543d807 +.www.o-big.com TRUE / TRUE 1786659845 svSession 0fd5e4906b7339cf9bde249633a18234cf868b613a67599fb1325cf6699014e5c326ac79c994a282767ff1780b559f631e60994d53964e647acf431e4f798bcdb7ea6cd9965668a1c08575c953936cf7a269ffc58bff5c078e08f5ac4e0c9f3523ed3cd3d08cd0d5bf5f8249d5cb460e97486947151a2d4b846e328f0b3a965bfc47f77fd29db05c561cd0b5dc7cb10e +www.capitalcreek.com FALSE / FALSE 1786662356 ss_cvr 9a009276-bc2c-42f1-ae1f-bd774a7e367a|1752102341467|1752102341467|1752102341467|1 +.phantombuster.com TRUE / FALSE 1786912344 _ga GA1.1.952538975.1752352344 +.phantombuster.com TRUE / FALSE 1783888344 amp_e1d871 17515780722794205086972709266.b3JnXzU0MDY4OTQ0Njk5OTgwNzg=..1j005diff.1j005diff.1.0.1 +.phantombuster.com TRUE / FALSE 1786912356 _ga_1J42NVR091 GS2.1.s1752352344$o1$g1$t1752352355$j49$l0$h0 +.dropbox.com TRUE / TRUE 1787106780 locale en +.dropbox.com TRUE / TRUE 1784082806 t Ro6TSx0EmgdOtX2d9pqOd4IT +www.dropbox.com FALSE / TRUE 1787106780 gvc MzA4NDYxNDYwOTg2NDU2ODM3NTY5MjU1OTU4OTMzMzkyODY0MDM5 +www.dropbox.com FALSE / TRUE 1784082806 __Host-js_csrf Ro6TSx0EmgdOtX2d9pqOd4IT +.x.com TRUE / TRUE 1787107244 guest_id_marketing v1%3A175254724429867078 +.x.com TRUE / TRUE 1787107244 guest_id_ads v1%3A175254724429867078 +.x.com TRUE / TRUE 1787107244 guest_id v1%3A175254724429867078 +.x.com TRUE / TRUE 1787107244 personalization_id "v1_6oYA/pddvCo/znTfM2ySMg==" +announcekit.app FALSE / TRUE 1784087903 ak_eu_41U9JC eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyIkIjpbMSwiODEyODM0MzEzODYwMjEzMS1wcm9kIl0sImlhdCI6MTc1MjU1MTkwM30.zHj6WLSLJK5OEX4a5WYD2vG75uxC24iffpeLzr47_FI +.arkm.com TRUE / FALSE 1784089797 mp_f32068aad7a42457f4470f3e023dd36f_mixpanel %7B%22distinct_id%22%3A%20%22%24device%3A1980c58b88316d-00fd236b85478a-17525636-1fa400-1980c58b88316d%22%2C%22%24device_id%22%3A%20%221980c58b88316d-00fd236b85478a-17525636-1fa400-1980c58b88316d%22%2C%22%24initial_referrer%22%3A%20%22https%3A%2F%2Fprimal.net%2F%22%2C%22%24initial_referring_domain%22%3A%20%22primal.net%22%2C%22__mps%22%3A%20%7B%7D%2C%22__mpso%22%3A%20%7B%22%24initial_referrer%22%3A%20%22https%3A%2F%2Fprimal.net%2F%22%2C%22%24initial_referring_domain%22%3A%20%22primal.net%22%7D%2C%22__mpus%22%3A%20%7B%7D%2C%22__mpa%22%3A%20%7B%7D%2C%22__mpu%22%3A%20%7B%7D%2C%22__mpr%22%3A%20%5B%5D%2C%22__mpap%22%3A%20%5B%5D%7D +.arkm.com TRUE / FALSE 1787113799 _ga GA1.1.1405382360.1752553799 +.arkm.com TRUE / FALSE 1784089799 _clck yis5e9%7C2%7Cfxm%7C0%7C2022 +.arkm.com TRUE / FALSE 1787113809 _ga_K3BXC51SZE GS2.1.s1752553798$o1$g1$t1752553809$j49$l0$h0 +.arkm.com TRUE / FALSE 1787113809 _ga_P74N755GGG GS2.1.s1752553799$o1$g1$t1752553809$j50$l0$h0 +www.clarity.ms FALSE / TRUE 1784089799 CLID 3796f63d2e084a1099127441ee73559a.20240224.20260715 +riverside.fm FALSE / TRUE 1787164202 fullstoryDisabled false +riverside.fm FALSE / FALSE 1784140202 language en +.techcrunch.com TRUE / FALSE 1787668441 _lc2_fpi 97c377c895b4--01k0ppft76z9bxs29b449re4k1 +.techcrunch.com TRUE / FALSE 1787668441 _lc2_fpi_meta %7B%22w%22%3A1753108441318%7D +.techcrunch.com TRUE / TRUE 1787236442 _awl 2.1753108442.5-4718d52d8d3ff7e48da0c74e99d3637d-6763652d75732d6561737431-1 +.royalcaribbean.com TRUE / FALSE 1784673342 rwd_id 863febde-c986-4dbf-bfaf-3013289b94f2 +.royalcaribbean.com TRUE / TRUE 1784673135 BVBRANDID ad90f986-2e00-4e20-b3dc-2f11159e449c +.royalcaribbean.com TRUE / FALSE 1784673135 crl8.fpcuid 92329951-c9c1-4190-90a4-3598a26f3afe +.royalcaribbean.com TRUE / TRUE 1784807731 _abck F108A0B9EC005650B661BF9BB01E7D19~0~YAAQxB82F8Uusw2YAQAAwIMjNw7zxV37FmFRxuYUmdPLtoXWoJcetrWoLyngJEXmdAvZRLJ3G8bUCK/9WC1A83/xsytYK/VjD0VDLgtX6WMJupvmzPjR/NKzWFWNvcdtWyHy/viOAR1lY+TUp4hJJOvvvaQg5YWJQhTJketokwwY5LujWHmkCS62dIPHsRKIXzSB3di8GjJUJT10IXUdLwQTKdtBNuRabiqewxVQ2luIxxBji809V9VIsr0PtK2OZt8gWAyiyOUDsusB0reCIQXFMFv1z7MfvJnp5WNCHgt2q7+gMVPwt8Kl2VSOckIcuclbQK110QY+XuD8xHy1Z9N7HcfAr4c7GvrUSaR6RUqHRFZ2RTZKeUUl+urKkXreeiOpWfuGOZJnh3GBblgbnPR7SCB17e4JBGBKPoZUBxbn/fUNDTfO51UmMIyU0bqgAku7TrogzHb7RW2L+/DtTjdkbNAHvS2Kjx4KaqTY3UgqGVpYfHXb+HW7Mq3qsCpNXm+gPGhPRuKWgrR5WEzfRZ30R/GPyfWG3RuHCe3DkaAawSt/Z2zeFaIsQIsJ6LmPgDdp0krG6sOWsELRj/09lhSF017IcDkrvRBkhpmQOOnEhHBv0E15VsnoBEWbjeZG54PxNW0=~-1~-1~1753275331 +.affirm.com TRUE / TRUE 1787697151 tracker_device 4292def8-15ab-4237-b3ca-9f5e52246878 +.affirm.com TRUE / TRUE 1787697151 t_v2_s IjQyOTJkZWY4LTE1YWItNDIzNy1iM2NhLTlmNWU1MjI0Njg3OCI.G2BRfw.kUXQa7Q6O69gRkS5dOf07g_tjjU +.affirm.com TRUE / TRUE 1787697151 3060738.3440491 4292def8-15ab-4237-b3ca-9f5e52246878 +www.affirm.com FALSE / TRUE 1787697151 session eyJfcGVybWFuZW50Ijp0cnVlfQ.G2BRfw.2iT6h9nSbIrnYiDK8QzBXBNu9rg +www.royalcaribbean.com FALSE / FALSE 1787697365 checkout_continuity_service 4292def8-15ab-4237-b3ca-9f5e52246878 +www.royalcaribbean.com FALSE / FALSE 1787697365 tracker_device 4292def8-15ab-4237-b3ca-9f5e52246878 +.www.royalcaribbean.com TRUE / FALSE 1784673365 OptanonConsent isGpcEnabled=0&datestamp=Mon+Jul+21+2025+17%3A36%3A05+GMT-0500+(Central+Daylight+Time)&version=202411.2.0&browserGpcFlag=0&isIABGlobal=false&hosts=&consentId=3f85f375-54ce-4137-8722-39c3b4977d19&interactionCount=1&isAnonUser=1&landingPath=NotLandingPage&groups=C0001%3A1%2CC0003%3A1%2CC0002%3A1%2CC0007%3A1%2CC0004%3A1&AwaitingReconsent=false&geolocation=%3B +.www.royalcaribbean.com TRUE / FALSE 1784673365 OptanonAlertBoxClosed 2025-07-21T22:36:05.381Z +panteracapital.com FALSE / FALSE 1784862486 cookielawinfo-checkbox-necessary yes +panteracapital.com FALSE / FALSE 1784862486 cookielawinfo-checkbox-functional no +panteracapital.com FALSE / FALSE 1784862486 cookielawinfo-checkbox-performance no +panteracapital.com FALSE / FALSE 1784862486 cookielawinfo-checkbox-analytics no +panteracapital.com FALSE / FALSE 1784862486 cookielawinfo-checkbox-advertisement no +panteracapital.com FALSE / FALSE 1784862486 cookielawinfo-checkbox-others no +.espn.com TRUE / FALSE 1788711177 SWID 1CF34069-B43A-481D-C820-B9858B640E40 +.espn.com TRUE / FALSE 1788711180 mbox session#b77414c80b6646a6a0cc0845b13a44bc#1754153040|PC#b77414c80b6646a6a0cc0845b13a44bc.34_0#1817395980 +.agi.cash TRUE / FALSE 1789382528 __gsas ID=6758cd34cb5426af:T=1755686528:RT=1755686528:S=ALNI_MZ-wFdtgNKLvbYZ4dowVyQMR64yFw +agi.cash FALSE / FALSE 1787222528 pvisitor e5aff3ba-477f-40b9-b537-d738f686877a +.archive.is TRUE / FALSE 1784477267 tmr_lvid 4d87e89d7858ef61d33e1fe99f47ac73 +.archive.is TRUE / FALSE 1784477267 tmr_lvidTS 1755706067933 +.mail.ru TRUE / TRUE 1787328588 VID 24Phk500X52Y0026Kk1Q01oY:::0-0-0-cae53fc-0-dc04c0c:CAASEKxMyii6AT78_-3NUPqD0UIaYHtsqvds-0kSklpezGsuCNzWPVpfXllbLL1vqX4f428ZW2vUxODue-givca9Uz03dLH8ZLOAeFiLjUWT2D7xIKjFSSw1mNF8GXEjOnpIeFEPmwLXqAyKewzaUgOzLS9SFg +.riverside.com TRUE / TRUE 1787243494 ajs_anonymous_id 21dd7898-1bfc-402f-b77a-7b431fcb8478 +.riverside.com TRUE / TRUE 1787243494 cookiehub eyJhbnN3ZXJlZCI6ZmFsc2UsInJldmlzaW9uIjoxLCJkbnQiOmZhbHNlLCJhbGxvd1NhbGUiOnRydWUsImltcGxpY3QiOnRydWUsInJlZ2lvbiI6IkcwIiwidG9rZW4iOiJwanhpdlJGdGpCeWw5bE1UTUxpWHNac3hWTzREdnNXb2c0eWRlYUhZNENlcmgxcmdhWkhaWVFGa3BWN0JTd1JJIiwidGltZXN0YW1wIjoiMjAyNC0wNC0xNlQxNzo1OTo1NC4wNTdaIiwiYWxsQWxsb3dlZCI6dHJ1ZSwiY2F0ZWdvcmllcyI6W10sInZlbmRvcnMiOltdLCJzZXJ2aWNlcyI6W119 +.riverside.com TRUE / TRUE 1787243494 _zitok e8af6ff1d02a6d1909bc1713290389 +.riverside.com TRUE / TRUE 1787243494 __stripe_mid 84ab569e-8d4f-4816-a632-04e6d62c32405c3e59 +.riverside.com TRUE / TRUE 1787243494 hubspotutk d4c3d9ccc190dc8a9c6c7ffef14b0996 +.riverside.com TRUE / TRUE 1787243494 _fbp fb.1.1731079730566.829343683934799639 +.riverside.com TRUE / TRUE 1787243494 _ga GA1.1.1848369474.1713290394 +.riverside.com TRUE / TRUE 1787243494 _clck viwp88%7C2%7Cfst%7C0%7C1849 +.riverside.com TRUE / TRUE 1787243494 fullstoryDisabled false +.riverside.com TRUE / TRUE 1787243494 _gcl_au 1.1.1385786570.1755707485 +.riverside.com TRUE / TRUE 1787243494 __hstc 163253411.d4c3d9ccc190dc8a9c6c7ffef14b0996.1731079729263.1752604204117.1755707484497.7 +.riverside.com TRUE / TRUE 1787243494 __hssrc 1 +.riverside.com TRUE / TRUE 1787243494 _ga_PF9PK8DC9Z GS2.1.s1755707484$o7$g1$t1755707493$j51$l0$h1388164421 +.riverside.com TRUE / TRUE 1787243494 _rdt_uuid 1747764962554.d2f3b35b-0d3d-44cb-994a-6b01b09c67d9 +.riverside.com TRUE / TRUE 1787243494 _uetsid 1d1a53907de311f0943c870e79b8d202 +.riverside.com TRUE / TRUE 1787243494 _uetvid 21509ba0fc1b11ee99478f310d5b7258 +.riverside.com TRUE / TRUE 1787243494 __hssc 163253411.2.1755707484497 +.riverside.com TRUE / TRUE 1787243494 _dd_s rum +riverside.com FALSE / TRUE 1787243494 language en +.bbc.co.uk TRUE / TRUE 1788311620 ckns_policy 000 +.bbc.co.uk TRUE / TRUE 1788225215 ckns_privacy july2019 +.bbc.co.uk TRUE / TRUE 1791249209 ckns_sylphid OmbZGfsd9Pz9Yo_rfUvosfWknKRGe5bjx2yy809wxzg +.bbc.co.uk TRUE / TRUE 1791249209 ckns_id eyJhYiI6Im8xOCIsInBhIjoiV0MyUiIsImVwIjp0cnVlLCJmaSI6eyJnYW0iOnsiaWQiOiIyNkJFMzY1MkZDMEU1NUM5NUZBN0ExQTA5NUFGMjdDQzEwRDIzNjczNDU0RDVDQjExOTJCNDczMDYxNjlCQzc4NTQyOENGQ0ZDQjU2MThFQkNGRUFBMzNGNDc1MkY2NTciLCJ2ZXJzaW9uIjoiYjk3MDk4MzItM2RhYS00ZTkyLWJjMDctMzg0MjA1YzIyZTQzIn0sInBpYW5vIjp7ImlkIjoieVNUQktyVlpLOTRuVnJDNzBNSUhjdlMwRXUzdVR6MnByd3hJcWM3UlFhbjRsUkZsUVN2elJhNThibnRSZFJ2ciIsInZlcnNpb24iOiI0NzFhMjM5YS1hYTNkLTQ5ZTYtOWIxZC1kNTcyNzhiNzkxMDgifSwiYWRhcHRlbXkiOnsiaWQiOiJGekFqQlBoWG5ydFQ0MEtENXhwdFg1K2ZlNDkzbXlpMmYxMTVDN0taTlV3RW5tSG5kNUxYZ2NUUFFrcVZTeEdDIiwidmVyc2lvbiI6IjFlZDZkOTM4LTM1NmEtNDU3MC1iMjZlLTU2NDg0NjcwNjhjYiJ9LCJnb29nbGUiOnsiaWQiOiJKcjQyVXZ3T1ZjbGZwNkdnbGE4bnpCRFNObk5GVFZ5eEdTdEhNR0ZwdkhoVUtNL1B5MVlZNjgvcW96OUhVdlpYIiwidmVyc2lvbiI6IjdjZDQ0MDJjLWViZjQtNDE5OC05MjliLWEyOWQ1ZmUwZTQxNiJ9LCJzdHVkaW9zX296b25lIjp7ImlkIjoiN3pWQkJWeE5HbEpqWUowbTFxcWFtWFpJMW5rYXFuK09XNExoNDkrOFpKeklQUlJGZU9ZWUNqeGl1SjJ4ZkF4SyIsInZlcnNpb24iOiI0OTNhNWI3Zi1jNjI1LTQ2ODctOTRmMi1lNWE1ZGIwOGM4OTkifSwicGVybXV0YXRpdmUiOnsiaWQiOiJUcitvU1B6RTVRNVh4ZVlQakFtdzNXaDNnMjlWbkRieHZScVJpdDZMbWM3UllGNHpGaWtEL1A1enNDSEFBZHl3IiwidmVyc2lvbiI6ImRkYjQ1ZGE3LWExNDQtNGUxNC04YjBlLTUwYjkyOTVjNzBmOSJ9fSwiZXYiOmZhbHNlLCJwbCI6ZmFsc2UsInBzIjoiaW1tUzFDRnpKMXg5VlRMQUx5aFJBeFpxSnkzZ3NPN1JSQm5MWGprX0JUMCIsImNsIjpmYWxzZSwiY2MiOiJnYiIsInJlYWxtIjoiLyIsInNlcy1leHAiOjE3NTY2OTAxMDkwMDAsImp3dC1leHAiOjE4MTk3NjEyMDkwMDAsInRrbi1leHAiOjE3NTY2OTU4MDgwMDAsInJ0a24tZXhwIjoxODE5NzYxMjA5MDAwfQ +.bbc.co.uk TRUE / TRUE 1790903615 ckns_policy_exp 1788225215721 +.bbc.co.uk TRUE / TRUE 1788225216 ckns_iplayer_experiments {} +.bbc.co.uk TRUE / TRUE 1788311620 ckns_explicit 1 +.bbc.com TRUE / TRUE 1788225190 ckns_mvt dc2f56e0-df7d-4cce-9e4b-dcf788e66fe4 +.bbc.com TRUE / TRUE 1788311620 ckns_policy 000 +.bbc.com TRUE / TRUE 1788311620 ckns_explicit 1 +.account.bbc.com TRUE / TRUE 1791249208 ckns_jwt eyJ0eXAiOiJKV1QiLCJjdHkiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.ZXlKMGVYQWlPaUpLVjFRaUxDSnJhV1FpT2lKTk1VcDFVMHhGVlRkb2IwaG9NMVUwVlN0MmFHSnNiR1ZyU1VrOUlpd2laVzVqSWpvaVFURXlPRU5DUXkxSVV6STFOaUlzSW1Gc1p5STZJbEpUUVRGZk5TSjkuRjZFTDBMZFBiRkJwb245WmxUaXd0ZmI5aXFFOVFLaTdsQ2JRSWt0NzZBa2FqeXNjVzFsYUl1TGtmcmN1VHFicWJMWldTVHJPX0t3VTFaZ2JFOXgxaEtLRjQ5ZllKZ1BidXdoZ0Fha1lZWUlpSllnXy12M3ZwQXdmOTVwUFRnclkzeVItNFZJTGJldW1pS3Zvcy04blRpc3VPdzZydTBlVm5XemhscjVaTHdacDI0SXhHdUhOV3pkNEp0T1F2WUhuWDBxR2JsMUNDUElFTzFMX1FMZFhSOHRDMW9BQzJjd0FHYy1CY1lfOElfcGNqaHBmZGFGRklJaUprempaZ1Jad3pzZzhUOEVNSVgxYktJdlo3blZ1eDR0WWNTMnlfUU9NeU95aE1yUnMwQ2w1VG50S1A1cWFlUUdBY25SMmJwd19OUl9VTElMczFxQklDcTdGMjN0ZVhnLjJWOUVQdHFxcDByQjdQNGdkeXFVc0Euc0s3eXByMld5ZWJkNER2WEtaZkNWaVZudXROQTRHeXpZcjVKZXlwNExkWkkzVE9fWUNJN01LbXNjcVZtaGtqNjB1UVZvaXh1eFlmRURjZU1oOTdKRnhmT2hEM0M5aFZ5NS1mTmxzcmpZUjVqRFc2a3ZUWFlZbWd2ZjZPQVBsMFhJRUM3SEc3R2U5ckxBX3Z3REJKZ3FId1EzUWVxZ3ZqaWctTUJMQjNCNTM1Nlo1SDR5djBBVVVpRHY1MU8xLWNYT2dBLTF0QWpIaEhfWDhDM1dtY3VzS2dkSDZ0WHVxVV9hdWZ3MkVFQ3FwTmFSa0pGMnU4clNRTTlkczFNdW1PVzhGRmZHanljZjZ5bU1kZ1A0bU44SGR3SmdvQnpGU0NhckJNb0VZV2xsWjJZSnZuN3pxdl9uZnMwLUVrcnZVR1pZeEU3YnM2OEVtV3dFMnVMR3lxQkhXdlpmaExkOFc1ZGJ6blc5ZEJkMjdDS2paUElnazZDNk1vYWVhZHNiVF8yYUx1RjJFTVZRMGJ3TGpWcXdGQ1dVZ2ZaLWhubEVMWG81ZWlKbXpvS0gta2pGUTR0c3B4X2Q1TmRNSzFXMzRsSEF0SmQ0WmotMlVyclRrNlBTZWhvN0ZxTnJDaGRkR0pJMlRtQVpFY2pGcGNFeENtdW1XUHRrNWNScWJYaThETjBxdmZXb05BRG9DYTA5MWtEVEpBZXI5SVJfRFEzRmlUUVlzRHRybVFmRk5NdkJLbEF3Tk5wa09CamlGT1V4dGgxVXR3TGE5U0NsRWRXMXViV2R4UGFGckZzNHlURFoyTzA4ckdpdVJ6Nk1kUS5QVHZMcGpYU0lJYXRlYi11dS1scnJ3.fjjZwBvJzKI0vgBvZO6blAwtY0YJFjaRs8mio7nmpOE +.session.bbc.co.uk TRUE / TRUE 1791249209 ckns_rtkn eyJ0eXAiOiJKV1QiLCJraWQiOiJFZ1VVKzhOaGFBWUtjNnlsb0NCcm5LUFRjZTg9IiwiYWxnIjoiRVMyNTYifQ.eyJzdWIiOiJiYzE5MzU0Yy04YmM2LTRhODYtODYyOC0yZTg2YjYxNzdmMDciLCJjdHMiOiJPQVVUSDJfU1RBVEVMRVNTX0dSQU5UIiwiYXV0aF9sZXZlbCI6MiwiYXVkaXRUcmFja2luZ0lkIjoiYTcyYWY3NjItZjMyNi00MGJjLWEwOTMtMjg2ZTIwNWYyMmE5LTExMjUxOTU2MSIsImlzcyI6Imh0dHBzOi8vYWNjZXNzLmFwaS5iYmMuY29tL2JiY2lkdjUvb2F1dGgyIiwidG9rZW5OYW1lIjoicmVmcmVzaF90b2tlbiIsImF1dGhNb2R1bGVzIjoiQkJDSURfSkRCQ19FTUFJTCIsInRva2VuX3R5cGUiOiJCZWFyZXIiLCJhdXRoR3JhbnRJZCI6IktuYXJhUVdkQUtJM05LWWNJaE1BRU92QlNRSSIsImF1ZCI6IkFjY291bnQiLCJhY3IiOiIwIiwibmJmIjoxNzU2Njg5MjA5LCJncmFudF90eXBlIjoiYXV0aG9yaXphdGlvbl9jb2RlIiwic2NvcGUiOlsiZXhwbGljaXQiLCJjb3JlIiwiaW1wbGljaXQiLCJwaWkiLCJ1aWQiLCJmaSIsIm9wZW5pZCIsImVkIl0sImF1dGhfdGltZSI6MTc1NjY4OTIwOCwicmVhbG0iOiIvIiwiZXhwIjoxODE5NzYxMjA5LCJpYXQiOjE3NTY2ODkyMDksImV4cGlyZXNfaW4iOjYzMDcyMDAwLCJqdGkiOiJBYm5zYml6aGt1UmRDbl96LVVvLUVRYUM5eDQifQ.eZRT1ndGRwxnsShBMfaE4EBO8k9mCxl2XGvadQcYlYLJZAojTbuOqeX8CXuU0Kr3FZjKmobzis570EwEVMRZmw +www.benchmade.com FALSE / FALSE 1788736114 localization US +www.benchmade.com FALSE / TRUE 1788736103 _shopify_essential :AZkhSEvUAAEA4RpevYPi8TQPeiP9QhKEUeiCqTaYc1dsi3rL20srm56ll2cYCcB6HjNfk9cIGFH0qm5_GPxfVNOjFN2nlK76b6vUQh3RDB3Qsc80ptryk1aj7UyjMo7UUNl869Rb64HXIbeaKeI: +.benchmade.com TRUE / TRUE 1791760011 __eventn_id 05grsl4da0.1757200010 +.benchmade.com TRUE / TRUE 1788736011 ssUserId f6a10f03-956c-496d-a271-dd135d92dca4 +.benchmade.com TRUE / TRUE 1788736011 _isuid f6a10f03-956c-496d-a271-dd135d92dca4 +.benchmade.com TRUE / TRUE 1791760011 ssViewedProducts 4010BK-01 +.benchmade.com TRUE / TRUE 1791760016 __mmapiwsid 01992148-6176-790f-9637-3c682e38cf66:abbb1dd4308adda60f6fd5c6d973e3d10626ab72 +.benchmade.com TRUE / TRUE 1788736021 osano_consentmanager_uuid b29340f4-60f9-4647-8eb1-b32488944e24 +.benchmade.com TRUE / TRUE 1788736021 osano_consentmanager wQMoLX7PZtaJlfz-sjj5K9A9o6kqoGvVi-ZBoD8HiI0yezCa-BNqhG_Vl_ZuQGEyEq3ruGM6-8fmI9Bx5vqNE5gRdx0rDX91eN28lxyyepTJspkSeOMuuUcvLz-tLU_byezjAsVcJm-_2VK9j1tm4mMX0yTRmuO01qYqVar_h9ixOL_aBckoMZWtVeCQZ_4GL3by9HrOBxnBxPcBiOg4awYi_RzpNNtCQaktptOrdK0Sitqh1cXXKWb5M-OU-OCb30yGQcoVz2r0PdEk2O8laKVeeio04id-hbuhK18fv-BlKdTUgUtClp0ft0cD4dnE +.benchmade.com TRUE / FALSE 1788757621 _tracking_consent 3pams._USTN_t_f_3D7Z7*ANTre7GLEfvycF*g_{"consent_id":"b29340f4-60f9-4647-8eb1-b32488944e24","consent_timestamp":"2025-09-06T23:07:00.879Z"} +.yotpo.com TRUE / TRUE 1788736222 pixel 3c1ab4cd-50fa-40c2-42fe-997c086dedae +d-ipv6.mmapiws.com FALSE / TRUE 1791760016 __mmapiwsid 01992148-6176-790f-9637-3c682e38cf66:abbb1dd4308adda60f6fd5c6d973e3d10626ab72 +.7ce243a1e1a2.cdn4.forter.com TRUE / TRUE 1788736016 forterSId 2436eb89683740e5a1e2611cea77050c_1757200015707 +d-ipv4.mmapiws.com FALSE / TRUE 1791760016 __mmapiwsid 01992148-6176-790f-9637-3c682e38cf66:abbb1dd4308adda60f6fd5c6d973e3d10626ab72 +.kys-tech.com TRUE / TRUE 1788978962 __stripe_mid 15f79900-7ee4-4525-84c9-04990e72a685d657ef +kys-tech.com FALSE / FALSE 1788978797 info true +support.ledger.com FALSE / TRUE 1789655123 CookieConsentPolicy 0:1 +support.ledger.com FALSE / TRUE 1789655123 LSKey-c$CookieConsentPolicy 0:1 +.ledger.com TRUE / FALSE 1792679513 _ga GA1.1.677620686.1758119129 +.ledger.com TRUE / FALSE 1792247129 _scid Rq0GQzyhVgelp7ZQXEj4p4eywsSR_5l2 +.ledger.com TRUE / FALSE 1792283129 _cs_c 1 +.ledger.com TRUE / FALSE 1791815180 _tt_enable_cookie 1 +.ledger.com TRUE / FALSE 1791815180 _ttp 01K5C11W3Y5FE9VY2YJHPS51BG_.tt.1 +.ledger.com TRUE / FALSE 1792247130 _sctr 1%7C1758085200000 +.ledger.com TRUE / FALSE 1792283129 _cs_id 04a79f3b-fb89-a1b2-ca66-13a74ef5139b.1758119129.1.1758119180.1758119129.1743519975.1792283129139.1.x +.ledger.com TRUE / FALSE 1791815180 ttcsid 1758119129217::4ILjIjLzkvXvFxQSxUaM.1.1758119180327.0 +.ledger.com TRUE / FALSE 1791815180 ttcsid_CCM80A3C77U9QMO0Q980 1758119129217::DWn4ZxMwXa91S6tK3o9C.1.1758119180716.0 +.ledger.com TRUE / FALSE 1792247512 _scid_r Ui0GQzyhVgelp7ZQXEj4p4eywsSR_5l2FzAF6Q +.ledger.com TRUE / FALSE 1791815512 _uetvid 2929bb5093d211f094dfef3879dafab7 +.ledger.com TRUE / FALSE 1792681770 _ga_Y38HP2KGC3 GS2.1.s1758121743$o2$g1$t1758121769$j34$l0$h0 +.waterbear.com TRUE / FALSE 1790346513 AMP_MKTG_e6b575e207 JTdCJTdE +.waterbear.com TRUE / FALSE 1793370694 ab.storage.deviceId.48d270e0-354a-41c6-ad46-4879e5b4e0ed g%3A97529535-dcfe-5088-5a99-b222d5a6f6a7%7Ce%3Aundefined%7Cc%3A1758810694823%7Cl%3A1758810694837 +.waterbear.com TRUE / FALSE 1793370694 ab.storage.userId.48d270e0-354a-41c6-ad46-4879e5b4e0ed g%3ApWAIJMExR2ZkGPyKaCkIMPA9TJI3%7Ce%3Aundefined%7Cc%3A1758810694837%7Cl%3A1758810694838 +.waterbear.com TRUE / FALSE 1793370716 ab.storage.sessionId.48d270e0-354a-41c6-ad46-4879e5b4e0ed g%3A39d5136d-2c47-c980-7d73-a8d1edcb6b79%7Ce%3A1758812516440%7Cc%3A1758810694837%7Cl%3A1758810716440 +.waterbear.com TRUE / FALSE 1790347120 AMP_e6b575e207 JTdCJTIyZGV2aWNlSWQlMjIlM0ElMjI5NDE0YWNiMS02NGQ4LTRmZGUtYjk4NC0wMzA1NmQyMjRhMzclMjIlMkMlMjJ1c2VySWQlMjIlM0ElMjJwV0FJSk1FeFIyWmtHUHlLYUNrSU1QQTlUSkkzJTIyJTJDJTIyc2Vzc2lvbklkJTIyJTNBMTc1ODgxMDUxMzg3OSUyQyUyMm9wdE91dCUyMiUzQWZhbHNlJTJDJTIybGFzdEV2ZW50VGltZSUyMiUzQTE3NTg4MTExMjA2NzYlMkMlMjJsYXN0RXZlbnRJZCUyMiUzQTQ0JTJDJTIycGFnZUNvdW50ZXIlMjIlM0EzJTdE +.getalby.com TRUE / TRUE 1777649101 cc_cookie {"categories":["necessary","analytics"],"level":["necessary","analytics"],"revision":0,"data":null,"rfc_cookie":false,"consent_date":"2025-07-01T18:52:45.856Z","consent_uuid":"4a542391-0497-4fe9-832d-98ec5c2be76f","last_consent_update":"2025-10-31T15:25:01.672Z"} +.getalby.com TRUE / TRUE 1802374856 ph_phc_W6d0RRrgfXiYX0pcFBdQHp4mC8HWgUdKQpDZkJYEAiD_posthog %7B%22%24device_id%22%3A%220197c755-9c24-7cdf-b425-62896d0125c1%22%2C%22distinct_id%22%3A%22nnISDNGBJUIqDV3NGap8%22%2C%22%24sesid%22%3A%5B1770838856866%2C%22019c4e0a-dbc9-7160-a65c-001c2749059e%22%2C1770835860407%5D%2C%22%24epp%22%3Atrue%2C%22%24initial_person_info%22%3A%7B%22r%22%3A%22https%3A%2F%2Fgetalby.com%2Foauth%2Fsessions%2Fnew%3Fclient_id%3DNYvmxLuaWE%26code_challenge%3D2z1VRRvKkLENMiKqy5814MVCv9g6X9UFSIMQXTxFs40%26code_challenge_method%3DS256%26redirect_uri%3Dhttps%253A%252F%252Fgetalby.com%252Fextension%252Fconnect%26scope%3Daccount%253Aread%2Bbalance%253Aread%2Binvoices%253Acreate%2Binvoices%253Aread%2Bpayments%253Asend%2Btransactions%253Aread%22%2C%22u%22%3A%22https%3A%2F%2Fgetalby.com%2Fextension%2Fconnect%3Fcode%3DZTE1MDLLMMMTOTQ5ZC0ZODQ5LWI4OGITZTHJMZJLNJDLNGEY%22%7D%7D +.getalby.com TRUE / TRUE 1802371855 cf_clearance HTj7XPrpro_FDlj9EzpTHpJczEspX9S7r9hz9DeMX7w-1770835855-1.2.1.1-DYGWiCTlTQ8QYXzW3_yjuVTzkgs6FWjMM2zaiFFFTA9T_6D8UrAEO1aLmmwWhnoHI4aeKD9GA8KTJgSpoTI3IuHAO_1slPX1BJhKT0cMw7NumWND7WkQj7oFSE6.PuGCuiWRiuT7m2Rq6eqbu3Wu6k0WgfLItvqVoS0CYl1lM8oV0EzHHO6kggSipw5Wbau5rQvUUMzWoQBFgbhll2Lx14jtSmb0H4OznJ9_Wepuyrk +.github.com TRUE / TRUE 1795617904 _octo GH1.1.659434916.1764081903 +.github.com TRUE / TRUE 1795617904 logged_in no +.apliiq.com TRUE / FALSE 1799190046 _ga GA1.1.225605822.1764615090 +.apliiq.com TRUE / FALSE 1799190046 ccid.86838876 347223090.3087116993 +.apliiq.com TRUE / TRUE 1799190046 apliiq-_zldp hpL8Ey9L33r%2FpBmy3ES%2BLnEa9z5a3Ru0sqYqVOmGsifDZb6QH3ZBTrS1TGiJ%2FcX2T3IUrdIYs4k%3D +.apliiq.com TRUE / FALSE 1799190453 _ga_ZL932S8CL9 GS2.1.s1764623129$o4$g1$t1764630453$j59$l0$h0 +.thrivecap.com TRUE / FALSE 1805844086 _ga GA1.1.1359966912.1764617644 +.thrivecap.com TRUE / FALSE 1805844086 _ga_CC3XJMND3M GS2.1.s1771284086$o2$g0$t1771284086$j60$l0$h0 +www.apliiq.com FALSE / FALSE 1799190046 __kla_id eyJjaWQiOiJZMlptTWpFNE4ySXRORFl4T1MwME5Ea3pMVGs1TjJNdE1XTTJPVFU0TmpsaE5EWmwiLCIkZXhjaGFuZ2VfaWQiOiJaYU9CMEwta1FPZjM1M0kxZEpPSVBNM3dzRjZjZVNTbFl2VTQ5aW8tV18wLkxHdkNFWCJ9 +checkout.apliiq.com FALSE / FALSE 1799189298 __kla_id eyJjaWQiOiJNRFprT1RReVpETXROekppTlMwMFpHTmhMVGcxTW1VdE5tWXpZMlZrWlRRd05EaGoiLCIkZXhjaGFuZ2VfaWQiOiJaYU9CMEwta1FPZjM1M0kxZEpPSVBNM3dzRjZjZVNTbFl2VTQ5aW8tV18wLkxHdkNFWCJ9 +.checkout.apliiq.com TRUE / TRUE 1799189183 apliiq-_zldp hpL8Ey9L33r%2FpBmy3ES%2BLnEa9z5a3Ru0sqYqVOmGsifDZb6QH3ZBTrS1TGiJ%2FcX2T3IUrdIYs4k%3D +.gfore.com TRUE / FALSE 1796108616 visid_incap_2081288 fR3D7pzZRNClUUXvZ0djUlMPLmkAAAAAQUIPAAAAAAAR7nhfh+ALBI09CWSIi1xz +.gfore.com TRUE / FALSE 1780394277 _conv_v vi%3A1*sc%3A1*cs%3A1764626267*fs%3A1764626267*pv%3A1*exp%3A%7B100493634.%7Bv.1004224736-g.%7B%7D%7D%7D +.gfore.com TRUE / FALSE 1780178277 _conv_r s%3Awww.google.com*m%3Aorganic*t%3A*c%3A +.gfore.com TRUE / TRUE 1796162268 BVBRANDID 2713ee0a-f16b-4724-ae7f-64dd6f7d9358 +.gfore.com TRUE / FALSE 1796162268 crl8.fpcuid 9ef62d87-b733-4303-9d76-cc57c9954c3a +.gfore.com TRUE / FALSE 1798581468 TCPID 12512115574812185174123 +.gfore.com TRUE / FALSE 1798322268 TC_PRIVACY_CPRA 0%40005%7C1%7C6985%401%2C2%403%2C4%401764626268380%40 +.gfore.com TRUE / FALSE 1798322268 TC_PRIVACY_CPRA_CENTER 1%2C2 +.gfore.com TRUE / FALSE 1798754268 __cq_uuid abc0mIAQzkjEcz7G7jKiIAQmA6 +.gfore.com TRUE / FALSE 1799186269 _ga_XXXXXXX1 GS2.1.s1764626268$o1$g0$t1764626268$j60$l0$h0 +.gfore.com TRUE / FALSE 1799186269 _ga GA1.1.2041936879.1764626268 +.gfore.com TRUE / FALSE 1799186269 _blkp_xps %7B%22HJSHP%22%3A13%7D +.gfore.com TRUE / FALSE 1799186269 tatari-session-cookie 4d93019f-1130-10d7-88d7-ba789134d1f2 +.gfore.com TRUE / TRUE 1798322269 __attentive_id f80a08145ae84bb4a15e3522ddf6ec89 +.gfore.com TRUE / TRUE 1798322269 _attn_ eyJ1Ijoie1wiY29cIjoxNzY0NjI2MjY5MTAxLFwidW9cIjoxNzY0NjI2MjY5MTAxLFwibWFcIjoyMTkwMCxcImluXCI6ZmFsc2UsXCJ2YWxcIjpcImY4MGEwODE0NWFlODRiYjRhMTVlMzUyMmRkZjZlYzg5XCJ9In0= +.gfore.com TRUE / TRUE 1798322269 __attentive_cco 1764626269102 +.gfore.com TRUE / FALSE 1798790269 _cs_c 0 +.gfore.com TRUE / FALSE 1798790269 _cs_id 67f94baa-0c07-aa0a-8730-2b163746ee77.1764626269.1.1764626269.1764626269.1732464474.1798790269114.1.x +.gfore.com TRUE / FALSE 1798322269 _uetvid c6d49190cf0011f0aeea9b5244ce38a2 +.gfore.com TRUE / FALSE 1799186269 forterToken e336e2a1c101466cab21e3b0cd875de2_1764626267339__UDF43-m4_15ck_ +.gfore.com TRUE / FALSE 1796162270 _ju_dc c76c9bf6-cf00-11f0-b023-2f66809d83c9 +.gfore.com TRUE / FALSE 1799186271 _lc2_fpi 8dce54196be4--01kbdyr369gqe5hbzn8fmg8sjx +.gfore.com TRUE / FALSE 1799186272 _li_ss CgA +.gfore.com TRUE / FALSE 1799186586 _ga_B0REW2WZF3 GS2.1.s1764626268$o1$g1$t1764626585$j60$l0$h411637605 +www.gfore.com FALSE / TRUE 1780178266 dwanonymous_9075bc7ed73102844fcce4f0052fc396 abc0mIAQzkjEcz7G7jKiIAQmA6 +www.gfore.com FALSE / FALSE 1799186269 __kla_id eyJjaWQiOiJNRGRsWm1JNFpUVXRObUkzWmkwME9HUmhMV0ppT1dNdFl6RTVORGc0WXpReE5EaGoifQ== +www.gfore.com FALSE / FALSE 1799186269 tatari-cookie-test 7751488 +www.gfore.com FALSE / FALSE 1796162271 mmuid 8bc762a20cf84eb3 +.cquotient.com TRUE / TRUE 1798754268 uuid abc0mIAQzkjEcz7G7jKiIAQmA6 +.pippio.com TRUE / TRUE 1796162270 did 2lV2IoCTOVt2NS-_ +.pippio.com TRUE / TRUE 1796162270 didts 1764626270 +.stats.paypal.com TRUE / FALSE 1799189168 c 98d9b886327596d2998e +www.paypal.com FALSE / FALSE 1796165182 _dd_s aid=5e3e2398-f9b0-450b-b96d-81e19d3ab6eb&rum=1&id=9519a9a5-c971-467f-9f02-e159e9c6b04c&created=1764628902830&expire=1764630082507 +.zaprite.com TRUE / FALSE 1799190233 _ga GA1.1.1488010542.1764630150 +.zaprite.com TRUE / FALSE 1799190191 _ga_XFZVJST60H GS2.1.s1764630150$o1$g1$t1764630190$j20$l0$h0 +.zaprite.com TRUE / FALSE 1799190233 _ga_DKN4TFVCXF GS2.1.s1764630191$o1$g1$t1764630233$j18$l0$h0 +.zaprite.com TRUE / FALSE 1787960234 intercom-id-vvv6kprm 53fb38b9-0790-4323-ad0d-bf81666b8e17 +.zaprite.com TRUE / FALSE 1787960234 intercom-device-id-vvv6kprm 28349a77-ec40-4fa5-8b4d-40552ffac9bb +.zaprite.com TRUE / FALSE 1799190340 _ga_7GLS7Z6F3N GS2.1.s1764630233$o1$g1$t1764630339$j60$l0$h0 +skims.com FALSE / TRUE 1797188683 _skid 65794e07-1d7d-4046-82d7-97b491f2207a +skims.com FALSE / TRUE 1797188683 _visitingStatus visited +skims.com FALSE / TRUE 1797620763 __rtbh.lid %7B%22eventType%22%3A%22lid%22%2C%22id%22%3A%22YlhgkQKyMucYj6OgV707%22%2C%22expiryDate%22%3A%222026-12-18T19%3A06%3A03.356Z%22%7D +skims.com FALSE / FALSE 1800644764 __kla_id eyJjaWQiOiJNbVF4WW1JeFpXRXRORGcxTkMwME9ESmhMV0ppTkRFdFpERmhaamRrWldRNE56Z3kifQ== +skims.com FALSE / TRUE 1797620837 __rtbh.uid %7B%22eventType%22%3A%22uid%22%2C%22id%22%3A%2265794e07-1d7d-4046-82d7-97b491f2207a%22%2C%22expiryDate%22%3A%222026-12-18T19%3A07%3A17.905Z%22%7D +.skims.com TRUE / FALSE 1800644684 GLBE_SESS_ID %7B%22sid%22%3A%22467132306.141432646.1155%22%2C%22expiry%22%3A%222025-12-18T19%3A34%3A43.788Z%22%7D +.skims.com TRUE / FALSE 1797620762 _pin_unauth dWlkPVptSTNNak5tWkRrdE1tUXpNQzAwWmpRMExUbGpOV1l0Tm1Zd1lXTTJOVGhqTW1ObQ +.skims.com TRUE / FALSE 1799780762 _tt_enable_cookie 1 +.skims.com TRUE / FALSE 1799780762 _ttp 01KCSDKA6XDMKRKZPT7DCE4AP2_.tt.1 +.skims.com TRUE / FALSE 1797188837 _shopify_y 32d9af33-1480-4758-D61F-71903CC651A6 +.skims.com TRUE / FALSE 1800644763 _ga GA1.1.504031878.1766084685 +.skims.com TRUE / FALSE 1800644685 _lc2_fpi 21287e9a14d4--01kcsdkavhydvmffvv0jxfzemq +.skims.com TRUE / TRUE 1799780764 __attentive_id 47bbcb9b962e4edca1e9cbef53e28d00 +.skims.com TRUE / TRUE 1799780763 _attn_ eyJ1Ijoie1wiY29cIjoxNzY2MDg0Njg0Njc3LFwidW9cIjoxNzY2MDg0Njg0Njc3LFwibWFcIjoyMTkwMCxcImluXCI6ZmFsc2UsXCJ2YWxcIjpcIjQ3YmJjYjliOTYyZTRlZGNhMWU5Y2JlZjUzZTI4ZDAwXCJ9In0= +.skims.com TRUE / TRUE 1799780684 __attentive_cco 1766084684678 +.skims.com TRUE / TRUE 1797620684 __ps_r _ +.skims.com TRUE / TRUE 1797620684 __ps_lu https://skims.com/collections/nikeskims?direction=next&cursor=eyJsYXN0X3ZhbHVlIjoiNDciLCJsYXN0X2lkIjoxMDI0Njg2MDI0MzI5Nywib2Zmc2V0Ijo0N30%3D +.skims.com TRUE / TRUE 1797620684 __ps_did pscrb_226743b1-9d44-4bb8-f968-04a31e8f8041 +.skims.com TRUE / TRUE 1797620684 __ps_fva 1766084684717 +.skims.com TRUE / TRUE 1800644685 IR_PI 6a48fb22-dc44-11f0-870a-6584898419f4%7C1766084684614 +.skims.com TRUE / FALSE 1797620684 _axwrt 8c9ab40d-c69d-4ee6-9183-e996d8a1c7b8 +.skims.com TRUE / FALSE 1800299084 _scid JRoE-ZvIBUJLSPCc1lIQKUMvwHza3_Nj +.skims.com TRUE / FALSE 1799953485 __qca P1-9906de41-ac66-4d3d-9d15-0f1f3e39e286 +.skims.com TRUE / TRUE 1797620766 QuantumMetricUserID 98414e535c76313591f9ee355cff76c4 +.skims.com TRUE / FALSE 1800299085 _sctr 1%7C1766037600000 +.skims.com TRUE / FALSE 1800644838 __ta_device ubGuBKNdUrjeaI0JaQhs4JFAcl4tQMLC +.skims.com TRUE / TRUE 1797620760 _dy_soct 1766084760!1159934.-77'1159935.0'1272376.0'2016990.0!adg54ijwhx2tu6ef4um4hp3eo8uhne4p~1159939.-77'1324063.-77'1327720.0 +.skims.com TRUE / FALSE 1797620760 OptanonConsent isGpcEnabled=0&datestamp=Thu+Dec+18+2025+13%3A06%3A00+GMT-0600+(Central+Standard+Time)&version=202306.1.0&browserGpcFlag=0&isIABGlobal=false&hosts=&consentId=afbd17d7-6dcd-40fa-98d8-cdc9ff46f400&interactionCount=1&landingPath=NotLandingPage&groups=BG34%3A1%2CC0001%3A1%2CC0002%3A1%2CC0003%3A1%2CC0004%3A1&geolocation=US%3BTN&AwaitingReconsent=false +.skims.com TRUE / FALSE 1797620760 OptanonAlertBoxClosed 2025-12-18T19:06:00.956Z +.skims.com TRUE / FALSE 1797620761 _tracking_consent 3AMPS._USTN_f_t_0zEbzYtoSAGJag49cJEAlg +.skims.com TRUE / FALSE 1800299163 _scid_r PpoE-ZvIBUJLSPCc1lIQKUMvwHza3_NjkUotaA +.skims.com TRUE / FALSE 1799780763 _uetvid 6a477db0dc4411f0b033537fd8e9476f +.skims.com TRUE / FALSE 1800248763 cto_bundle lxezUl9Ya05KT0lxalRzMlpmQTZ1WnNGcGVTa2FaVEtiTWIlMkJKY29ZSDRVM0Z1VGlwU3pqMWpLRm9OdUs5MWZLJTJCd1ZxbiUyQnByYVJXWE16QlhOS0FlVSUyRkI3aUwlMkY0a1pQTjN3ZkJaSDR6TjZGTlNWWEl6NnRVbmFzeWc2aHhQeVREcUVNYmZRM2tiT0pwayUyQjAlMkJNUCUyQkYwUFBDMSUyRnNQbmglMkZUUElseHdZbTZ6NVFzenF1bHNJckVuTGtLNyUyRmgwbzFwclEzb3Y0 +.skims.com TRUE / FALSE 1800644765 forterToken 0dc56201e2d447c483dafc18afc4d80f_1766084760076__UDF43-m4_23ck_ +.skims.com TRUE / TRUE 1797620837 _Elevar-apex [1%2C%2265794e07-1d7d-4046-82d7-97b491f2207a%22%2C%221766084684%22%2C%221%22%2C%221766084837%22%2C{}%2C[]%2C%22{%5C%22_ttp%5C%22:%5C%2201KCSDKA6XDMKRKZPT7DCE4AP2_.tt.1%5C%22%2C%5C%22_fbp%5C%22:%5C%22fb.1.1766084684456.3724806368%5C%22%2C%5C%22_uetsid%5C%22:%5C%226a4786e0dc4411f0be072b25ff65504f%5C%22%2C%5C%22_uetvid%5C%22:%5C%226a477db0dc4411f0b033537fd8e9476f%5C%22%2C%5C%22_ga%5C%22:%5C%22GA1.1.504031878.1766084685%5C%22%2C%5C%22_scid%5C%22:%5C%22JRoE-ZvIBUJLSPCc1lIQKUMvwHza3_Nj%5C%22%2C%5C%22_ga_FB40M4FWKG%5C%22:%5C%22GS2.1.s1766084684$o1$g1$t0$j60$l0$h0%5C%22}%22%2C0] +.skims.com TRUE / TRUE 1800644838 _sp_id.5e0d cffe6173-3fe8-42c0-ba5a-5752434cd290.1766084685.1.1766084838..343b2361-d02d-43ff-aef6-a93963ca8f87..69e731b2-03d7-4e90-be5a-612485fa927c.1766084684861.18 +.skims.com TRUE / FALSE 1799780852 ttcsid 1766084683999::SeCLjuB76f1lL4FbZ7aD.1.1766084852083.0 +.skims.com TRUE / FALSE 1799780852 ttcsid_C0VSMI3M56Q7UP188TTG 1766084683999::x8lq-MdBmPA7eS2m0G8k.1.1766084852083.1 +.skims.com TRUE / FALSE 1797620858 ax_visitor %7B%22firstVisitTs%22%3A1766084684723%2C%22lastVisitTs%22%3Anull%2C%22currentVisitStartTs%22%3A1766084684723%2C%22ts%22%3A1766084858302%2C%22visitCount%22%3A1%7D +.skims.com TRUE / FALSE 1800644858 _ga_FB40M4FWKG GS2.1.s1766084684$o1$g1$t1766084858$j13$l0$h0 +.wsktbf.net TRUE / TRUE 1797620685 brwsr 6a48fb22-dc44-11f0-870a-6584898419f4 +skims.wsktbf.net FALSE / TRUE 1781636685 irld L0DYwUSVnS1txSuPWHEVUBzXyUHPUSrSv2T1XXKQ1CYx9uScp +.applovin.com TRUE / TRUE 1797620764 axcrt AL.1.749430528.1766084684889.3 +.snapchat.com TRUE / TRUE 1799780686 sc_at v2|H4sIAAAAAAAAAE3GwRGAMAgEwIqY4RAPsJuYkCpSvF/3tT13LqKENi7xek1GISQStYC2nvvA9UGQms68z6/6AQMbeYBAAAAA +.360yield.com TRUE / TRUE 1775862466 tuuid 7fafe40b-12f1-414e-b944-2666315f73d5 +.360yield.com TRUE / TRUE 1775862466 tuuid_lu 1768086465 +.360yield.com TRUE / TRUE 1775862471 umeh !38,0,1828292838,-1!313,0,1830294470,-1 +.360yield.com TRUE / TRUE 1775862471 um !38,BMXavnbDSbrtd4.oP9GgaGHhGMIsdH1-0lojSjX0SUYXrIy507xIiBaWovN6Gzrz7PILKsTxjEyEIbK8RGgFG9lKZIw,1773860838!313,VFhMj4Rogp5bPH3bortlS155AbhA1mgZO86CZ1CUUsJ0Xfzu4KyqVsRHFR4jb-gbyldYYBTzwDrUjjgSqyqqA468msGKMkHPsMMcw4etS9OxrT1l,1775862470 +.3lift.com TRUE / TRUE 1775862514 tluid 1095917909795168967170 +.3lift.com TRUE / TRUE 1775862514 receive-cookie-deprecation 1 +.3lift.com TRUE / TRUE 1775862479 tluidp 1095917909795168967170 +.toast.com TRUE / TRUE 1781636741 BID RSSB37CZ5JRWID3174XWCDKWI +.toast.com TRUE / TRUE 1781636741 txpub_1570163526 d2OEmVpH39gWAzy-La7n8Vs1CcRnjHNo9i5CbT-KnV8_:_EXP_:_1781636740_:_EXP_:_1766084740 +.toast.com TRUE / TRUE 1781636741 txsync 1766084740 +.nhnace.com TRUE / TRUE 1781636742 BID RSSB37CZ5JRWID3174XWCDKWI +.nhnace.com TRUE / TRUE 1781636742 txpub_1570163526 d2OEmVpH39gWAzy-La7n8Vs1CcRnjHNo9i5CbT-KnV8_:_EXP_:_1781636741_:_EXP_:_1766084741 +.nhnace.com TRUE / TRUE 1781636742 txsync 1766084741 +.bidence.net TRUE / TRUE 1781669204 177_dsp_uid d2OEmVpH39gWAzy-La7n8Vs1CcRnjHNo9i5CbT-KnV8 +.bidence.net TRUE / TRUE 1781669204 duid_update_time 1766084803 +.bidence.net TRUE / TRUE 1781669204 114_ssp_update_time 1766084803 +.fwmrm.net TRUE / TRUE 1783638470 _uid umwbe31_7585846274144387383 +.ct.pinterest.com TRUE / TRUE 1797620838 _pinterest_ct_ua TWc9PSZWOW5BTVRpai94Y2ZzVm1seFNIOTROcXhJRlg1VUlYbUh2bDdERE8yWGhKVVJQSTFuOGt4YXhQTS9iamdSakp4SDJtbzhudlNnamZvdE01YVRxa2Q2VTkxdnlOb0J5YUZ5RGJqMEVZbVNqOD0mUEI4L2tkbFJySmhRKzhQb01FbU5JTVd1cUNvPQ== +.vour.io TRUE / TRUE 1797620838 624_jwt eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhaWQiOiI5ZGYzMTczNC00ZGU5LTQxZmEtOTE4Ny0xMzRkNzM1YTU2NmUiLCJpYXQiOjE3NjYwODQ4Mzh9.MbIIoNSNCU_wsXuJOi4ja0I7YU83U5d3bu7IF4_ejKBJHxyMfxg6Hrly89pXFYMvHidqEGIzm9flveSs-Gsgqazc4-3XCP0iT7IkmRcr0iujb3gv_PxYIoBcO7r3UPxniRSAB3cxakZaPArmSWXWWmPj2xpGb7beTPjC6abp827UG0ezAMruCrRJCYpaFBR_OMj9T3QIzV6syrVwbW1kshiZikQU8o2lEUt32tOv99cmPsMqfxuXpDgVUzp9ZMlSXSaor5_o8-M61B_MFXptlEtAb4BvX_DM8GJ77QJQl7Cghv0EdZMhAsPTpL7rk7MFfvuwckLXjmaTuADhIHow1g +.bestbuy.com TRUE / FALSE 1797709170 vt 6f690ae0-dd12-11f0-ad0a-0ee7b207dce3 +.bestbuy.com TRUE / FALSE 1776541172 pst2 170|N +.bestbuy.com TRUE / TRUE 1799869172 __gads ID=429e68df663c9775:T=1766173172:RT=1766173172:S=ALNI_MZxhbQ31SYi0pxCdtetDZIMIskvdg +.bestbuy.com TRUE / TRUE 1799869172 __gpi UID=0000131de02f3466:T=1766173172:RT=1766173172:S=ALNI_MbY9XCpzTvLqqUz0Rh78RjXf_ofgQ +.bestbuy.com TRUE / TRUE 1781725172 __eoi ID=ca0d26dfc81cc6e4:T=1766173172:RT=1766173172:S=AA-AfjZtPe0_KiUjvlJ2NBiOFOBD +.bestbuy.com TRUE / TRUE 1797709172 connectId {"connectId":"h41BbgQlSIHyJId5O-APjmQCXBg7b6ibxGpJLV7EEg81n8_XB96ECUyAVHwglTQesGfGtFseQZoaAKJHFHAVUw","puid":"05d8092bdb6760329fb8a13189c0cec789c100d61d0b4412e73274ed53edd6fc","ttl":86400000,"lastUsed":1766173172442,"lastSynced":1766173172442} +.bestbuy.com TRUE / FALSE 1800733182 s_ecid MCMID%7C58080136048519668114536865538030263176 +.bestbuy.com TRUE / FALSE 1800733182 AMCV_F6301253512D2BDB0A490D45%40AdobeOrg 1585540135%7CMCMID%7C58080136048519668114536865538030263176%7CMCAAMLH-1766777971%7C7%7CMCAAMB-1766777971%7CRKhpRz8krg2tLO6pguXWp5olkAcUniQYPHaMWWgdJ3xzPWQmdj0y%7CMCOPTOUT-1766180382s%7CNONE%7CMCAID%7CNONE%7CvVersion%7C4.4.0 +.bestbuy.com TRUE / FALSE 1800337186 _cs_c 1 +.bestbuy.com TRUE / TRUE 1797709196 _abck 98CE9281062EB29755F518F4E2632889~0~YAAQEX0vF7RqhzabAQAA9z4gOA8ujjyFR4zYs1rTxYLHEURlVdJ4OtbhDy2zsBP4b4YveBwzZEbAo/jJGNgPComzkF8zGClPAFi44WsKxhS0LcWx6mvKZwMZtasW5nI+Z4FLt7A89ko3d2NfGaS4fasItIDYUP54kWyyLcB+cwDYnTmI+1Qwr/vWiC880Y/fhiAI4vgA6Fqn9xNfnZFz4Ivj7G3UImaIw+Q2oS0OIPIoPWr8LVxBYVf0nJ/SOUj76gPaJNDc7Rf78NsjZSwr8lYK/aQV6nV2iRDQjUjasDmLCnbTGrfAQdfRE+crv41URBptfgxqnlbloME7Vkuf4W/ylVjgBGytkzzx0wu0jiHAcV3cPpjXBLnN2kAcHYSn4UoXJPgeXYz4ycnbntI9HQ6k5Mw9hrIAVXTt7vFN5ZyrGYwLOAWXAktezAqRct+YLUZV2FS3HxhFlmL2MGvsXJ3GNz9geF1JXYeilGM8Tay1FYQ2wfwI6oc+a9nDbH9DjnKE7HqLr3XJ5kxMU47KiXjJu+hyX1TedaZLMg5Aot3zFf/nvz9QwF71Z268ZX9FlTJmm2tAYC0zFlU8Dz70IacyvsiFcpHSsGwrt+16yk/hNkZyamYM6c1SyxOoju+lNvUTuAyuW4uyLvUQ5WQWE5C93ccebJnn~-1~-1~1766176771~AAQAAAAE%2f%2f%2f%2f%2f8oOA3tv34D2V7ONQZtmPYLejQtQVkGWs%2fvwofeeythQgyIiBizjnFUkvIb9LGyVvOYCw3xNHy+m86G3W50LV006WFXInvjS6rNE~-1 +.bestbuy.com TRUE / FALSE 1800337196 cto_bundle xqwVuV94ejhqbTA4bHB4b0JiNVVxcFclMkZPRUdwWUhuUTFUbGx6ZE9UWXZmVTczaDNSNSUyQkJ0TW90T3glMkJQODgycmpFR3hTN0REZWVJSUV0OHRxNUJxNXp4RW5xclNOdGQ2cXlMQTk1NlpVSFhybGFHYU1nbFNVYUx5MUdlUWZUcjA0bmZmbm1jbFZNOXFPaXE3NkxMQndoZiUyQjd6S2w0S1dBNTQyNEtjMEJxdGhFZTZybTl5VWZiUjAySndURDFjME1SYTh2VQ +.bestbuy.com TRUE / FALSE 1797709214 isGridViewEnabled true +.bestbuy.com TRUE / FALSE 1799869219 __gsas ID=78bad4b99391fe9a:T=1766173219:RT=1766173219:S=ALNI_MZ7PtsAhyKgA-RaJ1wnpzOGAacHDQ +.bestbuy.com TRUE / FALSE 1800337186 _cs_id 178c060b-ebba-a692-ebdd-0fc62bd54d08.1766173186.1.1766173232.1766173186.1645469968.1800337186882.1 +.bestbuy.com TRUE / FALSE 1797709247 locDestZip 37024 +.thingiverse.com TRUE / TRUE 1801782464 __gads ID=c274a2d1d73e5390:T=1768086464:RT=1768086464:S=ALNI_Mb0CVH9vFv-SqEXC4e1YO_sN8flTw +.thingiverse.com TRUE / TRUE 1801782464 __gpi UID=00001324f4cc2db5:T=1768086464:RT=1768086464:S=ALNI_MaewbhT_k00lySbZa5mbAYBf7rQdw +.thingiverse.com TRUE / TRUE 1783638464 __eoi ID=6378ed39ac9fb0ea:T=1768086464:RT=1768086464:S=AA-Afja98XhAT6jufaqPVnOucN-S +.thingiverse.com TRUE / FALSE 1791414465 _cc_id 3cf9e41188988b992aee1510314411e1 +.thingiverse.com TRUE / FALSE 1801760863 cto_bundle abRd819vSkMzOGd0M2dGSk5FSnpOd25ydFd4dDhpNEMlMkJXQjVBNjF6bXVpaURpYTBJbEFvWEU1V3NWUjhOMiUyRnZoZ1ZxY0QwJTJCc1ZBRTV4Vk1ZMkFERmslMkZXSnhSTVAzQXlmMUxwWEp0S3JYRmtjc1U2NnR0M1Q5RlB4N2VZN0VrNTk5YzB2Nm9TWld4RWNJRE9kNGFJaHN6eFlheDk1Ynd0QXdsN0xWckxYMDhMamRKSlRIS1hHM2pxMkhLcUJic0ZIUHFNYg +.thingiverse.com TRUE / FALSE 1801760863 cto_bidid mnWdDV9nbG84Y0Z1Zm1lRU9vMEVnJTJGdWQyODhXQjM0WTZlRSUyRkRaOUI2dFdKZWVac1hDcnJmZiUyRjA5NzNDcTFXUEdXekFiMXRwTm9IYmJiZDJ6ZHJvUnNjJTJCUWE0VldzdFhtc041MlBCdU5mWjNNYVZXUm0lMkZiWTFReXFWeTJhektHUCUyQm16UmhMJTJGQ29ZeTVTR1g0ZSUyRnh0dldib0x3JTNEJTNE +.thingiverse.com TRUE / TRUE 1799622465 cf_clearance hwUXmBceIFvRDfbB2BtWlQCpzcjHbmiSqo5cz6aGdEc-1768086465-1.2.1.1-VX.Q4T4aESaY6xi9IRJfTIQDfpvdaoxXMckW7vY8vmQkx7u4vX3Bdu5s_u0xmy89GTnveSCQ0SJlfHk7pQu3UaXVaPtbCRViQF9Oyu4u64vlE1o1XegeKxhhNX95YA7bSOfsRrr1UrxF1_8QTgKwoEDJhXOchZj2r_3TfpfHGgz02di9c5oXG_3SqG93ctZEyEEHU4SucDaTIPUEElZ1pZ81RwmbGGX2uHkTFWremag +.ipredictive.com TRUE / TRUE 1799622470 cu 066d8e19-5c26-450d-a649-863f2909f959|1768086465860 +.csync.loopme.me TRUE / TRUE 1775862478 viewer_token 2ca038bf-483c-4eaa-b684-a7905f94dc41 +.33across.com TRUE / TRUE 1799622479 33x_ps u%3D212328208636113%3As1%3D1698785496328%3Ats%3D1768086466187 +.opera.com TRUE / TRUE 1799622478 OAU OPUb598e447ff4b444484a3e5b793c7de50 +.xplosion.de TRUE / TRUE 1799622467 pid BSRCEif3WD_CWDa0WSRAEibkWSRsWD_8WiRkWi_ABifABfrr +.xplosion.de TRUE / TRUE 1799622467 pid_short 52I3odHeaUJ3xI5D_DbFH5_8__rr +.xplosion.de TRUE / TRUE 1799622467 pid_signature wSulwSjDBSU0wDjdwSBsWDU-wCHbWDwZWq7kBStIEiujwqUAEiU0Hfrr +.xplosion.de TRUE / TRUE 1799622467 ep aWLbwkDbaJugE4bcG2i- +.trustedstack.com TRUE / TRUE 1802387267 visitor-id 4110880664639125000V10 +.adfarm1.adition.com TRUE / TRUE 1775862469 UserID1 7593873548017072489 +.bttrack.com TRUE / TRUE 1775862468 GLOBALID 2uKlc8-sIBd984cSkD72DtzNhbXQZOzWrDrHRMWhaK7Tgu7vGY-DLeTd831jGxj6xBOn4fvgsrMC4Q2 +.simpli.fi TRUE / TRUE 1799708868 suid F807DADE2E214302BF3C6F3D58A4CEC8 +sync.srv.stackadapt.com FALSE / TRUE 1799622468 sa-user-id s%3A0-4629e297-6daa-5181-62e1-392785235d6f.PXNulmzJegZOvvWPXXg3lwleRwh%2F0%2B5MSVe1ySIMGEM +sync.srv.stackadapt.com FALSE / TRUE 1799622468 sa-user-id-v2 s%3ARinil22qUYFi4TknhSNdb2vCVQw.ezE7srbmqWgoMYYglaxkS%2BF8s6cNlNz0M9lOXWpG0ek +sync.srv.stackadapt.com FALSE / TRUE 1799622468 sa-user-id-v3 s%3AAQAKIOnhejbOhrV9-RM6AiFzDEwt3Ih8NIHekYWJsIGp7nzbEAMYAyDEt4vLBjABOgQTDjy1QgR2YepB.2F4w74GAZt5vjDhOMoMUFticPP20T51xHtlrhiwpK%2Bo +.srv.stackadapt.com TRUE / TRUE 1799622468 sa-user-id s%3A0-4629e297-6daa-5181-62e1-392785235d6f.PXNulmzJegZOvvWPXXg3lwleRwh%2F0%2B5MSVe1ySIMGEM +.srv.stackadapt.com TRUE / TRUE 1799622468 sa-user-id-v2 s%3ARinil22qUYFi4TknhSNdb2vCVQw.ezE7srbmqWgoMYYglaxkS%2BF8s6cNlNz0M9lOXWpG0ek +.srv.stackadapt.com TRUE / TRUE 1799622468 sa-user-id-v3 s%3AAQAKIOnhejbOhrV9-RM6AiFzDEwt3Ih8NIHekYWJsIGp7nzbEAMYAyDEt4vLBjABOgQTDjy1QgR2YepB.2F4w74GAZt5vjDhOMoMUFticPP20T51xHtlrhiwpK%2Bo +www.thingiverse.com FALSE / TRUE 1799622468 CookieConsent {stamp:%27dcCI10BHlJQetn3alh3J9z8IPiGNGQgScRgD0Fmt+ZeQiYr0g1z1WQ==%27%2Cnecessary:true%2Cpreferences:false%2Cstatistics:false%2Cmarketing:false%2Cmethod:%27explicit%27%2Cver:3%2Cutc:1768086468362%2Cregion:%27us-47%27} +.presage.io TRUE / TRUE 1783897669 presage-ssp %7B%22uuid%22%3A%2239a603b9-8fc8-42ed-b4f9-05588b5ca524%22%7D +.use3-sync.a-mo.net TRUE / TRUE 1799622469 sd_amuid2 6694de3f-a4e4-4153-be90-38070f322c76 +.use3-sync.a-mo.net TRUE / TRUE 1799622469 psd_amuid2 6694de3f-a4e4-4153-be90-38070f322c76 +.dxtech.ai TRUE / TRUE 1783638469 mtuid 2f39f687-b1fe-4539-85b6-f60b92005b47 +.media6degrees.com TRUE / TRUE 1783638469 clid 2smn2ow011718bshr4m678srm15k500i0a010201101 +.media6degrees.com TRUE / TRUE 1783638469 sglst 453a3mcu03o9yj21fo95q21f1liw0q607mu018dl30q6 +.media6degrees.com TRUE / TRUE 1783638469 rdrlst 5515401j084uk20q64ujk0q64uim0q64sz80q64hkx0q649pl0q62dc00q629zg0q6 +.media6degrees.com TRUE / TRUE 1783638469 acs 015020i0j0k0o1smn2owxzt1m15k5xzt1m15k5xzt1m15k5xzt1m15k5 +.resetdigital.co TRUE / TRUE 1775862469 ckbk 000011CF9CE959F2 +.advolve.io TRUE / TRUE 1799622469 x 6962dbc575e323aa0d79326e +.driftpixel.live TRUE / TRUE 1799622469 xedpxl 12261041.8bc2613b-cb1c-4e2c-9de0-564b760c7596 +cookies.nextmillmedia.com FALSE / TRUE 1799622478 NMUID c268b853-3d21-4300-bbd4-17f459389def +.quantserve.com TRUE / TRUE 1775862470 sp CgkI6KsGEgMQghEKCQiCrQMSAxCCEQoICNllEgMQghEKCQjRpgISAxCCEQoICIkNEgMQmREKCAieDRIDEIIRCgcICxIDEIIRCggIknESAxCZEQoJCLmKAxIDEJkRCgkIhf8CEgMQghE= +.pmbmonetize.live TRUE / TRUE 1799622470 xeadiu 12090783.fd98a23a-b3d0-487c-8fc9-8f1b434f671e +.rbstsystems.live TRUE / TRUE 1799622475 xeroid 11690718.a267af1d-fded-4805-82f1-a40eb66eb5a4 +.nextmillmedia.com TRUE / TRUE 1799536070 adkernel eyJVSUQiOiJBNjc4MTQ0ODEzNTM2NDc0NjgxMCIsIkV4cGlyZXMiOiIyMDI3LTAxLTA5VDIzOjA3OjQ5Ljk5MzczMjk0WiJ9 +.nextmillmedia.com TRUE / TRUE 1799536070 rubicon eyJVSUQiOiJNNkNGNFRHOC1XLUo3MFMiLCJFeHBpcmVzIjoiMjAyNy0wMS0wOVQyMzowNzo1MC40MDk1MjQ5NDVaIn0= +.nextmillmedia.com TRUE / TRUE 1799536075 adnxs eyJVSUQiOiIxNDQ2NjY0NjMzMDYyNDU1NzM4IiwiRXhwaXJlcyI6IjIwMjctMDEtMDlUMjM6MDc6NTUuMzMwNDU3NVoifQ== +.nextmillmedia.com TRUE / TRUE 1799536075 openx eyJVSUQiOiJkNjk4MWFlNy00ZWE1LTQ5NjUtODVjNi0zNDUzYTdjMDE0NTYiLCJFeHBpcmVzIjoiMjAyNy0wMS0wOVQyMzowNzo1NS4zNDAxNjk2OTVaIn0= +.nextmillmedia.com TRUE / TRUE 1799536075 pubmatic eyJVSUQiOiI3RUE1NURBRC01RUQxLTQyREQtQUZGNy05NkIwMTg3RTJGRTgiLCJFeHBpcmVzIjoiMjAyNy0wMS0wOVQyMzowNzo1NS4zNDYxNjA1MzlaIn0= +.nextmillmedia.com TRUE / TRUE 1799536075 yieldmo eyJVSUQiOiIzZUhQdkhIYm1QSHhTdE1vSVhPUiIsIkV4cGlyZXMiOiIyMDI3LTAxLTA5VDIzOjA3OjU1LjM1NzU5ODM1NloifQ== +.nextmillmedia.com TRUE / TRUE 1799536075 sovrn eyJVSUQiOiJIbEhDVVJaSG1uR1lfaHR3UnkycWRTN1giLCJFeHBpcmVzIjoiMjAyNy0wMS0wOVQyMzowNzo1NS4zODQyMDE3MDlaIn0= +.nextmillmedia.com TRUE / TRUE 1799536075 verve1 eyJVSUQiOiJiYzY3MTE5MTY4IiwiRXhwaXJlcyI6IjIwMjctMDEtMDlUMjM6MDc6NTUuNDgzMDc1Mzk2WiJ9 +.nextmillmedia.com TRUE / TRUE 1799536075 medianet eyJVSUQiOiIzODA3NTAzNzc5Nzg2ODU1MDAwVjEwIiwiRXhwaXJlcyI6IjIwMjctMDEtMDlUMjM6MDc6NTUuNDg0Mzk4OTI1WiJ9 +.nextmillmedia.com TRUE / TRUE 1799536075 robustApps eyJVSUQiOiJkNi42ODBiMWE3ZjE1OWE0YzQ4OTIxZjM1NmI2NDJmNDdhOSIsIkV4cGlyZXMiOiIyMDI3LTAxLTA5VDIzOjA3OjU1LjU0MDYzNzYzM1oifQ== +.nextmillmedia.com TRUE / TRUE 1799536076 zeta_global_ssp eyJVSUQiOiIxcnA2bHYyNjI3ZGIzIiwiRXhwaXJlcyI6IjIwMjctMDEtMDlUMjM6MDc6NTUuNjgwMTEwODIzWiJ9 +.nextmillmedia.com TRUE / TRUE 1799536076 unruly eyJVSUQiOiJSWC1mNjA3OTNiMS0wZWVmLTRjYTQtODJjNS1lZThhM2I1Y2RhYjktMDA1IiwiRXhwaXJlcyI6IjIwMjctMDEtMDlUMjM6MDc6NTUuODk3ODc3NjE4WiJ9 +.nextmillmedia.com TRUE / TRUE 1799536077 vidazoo eyJVSUQiOiIwNWYwNTVmNS0zY2E5LTUzNjctZjZkYS00ZWI3YTk5MTMzYzciLCJFeHBpcmVzIjoiMjAyNy0wMS0wOVQyMzowNzo1Ni42MTk3MzI3MzdaIn0= +.nextmillmedia.com TRUE / TRUE 1799536077 seedtag eyJVSUQiOiIwMTk3ZTgwOS0xZDI4LTc2ZmUtYmQyZS0yYTgzNjdhOWIxOTEiLCJFeHBpcmVzIjoiMjAyNy0wMS0wOVQyMzowNzo1Ni42MzA3NDc3MDZaIn0= +.nextmillmedia.com TRUE / TRUE 1799536077 insticator eyJVSUQiOiJjNjJkZDY0Ny0yNzNiLTQ0OTQtYmE2OS1kN2Y3NjAwNTI0YzQiLCJFeHBpcmVzIjoiMjAyNy0wMS0wOVQyMzowNzo1Ni42ODk4OTI2MjRaIn0= +.nextmillmedia.com TRUE / TRUE 1799536077 minutemedia eyJVSUQiOiIzOXJSX0FhY0NwX21tIiwiRXhwaXJlcyI6IjIwMjctMDEtMDlUMjM6MDc6NTYuNzg4MTA4OTIxWiJ9 +.nextmillmedia.com TRUE / TRUE 1799536077 rise eyJVSUQiOiJxN1lMVkFhY0NwX3MiLCJFeHBpcmVzIjoiMjAyNy0wMS0wOVQyMzowNzo1Ni43ODgzOTc3NzFaIn0= +.nextmillmedia.com TRUE / TRUE 1799536077 33across eyJVSUQiOiIyMTIzMjgyMDg2MzYxMTMiLCJFeHBpcmVzIjoiMjAyNy0wMS0wOVQyMzowNzo1Ni45MTkyNjk2NjdaIn0= +.nextmillmedia.com TRUE / TRUE 1799536078 madopi eyJVSUQiOiJBNjc4MTQ0ODEzNTM2NDc0NjgxMCIsIkV4cGlyZXMiOiIyMDI3LTAxLTA5VDIzOjA3OjU3Ljk2NjAyMTY2MloifQ== +.ingage.tech TRUE / TRUE 1775862476 instUid c62dd647-273b-4494-ba69-d7f7600524c4 +.ingage.tech TRUE / TRUE 1799622477 cf_clearance NCjJzyjOSrpPr8FbdKFfAf0KK4lm9mMYq9jvHHH0MR8-1768086477-1.2.1.1-mmrYg1gmneJqjVHHw9suApOL5Fp1OZNa_Www1ZEGXAncFrx3aCK6kyxZYt1wp1EWTPHaqANS5AZyQo1DXpBjc3fhm0NsRuAid0KJpU488XSwzWu1llU1Ggcb44as6HwlO.Img6iuRCK8kuU4i0G29GL0DeK3b0JrJdH26Q5oa1_wKK6IoBpZRKyoeE_kBAwsa4dnmkOWC7iAFyTiTQR2WJ2DICH4QBY3a4rvFj4PqpY +usync.ingage.tech FALSE / TRUE 1775862470 instUid c62dd647-273b-4494-ba69-d7f7600524c4 +.admatic.de TRUE / TRUE 1802646470 uid a6d006be-43ed-4d42-8378-04d11dbce1bb +.admatic.de TRUE / TRUE 1775862476 uids eyJ0ZW1wVUlEcyI6eyJwdWJtYXRpYyI6eyJleHBpcmVzIjoiMjAyNi0wMi0wOVQyMzowNzo1MC41NzNaIiwidWlkIjoiN0VBNTVEQUQtNUVEMS00MkRELUFGRjctOTZCMDE4N0UyRkU4In0sImFkZm9ybSI6eyJleHBpcmVzIjoiMjAyNi0wMi0wOVQyMzowNzo1MC41ODBaIiwidWlkIjoiMzg0NTk1MDc0ODA5NDc5ODMwMCJ9LCJibXRtIjp7ImV4cGlyZXMiOiIyMDI2LTAyLTA5VDIzOjA3OjUwLjU4OVoiLCJ1aWQiOiI3YjNhMGQ1Ni05Njg3LTRiNTktYjk1OS1iN2JjODJiNjhkMmEifSwibWVtYnJhbmEiOnsiZXhwaXJlcyI6IjIwMjYtMDItMDlUMjM6MDc6NTYuNzQ5WiIsInVpZCI6IjViMTk3ZDM2LWU4MjUtNGJmNi04ZTNiLWU5ZDc4NzI3OGQ5YiJ9fX0= +pool.liftdsp.com FALSE / TRUE 1799622470 tuuid 0f4e815b-c839-410d-a8b9-575d7cbe1645 +pool.liftdsp.com FALSE / TRUE 1799622470 c 1768086470 +pool.liftdsp.com FALSE / TRUE 1799622470 tuuid_lu 1768086470 +.ib.mookie1.com TRUE / TRUE 1799622470 ibkukiuno s=89d7a4bb-c402-4bc2-a3fb-d3d8d85f8a74&h=&c=0&l=-8584335204150487532&op=&hl=0&clu=0&tcs=5&dcc=-8584638581107438250 +.id5-sync.com TRUE / TRUE 1775862470 id5 b93ab64a-793a-7025-9261-742e7bb32ab5#1766084685808#6 +.id5-sync.com TRUE / TRUE 1775862472 3pi 2#1768086471140#-1461159667|264#1768086467127#-156260550#248c815d-b156-4db9-8a92-46c25764dd54|203#1768086469599#-1560233741#6f78483e-d4c5-431a-8711-a497d0431bf7|108#1768086466841#-206138872|429#1768086472009#-1443568634#7EA55DAD-5ED1-42DD-AFF7-96B0187E2FE8|846#1768086468514#-492225994|369#1768086470445#-912217451|434#1768086470823#878225581|821#1768086471855#1728330091|441#1768086471401#1885834214#u_03cf1816-47b2-4472-8e12-9f751667d0a4|122#1768086470085#-1735519148|1242#1768086472318#-1301550593|155#1768086472167#2740117#AADBck7KgtEAABjN509uAw|796#1768086468798#-255155510|124#1768086470620#1433885824|1245#1768086470976#-1301550593 +.tribalfusion.com TRUE / TRUE 1775862472 ANON_ID aenv7yu4YUdmqcn62NoCUTPUQYIVjZapqCBi8xWYWMildQOVZcnA0qvpwhTxqqnCNZauofeoJwyZcKFRZaMIjyOkWGZas8T9INjnEbgyPV3dRPJuISMl49Zdvea +.emxdgt.com TRUE / TRUE 1775862470 uid 47441768086470553925a6 +aorta.clickagy.com FALSE / TRUE 1802646470 chs [{"ch":"4","t":"2026-01-10 23:07:50"},{"ch":"185","t":"2025-01-24 19:59:38"},{"ch":"120","t":"2024-02-22 15:35:14"},{"ch":"8","t":"2025-07-08 03:16:33"},{"ch":"5","t":"2025-01-24 20:05:11"},{"ch":"114","t":"2025-07-08 03:16:33"},{"ch":"128","t":"2025-01-24 20:21:49"},{"ch":"124","t":"2025-01-24 20:21:49"},{"ch":"130","t":"2025-01-24 20:05:31"},{"ch":"150","t":"2025-07-08 03:16:33"}] +.mxptint.net TRUE / TRUE 1802646471 mxpim R35CA5_10B6EE5CA_9A1777C8.1.6793F432000000006962DBC46793F20F000000006962DBC60000000000000000000000006793F51B000000006793F3FD +.1rx.io TRUE / TRUE 1799622475 _rxuuid %7B%22rx_uuid%22%3A%22RX-f60793b1-0eef-4ca4-82c5-ee8a3b5cdab9-005%22%2C%22lastinit%22%3A%7B%222069.82%22%3A1737749787463%2C%222069.24%22%3A1737749787463%2C%222069.44%22%3A1737749787463%2C%222069.103%22%3A1737749787463%2C%222069.5%22%3A1737749787463%2C%222069.29%22%3A1737749787463%2C%222069.47%22%3A1737749787463%2C%222069.105%22%3A1737749787463%2C%222069.85%22%3A1737749787463%2C%222069.108%22%3A1737749787463%2C%222069.27%22%3A1737749787463%2C%222069.89%22%3A1737749787463%2C%222069.64%22%3A1737749787463%2C%222069.111%22%3A1737749787463%2C%222069.71%22%3A1737749787463%2C%222069.97%22%3A1737749787463%2C%222069.39%22%3A1737749787463%2C%222069.26%22%3A1737749787463%2C%222069.65%22%3A1737749787463%2C%222069.96%22%3A1737749787463%2C%222069.101%22%3A1737749787463%2C%222069.116%22%3A1737749787463%2C%222069.83%22%3A1737749787463%2C%222069.38%22%3A1737749787463%2C%222069.1%22%3A1737749787463%2C%222069.32%22%3A1737749787463%2C%222069.86%22%3A1737749787463%2C%222069.95%22%3A1737749787463%2C%222069.56%22%3A1737749787463%2C%222069.50%22%3A1737749787463%2C%222069.79%22%3A1737749787463%2C%222069.25%22%3A1737749787463%2C%222069.48%22%3A1737749787463%2C%222069.60%22%3A1737749787463%2C%222069.41%22%3A1737749787463%2C%222069.58%22%3A1737749787463%2C%222069.106%22%3A1737749787463%2C%222069.73%22%3A1737749787463%2C%222069.78%22%3A1737749787463%2C%222069.55%22%3A1737749787463%2C%222069.98%22%3A1737749787463%2C%222069.36%22%3A1737749787463%2C%222069.54%22%3A1737749787463%2C%222069.90%22%3A1737749787463%2C%222069.112%22%3A1737749787463%2C%222069.74%22%3A1737749787463%2C%222069.49%22%3A1737749787463%2C%222069.43%22%3A1737749787463%2C%222069.10%22%3A1737749787463%2C%222069.104%22%3A1737749787463%2C%222069.102%22%3A1737749787463%2C%222069.61%22%3A1737749787463%2C%222069.113%22%3A1737749787463%2C%222069.87%22%3A1737749787463%2C%222069.66%22%3A1737749787463%2C%222069.80%22%3A1737749787463%2C%222069.46%22%3A1737749787463%2C%222069.6%22%3A1737749787463%2C%222069.31%22%3A1737749787463%2C%222069.59%22%3A1737749787463%2C%222069.109%22%3A1737749787463%2C%222069.114%22%3A1737749787463%2C%222069.115%22%3A1737749787463%2C%222069.72%22%3A1737749787463%2C%222069.63%22%3A1737749787463%2C%222069.91%22%3A1737749787463%2C%222069.42%22%3A1737749787463%2C%222069.35%22%3A1737749787463%2C%222069.110%22%3A1737749787463%2C%222069.34%22%3A1737749787463%2C%222069.57%22%3A1737749787463%2C%222069.88%22%3A1737749787463%2C%222069.28%22%3A1737749787463%2C%222069.92%22%3A1737749787463%7D%2C%22lastsyncall%22%3A1737749787463%7D +.admixer.net TRUE / TRUE 1775862476 am-uid 0f98d334640144d587d3b02ce049917a +.adtelligent.com TRUE / TRUE 1776121677 vmuid 83a3bef4fbbf98a8 +server.smartytech.io FALSE / TRUE 1799622477 uid 3178aeee-de98-4209-9cd5-4a93fc663b44 +.rlcdn.com TRUE / TRUE 1799622478 rlas3 e/vV39S5p8q+XmmJZtjqYThcGcHi7BVfVwyFmwHekVdZZsLG1/Iz4RUpjoH9aGnHLho0Dk8C2wraaHJYoyT7csQFaIEszxKbBusappoLnpWJwynr2TGyGHQiET1cZU4aVRk0gAef9x0l3cL68Ah80sfJhjGRHbtBQemD/FHkryqMyA9jEACu5w== +.ow.pubmatic.com TRUE / TRUE 1775862477 uids eyJ0ZW1wVUlEcyI6eyJhbXgiOnsidWlkIjoiNjY5NGRlM2YtYTRlNC00MTUzLWJlOTAtMzgwNzBmMzIyYzc2IiwiZXhwaXJlcyI6IjIwMjYtMDEtMjRUMjM6MDc6NTcuMzM1NTgwNjkzWiJ9fX0= +.tynt.com TRUE / TRUE 1775862477 pids %5B%7B%22p%22%3A%22797f54a72d%22%2C%22f%22%3A1%2C%22ts%22%3A1768086466511%7D%2C%7B%22p%22%3A%22f46c881bee%22%2C%22f%22%3A1%2C%22ts%22%3A1768086469697%7D%2C%7B%22p%22%3A%224bee518595%22%2C%22f%22%3A1%2C%22ts%22%3A1768086468893%7D%2C%7B%22p%22%3A%226f27415d53%22%2C%22f%22%3A1%2C%22ts%22%3A1768086468893%7D%2C%7B%22p%22%3A%227daaa56bb0%22%2C%22f%22%3A1%2C%22ts%22%3A1768086468893%7D%2C%7B%22p%22%3A%227912d88d74%22%2C%22f%22%3A1%2C%22ts%22%3A1768086468893%7D%2C%7B%22p%22%3A%22d9fe068602%22%2C%22f%22%3A1%2C%22ts%22%3A1768086469809%7D%2C%7B%22p%22%3A%22f5b8438f72%22%2C%22f%22%3A1%2C%22ts%22%3A1768086468893%7D%2C%7B%22p%22%3A%22fcb82aaae3%22%2C%22f%22%3A1%2C%22ts%22%3A1768086469809%7D%2C%7B%22p%22%3A%22607295b4a4%22%2C%22f%22%3A2%2C%22ts%22%3A1768086474638%7D%2C%7B%22p%22%3A%223bfd58deb3%22%2C%22f%22%3A1%2C%22ts%22%3A1768086469697%7D%2C%7B%22p%22%3A%22baebe6454b%22%2C%22f%22%3A1%2C%22ts%22%3A1768086469697%7D%2C%7B%22p%22%3A%220f90caf3cf%22%2C%22f%22%3A1%2C%22ts%22%3A1768086469697%7D%2C%7B%22p%22%3A%22162dbd77b3%22%2C%22f%22%3A1%2C%22ts%22%3A1768086466511%7D%2C%7B%22p%22%3A%226db3fb8a85%22%2C%22f%22%3A1%2C%22ts%22%3A1768086469697%7D%2C%7B%22p%22%3A%22b32ef6f991%22%2C%22f%22%3A23%2C%22ts%22%3A1768086477380%7D%2C%7B%22p%22%3A%22002f98d420%22%2C%22f%22%3A1%2C%22ts%22%3A1768086469809%7D%2C%7B%22p%22%3A%2224c05c7b76%22%2C%22f%22%3A1%2C%22ts%22%3A1768086466511%7D%2C%7B%22p%22%3A%22cf4d6e49b5%22%2C%22f%22%3A1%2C%22ts%22%3A1768086466511%7D%2C%7B%22p%22%3A%2222833ea406%22%2C%22f%22%3A1%2C%22ts%22%3A1768086468893%7D%2C%7B%22p%22%3A%225cb91279ed%22%2C%22f%22%3A1%2C%22ts%22%3A1768086469697%7D%2C%7B%22p%22%3A%22f9a4a8fd15%22%2C%22f%22%3A1%2C%22ts%22%3A1768086466511%7D%2C%7B%22p%22%3A%22008c314e8f%22%2C%22f%22%3A1%2C%22ts%22%3A1768086466511%7D%2C%7B%22p%22%3A%22729ff3013e%22%2C%22f%22%3A1%2C%22ts%22%3A1768086469809%7D%5D +.exelator.com TRUE / TRUE 1778454480 EE "cc59f09a65a8447a5cf59d53c2ba71ef" +.exelator.com TRUE / TRUE 1778454480 ud "eJxrXxzq6XKLQSE52dQyzcAy0cw00cLExDzRNDnN1DLF1DjZKCnR3DA1bXFZatGCpaXFqSlJh5ZU5JTkNK0uiw91jHdz9PX0iVzmnFGUn5u6AiwU5hq02NDEeEl%252BUWb6otDgxUUpaQyLSopPBZ%252B9KgoAxksq1g%253D%253D" +.exelator.com TRUE / TRUE 1778454480 hsk_7144 "gAAAAAQAAABqKLUv%252FSBqUQMAiKRidWlkuWYzcmRoYm1xdHptYmdmYzg2NnEwNjg0a2mjaHNrpDY5NDmoZGVsaXZlcnmkNjk0OaN2ZXIBpWJuYW1lqFMyMDRVMjJWpXRzZWdzpzI4NTU5ODKlYmNvZGXNG%252BiidHPKU83VFQ%253D%253D" +.e-planning.net TRUE / TRUE 1802646477 E ALz5R0Mx61BTzRqq +pbs-publift-us.ay.delivery FALSE / TRUE 1775862477 uids eyJ0ZW1wVUlEcyI6eyIzM2Fjcm9zcyI6eyJ1aWQiOiIyMTIzMjgyMDg2MzYxMTMiLCJleHBpcmVzIjoiMjAyNi0wMS0yNFQyMzowNzo0Ni42Nzk0Mzc1MjZaIn0sImFkbnhzIjp7InVpZCI6IjE0NDY2NjQ2MzMwNjI0NTU3MzgiLCJleHBpcmVzIjoiMjAyNi0wMS0yNFQyMzowNzo1MC42MjIxNDgwNjZaIn0sImFteCI6eyJ1aWQiOiI2Njk0ZGUzZi1hNGU0LTQxNTMtYmU5MC0zODA3MGYzMjJjNzYiLCJleHBpcmVzIjoiMjAyNi0wMS0yNFQyMzowNzo1My42Mjg5OTY4OVoifSwia3VlZXpydGIiOnsidWlkIjoiNjZlODI5MjEtMjViOS1kZGM4LWM2MjYtZTU0ZjY3MTA2Mjk5IiwiZXhwaXJlcyI6IjIwMjYtMDEtMjRUMjM6MDc6NTIuNzE1MDkxNDA5WiJ9LCJtZWRpYW5ldCI6eyJ1aWQiOiIzODA3NTAzNzc5Nzg2ODU1MDAwVjEwIiwiZXhwaXJlcyI6IjIwMjYtMDEtMjRUMjM6MDc6NTcuNDExNTg0NzY2WiJ9LCJvcGVueCI6eyJ1aWQiOiJkNjk4MWFlNy00ZWE1LTQ5NjUtODVjNi0zNDUzYTdjMDE0NTYiLCJleHBpcmVzIjoiMjAyNi0wMS0yNFQyMzowNzo1MS42MTUyNzc0NTVaIn0sInB1Ym1hdGljIjp7InVpZCI6IjdFQTU1REFELTVFRDEtNDJERC1BRkY3LTk2QjAxODdFMkZFOCIsImV4cGlyZXMiOiIyMDI2LTAxLTI0VDIzOjA3OjUzLjg1NDE5NTExM1oifSwic2VlZHRhZyI6eyJ1aWQiOiIwMTk3ZTgwOS0xZDI4LTc2ZmUtYmQyZS0yYTgzNjdhOWIxOTEiLCJleHBpcmVzIjoiMjAyNi0wMS0yNFQyMzowNzo0NS41NjkzNTkwMzVaIn0sInZpZGF6b28iOnsidWlkIjoiMDVmMDU1ZjUtM2NhOS01MzY3LWY2ZGEtNGViN2E5OTEzM2M3IiwiZXhwaXJlcyI6IjIwMjYtMDEtMjRUMjM6MDc6NTQuNjM3ODUwNjk3WiJ9fX0= +.brand-display.com TRUE / TRUE 1798600578 _knxq_ 0c3b7d5a-56ff-e9a3-fb4fc63f.1751944578.2.1768086477.1751944662 +.adtarget.biz TRUE / TRUE 1775862477 uids eyJ0ZW1wVUlEcyI6eyJwdWJtYXRpYyI6eyJleHBpcmVzIjoiMjAyNi0wMi0wOVQyMzowNzo1Ny41NDhaIiwidWlkIjoiN0VBNTVEQUQtNUVEMS00MkRELUFGRjctOTZCMDE4N0UyRkU4In0sImFkZm9ybSI6eyJleHBpcmVzIjoiMjAyNi0wMi0wOVQyMzowNzo1Ny41NTRaIiwidWlkIjoiMzg0NTk1MDc0ODA5NDc5ODMwMCJ9LCJibXRtIjp7ImV4cGlyZXMiOiIyMDI2LTAyLTA5VDIzOjA3OjU3LjU4NVoiLCJ1aWQiOiI3YjNhMGQ1Ni05Njg3LTRiNTktYjk1OS1iN2JjODJiNjhkMmEifX19 +.adtarget.biz TRUE / TRUE 1802646478 uid 03f75d14-552e-4ca8-8bfd-041dbccd6bbb +.analytics.yahoo.com TRUE / TRUE 1799622478 IDSYNC "173n~2n5s:175s~2n57:175w~2hsn:1769~2el6:176l~2n5c:18vk~2g2j:18xa~2hsn:18y3~2gwf:18yi~2n57:18yl~2q6r:18yo~2g2j:18z8~2q6r:18z9~2hx1:18za~2hsn:190u~2n57:191q~2gwf:1929~2hx1:193k~2gwf:194o~2gwf:195g~2gce:1967~2hsn:1969~2tnb:196y~2hsn:199z~2nh7:19ab~2t7v:19ac~2n58:19aj~2lpr:19b9~2nf8:19bh~2gwf:19bk~2n5f:19bn~2lpr:19bu~2lpr:19bx~2f7r:19cg~2n58:19cu~2lpr:19cw~2lpr:19cx~2hsn:19e0~2lpr:19e3~2g2j:19e7~2lpr:19ea~2lpr:19ai~2n57:19cl~2tnb:19ba~2n58:17mv~2n58:173h~2n58:19h2~2tnb:19gl~2tnb:19h3~2tnb:19h0~2tnb" +.pro-market.net TRUE / TRUE 1783638478 anProfile "jivjmz9he9gc+1+4=2m3+1f=1+1g=1+1j=57:1+rs=s+rt=26001700477AB01084F88A9E2C958264+s0=(a)+s2=(t7j7y3)+vm=47-87fd5a53-dc6b-4dcd-a287-48e386f3b8f1:67-64651016430244522174023048184620348074" +.pbs.yahoo.com TRUE / TRUE 1783811278 uids eyJ0ZW1wVUlEcyI6eyJ0cmlwbGVsaWZ0Ijp7InVpZCI6IjEwOTU5MTc5MDk3OTUxNjg5NjcxNzAiLCJleHBpcmVzIjoiMjAyNi0wMS0yNFQyMzowNzo1OC4yNzcwMzY3NDJaIn19fQ== +.thrtle.com TRUE / TRUE 1785366478 mc eyJpZCI6IjdmNzFiNjVlLWQ5NjUtNDJjNC1hOWMyLTI3NTdmY2NjNWU2MCIsImwiOjE3NjgwODY0NzgzNTMsInQiOjI2OH0= +.thrtle.com TRUE / TRUE 1785366478 sc eyJpIjoiZDg4NjkzNjAtZDlhZS00ODdkLTg2OGQtMDhjYmM1ZTg4YTMyIiwic2lkIjoic2lkLTM0M2ZjMzcxLWVlNzktMTFmMC1hOWJiLTAyNDIwYWZmMTViOSIsIm1zIjoyLCJwcyI6MTMsImxwIjo1MDQ3LCJzcCI6NTA0NCwicHAiOjEzLCJ0c2UiOjMxLCJsdHNlIjoxNzY4MDg2NDc4MTY4fQ== +.clawi.ai TRUE / TRUE 1801951338 __stripe_mid 90fabc42-c1f3-4d66-9c87-5c4f03ef73f5cf7b18 +getalby.com FALSE / FALSE 1778527919 login_method otp +claude.ai FALSE / TRUE 1797201511 anthropic-device-id 534e1c34-4f23-40c6-8112-a7903ca8884e +claude.ai FALSE / FALSE 1805841472 _fbp fb.1.1771281471505.62904287848319980 +claude.ai FALSE / FALSE 1786833474 g_state {"i_l":0,"i_ll":1771281474848,"i_b":"m99XCDLAoL8P11crnbjIezvOZZdvtUX0Hgfq8LNtsLM","i_e":{"enable_itp_optimization":14}} +.claude.ai TRUE / FALSE 1802817511 ajs_anonymous_id claudeai.v1.bbd65f09-a89f-4ba0-8d3a-765e242e7b59 +.claude.ai TRUE / TRUE 1802817511 CH-prefers-color-scheme light +.claude.ai TRUE / FALSE 1805841473 __ssid 7aeefe83-85be-4b98-b9c0-b4f73844ccb6 +.claude.ai TRUE / TRUE 1802817511 lastActiveOrg 3a9dd5ca-f997-4fac-928b-86c0d8256273 +.claude.ai TRUE / TRUE 1794611513 intercom-device-id-lupk8zyo b53ff69c-4e9f-484c-8824-5fedc4acb6ee +.claude.ai TRUE / FALSE 1802817511 ajs_user_id d578b8e1-704f-49a3-a691-67538a600e48 +.claude.ai TRUE / TRUE 1802817511 cf_clearance Rhus4wvo7dTBFd9IdHj04VerNdQBvsLf4BSmR14P62M-1771281511-1.2.1.1-ApqfCOEl1m3Oi1wan95HTIr95afvB2d_xsRrruPB22RIc5RprR8gAv6Nsr1j.CKzzXLHNCX5UbsVvPnMYeEBQl6UszA8_k3Osf4PV.fXVu.2OYBHufWxS1iSWDBMRVsp_Ela_O._hctK7IGx9oWnoDAHaybY3SIDZx3bk_yjcy0.vURxhX0roinh8l37XhgxYYtxH77yryXASwc.z0ZEWi94Oks0TpNiRDNAQDQzyIg +immense-voyage.local FALSE / FALSE 1807808010 session jt3ax4vz67rvx4hwcccryo2bna +5.161.191.254 FALSE / FALSE 1807828861 session mrnehylzg5pod7utyx7ykyitgy +secure.chase.com FALSE / FALSE 1804898020 ktlvDW7IG5ClOcxYTbmY a +chromewebstore.google.com FALSE / TRUE 1776279448 OTZ 8523057_76_80_104160_76_446820 +ogs.google.com FALSE / TRUE 1776279489 OTZ 8523058_76_80_104160_76_446820 +accounts.google.com FALSE / TRUE 1776285616 OTZ 8523160_76_80_104160_76_446820 +accounts.google.com FALSE / TRUE 1808253661 ACCOUNT_CHOOSER AFx_qI64Fyd3WOgqzqEwirImDYclCyKBdomLnpImNfCbXy-ToyYOZLOQM6BhSmSlh7UFNCDPjszdP-z3uKjvrdOfLvtfp1F6Kg2wUiy8bAxCN7gdW25-ySdXdN2M4W1pBJex8Gf5FSrR +accounts.google.com FALSE / TRUE 1808253661 __Host-GAPS 1:RmYuBFSvtOYIoZSDApEcQTWRxTxxAOhQ7SWZ8-9OvRL405mb07I9hfesu8FtVAqHJcpnT5c1Yg0gdUg3wuOLqIyLqhKkJg:PNT2SoEsKh2Qqkj0 +accounts.google.com FALSE / TRUE 1808253661 SMSV ADHTe-DkkvBH6NujmTV1-jzXXvTKEoeb5sPPlOpFf60Ao3D66REzOEbHCQR1fWFuMkepvsaFR9tW8bz_UbR-t5hVK1ef7KuL3vlIIU9rx8ybr1mBFe0XlwQ +accounts.google.com FALSE / TRUE 1808253661 LSID s.youtube:g.a0007whSQ6uWt7O_xuWCIoHK_EdxOWsKkMphXjhgD52Z_0oaIFM-FJpJ_APy6iex2KGtKZTfMAACgYKAfASARMSFQHGX2MipyYBdH9B1sm4C82pTF10MhoVAUF8yKqMdmN7-ALswzn7C2ZHpz0g0076 +accounts.google.com FALSE / TRUE 1808253661 __Host-1PLSID s.youtube:g.a0007whSQ6uWt7O_xuWCIoHK_EdxOWsKkMphXjhgD52Z_0oaIFM-xChahLJ-oWsMFMsal1AN-gACgYKAeYSARMSFQHGX2Mi6WdZ1kGkd18xVbcWRxA_mxoVAUF8yKoV_PIQM3B0ISl_lr7KTTmu0076 +accounts.google.com FALSE / TRUE 1808253661 __Host-3PLSID s.youtube:g.a0007whSQ6uWt7O_xuWCIoHK_EdxOWsKkMphXjhgD52Z_0oaIFM-U7S3MQ5V_ZeYOlCxJ_8x2wACgYKAf8SARMSFQHGX2Mi6DaJTk2e9IEPdfrMYUlALhoVAUF8yKoUhbRHHVSlePzvMBFRGxc40076 +.youtube.com TRUE / FALSE 1808253662 HSID ASVnILepE6lKhaVKT +.youtube.com TRUE / TRUE 1808253662 SSID AOW01b5NEUFzESSgG +.youtube.com TRUE / FALSE 1808253662 APISID MdMQfFFo_4b0Cw2d/Au_xxzGsUXCUZnFia +.youtube.com TRUE / TRUE 1808253662 SAPISID gAA5ERfoktTnNYkF/A7x17szT_7WqXM9A1 +.youtube.com TRUE / TRUE 1808253662 __Secure-1PAPISID gAA5ERfoktTnNYkF/A7x17szT_7WqXM9A1 +.youtube.com TRUE / TRUE 1808253662 __Secure-3PAPISID gAA5ERfoktTnNYkF/A7x17szT_7WqXM9A1 +.youtube.com TRUE / FALSE 1808253662 SID g.a0007whSQ2FTtN3oaH2z5zAUg7rUNnJXuBC-FtNcmf_q4VZxCH6I5yCVYxA-LmPOHRXLgQktwAACgYKASYSARMSFQHGX2MitoydJ2nBzhSIkt8ceGNDPRoVAUF8yKpvGQGXHR2ixssAhIZ7Tlhg0076 +.youtube.com TRUE / TRUE 1808253662 __Secure-1PSID g.a0007whSQ2FTtN3oaH2z5zAUg7rUNnJXuBC-FtNcmf_q4VZxCH6IIWYz6SgNFiNwCFav4fBlxgACgYKAZgSARMSFQHGX2MiUhFl0FoKqeIalNYwK9r2kRoVAUF8yKquv1J4_ggvLRhNHGom3rco0076 +.youtube.com TRUE / TRUE 1808253662 __Secure-3PSID g.a0007whSQ2FTtN3oaH2z5zAUg7rUNnJXuBC-FtNcmf_q4VZxCH6Ip1KVQpXe0-3wXj_r0kABhgACgYKAVESARMSFQHGX2MiaYklqIL3lhBMrkEcEBXS5RoVAUF8yKpcc98ulcMv04cCcRloUdNL0076 +.youtube.com TRUE / TRUE 1808253662 LOGIN_INFO AFmmF2swRQIgDa8cIvI1fxFdd3GEA2GvmAmbS0amlSptrhn2SsGlEa0CIQCaL131LVEaQj7oJl3R9r7ONED30oCInRpvUDrLrbviyQ:QUQ3MjNmd3gxTkhRRmdRbC1Bb19lVDB2Znh0NzN0S2NmaGF5b0ZiNGlrdGpXOF8teVF1Q1ZzdHVuMmZtMVJNb1N4OVZVX0Y4MTRmbXZDTGdDaVpPRVo5YmJxSHVjT2FHOG01NkhzYmJsbTlSdEFZc0s4bFB5SWk5WlhNTWZzTmNPcEd4a01vY04tcVVuaEVWUjFWcTdveGVURDhldGtYU1Vn +.youtube.com TRUE / FALSE 0 PREF f6=80&f7=4100&hl=en&tz=UTC +.youtube.com TRUE / TRUE 1806760505 __Secure-1PSIDTS sidts-CjQBWhotCRA5YMKYuDyG5wumZa4VFuY3F7Fh2duwXD0UmuF6N7mEL_UYQOvz_1NTpoI1B-f4EAA +.youtube.com TRUE / TRUE 1806760505 __Secure-3PSIDTS sidts-CjQBWhotCRA5YMKYuDyG5wumZa4VFuY3F7Fh2duwXD0UmuF6N7mEL_UYQOvz_1NTpoI1B-f4EAA +.youtube.com TRUE / FALSE 1807301008 SIDCC AKEyXzUUyF0XN5paW4VLY0NtxejSk0M28OtfHP5n4n5pOvmXQZyuMzKtfpKiNzQdoxyuNYzuog +.youtube.com TRUE / TRUE 1807301008 __Secure-1PSIDCC AKEyXzUKO_KXpaA8y_dIx4hE0QqX4gfoqvsJg_JCzh5xMDXVTRzzXQWoHvptSZthdcHfYa15NA +.youtube.com TRUE / TRUE 1807301008 __Secure-3PSIDCC AKEyXzURyWvFIoT3UnuYN9789UBC3QqMjdjMkg4gfrVyPT5SQOJwjtlYGwRzqd0HCuQeYSwdjxY +.youtube.com TRUE / TRUE 1791317008 VISITOR_INFO1_LIVE ENb1E2-qMSc +.youtube.com TRUE / TRUE 1791317008 VISITOR_PRIVACY_METADATA CgJVUxIEGgAgUg%3D%3D +.youtube.com TRUE / TRUE 1791313395 __Secure-ROLLOUT_TOKEN CLav7oDA64mAEBDv_MPOo6WTAxiar9XZuuGTAw%3D%3D +.youtube.com TRUE / TRUE 1780182149 __Secure-YNID 13.YT=uPn267RhS6_DPP8X1r3X0mUsAq8X0L4zeknD1-ypQ02nK4yp2NT8iig-SVdbf_A0GP18-P4CgEglD8GsSkPjJVXW0IPFBWBykHuwczveAI30caCVgCUue4RQg2a9nLaU0s1BA2YJRygITXiXP7DGUp4lUDUhfK8-AEdzSeF_NcrFxnhs1lSzfO-og_isBQuS1O3Mv-kcOPgdkhUGWl4ZbIazInJka_fj45KQYi0IpoyMATQrN21FBdpCB-elz4s0Jk7cSB265FSf9McS8oQf0jIEW3pRbBJ2gTYIv5CDgJBGde-A43F8W2QnG2FLgc8huPihY9duf8fWyL6P9a5YLw +.youtube.com TRUE / TRUE 0 YSC JFh3yO0TPqY +.youtube.com TRUE / TRUE 1791138263 __Secure-BUCKET CLwC +.evenue.net TRUE / FALSE 1805835847 _pxvid d4560d49-26fb-11f1-b9e0-54cb44a244a8 +.evenue.net TRUE / FALSE 1782075847 _gcl_au 1.1.1393764598.1774299847.623268785.1774299856.1774299860 +.evenue.net TRUE / FALSE 1808859865 _ga GA1.1.1833572337.1774299847 +.evenue.net TRUE / FALSE 1808859904 _ga_PXLJRLJD73 GS2.2.s1774299863$o1$g1$t1774299903$j20$l0$h0 +.evenue.net TRUE / FALSE 1808859919 _ga_VKEY0CCQPT GS2.1.s1774299847$o1$g1$t1774299918$j60$l0$h0 +goduke.evenue.net FALSE / TRUE 1805835891 WTPERSIST +.adserver.inflightinternet.com TRUE / TRUE 1806510262 _ab_csid I0uhQm5%2BD3xbp97Js5KciY23Ok%2BiFXpu1ON3j7FZpOeWyNm2FpUYDmDCZnGw9%2F2K +www.aa.com FALSE / TRUE 0 XSRF-TOKEN d26ece12-58b2-44b5-a96d-845c65813ef1 +www.aa.com FALSE / TRUE 0 JSESSIONID 567F2ABD5E672A0A33951C9664299FD8 +www.aa.com FALSE / TRUE 0 aka_state_code VA +www.aa.com FALSE / TRUE 0 aka_cr_code US-VA +www.aa.com FALSE / TRUE 0 sessionLocale en_US +www.aa.com FALSE / TRUE 1777566385 al 0 +www.aa.com FALSE / TRUE 0 akavpau_www_aahomepage 1774974685~id=fc154d22d03c3f02c71c83c7d63a71fd +www.aa.com FALSE / FALSE 0 aka_lc_code ML +www.aa.com FALSE / TRUE 0 KROUTEID c4386c20c7a71c8b98ea571950b9023a|b1f37ed7f54333e7fed5541bf6553ced +www.aa.com FALSE / TRUE 0 akavpau_www_aafullsite 1775224801~id=f1411d92597cd0576b28f85835e74fcd +.www.aa.com TRUE / TRUE 1809534305 UAC 9660f397662842c9a5749fba1d2f34e8 +.aa.com TRUE / FALSE 0 rxVisitor 1774974462693TUVBMAUPSSLQG9LF1C8ENSS7P6ILAHIQ +.aa.com TRUE / FALSE 0 dtSa - +.aa.com TRUE / FALSE 0 dtCookie v_4_srv_16_sn_A6ED5A1920AD6C3AD36860C6EDA12B81_perc_100000_ol_0_mul_1_app-3A8b2a7e44ceb3fcd4_1_rcs-3Acss_0 +.aa.com TRUE / TRUE 1806759886 _abck 67380BEE96080DB117362BC3756BEA8C~-1~YAAQ5z3XF5a6iU2dAQAAKdCWUw/lBEKoHIIuWNYVmSiEDSpN5SyK9zGRg/U8PWg/ZCWVoBmFWJrfI94Yl876rAcDEOa7TXBbFPn93vnqoctznmL8dY8WdEdvJnIkZEGSDR92SLMD5eI4WbkLfGj6/ddv1TUZwKb7scYA7fCMvdE/Siib2YMIljMZgIKRDZA8w9bffKSTVntv8Tkiuq/DArqM+FnRvPKmI1qckwPbAmFc1zF67Nb7OOYkV36UZZmt7dJyKi0v+Zz9w58AWPXnoFLUKGuM34+O6yCs6qSRGxv+XrIe60ZUfmv1ent01YraNiGhC8sE1S4NOtt02nP6QU2sCg8cm/02tX7KX2jG85xqs/AW6u+QUmSgVqKfFTjksp6L0Ii2bBbY/Ru9YdlNeeZutmAQmns5al7+BPrEdCIqL4yimCyCU2y6IFbNYyUYgtz4ibjVqlFjad1HUAR1LInf~-1~-1~-1~-1~-1 +.aa.com TRUE / FALSE 0 dtsrVID 1775147472723 +.aa.com TRUE / FALSE 0 rxvt 1775149281085|1775146868389 +.aa.com TRUE / FALSE 0 dtPC 16$174462690_847h-vFJCRQWUFVIVJAVFKCRWLMPIAARUNADFH-0e0 +.doubleclick.net TRUE / TRUE 1809784503 IDE AHWqTUlisU2hmqPtDHgMSndCiEYb0PgfGDl4xaG6WQuM9aCEwjWFA-s7tqw9EZDh +.doubleclick.net TRUE / TRUE 1783638469 APC AfxxVi6hNvQV29SLhzAFSpJ9ITzn0e3Wg50VHJGNpgewSpGfGZILqQ +.protechts.net TRUE / TRUE 1781649266 _pxvid 0ed20029-4b02-11f0-942d-350be9935237 +.protechts.net TRUE / TRUE 1784385137 _px3 ff2e7f344e23124464181eb32a6547e8885afa2278f627d84c416eaa11765b2a:tEM1lQYPDIr7NIsSjXWJ26RKR1lKMP7Hq3mYq1PoOBjAT5hIQrofQYfUdbwKqECGvlfP42qmFno1iQBvlNuJbQ==:1000:7qGM1VmYIh4dHQ/0zkiQ11NC3Hly4knCGG1cM8RvU+GQcTtlRjayPpoTnJjspPvW0lgpzFNEUMkS2aDaxgVk5kQK+9HLuNcZXsxQtS5nZFLa7IWj7oGoPC4tlzi5XkBhgo8jZY+kvV7+WjKQoe4bzoJl0Si26iMlzeh3OtCpxkqFsOzlZ7i9j0COaEouvXsP8f06JnJwdn/6jfE8CJZbb2Bk0ivQkw61FEKzJAKH/lE= +.criteo.com TRUE / TRUE 1785640562 receive-cookie-deprecation 1 +.criteo.com TRUE / TRUE 1801782514 cto_bundle BW3AuV84ODVyMXZkYTg2T2R5YjRwTVI0Y3lRT1pqTU44RUVoWWcxQ29xczVWYm5wVkhodktxQzJDd0V1eGhtOGxrZ2N1Y0ZSVkdLTVh1WDNVd1ZMTjByNGZDQktQQjVLdkxKVTc1ZE1MbDB6RjB0U1VoZ0Fwc3VSSVlTTHkzWmpFRDVTNmNmVlNEVFBiVk9haTJwQlRDMEsyZEElM0QlM0Q +top-fwz1.mail.ru FALSE / TRUE 1787328588 PVID 24Phk500X52Y0026Kk1Q01oY:::0-0-0-cae53fc-0-dc04c0c:CAASEKxMyii6AT78_-3NUPqD0UIaYHtsqvds-0kSklpezGsuCNzWPVpfXllbLL1vqX4f428ZW2vUxODue-givca9Uz03dLH8ZLOAeFiLjUWT2D7xIKjFSSw1mNF8GXEjOnpIeFEPmwLXqAyKewzaUgOzLS9SFg +prebid.media.net FALSE / TRUE 1783638514 receive-cookie-deprecation 1 +.tracookiepixel.xyz TRUE / TRUE 1799622469 server_tracking_bdsp_uid AADBck7KgtEAABjN509uAw diff --git a/create-app.sh b/create-app.sh new file mode 100755 index 0000000..c9430c3 --- /dev/null +++ b/create-app.sh @@ -0,0 +1,194 @@ +#!/bin/bash +# ───────────────────────────────────────────────────────────── +# Creates "YouTube Summarizer.app" — a proper macOS app bundle +# that you can put in your Dock, Desktop, or Applications folder. +# +# Usage: Run this once from the project folder: +# chmod +x create-app.sh && ./create-app.sh +# ───────────────────────────────────────────────────────────── + +PROJECT_DIR="$(cd "$(dirname "$0")" && pwd)" +APP_NAME="YouTube Summarizer" +APP_PATH="$PROJECT_DIR/$APP_NAME.app" + +echo "" +echo "Creating $APP_NAME.app..." +echo "" + +# ── Build the .app bundle structure ────────────────────────── +rm -rf "$APP_PATH" +mkdir -p "$APP_PATH/Contents/MacOS" +mkdir -p "$APP_PATH/Contents/Resources" + +# ── Create the launcher script ─────────────────────────────── +cat > "$APP_PATH/Contents/MacOS/launcher" << 'LAUNCHER' +#!/bin/bash + +# Resolve the real project directory (the .app lives inside it) +APP_DIR="$(cd "$(dirname "$0")/../../.." && pwd)" + +# If the app has been moved (e.g. to /Applications), check for a saved path +SAVED_PATH="$HOME/.config/youtube-summarizer/project-path" +if [ ! -f "$APP_DIR/server/index.js" ]; then + if [ -f "$SAVED_PATH" ]; then + APP_DIR="$(cat "$SAVED_PATH")" + else + # Ask the user to locate the project folder + APP_DIR=$(osascript -e 'POSIX path of (choose folder with prompt "Locate your YouTube Summarizer project folder:")') + APP_DIR="${APP_DIR%/}" + if [ -z "$APP_DIR" ] || [ ! -f "$APP_DIR/server/index.js" ]; then + osascript -e 'display alert "YouTube Summarizer" message "Could not find the project folder. Make sure server/index.js exists." as critical' + exit 1 + fi + mkdir -p "$(dirname "$SAVED_PATH")" + echo "$APP_DIR" > "$SAVED_PATH" + fi +fi + +cd "$APP_DIR" + +# Add common Homebrew paths (node, yt-dlp) +export PATH="/opt/homebrew/bin:/usr/local/bin:$PATH" + +# Check for Node.js +if ! command -v node &> /dev/null; then + osascript -e 'display alert "YouTube Summarizer" message "Node.js is not installed. Install it with: brew install node" as critical' + exit 1 +fi + +# Check for yt-dlp +if ! command -v yt-dlp &> /dev/null; then + if command -v brew &> /dev/null; then + brew install yt-dlp 2>&1 + else + osascript -e 'display alert "YouTube Summarizer" message "yt-dlp is not installed. Install it with: brew install yt-dlp" as critical' + exit 1 + fi +fi + +# Install npm dependencies if needed +if [ ! -d "server/node_modules" ]; then + cd server && npm install && cd .. +fi + +# Ask user: Home or Traveling? +ICON_PATH="$APP_DIR/assets/icon.png" +NETWORK_CHOICE=$(osascript -e " + set iconFile to POSIX file \"$ICON_PATH\" + set theChoice to button returned of (display dialog \"Where are you right now?\" & return & return & \"Home — allows your phone and other devices on your Wi-Fi to use the app.\" & return & return & \"Traveling — locks access to just this laptop for safety on public Wi-Fi.\" buttons {\"Traveling\", \"Home\"} default button \"Traveling\" with title \"YouTube Summarizer\" with icon iconFile) + return theChoice +" 2>/dev/null) + +# Default to traveling (safe) if dialog was cancelled +if [ "$NETWORK_CHOICE" = "Home" ]; then + export LAN_MODE=true +else + export LAN_MODE=false +fi + +# Kill any existing instance on port 3001 +lsof -ti:3001 | xargs kill -9 2>/dev/null +sleep 0.3 + +# Start the server +cd server +node index.js & +SERVER_PID=$! +cd .. + +# Wait for server to be ready (up to 10 seconds) +for i in {1..20}; do + if curl -s http://localhost:3001/api/health > /dev/null 2>&1; then + break + fi + sleep 0.5 +done + +# Open browser +open http://localhost:3001 + +# Keep alive — when the app is quit, stop the server +trap "kill $SERVER_PID 2>/dev/null; exit 0" INT TERM +wait $SERVER_PID +LAUNCHER + +chmod +x "$APP_PATH/Contents/MacOS/launcher" + +# ── Create Info.plist ──────────────────────────────────────── +cat > "$APP_PATH/Contents/Info.plist" << PLIST + + + + + CFBundleExecutable + launcher + CFBundleName + YouTube Summarizer + CFBundleIdentifier + com.local.youtube-summarizer + CFBundleVersion + 1.0 + CFBundlePackageType + APPL + CFBundleIconFile + AppIcon + LSUIElement + + + +PLIST + +# ── Create the app icon from the pre-made PNG ─────────────── +ICON_PNG="$PROJECT_DIR/assets/icon.png" +ICON_DIR="$APP_PATH/Contents/Resources" + +if [ -f "$ICON_PNG" ]; then + echo "Building app icon..." + + # Create iconset with all required sizes using sips (built into macOS) + ICONSET="$ICON_DIR/AppIcon.iconset" + mkdir -p "$ICONSET" + + for size in 16 32 64 128 256 512; do + sips -z $size $size "$ICON_PNG" --out "$ICONSET/icon_${size}x${size}.png" > /dev/null 2>&1 + done + # @2x variants + for size in 16 32 128 256 512; do + double=$((size * 2)) + sips -z $double $double "$ICON_PNG" --out "$ICONSET/icon_${size}x${size}@2x.png" > /dev/null 2>&1 + done + + # Convert iconset → .icns using iconutil (built into macOS) + iconutil -c icns "$ICONSET" -o "$ICON_DIR/AppIcon.icns" 2>/dev/null + + # Clean up the iconset folder + rm -rf "$ICONSET" + + if [ -f "$ICON_DIR/AppIcon.icns" ]; then + echo " Icon created successfully." + else + echo " Warning: Could not create .icns icon. The app will use a generic icon." + fi +else + echo " Warning: assets/icon.png not found. The app will use a generic icon." +fi + +# ── Remove quarantine so macOS doesn't block it ───────────── +xattr -d com.apple.quarantine "$APP_PATH" 2>/dev/null + +# ── Done! ──────────────────────────────────────────────────── +echo "" +echo "============================================" +echo " Created: $APP_NAME.app" +echo "============================================" +echo "" +echo "You can now:" +echo " 1. Double-click it to launch the app" +echo " 2. Drag it to your Dock for quick access" +echo " 3. Move it to /Applications if you prefer" +echo "" +echo "If you move it outside this folder, it will" +echo "ask you to locate the project folder once." +echo "" +echo "Done!" +echo "" diff --git a/docker_entrypoint.sh b/docker_entrypoint.sh new file mode 100644 index 0000000..351f19b --- /dev/null +++ b/docker_entrypoint.sh @@ -0,0 +1,49 @@ +#!/bin/sh +set -eu + +DATA_DIR="/data" +HISTORY_DIR="$DATA_DIR/history" +CONFIG_DIR="$DATA_DIR/config" +BIN_DIR="$DATA_DIR/bin" +CACHE_DIR="$DATA_DIR/ytdlp-cache" + +# Create directory structure on persistent volume +mkdir -p "$HISTORY_DIR" "$CONFIG_DIR" "$BIN_DIR" "$CACHE_DIR" + +# Ensure the non-root user owns the data volume +# (on first boot the volume is root-owned; we need appuser to write) +chown -R 1001:1001 "$DATA_DIR" + +# Use persistent yt-dlp binary if available (runtime updates go here) +if [ -x "$BIN_DIR/yt-dlp" ]; then + export PATH="$BIN_DIR:$PATH" +fi + +# Point yt-dlp cache to persistent storage (stores OAuth tokens) +export XDG_CACHE_HOME="$CACHE_DIR" + +# Load Gemini API key from StartOS config if available +if [ -f "$CONFIG_DIR/startos-config.json" ]; then + GEMINI_KEY=$(python3 -c "import sys,json; print(json.load(open('$CONFIG_DIR/startos-config.json')).get('gemini_api_key',''))" 2>/dev/null || echo "") + if [ -n "$GEMINI_KEY" ]; then + export GEMINI_API_KEY="$GEMINI_KEY" + fi +fi + +# Also load from .env if it exists in data dir (user override) +if [ -f "$DATA_DIR/.env" ]; then + set -a + . "$DATA_DIR/.env" + set +a +fi + +export DATA_DIR="$DATA_DIR" +export PORT="${PORT:-3001}" +export HOSTNAME="0.0.0.0" + +echo "Starting YouTube Summarizer..." +echo " yt-dlp: $(yt-dlp --version 2>/dev/null || echo 'not found')" +echo " ffmpeg: $(ffmpeg -version 2>/dev/null | head -1 || echo 'not found')" +echo " Data: $DATA_DIR" + +exec node /app/server/index.js diff --git a/history/.DS_Store b/history/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/history/.DS_Store differ diff --git a/history/1772740338135-2JiMmye2ezg.json b/history/1772740338135-2JiMmye2ezg.json new file mode 100644 index 0000000..fb19ca5 --- /dev/null +++ b/history/1772740338135-2JiMmye2ezg.json @@ -0,0 +1 @@ +{"id":"1772740338135-2JiMmye2ezg","videoId":"2JiMmye2ezg","url":"https://youtu.be/2JiMmye2ezg?si=xmzyQpQLdVMjSJtd","title":"Untitled","type":"youtube","topicCount":10,"segmentCount":121,"createdAt":"2026-03-05T19:52:18.135Z","uploadDate":"","chunks":[{"title":"The Need for Agent-Readable Memory Infrastructure","summary":"The speaker introduces the concept of an \"Open Brain,\" an agent-readable, database-backed memory system. This addresses the limitations of previous \"Second Brain\" setups that lack seamless integration with autonomous AI agents.","entries":[{"text":"Your AI agent probably doesn't have a brain, and what I mean by that is it doesn't have a system that allows it to read and think through context that you have developed over months and years and reliably come back and be proactive with.","offset":0,"duration":13},{"text":"I published a whole guide on the Second Brain last month, it was super popular, a lot of people built it, a lot of people improved on it, you could use Zapier, you could use Notion, you could use n8n, you could use an MCP server, you could use Obsidian, I have all of those pieces.","offset":13,"duration":13},{"text":"But what I don't have is the agent piece, and that matters because in the intervening period, in the last few weeks, we are now at a point where agents are becoming mainstream.","offset":26,"duration":13},{"text":"Anthropic is working on one, OpenAI hired Peter Steinberger, the inventor of OpenClaw, OpenClaw itself passed 190,000 GitHub stars and spawned over 1.5 million autonomous agents in just a couple of weeks.","offset":39,"duration":17},{"text":"We need a second brain system that is agent-readable. And so what I'm going to lay out here today is the architecture for what I am calling an Open Brain, a database-backed AI-accessible knowledge system that you own outright with no SaaS middlemen that can break or reprice or disappear.","offset":56,"duration":23},{"text":"One brain that every AI you use, Claude, ChatGPT, Cursor, whatever ships next month, can plug into via MCP.","offset":79,"duration":11},{"text":"You can type a thought in Slack and five seconds later it's embedded, it's classified, it's searchable by meaning from any AI tool you touch or any AI agent that wants to touch it.","offset":90,"duration":12},{"text":"The total cost, and yes, we've benchmarked this, it's roughly 10 to 30 cents a month. I'm publishing a companion guide on the Substack to handle the step-by-step.","offset":102,"duration":10},{"text":"This video is about why the architecture of an agent-readable system matters much more than the individual tools you choose and why the memory problem we're talking about here is secretly the bottleneck in everything you're doing with AI today and why people who solve it for agents and themselves will have a compounding advantage that widens every single week.","offset":112,"duration":22}],"startTime":0},{"title":"The Context Bottleneck in AI Prompting","summary":"The quality of AI output relies heavily on context and specification. Without a centralized memory system, users burn energy on context transfer and suffer from constant, exhausting application switching.","entries":[{"text":"So first let's talk about the memory problem that is hiding inside your prompting. If you've been following my videos for a while you know I keep coming back to one idea: the quality of AI output depends entirely on the quality of your ability to specify.","offset":134,"duration":16},{"text":"That's not a nice to have principle anymore, that is the whole game. I laid out the full framework I see for prompting in 2026 in a video I did last week, from prompt craft through context engineering to intent engineering to specification engineering.","offset":150,"duration":16},{"text":"That hierarchy is real and the people who are 10x more effective than their peers have built context infrastructure that does the heavy lifting on all of those pieces, the context engineering, the specification engineering before they have to type a single prompt.","offset":166,"duration":14},{"text":"And what I want to talk about in this video is how you take that abstract skill set and how you turn it into a memory problem that gives you a leg up on everybody else.","offset":180,"duration":13},{"text":"In other words, if you're going to do context engineering, if you're going to do specification engineering seriously, you need to invest in a memory system that is yours, that is agent-readable, that makes calling and retrieving that context, that makes specifying easier.","offset":193,"duration":18},{"text":"The best prompt in the world cannot compensate for an AI that does not know what you've been working on, what you've already tried, what your constraints are, who the key people in your life are, or what you decided last Tuesday.","offset":211,"duration":14},{"text":"And by the way, that is also the constraint working with agents, they need that context too. And right now that's exactly what most of us are struggling with when it comes to AI. Every single time we open a new chat we often start from zero.","offset":225,"duration":14},{"text":"Every single time we switch from Claude to ChatGPT to Cursor, we tend to lose things, which is why we gravitate toward one of those systems more than another.","offset":239,"duration":10},{"text":"Think about how much of your prompting is asking AI to catch up on what you know already. The background here is you're burning up your best thinking on context transfer instead of real work.","offset":249,"duration":10},{"text":"A Harvard Business Review study found that digital workers toggle between applications nearly 1200 times a day, I get tired saying that sentence. Every switch seems really small but collectively this is devastating our attention.","offset":259,"duration":14},{"text":"I have watched this context switching issue play out over and over and over again in my own life and the lives of others, and what I keep coming back to is the insight that our desire to specify, to be clear with AI is only getting higher and it's demanding more of our memory systems and our memory systems and memory structures are not keeping up.","offset":273,"duration":20},{"text":"Memory architecture determines agent capabilities much more than model selection does, that's widely misunderstood. And when you construct memory incorrectly, you're stuck re-explaining yourself forever, or you're stuck in a world where you know how to access memory and the agent doesn't.","offset":293,"duration":18},{"text":"I believe we can make a stable memory system that is reasonably future-proofed, that enables us to plug in new tools via MCP server very efficiently, so we don't have to keep updating our system.","offset":311,"duration":11}],"startTime":134},{"title":"Corporate Lock-In and Siloed AI Memory","summary":"Major AI platforms have introduced memory features, but they remain siloed within each application. These walled gardens are deliberately designed by corporations to lock users in and monopolize their data.","entries":[{"text":"And yes, I want to acknowledge something, Claude has memory now, ChatGPT has memory now, Grok has memory now, Google has memory now. These features are getting better all the time, but think about what they give you and what they don't.","offset":322,"duration":14},{"text":"Claude's memory doesn't know what you told ChatGPT. ChatGPT's memory doesn't follow you into Cursor. Your phone app doesn't share context with your coding agent. Every platform has built a walled garden of memory and none of them talk to each other.","offset":336,"duration":15},{"text":"There's a whole new category of products emerging in early 2026 specifically because platforms refuse to solve this. Products like MemZero, MemSync, OneContext. The problem is real enough to spawn an entire VC-backed industry.","offset":351,"duration":15},{"text":"So what you've really got is multiple AI tools getting upgraded all the time, adding AI tools all the time to experiment with them, and you have a thin siloed layer of context that only works inside each of those individual tools. You know what, that's not really memory, that is five separate piles of sticky notes on five separate desks.","offset":366,"duration":20},{"text":"And now let's add autonomous agents into the picture. The agent category has absolutely detonated in the last few weeks, but the use cases that are shining, like the guy who got thousands of dollars off a car purchase, they're shining because the agent has the ability to securely and safely access relevant memories, relevant context from the user.","offset":386,"duration":25},{"text":"Whereas agents that just guess context or have to fill in the dots because you aren't able to provide them secure access to all of your systems, they're not going to be nearly as useful for you.","offset":411,"duration":8},{"text":"And whether we're talking about agents or we're talking about tools, the part that should bother you even more is that these systems that corporations are designing are all designed to create lock-in.","offset":419,"duration":13},{"text":"Memory is supposed to be a lock-in on ChatGPT, ditto on other systems. So you've spent a long time building up history with a tool and now if you want to try the latest other model, let's say you're on ChatGPT and you want to try Gemini or you want to try Claude or you want to try another model, you lose all of that context.","offset":432,"duration":19},{"text":"Not because the new model is worse, but because your context is trapped in the old one. And oh by the way, all of that memory in those individual tools, that is not agent-readable.","offset":451,"duration":11},{"text":"And so as we get to a world where autonomous agents are becoming more and more and more a thing, the big corporations are betting that if they can trap you with memory, you will only use their agents and they will get to keep you and your attention and your dollars forever.","offset":462,"duration":17},{"text":"But your knowledge should not be a hostage to any single platform. And for most of us right now, frankly, it is. And that's shaping our entire AI future.","offset":479,"duration":12},{"text":"We don't necessarily have a free choice between tools right now because the product strategy of these large businesses is to keep you, to keep you engaged, to keep you entertained.","offset":491,"duration":12},{"text":"I've talked about how in many cases you're pushing for engagement with these models. One of the reasons why ChatGPT-4o was so mourned and so grieved was because it was an engagement-optimized model and people liked the engagement, it works.","offset":503,"duration":14},{"text":"Ditto with memory. Memory is engaging. Feeling known is engaging. It works. It's smart product strategy. But you're smart too and you don't have to go along with that product strategy.","offset":517,"duration":10}],"startTime":322},{"title":"Transitioning from Human Web to Agent Web","summary":"Current note-taking apps are designed for human eyes, not AI agents. To truly leverage AI, users must migrate from visually-oriented notes to structured semantic data built for the emerging agent web.","entries":[{"text":"And you might be thinking at this point, Nate, you made a video on Second Brain, I can just connect it to my OpenClaw and I'm fine. Absolutely, you can try that, but you're going to run into a structural mismatch that most people haven't noticed that explains why the current generation of note-taking tools needs a different more structured memory layer underneath.","offset":527,"duration":20},{"text":"The internet right now is forking, I've talked about that. There's the human web with fonts, with layouts, with what you're reading, and there's the agent web that's emerging with APIs, with structured data that's built for machine-to-machine readability.","offset":547,"duration":15},{"text":"That fork is happening to your memory architectures and your notes as well. Your Notion workspace, for example, is built for human eyes. It's built for pages, for databases, for views, for toggles, for cover images.","offset":562,"duration":13},{"text":"It's beautiful for you, it's useless for an AI agent that needs to search by meaning, not by folder structure. Your Apple Notes are locked into an ecosystem. Your Evernote has a decade of accumulated clutter with no semantic structure. Your bookmarks are a graveyard of things you've meant to read.","offset":575,"duration":15},{"text":"These tools were built for the human web back in the 2010s. They were designed for you to browse, to organize, to read, they were never designed fundamentally with the expectation that AI agents would query them.","offset":590,"duration":11},{"text":"That got bolted on later, much more recently. And the apps adding AI features today are mostly doing it as bolt-ons, like Chat with your Notes. Great, you have one AI that can kind of search one app.","offset":601,"duration":13},{"text":"What about the other five tools you use every week? We're still in a world of separate sticky notes on separate desks. You've traded one silo for another.","offset":614,"duration":10},{"text":"Every second brain app has been reaching for something that required a different layer entirely: infrastructure built for the agent web, not the human web.","offset":624,"duration":9},{"text":"And that's what I want to focus on here, because if you can build infrastructure for the agent web, you are suddenly in a position to make a lot more human-friendly decisions with how you plug into that infrastructure.","offset":633,"duration":12},{"text":"The infrastructure is yours, it's something your agent can plug into, it's something your chatbots can plug into, but you control and manage it. This frees you from having memory that only lives with one of these corporations and their cloud-serviced AI systems.","offset":645,"duration":16},{"text":"You don't have to depend on ChatGPT memory anymore. It also frees you from having to depend on an individual SaaS company not changing a setting in order to keep your own second brain working.","offset":661,"duration":14},{"text":"And ultimately, as agents get better, it frees you from having to do as much manual work to retrain a second brain.","offset":675,"duration":6},{"text":"And so this is me essentially giving you a sense of how agents unlocking are changing our perspective on memory and changing our perspective on prompting and changing what we need to be digital citizens.","offset":681,"duration":16},{"text":"Just as we needed a personal computer to be digital citizens over the 2010s, over the 1990s, over the 2000s, we need our own memory architectures to be responsible AI citizens now.","offset":697,"duration":12},{"text":"But we haven't really had a way to do that and until very recently, until the last few weeks, we haven't had AI agents that would make that really practical. Now we do, and now the world has moved and now it's time to talk about it.","offset":709,"duration":14}],"startTime":527},{"title":"Technical Architecture of the Open Brain","summary":"The technical setup for the Open Brain utilizes a Postgres database, vector embeddings, and the Model Context Protocol (MCP). It allows any AI tool to natively search and capture meaning, costing pennies a month and requiring zero coding experience.","entries":[{"text":"So let's get specific. What am I proposing here? Instead of storing your thoughts in an app designed for humans, you should store them in infrastructure designed for anything: a real database, vector embeddings that capture meaning, not just keywords, a standard protocol that any AI can speak.","offset":723,"duration":19},{"text":"I'm calling it Open Brain because the architecture is what matters and you should not be forced to choose any given model. This is all possible because of MCP, the protocol shift that I talked about briefly above.","offset":742,"duration":14},{"text":"It started as Anthropic's open source experiment in November of 2024, but it's since become the HTTP infrastructure of the AI age, it's the USB-C of AI, it's one protocol every AI, your data is yours, it stays in one place, but every tool that speaks MCP can read it.","offset":756,"duration":20},{"text":"So at a high level, I don't want to make you go and click somewhere, let me show you what this actually looks like. Your thoughts live in a Postgres database you control, not somebody else's proprietary format.","offset":776,"duration":12},{"text":"This is the most boring battle-tested technology you can imagine. Postgres is not exciting, it's not deprecating, Postgres isn't chasing a growth metric, Postgres isn't VC-backed and needing to hit a billion dollar unicorn valuation. It's just a standard way of storing data.","offset":788,"duration":15},{"text":"And you want that boringness because everything else needs to plug into it. The nice thing about the database is that if you construct it properly, if you vectorize it, every thought you capture gets converted into a vector embedding, which means it's a mathematical representation of what it means that is immediately natively AI readable.","offset":803,"duration":18},{"text":"So when you ask, what was I thinking about career changes last month, it can find your note about how you were considering moving into consulting or how you were considering moving into product even if you never used the word career in the original thought. It's called semantic search and it's a whole different universe from Control-F.","offset":821,"duration":21},{"text":"So what this looks like when you have Postgres hooked up with an MCP server is you can type into a Slack channel, hey, I was talking with Sarah, she mentioned she's thinking about leaving her job to start a consulting business, she's been really unhappy since the reorg.","offset":842,"duration":16},{"text":"Five seconds later the system has stored the raw text, generated a vector embedding of the meaning, extracted the metadata, the people, the topics, the types, the action items, and filed all of it in a real database.","offset":858,"duration":13},{"text":"Now any AI that you're working with can go see that. If you're in Claude working on a coaching framework, hey search my brain for notes about people considering career transition, found it.","offset":871,"duration":10},{"text":"If I'm in ChatGPT drafting an email, same search same result. If I'm in Cursor building a tool and I need to remember a decision I made last week, hit the MCP server, it's right there. One brain every AI, persistent memory that never starts from zero even if you start a new tool tomorrow and you've never touched it before.","offset":881,"duration":20},{"text":"So this has two basic parts, right? Capture once through any tool you have open. You type a thought, it hits a Superbase Edge function that generates an embedding and it extracts the metadata in parallel and stores both in a Postgres database with pgvector and just replies in thread with a confirmation showing what it captured. The whole round trip takes under 10 seconds.","offset":901,"duration":22},{"text":"Retrieval runs through an MCP server that connects to any compatible AI client. You have three tools: semantic search, which is finding your thoughts by meaning, listing recent, which is browsing what you captured this week, and stats so you see your patterns, right?","offset":923,"duration":14},{"text":"You can hit this from Claude, from Claude Code, from ChatGPT, from Cursor, from VS Code, from anywhere you can query your brain through an MCP server.","offset":937,"duration":7},{"text":"If all of this sounds like Greek to you, the companion guide walks you through a complete setup. Copy-paste, no coding, about 45 minutes to set up.","offset":944,"duration":9},{"text":"And you know how I tested this? I asked someone in my life to follow this guide before I showed it to you. And she has no coding experience whatsoever and I said can you get it to a point where you can set this up. And she could and it took her about 45 minutes.","offset":953,"duration":15},{"text":"And I'm not kidding about the cost because the total running cost on the free tiers of say Slack and Superbase, which is what I'm talking about here, it's roughly a dime to 30 cents a month in API calls for about 20 thoughts a day. So you're going to spend more on coffee this morning than you're going to spend on the system this month.","offset":968,"duration":18}],"startTime":723},{"title":"The Compounding Advantage of Persistent AI Context","summary":"A centralized memory system provides a massive, compounding advantage over time. Users who integrate their workflow with persistent context will far outperform those who constantly start from scratch with every new AI chat.","entries":[{"text":"Here's why getting memory at the fundamental architectural level matters beyond the nice feeling we get from building a cool tool. I love to build, you can probably tell, people who love to build will love to build anyway, but it matters for everybody, it doesn't just matter for those of us that like to experiment.","offset":986,"duration":18},{"text":"We are in the middle of a massive shift in how AI integrates into our daily work. The models keep getting better at a terrifyingly fast pace and you don't want to fall behind. Opus 4.6 shipped just a couple of weeks back, the agent market is growing probably in triple figures this year.","offset":1004,"duration":18},{"text":"Three-person engineering teams are routinely out-producing teams 10 times their size. And we're finally seeing this explosion in AI productivity show up even in economy-wide metrics.","offset":1022,"duration":13},{"text":"Erik Brynjolfsson wrote in the Financial Times last month that US productivity grew roughly 2.7% in 2025, which is double the decade average, and frankly Erik attributed a fair bit of that to AI agents and AI.","offset":1035,"duration":13},{"text":"But the key is, as I've called out before, AI adoption is not the same everywhere. If you're just talking with a single chatbot, I've said it over and over, you're not really adopting and working your workflows around AI in the way you need to.","offset":1048,"duration":13},{"text":"And the people getting those outsized results are not depending on better models to get there, they're actually restructuring how they work with AI as a primary collaborator.","offset":1061,"duration":10},{"text":"But you cannot collaborate with something that has no memory of you. Think about the difference between these two workflows.","offset":1071,"duration":10},{"text":"Person A opens up Claude, spends four minutes explaining their role, their project, their constraints and the decision they're trying to make and they get a good answer.","offset":1081,"duration":8},{"text":"Person B opens up Claude, it already knows her role, her active projects, her constraints, her team members and the decisions she made last week because all of that lives via MCP server in Open Brain. All of it is loaded up before she types a word.","offset":1089,"duration":15},{"text":"She asks for a question, she gets an answer informed by six months of accumulated context. If she wants to switch to ChatGPT for a different perspective, she'll get a different model but she'll get the same brain, the same context and the same answer quality. Every single tool will have the full picture for her.","offset":1104,"duration":17},{"text":"And the key is that advantage will keep compounding. Every thought Person B captures makes the next iteration better. Every decision logged, every person noted, every insight saved adds another node to what's a growing knowledge graph that every AI in the system can access.","offset":1121,"duration":18},{"text":"So Person A is going to start from zero every single time. The gap between I use AI sometimes and AI is embedded in how I think and work is the career gap of this decade and it comes down to memory and context infrastructure.","offset":1139,"duration":16},{"text":"And the gap is going to get wider as Person B continues to accumulate knowledge every week. The people who build persistent, searchable, AI-accessible knowledge systems will have AI that gets better at helping them over time because it has more context to work with.","offset":1155,"duration":18},{"text":"Every thought you capture makes the next search smarter, the next connection more likely to surface and that is a compounding advantage that you own, that the big companies don't own.","offset":1173,"duration":11},{"text":"Whereas the people who keep re-explaining themselves in every chat window are going to wonder why AI still feels like a party trick. It's the same tech, it's just wildly different outcomes and the variable here is your infrastructure.","offset":1184,"duration":12}],"startTime":986},{"title":"Capturing Data with Two-Way MCP Integration","summary":"MCP enables seamless reading and writing to the Open Brain from any device or application. However, the system's true effectiveness relies entirely on the user's habit of consistently capturing their daily thoughts.","entries":[{"text":"And one thing I want to call out here, I've given you a simple example where you can retrieve a clear answer in text in any AI tool you want with an MCP server, but MCP servers are not just for retrieval.","offset":1196,"duration":11},{"text":"And if you construct an Open Brain, your MCP server can work in a lot of different directions to give you advantages you might not think of if you are just used to using memory in a single tool.","offset":1207,"duration":12},{"text":"MCP means you can write directly into the brain from anywhere, I really meant that. You can write into Claude on the phone, you can use ChatGPT on the desk, you can use Claude code in the terminal, you can rig it up to a messaging app. Any MCP-compatible client becomes both a capture point and a search tool. You're not locked into Slack or any other system. That's what Open means.","offset":1219,"duration":35},{"text":"And do you know that you don't need to use code to do that, because you can just ask the AI tool of your choice to retrieve from the MCP server the relevant slice of context and build something. Because the data is stored in a way that is easy to plug in and easy to store and easy to access from any tool out there. The ceiling is wherever you decide to stop building.","offset":1254,"duration":25},{"text":"Now I want to be honest, the metadata extraction isn't always perfect. The LLM makes its best guess to classify with limited context and it will sometimes misclassify a thought or miss a name.","offset":1279,"duration":11},{"text":"It doesn't matter as much with semantic embedding because the embeddings handle so much of the heavy lifting with retrieval. Semantic search works even when the metadata is off.","offset":1290,"duration":10},{"text":"The one real requirement for this to work is that you actually use it because the system compounds. Every thought you capture makes the next search smarter and the next connection more likely to surface. But it needs input. You need to build the habit. You need to be dumping your thinking into the system and let it do the rest.","offset":1300,"duration":21}],"startTime":1196},{"title":"Custom Prompts for Open Brain Maintenance","summary":"The speaker shares specific prompts designed to populate and maintain the Open Brain system. These tools include memory migration routines, quick capture templates, and weekly review workflows to synthesize data.","entries":[{"text":"Now if you're a subscriber on the Substack I've put together four prompts that cover the full life cycle and I actually want to describe them in the video because even if you're not a subscriber you should understand how we can use prompts in the architecture of this system to think more deliberately and make the memory architecture fit our needs.","offset":1321,"duration":20},{"text":"The memory migration is the first thing I'm going to suggest. You want to run this right after setup. It extracts everything your AI knows about you already from Claude's memory, from ChatGPT's memory, from wherever you've accumulated context and it saves it into your Open Brain.","offset":1341,"duration":14},{"text":"Every other AI you connect then starts with that foundation instead of zero. So you want to run it once and let it pull that stuff down.","offset":1355,"duration":9},{"text":"I'm also building what I call the Open Brain Spark because I sometimes get writer's block. So you want to have an interview prompt that discovers how the system fits your specific work. It asks about your tools, your decisions, your re-explanation patterns, your key people and then generates a personalized list organized by category that suggests what you should be putting into Open Brain regularly.","offset":1364,"duration":25},{"text":"Use it when you're staring at the Slack channel or you're staring at your messaging app or you're staring at ChatGPT and you're wondering what do I type that I want to put into Open Brain today.","offset":1389,"duration":8},{"text":"I also put together quick capture templates, so these are five sentence long starters optimized for really clean metadata extraction. So a decision capture prompt, a person note, an insight capture, a meeting debrief. Each one is designed to trigger the right classification in your processing pipeline.","offset":1397,"duration":19},{"text":"And after a week of capturing you'll find you don't need them as much because you're going to develop your own patterns. But they're really useful for building that habit early without having to think about how to sort of send the system a coherent message where it's likely to classify correctly.","offset":1416,"duration":15},{"text":"The weekly review is another one I put together. End of week synthesis across everything you captured. It clusters by topic, it scans for unresolved action items, it detects patterns across days, it finds connections you missed and it identifies gaps in what you're tracking.","offset":1431,"duration":15},{"text":"So about five minutes on a Friday afternoon becomes more valuable every week because your Open Brain continues to grow.","offset":1446,"duration":8}],"startTime":1321},{"title":"Human Clarity Through AI Context Engineering","summary":"Building a foundational memory architecture forces a clarity of thought that greatly benefits human workflows. Ultimately, practicing good context engineering for AI agents translates to better communication and less corporate politics among people.","entries":[{"text":"If we zoom back out, when this thing works, when you get the Postgres database set up, you're starting to use it in whatever messaging app you want, you're starting to see the memory become consistent across all your AI tools and you're starting to realize you do not depend on proprietary paid-for memory by big AI companies, something happens that's a little bit hard to describe until you experience it.","offset":1454,"duration":27},{"text":"Your AI in every single part of the system, whether you're using Claude or ChatGPT or both or Cursor or Grok, whatever it is, it starts to know you. Not in the creepy corporate surveillance way, in the, hey, we were thinking about this last week and it's relevant to what you're asking me now kind of way. The way a great colleague remembers what matters.","offset":1481,"duration":20},{"text":"So every AI you use gets better. You're less afraid of trying a new AI because you can just plug it into MCP and it finally has the context.","offset":1501,"duration":11},{"text":"This is what an agent-readable world makes possible, and I want to call out something really special here. When I suggested the original Second Brain guide, I built it before the agent revolution went mainstream, which again was only about a month and a half ago, a month ago.","offset":1512,"duration":-1184},{"text":"And it was useful for humans, and it was designed to solve a fundamental cognitive problem that we've had, which is that we have trouble holding stuff in our head and we need to see patterns over time. LLMs can help us assess patterns. That's all still true, and you can use this Open Brain in that way.","offset":328,"duration":1219},{"text":"But when the agent revolution came through in the last few weeks, because again AI is moving that fast, what we need to move to is a second brain system that is more foundational. Something that enables both us and our agents to reliably read from a system that isn't SaaS-controlled, that isn't proprietary company-controlled, that is frankly open source LLM-friendly.","offset":1547,"duration":24},{"text":"And when we have that, we get two benefits. Yes, the agent can read it and that is in line with where we're going with agents and how quickly agents are going mainstream and that's the reason I'm making this video.","offset":1571,"duration":12},{"text":"But second, look at how much cleaner and clearer the human-readable part of this gets. We get downstream benefits that we did not get when we think about the system from only a human-readable perspective.","offset":1583,"duration":17},{"text":"Because if you think about the system from a human-readable perspective, you get something like what I described. You focus on SaaS-friendly solutions with graphical user interfaces that humans can easily read because you want to make it easy and accessible to build the system.","offset":1600,"duration":16},{"text":"And that's what I did originally. But if you're willing to get slightly technical and follow a clean step-by-step tutorial to get to something that is a true database, what you get is a future-proofed system that unlocks the human benefit of touching any AI system in the future that you might want to try without doing any additional effort.","offset":1616,"duration":27},{"text":"And so we humans reap a tremendous amount of value from the clarity that comes from a truly foundational architected memory system.","offset":1643,"duration":12},{"text":"This reminds me of one of the larger lessons I've been meditating on in the AI revolution, which is that AI is forcing a clarity of thought in our work, in our lives that has a tremendous amount of human benefit.","offset":1655,"duration":16},{"text":"Tobi Lütke has said that he thinks a lot of corporate politics amount to bad human context engineering, which is a very provocative take. And I think that that is something that pops out here, because we need extraordinary clarity to work with AI agents.","offset":1671,"duration":19},{"text":"And when we develop that extraordinary clarity through memory architectures that are foundational, through good databases, through a clean MCP server, we get the benefit of cleanly and clearly being able to plug in and work with that memory system anywhere.","offset":1690,"duration":18},{"text":"We do good context engineering for our human brains when we build the right context engineering for AI. Which is kind of Tobi's point about politics. When we do good context engineering for agents, we happen to do good context engineering for people, and that makes people less likely to play politics.","offset":1708,"duration":16}],"startTime":1454},{"title":"Migration Steps and Final Encouragement","summary":"The Open Brain acts as a foundational layer to upgrade existing knowledge systems rather than entirely replacing them. The speaker offers a migration guide and encourages viewers to take the weekend to build their own agent-readable database.","entries":[{"text":"So the second brain you build, if you were one of the thousands of people that built it when I talked about it, was always reaching for this. It was reaching for a place where your thinking lives, where it's searchable by meaning, where it's accessible to any tool you use.","offset":1724,"duration":13},{"text":"And those tools solved the capture problem, they solved the organization problem, but what they didn't realize they needed to solve, because it wasn't really there yet, was the agent-readable problem.","offset":1737,"duration":11},{"text":"Open Brain adds that foundational layer, not by replacing what you built, but by giving it an infrastructure underneath. A database, a protocol, your thoughts, every AI you'll ever use.","offset":1748,"duration":13},{"text":"So you can build it in a morning over coffee this weekend. Yes, really, you. And your future AI, your future self as a human will thank you for every thought you start to capture now.","offset":1761,"duration":13},{"text":"If you have already built a second brain, I'm also including a special migration guide so that you can figure out how to not lose the thoughts you've been capturing and make sure you get them into a system that is more agent-readable going forward.","offset":1774,"duration":16},{"text":"Best of luck. Don't be afraid of how this is slightly technical. There've been lots of visuals all the way through this YouTube helping you to see what I mean and you'll see more guides in the Substack if you're interested.","offset":1790,"duration":11},{"text":"And honestly, I put enough visuals into this video that if you are not ready to hop into the Substack, totally fine, you should still be able to get there. You should be able to show this video to an AI and say help me build this and it should be able to do it. Cheers.","offset":1801,"duration":15}],"startTime":1724}],"entries":[{"text":"Your AI agent probably doesn't have a brain, and what I mean by that is it doesn't have a system that allows it to read and think through context that you have developed over months and years and reliably come back and be proactive with.","offset":0,"duration":13},{"text":"I published a whole guide on the Second Brain last month, it was super popular, a lot of people built it, a lot of people improved on it, you could use Zapier, you could use Notion, you could use n8n, you could use an MCP server, you could use Obsidian, I have all of those pieces.","offset":13,"duration":13},{"text":"But what I don't have is the agent piece, and that matters because in the intervening period, in the last few weeks, we are now at a point where agents are becoming mainstream.","offset":26,"duration":13},{"text":"Anthropic is working on one, OpenAI hired Peter Steinberger, the inventor of OpenClaw, OpenClaw itself passed 190,000 GitHub stars and spawned over 1.5 million autonomous agents in just a couple of weeks.","offset":39,"duration":17},{"text":"We need a second brain system that is agent-readable. And so what I'm going to lay out here today is the architecture for what I am calling an Open Brain, a database-backed AI-accessible knowledge system that you own outright with no SaaS middlemen that can break or reprice or disappear.","offset":56,"duration":23},{"text":"One brain that every AI you use, Claude, ChatGPT, Cursor, whatever ships next month, can plug into via MCP.","offset":79,"duration":11},{"text":"You can type a thought in Slack and five seconds later it's embedded, it's classified, it's searchable by meaning from any AI tool you touch or any AI agent that wants to touch it.","offset":90,"duration":12},{"text":"The total cost, and yes, we've benchmarked this, it's roughly 10 to 30 cents a month. I'm publishing a companion guide on the Substack to handle the step-by-step.","offset":102,"duration":10},{"text":"This video is about why the architecture of an agent-readable system matters much more than the individual tools you choose and why the memory problem we're talking about here is secretly the bottleneck in everything you're doing with AI today and why people who solve it for agents and themselves will have a compounding advantage that widens every single week.","offset":112,"duration":22},{"text":"So first let's talk about the memory problem that is hiding inside your prompting. If you've been following my videos for a while you know I keep coming back to one idea: the quality of AI output depends entirely on the quality of your ability to specify.","offset":134,"duration":16},{"text":"That's not a nice to have principle anymore, that is the whole game. I laid out the full framework I see for prompting in 2026 in a video I did last week, from prompt craft through context engineering to intent engineering to specification engineering.","offset":150,"duration":16},{"text":"That hierarchy is real and the people who are 10x more effective than their peers have built context infrastructure that does the heavy lifting on all of those pieces, the context engineering, the specification engineering before they have to type a single prompt.","offset":166,"duration":14},{"text":"And what I want to talk about in this video is how you take that abstract skill set and how you turn it into a memory problem that gives you a leg up on everybody else.","offset":180,"duration":13},{"text":"In other words, if you're going to do context engineering, if you're going to do specification engineering seriously, you need to invest in a memory system that is yours, that is agent-readable, that makes calling and retrieving that context, that makes specifying easier.","offset":193,"duration":18},{"text":"The best prompt in the world cannot compensate for an AI that does not know what you've been working on, what you've already tried, what your constraints are, who the key people in your life are, or what you decided last Tuesday.","offset":211,"duration":14},{"text":"And by the way, that is also the constraint working with agents, they need that context too. And right now that's exactly what most of us are struggling with when it comes to AI. Every single time we open a new chat we often start from zero.","offset":225,"duration":14},{"text":"Every single time we switch from Claude to ChatGPT to Cursor, we tend to lose things, which is why we gravitate toward one of those systems more than another.","offset":239,"duration":10},{"text":"Think about how much of your prompting is asking AI to catch up on what you know already. The background here is you're burning up your best thinking on context transfer instead of real work.","offset":249,"duration":10},{"text":"A Harvard Business Review study found that digital workers toggle between applications nearly 1200 times a day, I get tired saying that sentence. Every switch seems really small but collectively this is devastating our attention.","offset":259,"duration":14},{"text":"I have watched this context switching issue play out over and over and over again in my own life and the lives of others, and what I keep coming back to is the insight that our desire to specify, to be clear with AI is only getting higher and it's demanding more of our memory systems and our memory systems and memory structures are not keeping up.","offset":273,"duration":20},{"text":"Memory architecture determines agent capabilities much more than model selection does, that's widely misunderstood. And when you construct memory incorrectly, you're stuck re-explaining yourself forever, or you're stuck in a world where you know how to access memory and the agent doesn't.","offset":293,"duration":18},{"text":"I believe we can make a stable memory system that is reasonably future-proofed, that enables us to plug in new tools via MCP server very efficiently, so we don't have to keep updating our system.","offset":311,"duration":11},{"text":"And yes, I want to acknowledge something, Claude has memory now, ChatGPT has memory now, Grok has memory now, Google has memory now. These features are getting better all the time, but think about what they give you and what they don't.","offset":322,"duration":14},{"text":"Claude's memory doesn't know what you told ChatGPT. ChatGPT's memory doesn't follow you into Cursor. Your phone app doesn't share context with your coding agent. Every platform has built a walled garden of memory and none of them talk to each other.","offset":336,"duration":15},{"text":"There's a whole new category of products emerging in early 2026 specifically because platforms refuse to solve this. Products like MemZero, MemSync, OneContext. The problem is real enough to spawn an entire VC-backed industry.","offset":351,"duration":15},{"text":"So what you've really got is multiple AI tools getting upgraded all the time, adding AI tools all the time to experiment with them, and you have a thin siloed layer of context that only works inside each of those individual tools. You know what, that's not really memory, that is five separate piles of sticky notes on five separate desks.","offset":366,"duration":20},{"text":"And now let's add autonomous agents into the picture. The agent category has absolutely detonated in the last few weeks, but the use cases that are shining, like the guy who got thousands of dollars off a car purchase, they're shining because the agent has the ability to securely and safely access relevant memories, relevant context from the user.","offset":386,"duration":25},{"text":"Whereas agents that just guess context or have to fill in the dots because you aren't able to provide them secure access to all of your systems, they're not going to be nearly as useful for you.","offset":411,"duration":8},{"text":"And whether we're talking about agents or we're talking about tools, the part that should bother you even more is that these systems that corporations are designing are all designed to create lock-in.","offset":419,"duration":13},{"text":"Memory is supposed to be a lock-in on ChatGPT, ditto on other systems. So you've spent a long time building up history with a tool and now if you want to try the latest other model, let's say you're on ChatGPT and you want to try Gemini or you want to try Claude or you want to try another model, you lose all of that context.","offset":432,"duration":19},{"text":"Not because the new model is worse, but because your context is trapped in the old one. And oh by the way, all of that memory in those individual tools, that is not agent-readable.","offset":451,"duration":11},{"text":"And so as we get to a world where autonomous agents are becoming more and more and more a thing, the big corporations are betting that if they can trap you with memory, you will only use their agents and they will get to keep you and your attention and your dollars forever.","offset":462,"duration":17},{"text":"But your knowledge should not be a hostage to any single platform. And for most of us right now, frankly, it is. And that's shaping our entire AI future.","offset":479,"duration":12},{"text":"We don't necessarily have a free choice between tools right now because the product strategy of these large businesses is to keep you, to keep you engaged, to keep you entertained.","offset":491,"duration":12},{"text":"I've talked about how in many cases you're pushing for engagement with these models. One of the reasons why ChatGPT-4o was so mourned and so grieved was because it was an engagement-optimized model and people liked the engagement, it works.","offset":503,"duration":14},{"text":"Ditto with memory. Memory is engaging. Feeling known is engaging. It works. It's smart product strategy. But you're smart too and you don't have to go along with that product strategy.","offset":517,"duration":10},{"text":"And you might be thinking at this point, Nate, you made a video on Second Brain, I can just connect it to my OpenClaw and I'm fine. Absolutely, you can try that, but you're going to run into a structural mismatch that most people haven't noticed that explains why the current generation of note-taking tools needs a different more structured memory layer underneath.","offset":527,"duration":20},{"text":"The internet right now is forking, I've talked about that. There's the human web with fonts, with layouts, with what you're reading, and there's the agent web that's emerging with APIs, with structured data that's built for machine-to-machine readability.","offset":547,"duration":15},{"text":"That fork is happening to your memory architectures and your notes as well. Your Notion workspace, for example, is built for human eyes. It's built for pages, for databases, for views, for toggles, for cover images.","offset":562,"duration":13},{"text":"It's beautiful for you, it's useless for an AI agent that needs to search by meaning, not by folder structure. Your Apple Notes are locked into an ecosystem. Your Evernote has a decade of accumulated clutter with no semantic structure. Your bookmarks are a graveyard of things you've meant to read.","offset":575,"duration":15},{"text":"These tools were built for the human web back in the 2010s. They were designed for you to browse, to organize, to read, they were never designed fundamentally with the expectation that AI agents would query them.","offset":590,"duration":11},{"text":"That got bolted on later, much more recently. And the apps adding AI features today are mostly doing it as bolt-ons, like Chat with your Notes. Great, you have one AI that can kind of search one app.","offset":601,"duration":13},{"text":"What about the other five tools you use every week? We're still in a world of separate sticky notes on separate desks. You've traded one silo for another.","offset":614,"duration":10},{"text":"Every second brain app has been reaching for something that required a different layer entirely: infrastructure built for the agent web, not the human web.","offset":624,"duration":9},{"text":"And that's what I want to focus on here, because if you can build infrastructure for the agent web, you are suddenly in a position to make a lot more human-friendly decisions with how you plug into that infrastructure.","offset":633,"duration":12},{"text":"The infrastructure is yours, it's something your agent can plug into, it's something your chatbots can plug into, but you control and manage it. This frees you from having memory that only lives with one of these corporations and their cloud-serviced AI systems.","offset":645,"duration":16},{"text":"You don't have to depend on ChatGPT memory anymore. It also frees you from having to depend on an individual SaaS company not changing a setting in order to keep your own second brain working.","offset":661,"duration":14},{"text":"And ultimately, as agents get better, it frees you from having to do as much manual work to retrain a second brain.","offset":675,"duration":6},{"text":"And so this is me essentially giving you a sense of how agents unlocking are changing our perspective on memory and changing our perspective on prompting and changing what we need to be digital citizens.","offset":681,"duration":16},{"text":"Just as we needed a personal computer to be digital citizens over the 2010s, over the 1990s, over the 2000s, we need our own memory architectures to be responsible AI citizens now.","offset":697,"duration":12},{"text":"But we haven't really had a way to do that and until very recently, until the last few weeks, we haven't had AI agents that would make that really practical. Now we do, and now the world has moved and now it's time to talk about it.","offset":709,"duration":14},{"text":"So let's get specific. What am I proposing here? Instead of storing your thoughts in an app designed for humans, you should store them in infrastructure designed for anything: a real database, vector embeddings that capture meaning, not just keywords, a standard protocol that any AI can speak.","offset":723,"duration":19},{"text":"I'm calling it Open Brain because the architecture is what matters and you should not be forced to choose any given model. This is all possible because of MCP, the protocol shift that I talked about briefly above.","offset":742,"duration":14},{"text":"It started as Anthropic's open source experiment in November of 2024, but it's since become the HTTP infrastructure of the AI age, it's the USB-C of AI, it's one protocol every AI, your data is yours, it stays in one place, but every tool that speaks MCP can read it.","offset":756,"duration":20},{"text":"So at a high level, I don't want to make you go and click somewhere, let me show you what this actually looks like. Your thoughts live in a Postgres database you control, not somebody else's proprietary format.","offset":776,"duration":12},{"text":"This is the most boring battle-tested technology you can imagine. Postgres is not exciting, it's not deprecating, Postgres isn't chasing a growth metric, Postgres isn't VC-backed and needing to hit a billion dollar unicorn valuation. It's just a standard way of storing data.","offset":788,"duration":15},{"text":"And you want that boringness because everything else needs to plug into it. The nice thing about the database is that if you construct it properly, if you vectorize it, every thought you capture gets converted into a vector embedding, which means it's a mathematical representation of what it means that is immediately natively AI readable.","offset":803,"duration":18},{"text":"So when you ask, what was I thinking about career changes last month, it can find your note about how you were considering moving into consulting or how you were considering moving into product even if you never used the word career in the original thought. It's called semantic search and it's a whole different universe from Control-F.","offset":821,"duration":21},{"text":"So what this looks like when you have Postgres hooked up with an MCP server is you can type into a Slack channel, hey, I was talking with Sarah, she mentioned she's thinking about leaving her job to start a consulting business, she's been really unhappy since the reorg.","offset":842,"duration":16},{"text":"Five seconds later the system has stored the raw text, generated a vector embedding of the meaning, extracted the metadata, the people, the topics, the types, the action items, and filed all of it in a real database.","offset":858,"duration":13},{"text":"Now any AI that you're working with can go see that. If you're in Claude working on a coaching framework, hey search my brain for notes about people considering career transition, found it.","offset":871,"duration":10},{"text":"If I'm in ChatGPT drafting an email, same search same result. If I'm in Cursor building a tool and I need to remember a decision I made last week, hit the MCP server, it's right there. One brain every AI, persistent memory that never starts from zero even if you start a new tool tomorrow and you've never touched it before.","offset":881,"duration":20},{"text":"So this has two basic parts, right? Capture once through any tool you have open. You type a thought, it hits a Superbase Edge function that generates an embedding and it extracts the metadata in parallel and stores both in a Postgres database with pgvector and just replies in thread with a confirmation showing what it captured. The whole round trip takes under 10 seconds.","offset":901,"duration":22},{"text":"Retrieval runs through an MCP server that connects to any compatible AI client. You have three tools: semantic search, which is finding your thoughts by meaning, listing recent, which is browsing what you captured this week, and stats so you see your patterns, right?","offset":923,"duration":14},{"text":"You can hit this from Claude, from Claude Code, from ChatGPT, from Cursor, from VS Code, from anywhere you can query your brain through an MCP server.","offset":937,"duration":7},{"text":"If all of this sounds like Greek to you, the companion guide walks you through a complete setup. Copy-paste, no coding, about 45 minutes to set up.","offset":944,"duration":9},{"text":"And you know how I tested this? I asked someone in my life to follow this guide before I showed it to you. And she has no coding experience whatsoever and I said can you get it to a point where you can set this up. And she could and it took her about 45 minutes.","offset":953,"duration":15},{"text":"And I'm not kidding about the cost because the total running cost on the free tiers of say Slack and Superbase, which is what I'm talking about here, it's roughly a dime to 30 cents a month in API calls for about 20 thoughts a day. So you're going to spend more on coffee this morning than you're going to spend on the system this month.","offset":968,"duration":18},{"text":"Here's why getting memory at the fundamental architectural level matters beyond the nice feeling we get from building a cool tool. I love to build, you can probably tell, people who love to build will love to build anyway, but it matters for everybody, it doesn't just matter for those of us that like to experiment.","offset":986,"duration":18},{"text":"We are in the middle of a massive shift in how AI integrates into our daily work. The models keep getting better at a terrifyingly fast pace and you don't want to fall behind. Opus 4.6 shipped just a couple of weeks back, the agent market is growing probably in triple figures this year.","offset":1004,"duration":18},{"text":"Three-person engineering teams are routinely out-producing teams 10 times their size. And we're finally seeing this explosion in AI productivity show up even in economy-wide metrics.","offset":1022,"duration":13},{"text":"Erik Brynjolfsson wrote in the Financial Times last month that US productivity grew roughly 2.7% in 2025, which is double the decade average, and frankly Erik attributed a fair bit of that to AI agents and AI.","offset":1035,"duration":13},{"text":"But the key is, as I've called out before, AI adoption is not the same everywhere. If you're just talking with a single chatbot, I've said it over and over, you're not really adopting and working your workflows around AI in the way you need to.","offset":1048,"duration":13},{"text":"And the people getting those outsized results are not depending on better models to get there, they're actually restructuring how they work with AI as a primary collaborator.","offset":1061,"duration":10},{"text":"But you cannot collaborate with something that has no memory of you. Think about the difference between these two workflows.","offset":1071,"duration":10},{"text":"Person A opens up Claude, spends four minutes explaining their role, their project, their constraints and the decision they're trying to make and they get a good answer.","offset":1081,"duration":8},{"text":"Person B opens up Claude, it already knows her role, her active projects, her constraints, her team members and the decisions she made last week because all of that lives via MCP server in Open Brain. All of it is loaded up before she types a word.","offset":1089,"duration":15},{"text":"She asks for a question, she gets an answer informed by six months of accumulated context. If she wants to switch to ChatGPT for a different perspective, she'll get a different model but she'll get the same brain, the same context and the same answer quality. Every single tool will have the full picture for her.","offset":1104,"duration":17},{"text":"And the key is that advantage will keep compounding. Every thought Person B captures makes the next iteration better. Every decision logged, every person noted, every insight saved adds another node to what's a growing knowledge graph that every AI in the system can access.","offset":1121,"duration":18},{"text":"So Person A is going to start from zero every single time. The gap between I use AI sometimes and AI is embedded in how I think and work is the career gap of this decade and it comes down to memory and context infrastructure.","offset":1139,"duration":16},{"text":"And the gap is going to get wider as Person B continues to accumulate knowledge every week. The people who build persistent, searchable, AI-accessible knowledge systems will have AI that gets better at helping them over time because it has more context to work with.","offset":1155,"duration":18},{"text":"Every thought you capture makes the next search smarter, the next connection more likely to surface and that is a compounding advantage that you own, that the big companies don't own.","offset":1173,"duration":11},{"text":"Whereas the people who keep re-explaining themselves in every chat window are going to wonder why AI still feels like a party trick. It's the same tech, it's just wildly different outcomes and the variable here is your infrastructure.","offset":1184,"duration":12},{"text":"And one thing I want to call out here, I've given you a simple example where you can retrieve a clear answer in text in any AI tool you want with an MCP server, but MCP servers are not just for retrieval.","offset":1196,"duration":11},{"text":"And if you construct an Open Brain, your MCP server can work in a lot of different directions to give you advantages you might not think of if you are just used to using memory in a single tool.","offset":1207,"duration":12},{"text":"MCP means you can write directly into the brain from anywhere, I really meant that. You can write into Claude on the phone, you can use ChatGPT on the desk, you can use Claude code in the terminal, you can rig it up to a messaging app. Any MCP-compatible client becomes both a capture point and a search tool. You're not locked into Slack or any other system. That's what Open means.","offset":1219,"duration":35},{"text":"And do you know that you don't need to use code to do that, because you can just ask the AI tool of your choice to retrieve from the MCP server the relevant slice of context and build something. Because the data is stored in a way that is easy to plug in and easy to store and easy to access from any tool out there. The ceiling is wherever you decide to stop building.","offset":1254,"duration":25},{"text":"Now I want to be honest, the metadata extraction isn't always perfect. The LLM makes its best guess to classify with limited context and it will sometimes misclassify a thought or miss a name.","offset":1279,"duration":11},{"text":"It doesn't matter as much with semantic embedding because the embeddings handle so much of the heavy lifting with retrieval. Semantic search works even when the metadata is off.","offset":1290,"duration":10},{"text":"The one real requirement for this to work is that you actually use it because the system compounds. Every thought you capture makes the next search smarter and the next connection more likely to surface. But it needs input. You need to build the habit. You need to be dumping your thinking into the system and let it do the rest.","offset":1300,"duration":21},{"text":"Now if you're a subscriber on the Substack I've put together four prompts that cover the full life cycle and I actually want to describe them in the video because even if you're not a subscriber you should understand how we can use prompts in the architecture of this system to think more deliberately and make the memory architecture fit our needs.","offset":1321,"duration":20},{"text":"The memory migration is the first thing I'm going to suggest. You want to run this right after setup. It extracts everything your AI knows about you already from Claude's memory, from ChatGPT's memory, from wherever you've accumulated context and it saves it into your Open Brain.","offset":1341,"duration":14},{"text":"Every other AI you connect then starts with that foundation instead of zero. So you want to run it once and let it pull that stuff down.","offset":1355,"duration":9},{"text":"I'm also building what I call the Open Brain Spark because I sometimes get writer's block. So you want to have an interview prompt that discovers how the system fits your specific work. It asks about your tools, your decisions, your re-explanation patterns, your key people and then generates a personalized list organized by category that suggests what you should be putting into Open Brain regularly.","offset":1364,"duration":25},{"text":"Use it when you're staring at the Slack channel or you're staring at your messaging app or you're staring at ChatGPT and you're wondering what do I type that I want to put into Open Brain today.","offset":1389,"duration":8},{"text":"I also put together quick capture templates, so these are five sentence long starters optimized for really clean metadata extraction. So a decision capture prompt, a person note, an insight capture, a meeting debrief. Each one is designed to trigger the right classification in your processing pipeline.","offset":1397,"duration":19},{"text":"And after a week of capturing you'll find you don't need them as much because you're going to develop your own patterns. But they're really useful for building that habit early without having to think about how to sort of send the system a coherent message where it's likely to classify correctly.","offset":1416,"duration":15},{"text":"The weekly review is another one I put together. End of week synthesis across everything you captured. It clusters by topic, it scans for unresolved action items, it detects patterns across days, it finds connections you missed and it identifies gaps in what you're tracking.","offset":1431,"duration":15},{"text":"So about five minutes on a Friday afternoon becomes more valuable every week because your Open Brain continues to grow.","offset":1446,"duration":8},{"text":"If we zoom back out, when this thing works, when you get the Postgres database set up, you're starting to use it in whatever messaging app you want, you're starting to see the memory become consistent across all your AI tools and you're starting to realize you do not depend on proprietary paid-for memory by big AI companies, something happens that's a little bit hard to describe until you experience it.","offset":1454,"duration":27},{"text":"Your AI in every single part of the system, whether you're using Claude or ChatGPT or both or Cursor or Grok, whatever it is, it starts to know you. Not in the creepy corporate surveillance way, in the, hey, we were thinking about this last week and it's relevant to what you're asking me now kind of way. The way a great colleague remembers what matters.","offset":1481,"duration":20},{"text":"So every AI you use gets better. You're less afraid of trying a new AI because you can just plug it into MCP and it finally has the context.","offset":1501,"duration":11},{"text":"This is what an agent-readable world makes possible, and I want to call out something really special here. When I suggested the original Second Brain guide, I built it before the agent revolution went mainstream, which again was only about a month and a half ago, a month ago.","offset":1512,"duration":-1184},{"text":"And it was useful for humans, and it was designed to solve a fundamental cognitive problem that we've had, which is that we have trouble holding stuff in our head and we need to see patterns over time. LLMs can help us assess patterns. That's all still true, and you can use this Open Brain in that way.","offset":328,"duration":1219},{"text":"But when the agent revolution came through in the last few weeks, because again AI is moving that fast, what we need to move to is a second brain system that is more foundational. Something that enables both us and our agents to reliably read from a system that isn't SaaS-controlled, that isn't proprietary company-controlled, that is frankly open source LLM-friendly.","offset":1547,"duration":24},{"text":"And when we have that, we get two benefits. Yes, the agent can read it and that is in line with where we're going with agents and how quickly agents are going mainstream and that's the reason I'm making this video.","offset":1571,"duration":12},{"text":"But second, look at how much cleaner and clearer the human-readable part of this gets. We get downstream benefits that we did not get when we think about the system from only a human-readable perspective.","offset":1583,"duration":17},{"text":"Because if you think about the system from a human-readable perspective, you get something like what I described. You focus on SaaS-friendly solutions with graphical user interfaces that humans can easily read because you want to make it easy and accessible to build the system.","offset":1600,"duration":16},{"text":"And that's what I did originally. But if you're willing to get slightly technical and follow a clean step-by-step tutorial to get to something that is a true database, what you get is a future-proofed system that unlocks the human benefit of touching any AI system in the future that you might want to try without doing any additional effort.","offset":1616,"duration":27},{"text":"And so we humans reap a tremendous amount of value from the clarity that comes from a truly foundational architected memory system.","offset":1643,"duration":12},{"text":"This reminds me of one of the larger lessons I've been meditating on in the AI revolution, which is that AI is forcing a clarity of thought in our work, in our lives that has a tremendous amount of human benefit.","offset":1655,"duration":16},{"text":"Tobi Lütke has said that he thinks a lot of corporate politics amount to bad human context engineering, which is a very provocative take. And I think that that is something that pops out here, because we need extraordinary clarity to work with AI agents.","offset":1671,"duration":19},{"text":"And when we develop that extraordinary clarity through memory architectures that are foundational, through good databases, through a clean MCP server, we get the benefit of cleanly and clearly being able to plug in and work with that memory system anywhere.","offset":1690,"duration":18},{"text":"We do good context engineering for our human brains when we build the right context engineering for AI. Which is kind of Tobi's point about politics. When we do good context engineering for agents, we happen to do good context engineering for people, and that makes people less likely to play politics.","offset":1708,"duration":16},{"text":"So the second brain you build, if you were one of the thousands of people that built it when I talked about it, was always reaching for this. It was reaching for a place where your thinking lives, where it's searchable by meaning, where it's accessible to any tool you use.","offset":1724,"duration":13},{"text":"And those tools solved the capture problem, they solved the organization problem, but what they didn't realize they needed to solve, because it wasn't really there yet, was the agent-readable problem.","offset":1737,"duration":11},{"text":"Open Brain adds that foundational layer, not by replacing what you built, but by giving it an infrastructure underneath. A database, a protocol, your thoughts, every AI you'll ever use.","offset":1748,"duration":13},{"text":"So you can build it in a morning over coffee this weekend. Yes, really, you. And your future AI, your future self as a human will thank you for every thought you start to capture now.","offset":1761,"duration":13},{"text":"If you have already built a second brain, I'm also including a special migration guide so that you can figure out how to not lose the thoughts you've been capturing and make sure you get them into a system that is more agent-readable going forward.","offset":1774,"duration":16},{"text":"Best of luck. Don't be afraid of how this is slightly technical. There've been lots of visuals all the way through this YouTube helping you to see what I mean and you'll see more guides in the Substack if you're interested.","offset":1790,"duration":11},{"text":"And honestly, I put enough visuals into this video that if you are not ready to hop into the Substack, totally fine, you should still be able to get there. You should be able to show this video to an AI and say help me build this and it should be able to do it. Cheers.","offset":1801,"duration":15}],"logs":[{"elapsed":"0.0","message":"Downloading audio from YouTube...","detail":null},{"elapsed":"0.0","message":"Trying download with browser cookies (ad-free)...","detail":null},{"elapsed":"3.7","message":"⚠ Cookie download failed: WARNING: [youtube] [jsc] JS Challenge Provider \"deno\" returned an invalid response: response = JsChallengeProviderResponse(request=JsChallengeRequest(type=, input=NChal","detail":null},{"elapsed":"3.7","message":"Retrying without cookies...","detail":null},{"elapsed":"31.9","message":"⚠ Downloaded without cookies — audio may contain ads","detail":null},{"elapsed":"31.9","message":"Audio downloaded (18.3 MB) in 31.9s","detail":"File size: 18.3 MB"},{"elapsed":"35.8","message":"Uploading audio to Gemini File API...","detail":null},{"elapsed":"40.9","message":"Audio uploaded in 5.1s","detail":"File ref: files/1tjdszblq0dy"},{"elapsed":"40.9","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"106.8","message":"Transcription complete in 65.9s","detail":"30919 chars received"},{"elapsed":"106.8","message":"Transcription tokens: 45,607 in / 7,408 out — cost: $0.0450","detail":null},{"elapsed":"106.8","message":"Parsed 121 transcript segments","detail":null},{"elapsed":"106.8","message":"Analyzing topics across 121 segments with gemini-3.1-pro-preview...","detail":null},{"elapsed":"180.8","message":"Topic analysis complete in 73.9s — found 10 topics","detail":null},{"elapsed":"180.8","message":"Analysis tokens: 8,071 in / 837 out / 4,199 thinking — cost: $0.0766","detail":null},{"elapsed":"180.8","message":"Pipeline finished in 180.8s — total cost: $0.1216 (66,122 tokens)","detail":null}]} \ No newline at end of file diff --git a/history/1773021528170-MjczYmIzZjgtZjg1.json b/history/1773021528170-MjczYmIzZjgtZjg1.json new file mode 100644 index 0000000..9f8bb24 --- /dev/null +++ b/history/1773021528170-MjczYmIzZjgtZjg1.json @@ -0,0 +1 @@ +{"id":"1773021528170-MjczYmIzZjgtZjg1","videoId":"273bb3f8-f85a-4056-bbed-049976af4406","url":"https://serve.podhome.fm/episode/8029725b-0319-44b9-4793-08dc404e83a4/639084369127469757273bb3f8-f85a-4056-bbed-049976af4406.mp3","title":"CD193: FIPS - FIXING THE INTERNET","type":"podcast","topicCount":19,"segmentCount":161,"createdAt":"2026-03-09T01:58:48.170Z","uploadDate":"20260306","chunks":[{"title":"Introduction and Show Updates","summary":"Odell opens the show, provides the current Bitcoin block height and price metrics, and encourages viewers to support and share the podcast.","entries":[{"text":"[Music]","offset":0,"duration":32},{"text":"Odell: Happy Bitcoin Friday, freaks. It's your host Odell here for another Citadel Dispatch, the show focused on actionable Bitcoin and freedom tech discussion. Today is Friday, March 6th at 22:00 UTC. The current Bitcoin block height is 939631. Sats per dollar 1465. Current US dollar price is 68,239. I told you freaks I’m gonna go with the price priced in gold now as well. Priced in gold: 13.97 ounces of gold buys you a Bitcoin. We're outperforming gold on the week, but not on the day, the month, or the year. But we will eventually, hopefully, expecting, we’ll see.","offset":32,"duration":42},{"text":"Odell: As always, Dispatch is funded by our viewers. Viewers like you, thank you guys for supporting the show with your hard-earned Bitcoin. We have no ads or sponsors. Uh, this was—I’m trying to do as many shows as possible that are high signal for you freaks, so this one was two days after the last one. It seems like no one has supported the show in significant size, so I don't really have anything to read out, but thank you to everyone who does support the show. Uh, an easy way to support the show without sparing your hard-earned sats is sharing it with your friends and family. Citadel Dispatch is available on every major podcast app. All relevant links at citadeldispatch.com.","offset":74,"duration":46}],"startTime":0},{"title":"Introduction to FIPS and the IP Problem","summary":"Arjen introduces the Free Internetworking Peering System (FIPS). They discuss how the protocol solves the problem of IP addresses changing when users switch internet providers within mesh networks like Tollgate.","entries":[{"text":"Odell: Anyway, freaks, I have a great show today. We are going to be talking about the recently announced FIPS project, which I believe stands for Free Internetworking Peering System. Um, and it’s basically the idea of, of building the internet from the ground up, uh, without all the middlemen bullshit that is involved in the current internet setup, using Nostr at its core. It's a little bit above my pay grade, so we’re going to be diving in deep here. And if I can understand it, then at least some of you can understand it. And we have Arjen here, one of the main contributors. How's it going, Arjen?","offset":120,"duration":39},{"text":"Arjen: I’m good. Thank you for having me.","offset":159,"duration":2},{"text":"Odell: Was my basic explanation decent?","offset":161,"duration":3},{"text":"Arjen: Yeah, I think so. I think so.","offset":164,"duration":2},{"text":"Odell: What is FIPS?","offset":166,"duration":2},{"text":"Arjen: So, FIPS is an attempt to, uh, do networking in a way that doesn't require any, any authority to be involved. The need actually came from, uh, from Tollgate where, um, you know, we, we pay for internet access for, uh, but if you have a system where, you know, you can pay other people to peer with them, basically, you need, you can switch between the people. So, if you switch, the person you’re buying your internet from, what happens in the current structure of the internet is that you lose your IP address, it changes, and that’s okay if you’re reaching out to the outer world, but that’s not okay if you want to host anything inside such a network.","offset":168,"duration":53},{"text":"Odell: Yeah. So first to pull back, Tollgate is this project that allows you to basically sell your Wi-Fi for sats and then people are able to access it. And then in the traditional internet infrastructure, we have internet service providers, we have DNS providers, we have all this different, all these middlemen that are involved in networking everyone together. And our IP address is our quote-unquote identity, I guess, on the internet. And a lot of home internet, I guess, their IP addresses do change a decent amount. Sometimes they change, sometimes they don't. But if you’re, like, hosting a website or something, you basically need a fixed IP address, right?","offset":221,"duration":33},{"text":"Arjen: Exactly, yeah.","offset":254,"duration":1}],"startTime":120},{"title":"Decoupling Routing From Physical Transports","summary":"The discussion shifts to how FIPS separates the physical transport layer from the routing layer. This allows peers to connect seamlessly across different broadcast mediums like Wi-Fi, Ethernet, and Bluetooth.","entries":[{"text":"Odell: So FIPS, yeah, so continue.","offset":255,"duration":3},{"text":"Arjen: Yeah, so, so in a, in a Tollgate network, right, the, the way we envisioned it first is like, okay, you have someone that is connected to the legacy ISP, if you will. And from there on out, you start reselling that internet, and someone can buy it from you and they start reselling it. That assumes a tree structure where someone’s on top and someone’s at the bottom. But if you have a network that grows and like, say, you’re two, three steps down, and there’s someone that actually gives a better price for that connection and you’re going to switch over, everyone below you is going to lose their, lose that structure that was there to define them inside that network.","offset":258,"duration":41},{"text":"Odell: Right. So in this situation, everyone has a Nostr public key-private key pair, which you can spin up relatively easily. That's your public identity. And then this is why I think it's fascinating because conceptually, high level, it makes a lot of sense to me. So then you’re able to just connect peer-to-peer between those public keys without anything else. So I can be connected via Wi-Fi or Bluetooth, I can run a long-ass Ethernet cable to my neighbor, and he could run a long-ass Ethernet cable to his neighbor, and we’d all be connected to each other, and then one of them could then have, like, some kind of long-distance mesh to someone else, and then you can continue and all that networking would work natively with Nostr. That all seems awesome, high level. How, but how is that possible? That doesn’t, like, what's the nitty-gritty that actually makes that a reality versus just something that just seems really cool in a, in a tweet?","offset":299,"duration":52},{"text":"Arjen: It is just by, by decoupling two layers, if you will, the, the physical transport layer and the routing layer. In a lot of cases, they’re very interconnected. Right, if, um, we have internet, like, IP traffic, it presumes, um, that it uses Ethernet, basically Ethernet or Wi-Fi. Um, it doesn’t run over Bluetooth. And every different protocol kind of has its own way of doing that. And what we found is it’s better if you have something that works across it and just, um, show, expose some interfaces to the layer below where it doesn’t matter how it works. All you need to know is just I want to be able to send some data to a peer and I want to be able to get some data to a peer. I don’t care how you get it there, just get it there. If it’s Ethernet, right, you use the Ethernet protocol or Wi-Fi. If it’s Bluetooth, you use Bluetooth underneath, but the FIPS protocol doesn’t have to, doesn’t care about that.","offset":351,"duration":60},{"text":"Odell: But then how does discovery work?","offset":411,"duration":3},{"text":"Arjen: That depends on the layer you use, or the transport you use. If you use a broadcast medium, say Wi-Fi, you can broadcast the fact that you’re a FIPS node and that you want to peer with people. That way people can discover you and send messages back.","offset":414,"duration":18}],"startTime":255},{"title":"Hypothetical Global Routing and Discovery Servers","summary":"Odell and Arjen explore how FIPS could hypothetically route traffic across the globe. They discuss the potential use of specialized Nostr relays or discovery servers to find routes without relying on a central authority.","entries":[{"text":"Odell: Okay, work with me here on, uh, hypothetical, 'cause it—I understand hypotheticals better. Uh, let's say you're successful, this project is a smashing success, and it's five years in the future. Um, you’re in a different country than me. I have your public key. I want to send you information. How, how does me pressing enter on my side get to you?","offset":432,"duration":32},{"text":"Arjen: If we are on the other side of the world, that is a problem we hope that we’re going to run into with, um, people using it. Uh, we’re nowhere near that yet. But I, I think the, one thing that can help us with that, where, um, if you do mesh without the cryptographic identities and Nostr keys for that matter, I think we can use nodes that are somewhere in between that can help us route that traffic. But this is two-step, two, three steps ahead and like, routing further away.","offset":464,"duration":24},{"text":"Odell: So are these, are these similar to, like, what a DNS server currently is? How does that look?","offset":488,"duration":6},{"text":"Arjen: Yeah, in this instance, it would be something like that. Like, uh, you would maybe publish something to the—it's very theoretical. You would publish something to, say, a Nostr relay that is specialized in this, right? You can use your, you can use your Nostr keys to sign something and like how people can find you. But you can do it in a way where there’s not one party involved, it's like one central authority you look at, like how does that traffic go from A to B, uh, but you can send it to multiple people.","offset":494,"duration":32},{"text":"Odell: So the difference would be from the modern-day setup is that it'd just be more accessible to run these kind of discovery servers or whatever you’re calling them. Like, anyone could basically run one and there, there wouldn't be, like, lock-in. Maybe? Am I reading this correctly or...?","offset":526,"duration":13},{"text":"Arjen: Yeah, if you would use something like this, yes. Um, but I think we should backtrack a bit first, like how the, how it works.","offset":539,"duration":6},{"text":"Odell: Let's backtrack, yeah. Whatever you think is best.","offset":545,"duration":3}],"startTime":432},{"title":"Local Mesh Discovery and Cross-Transport Uplinks","summary":"Arjen details how local peers discover each other and encrypt traffic hop-to-hop using Nostr keys and Bloom filters. They also discuss bridging isolated mesh networks via Starlink and UDP connections.","entries":[{"text":"Arjen: In the local level. Um, so on the local level, you discover a peer, um, and you encrypt, like, you advertise your own pubkey, right? The peer advertises his pubkey. You can immediately encrypt something to that pubkey, so there’s a handshake there where the two peers use a noise protocol to establish an encrypted connection. And every peer does that amongst each other, and so every hop of the way is individually encrypted. And then on top of that, there is the, the longer routing of, like, the longer routes. And the way you can find another peer within the mesh, say, like, a mesh up to 10,000 people, oh shit, is that every peer holds a Bloom filter of the people that they can reach. So if you connect to a peer that can already reach, say, like, 10,000 other peers, it will give you a Bloom filter, which is a very compressed, uh, version of a list of npubs that it can reach. It's just one kilobyte at this moment. You get that, and then whenever you get a packet that’s for any of those 10,000, you know that that peer that’s on your left-hand side can actually reach it.","offset":548,"duration":76},{"text":"Odell: Got it. So in practice, each peer is like, almost like a DNS server?","offset":624,"duration":8},{"text":"Arjen: Um, I think it’s hard to make that comparison because it's not—it's, it's a different—it's a different way of doing things.","offset":632,"duration":12},{"text":"Odell: Right, it's fundamentally different. But each peer is also my method of discovery?","offset":644,"duration":6},{"text":"Arjen: Yes. In a smaller local mesh, that is the way you found other people.","offset":650,"duration":6},{"text":"Odell: Yeah, I mean, you can, this is a interoperable way of rolling out, like, a local community mesh relatively easily.","offset":656,"duration":6},{"text":"Arjen: Yeah, yeah. And that's honestly, that's if only that works, I would already be very happy because you can roll this out in a community, you can host servers, right? You can, you can host things on an npub that can even physically move around in a network, and if the network gets cut off from the rest of the world, everything just keeps working. You can do it if, you know, part of the network fails, you go over Bluetooth, uh, whatever works. Whatever method you have available, that’s how you want to route the traffic.","offset":662,"duration":29},{"text":"Odell: It's completely agnostic. And some peers can be on Ethernet, some could be on Wi-Fi, some could be on Bluetooth. Doesn't matter.","offset":691,"duration":7},{"text":"Arjen: Yeah, or even satellite uplinks.","offset":698,"duration":4},{"text":"Odell: Now, what if one person—have you guys, is it in scope of the project if, like, one person has Starlink, for instance? Would then the whole community have broader internet access or no? Is that...?","offset":702,"duration":11},{"text":"Arjen: Yes, you can, so if you use Starlink, you are using the, uh, regular internet stack, IPs, but you can establish peer connections over, over the internet. So if I have a mesh here in my house and you have one in your house, uh, we can establish a link over UDP and connect the mesh that way.","offset":713,"duration":21}],"startTime":548},{"title":"Circumventing Authoritarian Network Shutdowns","summary":"Using the Iran protests as a case study, Odell highlights how FIPS could help communities survive internet blackouts. The protocol allows users to maintain local communications while automatically discovering tunnels to the global internet.","entries":[{"text":"Odell: Yeah, I mean, 'cause like, in practice, so let's use a real-world example, right? The internet—the government of Iran cut the internet relatively recently. I don't know if the internet's on right now or if it’s off. But at least during the protests a couple weeks ago, uh, now we have war in Iran. But, uh, during the protests a couple weeks ago, uh, government internally cut the internet because they didn't want communication among the protesters. It's something we see happen all the time. And as a result, Bitchat usage spiked in the country. Now, Bitchat has its own issues, right, in terms of range and whatnot and capability. But the biggest one that I kept thinking about is those people could communicate internally, which is great, still an advantage, you know, it's better than the alternative which is no communication internally. But they couldn't, for instance, broadcast to the rest of the world and be like, this is what’s happening on the ground right now. There was a fog of war that was happening and, and that was part of the government's design. That's why when you see large protest movements happen in different places, authoritarian governments often cut the internet. Now, the dream high level in my mind has always been you have, like, local meshes and then one person smuggles in a Starlink and then all of a sudden the entire community can broadcast globally on Nostr, for instance, and say, you know, here's a video of the police abusing us or whatnot, or corruption or whatever they’re trying to get out. Presumably this project should be able to offer that kind of capability, no?","offset":734,"duration":88},{"text":"Arjen: Yes, because you can introduce, basically, say, quote-unquote a tunnel to the rest of the world from anywhere, and that would automatically be discovered by the network. So if, yes, you have a Starlink that goes up and, right, goes down in another country and you have a mesh there, well, as long as you knew one of the npubs that was on the other side of the mesh before it got cut off, you can actually find that route again.","offset":822,"duration":22},{"text":"Odell: That's awesome. I mean, have you talked to the, have you talked to the Bitchat guys at all or...?","offset":844,"duration":9},{"text":"Arjen: Uh, no, we just, uh, we just released it, actually, so it was two weeks—two weeks ago, uh, I just met—the idea has been around for, for a little while, and I met Jonathan just in last November, and we kept talking, talking about the idea, and, uh, so that slowly developed over the last few months, and just the last couple weeks we had a, had a working working demo.","offset":853,"duration":23}],"startTime":734},{"title":"FIPS Origins, Sovereign Engineering, and NoDNS","summary":"Arjen shares the backstory of meeting Jonathan and developing FIPS. They discuss Arjen's time at Sovereign Engineering and his previous work on NoDNS, which pioneered using Nostr pubkeys as static identifiers.","entries":[{"text":"Odell: That's awesome. Did you guys, did you guys meet at Sovereign Engineering?","offset":876,"duration":4},{"text":"Arjen: No, at a conference in Costa Rica. Uh, there was this conference for Nostr conference, and I think, yeah, it was two days and the only thing I did is basically sit in a room with him talking about these ideas on doing addressing with, with npubs instead of, instead of IP or for DNS as well.","offset":880,"duration":20},{"text":"Odell: So what is the Sovereign Engineering connection? I—Justin Moon introduced us. I believe he met you at Sovereign Engineering?","offset":900,"duration":6},{"text":"Arjen: Yeah, correct, yeah.","offset":906,"duration":1},{"text":"Odell: What was the Sovereign Engineering experience like? I mean, I love what those guys are doing. I haven't been myself, but I work closely with Gigi at OpenSats and he’s heavily involved in Sovereign Engineering. I think it’s a fascinating program.","offset":907,"duration":13},{"text":"Arjen: Yeah, so some of the, the original idea on, like, addressing with npubs is something I worked on at Sovereign Engineering last year. Uh, it came from the ideas like if we can use npubs to address services instead of IP addresses or traditional domain names, then at least we have a static identifier we can use across the web to reach things even if the IP address changes. Um, that experiment turned into what's called now, uh, NoDNS, where someone signs cryptographically on in a Nostr message all the, um, DNS records, publishes that, and other people can resolve that as DNS. So that’s kind of the, the predecessor of this idea. We can do it inside the IP network. You still have that structure, but when it changes, you have some flexibility on correcting that, similar to if an IP address changes now, you use update the DNS record and people can reach you again. You can do it much faster this way, that’s nice, but it doesn’t resolve the, the entire issue.","offset":920,"duration":62},{"text":"Odell: I didn't realize, so Tollgate is your project as well?","offset":982,"duration":5},{"text":"Arjen: I work on it as well, yeah.","offset":987,"duration":1},{"text":"Odell: Yeah. So Toll—you were in Sovereign Engineering for Tollgate specifically?","offset":988,"duration":4},{"text":"Arjen: Uh, the first one I was at, Sovereign Engineering 3, I didn’t know much about Tollgate back then, but I met the guy that started it, and from there on we started to basically rolled into it and we started to, uh, work, work on it together.","offset":992,"duration":18}],"startTime":876},{"title":"Routing Incentives and DDoS Defense Mechanisms","summary":"The conversation explores integrating economic incentives into FIPS so users can pay for cheaper or faster routing. Arjen also explains how hidden npubs and connection rate-limiting serve as native DDoS protections.","entries":[{"text":"Odell: I think it's a super cool project too. I so the the whole premise of Tollgate is that I’m, I’m paying sats for internet access. Are sats involved in FIPS at all? Like, are people, are people using—is the idea that people will be paying for peering, or have you thought about that at all?","offset":1010,"duration":21},{"text":"Arjen: Yeah, that, that’s my hope for sure. Like, the whole reason FIPS exists is because, um, we don't have a way to do this dynamic, uh, this dynamically changing network. So I think it's a very—payment is a very important part of it because you want to be able to steer traffic based on economic incentives as well. So if say one link is very expensive and the other is cheap, well why not, if you pay for that connection, why not incorporate that in your routing decisions as well. But that’s a—that’s definitely a next step. But it can be, can be combined.","offset":1031,"duration":33},{"text":"Odell: I mean, and wouldn’t something like that be necessary because—have you thought at all about DDoS concerns or, or any kind of malicious attacker trying to flood the network or break down the mesh?","offset":1064,"duration":16},{"text":"Arjen: Yeah, there’s, um, there's a couple things there. The mesh when, when joining the mesh, uh, physically, you need to do that with a peer, so, and that peer it will be, uh, rate-limiting how many people can connect at the same time. So that’s, that’s one defense. Another defense is that to send traffic to an endpoint, you need to know the npub because on the routing layer, uh, the nodes don’t know for the packets they send, they don’t know the npub. They only know a node ID that is derived from the npub. So that provides some protection. If your npub is not known by the whole world, it's hard for someone to DDoS you.","offset":1080,"duration":40},{"text":"Odell: Interesting. Because that would be the attack, right? If we were going to go down our hypothetical and you're in Iran and the government's shutting down the internet, they would try and jam different types of signals, I guess, and then also they would presumably just spin up, spin up npubs, right, and just start spamming the network.","offset":1120,"duration":21},{"text":"Arjen: Yeah. I mean, it’s a—it's definitely not a—not an easy problem to solve, right? That’s, it’s not fully solved in the current internet.","offset":1141,"duration":8},{"text":"Odell: Yeah. Probably the hardest problem set.","offset":1149,"duration":2},{"text":"Arjen: Well, the current internet just solved it with centralization, right?","offset":1151,"duration":4},{"text":"Arjen: Yes, yeah, you have Cloudflare to do these things.","offset":1155,"duration":5},{"text":"Odell: Which is just a massive middlemen honeypot. And then also just internet infrastructure in general, right? There’s, like, a million central points of failure that can be pressured and shut down. That’s why authoritarians can, I mean, it’s not as simple as it, but basically click a button and cut off the internet for the entire country, right?","offset":1160,"duration":17},{"text":"Arjen: Yeah, yeah. So, um, that’s why an internet that is, that is designed to fracture and recombine is, is very useful.","offset":1177,"duration":9}],"startTime":1010},{"title":"Backwards Compatibility and Seamless App Integration","summary":"Odell asks how FIPS overcomes the bootstrapping problem. Arjen delivers a 'mic drop' explanation of how a custom DNS server intercepts packets and issues deterministic IPv6 addresses, allowing unmodified apps to use the network seamlessly.","entries":[{"text":"Odell: Well, what I like about this is it's very pragmatic because one of the trouble—like, mesh is something that I've been fascinated with for maybe a decade. And there's been many different attempts at doing different things. Um, I think it was, it was exciting that and obviously partially it was because of Jack Dorsey tweeting it out, but the excitement around Bitchat. But it was also kind of weird, right, because if you'd actually been following the mesh space for a while, like people were acting like it was the first mesh project that ever existed, but there was a million predecessors that failed beforehand. And always the problem—well, not always, there’s many different, you, like you said, it's very hard problem to solve. But one of the core problems I feel like is this bootstrapping issue, where, you know, you need a critical mass of at least your neighbors to be using it for it to be useful, right? I, and people saw with Bitchat, right? It’s like they would download Bitchat, and then it was just nobody to talk to, right? Because you don't have neighbors that also download Bitchat. And there's different ways of solving it. You know, it's easier in cities. I like the idea of being in a, in a—like a sports arena or something that already has poor internet, and maybe in a sports arena everyone wants to talk about the same thing. They're all watching the same game, they all want to talk about the same game. It’s a high-density group of people. You could see it being really useful in that situation, a concert, a music festival. Um, but at scale, to actually, like, see it work at scale, um, it's a just a really hard problem. But one of the things that I've thought about historically is if you could bootstrap it in a way that it works with modern internet infrastructure until the modern internet infrastructure isn't needed anymore, then that makes it way more useful. Because if we’re in different parts of the world but we can use this tech to communicate because of the existing internet infrastructure, then all of a sudden it's useful today without actually having the build-out of people interconnected all the way between us or whatever, right? Does that make sense?","offset":1186,"duration":125},{"text":"Arjen: Yeah, yeah. And there's, um, there’s a couple things to unpack there too is that I really hope we can, when nerd-snipe the, the people from Bitchat into this. Because if, you know, if you run a mesh that is cross-transports, you can lower the burden of making apps like Bitchat because now Bitchat needs to design its own protocol on like how over Bluetooth the app, apps are going to talk together, whereas if it was just you can just send TCP/IP traffic like through this, like any existing application like a relay and a, and a Nostr app, then you can do this over Bluetooth without having to specifically design the app to also support that.","offset":1311,"duration":41},{"text":"Odell: Can we go a little bit deeper there? How does that look in practice?","offset":1352,"duration":5},{"text":"Arjen: So, say you would have, you would run a FIPS network and every phone has, has it running and is peering with each other over both Wi-Fi and Bluetooth, some people are only Bluetooth. Now on these phones, you can host, um, something like a Nostr relay. Now everyone can reach that relay over a npub.fips address from any app on their phone. So now they don't need a app that is specifically designed to be a Bluetooth app, it can just be like any other app and not have to put in any effort to, to do this. And so you don't just have one app that can do this, but you have pretty much everything under the sun that would work if, if it uses infrastructure like Nostr relays that are really good at, um, facilitating so many use cases at once.","offset":1357,"duration":47},{"text":"Odell: But so how does that look in practice for like an app developer? How would they integrate in that situation?","offset":1404,"duration":7},{"text":"Arjen: Um, so if I would, say, like White Noise, right? Bitchat app. White Noise connects to Nostr relays. White Noise does what White Noise does best, like do all the encryption, do all the rotation, group management, but they might not want to put so much effort into making a Bluetooth mesh. If they, if someone that uses their app on their phone also connects to a FIPS network, they can just configure a relay like they always would, saying npub.fips in the relay, in the relay list. Then they can already talk to that relay that’s on FIPS. Now if they then move around inside that mesh, and other people join, they go from Bluetooth to Wi-Fi, they can still reach that relay that is elsewhere in the network. So they don’t have to change their app to work over Bluetooth.","offset":1411,"duration":59},{"text":"Odell: But they have to add FIPS support specifically though, right?","offset":1470,"duration":7},{"text":"Arjen: No, that's the—that’s one of the things that I really wanted in here is a—I should have mentioned it earlier—is a system where it works for existing applications that expect the IP stack to work. Because I looked at some of the other protocols, and what I found is the, they often seem to expect everyone to re-implement all their applications to work with it. But there’s no way in hell you're going to get any adoption if everyone needs to rebuild their stack from scratch. There’s, there’s 40 years of history in libraries, etc. Unless it works from scratch or like without any modification in all the applications, it’s not going to fly. So the way this works is we add a custom DNS server together with FIPS, the FIPS daemon. What happens is if any application on your, on let's say with computers for now, any application on your computer asks for npub.fips, what that DNS server does is it gives you back an IPv6 address that is deterministically derived from that npub, which is the same as the node ID of the destination.","offset":1477,"duration":70},{"text":"Odell: That's wild.","offset":1547,"duration":1},{"text":"Arjen: And then the application will send its traffic like it always would, right? It's going to, in my browser it's going to be HTTP becomes TCP becomes IP packets. And then down at the bottom where, you know, the system would send it out as an IP packet, we know we just generated that IPv6 address, so we intercept it and actually send it over FIPS instead. And the app just thinks it’s using the regular internet.","offset":1548,"duration":27},{"text":"Odell: Yes. So that’s what we’re focusing on most now is like all the applications, right? Ping, when I did the first experiments in Sovereign Engineering, Sec5, I found is like, okay, I make something like this. And now I have to rewrite, fucking ping app—excuse my French—the ping application. I’m not going to do that. Like, no one’s—no one in hell’s going to rewrite everything from scratch. So it has to work with everything that we already have.","offset":1575,"duration":27},{"text":"Odell: That's awesome. I mean, I think that's the key, right? That's the key for bootstrapping, then you don't even have the app developers don't have to change a thing.","offset":1602,"duration":15},{"text":"Arjen: Yeah, I think, I think that's a must-have. I don't think anything like this can, can scale if it doesn’t, isn’t backwards compatible.","offset":1617,"duration":10}],"startTime":1186},{"title":"Local Network Resilience and the Offline Spectrum","summary":"FIPS envisions a network where local services like Bitcoin nodes and Cashu mints remain fully operational even if the broader internet goes down. Nostr's verifiable data allows nodes to gracefully reconcile information once reconnected.","entries":[{"text":"Odell: Okay, I mean, I don't know where to go from here. That's like a mic drop moment for me. I mean, if this works, it seems like it's kind of the holy grail that you stumbled on here, sir. I mean, I’m reading through your Git repo. What do you want to cover? You know better than me. I, by the way, huge shout out to Justin Moon. He set up this conversation. I told him to join for it. He said he was unnecessary. I think he would have been very helpful.","offset":1627,"duration":28},{"text":"Arjen: We can, we can still try to get him in.","offset":1655,"duration":4},{"text":"Odell: What do you want to talk about? What is, what is most interesting to you here? You have thousands of people listening to this show. What do you want to talk about?","offset":1659,"duration":9},{"text":"Arjen: I think, I think the opportunity to make the internet in this general—like, FIPS doesn’t have to replace the internet if for, like, long-range stuff, right? If we’re necessarily. If we’re doing a call like this, it's fine if that still exists, like the hierarchy there, we’re not, you know, that’s not going to change quick. Um, I think it already wins if it works local. And that’s exactly, I think the most exciting thing is like if it works local with, say, half a million people or a million people, you don’t even need the traditional internet—the traditional way of doing things is we go out, like when we visit a website, right? I go to amazon.com. The way it works now is I send a message to Amazon saying, go fetch, go fetch, go fetch. And I think in a world with Nostr where everything, everything in Nostr is a stream, all the data is signed, so we can do replication wherever needed. So what we can do with that is we collect information once, we pull it inside the network that we have here, and from there on out it doesn’t matter if that connection to the outside world gets severed because the information’s already inside the network on the relays. And then from there, we can spread that information. So I think if we have a decent way of hosting that stuff inside this network that can rearrange and is resilient, then it doesn’t matter as much when connections outside are, are unstable. Like, you’ll just pull in the new stuff whenever you have a connection. And if not, you go about your day and do your things inside your network. You can run your Bitcoin nodes, your Cashu mints, uh, Nostr relays and Blossom servers in the, in your town and the main cable gets cut. Well, okay, it sucks, but you can still chat with whoever you want over all the, over White Noise. You can still use, um, Primal, right? And then what—and then the key is when that cable gets uncut or whatever, I don’t know what the opposite analogy is, when you get reconnected, you can gracefully reconnect to the water network.","offset":1668,"duration":130},{"text":"Arjen: Yeah, and then you can see like what was gone, what is not, right? That boundary Nostr allows us to, to completely remove the boundary between what is offline and online is, becomes a spectrum of offline and online. Like, offline is I don’t have anything on, I don’t have a relay on my computer, I don’t have a Blossom server on my computer, and I’m not connected to any other node. Then I’m offline. Whereas like you can be a little bit online where you have one other node peering some info, right, like shades of grey. Yeah. So there’s no—and then everything because of Nostr, everything’s signed, it’s all verifiable, you can gracefully reconcile afterwards. Yeah, so the way information flows I think will dramatically change in a Nostr world.","offset":1798,"duration":48}],"startTime":1627},{"title":"Current Testing Status and MTU Limitations","summary":"Arjen calls for developers to test and break the newly released protocol. They discuss physical hardware limitations, noting that FIPS must account for the Maximum Transmission Unit (MTU) sizes of various communication channels.","entries":[{"text":"Odell: What are the, what are the hurdles you face? Like, what are the trade-offs here? Like concerns, what are the dealbreakers? How are you thinking about that?","offset":1846,"duration":10},{"text":"Arjen: Well, for sure we need a shitload of testing of this, right? People need to, you know, if you have any kind of knowledge related to this, you should test it out, break it. We want feedback as much as possible, because of course it’s a—it’s a very big aim.","offset":1856,"duration":13},{"text":"Odell: Do you have this running in the wild right now?","offset":1869,"duration":2},{"text":"Arjen: Um, it was—it’s just been two weeks, but I, yeah, I have two servers, public, public servers people can connect to, I can share that.","offset":1871,"duration":8},{"text":"Odell: Are they connected to any peers? How many people are using this thing?","offset":1879,"duration":5},{"text":"Arjen: Well, right now it's mostly Jonathan, me, and maybe one or two other people. So we’re hoping for a lot more.","offset":1884,"duration":6},{"text":"Odell: Is Justin Moon using it yet?","offset":1890,"duration":3},{"text":"Arjen: No, he said he didn’t yet. We have to bully him into doing it.","offset":1893,"duration":4},{"text":"Odell: Fair enough. I’ll try and get my feet wet. This is there limitations, like bandwidth, users, you know, where the, where the points of failure here as someone who—I want to strawman it, but I don't, I’m steelmanning it, sorry, continue.","offset":1897,"duration":34},{"text":"Arjen: Uh, so there are, um, limitations on the, the physical transport you can use, right? People need to—uh, you know, steelman by the way, steelman, sorry, continue. The underlying transport stack. So, like limitations—I'm sorry, like limitations on, like, Wi-Fi connections or, like, actual physical limitations.","offset":1931,"duration":8},{"text":"Arjen: Wi-Fi—yeah, Wi-Fi and Ethernet are fine. Um, but it is like the lower you get, like you have tech like LoRa, right? There is in the way internet protocols work you have something called an MTU, which is the—minimum—um, I'll, I'll, I’ll find what the full meaning is, but it's the amount of bytes you can, um, you can transfer in one go on a network. So on traditional IP that's like 1500 bytes for every packet, something like that. You can go up and down in some networks. But if you have transports that are less reliable or lower power, um, something like Bluetooth uses smaller packets but still works fine. But if you go down to LoRa, like LoRa Meshtastic, they might get too small to send like the minimum size of a FIPS packet might be too big for those. Although there's some really exciting developments with stuff like Halo, um, Halo, which is a, um, Wi-Fi standard on the LoRa frequencies. So I do have hopes that even though it’s the same frequencies, the throughput can be increased in the coming years. And then maybe that will become feasible. But stuff like satellite uplinks might be already.","offset":1939,"duration":78},{"text":"Odell: I mean, I don't know how much it matters, but MTU stands for Maximum Transmission Unit.","offset":2017,"duration":4},{"text":"Arjen: Oh, yes, yeah. Yeah.","offset":2021,"duration":2},{"text":"Odell: So what you were looking for.","offset":2023,"duration":1},{"text":"Arjen: Yeah, yeah. It’s basically just how thick the pipe is between the two nodes, like how much, uh, how much water you can move at once.","offset":2024,"duration":11}],"startTime":1846},{"title":"LoRa and Low-Power Hardware Integration","summary":"Odell inquires about integrating LoRa devices into FIPS. Arjen explains that while low-power frequency bands have strict data transmission limits, FIPS's agnostic design allows hardware experts to potentially build compatible low-power transports.","entries":[{"text":"Odell: What's happening with the LoRa project? Are you following it or...?","offset":2035,"duration":4},{"text":"Arjen: I’m not following it that much. I think it’s cool, but, but a lot of them have been around for years, right? Um, uh, I really hope, that’s my maybe it's wishful thinking, that if the throughput can get higher, which, um, Corridore, the guy I work with for, for Tollgate, he knows a lot about doing wireless, um, uh, wireless stuff. And the things he said, like, I have to go from secondhand information, but what I know about it is that the waves and the frequencies themselves are not necessarily the problem. It is the tech that’s used on either end on like how much data you can put through that on that same frequency at once. With newer hardware, you can use the same frequencies but actually transmit more data at once. So I think if those developments continue, I think those technologies will be, will help.","offset":2039,"duration":50},{"text":"Odell: Well, I mean, I’m a little bit confused because doesn’t, like if I have a LoRa device, isn't it using Wi-Fi usually to transmit information?","offset":2089,"duration":9},{"text":"Arjen: Um, I don't know. I don't know exactly what they use.","offset":2098,"duration":4},{"text":"Odell: Okay.","offset":2102,"duration":1},{"text":"Arjen: But it's like whatever their specific protocol is that is actually the limiter. Or—","offset":2103,"duration":7},{"text":"Arjen: Yeah, no, I think it's a bunch of things. It’s the hardware, it's the protocols they use for transmission. But the goal is, you’re—I guess your point here, the high-level point is that you want low-power devices to be able to communicate with this protocol, and there might be some limitations there that you'll have to...","offset":2110,"duration":18},{"text":"Arjen: Yes, yeah.","offset":2128,"duration":1},{"text":"Odell: Yeah, and I don't want to venture too much into that area. Like, that's not my, my area of expertise, so I don't want to go too much into that. Right.","offset":2129,"duration":7},{"text":"Odell: And I guess the cool part of FIPS is that you have a very a relatively simple, robust protocol that people that are then more technically sound on, on the hardware side could come up with low-power ways of handling it. Yeah, right?","offset":2136,"duration":17},{"text":"Arjen: Yes.","offset":2153,"duration":2}],"startTime":2035},{"title":"Overcoming Mesh Networking Hype Cycles","summary":"Acknowledging the long history of failed mesh networking projects, Odell pushes Arjen to address the skepticism. Arjen credits the protocol's viability to combining new primitives like e-cash and Nostr, alongside Jonathan's deep cryptography expertise.","entries":[{"text":"Odell: That's awesome. What uh are there any other pain points to steelman? Um, I just, I just want to be clear here, like I have, I got into the LoRa hype, I got into the GoTenna hype. GoTenna’s proprietary as hell. I don’t know. I’ve just been through a lot of mesh hype to the point where when Bitchat came out, like I went along with the hype but like internally I was fading it. I was like, yeah, okay. Um, so what are the things that you hit that guess disappoint you or—?","offset":2155,"duration":40},{"text":"Arjen: I just want it to be a reality, you know? Like, the modern internet sucks. But the story of this story of humanity is us just solving problems by centralizing things, it’s the easiest way to do it. Um, and as a result, our lives that are incredibly digital now, the most digital our lives have ever been in existence, are like built on a shitload of centralized points of failure. And so I would love to have this dream of robots and people and drones and everything all interconnected in a graceful, robust peer-to-peer mesh way. But usually it’s just hype and we don't actually see any of it in practice. And maybe this time is different, and I want to ask the hard questions but I don't have the capability of asking the hard questions. So I’m asking you to ask yourself the hard questions is what I’m trying to do here.","offset":2195,"duration":62},{"text":"Arjen: Yeah. No, I think—I think that’s a fair ask. It’s a—it's a very big aim. I think it’s a very big aim to say like we can make anything else than then work besides IP. I had this, like, I had this idea, this, this, like exactly what I told you, like this local, local networking stuff, I think it can, I think it can work and I think it can work because we have the primitives of Nostr and Blossom and e-cash, right? We can transact locally, do micropayments. So we have a bunch of new primitives that have never been combined this way. And when I talk to Jonathan, who by the way is like a very OG, um, OG open-source developer...","offset":2257,"duration":41},{"text":"Odell: Yeah, his reputation precedes himself.","offset":2298,"duration":3},{"text":"Arjen: Yeah, he’s been around, um, in Bitcoin early on. He was on the, on the mailing list, the Cypherpunks mailing list. He's done a ton of cryptography and he, he looked at it and was like, oh, this, this might work. And I’m not at his level, and but I, I think I nerd-sniped him hard enough to, to come back from his retirement. Blue seal of approval. Yeah. So, you know, it’s—it's not, um, you know, you might notice like I venture outside of some of my comfort zone as well, I know all of these high-over things and how we use these services together, but when it comes to cryptography, I have to, have to give it to Jonathan there.","offset":2301,"duration":44}],"startTime":2155},{"title":"Digital Identity and Client Key Rotation","summary":"Odell asks how digital identity works if Nostr private keys are compromised. Arjen explains that for regular clients browsing the network, FIPS keys should be rotated frequently—similar to MAC address spoofing—to preserve privacy.","entries":[{"text":"Odell: Okay, so let's pull back to something that I'm actually very comfortable with. By the way, when Justin said—so first of all, I saw FIPS because Jonathan posted it. And so I immediately retweeted on Nostr because it was Jonathan. So I was like, okay, like it might be hypy, but it’s coming from this dude, so I have respect for it automatically. And then Justin was like, um, Justin was like, you should talk about FIPS on Dispatch. I was like, I would love to. And I was like, I can't believe I’m getting Jonathan on the podcast. And then he’s like, no, Jonathan doesn't want to speak. But you’ll you’ll get Arjen. And Arjen is very impressive individual, I met him at Sovereign Engineering. So by the way, that's the background of the show. But Nostr, right? So Nostr gets a lot of shit, I think, because of people, specifically if I would distill it, is like perfect is the enemy of good. Like Nostr is fascinating to me because it's super simple and robust and doesn't try and solve all the problems. It’s like very relatively easy to implement. Um, I mean, things like just the events being just like simple JSON. The private keys just being simple single-sig private keys. When you think about Nostr used in this context, is there a concern that someone's basic digital identity is just, you know, just a private key that effectively can't really be rotated, right?","offset":2345,"duration":89},{"text":"Arjen: Um, I'm not too into the debate of, of rotating keys. I know it's a, I know it's a big topic. Uh, one thing I do think is that everyone should, like use Nostr keys in the FIPS context, but it’s not meant to be tied to your Nostr like social identity. It is just you should, it should be rotated. Um, we have an open issue for that. It should be rotated by default, only when you host something it should be static.","offset":2434,"duration":32},{"text":"Odell: Well so then—sorry, I don't know if that answers your question. I mean, it kind of does. I mean, I think on the, on the social aspect, I don't think it's like that big of a deal. I think you just deal with key security, and so it's a key security problem. I mean, you can't rotate Bitcoin keys, like if your Bitcoin key is compromised you lose your Bitcoin. Um, but you can have many, right? And like that's kind and also we have all these different mechanisms for accessible cold storage and all this other stuff. So I think you kind of solve it from the key storage piece, and I think especially when you start thinking about agents and stuff using these things, it's more important that you can spin up a ton of keys rather than the individual robustness of a single key. I mean, I've been diving down the AI rabbit hole like pretty hard over the last five weeks or so. Like my agent at this point has like 25 different Nostr keys, you know, so... My point is is the cool part is that you can just spin them up on demand all the time. But in so in practice, on your side for this, are you envisioning that peers would constantly be changing their, or not maybe not constantly, but they will be changing their identities often?","offset":2466,"duration":78},{"text":"Arjen: Yeah, I think they should. If you’re, if you’re just consuming like you are right now, like you don't, you don't care on your phone when you're out and about what your IP address is, right? You're not hosting anything. No, I have no idea what my IP address is. Yeah, and it's actually a good thing that it changes all the time, similar to MAC addresses when you go hop on different Wi-Fi networks, like your phone spoofs it, you should do the same with FIPS keys. Only when you host something.","offset":2544,"duration":23},{"text":"Odell: Yeah. I've been using Starlink, I’ve been using Starlink, and I was talking to a Greybeard about it, and I was like it’s fantastic, like blah blah blah, and he’s like, yeah, but Elon gimped it because the way he did the scaling, your IP address is like shared and rotated all the time and you can't host anything. And I was like that's a huge advantage, like if I accidentally leak my IP address, like I’d rather it be rotated and shared all the time.","offset":2567,"duration":23},{"text":"Arjen: Yeah, yeah. The IP now is in this, in this part of the world and two minutes later it’s elsewhere.","offset":2590,"duration":6},{"text":"Odell: Like, you know just the region, basically. Yeah, you basically just have the region. So for the actual individual, it's actually a benefit, but if you want to host something locally, it's a negative. That's interesting. But then how to—and I guess peers would just handle that gracefully. They would just have, it doesn't necessarily have to be a static identity for your peers to...","offset":2596,"duration":26},{"text":"Arjen: No, I think—and I think if you cycle, it’s going to be the same as like, you know, walking from from Wi-Fi to 4G right now. If you walk out the door, you get a little hiccup, right? Um, it would be similar.","offset":2622,"duration":9},{"text":"Odell: That's interesting. So yeah, then that doesn't really matter, I guess, unless you're hosting something.","offset":2631,"duration":6},{"text":"Arjen: Yeah.","offset":2637,"duration":1},{"text":"Odell: But if you're hosting something, how do you think about it in that regard? Like, what if, um, I don't know if these hypotheticals are helpful or not, but what if I’m the person in charge of keeping track of everyone's the total grain that the community has, or something? I don't know. Um, and my Nostr key gets compromised. Is that really that bad of a situation? Couldn't I just broadcast out that like I'm now at this new one? I mean, I don't know how they'd verify that I'm the one saying it and then—","offset":2638,"duration":35},{"text":"Arjen: Well, that’s social, social key rotation, right? If you lose your—you mean like the social Nostr key?","offset":2673,"duration":6}],"startTime":2345},{"title":"Securing Hosted Services and Server Key Management","summary":"The discussion pivots to identity management for long-standing services like Cashu mints. Arjen suggests using NoDNS to link a secure cold-storage key to a hot key, allowing service providers to safely rotate compromised keys without losing their identity.","entries":[{"text":"Odell: Yeah, I don't know what it looks like locally—a lot of these problems are easy to solve locally because you just, like, walk to the farmer’s market and you're like, yeah, it's just you can find it at this new address now, right? Um, I guess an example, a broader example would be, um, I don't know if you saw, but down-detector.com got sold for a billion dollars. No, isn't that wild? Um, but anyway, uh, I mean, it’s fiat games. It's like, what is things valued nowadays? But a part of the reason is not necessarily the data that—you know what Down Detector is, right? Like you go and check if a website's down. But it's not necessarily that they have the data on what things are down and a lot of it is user-reported, some of it is ISP-reported. But it's also just the reputation, right? Like, I know if I’m having trouble with something and I’m trying to troubleshoot if it’s me or if it’s, you know, Cloudflare going down globally, if I go to downdetector.com, they have a relatively good reputation that they’re telling the truth and have good data, right? So in this context, it would be some npub presumably that is like tracking some information and they’ve been doing it for five years, 10 years. How would they—have you even thought about like how they would gracefully move to—because it's hard to keep a key secure for five years hot.","offset":2679,"duration":88},{"text":"Arjen: Well, I can, I can only talk from the networking perspective. The social, social rotation I really don’t know how, how that should be solved. But for the routing side, if you say you are hosting an important server, say you are hosting a Cashu mint, right? That's an important server, and the traffic is encrypted with a Nostr key, which means that the key is probably hot, right? The key is used actively on the device. In that case, it might be dangerous to link that to make that the identity of the mint because currently the mint identity is the domain name. So if that becomes npub.fips, and that key leaks because it's always hot, that can be problematic. So it might still be useful to use, um, something like NoDNS where you have a key maybe in cold storage that then publishes these DNS records on Nostr, get resolved by name servers that are compatible, and that then actually link to the hot key, but that can then be rotated because the identity is then tied to that self-proclaimed—yes, but at least you can keep one in cold storage and no one should be able to touch it.","offset":2767,"duration":76},{"text":"Odell: That's a good solution. And that's a good example by the way. I'm running my basically my community bank. That's like a pretty serious responsibility. Yeah. And they need to be able to securely connect to me and know it's actually me and not some malicious actor.","offset":2843,"duration":20},{"text":"Arjen: Yeah, I think that's with, particularly with mints, I think it is a risk that it somewhat uses the domain name as its identity, right? It's mint.minibits.cash. It's, um, so if that gets rug-pulled and they change their domain, well, it's kind of gone from all the, from all the apps that use it. So I think those things should probably be npubs to begin with.","offset":2863,"duration":25},{"text":"Odell: I mean, on that note, I mean, it would it would make self-hosting these things way easier, right? And self-hosting and then connecting to them way easier. Yeah, that too. Specifically privately, right? Like, the powers that be know—I don't know who runs MiniBits, but the powers that be knows who runs MiniBits because of the existing networking stack, presumably. It's pretty hard to get a private domain, it's pretty hard to have a private IP address that's not linked to your identity, like he's presumably doxxed to the powers that be. And then existing solutions like things like Tor or whatever have a bunch of their own trade-offs and actually solve a bunch of things with centralization themselves and centralized blocklists and they have a bunch of—what about latency issues? Like, Tor’s slow as hell. Would this be slow as hell in comparison, or...?","offset":2888,"duration":55}],"startTime":2679},{"title":"Network Privacy and Tollgate ISP Liability","summary":"Arjen clarifies that FIPS is not onion routing, but its decentralized nature prevents any single entity from observing all traffic. They also debate the liability of individuals acting as local ISPs in Tollgate and the philosophy of an open internet.","entries":[{"text":"Arjen: It's not, uh, it's not onion routing, so—","offset":2943,"duration":4},{"text":"Odell: Because it's direct peer-to-peer?","offset":2947,"duration":1},{"text":"Arjen: It’s meant to be fast, so I I’m not making any any big privacy claims here. I I don't think it's necessarily way better than what we have. In some aspects it is, like it's encrypted hop-to-hop and then also end-to-end. Um, I think that helps. Of course, if you are the almighty observer of the entire network, I don’t think it's going to be much different from now.","offset":2948,"duration":22},{"text":"Odell: Fair enough. But right now we're forced to run through the almighty observer. In this case, we wouldn't be.","offset":2970,"duration":8},{"text":"Arjen: Yeah, yeah. I think that's actually a big thing with, with Tollgate, right? It changes the financial incentives. So if you have more, more actors, especially on, on the edges, right? You're always going to have the undersea cables or, like, major parties, that's fine, it's going to stay that way. But if you have entire communities that self-run and don't, you know, don't observe everything by choice, you can at least maybe only deduct that someone in this community looked up this thing, which is way better than always being able to point down everything to every individual.","offset":2978,"duration":31},{"text":"Odell: That's super cool. It's kind of like a—in that situation, it's almost like a hosted VPN, shared VPN kind of privacy model where you have a bunch of people coming out through the same IP address.","offset":3009,"duration":14},{"text":"Arjen: Well, yeah, I think it, I think it helps to introduce more people to convince to observe. Right. Now you just go to large ISPs and say, like, oh, you give me this information. Whereas with Tollgate, you have to go to maybe half a million ISPs because everyone is an ISP.","offset":3023,"duration":18},{"text":"Odell: Right. I mean, on the Tollgate piece, while I have you, a lot of people's concerns I've heard with the Tollgate project is like similar to running a Tor exit node. It's like, let's say I live in Paris and a bunch of random people are just connecting to my Wi-Fi and paying me sats and then looking up maybe questionable stuff. Yeah. What is your answer to those people on the Tollgate side?","offset":3041,"duration":25},{"text":"Arjen: Yeah. Um, I think the people that, like, have the connections to, um, basically to upstream, right? The general broader internet, should probably implement a specific block filters to block things that are like clearly illegal. Uh, but there's no clear-cut clear-cut solution to it. Um, but I think it's also why I want to move to local communities, doing everything local, where you should trust your community enough that everyone's, like, an honest actor, or I want to maybe. Maybe it's naive.","offset":3066,"duration":35},{"text":"Odell: Well, at least in small communities you definitely could. Yeah, yeah. I mean, small towns.","offset":3101,"duration":7},{"text":"Arjen: Yeah. It is a good point, but also it's not really—it’s like, are you going to abuse cars for—who’s responsible for producing—is the person that produces the cars responsible for, you know, anything anyone ever does with a car? Um, it becomes this this moral debate that is, you take either either one stance on.","offset":3108,"duration":25},{"text":"Odell: Yeah, I mean, it's not specific to Tollgate. I mean, you see this already with, like, coffee shops and stuff, right? Particularly in the developing world where you have bad cell connections, it's like every coffee shop becomes an ISP. They just don't have Tollgate there to charge people for it, instead it's just, you know, you're buying a coffee so you get the Wi-Fi password.","offset":3133,"duration":23},{"text":"Arjen: Yeah, yeah. But there's no, uh, there's no good answer. My personal opinion is that, you know, the internet is is should be open, open and free. I think the only counter-movement is that you observe everything and start to play police on every, every little thing, which is what we’re seemingly heading towards. I don't think that's the right future. Making everything, like, completely open and free, I think that's probably the best way and, like, solve things in the old-fashioned sleuthing way where you you go after bad people whenever the chance occurs.","offset":3156,"duration":35}],"startTime":2943},{"title":"How to Test and Deploy FIPS","summary":"Odell asks how listeners can get involved with the project. Arjen points users to the FIPS repository, highlighting available Docker images, test cases, and upcoming packages for OpenWrt routers.","entries":[{"text":"Odell: I think that's reasonable. I think that's what a lot of us are working towards. I just asked my bot to steelman FIPS. I think this conversation’s been fascinating. I think the project's really fucking cool, to be frank. I obviously need to play around with it. I’m hoping this conversation leads to more people trying it out, giving feedback.","offset":3191,"duration":25},{"text":"Arjen: Yes, please. We want we want a lot of people to test it.","offset":3216,"duration":4},{"text":"Odell: What's the process for—what like how does someone go about doing that? How should they think about participating here? Or testing it?","offset":3220,"duration":8},{"text":"Arjen: Yeah. So currently the repository, there's some, some manuals where you can compile and run it yourself. There's test cases, Docker, um, Docker-based meshes you can spin up quite easily. There's, like, step-by-step guides. Your LLM can do it. And we’re currently working on packaging, packaging it, uh, tarball should be ready any moment now, and I’m working on packaging it for OpenWrt routers and a bunch more. So then it should become easier to deploy it as well.","offset":3228,"duration":35},{"text":"Odell: I uh, okay, so I’m going to play around with it. Hopefully the freaks play around with it, give feedback. Those who can, will look over the the code and the specs and maybe provide feedback and advice on that side. Um, and then when I'm a little bit more fluent in it and more people are using it, I would love to have you back on when I can ask more reasonable questions, and I hope I wasn't too much of a struggle here. I think it will still be helpful to people.","offset":3263,"duration":28},{"text":"Arjen: No, no. These questions are these questions are valid and, and I have to make, like, you know, some of it ventures out of my my comfort zone as well. It’s a...","offset":3291,"duration":8}],"startTime":3191},{"title":"An AI Steelman of the FIPS Protocol","summary":"Odell reads a summary generated by Opus AI that perfectly captures the Cypherpunk ethos of FIPS. The AI argues that FIPS enforces privacy through mathematics rather than policy, aiming to return the internet to a network of peers.","entries":[{"text":"Odell: It's just so much—there's a lot of things to it, and it's really hard to, you know, convey these things in a short manner as well. Uh, so I asked—I asked Opus 4.6, which is supposed to be the smartest of the models right now, to steelman your project. I’ve never done this before, but I'm just going to read what Opus said: \"FIPS embodies a principle that the Cypherpunks articulated decades ago. Privacy and freedom of communication should be enforced by mathematics, not by policy. Laws change, companies get acquired, governments get replaced, but the laws of cryptography don't change. A system where your privacy is guaranteed by encryption rather than by someone's terms of service is fundamentally more robust. FIPS is ambitious but not delusional. It's technically sound, addresses a real and growing need, is built by someone with relevant deep expertise, integrates with an existing ecosystem, and is designed to work even at small scale. If it gets even 10% of the way to its vision, it could provide genuinely life-saving communication infrastructure for people living under authoritarian regimes and a meaningful privacy upgrade for everyone else. The internet was supposed to be a network of peers; somewhere along the way, it became a network of subjects. FIPS is trying to make it a network of peers again.\"","offset":3299,"duration":78},{"text":"Arjen: Damn. You didn't even have to have me on. You could have just generated—","offset":3377,"duration":3},{"text":"Odell: That's pretty good, right? That was just a one-shot prompt to steelman FIPS, and I gave the URL obviously.","offset":3380,"duration":8},{"text":"Arjen: Yeah, that’s a great summary.","offset":3388,"duration":2}],"startTime":3299},{"title":"Conclusion and Final Thoughts","summary":"Odell wraps up the show, providing links to the GitHub repository and Sovereign Engineering in the show notes. Arjen leaves the audience with a final call to test, break, and provide feedback on the FIPS protocol.","entries":[{"text":"Odell: Okay. Well, I had a great time. I'm excited, uh, I'm excited to see where this project goes. You have any final thoughts for the freaks before we wrap?","offset":3390,"duration":9},{"text":"Arjen: Test it. Give feedback. Break it. All that.","offset":3399,"duration":6},{"text":"Odell: Fair enough. I will link to the GitHub repo. I’m going to link to Sovereign Engineering. I think if you're a developer out there, you should check it out. It’s a really great program. Uh, anything else I should link to in the show notes for the freaks?","offset":3405,"duration":13},{"text":"Arjen: Tollgate.","offset":3418,"duration":1},{"text":"Odell: Tollgate. I’ll link to Tollgate. You are—are you on Nostr too? Do you have a personal npub on Nostr?","offset":3419,"duration":6},{"text":"Arjen: Yes, yeah.","offset":3425,"duration":1},{"text":"Odell: Okay. You don't have to say it out loud. You can just send it to me and then I’ll put it in the show notes as well.","offset":3426,"duration":4},{"text":"Arjen: I’ll send it.","offset":3430,"duration":1},{"text":"Odell: I'm not going to make you read the npub. Okay, Arjen, this was awesome. Uh, thanks for joining.","offset":3431,"duration":6},{"text":"Arjen: Yeah, thanks for having me.","offset":3437,"duration":3},{"text":"Odell: Freaks, I hope you enjoyed the show. Provide feedback. All links are at citadeldispatch.com. If you go to primal.net/citadel, it's the main Citadel Nostr experience. That's the best place to leave feedback, then the rest of the community can jump in and everyone can comment. I'll tag Arjen there in that post as well. Awesome. Love you all. Stay humble, stack sats. Peace.","offset":3440,"duration":24},{"text":"Arjen: Cheers. [Music] [Music fades]","offset":3464,"duration":15}],"startTime":3390}],"entries":[{"text":"[Music]","offset":0,"duration":32},{"text":"Odell: Happy Bitcoin Friday, freaks. It's your host Odell here for another Citadel Dispatch, the show focused on actionable Bitcoin and freedom tech discussion. Today is Friday, March 6th at 22:00 UTC. The current Bitcoin block height is 939631. Sats per dollar 1465. Current US dollar price is 68,239. I told you freaks I’m gonna go with the price priced in gold now as well. Priced in gold: 13.97 ounces of gold buys you a Bitcoin. We're outperforming gold on the week, but not on the day, the month, or the year. But we will eventually, hopefully, expecting, we’ll see.","offset":32,"duration":42},{"text":"Odell: As always, Dispatch is funded by our viewers. Viewers like you, thank you guys for supporting the show with your hard-earned Bitcoin. We have no ads or sponsors. Uh, this was—I’m trying to do as many shows as possible that are high signal for you freaks, so this one was two days after the last one. It seems like no one has supported the show in significant size, so I don't really have anything to read out, but thank you to everyone who does support the show. Uh, an easy way to support the show without sparing your hard-earned sats is sharing it with your friends and family. Citadel Dispatch is available on every major podcast app. All relevant links at citadeldispatch.com.","offset":74,"duration":46},{"text":"Odell: Anyway, freaks, I have a great show today. We are going to be talking about the recently announced FIPS project, which I believe stands for Free Internetworking Peering System. Um, and it’s basically the idea of, of building the internet from the ground up, uh, without all the middlemen bullshit that is involved in the current internet setup, using Nostr at its core. It's a little bit above my pay grade, so we’re going to be diving in deep here. And if I can understand it, then at least some of you can understand it. And we have Arjen here, one of the main contributors. How's it going, Arjen?","offset":120,"duration":39},{"text":"Arjen: I’m good. Thank you for having me.","offset":159,"duration":2},{"text":"Odell: Was my basic explanation decent?","offset":161,"duration":3},{"text":"Arjen: Yeah, I think so. I think so.","offset":164,"duration":2},{"text":"Odell: What is FIPS?","offset":166,"duration":2},{"text":"Arjen: So, FIPS is an attempt to, uh, do networking in a way that doesn't require any, any authority to be involved. The need actually came from, uh, from Tollgate where, um, you know, we, we pay for internet access for, uh, but if you have a system where, you know, you can pay other people to peer with them, basically, you need, you can switch between the people. So, if you switch, the person you’re buying your internet from, what happens in the current structure of the internet is that you lose your IP address, it changes, and that’s okay if you’re reaching out to the outer world, but that’s not okay if you want to host anything inside such a network.","offset":168,"duration":53},{"text":"Odell: Yeah. So first to pull back, Tollgate is this project that allows you to basically sell your Wi-Fi for sats and then people are able to access it. And then in the traditional internet infrastructure, we have internet service providers, we have DNS providers, we have all this different, all these middlemen that are involved in networking everyone together. And our IP address is our quote-unquote identity, I guess, on the internet. And a lot of home internet, I guess, their IP addresses do change a decent amount. Sometimes they change, sometimes they don't. But if you’re, like, hosting a website or something, you basically need a fixed IP address, right?","offset":221,"duration":33},{"text":"Arjen: Exactly, yeah.","offset":254,"duration":1},{"text":"Odell: So FIPS, yeah, so continue.","offset":255,"duration":3},{"text":"Arjen: Yeah, so, so in a, in a Tollgate network, right, the, the way we envisioned it first is like, okay, you have someone that is connected to the legacy ISP, if you will. And from there on out, you start reselling that internet, and someone can buy it from you and they start reselling it. That assumes a tree structure where someone’s on top and someone’s at the bottom. But if you have a network that grows and like, say, you’re two, three steps down, and there’s someone that actually gives a better price for that connection and you’re going to switch over, everyone below you is going to lose their, lose that structure that was there to define them inside that network.","offset":258,"duration":41},{"text":"Odell: Right. So in this situation, everyone has a Nostr public key-private key pair, which you can spin up relatively easily. That's your public identity. And then this is why I think it's fascinating because conceptually, high level, it makes a lot of sense to me. So then you’re able to just connect peer-to-peer between those public keys without anything else. So I can be connected via Wi-Fi or Bluetooth, I can run a long-ass Ethernet cable to my neighbor, and he could run a long-ass Ethernet cable to his neighbor, and we’d all be connected to each other, and then one of them could then have, like, some kind of long-distance mesh to someone else, and then you can continue and all that networking would work natively with Nostr. That all seems awesome, high level. How, but how is that possible? That doesn’t, like, what's the nitty-gritty that actually makes that a reality versus just something that just seems really cool in a, in a tweet?","offset":299,"duration":52},{"text":"Arjen: It is just by, by decoupling two layers, if you will, the, the physical transport layer and the routing layer. In a lot of cases, they’re very interconnected. Right, if, um, we have internet, like, IP traffic, it presumes, um, that it uses Ethernet, basically Ethernet or Wi-Fi. Um, it doesn’t run over Bluetooth. And every different protocol kind of has its own way of doing that. And what we found is it’s better if you have something that works across it and just, um, show, expose some interfaces to the layer below where it doesn’t matter how it works. All you need to know is just I want to be able to send some data to a peer and I want to be able to get some data to a peer. I don’t care how you get it there, just get it there. If it’s Ethernet, right, you use the Ethernet protocol or Wi-Fi. If it’s Bluetooth, you use Bluetooth underneath, but the FIPS protocol doesn’t have to, doesn’t care about that.","offset":351,"duration":60},{"text":"Odell: But then how does discovery work?","offset":411,"duration":3},{"text":"Arjen: That depends on the layer you use, or the transport you use. If you use a broadcast medium, say Wi-Fi, you can broadcast the fact that you’re a FIPS node and that you want to peer with people. That way people can discover you and send messages back.","offset":414,"duration":18},{"text":"Odell: Okay, work with me here on, uh, hypothetical, 'cause it—I understand hypotheticals better. Uh, let's say you're successful, this project is a smashing success, and it's five years in the future. Um, you’re in a different country than me. I have your public key. I want to send you information. How, how does me pressing enter on my side get to you?","offset":432,"duration":32},{"text":"Arjen: If we are on the other side of the world, that is a problem we hope that we’re going to run into with, um, people using it. Uh, we’re nowhere near that yet. But I, I think the, one thing that can help us with that, where, um, if you do mesh without the cryptographic identities and Nostr keys for that matter, I think we can use nodes that are somewhere in between that can help us route that traffic. But this is two-step, two, three steps ahead and like, routing further away.","offset":464,"duration":24},{"text":"Odell: So are these, are these similar to, like, what a DNS server currently is? How does that look?","offset":488,"duration":6},{"text":"Arjen: Yeah, in this instance, it would be something like that. Like, uh, you would maybe publish something to the—it's very theoretical. You would publish something to, say, a Nostr relay that is specialized in this, right? You can use your, you can use your Nostr keys to sign something and like how people can find you. But you can do it in a way where there’s not one party involved, it's like one central authority you look at, like how does that traffic go from A to B, uh, but you can send it to multiple people.","offset":494,"duration":32},{"text":"Odell: So the difference would be from the modern-day setup is that it'd just be more accessible to run these kind of discovery servers or whatever you’re calling them. Like, anyone could basically run one and there, there wouldn't be, like, lock-in. Maybe? Am I reading this correctly or...?","offset":526,"duration":13},{"text":"Arjen: Yeah, if you would use something like this, yes. Um, but I think we should backtrack a bit first, like how the, how it works.","offset":539,"duration":6},{"text":"Odell: Let's backtrack, yeah. Whatever you think is best.","offset":545,"duration":3},{"text":"Arjen: In the local level. Um, so on the local level, you discover a peer, um, and you encrypt, like, you advertise your own pubkey, right? The peer advertises his pubkey. You can immediately encrypt something to that pubkey, so there’s a handshake there where the two peers use a noise protocol to establish an encrypted connection. And every peer does that amongst each other, and so every hop of the way is individually encrypted. And then on top of that, there is the, the longer routing of, like, the longer routes. And the way you can find another peer within the mesh, say, like, a mesh up to 10,000 people, oh shit, is that every peer holds a Bloom filter of the people that they can reach. So if you connect to a peer that can already reach, say, like, 10,000 other peers, it will give you a Bloom filter, which is a very compressed, uh, version of a list of npubs that it can reach. It's just one kilobyte at this moment. You get that, and then whenever you get a packet that’s for any of those 10,000, you know that that peer that’s on your left-hand side can actually reach it.","offset":548,"duration":76},{"text":"Odell: Got it. So in practice, each peer is like, almost like a DNS server?","offset":624,"duration":8},{"text":"Arjen: Um, I think it’s hard to make that comparison because it's not—it's, it's a different—it's a different way of doing things.","offset":632,"duration":12},{"text":"Odell: Right, it's fundamentally different. But each peer is also my method of discovery?","offset":644,"duration":6},{"text":"Arjen: Yes. In a smaller local mesh, that is the way you found other people.","offset":650,"duration":6},{"text":"Odell: Yeah, I mean, you can, this is a interoperable way of rolling out, like, a local community mesh relatively easily.","offset":656,"duration":6},{"text":"Arjen: Yeah, yeah. And that's honestly, that's if only that works, I would already be very happy because you can roll this out in a community, you can host servers, right? You can, you can host things on an npub that can even physically move around in a network, and if the network gets cut off from the rest of the world, everything just keeps working. You can do it if, you know, part of the network fails, you go over Bluetooth, uh, whatever works. Whatever method you have available, that’s how you want to route the traffic.","offset":662,"duration":29},{"text":"Odell: It's completely agnostic. And some peers can be on Ethernet, some could be on Wi-Fi, some could be on Bluetooth. Doesn't matter.","offset":691,"duration":7},{"text":"Arjen: Yeah, or even satellite uplinks.","offset":698,"duration":4},{"text":"Odell: Now, what if one person—have you guys, is it in scope of the project if, like, one person has Starlink, for instance? Would then the whole community have broader internet access or no? Is that...?","offset":702,"duration":11},{"text":"Arjen: Yes, you can, so if you use Starlink, you are using the, uh, regular internet stack, IPs, but you can establish peer connections over, over the internet. So if I have a mesh here in my house and you have one in your house, uh, we can establish a link over UDP and connect the mesh that way.","offset":713,"duration":21},{"text":"Odell: Yeah, I mean, 'cause like, in practice, so let's use a real-world example, right? The internet—the government of Iran cut the internet relatively recently. I don't know if the internet's on right now or if it’s off. But at least during the protests a couple weeks ago, uh, now we have war in Iran. But, uh, during the protests a couple weeks ago, uh, government internally cut the internet because they didn't want communication among the protesters. It's something we see happen all the time. And as a result, Bitchat usage spiked in the country. Now, Bitchat has its own issues, right, in terms of range and whatnot and capability. But the biggest one that I kept thinking about is those people could communicate internally, which is great, still an advantage, you know, it's better than the alternative which is no communication internally. But they couldn't, for instance, broadcast to the rest of the world and be like, this is what’s happening on the ground right now. There was a fog of war that was happening and, and that was part of the government's design. That's why when you see large protest movements happen in different places, authoritarian governments often cut the internet. Now, the dream high level in my mind has always been you have, like, local meshes and then one person smuggles in a Starlink and then all of a sudden the entire community can broadcast globally on Nostr, for instance, and say, you know, here's a video of the police abusing us or whatnot, or corruption or whatever they’re trying to get out. Presumably this project should be able to offer that kind of capability, no?","offset":734,"duration":88},{"text":"Arjen: Yes, because you can introduce, basically, say, quote-unquote a tunnel to the rest of the world from anywhere, and that would automatically be discovered by the network. So if, yes, you have a Starlink that goes up and, right, goes down in another country and you have a mesh there, well, as long as you knew one of the npubs that was on the other side of the mesh before it got cut off, you can actually find that route again.","offset":822,"duration":22},{"text":"Odell: That's awesome. I mean, have you talked to the, have you talked to the Bitchat guys at all or...?","offset":844,"duration":9},{"text":"Arjen: Uh, no, we just, uh, we just released it, actually, so it was two weeks—two weeks ago, uh, I just met—the idea has been around for, for a little while, and I met Jonathan just in last November, and we kept talking, talking about the idea, and, uh, so that slowly developed over the last few months, and just the last couple weeks we had a, had a working working demo.","offset":853,"duration":23},{"text":"Odell: That's awesome. Did you guys, did you guys meet at Sovereign Engineering?","offset":876,"duration":4},{"text":"Arjen: No, at a conference in Costa Rica. Uh, there was this conference for Nostr conference, and I think, yeah, it was two days and the only thing I did is basically sit in a room with him talking about these ideas on doing addressing with, with npubs instead of, instead of IP or for DNS as well.","offset":880,"duration":20},{"text":"Odell: So what is the Sovereign Engineering connection? I—Justin Moon introduced us. I believe he met you at Sovereign Engineering?","offset":900,"duration":6},{"text":"Arjen: Yeah, correct, yeah.","offset":906,"duration":1},{"text":"Odell: What was the Sovereign Engineering experience like? I mean, I love what those guys are doing. I haven't been myself, but I work closely with Gigi at OpenSats and he’s heavily involved in Sovereign Engineering. I think it’s a fascinating program.","offset":907,"duration":13},{"text":"Arjen: Yeah, so some of the, the original idea on, like, addressing with npubs is something I worked on at Sovereign Engineering last year. Uh, it came from the ideas like if we can use npubs to address services instead of IP addresses or traditional domain names, then at least we have a static identifier we can use across the web to reach things even if the IP address changes. Um, that experiment turned into what's called now, uh, NoDNS, where someone signs cryptographically on in a Nostr message all the, um, DNS records, publishes that, and other people can resolve that as DNS. So that’s kind of the, the predecessor of this idea. We can do it inside the IP network. You still have that structure, but when it changes, you have some flexibility on correcting that, similar to if an IP address changes now, you use update the DNS record and people can reach you again. You can do it much faster this way, that’s nice, but it doesn’t resolve the, the entire issue.","offset":920,"duration":62},{"text":"Odell: I didn't realize, so Tollgate is your project as well?","offset":982,"duration":5},{"text":"Arjen: I work on it as well, yeah.","offset":987,"duration":1},{"text":"Odell: Yeah. So Toll—you were in Sovereign Engineering for Tollgate specifically?","offset":988,"duration":4},{"text":"Arjen: Uh, the first one I was at, Sovereign Engineering 3, I didn’t know much about Tollgate back then, but I met the guy that started it, and from there on we started to basically rolled into it and we started to, uh, work, work on it together.","offset":992,"duration":18},{"text":"Odell: I think it's a super cool project too. I so the the whole premise of Tollgate is that I’m, I’m paying sats for internet access. Are sats involved in FIPS at all? Like, are people, are people using—is the idea that people will be paying for peering, or have you thought about that at all?","offset":1010,"duration":21},{"text":"Arjen: Yeah, that, that’s my hope for sure. Like, the whole reason FIPS exists is because, um, we don't have a way to do this dynamic, uh, this dynamically changing network. So I think it's a very—payment is a very important part of it because you want to be able to steer traffic based on economic incentives as well. So if say one link is very expensive and the other is cheap, well why not, if you pay for that connection, why not incorporate that in your routing decisions as well. But that’s a—that’s definitely a next step. But it can be, can be combined.","offset":1031,"duration":33},{"text":"Odell: I mean, and wouldn’t something like that be necessary because—have you thought at all about DDoS concerns or, or any kind of malicious attacker trying to flood the network or break down the mesh?","offset":1064,"duration":16},{"text":"Arjen: Yeah, there’s, um, there's a couple things there. The mesh when, when joining the mesh, uh, physically, you need to do that with a peer, so, and that peer it will be, uh, rate-limiting how many people can connect at the same time. So that’s, that’s one defense. Another defense is that to send traffic to an endpoint, you need to know the npub because on the routing layer, uh, the nodes don’t know for the packets they send, they don’t know the npub. They only know a node ID that is derived from the npub. So that provides some protection. If your npub is not known by the whole world, it's hard for someone to DDoS you.","offset":1080,"duration":40},{"text":"Odell: Interesting. Because that would be the attack, right? If we were going to go down our hypothetical and you're in Iran and the government's shutting down the internet, they would try and jam different types of signals, I guess, and then also they would presumably just spin up, spin up npubs, right, and just start spamming the network.","offset":1120,"duration":21},{"text":"Arjen: Yeah. I mean, it’s a—it's definitely not a—not an easy problem to solve, right? That’s, it’s not fully solved in the current internet.","offset":1141,"duration":8},{"text":"Odell: Yeah. Probably the hardest problem set.","offset":1149,"duration":2},{"text":"Arjen: Well, the current internet just solved it with centralization, right?","offset":1151,"duration":4},{"text":"Arjen: Yes, yeah, you have Cloudflare to do these things.","offset":1155,"duration":5},{"text":"Odell: Which is just a massive middlemen honeypot. And then also just internet infrastructure in general, right? There’s, like, a million central points of failure that can be pressured and shut down. That’s why authoritarians can, I mean, it’s not as simple as it, but basically click a button and cut off the internet for the entire country, right?","offset":1160,"duration":17},{"text":"Arjen: Yeah, yeah. So, um, that’s why an internet that is, that is designed to fracture and recombine is, is very useful.","offset":1177,"duration":9},{"text":"Odell: Well, what I like about this is it's very pragmatic because one of the trouble—like, mesh is something that I've been fascinated with for maybe a decade. And there's been many different attempts at doing different things. Um, I think it was, it was exciting that and obviously partially it was because of Jack Dorsey tweeting it out, but the excitement around Bitchat. But it was also kind of weird, right, because if you'd actually been following the mesh space for a while, like people were acting like it was the first mesh project that ever existed, but there was a million predecessors that failed beforehand. And always the problem—well, not always, there’s many different, you, like you said, it's very hard problem to solve. But one of the core problems I feel like is this bootstrapping issue, where, you know, you need a critical mass of at least your neighbors to be using it for it to be useful, right? I, and people saw with Bitchat, right? It’s like they would download Bitchat, and then it was just nobody to talk to, right? Because you don't have neighbors that also download Bitchat. And there's different ways of solving it. You know, it's easier in cities. I like the idea of being in a, in a—like a sports arena or something that already has poor internet, and maybe in a sports arena everyone wants to talk about the same thing. They're all watching the same game, they all want to talk about the same game. It’s a high-density group of people. You could see it being really useful in that situation, a concert, a music festival. Um, but at scale, to actually, like, see it work at scale, um, it's a just a really hard problem. But one of the things that I've thought about historically is if you could bootstrap it in a way that it works with modern internet infrastructure until the modern internet infrastructure isn't needed anymore, then that makes it way more useful. Because if we’re in different parts of the world but we can use this tech to communicate because of the existing internet infrastructure, then all of a sudden it's useful today without actually having the build-out of people interconnected all the way between us or whatever, right? Does that make sense?","offset":1186,"duration":125},{"text":"Arjen: Yeah, yeah. And there's, um, there’s a couple things to unpack there too is that I really hope we can, when nerd-snipe the, the people from Bitchat into this. Because if, you know, if you run a mesh that is cross-transports, you can lower the burden of making apps like Bitchat because now Bitchat needs to design its own protocol on like how over Bluetooth the app, apps are going to talk together, whereas if it was just you can just send TCP/IP traffic like through this, like any existing application like a relay and a, and a Nostr app, then you can do this over Bluetooth without having to specifically design the app to also support that.","offset":1311,"duration":41},{"text":"Odell: Can we go a little bit deeper there? How does that look in practice?","offset":1352,"duration":5},{"text":"Arjen: So, say you would have, you would run a FIPS network and every phone has, has it running and is peering with each other over both Wi-Fi and Bluetooth, some people are only Bluetooth. Now on these phones, you can host, um, something like a Nostr relay. Now everyone can reach that relay over a npub.fips address from any app on their phone. So now they don't need a app that is specifically designed to be a Bluetooth app, it can just be like any other app and not have to put in any effort to, to do this. And so you don't just have one app that can do this, but you have pretty much everything under the sun that would work if, if it uses infrastructure like Nostr relays that are really good at, um, facilitating so many use cases at once.","offset":1357,"duration":47},{"text":"Odell: But so how does that look in practice for like an app developer? How would they integrate in that situation?","offset":1404,"duration":7},{"text":"Arjen: Um, so if I would, say, like White Noise, right? Bitchat app. White Noise connects to Nostr relays. White Noise does what White Noise does best, like do all the encryption, do all the rotation, group management, but they might not want to put so much effort into making a Bluetooth mesh. If they, if someone that uses their app on their phone also connects to a FIPS network, they can just configure a relay like they always would, saying npub.fips in the relay, in the relay list. Then they can already talk to that relay that’s on FIPS. Now if they then move around inside that mesh, and other people join, they go from Bluetooth to Wi-Fi, they can still reach that relay that is elsewhere in the network. So they don’t have to change their app to work over Bluetooth.","offset":1411,"duration":59},{"text":"Odell: But they have to add FIPS support specifically though, right?","offset":1470,"duration":7},{"text":"Arjen: No, that's the—that’s one of the things that I really wanted in here is a—I should have mentioned it earlier—is a system where it works for existing applications that expect the IP stack to work. Because I looked at some of the other protocols, and what I found is the, they often seem to expect everyone to re-implement all their applications to work with it. But there’s no way in hell you're going to get any adoption if everyone needs to rebuild their stack from scratch. There’s, there’s 40 years of history in libraries, etc. Unless it works from scratch or like without any modification in all the applications, it’s not going to fly. So the way this works is we add a custom DNS server together with FIPS, the FIPS daemon. What happens is if any application on your, on let's say with computers for now, any application on your computer asks for npub.fips, what that DNS server does is it gives you back an IPv6 address that is deterministically derived from that npub, which is the same as the node ID of the destination.","offset":1477,"duration":70},{"text":"Odell: That's wild.","offset":1547,"duration":1},{"text":"Arjen: And then the application will send its traffic like it always would, right? It's going to, in my browser it's going to be HTTP becomes TCP becomes IP packets. And then down at the bottom where, you know, the system would send it out as an IP packet, we know we just generated that IPv6 address, so we intercept it and actually send it over FIPS instead. And the app just thinks it’s using the regular internet.","offset":1548,"duration":27},{"text":"Odell: Yes. So that’s what we’re focusing on most now is like all the applications, right? Ping, when I did the first experiments in Sovereign Engineering, Sec5, I found is like, okay, I make something like this. And now I have to rewrite, fucking ping app—excuse my French—the ping application. I’m not going to do that. Like, no one’s—no one in hell’s going to rewrite everything from scratch. So it has to work with everything that we already have.","offset":1575,"duration":27},{"text":"Odell: That's awesome. I mean, I think that's the key, right? That's the key for bootstrapping, then you don't even have the app developers don't have to change a thing.","offset":1602,"duration":15},{"text":"Arjen: Yeah, I think, I think that's a must-have. I don't think anything like this can, can scale if it doesn’t, isn’t backwards compatible.","offset":1617,"duration":10},{"text":"Odell: Okay, I mean, I don't know where to go from here. That's like a mic drop moment for me. I mean, if this works, it seems like it's kind of the holy grail that you stumbled on here, sir. I mean, I’m reading through your Git repo. What do you want to cover? You know better than me. I, by the way, huge shout out to Justin Moon. He set up this conversation. I told him to join for it. He said he was unnecessary. I think he would have been very helpful.","offset":1627,"duration":28},{"text":"Arjen: We can, we can still try to get him in.","offset":1655,"duration":4},{"text":"Odell: What do you want to talk about? What is, what is most interesting to you here? You have thousands of people listening to this show. What do you want to talk about?","offset":1659,"duration":9},{"text":"Arjen: I think, I think the opportunity to make the internet in this general—like, FIPS doesn’t have to replace the internet if for, like, long-range stuff, right? If we’re necessarily. If we’re doing a call like this, it's fine if that still exists, like the hierarchy there, we’re not, you know, that’s not going to change quick. Um, I think it already wins if it works local. And that’s exactly, I think the most exciting thing is like if it works local with, say, half a million people or a million people, you don’t even need the traditional internet—the traditional way of doing things is we go out, like when we visit a website, right? I go to amazon.com. The way it works now is I send a message to Amazon saying, go fetch, go fetch, go fetch. And I think in a world with Nostr where everything, everything in Nostr is a stream, all the data is signed, so we can do replication wherever needed. So what we can do with that is we collect information once, we pull it inside the network that we have here, and from there on out it doesn’t matter if that connection to the outside world gets severed because the information’s already inside the network on the relays. And then from there, we can spread that information. So I think if we have a decent way of hosting that stuff inside this network that can rearrange and is resilient, then it doesn’t matter as much when connections outside are, are unstable. Like, you’ll just pull in the new stuff whenever you have a connection. And if not, you go about your day and do your things inside your network. You can run your Bitcoin nodes, your Cashu mints, uh, Nostr relays and Blossom servers in the, in your town and the main cable gets cut. Well, okay, it sucks, but you can still chat with whoever you want over all the, over White Noise. You can still use, um, Primal, right? And then what—and then the key is when that cable gets uncut or whatever, I don’t know what the opposite analogy is, when you get reconnected, you can gracefully reconnect to the water network.","offset":1668,"duration":130},{"text":"Arjen: Yeah, and then you can see like what was gone, what is not, right? That boundary Nostr allows us to, to completely remove the boundary between what is offline and online is, becomes a spectrum of offline and online. Like, offline is I don’t have anything on, I don’t have a relay on my computer, I don’t have a Blossom server on my computer, and I’m not connected to any other node. Then I’m offline. Whereas like you can be a little bit online where you have one other node peering some info, right, like shades of grey. Yeah. So there’s no—and then everything because of Nostr, everything’s signed, it’s all verifiable, you can gracefully reconcile afterwards. Yeah, so the way information flows I think will dramatically change in a Nostr world.","offset":1798,"duration":48},{"text":"Odell: What are the, what are the hurdles you face? Like, what are the trade-offs here? Like concerns, what are the dealbreakers? How are you thinking about that?","offset":1846,"duration":10},{"text":"Arjen: Well, for sure we need a shitload of testing of this, right? People need to, you know, if you have any kind of knowledge related to this, you should test it out, break it. We want feedback as much as possible, because of course it’s a—it’s a very big aim.","offset":1856,"duration":13},{"text":"Odell: Do you have this running in the wild right now?","offset":1869,"duration":2},{"text":"Arjen: Um, it was—it’s just been two weeks, but I, yeah, I have two servers, public, public servers people can connect to, I can share that.","offset":1871,"duration":8},{"text":"Odell: Are they connected to any peers? How many people are using this thing?","offset":1879,"duration":5},{"text":"Arjen: Well, right now it's mostly Jonathan, me, and maybe one or two other people. So we’re hoping for a lot more.","offset":1884,"duration":6},{"text":"Odell: Is Justin Moon using it yet?","offset":1890,"duration":3},{"text":"Arjen: No, he said he didn’t yet. We have to bully him into doing it.","offset":1893,"duration":4},{"text":"Odell: Fair enough. I’ll try and get my feet wet. This is there limitations, like bandwidth, users, you know, where the, where the points of failure here as someone who—I want to strawman it, but I don't, I’m steelmanning it, sorry, continue.","offset":1897,"duration":34},{"text":"Arjen: Uh, so there are, um, limitations on the, the physical transport you can use, right? People need to—uh, you know, steelman by the way, steelman, sorry, continue. The underlying transport stack. So, like limitations—I'm sorry, like limitations on, like, Wi-Fi connections or, like, actual physical limitations.","offset":1931,"duration":8},{"text":"Arjen: Wi-Fi—yeah, Wi-Fi and Ethernet are fine. Um, but it is like the lower you get, like you have tech like LoRa, right? There is in the way internet protocols work you have something called an MTU, which is the—minimum—um, I'll, I'll, I’ll find what the full meaning is, but it's the amount of bytes you can, um, you can transfer in one go on a network. So on traditional IP that's like 1500 bytes for every packet, something like that. You can go up and down in some networks. But if you have transports that are less reliable or lower power, um, something like Bluetooth uses smaller packets but still works fine. But if you go down to LoRa, like LoRa Meshtastic, they might get too small to send like the minimum size of a FIPS packet might be too big for those. Although there's some really exciting developments with stuff like Halo, um, Halo, which is a, um, Wi-Fi standard on the LoRa frequencies. So I do have hopes that even though it’s the same frequencies, the throughput can be increased in the coming years. And then maybe that will become feasible. But stuff like satellite uplinks might be already.","offset":1939,"duration":78},{"text":"Odell: I mean, I don't know how much it matters, but MTU stands for Maximum Transmission Unit.","offset":2017,"duration":4},{"text":"Arjen: Oh, yes, yeah. Yeah.","offset":2021,"duration":2},{"text":"Odell: So what you were looking for.","offset":2023,"duration":1},{"text":"Arjen: Yeah, yeah. It’s basically just how thick the pipe is between the two nodes, like how much, uh, how much water you can move at once.","offset":2024,"duration":11},{"text":"Odell: What's happening with the LoRa project? Are you following it or...?","offset":2035,"duration":4},{"text":"Arjen: I’m not following it that much. I think it’s cool, but, but a lot of them have been around for years, right? Um, uh, I really hope, that’s my maybe it's wishful thinking, that if the throughput can get higher, which, um, Corridore, the guy I work with for, for Tollgate, he knows a lot about doing wireless, um, uh, wireless stuff. And the things he said, like, I have to go from secondhand information, but what I know about it is that the waves and the frequencies themselves are not necessarily the problem. It is the tech that’s used on either end on like how much data you can put through that on that same frequency at once. With newer hardware, you can use the same frequencies but actually transmit more data at once. So I think if those developments continue, I think those technologies will be, will help.","offset":2039,"duration":50},{"text":"Odell: Well, I mean, I’m a little bit confused because doesn’t, like if I have a LoRa device, isn't it using Wi-Fi usually to transmit information?","offset":2089,"duration":9},{"text":"Arjen: Um, I don't know. I don't know exactly what they use.","offset":2098,"duration":4},{"text":"Odell: Okay.","offset":2102,"duration":1},{"text":"Arjen: But it's like whatever their specific protocol is that is actually the limiter. Or—","offset":2103,"duration":7},{"text":"Arjen: Yeah, no, I think it's a bunch of things. It’s the hardware, it's the protocols they use for transmission. But the goal is, you’re—I guess your point here, the high-level point is that you want low-power devices to be able to communicate with this protocol, and there might be some limitations there that you'll have to...","offset":2110,"duration":18},{"text":"Arjen: Yes, yeah.","offset":2128,"duration":1},{"text":"Odell: Yeah, and I don't want to venture too much into that area. Like, that's not my, my area of expertise, so I don't want to go too much into that. Right.","offset":2129,"duration":7},{"text":"Odell: And I guess the cool part of FIPS is that you have a very a relatively simple, robust protocol that people that are then more technically sound on, on the hardware side could come up with low-power ways of handling it. Yeah, right?","offset":2136,"duration":17},{"text":"Arjen: Yes.","offset":2153,"duration":2},{"text":"Odell: That's awesome. What uh are there any other pain points to steelman? Um, I just, I just want to be clear here, like I have, I got into the LoRa hype, I got into the GoTenna hype. GoTenna’s proprietary as hell. I don’t know. I’ve just been through a lot of mesh hype to the point where when Bitchat came out, like I went along with the hype but like internally I was fading it. I was like, yeah, okay. Um, so what are the things that you hit that guess disappoint you or—?","offset":2155,"duration":40},{"text":"Arjen: I just want it to be a reality, you know? Like, the modern internet sucks. But the story of this story of humanity is us just solving problems by centralizing things, it’s the easiest way to do it. Um, and as a result, our lives that are incredibly digital now, the most digital our lives have ever been in existence, are like built on a shitload of centralized points of failure. And so I would love to have this dream of robots and people and drones and everything all interconnected in a graceful, robust peer-to-peer mesh way. But usually it’s just hype and we don't actually see any of it in practice. And maybe this time is different, and I want to ask the hard questions but I don't have the capability of asking the hard questions. So I’m asking you to ask yourself the hard questions is what I’m trying to do here.","offset":2195,"duration":62},{"text":"Arjen: Yeah. No, I think—I think that’s a fair ask. It’s a—it's a very big aim. I think it’s a very big aim to say like we can make anything else than then work besides IP. I had this, like, I had this idea, this, this, like exactly what I told you, like this local, local networking stuff, I think it can, I think it can work and I think it can work because we have the primitives of Nostr and Blossom and e-cash, right? We can transact locally, do micropayments. So we have a bunch of new primitives that have never been combined this way. And when I talk to Jonathan, who by the way is like a very OG, um, OG open-source developer...","offset":2257,"duration":41},{"text":"Odell: Yeah, his reputation precedes himself.","offset":2298,"duration":3},{"text":"Arjen: Yeah, he’s been around, um, in Bitcoin early on. He was on the, on the mailing list, the Cypherpunks mailing list. He's done a ton of cryptography and he, he looked at it and was like, oh, this, this might work. And I’m not at his level, and but I, I think I nerd-sniped him hard enough to, to come back from his retirement. Blue seal of approval. Yeah. So, you know, it’s—it's not, um, you know, you might notice like I venture outside of some of my comfort zone as well, I know all of these high-over things and how we use these services together, but when it comes to cryptography, I have to, have to give it to Jonathan there.","offset":2301,"duration":44},{"text":"Odell: Okay, so let's pull back to something that I'm actually very comfortable with. By the way, when Justin said—so first of all, I saw FIPS because Jonathan posted it. And so I immediately retweeted on Nostr because it was Jonathan. So I was like, okay, like it might be hypy, but it’s coming from this dude, so I have respect for it automatically. And then Justin was like, um, Justin was like, you should talk about FIPS on Dispatch. I was like, I would love to. And I was like, I can't believe I’m getting Jonathan on the podcast. And then he’s like, no, Jonathan doesn't want to speak. But you’ll you’ll get Arjen. And Arjen is very impressive individual, I met him at Sovereign Engineering. So by the way, that's the background of the show. But Nostr, right? So Nostr gets a lot of shit, I think, because of people, specifically if I would distill it, is like perfect is the enemy of good. Like Nostr is fascinating to me because it's super simple and robust and doesn't try and solve all the problems. It’s like very relatively easy to implement. Um, I mean, things like just the events being just like simple JSON. The private keys just being simple single-sig private keys. When you think about Nostr used in this context, is there a concern that someone's basic digital identity is just, you know, just a private key that effectively can't really be rotated, right?","offset":2345,"duration":89},{"text":"Arjen: Um, I'm not too into the debate of, of rotating keys. I know it's a, I know it's a big topic. Uh, one thing I do think is that everyone should, like use Nostr keys in the FIPS context, but it’s not meant to be tied to your Nostr like social identity. It is just you should, it should be rotated. Um, we have an open issue for that. It should be rotated by default, only when you host something it should be static.","offset":2434,"duration":32},{"text":"Odell: Well so then—sorry, I don't know if that answers your question. I mean, it kind of does. I mean, I think on the, on the social aspect, I don't think it's like that big of a deal. I think you just deal with key security, and so it's a key security problem. I mean, you can't rotate Bitcoin keys, like if your Bitcoin key is compromised you lose your Bitcoin. Um, but you can have many, right? And like that's kind and also we have all these different mechanisms for accessible cold storage and all this other stuff. So I think you kind of solve it from the key storage piece, and I think especially when you start thinking about agents and stuff using these things, it's more important that you can spin up a ton of keys rather than the individual robustness of a single key. I mean, I've been diving down the AI rabbit hole like pretty hard over the last five weeks or so. Like my agent at this point has like 25 different Nostr keys, you know, so... My point is is the cool part is that you can just spin them up on demand all the time. But in so in practice, on your side for this, are you envisioning that peers would constantly be changing their, or not maybe not constantly, but they will be changing their identities often?","offset":2466,"duration":78},{"text":"Arjen: Yeah, I think they should. If you’re, if you’re just consuming like you are right now, like you don't, you don't care on your phone when you're out and about what your IP address is, right? You're not hosting anything. No, I have no idea what my IP address is. Yeah, and it's actually a good thing that it changes all the time, similar to MAC addresses when you go hop on different Wi-Fi networks, like your phone spoofs it, you should do the same with FIPS keys. Only when you host something.","offset":2544,"duration":23},{"text":"Odell: Yeah. I've been using Starlink, I’ve been using Starlink, and I was talking to a Greybeard about it, and I was like it’s fantastic, like blah blah blah, and he’s like, yeah, but Elon gimped it because the way he did the scaling, your IP address is like shared and rotated all the time and you can't host anything. And I was like that's a huge advantage, like if I accidentally leak my IP address, like I’d rather it be rotated and shared all the time.","offset":2567,"duration":23},{"text":"Arjen: Yeah, yeah. The IP now is in this, in this part of the world and two minutes later it’s elsewhere.","offset":2590,"duration":6},{"text":"Odell: Like, you know just the region, basically. Yeah, you basically just have the region. So for the actual individual, it's actually a benefit, but if you want to host something locally, it's a negative. That's interesting. But then how to—and I guess peers would just handle that gracefully. They would just have, it doesn't necessarily have to be a static identity for your peers to...","offset":2596,"duration":26},{"text":"Arjen: No, I think—and I think if you cycle, it’s going to be the same as like, you know, walking from from Wi-Fi to 4G right now. If you walk out the door, you get a little hiccup, right? Um, it would be similar.","offset":2622,"duration":9},{"text":"Odell: That's interesting. So yeah, then that doesn't really matter, I guess, unless you're hosting something.","offset":2631,"duration":6},{"text":"Arjen: Yeah.","offset":2637,"duration":1},{"text":"Odell: But if you're hosting something, how do you think about it in that regard? Like, what if, um, I don't know if these hypotheticals are helpful or not, but what if I’m the person in charge of keeping track of everyone's the total grain that the community has, or something? I don't know. Um, and my Nostr key gets compromised. Is that really that bad of a situation? Couldn't I just broadcast out that like I'm now at this new one? I mean, I don't know how they'd verify that I'm the one saying it and then—","offset":2638,"duration":35},{"text":"Arjen: Well, that’s social, social key rotation, right? If you lose your—you mean like the social Nostr key?","offset":2673,"duration":6},{"text":"Odell: Yeah, I don't know what it looks like locally—a lot of these problems are easy to solve locally because you just, like, walk to the farmer’s market and you're like, yeah, it's just you can find it at this new address now, right? Um, I guess an example, a broader example would be, um, I don't know if you saw, but down-detector.com got sold for a billion dollars. No, isn't that wild? Um, but anyway, uh, I mean, it’s fiat games. It's like, what is things valued nowadays? But a part of the reason is not necessarily the data that—you know what Down Detector is, right? Like you go and check if a website's down. But it's not necessarily that they have the data on what things are down and a lot of it is user-reported, some of it is ISP-reported. But it's also just the reputation, right? Like, I know if I’m having trouble with something and I’m trying to troubleshoot if it’s me or if it’s, you know, Cloudflare going down globally, if I go to downdetector.com, they have a relatively good reputation that they’re telling the truth and have good data, right? So in this context, it would be some npub presumably that is like tracking some information and they’ve been doing it for five years, 10 years. How would they—have you even thought about like how they would gracefully move to—because it's hard to keep a key secure for five years hot.","offset":2679,"duration":88},{"text":"Arjen: Well, I can, I can only talk from the networking perspective. The social, social rotation I really don’t know how, how that should be solved. But for the routing side, if you say you are hosting an important server, say you are hosting a Cashu mint, right? That's an important server, and the traffic is encrypted with a Nostr key, which means that the key is probably hot, right? The key is used actively on the device. In that case, it might be dangerous to link that to make that the identity of the mint because currently the mint identity is the domain name. So if that becomes npub.fips, and that key leaks because it's always hot, that can be problematic. So it might still be useful to use, um, something like NoDNS where you have a key maybe in cold storage that then publishes these DNS records on Nostr, get resolved by name servers that are compatible, and that then actually link to the hot key, but that can then be rotated because the identity is then tied to that self-proclaimed—yes, but at least you can keep one in cold storage and no one should be able to touch it.","offset":2767,"duration":76},{"text":"Odell: That's a good solution. And that's a good example by the way. I'm running my basically my community bank. That's like a pretty serious responsibility. Yeah. And they need to be able to securely connect to me and know it's actually me and not some malicious actor.","offset":2843,"duration":20},{"text":"Arjen: Yeah, I think that's with, particularly with mints, I think it is a risk that it somewhat uses the domain name as its identity, right? It's mint.minibits.cash. It's, um, so if that gets rug-pulled and they change their domain, well, it's kind of gone from all the, from all the apps that use it. So I think those things should probably be npubs to begin with.","offset":2863,"duration":25},{"text":"Odell: I mean, on that note, I mean, it would it would make self-hosting these things way easier, right? And self-hosting and then connecting to them way easier. Yeah, that too. Specifically privately, right? Like, the powers that be know—I don't know who runs MiniBits, but the powers that be knows who runs MiniBits because of the existing networking stack, presumably. It's pretty hard to get a private domain, it's pretty hard to have a private IP address that's not linked to your identity, like he's presumably doxxed to the powers that be. And then existing solutions like things like Tor or whatever have a bunch of their own trade-offs and actually solve a bunch of things with centralization themselves and centralized blocklists and they have a bunch of—what about latency issues? Like, Tor’s slow as hell. Would this be slow as hell in comparison, or...?","offset":2888,"duration":55},{"text":"Arjen: It's not, uh, it's not onion routing, so—","offset":2943,"duration":4},{"text":"Odell: Because it's direct peer-to-peer?","offset":2947,"duration":1},{"text":"Arjen: It’s meant to be fast, so I I’m not making any any big privacy claims here. I I don't think it's necessarily way better than what we have. In some aspects it is, like it's encrypted hop-to-hop and then also end-to-end. Um, I think that helps. Of course, if you are the almighty observer of the entire network, I don’t think it's going to be much different from now.","offset":2948,"duration":22},{"text":"Odell: Fair enough. But right now we're forced to run through the almighty observer. In this case, we wouldn't be.","offset":2970,"duration":8},{"text":"Arjen: Yeah, yeah. I think that's actually a big thing with, with Tollgate, right? It changes the financial incentives. So if you have more, more actors, especially on, on the edges, right? You're always going to have the undersea cables or, like, major parties, that's fine, it's going to stay that way. But if you have entire communities that self-run and don't, you know, don't observe everything by choice, you can at least maybe only deduct that someone in this community looked up this thing, which is way better than always being able to point down everything to every individual.","offset":2978,"duration":31},{"text":"Odell: That's super cool. It's kind of like a—in that situation, it's almost like a hosted VPN, shared VPN kind of privacy model where you have a bunch of people coming out through the same IP address.","offset":3009,"duration":14},{"text":"Arjen: Well, yeah, I think it, I think it helps to introduce more people to convince to observe. Right. Now you just go to large ISPs and say, like, oh, you give me this information. Whereas with Tollgate, you have to go to maybe half a million ISPs because everyone is an ISP.","offset":3023,"duration":18},{"text":"Odell: Right. I mean, on the Tollgate piece, while I have you, a lot of people's concerns I've heard with the Tollgate project is like similar to running a Tor exit node. It's like, let's say I live in Paris and a bunch of random people are just connecting to my Wi-Fi and paying me sats and then looking up maybe questionable stuff. Yeah. What is your answer to those people on the Tollgate side?","offset":3041,"duration":25},{"text":"Arjen: Yeah. Um, I think the people that, like, have the connections to, um, basically to upstream, right? The general broader internet, should probably implement a specific block filters to block things that are like clearly illegal. Uh, but there's no clear-cut clear-cut solution to it. Um, but I think it's also why I want to move to local communities, doing everything local, where you should trust your community enough that everyone's, like, an honest actor, or I want to maybe. Maybe it's naive.","offset":3066,"duration":35},{"text":"Odell: Well, at least in small communities you definitely could. Yeah, yeah. I mean, small towns.","offset":3101,"duration":7},{"text":"Arjen: Yeah. It is a good point, but also it's not really—it’s like, are you going to abuse cars for—who’s responsible for producing—is the person that produces the cars responsible for, you know, anything anyone ever does with a car? Um, it becomes this this moral debate that is, you take either either one stance on.","offset":3108,"duration":25},{"text":"Odell: Yeah, I mean, it's not specific to Tollgate. I mean, you see this already with, like, coffee shops and stuff, right? Particularly in the developing world where you have bad cell connections, it's like every coffee shop becomes an ISP. They just don't have Tollgate there to charge people for it, instead it's just, you know, you're buying a coffee so you get the Wi-Fi password.","offset":3133,"duration":23},{"text":"Arjen: Yeah, yeah. But there's no, uh, there's no good answer. My personal opinion is that, you know, the internet is is should be open, open and free. I think the only counter-movement is that you observe everything and start to play police on every, every little thing, which is what we’re seemingly heading towards. I don't think that's the right future. Making everything, like, completely open and free, I think that's probably the best way and, like, solve things in the old-fashioned sleuthing way where you you go after bad people whenever the chance occurs.","offset":3156,"duration":35},{"text":"Odell: I think that's reasonable. I think that's what a lot of us are working towards. I just asked my bot to steelman FIPS. I think this conversation’s been fascinating. I think the project's really fucking cool, to be frank. I obviously need to play around with it. I’m hoping this conversation leads to more people trying it out, giving feedback.","offset":3191,"duration":25},{"text":"Arjen: Yes, please. We want we want a lot of people to test it.","offset":3216,"duration":4},{"text":"Odell: What's the process for—what like how does someone go about doing that? How should they think about participating here? Or testing it?","offset":3220,"duration":8},{"text":"Arjen: Yeah. So currently the repository, there's some, some manuals where you can compile and run it yourself. There's test cases, Docker, um, Docker-based meshes you can spin up quite easily. There's, like, step-by-step guides. Your LLM can do it. And we’re currently working on packaging, packaging it, uh, tarball should be ready any moment now, and I’m working on packaging it for OpenWrt routers and a bunch more. So then it should become easier to deploy it as well.","offset":3228,"duration":35},{"text":"Odell: I uh, okay, so I’m going to play around with it. Hopefully the freaks play around with it, give feedback. Those who can, will look over the the code and the specs and maybe provide feedback and advice on that side. Um, and then when I'm a little bit more fluent in it and more people are using it, I would love to have you back on when I can ask more reasonable questions, and I hope I wasn't too much of a struggle here. I think it will still be helpful to people.","offset":3263,"duration":28},{"text":"Arjen: No, no. These questions are these questions are valid and, and I have to make, like, you know, some of it ventures out of my my comfort zone as well. It’s a...","offset":3291,"duration":8},{"text":"Odell: It's just so much—there's a lot of things to it, and it's really hard to, you know, convey these things in a short manner as well. Uh, so I asked—I asked Opus 4.6, which is supposed to be the smartest of the models right now, to steelman your project. I’ve never done this before, but I'm just going to read what Opus said: \"FIPS embodies a principle that the Cypherpunks articulated decades ago. Privacy and freedom of communication should be enforced by mathematics, not by policy. Laws change, companies get acquired, governments get replaced, but the laws of cryptography don't change. A system where your privacy is guaranteed by encryption rather than by someone's terms of service is fundamentally more robust. FIPS is ambitious but not delusional. It's technically sound, addresses a real and growing need, is built by someone with relevant deep expertise, integrates with an existing ecosystem, and is designed to work even at small scale. If it gets even 10% of the way to its vision, it could provide genuinely life-saving communication infrastructure for people living under authoritarian regimes and a meaningful privacy upgrade for everyone else. The internet was supposed to be a network of peers; somewhere along the way, it became a network of subjects. FIPS is trying to make it a network of peers again.\"","offset":3299,"duration":78},{"text":"Arjen: Damn. You didn't even have to have me on. You could have just generated—","offset":3377,"duration":3},{"text":"Odell: That's pretty good, right? That was just a one-shot prompt to steelman FIPS, and I gave the URL obviously.","offset":3380,"duration":8},{"text":"Arjen: Yeah, that’s a great summary.","offset":3388,"duration":2},{"text":"Odell: Okay. Well, I had a great time. I'm excited, uh, I'm excited to see where this project goes. You have any final thoughts for the freaks before we wrap?","offset":3390,"duration":9},{"text":"Arjen: Test it. Give feedback. Break it. All that.","offset":3399,"duration":6},{"text":"Odell: Fair enough. I will link to the GitHub repo. I’m going to link to Sovereign Engineering. I think if you're a developer out there, you should check it out. It’s a really great program. Uh, anything else I should link to in the show notes for the freaks?","offset":3405,"duration":13},{"text":"Arjen: Tollgate.","offset":3418,"duration":1},{"text":"Odell: Tollgate. I’ll link to Tollgate. You are—are you on Nostr too? Do you have a personal npub on Nostr?","offset":3419,"duration":6},{"text":"Arjen: Yes, yeah.","offset":3425,"duration":1},{"text":"Odell: Okay. You don't have to say it out loud. You can just send it to me and then I’ll put it in the show notes as well.","offset":3426,"duration":4},{"text":"Arjen: I’ll send it.","offset":3430,"duration":1},{"text":"Odell: I'm not going to make you read the npub. Okay, Arjen, this was awesome. Uh, thanks for joining.","offset":3431,"duration":6},{"text":"Arjen: Yeah, thanks for having me.","offset":3437,"duration":3},{"text":"Odell: Freaks, I hope you enjoyed the show. Provide feedback. All links are at citadeldispatch.com. If you go to primal.net/citadel, it's the main Citadel Nostr experience. That's the best place to leave feedback, then the rest of the community can jump in and everyone can comment. I'll tag Arjen there in that post as well. Awesome. Love you all. Stay humble, stack sats. Peace.","offset":3440,"duration":24},{"text":"Arjen: Cheers. [Music] [Music fades]","offset":3464,"duration":15}],"logs":[{"elapsed":"0.0","message":"Downloading podcast episode...","detail":null},{"elapsed":"5.2","message":"Episode downloaded (52.9 MB) in 5.2s","detail":"File size: 52.9 MB"},{"elapsed":"5.2","message":"Episode: CD193: FIPS - FIXING THE INTERNET","detail":null},{"elapsed":"5.2","message":"Uploading audio to Gemini File API...","detail":null},{"elapsed":"12.1","message":"Audio uploaded in 6.9s","detail":"File ref: files/r058j8icjipo"},{"elapsed":"12.1","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"118.5","message":"Transcription complete in 106.4s","detail":"55555 chars received"},{"elapsed":"118.5","message":"Transcription tokens: 86,935 in / 14,677 out — cost: $0.0875","detail":null},{"elapsed":"118.5","message":"Parsed 161 transcript segments","detail":null},{"elapsed":"118.5","message":"Analyzing topics across 161 segments with gemini-3.1-pro-preview...","detail":null},{"elapsed":"185.8","message":"Topic analysis complete in 67.3s — found 19 topics","detail":null},{"elapsed":"185.8","message":"Analysis tokens: 15,669 in / 1,666 out / 5,875 thinking — cost: $0.1218","detail":null},{"elapsed":"185.8","message":"Pipeline finished in 185.8s — total cost: $0.2093 (124,822 tokens)","detail":null}]} \ No newline at end of file diff --git a/history/1773185576199-YThlOTAyMWYtOTU4.json b/history/1773185576199-YThlOTAyMWYtOTU4.json new file mode 100644 index 0000000..b49d0cb --- /dev/null +++ b/history/1773185576199-YThlOTAyMWYtOTU4.json @@ -0,0 +1 @@ +{"id":"1773185576199-YThlOTAyMWYtOTU4","videoId":"a8e9021f-9587-4197-a1ab-820823d1e559","url":"https://serve.podhome.fm/episode/8029725b-0319-44b9-4793-08dc404e83a4/639086745068447337a8e9021f-9587-4197-a1ab-820823d1e559.mp3","title":"CD194: SIDESWAP - LIQUID PREDICTION MARKETS","type":"podcast","topicCount":13,"segmentCount":166,"createdAt":"2026-03-10T23:32:56.199Z","uploadDate":"20260309","chunks":[{"title":"Introduction & Citadel Dispatch Updates","summary":"The host introduces the episode, shares current Bitcoin metrics, thanks supporters, and introduces Scott from Sideswap.","entries":[{"text":"Host: Happy Bitcoin Monday freaks. It's your host Odell here for another Citadel Dispatch, the show focused on actionable Bitcoin and freedom tech discussion. The current block height is 840,011. That brings us into Fiat time. Fiat time, it's Monday March 11th, um they just did the timezone change on me, at 17:00 UTC, no, 16:00 UTC.","offset":0,"duration":46},{"text":"Um, you guys will probably be listening to this in a couple of hours. I don't like sitting on it, I like to get it to you ASAP. Current sats per dollar is 1,452. Current price in dollars is 68,863. And the current price in gold is one Bitcoin, you can get one Bitcoin for 12.84 ounces. Um, Bitcoin's down on gold on the day, the month, and the year, but we're slightly up on the week. Something to keep an eye on.","offset":46,"duration":52},{"text":"As always, Dispatch is supported by viewers like you. We have no ads or sponsors, so thank you to everyone who continues to send Bitcoin donations to support the show. The two largest supporters, I'm going to say from uh the last two weeks since, or the last two episodes since they were back to back, was we have Mav21, he sent two separate 10,000 sat zaps, both saying \"great rip\". Thank you Mav21, true ride or die.","offset":98,"duration":35},{"text":"And we have Captain Cook with 7,654 sats. He had no comment, but thank you for your support. As always, sharing with friends and family also goes a long way. Dispatch is available in all of your favorite podcast apps by searching Citadel Dispatch. All relevant links are at Citadeldispatch.com. And recently I've been playing around, I also launched Citadelwire.com where you can listen to the most recent Citadel Dispatch, the most recent Rabbit Hole Recap, um and get on demand news um from my soulless robot slave who I've been training and curating to try and provide the most relevant news using live market data.","offset":133,"duration":47},{"text":"Um, I got Poly Market plugged into him and Bitcoin prices and a bunch of other data sources, so that's a bit of a work in progress, but check it out at Citadelwire.com. Anyway, we have a great show lined up today. I have Scott here, he is the co-founder of Sideswap. Sideswap is, has just been grinding along building great product in the Liquid ecosystem. Something we haven't talked about for a while on the show. Um, how's it going Scott?","offset":180,"duration":32}],"startTime":0},{"title":"Introduction to Sideswap & Non-Custodial Swaps","summary":"Scott explains the foundational premise of Sideswap as a non-custodial wallet and swap market for Liquid assets. They discuss how the app facilitates easy swapping between regular Bitcoin, Liquid Bitcoin, and Liquid Tether.","entries":[{"text":"Scott: Hey Matt, uh thanks for inviting me. Yeah, uh everything's been going very well. Sideswap's been growing very nicely these past few years. Uh started out quite slow but we're growing organically and cash flow positive and um very happy with where we are. We focus much on the tech and building out what we hope is a great product liked by users. We don't focus much on marketing, which is why you may not have heard of us much.","offset":212,"duration":33},{"text":"Host: Yeah, so I mean, I was not really familiar with you guys. I like kind of a little bit a couple years back. Um, and then I started playing with Samson's Aqua Wallet, which more people might be familiar with, which is tries to do lightning um and Bitcoin with with Liquid as the base at rest. So it sits in Liquid and then it does swaps for receiving and sending. Um which we've seen a couple wallets do that.","offset":245,"duration":36},{"text":"Bolt Wallet has been doing it recently. Breeze has their own SDK that uses it as well. Breeze has like two rival SDKs in-house, one does Liquid and one does Spark. Um but I was playing around with Aqua Wallet and then I saw on the backend they were using you as the provider, which was cool. And then I was like, \"Okay well let me see what they're doing directly.\" And that's that's kind of how I was reintroduced to you guys and we had a mutual friend put us in touch and I it's just it's impressive what you guys have been quietly building with like you said, very little fanfare.","offset":281,"duration":39},{"text":"So I mean, to the freaks um to our audience here, what is Sideswap, how should they think about Sideswap?","offset":320,"duration":7},{"text":"Scott: Mm, well well Sideswap at its base is really a non-custodial wallet and it's based on the Bitcoin premise that your keys, your coins. So when we built the swap market, since Bitcoin doesn't have other assets other than Bitcoin on chain, we started looking at the layer twos. And since Tether was issued on Liquid, we figured we could build swap markets where we effectively have atomic swaps between two parties.","offset":327,"duration":32},{"text":"So you can create a bulletin board type of system and you trade a swap between the two parties so that settlement happens atomically and instantaneously real-time between the two counterparts to the trade. So we're never custodial of anything really, and that's a model that we're very much looking for. And the model we think everyone should really aim for and not go for the custodial model.","offset":359,"duration":34},{"text":"Host: So the correct- yeah, go on.","offset":393,"duration":2},{"text":"Scott: No no, you continue please, sorry.","offset":395,"duration":3},{"text":"Host: I mean, so the way I look at it is for the average person, at least on the surface, Sideswap is an app that you can download on your phone that lets you easily go from regular Bitcoin to Liquid Bitcoin and vice versa. And then if you want access to Tether, you can then easily swap between Liquid Bitcoin and Liquid Tether, correct?","offset":398,"duration":35}],"startTime":212},{"title":"Sideswap Mechanics: Order Books and D-Pix Adoption","summary":"Scott details Sideswap's peg-in and peg-out services, emphasizing their transparent order book system. They also discuss the surprising transaction volume growth from the Brazilian stablecoin D-Pix compared to Tether.","entries":[{"text":"Scott: Correct. So what one of the first big hurdles that we encountered was obviously getting people to move between the main chain and the Liquid sidechain. We effectively built one of these peg-in, peg-out services since very few people can be uh they they don't want to sit there and sync a full node on both the Bitcoin side and the Liquid side in order to be able to uh create the claim scripts and issue coins on Liquid.","offset":433,"duration":31},{"text":"And many of the services at the time had a very high fee, so we cut that down to 0.1% and had effectively a bridging service which anyone can use, which Aqua also uses. So um it's a 50-50 revenue split on anyone who's a partner and just uses our infrastructure, so they don't need to build it up themselves. And um with that done, uh we started focusing on the swaps on Liquid so that two participants can trade between themselves without having any intermediary.","offset":464,"duration":40},{"text":"So we effectively just offer a bulletin board system so that users can find each other and we and we help make sure that the swap has integrity, so that one party can't cheat the other one by effectively saving half-signed UTXOs which they could theoretically broadcast at a later date. And so the way we've built it, we also offer instant swaps but the way it's built we actually offer order books where anyone can come in and uh improve prices within the order book.","offset":504,"duration":34},{"text":"And any instant swap is effectively a market order into the order book. So dealers compete on pricing, um so hopefully we get spreads which become a lot tighter. Right now I think the spreads are about 0.2, 0.3% away from uh let's say the midpoint price many times. And um yeah, so there's lots of trading opportunities and lots of liquidity. The areas that we've really seen grow, initially it was a lot around um USDT but lately it's been D-Pix. It's really really grown in the Brazilian market.","offset":538,"duration":46},{"text":"Host: What is D-Pix? I saw it in the wallet.","offset":584,"duration":4},{"text":"Scott: Uh D-Pix is a Brazilian stablecoin uh issued by a company I believe called Ulem. So they have been behind much of the uh increase in adoption within Liquid lately.","offset":588,"duration":25},{"text":"Host: Fascinating.","offset":613,"duration":1},{"text":"Scott: Yeah, so if we look in our swap market just in terms of trades and transactions, I'd say D-Pix is probably the biggest market right now. Not in terms of volume, but in terms of transaction count.","offset":614,"duration":16},{"text":"Host: In transaction count D-Pix is the biggest, but in terms of total amount, Tether's still bigger?","offset":630,"duration":8},{"text":"Scott: Much bigger.","offset":638,"duration":1},{"text":"Host: Yeah.","offset":639,"duration":1},{"text":"Scott: People are a lot more comfortable holding Tether obviously.","offset":640,"duration":4},{"text":"Host: Yeah, they've been around for I mean, Tether's bread and butter is the high net worths, right? They've been around for a decade plus.","offset":644,"duration":9},{"text":"Scott: Uh exactly, whereas um I think D-Pix is many local payments within the Brazilian ecosystem, but it brings in a lot of users even if their transaction volumes aren't that large.","offset":653,"duration":16},{"text":"Host: How do I spell D-Pix?","offset":669,"duration":3},{"text":"Scott: D-E-P-I-X.","offset":672,"duration":3},{"text":"Host: D-Pix stablecoin. Interesting. So so okay, there's a couple things here. First of all, the order book thing is fascinating. It's like in general, a lot of these quote-unquote instant swap services you see are first of all custodial and second of all, they're kind of like a black box in terms of pricing. So it's cool that you actually have like a proper order book that basically anyone can participate in and become market makers. And as a result, it's more transparent pricing and theoretically, I guess, it should be better pricing.","offset":675,"duration":48},{"text":"Um I think it's pretty cool that you can actually participate in the order book on mobile, which makes accessibility good. But I assume it's quite obvious if you look at the order book for a little bit, like there's at least there's like one or two like real market makers there that are putting up more size than others. Are they using- they're not using like a mobile wallet, right? Like they is there like a CLI or something that they're accessing the order book with?","offset":723,"duration":36},{"text":"Scott: Uh we we've built quite a suite of tools. So in our GitHub repo, anyone can download the dealing software and if anyone needs help setting things up, um everything's available and you can yeah, run your own frontrunning code. So um I think we had a bit of an issue with that at one point since people were flooding the system with lots of quotes. But um yeah, growing pains like are good pains.","offset":759,"duration":35}],"startTime":433},{"title":"Liquid's Privacy, Confidential Transactions, and Tether","summary":"The conversation shifts to Liquid's slow adoption and how its confidential transactions offer superior financial privacy compared to Tron or Solana. They discuss why Tether adoption on Liquid remains relatively low despite its unconfiscatable nature and payjoin capabilities.","entries":[{"text":"Host: Yeah, I agree with that. Um okay, fascinating. I mean, before we continue on, I mean, I think the big question that we've been asking on this show for years now um and I think Bitcoiners have been asking for a while is ironically the lack of liquidity on Liquid and the lack of users using Liquid. It seems like cautiously optimistic in terms of adoption increasing lately, and I would say partially it's probably these wallets that are using Liquid at rest for Lightning payments, specifically Bull and Aqua Wallet.","offset":794,"duration":44},{"text":"I mean, the fact that Liquid has confidential assets which incorporates confidential transactions, so each transaction you can't see the amount or the asset that's being sent, whether that's Bitcoin or Tether or whatever, um means that people that, you know, maybe are in the developing world that are sending um 20 cents worth of Bitcoin, you can't tell if that's $2,000 worth of Bitcoin or 20 cents worth of Bitcoin. So it actually compounds kind of beautifully in terms of adding, I guess, anonymity set to to Liquid.","offset":838,"duration":50},{"text":"Anyway, this is kind of a long-winded question, but where do you see Liquid adoption? Have you been frustrated with the lack of adoption? Do you- are you still opti- I mean, I assume you're still optimistic on adoption and how can that be accelerated? Because it kind of feels like Liquid has always been like the ugly stepchild of Bitcoin that just hasn't really found its wings.","offset":888,"duration":27},{"text":"Scott: No no, correct. I think much has to do really with Bitcoin being a one asset chain, it didn't really have any scripting abilities or or ability to issue other assets so that you could trade things like atomically. So so there was no real layer two which could really scale Bitcoin. So I think when all of these other chains came around and they offered all the smart contracts etc., very easy for anyone to get involved. I think that took out took off a lot.","offset":915,"duration":37},{"text":"And many of the exchanges I think focused on offering products and development within that area since there's a lot of money flowing in and promise. But I think as time goes on, I think Bitcoin which is like the settlement layer, developed properly and financial markets, it may have taken a bit more time. But I think Liquid is a step in the right direction in terms of how you build secondary layers. There's lots of questions around the making the two-way peg trustless and how you can go about that and the federation model and- but if we skip that side of the discussion, it's very nice to have an asset layer which is like Bitcoin-based, UTXO-based, that can hold multiple assets so that you can have these financial transactions, the swaps and everything else around it.","offset":952,"duration":55},{"text":"So I just think that side has taken a lot of time to get going, especially since it requires you to manage your own keys. I think none of the big wallet custodians like Fireblocks or anyone else has integrated Liquid so it hasn't been very easy for any exchange to offer it. So it basically onboarding one by one people are comfortable to holding their own keys. But going forward, I think now that Simplicity is live on Liquid, uh I think there's a lot of things that can be done and will offer a lot of fantastic features to users such as being able to create prediction markets in a Bitcoin-native type of ecosystem.","offset":1007,"duration":52},{"text":"Host: Yeah, I mean I want to jump in there specifically on the prediction market stuff, but before we do, just real quick I mean like my fascination with Liquid has always been on the privacy side, specifically confidential transactions. Um you know, a lot of the probability analysis that Bitcoin chain surveillance firms do is based on amount correlation. And once you remove those amounts from being visible, it makes their job of detecting when ownership has changed hands much more difficult.","offset":1059,"duration":52},{"text":"On the asset side um let's be frank, I think most tokens that have been launched in crypto are just straight up scams and the ones that aren't are also just probably horrible investments except for the undeniable US tokens, specifically Tether, right? And we've seen a massive market for Tether on Tron specifically, to a lesser extent on Solana and Ethereum. Um and it's fascinating to me because if you use those ecosystems, it's even worse than Bitcoin privacy. It's like you have a fixed address that is literally your entire transaction history.","offset":1111,"duration":69},{"text":"And so where I'm going with this is right now it seems like I'm cautiously optimistic that financial privacy in quote-a-quote broader crypto space seems to be having a moment. First we saw it kind of with the Zcash pump and dump and then recently Ray Dalio and Chamath both mentioned financial privacy as a concern. And I think part of it is because of of not even Bitcoin like Bitcoin could have better privacy but it's still relatively accessible. But the privacy situation on a Tron or a Solana is absolutely abysmal. It's horrible.","offset":1180,"duration":51},{"text":"Um so I'm surprised that there hasn't been more uptick on just the Tether use case. Like if you want to use Tether, which obviously has a trusted third party and I've never advocated for people to use Tether but there's plenty of demand for people that want Tether and want access to US dollars where they can't get it otherwise. The most private way to access Tether is through Liquid and specifically through Sideswap because you make peg-ins so easy um and peg-outs so easy and you make the ecosystem much easier, much more accessible.","offset":1231,"duration":48},{"text":"Why do you think we haven't really seen like like let's nail down specifically on Tether like why haven't we seen specifically massive Tether adoption on Liquid? It's like it's pretty much negligible compared to the other chains.","offset":1279,"duration":19},{"text":"Scott: It- it's absolutely nothing. I think there was about $35 million of Tether circulating on Liquid up until a few months ago when it when it was increased to 90-something million. So if you compare that to the other chains it's a drop in the bucket. Well- I think also much of the liquidity on the other chains uh is not really held in private wallets, it's held with custodians in one shape or form. Um with Liquid, since there are no custodians, um effectively people who are comfortable holding their own keys and assets, Bitfinex effectively custodying the balances for you.","offset":1298,"duration":52},{"text":"But something that's very interesting, which few people might have considered, is that USDT on Liquid, it's the only- due to the confidential transaction nature of it, the issuer cannot confiscate the balance. They- they don't know which UTXOs are USDT.","offset":1350,"duration":20},{"text":"Host: Yeah they'd have to confiscate it basically they'd have to like basically shut down Tether on Liquid is what they could do. But they can't do their like pick and choose \"I'm blocking this Tron address\" or whatever.","offset":1370,"duration":17},{"text":"Scott: Not like they can do on the other chains.","offset":1387,"duration":2},{"text":"Host: Yeah, that's why it's wild to me that just the Tether use case alone has- and so okay, they have a website USDT.network that tracks all of their usage across the different chains. Just just for reference for the freaks. I mean Scott said, what'd you say, you said 95 million Tether on Liquid?","offset":1389,"duration":22},{"text":"Scott: Yeah, I believe it's about- in that ballpark area.","offset":1411,"duration":5},{"text":"Host: Okay, well anyway it's completely negligible. The- there's $92 billion worth of Tether on Ethereum, $85 billion on Tron, just to with a B, just just to show the discrepancy. On the privacy side, I think it's also pretty cool that basically in practice, am I correct in saying that anyone who's doing a swap between Tether and Bitcoin, Lightning Bit- Liquid Bitcoin and Liquid Tether, is basically a payjoin transaction. And payjoin works even better on Liquid because of confidential transactions than it does on Bitcoin in terms of breaking probability analysis.","offset":1416,"duration":78},{"text":"Scott: I think there's a few different aspects to that. Um payjoin is something that we offer for people who have wallets where they don't have Liquid Bitcoin and need to pay the network fee. So- so we do lots of payjoin transactions every day. I think there's about 2 or 3 cent fee which covers- includes the network fee. So- so it's very cheap to do these payjoin transactions.","offset":1494,"duration":40},{"text":"And um when we have swap markets where you have two assets traded against each other, um where you don't have Liquid Bitcoin as one of the assets, we actually pay the network fee on behalf of the user in a payjoin with the swap. And since the swap there's two different assets being exchanged, it's very very little- the heuristics become very very difficult to- yeah, it's pretty wild, and particularly at a small user base, which is obviously the single biggest thing holding back Liquid as a as a more robust privacy tool. But it's impressive that it breaks it already breaks even at a smaller usage, it still's breaking a lot of heuristics. It makes it quite difficult.","offset":1534,"duration":66},{"text":"Yeah, and especially with the peg-in, peg-out process when you peg in and then you peg out, the federation also selects the UTXOs that you get when you peg out so there's no correlation between the two.","offset":1600,"duration":16},{"text":"Host: Right. They just know it came from the Liquid network. Like if you pegged out and then sent to Strike, they would know that those are Liquid-affiliated transactions but there wouldn't be a direct connection between peg-in and peg-out.","offset":1616,"duration":18},{"text":"Scott: But mind you, this was like two, three years ago, we we ran the UTXO set of Liquid through one of the chain analysis tools, and the UTXO set is effectively pristine since Bitfinex is responsible for um a decent chunk of it.","offset":1634,"duration":22}],"startTime":794},{"title":"Building Bitcoin-Native Prediction Markets","summary":"The host highlights the flaws in centralized prediction markets like Poly Market, advocating for a self-custodial, Liquid-based alternative. Scott explains how they are adapting their order books and using Simplicity to fund binary contracts, while acknowledging the unresolved oracle problem.","entries":[{"text":"Host: Fascinating. Oh yeah, I mean yeah let's talk about I mean you mentioned it, let's talk about prediction markets. I mean to me one of the big shames is that we I mean Bitcoiners have been talking about prediction markets for over 10 years now and they finally hit critical mass and the biggest one is on Polygon and uses USDC as its primary base asset, um that being Poly Market.","offset":1656,"duration":42},{"text":"Obviously like the functionality specifically with something like prediction markets, you need it to be self-custody, you need to not have liquidity concerns. These things make it very difficult to run any kind of prediction market on Lightning. We've seen a competitor pop up called Predics that is basically just a custodial wallet, you know, with managed payouts, which I think is just not sustainable or scalable, um and has massive, you know, regulatory exposure.","offset":1698,"duration":37},{"text":"Liquid seems like it could be ideal for a Bitcoin-native prediction market because it has simplicity, because you can do self-custody type smart contracts, because you have privacy. I mean we're seeing on the Poly Market side people's wallets are being tracked. They're like, \"This person was successful on these six different military markets, like they must be an insider with the Israelis or an insider with the US\" or whatever. Like it's getting arguably as it's made it more obvious why financial privacy is important on blockchains than actual financial transactions themselves because a lot of these markets are quite sensitive. So how are you thinking about prediction markets, Liquid, what kind of opportunities are there?","offset":1735,"duration":89},{"text":"Scott: Um well I think there's many aspects to your question. The first point you raised now with the insider trading ahead of the Iran, where someone seemingly made quite a bit of money betting on the 28th I believe. Um in terms of prediction markets being built on Liquid, I think it's still a bit out. We've done so much work in the background because there's so many building blocks that need to come into place before you actually build it.","offset":1824,"duration":33},{"text":"So what we've been building in the background is effectively a Liquid Connect type of function so that anyone can plug their wallet into a web page or that the web page can connect with a wallet so that you can send these transactions to the wallet directly because these swap transactions, especially with Simplicity contracts, can become shall we say fairly messy, non-standard, not super easy to do. So it requires a bit of work in that regard, a bit of like Metamask type of features but for Liquid.","offset":1857,"duration":51},{"text":"So we we've done much of that work, hopefully should be I mean we have it ready and in production but it should be a lot more useful I think next week. And we should release um a public API so that anyone can integrate. But um so that was the first step and then the second step is how do you build these prediction markets? So with Simplicity you can build these binary contracts and we've started playing around with it.","offset":1908,"duration":38},{"text":"I'm still not entirely sure all of the limitations, you can create these binary contracts um between two people and you have an oracle that determines the outcome um of the contract. So as long as the two parties trust the oracle, you can effectively bet on anything. But- but then the question becomes also how do you get people to fund the contract at the same time?","offset":1946,"duration":30},{"text":"Because if you create markets where someone needs to fund the contract initially and then someone funds the contract at a later date, you need to create some form of market structure that allows for that. What- what we've done is we've applied our order book and our swap market to it. So we're looking at creating markets where you have a instead of an order book that goes from with a Bitcoin price say from wherever it is now um $70,000. So you have an order book that goes from 0 to 100 effectively.","offset":1976,"duration":47},{"text":"And so the bid will be the yes outcome and the offer will be the no outcome. And wherever you bid within that order book is the prediction rate. So- so whoever's on shall we say the yes side, it bids 30 um they fund the contract with 30 cents and the offer will need to fund it with 70 cents. So that there's one full dollar in the contract and once the contract um once the prediction either comes true or false, when the oracle has a definite outcome, it's a winner-take-all type of situation where everything goes to one of the two parties.","offset":2023,"duration":50},{"text":"And that's effectively how you price it. So with our order book structure, we can create that so that two parties enter into a swap at the same time and that the contract is funded with the swap at once. So that you don't have the issues of who goes first etc. funding a contract and creating an order book with resting orders and people having locked up funds waiting for other users to come in etc. etc. To be honest, I'm not sure how Poly Market's done it. I know their order book's quite efficient but the question is how does it actually work under the hood?","offset":2073,"duration":43},{"text":"Host: I'm pretty sure they're basically trading yes and no tokens on each market has their own token. I mean the user doesn't see it.","offset":2116,"duration":10},{"text":"Scott: Mm, that's one option of going about it but the other option is creating the contract directly and you have the two users fund the contract.","offset":2126,"duration":12},{"text":"Host: Yeah, there's a couple different things right? Because it's like okay with prediction markets for prediction markets to work at scale you need a couple things. You need uh you need the ability for people to participate anonymously because the whole idea is trading prediction markets benefits insiders, tracking and watching prediction markets benefits outsiders because you're giving insiders an incentive, a financial incentive to effectively tip their hand and and trade a market which then exposes um which exposes their belief on how that market will what the outcome will be.","offset":2138,"duration":51},{"text":"So they need to be able to do it anonymously because if they work for Intel or if they work for a government or something they're not going to do it unless they can do it anonymously. So with that understanding, then it needs to be at least relatively decentralized and self-custodial because if there's a single company that is controlling funds and controlling payouts, then they're ultimately going to be pressured by a government to dox all users. So you're never going to have permissionless participation unless it's relatively decentralized.","offset":2189,"duration":44},{"text":"And then the last piece is the oracle problem, which is how do you how do you determine in a um robust and objective way what actually happened to settle the contracts afterwards. And so Poly Market like kind of made it there on all of those pieces but they kind of hand-waved a bunch of stuff away. Like Polygon itself, you know, I think could be argued that it's still pretty centralized. Ethereum very centralized. USDC obviously is completely centralized and can be frozen at will.","offset":2233,"duration":52},{"text":"Um the oracle problem they haven't actually solved, they just offload it. It's like they don't make the decision, they have like for each market there's a designated quote-a-quote on-contract oracles so there's it's still crypto-native if you will but it's still ultimately, you know, centralized entities saying ESPN reported that the game um was, you know, the Clippers won the basketball game or whatever.","offset":2285,"duration":32},{"text":"Uh so they didn't solve the oracle problem and they're like quote-a-quote decentralized enough to not have to do KYC and block people's access to markets. Um and I think this is just something interesting by the way for Bitcoiners and Liquid where the shitcoiners have done a really good job of kind of being pragmatic about tradeoff balance when it comes to censorship resistance and decentralization that Bitcoiners have not been.","offset":2317,"duration":22},{"text":"I mean I we haven't really touched on it but there's a lot of controversy for instance around the Liquid Federation model and whether or not it is technically self-custody or not. But if you which is something that's I think unique to the Bitcoin community because if you look at something like Tron, it's pretty much the same trust model as Liquid but Tron has gotten a pass from regulators, they consider it decentralized enough. And Tron, like I said earlier, has $85 billion of Tether volume alone on it, which is a wild stat.","offset":2339,"duration":35},{"text":"So to me Liquid could be this middle ground for Bitcoiners. And we could actually I mean there could actually be a trust model set up on a Liquid-style prediction market that is significantly better than Poly Market, which is right now operating at scale with very sensitive markets at a $10 billion-plus valuation with many many users. And it seems like too good of an opportunity to to miss out. So I mean on that point, that was very long-winded, but you more than anyone, you know you've been quietly bootstrapping and building a business on Liquid, how do you think about that trust model in terms of the federated model? Because I mean it could kill your business if if it wasn't um sufficient enough, let me put it that way.","offset":2374,"duration":45},{"text":"Scott: Of course, and that's also one of the growing pains that we'll need to encounter at some point. But right now while we're so small, I I think no one's looked um deeply enough at all of these questions in terms of Liquid, the Federation, how it's structured set up, is it decentralized enough etc. etc. Uh right now we're very much just focused on getting the market model correctly, getting everything easy for users to access, make it easy to trade.","offset":2419,"duration":29},{"text":"Since everything's non-custodial, you hold your own wallet, you hold your own keys, the contracts are on chain, you swap into it can be verified uh within the wallet by the users prior to executing the swap. But then there's all the ques- so the question is is that decentralized enough? It's very difficult to say, like different regulators may take a different view given the Liquid governance model very unclear.","offset":2448,"duration":29},{"text":"Um then there's I think all the questions around how the oracle is constructed etc. We're not trying to solve all of these like shall we say philosophical or mathematical questions right now, we're just focusing trying to get the market structure correct. And once we have that in place, we can start tinkering around the edges with everything else. I think the oracle problem's not super easy to solve. Blockstream's working on it, they they have a model that they've proposed. Um is that good enough? Not sure.","offset":2477,"duration":34},{"text":"Host: I mean, like I said, it's not like Poly Market has solved it. It just needs to be robust enough. It's never going to be- we're not going to- I'm convinced that the oracle problem is is unsolvable. You can mitigate it, you can create a relatively usable and decent and robust solution but actually quote-a-quote solving the oracle problem, solving something happening in the real world and then being able to cryptographically prove it on chain is going to require some trusted third parties that are cryptographically proving it on chain.","offset":2511,"duration":45},{"text":"Those trusted third parties, you can reduce their influence or risk by combining multiple of them, by adding reputation systems. I think DLCs are interesting where they're providing oracles but they don't know which market they're providing oracles for. There's different ways you can do that. But at the end of the day, for someone on chain to know what the weather was in Chicago yesterday, like there's going to be trusted third parties. There's I- I don't think it's solvable in that regard.","offset":2556,"duration":15},{"text":"Scott: There's no way around it I think.","offset":2571,"duration":2}],"startTime":1656},{"title":"Evaluating Trust Models: Liquid vs. Tron","summary":"The host and Scott debate the tradeoffs of Liquid's federated trust model against other scaling layers and networks like Tron and Spark. They emphasize that while pure self-custody is ideal, secondary layers inherently involve complex decentralization tradeoffs.","entries":[{"text":"Host: Yeah, exactly. And on the on the point of Liquid, I mean would you agree with me like if Tron is self-custody, if you consider Tron self-custody, I think you have to consider Liquid self-custody. I mean Justin Sun is basically the arguably the model for Tron is worse than Liquid in terms of censorship resistance and trusted third parties.","offset":2573,"duration":17},{"text":"Scott: I- I would say so, obviously I'm biased, um my hope as well is in that direction so take it from what it is.","offset":2590,"duration":9},{"text":"Host: I will say that I think um where we're seeing, I mean the big one that everyone is I mean anyone who's actually building in the space has been paying attention to is Spark. Um and there's a lot out of Lightspark, which is David Marcus's A16Z-funded company after he was formidably working for Facebook for Meta. And I'm already seeing like the Bitcoin culture fights over whether or not that is considered self-custody. Um and it's a similar idea of a pragmatic approach that is maybe more similar to what we see in shitcoin land but I think could be very useful for Bitcoiners.","offset":2599,"duration":37},{"text":"Yeah, and I wonder if that will bring more attention to Liquid because I mean if you mono-a-mono it out, I think the Liquid model is more robust than the Spark model. Um and then you have other things, I love the Phoenix team with Async. Um like the trust model for that is not as clear cut as you hold your keys, you have self-custody. On-chain is very clean. On-chain Bitcoin's very clean, it's either self-custody or it isn't. Once you start playing with the tradeoff balances across the stack, things get a little bit more definitionally messy. And I think the Bitcoin community specifically has been wrestling with that for many years now.","offset":2636,"duration":41},{"text":"Scott: Well- I mean if you look at how the financial system is built, you effectively have a central bank they they operate one ledger. Uh then you have all the commercial banks below, they each operate their own ledger. So if you want to move cash from one one bank to another, it's actually the bank's accounts at the central bank that need to be updated before the banks themselves update their own accounts. So the whole financial system is built on lots of different ledgers and all these clearinghouses are effectively the ones managing the risks between the different ledgers and um shall we say the net deferred settlement between ledgers.","offset":2677,"duration":37},{"text":"So for Bitcoin to scale given that it is a one-asset chain, you need these secondary layers somehow. Since there's no solution yet exactly of how to create these exact or trustless two-way pegs between the Bitcoin main chain and a sidechain, that there is always going to be these different tradeoffs and discussion around how decentralized it is, at what point do the regulators consider it being decentralized or not. So there's always these questions.","offset":2714,"duration":34},{"text":"Host: Yeah of course. It's just an interesting it's an interesting um interesting thoughts to go down. Um I'm sure we're going to get comments about it too which is why it's incredibly important to talk about it. Um pretty much they come up anytime Liquid is brought up. And I think rightfully so. I think it's good that the community is at least a subset of the community, which percentage-wise is getting smaller by the day but absolute numbers-wise has never been higher, cares so much about these hard questions and sovereignty and and using these things in freedom-oriented ways while like like I said, like shitcoiners kind of just throw it out the window and think of it as an afterthought. You guys recently launched a new product. Are you at liberty to talk about it right now or?","offset":2748,"duration":53}],"startTime":2573},{"title":"Introducing Swaption and Liquid Connect","summary":"Scott unveils Swaption.io, a proof-of-concept platform featuring binary outcome contracts for Bitcoin's price. He also introduces Liquid Connect, a tool that allows users to link their Liquid wallets directly to web applications.","entries":[{"text":"Scott: Yeah, sure. Um so this is like our first dipping our toes into the Simplicity uh shall we say pool if we're in the Liquid space. But- but what we've effectively what- we have this website or sister website called Swaption, uh where we've plugged this Liquid Connect which is a bit of a privacy dox since if you do connect you share the watch-only wallet with Liquid Connect because otherwise it wouldn't be able to help you create the transactions and everything within your wallet and send the transaction for signing to your wallet. So there is that aspect to consider.","offset":2801,"duration":39},{"text":"Host: Would you- similar to the tradeoff with using like an Electrum server right? On-chain Bitcoin.","offset":2840,"duration":5},{"text":"Scott: Uh yeah. No no, exactly.","offset":2845,"duration":3},{"text":"Host: Right, okay, continue.","offset":2848,"duration":2},{"text":"Scott: There is that tradeoff. Um I mean, we never data mine our users or anything else. Uh so- but I mean, there's no way for users to verify that. But- but in terms of Swaption, so with the Liquid Connect function that we've developed with the wallet, if you visit the Swaption webpage, what we've built is the first binary outcome contracts, which is the first step in the direction towards prediction markets effectively.","offset":2850,"duration":29},{"text":"So we have two different products. One is \"Will the Bitcoin price be higher or lower in shall we say two, five or ten minutes than it is now?\" Um and then the other product is \"Will the Bitcoin price of Bitcoin go up or down like 1, 2, 3, 4 or 10% first?\" So it's a binary outcome, does it go up or down 10%. So people can make a bet in terms of direction etc., hedge positions um with leverage.","offset":2879,"duration":27},{"text":"So the idea was also here to open up so that anyone can trade in the order book and provide liquidity and improve prices etc. So right now there's not fantastic payouts but we're working very hard in that direction to create these order book type of markets so that anyone can come in and provide liquidity.","offset":2906,"duration":19},{"text":"Host: So I mean, your main website is sideswap.io?","offset":2925,"duration":4},{"text":"Scott: Correct, that's- that's where you download the app and the webpage is being reworked as well, so soon you'll be able to use the Liquid Connect and trade via the webpage as well.","offset":2929,"duration":10},{"text":"Host: And then Swaption is- is it swaption.com?","offset":2939,"duration":3},{"text":"Scott: .io.","offset":2942,"duration":1},{"text":"Host: swaption.io. And then that's S-W-A-P-T-I-O-N. Um I'll put all these links in the show notes. And then Liquid Wallet Connect is basically I have the Sideswap app on my phone or another compatible Liquid wallet, which I don't think there are any right now?","offset":2943,"duration":15},{"text":"Scott: Yeah, none.","offset":2958,"duration":1},{"text":"Host: Yeah. And then I'm like scanning a QR code on the website to sign in basically, right?","offset":2959,"duration":4},{"text":"Scott: Correct, or if you have a desktop wallet, it will detect the desktop wallet with the browser.","offset":2963,"duration":6},{"text":"Host: Do you have a desk- Sideswap has a desktop wallet too?","offset":2969,"duration":3},{"text":"Scott: Yeah. Well we've built everything in Flutter, so it's very easy to go cross-platform.","offset":2972,"duration":6},{"text":"Host: And then so you're saying this is kind of in a lot of ways it's kind of a proof of concept because it's a relatively simple type of market that you could have compared to a prediction market.","offset":2978,"duration":9},{"text":"Scott: Exactly. So we're dipping our toes, this is like the first MVP that we push out. There's only one dealer we don't allow yet, but that's coming, that anyone can compete and improve prices. Um and then the next steps are obviously developing these open order books so that anyone can come in. Maybe add functions such as auto-signing etc. in the Liquid Connect so that users don't need to sign every transaction so it becomes a bit more Poly Market-if you will.","offset":2987,"duration":31},{"text":"Uh so there's lots of these thoughts in terms of different directions we can go. We'd love for Aqua and other wallets obviously to integrate so that it becomes ubiquitous within the Liquid ecosystem. Liquid Wallet Connect.","offset":3018,"duration":11},{"text":"Scott: Yeah.","offset":3029,"duration":1},{"text":"Host: No that makes sense to me.","offset":3030,"duration":1},{"text":"Scott: But it's developed by us so- so it's called Liquid Connect but let's see if others pick it up or if it's actually Sideswap Connect.","offset":3031,"duration":8}],"startTime":2801},{"title":"Permissionless Asset Listing and Network Effects","summary":"Discussing the importance of open standards, Scott explains how other wallets have integrated Sideswap's infrastructure through a revenue-share model. They highlight the Cypherpunk nature of Liquid, where assets like D-Pix can list permissionlessly without exorbitant fees.","entries":[{"text":"Host: Fair enough. Um I mean we kind of have a similar situation in the Nostr ecosystem where we have an open standard called NsecBunker that uses you either paste a code or or use a QR code scan, I think QR code scan makes a lot of sense if like the user has a mobile phone, they're like scanning it with a QR code. But the reason I bring it up is because we integrated it into Primal, so it works with any Nostr website that has this standard set up but we are seeing people like add like some people frame it as \"Sign in with Primal\" even though it's an open standard technically anyone else can have NsecBunker support, which is important I think.","offset":3039,"duration":32},{"text":"I mean, you know, I think part of the challenge you guys have had is it seems like you've been building quality product but you need other people to also be building around you. You need more wallets. You need more hardware wallets, it's just Jade right now right? You need more use cases.","offset":3071,"duration":17},{"text":"Scott: There's quite a few others who have integrated like different types of service providers, different wallets. Um mainly actually in the Brazilian ecosystem around D-Pix. And anyone who integrates with us we offer a 50-50 split on any volumes they drive our way. Uh so it's a very easy way for them to build wallets not have to develop all the swap market infrastructure etc. They just plug our stack and then we split the whatever trading fees 50-50. So it makes a lot of sense for them as well and it helps us build network effects around our markets so that we get deep liquidity.","offset":3088,"duration":44},{"text":"Host: Yeah, I mean liquidity begets liquidity. It's like the hardest network effect to to tackle but once you get it-","offset":3132,"duration":6},{"text":"Scott: Yeah.","offset":3138,"duration":1},{"text":"Host: What- like where'd the D-Pix guys come from? Was that a why'd they choose Liquid? That's pretty-","offset":3139,"duration":6},{"text":"Scott: That's a very good question. Um I'm not quite sure. I actually think one of the aspects was that one of the premises of the Sideswap swap market is that any asset you hold in your wallet you can post on the bulletin board and create markets for. And we have all this dealing software that we offer for free so that anyone can create liquidity in whatever asset they have.","offset":3145,"duration":18},{"text":"Host: So did they start using you without even talking to you or was there a conversation?","offset":3163,"duration":4},{"text":"Scott: There was no conversation until they arrived, which is-","offset":3167,"duration":2},{"text":"Host: That's kind of awesome. That's super Cypherpunk.","offset":3169,"duration":2},{"text":"Scott: And um but moreover, since we don't charge any listing fees or anything else, so if they went like on in the Tron ecosystem if they want to get listed with Binance what would that cost to list their coin and millions of dollars?","offset":3171,"duration":-48},{"text":"Host: Millions of dollars.","offset":3123,"duration":62},{"text":"Scott: It- it wouldn't- it wouldn't work. So the barriers to entry I think in Liquid are so low because anyone can issue assets and if you trade through Sideswap there's absolutely no gatekeepers at all. Anyone can create order books for whatever product they have.","offset":3185,"duration":13}],"startTime":3039},{"title":"Understanding Simplicity Smart Contracts","summary":"Scott provides a high-level overview of Simplicity, a mathematically provable smart contract language native to Liquid. He contrasts its robust, conservative design with Ethereum's smart contracts, noting its potential for secure financial derivatives.","entries":[{"text":"Host: That's pretty cool. Um I mean you mentioned Simplicity and Simplicity is a smart contract language that Blockstream championed for Liquid with the the hope I think that one day it could be used on Bitcoin on-chain as well. Ironically, given the name, it's actually not that simple to get your head around. Do you have a high-level explanation of why Bitcoiners should care about Simplicity?","offset":3198,"duration":31},{"text":"Scott: Well I think high-level abilities for Bitcoin to have different types of scripting options were like limited to like timelocked contracts, hashlock, etc. There wasn't much functionality around building financial markets. So with Simplicity you have something where you have contracts which can be mathematically proven ahead of time, so you actually know what you're signing when you get yourself into it.","offset":3229,"duration":26},{"text":"But moreover, you can also create these binary outcome type of situations such as prediction markets. You can create these financial derivatives, there's a lot more scripting opportunities since you can have these external oracles that determine outcome etc. etc. So with that, you have a lot more opportunity to build financial products which are Bitcoin-native.","offset":3255,"duration":24},{"text":"Um so I think it's very early days. It went live on Liquid, it's not live on Bitcoin as you said. I think there's a lot to play around with to test and um it becomes possible to create these like HodlHodl type of structures etc. You can create options futures binary outcome contracts etc. etc. So I think it's super super valuable, but we're so early days. I think Swaption is the first one to go live with anything with Simplicity. We have maybe ten trades a day um most of the trades are shall we say very low value at this stage. Um people are just dipping their toes to try and understand the product I think. So um yeah if anyone's out there wants to play around with it, feel free to go uh ahead. There's no KYC or AML to get involved.","offset":3279,"duration":50},{"text":"Host: Yeah I mean and the key there is you can set up these types of P2P exchanges and whatnot without giving up custody using something like Simplicity, right?","offset":3329,"duration":12},{"text":"Scott: Correct.","offset":3341,"duration":1},{"text":"Host: Um and I guess it's kind of been pitched to me as like a competitor to how Ethereum does things that is more conservative and safety oriented, more robust kind of coming out from a Bitcoiner mindset rather than a shitcoiner mindset. But offering a lot of the same potential I guess if used appropriately.","offset":3342,"duration":20},{"text":"Scott: Exactly. The contract is mathematically verifiable ahead of time, whereas I think on Ethereum many times when a developer creates these smart contracts or vaults, there's a lot of how skilled is the developer behind it? Um and very easy to verify.","offset":3362,"duration":17}],"startTime":3198},{"title":"Call to Action: Testing Liquid Wallets","summary":"Scott and the host encourage listeners to download wallets like Sideswap, Bolt, or Aqua to experiment with Liquid's low fees and privacy features. The host praises the seamless experience of moving funds between wallets on the Liquid network compared to Lightning.","entries":[{"text":"Host: Fair enough. Um fascinating. Uh yeah, so I'll put links to all this stuff in the show notes. I mean to the the audience like what do you how can they be helpful? What are you what are you looking for? I mean obviously yeah, what is- do you have a call to action for them or how are you thinking about it?","offset":3379,"duration":26},{"text":"Scott: I mean, I'd love for people to just download the app and send a small- total amount of Bitcoin into Liquid and just play around with swaps. Just see what's possible, what's out there, how far it's come. Just do a few swaps back and forth. Um trying the order books. Go to Swaption just try these Simplicity contracts and just see where things are heading. Um and I think things will clear up for a lot of people because it's one thing for us to discuss back and forth, but once you get your hands on something and actually start playing around with it, trying it out, it just resonates so much more with you if that's what you believe where things should be heading. Um and hopefully more eyeballs will start looking at this and start developing these Simplicity products and building a lot more financial products around Liquid.","offset":3405,"duration":53},{"text":"Host: Yeah, what I would say is um just on um in terms of low-level playing around with Liquid, I mean if you install Bolt Wallet by Bull Bitcoin, so that's not their exchange service, I think people get confused by it but this is their self-custody wallet that offers on-chain, Liquid and Lightning. Aqua Wallet, which is Samson's wallet which offers um on-chain Lightning Liquid and then also Tether support. And then the Sideswap app, um you can peg in a very small amount for a very small fee from regular Bitcoin into Liquid Bitcoin on Sideswap. Then you can easily send it between the three wallets.","offset":3458,"duration":42},{"text":"Um and then if you go to liquid.network, which is mempool mempool.space's Liquid instance, it shows all the transactions that are happening on liquid.network. And do a little blockchain analysis on yourself. Look at the transactions as they're happening. Um you can check mempool.space for your peg-in transaction, you can look at liquid.network for your transactions in between wallets. Look at what the on-chain footprint looks like.","offset":3500,"duration":26},{"text":"I think it's if you care about Bitcoin privacy, it's pretty impressive. If you do a couple small swaps with Tether or whatnot you can also see what the privacy situation is in that regard and I think that's pretty fascinating. I think if you even if you're not interested in- I I remain convinced that the Tether use case is absolutely massive. Maybe not for this audience, I think a lot of us don't have a need for Tether, I mean I have the traditional US banking system, I keep the majority of my family's savings in on-chain Bitcoin in self-custody, but there's a huge demand for Tether out there.","offset":3526,"duration":-561},{"text":"But even if even if you're not interested in that aspect, the settling between Lightning-focused wallets. Like if you have a large amount of funds in Bolt Wallet and you want to move them over to Aqua, it's way easier to send a native Liquid transaction. You don't have to deal with liquidity, you have pretty good privacy uh guarantees. Um you have very low fees. It's way easier to send using Liquid than sending through Lightning.","offset":2965,"duration":35},{"text":"And I have noticed as someone who's been using Bolt Wallet more often, um it's a bit of a breath of fresh air versus having funds, you know, stuck in Phoenix Wallet for instance and knowing that every time you make a transaction you're going to get charged a 1% fee and you have liquidity constraints and channel management and all that to deal with. Um so I think that's an interesting way to get your feet wet. I think the Sideswap app in general is you should be very proud of it. It feels like a very robust app that is um performant, you know, like I I don't feel like it's like lagging when I'm clicking buttons and whatnot. I like I have confidence in it, which is no easy feat as someone who's been heavily involved in building out multiple apps now at this point.","offset":3000,"duration":41}],"startTime":3379},{"title":"The Potential for AI Agents Using Liquid","summary":"The host suggests that AI agents could benefit from Liquid's USD token support and node-less Bitcoin transactions. Scott acknowledges the massive opportunity but notes his small team remains laser-focused on developing Simplicity products.","entries":[{"text":"So you deserve a lot of credit that there. But, you know, people should just- I- it'd be great if people play around with it. And then the last thing I would say is I don't know, have you been playing around with like any of this AI stuff?","offset":3041,"duration":16},{"text":"Scott: I mean, in certain aspects we played around quite a bit but if you mean in terms of developing things within the Liquid ecosystem or Sideswap we've done very little. Helping write press releases etc. but yes but in terms of code um very little.","offset":3057,"duration":16},{"text":"Host: I mean everyone the newest thing to hit the block was this OpenCal idea which is you know I think directionally fascinating and probably still pretty early. But this idea of like having a self-hosted robot that has its own memory and can access any apps, ideally CLI apps it works better with, but it can actually like navigate a GUI which is crazy, it can navigate like a graphical user interface or like a website and stuff if there's no API or no CLI.","offset":3073,"duration":28},{"text":"And you basically just have like this robot butler and there's I think as a result of it there's been a a renewed focus on the concept of agentic payments. Like how would the agents pay each other? I think what a lot of people miss there is also the agents also have to be able to receive and send payments from humans too. So when you say agentic payments it's actually not just agent to agent, it's human to agent and agent to human and agent to agent.","offset":3101,"duration":24},{"text":"And Liquid could be interesting there. There's there's obviously demand for people to have USD token support on these things. USDC has become very common, at least in the Silicon Valley world of AI stuff. Um but the combination of Liquid Tether support and Liquid Bitcoin support on the same chain in a way that is as simple as just holding keys. They can just generate a wallet, they don't have to deal with having the node have uptime, dealing with channel management, dealing with all these other stuff. There there is an interesting opportunity there in terms of Liquid being used by by the robots. And that of course is just leaving out the vibe-coded apps or whatever building on top of Liquid which is presumably much easier than on Lightning as well. So that's what I was thinking.","offset":3125,"duration":46},{"text":"Scott: No no, there's so many opportunities in all these areas. We're a super small team, I mean we're trying to just be laser focused in a small area and many times it's probably bit like a horse walking around with the blinders. Miss- miss so many things happening around you all the time when you're too laser focused in one area. So right now we're just focused on building these Simplicity products, getting more acquainted with all limitation of um these binary products. Like how do you have many parties trade? Can you like hand over your position in one binary market to someone else if you need to hold to maturity? Can you have netting etc.","offset":3171,"duration":39},{"text":"There's sorry many things to figure out.","offset":3210,"duration":3}],"startTime":3041},{"title":"Roadmap: Satoshi Dice, Prediction Markets, and Oracles","summary":"Looking ahead six months, Scott outlines plans to release a Satoshi Dice-style game as a stepping stone toward a full prediction market MVP. The host suggests temporarily piggybacking on external oracles, like Polygon's UMA, while Liquid-native solutions are developed.","entries":[{"text":"Host: Well, I really want to see- the freaks know, I just want to see native Bitcoin prediction markets with decent privacy guarantees. I think Liquid could be the holy grail for it. We'll see. Cautiously optimistic. I've been wrong about Liquid adoption multiple times, both on the bear side and the bull side. I think um I was probably too bullish at one point, then I was a little bit too bearish. We've recently seen more of an uptick in usage. Maybe the reality is somewhere in the middle, but I applaud you guys for continuing to build it out and see what works and see what doesn't and try and build out that key infrastructure to to help everything else grow. I would love if we can we do like an update show in like six months or something to see where we stand on all this stuff?","offset":3213,"duration":47},{"text":"Scott: I'd love that, I'd love that.","offset":3260,"duration":3},{"text":"Host: Awesome, okay. Scott-","offset":3263,"duration":2},{"text":"Scott: Yeah, go on.","offset":3265,"duration":1},{"text":"Host: Let's do something funner. So if we have this update in six months, prediction-wise where are we? Um you're going to in six months you're going to have a full-fledged Poly Market competitor for me.","offset":3266,"duration":15},{"text":"Scott: Let's make it an MVP of it anyway.","offset":3281,"duration":2},{"text":"Host: I mean where do you think- I'm obviously half joking, it's a big undertaking- what do where do you think Liquid and Sideswap will be in six months?","offset":3283,"duration":9},{"text":"Scott: I think we'll have the POC for it.","offset":3292,"duration":3},{"text":"Host: That's awesome, that's exciting.","offset":3295,"duration":2},{"text":"Scott: We're not very far- we're actually doing in the background a Satoshi Dice-type of structure. So we're building out a few like more betting type style of markets just to figure out what all the edge cases around Simplicity and just get the market mechanics correct. So we're heading in that direction towards the prediction market model but right now we're just doing the binary outcome type of contracts. So we need to get the order book correct where the order book is 0 to 100 instead of whatever the price of Bitcoin is.","offset":3297,"duration":30},{"text":"Right.","offset":3327,"duration":1},{"text":"Scott: And then we need to- so we have Liquid Connect built, but there's still a bit more work in that area. And then we need to figure out the whole oracle aspect to make that have integrity in some shape, form, regard which we don't have any clarity over just yet. Right now we just have a super simple oracle that's basically just signing the Bitcoin price. So that the contract can determine outcomes.","offset":3328,"duration":23},{"text":"Host: There might be something there- first of all that makes sense to me. I mean, you know, you do the little things to get comfortable and um improve your understanding and your execution before you actually go for the the big one. You know, Poly Market is using something called UMA, I don't know, it's like so hard to keep track of all this shitcoin stuff. They're using something called UMA's optimistic oracle where there's like a whole process on chain of an oracle determining the result of markets. Um and that's all on chain on some Polygon or different shit chain.","offset":3351,"duration":46},{"text":"But because it's all on chain, you might actually be able to just piggyback their oracles in the beginning because that's a hard thing- it's hard to get people to step up and be the oracles is like just a people problem um in the beginning. Um so you might actually be able to just hijack their oracles and just use the same resolution mechanism that they're using in terms of source of truth. If they're already signing cryptographic attestations on some chain out there of ton of markets, right? Like from weather to missile strikes to basketball games, then you could potentially just piggyback them until you have a um Liquid native alternative out there on the oracle side.","offset":3397,"duration":43},{"text":"Scott: We'll look into it. I know Blockstream's putting a lot of work now into the oracle because they're obviously big team now laser focused on Simplicity. So so they're also doing a lot of work around integrating everything. I think they're looking at some Wallet Connect feature.","offset":3440,"duration":15}],"startTime":3213},{"title":"Episode Wrap-Up and Outro","summary":"Scott thanks the listeners for their interest in Liquid and Sideswap. The host provides final links, promotes next week's guest, and signs off.","entries":[{"text":"Host: Interesting. Fascinating. Scott, this has been great. Do you have any final thoughts for the freaks before we wrap here?","offset":3455,"duration":7},{"text":"Scott: Not much, just super happy if anyone's made it this far listening to us go on about Liquid and Simplicity and my favorite project Sideswap.","offset":3462,"duration":11},{"text":"Host: Love it. Um freaks, I'll have links to everything we discussed in the show notes. Like I said, you'll probably be listening to this in a couple hours. Um best way to support the show is sharing with friends and family. All relevant links at Citadeldispatch.com. Reminder to check out Citadelwire.com. I have uh already next week I have lined up on the calendar a conversation with Leia who is a co-founder of Vexel. They do P2P Bitcoin exchanges without KYC. So that'll be a great conversation keep an eye out for that. And uh play around with Liquid. Scott is looking for feedback, he's looking for more users, more people playing around with these things. I think all of it can be helpful. While we are in these bear market, it's always great to just dive into the tech and uh get your feet wet. Um there's no better time than today. Thank you Scott.","offset":3473,"duration":52},{"text":"Scott: Thanks Matt.","offset":3525,"duration":2},{"text":"Host: Thank you freaks. Stay humble, stack sats. Peace.","offset":3527,"duration":15}],"startTime":3455}],"entries":[{"text":"Host: Happy Bitcoin Monday freaks. It's your host Odell here for another Citadel Dispatch, the show focused on actionable Bitcoin and freedom tech discussion. The current block height is 840,011. That brings us into Fiat time. Fiat time, it's Monday March 11th, um they just did the timezone change on me, at 17:00 UTC, no, 16:00 UTC.","offset":0,"duration":46},{"text":"Um, you guys will probably be listening to this in a couple of hours. I don't like sitting on it, I like to get it to you ASAP. Current sats per dollar is 1,452. Current price in dollars is 68,863. And the current price in gold is one Bitcoin, you can get one Bitcoin for 12.84 ounces. Um, Bitcoin's down on gold on the day, the month, and the year, but we're slightly up on the week. Something to keep an eye on.","offset":46,"duration":52},{"text":"As always, Dispatch is supported by viewers like you. We have no ads or sponsors, so thank you to everyone who continues to send Bitcoin donations to support the show. The two largest supporters, I'm going to say from uh the last two weeks since, or the last two episodes since they were back to back, was we have Mav21, he sent two separate 10,000 sat zaps, both saying \"great rip\". Thank you Mav21, true ride or die.","offset":98,"duration":35},{"text":"And we have Captain Cook with 7,654 sats. He had no comment, but thank you for your support. As always, sharing with friends and family also goes a long way. Dispatch is available in all of your favorite podcast apps by searching Citadel Dispatch. All relevant links are at Citadeldispatch.com. And recently I've been playing around, I also launched Citadelwire.com where you can listen to the most recent Citadel Dispatch, the most recent Rabbit Hole Recap, um and get on demand news um from my soulless robot slave who I've been training and curating to try and provide the most relevant news using live market data.","offset":133,"duration":47},{"text":"Um, I got Poly Market plugged into him and Bitcoin prices and a bunch of other data sources, so that's a bit of a work in progress, but check it out at Citadelwire.com. Anyway, we have a great show lined up today. I have Scott here, he is the co-founder of Sideswap. Sideswap is, has just been grinding along building great product in the Liquid ecosystem. Something we haven't talked about for a while on the show. Um, how's it going Scott?","offset":180,"duration":32},{"text":"Scott: Hey Matt, uh thanks for inviting me. Yeah, uh everything's been going very well. Sideswap's been growing very nicely these past few years. Uh started out quite slow but we're growing organically and cash flow positive and um very happy with where we are. We focus much on the tech and building out what we hope is a great product liked by users. We don't focus much on marketing, which is why you may not have heard of us much.","offset":212,"duration":33},{"text":"Host: Yeah, so I mean, I was not really familiar with you guys. I like kind of a little bit a couple years back. Um, and then I started playing with Samson's Aqua Wallet, which more people might be familiar with, which is tries to do lightning um and Bitcoin with with Liquid as the base at rest. So it sits in Liquid and then it does swaps for receiving and sending. Um which we've seen a couple wallets do that.","offset":245,"duration":36},{"text":"Bolt Wallet has been doing it recently. Breeze has their own SDK that uses it as well. Breeze has like two rival SDKs in-house, one does Liquid and one does Spark. Um but I was playing around with Aqua Wallet and then I saw on the backend they were using you as the provider, which was cool. And then I was like, \"Okay well let me see what they're doing directly.\" And that's that's kind of how I was reintroduced to you guys and we had a mutual friend put us in touch and I it's just it's impressive what you guys have been quietly building with like you said, very little fanfare.","offset":281,"duration":39},{"text":"So I mean, to the freaks um to our audience here, what is Sideswap, how should they think about Sideswap?","offset":320,"duration":7},{"text":"Scott: Mm, well well Sideswap at its base is really a non-custodial wallet and it's based on the Bitcoin premise that your keys, your coins. So when we built the swap market, since Bitcoin doesn't have other assets other than Bitcoin on chain, we started looking at the layer twos. And since Tether was issued on Liquid, we figured we could build swap markets where we effectively have atomic swaps between two parties.","offset":327,"duration":32},{"text":"So you can create a bulletin board type of system and you trade a swap between the two parties so that settlement happens atomically and instantaneously real-time between the two counterparts to the trade. So we're never custodial of anything really, and that's a model that we're very much looking for. And the model we think everyone should really aim for and not go for the custodial model.","offset":359,"duration":34},{"text":"Host: So the correct- yeah, go on.","offset":393,"duration":2},{"text":"Scott: No no, you continue please, sorry.","offset":395,"duration":3},{"text":"Host: I mean, so the way I look at it is for the average person, at least on the surface, Sideswap is an app that you can download on your phone that lets you easily go from regular Bitcoin to Liquid Bitcoin and vice versa. And then if you want access to Tether, you can then easily swap between Liquid Bitcoin and Liquid Tether, correct?","offset":398,"duration":35},{"text":"Scott: Correct. So what one of the first big hurdles that we encountered was obviously getting people to move between the main chain and the Liquid sidechain. We effectively built one of these peg-in, peg-out services since very few people can be uh they they don't want to sit there and sync a full node on both the Bitcoin side and the Liquid side in order to be able to uh create the claim scripts and issue coins on Liquid.","offset":433,"duration":31},{"text":"And many of the services at the time had a very high fee, so we cut that down to 0.1% and had effectively a bridging service which anyone can use, which Aqua also uses. So um it's a 50-50 revenue split on anyone who's a partner and just uses our infrastructure, so they don't need to build it up themselves. And um with that done, uh we started focusing on the swaps on Liquid so that two participants can trade between themselves without having any intermediary.","offset":464,"duration":40},{"text":"So we effectively just offer a bulletin board system so that users can find each other and we and we help make sure that the swap has integrity, so that one party can't cheat the other one by effectively saving half-signed UTXOs which they could theoretically broadcast at a later date. And so the way we've built it, we also offer instant swaps but the way it's built we actually offer order books where anyone can come in and uh improve prices within the order book.","offset":504,"duration":34},{"text":"And any instant swap is effectively a market order into the order book. So dealers compete on pricing, um so hopefully we get spreads which become a lot tighter. Right now I think the spreads are about 0.2, 0.3% away from uh let's say the midpoint price many times. And um yeah, so there's lots of trading opportunities and lots of liquidity. The areas that we've really seen grow, initially it was a lot around um USDT but lately it's been D-Pix. It's really really grown in the Brazilian market.","offset":538,"duration":46},{"text":"Host: What is D-Pix? I saw it in the wallet.","offset":584,"duration":4},{"text":"Scott: Uh D-Pix is a Brazilian stablecoin uh issued by a company I believe called Ulem. So they have been behind much of the uh increase in adoption within Liquid lately.","offset":588,"duration":25},{"text":"Host: Fascinating.","offset":613,"duration":1},{"text":"Scott: Yeah, so if we look in our swap market just in terms of trades and transactions, I'd say D-Pix is probably the biggest market right now. Not in terms of volume, but in terms of transaction count.","offset":614,"duration":16},{"text":"Host: In transaction count D-Pix is the biggest, but in terms of total amount, Tether's still bigger?","offset":630,"duration":8},{"text":"Scott: Much bigger.","offset":638,"duration":1},{"text":"Host: Yeah.","offset":639,"duration":1},{"text":"Scott: People are a lot more comfortable holding Tether obviously.","offset":640,"duration":4},{"text":"Host: Yeah, they've been around for I mean, Tether's bread and butter is the high net worths, right? They've been around for a decade plus.","offset":644,"duration":9},{"text":"Scott: Uh exactly, whereas um I think D-Pix is many local payments within the Brazilian ecosystem, but it brings in a lot of users even if their transaction volumes aren't that large.","offset":653,"duration":16},{"text":"Host: How do I spell D-Pix?","offset":669,"duration":3},{"text":"Scott: D-E-P-I-X.","offset":672,"duration":3},{"text":"Host: D-Pix stablecoin. Interesting. So so okay, there's a couple things here. First of all, the order book thing is fascinating. It's like in general, a lot of these quote-unquote instant swap services you see are first of all custodial and second of all, they're kind of like a black box in terms of pricing. So it's cool that you actually have like a proper order book that basically anyone can participate in and become market makers. And as a result, it's more transparent pricing and theoretically, I guess, it should be better pricing.","offset":675,"duration":48},{"text":"Um I think it's pretty cool that you can actually participate in the order book on mobile, which makes accessibility good. But I assume it's quite obvious if you look at the order book for a little bit, like there's at least there's like one or two like real market makers there that are putting up more size than others. Are they using- they're not using like a mobile wallet, right? Like they is there like a CLI or something that they're accessing the order book with?","offset":723,"duration":36},{"text":"Scott: Uh we we've built quite a suite of tools. So in our GitHub repo, anyone can download the dealing software and if anyone needs help setting things up, um everything's available and you can yeah, run your own frontrunning code. So um I think we had a bit of an issue with that at one point since people were flooding the system with lots of quotes. But um yeah, growing pains like are good pains.","offset":759,"duration":35},{"text":"Host: Yeah, I agree with that. Um okay, fascinating. I mean, before we continue on, I mean, I think the big question that we've been asking on this show for years now um and I think Bitcoiners have been asking for a while is ironically the lack of liquidity on Liquid and the lack of users using Liquid. It seems like cautiously optimistic in terms of adoption increasing lately, and I would say partially it's probably these wallets that are using Liquid at rest for Lightning payments, specifically Bull and Aqua Wallet.","offset":794,"duration":44},{"text":"I mean, the fact that Liquid has confidential assets which incorporates confidential transactions, so each transaction you can't see the amount or the asset that's being sent, whether that's Bitcoin or Tether or whatever, um means that people that, you know, maybe are in the developing world that are sending um 20 cents worth of Bitcoin, you can't tell if that's $2,000 worth of Bitcoin or 20 cents worth of Bitcoin. So it actually compounds kind of beautifully in terms of adding, I guess, anonymity set to to Liquid.","offset":838,"duration":50},{"text":"Anyway, this is kind of a long-winded question, but where do you see Liquid adoption? Have you been frustrated with the lack of adoption? Do you- are you still opti- I mean, I assume you're still optimistic on adoption and how can that be accelerated? Because it kind of feels like Liquid has always been like the ugly stepchild of Bitcoin that just hasn't really found its wings.","offset":888,"duration":27},{"text":"Scott: No no, correct. I think much has to do really with Bitcoin being a one asset chain, it didn't really have any scripting abilities or or ability to issue other assets so that you could trade things like atomically. So so there was no real layer two which could really scale Bitcoin. So I think when all of these other chains came around and they offered all the smart contracts etc., very easy for anyone to get involved. I think that took out took off a lot.","offset":915,"duration":37},{"text":"And many of the exchanges I think focused on offering products and development within that area since there's a lot of money flowing in and promise. But I think as time goes on, I think Bitcoin which is like the settlement layer, developed properly and financial markets, it may have taken a bit more time. But I think Liquid is a step in the right direction in terms of how you build secondary layers. There's lots of questions around the making the two-way peg trustless and how you can go about that and the federation model and- but if we skip that side of the discussion, it's very nice to have an asset layer which is like Bitcoin-based, UTXO-based, that can hold multiple assets so that you can have these financial transactions, the swaps and everything else around it.","offset":952,"duration":55},{"text":"So I just think that side has taken a lot of time to get going, especially since it requires you to manage your own keys. I think none of the big wallet custodians like Fireblocks or anyone else has integrated Liquid so it hasn't been very easy for any exchange to offer it. So it basically onboarding one by one people are comfortable to holding their own keys. But going forward, I think now that Simplicity is live on Liquid, uh I think there's a lot of things that can be done and will offer a lot of fantastic features to users such as being able to create prediction markets in a Bitcoin-native type of ecosystem.","offset":1007,"duration":52},{"text":"Host: Yeah, I mean I want to jump in there specifically on the prediction market stuff, but before we do, just real quick I mean like my fascination with Liquid has always been on the privacy side, specifically confidential transactions. Um you know, a lot of the probability analysis that Bitcoin chain surveillance firms do is based on amount correlation. And once you remove those amounts from being visible, it makes their job of detecting when ownership has changed hands much more difficult.","offset":1059,"duration":52},{"text":"On the asset side um let's be frank, I think most tokens that have been launched in crypto are just straight up scams and the ones that aren't are also just probably horrible investments except for the undeniable US tokens, specifically Tether, right? And we've seen a massive market for Tether on Tron specifically, to a lesser extent on Solana and Ethereum. Um and it's fascinating to me because if you use those ecosystems, it's even worse than Bitcoin privacy. It's like you have a fixed address that is literally your entire transaction history.","offset":1111,"duration":69},{"text":"And so where I'm going with this is right now it seems like I'm cautiously optimistic that financial privacy in quote-a-quote broader crypto space seems to be having a moment. First we saw it kind of with the Zcash pump and dump and then recently Ray Dalio and Chamath both mentioned financial privacy as a concern. And I think part of it is because of of not even Bitcoin like Bitcoin could have better privacy but it's still relatively accessible. But the privacy situation on a Tron or a Solana is absolutely abysmal. It's horrible.","offset":1180,"duration":51},{"text":"Um so I'm surprised that there hasn't been more uptick on just the Tether use case. Like if you want to use Tether, which obviously has a trusted third party and I've never advocated for people to use Tether but there's plenty of demand for people that want Tether and want access to US dollars where they can't get it otherwise. The most private way to access Tether is through Liquid and specifically through Sideswap because you make peg-ins so easy um and peg-outs so easy and you make the ecosystem much easier, much more accessible.","offset":1231,"duration":48},{"text":"Why do you think we haven't really seen like like let's nail down specifically on Tether like why haven't we seen specifically massive Tether adoption on Liquid? It's like it's pretty much negligible compared to the other chains.","offset":1279,"duration":19},{"text":"Scott: It- it's absolutely nothing. I think there was about $35 million of Tether circulating on Liquid up until a few months ago when it when it was increased to 90-something million. So if you compare that to the other chains it's a drop in the bucket. Well- I think also much of the liquidity on the other chains uh is not really held in private wallets, it's held with custodians in one shape or form. Um with Liquid, since there are no custodians, um effectively people who are comfortable holding their own keys and assets, Bitfinex effectively custodying the balances for you.","offset":1298,"duration":52},{"text":"But something that's very interesting, which few people might have considered, is that USDT on Liquid, it's the only- due to the confidential transaction nature of it, the issuer cannot confiscate the balance. They- they don't know which UTXOs are USDT.","offset":1350,"duration":20},{"text":"Host: Yeah they'd have to confiscate it basically they'd have to like basically shut down Tether on Liquid is what they could do. But they can't do their like pick and choose \"I'm blocking this Tron address\" or whatever.","offset":1370,"duration":17},{"text":"Scott: Not like they can do on the other chains.","offset":1387,"duration":2},{"text":"Host: Yeah, that's why it's wild to me that just the Tether use case alone has- and so okay, they have a website USDT.network that tracks all of their usage across the different chains. Just just for reference for the freaks. I mean Scott said, what'd you say, you said 95 million Tether on Liquid?","offset":1389,"duration":22},{"text":"Scott: Yeah, I believe it's about- in that ballpark area.","offset":1411,"duration":5},{"text":"Host: Okay, well anyway it's completely negligible. The- there's $92 billion worth of Tether on Ethereum, $85 billion on Tron, just to with a B, just just to show the discrepancy. On the privacy side, I think it's also pretty cool that basically in practice, am I correct in saying that anyone who's doing a swap between Tether and Bitcoin, Lightning Bit- Liquid Bitcoin and Liquid Tether, is basically a payjoin transaction. And payjoin works even better on Liquid because of confidential transactions than it does on Bitcoin in terms of breaking probability analysis.","offset":1416,"duration":78},{"text":"Scott: I think there's a few different aspects to that. Um payjoin is something that we offer for people who have wallets where they don't have Liquid Bitcoin and need to pay the network fee. So- so we do lots of payjoin transactions every day. I think there's about 2 or 3 cent fee which covers- includes the network fee. So- so it's very cheap to do these payjoin transactions.","offset":1494,"duration":40},{"text":"And um when we have swap markets where you have two assets traded against each other, um where you don't have Liquid Bitcoin as one of the assets, we actually pay the network fee on behalf of the user in a payjoin with the swap. And since the swap there's two different assets being exchanged, it's very very little- the heuristics become very very difficult to- yeah, it's pretty wild, and particularly at a small user base, which is obviously the single biggest thing holding back Liquid as a as a more robust privacy tool. But it's impressive that it breaks it already breaks even at a smaller usage, it still's breaking a lot of heuristics. It makes it quite difficult.","offset":1534,"duration":66},{"text":"Yeah, and especially with the peg-in, peg-out process when you peg in and then you peg out, the federation also selects the UTXOs that you get when you peg out so there's no correlation between the two.","offset":1600,"duration":16},{"text":"Host: Right. They just know it came from the Liquid network. Like if you pegged out and then sent to Strike, they would know that those are Liquid-affiliated transactions but there wouldn't be a direct connection between peg-in and peg-out.","offset":1616,"duration":18},{"text":"Scott: But mind you, this was like two, three years ago, we we ran the UTXO set of Liquid through one of the chain analysis tools, and the UTXO set is effectively pristine since Bitfinex is responsible for um a decent chunk of it.","offset":1634,"duration":22},{"text":"Host: Fascinating. Oh yeah, I mean yeah let's talk about I mean you mentioned it, let's talk about prediction markets. I mean to me one of the big shames is that we I mean Bitcoiners have been talking about prediction markets for over 10 years now and they finally hit critical mass and the biggest one is on Polygon and uses USDC as its primary base asset, um that being Poly Market.","offset":1656,"duration":42},{"text":"Obviously like the functionality specifically with something like prediction markets, you need it to be self-custody, you need to not have liquidity concerns. These things make it very difficult to run any kind of prediction market on Lightning. We've seen a competitor pop up called Predics that is basically just a custodial wallet, you know, with managed payouts, which I think is just not sustainable or scalable, um and has massive, you know, regulatory exposure.","offset":1698,"duration":37},{"text":"Liquid seems like it could be ideal for a Bitcoin-native prediction market because it has simplicity, because you can do self-custody type smart contracts, because you have privacy. I mean we're seeing on the Poly Market side people's wallets are being tracked. They're like, \"This person was successful on these six different military markets, like they must be an insider with the Israelis or an insider with the US\" or whatever. Like it's getting arguably as it's made it more obvious why financial privacy is important on blockchains than actual financial transactions themselves because a lot of these markets are quite sensitive. So how are you thinking about prediction markets, Liquid, what kind of opportunities are there?","offset":1735,"duration":89},{"text":"Scott: Um well I think there's many aspects to your question. The first point you raised now with the insider trading ahead of the Iran, where someone seemingly made quite a bit of money betting on the 28th I believe. Um in terms of prediction markets being built on Liquid, I think it's still a bit out. We've done so much work in the background because there's so many building blocks that need to come into place before you actually build it.","offset":1824,"duration":33},{"text":"So what we've been building in the background is effectively a Liquid Connect type of function so that anyone can plug their wallet into a web page or that the web page can connect with a wallet so that you can send these transactions to the wallet directly because these swap transactions, especially with Simplicity contracts, can become shall we say fairly messy, non-standard, not super easy to do. So it requires a bit of work in that regard, a bit of like Metamask type of features but for Liquid.","offset":1857,"duration":51},{"text":"So we we've done much of that work, hopefully should be I mean we have it ready and in production but it should be a lot more useful I think next week. And we should release um a public API so that anyone can integrate. But um so that was the first step and then the second step is how do you build these prediction markets? So with Simplicity you can build these binary contracts and we've started playing around with it.","offset":1908,"duration":38},{"text":"I'm still not entirely sure all of the limitations, you can create these binary contracts um between two people and you have an oracle that determines the outcome um of the contract. So as long as the two parties trust the oracle, you can effectively bet on anything. But- but then the question becomes also how do you get people to fund the contract at the same time?","offset":1946,"duration":30},{"text":"Because if you create markets where someone needs to fund the contract initially and then someone funds the contract at a later date, you need to create some form of market structure that allows for that. What- what we've done is we've applied our order book and our swap market to it. So we're looking at creating markets where you have a instead of an order book that goes from with a Bitcoin price say from wherever it is now um $70,000. So you have an order book that goes from 0 to 100 effectively.","offset":1976,"duration":47},{"text":"And so the bid will be the yes outcome and the offer will be the no outcome. And wherever you bid within that order book is the prediction rate. So- so whoever's on shall we say the yes side, it bids 30 um they fund the contract with 30 cents and the offer will need to fund it with 70 cents. So that there's one full dollar in the contract and once the contract um once the prediction either comes true or false, when the oracle has a definite outcome, it's a winner-take-all type of situation where everything goes to one of the two parties.","offset":2023,"duration":50},{"text":"And that's effectively how you price it. So with our order book structure, we can create that so that two parties enter into a swap at the same time and that the contract is funded with the swap at once. So that you don't have the issues of who goes first etc. funding a contract and creating an order book with resting orders and people having locked up funds waiting for other users to come in etc. etc. To be honest, I'm not sure how Poly Market's done it. I know their order book's quite efficient but the question is how does it actually work under the hood?","offset":2073,"duration":43},{"text":"Host: I'm pretty sure they're basically trading yes and no tokens on each market has their own token. I mean the user doesn't see it.","offset":2116,"duration":10},{"text":"Scott: Mm, that's one option of going about it but the other option is creating the contract directly and you have the two users fund the contract.","offset":2126,"duration":12},{"text":"Host: Yeah, there's a couple different things right? Because it's like okay with prediction markets for prediction markets to work at scale you need a couple things. You need uh you need the ability for people to participate anonymously because the whole idea is trading prediction markets benefits insiders, tracking and watching prediction markets benefits outsiders because you're giving insiders an incentive, a financial incentive to effectively tip their hand and and trade a market which then exposes um which exposes their belief on how that market will what the outcome will be.","offset":2138,"duration":51},{"text":"So they need to be able to do it anonymously because if they work for Intel or if they work for a government or something they're not going to do it unless they can do it anonymously. So with that understanding, then it needs to be at least relatively decentralized and self-custodial because if there's a single company that is controlling funds and controlling payouts, then they're ultimately going to be pressured by a government to dox all users. So you're never going to have permissionless participation unless it's relatively decentralized.","offset":2189,"duration":44},{"text":"And then the last piece is the oracle problem, which is how do you how do you determine in a um robust and objective way what actually happened to settle the contracts afterwards. And so Poly Market like kind of made it there on all of those pieces but they kind of hand-waved a bunch of stuff away. Like Polygon itself, you know, I think could be argued that it's still pretty centralized. Ethereum very centralized. USDC obviously is completely centralized and can be frozen at will.","offset":2233,"duration":52},{"text":"Um the oracle problem they haven't actually solved, they just offload it. It's like they don't make the decision, they have like for each market there's a designated quote-a-quote on-contract oracles so there's it's still crypto-native if you will but it's still ultimately, you know, centralized entities saying ESPN reported that the game um was, you know, the Clippers won the basketball game or whatever.","offset":2285,"duration":32},{"text":"Uh so they didn't solve the oracle problem and they're like quote-a-quote decentralized enough to not have to do KYC and block people's access to markets. Um and I think this is just something interesting by the way for Bitcoiners and Liquid where the shitcoiners have done a really good job of kind of being pragmatic about tradeoff balance when it comes to censorship resistance and decentralization that Bitcoiners have not been.","offset":2317,"duration":22},{"text":"I mean I we haven't really touched on it but there's a lot of controversy for instance around the Liquid Federation model and whether or not it is technically self-custody or not. But if you which is something that's I think unique to the Bitcoin community because if you look at something like Tron, it's pretty much the same trust model as Liquid but Tron has gotten a pass from regulators, they consider it decentralized enough. And Tron, like I said earlier, has $85 billion of Tether volume alone on it, which is a wild stat.","offset":2339,"duration":35},{"text":"So to me Liquid could be this middle ground for Bitcoiners. And we could actually I mean there could actually be a trust model set up on a Liquid-style prediction market that is significantly better than Poly Market, which is right now operating at scale with very sensitive markets at a $10 billion-plus valuation with many many users. And it seems like too good of an opportunity to to miss out. So I mean on that point, that was very long-winded, but you more than anyone, you know you've been quietly bootstrapping and building a business on Liquid, how do you think about that trust model in terms of the federated model? Because I mean it could kill your business if if it wasn't um sufficient enough, let me put it that way.","offset":2374,"duration":45},{"text":"Scott: Of course, and that's also one of the growing pains that we'll need to encounter at some point. But right now while we're so small, I I think no one's looked um deeply enough at all of these questions in terms of Liquid, the Federation, how it's structured set up, is it decentralized enough etc. etc. Uh right now we're very much just focused on getting the market model correctly, getting everything easy for users to access, make it easy to trade.","offset":2419,"duration":29},{"text":"Since everything's non-custodial, you hold your own wallet, you hold your own keys, the contracts are on chain, you swap into it can be verified uh within the wallet by the users prior to executing the swap. But then there's all the ques- so the question is is that decentralized enough? It's very difficult to say, like different regulators may take a different view given the Liquid governance model very unclear.","offset":2448,"duration":29},{"text":"Um then there's I think all the questions around how the oracle is constructed etc. We're not trying to solve all of these like shall we say philosophical or mathematical questions right now, we're just focusing trying to get the market structure correct. And once we have that in place, we can start tinkering around the edges with everything else. I think the oracle problem's not super easy to solve. Blockstream's working on it, they they have a model that they've proposed. Um is that good enough? Not sure.","offset":2477,"duration":34},{"text":"Host: I mean, like I said, it's not like Poly Market has solved it. It just needs to be robust enough. It's never going to be- we're not going to- I'm convinced that the oracle problem is is unsolvable. You can mitigate it, you can create a relatively usable and decent and robust solution but actually quote-a-quote solving the oracle problem, solving something happening in the real world and then being able to cryptographically prove it on chain is going to require some trusted third parties that are cryptographically proving it on chain.","offset":2511,"duration":45},{"text":"Those trusted third parties, you can reduce their influence or risk by combining multiple of them, by adding reputation systems. I think DLCs are interesting where they're providing oracles but they don't know which market they're providing oracles for. There's different ways you can do that. But at the end of the day, for someone on chain to know what the weather was in Chicago yesterday, like there's going to be trusted third parties. There's I- I don't think it's solvable in that regard.","offset":2556,"duration":15},{"text":"Scott: There's no way around it I think.","offset":2571,"duration":2},{"text":"Host: Yeah, exactly. And on the on the point of Liquid, I mean would you agree with me like if Tron is self-custody, if you consider Tron self-custody, I think you have to consider Liquid self-custody. I mean Justin Sun is basically the arguably the model for Tron is worse than Liquid in terms of censorship resistance and trusted third parties.","offset":2573,"duration":17},{"text":"Scott: I- I would say so, obviously I'm biased, um my hope as well is in that direction so take it from what it is.","offset":2590,"duration":9},{"text":"Host: I will say that I think um where we're seeing, I mean the big one that everyone is I mean anyone who's actually building in the space has been paying attention to is Spark. Um and there's a lot out of Lightspark, which is David Marcus's A16Z-funded company after he was formidably working for Facebook for Meta. And I'm already seeing like the Bitcoin culture fights over whether or not that is considered self-custody. Um and it's a similar idea of a pragmatic approach that is maybe more similar to what we see in shitcoin land but I think could be very useful for Bitcoiners.","offset":2599,"duration":37},{"text":"Yeah, and I wonder if that will bring more attention to Liquid because I mean if you mono-a-mono it out, I think the Liquid model is more robust than the Spark model. Um and then you have other things, I love the Phoenix team with Async. Um like the trust model for that is not as clear cut as you hold your keys, you have self-custody. On-chain is very clean. On-chain Bitcoin's very clean, it's either self-custody or it isn't. Once you start playing with the tradeoff balances across the stack, things get a little bit more definitionally messy. And I think the Bitcoin community specifically has been wrestling with that for many years now.","offset":2636,"duration":41},{"text":"Scott: Well- I mean if you look at how the financial system is built, you effectively have a central bank they they operate one ledger. Uh then you have all the commercial banks below, they each operate their own ledger. So if you want to move cash from one one bank to another, it's actually the bank's accounts at the central bank that need to be updated before the banks themselves update their own accounts. So the whole financial system is built on lots of different ledgers and all these clearinghouses are effectively the ones managing the risks between the different ledgers and um shall we say the net deferred settlement between ledgers.","offset":2677,"duration":37},{"text":"So for Bitcoin to scale given that it is a one-asset chain, you need these secondary layers somehow. Since there's no solution yet exactly of how to create these exact or trustless two-way pegs between the Bitcoin main chain and a sidechain, that there is always going to be these different tradeoffs and discussion around how decentralized it is, at what point do the regulators consider it being decentralized or not. So there's always these questions.","offset":2714,"duration":34},{"text":"Host: Yeah of course. It's just an interesting it's an interesting um interesting thoughts to go down. Um I'm sure we're going to get comments about it too which is why it's incredibly important to talk about it. Um pretty much they come up anytime Liquid is brought up. And I think rightfully so. I think it's good that the community is at least a subset of the community, which percentage-wise is getting smaller by the day but absolute numbers-wise has never been higher, cares so much about these hard questions and sovereignty and and using these things in freedom-oriented ways while like like I said, like shitcoiners kind of just throw it out the window and think of it as an afterthought. You guys recently launched a new product. Are you at liberty to talk about it right now or?","offset":2748,"duration":53},{"text":"Scott: Yeah, sure. Um so this is like our first dipping our toes into the Simplicity uh shall we say pool if we're in the Liquid space. But- but what we've effectively what- we have this website or sister website called Swaption, uh where we've plugged this Liquid Connect which is a bit of a privacy dox since if you do connect you share the watch-only wallet with Liquid Connect because otherwise it wouldn't be able to help you create the transactions and everything within your wallet and send the transaction for signing to your wallet. So there is that aspect to consider.","offset":2801,"duration":39},{"text":"Host: Would you- similar to the tradeoff with using like an Electrum server right? On-chain Bitcoin.","offset":2840,"duration":5},{"text":"Scott: Uh yeah. No no, exactly.","offset":2845,"duration":3},{"text":"Host: Right, okay, continue.","offset":2848,"duration":2},{"text":"Scott: There is that tradeoff. Um I mean, we never data mine our users or anything else. Uh so- but I mean, there's no way for users to verify that. But- but in terms of Swaption, so with the Liquid Connect function that we've developed with the wallet, if you visit the Swaption webpage, what we've built is the first binary outcome contracts, which is the first step in the direction towards prediction markets effectively.","offset":2850,"duration":29},{"text":"So we have two different products. One is \"Will the Bitcoin price be higher or lower in shall we say two, five or ten minutes than it is now?\" Um and then the other product is \"Will the Bitcoin price of Bitcoin go up or down like 1, 2, 3, 4 or 10% first?\" So it's a binary outcome, does it go up or down 10%. So people can make a bet in terms of direction etc., hedge positions um with leverage.","offset":2879,"duration":27},{"text":"So the idea was also here to open up so that anyone can trade in the order book and provide liquidity and improve prices etc. So right now there's not fantastic payouts but we're working very hard in that direction to create these order book type of markets so that anyone can come in and provide liquidity.","offset":2906,"duration":19},{"text":"Host: So I mean, your main website is sideswap.io?","offset":2925,"duration":4},{"text":"Scott: Correct, that's- that's where you download the app and the webpage is being reworked as well, so soon you'll be able to use the Liquid Connect and trade via the webpage as well.","offset":2929,"duration":10},{"text":"Host: And then Swaption is- is it swaption.com?","offset":2939,"duration":3},{"text":"Scott: .io.","offset":2942,"duration":1},{"text":"Host: swaption.io. And then that's S-W-A-P-T-I-O-N. Um I'll put all these links in the show notes. And then Liquid Wallet Connect is basically I have the Sideswap app on my phone or another compatible Liquid wallet, which I don't think there are any right now?","offset":2943,"duration":15},{"text":"Scott: Yeah, none.","offset":2958,"duration":1},{"text":"Host: Yeah. And then I'm like scanning a QR code on the website to sign in basically, right?","offset":2959,"duration":4},{"text":"Scott: Correct, or if you have a desktop wallet, it will detect the desktop wallet with the browser.","offset":2963,"duration":6},{"text":"Host: Do you have a desk- Sideswap has a desktop wallet too?","offset":2969,"duration":3},{"text":"Scott: Yeah. Well we've built everything in Flutter, so it's very easy to go cross-platform.","offset":2972,"duration":6},{"text":"Host: And then so you're saying this is kind of in a lot of ways it's kind of a proof of concept because it's a relatively simple type of market that you could have compared to a prediction market.","offset":2978,"duration":9},{"text":"Scott: Exactly. So we're dipping our toes, this is like the first MVP that we push out. There's only one dealer we don't allow yet, but that's coming, that anyone can compete and improve prices. Um and then the next steps are obviously developing these open order books so that anyone can come in. Maybe add functions such as auto-signing etc. in the Liquid Connect so that users don't need to sign every transaction so it becomes a bit more Poly Market-if you will.","offset":2987,"duration":31},{"text":"Uh so there's lots of these thoughts in terms of different directions we can go. We'd love for Aqua and other wallets obviously to integrate so that it becomes ubiquitous within the Liquid ecosystem. Liquid Wallet Connect.","offset":3018,"duration":11},{"text":"Scott: Yeah.","offset":3029,"duration":1},{"text":"Host: No that makes sense to me.","offset":3030,"duration":1},{"text":"Scott: But it's developed by us so- so it's called Liquid Connect but let's see if others pick it up or if it's actually Sideswap Connect.","offset":3031,"duration":8},{"text":"Host: Fair enough. Um I mean we kind of have a similar situation in the Nostr ecosystem where we have an open standard called NsecBunker that uses you either paste a code or or use a QR code scan, I think QR code scan makes a lot of sense if like the user has a mobile phone, they're like scanning it with a QR code. But the reason I bring it up is because we integrated it into Primal, so it works with any Nostr website that has this standard set up but we are seeing people like add like some people frame it as \"Sign in with Primal\" even though it's an open standard technically anyone else can have NsecBunker support, which is important I think.","offset":3039,"duration":32},{"text":"I mean, you know, I think part of the challenge you guys have had is it seems like you've been building quality product but you need other people to also be building around you. You need more wallets. You need more hardware wallets, it's just Jade right now right? You need more use cases.","offset":3071,"duration":17},{"text":"Scott: There's quite a few others who have integrated like different types of service providers, different wallets. Um mainly actually in the Brazilian ecosystem around D-Pix. And anyone who integrates with us we offer a 50-50 split on any volumes they drive our way. Uh so it's a very easy way for them to build wallets not have to develop all the swap market infrastructure etc. They just plug our stack and then we split the whatever trading fees 50-50. So it makes a lot of sense for them as well and it helps us build network effects around our markets so that we get deep liquidity.","offset":3088,"duration":44},{"text":"Host: Yeah, I mean liquidity begets liquidity. It's like the hardest network effect to to tackle but once you get it-","offset":3132,"duration":6},{"text":"Scott: Yeah.","offset":3138,"duration":1},{"text":"Host: What- like where'd the D-Pix guys come from? Was that a why'd they choose Liquid? That's pretty-","offset":3139,"duration":6},{"text":"Scott: That's a very good question. Um I'm not quite sure. I actually think one of the aspects was that one of the premises of the Sideswap swap market is that any asset you hold in your wallet you can post on the bulletin board and create markets for. And we have all this dealing software that we offer for free so that anyone can create liquidity in whatever asset they have.","offset":3145,"duration":18},{"text":"Host: So did they start using you without even talking to you or was there a conversation?","offset":3163,"duration":4},{"text":"Scott: There was no conversation until they arrived, which is-","offset":3167,"duration":2},{"text":"Host: That's kind of awesome. That's super Cypherpunk.","offset":3169,"duration":2},{"text":"Scott: And um but moreover, since we don't charge any listing fees or anything else, so if they went like on in the Tron ecosystem if they want to get listed with Binance what would that cost to list their coin and millions of dollars?","offset":3171,"duration":-48},{"text":"Host: Millions of dollars.","offset":3123,"duration":62},{"text":"Scott: It- it wouldn't- it wouldn't work. So the barriers to entry I think in Liquid are so low because anyone can issue assets and if you trade through Sideswap there's absolutely no gatekeepers at all. Anyone can create order books for whatever product they have.","offset":3185,"duration":13},{"text":"Host: That's pretty cool. Um I mean you mentioned Simplicity and Simplicity is a smart contract language that Blockstream championed for Liquid with the the hope I think that one day it could be used on Bitcoin on-chain as well. Ironically, given the name, it's actually not that simple to get your head around. Do you have a high-level explanation of why Bitcoiners should care about Simplicity?","offset":3198,"duration":31},{"text":"Scott: Well I think high-level abilities for Bitcoin to have different types of scripting options were like limited to like timelocked contracts, hashlock, etc. There wasn't much functionality around building financial markets. So with Simplicity you have something where you have contracts which can be mathematically proven ahead of time, so you actually know what you're signing when you get yourself into it.","offset":3229,"duration":26},{"text":"But moreover, you can also create these binary outcome type of situations such as prediction markets. You can create these financial derivatives, there's a lot more scripting opportunities since you can have these external oracles that determine outcome etc. etc. So with that, you have a lot more opportunity to build financial products which are Bitcoin-native.","offset":3255,"duration":24},{"text":"Um so I think it's very early days. It went live on Liquid, it's not live on Bitcoin as you said. I think there's a lot to play around with to test and um it becomes possible to create these like HodlHodl type of structures etc. You can create options futures binary outcome contracts etc. etc. So I think it's super super valuable, but we're so early days. I think Swaption is the first one to go live with anything with Simplicity. We have maybe ten trades a day um most of the trades are shall we say very low value at this stage. Um people are just dipping their toes to try and understand the product I think. So um yeah if anyone's out there wants to play around with it, feel free to go uh ahead. There's no KYC or AML to get involved.","offset":3279,"duration":50},{"text":"Host: Yeah I mean and the key there is you can set up these types of P2P exchanges and whatnot without giving up custody using something like Simplicity, right?","offset":3329,"duration":12},{"text":"Scott: Correct.","offset":3341,"duration":1},{"text":"Host: Um and I guess it's kind of been pitched to me as like a competitor to how Ethereum does things that is more conservative and safety oriented, more robust kind of coming out from a Bitcoiner mindset rather than a shitcoiner mindset. But offering a lot of the same potential I guess if used appropriately.","offset":3342,"duration":20},{"text":"Scott: Exactly. The contract is mathematically verifiable ahead of time, whereas I think on Ethereum many times when a developer creates these smart contracts or vaults, there's a lot of how skilled is the developer behind it? Um and very easy to verify.","offset":3362,"duration":17},{"text":"Host: Fair enough. Um fascinating. Uh yeah, so I'll put links to all this stuff in the show notes. I mean to the the audience like what do you how can they be helpful? What are you what are you looking for? I mean obviously yeah, what is- do you have a call to action for them or how are you thinking about it?","offset":3379,"duration":26},{"text":"Scott: I mean, I'd love for people to just download the app and send a small- total amount of Bitcoin into Liquid and just play around with swaps. Just see what's possible, what's out there, how far it's come. Just do a few swaps back and forth. Um trying the order books. Go to Swaption just try these Simplicity contracts and just see where things are heading. Um and I think things will clear up for a lot of people because it's one thing for us to discuss back and forth, but once you get your hands on something and actually start playing around with it, trying it out, it just resonates so much more with you if that's what you believe where things should be heading. Um and hopefully more eyeballs will start looking at this and start developing these Simplicity products and building a lot more financial products around Liquid.","offset":3405,"duration":53},{"text":"Host: Yeah, what I would say is um just on um in terms of low-level playing around with Liquid, I mean if you install Bolt Wallet by Bull Bitcoin, so that's not their exchange service, I think people get confused by it but this is their self-custody wallet that offers on-chain, Liquid and Lightning. Aqua Wallet, which is Samson's wallet which offers um on-chain Lightning Liquid and then also Tether support. And then the Sideswap app, um you can peg in a very small amount for a very small fee from regular Bitcoin into Liquid Bitcoin on Sideswap. Then you can easily send it between the three wallets.","offset":3458,"duration":42},{"text":"Um and then if you go to liquid.network, which is mempool mempool.space's Liquid instance, it shows all the transactions that are happening on liquid.network. And do a little blockchain analysis on yourself. Look at the transactions as they're happening. Um you can check mempool.space for your peg-in transaction, you can look at liquid.network for your transactions in between wallets. Look at what the on-chain footprint looks like.","offset":3500,"duration":26},{"text":"I think it's if you care about Bitcoin privacy, it's pretty impressive. If you do a couple small swaps with Tether or whatnot you can also see what the privacy situation is in that regard and I think that's pretty fascinating. I think if you even if you're not interested in- I I remain convinced that the Tether use case is absolutely massive. Maybe not for this audience, I think a lot of us don't have a need for Tether, I mean I have the traditional US banking system, I keep the majority of my family's savings in on-chain Bitcoin in self-custody, but there's a huge demand for Tether out there.","offset":3526,"duration":-561},{"text":"But even if even if you're not interested in that aspect, the settling between Lightning-focused wallets. Like if you have a large amount of funds in Bolt Wallet and you want to move them over to Aqua, it's way easier to send a native Liquid transaction. You don't have to deal with liquidity, you have pretty good privacy uh guarantees. Um you have very low fees. It's way easier to send using Liquid than sending through Lightning.","offset":2965,"duration":35},{"text":"And I have noticed as someone who's been using Bolt Wallet more often, um it's a bit of a breath of fresh air versus having funds, you know, stuck in Phoenix Wallet for instance and knowing that every time you make a transaction you're going to get charged a 1% fee and you have liquidity constraints and channel management and all that to deal with. Um so I think that's an interesting way to get your feet wet. I think the Sideswap app in general is you should be very proud of it. It feels like a very robust app that is um performant, you know, like I I don't feel like it's like lagging when I'm clicking buttons and whatnot. I like I have confidence in it, which is no easy feat as someone who's been heavily involved in building out multiple apps now at this point.","offset":3000,"duration":41},{"text":"So you deserve a lot of credit that there. But, you know, people should just- I- it'd be great if people play around with it. And then the last thing I would say is I don't know, have you been playing around with like any of this AI stuff?","offset":3041,"duration":16},{"text":"Scott: I mean, in certain aspects we played around quite a bit but if you mean in terms of developing things within the Liquid ecosystem or Sideswap we've done very little. Helping write press releases etc. but yes but in terms of code um very little.","offset":3057,"duration":16},{"text":"Host: I mean everyone the newest thing to hit the block was this OpenCal idea which is you know I think directionally fascinating and probably still pretty early. But this idea of like having a self-hosted robot that has its own memory and can access any apps, ideally CLI apps it works better with, but it can actually like navigate a GUI which is crazy, it can navigate like a graphical user interface or like a website and stuff if there's no API or no CLI.","offset":3073,"duration":28},{"text":"And you basically just have like this robot butler and there's I think as a result of it there's been a a renewed focus on the concept of agentic payments. Like how would the agents pay each other? I think what a lot of people miss there is also the agents also have to be able to receive and send payments from humans too. So when you say agentic payments it's actually not just agent to agent, it's human to agent and agent to human and agent to agent.","offset":3101,"duration":24},{"text":"And Liquid could be interesting there. There's there's obviously demand for people to have USD token support on these things. USDC has become very common, at least in the Silicon Valley world of AI stuff. Um but the combination of Liquid Tether support and Liquid Bitcoin support on the same chain in a way that is as simple as just holding keys. They can just generate a wallet, they don't have to deal with having the node have uptime, dealing with channel management, dealing with all these other stuff. There there is an interesting opportunity there in terms of Liquid being used by by the robots. And that of course is just leaving out the vibe-coded apps or whatever building on top of Liquid which is presumably much easier than on Lightning as well. So that's what I was thinking.","offset":3125,"duration":46},{"text":"Scott: No no, there's so many opportunities in all these areas. We're a super small team, I mean we're trying to just be laser focused in a small area and many times it's probably bit like a horse walking around with the blinders. Miss- miss so many things happening around you all the time when you're too laser focused in one area. So right now we're just focused on building these Simplicity products, getting more acquainted with all limitation of um these binary products. Like how do you have many parties trade? Can you like hand over your position in one binary market to someone else if you need to hold to maturity? Can you have netting etc.","offset":3171,"duration":39},{"text":"There's sorry many things to figure out.","offset":3210,"duration":3},{"text":"Host: Well, I really want to see- the freaks know, I just want to see native Bitcoin prediction markets with decent privacy guarantees. I think Liquid could be the holy grail for it. We'll see. Cautiously optimistic. I've been wrong about Liquid adoption multiple times, both on the bear side and the bull side. I think um I was probably too bullish at one point, then I was a little bit too bearish. We've recently seen more of an uptick in usage. Maybe the reality is somewhere in the middle, but I applaud you guys for continuing to build it out and see what works and see what doesn't and try and build out that key infrastructure to to help everything else grow. I would love if we can we do like an update show in like six months or something to see where we stand on all this stuff?","offset":3213,"duration":47},{"text":"Scott: I'd love that, I'd love that.","offset":3260,"duration":3},{"text":"Host: Awesome, okay. Scott-","offset":3263,"duration":2},{"text":"Scott: Yeah, go on.","offset":3265,"duration":1},{"text":"Host: Let's do something funner. So if we have this update in six months, prediction-wise where are we? Um you're going to in six months you're going to have a full-fledged Poly Market competitor for me.","offset":3266,"duration":15},{"text":"Scott: Let's make it an MVP of it anyway.","offset":3281,"duration":2},{"text":"Host: I mean where do you think- I'm obviously half joking, it's a big undertaking- what do where do you think Liquid and Sideswap will be in six months?","offset":3283,"duration":9},{"text":"Scott: I think we'll have the POC for it.","offset":3292,"duration":3},{"text":"Host: That's awesome, that's exciting.","offset":3295,"duration":2},{"text":"Scott: We're not very far- we're actually doing in the background a Satoshi Dice-type of structure. So we're building out a few like more betting type style of markets just to figure out what all the edge cases around Simplicity and just get the market mechanics correct. So we're heading in that direction towards the prediction market model but right now we're just doing the binary outcome type of contracts. So we need to get the order book correct where the order book is 0 to 100 instead of whatever the price of Bitcoin is.","offset":3297,"duration":30},{"text":"Right.","offset":3327,"duration":1},{"text":"Scott: And then we need to- so we have Liquid Connect built, but there's still a bit more work in that area. And then we need to figure out the whole oracle aspect to make that have integrity in some shape, form, regard which we don't have any clarity over just yet. Right now we just have a super simple oracle that's basically just signing the Bitcoin price. So that the contract can determine outcomes.","offset":3328,"duration":23},{"text":"Host: There might be something there- first of all that makes sense to me. I mean, you know, you do the little things to get comfortable and um improve your understanding and your execution before you actually go for the the big one. You know, Poly Market is using something called UMA, I don't know, it's like so hard to keep track of all this shitcoin stuff. They're using something called UMA's optimistic oracle where there's like a whole process on chain of an oracle determining the result of markets. Um and that's all on chain on some Polygon or different shit chain.","offset":3351,"duration":46},{"text":"But because it's all on chain, you might actually be able to just piggyback their oracles in the beginning because that's a hard thing- it's hard to get people to step up and be the oracles is like just a people problem um in the beginning. Um so you might actually be able to just hijack their oracles and just use the same resolution mechanism that they're using in terms of source of truth. If they're already signing cryptographic attestations on some chain out there of ton of markets, right? Like from weather to missile strikes to basketball games, then you could potentially just piggyback them until you have a um Liquid native alternative out there on the oracle side.","offset":3397,"duration":43},{"text":"Scott: We'll look into it. I know Blockstream's putting a lot of work now into the oracle because they're obviously big team now laser focused on Simplicity. So so they're also doing a lot of work around integrating everything. I think they're looking at some Wallet Connect feature.","offset":3440,"duration":15},{"text":"Host: Interesting. Fascinating. Scott, this has been great. Do you have any final thoughts for the freaks before we wrap here?","offset":3455,"duration":7},{"text":"Scott: Not much, just super happy if anyone's made it this far listening to us go on about Liquid and Simplicity and my favorite project Sideswap.","offset":3462,"duration":11},{"text":"Host: Love it. Um freaks, I'll have links to everything we discussed in the show notes. Like I said, you'll probably be listening to this in a couple hours. Um best way to support the show is sharing with friends and family. All relevant links at Citadeldispatch.com. Reminder to check out Citadelwire.com. I have uh already next week I have lined up on the calendar a conversation with Leia who is a co-founder of Vexel. They do P2P Bitcoin exchanges without KYC. So that'll be a great conversation keep an eye out for that. And uh play around with Liquid. Scott is looking for feedback, he's looking for more users, more people playing around with these things. I think all of it can be helpful. While we are in these bear market, it's always great to just dive into the tech and uh get your feet wet. Um there's no better time than today. Thank you Scott.","offset":3473,"duration":52},{"text":"Scott: Thanks Matt.","offset":3525,"duration":2},{"text":"Host: Thank you freaks. Stay humble, stack sats. Peace.","offset":3527,"duration":15}],"logs":[{"elapsed":"0.0","message":"Downloading podcast episode...","detail":null},{"elapsed":"5.8","message":"Episode downloaded (53.9 MB) in 5.8s","detail":"File size: 53.9 MB"},{"elapsed":"5.8","message":"Episode: CD194: SIDESWAP - LIQUID PREDICTION MARKETS","detail":null},{"elapsed":"5.8","message":"Uploading audio to Gemini File API...","detail":null},{"elapsed":"17.3","message":"Audio uploaded in 11.5s","detail":"File ref: files/rzlbwfg6thmg"},{"elapsed":"17.3","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"117.0","message":"Transcription complete in 99.6s","detail":"56698 chars received"},{"elapsed":"117.0","message":"Transcription tokens: 88,523 in / 13,859 out — cost: $0.0858","detail":null},{"elapsed":"117.0","message":"Parsed 166 transcript segments","detail":null},{"elapsed":"117.0","message":"Analyzing topics across 166 segments with gemini-3.1-pro-preview...","detail":null},{"elapsed":"170.3","message":"Topic analysis complete in 53.3s — found 13 topics","detail":null},{"elapsed":"170.3","message":"Analysis tokens: 14,716 in / 1,175 out / 5,116 thinking — cost: $0.1049","detail":null},{"elapsed":"170.3","message":"Pipeline finished in 170.3s — total cost: $0.1908 (123,389 tokens)","detail":null}]} \ No newline at end of file diff --git a/history/1773694605993-Yzg3YjFlODQtYWNl.json b/history/1773694605993-Yzg3YjFlODQtYWNl.json new file mode 100644 index 0000000..629952d --- /dev/null +++ b/history/1773694605993-Yzg3YjFlODQtYWNl.json @@ -0,0 +1 @@ +{"id":"1773694605993-Yzg3YjFlODQtYWNl","videoId":"c87b1e84-ace0-4ce3-b26f-84764112d5e9","url":"https://serve.podhome.fm/episode/8029725b-0319-44b9-4793-08dc404e83a4/639092833199878670c87b1e84-ace0-4ce3-b26f-84764112d5e9.mp3","title":"CD195: VEXL - P2P NO KYC BITCOIN","type":"podcast","topicCount":14,"segmentCount":143,"createdAt":"2026-03-16T20:56:45.993Z","uploadDate":"20260316","chunks":[{"title":"Introduction & Show Support","summary":"Matt opens the show with the current Bitcoin block height, price statistics, and reads zaps from supporters.","entries":[{"text":"Matt Odell: Happy Bitcoin Monday, freaks! It's a beautiful Monday morning over here, and we've got a great show lined up. As always, this is Citadel Dispatch, the show focused on Bitcoin and freedom tech discussion. I'm your host, Odell. The current Bitcoin block height is 940,918.","offset":0,"duration":26},{"text":"Matt Odell: Sats per dollar is 1,355. The fiat price, in dollar terms—I guess that was also the fiat price—is $73,753. We got a little pump going on this morning. UTC time, it's Monday, March 16th, at 1800 UTC. You will be listening to this in a few hours once I clean it up and get it uploaded.","offset":26,"duration":28},{"text":"Matt Odell: Bitcoin priced in gold: one Bitcoin can now buy you 14.46 ounces. We're pumping in gold terms. We're up on the one-day, one-week, and one-month. Now we're just watching that one-year. I think we'll flip that, hopefully, relatively soon. As always, Dispatch is funded by viewers like you. We have no ads or sponsors.","offset":54,"duration":27},{"text":"Matt Odell: So thank you, freaks, for supporting the show. Our largest zaps from last week was Blockchain Boog with 50,000 sats. He said, \"Big fan of Vexl. Thanks for interviewing Scott and letting people know about this awesome project.\" We also got a 50,000 sat zap from Prodigious: \"Great content as always.\"","offset":81,"duration":24},{"text":"Matt Odell: And then we got two 21,000 sat zaps. We got Vertical Vines: \"Long-time Dispatch listener here, currently trying to liberate 3D printing.\" Love to hear it. And Rod Palmer: \"Very bullish on Vexl, Scott, and simplicity.\" Thank you, freaks, for your support. As always, if you do not have sats to spare—I know they're hard-earned—you can also support the show by sharing it with your friends and family.","offset":105,"duration":28}],"startTime":0},{"title":"Citadel Wire & Arcade Announcements","summary":"Matt briefly plugs his AI-powered news desk, Citadel Wire, and his new Lightning-integrated gaming site, Citadel Arcade.","entries":[{"text":"Matt Odell: Citadel Dispatch is available on every podcast app by searching \"Citadel Dispatch.\" You can also—all relevant links are at citadeldispatch.com. Also, by the way, freaks, just real quick, I've been going down an AI rabbit hole, so I told you guys about citadelwire.com, which is my AI-powered news desk, which is getting quite good, so check it out if you haven't.","offset":133,"duration":27},{"text":"Matt Odell: But I also decided to start making games, so you can go to citadelarcade.com. Coin-operated, nostalgia fun, simple games, no bullshit, no ads. You just pay 100 sats—that's seven cents right now, FYI guys—and get on the leaderboard. But check it out: citadelarcade.com. Anyway, we have a great show lined up. I have Lea here, founder—founder of Vexl.","offset":160,"duration":27}],"startTime":133},{"title":"Bringing Bitcoin Back to P2P","summary":"Lea introduces Vexl, explaining its mission to return Bitcoin to its roots as peer-to-peer electronic cash without third-party institutional control.","entries":[{"text":"Matt Odell: And she's focused on P2P exchange, no-KYC Bitcoin buying. How's it going?","offset":187,"duration":25},{"text":"Matt Odell: Also, I mean, I've been going down a bit of an AI rabbit hole, so the freaks have been getting AI shows left and right, so it's nice to be back to the basics of Bitcoin.","offset":212,"duration":25},{"text":"Lea: Vexl is a mobile app that allows you to buy and sell Bitcoin and products and services for Bitcoin, like it was intended. And when I say like it was intended, I don't mean intended by myself, but Satoshi Nakamoto himself, who in the very first sentence of the Bitcoin whitepaper said that Bitcoin should be peer-to-peer electronic cash that would allow you to transact without going through third parties, right?","offset":237,"duration":29},{"text":"Lea: But, well, it's not where the industry really shifted over the past couple of years. And certainly, Vexl is our attempt to bring Bitcoin back where it belongs, and that means from the hands of institutions to the hands of the users.","offset":266,"duration":28}],"startTime":187},{"title":"Vexl's Social Graph Reputation Model","summary":"Lea details how Vexl uses a user's phone contact list to build an encrypted social graph, ensuring trades only happen between friends or friends-of-friends.","entries":[{"text":"Matt Odell: Obviously, it's become very pervasive through the Bitcoin space, but also just pervasive, I think, through all of our digital lives. It's not just Bitcoin. It's very obvious in Bitcoin because the friction is heavy when you mix freedom money with highly regulated KYC services. But it's everywhere: it's in social media land, I mean, it's all over the place. Once you start paying attention, you start to realize that it's really seeping in everywhere.","offset":294,"duration":27},{"text":"Matt Odell: So it's cool to see Vexl launch in that environment. I guess, when did you guys launch? About two years ago, I think?","offset":321,"duration":30},{"text":"Lea: Exactly. And well, it might sound like, um, well, what is interesting about that, right? There is zillion apps, uh, desktop as mobile apps, that do exactly that. But what Vexl brings to the table as an innovation is the reputation model, I'd dare to say. And with us, it's—it's quite interesting, and I know it will sound controversial, uh, in the first place, but hear me out.","offset":351,"duration":27},{"text":"Lea: So basically, on Vexl you can meet only people you know or people you know know. While everything you see on the app is anonymous and end-to-end encrypted, you always know that you can't meet strangers and you can't trade with strangers. That's very important. And so how it works: when you download the app and you log—log into it, we determine your social graph based on your contact list in your mobile—of your, um, phone contact list.","offset":378,"duration":29},{"text":"Lea: And we show you the offers that are only encrypted for you in within this certain social graph. And you don't know who you're trading with, or you don't know until you decide to reveal the identity to each other in an end-to-end encrypted chat. But with every offer, which is anonymized, you can see how many common contacts you have with the—with the counterparty and who these people are.","offset":407,"duration":28},{"text":"Lea: Which, uh, when you zoom out, is very interesting because you always know per every offer in which social bubble you're kind of moving within. If you really think about it, the innovation is that we actually, in this way, we managed to bring the real-world reputation into an app, which—which I think it's—it's something, well, unheard of before.","offset":435,"duration":26}],"startTime":294},{"title":"Prioritizing Simple UX for Scaling","summary":"Matt and Lea discuss the importance of intuitive app design. Vexl's interface is built to be simple enough for beginners to use without tutorials.","entries":[{"text":"Matt Odell: Yeah, I mean, I think as someone who's been neck-deep in both the education side of Bitcoin and also building products in Bitcoin, the ideological stance of privacy best practices only gets you so far. Ultimately, what scales is users choose what's most convenient to them. So what I think is cool about Vexl is that, yes, I'm sure you probably have been bootstrapped with a bunch of users that really care about privacy and they seek it out.","offset":461,"duration":31},{"text":"Matt Odell: But as it scales, it's probably more just users finding it the most convenient option. And you guys have really done a good job of nailing that UX, nailing that user experience. So it's actually more convenient than using whatever your local KYC-regulated exchange is. And that's how we actually see massive user growth in these types of use cases.","offset":492,"duration":23},{"text":"Matt Odell: Would you agree? I almost kind of—I kind of think of it, and I haven't been in this world for a long, long time now at this point, but it's kind of similar to the dating app issue, right? Where people don't want to meet with strangers, but they want to meet with friends or friends of friends.","offset":515,"duration":27},{"text":"Lea: Um, and I'm very happy that you actually, well, pinpointed the UX because that's something I'm very proud of. From the day one, as we started designing Vexl and thinking about Vexl, I kept asking myself the question like, would my aunt be able to use this without—without guidance? And that was—that was my guideline for any kind of UX decision we were making.","offset":542,"duration":26},{"text":"Lea: It's—it's like—it's a huge focus since the very beginning, that it must—it must be understood by rookie—rookie users, uh, because like, look, if a product needs a two-hour long tutorial, it's not a good product.","offset":568,"duration":28},{"text":"Lea: [Laughs] That's an amazing KPI. I don't want to point fingers on BTC—onto BTC Sessions, but so far—so far, no guides on Vexl.","offset":596,"duration":28}],"startTime":461},{"title":"Handling Fiat Trades Off-Platform","summary":"The conversation shifts to how local currency is exchanged. Vexl encourages in-person cash meetups, but leaves the fiat execution entirely off-platform.","entries":[{"text":"Matt Odell: On your platform, what is the—what's the most common way that people are exchanging that side of the equation?","offset":624,"duration":28},{"text":"Matt Odell: It's like, the Bitcoin transfer side, they can send me Bitcoin super easily: I give them a Bitcoin address and they send me Bitcoin. The dollar side is the difficult part. I'm like sending them a wire transfer or in Europe like a Revolut payment or something like that. So how do you see the people using the dollar or euro side of the equation?","offset":652,"duration":16},{"text":"Lea: Okay, gotcha. Okay, so basically, it's always the local currency. And the important thing to note when we say peer-to-peer what we are encouraging is actually meeting in person, handing over the whatever fiat shitcoin you want to hand over. Cash. Yes. But that being said, if I connect over Vexl with someone who is sitting in an open space two desks from me, yes, I will Venmo the money or Revolut the money and I wouldn't care.","offset":668,"duration":28},{"text":"Lea: Important thing why we are—like, we can't say and we don't know, and it's impossible for us to know how people behave in reality. And but what I wanted to state is that the exchange itself happens out of the platform. We never touch fiat, we never touch Bitcoin, we never touch any data like associated with the transaction itself.","offset":696,"duration":27},{"text":"Lea: Um, so—but mostly, mostly, what we know, and that means literally what people are tweeting if they are tweeting or telling us when we meet them, is meeting in person.","offset":723,"duration":27},{"text":"Matt Odell: I'm like looked at—I go to dinner with friends or whatever, I pull out cash from my pocket, they like look like I'm crazy, everyone's throwing cards on the table. There's a whole informal economy in the US that's based on Venmo. You know, like my nanny, she usually accepts Venmo payments, uh, I don't know, the dog groomer, everyone accepts Venmo. Cash is the exception for them. Like, I'm one of the few people that pay them in cash.","offset":750,"duration":24},{"text":"Matt Odell: So I'm expecting that as you scale, more people will be using these, I don't know, these controlled fiat rails, and they come with a bunch of fraud issues. How do you think about those? Like, if someone sends a Bitcoin payment, obviously it's not reversible. It's beautiful, right? Bitcoin is fantastic. But if there historically with P2P exchanges, because Bitcoin is not reversible, there's been issues with the—the fiat side.","offset":774,"duration":26},{"text":"Matt Odell: And obviously, I mean, it's cool that you guys don't touch any of the actual flows of money or see actually the details of the transaction. So maybe you're limited there. But like, what does a user do if they get defrauded, basically, on the dollar or euro side?","offset":800,"duration":15}],"startTime":624},{"title":"Mitigating Fraud & Shadow-Banning","summary":"Lea explains how the platform's social incentives naturally deter fraud. She also outlines Vexl's method of shadow-banning accounts that receive multiple negative reports.","entries":[{"text":"Lea: So it's actually hard to be—like, to get fraud on Vexl, because well, as I said, like maybe let me repeat: the reputation model is all about like having common people you both know, right? And so you're strongly incentivized to behave properly on Vexl, because well, just easily, you—I mean, simply you don't want to be called a dick among your friends, right? So—and this works.","offset":815,"duration":29},{"text":"Lea: Of course, there might be like attacks like man-in-the-middle attack, or someone can try to impersonate you or whoever. That might happen, but it's very easily mitigated and it's actually something that works beautifully on Vexl. In like three years, we might have had maybe one man-in-the-middle attack we knew about. And unfortunately, like we can't do anything because we don't even know that the transaction happened, right?","offset":844,"duration":25},{"text":"Lea: Like, we have literally nothing with it. All of the communication is end-to-end encrypted, the offer is end-to-end encrypted, we don't know the users. So—but having this reputation model I described, what is actually happening—so, as I said, you might reveal the identity in the chat to each other with your—with your counterparty. But there's the point where someone could be impersonating someone else.","offset":869,"duration":26},{"text":"Lea: So what you do—and this is actually happening, and it works really, really flawlessly—is that you ask the common contact for recommendation. And you don't even have to ask if—uh, or you don't even have to tell that, \"Okay, this is—I'm trading Bitcoin with them,\" or whatever. You can just ask like, \"Is this a real person? Do you really know them?\"","offset":895,"duration":26},{"text":"Lea: Also, it allows you to individualize, to have the like very individualized look on—on the risk assessment, right? Because well, if I'm trading, if I need to buy 100 euros in lightning, I don't need to reveal identity and maybe I don't even need to ask the common person. If I will be trading one Bitcoin on-chain with $70,000 in cash, I will ask couple of people if I want to meet that person and if they are legit.","offset":921,"duration":28},{"text":"Lea: So, and honestly, like most of these—most of these issues can be prevented and most of the fraud can be prevented if you're meeting with the person in—in person. Like, and if you are—if you're sane, and actually treat it as, for example, dating. Well, you wouldn't meet someone in the middle of a forest in the middle of the night. You go to a public place, you have a coffee, you wait for two confirmations, you take the cash, and you shake hands and you split.","offset":949,"duration":30},{"text":"Lea: So, but that being said, like as I said, like these—these are hypothetically possible, but it's very rare on Vexl because as—like, inherently people want to behave properly when they know they might be ostracized.","offset":979,"duration":24},{"text":"Lea: No. I mean, we have—we because that's one of the challenge of like anonymous or like privacy-aware apps, like how are you tracking success and like what are your KPIs? So we have some kind of—we have like very basic tracking with data that is aggregated and anonymized, stripped of whatever identifiers there could possibly be, there are noise.","offset":1003,"duration":26},{"text":"Lea: So we are more like spotting—like, transporting instead of like—we can't have like exact KPIs. And one of these metrics is after you close a chat, we prompt you to leave an anonym—anonymous feedback where you can tell us like if the trade went well or not. And if it didn't go well, what was the problem. So—and it's rare. Like, most—like, if—if there is like—it's rare that there will be a fraud.","offset":1029,"duration":27},{"text":"Lea: I think it—I don't think we ever got any kind of report like this. What we got was maybe like, \"Yeah, the counterparty didn't show up.\" So, right. They got ghosted. No. We have different kind of policing of the network, um, and that's basically because we cannot prevent users, um—sorry.","offset":1056,"duration":23},{"text":"Lea: Yeah, we cannot prevent you to like buy 10 phone numbers and log with 10 phone numbers. And what we can do, because well, if I block you, you can just like try again. And as I'm not doing KYC, I cannot block Matt Odell, right? What we—what we can do and what we're doing—and it's something that we consider—consider like to be really um, like working out for us—is like we are shadow-banning offers.","offset":1079,"duration":29},{"text":"Lea: So that means if there is an offer that was problematic, uh, if three people—and this threshold can be changed—if three people marked that and flagged that offer, we—uh, stop showing it to like no one. So even if you're a scammer or you're a shady person or you sent like dick pics in—in a chat, uh, well, you just—you won't be shown to—to other users.","offset":1108,"duration":32}],"startTime":815},{"title":"Funding Open-Source Privacy Tools","summary":"Lea discusses Vexl's non-profit model and the struggle of funding open-source privacy projects. Matt adds how OpenSats facilitates large donations for such initiatives.","entries":[{"text":"Matt Odell: That makes sense to me. Um, is—is the goal for Vexl to be a for-profit project? And if so, how do you make money?","offset":1140,"duration":24},{"text":"Lea: So it's Vexl the app that has the developer account that is employing people, employing contractors, etc. And on the top, there is Vexl Foundation that is supporting Vexl and also other privacy-aware projects, communities, etc. Cool. So it's not just for Vexl, just basically it's a foundation dedicated to defending individual financial freedom.","offset":1164,"duration":24},{"text":"Lea: And well, but of course—and the Vexl as the app, well, it was brought to life as a gift to community. And it was brought to life because our very deep dedication and deep belief that we—we need an app like Vexl. And we don't plan to monetize it in any way. And we can't even, if we want—if we want to have a Vexl without KYC, we can't monetize.","offset":1188,"duration":25},{"text":"Lea: If we want to have it as privacy-aware as it is, it has to be this way. That being said, it's incredibly challenging to be an open-source project that is privacy-aware. Can't even sell the data, you know, to well maintain like financial health. So of course, we are constantly evaluating various various possible streams how that we could direct towards supporting Vexl.","offset":1213,"duration":28},{"text":"Lea: But the Vexl app as it is now, we plan to keep this uh for free. So there might be ways for launching or there might be ways for us to launch a separate service in the future that would be just—that would come to life just uh in order to support Vexl's mission, but right now there is none.","offset":1241,"duration":38},{"text":"Lea: I mean, like, look at me, I'm—I'm too way good-looking to be in—to spend my best life, best years of life in jail. So it's like—so far now we are very, very grateful to Satoshi Labs, V_H_R_F for—OpenSats for supporting us and enabling us to maintain—maintain the service up and running.","offset":1279,"duration":25},{"text":"Lea: That being said, I don't want to poke, but I don't want to poke, but I think we could be better—we could be doing much better as an industry generally. And as you said, like trying to maintain uh this kind of services and support them financially, it's not easy even if you—if you have a for-profit company and you want to support a service like—like ours. It's not easy for you either way.","offset":1304,"duration":28},{"text":"Lea: Like, for example, what happened to me is like, I personally know a CEO of of an exchange that uses us every week to trade Bitcoin. Cool. Like peer-to-peer without KYC, and they can't do it, and they hate KYC, but they can't support us because they are like, \"Yeah Lea, I can't give you money because well, I want to have my license, you know.\"","offset":1332,"duration":19},{"text":"Matt Odell: Yeah. So it's really tricky. I wish I've seen more entrepreneurs having balls and you know, directing—like, I mean, for this kind of companies earning like crapload—earning crapload, like it's like tiny portion of their marketing budget they could direct to if not to particular projects then like yeah, to OpenSats, to H_R_F, other other titans on whose shoulders these projects stand.","offset":1351,"duration":30},{"text":"Matt Odell: Yeah, I mean, the freaks know that I—I completely agree with your frustration in terms of trying to find open-source support within this industry. Uh, it has been a massive grind. I'm—I'm grateful to see the support that has been coming, uh, incredibly grateful, but it is—it is very lacking. It is a small subset of businesses and high-net-worth people that are supporting the majority of these projects.","offset":1381,"duration":29},{"text":"Matt Odell: And the industry very much depends on them, whether or not they realize it. Um, by the way, just in your particular situation, OpenSats, we do—we we're happy to facilitate larger one-off donations for you. It's a little bit difficult for us, but for instance, if a large exchange or something wants to pass through a donation to Vexl, like a $500,000 donation or something, and wants to do it through OpenSats, we can make that a reality.","offset":1410,"duration":29},{"text":"Matt Odell: We have done it in the past, but it has—just from a organization standpoint, it's got to be a larger amount because otherwise it—it just gets very—it's a lot of paperwork and what not that we have to do.","offset":1439,"duration":9},{"text":"Matt Odell: Yeah, um, because we have seen it in the past that people want to be disconnected, or I also don't know how your foundation sits, but in the case there's been European foundations that need a US entity so they get a US tax deduction. So we've done it in the past for them. Uh, the big one we did was, uh, we facilitated a million dollars to GrapheneOS.","offset":1448,"duration":21},{"text":"Matt Odell: And Graphene didn't have a foundation yet at this point, and the donor needed to donate through a—a US tax foundation. So they donated through us and then we passed it along to Graphene.","offset":1469,"duration":29},{"text":"Lea: Yeah, kind. It's—Vexl is a separate company, but with what connects us is basically I co-founded Vexl with Slush and Stick, who invented Trezor or invented hardware wallets like what—I don't know, what—13 years ago? Something like that. So, uh, we co-founded Vexl together. And so Satoshi Labs is owning Satoshi Labs, which is basically Slush and Stick, is owning Trezor and part of Vexl, etc.","offset":1498,"duration":29},{"text":"Lea: Other companies as well, Tropic Square, the open-source chip, etc. So that's the—that's the connection. And we share some resources because like, we are very small, lean team. So Trezor—like, if I need an accountant, Trezor might be because they are very kind to us, there might be lending us their accountant for a bit or something like that. Also, we are using their offices.","offset":1527,"duration":24},{"text":"Lea: But uh, except of that, it's a completely separate companies, um, not connected by any means.","offset":1551,"duration":31}],"startTime":1140},{"title":"App Store Censorship & The Freedom Store","summary":"Matt and Lea talk about the necessity of mobile apps and the frustration of dealing with Apple's App Store bans. Lea shares how they launched the Freedom Store via AltStore in the EU.","entries":[{"text":"Matt Odell: It's come a long way from the original—original device. I have like every device, uh.","offset":1582,"duration":39},{"text":"Matt Odell: Yeah, they do a good job with the app. Like the app combination, especially with the new hardware. Yes. Because I think a lot of people are mobile-focused. You know, they don't have a computer. Um, which is also why I think Vexl's really cool. Because I, you know, I think I had the JoinMarket guys on years ago. And I asked them, I asked them, \"When mobile app?\" And they were like, \"Well, if you care about privacy, you should only use desktop.\"","offset":1621,"duration":25},{"text":"Matt Odell: It's like, \"Okay, there's a subset of us that believe in that, but if you want this thing to scale, you gotta be mobile-focused now.\" Like, everything needs to be mobile-focused.","offset":1646,"duration":21},{"text":"Matt Odell: Well, that's a good—good point. I mean, part of the reason I assume you were thinking about PWA is because app stores fucking suck. And so you guys launched your own App Store in Europe, I believe?","offset":1667,"duration":25},{"text":"Lea: Which is like the—and like the amount of correspondence I wrote to Apple over the years by at this time, it might be in the by the range of Anna Karenina, it's like—so imagine my frustration. So it's years and years and years, and they just don't like you. It's like—and they don't give you any kind of like actionable points, like why, what you could do differently in order for them to accept you.","offset":1692,"duration":26},{"text":"Lea: So like—so it was actually year ago, like February 2025, when like once again we were—we got that—that one message telling us like, \"Oh yes, so this is your last 90 days and then like, bye-bye.\" So I was like, and so out of this frustration, I was like, \"Fuck this shit. Like, I really don't know what to do. Like, let's launch our own App Store.\" And we started looking into it back then.","offset":1718,"duration":27},{"text":"Lea: Um, so what we did, we basically used AltStore, the major provider of like side-loading marketplace for for—Apple. And within the AltStore, we launched dedicated like App Store, App Store which is dedicated to freedom tech. So open-source freedom tech. So it's not only for Vexl. If users with the EU App Store download AltStore and then add Freedom Store as a source—by the way, freedomstore.io is where you can check it out—then you can—you will be able to access also other apps like Minibits, Flash, like Sovereign, Bull Bitcoin. So it's not not just us. And any kind of open-source developer that is open-source freedom tech developer that is facing these issues is welcome.","offset":1745,"duration":55},{"text":"Matt Odell: Yes. So this is—this is probably one of the rare situations where the fact that the EU's a heavily regulated bureaucracy actually paid in in the freedom benefit. This is EU-only because Apple was ordered to allow outside app stores in uh into the for European customers. So just to clarify here, AltStore is basically another app store outside of the App Store and then it aggregates like other curators basically. Like, you're one of many different like packages you can install within AltStore.","offset":1800,"duration":43},{"text":"Lea: It's called sources.","offset":1843,"duration":17},{"text":"Lea: Yeah, we have APK's App Store Obtainium. You can also use Aurora Store. Like, when it comes to Android, you can push whatever into that phone. But of course, we don't want to lose Google App—Google Play Store. Right. And like, it's not because I love them, but you have to ask like, \"Okay, who am I building for? Am I building for nerds who are going to go to GitHub and then download APKs, or am I building for rookies who care about the privacy or can—or I can I can shield them from going to KYC exchange and buy with KYC? And I'm building for these people who are coolest, and like Play Store or App Store is the easiest way for them to get the app. So of course, I don't want to lose the—lose those.\"","offset":1860,"duration":48},{"text":"Matt Odell: Yeah. I mean, it's to our earlier conversation where you—it needs to be the most convenient option. You have to meet the users where they're at. Like, if you want this thing to actually scale, obviously if we can if you can get into the major app stores, you want to be there. I mean, working with Apple, trying to stay in the App Store, is like the most frustrating, infuriating thing ever. It's not clear. People, I mean, it's a little bit of an art itself in how to navigate it, especially if you have freedom-oriented aspects to it.","offset":1908,"duration":26},{"text":"Matt Odell: I remember like in Nostr-land, people were like, \"Apple hates us, they won't let Zaps into the App Store stuff.\" And then Primal, we got it in—we got Zaps into the App Store uh with Primal, and they were like, \"How'd you do it?\" And it's like, \"Well, we don't have like a rubric, like hopefully it lasts.\" Like we're just trying our best here to keep it in the App Store.","offset":1934,"duration":21},{"text":"Lea: And that's like—but this is ridiculous because we've been in the App Store for a year and then suddenly like we were not allowed anymore. And like—and you know what the reasoning was? Like, \"Using cash is clearly—clearly reckless.\" And I'm like, \"Dude, what the fuck? Like—\"","offset":1955,"duration":18},{"text":"Matt Odell: Um, so what's the—oh, I guess first off, so if we're in the US and you're have an iPhone, you have to download via TestFlight right now, right?","offset":1973,"duration":26},{"text":"Lea: No, it's 10,000 users. Or like, installs. So 10,000—you have 10,000 seats.","offset":1999,"duration":34},{"text":"Lea: Like, we are—we repeatedly come back to the idea and like evaluate the feasibility. And like, in theory it's feasible, but not—we are using contact list of the phone. And this this—this wouldn't work. Or the UX would be so clumsy, no one would use it. So right now, it's—it's not really feasible or like it doesn't really make sense from the UX perspective. It would be too much effort for well maybe what three users that would be—and also like PWAs, honestly, they never took off.","offset":2033,"duration":32},{"text":"Lea: I remember like five years ago or six years ago everyone would be like, \"Oh yeah, PWAs are changing everything, no more App Stores.\" But like who uses them? Like, you know what I mean?","offset":2065,"duration":34},{"text":"Matt Odell: I will say that I'm cautiously optimistic that all these people vibe coding apps will make them change their mind. Because supposedly right now, they've never had a bigger backlog for App review on the App Store. Um, every app that you see in the App—Apple App Store, freaks, is—is reviewed both usually it's like both by a bot and then by a human.","offset":2099,"duration":26},{"text":"Matt Odell: And then they have—so you can just imagine like just random people, often-times non-developers, like building a new weather app or something, and they're just mass submitting to the Apple App Store. So they're kind of getting DDoS'd right now. And it's causing an issue with their main driver apps because it's just the whole organization is getting slogged down with all these entries. So maybe they end up opening it more. I mean, I would love to see at the very least some kind of like APK-style, \"Okay, if you want to install an app outside of us, we won't listen to the App Store, but you can just click a couple buttons, check a box that says I take full responsibility for potentially messing up my phone and just installing it.\"","offset":2125,"duration":44},{"text":"Lea: It's actually interesting though—or it's sad—that once proponents of privacy and security now like are—like are these morons in like guarding their walled garden. At the same time, like this is one part where the regulation, no matter how much I hate regulation, any kind of regulation, and I feel like any kind of regulation is basically just it feels like if someone is throwing sand into a—into an engine, you know? You know what I mean?","offset":2169,"duration":31},{"text":"Lea: So no matter how much I hate it, um, it feel—like we can see the pressure of regulators around the world on Apple to be opening the platform more. There was—it was a—it was for example in Brazil, which is a huge market, others might follow. So we'll see how that goes.","offset":2200,"duration":32},{"text":"Matt Odell: Like there are people that, um, you know, have been Mac loyalists, iPhone loyalists, they've used it for years. Then they—then they vibe code an app and they want to use it on their iPhone. Maybe they don't even—they're not trying to commercialize it, they just want to use this app on their own iPhone with their own vibe-coded thing. And they're hitting walls and then they're going out and buying their first Android phone ever. And so I think if they're not careful here, if they're not careful here, it's going to cause a—a big momentum shift over to Android.","offset":2232,"duration":30},{"text":"Matt Odell: And if they're savvy, they would at least put a path that might—once again, it might not be as ideal as being in the App Store, right? There's plenty of people that the way they find their app, for better or for worse, is they open up the App Store and they type in \"Bitcoin wallet,\" you know, and and they just take whatever's the top in the App Store. But just a path: a path that like, I've created this app, I don't want to go through the review process, I want people to just download it directly from my website. I'm cautiously optimistic that the the free market pushes their hand here now. So we'll see.","offset":2262,"duration":32},{"text":"Lea: We'll see. Let's hope so.","offset":2294,"duration":38}],"startTime":1582},{"title":"Freedom Tech Summit & Mesh Networks","summary":"Lea promotes the upcoming Freedom Tech Summit in Prague, leading to a discussion on the growing importance of resilient, off-grid communication like mesh networks.","entries":[{"text":"Lea: And then me and a couple of friends like Max Hillebrand, also Stick, we were in parallel organizing a Cypherpunk meetup, which outgrew the DevHackDay eventually. Last year, it basically it had more visitors um from all around the world than the DevHackDay. And we started joking like, \"Yeah, we the next year we have to turn this into a festival.\" So and that—that's kind of happening.","offset":2332,"duration":23},{"text":"Lea: So Freedom Tech Summit is a successor of these two events. It's uh, well, um, it's in the name of the event: it's about all about freedom tech. It's for hackers, it's for builders, it's for designers, anything in—anything in between. One topic that I haven't explicitly mentioned so far was mesh networks. So we also have this track directly focused on we call it resilience track, so any kind of like post-Apple tech that offline communications etc.","offset":2355,"duration":31},{"text":"Lea: That's—and it's basically one-day one-day event where uh all the best brains of the industry being that free communication or free money or free and sound money, uh, off-grid communication, philosophy connected to it, come together and have a lot of fun on workshops, panels, keynotes, anything in between. So everyone is welcome. Uh, we are we are already selling the tickets and accepting calls for proposal, uh, yeah, CFPs, yeah, calls for proposals. So if you go to freedomtechsummit.com, you can find more information about about it there.","offset":2386,"duration":41},{"text":"Matt Odell: I'll put a link in the show notes. I mean, we need more of this. I love it. I think the concept is great. I think the topics are more important than ever. Um, and by the way, freaks, this is—this is the day before BTC Prague in Prague. So you can make one trip. BTC Prague's like the larger, more mainstream event, but still got good Cypherpunk roots. And then this one is going to be a little bit more intimate, probably higher signal.","offset":2427,"duration":27},{"text":"Matt Odell: So you can make—you can make a trip out of it. I will say, um, I unfortunately cannot make it this year for personal reasons, good personal reasons, but Prague is awesome. It is a great city. The Czech Bitcoin community is fantastic. If you're American, it's a really good place to visit. It's—it's relatively cheap, the food's good, the drink's good, the people are good. Everyone speaks English. Absolutely everyone speaks English.","offset":2454,"duration":25},{"text":"Matt Odell: It's a good place for families. I just—I love Prague. Prague is one of my favorite European cities. So just consider it, guys. On the topic of mesh networks, uh, do you have a connection with any of the guys working on F_I_P_S? Are you aware of F_I_P_S?","offset":2479,"duration":20},{"text":"Lea: Yeah, Arjun and Jonathan both of them. Jonathan can't make it, unfortunately. Arjun, fingers crossed, yes, um, but it's not confirmed yet.","offset":2499,"duration":20},{"text":"Lea: Yeah. Yeah, yeah, yeah. Uh, hopefully Arjun will be—yeah, yeah, yeah. Uh, also but of course we are trying to to get more of like for example, when you're buying a ticket, you can you can get the the kit, the MeshCore kit, in the the e-shop, and uh, we will be we will have people flashing it for you, we will have workshops like dedicated to MeshCore uh and but other mesh networks as well, also.","offset":2519,"duration":24},{"text":"Matt Odell: I wasn't familiar with this MeshCore project. Is it similar to Meshtastic or?","offset":2543,"duration":33},{"text":"Matt Odell: I can't even get them on the podcast.","offset":2576,"duration":17},{"text":"Lea: Yeah. Yeah, yeah, yeah. I'm a big fan. I'm a big fan. I can't—I will be never able to tell them in person. Uh, but I love—I love that you guys are leaning into the mesh stuff. I think it's the missing piece. Uh, and it's been—we've just had so many false starts with mesh. It's like hype, uh, you know, for like the last 10 years I've just like, \"Oh, this is the moment. This is—it's gonna happen, now it's—it's about to happen.\"","offset":2593,"duration":29},{"text":"Matt Odell: Um, and to be honest, I feel that way still. But uh, hopefully it happens uh because you know, the internet is uh is way more centralized than people realize and our society depends on it more than ever. So we need we need these alternative these alternative communication networks.","offset":2622,"duration":24},{"text":"Lea: Yes, exactly. But my friend Juri Bednar, who is co-organizing the the event with us, he keeps telling me since January that this is the year of crypto-anarchy. So fingers crossed.","offset":2646,"duration":25},{"text":"Lea: It's like—I'm completely on board with Justin Moon here who said like, it feels like centuries can happen in five years. So that's exactly how it feels to me. It's unbelievable. I have only two poles, right? Like, either like we are doomed or like, \"Wow, we got the—\" and the second one is like, \"We got the fire of Prometheus—fire of gods. They gave us the fire of gods.\" And I'm oscillating in between these two constantly.","offset":2671,"duration":28}],"startTime":2332},{"title":"Growing Local Liquidity Networks","summary":"Lea shares how dedicated individuals can bootstrap Vexl adoption in their area, and highlights the financial opportunity for users acting as local liquidity providers.","entries":[{"text":"Matt Odell: Yeah, I'm right there with you. Uh, I mean, so part of it is with all this stuff is—is it's a bit of a chicken and egg, right? Like you need the scale for them to be effective, but you need the tools to even get bootstrapped in the first place to ever dream of getting the scale. And I mean, I feel like there's a strong uh relationship here with you guys building out Vexl.","offset":2699,"duration":27},{"text":"Matt Odell: Just to get back to the main topic of the conversation, to the freaks listening, how can they be helpful in, you know, achieving this Vexl vision? Because I mean, you guys have found pretty good success. I think it's a very useful tool. Obviously the—like the big the big hold back is the network effect, right? Like if it's friends and friends of friends and you don't have people using it around you, then it's not as useful. So how do you think about how they can be helpful and how we make this thing uh a reality in a bigger way?","offset":2726,"duration":32},{"text":"Lea: So yeah, um, kickstarting a community like this is a pain in the ass. Um, and Odell just left, so—okay. So kickstarting a community like this is a major pain in the ass, but once you achieve a certain threshold, um, once you achieve a certain threshold then it grows exponentially, right? So uh, we are not uh present in the USA because it's a huge country that's far and we're a small team that doesn't have much money.","offset":2758,"duration":31},{"text":"Lea: But uh, good news is you don't need us to support you. We will, if you tell us what you need, we will manage and like for example the community in Namibia, they were like, \"Yeah, give us Namibian dollars, give us that, give us that,\" and we will we will proceed. But we cannot be there and we cannot be organizing meetups and we cannot be spreading the word.","offset":2789,"duration":23},{"text":"Lea: Right. But you can. And we've seen this as a huge success stories success story for example in Canada, where we had one one person that just fell in love with Vexl and started speaking about us on every meetup. And now, I don't want to bullshit you, but Canada might be like the fifth biggest market for us. So that's uh one thing that you can do. Like and we really literally had like zero presence there.","offset":2812,"duration":26},{"text":"Lea: We never like—like we did nothing in Canada. We haven't been in a conference, nothing. There was one person that understood the importance of peer-to-peer non-KYC Bitcoin and they wanted that for them and their community. So organizing meetups, speaking speaking about us, uh reaching out: if you need something from us, we are going to support you. Open an issue on GitHub, reach out to our support, GitHub live support. So speak to us. We are here to help.","offset":2838,"duration":31},{"text":"Lea: Second thing that you can do is uh, something I forgot. Okay, it'll come back to me. But the the community aspect is the most important one. As you said, uh there is the chicken of a chicken and a egg uh problem. And so the user, if they are not connected or they're isolated in the social graph, they don't see any offers.","offset":2869,"duration":25},{"text":"Lea: So I have what I wanted to say is you don't have to feel off or demotivated by the fact that you would have to onboard hundreds of people. So I just to illustrate on an example of like real-world story: imagine the community doesn't have to be big in order to be very active.","offset":2894,"duration":23},{"text":"Lea: So Botswana, for example, is one of our smallest communities again, we haven't we haven't spent any time building any kind of presence there because like we can't. We literally can't. But there must have been someone because um and that's like one of my most favorite stories from Vexl: like just one day I see this tweet from someone I've never heard of who is posting like, \"Yeah, I just bought pickles in Botswana for sats on Vexl.\"","offset":2917,"duration":30},{"text":"Matt Odell: That's awesome.","offset":2947,"duration":22},{"text":"Lea: And someone else who picked that offer. So don't be put off by the fact that we would have to go and be this like, you know, Vexl's witness going from door to door trying to onboard hundreds of users. So once it grows organically and like and it really spread by word of mouth. And the last thing, maybe motivation, you know?","offset":2969,"duration":25},{"text":"Lea: As I said, like a small network is enough. And there might be there might be another chicken and egg problem, so you have let's say like tens of people already on Vexl in your area, in your community, but everyone wants to be buying or everyone wants to be selling and depends. And then so I want to present you a opportunity.","offset":2994,"duration":24},{"text":"Lea: We have uh this is a this is a great opportunity for you to earn money. So what we see and how we actually scaled like how Vexl scaled in different markets, we would have these like agents of grey economy, the people who would be selling or buying with discount or fee and earning on the spread and basically providing liquidity to whatever side and earning like either sats or fiat or whatever how you decide decide to do it.","offset":3018,"duration":34},{"text":"Lea: Uh they would be hedging themselves on both sides and then basically earning money on providing the service. And now we like in the like more active network or the biggest ones here in Czech Republic for example, we can see these liquidity providers would be competing with each other. So they wouldn't be just because they are so many now.","offset":3052,"duration":17},{"text":"Matt Odell: Right.","offset":3069,"duration":17},{"text":"Lea: Exactly, like additional services. Yeah. \"I can come wherever you tell me to.\" So and these people are you don't need many of them. You need one effective one two to just like start serving these couple of users and everyone is happy, right? And these people are these liquidity providers are the blood of the marketplace, right? Without them just like so another like for the greedy ones or for the entrepreneurial ones, uh here is a great opportunity.","offset":3086,"duration":30}],"startTime":2699},{"title":"Vexl Clubs for Bitcoin Meetups","summary":"To accommodate Bitcoiners who prefer not to share phone numbers, Lea introduces Vexl Clubs, a feature allowing meetup organizers to curate trusted trading groups via invite codes.","entries":[{"text":"Matt Odell: Greed is good. I—I mean, I love the meetup point. Uh, especially in the US. I mean, we have such a established meetup infrastructure. There are so many meetups. It's one of the most bullish fundamentals of American Bitcoin. And it seems like such a good fit for meetup organizers. So I—I mean, I will say personally, I mean obviously I co-founded Bitcoin Park in Nashville.","offset":3116,"duration":27},{"text":"Matt Odell: We can do a better job of it. So I'm gonna start thinking about how uh we can incorporate that into our programming. But there's a bunch of meetup organizers that listen to the show, so just consider it. I think it's a way to supercharge your community and make your community more resilient and help out everyone else at the same time. And I do agree with you, like it probably doesn't take that many people. You get like five to 10 people start to use it more actively, and then they get a couple people, and then they're onboarding their nanny, and their nanny instead of buying from Strike, they're buying on Vexl, and then all of a sudden you're scaling.","offset":3143,"duration":24},{"text":"Lea: Exactly. Um and also like it goes vice versa because we also have we currently have couple of ways how we can support the community. One is Vexl Club. We can speak about that for a bit later, but another one is uh um uh another one is like we the upcoming redesign of the app, there will be even more community features that we will be launching.","offset":3167,"duration":27},{"text":"Lea: I don't want to get into too much detail here, stay tuned. But it's already being developed.","offset":3194,"duration":28},{"text":"Lea: It's particularly for for example rural areas where people wouldn't be connected just by their phone numbers. We shift this uh reputation model onto the meetup organizer and they can distribute an invite code that would connect these people. So if you know someone who is going to your meetup, coming to your meetup, for five years, and you know they are trustworthy, you can invite them.","offset":3222,"duration":20},{"text":"Lea: Or like have moderators who would be inviting more people. And then you can see offers from your community from your meetup. Of course you know and you might have people in common or might not. And then you can again like distinguish and individualize that way the risk. Like, okay, am I going to Venmo the money or not? Um, am I going to meet for meeting in person? Am I going to reveal the identity, etc.?","offset":3242,"duration":24},{"text":"Matt Odell: I mean, that makes sense to me because the uh, I'll say at least for my experience as a meetup organizer, you know, they're Bitcoiners, so I don't really have most of their phone numbers. Like, that's not how we communicate. So if there's a separate way to—it makes sense to me that for convenience' sake phone numbers are the single best way to create social graphs.","offset":3266,"duration":23},{"text":"Matt Odell: That's why WhatsApp has been so successful for instance. But on meetups specifically, Bitcoin meetups, I mean we communicate on Signal, right? We communicate through I don't have most of their phone numbers. So if there's a way for like someone to put in a code that is I like—I don't know how you actually set it up. That's on you as the person build part of the team building the project.","offset":3289,"duration":23},{"text":"Matt Odell: But like if there's a way for them to put in \"Nashville Bitcoiners\" and then have offers that are from Nashville Bitcoiners, and maybe that looks like empowering the organizers to manage that community or something like that. Um, I think that would probably go a long way. It would make it a lot easier because right now if I'm thinking about it and we're saying, \"Oh, you should use Vexl,\" we also kind of have to like go around and like collect everyone's phone numbers uh because we just don't have that information right now.","offset":3312,"duration":24},{"text":"Lea: Yeah. Um, it was one of the motivations why we came up with the idea of Vexl Clubs. Uh so uh because no matter that Bitcoiners don't use phone numbers, the rest the rookies I was speaking about they do and it's the best underlying social network there is like there is there is—that is global, that scales, that works everywhere from the east to west, from the north to south.","offset":3336,"duration":24},{"text":"Matt Odell: I agree.","offset":3360,"duration":24},{"text":"Lea: So it always starts with the with the Bitcoin community itself. And that's why we want to empower them as much as possible. And when it comes to when it comes to your point about the organizer then managing the community, it's not the case here. Like you of course you have to be sane like who you you should not put the invitation code somewhere on Twitter, right?","offset":3384,"duration":28},{"text":"Lea: Right. Uh I wouldn't do it. You can, but it's kind of reckless. Uh so well.","offset":3412,"duration":28},{"text":"Matt Odell: Yeah.","offset":3440,"duration":33},{"text":"Lea: We don't know what is happening inside of the club. We don't know who the people joining are, if you are and how you're interacting, nothing like that. It's from that we can just like set up some parameters for you like let it be um number of seats, etc. And again, it works like like the we are not policing it in any way. The people seeing the offers are policing it.","offset":3473,"duration":25},{"text":"Lea: So if there are I guess like five offers within the club that are shadow-banned then the club gets deactivated because probably there is something fishy going on. But we don't know the we don't know the contents of the offer. We don't know identities of the people, nothing like that.","offset":3498,"duration":18},{"text":"Lea: Uh sorry?","offset":3516,"duration":24},{"text":"Matt Odell: To be clear, like as a meetup organizer, I don't want to know either. Like that's how it should be set up.","offset":3540,"duration":22}],"startTime":3116},{"title":"The History Behind the Name Vexl","summary":"Lea shares the origin of Vexl's name, tracing it back to the 'vexclaks' who facilitated black market currency exchanges in the Czech Republic during the Soviet era.","entries":[{"text":"Matt Odell: Okay. Email. Got it. Uh that's awesome. Uh I have a last question for you before we wrap. It's kind of random, but why Vexl? Why'd you come up why is it called that?","offset":3562,"duration":-2981},{"text":"Lea: I like okay. I thought you know the backstory because it's like really interesting.","offset":581,"duration":3030},{"text":"Lea: In Russia it's called \"fartsovka.\" In Romania it was \"bisnitzars.\" In Czech Republic it was \"vexclaks.\" And they were doing \"vexcl.\" So um and the reason how they they gained this name was that these people typically would be people who would be exchanging foreign goods, foreign like currencies, and often in parking lots close to German border. Because there was the border in between the the west and the east.","offset":3611,"duration":32},{"text":"Lea: It would be also happening on the main squares, etc. and would be like these people wearing like long coat or leather jacket and then they would approach you and be like, \"vexcl, vexcl, vexcl.\" And the reason is because it's from German word \"wechseln,\" which means \"to exchange.\" So they acquired it so they were basically saying \"wechseln, wechseln, wechseln\" but bit used it as \"vexcl.\" And these people started to be called \"vexclaks\" in slang, in Czech slang.","offset":3643,"duration":29},{"text":"Lea: So we are paying tribute to them.","offset":3672,"duration":28},{"text":"Lea: —of the dollar was. So they actually went to the vexclaks to ask like, \"Okay, so what how much is the—\" after the Soviet Union fell, um they were actually went to vexclaks to ask ask them like, \"Okay, so uh what's the real real price of dollar these days?\" So.","offset":3700,"duration":20},{"text":"Matt Odell: Is it just makes it real hard for uh governments to pretend their their shitcoin is worth a different amount uh because you just look at what how much is someone willing to trade Bitcoin for it. And if that if that's the amount then that's the real price of whatever their fiat is. Uh, we've seen it time and time again. I mean, I remember I'm not sure what the current state is over there, but for a while like the official Argentinian price uh of dollars to I guess Argentinian pesos—I think that's what they're called—was way off of the difference between Bitcoin to them. And then you could just use you could use that as the official price of it.","offset":3720,"duration":42},{"text":"Lea: Actually, if I have one KPI for Vexl that's uh our two I have two KPIs. One would be if we used \"to Vexl\" in the same way as we use \"to HODL\" for peer-to-peer trading like \"to Vexl it.\" I love it. Use it as a verb. That would be pretty cool. And second one if the price—and that's that's how I will know that we made it everywhere—if the price of Bitcoin, the real price, the street price, will be the one that is being traded on Vexl, you know? Not what the charts on Binance show you, but the street price on Vexl.","offset":3762,"duration":39}],"startTime":3562},{"title":"Outro & Next Episode Teaser","summary":"Matt wraps up the show, encouraging listeners to trade peer-to-peer, and teases the upcoming episode featuring the founder of SimpleX.","entries":[{"text":"Matt Odell: Yeah, well the P2P exchanges is what keeps the centralized exchanges at least relatively honest. They can't play too many games. Lea, this was uh this was a great conversation. I would love can we plan on like uh doing it again in a year maybe and see where we're at?","offset":3801,"duration":24},{"text":"Lea: Uh that we need one zillion unregulated little exchanges, um and every single one of us can act as one. Be that on Vexl or not. So don't send your friends to centralized exchanges. Some sell sell them some Bitcoin or buy from them and don't tell anyone.","offset":3825,"duration":29},{"text":"Matt Odell: Freaks, I hope you enjoyed this conversation as much as me. I have a great conversation lined up on Friday. The next conversation, it's going to be with the SimpleX founder, uh the encrypted chat app. I'm very excited for it. Um, it's an awesome app if you haven't used it. All the links we talked about today will be in the show notes, so check them out if you forget what links you need. And uh love you all. Stay humble, stack sats. Peace.","offset":3854,"duration":15}],"startTime":3801}],"entries":[{"text":"Matt Odell: Happy Bitcoin Monday, freaks! It's a beautiful Monday morning over here, and we've got a great show lined up. As always, this is Citadel Dispatch, the show focused on Bitcoin and freedom tech discussion. I'm your host, Odell. The current Bitcoin block height is 940,918.","offset":0,"duration":26},{"text":"Matt Odell: Sats per dollar is 1,355. The fiat price, in dollar terms—I guess that was also the fiat price—is $73,753. We got a little pump going on this morning. UTC time, it's Monday, March 16th, at 1800 UTC. You will be listening to this in a few hours once I clean it up and get it uploaded.","offset":26,"duration":28},{"text":"Matt Odell: Bitcoin priced in gold: one Bitcoin can now buy you 14.46 ounces. We're pumping in gold terms. We're up on the one-day, one-week, and one-month. Now we're just watching that one-year. I think we'll flip that, hopefully, relatively soon. As always, Dispatch is funded by viewers like you. We have no ads or sponsors.","offset":54,"duration":27},{"text":"Matt Odell: So thank you, freaks, for supporting the show. Our largest zaps from last week was Blockchain Boog with 50,000 sats. He said, \"Big fan of Vexl. Thanks for interviewing Scott and letting people know about this awesome project.\" We also got a 50,000 sat zap from Prodigious: \"Great content as always.\"","offset":81,"duration":24},{"text":"Matt Odell: And then we got two 21,000 sat zaps. We got Vertical Vines: \"Long-time Dispatch listener here, currently trying to liberate 3D printing.\" Love to hear it. And Rod Palmer: \"Very bullish on Vexl, Scott, and simplicity.\" Thank you, freaks, for your support. As always, if you do not have sats to spare—I know they're hard-earned—you can also support the show by sharing it with your friends and family.","offset":105,"duration":28},{"text":"Matt Odell: Citadel Dispatch is available on every podcast app by searching \"Citadel Dispatch.\" You can also—all relevant links are at citadeldispatch.com. Also, by the way, freaks, just real quick, I've been going down an AI rabbit hole, so I told you guys about citadelwire.com, which is my AI-powered news desk, which is getting quite good, so check it out if you haven't.","offset":133,"duration":27},{"text":"Matt Odell: But I also decided to start making games, so you can go to citadelarcade.com. Coin-operated, nostalgia fun, simple games, no bullshit, no ads. You just pay 100 sats—that's seven cents right now, FYI guys—and get on the leaderboard. But check it out: citadelarcade.com. Anyway, we have a great show lined up. I have Lea here, founder—founder of Vexl.","offset":160,"duration":27},{"text":"Matt Odell: And she's focused on P2P exchange, no-KYC Bitcoin buying. How's it going?","offset":187,"duration":25},{"text":"Matt Odell: Also, I mean, I've been going down a bit of an AI rabbit hole, so the freaks have been getting AI shows left and right, so it's nice to be back to the basics of Bitcoin.","offset":212,"duration":25},{"text":"Lea: Vexl is a mobile app that allows you to buy and sell Bitcoin and products and services for Bitcoin, like it was intended. And when I say like it was intended, I don't mean intended by myself, but Satoshi Nakamoto himself, who in the very first sentence of the Bitcoin whitepaper said that Bitcoin should be peer-to-peer electronic cash that would allow you to transact without going through third parties, right?","offset":237,"duration":29},{"text":"Lea: But, well, it's not where the industry really shifted over the past couple of years. And certainly, Vexl is our attempt to bring Bitcoin back where it belongs, and that means from the hands of institutions to the hands of the users.","offset":266,"duration":28},{"text":"Matt Odell: Obviously, it's become very pervasive through the Bitcoin space, but also just pervasive, I think, through all of our digital lives. It's not just Bitcoin. It's very obvious in Bitcoin because the friction is heavy when you mix freedom money with highly regulated KYC services. But it's everywhere: it's in social media land, I mean, it's all over the place. Once you start paying attention, you start to realize that it's really seeping in everywhere.","offset":294,"duration":27},{"text":"Matt Odell: So it's cool to see Vexl launch in that environment. I guess, when did you guys launch? About two years ago, I think?","offset":321,"duration":30},{"text":"Lea: Exactly. And well, it might sound like, um, well, what is interesting about that, right? There is zillion apps, uh, desktop as mobile apps, that do exactly that. But what Vexl brings to the table as an innovation is the reputation model, I'd dare to say. And with us, it's—it's quite interesting, and I know it will sound controversial, uh, in the first place, but hear me out.","offset":351,"duration":27},{"text":"Lea: So basically, on Vexl you can meet only people you know or people you know know. While everything you see on the app is anonymous and end-to-end encrypted, you always know that you can't meet strangers and you can't trade with strangers. That's very important. And so how it works: when you download the app and you log—log into it, we determine your social graph based on your contact list in your mobile—of your, um, phone contact list.","offset":378,"duration":29},{"text":"Lea: And we show you the offers that are only encrypted for you in within this certain social graph. And you don't know who you're trading with, or you don't know until you decide to reveal the identity to each other in an end-to-end encrypted chat. But with every offer, which is anonymized, you can see how many common contacts you have with the—with the counterparty and who these people are.","offset":407,"duration":28},{"text":"Lea: Which, uh, when you zoom out, is very interesting because you always know per every offer in which social bubble you're kind of moving within. If you really think about it, the innovation is that we actually, in this way, we managed to bring the real-world reputation into an app, which—which I think it's—it's something, well, unheard of before.","offset":435,"duration":26},{"text":"Matt Odell: Yeah, I mean, I think as someone who's been neck-deep in both the education side of Bitcoin and also building products in Bitcoin, the ideological stance of privacy best practices only gets you so far. Ultimately, what scales is users choose what's most convenient to them. So what I think is cool about Vexl is that, yes, I'm sure you probably have been bootstrapped with a bunch of users that really care about privacy and they seek it out.","offset":461,"duration":31},{"text":"Matt Odell: But as it scales, it's probably more just users finding it the most convenient option. And you guys have really done a good job of nailing that UX, nailing that user experience. So it's actually more convenient than using whatever your local KYC-regulated exchange is. And that's how we actually see massive user growth in these types of use cases.","offset":492,"duration":23},{"text":"Matt Odell: Would you agree? I almost kind of—I kind of think of it, and I haven't been in this world for a long, long time now at this point, but it's kind of similar to the dating app issue, right? Where people don't want to meet with strangers, but they want to meet with friends or friends of friends.","offset":515,"duration":27},{"text":"Lea: Um, and I'm very happy that you actually, well, pinpointed the UX because that's something I'm very proud of. From the day one, as we started designing Vexl and thinking about Vexl, I kept asking myself the question like, would my aunt be able to use this without—without guidance? And that was—that was my guideline for any kind of UX decision we were making.","offset":542,"duration":26},{"text":"Lea: It's—it's like—it's a huge focus since the very beginning, that it must—it must be understood by rookie—rookie users, uh, because like, look, if a product needs a two-hour long tutorial, it's not a good product.","offset":568,"duration":28},{"text":"Lea: [Laughs] That's an amazing KPI. I don't want to point fingers on BTC—onto BTC Sessions, but so far—so far, no guides on Vexl.","offset":596,"duration":28},{"text":"Matt Odell: On your platform, what is the—what's the most common way that people are exchanging that side of the equation?","offset":624,"duration":28},{"text":"Matt Odell: It's like, the Bitcoin transfer side, they can send me Bitcoin super easily: I give them a Bitcoin address and they send me Bitcoin. The dollar side is the difficult part. I'm like sending them a wire transfer or in Europe like a Revolut payment or something like that. So how do you see the people using the dollar or euro side of the equation?","offset":652,"duration":16},{"text":"Lea: Okay, gotcha. Okay, so basically, it's always the local currency. And the important thing to note when we say peer-to-peer what we are encouraging is actually meeting in person, handing over the whatever fiat shitcoin you want to hand over. Cash. Yes. But that being said, if I connect over Vexl with someone who is sitting in an open space two desks from me, yes, I will Venmo the money or Revolut the money and I wouldn't care.","offset":668,"duration":28},{"text":"Lea: Important thing why we are—like, we can't say and we don't know, and it's impossible for us to know how people behave in reality. And but what I wanted to state is that the exchange itself happens out of the platform. We never touch fiat, we never touch Bitcoin, we never touch any data like associated with the transaction itself.","offset":696,"duration":27},{"text":"Lea: Um, so—but mostly, mostly, what we know, and that means literally what people are tweeting if they are tweeting or telling us when we meet them, is meeting in person.","offset":723,"duration":27},{"text":"Matt Odell: I'm like looked at—I go to dinner with friends or whatever, I pull out cash from my pocket, they like look like I'm crazy, everyone's throwing cards on the table. There's a whole informal economy in the US that's based on Venmo. You know, like my nanny, she usually accepts Venmo payments, uh, I don't know, the dog groomer, everyone accepts Venmo. Cash is the exception for them. Like, I'm one of the few people that pay them in cash.","offset":750,"duration":24},{"text":"Matt Odell: So I'm expecting that as you scale, more people will be using these, I don't know, these controlled fiat rails, and they come with a bunch of fraud issues. How do you think about those? Like, if someone sends a Bitcoin payment, obviously it's not reversible. It's beautiful, right? Bitcoin is fantastic. But if there historically with P2P exchanges, because Bitcoin is not reversible, there's been issues with the—the fiat side.","offset":774,"duration":26},{"text":"Matt Odell: And obviously, I mean, it's cool that you guys don't touch any of the actual flows of money or see actually the details of the transaction. So maybe you're limited there. But like, what does a user do if they get defrauded, basically, on the dollar or euro side?","offset":800,"duration":15},{"text":"Lea: So it's actually hard to be—like, to get fraud on Vexl, because well, as I said, like maybe let me repeat: the reputation model is all about like having common people you both know, right? And so you're strongly incentivized to behave properly on Vexl, because well, just easily, you—I mean, simply you don't want to be called a dick among your friends, right? So—and this works.","offset":815,"duration":29},{"text":"Lea: Of course, there might be like attacks like man-in-the-middle attack, or someone can try to impersonate you or whoever. That might happen, but it's very easily mitigated and it's actually something that works beautifully on Vexl. In like three years, we might have had maybe one man-in-the-middle attack we knew about. And unfortunately, like we can't do anything because we don't even know that the transaction happened, right?","offset":844,"duration":25},{"text":"Lea: Like, we have literally nothing with it. All of the communication is end-to-end encrypted, the offer is end-to-end encrypted, we don't know the users. So—but having this reputation model I described, what is actually happening—so, as I said, you might reveal the identity in the chat to each other with your—with your counterparty. But there's the point where someone could be impersonating someone else.","offset":869,"duration":26},{"text":"Lea: So what you do—and this is actually happening, and it works really, really flawlessly—is that you ask the common contact for recommendation. And you don't even have to ask if—uh, or you don't even have to tell that, \"Okay, this is—I'm trading Bitcoin with them,\" or whatever. You can just ask like, \"Is this a real person? Do you really know them?\"","offset":895,"duration":26},{"text":"Lea: Also, it allows you to individualize, to have the like very individualized look on—on the risk assessment, right? Because well, if I'm trading, if I need to buy 100 euros in lightning, I don't need to reveal identity and maybe I don't even need to ask the common person. If I will be trading one Bitcoin on-chain with $70,000 in cash, I will ask couple of people if I want to meet that person and if they are legit.","offset":921,"duration":28},{"text":"Lea: So, and honestly, like most of these—most of these issues can be prevented and most of the fraud can be prevented if you're meeting with the person in—in person. Like, and if you are—if you're sane, and actually treat it as, for example, dating. Well, you wouldn't meet someone in the middle of a forest in the middle of the night. You go to a public place, you have a coffee, you wait for two confirmations, you take the cash, and you shake hands and you split.","offset":949,"duration":30},{"text":"Lea: So, but that being said, like as I said, like these—these are hypothetically possible, but it's very rare on Vexl because as—like, inherently people want to behave properly when they know they might be ostracized.","offset":979,"duration":24},{"text":"Lea: No. I mean, we have—we because that's one of the challenge of like anonymous or like privacy-aware apps, like how are you tracking success and like what are your KPIs? So we have some kind of—we have like very basic tracking with data that is aggregated and anonymized, stripped of whatever identifiers there could possibly be, there are noise.","offset":1003,"duration":26},{"text":"Lea: So we are more like spotting—like, transporting instead of like—we can't have like exact KPIs. And one of these metrics is after you close a chat, we prompt you to leave an anonym—anonymous feedback where you can tell us like if the trade went well or not. And if it didn't go well, what was the problem. So—and it's rare. Like, most—like, if—if there is like—it's rare that there will be a fraud.","offset":1029,"duration":27},{"text":"Lea: I think it—I don't think we ever got any kind of report like this. What we got was maybe like, \"Yeah, the counterparty didn't show up.\" So, right. They got ghosted. No. We have different kind of policing of the network, um, and that's basically because we cannot prevent users, um—sorry.","offset":1056,"duration":23},{"text":"Lea: Yeah, we cannot prevent you to like buy 10 phone numbers and log with 10 phone numbers. And what we can do, because well, if I block you, you can just like try again. And as I'm not doing KYC, I cannot block Matt Odell, right? What we—what we can do and what we're doing—and it's something that we consider—consider like to be really um, like working out for us—is like we are shadow-banning offers.","offset":1079,"duration":29},{"text":"Lea: So that means if there is an offer that was problematic, uh, if three people—and this threshold can be changed—if three people marked that and flagged that offer, we—uh, stop showing it to like no one. So even if you're a scammer or you're a shady person or you sent like dick pics in—in a chat, uh, well, you just—you won't be shown to—to other users.","offset":1108,"duration":32},{"text":"Matt Odell: That makes sense to me. Um, is—is the goal for Vexl to be a for-profit project? And if so, how do you make money?","offset":1140,"duration":24},{"text":"Lea: So it's Vexl the app that has the developer account that is employing people, employing contractors, etc. And on the top, there is Vexl Foundation that is supporting Vexl and also other privacy-aware projects, communities, etc. Cool. So it's not just for Vexl, just basically it's a foundation dedicated to defending individual financial freedom.","offset":1164,"duration":24},{"text":"Lea: And well, but of course—and the Vexl as the app, well, it was brought to life as a gift to community. And it was brought to life because our very deep dedication and deep belief that we—we need an app like Vexl. And we don't plan to monetize it in any way. And we can't even, if we want—if we want to have a Vexl without KYC, we can't monetize.","offset":1188,"duration":25},{"text":"Lea: If we want to have it as privacy-aware as it is, it has to be this way. That being said, it's incredibly challenging to be an open-source project that is privacy-aware. Can't even sell the data, you know, to well maintain like financial health. So of course, we are constantly evaluating various various possible streams how that we could direct towards supporting Vexl.","offset":1213,"duration":28},{"text":"Lea: But the Vexl app as it is now, we plan to keep this uh for free. So there might be ways for launching or there might be ways for us to launch a separate service in the future that would be just—that would come to life just uh in order to support Vexl's mission, but right now there is none.","offset":1241,"duration":38},{"text":"Lea: I mean, like, look at me, I'm—I'm too way good-looking to be in—to spend my best life, best years of life in jail. So it's like—so far now we are very, very grateful to Satoshi Labs, V_H_R_F for—OpenSats for supporting us and enabling us to maintain—maintain the service up and running.","offset":1279,"duration":25},{"text":"Lea: That being said, I don't want to poke, but I don't want to poke, but I think we could be better—we could be doing much better as an industry generally. And as you said, like trying to maintain uh this kind of services and support them financially, it's not easy even if you—if you have a for-profit company and you want to support a service like—like ours. It's not easy for you either way.","offset":1304,"duration":28},{"text":"Lea: Like, for example, what happened to me is like, I personally know a CEO of of an exchange that uses us every week to trade Bitcoin. Cool. Like peer-to-peer without KYC, and they can't do it, and they hate KYC, but they can't support us because they are like, \"Yeah Lea, I can't give you money because well, I want to have my license, you know.\"","offset":1332,"duration":19},{"text":"Matt Odell: Yeah. So it's really tricky. I wish I've seen more entrepreneurs having balls and you know, directing—like, I mean, for this kind of companies earning like crapload—earning crapload, like it's like tiny portion of their marketing budget they could direct to if not to particular projects then like yeah, to OpenSats, to H_R_F, other other titans on whose shoulders these projects stand.","offset":1351,"duration":30},{"text":"Matt Odell: Yeah, I mean, the freaks know that I—I completely agree with your frustration in terms of trying to find open-source support within this industry. Uh, it has been a massive grind. I'm—I'm grateful to see the support that has been coming, uh, incredibly grateful, but it is—it is very lacking. It is a small subset of businesses and high-net-worth people that are supporting the majority of these projects.","offset":1381,"duration":29},{"text":"Matt Odell: And the industry very much depends on them, whether or not they realize it. Um, by the way, just in your particular situation, OpenSats, we do—we we're happy to facilitate larger one-off donations for you. It's a little bit difficult for us, but for instance, if a large exchange or something wants to pass through a donation to Vexl, like a $500,000 donation or something, and wants to do it through OpenSats, we can make that a reality.","offset":1410,"duration":29},{"text":"Matt Odell: We have done it in the past, but it has—just from a organization standpoint, it's got to be a larger amount because otherwise it—it just gets very—it's a lot of paperwork and what not that we have to do.","offset":1439,"duration":9},{"text":"Matt Odell: Yeah, um, because we have seen it in the past that people want to be disconnected, or I also don't know how your foundation sits, but in the case there's been European foundations that need a US entity so they get a US tax deduction. So we've done it in the past for them. Uh, the big one we did was, uh, we facilitated a million dollars to GrapheneOS.","offset":1448,"duration":21},{"text":"Matt Odell: And Graphene didn't have a foundation yet at this point, and the donor needed to donate through a—a US tax foundation. So they donated through us and then we passed it along to Graphene.","offset":1469,"duration":29},{"text":"Lea: Yeah, kind. It's—Vexl is a separate company, but with what connects us is basically I co-founded Vexl with Slush and Stick, who invented Trezor or invented hardware wallets like what—I don't know, what—13 years ago? Something like that. So, uh, we co-founded Vexl together. And so Satoshi Labs is owning Satoshi Labs, which is basically Slush and Stick, is owning Trezor and part of Vexl, etc.","offset":1498,"duration":29},{"text":"Lea: Other companies as well, Tropic Square, the open-source chip, etc. So that's the—that's the connection. And we share some resources because like, we are very small, lean team. So Trezor—like, if I need an accountant, Trezor might be because they are very kind to us, there might be lending us their accountant for a bit or something like that. Also, we are using their offices.","offset":1527,"duration":24},{"text":"Lea: But uh, except of that, it's a completely separate companies, um, not connected by any means.","offset":1551,"duration":31},{"text":"Matt Odell: It's come a long way from the original—original device. I have like every device, uh.","offset":1582,"duration":39},{"text":"Matt Odell: Yeah, they do a good job with the app. Like the app combination, especially with the new hardware. Yes. Because I think a lot of people are mobile-focused. You know, they don't have a computer. Um, which is also why I think Vexl's really cool. Because I, you know, I think I had the JoinMarket guys on years ago. And I asked them, I asked them, \"When mobile app?\" And they were like, \"Well, if you care about privacy, you should only use desktop.\"","offset":1621,"duration":25},{"text":"Matt Odell: It's like, \"Okay, there's a subset of us that believe in that, but if you want this thing to scale, you gotta be mobile-focused now.\" Like, everything needs to be mobile-focused.","offset":1646,"duration":21},{"text":"Matt Odell: Well, that's a good—good point. I mean, part of the reason I assume you were thinking about PWA is because app stores fucking suck. And so you guys launched your own App Store in Europe, I believe?","offset":1667,"duration":25},{"text":"Lea: Which is like the—and like the amount of correspondence I wrote to Apple over the years by at this time, it might be in the by the range of Anna Karenina, it's like—so imagine my frustration. So it's years and years and years, and they just don't like you. It's like—and they don't give you any kind of like actionable points, like why, what you could do differently in order for them to accept you.","offset":1692,"duration":26},{"text":"Lea: So like—so it was actually year ago, like February 2025, when like once again we were—we got that—that one message telling us like, \"Oh yes, so this is your last 90 days and then like, bye-bye.\" So I was like, and so out of this frustration, I was like, \"Fuck this shit. Like, I really don't know what to do. Like, let's launch our own App Store.\" And we started looking into it back then.","offset":1718,"duration":27},{"text":"Lea: Um, so what we did, we basically used AltStore, the major provider of like side-loading marketplace for for—Apple. And within the AltStore, we launched dedicated like App Store, App Store which is dedicated to freedom tech. So open-source freedom tech. So it's not only for Vexl. If users with the EU App Store download AltStore and then add Freedom Store as a source—by the way, freedomstore.io is where you can check it out—then you can—you will be able to access also other apps like Minibits, Flash, like Sovereign, Bull Bitcoin. So it's not not just us. And any kind of open-source developer that is open-source freedom tech developer that is facing these issues is welcome.","offset":1745,"duration":55},{"text":"Matt Odell: Yes. So this is—this is probably one of the rare situations where the fact that the EU's a heavily regulated bureaucracy actually paid in in the freedom benefit. This is EU-only because Apple was ordered to allow outside app stores in uh into the for European customers. So just to clarify here, AltStore is basically another app store outside of the App Store and then it aggregates like other curators basically. Like, you're one of many different like packages you can install within AltStore.","offset":1800,"duration":43},{"text":"Lea: It's called sources.","offset":1843,"duration":17},{"text":"Lea: Yeah, we have APK's App Store Obtainium. You can also use Aurora Store. Like, when it comes to Android, you can push whatever into that phone. But of course, we don't want to lose Google App—Google Play Store. Right. And like, it's not because I love them, but you have to ask like, \"Okay, who am I building for? Am I building for nerds who are going to go to GitHub and then download APKs, or am I building for rookies who care about the privacy or can—or I can I can shield them from going to KYC exchange and buy with KYC? And I'm building for these people who are coolest, and like Play Store or App Store is the easiest way for them to get the app. So of course, I don't want to lose the—lose those.\"","offset":1860,"duration":48},{"text":"Matt Odell: Yeah. I mean, it's to our earlier conversation where you—it needs to be the most convenient option. You have to meet the users where they're at. Like, if you want this thing to actually scale, obviously if we can if you can get into the major app stores, you want to be there. I mean, working with Apple, trying to stay in the App Store, is like the most frustrating, infuriating thing ever. It's not clear. People, I mean, it's a little bit of an art itself in how to navigate it, especially if you have freedom-oriented aspects to it.","offset":1908,"duration":26},{"text":"Matt Odell: I remember like in Nostr-land, people were like, \"Apple hates us, they won't let Zaps into the App Store stuff.\" And then Primal, we got it in—we got Zaps into the App Store uh with Primal, and they were like, \"How'd you do it?\" And it's like, \"Well, we don't have like a rubric, like hopefully it lasts.\" Like we're just trying our best here to keep it in the App Store.","offset":1934,"duration":21},{"text":"Lea: And that's like—but this is ridiculous because we've been in the App Store for a year and then suddenly like we were not allowed anymore. And like—and you know what the reasoning was? Like, \"Using cash is clearly—clearly reckless.\" And I'm like, \"Dude, what the fuck? Like—\"","offset":1955,"duration":18},{"text":"Matt Odell: Um, so what's the—oh, I guess first off, so if we're in the US and you're have an iPhone, you have to download via TestFlight right now, right?","offset":1973,"duration":26},{"text":"Lea: No, it's 10,000 users. Or like, installs. So 10,000—you have 10,000 seats.","offset":1999,"duration":34},{"text":"Lea: Like, we are—we repeatedly come back to the idea and like evaluate the feasibility. And like, in theory it's feasible, but not—we are using contact list of the phone. And this this—this wouldn't work. Or the UX would be so clumsy, no one would use it. So right now, it's—it's not really feasible or like it doesn't really make sense from the UX perspective. It would be too much effort for well maybe what three users that would be—and also like PWAs, honestly, they never took off.","offset":2033,"duration":32},{"text":"Lea: I remember like five years ago or six years ago everyone would be like, \"Oh yeah, PWAs are changing everything, no more App Stores.\" But like who uses them? Like, you know what I mean?","offset":2065,"duration":34},{"text":"Matt Odell: I will say that I'm cautiously optimistic that all these people vibe coding apps will make them change their mind. Because supposedly right now, they've never had a bigger backlog for App review on the App Store. Um, every app that you see in the App—Apple App Store, freaks, is—is reviewed both usually it's like both by a bot and then by a human.","offset":2099,"duration":26},{"text":"Matt Odell: And then they have—so you can just imagine like just random people, often-times non-developers, like building a new weather app or something, and they're just mass submitting to the Apple App Store. So they're kind of getting DDoS'd right now. And it's causing an issue with their main driver apps because it's just the whole organization is getting slogged down with all these entries. So maybe they end up opening it more. I mean, I would love to see at the very least some kind of like APK-style, \"Okay, if you want to install an app outside of us, we won't listen to the App Store, but you can just click a couple buttons, check a box that says I take full responsibility for potentially messing up my phone and just installing it.\"","offset":2125,"duration":44},{"text":"Lea: It's actually interesting though—or it's sad—that once proponents of privacy and security now like are—like are these morons in like guarding their walled garden. At the same time, like this is one part where the regulation, no matter how much I hate regulation, any kind of regulation, and I feel like any kind of regulation is basically just it feels like if someone is throwing sand into a—into an engine, you know? You know what I mean?","offset":2169,"duration":31},{"text":"Lea: So no matter how much I hate it, um, it feel—like we can see the pressure of regulators around the world on Apple to be opening the platform more. There was—it was a—it was for example in Brazil, which is a huge market, others might follow. So we'll see how that goes.","offset":2200,"duration":32},{"text":"Matt Odell: Like there are people that, um, you know, have been Mac loyalists, iPhone loyalists, they've used it for years. Then they—then they vibe code an app and they want to use it on their iPhone. Maybe they don't even—they're not trying to commercialize it, they just want to use this app on their own iPhone with their own vibe-coded thing. And they're hitting walls and then they're going out and buying their first Android phone ever. And so I think if they're not careful here, if they're not careful here, it's going to cause a—a big momentum shift over to Android.","offset":2232,"duration":30},{"text":"Matt Odell: And if they're savvy, they would at least put a path that might—once again, it might not be as ideal as being in the App Store, right? There's plenty of people that the way they find their app, for better or for worse, is they open up the App Store and they type in \"Bitcoin wallet,\" you know, and and they just take whatever's the top in the App Store. But just a path: a path that like, I've created this app, I don't want to go through the review process, I want people to just download it directly from my website. I'm cautiously optimistic that the the free market pushes their hand here now. So we'll see.","offset":2262,"duration":32},{"text":"Lea: We'll see. Let's hope so.","offset":2294,"duration":38},{"text":"Lea: And then me and a couple of friends like Max Hillebrand, also Stick, we were in parallel organizing a Cypherpunk meetup, which outgrew the DevHackDay eventually. Last year, it basically it had more visitors um from all around the world than the DevHackDay. And we started joking like, \"Yeah, we the next year we have to turn this into a festival.\" So and that—that's kind of happening.","offset":2332,"duration":23},{"text":"Lea: So Freedom Tech Summit is a successor of these two events. It's uh, well, um, it's in the name of the event: it's about all about freedom tech. It's for hackers, it's for builders, it's for designers, anything in—anything in between. One topic that I haven't explicitly mentioned so far was mesh networks. So we also have this track directly focused on we call it resilience track, so any kind of like post-Apple tech that offline communications etc.","offset":2355,"duration":31},{"text":"Lea: That's—and it's basically one-day one-day event where uh all the best brains of the industry being that free communication or free money or free and sound money, uh, off-grid communication, philosophy connected to it, come together and have a lot of fun on workshops, panels, keynotes, anything in between. So everyone is welcome. Uh, we are we are already selling the tickets and accepting calls for proposal, uh, yeah, CFPs, yeah, calls for proposals. So if you go to freedomtechsummit.com, you can find more information about about it there.","offset":2386,"duration":41},{"text":"Matt Odell: I'll put a link in the show notes. I mean, we need more of this. I love it. I think the concept is great. I think the topics are more important than ever. Um, and by the way, freaks, this is—this is the day before BTC Prague in Prague. So you can make one trip. BTC Prague's like the larger, more mainstream event, but still got good Cypherpunk roots. And then this one is going to be a little bit more intimate, probably higher signal.","offset":2427,"duration":27},{"text":"Matt Odell: So you can make—you can make a trip out of it. I will say, um, I unfortunately cannot make it this year for personal reasons, good personal reasons, but Prague is awesome. It is a great city. The Czech Bitcoin community is fantastic. If you're American, it's a really good place to visit. It's—it's relatively cheap, the food's good, the drink's good, the people are good. Everyone speaks English. Absolutely everyone speaks English.","offset":2454,"duration":25},{"text":"Matt Odell: It's a good place for families. I just—I love Prague. Prague is one of my favorite European cities. So just consider it, guys. On the topic of mesh networks, uh, do you have a connection with any of the guys working on F_I_P_S? Are you aware of F_I_P_S?","offset":2479,"duration":20},{"text":"Lea: Yeah, Arjun and Jonathan both of them. Jonathan can't make it, unfortunately. Arjun, fingers crossed, yes, um, but it's not confirmed yet.","offset":2499,"duration":20},{"text":"Lea: Yeah. Yeah, yeah, yeah. Uh, hopefully Arjun will be—yeah, yeah, yeah. Uh, also but of course we are trying to to get more of like for example, when you're buying a ticket, you can you can get the the kit, the MeshCore kit, in the the e-shop, and uh, we will be we will have people flashing it for you, we will have workshops like dedicated to MeshCore uh and but other mesh networks as well, also.","offset":2519,"duration":24},{"text":"Matt Odell: I wasn't familiar with this MeshCore project. Is it similar to Meshtastic or?","offset":2543,"duration":33},{"text":"Matt Odell: I can't even get them on the podcast.","offset":2576,"duration":17},{"text":"Lea: Yeah. Yeah, yeah, yeah. I'm a big fan. I'm a big fan. I can't—I will be never able to tell them in person. Uh, but I love—I love that you guys are leaning into the mesh stuff. I think it's the missing piece. Uh, and it's been—we've just had so many false starts with mesh. It's like hype, uh, you know, for like the last 10 years I've just like, \"Oh, this is the moment. This is—it's gonna happen, now it's—it's about to happen.\"","offset":2593,"duration":29},{"text":"Matt Odell: Um, and to be honest, I feel that way still. But uh, hopefully it happens uh because you know, the internet is uh is way more centralized than people realize and our society depends on it more than ever. So we need we need these alternative these alternative communication networks.","offset":2622,"duration":24},{"text":"Lea: Yes, exactly. But my friend Juri Bednar, who is co-organizing the the event with us, he keeps telling me since January that this is the year of crypto-anarchy. So fingers crossed.","offset":2646,"duration":25},{"text":"Lea: It's like—I'm completely on board with Justin Moon here who said like, it feels like centuries can happen in five years. So that's exactly how it feels to me. It's unbelievable. I have only two poles, right? Like, either like we are doomed or like, \"Wow, we got the—\" and the second one is like, \"We got the fire of Prometheus—fire of gods. They gave us the fire of gods.\" And I'm oscillating in between these two constantly.","offset":2671,"duration":28},{"text":"Matt Odell: Yeah, I'm right there with you. Uh, I mean, so part of it is with all this stuff is—is it's a bit of a chicken and egg, right? Like you need the scale for them to be effective, but you need the tools to even get bootstrapped in the first place to ever dream of getting the scale. And I mean, I feel like there's a strong uh relationship here with you guys building out Vexl.","offset":2699,"duration":27},{"text":"Matt Odell: Just to get back to the main topic of the conversation, to the freaks listening, how can they be helpful in, you know, achieving this Vexl vision? Because I mean, you guys have found pretty good success. I think it's a very useful tool. Obviously the—like the big the big hold back is the network effect, right? Like if it's friends and friends of friends and you don't have people using it around you, then it's not as useful. So how do you think about how they can be helpful and how we make this thing uh a reality in a bigger way?","offset":2726,"duration":32},{"text":"Lea: So yeah, um, kickstarting a community like this is a pain in the ass. Um, and Odell just left, so—okay. So kickstarting a community like this is a major pain in the ass, but once you achieve a certain threshold, um, once you achieve a certain threshold then it grows exponentially, right? So uh, we are not uh present in the USA because it's a huge country that's far and we're a small team that doesn't have much money.","offset":2758,"duration":31},{"text":"Lea: But uh, good news is you don't need us to support you. We will, if you tell us what you need, we will manage and like for example the community in Namibia, they were like, \"Yeah, give us Namibian dollars, give us that, give us that,\" and we will we will proceed. But we cannot be there and we cannot be organizing meetups and we cannot be spreading the word.","offset":2789,"duration":23},{"text":"Lea: Right. But you can. And we've seen this as a huge success stories success story for example in Canada, where we had one one person that just fell in love with Vexl and started speaking about us on every meetup. And now, I don't want to bullshit you, but Canada might be like the fifth biggest market for us. So that's uh one thing that you can do. Like and we really literally had like zero presence there.","offset":2812,"duration":26},{"text":"Lea: We never like—like we did nothing in Canada. We haven't been in a conference, nothing. There was one person that understood the importance of peer-to-peer non-KYC Bitcoin and they wanted that for them and their community. So organizing meetups, speaking speaking about us, uh reaching out: if you need something from us, we are going to support you. Open an issue on GitHub, reach out to our support, GitHub live support. So speak to us. We are here to help.","offset":2838,"duration":31},{"text":"Lea: Second thing that you can do is uh, something I forgot. Okay, it'll come back to me. But the the community aspect is the most important one. As you said, uh there is the chicken of a chicken and a egg uh problem. And so the user, if they are not connected or they're isolated in the social graph, they don't see any offers.","offset":2869,"duration":25},{"text":"Lea: So I have what I wanted to say is you don't have to feel off or demotivated by the fact that you would have to onboard hundreds of people. So I just to illustrate on an example of like real-world story: imagine the community doesn't have to be big in order to be very active.","offset":2894,"duration":23},{"text":"Lea: So Botswana, for example, is one of our smallest communities again, we haven't we haven't spent any time building any kind of presence there because like we can't. We literally can't. But there must have been someone because um and that's like one of my most favorite stories from Vexl: like just one day I see this tweet from someone I've never heard of who is posting like, \"Yeah, I just bought pickles in Botswana for sats on Vexl.\"","offset":2917,"duration":30},{"text":"Matt Odell: That's awesome.","offset":2947,"duration":22},{"text":"Lea: And someone else who picked that offer. So don't be put off by the fact that we would have to go and be this like, you know, Vexl's witness going from door to door trying to onboard hundreds of users. So once it grows organically and like and it really spread by word of mouth. And the last thing, maybe motivation, you know?","offset":2969,"duration":25},{"text":"Lea: As I said, like a small network is enough. And there might be there might be another chicken and egg problem, so you have let's say like tens of people already on Vexl in your area, in your community, but everyone wants to be buying or everyone wants to be selling and depends. And then so I want to present you a opportunity.","offset":2994,"duration":24},{"text":"Lea: We have uh this is a this is a great opportunity for you to earn money. So what we see and how we actually scaled like how Vexl scaled in different markets, we would have these like agents of grey economy, the people who would be selling or buying with discount or fee and earning on the spread and basically providing liquidity to whatever side and earning like either sats or fiat or whatever how you decide decide to do it.","offset":3018,"duration":34},{"text":"Lea: Uh they would be hedging themselves on both sides and then basically earning money on providing the service. And now we like in the like more active network or the biggest ones here in Czech Republic for example, we can see these liquidity providers would be competing with each other. So they wouldn't be just because they are so many now.","offset":3052,"duration":17},{"text":"Matt Odell: Right.","offset":3069,"duration":17},{"text":"Lea: Exactly, like additional services. Yeah. \"I can come wherever you tell me to.\" So and these people are you don't need many of them. You need one effective one two to just like start serving these couple of users and everyone is happy, right? And these people are these liquidity providers are the blood of the marketplace, right? Without them just like so another like for the greedy ones or for the entrepreneurial ones, uh here is a great opportunity.","offset":3086,"duration":30},{"text":"Matt Odell: Greed is good. I—I mean, I love the meetup point. Uh, especially in the US. I mean, we have such a established meetup infrastructure. There are so many meetups. It's one of the most bullish fundamentals of American Bitcoin. And it seems like such a good fit for meetup organizers. So I—I mean, I will say personally, I mean obviously I co-founded Bitcoin Park in Nashville.","offset":3116,"duration":27},{"text":"Matt Odell: We can do a better job of it. So I'm gonna start thinking about how uh we can incorporate that into our programming. But there's a bunch of meetup organizers that listen to the show, so just consider it. I think it's a way to supercharge your community and make your community more resilient and help out everyone else at the same time. And I do agree with you, like it probably doesn't take that many people. You get like five to 10 people start to use it more actively, and then they get a couple people, and then they're onboarding their nanny, and their nanny instead of buying from Strike, they're buying on Vexl, and then all of a sudden you're scaling.","offset":3143,"duration":24},{"text":"Lea: Exactly. Um and also like it goes vice versa because we also have we currently have couple of ways how we can support the community. One is Vexl Club. We can speak about that for a bit later, but another one is uh um uh another one is like we the upcoming redesign of the app, there will be even more community features that we will be launching.","offset":3167,"duration":27},{"text":"Lea: I don't want to get into too much detail here, stay tuned. But it's already being developed.","offset":3194,"duration":28},{"text":"Lea: It's particularly for for example rural areas where people wouldn't be connected just by their phone numbers. We shift this uh reputation model onto the meetup organizer and they can distribute an invite code that would connect these people. So if you know someone who is going to your meetup, coming to your meetup, for five years, and you know they are trustworthy, you can invite them.","offset":3222,"duration":20},{"text":"Lea: Or like have moderators who would be inviting more people. And then you can see offers from your community from your meetup. Of course you know and you might have people in common or might not. And then you can again like distinguish and individualize that way the risk. Like, okay, am I going to Venmo the money or not? Um, am I going to meet for meeting in person? Am I going to reveal the identity, etc.?","offset":3242,"duration":24},{"text":"Matt Odell: I mean, that makes sense to me because the uh, I'll say at least for my experience as a meetup organizer, you know, they're Bitcoiners, so I don't really have most of their phone numbers. Like, that's not how we communicate. So if there's a separate way to—it makes sense to me that for convenience' sake phone numbers are the single best way to create social graphs.","offset":3266,"duration":23},{"text":"Matt Odell: That's why WhatsApp has been so successful for instance. But on meetups specifically, Bitcoin meetups, I mean we communicate on Signal, right? We communicate through I don't have most of their phone numbers. So if there's a way for like someone to put in a code that is I like—I don't know how you actually set it up. That's on you as the person build part of the team building the project.","offset":3289,"duration":23},{"text":"Matt Odell: But like if there's a way for them to put in \"Nashville Bitcoiners\" and then have offers that are from Nashville Bitcoiners, and maybe that looks like empowering the organizers to manage that community or something like that. Um, I think that would probably go a long way. It would make it a lot easier because right now if I'm thinking about it and we're saying, \"Oh, you should use Vexl,\" we also kind of have to like go around and like collect everyone's phone numbers uh because we just don't have that information right now.","offset":3312,"duration":24},{"text":"Lea: Yeah. Um, it was one of the motivations why we came up with the idea of Vexl Clubs. Uh so uh because no matter that Bitcoiners don't use phone numbers, the rest the rookies I was speaking about they do and it's the best underlying social network there is like there is there is—that is global, that scales, that works everywhere from the east to west, from the north to south.","offset":3336,"duration":24},{"text":"Matt Odell: I agree.","offset":3360,"duration":24},{"text":"Lea: So it always starts with the with the Bitcoin community itself. And that's why we want to empower them as much as possible. And when it comes to when it comes to your point about the organizer then managing the community, it's not the case here. Like you of course you have to be sane like who you you should not put the invitation code somewhere on Twitter, right?","offset":3384,"duration":28},{"text":"Lea: Right. Uh I wouldn't do it. You can, but it's kind of reckless. Uh so well.","offset":3412,"duration":28},{"text":"Matt Odell: Yeah.","offset":3440,"duration":33},{"text":"Lea: We don't know what is happening inside of the club. We don't know who the people joining are, if you are and how you're interacting, nothing like that. It's from that we can just like set up some parameters for you like let it be um number of seats, etc. And again, it works like like the we are not policing it in any way. The people seeing the offers are policing it.","offset":3473,"duration":25},{"text":"Lea: So if there are I guess like five offers within the club that are shadow-banned then the club gets deactivated because probably there is something fishy going on. But we don't know the we don't know the contents of the offer. We don't know identities of the people, nothing like that.","offset":3498,"duration":18},{"text":"Lea: Uh sorry?","offset":3516,"duration":24},{"text":"Matt Odell: To be clear, like as a meetup organizer, I don't want to know either. Like that's how it should be set up.","offset":3540,"duration":22},{"text":"Matt Odell: Okay. Email. Got it. Uh that's awesome. Uh I have a last question for you before we wrap. It's kind of random, but why Vexl? Why'd you come up why is it called that?","offset":3562,"duration":-2981},{"text":"Lea: I like okay. I thought you know the backstory because it's like really interesting.","offset":581,"duration":3030},{"text":"Lea: In Russia it's called \"fartsovka.\" In Romania it was \"bisnitzars.\" In Czech Republic it was \"vexclaks.\" And they were doing \"vexcl.\" So um and the reason how they they gained this name was that these people typically would be people who would be exchanging foreign goods, foreign like currencies, and often in parking lots close to German border. Because there was the border in between the the west and the east.","offset":3611,"duration":32},{"text":"Lea: It would be also happening on the main squares, etc. and would be like these people wearing like long coat or leather jacket and then they would approach you and be like, \"vexcl, vexcl, vexcl.\" And the reason is because it's from German word \"wechseln,\" which means \"to exchange.\" So they acquired it so they were basically saying \"wechseln, wechseln, wechseln\" but bit used it as \"vexcl.\" And these people started to be called \"vexclaks\" in slang, in Czech slang.","offset":3643,"duration":29},{"text":"Lea: So we are paying tribute to them.","offset":3672,"duration":28},{"text":"Lea: —of the dollar was. So they actually went to the vexclaks to ask like, \"Okay, so what how much is the—\" after the Soviet Union fell, um they were actually went to vexclaks to ask ask them like, \"Okay, so uh what's the real real price of dollar these days?\" So.","offset":3700,"duration":20},{"text":"Matt Odell: Is it just makes it real hard for uh governments to pretend their their shitcoin is worth a different amount uh because you just look at what how much is someone willing to trade Bitcoin for it. And if that if that's the amount then that's the real price of whatever their fiat is. Uh, we've seen it time and time again. I mean, I remember I'm not sure what the current state is over there, but for a while like the official Argentinian price uh of dollars to I guess Argentinian pesos—I think that's what they're called—was way off of the difference between Bitcoin to them. And then you could just use you could use that as the official price of it.","offset":3720,"duration":42},{"text":"Lea: Actually, if I have one KPI for Vexl that's uh our two I have two KPIs. One would be if we used \"to Vexl\" in the same way as we use \"to HODL\" for peer-to-peer trading like \"to Vexl it.\" I love it. Use it as a verb. That would be pretty cool. And second one if the price—and that's that's how I will know that we made it everywhere—if the price of Bitcoin, the real price, the street price, will be the one that is being traded on Vexl, you know? Not what the charts on Binance show you, but the street price on Vexl.","offset":3762,"duration":39},{"text":"Matt Odell: Yeah, well the P2P exchanges is what keeps the centralized exchanges at least relatively honest. They can't play too many games. Lea, this was uh this was a great conversation. I would love can we plan on like uh doing it again in a year maybe and see where we're at?","offset":3801,"duration":24},{"text":"Lea: Uh that we need one zillion unregulated little exchanges, um and every single one of us can act as one. Be that on Vexl or not. So don't send your friends to centralized exchanges. Some sell sell them some Bitcoin or buy from them and don't tell anyone.","offset":3825,"duration":29},{"text":"Matt Odell: Freaks, I hope you enjoyed this conversation as much as me. I have a great conversation lined up on Friday. The next conversation, it's going to be with the SimpleX founder, uh the encrypted chat app. I'm very excited for it. Um, it's an awesome app if you haven't used it. All the links we talked about today will be in the show notes, so check them out if you forget what links you need. And uh love you all. Stay humble, stack sats. Peace.","offset":3854,"duration":15}],"logs":[{"elapsed":"0.0","message":"Downloading podcast episode...","detail":null},{"elapsed":"13.9","message":"Episode downloaded (59.2 MB) in 13.9s","detail":"File size: 59.2 MB"},{"elapsed":"13.9","message":"Episode: CD195: VEXL - P2P NO KYC BITCOIN","detail":null},{"elapsed":"14.0","message":"Audio duration: 1:04:42 (64.7 min)","detail":null},{"elapsed":"14.0","message":"Uploading audio to Gemini File API...","detail":null},{"elapsed":"21.8","message":"Audio uploaded in 7.8s","detail":"File ref: files/7d37wnb8pqal"},{"elapsed":"21.8","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"129.1","message":"Transcription complete in 115.1s","detail":"60638 chars received"},{"elapsed":"129.1","message":"Transcription tokens: 97,296 in / 16,012 out — cost: $0.0967","detail":null},{"elapsed":"129.1","message":"Parsed 143 transcript segments","detail":null},{"elapsed":"129.1","message":"Transcript coverage: 1:04:14 of 1:04:42 (99%) — OK","detail":null},{"elapsed":"129.1","message":"Total transcription time: 115.1s — 143 segments","detail":null},{"elapsed":"129.1","message":"Analyzing topics across 143 segments with gemini-3.1-pro-preview...","detail":null},{"elapsed":"162.5","message":"Topic analysis complete in 33.4s — found 14 topics","detail":null},{"elapsed":"162.5","message":"Analysis tokens: 13,956 in / 1,066 out / 2,858 thinking — cost: $0.0750","detail":null},{"elapsed":"162.5","message":"Pipeline finished in 162.5s — total cost: $0.1717 (131,188 tokens)","detail":null}]} \ No newline at end of file diff --git a/history/1773695002747-hlOA8ObQJXo.json b/history/1773695002747-hlOA8ObQJXo.json new file mode 100644 index 0000000..af7c809 --- /dev/null +++ b/history/1773695002747-hlOA8ObQJXo.json @@ -0,0 +1 @@ +{"id":"1773695002747-hlOA8ObQJXo","videoId":"hlOA8ObQJXo","url":"https://www.youtube.com/watch?v=hlOA8ObQJXo","title":"Science-Based Meditation Tools to Improve Your Brain & Health | Dr. Richard Davidson","type":"youtube","topicCount":26,"segmentCount":331,"createdAt":"2026-03-16T21:03:22.747Z","uploadDate":"20260316","chunks":[{"title":"Introduction","summary":"Dr. Huberman introduces Dr. Richie Davidson, highlighting his pioneering research on the science of meditation, neuroplasticity, and the benefits of brief daily practices.","entries":[{"text":"Dr. Richie Davidson: We actually have really good data on this that at least for beginning meditators, if you do it for 30 days and you do it just for 5 minutes a day, you will see a significant reduction in symptoms of depression, symptoms of anxiety, and symptoms of stress. We've shown that repeatedly in randomized control trials. You'll see an increase on measures of well-being or flourishing, and we can talk about what those actually mean. You can even see, just with this amount of practice, a reduction in IL-6. IL-6 is a pro-inflammatory cytokine.","offset":0,"duration":39},{"text":"Huberman Lab Intro: Welcome to the Huberman Lab Podcast where we discuss science and science-based tools for everyday life.","offset":39,"duration":10},{"text":"Andrew Huberman: I'm Andrew Huberman, and I'm a professor of neurobiology and ophthalmology at Stanford School of Medicine. My guest today is Dr. Richie Davidson. Dr. Richie Davidson is a professor of psychology and psychiatry at the University of Wisconsin-Madison. He is a pioneer in the study of how meditation impacts the brain both during meditations, but also how it changes your brain over time, what we refer to as neuroplasticity.","offset":49,"duration":29},{"text":"Andrew Huberman: Today, we discuss the incredible health and neuroplasticity benefits that come from regular meditation, including very brief meditations of just five minutes per day. Dr. Davidson also dispels many common myths about meditation. For example, contrary to what most people believe, the point of meditation is not to clear your mind or to feel inner peace during the meditation, but rather to observe your thoughts and any stress you might experience during the meditation, and in doing so, it's kind of like the final hard repetitions of resistance exercise or the burn you might feel during cardio which comes from lactate. In that sense, the stress you feel during meditation and your ability to observe it acts as a sort of lactate of the mind that in turn makes you adapt, it makes you more stress-resilient, focused, and peaceful outside of the meditation.","offset":78,"duration":44},{"text":"Andrew Huberman: Dr. Davidson also explains how your brain changes during different types of meditation, such as open monitoring meditation, or eyes-open meditation, walking versus seated, and standing meditations and more. I've been doing meditation over many years, but this conversation with Dr. Richie Davidson changed my daily routine. Afterwards, I immediately started implementing a five-minute-per-day meditation of the sort that Dr. Davidson describes specifically for stress resilience, and I have to say it's had a profound impact on my levels of mental clarity, focus, and sleep, and in stress, just as he explained. In fact, it's proved to be one of the most beneficial practices I've taken on, especially on days when I wake up with tons to do, a little bit stressed or a lot stressed, and if I didn't sleep quite as well as I would have liked.","offset":122,"duration":47},{"text":"Andrew Huberman: So today, you're going to hear about the incredible science of meditation, the brain and bodily changes that occur, but also how you can rewire your brain using meditation. Dr. Richie Davidson is a true pioneer in this field, being one of the first to bring brain imaging and studies of mindfulness and meditation to the West. He has of course authored some of the most impactful research papers on these topics, but also popular books, including a new book coming out later this month entitled \"Born to Flourish: How to Thrive in a Challenging World,\" which I myself look forward to reading.","offset":169,"duration":33},{"text":"Andrew Huberman: Before we begin, I'd like to emphasize that this podcast is separate from my teaching and research roles at Stanford. It is, however, part of my desire and effort to bring zero-cost-to-consumer information about science and science-related tools to the general public. In keeping with that theme, today's episode does include sponsors.","offset":202,"duration":19},{"text":"Andrew Huberman: And now, for my discussion with Dr. Richie Davidson. Dr. Richie Davidson, welcome.","offset":221,"duration":11},{"text":"Dr. Richie Davidson: Thank you Andrew, I'm honored to be here.","offset":232,"duration":3}],"startTime":0},{"title":"Brain States, Traits & Neuroplasticity","summary":"The discussion covers how recurring brain states lead to altered baseline traits over time, along with an overview of delta, theta, alpha, beta, and gamma brainwaves.","entries":[{"text":"Andrew Huberman: Oh, it's an honor to have you here. I am a long-time fan of your research, of what you've built at the University of Wisconsin-Madison, the books you've written - we'll talk about your new book, I didn't even know you had a new book, this wasn't a book tour invite, I had seen you give a seminar at Stanford and I said great, here's my opportunity to finally get you on the podcast. But you really transformed the way that I think about not just meditation, but all states of mind and how that relates to our individual traits and how those can change over time. Today we'll talk about concept and protocols. But I'm curious how you think about states of mind generally. I think it's really important that we frame the discussion with this because we all know what sleep is, most people have heard that sleep has different components, REM sleep etc. We know what it is to be awake, stressed versus calm. But how should we think about states of mind and then once you tell us how you think about that, perhaps then we can better place this thing we call meditation into a particular bin.","offset":235,"duration":52},{"text":"Dr. Richie Davidson: So thank you first for having me Andrew, and I've just want to say I've been a long-term fan of yours so I'm really happy to be here. In terms of states of mind, I think that at the outset it's really important that we also remind listeners that there's a thing called traits too, and so we can't talk about states without also talking about traits, and we'll get to traits in a moment. But I think with regard to states, we can think of them as organized patterns of activity in the brain that have corresponding organized mental correlates if you will, or subjective correlates.","offset":287,"duration":46},{"text":"Dr. Richie Davidson: And there are certain states that occur with regularity that are part of our biological rhythms, and so most human beings will have states of wakefulness, of deep sleep, and of REM sleep every day. And that is regulated by well-known kinds of biological rhythms. And then there are other kinds of states that are sometimes described that are states during what we normally think of as waking, although I think honestly the concept of state is often used loosely without rigorous boundary criteria for what constitutes a state and how it might be distinguished from another state.","offset":333,"duration":54},{"text":"Dr. Richie Davidson: There are certain states which if they occur with regularity will lead to a trait. They'll lead to a shift in the baseline for the next state. There was a paper I wrote many, many years ago with my dear friend and colleague Daniel Goleman who I wrote the book Altered Traits with, and the origin of Altered Traits is really in a sentence that we wrote in a paper 20 years earlier where we said: the after is the before for the next during.","offset":387,"duration":34},{"text":"Andrew Huberman: The after is the before for the next during. Let's drill into that for a second.","offset":421,"duration":4},{"text":"Dr. Richie Davidson: Yeah, so what we mean by that is that how you are after a state, say you do a little meditation practice and it leads to a state change, that state change may persist in some way and that becomes the next before for the next during, the during is the state, is the say the meditation state. And so it's a description of how a state can lead to a trait. In the domain of emotion, you might think that frequent bouts of anger, which you can think of as a state, can lead to the trait of irritability, which is sort of chronically having a low threshold. You can think of a trait in certain cases as altering the threshold for the elicitation of a state. So a trait of irritability would be a trait where you have a lowered threshold for the elicitation of anger, for example.","offset":425,"duration":64},{"text":"Andrew Huberman: Yeah, I love that example because I know that many people will resonate with it because so much of what we see online nowadays is designed to capture our attention by engaging negative affect - mild anger, frustration, or even outrage. There's other content online too of course, and this podcast is online after all. And many other sources of what I consider benevolent educational information. But it is so true that, you know, what we experience in one portion of our day impacts how we are in the rest of our day. And perhaps the simplest correlate for all of it for me anyway is sleep. You know, if I sleep really well for three or four nights in a row, I wake up in a certain state that certainly makes my day go differently. And the inverse is also true if I don't sleep well. I feel like we have such great nomenclature and understanding of brain activity and how that impacts emotionality for sleep. We know that REM sleep based dreams are very vivid, slow wave sleep based dreams are less vivid perhaps. We know the electrical activities associated with those different states of sleep. I'm aware of a lot less information about brain activities and clear definitions of waking states of mind. Do you mind if we talk about this for a little bit? It's been a few years since I've heard about and I don't think we've ever really talked on this podcast about, you know, alpha waves, beta waves, theta waves. Maybe just educate us a bit on some of the waking brain states that we've all experienced, perhaps are in right now, but that we just don't hear about that much anymore.","offset":489,"duration":104},{"text":"Dr. Richie Davidson: So yeah, we can talk about those oscillations of brain electrical activity, and there are broad suggestions for what kind of state they may reflect, and you know, I'll go through that, but it's also important to recognize that you can be showing alpha activity in one part of the brain and beta activity in another part of the brain simultaneously. And so it's a bit coarse to talk about these as general characteristics, but there could be times when we see predominantly one oscillation or another and so talking about generalized states in that context may be more reasonable.","offset":593,"duration":45},{"text":"Dr. Richie Davidson: So with that as a caveat, let me say that in humans we see a broad range of frequencies that go from approximately 1 Hz (one cycle per second) to approximately 40 Hz. And from roughly 1 to 4 Hz is delta activity, that is typically not seen during waking, it's predominant during deep sleep. And there is data that suggests that the density of delta activity or slow wave activity during deep sleep is actually diagnostic of how restorative that sleep is, which is a whole separate set of issues and super cool.","offset":638,"duration":41},{"text":"Dr. Richie Davidson: And there are actually some really interesting highly novel strategies now using neurostimulation to actually boost slow wave activity during deep sleep which may actually help to potentiate some of the skill acquisition that we do during the day, including meditation. And we're doing some of that work now, which is actually you had asked earlier before we started about some novel new work that we're doing and that's also one of the really cool new things. So we can dive into that.","offset":679,"duration":36}],"startTime":235},{"title":"Sponsors: David Protein & Eight Sleep","summary":"Brief sponsor ad reads for David Protein bars and Eight Sleep mattress covers.","entries":[{"text":"Andrew Huberman: I'd like to take a quick break to acknowledge one of our sponsors, David. David makes protein bars unlike any other. Their newest bar, the Bronze Bar, has 20 grams of protein, only 150 calories, and zero grams of sugar. I have to say these are the best tasting protein bars I've ever had, and I've tried a lot of protein bars over the years. These new David bars have a marshmallow base and they're covered in chocolate coating and they're absolutely incredible. I of course eat regular whole foods - I eat meat, chicken, fish, eggs, fruits, vegetables, etc. But I also make it a point to eat one or two David bars per day as a snack, which makes it easy to hit my protein goal of one gram of protein per pound of body weight, and that allows me to take in the protein I need without consuming excess calories. I love all the David Bronze Bar flavors, including cookie dough, caramel chocolate, double chocolate, peanut butter chocolate, they all actually taste like candy bars. Again, they're amazing, but again they have no sugar and they have 20 grams of protein with just 150 calories. If you'd like to try David, you can go to davidprotein.com/huberman. Right now David is offering a deal where if you buy four cartons, you get the fifth carton for free. You can also find David on Amazon or in stores such as Target, Walmart, and Kroger. Again, to get the fifth carton for free, go to davidprotein.com/huberman.","offset":715,"duration":79},{"text":"Andrew Huberman: Today's episode is also brought to us by Eight Sleep. Eight Sleep makes smart mattress covers with cooling, heating, and sleep tracking capacity. One of the best ways to ensure you get a great night's sleep is to make sure that the temperature of your sleeping environment is correct. And that's because in order to fall asleep and stay deeply asleep, your body temperature actually has to drop by about one to three degrees. And in order to wake up feeling refreshed and energized, your body temperature actually has to increase by about one to three degrees. Eight Sleep automatically regulates the temperature of your bed throughout the night according to your unique needs. I've been sleeping on an Eight Sleep mattress cover for nearly five years now and it has completely transformed and improved the quality of my sleep. The latest Eight Sleep model is the Pod 5. This is what I'm now sleeping on and I absolutely love it. It has so many incredible features. For instance, the Pod 5 has a feature called Autopilot, which is an AI engine that learns your sleep patterns and then adjusts the temperature of your sleeping environment across different sleep stages. It'll even elevate your head if you're snoring and it makes other shifts to optimize your sleep. If you'd like to try Eight Sleep, go to eightsleep.com/huberman to get up to $350 off the new Pod 5. Eight Sleep ships to many countries worldwide, including Mexico and the UAE. Again, that's eightsleep.com/huberman to save up to $350.","offset":794,"duration":76}],"startTime":715},{"title":"Sleep Needs & When to Meditate","summary":"Exploring individual sleep needs, the Dalai Lama's sleep habits, and the optimal time of day to practice meditation to avoid sleepiness.","entries":[{"text":"Andrew Huberman: I saw a paper recently that described a, and forgive me if this was one of your papers, I don't think it was, it described a pre-sleep meditation that one could do to significantly increase the amount of growth hormone that's released once one gets to sleep. And I thought, [Dr. Richie Davidson: That wasn't ours] and I thought this makes total sense, right? I mean it's it has to do with, I forget the sentence you wrote, but that how we exit one state impacts how we encounter the next one and perhaps even our trait within that next event of life. So we'll definitely get back to this when we talk about protocols because I think that people vastly underestimate the extent to which different let's call them meditations, for lack of a better word right now, how they can impact how we show up to work, how we show up to relating, how we show up even to sleep. And it's not just about being calm so you can fall asleep. Turns out this meditation that was described boosts growth hormone in a, you know, incredible way without altering some of the other features of sleep.","offset":870,"duration":71},{"text":"Dr. Richie Davidson: I saw that paper too, it wasn't ours, but yeah, super interesting. I agree. Yeah, so just to continue with the brain oscillations, I talked about delta. The next brain, the next faster brain rhythm is theta activity, which is roughly between 5 and 7 Hz. Theta activity is often seen during transition from wakefulness to sleep. And it's associated with these, as you were saying earlier, these liminal states. It's also been associated with certain kinds of meditation. Alpha activity is roughly between 8 and 13 cycles per second or Hz, and it's often characterized as quote relaxed wakefulness. Beta activity is typically defined as roughly 13 to roughly 20 Hz, and it's associated with activation. If there is a cognitive task that a person is engaged in, you will typically see increases in beta activity, particularly in the cortical regions that are engaged in those cognitive tasks. And then finally there's gamma activity. Gamma activity is especially interesting, we see that in meditators, long-term meditators. Gamma activity has as its peak frequency roughly 40 Hz. It is seen in a number of contexts. One of them is during what some have called insight. And insight is where I think most viewers have had the experience of working on a problem and all of a sudden they just have an aha moment and things sort of gel, they congeal, they come together. And there've been some clever experimental designs where investigators have created tasks that increase the likelihood of aha moments. They're sort of trivial in the experimental context, they're simple cognitive tasks where all of a sudden you just recognize the answer. It might be something like a crossword puzzle, and you're trying to get something, a word to fit, and suddenly you get the word. It comes in a moment and it's kind of an instantaneous recognition. And you typically would see a burst of gamma oscillations that is very short - the average duration would be around 250 milliseconds, really short. What we see in these long-term meditators is the prevalence of high amplitude gamma activity that goes on for seconds and minutes. When we first saw that by the way, and there's a lot of interesting history here, but we first reported this in 2004 with very long-term meditators where the average lifetime practice of this group was 34,000 hours. Listeners can do the arithmetic later, but 34,000 hours is a big number. And in these practitioners we saw these really high amplitude gamma oscillations that actually were visible to the naked eye, which is unusual for this kind of measurement. And in the original paper which was published in PNAS in 2004, we actually had a figure of the raw EEG from one practitioner just to illustrate how prominent it is that you can see it with the naked eye. And we've subsequently replicated that, it's been replicated by others. We've also seen that this gamma activity is found during slow wave sleep. It's actually superimposed on delta oscillations.","offset":941,"duration":225},{"text":"Andrew Huberman: Is there any evidence that meditation can actually replace sleep or that it can offset some of the negative effects of sleep deprivation, mild sleep deprivation?","offset":1166,"duration":9},{"text":"Dr. Richie Davidson: This is a great question. I think about it a lot. I don't think that the evidence is is clear on this at all. And I'll give several examples. First, the Dalai Lama, who probably meditates more than anybody I know, he has a practice of literally doing approximately four hours of meditation every day and he's been doing that for more than 60 years.","offset":1175,"duration":23},{"text":"Andrew Huberman: I'm reassured by that. If you told me the Dalai Lama meditates for, you know, 40 minutes a week, I'd actually be concerned about the role of Dalai Lama, so that the title, you know.","offset":1198,"duration":10},{"text":"Dr. Richie Davidson: So that, and he very proudly says, \"I sleep nine hours a night.\" Wow, okay. Nine hours a night and he gets nine hours of sleep, that's his regular sleep, and he gets it all the time. And you know, I don't know whether he would say he needs it, but he gets nine hours a night, and he's very proud of that. Okay. That's one counter-example. You know, myself, I have done a bunch of sleep science with collaborating with some sleep researchers, and many years ago one of these people said to me, \"Richie, you really should give up an alarm clock, just don't use an alarm clock anymore.\" And I was getting at that time between five and a half and six hours a night of sleep, and I gave up the alarm clock and my average length of sleep increased by about 30 to 45 minutes. And I feel much better. Oh sure. Especially since the extra sleep tends to be toward morning, you're getting more REM sleep. But the difference for me between five and a half and six or six and a half is in terms of just subjective well-being and focus, etc. is tremendous.","offset":1208,"duration":71},{"text":"Andrew Huberman: Slightly related question: if one were going to choose to meditate and had the option to do it at a sort of liminal state between let's say being awake and going to sleep at night or between sleep and what shortly after one wakes up and starts the day versus in the middle of the day or in the middle of the morning, is there any advantage to placing meditation in one of these what I'm calling liminal states or transition states between sleeping and awaking in either direction?","offset":1279,"duration":30},{"text":"Dr. Richie Davidson: I would say probably for most people yes is the answer, but I think there's a lot of individual variability. In general, I would say it's useful to meditate when you're feeling most awake and less sleepy. Sleepiness is an important obstacle in meditation and there's a lot to say about that.","offset":1309,"duration":23},{"text":"Andrew Huberman: Yeah, I'm surprised to hear that. I expected you to say that one should meditate at a time when the brain is closest to sleep because you want to be in a state of mind that's less about controlling your thoughts. But then again, I could also see an argument for how meditation involves a redirect of attention. So let's actually drill into this a bit. What is the meditative state that one is seeking for quote-unquote effective meditation?","offset":1332,"duration":26}],"startTime":870},{"title":"Meditation Types & The State of Being","summary":"Dr. Davidson breaks down focused attention versus open monitoring meditation, and the value of shifting from a mode of \"doing\" to a mode of simply \"being.\"","entries":[{"text":"Dr. Richie Davidson: Yeah, so first let me say that just like there are hundreds of different kinds of sports, there are hundreds of different kinds of meditation. They don't all do the same thing, they have different effects on the brain and the body. And so I think it's really important that we not lump all of meditation together. So that's one really important thing.","offset":1358,"duration":25},{"text":"Andrew Huberman: Can we divide it up? So for instance, if we were going to draw the parallel with exercise, and maybe we'll do that several times today. We can broadly lump exercise into cardiovascular and resistance training. There's also mobility work and then there's a bunch of other stuff. With meditation can we create some broad bins? And what are those broad bins? And then we can go into specific practices.","offset":1383,"duration":25},{"text":"Dr. Richie Davidson: Yeah, so yes, we can create some broad bins. So and we've done that, we've published some papers that offer typologies for classifying different meditation states. So one kind of meditation we call focused attention meditation. And focused attention meditation is where you are narrowing your aperture of awareness to a specific object. It could be an external object, it could also be an internal, it could be for example your respiration, it could be a sound. And there is a narrowing of the aperture. And this is all broadly within the category of practices that we would say are cultivating aspects of awareness. So another awareness practice is what we call open monitoring meditation. And open monitoring is where there is no specific focus but rather the aperture is broadened. And there is no specific intention to focus on any one thing or another. The invitation is to simply be aware of whatever is arising as it arises. One of the aspirations there or the invitations is not to try to get rid of thoughts because our minds and our brains are built to generate thoughts. So there's no goal if you will to get rid of thoughts, but rather to if thoughts arise, that's another object that you can be aware of. You know, we talked about sleep and sleepiness and that earlier, you can even, you can be aware of being sleepy, you can be aware of being distracted. The goal if you will is not to change or to fix anything. If you will, the invitation is to shift from a mode of doing to a mode of simply being.","offset":1408,"duration":116},{"text":"Andrew Huberman: I want to talk about this thing about doing to being because the language can sound a bit mystical and vague to people. But as a long-time practitioner of Yoga Nidra, which I've talked a lot about on this podcast, there's this instruction inside of Yoga Nidra to shift from thinking and doing to being and feeling. [Dr. Richie Davidson: Exactly.] Which is beautiful language, poetic, etc. but also as neuroscientists and for the general public, I think it might be useful for us to just maybe just double click on that for one second. As a neuroscientist I think of thinking and doing as okay, doing is action, so that would the opposite of that would be stop moving the body. Thinking - well, there's a whole discussion to be had about what is thinking in neuroscience - but certainly you wouldn't want to plan, you wouldn't want to be ruminating on the past. Presumably you would want to be more in a state of sensation and perceiving what's happening right now. So is that an appropriate breakdown or is it wrong, is it insufficient? I'm not trying to score an A with the professor here, I'm just trying to figure out when we hear \"move from thinking and doing to being and feeling,\" what does that mean in terms of actionable steps that people can take?","offset":1524,"duration":86},{"text":"Dr. Richie Davidson: Yeah, so I think that the way you describe it is basically accurate with a little bit of perhaps tweak. So if when if one is invited to do this and one finds oneself ruminating or planning for example, which is supposedly an activity you're quote not supposed to be doing, you know, rather than trying to stop it, it's simply to be aware of it. Wow, I'm now planning or I'm now ruminating about something that happened in the past. What really is most important is the invitation not to change it, not to actively try to shift it, but to simply be aware. And one of the conjectures in all of this is that there's so much going on under the hood that we're typically not aware of. You know, our lives are moving at such a pace that the information that is transpiring is occurring at such a rapid rate that we are typically aware of only a small fraction of that. And this is a practice that's inviting you to simply be aware of that and and and you know, not doing is a helpful kind of thing because if we're if we're acting in the world, we obviously need to navigate and there are things we obviously need to do to be safe and to protect ourselves and so forth. And so that will engage other mechanisms.","offset":1610,"duration":101},{"text":"Andrew Huberman: I'm interested in the possibility, or maybe you've seen this in the data, that there are at least two different types of people. People who for instance go through life feeling, doing, being, thinking and projecting things out into the world, or maybe they're quiet people and they don't project much out into the world but they're just doing their thing and they're not thinking about their thinking. They're not thinking about their doing, they're just doing. We know people like that. Then there are people who are always multi-tracking, like uh, you know, they're self-conscious, they're very self-aware. And I'm wondering whether or not a form of meditation where somebody arrives at the meditation very self-aware, like oh, there's my thought about that again, there's my thought about that again, and working perhaps on not judging it, could be beneficial. But perhaps what that person quote-unquote needs or would benefit from was just being in a state of a freedom from their self-monitoring, whereas the other person perhaps could afford to be a little more self-aware and realize, oh, you know, I'm in this mode where and see their thinking a little bit.","offset":1711,"duration":72},{"text":"Dr. Richie Davidson: Totally, and and you're naming something super important. And you know, I think that the way you characterize the second person who is more self-aware, there's more than just self-awareness in your description. There's a kind of holding back. It's not just monitoring, but there's a kind of suppression almost. It's a lot of work. [Dr. Richie Davidson: It's a lot of work.] And it kind of and it could be stifling for their creativity. Absolutely. We had my friend David Choe on the podcast, now we're friends, that was actually the first time we had met but we've become good friends and he's a brilliant artist, brilliant artist. And he talks about how the best art comes from just forgetting what anyone thinks or wants. Rick Rubin talks about this, just getting the audience out of your mind and just letting it flow through you. And I think great artists do that. And it's what we pay money to see. We want to see that form of expression. We don't want to see the self-monitoring artist. [Dr. Richie Davidson: Yeah.] That's great. And I totally resonate with that. And there is a phrase in the Tibetan Buddhist tradition that is called \"undistracted non-meditation.\" Undistracted non-meditation. And that's said to be the highest form of meditation, where you just drop all the crap, you know, all the techniques, all the control, all the tightness.","offset":1783,"duration":95},{"text":"Andrew Huberman: This is my goal in life. Watch out folks, if this ever happens.","offset":1878,"duration":4},{"text":"Dr. Richie Davidson: But you're totally aware. You're fully aware. But there's no artifice, there's no uh, it's just complete freedom. And and there are, you know, I think there I've had the the honor of just hanging out with some people who I think are really in that as a trait. That's who they are. Rick Rubin's like that. He's a close friend and I can tell you I've spent a lot of time with Rick. And how he appears to people and his kind of mythical status, I think a lot of people his magnetism is because that's real. He can be in very, very close proximity to things, online, in person, he can see all of it. He's in real touch with it, but he's still him. It somehow it doesn't invade him in a way that changes the way he shows up. He, you know, like if if we were to paint little beams of energy - now we're really sounding woo - coming out, there's stuff coming out, there's stuff going in and they're interacting, but they're not contaminating one another. Where they interact it just makes both things better. And that's a very, very rare trait.","offset":1882,"duration":74},{"text":"Dr. Richie Davidson: Yeah, I agree. You know, there's a term that I often use which, you know, I can talk about how we can define this more technically, but for lack of a better word, I call stickiness. And it's kind of an affective hysteresis, if you will. It's where you know, you're hanging on to emotions that may not be useful. You're carrying stuff from a previous experience into a current experience and it muddles things. And you know, our emotional lives are so infused with this kind of stickiness, but with like with Rick Rubin, or with other people who are showing this, there's no stickiness. There's no stickiness. And you know, that's a kind of of freedom that I think is very much what we're talking about as the trait manifestation of these kinds of practices.","offset":1956,"duration":64},{"text":"Andrew Huberman: It's interesting. I think a lot of people mistakenly use drugs to try and access that state. And I also think that we have a real as a species, as a culture but also as a species, we have a real affinity to people who can embody this freedom that you're talking about. Great comedians - like when Richard Pryor was on, you're just like, I mean you maybe he had a subscript in there, maybe he was devoting like 2% of his prefrontal cortex to monitoring but it just seemed like we call it flow, but we're in their flow, they're in ours, whatever it is. There's a powerful interaction there that there seems to be very little self-monitoring from the perspective of performing arts or comedic arts.","offset":2020,"duration":53},{"text":"Andrew Huberman: But for people who want to approach meditation, would it do you think it's useful at all to ask themselves before they go into the meditation, you know, are they in a are they in a mode of self-monitoring or are they in a kind of or are they feeling more free? More present to just whatever it is they're experiencing not questioning it. [Dr. Richie Davidson: Yeah.] And asking them for do you think it's useful in order to get the most out of a meditation practice? I guess what I'm getting at indirectly here is most meditation practices involve shifting from doing one thing to maybe you're walking, maybe you're open eyes, but typically I think people either sit or lie down, close eyes and start focusing on their breathing and trying to quote-unquote get present. [Dr. Richie Davidson: Although the kind of practice that I most often do is actually with eyes open.] Really? Oh, well then just tell us about that. What what would be a good uh, let's use the parallel to cardio again. I would say if somebody's really out of shape and wants to get in shape, I would say the first thing is take two 20-minute walks a day. And then we could talk about getting on a exercise bike and then maybe doing some resistance you start layering things in, right? But what would be the equivalent of the 2 20-minute walks a day for meditation?","offset":2073,"duration":81}],"startTime":1358},{"title":"The 5-Minute Daily Meditation Protocol","summary":"Outlining a foundational meditation practice of just five minutes a day and its significant benefits for reducing stress, anxiety, and inflammation.","entries":[{"text":"Dr. Richie Davidson: So this is the protocol question I guess. You know, I would say it's really important to start modestly and we often will ask a person, what's the minimum amount of meditation that you think you can commit to every single day and do it for 30 days consistently? [Andrew Huberman: 5 minutes.] Perfect. Whatever that number is, perfect. Start with that. And then the next question is, are you comfortable doing it formally as a seated practice or would you prefer to do it while you're walking or while you're doing another non-cognitively demanding activity? It could be commuting, it could be washing the dishes. There are lots of those kind of activities that we often do on a daily basis that you can actually intentionally use your mind in this way while you're also doing those activities. And by the way, we've shown - we actually have really good data on this - that at least for beginning meditators, it doesn't matter if you're doing it as a formal meditation practice or as an active practice. The benefits are absolutely comparable.","offset":2154,"duration":76},{"text":"Andrew Huberman: And what are those benefits?","offset":2230,"duration":2},{"text":"Dr. Richie Davidson: So if you do it for 30 days and you do it just for 5 minutes a day, you will see a significant reduction in symptoms of depression, symptoms of anxiety, and symptoms of stress. We've shown that repeatedly in randomized control trials. You'll see an increase on measures of well-being or flourishing, and we can talk about what those actually mean. You can even see, just with this amount of practice, a reduction in IL-6. IL-6 is a pro-inflammatory cytokine that is important in systemic inflammation. And with just this minimal amount of practice you see a significant reduction in IL-6 over the course of 28 days, five minutes a day. We've actually seen changes in the microbiome. And we've seen changes in the brain with just this minimal amount of practice. But the important point is that you're doing it every day. When people ask me what's the best form of meditation that they should do if they're just beginning, I say the best form of meditation that you can possibly do is the form of meditation that you actually do. So figure out what that form of meditation is and then stick to it. Do it every single day.","offset":2232,"duration":81},{"text":"Andrew Huberman: I love this. I actually am going to challenge our podcast audience to five minutes a day for 30 days. I'll put something out on social media. Rob, please remind me to put something out on social media to do five minutes a day for 30 days because what you describe are significant health effects. And as you described them, it made me remember this set of experiments from neuroplasticity. Do you mind if I share these? Because I have a this is a theoretical/practical question as we move into these protocols. But before we do that, what what should we call this protocol? It's the Richie Davidson five minutes a day. Richie's five meditation. I'm going to start that. Later I'll share what I've been doing but it's not even that. I've been doing 10 breaths upon waking. Ten breaths before I even get out of bed. I'm like if I can just do 10 breaths of focused meditation before I get out of bed, the whole day will go better and it and it tends to.","offset":2313,"duration":68},{"text":"Andrew Huberman: There's this wild set of findings in the neuroplasticity research that most people don't talk about because it's very inconvenient for neuroscientists. We're all familiar with the enriched environment thing where you give rats a bunch of toys or mice a bunch of toys or monkeys a bunch of toys, and the idea would be if you give kids a bunch of toys or listening to Mozart that their brains will develop more. You see more physical connections, you see improved cognition, etc. etc. A really smart guy down at University of California, Irvine, Ron Frostig, did an experiment where he said, \"Maybe this is all backwards. Maybe the normal cages they live in without all these toys are just deprived environments.\" And it turns out that's probably the case. So all this enriched environment stuff, it's not that it's BS, it's just that the experimental conditions were so deprived that what you had was most animals just deprived in a certain way, then you give them what they needed naturally and all of a sudden you saw more connections etc.","offset":2381,"duration":70},{"text":"Andrew Huberman: If we applied that to meditation - something that we think of as kind of an enriched mental environment - okay, I'm going to now do this exercise, I'm going to do five minutes a day or 10 or 20. We think of it as kind of adding exercise, but riding a treadmill, doing resistance training, I mean we used to just farm and go get water and do things. So in some sense all of that is a replacement for a quote-unquote deprived environment. So is it possible that what you're describing is not something that people developed over time, but rather something that was core to our experience as humans and that the brain needed, but that with the advent of technologies and busyness or whatever we've gotten away from? And so when you talk about doing 5 or 10 or 20 minutes of meditation a day and seeing all these health effects, what we're doing is we're actually just putting back what needed to be there in the first place. This is like the equivalent of you getting your 30 minutes more sleep because alarm clocks weren't really a thing 2,000 years ago. Does that make sense?","offset":2451,"duration":69},{"text":"Dr. Richie Davidson: It makes sense, but you know, and I think that there's an element of truth to it, but I also think that there's some additional discussion that we should have about it and dialogue. So first of all, these practices have been around for, you know, 2,500 years or more. It's not like they've been invented in the modern era to deal with the the separation that has occurred between humans and the natural world that is a distinctly modern kind of invention. So that's one thing. The second thing is that yes, I agree with you that the characteristics that we're talking about as traits that are outcomes of these practices, there many ways to get there. And there are probably natural ways to get there that don't require meditation. And in fact, you know, when we in our early days we interviewed these practitioners around Dharamsala, India who were spending 30 years in retreat. They're called hermit monks. And you know, there you have to hike for three hours to find their cave. And we interviewed these these people. You know, they they told us, \"Well, you know, I need to meditate, but many others are just born or they're just naturally have these qualities. They don't need to meditate as much as me. I'm just a simple, you know, poor monk who really needs to do this because I'm inferior to those people,\" if you will.","offset":2520,"duration":90},{"text":"Dr. Richie Davidson: And it's a kind of modesty but also, you know, there may be some truth to that. And so I think that that is is real. But I also think that the qualities like for example, kindness. I believe, and this is the subject of this new book that I wrote with my colleague Cortland Dahl, \"Born to Flourish,\" qualities like kindness are innate. They are part of our innate repertoire. But in order for them to be expressed, they require nurturing. And it's very similar to the way scientists talk about language. Language is innate, I think most scientists would agree with that, but we know that there have been case studies for example of feral children who are raised in the wild and they don't develop normal language. So in order for the language to develop normally it requires nurturing of some kind. And kindness is the same thing, it requires nurturing in order for it to be expressed. And similarly for other qualities that we're cultivating when we meditate. I think those qualities are innate, but they require nurturing. And and in certain cases, I think that in order for those qualities to really be expressed at high levels if you will, intentional nurturing may be required for at least the vast majority of people. There may be, you know, statistically very rare people who emerge who are like this from the start for whatever reasons.","offset":2610,"duration":90},{"text":"Dr. Richard Davidson: reason. But for most of us, I think uh this kind of nurturing is important.","offset":2700,"duration":8}],"startTime":2154},{"title":"Sponsor: AG1","summary":"Brief sponsor ad read for the AG1 nutritional supplement.","entries":[{"text":"Andrew Huberman: As many of you know, I've been taking AG1 for nearly 15 years now. I discovered it way back in 2012, long before I ever had a podcast, and I've been taking it every day since. The reason I started taking it, and the reason I still take it, is because AG1 is, to my knowledge, the highest quality and most comprehensive of the foundational nutritional supplements on the market.","offset":2708,"duration":22},{"text":"Andrew Huberman: It combines vitamins, minerals, prebiotics, probiotics, and adaptogens into a single scoop that's easy to drink and it tastes great. It's designed to support things like gut health, immune health, and overall energy, and it does so by helping to fill any gaps you might have in your daily nutrition. Now, of course, everyone should strive to eat nutritious whole foods. I certainly do that every day.","offset":2730,"duration":21},{"text":"Andrew Huberman: But I'm often asked if you could take just one supplement, what would that supplement be? And my answer is always AG1, because it has just been oh-so-critical to supporting all aspects of my physical health, mental health, and performance. I know this from my own experience with AG1, and I continually hear this from other people who use AG1 daily. If you would like to try AG1, you can go to drinkag1.com/huberman to get a special offer.","offset":2751,"duration":26},{"text":"Andrew Huberman: For a limited time, AG1 is giving away six free travel packs of AG1 and a bottle of Vitamin D3K2 with your subscription. Again, that's drinkag1 with the numeral one dot com slash huberman to get six free travel packs and a bottle of Vitamin D3K2 with your subscription.","offset":2777,"duration":22}],"startTime":2708},{"title":"The 'Lactate' of the Mind","summary":"Discussing why sitting alone with our thoughts is difficult and how the initial anxiety of meditation acts like the beneficial \"burn\" of physical exercise.","entries":[{"text":"Andrew Huberman: Why do you think it is that so many people find it challenging to maintain a meditation practice? I mean, 5 minutes a day is nothing. 10 minutes a day is barely anything even for the very busiest of person. And the positive effects that you describe—and we could also layer in reduced stress, anxiety, lower resting heart rate, uh increase uh you know, um feelings of well-being and on and on—I mean, there there are just so many great studies now, including, like you said, you know, double-blind trials. I mean, it's it's incredible.","offset":2799,"duration":39},{"text":"Andrew Huberman: Um, so why do you think it's so hard for people to maintain this practice of just saying, \"Okay, you know what, I'm going to just go into this atypical state. It's it's not being stimulated by anything in my environment. I have to do this internally. There aren't gyms to go to for this.\" although, I mean there are breathwork classes and things like that, but people don't tend to stick to it. That's the challenge.","offset":2838,"duration":26},{"text":"Dr. Richard Davidson: Yeah, so I do have a theory about it, which I'll share. But before I do that, let me just say that uh I often use the analogy of brushing your teeth. When when humans first evolved on this planet, none of us were brushing our teeth. And somehow, a very large swath of humanity has learned to brush their teeth every day. It's not part of our genome.","offset":2864,"duration":26},{"text":"Andrew Huberman: I think most people brush their teeth so that their breath isn't bad. I think they like the idea that their teeth look cleaner and they get less um gum disease, et cetera. But all the scary stuff is actually very uh ineffective public health messaging. I mean, that's my guess.","offset":2890,"duration":23},{"text":"Dr. Richard Davidson: Yeah, so actually that's quite interesting, um that that view. But getting back to your question, why do people find it so hard? So there was a study published in *Science* not too long ago by a group of social psychologists. And um it was a study of, quote, boredom. Um and what they did essentially in this study, the core of it was they took people into the lab and they said, um \"We had a little problem and you guys are going to have to wait for like 15 or 20 minutes before the experiment starts while we fix some piece of equipment.\" And they were in a waiting room.","offset":2913,"duration":42},{"text":"Dr. Richard Davidson: There were magazines and books around and they also said that there's um you know, social psychologists are really good at creating these um scenarios. Um and so uh another experimenter came in and said, you know they're from another research group and they understand they have to wait a little while and we have another experiment that you can do in the meantime and it involves um receiving electric shocks. Um and of course it's completely voluntary, you are free to participate or not.","offset":2955,"duration":38},{"text":"Dr. Richard Davidson: And the bottom line is that these—particularly male undergraduates in the United States—preferred to shock themselves than to sit alone and not do anything. It's a robust finding. Uh people could not sit without doing something is the bottom line.","offset":2993,"duration":25},{"text":"Dr. Richard Davidson: And the reason, I think, is that once we actually begin to inspect our own minds, most people are frightened at the chaos that they see. One of the things we found when we look at a very in a very granular way is that when people start to meditate, we see a statistically reliable increase—increase—in anxiety in the first week.","offset":3018,"duration":34},{"text":"Andrew Huberman: Interesting.","offset":3052,"duration":1},{"text":"Dr. Richard Davidson: And that's often when people say, \"I can't do this. It's making me crazy.\" Um and you know, what we tell them is that's exactly you're doing exactly the right thing, you're you know you're noticing the chaos in your own mind.","offset":3053,"duration":17},{"text":"Andrew Huberman: This is the soreness that comes from a new exercise program.","offset":3070,"duration":3},{"text":"Dr. Richard Davidson: Yeah, exactly.","offset":3073,"duration":1},{"text":"Andrew Huberman: But people know to associate the soreness with, \"Okay, the exercise was effective, it's going to lead to an adaptation.\"","offset":3074,"duration":8},{"text":"Dr. Richard Davidson: And what we haven't changed the the narrative yet about this, but what we're trying to, where we say, \"It this is great that you're feeling anxious, it's exactly what you should be feeling.\"","offset":3082,"duration":13},{"text":"Andrew Huberman: Forgive me, I'm I'm doing all this in real time, so if I if I'm slow, um there's a reason. The analogy to exercise feels ever more important now because thankfully the narrative has been embedded in people's minds that you lift objects or you cycle or run or row or swim, et cetera, to stimulate an adaptation.","offset":3095,"duration":28},{"text":"Andrew Huberman: I think that the exercise scientists, the fields of health and wellness, whatever it is, has been very effective in getting the message out that the burn in your muscles is the thing that's going to lead to an easier run the next time, to more fitness, more longevity, more well-being, et cetera. But it's discomfort in the moment.","offset":3123,"duration":24},{"text":"Andrew Huberman: For a long while now, I've been trying to convince people because it's true that the agitation that one feels trying to solve a problem or read a hard uh page or passage in a book, the one that you have to return to three times that you can't wrap your head around, that that agitation is the stimulus for neuroplasticity. If you could just breeze right through it, the brain has no reason to change. It's not stimulated to change.","offset":3147,"duration":34},{"text":"Andrew Huberman: I can after all just do the thing you're trying to do. So it becomes sort of a duh when you compare when you look at exercise or you look at um cognitive development. But somehow when it comes to meditation, maybe we can accomplish this today, I think you're doing this for us, just knowing for me, just knowing that in the first week anxiety is going to go up but that's the equivalent of lactate accumulating in the muscles, of of the burn—it's the lactate of the mind.","offset":3181,"duration":34},{"text":"Dr. Richard Davidson: Yeah.","offset":3215,"duration":1},{"text":"Andrew Huberman: Thank you.","offset":3216,"duration":0},{"text":"Dr. Richard Davidson: Yes.","offset":3216,"duration":1},{"text":"Andrew Huberman: Perfect. I believe that languaging and messaging is so critical to get people to adopt practices that require this discomfort-adaptation loop that needs to be repeated over time. I love that. I knew we'd get someplace in that in that one. Thanks to you. So glad you're here. So week one, five minutes a day, expect and embrace the anxiety. Is it the thing that's going to produce the adaptation?","offset":3217,"duration":37}],"startTime":2799},{"title":"Meta-Awareness & Flow States","summary":"Defining meta-awareness and exploring how it differs from traditional flow states or \"experiential fusion,\" using the analogy of watching a movie.","entries":[{"text":"Dr. Richard Davidson: I think it's contributing to it, yes. Um and you know it's also being aware of the anxiety without being hijacked by the anxiety, without being lost in the anxiety. So being able to see the anxiety um as it's arising um and that's um you know this is training in meta-awareness. Meta-awareness is super important. I actually think meta-awareness is a necessary prerequisite for any kind of human transformation, mental transformation.","offset":3254,"duration":43},{"text":"Andrew Huberman: Um could you define it for us? Tell us a bit more about it. I'm very curious.","offset":3297,"duration":4},{"text":"Dr. Richard Davidson: Yeah, so I would say meta-awareness is the faculty of knowing what our minds are doing. And to some listeners that may sound a little strange, but how many of you have had the experience of reading a book where you might be reading each word on a page and you read one page, a second page, and after a few minutes you have no idea what you've just read? Your mind is lost, it's somewhere else.","offset":3301,"duration":33},{"text":"Dr. Richard Davidson: But then you wake up. The moment you wake up is a moment of meta-awareness. And it turns out that that's a trainable skill. And that is one of the really important prerequisites um for all other forms of training, of mental training.","offset":3334,"duration":30},{"text":"Andrew Huberman: Do we know where this meta-awareness resides in the brain? Is it prefrontal cortex?","offset":3364,"duration":6},{"text":"Dr. Richard Davidson: You know, it's a network of um prefrontal cortex, anterior cingulate, um insula, um uh I think those are all structures that are participating in meta-awareness.","offset":3370,"duration":16},{"text":"Andrew Huberman: It's interesting because I feel like as we were discussing earlier, people crave forgetting about themselves and just being in experience, it's just such a powerfully and I think positive, seductive thing. I often think about, you know like I at a party, dancing, like like people who can just dance and enjoy themselves versus people who are self-conscious about how they're dancing. Even people who are good at dancing.","offset":3386,"duration":33},{"text":"Dr. Richard Davidson: You can be meta-aware without being awkwardly self-conscious, if you will. So um you know, you talked earlier about flow. Uh I didn't jump in then, but flow can occur with or without meta-awareness.","offset":3419,"duration":18},{"text":"Andrew Huberman: Really?","offset":3437,"duration":0},{"text":"Dr. Richard Davidson: Yes. Um a lot of flow, I think, occurs without meta-awareness. So you know, Csikszentmihalyi who first studied flow, he studied rock climbers. And like a rock climber who is, I mean think about this, why do people do stuff like rock climbing? I think that the reason why people do stuff like that is to produce this state of flow where um most of those kinds of states of flow I think are states of flow without meta-awareness, where you're completely absorbed in the activity.","offset":3437,"duration":48},{"text":"Dr. Richard Davidson: And for a rock climber, if there's even a momentary lapse in attention, it could be potentially lethal. Uh and so by arranging one's physical environment in that way, you are basically forcing uh the default mode to be suppressed. Uh and the default mode is a mode that we know is associated with a lot of self-referential thought. And self-referential thought often is anxiety-provoking.","offset":3485,"duration":40},{"text":"Dr. Richard Davidson: Um and so this is a way to transiently suppress the default mode. But flow can also occur with meta-awareness. Um and so and it doesn't diminish the quality of the flow. And one analogy that we can use is in a movie theater. I mean viewers have had the experience of being in a movie theater and I'm sure people have had the experience of being in a movie theater where you're so engrossed in the movie that you may actually you're not aware that you're in a theater and you may not be even aware that you're watching a movie. You're so you are totally absorbed in the plot.","offset":3525,"duration":56},{"text":"Dr. Richard Davidson: And we've actually come up with a term to define that and we call it \"experiential fusion\" where you're fused with the experience. And that is a kind of the analogous to flow without meta-awareness. But imagine being in the movie theater where your your attention is riveted and there's absolutely no lapse in attention, but in the kind of penumbra of awareness, you are aware you're in a movie theater, you're aware that you're watching a movie, but that doesn't diminish the quality of your attention.","offset":3581,"duration":55}],"startTime":3254},{"title":"Creativity & Capturing the Mind's Chaos","summary":"How paying attention to the mind's chaotic thoughts can lead to creative insights, and the benefit of capturing those ideas by writing them down.","entries":[{"text":"Andrew Huberman: I want to uh ask about this thing about chaos, noticing the chaos of one's mind, because you said that sort sits at the seat of the anxiety that people will feel when they first start to meditate. Now everyone knows in the Richie meditation of push through the first week, expect the the lactate of the mind, push through it. I love that so much, thank you.","offset":3636,"duration":30},{"text":"Andrew Huberman: The idea that the mind is chaotic and getting comfortable with that and not reacting to it, not feeling like we have to get away from it, um we've heard this before, but I think it's somewhat of a novel concept to me to think that a goal of meditation is to be able to see that and sit with it, not necessarily eradicate it. You know I think you said you know the Dalai Lama. I think for most of us we see the Dalai Lama and other monks in robes and you said he sleeps nine hours per night and he's meditating four hours per day and we think, \"All right, he looks pretty blissed out and that's great for them.\"","offset":3666,"duration":45},{"text":"Andrew Huberman: Do you think he has chaos in his mind? Is the idea that extreme meditators or even, you know well-practitioned meditators are free of the chaos or that they're just comfortable with the chaos?","offset":3711,"duration":16},{"text":"Dr. Richard Davidson: I would say that um it's a developmental process that changes longitudinally. So initially there's a lot of chaos and I think it gradually subsides. I don't think it it's like a step function. I think it really occurs gradually over time and the chaos just sort of naturally diminishes.","offset":3727,"duration":28},{"text":"Dr. Richard Davidson: Um but that's a long-term process. Uh and I think for most of us, uh there's always going to be some chaos, uh but part of the chaos also is I think a source of creativity. And you know, when we talk about meta-awareness and awareness of all that's going on in our mind, you know I often give my students the the permission to I tell even if they're not meditators, to just spend a couple hours a week inspecting your mind. Just inspect your mind.","offset":3755,"duration":44},{"text":"Dr. Richard Davidson: Pay attention to what's going on in your mind. Don't do stuff outside, but and and if you come up with some interesting thought, write a little note to yourself as you're doing this, you know not a lot of words, but just a note to remind you when you're finished with this session. Um and my I have the conviction that there's a lot of creative work that humans do on a regular basis that's kind of like dreams.","offset":3799,"duration":33},{"text":"Dr. Richard Davidson: Most people don't remember their dreams, but they occur reliably. And I think that there's a lot of creative thought that occurs on a regular basis but we just don't pay attention to it and we we forget it just like we forget our dreams. But if we have the invitation to really inspect our mind in that way, I think um this chaos actually uh often can contain the seat of real creative insight that potentially could be valuable.","offset":3832,"duration":49},{"text":"Andrew Huberman: I do too. I mean, I wake up every morning with at least one idea from the transition from sleep to waking. Sometimes it's from a dream. I often will record my dreams as voice memos. After I die, if somebody ever finds these voice memos, they're they're so crazy. Every once in a while I'll try and listen to one, I'm like, \"This is crazy,\" but I don't want to forget things and sometimes I don't want to wake up and turn the lights on and I'll go back to sleep.","offset":3881,"duration":26},{"text":"Andrew Huberman: So I'll just record something in the voice memo, sometimes write it down. I think there's so much learning to be had from what's coming up from the unconscious mind in dreams, but also just having a mode of capture during the day. Some way to just capture the things that spring to mind. The great Joe Strummer from The Clash, he said this, he said you know, if you are walking along and an idea comes to mind, you have to write it down because you think you'll remember it later but you will remember it in a form that is not nearly as potent.","offset":3907,"duration":35},{"text":"Andrew Huberman: He said something like that, that this is the mind throwing you ideas and and you got to you have to capture them.","offset":3942,"duration":7},{"text":"Dr. Richard Davidson: I love that. I think it's it's wise advice.","offset":3949,"duration":5},{"text":"Andrew Huberman: Friends of mine who are songwriters, poets, they they do this all the time. They're constantly writing things down that they may or may not develop something from, but they understand that there's information being like thrown up to the surface for them. And if you don't write it down or capture it in some other way, it's it goes, it's evanescent.","offset":3954,"duration":22},{"text":"Dr. Richard Davidson: I actually have—um I mean this may seem contrary to um views of how meditation is done—but when I meditate every morning, I actually have a a little notepad by my cushion and occasionally, I don't do this every session, but maybe twice a week, um I'll actually write down something during the meditation, one or two words just to remind me, because something comes up in my practice, um maybe an idea and I I want to remember it and I know also that I won't remember it after uh in in the same richness, and so I'll just jot jot it down and then go back to my practice.","offset":3976,"duration":51}],"startTime":3636},{"title":"Contagious Flourishing & Meditation for Kids","summary":"Highlighting a mindfulness curriculum for children and a study demonstrating that teachers trained in well-being positively impact their students' math scores.","entries":[{"text":"Andrew Huberman: Is meditation something that kids can do and benefit from? Has that been studied in a formal way?","offset":4027,"duration":7},{"text":"Dr. Richard Davidson: Yes, it's been studied. Um we actually developed a um what we've called a a \"mindfulness-based kindness curriculum\" for preschool kids.","offset":4034,"duration":12},{"text":"Andrew Huberman: Preschool?","offset":4046,"duration":1},{"text":"Dr. Richard Davidson: Preschool. And we've actually published a randomized control trial in a public school system of this curriculum. And the curriculum is available freely on our website in both English and Spanish. So if any teachers are out there or you know teachers and want to use it, please please feel free to to download it and and see how it is.","offset":4047,"duration":29},{"text":"Dr. Richard Davidson: But yeah, so it looks very different. So for example, what we do with a three-year-old, one of the exercises that they love is we ring a bell in a classroom and we have them listen, tell them, \"Listen to this sound and as soon as you no longer hear sound, raise your hand.\" And it's it's amazing to see this because you can get 25 three- and four-year-olds sitting perfectly still for around 10 seconds.","offset":4076,"duration":38},{"text":"Dr. Richard Davidson: But you know, they could taste it. There's a palpable, you know sense of of quiet in that 10 seconds and then they all raise their hand excitedly. But they can really taste it. And so I I do think it's possible. The other thing is—and this is something really important—there's something we've discovered empirically recently, which is that flourishing is infectious. It's contagious. Flourishing is contagious.","offset":4114,"duration":33},{"text":"Andrew Huberman: You explained what that means and how you study that?","offset":4147,"duration":5},{"text":"Dr. Richard Davidson: Yeah, so um uh in the example of you asked about meditating in kids and the reason I'm bringing up in this context is one of the best things I can think a parent can do for a kid is not to have the kid meditate, but meditate yourself. And just be with the child and be fully present, be connected, and really show up in that way and you will osmotically transmit through your demeanor um and your your interaction, you'll transmit these qualities to the child in a completely implicit way.","offset":4152,"duration":52},{"text":"Dr. Richard Davidson: And that's what we mean when we say flourishing is contagious. But how we studied it—so let me actually share one of the this is a finding that we're super excited about and it's not yet published, but it's um the paper is just under review. So one of the things we're deeply interested in these days is how can we scale human flourishing? So we're doing this kind of sector by sector.","offset":4204,"duration":41},{"text":"Dr. Richard Davidson: And one sector that we're doing a lot of work with is educators. And educators around the world and particularly in the US—but we've done this in in Mexico too, so it's not just US-based—but they're super stressed, they're not well-paid, and all of that. Um uh so we did a study with public school educators in Louisville, Kentucky. And um there are many reasons why we went to Louisville, but Louisville is a complicated school system, it's diverse, there are a lot of problems in it, and um it's a big urban school district, the Jefferson County Public School District in Louisville.","offset":4245,"duration":57},{"text":"Dr. Richard Davidson: And we did a randomized control trial with 832 educators in Louisville. And we had them use our Healthy Minds program, which is uh uh a um a digital offering which is freely available as the Healthy Minds program, uh where we had them cultivate four key pillars of well-being: awareness, connection, insight, and purpose. We can take a deeper dive into each of those after.","offset":4302,"duration":32},{"text":"Dr. Richard Davidson: But they practiced for around five minutes a day. The average was a little less than five minutes a day over the course of 28 days. And we measured standard outcomes like depression and anxiety and stress and measures of flourishing, and we find what we found in other studies, which is that depression and anxiety and stress went down and measures of well-being and flourishing went up.","offset":4334,"duration":30},{"text":"Dr. Richard Davidson: But the real kicker is that we by prior agreement had access to the um student-level data in the school system. So we were able to look at the performance of the students who were taught by teachers randomly assigned to the well-being training, and we compared them to students who are taught by teachers randomly assigned to a control group. The the students had no idea that there was any research going on.","offset":4364,"duration":44},{"text":"Dr. Richard Davidson: And what we found is that on standardized tests—this is in middle school children and the sample size for these students was around 13,000—uh and what we found is that the math standardized math scores of the students who were taught by teachers randomly assigned to the well-being training was significantly greater than the scores of the students who are taught by teachers randomly assigned to the control group.","offset":4408,"duration":30},{"text":"Andrew Huberman: Same curriculum.","offset":4438,"duration":1},{"text":"Dr. Richard Davidson: Identical.","offset":4439,"duration":2},{"text":"Andrew Huberman: So what do you think is being transmitted there? Is it that the teachers are calmer, therefore the students are calmer? Is it that the teachers are calmer, therefore they're clearer so the students are I mean, there are a lot of variables. And we don't need to isolate them. I mean, this isn't um we're not trying to do um you know, pharmacology here. Uh but what do you think could be going on?","offset":4441,"duration":22},{"text":"Dr. Richard Davidson: Yeah, I think everything you said is likely to be going on. I think the students are the teachers are are likely calmer, they're more connected. Uh the and what we know is that, you know it was interesting because we looked at reading scores and the the data for the standardized reading measure was in the same direction, but it wasn't as robust. The the biggest signal was in math scores.","offset":4463,"duration":33},{"text":"Dr. Richard Davidson: And we know that math performance is degraded by stress more than reading performance uh uh in this age group. And so it you know, could be as something as simple as the kids who were taught by teachers that went through the well-being training are simply calmer and less stressed when they take the exam. Uh and so their true competence is more likely to be reflected in the test uh and not have it degraded by this kind of added stress and anxiety.","offset":4496,"duration":37},{"text":"Dr. Richard Davidson: Um so this is, you know an illustration that flourishing is contagious in this way.","offset":4533,"duration":10}],"startTime":4027},{"title":"Sponsor: Joovv","summary":"Brief sponsor ad read for Joovv red light therapy devices.","entries":[{"text":"Andrew Huberman: I would like to take a quick break and acknowledge one of our sponsors: Joovv. Joovv makes medical-grade red light therapy devices. Now, if there's one thing that I have consistently emphasized on this podcast, it's the incredible impact that light can have on our biology and our health. Now, in addition to sunlight, which I've talked about a lot on this podcast, red light, near-infrared, and infrared light have been specifically shown to have positive effects on improving numerous aspects of cellular and organ health.","offset":4543,"duration":33},{"text":"Andrew Huberman: These include faster muscle recovery, improved skin health, wound healing, improvements in acne, reduced pain and inflammation, improved mitochondrial function, and even improvements in vision. Nowadays there are a lot of red light devices out there. But what sets Joovv lights apart and why they're my preferred red light therapy device is that they use clinically proven wavelengths, meaning they use the specific wavelengths of red light, near-infrared, and infrared light in combination to trigger the optimal cellular adaptations.","offset":4576,"duration":29},{"text":"Andrew Huberman: Personally, I use the Joovv whole-body panel about three to four times a week, usually for about 10 to 20 minutes per session, and I use the Joovv handheld light both at home and when I travel. If you would like to try Joovv, they're offering up to $400 off select products for listeners of this podcast. To learn more, visit Joovv, spelled J-O-O-V-V dot com slash huberman. Again, that's J-O-O-V-V dot com slash huberman.","offset":4605,"duration":30}],"startTime":4543},{"title":"Escaping Stimulus-Response","summary":"Examining how taking time out of the daily stimulus-response cycle improves overall effectiveness and connects us to a deeper sense of spiritual meaning.","entries":[{"text":"Andrew Huberman: It's so interesting. And again, there I can think of so many different variables that could be at play. Um we did an episode—one of our most popular episodes of ever—uh with a guy named James Hollis. Are you familiar with James Hollis?","offset":4635,"duration":19},{"text":"Dr. Richard Davidson: No.","offset":4654,"duration":0},{"text":"Andrew Huberman: He's a probably by now 85-year-old Jungian analyst.","offset":4654,"duration":7},{"text":"Dr. Richard Davidson: Okay.","offset":4661,"duration":0},{"text":"Andrew Huberman: Brilliant guy. He wrote he's written a number of of books, *The Eden Project*, which is about um relationships and relating, *Under Saturn's Shadow* on the um about trauma and healing, just just an incredible soul, incredible human, incredible educator. And um I'm not alone in in believing that, just spectacular. And I said, you know he's a Jungian analyst, so I said, \"You know like what's the key to a really good life, like but can we talk protocols?\"","offset":4661,"duration":37},{"text":"Andrew Huberman: And he said something really interesting that I think will resonate uh with what you're saying and perhaps shed some light on what happened with these students and flourishing in general. He said, \"It's so important that we wake up each day and we suit up and we show up and we work. In school, in relationships, in life.\" He said, \"But it's also just as important that we take a short amount of time every day and get out of stimulus and response.\"","offset":4698,"duration":36},{"text":"Andrew Huberman: Because by getting out of stimulus and response—and I'm not being nearly as eloquent as Hollis—we come to know ourselves in a certain way that lets ourselves show up so much more effectively for everything else. And so maybe, just maybe what these teachers achieved is by sitting in this anxiety—because now I'm thinking about the lactate of the mind—they're doing a practice which lets them experience the anxiety, not respond to it.","offset":4734,"duration":29},{"text":"Andrew Huberman: They're getting out of stimulus and response.","offset":4763,"duration":3},{"text":"Dr. Richard Davidson: Exactly.","offset":4766,"duration":1},{"text":"Andrew Huberman: And perhaps in the classroom they're able to teach more. Teach more effectively because they're not paying attention to the things that don't matter. Mm-hmm. Or maybe it's because they're also paying attention to the things that do matter. They're signal-to-noise is higher, so to speak. Anyway, I couldn't help but reference the Hollis thing because to not do that would would be remiss. But also, you know here's a guy who's saying you got to go to work each day, this is essential to building a good life and you have to do all these things.","offset":4767,"duration":33},{"text":"Andrew Huberman: And he's also saying, \"But getting out of stimulus response is what makes you effective in everything\" and of course improves your self-understanding. And I think what you're saying, I don't want to put words in your mouth, but what I think you're saying when you talk about meditation is that it's a way of getting out of stimulus and response.","offset":4800,"duration":19},{"text":"Dr. Richard Davidson: Yeah, absolutely. I think that's a great analogy, yeah.","offset":4819,"duration":4},{"text":"Andrew Huberman: Well, he deserves all the credit for all of that, um you deserve all the credit for running all these experiments because I feel like what's been so frustrating over the years has been to hear how powerful meditation is but that for people in the West, um the word meditation brings up ideas of mysticism and um ancient things and people think, \"Well that's not for me. That's not going to benefit me now in this world.\" But I would argue we need it even more so now.","offset":4823,"duration":40},{"text":"Dr. Richard Davidson: I agree. I think that um and I think that the divisiveness and polarization that is just eating away at our society is um underscores the the critical importance of this. I think it's needed now more than ever before in human history. And I think that it will, you know with just modest amounts of practice and and one of the other um you know kind of slogans that we think is really important is that it's easier than you think.","offset":4863,"duration":35},{"text":"Dr. Richard Davidson: It really is. It it 5 minutes a day has a measurable impact. And so I think that if we really take this to heart, uh you know if everyone practiced for 5 minutes a day, I have the strong conviction that this world would really be a different place.","offset":4898,"duration":22},{"text":"Andrew Huberman: Oh, absolutely. I I think the challenge is convincing people and and that's you know, you're doing it, we're trying to do that little by little. I mean, for a zero-cost tool, it's it's just outsized positive effects. I think most people come to the table because it will lower their blood pressure, they hear that it will reduce their stress, maybe make them more effective, make them smarter, sleep better.","offset":4920,"duration":34},{"text":"Andrew Huberman: But there are also the higher-order effects um that people talk about, being gaining some understanding of consciousness and what it may or may not be. When do those effects tend to arise? Uh if they ever do? Or does is it true that by meditating, by getting out of the stimulus and response and just watching one's thoughts and not responding to them and just non-judgment, that we can actually gain some fundamental insight into how our minds work?","offset":4954,"duration":34},{"text":"Dr. Richard Davidson: I do think that that's possible and I think that it does occur and um you know I think that um if we're really good scientists, um there there is um an important element of humility uh as we approach this uh that underscores really how little we know. Um and I think that these kinds of practices help us tap into something that I think is part of what it means to be a human being um and and part of it is honestly, um you know we can use the words \"spiritual\" in some way.","offset":4988,"duration":52},{"text":"Dr. Richard Davidson: Um and uh or \"transcendent\" and by that I mean something connected to something larger than oneself. And I know that this is getting into a little bit of woo territory um and uh uh but people do have a taste of this and it helps to give their life more meaning and and to infuse it with a kind of purpose that um I think is really beneficial.","offset":5040,"duration":46}],"startTime":4635},{"title":"Meditation and the Fear of Death","summary":"Dr. Davidson shares how decades of meditation practice and living intentionally have gradually eliminated his fear of mortality.","entries":[{"text":"Andrew Huberman: I wonder—and I'd love your thoughts on this—whether by doing meditation and seeing that the mind is chaotic and that it's difficult to control and that perhaps the best thing we can do is just observe and not respond to it but not try and control it, that inevitably in one's meditation practice that the reality surfaces that we're all going to die. And I think for a lot of people the fear of death is terrifying.","offset":5086,"duration":41},{"text":"Andrew Huberman: I mean, it's inevitable and it's terrifying. And I do sometimes feel that a lot of the the stuff in the world that we're offered, whether or not it's drugs or alcohol or excessive work or whatever, just all the stuff is um that a deeper layer of that offering is that it it distracts us from that reality. Because it's terrifying, right? I don't most any healthy person doesn't want to die.","offset":5127,"duration":35},{"text":"Dr. Richard Davidson: Although I don't think it's terrifying for all people and I think that it's this is actually one of the dimensions that is shifted by long-term meditation practice unquestionably.","offset":5162,"duration":12},{"text":"Andrew Huberman: Is it shifted because people come to some understanding of energy and the fact that they will likely become part of something else, or do you think it's that they can just accept the reality that we're here then we're not here?","offset":5174,"duration":16},{"text":"Dr. Richard Davidson: I think it's more the latter and also, um imagine that this is the last day we're living, right now.","offset":5190,"duration":9},{"text":"Andrew Huberman: Friday the 13th, of all days.","offset":5199,"duration":2},{"text":"Dr. Richard Davidson: Of all days, it happens to be Friday the 13th. Uh and you know, are we um are we showing up in a way that feels right for us? Um and making the most of our lives and not squandering the opportunity that we have? And if we can live every day in that way, uh it really will change, I think, how we approach our mortality.","offset":5201,"duration":28},{"text":"Dr. Richard Davidson: And I know for me personally, I mean we I'm not well, it I I feel very differently about dying today than I did like 15 years ago. It's that that's one dimension where there's been a dramatic shift.","offset":5229,"duration":21},{"text":"Andrew Huberman: Would you mind elaborating on that? How so? How did you feel about it 15, 20 years ago?","offset":5250,"duration":4},{"text":"Dr. Richard Davidson: Yeah, I was terrified, you know in the same way. I, you know had a family, I have two kids, I have all these, you know responsibilities and um I reflect on this. I really do. And um you know if I died today, I would feel like I've lived a very fulfilling life. Um and uh uh and I'm fine with that.","offset":5254,"duration":39},{"text":"Andrew Huberman: That's a great thing to be able to say. That's a great thing to be able to say. I don't think most people would probably be able to say the same wholeheartedly. Yeah. And you attribute some of that sense to meditation?","offset":5293,"duration":15}],"startTime":5086},{"title":"Consistency, Discipline & Social Zeitgebers","summary":"Dr. Davidson details his personal daily practice and suggests tying meditation to daily habits (social zeitgebers) to effortlessly build consistent discipline.","entries":[{"text":"Dr. Richard Davidson: Definitely, but it's been gradual. You know I've been at this my I my very first meditation retreat was in 1974. Um and I've been practicing daily ever since.","offset":5308,"duration":16},{"text":"Andrew Huberman: Every single day?","offset":5324,"duration":2},{"text":"Dr. Richard Davidson: Well, I may have missed, you know one or two days a year when I had a 6 a.m. flight, but other than that, yes.","offset":5326,"duration":8},{"text":"Andrew Huberman: And what has your practice um your most consistent practice been?","offset":5334,"duration":6},{"text":"Dr. Richard Davidson: You know my practice has changed many times over these the course of these years and very different traditions in which I've practiced um so.","offset":5340,"duration":10},{"text":"Andrew Huberman: What about time of day? Is it typically morning?","offset":5350,"duration":4},{"text":"Dr. Richard Davidson: Always been morning for me.","offset":5354,"duration":1},{"text":"Andrew Huberman: You get up, you use the bathroom, have a drink of water and start, or you go right into it?","offset":5355,"duration":4},{"text":"Dr. Richard Davidson: No, I get up um and I make myself these days a cup of strong black tea um and I drink the tea, which takes maybe 15 minutes, um and then I meditate.","offset":5359,"duration":13},{"text":"Andrew Huberman: Got it. Do you set a timer or a chime?","offset":5372,"duration":2},{"text":"Dr. Richard Davidson: Yeah, I do set a timer. And you know, I meditate at various lengths, but I my modal time sitting is about 45 minutes a day. Um sometimes it's longer, sometimes it's shorter but usually around 45 minutes a day. And maybe three or four days a week I do a really short practice at night, maybe 5 minutes before I go to sleep.","offset":5374,"duration":36},{"text":"Andrew Huberman: Since everyone that takes on the 5-minute-a-day 30-day meditation challenge will do it, um once they reach 30 days, would does it make sense to update that to a longer meditation, or would you just suggest that people stay with that as long as possible?","offset":5410,"duration":18},{"text":"Dr. Richard Davidson: What I would suggest is check in with yourself um and see how you're feeling about it and um how it's resonating with you and um uh and if you feel like you can't really do much more, just stick with 5 minutes a day and keep doing that. The important thing is to stick with a daily practice. And one of the things that um we talk about in this new book, *Born to Flourish*, is a lot of people have a really difficult time coming up with a being able to do this daily.","offset":5428,"duration":36},{"text":"Dr. Richard Davidson: And one of the things that we talk about based on our finding that it doesn't matter, at least in the early stages, whether you're meditating uh as a formal practice or doing it while doing other activities of daily living that are not demanding, like walking or commuting, you tie this to regular activities that you do every day, whatever those activities are. And we talk about this idea of social zeitgebers.","offset":5464,"duration":36},{"text":"Dr. Richard Davidson: A zeitgeber, as you know, uh is um an environmental event, a signal um that is that marks a in the classical literature a biological rhythm like um light is a zeitgeber um to set our biological rhythms. But we in the modern world we have social zeitgebers that are human-created zeitgebers. So eating, for example, is a zeitgeber.","offset":5500,"duration":29},{"text":"Dr. Richard Davidson: Um we eat typically at roughly similar times every day, at least most people. And that's an opportunity. Uh you do that every day, you can pair a little practice with that. Um and you know one of the practices that you can do, which I do every time I eat, virtually, unless I'm eating with someone and it's awkward. Um but I do it at home, is do a little appreciation practice. Spend just a um 30 to to 90 seconds reflecting on all the people it took to have food on your plate.","offset":5529,"duration":36},{"text":"Dr. Richard Davidson: Um and it also gives you a sense of interdependence. And when I sit down, you know and have my breakfast, uh it's a cue for me. It's a social zeitgeber. I do my appreciation practice every single time. Um and then you there are crazy things you can do like I have a cat at home. Um I'm the one who scoops the litter every night. I actually do that as a practice.","offset":5565,"duration":29},{"text":"Dr. Richard Davidson: Um uh and it it literally takes no extra time. I do it while I'm doing the the scooping of the litter. But I I honestly do this in in a very authentic genuine way. I reflect on, \"You know the cat really appreciates this, my wife appreciates this.\"","offset":5594,"duration":20},{"text":"Andrew Huberman: I bet.","offset":5614,"duration":1},{"text":"Dr. Richard Davidson: Um \"People who go into the room with the cat litter appreciate that it's clean and scooped on a regular basis.\" And you know, I just reflect on that intentionally. Um it doesn't take much, it's easier than you think.","offset":5615,"duration":18},{"text":"Andrew Huberman: Yeah, it's so interesting. I mean, I don't want to um contort the message you're you're offering because it's a powerful one about bringing awareness to the things that we have to do anyway and allowing that to make us more effective and happier and more present. But there's also this idea around disciplines, and the word discipline gets is kind of heavy, nobody really likes it because we got disciplined or something.","offset":5633,"duration":32},{"text":"Andrew Huberman: But uh I used to pride myself on working longer hours than everyone and and as the years have gone on, I pride myself in just uh consistency is my superpower. I may not show up with the most intensity every time, although sometimes, but intensity uh kind of waxes and wanes. But there's something about just showing up anyway and just doing it anyway that is so powerful. And I I sometimes wonder whether or not the mind is just it's our foe until we embrace that piece. It's kind of a little bit of what you're saying.","offset":5665,"duration":45},{"text":"Dr. Richard Davidson: Yeah. And I love the consistency uh theme and also the discipline. And yes, I think you're naming something real and important. And there's a delicate calculus uh that ranges between kind of um letting go and discipline. And each person, I think, falls at a different point in this continuum. Uh and what works for one person may not work for for another.","offset":5710,"duration":36},{"text":"Dr. Richard Davidson: You know, with regard to meditation, I always say that what's best for one person isn't necessarily what's best for others and we have to discover what works for us. Um you know what we do know is that in in terms of meditation that consistency is really important.","offset":5746,"duration":22},{"text":"Andrew Huberman: Yeah, I was never a particularly good athlete or bad athlete, but I've just been really consistent at exercise and I mean I play fewer sports these days than than I did, but just the continuing to show up uh allows you to be the person among your peers—not that it's competitive where you go everyone else seems to have quit and they're talking about how much this hurts and that hurts and you're like and all you really had to do was just kind of keep keep going.","offset":5768,"duration":23},{"text":"Andrew Huberman: And I sometimes think that the people that are max intensity and they you know it's like gold medal or bust, they're always the ones or often the ones that we don't hear from anymore, they're like gone. Uh burn out. Yeah. So I love the examples of the Dalai Lama and, you know the Michael Jordans of every domain. But I don't know, I mean I'm more interested in um being the person that at 50, 60 I mean, you're in your mid-70s, you look incredible, you're super vital, cognitively sharp, you're in shape, you're excited about life, you're not afraid of death, clearly you're onto something, you know.","offset":5791,"duration":40},{"text":"Andrew Huberman: So and I doubt it's just the black tea. I'm guessing it's to some extent, I mean you have all the other aspects of your life, but this consistency of meditation practice.","offset":5831,"duration":10},{"text":"Dr. Richard Davidson: Yeah, no I think it's been super important. I do think that the discipline that you're talking about is really important and it is part of it. Uh uh but again, I think we need to find the right balance for each person and initially it's really important to um have people embrace invite them to taste this with the lowest possible friction so that they can really uh experience the benefit and then it can gradually progress and and they can, you know um harness some discipline which eventually will be important.","offset":5841,"duration":52}],"startTime":5308},{"title":"Digital Hygiene & The 'No-Go' Response","summary":"Addressing the cognitive cost of smartphones and how practicing the \"no-go\" impulse by restricting phone use can dramatically improve focus.","entries":[{"text":"Andrew Huberman: I'd like to talk about online culture and social media just briefly because I don't want to demonize it...","offset":5893,"duration":9},{"text":"Dr. Richard Davidson: Yeah, so, um, these are, um, really complicated issues. I think that, um, you know, I certainly don't, um, in any way pretend to have the answer, but I do think that, um, we need to take digital hygiene seriously. And we need to figure out ways of, as part of standard school curricula, of educating our youth in how to change their relationship or how to be, to say it a different way, how to be in healthy relationship with their digital devices and the products and features that are available on those devices.","offset":5902,"duration":57},{"text":"Dr. Richard Davidson: Um, I have the conviction that it's a trainable skill. Um, but we need particularly in youth to start early before they get their first phone.","offset":5959,"duration":15},{"text":"Andrew Huberman: Is there any evidence that meditation because it allows somebody to sit with the lactate of the mind can also, um, afford someone less impulsivity and, um, sort of being less prone to getting hooked by the chaos of the world around them?","offset":5974,"duration":22},{"text":"Dr. Richard Davidson: Yeah, I, um, you know, I don't think there's any hard data on that, but I think it's a great question. I think it's actually empirically tractable. And I think it's really worth studying. My conviction is yes.","offset":5996,"duration":19},{"text":"Dr. Richard Davidson: Um, I think it's, um, it would be helpful, but the data don't exist.","offset":6015,"duration":9},{"text":"Andrew Huberman: What would an experiment like that look like? I feel like we should run that experiment.","offset":6024,"duration":6},{"text":"Dr. Richard Davidson: That would be cool, I'd love to collaborate.","offset":6030,"duration":3},{"text":"Andrew Huberman: Yeah, I feel like there's got to be established in-lab measures of impulsivity.","offset":6033,"duration":5},{"text":"Dr. Richard Davidson: Yeah, there are good measures of impulsivity. And actually with impulsivity, um, there, there are measures that go beyond self-report measures. They are behavioral measures of impulsivity, which may have more validity. And so it would be extremely interesting and, you know, with, um, device use and with, with a person's consent you can actually get backend data so you don't rely on self-report so it can be really, um, robust kind of evidence.","offset":6038,"duration":42},{"text":"Andrew Huberman: The word discipline comes to mind again and I think so many people when they hear discipline they think about doing certain things. Waking up at five, exercising, meditating, eating clean, etc. But to me the most interesting aspect of discipline are the don't dos. It's all the stuff you don't do.","offset":6080,"duration":28},{"text":"Andrew Huberman: You know we're in the Winter Olympics now and I haven't been watching it, I like the Summer Olympics, but um, inevitably when they do the Olympics they interview the people who win gold medals or they'll do a day in the life of and they'll say you know um, they wake up at 5 a.m. and then they train. And they always want to say what do they eat? You know they go well I have four eggs and my oatmeal or whatever it is. Um, what they really need to show is all the things they don't eat. Right because sure what they eat is interesting perhaps, but far more relevant to their performance is all the things they don't eat.","offset":6108,"duration":37},{"text":"Andrew Huberman: Yeah. It's all the things they're not doing. And of course that makes for much less entertaining um, shows, so they don't do that. But I feel like the, the training that would be so valuable is the, to train up the no-go response.","offset":6145,"duration":16},{"text":"Dr. Richard Davidson: Absolutely. One of the things in my own life that I'm very aware of is an apropos not doing is not taking out my phone. Um, and I'm very intentionally aware of that. I actually do a little practice of feeling my phone in my pocket. And I really, um, will not take it out unless I actually need it.","offset":6161,"duration":31},{"text":"Dr. Richard Davidson: Um, I remind people when I have meetings at our center, you know, often it's just the cultural habit particularly with young people, you know, they put their phone on the table. And there are data showing that even if you have all your notifications turned off the simple presence of the device is enough to, um, impair the interaction in some way to have a discernable impact.","offset":6192,"duration":44},{"text":"Andrew Huberman: And cognitive ability. There's this really, I don't know if you've seen this study, it's pretty cool. They um, they looked at cognitive performance in people that had the phone upside down on the table, in their backpack beneath their chair, or in a different room. And only by having it in a different room, um, do you see the, the normal level of cognitive focus, not even an improvement.","offset":6236,"duration":31},{"text":"Andrew Huberman: It turns out that people can focus just as well, it's really interesting, they focus just as well if the phone is on the table or under, um, their chair in their backpack. But that the brain is using additional resources to keep suppressing the thought about the phone. So their cognitive performance is diminished. So the phone is really a cognitive detractor under those conditions.","offset":6267,"duration":33},{"text":"Andrew Huberman: Um, and I think about that a lot. It's also why I have a lockbox for my phone. I keep it in a separate room. It's one of the reasons I love this podcast more and more with every passing week, because no phones in here, um, we can really drop into things. Yeah, I think that, um, training the no-go response, having that level of discipline, is the superpower.","offset":6300,"duration":26},{"text":"Andrew Huberman: Yeah. All the other stuff, the to-dos, I mean yeah it's, it's important. Can't just not do anything obviously. But we focus so much on what to take, what to do. People always want to know what should I take? You know what should I do? What's the ideal workout routine? What's the... and here we have this five minute a day meditation, great. But it's also all the things you're not doing when you can sit for five minutes. You're not responding to the impulse to get up.","offset":6326,"duration":38}],"startTime":5893},{"title":"Pain, Retreats & Emotional Reactivity","summary":"Exploring how meditation alters the secondary emotional response to physical pain, especially after intense retreat practice.","entries":[{"text":"Andrew Huberman: Yes. The discomfort of body that can come up during meditation. A pain in the back, um, your hip getting tight. Should we look at those as an opportunity to train up the mind and our ability to not go into stimulus response or should we get comfortable?","offset":6364,"duration":21},{"text":"Dr. Richard Davidson: It's a great question. And, um, uh, you know my very first meditation retreat in 1974 that I just went into this cold and it was like meditation boot camp. Uh, it was a kind of retreat where we were practicing for 16 hours a day and my body was on fire. I, it was so painful physically.","offset":6385,"duration":33},{"text":"Dr. Richard Davidson: Um, that was, you know, the most predominant experience that I had, just intense, intense physical pain. And then in this style of practice after the third day you had to make a vow that you're not going to move during each hour-long session. So the meditation sessions were hour-long and you had to make a vow that you're not going to move.","offset":6418,"duration":35},{"text":"Dr. Richard Davidson: Man the pain was so intense, the physical pain. And you know, eventually um, after the like the fourth day there's a kind of breakthrough that most people have, um, which is this remarkable kind of experiential insight where you directly look at the pain and you see that it's not exactly what it's cracked up to be and it's actually much more differentiated. And you begin to see all of its constituents. And that's when there's a kind of relief.","offset":6453,"duration":49},{"text":"Dr. Richard Davidson: The other thing to say is that we've done imaging work with physical pain and meditation. Um, it's um, one of the most robust kind of probes that you can use to interrogate the quality of the practice and also the longer term trait effects if you will.","offset":6502,"duration":42},{"text":"Dr. Richard Davidson: Um, and I liken it by the way, you know when you go to a cardiologist you'll often do a cardiac stress test, um, and so one of the best ways to probe the integrity of a system is by challenging it. Um, um, and not just looking at it at baseline so to speak. And it's true of the mind and the brain. And one of the best challenges is physical pain.","offset":6544,"duration":29},{"text":"Dr. Richard Davidson: So we've done work where we've primarily used heat, um, as a um, a painful stimulus because it can be delivered very precisely and very safely. Um, in imaging data there is a signature that is quite specifically tied to the physical pain itself and that there's another signature that is associated with the emotional reaction to the pain.","offset":6573,"duration":38},{"text":"Andrew Huberman: The interpretation of it.","offset":6611,"duration":1},{"text":"Dr. Richard Davidson: The interpretation.","offset":6612,"duration":1},{"text":"Andrew Huberman: Got it.","offset":6613,"duration":1},{"text":"Dr. Richard Davidson: And when we subjectively experience distress in response to pain it's actually mostly contributed by the secondary response. That is the emotional response to the initial noxious stimulus itself. And that is the set of neural changes that we most dramatically see transformed by meditation, uh, as a trait effect.","offset":6614,"duration":48},{"text":"Dr. Richard Davidson: Um, and it's um, particularly in this particular and this is published data, we've we this was done with long-term meditation practitioners and we show that actually it's specifically retreat practice. Um, so we can have two people who are matched on the total number of hours that they've practiced in a lifetime where in one person it is much more um, during retreat compared to another person. And it's specifically retreat practice where you're doing more intensive practice that contributes to the transformation of this emotional pain signature.","offset":6662,"duration":61},{"text":"Andrew Huberman: What would a good retreat practice look like? It would be presumably a course. But I guess if somebody didn't have the resources they could take a weekend and what does that look like? They're meditating a couple hours a day?","offset":6723,"duration":16},{"text":"Dr. Richard Davidson: More than a couple hours a day.","offset":6739,"duration":2},{"text":"Andrew Huberman: Okay, so it would be kind of hard to self-direct.","offset":6741,"duration":4},{"text":"Dr. Richard Davidson: Yeah, although there are a lot of online resources um, for this. And actually for a person who is unable for whatever reason to go physically to retreat there are online resources. Um, but of course, you know, I think it's probably more beneficial to do it in person, um, because you're more likely to comply with the, uh, with the expectations of like not checking your phone and things of that sort and being silent.","offset":6745,"duration":42},{"text":"Andrew Huberman: I'm always impressed by people that can sort of self-direct so much discipline. Um, it's pretty cool. I have rules in my house like I have a study area in my basement where I draw and prepare podcasts and I I don't allow phones down there. Mine or anyone else's.","offset":6787,"duration":22},{"text":"Dr. Richard Davidson: That's wonderful, I love that.","offset":6809,"duration":1},{"text":"Andrew Huberman: It's just an electronic free zone. I also now um, I noticed I I like working out, it's a pleasure for me. Um, and I noticed that my workouts would take much longer if I brought my phone in. So now I allow myself to turn on an album or two and leave the phone outside, but there's no phones allowed there either. And now I'm thinking about also making that the rule for the loft, for the bedroom. Like no phones.","offset":6810,"duration":32},{"text":"Andrew Huberman: So there's fewer and fewer areas where where things are allowed. But I think unless you set real constraints that it just starts to permeate everywhere. And I don't think I'm alone in that. And I grew up in Silicon Valley so I'm not anti-technology. I just want to have the richest experience of life possible. And so I just find that harder and harder to do when it's like inviting all these other things and people into the room when you when you have a phone there.","offset":6842,"duration":53},{"text":"Dr. Richard Davidson: Well I love those examples and I think uh you know you are setting an inspiring example for others. Um, and I think uh things have gotten so bad with uh the deleterious impact of technology that uh you know we've we've been led to to do those kinds of things which I think are so important and I think the more examples of that the better.","offset":6895,"duration":39},{"text":"Andrew Huberman: Yeah I feel like um it took us a while to um become the country with such um excessively high rates of obesity that we finally went oh my goodness, you know and we need to do something about this. So better eating, exercise of course critical, the GLP drugs have been, I believe have been very helpful for a lot of people. I don't I would hope people first embrace lifestyle tools and then and in any case embrace lifestyle tools.","offset":6934,"duration":36},{"text":"Andrew Huberman: But I don't think we're going to have the so-called Ozempic for uh addiction to devices. There isn't going to be something to come along and knock us off that um place. I think it just requires a lot of self-control. But I can promise everyone that the your workouts get way better, way better. Your work gets way better. I actually think that for the younger generation it's become easier than ever to excel simply by not doing a lot of the things that other people around you are doing.","offset":6970,"duration":61},{"text":"Dr. Richard Davidson: Totally, totally.","offset":7031,"duration":1},{"text":"Andrew Huberman: Totally. You know it used to be you know how do I succeed? How do I succeed? And the joking these days, the shortest, um, you know, how to become the best at your craft book is going to be by turning off your phone 22 hours a day. You will become best in class. I I know it. I absolutely know it. And people say well then you can't access certain things. There are ways around it. And um, because it's really the presence that you bring to things that um allows you to be effective.","offset":7032,"duration":53}],"startTime":6364},{"title":"Self-Control & The Dunedin Study","summary":"Highlighting a longitudinal study from New Zealand showing how childhood self-control strongly predicts success, health, and wealth in adulthood.","entries":[{"text":"Dr. Richard Davidson: Yeah, absolutely. And regarding self-control, I think that self-control is a trainable skill. Um, and it is a byproduct of flourishing. Um, and one of the central capacities, I mean I we talked about meta-awareness earlier, and I think meta-awareness is really a key ingredient for self-control. And self-control will or self-regulation will improve as a consequence of that. And that's a superpower.","offset":7085,"duration":50},{"text":"Dr. Richard Davidson: You know there was a study done by these two psychologists, Moffitt and Caspi, who um, are um, developmental sort of life-span psychologists, and they've been studying this cohort in Dunedin, New Zealand. Uh, it's a birth cohort, so these folks have been studied since birth, they're now I think in their 60s. But there's amazing longitudinal data on on these people. And um, they had a paper in PNAS uh a number of years ago that looked at measure behavioral measures of self-control in f in these in this cohort when these people were four and five years of age.","offset":7135,"duration":63},{"text":"Dr. Richard Davidson: And this particular paper was looking at outcomes when they were 32 years of age. And what they found is that the individuals who are in the upper quintile of self-control at four f four and five years of age had significantly less drug abuse, were significantly less likely to be involved in um, in uh court proceedings. Uh, they earned on average $6,000 US dollars more per year, and they were matched on socioeconomic status of their families at birth.","offset":7198,"duration":48},{"text":"Andrew Huberman: So they were more successful.","offset":7246,"duration":1},{"text":"Dr. Richard Davidson: More successful. So all these amazing outcomes. Um, and they I remember this paper was published many years ago, but I remember the there's a line in the paper that says um, uh strategies which will improve self-control will lead to all these these important outcomes and save taxpayers money.","offset":7247,"duration":34}],"startTime":7085},{"title":"Sponsor: Waking Up App","summary":"Brief sponsor ad read for the Waking Up meditation application.","entries":[{"text":"Andrew Huberman: I’d like to take a brief break and acknowledge one of our sponsors, Waking Up. Waking Up is a meditation app that offers hundreds of guided meditation programs, mindfulness trainings, yoga nidra sessions, and more. I started practicing meditation when I was about 15 years old and it made a profound impact on my life. And by now there are thousands of quality peer reviewed studies that emphasize how useful mindfulness meditation can be for improving our focus, managing stress and anxiety, improving our mood, and much more. In recent years, I started using the Waking Up app for my meditations because I find it to be a terrific resource for allowing me to really be consistent with my meditation practice. Many people start a meditation practice and experience some benefits, but many people also have challenges keeping up with that practice. What I and so many other people love about the Waking Up app is that it has a lot of different meditations to choose from, and those meditations are of different durations. So it makes it very easy to keep up with your meditation practice both from the perspective of novelty, you never get tired of those meditations, there's always something new to explore and to learn about yourself and about the effectiveness of meditation, and you can always fit meditation into your schedule even if you only have two or three minutes per day in which to meditate. If you’d like to try the Waking Up app, please go to wakingup.com/huberman where you can access a free 30-day trial. Again, that’s wakingup.com/huberman to access a free 30-day trial.","offset":7281,"duration":99}],"startTime":7281},{"title":"Making Friends With Your Mind","summary":"Shifting the approach to meditation from fighting the mind with rigid discipline to gently accepting and making friends with it.","entries":[{"text":"Andrew Huberman: Super impressive. Uh, and I do think that um nowadays we hear so much about the dos. You exercise, you eat this, and do and we five minutes a day meditation, great. I think the self-control component that's an outgrowth of meditation seems like a distinct benefit of meditation.","offset":7380,"duration":36},{"text":"Andrew Huberman: Because when you're exercising, yeah, I suppose if you if you really hate it and you're constantly forcing yourself not to quit, that's a form of self-control. But I feel like most people once they get going they're kind of moving through it, but who knows? I do want to um use this this notion of self-control as an opportunity to look at the other side of it. And I was planning on doing this at some point. I think now's the point.","offset":7416,"duration":37},{"text":"Andrew Huberman: I'm fundamentally confused about something about life, maybe you can help me. Um, I'm still not sure how much of life, of a really good life, should be forcing ourselves to do things versus um, kind of quote unquote honoring what what's right for us. Now obviously you know with respect to morality, with respect to the the big stuff in life that's those are easy answers. Okay.","offset":7453,"duration":34},{"text":"Andrew Huberman: But when it comes to moving through the day, we're now talking here today about starting the day doing something that you probably don't want to do or that you would reflexively not do as a means to gain some other larger benefit. Um, we're talking about going against the reflex, against the impulse.","offset":7487,"duration":23},{"text":"Andrew Huberman: In the Buddhist traditions, in the field of meditation, how is this kind of thought about? And just personally, how do you think about this? Because I think a lot of people listening are probably thinking, okay great like I'll do this if it gives me some benefits, I'll lower my heart rate, I'll have less stress, I'll learn some additional self-control.","offset":7510,"duration":26},{"text":"Andrew Huberman: But I think people are also feeling overwhelmed with all the stuff they feel like they have to do and fight themselves. And I think people are tired of fighting. And I think part of the reason they're tired of fighting is that they're not picking up the phone and going oh this is cool this is good this is great this is great. I think that they're they feel slightly out of control that they're just can't resist it and it's just happening. And so we've lost the muscle so to speak, the mental muscle of resistance, but I think that of overcoming resistance. Um, but it's also kind of a philosophical question. I mean how much of our lives should we be forcing things upon ourselves to be better and how much of life should we just live and and be free like a like a bulldog which is the best breed of dog.","offset":7536,"duration":64},{"text":"Dr. Richard Davidson: When I first started meditating I was fighting with my mind. Um, and I thought that that was great, you know, I'm this is uh means I'm really doing the work that's necessary and sitting through the physical pain, you know, forcing myself to sit for an hour while my, you know, feeling like my knee was on fire um, and my back was killing me. Um, and you know, I had a kind of sense of pride, I'm able to just uh tough this out. Um, and I was miserable.","offset":7600,"duration":54},{"text":"Dr. Richard Davidson: You know I did that kind of practice for quite some time and it may have had some benefit uh in shaping my skills of self-control. But you know, at some point I discovered that maybe there's another strategy that can be effective that is um, that that's not about fighting with your mind. And not about fixing anything, but it's the invitation is really to make friends with your mind.","offset":7654,"duration":44},{"text":"Dr. Richard Davidson: To welcome this. Uh, to have a completely different stance toward it and to do it with ease rather than with, you know, um, this kind of tension-ridden uh stance. I think that that is possible. Um, and the approach that we are taking in the Healthy Minds program, for example, is we're trying to do that. So there is a bit of discipline involved, but it's kind of um, really at the at the most minimal.","offset":7698,"duration":44},{"text":"Dr. Richard Davidson: It's inviting people to um, to be where they are not and not and to really um, make friends with their mind. Um, and not to fight against it. It's not about pushing away thoughts, it's not about um, you know, sitting down to meditate if you if you're restless and can't sit, that's fine. Do it while you're walking.","offset":7742,"duration":32},{"text":"Dr. Richard Davidson: So the discipline is the intentional use of the mind. Um, and there is discipline involved in that, but it's kind of um, what is the minimum level of discipline to begin to get these networks going? Um, and that's kind of the question that we've asked.","offset":7774,"duration":30}],"startTime":7380},{"title":"Brain Connectivity Changes","summary":"Discussing neuroimaging data that reveals structural changes in the brain's white matter tracts after just a month of five-minute daily meditation.","entries":[{"text":"Andrew Huberman: Yeah, because your lab has been focused heavily on the neuroimaging and understanding what brain networks are activated as well as the positive outcomes. So this five minute a day meditation could be done eyes open, could be done eyes closed, could be done while you're walking, while you're commuting, and it shuts down the sort of default mode network and brings higher levels of activity in these awareness and attentional networks? Is that I'm broadly speaking. I'm a neuroscientist but I want to translate this for for people because the names of the structures actually are somewhat meaningless right unless we're we've got someone in a stereotax, right? So yeah.","offset":7804,"duration":59},{"text":"Dr. Richard Davidson: Exactly. Yeah. So um, just to be transparently honest, there's been very little imaging work on the five minutes per day. We've done some, um, and what we've seen in the work we've done is the biggest and in general I think this is true, the biggest changes that you see particularly in the early stages of practice are in measures of connectivity.","offset":7863,"duration":39},{"text":"Dr. Richard Davidson: And it could be functional connectivity which um uh has to do with the functional integration across different networks, or it could be in measures of actual structural connectivity that we can image with diffusion weighted imaging uh and looking at white matter uh connectivity.","offset":7902,"duration":20},{"text":"Dr. Richard Davidson: And what we've actually seen with the five minutes a day is changes in um, in diffusion weighted imaging looking uh at, I mean the biggest change we see is in the superior longitudinal fasciculus, which um, as you know Andrew, connects the the prefrontal and the parietal regions, and it's basically a major pathway through which the central executive network is um, interacting with the default mode. And that's what we see with just five minutes a day of practice. We can see measurable changes in diffusion weighted parameters in with just five minutes a day for a month.","offset":7922,"duration":64},{"text":"Andrew Huberman: That's super impressive. More and more incentive to doing the five minute a day meditation. I guess that's the protocol we're weaving through this entire episode. And of course people could do seven, could do ten. I'd like to see people do six months every day, that would be impressive. That's what I'm going to shoot for.","offset":7986,"duration":24}],"startTime":7804},{"title":"Sleepiness Meditation & Self-Awareness","summary":"How to handle sleepiness during meditation by observing it curiously, and a look at self-awareness in animals via the elephant mirror test.","entries":[{"text":"Dr. Richard Davidson: Six months every day?","offset":8010,"duration":1},{"text":"Andrew Huberman: Just do five minutes a day for you know hit 30 days and then six months later. I don't know, I feel like if it's just the repeated showing up. I that's really it. I mean I have a prayer practice I do every night before I go to sleep. If I fall asleep, I get out of bed. My girlfriend knows this. I'll get out of bed and I pray. Like I've not missed a night since I started doing this.","offset":8011,"duration":33},{"text":"Dr. Richard Davidson: I love that. I think that's beautiful. And I you know, I'd love to see a study done with pre-sleep prayer and see how it affects sleep.","offset":8044,"duration":10},{"text":"Andrew Huberman: My sleep is definitely better than ever but there are probably a variety of reasons for that. I'm sure. But sometimes I find that I'm falling asleep while I'm praying and I just tell myself, okay just it's the consistency. It's like I I have this script in my head that I'm showing devotion by showing up.","offset":8054,"duration":24},{"text":"Dr. Richard Davidson: Yeah.","offset":8078,"duration":1},{"text":"Andrew Huberman: It's just the repeated showing up and it's one of the few areas of my life that I was able to really remove the the need to do it perfectly. I mean what what would that even look like? I realize how ridiculous that is, right? But um some perfectionist tendencies in in me. You know we're showing up. Um, so for me the the um, I won't even say the the pride in it, the joy in it is from the consistency.","offset":8079,"duration":31},{"text":"Dr. Richard Davidson: Yeah, I love that. And I feel exactly the same way in my consistent practice. Um, I think that's so important. I wanted to mention one thing about sleepiness because you mentioned that sometimes when you're doing the nightly prayer you're sleepy.","offset":8110,"duration":25},{"text":"Dr. Richard Davidson: And sleep sleepiness is is often uh something reported when people are meditating and particularly in the early stages of practice. And uh you know I've uh dealt with sleepiness a lot. Uh, uh and particularly before I changed my routine of and when I gave up the alarm clock because I was getting too little sleep.","offset":8135,"duration":28},{"text":"Andrew Huberman: You were sleep deprived.","offset":8163,"duration":1},{"text":"Dr. Richard Davidson: Yeah, exactly. And I felt it and I struggled with it. So I have this meditation uh teacher Mingyur Rinpoche who uh one of the things he's taught is um is sleepiness meditation. Uh and sleepiness meditation is simply to be aware of sleepiness.","offset":8164,"duration":34},{"text":"Dr. Richard Davidson: Hm. Just be aware of sleepiness. Uh and uh and don't try to fight it. Just simply notice what it what is sleepiness, what is how is it feeling, and um investigate it with curiosity. Uh and that completely changed things for me.","offset":8198,"duration":30},{"text":"Andrew Huberman: There just seems to be this this thing where when we fight our state or our nature it it gains power.","offset":8228,"duration":11},{"text":"Dr. Richard Davidson: Yeah.","offset":8239,"duration":1},{"text":"Andrew Huberman: But when we we don't want to give in to it but when you acknowledge it but you don't completely give in to it somehow it it changes. Martha Beck was the first person to really teach me this, first in her books and then on the podcast. This idea that like if a feeling sucks or you don't want it to be there that rather than trying to suppress it you really look at it and let yourself feel it until it changes shape just a little bit, her language.","offset":8240,"duration":31},{"text":"Dr. Richard Davidson: Yeah.","offset":8271,"duration":1},{"text":"Andrew Huberman: And then you start to look at it through that different slightly different lens and then it morphs and it goes away.","offset":8272,"duration":7},{"text":"Dr. Richard Davidson: Exactly, exactly.","offset":8279,"duration":1},{"text":"Andrew Huberman: And I think in her descrip- I didn't again didn't describe it as well as as she did or would or could but um what we're talking about over and over again today is the mind looking at the mind. And it does seem to have this ability to, you know, humans have this ability to... do you think other animals have this ability? I know you can't answer that quest- question for sure. But do you think one of the reasons dogs are so wonderful is because they're not self-conscious?","offset":8280,"duration":36},{"text":"Dr. Richard Davidson: My conjecture is that um that our ability to uh look at our minds is way more developed than in any other species. And there may be some rudimentary kinds of meta-awareness in other species and you know some scientists have suggested that it may be correlated with successful performance on the self test, you know recogn- recognizing yourself in the mirror.","offset":8316,"duration":36},{"text":"Dr. Richard Davidson: Um you know there's a recent report of elephants passing the self-test. Hm. So they are smart after all. Yeah. Uh and you know that's an interesting story. They did this actually in the Bronx Zoo in New York and they had to construct a mirror that was the size of an elephant to how do they know if the elephant knows it's itself because they don't attack it if it's itself. So they they put rouge on the trunk and they expose the elephant to the mirror. And if the elephant touches the point where the rouge is it's recognizing itself in the mirror.","offset":8352,"duration":48},{"text":"Dr. Richard Davidson: And there are very few species that uh pass the self-test in that way. Most species don't.","offset":8400,"duration":13}],"startTime":8010},{"title":"The Four Pillars of Human Flourishing","summary":"Breaking down the four trainable components of flourishing: awareness, connection, insight, and purpose, along with a guided compassion practice.","entries":[{"text":"Andrew Huberman: We were talking offline a little bit earlier about a course that you're teaching about this very thing that you're calling flourishing. So what do the students get in that course and what components could you possibly educate us on right here right now so that we can benefit without having the opportunity to take the course?","offset":8413,"duration":24},{"text":"Dr. Richard Davidson: Yeah, absolutely. So the course is built on a framework that uh we've developed on the plasticity of flourishing. Um. It holds that there are four key pillars of human flourishing. And each of these pillars exhibits plasticity. Uh and these are the key trainable ingredients that constitute human flourishing.","offset":8437,"duration":32},{"text":"Dr. Richard Davidson: So what are these four pillars? The first pillar is and we've talked about some in the course of our conversation already but the first we call awareness. And awareness is where mindfulness is would be, it's where voluntary attention the capacity to focus resides, and it also includes our capacity for self-awareness and for meta-awareness which we've spoken about.","offset":8469,"duration":40},{"text":"Dr. Richard Davidson: The second pillar we call connection. And connection is about the qualities which are important for healthy social relationships, uh qualities like appreciation and gratitude and kindness and compassion. You can think of the the opposite of that being um at least in part social isolation and loneliness. Again these are elements that we know can be trained, they are importantly connected to our well-being.","offset":8509,"duration":41},{"text":"Dr. Richard Davidson: The third pillar we call insight. And insight is about a curiosity driven understanding of the narrative that all human beings have about themselves. Uh the narrative that we carry around in our minds. And we know that we all have a set of beliefs and expectations of ourselves. And we know that at one extreme of the continuum there are people that have very negative beliefs and expectations of themselves and of course that's a prescription for depression.","offset":8550,"duration":44},{"text":"Dr. Richard Davidson: But what's really critical for well-being is not so much changing the narrative, particularly at first, but it's changing our relationship to the narrative. So that we can see the narrative for what it is, which is a set of beliefs and thoughts and expectations.","offset":8594,"duration":24},{"text":"Dr. Richard Davidson: And then finally the last pillar is purpose. And purpose here is not necessarily about finding something grand to do with your life that's more meaningful and purposeful, but rather how can we find meaning and purpose in even the most pedestrian activities of daily living?","offset":8618,"duration":28},{"text":"Dr. Richard Davidson: And we actually talked about some of this earlier, but can taking out the garbage be connected to our sense of purpose? Cleaning the kitty litter. Cleaning the kitty litter. And of course it can be, it just requires a little bit of reframing and that's a learnable skill.","offset":8646,"duration":22},{"text":"Dr. Richard Davidson: There are really three things that we've discovered in this work uh uh that can be easily summarized. The first is that flourishing is a skill, the second is that it's easier than you think, and the third is that flourishing is contagious so that when you're flourishing it's going to have beneficial impact on the people around you.","offset":8668,"duration":37},{"text":"Dr. Richard Davidson: And our course, the Art and Science of Human Flourishing, is built on each of these pillars to give students not just um an intellectual understanding, but an experiential um uh practice, a taste, uh of what these pillars actually are.","offset":8705,"duration":35},{"text":"Dr. Richard Davidson: One of the important insights that the course is built on is that there are two major forms of learning that we know from modern neuroscience. One we can think of as declarative learning, which is learning about stuff, it's conceptual learning. The other we call procedural learning. And procedural learning is learning that is skill-based, it's acquired through practice, and we know that it's instantiated in different brain networks compared to declarative learning.","offset":8740,"duration":60},{"text":"Dr. Richard Davidson: And human flourishing requires both. Um and most of the academy privileges declarative learning over procedural learning. Uh and so this course that we teach is an unusual course because it includes a lab every week, so to speak, um a little section where students do the procedural learning for the stuff that they're learning declaratively in the lecture part of the class.","offset":8800,"duration":51},{"text":"Andrew Huberman: I love that. I've long wanted to do a course that had information and practices involved. Sounds like you've built that course. Um if people who are not able to take the course wanted to access these different bins with some practical tools, um you already gave us um a tool for awareness, so meditation, um five minutes would be a great place to start done daily, um and just to be aware of what's of the chaos and be able to observe it but not go not follow it.","offset":8851,"duration":43},{"text":"Andrew Huberman: How does one incorporate connection?","offset":8894,"duration":2},{"text":"Dr. Richard Davidson: So I actually talked a little bit about connection in in uh earlier, but there's a lot more to say. But one kind of connection is doing a little appreciation practice when we eat, that's one I talked about earlier, um where we connect to the people even if we don't know them who have brought us food to the table. Some we some we may know, some we might not know.","offset":8896,"duration":35},{"text":"Dr. Richard Davidson: There are formal kinds of connection practices that we there are meditation practices that we call loving kindness and compassion practices. And so we can um we've shown in a randomized control trial uh that just a few hours of this practice over two weeks is sufficient to produce a measurable change in the brain.","offset":8931,"duration":35},{"text":"Dr. Richard Davidson: Uh and so here's a a way you can do this. You can begin with a loved one and bring the loved one into your mind and your heart and envision a time in their life when they may have had some challenge or difficulty and then cultivate the strong aspiration that they be relieved of that difficulty and that they have um a life of ease.","offset":8966,"duration":42},{"text":"Dr. Richard Davidson: That's it. And you can use a simple phrase that you can repeat to yourself um that embodies that captures that theme. It could be something as simple as may you be happy, may you be free of suffering. But the words don't matter whatever words are most well-suited for each person.","offset":9008,"duration":30},{"text":"Dr. Richard Davidson: Um but then you move on to different categories of people. So you start with a loved one, you then move on to yourself, you then move on to to a category of person that we call a stranger. And a stranger is someone you recognize whose face you recognize but you don't know them well.","offset":9038,"duration":29},{"text":"Dr. Richard Davidson: It could be someone that works in the same building that you work in, it could be a classmate, it could be a bus driver, it could be the cashier at a local um store that you go to, a barista. Um you don't know anything about them but you recognize them. And you can envision a time in their life when they may have had some difficulty even if you don't know anything about their life. So you do that with the stranger.","offset":9067,"duration":42},{"text":"Dr. Richard Davidson: And then finally you move on to what's probably the most important category which is a difficult person. Someone who pushes your buttons. And you genuinely bring them into your mind and your heart and you recognize a time, you imagine a time when they have been having some challenge and you cultivate the aspiration that they be relieved of that suffering.","offset":9109,"duration":32},{"text":"Dr. Richard Davidson: And that practice just done a few minutes a day can change your brain and it changes your behavior.","offset":9141,"duration":12},{"text":"Andrew Huberman: And it changes the brain how? Makes it um a capable of more empathy?","offset":9153,"duration":8},{"text":"Dr. Richard Davidson: So one of the key regions of the brain that's been implicated in empathy is the um the temporal parietal junction. What we see is that in this kind of compassion practice there's significantly enhanced activation of the temporal parietal junction particularly in response to stimuli of people in distress. Hm. There's also uh networks in the brain that are involved in positive affect that are activated by this kind of practice.","offset":9161,"duration":57},{"text":"Dr. Richard Davidson: And behaviorally we've shown using hard-nosed um tasks that are derived from behavioral economics and...","offset":9218,"duration":42}],"startTime":8413},{"title":"Enhancing Slow-Wave Sleep","summary":"A look at preliminary research combining imperceptible electrical brain stimulation and pre-sleep meditation to boost restorative slow-wave sleep.","entries":[{"text":"Dr. Davidson: And we're doing—and this—the other cool thing about this stimulation is you cannot feel it. It has no subjective sensations. So, it's very different than TMS which is, you know, you feel it big time. You don't feel a thing. So, we are delivering this during sleep. People don't know when they're getting stimulated. They of course know they're being stimulated because they're giving informed consent, but it doesn't wake them up.","offset":9260,"duration":24},{"text":"Dr. Huberman: And it increases slow wave sleep?","offset":9284,"duration":3},{"text":"Dr. Davidson: We've definitively demonstrated that it increases the density of slow wave activity during deep sleep.","offset":9287,"duration":6},{"text":"Dr. Huberman: How do they feel in their wakeful subjective life? Better?","offset":9293,"duration":4},{"text":"Dr. Davidson: Yes.","offset":9297,"duration":1},{"text":"Dr. Huberman: And how do I become a participant in the study? I mean, I get plenty of slow wave sleep, my sleep is great lately and has been for a while, but what—are you recruiting subjects?","offset":9298,"duration":10},{"text":"Dr. Davidson: This is a—yeah, it's a big complicated protocol.","offset":9308,"duration":3},{"text":"Dr. Huberman: I don't care, are you recruiting subjects? I'm just kidding, I'm just kidding. I do care. I'm just teasing. People are probably thinking, \"How do I get that?\" Well, maybe this pre-sleep meditation protocol should be looked at, because that's something anyone can do. I'll provide a link to that paper.","offset":9311,"duration":12},{"text":"Dr. Davidson: So, that's exactly what we're doing in this study now. We're using a—this is a little technical, but we're using a micro-randomized design where, so in a single participant on some nights they get pre-sleep meditation, just before sleep, just a five-minute practice. And in other nights, they do not receive that.","offset":9323,"duration":24},{"text":"Dr. Davidson: And we are looking at the impact of that on slow wave sleep and also looking at the synergistic effects of pre-sleep meditation with the Testi stimulation to increase slow wave activity. And we're getting experience sampling measures during the next day to see if the pre-sleep meditation has a demonstrable impact on their mood the next day and how that interacts with our boosting of slow wave activity.","offset":9347,"duration":27},{"text":"Dr. Davidson: Very, very cool. I should just say this is work that's being done collaboratively with Giulio Tononi and his group at in Wisconsin. He's a very well-known sleep and consciousness scientist, neuroscientist.","offset":9374,"duration":15},{"text":"Dr. Huberman: Great lab.","offset":9389,"duration":1},{"text":"Dr. Davidson: Yeah, great lab.","offset":9390,"duration":1},{"text":"Dr. Huberman: Are you able to share any preliminary findings about what the pre-sleep five-minute meditation does to deep sleep?","offset":9391,"duration":7},{"text":"Dr. Davidson: We don't know yet. And honestly, it's not me being, you know, super cautious. We just this is a new study that we're just in the middle of. We have roughly 20-something participants who've completed the protocol, but it's it's ongoing right now.","offset":9398,"duration":15},{"text":"Dr. Huberman: Well, given what you just described, and given that this other paper described that some pre-sleep meditation can have a really impressive impact on growth hormone release, I'm encouraged to do the five minutes before sleep. So, I suppose that if you want to double up on the benefits, you could just do the five minute per day meditation, folks, right in the hour before sleep.","offset":9413,"duration":21},{"text":"Dr. Davidson: Why not? I think it would be great.","offset":9434,"duration":2}],"startTime":9260},{"title":"Open Monitoring Meditation & Creativity","summary":"Dr. Davidson explains how open monitoring meditation can enhance creative thought by making us more aware of passing associative ideas.","entries":[{"text":"Dr. Huberman: What are your thoughts on open monitoring meditation for increasing creativity?","offset":9436,"duration":5},{"text":"Dr. Davidson: Honestly, the data on open monitoring meditation or for that matter any meditation and creativity, I would say are very limited. In part, it's because the measures of creativity that are used by psychologists typically are honestly, I think pretty crappy measures of creativity. So we're quite limited by the measurement tools that we have.","offset":9441,"duration":39},{"text":"Dr. Davidson: Having said all that, I do think that open monitoring meditation can really boost creativity primarily by helping people become more aware of the associative thoughts that they have. And this relates to something we talked about earlier. I often tell students of mine to spend time inspecting their own mind, just watching their own mind and writing down thoughts that may occur that may be interesting.","offset":9480,"duration":32},{"text":"Dr. Davidson: And this is a kind of open monitoring meditation. It's having no specific object and just being open, aware, awake, and not distracted, not getting lost in a train of thought, but simply being aware. I believe that we probably have much more creative thought occurring than we give ourselves credit for, and it's simply because we forget. And I think this can really improve that. But the data are pretty meager.","offset":9512,"duration":35},{"text":"Dr. Huberman: But you still recommend it if people want to increase their creativity.","offset":9547,"duration":3},{"text":"Dr. Davidson: Yes, I do, because this is one of those things where there's essentially no downside to it. We know there'll be other benefits that have been empirically documented.","offset":9550,"duration":16}],"startTime":9436},{"title":"Conclusion & Outro","summary":"Dr. Huberman thanks Dr. Davidson, promotes his upcoming book, and provides closing remarks and social media links.","entries":[{"text":"Dr. Huberman: Awesome. Well, Richie, thank you so much for coming here today and educating us on meditation, but really much more than that. You've educated us on states of mind, how to access different states of mind, what they mean, how they impact the state of being and our traits that we will enter after we meditate. And now everyone should be inspired to do at least five minutes per day of meditation, maybe in the morning, maybe before sleep.","offset":9566,"duration":26},{"text":"Dr. Huberman: Would love to get the update on this study that you described looking at slow wave sleep. And I'm really excited about your book. It's so great that you have a new book coming out because I, of course, read *Altered Traits*. I've talked about it on the podcast. I love, love, love the book. We'll put a link to that. But *Born to Flourish: How New Science and Ancient Wisdom Reveal a Simple Path to Thriving* by you and we should give credit to your co-author, Cortland Dahl.","offset":9592,"duration":25},{"text":"Dr. Huberman: And he is a neuroscientist as well?","offset":9617,"duration":2},{"text":"Dr. Davidson: Yes, he's a neuroscientist, contemplative scientist, and chief contemplative officer of our non-profit human.org.","offset":9619,"duration":10},{"text":"Dr. Huberman: Awesome. Well, you're a real pioneer in this space. The field, as it were, of meditation really needed a serious scientist to break in and study and share so that everyone could learn about and adopt meditation and you've just done so much to educate so many people and coming here today you've just done more of that, so I have immense gratitude for you and I know millions of other people do as well. So, thank you so much.","offset":9629,"duration":25},{"text":"Dr. Davidson: Thank you. And I want to express my immense gratitude to you for bringing science that can make our lives better to so many people, and that is such a gift and such a wonderful service that you are providing, so thank you.","offset":9654,"duration":16},{"text":"Dr. Huberman: Thank you. Thank you for joining me for today's discussion with Dr. Richie Davidson. To learn more about his work and to find a link to his new book, *Born to Flourish*, please see the links in the show note captions. If you're learning from and or enjoying this podcast, please subscribe to our YouTube channel. That's a terrific zero-cost way to support us. In addition, please follow the podcast by clicking the follow button on both Spotify and Apple.","offset":9670,"duration":25},{"text":"Dr. Huberman: And on both Spotify and Apple, you can leave us up to a five-star review. And you can now leave us comments at both Spotify and Apple. Please also check out the sponsors mentioned at the beginning and throughout today's episode. That's the best way to support this podcast. If you have questions for me or comments about the podcast or guests or topics that you like me to consider for the Huberman Lab podcast, please put those in the comment section on YouTube. I do read all the comments.","offset":9695,"duration":26},{"text":"Dr. Huberman: For those of you that haven't heard, I have a new book coming out. It's my very first book. It's entitled *Protocols: An Operating Manual for the Human Body*. This is a book that I've been working on for more than five years and that's been based on more than 30 years of research and experience. And it covers protocols for everything from sleep to exercise to stress control, protocols related to focus and motivation. And of course, I provide the scientific substantiation for the protocols that are included.","offset":9721,"duration":24},{"text":"Dr. Huberman: The book is now available by pre-sale at protocolsbook.com. There you can find links to various vendors. You can pick the one that you like best. Again, the book is called *Protocols: An Operating Manual for the Human Body*. And if you're not already following me on social media, I am Huberman Lab on all social media platforms. So that's Instagram, X, Threads, Facebook, and LinkedIn. And on all those platforms, I discuss science and science-related tools, some of which overlaps with the content of the Huberman Lab podcast, but much of which is distinct from the information on the Huberman Lab podcast.","offset":9745,"duration":331},{"text":"Dr. Huberman: Again, it's Huberman Lab on all social media platforms. And if you haven't already subscribed to our Neural Network newsletter, the Neural Network newsletter is a zero-cost monthly newsletter that includes podcast summaries as well as what we call protocols in the form of one-to-three page PDFs that cover everything from how to optimize your sleep, how to optimize dopamine, deliberate cold exposure.","offset":10076,"duration":23},{"text":"Dr. Huberman: We have a foundational fitness protocol that covers cardiovascular training and resistance training. All of that is available completely zero-cost. You simply go to hubermanlab.com, go to the menu tab in the top right corner, scroll down to newsletter, and enter your email. And I should emphasize that we do not share your email with anybody. Thank you once again for joining me for today's discussion with Dr. Richie Davidson. And last but certainly not least, thank you for your interest in science. [2:48:47]","offset":10099,"duration":15}],"startTime":9566}],"entries":[{"text":"Dr. Richie Davidson: We actually have really good data on this that at least for beginning meditators, if you do it for 30 days and you do it just for 5 minutes a day, you will see a significant reduction in symptoms of depression, symptoms of anxiety, and symptoms of stress. We've shown that repeatedly in randomized control trials. You'll see an increase on measures of well-being or flourishing, and we can talk about what those actually mean. You can even see, just with this amount of practice, a reduction in IL-6. IL-6 is a pro-inflammatory cytokine.","offset":0,"duration":39},{"text":"Huberman Lab Intro: Welcome to the Huberman Lab Podcast where we discuss science and science-based tools for everyday life.","offset":39,"duration":10},{"text":"Andrew Huberman: I'm Andrew Huberman, and I'm a professor of neurobiology and ophthalmology at Stanford School of Medicine. My guest today is Dr. Richie Davidson. Dr. Richie Davidson is a professor of psychology and psychiatry at the University of Wisconsin-Madison. He is a pioneer in the study of how meditation impacts the brain both during meditations, but also how it changes your brain over time, what we refer to as neuroplasticity.","offset":49,"duration":29},{"text":"Andrew Huberman: Today, we discuss the incredible health and neuroplasticity benefits that come from regular meditation, including very brief meditations of just five minutes per day. Dr. Davidson also dispels many common myths about meditation. For example, contrary to what most people believe, the point of meditation is not to clear your mind or to feel inner peace during the meditation, but rather to observe your thoughts and any stress you might experience during the meditation, and in doing so, it's kind of like the final hard repetitions of resistance exercise or the burn you might feel during cardio which comes from lactate. In that sense, the stress you feel during meditation and your ability to observe it acts as a sort of lactate of the mind that in turn makes you adapt, it makes you more stress-resilient, focused, and peaceful outside of the meditation.","offset":78,"duration":44},{"text":"Andrew Huberman: Dr. Davidson also explains how your brain changes during different types of meditation, such as open monitoring meditation, or eyes-open meditation, walking versus seated, and standing meditations and more. I've been doing meditation over many years, but this conversation with Dr. Richie Davidson changed my daily routine. Afterwards, I immediately started implementing a five-minute-per-day meditation of the sort that Dr. Davidson describes specifically for stress resilience, and I have to say it's had a profound impact on my levels of mental clarity, focus, and sleep, and in stress, just as he explained. In fact, it's proved to be one of the most beneficial practices I've taken on, especially on days when I wake up with tons to do, a little bit stressed or a lot stressed, and if I didn't sleep quite as well as I would have liked.","offset":122,"duration":47},{"text":"Andrew Huberman: So today, you're going to hear about the incredible science of meditation, the brain and bodily changes that occur, but also how you can rewire your brain using meditation. Dr. Richie Davidson is a true pioneer in this field, being one of the first to bring brain imaging and studies of mindfulness and meditation to the West. He has of course authored some of the most impactful research papers on these topics, but also popular books, including a new book coming out later this month entitled \"Born to Flourish: How to Thrive in a Challenging World,\" which I myself look forward to reading.","offset":169,"duration":33},{"text":"Andrew Huberman: Before we begin, I'd like to emphasize that this podcast is separate from my teaching and research roles at Stanford. It is, however, part of my desire and effort to bring zero-cost-to-consumer information about science and science-related tools to the general public. In keeping with that theme, today's episode does include sponsors.","offset":202,"duration":19},{"text":"Andrew Huberman: And now, for my discussion with Dr. Richie Davidson. Dr. Richie Davidson, welcome.","offset":221,"duration":11},{"text":"Dr. Richie Davidson: Thank you Andrew, I'm honored to be here.","offset":232,"duration":3},{"text":"Andrew Huberman: Oh, it's an honor to have you here. I am a long-time fan of your research, of what you've built at the University of Wisconsin-Madison, the books you've written - we'll talk about your new book, I didn't even know you had a new book, this wasn't a book tour invite, I had seen you give a seminar at Stanford and I said great, here's my opportunity to finally get you on the podcast. But you really transformed the way that I think about not just meditation, but all states of mind and how that relates to our individual traits and how those can change over time. Today we'll talk about concept and protocols. But I'm curious how you think about states of mind generally. I think it's really important that we frame the discussion with this because we all know what sleep is, most people have heard that sleep has different components, REM sleep etc. We know what it is to be awake, stressed versus calm. But how should we think about states of mind and then once you tell us how you think about that, perhaps then we can better place this thing we call meditation into a particular bin.","offset":235,"duration":52},{"text":"Dr. Richie Davidson: So thank you first for having me Andrew, and I've just want to say I've been a long-term fan of yours so I'm really happy to be here. In terms of states of mind, I think that at the outset it's really important that we also remind listeners that there's a thing called traits too, and so we can't talk about states without also talking about traits, and we'll get to traits in a moment. But I think with regard to states, we can think of them as organized patterns of activity in the brain that have corresponding organized mental correlates if you will, or subjective correlates.","offset":287,"duration":46},{"text":"Dr. Richie Davidson: And there are certain states that occur with regularity that are part of our biological rhythms, and so most human beings will have states of wakefulness, of deep sleep, and of REM sleep every day. And that is regulated by well-known kinds of biological rhythms. And then there are other kinds of states that are sometimes described that are states during what we normally think of as waking, although I think honestly the concept of state is often used loosely without rigorous boundary criteria for what constitutes a state and how it might be distinguished from another state.","offset":333,"duration":54},{"text":"Dr. Richie Davidson: There are certain states which if they occur with regularity will lead to a trait. They'll lead to a shift in the baseline for the next state. There was a paper I wrote many, many years ago with my dear friend and colleague Daniel Goleman who I wrote the book Altered Traits with, and the origin of Altered Traits is really in a sentence that we wrote in a paper 20 years earlier where we said: the after is the before for the next during.","offset":387,"duration":34},{"text":"Andrew Huberman: The after is the before for the next during. Let's drill into that for a second.","offset":421,"duration":4},{"text":"Dr. Richie Davidson: Yeah, so what we mean by that is that how you are after a state, say you do a little meditation practice and it leads to a state change, that state change may persist in some way and that becomes the next before for the next during, the during is the state, is the say the meditation state. And so it's a description of how a state can lead to a trait. In the domain of emotion, you might think that frequent bouts of anger, which you can think of as a state, can lead to the trait of irritability, which is sort of chronically having a low threshold. You can think of a trait in certain cases as altering the threshold for the elicitation of a state. So a trait of irritability would be a trait where you have a lowered threshold for the elicitation of anger, for example.","offset":425,"duration":64},{"text":"Andrew Huberman: Yeah, I love that example because I know that many people will resonate with it because so much of what we see online nowadays is designed to capture our attention by engaging negative affect - mild anger, frustration, or even outrage. There's other content online too of course, and this podcast is online after all. And many other sources of what I consider benevolent educational information. But it is so true that, you know, what we experience in one portion of our day impacts how we are in the rest of our day. And perhaps the simplest correlate for all of it for me anyway is sleep. You know, if I sleep really well for three or four nights in a row, I wake up in a certain state that certainly makes my day go differently. And the inverse is also true if I don't sleep well. I feel like we have such great nomenclature and understanding of brain activity and how that impacts emotionality for sleep. We know that REM sleep based dreams are very vivid, slow wave sleep based dreams are less vivid perhaps. We know the electrical activities associated with those different states of sleep. I'm aware of a lot less information about brain activities and clear definitions of waking states of mind. Do you mind if we talk about this for a little bit? It's been a few years since I've heard about and I don't think we've ever really talked on this podcast about, you know, alpha waves, beta waves, theta waves. Maybe just educate us a bit on some of the waking brain states that we've all experienced, perhaps are in right now, but that we just don't hear about that much anymore.","offset":489,"duration":104},{"text":"Dr. Richie Davidson: So yeah, we can talk about those oscillations of brain electrical activity, and there are broad suggestions for what kind of state they may reflect, and you know, I'll go through that, but it's also important to recognize that you can be showing alpha activity in one part of the brain and beta activity in another part of the brain simultaneously. And so it's a bit coarse to talk about these as general characteristics, but there could be times when we see predominantly one oscillation or another and so talking about generalized states in that context may be more reasonable.","offset":593,"duration":45},{"text":"Dr. Richie Davidson: So with that as a caveat, let me say that in humans we see a broad range of frequencies that go from approximately 1 Hz (one cycle per second) to approximately 40 Hz. And from roughly 1 to 4 Hz is delta activity, that is typically not seen during waking, it's predominant during deep sleep. And there is data that suggests that the density of delta activity or slow wave activity during deep sleep is actually diagnostic of how restorative that sleep is, which is a whole separate set of issues and super cool.","offset":638,"duration":41},{"text":"Dr. Richie Davidson: And there are actually some really interesting highly novel strategies now using neurostimulation to actually boost slow wave activity during deep sleep which may actually help to potentiate some of the skill acquisition that we do during the day, including meditation. And we're doing some of that work now, which is actually you had asked earlier before we started about some novel new work that we're doing and that's also one of the really cool new things. So we can dive into that.","offset":679,"duration":36},{"text":"Andrew Huberman: I'd like to take a quick break to acknowledge one of our sponsors, David. David makes protein bars unlike any other. Their newest bar, the Bronze Bar, has 20 grams of protein, only 150 calories, and zero grams of sugar. I have to say these are the best tasting protein bars I've ever had, and I've tried a lot of protein bars over the years. These new David bars have a marshmallow base and they're covered in chocolate coating and they're absolutely incredible. I of course eat regular whole foods - I eat meat, chicken, fish, eggs, fruits, vegetables, etc. But I also make it a point to eat one or two David bars per day as a snack, which makes it easy to hit my protein goal of one gram of protein per pound of body weight, and that allows me to take in the protein I need without consuming excess calories. I love all the David Bronze Bar flavors, including cookie dough, caramel chocolate, double chocolate, peanut butter chocolate, they all actually taste like candy bars. Again, they're amazing, but again they have no sugar and they have 20 grams of protein with just 150 calories. If you'd like to try David, you can go to davidprotein.com/huberman. Right now David is offering a deal where if you buy four cartons, you get the fifth carton for free. You can also find David on Amazon or in stores such as Target, Walmart, and Kroger. Again, to get the fifth carton for free, go to davidprotein.com/huberman.","offset":715,"duration":79},{"text":"Andrew Huberman: Today's episode is also brought to us by Eight Sleep. Eight Sleep makes smart mattress covers with cooling, heating, and sleep tracking capacity. One of the best ways to ensure you get a great night's sleep is to make sure that the temperature of your sleeping environment is correct. And that's because in order to fall asleep and stay deeply asleep, your body temperature actually has to drop by about one to three degrees. And in order to wake up feeling refreshed and energized, your body temperature actually has to increase by about one to three degrees. Eight Sleep automatically regulates the temperature of your bed throughout the night according to your unique needs. I've been sleeping on an Eight Sleep mattress cover for nearly five years now and it has completely transformed and improved the quality of my sleep. The latest Eight Sleep model is the Pod 5. This is what I'm now sleeping on and I absolutely love it. It has so many incredible features. For instance, the Pod 5 has a feature called Autopilot, which is an AI engine that learns your sleep patterns and then adjusts the temperature of your sleeping environment across different sleep stages. It'll even elevate your head if you're snoring and it makes other shifts to optimize your sleep. If you'd like to try Eight Sleep, go to eightsleep.com/huberman to get up to $350 off the new Pod 5. Eight Sleep ships to many countries worldwide, including Mexico and the UAE. Again, that's eightsleep.com/huberman to save up to $350.","offset":794,"duration":76},{"text":"Andrew Huberman: I saw a paper recently that described a, and forgive me if this was one of your papers, I don't think it was, it described a pre-sleep meditation that one could do to significantly increase the amount of growth hormone that's released once one gets to sleep. And I thought, [Dr. Richie Davidson: That wasn't ours] and I thought this makes total sense, right? I mean it's it has to do with, I forget the sentence you wrote, but that how we exit one state impacts how we encounter the next one and perhaps even our trait within that next event of life. So we'll definitely get back to this when we talk about protocols because I think that people vastly underestimate the extent to which different let's call them meditations, for lack of a better word right now, how they can impact how we show up to work, how we show up to relating, how we show up even to sleep. And it's not just about being calm so you can fall asleep. Turns out this meditation that was described boosts growth hormone in a, you know, incredible way without altering some of the other features of sleep.","offset":870,"duration":71},{"text":"Dr. Richie Davidson: I saw that paper too, it wasn't ours, but yeah, super interesting. I agree. Yeah, so just to continue with the brain oscillations, I talked about delta. The next brain, the next faster brain rhythm is theta activity, which is roughly between 5 and 7 Hz. Theta activity is often seen during transition from wakefulness to sleep. And it's associated with these, as you were saying earlier, these liminal states. It's also been associated with certain kinds of meditation. Alpha activity is roughly between 8 and 13 cycles per second or Hz, and it's often characterized as quote relaxed wakefulness. Beta activity is typically defined as roughly 13 to roughly 20 Hz, and it's associated with activation. If there is a cognitive task that a person is engaged in, you will typically see increases in beta activity, particularly in the cortical regions that are engaged in those cognitive tasks. And then finally there's gamma activity. Gamma activity is especially interesting, we see that in meditators, long-term meditators. Gamma activity has as its peak frequency roughly 40 Hz. It is seen in a number of contexts. One of them is during what some have called insight. And insight is where I think most viewers have had the experience of working on a problem and all of a sudden they just have an aha moment and things sort of gel, they congeal, they come together. And there've been some clever experimental designs where investigators have created tasks that increase the likelihood of aha moments. They're sort of trivial in the experimental context, they're simple cognitive tasks where all of a sudden you just recognize the answer. It might be something like a crossword puzzle, and you're trying to get something, a word to fit, and suddenly you get the word. It comes in a moment and it's kind of an instantaneous recognition. And you typically would see a burst of gamma oscillations that is very short - the average duration would be around 250 milliseconds, really short. What we see in these long-term meditators is the prevalence of high amplitude gamma activity that goes on for seconds and minutes. When we first saw that by the way, and there's a lot of interesting history here, but we first reported this in 2004 with very long-term meditators where the average lifetime practice of this group was 34,000 hours. Listeners can do the arithmetic later, but 34,000 hours is a big number. And in these practitioners we saw these really high amplitude gamma oscillations that actually were visible to the naked eye, which is unusual for this kind of measurement. And in the original paper which was published in PNAS in 2004, we actually had a figure of the raw EEG from one practitioner just to illustrate how prominent it is that you can see it with the naked eye. And we've subsequently replicated that, it's been replicated by others. We've also seen that this gamma activity is found during slow wave sleep. It's actually superimposed on delta oscillations.","offset":941,"duration":225},{"text":"Andrew Huberman: Is there any evidence that meditation can actually replace sleep or that it can offset some of the negative effects of sleep deprivation, mild sleep deprivation?","offset":1166,"duration":9},{"text":"Dr. Richie Davidson: This is a great question. I think about it a lot. I don't think that the evidence is is clear on this at all. And I'll give several examples. First, the Dalai Lama, who probably meditates more than anybody I know, he has a practice of literally doing approximately four hours of meditation every day and he's been doing that for more than 60 years.","offset":1175,"duration":23},{"text":"Andrew Huberman: I'm reassured by that. If you told me the Dalai Lama meditates for, you know, 40 minutes a week, I'd actually be concerned about the role of Dalai Lama, so that the title, you know.","offset":1198,"duration":10},{"text":"Dr. Richie Davidson: So that, and he very proudly says, \"I sleep nine hours a night.\" Wow, okay. Nine hours a night and he gets nine hours of sleep, that's his regular sleep, and he gets it all the time. And you know, I don't know whether he would say he needs it, but he gets nine hours a night, and he's very proud of that. Okay. That's one counter-example. You know, myself, I have done a bunch of sleep science with collaborating with some sleep researchers, and many years ago one of these people said to me, \"Richie, you really should give up an alarm clock, just don't use an alarm clock anymore.\" And I was getting at that time between five and a half and six hours a night of sleep, and I gave up the alarm clock and my average length of sleep increased by about 30 to 45 minutes. And I feel much better. Oh sure. Especially since the extra sleep tends to be toward morning, you're getting more REM sleep. But the difference for me between five and a half and six or six and a half is in terms of just subjective well-being and focus, etc. is tremendous.","offset":1208,"duration":71},{"text":"Andrew Huberman: Slightly related question: if one were going to choose to meditate and had the option to do it at a sort of liminal state between let's say being awake and going to sleep at night or between sleep and what shortly after one wakes up and starts the day versus in the middle of the day or in the middle of the morning, is there any advantage to placing meditation in one of these what I'm calling liminal states or transition states between sleeping and awaking in either direction?","offset":1279,"duration":30},{"text":"Dr. Richie Davidson: I would say probably for most people yes is the answer, but I think there's a lot of individual variability. In general, I would say it's useful to meditate when you're feeling most awake and less sleepy. Sleepiness is an important obstacle in meditation and there's a lot to say about that.","offset":1309,"duration":23},{"text":"Andrew Huberman: Yeah, I'm surprised to hear that. I expected you to say that one should meditate at a time when the brain is closest to sleep because you want to be in a state of mind that's less about controlling your thoughts. But then again, I could also see an argument for how meditation involves a redirect of attention. So let's actually drill into this a bit. What is the meditative state that one is seeking for quote-unquote effective meditation?","offset":1332,"duration":26},{"text":"Dr. Richie Davidson: Yeah, so first let me say that just like there are hundreds of different kinds of sports, there are hundreds of different kinds of meditation. They don't all do the same thing, they have different effects on the brain and the body. And so I think it's really important that we not lump all of meditation together. So that's one really important thing.","offset":1358,"duration":25},{"text":"Andrew Huberman: Can we divide it up? So for instance, if we were going to draw the parallel with exercise, and maybe we'll do that several times today. We can broadly lump exercise into cardiovascular and resistance training. There's also mobility work and then there's a bunch of other stuff. With meditation can we create some broad bins? And what are those broad bins? And then we can go into specific practices.","offset":1383,"duration":25},{"text":"Dr. Richie Davidson: Yeah, so yes, we can create some broad bins. So and we've done that, we've published some papers that offer typologies for classifying different meditation states. So one kind of meditation we call focused attention meditation. And focused attention meditation is where you are narrowing your aperture of awareness to a specific object. It could be an external object, it could also be an internal, it could be for example your respiration, it could be a sound. And there is a narrowing of the aperture. And this is all broadly within the category of practices that we would say are cultivating aspects of awareness. So another awareness practice is what we call open monitoring meditation. And open monitoring is where there is no specific focus but rather the aperture is broadened. And there is no specific intention to focus on any one thing or another. The invitation is to simply be aware of whatever is arising as it arises. One of the aspirations there or the invitations is not to try to get rid of thoughts because our minds and our brains are built to generate thoughts. So there's no goal if you will to get rid of thoughts, but rather to if thoughts arise, that's another object that you can be aware of. You know, we talked about sleep and sleepiness and that earlier, you can even, you can be aware of being sleepy, you can be aware of being distracted. The goal if you will is not to change or to fix anything. If you will, the invitation is to shift from a mode of doing to a mode of simply being.","offset":1408,"duration":116},{"text":"Andrew Huberman: I want to talk about this thing about doing to being because the language can sound a bit mystical and vague to people. But as a long-time practitioner of Yoga Nidra, which I've talked a lot about on this podcast, there's this instruction inside of Yoga Nidra to shift from thinking and doing to being and feeling. [Dr. Richie Davidson: Exactly.] Which is beautiful language, poetic, etc. but also as neuroscientists and for the general public, I think it might be useful for us to just maybe just double click on that for one second. As a neuroscientist I think of thinking and doing as okay, doing is action, so that would the opposite of that would be stop moving the body. Thinking - well, there's a whole discussion to be had about what is thinking in neuroscience - but certainly you wouldn't want to plan, you wouldn't want to be ruminating on the past. Presumably you would want to be more in a state of sensation and perceiving what's happening right now. So is that an appropriate breakdown or is it wrong, is it insufficient? I'm not trying to score an A with the professor here, I'm just trying to figure out when we hear \"move from thinking and doing to being and feeling,\" what does that mean in terms of actionable steps that people can take?","offset":1524,"duration":86},{"text":"Dr. Richie Davidson: Yeah, so I think that the way you describe it is basically accurate with a little bit of perhaps tweak. So if when if one is invited to do this and one finds oneself ruminating or planning for example, which is supposedly an activity you're quote not supposed to be doing, you know, rather than trying to stop it, it's simply to be aware of it. Wow, I'm now planning or I'm now ruminating about something that happened in the past. What really is most important is the invitation not to change it, not to actively try to shift it, but to simply be aware. And one of the conjectures in all of this is that there's so much going on under the hood that we're typically not aware of. You know, our lives are moving at such a pace that the information that is transpiring is occurring at such a rapid rate that we are typically aware of only a small fraction of that. And this is a practice that's inviting you to simply be aware of that and and and you know, not doing is a helpful kind of thing because if we're if we're acting in the world, we obviously need to navigate and there are things we obviously need to do to be safe and to protect ourselves and so forth. And so that will engage other mechanisms.","offset":1610,"duration":101},{"text":"Andrew Huberman: I'm interested in the possibility, or maybe you've seen this in the data, that there are at least two different types of people. People who for instance go through life feeling, doing, being, thinking and projecting things out into the world, or maybe they're quiet people and they don't project much out into the world but they're just doing their thing and they're not thinking about their thinking. They're not thinking about their doing, they're just doing. We know people like that. Then there are people who are always multi-tracking, like uh, you know, they're self-conscious, they're very self-aware. And I'm wondering whether or not a form of meditation where somebody arrives at the meditation very self-aware, like oh, there's my thought about that again, there's my thought about that again, and working perhaps on not judging it, could be beneficial. But perhaps what that person quote-unquote needs or would benefit from was just being in a state of a freedom from their self-monitoring, whereas the other person perhaps could afford to be a little more self-aware and realize, oh, you know, I'm in this mode where and see their thinking a little bit.","offset":1711,"duration":72},{"text":"Dr. Richie Davidson: Totally, and and you're naming something super important. And you know, I think that the way you characterize the second person who is more self-aware, there's more than just self-awareness in your description. There's a kind of holding back. It's not just monitoring, but there's a kind of suppression almost. It's a lot of work. [Dr. Richie Davidson: It's a lot of work.] And it kind of and it could be stifling for their creativity. Absolutely. We had my friend David Choe on the podcast, now we're friends, that was actually the first time we had met but we've become good friends and he's a brilliant artist, brilliant artist. And he talks about how the best art comes from just forgetting what anyone thinks or wants. Rick Rubin talks about this, just getting the audience out of your mind and just letting it flow through you. And I think great artists do that. And it's what we pay money to see. We want to see that form of expression. We don't want to see the self-monitoring artist. [Dr. Richie Davidson: Yeah.] That's great. And I totally resonate with that. And there is a phrase in the Tibetan Buddhist tradition that is called \"undistracted non-meditation.\" Undistracted non-meditation. And that's said to be the highest form of meditation, where you just drop all the crap, you know, all the techniques, all the control, all the tightness.","offset":1783,"duration":95},{"text":"Andrew Huberman: This is my goal in life. Watch out folks, if this ever happens.","offset":1878,"duration":4},{"text":"Dr. Richie Davidson: But you're totally aware. You're fully aware. But there's no artifice, there's no uh, it's just complete freedom. And and there are, you know, I think there I've had the the honor of just hanging out with some people who I think are really in that as a trait. That's who they are. Rick Rubin's like that. He's a close friend and I can tell you I've spent a lot of time with Rick. And how he appears to people and his kind of mythical status, I think a lot of people his magnetism is because that's real. He can be in very, very close proximity to things, online, in person, he can see all of it. He's in real touch with it, but he's still him. It somehow it doesn't invade him in a way that changes the way he shows up. He, you know, like if if we were to paint little beams of energy - now we're really sounding woo - coming out, there's stuff coming out, there's stuff going in and they're interacting, but they're not contaminating one another. Where they interact it just makes both things better. And that's a very, very rare trait.","offset":1882,"duration":74},{"text":"Dr. Richie Davidson: Yeah, I agree. You know, there's a term that I often use which, you know, I can talk about how we can define this more technically, but for lack of a better word, I call stickiness. And it's kind of an affective hysteresis, if you will. It's where you know, you're hanging on to emotions that may not be useful. You're carrying stuff from a previous experience into a current experience and it muddles things. And you know, our emotional lives are so infused with this kind of stickiness, but with like with Rick Rubin, or with other people who are showing this, there's no stickiness. There's no stickiness. And you know, that's a kind of of freedom that I think is very much what we're talking about as the trait manifestation of these kinds of practices.","offset":1956,"duration":64},{"text":"Andrew Huberman: It's interesting. I think a lot of people mistakenly use drugs to try and access that state. And I also think that we have a real as a species, as a culture but also as a species, we have a real affinity to people who can embody this freedom that you're talking about. Great comedians - like when Richard Pryor was on, you're just like, I mean you maybe he had a subscript in there, maybe he was devoting like 2% of his prefrontal cortex to monitoring but it just seemed like we call it flow, but we're in their flow, they're in ours, whatever it is. There's a powerful interaction there that there seems to be very little self-monitoring from the perspective of performing arts or comedic arts.","offset":2020,"duration":53},{"text":"Andrew Huberman: But for people who want to approach meditation, would it do you think it's useful at all to ask themselves before they go into the meditation, you know, are they in a are they in a mode of self-monitoring or are they in a kind of or are they feeling more free? More present to just whatever it is they're experiencing not questioning it. [Dr. Richie Davidson: Yeah.] And asking them for do you think it's useful in order to get the most out of a meditation practice? I guess what I'm getting at indirectly here is most meditation practices involve shifting from doing one thing to maybe you're walking, maybe you're open eyes, but typically I think people either sit or lie down, close eyes and start focusing on their breathing and trying to quote-unquote get present. [Dr. Richie Davidson: Although the kind of practice that I most often do is actually with eyes open.] Really? Oh, well then just tell us about that. What what would be a good uh, let's use the parallel to cardio again. I would say if somebody's really out of shape and wants to get in shape, I would say the first thing is take two 20-minute walks a day. And then we could talk about getting on a exercise bike and then maybe doing some resistance you start layering things in, right? But what would be the equivalent of the 2 20-minute walks a day for meditation?","offset":2073,"duration":81},{"text":"Dr. Richie Davidson: So this is the protocol question I guess. You know, I would say it's really important to start modestly and we often will ask a person, what's the minimum amount of meditation that you think you can commit to every single day and do it for 30 days consistently? [Andrew Huberman: 5 minutes.] Perfect. Whatever that number is, perfect. Start with that. And then the next question is, are you comfortable doing it formally as a seated practice or would you prefer to do it while you're walking or while you're doing another non-cognitively demanding activity? It could be commuting, it could be washing the dishes. There are lots of those kind of activities that we often do on a daily basis that you can actually intentionally use your mind in this way while you're also doing those activities. And by the way, we've shown - we actually have really good data on this - that at least for beginning meditators, it doesn't matter if you're doing it as a formal meditation practice or as an active practice. The benefits are absolutely comparable.","offset":2154,"duration":76},{"text":"Andrew Huberman: And what are those benefits?","offset":2230,"duration":2},{"text":"Dr. Richie Davidson: So if you do it for 30 days and you do it just for 5 minutes a day, you will see a significant reduction in symptoms of depression, symptoms of anxiety, and symptoms of stress. We've shown that repeatedly in randomized control trials. You'll see an increase on measures of well-being or flourishing, and we can talk about what those actually mean. You can even see, just with this amount of practice, a reduction in IL-6. IL-6 is a pro-inflammatory cytokine that is important in systemic inflammation. And with just this minimal amount of practice you see a significant reduction in IL-6 over the course of 28 days, five minutes a day. We've actually seen changes in the microbiome. And we've seen changes in the brain with just this minimal amount of practice. But the important point is that you're doing it every day. When people ask me what's the best form of meditation that they should do if they're just beginning, I say the best form of meditation that you can possibly do is the form of meditation that you actually do. So figure out what that form of meditation is and then stick to it. Do it every single day.","offset":2232,"duration":81},{"text":"Andrew Huberman: I love this. I actually am going to challenge our podcast audience to five minutes a day for 30 days. I'll put something out on social media. Rob, please remind me to put something out on social media to do five minutes a day for 30 days because what you describe are significant health effects. And as you described them, it made me remember this set of experiments from neuroplasticity. Do you mind if I share these? Because I have a this is a theoretical/practical question as we move into these protocols. But before we do that, what what should we call this protocol? It's the Richie Davidson five minutes a day. Richie's five meditation. I'm going to start that. Later I'll share what I've been doing but it's not even that. I've been doing 10 breaths upon waking. Ten breaths before I even get out of bed. I'm like if I can just do 10 breaths of focused meditation before I get out of bed, the whole day will go better and it and it tends to.","offset":2313,"duration":68},{"text":"Andrew Huberman: There's this wild set of findings in the neuroplasticity research that most people don't talk about because it's very inconvenient for neuroscientists. We're all familiar with the enriched environment thing where you give rats a bunch of toys or mice a bunch of toys or monkeys a bunch of toys, and the idea would be if you give kids a bunch of toys or listening to Mozart that their brains will develop more. You see more physical connections, you see improved cognition, etc. etc. A really smart guy down at University of California, Irvine, Ron Frostig, did an experiment where he said, \"Maybe this is all backwards. Maybe the normal cages they live in without all these toys are just deprived environments.\" And it turns out that's probably the case. So all this enriched environment stuff, it's not that it's BS, it's just that the experimental conditions were so deprived that what you had was most animals just deprived in a certain way, then you give them what they needed naturally and all of a sudden you saw more connections etc.","offset":2381,"duration":70},{"text":"Andrew Huberman: If we applied that to meditation - something that we think of as kind of an enriched mental environment - okay, I'm going to now do this exercise, I'm going to do five minutes a day or 10 or 20. We think of it as kind of adding exercise, but riding a treadmill, doing resistance training, I mean we used to just farm and go get water and do things. So in some sense all of that is a replacement for a quote-unquote deprived environment. So is it possible that what you're describing is not something that people developed over time, but rather something that was core to our experience as humans and that the brain needed, but that with the advent of technologies and busyness or whatever we've gotten away from? And so when you talk about doing 5 or 10 or 20 minutes of meditation a day and seeing all these health effects, what we're doing is we're actually just putting back what needed to be there in the first place. This is like the equivalent of you getting your 30 minutes more sleep because alarm clocks weren't really a thing 2,000 years ago. Does that make sense?","offset":2451,"duration":69},{"text":"Dr. Richie Davidson: It makes sense, but you know, and I think that there's an element of truth to it, but I also think that there's some additional discussion that we should have about it and dialogue. So first of all, these practices have been around for, you know, 2,500 years or more. It's not like they've been invented in the modern era to deal with the the separation that has occurred between humans and the natural world that is a distinctly modern kind of invention. So that's one thing. The second thing is that yes, I agree with you that the characteristics that we're talking about as traits that are outcomes of these practices, there many ways to get there. And there are probably natural ways to get there that don't require meditation. And in fact, you know, when we in our early days we interviewed these practitioners around Dharamsala, India who were spending 30 years in retreat. They're called hermit monks. And you know, there you have to hike for three hours to find their cave. And we interviewed these these people. You know, they they told us, \"Well, you know, I need to meditate, but many others are just born or they're just naturally have these qualities. They don't need to meditate as much as me. I'm just a simple, you know, poor monk who really needs to do this because I'm inferior to those people,\" if you will.","offset":2520,"duration":90},{"text":"Dr. Richie Davidson: And it's a kind of modesty but also, you know, there may be some truth to that. And so I think that that is is real. But I also think that the qualities like for example, kindness. I believe, and this is the subject of this new book that I wrote with my colleague Cortland Dahl, \"Born to Flourish,\" qualities like kindness are innate. They are part of our innate repertoire. But in order for them to be expressed, they require nurturing. And it's very similar to the way scientists talk about language. Language is innate, I think most scientists would agree with that, but we know that there have been case studies for example of feral children who are raised in the wild and they don't develop normal language. So in order for the language to develop normally it requires nurturing of some kind. And kindness is the same thing, it requires nurturing in order for it to be expressed. And similarly for other qualities that we're cultivating when we meditate. I think those qualities are innate, but they require nurturing. And and in certain cases, I think that in order for those qualities to really be expressed at high levels if you will, intentional nurturing may be required for at least the vast majority of people. There may be, you know, statistically very rare people who emerge who are like this from the start for whatever reasons.","offset":2610,"duration":90},{"text":"Dr. Richard Davidson: reason. But for most of us, I think uh this kind of nurturing is important.","offset":2700,"duration":8},{"text":"Andrew Huberman: As many of you know, I've been taking AG1 for nearly 15 years now. I discovered it way back in 2012, long before I ever had a podcast, and I've been taking it every day since. The reason I started taking it, and the reason I still take it, is because AG1 is, to my knowledge, the highest quality and most comprehensive of the foundational nutritional supplements on the market.","offset":2708,"duration":22},{"text":"Andrew Huberman: It combines vitamins, minerals, prebiotics, probiotics, and adaptogens into a single scoop that's easy to drink and it tastes great. It's designed to support things like gut health, immune health, and overall energy, and it does so by helping to fill any gaps you might have in your daily nutrition. Now, of course, everyone should strive to eat nutritious whole foods. I certainly do that every day.","offset":2730,"duration":21},{"text":"Andrew Huberman: But I'm often asked if you could take just one supplement, what would that supplement be? And my answer is always AG1, because it has just been oh-so-critical to supporting all aspects of my physical health, mental health, and performance. I know this from my own experience with AG1, and I continually hear this from other people who use AG1 daily. If you would like to try AG1, you can go to drinkag1.com/huberman to get a special offer.","offset":2751,"duration":26},{"text":"Andrew Huberman: For a limited time, AG1 is giving away six free travel packs of AG1 and a bottle of Vitamin D3K2 with your subscription. Again, that's drinkag1 with the numeral one dot com slash huberman to get six free travel packs and a bottle of Vitamin D3K2 with your subscription.","offset":2777,"duration":22},{"text":"Andrew Huberman: Why do you think it is that so many people find it challenging to maintain a meditation practice? I mean, 5 minutes a day is nothing. 10 minutes a day is barely anything even for the very busiest of person. And the positive effects that you describe—and we could also layer in reduced stress, anxiety, lower resting heart rate, uh increase uh you know, um feelings of well-being and on and on—I mean, there there are just so many great studies now, including, like you said, you know, double-blind trials. I mean, it's it's incredible.","offset":2799,"duration":39},{"text":"Andrew Huberman: Um, so why do you think it's so hard for people to maintain this practice of just saying, \"Okay, you know what, I'm going to just go into this atypical state. It's it's not being stimulated by anything in my environment. I have to do this internally. There aren't gyms to go to for this.\" although, I mean there are breathwork classes and things like that, but people don't tend to stick to it. That's the challenge.","offset":2838,"duration":26},{"text":"Dr. Richard Davidson: Yeah, so I do have a theory about it, which I'll share. But before I do that, let me just say that uh I often use the analogy of brushing your teeth. When when humans first evolved on this planet, none of us were brushing our teeth. And somehow, a very large swath of humanity has learned to brush their teeth every day. It's not part of our genome.","offset":2864,"duration":26},{"text":"Andrew Huberman: I think most people brush their teeth so that their breath isn't bad. I think they like the idea that their teeth look cleaner and they get less um gum disease, et cetera. But all the scary stuff is actually very uh ineffective public health messaging. I mean, that's my guess.","offset":2890,"duration":23},{"text":"Dr. Richard Davidson: Yeah, so actually that's quite interesting, um that that view. But getting back to your question, why do people find it so hard? So there was a study published in *Science* not too long ago by a group of social psychologists. And um it was a study of, quote, boredom. Um and what they did essentially in this study, the core of it was they took people into the lab and they said, um \"We had a little problem and you guys are going to have to wait for like 15 or 20 minutes before the experiment starts while we fix some piece of equipment.\" And they were in a waiting room.","offset":2913,"duration":42},{"text":"Dr. Richard Davidson: There were magazines and books around and they also said that there's um you know, social psychologists are really good at creating these um scenarios. Um and so uh another experimenter came in and said, you know they're from another research group and they understand they have to wait a little while and we have another experiment that you can do in the meantime and it involves um receiving electric shocks. Um and of course it's completely voluntary, you are free to participate or not.","offset":2955,"duration":38},{"text":"Dr. Richard Davidson: And the bottom line is that these—particularly male undergraduates in the United States—preferred to shock themselves than to sit alone and not do anything. It's a robust finding. Uh people could not sit without doing something is the bottom line.","offset":2993,"duration":25},{"text":"Dr. Richard Davidson: And the reason, I think, is that once we actually begin to inspect our own minds, most people are frightened at the chaos that they see. One of the things we found when we look at a very in a very granular way is that when people start to meditate, we see a statistically reliable increase—increase—in anxiety in the first week.","offset":3018,"duration":34},{"text":"Andrew Huberman: Interesting.","offset":3052,"duration":1},{"text":"Dr. Richard Davidson: And that's often when people say, \"I can't do this. It's making me crazy.\" Um and you know, what we tell them is that's exactly you're doing exactly the right thing, you're you know you're noticing the chaos in your own mind.","offset":3053,"duration":17},{"text":"Andrew Huberman: This is the soreness that comes from a new exercise program.","offset":3070,"duration":3},{"text":"Dr. Richard Davidson: Yeah, exactly.","offset":3073,"duration":1},{"text":"Andrew Huberman: But people know to associate the soreness with, \"Okay, the exercise was effective, it's going to lead to an adaptation.\"","offset":3074,"duration":8},{"text":"Dr. Richard Davidson: And what we haven't changed the the narrative yet about this, but what we're trying to, where we say, \"It this is great that you're feeling anxious, it's exactly what you should be feeling.\"","offset":3082,"duration":13},{"text":"Andrew Huberman: Forgive me, I'm I'm doing all this in real time, so if I if I'm slow, um there's a reason. The analogy to exercise feels ever more important now because thankfully the narrative has been embedded in people's minds that you lift objects or you cycle or run or row or swim, et cetera, to stimulate an adaptation.","offset":3095,"duration":28},{"text":"Andrew Huberman: I think that the exercise scientists, the fields of health and wellness, whatever it is, has been very effective in getting the message out that the burn in your muscles is the thing that's going to lead to an easier run the next time, to more fitness, more longevity, more well-being, et cetera. But it's discomfort in the moment.","offset":3123,"duration":24},{"text":"Andrew Huberman: For a long while now, I've been trying to convince people because it's true that the agitation that one feels trying to solve a problem or read a hard uh page or passage in a book, the one that you have to return to three times that you can't wrap your head around, that that agitation is the stimulus for neuroplasticity. If you could just breeze right through it, the brain has no reason to change. It's not stimulated to change.","offset":3147,"duration":34},{"text":"Andrew Huberman: I can after all just do the thing you're trying to do. So it becomes sort of a duh when you compare when you look at exercise or you look at um cognitive development. But somehow when it comes to meditation, maybe we can accomplish this today, I think you're doing this for us, just knowing for me, just knowing that in the first week anxiety is going to go up but that's the equivalent of lactate accumulating in the muscles, of of the burn—it's the lactate of the mind.","offset":3181,"duration":34},{"text":"Dr. Richard Davidson: Yeah.","offset":3215,"duration":1},{"text":"Andrew Huberman: Thank you.","offset":3216,"duration":0},{"text":"Dr. Richard Davidson: Yes.","offset":3216,"duration":1},{"text":"Andrew Huberman: Perfect. I believe that languaging and messaging is so critical to get people to adopt practices that require this discomfort-adaptation loop that needs to be repeated over time. I love that. I knew we'd get someplace in that in that one. Thanks to you. So glad you're here. So week one, five minutes a day, expect and embrace the anxiety. Is it the thing that's going to produce the adaptation?","offset":3217,"duration":37},{"text":"Dr. Richard Davidson: I think it's contributing to it, yes. Um and you know it's also being aware of the anxiety without being hijacked by the anxiety, without being lost in the anxiety. So being able to see the anxiety um as it's arising um and that's um you know this is training in meta-awareness. Meta-awareness is super important. I actually think meta-awareness is a necessary prerequisite for any kind of human transformation, mental transformation.","offset":3254,"duration":43},{"text":"Andrew Huberman: Um could you define it for us? Tell us a bit more about it. I'm very curious.","offset":3297,"duration":4},{"text":"Dr. Richard Davidson: Yeah, so I would say meta-awareness is the faculty of knowing what our minds are doing. And to some listeners that may sound a little strange, but how many of you have had the experience of reading a book where you might be reading each word on a page and you read one page, a second page, and after a few minutes you have no idea what you've just read? Your mind is lost, it's somewhere else.","offset":3301,"duration":33},{"text":"Dr. Richard Davidson: But then you wake up. The moment you wake up is a moment of meta-awareness. And it turns out that that's a trainable skill. And that is one of the really important prerequisites um for all other forms of training, of mental training.","offset":3334,"duration":30},{"text":"Andrew Huberman: Do we know where this meta-awareness resides in the brain? Is it prefrontal cortex?","offset":3364,"duration":6},{"text":"Dr. Richard Davidson: You know, it's a network of um prefrontal cortex, anterior cingulate, um insula, um uh I think those are all structures that are participating in meta-awareness.","offset":3370,"duration":16},{"text":"Andrew Huberman: It's interesting because I feel like as we were discussing earlier, people crave forgetting about themselves and just being in experience, it's just such a powerfully and I think positive, seductive thing. I often think about, you know like I at a party, dancing, like like people who can just dance and enjoy themselves versus people who are self-conscious about how they're dancing. Even people who are good at dancing.","offset":3386,"duration":33},{"text":"Dr. Richard Davidson: You can be meta-aware without being awkwardly self-conscious, if you will. So um you know, you talked earlier about flow. Uh I didn't jump in then, but flow can occur with or without meta-awareness.","offset":3419,"duration":18},{"text":"Andrew Huberman: Really?","offset":3437,"duration":0},{"text":"Dr. Richard Davidson: Yes. Um a lot of flow, I think, occurs without meta-awareness. So you know, Csikszentmihalyi who first studied flow, he studied rock climbers. And like a rock climber who is, I mean think about this, why do people do stuff like rock climbing? I think that the reason why people do stuff like that is to produce this state of flow where um most of those kinds of states of flow I think are states of flow without meta-awareness, where you're completely absorbed in the activity.","offset":3437,"duration":48},{"text":"Dr. Richard Davidson: And for a rock climber, if there's even a momentary lapse in attention, it could be potentially lethal. Uh and so by arranging one's physical environment in that way, you are basically forcing uh the default mode to be suppressed. Uh and the default mode is a mode that we know is associated with a lot of self-referential thought. And self-referential thought often is anxiety-provoking.","offset":3485,"duration":40},{"text":"Dr. Richard Davidson: Um and so this is a way to transiently suppress the default mode. But flow can also occur with meta-awareness. Um and so and it doesn't diminish the quality of the flow. And one analogy that we can use is in a movie theater. I mean viewers have had the experience of being in a movie theater and I'm sure people have had the experience of being in a movie theater where you're so engrossed in the movie that you may actually you're not aware that you're in a theater and you may not be even aware that you're watching a movie. You're so you are totally absorbed in the plot.","offset":3525,"duration":56},{"text":"Dr. Richard Davidson: And we've actually come up with a term to define that and we call it \"experiential fusion\" where you're fused with the experience. And that is a kind of the analogous to flow without meta-awareness. But imagine being in the movie theater where your your attention is riveted and there's absolutely no lapse in attention, but in the kind of penumbra of awareness, you are aware you're in a movie theater, you're aware that you're watching a movie, but that doesn't diminish the quality of your attention.","offset":3581,"duration":55},{"text":"Andrew Huberman: I want to uh ask about this thing about chaos, noticing the chaos of one's mind, because you said that sort sits at the seat of the anxiety that people will feel when they first start to meditate. Now everyone knows in the Richie meditation of push through the first week, expect the the lactate of the mind, push through it. I love that so much, thank you.","offset":3636,"duration":30},{"text":"Andrew Huberman: The idea that the mind is chaotic and getting comfortable with that and not reacting to it, not feeling like we have to get away from it, um we've heard this before, but I think it's somewhat of a novel concept to me to think that a goal of meditation is to be able to see that and sit with it, not necessarily eradicate it. You know I think you said you know the Dalai Lama. I think for most of us we see the Dalai Lama and other monks in robes and you said he sleeps nine hours per night and he's meditating four hours per day and we think, \"All right, he looks pretty blissed out and that's great for them.\"","offset":3666,"duration":45},{"text":"Andrew Huberman: Do you think he has chaos in his mind? Is the idea that extreme meditators or even, you know well-practitioned meditators are free of the chaos or that they're just comfortable with the chaos?","offset":3711,"duration":16},{"text":"Dr. Richard Davidson: I would say that um it's a developmental process that changes longitudinally. So initially there's a lot of chaos and I think it gradually subsides. I don't think it it's like a step function. I think it really occurs gradually over time and the chaos just sort of naturally diminishes.","offset":3727,"duration":28},{"text":"Dr. Richard Davidson: Um but that's a long-term process. Uh and I think for most of us, uh there's always going to be some chaos, uh but part of the chaos also is I think a source of creativity. And you know, when we talk about meta-awareness and awareness of all that's going on in our mind, you know I often give my students the the permission to I tell even if they're not meditators, to just spend a couple hours a week inspecting your mind. Just inspect your mind.","offset":3755,"duration":44},{"text":"Dr. Richard Davidson: Pay attention to what's going on in your mind. Don't do stuff outside, but and and if you come up with some interesting thought, write a little note to yourself as you're doing this, you know not a lot of words, but just a note to remind you when you're finished with this session. Um and my I have the conviction that there's a lot of creative work that humans do on a regular basis that's kind of like dreams.","offset":3799,"duration":33},{"text":"Dr. Richard Davidson: Most people don't remember their dreams, but they occur reliably. And I think that there's a lot of creative thought that occurs on a regular basis but we just don't pay attention to it and we we forget it just like we forget our dreams. But if we have the invitation to really inspect our mind in that way, I think um this chaos actually uh often can contain the seat of real creative insight that potentially could be valuable.","offset":3832,"duration":49},{"text":"Andrew Huberman: I do too. I mean, I wake up every morning with at least one idea from the transition from sleep to waking. Sometimes it's from a dream. I often will record my dreams as voice memos. After I die, if somebody ever finds these voice memos, they're they're so crazy. Every once in a while I'll try and listen to one, I'm like, \"This is crazy,\" but I don't want to forget things and sometimes I don't want to wake up and turn the lights on and I'll go back to sleep.","offset":3881,"duration":26},{"text":"Andrew Huberman: So I'll just record something in the voice memo, sometimes write it down. I think there's so much learning to be had from what's coming up from the unconscious mind in dreams, but also just having a mode of capture during the day. Some way to just capture the things that spring to mind. The great Joe Strummer from The Clash, he said this, he said you know, if you are walking along and an idea comes to mind, you have to write it down because you think you'll remember it later but you will remember it in a form that is not nearly as potent.","offset":3907,"duration":35},{"text":"Andrew Huberman: He said something like that, that this is the mind throwing you ideas and and you got to you have to capture them.","offset":3942,"duration":7},{"text":"Dr. Richard Davidson: I love that. I think it's it's wise advice.","offset":3949,"duration":5},{"text":"Andrew Huberman: Friends of mine who are songwriters, poets, they they do this all the time. They're constantly writing things down that they may or may not develop something from, but they understand that there's information being like thrown up to the surface for them. And if you don't write it down or capture it in some other way, it's it goes, it's evanescent.","offset":3954,"duration":22},{"text":"Dr. Richard Davidson: I actually have—um I mean this may seem contrary to um views of how meditation is done—but when I meditate every morning, I actually have a a little notepad by my cushion and occasionally, I don't do this every session, but maybe twice a week, um I'll actually write down something during the meditation, one or two words just to remind me, because something comes up in my practice, um maybe an idea and I I want to remember it and I know also that I won't remember it after uh in in the same richness, and so I'll just jot jot it down and then go back to my practice.","offset":3976,"duration":51},{"text":"Andrew Huberman: Is meditation something that kids can do and benefit from? Has that been studied in a formal way?","offset":4027,"duration":7},{"text":"Dr. Richard Davidson: Yes, it's been studied. Um we actually developed a um what we've called a a \"mindfulness-based kindness curriculum\" for preschool kids.","offset":4034,"duration":12},{"text":"Andrew Huberman: Preschool?","offset":4046,"duration":1},{"text":"Dr. Richard Davidson: Preschool. And we've actually published a randomized control trial in a public school system of this curriculum. And the curriculum is available freely on our website in both English and Spanish. So if any teachers are out there or you know teachers and want to use it, please please feel free to to download it and and see how it is.","offset":4047,"duration":29},{"text":"Dr. Richard Davidson: But yeah, so it looks very different. So for example, what we do with a three-year-old, one of the exercises that they love is we ring a bell in a classroom and we have them listen, tell them, \"Listen to this sound and as soon as you no longer hear sound, raise your hand.\" And it's it's amazing to see this because you can get 25 three- and four-year-olds sitting perfectly still for around 10 seconds.","offset":4076,"duration":38},{"text":"Dr. Richard Davidson: But you know, they could taste it. There's a palpable, you know sense of of quiet in that 10 seconds and then they all raise their hand excitedly. But they can really taste it. And so I I do think it's possible. The other thing is—and this is something really important—there's something we've discovered empirically recently, which is that flourishing is infectious. It's contagious. Flourishing is contagious.","offset":4114,"duration":33},{"text":"Andrew Huberman: You explained what that means and how you study that?","offset":4147,"duration":5},{"text":"Dr. Richard Davidson: Yeah, so um uh in the example of you asked about meditating in kids and the reason I'm bringing up in this context is one of the best things I can think a parent can do for a kid is not to have the kid meditate, but meditate yourself. And just be with the child and be fully present, be connected, and really show up in that way and you will osmotically transmit through your demeanor um and your your interaction, you'll transmit these qualities to the child in a completely implicit way.","offset":4152,"duration":52},{"text":"Dr. Richard Davidson: And that's what we mean when we say flourishing is contagious. But how we studied it—so let me actually share one of the this is a finding that we're super excited about and it's not yet published, but it's um the paper is just under review. So one of the things we're deeply interested in these days is how can we scale human flourishing? So we're doing this kind of sector by sector.","offset":4204,"duration":41},{"text":"Dr. Richard Davidson: And one sector that we're doing a lot of work with is educators. And educators around the world and particularly in the US—but we've done this in in Mexico too, so it's not just US-based—but they're super stressed, they're not well-paid, and all of that. Um uh so we did a study with public school educators in Louisville, Kentucky. And um there are many reasons why we went to Louisville, but Louisville is a complicated school system, it's diverse, there are a lot of problems in it, and um it's a big urban school district, the Jefferson County Public School District in Louisville.","offset":4245,"duration":57},{"text":"Dr. Richard Davidson: And we did a randomized control trial with 832 educators in Louisville. And we had them use our Healthy Minds program, which is uh uh a um a digital offering which is freely available as the Healthy Minds program, uh where we had them cultivate four key pillars of well-being: awareness, connection, insight, and purpose. We can take a deeper dive into each of those after.","offset":4302,"duration":32},{"text":"Dr. Richard Davidson: But they practiced for around five minutes a day. The average was a little less than five minutes a day over the course of 28 days. And we measured standard outcomes like depression and anxiety and stress and measures of flourishing, and we find what we found in other studies, which is that depression and anxiety and stress went down and measures of well-being and flourishing went up.","offset":4334,"duration":30},{"text":"Dr. Richard Davidson: But the real kicker is that we by prior agreement had access to the um student-level data in the school system. So we were able to look at the performance of the students who were taught by teachers randomly assigned to the well-being training, and we compared them to students who are taught by teachers randomly assigned to a control group. The the students had no idea that there was any research going on.","offset":4364,"duration":44},{"text":"Dr. Richard Davidson: And what we found is that on standardized tests—this is in middle school children and the sample size for these students was around 13,000—uh and what we found is that the math standardized math scores of the students who were taught by teachers randomly assigned to the well-being training was significantly greater than the scores of the students who are taught by teachers randomly assigned to the control group.","offset":4408,"duration":30},{"text":"Andrew Huberman: Same curriculum.","offset":4438,"duration":1},{"text":"Dr. Richard Davidson: Identical.","offset":4439,"duration":2},{"text":"Andrew Huberman: So what do you think is being transmitted there? Is it that the teachers are calmer, therefore the students are calmer? Is it that the teachers are calmer, therefore they're clearer so the students are I mean, there are a lot of variables. And we don't need to isolate them. I mean, this isn't um we're not trying to do um you know, pharmacology here. Uh but what do you think could be going on?","offset":4441,"duration":22},{"text":"Dr. Richard Davidson: Yeah, I think everything you said is likely to be going on. I think the students are the teachers are are likely calmer, they're more connected. Uh the and what we know is that, you know it was interesting because we looked at reading scores and the the data for the standardized reading measure was in the same direction, but it wasn't as robust. The the biggest signal was in math scores.","offset":4463,"duration":33},{"text":"Dr. Richard Davidson: And we know that math performance is degraded by stress more than reading performance uh uh in this age group. And so it you know, could be as something as simple as the kids who were taught by teachers that went through the well-being training are simply calmer and less stressed when they take the exam. Uh and so their true competence is more likely to be reflected in the test uh and not have it degraded by this kind of added stress and anxiety.","offset":4496,"duration":37},{"text":"Dr. Richard Davidson: Um so this is, you know an illustration that flourishing is contagious in this way.","offset":4533,"duration":10},{"text":"Andrew Huberman: I would like to take a quick break and acknowledge one of our sponsors: Joovv. Joovv makes medical-grade red light therapy devices. Now, if there's one thing that I have consistently emphasized on this podcast, it's the incredible impact that light can have on our biology and our health. Now, in addition to sunlight, which I've talked about a lot on this podcast, red light, near-infrared, and infrared light have been specifically shown to have positive effects on improving numerous aspects of cellular and organ health.","offset":4543,"duration":33},{"text":"Andrew Huberman: These include faster muscle recovery, improved skin health, wound healing, improvements in acne, reduced pain and inflammation, improved mitochondrial function, and even improvements in vision. Nowadays there are a lot of red light devices out there. But what sets Joovv lights apart and why they're my preferred red light therapy device is that they use clinically proven wavelengths, meaning they use the specific wavelengths of red light, near-infrared, and infrared light in combination to trigger the optimal cellular adaptations.","offset":4576,"duration":29},{"text":"Andrew Huberman: Personally, I use the Joovv whole-body panel about three to four times a week, usually for about 10 to 20 minutes per session, and I use the Joovv handheld light both at home and when I travel. If you would like to try Joovv, they're offering up to $400 off select products for listeners of this podcast. To learn more, visit Joovv, spelled J-O-O-V-V dot com slash huberman. Again, that's J-O-O-V-V dot com slash huberman.","offset":4605,"duration":30},{"text":"Andrew Huberman: It's so interesting. And again, there I can think of so many different variables that could be at play. Um we did an episode—one of our most popular episodes of ever—uh with a guy named James Hollis. Are you familiar with James Hollis?","offset":4635,"duration":19},{"text":"Dr. Richard Davidson: No.","offset":4654,"duration":0},{"text":"Andrew Huberman: He's a probably by now 85-year-old Jungian analyst.","offset":4654,"duration":7},{"text":"Dr. Richard Davidson: Okay.","offset":4661,"duration":0},{"text":"Andrew Huberman: Brilliant guy. He wrote he's written a number of of books, *The Eden Project*, which is about um relationships and relating, *Under Saturn's Shadow* on the um about trauma and healing, just just an incredible soul, incredible human, incredible educator. And um I'm not alone in in believing that, just spectacular. And I said, you know he's a Jungian analyst, so I said, \"You know like what's the key to a really good life, like but can we talk protocols?\"","offset":4661,"duration":37},{"text":"Andrew Huberman: And he said something really interesting that I think will resonate uh with what you're saying and perhaps shed some light on what happened with these students and flourishing in general. He said, \"It's so important that we wake up each day and we suit up and we show up and we work. In school, in relationships, in life.\" He said, \"But it's also just as important that we take a short amount of time every day and get out of stimulus and response.\"","offset":4698,"duration":36},{"text":"Andrew Huberman: Because by getting out of stimulus and response—and I'm not being nearly as eloquent as Hollis—we come to know ourselves in a certain way that lets ourselves show up so much more effectively for everything else. And so maybe, just maybe what these teachers achieved is by sitting in this anxiety—because now I'm thinking about the lactate of the mind—they're doing a practice which lets them experience the anxiety, not respond to it.","offset":4734,"duration":29},{"text":"Andrew Huberman: They're getting out of stimulus and response.","offset":4763,"duration":3},{"text":"Dr. Richard Davidson: Exactly.","offset":4766,"duration":1},{"text":"Andrew Huberman: And perhaps in the classroom they're able to teach more. Teach more effectively because they're not paying attention to the things that don't matter. Mm-hmm. Or maybe it's because they're also paying attention to the things that do matter. They're signal-to-noise is higher, so to speak. Anyway, I couldn't help but reference the Hollis thing because to not do that would would be remiss. But also, you know here's a guy who's saying you got to go to work each day, this is essential to building a good life and you have to do all these things.","offset":4767,"duration":33},{"text":"Andrew Huberman: And he's also saying, \"But getting out of stimulus response is what makes you effective in everything\" and of course improves your self-understanding. And I think what you're saying, I don't want to put words in your mouth, but what I think you're saying when you talk about meditation is that it's a way of getting out of stimulus and response.","offset":4800,"duration":19},{"text":"Dr. Richard Davidson: Yeah, absolutely. I think that's a great analogy, yeah.","offset":4819,"duration":4},{"text":"Andrew Huberman: Well, he deserves all the credit for all of that, um you deserve all the credit for running all these experiments because I feel like what's been so frustrating over the years has been to hear how powerful meditation is but that for people in the West, um the word meditation brings up ideas of mysticism and um ancient things and people think, \"Well that's not for me. That's not going to benefit me now in this world.\" But I would argue we need it even more so now.","offset":4823,"duration":40},{"text":"Dr. Richard Davidson: I agree. I think that um and I think that the divisiveness and polarization that is just eating away at our society is um underscores the the critical importance of this. I think it's needed now more than ever before in human history. And I think that it will, you know with just modest amounts of practice and and one of the other um you know kind of slogans that we think is really important is that it's easier than you think.","offset":4863,"duration":35},{"text":"Dr. Richard Davidson: It really is. It it 5 minutes a day has a measurable impact. And so I think that if we really take this to heart, uh you know if everyone practiced for 5 minutes a day, I have the strong conviction that this world would really be a different place.","offset":4898,"duration":22},{"text":"Andrew Huberman: Oh, absolutely. I I think the challenge is convincing people and and that's you know, you're doing it, we're trying to do that little by little. I mean, for a zero-cost tool, it's it's just outsized positive effects. I think most people come to the table because it will lower their blood pressure, they hear that it will reduce their stress, maybe make them more effective, make them smarter, sleep better.","offset":4920,"duration":34},{"text":"Andrew Huberman: But there are also the higher-order effects um that people talk about, being gaining some understanding of consciousness and what it may or may not be. When do those effects tend to arise? Uh if they ever do? Or does is it true that by meditating, by getting out of the stimulus and response and just watching one's thoughts and not responding to them and just non-judgment, that we can actually gain some fundamental insight into how our minds work?","offset":4954,"duration":34},{"text":"Dr. Richard Davidson: I do think that that's possible and I think that it does occur and um you know I think that um if we're really good scientists, um there there is um an important element of humility uh as we approach this uh that underscores really how little we know. Um and I think that these kinds of practices help us tap into something that I think is part of what it means to be a human being um and and part of it is honestly, um you know we can use the words \"spiritual\" in some way.","offset":4988,"duration":52},{"text":"Dr. Richard Davidson: Um and uh or \"transcendent\" and by that I mean something connected to something larger than oneself. And I know that this is getting into a little bit of woo territory um and uh uh but people do have a taste of this and it helps to give their life more meaning and and to infuse it with a kind of purpose that um I think is really beneficial.","offset":5040,"duration":46},{"text":"Andrew Huberman: I wonder—and I'd love your thoughts on this—whether by doing meditation and seeing that the mind is chaotic and that it's difficult to control and that perhaps the best thing we can do is just observe and not respond to it but not try and control it, that inevitably in one's meditation practice that the reality surfaces that we're all going to die. And I think for a lot of people the fear of death is terrifying.","offset":5086,"duration":41},{"text":"Andrew Huberman: I mean, it's inevitable and it's terrifying. And I do sometimes feel that a lot of the the stuff in the world that we're offered, whether or not it's drugs or alcohol or excessive work or whatever, just all the stuff is um that a deeper layer of that offering is that it it distracts us from that reality. Because it's terrifying, right? I don't most any healthy person doesn't want to die.","offset":5127,"duration":35},{"text":"Dr. Richard Davidson: Although I don't think it's terrifying for all people and I think that it's this is actually one of the dimensions that is shifted by long-term meditation practice unquestionably.","offset":5162,"duration":12},{"text":"Andrew Huberman: Is it shifted because people come to some understanding of energy and the fact that they will likely become part of something else, or do you think it's that they can just accept the reality that we're here then we're not here?","offset":5174,"duration":16},{"text":"Dr. Richard Davidson: I think it's more the latter and also, um imagine that this is the last day we're living, right now.","offset":5190,"duration":9},{"text":"Andrew Huberman: Friday the 13th, of all days.","offset":5199,"duration":2},{"text":"Dr. Richard Davidson: Of all days, it happens to be Friday the 13th. Uh and you know, are we um are we showing up in a way that feels right for us? Um and making the most of our lives and not squandering the opportunity that we have? And if we can live every day in that way, uh it really will change, I think, how we approach our mortality.","offset":5201,"duration":28},{"text":"Dr. Richard Davidson: And I know for me personally, I mean we I'm not well, it I I feel very differently about dying today than I did like 15 years ago. It's that that's one dimension where there's been a dramatic shift.","offset":5229,"duration":21},{"text":"Andrew Huberman: Would you mind elaborating on that? How so? How did you feel about it 15, 20 years ago?","offset":5250,"duration":4},{"text":"Dr. Richard Davidson: Yeah, I was terrified, you know in the same way. I, you know had a family, I have two kids, I have all these, you know responsibilities and um I reflect on this. I really do. And um you know if I died today, I would feel like I've lived a very fulfilling life. Um and uh uh and I'm fine with that.","offset":5254,"duration":39},{"text":"Andrew Huberman: That's a great thing to be able to say. That's a great thing to be able to say. I don't think most people would probably be able to say the same wholeheartedly. Yeah. And you attribute some of that sense to meditation?","offset":5293,"duration":15},{"text":"Dr. Richard Davidson: Definitely, but it's been gradual. You know I've been at this my I my very first meditation retreat was in 1974. Um and I've been practicing daily ever since.","offset":5308,"duration":16},{"text":"Andrew Huberman: Every single day?","offset":5324,"duration":2},{"text":"Dr. Richard Davidson: Well, I may have missed, you know one or two days a year when I had a 6 a.m. flight, but other than that, yes.","offset":5326,"duration":8},{"text":"Andrew Huberman: And what has your practice um your most consistent practice been?","offset":5334,"duration":6},{"text":"Dr. Richard Davidson: You know my practice has changed many times over these the course of these years and very different traditions in which I've practiced um so.","offset":5340,"duration":10},{"text":"Andrew Huberman: What about time of day? Is it typically morning?","offset":5350,"duration":4},{"text":"Dr. Richard Davidson: Always been morning for me.","offset":5354,"duration":1},{"text":"Andrew Huberman: You get up, you use the bathroom, have a drink of water and start, or you go right into it?","offset":5355,"duration":4},{"text":"Dr. Richard Davidson: No, I get up um and I make myself these days a cup of strong black tea um and I drink the tea, which takes maybe 15 minutes, um and then I meditate.","offset":5359,"duration":13},{"text":"Andrew Huberman: Got it. Do you set a timer or a chime?","offset":5372,"duration":2},{"text":"Dr. Richard Davidson: Yeah, I do set a timer. And you know, I meditate at various lengths, but I my modal time sitting is about 45 minutes a day. Um sometimes it's longer, sometimes it's shorter but usually around 45 minutes a day. And maybe three or four days a week I do a really short practice at night, maybe 5 minutes before I go to sleep.","offset":5374,"duration":36},{"text":"Andrew Huberman: Since everyone that takes on the 5-minute-a-day 30-day meditation challenge will do it, um once they reach 30 days, would does it make sense to update that to a longer meditation, or would you just suggest that people stay with that as long as possible?","offset":5410,"duration":18},{"text":"Dr. Richard Davidson: What I would suggest is check in with yourself um and see how you're feeling about it and um how it's resonating with you and um uh and if you feel like you can't really do much more, just stick with 5 minutes a day and keep doing that. The important thing is to stick with a daily practice. And one of the things that um we talk about in this new book, *Born to Flourish*, is a lot of people have a really difficult time coming up with a being able to do this daily.","offset":5428,"duration":36},{"text":"Dr. Richard Davidson: And one of the things that we talk about based on our finding that it doesn't matter, at least in the early stages, whether you're meditating uh as a formal practice or doing it while doing other activities of daily living that are not demanding, like walking or commuting, you tie this to regular activities that you do every day, whatever those activities are. And we talk about this idea of social zeitgebers.","offset":5464,"duration":36},{"text":"Dr. Richard Davidson: A zeitgeber, as you know, uh is um an environmental event, a signal um that is that marks a in the classical literature a biological rhythm like um light is a zeitgeber um to set our biological rhythms. But we in the modern world we have social zeitgebers that are human-created zeitgebers. So eating, for example, is a zeitgeber.","offset":5500,"duration":29},{"text":"Dr. Richard Davidson: Um we eat typically at roughly similar times every day, at least most people. And that's an opportunity. Uh you do that every day, you can pair a little practice with that. Um and you know one of the practices that you can do, which I do every time I eat, virtually, unless I'm eating with someone and it's awkward. Um but I do it at home, is do a little appreciation practice. Spend just a um 30 to to 90 seconds reflecting on all the people it took to have food on your plate.","offset":5529,"duration":36},{"text":"Dr. Richard Davidson: Um and it also gives you a sense of interdependence. And when I sit down, you know and have my breakfast, uh it's a cue for me. It's a social zeitgeber. I do my appreciation practice every single time. Um and then you there are crazy things you can do like I have a cat at home. Um I'm the one who scoops the litter every night. I actually do that as a practice.","offset":5565,"duration":29},{"text":"Dr. Richard Davidson: Um uh and it it literally takes no extra time. I do it while I'm doing the the scooping of the litter. But I I honestly do this in in a very authentic genuine way. I reflect on, \"You know the cat really appreciates this, my wife appreciates this.\"","offset":5594,"duration":20},{"text":"Andrew Huberman: I bet.","offset":5614,"duration":1},{"text":"Dr. Richard Davidson: Um \"People who go into the room with the cat litter appreciate that it's clean and scooped on a regular basis.\" And you know, I just reflect on that intentionally. Um it doesn't take much, it's easier than you think.","offset":5615,"duration":18},{"text":"Andrew Huberman: Yeah, it's so interesting. I mean, I don't want to um contort the message you're you're offering because it's a powerful one about bringing awareness to the things that we have to do anyway and allowing that to make us more effective and happier and more present. But there's also this idea around disciplines, and the word discipline gets is kind of heavy, nobody really likes it because we got disciplined or something.","offset":5633,"duration":32},{"text":"Andrew Huberman: But uh I used to pride myself on working longer hours than everyone and and as the years have gone on, I pride myself in just uh consistency is my superpower. I may not show up with the most intensity every time, although sometimes, but intensity uh kind of waxes and wanes. But there's something about just showing up anyway and just doing it anyway that is so powerful. And I I sometimes wonder whether or not the mind is just it's our foe until we embrace that piece. It's kind of a little bit of what you're saying.","offset":5665,"duration":45},{"text":"Dr. Richard Davidson: Yeah. And I love the consistency uh theme and also the discipline. And yes, I think you're naming something real and important. And there's a delicate calculus uh that ranges between kind of um letting go and discipline. And each person, I think, falls at a different point in this continuum. Uh and what works for one person may not work for for another.","offset":5710,"duration":36},{"text":"Dr. Richard Davidson: You know, with regard to meditation, I always say that what's best for one person isn't necessarily what's best for others and we have to discover what works for us. Um you know what we do know is that in in terms of meditation that consistency is really important.","offset":5746,"duration":22},{"text":"Andrew Huberman: Yeah, I was never a particularly good athlete or bad athlete, but I've just been really consistent at exercise and I mean I play fewer sports these days than than I did, but just the continuing to show up uh allows you to be the person among your peers—not that it's competitive where you go everyone else seems to have quit and they're talking about how much this hurts and that hurts and you're like and all you really had to do was just kind of keep keep going.","offset":5768,"duration":23},{"text":"Andrew Huberman: And I sometimes think that the people that are max intensity and they you know it's like gold medal or bust, they're always the ones or often the ones that we don't hear from anymore, they're like gone. Uh burn out. Yeah. So I love the examples of the Dalai Lama and, you know the Michael Jordans of every domain. But I don't know, I mean I'm more interested in um being the person that at 50, 60 I mean, you're in your mid-70s, you look incredible, you're super vital, cognitively sharp, you're in shape, you're excited about life, you're not afraid of death, clearly you're onto something, you know.","offset":5791,"duration":40},{"text":"Andrew Huberman: So and I doubt it's just the black tea. I'm guessing it's to some extent, I mean you have all the other aspects of your life, but this consistency of meditation practice.","offset":5831,"duration":10},{"text":"Dr. Richard Davidson: Yeah, no I think it's been super important. I do think that the discipline that you're talking about is really important and it is part of it. Uh uh but again, I think we need to find the right balance for each person and initially it's really important to um have people embrace invite them to taste this with the lowest possible friction so that they can really uh experience the benefit and then it can gradually progress and and they can, you know um harness some discipline which eventually will be important.","offset":5841,"duration":52},{"text":"Andrew Huberman: I'd like to talk about online culture and social media just briefly because I don't want to demonize it...","offset":5893,"duration":9},{"text":"Dr. Richard Davidson: Yeah, so, um, these are, um, really complicated issues. I think that, um, you know, I certainly don't, um, in any way pretend to have the answer, but I do think that, um, we need to take digital hygiene seriously. And we need to figure out ways of, as part of standard school curricula, of educating our youth in how to change their relationship or how to be, to say it a different way, how to be in healthy relationship with their digital devices and the products and features that are available on those devices.","offset":5902,"duration":57},{"text":"Dr. Richard Davidson: Um, I have the conviction that it's a trainable skill. Um, but we need particularly in youth to start early before they get their first phone.","offset":5959,"duration":15},{"text":"Andrew Huberman: Is there any evidence that meditation because it allows somebody to sit with the lactate of the mind can also, um, afford someone less impulsivity and, um, sort of being less prone to getting hooked by the chaos of the world around them?","offset":5974,"duration":22},{"text":"Dr. Richard Davidson: Yeah, I, um, you know, I don't think there's any hard data on that, but I think it's a great question. I think it's actually empirically tractable. And I think it's really worth studying. My conviction is yes.","offset":5996,"duration":19},{"text":"Dr. Richard Davidson: Um, I think it's, um, it would be helpful, but the data don't exist.","offset":6015,"duration":9},{"text":"Andrew Huberman: What would an experiment like that look like? I feel like we should run that experiment.","offset":6024,"duration":6},{"text":"Dr. Richard Davidson: That would be cool, I'd love to collaborate.","offset":6030,"duration":3},{"text":"Andrew Huberman: Yeah, I feel like there's got to be established in-lab measures of impulsivity.","offset":6033,"duration":5},{"text":"Dr. Richard Davidson: Yeah, there are good measures of impulsivity. And actually with impulsivity, um, there, there are measures that go beyond self-report measures. They are behavioral measures of impulsivity, which may have more validity. And so it would be extremely interesting and, you know, with, um, device use and with, with a person's consent you can actually get backend data so you don't rely on self-report so it can be really, um, robust kind of evidence.","offset":6038,"duration":42},{"text":"Andrew Huberman: The word discipline comes to mind again and I think so many people when they hear discipline they think about doing certain things. Waking up at five, exercising, meditating, eating clean, etc. But to me the most interesting aspect of discipline are the don't dos. It's all the stuff you don't do.","offset":6080,"duration":28},{"text":"Andrew Huberman: You know we're in the Winter Olympics now and I haven't been watching it, I like the Summer Olympics, but um, inevitably when they do the Olympics they interview the people who win gold medals or they'll do a day in the life of and they'll say you know um, they wake up at 5 a.m. and then they train. And they always want to say what do they eat? You know they go well I have four eggs and my oatmeal or whatever it is. Um, what they really need to show is all the things they don't eat. Right because sure what they eat is interesting perhaps, but far more relevant to their performance is all the things they don't eat.","offset":6108,"duration":37},{"text":"Andrew Huberman: Yeah. It's all the things they're not doing. And of course that makes for much less entertaining um, shows, so they don't do that. But I feel like the, the training that would be so valuable is the, to train up the no-go response.","offset":6145,"duration":16},{"text":"Dr. Richard Davidson: Absolutely. One of the things in my own life that I'm very aware of is an apropos not doing is not taking out my phone. Um, and I'm very intentionally aware of that. I actually do a little practice of feeling my phone in my pocket. And I really, um, will not take it out unless I actually need it.","offset":6161,"duration":31},{"text":"Dr. Richard Davidson: Um, I remind people when I have meetings at our center, you know, often it's just the cultural habit particularly with young people, you know, they put their phone on the table. And there are data showing that even if you have all your notifications turned off the simple presence of the device is enough to, um, impair the interaction in some way to have a discernable impact.","offset":6192,"duration":44},{"text":"Andrew Huberman: And cognitive ability. There's this really, I don't know if you've seen this study, it's pretty cool. They um, they looked at cognitive performance in people that had the phone upside down on the table, in their backpack beneath their chair, or in a different room. And only by having it in a different room, um, do you see the, the normal level of cognitive focus, not even an improvement.","offset":6236,"duration":31},{"text":"Andrew Huberman: It turns out that people can focus just as well, it's really interesting, they focus just as well if the phone is on the table or under, um, their chair in their backpack. But that the brain is using additional resources to keep suppressing the thought about the phone. So their cognitive performance is diminished. So the phone is really a cognitive detractor under those conditions.","offset":6267,"duration":33},{"text":"Andrew Huberman: Um, and I think about that a lot. It's also why I have a lockbox for my phone. I keep it in a separate room. It's one of the reasons I love this podcast more and more with every passing week, because no phones in here, um, we can really drop into things. Yeah, I think that, um, training the no-go response, having that level of discipline, is the superpower.","offset":6300,"duration":26},{"text":"Andrew Huberman: Yeah. All the other stuff, the to-dos, I mean yeah it's, it's important. Can't just not do anything obviously. But we focus so much on what to take, what to do. People always want to know what should I take? You know what should I do? What's the ideal workout routine? What's the... and here we have this five minute a day meditation, great. But it's also all the things you're not doing when you can sit for five minutes. You're not responding to the impulse to get up.","offset":6326,"duration":38},{"text":"Andrew Huberman: Yes. The discomfort of body that can come up during meditation. A pain in the back, um, your hip getting tight. Should we look at those as an opportunity to train up the mind and our ability to not go into stimulus response or should we get comfortable?","offset":6364,"duration":21},{"text":"Dr. Richard Davidson: It's a great question. And, um, uh, you know my very first meditation retreat in 1974 that I just went into this cold and it was like meditation boot camp. Uh, it was a kind of retreat where we were practicing for 16 hours a day and my body was on fire. I, it was so painful physically.","offset":6385,"duration":33},{"text":"Dr. Richard Davidson: Um, that was, you know, the most predominant experience that I had, just intense, intense physical pain. And then in this style of practice after the third day you had to make a vow that you're not going to move during each hour-long session. So the meditation sessions were hour-long and you had to make a vow that you're not going to move.","offset":6418,"duration":35},{"text":"Dr. Richard Davidson: Man the pain was so intense, the physical pain. And you know, eventually um, after the like the fourth day there's a kind of breakthrough that most people have, um, which is this remarkable kind of experiential insight where you directly look at the pain and you see that it's not exactly what it's cracked up to be and it's actually much more differentiated. And you begin to see all of its constituents. And that's when there's a kind of relief.","offset":6453,"duration":49},{"text":"Dr. Richard Davidson: The other thing to say is that we've done imaging work with physical pain and meditation. Um, it's um, one of the most robust kind of probes that you can use to interrogate the quality of the practice and also the longer term trait effects if you will.","offset":6502,"duration":42},{"text":"Dr. Richard Davidson: Um, and I liken it by the way, you know when you go to a cardiologist you'll often do a cardiac stress test, um, and so one of the best ways to probe the integrity of a system is by challenging it. Um, um, and not just looking at it at baseline so to speak. And it's true of the mind and the brain. And one of the best challenges is physical pain.","offset":6544,"duration":29},{"text":"Dr. Richard Davidson: So we've done work where we've primarily used heat, um, as a um, a painful stimulus because it can be delivered very precisely and very safely. Um, in imaging data there is a signature that is quite specifically tied to the physical pain itself and that there's another signature that is associated with the emotional reaction to the pain.","offset":6573,"duration":38},{"text":"Andrew Huberman: The interpretation of it.","offset":6611,"duration":1},{"text":"Dr. Richard Davidson: The interpretation.","offset":6612,"duration":1},{"text":"Andrew Huberman: Got it.","offset":6613,"duration":1},{"text":"Dr. Richard Davidson: And when we subjectively experience distress in response to pain it's actually mostly contributed by the secondary response. That is the emotional response to the initial noxious stimulus itself. And that is the set of neural changes that we most dramatically see transformed by meditation, uh, as a trait effect.","offset":6614,"duration":48},{"text":"Dr. Richard Davidson: Um, and it's um, particularly in this particular and this is published data, we've we this was done with long-term meditation practitioners and we show that actually it's specifically retreat practice. Um, so we can have two people who are matched on the total number of hours that they've practiced in a lifetime where in one person it is much more um, during retreat compared to another person. And it's specifically retreat practice where you're doing more intensive practice that contributes to the transformation of this emotional pain signature.","offset":6662,"duration":61},{"text":"Andrew Huberman: What would a good retreat practice look like? It would be presumably a course. But I guess if somebody didn't have the resources they could take a weekend and what does that look like? They're meditating a couple hours a day?","offset":6723,"duration":16},{"text":"Dr. Richard Davidson: More than a couple hours a day.","offset":6739,"duration":2},{"text":"Andrew Huberman: Okay, so it would be kind of hard to self-direct.","offset":6741,"duration":4},{"text":"Dr. Richard Davidson: Yeah, although there are a lot of online resources um, for this. And actually for a person who is unable for whatever reason to go physically to retreat there are online resources. Um, but of course, you know, I think it's probably more beneficial to do it in person, um, because you're more likely to comply with the, uh, with the expectations of like not checking your phone and things of that sort and being silent.","offset":6745,"duration":42},{"text":"Andrew Huberman: I'm always impressed by people that can sort of self-direct so much discipline. Um, it's pretty cool. I have rules in my house like I have a study area in my basement where I draw and prepare podcasts and I I don't allow phones down there. Mine or anyone else's.","offset":6787,"duration":22},{"text":"Dr. Richard Davidson: That's wonderful, I love that.","offset":6809,"duration":1},{"text":"Andrew Huberman: It's just an electronic free zone. I also now um, I noticed I I like working out, it's a pleasure for me. Um, and I noticed that my workouts would take much longer if I brought my phone in. So now I allow myself to turn on an album or two and leave the phone outside, but there's no phones allowed there either. And now I'm thinking about also making that the rule for the loft, for the bedroom. Like no phones.","offset":6810,"duration":32},{"text":"Andrew Huberman: So there's fewer and fewer areas where where things are allowed. But I think unless you set real constraints that it just starts to permeate everywhere. And I don't think I'm alone in that. And I grew up in Silicon Valley so I'm not anti-technology. I just want to have the richest experience of life possible. And so I just find that harder and harder to do when it's like inviting all these other things and people into the room when you when you have a phone there.","offset":6842,"duration":53},{"text":"Dr. Richard Davidson: Well I love those examples and I think uh you know you are setting an inspiring example for others. Um, and I think uh things have gotten so bad with uh the deleterious impact of technology that uh you know we've we've been led to to do those kinds of things which I think are so important and I think the more examples of that the better.","offset":6895,"duration":39},{"text":"Andrew Huberman: Yeah I feel like um it took us a while to um become the country with such um excessively high rates of obesity that we finally went oh my goodness, you know and we need to do something about this. So better eating, exercise of course critical, the GLP drugs have been, I believe have been very helpful for a lot of people. I don't I would hope people first embrace lifestyle tools and then and in any case embrace lifestyle tools.","offset":6934,"duration":36},{"text":"Andrew Huberman: But I don't think we're going to have the so-called Ozempic for uh addiction to devices. There isn't going to be something to come along and knock us off that um place. I think it just requires a lot of self-control. But I can promise everyone that the your workouts get way better, way better. Your work gets way better. I actually think that for the younger generation it's become easier than ever to excel simply by not doing a lot of the things that other people around you are doing.","offset":6970,"duration":61},{"text":"Dr. Richard Davidson: Totally, totally.","offset":7031,"duration":1},{"text":"Andrew Huberman: Totally. You know it used to be you know how do I succeed? How do I succeed? And the joking these days, the shortest, um, you know, how to become the best at your craft book is going to be by turning off your phone 22 hours a day. You will become best in class. I I know it. I absolutely know it. And people say well then you can't access certain things. There are ways around it. And um, because it's really the presence that you bring to things that um allows you to be effective.","offset":7032,"duration":53},{"text":"Dr. Richard Davidson: Yeah, absolutely. And regarding self-control, I think that self-control is a trainable skill. Um, and it is a byproduct of flourishing. Um, and one of the central capacities, I mean I we talked about meta-awareness earlier, and I think meta-awareness is really a key ingredient for self-control. And self-control will or self-regulation will improve as a consequence of that. And that's a superpower.","offset":7085,"duration":50},{"text":"Dr. Richard Davidson: You know there was a study done by these two psychologists, Moffitt and Caspi, who um, are um, developmental sort of life-span psychologists, and they've been studying this cohort in Dunedin, New Zealand. Uh, it's a birth cohort, so these folks have been studied since birth, they're now I think in their 60s. But there's amazing longitudinal data on on these people. And um, they had a paper in PNAS uh a number of years ago that looked at measure behavioral measures of self-control in f in these in this cohort when these people were four and five years of age.","offset":7135,"duration":63},{"text":"Dr. Richard Davidson: And this particular paper was looking at outcomes when they were 32 years of age. And what they found is that the individuals who are in the upper quintile of self-control at four f four and five years of age had significantly less drug abuse, were significantly less likely to be involved in um, in uh court proceedings. Uh, they earned on average $6,000 US dollars more per year, and they were matched on socioeconomic status of their families at birth.","offset":7198,"duration":48},{"text":"Andrew Huberman: So they were more successful.","offset":7246,"duration":1},{"text":"Dr. Richard Davidson: More successful. So all these amazing outcomes. Um, and they I remember this paper was published many years ago, but I remember the there's a line in the paper that says um, uh strategies which will improve self-control will lead to all these these important outcomes and save taxpayers money.","offset":7247,"duration":34},{"text":"Andrew Huberman: I’d like to take a brief break and acknowledge one of our sponsors, Waking Up. Waking Up is a meditation app that offers hundreds of guided meditation programs, mindfulness trainings, yoga nidra sessions, and more. I started practicing meditation when I was about 15 years old and it made a profound impact on my life. And by now there are thousands of quality peer reviewed studies that emphasize how useful mindfulness meditation can be for improving our focus, managing stress and anxiety, improving our mood, and much more. In recent years, I started using the Waking Up app for my meditations because I find it to be a terrific resource for allowing me to really be consistent with my meditation practice. Many people start a meditation practice and experience some benefits, but many people also have challenges keeping up with that practice. What I and so many other people love about the Waking Up app is that it has a lot of different meditations to choose from, and those meditations are of different durations. So it makes it very easy to keep up with your meditation practice both from the perspective of novelty, you never get tired of those meditations, there's always something new to explore and to learn about yourself and about the effectiveness of meditation, and you can always fit meditation into your schedule even if you only have two or three minutes per day in which to meditate. If you’d like to try the Waking Up app, please go to wakingup.com/huberman where you can access a free 30-day trial. Again, that’s wakingup.com/huberman to access a free 30-day trial.","offset":7281,"duration":99},{"text":"Andrew Huberman: Super impressive. Uh, and I do think that um nowadays we hear so much about the dos. You exercise, you eat this, and do and we five minutes a day meditation, great. I think the self-control component that's an outgrowth of meditation seems like a distinct benefit of meditation.","offset":7380,"duration":36},{"text":"Andrew Huberman: Because when you're exercising, yeah, I suppose if you if you really hate it and you're constantly forcing yourself not to quit, that's a form of self-control. But I feel like most people once they get going they're kind of moving through it, but who knows? I do want to um use this this notion of self-control as an opportunity to look at the other side of it. And I was planning on doing this at some point. I think now's the point.","offset":7416,"duration":37},{"text":"Andrew Huberman: I'm fundamentally confused about something about life, maybe you can help me. Um, I'm still not sure how much of life, of a really good life, should be forcing ourselves to do things versus um, kind of quote unquote honoring what what's right for us. Now obviously you know with respect to morality, with respect to the the big stuff in life that's those are easy answers. Okay.","offset":7453,"duration":34},{"text":"Andrew Huberman: But when it comes to moving through the day, we're now talking here today about starting the day doing something that you probably don't want to do or that you would reflexively not do as a means to gain some other larger benefit. Um, we're talking about going against the reflex, against the impulse.","offset":7487,"duration":23},{"text":"Andrew Huberman: In the Buddhist traditions, in the field of meditation, how is this kind of thought about? And just personally, how do you think about this? Because I think a lot of people listening are probably thinking, okay great like I'll do this if it gives me some benefits, I'll lower my heart rate, I'll have less stress, I'll learn some additional self-control.","offset":7510,"duration":26},{"text":"Andrew Huberman: But I think people are also feeling overwhelmed with all the stuff they feel like they have to do and fight themselves. And I think people are tired of fighting. And I think part of the reason they're tired of fighting is that they're not picking up the phone and going oh this is cool this is good this is great this is great. I think that they're they feel slightly out of control that they're just can't resist it and it's just happening. And so we've lost the muscle so to speak, the mental muscle of resistance, but I think that of overcoming resistance. Um, but it's also kind of a philosophical question. I mean how much of our lives should we be forcing things upon ourselves to be better and how much of life should we just live and and be free like a like a bulldog which is the best breed of dog.","offset":7536,"duration":64},{"text":"Dr. Richard Davidson: When I first started meditating I was fighting with my mind. Um, and I thought that that was great, you know, I'm this is uh means I'm really doing the work that's necessary and sitting through the physical pain, you know, forcing myself to sit for an hour while my, you know, feeling like my knee was on fire um, and my back was killing me. Um, and you know, I had a kind of sense of pride, I'm able to just uh tough this out. Um, and I was miserable.","offset":7600,"duration":54},{"text":"Dr. Richard Davidson: You know I did that kind of practice for quite some time and it may have had some benefit uh in shaping my skills of self-control. But you know, at some point I discovered that maybe there's another strategy that can be effective that is um, that that's not about fighting with your mind. And not about fixing anything, but it's the invitation is really to make friends with your mind.","offset":7654,"duration":44},{"text":"Dr. Richard Davidson: To welcome this. Uh, to have a completely different stance toward it and to do it with ease rather than with, you know, um, this kind of tension-ridden uh stance. I think that that is possible. Um, and the approach that we are taking in the Healthy Minds program, for example, is we're trying to do that. So there is a bit of discipline involved, but it's kind of um, really at the at the most minimal.","offset":7698,"duration":44},{"text":"Dr. Richard Davidson: It's inviting people to um, to be where they are not and not and to really um, make friends with their mind. Um, and not to fight against it. It's not about pushing away thoughts, it's not about um, you know, sitting down to meditate if you if you're restless and can't sit, that's fine. Do it while you're walking.","offset":7742,"duration":32},{"text":"Dr. Richard Davidson: So the discipline is the intentional use of the mind. Um, and there is discipline involved in that, but it's kind of um, what is the minimum level of discipline to begin to get these networks going? Um, and that's kind of the question that we've asked.","offset":7774,"duration":30},{"text":"Andrew Huberman: Yeah, because your lab has been focused heavily on the neuroimaging and understanding what brain networks are activated as well as the positive outcomes. So this five minute a day meditation could be done eyes open, could be done eyes closed, could be done while you're walking, while you're commuting, and it shuts down the sort of default mode network and brings higher levels of activity in these awareness and attentional networks? Is that I'm broadly speaking. I'm a neuroscientist but I want to translate this for for people because the names of the structures actually are somewhat meaningless right unless we're we've got someone in a stereotax, right? So yeah.","offset":7804,"duration":59},{"text":"Dr. Richard Davidson: Exactly. Yeah. So um, just to be transparently honest, there's been very little imaging work on the five minutes per day. We've done some, um, and what we've seen in the work we've done is the biggest and in general I think this is true, the biggest changes that you see particularly in the early stages of practice are in measures of connectivity.","offset":7863,"duration":39},{"text":"Dr. Richard Davidson: And it could be functional connectivity which um uh has to do with the functional integration across different networks, or it could be in measures of actual structural connectivity that we can image with diffusion weighted imaging uh and looking at white matter uh connectivity.","offset":7902,"duration":20},{"text":"Dr. Richard Davidson: And what we've actually seen with the five minutes a day is changes in um, in diffusion weighted imaging looking uh at, I mean the biggest change we see is in the superior longitudinal fasciculus, which um, as you know Andrew, connects the the prefrontal and the parietal regions, and it's basically a major pathway through which the central executive network is um, interacting with the default mode. And that's what we see with just five minutes a day of practice. We can see measurable changes in diffusion weighted parameters in with just five minutes a day for a month.","offset":7922,"duration":64},{"text":"Andrew Huberman: That's super impressive. More and more incentive to doing the five minute a day meditation. I guess that's the protocol we're weaving through this entire episode. And of course people could do seven, could do ten. I'd like to see people do six months every day, that would be impressive. That's what I'm going to shoot for.","offset":7986,"duration":24},{"text":"Dr. Richard Davidson: Six months every day?","offset":8010,"duration":1},{"text":"Andrew Huberman: Just do five minutes a day for you know hit 30 days and then six months later. I don't know, I feel like if it's just the repeated showing up. I that's really it. I mean I have a prayer practice I do every night before I go to sleep. If I fall asleep, I get out of bed. My girlfriend knows this. I'll get out of bed and I pray. Like I've not missed a night since I started doing this.","offset":8011,"duration":33},{"text":"Dr. Richard Davidson: I love that. I think that's beautiful. And I you know, I'd love to see a study done with pre-sleep prayer and see how it affects sleep.","offset":8044,"duration":10},{"text":"Andrew Huberman: My sleep is definitely better than ever but there are probably a variety of reasons for that. I'm sure. But sometimes I find that I'm falling asleep while I'm praying and I just tell myself, okay just it's the consistency. It's like I I have this script in my head that I'm showing devotion by showing up.","offset":8054,"duration":24},{"text":"Dr. Richard Davidson: Yeah.","offset":8078,"duration":1},{"text":"Andrew Huberman: It's just the repeated showing up and it's one of the few areas of my life that I was able to really remove the the need to do it perfectly. I mean what what would that even look like? I realize how ridiculous that is, right? But um some perfectionist tendencies in in me. You know we're showing up. Um, so for me the the um, I won't even say the the pride in it, the joy in it is from the consistency.","offset":8079,"duration":31},{"text":"Dr. Richard Davidson: Yeah, I love that. And I feel exactly the same way in my consistent practice. Um, I think that's so important. I wanted to mention one thing about sleepiness because you mentioned that sometimes when you're doing the nightly prayer you're sleepy.","offset":8110,"duration":25},{"text":"Dr. Richard Davidson: And sleep sleepiness is is often uh something reported when people are meditating and particularly in the early stages of practice. And uh you know I've uh dealt with sleepiness a lot. Uh, uh and particularly before I changed my routine of and when I gave up the alarm clock because I was getting too little sleep.","offset":8135,"duration":28},{"text":"Andrew Huberman: You were sleep deprived.","offset":8163,"duration":1},{"text":"Dr. Richard Davidson: Yeah, exactly. And I felt it and I struggled with it. So I have this meditation uh teacher Mingyur Rinpoche who uh one of the things he's taught is um is sleepiness meditation. Uh and sleepiness meditation is simply to be aware of sleepiness.","offset":8164,"duration":34},{"text":"Dr. Richard Davidson: Hm. Just be aware of sleepiness. Uh and uh and don't try to fight it. Just simply notice what it what is sleepiness, what is how is it feeling, and um investigate it with curiosity. Uh and that completely changed things for me.","offset":8198,"duration":30},{"text":"Andrew Huberman: There just seems to be this this thing where when we fight our state or our nature it it gains power.","offset":8228,"duration":11},{"text":"Dr. Richard Davidson: Yeah.","offset":8239,"duration":1},{"text":"Andrew Huberman: But when we we don't want to give in to it but when you acknowledge it but you don't completely give in to it somehow it it changes. Martha Beck was the first person to really teach me this, first in her books and then on the podcast. This idea that like if a feeling sucks or you don't want it to be there that rather than trying to suppress it you really look at it and let yourself feel it until it changes shape just a little bit, her language.","offset":8240,"duration":31},{"text":"Dr. Richard Davidson: Yeah.","offset":8271,"duration":1},{"text":"Andrew Huberman: And then you start to look at it through that different slightly different lens and then it morphs and it goes away.","offset":8272,"duration":7},{"text":"Dr. Richard Davidson: Exactly, exactly.","offset":8279,"duration":1},{"text":"Andrew Huberman: And I think in her descrip- I didn't again didn't describe it as well as as she did or would or could but um what we're talking about over and over again today is the mind looking at the mind. And it does seem to have this ability to, you know, humans have this ability to... do you think other animals have this ability? I know you can't answer that quest- question for sure. But do you think one of the reasons dogs are so wonderful is because they're not self-conscious?","offset":8280,"duration":36},{"text":"Dr. Richard Davidson: My conjecture is that um that our ability to uh look at our minds is way more developed than in any other species. And there may be some rudimentary kinds of meta-awareness in other species and you know some scientists have suggested that it may be correlated with successful performance on the self test, you know recogn- recognizing yourself in the mirror.","offset":8316,"duration":36},{"text":"Dr. Richard Davidson: Um you know there's a recent report of elephants passing the self-test. Hm. So they are smart after all. Yeah. Uh and you know that's an interesting story. They did this actually in the Bronx Zoo in New York and they had to construct a mirror that was the size of an elephant to how do they know if the elephant knows it's itself because they don't attack it if it's itself. So they they put rouge on the trunk and they expose the elephant to the mirror. And if the elephant touches the point where the rouge is it's recognizing itself in the mirror.","offset":8352,"duration":48},{"text":"Dr. Richard Davidson: And there are very few species that uh pass the self-test in that way. Most species don't.","offset":8400,"duration":13},{"text":"Andrew Huberman: We were talking offline a little bit earlier about a course that you're teaching about this very thing that you're calling flourishing. So what do the students get in that course and what components could you possibly educate us on right here right now so that we can benefit without having the opportunity to take the course?","offset":8413,"duration":24},{"text":"Dr. Richard Davidson: Yeah, absolutely. So the course is built on a framework that uh we've developed on the plasticity of flourishing. Um. It holds that there are four key pillars of human flourishing. And each of these pillars exhibits plasticity. Uh and these are the key trainable ingredients that constitute human flourishing.","offset":8437,"duration":32},{"text":"Dr. Richard Davidson: So what are these four pillars? The first pillar is and we've talked about some in the course of our conversation already but the first we call awareness. And awareness is where mindfulness is would be, it's where voluntary attention the capacity to focus resides, and it also includes our capacity for self-awareness and for meta-awareness which we've spoken about.","offset":8469,"duration":40},{"text":"Dr. Richard Davidson: The second pillar we call connection. And connection is about the qualities which are important for healthy social relationships, uh qualities like appreciation and gratitude and kindness and compassion. You can think of the the opposite of that being um at least in part social isolation and loneliness. Again these are elements that we know can be trained, they are importantly connected to our well-being.","offset":8509,"duration":41},{"text":"Dr. Richard Davidson: The third pillar we call insight. And insight is about a curiosity driven understanding of the narrative that all human beings have about themselves. Uh the narrative that we carry around in our minds. And we know that we all have a set of beliefs and expectations of ourselves. And we know that at one extreme of the continuum there are people that have very negative beliefs and expectations of themselves and of course that's a prescription for depression.","offset":8550,"duration":44},{"text":"Dr. Richard Davidson: But what's really critical for well-being is not so much changing the narrative, particularly at first, but it's changing our relationship to the narrative. So that we can see the narrative for what it is, which is a set of beliefs and thoughts and expectations.","offset":8594,"duration":24},{"text":"Dr. Richard Davidson: And then finally the last pillar is purpose. And purpose here is not necessarily about finding something grand to do with your life that's more meaningful and purposeful, but rather how can we find meaning and purpose in even the most pedestrian activities of daily living?","offset":8618,"duration":28},{"text":"Dr. Richard Davidson: And we actually talked about some of this earlier, but can taking out the garbage be connected to our sense of purpose? Cleaning the kitty litter. Cleaning the kitty litter. And of course it can be, it just requires a little bit of reframing and that's a learnable skill.","offset":8646,"duration":22},{"text":"Dr. Richard Davidson: There are really three things that we've discovered in this work uh uh that can be easily summarized. The first is that flourishing is a skill, the second is that it's easier than you think, and the third is that flourishing is contagious so that when you're flourishing it's going to have beneficial impact on the people around you.","offset":8668,"duration":37},{"text":"Dr. Richard Davidson: And our course, the Art and Science of Human Flourishing, is built on each of these pillars to give students not just um an intellectual understanding, but an experiential um uh practice, a taste, uh of what these pillars actually are.","offset":8705,"duration":35},{"text":"Dr. Richard Davidson: One of the important insights that the course is built on is that there are two major forms of learning that we know from modern neuroscience. One we can think of as declarative learning, which is learning about stuff, it's conceptual learning. The other we call procedural learning. And procedural learning is learning that is skill-based, it's acquired through practice, and we know that it's instantiated in different brain networks compared to declarative learning.","offset":8740,"duration":60},{"text":"Dr. Richard Davidson: And human flourishing requires both. Um and most of the academy privileges declarative learning over procedural learning. Uh and so this course that we teach is an unusual course because it includes a lab every week, so to speak, um a little section where students do the procedural learning for the stuff that they're learning declaratively in the lecture part of the class.","offset":8800,"duration":51},{"text":"Andrew Huberman: I love that. I've long wanted to do a course that had information and practices involved. Sounds like you've built that course. Um if people who are not able to take the course wanted to access these different bins with some practical tools, um you already gave us um a tool for awareness, so meditation, um five minutes would be a great place to start done daily, um and just to be aware of what's of the chaos and be able to observe it but not go not follow it.","offset":8851,"duration":43},{"text":"Andrew Huberman: How does one incorporate connection?","offset":8894,"duration":2},{"text":"Dr. Richard Davidson: So I actually talked a little bit about connection in in uh earlier, but there's a lot more to say. But one kind of connection is doing a little appreciation practice when we eat, that's one I talked about earlier, um where we connect to the people even if we don't know them who have brought us food to the table. Some we some we may know, some we might not know.","offset":8896,"duration":35},{"text":"Dr. Richard Davidson: There are formal kinds of connection practices that we there are meditation practices that we call loving kindness and compassion practices. And so we can um we've shown in a randomized control trial uh that just a few hours of this practice over two weeks is sufficient to produce a measurable change in the brain.","offset":8931,"duration":35},{"text":"Dr. Richard Davidson: Uh and so here's a a way you can do this. You can begin with a loved one and bring the loved one into your mind and your heart and envision a time in their life when they may have had some challenge or difficulty and then cultivate the strong aspiration that they be relieved of that difficulty and that they have um a life of ease.","offset":8966,"duration":42},{"text":"Dr. Richard Davidson: That's it. And you can use a simple phrase that you can repeat to yourself um that embodies that captures that theme. It could be something as simple as may you be happy, may you be free of suffering. But the words don't matter whatever words are most well-suited for each person.","offset":9008,"duration":30},{"text":"Dr. Richard Davidson: Um but then you move on to different categories of people. So you start with a loved one, you then move on to yourself, you then move on to to a category of person that we call a stranger. And a stranger is someone you recognize whose face you recognize but you don't know them well.","offset":9038,"duration":29},{"text":"Dr. Richard Davidson: It could be someone that works in the same building that you work in, it could be a classmate, it could be a bus driver, it could be the cashier at a local um store that you go to, a barista. Um you don't know anything about them but you recognize them. And you can envision a time in their life when they may have had some difficulty even if you don't know anything about their life. So you do that with the stranger.","offset":9067,"duration":42},{"text":"Dr. Richard Davidson: And then finally you move on to what's probably the most important category which is a difficult person. Someone who pushes your buttons. And you genuinely bring them into your mind and your heart and you recognize a time, you imagine a time when they have been having some challenge and you cultivate the aspiration that they be relieved of that suffering.","offset":9109,"duration":32},{"text":"Dr. Richard Davidson: And that practice just done a few minutes a day can change your brain and it changes your behavior.","offset":9141,"duration":12},{"text":"Andrew Huberman: And it changes the brain how? Makes it um a capable of more empathy?","offset":9153,"duration":8},{"text":"Dr. Richard Davidson: So one of the key regions of the brain that's been implicated in empathy is the um the temporal parietal junction. What we see is that in this kind of compassion practice there's significantly enhanced activation of the temporal parietal junction particularly in response to stimuli of people in distress. Hm. There's also uh networks in the brain that are involved in positive affect that are activated by this kind of practice.","offset":9161,"duration":57},{"text":"Dr. Richard Davidson: And behaviorally we've shown using hard-nosed um tasks that are derived from behavioral economics and...","offset":9218,"duration":42},{"text":"Dr. Davidson: And we're doing—and this—the other cool thing about this stimulation is you cannot feel it. It has no subjective sensations. So, it's very different than TMS which is, you know, you feel it big time. You don't feel a thing. So, we are delivering this during sleep. People don't know when they're getting stimulated. They of course know they're being stimulated because they're giving informed consent, but it doesn't wake them up.","offset":9260,"duration":24},{"text":"Dr. Huberman: And it increases slow wave sleep?","offset":9284,"duration":3},{"text":"Dr. Davidson: We've definitively demonstrated that it increases the density of slow wave activity during deep sleep.","offset":9287,"duration":6},{"text":"Dr. Huberman: How do they feel in their wakeful subjective life? Better?","offset":9293,"duration":4},{"text":"Dr. Davidson: Yes.","offset":9297,"duration":1},{"text":"Dr. Huberman: And how do I become a participant in the study? I mean, I get plenty of slow wave sleep, my sleep is great lately and has been for a while, but what—are you recruiting subjects?","offset":9298,"duration":10},{"text":"Dr. Davidson: This is a—yeah, it's a big complicated protocol.","offset":9308,"duration":3},{"text":"Dr. Huberman: I don't care, are you recruiting subjects? I'm just kidding, I'm just kidding. I do care. I'm just teasing. People are probably thinking, \"How do I get that?\" Well, maybe this pre-sleep meditation protocol should be looked at, because that's something anyone can do. I'll provide a link to that paper.","offset":9311,"duration":12},{"text":"Dr. Davidson: So, that's exactly what we're doing in this study now. We're using a—this is a little technical, but we're using a micro-randomized design where, so in a single participant on some nights they get pre-sleep meditation, just before sleep, just a five-minute practice. And in other nights, they do not receive that.","offset":9323,"duration":24},{"text":"Dr. Davidson: And we are looking at the impact of that on slow wave sleep and also looking at the synergistic effects of pre-sleep meditation with the Testi stimulation to increase slow wave activity. And we're getting experience sampling measures during the next day to see if the pre-sleep meditation has a demonstrable impact on their mood the next day and how that interacts with our boosting of slow wave activity.","offset":9347,"duration":27},{"text":"Dr. Davidson: Very, very cool. I should just say this is work that's being done collaboratively with Giulio Tononi and his group at in Wisconsin. He's a very well-known sleep and consciousness scientist, neuroscientist.","offset":9374,"duration":15},{"text":"Dr. Huberman: Great lab.","offset":9389,"duration":1},{"text":"Dr. Davidson: Yeah, great lab.","offset":9390,"duration":1},{"text":"Dr. Huberman: Are you able to share any preliminary findings about what the pre-sleep five-minute meditation does to deep sleep?","offset":9391,"duration":7},{"text":"Dr. Davidson: We don't know yet. And honestly, it's not me being, you know, super cautious. We just this is a new study that we're just in the middle of. We have roughly 20-something participants who've completed the protocol, but it's it's ongoing right now.","offset":9398,"duration":15},{"text":"Dr. Huberman: Well, given what you just described, and given that this other paper described that some pre-sleep meditation can have a really impressive impact on growth hormone release, I'm encouraged to do the five minutes before sleep. So, I suppose that if you want to double up on the benefits, you could just do the five minute per day meditation, folks, right in the hour before sleep.","offset":9413,"duration":21},{"text":"Dr. Davidson: Why not? I think it would be great.","offset":9434,"duration":2},{"text":"Dr. Huberman: What are your thoughts on open monitoring meditation for increasing creativity?","offset":9436,"duration":5},{"text":"Dr. Davidson: Honestly, the data on open monitoring meditation or for that matter any meditation and creativity, I would say are very limited. In part, it's because the measures of creativity that are used by psychologists typically are honestly, I think pretty crappy measures of creativity. So we're quite limited by the measurement tools that we have.","offset":9441,"duration":39},{"text":"Dr. Davidson: Having said all that, I do think that open monitoring meditation can really boost creativity primarily by helping people become more aware of the associative thoughts that they have. And this relates to something we talked about earlier. I often tell students of mine to spend time inspecting their own mind, just watching their own mind and writing down thoughts that may occur that may be interesting.","offset":9480,"duration":32},{"text":"Dr. Davidson: And this is a kind of open monitoring meditation. It's having no specific object and just being open, aware, awake, and not distracted, not getting lost in a train of thought, but simply being aware. I believe that we probably have much more creative thought occurring than we give ourselves credit for, and it's simply because we forget. And I think this can really improve that. But the data are pretty meager.","offset":9512,"duration":35},{"text":"Dr. Huberman: But you still recommend it if people want to increase their creativity.","offset":9547,"duration":3},{"text":"Dr. Davidson: Yes, I do, because this is one of those things where there's essentially no downside to it. We know there'll be other benefits that have been empirically documented.","offset":9550,"duration":16},{"text":"Dr. Huberman: Awesome. Well, Richie, thank you so much for coming here today and educating us on meditation, but really much more than that. You've educated us on states of mind, how to access different states of mind, what they mean, how they impact the state of being and our traits that we will enter after we meditate. And now everyone should be inspired to do at least five minutes per day of meditation, maybe in the morning, maybe before sleep.","offset":9566,"duration":26},{"text":"Dr. Huberman: Would love to get the update on this study that you described looking at slow wave sleep. And I'm really excited about your book. It's so great that you have a new book coming out because I, of course, read *Altered Traits*. I've talked about it on the podcast. I love, love, love the book. We'll put a link to that. But *Born to Flourish: How New Science and Ancient Wisdom Reveal a Simple Path to Thriving* by you and we should give credit to your co-author, Cortland Dahl.","offset":9592,"duration":25},{"text":"Dr. Huberman: And he is a neuroscientist as well?","offset":9617,"duration":2},{"text":"Dr. Davidson: Yes, he's a neuroscientist, contemplative scientist, and chief contemplative officer of our non-profit human.org.","offset":9619,"duration":10},{"text":"Dr. Huberman: Awesome. Well, you're a real pioneer in this space. The field, as it were, of meditation really needed a serious scientist to break in and study and share so that everyone could learn about and adopt meditation and you've just done so much to educate so many people and coming here today you've just done more of that, so I have immense gratitude for you and I know millions of other people do as well. So, thank you so much.","offset":9629,"duration":25},{"text":"Dr. Davidson: Thank you. And I want to express my immense gratitude to you for bringing science that can make our lives better to so many people, and that is such a gift and such a wonderful service that you are providing, so thank you.","offset":9654,"duration":16},{"text":"Dr. Huberman: Thank you. Thank you for joining me for today's discussion with Dr. Richie Davidson. To learn more about his work and to find a link to his new book, *Born to Flourish*, please see the links in the show note captions. If you're learning from and or enjoying this podcast, please subscribe to our YouTube channel. That's a terrific zero-cost way to support us. In addition, please follow the podcast by clicking the follow button on both Spotify and Apple.","offset":9670,"duration":25},{"text":"Dr. Huberman: And on both Spotify and Apple, you can leave us up to a five-star review. And you can now leave us comments at both Spotify and Apple. Please also check out the sponsors mentioned at the beginning and throughout today's episode. That's the best way to support this podcast. If you have questions for me or comments about the podcast or guests or topics that you like me to consider for the Huberman Lab podcast, please put those in the comment section on YouTube. I do read all the comments.","offset":9695,"duration":26},{"text":"Dr. Huberman: For those of you that haven't heard, I have a new book coming out. It's my very first book. It's entitled *Protocols: An Operating Manual for the Human Body*. This is a book that I've been working on for more than five years and that's been based on more than 30 years of research and experience. And it covers protocols for everything from sleep to exercise to stress control, protocols related to focus and motivation. And of course, I provide the scientific substantiation for the protocols that are included.","offset":9721,"duration":24},{"text":"Dr. Huberman: The book is now available by pre-sale at protocolsbook.com. There you can find links to various vendors. You can pick the one that you like best. Again, the book is called *Protocols: An Operating Manual for the Human Body*. And if you're not already following me on social media, I am Huberman Lab on all social media platforms. So that's Instagram, X, Threads, Facebook, and LinkedIn. And on all those platforms, I discuss science and science-related tools, some of which overlaps with the content of the Huberman Lab podcast, but much of which is distinct from the information on the Huberman Lab podcast.","offset":9745,"duration":331},{"text":"Dr. Huberman: Again, it's Huberman Lab on all social media platforms. And if you haven't already subscribed to our Neural Network newsletter, the Neural Network newsletter is a zero-cost monthly newsletter that includes podcast summaries as well as what we call protocols in the form of one-to-three page PDFs that cover everything from how to optimize your sleep, how to optimize dopamine, deliberate cold exposure.","offset":10076,"duration":23},{"text":"Dr. Huberman: We have a foundational fitness protocol that covers cardiovascular training and resistance training. All of that is available completely zero-cost. You simply go to hubermanlab.com, go to the menu tab in the top right corner, scroll down to newsletter, and enter your email. And I should emphasize that we do not share your email with anybody. Thank you once again for joining me for today's discussion with Dr. Richie Davidson. And last but certainly not least, thank you for your interest in science. [2:48:47]","offset":10099,"duration":15}],"logs":[{"elapsed":"0.0","message":"Downloading audio from YouTube...","detail":null},{"elapsed":"0.0","message":"Trying download with browser cookies (ad-free)...","detail":null},{"elapsed":"2.8","message":"⚠ Cookie download failed: WARNING: [youtube] [jsc] JS Challenge Provider \"deno\" returned an invalid response: response = JsChallengeProviderResponse(request=JsChallengeRequest(type=, input=NChal","detail":null},{"elapsed":"2.8","message":"Retrying without cookies...","detail":null},{"elapsed":"75.6","message":"⚠ Downloaded without cookies — audio may contain ads","detail":null},{"elapsed":"75.6","message":"Audio downloaded (99.6 MB) in 75.6s","detail":"File size: 99.6 MB"},{"elapsed":"75.6","message":"Video title: Science-Based Meditation Tools to Improve Your Brain & Health | Dr. Richard Davidson","detail":null},{"elapsed":"75.7","message":"Audio duration: 2:43:44 (163.7 min)","detail":null},{"elapsed":"75.7","message":"Very long audio (163.7 min) — will use chunked transcription with gemini-3-flash-preview","detail":null},{"elapsed":"75.7","message":"Skipping full-file attempt — using chunked transcription for 163.7 min audio","detail":null},{"elapsed":"77.1","message":"Split audio into 4 chunks for transcription","detail":null},{"elapsed":"77.1","message":"Transcribing chunk 1/4 (starts at 0:00)...","detail":null},{"elapsed":"77.1","message":"Uploading audio to Gemini File API...","detail":null},{"elapsed":"82.4","message":"Audio uploaded in 5.3s","detail":"File ref: files/edy8bj4ou95v"},{"elapsed":"82.4","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"142.8","message":"Chunk 1: 50 segments, last timestamp 43:30","detail":null},{"elapsed":"142.8","message":"Transcribing chunk 2/4 (starts at 45:00)...","detail":null},{"elapsed":"142.8","message":"Uploading audio (offset 45:00) to Gemini File API...","detail":null},{"elapsed":"147.3","message":"Audio uploaded in 4.5s","detail":"File ref: files/1ru169vpd4t4"},{"elapsed":"147.3","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"216.7","message":"Chunk 2: 135 segments, last timestamp 1:38:13","detail":null},{"elapsed":"216.7","message":"Transcribing chunk 3/4 (starts at 1:30:00)...","detail":null},{"elapsed":"216.7","message":"Uploading audio (offset 1:30:00) to Gemini File API...","detail":null},{"elapsed":"221.5","message":"Audio uploaded in 4.8s","detail":"File ref: files/sce52wbi2j4q"},{"elapsed":"221.5","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"293.3","message":"Chunk 3: 123 segments, last timestamp 2:33:38","detail":null},{"elapsed":"293.3","message":"Transcribing chunk 4/4 (starts at 2:15:00)...","detail":null},{"elapsed":"293.3","message":"Uploading audio (offset 2:15:00) to Gemini File API...","detail":null},{"elapsed":"296.8","message":"Audio uploaded in 3.5s","detail":"File ref: files/im13owulqm3f"},{"elapsed":"296.8","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"335.3","message":"Chunk 4: 76 segments, last timestamp 2:48:19","detail":null},{"elapsed":"335.3","message":"Chunked transcription complete: 331 total segments","detail":null},{"elapsed":"335.3","message":"Total cost: 246,690 in / 37,795 out — cost: $0.2367","detail":null},{"elapsed":"335.4","message":"Total transcription time: 259.7s — 331 segments","detail":null},{"elapsed":"335.4","message":"Analyzing topics across 331 segments with gemini-3.1-pro-preview...","detail":null},{"elapsed":"396.5","message":"Topic analysis complete in 61.2s — found 26 topics","detail":null},{"elapsed":"396.5","message":"Analysis tokens: 33,741 in / 1,808 out / 5,506 thinking — cost: $0.1552","detail":null},{"elapsed":"396.5","message":"Pipeline finished in 396.5s — total cost: $0.3920 (325,540 tokens)","detail":null}]} \ No newline at end of file diff --git a/history/1773775610426-xaNl2EY8b-c.json b/history/1773775610426-xaNl2EY8b-c.json new file mode 100644 index 0000000..4f835a8 --- /dev/null +++ b/history/1773775610426-xaNl2EY8b-c.json @@ -0,0 +1 @@ +{"id":"1773775610426-xaNl2EY8b-c","videoId":"xaNl2EY8b-c","url":"https://www.youtube.com/watch?v=xaNl2EY8b-c","title":"How To Breathe Properly | Brian Mackenzie | Modern Wisdom Podcast 121","type":"youtube","topicCount":14,"segmentCount":112,"createdAt":"2026-03-17T19:26:50.426Z","uploadDate":"20191118","chunks":[{"title":"Introduction and the Missing Link","summary":"The host introduces Brian Mackenzie to discuss breathwork. They reflect on how even top strength and conditioning coaches often overlook the profound role breathing plays in performance.","entries":[{"text":"Brian: Today, 500 million years ago, aerobic metabolism sits at the forefront of the most efficient way to use energy. And so, anything outside of aerobic metabolism becomes anaerobic. So, if I don't have that process, that conversion of energy, I'll default very simply, and we should, to this higher stress situation of using energy. So, anaerobic doesn't necessarily become a training process, it's more or less the byproduct of I'm no longer able to handle aerobically what's going on. So, how quickly I can come back to that aerobic is literally how well I can. So, having a very high aerobic capacity means I function higher aerobically. So, when we look at people like a guy smashing the two-hour marathon, what does he look like physiologically? And although there's, like, look, to be totally hon- like, look, I support and I'm very happy for the man and everything, but realistically, if he were in the same setup as they were in 1950, or even 1980, he wouldn't have run a sub-two-hour marathon.","offset":0,"duration":69},{"text":"Host: I'm joined by Brian Mackenzie, the man behind Power Speed Endurance, and today we are talking about something that you will all be familiar with, but are probably doing a little bit wrong: breathing. Brian, welcome to the show.","offset":69,"duration":12},{"text":"Brian: Thanks for having me.","offset":81,"duration":1},{"text":"Host: It's gonna be awesome. I'm really excited to speak about this sort of stuff today. We've been talking about endurance a lot recently. Had Alex Hutchinson, writer of Runner's World on analyzing Eliud Kipchoge's recent performance. We've had Brian Carroll from Power-X-Strength on talking about squatting over a thousand pounds, and all of this is enabled by a lot of different things, but I guess principally, one of those is breath work, right?","offset":82,"duration":29},{"text":"Brian: Yeah, well, physiology, and almost chemistry is regulated through our breath. So, anything and everything- I mean, I- I- I've known Alex for quite some time, we've kind of gone back and forth over the years, he's a great fucking kid, man. I like him a lot. I don't know your other- the other guy, but to squat a thousand pounds is to understand some things.","offset":111,"duration":27},{"text":"Host: He really does. He really does understand some things. I mean, Kelly Starrett, we just released an episode with him today, we've had Dr. Stu McGill on, so, you know, we've had a lot of these guys, and when they talk about this, even, you know, Kelly and- and- and Stu, people that are really, really kind of at the- the top of their game, very well respected in their field, it's rare that I hear someone bring up breath work. Why do you think that is?","offset":138,"duration":26},{"text":"Host: Kelly- Kelly didn't. Kelly didn't, no. We were talking a bit about the Game Changers- we were talking about the Game Changers documentary and veganism, we went off on a rabbit hole down that.","offset":164,"duration":8}],"startTime":0},{"title":"Discovering Breath Mechanics","summary":"Brian shares his background in endurance training and yoga. He explains how skeptically trying an altitude training mask surprisingly taught him about diaphragm activation and spinal organization.","entries":[{"text":"Brian: Oh, really? Wow. No, I know Kelly's very much into the breath work at this point. Uh, I mean, I introduced it to him, so, you know, and I know he- he uses it inside of his- 101s and 102 courses now, so, you know, from his work. But, you know, at any rate, Kelly's been a very close comrade of mine for a very long time. Um, so we've kind of grown up in the industry together, but, you know, the- it's interesting how I stumbled onto the breath work and why, even though I was introduced to it quite some time ago, and it just didn't take. And I understand why it didn't take, um, because it was never explained in a way that made sense to, especially, a guy who was participating in strength and conditioning was all about performance.","offset":172,"duration":51},{"text":"Brian: Yeah, I understand. So, I- I- I entered into this world of yoga many years ago and had a yoga practice because I was a triathlete who was getting tight. And when you get tight, you need to loosen up. And so I went to yoga and I ended up enjoying yoga real- like a ton. And I chased around a yogi in Ashtanga um, that was really good at what she was doing. But I just never paid attention to the fact that we were in- we were utilizing a breath practice at the foundation of this practice. Like we were controlling our breathing, we were told to control our breathing, we were told to control our breathing in specific patterns. You know, this went on and on, and I was like, you know, I just remember it blowing over to a large degree.","offset":223,"duration":53},{"text":"Brian: And that in and of itself is kind of how we all behave to a large degree, and I'm- I'll connect all this through this talk so that it makes sense for everybody else. Um, you know, but I largely just paid attention to the fact that I needed to get more flexible or more mobile at the time. And then I drifted away from yoga for a little bit, really got hardcore into endurance training, obviously wrote a couple books on that and came to a pretty good understanding of some ways to tweak things for people who are busy um, and who were injured. Um, you know, and that that was a big part of my career for about 10 or 12 years. And then somebody handed me a training mask and I laughed, and I was like, \"This doesn't change altitude. I know how pressure works. I've actually worked on altitude training for quite some time and this can't change pressure.\" So, you know, but nonetheless, you know, when you you you make fun of something and if you're in you know, done enough work in your life to understand that you haven't if you're making fun of things or you're crit- criticizing things that you've never used, that's called ignorance.","offset":276,"duration":75},{"text":"Brian: And I didn't want to remain ignorant to something, so I put the damn thing on. And I instantly went from like I'm seated now to I sat up and I engaged my diaphragm and I felt my ribs expand out and, like, my back light up, and like I was like, \"Whoa!\" Like, you know, it was it was just- I tend to feel a lot. And because of my background in teaching movement and getting people fixed, or helping people to fix themselves, I um, you know, I I was just like, \"Whoa, here- whoa! What happened? Like maybe we've got something that I could put on my athletes when they're warming up so that we can get 'em moving properly and using their you know, their core correctly, organizing their spine in a way that it should be, because, oh shit, like it just so happens that we organize the spine based on our diaphragm. We have to. At the- at the root of who we are and what we do is a system that is dependent upon one thing, and that is life. And that life is predicated on a deal that was made 500 million years ago in order to use aerobic metabolism.","offset":351,"duration":74}],"startTime":172},{"title":"The Physiological Alarms of CO2","summary":"Brian explains how rising carbon dioxide levels trigger deep survival alarms in the brain. Poor breathing mechanics can default the body into unnecessary anaerobic stress responses, even at rest.","entries":[{"text":"Brian: So, suffocation sits at the heart of that. So we could remove our amygdala, our panic- our freak out- our, not our panic center, our fear center, and you will still have chemoreceptors that will set you off in a panic when carbon dioxide levels raise. So, if I'm not organized correctly around my spine, I don't use my diaphragm correctly, so I default into poor breathing patterns. So, this is a rabbit hole of movement that really made more sense to something about organization of the spine, right? And there's a- there's a lot of minutia around the spine and organization and core stability and everything we want to do, but by and large we have figured out and theorized that the only reason you need to organize that spine correctly is to actually take a breath and understand that breath. Because the lungs don't do that work on their own. The diaphragm is the primary in that and then we follow up through the intercostals and several other muscles that end up getting involved. But poor breathing habits elicit poor responses including that of the sympathetic nervous system, or I default into some poor breathing patterns that have me using my anaerobic system more than necessary.","offset":425,"duration":71},{"text":"Host: And is that in and out of exercise?","offset":496,"duration":2},{"text":"Brian: Yes, that is without exercise, my friend.","offset":498,"duration":2},{"text":"Host: Wow.","offset":500,"duration":1},{"text":"Brian: You are constantly using anaerobic systems and aerobic systems at all times. We all- we're like- this is- we know this. What we started seeing was like look man, we took a look back, so this started with a training mask and it inevitably became like \"Oh shit, you've got your own training mask on your face, it's called a nose.\" And holy crap, it like it has this filter system and it's got these- this humidification system, it's got- oh my gosh, this thing, mucus, oh, it releases like immune cells. Like, um, so it helps my immune system function better. I spinning the air differently, it forces my diaphragm to actually pull more because it's- it's not allowing for fast air to happen. It doesn't mean we can't breathe through our mouth or shouldn't, it's just when is it necessary? And we can get into that in a bit if you want. But, you know, it- it's interesting we we started understanding we started looking at the physiology behind all this stuff and the framework behind physiology, and we've missed some big, big things.","offset":501,"duration":71}],"startTime":425},{"title":"CO2 Tolerance and Oxygen Efficiency","summary":"Looking at cellular respiration, Brian discusses how carbon dioxide tolerance dictates our efficiency in using oxygen. He contrasts the static CO2 tolerance of freedivers with the dynamic needs of working athletes.","entries":[{"text":"Brian: And it- it's all there, it's just the way we've taught it and the way we've looked at it has not been real um, I would say it- it's not a very creative process, thus why it's eluded us. And even in the world of yoga today they've missed it, and they've misunderstood what it is that pranayama actually means. And pranayama is a word that is basically- it's a Sanskrit word that's probably about 5,000 years old, and there's other languages that use these very similar terminology, including um, Hebrew, um, that it means \"energy control\" at its root. It also means \"breath control.\" Odd that they're the same. Odd that we use a cardiometabolic device in order to measure our breath, which tells us what's happening from a cellular level. So, through cellular respiration, we understand the only way we can we measure that is through the gas exchange of what's going on here.","offset":572,"duration":58},{"text":"Brian: So, we said let's look at this realistically and see what happens. And so we started measuring things, and we were measuring things in many different ways including just a simple breath practice um, or hey, I'm going to go for a walk, I'm going to walk my dog. And Rob Wilson, who's my counterpart in the Art of Breath, who's our lead on education- he's our Director of Education, um, went for a walk with his dogs with his mouth open. And then he came back, reset his device, and we have portable metabolic carts, and he shut his mouth and went for a walk with his dogs, the exact same route. Turns out those are two different and totally, totally different metabolic profiles. Weird. And- and it's not weird. This has been said for thousands of years. We're not actually bringing- we're not actually saying things that, you know, are that crazy, but unfortunately they are crazy in our world because there's so many really, really, really smart scientific people who we look to who've missed the boat on a lot of this stuff, and the simplicity of it.","offset":630,"duration":72},{"text":"Brian: And it's not that they're dumb or that they've you what- whatever, it's just we weren't really looking at this. And so we started really going after not only the movement and and and how the mechanics work around this, but then the physiology, right? Um, and then starting to see that, oh wow, it's all chemistry in the body is regulated through our breath. All of it. So how we shift from alkaline to acidic is literally governed through how I breathe, and how I absorb oxygen is dependent upon how well my body actually plays with this molecule this- this thing called carbon dioxide. In the body in the blood it's carbonic acid, and then as we exhale as it gas exchange it becomes carbon dioxide. But I am largely dependent upon how well I actually react to that and that can, you know, that has other facets to it, I'll go here in a second. But my relationship to carbon dioxide is actually how well I play with oxygen and how well I'm efficient- how efficient I am at using oxygen.","offset":702,"duration":64},{"text":"Brian: So, I may be a freediver who can actually sit here and do breath work and be very, very, very oxygen efficient because I can hold my breath for long periods of time, which also requires an ex- a very high level of CO2 tolerance. This is static CO2 tolerance. This is non-working CO2 tolerance. When we look at training or we look at human performance- and I use quotes because performance I think is- we're about to kind of shift a paradigm on what human performance is. Um, but the idea that if I work- like, when I start to work out, that shifts. There's a different response, or there's a- there's a very different play that happens within CO2 tolerance. And so I've been I've been able to observe and take people who are freedivers who are highly specialized, or big-wave surfers who are also, you know, freedivers in essence to some degree, but they're highly specialized.","offset":766,"duration":65},{"text":"Brian: And when we apply work to them, we see a very different story happen. So we see the specialist kind of come apart, right? Meaning, there's a very different- like that CO2 tolerance that was really high when I'm static and not a lot of stressors going on, or a big wave- some things like that- I'm very accustomed to. When I start working out, my respiration rate goes up considerably higher than it would with somebody, let's say, let's call it, you know, Eliud, right? His respiration rate isn't going to go up so high, right? But the interesting thing here is I would bet if Eliud's never really participated in any sort of static breathing or carbon dioxide tolerance training, he's probably shit statically. Right? And so there's this weird world that we started to see.","offset":831,"duration":46}],"startTime":572},{"title":"The Neurobiology of Respiration","summary":"Brian breaks down the neurobiology of breathing, from the neocortex down to the brain stem. He explains how unconscious respiration centers constantly react to emotional states and physiological predictions.","entries":[{"text":"Brian: Now, my fascination is in connection with the brain and- so the neurobiology of it and the physiology. I'm- I- I'm now considering what physiology is more or less our mind. Our abili- that's what our mind is, and our ability to connect to the mind and understand the feelings and the processes and the things that are going on. And so the brain is where the circuitry and- and the information is being sent out. The brain works perfectly fine as long as we're connected to the physiology and understand the physiology. If we don't understand the physiology, the brain will get away from us and start overthinking, right? And so as kids, when we come into this world, we have this thing where we're attached to a parent and we learn- this is- it's unavoidable, right? And and so from a neurobiological perspective, at the top layer, the most evolved part of the brain is our neocortex, and this is where the stories- this is where some of the emotional things, like, start to trigger.","offset":877,"duration":65},{"text":"Brian: But this is where the storytelling, motor control- a lot of- there's a lot of dedicated area to motor control in the brain, um, to where we can do different tasks. Like I can talk or- like I can talk and drink water at the same time, or think and drink water. You know what I mean? I mean, just simple basic shit that we go throughout our day that some of us confuse ourselves in thinking it's multitasking, of which it's not. Um, so that's the storytelling side of things. Below that becomes the limbic system. This is where emotions are now concrete and set up in the system, and where I will have a reaction emotionally to something, and then the storytelling gets played into there, right? And so it can get exacerbated. Then down below that, we have the brain stem where the- or we could call it the reptilian brain, the oldest part of the brain. And this is where the kind of evolution of everything takes place. Oh, it just so happens that our respiration centers are set up in that brain stem. So, meaning, they are on autopilot with my system, and they can respond to every emotion and every thought that I have.","offset":942,"duration":60},{"text":"Brian: It also can respond to the work that I have because I have dedicated chemoreceptors set up in the carotid and the aortic valves which are headed out to the periphery. So that means we're on a prediction system that carbon dioxide levels that are set up in my brain stem react to a prediction of what's occurring in the system through chemoreceptors and baroreceptors that are in my arteries, and it's triggering me to breathe. So my heart rate responds to that, right? So the heart rate's late to the game. And so, you know, there's a whole plethora of things in there, but how I decide to grow up and how I go through my experiences in life inevitably have a Rolodex of things on how I actually respond to breath. So, when I actually am working out, I can tell with many people where the potential trauma or problems can set up, or we can see metabolic issues, even from somebody who doesn't work out as they sit and are doing things.","offset":1002,"duration":71}],"startTime":877},{"title":"Conscious Control Over Heart Rate","summary":"The host asks if humans possess any direct control over internal organs like the heart. Brian demonstrates that intentional breathing is our primary conscious mechanism for manipulating autonomic functions like heart rate.","entries":[{"text":"Host: I get you. Yeah. Um, one thing that's just come to me there as you were talking. Do you think it's strange that we don't have control over our heartbeat as humans, as evolved creatures?","offset":1073,"duration":10},{"text":"Brian: Well, the only way you're going to control your heart rate is how?","offset":1083,"duration":5},{"text":"Host: Output? Movement?","offset":1088,"duration":1},{"text":"Brian: Nope.","offset":1089,"duration":2},{"text":"Host: Breath?","offset":1091,"duration":1},{"text":"Brian: You got it. So, if I just said, \"Hey, Chris, check it out. Control your heart rate for me right now.\" And if we put you on a heart rate monitor, because that's what you- we- most people would do, they go \"Alright, let me get on a heart rate monitor.\" Like, no no no no no. Can you feel your heartbeat right now without doing anything? Can you feel it?","offset":1092,"duration":24},{"text":"Host: A tiny bit- I'd have to be very tuned into my body.","offset":1116,"duration":2},{"text":"Brian: Yeah, yeah, yeah. It took me about- it- about three years ago I was able to like I can just sit there and I could pick it up anywhere in my body I really want to. Whether I want to do it in a toe or a finger or my neck or whatever, right? But it's like, alright, how do I lower that? And I literally will go [breathes in deeply and exhales slowly] and my heart rate will start to drop by controlling my breathing.","offset":1118,"duration":25},{"text":"Host: I understand. I think that obviously shows that the heart rate is um, at the mercy of the breath to a large degree. I was just thinking about whether it's- I can control my breath. I can consciously hold it, breathe quicker, breathe slower. But that's not something that we have with our digestive system, that's not something that we have with our heart. You know, that- that- it would appear that from our- the- the things that are inside of us, the lungs are kind of the only thing that we have that kind of control over. Is that fair to say, or am I missing something there?","offset":1143,"duration":31}],"startTime":1073},{"title":"Regulating the Nervous System","summary":"Brian outlines how breathing influences digestion, heart rate variability (HRV), and sympathetic nervous system activation. He details how breathwork acts as a powerful recovery tool for overtrained, highly stressed individuals.","entries":[{"text":"Brian: Your- your breath is- so, check this out. This and this might flip your lid.","offset":1174,"duration":8},{"text":"Host: I'm ready.","offset":1182,"duration":1},{"text":"Brian: Your- your breath controls all of that.","offset":1183,"duration":3},{"text":"Host: Okay. Rest and digest is controlled by the breath.","offset":1186,"duration":4},{"text":"Brian: BKS Iyengar has a quote. He is responsible for bringing yoga to the Western world. He's one of the last great yogis. What- now, he also taught things in a way that was fairly brutal. Um, it would not have gone by real well today. Um, nonetheless, I- I'm of that school. Like, I- I like that- I don't need to be coddled. I- I- I want work, and I want real work. Um, nonetheless, the mind is the king of the senses, but the breath is the king of the mind.","offset":1190,"duration":41},{"text":"Host: Hmm. I like that.","offset":1231,"duration":2},{"text":"Brian: Okay? So, that was his. It's not mine. My breathing affects how I digest things. How so? Well, my diaphragm pushes down into my organs. I have regulation of my para- I- I- I have regulation of my sympathetic activity due to how I control my breathing. The inhale is known as the sympathetic and for a long time people have said the exhale is known as parasympathetic. Well, it's not parasympathetic. It's inhibition of sympathetic.","offset":1233,"duration":35},{"text":"Host: That's interesting, because that's that's where HRV, a lot of HRV stuff gets um, wrist monitors and stuff would come from, right? It's the variation within heartbeats.","offset":1268,"duration":11},{"text":"Brian: Yes. Yes, yeah. And so the con- we- started figuring out a long time ago that you could manipulate heart rate variability through breath control. Easy. So you could change a profile of an athlete who who might not have the score or the readiness state that we want, right? And we'd apply breath work to that person and we could manipulate and then they'd have a green light.","offset":1279,"duration":28},{"text":"Host: What's readiness state? What- what's the- uh, characteristics that contribute to that?","offset":1307,"duration":5},{"text":"Brian: You fit into a specific profile of- so, like, think of a spectrum, like think- think of an arc, right? Um, of sympathetic and parasympathetic, right? There's a specific arc with para- inside parasympathetic and slightly into sympathetic that you can be in order to be ready to train at let's call it 80% and above, right? So we would have- if an athlete fell too parasympathetic, that meant that they were literally, you know, you're dissociative, you're shutting down type of thing, you need more upregulatory things like cold plunge, like some, you know, things to kind of bring you up out of that. Um, but lo- from the- and there's there's a lot more to that. But from a more sympathetic side, this is where most of us tend to fall, is where we just aren't coming down enough. We're not coming out of that high sympathetic activity. That's by and large most of the people I deal with and I see. This is the people who are probably listening to here.","offset":1312,"duration":66},{"text":"Host: The overtrainers, the people that are caffeinated, overworked.","offset":1378,"duration":4},{"text":"Brian: Yeah. I like coffee, I like to work out hard, I like to uh work hard, I'm very passionate about what I do, I'm type A, you know, maybe not so type A, but I do like to train hard and do things hard and do all this. And and by and large, what we end up getting with those people is an inability to understand actually what they're training for. Like they, you know, and this is why breathing's so important is because I can actually get you to understand a lot more through that process of training and understanding your breath. It's also why we created a gear system around training and how you can actually manipulate the one variable that is actually responsible for the rest of the variables that you're training for.","offset":1382,"duration":44}],"startTime":1174},{"title":"The CO2 Tolerance Assessment","summary":"Brian details his three-part CO2 tolerance test involving a controlled, maximum exhale. He explains how this assessment acts as a diagnostic tool for an individual's mechanical, physiological, and emotional reactivity.","entries":[{"text":"Host: Hmm. Yeah, that is that is right. And it- it does make sense that you have this direct control over one of the internal processes that's going on. We have a, I suppose, a quite diluted control over the thoughts that go through our mind, but I have a lot better control over my breath than I do the thoughts in my mind, and that's after three years of pretty consistent meditation. So, I think I think focusing on the breath seems like a good place to start. So if we were to do a uh breath MOT, Brian, where would you- where would you start? If you lay someone down, you're gonna look under the hood, you're gonna look at the way that they breathe, either in or out of- of a training situation. Where do you start? Is it the cycle? Is it the pace? Is it-","offset":1426,"duration":39},{"text":"Brian: I start with a CO2 tolerance test. I get a CO2 tolerance test down on 'em, a max exhale test. That tells me literally what's going- like, I mean- look, so my- Rob who I work with, he's in Virginia Beach, which is lar- the largest hub of um special forces, so special warfare in the world. Um, it's where they house seal te- Dev Group, Seal Team Six, um, you know, there's another team over there too, but there's a lot of high-level dudes over there.","offset":1465,"duration":28},{"text":"Host: A lot of badasses.","offset":1493,"duration":2},{"text":"Brian: Yeah, but these dudes like to train a certain way too, right? And so, you know, like you get these guys and and they've got problems going on and it's like, \"Alright, you know,\" Rob got called in yesterday for- or no, this morning. We were on the phone this morning and it was his afternoon and he um- it was like, \"Yeah, I- I couldn't finish training, I got called in to go over to this uh- this place to go meet this guy who seems to be a pr- pretty problematic and he's got a lot of issues and he can't recover, he's got these injuries going on and blah, blah, blah,\" just a whole host of shit. And he's a team guy. And um, you know, he- Rob went over and he's like, \"Guess what his CO2 tolerance level was.\" And I was like, \"Under 20 seconds.\" And he said, \"17 seconds.\" And I was like, \"Yep. Get it.\" And uh, you know, he is cooked.","offset":1495,"duration":57},{"text":"Brian: And most of us are cooked. If I've got somebody who's training like that, if I've got an operator, especially an operator, who's got anything under a minute of a CO2 tolerance test, I've got somebody who's reactive, I've got somebody who- their system is reactive. They might not be emotionally reactive, but their suppression of things- I know that. The tissue isn't responding well, meaning they're tight, they've probably got painful tissue. Like, these things start to like compound, right? And they're all signs- like- so, so carbon dioxide is the metabolic stress messenger of the body, of the system. We don't even need an amygdala, man. You know, so it tells me what's going on with the person. So if- like when I have too much going on upstairs, I push that CO2 tolerance down, right? If I'm overtrained, if I've been training too much and I haven't let my body recover enough, I'm pushing that CO2 tolerance level down. When I think, when I do too much, I'm pushing that CO2 tolerance level down. Meaning, when CO2 raises, it doesn't have to raise as much in order for me to react to it- respond to it- and the first respondent of that is your breath because I have to offload that CO2 in order to feel better. So my aerobic efficiency, capacity, threshold, whatever, switches based on how much- how- how well I tolerate CO2.","offset":1552,"duration":94},{"text":"Brian: It's also telling me what basically is going to be happening cognitively. So if I get a person, the first thing I'm doing with them most likely is a CO2 tolerance test to tell me exactly where they're at. It's a threefold test. So, I- we- you sit down for a couple minutes or you lay down for a couple minutes and you just do some slow controlled breathing that you're comfortable with. Not fast, you can't hyperventilate. Then we go into a four-breath pattern to where we breathe up for like three- three or four seconds and then you relax, let it go for about five to seven, you know, five seconds or so. So it's a little bit longer of an exhale, but let's relax, let it go. Then inhale. Fourth breath you pull it in, you start the timer the moment it hits the top of the breath and you start exhaling as long and as slow as you possibly can. So you have to control it.","offset":1646,"duration":50},{"text":"Brian: So this- there's a three-part test in that it tells me how much control you have of your diaphragm on the negative, how well I have control of that, so there's the mechanical aspect of it, right? Then from a physiological perspective, it tells me how well you how- how well your physiology is responding to carbon dioxide, so how aerobically efficient you're going to be just calm. Okay? Remember the dog- walking the dog story? How- how well do you respond in a very simple fashion to carbon dioxide? Cognitively, so from a state perspective and arousal state perspective, how what you- how you react to carbon dioxide. The panic switch. So when you're going to be reactive, how you're going to be reactive. Anybody below 20 seconds and we have a very reactive volatile environment that we need to actually start working to clean up.","offset":1696,"duration":58},{"text":"Brian: And that's usually done fairly quickly with most people if and only if they're willing to actually back off a bit and learn. That allows for a gap to start to occur, an improvement to start to occur in the CO2 tolerance. So then we start to administer some breathing protocols: \"Hey, let's figure out-\" and this is why we built the State app was so that we could actually get people some protocols to use to actually work on breath control to increase uh their CO2 tolerance, but also allow them to kind of get into this more focused or calm, clear state um or downshift them prior to after training or prior to bed. That was the whole point of that. And so we'll set protocols up for people based on where they need the most help.","offset":1754,"duration":54}],"startTime":1426},{"title":"Customizing Breath Protocols","summary":"Moving beyond one-size-fits-all methods, Brian emphasizes the need for individualized breathing protocols. He also explains why large athletes with high muscle mass must improve their aerobic efficiency through nasal breathing.","entries":[{"text":"Host: How much of the breath control that we're talking about there is simple ability to avoid discomfort? Because someone who is in a good place, who might feel like \"I can control this gasp reflex for longer,\" that'll contribute a little bit, but as you've mentioned as well, the CO2, this CO2 tolerance appears to be like the master of this. Is that right?","offset":1808,"duration":25},{"text":"Brian: Yeah, so what's the question? Am I rephrasing? Or- or- you're bringing that back again?","offset":1833,"duration":4},{"text":"Host: So, how much can be trained in terms of someone's ability to breathe that is um separate to the way that their physiology is put together at that time? So, is there someone who's very good at controlling their breath but still might be in this-","offset":1837,"duration":14},{"text":"Brian: Yeah, yeah, yeah, yeah. So, that- that's- that's the interesting thing. And this- why- this is where my work really diverted because I was running around with guys like Wim Hof- I was literally pretty close with Wim Hof. Um, and there's nothing- like Wim's got a great thing, he's doing great work, um, you know, uh there's other- like I've gone and participated and learned about Tumo, um many of the you know yoga practices, etc, etc. Holotropic, um, like there's Buteyko, um, like there's a lot of methods out there, right? And unfortunately each and one of each and every one of these methods is making claims that it doesn't do in some fashion. In some fashions they do, in other fashions- and this is the problem with you know getting caught up in and understanding our attachments to things and you know thinking that you know we've got an answer, and the answer is you. You're the answer, you're the only answer there is. It's not your breathing, your breathing's not an answer either. It's just an indicator of something, right?","offset":1851,"duration":59},{"text":"Brian: And so our ability biologically is- is not even close to being tapped. And I I think that be true even with something like, you know, what happened with Eliud. But going back to this is- I started seeing that not everybody reacts to the same protocols in the same way. Hmm. And so it became a there is not a one-size-fit-all fits all. There's a- there's a more or less kind of a fingerprint to some degree. And although we can bucket people and categorize them in specific ways or you know things that are going on, like \"Hey, this guy is angry about stuff and that guy's angry about stuff and she's angry about stuff and you know she's more emotional and he's more emotional about things,\" like- like meaning, depending on how you emotionally handle things, there are going to be certain patterns that are going to set certain th- things off and connect you to certain things.","offset":1910,"duration":56},{"text":"Brian: So, we had to I had to start- I was literally running around fingerprinting people with breath breath protocols because not everybody was responding the same way, and that wasn't a very you know viable thing for helping people. I was sure I was helping specific people, but I was burning myself out and there was no way I was ever going to be able to do this by myself. So, build an app and build an algorithm that work with that and we understood how to do that. So, we we literally customize things to people, but then it's like, okay well a lot of these people like to engage in performance, and they should because you should have a movement practice. Any human being that does not have a movement practice is not being a human being. Um, we we are designed to move. Now, getting neurotic about that to the degree that like I have to be this specific thing or whatever, that that's where it gets crazy.","offset":1966,"duration":50},{"text":"Brian: But nonetheless, applying this inside of movement, the framework of movement, becomes the next catalyst in how we do things. And the base layer of that is, hey, for the first few weeks we're going to just be nasal breathing. You can't go anything past nasal breathing. And for most people that's such a kick in the balls that it's like \"I don't want to do- like my ego's not ready for that check.\" And, you know, you take a powerlifter that squats a thousand pounds, I can tell you right now if they've not done any breath work, their CO2 tolerance is shit. That's a massive, massive carbon footprint. You're carrying so much lean muscle, so much muscle, but you don't do you know most of these people don't do enough of the kind of aerobic efficiency work and and that's a scary word to guys like that and and gals because they think they're scared of aerob- and it's like that's not what I'm talking about. What I'm talking about is the thing that actually makes you survive.","offset":2016,"duration":57},{"text":"Brian: Like, aerobic metabolism is what makes you survive. So when you're resting, you should be high level aerobic. And yet you see these guys and gals on oxygen tanks and like breathing like [panting heavily] and- that's not necessary. It's not. And and it's not healthy. It's an indication-","offset":2073,"duration":20},{"text":"Host: What's that due to?","offset":2093,"duration":2},{"text":"Brian: Por- poor CO2 tolerance.","offset":2095,"duration":2},{"text":"Host: Okay. And that is exacerbated by people who are high mass, high muscle mass, heavy weight.","offset":2097,"duration":8},{"text":"Brian: Huge- look look- how what's the demand for oxygen with more muscle mass? It's up. Higher. So I need more oxygen in order because the mi- like look or- like- you know, so I've got all this tissue. Well, when I don't have enough oxygen or I'm not efficient enough [panting heavily], about four five breaths in, you're going to start dipping that needle more towards those anaer- like more towards the- the demand for the tissue's demand for more glucose, more glycogen. Okay? The nervous system and brain are- are stuck with glucose and glycogen. There's no- there's no if and but- and buts about that, right?","offset":2105,"duration":43},{"text":"Brian: But fat is what the muscles like can use. So the more fat we're using with the tissue, the better, right? And so the better we get the mitochondria functioning, the better off we are. And there's no reason why an NFL lineman and a gymnast or an endurance athlete can't all be aerobically efficient. It's just different thresholds at which point- like- sure, the lineman's going to be much more of an anaerobic athlete. Like much more high level, you know, spr- sprinter type explosive, you know, and so's the gymnast to some degree is, you know, pulling it back a little bit more. And then we got the endurance athlete where you're like, you know, all slow twitch, right? And it's all the same thing in terms of efficiency aerobically. So if I've got an- if I've got an endurance athlete who's going out on an- high level aerobic ride, but they got to open their mouth, I can tell you right now they're not as aerobic as they could be. They might be somewhat aerobic, but they are not as aerobic as they could be and they are not utilizing the system in a way that they could. This- this is literally factual things we have tested that are now going into re- that- that have raised some eyebrows enough to go, \"Wow, we didn't really look at it like this. We should really be testing this.\" So, this is what's happening.","offset":2148,"duration":79}],"startTime":1808},{"title":"Practical Steps for Better Breathing","summary":"Brian provides actionable advice for listeners looking to improve their daily breathing. He recommends using specific app protocols morning and night, alongside a challenging three-week phase of strict nasal-only training.","entries":[{"text":"Host: I get it. So, let's take it from the top with regards to Brian's advice for good breath. Where do we begin with that? What are the- what are the principles for good breath?","offset":2227,"duration":12},{"text":"Brian: Like the State app was created for this. Like look, start in the- do one- one breath protocol exercise in the morning, do one in the evening for sleep. Play with that for a few weeks, see where it improves what you feel, how- what you like, what you don't. If you want to play with more, go for it, right? That's probably going to be in the vicinity of five minutes each, right? That's not hard for people who like to train.","offset":2239,"duration":27},{"text":"Host: Morning and evening.","offset":2266,"duration":1},{"text":"Brian: Morning and evening, right? Simple. If you want to do all four, go for it. Do it. Like, you're- you're getting an A+ now. Um, the- the second part of this is if you're not going to the world championships or you're not competing for, you know, an Olympic medal or you're not like going to an A-priority race within the next two months, you do- like- there's no reason why you can't go dedicate three to four weeks to strictly nasal only breathing and take enough step back to actually get your physiology rewired.","offset":2267,"duration":38},{"text":"Host: Across all- across all training methodology? Whether you're-","offset":2305,"duration":3},{"text":"Brian: Across all training methodology. I don't care if you're an MMA athlete, powerlifter, Crossfitter, whatever. I've done it with the Crossfit athletes. I did it with Tia. Like, I've done it with like I've- done it with several fucking athletes that people would never consider would do- would be able to do something like this. And it rearranged what was going on and gave them an ability to do things that they didn't think they could- they could manage to do. And so it just empowered them in a level. Yeah. Yeah.","offset":2308,"duration":34},{"text":"Host: What- I mean, how long does it take to create adaptation to something?","offset":2342,"duration":4},{"text":"Brian: Right around three weeks.","offset":2346,"duration":3},{"text":"Host: I like it. I like that. Um, of course, everyone who is listening, the State app will be linked in the show notes below. Brian's app, which I'm pretty certain- is this the first iteration or is it on to kind of like a 1.5 now?","offset":2349,"duration":14},{"text":"Brian: What's- the app?","offset":2363,"duration":2},{"text":"Host: Yes.","offset":2365,"duration":0},{"text":"Brian: Uh, this is the first ver- there's been a couple updates on it. Yeah. Yeah. But this is the first version of it. We're- there's- there's a lot more that's going to come into the pipeline of- once we get through the first investor stuff that we're going through. Uh, there will be some serious, serious things that are coming down that pipeline. Um, you know, I mean, it's already a- it's been way more successful than we ever thought it was going to be. Um, but we also know like- there's- there's a lot more that we do than just doing some simple breath protocols. Like there's high-level things you can do in order to change your physiology that could, you know, that are game-changing things.","offset":2365,"duration":47},{"text":"Host: Hmm. So what happens when you breathe through your nose? Tell me. Someone's training they're just breathing through their nose. What's happening? Why- we've talked about the- the different workout of the walk with the dog with the nose open and closed. What- how's that characterized?","offset":2412,"duration":14}],"startTime":2227},{"title":"Evolution and Elite Endurance","summary":"Brian explores the evolutionary origins of aerobic metabolism to explain why nasal breathing is biologically optimal. He uses marathoner Eliud Kipchoge's nasal breathing technique to illustrate supreme aerobic efficiency.","entries":[{"text":"Brian: It's- it's your biological way of staying aerobic. 500 million years ago, cells single-cell organisms figured out how to become multicellular organisms. They said, \"Hey, let's you and I communicate like you and I are right now. Let's talk about some things. Let's share some information so that we can pass this shit on and p- see that oxygen-rich environment now? It used to be hostile. It used to be mostly carbon.\" Like and it was we had to be mostly anaerobic and we changed energy otherwise. And this is where like we're headed right now is this is all about energy. There's nothing else. There's nothing other other than energy. All energy that's ever existed has existed. It's how we're con- the conversion of energy is happening. We don't b- it's not we burn- we don't burn calories. Okay? That- that's us- we're converting calories. We're literally taking energy converting that energy and then putting energy back out. Like it's literally this cycle of and we forget about all this thing. And so that energy deal got made when cells learned to communicate and said \"Hey, let's take this oxygen and let's use this,\" and it's much more complex than this but this is just the story that I like you know like- but it's like, \"Hey, 500 million years ago multicellular organisms figured out how to use oxygen after algae and algae literally figured out how to convert sunlight into energy itself and the byproduct of that was oxygen.\" So the Earth became engulfed in this algae, all of a sudden there's all this oxygen in the environment. Then cells were like, \"Yo, there's a- got to be an efficient process to this.\" And here's that process.","offset":2426,"duration":93},{"text":"Brian: Today, 500 million years ago, aerobic metabolism sits at the forefront of the most efficient way to use energy. And so anything outside of aerobic metabolism becomes anaerobic. So if I don't have that process that conversion of energy I'll default very simply and we should to this higher stress situation of using energy. So anaerobic doesn't necessarily become a training process, it's more or less the byproduct of I'm no longer able to handle aerobically what's going on. So how quickly I can come back to that aerobic is literally how well I can. So having a very high aerobic capacity means I function higher aerobically. So when we look at people like a guy smashing the two-hour marathon, what does he look like physiologically? And although there's like look to be total like look I support and I'm very happy for the man and everything but realistically if he were in the same setup as they were in 1950 or even 1980 he wouldn't have run a sub-two-hour marathon. That that wouldn't have- it's not the same marathon. It's a different marathon even though the distances are the same. The shoes, the pacers, the- the- all of these things exist, but I don't deny the fact that this man's physiology is off the hook and the only reason I really know that is not only have I studied how he moves, but I've watched how he breathes.","offset":2519,"duration":108},{"text":"Host: What's your analysis? What's your analysis of his-?","offset":2627,"duration":2},{"text":"Brian: He primarily breathes through his nose.","offset":2629,"duration":3},{"text":"Host: Okay.","offset":2632,"duration":1},{"text":"Brian: Most of his marathon is done nose-only breathing. You can find pictures all over the internet with salt marks that come down his nose, and you'll see when he's running that most of the pictures are of him with his mouth shut. Hmm. I did notice that. So I've watched video. Yeah. Yeah, I've- I've- I've videoed the video so that I could go and slow it down and look at it and watch it, and you know there it is. And, you know, I mean he comes from African culture, right? And what what is of the African nose? Like they've got larger nostrils. Well, they've dev- like genetically they are set up to do something. Like if you've ever watched a horse race- so I watched an- I watch animals like like- it's a like big passion like I'm almost neurotic about it. You know, you watch animals who don't sweat and they don't actually the only time they're mouth breathing is when they're overheating. Okay? You watch animals who do sweat, a horse, a racing horse, they will not breathe out of their mouth. They just have a bit in their mouth. They breathe through their nostrils. They literally will not breathe out of their mouth.","offset":2633,"duration":76},{"text":"Host: Why do we then?","offset":2709,"duration":4}],"startTime":2426},{"title":"Historical Wisdom on Nasal Breathing","summary":"Referencing 19th-century observations of indigenous cultures and Comanche warriors, Brian highlights how native populations innately understood the benefits of nasal breathing. He contrasts this wisdom with the chronic overstimulation of the modern world.","entries":[{"text":"Brian: Uh, you know, it's interesting, we have um done real well at progressing ourselves culturally through comfort and convenience. And in that process we've more or less stressed ourselves more than we actually needed to. So by that I mean this. Uh, there was a book written in 1867 I believe, I forget the date, um but George Catlin wrote a book called \"Shut Your Mouth and Save Your Life.\" And he wrote this book as a historian who was a lawyer from England who came over to the State- which was basically North America and South America at the time- studied about a million and a half indigenous cultures and civilized world. He was uh the biggest thing he picked up on was the fact that in- in indigenous culture, they did not breathe through their mouth, rarely. And- and when they- when they spoke, they spoke with intent. They did not speak too much. They meant what they said, they said what they meant. When they slept, they slept with their mouths shut, when they hunted, they hunted with their mouths shut. They did everything they could, including when children came off of the nipple, mothers would shut the mouth of the child for fear of the black mouth. Because not only was the white eye called the white eye or round eye, he was called the black mouth. And the reason he was called the black mouth was because his mouth looked disgusting.","offset":2713,"duration":108},{"text":"Brian: And why would that be? Well, look at what we started doing cultu- look at what we- were starting to do. I mean, we were drinking more alcohol, we were- sugar started to become- agriculture started to kick in, all of these things of convenience started to happen, right? And here's a culture of people who pay attention to nature. What is nature? Physiology. That is literally one of the definitions of- of physiology is nature, origin. And thus paying attention to the feelings of nature and what's going on. So what happens when I feel when I breathe through my mouth? Right? Well, I get ramped up, I turn on, I speak. If I go speak somewhere and I talk just for an hour, I'm on, like I feel like I'm on. If I speak for an entire day, I'm exhausted. I don't go work out, I try not to go to dinner with people afterwards. Why am I so exhausted? I'm blowing off a ton of carbon dioxide, I'm more sympathetic dominant, I'm actually using less of the fat so I'm- I'm not as aerobic as I could be, even though I am still slightly aerobic, I'm not as aerobic as I could be, right? So it's learning those waves, they felt that shit, man. They felt it.","offset":2821,"duration":70},{"text":"Brian: We don't feel. We have- we have these things in front of us and we're getting stimulated and we've got all these kids that are going batshit crazy because they don't have recess anymore, they're pulled from play, they're told what to do, they're told how they're going to learn, then they're given infinite possibilities on a machine to play games and keep them occupied because Mom and Dad don't want to deal with 'em. And then they've got anxiety because of this. They don't have anxiety. They've got proper stimulation from being overstimulated. They've got physiology that's run amok and they don't understand it, and this has been by and large what's going on with us even those of us that like to train a lot. Like I mean, I'm on I'm talking to you, I'm on, I need to sh- when I'm done here, I mean I'm feeling this. I feel it. So I've gotten to the point where I feel all this stuff and I'm paying attention. If my mouth opens when I'm asleep at night, I wake up.","offset":2891,"duration":55},{"text":"Host: Why? Why would you wake up if your mouth opens, based on everything you've just gone over?","offset":2946,"duration":9},{"text":"Brian: Because you become more stressed. Bingo. I'm now slipping more into sympathetic and I'm turning myself on. Hmm. Okay. I understand. How many of us are trying to sleep in this high sympathetic activity state, right? And I'm also not as aerobic, and then oh shit, I've got sleep apnea so now I'm holding my breath in an awkward fashion and [gasps and exhales heavily] like, I've got all- like weird. Like, what are you paying atten- are- like, you need medication and a fucking- you need a mask to wear at night? I've got friends who do this and they refuse to do breath work and I'm like, \"Dude, it's your choice.\" Um, I've got more DMs and P- I don't even talk about this I don't write about this stuff publicly. Like I don't go out and go, \"I'm going to solve your problems.\" No. Here, start with some breathing protocols, start rearranging your training, then start feeling what's going on in your body.","offset":2955,"duration":54},{"text":"Brian: You're going to default to places that you can. Is it weird that George Catlin was also in a book that I've read and the- I'm the only person who's caught this so far, right? Only because I've read this other book. It's a book called \"Empire of the Summer Moon\" and it is about the Comanche Indians who are arguably the- the most war-driven tribe of people that have almost existed. They- they're in comparison to the Mongols in like- uh lot of the stuff that happened with 'em, but they were very, very gnarly. They were so gnarly that had the Colt revolver not ended up in the hands of a few young white boys from Texas called Texas Rangers, they would have- this world- this country would be a very different place right now. They knew how to fight off of horseback in a way that no other culture had understood and they couldn't combat it. So shooting a rifle with one shot was no good, right?","offset":3009,"duration":61},{"text":"Brian: And so this book was written and there was a guy around- there were a number of historians that were there that were interviewed and one of those historians throughout this book that was written about was George Catlin. And so there's this guy that's there and the biggest thing he picked up on was that the people who were of the of the- Earth, that were literally living on the Earth, that were living in planes that everybody feared to cross because they had no idea how to navigate, they had no idea how to do things, and there was this murderous culture of people who did not want them near anything and- including other tribes, like other tribes feared the Comanche, right? Like they were feared. And it- it's a fantastic read.","offset":3070,"duration":49},{"text":"Brian: But the fact of the matter is is I'm able to now connect through reading physiology and then reading about literally \"Hey, George Catlin wrote this book in the six- in 1800s about this,\" holy crap, there it is! What is history? It's literally telling us what's going on with- like- there's- there's lessons to be learned about all this stuff and what people were doing. You think- you think a Comanche Indian who knew how to navigate the land could get on his horse and ride for three or four days straight with no food basically, or limited food supply and water supply, what do you think the physiology of a human being like that is? Like, literally could survive in freezing cold temperatures, navigate land in storms, like where do you think we're at culturally right now? We're worried about squatting a thousand pounds and running a two-hour marathon. I don't think we're anywhere close to what our biological potential is. I think we missed the boat. I think we're confused. I think we think that technology is this great thing that's going to get us into the future and it's not. It's going to just lead us right back to our own biology and going \"Shit, we're mimicking all this technology after stuff we internally are able to do.\" It's why I asked you what- how would- how- how do you control your heart rate and how do you feel that? \"Well, I'd have to be calm for a minute and then I could really pick up on-\". Yeah. Well, guess what? You can feel that at any moment you want. Just got to spend the time to get back to that.","offset":3119,"duration":85}],"startTime":2713},{"title":"Redefining Human Performance","summary":"Brian explains how excessive talking and visual focus affect our autonomic nervous system. He redefines human performance not as physical lifting feats, but as the ability to make better decisions under stress without relying on ego.","entries":[{"text":"Host: I understand. Yeah. It's interesting what you said there about when you spend a whole day talking, right? So I do coaching calls. I coach a sales company in Germany and every time I'm done, let's say it's maybe three hours and I've been talking to these guys, and it's a conversation. It's at least 50-50 between me and them, it's not all me. But once I'm finished, let's say I've done three hours, four hours of- of talking, little bit of water in between, little bit of chill or whatever. After I've done that, I'm absolutely gassed. Like once I'm done, I'm like, \"Hhh, I'm really tired.\" And I wasn't really sure- I thought, well maybe it's because cognitively it's quite demanding, I'm trying to link these things together, it's because I'm really putting myself into the person I'm speaking to or whatever it might be. And your suggestion here is that one of the principal reasons for this is going to be that I'm just inhaling and exhaling quite a bit of air quite a lot.","offset":3204,"duration":53},{"text":"Brian: Well, your- yeah- you're on, right? And so you're getting stimulated, but you're getting a stimulation that you're automatically like you're falling into autopilot on because you're talking, I'm talking, right? So we're- I'm ramping myself up. Not only am I ramping myself up and getting into what I'm doing, I'm getting focused and I'm being engaged with you, but the byproduct of that becomes my breath. My breath is the instant reaction to that. It- it's- it's the first respondent. There's only two- two things we can do in order to regulate or- or stimulate autonomic control consciously. That is our breath and our vision. So I can choose not to look at you right now and I can look at the end of the room and I can go into peripheral vision and I can downshift myself. I can go outside and look at the fucking look at nature, look at trees, right? How many people freak out looking at a sunset? None of 'em. Why? Because it's math. No, it's beautiful. Yeah, beautiful's there, but that's not math. Math is the algorithm that and it's the light waves that enter your eyes and open you up to go \"whomp!\" and it drops you into parasympathetic.","offset":3257,"duration":78},{"text":"Host: It's interesting vision side.","offset":3335,"duration":4},{"text":"Brian: We've got so many tools and things going on that we don't know about. I- literally man, I was just at the Cleveland Clinic, I was in open-heart surgery with them with a team there, and they were like, \"What do you think you could help with?\" And it's like simple man. Control your breathing and control your vision when you need to, when you need to make a better decision or something fucking- the shit hits the fan. Like, it's time to do that. That's human performance. That's human performance at its finest in trying to help somebody's life be saved, you know? And like why'd that person get there is another fucking- another story that we could be dovetailing back towards \"Hey, why we move and what we love about human performance.\" But that's human performance for me. Like human performance is literally getting to the core of why you know people doing everyday stuff, right? Like that's human performance. And I think we're eluding ourselves into thinking that we understand something by, you know, like \"What's a 500-pound deadlift do for me?\" These were- these were things I had to ask myself, right? Like this isn- I'm not asking this of you, I'm- I had to ask this of myself. What's a 500-pound deadlift? Because I've had a 500-pound deadlift, right? And it's like I- I was not able to connect the dots on what that meant. That I don't know that that made it better for me to survive. Getting up off the couch or picking shit up off the floor? I- I don't know that that 500 pounds is necessary for that.","offset":3339,"duration":81},{"text":"Brian: Like \"What's running 100 miles doing for me?\" It was a fucking amazing spiritual experience. But what was it doing for me, right? And like where was I at? And so what- you know- do I need to actually run 100 miles? No. But will I? I mean sure, I did a couple times but, you know, like- it's just- like I've done these things and I'm like so what's the point of this? Is this oh, I'm now clinging to this thing thinking it's the thing and- there we go. Now the mind now- now let's look at the ner- let's look at the neuroscience. Let's let's really start looking at the down the up- how everything's compiling and what I'm doing and why I'm doing it. So when I ask people like what do you want? Because they'll come to me. I literally have a call after this from with our mentorship program and I've already had two today. And it's \"What do you want?\" And I'm pretty quick to to understand that they don't know what they want even though they're telling me what they want. And so it's usually like \"Tell me what you want, I'll show you a liar.\"","offset":3420,"duration":62},{"text":"Brian: Because we're just not ready- really ready to let go of all these ideas that we have and it's not that you can't go deadlift a thousand pound or you know whatever you can't squat a thousand deadlift 500 go run 100 miles. Like these are just extreme versions of 'em, right? I don't need to go dive with Great White sharks but I did and I got that experience and it taught me some profound lessons man, profound. But if I'm actually in the moment and understanding what's going on in this very moment and how I'm operating and what I feel, then I'm moving back more towards what that Comanche was doing. And I'm actually getting in tune with the vibration of how everything works and why when I go why- you know, I went on a run earlier. What I'm trying to accomplish with that run and understand about that run. Where is it that on this hill that I'm climbing right now that I have that I feel like I need to make this switch? And how like- how cooked do I feel and where is that at and what can I do in order to improve that so that like, hey, this- this improves my day and it doesn't ruin my day, right?","offset":3482,"duration":61},{"text":"Brian: That's what I'm talk- you know, this is where we start- my reactions to what I'm doing in training, my reactions to what I'm doing throughout my day are the same thing. But I'm just getting people closer to what that actually is. And that's what we've been doing with the Art of Breath is really just you know, like people come in there and like this gal this weekend who showed up at at Rob's seminar, she was like she's a Crossfit Games athlete and you know she identified as a Crossfit Games athlete, I love that. Like I just love somebody comes in \"I'm like a professional athlete, I'm a professional Crossfitter,\" like whoa, okay. Um, I get it. I know where you're at. Um you know and we're doing all this work and stuff and there's a hypoxic set where you do farmer carries with- with kettlebells, right? So like you'll do some burpees and then you go and we have people grab the the kettlebells and then they dump their air and they have to walk as far as they can down and back.","offset":3543,"duration":53},{"text":"Host: Okay, yep, just farmer's walk.","offset":3596,"duration":1},{"text":"Brian: Yeah yeah yeah. And and so everybody- like this chick just takes off running, man. Like she's trying to win it, you know? And one of our coaches, Danny Yeager, who's phenomenal, um he runs Crossfit Kingfield out in Minnesota and he's like he watches this and then he sees a bunch of guys. So there's a lot of people there in in the warfare community, and so there's a lot of you know dudes and people who are like want to win, right? It's like what are you trying to win? So Danny stopped and he goes \"Hey! If you think we brought you here to actually see how long you could hold your breath while farmer walking kettlebells, you don't understand why you're here. You don't understand what we're doing. What is it you're feeling when you're holding your breath and walking these things? What's- if you're trying to win the farmer carry holding your breath, what is it you're winning here? There is no reward. It's we're here to experience something and understand what this thing can do and teach us. Well, I thought I was going to be able to carry those kettlebells a lot farther, or I thought I was only going to be able to carry 'em a few steps and I went further than I did. Awesome. Now we're starting to get somewhere versus \"Oh, I got to win this.\" Like win what? What are we winning? That's called ego. And and you just removed yourself from understanding all purpose of- of training. All training at the foundation of training is to make better decisions under stress. Carbon dioxide is the metabolic stress messenger of the human body. Done deal.\"","offset":3597,"duration":112}],"startTime":3204},{"title":"Integrating Breathwork and Meditation","summary":"The episode concludes with recommendations on where to find Brian's programs. Brian also offers practical advice on how to effectively sequence breathwork before meditation and prior to sleep.","entries":[{"text":"Host: I love it. I love it. Brian, today's been fantastic. I really appreciate you coming on. Anyone who wants to check out some more of your work, where should they head? We've talked about Art of Breath. How does that relate to the State app? Is the State app a part of that? No.","offset":3709,"duration":16},{"text":"Brian: Does not- separate. No, State app's- a bit differ- um the State app's separate the you know a lot of the stuff with the business is going to change real soon. Um in fact the whole name everything's going to change, we're changing that so it all kind of fit and be seamless so it makes more sense to the world. Um that being said, the Art of Breath is a component of what we teach inside of Power Speed Endurance. It's a performance-based seminar, there's a 101 that we teach around the world but we also have it online. So that can be found on Power Speed Endurance. The State app is you can find each app whether it's Android or iOS on shiftstate.io. Anything about me or or if you want to get in contact with me or or you know whatever can be found on brianmackenzie.com or you can go through Power Speed Endurance.","offset":3725,"duration":50},{"text":"Host: Amazing. I- I have to say it was a listener who recommended that I- I check out the State app and get in touch with yourself and I think I've found the new thing that I'm going to add into my morning and evening routine. I've been looking for what it's going to be. I've stopped doing Rom-Wod for the time being and I do miss some of the breath control, I miss that parasympathetic activation. I'm still doing my meditation on a morning, I'm reading, I'm doing other bits and pieces, Stu McGill's Big Three, but I'm not I'm not feeling myself in the body quite so much with that. It's very- it's very visceral, it's very kind of um transactional that I'm doing it for the for the return on what I know it needs to do to my spine health. Um and I think I think the next- I think the- between now and Christmas it'll be- it'll be me doing that. So I'll report back, I'll keep you updated and I'll let the listeners know how I'm getting on.","offset":3775,"duration":51},{"text":"Brian: Please do. Please do. Yeah. Look at I- I would do the either \"Feel Alert\" or \"Be Present\" protocol if you're- if you're doing your meditation in the morning, do the breathing beforehand. There's a reason why breathing is at the foundation of every meditative practice.","offset":3826,"duration":14},{"text":"Host: That's interesting. So you'd say for a lot of people that are listening, maybe they have a meditative practice in their morning routine, you'd say do the breath work before that and then how- how do you program that in on an evening? Is it right before bed?","offset":3840,"duration":11},{"text":"Brian: If you have an active sitting, yeah. If you have an active sitting meditative practice, just be clear that if you want that brought up to the next level, add breathing before that. If you want it really brought up to the next level, use the State app so that you can fingerprint your- the rhythms that work with you. Like so your app's different- going to be different than mine based on you know how you actually handle carbon dioxide cognitively and how you handle emotional stress. So that can give you a ramp in. I can't tell you how many people who come to me who are like \"I can't meditate, it's just I don't have the patience, I don't have this, I don't have that.\" You're already there, but it's like I show 'em breathing and the fact is is breathing is a controlled breathing is meditation. Literally. Um you'll get there. Just give it some time, right? So use that beforehand. In the evening, anything less than two hours before you go to bed, okay, using the \"Fall Asleep\" protocol. That'll downshift you and change the sleep. You'll you should probably see some increases definitely in deep sleep, but also potentially in the REM cycle.","offset":3851,"duration":72},{"text":"Host: Fantastic. I've also got um my new Whoop band coming as the last one has um has lapsed, so I'll actually be able to track that and see if that's making any difference as well, which'll be- which'll be interesting. But Brian, today's been absolutely awesome. To the people that are listening, you already know what to do. The links to everything that we've spoken about, the State app, shiftstate.io, Power Speed Endurance, and Brian's website will be linked in the show notes below. Go hassle him online if um if you need to get some more info out of him. Um but Brian it's been- it's been fantastic, man. I'm really looking forwards to getting into my breath work.","offset":3923,"duration":31},{"text":"Brian: Right on, Chris. Thanks for having me, man.","offset":3954,"duration":15}],"startTime":3709}],"entries":[{"text":"Brian: Today, 500 million years ago, aerobic metabolism sits at the forefront of the most efficient way to use energy. And so, anything outside of aerobic metabolism becomes anaerobic. So, if I don't have that process, that conversion of energy, I'll default very simply, and we should, to this higher stress situation of using energy. So, anaerobic doesn't necessarily become a training process, it's more or less the byproduct of I'm no longer able to handle aerobically what's going on. So, how quickly I can come back to that aerobic is literally how well I can. So, having a very high aerobic capacity means I function higher aerobically. So, when we look at people like a guy smashing the two-hour marathon, what does he look like physiologically? And although there's, like, look, to be totally hon- like, look, I support and I'm very happy for the man and everything, but realistically, if he were in the same setup as they were in 1950, or even 1980, he wouldn't have run a sub-two-hour marathon.","offset":0,"duration":69},{"text":"Host: I'm joined by Brian Mackenzie, the man behind Power Speed Endurance, and today we are talking about something that you will all be familiar with, but are probably doing a little bit wrong: breathing. Brian, welcome to the show.","offset":69,"duration":12},{"text":"Brian: Thanks for having me.","offset":81,"duration":1},{"text":"Host: It's gonna be awesome. I'm really excited to speak about this sort of stuff today. We've been talking about endurance a lot recently. Had Alex Hutchinson, writer of Runner's World on analyzing Eliud Kipchoge's recent performance. We've had Brian Carroll from Power-X-Strength on talking about squatting over a thousand pounds, and all of this is enabled by a lot of different things, but I guess principally, one of those is breath work, right?","offset":82,"duration":29},{"text":"Brian: Yeah, well, physiology, and almost chemistry is regulated through our breath. So, anything and everything- I mean, I- I- I've known Alex for quite some time, we've kind of gone back and forth over the years, he's a great fucking kid, man. I like him a lot. I don't know your other- the other guy, but to squat a thousand pounds is to understand some things.","offset":111,"duration":27},{"text":"Host: He really does. He really does understand some things. I mean, Kelly Starrett, we just released an episode with him today, we've had Dr. Stu McGill on, so, you know, we've had a lot of these guys, and when they talk about this, even, you know, Kelly and- and- and Stu, people that are really, really kind of at the- the top of their game, very well respected in their field, it's rare that I hear someone bring up breath work. Why do you think that is?","offset":138,"duration":26},{"text":"Host: Kelly- Kelly didn't. Kelly didn't, no. We were talking a bit about the Game Changers- we were talking about the Game Changers documentary and veganism, we went off on a rabbit hole down that.","offset":164,"duration":8},{"text":"Brian: Oh, really? Wow. No, I know Kelly's very much into the breath work at this point. Uh, I mean, I introduced it to him, so, you know, and I know he- he uses it inside of his- 101s and 102 courses now, so, you know, from his work. But, you know, at any rate, Kelly's been a very close comrade of mine for a very long time. Um, so we've kind of grown up in the industry together, but, you know, the- it's interesting how I stumbled onto the breath work and why, even though I was introduced to it quite some time ago, and it just didn't take. And I understand why it didn't take, um, because it was never explained in a way that made sense to, especially, a guy who was participating in strength and conditioning was all about performance.","offset":172,"duration":51},{"text":"Brian: Yeah, I understand. So, I- I- I entered into this world of yoga many years ago and had a yoga practice because I was a triathlete who was getting tight. And when you get tight, you need to loosen up. And so I went to yoga and I ended up enjoying yoga real- like a ton. And I chased around a yogi in Ashtanga um, that was really good at what she was doing. But I just never paid attention to the fact that we were in- we were utilizing a breath practice at the foundation of this practice. Like we were controlling our breathing, we were told to control our breathing, we were told to control our breathing in specific patterns. You know, this went on and on, and I was like, you know, I just remember it blowing over to a large degree.","offset":223,"duration":53},{"text":"Brian: And that in and of itself is kind of how we all behave to a large degree, and I'm- I'll connect all this through this talk so that it makes sense for everybody else. Um, you know, but I largely just paid attention to the fact that I needed to get more flexible or more mobile at the time. And then I drifted away from yoga for a little bit, really got hardcore into endurance training, obviously wrote a couple books on that and came to a pretty good understanding of some ways to tweak things for people who are busy um, and who were injured. Um, you know, and that that was a big part of my career for about 10 or 12 years. And then somebody handed me a training mask and I laughed, and I was like, \"This doesn't change altitude. I know how pressure works. I've actually worked on altitude training for quite some time and this can't change pressure.\" So, you know, but nonetheless, you know, when you you you make fun of something and if you're in you know, done enough work in your life to understand that you haven't if you're making fun of things or you're crit- criticizing things that you've never used, that's called ignorance.","offset":276,"duration":75},{"text":"Brian: And I didn't want to remain ignorant to something, so I put the damn thing on. And I instantly went from like I'm seated now to I sat up and I engaged my diaphragm and I felt my ribs expand out and, like, my back light up, and like I was like, \"Whoa!\" Like, you know, it was it was just- I tend to feel a lot. And because of my background in teaching movement and getting people fixed, or helping people to fix themselves, I um, you know, I I was just like, \"Whoa, here- whoa! What happened? Like maybe we've got something that I could put on my athletes when they're warming up so that we can get 'em moving properly and using their you know, their core correctly, organizing their spine in a way that it should be, because, oh shit, like it just so happens that we organize the spine based on our diaphragm. We have to. At the- at the root of who we are and what we do is a system that is dependent upon one thing, and that is life. And that life is predicated on a deal that was made 500 million years ago in order to use aerobic metabolism.","offset":351,"duration":74},{"text":"Brian: So, suffocation sits at the heart of that. So we could remove our amygdala, our panic- our freak out- our, not our panic center, our fear center, and you will still have chemoreceptors that will set you off in a panic when carbon dioxide levels raise. So, if I'm not organized correctly around my spine, I don't use my diaphragm correctly, so I default into poor breathing patterns. So, this is a rabbit hole of movement that really made more sense to something about organization of the spine, right? And there's a- there's a lot of minutia around the spine and organization and core stability and everything we want to do, but by and large we have figured out and theorized that the only reason you need to organize that spine correctly is to actually take a breath and understand that breath. Because the lungs don't do that work on their own. The diaphragm is the primary in that and then we follow up through the intercostals and several other muscles that end up getting involved. But poor breathing habits elicit poor responses including that of the sympathetic nervous system, or I default into some poor breathing patterns that have me using my anaerobic system more than necessary.","offset":425,"duration":71},{"text":"Host: And is that in and out of exercise?","offset":496,"duration":2},{"text":"Brian: Yes, that is without exercise, my friend.","offset":498,"duration":2},{"text":"Host: Wow.","offset":500,"duration":1},{"text":"Brian: You are constantly using anaerobic systems and aerobic systems at all times. We all- we're like- this is- we know this. What we started seeing was like look man, we took a look back, so this started with a training mask and it inevitably became like \"Oh shit, you've got your own training mask on your face, it's called a nose.\" And holy crap, it like it has this filter system and it's got these- this humidification system, it's got- oh my gosh, this thing, mucus, oh, it releases like immune cells. Like, um, so it helps my immune system function better. I spinning the air differently, it forces my diaphragm to actually pull more because it's- it's not allowing for fast air to happen. It doesn't mean we can't breathe through our mouth or shouldn't, it's just when is it necessary? And we can get into that in a bit if you want. But, you know, it- it's interesting we we started understanding we started looking at the physiology behind all this stuff and the framework behind physiology, and we've missed some big, big things.","offset":501,"duration":71},{"text":"Brian: And it- it's all there, it's just the way we've taught it and the way we've looked at it has not been real um, I would say it- it's not a very creative process, thus why it's eluded us. And even in the world of yoga today they've missed it, and they've misunderstood what it is that pranayama actually means. And pranayama is a word that is basically- it's a Sanskrit word that's probably about 5,000 years old, and there's other languages that use these very similar terminology, including um, Hebrew, um, that it means \"energy control\" at its root. It also means \"breath control.\" Odd that they're the same. Odd that we use a cardiometabolic device in order to measure our breath, which tells us what's happening from a cellular level. So, through cellular respiration, we understand the only way we can we measure that is through the gas exchange of what's going on here.","offset":572,"duration":58},{"text":"Brian: So, we said let's look at this realistically and see what happens. And so we started measuring things, and we were measuring things in many different ways including just a simple breath practice um, or hey, I'm going to go for a walk, I'm going to walk my dog. And Rob Wilson, who's my counterpart in the Art of Breath, who's our lead on education- he's our Director of Education, um, went for a walk with his dogs with his mouth open. And then he came back, reset his device, and we have portable metabolic carts, and he shut his mouth and went for a walk with his dogs, the exact same route. Turns out those are two different and totally, totally different metabolic profiles. Weird. And- and it's not weird. This has been said for thousands of years. We're not actually bringing- we're not actually saying things that, you know, are that crazy, but unfortunately they are crazy in our world because there's so many really, really, really smart scientific people who we look to who've missed the boat on a lot of this stuff, and the simplicity of it.","offset":630,"duration":72},{"text":"Brian: And it's not that they're dumb or that they've you what- whatever, it's just we weren't really looking at this. And so we started really going after not only the movement and and and how the mechanics work around this, but then the physiology, right? Um, and then starting to see that, oh wow, it's all chemistry in the body is regulated through our breath. All of it. So how we shift from alkaline to acidic is literally governed through how I breathe, and how I absorb oxygen is dependent upon how well my body actually plays with this molecule this- this thing called carbon dioxide. In the body in the blood it's carbonic acid, and then as we exhale as it gas exchange it becomes carbon dioxide. But I am largely dependent upon how well I actually react to that and that can, you know, that has other facets to it, I'll go here in a second. But my relationship to carbon dioxide is actually how well I play with oxygen and how well I'm efficient- how efficient I am at using oxygen.","offset":702,"duration":64},{"text":"Brian: So, I may be a freediver who can actually sit here and do breath work and be very, very, very oxygen efficient because I can hold my breath for long periods of time, which also requires an ex- a very high level of CO2 tolerance. This is static CO2 tolerance. This is non-working CO2 tolerance. When we look at training or we look at human performance- and I use quotes because performance I think is- we're about to kind of shift a paradigm on what human performance is. Um, but the idea that if I work- like, when I start to work out, that shifts. There's a different response, or there's a- there's a very different play that happens within CO2 tolerance. And so I've been I've been able to observe and take people who are freedivers who are highly specialized, or big-wave surfers who are also, you know, freedivers in essence to some degree, but they're highly specialized.","offset":766,"duration":65},{"text":"Brian: And when we apply work to them, we see a very different story happen. So we see the specialist kind of come apart, right? Meaning, there's a very different- like that CO2 tolerance that was really high when I'm static and not a lot of stressors going on, or a big wave- some things like that- I'm very accustomed to. When I start working out, my respiration rate goes up considerably higher than it would with somebody, let's say, let's call it, you know, Eliud, right? His respiration rate isn't going to go up so high, right? But the interesting thing here is I would bet if Eliud's never really participated in any sort of static breathing or carbon dioxide tolerance training, he's probably shit statically. Right? And so there's this weird world that we started to see.","offset":831,"duration":46},{"text":"Brian: Now, my fascination is in connection with the brain and- so the neurobiology of it and the physiology. I'm- I- I'm now considering what physiology is more or less our mind. Our abili- that's what our mind is, and our ability to connect to the mind and understand the feelings and the processes and the things that are going on. And so the brain is where the circuitry and- and the information is being sent out. The brain works perfectly fine as long as we're connected to the physiology and understand the physiology. If we don't understand the physiology, the brain will get away from us and start overthinking, right? And so as kids, when we come into this world, we have this thing where we're attached to a parent and we learn- this is- it's unavoidable, right? And and so from a neurobiological perspective, at the top layer, the most evolved part of the brain is our neocortex, and this is where the stories- this is where some of the emotional things, like, start to trigger.","offset":877,"duration":65},{"text":"Brian: But this is where the storytelling, motor control- a lot of- there's a lot of dedicated area to motor control in the brain, um, to where we can do different tasks. Like I can talk or- like I can talk and drink water at the same time, or think and drink water. You know what I mean? I mean, just simple basic shit that we go throughout our day that some of us confuse ourselves in thinking it's multitasking, of which it's not. Um, so that's the storytelling side of things. Below that becomes the limbic system. This is where emotions are now concrete and set up in the system, and where I will have a reaction emotionally to something, and then the storytelling gets played into there, right? And so it can get exacerbated. Then down below that, we have the brain stem where the- or we could call it the reptilian brain, the oldest part of the brain. And this is where the kind of evolution of everything takes place. Oh, it just so happens that our respiration centers are set up in that brain stem. So, meaning, they are on autopilot with my system, and they can respond to every emotion and every thought that I have.","offset":942,"duration":60},{"text":"Brian: It also can respond to the work that I have because I have dedicated chemoreceptors set up in the carotid and the aortic valves which are headed out to the periphery. So that means we're on a prediction system that carbon dioxide levels that are set up in my brain stem react to a prediction of what's occurring in the system through chemoreceptors and baroreceptors that are in my arteries, and it's triggering me to breathe. So my heart rate responds to that, right? So the heart rate's late to the game. And so, you know, there's a whole plethora of things in there, but how I decide to grow up and how I go through my experiences in life inevitably have a Rolodex of things on how I actually respond to breath. So, when I actually am working out, I can tell with many people where the potential trauma or problems can set up, or we can see metabolic issues, even from somebody who doesn't work out as they sit and are doing things.","offset":1002,"duration":71},{"text":"Host: I get you. Yeah. Um, one thing that's just come to me there as you were talking. Do you think it's strange that we don't have control over our heartbeat as humans, as evolved creatures?","offset":1073,"duration":10},{"text":"Brian: Well, the only way you're going to control your heart rate is how?","offset":1083,"duration":5},{"text":"Host: Output? Movement?","offset":1088,"duration":1},{"text":"Brian: Nope.","offset":1089,"duration":2},{"text":"Host: Breath?","offset":1091,"duration":1},{"text":"Brian: You got it. So, if I just said, \"Hey, Chris, check it out. Control your heart rate for me right now.\" And if we put you on a heart rate monitor, because that's what you- we- most people would do, they go \"Alright, let me get on a heart rate monitor.\" Like, no no no no no. Can you feel your heartbeat right now without doing anything? Can you feel it?","offset":1092,"duration":24},{"text":"Host: A tiny bit- I'd have to be very tuned into my body.","offset":1116,"duration":2},{"text":"Brian: Yeah, yeah, yeah. It took me about- it- about three years ago I was able to like I can just sit there and I could pick it up anywhere in my body I really want to. Whether I want to do it in a toe or a finger or my neck or whatever, right? But it's like, alright, how do I lower that? And I literally will go [breathes in deeply and exhales slowly] and my heart rate will start to drop by controlling my breathing.","offset":1118,"duration":25},{"text":"Host: I understand. I think that obviously shows that the heart rate is um, at the mercy of the breath to a large degree. I was just thinking about whether it's- I can control my breath. I can consciously hold it, breathe quicker, breathe slower. But that's not something that we have with our digestive system, that's not something that we have with our heart. You know, that- that- it would appear that from our- the- the things that are inside of us, the lungs are kind of the only thing that we have that kind of control over. Is that fair to say, or am I missing something there?","offset":1143,"duration":31},{"text":"Brian: Your- your breath is- so, check this out. This and this might flip your lid.","offset":1174,"duration":8},{"text":"Host: I'm ready.","offset":1182,"duration":1},{"text":"Brian: Your- your breath controls all of that.","offset":1183,"duration":3},{"text":"Host: Okay. Rest and digest is controlled by the breath.","offset":1186,"duration":4},{"text":"Brian: BKS Iyengar has a quote. He is responsible for bringing yoga to the Western world. He's one of the last great yogis. What- now, he also taught things in a way that was fairly brutal. Um, it would not have gone by real well today. Um, nonetheless, I- I'm of that school. Like, I- I like that- I don't need to be coddled. I- I- I want work, and I want real work. Um, nonetheless, the mind is the king of the senses, but the breath is the king of the mind.","offset":1190,"duration":41},{"text":"Host: Hmm. I like that.","offset":1231,"duration":2},{"text":"Brian: Okay? So, that was his. It's not mine. My breathing affects how I digest things. How so? Well, my diaphragm pushes down into my organs. I have regulation of my para- I- I- I have regulation of my sympathetic activity due to how I control my breathing. The inhale is known as the sympathetic and for a long time people have said the exhale is known as parasympathetic. Well, it's not parasympathetic. It's inhibition of sympathetic.","offset":1233,"duration":35},{"text":"Host: That's interesting, because that's that's where HRV, a lot of HRV stuff gets um, wrist monitors and stuff would come from, right? It's the variation within heartbeats.","offset":1268,"duration":11},{"text":"Brian: Yes. Yes, yeah. And so the con- we- started figuring out a long time ago that you could manipulate heart rate variability through breath control. Easy. So you could change a profile of an athlete who who might not have the score or the readiness state that we want, right? And we'd apply breath work to that person and we could manipulate and then they'd have a green light.","offset":1279,"duration":28},{"text":"Host: What's readiness state? What- what's the- uh, characteristics that contribute to that?","offset":1307,"duration":5},{"text":"Brian: You fit into a specific profile of- so, like, think of a spectrum, like think- think of an arc, right? Um, of sympathetic and parasympathetic, right? There's a specific arc with para- inside parasympathetic and slightly into sympathetic that you can be in order to be ready to train at let's call it 80% and above, right? So we would have- if an athlete fell too parasympathetic, that meant that they were literally, you know, you're dissociative, you're shutting down type of thing, you need more upregulatory things like cold plunge, like some, you know, things to kind of bring you up out of that. Um, but lo- from the- and there's there's a lot more to that. But from a more sympathetic side, this is where most of us tend to fall, is where we just aren't coming down enough. We're not coming out of that high sympathetic activity. That's by and large most of the people I deal with and I see. This is the people who are probably listening to here.","offset":1312,"duration":66},{"text":"Host: The overtrainers, the people that are caffeinated, overworked.","offset":1378,"duration":4},{"text":"Brian: Yeah. I like coffee, I like to work out hard, I like to uh work hard, I'm very passionate about what I do, I'm type A, you know, maybe not so type A, but I do like to train hard and do things hard and do all this. And and by and large, what we end up getting with those people is an inability to understand actually what they're training for. Like they, you know, and this is why breathing's so important is because I can actually get you to understand a lot more through that process of training and understanding your breath. It's also why we created a gear system around training and how you can actually manipulate the one variable that is actually responsible for the rest of the variables that you're training for.","offset":1382,"duration":44},{"text":"Host: Hmm. Yeah, that is that is right. And it- it does make sense that you have this direct control over one of the internal processes that's going on. We have a, I suppose, a quite diluted control over the thoughts that go through our mind, but I have a lot better control over my breath than I do the thoughts in my mind, and that's after three years of pretty consistent meditation. So, I think I think focusing on the breath seems like a good place to start. So if we were to do a uh breath MOT, Brian, where would you- where would you start? If you lay someone down, you're gonna look under the hood, you're gonna look at the way that they breathe, either in or out of- of a training situation. Where do you start? Is it the cycle? Is it the pace? Is it-","offset":1426,"duration":39},{"text":"Brian: I start with a CO2 tolerance test. I get a CO2 tolerance test down on 'em, a max exhale test. That tells me literally what's going- like, I mean- look, so my- Rob who I work with, he's in Virginia Beach, which is lar- the largest hub of um special forces, so special warfare in the world. Um, it's where they house seal te- Dev Group, Seal Team Six, um, you know, there's another team over there too, but there's a lot of high-level dudes over there.","offset":1465,"duration":28},{"text":"Host: A lot of badasses.","offset":1493,"duration":2},{"text":"Brian: Yeah, but these dudes like to train a certain way too, right? And so, you know, like you get these guys and and they've got problems going on and it's like, \"Alright, you know,\" Rob got called in yesterday for- or no, this morning. We were on the phone this morning and it was his afternoon and he um- it was like, \"Yeah, I- I couldn't finish training, I got called in to go over to this uh- this place to go meet this guy who seems to be a pr- pretty problematic and he's got a lot of issues and he can't recover, he's got these injuries going on and blah, blah, blah,\" just a whole host of shit. And he's a team guy. And um, you know, he- Rob went over and he's like, \"Guess what his CO2 tolerance level was.\" And I was like, \"Under 20 seconds.\" And he said, \"17 seconds.\" And I was like, \"Yep. Get it.\" And uh, you know, he is cooked.","offset":1495,"duration":57},{"text":"Brian: And most of us are cooked. If I've got somebody who's training like that, if I've got an operator, especially an operator, who's got anything under a minute of a CO2 tolerance test, I've got somebody who's reactive, I've got somebody who- their system is reactive. They might not be emotionally reactive, but their suppression of things- I know that. The tissue isn't responding well, meaning they're tight, they've probably got painful tissue. Like, these things start to like compound, right? And they're all signs- like- so, so carbon dioxide is the metabolic stress messenger of the body, of the system. We don't even need an amygdala, man. You know, so it tells me what's going on with the person. So if- like when I have too much going on upstairs, I push that CO2 tolerance down, right? If I'm overtrained, if I've been training too much and I haven't let my body recover enough, I'm pushing that CO2 tolerance level down. When I think, when I do too much, I'm pushing that CO2 tolerance level down. Meaning, when CO2 raises, it doesn't have to raise as much in order for me to react to it- respond to it- and the first respondent of that is your breath because I have to offload that CO2 in order to feel better. So my aerobic efficiency, capacity, threshold, whatever, switches based on how much- how- how well I tolerate CO2.","offset":1552,"duration":94},{"text":"Brian: It's also telling me what basically is going to be happening cognitively. So if I get a person, the first thing I'm doing with them most likely is a CO2 tolerance test to tell me exactly where they're at. It's a threefold test. So, I- we- you sit down for a couple minutes or you lay down for a couple minutes and you just do some slow controlled breathing that you're comfortable with. Not fast, you can't hyperventilate. Then we go into a four-breath pattern to where we breathe up for like three- three or four seconds and then you relax, let it go for about five to seven, you know, five seconds or so. So it's a little bit longer of an exhale, but let's relax, let it go. Then inhale. Fourth breath you pull it in, you start the timer the moment it hits the top of the breath and you start exhaling as long and as slow as you possibly can. So you have to control it.","offset":1646,"duration":50},{"text":"Brian: So this- there's a three-part test in that it tells me how much control you have of your diaphragm on the negative, how well I have control of that, so there's the mechanical aspect of it, right? Then from a physiological perspective, it tells me how well you how- how well your physiology is responding to carbon dioxide, so how aerobically efficient you're going to be just calm. Okay? Remember the dog- walking the dog story? How- how well do you respond in a very simple fashion to carbon dioxide? Cognitively, so from a state perspective and arousal state perspective, how what you- how you react to carbon dioxide. The panic switch. So when you're going to be reactive, how you're going to be reactive. Anybody below 20 seconds and we have a very reactive volatile environment that we need to actually start working to clean up.","offset":1696,"duration":58},{"text":"Brian: And that's usually done fairly quickly with most people if and only if they're willing to actually back off a bit and learn. That allows for a gap to start to occur, an improvement to start to occur in the CO2 tolerance. So then we start to administer some breathing protocols: \"Hey, let's figure out-\" and this is why we built the State app was so that we could actually get people some protocols to use to actually work on breath control to increase uh their CO2 tolerance, but also allow them to kind of get into this more focused or calm, clear state um or downshift them prior to after training or prior to bed. That was the whole point of that. And so we'll set protocols up for people based on where they need the most help.","offset":1754,"duration":54},{"text":"Host: How much of the breath control that we're talking about there is simple ability to avoid discomfort? Because someone who is in a good place, who might feel like \"I can control this gasp reflex for longer,\" that'll contribute a little bit, but as you've mentioned as well, the CO2, this CO2 tolerance appears to be like the master of this. Is that right?","offset":1808,"duration":25},{"text":"Brian: Yeah, so what's the question? Am I rephrasing? Or- or- you're bringing that back again?","offset":1833,"duration":4},{"text":"Host: So, how much can be trained in terms of someone's ability to breathe that is um separate to the way that their physiology is put together at that time? So, is there someone who's very good at controlling their breath but still might be in this-","offset":1837,"duration":14},{"text":"Brian: Yeah, yeah, yeah, yeah. So, that- that's- that's the interesting thing. And this- why- this is where my work really diverted because I was running around with guys like Wim Hof- I was literally pretty close with Wim Hof. Um, and there's nothing- like Wim's got a great thing, he's doing great work, um, you know, uh there's other- like I've gone and participated and learned about Tumo, um many of the you know yoga practices, etc, etc. Holotropic, um, like there's Buteyko, um, like there's a lot of methods out there, right? And unfortunately each and one of each and every one of these methods is making claims that it doesn't do in some fashion. In some fashions they do, in other fashions- and this is the problem with you know getting caught up in and understanding our attachments to things and you know thinking that you know we've got an answer, and the answer is you. You're the answer, you're the only answer there is. It's not your breathing, your breathing's not an answer either. It's just an indicator of something, right?","offset":1851,"duration":59},{"text":"Brian: And so our ability biologically is- is not even close to being tapped. And I I think that be true even with something like, you know, what happened with Eliud. But going back to this is- I started seeing that not everybody reacts to the same protocols in the same way. Hmm. And so it became a there is not a one-size-fit-all fits all. There's a- there's a more or less kind of a fingerprint to some degree. And although we can bucket people and categorize them in specific ways or you know things that are going on, like \"Hey, this guy is angry about stuff and that guy's angry about stuff and she's angry about stuff and you know she's more emotional and he's more emotional about things,\" like- like meaning, depending on how you emotionally handle things, there are going to be certain patterns that are going to set certain th- things off and connect you to certain things.","offset":1910,"duration":56},{"text":"Brian: So, we had to I had to start- I was literally running around fingerprinting people with breath breath protocols because not everybody was responding the same way, and that wasn't a very you know viable thing for helping people. I was sure I was helping specific people, but I was burning myself out and there was no way I was ever going to be able to do this by myself. So, build an app and build an algorithm that work with that and we understood how to do that. So, we we literally customize things to people, but then it's like, okay well a lot of these people like to engage in performance, and they should because you should have a movement practice. Any human being that does not have a movement practice is not being a human being. Um, we we are designed to move. Now, getting neurotic about that to the degree that like I have to be this specific thing or whatever, that that's where it gets crazy.","offset":1966,"duration":50},{"text":"Brian: But nonetheless, applying this inside of movement, the framework of movement, becomes the next catalyst in how we do things. And the base layer of that is, hey, for the first few weeks we're going to just be nasal breathing. You can't go anything past nasal breathing. And for most people that's such a kick in the balls that it's like \"I don't want to do- like my ego's not ready for that check.\" And, you know, you take a powerlifter that squats a thousand pounds, I can tell you right now if they've not done any breath work, their CO2 tolerance is shit. That's a massive, massive carbon footprint. You're carrying so much lean muscle, so much muscle, but you don't do you know most of these people don't do enough of the kind of aerobic efficiency work and and that's a scary word to guys like that and and gals because they think they're scared of aerob- and it's like that's not what I'm talking about. What I'm talking about is the thing that actually makes you survive.","offset":2016,"duration":57},{"text":"Brian: Like, aerobic metabolism is what makes you survive. So when you're resting, you should be high level aerobic. And yet you see these guys and gals on oxygen tanks and like breathing like [panting heavily] and- that's not necessary. It's not. And and it's not healthy. It's an indication-","offset":2073,"duration":20},{"text":"Host: What's that due to?","offset":2093,"duration":2},{"text":"Brian: Por- poor CO2 tolerance.","offset":2095,"duration":2},{"text":"Host: Okay. And that is exacerbated by people who are high mass, high muscle mass, heavy weight.","offset":2097,"duration":8},{"text":"Brian: Huge- look look- how what's the demand for oxygen with more muscle mass? It's up. Higher. So I need more oxygen in order because the mi- like look or- like- you know, so I've got all this tissue. Well, when I don't have enough oxygen or I'm not efficient enough [panting heavily], about four five breaths in, you're going to start dipping that needle more towards those anaer- like more towards the- the demand for the tissue's demand for more glucose, more glycogen. Okay? The nervous system and brain are- are stuck with glucose and glycogen. There's no- there's no if and but- and buts about that, right?","offset":2105,"duration":43},{"text":"Brian: But fat is what the muscles like can use. So the more fat we're using with the tissue, the better, right? And so the better we get the mitochondria functioning, the better off we are. And there's no reason why an NFL lineman and a gymnast or an endurance athlete can't all be aerobically efficient. It's just different thresholds at which point- like- sure, the lineman's going to be much more of an anaerobic athlete. Like much more high level, you know, spr- sprinter type explosive, you know, and so's the gymnast to some degree is, you know, pulling it back a little bit more. And then we got the endurance athlete where you're like, you know, all slow twitch, right? And it's all the same thing in terms of efficiency aerobically. So if I've got an- if I've got an endurance athlete who's going out on an- high level aerobic ride, but they got to open their mouth, I can tell you right now they're not as aerobic as they could be. They might be somewhat aerobic, but they are not as aerobic as they could be and they are not utilizing the system in a way that they could. This- this is literally factual things we have tested that are now going into re- that- that have raised some eyebrows enough to go, \"Wow, we didn't really look at it like this. We should really be testing this.\" So, this is what's happening.","offset":2148,"duration":79},{"text":"Host: I get it. So, let's take it from the top with regards to Brian's advice for good breath. Where do we begin with that? What are the- what are the principles for good breath?","offset":2227,"duration":12},{"text":"Brian: Like the State app was created for this. Like look, start in the- do one- one breath protocol exercise in the morning, do one in the evening for sleep. Play with that for a few weeks, see where it improves what you feel, how- what you like, what you don't. If you want to play with more, go for it, right? That's probably going to be in the vicinity of five minutes each, right? That's not hard for people who like to train.","offset":2239,"duration":27},{"text":"Host: Morning and evening.","offset":2266,"duration":1},{"text":"Brian: Morning and evening, right? Simple. If you want to do all four, go for it. Do it. Like, you're- you're getting an A+ now. Um, the- the second part of this is if you're not going to the world championships or you're not competing for, you know, an Olympic medal or you're not like going to an A-priority race within the next two months, you do- like- there's no reason why you can't go dedicate three to four weeks to strictly nasal only breathing and take enough step back to actually get your physiology rewired.","offset":2267,"duration":38},{"text":"Host: Across all- across all training methodology? Whether you're-","offset":2305,"duration":3},{"text":"Brian: Across all training methodology. I don't care if you're an MMA athlete, powerlifter, Crossfitter, whatever. I've done it with the Crossfit athletes. I did it with Tia. Like, I've done it with like I've- done it with several fucking athletes that people would never consider would do- would be able to do something like this. And it rearranged what was going on and gave them an ability to do things that they didn't think they could- they could manage to do. And so it just empowered them in a level. Yeah. Yeah.","offset":2308,"duration":34},{"text":"Host: What- I mean, how long does it take to create adaptation to something?","offset":2342,"duration":4},{"text":"Brian: Right around three weeks.","offset":2346,"duration":3},{"text":"Host: I like it. I like that. Um, of course, everyone who is listening, the State app will be linked in the show notes below. Brian's app, which I'm pretty certain- is this the first iteration or is it on to kind of like a 1.5 now?","offset":2349,"duration":14},{"text":"Brian: What's- the app?","offset":2363,"duration":2},{"text":"Host: Yes.","offset":2365,"duration":0},{"text":"Brian: Uh, this is the first ver- there's been a couple updates on it. Yeah. Yeah. But this is the first version of it. We're- there's- there's a lot more that's going to come into the pipeline of- once we get through the first investor stuff that we're going through. Uh, there will be some serious, serious things that are coming down that pipeline. Um, you know, I mean, it's already a- it's been way more successful than we ever thought it was going to be. Um, but we also know like- there's- there's a lot more that we do than just doing some simple breath protocols. Like there's high-level things you can do in order to change your physiology that could, you know, that are game-changing things.","offset":2365,"duration":47},{"text":"Host: Hmm. So what happens when you breathe through your nose? Tell me. Someone's training they're just breathing through their nose. What's happening? Why- we've talked about the- the different workout of the walk with the dog with the nose open and closed. What- how's that characterized?","offset":2412,"duration":14},{"text":"Brian: It's- it's your biological way of staying aerobic. 500 million years ago, cells single-cell organisms figured out how to become multicellular organisms. They said, \"Hey, let's you and I communicate like you and I are right now. Let's talk about some things. Let's share some information so that we can pass this shit on and p- see that oxygen-rich environment now? It used to be hostile. It used to be mostly carbon.\" Like and it was we had to be mostly anaerobic and we changed energy otherwise. And this is where like we're headed right now is this is all about energy. There's nothing else. There's nothing other other than energy. All energy that's ever existed has existed. It's how we're con- the conversion of energy is happening. We don't b- it's not we burn- we don't burn calories. Okay? That- that's us- we're converting calories. We're literally taking energy converting that energy and then putting energy back out. Like it's literally this cycle of and we forget about all this thing. And so that energy deal got made when cells learned to communicate and said \"Hey, let's take this oxygen and let's use this,\" and it's much more complex than this but this is just the story that I like you know like- but it's like, \"Hey, 500 million years ago multicellular organisms figured out how to use oxygen after algae and algae literally figured out how to convert sunlight into energy itself and the byproduct of that was oxygen.\" So the Earth became engulfed in this algae, all of a sudden there's all this oxygen in the environment. Then cells were like, \"Yo, there's a- got to be an efficient process to this.\" And here's that process.","offset":2426,"duration":93},{"text":"Brian: Today, 500 million years ago, aerobic metabolism sits at the forefront of the most efficient way to use energy. And so anything outside of aerobic metabolism becomes anaerobic. So if I don't have that process that conversion of energy I'll default very simply and we should to this higher stress situation of using energy. So anaerobic doesn't necessarily become a training process, it's more or less the byproduct of I'm no longer able to handle aerobically what's going on. So how quickly I can come back to that aerobic is literally how well I can. So having a very high aerobic capacity means I function higher aerobically. So when we look at people like a guy smashing the two-hour marathon, what does he look like physiologically? And although there's like look to be total like look I support and I'm very happy for the man and everything but realistically if he were in the same setup as they were in 1950 or even 1980 he wouldn't have run a sub-two-hour marathon. That that wouldn't have- it's not the same marathon. It's a different marathon even though the distances are the same. The shoes, the pacers, the- the- all of these things exist, but I don't deny the fact that this man's physiology is off the hook and the only reason I really know that is not only have I studied how he moves, but I've watched how he breathes.","offset":2519,"duration":108},{"text":"Host: What's your analysis? What's your analysis of his-?","offset":2627,"duration":2},{"text":"Brian: He primarily breathes through his nose.","offset":2629,"duration":3},{"text":"Host: Okay.","offset":2632,"duration":1},{"text":"Brian: Most of his marathon is done nose-only breathing. You can find pictures all over the internet with salt marks that come down his nose, and you'll see when he's running that most of the pictures are of him with his mouth shut. Hmm. I did notice that. So I've watched video. Yeah. Yeah, I've- I've- I've videoed the video so that I could go and slow it down and look at it and watch it, and you know there it is. And, you know, I mean he comes from African culture, right? And what what is of the African nose? Like they've got larger nostrils. Well, they've dev- like genetically they are set up to do something. Like if you've ever watched a horse race- so I watched an- I watch animals like like- it's a like big passion like I'm almost neurotic about it. You know, you watch animals who don't sweat and they don't actually the only time they're mouth breathing is when they're overheating. Okay? You watch animals who do sweat, a horse, a racing horse, they will not breathe out of their mouth. They just have a bit in their mouth. They breathe through their nostrils. They literally will not breathe out of their mouth.","offset":2633,"duration":76},{"text":"Host: Why do we then?","offset":2709,"duration":4},{"text":"Brian: Uh, you know, it's interesting, we have um done real well at progressing ourselves culturally through comfort and convenience. And in that process we've more or less stressed ourselves more than we actually needed to. So by that I mean this. Uh, there was a book written in 1867 I believe, I forget the date, um but George Catlin wrote a book called \"Shut Your Mouth and Save Your Life.\" And he wrote this book as a historian who was a lawyer from England who came over to the State- which was basically North America and South America at the time- studied about a million and a half indigenous cultures and civilized world. He was uh the biggest thing he picked up on was the fact that in- in indigenous culture, they did not breathe through their mouth, rarely. And- and when they- when they spoke, they spoke with intent. They did not speak too much. They meant what they said, they said what they meant. When they slept, they slept with their mouths shut, when they hunted, they hunted with their mouths shut. They did everything they could, including when children came off of the nipple, mothers would shut the mouth of the child for fear of the black mouth. Because not only was the white eye called the white eye or round eye, he was called the black mouth. And the reason he was called the black mouth was because his mouth looked disgusting.","offset":2713,"duration":108},{"text":"Brian: And why would that be? Well, look at what we started doing cultu- look at what we- were starting to do. I mean, we were drinking more alcohol, we were- sugar started to become- agriculture started to kick in, all of these things of convenience started to happen, right? And here's a culture of people who pay attention to nature. What is nature? Physiology. That is literally one of the definitions of- of physiology is nature, origin. And thus paying attention to the feelings of nature and what's going on. So what happens when I feel when I breathe through my mouth? Right? Well, I get ramped up, I turn on, I speak. If I go speak somewhere and I talk just for an hour, I'm on, like I feel like I'm on. If I speak for an entire day, I'm exhausted. I don't go work out, I try not to go to dinner with people afterwards. Why am I so exhausted? I'm blowing off a ton of carbon dioxide, I'm more sympathetic dominant, I'm actually using less of the fat so I'm- I'm not as aerobic as I could be, even though I am still slightly aerobic, I'm not as aerobic as I could be, right? So it's learning those waves, they felt that shit, man. They felt it.","offset":2821,"duration":70},{"text":"Brian: We don't feel. We have- we have these things in front of us and we're getting stimulated and we've got all these kids that are going batshit crazy because they don't have recess anymore, they're pulled from play, they're told what to do, they're told how they're going to learn, then they're given infinite possibilities on a machine to play games and keep them occupied because Mom and Dad don't want to deal with 'em. And then they've got anxiety because of this. They don't have anxiety. They've got proper stimulation from being overstimulated. They've got physiology that's run amok and they don't understand it, and this has been by and large what's going on with us even those of us that like to train a lot. Like I mean, I'm on I'm talking to you, I'm on, I need to sh- when I'm done here, I mean I'm feeling this. I feel it. So I've gotten to the point where I feel all this stuff and I'm paying attention. If my mouth opens when I'm asleep at night, I wake up.","offset":2891,"duration":55},{"text":"Host: Why? Why would you wake up if your mouth opens, based on everything you've just gone over?","offset":2946,"duration":9},{"text":"Brian: Because you become more stressed. Bingo. I'm now slipping more into sympathetic and I'm turning myself on. Hmm. Okay. I understand. How many of us are trying to sleep in this high sympathetic activity state, right? And I'm also not as aerobic, and then oh shit, I've got sleep apnea so now I'm holding my breath in an awkward fashion and [gasps and exhales heavily] like, I've got all- like weird. Like, what are you paying atten- are- like, you need medication and a fucking- you need a mask to wear at night? I've got friends who do this and they refuse to do breath work and I'm like, \"Dude, it's your choice.\" Um, I've got more DMs and P- I don't even talk about this I don't write about this stuff publicly. Like I don't go out and go, \"I'm going to solve your problems.\" No. Here, start with some breathing protocols, start rearranging your training, then start feeling what's going on in your body.","offset":2955,"duration":54},{"text":"Brian: You're going to default to places that you can. Is it weird that George Catlin was also in a book that I've read and the- I'm the only person who's caught this so far, right? Only because I've read this other book. It's a book called \"Empire of the Summer Moon\" and it is about the Comanche Indians who are arguably the- the most war-driven tribe of people that have almost existed. They- they're in comparison to the Mongols in like- uh lot of the stuff that happened with 'em, but they were very, very gnarly. They were so gnarly that had the Colt revolver not ended up in the hands of a few young white boys from Texas called Texas Rangers, they would have- this world- this country would be a very different place right now. They knew how to fight off of horseback in a way that no other culture had understood and they couldn't combat it. So shooting a rifle with one shot was no good, right?","offset":3009,"duration":61},{"text":"Brian: And so this book was written and there was a guy around- there were a number of historians that were there that were interviewed and one of those historians throughout this book that was written about was George Catlin. And so there's this guy that's there and the biggest thing he picked up on was that the people who were of the of the- Earth, that were literally living on the Earth, that were living in planes that everybody feared to cross because they had no idea how to navigate, they had no idea how to do things, and there was this murderous culture of people who did not want them near anything and- including other tribes, like other tribes feared the Comanche, right? Like they were feared. And it- it's a fantastic read.","offset":3070,"duration":49},{"text":"Brian: But the fact of the matter is is I'm able to now connect through reading physiology and then reading about literally \"Hey, George Catlin wrote this book in the six- in 1800s about this,\" holy crap, there it is! What is history? It's literally telling us what's going on with- like- there's- there's lessons to be learned about all this stuff and what people were doing. You think- you think a Comanche Indian who knew how to navigate the land could get on his horse and ride for three or four days straight with no food basically, or limited food supply and water supply, what do you think the physiology of a human being like that is? Like, literally could survive in freezing cold temperatures, navigate land in storms, like where do you think we're at culturally right now? We're worried about squatting a thousand pounds and running a two-hour marathon. I don't think we're anywhere close to what our biological potential is. I think we missed the boat. I think we're confused. I think we think that technology is this great thing that's going to get us into the future and it's not. It's going to just lead us right back to our own biology and going \"Shit, we're mimicking all this technology after stuff we internally are able to do.\" It's why I asked you what- how would- how- how do you control your heart rate and how do you feel that? \"Well, I'd have to be calm for a minute and then I could really pick up on-\". Yeah. Well, guess what? You can feel that at any moment you want. Just got to spend the time to get back to that.","offset":3119,"duration":85},{"text":"Host: I understand. Yeah. It's interesting what you said there about when you spend a whole day talking, right? So I do coaching calls. I coach a sales company in Germany and every time I'm done, let's say it's maybe three hours and I've been talking to these guys, and it's a conversation. It's at least 50-50 between me and them, it's not all me. But once I'm finished, let's say I've done three hours, four hours of- of talking, little bit of water in between, little bit of chill or whatever. After I've done that, I'm absolutely gassed. Like once I'm done, I'm like, \"Hhh, I'm really tired.\" And I wasn't really sure- I thought, well maybe it's because cognitively it's quite demanding, I'm trying to link these things together, it's because I'm really putting myself into the person I'm speaking to or whatever it might be. And your suggestion here is that one of the principal reasons for this is going to be that I'm just inhaling and exhaling quite a bit of air quite a lot.","offset":3204,"duration":53},{"text":"Brian: Well, your- yeah- you're on, right? And so you're getting stimulated, but you're getting a stimulation that you're automatically like you're falling into autopilot on because you're talking, I'm talking, right? So we're- I'm ramping myself up. Not only am I ramping myself up and getting into what I'm doing, I'm getting focused and I'm being engaged with you, but the byproduct of that becomes my breath. My breath is the instant reaction to that. It- it's- it's the first respondent. There's only two- two things we can do in order to regulate or- or stimulate autonomic control consciously. That is our breath and our vision. So I can choose not to look at you right now and I can look at the end of the room and I can go into peripheral vision and I can downshift myself. I can go outside and look at the fucking look at nature, look at trees, right? How many people freak out looking at a sunset? None of 'em. Why? Because it's math. No, it's beautiful. Yeah, beautiful's there, but that's not math. Math is the algorithm that and it's the light waves that enter your eyes and open you up to go \"whomp!\" and it drops you into parasympathetic.","offset":3257,"duration":78},{"text":"Host: It's interesting vision side.","offset":3335,"duration":4},{"text":"Brian: We've got so many tools and things going on that we don't know about. I- literally man, I was just at the Cleveland Clinic, I was in open-heart surgery with them with a team there, and they were like, \"What do you think you could help with?\" And it's like simple man. Control your breathing and control your vision when you need to, when you need to make a better decision or something fucking- the shit hits the fan. Like, it's time to do that. That's human performance. That's human performance at its finest in trying to help somebody's life be saved, you know? And like why'd that person get there is another fucking- another story that we could be dovetailing back towards \"Hey, why we move and what we love about human performance.\" But that's human performance for me. Like human performance is literally getting to the core of why you know people doing everyday stuff, right? Like that's human performance. And I think we're eluding ourselves into thinking that we understand something by, you know, like \"What's a 500-pound deadlift do for me?\" These were- these were things I had to ask myself, right? Like this isn- I'm not asking this of you, I'm- I had to ask this of myself. What's a 500-pound deadlift? Because I've had a 500-pound deadlift, right? And it's like I- I was not able to connect the dots on what that meant. That I don't know that that made it better for me to survive. Getting up off the couch or picking shit up off the floor? I- I don't know that that 500 pounds is necessary for that.","offset":3339,"duration":81},{"text":"Brian: Like \"What's running 100 miles doing for me?\" It was a fucking amazing spiritual experience. But what was it doing for me, right? And like where was I at? And so what- you know- do I need to actually run 100 miles? No. But will I? I mean sure, I did a couple times but, you know, like- it's just- like I've done these things and I'm like so what's the point of this? Is this oh, I'm now clinging to this thing thinking it's the thing and- there we go. Now the mind now- now let's look at the ner- let's look at the neuroscience. Let's let's really start looking at the down the up- how everything's compiling and what I'm doing and why I'm doing it. So when I ask people like what do you want? Because they'll come to me. I literally have a call after this from with our mentorship program and I've already had two today. And it's \"What do you want?\" And I'm pretty quick to to understand that they don't know what they want even though they're telling me what they want. And so it's usually like \"Tell me what you want, I'll show you a liar.\"","offset":3420,"duration":62},{"text":"Brian: Because we're just not ready- really ready to let go of all these ideas that we have and it's not that you can't go deadlift a thousand pound or you know whatever you can't squat a thousand deadlift 500 go run 100 miles. Like these are just extreme versions of 'em, right? I don't need to go dive with Great White sharks but I did and I got that experience and it taught me some profound lessons man, profound. But if I'm actually in the moment and understanding what's going on in this very moment and how I'm operating and what I feel, then I'm moving back more towards what that Comanche was doing. And I'm actually getting in tune with the vibration of how everything works and why when I go why- you know, I went on a run earlier. What I'm trying to accomplish with that run and understand about that run. Where is it that on this hill that I'm climbing right now that I have that I feel like I need to make this switch? And how like- how cooked do I feel and where is that at and what can I do in order to improve that so that like, hey, this- this improves my day and it doesn't ruin my day, right?","offset":3482,"duration":61},{"text":"Brian: That's what I'm talk- you know, this is where we start- my reactions to what I'm doing in training, my reactions to what I'm doing throughout my day are the same thing. But I'm just getting people closer to what that actually is. And that's what we've been doing with the Art of Breath is really just you know, like people come in there and like this gal this weekend who showed up at at Rob's seminar, she was like she's a Crossfit Games athlete and you know she identified as a Crossfit Games athlete, I love that. Like I just love somebody comes in \"I'm like a professional athlete, I'm a professional Crossfitter,\" like whoa, okay. Um, I get it. I know where you're at. Um you know and we're doing all this work and stuff and there's a hypoxic set where you do farmer carries with- with kettlebells, right? So like you'll do some burpees and then you go and we have people grab the the kettlebells and then they dump their air and they have to walk as far as they can down and back.","offset":3543,"duration":53},{"text":"Host: Okay, yep, just farmer's walk.","offset":3596,"duration":1},{"text":"Brian: Yeah yeah yeah. And and so everybody- like this chick just takes off running, man. Like she's trying to win it, you know? And one of our coaches, Danny Yeager, who's phenomenal, um he runs Crossfit Kingfield out in Minnesota and he's like he watches this and then he sees a bunch of guys. So there's a lot of people there in in the warfare community, and so there's a lot of you know dudes and people who are like want to win, right? It's like what are you trying to win? So Danny stopped and he goes \"Hey! If you think we brought you here to actually see how long you could hold your breath while farmer walking kettlebells, you don't understand why you're here. You don't understand what we're doing. What is it you're feeling when you're holding your breath and walking these things? What's- if you're trying to win the farmer carry holding your breath, what is it you're winning here? There is no reward. It's we're here to experience something and understand what this thing can do and teach us. Well, I thought I was going to be able to carry those kettlebells a lot farther, or I thought I was only going to be able to carry 'em a few steps and I went further than I did. Awesome. Now we're starting to get somewhere versus \"Oh, I got to win this.\" Like win what? What are we winning? That's called ego. And and you just removed yourself from understanding all purpose of- of training. All training at the foundation of training is to make better decisions under stress. Carbon dioxide is the metabolic stress messenger of the human body. Done deal.\"","offset":3597,"duration":112},{"text":"Host: I love it. I love it. Brian, today's been fantastic. I really appreciate you coming on. Anyone who wants to check out some more of your work, where should they head? We've talked about Art of Breath. How does that relate to the State app? Is the State app a part of that? No.","offset":3709,"duration":16},{"text":"Brian: Does not- separate. No, State app's- a bit differ- um the State app's separate the you know a lot of the stuff with the business is going to change real soon. Um in fact the whole name everything's going to change, we're changing that so it all kind of fit and be seamless so it makes more sense to the world. Um that being said, the Art of Breath is a component of what we teach inside of Power Speed Endurance. It's a performance-based seminar, there's a 101 that we teach around the world but we also have it online. So that can be found on Power Speed Endurance. The State app is you can find each app whether it's Android or iOS on shiftstate.io. Anything about me or or if you want to get in contact with me or or you know whatever can be found on brianmackenzie.com or you can go through Power Speed Endurance.","offset":3725,"duration":50},{"text":"Host: Amazing. I- I have to say it was a listener who recommended that I- I check out the State app and get in touch with yourself and I think I've found the new thing that I'm going to add into my morning and evening routine. I've been looking for what it's going to be. I've stopped doing Rom-Wod for the time being and I do miss some of the breath control, I miss that parasympathetic activation. I'm still doing my meditation on a morning, I'm reading, I'm doing other bits and pieces, Stu McGill's Big Three, but I'm not I'm not feeling myself in the body quite so much with that. It's very- it's very visceral, it's very kind of um transactional that I'm doing it for the for the return on what I know it needs to do to my spine health. Um and I think I think the next- I think the- between now and Christmas it'll be- it'll be me doing that. So I'll report back, I'll keep you updated and I'll let the listeners know how I'm getting on.","offset":3775,"duration":51},{"text":"Brian: Please do. Please do. Yeah. Look at I- I would do the either \"Feel Alert\" or \"Be Present\" protocol if you're- if you're doing your meditation in the morning, do the breathing beforehand. There's a reason why breathing is at the foundation of every meditative practice.","offset":3826,"duration":14},{"text":"Host: That's interesting. So you'd say for a lot of people that are listening, maybe they have a meditative practice in their morning routine, you'd say do the breath work before that and then how- how do you program that in on an evening? Is it right before bed?","offset":3840,"duration":11},{"text":"Brian: If you have an active sitting, yeah. If you have an active sitting meditative practice, just be clear that if you want that brought up to the next level, add breathing before that. If you want it really brought up to the next level, use the State app so that you can fingerprint your- the rhythms that work with you. Like so your app's different- going to be different than mine based on you know how you actually handle carbon dioxide cognitively and how you handle emotional stress. So that can give you a ramp in. I can't tell you how many people who come to me who are like \"I can't meditate, it's just I don't have the patience, I don't have this, I don't have that.\" You're already there, but it's like I show 'em breathing and the fact is is breathing is a controlled breathing is meditation. Literally. Um you'll get there. Just give it some time, right? So use that beforehand. In the evening, anything less than two hours before you go to bed, okay, using the \"Fall Asleep\" protocol. That'll downshift you and change the sleep. You'll you should probably see some increases definitely in deep sleep, but also potentially in the REM cycle.","offset":3851,"duration":72},{"text":"Host: Fantastic. I've also got um my new Whoop band coming as the last one has um has lapsed, so I'll actually be able to track that and see if that's making any difference as well, which'll be- which'll be interesting. But Brian, today's been absolutely awesome. To the people that are listening, you already know what to do. The links to everything that we've spoken about, the State app, shiftstate.io, Power Speed Endurance, and Brian's website will be linked in the show notes below. Go hassle him online if um if you need to get some more info out of him. Um but Brian it's been- it's been fantastic, man. I'm really looking forwards to getting into my breath work.","offset":3923,"duration":31},{"text":"Brian: Right on, Chris. Thanks for having me, man.","offset":3954,"duration":15}],"logs":[{"elapsed":"0.0","message":"Downloading audio from YouTube...","detail":null},{"elapsed":"0.0","message":"Trying download with browser cookies (ad-free)...","detail":null},{"elapsed":"11.0","message":"⚠ Cookie download failed: WARNING: [youtube] [jsc] JS Challenge Provider \"deno\" returned an invalid response: response = JsChallengeProviderResponse(request=JsChallengeRequest(type=, input=NChal","detail":null},{"elapsed":"11.0","message":"Retrying without cookies...","detail":null},{"elapsed":"368.8","message":"⚠ Downloaded without cookies — audio may contain ads","detail":null},{"elapsed":"368.8","message":"Audio downloaded (32.9 MB) in 368.8s","detail":"File size: 32.9 MB"},{"elapsed":"368.8","message":"Video title: How To Breathe Properly | Brian Mackenzie | Modern Wisdom Podcast 121","detail":null},{"elapsed":"368.8","message":"Audio duration: 1:06:12 (66.2 min)","detail":null},{"elapsed":"368.8","message":"Uploading audio to Gemini File API...","detail":null},{"elapsed":"404.2","message":"Audio uploaded in 35.4s","detail":"File ref: files/zirumnb8z7qy"},{"elapsed":"404.2","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"506.0","message":"Transcription complete in 137.2s","detail":"63601 chars received"},{"elapsed":"506.0","message":"Transcription tokens: 99,544 in / 16,162 out — cost: $0.0983","detail":null},{"elapsed":"506.0","message":"Parsed 112 transcript segments","detail":null},{"elapsed":"506.0","message":"Transcript coverage: 1:05:54 of 1:06:12 (100%) — OK","detail":null},{"elapsed":"506.0","message":"Total transcription time: 137.2s — 112 segments","detail":null},{"elapsed":"506.0","message":"Analyzing topics across 112 segments with gemini-3.1-pro-preview...","detail":null},{"elapsed":"559.8","message":"Topic analysis complete in 53.8s — found 14 topics","detail":null},{"elapsed":"559.8","message":"Analysis tokens: 16,864 in / 1,109 out / 4,612 thinking — cost: $0.1024","detail":null},{"elapsed":"559.8","message":"Pipeline finished in 559.8s — total cost: $0.2006 (138,291 tokens)","detail":null}]} \ No newline at end of file diff --git a/history/1773858934218--dgsZ0O-lZQ.json b/history/1773858934218--dgsZ0O-lZQ.json new file mode 100644 index 0000000..eeddaed --- /dev/null +++ b/history/1773858934218--dgsZ0O-lZQ.json @@ -0,0 +1 @@ +{"id":"1773858934218--dgsZ0O-lZQ","videoId":"-dgsZ0O-lZQ","url":"https://www.youtube.com/watch?v=-dgsZ0O-lZQ","title":"How to Breathe Better for Peak Performance | Brian MacKenzie | Align Podcast #527","type":"youtube","topicCount":10,"segmentCount":129,"createdAt":"2026-03-18T18:35:34.218Z","uploadDate":"20250123","chunks":[{"title":"Oxygen and CO2 Synergy","summary":"Brian explains that CO2 is essential for regulating pH and offloading oxygen to the cells via the Bohr effect. They discuss how CO2 has been historically villainized, despite oxygen being a destructive, oxidizing molecule without it.","entries":[{"text":"Brian MacKenzie: Oxygen is a useless, destructive molecule without CO2. Most people are getting lost and stuck to a methodology versus understanding respiratory physiology and physiology in general. When you can hold your breath for a significant amount of time, what you’re doing is training your mitochondria to use less oxygen for more ATP. It’s not about the inhale, it’s about the exhale, which is something most people are never thinking about. Breathing’s the tool to kind of get you out of where you don't like what you’re feeling.","offset":0,"duration":36},{"text":"Host: Why is it that breathing affects one's state of consciousness so deeply and quickly and with such great efficiency and consistency?","offset":36,"duration":12},{"text":"Brian MacKenzie: Well, a number of reasons but, you know, one of the main being the fact that, you know, we're largely controlling carbon dioxide with breathing. Although, you know, you're bringing in oxygen as well and that's important, you know, 80 percent of that oxygen is roughly offloaded at rest. So when we're not working, when we're not doing something, a lot of that oxygen is not necessary. That being said, the CO2 actually is, and that is the, you know, one of the big drivers of things, but from a biochemical standpoint, CO2 regulates pH.","offset":48,"duration":40},{"text":"Brian MacKenzie: So that is essentially what's really the big player in regulating pH real time. Yes, the kidneys play a role in that and there’s a lot of other processes, but the major player with breathing is that it's a respondent to pH and if I change that pH, things start to change, the dynamics start to change, right? And as CO2 goes up, more oxygen comes off, comes out and is usable.","offset":88,"duration":24},{"text":"Host: From hemoglobin, from red blood cells. It liberates them.","offset":112,"duration":5},{"text":"Brian MacKenzie: It liberates that. So then you've got, you know, if you've got functional mitochondria, you then get that oxygen down to the electron transport chain and you're now pumping that out. The better you get at this, and you know, as I used earlier as his, you know, opening protocol, when you get to his level of breath hold, you know, you don't even necessarily need to be at his level, but the reality is is that when you get to, you know, when you can hold your breath for a significant amount of time, what you're doing is training your mitochondria to use less oxygen for more ATP.","offset":117,"duration":33},{"text":"Brian MacKenzie: This was done in a, they looked at this at a study done, I think it was in Sweden, but it's called the Tortoise and the Hare. And uh, in the lab, these guys had a professional triathlete, an elite triathlete, and an elite freediver who were both in the lab at the same time who were PhD students, I guess, or master's students, and they decided to take a look at the differences in them and how they used oxygen. And of course the triathlete being elite, used it real well from a VO2 standpoint and all of these things, he had a much larger aerobic threshold than the actual freediver.","offset":150,"duration":40},{"text":"Brian MacKenzie: However, once they came into this conclusion about the less oxygen for more ATP, they were like, oh, well there's the other side of aerobic we haven't been looking at. So there's high benefit in in being able to hold one's breath, but you don't necessarily need to become a freediver or breath hold expert in order to get these benefits. Uh, you know, most people are overbreathing, which is you're just off- you’re just offloading CO2, um, as a result of that overbreathing even a slight bit, and that means you're just not getting as much of that oxygen off that hemoglobin.","offset":190,"duration":35},{"text":"Host: And what is- CO2 has largely been villainized historically for most basic people.","offset":225,"duration":7},{"text":"Brian MacKenzie: As a waste, as a waste product.","offset":232,"duration":3},{"text":"Host: And- and yeah, oxygen good, CO2 bad, get the CO2 out, get the oxygen in. That’s obviously wildly incorrect and excessively basic and just...","offset":235,"duration":7},{"text":"Brian MacKenzie: In facts, actually it’s kind of reversed.","offset":242,"duration":4},{"text":"Host: Yeah.","offset":246,"duration":0},{"text":"Brian MacKenzie: So oxygen is a useless, destructive molecule without CO2.","offset":246,"duration":6},{"text":"Host: Right.","offset":252,"duration":1},{"text":"Brian MacKenzie: No, literally. Like, it we’re- we're literally getting oxidized from the inside. Free radicals, like, have you heard of it? Oxidation? Like your car, you know, you go look at a car that’s being oxidized, that’s oxygen.","offset":253,"duration":13},{"text":"Host: And that’s a part of like hyperbaric chambers, it’s you’re pushing oxygen deeper which is actually creating a hormetic stressor. That’s like a part of mobilization of stem cells and such, you’re actually challenging your body.","offset":266,"duration":10},{"text":"Brian MacKenzie: Correct. Oxygen is important because of aerobic cellular respiration in that oxygen's role is to regulate metabolism, right? Where CO2 is there to regulate biochemically pH, right? And so they- they work together, but, you know, as- as you explained, you know, lots of people like to go in hyperbaric chambers and they don't actually understand why they're going in there. They're actually creating a very stressful response that they rebound from and a hormetic effect that inevitably has a very positive response after about 20 sessions can turn some things on and get some things boosted as a result, but make no mistake, you are stressing the hell out of your system as you're doing it.","offset":276,"duration":48}],"startTime":0},{"title":"Calming Benefits of Nasal Breathing","summary":"Brian outlines the physiological benefits of maintaining higher CO2 levels, including vasodilation and a robust parasympathetic response. He explains why the nose is specifically designed to retard airflow and maintain healthy CO2 dosing compared to mouth breathing.","entries":[{"text":"Host: Could you outline some of the benefits you already have a little bit, but go a little bit deeper into some of the benefits of CO2 that people might not recognize or realize, some of the like effects that people experience by having CO2 in their system?","offset":324,"duration":15},{"text":"Brian MacKenzie: Yeah, I mean it- it's a calm- it’s going to create a calming effect back you know, like 60s, 70s probably before even the 60s, but I mean I even remember in the 80s that, you know, people who the rare panic attack that would happen, people were given a paper bag to to breathe re-rebreath into. You’re just basically rebreathing CO2 and that creates a calming effect, right?","offset":339,"duration":22},{"text":"Brian MacKenzie: Um, because the more CO2 that's in the bloodstream, you're actually starting to vasodilate things, the nervous system’s responding by coming- calming down, becoming more parasympathetically driven. You know, and that's- that's essentially why we were really designed or the respiratory system, the pulmonary system was designed with the nose in mind and not necessarily the mouth for most of breathing, right? That nose has intricate processes set up and one of them is it retards how much air can come out and by that, you're getting the ni- you're getting a good dosing of CO2 whereas as I speak or you speak, you know, arousal starts to shift and that CO2 starts to drop.","offset":361,"duration":47},{"text":"Brian MacKenzie: So I start to use more glucose, I start to move, you know, I'm moving into a- a more activated state, which is natural. However, if that's what I'm doing all day long, where am I- where are those changes coming in to where I’m not? And that's where the regulation of breathing and and CO2 essentially start to come in where, uh, you know, people who who aren't mouth breathers tend to be a little bit calmer.","offset":408,"duration":23}],"startTime":324},{"title":"The Amygdala, Stress, and CO2 Intolerance","summary":"Discussing the evolutionary and psychological aspects of breathing, Brian references the \"Chimp Model\" of the brain. He explains the intimate connection between the amygdala and CO2 modulation, detailing how emotional reactivity leads to a hot nervous system and CO2 intolerance.","entries":[{"text":"Host: It’s interesting how it seems confusing. I was just doing a podcast with Robert Sapolsky, the \"Why Zebras Don't Get Ulcers\" guy, a couple- couple days ago. And that was- I had some questions for him in relation to like what's the evolutionary or adaptive quality of certain things like people, you know, he’s like baboons and certain primates and humans end up having too much time on their hands and then they end up being like evil to each other and destructive to each other. So the questions of like why is that an adaptive quality and strategy and how has that managed to persist in evolution?","offset":431,"duration":40},{"text":"Host: I wonder with breathing, kind of similar type style question, bad breathing and anxiety and maybe a higher proclivity towards reactivity or anger outbursts and things of the sort will end up actually perpetuating more bad breathing, which bad breathing being like maybe mouth breathing or emphasis on the exhalation or faster breathing or excessive dumping of CO2 making you be more stingy with holding on to oxygen and a less efficient mobilizer of oxygen and just generally like puts you in a place of feeling like you’re kind of suffocating within yourself and you kind of literally are. That seems contradictory to me that evolution would- would permit that. Do you know what I’m saying?","offset":471,"duration":37},{"text":"Brian MacKenzie: No, I- know, because I- I get it and I'll- I'll kind of this is great question. So- or great statement. It's not that I understand what you're saying, however, I've spent so much time in this that I've got a pretty good handle on what I think is the reasoning, you know, and what what happens. Um...","offset":508,"duration":20},{"text":"Host: And did I outline that question appropriately? Was there anything that I said in there that was like that should be cleared up or was that an appropriate way of asking it?","offset":528,"duration":7},{"text":"Brian MacKenzie: No, no, it was very appro- no, no, very appropriate. I'm just- I'm- I- was tickled that you asked because, uh, you know, it's interesting because I was just speaking with Professor Steve Peters in- do you know who he is?","offset":535,"duration":12},{"text":"Host: No.","offset":547,"duration":1},{"text":"Brian MacKenzie: So he wrote, \"The Chimp Model\" for, uh, brain I think, and now his newest book is \"The Path Through the Jungle\". Dude, the dude is on a level. Um, he- he lives in, um, he's English, but I have never heard anybody explain he's a psychiatrist by trade, but he explains the neuroscience of everything and this is where why it got so interesting to me is because he started explaining this chimp model of the brain and how we've got two- we’ve got three teams, right?","offset":548,"duration":32},{"text":"Brian MacKenzie: And one team is the kind of the it works off an emotional response and then there's a logical reaction that kind of tells a story to validate that emotional response and this is how children grow, this is the child’s mind. And then it has an action next to it, right? And that action feeds team three, which is a program, okay? The second team is the logical brain or the human brain. And so that first team is the chimp model, the second team is the human model where logic is the basis of things, reality is the basis of things, then there's an emotional response then there's an action towards that thing.","offset":580,"duration":33},{"text":"Brian MacKenzie: Either one of these feeds that system down to team three or the program, okay? So the program wires up based on how you're going, right? And team one, the chimp model's not bad and team two is not good. They're both good, they're both there for a reason, you're there to survive, we're here to survive and we should honor how we've decided to move through the world, how we grew up and how those responses came in, etc., etc.","offset":613,"duration":30},{"text":"Brian MacKenzie: Anyway, when he got into this stuff, he started talking about that emotional model and the limbic system, because that's what it- where it really functions. And in the limbic system is the amygdala. So we understand that there is this little, you know, almond-shaped thing that is like the fear center of the brain. A good friend of mine did some research where he figured out the he- I think the paper was titled, um, well, forget what it's titled, but it's about what he found with the amygdala is that is it is a modulator of CO2 as well.","offset":643,"duration":38},{"text":"Brian MacKenzie: So for those of us that are a little bit more less emotionally developed, we tend to become more reactive and when we become more reactive our nervous system's a bit more hot, when our nervous system's hot, you can bet you'll become more CO2 intolerant, so meaning if Aaron got stressed out, which Aaron doesn't get too stressed out, but let's just pretend he did, and I said Aaron hold your breath versus if Aaron were calm, hold your breath.","offset":681,"duration":30},{"text":"Host: Yeah.","offset":711,"duration":0},{"text":"Brian MacKenzie: There would be two very different breath holds, CO2 being the main mechanism and driver for why you would need- feel the urge to breathe, right? You understand that pretty intimately. So that modulator gets involved with things especially for those of us that are wired up in certain ways or just are more reactive or talk a lot more or, uh, you know, are mouth breathers by nature, you end up retarding this process and then you become sensitive to its change because the nervous system's running pretty hot as a result.","offset":711,"duration":37},{"text":"Brian MacKenzie: Because it biochemically speaking you're moving the needle over to say, oh not enough o- not as much oxygen available, no problem, we'll move into more sympathetic survival mode, which provides more glucose, glycolysis, etc. So I just run up here on carbohydrate most of the day and I don't, you know, my mitochondria are not as functional, right, in terms of where I’d be util- and that doesn't just mean we're not using carbohydrate with mitochondria, etc. because we oxidize, right? We're just not oxidizing as much because we don't have that availability.","offset":748,"duration":40},{"text":"Brian MacKenzie: So the the system has a very easy long-term way of managing that. It just uses more glucose, right? And and it just happens quicker. It's not that we're not using oxygen, it's just you're not using it well. And so that state becomes chronic stress is what we see and that sensitized chronic stress, you could look at most people who deal with chronic stress have some form of chronic anxiety they're also dealing with or depression, which are same same just different modes of how you're operating with it. Without a doubt, we've seen that people are CO2 intolerant or more CO2 intolerant who are anxious.","offset":788,"duration":43},{"text":"Host: Could you say a little bit more about the relationship of the amygdala and the and CO2? Is that like a downstream effect because of upregulation of the amygdala is causing the nervous system and the respiratory system to go into more of like a hyperventilatory state, therefore the downstream effect is off-gassing CO2, or is it more intimately and closely related than that?","offset":831,"duration":22},{"text":"Brian MacKenzie: Yeah, correct. Yeah, it is that downstream side of things. Um, you know, however when I talk about, oh, you know, my run- my nervous system's now running hot, well you're a high-stress individual so now what you're doing is, you know, if we look at like HRV, your HRV's low, so the beats between the heartbeats aren't as far apart and, you know, your chemoreceptors are on alert because you're in a predictive system.","offset":853,"duration":29},{"text":"Brian MacKenzie: So you've got chemoreceptors off the aortic arch, the carotid arch, the the carotid artery. So you're talking about a predictive system and when you look at the predictive system, you then can get into free energy principle, which is, well yeah, everything's kind of off of a prediction that I've predicted how my day's going to go. I've gotten in a car to go somewhere, I don't predict there's going to be an accident so any sort of thing that gets in the way of that sets me off.","offset":882,"duration":26},{"text":"Brian MacKenzie: And if I'm somebody who gets set off really easy, that predictive system is a mess, right? Well, my- those chemoreceptors that are picking things up are now on a hot nervous system. So I'm in a nervous system that's set up on a high sympathetic drive to be on alert and not be able to manage things, so then I'm just more set cued up to be driven into reactive mode where I'm in that limbic system where I'm in that emotional system trying to validate the problems that I have by not looking at where they originated from, which is myself in most cases, 99.9 percent of the time, right? Accidents do happen, however...","offset":908,"duration":44},{"text":"Host: Yeah, that’s that's I think that's like the bridge between the mind-body conversation I think is really interesting and you know, I’m like the if there is some type of internal impression, you know, or trauma unprocessed aspect of yourself or event or experience within your life that could be like a a smoldering ember deep within your subconscious, you know, and you keep on addressing all of the smoke that's arising and you temporarily be like, oh cool I feel better because I did this breathing practice, I’m down-regulated temporarily. Or I did this psychedelic thing or I had sex or I had this dopaminergic response from you know whatever the thing is, I'm like ah I'm temporarily okay.","offset":952,"duration":37},{"text":"Host: But you haven't actually addressed the smoldering part. And then simultaneously, you can use the breathing tools tools in order to down-regulate the system enough to be able to develop clarity to actually do the work to assess the smoldering ember. Does that make sense? And then so just how do we- how do we do that? Because I think that's what we're trying to do.","offset":989,"duration":21}],"startTime":431},{"title":"Overcoming Victim Mentality","summary":"Brian and the host emphasize that breathing exercises alone cannot fix underlying psychological traumas. They discuss the necessity of shifting away from a victim mindset to genuinely address the root causes of stress rather than remaining in stasis.","entries":[{"text":"Brian MacKenzie: Yeah, you know, I- I think fundamentally people have to start to look I mean here's what I've done and the people that I've worked with do, you know, a lot of them, um, is if you're not willing to look at your experiences a bit differently, meaning, yeah maybe that wasn't exactly how it went or maybe there's another way to look at this, you know, um, then you're you're pretty fucked, excuse my language.","offset":1010,"duration":29},{"text":"Host: Yeah, you’re just if you’re not- if you’re not willing to take yourself out of like a victim kind of mindset I think everything else is just like stasis.","offset":1039,"duration":6},{"text":"Brian MacKenzie: Yeah, you're like if you're just so cued up that you had this torturous childhood that, you know, maybe you did, however hate to be the bearer of bad news but you are a survivor, you are here now and you are listening and if you're listening to this you're on the internet, you're on something and you're living a pretty decent life. So you you can do it, I promise you. Um, I'm a bit more direct than most people with this stuff because I'm not a therapist and I'm like hey you're either going to address this or you're not and if you're not going to really start to address this and you continue down this path, the work we're doing isn't going to work.","offset":1045,"duration":38},{"text":"Brian MacKenzie: Because you cannot just apply breathing methods and hope you're going all the pain's going to go away. You're just become you're just using you're just using another addiction for something, just filling a void that isn't, you know, fillable.","offset":1083,"duration":16},{"text":"Host: What would be the because I think there are mechanical levers that a person could start to pull?","offset":1099,"duration":5},{"text":"Brian MacKenzie: Oh- 100 percent. Here's how I look at it. It's like hey, let's let's go over to that model like Steve Peters created. Let's let's just say I'm in this emotional state where I don't he created this model's brilliant, it's like if you don't like how you feel, if you don't like how you behaved or you don't like what you think, guess where you're at. You're inside that chimp. Okay? So if you've got anything going on there, that is the perfect opportunity to introduce some breathing of some sort to bring you down to a level to be able to calm down enough to say to yourself what is the truth or what is the reality about what it is I'm feeling right now.","offset":1104,"duration":43},{"text":"Brian MacKenzie: Is this person who cut me off in in traffic, were they out to get me or maybe they're just in a rush and I can let this go. I don't know, whatever your f- whatever you're dealing with, right? Like, you know, the deal that you were supposedly going to close for millions of dollars or, you know, the job you were going to get, I understand that that was, you know, that's difficult. But are you capable of lacing up your shoes tomorrow and going after something else and finding something else creative in your life in order to yeah, because you've made it this far. So yes you are.","offset":1147,"duration":28},{"text":"Brian MacKenzie: So if you can really look at that and go oh okay, but breathing’s the tool to kind of get you out of where you don't like what you're feeling and you know in that with what you said earlier it's like you know you got this victim side if you're ever the victim you're in the mod- you’re- you’re on the wrong side of the tracks, trust me.","offset":1175,"duration":23},{"text":"Host: I think you’re just in stasis. I think it’s I think victim and stasis are synonymous. It's fine, but just know that you will not grow from there. It's fine, just know that you're in a pause state for as long as you choose to be in that victim space. And it’s fine, be there for 20 years. It’s fine, just stay- stay put.","offset":1198,"duration":15},{"text":"Brian MacKenzie: Yeah, no big deal. It’s just nothing will change.","offset":1213,"duration":3},{"text":"Host: Yeah.","offset":1216,"duration":1},{"text":"Brian MacKenzie: So and- and I’m really good with my life and I’ve, you know, we just won't be close. We won't be having many conversations. Awesome.","offset":1217,"duration":9}],"startTime":1010},{"title":"Breathing Mechanics and the Pelvic Floor","summary":"The conversation shifts to the mechanical aspects of breathing, highlighting the diaphragm as the epicenter of the core. They detail the importance of horizontal rib expansion and the functional, synchronized relationship between the diaphragm and the pelvic floor.","entries":[{"text":"Host: Um yeah. So breathing something that I'm curious from your perspective and experience with in relation to breathing and mechanics, I feel like mechanics is something that's not spoken about that much. It's a lot about breathing practices and do a 5-7-8 or do a box breathing or do a Wim Hof or do a holotropic or do a this and there's I don't hear very much other than like postural restoration institute which is super complex and hard for any even super smart person to understand.","offset":1226,"duration":30},{"text":"Host: Um, you know, so within these conversations are there some aspects of the physical meat suit that you would recommend people be able to start to work on within themselves to be like oh actually just like you need to shift some things mechanically within your shoulders or your diaphragm or your pelvic floor or your tongue or your you know nasal passages, whatever. How do we start from from the mechanics of the physical body to be able to naturally breathe better?","offset":1256,"duration":30},{"text":"Brian MacKenzie: The the easiest way to do it without having me or you there for somebody is to really go you know go somewhere on YouTube and start to find you know look for some core exercises or go look at somebody like a Starrett who's going over movement principles. And like for for for complex movements like a squat or a hang or like a press, right? Like you're overhead with a press. Like here's something for people like you go and press overhead just take a 45-pound dumbbell or a- a bar, dumbbells are going to be far more challenging, right?","offset":1286,"duration":33},{"text":"Brian MacKenzie: But take a- take a bar and go overhead. Shut your mouth and go end to end nose-only breathing, right? You're going to start to figure out how how non-integrated your core actually is because or how much your diaphragm actually should is is integrated into the core complex. In fact, I'm of the mindset it is the epicenter of the core complex because the moment that diaphragm's out of place, the breathing gets very difficult, right? Maybe you don't start with a press overhead, maybe you go online, find some videos or some tutorials from some experts on movement standards for some complex movements, go get into those those positions, shut your mouth. Can you go end to end from your nose for 5 to 10 breaths and just hold that?","offset":1319,"duration":51},{"text":"Brian MacKenzie: That will tell you how you're set up with that diaphragm real quick and the intercostals per se. I don't want to leave the intercostals out because the intercostals and the diaphragm work together. It's not a separate thing, those two muscle groups work together um, to move that cage open. From there, it becomes secondary where you're talking about things, you know, pecs that come off, the neck muscles, etc., then things start to grab. You want to make sure that those those secondary muscles aren't first things to grab when you're doing these things.","offset":1370,"duration":40},{"text":"Brian MacKenzie: If they are the first things to when I breathe then we definitely want to address this and this is where it's like get into those positions and try that. You know, I go to the extremes of getting people with some resistance breathing devices that are fairly cheap and easy to get, um, to where we really train, you know, the strength of these things um, to challenge people. But we don't do a a ton of it. We do some of it as some auxiliary work and then it's like I move more into like breathing gear work with, you know, warm-up and and designed cardio or aerobic work that we implement the breathing gears into.","offset":1410,"duration":38},{"text":"Host: Um what would be the- I mean this might be kind of a a variable question, but what would be the ideal sequence of breathing through you know the ribcage and the torso and the whole chest cavity? If you were to start a breath, an inhalation from full evacuation, what should that look like? What are cues that we could be feeling into and how would that- how would that look in an ideal world?","offset":1448,"duration":26},{"text":"Brian MacKenzie: If this is the bottom of your ribcage, right, your ribs, this thing goes out like that. Most people are taught or hear their belly should move. You should feel the air into your back first. That doesn't mean the belly doesn't move, but we're talking the upper belly, not the lower belly. If the lower belly is what is coming out, you're dealing with pelvic dysfunction, pelvic floor dysfunction most likely.","offset":1474,"duration":38},{"text":"Brian MacKenzie: So I've run into a number of yogis who've practiced for years and taught that whole belly thing and literal- you know and and they're quite they have quite dysfunctional breathing patterns because they can't breathe into the ribcage. They're actually just breathing down, they're not expanding the cage, right? We want expansion horizontal and then that's where the vertical occurs, right?","offset":1512,"duration":26},{"text":"Brian MacKenzie: So it horizontally initiates and if I just put if I just sit if I just sit up with on my sit bones vertically in a chair with my back my back's not on and I put my hands around my lower ribs, I just want to organize down a little bit and then I and I feel those ribs move immediately out and into my back and then my belly ends up filling, right? That's the the upper part of my belly. So that's that's essentially where that happens and then from there it then becomes shoulders and and all that. But we're not you don't need to really train those secondary muscles, those are short-term muscles that are very glycolytic in nature, so those are those are for last resort type things.","offset":1538,"duration":50},{"text":"Host: And the the most common tendency for people would be for the ribs to have a tendency to flare and kind of be stuck in like external rotation. And to be able to come down and drop down towards the pelvis and drop into internal rotation on the exhalation is going to be very healing for creating support and stability for that respiratory diaphragm pelvic floor relationship slash the whole everything.","offset":1588,"duration":22},{"text":"Brian MacKenzie: Correct. Yeah, I mean that pelvic floor is so important and I think so many people miss that to where it's like, you know, if you're if you're really working on some breath control and core work, you should be pulling up. Like you should be you should be like it's like you're stopping yourself like you've got to go the bathroom real bad and you're pulling up and trying to stop that. That should be engaged as you're breathing, especially on that exhale.","offset":1610,"duration":28},{"text":"Brian MacKenzie: Now, that shouldn't be something you're walking around all day thinking about, right? Because if you've done the work, those muscles naturally should remain engaged then when they should be.","offset":1638,"duration":16},{"text":"Host: It’s kind of like healthy healthy tone, not be excessively flaccid or hypertone either. Be like dynamic. It’s interesting the idea of so the, you know, your whole body's a closed hydraulic system and so if you think of the diaphragm descending to expand open, create a vacuum in the lungs to pull air in, the pelvic floor needs to also be able to expand and relax. And so going through that that relationship of as I inhale, there needs to be an opening through my abdomen and my lower back and my pelvic floor to be able to actually allow the space for my diaphragm to function. Like there could be dysfunction because of inhibition or rigidity within my pelvis, which is interesting I think to start to bring- it’s like oh I need to breathe into my cock. Cool. I didn’t think about that.","offset":1654,"duration":55},{"text":"Brian MacKenzie: Yeah. Most people aren’t engaged down there in the wrong way. It’s just it is what it is, but I mean that's part of it. So mechanically speaking, you know, you kind of want to dial that in a little bit every day or, you know, whenever you go train, like that's just kind of like starting, you know, with some stuff, like do a few exercises that revolve around that. Once you get it dialed, that stuff can get a little bit more extreme. Like I I do I'll do some hard some hardcore like kind of neck training stuff that involves the whole core, but like I've got a resistance breathing device in and I'm going end to end with that for a couple of sets to get that strengthened but also to get it activated so that when like I go squat or deadlift, I’m not doing that shit, I’m just squatting and deadlifting because it’s now integrated and it’s a part of the process.","offset":1709,"duration":52}],"startTime":1226},{"title":"Training with Resistance Devices","summary":"Brian recommends using inexpensive resistance breathing devices to strength-train primary respiratory muscles. They discuss how to incorporate this training into warm-ups and emphasize the need for proper rib alignment and horizontal expansion during practice.","entries":[{"text":"Host: What resistance breathing devices would you recommend for someone? Is a straw enough or like what should...","offset":1761,"duration":5},{"text":"Brian MacKenzie: I I would just get um, I mean I can here I can tell you and it's actually really cheap, very cheap, I mean I send this to everybody...","offset":1766,"duration":8},{"text":"Host: It’s like one of those little like snorkel snorkel mouse things with a little little turny doodad valve on it.","offset":1774,"duration":7},{"text":"Brian MacKenzie: Correct. Yeah, I have one of those too, I like it.","offset":1781,"duration":2},{"text":"Host: It gets all slobbery though, that’s the only thing I don’t like about it.","offset":1783,"duration":2},{"text":"Brian MacKenzie: It does, but like it's yours, man. Like you wash it out with water every time. Portable respiratory muscle trainer on Amazon.","offset":1785,"duration":11},{"text":"Host: Yeah, that’s the same thing I think, it’s like 13 bucks or something like that.","offset":1796,"duration":3},{"text":"Brian MacKenzie: Yeah. Yeah and so- I buy like 20 of them at a time and then I just give them to clients as they come in and stuff.","offset":1799,"duration":9},{"text":"Host: Yeah those tools are great because it it creates feedback and resistance to be able to actually have to really actively engage those muscles, the respiratory muscles. And you'll see people's neck start to grab and you're like dude, no, no, no.","offset":1808,"duration":12},{"text":"Host: So I have a question for you with that. With using the respiratory tool like that, would it be is it okay that you are now practicing mouth breathing for one thing, um, and is it more efficacious or does it matter to emphasize the exhalation or the inhalation if you're using resistance for your breath?","offset":1820,"duration":22},{"text":"Brian MacKenzie: So in- in with respects to this is causing more resistance than what the nose does. So that's why I'm actually using it, it's strength training. So I'm actually doing some strength training I'm looking at it like lifting weights for the primary breathing muscles um, and getting the core integrated into that. Um, that is all we're doing with that. I will sometimes include it into cardio warm-ups where we go resistance breathing device, you go end to end one- one to three breaths at the top of every minute and then you go right back into nose breathing and the nose breathing feels like mouth breathing.","offset":1842,"duration":43},{"text":"Brian MacKenzie: So it's a very easy, well-orchestrated path to kind of not only getting warmed up and getting the pulmonary system integrated with everything, but I'm getting my breathing really ready to go for whatever sort of intense work I might be doing, which is something most people are never thinking about or doing.","offset":1885,"duration":26},{"text":"Host: And something probably for people to think about if they are using a a resistance tool like that or just using the natural resistance of just, you know, breathing in general, uh, would be paying attention to the alignment of your ribs and your pelvis and all of that. Because it's kind of like if you're doing, you know, kegel exercises but you're practicing clenching your- your kegels um from a a quote unquote like dysfunctional position, you're just um downloading or pressing save on a dysfunctional file. And so if you're doing these resistance exercises, it would probably also be wise to be paying attention to orientation of the ribs and all the other different parts. Is there any specific cues you would provide for a client or yourself as far as rib orientation or body orientation when they're going through a a resistance breathing exercise?","offset":1911,"duration":53},{"text":"Brian MacKenzie: They they will typically because my clients are typically all over the work- they're all over the place. So I'll they'll get videos of how to do a specific exercise then they're actually given, hey, I want you to go end to end three breaths with this device in that position. And they supply me with the feedback on that type of stuff. So hey, was that how hard you know, what was going on? Um, if somebody comes to see me and I work with them, I'm actually my hands are on them and I'm showing them exactly what's going on, um, you know, but for- you know I don't I try to keep it as dumbed down basic as possible meaning I don't try and talk over their head about mechanics, I try and just go no let's see this position, now show me your breathing. And they like fill up. And they're like holy crap, you know, and it's like yeah, you couldn't fill up before.","offset":1964,"duration":57},{"text":"Host: I like the I don’t know if this is Belisa Vranich’s language or not, but I got it from her of like the horizontal versus vertical breathing.","offset":2021,"duration":7},{"text":"Brian MacKenzie: Yes, that is- yeah. That yeah, that is Belisa's. She’s...","offset":2028,"duration":5},{"text":"Host: And so something like really simple would just be like allow your ribs to kind of descend a little bit, like relax, like relax in yourself and then bring your hands on the sides of the ribs and feel that breath starting to move horizontally. And then you could also put your hands in your lower back, which I don't know if Belisa recommends this as well, but I do. Um and feel that breath going into your back and that’s going to naturally place the ribs into a more natural healthy kind of like cylindrical orientation to be able to create better pressure and then maybe stack the the breathing on top of that. I think would be maybe a potential you know horizontal breathing with that. Yeah. And then with with and then with something that's very common with people is nasal restrictions. Do you have any recommendation for that? So we- so we've got resistance, we're starting to turn on the respiratory muscles, we're starting to align and organize the diaphragm and all that stuff, but we still are bunched up and we actually can't get breath through the nose.","offset":2033,"duration":56}],"startTime":1761},{"title":"Fixing Nasal Restrictions","summary":"To fix nasal restrictions, Brian suggests a month of strict, low-respiration nose breathing to force adaptation without using mouth tape. However, he warns against the exclusive nose-breathing trend, noting that mouth breathing becomes physiologically necessary at higher cardiovascular intensities.","entries":[{"text":"Brian MacKenzie: Yeah, I uh go spend one month focused on not going outside of a gear one, which is you know an equal in and out nose-only breathing where it's greater than 4 seconds in length, so like a two in two out, two seconds out, two seconds in, two seconds out. So your breath rate your respiration rate is below 20 breaths per minute, right? Go only do that for a month no matter what. So toggle down the intensity of whatever you're doing if it pushes you beyond that, right? Do that for a month, then if your nose is still an issue, go see an ENT and get that thing- thing cleaned out.","offset":2089,"duration":47},{"text":"Host: Why a month? What happens during that time frame? and would you recommend mouth taping during that time frame for any activities at all?","offset":2136,"duration":10},{"text":"Brian MacKenzie: No. I don't like mouth taping because it just- it kind of- it changes the the level of commitment. It's like oh I'm just going to put this tape on so I don't open my mouth. No, you- you really should be learning to kind of wire that up mind and body a bit. Um the big thing is adaptation. What sort of- like for if you look at my nose...","offset":2146,"duration":27},{"text":"Host: You got- you got a little lopsided there, bro.","offset":2173,"duration":3},{"text":"Brian MacKenzie: Yeah, I'm very lopsided.","offset":2176,"duration":2},{"text":"Host: I think mine’s lopsided too.","offset":2178,"duration":1},{"text":"Brian MacKenzie: Yeah you’re not too bad. Regardless, I can operate in a gear one up to about 140 heart rate, which is just touching zone four for if we're talking about cardiovascular, right? Like so like that and beyond that I then switch into a gear four which is easy mouth breathing because that's where that should happen because now we have a whole community of people who bought into this nose breathing thing and thinking that it's the be all end all. It is not. I've- I've tested a lot of people, they retard things in the opposite direction because now you're not getting enough oxygen when you go above moderate efforts of exercise.","offset":2179,"duration":53},{"text":"Brian MacKenzie: So now you're not actually onboarding enough oxygen for use. So ventilation goes up, right? So depth and rate change for very good reason. But easy mouth breathing gear four is just and because you've been rewiring things for a month, when you do switch out when you do go up to that you now are primed and designed to really be using those primary breathing muscles still.","offset":2232,"duration":27},{"text":"Brian MacKenzie: You don't need to bring on where most people who have not done any sort of training with these with their with their breathing muscles are tend to have I mean I can- the amount of runners I watch and see that are just like breathing here, stiff upper, you know, their neck is stiff, all of it. They don't they only have access to the upper chest for breathing. They're missing huge huge opportunity and the huge opportunity from what I've been seeing with testing, I mean I I see between 20 and 60 percent changes in VO2 Max with most of the people that come to me. And I have seen some elite athletes.","offset":2259,"duration":46}],"startTime":2089},{"title":"The Gear System of Breathing","summary":"Brian outlines his five-gear system for breathing, ranging from slow nasal breathing (Gear 1) to heavy mouth breathing (Gear 5). He explains how tidal volume changes with intensity and how alveolar sacs are most sensitive at the end ranges of respiration.","entries":[{"text":"Host: Could you outline the gear system of breathing quickly? Because I think it's a a great model for people to to have.","offset":2305,"duration":7},{"text":"Brian MacKenzie: Yeah. Gear one is easily is is easy nasal breathing, but it's also, you know, it's controlled, it's it's greater than 4 seconds in length, right? So two like just think of it as two in two out. Gear two is power nose breathing. Gear two is very limited because we will skip gear three, which is transitional, that's usually transitional gearing down, but I'll sometimes use that to train people just for some just training purposes.","offset":2312,"duration":35},{"text":"Brian MacKenzie: However, it's a gear it's a transitional gear for gearing down, so so don't think of gear three right now. We go gear two, gear four, which is... into gear five... So anything above roughly a 30 respiration rate with mouth breathing is gear five. Gear four is between 20 and 30 breaths a minute. Um, gear three comes in when I go from working hard into I now shut it off and now I'm... nose in, mouth out. And you will see recovery happen pretty quickly by doing that and you could also reverse that but then you move that air with that transitional gear and as soon as you feel a change then you drop into a gear one.","offset":2347,"duration":70},{"text":"Host: And how does that work that when you are in say gear five because you are in higher respiratory demand, being in that gear too much or just breathing that way in general or mouth breathing, you're off-gassing more CO2 and alla Bohr Effect, you're increasing alkalinity, decreasing acidity and you are causing your hemoglobin to become change shape and become more stingy with the release of oxygen while simultaneously you need more oxygen in that moment.","offset":2417,"duration":33},{"text":"Brian MacKenzie: You you can overbreathe at moderate to lower to low-high intensity efforts, meaning like heart rate zone four and below, you can overbreathe in. Like heart rate zone you're 90 percent and above, you really can't overbreathe, although there are compensations that I've seen and picked up on where people are breathing at like a 60 respiration rate but they're at like 70 percent tidal volume. So you're in an obvious compensation at that point where you can't hit tidal volume, you know, because you're so stressed.","offset":2450,"duration":34},{"text":"Host: Can you define tidal volume?","offset":2484,"duration":2},{"text":"Brian MacKenzie: Yeah. The depth at which so how much air you can act- how much air you can fill your lungs with. You'll still you will see people hit some tidal volume in like a gear two, gear one, so they'll hit in range, but they're not needing to move that very fast, right? Well, if I'm moving up into a gear five and I can't go all the way in, so that just means I'm going short and short-change breathing, I'm just going... versus... Right? You don't need to necessarily hit end to you know bottom end, but if you can't hit that top end, there's a problem. Your alveolar sacs are most sensitive at end ranges. So you're getting to you're getting best diffusion off of CO2 and O2 at those end ranges.","offset":2486,"duration":46},{"text":"Brian MacKenzie: There's a there is a genetic reason for that. If I'm in fight or flight and I'm hauling ass and I'm moving, I got to be able to move air and get real good air.","offset":2532,"duration":15},{"text":"Host: How interesting, your alveolar sacs are more sensitive during end ranges, so full exhalation full inhalation you're going to have more sensitivity within- is that- is that kind of like the the physiological sigh kind of thing where it kind of like lifts them off of themselves from collapse?","offset":2547,"duration":16},{"text":"Brian MacKenzie: Yeah and yet none of that is necessary if I'm calm. So I can just be but you can't see that I'm breathing, that that's, you know, when you get back to normal breathing, normal breathing should be I can't tell that fool's breathing.","offset":2563,"duration":16}],"startTime":2305},{"title":"Contextual Importance of Exhalations","summary":"Prompted by the host's experience with Laird Hamilton's pool training, Brian discusses the value of a full exhalation. He clarifies that while dumping all your air is crucial for extreme breath-hold scenarios, it isn't always optimal or necessary during standard aerobic exercise.","entries":[{"text":"Host: Yeah. Like the samurai breath or what- what people call it. Um I was doing the I know you have relationship with Laird Hamilton I was doing the the pool training stuff uh out at his place maybe I don't know whatever last summer. And the one of the things that stood out to me as we're dunking up and down uh that he said that has continued to stand out and been something that I've like I've continued to perpetuate with myself is that it's not about the inhale, it's about the exhale. And that was like a download that he got from I don't know who somebody else and that was one of the things like when we come up out of the pool it was like getting a full evacuation to get all of that air out to be able to get replenished with a like a you know a a more robust inhalation or a richer inhalation. Do you think that there's something to that? What are your thoughts of the value of of exhalation?","offset":2579,"duration":56},{"text":"Brian MacKenzie: In in certain instance in certain instances, yes, right? In certain instances, yes. I don't think you need to dump all your air all the time. Um in fact, I I mean I'm on a bike or I'm on a you know I'm running and I'm I'm I'm literally research I'm studying the stuff I'm doing, I'm paying attention to where is the change happening. And I've got like a metabolic cart on, right? And I've got and I'm watching tissue saturation. I'm watching this stuff as it's occurring and dumping the air while exercising all the time is not necessarily the best like trying to get rid of that, that's just wasted time. You're going to actually move you're moving air fast, air doesn't just sit while I'm moving air like this, right?","offset":2635,"duration":45},{"text":"Brian MacKenzie: But in instances like with Laird in the pool or Laird in big surf, yeah you want to be getting rid of your air before you go to take a full inhale because you're going to need all the fresh air you can get in order to be down for two or three minutes while you're getting rolled, right? Like so in Laird's training to be clear is is genius in that this this maniac discover- figured out how to kind of push those limits of CO2 and pressure and force control of breathing in a pool environment. So I mean it- he's a genius like that. I mean he's an innovator, the guy is an innovator. That's what he does.","offset":2680,"duration":46}],"startTime":2579},{"title":"Avoiding Dogma and Assessing Physiology","summary":"Brian criticizes the breathing industry for focusing on rigid methodologies rather than fundamental mechanics and physiology. He shares his approach to using metabolic assessments to spot limiters in elite athletes and executives, concluding with where listeners can find his coaching.","entries":[{"text":"Host: Are there so we we can wrap up here do you have like a hard out you got to get out of here like...","offset":2726,"duration":5},{"text":"Brian MacKenzie: Yeah I do I have a yeah I definitely have a hard out in like 5 minutes.","offset":2731,"duration":4},{"text":"Host: All right, cool. Sweet. Um I so in wrapping things up, uh are is there anything that you see standing out in the in the breathing world that you feel is maligned or off that you would like to see rectified or shifted?","offset":2735,"duration":22},{"text":"Brian MacKenzie: Oh, I stay away from the breathing world. Most of it's hogwash.","offset":2757,"duration":10},{"text":"Host: So what's- what would you say is hogwash in the in the breathing education space?","offset":2767,"duration":5},{"text":"Brian MacKenzie: Uh I I would say most people are getting lost and stuck to a methodology versus understanding respiratory physiology and physiology in general, you know, and and even mechanics, you know, you went into a deep dive with mechanics here. Most of these methodologies and things don't even touch that, right? Because they don't want to because they've got this cool little toy that can change somebody's state and that's really all anybody's interested in. They'll just keep breathing people and doing this with people without actually, you know, going well you're still doing the same shit.","offset":2772,"duration":41},{"text":"Brian MacKenzie: Like hey, for me with what I do with clients is I'm looking to kind of help these people who I mean I'm dealing with professional athletes and like executives working at very very high levels, so managing multiple companies things like that where I do a full run down of like how they manage stress, how they respond to s- an exhale assessment CO2, and then how they respond to a metabolic assessment that I'm looking at tissue saturation, oxygen to the brain, etc. I'm looking at all this stuff so that I can go, hey what you're doing throughout the day we need to figure out some off points because you're not managing stress here very well.","offset":2813,"duration":42},{"text":"Brian MacKenzie: Like I I run people through an assessment that is very um boring to start. They're doing they're doing low-low effort work on a metabolic cart that just goes up a a smidge every five minutes and they're like bored out of their mind and it's everything I need to see because the thing one of the things that changes that really that is that stress thing we started kind of with this is CO2. Is CO2 changes that respiratory drive it changes how things are going on in the body and if I've got somebody we'll just use this as one case because we've talked about it, if I've got somebody who overbreathes a little bit I see that in the tissue. I see that even though the metabolic cart is saying oh he's aerobic right now, or he's utilizing fat. But yet his tissue and his brain are not getting oxygen very well.","offset":2855,"duration":51},{"text":"Host: What would be the metabolic test that that you would suggest someone uh goes through, say from from home? Is there are they going to need fancy gadgets and devices and such or what would be your suggestion?","offset":2906,"duration":12},{"text":"Brian MacKenzie: There so there is actually it's gotten better and I'm supposed to get my third version of this one, but I got a buddy of mine at Duke who's really like I swear this version of it is badass. It's called Caliber, it's spelled C-A-L-B... C-A-L-I-B-R-E, so it's English Caliber, Caliber Biometrics. They've got a $400 uh metabolic cart that's pretty badass.","offset":2918,"duration":25},{"text":"Host: Okay. I’ll look it up.","offset":2943,"duration":2},{"text":"Brian MacKenzie: Um, and- and it's a pretty easy to use with their app um, but it'll give you some pretty good numbers. But if you really want the whole shebang, you're going to want either a MOXY or a Train Red Near-Infrared, but you know it takes time to kind of understand what you're do- I’ve kind of pioneered a way to look at this and look at clientele with this stuff that come to me because I mean I can get some of the high- the highest level players in the world in a sport and I can see a limiter that somebody else wasn't picking up because they just did a traditional VO2 Max test which is just like you start at nothing and you go to everything within like eight minutes. And I'm taking like 30 minutes to get to that to a point to where I might have them work really hard for three minutes, right?","offset":2945,"duration":47},{"text":"Brian MacKenzie: Needless to say, my point here is that most of what I'm seeing if people go and address how they're looking at how they manage their daily life, like the stress of their life, and then they start to implement tools around that in order to bring themselves into reality, breathing has a very potent impact in that, especially when we apply it to exercise and you decide to stop being a reactive, you know, SOB to everything or victimizing yourself to everything, that is where breathing has a very very potent deal. And I've had I've had um an entire C-suite at one point thank me as a client walked out of the room, who was you know the owner of the company, and they literally were like thank you with what for what you're doing this this like over the last three years this dude this dude has changed so much, like he's calmed down in a level to where he's not as reactive and not this tyrant, right?","offset":2992,"duration":60},{"text":"Host: Like he’s- he’s regulated. Um I so I appreciate you saying the thing that you'd want to change is the lack of emphasis on mechanics and a lack of emphasis on principles around respiratory physiology and understanding like how to how to kind of drive the boat as opposed to just having some specific exercises because I created a program that's not out yet but it's all founded on first mechanics and then the principles of down-regulation and up-regulation and then a section on anatomy and physiology of just like what you ought to know to have a visualization of what's happening. So I’ll include that for people listening in the intro- the link for that for like we’ll have like a free trial and all that stuff. And so I'm very glad that that's the exact thing because I'm like I agree. That’s why I made something.","offset":3052,"duration":46},{"text":"Brian MacKenzie: Exactly. I’m like yeah I’m off- I’m in my own world doing my own thing, I'm like I'm good man I don't want to like the whole breath space it got so I was just like no I'm out, everybody's into their own little methodology of some sort.","offset":3098,"duration":14},{"text":"Host: Yeah, I’m not into methodologies. Principles, learn principles. What do you need to know as far from a principle-based understanding and then from there you can apply the principles on whatever methodology but actually understand the intrinsics of the methodology as opposed to being lost in the methodology. Um, thanks so much man, I really appreciate these conversations. Um where if people want to I know that you do various different things you actually actually work with with coaching clients you have all sorts of things...","offset":3112,"duration":29},{"text":"Brian MacKenzie: We we have a membership website people can jump on we're not exactly very active with that. I have some coaches that help run that with for me, but what I do is very personalized, um it requires high high um commitment level uh meaning life and financially for people to invest in. Um it's not a a short-order process, but if people really are interested and think that they want to you know test that, more than welcome to jump in, go to shiftadapt.com and just go through the website, they'll they'll find everything there.","offset":3141,"duration":37},{"text":"Host: Amazing. Cool. Um thanks so much I appreciate you...","offset":3178,"duration":3},{"text":"Brian MacKenzie: Very easy, uh I I love you dude you are such a cool soul.","offset":3181,"duration":4},{"text":"Host: I love you more I appreciate you man. All right that’s it that’s all thank you for tuning in I’ll see you next week.","offset":3185,"duration":15}],"startTime":2726}],"entries":[{"text":"Brian MacKenzie: Oxygen is a useless, destructive molecule without CO2. Most people are getting lost and stuck to a methodology versus understanding respiratory physiology and physiology in general. When you can hold your breath for a significant amount of time, what you’re doing is training your mitochondria to use less oxygen for more ATP. It’s not about the inhale, it’s about the exhale, which is something most people are never thinking about. Breathing’s the tool to kind of get you out of where you don't like what you’re feeling.","offset":0,"duration":36},{"text":"Host: Why is it that breathing affects one's state of consciousness so deeply and quickly and with such great efficiency and consistency?","offset":36,"duration":12},{"text":"Brian MacKenzie: Well, a number of reasons but, you know, one of the main being the fact that, you know, we're largely controlling carbon dioxide with breathing. Although, you know, you're bringing in oxygen as well and that's important, you know, 80 percent of that oxygen is roughly offloaded at rest. So when we're not working, when we're not doing something, a lot of that oxygen is not necessary. That being said, the CO2 actually is, and that is the, you know, one of the big drivers of things, but from a biochemical standpoint, CO2 regulates pH.","offset":48,"duration":40},{"text":"Brian MacKenzie: So that is essentially what's really the big player in regulating pH real time. Yes, the kidneys play a role in that and there’s a lot of other processes, but the major player with breathing is that it's a respondent to pH and if I change that pH, things start to change, the dynamics start to change, right? And as CO2 goes up, more oxygen comes off, comes out and is usable.","offset":88,"duration":24},{"text":"Host: From hemoglobin, from red blood cells. It liberates them.","offset":112,"duration":5},{"text":"Brian MacKenzie: It liberates that. So then you've got, you know, if you've got functional mitochondria, you then get that oxygen down to the electron transport chain and you're now pumping that out. The better you get at this, and you know, as I used earlier as his, you know, opening protocol, when you get to his level of breath hold, you know, you don't even necessarily need to be at his level, but the reality is is that when you get to, you know, when you can hold your breath for a significant amount of time, what you're doing is training your mitochondria to use less oxygen for more ATP.","offset":117,"duration":33},{"text":"Brian MacKenzie: This was done in a, they looked at this at a study done, I think it was in Sweden, but it's called the Tortoise and the Hare. And uh, in the lab, these guys had a professional triathlete, an elite triathlete, and an elite freediver who were both in the lab at the same time who were PhD students, I guess, or master's students, and they decided to take a look at the differences in them and how they used oxygen. And of course the triathlete being elite, used it real well from a VO2 standpoint and all of these things, he had a much larger aerobic threshold than the actual freediver.","offset":150,"duration":40},{"text":"Brian MacKenzie: However, once they came into this conclusion about the less oxygen for more ATP, they were like, oh, well there's the other side of aerobic we haven't been looking at. So there's high benefit in in being able to hold one's breath, but you don't necessarily need to become a freediver or breath hold expert in order to get these benefits. Uh, you know, most people are overbreathing, which is you're just off- you’re just offloading CO2, um, as a result of that overbreathing even a slight bit, and that means you're just not getting as much of that oxygen off that hemoglobin.","offset":190,"duration":35},{"text":"Host: And what is- CO2 has largely been villainized historically for most basic people.","offset":225,"duration":7},{"text":"Brian MacKenzie: As a waste, as a waste product.","offset":232,"duration":3},{"text":"Host: And- and yeah, oxygen good, CO2 bad, get the CO2 out, get the oxygen in. That’s obviously wildly incorrect and excessively basic and just...","offset":235,"duration":7},{"text":"Brian MacKenzie: In facts, actually it’s kind of reversed.","offset":242,"duration":4},{"text":"Host: Yeah.","offset":246,"duration":0},{"text":"Brian MacKenzie: So oxygen is a useless, destructive molecule without CO2.","offset":246,"duration":6},{"text":"Host: Right.","offset":252,"duration":1},{"text":"Brian MacKenzie: No, literally. Like, it we’re- we're literally getting oxidized from the inside. Free radicals, like, have you heard of it? Oxidation? Like your car, you know, you go look at a car that’s being oxidized, that’s oxygen.","offset":253,"duration":13},{"text":"Host: And that’s a part of like hyperbaric chambers, it’s you’re pushing oxygen deeper which is actually creating a hormetic stressor. That’s like a part of mobilization of stem cells and such, you’re actually challenging your body.","offset":266,"duration":10},{"text":"Brian MacKenzie: Correct. Oxygen is important because of aerobic cellular respiration in that oxygen's role is to regulate metabolism, right? Where CO2 is there to regulate biochemically pH, right? And so they- they work together, but, you know, as- as you explained, you know, lots of people like to go in hyperbaric chambers and they don't actually understand why they're going in there. They're actually creating a very stressful response that they rebound from and a hormetic effect that inevitably has a very positive response after about 20 sessions can turn some things on and get some things boosted as a result, but make no mistake, you are stressing the hell out of your system as you're doing it.","offset":276,"duration":48},{"text":"Host: Could you outline some of the benefits you already have a little bit, but go a little bit deeper into some of the benefits of CO2 that people might not recognize or realize, some of the like effects that people experience by having CO2 in their system?","offset":324,"duration":15},{"text":"Brian MacKenzie: Yeah, I mean it- it's a calm- it’s going to create a calming effect back you know, like 60s, 70s probably before even the 60s, but I mean I even remember in the 80s that, you know, people who the rare panic attack that would happen, people were given a paper bag to to breathe re-rebreath into. You’re just basically rebreathing CO2 and that creates a calming effect, right?","offset":339,"duration":22},{"text":"Brian MacKenzie: Um, because the more CO2 that's in the bloodstream, you're actually starting to vasodilate things, the nervous system’s responding by coming- calming down, becoming more parasympathetically driven. You know, and that's- that's essentially why we were really designed or the respiratory system, the pulmonary system was designed with the nose in mind and not necessarily the mouth for most of breathing, right? That nose has intricate processes set up and one of them is it retards how much air can come out and by that, you're getting the ni- you're getting a good dosing of CO2 whereas as I speak or you speak, you know, arousal starts to shift and that CO2 starts to drop.","offset":361,"duration":47},{"text":"Brian MacKenzie: So I start to use more glucose, I start to move, you know, I'm moving into a- a more activated state, which is natural. However, if that's what I'm doing all day long, where am I- where are those changes coming in to where I’m not? And that's where the regulation of breathing and and CO2 essentially start to come in where, uh, you know, people who who aren't mouth breathers tend to be a little bit calmer.","offset":408,"duration":23},{"text":"Host: It’s interesting how it seems confusing. I was just doing a podcast with Robert Sapolsky, the \"Why Zebras Don't Get Ulcers\" guy, a couple- couple days ago. And that was- I had some questions for him in relation to like what's the evolutionary or adaptive quality of certain things like people, you know, he’s like baboons and certain primates and humans end up having too much time on their hands and then they end up being like evil to each other and destructive to each other. So the questions of like why is that an adaptive quality and strategy and how has that managed to persist in evolution?","offset":431,"duration":40},{"text":"Host: I wonder with breathing, kind of similar type style question, bad breathing and anxiety and maybe a higher proclivity towards reactivity or anger outbursts and things of the sort will end up actually perpetuating more bad breathing, which bad breathing being like maybe mouth breathing or emphasis on the exhalation or faster breathing or excessive dumping of CO2 making you be more stingy with holding on to oxygen and a less efficient mobilizer of oxygen and just generally like puts you in a place of feeling like you’re kind of suffocating within yourself and you kind of literally are. That seems contradictory to me that evolution would- would permit that. Do you know what I’m saying?","offset":471,"duration":37},{"text":"Brian MacKenzie: No, I- know, because I- I get it and I'll- I'll kind of this is great question. So- or great statement. It's not that I understand what you're saying, however, I've spent so much time in this that I've got a pretty good handle on what I think is the reasoning, you know, and what what happens. Um...","offset":508,"duration":20},{"text":"Host: And did I outline that question appropriately? Was there anything that I said in there that was like that should be cleared up or was that an appropriate way of asking it?","offset":528,"duration":7},{"text":"Brian MacKenzie: No, no, it was very appro- no, no, very appropriate. I'm just- I'm- I- was tickled that you asked because, uh, you know, it's interesting because I was just speaking with Professor Steve Peters in- do you know who he is?","offset":535,"duration":12},{"text":"Host: No.","offset":547,"duration":1},{"text":"Brian MacKenzie: So he wrote, \"The Chimp Model\" for, uh, brain I think, and now his newest book is \"The Path Through the Jungle\". Dude, the dude is on a level. Um, he- he lives in, um, he's English, but I have never heard anybody explain he's a psychiatrist by trade, but he explains the neuroscience of everything and this is where why it got so interesting to me is because he started explaining this chimp model of the brain and how we've got two- we’ve got three teams, right?","offset":548,"duration":32},{"text":"Brian MacKenzie: And one team is the kind of the it works off an emotional response and then there's a logical reaction that kind of tells a story to validate that emotional response and this is how children grow, this is the child’s mind. And then it has an action next to it, right? And that action feeds team three, which is a program, okay? The second team is the logical brain or the human brain. And so that first team is the chimp model, the second team is the human model where logic is the basis of things, reality is the basis of things, then there's an emotional response then there's an action towards that thing.","offset":580,"duration":33},{"text":"Brian MacKenzie: Either one of these feeds that system down to team three or the program, okay? So the program wires up based on how you're going, right? And team one, the chimp model's not bad and team two is not good. They're both good, they're both there for a reason, you're there to survive, we're here to survive and we should honor how we've decided to move through the world, how we grew up and how those responses came in, etc., etc.","offset":613,"duration":30},{"text":"Brian MacKenzie: Anyway, when he got into this stuff, he started talking about that emotional model and the limbic system, because that's what it- where it really functions. And in the limbic system is the amygdala. So we understand that there is this little, you know, almond-shaped thing that is like the fear center of the brain. A good friend of mine did some research where he figured out the he- I think the paper was titled, um, well, forget what it's titled, but it's about what he found with the amygdala is that is it is a modulator of CO2 as well.","offset":643,"duration":38},{"text":"Brian MacKenzie: So for those of us that are a little bit more less emotionally developed, we tend to become more reactive and when we become more reactive our nervous system's a bit more hot, when our nervous system's hot, you can bet you'll become more CO2 intolerant, so meaning if Aaron got stressed out, which Aaron doesn't get too stressed out, but let's just pretend he did, and I said Aaron hold your breath versus if Aaron were calm, hold your breath.","offset":681,"duration":30},{"text":"Host: Yeah.","offset":711,"duration":0},{"text":"Brian MacKenzie: There would be two very different breath holds, CO2 being the main mechanism and driver for why you would need- feel the urge to breathe, right? You understand that pretty intimately. So that modulator gets involved with things especially for those of us that are wired up in certain ways or just are more reactive or talk a lot more or, uh, you know, are mouth breathers by nature, you end up retarding this process and then you become sensitive to its change because the nervous system's running pretty hot as a result.","offset":711,"duration":37},{"text":"Brian MacKenzie: Because it biochemically speaking you're moving the needle over to say, oh not enough o- not as much oxygen available, no problem, we'll move into more sympathetic survival mode, which provides more glucose, glycolysis, etc. So I just run up here on carbohydrate most of the day and I don't, you know, my mitochondria are not as functional, right, in terms of where I’d be util- and that doesn't just mean we're not using carbohydrate with mitochondria, etc. because we oxidize, right? We're just not oxidizing as much because we don't have that availability.","offset":748,"duration":40},{"text":"Brian MacKenzie: So the the system has a very easy long-term way of managing that. It just uses more glucose, right? And and it just happens quicker. It's not that we're not using oxygen, it's just you're not using it well. And so that state becomes chronic stress is what we see and that sensitized chronic stress, you could look at most people who deal with chronic stress have some form of chronic anxiety they're also dealing with or depression, which are same same just different modes of how you're operating with it. Without a doubt, we've seen that people are CO2 intolerant or more CO2 intolerant who are anxious.","offset":788,"duration":43},{"text":"Host: Could you say a little bit more about the relationship of the amygdala and the and CO2? Is that like a downstream effect because of upregulation of the amygdala is causing the nervous system and the respiratory system to go into more of like a hyperventilatory state, therefore the downstream effect is off-gassing CO2, or is it more intimately and closely related than that?","offset":831,"duration":22},{"text":"Brian MacKenzie: Yeah, correct. Yeah, it is that downstream side of things. Um, you know, however when I talk about, oh, you know, my run- my nervous system's now running hot, well you're a high-stress individual so now what you're doing is, you know, if we look at like HRV, your HRV's low, so the beats between the heartbeats aren't as far apart and, you know, your chemoreceptors are on alert because you're in a predictive system.","offset":853,"duration":29},{"text":"Brian MacKenzie: So you've got chemoreceptors off the aortic arch, the carotid arch, the the carotid artery. So you're talking about a predictive system and when you look at the predictive system, you then can get into free energy principle, which is, well yeah, everything's kind of off of a prediction that I've predicted how my day's going to go. I've gotten in a car to go somewhere, I don't predict there's going to be an accident so any sort of thing that gets in the way of that sets me off.","offset":882,"duration":26},{"text":"Brian MacKenzie: And if I'm somebody who gets set off really easy, that predictive system is a mess, right? Well, my- those chemoreceptors that are picking things up are now on a hot nervous system. So I'm in a nervous system that's set up on a high sympathetic drive to be on alert and not be able to manage things, so then I'm just more set cued up to be driven into reactive mode where I'm in that limbic system where I'm in that emotional system trying to validate the problems that I have by not looking at where they originated from, which is myself in most cases, 99.9 percent of the time, right? Accidents do happen, however...","offset":908,"duration":44},{"text":"Host: Yeah, that’s that's I think that's like the bridge between the mind-body conversation I think is really interesting and you know, I’m like the if there is some type of internal impression, you know, or trauma unprocessed aspect of yourself or event or experience within your life that could be like a a smoldering ember deep within your subconscious, you know, and you keep on addressing all of the smoke that's arising and you temporarily be like, oh cool I feel better because I did this breathing practice, I’m down-regulated temporarily. Or I did this psychedelic thing or I had sex or I had this dopaminergic response from you know whatever the thing is, I'm like ah I'm temporarily okay.","offset":952,"duration":37},{"text":"Host: But you haven't actually addressed the smoldering part. And then simultaneously, you can use the breathing tools tools in order to down-regulate the system enough to be able to develop clarity to actually do the work to assess the smoldering ember. Does that make sense? And then so just how do we- how do we do that? Because I think that's what we're trying to do.","offset":989,"duration":21},{"text":"Brian MacKenzie: Yeah, you know, I- I think fundamentally people have to start to look I mean here's what I've done and the people that I've worked with do, you know, a lot of them, um, is if you're not willing to look at your experiences a bit differently, meaning, yeah maybe that wasn't exactly how it went or maybe there's another way to look at this, you know, um, then you're you're pretty fucked, excuse my language.","offset":1010,"duration":29},{"text":"Host: Yeah, you’re just if you’re not- if you’re not willing to take yourself out of like a victim kind of mindset I think everything else is just like stasis.","offset":1039,"duration":6},{"text":"Brian MacKenzie: Yeah, you're like if you're just so cued up that you had this torturous childhood that, you know, maybe you did, however hate to be the bearer of bad news but you are a survivor, you are here now and you are listening and if you're listening to this you're on the internet, you're on something and you're living a pretty decent life. So you you can do it, I promise you. Um, I'm a bit more direct than most people with this stuff because I'm not a therapist and I'm like hey you're either going to address this or you're not and if you're not going to really start to address this and you continue down this path, the work we're doing isn't going to work.","offset":1045,"duration":38},{"text":"Brian MacKenzie: Because you cannot just apply breathing methods and hope you're going all the pain's going to go away. You're just become you're just using you're just using another addiction for something, just filling a void that isn't, you know, fillable.","offset":1083,"duration":16},{"text":"Host: What would be the because I think there are mechanical levers that a person could start to pull?","offset":1099,"duration":5},{"text":"Brian MacKenzie: Oh- 100 percent. Here's how I look at it. It's like hey, let's let's go over to that model like Steve Peters created. Let's let's just say I'm in this emotional state where I don't he created this model's brilliant, it's like if you don't like how you feel, if you don't like how you behaved or you don't like what you think, guess where you're at. You're inside that chimp. Okay? So if you've got anything going on there, that is the perfect opportunity to introduce some breathing of some sort to bring you down to a level to be able to calm down enough to say to yourself what is the truth or what is the reality about what it is I'm feeling right now.","offset":1104,"duration":43},{"text":"Brian MacKenzie: Is this person who cut me off in in traffic, were they out to get me or maybe they're just in a rush and I can let this go. I don't know, whatever your f- whatever you're dealing with, right? Like, you know, the deal that you were supposedly going to close for millions of dollars or, you know, the job you were going to get, I understand that that was, you know, that's difficult. But are you capable of lacing up your shoes tomorrow and going after something else and finding something else creative in your life in order to yeah, because you've made it this far. So yes you are.","offset":1147,"duration":28},{"text":"Brian MacKenzie: So if you can really look at that and go oh okay, but breathing’s the tool to kind of get you out of where you don't like what you're feeling and you know in that with what you said earlier it's like you know you got this victim side if you're ever the victim you're in the mod- you’re- you’re on the wrong side of the tracks, trust me.","offset":1175,"duration":23},{"text":"Host: I think you’re just in stasis. I think it’s I think victim and stasis are synonymous. It's fine, but just know that you will not grow from there. It's fine, just know that you're in a pause state for as long as you choose to be in that victim space. And it’s fine, be there for 20 years. It’s fine, just stay- stay put.","offset":1198,"duration":15},{"text":"Brian MacKenzie: Yeah, no big deal. It’s just nothing will change.","offset":1213,"duration":3},{"text":"Host: Yeah.","offset":1216,"duration":1},{"text":"Brian MacKenzie: So and- and I’m really good with my life and I’ve, you know, we just won't be close. We won't be having many conversations. Awesome.","offset":1217,"duration":9},{"text":"Host: Um yeah. So breathing something that I'm curious from your perspective and experience with in relation to breathing and mechanics, I feel like mechanics is something that's not spoken about that much. It's a lot about breathing practices and do a 5-7-8 or do a box breathing or do a Wim Hof or do a holotropic or do a this and there's I don't hear very much other than like postural restoration institute which is super complex and hard for any even super smart person to understand.","offset":1226,"duration":30},{"text":"Host: Um, you know, so within these conversations are there some aspects of the physical meat suit that you would recommend people be able to start to work on within themselves to be like oh actually just like you need to shift some things mechanically within your shoulders or your diaphragm or your pelvic floor or your tongue or your you know nasal passages, whatever. How do we start from from the mechanics of the physical body to be able to naturally breathe better?","offset":1256,"duration":30},{"text":"Brian MacKenzie: The the easiest way to do it without having me or you there for somebody is to really go you know go somewhere on YouTube and start to find you know look for some core exercises or go look at somebody like a Starrett who's going over movement principles. And like for for for complex movements like a squat or a hang or like a press, right? Like you're overhead with a press. Like here's something for people like you go and press overhead just take a 45-pound dumbbell or a- a bar, dumbbells are going to be far more challenging, right?","offset":1286,"duration":33},{"text":"Brian MacKenzie: But take a- take a bar and go overhead. Shut your mouth and go end to end nose-only breathing, right? You're going to start to figure out how how non-integrated your core actually is because or how much your diaphragm actually should is is integrated into the core complex. In fact, I'm of the mindset it is the epicenter of the core complex because the moment that diaphragm's out of place, the breathing gets very difficult, right? Maybe you don't start with a press overhead, maybe you go online, find some videos or some tutorials from some experts on movement standards for some complex movements, go get into those those positions, shut your mouth. Can you go end to end from your nose for 5 to 10 breaths and just hold that?","offset":1319,"duration":51},{"text":"Brian MacKenzie: That will tell you how you're set up with that diaphragm real quick and the intercostals per se. I don't want to leave the intercostals out because the intercostals and the diaphragm work together. It's not a separate thing, those two muscle groups work together um, to move that cage open. From there, it becomes secondary where you're talking about things, you know, pecs that come off, the neck muscles, etc., then things start to grab. You want to make sure that those those secondary muscles aren't first things to grab when you're doing these things.","offset":1370,"duration":40},{"text":"Brian MacKenzie: If they are the first things to when I breathe then we definitely want to address this and this is where it's like get into those positions and try that. You know, I go to the extremes of getting people with some resistance breathing devices that are fairly cheap and easy to get, um, to where we really train, you know, the strength of these things um, to challenge people. But we don't do a a ton of it. We do some of it as some auxiliary work and then it's like I move more into like breathing gear work with, you know, warm-up and and designed cardio or aerobic work that we implement the breathing gears into.","offset":1410,"duration":38},{"text":"Host: Um what would be the- I mean this might be kind of a a variable question, but what would be the ideal sequence of breathing through you know the ribcage and the torso and the whole chest cavity? If you were to start a breath, an inhalation from full evacuation, what should that look like? What are cues that we could be feeling into and how would that- how would that look in an ideal world?","offset":1448,"duration":26},{"text":"Brian MacKenzie: If this is the bottom of your ribcage, right, your ribs, this thing goes out like that. Most people are taught or hear their belly should move. You should feel the air into your back first. That doesn't mean the belly doesn't move, but we're talking the upper belly, not the lower belly. If the lower belly is what is coming out, you're dealing with pelvic dysfunction, pelvic floor dysfunction most likely.","offset":1474,"duration":38},{"text":"Brian MacKenzie: So I've run into a number of yogis who've practiced for years and taught that whole belly thing and literal- you know and and they're quite they have quite dysfunctional breathing patterns because they can't breathe into the ribcage. They're actually just breathing down, they're not expanding the cage, right? We want expansion horizontal and then that's where the vertical occurs, right?","offset":1512,"duration":26},{"text":"Brian MacKenzie: So it horizontally initiates and if I just put if I just sit if I just sit up with on my sit bones vertically in a chair with my back my back's not on and I put my hands around my lower ribs, I just want to organize down a little bit and then I and I feel those ribs move immediately out and into my back and then my belly ends up filling, right? That's the the upper part of my belly. So that's that's essentially where that happens and then from there it then becomes shoulders and and all that. But we're not you don't need to really train those secondary muscles, those are short-term muscles that are very glycolytic in nature, so those are those are for last resort type things.","offset":1538,"duration":50},{"text":"Host: And the the most common tendency for people would be for the ribs to have a tendency to flare and kind of be stuck in like external rotation. And to be able to come down and drop down towards the pelvis and drop into internal rotation on the exhalation is going to be very healing for creating support and stability for that respiratory diaphragm pelvic floor relationship slash the whole everything.","offset":1588,"duration":22},{"text":"Brian MacKenzie: Correct. Yeah, I mean that pelvic floor is so important and I think so many people miss that to where it's like, you know, if you're if you're really working on some breath control and core work, you should be pulling up. Like you should be you should be like it's like you're stopping yourself like you've got to go the bathroom real bad and you're pulling up and trying to stop that. That should be engaged as you're breathing, especially on that exhale.","offset":1610,"duration":28},{"text":"Brian MacKenzie: Now, that shouldn't be something you're walking around all day thinking about, right? Because if you've done the work, those muscles naturally should remain engaged then when they should be.","offset":1638,"duration":16},{"text":"Host: It’s kind of like healthy healthy tone, not be excessively flaccid or hypertone either. Be like dynamic. It’s interesting the idea of so the, you know, your whole body's a closed hydraulic system and so if you think of the diaphragm descending to expand open, create a vacuum in the lungs to pull air in, the pelvic floor needs to also be able to expand and relax. And so going through that that relationship of as I inhale, there needs to be an opening through my abdomen and my lower back and my pelvic floor to be able to actually allow the space for my diaphragm to function. Like there could be dysfunction because of inhibition or rigidity within my pelvis, which is interesting I think to start to bring- it’s like oh I need to breathe into my cock. Cool. I didn’t think about that.","offset":1654,"duration":55},{"text":"Brian MacKenzie: Yeah. Most people aren’t engaged down there in the wrong way. It’s just it is what it is, but I mean that's part of it. So mechanically speaking, you know, you kind of want to dial that in a little bit every day or, you know, whenever you go train, like that's just kind of like starting, you know, with some stuff, like do a few exercises that revolve around that. Once you get it dialed, that stuff can get a little bit more extreme. Like I I do I'll do some hard some hardcore like kind of neck training stuff that involves the whole core, but like I've got a resistance breathing device in and I'm going end to end with that for a couple of sets to get that strengthened but also to get it activated so that when like I go squat or deadlift, I’m not doing that shit, I’m just squatting and deadlifting because it’s now integrated and it’s a part of the process.","offset":1709,"duration":52},{"text":"Host: What resistance breathing devices would you recommend for someone? Is a straw enough or like what should...","offset":1761,"duration":5},{"text":"Brian MacKenzie: I I would just get um, I mean I can here I can tell you and it's actually really cheap, very cheap, I mean I send this to everybody...","offset":1766,"duration":8},{"text":"Host: It’s like one of those little like snorkel snorkel mouse things with a little little turny doodad valve on it.","offset":1774,"duration":7},{"text":"Brian MacKenzie: Correct. Yeah, I have one of those too, I like it.","offset":1781,"duration":2},{"text":"Host: It gets all slobbery though, that’s the only thing I don’t like about it.","offset":1783,"duration":2},{"text":"Brian MacKenzie: It does, but like it's yours, man. Like you wash it out with water every time. Portable respiratory muscle trainer on Amazon.","offset":1785,"duration":11},{"text":"Host: Yeah, that’s the same thing I think, it’s like 13 bucks or something like that.","offset":1796,"duration":3},{"text":"Brian MacKenzie: Yeah. Yeah and so- I buy like 20 of them at a time and then I just give them to clients as they come in and stuff.","offset":1799,"duration":9},{"text":"Host: Yeah those tools are great because it it creates feedback and resistance to be able to actually have to really actively engage those muscles, the respiratory muscles. And you'll see people's neck start to grab and you're like dude, no, no, no.","offset":1808,"duration":12},{"text":"Host: So I have a question for you with that. With using the respiratory tool like that, would it be is it okay that you are now practicing mouth breathing for one thing, um, and is it more efficacious or does it matter to emphasize the exhalation or the inhalation if you're using resistance for your breath?","offset":1820,"duration":22},{"text":"Brian MacKenzie: So in- in with respects to this is causing more resistance than what the nose does. So that's why I'm actually using it, it's strength training. So I'm actually doing some strength training I'm looking at it like lifting weights for the primary breathing muscles um, and getting the core integrated into that. Um, that is all we're doing with that. I will sometimes include it into cardio warm-ups where we go resistance breathing device, you go end to end one- one to three breaths at the top of every minute and then you go right back into nose breathing and the nose breathing feels like mouth breathing.","offset":1842,"duration":43},{"text":"Brian MacKenzie: So it's a very easy, well-orchestrated path to kind of not only getting warmed up and getting the pulmonary system integrated with everything, but I'm getting my breathing really ready to go for whatever sort of intense work I might be doing, which is something most people are never thinking about or doing.","offset":1885,"duration":26},{"text":"Host: And something probably for people to think about if they are using a a resistance tool like that or just using the natural resistance of just, you know, breathing in general, uh, would be paying attention to the alignment of your ribs and your pelvis and all of that. Because it's kind of like if you're doing, you know, kegel exercises but you're practicing clenching your- your kegels um from a a quote unquote like dysfunctional position, you're just um downloading or pressing save on a dysfunctional file. And so if you're doing these resistance exercises, it would probably also be wise to be paying attention to orientation of the ribs and all the other different parts. Is there any specific cues you would provide for a client or yourself as far as rib orientation or body orientation when they're going through a a resistance breathing exercise?","offset":1911,"duration":53},{"text":"Brian MacKenzie: They they will typically because my clients are typically all over the work- they're all over the place. So I'll they'll get videos of how to do a specific exercise then they're actually given, hey, I want you to go end to end three breaths with this device in that position. And they supply me with the feedback on that type of stuff. So hey, was that how hard you know, what was going on? Um, if somebody comes to see me and I work with them, I'm actually my hands are on them and I'm showing them exactly what's going on, um, you know, but for- you know I don't I try to keep it as dumbed down basic as possible meaning I don't try and talk over their head about mechanics, I try and just go no let's see this position, now show me your breathing. And they like fill up. And they're like holy crap, you know, and it's like yeah, you couldn't fill up before.","offset":1964,"duration":57},{"text":"Host: I like the I don’t know if this is Belisa Vranich’s language or not, but I got it from her of like the horizontal versus vertical breathing.","offset":2021,"duration":7},{"text":"Brian MacKenzie: Yes, that is- yeah. That yeah, that is Belisa's. She’s...","offset":2028,"duration":5},{"text":"Host: And so something like really simple would just be like allow your ribs to kind of descend a little bit, like relax, like relax in yourself and then bring your hands on the sides of the ribs and feel that breath starting to move horizontally. And then you could also put your hands in your lower back, which I don't know if Belisa recommends this as well, but I do. Um and feel that breath going into your back and that’s going to naturally place the ribs into a more natural healthy kind of like cylindrical orientation to be able to create better pressure and then maybe stack the the breathing on top of that. I think would be maybe a potential you know horizontal breathing with that. Yeah. And then with with and then with something that's very common with people is nasal restrictions. Do you have any recommendation for that? So we- so we've got resistance, we're starting to turn on the respiratory muscles, we're starting to align and organize the diaphragm and all that stuff, but we still are bunched up and we actually can't get breath through the nose.","offset":2033,"duration":56},{"text":"Brian MacKenzie: Yeah, I uh go spend one month focused on not going outside of a gear one, which is you know an equal in and out nose-only breathing where it's greater than 4 seconds in length, so like a two in two out, two seconds out, two seconds in, two seconds out. So your breath rate your respiration rate is below 20 breaths per minute, right? Go only do that for a month no matter what. So toggle down the intensity of whatever you're doing if it pushes you beyond that, right? Do that for a month, then if your nose is still an issue, go see an ENT and get that thing- thing cleaned out.","offset":2089,"duration":47},{"text":"Host: Why a month? What happens during that time frame? and would you recommend mouth taping during that time frame for any activities at all?","offset":2136,"duration":10},{"text":"Brian MacKenzie: No. I don't like mouth taping because it just- it kind of- it changes the the level of commitment. It's like oh I'm just going to put this tape on so I don't open my mouth. No, you- you really should be learning to kind of wire that up mind and body a bit. Um the big thing is adaptation. What sort of- like for if you look at my nose...","offset":2146,"duration":27},{"text":"Host: You got- you got a little lopsided there, bro.","offset":2173,"duration":3},{"text":"Brian MacKenzie: Yeah, I'm very lopsided.","offset":2176,"duration":2},{"text":"Host: I think mine’s lopsided too.","offset":2178,"duration":1},{"text":"Brian MacKenzie: Yeah you’re not too bad. Regardless, I can operate in a gear one up to about 140 heart rate, which is just touching zone four for if we're talking about cardiovascular, right? Like so like that and beyond that I then switch into a gear four which is easy mouth breathing because that's where that should happen because now we have a whole community of people who bought into this nose breathing thing and thinking that it's the be all end all. It is not. I've- I've tested a lot of people, they retard things in the opposite direction because now you're not getting enough oxygen when you go above moderate efforts of exercise.","offset":2179,"duration":53},{"text":"Brian MacKenzie: So now you're not actually onboarding enough oxygen for use. So ventilation goes up, right? So depth and rate change for very good reason. But easy mouth breathing gear four is just and because you've been rewiring things for a month, when you do switch out when you do go up to that you now are primed and designed to really be using those primary breathing muscles still.","offset":2232,"duration":27},{"text":"Brian MacKenzie: You don't need to bring on where most people who have not done any sort of training with these with their with their breathing muscles are tend to have I mean I can- the amount of runners I watch and see that are just like breathing here, stiff upper, you know, their neck is stiff, all of it. They don't they only have access to the upper chest for breathing. They're missing huge huge opportunity and the huge opportunity from what I've been seeing with testing, I mean I I see between 20 and 60 percent changes in VO2 Max with most of the people that come to me. And I have seen some elite athletes.","offset":2259,"duration":46},{"text":"Host: Could you outline the gear system of breathing quickly? Because I think it's a a great model for people to to have.","offset":2305,"duration":7},{"text":"Brian MacKenzie: Yeah. Gear one is easily is is easy nasal breathing, but it's also, you know, it's controlled, it's it's greater than 4 seconds in length, right? So two like just think of it as two in two out. Gear two is power nose breathing. Gear two is very limited because we will skip gear three, which is transitional, that's usually transitional gearing down, but I'll sometimes use that to train people just for some just training purposes.","offset":2312,"duration":35},{"text":"Brian MacKenzie: However, it's a gear it's a transitional gear for gearing down, so so don't think of gear three right now. We go gear two, gear four, which is... into gear five... So anything above roughly a 30 respiration rate with mouth breathing is gear five. Gear four is between 20 and 30 breaths a minute. Um, gear three comes in when I go from working hard into I now shut it off and now I'm... nose in, mouth out. And you will see recovery happen pretty quickly by doing that and you could also reverse that but then you move that air with that transitional gear and as soon as you feel a change then you drop into a gear one.","offset":2347,"duration":70},{"text":"Host: And how does that work that when you are in say gear five because you are in higher respiratory demand, being in that gear too much or just breathing that way in general or mouth breathing, you're off-gassing more CO2 and alla Bohr Effect, you're increasing alkalinity, decreasing acidity and you are causing your hemoglobin to become change shape and become more stingy with the release of oxygen while simultaneously you need more oxygen in that moment.","offset":2417,"duration":33},{"text":"Brian MacKenzie: You you can overbreathe at moderate to lower to low-high intensity efforts, meaning like heart rate zone four and below, you can overbreathe in. Like heart rate zone you're 90 percent and above, you really can't overbreathe, although there are compensations that I've seen and picked up on where people are breathing at like a 60 respiration rate but they're at like 70 percent tidal volume. So you're in an obvious compensation at that point where you can't hit tidal volume, you know, because you're so stressed.","offset":2450,"duration":34},{"text":"Host: Can you define tidal volume?","offset":2484,"duration":2},{"text":"Brian MacKenzie: Yeah. The depth at which so how much air you can act- how much air you can fill your lungs with. You'll still you will see people hit some tidal volume in like a gear two, gear one, so they'll hit in range, but they're not needing to move that very fast, right? Well, if I'm moving up into a gear five and I can't go all the way in, so that just means I'm going short and short-change breathing, I'm just going... versus... Right? You don't need to necessarily hit end to you know bottom end, but if you can't hit that top end, there's a problem. Your alveolar sacs are most sensitive at end ranges. So you're getting to you're getting best diffusion off of CO2 and O2 at those end ranges.","offset":2486,"duration":46},{"text":"Brian MacKenzie: There's a there is a genetic reason for that. If I'm in fight or flight and I'm hauling ass and I'm moving, I got to be able to move air and get real good air.","offset":2532,"duration":15},{"text":"Host: How interesting, your alveolar sacs are more sensitive during end ranges, so full exhalation full inhalation you're going to have more sensitivity within- is that- is that kind of like the the physiological sigh kind of thing where it kind of like lifts them off of themselves from collapse?","offset":2547,"duration":16},{"text":"Brian MacKenzie: Yeah and yet none of that is necessary if I'm calm. So I can just be but you can't see that I'm breathing, that that's, you know, when you get back to normal breathing, normal breathing should be I can't tell that fool's breathing.","offset":2563,"duration":16},{"text":"Host: Yeah. Like the samurai breath or what- what people call it. Um I was doing the I know you have relationship with Laird Hamilton I was doing the the pool training stuff uh out at his place maybe I don't know whatever last summer. And the one of the things that stood out to me as we're dunking up and down uh that he said that has continued to stand out and been something that I've like I've continued to perpetuate with myself is that it's not about the inhale, it's about the exhale. And that was like a download that he got from I don't know who somebody else and that was one of the things like when we come up out of the pool it was like getting a full evacuation to get all of that air out to be able to get replenished with a like a you know a a more robust inhalation or a richer inhalation. Do you think that there's something to that? What are your thoughts of the value of of exhalation?","offset":2579,"duration":56},{"text":"Brian MacKenzie: In in certain instance in certain instances, yes, right? In certain instances, yes. I don't think you need to dump all your air all the time. Um in fact, I I mean I'm on a bike or I'm on a you know I'm running and I'm I'm I'm literally research I'm studying the stuff I'm doing, I'm paying attention to where is the change happening. And I've got like a metabolic cart on, right? And I've got and I'm watching tissue saturation. I'm watching this stuff as it's occurring and dumping the air while exercising all the time is not necessarily the best like trying to get rid of that, that's just wasted time. You're going to actually move you're moving air fast, air doesn't just sit while I'm moving air like this, right?","offset":2635,"duration":45},{"text":"Brian MacKenzie: But in instances like with Laird in the pool or Laird in big surf, yeah you want to be getting rid of your air before you go to take a full inhale because you're going to need all the fresh air you can get in order to be down for two or three minutes while you're getting rolled, right? Like so in Laird's training to be clear is is genius in that this this maniac discover- figured out how to kind of push those limits of CO2 and pressure and force control of breathing in a pool environment. So I mean it- he's a genius like that. I mean he's an innovator, the guy is an innovator. That's what he does.","offset":2680,"duration":46},{"text":"Host: Are there so we we can wrap up here do you have like a hard out you got to get out of here like...","offset":2726,"duration":5},{"text":"Brian MacKenzie: Yeah I do I have a yeah I definitely have a hard out in like 5 minutes.","offset":2731,"duration":4},{"text":"Host: All right, cool. Sweet. Um I so in wrapping things up, uh are is there anything that you see standing out in the in the breathing world that you feel is maligned or off that you would like to see rectified or shifted?","offset":2735,"duration":22},{"text":"Brian MacKenzie: Oh, I stay away from the breathing world. Most of it's hogwash.","offset":2757,"duration":10},{"text":"Host: So what's- what would you say is hogwash in the in the breathing education space?","offset":2767,"duration":5},{"text":"Brian MacKenzie: Uh I I would say most people are getting lost and stuck to a methodology versus understanding respiratory physiology and physiology in general, you know, and and even mechanics, you know, you went into a deep dive with mechanics here. Most of these methodologies and things don't even touch that, right? Because they don't want to because they've got this cool little toy that can change somebody's state and that's really all anybody's interested in. They'll just keep breathing people and doing this with people without actually, you know, going well you're still doing the same shit.","offset":2772,"duration":41},{"text":"Brian MacKenzie: Like hey, for me with what I do with clients is I'm looking to kind of help these people who I mean I'm dealing with professional athletes and like executives working at very very high levels, so managing multiple companies things like that where I do a full run down of like how they manage stress, how they respond to s- an exhale assessment CO2, and then how they respond to a metabolic assessment that I'm looking at tissue saturation, oxygen to the brain, etc. I'm looking at all this stuff so that I can go, hey what you're doing throughout the day we need to figure out some off points because you're not managing stress here very well.","offset":2813,"duration":42},{"text":"Brian MacKenzie: Like I I run people through an assessment that is very um boring to start. They're doing they're doing low-low effort work on a metabolic cart that just goes up a a smidge every five minutes and they're like bored out of their mind and it's everything I need to see because the thing one of the things that changes that really that is that stress thing we started kind of with this is CO2. Is CO2 changes that respiratory drive it changes how things are going on in the body and if I've got somebody we'll just use this as one case because we've talked about it, if I've got somebody who overbreathes a little bit I see that in the tissue. I see that even though the metabolic cart is saying oh he's aerobic right now, or he's utilizing fat. But yet his tissue and his brain are not getting oxygen very well.","offset":2855,"duration":51},{"text":"Host: What would be the metabolic test that that you would suggest someone uh goes through, say from from home? Is there are they going to need fancy gadgets and devices and such or what would be your suggestion?","offset":2906,"duration":12},{"text":"Brian MacKenzie: There so there is actually it's gotten better and I'm supposed to get my third version of this one, but I got a buddy of mine at Duke who's really like I swear this version of it is badass. It's called Caliber, it's spelled C-A-L-B... C-A-L-I-B-R-E, so it's English Caliber, Caliber Biometrics. They've got a $400 uh metabolic cart that's pretty badass.","offset":2918,"duration":25},{"text":"Host: Okay. I’ll look it up.","offset":2943,"duration":2},{"text":"Brian MacKenzie: Um, and- and it's a pretty easy to use with their app um, but it'll give you some pretty good numbers. But if you really want the whole shebang, you're going to want either a MOXY or a Train Red Near-Infrared, but you know it takes time to kind of understand what you're do- I’ve kind of pioneered a way to look at this and look at clientele with this stuff that come to me because I mean I can get some of the high- the highest level players in the world in a sport and I can see a limiter that somebody else wasn't picking up because they just did a traditional VO2 Max test which is just like you start at nothing and you go to everything within like eight minutes. And I'm taking like 30 minutes to get to that to a point to where I might have them work really hard for three minutes, right?","offset":2945,"duration":47},{"text":"Brian MacKenzie: Needless to say, my point here is that most of what I'm seeing if people go and address how they're looking at how they manage their daily life, like the stress of their life, and then they start to implement tools around that in order to bring themselves into reality, breathing has a very potent impact in that, especially when we apply it to exercise and you decide to stop being a reactive, you know, SOB to everything or victimizing yourself to everything, that is where breathing has a very very potent deal. And I've had I've had um an entire C-suite at one point thank me as a client walked out of the room, who was you know the owner of the company, and they literally were like thank you with what for what you're doing this this like over the last three years this dude this dude has changed so much, like he's calmed down in a level to where he's not as reactive and not this tyrant, right?","offset":2992,"duration":60},{"text":"Host: Like he’s- he’s regulated. Um I so I appreciate you saying the thing that you'd want to change is the lack of emphasis on mechanics and a lack of emphasis on principles around respiratory physiology and understanding like how to how to kind of drive the boat as opposed to just having some specific exercises because I created a program that's not out yet but it's all founded on first mechanics and then the principles of down-regulation and up-regulation and then a section on anatomy and physiology of just like what you ought to know to have a visualization of what's happening. So I’ll include that for people listening in the intro- the link for that for like we’ll have like a free trial and all that stuff. And so I'm very glad that that's the exact thing because I'm like I agree. That’s why I made something.","offset":3052,"duration":46},{"text":"Brian MacKenzie: Exactly. I’m like yeah I’m off- I’m in my own world doing my own thing, I'm like I'm good man I don't want to like the whole breath space it got so I was just like no I'm out, everybody's into their own little methodology of some sort.","offset":3098,"duration":14},{"text":"Host: Yeah, I’m not into methodologies. Principles, learn principles. What do you need to know as far from a principle-based understanding and then from there you can apply the principles on whatever methodology but actually understand the intrinsics of the methodology as opposed to being lost in the methodology. Um, thanks so much man, I really appreciate these conversations. Um where if people want to I know that you do various different things you actually actually work with with coaching clients you have all sorts of things...","offset":3112,"duration":29},{"text":"Brian MacKenzie: We we have a membership website people can jump on we're not exactly very active with that. I have some coaches that help run that with for me, but what I do is very personalized, um it requires high high um commitment level uh meaning life and financially for people to invest in. Um it's not a a short-order process, but if people really are interested and think that they want to you know test that, more than welcome to jump in, go to shiftadapt.com and just go through the website, they'll they'll find everything there.","offset":3141,"duration":37},{"text":"Host: Amazing. Cool. Um thanks so much I appreciate you...","offset":3178,"duration":3},{"text":"Brian MacKenzie: Very easy, uh I I love you dude you are such a cool soul.","offset":3181,"duration":4},{"text":"Host: I love you more I appreciate you man. All right that’s it that’s all thank you for tuning in I’ll see you next week.","offset":3185,"duration":15}],"logs":[{"elapsed":"0.0","message":"Downloading audio from YouTube...","detail":null},{"elapsed":"0.0","message":"Trying download with browser cookies (ad-free)...","detail":null},{"elapsed":"2.9","message":"⚠ Cookie download failed: WARNING: [youtube] [jsc] Error solving n challenge request using \"deno\" provider: Error running deno process (returncode: 1): \u001b[0m\u001b[1m\u001b[31merror\u001b[0m: Uncaught (in promise) TypeError: Cannot read prope","detail":null},{"elapsed":"2.9","message":"Retrying without cookies...","detail":null},{"elapsed":"26.5","message":"⚠ Downloaded without cookies — audio may contain ads","detail":null},{"elapsed":"26.5","message":"Audio downloaded (31.7 MB) in 26.5s","detail":"File size: 31.7 MB"},{"elapsed":"26.5","message":"Video title: How to Breathe Better for Peak Performance | Brian MacKenzie | Align Podcast #527","detail":null},{"elapsed":"26.6","message":"Audio duration: 53:15 (53.3 min)","detail":null},{"elapsed":"26.6","message":"Uploading audio to Gemini File API...","detail":null},{"elapsed":"30.3","message":"Audio uploaded in 3.8s","detail":"File ref: files/53gb8lo4p30m"},{"elapsed":"30.3","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"110.7","message":"Transcription complete in 84.2s","detail":"51198 chars received"},{"elapsed":"110.7","message":"Transcription tokens: 80,125 in / 12,837 out — cost: $0.0786","detail":null},{"elapsed":"110.8","message":"Parsed 129 transcript segments","detail":null},{"elapsed":"110.8","message":"Transcript coverage: 53:05 of 53:15 (100%) — OK","detail":null},{"elapsed":"110.8","message":"Total transcription time: 84.2s — 129 segments","detail":null},{"elapsed":"110.8","message":"Analyzing topics across 129 segments with gemini-3.1-pro-preview...","detail":null},{"elapsed":"153.2","message":"Topic analysis complete in 42.4s — found 10 topics","detail":null},{"elapsed":"153.2","message":"Analysis tokens: 13,554 in / 921 out / 3,883 thinking — cost: $0.0848","detail":null},{"elapsed":"153.2","message":"Pipeline finished in 153.2s — total cost: $0.1633 (111,320 tokens)","detail":null}]} \ No newline at end of file diff --git a/history/1774289546791-rngx_PsPxkg.json b/history/1774289546791-rngx_PsPxkg.json new file mode 100644 index 0000000..c419a23 --- /dev/null +++ b/history/1774289546791-rngx_PsPxkg.json @@ -0,0 +1 @@ +{"id":"1774289546791-rngx_PsPxkg","videoId":"rngx_PsPxkg","url":"https://www.youtube.com/watch?v=rngx_PsPxkg","title":"The Best Week For Bitcoin Nobody Is Talking About","type":"youtube","topicCount":7,"segmentCount":87,"createdAt":"2026-03-23T18:12:26.791Z","uploadDate":"20260318","chunks":[{"title":"Introduction to Positive News","summary":"The host introduces the episode, acknowledging ongoing global chaos but choosing to focus on positive developments related to Bitcoin and United States progression.","entries":[{"text":"Host: 'Sup freaks and Happy St. Paddy's Day. Probably getting this the day after, but I wanted to say it anyway. Top of the morning to you. War in Iran raging on. We have the counterintelligence chief resigning today. It's chaos out there.","offset":0,"duration":13},{"text":"There's a ton of people covering that stuff. Today, I wanted to focus on positive stuff as it pertains to Bitcoin and progression here in the United States.","offset":13,"duration":9},{"text":"I'm Marty Bent, founder of TFTC, been doing this for nine years. Managing Partner at 10:31, investing in Bitcoin infrastructure, been doing that for five years.","offset":22,"duration":10},{"text":"Been around the block, seen a lot of things, and believe that Bitcoin is one of the most powerful technologies that we have at our fingertips right now. And if you look out there, things are looking up for Bitcoin.","offset":32,"duration":14}],"startTime":0},{"title":"Square Auto-Enables Bitcoin Payments","summary":"Square has updated its terms of service to automatically enable Bitcoin payments for millions of eligible sellers by the end of the month, facilitating seamless transactions for those living on a Bitcoin standard.","entries":[{"text":"We've got Square, we'll start there. Our boy Nick Slany from Money Dev Kit, he was on the TFTC podcast a couple of months ago and if you're building with AI tools and you need them to have Bitcoin wallets, go check out Money Dev Kit to do that.","offset":46,"duration":17},{"text":"But he highlighted something here, maybe known where to look, being an ex-Square employee, but he said huge news coming through if you know where to look. We are going to win. Yes, we are, Nick. We are going to win.","offset":63,"duration":12},{"text":"But essentially, he's highlighting a change of service to the Square point-of-sale terminals where they've updated Square Bitcoin Terms of Service which is going to become effective at the end of this month, March 30th, 2026.","offset":75,"duration":16},{"text":"They are auto-enabling Square Bitcoin payments for all eligible sellers and so no longer will you have to be tasked with going to a Square merchant in your neighborhood and convincing them to turn on Bitcoin payments.","offset":91,"duration":14},{"text":"Square is enabling them automatically for all eligible sellers. So that should mean that millions of sellers will be able to accept Bitcoin as payment as of the end of this month.","offset":105,"duration":12},{"text":"So that's pretty massive. If you're a Bitcoiner living on a Bitcoin standard and you would like to spend Bitcoin wherever you shop, particularly via Square point-of-sale terminals, if you're going throughout your day and a lot of the merchants that you interact with are running Square, as of the end of the month, you should be able to pay in Bitcoin.","offset":117,"duration":21},{"text":"Don't know the exact details, but I assume that the auto-enable feature is not going to have it so the merchants are holding Bitcoin automatically. What I assume is happening is that you'll simply be able to pay. They'll be able to hit the \"Pay in Bitcoin\" button on the back-end of their terminal and then it will present a Bitcoin invoice that you can pay via QR code or NFC and you'll be able to pay in Bitcoin.","offset":138,"duration":23},{"text":"And the merchant will reap the benefits of saving on the interchange fees and then the Bitcoin will be auto-converted to dollars on the back-end that will sit in their Square account. Again, this is an assumption.","offset":161,"duration":13},{"text":"I'm assuming that this is how they're going to roll it out. Everything that Square has done up to this point seems like a bridge stepping stone towards a Bitcoin standard. And I think it would be a long shot for them to take the assumption that every merchant with this enabled wants to hold Bitcoin.","offset":174,"duration":17},{"text":"However, it's big for people like myself living on a Bitcoin standard. Instead of selling Bitcoin for cash and just paying with a card, you want to hold your cash reserves in the best cash ever, digital cash, Bitcoin, and you simply want to pay for things as you go about your day.","offset":191,"duration":15},{"text":"You should be able to do that by the end of the month and the merchant, unbeknownst to them, I assume most of them will not be aware of this, but they will be saving on the interchange fees per transaction of their customers paying in Bitcoin. It's a beautiful thing. It's great to see. Very bullish, as Nick said.","offset":206,"duration":19}],"startTime":46},{"title":"CFTC Protects Self-Custodial Wallets","summary":"The CFTC issued a no-action letter to Phantom Wallet, clarifying that developers of self-custodial software do not need to register as brokers as long as they do not custody user funds. The host connects this to the broader fight for open-source developer rights.","entries":[{"text":"I will reiterate: we are going to win. Things are chaotic out there right now, but let's focus on the positive sides. Next up, big news from the CFTC today.","offset":225,"duration":12},{"text":"The team at Phantom Wallet, which for those of you in Bitcoin who are unaware, Phantom Wallet, from what I understand, is a big Solana wallet that enables self-custodial properties for shitcoins, for lack of a better term, Solana and tokens being spun up there.","offset":237,"duration":15},{"text":"I believe they petitioned, or asked for a letter of clarity from the CFTC, and the CFTC got back to them today and told them that self-custodial wallet developers don't need to register as brokers.","offset":252,"duration":13},{"text":"So Phantom Wallet received a no-action letter stating that the CFTC will not pursue enforcement against self-custodial wallet developers who connect users to regulated trading venues as long as they don't custody user funds.","offset":265,"duration":14},{"text":"First time the agency has formally drawn that line. Again, here's why that's massive: under existing US law, any entity that solicits or facilitates derivatives trading typically must register as an introducing broker with the CFTC.","offset":279,"duration":15},{"text":"That rule was written for traditional financial intermediaries, but as self-custodial wallets started integrating across derivatives markets, developers faced a legal gray area that could have classified them as unregistered brokers simply for writing software.","offset":294,"duration":16},{"text":"The CFTC position, the CFTC's position was: if your wallet software connects users to properly registered futures commission merchants, introducing brokers, or designated contract markets, and you don't custody user funds, you are not a broker, you are a software provider.","offset":310,"duration":17},{"text":"Timing is not coincidental. One week ago, CFTC Chairman Mike Selig said at FIA's Boca Raton conference: for too long there's been an open question as to whether software providers trigger the CFTC's registration requirements. We intend to address the question head-on.","offset":327,"duration":19},{"text":"Seven days later, they did. So this is massive. I mean, I don't think it's all-encompassing for all software developers. I think this is just any that may fall under the purview of CFTC regulation.","offset":346,"duration":12},{"text":"But it is great to see a US regulator stepping up and saying, \"Hey, we recognize that we are entering into a new world, particularly at the intersection of technology and financial services.\"","offset":358,"duration":13},{"text":"The technology that was unleashed with Bitcoin enables you to truly custody your own wealth using open-source software and wallet software that gives you full control over your funds as you're holding them.","offset":371,"duration":12},{"text":"And for many years, but more particularly over the last two years, as open-source software developers connected to Samurai Wallet and Tornado Cash, the open-source wallet developers writing, building those wallets, either were thrown in jail or are on trial to go to jail for providing free and open-source wallet software that just so happened to provide privacy benefits for individuals.","offset":383,"duration":25},{"text":"So it's good to see the Trump administration moving in the right direction as it pertains to self-custody of Bitcoin and other crypto assets. Hopefully this becomes broad brush and applies to everything.","offset":408,"duration":13},{"text":"We still need to free Samurai, Roman Storm. The SDNY and the DOJ seems to be on a witch hunt after him specifically. Looks like he will have a retrial later this year as of right now.","offset":421,"duration":13},{"text":"And I believe Samurai Wallet developers, Keonne Rodriguez and William Hill, need to be pardoned. And the DOJ needs to drop the case on Roman Storm.","offset":434,"duration":9},{"text":"And so hopefully they see what the CFTC has done, the people at the DOJ look at the CFTC saying, \"Hey, this is free and open-source software, developers who make this don't need to worry, you don't need to register, you are not responsible for what your end-users do with that open-source software tool.\"","offset":443,"duration":21},{"text":"Hopefully it becomes more popular, but again, incredible to see positive development, bullish news, and something that has been long-awaited. So shout out to CFTC Chairman Mike Selig and others who came out and made this no-action letter.","offset":464,"duration":16},{"text":"Big day, big day. It's getting swept under the rug of all the news pertaining to the Iran-Israel right now. So I wanted to make sure we highlight that that's on your radar.","offset":480,"duration":12}],"startTime":225},{"title":"Oklo's Nuclear and Isotope Approvals","summary":"Oklo received crucial regulatory approvals from the DOE and NRC to advance their small modular reactors (SMRs) and begin domestic isotope production. The host discusses how this technology intersects with Bitcoin mining and medical supply chains.","entries":[{"text":"Another thing, I've been talking about this for years, as many of you know. If you've been around for a while, I have been heavily involved in the Bitcoin mining industry since 2018.","offset":492,"duration":12},{"text":"I am fascinated by this intersection of energy and Bitcoin mining. I think Bitcoin mining as a buyer of first and last resort for energy sources across the spectrum, anywhere from my- my plug here in the corner where I could put a bitaxe, to a multi-gigawatt facility participating in demand response.","offset":504,"duration":19},{"text":"There are arbitrage, energy arbitrage plays that Bitcoin mining can fit into to help level out demand and increase revenue and profitability for energy providers in many different flavors, whether that's an energy generation facility, a utility company, a substation, whatever it may be.","offset":523,"duration":21},{"text":"Off-grid, stranded oil and gas wells, like Bitcoin mining plays perfectly here. And one topic in the energy sector that I've been fascinated with and waiting for for the last eight years is the proliferation of small modular reactors, small modular nuclear reactors.","offset":544,"duration":19},{"text":"And a company I've been following, I believe since 2019, 2020 is Oklo. And today, Oklo got some good news. They've been trying to get the regulatory red tape cut off so that they can go do what they need to do to begin implementing and integrating their small modular reactor technology across the country.","offset":563,"duration":21},{"text":"And today, the Nuclear Regulatory Commission came out and gave them their first go-ahead. And so actually, I don't want to show this first. We will show this message from Stefan.","offset":584,"duration":27},{"text":"So Oklo announces that the US Department of Energy approval for nuclear safety design agreement of Aurora Powerhouse at Idaho National Laboratory has been approved.","offset":611,"duration":13},{"text":"This is an acronym word salad for folks not versed in DOE STD-1271. Oklo has signed an other transaction agreement with the DOE to initiate their Aurora reactor design and development project.","offset":624,"duration":14},{"text":"They're currently deploying their reactor at INL under the DOE's Reactor Pilot Program. Signing an OTA is the first step and enables the discussion and planning to start. Oklo says they also signed a nuclear safety design agreement.","offset":638,"duration":14},{"text":"The purpose of the NSDA is to gain agreement on design requirements, safety analysis approach, regulatory engagement process, applicable regulatory requirements, and to identify the key safety decisions for the design.","offset":652,"duration":14},{"text":"Oklo has requested immediate review of the preliminary documented safety analysis or PDSA to progress the project further. The purpose of the PDSA is to provide a comprehensive and preliminary assessment of the safety aspects of nuclear facility or activity.","offset":666,"duration":17},{"text":"Normally done when design is at least 50% complete. Very big accomplishment by the Oklo team. And as you can see here, you have the different phases of going through the approval process to get new nuclear generation approved in the United States.","offset":683,"duration":13},{"text":"It's been decades and nuclear energy is the most reliable, cleanest, and sustainable- sustainable in the form of profitable and manageable energy out there.","offset":696,"duration":12},{"text":"And I think it's been- the US has done itself a great disservice by throwing up a regulatory regime that has made it almost impossible to bring new nuclear generation facilities to market.","offset":708,"duration":12},{"text":"It seems like under Chris Wright and the current Department of Energy they are looking to reverse course there and make sure that the US leads on nuclear power generation, particularly with small modular reactors.","offset":720,"duration":13},{"text":"And so I don't think Oklo's going to be setting down an SMR tomorrow, but we're making material progress in unleashing the small modular reactor industry to be able to go do their thing.","offset":733,"duration":13},{"text":"Beautiful to see. Bitcoin miners I think will have a role to play here, particularly if you're going to rural areas to provide electricity in areas where something like a diesel generator is the main source of energy right now.","offset":746,"duration":14},{"text":"You want to replace that with cleaner, more reliable energy. SMRs are perfect. The problem that these SMRs are going to run into is that they'll be able to plop down, but there will be a period of time between when they plop down and when they have a grid interconnect and transmission lines built to the local grid system they're looking to serve.","offset":760,"duration":19},{"text":"And so you have this economic problem where you've spent a lot of capital and CAPEX up front to build the SMR, you plop it down, and then you have a period of time where it's just sitting there doing nothing.","offset":779,"duration":11},{"text":"This is where Bitcoin miners come in. They could sit behind the meter and while grid interconnect and transmission is being built out, you can use the Bitcoin mine to produce revenue by mining Bitcoin.","offset":790,"duration":11},{"text":"And so I think we're at the very early stages of the progression of small modular reactors in the United States. This is something I'm very excited about, I've been waiting for, and again, good news.","offset":801,"duration":13},{"text":"We're going to fade the doomerism today. We're going to focus on the good news. This is good news and it's great to see. And just to sort of elaborate on that, I'll pull up the tweet I had before which was our reporting on this today from TFTC.","offset":814,"duration":74},{"text":"And I think just to give you more context about the gravity of something like this happening, the US has no real domestic isotope supply chain. 50 million nuclear medicine procedures a year depend on aging reactors in other countries. Oklo just got the green light to change that.","offset":888,"duration":17},{"text":"The NRC issued Atomic Alchemy, Oklo's wholly owned subsidiary, a materials license to receive, process, repackage, and distribute Radium-226, Cobalt-60, and Americium-241 from its Idaho radiochemistry laboratory.","offset":905,"duration":15},{"text":"This enables initial commercial isotope sales for the use in cancer therapies, medical research, advanced manufacturing, and national security. 50 million nuclear medicine procedures are performed annually in the US.","offset":920,"duration":13},{"text":"The isotopes they depend on are mostly produced by aging reactors outside the country. Supply is shrinking while demand is growing. The US has had no meaningful domestic isotope production pipeline for years.","offset":933,"duration":12},{"text":"Oklo is building one from scratch. And on the same day- so that is another thing- there are many things you can do with the nuclear products that Oklo is building.","offset":945,"duration":11},{"text":"One of which is energy, the other of which is this byproduct of isotopes that that is critical for a lot of medical procedures. And so in the same day DOE approved the nuclear safety design agreement for Oklo's Aurora Powerhouse at Idaho.","offset":956,"duration":15},{"text":"So we just talked about that, but that wasn't the only thing that happened today. Oklo also got the approval for this isotope production which should bolster the supply and is part of the reshoring and re-industrialization efforts of the Trump administration.","offset":971,"duration":15},{"text":"So it looks like we're bringing that home. It would be remiss of me not to shout out our friend Nuclear Bitcoiner, who's been on the show before. He said hello from Canada, where our freshly refurbished CANDU- CANDU reactor fleet will continue to produce a substantial portion of those isotopes for global market well into the 2060s.","offset":986,"duration":21},{"text":"So looks like North America has isotope production pretty- pretty locked down with what's going on between Oklo and the production we're seeing up north in Canada.","offset":1007,"duration":12}],"startTime":492},{"title":"El Salvador as the New Dubai","summary":"The host highlights El Salvador's success as an economic zone, comparing its safety, tax incentives, and tech-forward policies to a \"Dubai 2.0\" for the Western Hemisphere.","entries":[{"text":"Not really a- this next story is not really a positive headline or anything. I just thought this framing from our good friend Julian Figueroa highlighting the success of El Salvador and particularly juxtaposed to Dubai is something I wanted to cover.","offset":1019,"duration":16},{"text":"Because I- I do think it's true. I- I think many people look at these economic regions that have popped up in the East particularly, whether it's Dubai, Abu Dhabi in the UAE, many people look to Singapore, Thailand, and other places and say, \"Hey, Hong Kong until China took it over in 2019.\"","offset":1035,"duration":19},{"text":"But these areas, they've historically existed in the East and the Western Hemisphere hasn't had any of these. And looks like El Salvador is shaping up to be a pretty incredible Dubai 2.0 for the Western Hemisphere.","offset":1054,"duration":15},{"text":"And Julian makes the good point, I don't think enough people are talking about this. It's the safest country in the Western Hemisphere for four years in a row. Has no Middle East war fallout risk.","offset":1069,"duration":11},{"text":"0% tax on all foreign-sourced income. 0% property tax, dollarized economy, Bitcoin is legal tender, you have 0% capital gains tax on Bitcoin. Inflation is under 1%.","offset":1080,"duration":13},{"text":"You have 90-minute direct flights from Miami for less than $200. Four-to-six-hour flights from San Francisco or New York for under $400. You have world-class surfing, big plus for me.","offset":1093,"duration":12},{"text":"Democratically elected president with 85% approval rating. First country to give open-source AI developers full legal protection. That's pretty beautiful.","offset":1105,"duration":10},{"text":"First country with a sovereign order of Nvidia B300 chips. Elon Musk has Grok AI in 1 million-plus public school kids' hands. Democratically elected president, already said that, world-class surfing.","offset":1115,"duration":15},{"text":"Looks like we have a couple regos here. Locally grown coffee, tropical fruit, grass-fed beef, you get it. El Salvador's an incredible economic zone.","offset":1130,"duration":10},{"text":"I think what Bukele and his administration have done over the last six years has been incredible. I think longer than that now. And I think El Salvador's economic zone and this free market experiment in Central America is something that many people aren't talking enough about.","offset":1140,"duration":18},{"text":"And something that we should be highlighting here in the Western Hemisphere, particularly if we believe in Trump's national security strategy document and this focus on the Western Hemisphere.","offset":1158,"duration":12},{"text":"It is incredible to see our southern neighbors in Central America doing well and creating an environment that would draw capital, talent, and peace at the end of the day. It's beautiful to see.","offset":1170,"duration":13}],"startTime":1019},{"title":"SAVE Act Advances in the Senate","summary":"The SAVE Act, which mandates voter ID for federal elections to ensure only American citizens can vote, has advanced in the US Senate, marking a sensible win for domestic politics.","entries":[{"text":"Last but not least, bringing it back to domestic politics. Everybody looks at DC and again, they're not happy with the war and what's going on, but we should highlight wins when they do happen.","offset":1183,"duration":11},{"text":"It looks like the Save America Act has advanced in US Senate, 51-to-48. I believe now it'll go to a vote, but I think this is something many Americans have been waiting for.","offset":1194,"duration":12},{"text":"For those who are unaware, the SAVE Act would make it so you have to show an ID when you go to the vote. So securing our elections and making it so only American citizens are voting in American presidential elections and elections for House of Representatives and Senators.","offset":1206,"duration":17},{"text":"So this is a good thing to see. You want to see sensible laws passed and I think voter ID is a very sensible law. If you have to show ID if you go to a bar, if you go to a gas station to buy a pack of cigarettes, if you get pulled over by the cops, it would make sense that if you're participating in what is deemed to be one of the most important functions of our democratic society here in the United States, which is voting on your representatives, it would make sense that you show an ID.","offset":1223,"duration":30}],"startTime":1183},{"title":"Outro and Good News Recap","summary":"The host recaps the positive news stories covered in the episode, encouraging listeners to avoid doomscrolling and remain optimistic about the future.","entries":[{"text":"So that is advancing. We'll see whether or not it passes ultimately. Hopefully it does. And so yeah, that is the Bent for today. Looking out at the world, looking on Twitter, doomscrolling, a lot of negativity out there.","offset":1253,"duration":14},{"text":"I wanted to bring you some positivity. Bitcoin payments going to be turned on by default for Square at the end of this month. So if you're living on a Bitcoin standard, you'll be able to do that more seamlessly on March 30th.","offset":1267,"duration":12},{"text":"So it's a beautiful thing to see. CFTC stepping up, saying, \"Hey, self-custody if you're building open-source wallet software that enables people to self-custody as long as you're not custodying those funds, you don't have to register with us.\"","offset":1279,"duration":12},{"text":"So that recognition that open-source wallet software that enables self-custody is something that developers should be able to build and not worry about having the books thrown at them. Another good plus.","offset":1291,"duration":11},{"text":"Obviously the progression with Oklo and their nuclear technology, from their small modular reactors to their isotope production is advancing. This is something we want to see.","offset":1302,"duration":10},{"text":"The re-industrialization of the United States as well as the proliferation of nuclear energy generation. It's a long time coming. We're beginning to make steps in the right direction.","offset":1312,"duration":12},{"text":"And then the last two we have El Salvador being the Dubai of the Western Hemisphere and the SAVE Act advancing. Positive things happening out there. Don't doom, never doom. We're going to win. Tka-ka-ka.","offset":1324,"duration":15}],"startTime":1253}],"entries":[{"text":"Host: 'Sup freaks and Happy St. Paddy's Day. Probably getting this the day after, but I wanted to say it anyway. Top of the morning to you. War in Iran raging on. We have the counterintelligence chief resigning today. It's chaos out there.","offset":0,"duration":13},{"text":"There's a ton of people covering that stuff. Today, I wanted to focus on positive stuff as it pertains to Bitcoin and progression here in the United States.","offset":13,"duration":9},{"text":"I'm Marty Bent, founder of TFTC, been doing this for nine years. Managing Partner at 10:31, investing in Bitcoin infrastructure, been doing that for five years.","offset":22,"duration":10},{"text":"Been around the block, seen a lot of things, and believe that Bitcoin is one of the most powerful technologies that we have at our fingertips right now. And if you look out there, things are looking up for Bitcoin.","offset":32,"duration":14},{"text":"We've got Square, we'll start there. Our boy Nick Slany from Money Dev Kit, he was on the TFTC podcast a couple of months ago and if you're building with AI tools and you need them to have Bitcoin wallets, go check out Money Dev Kit to do that.","offset":46,"duration":17},{"text":"But he highlighted something here, maybe known where to look, being an ex-Square employee, but he said huge news coming through if you know where to look. We are going to win. Yes, we are, Nick. We are going to win.","offset":63,"duration":12},{"text":"But essentially, he's highlighting a change of service to the Square point-of-sale terminals where they've updated Square Bitcoin Terms of Service which is going to become effective at the end of this month, March 30th, 2026.","offset":75,"duration":16},{"text":"They are auto-enabling Square Bitcoin payments for all eligible sellers and so no longer will you have to be tasked with going to a Square merchant in your neighborhood and convincing them to turn on Bitcoin payments.","offset":91,"duration":14},{"text":"Square is enabling them automatically for all eligible sellers. So that should mean that millions of sellers will be able to accept Bitcoin as payment as of the end of this month.","offset":105,"duration":12},{"text":"So that's pretty massive. If you're a Bitcoiner living on a Bitcoin standard and you would like to spend Bitcoin wherever you shop, particularly via Square point-of-sale terminals, if you're going throughout your day and a lot of the merchants that you interact with are running Square, as of the end of the month, you should be able to pay in Bitcoin.","offset":117,"duration":21},{"text":"Don't know the exact details, but I assume that the auto-enable feature is not going to have it so the merchants are holding Bitcoin automatically. What I assume is happening is that you'll simply be able to pay. They'll be able to hit the \"Pay in Bitcoin\" button on the back-end of their terminal and then it will present a Bitcoin invoice that you can pay via QR code or NFC and you'll be able to pay in Bitcoin.","offset":138,"duration":23},{"text":"And the merchant will reap the benefits of saving on the interchange fees and then the Bitcoin will be auto-converted to dollars on the back-end that will sit in their Square account. Again, this is an assumption.","offset":161,"duration":13},{"text":"I'm assuming that this is how they're going to roll it out. Everything that Square has done up to this point seems like a bridge stepping stone towards a Bitcoin standard. And I think it would be a long shot for them to take the assumption that every merchant with this enabled wants to hold Bitcoin.","offset":174,"duration":17},{"text":"However, it's big for people like myself living on a Bitcoin standard. Instead of selling Bitcoin for cash and just paying with a card, you want to hold your cash reserves in the best cash ever, digital cash, Bitcoin, and you simply want to pay for things as you go about your day.","offset":191,"duration":15},{"text":"You should be able to do that by the end of the month and the merchant, unbeknownst to them, I assume most of them will not be aware of this, but they will be saving on the interchange fees per transaction of their customers paying in Bitcoin. It's a beautiful thing. It's great to see. Very bullish, as Nick said.","offset":206,"duration":19},{"text":"I will reiterate: we are going to win. Things are chaotic out there right now, but let's focus on the positive sides. Next up, big news from the CFTC today.","offset":225,"duration":12},{"text":"The team at Phantom Wallet, which for those of you in Bitcoin who are unaware, Phantom Wallet, from what I understand, is a big Solana wallet that enables self-custodial properties for shitcoins, for lack of a better term, Solana and tokens being spun up there.","offset":237,"duration":15},{"text":"I believe they petitioned, or asked for a letter of clarity from the CFTC, and the CFTC got back to them today and told them that self-custodial wallet developers don't need to register as brokers.","offset":252,"duration":13},{"text":"So Phantom Wallet received a no-action letter stating that the CFTC will not pursue enforcement against self-custodial wallet developers who connect users to regulated trading venues as long as they don't custody user funds.","offset":265,"duration":14},{"text":"First time the agency has formally drawn that line. Again, here's why that's massive: under existing US law, any entity that solicits or facilitates derivatives trading typically must register as an introducing broker with the CFTC.","offset":279,"duration":15},{"text":"That rule was written for traditional financial intermediaries, but as self-custodial wallets started integrating across derivatives markets, developers faced a legal gray area that could have classified them as unregistered brokers simply for writing software.","offset":294,"duration":16},{"text":"The CFTC position, the CFTC's position was: if your wallet software connects users to properly registered futures commission merchants, introducing brokers, or designated contract markets, and you don't custody user funds, you are not a broker, you are a software provider.","offset":310,"duration":17},{"text":"Timing is not coincidental. One week ago, CFTC Chairman Mike Selig said at FIA's Boca Raton conference: for too long there's been an open question as to whether software providers trigger the CFTC's registration requirements. We intend to address the question head-on.","offset":327,"duration":19},{"text":"Seven days later, they did. So this is massive. I mean, I don't think it's all-encompassing for all software developers. I think this is just any that may fall under the purview of CFTC regulation.","offset":346,"duration":12},{"text":"But it is great to see a US regulator stepping up and saying, \"Hey, we recognize that we are entering into a new world, particularly at the intersection of technology and financial services.\"","offset":358,"duration":13},{"text":"The technology that was unleashed with Bitcoin enables you to truly custody your own wealth using open-source software and wallet software that gives you full control over your funds as you're holding them.","offset":371,"duration":12},{"text":"And for many years, but more particularly over the last two years, as open-source software developers connected to Samurai Wallet and Tornado Cash, the open-source wallet developers writing, building those wallets, either were thrown in jail or are on trial to go to jail for providing free and open-source wallet software that just so happened to provide privacy benefits for individuals.","offset":383,"duration":25},{"text":"So it's good to see the Trump administration moving in the right direction as it pertains to self-custody of Bitcoin and other crypto assets. Hopefully this becomes broad brush and applies to everything.","offset":408,"duration":13},{"text":"We still need to free Samurai, Roman Storm. The SDNY and the DOJ seems to be on a witch hunt after him specifically. Looks like he will have a retrial later this year as of right now.","offset":421,"duration":13},{"text":"And I believe Samurai Wallet developers, Keonne Rodriguez and William Hill, need to be pardoned. And the DOJ needs to drop the case on Roman Storm.","offset":434,"duration":9},{"text":"And so hopefully they see what the CFTC has done, the people at the DOJ look at the CFTC saying, \"Hey, this is free and open-source software, developers who make this don't need to worry, you don't need to register, you are not responsible for what your end-users do with that open-source software tool.\"","offset":443,"duration":21},{"text":"Hopefully it becomes more popular, but again, incredible to see positive development, bullish news, and something that has been long-awaited. So shout out to CFTC Chairman Mike Selig and others who came out and made this no-action letter.","offset":464,"duration":16},{"text":"Big day, big day. It's getting swept under the rug of all the news pertaining to the Iran-Israel right now. So I wanted to make sure we highlight that that's on your radar.","offset":480,"duration":12},{"text":"Another thing, I've been talking about this for years, as many of you know. If you've been around for a while, I have been heavily involved in the Bitcoin mining industry since 2018.","offset":492,"duration":12},{"text":"I am fascinated by this intersection of energy and Bitcoin mining. I think Bitcoin mining as a buyer of first and last resort for energy sources across the spectrum, anywhere from my- my plug here in the corner where I could put a bitaxe, to a multi-gigawatt facility participating in demand response.","offset":504,"duration":19},{"text":"There are arbitrage, energy arbitrage plays that Bitcoin mining can fit into to help level out demand and increase revenue and profitability for energy providers in many different flavors, whether that's an energy generation facility, a utility company, a substation, whatever it may be.","offset":523,"duration":21},{"text":"Off-grid, stranded oil and gas wells, like Bitcoin mining plays perfectly here. And one topic in the energy sector that I've been fascinated with and waiting for for the last eight years is the proliferation of small modular reactors, small modular nuclear reactors.","offset":544,"duration":19},{"text":"And a company I've been following, I believe since 2019, 2020 is Oklo. And today, Oklo got some good news. They've been trying to get the regulatory red tape cut off so that they can go do what they need to do to begin implementing and integrating their small modular reactor technology across the country.","offset":563,"duration":21},{"text":"And today, the Nuclear Regulatory Commission came out and gave them their first go-ahead. And so actually, I don't want to show this first. We will show this message from Stefan.","offset":584,"duration":27},{"text":"So Oklo announces that the US Department of Energy approval for nuclear safety design agreement of Aurora Powerhouse at Idaho National Laboratory has been approved.","offset":611,"duration":13},{"text":"This is an acronym word salad for folks not versed in DOE STD-1271. Oklo has signed an other transaction agreement with the DOE to initiate their Aurora reactor design and development project.","offset":624,"duration":14},{"text":"They're currently deploying their reactor at INL under the DOE's Reactor Pilot Program. Signing an OTA is the first step and enables the discussion and planning to start. Oklo says they also signed a nuclear safety design agreement.","offset":638,"duration":14},{"text":"The purpose of the NSDA is to gain agreement on design requirements, safety analysis approach, regulatory engagement process, applicable regulatory requirements, and to identify the key safety decisions for the design.","offset":652,"duration":14},{"text":"Oklo has requested immediate review of the preliminary documented safety analysis or PDSA to progress the project further. The purpose of the PDSA is to provide a comprehensive and preliminary assessment of the safety aspects of nuclear facility or activity.","offset":666,"duration":17},{"text":"Normally done when design is at least 50% complete. Very big accomplishment by the Oklo team. And as you can see here, you have the different phases of going through the approval process to get new nuclear generation approved in the United States.","offset":683,"duration":13},{"text":"It's been decades and nuclear energy is the most reliable, cleanest, and sustainable- sustainable in the form of profitable and manageable energy out there.","offset":696,"duration":12},{"text":"And I think it's been- the US has done itself a great disservice by throwing up a regulatory regime that has made it almost impossible to bring new nuclear generation facilities to market.","offset":708,"duration":12},{"text":"It seems like under Chris Wright and the current Department of Energy they are looking to reverse course there and make sure that the US leads on nuclear power generation, particularly with small modular reactors.","offset":720,"duration":13},{"text":"And so I don't think Oklo's going to be setting down an SMR tomorrow, but we're making material progress in unleashing the small modular reactor industry to be able to go do their thing.","offset":733,"duration":13},{"text":"Beautiful to see. Bitcoin miners I think will have a role to play here, particularly if you're going to rural areas to provide electricity in areas where something like a diesel generator is the main source of energy right now.","offset":746,"duration":14},{"text":"You want to replace that with cleaner, more reliable energy. SMRs are perfect. The problem that these SMRs are going to run into is that they'll be able to plop down, but there will be a period of time between when they plop down and when they have a grid interconnect and transmission lines built to the local grid system they're looking to serve.","offset":760,"duration":19},{"text":"And so you have this economic problem where you've spent a lot of capital and CAPEX up front to build the SMR, you plop it down, and then you have a period of time where it's just sitting there doing nothing.","offset":779,"duration":11},{"text":"This is where Bitcoin miners come in. They could sit behind the meter and while grid interconnect and transmission is being built out, you can use the Bitcoin mine to produce revenue by mining Bitcoin.","offset":790,"duration":11},{"text":"And so I think we're at the very early stages of the progression of small modular reactors in the United States. This is something I'm very excited about, I've been waiting for, and again, good news.","offset":801,"duration":13},{"text":"We're going to fade the doomerism today. We're going to focus on the good news. This is good news and it's great to see. And just to sort of elaborate on that, I'll pull up the tweet I had before which was our reporting on this today from TFTC.","offset":814,"duration":74},{"text":"And I think just to give you more context about the gravity of something like this happening, the US has no real domestic isotope supply chain. 50 million nuclear medicine procedures a year depend on aging reactors in other countries. Oklo just got the green light to change that.","offset":888,"duration":17},{"text":"The NRC issued Atomic Alchemy, Oklo's wholly owned subsidiary, a materials license to receive, process, repackage, and distribute Radium-226, Cobalt-60, and Americium-241 from its Idaho radiochemistry laboratory.","offset":905,"duration":15},{"text":"This enables initial commercial isotope sales for the use in cancer therapies, medical research, advanced manufacturing, and national security. 50 million nuclear medicine procedures are performed annually in the US.","offset":920,"duration":13},{"text":"The isotopes they depend on are mostly produced by aging reactors outside the country. Supply is shrinking while demand is growing. The US has had no meaningful domestic isotope production pipeline for years.","offset":933,"duration":12},{"text":"Oklo is building one from scratch. And on the same day- so that is another thing- there are many things you can do with the nuclear products that Oklo is building.","offset":945,"duration":11},{"text":"One of which is energy, the other of which is this byproduct of isotopes that that is critical for a lot of medical procedures. And so in the same day DOE approved the nuclear safety design agreement for Oklo's Aurora Powerhouse at Idaho.","offset":956,"duration":15},{"text":"So we just talked about that, but that wasn't the only thing that happened today. Oklo also got the approval for this isotope production which should bolster the supply and is part of the reshoring and re-industrialization efforts of the Trump administration.","offset":971,"duration":15},{"text":"So it looks like we're bringing that home. It would be remiss of me not to shout out our friend Nuclear Bitcoiner, who's been on the show before. He said hello from Canada, where our freshly refurbished CANDU- CANDU reactor fleet will continue to produce a substantial portion of those isotopes for global market well into the 2060s.","offset":986,"duration":21},{"text":"So looks like North America has isotope production pretty- pretty locked down with what's going on between Oklo and the production we're seeing up north in Canada.","offset":1007,"duration":12},{"text":"Not really a- this next story is not really a positive headline or anything. I just thought this framing from our good friend Julian Figueroa highlighting the success of El Salvador and particularly juxtaposed to Dubai is something I wanted to cover.","offset":1019,"duration":16},{"text":"Because I- I do think it's true. I- I think many people look at these economic regions that have popped up in the East particularly, whether it's Dubai, Abu Dhabi in the UAE, many people look to Singapore, Thailand, and other places and say, \"Hey, Hong Kong until China took it over in 2019.\"","offset":1035,"duration":19},{"text":"But these areas, they've historically existed in the East and the Western Hemisphere hasn't had any of these. And looks like El Salvador is shaping up to be a pretty incredible Dubai 2.0 for the Western Hemisphere.","offset":1054,"duration":15},{"text":"And Julian makes the good point, I don't think enough people are talking about this. It's the safest country in the Western Hemisphere for four years in a row. Has no Middle East war fallout risk.","offset":1069,"duration":11},{"text":"0% tax on all foreign-sourced income. 0% property tax, dollarized economy, Bitcoin is legal tender, you have 0% capital gains tax on Bitcoin. Inflation is under 1%.","offset":1080,"duration":13},{"text":"You have 90-minute direct flights from Miami for less than $200. Four-to-six-hour flights from San Francisco or New York for under $400. You have world-class surfing, big plus for me.","offset":1093,"duration":12},{"text":"Democratically elected president with 85% approval rating. First country to give open-source AI developers full legal protection. That's pretty beautiful.","offset":1105,"duration":10},{"text":"First country with a sovereign order of Nvidia B300 chips. Elon Musk has Grok AI in 1 million-plus public school kids' hands. Democratically elected president, already said that, world-class surfing.","offset":1115,"duration":15},{"text":"Looks like we have a couple regos here. Locally grown coffee, tropical fruit, grass-fed beef, you get it. El Salvador's an incredible economic zone.","offset":1130,"duration":10},{"text":"I think what Bukele and his administration have done over the last six years has been incredible. I think longer than that now. And I think El Salvador's economic zone and this free market experiment in Central America is something that many people aren't talking enough about.","offset":1140,"duration":18},{"text":"And something that we should be highlighting here in the Western Hemisphere, particularly if we believe in Trump's national security strategy document and this focus on the Western Hemisphere.","offset":1158,"duration":12},{"text":"It is incredible to see our southern neighbors in Central America doing well and creating an environment that would draw capital, talent, and peace at the end of the day. It's beautiful to see.","offset":1170,"duration":13},{"text":"Last but not least, bringing it back to domestic politics. Everybody looks at DC and again, they're not happy with the war and what's going on, but we should highlight wins when they do happen.","offset":1183,"duration":11},{"text":"It looks like the Save America Act has advanced in US Senate, 51-to-48. I believe now it'll go to a vote, but I think this is something many Americans have been waiting for.","offset":1194,"duration":12},{"text":"For those who are unaware, the SAVE Act would make it so you have to show an ID when you go to the vote. So securing our elections and making it so only American citizens are voting in American presidential elections and elections for House of Representatives and Senators.","offset":1206,"duration":17},{"text":"So this is a good thing to see. You want to see sensible laws passed and I think voter ID is a very sensible law. If you have to show ID if you go to a bar, if you go to a gas station to buy a pack of cigarettes, if you get pulled over by the cops, it would make sense that if you're participating in what is deemed to be one of the most important functions of our democratic society here in the United States, which is voting on your representatives, it would make sense that you show an ID.","offset":1223,"duration":30},{"text":"So that is advancing. We'll see whether or not it passes ultimately. Hopefully it does. And so yeah, that is the Bent for today. Looking out at the world, looking on Twitter, doomscrolling, a lot of negativity out there.","offset":1253,"duration":14},{"text":"I wanted to bring you some positivity. Bitcoin payments going to be turned on by default for Square at the end of this month. So if you're living on a Bitcoin standard, you'll be able to do that more seamlessly on March 30th.","offset":1267,"duration":12},{"text":"So it's a beautiful thing to see. CFTC stepping up, saying, \"Hey, self-custody if you're building open-source wallet software that enables people to self-custody as long as you're not custodying those funds, you don't have to register with us.\"","offset":1279,"duration":12},{"text":"So that recognition that open-source wallet software that enables self-custody is something that developers should be able to build and not worry about having the books thrown at them. Another good plus.","offset":1291,"duration":11},{"text":"Obviously the progression with Oklo and their nuclear technology, from their small modular reactors to their isotope production is advancing. This is something we want to see.","offset":1302,"duration":10},{"text":"The re-industrialization of the United States as well as the proliferation of nuclear energy generation. It's a long time coming. We're beginning to make steps in the right direction.","offset":1312,"duration":12},{"text":"And then the last two we have El Salvador being the Dubai of the Western Hemisphere and the SAVE Act advancing. Positive things happening out there. Don't doom, never doom. We're going to win. Tka-ka-ka.","offset":1324,"duration":15}],"logs":[{"elapsed":"0.0","message":"Downloading audio from YouTube...","detail":null},{"elapsed":"0.0","message":"Trying download with browser cookies (ad-free)...","detail":null},{"elapsed":"3.4","message":"⚠ Cookie download failed: WARNING: [youtube] [jsc] Error solving n challenge request using \"deno\" provider: Error running deno process (returncode: 1): \u001b[0m\u001b[1m\u001b[31merror\u001b[0m: Uncaught (in promise) TypeError: Cannot read prope","detail":null},{"elapsed":"3.4","message":"Retrying without cookies...","detail":null},{"elapsed":"15.4","message":"⚠ Downloaded without cookies — audio may contain ads","detail":null},{"elapsed":"15.4","message":"Audio downloaded (11.9 MB) in 15.4s","detail":"File size: 11.9 MB"},{"elapsed":"15.4","message":"Video title: The Best Week For Bitcoin Nobody Is Talking About","detail":null},{"elapsed":"15.5","message":"Audio duration: 19:20 (19.3 min)","detail":null},{"elapsed":"15.5","message":"Uploading audio to Gemini File API...","detail":null},{"elapsed":"18.1","message":"Audio uploaded in 2.6s","detail":"File ref: files/jm31luybqpe8"},{"elapsed":"18.1","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"50.1","message":"Transcription complete in 34.6s","detail":"20898 chars received"},{"elapsed":"50.1","message":"Transcription tokens: 29,231 in / 5,097 out — cost: $0.0299","detail":null},{"elapsed":"50.1","message":"Parsed 87 transcript segments","detail":null},{"elapsed":"50.1","message":"Transcript coverage: 22:04 of 19:20 (114%) — OK","detail":null},{"elapsed":"50.1","message":"Total transcription time: 34.6s — 87 segments","detail":null},{"elapsed":"50.1","message":"Analyzing topics across 87 segments with gemini-3.1-pro-preview...","detail":null},{"elapsed":"69.3","message":"Topic analysis complete in 19.2s — found 7 topics","detail":null},{"elapsed":"69.3","message":"Analysis tokens: 5,631 in / 574 out / 1,478 thinking — cost: $0.0359","detail":null},{"elapsed":"69.3","message":"Pipeline finished in 69.3s — total cost: $0.0658 (42,011 tokens)","detail":null}]} \ No newline at end of file diff --git a/history/1774302030087--JBhTBu9ZbA.json b/history/1774302030087--JBhTBu9ZbA.json new file mode 100644 index 0000000..6173a38 --- /dev/null +++ b/history/1774302030087--JBhTBu9ZbA.json @@ -0,0 +1 @@ +{"id":"1774302030087--JBhTBu9ZbA","videoId":"-JBhTBu9ZbA","url":"https://www.youtube.com/watch?v=-JBhTBu9ZbA","title":"Four CEOs on the Future of AI: CoreWeave, Perplexity, Mistral, and IREN","type":"youtube","topicCount":23,"segmentCount":269,"createdAt":"2026-03-23T21:40:30.087Z","uploadDate":"20260323","chunks":[{"title":"Introduction","summary":"The host introduces the episode from NVIDIA's GTC conference.","entries":[{"text":"Host: I'm here at NVIDIA's annual GTC conference and I'm going to interview four amazing AI CEOs. Stick with us. Our episode is sponsored by the New York Stock Exchange. Are you looking to change the world and raise capital? Do it at the NYSE. The NYSE is a modern marketplace and a massive platform built for scale and long-term impact. So, if you're building for the future, the NYSE is where it happens.","offset":0,"duration":41}],"startTime":0},{"title":"CoreWeave's Origins","summary":"Michael Intrator discusses CoreWeave's early days, pivoting from crypto mining to CGI rendering, and eventually donating hardware to AI researchers.","entries":[{"text":"Host: One of the great companies of the AI era is of course CoreWeave. They're building massive infrastructure for these hyper scalers. And in some ways Michael Intrator, welcome to the program, you're the original hyper scaler. You guys got in very early and secured your, I don't know which GPUs you wound up getting, but you were very early to this trend. How did you get to it so early and how did you build out this, you know, first, I guess at the time, neo cloud?","offset":41,"duration":33},{"text":"Michael Intrator: Yeah, so we didn't really start it as a neo cloud. I was running an algorithmic hedge fund focused on natural gas. And when you build an algorithmic hedge fund, once the algorithms are built, you're really just monitoring it and testing different theses and doing all of that. But there's also a lot of downtime. And we got super interested in crypto.","offset":74,"duration":21},{"text":"Michael Intrator: And you know, we're pretty nerdy, we kind of dig under the hood and we started to get interested in the security layer. We looked at Bitcoin and the mining for Bitcoin and we didn't like it. We just thought that like there's some brilliant engineer that built the ASIC and they're probably going to be better at running it than we are. So we really began to focus on the GPUs mostly because the GPUs were—you can mine Ethereum with them, but you could also do all these other things.","offset":95,"duration":24},{"text":"Michael Intrator: And really right from the start, we looked at the compute as an option to be able to deploy our computing power to different use cases. And so, you know, began the company in 2017, spent the first kind of three years mining crypto, went through a couple of crypto winters. Because we had come from a hedge fund our—we have real chops in risk management and how we think about capital and risk exposure and allocation and all of that.","offset":119,"duration":27},{"text":"Michael Intrator: And so we were really careful around that right from the start. So we weathered crypto winter really well and began to scale the company and immediately started to look for other use cases that you could use this compute for because crypto was pretty volatile.","offset":146,"duration":18},{"text":"Host: Yeah, and crypto was a question mark at that time. I mean, Bitcoin was speculative and there were many other speculative projects. The only other people using this type of hardware: quants, medical research...","offset":164,"duration":18},{"text":"Michael Intrator: Yeah, so a good way to think about it is like the progression of products that we kind of started to work on. You know, first was crypto, but we immediately moved from crypto to CGI rendering and we built projects that allowed folks that were trying to animate and render images, you know, kind of what makes the movies cool, right? And we started to work on that and then we moved to batch computing and started to look at medical research and different ways of using the compute to be able to drive science.","offset":182,"duration":28},{"text":"Michael Intrator: And we just kind of kept moving up the stack in terms of complexity on how GPUs can be used and ultimately in like call it like 2020-2021, we started to really try to figure out how you can go ahead and use GPUs for neural networks. And that was not something that we knew how to do. And so we actually went out and bought a bunch of A100s and donated them to a group that was working on EleutherAI.","offset":210,"duration":30},{"text":"Michael Intrator: They were working on an open-source project with the thought that these guys are taking the GPU compute because we're donating it, they can't really get pissed at us if we're not very good at it initially. And that worked out really well because they kept telling us like we need more of this, you gotta work on that, and that began to really give us an understanding of what was necessary to run scale parallelized computing.","offset":240,"duration":31},{"text":"Michael Intrator: And you know, that we went through it—I kind of feel like buying those initial GPUs was the tuition we paid to learn how to run this business. And then one of the interesting things is all of those guys went back to their day jobs because they were all volunteers working on this, they were like-minded scientists. And when they got to their day jobs, they were all like, \"I want that infrastructure, it's built the right way, that's the way that researchers are going to want to use it,\" and that launched our business. It was an amazing story.","offset":271,"duration":30},{"text":"Host: Yeah, so you went from crypto to these researchers, into academia and deep research. What's the next card to turn over in the poker game?","offset":301,"duration":12}],"startTime":41},{"title":"Scaling LLM Infrastructure","summary":"CoreWeave recognizes the scaling laws of AI and shifts focus to building massive supercomputers for model training and real-world inference.","entries":[{"text":"Michael Intrator: Yeah, so what became very clear to us very, very early on was that the scaling laws were going to drive... and remember, this is really back in the, you know, 2020-2021 before the ChatGPT moment occurred. And we began to understand that like computing decommoditizes at scale, right? Like when anybody can run a GPU, but can you run a cluster that's large enough to train a model that can change the world? And that's a different question.","offset":313,"duration":28},{"text":"Michael Intrator: And so we really began to think about like how do you go about scaling up your delivery of this computing to clients, larger and larger clients. And that was the next card to turn is to think about it from a... okay, you know, there's a component of this that is going to lean into our ability to access the capital to be able to deliver our solution to the broadest possible audience, to the most sophisticated consumers of this compute.","offset":341,"duration":26},{"text":"Michael Intrator: And that was really the next card is thinking about it as a business rather than as an engineering project to be able to deliver the infrastructure and the software and really everything between... you know, when you're thinking about what we do, we kind of live above the NVIDIA GPUs but below the models. And everything in there, all the software, the integration of software and operations and observability and all the things that you need to be able to build a cloud that's purpose-built for this one specific use case, right?","offset":367,"duration":33},{"text":"Michael Intrator: So we don't do everything, we really focus on one use case which allows us to...","offset":400,"duration":6},{"text":"Host: You don't want to do web servers and things like that?","offset":406,"duration":2},{"text":"Michael Intrator: You know what, they do a great job, it's a great solution, it was a brilliant solution to solve a problem. We just looked at it and said there's a new problem and let's go about looking at this problem and trying to come up with a solution to deliver compute that solves that problem.","offset":408,"duration":13},{"text":"Host: And when did the language model start dialing and calling you for, you know, capacity?","offset":421,"duration":6},{"text":"Michael Intrator: Yeah, so our first... well, our first language model was really Eleuther. But our first like large commercial was Inflection. And so, you know, we worked with Mustafa and Inflection and then we really diversified from there into the hyper scalers, into you know, OpenAI across the foundation models and just kept scaling and scaling with the belief that, once again, the decommoditization of compute...","offset":427,"duration":42},{"text":"Michael Intrator: ...the ability to deliver a solution, and the solution is building super computers that can change the world. And that's really what we began to focus on. That was the lead into training and now the world has gone through you know this moment where we've moved from research into the productization of this. It's beginning to work its way in from the fringe of organizations into the core of what they do. And you can see that every day in the amount of inference compute that is being driven through our infrastructure layer which is just massive.","offset":469,"duration":40},{"text":"Host: And the inference shows you people are consuming it, not just building models, but they're deploying them and utilizing them.","offset":509,"duration":6},{"text":"Michael Intrator: I always think of inference as the monetization of the investment in artificial intelligence. So when we see our compute being used to stand up the massive scale of inference that's hitting our compute every day... and you know inference is when people ask the model a question, it comes back with an answer. That's an inference. Or when you ask the model a question and then to go do something, that's inference, right? And that's actually where you have the opportunity to really drive value outside of the model itself but into the real world. And that's really exciting for us. That's what we like to watch, that's what I like to watch in terms of gauging the health.","offset":515,"duration":44}],"startTime":313},{"title":"The GPU Depreciation Debate","summary":"Michael refutes the idea that GPUs become obsolete quickly, noting that older chips like Ampere retain high value for inference and specialized tasks.","entries":[{"text":"Host: What chips are those?","offset":559,"duration":2},{"text":"Michael Intrator: So really you know we are the tip of the spear in bringing the new architecture out of NVIDIA into commercial production at scale. And so when you know we were the first ones to bring the H100s at scale, we were the first ones to bring the H200s at scale, first ones with the GB200s, and now you've got the GB300s. And one of the things that's amazing and really fascinating for us is people are using the bleeding-edge GPUs to train models as the new architectures come out.","offset":561,"duration":40},{"text":"Michael Intrator: And then they take those GPUs and they move them into different experiments and then over time they move them into inference and they continue to use them in inference for a very, very long time.","offset":601,"duration":10},{"text":"Host: What is the shelf life of a 100 right now? That's been a big debate I think for your company, for Microsoft, and I guess Michael Burry, you know, who you must have known when you were a quant, saying, \"oh my God, the whole industry is... the sky's falling.\" And then we all know in the industry that people don't just throw this hardware away, they find uses for it, the street finds its own use for technology. So what's the reality of the lifespan of these things?","offset":611,"duration":28},{"text":"Michael Intrator: So my take on the GPU depreciation debate is that it's nonsense, right? It's a debate that is being brought to the forefront by some traders that have a short position in the stock and they're trying to talk down. Look, here's what we know, right? When we buy infrastructure, we're a success-based company, right? We're a small company on a relative basis compared to the enormous companies that we're competing with.","offset":639,"duration":28},{"text":"Michael Intrator: And so our clients come into us and they buy compute for five years, for six years. Our average contract is five years. So any commentary by anyone either inside or outside of the industry that this stuff becomes obsolete in 16 months or whatever nonsense they're spewing, it doesn't in any way match up with the facts on the ground. The facts on the ground is they're buying it for five years, right?","offset":667,"duration":29},{"text":"Michael Intrator: If and my approach to this has always been, if people are willing to pay me for it, it still has value. Pretty simple way of approaching it. We use a six-year depreciation, we believe that the GPUs will last in excess of six years, but we felt like that was a fair and reasonable approach to a technology cycle that's moving at this velocity. The A100s, the Amperes, this year the price has appreciated through the year.","offset":696,"duration":22},{"text":"Host: Yeah, why is that?","offset":718,"duration":1},{"text":"Michael Intrator: I think it's because one of the things that happens is as more installed capacity becomes available, you have new companies that come into existence that have new use cases, that have different sized models, that are trying to build new commercial ventures that maybe have been blocked out of the H100 and never had an opportunity to run on that.","offset":719,"duration":22},{"text":"Host: I mean, to make a very simple example for the audience, like you when you trade in your iPhone after three or four years you're like, \"who's gonna use an iPhone 12?\" And it's like, have you been to South America or Africa where you go to the store and you buy an iPhone 12 or you buy the Pixel 7 and it costs $50? That's still got great life left in it.","offset":741,"duration":20},{"text":"Michael Intrator: Absolutely. And so look you know we find these amazing use cases, new companies that have come into existence or existing companies that have integrated new models into their workflow that are able to use the Amperes. And so they keep buying any GPUs that we have available. And once again, you know, the concept that a GPU is no longer relevant or commercially viable after 16, 18 months or two years, it just doesn't make any sense.","offset":761,"duration":31},{"text":"Host: It's obviously farscale. I think sometimes people get caught up in Moore's Law or in just how fast our industry is growing, and that there's so much at stake that big companies are demanding the most recent products that doesn't mean that the lifespan has gotten shorter. It means the opportunity and the surface area of the opportunity's gotten much larger.","offset":792,"duration":22},{"text":"Michael Intrator: Yeah, one of the things is like you know the industry has gotten so much attention for the unprecedented scale of capital that is coming to bear on this. And because of that there tends to be an incredible focus on the companies that are building on these most advanced chipsets.","offset":814,"duration":27},{"text":"Michael Intrator: And the truth of the matter is is you know even within those companies they have a long tail of useful life to provide inference horsepower, to work on other experiments, to do less bleeding-edge activity but still needs to be done. And yeah, I mean rendering comes to mind as well, or yeah, or making images on Nano Banana, like there will be a use for it.","offset":841,"duration":26},{"text":"Michael Intrator: There is a moment of time where maybe the compute to power ratio doesn't make sense. My expectation is obsolescence will be defined by the moment in time where the power in the data center for me will be able to be repurposed for a higher margin than the existing infrastructure provides.","offset":867,"duration":24},{"text":"Michael Intrator: And you know like I said, I fully expect this infrastructure to last in excess of six years, but the standard in the space is really been used with one exception which is Amazon, which is yeah it's six years. That seems like the right schedule. I'm not making it up, that's what everybody's using.","offset":891,"duration":15},{"text":"Host: Yeah, and the energy cost is the opportunity because hey it's just a... we need that space, there's a better reward here, and that might get resold that hardware to somebody else who wants it, a hobbyist or something.","offset":906,"duration":14},{"text":"Michael Intrator: Yeah, I mean or it could be sent some place else where they have more capacity and they can repurpose it there. But I kind of feel like you know we'll deal with that part of the business when we get there. What I know right now is it is extraordinarily profitable, it's very accretive to my company to continue to keep the infrastructure that's been up and running, that's been on these long-term contracts and as it rolls off, as it's been in use for five years, you know as it becomes available, I'm still able to sell it at a higher price than it was at a year ago.","offset":920,"duration":33}],"startTime":559},{"title":"Hardware Allocations and Competition","summary":"A look at how CoreWeave secures the latest hardware from NVIDIA through straightforward purchasing, and how market competition validates their business model.","entries":[{"text":"Host: There's competition now when you were buying these from Jensen back in the day, yeah, you could buy them and have them shipped I would assume within 30 days or less. Nowadays what's the weight like even for you a loyal old customer and is there a bit of a battle? Is there politics to who gets the servers? Like I you see some like very big names talking about they gotta get an allocation. Is it still a little bit crazy? What's it like to be in that category having to buy something everybody wants?","offset":953,"duration":30},{"text":"Michael Intrator: Look you know I think of it as an affirmation of the business that we're in, right? Like the fact that we are attracting competitors means that the business is healthy and there's a lot of people trying to deliver this service because the need for this infrastructure, the need to integrate the infrastructure you know into the software layers to deliver it to artificial intelligence either at the model level or the inference level or the application level or whatever you know level of the five layer cake that Jensen's you know focused on.","offset":983,"duration":36},{"text":"Michael Intrator: The fact that there are more people coming into this, it doesn't discourage me. As far as getting access to the GPUs, we show up like everybody else with a you know, \"we'd like to buy, here's a PO and we're ready to pay.\"","offset":1019,"duration":11},{"text":"Host: What's the wait time like and is it just really competitive or not? Because I talk to Jensen about it he said... I said \"how do you manage all these like big egos and names and companies trying to buy stuff?\" And he said \"well, they order it and we give it to them in the order in which they order it.\" Is it really like that?","offset":1030,"duration":17},{"text":"Michael Intrator: It really is, right? Like you know he doesn't want to be in the position of playing favorites or... like that just seems like a bad place to be with your clients.","offset":1047,"duration":10},{"text":"Host: Or auctioning them off, can you imagine?","offset":1057,"duration":2},{"text":"Michael Intrator: Yeah, so yeah that would that would that would be crazy. Yeah, I don't I'm not sure that would be good for the long-term business.","offset":1059,"duration":10},{"text":"Host: You might get some sovereigns coming in and saying \"I'll pay double.\" They do that with Ferraris too sometimes.","offset":1069,"duration":6},{"text":"Michael Intrator: Yes, these are the Ferraris of computing in a way. They are, yeah. But I mean our approach is to work with clients across the entire space to find opportunities that are really interesting companies that can fit into our contracting requirements where we're going to be able to go out and structure the debt that we require in order to go out and build infrastructure at this scale.","offset":1075,"duration":27}],"startTime":953},{"title":"CoreWeave's 'Box' Financing","summary":"An explanation of 'The Box', CoreWeave's innovative debt-financing vehicle that leverages long-term client contracts to drastically lower their cost of capital.","entries":[{"text":"Host: How does all that debt work? That is something that you guys specialize in. Corporate debt, I'm in the venture business people are like \"why should I be in venture when corporate debt pays so well? Corporate paper is so huge.\" I'm curious how this fits in and like what interest rate people are paying on you know a billion dollars in infrastructure. What do they pay on that?","offset":1102,"duration":23},{"text":"Michael Intrator: Yeah, so CoreWeave has really been the innovator around a lot of the financing engines that have come to bear on this. We did the first GPU-based loans. And like I think it's important or I'm gonna try to explain this in a way people can understand. So what we do is we go out and we find a client. Let's use Microsoft, you brought them up before, right? And Microsoft comes to us and says we'd like to buy some compute for you and we say okay great we're gonna sign a contract.","offset":1125,"duration":31},{"text":"Michael Intrator: Once I have a contract in hand, then what I do is I create something it's not a particularly creative name, it's called \"The Box\", right? And what I do with the box is I take my contract with Microsoft and I put it in the box. I go to Jensen and I buy the GPUs, I put it in the box. I take my data center contract, I put it in the box. And now the box governs cash flow.","offset":1156,"duration":23},{"text":"Michael Intrator: And it has a waterfall of cash flow that comes into it and goes out of it. And so the way it works is then I build the compute and then I deliver the compute to Microsoft and they pay the box. They don't pay me. Right. It goes into the box and the first thing it does is it pays the data center, it pays the power bill, it pays the interest and the principal and then whatever's left flows back to us, right?","offset":1179,"duration":23},{"text":"Michael Intrator: And so it is an incredibly well structured, time-tested, pressure-tested vehicle to be able to borrow money against client paper and all of the other collateral around the deal. Which is why CoreWeave which is a company that many people haven't ever heard of was able to go out and raise $35 billion in 18 months to build infrastructure at scale.","offset":1202,"duration":27},{"text":"Michael Intrator: But what's important to understand is the economics in this box are such that within two and a half years of a five-year deal we have paid for everything. The principal's been paid off, the interest has been paid off. The return into the box is such that we are able to generate returns to our company at the box level which gives the most sophisticated lenders in the world, whether it's banks or private equity funds or you know whoever, confidence that they're going to be able to achieve the one rule of lending which is give me my money back.","offset":1229,"duration":42},{"text":"Host: Yes, works better when that happens.","offset":1271,"duration":2},{"text":"Michael Intrator: So they look at this box and they're like \"wow we're really confident we're gonna get our money back.\"","offset":1273,"duration":4},{"text":"Host: And maybe they want 10 boxes?","offset":1277,"duration":1},{"text":"Michael Intrator: That's correct. And if anyone box goes upside down you can deal with it and it's not as acute.","offset":1278,"duration":8},{"text":"Michael Intrator: That's correct and they don't cross-pollinate, they don't cause contagion across the boxes. They're all independent and discrete. One. And number two is as you do this and as you show the lenders how this financing tool and how this financing mechanism works, what they do is they continue to lend you money at progressively lower rates.","offset":1286,"duration":23},{"text":"Michael Intrator: And so when you think about our cost of capital over the last two years, we have dropped our cost of capital by 600 basis points. Wow, it is enormous, right? And so you're seeing a company that is driving its cost of capital down towards where the hyper scalers borrow. Which will enable us to be able to be competitive with them over time. And we have been extremely militant and diligent about feeding, watering and caring for those boxes so that we continue to have access to the capital markets in a way that allows us to build and drive our business.","offset":1309,"duration":38},{"text":"Host: Means you have to say no to maybe some people who want to be in the box, some customers?","offset":1347,"duration":4},{"text":"Michael Intrator: Yeah, so like we look at some deals and we're just like you know they want to buy GPUs for a year and I look at it and say \"I that's not a deal that I can do because it's too short for me to amortize the expenses.\" And so I won't do that, right? Like once again...","offset":1351,"duration":16},{"text":"Host: And they can go to another provider maybe wants to take that risk on who has extra capacity.","offset":1367,"duration":4},{"text":"Michael Intrator: Absolutely, but our business is really built about around the risk management of being able to get to scale. Because in my mind during this period of disequilibrium, during this period where there are not enough GPUs in the world to provide the compute for all of the different use cases in artificial intelligence, the part that's important for me and for my company is to get enormously large so we can drive down our cost of capital so that we have information flow coming in from all different parts of the market: the large language models, high-speed trading, search, all of these things and they're feeding...","offset":1371,"duration":39},{"text":"Michael Intrator: ...they're feeding information back into us that is letting us know what the next product we need to build is, or where you know they need help scaling, or what type of compute they need. And all of that information flow is incredibly valuable to us.","offset":1410,"duration":14}],"startTime":1102},{"title":"AI Demand and Hardware Throttles","summary":"The relentless demand for AI compute far outpaces global supply, facing major bottlenecks from power availability and cyclical memory shortages.","entries":[{"text":"Host: What what can you tell us about demand? There's been reports of hey maybe the Oracle Starbase thing with OpenAI's been downsized or maybe not, and then you know other folks Microsoft is going big and Google's going big, Meta's going big and those people obviously have massive cash flow. Apple seems to be MIA, they don't seem to want to play.","offset":1424,"duration":25},{"text":"Michael Intrator: You've named a lot of really big companies with really big balance sheets that have the capacity to drive a lot of demand. Look I have been truly steadfast in this for years now. For four years the depth of the demand for the service we provide has been relentless and overwhelms the global capacity of the world to deliver enough compute to enable all of the demand for artificial intelligence to be stated. And that has been... we have been relentless about that.","offset":1449,"duration":34},{"text":"Host: Sounds like Knicks tickets during the Patrick Ewing era, like they're up to 50,000 people on the wait list. So if magically the wait list went away, if the constraint went away and we just had a a large amount of GPUs available, a lot of energy available and a lot of data center available...","offset":1483,"duration":19},{"text":"Michael Intrator: So so... or how would be deployed, I should say. So remember how we build our our business: through this box and it's a five-year box. So if we had an air pocket, if demand were suddenly to disappear because of a technology breakthrough, because of a war, anything, right? Like the why from a risk management perspective does not matter. You have to prepare your company for the what happens if it happens.","offset":1502,"duration":33},{"text":"Michael Intrator: And so by entering into these long-term contracts, into entering into contracts with counterparts that have large balance sheets, you are or we are protecting ourselves and our lenders so that we are confident and they are confident because you can see how confident they are by the rate that they're charging us continuing to decline, that they're ultimately going to get their money back and that is the one rule of lending.","offset":1535,"duration":28},{"text":"Host: But just in terms of the capacity, if you were unconstrained and NVIDIA Jensen says \"hey order as many as you want,\" what would happen?","offset":1563,"duration":8},{"text":"Michael Intrator: So the the it's also important to understand the constraints aren't just GPUs, right? Electricity, data center... it's power shells, it's memory, it's storage, it's networking, it's optics, all of the things and there's various throttles that will limit the...","offset":1571,"duration":16},{"text":"Host: Memory's a throttle right now?","offset":1587,"duration":2},{"text":"Michael Intrator: Oh yeah it is. Oh yeah it is.","offset":1589,"duration":1},{"text":"Host: Why how did memory become the throttle?","offset":1590,"duration":2},{"text":"Michael Intrator: If memory and it is historically been a cyclical business, right? We have seen these waves of demand driving up the cost for memory and then it collapses and then it drives it up. It's a very boom and bust business. It's cyclical in its nature because the fabs are so capital intensive that people invest in the fabs, build a ton of capacity and then overbuild if there's any type of downturn.","offset":1592,"duration":29},{"text":"Michael Intrator: And we've seen that cycle again and again. What's happening right now is the confluence of two things, right? One is is with all the demand for artificial intelligence and the corresponding demand for compute and the ancillary services around the GPU, the demand is through the roof. That's number one. Number two is is that there was probably an investment cycle that needed to happen back in 2023...","offset":1621,"duration":30},{"text":"Host: Got it.","offset":1651,"duration":1},{"text":"Michael Intrator: ...that would have brought on the necessary fab capacity to be able to serve... impossible to predict what's happened just with energy it's impossible to predict what just happened and now people are chasing energy, the data centers are going where the energy is, it's not based on real estate it's based on where there's some wind.","offset":1652,"duration":17},{"text":"Michael Intrator: And and anytime you have a very not anytime but many times when you have a a capital intensive business like you know building fabs you will get this boom and bust cycle just like in energy they overbuild and you know fiber...","offset":1669,"duration":16},{"text":"Michael Intrator: ...yeah I mean there's there's a lot of examples of that. Our approach in some ways when you look at that it's a beautiful aspect of capitalism that we're able to have a boom bust cycle that we're able to weather it right?","offset":1685,"duration":15},{"text":"Host: If you think just like capitalism from first principles something like that happens and we have too much fiber, it creates an opportunity for Google to buy it all up or the next person.","offset":1700,"duration":8},{"text":"Michael Intrator: Listen the the you know it does it does a lot of things having a boom bust cycle: it clears out the underbrush, the strongest companies will be able to survive and take advantage of that and it sows the seeds of future business. The other thing that it does is you put that infrastructure into the ground, you put the fiber into the ground, which became the backbone of how you know we watch movies every day and how we you know communicate and how we talk on a Zoom and you know COVID and all of these things were based on that infrastructure that was available to be consumed.","offset":1708,"duration":36}],"startTime":1424},{"title":"Falling Costs and AI Enablement","summary":"Comparing AI to the broadband build-out, Michael notes how rapidly falling token costs will empower individuals to build unprecedented new businesses.","entries":[{"text":"Host: People don't recognize this fact. If you the the premise of YouTube from the founders who I knew: Chad Hurley and his other partner, they basically had the realization \"at this curve storage is coming down so quickly we could offer free unlimited uploads and bandwidth is coming down so I guess we don't have to charge people for sharing a video online.\"","offset":1744,"duration":22},{"text":"Host: Before that if your video went viral people are gonna have their minds blown but your server would turn off and it would say \"this person you know needs to pay their bill\" because they were getting charged for carriage by the megabit going out. Yes. I mean look and and you know these the business models change and evolve and you know like you said Moore's Law and and certainly Jensen will talk about the fact that like what what is going on within the the accelerated compute space dwarfs Moore's Law right?","offset":1766,"duration":34},{"text":"Michael Intrator: And all of that is going to lead to more opportunity to build more companies that are going to do things like YouTube did which has really changed the world.","offset":1800,"duration":11},{"text":"Host: Yeah I mean the the concept that I don't know if it was a a million hours being uploaded every hour or minute... but at some point Susan Wojcicki, rest in peace, said told me just like how much was being uploaded every minute and it made no logical sense until you realize well there's three billion people, two or three billion people in the service and 1% upload or 0.1 10 bips upload and it's like okay one in a thousand people upload. It's a big it's a big denominator.","offset":1811,"duration":31},{"text":"Michael Intrator: I was sitting on a panel with Sarah Friar, CFO of OpenAI, and she everyone once in a while she really puts out like interesting information. And so she was talking about the cost of a million tokens when ChatGPT 3 came out and it was $32 and change. And now a million tokens costs nine cents.","offset":1842,"duration":25},{"text":"Michael Intrator: Right and so you just see like like the incredible power of how the capital market, how capitalism is fueling engineering and fueling competition. And it's become...","offset":1867,"duration":15},{"text":"Host: It's become recursive now. I mean these models, if you say to the model \"hey make yourself more efficient spend less money and lower the cost of tokens,\" it'd be like \"okay captain.\" I don't know if you saw Karpathy's recursive thing last weekend but it's like now civilians who've never worked in a language model done computer science like \"I'm gonna try to do something recursive this weekend.\"","offset":1882,"duration":23},{"text":"Michael Intrator: You know it's one of the things that I talk to you know the other founders about you know and is like when you think about some of the things that AI does right? It's lowering the barrier to operations. So if you have a good idea or a great idea you can open up your model and you can tell your model, you can vibe code it, you can do all kinds of different things and create things that never existed before. That's amazing right?","offset":1905,"duration":29},{"text":"Michael Intrator: Like that's bringing down this incredible barrier that kept human creativity contained and now all of a sudden this whole new vector of medical research or different approaches to baseball cards or whatever you want if you've got a great idea if you've got a new creative idea that's the valuable kernel right now that allows you to to build new things and to create new things and I just think that's incredibly exciting right?","offset":1934,"duration":30},{"text":"Michael Intrator: Like you're bringing the minds of eight billion people a tool that allows them to overcome what was insurmountable for forever. For humanity. Yeah. It's a bright new future Michael, appreciate you sharing the information with us and the vision.","offset":1964,"duration":15}],"startTime":1744},{"title":"Perplexity's Agentic Evolution","summary":"Aravind Srinivas details Perplexity's journey from an accurate answer engine to a full computer interface that orchestrates multiple AI models seamlessly.","entries":[{"text":"Host: I am really delighted to have Aravind Srinivas on the program.","offset":1979,"duration":6},{"text":"Aravind Srinivas: Thank you for having me here Jason.","offset":1985,"duration":2},{"text":"Host: It's so great. I want to go through three stages in which I fell in love with your product. The first phase was I could go in pick my language model if I want to use OpenAI, if I want to use Claude, whatever it was. That was like a real unlock for me. And on the side sidebar I noticed you had done essentially like what Yahoo did in the early days: finance, sports.","offset":1987,"duration":33},{"text":"Host: And when I pull my Nick game up it gave me a live version of that. When I pull my stocks up it summarized the news in real time and I was like \"wow this execution's great.\" And I I kind of made you my front door to different models and it made it easier for me to check in. Then you came out with the Comet browser and I was like \"holy cow, I can give this a series of instructions: go to my LinkedIn, find everybody from this company, put them into a Google sheet,\" and boom you were the first out of the gate with that.","offset":2020,"duration":24},{"text":"Host: And then just the last couple of weeks I had been claw-pilled and using open Claude but you came out with Computer. And I started using Computer and boy it's good. It's a really strong start. allowing me to do repetitive tasks, very similar in some ways to Cowork from Claude or basically an engineer or developer using it. So are these the evolution of the company and I should think about it that way?","offset":2044,"duration":29},{"text":"Host: But how do you look at Perplexity now? You have a very loyal fan base. You're making a lot of money, I don't know if you disclose it but I think it's hundreds of millions to billions. You can tell us. But what is Perplexity in the face of, wow Claude's having a great run, OpenAI still doing strong, Grok doing very well, Gemini coming on strong? There's like six or seven of you and you happen to be one of my top two right now.","offset":2073,"duration":25},{"text":"Aravind Srinivas: Thank you. First of all, thank you so much. Perplexity has always been built for people who are always looking for the extra edge, the curious people. So it's very natural that you are one of our power users. One common theme for us for the last three and a half years is accuracy. Perplexity wants to be the company that's building the most accurate AI.","offset":2098,"duration":25},{"text":"Aravind Srinivas: So when you want to give somebody answers, accuracy is very essential for building trust because only then the user is going to ask the next set of questions. It turns out it was a great idea to give AI access to the internet to be accurate, so that's the Perplexity Ask product. It turns out it's a great idea for AI to have full access to a browser so that it can be accurate when you task it to go do something that you would do yourself on a browser... agentic browsing, Comet.","offset":2123,"duration":26},{"text":"Aravind Srinivas: Now the last phase is it turns out it's a great idea for AI to be given a full access to a computer so that it can do whatever you do on a computer on its own. Essentially becoming the computer itself, an orchestra of everything AI can do today. Every single capability each individual AI model has, be it GPT or Claude or Gemini or anything else, an orchestra of all those capabilities, that's what Perplexity Computer is.","offset":2149,"duration":32},{"text":"Aravind Srinivas: And all these sub-agents that are running inside Computer are the musicians. The models are essentially the instruments and there are like hundreds of models out there, each having their own specialization. Some are good at coding, some are good at writing, some are good at multi-modal, visual synthesis, image generation, video generation, audio. But what matters is the end output, the music you play. That's the work AI gets done for you and that's what Perplexity Computer is. The AI itself is the computer now.","offset":2181,"duration":30}],"startTime":1979},{"title":"Local Execution and Privacy","summary":"Aravind introduces Perplexity Personal Computer, a hybrid approach that handles sensitive data locally on devices like a Mac Mini while securely routing broader tasks to the server.","entries":[{"text":"Host: Still lives inside of a browser. Have you considered giving it desktop root access? That feels like the next place this is going but that comes with a lot of security issues, a lot of trust issues. As you mentioned trust is paramount getting the right answer is what builds it but also not getting hacked and not having it delete your files. So how do you think about root access to my Windows machine? Obviously iOS they won't let you, but with an Android phone it would let you. So do you have that in the work?","offset":2211,"duration":31},{"text":"Aravind Srinivas: Yes. so we announced something called Personal Computer. Perplexity Personal Computer. That's essentially going to take all the trust and reliability and the server-side execution of Perplexity Computer but synchronize it with your local computer so that you can use it from your phone. And we're going to do this with the Mac Mini where you synchronize your computer with the Mac Mini so that becomes your local server.","offset":2242,"duration":31},{"text":"Aravind Srinivas: All the agent orchestration that has to do with your local private data will run on that local orchestration loop, that runtime with the Mac Mini. Not on your servers, not on Anthropic. Exactly. It could still ping frontier models if it needs to, with your permission. But it will be orchestrating everything on your local hardware.","offset":2273,"duration":12},{"text":"Aravind Srinivas: And if it needs to run on the server-side hardware, if you don't want very complicated long-running tasks to be running on your local hardware, you can delegate it to run on your server-side computer, which is again only accessible to you and you alone. So that way we're going to bring this perfect hybrid of trustworthy compute... a hybrid between local and server side. And you'll make it easy to do it just be abstracted you install one executable boom it's done.","offset":2285,"duration":26},{"text":"Aravind Srinivas: Exactly. It's like Open Claude for dummies. Nobody needs to learn how to use it, nobody needs to manage API keys, nobody needs to manage separate billing across like 100 different services, figure out what you can give access to and not access to. We take care of that. So the Steve Jobs way of doing it, you know end to end integration.","offset":2311,"duration":20},{"text":"Host: And how do you think about local models? I have started running Kimmy 2.5 on a Mac Studio, not as good as Claude or Gemini or Grok, but you can probably do about 80% there for free essentially. And so that's quite compelling considering some of my other bills: Claude and and stuff are getting expensive. So do you have one of those you started testing on your local Mac Studio? I assume you have a Mac Studio and you're doing this yourself?","offset":2331,"duration":26},{"text":"Aravind Srinivas: Yeah. Or now I don't know if you saw Dell and NVIDIA announced a giant workstation... is it the 3800? something like that with 750 gigs of RAM.","offset":2357,"duration":15},{"text":"Host: What do you think about the desktop going back to workstation slash server status?","offset":2372,"duration":7},{"text":"Aravind Srinivas: I think it's very promising. My prediction is it initially start off as a sub-agent. So whatever you need to go like your tax returns, your personal photos, your emails, your calendar, all that stuff, those local apps, your personal notes, very personal notes, you can make sure that the models that access those tokens will be running on your local hardware if you want to, if you're that privacy conscious.","offset":2379,"duration":32},{"text":"Aravind Srinivas: And more complicated stuff that accesses your data that's already on the server side, example your Google Calendar, your Gmail, this is personal data still, but an AI runtime can access that through your connector: your Google Calendar connector, your Google Workspace connector. And that could run on the server side because anyway the data's on the server it's not even lying on your device.","offset":2411,"duration":23},{"text":"Aravind Srinivas: So that sort of hybrid orchestration is where we're headed to. I don't think it's a dichotomy between fully local versus fully server. It's all about choice. And anyway when you're on your phone you want to you don't care actually which server that workload's running from because it's not going to be able to run on your phone anyway. The chips need to exist on a Mac Studio or a Mac Mini... or on the server. Or this new Dell that's coming out.","offset":2434,"duration":26},{"text":"Host: And I really think the idea of spending $10,000 on a powerful desktop will appeal to people if it lowers their $500 a month Claude bill. This is an incredible savings plus you get the benefit of privacy and not educating the language models on your personal data.","offset":2460,"duration":19},{"text":"Aravind Srinivas: Yes. and it's going to be like you're buying a refrigerator. your your internet modem... like the cost for these will eventually go down but it's not going to feel like you're wasting your money. every AI every home has a lot of other sensors that runs your home. that'll also be part of this orchestration loop.","offset":2479,"duration":23},{"text":"Aravind Srinivas: So so that's where it gets exciting because now you can just dictate something to your phone and that can control your entire home. So that's the dream that everybody has and all that orchestration loop can run on your local hardware, no problem.","offset":2502,"duration":12}],"startTime":2211},{"title":"AI as an Operating System","summary":"A discussion on how AI is becoming an objective-driven operating system, operating autonomously over Linux without needing a traditional user interface.","entries":[{"text":"Host: And I'm curious what you think of the operating system. What's eventually going to be the operating system of this workstation?","offset":2514,"duration":10},{"text":"Aravind Srinivas: AI is the operating system. Like earlier in the traditional operating system you would execute programmatically. Now you start with objectives not specific instructions. You come up with a high-level objective: go build this website for me that you know takes all the transcripts of all in podcasts and tracks the stock price just before the podcast and after and charter it for the Max Seven and charted over time.","offset":2524,"duration":27},{"text":"Aravind Srinivas: You can so that's an objective. But individually it's running a file system, a code sandbox, access to the internet, it's having like its own HTML tools and like so I think that's basically where you know model, systems, and files, and connectors are all coming together. You would think of that as an OS except you're operating at an abstraction above that where you're thinking in terms of objectives.","offset":2551,"duration":22},{"text":"Host: Yeah. and does it need to eventually become its own operating system in your mind?","offset":2573,"duration":5},{"text":"Aravind Srinivas: It could be. Like people could think about it as like \"yeah I have a my perplexity computer running all the time.\" Whether it essentially runs on Linux machines right now on every server side computer is a Linux machine. So I think Marc Andreessen tweeted this right after our release that \"turns out Linux computers was the right idea. desktop Linux computers are finally going to work.\"","offset":2578,"duration":21},{"text":"Host: Yeah I mean they're stable, they're customizable and you're not at the mercy of Apple's desire to contain the experience or Microsoft's surface area for hackers. You build something rock solid and it does feel like Linux might actually become the the eventual winner.","offset":2599,"duration":23},{"text":"Aravind Srinivas: Correct. It may not need to have a front end. That's the thing. You could you could access the Linux machine on your phone which could be running iOS or Android doesn't matter. The actual valuable runtime is running on Linux on the server.","offset":2622,"duration":14}],"startTime":2514},{"title":"Enterprise Growth and Margins","summary":"Perplexity is seeing massive adoption in the corporate sector through integrations like Slack, while maintaining positive gross margins through efficient model routing.","entries":[{"text":"Host: You've done great as a consumer company lot of love there. now I'm starting to see corporations with Computer starting engaging. In fact, you'll be happy to know this last week I took two people in my back office and I said \"stop working on Open Claude, your job is to do the back office automation at our venture firm only using Perplexity Computer.\" And they were like \"oh okay, it doesn't talk well in Slack, it doesn't have an agent in Slack.\" I was like \"it will. I'm going to see Aravind, I'll talk to him about that.\" So we need a really strong Slack connector.","offset":2636,"duration":37},{"text":"Aravind Srinivas: It's already out. It is? Okay great. Computer exists as a Slack bot right now that you can add to your Slack workspace on the enterprise plan and our entire company works like that. People are talking more to Computer on Slack than to other people.","offset":2673,"duration":15},{"text":"Host: Okay in our first volley we were sending reports in but it wasn't interactive. That's perfect. So now you've got your company going in two different directions: this incredible consumer run you have... how many people are using Perplexity today?","offset":2688,"duration":12},{"text":"Host: Using the product every month?","offset":2700,"duration":1},{"text":"Aravind Srinivas: Several tens of millions.","offset":2701,"duration":2},{"text":"Host: Tens of millions of people. That’s very much similar to the trajectory of the Google and Yahoo consumer business. Now you’ve got corporate. How are you doing on the corporate side? Thousands of companies?","offset":2703,"duration":11},{"text":"Aravind Srinivas: That’s the fastest growing uh business for us. Uh, it’s growing faster than the consumer in revenue and things like Computer unlock entirely new possibilities. For example, we’ve saved more than $100 million dollars for our enterprise max customers who are on the highest tier of enterprise.","offset":2714,"duration":17},{"text":"Host: Explain what that is. What does it cost? 200 a month per person?","offset":2731,"duration":3},{"text":"Aravind Srinivas: So there are two tiers. One is the enterprise pro, which is $40 a month. And there's the enterprise max, which is $400 a month. And that- that- and- and on Computer after you run out of your credits, you would pay for the tokens, you pay for the usage.","offset":2734,"duration":17},{"text":"Host: Are you making money on the $400 a month, $5,000 a year one, or at this point in time are people going so crazy...","offset":2751,"duration":6},{"text":"Aravind Srinivas: Every- so our- one thing that Perplexity has is every revenue we make, unlike certain other wrapper companies, every revenue Perplexity makes has positive gross margins.","offset":2757,"duration":11},{"text":"Host: Got it.","offset":2768,"duration":0},{"text":"Aravind Srinivas: Because uh we’re not just selling tokens. Right. Most of our revenue is recurring because people are paying a subscription fee. And because we route through multiple different models, we're very efficient in terms of how we spend on the tokens.","offset":2768,"duration":16},{"text":"Aravind Srinivas: Because we have all this advantage with RAG and orchestration and search, we don’t actually need to blow up the context window of the models. Yeah. As a result of that, we have positive gross margins on all the revenue we make. Every single penny we make, we make profits on that. The- overall the company's still yet to be profitable, but we're working towards that.","offset":2784,"duration":20},{"text":"Host: You’ve had the opportunity to exit. A lot of rumors, Apple, other people, were like, hey, this is a great team. How many people on the team now?","offset":2804,"duration":9},{"text":"Aravind Srinivas: About 400.","offset":2813,"duration":1}],"startTime":2636},{"title":"Independence and Model Routing","summary":"Aravind explains why Perplexity declined acquisition offers, preferring a 'Switzerland' approach that gives users the best specialized outputs across multiple frontier models.","entries":[{"text":"Host: Yeah. You- you’ve got a very coveted team. You obviously understand consumer, you obviously understand business. It’s a product-driven organization. Reports are you declined, but the world’s getting hyper-competitive here. How do you keep up as a 400-person organization when you’ve got Sam Altman over here raising $100 billion dollars?","offset":2814,"duration":23},{"text":"Host: You know, and then you have Elon putting data centers in space and merging with SpaceX and Twitter. You have Google with unlimited resources, Amazon getting in the game, and obviously Gemini, uh, very strong product, and Google really good at consumer. I think we’d all agree Facebook and Meta haven’t figured it out yet, except maybe for serving us better ads, but they haven’t figured out the consumer case yet. But they’ll copy it, they always do.","offset":2837,"duration":27},{"text":"Host: How do you look at the playing field? Because the degree of difficulty... this isn’t playing checkers or... this is like playing against the ten best chess players in the world. That’s what you have to do every day. So how do you think about it, long-term an independent company? Do you think you’ll need to join forces at some point? And why didn’t you take the deal? This- these deals were incredible that you got offered.","offset":2864,"duration":25},{"text":"Aravind Srinivas: So uh one advantage we have that all these companies you mentioned don’t have is the multi-model orchestration. We’re like Switzerland, we don’t have to have one horse in the race. If GPT wins, Gemini wins, Claude wins, Llama wins, it doesn’t matter to us. Or even open-source models can win. No problem.","offset":2889,"duration":22},{"text":"Host: And you have them on the service. You have DeepSeek and Kimi?","offset":2911,"duration":2},{"text":"Aravind Srinivas: We have Kimi, we have Nemotron, and we have uh a lot of usage of Qwen, Alibaba Qwen, silently under the hood. So for us like that advantage of being able to take the best in each model and give the user the orchestra of everything they can do, I don't think any of the companies you mentioned can do that.","offset":2913,"duration":25},{"text":"Host: Right, nor would they.","offset":2938,"duration":1},{"text":"Aravind Srinivas: Nor would they. It- it makes no sense for them. It would be an admission that all the data centers and CapEx they've built out means they still couldn't produce them the best model. And uh Dario, uh CEO of Anthropic, said recently in an interview uh that models are specializing. Towards the beginning of last year, people thought models are going to commoditize. But towards the end of last year, people models started specializing. Even within coding, uh Claude Code and Co-pilot have very different capabilities.","offset":2939,"duration":37},{"text":"Aravind Srinivas: Our iOS engineers love using Co-pilot. Our backend engineers love using Claude Code. Yeah. So even within a specialization like coding, models have their own unique specialties and there are many other use cases outside coding where different models are good at different things, which means the orchestra conductor that has no one model to- horse in the race can win by providing a very unique value and service to the customer that each of these amazing names that you mentioned cannot.","offset":2976,"duration":35},{"text":"Host: And so you’re buying tokens wholesale from them and then you’ll charge customers to do it or do you think it’s all-in?","offset":3011,"duration":9},{"text":"Aravind Srinivas: We're going to take care of all their orchestration. Yeah. So you don't have to manage tokens across different models.","offset":3020,"duration":6},{"text":"Host: 'Cause I authenticate a couple of my different accounts, my pro accounts, into Perplexity. But is it- I- I don't have enough knowledge to know if you're abstracting that and people can just search across them and it's part of their Perplexity subscription?","offset":3026,"duration":15},{"text":"Aravind Srinivas: No, we're not bundling subscriptions from other AIs. We just ping the models directly. Got it. What you get in us is the Perplexity orchestration. Got it. The harness. Right. So the- when- when- when models are kind of specializing, the- there's a bigger value in the one who knows how to build a great harness right that can take the best in each.","offset":3041,"duration":25},{"text":"Host: Does it auto-route today or do you still have the dropdown somebody's gotta pick?","offset":3066,"duration":4},{"text":"Aravind Srinivas: It definitely auto-routes the best model for each prompt, but we also give users the flexibility to pick whatever model you want.","offset":3070,"duration":8},{"text":"Host: What do you think of- I’ve seen a bunch of startups hack this together, but doing the same query across multiple...","offset":3078,"duration":6},{"text":"Aravind Srinivas: We built a thing called Model Council.","offset":3084,"duration":1},{"text":"Host: Model Council, yeah.","offset":3085,"duration":1},{"text":"Aravind Srinivas: So that's one of the- one of the modes on Perplexity where I saw Jensen say in one of his interviews that he he puts the same prompt in five different AIs and sees what each of them says. Yes. Everybody does that, yeah. But then you still have to apply your biological compute to read every answer and then figure out where they differ.","offset":3086,"duration":22},{"text":"Host: It’s like talking to five lawyers about your trust or your... five different doctors. Yeah. Five different doctors and trying to figure it out. Exactly. It’s dumb.","offset":3108,"duration":10},{"text":"Aravind Srinivas: So the Model Council is a feature we built where it would not just give you the answers of each model, but it'll tell you exactly where they agree, where they disagree, and where the nuance is.","offset":3118,"duration":12}],"startTime":2814},{"title":"Product Velocity and Bespoke Software","summary":"Leveraging AI to ship code incredibly fast, Perplexity's tools can now autonomously build custom software, compile research, and draft internal corporate memos.","entries":[{"text":"Host: And that’s in the interface, Model Council? I didn’t know it was there. It’s there. I mean, you- you release product at a pretty great cadence, huh? How- where did you learn that and what’s your philosophy of shipping product?","offset":3130,"duration":11},{"text":"Aravind Srinivas: Our philosophy is like speed is our moat. Like, you know, again one of the things that big companies cannot do is move at the speed we do, serve customers at the speed and qual- it's very hard to maintain quality, speed, and trust at the same time. Like Apple takes a long time to ship anything 'cause he's very worried about people not trusting them. Uh and so some companies are bureaucratic and they just take forever to ship something. They don't maintain what they ship. They they'll make a big deal about an event, but nobody even knows how to go and use that feature. Yeah, they get abandoned. Exactly.","offset":3141,"duration":39},{"text":"Aravind Srinivas: So Perplexity has those advantages by being very small. And towards the end of last year, we found that like AI coding tools have made it much faster for us to ship things. Which is honestly one of the reasons why we built Computer because now even non-engineers are shipping code here by just pinging a Slackbot and asking it to fix bugs. Yeah. So the the iteration has just been like exponential.","offset":3180,"duration":29},{"text":"Host: The- the moment I had where I became \"claw-pilled\" was when I was working with it and I was like, hey, I want to build my network. I know these 20 people in Japan I had dinner with them during my recent trip. I want to know who they know, so check out LinkedIn and other things and who they’re associated with and make me like a mind map of it. And then the next trip, I want to meet with the next circle of, you know, those connections. So I start asking... it’s like, okay, I got the results. I was like, great. Um, and it said where do you want me to put them?","offset":3209,"duration":33},{"text":"Host: And uh I was like well where can you put them? And it said \"Why, I can put it in a Google Sheet, I can put it in a Notion table, I can put it here, I can give you a PDF, I can give you a CSV file, or I could write you a CRM.\" And I was like, yeah, sure, make me a CRM system. And it made a CRM system. And I think that becomes... and I think maybe one out of a thousand people working with AI have had that experience. Yeah. Maybe it’s one in 10,000 where your agent says \"I’ll make you bespoke software.\" Have you had that yet and and do you see that as a part of Computer that when a person needs a spreadsheet, you don’t launch Excel or Google Sheets, you just pop up a spreadsheet?","offset":3242,"duration":41},{"text":"Aravind Srinivas: Yeah. Well, we have a board meeting tomorrow. OK. I’ll come. I'll pitch it to the board. Sure. Uh our Computer- Computer made the memo.","offset":3283,"duration":10},{"text":"Host: Oh wow.","offset":3293,"duration":1},{"text":"Aravind Srinivas: Yeah. And uh we had a partner meeting to pitch a partnership idea and uh earlier we would have a design team do the whole deck. Computer just one-shotted it. I had a press briefing with a bunch of journalists. My comms person would usually... Sorry about that. Oof. Brutal. And then my comms person would usually uh give me a memo. Dossier. What to say. Computer one-shotted him.","offset":3294,"duration":24},{"text":"Host: So- it’s crazy. It's crazy. And the context is so good because the memory’s getting better, yeah?","offset":3318,"duration":7},{"text":"Aravind Srinivas: Yeah. So it’s like, I know that journalist from the last time. Yeah. I know the board meeting. I have all the previous decks. Yep.","offset":3325,"duration":6},{"text":"Host: When did that happen?","offset":3331,"duration":3},{"text":"Aravind Srinivas: I think it it happened with Opus 3.5. Uh-huh. Opus 3.5, yeah. That was the inflection point when models were start starting being amazingly good at orchestration and reasoning and tool calls. And uh Claude Code brought in this new idea in AI that everything can happen inside a sandbox, a console, a terminal, with access to tools where tools are just command-line tools. Yeah. They don't even need to have graphical user interface. So when you did that and when you organized around files and subagents and skills and CLIs, the model start started becoming very good at handling the context. So the context window no longer became a problem. It just put whatever necessary into the context whenever it wanted to and dump them dumped them away when it wanted to. Yeah. And that made it like suddenly so good at doing very long orchestration tasks.","offset":3334,"duration":58},{"text":"Host: Yeah. It’s- it’s pretty crazy. I have every episode of This Week in Startups, all the transcripts, and then all of All-In...","offset":3392,"duration":9},{"text":"Aravind Srinivas: That was one of the tasks I did by the way. I can send it to you. I asked it \"I want you to download every All-In podcast uh since the beginning. Yeah. And I want you to take a mention of all the public companies they mentioned during their episodes. Yes. I want you to have a histogram of the counts. And I also want you to chart it across time. And then I want you to analyze the impact on the stock price. And the sentiment of what we said. Exactly. And it did! Like it clearly said around Google’s stock going up, yes, prior to that you guys were talking a lot about Google. Yes.","offset":3401,"duration":30},{"text":"Host: And I said I made a bet publicly on the thing. I said I am buying a bunch of Google because I believe even though they’re behind, it’s because they’re too precious. You were kind of mentioning a company that might be too precious at times and doesn’t release. I was like that’s that company. They need to release more. Yeah. And uh I told Sergey, I was like \"Like give us the good stuff.\" And they started giving us the good stuff.","offset":3431,"duration":17},{"text":"Aravind Srinivas: Not only did it do that, it literally gives you the timestamps of every single mention and then I can go click on it and actually hear that moment. Yeah. Sweet. Yeah. So that's when that's when I was like, damn, like this I would have had somebody do this as a week-long project.","offset":3448,"duration":15},{"text":"Host: It would have been 10 hours a week of researcher. I- I'm experiencing the same thing. When I do research notes, I've created my own uh like mega prompt. Yeah. And it will go and like tell me where you worked before and who's in your circle, who your competitors are, who your friends are, blah blah blah. And then go find- I try to find old podcasts as one of my secrets if you're an interviewer watching. I try to find what was the person talking about five years ago, 10 years ago, and then over 10 years ago. And I've gone into interviews now with Michael Dell and talked about things he was talking about in the '90s. Yep. And it finds me some ancient stuff. Like you would pay a researcher or producer you know $70,000 a year, $80,000 a year to do this and they would have done a third of the job in 10 times longer.","offset":3463,"duration":50},{"text":"Host: Yeah. It’s really gotten weird just in the last six months. What do you think the next six months looks like?","offset":3513,"duration":5}],"startTime":3130},{"title":"Solo Entrepreneurship and Jobs","summary":"Aravind shares his vision of AI tools enabling driven individuals to run highly profitable, autonomous solo businesses, fundamentally changing the labor landscape.","entries":[{"text":"Aravind Srinivas: I think the the dream that what we're going to try to do is help businesses run as autonomously as possible. You know everybody talks about this AI is going to create this one-person $1 billion company. Some people say it's already happened because people pay researchers like 1 billion. But it's not truly moving the GDP by 1 billion. It's not truly creating new value. So the best way to do that is to actually help a small business, people who would otherwise drive Ubers for like extra passive income, yes, to like buy like a Mac mini, set up Perplexity personal computer, and run their business on that or like run it on the server, it doesn't matter. Uh and actually make real money. Hundreds of thousands or even millions a year. Yeah. And uh grow it. Have Computer go and run your ad campaigns on Instagram or Google, integrate with SEM and SEO tools, find new users, and uh integrate with Stripe, charge them, ship new features, have your own like Intercom integration for customer support, and like have those all working while you can be sipping wine in Napa. That's the dream that you know it's- it feels awesome to say. Everybody thinks AI is already there. It's not there yet. Someone has to do that hard work. Yeah. But that's what we want to do.","offset":3518,"duration":80},{"text":"Host: Yeah, it- it’s a great vision because when I watched startups 20 years ago, there were so many checkboxes they had to do. I have to find an office space, I gotta put up a bunch of servers, I gotta hire an HR firm, I gotta hire a PR person, all this stuff. And now I talk to young founders, they got a three-person team, they’ve come out of A16Z, my program Launch Accelerator, whatever it is, Y Combinator. And I’m like \"Okay, you raised a half million, you raised a million. Who are you hiring?\" And they’re like \"Um, I don't know if we need to hire anybody.\" I’m like \"If you could hire somebody, would you hire them?\" They’re like \"Well, I do my own HR, I have this partner, and...\"","offset":3598,"duration":31},{"text":"Host: They’re... I’m like \"How are you doing hiring anyway?\" And they’re like \"Well, I put out an ad and then uh it sorts and ranks the candidates and then it emails the top 10, asks them a bunch of questions, and then I meet with the last two.\" And I’m like \"That’s what a recruiter did!\" Like the entire recruiting job has been abstracted. And like a tool like Computer is going to make that even faster.","offset":3629,"duration":22},{"text":"Aravind Srinivas: There's so much work to do. Uh a lot of connectors, a lot of specific workflows. People don't want to like learn how to write like you know essay long prompts. You know needs to be so quick and fast and autonomous. You just set it up and done. And you have an idea you can turn it into a business and start making money.","offset":3651,"duration":18},{"text":"Host: Yeah, it’s- it’s an incredible future uh and it feels like it’s right here. Do you- how do you think about job displacement because you’re actually making the tool that enables people to be a solo entrepreneur and get to a million in revenue, but it’s also the same tool that doesn’t require them to hire, and we’ve had this debate a million times on the podcast. Do you- I’m wondering if like me you have moments where you’re like \"Oh my God, this is really terrifying, a lot of people are going to lose their jobs really fast.\" And then \"Oh my God, you can learn any skill you want and all the things that were hard are now easy.\" I- I go back and forth. I’m 70-80% super positive about this, but I do worry about like 20% of the time I’m a little worried. Where do you sit?","offset":3669,"duration":45},{"text":"Aravind Srinivas: I mean America's always been about like entrepreneur entrepreneurship right like we've been about like trying to build new things discover new things go explore. Uh I think this whole like Henry Ford came and built factories and brought in jobs and things like that and like put people into a box. But uh I think the reality is people most people don't enjoy their jobs. They're doing it for money. Exactly. So there's suddenly a new possibility, a new opportunity to go use these tools, learn them, and start your own mini business and if it pays for your needs for a year or multiple years and lets you have a high-quality life and good work-life balance and true feeling of agency and ownership and passion to like get your ideas out there. I think that even if there is temporary job displacement to deal with, that sort of a glorious future is what we should look forward to.","offset":3714,"duration":55},{"text":"Host: I- I think you’re exactly right. If there will be some displacement, but then there’s also going to be so many opportunities open up. And it requires the individual to not be passive. Exactly. They have to be rugged individualists. They have to be resilient. And they have to be resourceful. And I think once you start playing with these tools, that’s what happens. Exactly. You- you all of a sudden feel...","offset":3769,"duration":18},{"text":"Aravind Srinivas: It brings out the best in you if you truly are in a good space.","offset":3787,"duration":3}],"startTime":3518},{"title":"Comet Browser and API Access","summary":"With the launch of Comet for iOS, Aravind and the host advocate for social networks to offer paid API access, allowing AI agents to navigate the web smoothly.","entries":[{"text":"Host: Yeah. Yeah. And then today uh Comet for iOS is out?","offset":3790,"duration":4},{"text":"Aravind Srinivas: Yeah.","offset":3794,"duration":0},{"text":"Host: I’m a Comet super fan. I required everybody... you were nice enough when I I emailed you, I was like \"Can you send some licenses?\" You sent- you may not remember, you sent me a bunch of licenses. I said \"Everybody put this on\" because it was $300 a month when you first came out with the Comet browser. Now it’s free, I think, for all users? Highly recommend it. Highly recommend getting a pro account. It’s only 20 bucks a month to get into Perplexity, which is a joke, so you can get on board for nothing or a little- less than a dollar a day. But what does iOS allow me to do and and how does it connect to Computer 'cause that’s another thing I’m having. Claude Code, uh Computer, they there’s not a good enough integration with this mobile device yet.","offset":3794,"duration":46},{"text":"Aravind Srinivas: Yeah. So Computer is already on the Perplexity app, so you can just toggle the Computer and start using it. Uh Comet's uniqueness and Perplexity for the company uh and and the strategy is the fact that you can control the browser. So the browser also becomes a tool for Computer just like your Google Workspace and all these other things. Uh until the whole world is organized around CLIs and tools, there's still a lot of tasks we have to do manually on the web on the browser open tabs fill of forms click on things upload stuff all that stuff if you want to automate you need the browser. You need an AI that can natively control the browser. So that is Comet and that's why no matter how many other tools in the market exist like Open- Open Claude or like Claude Co-worker, executing tasks on the browser on the server side along with all the other things is something uniquely Perplexity can do.","offset":3840,"duration":291},{"text":"Host: Yeah, my dream is that you’ll create an Android app that roots my Android phone. Yeah. And that you just take over and see everything. Because one of the blockers I have now is some of the websites have gotten a little persnickety. I don’t want to mention too many, but Reddit, LinkedIn, these... and like I am a great Reddit user, I’m a great LinkedIn supporter, but sometimes like I need to get my InMail from my LinkedIn and I just need to, you know, find seven people at a company. Is there going to be a solution between the LinkedIns and Reddits of the world and the Claudes and Perplexities? Is how is that negotiation going? You don’t have to speak about any specific ones unless you want to, but it feels like there’s gotta be a solution and I’m willing to pay for it as a user. I’m willing to pay Reddit to allow my bot to show up and behave properly.","offset":4131,"duration":56},{"text":"Aravind Srinivas: Well, I I cannot speak about any particular company, but we're happy to work with anyone, right? So uh I think with Comet our idea is to give people the flexibility to set things up on their own and with any official APIs that anyone's going to offer, we're always happy to put that as part of Computer.","offset":4187,"duration":21},{"text":"Host: Here’s what I think should happen. Let me see if you agree. Um, and this is for Steve Huffman uh at Reddit. I go on Reddit. I do a pro account for 20 bucks a month. And when I do that, I can authenticate whatever tool I want uh to do a series of well-behaved things a certain number of times a day. So it’s not unlimited, I’m not going to scrape the whole site, but I would like it to just let Perplexity or Computer go and just tell me \"Hey, what are people saying on the This Week in Startups and All-In subreddits? Summarize it for me so I get the customer feedback.\" And I would literally name my uh agent and I would say \"It won’t post on my behalf, it won’t vote on my half, just need it to do a couple of little read-only things.\" This would be an easy solution. Or LinkedIn, I would like if you... I already pay LinkedIn like 50 bucks a month. Like they should just let the $50 a month one work with Computer.","offset":4208,"duration":57},{"text":"Aravind Srinivas: Yeah, absolutely. Mean...","offset":4265,"duration":1},{"text":"Host: Okay. This is for Satya Nadella. Let LinkedIn work with Perplexity and the other players and we’ll pay you extra.","offset":4266,"duration":7},{"text":"Aravind Srinivas: Perfect.","offset":4273,"duration":1},{"text":"Host: It’s a revenue stream. Don’t you think API access for customers is a revenue stream?","offset":4274,"duration":4},{"text":"Aravind Srinivas: I think so. I think so. Again I think fundamentally giving users a choice and setting it up as a win-win for both the business and the user is where the world should head to. And and I would say the same thing applies to any any website in the world. Like if if you want an AI to use it on your behalf, it should be okay for- because that's what the user wants.","offset":4278,"duration":24},{"text":"Host: I mean, I have a paid New York Times subscription, like let me go in there and do, you know, whatever 100 searches a day, a week, a month, whatever they choose, but that would make the subscription that much more sticky.","offset":4302,"duration":19},{"text":"Aravind Srinivas: Exactly.","offset":4321,"duration":1},{"text":"Host: All right, Aravind. Love the product. Anybody at home, it’s just tremendous. Go learn Computer and get the Comet browser. It is changed my business for the last two years. Love the product and uh we’ll have you back soon when you launch your operating system and come up with your own server and desktop server, but business is the focus, yes?","offset":4322,"duration":20},{"text":"Aravind Srinivas: Yes.","offset":4342,"duration":1},{"text":"Host: All right, brother. Great seeing you.","offset":4343,"duration":1},{"text":"Aravind Srinivas: Thank you, J-S. Thank you.","offset":4344,"duration":1}],"startTime":3790},{"title":"Mistral's Enterprise Strategy","summary":"Arthur Mensch outlines Mistral's partnership with NVIDIA and its focus on customizing open-source frontier models for heavy manufacturing and financial sectors.","entries":[{"text":"Host: We have an amazing guest, Arthur Mensch here, the CEO of Mistral AI. How are you doing, sir?","offset":4345,"duration":5},{"text":"Arthur Mensch: Great. Thank you for having me.","offset":4350,"duration":1},{"text":"Host: Uh and so you’re here at uh NVIDIA’s big conference. Big announcement. You’re going to be working with NVIDIA to build models, uh to open source them. What is the big announcement here?","offset":4351,"duration":17},{"text":"Arthur Mensch: Well, we’re announcing that we are going to be training the next generation of frontier models with with NVIDIA. Um, it’s something that we’ve been doing uh before with NVIDIA, with Mistral NeMo, something we did like 18 months ago. And the point for us is really to be able to produce the best open-source models out there so that we can actually use those assets to specialize them through products that we do for our customers like Forge that helps us customize the models for the enterprise we work with in engineering, in physics, in science, uh in making them better at certain languages when we work with governments, etc.","offset":4368,"duration":40},{"text":"Host: And and Mistral obviously based in uh France. You’re the leading AI company there. What’s it like running the company and building a large language model in Europe? Obviously there’s regulations and all kinds of considerations, privacy... the French are known for protecting privacy. In the United States, we’re known for taking it away. How is the landscape there and what do you have to deal with there that maybe you wouldn’t have to deal with in America and what’s the pros and the cons?","offset":4408,"duration":27},{"text":"Arthur Mensch: Well, I’d say first we have 25% of our business in the US uh and 25% of our researchers are actually here. So I actually spend a lot of time here as well as in France, as well as in the UK, in Singapore where we are. So of course it’s it’s different markets. Uh it’s markets where you have language which is a topic, uh where there’s much more manufa- manufacturing is a bigger piece of the cake than it is here. Uh and I’d say the our strength has been to also work with European companies that are a bit lagging behind uh and that wants to adopt the technology to to leap forward. And we’ve been able to do that through a forward deployment engineering engagement, through our Forge product, for our Studio product that allows to deploy agents that do end-to-end automation. But on top of that, the thing that we have announced today like Forge is something that is actually being used today uh with customers in the US because they come to us with uh needs for post-training, for making models specifically good at financial services, and uh what’s happening is that we have this product and we can bring the models to specialize them as well.","offset":4435,"duration":70},{"text":"Host: And and so your belief is specialized verticalized models, healthcare, finance, engineering, different verticals, will win the day or a a global model will win the day that does everything?","offset":4505,"duration":14},{"text":"Arthur Mensch: Well, you need general-purpose models to do the orchestration part, etc. But at some point, you enterprise sits on a lot of intellectual property, on a lot of signals coming from physical systems, from factories, from tools. And the- it’s actually not trivial to connect those systems, to connect those data to models that are closed source. If you have open models, you can actually add new parameters, you can make a lot of deeper things that you cannot do with closed models. You can also, and that’s what something that we do, we don- not only do we work at the model side but also at the orchestration side, we sit with subject matter experts to understand their needs and we build business applications that are fully bespoke to their needs by modifying the models, but also modifying the harness on top, etc. So we believe that eventually building on open-source technology is a way to save cost, is a way to have better control because you can sit the thing on every cloud that you want, on your hardware if you want, you can deploy it on the edge if you want. And eventually, uh from a from a customization perspective and from leveraging your decades of IP that you’ve been accruing in financial services, in heavy manufacturing like companies like ASML for instance, they do benefit from working with us because we take their data and we build models that are specifically good for their for their process.","offset":4519,"duration":76},{"text":"Host: And um this training data, using experts to come in and refine a model... most people don’t know this business that well, but this has become a very large part of the industry. Obviously Scale AI was doing it, they went to Facebook, lost a lot of the customer base who didn’t want to um send their data I guess over to Meta. Uh we’re investors in a company called Micro1 that’s doing pretty well in this space. There’s other folks doing it. Explain to the audience what you’re doing specifically for companies and how this training works in a verticalized way and then how you silo that data. Because if you’re working with one customer in aerospace or fintech, they might have a need set but they may not want that training to go to a competitor.","offset":4595,"duration":53}],"startTime":4345},{"title":"Data Segregation and Model Training","summary":"Mistral brings its platform directly to enterprise infrastructure to ensure data privacy, utilizing both subject matter experts and synthetic data to train custom models.","entries":[{"text":"Arthur Mensch: Well, let me give you a few examples. I think overall the data segregation is super important. And the way we have solved that is through a portable platform. So our technology is a set of services, a set of training tools, a set of data processing tools that I can take and that I can put on the infrastructure of my customers. So suddenly from an IT perspective and when we talk to the CIOs, they realize that from security perspective the flow of data doesn't go there's no data flow coming back to Mistral 'cause everything stays there. Now uh the way we then use that technology that has been deployed is that we're going to be working with the teams that is doing image scanning and default detection with ASML for instance. And we're going to be sending forward deployment engineers, scientists, they all PhDs, they know how to train models. And they spend some time with the subject matter experts that can explain how an image is being detected, what how do you detect defects etc. And based on that we're going to work out what kind of data needs to be used to train the models that is going to solve the task in in itself. And so the we send the technology, typically we send a little bit of scientist 'cause you do need that expertise transfer and that knowledge transfer in between our teams and the vertical experts. And then we make sure that eventually our team no longer needs to be there to retrain the models, to get more data access etc. So that combination of data segregation, expertise transfer, knowledge transfer is the one thing that makes us quite unique and allows us to serve the most critical use cases, the most critical processes in industries that actually need to take their data and put it into models for it to work.","offset":4648,"duration":91},{"text":"Host: Yeah, this seems to be once the entire open web what was available legally, gray market, etc., I won’t have you comment on that controversy uh but we we kind of exhausted what’s in the open crawl, yeah?","offset":4739,"duration":17},{"text":"Arthur Mensch: We have.","offset":4756,"duration":1},{"text":"Host: And and it’s time to actually either make synthetic data or actually use experts. Do you believe in synthetic data and where does that work and where does it fail?","offset":4757,"duration":9},{"text":"Arthur Mensch: We use synthetic data as a way to warm up the models. It’s a way to actually be quite efficient at the beginning. If you have a large model and you want to train a small model, you would use you would use your large model to to process and to produce a lot of synthetic data at the beginning. Uh and then but eventually you do need to have human signal. Uh so the human signal is something that is always a bit costly to acquire because you need to talk to the experts, they need to give feedback to the machines. And so at the beginning synthetic data allows you to do the compression to to further compress the models, but at the end you do need to go and get data that is uh produced by humans. So yeah it's a way to have it's it's mostly an efficient way of training models to have bigger models that are used as as teachers for smaller models, but it's not enough and so you also need human signal.","offset":4766,"duration":51}],"startTime":4648},{"title":"Enterprise AI Access Controls","summary":"While hacker culture embraces fully autonomous AI agents, Arthur highlights the crucial need for deterministic gates and role-based access controls in corporate IT systems.","entries":[{"text":"Host: Arthur, we’ve seen um an incredible explosion. We’re sitting here on um AO 52. After Open Claude, the year of our Lord 52 days. When you first saw Open Claude and saw the reaction of hackers, founders, startup CEOs, just the amount of energy and it racing to the top of GitHub with the most number of stars and likes and and all these contributors, what did that say to you as an executive in the space who’s been grinding on this for many years? What what does that Open Claude moment mean?","offset":4817,"duration":36},{"text":"Arthur Mensch: Well, it resonated a lot with what we were doing with our customers uh because pretty quickly enterprise realized that if they wanted to make some gains with artificial intelligence, generative AI, they would need to automate full processes. And to automate a full process as an enterprise, while you can use Open Claude but it’s going to be it’s actually not really enough 'cause you have data problems, you have governance problems, you can't observe the process that is running and you can't control it in in many cases. When you run a KYC process if you're HSBC for instance, one of our customers, uh you will want to have deterministic gates that are going to always do the same thing in a way that is observable and that you can guarantee the CIO that it's always going to go through these gates. And that's not something that Open Claude is providing because it doesn't have this the kind of primitives that you need to work on collective productivity, observable productivity, and to work on mission-critical systems. On the other hand, the autonomy it gives and the autonomy it brings to to people that are just individuals that are hacking together things is a way to also show to enterprise that if you set up the right control plane, if you set up the right sandboxes, if you connect to the right data sources, if you make sure that you your access controls are well-respected, then you can actually unleash the power of agents doing things for your employees and that's going to work, work on the platform 'cause otherwise you will not be at ease when you're sleeping.","offset":4853,"duration":92},{"text":"Host: It is um definitely something you have to be thoughtful about. When I installed it, I gave it just for my agent root access to my Google Docs and my G Suite, my Notion, my Zoom, my Notion, uh and G Calendar, everything. And then I realized wow, I can with my enterprise edition of Gmail, essentially I can just summarize for my entire 21-person investment company every conversation going on in Gmail and then correlate it with every conversation in Slack. And then I realized oh my gosh, there’s compensation discussions going on. There’s a person on a PIP who we put him on a performance improvement plan perhaps or something like that. Oh, I have to make sure nobody else can access this because the power comes from giving it access to data, but with great power comes great responsibility and I think people are learning that in real time.","offset":4945,"duration":57},{"text":"Arthur Mensch: Yeah, it’s a big problem because the enterprise data is not a single thing that you want to put into a single system that is going to be accessible by by everyone. And so you need to have this layer that actually understands what is in the what is in the data. You need to have a semantic of what can actually be proposed to uh HR or what can be proposed to uh engineering. And typically compensation is one of these things. You want to make sure that the compensation data does not flow back to all of the all of the enterprise 'cause you're going to have a lot of problems uh if if that's the case. And so what you actually need and which is hard to do is what we call context engine. So a mapping of where the data sits that comes with a certain number of metadata that is telling you that this data is actually not accessible to this part of the company. And if you actually have someone in engineering that is asking for something related to comp, the thing is actually going to tell you look, you actually can't access that data. So so that's uh that's hard. It's actually hard. You need to rethink entirely the way your IT systems are being connected and at some point you also need to think about your management because your infor- your information flow is completely different today if you're connecting agents together with your data sources than it used to be. And suddenly maybe you don't need that manager whose only purpose was to take information from the bottom and put the information on the top etc. So there's some IT problems to solve and you need the right primitives, you need sandboxes, you need role-based access control and this kind of things. And you have change to do. You need to rethink your entire customer service department 'cause suddenly you actually don't need that much transfer of information operated by humans.","offset":5002,"duration":133},{"text":"Host: All right. Uh you have to go, you got a flight to catch. It is so great to see you, Arthur. Continued success with Mistral.","offset":5135,"duration":6},{"text":"Arthur Mensch: Thank you very much.","offset":5141,"duration":1}],"startTime":4817},{"title":"IREN's Pivot to AI Data Centers","summary":"Daniel Roberts discusses IREN's transition from an early Bitcoin miner into a massive, publicly-traded provider of high-performance AI data centers.","entries":[{"text":"Host: Cheers. We have an amazing guest, Daniel Roberts here. He’s the co-CEO and co-founder along with his brother of IREN. They uh are a publicly traded company. They started in BTC. Welcome to the All-In interview program.","offset":5142,"duration":19},{"text":"Daniel Roberts: Thanks, Jason. Pleasure to be here.","offset":5161,"duration":1},{"text":"Host: Yeah. And so you started in Sydney, you and your brother uh what, seven, eight years ago? And you got in early on Bitcoin and all these Bitcoin- miner miners wanted to have data centers, huh?","offset":5162,"duration":13},{"text":"Daniel Roberts: Yeah, that’s directionally right. So the thesis we saw was this explosion of the digital world, the growth in the online, and at some point the real world was going to struggle. So we set about to build out large-scale data centers. Yes, the first use case was Bitcoin mining. But as we said to our seed investors, use that to bootstrap the platform, generate cash flow, layer in higher and better use cases over time as they emerge. Here we are today with AI. We are swapping out all the Bitcoin for AI chips.","offset":5175,"duration":33},{"text":"Host: When did you first start seeing the demand in the company shift from \"Hey, Bitcoin miners\" \"Well, we need some H100s, whatever it is\" to \"Hey, we’re this non-profit OpenAI\" \"Hey, we’re this research lab, we need some AI compute\"? When did that start hitting?","offset":5208,"duration":18},{"text":"Daniel Roberts: Look, we had a bit of a false dawn, I would say, back in 2020. We signed an MOU with Dell to start bringing out customers in compute. But in hindsight, it was too early. So we went back to Bitcoin, kept bootstrapping the platform. Look, I would say about two years ago and month-by-month, the demand just continues to escalate.","offset":5226,"duration":20},{"text":"Host: And you were in so early that when you were looking at data center space in the United States, you were one of one looking at the space, one of two or three people looking at the space. They they were trying to sell you on space, yeah?","offset":5246,"duration":15},{"text":"Daniel Roberts: Yeah, so we actually develop the data centers ourselves. So we go and find the land, we go and get the permits, we go and at apply for grid connections. And we were doing it at a scale that just amazed people at the time. Like 750 megawatts is our flagship Texas site. Four years ago, was unheard of in the middle of the desert where building these big data centers. The traditional data center industry going \"What are you guys doing?\" And we’re saying \"We believe in the future digitization, high-performance computing, and obviously now today it's paying dividends.\"","offset":5261,"duration":35},{"text":"Host: Yeah, I don’t think anybody could have predicted when ChatGPT came out, Open Claude recently as a turning point um and then, you know, Microsoft, Google, and everybody embracing this. And that’s your big partner, Microsoft.","offset":5296,"duration":17},{"text":"Daniel Roberts: Yes, Microsoft’s one of our early partners. We signed a $9.7 billion dollar contract with them late last year. But as I was explaining to you before the show, that’s 5% of our capacity. So things are busy at the moment.","offset":5313,"duration":12}],"startTime":5142},{"title":"Physical Infrastructure and Labor","summary":"Building huge data centers in remote locations requires solving extreme logistical challenges and has sparked a lucrative boom for skilled tradespeople.","entries":[{"text":"Host: And when you do these buildouts, the big conversation today is not is no longer the number of GPUs put in, it’s just power. Power is the constraint today, yeah?","offset":5325,"duration":14},{"text":"Daniel Roberts: Look, for many in the industry it is, but for us because we started eight years ago tying up all this land and power, it’s not. So we’ve got four and a half gigawatts. For context, that’s almost as much power annually as the Bay Area uses in its entirety each year. Wow, it’s huge. So for us, the hurdle or the constraint is really time to compute. And that’s emerging across the industry as well.","offset":5339,"duration":23},{"text":"Host: And time to compute means tradespeople coming to West Texas living in a a trailer that you set up to then break ground on a data center, build foundations, build water cooling systems... like this is hard manual labor going on, yeah?","offset":5362,"duration":17},{"text":"Daniel Roberts: Exactly. And this is the whole real-world challenge to respond to these digital exponential demand curves that are unconstrained by the real world in terms of their appetite and it just compounds. You need thousands of people out in these locations that haven’t supported it. You put stress on supply chains. We’re seeing what’s happening with the memory, every aspect of it. So it’s just permanent whack-a-mole, permanent solving fires to try and be bring online this compute.","offset":5379,"duration":29},{"text":"Host: And you get to spend time there. What’s it like when you set up a town or you bring a thousand people or 2,000 people to what’s a pretty much remote small town? You I’m assuming that like when you bring a thousand, there might only be 500 living there right now. So what are those towns like? I’m- it sounds to me like something out of like the gold mining era when people first, you know, went and were prospectors. You’ve become prospecting town?","offset":5408,"duration":26},{"text":"Daniel Roberts: Pretty- pretty much. I mean the barbecue’s great, that was a draw card. But apart from that, look we’ve always had a policy of hiring local, supporting the local community. This year we’re hitting a million dollars in community grants cumulatively. That’s things like local playgrounds, supporting the fire departments. But we will hire locally. Once we can’t find that trade locally, we will expand the radius by 20 miles and hire out of that and so on and so on. Well, that’s very thoughtful, yeah.","offset":5434,"duration":28},{"text":"Host: And- and these folks are coming, say an electrician or a construction worker. They’re coming having built houses or, you know, uh built um corporate offices and now they come for a tour of duty here and the salaries go up massively, but they gotta leave their family for a three-month tour or something?","offset":5462,"duration":20},{"text":"Daniel Roberts: Yes- yes and no because typically where we locate is where there's heavy electrical infrastructure. Ah, where there's heavy electrical infrastructure is typically where old manufacturing and industry has closed down. Ah. So we go down in leverage that sunk CapEx, rehire, retrain local workforces, and bring a new industry to town in these data centers.","offset":5482,"duration":23},{"text":"Host: Has- has that workforce now been completely depleted and we need to train another generation, a younger generation to be generation tool-belt and really embrace the trades?","offset":5505,"duration":11},{"text":"Daniel Roberts: 100%. We’re partnering with universities, trade colleges, absolutely.","offset":5516,"duration":3},{"text":"Host: And you go to a trade school, you got you go to a college, people are getting degrees in philosophy and English literature, they’re going 50k a year in debt, 200k a year in debt. What’s the starting salary for a tradesperson working on a data center doing electrical or construction or HVAC? What’s the ballpark range?","offset":5519,"duration":20},{"text":"Daniel Roberts: Oh look, I won’t talk specifics, but they they are going up, the price is going up, depends on the level, but yes there is a rush for good talent.","offset":5539,"duration":10},{"text":"Host: I’m hearing 150 to like 300k. Am I in the ballpark?","offset":5549,"duration":4},{"text":"Daniel Roberts: The lower end directionally you’re right, yeah.","offset":5553,"duration":2}],"startTime":5325},{"title":"Stranded Renewable Energy","summary":"IREN locates its data centers near massive sources of stranded wind and solar power in West Texas, maintaining 100% renewable operations while relying on the utility grid for stability.","entries":[{"text":"Host: Yeah, I mean it’s incredible when you think about it. There’s concern about \"Hey, AI taking jobs\" and then on this other side of the ledger, can’t find enough talent to- to- to service it. Talk to me about energy sources and how you think about that. Uh President Trump, Chris Wright, the administration, they kind of started with \"Hey, clean beautiful coal.\" Year two they’re like \"All sources matter, nuclear.\" Obviously Nat Gas is plentiful in that area, we obviously got a lot of oil. People don’t know this about Texas. In the United States, the number one uh source of solar installations, yeah? Yeah.","offset":5555,"duration":39},{"text":"Daniel Roberts: So our- so our philosophy's been sustainability from day one. We have used 100% renewable energy since inception.","offset":5594,"duration":6},{"text":"Host: What? 100- wait, how is that possible?","offset":5600,"duration":4},{"text":"Daniel Roberts: We use hydro in British Columbia, we use wind and solar in West Texas. In West Texas where we're located, there's around 45 to 50 gigawatts of wind and solar. Yeah. The transmission line to export that down to the load centers in Dallas and Houston is 12 gigawatts. Oh. So you go and locate to the source of low-cost excess renewable energy, monetize it into this digital commodity, export it at the speed of light.","offset":5604,"duration":27},{"text":"Host: Great arbitrage. And the wind is producing a lot, but they it’s harder to get from those areas where people are willing to put up... I mean, people don’t understand how big West Texas is. It is an incredible amount of land. And you’re coming from Australia where also on the West side, people don’t understand exactly how much pure nature land there is, yeah, undeveloped.","offset":5631,"duration":20},{"text":"Daniel Roberts: So much land. And the issue is distance. You’ve got to spend billions of dollars on this transmission connectivity infrastructure to move that power to where people actually want it. You can build wind farms, you can build solar farms, but if you build it in the desert and no one can use it, then what’s the point? So the whole opportunity for our industry is go to the source of that power and monetize it.","offset":5651,"duration":19},{"text":"Host: So the data centers follow the wind turbines, the solar installations. How do you think about batteries and are you able to put those online because obviously you’re going to have periods where, hey, it’s not a windy day. In Texas, we have very few days when it’s overcast, so that problem’s pretty much solved, but you’re going to have 50 days where the sun’s not beating down. So how do you deal with the demand and and softening that duck curve?","offset":5670,"duration":24},{"text":"Daniel Roberts: We don’t need to. The utility does that on our behalf. So this is why these grid connections are so scarce, so hard to get, and so highly valued, because once you get that grid connection, the utility underwrites all of that variability. They guarantee you 24/7 reliable power. Got it.","offset":5694,"duration":17},{"text":"Host: So on their side, they’re figuring it out. Something goes down and they could fall back even though you’re 100% committed to renewables. If they needed to fall back to- to gas or whatever, they have that ability out there. So you have that as a backup. A lot of talk about or a debate: are we getting ahead of our skis, are people slowing down? There was some talk about the OpenAI project maybe downscaling a little bit. Is OpenAI a partner as well or...","offset":5711,"duration":29},{"text":"Daniel Roberts: Ah, can’t comment.","offset":5740,"duration":1}],"startTime":5555},{"title":"Insatiable Demand and Growth","summary":"Daniel explains that there is absolutely no slowdown in compute demand; the industry remains heavily constrained by 'time to compute' as AI use cases continue to expand.","entries":[{"text":"Host: Can’t comment. Okay. So well we’ll read into that whatever we want. But are there pockets where people are saying \"Hey, let’s slow down\" or is it still gangbusters?","offset":5741,"duration":9},{"text":"Daniel Roberts: It’s right up the end of the spectrum, it's gangbusters. OK. We we cannot meet demand. That's why the whole industry now is around time to compute. There are no idle GPUs in the world sitting in a data center.","offset":5750,"duration":13},{"text":"Host: Yeah. And what’s your take on when software makes... and this is a big um discussion from Jensen himself during his two-and-a-half-hour keynote yesterday... uh we’re sitting here Wednesday, I think he did his keynote on Tuesday. He was talking about, hey, software’s going to make it 50 times more uh, you know, lower the cost of tokens, 50x. And then um transport also contributing to that. When do you think the curve goes from parabolic to simply growing at a ridiculous level? Is- is there a slowdown coming or how are you planning for the future?","offset":5763,"duration":36},{"text":"Daniel Roberts: Look, I think it’s actually the opposite. I think it feeds on itself. So I’ll give you one example. You go into ChatGPT today and you generate an image. You enter the prompt, it’s like the dial-up internet days. It is. Right? It takes minutes and you’re like \"I better get this prompt right.\" Yeah. Finally two minutes later it comes. Now, I’ll give you an example: if we 10x the amount of compute available, which is an enormous task from where we are today...","offset":5799,"duration":14},{"text":"Host: Yeah, it's definitely not material. Listen, continued success and you're hiring a lot of people.","offset":5813,"duration":9},{"text":"Will: Yeah, I think we've got 129 job advertisements up at the moment.","offset":5822,"duration":4},{"text":"Host: All right, so everybody go to the IREN website and listen, the company's doing fantastic. Thanks for spending some time with us here at All-In at GTC.","offset":5826,"duration":10},{"text":"Will: Thanks Jason, appreciate it.","offset":5836,"duration":15}],"startTime":5741}],"entries":[{"text":"Host: I'm here at NVIDIA's annual GTC conference and I'm going to interview four amazing AI CEOs. Stick with us. Our episode is sponsored by the New York Stock Exchange. Are you looking to change the world and raise capital? Do it at the NYSE. The NYSE is a modern marketplace and a massive platform built for scale and long-term impact. So, if you're building for the future, the NYSE is where it happens.","offset":0,"duration":41},{"text":"Host: One of the great companies of the AI era is of course CoreWeave. They're building massive infrastructure for these hyper scalers. And in some ways Michael Intrator, welcome to the program, you're the original hyper scaler. You guys got in very early and secured your, I don't know which GPUs you wound up getting, but you were very early to this trend. How did you get to it so early and how did you build out this, you know, first, I guess at the time, neo cloud?","offset":41,"duration":33},{"text":"Michael Intrator: Yeah, so we didn't really start it as a neo cloud. I was running an algorithmic hedge fund focused on natural gas. And when you build an algorithmic hedge fund, once the algorithms are built, you're really just monitoring it and testing different theses and doing all of that. But there's also a lot of downtime. And we got super interested in crypto.","offset":74,"duration":21},{"text":"Michael Intrator: And you know, we're pretty nerdy, we kind of dig under the hood and we started to get interested in the security layer. We looked at Bitcoin and the mining for Bitcoin and we didn't like it. We just thought that like there's some brilliant engineer that built the ASIC and they're probably going to be better at running it than we are. So we really began to focus on the GPUs mostly because the GPUs were—you can mine Ethereum with them, but you could also do all these other things.","offset":95,"duration":24},{"text":"Michael Intrator: And really right from the start, we looked at the compute as an option to be able to deploy our computing power to different use cases. And so, you know, began the company in 2017, spent the first kind of three years mining crypto, went through a couple of crypto winters. Because we had come from a hedge fund our—we have real chops in risk management and how we think about capital and risk exposure and allocation and all of that.","offset":119,"duration":27},{"text":"Michael Intrator: And so we were really careful around that right from the start. So we weathered crypto winter really well and began to scale the company and immediately started to look for other use cases that you could use this compute for because crypto was pretty volatile.","offset":146,"duration":18},{"text":"Host: Yeah, and crypto was a question mark at that time. I mean, Bitcoin was speculative and there were many other speculative projects. The only other people using this type of hardware: quants, medical research...","offset":164,"duration":18},{"text":"Michael Intrator: Yeah, so a good way to think about it is like the progression of products that we kind of started to work on. You know, first was crypto, but we immediately moved from crypto to CGI rendering and we built projects that allowed folks that were trying to animate and render images, you know, kind of what makes the movies cool, right? And we started to work on that and then we moved to batch computing and started to look at medical research and different ways of using the compute to be able to drive science.","offset":182,"duration":28},{"text":"Michael Intrator: And we just kind of kept moving up the stack in terms of complexity on how GPUs can be used and ultimately in like call it like 2020-2021, we started to really try to figure out how you can go ahead and use GPUs for neural networks. And that was not something that we knew how to do. And so we actually went out and bought a bunch of A100s and donated them to a group that was working on EleutherAI.","offset":210,"duration":30},{"text":"Michael Intrator: They were working on an open-source project with the thought that these guys are taking the GPU compute because we're donating it, they can't really get pissed at us if we're not very good at it initially. And that worked out really well because they kept telling us like we need more of this, you gotta work on that, and that began to really give us an understanding of what was necessary to run scale parallelized computing.","offset":240,"duration":31},{"text":"Michael Intrator: And you know, that we went through it—I kind of feel like buying those initial GPUs was the tuition we paid to learn how to run this business. And then one of the interesting things is all of those guys went back to their day jobs because they were all volunteers working on this, they were like-minded scientists. And when they got to their day jobs, they were all like, \"I want that infrastructure, it's built the right way, that's the way that researchers are going to want to use it,\" and that launched our business. It was an amazing story.","offset":271,"duration":30},{"text":"Host: Yeah, so you went from crypto to these researchers, into academia and deep research. What's the next card to turn over in the poker game?","offset":301,"duration":12},{"text":"Michael Intrator: Yeah, so what became very clear to us very, very early on was that the scaling laws were going to drive... and remember, this is really back in the, you know, 2020-2021 before the ChatGPT moment occurred. And we began to understand that like computing decommoditizes at scale, right? Like when anybody can run a GPU, but can you run a cluster that's large enough to train a model that can change the world? And that's a different question.","offset":313,"duration":28},{"text":"Michael Intrator: And so we really began to think about like how do you go about scaling up your delivery of this computing to clients, larger and larger clients. And that was the next card to turn is to think about it from a... okay, you know, there's a component of this that is going to lean into our ability to access the capital to be able to deliver our solution to the broadest possible audience, to the most sophisticated consumers of this compute.","offset":341,"duration":26},{"text":"Michael Intrator: And that was really the next card is thinking about it as a business rather than as an engineering project to be able to deliver the infrastructure and the software and really everything between... you know, when you're thinking about what we do, we kind of live above the NVIDIA GPUs but below the models. And everything in there, all the software, the integration of software and operations and observability and all the things that you need to be able to build a cloud that's purpose-built for this one specific use case, right?","offset":367,"duration":33},{"text":"Michael Intrator: So we don't do everything, we really focus on one use case which allows us to...","offset":400,"duration":6},{"text":"Host: You don't want to do web servers and things like that?","offset":406,"duration":2},{"text":"Michael Intrator: You know what, they do a great job, it's a great solution, it was a brilliant solution to solve a problem. We just looked at it and said there's a new problem and let's go about looking at this problem and trying to come up with a solution to deliver compute that solves that problem.","offset":408,"duration":13},{"text":"Host: And when did the language model start dialing and calling you for, you know, capacity?","offset":421,"duration":6},{"text":"Michael Intrator: Yeah, so our first... well, our first language model was really Eleuther. But our first like large commercial was Inflection. And so, you know, we worked with Mustafa and Inflection and then we really diversified from there into the hyper scalers, into you know, OpenAI across the foundation models and just kept scaling and scaling with the belief that, once again, the decommoditization of compute...","offset":427,"duration":42},{"text":"Michael Intrator: ...the ability to deliver a solution, and the solution is building super computers that can change the world. And that's really what we began to focus on. That was the lead into training and now the world has gone through you know this moment where we've moved from research into the productization of this. It's beginning to work its way in from the fringe of organizations into the core of what they do. And you can see that every day in the amount of inference compute that is being driven through our infrastructure layer which is just massive.","offset":469,"duration":40},{"text":"Host: And the inference shows you people are consuming it, not just building models, but they're deploying them and utilizing them.","offset":509,"duration":6},{"text":"Michael Intrator: I always think of inference as the monetization of the investment in artificial intelligence. So when we see our compute being used to stand up the massive scale of inference that's hitting our compute every day... and you know inference is when people ask the model a question, it comes back with an answer. That's an inference. Or when you ask the model a question and then to go do something, that's inference, right? And that's actually where you have the opportunity to really drive value outside of the model itself but into the real world. And that's really exciting for us. That's what we like to watch, that's what I like to watch in terms of gauging the health.","offset":515,"duration":44},{"text":"Host: What chips are those?","offset":559,"duration":2},{"text":"Michael Intrator: So really you know we are the tip of the spear in bringing the new architecture out of NVIDIA into commercial production at scale. And so when you know we were the first ones to bring the H100s at scale, we were the first ones to bring the H200s at scale, first ones with the GB200s, and now you've got the GB300s. And one of the things that's amazing and really fascinating for us is people are using the bleeding-edge GPUs to train models as the new architectures come out.","offset":561,"duration":40},{"text":"Michael Intrator: And then they take those GPUs and they move them into different experiments and then over time they move them into inference and they continue to use them in inference for a very, very long time.","offset":601,"duration":10},{"text":"Host: What is the shelf life of a 100 right now? That's been a big debate I think for your company, for Microsoft, and I guess Michael Burry, you know, who you must have known when you were a quant, saying, \"oh my God, the whole industry is... the sky's falling.\" And then we all know in the industry that people don't just throw this hardware away, they find uses for it, the street finds its own use for technology. So what's the reality of the lifespan of these things?","offset":611,"duration":28},{"text":"Michael Intrator: So my take on the GPU depreciation debate is that it's nonsense, right? It's a debate that is being brought to the forefront by some traders that have a short position in the stock and they're trying to talk down. Look, here's what we know, right? When we buy infrastructure, we're a success-based company, right? We're a small company on a relative basis compared to the enormous companies that we're competing with.","offset":639,"duration":28},{"text":"Michael Intrator: And so our clients come into us and they buy compute for five years, for six years. Our average contract is five years. So any commentary by anyone either inside or outside of the industry that this stuff becomes obsolete in 16 months or whatever nonsense they're spewing, it doesn't in any way match up with the facts on the ground. The facts on the ground is they're buying it for five years, right?","offset":667,"duration":29},{"text":"Michael Intrator: If and my approach to this has always been, if people are willing to pay me for it, it still has value. Pretty simple way of approaching it. We use a six-year depreciation, we believe that the GPUs will last in excess of six years, but we felt like that was a fair and reasonable approach to a technology cycle that's moving at this velocity. The A100s, the Amperes, this year the price has appreciated through the year.","offset":696,"duration":22},{"text":"Host: Yeah, why is that?","offset":718,"duration":1},{"text":"Michael Intrator: I think it's because one of the things that happens is as more installed capacity becomes available, you have new companies that come into existence that have new use cases, that have different sized models, that are trying to build new commercial ventures that maybe have been blocked out of the H100 and never had an opportunity to run on that.","offset":719,"duration":22},{"text":"Host: I mean, to make a very simple example for the audience, like you when you trade in your iPhone after three or four years you're like, \"who's gonna use an iPhone 12?\" And it's like, have you been to South America or Africa where you go to the store and you buy an iPhone 12 or you buy the Pixel 7 and it costs $50? That's still got great life left in it.","offset":741,"duration":20},{"text":"Michael Intrator: Absolutely. And so look you know we find these amazing use cases, new companies that have come into existence or existing companies that have integrated new models into their workflow that are able to use the Amperes. And so they keep buying any GPUs that we have available. And once again, you know, the concept that a GPU is no longer relevant or commercially viable after 16, 18 months or two years, it just doesn't make any sense.","offset":761,"duration":31},{"text":"Host: It's obviously farscale. I think sometimes people get caught up in Moore's Law or in just how fast our industry is growing, and that there's so much at stake that big companies are demanding the most recent products that doesn't mean that the lifespan has gotten shorter. It means the opportunity and the surface area of the opportunity's gotten much larger.","offset":792,"duration":22},{"text":"Michael Intrator: Yeah, one of the things is like you know the industry has gotten so much attention for the unprecedented scale of capital that is coming to bear on this. And because of that there tends to be an incredible focus on the companies that are building on these most advanced chipsets.","offset":814,"duration":27},{"text":"Michael Intrator: And the truth of the matter is is you know even within those companies they have a long tail of useful life to provide inference horsepower, to work on other experiments, to do less bleeding-edge activity but still needs to be done. And yeah, I mean rendering comes to mind as well, or yeah, or making images on Nano Banana, like there will be a use for it.","offset":841,"duration":26},{"text":"Michael Intrator: There is a moment of time where maybe the compute to power ratio doesn't make sense. My expectation is obsolescence will be defined by the moment in time where the power in the data center for me will be able to be repurposed for a higher margin than the existing infrastructure provides.","offset":867,"duration":24},{"text":"Michael Intrator: And you know like I said, I fully expect this infrastructure to last in excess of six years, but the standard in the space is really been used with one exception which is Amazon, which is yeah it's six years. That seems like the right schedule. I'm not making it up, that's what everybody's using.","offset":891,"duration":15},{"text":"Host: Yeah, and the energy cost is the opportunity because hey it's just a... we need that space, there's a better reward here, and that might get resold that hardware to somebody else who wants it, a hobbyist or something.","offset":906,"duration":14},{"text":"Michael Intrator: Yeah, I mean or it could be sent some place else where they have more capacity and they can repurpose it there. But I kind of feel like you know we'll deal with that part of the business when we get there. What I know right now is it is extraordinarily profitable, it's very accretive to my company to continue to keep the infrastructure that's been up and running, that's been on these long-term contracts and as it rolls off, as it's been in use for five years, you know as it becomes available, I'm still able to sell it at a higher price than it was at a year ago.","offset":920,"duration":33},{"text":"Host: There's competition now when you were buying these from Jensen back in the day, yeah, you could buy them and have them shipped I would assume within 30 days or less. Nowadays what's the weight like even for you a loyal old customer and is there a bit of a battle? Is there politics to who gets the servers? Like I you see some like very big names talking about they gotta get an allocation. Is it still a little bit crazy? What's it like to be in that category having to buy something everybody wants?","offset":953,"duration":30},{"text":"Michael Intrator: Look you know I think of it as an affirmation of the business that we're in, right? Like the fact that we are attracting competitors means that the business is healthy and there's a lot of people trying to deliver this service because the need for this infrastructure, the need to integrate the infrastructure you know into the software layers to deliver it to artificial intelligence either at the model level or the inference level or the application level or whatever you know level of the five layer cake that Jensen's you know focused on.","offset":983,"duration":36},{"text":"Michael Intrator: The fact that there are more people coming into this, it doesn't discourage me. As far as getting access to the GPUs, we show up like everybody else with a you know, \"we'd like to buy, here's a PO and we're ready to pay.\"","offset":1019,"duration":11},{"text":"Host: What's the wait time like and is it just really competitive or not? Because I talk to Jensen about it he said... I said \"how do you manage all these like big egos and names and companies trying to buy stuff?\" And he said \"well, they order it and we give it to them in the order in which they order it.\" Is it really like that?","offset":1030,"duration":17},{"text":"Michael Intrator: It really is, right? Like you know he doesn't want to be in the position of playing favorites or... like that just seems like a bad place to be with your clients.","offset":1047,"duration":10},{"text":"Host: Or auctioning them off, can you imagine?","offset":1057,"duration":2},{"text":"Michael Intrator: Yeah, so yeah that would that would that would be crazy. Yeah, I don't I'm not sure that would be good for the long-term business.","offset":1059,"duration":10},{"text":"Host: You might get some sovereigns coming in and saying \"I'll pay double.\" They do that with Ferraris too sometimes.","offset":1069,"duration":6},{"text":"Michael Intrator: Yes, these are the Ferraris of computing in a way. They are, yeah. But I mean our approach is to work with clients across the entire space to find opportunities that are really interesting companies that can fit into our contracting requirements where we're going to be able to go out and structure the debt that we require in order to go out and build infrastructure at this scale.","offset":1075,"duration":27},{"text":"Host: How does all that debt work? That is something that you guys specialize in. Corporate debt, I'm in the venture business people are like \"why should I be in venture when corporate debt pays so well? Corporate paper is so huge.\" I'm curious how this fits in and like what interest rate people are paying on you know a billion dollars in infrastructure. What do they pay on that?","offset":1102,"duration":23},{"text":"Michael Intrator: Yeah, so CoreWeave has really been the innovator around a lot of the financing engines that have come to bear on this. We did the first GPU-based loans. And like I think it's important or I'm gonna try to explain this in a way people can understand. So what we do is we go out and we find a client. Let's use Microsoft, you brought them up before, right? And Microsoft comes to us and says we'd like to buy some compute for you and we say okay great we're gonna sign a contract.","offset":1125,"duration":31},{"text":"Michael Intrator: Once I have a contract in hand, then what I do is I create something it's not a particularly creative name, it's called \"The Box\", right? And what I do with the box is I take my contract with Microsoft and I put it in the box. I go to Jensen and I buy the GPUs, I put it in the box. I take my data center contract, I put it in the box. And now the box governs cash flow.","offset":1156,"duration":23},{"text":"Michael Intrator: And it has a waterfall of cash flow that comes into it and goes out of it. And so the way it works is then I build the compute and then I deliver the compute to Microsoft and they pay the box. They don't pay me. Right. It goes into the box and the first thing it does is it pays the data center, it pays the power bill, it pays the interest and the principal and then whatever's left flows back to us, right?","offset":1179,"duration":23},{"text":"Michael Intrator: And so it is an incredibly well structured, time-tested, pressure-tested vehicle to be able to borrow money against client paper and all of the other collateral around the deal. Which is why CoreWeave which is a company that many people haven't ever heard of was able to go out and raise $35 billion in 18 months to build infrastructure at scale.","offset":1202,"duration":27},{"text":"Michael Intrator: But what's important to understand is the economics in this box are such that within two and a half years of a five-year deal we have paid for everything. The principal's been paid off, the interest has been paid off. The return into the box is such that we are able to generate returns to our company at the box level which gives the most sophisticated lenders in the world, whether it's banks or private equity funds or you know whoever, confidence that they're going to be able to achieve the one rule of lending which is give me my money back.","offset":1229,"duration":42},{"text":"Host: Yes, works better when that happens.","offset":1271,"duration":2},{"text":"Michael Intrator: So they look at this box and they're like \"wow we're really confident we're gonna get our money back.\"","offset":1273,"duration":4},{"text":"Host: And maybe they want 10 boxes?","offset":1277,"duration":1},{"text":"Michael Intrator: That's correct. And if anyone box goes upside down you can deal with it and it's not as acute.","offset":1278,"duration":8},{"text":"Michael Intrator: That's correct and they don't cross-pollinate, they don't cause contagion across the boxes. They're all independent and discrete. One. And number two is as you do this and as you show the lenders how this financing tool and how this financing mechanism works, what they do is they continue to lend you money at progressively lower rates.","offset":1286,"duration":23},{"text":"Michael Intrator: And so when you think about our cost of capital over the last two years, we have dropped our cost of capital by 600 basis points. Wow, it is enormous, right? And so you're seeing a company that is driving its cost of capital down towards where the hyper scalers borrow. Which will enable us to be able to be competitive with them over time. And we have been extremely militant and diligent about feeding, watering and caring for those boxes so that we continue to have access to the capital markets in a way that allows us to build and drive our business.","offset":1309,"duration":38},{"text":"Host: Means you have to say no to maybe some people who want to be in the box, some customers?","offset":1347,"duration":4},{"text":"Michael Intrator: Yeah, so like we look at some deals and we're just like you know they want to buy GPUs for a year and I look at it and say \"I that's not a deal that I can do because it's too short for me to amortize the expenses.\" And so I won't do that, right? Like once again...","offset":1351,"duration":16},{"text":"Host: And they can go to another provider maybe wants to take that risk on who has extra capacity.","offset":1367,"duration":4},{"text":"Michael Intrator: Absolutely, but our business is really built about around the risk management of being able to get to scale. Because in my mind during this period of disequilibrium, during this period where there are not enough GPUs in the world to provide the compute for all of the different use cases in artificial intelligence, the part that's important for me and for my company is to get enormously large so we can drive down our cost of capital so that we have information flow coming in from all different parts of the market: the large language models, high-speed trading, search, all of these things and they're feeding...","offset":1371,"duration":39},{"text":"Michael Intrator: ...they're feeding information back into us that is letting us know what the next product we need to build is, or where you know they need help scaling, or what type of compute they need. And all of that information flow is incredibly valuable to us.","offset":1410,"duration":14},{"text":"Host: What what can you tell us about demand? There's been reports of hey maybe the Oracle Starbase thing with OpenAI's been downsized or maybe not, and then you know other folks Microsoft is going big and Google's going big, Meta's going big and those people obviously have massive cash flow. Apple seems to be MIA, they don't seem to want to play.","offset":1424,"duration":25},{"text":"Michael Intrator: You've named a lot of really big companies with really big balance sheets that have the capacity to drive a lot of demand. Look I have been truly steadfast in this for years now. For four years the depth of the demand for the service we provide has been relentless and overwhelms the global capacity of the world to deliver enough compute to enable all of the demand for artificial intelligence to be stated. And that has been... we have been relentless about that.","offset":1449,"duration":34},{"text":"Host: Sounds like Knicks tickets during the Patrick Ewing era, like they're up to 50,000 people on the wait list. So if magically the wait list went away, if the constraint went away and we just had a a large amount of GPUs available, a lot of energy available and a lot of data center available...","offset":1483,"duration":19},{"text":"Michael Intrator: So so... or how would be deployed, I should say. So remember how we build our our business: through this box and it's a five-year box. So if we had an air pocket, if demand were suddenly to disappear because of a technology breakthrough, because of a war, anything, right? Like the why from a risk management perspective does not matter. You have to prepare your company for the what happens if it happens.","offset":1502,"duration":33},{"text":"Michael Intrator: And so by entering into these long-term contracts, into entering into contracts with counterparts that have large balance sheets, you are or we are protecting ourselves and our lenders so that we are confident and they are confident because you can see how confident they are by the rate that they're charging us continuing to decline, that they're ultimately going to get their money back and that is the one rule of lending.","offset":1535,"duration":28},{"text":"Host: But just in terms of the capacity, if you were unconstrained and NVIDIA Jensen says \"hey order as many as you want,\" what would happen?","offset":1563,"duration":8},{"text":"Michael Intrator: So the the it's also important to understand the constraints aren't just GPUs, right? Electricity, data center... it's power shells, it's memory, it's storage, it's networking, it's optics, all of the things and there's various throttles that will limit the...","offset":1571,"duration":16},{"text":"Host: Memory's a throttle right now?","offset":1587,"duration":2},{"text":"Michael Intrator: Oh yeah it is. Oh yeah it is.","offset":1589,"duration":1},{"text":"Host: Why how did memory become the throttle?","offset":1590,"duration":2},{"text":"Michael Intrator: If memory and it is historically been a cyclical business, right? We have seen these waves of demand driving up the cost for memory and then it collapses and then it drives it up. It's a very boom and bust business. It's cyclical in its nature because the fabs are so capital intensive that people invest in the fabs, build a ton of capacity and then overbuild if there's any type of downturn.","offset":1592,"duration":29},{"text":"Michael Intrator: And we've seen that cycle again and again. What's happening right now is the confluence of two things, right? One is is with all the demand for artificial intelligence and the corresponding demand for compute and the ancillary services around the GPU, the demand is through the roof. That's number one. Number two is is that there was probably an investment cycle that needed to happen back in 2023...","offset":1621,"duration":30},{"text":"Host: Got it.","offset":1651,"duration":1},{"text":"Michael Intrator: ...that would have brought on the necessary fab capacity to be able to serve... impossible to predict what's happened just with energy it's impossible to predict what just happened and now people are chasing energy, the data centers are going where the energy is, it's not based on real estate it's based on where there's some wind.","offset":1652,"duration":17},{"text":"Michael Intrator: And and anytime you have a very not anytime but many times when you have a a capital intensive business like you know building fabs you will get this boom and bust cycle just like in energy they overbuild and you know fiber...","offset":1669,"duration":16},{"text":"Michael Intrator: ...yeah I mean there's there's a lot of examples of that. Our approach in some ways when you look at that it's a beautiful aspect of capitalism that we're able to have a boom bust cycle that we're able to weather it right?","offset":1685,"duration":15},{"text":"Host: If you think just like capitalism from first principles something like that happens and we have too much fiber, it creates an opportunity for Google to buy it all up or the next person.","offset":1700,"duration":8},{"text":"Michael Intrator: Listen the the you know it does it does a lot of things having a boom bust cycle: it clears out the underbrush, the strongest companies will be able to survive and take advantage of that and it sows the seeds of future business. The other thing that it does is you put that infrastructure into the ground, you put the fiber into the ground, which became the backbone of how you know we watch movies every day and how we you know communicate and how we talk on a Zoom and you know COVID and all of these things were based on that infrastructure that was available to be consumed.","offset":1708,"duration":36},{"text":"Host: People don't recognize this fact. If you the the premise of YouTube from the founders who I knew: Chad Hurley and his other partner, they basically had the realization \"at this curve storage is coming down so quickly we could offer free unlimited uploads and bandwidth is coming down so I guess we don't have to charge people for sharing a video online.\"","offset":1744,"duration":22},{"text":"Host: Before that if your video went viral people are gonna have their minds blown but your server would turn off and it would say \"this person you know needs to pay their bill\" because they were getting charged for carriage by the megabit going out. Yes. I mean look and and you know these the business models change and evolve and you know like you said Moore's Law and and certainly Jensen will talk about the fact that like what what is going on within the the accelerated compute space dwarfs Moore's Law right?","offset":1766,"duration":34},{"text":"Michael Intrator: And all of that is going to lead to more opportunity to build more companies that are going to do things like YouTube did which has really changed the world.","offset":1800,"duration":11},{"text":"Host: Yeah I mean the the concept that I don't know if it was a a million hours being uploaded every hour or minute... but at some point Susan Wojcicki, rest in peace, said told me just like how much was being uploaded every minute and it made no logical sense until you realize well there's three billion people, two or three billion people in the service and 1% upload or 0.1 10 bips upload and it's like okay one in a thousand people upload. It's a big it's a big denominator.","offset":1811,"duration":31},{"text":"Michael Intrator: I was sitting on a panel with Sarah Friar, CFO of OpenAI, and she everyone once in a while she really puts out like interesting information. And so she was talking about the cost of a million tokens when ChatGPT 3 came out and it was $32 and change. And now a million tokens costs nine cents.","offset":1842,"duration":25},{"text":"Michael Intrator: Right and so you just see like like the incredible power of how the capital market, how capitalism is fueling engineering and fueling competition. And it's become...","offset":1867,"duration":15},{"text":"Host: It's become recursive now. I mean these models, if you say to the model \"hey make yourself more efficient spend less money and lower the cost of tokens,\" it'd be like \"okay captain.\" I don't know if you saw Karpathy's recursive thing last weekend but it's like now civilians who've never worked in a language model done computer science like \"I'm gonna try to do something recursive this weekend.\"","offset":1882,"duration":23},{"text":"Michael Intrator: You know it's one of the things that I talk to you know the other founders about you know and is like when you think about some of the things that AI does right? It's lowering the barrier to operations. So if you have a good idea or a great idea you can open up your model and you can tell your model, you can vibe code it, you can do all kinds of different things and create things that never existed before. That's amazing right?","offset":1905,"duration":29},{"text":"Michael Intrator: Like that's bringing down this incredible barrier that kept human creativity contained and now all of a sudden this whole new vector of medical research or different approaches to baseball cards or whatever you want if you've got a great idea if you've got a new creative idea that's the valuable kernel right now that allows you to to build new things and to create new things and I just think that's incredibly exciting right?","offset":1934,"duration":30},{"text":"Michael Intrator: Like you're bringing the minds of eight billion people a tool that allows them to overcome what was insurmountable for forever. For humanity. Yeah. It's a bright new future Michael, appreciate you sharing the information with us and the vision.","offset":1964,"duration":15},{"text":"Host: I am really delighted to have Aravind Srinivas on the program.","offset":1979,"duration":6},{"text":"Aravind Srinivas: Thank you for having me here Jason.","offset":1985,"duration":2},{"text":"Host: It's so great. I want to go through three stages in which I fell in love with your product. The first phase was I could go in pick my language model if I want to use OpenAI, if I want to use Claude, whatever it was. That was like a real unlock for me. And on the side sidebar I noticed you had done essentially like what Yahoo did in the early days: finance, sports.","offset":1987,"duration":33},{"text":"Host: And when I pull my Nick game up it gave me a live version of that. When I pull my stocks up it summarized the news in real time and I was like \"wow this execution's great.\" And I I kind of made you my front door to different models and it made it easier for me to check in. Then you came out with the Comet browser and I was like \"holy cow, I can give this a series of instructions: go to my LinkedIn, find everybody from this company, put them into a Google sheet,\" and boom you were the first out of the gate with that.","offset":2020,"duration":24},{"text":"Host: And then just the last couple of weeks I had been claw-pilled and using open Claude but you came out with Computer. And I started using Computer and boy it's good. It's a really strong start. allowing me to do repetitive tasks, very similar in some ways to Cowork from Claude or basically an engineer or developer using it. So are these the evolution of the company and I should think about it that way?","offset":2044,"duration":29},{"text":"Host: But how do you look at Perplexity now? You have a very loyal fan base. You're making a lot of money, I don't know if you disclose it but I think it's hundreds of millions to billions. You can tell us. But what is Perplexity in the face of, wow Claude's having a great run, OpenAI still doing strong, Grok doing very well, Gemini coming on strong? There's like six or seven of you and you happen to be one of my top two right now.","offset":2073,"duration":25},{"text":"Aravind Srinivas: Thank you. First of all, thank you so much. Perplexity has always been built for people who are always looking for the extra edge, the curious people. So it's very natural that you are one of our power users. One common theme for us for the last three and a half years is accuracy. Perplexity wants to be the company that's building the most accurate AI.","offset":2098,"duration":25},{"text":"Aravind Srinivas: So when you want to give somebody answers, accuracy is very essential for building trust because only then the user is going to ask the next set of questions. It turns out it was a great idea to give AI access to the internet to be accurate, so that's the Perplexity Ask product. It turns out it's a great idea for AI to have full access to a browser so that it can be accurate when you task it to go do something that you would do yourself on a browser... agentic browsing, Comet.","offset":2123,"duration":26},{"text":"Aravind Srinivas: Now the last phase is it turns out it's a great idea for AI to be given a full access to a computer so that it can do whatever you do on a computer on its own. Essentially becoming the computer itself, an orchestra of everything AI can do today. Every single capability each individual AI model has, be it GPT or Claude or Gemini or anything else, an orchestra of all those capabilities, that's what Perplexity Computer is.","offset":2149,"duration":32},{"text":"Aravind Srinivas: And all these sub-agents that are running inside Computer are the musicians. The models are essentially the instruments and there are like hundreds of models out there, each having their own specialization. Some are good at coding, some are good at writing, some are good at multi-modal, visual synthesis, image generation, video generation, audio. But what matters is the end output, the music you play. That's the work AI gets done for you and that's what Perplexity Computer is. The AI itself is the computer now.","offset":2181,"duration":30},{"text":"Host: Still lives inside of a browser. Have you considered giving it desktop root access? That feels like the next place this is going but that comes with a lot of security issues, a lot of trust issues. As you mentioned trust is paramount getting the right answer is what builds it but also not getting hacked and not having it delete your files. So how do you think about root access to my Windows machine? Obviously iOS they won't let you, but with an Android phone it would let you. So do you have that in the work?","offset":2211,"duration":31},{"text":"Aravind Srinivas: Yes. so we announced something called Personal Computer. Perplexity Personal Computer. That's essentially going to take all the trust and reliability and the server-side execution of Perplexity Computer but synchronize it with your local computer so that you can use it from your phone. And we're going to do this with the Mac Mini where you synchronize your computer with the Mac Mini so that becomes your local server.","offset":2242,"duration":31},{"text":"Aravind Srinivas: All the agent orchestration that has to do with your local private data will run on that local orchestration loop, that runtime with the Mac Mini. Not on your servers, not on Anthropic. Exactly. It could still ping frontier models if it needs to, with your permission. But it will be orchestrating everything on your local hardware.","offset":2273,"duration":12},{"text":"Aravind Srinivas: And if it needs to run on the server-side hardware, if you don't want very complicated long-running tasks to be running on your local hardware, you can delegate it to run on your server-side computer, which is again only accessible to you and you alone. So that way we're going to bring this perfect hybrid of trustworthy compute... a hybrid between local and server side. And you'll make it easy to do it just be abstracted you install one executable boom it's done.","offset":2285,"duration":26},{"text":"Aravind Srinivas: Exactly. It's like Open Claude for dummies. Nobody needs to learn how to use it, nobody needs to manage API keys, nobody needs to manage separate billing across like 100 different services, figure out what you can give access to and not access to. We take care of that. So the Steve Jobs way of doing it, you know end to end integration.","offset":2311,"duration":20},{"text":"Host: And how do you think about local models? I have started running Kimmy 2.5 on a Mac Studio, not as good as Claude or Gemini or Grok, but you can probably do about 80% there for free essentially. And so that's quite compelling considering some of my other bills: Claude and and stuff are getting expensive. So do you have one of those you started testing on your local Mac Studio? I assume you have a Mac Studio and you're doing this yourself?","offset":2331,"duration":26},{"text":"Aravind Srinivas: Yeah. Or now I don't know if you saw Dell and NVIDIA announced a giant workstation... is it the 3800? something like that with 750 gigs of RAM.","offset":2357,"duration":15},{"text":"Host: What do you think about the desktop going back to workstation slash server status?","offset":2372,"duration":7},{"text":"Aravind Srinivas: I think it's very promising. My prediction is it initially start off as a sub-agent. So whatever you need to go like your tax returns, your personal photos, your emails, your calendar, all that stuff, those local apps, your personal notes, very personal notes, you can make sure that the models that access those tokens will be running on your local hardware if you want to, if you're that privacy conscious.","offset":2379,"duration":32},{"text":"Aravind Srinivas: And more complicated stuff that accesses your data that's already on the server side, example your Google Calendar, your Gmail, this is personal data still, but an AI runtime can access that through your connector: your Google Calendar connector, your Google Workspace connector. And that could run on the server side because anyway the data's on the server it's not even lying on your device.","offset":2411,"duration":23},{"text":"Aravind Srinivas: So that sort of hybrid orchestration is where we're headed to. I don't think it's a dichotomy between fully local versus fully server. It's all about choice. And anyway when you're on your phone you want to you don't care actually which server that workload's running from because it's not going to be able to run on your phone anyway. The chips need to exist on a Mac Studio or a Mac Mini... or on the server. Or this new Dell that's coming out.","offset":2434,"duration":26},{"text":"Host: And I really think the idea of spending $10,000 on a powerful desktop will appeal to people if it lowers their $500 a month Claude bill. This is an incredible savings plus you get the benefit of privacy and not educating the language models on your personal data.","offset":2460,"duration":19},{"text":"Aravind Srinivas: Yes. and it's going to be like you're buying a refrigerator. your your internet modem... like the cost for these will eventually go down but it's not going to feel like you're wasting your money. every AI every home has a lot of other sensors that runs your home. that'll also be part of this orchestration loop.","offset":2479,"duration":23},{"text":"Aravind Srinivas: So so that's where it gets exciting because now you can just dictate something to your phone and that can control your entire home. So that's the dream that everybody has and all that orchestration loop can run on your local hardware, no problem.","offset":2502,"duration":12},{"text":"Host: And I'm curious what you think of the operating system. What's eventually going to be the operating system of this workstation?","offset":2514,"duration":10},{"text":"Aravind Srinivas: AI is the operating system. Like earlier in the traditional operating system you would execute programmatically. Now you start with objectives not specific instructions. You come up with a high-level objective: go build this website for me that you know takes all the transcripts of all in podcasts and tracks the stock price just before the podcast and after and charter it for the Max Seven and charted over time.","offset":2524,"duration":27},{"text":"Aravind Srinivas: You can so that's an objective. But individually it's running a file system, a code sandbox, access to the internet, it's having like its own HTML tools and like so I think that's basically where you know model, systems, and files, and connectors are all coming together. You would think of that as an OS except you're operating at an abstraction above that where you're thinking in terms of objectives.","offset":2551,"duration":22},{"text":"Host: Yeah. and does it need to eventually become its own operating system in your mind?","offset":2573,"duration":5},{"text":"Aravind Srinivas: It could be. Like people could think about it as like \"yeah I have a my perplexity computer running all the time.\" Whether it essentially runs on Linux machines right now on every server side computer is a Linux machine. So I think Marc Andreessen tweeted this right after our release that \"turns out Linux computers was the right idea. desktop Linux computers are finally going to work.\"","offset":2578,"duration":21},{"text":"Host: Yeah I mean they're stable, they're customizable and you're not at the mercy of Apple's desire to contain the experience or Microsoft's surface area for hackers. You build something rock solid and it does feel like Linux might actually become the the eventual winner.","offset":2599,"duration":23},{"text":"Aravind Srinivas: Correct. It may not need to have a front end. That's the thing. You could you could access the Linux machine on your phone which could be running iOS or Android doesn't matter. The actual valuable runtime is running on Linux on the server.","offset":2622,"duration":14},{"text":"Host: You've done great as a consumer company lot of love there. now I'm starting to see corporations with Computer starting engaging. In fact, you'll be happy to know this last week I took two people in my back office and I said \"stop working on Open Claude, your job is to do the back office automation at our venture firm only using Perplexity Computer.\" And they were like \"oh okay, it doesn't talk well in Slack, it doesn't have an agent in Slack.\" I was like \"it will. I'm going to see Aravind, I'll talk to him about that.\" So we need a really strong Slack connector.","offset":2636,"duration":37},{"text":"Aravind Srinivas: It's already out. It is? Okay great. Computer exists as a Slack bot right now that you can add to your Slack workspace on the enterprise plan and our entire company works like that. People are talking more to Computer on Slack than to other people.","offset":2673,"duration":15},{"text":"Host: Okay in our first volley we were sending reports in but it wasn't interactive. That's perfect. So now you've got your company going in two different directions: this incredible consumer run you have... how many people are using Perplexity today?","offset":2688,"duration":12},{"text":"Host: Using the product every month?","offset":2700,"duration":1},{"text":"Aravind Srinivas: Several tens of millions.","offset":2701,"duration":2},{"text":"Host: Tens of millions of people. That’s very much similar to the trajectory of the Google and Yahoo consumer business. Now you’ve got corporate. How are you doing on the corporate side? Thousands of companies?","offset":2703,"duration":11},{"text":"Aravind Srinivas: That’s the fastest growing uh business for us. Uh, it’s growing faster than the consumer in revenue and things like Computer unlock entirely new possibilities. For example, we’ve saved more than $100 million dollars for our enterprise max customers who are on the highest tier of enterprise.","offset":2714,"duration":17},{"text":"Host: Explain what that is. What does it cost? 200 a month per person?","offset":2731,"duration":3},{"text":"Aravind Srinivas: So there are two tiers. One is the enterprise pro, which is $40 a month. And there's the enterprise max, which is $400 a month. And that- that- and- and on Computer after you run out of your credits, you would pay for the tokens, you pay for the usage.","offset":2734,"duration":17},{"text":"Host: Are you making money on the $400 a month, $5,000 a year one, or at this point in time are people going so crazy...","offset":2751,"duration":6},{"text":"Aravind Srinivas: Every- so our- one thing that Perplexity has is every revenue we make, unlike certain other wrapper companies, every revenue Perplexity makes has positive gross margins.","offset":2757,"duration":11},{"text":"Host: Got it.","offset":2768,"duration":0},{"text":"Aravind Srinivas: Because uh we’re not just selling tokens. Right. Most of our revenue is recurring because people are paying a subscription fee. And because we route through multiple different models, we're very efficient in terms of how we spend on the tokens.","offset":2768,"duration":16},{"text":"Aravind Srinivas: Because we have all this advantage with RAG and orchestration and search, we don’t actually need to blow up the context window of the models. Yeah. As a result of that, we have positive gross margins on all the revenue we make. Every single penny we make, we make profits on that. The- overall the company's still yet to be profitable, but we're working towards that.","offset":2784,"duration":20},{"text":"Host: You’ve had the opportunity to exit. A lot of rumors, Apple, other people, were like, hey, this is a great team. How many people on the team now?","offset":2804,"duration":9},{"text":"Aravind Srinivas: About 400.","offset":2813,"duration":1},{"text":"Host: Yeah. You- you’ve got a very coveted team. You obviously understand consumer, you obviously understand business. It’s a product-driven organization. Reports are you declined, but the world’s getting hyper-competitive here. How do you keep up as a 400-person organization when you’ve got Sam Altman over here raising $100 billion dollars?","offset":2814,"duration":23},{"text":"Host: You know, and then you have Elon putting data centers in space and merging with SpaceX and Twitter. You have Google with unlimited resources, Amazon getting in the game, and obviously Gemini, uh, very strong product, and Google really good at consumer. I think we’d all agree Facebook and Meta haven’t figured it out yet, except maybe for serving us better ads, but they haven’t figured out the consumer case yet. But they’ll copy it, they always do.","offset":2837,"duration":27},{"text":"Host: How do you look at the playing field? Because the degree of difficulty... this isn’t playing checkers or... this is like playing against the ten best chess players in the world. That’s what you have to do every day. So how do you think about it, long-term an independent company? Do you think you’ll need to join forces at some point? And why didn’t you take the deal? This- these deals were incredible that you got offered.","offset":2864,"duration":25},{"text":"Aravind Srinivas: So uh one advantage we have that all these companies you mentioned don’t have is the multi-model orchestration. We’re like Switzerland, we don’t have to have one horse in the race. If GPT wins, Gemini wins, Claude wins, Llama wins, it doesn’t matter to us. Or even open-source models can win. No problem.","offset":2889,"duration":22},{"text":"Host: And you have them on the service. You have DeepSeek and Kimi?","offset":2911,"duration":2},{"text":"Aravind Srinivas: We have Kimi, we have Nemotron, and we have uh a lot of usage of Qwen, Alibaba Qwen, silently under the hood. So for us like that advantage of being able to take the best in each model and give the user the orchestra of everything they can do, I don't think any of the companies you mentioned can do that.","offset":2913,"duration":25},{"text":"Host: Right, nor would they.","offset":2938,"duration":1},{"text":"Aravind Srinivas: Nor would they. It- it makes no sense for them. It would be an admission that all the data centers and CapEx they've built out means they still couldn't produce them the best model. And uh Dario, uh CEO of Anthropic, said recently in an interview uh that models are specializing. Towards the beginning of last year, people thought models are going to commoditize. But towards the end of last year, people models started specializing. Even within coding, uh Claude Code and Co-pilot have very different capabilities.","offset":2939,"duration":37},{"text":"Aravind Srinivas: Our iOS engineers love using Co-pilot. Our backend engineers love using Claude Code. Yeah. So even within a specialization like coding, models have their own unique specialties and there are many other use cases outside coding where different models are good at different things, which means the orchestra conductor that has no one model to- horse in the race can win by providing a very unique value and service to the customer that each of these amazing names that you mentioned cannot.","offset":2976,"duration":35},{"text":"Host: And so you’re buying tokens wholesale from them and then you’ll charge customers to do it or do you think it’s all-in?","offset":3011,"duration":9},{"text":"Aravind Srinivas: We're going to take care of all their orchestration. Yeah. So you don't have to manage tokens across different models.","offset":3020,"duration":6},{"text":"Host: 'Cause I authenticate a couple of my different accounts, my pro accounts, into Perplexity. But is it- I- I don't have enough knowledge to know if you're abstracting that and people can just search across them and it's part of their Perplexity subscription?","offset":3026,"duration":15},{"text":"Aravind Srinivas: No, we're not bundling subscriptions from other AIs. We just ping the models directly. Got it. What you get in us is the Perplexity orchestration. Got it. The harness. Right. So the- when- when- when models are kind of specializing, the- there's a bigger value in the one who knows how to build a great harness right that can take the best in each.","offset":3041,"duration":25},{"text":"Host: Does it auto-route today or do you still have the dropdown somebody's gotta pick?","offset":3066,"duration":4},{"text":"Aravind Srinivas: It definitely auto-routes the best model for each prompt, but we also give users the flexibility to pick whatever model you want.","offset":3070,"duration":8},{"text":"Host: What do you think of- I’ve seen a bunch of startups hack this together, but doing the same query across multiple...","offset":3078,"duration":6},{"text":"Aravind Srinivas: We built a thing called Model Council.","offset":3084,"duration":1},{"text":"Host: Model Council, yeah.","offset":3085,"duration":1},{"text":"Aravind Srinivas: So that's one of the- one of the modes on Perplexity where I saw Jensen say in one of his interviews that he he puts the same prompt in five different AIs and sees what each of them says. Yes. Everybody does that, yeah. But then you still have to apply your biological compute to read every answer and then figure out where they differ.","offset":3086,"duration":22},{"text":"Host: It’s like talking to five lawyers about your trust or your... five different doctors. Yeah. Five different doctors and trying to figure it out. Exactly. It’s dumb.","offset":3108,"duration":10},{"text":"Aravind Srinivas: So the Model Council is a feature we built where it would not just give you the answers of each model, but it'll tell you exactly where they agree, where they disagree, and where the nuance is.","offset":3118,"duration":12},{"text":"Host: And that’s in the interface, Model Council? I didn’t know it was there. It’s there. I mean, you- you release product at a pretty great cadence, huh? How- where did you learn that and what’s your philosophy of shipping product?","offset":3130,"duration":11},{"text":"Aravind Srinivas: Our philosophy is like speed is our moat. Like, you know, again one of the things that big companies cannot do is move at the speed we do, serve customers at the speed and qual- it's very hard to maintain quality, speed, and trust at the same time. Like Apple takes a long time to ship anything 'cause he's very worried about people not trusting them. Uh and so some companies are bureaucratic and they just take forever to ship something. They don't maintain what they ship. They they'll make a big deal about an event, but nobody even knows how to go and use that feature. Yeah, they get abandoned. Exactly.","offset":3141,"duration":39},{"text":"Aravind Srinivas: So Perplexity has those advantages by being very small. And towards the end of last year, we found that like AI coding tools have made it much faster for us to ship things. Which is honestly one of the reasons why we built Computer because now even non-engineers are shipping code here by just pinging a Slackbot and asking it to fix bugs. Yeah. So the the iteration has just been like exponential.","offset":3180,"duration":29},{"text":"Host: The- the moment I had where I became \"claw-pilled\" was when I was working with it and I was like, hey, I want to build my network. I know these 20 people in Japan I had dinner with them during my recent trip. I want to know who they know, so check out LinkedIn and other things and who they’re associated with and make me like a mind map of it. And then the next trip, I want to meet with the next circle of, you know, those connections. So I start asking... it’s like, okay, I got the results. I was like, great. Um, and it said where do you want me to put them?","offset":3209,"duration":33},{"text":"Host: And uh I was like well where can you put them? And it said \"Why, I can put it in a Google Sheet, I can put it in a Notion table, I can put it here, I can give you a PDF, I can give you a CSV file, or I could write you a CRM.\" And I was like, yeah, sure, make me a CRM system. And it made a CRM system. And I think that becomes... and I think maybe one out of a thousand people working with AI have had that experience. Yeah. Maybe it’s one in 10,000 where your agent says \"I’ll make you bespoke software.\" Have you had that yet and and do you see that as a part of Computer that when a person needs a spreadsheet, you don’t launch Excel or Google Sheets, you just pop up a spreadsheet?","offset":3242,"duration":41},{"text":"Aravind Srinivas: Yeah. Well, we have a board meeting tomorrow. OK. I’ll come. I'll pitch it to the board. Sure. Uh our Computer- Computer made the memo.","offset":3283,"duration":10},{"text":"Host: Oh wow.","offset":3293,"duration":1},{"text":"Aravind Srinivas: Yeah. And uh we had a partner meeting to pitch a partnership idea and uh earlier we would have a design team do the whole deck. Computer just one-shotted it. I had a press briefing with a bunch of journalists. My comms person would usually... Sorry about that. Oof. Brutal. And then my comms person would usually uh give me a memo. Dossier. What to say. Computer one-shotted him.","offset":3294,"duration":24},{"text":"Host: So- it’s crazy. It's crazy. And the context is so good because the memory’s getting better, yeah?","offset":3318,"duration":7},{"text":"Aravind Srinivas: Yeah. So it’s like, I know that journalist from the last time. Yeah. I know the board meeting. I have all the previous decks. Yep.","offset":3325,"duration":6},{"text":"Host: When did that happen?","offset":3331,"duration":3},{"text":"Aravind Srinivas: I think it it happened with Opus 3.5. Uh-huh. Opus 3.5, yeah. That was the inflection point when models were start starting being amazingly good at orchestration and reasoning and tool calls. And uh Claude Code brought in this new idea in AI that everything can happen inside a sandbox, a console, a terminal, with access to tools where tools are just command-line tools. Yeah. They don't even need to have graphical user interface. So when you did that and when you organized around files and subagents and skills and CLIs, the model start started becoming very good at handling the context. So the context window no longer became a problem. It just put whatever necessary into the context whenever it wanted to and dump them dumped them away when it wanted to. Yeah. And that made it like suddenly so good at doing very long orchestration tasks.","offset":3334,"duration":58},{"text":"Host: Yeah. It’s- it’s pretty crazy. I have every episode of This Week in Startups, all the transcripts, and then all of All-In...","offset":3392,"duration":9},{"text":"Aravind Srinivas: That was one of the tasks I did by the way. I can send it to you. I asked it \"I want you to download every All-In podcast uh since the beginning. Yeah. And I want you to take a mention of all the public companies they mentioned during their episodes. Yes. I want you to have a histogram of the counts. And I also want you to chart it across time. And then I want you to analyze the impact on the stock price. And the sentiment of what we said. Exactly. And it did! Like it clearly said around Google’s stock going up, yes, prior to that you guys were talking a lot about Google. Yes.","offset":3401,"duration":30},{"text":"Host: And I said I made a bet publicly on the thing. I said I am buying a bunch of Google because I believe even though they’re behind, it’s because they’re too precious. You were kind of mentioning a company that might be too precious at times and doesn’t release. I was like that’s that company. They need to release more. Yeah. And uh I told Sergey, I was like \"Like give us the good stuff.\" And they started giving us the good stuff.","offset":3431,"duration":17},{"text":"Aravind Srinivas: Not only did it do that, it literally gives you the timestamps of every single mention and then I can go click on it and actually hear that moment. Yeah. Sweet. Yeah. So that's when that's when I was like, damn, like this I would have had somebody do this as a week-long project.","offset":3448,"duration":15},{"text":"Host: It would have been 10 hours a week of researcher. I- I'm experiencing the same thing. When I do research notes, I've created my own uh like mega prompt. Yeah. And it will go and like tell me where you worked before and who's in your circle, who your competitors are, who your friends are, blah blah blah. And then go find- I try to find old podcasts as one of my secrets if you're an interviewer watching. I try to find what was the person talking about five years ago, 10 years ago, and then over 10 years ago. And I've gone into interviews now with Michael Dell and talked about things he was talking about in the '90s. Yep. And it finds me some ancient stuff. Like you would pay a researcher or producer you know $70,000 a year, $80,000 a year to do this and they would have done a third of the job in 10 times longer.","offset":3463,"duration":50},{"text":"Host: Yeah. It’s really gotten weird just in the last six months. What do you think the next six months looks like?","offset":3513,"duration":5},{"text":"Aravind Srinivas: I think the the dream that what we're going to try to do is help businesses run as autonomously as possible. You know everybody talks about this AI is going to create this one-person $1 billion company. Some people say it's already happened because people pay researchers like 1 billion. But it's not truly moving the GDP by 1 billion. It's not truly creating new value. So the best way to do that is to actually help a small business, people who would otherwise drive Ubers for like extra passive income, yes, to like buy like a Mac mini, set up Perplexity personal computer, and run their business on that or like run it on the server, it doesn't matter. Uh and actually make real money. Hundreds of thousands or even millions a year. Yeah. And uh grow it. Have Computer go and run your ad campaigns on Instagram or Google, integrate with SEM and SEO tools, find new users, and uh integrate with Stripe, charge them, ship new features, have your own like Intercom integration for customer support, and like have those all working while you can be sipping wine in Napa. That's the dream that you know it's- it feels awesome to say. Everybody thinks AI is already there. It's not there yet. Someone has to do that hard work. Yeah. But that's what we want to do.","offset":3518,"duration":80},{"text":"Host: Yeah, it- it’s a great vision because when I watched startups 20 years ago, there were so many checkboxes they had to do. I have to find an office space, I gotta put up a bunch of servers, I gotta hire an HR firm, I gotta hire a PR person, all this stuff. And now I talk to young founders, they got a three-person team, they’ve come out of A16Z, my program Launch Accelerator, whatever it is, Y Combinator. And I’m like \"Okay, you raised a half million, you raised a million. Who are you hiring?\" And they’re like \"Um, I don't know if we need to hire anybody.\" I’m like \"If you could hire somebody, would you hire them?\" They’re like \"Well, I do my own HR, I have this partner, and...\"","offset":3598,"duration":31},{"text":"Host: They’re... I’m like \"How are you doing hiring anyway?\" And they’re like \"Well, I put out an ad and then uh it sorts and ranks the candidates and then it emails the top 10, asks them a bunch of questions, and then I meet with the last two.\" And I’m like \"That’s what a recruiter did!\" Like the entire recruiting job has been abstracted. And like a tool like Computer is going to make that even faster.","offset":3629,"duration":22},{"text":"Aravind Srinivas: There's so much work to do. Uh a lot of connectors, a lot of specific workflows. People don't want to like learn how to write like you know essay long prompts. You know needs to be so quick and fast and autonomous. You just set it up and done. And you have an idea you can turn it into a business and start making money.","offset":3651,"duration":18},{"text":"Host: Yeah, it’s- it’s an incredible future uh and it feels like it’s right here. Do you- how do you think about job displacement because you’re actually making the tool that enables people to be a solo entrepreneur and get to a million in revenue, but it’s also the same tool that doesn’t require them to hire, and we’ve had this debate a million times on the podcast. Do you- I’m wondering if like me you have moments where you’re like \"Oh my God, this is really terrifying, a lot of people are going to lose their jobs really fast.\" And then \"Oh my God, you can learn any skill you want and all the things that were hard are now easy.\" I- I go back and forth. I’m 70-80% super positive about this, but I do worry about like 20% of the time I’m a little worried. Where do you sit?","offset":3669,"duration":45},{"text":"Aravind Srinivas: I mean America's always been about like entrepreneur entrepreneurship right like we've been about like trying to build new things discover new things go explore. Uh I think this whole like Henry Ford came and built factories and brought in jobs and things like that and like put people into a box. But uh I think the reality is people most people don't enjoy their jobs. They're doing it for money. Exactly. So there's suddenly a new possibility, a new opportunity to go use these tools, learn them, and start your own mini business and if it pays for your needs for a year or multiple years and lets you have a high-quality life and good work-life balance and true feeling of agency and ownership and passion to like get your ideas out there. I think that even if there is temporary job displacement to deal with, that sort of a glorious future is what we should look forward to.","offset":3714,"duration":55},{"text":"Host: I- I think you’re exactly right. If there will be some displacement, but then there’s also going to be so many opportunities open up. And it requires the individual to not be passive. Exactly. They have to be rugged individualists. They have to be resilient. And they have to be resourceful. And I think once you start playing with these tools, that’s what happens. Exactly. You- you all of a sudden feel...","offset":3769,"duration":18},{"text":"Aravind Srinivas: It brings out the best in you if you truly are in a good space.","offset":3787,"duration":3},{"text":"Host: Yeah. Yeah. And then today uh Comet for iOS is out?","offset":3790,"duration":4},{"text":"Aravind Srinivas: Yeah.","offset":3794,"duration":0},{"text":"Host: I’m a Comet super fan. I required everybody... you were nice enough when I I emailed you, I was like \"Can you send some licenses?\" You sent- you may not remember, you sent me a bunch of licenses. I said \"Everybody put this on\" because it was $300 a month when you first came out with the Comet browser. Now it’s free, I think, for all users? Highly recommend it. Highly recommend getting a pro account. It’s only 20 bucks a month to get into Perplexity, which is a joke, so you can get on board for nothing or a little- less than a dollar a day. But what does iOS allow me to do and and how does it connect to Computer 'cause that’s another thing I’m having. Claude Code, uh Computer, they there’s not a good enough integration with this mobile device yet.","offset":3794,"duration":46},{"text":"Aravind Srinivas: Yeah. So Computer is already on the Perplexity app, so you can just toggle the Computer and start using it. Uh Comet's uniqueness and Perplexity for the company uh and and the strategy is the fact that you can control the browser. So the browser also becomes a tool for Computer just like your Google Workspace and all these other things. Uh until the whole world is organized around CLIs and tools, there's still a lot of tasks we have to do manually on the web on the browser open tabs fill of forms click on things upload stuff all that stuff if you want to automate you need the browser. You need an AI that can natively control the browser. So that is Comet and that's why no matter how many other tools in the market exist like Open- Open Claude or like Claude Co-worker, executing tasks on the browser on the server side along with all the other things is something uniquely Perplexity can do.","offset":3840,"duration":291},{"text":"Host: Yeah, my dream is that you’ll create an Android app that roots my Android phone. Yeah. And that you just take over and see everything. Because one of the blockers I have now is some of the websites have gotten a little persnickety. I don’t want to mention too many, but Reddit, LinkedIn, these... and like I am a great Reddit user, I’m a great LinkedIn supporter, but sometimes like I need to get my InMail from my LinkedIn and I just need to, you know, find seven people at a company. Is there going to be a solution between the LinkedIns and Reddits of the world and the Claudes and Perplexities? Is how is that negotiation going? You don’t have to speak about any specific ones unless you want to, but it feels like there’s gotta be a solution and I’m willing to pay for it as a user. I’m willing to pay Reddit to allow my bot to show up and behave properly.","offset":4131,"duration":56},{"text":"Aravind Srinivas: Well, I I cannot speak about any particular company, but we're happy to work with anyone, right? So uh I think with Comet our idea is to give people the flexibility to set things up on their own and with any official APIs that anyone's going to offer, we're always happy to put that as part of Computer.","offset":4187,"duration":21},{"text":"Host: Here’s what I think should happen. Let me see if you agree. Um, and this is for Steve Huffman uh at Reddit. I go on Reddit. I do a pro account for 20 bucks a month. And when I do that, I can authenticate whatever tool I want uh to do a series of well-behaved things a certain number of times a day. So it’s not unlimited, I’m not going to scrape the whole site, but I would like it to just let Perplexity or Computer go and just tell me \"Hey, what are people saying on the This Week in Startups and All-In subreddits? Summarize it for me so I get the customer feedback.\" And I would literally name my uh agent and I would say \"It won’t post on my behalf, it won’t vote on my half, just need it to do a couple of little read-only things.\" This would be an easy solution. Or LinkedIn, I would like if you... I already pay LinkedIn like 50 bucks a month. Like they should just let the $50 a month one work with Computer.","offset":4208,"duration":57},{"text":"Aravind Srinivas: Yeah, absolutely. Mean...","offset":4265,"duration":1},{"text":"Host: Okay. This is for Satya Nadella. Let LinkedIn work with Perplexity and the other players and we’ll pay you extra.","offset":4266,"duration":7},{"text":"Aravind Srinivas: Perfect.","offset":4273,"duration":1},{"text":"Host: It’s a revenue stream. Don’t you think API access for customers is a revenue stream?","offset":4274,"duration":4},{"text":"Aravind Srinivas: I think so. I think so. Again I think fundamentally giving users a choice and setting it up as a win-win for both the business and the user is where the world should head to. And and I would say the same thing applies to any any website in the world. Like if if you want an AI to use it on your behalf, it should be okay for- because that's what the user wants.","offset":4278,"duration":24},{"text":"Host: I mean, I have a paid New York Times subscription, like let me go in there and do, you know, whatever 100 searches a day, a week, a month, whatever they choose, but that would make the subscription that much more sticky.","offset":4302,"duration":19},{"text":"Aravind Srinivas: Exactly.","offset":4321,"duration":1},{"text":"Host: All right, Aravind. Love the product. Anybody at home, it’s just tremendous. Go learn Computer and get the Comet browser. It is changed my business for the last two years. Love the product and uh we’ll have you back soon when you launch your operating system and come up with your own server and desktop server, but business is the focus, yes?","offset":4322,"duration":20},{"text":"Aravind Srinivas: Yes.","offset":4342,"duration":1},{"text":"Host: All right, brother. Great seeing you.","offset":4343,"duration":1},{"text":"Aravind Srinivas: Thank you, J-S. Thank you.","offset":4344,"duration":1},{"text":"Host: We have an amazing guest, Arthur Mensch here, the CEO of Mistral AI. How are you doing, sir?","offset":4345,"duration":5},{"text":"Arthur Mensch: Great. Thank you for having me.","offset":4350,"duration":1},{"text":"Host: Uh and so you’re here at uh NVIDIA’s big conference. Big announcement. You’re going to be working with NVIDIA to build models, uh to open source them. What is the big announcement here?","offset":4351,"duration":17},{"text":"Arthur Mensch: Well, we’re announcing that we are going to be training the next generation of frontier models with with NVIDIA. Um, it’s something that we’ve been doing uh before with NVIDIA, with Mistral NeMo, something we did like 18 months ago. And the point for us is really to be able to produce the best open-source models out there so that we can actually use those assets to specialize them through products that we do for our customers like Forge that helps us customize the models for the enterprise we work with in engineering, in physics, in science, uh in making them better at certain languages when we work with governments, etc.","offset":4368,"duration":40},{"text":"Host: And and Mistral obviously based in uh France. You’re the leading AI company there. What’s it like running the company and building a large language model in Europe? Obviously there’s regulations and all kinds of considerations, privacy... the French are known for protecting privacy. In the United States, we’re known for taking it away. How is the landscape there and what do you have to deal with there that maybe you wouldn’t have to deal with in America and what’s the pros and the cons?","offset":4408,"duration":27},{"text":"Arthur Mensch: Well, I’d say first we have 25% of our business in the US uh and 25% of our researchers are actually here. So I actually spend a lot of time here as well as in France, as well as in the UK, in Singapore where we are. So of course it’s it’s different markets. Uh it’s markets where you have language which is a topic, uh where there’s much more manufa- manufacturing is a bigger piece of the cake than it is here. Uh and I’d say the our strength has been to also work with European companies that are a bit lagging behind uh and that wants to adopt the technology to to leap forward. And we’ve been able to do that through a forward deployment engineering engagement, through our Forge product, for our Studio product that allows to deploy agents that do end-to-end automation. But on top of that, the thing that we have announced today like Forge is something that is actually being used today uh with customers in the US because they come to us with uh needs for post-training, for making models specifically good at financial services, and uh what’s happening is that we have this product and we can bring the models to specialize them as well.","offset":4435,"duration":70},{"text":"Host: And and so your belief is specialized verticalized models, healthcare, finance, engineering, different verticals, will win the day or a a global model will win the day that does everything?","offset":4505,"duration":14},{"text":"Arthur Mensch: Well, you need general-purpose models to do the orchestration part, etc. But at some point, you enterprise sits on a lot of intellectual property, on a lot of signals coming from physical systems, from factories, from tools. And the- it’s actually not trivial to connect those systems, to connect those data to models that are closed source. If you have open models, you can actually add new parameters, you can make a lot of deeper things that you cannot do with closed models. You can also, and that’s what something that we do, we don- not only do we work at the model side but also at the orchestration side, we sit with subject matter experts to understand their needs and we build business applications that are fully bespoke to their needs by modifying the models, but also modifying the harness on top, etc. So we believe that eventually building on open-source technology is a way to save cost, is a way to have better control because you can sit the thing on every cloud that you want, on your hardware if you want, you can deploy it on the edge if you want. And eventually, uh from a from a customization perspective and from leveraging your decades of IP that you’ve been accruing in financial services, in heavy manufacturing like companies like ASML for instance, they do benefit from working with us because we take their data and we build models that are specifically good for their for their process.","offset":4519,"duration":76},{"text":"Host: And um this training data, using experts to come in and refine a model... most people don’t know this business that well, but this has become a very large part of the industry. Obviously Scale AI was doing it, they went to Facebook, lost a lot of the customer base who didn’t want to um send their data I guess over to Meta. Uh we’re investors in a company called Micro1 that’s doing pretty well in this space. There’s other folks doing it. Explain to the audience what you’re doing specifically for companies and how this training works in a verticalized way and then how you silo that data. Because if you’re working with one customer in aerospace or fintech, they might have a need set but they may not want that training to go to a competitor.","offset":4595,"duration":53},{"text":"Arthur Mensch: Well, let me give you a few examples. I think overall the data segregation is super important. And the way we have solved that is through a portable platform. So our technology is a set of services, a set of training tools, a set of data processing tools that I can take and that I can put on the infrastructure of my customers. So suddenly from an IT perspective and when we talk to the CIOs, they realize that from security perspective the flow of data doesn't go there's no data flow coming back to Mistral 'cause everything stays there. Now uh the way we then use that technology that has been deployed is that we're going to be working with the teams that is doing image scanning and default detection with ASML for instance. And we're going to be sending forward deployment engineers, scientists, they all PhDs, they know how to train models. And they spend some time with the subject matter experts that can explain how an image is being detected, what how do you detect defects etc. And based on that we're going to work out what kind of data needs to be used to train the models that is going to solve the task in in itself. And so the we send the technology, typically we send a little bit of scientist 'cause you do need that expertise transfer and that knowledge transfer in between our teams and the vertical experts. And then we make sure that eventually our team no longer needs to be there to retrain the models, to get more data access etc. So that combination of data segregation, expertise transfer, knowledge transfer is the one thing that makes us quite unique and allows us to serve the most critical use cases, the most critical processes in industries that actually need to take their data and put it into models for it to work.","offset":4648,"duration":91},{"text":"Host: Yeah, this seems to be once the entire open web what was available legally, gray market, etc., I won’t have you comment on that controversy uh but we we kind of exhausted what’s in the open crawl, yeah?","offset":4739,"duration":17},{"text":"Arthur Mensch: We have.","offset":4756,"duration":1},{"text":"Host: And and it’s time to actually either make synthetic data or actually use experts. Do you believe in synthetic data and where does that work and where does it fail?","offset":4757,"duration":9},{"text":"Arthur Mensch: We use synthetic data as a way to warm up the models. It’s a way to actually be quite efficient at the beginning. If you have a large model and you want to train a small model, you would use you would use your large model to to process and to produce a lot of synthetic data at the beginning. Uh and then but eventually you do need to have human signal. Uh so the human signal is something that is always a bit costly to acquire because you need to talk to the experts, they need to give feedback to the machines. And so at the beginning synthetic data allows you to do the compression to to further compress the models, but at the end you do need to go and get data that is uh produced by humans. So yeah it's a way to have it's it's mostly an efficient way of training models to have bigger models that are used as as teachers for smaller models, but it's not enough and so you also need human signal.","offset":4766,"duration":51},{"text":"Host: Arthur, we’ve seen um an incredible explosion. We’re sitting here on um AO 52. After Open Claude, the year of our Lord 52 days. When you first saw Open Claude and saw the reaction of hackers, founders, startup CEOs, just the amount of energy and it racing to the top of GitHub with the most number of stars and likes and and all these contributors, what did that say to you as an executive in the space who’s been grinding on this for many years? What what does that Open Claude moment mean?","offset":4817,"duration":36},{"text":"Arthur Mensch: Well, it resonated a lot with what we were doing with our customers uh because pretty quickly enterprise realized that if they wanted to make some gains with artificial intelligence, generative AI, they would need to automate full processes. And to automate a full process as an enterprise, while you can use Open Claude but it’s going to be it’s actually not really enough 'cause you have data problems, you have governance problems, you can't observe the process that is running and you can't control it in in many cases. When you run a KYC process if you're HSBC for instance, one of our customers, uh you will want to have deterministic gates that are going to always do the same thing in a way that is observable and that you can guarantee the CIO that it's always going to go through these gates. And that's not something that Open Claude is providing because it doesn't have this the kind of primitives that you need to work on collective productivity, observable productivity, and to work on mission-critical systems. On the other hand, the autonomy it gives and the autonomy it brings to to people that are just individuals that are hacking together things is a way to also show to enterprise that if you set up the right control plane, if you set up the right sandboxes, if you connect to the right data sources, if you make sure that you your access controls are well-respected, then you can actually unleash the power of agents doing things for your employees and that's going to work, work on the platform 'cause otherwise you will not be at ease when you're sleeping.","offset":4853,"duration":92},{"text":"Host: It is um definitely something you have to be thoughtful about. When I installed it, I gave it just for my agent root access to my Google Docs and my G Suite, my Notion, my Zoom, my Notion, uh and G Calendar, everything. And then I realized wow, I can with my enterprise edition of Gmail, essentially I can just summarize for my entire 21-person investment company every conversation going on in Gmail and then correlate it with every conversation in Slack. And then I realized oh my gosh, there’s compensation discussions going on. There’s a person on a PIP who we put him on a performance improvement plan perhaps or something like that. Oh, I have to make sure nobody else can access this because the power comes from giving it access to data, but with great power comes great responsibility and I think people are learning that in real time.","offset":4945,"duration":57},{"text":"Arthur Mensch: Yeah, it’s a big problem because the enterprise data is not a single thing that you want to put into a single system that is going to be accessible by by everyone. And so you need to have this layer that actually understands what is in the what is in the data. You need to have a semantic of what can actually be proposed to uh HR or what can be proposed to uh engineering. And typically compensation is one of these things. You want to make sure that the compensation data does not flow back to all of the all of the enterprise 'cause you're going to have a lot of problems uh if if that's the case. And so what you actually need and which is hard to do is what we call context engine. So a mapping of where the data sits that comes with a certain number of metadata that is telling you that this data is actually not accessible to this part of the company. And if you actually have someone in engineering that is asking for something related to comp, the thing is actually going to tell you look, you actually can't access that data. So so that's uh that's hard. It's actually hard. You need to rethink entirely the way your IT systems are being connected and at some point you also need to think about your management because your infor- your information flow is completely different today if you're connecting agents together with your data sources than it used to be. And suddenly maybe you don't need that manager whose only purpose was to take information from the bottom and put the information on the top etc. So there's some IT problems to solve and you need the right primitives, you need sandboxes, you need role-based access control and this kind of things. And you have change to do. You need to rethink your entire customer service department 'cause suddenly you actually don't need that much transfer of information operated by humans.","offset":5002,"duration":133},{"text":"Host: All right. Uh you have to go, you got a flight to catch. It is so great to see you, Arthur. Continued success with Mistral.","offset":5135,"duration":6},{"text":"Arthur Mensch: Thank you very much.","offset":5141,"duration":1},{"text":"Host: Cheers. We have an amazing guest, Daniel Roberts here. He’s the co-CEO and co-founder along with his brother of IREN. They uh are a publicly traded company. They started in BTC. Welcome to the All-In interview program.","offset":5142,"duration":19},{"text":"Daniel Roberts: Thanks, Jason. Pleasure to be here.","offset":5161,"duration":1},{"text":"Host: Yeah. And so you started in Sydney, you and your brother uh what, seven, eight years ago? And you got in early on Bitcoin and all these Bitcoin- miner miners wanted to have data centers, huh?","offset":5162,"duration":13},{"text":"Daniel Roberts: Yeah, that’s directionally right. So the thesis we saw was this explosion of the digital world, the growth in the online, and at some point the real world was going to struggle. So we set about to build out large-scale data centers. Yes, the first use case was Bitcoin mining. But as we said to our seed investors, use that to bootstrap the platform, generate cash flow, layer in higher and better use cases over time as they emerge. Here we are today with AI. We are swapping out all the Bitcoin for AI chips.","offset":5175,"duration":33},{"text":"Host: When did you first start seeing the demand in the company shift from \"Hey, Bitcoin miners\" \"Well, we need some H100s, whatever it is\" to \"Hey, we’re this non-profit OpenAI\" \"Hey, we’re this research lab, we need some AI compute\"? When did that start hitting?","offset":5208,"duration":18},{"text":"Daniel Roberts: Look, we had a bit of a false dawn, I would say, back in 2020. We signed an MOU with Dell to start bringing out customers in compute. But in hindsight, it was too early. So we went back to Bitcoin, kept bootstrapping the platform. Look, I would say about two years ago and month-by-month, the demand just continues to escalate.","offset":5226,"duration":20},{"text":"Host: And you were in so early that when you were looking at data center space in the United States, you were one of one looking at the space, one of two or three people looking at the space. They they were trying to sell you on space, yeah?","offset":5246,"duration":15},{"text":"Daniel Roberts: Yeah, so we actually develop the data centers ourselves. So we go and find the land, we go and get the permits, we go and at apply for grid connections. And we were doing it at a scale that just amazed people at the time. Like 750 megawatts is our flagship Texas site. Four years ago, was unheard of in the middle of the desert where building these big data centers. The traditional data center industry going \"What are you guys doing?\" And we’re saying \"We believe in the future digitization, high-performance computing, and obviously now today it's paying dividends.\"","offset":5261,"duration":35},{"text":"Host: Yeah, I don’t think anybody could have predicted when ChatGPT came out, Open Claude recently as a turning point um and then, you know, Microsoft, Google, and everybody embracing this. And that’s your big partner, Microsoft.","offset":5296,"duration":17},{"text":"Daniel Roberts: Yes, Microsoft’s one of our early partners. We signed a $9.7 billion dollar contract with them late last year. But as I was explaining to you before the show, that’s 5% of our capacity. So things are busy at the moment.","offset":5313,"duration":12},{"text":"Host: And when you do these buildouts, the big conversation today is not is no longer the number of GPUs put in, it’s just power. Power is the constraint today, yeah?","offset":5325,"duration":14},{"text":"Daniel Roberts: Look, for many in the industry it is, but for us because we started eight years ago tying up all this land and power, it’s not. So we’ve got four and a half gigawatts. For context, that’s almost as much power annually as the Bay Area uses in its entirety each year. Wow, it’s huge. So for us, the hurdle or the constraint is really time to compute. And that’s emerging across the industry as well.","offset":5339,"duration":23},{"text":"Host: And time to compute means tradespeople coming to West Texas living in a a trailer that you set up to then break ground on a data center, build foundations, build water cooling systems... like this is hard manual labor going on, yeah?","offset":5362,"duration":17},{"text":"Daniel Roberts: Exactly. And this is the whole real-world challenge to respond to these digital exponential demand curves that are unconstrained by the real world in terms of their appetite and it just compounds. You need thousands of people out in these locations that haven’t supported it. You put stress on supply chains. We’re seeing what’s happening with the memory, every aspect of it. So it’s just permanent whack-a-mole, permanent solving fires to try and be bring online this compute.","offset":5379,"duration":29},{"text":"Host: And you get to spend time there. What’s it like when you set up a town or you bring a thousand people or 2,000 people to what’s a pretty much remote small town? You I’m assuming that like when you bring a thousand, there might only be 500 living there right now. So what are those towns like? I’m- it sounds to me like something out of like the gold mining era when people first, you know, went and were prospectors. You’ve become prospecting town?","offset":5408,"duration":26},{"text":"Daniel Roberts: Pretty- pretty much. I mean the barbecue’s great, that was a draw card. But apart from that, look we’ve always had a policy of hiring local, supporting the local community. This year we’re hitting a million dollars in community grants cumulatively. That’s things like local playgrounds, supporting the fire departments. But we will hire locally. Once we can’t find that trade locally, we will expand the radius by 20 miles and hire out of that and so on and so on. Well, that’s very thoughtful, yeah.","offset":5434,"duration":28},{"text":"Host: And- and these folks are coming, say an electrician or a construction worker. They’re coming having built houses or, you know, uh built um corporate offices and now they come for a tour of duty here and the salaries go up massively, but they gotta leave their family for a three-month tour or something?","offset":5462,"duration":20},{"text":"Daniel Roberts: Yes- yes and no because typically where we locate is where there's heavy electrical infrastructure. Ah, where there's heavy electrical infrastructure is typically where old manufacturing and industry has closed down. Ah. So we go down in leverage that sunk CapEx, rehire, retrain local workforces, and bring a new industry to town in these data centers.","offset":5482,"duration":23},{"text":"Host: Has- has that workforce now been completely depleted and we need to train another generation, a younger generation to be generation tool-belt and really embrace the trades?","offset":5505,"duration":11},{"text":"Daniel Roberts: 100%. We’re partnering with universities, trade colleges, absolutely.","offset":5516,"duration":3},{"text":"Host: And you go to a trade school, you got you go to a college, people are getting degrees in philosophy and English literature, they’re going 50k a year in debt, 200k a year in debt. What’s the starting salary for a tradesperson working on a data center doing electrical or construction or HVAC? What’s the ballpark range?","offset":5519,"duration":20},{"text":"Daniel Roberts: Oh look, I won’t talk specifics, but they they are going up, the price is going up, depends on the level, but yes there is a rush for good talent.","offset":5539,"duration":10},{"text":"Host: I’m hearing 150 to like 300k. Am I in the ballpark?","offset":5549,"duration":4},{"text":"Daniel Roberts: The lower end directionally you’re right, yeah.","offset":5553,"duration":2},{"text":"Host: Yeah, I mean it’s incredible when you think about it. There’s concern about \"Hey, AI taking jobs\" and then on this other side of the ledger, can’t find enough talent to- to- to service it. Talk to me about energy sources and how you think about that. Uh President Trump, Chris Wright, the administration, they kind of started with \"Hey, clean beautiful coal.\" Year two they’re like \"All sources matter, nuclear.\" Obviously Nat Gas is plentiful in that area, we obviously got a lot of oil. People don’t know this about Texas. In the United States, the number one uh source of solar installations, yeah? Yeah.","offset":5555,"duration":39},{"text":"Daniel Roberts: So our- so our philosophy's been sustainability from day one. We have used 100% renewable energy since inception.","offset":5594,"duration":6},{"text":"Host: What? 100- wait, how is that possible?","offset":5600,"duration":4},{"text":"Daniel Roberts: We use hydro in British Columbia, we use wind and solar in West Texas. In West Texas where we're located, there's around 45 to 50 gigawatts of wind and solar. Yeah. The transmission line to export that down to the load centers in Dallas and Houston is 12 gigawatts. Oh. So you go and locate to the source of low-cost excess renewable energy, monetize it into this digital commodity, export it at the speed of light.","offset":5604,"duration":27},{"text":"Host: Great arbitrage. And the wind is producing a lot, but they it’s harder to get from those areas where people are willing to put up... I mean, people don’t understand how big West Texas is. It is an incredible amount of land. And you’re coming from Australia where also on the West side, people don’t understand exactly how much pure nature land there is, yeah, undeveloped.","offset":5631,"duration":20},{"text":"Daniel Roberts: So much land. And the issue is distance. You’ve got to spend billions of dollars on this transmission connectivity infrastructure to move that power to where people actually want it. You can build wind farms, you can build solar farms, but if you build it in the desert and no one can use it, then what’s the point? So the whole opportunity for our industry is go to the source of that power and monetize it.","offset":5651,"duration":19},{"text":"Host: So the data centers follow the wind turbines, the solar installations. How do you think about batteries and are you able to put those online because obviously you’re going to have periods where, hey, it’s not a windy day. In Texas, we have very few days when it’s overcast, so that problem’s pretty much solved, but you’re going to have 50 days where the sun’s not beating down. So how do you deal with the demand and and softening that duck curve?","offset":5670,"duration":24},{"text":"Daniel Roberts: We don’t need to. The utility does that on our behalf. So this is why these grid connections are so scarce, so hard to get, and so highly valued, because once you get that grid connection, the utility underwrites all of that variability. They guarantee you 24/7 reliable power. Got it.","offset":5694,"duration":17},{"text":"Host: So on their side, they’re figuring it out. Something goes down and they could fall back even though you’re 100% committed to renewables. If they needed to fall back to- to gas or whatever, they have that ability out there. So you have that as a backup. A lot of talk about or a debate: are we getting ahead of our skis, are people slowing down? There was some talk about the OpenAI project maybe downscaling a little bit. Is OpenAI a partner as well or...","offset":5711,"duration":29},{"text":"Daniel Roberts: Ah, can’t comment.","offset":5740,"duration":1},{"text":"Host: Can’t comment. Okay. So well we’ll read into that whatever we want. But are there pockets where people are saying \"Hey, let’s slow down\" or is it still gangbusters?","offset":5741,"duration":9},{"text":"Daniel Roberts: It’s right up the end of the spectrum, it's gangbusters. OK. We we cannot meet demand. That's why the whole industry now is around time to compute. There are no idle GPUs in the world sitting in a data center.","offset":5750,"duration":13},{"text":"Host: Yeah. And what’s your take on when software makes... and this is a big um discussion from Jensen himself during his two-and-a-half-hour keynote yesterday... uh we’re sitting here Wednesday, I think he did his keynote on Tuesday. He was talking about, hey, software’s going to make it 50 times more uh, you know, lower the cost of tokens, 50x. And then um transport also contributing to that. When do you think the curve goes from parabolic to simply growing at a ridiculous level? Is- is there a slowdown coming or how are you planning for the future?","offset":5763,"duration":36},{"text":"Daniel Roberts: Look, I think it’s actually the opposite. I think it feeds on itself. So I’ll give you one example. You go into ChatGPT today and you generate an image. You enter the prompt, it’s like the dial-up internet days. It is. Right? It takes minutes and you’re like \"I better get this prompt right.\" Yeah. Finally two minutes later it comes. Now, I’ll give you an example: if we 10x the amount of compute available, which is an enormous task from where we are today...","offset":5799,"duration":14},{"text":"Host: Yeah, it's definitely not material. Listen, continued success and you're hiring a lot of people.","offset":5813,"duration":9},{"text":"Will: Yeah, I think we've got 129 job advertisements up at the moment.","offset":5822,"duration":4},{"text":"Host: All right, so everybody go to the IREN website and listen, the company's doing fantastic. Thanks for spending some time with us here at All-In at GTC.","offset":5826,"duration":10},{"text":"Will: Thanks Jason, appreciate it.","offset":5836,"duration":15}],"logs":[{"elapsed":"0.0","message":"Downloading audio from YouTube...","detail":null},{"elapsed":"0.0","message":"Trying download with browser cookies (ad-free)...","detail":null},{"elapsed":"2.7","message":"⚠ Cookie download failed: WARNING: [youtube] [jsc] Error solving n challenge request using \"deno\" provider: Error running deno process (returncode: 1): \u001b[0m\u001b[1m\u001b[31merror\u001b[0m: Uncaught (in promise) TypeError: Cannot read prope","detail":null},{"elapsed":"2.7","message":"Retrying without cookies...","detail":null},{"elapsed":"47.1","message":"⚠ Downloaded without cookies — audio may contain ads","detail":null},{"elapsed":"47.1","message":"Audio downloaded (59.8 MB) in 47.1s","detail":"File size: 59.8 MB"},{"elapsed":"47.1","message":"Video title: Four CEOs on the Future of AI: CoreWeave, Perplexity, Mistral, and IREN","detail":null},{"elapsed":"47.1","message":"Audio duration: 1:37:38 (97.6 min)","detail":null},{"elapsed":"47.1","message":"Very long audio (97.6 min) — will use chunked transcription with gemini-3-flash-preview","detail":null},{"elapsed":"47.1","message":"Skipping full-file attempt — using chunked transcription for 97.6 min audio","detail":null},{"elapsed":"47.9","message":"Split audio into 3 chunks for transcription","detail":null},{"elapsed":"47.9","message":"Transcribing chunk 1/3 (starts at 0:00)...","detail":null},{"elapsed":"47.9","message":"Uploading audio to Gemini File API...","detail":null},{"elapsed":"53.7","message":"Audio uploaded in 5.8s","detail":"File ref: files/3k1vnce3p6e7"},{"elapsed":"53.7","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"410.3","message":"Chunk 1: 129 segments, last timestamp 44:48","detail":null},{"elapsed":"410.3","message":"Transcribing chunk 2/3 (starts at 45:00)...","detail":null},{"elapsed":"410.3","message":"Uploading audio (offset 45:00) to Gemini File API...","detail":null},{"elapsed":"416.1","message":"Audio uploaded in 5.8s","detail":"File ref: files/p8boavgybgp8"},{"elapsed":"416.1","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"581.4","message":"Chunk 2: 136 segments, last timestamp 1:36:39","detail":null},{"elapsed":"581.4","message":"Transcribing chunk 3/3 (starts at 1:30:00)...","detail":null},{"elapsed":"581.4","message":"Uploading audio (offset 1:30:00) to Gemini File API...","detail":null},{"elapsed":"582.9","message":"Audio uploaded in 1.5s","detail":"File ref: files/zb344k5842vc"},{"elapsed":"582.9","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"609.9","message":"Chunk 3: 26 segments, last timestamp 1:37:16","detail":null},{"elapsed":"609.9","message":"Chunked transcription complete: 269 total segments","detail":null},{"elapsed":"609.9","message":"Total cost: 147,275 in / 25,144 out — cost: $0.1491","detail":null},{"elapsed":"609.9","message":"Total transcription time: 562.7s — 269 segments","detail":null},{"elapsed":"609.9","message":"Analyzing topics across 269 segments with gemini-3.1-pro-preview...","detail":null},{"elapsed":"663.8","message":"Topic analysis complete in 53.9s — found 23 topics","detail":null},{"elapsed":"663.8","message":"Analysis tokens: 24,819 in / 1,646 out / 4,517 thinking — cost: $0.1236","detail":null},{"elapsed":"663.8","message":"Pipeline finished in 663.8s — total cost: $0.2727 (203,401 tokens)","detail":null}]} \ No newline at end of file diff --git a/history/1775221563723-9ZbbxSgrjhw.json b/history/1775221563723-9ZbbxSgrjhw.json new file mode 100644 index 0000000..1810e4f --- /dev/null +++ b/history/1775221563723-9ZbbxSgrjhw.json @@ -0,0 +1 @@ +{"id":"1775221563723-9ZbbxSgrjhw","videoId":"9ZbbxSgrjhw","url":"https://www.youtube.com/watch?v=9ZbbxSgrjhw","title":"He's Running A $5bn Company With An AI CEO","type":"youtube","topicCount":22,"segmentCount":341,"createdAt":"2026-04-03T13:06:03.723Z","uploadDate":"20260401","chunks":[{"title":"Podcast Introduction & Guest Background","summary":"The host introduces Pedro Franceschi, co-founder and CEO of Brex. He highlights Pedro's background as a coding prodigy, Brex's recent acquisition by Capital One, and his innovative use of AI agents.","entries":[{"text":"Host: Today's guest is a coding and entrepreneurial prodigy. He is Pedro Franceschi, the CEO and co-founder of Brex. The headlines on his life story are quite remarkable.","offset":0,"duration":15},{"text":"Host: He grew up in Brazil, taught himself to code as an eight or nine-year-old. By the time he was a teenager, he was—he was hacking the iPhone. He was getting legal notices from Apple asking him to stop hacking the iPhone.","offset":15,"duration":16},{"text":"Host: He was starting a number of businesses where he made hundreds of thousands of dollars while all the rest of his, uh, compatriots were on the beach in Rio de Janeiro or playing soccer. Pedro was coding away, creating these—these companies.","offset":31,"duration":21},{"text":"Host: He has some—some very deep sadness in his childhood. His father got cancer and passed away when Pedro was just eight. That left his mother to raise Pedro and his sibling, uh, as a single mother. She had some unconventional approaches to—to raising Pedro, which we get into in the show.","offset":52,"duration":21},{"text":"Host: Obviously, we get into Brex, which has been this just superstar of—of modern financial tech. Um, they were just acquired by Capital One for $5.15 billion. We speak about this on the episode.","offset":73,"duration":18},{"text":"Host: We talk about—Pedro's really open about the ups and downs running this business, his own personal ups and downs, struggles with mental health. He writes about these things, he talks about them in the show. Um, just—he's 29 years old, so this dude has lived quite a—quite a juggernaut of—of a life so far.","offset":91,"duration":20},{"text":"Host: And these days, he's using AI agents in some what I find imaginative and—and comical and—and inspirational ways. He's got a team of AI agents running his life, and—and we speak about all that.","offset":111,"duration":17},{"text":"Host: And so, um, I should note, Brex is the flagship sponsor of this podcast and our video series. As such, we are deeply journalistically conflicted in this episode. Nonetheless, I think it is, uh, it's a good listen, and he has a fascinating story to tell.","offset":128,"duration":19},{"text":"Host: This is Ashley Vance. You're listening to the Core Memory podcast, and off we go.","offset":147,"duration":17}],"startTime":0},{"title":"Welcome & Recent Life Milestones","summary":"Ashley welcomes Pedro to the podcast. They briefly exchange banter about the major events currently happening in Pedro's life, including getting married and selling his company.","entries":[{"text":"Ashley: Pedro, thank you so much for coming in.","offset":164,"duration":3},{"text":"Pedro: Thanks for having me.","offset":167,"duration":0},{"text":"Ashley: You are—you're royalty in these parts. Um, you guys have been such amazing supporters of everything Core Memory's been doing, so...","offset":167,"duration":9},{"text":"Pedro: Oh, thank you. Very glad to help. We're big fans.","offset":176,"duration":3},{"text":"Ashley: I feel extra pressure, uh, doing this one. You, uh, at the end of last year, you got married. You just were acquired for $5.1 billion, and now you're on the Core Memory podcast. It's all happening.","offset":179,"duration":14},{"text":"Pedro: It's all happening. It's really all happening.","offset":193,"duration":4}],"startTime":164},{"title":"Early Coding Journey & Teenage Entrepreneurship","summary":"Pedro discusses teaching himself to code at age eight and becoming a well-known iPhone jailbreaker. He shares stories of building software and running profitable businesses as a young teenager in Brazil.","entries":[{"text":"Ashley: Um, I wanted to—I wanted to for people to get to know you a little bit. I mean, look, I cover—I cover all kinds of inventors, startup founders, you know, and so some stories I see repeating a little bit, and there's—there's echoes of that in some of your biography.","offset":197,"duration":20},{"text":"Ashley: I'm just going to read off a little list here for people, uh, super quick, and then dive into a couple of these things. But, you know, if you throw your name into Claude or ChatGPT and ask for like a quick—quick background or, you know, it's like ages eight to nine, teaches himself to code entirely via Google, no formal—formal training.","offset":217,"duration":25},{"text":"Ashley: Age 11, begins jailbreaking iPhones and iPads. Uh, age 12, you know, starts creating apps, you're selling apps to—to friends at school. Age 15 to 16, um, well, then this is kind of when you start your—your journey heading towards Brex one day, um, meeting—meeting your friend Henrique.","offset":242,"duration":22},{"text":"Ashley: But, but, you know, so some of this is familiar. I mean, it reminded me a lot of George Hotz, who I've written about. Uh, in OA. Yeah, he's like this teenage hacker. He was—he was busting into PlayStation.","offset":264,"duration":12},{"text":"Pedro: We used to be IRC buddies back in the day.","offset":276,"duration":3},{"text":"Ashley: OK, you know, he was getting into PlayStation, but, I mean, like even among these people I've covered, like quite exceptional, especially running, you know, money-making businesses as a kid. Um, so—and there's some of this in the things that I read, but I mean, tell me, were you just always—you—you hit upon a computer and it just—it just made sense to you?","offset":279,"duration":20},{"text":"Pedro: Yeah, so—I think the biggest luck of my life was I found out what I loved doing when I was eight or nine. And most people don't have that luck, but I—I did, and—uh, my—my—I grew up in Brazil, I'm from Rio originally, and—uh, growing up, um, I lost my dad when I was eight, um, and—uh, he was a big nerd and used to spend a lot of time in the computer.","offset":299,"duration":23},{"text":"Pedro: Uh, we had a computer at home, which was—uh, relatively rare—uh, back in Brazil. And—uh, that somehow was something that was around my life since the beginning. And I would say when I was eight or nine, I just had this very deep curiosity to understand how the computer worked.","offset":322,"duration":17},{"text":"Pedro: Um, and then I opened it up one day and I saw there wasn't anything interesting inside the computer, so I thought, well, there's something else going on here that makes this actually be so ama—so magical and so amazing, and I realized it was software.","offset":339,"duration":15},{"text":"Pedro: And then as a kid, um, in Brazil, um, I wasn't really exposed to software engineering in any capacity, but the internet existed, and the internet's this amazing thing—uh, uh, that, you know, allowed people like me to learn something that I would never be able to learn otherwise.","offset":354,"duration":18},{"text":"Pedro: So I started Googling how to code and started learning, uh, C and C++ back when I was nine. And—uh, learning that and English at the same time made it a little bit more challenging. Uh, C isn't a particularly friendly language, but it's all the resources that I found back then in, I guess, 2004 or five.","offset":372,"duration":21},{"text":"Pedro: So—uh, so that was—uh, that was sort of the—the backdrop of how I started coding. And—and what I really found—uh, remarkable about computers was you just had this ability of taking whatever you wanted with very little—uh, sort of permission or need to go do something.","offset":393,"duration":18},{"text":"Pedro: And then around the time I was 12, I became a little bit of a better—uh, engineer, um—and—uh, it was around the time that Apple launched the iPhone. And—and if you remember back in 2008 or nine, iPhone—the iPhone only worked with AT&T here in the US.","offset":411,"duration":16},{"text":"Pedro: So there was this whole thing of when you wanted to use the iPhone abroad, you had to jailbreak it to get it working in other countries. You would jailbreak it and then do the carrier unlock. But jailbreaking was—uh, the hardest part. So I was using a lot of the tools that existed online to make that happen.","offset":427,"duration":16},{"text":"Pedro: And then a new iPhone came out, the iPhone 3G, I ended up finding—uh, a way to jailbreak it that was one of the first ones back then in 2009. And I got sort of known in this like iPhone—uh, jailbreaking community.","offset":443,"duration":15},{"text":"Pedro: And then, weirdly enough, that's actually how I got—uh, I started working. So—uh, I used to, you know, a reporter in Brazil realized that there was this kid doing, you know, jailbreaking things online because...","offset":458,"duration":13},{"text":"Ashley: I mean, you became like a celebrity.","offset":471,"duration":2},{"text":"Pedro: Uh, I—I guess I wasn't really known back then, but because I used to just publish things online with my handle, which was PH, um, my name is Pedro Henrique, that's why PH, like the chemistry pH. Uh, and—and some—somehow this—this reporter realized I was Brazilian. Uh, I think was because of my IP address in—in this IRC form.","offset":473,"duration":21},{"text":"Pedro: And—uh, he reached out and said, \"Hey, there's a Brazilian involved in this like iPhone jailbreaking community.\" And then—uh, he asked, \"How old are you? I want to know more about you.\" And in my head I thought, well, if I tell people I'm 12, they're not going to take me seriously. So I told people I was 14. And in my head it made a huge difference.","offset":494,"duration":20},{"text":"Ashley: But—um—and then—uh—and then—um, right around that time that was sort of in the Brazilian press, and—uh, a company in Brazil that was building mobile apps—uh, reached out to me, and—uh, and I ended up going to work there, right around the time I was 12, uh, 11 or 12.","offset":514,"duration":18},{"text":"Pedro: And—uh, at first my—I told my mom, \"Hey, this company wants to hire me.\" And she said, \"No way, what are you talking about? You're 12. Uh, no freaking way.\" But then I convinced her to come interview with me, so she went there, uh, and I started working there part-time.","offset":532,"duration":20},{"text":"Pedro: And it was great because it was the first time that—uh, I actually met professional software engineers. Like, what does it look like to—to really be sort of world-class? And my first boss, uh, Ben Jackson, was—uh, fantastic, and, you know, he—he worked at New York Times after building their mobile app, and, you know, he—he—he went to Penn.","offset":552,"duration":22},{"text":"Pedro: So it was just like a—you know, US-grade software engineering—uh, experience, which I—I don't think—I think was very formative. And then—um, right around the time I was 14, uh, I did two things that sort of got—got me in trouble. One is I—I ended up reverse-engineering Siri to make it work in Portuguese, and—uh...","offset":574,"duration":37},{"text":"Ashley: Terrible.","offset":611,"duration":1},{"text":"Pedro: Nuance and Apple were not very happy with me. Um, and then the second was—uh, I built this app for the iPad—uh, called Quasar, which you could run, you know, apps on windows, the same way you can now on iPad, but that was in 2012, so—uh, 13 years ago.","offset":612,"duration":19},{"text":"Pedro: And—uh, that was really fun. Uh, and I put this online and I used to charge 10 bucks per—per download in—in Cydia Store back then, which was this sort of parallel app store. Um, and I made like 300k when I was 14. Um, so I had to explain to my mom what that money was about. She thought I was doing something illegal online.","offset":631,"duration":19},{"text":"Pedro: Um, but anyway, so—so I did all that. And then—um, right...","offset":650,"duration":5}],"startTime":197},{"title":"First Software Engineering Job at Age 12","summary":"Pedro recalls the unique experience of interviewing for a software engineering job at just 12 years old. His mother accompanied him to ensure his safety, supporting his unconventional passion for computers.","entries":[{"text":"Ashley: Can I—can I pause you for one second? Because I'd—I'd read about some of this and I just had—I had a couple—couple questions along these lines. I mean, your mom goes to your first job interview with you. You said I think you were 12 for that one. So like, what does that look like? You—you both walk into the office together?","offset":655,"duration":15},{"text":"Pedro: Yeah. So—so it's funny because I think your parents make a few decisions that they may not be aware at the moment, but they drastically change the course of your life. And I remember around that time, there were all these articles—uh, that came out that Bill Gates's daughter could only spend 45 minutes today in the computer.","offset":670,"duration":17},{"text":"Pedro: And then my mom looked at that, and—and here—here was her son spending 14 hours a day in the computer. And well, Bill Gates know—a thing or two about computer, so who am I to allow that? And I think she was—uh, very fortunate to—to see what I was doing with—a little bit of a bigger aperture and see that I wasn't like playing games, I was actually building something productive that people got value from.","offset":687,"duration":24},{"text":"Pedro: And—uh, and that sense of being a builder, which is really the—the biggest luck of my life, realizing that I love to build things, was something that I think she—she saw the impact it had on me and on the people that used the things I built.","offset":711,"duration":14},{"text":"Pedro: And—uh, I think that unlocked her to—to allow me to—to not only spend a lot of time in the computer, which I needed, but also at the same time—uh, uh, just—just really open to these experiences of going in and working even though it was very counter-intuitive and, you know, my family and, you know, sort of extended family friends were all asking her, \"You know, this kid is 12, why is he working?\" And she's like, \"You don't understand, he wants to.\"","offset":725,"duration":25},{"text":"Pedro: Uh, and—and thankfully she did it because if she hadn't, I think the course of my—my life—uh, would have been very different.","offset":750,"duration":8},{"text":"Ashley: What—but what's that like? You go in for this job interview together, and so what? The two of you are just sitting on one side of the...","offset":758,"duration":6},{"text":"Pedro: Yeah. So—so it was—so it went to—went to have lunch—uh, with—uh, with the two founders of that company.","offset":764,"duration":4},{"text":"Ashley: And they're Brazilian or...?","offset":768,"duration":1},{"text":"Pedro: Oh, one of them is American, the other's Brazilian. OK. The American one went to Brazil for Carnival—uh, one year and never left. He stayed there four years. Now—now he's in the US, he's in New York now, but—um, but it was—it was really funny just to see—uh, uh, you know, like a—like a professional software engineer in Brazil in Rio.","offset":769,"duration":19},{"text":"Pedro: And then—um, we went for this—for this lunch, and I was just talking to them technically about the things I was building, and my mom was like, \"I have no idea what's happening, but sounds like they are excited, so that's I guess it's a good sign.\" Um, and then at the end she—they were like, \"Look, we—we think—we think he's good, we'd like to work with him.\"","offset":788,"duration":16},{"text":"Pedro: And she said, \"Um, I have only one thing to say. Uh, he's 12 years old, so if something happens to him, I'm going to kill you.\" And then—and then they were like, \"OK, understood.\" Um, so—so she was—she was very protective but in—in a way, you know, obviously was a very different environment.","offset":804,"duration":18},{"text":"Pedro: It was this company where, you know, I guess the—young—second youngest person was probably like 26, and then I was 12. So—um, I—I don't know if I would have the—the courage let my—my son do that, but she did, thankfully, and—uh, and things worked out.","offset":822,"duration":-46}],"startTime":655},{"title":"The Drive Behind His Early Obsession","summary":"The conversation explores the intrinsic motivation that fueled Pedro's rapid growth as a programmer. He explains that his deep connection to the craft and pure creative energy were his primary drivers, rather than a desire to make money.","entries":[{"text":"Ashley: Yeah. OK. That's—that's kind of how I pictured it in my head a little bit. I mean, look, lots of—lots of young kids code. Um, you know, and this is—this is a difficult question because I'm asking you to—to tell me how awesome you are in some ways, but I'm more curious how your brain works. Because I—again, you know, I've met so many people. This is a common story. They start coding at a young age. But I mean, what you're doing, it is—it is—it again, it reminds me of Hotz, just because it's—it's on the exceptional side. How does the—like, what are you... what are you particularly good at when it comes to coding? Why were you standing out at that age?","offset":776,"duration":34},{"text":"Pedro: I think—I think it was just this—uh, you know, Paul Graham has this essay about the—you know, the bus ticket theory of genius, about these uninteresting obsessions that when you multiply over the course of one's life, you—you end up in a—in a—in a pretty interesting place.","offset":810,"duration":18},{"text":"Pedro: And to me, I just had this deep curiosity to get computers to do things that they were not design or supposed to do, and—uh, and almost sort of proving that it could—it could—it could happen from a technical standpoint. Um, so that was probably the backdrop.","offset":828,"duration":15},{"text":"Pedro: And—and I would say the biggest benefit that I had having started that early is because I feel that when you are 12 or 14 or you're very young, the creative energy that flows through you when you're building something is—is almost like the purest kind. Because there is no other reason besides love for the game, right?","offset":843,"duration":20},{"text":"Pedro: There's no other reason like—I didn't need to make money, thankfully my—my—you know, my—I grew up in a middle-class family in Brazil so I—you know, um, I was lucky to not have to—you know, I wasn't wealthy growing up, but I—um—it wasn't—it wasn't for the money that I was making, it was because I was just very deeply interested in the craft itself.","offset":863,"duration":20},{"text":"Pedro: So—so that to me has always been the thing, and having this sort of—uh, respect for the—the creative energy that comes when you have an idea and saying, \"Um, how do I manifest this thing into happening?\"","offset":883,"duration":13},{"text":"Pedro: And I remember when um I built this app Quasar, and when I was 14 and it was actually a very tech—very complex um problem from a technical standpoint. You had to you know make the iPad become you know basically instead of being single processor rendering the UI, you had to make multiple processes render the UI so you needed to build a scheduler to coordinate different things rendering at the same time on the screen, which was technically complex.","offset":896,"duration":24},{"text":"Pedro: And and that to me was I just had a sense that it was possible and uh and when you have this sort of deep connection to this thing you want to see in the world, I think the way you show up and and and the hours and the time and the energy, these things all go away and you sort of uh surrender yourself to that process in a weird way.","offset":920,"duration":28},{"text":"Pedro: And and I think so much of my my journey as a builder was how do you connect to that energy? Uh and it's funny because I was telling my team that you know now with AI and a lot of the things that we're building uh in Brex and being much more hands-on as an engineer uh in a world of you know a company of like 1,300 people and a much bigger scale, weirdly enough connects me back to that very same energy that I started with and and uh coming from a very pure uh uh standpoint. So I think that's been the biggest driver for me and of course you know lot of curiosity and and energy and time but it came from a very sort of creative place versus from a like a like a like a work uh in sort of traditional sense of I need to do this and make money and there's parts that are good, parts that are not good. No, it was all great. It was all really fun.","offset":948,"duration":47},{"text":"Ashley: And so and then you're in Rio. I mean, all your peers are running around playing soccer, having a good time, going to the beach, and you're like locked in your house, like in a—yeah, in your room or what? What did it look like? I mean, what kind of posters did you have on the wall?","offset":995,"duration":16},{"text":"Pedro: Um I mean I I had a I the time I made enough money I I bought myself an iMac. Um so it was me and my Mac and just like hours and hours and hours of like coding um on you know Vim or TextMate back then was the text editor we used to use um and a lot of lots of IRC channels uh that's how I met uh GeoHot originally um and you know a lot of the folks involved in Cydia and the original jailbreak community mobile substrate there were a lot of different sort of work groups back then but it was that was my universe was sort of living this parallel reality um and you were you were kind of you were a nerd.","offset":1011,"duration":45},{"text":"Pedro: Oh yeah. For sure. For sure.","offset":1056,"duration":3}],"startTime":776},{"title":"Losing His Father & Childhood Sadness","summary":"Pedro opens up about a difficult period in his childhood, losing his father to cancer at age eight. He reflects on how this trauma shaped his need to find control through coding and praises his mother for raising him.","entries":[{"text":"Ashley: If—if I can ask, you know, when I was a teenager, both my parents got cancer and, um, you know...","offset":1059,"duration":5},{"text":"Pedro: Sorry to hear.","offset":1064,"duration":1},{"text":"Ashley: Thank you. And—and likewise to you. I mean, I mean, you're eight. Were you—were you an only child?","offset":1065,"duration":4},{"text":"Pedro: I had—I have a younger brother. Two years—two years younger.","offset":1069,"duration":3},{"text":"Ashley: OK. And so—and your dad gets cancer. When—did—I mean, if you're OK talking about it, was this a multi-year protracted thing or...?","offset":1072,"duration":10},{"text":"Pedro: Yeah. So he had—he passed away when I was eight. He had cancer for five, six years. So most of my childhood. Um, he had a lymphoma, which is obviously a relatively rare kind of cancer. Um, and, you know, cycles of ups and downs over the years. So moments that he was very well, moments that he wasn't so well. Um, but it was a big part of my—my childhood.","offset":1082,"duration":20},{"text":"Ashley: Like, how do you—I remember, you know, in the moment for me as a teenager, I mean, you—I don't think it was obvious to me sort of how it was changing me, but, you know, a year or two go by and—and you can kind of feel it. Um, was it obvious to you? You're so young. Or what is that?","offset":1102,"duration":14},{"text":"Pedro: It's funny because I—I think I fully processed that—um, maybe five years ago, when you—with the benefit of hindsight and perspective and living your own life and understanding that, you know, life is finite and all of that, and—and then you sort of appreciate the—uh, you sort of re-signify an experience you've had as a kid.","offset":1116,"duration":23},{"text":"Pedro: And—and that was probably when I really realized. But for sure in the moment, there were things that were that affected me, right? I think for a lot of this thing of building and coding, I think was how do you insert yourself in a place where you control all the variables and the entire thing is in your control because the outside world isn't? So I think that was a—there was definitely a relationship there.","offset":1139,"duration":25},{"text":"Pedro: Um, and look, I think my mom did an amazing job raising me and my brother after my dad passed away, but—but it—you see—you get exposed to, you know, yes, life is, you know, not infinite, you know, shit happens, that—that kind of thing early on, and that certainly shapes your—your brain chemistry in one way or another.","offset":1164,"duration":20},{"text":"Ashley: And so—and then your mom's a single mom from that point on. And she was—I read, it sounded like your family was kind of doctors and scientists and...","offset":1184,"duration":7},{"text":"Pedro: Um, no, my mom—she was—my mom was a—she was a psychologist, but she—she worked in, you know, psychology and then sort of marketing and, you know, bit more sort of corporate life—um, and—um, you know, worked in a few different companies in Brazil—uh, as I was growing up. Um, so—um, yeah, that was the backdrop.","offset":1191,"duration":19}],"startTime":1059},{"title":"Leaving Brazil & Meeting the Collison Brothers","summary":"Pedro talks about his initial assumption that he would live in Rio forever. He explains how building his first payments company ultimately led him to the US and to crossing paths with the founders of Stripe.","entries":[{"text":"Ashley: Were—were you like pining for Silicon Valley? Or you thought...","offset":1210,"duration":3},{"text":"Pedro: Oh, no. Um, so my original plan was to just like live in Rio. Like most people that are born in Rio—and by the way, I understand them because the city is amazing—um, they never leave the—never leave the city.","offset":1213,"duration":12},{"text":"Pedro: So my brother, for example, um, he's 27 now, and he is the sort of archetypical Carioca, like the person born in Rio, and he whenever—I think he's never going to leave. And so that—that was my sort of destiny.","offset":1225,"duration":14},{"text":"Pedro: And then um when I—we started our first company in Brazil in 2013...","offset":1239,"duration":3},{"text":"Ashley: Oh, how old are you now?","offset":1242,"duration":1},{"text":"Pedro: Uh now I'm 29.","offset":1243,"duration":1},{"text":"Ashley: 29. OK. OK.","offset":1244,"duration":2},{"text":"Pedro: Yeah. Um, so when we started that back in 2013, um, that was the first time that I actually left Rio and moved to São Paulo, um, and then decided to apply for schools in the US because, you know, we all—I always wanted to build something at a sort of US-level scale. There were not that many big tech companies in Brazil back—back at that time.","offset":1246,"duration":19},{"text":"Pedro: And we came in 2016 for—after building Pagar.me, our first company that was effectively a version of—uh, Stripe in Brazil. And then we moved to the US in 2016 to—uh, start Brex.","offset":1265,"duration":13},{"text":"Ashley: And had you seen what the Collison brothers had done with Stripe?","offset":1278,"duration":2},{"text":"Pedro: So it's so funny. We—so—so we—so we—we thought we were the original inventors of this idea of like, gosh, like payments are really bad for developers and engineers, let's build a better version. And then uh one day we we met someone and they said, \"Oh, it's just like Stripe.\" And we're like, \"What is Stripe?\" Uh, so uh we we met Patrick and John back then actually. We we know them for for a while and you know we have huge respect for them.","offset":1280,"duration":22},{"text":"Ashley: Because because they went down to Argentina or something.","offset":1302,"duration":2},{"text":"Pedro: Yeah, they actually I think they worked there in the very early days of Stripe. Yeah. But you didn't meet them on that trip? No, I didn't. I didn't. I think that was in 2011. Uh, I was still maybe doing too much jailbreaking, but but you know it was uh but we actually met them in probably 2014 or 15. Um, that's when I met I think I met Patrick for the first time, and we've stayed in touch over the years and you know we have huge respect for them.","offset":1304,"duration":22}],"startTime":1210},{"title":"Discovering the Payments Industry","summary":"Pedro traces his entry into the fintech space, starting from a job fixing iOS security for a mobile payments startup. He details his engineering-driven philosophy of controlling the entire payment stack to build a better customer experience.","entries":[{"text":"Ashley: So you're doing this jailbreaking and then Pagar.me is—is a payments system. I mean, did you feel this pull towards finance, or it was just this was a problem that you just saw?","offset":1326,"duration":9},{"text":"Pedro: Yeah. So weirdly enough, the—the way I got into it is when I was 14, I—I actually changed jobs to a company in Brazil that was building sort of a version of Square, like mobile payments in—um, in—you know, in your phone.","offset":1335,"duration":12},{"text":"Pedro: And—uh, and I went to work there initially to fix uh an iOS security issue. So I—and—and there I was inside a payments company initially through this sort of iOS security angle, but very soon realizing how bad payments were and how uh old and archaic those systems were.","offset":1347,"duration":19},{"text":"Pedro: And then I met my co-founder Henrique at the end of 2012, and he was in the sort of, \"OK, I am—I want to accept payments online, that is a really challenging thing to do. Um, there isn't a better solution.\" And then I was like, \"Well, I was inside a payments company seeing how bad it was.\" So it was a little bit, you know, 1 + 1 = 3 from the the perspective of the the idea.","offset":1366,"duration":22},{"text":"Pedro: And then as we started it, uh-uh, payments became this thing that we went very deep and and started to understand better and uh-uh, and one of the things that I think was very big for us since that very inception was um building from the bottom of the stack up.","offset":1388,"duration":15},{"text":"Pedro: So we realized that at the end of the day, um, payments companies were limited by these uh vendors that they needed to use to actually interact with the the foundational payment rails. So Visa, Mastercard, like the equivalents of ACH and and Fedwire.","offset":1403,"duration":16},{"text":"Pedro: And uh as an engineer to me I had this like very um almost religious view that you can never build a fundamentally better customer experience unless you control the entire stack all the way to the metal.","offset":1419,"duration":12},{"text":"Pedro: A little bit the version of, you know, uh-uh, Steve Jobs used to say that, you know, if you care about your hardware—about your software, you should build your own hardware and just control the whole thing vertically.","offset":1431,"duration":12},{"text":"Pedro: Um, and we did that first in our previous company in Brazil and we built the entire processing stack and, you know, the acquiring rail and Visa Mastercard connections and all of that. And then we did the same again at Brex.","offset":1443,"duration":11},{"text":"Pedro: And I think that was a big reason of a lot of this success and the, you know, where we really started to innovate and being able to go after, you know, a lot of very large enterprise companies, AI companies, because of the the vertical integration building the whole product. Uh, so—so weirdly enough, I think the engineering mindset shaped the way we ended up building both companies, actually.","offset":1454,"duration":23}],"startTime":1326},{"title":"The \"Sexy Brexy\" Car & Sponsor Pitch","summary":"The host playfully introduces a branded Brex vehicle to Pedro as part of a sponsor ad read. Pedro then delivers a quick pitch on how Brex helps companies efficiently manage employee spending.","entries":[{"text":"Ashley: OK. I'm going to be gratuitous here and just lean in. Um, so Brex—Brex is our sponsor. You told me before we started, you haven't seen our videos um that we make and and so I just want to show you, I'm going to try to do this artfully so we can have the camera see it. All right. So you have not seen this before. You've not seen Sexy Brexy.","offset":1477,"duration":21},{"text":"Pedro: Oh wow. No, but this is cool.","offset":1498,"duration":2},{"text":"Ashley: All right. So we're doing an episode in Detroit, and GM gave us a loaner car.","offset":1500,"duration":5},{"text":"Pedro: I want that. How do I get that?","offset":1505,"duration":2},{"text":"Ashley: So GM gave us this car for the week. Their lawyers did not properly—uh, the—I—I found some—some wiggle room in the contract to do with the car as—as I saw fit. And so we gave it to these guys to wrap it. And—so you've never seen this. But here we go.","offset":1507,"duration":20},{"text":"[Narrator voice on video]: Meet Sexy Brexy, the intelligent finance vehicle. Fan-fucking-tastic. While this subtle product placement is awesome, the truck is not really the point of this video. No, we are here to check in on Detroit.","offset":1527,"duration":17},{"text":"Pedro: That's so good. I love it. I love it.","offset":1544,"duration":3},{"text":"Ashley: You know, so usually around this time we have an ad read—um, and I thought since you're here, I don't know if it's putting you on the spot, what—what would you like—what would you like to say about Brex real quick?","offset":1547,"duration":13},{"text":"Pedro: They only give me 30 seconds? Well, I'll give you 30 seconds. Um, no, look, I—I think I think the reality is um we believe that managing spend is a fundamental necessity of building a great company, because you become what you spend on, right?","offset":1560,"duration":14},{"text":"Pedro: A company you're you're literally are a byproduct of your spending and resource allocation decisions. And the fundamental problem is as a company gets bigger, you look at the finance team and they are responsible for 100% of the spend, but they only make 5% of the decisions.","offset":1574,"duration":17},{"text":"Pedro: 95% of the decisions of spending in a company are made by employees and leaders everywhere uh in different offices, in different countries, and that is an incredibly complex problem to coordinate.","offset":1591,"duration":11},{"text":"Pedro: And a lot of what we believe at Brex is that typically as a company grows, because of this amount of complexity, is you have to choose either to um put in a lot of controls in place um and slow down the company because you need to have control to make sure the money is going to the right place, or you take off controls and then you increase speed.","offset":1602,"duration":24},{"text":"Pedro: So speed and controls are this tradeoff. And the reason we built Brex is to break that tradeoff and give companies the agility of a startup all the way uh into becoming, you know, some of the largest companies in the world um that run on Brex today.","offset":1626,"duration":15},{"text":"Pedro: Um, so you know today we serve, you know, um more than 35,000, 35,000 from startups to the world's largest corporations. Uh, and you know 300 plus public companies uh including you know like uh Zoom uh you know Palantir, Anthropic, and as of two weeks ago, OpenAI. Uh, yes, um...","offset":1641,"duration":21},{"text":"Ashley: I've done this before.","offset":1662,"duration":1},{"text":"Pedro: Robinhood and you know we you can go to our website and see the customer list, uh-uh, which is really exciting. But one of the things we're really proud of is um when you're looking into AI, um we spend a lot of time making sure that we think about the role and how the finance function will fundamentally change.","offset":1663,"duration":17},{"text":"Pedro: And all the big AI labs today and, you know, like Cursor, Vercel, of course OpenAI and Anthropic, um, Mercor, um, you know, all these companies run on Brex because of uh looking at our AI vision and believing that this is the way finance is going to work.","offset":1680,"duration":21},{"text":"Pedro: And of course they looked at all competitors and all the alternatives in the space and still ended up going with us, which is a a very cool uh proof point, I guess, of the way we're building the product towards the future of finance.","offset":1701,"duration":13},{"text":"Ashley: All right, that was longer than 30 seconds, but we'll—we'll allow it. Uh, what did—yeah, what did you think of Sexy Brexy?","offset":1714,"duration":6},{"text":"Pedro: I loved it. Uh, it's really cool. Very cool, right? Very cool. I want to get the car.","offset":1720,"duration":6}],"startTime":1477},{"title":"A Brief Stint at Stanford","summary":"Pedro discusses briefly attending Stanford University alongside his co-founder Henrique. The two ultimately left after less than a year to pursue their entrepreneurial ambitions.","entries":[{"text":"Ashley: We can make that happen. We can make that happen. Um, OK, so you know, you—you meet Henrique, you guys apparently get in a fight, a Twitter spat at first, but then become best of friends and—and business partners. You both head off to Stanford together. Um, it's kind of amazing that you both got into Stanford.","offset":1726,"duration":20},{"text":"Pedro: Yes. He convinced me to apply, actually. I decided I I heard what an SAT was for the first time I think was in mid-September 2023, and deadlines were in December. So that was a busy two and a half months.","offset":1746,"duration":16},{"text":"Ashley: OK, yeah, I bet. And—and so you—you get into Stanford, you guys—you don't stay around too long. About eight months, I think. Um.","offset":1762,"duration":7},{"text":"Pedro: That was not the original plan. Yeah. But um.","offset":1769,"duration":2},{"text":"Ashley: So it was like a semester and a bit?","offset":1771,"duration":2},{"text":"Pedro: Uh, three quarters. Yes, three quarters. Stanford is a quarter system.","offset":1773,"duration":3}],"startTime":1726},{"title":"Pivoting to Brex & Underwriting Startups","summary":"Pedro recounts joining Y Combinator to build a VR startup before quickly realizing it wasn't a fit. They pivoted to Brex after noticing that well-funded startups were unable to secure corporate credit cards from traditional banks.","entries":[{"text":"Ashley: OK. OK. And so you're you're already on to um you're thinking about your next idea. I mean, the one part that I picked up on was that you guys get into YC, you start with a VR company, and then it kind of pivots into Brex.","offset":1776,"duration":15},{"text":"Ashley: I mean, that's a pretty dramatic shift. I was I was curious about a couple things. I mean, as you're going through this um very um unusual childhood and working on these different projects, did you what did you picture in your head? What was your dream? Like, was finance the end goal?","offset":1791,"duration":20},{"text":"Pedro: So—uh, it's funny because we moved to the US and we spent four or five years building fintech in Brazil, you know, one or two before Pagar.me, then three and a half at Pagar.me. And the funny thing is when we came to the US, we had this idea of, you know, fintech is a solved problem in the US.","offset":1811,"duration":19},{"text":"Pedro: Brazil is this, you know, shitty country where, you know, fintech is still unsolved, that's why it was an opportunity. But here we want to be at the forefront of technology, so we went to this um Microsoft store at Stanford Shopping Mall back in 2016 and we tried um um the first Oculus prototype.","offset":1830,"duration":17},{"text":"Pedro: Like a early early version of Oculus. I think Oculus Rift or something. And we're amazed. So we thought, let's just go build that. And uh in a very like uh uh naive way we thought we could do it.","offset":1847,"duration":14},{"text":"Pedro: And then, you know, we spent, I don't know, two or three weeks playing with the hardware and the software and the technology, and we realized that, you know, it required—we knew nothing about hardware, nothing about optics.","offset":1861,"duration":12},{"text":"Pedro: And then—uh, we decided to pivot to something that we knew a little more, which was software. So—um, it took us maybe three or four weeks to pivot again. And then in YC, we saw that all companies needed a corporate card, and they couldn't get one.","offset":1873,"duration":13},{"text":"Pedro: So they went to the banks and they got rejected. The bank said, you know, you have no revenue history, and they said, yes, that's the point, that's why I'm a—that's why I'm a startup. And—and...","offset":1886,"duration":11},{"text":"Ashley: So even though you might have like seven million bucks in your bank account, you couldn't get a corporate card just because you don't have this track record.","offset":1897,"duration":7},{"text":"Pedro: Exactly. Um, and we thought, well, but they have cash in the bank, so what's the risk? And the bank didn't get that. So that was the original idea that uh allowed Brex to scale was underwriting the companies based on cash and effectively build a better American Express. That was the original original thesis and...","offset":1904,"duration":17},{"text":"Ashley: So it's supposed to be Brex, Brazilian Americ—well, instead of Amex.","offset":1921,"duration":5},{"text":"Pedro: Brazilian Express, yeah, that's—that's—uh—so—so the myth goes. OK. Um, but—but yes, um, it was a four-letter domain pronounceable in English with a backdrop name, uh, backdrop story for sure.","offset":1926,"duration":13},{"text":"Pedro: Um, so—so that that's how it got we got it off the ground. And it turns out it was uh one of the things that was interesting between Brazil and the US is there's actually this weird uh-uh negative correlation between how developed an economy is and how bad I think their payment rails are.","offset":1939,"duration":22},{"text":"Pedro: So, you know, when I was born in Brazil in '96, we had real-time settlement. Like the day I was born, it was not cheap, but you could settle a wire in real-time. We're in the US now um in 2026, right? 29 years later. And you still don't have, you know, you have like partly, but you cannot—like not all payments are in real-time yet.","offset":1961,"duration":18},{"text":"Pedro: And the reason is because when you look at Brazil in the 90s, we had hyperinflation. So the inflation was 30% a month. So if you didn't clear in two days, you lost like, I don't know, like 5-7% of the value of the money.","offset":1979,"duration":12},{"text":"Pedro: So there was a very deep investment in the payment rails because the economy needed it. And then the US, because it's such a stable economy and such a stable currency for, you know, hundreds of years, I—I don't think was as developed.","offset":1991,"duration":12},{"text":"Pedro: So weirdly enough, we saw a lot of room to actually revamp a lot of the financial stack in the US in a way that was bigger even than Brazil just because of the scale of the US economy.","offset":2003,"duration":14}],"startTime":1776},{"title":"Why US Financial Infrastructure Lags Behind","summary":"The discussion shifts to a comparison of international payment systems. Pedro explains how the US's economic stability and fragmented banking system have ironically caused its payment infrastructure to lag behind countries like Brazil.","entries":[{"text":"Ashley: People explain this to me sometimes. I mean, it's, you know, if you go to Europe, they're doing all kinds of amazing like very interesting stuff with financial systems. When I go to China, it's insane.","offset":2017,"duration":13},{"text":"Ashley: Yeah. Even like I went to Nigeria to shoot an episode of our show and, you know, there's parts of it that are like really backward, but then there's other parts where you you're just paying for your cellphone at like whatever the chicken shop and... mobile wallets, yeah.","offset":2030,"duration":14},{"text":"Ashley: Um, and then, you know, South America's—in Mexico are quite famous for innovating um on financial tech. And so the US always seems to be behind. It reminded me of like when I was starting out as a reporter, we were just woeful at telecommunications and Europe was so far ahead. And then and then like the iPhone like sort of rescued the US and made it interesting again.","offset":2044,"duration":21},{"text":"Ashley: But um I mean people have told me—you went over some of the points of this like stability—but other people have said to me it's because we have our banking system is so fragmented.","offset":2065,"duration":7},{"text":"Pedro: We have thousands of banks in the US. So uh for example, like Brazil, the Central Bank created this payment rails called Pix, which is effectively a real-time uh settlement between any two accounts. You can use your phone number or your tax ID as—as a key, and then it found—it finds your bank account and you can—I can transfer money to you right now, like almost any amount.","offset":2072,"duration":21},{"text":"Pedro: Which by the way has other uh-uh security implications in Brazil, which the system ended up handling later, but that's a separate story. And then in the US—but in Brazil you have really probably 30 major banks.","offset":2093,"duration":12},{"text":"Pedro: In the US you have thousands, like two or three thousand banks today. So when you want to roll out anything new at a systemic level, you have to go in bank by bank and make sure they comply.","offset":2105,"duration":11},{"text":"Pedro: So even if you look at uh RTP, like real-time payments, today, um, the ubiquity is of course the big banks support it, but if you're transferring to a community bank or a regional bank, a lot of times they don't support because, you know, technology is really behind in terms of adoption.","offset":2116,"duration":16},{"text":"Pedro: So being more concentrated also allowed for uh a faster innovation cycle. So but I would say it was uh the fact that the economy really needed it, right?","offset":2132,"duration":10},{"text":"Pedro: In Brazil, we because a lot of the payments were in cash and and offline um and and even on cards, um the government saw this need for first sort of bringing and modernizing payments.","offset":2142,"duration":12},{"text":"Pedro: And the Central Bank in Brazil I think did an amazing job with that, and and then second was moving more of the economy outside of cards into something that the government had more agency over. Um, and these movements were easier just because of, like, one, the pain point that existed and, second, the concentration of banks.","offset":2154,"duration":19},{"text":"Ashley: I'm going like—I was going to go chronologically, but now I just want to talk about this for a second. I mean, so the US is—is like destined to be woefully behind the rest of the world on—on many interesting financial innovations. Like, we're stuck unless we kind of change the...","offset":2173,"duration":18},{"text":"Pedro: Yeah. And the US has this like has a lot of uh sort of particular things that, you know, when you look at the the amount of the economy and and credit cards, for example, of course you have uh, you know, you have rewards, which is a very big part of the decision-making factor.","offset":2191,"duration":19},{"text":"Pedro: Um, you have uh uh no real-time payments in some things um and especially most money movement actually not real-time today in the US. You still have a lot of ACH that takes two or three days to clear. Um, you have uh you have, you know, there's no for example something you have in in Brazil, which I think is fascinating, is you have a clearing house for receivables.","offset":2210,"duration":21},{"text":"Pedro: So because because the interest rate is so high and the country um is so dependent on uh on factoring of any receivable you have when you have a contract or something, you actually have a centralized clearing house that you can register a contract and get a prepayment on that contract.","offset":2231,"duration":17},{"text":"Pedro: Doesn't exist in the US. So there's a lot of things that are that are very different um but at the same time creates a lot of opportunities for companies like us to to go in and do new things.","offset":2248,"duration":9}],"startTime":2017},{"title":"Capital One Acquisition & Integration Strategy","summary":"Pedro addresses Brex's $5.15 billion acquisition by Capital One. He explains the rationale of pairing Brex's modern software with Capital One's massive scale and resources while preserving the startup's unique culture.","entries":[{"text":"Ashley: But—and OK, and then, you know, this next question comes with some baggage, because you've just—your—you're part of—you're going to be, whenever the deal closes, part of Capital One. This is a traditional um financial player.","offset":2257,"duration":14},{"text":"Ashley: I—I've just always found this shocking, you know, because I followed Stripe. I knew Patrick and John when they were like, I don't know, there was like eight people in the room or something like that.","offset":2271,"duration":8},{"text":"Ashley: And and then just the story you were describing about startups had money in the bank, people wouldn't lend to them. I mean like it's sort of I mean in some ways it makes sense because this is the story of business is that incumbents move slow and don't see opportunities in other ways.","offset":2279,"duration":18},{"text":"Ashley: I find it really shocking that that like Stripe could become such this foundational layer, this massive multi-multi-multi-billion dollar business that that the traditional financial companies were just apparently, you know, willing to to cede to these two Irish kids.","offset":2297,"duration":16},{"text":"Ashley: You—Brex just took off like a rocket ship from this this insight that you guys had and you being able to code all this infrastructure to make it happen. Um, yeah, like like are there still—is that typical? This is the same as I would see if I went into the energy industry or defense, or is finance uniquely um kind of conservative and bad?","offset":2313,"duration":30},{"text":"Pedro: I think I think I think it's, you know, if if the history of technology serves us any any any uh backdrop, I would say I don't think finance is too dissimilar.","offset":2343,"duration":12},{"text":"Pedro: What I would say is I think the interesting aspect is first the just the scale that finance has in terms of how businesses operate and how uh ubiquitous it is as a part of what makes just the US economy work.","offset":2355,"duration":15},{"text":"Pedro: So, for example, you look at Brex and we created this new category of, you know, modern modern uh software and financial services together. Um, you know, when you look into the US economy today, we've made a lot of progress, but 97% of the US economy still runs on traditional corporate cards.","offset":2370,"duration":20},{"text":"Pedro: 97%. And and there's a lot of room to grow in terms of just expanding what we've done and serving the rest of the market. And when we when we, you know, got approached by Capital One, the the interesting thing for us was we started just think, OK, where can the company be let's say in five, seven, 10 years in a standalone path?","offset":2390,"duration":21},{"text":"Pedro: And then what if we joined forces with uh an incumbent, but actually I think the most tech-forward bank in the world, um, that, you know, really realized that you could bring in data and machine learning and technology to revolutionize credit cards and the way underwriting was done. And by the way, there's sort of fascinating stories of how Capital One started that.","offset":2411,"duration":21},{"text":"Pedro: Um, and what could we do having that platform and that scale? And as we started to click into that, it was impossible to unsee it. And and really the the way to think about it is how do you bring the scale, brand, credit of, you know, major US financial institution with the technology and product we have?","offset":2432,"duration":21},{"text":"Pedro: And in a in a very interesting way, the thesis behind this is exactly what you were describing, is how do you accelerate the adoption curve of this technology that we believe should be core to how every business runs, but do it at a scale that is country affecting, right?","offset":2453,"duration":20},{"text":"Pedro: That you actually inflect uh the outcomes of so many businesses that depend on these things to to run and operate and are still working, you know, in with technology of like 30, 40 years ago.","offset":2473,"duration":16},{"text":"Host: Hello, geniuses. Let me tell you about E1 Ventures. They are a venture capital firm in Silicon Valley, a long-time supporter of this podcast and a long-time supporter of big, fantastic, world-changing ideas.","offset":2489,"duration":19},{"text":"Host: If you have such an idea, hit up E1 Ventures or send me a note and I'll put you in touch with E1 Ventures. It's uh it's quite a quite a deal for listening to this podcast. Um, thank you again, as always, to E1 Ventures for their support.","offset":2508,"duration":14},{"text":"Host: So like in these things, I mean they do work sometimes these types of arrangements. It's also not uncommon for the big incumbent company to to reject, you know, the innovation arm that they have purposefully set out to acquire, you know, for that very reason. Yeah.","offset":2522,"duration":18},{"text":"Pedro: So it's funny because one of the things that—well, two things I was very impressed by Capital One. One was just the speed. So from inception of this idea all the way to sign definitive agreement was a little over 40 days. So they actually moved with a lot of conviction and speed.","offset":2540,"duration":21},{"text":"Pedro: And second was the fact that being a founder-led company really changes the calculus for how you do things. And and speaking to—to Rich and the Capital One team, um, one of the major things that that they they realized was, \"Look, you know, the most important thing for us to think about as we make this work is don't crush the butterfly.\"","offset":2561,"duration":22},{"text":"Pedro: So how do you how do you leverage the scale and the distribution and all the benefits of Capital One, but also keep the things that are uniquely Brex and make Brex into what it is today alive and growing and...","offset":2583,"duration":13},{"text":"Pedro: The way Rich the founder describes it is uh, \"How do we just add water?\" To the Brex plant? Uh, and of course, you know, be very mindful about the the risk management aspect and the aspects that are inherent to being a bank. Um, but also leverage the scale and the distribution.","offset":2596,"duration":16},{"text":"Pedro: So I would say there's been so much thoughts on how to make this as lightweight of an integration as possible to preserve the momentum that Brex had as a standalone company and actually accelerate it.","offset":2612,"duration":14},{"text":"Pedro: So um, you know, what when you look into the the outcome here, um, we really think in three to five years the company will be just dramatically bigger than than what it would be on a standalone basis because of the water and the scale that Capital One brings.","offset":2626,"duration":15}],"startTime":2257},{"title":"Resetting Brex's Valuation & Repricing Equity","summary":"Facing questions about a previous $12.3 billion valuation, Pedro details the tough decisions made to restructure the company. He explains the move to reprice employee equity to ensure the acquisition remained a massive win for the team.","entries":[{"text":"Ashley: Uh, let me—let me ask one annoying reporter question. I mean you at one point you guys are valued at 12.3 billion dollars in 2022. Uh, different world for variety of reasons.","offset":2641,"duration":12},{"text":"Ashley: You sell the company for 5.15 billion. I mean look, I think anyone would be happy with that outcome. But it is the nature of the beast then that some people compare your previous valuation to this number, and we're in this like total frenzy of of you guys...","offset":2653,"duration":19},{"text":"Ashley: Uh, some companies that shouldn't be named, um, you know, all um competing against each other very very vocally, very aggressively. I saw some some ramp cheerleaders, you know, celebrating this 5.15 billion dollar number. Um, yeah, I mean it's got to be a weird feeling to like you're having this great moment.","offset":2672,"duration":22},{"text":"Ashley: Yeah. There's a lot of money. You've accomplished something. It marks a moment in time. And then...","offset":2694,"duration":6},{"text":"Host: I guess it's competition, but then for it to be portrayed by some people one way.","offset":2700,"duration":5},{"text":"Pedro: So, so I think there's two sides of this. So the first one is, one of the things that we realized in 2023 is the company was in a very different position than today. And, and we decided to sort of aggressively turn things around, and that was end of '23, early '24.","offset":2705,"duration":20},{"text":"Pedro: And one of the things that we did that was very unpopular and, and extraordinary back then, is we actually did a big reset on the internal valuation. So, so, you know, yes, of course, we raised at $12 billion, that's, you know, that's a fact, but at the same time, how do you create enough upside for employees so that a $5 billion outcome is a win?","offset":2725,"duration":24},{"text":"Pedro: And that's what we did. So we went to the board, we actually repriced all the employee equity at a much different price. And that effectively, really changed the picture for employees and the team. And, you know, investors that invested at 12 billion, of course, you know, got their preference back. So, so it ended up being actually a very good outcome for everyone.","offset":2749,"duration":22},{"text":"Pedro: But the, the key thing was, in the moment where things were, were the hardest, like three and a half years ago, actually looking ourselves in the mirror and saying, \"Look, um, you know, I always say, you know, hard decisions easy life, easy decisions hard life.\" And the hard decision was, we let go of, you know, almost 30% of the company, we repriced the equity, we changed the way we operate a lot.","offset":2771,"duration":22},{"text":"Pedro: We promoted a lot from within. Uh, we took out two layers of management in the entire company, and we, we started this thing that, that I called Brex 3.0. Uh, so, so that backdrop was how we got to where we are today. And by the way, where we're still accelerating even faster than when we closed the deal, uh, uh, when we signed the deal back in, back in, uh, January.","offset":2793,"duration":25},{"text":"Pedro: So I would say the best way to think about it is we made a lot of deliberate decisions two and a half, three years ago that made this a win for employees because we decided to face reality and, and actually look at it with the lens of: everything eventually converges to public markets. Whether you like it or not, that's the only price signal that really matters. So how would you think of the company today if it was a public company?","offset":2818,"duration":26},{"text":"Pedro: And how do you ground ourselves in that reality, uh, as hard as it may have was in my be because, you know, the fairy tales of 2021 were just that—fairy tales. So then, and then I think the second piece is, you know, of course there's competition in the space, it's a massive part of the US economy, massive part of fintech, and it would be ludicrous to think that there wouldn't be.","offset":2844,"duration":24},{"text":"Pedro: But I think the, the best way to think about it is, you know, us and all modern competitors in the space, we're still 3% of the US market. So, so the question becomes: how do you go after the 97%? And, and what we decided to do at Brex is we said, \"Look, the reality is the chances of hitting two orders of magnitude bigger scale together, partnering with a massive incumbent, are fundamentally different.\"","offset":2868,"duration":27},{"text":"Pedro: And, uh, as we started to actually just see the scale of, like for example, like Capital One spends $6 billion a year in marketing. Um, we spend, you know, around 1% of that. Um, $6 billion in R&D, we spend, you know, 2 or 3% of that. So, so when you just apply the scale into the problem, and you just accelerate what's working, um, the question for us was: how do you solve for the 97%?","offset":2895,"duration":29},{"text":"Pedro: And, and how do we be the clear winner there? And subordinate all decisions to that, including structure, the capital, you know, all that, because for me, it was always about at the end of the day, I wanted Brex to become a major part of the US economy, Brex to outlive and outlast me. And the same way I look back, I left my previous company in Brazil 10 years ago, and Pagar.me is still second or third largest player in Brazil in online payments.","offset":2924,"duration":26},{"text":"Pedro: Um, I want the same to be true at Brex, and I want to be here for the next many years, um, and, and, but, but still I think the, the scale, solving for scale and just the reach of this technology in the way the average business runs was, uh, fundamentally a different thing to solve, and it's still very early days.","offset":2950,"duration":23}],"startTime":2641},{"title":"Navigating a Fast-Paced Career","summary":"The host asks if Pedro feels he is actively directing his life or simply being swept along by its rapid pace. Pedro reflects on how mastering a domain like fintech creates compound knowledge that naturally reveals new opportunities.","entries":[{"text":"Host: Well, please introduce Capital One's marketing budget to sexy Brex, say, and let them know what's possible. Um, and, okay, in, as far as like, you've been on this, um, I mean, it just feels like a whirlwind, man. I mean, you starting, you know, a business around 12, and then here you are, you're 29, I mean it's been nonstop, one thing after another.","offset":2973,"duration":24},{"text":"Host: You've been actually, like to your credit, uh, super open, you write these essays from time to time about, about big moments in your life, mental health things, um, things about, you had this really nice note about your mom, um, and I know you talked about some of the decisions she had made, but you know, she seemed um like a kind of like unconventional thinker around, around a variety of things with this, this kid who was, who was living an unconventional life.","offset":2997,"duration":27},{"text":"Host: And so anyway, I found your like really, you're quite thoughtful and open about these things. Um, do you, is there like part of you though, yeah, that just feels like you've been on this, you've just been carried, you know, not like you were, um, not an active participant, but I mean more that you've been bounding from one thing to the next on this ride?","offset":3024,"duration":23},{"text":"Host: Like is there, I always ask the Collisons this, okay, because they're like two of the smartest people I know, they are uh polymaths, they're interested in so much different stuff. Um, I know financial tech is very important, it's not the particular thing that like I think about all the time, and so you know, I'm always like, \"What do you guys, what do you guys like want out of life?\"","offset":3047,"duration":23},{"text":"Host: You know? Because, because is this, is this just a thing that you made when you were young and it turned into this huge hit, and you're, you're trying to, they always talk about increasing the GDP of the internet and the world, and I see that, right? It opens, I went with Patrick to, uh, Israel and Palestine and I saw people who were setting up businesses on Atlas that like otherwise just could not incorporate their company and now they're selling to the entire world.","offset":3070,"duration":22},{"text":"Host: So like I get it, I'm not trying to undermine something, but um like is there part of you that just feels like you've, are you making all these conscious decisions or you've just been pulled on this journey?","offset":3092,"duration":12},{"text":"Pedro: Yeah, it's, it's a great question. I think, I think I think it's a little bit of both, because I, I would say on one hand, you know, I, I really like to believe that, especially now with AI, learning new things is a fundamentally lower barrier than it's ever been. So if I said, \"Look, I'm going to learn how to make X,\" I think it's possible to learn and master that.","offset":3104,"duration":24},{"text":"Pedro: At the same time, I think the sets of opportunities that exist that are interesting, they tend to be related to domains that you explored in the past. And, and I think your ability to recognize what's a good opportunity is also higher in things that you have more exposure to. So I don't think we would have been able to build Brex if we hadn't built our first company in Brazil, because we just knew too much about payments.","offset":3128,"duration":25},{"text":"Pedro: Uh, we were just very deep in the weeds, we knew the issues with credit card issuing, we knew like what the acquiring side looked like on the merchant side, uh, we knew a little bit of credit underwriting, our first company was also regulated by the Central Bank, uh, and we were the officers of that. So, so there were a lot of conditions that made Brex possible. So in a weird way, I think you create this set of experiences that make the next thing possible.","offset":3153,"duration":24},{"text":"Pedro: And, and I think there's something that, that Jensen says that I think is really true, which is, you know, at the end of the day, it's easier to learn to fall in love with what you do than to do something that you love. Because I think when you think about love and, and sort of a deep connection to a craft, ultimately something that I think is very deeply encouraging is when you feel the sense of mastery with something.","offset":3177,"duration":26},{"text":"Pedro: And not from an ego perspective, but from the perspective of: I just understand every layer of this problem, and I can think about second-order effects, I can think about implications, and I can see the world through a much bigger aperture because I have this unusually high exposure to this problem. And, and I think there's something about that in fintech where, you know, the more you think about, you know, and we see this with AI, like we, you know, we spend a lot of time looking into like what actually changes when you, when you start to deploy AI agents in companies.","offset":3203,"duration":31},{"text":"Pedro: And of course, the early things are, yes, there's a bunch of cost savings. Like second, there's, you know, compliance increases and data quality increases and automation increases, but, but then you look into like a layer deeper and you see like: okay, how much time does the, does the US economy spend like managing expenses? And turns out it's 50 million hours.","offset":3234,"duration":25},{"text":"Pedro: And then we're like, \"Okay, like how many things can we do, possibly, that contribute 50 million hours to the US economy?\" And, you know, we build these agents that automate all of the tiny processes and, uh, and, you know, you see the impact inside a customer and it's pretty remarkable, the reactions of the finance teams as they say, \"Wow, I actually didn't even think this was possible, even with technology today.\"","offset":3259,"duration":21},{"text":"Pedro: And this is like, by the way, on like Anthropic and OpenAI, like that are sort of at the bleeding edge of AI and deploying AI internally. So, so but then it's like: okay, how would we even recognize that that opportunity existed? Um, and it goes all the way down from, well, you know, yes, we were building corporate cards originally, and corporate cards are a big part of how spend gets initiated in the company.","offset":3280,"duration":24},{"text":"Pedro: And it turns out that, you know, initiating and making spend decisions requires, you know, a lot of sort of delegated decision making, so you need to create tools that empower the finance team to be in every decision. What can help with that? AI. And then, well, how to make AI really, you know, really effective at scale and give the finance team control over how AI is operating? And then you build a lot of agents.","offset":3304,"duration":23},{"text":"Pedro: So, so you sort of, you sort of cascade this down, and there's seven or eight hops from the original idea all the way to the outcome that we deliver today. And these things were recognizable because of a previous pattern. So, so I think that's the part that's like hard to understand, to, to overstate. I wouldn't say that it's, I am sort of a uh, like I, it would be irresponsible to not do something that's not fintech, like, like, but there's something to be noted about the fact that you get to certain places because of where you've been in the past.","offset":3327,"duration":37},{"text":"Pedro: And uh, I'm grateful for the, the experiences that sort of exposed me to the the issues and the problems and the solutions that I was able to build by having been on this track.","offset":3364,"duration":12}],"startTime":2973},{"title":"Exploring AI Agents & Virtual Employees","summary":"Pedro shares his recent fascinations with robotics and AI agents. He describes how Brex is developing virtual employees for internal tasks and utilizing LLMs to monitor the security of other AI systems.","entries":[{"text":"Host: And do you think this is going to, maybe it's really hard, I mean you're still so young, 29. Um, you know, I read about you being obsessed with space documentaries when you were a kid. Um, you know, I hit you up on a, on an AMA asking what you were interested in outside of, of fintech and you mentioned space and energy. Do you think there's like another chapter in your life where you dig in on something like that, or is that something maybe you're investing in and, and it's on the side?","offset":3376,"duration":29},{"text":"Pedro: Yeah, I mean, I am, in the, in the sort of spirit of both topics, you know, I'm actually very curious about robotics now and trying to understand what's at that frontier. And of course, you see Tesla and Optimus and all that, but also what are sort of more bootstrapped versions of that in, in new companies building things that are pretty uh interesting? So that's been a, the a big area.","offset":3405,"duration":27},{"text":"Host: Meaning like you, you just keep an eye on it or you're, you're participating?","offset":3432,"duration":5},{"text":"Pedro: I, I, I mostly keep an eye on it and try to, you know, angel invest in a few things. But, but I would say that's sort of a newer curiosity over the past maybe like three to six months. Um, when you look into like things I'm spending a lot of time um is, is, uh, you know, I am really interested in this idea of virtual employees. So how do you actually deploy virtual employees inside a company that look and feel and act like an employee?","offset":3437,"duration":26},{"text":"Pedro: So they are real people with real names on Slack, on email, engaging with people, joining meetings. Um, I got obsessed with Open-webUI over the past like three months, uh, and, uh, you know, automated my entire life. I can tell you more about that, but, but these are the things that I'm spending a lot of hours now.","offset":3463,"duration":19},{"text":"Host: No, no, please do. Do you have a, do you have a human admin?","offset":3482,"duration":4},{"text":"Pedro: I do, I do.","offset":3486,"duration":2},{"text":"Host: And then is this human admin competing against your virtual admin?","offset":3488,"duration":4},{"text":"Pedro: Um, they, they, I would say they don't overlap as much, per se, uh, deliberately. My, my human admin is amazing. But, uh, I would say, no, so look, I think the, how we got here, right? And I think Opus 4.5 was AGI, or very close to AGI, and Opus 4.6 was the sort of missing, missing—the sort of rough edges that, you know, got a little better.","offset":3492,"duration":24},{"text":"Pedro: So the way I think about it is, you know, electricity was invented in December. We're now in March. Uh, what are the things that you can build with electricity now? And that is the, the big question. And to me, the fundamental capability jump was uh, that of course coding models were the, the very interesting thing that, that and you see Claude Code and all these, these agent harnesses evolving.","offset":3516,"duration":26},{"text":"Pedro: But I actually think the most interesting property that was unlocked was, uh, the capability of a model to self-bootstrap. So, so basically one of the things we're experimenting now at Brex is actually using Open-webUI to create virtual employees. So, uh, we created this, like, virtual recruiter, for example. Uh, we call him Jim. Um, and Jim is literally a Slack entity, a Slack person, has his own email, and engages and talks to recruiters internally.","offset":3542,"duration":27},{"text":"Pedro: And the thing, the whole, the whole challenge was: how do you build Jim without writing a single line of code? Um, and the idea is, and of course, there was still semi-technical people involved because it was one of our first early iterations of this. But the really interesting thing is, you see a recruiter engaging with Jim, and then saying, you know, for example, I just saw this before coming in here, a recruiter was saying, \"Look, can you take a look at this person's application? I have a sense that this resume was fabricated. So how do, how do you look at that?\"","offset":3569,"duration":29},{"text":"Pedro: And then the agent looked at that and actually built a capability of screening a resume and understanding if it was fabricated or not. And that was never coded by anyone. And I think that's the fundamental leap that we were missing. And a lot of what we're spending time thinking is how to deploy this safely, of course, inside Brex, and there's a lot of things on the security side that we're also spending a lot of time.","offset":3598,"duration":23},{"text":"Pedro: Because I feel the challenge that the industry is in now is people say, \"Well, you can't predict what models do, they're not safe, therefore I'm not going to use something like Open-webUI in a very, you know, in a very important environment because who knows what's going to happen.\" And the stance that we decided to take is saying, \"Well, why don't we just solve for that security aspect and then actually deploy these things internally and leverage that technology and, and see where the frontier really is.\"","offset":3621,"duration":27},{"text":"Pedro: Um, so, you know, we, we're actually going to open source this, but we actually built this entire, like, technology layer. Um, we actually call it Crabtrap, uh, funnily enough, where the idea is when you have something like Open-webUI running, um, we, the best way to monitor what an agent is doing isn't to have a human looking at it, it's actually to have another LLM looking at it.","offset":3648,"duration":22},{"text":"Pedro: So we build this thing that effectively intercepts all the traffic coming out of like an Open-webUI instance and routes it through another LLM that's through uh an HTTP proxy that screens all the traffic and says, \"Is this something that a recruiter agent should be doing?\" So, for example, should a recruiting agent send like a harmful message to a candidate? No. Um, and it can go in and block that request at the network layer, while the agent itself is even not even aware that that's happening.","offset":3670,"duration":30},{"text":"Pedro: And the really cool thing of that is you can actually run this at scale, and the only technology that we think will be able to monitor agents is actually agents themselves. But you build this almost adversarial effect where you have one agent monitoring another agent, um, and we've seen surprisingly good outcomes of this thing so far.","offset":3700,"duration":21},{"text":"Pedro: So, uh, does that mean that we're deploying, you know, Open-webUI and virtual employees in the most critical workflows in the company? Not yet. Um, we're deploying in a few. But the really interesting thing is, instead of saying, \"Well, let's hold back and not deploy these things because at the frontier we haven't resolved security yet,\" we said, \"No, no, why don't we just solve security?\"","offset":3721,"duration":21},{"text":"Pedro: Which is a, a systems problem, um, it's a distributed systems problem more than anything else. It's an engineering challenge. And then the technology and the LLMs and the state of the art of the models is already like wildly capable except for this one problem that we'd rather solve against, around. Um, so that's been like fascinating.","offset":3742,"duration":22}],"startTime":3376},{"title":"Automating His Personal Life with Open-webUI","summary":"Pedro outlines the complex AI autopilot system he built to ingest signals, filter information, and execute tasks on his behalf. He also shares that he implements \"no AI Saturdays\" to give himself a break.","entries":[{"text":"Host: And then and you were saying and you're using Open-webUI like in your life? I mean is this the stuff you're talking about or you more personal?","offset":3764,"duration":7},{"text":"Pedro: Oh yeah, well, no, this is we're using Open-webUI in a bunch of different contexts. Yeah, virtual employees is one. The other one is, uh, um I use it personally to do everything, um at this point. Uh, like I literally run Brex through Open-webUI right now.","offset":3771,"duration":16},{"text":"Pedro: So the the way it works is, I think most, there's a lot of productivity tools with AI, right? And I think the thing they fail is that they they don't assume that the world is a very noisy place. So when I go into Brex, Brex has like thousands of Slack channels, like thousands of people, thousands of—I receive like hundreds of emails a day. And the question is like: what matters? Like what what to pay attention to?","offset":3787,"duration":25},{"text":"Pedro: So I built this um this uh autopilot system that starts with this uh signal ingestion pipeline. And basically the way it works is it screens my email, my Slack, uh Google Docs, um WhatsApp, a few different data sources. And then, but the really interesting thing is I decided to build my automation in my life around two concepts: uh people and programs.","offset":3812,"duration":328},{"text":"Pedro: So programs is almost like a project that I want to be updated on. So, for example, financial performance of the company, um Capital One integration, um uh AI strategy internally. And the thing about a program is it's very declarative about what I care about and what I don't care about. And then what it does is it screens those signals in the context of these programs and then organizes, you know, interactions that happened that I should be aware of or action items.","offset":4140,"duration":30},{"text":"Pedro: And then it does the same for people. There are also people that I care about. So I declare who are the people that I care about, and there's probably 25 people in the company, um and in my my life more broadly. I declare those people and what are the things that I actually care about. And then the signal ingestion filters with the lens of these people, you denormalizes signals and then it processes them. And then it produces this very clean uh summary of everything that's happening in the company that I should care about and all the action items.","offset":4170,"duration":31},{"text":"Pedro: And then then there's the really cool part, which is all the action items that I should do are things like, \"Well, I finished the customer conversation, I need to go in and update the the deal team on that account,\" or \"I had a meeting, someone asked me for an intro,\" or or all these things that are follow-ups from meetings.","offset":4201,"duration":17},{"text":"Pedro: And then the cool thing is because I have the signal ingestion, I can go in and I have this other thing called an auto-resolver that it can go into the list of to-dos that I have and say: how do I automatically action this task based on the context from the meeting?","offset":4218,"duration":15},{"text":"Pedro: So, for example, like let's say I go in and I say, you know, uh we should talk about, I want to figure out how to get that card. Uh let me have a follow-up on that. So then I can have Granola listening to the conversation. Granola is running on every meeting that I have, ingesting that into the signal ingestion pipeline, creating an action item.","offset":4233,"duration":19},{"text":"Pedro: And then when the auto-resolver runs, it says, \"Okay, what's the context for this to-do, this task that I have?\" It will go back to the notes, and then it can say, \"Well, I can send you a text or send you a Slack message or you an email, depending on, you know, whatever is best.\" And then it can draft that message automatically.","offset":4252,"duration":13},{"text":"Pedro: And then all I have to do is click a button. So all these are building blocks and skills that you can build together. Uh you can do it either on Open-webUI or or Claude. I actually have it running on Open-webUI now to effectively decompose the CEO job of like ingesting signals, what matters, building a summary, determining tasks, making those tasks happen, monitoring my team for those tasks, so it also can do follow-ups automatically.","offset":4265,"duration":27},{"text":"Pedro: Uh, and I can also go then and build skills. So for example, I can go in and say, \"Well, a way to auto-resolve is a Slack message, or is there's a skill that I created called Review a Doc as Pedro.\" So there are things when I'm reviewing a document or a product review or a presentation that I always ask.","offset":4292,"duration":19},{"text":"Pedro: So I like, for example, like, you know, \"What is the most important thing that this thing should be driving? And like how did we choose that thing? Um what's the bottleneck making this thing happen to go faster? Um, you know, why aren't we moving faster?\" There are like three or five questions that I always so you basically make that into a skill, and then you build that into the pipeline.","offset":4311,"duration":18},{"text":"Pedro: So it's basically LEGO blocks that you can put together to accomplish like really complicated things uh through these systems. And of course, like I, I as an engineer, I had to go and build these things. But, uh, and I think I'm going to open source this, but it's basically this entire like CEO or I guess like almost like, you know, leader in a in a information-based company uh workflow, um and it's been really fun to build it.","offset":4329,"duration":26},{"text":"Host: So it sounds like, I mean you just got really sucked into this and so and you just mentioned, I mean you're doing this.","offset":4355,"duration":6},{"text":"Pedro: Oh yeah, like yeah, like it's the AGI psychosis I would say. We have a rule at home, which is uh no AI Saturdays. My wife is like—because like I'm basically like talking to my Open-webUI all the time, like I'm sending voice notes. Uh and it's the best developer experience because you can be like on the way here, I was like like I had this like synchronization issue on my data pipeline.","offset":4361,"duration":22},{"text":"Pedro: So I was like literally sending voice notes saying, \"Hey, like change this, change that, do this, do that.\" Um and it's amazing. Like I can be on the car, I was on a Waymo like coming in here and uh getting getting a bunch of things done, um so but the problem is it's so easy that you start doing it all the time. So then I can be having dinner and sending voice notes and my wife's like, \"Stop, let's have dinner.\" Um and then Saturdays no AI at home, which is a which is a kind of a fun thing.","offset":4383,"duration":25}],"startTime":3764},{"title":"Reading Biographies & Building Mental Models","summary":"The conversation shifts to Pedro's reading habits and evening routines. He explains his love for reading biographies of figures like Benjamin Franklin to understand their unique mental models and perspectives on the world.","entries":[{"text":"Host: And when you were when you were um living such a frenetic life and and getting pulled in all these different directions and you kind of, you know, you talk—\"I've had a panic attack\"—you talked about having a panic attack, you talked about getting into meditation and reading and sort of changing your nighttime ritual. Like what kind of things do you read at night?","offset":4408,"duration":23},{"text":"Pedro: Gosh, uh right now I'm reading a totally different thing. I'm reading uh Benjamin Franklin's biography, um uh by Walter Isaacson, which is actually quite good.","offset":4431,"duration":10},{"text":"Host: I've read that one.","offset":4441,"duration":1},{"text":"Pedro: Yeah, yeah, very interesting. I mean I I generally like uh the Da Vinci one's also very good because I I think there's this thing where uh a hundred, a couple hundred years ago, or even longer, I think the sort of Renaissance man, this like multi-faceted person that knew a little bit or actually even a lot about different domains, was a big thing.","offset":4442,"duration":29},{"text":"Pedro: And uh intersection of arts and science is something that I like a lot. And uh, you know, Benjamin Franklin was a not only of course had a massive effect on uh as a Founding Father and in the definition of what the US is, but but also as an inventor, and you know, um he was so deep in in electricity and things like that. And uh that's very that's very remarkable.","offset":4471,"duration":21},{"text":"Host: Journalist.","offset":4492,"duration":1},{"text":"Pedro: Journalist, of course. Uh, so and uh, you know, uh uh ambassador for the US, right, in in France for the first time in the right after the the Independence. So so it's a it's remarkable to read it.","offset":4493,"duration":15},{"text":"Host: Is that like, do you like non-fiction?","offset":4508,"duration":3},{"text":"Pedro: I I almost always read non-fiction. Um I read your book, um the Elon book, which is very good. Uh and uh you can and I think I think so much of what I enjoy is trying to understand someone's frame of mind.","offset":4511,"duration":17},{"text":"Pedro: And one of my favorite questions, um it's a weird question, but it's uh: what is the experience of being you? And it's a it's a profound question because there's there's a few like mental models in your head when you look at the world that sort of shape your experience of acting and being a person.","offset":4528,"duration":23},{"text":"Pedro: And and I think that's very profound. So um when you read these like biographies that go very deep, I think ultimately what you're getting to is like: what is the experience of being this person? And great biographers, as I'm sure you know, like you ultimately that's what you're trying to crack, right?","offset":4551,"duration":18},{"text":"Pedro: You're trying to you're trying to there's all these stories and it's almost like, you know, there's this elephant that you're touching different parts and you're trying to triangulate like: what what is the entirety of this person? And and I think biographies are great at that. Um, I mean I read you know I read a few technical books on uh the Art of Doing Science and Engineering from from Stripe Press.","offset":4569,"duration":23},{"text":"Pedro: I read a lot of things that are relatively technical, um but I think biographies and things that go very deep, um the Nvidia way um from about about Jensen, I think I think gives you that same mental model. And ultimately, I think you know it's the the Charlie Munger thing, you know, at the end of the day uh being successful is a collection of like 30, 40 to 50 good mental models and just applying them everywhere.","offset":4592,"duration":26},{"text":"Pedro: And uh and and I think seeing how remarkable people have different sets of these like 30, 40, 50 different mental models I think is uh is pretty fascinating.","offset":4618,"duration":12}],"startTime":4408},{"title":"The Experience of Writing Elon Musk's Biography","summary":"The host shares his own intense, all-consuming experience writing a biography on Elon Musk. They discuss the psychological toll of inhabiting another person's life for years to properly capture their story.","entries":[{"text":"Host: Yeah, no, um biography, yes, oh we could talk for long time about that. Very strange experience doing one as well.","offset":4630,"duration":8},{"text":"Pedro: What was it like? What was the what were the—","offset":4638,"duration":3},{"text":"Host: God, I set myself up for that, didn't I? I mean I really could talk for hours. It was it was uh it was funny in some ways because I I at that moment in time, I wanted to do a book. I'd gone to see uh SpaceX—I was working on a magazine story about Elon.","offset":4641,"duration":20},{"text":"Host: I had not like set out to do like a biography on Elon Musk. But I, you know, I when I went to SpaceX, it was it was just so um so different and and further along than I pictured in my head. And it was just right in Los Angeles and it was it was like it was just thriving and just had this energy.","offset":4661,"duration":18},{"text":"Host: And anyway, that's what kind of sucked me in. And then I got interested in Elon, you know, interacting with him and reporting the story. And then so anyway, you know, I signed up for this thing, but I had no idea what I was getting into in the sense that you spend three years thinking about this one person. And that's like your job. And it's like it's very all-consuming, you know?","offset":4679,"duration":21},{"text":"Host: You start to have dreams about that person. Um all the things you mentioned you're trying to do, hopefully you're trying to do a good job, and so you're not you're trying to you're trying to talk to a bunch of people to get at what you're talking about. It's like it's like Elon's always going to represent sort of like how he wants to be represented, and then you're trying to talk to all these other people to triangulate.","offset":4700,"duration":21},{"text":"Host: I don't know if you ever get to truth, but some some version of that that you're conveying at least you can you can give people: well, this is how these other people experience him and you know, and try to create as full of a picture as you can. But then you get into this um becomes very strange, right? You um I you know, was like: I'm thinking about him all day, you're like having dreams about him at night.","offset":4721,"duration":26},{"text":"Host: I was like: I didn't sign up for this. I want some peace, you know? And and so I mean there was just part of it that I didn't expect. A lot of what you're talking about though, you're like trying to put yourself in this person's shoes. And then and then there's this strange thing where you're like: I don't know I don't know if I was ever really trying to pass judgment, but you are passing judgment on certain things for the people that are going to read this book.","offset":4747,"duration":26},{"text":"Host: And then it's just like a lot of I don't know if it's like pressure, but but if I think if you're wired the right way you kind of you want to do a good job at it and and so yeah, it's very strange. And then um after that, you know, that book became such a hit that there's just all these things I didn't sign up for, you know? Now you're like the Elon guy. And it's like it's like: yeah, I found him fascinating, but I'm interested in lots of shit, you know?","offset":4773,"duration":23},{"text":"Host: I don't I don't need to be the Elon guy for 10 years. Um and so but you know—","offset":4796,"duration":3},{"text":"Pedro: But you know, I think the gift of uh great biographers is uh well just books in general, right, is I don't think people realize how remarkable it is that you spend three years of your life dedicated to this. And I can sit down in four days and consume that. Uh I think that's such a profound such a profound realization.","offset":4799,"duration":20},{"text":"Host: That it's a crazy amount of work. Yeah, when *The Heavens* went on sale, the one I just did, that was six years and it's it was just it's kind of crazy. I mean, I love it. That's actually the most fun part is the journey, you know, and like the process. And by the time you finish the book, you've worked on it for so long, you've read it so many times, you're just like: I never need to look at this again. It's just like now I want to do the next next thing.","offset":4819,"duration":27},{"text":"Host: But that exactly what you said is also what I love about magazine writing. It's why I liked working at *Businessweek* for so long was that I could go in a in a condensed, smaller form than the book to go like live your life for some version of your life for three, four months. And like inhabit these worlds, right? And like see what people's mental models are like and see what their you know, it's not always perfect because again people are putting on personas and things like that. But if you if you spend a decent amount of time at it.","offset":4846,"duration":27},{"text":"Pedro: And I'm sure the more you do it, the better you get at cracking it.","offset":4873,"duration":4},{"text":"Host: A little bit, right? I think, and and but that's the best part of the job is you just get to see it's like: oh, this is how Bryan Johnson lives, this is how Jensen lives, this is how, you know, Jennifer Doudna lives, it's like it's it's just cool to to sort of shed your own ego for a bit and just just watch. Yeah.","offset":4877,"duration":22},{"text":"Pedro: That's inspiring.","offset":4899,"duration":3}],"startTime":4630},{"title":"The Future of AI in Financial Decisions","summary":"Pedro predicts that within 20 years, AI agents will act as flawless corporate CFOs. He envisions a future where companies leverage AI to align their resource allocation and hiring directly with their unique cultural ethos.","entries":[{"text":"Host: Um well I want to be mindful of your time. I just had like a couple last, I mean they're more just like just out there questions I guess. I mean I'm just so curious what you think like the future of money is in 20 years.","offset":4902,"duration":16},{"text":"Pedro: Yeah, I think I mean I think I think you're going to have a lot of the the the sort of payment, you know, evolution, right? You see Visa Mastercard already positioning themselves on stables, you see of course Stripe doing a lot of moves there. So I think that's going to continue. But I actually think that's less interesting. What I think is more interesting is the the decision to spend money itself.","offset":4918,"duration":25},{"text":"Pedro: And and I fundamentally believe that, you know, you become what you spend on as a company, as an individual. Like you become your resource allocation. In terms of the people you hire, in terms of the the decisions you make, the technology you use, right? You know, one of the quotes that I that I really like is, you know: we shape our tools and our tools shape us.","offset":4943,"duration":22},{"text":"Pedro: So so I think the way I think there's going to be a fundamentally higher level of thinking behind how companies make financial decisions. And and you can imagine that a lot of it is this problem of context and just aggregating information and understanding what are the implications of this decision uh to of course the revenue, the costs, but but even to things like the culture of the company, to the vision and the mission and what are you trying to do.","offset":4965,"duration":26},{"text":"Pedro: And these things cascade down all the way into a single individual Wednesday, right? So uh you know, there's this thing that uh I forgot who said it, but uh \"life is a picture but you live on a pixel.\" So at the end of the day, you know, you can talk about these visions, but it has to materialize on a mundane Wednesday. Like how does how does that change your mundane Wednesday?","offset":4991,"duration":27},{"text":"Pedro: And I think when you have this this uh autopilot to the way companies make decisions and you fundamentally change the calculus of where capital is going to be more aligned to where what matters to you as a company and as an individual, I think that's a very big unlock.","offset":5018,"duration":24},{"text":"Pedro: Um and and I think it's it's going to be more profound than people realize. And of course, AI is going to enable that and you're going to need all the of course the payments technology, agentic payments, like agentic commerce, all these things will will play a role. But ultimately like, you know, what's the icing on the cake and what's the cake itself?","offset":5042,"duration":17},{"text":"Pedro: And the cake itself to me is this idea that, you know, the the quality and the ability and the level of discernment that you're going to have in financial decisions because you can have so much of this context is like: what if you had the best CFO in the world making every decision? You know, the best, you know, founder in the world helping you make hiring decisions.","offset":5059,"duration":20},{"text":"Pedro: What if you had the best person in the world deciding where to where to expand next, where to grow, how to grow, how to look at your unit economics? And I think that will become true in the next few years and hopefully we play a big role in it. But it's like it's going to happen regardless.","offset":5079,"duration":16},{"text":"Host: So then companies just like if everybody has some sort of perfect information and they have the ideal CFO and the ideal all these positions, I mean so you just still end up competing on on your product and your your—","offset":5095,"duration":14},{"text":"Pedro: So that's that's the fascinating thing, which we have we had a lot. So for example, we're building these recruiting agents. And and I think the models are because of the amount of like post-training that goes into them, they have this relatively uniform view of what is a good candidate. But then the question becomes: what is a good candidate for us?","offset":5109,"duration":22},{"text":"Pedro: And and I think it's that like focus and constraints uh are what give meaning to your choices. So so when you have to go to a recruiter and you say: what are you willing like where does this person need to spike on? And how do you hire for that instead of sort of lack of weaknesses, which is where the models generalize and go typically, right?","offset":5131,"duration":21},{"text":"Pedro: Model is very hard to make a model say no. And and I think that's a very profound learning because that is the hard question. It's like what what where does this spikeiness matter, right? Where does it matter to be you know astronomically different? And and I think that's where the judgment comes in of what kind of company you want to build.","offset":5152,"duration":18},{"text":"Pedro: And I think that's an inherently human decision.","offset":5170,"duration":2},{"text":"Host: And you're giving it that flavor?","offset":5172,"duration":1},{"text":"Pedro: Yeah, that's the challenge. It's like how do you give that taste of Brexiness into—","offset":5173,"duration":5},{"text":"Host: Yeah, because there's like a world where the AI recruiter doesn't want you or George Hotz because you look pretty weird.","offset":5178,"duration":7},{"text":"Pedro: Exactly. And one of the things that we do is like one of the factors that we really like is, I mean of course I'm biased by this, but it's who were people that did something uh at a moment in their life where they had absolutely no other reason besides love for the game, love for the craft.","offset":5185,"duration":19},{"text":"Pedro: And well, people that are coding in high school don't have any reason to code, maybe getting into college, but you just you can just tell based on the kinds of things they build and the relationship they have with the craft. Um people that were doing completely different jobs, like someone that was in finance but ended up going super deep in AI and Claude Code and building this massive thing to automate their jobs—they didn't have to do that but they did it anyway. That was driven by something pure.","offset":5204,"duration":23},{"text":"Pedro: So so that is something that we care about a lot and we want to teach our recruiters to do it, but that's us. That may not be true for every company. And I think this ability to to understand the ethos of what you care about when it comes to this function and separating that from the technical excellence, I think is a really important thing because the technical excellence I think will be true no matter what.","offset":5227,"duration":24},{"text":"Pedro: And the and the point about the ethos—the reason a model can't discern that is because like that is a choice. And and you can't really argue with you know is it better to hire someone that's uh you know started coding before they had to in their lives, or to hire someone that went to an academic route and has a PhD in machine learning and you know and AI and is going to go do research at OpenAI or Anthropic? Like it depends. Depends on what kind of company you want to build.","offset":5251,"duration":34},{"text":"Pedro: Um and I think that's the that's the part that's really interesting is like if you just take out all the things that are not about the ethos away and you give that job to the models, what what matters what remains? And these are the harder questions, the ones that require a lot of discernment. And uh and I think it's where people should spend a lot more time.","offset":5285,"duration":19}],"startTime":4902},{"title":"Delegating Real-World Tasks to AI Agents","summary":"Pedro shares anecdotes about his personal AI agent, \"Lemonpie,\" autonomously executing tasks like buying movie tickets. The two speculate on a future where AI handles tedious chores like tax preparation and bookkeeping.","entries":[{"text":"Host: What's the UI on your Claude your Claude bot?","offset":5304,"duration":4},{"text":"Pedro: Uh the UI? I have a I have a I have a autopilot UI that has like all my all my tasks and like all my my entire system. It's like a just a a little web UI.","offset":5308,"duration":11},{"text":"Host: But it's almost like a Claude project or—","offset":5319,"duration":2},{"text":"Pedro: Uh no, it's like a website, like a server that it runs, and then I talk to it on Telegram and uh I use Discord for uh multi-channel and like sub-agent coordination and things like that.","offset":5321,"duration":11},{"text":"Host: So like if you're if you're trying to set up a tennis match on Sunday at 3:00 p.m., are you—","offset":5332,"duration":6},{"text":"Pedro: I would just send a voice note.","offset":5338,"duration":3},{"text":"Host: And then and like it would uh what if it needed to book the court?","offset":5341,"duration":4},{"text":"Pedro: Um it has well it actually has uh something that we're shipping at Brex very soon. Uh it has access to a way of creating virtual cards on Brex through an MCP. So we'll go do that, go in the website, put a credit card on file, come back and say, \"Hey, it's done.\"","offset":5345,"duration":16},{"text":"Host: So the agent would go do that. Is there like any way I'm spending three days assembling and answering questions about my personal taxes in 10 years to do my tax return? Please tell me that's not going to happen.","offset":5361,"duration":11},{"text":"Pedro: No way. Absolutely no way.","offset":5372,"duration":2},{"text":"Pedro: Well and it's going to happen on both sides, right? The IRS will also be doing your taxes for you and then it's going to be with yeah exactly. So it's uh I think that's probably true already to some degree but but you know I I tell people: everybody's going to be audited because the cost is going to be zero. So uh that will be an interesting future.","offset":5374,"duration":17},{"text":"Host: It like it drives me insane. It's like all I do I it's a lot of hours just to gather up all these stupid documents every year when my my computer could just be doing this all year.","offset":5391,"duration":11},{"text":"Pedro: Unbelievable. Unbelievable. Yeah. And and the thing that's interesting is, uh, you know, it's a fundamentally different problem. Like it's almost like there's the tax software and there's the bookkeeping job. And the bookkeeping job part of it is interacting with the tax software.","offset":5402,"duration":17},{"text":"Pedro: But another part is gathering all documentation and going in and asking you about specific expense and transactions and what they were and what they weren't. And uh yeah that the the bookkeeping job is the is the really interesting part that will which will become part of the software eventually.","offset":5419,"duration":14},{"text":"Host: So what like what I mean accountants become like um lawyers? I mean they're just handling the highest most difficult questions?","offset":5433,"duration":8},{"text":"Pedro: I think so. I think so. And and I think the my my thesis is, like for example on accounting, I think you will still have a bookkeeper because you need a CPA to file your taxes. That's like a legal requirement. Like if you're filing someone's taxes on their behalf, you have to be a CPA.","offset":5441,"duration":18},{"text":"Pedro: And and the beautiful thing of this system and the way it works actually is a CPA has some degree of personal liability in case there's something wrong with your taxes. And that creates this very very good back pressure in the system where well because someone is personally liable, they better make sure that the data is correct. So they better make sure the tools they're using have a high enough bar for accuracy and control.","offset":5459,"duration":23},{"text":"Pedro: So so I think that's actually a really powerful thing where I like even if you had like Harvey and and let's say the the law the law uh agentic AI, uh sorry agentic agentic law firms doing doing really great work, having a human in the end matters because you know I we we talk a lot about this idea like what if Jim makes a makes a very big mistake on hiring?","offset":5482,"duration":27},{"text":"Pedro: Like do you hold Jim accountable or do you hold an employee accountable? And actually you need the same oversight mechanisms that you have of employees. So Jim has a manager. There's someone on the recruit team that's actually Jim's manager. So signs off on all the actions.","offset":5509,"duration":10},{"text":"Host: Has to have a hard talk with Jim.","offset":5519,"duration":2},{"text":"Pedro: Exactly. Exactly. And give feedback, right? And and give access to tools and set a budget and, uh, you know, have ways of giving feedback and make sure the feedback's incorporated, um and and fire Jim and change Jim in in case things go wrong. So I mean firing is more more of a figure of speech.","offset":5521,"duration":18},{"text":"Pedro: But ultimately the idea I think this idea of oversight over agents and how do you get humans comfortable with the fact that agents are doing things on their behalf I think is a very fascinating problem.","offset":5539,"duration":-587},{"text":"Host: Have you had a AI agent pay for something on your behalf? You have. Through Brex or through the—","offset":4952,"duration":7},{"text":"Pedro: Yeah, yeah. Yeah, yeah, yeah. Through Brex. Through uh well Open-webUI through a card a Brex initiated card, a Brex created card.","offset":4959,"duration":6},{"text":"Host: Okay. Like you're doing this all the time or this is—","offset":4965,"duration":-598},{"text":"Pedro: No, so so I mean I I don't do it like I probably do it like once a week I would say, um even though I make an online purchase probably like every two or three days. So so I would say it's like a third. But but I am I am also trying to deliberately push the boundaries.","offset":4367,"duration":612},{"text":"Pedro: So a fun one was uh we had a couple of friends that were going to the movies, and then they they sent us, \"Hey here are our seats.\" And then like I literally just forwarded the message to uh to my Open-webUI and I said, \"Buy the tickets nearby.\"","offset":4979,"duration":-585},{"text":"Pedro: And then it went online, went on the Cinemark website, found the movie room, found the the time, uh found where they were seated and said, \"Well these two seats are taken you should take the ones next,\" um and then I was like, \"Sure.\" And then it went online, put the card details, made the payment, and it was done. And then I got an email confirmation and I didn't touch anything.","offset":4394,"duration":23},{"text":"Host: Do you have a name for your Open-webUI system?","offset":4417,"duration":3},{"text":"Pedro: Uh I do. It's uh a funny it's I call it Lemonpie, which is a it's a weird thing because when I was 12 my first AI agents uh I call Lemonpies, my favorite dessert. Um and every sort of bot that I do in my life is called Lemonpie. So I was like: okay this thing has to be called Lemonpie. Um but anyway it was a was a sort of funny historical accident.","offset":4420,"duration":18},{"text":"Host: Okay, okay, okay, well I want that system. I look forward to you making all these things available in Brex for us to use. I hate doing my expenses so much. Um always hated that. It's pretty funny because I worked at *The New York Times* and *Bloomberg* for a long very many years and their systems were so archaic and when I did this startup and and started encountering things like Brex, I was like: oh my god, thank thank heavens that I no longer have to toil in all these things that destroy my soul.","offset":4438,"duration":34},{"text":"Pedro: No one likes doing expense reports. No.","offset":4472,"duration":1}],"startTime":5304},{"title":"Wrapping Up & Podcast Outro","summary":"The host thanks Pedro for his time and for sharing his story. The episode concludes with final pleasantries and the standard podcast credits.","entries":[{"text":"Host: No and I'm just you yeah and I'm just it's like self-defeating on that because I just don't do it then. Exactly. Well, thank you so much for coming in. Thanks for all the support. And um when we finish this, if you have a few minutes, I want to show you a cool video that you guys are in.","offset":4473,"duration":19},{"text":"Pedro: Let's do it. All right, Pedro. Thank you so much for coming. And um we will see you guys again soon.","offset":4492,"duration":6},{"text":"Host: Yeah, thanks for having me. Really appreciate it.","offset":4498,"duration":902},{"text":"Ashley: Close-up podcast is hosted by me, Ashley Vance, and or Kylie Robison, or both of us together. It is produced by me and David Nicholson. Our theme song is by James Mercer and John Sortland, and the show is edited always by the John Sortland.","offset":5400,"duration":21},{"text":"Ashley: Thank you so much to Brex and Eniac Ventures for all your support, and thank you most of all to everybody for listening or watching. We love you. Please leave us a like, a review, a subscribe, all those tremendous things. Thank you, and we'll see you again.","offset":5421,"duration":15}],"startTime":4473}],"entries":[{"text":"Host: Today's guest is a coding and entrepreneurial prodigy. He is Pedro Franceschi, the CEO and co-founder of Brex. The headlines on his life story are quite remarkable.","offset":0,"duration":15},{"text":"Host: He grew up in Brazil, taught himself to code as an eight or nine-year-old. By the time he was a teenager, he was—he was hacking the iPhone. He was getting legal notices from Apple asking him to stop hacking the iPhone.","offset":15,"duration":16},{"text":"Host: He was starting a number of businesses where he made hundreds of thousands of dollars while all the rest of his, uh, compatriots were on the beach in Rio de Janeiro or playing soccer. Pedro was coding away, creating these—these companies.","offset":31,"duration":21},{"text":"Host: He has some—some very deep sadness in his childhood. His father got cancer and passed away when Pedro was just eight. That left his mother to raise Pedro and his sibling, uh, as a single mother. She had some unconventional approaches to—to raising Pedro, which we get into in the show.","offset":52,"duration":21},{"text":"Host: Obviously, we get into Brex, which has been this just superstar of—of modern financial tech. Um, they were just acquired by Capital One for $5.15 billion. We speak about this on the episode.","offset":73,"duration":18},{"text":"Host: We talk about—Pedro's really open about the ups and downs running this business, his own personal ups and downs, struggles with mental health. He writes about these things, he talks about them in the show. Um, just—he's 29 years old, so this dude has lived quite a—quite a juggernaut of—of a life so far.","offset":91,"duration":20},{"text":"Host: And these days, he's using AI agents in some what I find imaginative and—and comical and—and inspirational ways. He's got a team of AI agents running his life, and—and we speak about all that.","offset":111,"duration":17},{"text":"Host: And so, um, I should note, Brex is the flagship sponsor of this podcast and our video series. As such, we are deeply journalistically conflicted in this episode. Nonetheless, I think it is, uh, it's a good listen, and he has a fascinating story to tell.","offset":128,"duration":19},{"text":"Host: This is Ashley Vance. You're listening to the Core Memory podcast, and off we go.","offset":147,"duration":17},{"text":"Ashley: Pedro, thank you so much for coming in.","offset":164,"duration":3},{"text":"Pedro: Thanks for having me.","offset":167,"duration":0},{"text":"Ashley: You are—you're royalty in these parts. Um, you guys have been such amazing supporters of everything Core Memory's been doing, so...","offset":167,"duration":9},{"text":"Pedro: Oh, thank you. Very glad to help. We're big fans.","offset":176,"duration":3},{"text":"Ashley: I feel extra pressure, uh, doing this one. You, uh, at the end of last year, you got married. You just were acquired for $5.1 billion, and now you're on the Core Memory podcast. It's all happening.","offset":179,"duration":14},{"text":"Pedro: It's all happening. It's really all happening.","offset":193,"duration":4},{"text":"Ashley: Um, I wanted to—I wanted to for people to get to know you a little bit. I mean, look, I cover—I cover all kinds of inventors, startup founders, you know, and so some stories I see repeating a little bit, and there's—there's echoes of that in some of your biography.","offset":197,"duration":20},{"text":"Ashley: I'm just going to read off a little list here for people, uh, super quick, and then dive into a couple of these things. But, you know, if you throw your name into Claude or ChatGPT and ask for like a quick—quick background or, you know, it's like ages eight to nine, teaches himself to code entirely via Google, no formal—formal training.","offset":217,"duration":25},{"text":"Ashley: Age 11, begins jailbreaking iPhones and iPads. Uh, age 12, you know, starts creating apps, you're selling apps to—to friends at school. Age 15 to 16, um, well, then this is kind of when you start your—your journey heading towards Brex one day, um, meeting—meeting your friend Henrique.","offset":242,"duration":22},{"text":"Ashley: But, but, you know, so some of this is familiar. I mean, it reminded me a lot of George Hotz, who I've written about. Uh, in OA. Yeah, he's like this teenage hacker. He was—he was busting into PlayStation.","offset":264,"duration":12},{"text":"Pedro: We used to be IRC buddies back in the day.","offset":276,"duration":3},{"text":"Ashley: OK, you know, he was getting into PlayStation, but, I mean, like even among these people I've covered, like quite exceptional, especially running, you know, money-making businesses as a kid. Um, so—and there's some of this in the things that I read, but I mean, tell me, were you just always—you—you hit upon a computer and it just—it just made sense to you?","offset":279,"duration":20},{"text":"Pedro: Yeah, so—I think the biggest luck of my life was I found out what I loved doing when I was eight or nine. And most people don't have that luck, but I—I did, and—uh, my—my—I grew up in Brazil, I'm from Rio originally, and—uh, growing up, um, I lost my dad when I was eight, um, and—uh, he was a big nerd and used to spend a lot of time in the computer.","offset":299,"duration":23},{"text":"Pedro: Uh, we had a computer at home, which was—uh, relatively rare—uh, back in Brazil. And—uh, that somehow was something that was around my life since the beginning. And I would say when I was eight or nine, I just had this very deep curiosity to understand how the computer worked.","offset":322,"duration":17},{"text":"Pedro: Um, and then I opened it up one day and I saw there wasn't anything interesting inside the computer, so I thought, well, there's something else going on here that makes this actually be so ama—so magical and so amazing, and I realized it was software.","offset":339,"duration":15},{"text":"Pedro: And then as a kid, um, in Brazil, um, I wasn't really exposed to software engineering in any capacity, but the internet existed, and the internet's this amazing thing—uh, uh, that, you know, allowed people like me to learn something that I would never be able to learn otherwise.","offset":354,"duration":18},{"text":"Pedro: So I started Googling how to code and started learning, uh, C and C++ back when I was nine. And—uh, learning that and English at the same time made it a little bit more challenging. Uh, C isn't a particularly friendly language, but it's all the resources that I found back then in, I guess, 2004 or five.","offset":372,"duration":21},{"text":"Pedro: So—uh, so that was—uh, that was sort of the—the backdrop of how I started coding. And—and what I really found—uh, remarkable about computers was you just had this ability of taking whatever you wanted with very little—uh, sort of permission or need to go do something.","offset":393,"duration":18},{"text":"Pedro: And then around the time I was 12, I became a little bit of a better—uh, engineer, um—and—uh, it was around the time that Apple launched the iPhone. And—and if you remember back in 2008 or nine, iPhone—the iPhone only worked with AT&T here in the US.","offset":411,"duration":16},{"text":"Pedro: So there was this whole thing of when you wanted to use the iPhone abroad, you had to jailbreak it to get it working in other countries. You would jailbreak it and then do the carrier unlock. But jailbreaking was—uh, the hardest part. So I was using a lot of the tools that existed online to make that happen.","offset":427,"duration":16},{"text":"Pedro: And then a new iPhone came out, the iPhone 3G, I ended up finding—uh, a way to jailbreak it that was one of the first ones back then in 2009. And I got sort of known in this like iPhone—uh, jailbreaking community.","offset":443,"duration":15},{"text":"Pedro: And then, weirdly enough, that's actually how I got—uh, I started working. So—uh, I used to, you know, a reporter in Brazil realized that there was this kid doing, you know, jailbreaking things online because...","offset":458,"duration":13},{"text":"Ashley: I mean, you became like a celebrity.","offset":471,"duration":2},{"text":"Pedro: Uh, I—I guess I wasn't really known back then, but because I used to just publish things online with my handle, which was PH, um, my name is Pedro Henrique, that's why PH, like the chemistry pH. Uh, and—and some—somehow this—this reporter realized I was Brazilian. Uh, I think was because of my IP address in—in this IRC form.","offset":473,"duration":21},{"text":"Pedro: And—uh, he reached out and said, \"Hey, there's a Brazilian involved in this like iPhone jailbreaking community.\" And then—uh, he asked, \"How old are you? I want to know more about you.\" And in my head I thought, well, if I tell people I'm 12, they're not going to take me seriously. So I told people I was 14. And in my head it made a huge difference.","offset":494,"duration":20},{"text":"Ashley: But—um—and then—uh—and then—um, right around that time that was sort of in the Brazilian press, and—uh, a company in Brazil that was building mobile apps—uh, reached out to me, and—uh, and I ended up going to work there, right around the time I was 12, uh, 11 or 12.","offset":514,"duration":18},{"text":"Pedro: And—uh, at first my—I told my mom, \"Hey, this company wants to hire me.\" And she said, \"No way, what are you talking about? You're 12. Uh, no freaking way.\" But then I convinced her to come interview with me, so she went there, uh, and I started working there part-time.","offset":532,"duration":20},{"text":"Pedro: And it was great because it was the first time that—uh, I actually met professional software engineers. Like, what does it look like to—to really be sort of world-class? And my first boss, uh, Ben Jackson, was—uh, fantastic, and, you know, he—he worked at New York Times after building their mobile app, and, you know, he—he—he went to Penn.","offset":552,"duration":22},{"text":"Pedro: So it was just like a—you know, US-grade software engineering—uh, experience, which I—I don't think—I think was very formative. And then—um, right around the time I was 14, uh, I did two things that sort of got—got me in trouble. One is I—I ended up reverse-engineering Siri to make it work in Portuguese, and—uh...","offset":574,"duration":37},{"text":"Ashley: Terrible.","offset":611,"duration":1},{"text":"Pedro: Nuance and Apple were not very happy with me. Um, and then the second was—uh, I built this app for the iPad—uh, called Quasar, which you could run, you know, apps on windows, the same way you can now on iPad, but that was in 2012, so—uh, 13 years ago.","offset":612,"duration":19},{"text":"Pedro: And—uh, that was really fun. Uh, and I put this online and I used to charge 10 bucks per—per download in—in Cydia Store back then, which was this sort of parallel app store. Um, and I made like 300k when I was 14. Um, so I had to explain to my mom what that money was about. She thought I was doing something illegal online.","offset":631,"duration":19},{"text":"Pedro: Um, but anyway, so—so I did all that. And then—um, right...","offset":650,"duration":5},{"text":"Ashley: Can I—can I pause you for one second? Because I'd—I'd read about some of this and I just had—I had a couple—couple questions along these lines. I mean, your mom goes to your first job interview with you. You said I think you were 12 for that one. So like, what does that look like? You—you both walk into the office together?","offset":655,"duration":15},{"text":"Pedro: Yeah. So—so it's funny because I think your parents make a few decisions that they may not be aware at the moment, but they drastically change the course of your life. And I remember around that time, there were all these articles—uh, that came out that Bill Gates's daughter could only spend 45 minutes today in the computer.","offset":670,"duration":17},{"text":"Pedro: And then my mom looked at that, and—and here—here was her son spending 14 hours a day in the computer. And well, Bill Gates know—a thing or two about computer, so who am I to allow that? And I think she was—uh, very fortunate to—to see what I was doing with—a little bit of a bigger aperture and see that I wasn't like playing games, I was actually building something productive that people got value from.","offset":687,"duration":24},{"text":"Pedro: And—uh, and that sense of being a builder, which is really the—the biggest luck of my life, realizing that I love to build things, was something that I think she—she saw the impact it had on me and on the people that used the things I built.","offset":711,"duration":14},{"text":"Pedro: And—uh, I think that unlocked her to—to allow me to—to not only spend a lot of time in the computer, which I needed, but also at the same time—uh, uh, just—just really open to these experiences of going in and working even though it was very counter-intuitive and, you know, my family and, you know, sort of extended family friends were all asking her, \"You know, this kid is 12, why is he working?\" And she's like, \"You don't understand, he wants to.\"","offset":725,"duration":25},{"text":"Pedro: Uh, and—and thankfully she did it because if she hadn't, I think the course of my—my life—uh, would have been very different.","offset":750,"duration":8},{"text":"Ashley: What—but what's that like? You go in for this job interview together, and so what? The two of you are just sitting on one side of the...","offset":758,"duration":6},{"text":"Pedro: Yeah. So—so it was—so it went to—went to have lunch—uh, with—uh, with the two founders of that company.","offset":764,"duration":4},{"text":"Ashley: And they're Brazilian or...?","offset":768,"duration":1},{"text":"Pedro: Oh, one of them is American, the other's Brazilian. OK. The American one went to Brazil for Carnival—uh, one year and never left. He stayed there four years. Now—now he's in the US, he's in New York now, but—um, but it was—it was really funny just to see—uh, uh, you know, like a—like a professional software engineer in Brazil in Rio.","offset":769,"duration":19},{"text":"Pedro: And then—um, we went for this—for this lunch, and I was just talking to them technically about the things I was building, and my mom was like, \"I have no idea what's happening, but sounds like they are excited, so that's I guess it's a good sign.\" Um, and then at the end she—they were like, \"Look, we—we think—we think he's good, we'd like to work with him.\"","offset":788,"duration":16},{"text":"Pedro: And she said, \"Um, I have only one thing to say. Uh, he's 12 years old, so if something happens to him, I'm going to kill you.\" And then—and then they were like, \"OK, understood.\" Um, so—so she was—she was very protective but in—in a way, you know, obviously was a very different environment.","offset":804,"duration":18},{"text":"Pedro: It was this company where, you know, I guess the—young—second youngest person was probably like 26, and then I was 12. So—um, I—I don't know if I would have the—the courage let my—my son do that, but she did, thankfully, and—uh, and things worked out.","offset":822,"duration":-46},{"text":"Ashley: Yeah. OK. That's—that's kind of how I pictured it in my head a little bit. I mean, look, lots of—lots of young kids code. Um, you know, and this is—this is a difficult question because I'm asking you to—to tell me how awesome you are in some ways, but I'm more curious how your brain works. Because I—again, you know, I've met so many people. This is a common story. They start coding at a young age. But I mean, what you're doing, it is—it is—it again, it reminds me of Hotz, just because it's—it's on the exceptional side. How does the—like, what are you... what are you particularly good at when it comes to coding? Why were you standing out at that age?","offset":776,"duration":34},{"text":"Pedro: I think—I think it was just this—uh, you know, Paul Graham has this essay about the—you know, the bus ticket theory of genius, about these uninteresting obsessions that when you multiply over the course of one's life, you—you end up in a—in a—in a pretty interesting place.","offset":810,"duration":18},{"text":"Pedro: And to me, I just had this deep curiosity to get computers to do things that they were not design or supposed to do, and—uh, and almost sort of proving that it could—it could—it could happen from a technical standpoint. Um, so that was probably the backdrop.","offset":828,"duration":15},{"text":"Pedro: And—and I would say the biggest benefit that I had having started that early is because I feel that when you are 12 or 14 or you're very young, the creative energy that flows through you when you're building something is—is almost like the purest kind. Because there is no other reason besides love for the game, right?","offset":843,"duration":20},{"text":"Pedro: There's no other reason like—I didn't need to make money, thankfully my—my—you know, my—I grew up in a middle-class family in Brazil so I—you know, um, I was lucky to not have to—you know, I wasn't wealthy growing up, but I—um—it wasn't—it wasn't for the money that I was making, it was because I was just very deeply interested in the craft itself.","offset":863,"duration":20},{"text":"Pedro: So—so that to me has always been the thing, and having this sort of—uh, respect for the—the creative energy that comes when you have an idea and saying, \"Um, how do I manifest this thing into happening?\"","offset":883,"duration":13},{"text":"Pedro: And I remember when um I built this app Quasar, and when I was 14 and it was actually a very tech—very complex um problem from a technical standpoint. You had to you know make the iPad become you know basically instead of being single processor rendering the UI, you had to make multiple processes render the UI so you needed to build a scheduler to coordinate different things rendering at the same time on the screen, which was technically complex.","offset":896,"duration":24},{"text":"Pedro: And and that to me was I just had a sense that it was possible and uh and when you have this sort of deep connection to this thing you want to see in the world, I think the way you show up and and and the hours and the time and the energy, these things all go away and you sort of uh surrender yourself to that process in a weird way.","offset":920,"duration":28},{"text":"Pedro: And and I think so much of my my journey as a builder was how do you connect to that energy? Uh and it's funny because I was telling my team that you know now with AI and a lot of the things that we're building uh in Brex and being much more hands-on as an engineer uh in a world of you know a company of like 1,300 people and a much bigger scale, weirdly enough connects me back to that very same energy that I started with and and uh coming from a very pure uh uh standpoint. So I think that's been the biggest driver for me and of course you know lot of curiosity and and energy and time but it came from a very sort of creative place versus from a like a like a like a work uh in sort of traditional sense of I need to do this and make money and there's parts that are good, parts that are not good. No, it was all great. It was all really fun.","offset":948,"duration":47},{"text":"Ashley: And so and then you're in Rio. I mean, all your peers are running around playing soccer, having a good time, going to the beach, and you're like locked in your house, like in a—yeah, in your room or what? What did it look like? I mean, what kind of posters did you have on the wall?","offset":995,"duration":16},{"text":"Pedro: Um I mean I I had a I the time I made enough money I I bought myself an iMac. Um so it was me and my Mac and just like hours and hours and hours of like coding um on you know Vim or TextMate back then was the text editor we used to use um and a lot of lots of IRC channels uh that's how I met uh GeoHot originally um and you know a lot of the folks involved in Cydia and the original jailbreak community mobile substrate there were a lot of different sort of work groups back then but it was that was my universe was sort of living this parallel reality um and you were you were kind of you were a nerd.","offset":1011,"duration":45},{"text":"Pedro: Oh yeah. For sure. For sure.","offset":1056,"duration":3},{"text":"Ashley: If—if I can ask, you know, when I was a teenager, both my parents got cancer and, um, you know...","offset":1059,"duration":5},{"text":"Pedro: Sorry to hear.","offset":1064,"duration":1},{"text":"Ashley: Thank you. And—and likewise to you. I mean, I mean, you're eight. Were you—were you an only child?","offset":1065,"duration":4},{"text":"Pedro: I had—I have a younger brother. Two years—two years younger.","offset":1069,"duration":3},{"text":"Ashley: OK. And so—and your dad gets cancer. When—did—I mean, if you're OK talking about it, was this a multi-year protracted thing or...?","offset":1072,"duration":10},{"text":"Pedro: Yeah. So he had—he passed away when I was eight. He had cancer for five, six years. So most of my childhood. Um, he had a lymphoma, which is obviously a relatively rare kind of cancer. Um, and, you know, cycles of ups and downs over the years. So moments that he was very well, moments that he wasn't so well. Um, but it was a big part of my—my childhood.","offset":1082,"duration":20},{"text":"Ashley: Like, how do you—I remember, you know, in the moment for me as a teenager, I mean, you—I don't think it was obvious to me sort of how it was changing me, but, you know, a year or two go by and—and you can kind of feel it. Um, was it obvious to you? You're so young. Or what is that?","offset":1102,"duration":14},{"text":"Pedro: It's funny because I—I think I fully processed that—um, maybe five years ago, when you—with the benefit of hindsight and perspective and living your own life and understanding that, you know, life is finite and all of that, and—and then you sort of appreciate the—uh, you sort of re-signify an experience you've had as a kid.","offset":1116,"duration":23},{"text":"Pedro: And—and that was probably when I really realized. But for sure in the moment, there were things that were that affected me, right? I think for a lot of this thing of building and coding, I think was how do you insert yourself in a place where you control all the variables and the entire thing is in your control because the outside world isn't? So I think that was a—there was definitely a relationship there.","offset":1139,"duration":25},{"text":"Pedro: Um, and look, I think my mom did an amazing job raising me and my brother after my dad passed away, but—but it—you see—you get exposed to, you know, yes, life is, you know, not infinite, you know, shit happens, that—that kind of thing early on, and that certainly shapes your—your brain chemistry in one way or another.","offset":1164,"duration":20},{"text":"Ashley: And so—and then your mom's a single mom from that point on. And she was—I read, it sounded like your family was kind of doctors and scientists and...","offset":1184,"duration":7},{"text":"Pedro: Um, no, my mom—she was—my mom was a—she was a psychologist, but she—she worked in, you know, psychology and then sort of marketing and, you know, bit more sort of corporate life—um, and—um, you know, worked in a few different companies in Brazil—uh, as I was growing up. Um, so—um, yeah, that was the backdrop.","offset":1191,"duration":19},{"text":"Ashley: Were—were you like pining for Silicon Valley? Or you thought...","offset":1210,"duration":3},{"text":"Pedro: Oh, no. Um, so my original plan was to just like live in Rio. Like most people that are born in Rio—and by the way, I understand them because the city is amazing—um, they never leave the—never leave the city.","offset":1213,"duration":12},{"text":"Pedro: So my brother, for example, um, he's 27 now, and he is the sort of archetypical Carioca, like the person born in Rio, and he whenever—I think he's never going to leave. And so that—that was my sort of destiny.","offset":1225,"duration":14},{"text":"Pedro: And then um when I—we started our first company in Brazil in 2013...","offset":1239,"duration":3},{"text":"Ashley: Oh, how old are you now?","offset":1242,"duration":1},{"text":"Pedro: Uh now I'm 29.","offset":1243,"duration":1},{"text":"Ashley: 29. OK. OK.","offset":1244,"duration":2},{"text":"Pedro: Yeah. Um, so when we started that back in 2013, um, that was the first time that I actually left Rio and moved to São Paulo, um, and then decided to apply for schools in the US because, you know, we all—I always wanted to build something at a sort of US-level scale. There were not that many big tech companies in Brazil back—back at that time.","offset":1246,"duration":19},{"text":"Pedro: And we came in 2016 for—after building Pagar.me, our first company that was effectively a version of—uh, Stripe in Brazil. And then we moved to the US in 2016 to—uh, start Brex.","offset":1265,"duration":13},{"text":"Ashley: And had you seen what the Collison brothers had done with Stripe?","offset":1278,"duration":2},{"text":"Pedro: So it's so funny. We—so—so we—so we—we thought we were the original inventors of this idea of like, gosh, like payments are really bad for developers and engineers, let's build a better version. And then uh one day we we met someone and they said, \"Oh, it's just like Stripe.\" And we're like, \"What is Stripe?\" Uh, so uh we we met Patrick and John back then actually. We we know them for for a while and you know we have huge respect for them.","offset":1280,"duration":22},{"text":"Ashley: Because because they went down to Argentina or something.","offset":1302,"duration":2},{"text":"Pedro: Yeah, they actually I think they worked there in the very early days of Stripe. Yeah. But you didn't meet them on that trip? No, I didn't. I didn't. I think that was in 2011. Uh, I was still maybe doing too much jailbreaking, but but you know it was uh but we actually met them in probably 2014 or 15. Um, that's when I met I think I met Patrick for the first time, and we've stayed in touch over the years and you know we have huge respect for them.","offset":1304,"duration":22},{"text":"Ashley: So you're doing this jailbreaking and then Pagar.me is—is a payments system. I mean, did you feel this pull towards finance, or it was just this was a problem that you just saw?","offset":1326,"duration":9},{"text":"Pedro: Yeah. So weirdly enough, the—the way I got into it is when I was 14, I—I actually changed jobs to a company in Brazil that was building sort of a version of Square, like mobile payments in—um, in—you know, in your phone.","offset":1335,"duration":12},{"text":"Pedro: And—uh, and I went to work there initially to fix uh an iOS security issue. So I—and—and there I was inside a payments company initially through this sort of iOS security angle, but very soon realizing how bad payments were and how uh old and archaic those systems were.","offset":1347,"duration":19},{"text":"Pedro: And then I met my co-founder Henrique at the end of 2012, and he was in the sort of, \"OK, I am—I want to accept payments online, that is a really challenging thing to do. Um, there isn't a better solution.\" And then I was like, \"Well, I was inside a payments company seeing how bad it was.\" So it was a little bit, you know, 1 + 1 = 3 from the the perspective of the the idea.","offset":1366,"duration":22},{"text":"Pedro: And then as we started it, uh-uh, payments became this thing that we went very deep and and started to understand better and uh-uh, and one of the things that I think was very big for us since that very inception was um building from the bottom of the stack up.","offset":1388,"duration":15},{"text":"Pedro: So we realized that at the end of the day, um, payments companies were limited by these uh vendors that they needed to use to actually interact with the the foundational payment rails. So Visa, Mastercard, like the equivalents of ACH and and Fedwire.","offset":1403,"duration":16},{"text":"Pedro: And uh as an engineer to me I had this like very um almost religious view that you can never build a fundamentally better customer experience unless you control the entire stack all the way to the metal.","offset":1419,"duration":12},{"text":"Pedro: A little bit the version of, you know, uh-uh, Steve Jobs used to say that, you know, if you care about your hardware—about your software, you should build your own hardware and just control the whole thing vertically.","offset":1431,"duration":12},{"text":"Pedro: Um, and we did that first in our previous company in Brazil and we built the entire processing stack and, you know, the acquiring rail and Visa Mastercard connections and all of that. And then we did the same again at Brex.","offset":1443,"duration":11},{"text":"Pedro: And I think that was a big reason of a lot of this success and the, you know, where we really started to innovate and being able to go after, you know, a lot of very large enterprise companies, AI companies, because of the the vertical integration building the whole product. Uh, so—so weirdly enough, I think the engineering mindset shaped the way we ended up building both companies, actually.","offset":1454,"duration":23},{"text":"Ashley: OK. I'm going to be gratuitous here and just lean in. Um, so Brex—Brex is our sponsor. You told me before we started, you haven't seen our videos um that we make and and so I just want to show you, I'm going to try to do this artfully so we can have the camera see it. All right. So you have not seen this before. You've not seen Sexy Brexy.","offset":1477,"duration":21},{"text":"Pedro: Oh wow. No, but this is cool.","offset":1498,"duration":2},{"text":"Ashley: All right. So we're doing an episode in Detroit, and GM gave us a loaner car.","offset":1500,"duration":5},{"text":"Pedro: I want that. How do I get that?","offset":1505,"duration":2},{"text":"Ashley: So GM gave us this car for the week. Their lawyers did not properly—uh, the—I—I found some—some wiggle room in the contract to do with the car as—as I saw fit. And so we gave it to these guys to wrap it. And—so you've never seen this. But here we go.","offset":1507,"duration":20},{"text":"[Narrator voice on video]: Meet Sexy Brexy, the intelligent finance vehicle. Fan-fucking-tastic. While this subtle product placement is awesome, the truck is not really the point of this video. No, we are here to check in on Detroit.","offset":1527,"duration":17},{"text":"Pedro: That's so good. I love it. I love it.","offset":1544,"duration":3},{"text":"Ashley: You know, so usually around this time we have an ad read—um, and I thought since you're here, I don't know if it's putting you on the spot, what—what would you like—what would you like to say about Brex real quick?","offset":1547,"duration":13},{"text":"Pedro: They only give me 30 seconds? Well, I'll give you 30 seconds. Um, no, look, I—I think I think the reality is um we believe that managing spend is a fundamental necessity of building a great company, because you become what you spend on, right?","offset":1560,"duration":14},{"text":"Pedro: A company you're you're literally are a byproduct of your spending and resource allocation decisions. And the fundamental problem is as a company gets bigger, you look at the finance team and they are responsible for 100% of the spend, but they only make 5% of the decisions.","offset":1574,"duration":17},{"text":"Pedro: 95% of the decisions of spending in a company are made by employees and leaders everywhere uh in different offices, in different countries, and that is an incredibly complex problem to coordinate.","offset":1591,"duration":11},{"text":"Pedro: And a lot of what we believe at Brex is that typically as a company grows, because of this amount of complexity, is you have to choose either to um put in a lot of controls in place um and slow down the company because you need to have control to make sure the money is going to the right place, or you take off controls and then you increase speed.","offset":1602,"duration":24},{"text":"Pedro: So speed and controls are this tradeoff. And the reason we built Brex is to break that tradeoff and give companies the agility of a startup all the way uh into becoming, you know, some of the largest companies in the world um that run on Brex today.","offset":1626,"duration":15},{"text":"Pedro: Um, so you know today we serve, you know, um more than 35,000, 35,000 from startups to the world's largest corporations. Uh, and you know 300 plus public companies uh including you know like uh Zoom uh you know Palantir, Anthropic, and as of two weeks ago, OpenAI. Uh, yes, um...","offset":1641,"duration":21},{"text":"Ashley: I've done this before.","offset":1662,"duration":1},{"text":"Pedro: Robinhood and you know we you can go to our website and see the customer list, uh-uh, which is really exciting. But one of the things we're really proud of is um when you're looking into AI, um we spend a lot of time making sure that we think about the role and how the finance function will fundamentally change.","offset":1663,"duration":17},{"text":"Pedro: And all the big AI labs today and, you know, like Cursor, Vercel, of course OpenAI and Anthropic, um, Mercor, um, you know, all these companies run on Brex because of uh looking at our AI vision and believing that this is the way finance is going to work.","offset":1680,"duration":21},{"text":"Pedro: And of course they looked at all competitors and all the alternatives in the space and still ended up going with us, which is a a very cool uh proof point, I guess, of the way we're building the product towards the future of finance.","offset":1701,"duration":13},{"text":"Ashley: All right, that was longer than 30 seconds, but we'll—we'll allow it. Uh, what did—yeah, what did you think of Sexy Brexy?","offset":1714,"duration":6},{"text":"Pedro: I loved it. Uh, it's really cool. Very cool, right? Very cool. I want to get the car.","offset":1720,"duration":6},{"text":"Ashley: We can make that happen. We can make that happen. Um, OK, so you know, you—you meet Henrique, you guys apparently get in a fight, a Twitter spat at first, but then become best of friends and—and business partners. You both head off to Stanford together. Um, it's kind of amazing that you both got into Stanford.","offset":1726,"duration":20},{"text":"Pedro: Yes. He convinced me to apply, actually. I decided I I heard what an SAT was for the first time I think was in mid-September 2023, and deadlines were in December. So that was a busy two and a half months.","offset":1746,"duration":16},{"text":"Ashley: OK, yeah, I bet. And—and so you—you get into Stanford, you guys—you don't stay around too long. About eight months, I think. Um.","offset":1762,"duration":7},{"text":"Pedro: That was not the original plan. Yeah. But um.","offset":1769,"duration":2},{"text":"Ashley: So it was like a semester and a bit?","offset":1771,"duration":2},{"text":"Pedro: Uh, three quarters. Yes, three quarters. Stanford is a quarter system.","offset":1773,"duration":3},{"text":"Ashley: OK. OK. And so you're you're already on to um you're thinking about your next idea. I mean, the one part that I picked up on was that you guys get into YC, you start with a VR company, and then it kind of pivots into Brex.","offset":1776,"duration":15},{"text":"Ashley: I mean, that's a pretty dramatic shift. I was I was curious about a couple things. I mean, as you're going through this um very um unusual childhood and working on these different projects, did you what did you picture in your head? What was your dream? Like, was finance the end goal?","offset":1791,"duration":20},{"text":"Pedro: So—uh, it's funny because we moved to the US and we spent four or five years building fintech in Brazil, you know, one or two before Pagar.me, then three and a half at Pagar.me. And the funny thing is when we came to the US, we had this idea of, you know, fintech is a solved problem in the US.","offset":1811,"duration":19},{"text":"Pedro: Brazil is this, you know, shitty country where, you know, fintech is still unsolved, that's why it was an opportunity. But here we want to be at the forefront of technology, so we went to this um Microsoft store at Stanford Shopping Mall back in 2016 and we tried um um the first Oculus prototype.","offset":1830,"duration":17},{"text":"Pedro: Like a early early version of Oculus. I think Oculus Rift or something. And we're amazed. So we thought, let's just go build that. And uh in a very like uh uh naive way we thought we could do it.","offset":1847,"duration":14},{"text":"Pedro: And then, you know, we spent, I don't know, two or three weeks playing with the hardware and the software and the technology, and we realized that, you know, it required—we knew nothing about hardware, nothing about optics.","offset":1861,"duration":12},{"text":"Pedro: And then—uh, we decided to pivot to something that we knew a little more, which was software. So—um, it took us maybe three or four weeks to pivot again. And then in YC, we saw that all companies needed a corporate card, and they couldn't get one.","offset":1873,"duration":13},{"text":"Pedro: So they went to the banks and they got rejected. The bank said, you know, you have no revenue history, and they said, yes, that's the point, that's why I'm a—that's why I'm a startup. And—and...","offset":1886,"duration":11},{"text":"Ashley: So even though you might have like seven million bucks in your bank account, you couldn't get a corporate card just because you don't have this track record.","offset":1897,"duration":7},{"text":"Pedro: Exactly. Um, and we thought, well, but they have cash in the bank, so what's the risk? And the bank didn't get that. So that was the original idea that uh allowed Brex to scale was underwriting the companies based on cash and effectively build a better American Express. That was the original original thesis and...","offset":1904,"duration":17},{"text":"Ashley: So it's supposed to be Brex, Brazilian Americ—well, instead of Amex.","offset":1921,"duration":5},{"text":"Pedro: Brazilian Express, yeah, that's—that's—uh—so—so the myth goes. OK. Um, but—but yes, um, it was a four-letter domain pronounceable in English with a backdrop name, uh, backdrop story for sure.","offset":1926,"duration":13},{"text":"Pedro: Um, so—so that that's how it got we got it off the ground. And it turns out it was uh one of the things that was interesting between Brazil and the US is there's actually this weird uh-uh negative correlation between how developed an economy is and how bad I think their payment rails are.","offset":1939,"duration":22},{"text":"Pedro: So, you know, when I was born in Brazil in '96, we had real-time settlement. Like the day I was born, it was not cheap, but you could settle a wire in real-time. We're in the US now um in 2026, right? 29 years later. And you still don't have, you know, you have like partly, but you cannot—like not all payments are in real-time yet.","offset":1961,"duration":18},{"text":"Pedro: And the reason is because when you look at Brazil in the 90s, we had hyperinflation. So the inflation was 30% a month. So if you didn't clear in two days, you lost like, I don't know, like 5-7% of the value of the money.","offset":1979,"duration":12},{"text":"Pedro: So there was a very deep investment in the payment rails because the economy needed it. And then the US, because it's such a stable economy and such a stable currency for, you know, hundreds of years, I—I don't think was as developed.","offset":1991,"duration":12},{"text":"Pedro: So weirdly enough, we saw a lot of room to actually revamp a lot of the financial stack in the US in a way that was bigger even than Brazil just because of the scale of the US economy.","offset":2003,"duration":14},{"text":"Ashley: People explain this to me sometimes. I mean, it's, you know, if you go to Europe, they're doing all kinds of amazing like very interesting stuff with financial systems. When I go to China, it's insane.","offset":2017,"duration":13},{"text":"Ashley: Yeah. Even like I went to Nigeria to shoot an episode of our show and, you know, there's parts of it that are like really backward, but then there's other parts where you you're just paying for your cellphone at like whatever the chicken shop and... mobile wallets, yeah.","offset":2030,"duration":14},{"text":"Ashley: Um, and then, you know, South America's—in Mexico are quite famous for innovating um on financial tech. And so the US always seems to be behind. It reminded me of like when I was starting out as a reporter, we were just woeful at telecommunications and Europe was so far ahead. And then and then like the iPhone like sort of rescued the US and made it interesting again.","offset":2044,"duration":21},{"text":"Ashley: But um I mean people have told me—you went over some of the points of this like stability—but other people have said to me it's because we have our banking system is so fragmented.","offset":2065,"duration":7},{"text":"Pedro: We have thousands of banks in the US. So uh for example, like Brazil, the Central Bank created this payment rails called Pix, which is effectively a real-time uh settlement between any two accounts. You can use your phone number or your tax ID as—as a key, and then it found—it finds your bank account and you can—I can transfer money to you right now, like almost any amount.","offset":2072,"duration":21},{"text":"Pedro: Which by the way has other uh-uh security implications in Brazil, which the system ended up handling later, but that's a separate story. And then in the US—but in Brazil you have really probably 30 major banks.","offset":2093,"duration":12},{"text":"Pedro: In the US you have thousands, like two or three thousand banks today. So when you want to roll out anything new at a systemic level, you have to go in bank by bank and make sure they comply.","offset":2105,"duration":11},{"text":"Pedro: So even if you look at uh RTP, like real-time payments, today, um, the ubiquity is of course the big banks support it, but if you're transferring to a community bank or a regional bank, a lot of times they don't support because, you know, technology is really behind in terms of adoption.","offset":2116,"duration":16},{"text":"Pedro: So being more concentrated also allowed for uh a faster innovation cycle. So but I would say it was uh the fact that the economy really needed it, right?","offset":2132,"duration":10},{"text":"Pedro: In Brazil, we because a lot of the payments were in cash and and offline um and and even on cards, um the government saw this need for first sort of bringing and modernizing payments.","offset":2142,"duration":12},{"text":"Pedro: And the Central Bank in Brazil I think did an amazing job with that, and and then second was moving more of the economy outside of cards into something that the government had more agency over. Um, and these movements were easier just because of, like, one, the pain point that existed and, second, the concentration of banks.","offset":2154,"duration":19},{"text":"Ashley: I'm going like—I was going to go chronologically, but now I just want to talk about this for a second. I mean, so the US is—is like destined to be woefully behind the rest of the world on—on many interesting financial innovations. Like, we're stuck unless we kind of change the...","offset":2173,"duration":18},{"text":"Pedro: Yeah. And the US has this like has a lot of uh sort of particular things that, you know, when you look at the the amount of the economy and and credit cards, for example, of course you have uh, you know, you have rewards, which is a very big part of the decision-making factor.","offset":2191,"duration":19},{"text":"Pedro: Um, you have uh uh no real-time payments in some things um and especially most money movement actually not real-time today in the US. You still have a lot of ACH that takes two or three days to clear. Um, you have uh you have, you know, there's no for example something you have in in Brazil, which I think is fascinating, is you have a clearing house for receivables.","offset":2210,"duration":21},{"text":"Pedro: So because because the interest rate is so high and the country um is so dependent on uh on factoring of any receivable you have when you have a contract or something, you actually have a centralized clearing house that you can register a contract and get a prepayment on that contract.","offset":2231,"duration":17},{"text":"Pedro: Doesn't exist in the US. So there's a lot of things that are that are very different um but at the same time creates a lot of opportunities for companies like us to to go in and do new things.","offset":2248,"duration":9},{"text":"Ashley: But—and OK, and then, you know, this next question comes with some baggage, because you've just—your—you're part of—you're going to be, whenever the deal closes, part of Capital One. This is a traditional um financial player.","offset":2257,"duration":14},{"text":"Ashley: I—I've just always found this shocking, you know, because I followed Stripe. I knew Patrick and John when they were like, I don't know, there was like eight people in the room or something like that.","offset":2271,"duration":8},{"text":"Ashley: And and then just the story you were describing about startups had money in the bank, people wouldn't lend to them. I mean like it's sort of I mean in some ways it makes sense because this is the story of business is that incumbents move slow and don't see opportunities in other ways.","offset":2279,"duration":18},{"text":"Ashley: I find it really shocking that that like Stripe could become such this foundational layer, this massive multi-multi-multi-billion dollar business that that the traditional financial companies were just apparently, you know, willing to to cede to these two Irish kids.","offset":2297,"duration":16},{"text":"Ashley: You—Brex just took off like a rocket ship from this this insight that you guys had and you being able to code all this infrastructure to make it happen. Um, yeah, like like are there still—is that typical? This is the same as I would see if I went into the energy industry or defense, or is finance uniquely um kind of conservative and bad?","offset":2313,"duration":30},{"text":"Pedro: I think I think I think it's, you know, if if the history of technology serves us any any any uh backdrop, I would say I don't think finance is too dissimilar.","offset":2343,"duration":12},{"text":"Pedro: What I would say is I think the interesting aspect is first the just the scale that finance has in terms of how businesses operate and how uh ubiquitous it is as a part of what makes just the US economy work.","offset":2355,"duration":15},{"text":"Pedro: So, for example, you look at Brex and we created this new category of, you know, modern modern uh software and financial services together. Um, you know, when you look into the US economy today, we've made a lot of progress, but 97% of the US economy still runs on traditional corporate cards.","offset":2370,"duration":20},{"text":"Pedro: 97%. And and there's a lot of room to grow in terms of just expanding what we've done and serving the rest of the market. And when we when we, you know, got approached by Capital One, the the interesting thing for us was we started just think, OK, where can the company be let's say in five, seven, 10 years in a standalone path?","offset":2390,"duration":21},{"text":"Pedro: And then what if we joined forces with uh an incumbent, but actually I think the most tech-forward bank in the world, um, that, you know, really realized that you could bring in data and machine learning and technology to revolutionize credit cards and the way underwriting was done. And by the way, there's sort of fascinating stories of how Capital One started that.","offset":2411,"duration":21},{"text":"Pedro: Um, and what could we do having that platform and that scale? And as we started to click into that, it was impossible to unsee it. And and really the the way to think about it is how do you bring the scale, brand, credit of, you know, major US financial institution with the technology and product we have?","offset":2432,"duration":21},{"text":"Pedro: And in a in a very interesting way, the thesis behind this is exactly what you were describing, is how do you accelerate the adoption curve of this technology that we believe should be core to how every business runs, but do it at a scale that is country affecting, right?","offset":2453,"duration":20},{"text":"Pedro: That you actually inflect uh the outcomes of so many businesses that depend on these things to to run and operate and are still working, you know, in with technology of like 30, 40 years ago.","offset":2473,"duration":16},{"text":"Host: Hello, geniuses. Let me tell you about E1 Ventures. They are a venture capital firm in Silicon Valley, a long-time supporter of this podcast and a long-time supporter of big, fantastic, world-changing ideas.","offset":2489,"duration":19},{"text":"Host: If you have such an idea, hit up E1 Ventures or send me a note and I'll put you in touch with E1 Ventures. It's uh it's quite a quite a deal for listening to this podcast. Um, thank you again, as always, to E1 Ventures for their support.","offset":2508,"duration":14},{"text":"Host: So like in these things, I mean they do work sometimes these types of arrangements. It's also not uncommon for the big incumbent company to to reject, you know, the innovation arm that they have purposefully set out to acquire, you know, for that very reason. Yeah.","offset":2522,"duration":18},{"text":"Pedro: So it's funny because one of the things that—well, two things I was very impressed by Capital One. One was just the speed. So from inception of this idea all the way to sign definitive agreement was a little over 40 days. So they actually moved with a lot of conviction and speed.","offset":2540,"duration":21},{"text":"Pedro: And second was the fact that being a founder-led company really changes the calculus for how you do things. And and speaking to—to Rich and the Capital One team, um, one of the major things that that they they realized was, \"Look, you know, the most important thing for us to think about as we make this work is don't crush the butterfly.\"","offset":2561,"duration":22},{"text":"Pedro: So how do you how do you leverage the scale and the distribution and all the benefits of Capital One, but also keep the things that are uniquely Brex and make Brex into what it is today alive and growing and...","offset":2583,"duration":13},{"text":"Pedro: The way Rich the founder describes it is uh, \"How do we just add water?\" To the Brex plant? Uh, and of course, you know, be very mindful about the the risk management aspect and the aspects that are inherent to being a bank. Um, but also leverage the scale and the distribution.","offset":2596,"duration":16},{"text":"Pedro: So I would say there's been so much thoughts on how to make this as lightweight of an integration as possible to preserve the momentum that Brex had as a standalone company and actually accelerate it.","offset":2612,"duration":14},{"text":"Pedro: So um, you know, what when you look into the the outcome here, um, we really think in three to five years the company will be just dramatically bigger than than what it would be on a standalone basis because of the water and the scale that Capital One brings.","offset":2626,"duration":15},{"text":"Ashley: Uh, let me—let me ask one annoying reporter question. I mean you at one point you guys are valued at 12.3 billion dollars in 2022. Uh, different world for variety of reasons.","offset":2641,"duration":12},{"text":"Ashley: You sell the company for 5.15 billion. I mean look, I think anyone would be happy with that outcome. But it is the nature of the beast then that some people compare your previous valuation to this number, and we're in this like total frenzy of of you guys...","offset":2653,"duration":19},{"text":"Ashley: Uh, some companies that shouldn't be named, um, you know, all um competing against each other very very vocally, very aggressively. I saw some some ramp cheerleaders, you know, celebrating this 5.15 billion dollar number. Um, yeah, I mean it's got to be a weird feeling to like you're having this great moment.","offset":2672,"duration":22},{"text":"Ashley: Yeah. There's a lot of money. You've accomplished something. It marks a moment in time. And then...","offset":2694,"duration":6},{"text":"Host: I guess it's competition, but then for it to be portrayed by some people one way.","offset":2700,"duration":5},{"text":"Pedro: So, so I think there's two sides of this. So the first one is, one of the things that we realized in 2023 is the company was in a very different position than today. And, and we decided to sort of aggressively turn things around, and that was end of '23, early '24.","offset":2705,"duration":20},{"text":"Pedro: And one of the things that we did that was very unpopular and, and extraordinary back then, is we actually did a big reset on the internal valuation. So, so, you know, yes, of course, we raised at $12 billion, that's, you know, that's a fact, but at the same time, how do you create enough upside for employees so that a $5 billion outcome is a win?","offset":2725,"duration":24},{"text":"Pedro: And that's what we did. So we went to the board, we actually repriced all the employee equity at a much different price. And that effectively, really changed the picture for employees and the team. And, you know, investors that invested at 12 billion, of course, you know, got their preference back. So, so it ended up being actually a very good outcome for everyone.","offset":2749,"duration":22},{"text":"Pedro: But the, the key thing was, in the moment where things were, were the hardest, like three and a half years ago, actually looking ourselves in the mirror and saying, \"Look, um, you know, I always say, you know, hard decisions easy life, easy decisions hard life.\" And the hard decision was, we let go of, you know, almost 30% of the company, we repriced the equity, we changed the way we operate a lot.","offset":2771,"duration":22},{"text":"Pedro: We promoted a lot from within. Uh, we took out two layers of management in the entire company, and we, we started this thing that, that I called Brex 3.0. Uh, so, so that backdrop was how we got to where we are today. And by the way, where we're still accelerating even faster than when we closed the deal, uh, uh, when we signed the deal back in, back in, uh, January.","offset":2793,"duration":25},{"text":"Pedro: So I would say the best way to think about it is we made a lot of deliberate decisions two and a half, three years ago that made this a win for employees because we decided to face reality and, and actually look at it with the lens of: everything eventually converges to public markets. Whether you like it or not, that's the only price signal that really matters. So how would you think of the company today if it was a public company?","offset":2818,"duration":26},{"text":"Pedro: And how do you ground ourselves in that reality, uh, as hard as it may have was in my be because, you know, the fairy tales of 2021 were just that—fairy tales. So then, and then I think the second piece is, you know, of course there's competition in the space, it's a massive part of the US economy, massive part of fintech, and it would be ludicrous to think that there wouldn't be.","offset":2844,"duration":24},{"text":"Pedro: But I think the, the best way to think about it is, you know, us and all modern competitors in the space, we're still 3% of the US market. So, so the question becomes: how do you go after the 97%? And, and what we decided to do at Brex is we said, \"Look, the reality is the chances of hitting two orders of magnitude bigger scale together, partnering with a massive incumbent, are fundamentally different.\"","offset":2868,"duration":27},{"text":"Pedro: And, uh, as we started to actually just see the scale of, like for example, like Capital One spends $6 billion a year in marketing. Um, we spend, you know, around 1% of that. Um, $6 billion in R&D, we spend, you know, 2 or 3% of that. So, so when you just apply the scale into the problem, and you just accelerate what's working, um, the question for us was: how do you solve for the 97%?","offset":2895,"duration":29},{"text":"Pedro: And, and how do we be the clear winner there? And subordinate all decisions to that, including structure, the capital, you know, all that, because for me, it was always about at the end of the day, I wanted Brex to become a major part of the US economy, Brex to outlive and outlast me. And the same way I look back, I left my previous company in Brazil 10 years ago, and Pagar.me is still second or third largest player in Brazil in online payments.","offset":2924,"duration":26},{"text":"Pedro: Um, I want the same to be true at Brex, and I want to be here for the next many years, um, and, and, but, but still I think the, the scale, solving for scale and just the reach of this technology in the way the average business runs was, uh, fundamentally a different thing to solve, and it's still very early days.","offset":2950,"duration":23},{"text":"Host: Well, please introduce Capital One's marketing budget to sexy Brex, say, and let them know what's possible. Um, and, okay, in, as far as like, you've been on this, um, I mean, it just feels like a whirlwind, man. I mean, you starting, you know, a business around 12, and then here you are, you're 29, I mean it's been nonstop, one thing after another.","offset":2973,"duration":24},{"text":"Host: You've been actually, like to your credit, uh, super open, you write these essays from time to time about, about big moments in your life, mental health things, um, things about, you had this really nice note about your mom, um, and I know you talked about some of the decisions she had made, but you know, she seemed um like a kind of like unconventional thinker around, around a variety of things with this, this kid who was, who was living an unconventional life.","offset":2997,"duration":27},{"text":"Host: And so anyway, I found your like really, you're quite thoughtful and open about these things. Um, do you, is there like part of you though, yeah, that just feels like you've been on this, you've just been carried, you know, not like you were, um, not an active participant, but I mean more that you've been bounding from one thing to the next on this ride?","offset":3024,"duration":23},{"text":"Host: Like is there, I always ask the Collisons this, okay, because they're like two of the smartest people I know, they are uh polymaths, they're interested in so much different stuff. Um, I know financial tech is very important, it's not the particular thing that like I think about all the time, and so you know, I'm always like, \"What do you guys, what do you guys like want out of life?\"","offset":3047,"duration":23},{"text":"Host: You know? Because, because is this, is this just a thing that you made when you were young and it turned into this huge hit, and you're, you're trying to, they always talk about increasing the GDP of the internet and the world, and I see that, right? It opens, I went with Patrick to, uh, Israel and Palestine and I saw people who were setting up businesses on Atlas that like otherwise just could not incorporate their company and now they're selling to the entire world.","offset":3070,"duration":22},{"text":"Host: So like I get it, I'm not trying to undermine something, but um like is there part of you that just feels like you've, are you making all these conscious decisions or you've just been pulled on this journey?","offset":3092,"duration":12},{"text":"Pedro: Yeah, it's, it's a great question. I think, I think I think it's a little bit of both, because I, I would say on one hand, you know, I, I really like to believe that, especially now with AI, learning new things is a fundamentally lower barrier than it's ever been. So if I said, \"Look, I'm going to learn how to make X,\" I think it's possible to learn and master that.","offset":3104,"duration":24},{"text":"Pedro: At the same time, I think the sets of opportunities that exist that are interesting, they tend to be related to domains that you explored in the past. And, and I think your ability to recognize what's a good opportunity is also higher in things that you have more exposure to. So I don't think we would have been able to build Brex if we hadn't built our first company in Brazil, because we just knew too much about payments.","offset":3128,"duration":25},{"text":"Pedro: Uh, we were just very deep in the weeds, we knew the issues with credit card issuing, we knew like what the acquiring side looked like on the merchant side, uh, we knew a little bit of credit underwriting, our first company was also regulated by the Central Bank, uh, and we were the officers of that. So, so there were a lot of conditions that made Brex possible. So in a weird way, I think you create this set of experiences that make the next thing possible.","offset":3153,"duration":24},{"text":"Pedro: And, and I think there's something that, that Jensen says that I think is really true, which is, you know, at the end of the day, it's easier to learn to fall in love with what you do than to do something that you love. Because I think when you think about love and, and sort of a deep connection to a craft, ultimately something that I think is very deeply encouraging is when you feel the sense of mastery with something.","offset":3177,"duration":26},{"text":"Pedro: And not from an ego perspective, but from the perspective of: I just understand every layer of this problem, and I can think about second-order effects, I can think about implications, and I can see the world through a much bigger aperture because I have this unusually high exposure to this problem. And, and I think there's something about that in fintech where, you know, the more you think about, you know, and we see this with AI, like we, you know, we spend a lot of time looking into like what actually changes when you, when you start to deploy AI agents in companies.","offset":3203,"duration":31},{"text":"Pedro: And of course, the early things are, yes, there's a bunch of cost savings. Like second, there's, you know, compliance increases and data quality increases and automation increases, but, but then you look into like a layer deeper and you see like: okay, how much time does the, does the US economy spend like managing expenses? And turns out it's 50 million hours.","offset":3234,"duration":25},{"text":"Pedro: And then we're like, \"Okay, like how many things can we do, possibly, that contribute 50 million hours to the US economy?\" And, you know, we build these agents that automate all of the tiny processes and, uh, and, you know, you see the impact inside a customer and it's pretty remarkable, the reactions of the finance teams as they say, \"Wow, I actually didn't even think this was possible, even with technology today.\"","offset":3259,"duration":21},{"text":"Pedro: And this is like, by the way, on like Anthropic and OpenAI, like that are sort of at the bleeding edge of AI and deploying AI internally. So, so but then it's like: okay, how would we even recognize that that opportunity existed? Um, and it goes all the way down from, well, you know, yes, we were building corporate cards originally, and corporate cards are a big part of how spend gets initiated in the company.","offset":3280,"duration":24},{"text":"Pedro: And it turns out that, you know, initiating and making spend decisions requires, you know, a lot of sort of delegated decision making, so you need to create tools that empower the finance team to be in every decision. What can help with that? AI. And then, well, how to make AI really, you know, really effective at scale and give the finance team control over how AI is operating? And then you build a lot of agents.","offset":3304,"duration":23},{"text":"Pedro: So, so you sort of, you sort of cascade this down, and there's seven or eight hops from the original idea all the way to the outcome that we deliver today. And these things were recognizable because of a previous pattern. So, so I think that's the part that's like hard to understand, to, to overstate. I wouldn't say that it's, I am sort of a uh, like I, it would be irresponsible to not do something that's not fintech, like, like, but there's something to be noted about the fact that you get to certain places because of where you've been in the past.","offset":3327,"duration":37},{"text":"Pedro: And uh, I'm grateful for the, the experiences that sort of exposed me to the the issues and the problems and the solutions that I was able to build by having been on this track.","offset":3364,"duration":12},{"text":"Host: And do you think this is going to, maybe it's really hard, I mean you're still so young, 29. Um, you know, I read about you being obsessed with space documentaries when you were a kid. Um, you know, I hit you up on a, on an AMA asking what you were interested in outside of, of fintech and you mentioned space and energy. Do you think there's like another chapter in your life where you dig in on something like that, or is that something maybe you're investing in and, and it's on the side?","offset":3376,"duration":29},{"text":"Pedro: Yeah, I mean, I am, in the, in the sort of spirit of both topics, you know, I'm actually very curious about robotics now and trying to understand what's at that frontier. And of course, you see Tesla and Optimus and all that, but also what are sort of more bootstrapped versions of that in, in new companies building things that are pretty uh interesting? So that's been a, the a big area.","offset":3405,"duration":27},{"text":"Host: Meaning like you, you just keep an eye on it or you're, you're participating?","offset":3432,"duration":5},{"text":"Pedro: I, I, I mostly keep an eye on it and try to, you know, angel invest in a few things. But, but I would say that's sort of a newer curiosity over the past maybe like three to six months. Um, when you look into like things I'm spending a lot of time um is, is, uh, you know, I am really interested in this idea of virtual employees. So how do you actually deploy virtual employees inside a company that look and feel and act like an employee?","offset":3437,"duration":26},{"text":"Pedro: So they are real people with real names on Slack, on email, engaging with people, joining meetings. Um, I got obsessed with Open-webUI over the past like three months, uh, and, uh, you know, automated my entire life. I can tell you more about that, but, but these are the things that I'm spending a lot of hours now.","offset":3463,"duration":19},{"text":"Host: No, no, please do. Do you have a, do you have a human admin?","offset":3482,"duration":4},{"text":"Pedro: I do, I do.","offset":3486,"duration":2},{"text":"Host: And then is this human admin competing against your virtual admin?","offset":3488,"duration":4},{"text":"Pedro: Um, they, they, I would say they don't overlap as much, per se, uh, deliberately. My, my human admin is amazing. But, uh, I would say, no, so look, I think the, how we got here, right? And I think Opus 4.5 was AGI, or very close to AGI, and Opus 4.6 was the sort of missing, missing—the sort of rough edges that, you know, got a little better.","offset":3492,"duration":24},{"text":"Pedro: So the way I think about it is, you know, electricity was invented in December. We're now in March. Uh, what are the things that you can build with electricity now? And that is the, the big question. And to me, the fundamental capability jump was uh, that of course coding models were the, the very interesting thing that, that and you see Claude Code and all these, these agent harnesses evolving.","offset":3516,"duration":26},{"text":"Pedro: But I actually think the most interesting property that was unlocked was, uh, the capability of a model to self-bootstrap. So, so basically one of the things we're experimenting now at Brex is actually using Open-webUI to create virtual employees. So, uh, we created this, like, virtual recruiter, for example. Uh, we call him Jim. Um, and Jim is literally a Slack entity, a Slack person, has his own email, and engages and talks to recruiters internally.","offset":3542,"duration":27},{"text":"Pedro: And the thing, the whole, the whole challenge was: how do you build Jim without writing a single line of code? Um, and the idea is, and of course, there was still semi-technical people involved because it was one of our first early iterations of this. But the really interesting thing is, you see a recruiter engaging with Jim, and then saying, you know, for example, I just saw this before coming in here, a recruiter was saying, \"Look, can you take a look at this person's application? I have a sense that this resume was fabricated. So how do, how do you look at that?\"","offset":3569,"duration":29},{"text":"Pedro: And then the agent looked at that and actually built a capability of screening a resume and understanding if it was fabricated or not. And that was never coded by anyone. And I think that's the fundamental leap that we were missing. And a lot of what we're spending time thinking is how to deploy this safely, of course, inside Brex, and there's a lot of things on the security side that we're also spending a lot of time.","offset":3598,"duration":23},{"text":"Pedro: Because I feel the challenge that the industry is in now is people say, \"Well, you can't predict what models do, they're not safe, therefore I'm not going to use something like Open-webUI in a very, you know, in a very important environment because who knows what's going to happen.\" And the stance that we decided to take is saying, \"Well, why don't we just solve for that security aspect and then actually deploy these things internally and leverage that technology and, and see where the frontier really is.\"","offset":3621,"duration":27},{"text":"Pedro: Um, so, you know, we, we're actually going to open source this, but we actually built this entire, like, technology layer. Um, we actually call it Crabtrap, uh, funnily enough, where the idea is when you have something like Open-webUI running, um, we, the best way to monitor what an agent is doing isn't to have a human looking at it, it's actually to have another LLM looking at it.","offset":3648,"duration":22},{"text":"Pedro: So we build this thing that effectively intercepts all the traffic coming out of like an Open-webUI instance and routes it through another LLM that's through uh an HTTP proxy that screens all the traffic and says, \"Is this something that a recruiter agent should be doing?\" So, for example, should a recruiting agent send like a harmful message to a candidate? No. Um, and it can go in and block that request at the network layer, while the agent itself is even not even aware that that's happening.","offset":3670,"duration":30},{"text":"Pedro: And the really cool thing of that is you can actually run this at scale, and the only technology that we think will be able to monitor agents is actually agents themselves. But you build this almost adversarial effect where you have one agent monitoring another agent, um, and we've seen surprisingly good outcomes of this thing so far.","offset":3700,"duration":21},{"text":"Pedro: So, uh, does that mean that we're deploying, you know, Open-webUI and virtual employees in the most critical workflows in the company? Not yet. Um, we're deploying in a few. But the really interesting thing is, instead of saying, \"Well, let's hold back and not deploy these things because at the frontier we haven't resolved security yet,\" we said, \"No, no, why don't we just solve security?\"","offset":3721,"duration":21},{"text":"Pedro: Which is a, a systems problem, um, it's a distributed systems problem more than anything else. It's an engineering challenge. And then the technology and the LLMs and the state of the art of the models is already like wildly capable except for this one problem that we'd rather solve against, around. Um, so that's been like fascinating.","offset":3742,"duration":22},{"text":"Host: And then and you were saying and you're using Open-webUI like in your life? I mean is this the stuff you're talking about or you more personal?","offset":3764,"duration":7},{"text":"Pedro: Oh yeah, well, no, this is we're using Open-webUI in a bunch of different contexts. Yeah, virtual employees is one. The other one is, uh, um I use it personally to do everything, um at this point. Uh, like I literally run Brex through Open-webUI right now.","offset":3771,"duration":16},{"text":"Pedro: So the the way it works is, I think most, there's a lot of productivity tools with AI, right? And I think the thing they fail is that they they don't assume that the world is a very noisy place. So when I go into Brex, Brex has like thousands of Slack channels, like thousands of people, thousands of—I receive like hundreds of emails a day. And the question is like: what matters? Like what what to pay attention to?","offset":3787,"duration":25},{"text":"Pedro: So I built this um this uh autopilot system that starts with this uh signal ingestion pipeline. And basically the way it works is it screens my email, my Slack, uh Google Docs, um WhatsApp, a few different data sources. And then, but the really interesting thing is I decided to build my automation in my life around two concepts: uh people and programs.","offset":3812,"duration":328},{"text":"Pedro: So programs is almost like a project that I want to be updated on. So, for example, financial performance of the company, um Capital One integration, um uh AI strategy internally. And the thing about a program is it's very declarative about what I care about and what I don't care about. And then what it does is it screens those signals in the context of these programs and then organizes, you know, interactions that happened that I should be aware of or action items.","offset":4140,"duration":30},{"text":"Pedro: And then it does the same for people. There are also people that I care about. So I declare who are the people that I care about, and there's probably 25 people in the company, um and in my my life more broadly. I declare those people and what are the things that I actually care about. And then the signal ingestion filters with the lens of these people, you denormalizes signals and then it processes them. And then it produces this very clean uh summary of everything that's happening in the company that I should care about and all the action items.","offset":4170,"duration":31},{"text":"Pedro: And then then there's the really cool part, which is all the action items that I should do are things like, \"Well, I finished the customer conversation, I need to go in and update the the deal team on that account,\" or \"I had a meeting, someone asked me for an intro,\" or or all these things that are follow-ups from meetings.","offset":4201,"duration":17},{"text":"Pedro: And then the cool thing is because I have the signal ingestion, I can go in and I have this other thing called an auto-resolver that it can go into the list of to-dos that I have and say: how do I automatically action this task based on the context from the meeting?","offset":4218,"duration":15},{"text":"Pedro: So, for example, like let's say I go in and I say, you know, uh we should talk about, I want to figure out how to get that card. Uh let me have a follow-up on that. So then I can have Granola listening to the conversation. Granola is running on every meeting that I have, ingesting that into the signal ingestion pipeline, creating an action item.","offset":4233,"duration":19},{"text":"Pedro: And then when the auto-resolver runs, it says, \"Okay, what's the context for this to-do, this task that I have?\" It will go back to the notes, and then it can say, \"Well, I can send you a text or send you a Slack message or you an email, depending on, you know, whatever is best.\" And then it can draft that message automatically.","offset":4252,"duration":13},{"text":"Pedro: And then all I have to do is click a button. So all these are building blocks and skills that you can build together. Uh you can do it either on Open-webUI or or Claude. I actually have it running on Open-webUI now to effectively decompose the CEO job of like ingesting signals, what matters, building a summary, determining tasks, making those tasks happen, monitoring my team for those tasks, so it also can do follow-ups automatically.","offset":4265,"duration":27},{"text":"Pedro: Uh, and I can also go then and build skills. So for example, I can go in and say, \"Well, a way to auto-resolve is a Slack message, or is there's a skill that I created called Review a Doc as Pedro.\" So there are things when I'm reviewing a document or a product review or a presentation that I always ask.","offset":4292,"duration":19},{"text":"Pedro: So I like, for example, like, you know, \"What is the most important thing that this thing should be driving? And like how did we choose that thing? Um what's the bottleneck making this thing happen to go faster? Um, you know, why aren't we moving faster?\" There are like three or five questions that I always so you basically make that into a skill, and then you build that into the pipeline.","offset":4311,"duration":18},{"text":"Pedro: So it's basically LEGO blocks that you can put together to accomplish like really complicated things uh through these systems. And of course, like I, I as an engineer, I had to go and build these things. But, uh, and I think I'm going to open source this, but it's basically this entire like CEO or I guess like almost like, you know, leader in a in a information-based company uh workflow, um and it's been really fun to build it.","offset":4329,"duration":26},{"text":"Host: So it sounds like, I mean you just got really sucked into this and so and you just mentioned, I mean you're doing this.","offset":4355,"duration":6},{"text":"Pedro: Oh yeah, like yeah, like it's the AGI psychosis I would say. We have a rule at home, which is uh no AI Saturdays. My wife is like—because like I'm basically like talking to my Open-webUI all the time, like I'm sending voice notes. Uh and it's the best developer experience because you can be like on the way here, I was like like I had this like synchronization issue on my data pipeline.","offset":4361,"duration":22},{"text":"Pedro: So I was like literally sending voice notes saying, \"Hey, like change this, change that, do this, do that.\" Um and it's amazing. Like I can be on the car, I was on a Waymo like coming in here and uh getting getting a bunch of things done, um so but the problem is it's so easy that you start doing it all the time. So then I can be having dinner and sending voice notes and my wife's like, \"Stop, let's have dinner.\" Um and then Saturdays no AI at home, which is a which is a kind of a fun thing.","offset":4383,"duration":25},{"text":"Host: And when you were when you were um living such a frenetic life and and getting pulled in all these different directions and you kind of, you know, you talk—\"I've had a panic attack\"—you talked about having a panic attack, you talked about getting into meditation and reading and sort of changing your nighttime ritual. Like what kind of things do you read at night?","offset":4408,"duration":23},{"text":"Pedro: Gosh, uh right now I'm reading a totally different thing. I'm reading uh Benjamin Franklin's biography, um uh by Walter Isaacson, which is actually quite good.","offset":4431,"duration":10},{"text":"Host: I've read that one.","offset":4441,"duration":1},{"text":"Pedro: Yeah, yeah, very interesting. I mean I I generally like uh the Da Vinci one's also very good because I I think there's this thing where uh a hundred, a couple hundred years ago, or even longer, I think the sort of Renaissance man, this like multi-faceted person that knew a little bit or actually even a lot about different domains, was a big thing.","offset":4442,"duration":29},{"text":"Pedro: And uh intersection of arts and science is something that I like a lot. And uh, you know, Benjamin Franklin was a not only of course had a massive effect on uh as a Founding Father and in the definition of what the US is, but but also as an inventor, and you know, um he was so deep in in electricity and things like that. And uh that's very that's very remarkable.","offset":4471,"duration":21},{"text":"Host: Journalist.","offset":4492,"duration":1},{"text":"Pedro: Journalist, of course. Uh, so and uh, you know, uh uh ambassador for the US, right, in in France for the first time in the right after the the Independence. So so it's a it's remarkable to read it.","offset":4493,"duration":15},{"text":"Host: Is that like, do you like non-fiction?","offset":4508,"duration":3},{"text":"Pedro: I I almost always read non-fiction. Um I read your book, um the Elon book, which is very good. Uh and uh you can and I think I think so much of what I enjoy is trying to understand someone's frame of mind.","offset":4511,"duration":17},{"text":"Pedro: And one of my favorite questions, um it's a weird question, but it's uh: what is the experience of being you? And it's a it's a profound question because there's there's a few like mental models in your head when you look at the world that sort of shape your experience of acting and being a person.","offset":4528,"duration":23},{"text":"Pedro: And and I think that's very profound. So um when you read these like biographies that go very deep, I think ultimately what you're getting to is like: what is the experience of being this person? And great biographers, as I'm sure you know, like you ultimately that's what you're trying to crack, right?","offset":4551,"duration":18},{"text":"Pedro: You're trying to you're trying to there's all these stories and it's almost like, you know, there's this elephant that you're touching different parts and you're trying to triangulate like: what what is the entirety of this person? And and I think biographies are great at that. Um, I mean I read you know I read a few technical books on uh the Art of Doing Science and Engineering from from Stripe Press.","offset":4569,"duration":23},{"text":"Pedro: I read a lot of things that are relatively technical, um but I think biographies and things that go very deep, um the Nvidia way um from about about Jensen, I think I think gives you that same mental model. And ultimately, I think you know it's the the Charlie Munger thing, you know, at the end of the day uh being successful is a collection of like 30, 40 to 50 good mental models and just applying them everywhere.","offset":4592,"duration":26},{"text":"Pedro: And uh and and I think seeing how remarkable people have different sets of these like 30, 40, 50 different mental models I think is uh is pretty fascinating.","offset":4618,"duration":12},{"text":"Host: Yeah, no, um biography, yes, oh we could talk for long time about that. Very strange experience doing one as well.","offset":4630,"duration":8},{"text":"Pedro: What was it like? What was the what were the—","offset":4638,"duration":3},{"text":"Host: God, I set myself up for that, didn't I? I mean I really could talk for hours. It was it was uh it was funny in some ways because I I at that moment in time, I wanted to do a book. I'd gone to see uh SpaceX—I was working on a magazine story about Elon.","offset":4641,"duration":20},{"text":"Host: I had not like set out to do like a biography on Elon Musk. But I, you know, I when I went to SpaceX, it was it was just so um so different and and further along than I pictured in my head. And it was just right in Los Angeles and it was it was like it was just thriving and just had this energy.","offset":4661,"duration":18},{"text":"Host: And anyway, that's what kind of sucked me in. And then I got interested in Elon, you know, interacting with him and reporting the story. And then so anyway, you know, I signed up for this thing, but I had no idea what I was getting into in the sense that you spend three years thinking about this one person. And that's like your job. And it's like it's very all-consuming, you know?","offset":4679,"duration":21},{"text":"Host: You start to have dreams about that person. Um all the things you mentioned you're trying to do, hopefully you're trying to do a good job, and so you're not you're trying to you're trying to talk to a bunch of people to get at what you're talking about. It's like it's like Elon's always going to represent sort of like how he wants to be represented, and then you're trying to talk to all these other people to triangulate.","offset":4700,"duration":21},{"text":"Host: I don't know if you ever get to truth, but some some version of that that you're conveying at least you can you can give people: well, this is how these other people experience him and you know, and try to create as full of a picture as you can. But then you get into this um becomes very strange, right? You um I you know, was like: I'm thinking about him all day, you're like having dreams about him at night.","offset":4721,"duration":26},{"text":"Host: I was like: I didn't sign up for this. I want some peace, you know? And and so I mean there was just part of it that I didn't expect. A lot of what you're talking about though, you're like trying to put yourself in this person's shoes. And then and then there's this strange thing where you're like: I don't know I don't know if I was ever really trying to pass judgment, but you are passing judgment on certain things for the people that are going to read this book.","offset":4747,"duration":26},{"text":"Host: And then it's just like a lot of I don't know if it's like pressure, but but if I think if you're wired the right way you kind of you want to do a good job at it and and so yeah, it's very strange. And then um after that, you know, that book became such a hit that there's just all these things I didn't sign up for, you know? Now you're like the Elon guy. And it's like it's like: yeah, I found him fascinating, but I'm interested in lots of shit, you know?","offset":4773,"duration":23},{"text":"Host: I don't I don't need to be the Elon guy for 10 years. Um and so but you know—","offset":4796,"duration":3},{"text":"Pedro: But you know, I think the gift of uh great biographers is uh well just books in general, right, is I don't think people realize how remarkable it is that you spend three years of your life dedicated to this. And I can sit down in four days and consume that. Uh I think that's such a profound such a profound realization.","offset":4799,"duration":20},{"text":"Host: That it's a crazy amount of work. Yeah, when *The Heavens* went on sale, the one I just did, that was six years and it's it was just it's kind of crazy. I mean, I love it. That's actually the most fun part is the journey, you know, and like the process. And by the time you finish the book, you've worked on it for so long, you've read it so many times, you're just like: I never need to look at this again. It's just like now I want to do the next next thing.","offset":4819,"duration":27},{"text":"Host: But that exactly what you said is also what I love about magazine writing. It's why I liked working at *Businessweek* for so long was that I could go in a in a condensed, smaller form than the book to go like live your life for some version of your life for three, four months. And like inhabit these worlds, right? And like see what people's mental models are like and see what their you know, it's not always perfect because again people are putting on personas and things like that. But if you if you spend a decent amount of time at it.","offset":4846,"duration":27},{"text":"Pedro: And I'm sure the more you do it, the better you get at cracking it.","offset":4873,"duration":4},{"text":"Host: A little bit, right? I think, and and but that's the best part of the job is you just get to see it's like: oh, this is how Bryan Johnson lives, this is how Jensen lives, this is how, you know, Jennifer Doudna lives, it's like it's it's just cool to to sort of shed your own ego for a bit and just just watch. Yeah.","offset":4877,"duration":22},{"text":"Pedro: That's inspiring.","offset":4899,"duration":3},{"text":"Host: Um well I want to be mindful of your time. I just had like a couple last, I mean they're more just like just out there questions I guess. I mean I'm just so curious what you think like the future of money is in 20 years.","offset":4902,"duration":16},{"text":"Pedro: Yeah, I think I mean I think I think you're going to have a lot of the the the sort of payment, you know, evolution, right? You see Visa Mastercard already positioning themselves on stables, you see of course Stripe doing a lot of moves there. So I think that's going to continue. But I actually think that's less interesting. What I think is more interesting is the the decision to spend money itself.","offset":4918,"duration":25},{"text":"Pedro: And and I fundamentally believe that, you know, you become what you spend on as a company, as an individual. Like you become your resource allocation. In terms of the people you hire, in terms of the the decisions you make, the technology you use, right? You know, one of the quotes that I that I really like is, you know: we shape our tools and our tools shape us.","offset":4943,"duration":22},{"text":"Pedro: So so I think the way I think there's going to be a fundamentally higher level of thinking behind how companies make financial decisions. And and you can imagine that a lot of it is this problem of context and just aggregating information and understanding what are the implications of this decision uh to of course the revenue, the costs, but but even to things like the culture of the company, to the vision and the mission and what are you trying to do.","offset":4965,"duration":26},{"text":"Pedro: And these things cascade down all the way into a single individual Wednesday, right? So uh you know, there's this thing that uh I forgot who said it, but uh \"life is a picture but you live on a pixel.\" So at the end of the day, you know, you can talk about these visions, but it has to materialize on a mundane Wednesday. Like how does how does that change your mundane Wednesday?","offset":4991,"duration":27},{"text":"Pedro: And I think when you have this this uh autopilot to the way companies make decisions and you fundamentally change the calculus of where capital is going to be more aligned to where what matters to you as a company and as an individual, I think that's a very big unlock.","offset":5018,"duration":24},{"text":"Pedro: Um and and I think it's it's going to be more profound than people realize. And of course, AI is going to enable that and you're going to need all the of course the payments technology, agentic payments, like agentic commerce, all these things will will play a role. But ultimately like, you know, what's the icing on the cake and what's the cake itself?","offset":5042,"duration":17},{"text":"Pedro: And the cake itself to me is this idea that, you know, the the quality and the ability and the level of discernment that you're going to have in financial decisions because you can have so much of this context is like: what if you had the best CFO in the world making every decision? You know, the best, you know, founder in the world helping you make hiring decisions.","offset":5059,"duration":20},{"text":"Pedro: What if you had the best person in the world deciding where to where to expand next, where to grow, how to grow, how to look at your unit economics? And I think that will become true in the next few years and hopefully we play a big role in it. But it's like it's going to happen regardless.","offset":5079,"duration":16},{"text":"Host: So then companies just like if everybody has some sort of perfect information and they have the ideal CFO and the ideal all these positions, I mean so you just still end up competing on on your product and your your—","offset":5095,"duration":14},{"text":"Pedro: So that's that's the fascinating thing, which we have we had a lot. So for example, we're building these recruiting agents. And and I think the models are because of the amount of like post-training that goes into them, they have this relatively uniform view of what is a good candidate. But then the question becomes: what is a good candidate for us?","offset":5109,"duration":22},{"text":"Pedro: And and I think it's that like focus and constraints uh are what give meaning to your choices. So so when you have to go to a recruiter and you say: what are you willing like where does this person need to spike on? And how do you hire for that instead of sort of lack of weaknesses, which is where the models generalize and go typically, right?","offset":5131,"duration":21},{"text":"Pedro: Model is very hard to make a model say no. And and I think that's a very profound learning because that is the hard question. It's like what what where does this spikeiness matter, right? Where does it matter to be you know astronomically different? And and I think that's where the judgment comes in of what kind of company you want to build.","offset":5152,"duration":18},{"text":"Pedro: And I think that's an inherently human decision.","offset":5170,"duration":2},{"text":"Host: And you're giving it that flavor?","offset":5172,"duration":1},{"text":"Pedro: Yeah, that's the challenge. It's like how do you give that taste of Brexiness into—","offset":5173,"duration":5},{"text":"Host: Yeah, because there's like a world where the AI recruiter doesn't want you or George Hotz because you look pretty weird.","offset":5178,"duration":7},{"text":"Pedro: Exactly. And one of the things that we do is like one of the factors that we really like is, I mean of course I'm biased by this, but it's who were people that did something uh at a moment in their life where they had absolutely no other reason besides love for the game, love for the craft.","offset":5185,"duration":19},{"text":"Pedro: And well, people that are coding in high school don't have any reason to code, maybe getting into college, but you just you can just tell based on the kinds of things they build and the relationship they have with the craft. Um people that were doing completely different jobs, like someone that was in finance but ended up going super deep in AI and Claude Code and building this massive thing to automate their jobs—they didn't have to do that but they did it anyway. That was driven by something pure.","offset":5204,"duration":23},{"text":"Pedro: So so that is something that we care about a lot and we want to teach our recruiters to do it, but that's us. That may not be true for every company. And I think this ability to to understand the ethos of what you care about when it comes to this function and separating that from the technical excellence, I think is a really important thing because the technical excellence I think will be true no matter what.","offset":5227,"duration":24},{"text":"Pedro: And the and the point about the ethos—the reason a model can't discern that is because like that is a choice. And and you can't really argue with you know is it better to hire someone that's uh you know started coding before they had to in their lives, or to hire someone that went to an academic route and has a PhD in machine learning and you know and AI and is going to go do research at OpenAI or Anthropic? Like it depends. Depends on what kind of company you want to build.","offset":5251,"duration":34},{"text":"Pedro: Um and I think that's the that's the part that's really interesting is like if you just take out all the things that are not about the ethos away and you give that job to the models, what what matters what remains? And these are the harder questions, the ones that require a lot of discernment. And uh and I think it's where people should spend a lot more time.","offset":5285,"duration":19},{"text":"Host: What's the UI on your Claude your Claude bot?","offset":5304,"duration":4},{"text":"Pedro: Uh the UI? I have a I have a I have a autopilot UI that has like all my all my tasks and like all my my entire system. It's like a just a a little web UI.","offset":5308,"duration":11},{"text":"Host: But it's almost like a Claude project or—","offset":5319,"duration":2},{"text":"Pedro: Uh no, it's like a website, like a server that it runs, and then I talk to it on Telegram and uh I use Discord for uh multi-channel and like sub-agent coordination and things like that.","offset":5321,"duration":11},{"text":"Host: So like if you're if you're trying to set up a tennis match on Sunday at 3:00 p.m., are you—","offset":5332,"duration":6},{"text":"Pedro: I would just send a voice note.","offset":5338,"duration":3},{"text":"Host: And then and like it would uh what if it needed to book the court?","offset":5341,"duration":4},{"text":"Pedro: Um it has well it actually has uh something that we're shipping at Brex very soon. Uh it has access to a way of creating virtual cards on Brex through an MCP. So we'll go do that, go in the website, put a credit card on file, come back and say, \"Hey, it's done.\"","offset":5345,"duration":16},{"text":"Host: So the agent would go do that. Is there like any way I'm spending three days assembling and answering questions about my personal taxes in 10 years to do my tax return? Please tell me that's not going to happen.","offset":5361,"duration":11},{"text":"Pedro: No way. Absolutely no way.","offset":5372,"duration":2},{"text":"Pedro: Well and it's going to happen on both sides, right? The IRS will also be doing your taxes for you and then it's going to be with yeah exactly. So it's uh I think that's probably true already to some degree but but you know I I tell people: everybody's going to be audited because the cost is going to be zero. So uh that will be an interesting future.","offset":5374,"duration":17},{"text":"Host: It like it drives me insane. It's like all I do I it's a lot of hours just to gather up all these stupid documents every year when my my computer could just be doing this all year.","offset":5391,"duration":11},{"text":"Pedro: Unbelievable. Unbelievable. Yeah. And and the thing that's interesting is, uh, you know, it's a fundamentally different problem. Like it's almost like there's the tax software and there's the bookkeeping job. And the bookkeeping job part of it is interacting with the tax software.","offset":5402,"duration":17},{"text":"Pedro: But another part is gathering all documentation and going in and asking you about specific expense and transactions and what they were and what they weren't. And uh yeah that the the bookkeeping job is the is the really interesting part that will which will become part of the software eventually.","offset":5419,"duration":14},{"text":"Host: So what like what I mean accountants become like um lawyers? I mean they're just handling the highest most difficult questions?","offset":5433,"duration":8},{"text":"Pedro: I think so. I think so. And and I think the my my thesis is, like for example on accounting, I think you will still have a bookkeeper because you need a CPA to file your taxes. That's like a legal requirement. Like if you're filing someone's taxes on their behalf, you have to be a CPA.","offset":5441,"duration":18},{"text":"Pedro: And and the beautiful thing of this system and the way it works actually is a CPA has some degree of personal liability in case there's something wrong with your taxes. And that creates this very very good back pressure in the system where well because someone is personally liable, they better make sure that the data is correct. So they better make sure the tools they're using have a high enough bar for accuracy and control.","offset":5459,"duration":23},{"text":"Pedro: So so I think that's actually a really powerful thing where I like even if you had like Harvey and and let's say the the law the law uh agentic AI, uh sorry agentic agentic law firms doing doing really great work, having a human in the end matters because you know I we we talk a lot about this idea like what if Jim makes a makes a very big mistake on hiring?","offset":5482,"duration":27},{"text":"Pedro: Like do you hold Jim accountable or do you hold an employee accountable? And actually you need the same oversight mechanisms that you have of employees. So Jim has a manager. There's someone on the recruit team that's actually Jim's manager. So signs off on all the actions.","offset":5509,"duration":10},{"text":"Host: Has to have a hard talk with Jim.","offset":5519,"duration":2},{"text":"Pedro: Exactly. Exactly. And give feedback, right? And and give access to tools and set a budget and, uh, you know, have ways of giving feedback and make sure the feedback's incorporated, um and and fire Jim and change Jim in in case things go wrong. So I mean firing is more more of a figure of speech.","offset":5521,"duration":18},{"text":"Pedro: But ultimately the idea I think this idea of oversight over agents and how do you get humans comfortable with the fact that agents are doing things on their behalf I think is a very fascinating problem.","offset":5539,"duration":-587},{"text":"Host: Have you had a AI agent pay for something on your behalf? You have. Through Brex or through the—","offset":4952,"duration":7},{"text":"Pedro: Yeah, yeah. Yeah, yeah, yeah. Through Brex. Through uh well Open-webUI through a card a Brex initiated card, a Brex created card.","offset":4959,"duration":6},{"text":"Host: Okay. Like you're doing this all the time or this is—","offset":4965,"duration":-598},{"text":"Pedro: No, so so I mean I I don't do it like I probably do it like once a week I would say, um even though I make an online purchase probably like every two or three days. So so I would say it's like a third. But but I am I am also trying to deliberately push the boundaries.","offset":4367,"duration":612},{"text":"Pedro: So a fun one was uh we had a couple of friends that were going to the movies, and then they they sent us, \"Hey here are our seats.\" And then like I literally just forwarded the message to uh to my Open-webUI and I said, \"Buy the tickets nearby.\"","offset":4979,"duration":-585},{"text":"Pedro: And then it went online, went on the Cinemark website, found the movie room, found the the time, uh found where they were seated and said, \"Well these two seats are taken you should take the ones next,\" um and then I was like, \"Sure.\" And then it went online, put the card details, made the payment, and it was done. And then I got an email confirmation and I didn't touch anything.","offset":4394,"duration":23},{"text":"Host: Do you have a name for your Open-webUI system?","offset":4417,"duration":3},{"text":"Pedro: Uh I do. It's uh a funny it's I call it Lemonpie, which is a it's a weird thing because when I was 12 my first AI agents uh I call Lemonpies, my favorite dessert. Um and every sort of bot that I do in my life is called Lemonpie. So I was like: okay this thing has to be called Lemonpie. Um but anyway it was a was a sort of funny historical accident.","offset":4420,"duration":18},{"text":"Host: Okay, okay, okay, well I want that system. I look forward to you making all these things available in Brex for us to use. I hate doing my expenses so much. Um always hated that. It's pretty funny because I worked at *The New York Times* and *Bloomberg* for a long very many years and their systems were so archaic and when I did this startup and and started encountering things like Brex, I was like: oh my god, thank thank heavens that I no longer have to toil in all these things that destroy my soul.","offset":4438,"duration":34},{"text":"Pedro: No one likes doing expense reports. No.","offset":4472,"duration":1},{"text":"Host: No and I'm just you yeah and I'm just it's like self-defeating on that because I just don't do it then. Exactly. Well, thank you so much for coming in. Thanks for all the support. And um when we finish this, if you have a few minutes, I want to show you a cool video that you guys are in.","offset":4473,"duration":19},{"text":"Pedro: Let's do it. All right, Pedro. Thank you so much for coming. And um we will see you guys again soon.","offset":4492,"duration":6},{"text":"Host: Yeah, thanks for having me. Really appreciate it.","offset":4498,"duration":902},{"text":"Ashley: Close-up podcast is hosted by me, Ashley Vance, and or Kylie Robison, or both of us together. It is produced by me and David Nicholson. Our theme song is by James Mercer and John Sortland, and the show is edited always by the John Sortland.","offset":5400,"duration":21},{"text":"Ashley: Thank you so much to Brex and Eniac Ventures for all your support, and thank you most of all to everybody for listening or watching. We love you. Please leave us a like, a review, a subscribe, all those tremendous things. Thank you, and we'll see you again.","offset":5421,"duration":15}],"logs":[{"elapsed":"0.0","message":"Downloading audio from YouTube...","detail":null},{"elapsed":"0.0","message":"Trying download with browser cookies (ad-free)...","detail":null},{"elapsed":"47.4","message":"Audio downloaded (58.3 MB) in 47.4s","detail":"File size: 58.3 MB"},{"elapsed":"47.4","message":"Video title: He's Running A $5bn Company With An AI CEO","detail":null},{"elapsed":"47.5","message":"Audio duration: 1:30:44 (90.7 min)","detail":null},{"elapsed":"47.5","message":"Very long audio (90.7 min) — will use chunked transcription with gemini-3-flash-preview","detail":null},{"elapsed":"47.5","message":"Skipping full-file attempt — using chunked transcription for 90.7 min audio","detail":null},{"elapsed":"48.3","message":"Split audio into 3 chunks for transcription","detail":null},{"elapsed":"48.3","message":"Transcribing chunk 1/3 (starts at 0:00)...","detail":null},{"elapsed":"48.3","message":"Uploading audio to Gemini File API...","detail":null},{"elapsed":"52.5","message":"Audio uploaded in 4.2s","detail":"File ref: files/i1zkcejm7p1m"},{"elapsed":"52.5","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"123.3","message":"Chunk 1: 187 segments, last timestamp 44:54","detail":null},{"elapsed":"123.3","message":"Transcribing chunk 2/3 (starts at 45:00)...","detail":null},{"elapsed":"123.3","message":"Uploading audio (offset 45:00) to Gemini File API...","detail":null},{"elapsed":"127.6","message":"Audio uploaded in 4.3s","detail":"File ref: files/iix57embd0kv"},{"elapsed":"127.6","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"199.3","message":"Chunk 2: 152 segments, last timestamp 1:14:58","detail":null},{"elapsed":"199.3","message":"Transcribing chunk 3/3 (starts at 1:30:00)...","detail":null},{"elapsed":"199.3","message":"Uploading audio (offset 1:30:00) to Gemini File API...","detail":null},{"elapsed":"200.3","message":"Audio uploaded in 1.0s","detail":"File ref: files/3gwfzt0v3oz7"},{"elapsed":"200.3","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"221.0","message":"Chunk 3: 2 segments, last timestamp 1:30:21","detail":null},{"elapsed":"221.0","message":"Chunked transcription complete: 341 total segments","detail":null},{"elapsed":"221.0","message":"Total cost: 136,906 in / 25,528 out — cost: $0.1450","detail":null},{"elapsed":"221.0","message":"Total transcription time: 173.5s — 341 segments","detail":null},{"elapsed":"221.0","message":"Analyzing topics across 341 segments with gemini-3.1-pro-preview...","detail":null},{"elapsed":"282.8","message":"Topic analysis complete in 61.8s — found 22 topics","detail":null},{"elapsed":"282.8","message":"Analysis tokens: 27,258 in / 1,873 out / 6,970 thinking — cost: $0.1606","detail":null},{"elapsed":"282.8","message":"Pipeline finished in 282.8s — total cost: $0.3057 (198,535 tokens)","detail":null}]} \ No newline at end of file diff --git a/history/1775221783211-YTVSwOY19Qs.json b/history/1775221783211-YTVSwOY19Qs.json new file mode 100644 index 0000000..f8be60f --- /dev/null +++ b/history/1775221783211-YTVSwOY19Qs.json @@ -0,0 +1 @@ +{"id":"1775221783211-YTVSwOY19Qs","videoId":"YTVSwOY19Qs","url":"https://www.youtube.com/watch?v=YTVSwOY19Qs","title":"Jack Dorsey: Every Company Can Now Be a Mini-AGI","type":"youtube","topicCount":16,"segmentCount":158,"createdAt":"2026-04-03T13:09:43.211Z","uploadDate":"20260402","chunks":[{"title":"Podcast Introduction","summary":"Brian Halligan introduces Jack Dorsey and Roelof Botha. He outlines the podcast's focus on rethinking corporate hierarchy, AI integration, and CEO advice.","entries":[{"text":"Jack Dorsey: Since last year, I've just had this existential dread and also, like, hope and optimism in the same hour, in the same thought process, of like, what is even a company going forward? Like, what are these structures going forward? And this is the only, like, durable structure that I could actually imagine lasting for quite some time. And it was coming from a place of like, wow, is our company just going to be completely irrelevant, you know, in the next coming years?","offset":0,"duration":30},{"text":"Brian Halligan: All right, everybody, we had Jack Dorsey on the pod today, founder of Twitter and founder of Block. He's the only founder to have two of his companies end up on the S&P 500. I just learned that today, that's pretty cool. Also, Roelof Botha, who's a Sequoia partner and is on Jack's board at Block.","offset":30,"duration":30},{"text":"Brian Halligan: The conversation was super interesting to me. He recently put an article out that you may have seen, called \"From Hierarchy to Intelligence,\" and it's a manifesto on how to rethink, basically rethink from the first principles how an organization works. How do you completely eliminate hierarchy and how do you put AI right in the center and transform how your company works? And I let him go on that and he was very thoughtful and he spoke a lot about it. Block is really changing the way it's organized.","offset":60,"duration":30},{"text":"Brian Halligan: Before we started, he said, \"I'd love to get some feedback from you and from other people on this.\" So if you've got comments on it, let it rip. He wants some feedback on it. He's in the early innings of a big transformation over there. That was about half of it. The second half of it I just asked him for, like, CEO advice. I work with lots of CEOs, as you folks know. Like, how do you build an amazing board? He's certainly got some scars around board building.","offset":90,"duration":30},{"text":"Brian Halligan: How do you build your second act, like the Cash App versus the original business of Square? Is it a good idea to be a CEO of two different companies at the same time? Being brave and not giving a flock versus going with the flow, and when do you really dig in and when do you kind of go with the flow? And he had some really interesting thoughts on the job of a modern CEO. So tune in, I'll be back at the end and give you some further thoughts.","offset":120,"duration":30}],"startTime":0},{"title":"Replacing Traditional Hierarchy","summary":"Jack discusses the original purpose of hierarchy as an information flow mechanism. He suggests replacing management structures with an AI world model that makes the company's information legible to everyone.","entries":[{"text":"Brian Halligan: But I thought Jack did a really nice job and Roelof did too. Let's get into it. Jack, I read your piece, I think it's fantastic, \"From Hierarchy to Intelligence.\" Before we get into the meat of what it is, can you describe what you think is wrong with the way normal companies' hierarchies work, companies like HubSpot, companies like Block, like what kind of led you to this?","offset":150,"duration":27},{"text":"Jack Dorsey: I don't know if there's one thing that's ultimately wrong. It's just recognizing that like what do we see in the pattern, what is the function of the hierarchy? And what we wanted to explore is just like where does it actually come from and why does it exist in the first place? And if you look at it from first principles, it's all about information flow to a broad base of people.","offset":177,"duration":33},{"text":"Jack Dorsey: So being able to communicate over a breadth of people and have that be manageable at a human scale. So we've gotten into structures that, you know, we've borrowed and iterated on a little bit over 2,000 years. And now we're faced with this, I think, a completely foundational moment in being able to question every element of how we work. And the one that I think is questioned the least is probably the hierarchy and probably about how we manage communication flow around the company.","offset":210,"duration":30},{"text":"Jack Dorsey: So if we're in a world, where we are today, where Block for instance is completely remote, we're remote-first, every single thing that we do creates some sort of artifact. Whether it be a Slack message, an email, a pull request, code, you know, all these Google Document, a meeting that we record, all these things have these artifacts of information about how the company is working, is building, is failing, is making mistakes, all these things.","offset":240,"duration":40},{"text":"Jack Dorsey: And traditionally we've been reliant upon humans in a management structure in a hierarchy to go up and down a chain to relay that information. Instead, we can take all of those artifacts and put an intelligence on top of it, build a model around it, and actually have a conversation with the company about how the company is doing. And it's not just me as CEO that can do that, but anyone in the company could have that same sort of access to information and same understanding of like what the company can do.","offset":280,"duration":40},{"text":"Jack Dorsey: So you get to a point where you can build these world models for a company, like treat the company as a mini-AGI, for instance, an artificial general intelligence, because it really is. I mean, if you look at a company, it is an intelligence, but it hasn't been structured in a way that's the most efficient or the least lossy in terms of information flow and what people can actually do within the company.","offset":320,"duration":30},{"text":"Jack Dorsey: So the technology is good enough today that we can actually model the company. We can have everyone in the company put in intent, which would be strategy or these artifacts, and we can also have everyone in the company query it as well. And it just really opens the door for what's possible, like Roelof and I have a board meeting every quarter where we construct a bunch of board docs, slides, presentations. We get only so much time for them to have questions.","offset":350,"duration":30},{"text":"Jack Dorsey: But imagine if every single board member can just query the company and have a conversation with the company's intelligence in real time, and we can make that meeting time that we have every quarter really focused on more of the creative or bigger existential decisions and issues than the day-to-day. The same can be said for like our earnings call and analysts, like giving them like fully Reg-FD possible information that is on their timeline with their questioning.","offset":380,"duration":30},{"text":"Jack Dorsey: But you can scale this to any position or any role in the company, which is pretty phenomenal and like we've just never had that ability before. And now we do. And, you know, I think the architecture and the structure of the company is ultimately going to determine its velocity and how well it's roadmapped for customers, correct?","offset":410,"duration":22}],"startTime":150},{"title":"Block's Three-Role Structure","summary":"Jack explains Block's transition to a flatter organization. He details their goal of reducing management layers and standardizing into three roles: individual contributors, directly responsible individuals, and player-coaches.","entries":[{"text":"Brian Halligan: Mm, just kind of drilling down on it, can you describe sort of what the organization looked like before? And granted you're very early in this, but what's it look like now? Which roles have been eliminated? What are the new roles? Just kind of drill down a little bit into what Block looks like today and kind of where it's going.","offset":432,"duration":23},{"text":"Jack Dorsey: Yeah, we are early in it. I mean, just from a, you know, one measurement of how far along we are would be the depth from me to any other individual in the company, and I would say our max depth right now is probably five folks between me and anyone in the company. I would want to get that down to two to three this year.","offset":455,"duration":25},{"text":"Jack Dorsey: And in the most ideal case, you know, there is no layer, everyone in the company reports to me, and that would be, you know, all 6,000 of the company. And that feels somewhat, you know, ridiculous when you consider the old structure. But when you consider that the majority of our work is going through this intelligence layer, it's a lot more manageable.","offset":480,"duration":24},{"text":"Jack Dorsey: And that goes into the roles going forward. We want to normalize down to just three roles. The first is an IC, which is a builder or an operator. This is a salesperson, it's an engineer, it's a designer, product person, you know, whatever it is, they're actually working with the tools to build or to operate the company. They're augmented because they have access to agents, so you know, one person can, you know, potentially do the work or explore the breath that, you know, it would take a team or 10 people to do in the past.","offset":504,"duration":38},{"text":"Jack Dorsey: So that's number one, and I think there's a durable human skill that lasts there, which is judgment and taste and creativity. So that's probably the largest part of the population is the builder and the operators, the ICs. The second role is the DRI, and that's someone who can own the customer outcomes. They're putting a strategy together, they're understanding what roadmap allows us to solve customer needs and problems, and they're assembling a team of these ICs to get something done.","offset":542,"duration":38},{"text":"Jack Dorsey: But the durable human skill there is ownership and accountability. You know, they're really owning the outcomes and whether something is failing or not. And then the last role would be what we consider managers today, which we're calling a player-coach. This is someone who is building the capability and the capacity of other humans and their craft.","offset":580,"duration":25},{"text":"Jack Dorsey: But instead of telling them how to do it, they're showing them how to do it by doing the work. So these are people who might be ICs or they might be DRIs, but they're also really good at giving coaching skills, a coaching skill to help the people around them get better and better and master their craft. And today that's a management structure where ICs and even DRIs report to a player-coach.","offset":605,"duration":30},{"text":"Jack Dorsey: But I think in the future it's an assignment. It's not a reporting structure, but I'm assigned to ICs or I'm assigned to DRIs to help them master their craft. And obviously the durable human skill there is building human capacity and coaching. And there's a lot of empathy there and, you know, all the soft skills that we recognize great managers are known for.","offset":635,"duration":30},{"text":"Jack Dorsey: But not making it a requirement that they have to be strategic necessarily. They have to build, because they need to show off the skill and teach in that way, but they don't necessarily need to be a DRI. Now, I think in very rare cases one person can take on all three of those roles. I think I can take on all three of those roles. My leadership team is expected to take on all three of those roles. They're expected to build as an IC or operate the company, they're expected to be strategic and actually think about roadmaps and customer outcomes, and they're expected to coach and help raise the skill level around them with the people that they work with or with their direct team.","offset":665,"duration":36}],"startTime":432},{"title":"The Evolving Role of the CEO","summary":"Jack describes how the CEO's job shifts from traditional management to architectural alignment. He explains how customer interactions will proactively define the company's roadmap based on its core capabilities.","entries":[{"text":"Brian Halligan: Just a little kind of before and after, and you're mid on this, let's pretend like it's working great and it's years from now and it's extremely flat. Like what does the role of the CEO before and after? How's that changed? Most of the listeners, by the way, are CEOs. What does, like, planning look like before and after? What happens to all those people who are directors and managers or the glue people? Like what are sort of the before and afters in your mind?","offset":701,"duration":30},{"text":"Jack Dorsey: I think my job as CEO in the past I've thought about in three ways. Number one is to ensure that we have the right principles and the right team dynamic. And that's like hiring and firing and setting values and setting the culture and setting the tone. The second is to ensure that decisions are being made in context of our customers and industry trends and competition. And the third would be to raise the bar on our execution, like to constantly increase our capability and to push ourselves into doing things that are uncomfortable so that we're growing all the time.","offset":731,"duration":34},{"text":"Jack Dorsey: So that's how I thought about my job up until this point. I think in the future you have those elements certainly, but I think it's more about like the architecture of how the company as an intelligence works. And if we're building the company as an intelligence, our job as humans and my job as CEO is to constantly align it to where we think the right outcome is.","offset":765,"duration":28},{"text":"Jack Dorsey: And I see, like, visually I see the intelligence, the world model for the company in the center, and then on the edge are the humans who are just constantly aligning this towards customer outcomes. But even that changes, I believe, because I think a company's ultimate limiting factor is its own roadmap.","offset":793,"duration":27},{"text":"Jack Dorsey: And I think what these technologies point to are that our customers are going to, they're going to have the expectation that they can ask for a feature that doesn't exist on our roadmap and that it just is served to them. And that's where like you really get into the layers of like, okay, so what do we actually build? We build up capabilities, which are effectively our tools.","offset":820,"duration":22},{"text":"Jack Dorsey: Like we can issue cards, we card acceptance, peer-to-peer, lending, all these things we do as a financial technology company. We have these interfaces like Square, which has a register and a dashboard. We have Cash App, we have TIDAL, we have Bitkey, we have Proto, these are interfaces, these actually touch the real world, touch humans, and we can deliver our capabilities in these interfaces.","offset":842,"duration":24},{"text":"Jack Dorsey: Today they're built with like these very specific navigations that are our roadmap and our understanding of what our customers want. When you move to the third layer, you have proactive intelligence. We have all this understanding of our customers, we're moving money, money is the most honest signal in the world. You can lie about literally everything, but when a transaction occurs like that's something that really tells the truth about your life or your business's life.","offset":866,"duration":22},{"text":"Jack Dorsey: And based on that, we can actually prompt our customers instead of waiting for them to prompt us or having the right question to ask. So we can do the very simple but very valuable thing of like how do we protect our customer's cash flow? Like we have people using us as a bank account. How do we make sure that they can pay their rent and they can pay their Spotify bill and they can pay their kid's allowance?","offset":888,"duration":27},{"text":"Jack Dorsey: And this is all sequenced in a way that allows them to never go to zero, never go negative, and have some cushion that allows them to even think about getting to saving or building wealth. And that's just, you know, peace of mind I think is the most critical aspect here. So if we're enabling a customer, if we're able to prompt a customer, and also they can ask like as a business, \"Hey, I have this inventory thing that I've been using, but it's missing this feature, can I have this feature?\" We should just be able to build that and compose it in real time based on our capabilities.","offset":915,"duration":37},{"text":"Jack Dorsey: If we can't and it points to a deficiency in capabilities or a gap, that's our roadmap. So our customers just by using and talking with our systems are telling us what our roadmap should be, and then it's up to us to give the judgment. And then the final layer is the world model, it's the customer world model, it's the company world model, our deep understanding of ourselves and also our customers.","offset":952,"duration":23},{"text":"Jack Dorsey: But I think like if I had to say one thing that myself or anyone in the company has to do, it's I guess it's this overused phrase of judgment. But it is judgment against like what we intend to build in the world and is it on, is it aligned with that judgment, is it aligned with the values, is it aligned with the taste that we have and is it unique or is it not?","offset":975,"duration":29},{"text":"Jack Dorsey: And I guess for my part I'm the extra checkpoint on like is the alignment circle of humans, that edge of humans actually working correctly.","offset":1004,"duration":9}],"startTime":701},{"title":"Rebuilding Around Ground Truth","summary":"Jack and Roelof discuss whether this AI-centric model applies to all businesses. They argue that organizations built around ground truth and transparent signals will outperform command-and-control structures.","entries":[{"text":"Brian Halligan: And I see how this works exceptionally well for Block, you have a lot of signal. How does this work for, I don't know, Sierra, Workday, somebody who doesn't have the quality signal, the frequency of signal? Does it apply or doesn't work as well?","offset":1013,"duration":8},{"text":"Jack Dorsey: I think it probably does. I think it goes down to like are you building a business that like understands something of human nature deeply and it gets deeper every single time? And that's a real tangible signal that just doesn't go away. And if you are, then I think you can build your company as an intelligence. If you're not, then it's probably a an add-on to something else.","offset":1021,"duration":33},{"text":"Jack Dorsey: And I think most of the industry is thinking about AI as like a copilot, as something that is augmented onto rather than like how do you just rebuild this our whole company with this as the core. Like and if it doesn't make sense for your business to do that and you end up being or looking very similar or rhyming too closely with the frontier labs, then I think it's going to be very, very challenging to differentiate and survive.","offset":1054,"duration":28},{"text":"Jack Dorsey: And that's kind of what's been leading me to all this is like I just, you know, since January of 2024 which is when these tools really came to bear, like Goose which is an agent coding harness was one month before Claude Code in January of 2024. And Claude Code came out that following month and then like was really put into out of beta in May of that year.","offset":1082,"duration":29},{"text":"Jack Dorsey: And, you know, that whole year I just spent every single day for 3 hours every morning just pushing myself, like can I get it to do something that I didn't think it was capable of or I didn't think I was capable of? And every single day it worked. Like every single day I was surprised. And it's, you know, I'm sorry, it wasn't 2024, it's 2025.","offset":1111,"duration":23},{"text":"Jack Dorsey: It's only been a year of those tools, like one year, it's just the compounding nature of this is pretty incredible. So being able to like see that, understand it, and then shift your company to be ahead of it I think is absolutely critical right now. And I don't think people are feeling it enough. They're just living in this abstraction of like oh yeah, like these tools will make everyone in our company 10x more productive. I don't think this is a productivity thing. I think it's a structural thing that needs to shift.","offset":1134,"duration":36},{"text":"Brian Halligan: I think you're right. I think if people are thinking of it as copilots and individual productivity versus your, I think your idea is complete business transformation and I think it's super interesting and compelling.","offset":1170,"duration":10},{"text":"Roelof Botha: Can I add one thought I've had as I've listened to this so far. In one of the one of my favorite pieces of writing ever is Adam Smith, \"Wealth of Nations,\" and this idea that if you have the right signals you can rely on the self-interested behavior of many small participants in the system to actually lead to optimal outcomes, but you just need to have the right framework and the right system.","offset":1180,"duration":17},{"text":"Roelof Botha: I think the way that many companies work today is a little bit more command and control. Very much so. And you have hierarchies and you have political actions and people, you know, are jockeying for position and it's it's not always clear what is actually true. And I think part of what we're envisioning here is you have a system that's just ground truth.","offset":1197,"duration":21},{"text":"Roelof Botha: And you do away with all the layers, you get back to the kind of productivity that founders often long for. They long for the days when they were 100 people and not 500 people because they were so much more productive. Why? Because you had, you know, lots of transparency, limited hierarchy. And so I think the possibility here as Jack was saying is instead of just focusing on individual productivity you reimagine how we work together as humans.","offset":1218,"duration":31},{"text":"Roelof Botha: And you can do it with far smaller number of people that are far more productive, yes, but there's a different way of working together where you get the right signals and it's it's much more similar to a capitalist system where the signals tell you what to build. It's not somebody who pounds the table harder who gets their product approved, it's just listen, more customers want this than that, that's how we're going to decide what to build next. For me there's something quite magical in that realization.","offset":1249,"duration":25},{"text":"Brian Halligan: Yeah. About four years into building HubSpot I eliminated no org charts, no titles, and everyone lost their mind. They didn't like the idea. And we ran that for about nine months and I got worn down and I brought it back. The thing we didn't have was an intelligent system that had all those signals that could help us make decisions. So it's exciting to see this here.","offset":1274,"duration":21}],"startTime":1013},{"title":"Dorsey Mode and Decision Making","summary":"Brian pitches the idea of \"Dorsey Mode\" where AI makes decisions. Jack clarifies that AI simply facilitates context-rich choices, while customer behaviors and human judgment actually drive the company's direction.","entries":[{"text":"Brian Halligan: I have a theory I want to run by you Roelof, like I sort of think of like there's Manager Mode, it's a pyramid, the VPs make most of the decisions. And there's Founder Mode, kind of flat, the founder makes a lot of the decisions. And then there's, I'm just going to call it Dorsey Mode, it's a circle and the AI makes most of the decisions. Do you buy that?","offset":1295,"duration":26},{"text":"Roelof Botha: Oh, I don't think the AI makes most of the decisions. I think and Jack should correct me here, I think the AI helps with communicating the alignment and the management team or the inner core helps set the framework. What is the objective function? Are we optimizing for growth rate, gross profit per employee, net promoter score, probably some combination of those variables?","offset":1321,"duration":23},{"text":"Roelof Botha: And the humans at the edges perform an incredibly valuable function of correcting and informing and sort of steering that. And I think one of the phrases that Jack has which I absolutely love and I've stolen so many times is companies have multiple founding moments. There's so many smart people in your company that have clever ideas that every day inflect the product, introduce something new.","offset":1344,"duration":26},{"text":"Roelof Botha: And so this idea that there's just, you know, one person who is the brilliant person who comes up with everything, I just don't think, you know, I don't believe in hero worship or the converse of that where you sort of scapegoat people. I think it's harnessing the best of of your team to really advance the company. So I subscribe to the circle idea.","offset":1370,"duration":11},{"text":"Jack Dorsey: Yeah, I also don't think the AI is making the majority of the decisions. I think it's facilitating a more context-rich decision. I think ultimately, like in the most ideal case, our customers are actually making the majority of the decisions because they're just based on their queries and what they're trying to do with the system delineates like where our roadmap should go.","offset":1381,"duration":24},{"text":"Jack Dorsey: And then it's up to our judgment as to whether that's consistent with what we want to be and what we think is most strategic or not. But we just, you know, we weren't able to get to that level of data fidelity before because we had to infer it. We had to do customer research, we had to do interviews, we had to do look at our customer support, product feedback on Twitter, all these other things.","offset":1405,"duration":29},{"text":"Jack Dorsey: But when your interface is a conversation with your customer instead of like this visual navigation, you suddenly get like this amazing fidelity of like what do our customers actually care about, what do they actually want? And it's up to us then to decide if that's consistent with what we want to be as a company or if they should be going elsewhere to to do that.","offset":1434,"duration":25},{"text":"Jack Dorsey: And I think all these things are going to blur. That, I mean, that's the craziest thing is like, you know, again since since last year I've just had this existential dread and also like hope and optimism in the same hour, in the same thought process of like what is even a company going forward? Like what are these structures going forward? And this is the only like durable one structure that I could actually imagine lasting for quite some time.","offset":1459,"duration":29},{"text":"Jack Dorsey: And it was coming from a place of like wow, is our company just going to be completely irrelevant in the next coming years or even even sooner? Like what do we what do we actually differentiate on? What do we have a moat around and what do we need to be to defend and and also to grow that? And like what are the and all that follows from customer expectation?","offset":1488,"duration":27},{"text":"Jack Dorsey: Like the most amazing thing about open-Claude to me was that people wanted to take this thing and contain it into a Mac Mini and make it very tangibly theirs and have all this agency around what they did with it. And we're seeing Square sellers do stuff with it like that in interface with the Square APIs, and we're seeing Cash App customers, and these are not tech people, these are just like people, \"I want I want a bot to help me manage my life.\"","offset":1515,"duration":-1166},{"text":"Jack Dorsey: That agency, independent of your thoughts on like how good of a system open-Claude is right now, it'll get better and better, but the intent behind that is agency. I want to tangibly control this intelligence and for it to better me and what it makes possible for me is incredible. And that expectation floor has just risen dramatically.","offset":349,"duration":1226},{"text":"Jack Dorsey: And that leads me again to like yeah, our limiting factor as a company is our roadmap. Like we need to remove that from the equation. We need to ensure that our customers are truly building alongside us and that they, you know, are seeing us as a series of capabilities that makes their desires fast and easy and and valuable.","offset":1575,"duration":25},{"text":"Jack Dorsey: So like it really goes back to the capability set that we have and then the intuition of the interface that we have and then like how intelligent our world models can can be to be helpful and to compose UI in real time.","offset":1600,"duration":15}],"startTime":1295},{"title":"Applying the Intelligence Model","summary":"Jack advises startups to structure their companies as an intelligence from day one. He emphasizes the importance of making workflows entirely legible and eliminating unnecessary titles to maintain focus.","entries":[{"text":"Brian Halligan: I spent this morning at a company called Rogo here in New York City. They read your article. Let's say you're advising the CEO of 100-person company. They've already got their hierarchy. What should they do? Should they start with their system? Should they start with data? Should they start with org? Like how should people go about, you know, running the Dorsey playbook?","offset":1615,"duration":23},{"text":"Roelof Botha: Uh, we don't have it all figured out. I think there's an important dose of humility that we have that we're endeavoring on this path. We believe it's right, but we we know there's a lot to figure out.","offset":1638,"duration":12},{"text":"Jack Dorsey: Yeah, it's more like if if you were at 100 people or even, you know, just starting today, if you were to build your company as an AGI, as an intelligence, what would it look like? And what would you need to really differentiate? Like if I were starting a company today, I would be so excited about how quickly I could build things and how quickly I could prototype and get things out to customers.","offset":1650,"duration":23},{"text":"Jack Dorsey: I would be in this like valley of dread about distribution and attention because there is so much noise out there and it's so hard to get to the actual signal of like who's building something interesting that will actually fundamentally change something and will be around for more than a year. It just like I think distribution really becomes a differentiator.","offset":1673,"duration":27},{"text":"Jack Dorsey: And I think there's some event horizon where the way we think about distribution today closes off. You know, it like there's there's apps, for instance, and websites and like the traditional retail. There's a number of things that will change and if you don't have the distribution today, it's going to be very hard to fight for that.","offset":1700,"duration":24},{"text":"Jack Dorsey: But there'll be new areas of distribution that are probably more important, and I don't know what those look like. But I would say like I would assume that a company of 100 probably is no more than two to three layers deep, hopefully. And now would be the time to just like really question, like do I do I need a hierarchy?","offset":1724,"duration":21},{"text":"Jack Dorsey: Brian, a year into Square, I also removed titles, we normalized everyone to lead. We did it for like we were talking with all these banks all the time and you would have these EVPs and VPs and they were looking for the same on the business card and there's this whole business card culture. So we ripped up all the business cards, we normalized down to a title of like you're lead of what, and the longer that is behind lead is probably the farther down you are in the organization.","offset":1745,"duration":29},{"text":"Jack Dorsey: And we've kept it, like we we you know we don't have titles. We have like, you know, what do you lead, going back to like the DRI thing, what are you ultimately responsible for? And I think it's helped us a lot. But this is another step. Like if if you're starting today or you're 100 today, like what what is actually fundamental to solving your customer's problems and and where is the hierarchy getting in the way of that?","offset":1774,"duration":26},{"text":"Jack Dorsey: And look at all the tools you're using. Like look at all the information you're generating just by doing your work. Like just putting that into an intelligence and being able to query it will give you an understanding of the company that like is two to three times more than you had before, ever. Because you're relying upon people telling you things.","offset":1800,"duration":20},{"text":"Jack Dorsey: And, you know, that doesn't always happen for various reasons that, you know, Roelof spoke to in terms of agenda or politics or emotions or empathy, all all these things. Imagine if your company was entirely legible. Like entirely legible every aspect of it. And we're not far off from that from a data perspective. It's putting the intelligence on top of it and making it useful and then making it proactive.","offset":1820,"duration":28},{"text":"Jack Dorsey: Like that's that's the hardest bet is like we can determine causal, getting to predictability for these world models around the company and customers is still right now very much a research bet. But like it's imminently solvable.","offset":1848,"duration":17}],"startTime":1615},{"title":"Logic Behind Block's Restructuring","summary":"Jack and Roelof share the behind-the-scenes process of Block's 40% reduction in force. They explain how rapid advancements in AI coding tools prompted them to proactively redesign the company's scale.","entries":[{"text":"Brian Halligan: Mm. Can you guys just take me behind the scenes, like Jack this was a really bold move, you laid off 40% of your employees. Just like for CEOs listening, what was that debate inside, like how big should it be, how bold should it be? You know, Ruth Porat's got this good line, if you're going to eat a shit sandwich, don't nibble. And you seem like you took a big bite. What was that debate behind the scenes and then Roelof, like how did he pitch it to you guys and what was the board's reaction? Just like behind the scenes on that.","offset":1865,"duration":35},{"text":"Jack Dorsey: Yeah. So December of last year is when the model is really got a noticeable upgrade from being able to be really good at building prototypes and greenfield efforts to like understanding like large codebases and legacy codebases like our own. There was, you know, hallucination wasn't much of a topic in terms of like the coding ability and the tool harnesses became suddenly very mature. Like just in that month.","offset":1900,"duration":35},{"text":"Jack Dorsey: And it just like everyone went home for the holidays and everyone played with these tools and they were surprised at how capable they were and what they could do with them. And you know, we came back and the conversation was like just going around the table, \"Would you build the company this way if you had these tools today? Like what would the company look like?\"","offset":1935,"duration":23},{"text":"Jack Dorsey: And everyone around the table and my team just said like it would not look like this. It would not be this size. It would not be structured this way. And we've been making like changes on the on the edge, like, you know, going from a GM structure to a functional structure to reduce, like putting a a cap on our layers to four, me plus four, and all these like small things.","offset":1958,"duration":26},{"text":"Jack Dorsey: But if we were to really reboot and rebuild the company, like would we end up where we where we look today? And the answer was uniformly no. And then we just did this exercise of like okay, so what is the minimum number of people that we would need to keep the service up 100%? And then next, what is the minimum number of people that we would need to fully be in compliance with our regulators? We're a highly regulated business, so that one's extremely important to us, and legal obviously.","offset":1984,"duration":34},{"text":"Jack Dorsey: And then third, what is the minimum set of folks that we need in order to grow, to fulfill our commitments we've made to the street, but also rebuild the company as an intelligence. And that's roughly the number that we got to and we built in some buffer in case we made mistakes, which we did. And you know, hard hard not to, especially operating the way we have.","offset":2018,"duration":25},{"text":"Jack Dorsey: Like I think going forward it'll be much easier because more of the company will be legible and all of our actions will be a lot more legible. So I'd have a lot more confidence going forward than not. But it was that and and there was a span of exploration to execution and, you know, under under three weeks.","offset":2043,"duration":22},{"text":"Jack Dorsey: And I think generally I wanted to make sure that we if we knew that this was what our company was going to be in the future, I didn't want to have to do it with our backs against the wall. We're a public company and there's various challenges there, and other companies will will probably get to this realization at some point.","offset":2065,"duration":24},{"text":"Jack Dorsey: I don't want to react to that. I want to I want to be ahead of it, because then we can do it with a lot more integrity, we can do it with a lot more generosity for the people that we're asking to part, to leave, and even for the people that we're asking to stay and we're not just reacting into something mediocre, we're acting towards excellence. And like that's just the tone that we wanted to set.","offset":2089,"duration":28},{"text":"Jack Dorsey: So, you know, every day was just like constantly checking like are we doing the right thing, is this the right set of folks, like what are we not thinking about, what are we not talking about? And we you know we kept the the group very, very tight and had a conversation with with a board, which was a my perspective very open to it and actually more than open, more like, \"Yes, we agree, like we should we should do this.\" But I'll let Roelof speak to that.","offset":2117,"duration":37},{"text":"Roelof Botha: It was a very quick process. I think part of what helps is that Jack had written us a very detailed note laying out the logic. It's principled. It's not reactive as Jack was saying, it's not reactionary, it's very well laid out, very logical.","offset":2154,"duration":17},{"text":"Roelof Botha: It was clear that the company and the management team was interested in a conversation about how to make this work, as opposed to being dogmatic and saying they have it all figured out. So even in the course of those three weeks, elements of this evolved, and it evolved in light of feedback from management team members and board members. You know, some of some of where we started in the first of those three weeks is different from where we ultimately landed by the time the announcement took place.","offset":2171,"duration":27},{"text":"Roelof Botha: And I also think it's just an example of where we've built enormous trust between the board and the management team. You know, we've been through a lot as a team, and so we have a lot of shorthand to be able to make crucial decisions like this. We gathered several times in quick succession to make sure we drilled in on the key issues, and the board was fully supportive.","offset":2198,"duration":20}],"startTime":1865},{"title":"How to Build an Effective Board","summary":"Jack and Roelof share advice on selecting board members. They recommend treating early investors as hires you can't fire and adding independent directors who will elevate execution and handle crises.","entries":[{"text":"Brian Halligan: You two, Roelof you've been on a lot of boards, Jack you've had your ups and downs with different boards. Any advice for these CEOs listening that should they start at 100 employees, should they start bringing in independents, should they like how do you build an amazing board that really serves the company well, the employees well, the investors well, the customers well? Like what's your advice on that?","offset":2218,"duration":21},{"text":"Jack Dorsey: I mean early on I always told myself and my team that like your your first board is your investors, right? And I would treat that relationship as a hire you can never fire, and in fact they can fire you, and I've been on the other side of that. So it really puts pressure on finding the right person that you'd actually want to work with at the company knowing that you could never fire them.","offset":2239,"duration":31},{"text":"Jack Dorsey: And again, they can fire you. And for me, it was around, you know, I think a lot of young founders kind of go for the brand names, especially around VCs, but I always wanted to go for the for the person, and you know that's why Roelof, you know, we we we were optimizing for him to be on our board and be an investor.","offset":2270,"duration":23},{"text":"Jack Dorsey: But like it was the fact that like he would up-level our conversation, up-level our execution more than anything else and challenge us along the way. So even as you think about adding independent board members, like the core function of a board is to ensure that the company has the right CEO. Like that's their one job. They have all these committee responsibilities and but the ultimate fiduciary duty is like do we have the right CEO going forward?","offset":2293,"duration":33},{"text":"Jack Dorsey: And I think you have to build a board that has different perspective on that and that is open to wild ideas, things that are going to just seem like crazy in the moment, which like this one might might be. But it can be rationalized if we talk through it and we like really document it and paint a picture of like where this could go and like what the opportunity cost is if we don't do something.","offset":2326,"duration":27},{"text":"Jack Dorsey: Because if we didn't do something like this, I just imagine like every year it's a 10% RIF or 20% RIF or whatever it is, and like that is just the most demoralizing, like crappy, like non-creative building of a company ever and it's all, you know, with your backs against a wall and like it just feels like losing constantly.","offset":2353,"duration":18},{"text":"Jack Dorsey: And I, you know, had a conversation with a board about I don't want that. Like that's not I don't want to be at a company like that. Like it's just it doesn't make sense, it's soul-crushing, you know, and it's just not not inspiring and I don't feel good about it. So here's here's what I do feel good about and like let's let's go, let's let's challenge it.","offset":2371,"duration":17},{"text":"Roelof Botha: Well I think the first financing when you get an investor, if you're getting an investor board member, you should treat it as a recruiting decision, not a financing decision, because it'll have a much bigger bearing on the ultimate outcome of your company.","offset":2388,"duration":23},{"text":"Roelof Botha: And then I'm generally a fan of getting a very good independent board member within a year or two, certainly by the time you get product-market fit. And I think there's a different relationship that the founder has with the investor board member by virtue of what Jack, you know, described that sometimes, you know, that person may come to the conclusion that the founder's no longer the right person to run the company, maybe rightly, maybe wrongly.","offset":2411,"duration":24},{"text":"Roelof Botha: If you can get an independent board member, there's a different relationship that the founder has with that board member. And especially if that person has previous experience, it can be a fantastic mentor relationship to help the founder on that journey depending obviously on their level of experience.","offset":2435,"duration":18},{"text":"Roelof Botha: I think boards are often built too late in a rush, especially in the run up up to an IPO where people suddenly realize, \"Ooh, I've got a four-person board and I need nine,\" whatever the case is, and then you suddenly assemble people who have no context, they have no history, and they have no chemistry, because you will be tested.","offset":2453,"duration":19},{"text":"Roelof Botha: You're going to have a situation where there's a short-seller report or you're dealing with a hostile, you know, situation with activist investor or a tricky financing, you know, that really tests the mettle of the team, and you want to understand the dynamic between the board members and just their willingness to go along and their alignment with the core values of the business. And so I just think it's one of those things that requires a lot more care than I think most people apply to it.","offset":2472,"duration":21}],"startTime":2218},{"title":"CEO Mistakes and Over-Delegation","summary":"Jack reflects on his biggest career mistakes, noting that leading two public companies is an anti-goal. He regrets over-delegating within Block and creating misaligned cultures instead of a unified ecosystem.","entries":[{"text":"Brian Halligan: Jack, you've started a couple great companies here, you're a startup founder, scale-up CEO. Roelof, he was the only person to have founded two companies that made it into the S&P 500. That's amazing. And the only person to have been simultaneously CEO of two public companies, for the record.","offset":2493,"duration":23},{"text":"Jack Dorsey: Which should not be should not be a goal for anyone, by the way.","offset":2516,"duration":2},{"text":"Brian Halligan: Let me ask him, he's CEO of two companies. Is it ever a good idea?","offset":2518,"duration":3},{"text":"Jack Dorsey: Not public companies. Private maybe. Private I would I think there's probably going to be more of a trend where people are leading multiple companies that are private, but public companies like I should definitely like an anti-goal, it's an anti-pattern.","offset":2521,"duration":15},{"text":"Brian Halligan: What can founder-CEOs learn from like, what did you do right, what did you just get wrong? What advice do you have for that 100-person company CEO growing really fast? Like yeah, what do you got?","offset":2536,"duration":15},{"text":"Jack Dorsey: My only regrets in life and and also in our in our businesses, um, are where I decided not to learn something. Because I like I embrace all of our mistakes and all the bad decisions we made, but like if I'm not learning from that, actively learning from it, like that's that's what I regret.","offset":2551,"duration":29},{"text":"Jack Dorsey: And, you know, in in probably the worst case in any of these companies, just delegating way too much. Especially within Block because like I wanted to set a structure where we had multiple CEOs in this company, but I realized, \"Oh man, we're just building like a holding company now.\"","offset":2580,"duration":24},{"text":"Jack Dorsey: And like we got like you know the CEO over here for Square and CEO over here for Cash App and like the value of our company is not like these, you know, unrelated things that are growing at different clips, it's how do we bring them together and like really, you know, um, challenge the whole financial network entirely, because we have we have both sides of the counter.","offset":2604,"duration":22},{"text":"Jack Dorsey: So like why aren't we structured that way? And that I think led to just very differing cultures and values and execution levels and um, that was a mess. So I think the one thing that I probably consistently would have corrected would be just delegating too much. You know, too too much of that and I didn't learn that fast enough. Like that's that's the regret, is I didn't choose to to learn from that fast enough.","offset":2626,"duration":31},{"text":"Jack Dorsey: But when you have your whole your entire company is legible, it's a very different equation. Um, and I think my regrets going forward if I were to predict them would be like am I actually putting enough entropy into the system, like enough of the intent into the system to actually keep us relevant going forward?","offset":2657,"duration":29},{"text":"Jack Dorsey: And and that's hence the shift. Like I I can't imagine doing anything bigger than rebuilding our company as an intelligence um, or more correct um given where where everything is trending. So it just feels like I have to constantly build um and constantly learn from whatever we're putting out there in order for us to stay relevant going forward.","offset":2686,"duration":21}],"startTime":2493},{"title":"How AI Transformed Internal Meetings","summary":"Roelof and Jack discuss how internal meetings have drastically changed. Instead of presenting slide decks, teams now bring interactive, real-time prototypes to test ideas with near-zero cost of failure.","entries":[{"text":"Roelof Botha: So there's one anecdote that came up Jack last week which is how different meetings are today. They're obviously, maybe you can talk about how frequent meetings are taking place now and what's the color, what are the nature of the meetings today versus what they were a year ago?","offset":2707,"duration":14},{"text":"Jack Dorsey: Well I mean just two months ago, every meeting that we would have would come you mean you you you have this Brian, like you see a presentation or a Google Doc and we go through it. Now, everyone is bringing a prototype that they built, which is pretty amazing and like it's either simulated data or real data, but it's a cut on their work in a way that's far more um has far more depth and realism than we could ever get from a slide deck.","offset":2721,"duration":37},{"text":"Jack Dorsey: And because they can actually modify it in real time, like we can have a conversation around like what they're actually building in real time. Um, so like the the breath that we get to explore is suddenly incredible and that allows us to like really again it goes back to judgment, like which thread are we pulling on this now because we can see like everything in the horizontal. Where do we want to go like deep? And like what what is the right path?","offset":2758,"duration":33},{"text":"Jack Dorsey: And the cost of like being wrong on that path and going back up the tree and going down another path is getting closer and closer to zero because the tools can explore the path so quickly and then also we can go down them much much faster.","offset":2791,"duration":13},{"text":"Brian Halligan: I I completely agree with you, like a lot of times in HubSpot's history what worked was when we were doing a lot of different stuff and we were distracted, let's just get focused and then we made progress. I see the startups these days doing more things in parallel and just being more productive and getting more done, and I used to preach focus, I don't preach it as much as I do. Do you have a reaction to that?","offset":2804,"duration":20},{"text":"Jack Dorsey: Yeah it's uh I think it's I think it's having a wider perspective to start and then because in the past if we were to explore different paths like it would be a uh you know three it'd be a very costly exercise, especially within hardware for instance. Take you a long time to build that prototype.","offset":2824,"duration":22},{"text":"Jack Dorsey: But today we can do it in an hour. And then um so I do encourage more exploration, but I think focus on getting the details right when we do choose that path. And like it's the 80/20% thing, which is like you know these tools will build about 80% of what where we need to go and then that last 20% is going to be a function of like how good our creativity, how good our taste is, how good our judgment is and um and just constantly pushing these these models to to doing something that they weren't they weren't we didn't think they were capable of.","offset":2846,"duration":35},{"text":"Jack Dorsey: And that's where I think the magic still happens and where where I think the focus still comes to bear um because at the end of the day you have to pick something to put out there because we do have a roadmap. But when you remove that limiting factor as I said and you focus on building the four things instead, like you know the capabilities, interface, proactive intelligence and the world model, then you know it just changes everything. So I don't even know if the question matters anymore.","offset":2881,"duration":20}],"startTime":2707},{"title":"Second Acts and Risking Credibility","summary":"Jack shares the story of creating Cash App against the board's initial resistance. He emphasizes that leaders must be willing to lose credibility in the short term to build a successful new venture.","entries":[{"text":"Brian Halligan: Yeah. A lot of CEOs are struggling with the second acts. And you've done amazing second act work at Block, you did interesting stuff with BlueSky, interesting stuff with Spiral. Advice to CEOs trying to figure that second act out?","offset":2901,"duration":14},{"text":"Jack Dorsey: Uh, I don't know if I ever considered to be like a second act, it's just something that like we had I wanted to do and I had to do and it was interesting.","offset":2915,"duration":7},{"text":"Brian Halligan: How's building something new distracting to the org and like how do you resource it?","offset":2922,"duration":4},{"text":"Roelof Botha: Well Cash App was like that in early days.","offset":2926,"duration":1},{"text":"Jack Dorsey: Yeah. Well that's that's a good point, like so I think every leader has to be comfortable with losing credibility with their stakeholders at some point in order to do something interesting. Like when we we had multiple moments and these are the founding moments that um I think are critical for a company.","offset":2927,"duration":23},{"text":"Jack Dorsey: But like we were we started with a card reader, eventually we determined that \"Hey we should probably lend money to sellers\" because like no seller wants to accept credit cards, what they want is to get more sales. And what helps them get more sales? More capital to deploy into their business.","offset":2950,"duration":18},{"text":"Jack Dorsey: When we first brought it to our board, um our board said absolutely no. Like you're not getting into the lending business, like it's ridiculous. And we lost I lost some credibility with with the board and our population because we wanted to do this and we kept pushing it and pushing it and eventually they said yes.","offset":2968,"duration":19},{"text":"Jack Dorsey: Cash App was the same thing where we were about merchants, our mission was make commerce easy, and we built this thing that allowed effortless peer-to-peer, as effortless as just you know sending an email to start. And uh our our COO at the time was on the founding team of PayPal or uh Keith Rabois. And even he said no, and he said like you know this is a solved problem.","offset":2987,"duration":24},{"text":"Jack Dorsey: Everyone in the company hated Cash App, it was a team of eight people. And uh hated it for two to three years, we mentioned it less than eight times in our S-1 to go public. Um our investors didn't understand it at all. And every day that I allowed it to persist and defended it, I lost credibility.","offset":3011,"duration":22},{"text":"Jack Dorsey: And I knew that I could earn it back if it if we saw success there, and we did, like we we monetized it and it became profitable and you know it's now over half our business. And um so I think it's getting comfortable with like you're going to lose credibility and if you have an understanding of like how to earn that back uh it's okay and you don't have to care about like what what people think if you have the principle of why it's important and why this needs to exist and and you're okay with yeah people aren't going to trust me for a bit and it's okay. Um I'm I'm staking part of my reputation on this and this I believe it. I think it makes all those answers stronger, by the way.","offset":3033,"duration":38}],"startTime":2901},{"title":"Treating Every Encounter as a Mentor","summary":"Jack discusses his approach to personal growth and feedback. Rather than relying on a single mentor, he chooses to treat every encounter and problem as an opportunity to actively learn something new.","entries":[{"text":"Brian Halligan: I have a weird story for you, when Sequoia was hiring me they write a memo when they're investing in a company or when they're hiring someone and the memo on me was one of my strengths was I was DGAF, don't give a flock, and one of my weaknesses was I was DGAF, I don't give a flock. You strike me as someone who's has high DGAF and you stick with your convictions for a very long periods of time. Founders struggle with that. I struggle with that. Advice?","offset":3071,"duration":30},{"text":"Jack Dorsey: Yeah I would say it wavers for me. Like it it it's definitely um I get a lot of hate, a lot of pushback, a lot of challenges like internally, externally um but again it's uh I made a I made a decision some time ago when I first became CEO of Twitter, everyone was telling me I needed a uh CEO coach.","offset":3101,"duration":19},{"text":"Brian Halligan: Hmm.","offset":3120,"duration":1},{"text":"Jack Dorsey: And I got the CEO coach and he was a great guy but like I was learning absolutely nothing. And it it just reminded me of all these times when you put so much emphasis on like who's my mentor, who am I learning from, who's my mentor, who am I learning from? And around that time I just decided I'm going to shift my mindset and every single person I talk with, every single encounter I have, every single problem I face, that's my mentor.","offset":3121,"duration":30},{"text":"Jack Dorsey: And to for it to be a mentor I have to decide that I'm going to learn something from it. Like every every encounter I have is trying to teach me something and what am I trying to learn from it? And just I would force myself to like write it down like every day and every encounter and just like what did I learn from this?","offset":3151,"duration":20},{"text":"Jack Dorsey: And again my biggest regrets are when I decided not to learn something from it. Because it's likely that I would have repeated it or what not. So even the negative feedback um or the credibility loss is a is a teaching moment and it's just a decision of like am I learning from this or not?","offset":3171,"duration":20},{"text":"Jack Dorsey: And that allows you ownership over it. Like it just like it gives you agency over all this stuff. Like what is this thing trying to tell me right now? Like what am I ignoring, what am I being stubborn about? Um and uh you know sometimes I I get to the right answer, sometimes I don't, and I just like continue in my ways and it's a failure. But I just having that mindset instead of having this one mentor in your life now you have infinite mentors. Like you know it's it's just an amazing way to approach life and challenges that that I found.","offset":3191,"duration":29}],"startTime":3071},{"title":"The Purpose of Meditation","summary":"Jack explains his physical practice of Vipassana meditation. He details how sitting with pain and focusing on the breath trains the mind to observe without reacting emotionally to impermanent situations.","entries":[{"text":"Brian Halligan: You're definitely a learner, talked a lot about it on other, I've seen you talk about it a lot. You're a meditator. Should all CEOs meditate? What are the benefits you get as the CEO? And what do you take from Marc Andreessen talking about how he's very he's not introspective? I thought that was an interesting comment. Like talk about in meditation, CEOs, what do you get from it? Yeah.","offset":3220,"duration":26},{"text":"Jack Dorsey: Him saying that he's not introspective is very introspective of him, just to be clear. Um I didn't get a lot from that. But I do think um the when people think of meditation they think of like this woo-woo like you know person in the desert and uh I have been characterized as that and looking at the clouds and like imagine the clouds going by and your thoughts are the clouds and you know make them dissipate.","offset":3246,"duration":27},{"text":"Jack Dorsey: But if you actually get into like true meditation, it's a very physical thing. Like it's a very physical um practice and what you're doing is you're training your mind to focus on one point. One point. Like the the meditation retreats I did were 10 days and you spend the first 3 days sitting from 4:30 in the morning till 9:00 p.m. focusing on the feeling of your breath on your upper lip. Yep.","offset":3273,"duration":24},{"text":"Jack Dorsey: Just that and just the sensation of it. And what you're training your mind to do is to sharpen your focus and then just to observe. Observe the sensation without reacting to it from an emotional or intellectual standpoint. Then the next seven days you go up and down your body and you're scanning for sensations like pain. And you're sitting cross-legged and you can't move for three hours at a time. And it's super painful. And you actually observe this pain and you're just like you're constantly with this mindset of like this isn't permanent.","offset":3297,"duration":33},{"text":"Jack Dorsey: If I were to stand up, it goes away. Hmm. And it's just that that training your mind to like recognize everything is impermanent. There's no need to suffer or be attached to something that's going to go away. Like in you're doing in this very small physical way, but then you apply that whole concept to your to your whole life. Every emotion or reaction or encounter you have.","offset":3330,"duration":24},{"text":"Jack Dorsey: So I would recommend it only because it sharpens your focus, it sharpens your power of observation, and it diminishes your instinct to immediately react to things. And to actually see them for what they are and then choose how you want to act with that information. So if you think about it as like a woo-woo you know head in the clouds then that's what you're going to get from it. If you see it as a physical practice to make your mind stronger, you'll get that and and that's that's what I see and that's what you practice.","offset":3354,"duration":28}],"startTime":3220},{"title":"Essential CEO Qualities","summary":"Roelof shares his ALE framework (Authenticity, Logic, Empathy) for leadership. Jack adds that the modern era requires leaders who can constantly reprogram their assumptions and use AI as input to create unique output.","entries":[{"text":"Brian Halligan: Maybe just close on, start with you Roelof. There's some timeless qualities of CEOs um that last the test the time. And Roelof you you you're involved with YouTube, Instagram, Block, Mongo, Unity. What are timeless CEO qualities and what is new? Like what are the new qualities CEOs need today?","offset":3382,"duration":30},{"text":"Roelof Botha: I like acronyms, so I came up with one which is ALE. ALE, which is sort of not a very pleasant drink for most people, but anyway, um authenticity, logic, and empathy. So authenticity, I mean are you, you know, are you pretentious, are you who you do people see who you really are? Do you behave authentically? Are you logical? Are you predictable? Are you rational? Or do you fly off the handle?","offset":3412,"duration":29},{"text":"Roelof Botha: And are you empathetic? Do you really care about the team that you manage? Do you really care about the business? Um you know, sort of opposite of being a sociopath perhaps, but deep empathy. So I think of those three qualities, I mean there are many more that one could list, but you know I think it just hard to keep it in your mind.","offset":3441,"duration":12},{"text":"Roelof Botha: So for me those are the three most important, authenticity, logic, and empathy. I think when it comes to dealing with humans, most of those things stay the same. And I remember how many of us thought the world was going to be so different in the midst of COVID, and I listened to a talk that Steven Pinker gave and he talked about how probably things are going to go back largely the way they were before.","offset":3453,"duration":23},{"text":"Roelof Botha: And I think the same is true here. Yes companies are being built differently, yes AI's absolutely transformational, it's going to upend so many industries. I think it's the biggest drainer of moats companies have ever seen. But some of the you know basics of dealing with people and leading remain true.","offset":3476,"duration":18},{"text":"Roelof Botha: The one I would say is probably different is the pace of of change is so fast. And I think, you know, kudos again to Jack for the the speed with which we're moving on this decision because it would have been easy to dither for 6 or 12 months on this decision. So you've got to move fast.","offset":3494,"duration":19},{"text":"Brian Halligan: Mm. Jack thoughts on that? Like when you're you've hired some amazing people in your career that have gone on to do some amazing things. What do you think? And what's what's what's timeless, what's changed?","offset":3513,"duration":10},{"text":"Jack Dorsey: I value someone who's able to reprogram their mind and assumptions constantly. Um I mean this is stated a lot, but just being able to question your own requirements, your own assumptions, and your own decisions, um or how rigid you are uh towards your past, the company's past and its sacred cows or what the competition is doing.","offset":3523,"duration":29},{"text":"Jack Dorsey: Um it's just being able to like go wild for a bit and then also being able to get that entire corpus down to something that's actually manageable and then can be articulated in a way that other people understand. I think that's extremely valuable.","offset":3552,"duration":14},{"text":"Brian Halligan: Has it always been valuable or is it more valuable because things are moving so fast right now?","offset":3566,"duration":4},{"text":"Jack Dorsey: I think it's more valuable. Like being able to, yeah, I mean I think it's going to be so easy to go along with the momentum of what's happening around us today, and it's going to be increasingly hard to break free of that momentum given what what the tools do and like this is the way we do things and I think people will um because we're offloading some of our intelligence to intelligences, and people will go along with um more likely to to default to what these things are suggesting rather than seeing them as an input.","offset":3570,"duration":33},{"text":"Jack Dorsey: Like I I think we're still in the mode where most people are seeing all what the intelligences do, these tools do as output rather than better input to create better output ourselves. Um and I like I think that's important to me like when I was doing that like everyday 3 hours, like this is input to me and it's now up to me to like really um make better output from like all this new input that I have and like the ability to just take all this and see it at once, it's just phenomenal.","offset":3603,"duration":31},{"text":"Jack Dorsey: So having someone who's able to discern signal from noise and cool from not, relevant, you know, like there is, you know, this is highly overused right now, um the the taste thing is real and it's not just like I know what things look good together, it's more like do I have a point of view? Do I have a perspective and an opinionated drive to get it there and is it is it relevant, is it more relevant than than you know what else is out there?","offset":3634,"duration":29},{"text":"Jack Dorsey: And I think that's that's critical. That's what any founder is doing is like I'm building something that didn't exist in the world because I wanted to see it there. And and because it didn't exist is why I'm building it. And I think um right now you're seeing a lot of companies that are just copies of copies of copies of copies because it's easy instead of like what's your what's your point of view? Like what what is opinionated in this and like where where is it pushing the the boundaries and where is it uncomfortable?","offset":3663,"duration":34}],"startTime":3382},{"title":"Podcast Outro","summary":"Brian thanks his guests and concludes the episode. He reflects on the evolution from Manager Mode to Founder Mode, and potentially to \"Dorsey Mode,\" asking the audience for their thoughts.","entries":[{"text":"Brian Halligan: Mm. I think that's brilliant. It's a great place to end. Thank you both for coming on Long Strange Trip. I love the article you wrote, I think it's going to be game-changer for lots of companies. Appreciate you both.","offset":3697,"duration":9},{"text":"Jack Dorsey/Roelof Botha: Thank you. Thank you. Thank you, Brian. Thank you, Jack. Thank you.","offset":3706,"duration":4},{"text":"Brian Halligan: Hope you liked that. I really enjoyed speaking to him. He's an unusual Homo sapien and he's got some interesting thoughts. Um I think his ideas on how to transform the way you build a company and rethink the hierarchy, they kind of make sense to me and I feel like at some point in the future it's somewhat inevitable that this kind of thing is going to happen.","offset":3710,"duration":28},{"text":"Brian Halligan: And I sort of think of it as like when I grew up in my career, I worked at this company PTC in the 90s. It was very, very Manager Mode, uh very hierarchical, uh the power rested in the VPs essentially. Uh when I ran HubSpot, they didn't call it Founder Mode then but it was kind of Founder Mode. Instead of being a pyramid, it was flat and a lot of power was rested in the in the founder's hands.","offset":3738,"duration":25},{"text":"Brian Halligan: Um he sort of proposing the Dorsey Mode in my mind. He laughed about it when I said it, but I think of it as like what's next? And it's more like a circle than a really flat organization and the power rests in the kind of in the system and the system makes a lot of decisions and can react real time to the employees and the customers.","offset":3763,"duration":24},{"text":"Brian Halligan: But I think of Dorsey Mode as getting rid of the hierarchy all together, building basically the brain, getting the inputs right, and having it make a lot of the decisions that a hierarchy used to. I think he's onto something, I'm curious to see what you think. Um comment on Twitter, comment on on YouTube. I'm I'm curious about your thoughts on it. I think Jack would be curious too. He's in the very early innings of rolling this out and he's looking for feedback on it. Anyway, appreciate you all. Thanks for tuning in.","offset":3787,"duration":15}],"startTime":3697}],"entries":[{"text":"Jack Dorsey: Since last year, I've just had this existential dread and also, like, hope and optimism in the same hour, in the same thought process, of like, what is even a company going forward? Like, what are these structures going forward? And this is the only, like, durable structure that I could actually imagine lasting for quite some time. And it was coming from a place of like, wow, is our company just going to be completely irrelevant, you know, in the next coming years?","offset":0,"duration":30},{"text":"Brian Halligan: All right, everybody, we had Jack Dorsey on the pod today, founder of Twitter and founder of Block. He's the only founder to have two of his companies end up on the S&P 500. I just learned that today, that's pretty cool. Also, Roelof Botha, who's a Sequoia partner and is on Jack's board at Block.","offset":30,"duration":30},{"text":"Brian Halligan: The conversation was super interesting to me. He recently put an article out that you may have seen, called \"From Hierarchy to Intelligence,\" and it's a manifesto on how to rethink, basically rethink from the first principles how an organization works. How do you completely eliminate hierarchy and how do you put AI right in the center and transform how your company works? And I let him go on that and he was very thoughtful and he spoke a lot about it. Block is really changing the way it's organized.","offset":60,"duration":30},{"text":"Brian Halligan: Before we started, he said, \"I'd love to get some feedback from you and from other people on this.\" So if you've got comments on it, let it rip. He wants some feedback on it. He's in the early innings of a big transformation over there. That was about half of it. The second half of it I just asked him for, like, CEO advice. I work with lots of CEOs, as you folks know. Like, how do you build an amazing board? He's certainly got some scars around board building.","offset":90,"duration":30},{"text":"Brian Halligan: How do you build your second act, like the Cash App versus the original business of Square? Is it a good idea to be a CEO of two different companies at the same time? Being brave and not giving a flock versus going with the flow, and when do you really dig in and when do you kind of go with the flow? And he had some really interesting thoughts on the job of a modern CEO. So tune in, I'll be back at the end and give you some further thoughts.","offset":120,"duration":30},{"text":"Brian Halligan: But I thought Jack did a really nice job and Roelof did too. Let's get into it. Jack, I read your piece, I think it's fantastic, \"From Hierarchy to Intelligence.\" Before we get into the meat of what it is, can you describe what you think is wrong with the way normal companies' hierarchies work, companies like HubSpot, companies like Block, like what kind of led you to this?","offset":150,"duration":27},{"text":"Jack Dorsey: I don't know if there's one thing that's ultimately wrong. It's just recognizing that like what do we see in the pattern, what is the function of the hierarchy? And what we wanted to explore is just like where does it actually come from and why does it exist in the first place? And if you look at it from first principles, it's all about information flow to a broad base of people.","offset":177,"duration":33},{"text":"Jack Dorsey: So being able to communicate over a breadth of people and have that be manageable at a human scale. So we've gotten into structures that, you know, we've borrowed and iterated on a little bit over 2,000 years. And now we're faced with this, I think, a completely foundational moment in being able to question every element of how we work. And the one that I think is questioned the least is probably the hierarchy and probably about how we manage communication flow around the company.","offset":210,"duration":30},{"text":"Jack Dorsey: So if we're in a world, where we are today, where Block for instance is completely remote, we're remote-first, every single thing that we do creates some sort of artifact. Whether it be a Slack message, an email, a pull request, code, you know, all these Google Document, a meeting that we record, all these things have these artifacts of information about how the company is working, is building, is failing, is making mistakes, all these things.","offset":240,"duration":40},{"text":"Jack Dorsey: And traditionally we've been reliant upon humans in a management structure in a hierarchy to go up and down a chain to relay that information. Instead, we can take all of those artifacts and put an intelligence on top of it, build a model around it, and actually have a conversation with the company about how the company is doing. And it's not just me as CEO that can do that, but anyone in the company could have that same sort of access to information and same understanding of like what the company can do.","offset":280,"duration":40},{"text":"Jack Dorsey: So you get to a point where you can build these world models for a company, like treat the company as a mini-AGI, for instance, an artificial general intelligence, because it really is. I mean, if you look at a company, it is an intelligence, but it hasn't been structured in a way that's the most efficient or the least lossy in terms of information flow and what people can actually do within the company.","offset":320,"duration":30},{"text":"Jack Dorsey: So the technology is good enough today that we can actually model the company. We can have everyone in the company put in intent, which would be strategy or these artifacts, and we can also have everyone in the company query it as well. And it just really opens the door for what's possible, like Roelof and I have a board meeting every quarter where we construct a bunch of board docs, slides, presentations. We get only so much time for them to have questions.","offset":350,"duration":30},{"text":"Jack Dorsey: But imagine if every single board member can just query the company and have a conversation with the company's intelligence in real time, and we can make that meeting time that we have every quarter really focused on more of the creative or bigger existential decisions and issues than the day-to-day. The same can be said for like our earnings call and analysts, like giving them like fully Reg-FD possible information that is on their timeline with their questioning.","offset":380,"duration":30},{"text":"Jack Dorsey: But you can scale this to any position or any role in the company, which is pretty phenomenal and like we've just never had that ability before. And now we do. And, you know, I think the architecture and the structure of the company is ultimately going to determine its velocity and how well it's roadmapped for customers, correct?","offset":410,"duration":22},{"text":"Brian Halligan: Mm, just kind of drilling down on it, can you describe sort of what the organization looked like before? And granted you're very early in this, but what's it look like now? Which roles have been eliminated? What are the new roles? Just kind of drill down a little bit into what Block looks like today and kind of where it's going.","offset":432,"duration":23},{"text":"Jack Dorsey: Yeah, we are early in it. I mean, just from a, you know, one measurement of how far along we are would be the depth from me to any other individual in the company, and I would say our max depth right now is probably five folks between me and anyone in the company. I would want to get that down to two to three this year.","offset":455,"duration":25},{"text":"Jack Dorsey: And in the most ideal case, you know, there is no layer, everyone in the company reports to me, and that would be, you know, all 6,000 of the company. And that feels somewhat, you know, ridiculous when you consider the old structure. But when you consider that the majority of our work is going through this intelligence layer, it's a lot more manageable.","offset":480,"duration":24},{"text":"Jack Dorsey: And that goes into the roles going forward. We want to normalize down to just three roles. The first is an IC, which is a builder or an operator. This is a salesperson, it's an engineer, it's a designer, product person, you know, whatever it is, they're actually working with the tools to build or to operate the company. They're augmented because they have access to agents, so you know, one person can, you know, potentially do the work or explore the breath that, you know, it would take a team or 10 people to do in the past.","offset":504,"duration":38},{"text":"Jack Dorsey: So that's number one, and I think there's a durable human skill that lasts there, which is judgment and taste and creativity. So that's probably the largest part of the population is the builder and the operators, the ICs. The second role is the DRI, and that's someone who can own the customer outcomes. They're putting a strategy together, they're understanding what roadmap allows us to solve customer needs and problems, and they're assembling a team of these ICs to get something done.","offset":542,"duration":38},{"text":"Jack Dorsey: But the durable human skill there is ownership and accountability. You know, they're really owning the outcomes and whether something is failing or not. And then the last role would be what we consider managers today, which we're calling a player-coach. This is someone who is building the capability and the capacity of other humans and their craft.","offset":580,"duration":25},{"text":"Jack Dorsey: But instead of telling them how to do it, they're showing them how to do it by doing the work. So these are people who might be ICs or they might be DRIs, but they're also really good at giving coaching skills, a coaching skill to help the people around them get better and better and master their craft. And today that's a management structure where ICs and even DRIs report to a player-coach.","offset":605,"duration":30},{"text":"Jack Dorsey: But I think in the future it's an assignment. It's not a reporting structure, but I'm assigned to ICs or I'm assigned to DRIs to help them master their craft. And obviously the durable human skill there is building human capacity and coaching. And there's a lot of empathy there and, you know, all the soft skills that we recognize great managers are known for.","offset":635,"duration":30},{"text":"Jack Dorsey: But not making it a requirement that they have to be strategic necessarily. They have to build, because they need to show off the skill and teach in that way, but they don't necessarily need to be a DRI. Now, I think in very rare cases one person can take on all three of those roles. I think I can take on all three of those roles. My leadership team is expected to take on all three of those roles. They're expected to build as an IC or operate the company, they're expected to be strategic and actually think about roadmaps and customer outcomes, and they're expected to coach and help raise the skill level around them with the people that they work with or with their direct team.","offset":665,"duration":36},{"text":"Brian Halligan: Just a little kind of before and after, and you're mid on this, let's pretend like it's working great and it's years from now and it's extremely flat. Like what does the role of the CEO before and after? How's that changed? Most of the listeners, by the way, are CEOs. What does, like, planning look like before and after? What happens to all those people who are directors and managers or the glue people? Like what are sort of the before and afters in your mind?","offset":701,"duration":30},{"text":"Jack Dorsey: I think my job as CEO in the past I've thought about in three ways. Number one is to ensure that we have the right principles and the right team dynamic. And that's like hiring and firing and setting values and setting the culture and setting the tone. The second is to ensure that decisions are being made in context of our customers and industry trends and competition. And the third would be to raise the bar on our execution, like to constantly increase our capability and to push ourselves into doing things that are uncomfortable so that we're growing all the time.","offset":731,"duration":34},{"text":"Jack Dorsey: So that's how I thought about my job up until this point. I think in the future you have those elements certainly, but I think it's more about like the architecture of how the company as an intelligence works. And if we're building the company as an intelligence, our job as humans and my job as CEO is to constantly align it to where we think the right outcome is.","offset":765,"duration":28},{"text":"Jack Dorsey: And I see, like, visually I see the intelligence, the world model for the company in the center, and then on the edge are the humans who are just constantly aligning this towards customer outcomes. But even that changes, I believe, because I think a company's ultimate limiting factor is its own roadmap.","offset":793,"duration":27},{"text":"Jack Dorsey: And I think what these technologies point to are that our customers are going to, they're going to have the expectation that they can ask for a feature that doesn't exist on our roadmap and that it just is served to them. And that's where like you really get into the layers of like, okay, so what do we actually build? We build up capabilities, which are effectively our tools.","offset":820,"duration":22},{"text":"Jack Dorsey: Like we can issue cards, we card acceptance, peer-to-peer, lending, all these things we do as a financial technology company. We have these interfaces like Square, which has a register and a dashboard. We have Cash App, we have TIDAL, we have Bitkey, we have Proto, these are interfaces, these actually touch the real world, touch humans, and we can deliver our capabilities in these interfaces.","offset":842,"duration":24},{"text":"Jack Dorsey: Today they're built with like these very specific navigations that are our roadmap and our understanding of what our customers want. When you move to the third layer, you have proactive intelligence. We have all this understanding of our customers, we're moving money, money is the most honest signal in the world. You can lie about literally everything, but when a transaction occurs like that's something that really tells the truth about your life or your business's life.","offset":866,"duration":22},{"text":"Jack Dorsey: And based on that, we can actually prompt our customers instead of waiting for them to prompt us or having the right question to ask. So we can do the very simple but very valuable thing of like how do we protect our customer's cash flow? Like we have people using us as a bank account. How do we make sure that they can pay their rent and they can pay their Spotify bill and they can pay their kid's allowance?","offset":888,"duration":27},{"text":"Jack Dorsey: And this is all sequenced in a way that allows them to never go to zero, never go negative, and have some cushion that allows them to even think about getting to saving or building wealth. And that's just, you know, peace of mind I think is the most critical aspect here. So if we're enabling a customer, if we're able to prompt a customer, and also they can ask like as a business, \"Hey, I have this inventory thing that I've been using, but it's missing this feature, can I have this feature?\" We should just be able to build that and compose it in real time based on our capabilities.","offset":915,"duration":37},{"text":"Jack Dorsey: If we can't and it points to a deficiency in capabilities or a gap, that's our roadmap. So our customers just by using and talking with our systems are telling us what our roadmap should be, and then it's up to us to give the judgment. And then the final layer is the world model, it's the customer world model, it's the company world model, our deep understanding of ourselves and also our customers.","offset":952,"duration":23},{"text":"Jack Dorsey: But I think like if I had to say one thing that myself or anyone in the company has to do, it's I guess it's this overused phrase of judgment. But it is judgment against like what we intend to build in the world and is it on, is it aligned with that judgment, is it aligned with the values, is it aligned with the taste that we have and is it unique or is it not?","offset":975,"duration":29},{"text":"Jack Dorsey: And I guess for my part I'm the extra checkpoint on like is the alignment circle of humans, that edge of humans actually working correctly.","offset":1004,"duration":9},{"text":"Brian Halligan: And I see how this works exceptionally well for Block, you have a lot of signal. How does this work for, I don't know, Sierra, Workday, somebody who doesn't have the quality signal, the frequency of signal? Does it apply or doesn't work as well?","offset":1013,"duration":8},{"text":"Jack Dorsey: I think it probably does. I think it goes down to like are you building a business that like understands something of human nature deeply and it gets deeper every single time? And that's a real tangible signal that just doesn't go away. And if you are, then I think you can build your company as an intelligence. If you're not, then it's probably a an add-on to something else.","offset":1021,"duration":33},{"text":"Jack Dorsey: And I think most of the industry is thinking about AI as like a copilot, as something that is augmented onto rather than like how do you just rebuild this our whole company with this as the core. Like and if it doesn't make sense for your business to do that and you end up being or looking very similar or rhyming too closely with the frontier labs, then I think it's going to be very, very challenging to differentiate and survive.","offset":1054,"duration":28},{"text":"Jack Dorsey: And that's kind of what's been leading me to all this is like I just, you know, since January of 2024 which is when these tools really came to bear, like Goose which is an agent coding harness was one month before Claude Code in January of 2024. And Claude Code came out that following month and then like was really put into out of beta in May of that year.","offset":1082,"duration":29},{"text":"Jack Dorsey: And, you know, that whole year I just spent every single day for 3 hours every morning just pushing myself, like can I get it to do something that I didn't think it was capable of or I didn't think I was capable of? And every single day it worked. Like every single day I was surprised. And it's, you know, I'm sorry, it wasn't 2024, it's 2025.","offset":1111,"duration":23},{"text":"Jack Dorsey: It's only been a year of those tools, like one year, it's just the compounding nature of this is pretty incredible. So being able to like see that, understand it, and then shift your company to be ahead of it I think is absolutely critical right now. And I don't think people are feeling it enough. They're just living in this abstraction of like oh yeah, like these tools will make everyone in our company 10x more productive. I don't think this is a productivity thing. I think it's a structural thing that needs to shift.","offset":1134,"duration":36},{"text":"Brian Halligan: I think you're right. I think if people are thinking of it as copilots and individual productivity versus your, I think your idea is complete business transformation and I think it's super interesting and compelling.","offset":1170,"duration":10},{"text":"Roelof Botha: Can I add one thought I've had as I've listened to this so far. In one of the one of my favorite pieces of writing ever is Adam Smith, \"Wealth of Nations,\" and this idea that if you have the right signals you can rely on the self-interested behavior of many small participants in the system to actually lead to optimal outcomes, but you just need to have the right framework and the right system.","offset":1180,"duration":17},{"text":"Roelof Botha: I think the way that many companies work today is a little bit more command and control. Very much so. And you have hierarchies and you have political actions and people, you know, are jockeying for position and it's it's not always clear what is actually true. And I think part of what we're envisioning here is you have a system that's just ground truth.","offset":1197,"duration":21},{"text":"Roelof Botha: And you do away with all the layers, you get back to the kind of productivity that founders often long for. They long for the days when they were 100 people and not 500 people because they were so much more productive. Why? Because you had, you know, lots of transparency, limited hierarchy. And so I think the possibility here as Jack was saying is instead of just focusing on individual productivity you reimagine how we work together as humans.","offset":1218,"duration":31},{"text":"Roelof Botha: And you can do it with far smaller number of people that are far more productive, yes, but there's a different way of working together where you get the right signals and it's it's much more similar to a capitalist system where the signals tell you what to build. It's not somebody who pounds the table harder who gets their product approved, it's just listen, more customers want this than that, that's how we're going to decide what to build next. For me there's something quite magical in that realization.","offset":1249,"duration":25},{"text":"Brian Halligan: Yeah. About four years into building HubSpot I eliminated no org charts, no titles, and everyone lost their mind. They didn't like the idea. And we ran that for about nine months and I got worn down and I brought it back. The thing we didn't have was an intelligent system that had all those signals that could help us make decisions. So it's exciting to see this here.","offset":1274,"duration":21},{"text":"Brian Halligan: I have a theory I want to run by you Roelof, like I sort of think of like there's Manager Mode, it's a pyramid, the VPs make most of the decisions. And there's Founder Mode, kind of flat, the founder makes a lot of the decisions. And then there's, I'm just going to call it Dorsey Mode, it's a circle and the AI makes most of the decisions. Do you buy that?","offset":1295,"duration":26},{"text":"Roelof Botha: Oh, I don't think the AI makes most of the decisions. I think and Jack should correct me here, I think the AI helps with communicating the alignment and the management team or the inner core helps set the framework. What is the objective function? Are we optimizing for growth rate, gross profit per employee, net promoter score, probably some combination of those variables?","offset":1321,"duration":23},{"text":"Roelof Botha: And the humans at the edges perform an incredibly valuable function of correcting and informing and sort of steering that. And I think one of the phrases that Jack has which I absolutely love and I've stolen so many times is companies have multiple founding moments. There's so many smart people in your company that have clever ideas that every day inflect the product, introduce something new.","offset":1344,"duration":26},{"text":"Roelof Botha: And so this idea that there's just, you know, one person who is the brilliant person who comes up with everything, I just don't think, you know, I don't believe in hero worship or the converse of that where you sort of scapegoat people. I think it's harnessing the best of of your team to really advance the company. So I subscribe to the circle idea.","offset":1370,"duration":11},{"text":"Jack Dorsey: Yeah, I also don't think the AI is making the majority of the decisions. I think it's facilitating a more context-rich decision. I think ultimately, like in the most ideal case, our customers are actually making the majority of the decisions because they're just based on their queries and what they're trying to do with the system delineates like where our roadmap should go.","offset":1381,"duration":24},{"text":"Jack Dorsey: And then it's up to our judgment as to whether that's consistent with what we want to be and what we think is most strategic or not. But we just, you know, we weren't able to get to that level of data fidelity before because we had to infer it. We had to do customer research, we had to do interviews, we had to do look at our customer support, product feedback on Twitter, all these other things.","offset":1405,"duration":29},{"text":"Jack Dorsey: But when your interface is a conversation with your customer instead of like this visual navigation, you suddenly get like this amazing fidelity of like what do our customers actually care about, what do they actually want? And it's up to us then to decide if that's consistent with what we want to be as a company or if they should be going elsewhere to to do that.","offset":1434,"duration":25},{"text":"Jack Dorsey: And I think all these things are going to blur. That, I mean, that's the craziest thing is like, you know, again since since last year I've just had this existential dread and also like hope and optimism in the same hour, in the same thought process of like what is even a company going forward? Like what are these structures going forward? And this is the only like durable one structure that I could actually imagine lasting for quite some time.","offset":1459,"duration":29},{"text":"Jack Dorsey: And it was coming from a place of like wow, is our company just going to be completely irrelevant in the next coming years or even even sooner? Like what do we what do we actually differentiate on? What do we have a moat around and what do we need to be to defend and and also to grow that? And like what are the and all that follows from customer expectation?","offset":1488,"duration":27},{"text":"Jack Dorsey: Like the most amazing thing about open-Claude to me was that people wanted to take this thing and contain it into a Mac Mini and make it very tangibly theirs and have all this agency around what they did with it. And we're seeing Square sellers do stuff with it like that in interface with the Square APIs, and we're seeing Cash App customers, and these are not tech people, these are just like people, \"I want I want a bot to help me manage my life.\"","offset":1515,"duration":-1166},{"text":"Jack Dorsey: That agency, independent of your thoughts on like how good of a system open-Claude is right now, it'll get better and better, but the intent behind that is agency. I want to tangibly control this intelligence and for it to better me and what it makes possible for me is incredible. And that expectation floor has just risen dramatically.","offset":349,"duration":1226},{"text":"Jack Dorsey: And that leads me again to like yeah, our limiting factor as a company is our roadmap. Like we need to remove that from the equation. We need to ensure that our customers are truly building alongside us and that they, you know, are seeing us as a series of capabilities that makes their desires fast and easy and and valuable.","offset":1575,"duration":25},{"text":"Jack Dorsey: So like it really goes back to the capability set that we have and then the intuition of the interface that we have and then like how intelligent our world models can can be to be helpful and to compose UI in real time.","offset":1600,"duration":15},{"text":"Brian Halligan: I spent this morning at a company called Rogo here in New York City. They read your article. Let's say you're advising the CEO of 100-person company. They've already got their hierarchy. What should they do? Should they start with their system? Should they start with data? Should they start with org? Like how should people go about, you know, running the Dorsey playbook?","offset":1615,"duration":23},{"text":"Roelof Botha: Uh, we don't have it all figured out. I think there's an important dose of humility that we have that we're endeavoring on this path. We believe it's right, but we we know there's a lot to figure out.","offset":1638,"duration":12},{"text":"Jack Dorsey: Yeah, it's more like if if you were at 100 people or even, you know, just starting today, if you were to build your company as an AGI, as an intelligence, what would it look like? And what would you need to really differentiate? Like if I were starting a company today, I would be so excited about how quickly I could build things and how quickly I could prototype and get things out to customers.","offset":1650,"duration":23},{"text":"Jack Dorsey: I would be in this like valley of dread about distribution and attention because there is so much noise out there and it's so hard to get to the actual signal of like who's building something interesting that will actually fundamentally change something and will be around for more than a year. It just like I think distribution really becomes a differentiator.","offset":1673,"duration":27},{"text":"Jack Dorsey: And I think there's some event horizon where the way we think about distribution today closes off. You know, it like there's there's apps, for instance, and websites and like the traditional retail. There's a number of things that will change and if you don't have the distribution today, it's going to be very hard to fight for that.","offset":1700,"duration":24},{"text":"Jack Dorsey: But there'll be new areas of distribution that are probably more important, and I don't know what those look like. But I would say like I would assume that a company of 100 probably is no more than two to three layers deep, hopefully. And now would be the time to just like really question, like do I do I need a hierarchy?","offset":1724,"duration":21},{"text":"Jack Dorsey: Brian, a year into Square, I also removed titles, we normalized everyone to lead. We did it for like we were talking with all these banks all the time and you would have these EVPs and VPs and they were looking for the same on the business card and there's this whole business card culture. So we ripped up all the business cards, we normalized down to a title of like you're lead of what, and the longer that is behind lead is probably the farther down you are in the organization.","offset":1745,"duration":29},{"text":"Jack Dorsey: And we've kept it, like we we you know we don't have titles. We have like, you know, what do you lead, going back to like the DRI thing, what are you ultimately responsible for? And I think it's helped us a lot. But this is another step. Like if if you're starting today or you're 100 today, like what what is actually fundamental to solving your customer's problems and and where is the hierarchy getting in the way of that?","offset":1774,"duration":26},{"text":"Jack Dorsey: And look at all the tools you're using. Like look at all the information you're generating just by doing your work. Like just putting that into an intelligence and being able to query it will give you an understanding of the company that like is two to three times more than you had before, ever. Because you're relying upon people telling you things.","offset":1800,"duration":20},{"text":"Jack Dorsey: And, you know, that doesn't always happen for various reasons that, you know, Roelof spoke to in terms of agenda or politics or emotions or empathy, all all these things. Imagine if your company was entirely legible. Like entirely legible every aspect of it. And we're not far off from that from a data perspective. It's putting the intelligence on top of it and making it useful and then making it proactive.","offset":1820,"duration":28},{"text":"Jack Dorsey: Like that's that's the hardest bet is like we can determine causal, getting to predictability for these world models around the company and customers is still right now very much a research bet. But like it's imminently solvable.","offset":1848,"duration":17},{"text":"Brian Halligan: Mm. Can you guys just take me behind the scenes, like Jack this was a really bold move, you laid off 40% of your employees. Just like for CEOs listening, what was that debate inside, like how big should it be, how bold should it be? You know, Ruth Porat's got this good line, if you're going to eat a shit sandwich, don't nibble. And you seem like you took a big bite. What was that debate behind the scenes and then Roelof, like how did he pitch it to you guys and what was the board's reaction? Just like behind the scenes on that.","offset":1865,"duration":35},{"text":"Jack Dorsey: Yeah. So December of last year is when the model is really got a noticeable upgrade from being able to be really good at building prototypes and greenfield efforts to like understanding like large codebases and legacy codebases like our own. There was, you know, hallucination wasn't much of a topic in terms of like the coding ability and the tool harnesses became suddenly very mature. Like just in that month.","offset":1900,"duration":35},{"text":"Jack Dorsey: And it just like everyone went home for the holidays and everyone played with these tools and they were surprised at how capable they were and what they could do with them. And you know, we came back and the conversation was like just going around the table, \"Would you build the company this way if you had these tools today? Like what would the company look like?\"","offset":1935,"duration":23},{"text":"Jack Dorsey: And everyone around the table and my team just said like it would not look like this. It would not be this size. It would not be structured this way. And we've been making like changes on the on the edge, like, you know, going from a GM structure to a functional structure to reduce, like putting a a cap on our layers to four, me plus four, and all these like small things.","offset":1958,"duration":26},{"text":"Jack Dorsey: But if we were to really reboot and rebuild the company, like would we end up where we where we look today? And the answer was uniformly no. And then we just did this exercise of like okay, so what is the minimum number of people that we would need to keep the service up 100%? And then next, what is the minimum number of people that we would need to fully be in compliance with our regulators? We're a highly regulated business, so that one's extremely important to us, and legal obviously.","offset":1984,"duration":34},{"text":"Jack Dorsey: And then third, what is the minimum set of folks that we need in order to grow, to fulfill our commitments we've made to the street, but also rebuild the company as an intelligence. And that's roughly the number that we got to and we built in some buffer in case we made mistakes, which we did. And you know, hard hard not to, especially operating the way we have.","offset":2018,"duration":25},{"text":"Jack Dorsey: Like I think going forward it'll be much easier because more of the company will be legible and all of our actions will be a lot more legible. So I'd have a lot more confidence going forward than not. But it was that and and there was a span of exploration to execution and, you know, under under three weeks.","offset":2043,"duration":22},{"text":"Jack Dorsey: And I think generally I wanted to make sure that we if we knew that this was what our company was going to be in the future, I didn't want to have to do it with our backs against the wall. We're a public company and there's various challenges there, and other companies will will probably get to this realization at some point.","offset":2065,"duration":24},{"text":"Jack Dorsey: I don't want to react to that. I want to I want to be ahead of it, because then we can do it with a lot more integrity, we can do it with a lot more generosity for the people that we're asking to part, to leave, and even for the people that we're asking to stay and we're not just reacting into something mediocre, we're acting towards excellence. And like that's just the tone that we wanted to set.","offset":2089,"duration":28},{"text":"Jack Dorsey: So, you know, every day was just like constantly checking like are we doing the right thing, is this the right set of folks, like what are we not thinking about, what are we not talking about? And we you know we kept the the group very, very tight and had a conversation with with a board, which was a my perspective very open to it and actually more than open, more like, \"Yes, we agree, like we should we should do this.\" But I'll let Roelof speak to that.","offset":2117,"duration":37},{"text":"Roelof Botha: It was a very quick process. I think part of what helps is that Jack had written us a very detailed note laying out the logic. It's principled. It's not reactive as Jack was saying, it's not reactionary, it's very well laid out, very logical.","offset":2154,"duration":17},{"text":"Roelof Botha: It was clear that the company and the management team was interested in a conversation about how to make this work, as opposed to being dogmatic and saying they have it all figured out. So even in the course of those three weeks, elements of this evolved, and it evolved in light of feedback from management team members and board members. You know, some of some of where we started in the first of those three weeks is different from where we ultimately landed by the time the announcement took place.","offset":2171,"duration":27},{"text":"Roelof Botha: And I also think it's just an example of where we've built enormous trust between the board and the management team. You know, we've been through a lot as a team, and so we have a lot of shorthand to be able to make crucial decisions like this. We gathered several times in quick succession to make sure we drilled in on the key issues, and the board was fully supportive.","offset":2198,"duration":20},{"text":"Brian Halligan: You two, Roelof you've been on a lot of boards, Jack you've had your ups and downs with different boards. Any advice for these CEOs listening that should they start at 100 employees, should they start bringing in independents, should they like how do you build an amazing board that really serves the company well, the employees well, the investors well, the customers well? Like what's your advice on that?","offset":2218,"duration":21},{"text":"Jack Dorsey: I mean early on I always told myself and my team that like your your first board is your investors, right? And I would treat that relationship as a hire you can never fire, and in fact they can fire you, and I've been on the other side of that. So it really puts pressure on finding the right person that you'd actually want to work with at the company knowing that you could never fire them.","offset":2239,"duration":31},{"text":"Jack Dorsey: And again, they can fire you. And for me, it was around, you know, I think a lot of young founders kind of go for the brand names, especially around VCs, but I always wanted to go for the for the person, and you know that's why Roelof, you know, we we we were optimizing for him to be on our board and be an investor.","offset":2270,"duration":23},{"text":"Jack Dorsey: But like it was the fact that like he would up-level our conversation, up-level our execution more than anything else and challenge us along the way. So even as you think about adding independent board members, like the core function of a board is to ensure that the company has the right CEO. Like that's their one job. They have all these committee responsibilities and but the ultimate fiduciary duty is like do we have the right CEO going forward?","offset":2293,"duration":33},{"text":"Jack Dorsey: And I think you have to build a board that has different perspective on that and that is open to wild ideas, things that are going to just seem like crazy in the moment, which like this one might might be. But it can be rationalized if we talk through it and we like really document it and paint a picture of like where this could go and like what the opportunity cost is if we don't do something.","offset":2326,"duration":27},{"text":"Jack Dorsey: Because if we didn't do something like this, I just imagine like every year it's a 10% RIF or 20% RIF or whatever it is, and like that is just the most demoralizing, like crappy, like non-creative building of a company ever and it's all, you know, with your backs against a wall and like it just feels like losing constantly.","offset":2353,"duration":18},{"text":"Jack Dorsey: And I, you know, had a conversation with a board about I don't want that. Like that's not I don't want to be at a company like that. Like it's just it doesn't make sense, it's soul-crushing, you know, and it's just not not inspiring and I don't feel good about it. So here's here's what I do feel good about and like let's let's go, let's let's challenge it.","offset":2371,"duration":17},{"text":"Roelof Botha: Well I think the first financing when you get an investor, if you're getting an investor board member, you should treat it as a recruiting decision, not a financing decision, because it'll have a much bigger bearing on the ultimate outcome of your company.","offset":2388,"duration":23},{"text":"Roelof Botha: And then I'm generally a fan of getting a very good independent board member within a year or two, certainly by the time you get product-market fit. And I think there's a different relationship that the founder has with the investor board member by virtue of what Jack, you know, described that sometimes, you know, that person may come to the conclusion that the founder's no longer the right person to run the company, maybe rightly, maybe wrongly.","offset":2411,"duration":24},{"text":"Roelof Botha: If you can get an independent board member, there's a different relationship that the founder has with that board member. And especially if that person has previous experience, it can be a fantastic mentor relationship to help the founder on that journey depending obviously on their level of experience.","offset":2435,"duration":18},{"text":"Roelof Botha: I think boards are often built too late in a rush, especially in the run up up to an IPO where people suddenly realize, \"Ooh, I've got a four-person board and I need nine,\" whatever the case is, and then you suddenly assemble people who have no context, they have no history, and they have no chemistry, because you will be tested.","offset":2453,"duration":19},{"text":"Roelof Botha: You're going to have a situation where there's a short-seller report or you're dealing with a hostile, you know, situation with activist investor or a tricky financing, you know, that really tests the mettle of the team, and you want to understand the dynamic between the board members and just their willingness to go along and their alignment with the core values of the business. And so I just think it's one of those things that requires a lot more care than I think most people apply to it.","offset":2472,"duration":21},{"text":"Brian Halligan: Jack, you've started a couple great companies here, you're a startup founder, scale-up CEO. Roelof, he was the only person to have founded two companies that made it into the S&P 500. That's amazing. And the only person to have been simultaneously CEO of two public companies, for the record.","offset":2493,"duration":23},{"text":"Jack Dorsey: Which should not be should not be a goal for anyone, by the way.","offset":2516,"duration":2},{"text":"Brian Halligan: Let me ask him, he's CEO of two companies. Is it ever a good idea?","offset":2518,"duration":3},{"text":"Jack Dorsey: Not public companies. Private maybe. Private I would I think there's probably going to be more of a trend where people are leading multiple companies that are private, but public companies like I should definitely like an anti-goal, it's an anti-pattern.","offset":2521,"duration":15},{"text":"Brian Halligan: What can founder-CEOs learn from like, what did you do right, what did you just get wrong? What advice do you have for that 100-person company CEO growing really fast? Like yeah, what do you got?","offset":2536,"duration":15},{"text":"Jack Dorsey: My only regrets in life and and also in our in our businesses, um, are where I decided not to learn something. Because I like I embrace all of our mistakes and all the bad decisions we made, but like if I'm not learning from that, actively learning from it, like that's that's what I regret.","offset":2551,"duration":29},{"text":"Jack Dorsey: And, you know, in in probably the worst case in any of these companies, just delegating way too much. Especially within Block because like I wanted to set a structure where we had multiple CEOs in this company, but I realized, \"Oh man, we're just building like a holding company now.\"","offset":2580,"duration":24},{"text":"Jack Dorsey: And like we got like you know the CEO over here for Square and CEO over here for Cash App and like the value of our company is not like these, you know, unrelated things that are growing at different clips, it's how do we bring them together and like really, you know, um, challenge the whole financial network entirely, because we have we have both sides of the counter.","offset":2604,"duration":22},{"text":"Jack Dorsey: So like why aren't we structured that way? And that I think led to just very differing cultures and values and execution levels and um, that was a mess. So I think the one thing that I probably consistently would have corrected would be just delegating too much. You know, too too much of that and I didn't learn that fast enough. Like that's that's the regret, is I didn't choose to to learn from that fast enough.","offset":2626,"duration":31},{"text":"Jack Dorsey: But when you have your whole your entire company is legible, it's a very different equation. Um, and I think my regrets going forward if I were to predict them would be like am I actually putting enough entropy into the system, like enough of the intent into the system to actually keep us relevant going forward?","offset":2657,"duration":29},{"text":"Jack Dorsey: And and that's hence the shift. Like I I can't imagine doing anything bigger than rebuilding our company as an intelligence um, or more correct um given where where everything is trending. So it just feels like I have to constantly build um and constantly learn from whatever we're putting out there in order for us to stay relevant going forward.","offset":2686,"duration":21},{"text":"Roelof Botha: So there's one anecdote that came up Jack last week which is how different meetings are today. They're obviously, maybe you can talk about how frequent meetings are taking place now and what's the color, what are the nature of the meetings today versus what they were a year ago?","offset":2707,"duration":14},{"text":"Jack Dorsey: Well I mean just two months ago, every meeting that we would have would come you mean you you you have this Brian, like you see a presentation or a Google Doc and we go through it. Now, everyone is bringing a prototype that they built, which is pretty amazing and like it's either simulated data or real data, but it's a cut on their work in a way that's far more um has far more depth and realism than we could ever get from a slide deck.","offset":2721,"duration":37},{"text":"Jack Dorsey: And because they can actually modify it in real time, like we can have a conversation around like what they're actually building in real time. Um, so like the the breath that we get to explore is suddenly incredible and that allows us to like really again it goes back to judgment, like which thread are we pulling on this now because we can see like everything in the horizontal. Where do we want to go like deep? And like what what is the right path?","offset":2758,"duration":33},{"text":"Jack Dorsey: And the cost of like being wrong on that path and going back up the tree and going down another path is getting closer and closer to zero because the tools can explore the path so quickly and then also we can go down them much much faster.","offset":2791,"duration":13},{"text":"Brian Halligan: I I completely agree with you, like a lot of times in HubSpot's history what worked was when we were doing a lot of different stuff and we were distracted, let's just get focused and then we made progress. I see the startups these days doing more things in parallel and just being more productive and getting more done, and I used to preach focus, I don't preach it as much as I do. Do you have a reaction to that?","offset":2804,"duration":20},{"text":"Jack Dorsey: Yeah it's uh I think it's I think it's having a wider perspective to start and then because in the past if we were to explore different paths like it would be a uh you know three it'd be a very costly exercise, especially within hardware for instance. Take you a long time to build that prototype.","offset":2824,"duration":22},{"text":"Jack Dorsey: But today we can do it in an hour. And then um so I do encourage more exploration, but I think focus on getting the details right when we do choose that path. And like it's the 80/20% thing, which is like you know these tools will build about 80% of what where we need to go and then that last 20% is going to be a function of like how good our creativity, how good our taste is, how good our judgment is and um and just constantly pushing these these models to to doing something that they weren't they weren't we didn't think they were capable of.","offset":2846,"duration":35},{"text":"Jack Dorsey: And that's where I think the magic still happens and where where I think the focus still comes to bear um because at the end of the day you have to pick something to put out there because we do have a roadmap. But when you remove that limiting factor as I said and you focus on building the four things instead, like you know the capabilities, interface, proactive intelligence and the world model, then you know it just changes everything. So I don't even know if the question matters anymore.","offset":2881,"duration":20},{"text":"Brian Halligan: Yeah. A lot of CEOs are struggling with the second acts. And you've done amazing second act work at Block, you did interesting stuff with BlueSky, interesting stuff with Spiral. Advice to CEOs trying to figure that second act out?","offset":2901,"duration":14},{"text":"Jack Dorsey: Uh, I don't know if I ever considered to be like a second act, it's just something that like we had I wanted to do and I had to do and it was interesting.","offset":2915,"duration":7},{"text":"Brian Halligan: How's building something new distracting to the org and like how do you resource it?","offset":2922,"duration":4},{"text":"Roelof Botha: Well Cash App was like that in early days.","offset":2926,"duration":1},{"text":"Jack Dorsey: Yeah. Well that's that's a good point, like so I think every leader has to be comfortable with losing credibility with their stakeholders at some point in order to do something interesting. Like when we we had multiple moments and these are the founding moments that um I think are critical for a company.","offset":2927,"duration":23},{"text":"Jack Dorsey: But like we were we started with a card reader, eventually we determined that \"Hey we should probably lend money to sellers\" because like no seller wants to accept credit cards, what they want is to get more sales. And what helps them get more sales? More capital to deploy into their business.","offset":2950,"duration":18},{"text":"Jack Dorsey: When we first brought it to our board, um our board said absolutely no. Like you're not getting into the lending business, like it's ridiculous. And we lost I lost some credibility with with the board and our population because we wanted to do this and we kept pushing it and pushing it and eventually they said yes.","offset":2968,"duration":19},{"text":"Jack Dorsey: Cash App was the same thing where we were about merchants, our mission was make commerce easy, and we built this thing that allowed effortless peer-to-peer, as effortless as just you know sending an email to start. And uh our our COO at the time was on the founding team of PayPal or uh Keith Rabois. And even he said no, and he said like you know this is a solved problem.","offset":2987,"duration":24},{"text":"Jack Dorsey: Everyone in the company hated Cash App, it was a team of eight people. And uh hated it for two to three years, we mentioned it less than eight times in our S-1 to go public. Um our investors didn't understand it at all. And every day that I allowed it to persist and defended it, I lost credibility.","offset":3011,"duration":22},{"text":"Jack Dorsey: And I knew that I could earn it back if it if we saw success there, and we did, like we we monetized it and it became profitable and you know it's now over half our business. And um so I think it's getting comfortable with like you're going to lose credibility and if you have an understanding of like how to earn that back uh it's okay and you don't have to care about like what what people think if you have the principle of why it's important and why this needs to exist and and you're okay with yeah people aren't going to trust me for a bit and it's okay. Um I'm I'm staking part of my reputation on this and this I believe it. I think it makes all those answers stronger, by the way.","offset":3033,"duration":38},{"text":"Brian Halligan: I have a weird story for you, when Sequoia was hiring me they write a memo when they're investing in a company or when they're hiring someone and the memo on me was one of my strengths was I was DGAF, don't give a flock, and one of my weaknesses was I was DGAF, I don't give a flock. You strike me as someone who's has high DGAF and you stick with your convictions for a very long periods of time. Founders struggle with that. I struggle with that. Advice?","offset":3071,"duration":30},{"text":"Jack Dorsey: Yeah I would say it wavers for me. Like it it it's definitely um I get a lot of hate, a lot of pushback, a lot of challenges like internally, externally um but again it's uh I made a I made a decision some time ago when I first became CEO of Twitter, everyone was telling me I needed a uh CEO coach.","offset":3101,"duration":19},{"text":"Brian Halligan: Hmm.","offset":3120,"duration":1},{"text":"Jack Dorsey: And I got the CEO coach and he was a great guy but like I was learning absolutely nothing. And it it just reminded me of all these times when you put so much emphasis on like who's my mentor, who am I learning from, who's my mentor, who am I learning from? And around that time I just decided I'm going to shift my mindset and every single person I talk with, every single encounter I have, every single problem I face, that's my mentor.","offset":3121,"duration":30},{"text":"Jack Dorsey: And to for it to be a mentor I have to decide that I'm going to learn something from it. Like every every encounter I have is trying to teach me something and what am I trying to learn from it? And just I would force myself to like write it down like every day and every encounter and just like what did I learn from this?","offset":3151,"duration":20},{"text":"Jack Dorsey: And again my biggest regrets are when I decided not to learn something from it. Because it's likely that I would have repeated it or what not. So even the negative feedback um or the credibility loss is a is a teaching moment and it's just a decision of like am I learning from this or not?","offset":3171,"duration":20},{"text":"Jack Dorsey: And that allows you ownership over it. Like it just like it gives you agency over all this stuff. Like what is this thing trying to tell me right now? Like what am I ignoring, what am I being stubborn about? Um and uh you know sometimes I I get to the right answer, sometimes I don't, and I just like continue in my ways and it's a failure. But I just having that mindset instead of having this one mentor in your life now you have infinite mentors. Like you know it's it's just an amazing way to approach life and challenges that that I found.","offset":3191,"duration":29},{"text":"Brian Halligan: You're definitely a learner, talked a lot about it on other, I've seen you talk about it a lot. You're a meditator. Should all CEOs meditate? What are the benefits you get as the CEO? And what do you take from Marc Andreessen talking about how he's very he's not introspective? I thought that was an interesting comment. Like talk about in meditation, CEOs, what do you get from it? Yeah.","offset":3220,"duration":26},{"text":"Jack Dorsey: Him saying that he's not introspective is very introspective of him, just to be clear. Um I didn't get a lot from that. But I do think um the when people think of meditation they think of like this woo-woo like you know person in the desert and uh I have been characterized as that and looking at the clouds and like imagine the clouds going by and your thoughts are the clouds and you know make them dissipate.","offset":3246,"duration":27},{"text":"Jack Dorsey: But if you actually get into like true meditation, it's a very physical thing. Like it's a very physical um practice and what you're doing is you're training your mind to focus on one point. One point. Like the the meditation retreats I did were 10 days and you spend the first 3 days sitting from 4:30 in the morning till 9:00 p.m. focusing on the feeling of your breath on your upper lip. Yep.","offset":3273,"duration":24},{"text":"Jack Dorsey: Just that and just the sensation of it. And what you're training your mind to do is to sharpen your focus and then just to observe. Observe the sensation without reacting to it from an emotional or intellectual standpoint. Then the next seven days you go up and down your body and you're scanning for sensations like pain. And you're sitting cross-legged and you can't move for three hours at a time. And it's super painful. And you actually observe this pain and you're just like you're constantly with this mindset of like this isn't permanent.","offset":3297,"duration":33},{"text":"Jack Dorsey: If I were to stand up, it goes away. Hmm. And it's just that that training your mind to like recognize everything is impermanent. There's no need to suffer or be attached to something that's going to go away. Like in you're doing in this very small physical way, but then you apply that whole concept to your to your whole life. Every emotion or reaction or encounter you have.","offset":3330,"duration":24},{"text":"Jack Dorsey: So I would recommend it only because it sharpens your focus, it sharpens your power of observation, and it diminishes your instinct to immediately react to things. And to actually see them for what they are and then choose how you want to act with that information. So if you think about it as like a woo-woo you know head in the clouds then that's what you're going to get from it. If you see it as a physical practice to make your mind stronger, you'll get that and and that's that's what I see and that's what you practice.","offset":3354,"duration":28},{"text":"Brian Halligan: Maybe just close on, start with you Roelof. There's some timeless qualities of CEOs um that last the test the time. And Roelof you you you're involved with YouTube, Instagram, Block, Mongo, Unity. What are timeless CEO qualities and what is new? Like what are the new qualities CEOs need today?","offset":3382,"duration":30},{"text":"Roelof Botha: I like acronyms, so I came up with one which is ALE. ALE, which is sort of not a very pleasant drink for most people, but anyway, um authenticity, logic, and empathy. So authenticity, I mean are you, you know, are you pretentious, are you who you do people see who you really are? Do you behave authentically? Are you logical? Are you predictable? Are you rational? Or do you fly off the handle?","offset":3412,"duration":29},{"text":"Roelof Botha: And are you empathetic? Do you really care about the team that you manage? Do you really care about the business? Um you know, sort of opposite of being a sociopath perhaps, but deep empathy. So I think of those three qualities, I mean there are many more that one could list, but you know I think it just hard to keep it in your mind.","offset":3441,"duration":12},{"text":"Roelof Botha: So for me those are the three most important, authenticity, logic, and empathy. I think when it comes to dealing with humans, most of those things stay the same. And I remember how many of us thought the world was going to be so different in the midst of COVID, and I listened to a talk that Steven Pinker gave and he talked about how probably things are going to go back largely the way they were before.","offset":3453,"duration":23},{"text":"Roelof Botha: And I think the same is true here. Yes companies are being built differently, yes AI's absolutely transformational, it's going to upend so many industries. I think it's the biggest drainer of moats companies have ever seen. But some of the you know basics of dealing with people and leading remain true.","offset":3476,"duration":18},{"text":"Roelof Botha: The one I would say is probably different is the pace of of change is so fast. And I think, you know, kudos again to Jack for the the speed with which we're moving on this decision because it would have been easy to dither for 6 or 12 months on this decision. So you've got to move fast.","offset":3494,"duration":19},{"text":"Brian Halligan: Mm. Jack thoughts on that? Like when you're you've hired some amazing people in your career that have gone on to do some amazing things. What do you think? And what's what's what's timeless, what's changed?","offset":3513,"duration":10},{"text":"Jack Dorsey: I value someone who's able to reprogram their mind and assumptions constantly. Um I mean this is stated a lot, but just being able to question your own requirements, your own assumptions, and your own decisions, um or how rigid you are uh towards your past, the company's past and its sacred cows or what the competition is doing.","offset":3523,"duration":29},{"text":"Jack Dorsey: Um it's just being able to like go wild for a bit and then also being able to get that entire corpus down to something that's actually manageable and then can be articulated in a way that other people understand. I think that's extremely valuable.","offset":3552,"duration":14},{"text":"Brian Halligan: Has it always been valuable or is it more valuable because things are moving so fast right now?","offset":3566,"duration":4},{"text":"Jack Dorsey: I think it's more valuable. Like being able to, yeah, I mean I think it's going to be so easy to go along with the momentum of what's happening around us today, and it's going to be increasingly hard to break free of that momentum given what what the tools do and like this is the way we do things and I think people will um because we're offloading some of our intelligence to intelligences, and people will go along with um more likely to to default to what these things are suggesting rather than seeing them as an input.","offset":3570,"duration":33},{"text":"Jack Dorsey: Like I I think we're still in the mode where most people are seeing all what the intelligences do, these tools do as output rather than better input to create better output ourselves. Um and I like I think that's important to me like when I was doing that like everyday 3 hours, like this is input to me and it's now up to me to like really um make better output from like all this new input that I have and like the ability to just take all this and see it at once, it's just phenomenal.","offset":3603,"duration":31},{"text":"Jack Dorsey: So having someone who's able to discern signal from noise and cool from not, relevant, you know, like there is, you know, this is highly overused right now, um the the taste thing is real and it's not just like I know what things look good together, it's more like do I have a point of view? Do I have a perspective and an opinionated drive to get it there and is it is it relevant, is it more relevant than than you know what else is out there?","offset":3634,"duration":29},{"text":"Jack Dorsey: And I think that's that's critical. That's what any founder is doing is like I'm building something that didn't exist in the world because I wanted to see it there. And and because it didn't exist is why I'm building it. And I think um right now you're seeing a lot of companies that are just copies of copies of copies of copies because it's easy instead of like what's your what's your point of view? Like what what is opinionated in this and like where where is it pushing the the boundaries and where is it uncomfortable?","offset":3663,"duration":34},{"text":"Brian Halligan: Mm. I think that's brilliant. It's a great place to end. Thank you both for coming on Long Strange Trip. I love the article you wrote, I think it's going to be game-changer for lots of companies. Appreciate you both.","offset":3697,"duration":9},{"text":"Jack Dorsey/Roelof Botha: Thank you. Thank you. Thank you, Brian. Thank you, Jack. Thank you.","offset":3706,"duration":4},{"text":"Brian Halligan: Hope you liked that. I really enjoyed speaking to him. He's an unusual Homo sapien and he's got some interesting thoughts. Um I think his ideas on how to transform the way you build a company and rethink the hierarchy, they kind of make sense to me and I feel like at some point in the future it's somewhat inevitable that this kind of thing is going to happen.","offset":3710,"duration":28},{"text":"Brian Halligan: And I sort of think of it as like when I grew up in my career, I worked at this company PTC in the 90s. It was very, very Manager Mode, uh very hierarchical, uh the power rested in the VPs essentially. Uh when I ran HubSpot, they didn't call it Founder Mode then but it was kind of Founder Mode. Instead of being a pyramid, it was flat and a lot of power was rested in the in the founder's hands.","offset":3738,"duration":25},{"text":"Brian Halligan: Um he sort of proposing the Dorsey Mode in my mind. He laughed about it when I said it, but I think of it as like what's next? And it's more like a circle than a really flat organization and the power rests in the kind of in the system and the system makes a lot of decisions and can react real time to the employees and the customers.","offset":3763,"duration":24},{"text":"Brian Halligan: But I think of Dorsey Mode as getting rid of the hierarchy all together, building basically the brain, getting the inputs right, and having it make a lot of the decisions that a hierarchy used to. I think he's onto something, I'm curious to see what you think. Um comment on Twitter, comment on on YouTube. I'm I'm curious about your thoughts on it. I think Jack would be curious too. He's in the very early innings of rolling this out and he's looking for feedback on it. Anyway, appreciate you all. Thanks for tuning in.","offset":3787,"duration":15}],"logs":[{"elapsed":"0.0","message":"Downloading audio from YouTube...","detail":null},{"elapsed":"0.0","message":"Trying download with browser cookies (ad-free)...","detail":null},{"elapsed":"30.9","message":"Audio downloaded (31.9 MB) in 30.9s","detail":"File size: 31.9 MB"},{"elapsed":"30.9","message":"Video title: Jack Dorsey: Every Company Can Now Be a Mini-AGI","detail":null},{"elapsed":"30.9","message":"Audio duration: 1:03:41 (63.7 min)","detail":null},{"elapsed":"30.9","message":"Uploading audio to Gemini File API...","detail":null},{"elapsed":"35.4","message":"Audio uploaded in 4.5s","detail":"File ref: files/mx4izzo8q2u1"},{"elapsed":"35.4","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"167.2","message":"Transcription complete in 136.2s","detail":"62071 chars received"},{"elapsed":"167.2","message":"Transcription tokens: 95,766 in / 15,172 out — cost: $0.0934","detail":null},{"elapsed":"167.2","message":"Parsed 158 transcript segments","detail":null},{"elapsed":"167.2","message":"Transcript coverage: 1:03:07 of 1:03:41 (99%) — OK","detail":null},{"elapsed":"167.2","message":"Total transcription time: 136.2s — 158 segments","detail":null},{"elapsed":"167.2","message":"Analyzing topics across 158 segments with gemini-3.1-pro-preview...","detail":null},{"elapsed":"219.4","message":"Topic analysis complete in 52.2s — found 16 topics","detail":null},{"elapsed":"219.4","message":"Analysis tokens: 16,039 in / 1,298 out / 5,753 thinking — cost: $0.1167","detail":null},{"elapsed":"219.4","message":"Pipeline finished in 219.4s — total cost: $0.2101 (134,028 tokens)","detail":null}]} \ No newline at end of file diff --git a/history/1775222175607-91up0VxYeNw.json b/history/1775222175607-91up0VxYeNw.json new file mode 100644 index 0000000..8348c1c --- /dev/null +++ b/history/1775222175607-91up0VxYeNw.json @@ -0,0 +1 @@ +{"id":"1775222175607-91up0VxYeNw","videoId":"91up0VxYeNw","url":"https://www.youtube.com/watch?v=91up0VxYeNw","title":"The Macro Chain Reaction of Oil Shocks | Bob Elliott","type":"youtube","topicCount":14,"segmentCount":76,"createdAt":"2026-04-03T13:16:15.607Z","uploadDate":"20260318","chunks":[{"title":"Teaser: Central Banks and Oil Shocks","summary":"A short teaser from Bob Elliott emphasizing that central banks never ease into an oil shock.","entries":[{"text":"Bob Elliott: Central banks never ease into an oil shock. It doesn't happen. When you have an oil shock, it's a very difficult scenario for, basically, policymakers to respond to because it both increases inflation and decreases real growth. I think a lot of people are getting ahead of themselves on talking about the disinflationary impact of an oil price rise. The first step is prices go up, real spending goes down, and that's where we're at right now. Shit has to get bad before someone does something about it in order to make it fine. People are kind of looking through the \"has to be bad\" in order for something to happen and just assuming everything will be okay forever. And that's just not how markets or economies, certainly, have worked over the last hundred years.","offset":0,"duration":50}],"startTime":0},{"title":"Sponsor Read and Financial Disclaimers","summary":"An ad read for the Digital Asset Summit and a standard financial disclaimer for the podcast.","entries":[{"text":"Host: Before we get started, a quick reminder that Blockworks' premier institutional conference, the Digital Asset Summit, is returning to New York City this March 24th to 26th. This year represents more than $4.2 trillion in assets under management with 150 speakers and 700 institutions attending. Speakers include SEC Chair Paul Atkins, CFTC Chair Michael Selig, Fed Governor Steven Moron, and Tether CEO Paolo Ardoino, alongside countless other executives, asset managers, regulators, and the core crypto infrastructure builders shaping the industry. If you want serious institutional-grade view of digital assets in 2024, Digital Asset Summit is where it happens. Use code Forward200 for $200 off and head to blockworks.co/events for more updates.","offset":50,"duration":48},{"text":"Host: Nothing said on Forward Guidance is a recommendation to buy or sell any investments or products. This podcast is for informational purposes only, and the views expressed by anyone on the show are solely their opinions, not financial advice or necessarily the views of Blockworks. Our hosts, guests, and the Blockworks team may hold positions in the companies, funds, or projects discussed. As always, investments in blockchain technology involve risk, terms and conditions apply. Do your own research.","offset":98,"duration":20}],"startTime":50},{"title":"Introduction and the Desavings-Driven Economy","summary":"The host introduces Bob Elliott, and they begin discussing the recent oil shock. Bob explains how recent economic growth was heavily reliant on household desaving, putting the economy on a knife's edge.","entries":[{"text":"Host: Alright everybody, welcome back to another episode of Forward Guidance, and joining me is one of my favorite repeat guests, Bob Elliott of Unlimited Funds. Always one of the best folks to get on to understand high-level macro frameworks and how it impacts the world, the economy, markets, everything in between. Bob, always great to have you on here.","offset":118,"duration":20},{"text":"Bob Elliott: Great, thanks so much for having me. I feel like when we tried to find a good time, which was a few weeks ago, you know, the world was a very different place than it is today, so we'll just roll with the punches and talk about what's going on.","offset":138,"duration":12},{"text":"Host: Yeah, honestly, probably silver lining that, yeah, we were planning to do this a few weeks ago and then it got delayed and now we're in a completely different situation, completely different conversation that we're going to have. So, at least that, yeah, we're in amongst it now. We're going to try and put on our geopolitical hats on a little bit and try to figure out how to understand everything that's going on with the Iran strike and how it impacts the global economy. So, you've been writing a lot on your Substack, which is really great. You've been writing a few different pieces on how to understand the context of this oil shock, of the Strait of Hormuz being closed and its impact on the global economy. And yeah, like I said, you're really excellent at these high-level macro frameworks. So I just want to understand, to you, when you see something like this happen and you contextualize it with where the global economy was heading into this supply shock, what does it look like? How are you understanding this and how does it relate to different oil shocks that we've had, like the 2022 one, and even the '08 one? Like, we had a pretty significant oil spike back then that led into a recession. So yeah, walk us through how do you digest something like this when it hits.","offset":150,"duration":65},{"text":"Bob Elliott: Yeah, well, I think we were coming into the beginning of the year experiencing something that I called the \"desavings-driven economy,\" which I sort of describe in contrast to what was, for many years post-COVID, an \"income-driven economy.\" And what I mean by desavings-driven economy was we started to see, basically, that spending continued to hold up and investment continued to hold up despite the fact that, you know, it took more desavings from households to keep that spending going as labor markets weakened, and more desavings from businesses to keep their pace of investment, particularly related to AI and such, alive.","offset":215,"duration":43},{"text":"Bob Elliott: And so, that's sort of the premise coming into this, which in many ways created an economy somewhat on a knife's edge. Meaning, if things had gone well and the government was pursuing modestly expansionary policy during the year and asset prices lifted a little bit, we were probably going to at least meet those sort of expectations, maybe even do a little bit better than the expectations that were out in markets at the outset of the year. I think the challenge is when you have an oil shock, it totally rewrites the conversation, and the reason why that is is because it's a very difficult scenario for policymakers to respond to because it both increases inflation and decreases real growth.","offset":258,"duration":43},{"text":"Bob Elliott: And as a result, you know, policymakers are kind of stuck in that sort of environment. And part of the challenge is when we were coming in, we had already had a lot of desavings sort of baked in the cake, and so there's not that much room for additional desavings to be applied in this circumstance. Doesn't mean it's impossible or the households won't desave at all, it's just we're in a very different environment now than we were, say, if this happened two or three years ago.","offset":301,"duration":32},{"text":"Bob Elliott: And so, I think the challenge is basically for households and in particular that were already spending more than they were earning, desaving relatively rapidly, now you've basically added another 1 to 1.5 percent price hike across their basket of goods to households that were already spending at only about 1.5 percent to wrap up the year in real terms. And that basically means household consumption is likely to fall to zero in real terms. And for a US economy that's so reliant on household consumption to keep it going, you know, zero real household consumption is pretty antithetical to expectations of growth of 2 to 3 percent that we've become used to.","offset":333,"duration":38}],"startTime":118},{"title":"Comparing Current Vulnerabilities to 2022","summary":"Bob contrasts the current environment with the 2022 oil shock, noting that while both periods had elevated inflation, the current shock is projected to last longer and put sustained pressure on real spending.","entries":[{"text":"Host: Hmm. Yeah, so contrasting that with 2022, you know, back then we had probably one of the hottest labor markets we've ever seen, like job openings were just absurd. And so, I'd love to just hear, back then when we had that one in 2022, it seems like we narrowly missed a recession on its own. You know, some people debate the semantics that we did see a little one, but whatever. The fact is that we came out of that somewhat unscathed and it feels to me like that is because, yeah, the labor market was in an excellent place. People were stuffed with cash from COVID-era stimulus. Companies had plenty of cash as well. Things were good and we narrowly avoided any sort of major issue there. I get the feeling that, yeah, consumers and households, like you said, are in a very different situation right now. So I'm curious, like when you see something like this oil shock that leads to higher prices and then lower consumption, how at risk are we today versus 2022?","offset":371,"duration":58},{"text":"Bob Elliott: Well, I think 2022 is really helpful because to study it helps you understand all the different mechanics. So what happened, while the magnitudes are slightly different, the mechanics are actually super similar in the sense of going into it, we had a period of elevated inflation, you know, that was sort of underlying the economy. Now, of course, that was related to COVID shocks and it was at a higher level versus today, which is essentially, you know, tariff-related plus in terms of inflation dynamics, and at a lower level. But that sort of kindling that existed of elevated inflation in the economy before the oil shock existed in both places.","offset":429,"duration":40},{"text":"Bob Elliott: In both places we had actually basically the same size oil shock, if anything this oil shock might be larger based upon just what's priced into the curve. So, you know, leaving aside whether you believe that that's good pricing or bad pricing or whatever, if you just basically take the curve as the market price and the future path of oil prices, this one's actually going to be a bit higher. The '22 oil shock largely resolved within a year, meaning it started at the beginning of the year, it peaked first in March and then in the summer and then it went back to basically where it was to start the year.","offset":469,"duration":37},{"text":"Bob Elliott: Right now, oil prices are projected to be 40 percent higher at the end of this year than they were at the beginning of this year, so that's a more extended oil shock. And in that 2022 case, basically what you saw was you saw inflation continued to be elevated. Fortunately, nominal earnings growth was relatively strong during that period, particularly when you add in all the transfer payments that were still sort of in the system. It allowed households to desave in response to maintain their real spending to some extent, but you still saw a reduction in real spending.","offset":506,"duration":32},{"text":"Bob Elliott: And so those in the '22 period, if you just think about each one of those levers, it was like household spending was strong nominally, right, so picked up nominally, financed by desaving, but real spending fell. And that's a perfect example of this combination that I'm describing that comes with an oil shock, which is both prices rise because people desave in order to keep up their real spending as much as they can, and real spending falls. So it's really hitting essentially both sides of the Fed's mandate.","offset":538,"duration":32},{"text":"Bob Elliott: And what did we see in response from the Fed? Now, of course, it was sort of the unlucky outcome that forced the Fed's hands to transition from basically the transitory narrative to the not transitory narrative and hike a whole heck of a lot in response. And today what we're seeing is, at least so far, we've seen an unwind of expectations of easing to basically neutral policy. I think the real question is actually the next set of policies likely to go higher because this will be enough to sort of force the Fed's hand. Certainly in neither case did we see the Fed cutting into an oil shock, right? We didn't see that at all, we saw the exact, at least back in 2022, we saw the exact opposite.","offset":570,"duration":44}],"startTime":371},{"title":"Contextualizing the 2008 Oil Shock","summary":"Bob clarifies that the 2008 economic collapse was primarily driven by severe US credit problems, whereas the oil price spike during that time was largely a byproduct of emerging market demand.","entries":[{"text":"Host: Hmm. Okay, so if we just think about like a matrix of the quality of the economy going into these shocks, so you have the current one, you have the 2022 one, I'd love for you to also unpack what happened in '08 and what was the quality of the economy back then going into it, because obviously that one we saw oil prices surge and then we just had, yeah, one of the greatest, you know, the Great Recession, and oil prices crashed afterwards, and you know there's this whole demand destruction era. So yeah, I'd love to add onto the matrix here of what did it look like in '08 and how did that sequence of events look like.","offset":614,"duration":34},{"text":"Bob Elliott: Well, I think interestingly in the '08 cycle, there was obviously a huge surge in oil prices, I mean more meaningfully than we're seeing right now, and it was predominantly driven at the time by a tight market intersecting with relatively strong demand from the emerging world. You know, for those folks who were back around that time, there was this whole idea of a global decoupling, right, that maybe the US was going to face some pain related to its housing problems, but globally we were going to decouple and it wasn't going to be a problem.","offset":648,"duration":40},{"text":"Bob Elliott: And the reality was at that time that sort of global growth narrative, or the narrative of the data outside the US, was quite strong. And it was only when the credit problems emerged in the US that created the second and third order consequences through the US, the economy, and the financial systems system that we saw a withdrawal of capital that basically crushed the emerging markets and created that reduction in demand. And so, in some ways I think people who are not sort of living through that period might confuse and confuse that period as indicating a strong US economy, or even that oil price rises were a meaningful driver of the economic slowing that occurred. And they were pretty marginal, it was pretty fast, it was pretty marginal, and the big story there was the credit problems, because I mean the credit problems were an like the credit problems nearly ruined the entire financial system. So I mean it was just like orders of magnitude more important for the economy in the US. But what it did highlight was just how tight that market was and how reliant it was on emerging markets who then were sort of the ancillary took sort of the ancillary hit from the US financial problems.","offset":688,"duration":74}],"startTime":614},{"title":"Economic Lessons from the 1970s","summary":"Drawing comparisons to the 1970s, Bob explains that while the magnitude of today's oil price increases is smaller, the macroeconomic linkages of inflation leading to economic pain remain consistent.","entries":[{"text":"Host: Got it. Last historical analog I want to ask you to contextualize the situation, and I know I'm really testing your financial history, but you've also written a lot, studied a lot of big macro cycles, so I feel confident you can answer this one too. The other one is, of course, the 1970s oil shock and what happened there. Obviously that one was the Great Inflation that also ensued in the '70s. So yeah, lastly, I'd just love to understand what was going on there and how is it different from today.","offset":762,"duration":30},{"text":"Bob Elliott: Yeah, I think in many ways the linkages are similar to today, but the magnitudes are very different. And so I think people often try and draw analogies of magnitude, and analogies of magnitude are kind of silly because, you know, for instance back then, oil prices went up 4 or 5x, right? Okay, so oil prices today are not going up 4 or 5x, so we're not likely to see the same sort of magnitude of inflationary pressures in the economy.","offset":792,"duration":32},{"text":"Bob Elliott: But what that doesn't mean is that the linkages are to be ignored. The linkages are the same exact linkages at different magnitude. And so in that case, you really had a lot of ways I talked about the sort of post-COVID period I think as being very similar to sort of that late '60s environment where you had sort of persistent inflation that was gradually creeping up, large fiscal expansion, you know, large deficits, not much credit driving the economy. That's why I think the late '60s is actually a really not much sort of household credit or corporate credit or borrowing driving the economy. A very income-driven expansion that eventually got to a point where we had an oil shock, and that oil shock created a lot of pain in the economy, created a lot of inflation and pain.","offset":824,"duration":50},{"text":"Bob Elliott: And then we had another oil shock on top of it, right? And so I think it's a good analogy in the sense of sort of similar kind of kindling that existed, meaning like inflation was a little too high for a little too long, an oil price rise occurred, and then that created basically the conditions that we saw in '22 and likely to see here, which is rising prices and weakening real demand and real activity, creating a challenging circumstance which sort of forces the central bank and the Fed into tightening, even though it's kind of an unpleasant tightening given the set of circumstances that existed.","offset":874,"duration":39}],"startTime":762},{"title":"Household Income, Spending, and Desaving","summary":"Bob breaks down the mechanics of household income and consumption, highlighting the risk that higher inflation will force households to reduce real spending if they pull back on desaving.","entries":[{"text":"Host: Cool. Alright, so coming back to present day, we have an economy, as you mentioned, in the last few months was largely driven by desaving, so savings rate coming lower. And yeah, I want to contextualize that with what you were seeing in the health of, yeah, the consumer in terms of its spending potential and and what the incomes were looking like going into this. And so you mentioned that the current oil market is pricing in a crisis that is more extended than the 2022 one leading into this situation of an economy that is on a knife's edge, largely held up by desavings. And when you put that all together, how do you see things playing out from here on?","offset":913,"duration":46},{"text":"Bob Elliott: Well, I think coming into this, it's good to just start with the baseline dynamic and sometimes macro folks will try and make an economy more complicated than it is. Like, the US economy is basically households earning money and spending. Like, to oversimplify. And then there's some other stuff that goes on, but that's basically what it is. And so when we were coming into this, you know, let's call it through January, household income growth was growing at about 3.5 percent or a touch better than that.","offset":959,"duration":30},{"text":"Bob Elliott: How was that growing? That was growing by essentially zero employment growth and 3.5 plus percent wage growth year over year per worker, right? That's how you get that nominal wage growth. US households were spending at about 5.5 percent coming into it, on a 5.5 percent growth coming into it. How do you close that gap between those two things? Well, essentially it's just mechanical: the savings rate has to fall in response to that, or transfers have to pick up, but transfers have largely been the same through this period.","offset":989,"duration":30},{"text":"Bob Elliott: And so what you see there is you basically see that gap widening and widening, which is the labor market's weakening gradually, no acute crisis, nothing crazy, just kind of gradually weakening, spending trying to stay up as much as possible driven by that that savings rate. And then if you think about if you sort of work through those numbers, we had 5 percent nominal spending growth in an environment of 3 percent inflation, which led to 2 percent real spending growth.","offset":1019,"duration":29},{"text":"Bob Elliott: Okay, now let's fast-forward oil, introduce the oil shock. How does that change things? Well, the labor markets aren't going to really change in the next day or two, it just labor markets are like watching paint dry. They just basically carry on as they are, right? I mean slowly but surely might move in one direction or another. But basically what we're going to see is 3.5 percent wage growth. Real spending growth, the question is, okay, let's just say they keep desaving. You keep that 5 percent nominal spending, but now we've gone from inflation environment of near three to a inflation environment that's going to have a 1 to 1.5 percent increase, and therefore real spending is going to fall.","offset":1048,"duration":40},{"text":"Bob Elliott: Those are the numbers, that's the sort of the household math problem, I always call it. If anything, the risk is that households might hold back on their desaving to some extent, right? What I just described is that they continue to desave, they continue their pace of desaving or the savings rate continues to fall. If you have an environment where stocks are falling or there's more uncertainty or more concern, you might actually see households no longer choose to increasingly desave and they might pull back on that and bring their spending in line with income.","offset":1088,"duration":33},{"text":"Bob Elliott: That would be the biggest risk, because then we'd go from a 5 percent nominal spending growth environment to say a 3.5 percent nominal spending growth environment, in the context of inflation that could be in the range of, you know, 4 percent, and that's where you get negative real spending growth. And that creates the second and third order effects of on labor markets and incomes in the future. But we're kind of getting ahead of ourselves on that. I think a lot of people are getting ahead of themselves on talking about the disinflationary impacts of an oil price rise. The first step is that prices go up, real spending goes down, and that's where we're at right now.","offset":1121,"duration":35}],"startTime":913},{"title":"Monetary Policy Response to Oil Shocks","summary":"Addressing monetary policy, Bob stresses that central banks do not cut rates during an oil shock because they must prioritize containing inflation and long-term expectations over supporting near-term growth.","entries":[{"text":"Host: Yeah, I think, yeah, that was a that was a nice little segue into how do people try to understand the sequence of events here, especially of something like an oil supply shock because you look at something like '08 and it's like, well, look, you know central banks should have looked through that and been like, oh shoot, there's this huge negative growth impulse on the other side of things. So now you have everybody skipping the first step and saying we got to go straight to cuts. And then contrasting that with what so far the reaction from central bank pricing has been, mostly hikes or or at least less cuts in the case of the US. So I'd just love to understand how you're thinking about monetary policy within this context. So you have, like I said, you know the US curve is we had a few cuts, now we're down to like one, maybe zero. Other countries are are looking at even priced beginning of their price in hikes. And people will look at that and say, hey look, we should we should move to the next phase of things, which is begin to think about cuts because this is obviously going to be really bad for growth. But obviously you need the first to get the second, and I feel like that just needs a better explanation. So I'd love for you to unpack that.","offset":1156,"duration":63},{"text":"Bob Elliott: Yeah, yeah, I mean I was I was writing last night having gotten a lot of comments about how oil shocks are deflationary or disinflationary. And the answer is like, of course, reducing household purchasing power through higher prices can be disinflationary, right? But the question is, how does that how does that system work? Because what has to happen is the first step is you have to have the prices rise, which eat into the real demand capability of the household, which then creates the slowing of labor market growth, which then hurts nominal incomes, which then reduces nominal spending that then has an effect on overall prices. Like that's the path.","offset":1219,"duration":46},{"text":"Bob Elliott: And as anyone who's watched labor markets through time knows, labor markets do not move that fast. Like they just labor markets are boring. We try our best, you know, the first Friday of every month to make this thing exciting. Like the answer the reality is they are boring as hell. And so, don't forget that, that they take forever to play out. You know, if we had a reduction in real, say tomorrow real household spending went down to zero or started to contract, it would probably be 9 or 12 months before we would fully feel that effect in the labor markets.","offset":1265,"duration":39},{"text":"Bob Elliott: And so, the point is you got to focus on the first on first things first here as in terms of how this is likely to play out. And the first step is you're going to have those price rises. And so central banks, I think part of the story going back to your sort of the core of your original question, which is how do central banks respond to this stuff? Like, central banks don't ease into oil shocks. Go back, look through all of time at all central banks and how they've responded every single time.","offset":1304,"duration":31},{"text":"Bob Elliott: Like, who cares if you think it's a good idea or not? Like, I don't really care as a market participant as a fiduciary like what you think how you think they should respond is an irrelevant a totally irrelevant way of thinking. A lot of people spend time on it, it's totally irrelevant, it's useless, it's distraction. Central banks never ease into an oil shock. Doesn't happen. And so what are we seeing right now? Well, we're seeing what you'd largely expect, which is if oil prices are going to get, I don't know, a 1 to 1.5 maybe 2 percent inflation pressure through through these economies, a little less in the US a little more in places like Europe and the UK. Yeah, that's probably worth, I don't know, a couple of hikes over the course of the next year, meaning either going from two cuts to zero or from no cuts to two hikes. That seems like about right if you look back through time.","offset":1335,"duration":57},{"text":"Bob Elliott: The challenge is that that will, as I think people understand, will put more pressure on growth, right? But it's the only solution that they have because the biggest risk here, the biggest risk is that these central banks, having accepted elevated inflation for five years post-COVID, ease into this oil shock and then what are they going to do? Like let long-term inflation expectations rise radically? There's no way they're going to let that happen. That would be incredibly risky for them to do. So they've got to nip this in the bud and make sure it doesn't have the second and third order effects through the prices on the economy.","offset":1392,"duration":36}],"startTime":1156},{"title":"Bond Market Pricing and Risk Premiums","summary":"Bob observes that long-term bond yields have shifted upward without a meaningful expansion in risk premiums, suggesting markets are underestimating the persistence of elevated inflation.","entries":[{"text":"Host: Yeah. I guess the big question that people are trying to sort out is how forward-looking and efficient is the bond market going to price this in. Because obviously, to your point, it makes sense for initially the short end of the bond market to begin to price in some hikes and some hawkishness. But you would expect potentially to see the long end begin to price in that, okay, well look we're having this this oil shock and central banks are hawkish into it. If we're looking at a 10-year bond, maybe it makes sense to start to price in some some negative growth outlooks into that. But so far we've seen the long end of the bond market sell off pretty significantly. I know you've been bearish bonds, bearish stocks. So I'd love for you to just explain how you think about how and when the bond market prices in these events and the sequences of them.","offset":1428,"duration":48},{"text":"Bob Elliott: Yeah, I mean the long end of of the bond market, so far what we've seen is sort of the curve move up, basically. As as this is happened, and if anything what we haven't seen is we haven't seen a real expansion in risk premiums in the bond market through this event. And I think that's interesting because if you just sort of go back to what what caused sort of a lot of the risk in the bond market, what caused the big lift in bonds, was basically this transition in the post-COVID period, I should say, is a transition from basically no one in the world ever considering that we would have elevated inflation ever again to a world where people are like, yeah, it can happen, you know we'll we'll have elevated inflation again. And that forced essentially, you know some risk premium getting put into the long end of the curve into bonds.","offset":1476,"duration":53},{"text":"Bob Elliott: You know, what I see now is that there's not people are sort of in that point where they're like, oh, they're sort of have have memory that inflation is likely to come down to central banks' targets over the course of the next year or two, not recognizing that, you know inflation shocks can often have a life of their own. Meaning like if you get an inflation shock into already elevated inflation, just go back to 2022, what did we see? We saw a persistence, we saw inflation above these central banks' targets for five years.","offset":1529,"duration":38},{"text":"Bob Elliott: Right, we were year one into something that has played out for the last five years. And that was with massive tightening, right, a massive rise in interest rates. Inflation is still elevated across every major developed economy relative to what central banks' targets are. So far we have not seen a recognition that this could extend the life of that dynamic. And so when I think about what's getting priced into the curve, what's notable is so far there has not been a meaningful expansion of risk premiums in the bond market that should create steepness in the curve, should create a sell-off in the curve beyond basically just reflecting the fact that we need tighter monetary policy.","offset":1567,"duration":41},{"text":"Bob Elliott: And to be clear, that's true across the totality of basically financial assets, financial assets in aggregate. Like, risk premiums have not risen very much despite the fact that we've we've entered possibly a new environment of elevated uncertainty, and and yet, you know it's hunky-dory when it comes to how most investors are viewing financial assets at this point.","offset":1608,"duration":26}],"startTime":1428},{"title":"Sequencing Linkages and Asset Drawdown Signals","summary":"Outlining the sequence of economic events, Bob explains that bond yields must rise enough (near 5% on the 10-year) to meaningfully drag down economic activity, a chronological step that overly optimistic investors are ignoring.","entries":[{"text":"Host: Hmm. So, so what's your checklist or signals to look for for when to flip from being concerned about a hawkish central bank and inflation to demand destruction and negative growth?","offset":1634,"duration":12},{"text":"Bob Elliott: Yeah, great question. And part of the story that creates the weakness in economic activity that comes from an oil shock is from the fact that interest rates rise. Again, important to recognize the ordering matters. Like first interest rates rise, then there's a drag on the economy. And so what you need to see is you need to see interest rates on the long end rise enough, and short end to some extent, but really on the long end, rise enough to start to create a hit to economic activity and also create a hit to asset prices, right? Through the discounting effect.","offset":1646,"duration":36},{"text":"Bob Elliott: And so when I look at the market right now, you know bond yields right now are basically where they've been for the last six or nine months, right? Bond yields are like boring, right, you know if you had just slept through the last six or nine months you'd be like, oh, we're basically where we were before. So we got to see bonds move to something that's going to be you know create a more meaningful hit to asset prices and the economy. So that's moving up towards the 5 range, say on tens, in order to get a more meaningful drag.","offset":1682,"duration":32},{"text":"Bob Elliott: Now I think part of the story here is that there's not a lot of the economy's very sensitive to those financial conditions, so I don't think you have to have bond yields go up to 6 or 7 or 8 or something like that to start to create the reversal. I think the cap is closer to 5 on tens and then at that point that's probably enough of a drag combined with all the other things that we talked about to create you know the subsequent downdraft in bonds.","offset":1714,"duration":23},{"text":"Bob Elliott: But again, the ordering, I know it's I know it's hard to it's easy to sort of get ahead of yourself on this thing but you've got to like linkages are ordered for a reason because they have that ordered effect on macroeconomic conditions. And so I think in some ways we've almost been like so it's like we have a a a cancer of, you know, it's like the cancer of QE that people are like, okay well then everything's going to be fine, right? So why should I ever worry about anything?","offset":1737,"duration":31},{"text":"Bob Elliott: And the answer is like shit has to get bad before someone does something about it in order to make it fine. And like people are kind of looking through the has to be bad in order for something to happen and just assuming everything will be okay forever and that's just not how markets or economies have certainly worked over the last hundred years.","offset":1768,"duration":22},{"text":"Host: Yeah, that's kind of funny. It just reminds me of, like, 2022 era when you were fighting the battle of everybody was, I don't know, freaking out about Sahm rules and a recession back then, you're like look like here where we are in the economy, the labor market's pretty good, like we need to see the sequence of events to occur before we get to a point where things are bad, and it sort of feels like a mirrored situation here.","offset":1790,"duration":18},{"text":"Bob Elliott: Right, right. That's right, that's right. That's, I mean maybe it's just kind of a boring old macro person who writes down this linkage and then this thing and then this thing, who's studied too many cycles, um who who thinks in ordered you know in order in terms of how these things play out. But um but I think that's part of the advantage. Part of the advantage and the alpha opportunities that exist is when people don't think in a disciplined way about the ordering and just rush to one direction or one narrative or one intuition and away from another.","offset":1808,"duration":37},{"text":"Bob Elliott: I mean look when we look at what's going on with the pricing right now, like financial the biggest thing if you think about sort of from those folks who are trading markets, what's the biggest thing that oil shocks create? They create a a hit on financial asset prices as risk premiums as the Fed tightens, central banks tighten, and risk premiums expand, right? That's that's what they do. Uh and you know there's a long track record related to that. And so far if you look at what's going on with asset prices in aggregate, stocks are basically flat and bonds are basically flat since this whole thing has started. Okay, so like that is that is the inconsistency there, which is that across asset markets people are just not recognizing one, you know, that the oil shock creates this effect and they're rushing to the resolution down the line.","offset":1845,"duration":50}],"startTime":1634},{"title":"Global Impacts and Currency Market Dynamics","summary":"The discussion shifts to how energy shocks disproportionately harm importing regions like Europe and Japan. Bob argues that these macroeconomic fundamentals will dictate currency strength more than relative monetary policy.","entries":[{"text":"Host: Well said. Alright, so I want to I want to zoom out to the global economy and how this oil shock is hitting different countries, how it gets reflected in their currencies, and really divide it between countries that are importing energy versus energy exporters. Because, you know, you have Asian Asian economies or the European economy that are that are big energy importers and especially acutely tied to the Strait of Hormuz versus a country like the US which is nearly energy independent, has very little exposure and demand and dependency on the Strait of Hormuz and what flows through it. And I would just love for you to unpack like how does that get reflected in the impact of those economies and then how does that get shown in these currencies between energy importers versus exporters.","offset":1895,"duration":99},{"text":"Bob Elliott: Yeah, I think it's been one of the most challenging circumstances this year is for the first whatever two months of the year, the overwhelming narrative in market action was you know rest of the world stocks doing well, certainly better than expectations and the US trying to keep up and the dollar being a bit soft and and then we have this this thing that happens that basically runs counter to like all of that underlying trend that had existed before.","offset":1994,"duration":34},{"text":"Bob Elliott: Um, you know I thought we were going to talk about, you know, de-dollarization when we uh when we originally scheduled this. Like it was going to be an update on that conversation from last year, and and it's very much the opposite for exactly the fundamental reasons that you described, which is look, Japan and Europe are in bad shape when it comes to big oil price rises. That's just all there is to it. They are the, you know across the developed world, they're very sensitive to these things. And other jurisdictions, particularly Canada and the US, are in a lot better shape to absorb these dynamics.","offset":2028,"duration":37},{"text":"Bob Elliott: And so it's not that surprising that we've seen one heck of an unwind of the foreign stock versus US stock story in response to this, as well as you know some strength in the dollar. It's not it's not a huge strength relative to what we've seen in the past, but it's still meaningful. And I think that's a combination of the fundamentals plus I think a lot of people got caught offsides, you know, people kind of all in on one direction and got whipped back in the other direction.","offset":2065,"duration":27},{"text":"Bob Elliott: Uh at this point, I look at things and I sort of say, look, broadly on a relative basis whether you're looking at when you're looking particularly when you're looking at stocks, like we've largely priced in the differential effect of of these of these dynamics. You know, Japanese and European stocks have come back a ton, basically erase their their gains for the year. The place in aggregate that doesn't make sense I'd say is around the aggregate pricing, meaning like aggregate stock prices across the global economy. You know those have come down a little bit, but particularly when you add in the US, you know we haven't seen a huge hit to aggregate asset prices in the way um that we, you know even we haven't seen a quarter of the hit to aggregate asset prices that we saw during the '22 episode even though the shock that we're seeing here is um certainly on par with, maybe even a bit a bit more significant.","offset":2092,"duration":52},{"text":"Bob Elliott: And then when it comes to currencies, you know the real risk in the currency market is um you know I think again it's largely played out as you'd expect from the fundamentals uh with the dollar being favored relative to these other currencies. Um it is uh you know part of the story of what has driven these foreign asset markets is you know a lot of US investors looking elsewhere outside the US for you know more cheaply valued asset markets. If that really starts to unwind, you could create another dollar squeeze scenario which would be very detrimental to asset prices in aggregate, somewhat foreign asset prices, but really asset prices in aggregate as sort of the dollar wins. And I know you guys have been talking about that um in your um in your weekly conversations. You know, the dollar shock we should not totally forget the the risk of a dollar shock uh in this whole story. Um and you start to think about that from a risk management perspective that you might have a lot of risk if the dollar, you know, pushes higher here.","offset":2144,"duration":67},{"text":"Host: Yeah. I mean like just if you if you take what's priced on central banks at face value right now it just seems crazy to me that we're in a situation where like we could see the Bank of England or something hiking while the Fed is still on on a cutting bias. Like does that is there any evidence of that even being like something that occurs? Like I just I can't even imagine the impact on on currencies if that actually plays out.","offset":2211,"duration":24},{"text":"Bob Elliott: Well, I think it comes down to um it comes down to where like the Bank of England or the ECB are going to be tightening aggressively in an environment where they're experiencing a hell of a external drag from rising energy prices, which is probably a way more important story for them than is the incremental monetary policy. I I think often people um overfocus on relative monetary policies as a story for exchange rate movements.","offset":2235,"duration":36},{"text":"Bob Elliott: Like, just think about it, let's say the Bank of England tomorrow was like we're going to we're going to tighten 100 basis points. Be like, wow, that's that's a that's a big tightening, right? Well, 100 basis points in yield terms is like a one-day standard deviation in currency price terms. Like if you just think about it from a total return perspective it like is irrelevant, right? It's why like central banks if they're trying to maintain a currency peg have to tighten you know to a thousand percent or something like that because you have to be on an annualized basis because you have to be at levels like that to change the underlying supply-demand dynamic of an exchange rate.","offset":2271,"duration":45},{"text":"Bob Elliott: And so, um I think probably the relative monetary policy is just going to matter a lot less than the relative macroeconomic effects of the rising energy prices and those are so disproportionately uh in favor of the US and Canada to some extent and and negative for uh Europe and Japan that that's just going to drive those currencies, that's going to be the much bigger driver of exchange rates ahead.","offset":2316,"duration":23}],"startTime":1895},{"title":"Gold, Commodities, and Portfolio Diversification","summary":"Bob explains that gold, as a financial asset, often drops alongside equities when interest rates rise. He advocates for holding actual commodities for true portfolio diversification during commodity shocks.","entries":[{"text":"Host: That's that's a good point, I like that. Um the other thing I'm trying to tease out here from you know if if we have this potential tail risk of a major dollar rally is contrasting that with the price action of potential for gold. Um, you know when I look at everything that's going on, you you would expect gold to rally pretty significantly here I imagine but uh since the shock it's it's been bleeding. Um I'm curious how do you think about that. Is it largely something getting caught up short-term in this dollar rally? Is it because positioning was so stretched into this shock or or how like how's gold playing out for you so far and where do you expect that to go from here?","offset":2339,"duration":40},{"text":"Bob Elliott: Well gold is a financial asset and so it's really important to keep that in mind. And so to the extent that there are, you know you're seeing elevated risk premiums across all financial assets, you would expect gold to be affected by it. And you know not only was gold is gold just sort of generally a financial asset and and to be clear if you go back and look at how it played out in '22, which I think is very helpful to see like gold rallies initially and then it sells off a lot, why? Because rates go up and all asset prices go down and gold is just one of many assets, financial assets, and so it takes a hit just like everything else.","offset":2379,"duration":33},{"text":"Bob Elliott: Um and so uh what's played out here, you know I'd probably put gold in the in the gold is like the macro equivalent of Japanese and European stocks for the equity allocators in the sense of everyone got bulled up on these things, they generally made a fair amount of money on those things through the first two months of the year, and then all of a sudden you have this shock everyone's bringing down their risk and you know gold takes a hit just like the European stocks and the and the um and the Japanese stocks.","offset":2412,"duration":31},{"text":"Bob Elliott: From a fundamentals perspective, you know it's a little bit better situation better situated than those assets, but it's still part of the sort of overextended uh positioning that came into this into this reversal. It's why when you take a step back, it's why um if you're building a well-diversified portfolio of assets, it's why you can't just you certainly can't just rely on bonds to be your diversifier to equities which we've learned, you but you can't also just rely on gold as a diversifier to your equities in addition to bonds because in an environment of elevated commodity prices, gold underperforms like all financial assets, which is why you have to have commodities in your portfolio, right?","offset":2443,"duration":48},{"text":"Bob Elliott: And when I ask people, you know had was doing some of these uh some CFA events uh a couple of weeks ago, I asked people, you know how many people have commodities in their portfolio, and it's crickets. And they're like, well, commodities, you know they don't go up as much as stocks, why would I ever hold them? Well, for this this is the reason why you would hold them, right? Because there are going to be times when all assets are doing poorly because commodity prices are surging and if you want to have some protection to your portfolio, that's why you have to have some commodity uh exposure within your portfolio.","offset":2491,"duration":33}],"startTime":2339},{"title":"Market Complacency and Geopolitical Realities","summary":"Bob warns that markets are suffering from collective amnesia and an overreliance on central bank easing. He emphasizes that the prolonged momentum and severe realities of geopolitical conflicts are not fully priced in.","entries":[{"text":"Host: Well said. Yeah, I just so I just want to bring this all together now in terms of when we look at all these asset classes and what they're reflecting. So you have the oil curve is pricing in something that's more significant than 2022. You have bond yields that are the same six months ago. You have equities that are largely flat, um seen small changes in currencies, pretty aggressive moves in in interest rate pricing from central banks. um gold's bled a little bit. Why why do you think there's such a contrast or tension between all those asset classes right now? Is it just like a positioning thing or people in complacency, are they expecting a, you know, a Taco-like Liberation Day? What's your what's your read high-level?","offset":2524,"duration":44},{"text":"Bob Elliott: Well, I think there's some collective amnesia about what's going on what happened in 2022. Um and part of that is I think folks have been sort of primed that there's always going to be the next easing and the next easing and the next easing. It's like, you know QE is like burn like there's all these burnouts on QE walking around, right? Thinking that ah they're just going to get the next, you know money hit coming.","offset":2568,"duration":30},{"text":"Bob Elliott: And this is very different from other shocks like this is very different from traditional growth shocks where the central bank where central banks are sort of all all well-positioned to ease into this into a growth shock into, you know an external growth shock of some sort. It's a totally different environment. And so, the combination of sort of that sort of uh forgetting conveniently forgetting about how '22 played out and then also you know this Taco stuff is I think people have really uh gone hook, line, and sinker, I mean for good empirical reason let's say, for why Taco you should always be betting on Taco and any fall is a is a good opportunity to buy.","offset":2598,"duration":42},{"text":"Bob Elliott: But again, a war is a is a very different thing than Liberation Day. Liberation Day was entirely determined by the you know mercurial views of a single person, meaning tomorrow you know on um the day after Liberation Day or five days after Liberation Day, like Trump could just change his mind and then magic, you know policy was different and and things like. He could he ran the Taco shop. Today the Taco shop is jointly run by two big parties but really like a dozen parties and if they don't all agree that we're getting Taco ahead then the then no Tacos will be served, to extend the analogy, right?","offset":2640,"duration":54},{"text":"Bob Elliott: Um and I think that's one of the challenges, like uh I think most people have not really spent a lot of time studying wars and their effects and things like that because I mean really for 75 years we basically had no wars, by and large. Like you know small wars, not no wars, but basically small wars that didn't matter that much. But wars have a momentum of their own. And we're seeing that in real time in terms of how wars have a momentum of their own. And so it's going to take much more than just a simple, you know Taco, for this thing to to get resolved anytime soon.","offset":2694,"duration":36},{"text":"Bob Elliott: And even and I think the oil market is really reflecting that because I mean people are down there counting the barrels, you know they're saying this many barrels in this under this circumstance and this circumstance and this circumstance. Um and when they pencil out all those barrels even assuming that there's a high probability that the US is just going to try and back down or have an off-ramp or something like that, you what is it like a 60 percent chance conflict ends within 45 days. That's a very high chance that a war ends within 45 days. Most wars take you know at a minimum years and often longer than years to play out.","offset":2730,"duration":30},{"text":"Bob Elliott: You know, when they add up all the barrels, they still have that curve where oil prices are 40 percent um above where they are today. The problem is, you know it doesn't look like people in the equity market and the bond market are actually counting the barrels. They're lazily thinking about Taco and QE and not thinking about the barrels and what the second and third order consequences are of those barrels. And so that is the gap and these gaps happen in markets. This is why you can generally generate alpha from a macro perspective because, you know not everyone is seeing the same reality and future reality at the same time. And so I think that's the gap we're seeing.","offset":2760,"duration":36}],"startTime":2524},{"title":"Conclusion and Where to Find Bob","summary":"The host thanks Bob for his insights, and Bob shares where listeners can find his macroeconomic research and follow his ETF strategies.","entries":[{"text":"Host: Amazing. Well Bob, that that's a great place to leave it. Some sage advice, appreciate a lot. And uh great to just walk through these things. You know, there's just endless whipsaws of news headlines right now, so I think it's it's a helpful mental model for everybody to digest and understand. Um so thank you for coming on and walking us through all that. I appreciate it. And where can where can folks go if they want to see more of your work in depth?","offset":2796,"duration":20},{"text":"Bob Elliott: Yeah, thanks so much for for having me. Uh if you're interested in my sort of ongoing macro commentary you can find me at BobUnlimited on anywhere you can find me, um or check out my Substack Nonconsensus, um which you noted earlier. Uh and if you want to learn more about uh my day job uh behind me, uh check out unlimitedetfs.com.","offset":2816,"duration":22},{"text":"Host: Awesome. Well thanks Bob, always great to have you on.","offset":2838,"duration":2},{"text":"Bob Elliott: Thanks for having me.","offset":2840,"duration":15}],"startTime":2796}],"entries":[{"text":"Bob Elliott: Central banks never ease into an oil shock. It doesn't happen. When you have an oil shock, it's a very difficult scenario for, basically, policymakers to respond to because it both increases inflation and decreases real growth. I think a lot of people are getting ahead of themselves on talking about the disinflationary impact of an oil price rise. The first step is prices go up, real spending goes down, and that's where we're at right now. Shit has to get bad before someone does something about it in order to make it fine. People are kind of looking through the \"has to be bad\" in order for something to happen and just assuming everything will be okay forever. And that's just not how markets or economies, certainly, have worked over the last hundred years.","offset":0,"duration":50},{"text":"Host: Before we get started, a quick reminder that Blockworks' premier institutional conference, the Digital Asset Summit, is returning to New York City this March 24th to 26th. This year represents more than $4.2 trillion in assets under management with 150 speakers and 700 institutions attending. Speakers include SEC Chair Paul Atkins, CFTC Chair Michael Selig, Fed Governor Steven Moron, and Tether CEO Paolo Ardoino, alongside countless other executives, asset managers, regulators, and the core crypto infrastructure builders shaping the industry. If you want serious institutional-grade view of digital assets in 2024, Digital Asset Summit is where it happens. Use code Forward200 for $200 off and head to blockworks.co/events for more updates.","offset":50,"duration":48},{"text":"Host: Nothing said on Forward Guidance is a recommendation to buy or sell any investments or products. This podcast is for informational purposes only, and the views expressed by anyone on the show are solely their opinions, not financial advice or necessarily the views of Blockworks. Our hosts, guests, and the Blockworks team may hold positions in the companies, funds, or projects discussed. As always, investments in blockchain technology involve risk, terms and conditions apply. Do your own research.","offset":98,"duration":20},{"text":"Host: Alright everybody, welcome back to another episode of Forward Guidance, and joining me is one of my favorite repeat guests, Bob Elliott of Unlimited Funds. Always one of the best folks to get on to understand high-level macro frameworks and how it impacts the world, the economy, markets, everything in between. Bob, always great to have you on here.","offset":118,"duration":20},{"text":"Bob Elliott: Great, thanks so much for having me. I feel like when we tried to find a good time, which was a few weeks ago, you know, the world was a very different place than it is today, so we'll just roll with the punches and talk about what's going on.","offset":138,"duration":12},{"text":"Host: Yeah, honestly, probably silver lining that, yeah, we were planning to do this a few weeks ago and then it got delayed and now we're in a completely different situation, completely different conversation that we're going to have. So, at least that, yeah, we're in amongst it now. We're going to try and put on our geopolitical hats on a little bit and try to figure out how to understand everything that's going on with the Iran strike and how it impacts the global economy. So, you've been writing a lot on your Substack, which is really great. You've been writing a few different pieces on how to understand the context of this oil shock, of the Strait of Hormuz being closed and its impact on the global economy. And yeah, like I said, you're really excellent at these high-level macro frameworks. So I just want to understand, to you, when you see something like this happen and you contextualize it with where the global economy was heading into this supply shock, what does it look like? How are you understanding this and how does it relate to different oil shocks that we've had, like the 2022 one, and even the '08 one? Like, we had a pretty significant oil spike back then that led into a recession. So yeah, walk us through how do you digest something like this when it hits.","offset":150,"duration":65},{"text":"Bob Elliott: Yeah, well, I think we were coming into the beginning of the year experiencing something that I called the \"desavings-driven economy,\" which I sort of describe in contrast to what was, for many years post-COVID, an \"income-driven economy.\" And what I mean by desavings-driven economy was we started to see, basically, that spending continued to hold up and investment continued to hold up despite the fact that, you know, it took more desavings from households to keep that spending going as labor markets weakened, and more desavings from businesses to keep their pace of investment, particularly related to AI and such, alive.","offset":215,"duration":43},{"text":"Bob Elliott: And so, that's sort of the premise coming into this, which in many ways created an economy somewhat on a knife's edge. Meaning, if things had gone well and the government was pursuing modestly expansionary policy during the year and asset prices lifted a little bit, we were probably going to at least meet those sort of expectations, maybe even do a little bit better than the expectations that were out in markets at the outset of the year. I think the challenge is when you have an oil shock, it totally rewrites the conversation, and the reason why that is is because it's a very difficult scenario for policymakers to respond to because it both increases inflation and decreases real growth.","offset":258,"duration":43},{"text":"Bob Elliott: And as a result, you know, policymakers are kind of stuck in that sort of environment. And part of the challenge is when we were coming in, we had already had a lot of desavings sort of baked in the cake, and so there's not that much room for additional desavings to be applied in this circumstance. Doesn't mean it's impossible or the households won't desave at all, it's just we're in a very different environment now than we were, say, if this happened two or three years ago.","offset":301,"duration":32},{"text":"Bob Elliott: And so, I think the challenge is basically for households and in particular that were already spending more than they were earning, desaving relatively rapidly, now you've basically added another 1 to 1.5 percent price hike across their basket of goods to households that were already spending at only about 1.5 percent to wrap up the year in real terms. And that basically means household consumption is likely to fall to zero in real terms. And for a US economy that's so reliant on household consumption to keep it going, you know, zero real household consumption is pretty antithetical to expectations of growth of 2 to 3 percent that we've become used to.","offset":333,"duration":38},{"text":"Host: Hmm. Yeah, so contrasting that with 2022, you know, back then we had probably one of the hottest labor markets we've ever seen, like job openings were just absurd. And so, I'd love to just hear, back then when we had that one in 2022, it seems like we narrowly missed a recession on its own. You know, some people debate the semantics that we did see a little one, but whatever. The fact is that we came out of that somewhat unscathed and it feels to me like that is because, yeah, the labor market was in an excellent place. People were stuffed with cash from COVID-era stimulus. Companies had plenty of cash as well. Things were good and we narrowly avoided any sort of major issue there. I get the feeling that, yeah, consumers and households, like you said, are in a very different situation right now. So I'm curious, like when you see something like this oil shock that leads to higher prices and then lower consumption, how at risk are we today versus 2022?","offset":371,"duration":58},{"text":"Bob Elliott: Well, I think 2022 is really helpful because to study it helps you understand all the different mechanics. So what happened, while the magnitudes are slightly different, the mechanics are actually super similar in the sense of going into it, we had a period of elevated inflation, you know, that was sort of underlying the economy. Now, of course, that was related to COVID shocks and it was at a higher level versus today, which is essentially, you know, tariff-related plus in terms of inflation dynamics, and at a lower level. But that sort of kindling that existed of elevated inflation in the economy before the oil shock existed in both places.","offset":429,"duration":40},{"text":"Bob Elliott: In both places we had actually basically the same size oil shock, if anything this oil shock might be larger based upon just what's priced into the curve. So, you know, leaving aside whether you believe that that's good pricing or bad pricing or whatever, if you just basically take the curve as the market price and the future path of oil prices, this one's actually going to be a bit higher. The '22 oil shock largely resolved within a year, meaning it started at the beginning of the year, it peaked first in March and then in the summer and then it went back to basically where it was to start the year.","offset":469,"duration":37},{"text":"Bob Elliott: Right now, oil prices are projected to be 40 percent higher at the end of this year than they were at the beginning of this year, so that's a more extended oil shock. And in that 2022 case, basically what you saw was you saw inflation continued to be elevated. Fortunately, nominal earnings growth was relatively strong during that period, particularly when you add in all the transfer payments that were still sort of in the system. It allowed households to desave in response to maintain their real spending to some extent, but you still saw a reduction in real spending.","offset":506,"duration":32},{"text":"Bob Elliott: And so those in the '22 period, if you just think about each one of those levers, it was like household spending was strong nominally, right, so picked up nominally, financed by desaving, but real spending fell. And that's a perfect example of this combination that I'm describing that comes with an oil shock, which is both prices rise because people desave in order to keep up their real spending as much as they can, and real spending falls. So it's really hitting essentially both sides of the Fed's mandate.","offset":538,"duration":32},{"text":"Bob Elliott: And what did we see in response from the Fed? Now, of course, it was sort of the unlucky outcome that forced the Fed's hands to transition from basically the transitory narrative to the not transitory narrative and hike a whole heck of a lot in response. And today what we're seeing is, at least so far, we've seen an unwind of expectations of easing to basically neutral policy. I think the real question is actually the next set of policies likely to go higher because this will be enough to sort of force the Fed's hand. Certainly in neither case did we see the Fed cutting into an oil shock, right? We didn't see that at all, we saw the exact, at least back in 2022, we saw the exact opposite.","offset":570,"duration":44},{"text":"Host: Hmm. Okay, so if we just think about like a matrix of the quality of the economy going into these shocks, so you have the current one, you have the 2022 one, I'd love for you to also unpack what happened in '08 and what was the quality of the economy back then going into it, because obviously that one we saw oil prices surge and then we just had, yeah, one of the greatest, you know, the Great Recession, and oil prices crashed afterwards, and you know there's this whole demand destruction era. So yeah, I'd love to add onto the matrix here of what did it look like in '08 and how did that sequence of events look like.","offset":614,"duration":34},{"text":"Bob Elliott: Well, I think interestingly in the '08 cycle, there was obviously a huge surge in oil prices, I mean more meaningfully than we're seeing right now, and it was predominantly driven at the time by a tight market intersecting with relatively strong demand from the emerging world. You know, for those folks who were back around that time, there was this whole idea of a global decoupling, right, that maybe the US was going to face some pain related to its housing problems, but globally we were going to decouple and it wasn't going to be a problem.","offset":648,"duration":40},{"text":"Bob Elliott: And the reality was at that time that sort of global growth narrative, or the narrative of the data outside the US, was quite strong. And it was only when the credit problems emerged in the US that created the second and third order consequences through the US, the economy, and the financial systems system that we saw a withdrawal of capital that basically crushed the emerging markets and created that reduction in demand. And so, in some ways I think people who are not sort of living through that period might confuse and confuse that period as indicating a strong US economy, or even that oil price rises were a meaningful driver of the economic slowing that occurred. And they were pretty marginal, it was pretty fast, it was pretty marginal, and the big story there was the credit problems, because I mean the credit problems were an like the credit problems nearly ruined the entire financial system. So I mean it was just like orders of magnitude more important for the economy in the US. But what it did highlight was just how tight that market was and how reliant it was on emerging markets who then were sort of the ancillary took sort of the ancillary hit from the US financial problems.","offset":688,"duration":74},{"text":"Host: Got it. Last historical analog I want to ask you to contextualize the situation, and I know I'm really testing your financial history, but you've also written a lot, studied a lot of big macro cycles, so I feel confident you can answer this one too. The other one is, of course, the 1970s oil shock and what happened there. Obviously that one was the Great Inflation that also ensued in the '70s. So yeah, lastly, I'd just love to understand what was going on there and how is it different from today.","offset":762,"duration":30},{"text":"Bob Elliott: Yeah, I think in many ways the linkages are similar to today, but the magnitudes are very different. And so I think people often try and draw analogies of magnitude, and analogies of magnitude are kind of silly because, you know, for instance back then, oil prices went up 4 or 5x, right? Okay, so oil prices today are not going up 4 or 5x, so we're not likely to see the same sort of magnitude of inflationary pressures in the economy.","offset":792,"duration":32},{"text":"Bob Elliott: But what that doesn't mean is that the linkages are to be ignored. The linkages are the same exact linkages at different magnitude. And so in that case, you really had a lot of ways I talked about the sort of post-COVID period I think as being very similar to sort of that late '60s environment where you had sort of persistent inflation that was gradually creeping up, large fiscal expansion, you know, large deficits, not much credit driving the economy. That's why I think the late '60s is actually a really not much sort of household credit or corporate credit or borrowing driving the economy. A very income-driven expansion that eventually got to a point where we had an oil shock, and that oil shock created a lot of pain in the economy, created a lot of inflation and pain.","offset":824,"duration":50},{"text":"Bob Elliott: And then we had another oil shock on top of it, right? And so I think it's a good analogy in the sense of sort of similar kind of kindling that existed, meaning like inflation was a little too high for a little too long, an oil price rise occurred, and then that created basically the conditions that we saw in '22 and likely to see here, which is rising prices and weakening real demand and real activity, creating a challenging circumstance which sort of forces the central bank and the Fed into tightening, even though it's kind of an unpleasant tightening given the set of circumstances that existed.","offset":874,"duration":39},{"text":"Host: Cool. Alright, so coming back to present day, we have an economy, as you mentioned, in the last few months was largely driven by desaving, so savings rate coming lower. And yeah, I want to contextualize that with what you were seeing in the health of, yeah, the consumer in terms of its spending potential and and what the incomes were looking like going into this. And so you mentioned that the current oil market is pricing in a crisis that is more extended than the 2022 one leading into this situation of an economy that is on a knife's edge, largely held up by desavings. And when you put that all together, how do you see things playing out from here on?","offset":913,"duration":46},{"text":"Bob Elliott: Well, I think coming into this, it's good to just start with the baseline dynamic and sometimes macro folks will try and make an economy more complicated than it is. Like, the US economy is basically households earning money and spending. Like, to oversimplify. And then there's some other stuff that goes on, but that's basically what it is. And so when we were coming into this, you know, let's call it through January, household income growth was growing at about 3.5 percent or a touch better than that.","offset":959,"duration":30},{"text":"Bob Elliott: How was that growing? That was growing by essentially zero employment growth and 3.5 plus percent wage growth year over year per worker, right? That's how you get that nominal wage growth. US households were spending at about 5.5 percent coming into it, on a 5.5 percent growth coming into it. How do you close that gap between those two things? Well, essentially it's just mechanical: the savings rate has to fall in response to that, or transfers have to pick up, but transfers have largely been the same through this period.","offset":989,"duration":30},{"text":"Bob Elliott: And so what you see there is you basically see that gap widening and widening, which is the labor market's weakening gradually, no acute crisis, nothing crazy, just kind of gradually weakening, spending trying to stay up as much as possible driven by that that savings rate. And then if you think about if you sort of work through those numbers, we had 5 percent nominal spending growth in an environment of 3 percent inflation, which led to 2 percent real spending growth.","offset":1019,"duration":29},{"text":"Bob Elliott: Okay, now let's fast-forward oil, introduce the oil shock. How does that change things? Well, the labor markets aren't going to really change in the next day or two, it just labor markets are like watching paint dry. They just basically carry on as they are, right? I mean slowly but surely might move in one direction or another. But basically what we're going to see is 3.5 percent wage growth. Real spending growth, the question is, okay, let's just say they keep desaving. You keep that 5 percent nominal spending, but now we've gone from inflation environment of near three to a inflation environment that's going to have a 1 to 1.5 percent increase, and therefore real spending is going to fall.","offset":1048,"duration":40},{"text":"Bob Elliott: Those are the numbers, that's the sort of the household math problem, I always call it. If anything, the risk is that households might hold back on their desaving to some extent, right? What I just described is that they continue to desave, they continue their pace of desaving or the savings rate continues to fall. If you have an environment where stocks are falling or there's more uncertainty or more concern, you might actually see households no longer choose to increasingly desave and they might pull back on that and bring their spending in line with income.","offset":1088,"duration":33},{"text":"Bob Elliott: That would be the biggest risk, because then we'd go from a 5 percent nominal spending growth environment to say a 3.5 percent nominal spending growth environment, in the context of inflation that could be in the range of, you know, 4 percent, and that's where you get negative real spending growth. And that creates the second and third order effects of on labor markets and incomes in the future. But we're kind of getting ahead of ourselves on that. I think a lot of people are getting ahead of themselves on talking about the disinflationary impacts of an oil price rise. The first step is that prices go up, real spending goes down, and that's where we're at right now.","offset":1121,"duration":35},{"text":"Host: Yeah, I think, yeah, that was a that was a nice little segue into how do people try to understand the sequence of events here, especially of something like an oil supply shock because you look at something like '08 and it's like, well, look, you know central banks should have looked through that and been like, oh shoot, there's this huge negative growth impulse on the other side of things. So now you have everybody skipping the first step and saying we got to go straight to cuts. And then contrasting that with what so far the reaction from central bank pricing has been, mostly hikes or or at least less cuts in the case of the US. So I'd just love to understand how you're thinking about monetary policy within this context. So you have, like I said, you know the US curve is we had a few cuts, now we're down to like one, maybe zero. Other countries are are looking at even priced beginning of their price in hikes. And people will look at that and say, hey look, we should we should move to the next phase of things, which is begin to think about cuts because this is obviously going to be really bad for growth. But obviously you need the first to get the second, and I feel like that just needs a better explanation. So I'd love for you to unpack that.","offset":1156,"duration":63},{"text":"Bob Elliott: Yeah, yeah, I mean I was I was writing last night having gotten a lot of comments about how oil shocks are deflationary or disinflationary. And the answer is like, of course, reducing household purchasing power through higher prices can be disinflationary, right? But the question is, how does that how does that system work? Because what has to happen is the first step is you have to have the prices rise, which eat into the real demand capability of the household, which then creates the slowing of labor market growth, which then hurts nominal incomes, which then reduces nominal spending that then has an effect on overall prices. Like that's the path.","offset":1219,"duration":46},{"text":"Bob Elliott: And as anyone who's watched labor markets through time knows, labor markets do not move that fast. Like they just labor markets are boring. We try our best, you know, the first Friday of every month to make this thing exciting. Like the answer the reality is they are boring as hell. And so, don't forget that, that they take forever to play out. You know, if we had a reduction in real, say tomorrow real household spending went down to zero or started to contract, it would probably be 9 or 12 months before we would fully feel that effect in the labor markets.","offset":1265,"duration":39},{"text":"Bob Elliott: And so, the point is you got to focus on the first on first things first here as in terms of how this is likely to play out. And the first step is you're going to have those price rises. And so central banks, I think part of the story going back to your sort of the core of your original question, which is how do central banks respond to this stuff? Like, central banks don't ease into oil shocks. Go back, look through all of time at all central banks and how they've responded every single time.","offset":1304,"duration":31},{"text":"Bob Elliott: Like, who cares if you think it's a good idea or not? Like, I don't really care as a market participant as a fiduciary like what you think how you think they should respond is an irrelevant a totally irrelevant way of thinking. A lot of people spend time on it, it's totally irrelevant, it's useless, it's distraction. Central banks never ease into an oil shock. Doesn't happen. And so what are we seeing right now? Well, we're seeing what you'd largely expect, which is if oil prices are going to get, I don't know, a 1 to 1.5 maybe 2 percent inflation pressure through through these economies, a little less in the US a little more in places like Europe and the UK. Yeah, that's probably worth, I don't know, a couple of hikes over the course of the next year, meaning either going from two cuts to zero or from no cuts to two hikes. That seems like about right if you look back through time.","offset":1335,"duration":57},{"text":"Bob Elliott: The challenge is that that will, as I think people understand, will put more pressure on growth, right? But it's the only solution that they have because the biggest risk here, the biggest risk is that these central banks, having accepted elevated inflation for five years post-COVID, ease into this oil shock and then what are they going to do? Like let long-term inflation expectations rise radically? There's no way they're going to let that happen. That would be incredibly risky for them to do. So they've got to nip this in the bud and make sure it doesn't have the second and third order effects through the prices on the economy.","offset":1392,"duration":36},{"text":"Host: Yeah. I guess the big question that people are trying to sort out is how forward-looking and efficient is the bond market going to price this in. Because obviously, to your point, it makes sense for initially the short end of the bond market to begin to price in some hikes and some hawkishness. But you would expect potentially to see the long end begin to price in that, okay, well look we're having this this oil shock and central banks are hawkish into it. If we're looking at a 10-year bond, maybe it makes sense to start to price in some some negative growth outlooks into that. But so far we've seen the long end of the bond market sell off pretty significantly. I know you've been bearish bonds, bearish stocks. So I'd love for you to just explain how you think about how and when the bond market prices in these events and the sequences of them.","offset":1428,"duration":48},{"text":"Bob Elliott: Yeah, I mean the long end of of the bond market, so far what we've seen is sort of the curve move up, basically. As as this is happened, and if anything what we haven't seen is we haven't seen a real expansion in risk premiums in the bond market through this event. And I think that's interesting because if you just sort of go back to what what caused sort of a lot of the risk in the bond market, what caused the big lift in bonds, was basically this transition in the post-COVID period, I should say, is a transition from basically no one in the world ever considering that we would have elevated inflation ever again to a world where people are like, yeah, it can happen, you know we'll we'll have elevated inflation again. And that forced essentially, you know some risk premium getting put into the long end of the curve into bonds.","offset":1476,"duration":53},{"text":"Bob Elliott: You know, what I see now is that there's not people are sort of in that point where they're like, oh, they're sort of have have memory that inflation is likely to come down to central banks' targets over the course of the next year or two, not recognizing that, you know inflation shocks can often have a life of their own. Meaning like if you get an inflation shock into already elevated inflation, just go back to 2022, what did we see? We saw a persistence, we saw inflation above these central banks' targets for five years.","offset":1529,"duration":38},{"text":"Bob Elliott: Right, we were year one into something that has played out for the last five years. And that was with massive tightening, right, a massive rise in interest rates. Inflation is still elevated across every major developed economy relative to what central banks' targets are. So far we have not seen a recognition that this could extend the life of that dynamic. And so when I think about what's getting priced into the curve, what's notable is so far there has not been a meaningful expansion of risk premiums in the bond market that should create steepness in the curve, should create a sell-off in the curve beyond basically just reflecting the fact that we need tighter monetary policy.","offset":1567,"duration":41},{"text":"Bob Elliott: And to be clear, that's true across the totality of basically financial assets, financial assets in aggregate. Like, risk premiums have not risen very much despite the fact that we've we've entered possibly a new environment of elevated uncertainty, and and yet, you know it's hunky-dory when it comes to how most investors are viewing financial assets at this point.","offset":1608,"duration":26},{"text":"Host: Hmm. So, so what's your checklist or signals to look for for when to flip from being concerned about a hawkish central bank and inflation to demand destruction and negative growth?","offset":1634,"duration":12},{"text":"Bob Elliott: Yeah, great question. And part of the story that creates the weakness in economic activity that comes from an oil shock is from the fact that interest rates rise. Again, important to recognize the ordering matters. Like first interest rates rise, then there's a drag on the economy. And so what you need to see is you need to see interest rates on the long end rise enough, and short end to some extent, but really on the long end, rise enough to start to create a hit to economic activity and also create a hit to asset prices, right? Through the discounting effect.","offset":1646,"duration":36},{"text":"Bob Elliott: And so when I look at the market right now, you know bond yields right now are basically where they've been for the last six or nine months, right? Bond yields are like boring, right, you know if you had just slept through the last six or nine months you'd be like, oh, we're basically where we were before. So we got to see bonds move to something that's going to be you know create a more meaningful hit to asset prices and the economy. So that's moving up towards the 5 range, say on tens, in order to get a more meaningful drag.","offset":1682,"duration":32},{"text":"Bob Elliott: Now I think part of the story here is that there's not a lot of the economy's very sensitive to those financial conditions, so I don't think you have to have bond yields go up to 6 or 7 or 8 or something like that to start to create the reversal. I think the cap is closer to 5 on tens and then at that point that's probably enough of a drag combined with all the other things that we talked about to create you know the subsequent downdraft in bonds.","offset":1714,"duration":23},{"text":"Bob Elliott: But again, the ordering, I know it's I know it's hard to it's easy to sort of get ahead of yourself on this thing but you've got to like linkages are ordered for a reason because they have that ordered effect on macroeconomic conditions. And so I think in some ways we've almost been like so it's like we have a a a cancer of, you know, it's like the cancer of QE that people are like, okay well then everything's going to be fine, right? So why should I ever worry about anything?","offset":1737,"duration":31},{"text":"Bob Elliott: And the answer is like shit has to get bad before someone does something about it in order to make it fine. And like people are kind of looking through the has to be bad in order for something to happen and just assuming everything will be okay forever and that's just not how markets or economies have certainly worked over the last hundred years.","offset":1768,"duration":22},{"text":"Host: Yeah, that's kind of funny. It just reminds me of, like, 2022 era when you were fighting the battle of everybody was, I don't know, freaking out about Sahm rules and a recession back then, you're like look like here where we are in the economy, the labor market's pretty good, like we need to see the sequence of events to occur before we get to a point where things are bad, and it sort of feels like a mirrored situation here.","offset":1790,"duration":18},{"text":"Bob Elliott: Right, right. That's right, that's right. That's, I mean maybe it's just kind of a boring old macro person who writes down this linkage and then this thing and then this thing, who's studied too many cycles, um who who thinks in ordered you know in order in terms of how these things play out. But um but I think that's part of the advantage. Part of the advantage and the alpha opportunities that exist is when people don't think in a disciplined way about the ordering and just rush to one direction or one narrative or one intuition and away from another.","offset":1808,"duration":37},{"text":"Bob Elliott: I mean look when we look at what's going on with the pricing right now, like financial the biggest thing if you think about sort of from those folks who are trading markets, what's the biggest thing that oil shocks create? They create a a hit on financial asset prices as risk premiums as the Fed tightens, central banks tighten, and risk premiums expand, right? That's that's what they do. Uh and you know there's a long track record related to that. And so far if you look at what's going on with asset prices in aggregate, stocks are basically flat and bonds are basically flat since this whole thing has started. Okay, so like that is that is the inconsistency there, which is that across asset markets people are just not recognizing one, you know, that the oil shock creates this effect and they're rushing to the resolution down the line.","offset":1845,"duration":50},{"text":"Host: Well said. Alright, so I want to I want to zoom out to the global economy and how this oil shock is hitting different countries, how it gets reflected in their currencies, and really divide it between countries that are importing energy versus energy exporters. Because, you know, you have Asian Asian economies or the European economy that are that are big energy importers and especially acutely tied to the Strait of Hormuz versus a country like the US which is nearly energy independent, has very little exposure and demand and dependency on the Strait of Hormuz and what flows through it. And I would just love for you to unpack like how does that get reflected in the impact of those economies and then how does that get shown in these currencies between energy importers versus exporters.","offset":1895,"duration":99},{"text":"Bob Elliott: Yeah, I think it's been one of the most challenging circumstances this year is for the first whatever two months of the year, the overwhelming narrative in market action was you know rest of the world stocks doing well, certainly better than expectations and the US trying to keep up and the dollar being a bit soft and and then we have this this thing that happens that basically runs counter to like all of that underlying trend that had existed before.","offset":1994,"duration":34},{"text":"Bob Elliott: Um, you know I thought we were going to talk about, you know, de-dollarization when we uh when we originally scheduled this. Like it was going to be an update on that conversation from last year, and and it's very much the opposite for exactly the fundamental reasons that you described, which is look, Japan and Europe are in bad shape when it comes to big oil price rises. That's just all there is to it. They are the, you know across the developed world, they're very sensitive to these things. And other jurisdictions, particularly Canada and the US, are in a lot better shape to absorb these dynamics.","offset":2028,"duration":37},{"text":"Bob Elliott: And so it's not that surprising that we've seen one heck of an unwind of the foreign stock versus US stock story in response to this, as well as you know some strength in the dollar. It's not it's not a huge strength relative to what we've seen in the past, but it's still meaningful. And I think that's a combination of the fundamentals plus I think a lot of people got caught offsides, you know, people kind of all in on one direction and got whipped back in the other direction.","offset":2065,"duration":27},{"text":"Bob Elliott: Uh at this point, I look at things and I sort of say, look, broadly on a relative basis whether you're looking at when you're looking particularly when you're looking at stocks, like we've largely priced in the differential effect of of these of these dynamics. You know, Japanese and European stocks have come back a ton, basically erase their their gains for the year. The place in aggregate that doesn't make sense I'd say is around the aggregate pricing, meaning like aggregate stock prices across the global economy. You know those have come down a little bit, but particularly when you add in the US, you know we haven't seen a huge hit to aggregate asset prices in the way um that we, you know even we haven't seen a quarter of the hit to aggregate asset prices that we saw during the '22 episode even though the shock that we're seeing here is um certainly on par with, maybe even a bit a bit more significant.","offset":2092,"duration":52},{"text":"Bob Elliott: And then when it comes to currencies, you know the real risk in the currency market is um you know I think again it's largely played out as you'd expect from the fundamentals uh with the dollar being favored relative to these other currencies. Um it is uh you know part of the story of what has driven these foreign asset markets is you know a lot of US investors looking elsewhere outside the US for you know more cheaply valued asset markets. If that really starts to unwind, you could create another dollar squeeze scenario which would be very detrimental to asset prices in aggregate, somewhat foreign asset prices, but really asset prices in aggregate as sort of the dollar wins. And I know you guys have been talking about that um in your um in your weekly conversations. You know, the dollar shock we should not totally forget the the risk of a dollar shock uh in this whole story. Um and you start to think about that from a risk management perspective that you might have a lot of risk if the dollar, you know, pushes higher here.","offset":2144,"duration":67},{"text":"Host: Yeah. I mean like just if you if you take what's priced on central banks at face value right now it just seems crazy to me that we're in a situation where like we could see the Bank of England or something hiking while the Fed is still on on a cutting bias. Like does that is there any evidence of that even being like something that occurs? Like I just I can't even imagine the impact on on currencies if that actually plays out.","offset":2211,"duration":24},{"text":"Bob Elliott: Well, I think it comes down to um it comes down to where like the Bank of England or the ECB are going to be tightening aggressively in an environment where they're experiencing a hell of a external drag from rising energy prices, which is probably a way more important story for them than is the incremental monetary policy. I I think often people um overfocus on relative monetary policies as a story for exchange rate movements.","offset":2235,"duration":36},{"text":"Bob Elliott: Like, just think about it, let's say the Bank of England tomorrow was like we're going to we're going to tighten 100 basis points. Be like, wow, that's that's a that's a big tightening, right? Well, 100 basis points in yield terms is like a one-day standard deviation in currency price terms. Like if you just think about it from a total return perspective it like is irrelevant, right? It's why like central banks if they're trying to maintain a currency peg have to tighten you know to a thousand percent or something like that because you have to be on an annualized basis because you have to be at levels like that to change the underlying supply-demand dynamic of an exchange rate.","offset":2271,"duration":45},{"text":"Bob Elliott: And so, um I think probably the relative monetary policy is just going to matter a lot less than the relative macroeconomic effects of the rising energy prices and those are so disproportionately uh in favor of the US and Canada to some extent and and negative for uh Europe and Japan that that's just going to drive those currencies, that's going to be the much bigger driver of exchange rates ahead.","offset":2316,"duration":23},{"text":"Host: That's that's a good point, I like that. Um the other thing I'm trying to tease out here from you know if if we have this potential tail risk of a major dollar rally is contrasting that with the price action of potential for gold. Um, you know when I look at everything that's going on, you you would expect gold to rally pretty significantly here I imagine but uh since the shock it's it's been bleeding. Um I'm curious how do you think about that. Is it largely something getting caught up short-term in this dollar rally? Is it because positioning was so stretched into this shock or or how like how's gold playing out for you so far and where do you expect that to go from here?","offset":2339,"duration":40},{"text":"Bob Elliott: Well gold is a financial asset and so it's really important to keep that in mind. And so to the extent that there are, you know you're seeing elevated risk premiums across all financial assets, you would expect gold to be affected by it. And you know not only was gold is gold just sort of generally a financial asset and and to be clear if you go back and look at how it played out in '22, which I think is very helpful to see like gold rallies initially and then it sells off a lot, why? Because rates go up and all asset prices go down and gold is just one of many assets, financial assets, and so it takes a hit just like everything else.","offset":2379,"duration":33},{"text":"Bob Elliott: Um and so uh what's played out here, you know I'd probably put gold in the in the gold is like the macro equivalent of Japanese and European stocks for the equity allocators in the sense of everyone got bulled up on these things, they generally made a fair amount of money on those things through the first two months of the year, and then all of a sudden you have this shock everyone's bringing down their risk and you know gold takes a hit just like the European stocks and the and the um and the Japanese stocks.","offset":2412,"duration":31},{"text":"Bob Elliott: From a fundamentals perspective, you know it's a little bit better situation better situated than those assets, but it's still part of the sort of overextended uh positioning that came into this into this reversal. It's why when you take a step back, it's why um if you're building a well-diversified portfolio of assets, it's why you can't just you certainly can't just rely on bonds to be your diversifier to equities which we've learned, you but you can't also just rely on gold as a diversifier to your equities in addition to bonds because in an environment of elevated commodity prices, gold underperforms like all financial assets, which is why you have to have commodities in your portfolio, right?","offset":2443,"duration":48},{"text":"Bob Elliott: And when I ask people, you know had was doing some of these uh some CFA events uh a couple of weeks ago, I asked people, you know how many people have commodities in their portfolio, and it's crickets. And they're like, well, commodities, you know they don't go up as much as stocks, why would I ever hold them? Well, for this this is the reason why you would hold them, right? Because there are going to be times when all assets are doing poorly because commodity prices are surging and if you want to have some protection to your portfolio, that's why you have to have some commodity uh exposure within your portfolio.","offset":2491,"duration":33},{"text":"Host: Well said. Yeah, I just so I just want to bring this all together now in terms of when we look at all these asset classes and what they're reflecting. So you have the oil curve is pricing in something that's more significant than 2022. You have bond yields that are the same six months ago. You have equities that are largely flat, um seen small changes in currencies, pretty aggressive moves in in interest rate pricing from central banks. um gold's bled a little bit. Why why do you think there's such a contrast or tension between all those asset classes right now? Is it just like a positioning thing or people in complacency, are they expecting a, you know, a Taco-like Liberation Day? What's your what's your read high-level?","offset":2524,"duration":44},{"text":"Bob Elliott: Well, I think there's some collective amnesia about what's going on what happened in 2022. Um and part of that is I think folks have been sort of primed that there's always going to be the next easing and the next easing and the next easing. It's like, you know QE is like burn like there's all these burnouts on QE walking around, right? Thinking that ah they're just going to get the next, you know money hit coming.","offset":2568,"duration":30},{"text":"Bob Elliott: And this is very different from other shocks like this is very different from traditional growth shocks where the central bank where central banks are sort of all all well-positioned to ease into this into a growth shock into, you know an external growth shock of some sort. It's a totally different environment. And so, the combination of sort of that sort of uh forgetting conveniently forgetting about how '22 played out and then also you know this Taco stuff is I think people have really uh gone hook, line, and sinker, I mean for good empirical reason let's say, for why Taco you should always be betting on Taco and any fall is a is a good opportunity to buy.","offset":2598,"duration":42},{"text":"Bob Elliott: But again, a war is a is a very different thing than Liberation Day. Liberation Day was entirely determined by the you know mercurial views of a single person, meaning tomorrow you know on um the day after Liberation Day or five days after Liberation Day, like Trump could just change his mind and then magic, you know policy was different and and things like. He could he ran the Taco shop. Today the Taco shop is jointly run by two big parties but really like a dozen parties and if they don't all agree that we're getting Taco ahead then the then no Tacos will be served, to extend the analogy, right?","offset":2640,"duration":54},{"text":"Bob Elliott: Um and I think that's one of the challenges, like uh I think most people have not really spent a lot of time studying wars and their effects and things like that because I mean really for 75 years we basically had no wars, by and large. Like you know small wars, not no wars, but basically small wars that didn't matter that much. But wars have a momentum of their own. And we're seeing that in real time in terms of how wars have a momentum of their own. And so it's going to take much more than just a simple, you know Taco, for this thing to to get resolved anytime soon.","offset":2694,"duration":36},{"text":"Bob Elliott: And even and I think the oil market is really reflecting that because I mean people are down there counting the barrels, you know they're saying this many barrels in this under this circumstance and this circumstance and this circumstance. Um and when they pencil out all those barrels even assuming that there's a high probability that the US is just going to try and back down or have an off-ramp or something like that, you what is it like a 60 percent chance conflict ends within 45 days. That's a very high chance that a war ends within 45 days. Most wars take you know at a minimum years and often longer than years to play out.","offset":2730,"duration":30},{"text":"Bob Elliott: You know, when they add up all the barrels, they still have that curve where oil prices are 40 percent um above where they are today. The problem is, you know it doesn't look like people in the equity market and the bond market are actually counting the barrels. They're lazily thinking about Taco and QE and not thinking about the barrels and what the second and third order consequences are of those barrels. And so that is the gap and these gaps happen in markets. This is why you can generally generate alpha from a macro perspective because, you know not everyone is seeing the same reality and future reality at the same time. And so I think that's the gap we're seeing.","offset":2760,"duration":36},{"text":"Host: Amazing. Well Bob, that that's a great place to leave it. Some sage advice, appreciate a lot. And uh great to just walk through these things. You know, there's just endless whipsaws of news headlines right now, so I think it's it's a helpful mental model for everybody to digest and understand. Um so thank you for coming on and walking us through all that. I appreciate it. And where can where can folks go if they want to see more of your work in depth?","offset":2796,"duration":20},{"text":"Bob Elliott: Yeah, thanks so much for for having me. Uh if you're interested in my sort of ongoing macro commentary you can find me at BobUnlimited on anywhere you can find me, um or check out my Substack Nonconsensus, um which you noted earlier. Uh and if you want to learn more about uh my day job uh behind me, uh check out unlimitedetfs.com.","offset":2816,"duration":22},{"text":"Host: Awesome. Well thanks Bob, always great to have you on.","offset":2838,"duration":2},{"text":"Bob Elliott: Thanks for having me.","offset":2840,"duration":15}],"logs":[{"elapsed":"0.0","message":"Downloading audio from YouTube...","detail":null},{"elapsed":"0.0","message":"Trying download with browser cookies (ad-free)...","detail":null},{"elapsed":"26.3","message":"Audio downloaded (23.4 MB) in 26.3s","detail":"File size: 23.4 MB"},{"elapsed":"26.3","message":"Video title: The Macro Chain Reaction of Oil Shocks | Bob Elliott","detail":null},{"elapsed":"26.4","message":"Audio duration: 47:32 (47.5 min)","detail":null},{"elapsed":"26.4","message":"Uploading audio to Gemini File API...","detail":null},{"elapsed":"30.0","message":"Audio uploaded in 3.6s","detail":"File ref: files/pdnyi5bd5lom"},{"elapsed":"30.0","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"89.8","message":"Transcription complete in 63.4s","detail":"47568 chars received"},{"elapsed":"89.8","message":"Transcription tokens: 71,538 in / 10,939 out — cost: $0.0686","detail":null},{"elapsed":"89.8","message":"Parsed 76 transcript segments","detail":null},{"elapsed":"89.8","message":"Transcript coverage: 47:20 of 47:32 (100%) — OK","detail":null},{"elapsed":"89.8","message":"Total transcription time: 63.4s — 76 segments","detail":null},{"elapsed":"89.8","message":"Analyzing topics across 76 segments with gemini-3.1-pro-preview...","detail":null},{"elapsed":"131.7","message":"Topic analysis complete in 41.9s — found 14 topics","detail":null},{"elapsed":"131.7","message":"Analysis tokens: 11,495 in / 1,099 out / 4,191 thinking — cost: $0.0865","detail":null},{"elapsed":"131.7","message":"Pipeline finished in 131.7s — total cost: $0.1551 (99,262 tokens)","detail":null}]} \ No newline at end of file diff --git a/history/1775222522683-lTuS7Ns8cZg.json b/history/1775222522683-lTuS7Ns8cZg.json new file mode 100644 index 0000000..74b7632 --- /dev/null +++ b/history/1775222522683-lTuS7Ns8cZg.json @@ -0,0 +1 @@ +{"id":"1775222522683-lTuS7Ns8cZg","videoId":"lTuS7Ns8cZg","url":"https://www.youtube.com/watch?v=lTuS7Ns8cZg","title":"NVIDIA Predicts $1TRN in Revenue: Everything You Need to Know From GTC & Anduril Lands $20B Contract","type":"youtube","topicCount":7,"segmentCount":282,"createdAt":"2026-04-03T13:22:02.683Z","uploadDate":"20260319","chunks":[{"title":"Podcast Intro and Teasers","summary":"The hosts preview the key topics of the episode, including Nvidia's monumental growth, tech layoffs, and Travis Kalanick's legacy at Uber.","entries":[{"text":"Jason: Man, this is summer at Nvidia. I mean, they're on fire on everything.","offset":0,"duration":4},{"text":"Rory: These are unprecedented levels of CapEx spend and now we're forecasting them to keep going for four or five years.","offset":4,"duration":5},{"text":"Host: What are we discussing this week? GTC, what happened with Nvidia, Anduril's $20 billion dollar contract, then finally why $50 to $100 million dollar seed funds could be the worst performing size fund of this vintage.","offset":9,"duration":12},{"text":"Jason: I think Travis' Uber would be a trillion dollar company today because it'd be five years ahead of where it is today.","offset":21,"duration":5},{"text":"Rory: Wall Street is simple: if you give them growth, they leave you alone, if you don't give them growth, you better give them profitability. And if you don't give them either, they're going to bust your chops.","offset":26,"duration":6},{"text":"Rory: And today compute eats jobs.","offset":32,"duration":3},{"text":"Jason: You do not need to be technical to win with AI agents in Q2 of '26. You do not need to be even 1% technical.","offset":35,"duration":6},{"text":"Rory: The bigger your fund size, the more you have to be a power law junkie. There's no investment opportunity so good that excess capital won't destroy it.","offset":41,"duration":7},{"text":"Jason: You're going to get laid off because you're not going to matter.","offset":48,"duration":16}],"startTime":0},{"title":"Nvidia's GTC and AI CapEx","summary":"The hosts unpack Nvidia's massive revenue forecasts and the staggering levels of CapEx investment required to support AI infrastructure. They debate whether Nvidia's cumulative $1 trillion demand projection is realistic and how it impacts the market.","entries":[{"text":"Host: Guys, I'm so excited for this. We were just talking about where to start, so much news. And Jason, I think you're absolutely right, it's very important to start with GTC and Jensen and data centers in space. Obviously, Rory said, \"no, not going to happen,\" but maybe it does. How did we think about the data centers in space and last night GTC, Jason?","offset":64,"duration":27},{"text":"Jason: To me, I mean listen, the interesting thing, which you don't even have to watch anything, you just have to look at the Twitter stream is the sheer sense of energy and momentum and confidence there. And the confidence to do things—not only talk about data centers in space, but launch things like NeMo-Cloud, which are their version of Open-Cloud, to launch a partnership with Thinking Machines and others for their own open-source LLMs.","offset":91,"duration":26},{"text":"Jason: I mean, they're just going for it, right? And you can just smell the—I mean, obviously Nvidia is a pretty good stock and a pretty good company at the center of AI, but you can just smell the companies in decline, you can smell the companies struggling. You can smell OpenAI struggling right now. You can just smell it. You can smell the code red and the fact that they said yesterday, \"we have to concentrate on enterprise, we have to stop side projects.\"","offset":117,"duration":25},{"text":"Jason: It's not a—I mean, anytime you've worked with any startups you see the seasons, right? But man, this is summer at Nvidia. I mean, they're on fire on everything. And all the things where you see—and they're at risk, they're at risk from their customers using, um, TPUs from, uh, from Google and from Amazon. But man, everything from already integrating Groq to data centers in space to crossing a trillion dollars in bookings to NeMo-Cloud, it just feels like a company firing on about 13 cylinders.","offset":142,"duration":31},{"text":"Rory: Yeah, so I'll come back to your mis-portrayal of what I said later, Jason. But let's hit the main point because it's all about—in the end, it's all about the money, right? Super interesting kind of counterpoint on something. On the one hand, you had an extraordinarily aggressive number, a trillion dollars in revenue. On the other hand, the stock moved less than 1%. Why?","offset":173,"duration":22},{"text":"Host: It was already priced in.","offset":195,"duration":1},{"text":"Rory: Already priced in. And if you start parsing it out, I think what happened is as simple as this: If you look at the forecast, company did $215 billion dollars in revenue last fiscal year, up from 130 I think the prior year. You know, the forecast is mid-300s next year. So the soundbite was 25 and—sorry, next year I should say this year to be precise. The soundbite was half a trillion dollars of demand over the next two years, and that was a soundbite a year ago.","offset":196,"duration":29},{"text":"Rory: And now the soundbite is a trillion dollars in demand, but if you listen carefully, it includes '27. And lo and behold, if you go and check the analyst forecast for '27, it's in the mid-400s. So it turns out if you add 500 and 400 and then you apply a salesman's round-up, you get to a trillion dollars.","offset":225,"duration":15},{"text":"Rory: Another way of translating that wonderful amazing number of a trillion dollars is the analyst forecasts for the next two or three years look roughly right. So once the analyst processed that, the stock said, \"yep, nothing—no new information here.\" Which is just fascinating because what it says is, you know—this is a company by the way, for context, four years ago was doing $20 billion dollars a year.","offset":240,"duration":22},{"text":"Rory: Maybe five years ago now, actually—well, yeah, five years ago because we're in '26. $20 billion dollars a year. Last year did $215 billion dollars, 10x growth over four years. You know, about under 60% growth last year, forecasting 60% growth this year, and attenuating down to 20s, 30% growth in a couple of years.","offset":262,"duration":24},{"text":"Rory: So on one level not insane relative to past performance being predictive. If you have a company that grows 10x, saying it's only going to go 20, 30, 40% over the next couple of years doesn't seem unreasonable. But what it does imply is a massive level of CapEx continuing for the next four or five years.","offset":286,"duration":15},{"text":"Rory: That's fundamentally the bet. That's the big statement that came out here is: we think this level of CapEx investment is going to keep going for the next four or five years, we're reaffirming our estimates, and um, no—none of my customers are going to blink on our spend. That's the takeaway.","offset":301,"duration":17},{"text":"Host: Jason, I constantly go back to something that you said, which is we're going to see inference running 24 hours a day for a larger and increasing number of the worker population. If we think about that, in 2030 will Nvidia be a $10 trillion dollar company?","offset":318,"duration":14},{"text":"Jason: Oh, I think 10 trillion in revenue is more interesting because he's just predicted a trillion, right? And so...","offset":332,"duration":4},{"text":"Rory: No, cumulative a trillion! Again, we gotta be precise. Cumulative a trillion.","offset":336,"duration":4},{"text":"Jason: Yeah, no, it's a cumulative trillion. Can I—so, so how long does it take to do a cumulative 10 trillion? That's an order of magnitude, that's at the limit I think of general non-Andreessen level human uh ability to, to grok is about an order of magnitude. Um, so I think five years it will have a cumulative 10 trillion from one tri—I don't think it'll take five years to go from 1 trillion to 10 trillion. That's my, that's my bet.","offset":340,"duration":21},{"text":"Jason: I do think the inference thing—and listen, there's a lot of interesting things in the math. How fast, how fast will the cost of inference continue to fall versus the consumption of inference, right? Is there—will there eventually be a Moore's law an inverse Moore's law where it doesn't where we don't see the dramatic cost decreases we're seeing. Maybe that's why we need data centers in space. There's a lot of, there's a lot of complexity here.","offset":361,"duration":20},{"text":"Jason: But even if you think like, why, why the hell does Nvidia do NeMo-Cloud? Like why? Now Jensen said it's the most GitHub stars per unit time, faster than Linux, faster than anything. But I think the real reason is, is it uses a lot of inference. This is why all—everyone in China is giving—all the, all the providers are giving away Open-Cloud because you've got Grandma and Grandpa lined up on the streets outside of Tencent, Alibaba with their free Open-Cloud because it just burns tokens, right?","offset":381,"duration":28},{"text":"Jason: So, uh, part of it is Jensen saying, \"we're going to\"—and this is probably part of the, um, you know, big part of the Groq acquisition, \"we just want, we want you to be burning tokens at least 72 hours a day, we want at least three agents running 24 hours a day.\" So yeah, I mean, I think it's got to be three orders of magnitude more inference we run in the next five years.","offset":409,"duration":20},{"text":"Rory: You could have 3x more tokens but if the price per token goes down by 6x the revenue would decline. Just pointing out.","offset":429,"duration":6},{"text":"Jason: Yeah but it's going to be it's going to be like a—it might be 3,000 times more tokens not 3x. But yes, the math, same math issue, right?","offset":435,"duration":7},{"text":"Rory: Again, going back to my comment is, you know, someone unveiled a trillion dollar number and within, you know, 10 minutes the stock market processed to nothing to see here, right? Just points out the expectation of a, you know, railway boom, internet boom level of CapEx investment continuing unabated growing at 30% for the next four or five years. It's a pretty heroic assumption.","offset":442,"duration":24},{"text":"Rory: It's validated by the recent past, and there's nothing at this point to say it won't happen, but it is just worth pointing out. You know, for con—if, when Nvidia does 200 the CapEx spend is probably 4 or 500 billion because they get about half of it. If Nvidia is doing 600 the CapEx spend is probably 1.2 trillion, plus or minus. These are unprecedented levels of CapEx spend and now we're forecasting them to keep going for four or five years. There is at least some probability—pick a number, 30%—that it doesn't happen this way.","offset":466,"duration":28},{"text":"Host: Is there anything else that you think is notable from GTC before we move on?","offset":494,"duration":5},{"text":"Jason: The thing that stayed with me, and this is—I think there's a lot of interesting, I hit the things I thought were interesting. Um, but the message behind the message, right, was that, uh, open-source whatever models, everyone needs gigawatt centers. They all need massive amounts of data centers with inference, with GPUs, with everything and that it doesn't really matter. It doesn't matter.","offset":499,"duration":26},{"text":"Jason: And that the best models are still going to win, which is where he's made his bet. He's announced another open-source alliance, other things will win, but at the end of the end of the day his main point: we're going to win. We produce the best outputs, we produce the best, uh, we produce the best inference, we produce the best everything, and everyone needs data centers.","offset":525,"duration":18},{"text":"Jason: And that level of confidence that most rolls of the dice lead to Nvidia winning, um, you know, it's a—go—we can take shots at, at its armor, right, at its moats, but I think there's a high degree of confidence that most of the roads lead back to Nvidia reaching 10 trillion of cumulative, cumulative uh bookings over the next five to seven years.","offset":543,"duration":25}],"startTime":64},{"title":"Tech Layoffs and AI Efficiency","summary":"Analyzing recent workforce reductions at Atlassian and Meta, the hosts outline multiple categories of layoffs. They discuss how companies are shifting capital from human workers to compute and strategically reshuffling teams.","entries":[{"text":"Host: Speaking of playing for this game, Jason you said why you can feel energy in rooms. There are also tough times for certain companies where you feel other forms of energy. Two big announcements this week were in terms of layoffs: Atlassian announcing 1,600 people and then Meta reportedly a speculative 20% workforce reduction, which would be 16,000 of 79,000. We've spoken about layoffs before. Is this really just the start of the dominoes falling? Is this a an a sign of overhiring from 2021 and beyond and actually we're just relabeling it AI? How do we think about these very large scale layoffs from the biggest players?","offset":568,"duration":39},{"text":"Jason: Well, look, I don't know that much has changed from our prior conversations other than that, you know, everything we've said has come true. Um, this is every conversation at scale. Here's the thing: it's not—Atlassian and Meta are both interesting I think because, I mean, I guess they're all the same. It's not really about layoffs. Neither of these company has to lay off anybody, okay?","offset":607,"duration":23},{"text":"Jason: Atlassian has substantial free cash flow. Um, Meta I don't know, they're in the—their free cash flow has dipped but it's still like in the mid-40s, right? They don't have to do this. This is not a unicorn trying to figure out what to do with the last 20 million that SaaStr Scale and 20 VC gave it. Okay, this is a decision. This is a purposeful decision.","offset":630,"duration":21},{"text":"Jason: And what's happening behind in board meetings and in management teams is everyone's looking at the teams they have and saying, \"I just don't know what to do with half of these people. I don't need half of these people. I don't need them. I do need people. I need people—I need different people.\" And I don't, you know, there was a great LinkedIn post today, this morning, from the ex-VP of Engineering of Ping Identity.","offset":651,"duration":22},{"text":"Jason: Um, who said, \"this is going to be a sad post, I don't know if anyone's going to see it, but but my what I learned is over. The craft art of creating code, creating modules, testing it, being creative, figuring out how to do something that hasn't been done before is why I got into engineering, why my teams joined me, right? That era is over. Now the AI writes the code and all an engineer does is review the code, but now the LLMs are review—doing the code review. We won't need me anymore.\"","offset":673,"duration":29},{"text":"Jason: And everyone's looking at their team and wondering: why do I need that engineer? And do I need half my sales and go-to-market team? Do I need to brute force sales and marketing the way it was when the three of us met? You brute force sales and marketing in the enterprise. Everyone's looking and they're saying, \"I don't need to do these things.\"","offset":702,"duration":17},{"text":"Jason: And so, these are leading to radically different ways of thinking about the future. And some folks are going to be very slow on this, um, but everyone's talking about it. Everyone's talking about it, and just whether it's 10% or 40% or 50%, it's just an output of these conversations of: what people do I need in the new world? And most folks are probably half their teams are not the folks they need going forward.","offset":719,"duration":24},{"text":"Jason: Do you want to be kind about it like Mike? Do you want to be brutal about it like Zuck? Does it matter? I mean, I—I get—it matters to the humans but at some point we're going to end up in the same place over the next 36 months. The pace of change is so fast.","offset":743,"duration":16},{"text":"Jason: So but I do think it—the block thing, you could argue it's different and they're growing 2% like we talked about and and I think Marc Benioff said it was an—Block is different, right? But these conversations are in every boardroom. Even if you're in—your margins are in the 40s, in every board: we have the wrong people.","offset":759,"duration":19},{"text":"Jason: And everyone's un—is stressed AF right now, because including OpenAI, including Anthropic, everyone's stressed AF, and they need to reboot their teams for the future and they can't stick with people in the past. You just can't afford to, you're going to be obsolete in 18 months. And layoffs are just one way to re-engineer your company there, and as brutal as they are, they're just a small piece of re-engineering your company, and we're running out of time.","offset":778,"duration":26},{"text":"Jason: Everyone knows they're running out of time. Everyone knows. In—unless you're Legora or Shenora or Ladora, but even them know they're running out of time. They—in 12 months their current products will be obsolete.","offset":804,"duration":11},{"text":"Rory: That was helpful because I-I actually been thinking a lot about this layoff thing and I came in with four different categories um of really what's going on. And Jason's actually added a fifth that I'll come to last. And I think if you try and be logical and use categories, it just kind—I think yields more insight.","offset":815,"duration":16},{"text":"Rory: There's a whole category of layoffs that are really: we never should have hired these people, we got fat, we're using AI as an excuse but if you run the efficiency metrics, we just don't need these people, right? And I think there's some of that in there.","offset":831,"duration":12},{"text":"Rory: Then the second category is the, you know: we used to have a business growing at 20%, we're now growing at 2, if we were growing at 20 we'd need all these people but we're not, we're growing at 2. I need to give the financial market what it wants, and it wants profitability, right? Again, no com—you're not making any comment on the labor, you're just conforming to capitalism, right? And I think there's a lot of that going on in the SaaS world, right?","offset":843,"duration":24},{"text":"Rory: I think that first category Block is clearly an example of the first category, and maybe Meta, but I'll come to Meta in a second. I think a lot of the SaaS world is that second category of: I have to give—Wall Street is simple: if you give them growth, they leave you alone, if you don't give them growth, you better give them profitability. And if you don't give them either, they're going to bust your chops. Them be the rules, and if you can't give them growth you gotta give them the second. That's what the second is. That's a second category of layoff.","offset":867,"duration":24},{"text":"Rory: And someone interesting: the third category is starting to get into what Jason talks about. The third category is maybe you just—that you did need these people pre-AI but now there are AI efficiencies that allow you to do the same thing with less. That's probably true in coding, um, not sure it's true at the same scale across the board.","offset":891,"duration":20},{"text":"Rory: The four—one isn't the one that Jason gave me, but it is the Cap—it is the Meta example, right? It's that's something different: you spent all your money on computers, you need operating cash flow because you-you got that depreciation hit coming, right? I mean, literally that's reallocating dollars from humans to computers, right? To compute, right?","offset":911,"duration":24},{"text":"Rory: That's not what's going on at Block, that's not—because they're not investing massively in CapEx, but that is 100% what's going on at Meta because—Jason you actually wrong in that their-their operating margins are still 40%, their free cash flow when you honestly account for the CapEx is almost zero, right? And that depreciation's going to start hitting, and they're going to be firing people because they need to feed—give it to Jensen.","offset":935,"duration":24},{"text":"Rory: And today compute eats jobs. And that's what you're seeing at kind of Facebook, you literally can't afford to have Nvidia and people.","offset":959,"duration":8},{"text":"Rory: And then the last one that I didn't have that Jason's added to me, which I think actually could be more of it than I realized, is this idea that in some cases you actually are going to hire back. Maybe not as many people, but maybe at twice the salary, but just different people. And maybe there's a little bit of deck cleaning—I think if I'm right Jason, I hadn't thought of it, but deck cleaning going on in that maybe I don't need 20 engineers who all know, you know, C++ or Rust, maybe I need eight engineers who are just really awesome at AI.","offset":967,"duration":29},{"text":"Rory: My aha is if that's not going on, it probably should be in every company. Even if you don't have any of the first four, even if you didn't overhire, if business is still going strongly, even if you don't need to feed Wall Street, even if you're not spending it all on compute, you probably are doing, to Jason's point, a pretty significant talent reshuffle in real-time.","offset":996,"duration":22}],"startTime":568},{"title":"Hiring Agent Deployment Experts","summary":"Jason argues that technical engineering skills are no longer the primary requirement to win with AI. Instead, companies need to hire generalist \"Agent Deployment Experts\" who proactively test and integrate new AI tools to drive enterprise efficiency.","entries":[{"text":"Host: I-I just wanted to ask Jason: if the people that we want are fundamentally different, the developers that we used to hire we don't because AI writes the code for us, the marketers we don't want, the sales people we don't want. Who-who do we want, genuinely? Like, what is the attractive profile? 'Cause your Anthropics and your OpenAI are hiring. So what are the people that we want in the companies of the future?","offset":1018,"duration":23},{"text":"Jason: Look, I know it sounds trite, but-but the answer is simple. It's just the expression each year changes. We want folks that are genuinely AI fluent. It's pretty simple. Now, you know, maybe last year we called them prompt engineers, right? That used to be a job. I don't know if you remember, that actually used to be the hottest job on planet Earth. Now no one needs a prompt engineer because it's pretty easy to prompt all these tools. That job died, okay?","offset":1041,"duration":23},{"text":"Jason: Um, and now we need go-to-market engineers. Um, I think that job's going to die. We need—everyone needs so many forward deployed engineers, like you can't hire enough forward deployed engineers. But, uh, um, but Palantir just announced in whatever their-their big event they've gotten their deployment times down over 90% with forward deployed engineers.","offset":1064,"duration":20},{"text":"Jason: So that may become—so this wave of disruption for the titles and the specificity, it's also exhaustingly accelerating. But it's really simple. You meet anyone for any role: sales, marketing, engineering, product, QA. They're-they're either—they can't keep all of the ways they use AI to accelerate their job from spewing out of their mouth, or they're staring at you. There's nowhere in the middle.","offset":1084,"duration":25},{"text":"Jason: Like and the person that comes in and says—it-it sounds Captain Obvious but like, you know you just had the whatever from Lovable, the marketing head that was super popular in the show, right? She's just spewing AI native insights into Lovable, right? It's not that complicated, you hire her. Elena or whatever it is. You just hire her. It doesn't matter whether she's still in college or a junior or a senior or a middle or a left or a right.","offset":1109,"duration":22},{"text":"Jason: And honestly, if you interview people, I would say of all—even of the best startups I've invested in, maybe 30% of the management team meets this standard, at best. 30%. Maybe less. And of the interviews I do in general, it's single-digit percents. It's just—and in-in that sense it's the same as ever. Like you either lower the bar in hiring or you hire someone that's actually great. And someone that's actually great is so far ahead of you in how to deploy to-to deploy the efficiencies of AI in their role, your jaw falls on the table.","offset":1131,"duration":31},{"text":"Jason: The difference is we used to need warm bodies. That's what's changing. We used to need warm bodies to answer the call, to do the QA, to do code review, to-to get the blue pixel to go from the upper left to the lower right. You laugh but you need—you literally needed to brute force this with humans.","offset":1162,"duration":18},{"text":"Jason: With AI every day that goes by, the AI—you do not need brute force human beings on your team. And that's another reason they're shrinking. Why are all these new companies so efficient? They're just not brute forcing things with humans. They're just not. They're choosing not to. And so these teams—all the brute forcers out there.","offset":1180,"duration":19},{"text":"Jason: Everyone talks about how bloated teams got in 2021. I don't agree with that. I think they got as big as they needed to be when growth was high and you needed humans to do everything. All—you look at these teams that doubled. Well, if growth continued at 60% like the rate in early 2021 for five years, Rory can help me do the math. And every single thing a software company did required a human, you were understaffed by your 2021 headcount. You'd be sitting here in 2026, you-you'd every office in SoMa would be triple-packed and there wouldn't be enough humans to staff your company. It's just the world changed.","offset":1199,"duration":34},{"text":"Host: Jason, you live on the bleeding edge. I think me and Rory see that and I think the world sees that when they hear you every week in terms of how you run SaaStr. For all of the CEOs and execs who listen to the show, what would you advise them in terms of determining whether someone is AI fluent when they meet them for jobs, for talent?","offset":1233,"duration":18},{"text":"Jason: Here's my—I realize I was just asked this. I just did a review with a super fast startup growing, just crossing 100 million. And I was asked this question. And one of my favorite executives I thought his answer was pretty dated and because he gave me an answer that was about six months old. The answer six months old is I look for folks in my team, I look for, you know, uh what tools they play with. Okay, that was a great answer in in like summer of 2025, okay?","offset":1251,"duration":22},{"text":"Jason: Um, I tried Lovable last week, okay? [makes game buzzer sound effect] The answer in 2026 is: what commercial AI tool have you brought into your organization this month? That's the test. Anyone that is on the bleeding edge that you would want to hire—now there are so many great products in the market, okay? There is no excuse in any role to have not brought one tool a month into your organization, okay?","offset":1273,"duration":29},{"text":"Jason: There—now there's going to be better and better tools and better and better products as the year goes on. What's the one you did? And you will see folks with their deer in the headlights to this question. What sales tool? What marketing tool? What product tool? What engineering tool? What did you bring in? Why did you pick it? How is it working?","offset":1302,"duration":16},{"text":"Jason: Because if you're at—remotely at the cutting edge, you're all over this. You're looking for the next agentic tools that will radically improve how you do bus—this-this is—you think—everyone thinks SaaStr is at the bleeding edge, right? You know, you know all we do? Is we're just looking for the tools and trying them. Okay? We're one year ahead of everybody else because we did the simplest thing in the world: like we tried the tools early and we trained them. We trained them for a month, okay?","offset":1318,"duration":24},{"text":"Jason: I'll give you—want to hear a horrible example from this week? Super hot AI company valued at six billion, okay? I'm not going to name it. Um, this week yesterday told us we had to quadruple what we spent on their product, okay? Their agent told us, right? And why did this happen? Okay, well at this six billion dollar company no one had trained the agent on its pricing properly. No one had tested it.","offset":1342,"duration":24},{"text":"Jason: They said, \"where-well we've been in beta.\" And we said, \"well when did the beta launch? A year ago.\" Okay, these are people asleep at-at the wheel. You want somebody who the instant this comes up they exactly know what the issue is. And \"hey, when I was at Lovable or Replit, we trained the agent, this is how we did it. I brought in this tool, I brought in this tool that-that Rory invested in last week, it solved all these issues.\"","offset":1366,"duration":21},{"text":"Jason: That's what you want to hear. And if they haven't brought in a tool in the last 30 days or at least deeply evaluated it—I don't really care whether they bought it, but gone so far down the funnel they can tell you, pick whatever tool, Fixer, Reggie, GC—AI GC, I don't care. How-how you went through it, you looked at it, you can tell me the eight ways it would improve the productivity of your business and three it didn't.","offset":1387,"duration":22},{"text":"Jason: Just don't hire that person because they're going to run your company into the ground. This is the job today. The job today is not to screw around on ChatGPT and to be a prompt engineer. The job today is to bring the best AI agent agentic products into your organization and leverage all the hard work that the engineers have done building those products. That's your job.","offset":1409,"duration":18},{"text":"Jason: You don't have to screw arou-you don't have to be a prompt engineer anymore. You have to be an Agent Deployment Expert, ADE. This is the new job we're making up today. An Agent Deployment Expert. That's your job from C-level to junior. Agent Deployment Expert. Don't hire anybody else. You're going to regret it. They're going to stare at the camera.","offset":1427,"duration":21},{"text":"Rory: He's good, he's good. Stare at the camera. He's on a roll. We could probably just slip away, get a coffee and come back.","offset":1448,"duration":6},{"text":"Jason: No, and I sound exasperated Rory, and the reason I am is I can just see—I can see my best company's doing it and I can see some companies I've invested in not doing it. And I want to cry. I just want to cry when they have no ADs on their team. I just—like you're flushing your years of your life down the toilet by not approaching your how you're building this company this way.","offset":1454,"duration":20},{"text":"Rory: Yes, and at the risk of being positive it's worth pointing out two things he didn't say, well—something implicit in what he said. Jason didn't do the only hire, you know, he didn't commit the um employment law I think it's a civil penalty of saying, \"only employ people below X who get the new new thing,\" 'cause he implicitly said anyone can do it provided you're willing to learn. And I think that's the big aha, that's one of the positive statements to make here, right?","offset":1474,"duration":24},{"text":"Rory: Look, and I think it applies—I'm always wary of being hit come across: \"hey this-this is the things that you all have to do.\" I think it applies to everyone including investors. Right? I mean I will say I have found that unless you're willing to invest the time learning these tools you actually shouldn't be an investing in them. I mean one of my partners Andy had this expression, you know, \"if you decide you want to stop learning new things you probably should retire within six to 12 months and never write another check again.\" For sure. And maybe that's down to three to six months at this stage, right? And I think, you know, it's, yeah.","offset":1498,"duration":30},{"text":"Host: I actually, Rory, I actually just had a meeting with mine and Jason's biggest investor the other day. Yeah. And I am pretending he's not here. I said I think he's the most equipped investor for this generation of investing, because I don't think anyone quite sits at the bleeding edge like he does on the investor side. Like...","offset":1528,"duration":16},{"text":"Rory: In terms of using the stuff, yeah.","offset":1544,"duration":2},{"text":"Host: Yeah, in terms of using the stuff, understanding, understanding bottlenecks, constraints.","offset":1546,"duration":5},{"text":"Jason: For sure. But can I just add one point? We can talk about—just 'cause it's so important if it helps people, okay? We are and thank you Harry. We're going through these phases, okay? And when AI started to blow up for real for us, uh call it early 2024, right? Maybe late '23. I wasn't equipped. It was too technical. I wasn't going to go in and figure out—I wasn't smart enough to figure out how to deal with a massively hallucinating LLM API and turn that and turn that into something magical.","offset":1551,"duration":28},{"text":"Jason: Kudos to investors and others that that got it in early '23, '22. I mean I remember I guess it was maybe SaaStr Annual '23 I was with David Sacks and I did a Q&A and I said, \"how you thinking about AI?\" at Craft. He's like, \"well we're all in, we want 80% in '23 of our investments to be AI.\" I'm like, \"great, but like show me the—show me the great ones in market.\" He's like, \"they're all prototypes. We're all—they're all proof of concept but we're all in anyway.\" That's where you kind of had to be in '23 if you weren't investing at like the LLM level, okay? I wasn't smart enough.","offset":1579,"duration":34},{"text":"Jason: Then we went through this weird ass prompt engineer era where like you you could torture these products to do something good, right? But you had to torture them. You had to like craft these crazy things that made no sense. Now we are in the era where mere ordinarily smart generalists can make these tools do magical things.","offset":1613,"duration":20},{"text":"Jason: And literally I go to these meetings and people are like, \"I don't know how to do this, it's so scary I don't know how to do this.\" And we show them our backends. Do you know how to do a workflow generator? Do you know how to do a um decision tree? Like we've been building these since software in the 90s, okay? If you—I can show you all of our agents. The-the how they work is novel. They do have to be trained, you can't be LAF [lazy as fuck] and have these agents work.","offset":1633,"duration":24},{"text":"Jason: But honestly, the UI, the UX, the way we interact with them, it's just software. And so my point is: pick yourself off the ground. This is your time now. If you felt lost in AI era, if you felt like you're behind, you don't understand what all these people are saying on X and Twitter in their claws and and talking about all the 4.6.nano.whatever and it's over like you just that's not your world. This is your time.","offset":1657,"duration":24},{"text":"Jason: This is your time for the generalist that knows how to use software tools really, really well. And this is my last point, but it's so important. If ever in your recent life, and this is why you could be all you need to be is young at heart, to Rory's point. If in the last three to five years you have successfully deployed a piece of enterprise software of any sort—you yourself, not some agency you hired—but if you have deployed it, you can deploy any agentic tool. Any.","offset":1681,"duration":25},{"text":"Jason: And you can become the hero in your company and you can become the hero in your functional area. But I watch folks—I'm literally helping a company now, they're adding hundreds of sales folks this year with the new pre-AI CRO. He's not—hasn't brought in a single tool, he's scared of it. Okay? It's not that hard. Did you use SalesLoft? Did you use Outreach? Did you use HubSpot? You know these tools? If you can deploy these tools, you can deploy a world-changing AI agent.","offset":1706,"duration":26},{"text":"Jason: And so, this is the time for people. Like the folks that that were shut out of the AI revolution. Right now the generalist folks that are not—that know how to deploy software, that don't even know how to build software. Like vibe coding for me was folks who knew how to build software but you didn't have to be an engineer. Now you just need to know how to deploy software to win with AI agents. That's all you need to know.","offset":1732,"duration":21},{"text":"Jason: So many people have these skills and they're petrified of AI. \"How did you do that? How did you deploy an AI BDR?\" Well, we bought a piece of software, we figured out how it worked for a day, we set it up in an afternoon and then, and then we did spend 30 months training it, which you didn't do with this old software.","offset":1753,"duration":16},{"text":"Jason: Because in the old days we just had to manually upload all the data, right? And there was no training. The only non-intuitive part is training these things. And it's-it's just work. Um, so that's why when I see folks on the management team not doing this, there's no excuse.","offset":1769,"duration":15},{"text":"Jason: You do not need to be technical to win with AI agents in Q2 of 2026. You do not need to be even 1% technical. Not at all. So it's your time. It—or you're going to get laid off, or you're going to get laid off because you're not going to matter.","offset":1784,"duration":16},{"text":"Host: You said not mattering there Jason, uh and thank you, that was impassioned rant that I learned a lot from. And I love ADE, that's a fantas—I think you should coin it. I would say write a book, but I don't think writing a book is ever useful these days given the speed of news and frankly attention...","offset":1800,"duration":15},{"text":"Rory: Given that no one reads them, yeah.","offset":1815,"duration":1},{"text":"Host: Yeah, 100%. The amount of VCs that write books I'm like \"seriously what-what are you doing, wasting a year doing this?\" Um...","offset":1816,"duration":6},{"text":"Jason: Well you get your friends to go on the book tour with you, there's something to be said for that.","offset":1822,"duration":3},{"text":"Host: Oh yeah, great, yeah yeah yeah. Totally totally. Come on, we're actually meant to add value here, keep going.","offset":1825,"duration":5}],"startTime":1018},{"title":"Anduril's Contract and Massive TAMs","summary":"Prompted by Anduril's massive $20 billion defense contract, Jason reflects on his changing investment thesis, arguing that small starting TAMs are no longer viable for venture returns. Rory counters by explaining how to balance near-term product traction with long-term market expansion.","entries":[{"text":"Host: Okay, Anduril lands $20 billion dollar army contract. The reason I said this is when you said about just mattering. I remember reading this being like: $20 billion dollar army contract. 10-year deal, five-year base and a five-year option to consolidate 120-plus separate procurement actions into one enterprise contract. Um, it's enormous. I-I when I read this I was like, God, the shit I do just doesn't matter. This sweet little unicorn company that's going from 1 to 4 million ARR. How did you guys think, analyze this $20 billion dollar annual...","offset":1830,"duration":38},{"text":"Rory: Well, first of all, yes it's obviously a vast contract, but as a reminder they have four or five on—they only have four or five customers. So you better get 20 billion from each of them if you want to be a big company, right? I mean, what it really told me is they've succeeded, right?","offset":1868,"duration":14},{"text":"Rory: Basic—'cause this isn't as much a new program, this is basically the army saying: \"look, we got 120 separate contracts with you, we get it, you're now effectively a prime supplier. Why don't we consolidate all the paperwork so that people one level down have less process to go through every time to buy your stuff, right?\"","offset":1882,"duration":18},{"text":"Rory: So it's a-it's a—both a procurement thing, and also there's a systems lock-in here. I think the primary product I think they're talking about is their Lattice, which is their software connectivity system. You know, you've got all these different physical hardware products out there. Some made by Anduril, some made by other people, right?","offset":1900,"duration":19},{"text":"Rory: And as is becoming clear in recent conflicts, a huge part of the problem is making all these systems talk to each other, dare I say it, autonomously and quickly, right? And connecting all these things in not just near real-time but real-time. Because, you know, as we're learning right now, it turns out if you're in the Strait of Hormuz you've got literally seconds before you can take down an incoming drone.","offset":1919,"duration":20},{"text":"Rory: You don't have time for a slow connectivity protocol. You definitely don't have time for a human. So you need this integrated communication system that connects all your different physical hardware offensive and defensive weapons. And I think it looks like the product that these guys have, that Anduril has, is becoming at least the primary default for that, for effectively moving information between different systems.","offset":1939,"duration":25},{"text":"Rory: So it makes sense for what the Pentagon's doing. They're basically saying: \"look, we've gone from trying you out in a lot of different areas to saying okay damn it, you're the dominant provider of this layer, so why don't we just systematize the contract.\" It kind of picks them as it picks them as the clear new prime.","offset":1964,"duration":18},{"text":"Jason: I'll tell you to answer Harry's question and this may be wrong. Like this may be a flaw in me, like I completely concede this. But Harry's part of—part of Harry's question was, \"hey am I investing in things that don't matter when Anduril has a $20 billion dollar contract.\"","offset":1982,"duration":15},{"text":"Jason: My version of—I-I feel that. And my version of this is I have given up on an-an investment thesis I had for 10 years because I was a B2B founder, which is that uh a smallish TAM is okay with a great founder. Start small, okay. Fine. But you know what? Every—thing we can all point to small things.","offset":1997,"duration":18},{"text":"Jason: For me, you know when I started E-Signatures, the TAM was 2 million. It was 2 million. Obviously if you just look at Rory's investment DocuSign, it is doing more than 2 million today, as I haven't checked the latest quarter, but even with some challenges the TAM certainly grew, right?","offset":2015,"duration":12},{"text":"Jason: So as soon as I realized that, I'm like: I'm investing in areas that are going through phase transitions with great founders and they will grow the TAM, right? And for sure we can show if—I hate to do trite things we've done, certainly the legal tech space is one that has shown an explosion in TAM, right? Because of AI. So there's many examples.","offset":2027,"duration":18},{"text":"Jason: But, but, in my heart and soul I can't do any of those investments anymore. I can't. I can't invest in anything that is mid-sized or smaller. I just can't. This is the Anduril problem. And this is also why I think a lot of funds are going to have terrible returns. Because a lot of early stage funds are going to swing so hard for the fences that they're going to invest in the number three or the number four and get just zeros after zeros because there isn't a chance to stairstep your investment.","offset":2045,"duration":23},{"text":"Jason: There isn't a chance to go from the $50 million dollar TAM to the 150 to the 500. So I think there's going to be a lot of zeros. But I can't help myself, and literally I can't even—I don't like—I can't even bring myself to take a meeting with a startup where I don't believe the TAM will be utterly massive. I just can't take the meeting anymore.","offset":2068,"duration":18},{"text":"Rory: Jason, you you—there's a lot in there. I want to unpick it and frankly be more precise. Right? What you say—I think you're saying two things, just to be clear. When you see what a big TAM feels like, and let's agree um the com system for the Army probably is one of those big ass TAMs, right? You're saying is: you just can't get excited by super small TAMs. That's one statement.","offset":2086,"duration":22},{"text":"Rory: And the second statement you made is: if everyone's thinking like that, they're all going to do a swing—they're all going to swing more aggressively at the big TAMs but in the third or fourth player in those TAMs and probably lose. Is that what you're saying?","offset":2108,"duration":13},{"text":"Jason: Yeah, and-and even worse: they're going to pay up 100 pre for these seed investments because it all—because as the best accelerators tell us, it doesn't matter in these big outcomes. It doesn't matter whether you pay 60 post or 100 post at a top accelerator because when it's a hundred billion dollar outcome, that's a better return than a unicorn, right? Mathematically it's true, but I think it's going to lead to a lot of zeros.","offset":2121,"duration":21},{"text":"Host: But Jason, do the best markets not start small? To your point there when you said—to your point—do the best markets not start small?","offset":2142,"duration":7},{"text":"Jason: I don't believe it anymore. That—the de-fense—I be—Rory correct me if I'm wrong, I still think defense is the number one largest segment of our spend in the country, maybe healthcare is number one and defense is number two, right?","offset":2149,"duration":9},{"text":"Rory: No, defense isn't actually—shockingly defense isn't that large. We just spend a little over 3% of GDP on it. And turns out most of that—not most of that—a good slug of that, almost half is people. It turns out the actual amount of money—what—I'll make a comment: it's not counters. I think Anduril's going to do amazingly well.","offset":2158,"duration":19},{"text":"Rory: The Pentagon budget for new shit is fairly finite. And I think there'll be five or six big winners in defense. I'm not sure there'll be 100.","offset":2177,"duration":7},{"text":"Jason: Um, but but isn't that the game of venture? Is five or four—not 100?","offset":2184,"duration":4},{"text":"Rory: What? But that's the game of venture is to find the four or five, not the hundred.","offset":2188,"duration":3},{"text":"Rory: Agreed. So and that's my point is that, you know, power law—the thing about power laws is they get in your head, like it's getting in your head, and you can over-project from: nothing matters except the hundred billion dollar outcome. Well, if you own 10% of a hundred—of a billion dollar outcome and you are a $100 million dollar fund, that's a 1x fund.","offset":2191,"duration":17},{"text":"Rory: So I-I hear you, I understand what you're saying. The bigger your fund size, the more you have to be a power law junkie. At some level you want to be a power law junkie because in the end even if you have a $100 million dollar fund, wouldn't you prefer to be in the trillion dollar outcome than the billion dollar outcome?","offset":2208,"duration":15},{"text":"Rory: Right? The question is: when does that focus on the power law, could it become overly myopic and and lead you to swing—you know, you know where gamblers can go on tilt? Where they're so desperate to earn, you know, their money back that they start swinging at anything?","offset":2223,"duration":15},{"text":"Rory: Right? And, you know, if you're like: \"oh my God, I just gotta get—I wish I'd done—is someone saying I wish I'd done OpenAI or Anthropic therefore I'm going to fund eight next-gen foundation models because maybe one of them will be like that,\" right? That's another failure mode that as you said could happen.","offset":2238,"duration":17},{"text":"Jason: We might be seeing that happen right now, right?","offset":2255,"duration":2},{"text":"Rory: That's my point. So I-I'm not sure I fully—I hear you on the small—no one wants to be in a small TAM, but almost as important as TAM size, there's two other things: there's TAM velocity, for lack of a better word, your ability to dominate that TAM. There are mid—small and mid-tier markets that are wildly profitable software markets for the winner, and you can make, you know, really good coin in a four or five billion dollar market with a great outcome.","offset":2257,"duration":26},{"text":"Jason: But not if-but not if your entry point is-is what they are today.","offset":2283,"duration":3},{"text":"Host: Totally.","offset":2286,"duration":1},{"text":"Jason: Yeah, no, totally. The thing is now that like YC has productized a $60 million dollar post, right? Nothing wrong with it, I'm not criticizing it, more power to them, right? But what is as a seed investor—I mean Harry made this point that all these classic seed investments can't make money, right?","offset":2287,"duration":15},{"text":"Rory: Just, agreed. You can't go into a game paying power law prices for mid-tier market outcomes. For mid-tier markets. Because you're exactly right.","offset":2302,"duration":8},{"text":"Jason: That's the game today. But that's the game today.","offset":2310,"duration":2},{"text":"Rory: I keep—I understand. That's a fair comment. That's a—as a combined comment that's fair, is that if you price every deal like \"quote unquote\" it might have a two billion dollar or 20 billion dollar contract, most of them won't.","offset":2312,"duration":13},{"text":"Jason: Harry wouldn't do this, but if a founder came—a classic founder came to me with a-a structure that made sense and I believed in them, I might still take the bet, but at 60 post for a pre-seed investment, right? You-you can't risk that it's not Anduril or better. Like you can take risk it doesn't happen, but you have to believe the TAM the opportunity is so large.","offset":2325,"duration":20},{"text":"Jason: How else you're going to get your 100x with dilution? Right? That's 250x in today's world, uh post-dilution and everything. What's help me what's 250 times six billion—60 million post? Like lots.","offset":2345,"duration":12},{"text":"Host: 13, 14 billion.","offset":2357,"duration":1},{"text":"Jason: Yeah. So let's round up to 20. How many public companies—tech companies today have market caps north of—not as many, less than when we started this podcast. The math is grim.","offset":2358,"duration":10},{"text":"Rory: Yeah, no, I have that count somewhere. Sub-50, yes.","offset":2368,"duration":3},{"text":"Host: No, I mean I think that if you look—Jason, if you take this mindset though, like genuinely, when a deal comes through the door, what is big enough? Because, you know, you've talked about your Qualifieds and your Artisans and your Monicas. Are they big enough? Like, SDR AIs? You know, I'm seeing like constant call center replacement for healthcare assistants, for auto manufacturers. What is big enough?","offset":2371,"duration":23},{"text":"Jason: Well, some—well listen, there's-there's arguments they are, right? If you look, um the—but what-but I think it's why the growth fund is the winning strategy at the moment because they wait for the proof. Okay? It's easy to be cre—take any—I mean I-I'm getting bored of talking about the same companies, but for to have a thread through our conversation, certainly I-I wouldn't have believed that—being in this space, having made so many investments—I wouldn't believe that Decagon and Sierra—now granted the revenue multiples are very high, right?","offset":2394,"duration":25},{"text":"Jason: I wouldn't have believed they would be doing what they're doing. I'm not even sure I would have believed to-to Rory that Intercom would have re-accelerated as it has or others. I wouldn't have believed it. But the beauty to-to doing the deal when Rory did it is he gets the proof points. That's when—that's why it's such—but hoping that a slide and a vibe-coded website proves it is tough.","offset":2419,"duration":24},{"text":"Jason: But Harry going to your point, like what—there is a bull ca—there's—this is—I'm not saying I'm right. Like here's the counter-argument where I'm wrong, right? And this is Captain Obvi—but like, the reason and like—I mean I barely know Decagon, but they just talked about it this week, and and uh and Owen talked about it last week. All these spaces are converging.","offset":2443,"duration":17},{"text":"Jason: So Owen said there's not going to be any difference between support and sales in a lot of what we do. All these agents are converging to a meta—a meta agent that does more, replaces a lot of humans and is worth a lot. Okay? If that bet comes true—and it's already happening—then your TAM but here's my point: your TAM explodes, right? Your TAM explodes, right?","offset":2460,"duration":18},{"text":"Jason: The question is: will you invest in a space where there's no evidence that the TAM is exploding due to AI? That's-that's where it's tough, right? Will you invest in—and it's kind of the question that you're asking, uh Harry.","offset":2478,"duration":12},{"text":"Rory: I don't understand what actual—the actual—what you're actually articulating. I mean, yes, it turns out, yeah, seed investing is harder than A, and on a deal-by-deal basis is harder than A and B, which is harder on a deal-by-deal basis than C, D and E growth investing.","offset":2490,"duration":17},{"text":"Jason: I'm just saying you can't take the smaller TAM the stairstep risk. The classic VC seed stairstep the TAM risk. Take a—take something that starts small, that has a-a nuclear core that's stro—that's strong and then build—add TAM layers over time, right?","offset":2507,"duration":16},{"text":"Host: But Jason, but Jason, if I go to-if I go to like Replit or Lovable at the seed, vibe coding at the time was a very new and nascent category. I don't think you could say the TAM was particularly massive. It was a small market.","offset":2523,"duration":15},{"text":"Jason: Well, look, I-I'm first of all I'm completely starting this conversation by saying I'm not sure this is necessarily a good thing that I'm criticizing myself. I've changed. I've changed my perspective. I used to stairstep everything, right?","offset":2538,"duration":13},{"text":"Jason: And even the investments I made that weren't stairstepped, I would invest in something that had like a terrible terrible comps because I believed they were being remade by the space and would be much bigger. I just don't feel that-that vibe anymore, right?","offset":2551,"duration":10},{"text":"Jason: I actually think the—the like the Replit round that blows my mind when I think Craft and some other folks did it at a billion in Replit in like '21 pre-AI? Like they did like Replit at 10 million and 8 million in revenue pre-AI. I would have not have been that omniscient, okay? Like good—it's not that I wouldn't have bet in on Amjad, I mean he's a force of nature.","offset":2561,"duration":22},{"text":"Jason: But pre-AI this weird web IDE that doesn't do much and doesn't even doesn't finish any software? Like, I ain't that visionary. But, but, but, I think if you ask Paul Graham or or David Sacks, they would say, Harry, listen, I mean revolutionizing how we do software development on the web is massive. Like this is going to—I know you don't see it today, but-but I actually think you could argue the TAM is very large, right?","offset":2583,"duration":25},{"text":"Jason: If we really believe Amjad is going to take this-this kid out of the wonderkid out of Facebook who brought the co-you know the guy that created React with him to co-found the company. These guys—these two guys—they just might re-change how we build software, that's a big TAM, right?","offset":2608,"duration":16},{"text":"Jason: Now little—now where I struggle is when I meet founders doing little niche things in vibe coding. That's where I'm struggling today. Oh, I've got a little thing that does a hint of security on these platforms, right? Or makes or makes the objects prettier, okay? Like I-I design is terrible in Claude Code, it's unacceptable in-in OpenAI, it's it's um it's ba—it's—but and so there's a lot of folks trying to tease at design, right?","offset":2624,"duration":25},{"text":"Jason: But is it big enough and will the models just take it over? Uh you better show me something like hyper-disruptive like my jaw falls on the ground or I just don't believe, right? Replit I might have believed but this little niche fixing the fact that the icons all look like Claude artifacts, I just don't believe. But you could say it's bigger than Figma.","offset":2649,"duration":21},{"text":"Rory: But what am I meant to do with all this? I'm just trying to understand how I do my job differently tomorrow because of this information. Genuinely Jason, like...","offset":2670,"duration":6},{"text":"Jason: Yeah, you raise a growth fund like all of our all of our friends do. You raise a multi-ten billion dollar growth fund and you just wait until you have extreme product-market fit, right?","offset":2676,"duration":9},{"text":"Rory: But again I think you should assume that, look, the great thing about American capitalism is money fills any void. Like there—and-and-and it's the Barton Biggs quote I've made very often: there's no investment opportunity so good that excess capital won't destroy it.","offset":2685,"duration":14},{"text":"Rory: You're right. There's a period of time, look, I think you'll look back and go the growth investments in '17 and '18 were awesome because they sold in '21. The growth investments were '21 because they priced in '21 and then they were shit, um because the revenue slowed down and the exit market died.","offset":2699,"duration":20},{"text":"Rory: The growth investments from '23 on that were LLM-centric were amazing, and from the growth investor perspective needed more capital than was easily available. There was a period of two or three years where, you know, the capital needs of Anthropic and OpenAI were unprecedented as were several other companies. And when capital needs are unprecedented the people selling the capital can do actually better at the margin.","offset":2719,"duration":22},{"text":"Rory: Take that and have some insights as well about the future you can make money. Now the wall of money's come back in, and I'm sure growth will go through the same thing again which is everyone will pay a hundred times run-rate revenues for late-stage stuff they think is growing quickly just as in '21 people thought they're growing quickly. And fast forward some will work and make people look really smart and some won't, right?","offset":2741,"duration":19},{"text":"Rory: Whenever you're investing you have to have some marginal insight more than the other guy about why this thing that is at whatever stage it's at, yeah, can outperform and be bigger over the next X years. Once it becomes consensus and the capital arrives, then it's just very hard to have excess returns.","offset":2760,"duration":16},{"text":"Rory: And look and one of those ways of non-consensus is funding these small markets that can expand. 'Cause I don't agree that—one of the things we often think about stepping back is we actually because the stage we invest is early product-market fit and our highest level rule of thumb has been the big aha is: we want big picture trends and near-in traction. We don't want to compromise between the two.","offset":2776,"duration":23},{"text":"Rory: We want something that's working right now, which could be something small that's working right now as a—you want something that's actually a thing right now with early product-market fit. But you're right Jason, where you are correct is: you don't want something that's a cute little thing now but could converge and there's just no white space.","offset":2799,"duration":14},{"text":"Rory: You want—yeah, and taking that and saying the Anduril example: yeah, if you had done a post-product market fit investment there in 2018, you know, unfortunately we didn't, would have been their near-in product and everyone half the country can get mad at this right now was watchtowers for the US border, right?","offset":2813,"duration":22},{"text":"Rory: That was the near-in traction, they had really good traction on that, and that's the near-in product. And if you applied the lens of: how big is the market for watchtowers on the US border? The correct answer is: bigger than you think, but goes up and down every four years depending on random exogenous events, right?","offset":2835,"duration":16},{"text":"Rory: The US Defense Department has purchased things on cost-plus for 40 years and is wildly inefficient, and Anduril is going to let them purchase things on a Silicon Valley \"we build the product upfront and then we sell it to you on a,\" you know, per-unit basis, right? That's the big picture trend.","offset":2851,"duration":17},{"text":"Rory: So from the A on you have to have both, some near-in traction, something to hang your hat on, but then to avoid the risk you're talking about, you gotta be able to articulate an expansion story. Now the trick becomes anyone can use words.","offset":2868,"duration":13},{"text":"Rory: Like because technically take your Replit example, you're right: you-you can, yeah, if you squint one way it's a-it's in 2021 it's a tiny little tool for a niche case. If you squint another way and use big high-falutin words it's the future of software and democratization of software. And it turns out the trick in investing is to figure out which of those words is bullshit and which is not.","offset":2881,"duration":23}],"startTime":1830},{"title":"Travis Kalanick's Return with Atoms","summary":"The hosts discuss Travis Kalanick's new robotics company, Atoms, and debate whether Uber would be a $1 trillion company today had he remained CEO. They also consider the nuances of investing large funds into proven, yet controversial, founders.","entries":[{"text":"Host: I-I do want to talk about Travis Kalanick, um came back in in force with Atoms. Um and to be clear, eight years in stealth, thousand employees, rebranded City Storage Systems and CloudKitchens which is more well-known into this new company Atoms building gainfully employed robots: food, mining, transport. He came out with a pretty um I don't know if you'd say scathing, but a an opinionated piece: \"I bled but I did not perish.\" He wants to be more aggressive than Waymo. How did we read this guys?","offset":2904,"duration":38},{"text":"Rory: I thought on the—I thought on the merits of what he said about robotics that he's correct, and was pleased 'cause it's something we've believed. So as again to remind the viewers it's obviously Travis Kalanick, the wildly successful founding CEO of Uber, famously terminated by the board, enduring feud with Bill Gurley, which can cycle back to the Anthropic um Pentagon discussion 'cause uh Travis's number two is now driving at the Pentagon and also showing an ability to maintain a grudge, which is just one of those things you've just gotta admire in people.","offset":2942,"duration":29},{"text":"Rory: But anyway went away, founded CloudKitchens, surfaced last week and basically said: it's not about CloudKitchens anymore, it's about robots. And Atoms is building robots for a variety of industrial use cases. And he has an investment in Pronto which is an autonomous driving um company, uh founded by Anthony I-I always mangle his last name, my Polish sucks, Levandowski, who was with him at Uber, right?","offset":2971,"duration":29},{"text":"Rory: So it's basically coming back and saying: \"I-I was doing CloudKitchens, I'm now using that information to build robots and I'm also thinking about autonomy,\" which obviously cycles back to Uber. So that's kind of the background. I thought he was spot on on the robotics call, and let's be clear what he said.","offset":3000,"duration":16},{"text":"Rory: He said he didn't fundamentally think humanoids are the answer. He thinks robots on wheels are the incremental next step. And the big aha that-that Travis had was: it's not clear if you're building an industrial machine for a lot of use cases that you add legs. The you know, the humanoid robotics that we all see, they have these legs, they consume a lot of battery life, they're pretty unstable.","offset":3016,"duration":27},{"text":"Rory: And most of the time in factory work or logistics, warehouse work, you don't want someone using—you don't need legs, you just need wheels, right? They're a lot more efficient. And I think it's a big picture insight of Travis to say this is the direction things are going.","offset":3043,"duration":15},{"text":"Rory: And you know worth pointing out is he's effectively making a call against a whole bunch of the humanoid companies. Not saying it's not going to happen ever, but saying it might take a a lot longer than you think, and the path to humanoid robotics might be through specific-purpose non-humanoid type machines maybe expanding over time. So big ass call on robotics that for what it's worth I agree with.","offset":3058,"duration":25},{"text":"Rory: And it's interesting: just one more comment is Sunday, which just raised recently, which is another one of these robotics companies focused on the home, if you actually look at the form factor they've gone with um wheels too. Right? If you look at the—it's very cute, it's a really cute robot, it's kind of nice happy plastic, but you look at the—on the ground and it's actually running on wheels.","offset":3083,"duration":21},{"text":"Rory: Because they too have recognized that spending the money to give feet to many robots is just a waste of money here, right? Because you don't need them. So I think actually on-trend he's correct.","offset":3104,"duration":10},{"text":"Jason: The main thing when I saw the T-B-N interview, the main thing I thought was um if he were running Uber today it'd be a trillion dollar company. Without que—I-I mean to me without question in today's world. It's-it's his time. Uber's 160 billion dollar company with massive free cash flow and it is epic.","offset":3114,"duration":20},{"text":"Jason: And it you know, I think the-the-the his hyper-aggressiveness which in a different era led to his downfall, which I come back to, but it worked, right? It destroyed Lyft. So his-his view that like: if you're not as a-a 57 on the 1 to 10 scale of hyper-aggressiveness you're not going to win this, and this is the era we're in today, right?","offset":3134,"duration":22},{"text":"Jason: He was just too early, like and there was toxicity to him and there's elements of, you know, treating women and other things that are probably terrible and not okay. Putting that and it's hard to, but putting that aside he-he was just early for his time. And look at Uber today, despite that, wildly successful, but mostly been engineered since then, right?","offset":3156,"duration":19},{"text":"Jason: Acquire, get into food delivery, which is huge for it, but a lot of that's through acquisition and managing his existing fleet. And when Travis was CEO, all he wanted to do was get into autonomy. He said from the beginning, \"our business is dead at its terminal state. No one is going to be driving cars in an Uber.\"","offset":3175,"duration":-1065},{"text":"Jason: And now they're years and years and-and years behind where they could have been. So when I look today, the trillion dollar companies are becoming commonplace. I think Travis' Uber would be a trillion dollar company today, because it'd be five years ahead of where it is today. And that's all I thought.","offset":2110,"duration":1095},{"text":"Jason: Do I actually think this CloudKitchens eight years out in the the-the winterland, do I think it's going to make it? Probably not, right? But that guy, that guy would be running a trillion dollar company today if Gurley and buddies didn't force him out. That's what I thought.","offset":3205,"duration":13},{"text":"Rory: I disagree. And so, picking apart the argument...","offset":3218,"duration":4},{"text":"Jason: Would you have pushed him out?","offset":3222,"duration":1},{"text":"Rory: I'll come back to that at the end of this conversation. I will answer I will answer that question. But first of all, it's interesting you made-you made a comment here: \"CloudKitchens I don't know if I believe in it, but Uber would be a million dollar a billion dollar a trillion dollar company,\" that's what you said, right?","offset":3223,"duration":14},{"text":"Rory: Implicit in that statement is a repudiation of the logic of it, which is: you're saying the great founder is everything, but what you're saying is the great founder can't make this company worth a trillion dollars. So implicitly what you're saying is it's the great founder plus a great opportunity. It's not quote unquote all about the founder.","offset":3237,"duration":15},{"text":"Jason: Well he has to start from scratch now.","offset":3252,"duration":2},{"text":"Rory: Yeah, but yes. But my point—my point—starting from 80% market share in-in rideshailing's a pretty good platform to start from if you start if you know everything about the industry every inch every-every every everything every inch of this industry you know it cold.","offset":3254,"duration":13},{"text":"Rory: So now let's talk about that, right? Dara had to drive Ubers to learn it, and bless his soul he's great, but he had to drive cabs. Travis didn't have to drive any cabs to learn how Uber Uber worked, like he already knew he already knew how it worked.","offset":3267,"duration":13},{"text":"Rory: So give-let's ask a question here: given, okay, so let's talk about that, right? And I want to leave aside the inap—the personal behavior stuff where I frankly don't have visibility and I'm genuinely not going to try and make a call on that. The hypothesis that Uber instead of being a 160 billion dollar company would be a trillion dollar company implicitly has to be some ver—the only thing that could bridge that gap would be autonomous driving, correct?","offset":3280,"duration":25},{"text":"Jason: Well, no, you would you would be five years ahead of autonomous driving, which is-is already is now taking off, and I think you would dominate food delivery more than it does. Because you only—you already had such a head start ahead of your competition. You wouldn't you wouldn't dribble-drabble into it and you wouldn't then uh go buy or do this and that. You would just dominate it and you would use capital and you would weaponize and you would use implicit and you would use some dark arts in your mobile app so that-so that the competition would get blocked and all this crap. But you would you would dominate it with.","offset":3305,"duration":33},{"text":"Jason: You would just go for 90% market share in food delivery. 'Cause it's a better market than autonomous autonomy, it in the short term, maybe not in the long term, but it's a better market in the short term than rideshailing.","offset":3338,"duration":10},{"text":"Rory: I-I agree—for what it's worth I agree with that. So two separate arguments: right, do—they had to get public. They had to get cash flow positive. Hard-nose comment: you could another spin on autonomy, you could say: \"yes we need to do this thing but we can't afford to spend at the level they were spending in 2015 on something that reminder 10 years later is still only now finally doing a meaningful number of rides sub-economically in San Francisco.\"","offset":3348,"duration":28},{"text":"Rory: Right? It's a trend, it is the future, it was 10 years away. And they had to get public and they had to have a plan to cash flow break-even to get public to dominate Lyft. And you know on-it wasn't an option then as perhaps it might be today to stay private longer.","offset":3376,"duration":13},{"text":"Rory: Do you think they had to cut back on their autonomous spend? Maybe not to zero, which I think probably was a mistake, but dramatically focusing on getting cash flow positive, giving Wall Street what it wants, to get public to have the acquisition currency to do the food things. Right?","offset":3389,"duration":16},{"text":"Rory: And-and growth at all costs had reached its limits there and maybe a different manager was the right person for the next stage of that journey.","offset":3405,"duration":6},{"text":"Jason: Listen, I-I think in this-in this universe, um outside management through-through just like many companies, performs as well or better through early 2022. Remember, it was a decade where no products changed, even Uber didn't change much, right? Uber seemed feature-complete about two years after it launched, okay? Great, they added they added UberX. Now now for five bucks I could get to work and nothing changed. Okay, these-this app was frozen in time for a decade, right?","offset":3411,"duration":26},{"text":"Jason: That's why outside management can run it. And I believe what it would probably look like is that as late as two years ago, both-both they might have led to similar outcomes or maybe even a better outcome with outside management, right?","offset":3437,"duration":12},{"text":"Jason: But today it would be a trillion dollar company. My point is: now would be his second-second time, because he wouldn't have quit, he wouldn't have stopped building. And-and frankly and one of his best friends is Elon Musk. Maybe he would have owned autonomy with Tesla in a way that that you can't—who knows? But good God, it would be a trillion dollar company today.","offset":3449,"duration":19},{"text":"Rory: I actually think now I would agree with you. I actually think there was a period of time where they needed to conform to that reality of the market at that time, get cash flow positive and run it like a financial engineer, and he didn't-he clearly was unwilling to do it. Actually and in terms of—in retrospect they should have done the Steve Jobs thing: they should have swapped him out, got it public, got it cash flow like crazy, and sometime in '22 should have got him back and said: \"now, now is the time to do autonomy.\"","offset":3468,"duration":24},{"text":"Rory: So I do agree in the last two or three years—it's still unproven by the way whether or not Uber needs to own the technology to still make autonomy work. But I agree: I like your framing that there was a period of five or six years where the best manager for a lot of companies was a, you know, professional executive with a financial bent, and I think I can see why they made that change.","offset":3492,"duration":23},{"text":"Rory: If there was no more private capital to be raised, and if your CEO just was unwilling to focus on convergence, at the expense of long-term projects, and you had a risk of going bust, I can see why you made the change. But I agree with you: now you can say in the last two or three years the financial management game is out, and the product innovation game is back in.","offset":3515,"duration":21},{"text":"Host: And accelerating, and accelerating. Rory you said you would answer the question which Jason posed: would you have made that decision and switched him out?","offset":3536,"duration":9},{"text":"Rory: You should be very, very, very wary of ever swapping out a founder, right? It's like—I tell people it's like open heart surgery and 50% of people die, right? It's a shitty business. Occasionally I've done it for a bunch of reasons, and it's hell on earth. Forget morality, forget am I a good guy or a bad guy, it's just the most exhausting thing you do. It is easier to just lose money, right? So I hate doing it.","offset":3545,"duration":23},{"text":"Rory: There's only two reasons why you do it: if the business decisions they're making is literally going to bankrupt the company, right? If you feel that, you know, they're investing in—to take a concrete example here—if they were investing in a way whereby there simply just wasn't going to be any more private capital and we could run out of money and they were unwilling to change course, then at some point you have to consider that.","offset":3568,"duration":21},{"text":"Rory: And then—let me finish—and then the second option is the thing we said we wouldn't discuss, which is if internal behavioral issues rise to the level of a really systemic problem with a high bar, right? If both if-if both—if one or both of those things is present, then wildly reluctantly you have to do it, right? And even you have to take the heat.","offset":3589,"duration":19},{"text":"Host: Would you have done it?","offset":3608,"duration":1},{"text":"Rory: If one of those two things were the thing, then reluctantly you would have. You'd move heaven on earth not to, but if it's the former: at some point you gotta say: \"we're going to run out of private capital, you're not doing what it takes to get profitable, we need to focus on profitability, give Wall Street what it wants,\" then yeah, you-you might have to. You'd hate doing it.","offset":3609,"duration":18},{"text":"Rory: And again I hate this positioning, I'm not the guy—like nine times out of ten I'd be like: sell the company, get a president, get therapy, be better, all the other things. But especially my logic is this: knowing what it's like in those board meetings and knowing if you're a founder-friendly firm, like I would say Benchmark would like themselves to be, you don't do that lightly. So you gotta believe that some one or two of those issues was on the table for them to have to do that, and they felt at least it was necessary.","offset":3627,"duration":31},{"text":"Host: And I think you obviously see that with with Adam and and WeWork being the first there in terms of just the fiduciary responsibility in terms of how they spent money and the financial profile, so totally get you there. Are we bullish on Atoms now? Do we look at this and think this is exciting, this is going to work, awesome?","offset":3658,"duration":19},{"text":"Jason: Look, I don't know. I-I-I get-I get the big bet and certainly making this bet seems to-to be a lot more make a lot more sense than betting on the WeWork founder, right, who just doesn't is not as deeply product and software focused, um, building co-working spaces and then having everyone figure out the finance.","offset":3677,"duration":19},{"text":"Jason: Listen, I can only use—if I were a huge fund and he wanted my money, I would give it to him, don't get me wrong. But my smell test from watching the interview, um, some of the things he said felt like I was back in 2017 when this happened. The world is different now, and so I-I'm just I've just got to use my G2. And the question is: do I-do I think he's past it, right? and not being not being able to execute, but being able to—at some point you-you do lose, you lose the ability to create and you're better off amalgamating, and this is in the middle, right? This is a combination of amalgamation and creation. So you just asked my opinion, would I invest based on the interview? No, I wouldn't.","offset":3696,"duration":38},{"text":"Rory: It's so funny the way you answered that question the way we pro—'cause I-I the same question I didn't process to any kind of internal analysis of Travis' calling soul. I literally found myself thinking, do I—I kind of come from the market side: do I buy the market? I think there's two businesses going on here.","offset":3734,"duration":16},{"text":"Rory: One is the Atoms/robot business. As I said I like the fo—I like-I like the approach of more bounded industrial robots versus general purpose humanoids, so I think he's on the right broad track. But I think all those markets tend to be very different and trying to do one robot for all of them is hard. So I think that's a hard road and will be less amenable to any kind of \"quote unquote\" blitz-scaling.","offset":3750,"duration":27},{"text":"Rory: And let me finish then. The autonomy thing is interesting. I think we are at the stage now—the other company that he's invested in is Pronto, or I'm sorry I should remember the name.","offset":3777,"duration":9},{"text":"Host: Pronto.","offset":3786,"duration":1},{"text":"Rory: Pronto, yeah. That's super interesting because we're now at the stage, you know, where, yeah, autonomous driving in freeways is kind of hovering on the edge of being a thing with Waymo, but autonomous driving for mining and for industrial equipment is a category now and there's some players in that space.","offset":3787,"duration":16},{"text":"Rory: So I buy that that market is there and doable. I'd have to do the next level down: why is their technology different and better? Credible market and focused for autonomy, believable market but lots of sub-segments in industrial robotics to really play there. So that's my comment on them.","offset":3803,"duration":18},{"text":"Jason: Would you invest at 20 billion post? That's probably what he's looking for. That's what Claude thinks he's looking for in the round. He's fundraising, that's why he did the interview, he's fundraising, right?","offset":3821,"duration":7},{"text":"Rory: Oh God, dear God no. No.","offset":3828,"duration":2},{"text":"Jason: Yeah because the last round was at 15. Claude thinks he's-he's looking for a flatter-up round, so up to 20 billion.","offset":3830,"duration":8},{"text":"Host: Absolutely you would do that. 100% you would do that each and every day of the week.","offset":3838,"duration":5},{"text":"Jason: You'll put in your own 20 VC money at 20 billion?","offset":3843,"duration":3},{"text":"Host: I'm absolutely not, if I'm General Catalyst raising $10 billion dollars now, or I am Coatue with the multi-b—100%. Do I want to chuck a couple hundred million into Travis, one of the greatest founders of our time? Yes, I have to move hundreds of millions of dollars a month.","offset":3846,"duration":16},{"text":"Rory: I completely agree with you from our fund size, so far yeah. This is just so-this is just so everyone's a victim of their fund. If you're a seed stage fund you assess the guy, if you're a growth stage fund you assess the opportunity to put quantities of money to work, and if you're in the middle like us you look at the market trying to be intelligent and maybe overthinking it. It's funny.","offset":3862,"duration":21},{"text":"Host: Pro—if I have $9 billion dollars in my growth fund, putting 250 million with Travis here? 100% I would do it.","offset":3883,"duration":7},{"text":"Rory: Okay, good to know.","offset":3890,"duration":1},{"text":"Host: Would you-would you not agree with that rationale, Rory?","offset":3891,"duration":3},{"text":"Rory: I always struggle with the \"oh, just have a go, it's only\"—one of the—let me-let me put it on another term for you. You've got four and a half billion dollars a year. That is $400 million dollars a month you've got to move.","offset":3894,"duration":12},{"text":"Rory: I understand, but whenever you find your—I'll give you an honest answer. If you find your logic being reduced to \"I've got to get rid of this much money this month and this entrepreneur is amazing so I'm not sure about the opportunity and I don't like the price but have a go,\" if that's your logic, let me give you some advice: halve your fund size.","offset":3906,"duration":17},{"text":"Host: And that's why you're not playing the AUM game. That's why. Now, um...","offset":3923,"duration":4},{"text":"Jason: Look, for what it's worth I'll say one thing. I-I wrote this on Quora years ago and I-I had to write so many disclaimers about it because I was going to get hazed. But I wrote that uh the question was who's the-who's the best entrepreneur you've ever met, okay? And this was this was a few years ago so it was before I met more folks. And I wrote Travis Kalanick, best one I ever met.","offset":3927,"duration":18},{"text":"Jason: I met him when he was at RedSwoosh, his startup that um mostly failed, right? His-his uh whatever.","offset":3945,"duration":6},{"text":"Rory: For the record, made money for his investors. I remember the deal, he made money for his investors.","offset":3951,"duration":5},{"text":"Jason: Yeah, I went by his office in San Mateo, he was down to two employees I think, and had lunch, and this was before even YouTube had launched, okay? Sat down, and I never met a founder that explained the entire future of video on the internet to me with the clarity and insights that he did. My jaw—it was the first time I'd met a founder that could see the future in all the elements and how it all came together and explain it in a way that kind of blew my mind.","offset":3956,"duration":26},{"text":"Jason: And that's what you-and-and I if I look at my investing mistakes it's when I've invested below that line. When a founder has not come in and utterly blown my mind for the future of voice, right? The future of sales in the age of AI. Blown my mind. And and I took some heat, but I'm like I never had—that was the first time in my life I met a founder where I walked out of the meet my jaw was just on the ground because he explained the whole future to me.","offset":3982,"duration":25},{"text":"Jason: That's why I go to Rory's point. I guess if I was General Catalyst, I'd do the bet, right? Unless I thought he was washed up, unless I thought he was washed up.","offset":4007,"duration":6},{"text":"Rory: Yeah, I-I'm going to give you shit Jason because basically you're in the category of: I Jason wouldn't invest but I'd be delighted to let you—I think General Catalyst you should stick 400 million in. Because earlier on you were like \"I don't know if it's dated or not.\"","offset":4013,"duration":10},{"text":"Jason: I just think for me to invest at 20 billion with-for me, I have to believe he's not he can still do it. I have to have 100% conviction he can still do it to justify it. I think General Catalyst does not have to have 100% conviction, or Harry's math destroys me or I end up with a 1x fund if I invest with anything less than 100%—and I mean conviction at all levels, okay? Not just believing in the invest—like I have to know Travis is a thousand percent in for doing this for 20 years, at 51 or whatever he is, 48. I have to believe it.","offset":4023,"duration":32},{"text":"Rory: We're back into Kelly betting inadvertently. What you're basically saying is the percentage of your bankroll that you play, you know, it's-it's edge over odds or whatever it is, I'd have to think again. And what you're saying is for your fund—this is where fund size is strategy, right? On-on every dimension.","offset":4055,"duration":19},{"text":"Host: Mike Maples, Mike Maples said it first.","offset":4074,"duration":2},{"text":"Rory: Yeah, it's just so true. And what you're basically saying is you wouldn't because you don't have the edge and the return and the odds aren't great. But if you have a different kind of fund where instead of being 20% of your fund it's 1% of your fund, maybe you do. I hate that logic, but I understand it.","offset":4076,"duration":15},{"text":"Jason: No no no, I'm saying if I smelled some risk Travis isn't—is like he might be a little bit in the past as well as the future. That's a flag for me at-at the rate that I have to win.","offset":4091,"duration":14}],"startTime":2904},{"title":"Adobe CEO Transition & AI Threats","summary":"The announcement of Adobe's CEO stepping down without a clear successor prompts a discussion on the pressures public company leaders face. The hosts compare Adobe's vulnerability to AI creative tools against the relative safety of Intuit's financial software.","entries":[{"text":"Host: Okay we can choose one final topic. We can go for Adobe. They beat earnings, their stock tanked, and as a result CEO leaving. I bet 10 Shantanu's step down in 2026. That's my bet. 10 Shantanu's.","offset":4105,"duration":14},{"text":"Rory: I think you've got the I think the interesting comment and I want to hear Jason's comment 'cause he's worked there. Be precise in your sequencing: they beat earnings at the same time the CEO announced his resignation without a successor, and the stock tanked. It wasn't the stock tanked and then they whacked him. It was the two were announced together which is odd, and in response to one or both of those events, the stock went down. Correct?","offset":4119,"duration":26},{"text":"Host: Great. Yes, correct. Jason over to you 'cause I think your take is right here.","offset":4145,"duration":4},{"text":"Jason: Well look, there-there we don't really know exactly why he stepped down without a successor other than that it's odd, okay? It is odd because a lot of folks on the internet are saying David Wadhwani who runs Creative Cloud is going to be a successor. But this is David S—like he quit Adobe and went to AppDynamics and VC when he was passed over for CEO the first time. Then he came back to be CEO and then Shantanu steps down and he isn't made CEO.","offset":4149,"duration":25},{"text":"Jason: So that suggests to me the odds that he becomes CEO are less than 100%, right? Because certainly the most elegant thing is to hand it off to your president, right? Of your largest business unit. Then to say we need—the board's going to do a search while I step down—like there's just no way that's confidence inspiring, right?","offset":4174,"duration":18},{"text":"Jason: So I don't know what happened. There could be multiple things but to me it suggests he left the keys on the table after a very 18 years. Not five years, not was fired quietly, right? by the board. I don't think that for a million reasons, I don't think he was fired, he's very competent, right, very insightful.","offset":4192,"duration":19},{"text":"Jason: I think he left the—he calmly and respectfully left the keys, maybe after a quarter of discussion and um now they're going to go recruit somebody um and it's not a good sign. And I think we're going to see a lot of these. I mean, you know, Dustin Moskovitz quit his own company Asana in a hiss and left the keys, threw the keys on the ground, right? No successor, no anything.","offset":4211,"duration":24},{"text":"Jason: And these are not fun times to run most public companies. There's a handful—I mean Alex Karp seems to be having the time of his life, moved to a $50 million dollar mansion in Miami, he's-he's crushing it. Yeah, yeah, 'cause-'cause he's winning. But who else is having fun that's that's public? Not-not too many are having fun.","offset":4235,"duration":17},{"text":"Rory: The correlation between winning and having fun is pretty high, pretty damn high, right? And you're—and I tell you what, you're not having fun if you're the CEO of Adobe. And you're not having fun if you're any CEO who realizes—I going back to I think this you're spot on, going back to our where we started this conversation: \"oh, the only way to make my I have an obligation to my shareholders to make the stock go up, and the only way to make the stock go up given my growth rate's gone down is to sack 20% of the people I spent the last 10 years hiring.\"","offset":4252,"duration":27},{"text":"Rory: Now you might know it's the right thing to do, you might even be willing to do it, but it's not going to be your best week in the office. So I agree with you: it's a tough—yeah, I don't know if 10 quit this year, but I can totally see more than 10 saying \"should I quit this year?\" Going home and telling spouse and saying, \"now tell me exactly why you're doing this,\" right?","offset":4279,"duration":25},{"text":"Jason: I gave you 18 years.","offset":4304,"duration":2},{"text":"Rory: You know, we've all been on boards or where we've had to do CEO transitions and no matter what's going on underneath the surface, right, provided you've good relations and you've reasonable level of trust, you always go for the: leave the person in place, find the successor, announce an orderly transition, look like you have your shit together.","offset":4306,"duration":20},{"text":"Rory: 'Cause at the margin you never want to show you don't have your shit together. The only reason—so that's not what happened here. And there's only—to Jason's point, there's only two ways that that occurs: the first is if the board decides they want to make a statement, right? We-we, you know and I've been in those meetings where sometimes you're like \"you gotta go right now because there's crimes of moral turpitude, you're out, we've totally lost confidence in you,\" or much more likely \"the team's totally lost confidence in you, you're out.\" That doesn't feel like what happened here, right? Because he's staying on as chairman.","offset":4326,"duration":27},{"text":"Rory: If they've run the damn thing for 18 years, you probably should let him run it for another quarter or two while you line up their successor. So I don't know, I wasn't in the room, but it may well be some version of what Jason's saying is right, because you just go in as the CEO and say \"I my heart's not in it,\" right? It was a weird outcome.","offset":4353,"duration":21},{"text":"Jason: 'Cause it's interesting, now-now it's—someone wrote this point out that now-I mean Adobe had a great run, right? Um but now its aggregate returns are just below the S&P over the last decade or something like that. So when you look at that after 18 years and you're not really excited about agentic change—like you're not waking up each morning and saying \"I'm excited about my agents\"—this is a good time to leave the keys on the table.","offset":4374,"duration":24},{"text":"Rory: And-and to be clear, hang on, actually one thing I we're assuming something. He is continuing in the role until you get a new CEO? I just didn't check that. I think he is. Is that correct?","offset":4398,"duration":10},{"text":"Jason: I believe I think so.","offset":4408,"duration":1},{"text":"Rory: In which case it's not keys on the table, it's more making an announcement before you have the answer. It's a little less herky-jerky, uh, you know.","offset":4409,"duration":9},{"text":"Jason: I mean, it's leaving the keys on the table but still grabbing a drink at the-at the bar in the kitchen.","offset":4418,"duration":4},{"text":"Rory: Yeah no, it's \"I'll-I'll do the right thing,\" but um...","offset":4422,"duration":2},{"text":"Jason: \"I'm leaving the keys but I'm hanging out in the house until dad gets home,\" or whatever the extenuating version is.","offset":4424,"duration":5},{"text":"Rory: Yeah, yeah, metaphors never work, you should just say the thing instead. Um, it's—where-where is Adobe in five years' time?","offset":4429,"duration":5},{"text":"Jason: A massive installed base. You have a set of core—here's the meta issue. Um, someone on Twitter—the guy you just had, who'd you just have, the super smart guy, what's his name? The last one, Go—what's his name, sorry.","offset":4434,"duration":11},{"text":"Host: Gokul Rajaram.","offset":4445,"duration":1},{"text":"Jason: Yeah, super-off the charts smart. He made this thing on Twitter and everyone got it wrong, I think. Uh, he said—and-and because they misinterpreted—he basically said there's no threat to companies like Intuit and Adobe because it's so hard, but SMB is so hard to nail the price point and the motion that whether it's Adobe or Intuit which are still largely self-service businesses, right?","offset":4446,"duration":21},{"text":"Jason: Or whether it's a sales-led motion, these are almost immune from competitive threats because they're just so hard to get right, okay? And-so let me answer the question: here's the thing, there is a lot of truth to that as we've all seen. Um, I think it's true in all software. But it doesn't mean you grow.","offset":4467,"duration":16},{"text":"Jason: Just because it's hard to churn—here's the mistake so many people are making right now in the age of AI: just because your GRR stays high, just because your nominal churn is low, does not mean you're going to grow. And I see no evidence Adobe will grow. I see no products that-that show they'll grow. Nothing.","offset":4483,"duration":16},{"text":"Rory: I want to come on here and three things and then we'll wrap. Right? One is I just checked, he is actually staying on as CEO until the new successor, so it's more kind of an announcement without an answer, in which case changing my opinion here, it may well be the board also felt they wanted to send a statement, they felt the results were disappointing, they didn't want to have—they didn't want to attract a whole bunch of \"oh you need to make a change\" activists could show up.","offset":4499,"duration":23},{"text":"Rory: Maybe they thought that given these results they actually needed to state now that a change was happening.","offset":4522,"duration":5},{"text":"Jason: Pull it forward, pull it—maybe they felt they needed to pull it forward, right?","offset":4527,"duration":3},{"text":"Rory: In other words, please don't call us Elliott and you know shit Elliott Capital. We know we need to make a change, Shantanu wants to make a change, here it is. That would actually fit the facts pretty well. You are right if you've been the number two who've been passed over a second time, 'cause you know, if you need to make a change and you have a good number two and you feel the activists are circling, I tell you what you do: you-you hire the guy.","offset":4530,"duration":19},{"text":"Rory: But be that as it may, going to your second comment, the Adobe/Intuit—I really want to key on that because in my less than amazing—yeah I think Intuit has pretty durability over the next five years 'cause I think the thing they automate, which is accounting and tax, has some AI impact but it's not infinitely large and I think they can adapt to it, and we can argue that another day.","offset":4549,"duration":24},{"text":"Rory: I think the challenge for Adobe is: what kills you as a software business if the—if the—is if the if the work that you're automating gets done in a totally different way. Right? And Adobe and you know what we've seen: one of the—one of the area AI I saw it really good post on this I can't remember who wrote it: said most of the AI traction so far has been individual users, creators, you know, individuals even within the enterprise. It's not yet amazing great workflow tool, not all of it but most of it, right?","offset":4573,"duration":32},{"text":"Rory: Adobe is the classic creator tool. There is a whole new way to create. They're not—by definition they're playing catchup. So more than most companies they are under the gun to figure out how to meet their creators in a totally different way. So I think the disruption risk on those guys versus Intuit is a lot higher.","offset":4605,"duration":21},{"text":"Rory: Five years from now there will be some disruption Intuit but we'll still be moving money around, we'll still be producing quarterly accounts and I tell you we'll still be paying taxes to the US government. I don't know if we'll be doing pixel-by-pixel removing on Photoshop and therefore I don't—so I think the Adobe AI risk over the next five years is pretty large, and that actually probably should be figuring into their search.","offset":4626,"duration":24},{"text":"Host: Whew, we didn't cover much did we? Um that was uh...","offset":4650,"duration":3},{"text":"Rory: Bit more and more left.","offset":4653,"duration":1},{"text":"Host: Yeah bit of-bit of a materialist show wasn't it? Um guys thank you so much, that was fantastic.","offset":4654,"duration":15}],"startTime":4105}],"entries":[{"text":"Jason: Man, this is summer at Nvidia. I mean, they're on fire on everything.","offset":0,"duration":4},{"text":"Rory: These are unprecedented levels of CapEx spend and now we're forecasting them to keep going for four or five years.","offset":4,"duration":5},{"text":"Host: What are we discussing this week? GTC, what happened with Nvidia, Anduril's $20 billion dollar contract, then finally why $50 to $100 million dollar seed funds could be the worst performing size fund of this vintage.","offset":9,"duration":12},{"text":"Jason: I think Travis' Uber would be a trillion dollar company today because it'd be five years ahead of where it is today.","offset":21,"duration":5},{"text":"Rory: Wall Street is simple: if you give them growth, they leave you alone, if you don't give them growth, you better give them profitability. And if you don't give them either, they're going to bust your chops.","offset":26,"duration":6},{"text":"Rory: And today compute eats jobs.","offset":32,"duration":3},{"text":"Jason: You do not need to be technical to win with AI agents in Q2 of '26. You do not need to be even 1% technical.","offset":35,"duration":6},{"text":"Rory: The bigger your fund size, the more you have to be a power law junkie. There's no investment opportunity so good that excess capital won't destroy it.","offset":41,"duration":7},{"text":"Jason: You're going to get laid off because you're not going to matter.","offset":48,"duration":16},{"text":"Host: Guys, I'm so excited for this. We were just talking about where to start, so much news. And Jason, I think you're absolutely right, it's very important to start with GTC and Jensen and data centers in space. Obviously, Rory said, \"no, not going to happen,\" but maybe it does. How did we think about the data centers in space and last night GTC, Jason?","offset":64,"duration":27},{"text":"Jason: To me, I mean listen, the interesting thing, which you don't even have to watch anything, you just have to look at the Twitter stream is the sheer sense of energy and momentum and confidence there. And the confidence to do things—not only talk about data centers in space, but launch things like NeMo-Cloud, which are their version of Open-Cloud, to launch a partnership with Thinking Machines and others for their own open-source LLMs.","offset":91,"duration":26},{"text":"Jason: I mean, they're just going for it, right? And you can just smell the—I mean, obviously Nvidia is a pretty good stock and a pretty good company at the center of AI, but you can just smell the companies in decline, you can smell the companies struggling. You can smell OpenAI struggling right now. You can just smell it. You can smell the code red and the fact that they said yesterday, \"we have to concentrate on enterprise, we have to stop side projects.\"","offset":117,"duration":25},{"text":"Jason: It's not a—I mean, anytime you've worked with any startups you see the seasons, right? But man, this is summer at Nvidia. I mean, they're on fire on everything. And all the things where you see—and they're at risk, they're at risk from their customers using, um, TPUs from, uh, from Google and from Amazon. But man, everything from already integrating Groq to data centers in space to crossing a trillion dollars in bookings to NeMo-Cloud, it just feels like a company firing on about 13 cylinders.","offset":142,"duration":31},{"text":"Rory: Yeah, so I'll come back to your mis-portrayal of what I said later, Jason. But let's hit the main point because it's all about—in the end, it's all about the money, right? Super interesting kind of counterpoint on something. On the one hand, you had an extraordinarily aggressive number, a trillion dollars in revenue. On the other hand, the stock moved less than 1%. Why?","offset":173,"duration":22},{"text":"Host: It was already priced in.","offset":195,"duration":1},{"text":"Rory: Already priced in. And if you start parsing it out, I think what happened is as simple as this: If you look at the forecast, company did $215 billion dollars in revenue last fiscal year, up from 130 I think the prior year. You know, the forecast is mid-300s next year. So the soundbite was 25 and—sorry, next year I should say this year to be precise. The soundbite was half a trillion dollars of demand over the next two years, and that was a soundbite a year ago.","offset":196,"duration":29},{"text":"Rory: And now the soundbite is a trillion dollars in demand, but if you listen carefully, it includes '27. And lo and behold, if you go and check the analyst forecast for '27, it's in the mid-400s. So it turns out if you add 500 and 400 and then you apply a salesman's round-up, you get to a trillion dollars.","offset":225,"duration":15},{"text":"Rory: Another way of translating that wonderful amazing number of a trillion dollars is the analyst forecasts for the next two or three years look roughly right. So once the analyst processed that, the stock said, \"yep, nothing—no new information here.\" Which is just fascinating because what it says is, you know—this is a company by the way, for context, four years ago was doing $20 billion dollars a year.","offset":240,"duration":22},{"text":"Rory: Maybe five years ago now, actually—well, yeah, five years ago because we're in '26. $20 billion dollars a year. Last year did $215 billion dollars, 10x growth over four years. You know, about under 60% growth last year, forecasting 60% growth this year, and attenuating down to 20s, 30% growth in a couple of years.","offset":262,"duration":24},{"text":"Rory: So on one level not insane relative to past performance being predictive. If you have a company that grows 10x, saying it's only going to go 20, 30, 40% over the next couple of years doesn't seem unreasonable. But what it does imply is a massive level of CapEx continuing for the next four or five years.","offset":286,"duration":15},{"text":"Rory: That's fundamentally the bet. That's the big statement that came out here is: we think this level of CapEx investment is going to keep going for the next four or five years, we're reaffirming our estimates, and um, no—none of my customers are going to blink on our spend. That's the takeaway.","offset":301,"duration":17},{"text":"Host: Jason, I constantly go back to something that you said, which is we're going to see inference running 24 hours a day for a larger and increasing number of the worker population. If we think about that, in 2030 will Nvidia be a $10 trillion dollar company?","offset":318,"duration":14},{"text":"Jason: Oh, I think 10 trillion in revenue is more interesting because he's just predicted a trillion, right? And so...","offset":332,"duration":4},{"text":"Rory: No, cumulative a trillion! Again, we gotta be precise. Cumulative a trillion.","offset":336,"duration":4},{"text":"Jason: Yeah, no, it's a cumulative trillion. Can I—so, so how long does it take to do a cumulative 10 trillion? That's an order of magnitude, that's at the limit I think of general non-Andreessen level human uh ability to, to grok is about an order of magnitude. Um, so I think five years it will have a cumulative 10 trillion from one tri—I don't think it'll take five years to go from 1 trillion to 10 trillion. That's my, that's my bet.","offset":340,"duration":21},{"text":"Jason: I do think the inference thing—and listen, there's a lot of interesting things in the math. How fast, how fast will the cost of inference continue to fall versus the consumption of inference, right? Is there—will there eventually be a Moore's law an inverse Moore's law where it doesn't where we don't see the dramatic cost decreases we're seeing. Maybe that's why we need data centers in space. There's a lot of, there's a lot of complexity here.","offset":361,"duration":20},{"text":"Jason: But even if you think like, why, why the hell does Nvidia do NeMo-Cloud? Like why? Now Jensen said it's the most GitHub stars per unit time, faster than Linux, faster than anything. But I think the real reason is, is it uses a lot of inference. This is why all—everyone in China is giving—all the, all the providers are giving away Open-Cloud because you've got Grandma and Grandpa lined up on the streets outside of Tencent, Alibaba with their free Open-Cloud because it just burns tokens, right?","offset":381,"duration":28},{"text":"Jason: So, uh, part of it is Jensen saying, \"we're going to\"—and this is probably part of the, um, you know, big part of the Groq acquisition, \"we just want, we want you to be burning tokens at least 72 hours a day, we want at least three agents running 24 hours a day.\" So yeah, I mean, I think it's got to be three orders of magnitude more inference we run in the next five years.","offset":409,"duration":20},{"text":"Rory: You could have 3x more tokens but if the price per token goes down by 6x the revenue would decline. Just pointing out.","offset":429,"duration":6},{"text":"Jason: Yeah but it's going to be it's going to be like a—it might be 3,000 times more tokens not 3x. But yes, the math, same math issue, right?","offset":435,"duration":7},{"text":"Rory: Again, going back to my comment is, you know, someone unveiled a trillion dollar number and within, you know, 10 minutes the stock market processed to nothing to see here, right? Just points out the expectation of a, you know, railway boom, internet boom level of CapEx investment continuing unabated growing at 30% for the next four or five years. It's a pretty heroic assumption.","offset":442,"duration":24},{"text":"Rory: It's validated by the recent past, and there's nothing at this point to say it won't happen, but it is just worth pointing out. You know, for con—if, when Nvidia does 200 the CapEx spend is probably 4 or 500 billion because they get about half of it. If Nvidia is doing 600 the CapEx spend is probably 1.2 trillion, plus or minus. These are unprecedented levels of CapEx spend and now we're forecasting them to keep going for four or five years. There is at least some probability—pick a number, 30%—that it doesn't happen this way.","offset":466,"duration":28},{"text":"Host: Is there anything else that you think is notable from GTC before we move on?","offset":494,"duration":5},{"text":"Jason: The thing that stayed with me, and this is—I think there's a lot of interesting, I hit the things I thought were interesting. Um, but the message behind the message, right, was that, uh, open-source whatever models, everyone needs gigawatt centers. They all need massive amounts of data centers with inference, with GPUs, with everything and that it doesn't really matter. It doesn't matter.","offset":499,"duration":26},{"text":"Jason: And that the best models are still going to win, which is where he's made his bet. He's announced another open-source alliance, other things will win, but at the end of the end of the day his main point: we're going to win. We produce the best outputs, we produce the best, uh, we produce the best inference, we produce the best everything, and everyone needs data centers.","offset":525,"duration":18},{"text":"Jason: And that level of confidence that most rolls of the dice lead to Nvidia winning, um, you know, it's a—go—we can take shots at, at its armor, right, at its moats, but I think there's a high degree of confidence that most of the roads lead back to Nvidia reaching 10 trillion of cumulative, cumulative uh bookings over the next five to seven years.","offset":543,"duration":25},{"text":"Host: Speaking of playing for this game, Jason you said why you can feel energy in rooms. There are also tough times for certain companies where you feel other forms of energy. Two big announcements this week were in terms of layoffs: Atlassian announcing 1,600 people and then Meta reportedly a speculative 20% workforce reduction, which would be 16,000 of 79,000. We've spoken about layoffs before. Is this really just the start of the dominoes falling? Is this a an a sign of overhiring from 2021 and beyond and actually we're just relabeling it AI? How do we think about these very large scale layoffs from the biggest players?","offset":568,"duration":39},{"text":"Jason: Well, look, I don't know that much has changed from our prior conversations other than that, you know, everything we've said has come true. Um, this is every conversation at scale. Here's the thing: it's not—Atlassian and Meta are both interesting I think because, I mean, I guess they're all the same. It's not really about layoffs. Neither of these company has to lay off anybody, okay?","offset":607,"duration":23},{"text":"Jason: Atlassian has substantial free cash flow. Um, Meta I don't know, they're in the—their free cash flow has dipped but it's still like in the mid-40s, right? They don't have to do this. This is not a unicorn trying to figure out what to do with the last 20 million that SaaStr Scale and 20 VC gave it. Okay, this is a decision. This is a purposeful decision.","offset":630,"duration":21},{"text":"Jason: And what's happening behind in board meetings and in management teams is everyone's looking at the teams they have and saying, \"I just don't know what to do with half of these people. I don't need half of these people. I don't need them. I do need people. I need people—I need different people.\" And I don't, you know, there was a great LinkedIn post today, this morning, from the ex-VP of Engineering of Ping Identity.","offset":651,"duration":22},{"text":"Jason: Um, who said, \"this is going to be a sad post, I don't know if anyone's going to see it, but but my what I learned is over. The craft art of creating code, creating modules, testing it, being creative, figuring out how to do something that hasn't been done before is why I got into engineering, why my teams joined me, right? That era is over. Now the AI writes the code and all an engineer does is review the code, but now the LLMs are review—doing the code review. We won't need me anymore.\"","offset":673,"duration":29},{"text":"Jason: And everyone's looking at their team and wondering: why do I need that engineer? And do I need half my sales and go-to-market team? Do I need to brute force sales and marketing the way it was when the three of us met? You brute force sales and marketing in the enterprise. Everyone's looking and they're saying, \"I don't need to do these things.\"","offset":702,"duration":17},{"text":"Jason: And so, these are leading to radically different ways of thinking about the future. And some folks are going to be very slow on this, um, but everyone's talking about it. Everyone's talking about it, and just whether it's 10% or 40% or 50%, it's just an output of these conversations of: what people do I need in the new world? And most folks are probably half their teams are not the folks they need going forward.","offset":719,"duration":24},{"text":"Jason: Do you want to be kind about it like Mike? Do you want to be brutal about it like Zuck? Does it matter? I mean, I—I get—it matters to the humans but at some point we're going to end up in the same place over the next 36 months. The pace of change is so fast.","offset":743,"duration":16},{"text":"Jason: So but I do think it—the block thing, you could argue it's different and they're growing 2% like we talked about and and I think Marc Benioff said it was an—Block is different, right? But these conversations are in every boardroom. Even if you're in—your margins are in the 40s, in every board: we have the wrong people.","offset":759,"duration":19},{"text":"Jason: And everyone's un—is stressed AF right now, because including OpenAI, including Anthropic, everyone's stressed AF, and they need to reboot their teams for the future and they can't stick with people in the past. You just can't afford to, you're going to be obsolete in 18 months. And layoffs are just one way to re-engineer your company there, and as brutal as they are, they're just a small piece of re-engineering your company, and we're running out of time.","offset":778,"duration":26},{"text":"Jason: Everyone knows they're running out of time. Everyone knows. In—unless you're Legora or Shenora or Ladora, but even them know they're running out of time. They—in 12 months their current products will be obsolete.","offset":804,"duration":11},{"text":"Rory: That was helpful because I-I actually been thinking a lot about this layoff thing and I came in with four different categories um of really what's going on. And Jason's actually added a fifth that I'll come to last. And I think if you try and be logical and use categories, it just kind—I think yields more insight.","offset":815,"duration":16},{"text":"Rory: There's a whole category of layoffs that are really: we never should have hired these people, we got fat, we're using AI as an excuse but if you run the efficiency metrics, we just don't need these people, right? And I think there's some of that in there.","offset":831,"duration":12},{"text":"Rory: Then the second category is the, you know: we used to have a business growing at 20%, we're now growing at 2, if we were growing at 20 we'd need all these people but we're not, we're growing at 2. I need to give the financial market what it wants, and it wants profitability, right? Again, no com—you're not making any comment on the labor, you're just conforming to capitalism, right? And I think there's a lot of that going on in the SaaS world, right?","offset":843,"duration":24},{"text":"Rory: I think that first category Block is clearly an example of the first category, and maybe Meta, but I'll come to Meta in a second. I think a lot of the SaaS world is that second category of: I have to give—Wall Street is simple: if you give them growth, they leave you alone, if you don't give them growth, you better give them profitability. And if you don't give them either, they're going to bust your chops. Them be the rules, and if you can't give them growth you gotta give them the second. That's what the second is. That's a second category of layoff.","offset":867,"duration":24},{"text":"Rory: And someone interesting: the third category is starting to get into what Jason talks about. The third category is maybe you just—that you did need these people pre-AI but now there are AI efficiencies that allow you to do the same thing with less. That's probably true in coding, um, not sure it's true at the same scale across the board.","offset":891,"duration":20},{"text":"Rory: The four—one isn't the one that Jason gave me, but it is the Cap—it is the Meta example, right? It's that's something different: you spent all your money on computers, you need operating cash flow because you-you got that depreciation hit coming, right? I mean, literally that's reallocating dollars from humans to computers, right? To compute, right?","offset":911,"duration":24},{"text":"Rory: That's not what's going on at Block, that's not—because they're not investing massively in CapEx, but that is 100% what's going on at Meta because—Jason you actually wrong in that their-their operating margins are still 40%, their free cash flow when you honestly account for the CapEx is almost zero, right? And that depreciation's going to start hitting, and they're going to be firing people because they need to feed—give it to Jensen.","offset":935,"duration":24},{"text":"Rory: And today compute eats jobs. And that's what you're seeing at kind of Facebook, you literally can't afford to have Nvidia and people.","offset":959,"duration":8},{"text":"Rory: And then the last one that I didn't have that Jason's added to me, which I think actually could be more of it than I realized, is this idea that in some cases you actually are going to hire back. Maybe not as many people, but maybe at twice the salary, but just different people. And maybe there's a little bit of deck cleaning—I think if I'm right Jason, I hadn't thought of it, but deck cleaning going on in that maybe I don't need 20 engineers who all know, you know, C++ or Rust, maybe I need eight engineers who are just really awesome at AI.","offset":967,"duration":29},{"text":"Rory: My aha is if that's not going on, it probably should be in every company. Even if you don't have any of the first four, even if you didn't overhire, if business is still going strongly, even if you don't need to feed Wall Street, even if you're not spending it all on compute, you probably are doing, to Jason's point, a pretty significant talent reshuffle in real-time.","offset":996,"duration":22},{"text":"Host: I-I just wanted to ask Jason: if the people that we want are fundamentally different, the developers that we used to hire we don't because AI writes the code for us, the marketers we don't want, the sales people we don't want. Who-who do we want, genuinely? Like, what is the attractive profile? 'Cause your Anthropics and your OpenAI are hiring. So what are the people that we want in the companies of the future?","offset":1018,"duration":23},{"text":"Jason: Look, I know it sounds trite, but-but the answer is simple. It's just the expression each year changes. We want folks that are genuinely AI fluent. It's pretty simple. Now, you know, maybe last year we called them prompt engineers, right? That used to be a job. I don't know if you remember, that actually used to be the hottest job on planet Earth. Now no one needs a prompt engineer because it's pretty easy to prompt all these tools. That job died, okay?","offset":1041,"duration":23},{"text":"Jason: Um, and now we need go-to-market engineers. Um, I think that job's going to die. We need—everyone needs so many forward deployed engineers, like you can't hire enough forward deployed engineers. But, uh, um, but Palantir just announced in whatever their-their big event they've gotten their deployment times down over 90% with forward deployed engineers.","offset":1064,"duration":20},{"text":"Jason: So that may become—so this wave of disruption for the titles and the specificity, it's also exhaustingly accelerating. But it's really simple. You meet anyone for any role: sales, marketing, engineering, product, QA. They're-they're either—they can't keep all of the ways they use AI to accelerate their job from spewing out of their mouth, or they're staring at you. There's nowhere in the middle.","offset":1084,"duration":25},{"text":"Jason: Like and the person that comes in and says—it-it sounds Captain Obvious but like, you know you just had the whatever from Lovable, the marketing head that was super popular in the show, right? She's just spewing AI native insights into Lovable, right? It's not that complicated, you hire her. Elena or whatever it is. You just hire her. It doesn't matter whether she's still in college or a junior or a senior or a middle or a left or a right.","offset":1109,"duration":22},{"text":"Jason: And honestly, if you interview people, I would say of all—even of the best startups I've invested in, maybe 30% of the management team meets this standard, at best. 30%. Maybe less. And of the interviews I do in general, it's single-digit percents. It's just—and in-in that sense it's the same as ever. Like you either lower the bar in hiring or you hire someone that's actually great. And someone that's actually great is so far ahead of you in how to deploy to-to deploy the efficiencies of AI in their role, your jaw falls on the table.","offset":1131,"duration":31},{"text":"Jason: The difference is we used to need warm bodies. That's what's changing. We used to need warm bodies to answer the call, to do the QA, to do code review, to-to get the blue pixel to go from the upper left to the lower right. You laugh but you need—you literally needed to brute force this with humans.","offset":1162,"duration":18},{"text":"Jason: With AI every day that goes by, the AI—you do not need brute force human beings on your team. And that's another reason they're shrinking. Why are all these new companies so efficient? They're just not brute forcing things with humans. They're just not. They're choosing not to. And so these teams—all the brute forcers out there.","offset":1180,"duration":19},{"text":"Jason: Everyone talks about how bloated teams got in 2021. I don't agree with that. I think they got as big as they needed to be when growth was high and you needed humans to do everything. All—you look at these teams that doubled. Well, if growth continued at 60% like the rate in early 2021 for five years, Rory can help me do the math. And every single thing a software company did required a human, you were understaffed by your 2021 headcount. You'd be sitting here in 2026, you-you'd every office in SoMa would be triple-packed and there wouldn't be enough humans to staff your company. It's just the world changed.","offset":1199,"duration":34},{"text":"Host: Jason, you live on the bleeding edge. I think me and Rory see that and I think the world sees that when they hear you every week in terms of how you run SaaStr. For all of the CEOs and execs who listen to the show, what would you advise them in terms of determining whether someone is AI fluent when they meet them for jobs, for talent?","offset":1233,"duration":18},{"text":"Jason: Here's my—I realize I was just asked this. I just did a review with a super fast startup growing, just crossing 100 million. And I was asked this question. And one of my favorite executives I thought his answer was pretty dated and because he gave me an answer that was about six months old. The answer six months old is I look for folks in my team, I look for, you know, uh what tools they play with. Okay, that was a great answer in in like summer of 2025, okay?","offset":1251,"duration":22},{"text":"Jason: Um, I tried Lovable last week, okay? [makes game buzzer sound effect] The answer in 2026 is: what commercial AI tool have you brought into your organization this month? That's the test. Anyone that is on the bleeding edge that you would want to hire—now there are so many great products in the market, okay? There is no excuse in any role to have not brought one tool a month into your organization, okay?","offset":1273,"duration":29},{"text":"Jason: There—now there's going to be better and better tools and better and better products as the year goes on. What's the one you did? And you will see folks with their deer in the headlights to this question. What sales tool? What marketing tool? What product tool? What engineering tool? What did you bring in? Why did you pick it? How is it working?","offset":1302,"duration":16},{"text":"Jason: Because if you're at—remotely at the cutting edge, you're all over this. You're looking for the next agentic tools that will radically improve how you do bus—this-this is—you think—everyone thinks SaaStr is at the bleeding edge, right? You know, you know all we do? Is we're just looking for the tools and trying them. Okay? We're one year ahead of everybody else because we did the simplest thing in the world: like we tried the tools early and we trained them. We trained them for a month, okay?","offset":1318,"duration":24},{"text":"Jason: I'll give you—want to hear a horrible example from this week? Super hot AI company valued at six billion, okay? I'm not going to name it. Um, this week yesterday told us we had to quadruple what we spent on their product, okay? Their agent told us, right? And why did this happen? Okay, well at this six billion dollar company no one had trained the agent on its pricing properly. No one had tested it.","offset":1342,"duration":24},{"text":"Jason: They said, \"where-well we've been in beta.\" And we said, \"well when did the beta launch? A year ago.\" Okay, these are people asleep at-at the wheel. You want somebody who the instant this comes up they exactly know what the issue is. And \"hey, when I was at Lovable or Replit, we trained the agent, this is how we did it. I brought in this tool, I brought in this tool that-that Rory invested in last week, it solved all these issues.\"","offset":1366,"duration":21},{"text":"Jason: That's what you want to hear. And if they haven't brought in a tool in the last 30 days or at least deeply evaluated it—I don't really care whether they bought it, but gone so far down the funnel they can tell you, pick whatever tool, Fixer, Reggie, GC—AI GC, I don't care. How-how you went through it, you looked at it, you can tell me the eight ways it would improve the productivity of your business and three it didn't.","offset":1387,"duration":22},{"text":"Jason: Just don't hire that person because they're going to run your company into the ground. This is the job today. The job today is not to screw around on ChatGPT and to be a prompt engineer. The job today is to bring the best AI agent agentic products into your organization and leverage all the hard work that the engineers have done building those products. That's your job.","offset":1409,"duration":18},{"text":"Jason: You don't have to screw arou-you don't have to be a prompt engineer anymore. You have to be an Agent Deployment Expert, ADE. This is the new job we're making up today. An Agent Deployment Expert. That's your job from C-level to junior. Agent Deployment Expert. Don't hire anybody else. You're going to regret it. They're going to stare at the camera.","offset":1427,"duration":21},{"text":"Rory: He's good, he's good. Stare at the camera. He's on a roll. We could probably just slip away, get a coffee and come back.","offset":1448,"duration":6},{"text":"Jason: No, and I sound exasperated Rory, and the reason I am is I can just see—I can see my best company's doing it and I can see some companies I've invested in not doing it. And I want to cry. I just want to cry when they have no ADs on their team. I just—like you're flushing your years of your life down the toilet by not approaching your how you're building this company this way.","offset":1454,"duration":20},{"text":"Rory: Yes, and at the risk of being positive it's worth pointing out two things he didn't say, well—something implicit in what he said. Jason didn't do the only hire, you know, he didn't commit the um employment law I think it's a civil penalty of saying, \"only employ people below X who get the new new thing,\" 'cause he implicitly said anyone can do it provided you're willing to learn. And I think that's the big aha, that's one of the positive statements to make here, right?","offset":1474,"duration":24},{"text":"Rory: Look, and I think it applies—I'm always wary of being hit come across: \"hey this-this is the things that you all have to do.\" I think it applies to everyone including investors. Right? I mean I will say I have found that unless you're willing to invest the time learning these tools you actually shouldn't be an investing in them. I mean one of my partners Andy had this expression, you know, \"if you decide you want to stop learning new things you probably should retire within six to 12 months and never write another check again.\" For sure. And maybe that's down to three to six months at this stage, right? And I think, you know, it's, yeah.","offset":1498,"duration":30},{"text":"Host: I actually, Rory, I actually just had a meeting with mine and Jason's biggest investor the other day. Yeah. And I am pretending he's not here. I said I think he's the most equipped investor for this generation of investing, because I don't think anyone quite sits at the bleeding edge like he does on the investor side. Like...","offset":1528,"duration":16},{"text":"Rory: In terms of using the stuff, yeah.","offset":1544,"duration":2},{"text":"Host: Yeah, in terms of using the stuff, understanding, understanding bottlenecks, constraints.","offset":1546,"duration":5},{"text":"Jason: For sure. But can I just add one point? We can talk about—just 'cause it's so important if it helps people, okay? We are and thank you Harry. We're going through these phases, okay? And when AI started to blow up for real for us, uh call it early 2024, right? Maybe late '23. I wasn't equipped. It was too technical. I wasn't going to go in and figure out—I wasn't smart enough to figure out how to deal with a massively hallucinating LLM API and turn that and turn that into something magical.","offset":1551,"duration":28},{"text":"Jason: Kudos to investors and others that that got it in early '23, '22. I mean I remember I guess it was maybe SaaStr Annual '23 I was with David Sacks and I did a Q&A and I said, \"how you thinking about AI?\" at Craft. He's like, \"well we're all in, we want 80% in '23 of our investments to be AI.\" I'm like, \"great, but like show me the—show me the great ones in market.\" He's like, \"they're all prototypes. We're all—they're all proof of concept but we're all in anyway.\" That's where you kind of had to be in '23 if you weren't investing at like the LLM level, okay? I wasn't smart enough.","offset":1579,"duration":34},{"text":"Jason: Then we went through this weird ass prompt engineer era where like you you could torture these products to do something good, right? But you had to torture them. You had to like craft these crazy things that made no sense. Now we are in the era where mere ordinarily smart generalists can make these tools do magical things.","offset":1613,"duration":20},{"text":"Jason: And literally I go to these meetings and people are like, \"I don't know how to do this, it's so scary I don't know how to do this.\" And we show them our backends. Do you know how to do a workflow generator? Do you know how to do a um decision tree? Like we've been building these since software in the 90s, okay? If you—I can show you all of our agents. The-the how they work is novel. They do have to be trained, you can't be LAF [lazy as fuck] and have these agents work.","offset":1633,"duration":24},{"text":"Jason: But honestly, the UI, the UX, the way we interact with them, it's just software. And so my point is: pick yourself off the ground. This is your time now. If you felt lost in AI era, if you felt like you're behind, you don't understand what all these people are saying on X and Twitter in their claws and and talking about all the 4.6.nano.whatever and it's over like you just that's not your world. This is your time.","offset":1657,"duration":24},{"text":"Jason: This is your time for the generalist that knows how to use software tools really, really well. And this is my last point, but it's so important. If ever in your recent life, and this is why you could be all you need to be is young at heart, to Rory's point. If in the last three to five years you have successfully deployed a piece of enterprise software of any sort—you yourself, not some agency you hired—but if you have deployed it, you can deploy any agentic tool. Any.","offset":1681,"duration":25},{"text":"Jason: And you can become the hero in your company and you can become the hero in your functional area. But I watch folks—I'm literally helping a company now, they're adding hundreds of sales folks this year with the new pre-AI CRO. He's not—hasn't brought in a single tool, he's scared of it. Okay? It's not that hard. Did you use SalesLoft? Did you use Outreach? Did you use HubSpot? You know these tools? If you can deploy these tools, you can deploy a world-changing AI agent.","offset":1706,"duration":26},{"text":"Jason: And so, this is the time for people. Like the folks that that were shut out of the AI revolution. Right now the generalist folks that are not—that know how to deploy software, that don't even know how to build software. Like vibe coding for me was folks who knew how to build software but you didn't have to be an engineer. Now you just need to know how to deploy software to win with AI agents. That's all you need to know.","offset":1732,"duration":21},{"text":"Jason: So many people have these skills and they're petrified of AI. \"How did you do that? How did you deploy an AI BDR?\" Well, we bought a piece of software, we figured out how it worked for a day, we set it up in an afternoon and then, and then we did spend 30 months training it, which you didn't do with this old software.","offset":1753,"duration":16},{"text":"Jason: Because in the old days we just had to manually upload all the data, right? And there was no training. The only non-intuitive part is training these things. And it's-it's just work. Um, so that's why when I see folks on the management team not doing this, there's no excuse.","offset":1769,"duration":15},{"text":"Jason: You do not need to be technical to win with AI agents in Q2 of 2026. You do not need to be even 1% technical. Not at all. So it's your time. It—or you're going to get laid off, or you're going to get laid off because you're not going to matter.","offset":1784,"duration":16},{"text":"Host: You said not mattering there Jason, uh and thank you, that was impassioned rant that I learned a lot from. And I love ADE, that's a fantas—I think you should coin it. I would say write a book, but I don't think writing a book is ever useful these days given the speed of news and frankly attention...","offset":1800,"duration":15},{"text":"Rory: Given that no one reads them, yeah.","offset":1815,"duration":1},{"text":"Host: Yeah, 100%. The amount of VCs that write books I'm like \"seriously what-what are you doing, wasting a year doing this?\" Um...","offset":1816,"duration":6},{"text":"Jason: Well you get your friends to go on the book tour with you, there's something to be said for that.","offset":1822,"duration":3},{"text":"Host: Oh yeah, great, yeah yeah yeah. Totally totally. Come on, we're actually meant to add value here, keep going.","offset":1825,"duration":5},{"text":"Host: Okay, Anduril lands $20 billion dollar army contract. The reason I said this is when you said about just mattering. I remember reading this being like: $20 billion dollar army contract. 10-year deal, five-year base and a five-year option to consolidate 120-plus separate procurement actions into one enterprise contract. Um, it's enormous. I-I when I read this I was like, God, the shit I do just doesn't matter. This sweet little unicorn company that's going from 1 to 4 million ARR. How did you guys think, analyze this $20 billion dollar annual...","offset":1830,"duration":38},{"text":"Rory: Well, first of all, yes it's obviously a vast contract, but as a reminder they have four or five on—they only have four or five customers. So you better get 20 billion from each of them if you want to be a big company, right? I mean, what it really told me is they've succeeded, right?","offset":1868,"duration":14},{"text":"Rory: Basic—'cause this isn't as much a new program, this is basically the army saying: \"look, we got 120 separate contracts with you, we get it, you're now effectively a prime supplier. Why don't we consolidate all the paperwork so that people one level down have less process to go through every time to buy your stuff, right?\"","offset":1882,"duration":18},{"text":"Rory: So it's a-it's a—both a procurement thing, and also there's a systems lock-in here. I think the primary product I think they're talking about is their Lattice, which is their software connectivity system. You know, you've got all these different physical hardware products out there. Some made by Anduril, some made by other people, right?","offset":1900,"duration":19},{"text":"Rory: And as is becoming clear in recent conflicts, a huge part of the problem is making all these systems talk to each other, dare I say it, autonomously and quickly, right? And connecting all these things in not just near real-time but real-time. Because, you know, as we're learning right now, it turns out if you're in the Strait of Hormuz you've got literally seconds before you can take down an incoming drone.","offset":1919,"duration":20},{"text":"Rory: You don't have time for a slow connectivity protocol. You definitely don't have time for a human. So you need this integrated communication system that connects all your different physical hardware offensive and defensive weapons. And I think it looks like the product that these guys have, that Anduril has, is becoming at least the primary default for that, for effectively moving information between different systems.","offset":1939,"duration":25},{"text":"Rory: So it makes sense for what the Pentagon's doing. They're basically saying: \"look, we've gone from trying you out in a lot of different areas to saying okay damn it, you're the dominant provider of this layer, so why don't we just systematize the contract.\" It kind of picks them as it picks them as the clear new prime.","offset":1964,"duration":18},{"text":"Jason: I'll tell you to answer Harry's question and this may be wrong. Like this may be a flaw in me, like I completely concede this. But Harry's part of—part of Harry's question was, \"hey am I investing in things that don't matter when Anduril has a $20 billion dollar contract.\"","offset":1982,"duration":15},{"text":"Jason: My version of—I-I feel that. And my version of this is I have given up on an-an investment thesis I had for 10 years because I was a B2B founder, which is that uh a smallish TAM is okay with a great founder. Start small, okay. Fine. But you know what? Every—thing we can all point to small things.","offset":1997,"duration":18},{"text":"Jason: For me, you know when I started E-Signatures, the TAM was 2 million. It was 2 million. Obviously if you just look at Rory's investment DocuSign, it is doing more than 2 million today, as I haven't checked the latest quarter, but even with some challenges the TAM certainly grew, right?","offset":2015,"duration":12},{"text":"Jason: So as soon as I realized that, I'm like: I'm investing in areas that are going through phase transitions with great founders and they will grow the TAM, right? And for sure we can show if—I hate to do trite things we've done, certainly the legal tech space is one that has shown an explosion in TAM, right? Because of AI. So there's many examples.","offset":2027,"duration":18},{"text":"Jason: But, but, in my heart and soul I can't do any of those investments anymore. I can't. I can't invest in anything that is mid-sized or smaller. I just can't. This is the Anduril problem. And this is also why I think a lot of funds are going to have terrible returns. Because a lot of early stage funds are going to swing so hard for the fences that they're going to invest in the number three or the number four and get just zeros after zeros because there isn't a chance to stairstep your investment.","offset":2045,"duration":23},{"text":"Jason: There isn't a chance to go from the $50 million dollar TAM to the 150 to the 500. So I think there's going to be a lot of zeros. But I can't help myself, and literally I can't even—I don't like—I can't even bring myself to take a meeting with a startup where I don't believe the TAM will be utterly massive. I just can't take the meeting anymore.","offset":2068,"duration":18},{"text":"Rory: Jason, you you—there's a lot in there. I want to unpick it and frankly be more precise. Right? What you say—I think you're saying two things, just to be clear. When you see what a big TAM feels like, and let's agree um the com system for the Army probably is one of those big ass TAMs, right? You're saying is: you just can't get excited by super small TAMs. That's one statement.","offset":2086,"duration":22},{"text":"Rory: And the second statement you made is: if everyone's thinking like that, they're all going to do a swing—they're all going to swing more aggressively at the big TAMs but in the third or fourth player in those TAMs and probably lose. Is that what you're saying?","offset":2108,"duration":13},{"text":"Jason: Yeah, and-and even worse: they're going to pay up 100 pre for these seed investments because it all—because as the best accelerators tell us, it doesn't matter in these big outcomes. It doesn't matter whether you pay 60 post or 100 post at a top accelerator because when it's a hundred billion dollar outcome, that's a better return than a unicorn, right? Mathematically it's true, but I think it's going to lead to a lot of zeros.","offset":2121,"duration":21},{"text":"Host: But Jason, do the best markets not start small? To your point there when you said—to your point—do the best markets not start small?","offset":2142,"duration":7},{"text":"Jason: I don't believe it anymore. That—the de-fense—I be—Rory correct me if I'm wrong, I still think defense is the number one largest segment of our spend in the country, maybe healthcare is number one and defense is number two, right?","offset":2149,"duration":9},{"text":"Rory: No, defense isn't actually—shockingly defense isn't that large. We just spend a little over 3% of GDP on it. And turns out most of that—not most of that—a good slug of that, almost half is people. It turns out the actual amount of money—what—I'll make a comment: it's not counters. I think Anduril's going to do amazingly well.","offset":2158,"duration":19},{"text":"Rory: The Pentagon budget for new shit is fairly finite. And I think there'll be five or six big winners in defense. I'm not sure there'll be 100.","offset":2177,"duration":7},{"text":"Jason: Um, but but isn't that the game of venture? Is five or four—not 100?","offset":2184,"duration":4},{"text":"Rory: What? But that's the game of venture is to find the four or five, not the hundred.","offset":2188,"duration":3},{"text":"Rory: Agreed. So and that's my point is that, you know, power law—the thing about power laws is they get in your head, like it's getting in your head, and you can over-project from: nothing matters except the hundred billion dollar outcome. Well, if you own 10% of a hundred—of a billion dollar outcome and you are a $100 million dollar fund, that's a 1x fund.","offset":2191,"duration":17},{"text":"Rory: So I-I hear you, I understand what you're saying. The bigger your fund size, the more you have to be a power law junkie. At some level you want to be a power law junkie because in the end even if you have a $100 million dollar fund, wouldn't you prefer to be in the trillion dollar outcome than the billion dollar outcome?","offset":2208,"duration":15},{"text":"Rory: Right? The question is: when does that focus on the power law, could it become overly myopic and and lead you to swing—you know, you know where gamblers can go on tilt? Where they're so desperate to earn, you know, their money back that they start swinging at anything?","offset":2223,"duration":15},{"text":"Rory: Right? And, you know, if you're like: \"oh my God, I just gotta get—I wish I'd done—is someone saying I wish I'd done OpenAI or Anthropic therefore I'm going to fund eight next-gen foundation models because maybe one of them will be like that,\" right? That's another failure mode that as you said could happen.","offset":2238,"duration":17},{"text":"Jason: We might be seeing that happen right now, right?","offset":2255,"duration":2},{"text":"Rory: That's my point. So I-I'm not sure I fully—I hear you on the small—no one wants to be in a small TAM, but almost as important as TAM size, there's two other things: there's TAM velocity, for lack of a better word, your ability to dominate that TAM. There are mid—small and mid-tier markets that are wildly profitable software markets for the winner, and you can make, you know, really good coin in a four or five billion dollar market with a great outcome.","offset":2257,"duration":26},{"text":"Jason: But not if-but not if your entry point is-is what they are today.","offset":2283,"duration":3},{"text":"Host: Totally.","offset":2286,"duration":1},{"text":"Jason: Yeah, no, totally. The thing is now that like YC has productized a $60 million dollar post, right? Nothing wrong with it, I'm not criticizing it, more power to them, right? But what is as a seed investor—I mean Harry made this point that all these classic seed investments can't make money, right?","offset":2287,"duration":15},{"text":"Rory: Just, agreed. You can't go into a game paying power law prices for mid-tier market outcomes. For mid-tier markets. Because you're exactly right.","offset":2302,"duration":8},{"text":"Jason: That's the game today. But that's the game today.","offset":2310,"duration":2},{"text":"Rory: I keep—I understand. That's a fair comment. That's a—as a combined comment that's fair, is that if you price every deal like \"quote unquote\" it might have a two billion dollar or 20 billion dollar contract, most of them won't.","offset":2312,"duration":13},{"text":"Jason: Harry wouldn't do this, but if a founder came—a classic founder came to me with a-a structure that made sense and I believed in them, I might still take the bet, but at 60 post for a pre-seed investment, right? You-you can't risk that it's not Anduril or better. Like you can take risk it doesn't happen, but you have to believe the TAM the opportunity is so large.","offset":2325,"duration":20},{"text":"Jason: How else you're going to get your 100x with dilution? Right? That's 250x in today's world, uh post-dilution and everything. What's help me what's 250 times six billion—60 million post? Like lots.","offset":2345,"duration":12},{"text":"Host: 13, 14 billion.","offset":2357,"duration":1},{"text":"Jason: Yeah. So let's round up to 20. How many public companies—tech companies today have market caps north of—not as many, less than when we started this podcast. The math is grim.","offset":2358,"duration":10},{"text":"Rory: Yeah, no, I have that count somewhere. Sub-50, yes.","offset":2368,"duration":3},{"text":"Host: No, I mean I think that if you look—Jason, if you take this mindset though, like genuinely, when a deal comes through the door, what is big enough? Because, you know, you've talked about your Qualifieds and your Artisans and your Monicas. Are they big enough? Like, SDR AIs? You know, I'm seeing like constant call center replacement for healthcare assistants, for auto manufacturers. What is big enough?","offset":2371,"duration":23},{"text":"Jason: Well, some—well listen, there's-there's arguments they are, right? If you look, um the—but what-but I think it's why the growth fund is the winning strategy at the moment because they wait for the proof. Okay? It's easy to be cre—take any—I mean I-I'm getting bored of talking about the same companies, but for to have a thread through our conversation, certainly I-I wouldn't have believed that—being in this space, having made so many investments—I wouldn't believe that Decagon and Sierra—now granted the revenue multiples are very high, right?","offset":2394,"duration":25},{"text":"Jason: I wouldn't have believed they would be doing what they're doing. I'm not even sure I would have believed to-to Rory that Intercom would have re-accelerated as it has or others. I wouldn't have believed it. But the beauty to-to doing the deal when Rory did it is he gets the proof points. That's when—that's why it's such—but hoping that a slide and a vibe-coded website proves it is tough.","offset":2419,"duration":24},{"text":"Jason: But Harry going to your point, like what—there is a bull ca—there's—this is—I'm not saying I'm right. Like here's the counter-argument where I'm wrong, right? And this is Captain Obvi—but like, the reason and like—I mean I barely know Decagon, but they just talked about it this week, and and uh and Owen talked about it last week. All these spaces are converging.","offset":2443,"duration":17},{"text":"Jason: So Owen said there's not going to be any difference between support and sales in a lot of what we do. All these agents are converging to a meta—a meta agent that does more, replaces a lot of humans and is worth a lot. Okay? If that bet comes true—and it's already happening—then your TAM but here's my point: your TAM explodes, right? Your TAM explodes, right?","offset":2460,"duration":18},{"text":"Jason: The question is: will you invest in a space where there's no evidence that the TAM is exploding due to AI? That's-that's where it's tough, right? Will you invest in—and it's kind of the question that you're asking, uh Harry.","offset":2478,"duration":12},{"text":"Rory: I don't understand what actual—the actual—what you're actually articulating. I mean, yes, it turns out, yeah, seed investing is harder than A, and on a deal-by-deal basis is harder than A and B, which is harder on a deal-by-deal basis than C, D and E growth investing.","offset":2490,"duration":17},{"text":"Jason: I'm just saying you can't take the smaller TAM the stairstep risk. The classic VC seed stairstep the TAM risk. Take a—take something that starts small, that has a-a nuclear core that's stro—that's strong and then build—add TAM layers over time, right?","offset":2507,"duration":16},{"text":"Host: But Jason, but Jason, if I go to-if I go to like Replit or Lovable at the seed, vibe coding at the time was a very new and nascent category. I don't think you could say the TAM was particularly massive. It was a small market.","offset":2523,"duration":15},{"text":"Jason: Well, look, I-I'm first of all I'm completely starting this conversation by saying I'm not sure this is necessarily a good thing that I'm criticizing myself. I've changed. I've changed my perspective. I used to stairstep everything, right?","offset":2538,"duration":13},{"text":"Jason: And even the investments I made that weren't stairstepped, I would invest in something that had like a terrible terrible comps because I believed they were being remade by the space and would be much bigger. I just don't feel that-that vibe anymore, right?","offset":2551,"duration":10},{"text":"Jason: I actually think the—the like the Replit round that blows my mind when I think Craft and some other folks did it at a billion in Replit in like '21 pre-AI? Like they did like Replit at 10 million and 8 million in revenue pre-AI. I would have not have been that omniscient, okay? Like good—it's not that I wouldn't have bet in on Amjad, I mean he's a force of nature.","offset":2561,"duration":22},{"text":"Jason: But pre-AI this weird web IDE that doesn't do much and doesn't even doesn't finish any software? Like, I ain't that visionary. But, but, but, I think if you ask Paul Graham or or David Sacks, they would say, Harry, listen, I mean revolutionizing how we do software development on the web is massive. Like this is going to—I know you don't see it today, but-but I actually think you could argue the TAM is very large, right?","offset":2583,"duration":25},{"text":"Jason: If we really believe Amjad is going to take this-this kid out of the wonderkid out of Facebook who brought the co-you know the guy that created React with him to co-found the company. These guys—these two guys—they just might re-change how we build software, that's a big TAM, right?","offset":2608,"duration":16},{"text":"Jason: Now little—now where I struggle is when I meet founders doing little niche things in vibe coding. That's where I'm struggling today. Oh, I've got a little thing that does a hint of security on these platforms, right? Or makes or makes the objects prettier, okay? Like I-I design is terrible in Claude Code, it's unacceptable in-in OpenAI, it's it's um it's ba—it's—but and so there's a lot of folks trying to tease at design, right?","offset":2624,"duration":25},{"text":"Jason: But is it big enough and will the models just take it over? Uh you better show me something like hyper-disruptive like my jaw falls on the ground or I just don't believe, right? Replit I might have believed but this little niche fixing the fact that the icons all look like Claude artifacts, I just don't believe. But you could say it's bigger than Figma.","offset":2649,"duration":21},{"text":"Rory: But what am I meant to do with all this? I'm just trying to understand how I do my job differently tomorrow because of this information. Genuinely Jason, like...","offset":2670,"duration":6},{"text":"Jason: Yeah, you raise a growth fund like all of our all of our friends do. You raise a multi-ten billion dollar growth fund and you just wait until you have extreme product-market fit, right?","offset":2676,"duration":9},{"text":"Rory: But again I think you should assume that, look, the great thing about American capitalism is money fills any void. Like there—and-and-and it's the Barton Biggs quote I've made very often: there's no investment opportunity so good that excess capital won't destroy it.","offset":2685,"duration":14},{"text":"Rory: You're right. There's a period of time, look, I think you'll look back and go the growth investments in '17 and '18 were awesome because they sold in '21. The growth investments were '21 because they priced in '21 and then they were shit, um because the revenue slowed down and the exit market died.","offset":2699,"duration":20},{"text":"Rory: The growth investments from '23 on that were LLM-centric were amazing, and from the growth investor perspective needed more capital than was easily available. There was a period of two or three years where, you know, the capital needs of Anthropic and OpenAI were unprecedented as were several other companies. And when capital needs are unprecedented the people selling the capital can do actually better at the margin.","offset":2719,"duration":22},{"text":"Rory: Take that and have some insights as well about the future you can make money. Now the wall of money's come back in, and I'm sure growth will go through the same thing again which is everyone will pay a hundred times run-rate revenues for late-stage stuff they think is growing quickly just as in '21 people thought they're growing quickly. And fast forward some will work and make people look really smart and some won't, right?","offset":2741,"duration":19},{"text":"Rory: Whenever you're investing you have to have some marginal insight more than the other guy about why this thing that is at whatever stage it's at, yeah, can outperform and be bigger over the next X years. Once it becomes consensus and the capital arrives, then it's just very hard to have excess returns.","offset":2760,"duration":16},{"text":"Rory: And look and one of those ways of non-consensus is funding these small markets that can expand. 'Cause I don't agree that—one of the things we often think about stepping back is we actually because the stage we invest is early product-market fit and our highest level rule of thumb has been the big aha is: we want big picture trends and near-in traction. We don't want to compromise between the two.","offset":2776,"duration":23},{"text":"Rory: We want something that's working right now, which could be something small that's working right now as a—you want something that's actually a thing right now with early product-market fit. But you're right Jason, where you are correct is: you don't want something that's a cute little thing now but could converge and there's just no white space.","offset":2799,"duration":14},{"text":"Rory: You want—yeah, and taking that and saying the Anduril example: yeah, if you had done a post-product market fit investment there in 2018, you know, unfortunately we didn't, would have been their near-in product and everyone half the country can get mad at this right now was watchtowers for the US border, right?","offset":2813,"duration":22},{"text":"Rory: That was the near-in traction, they had really good traction on that, and that's the near-in product. And if you applied the lens of: how big is the market for watchtowers on the US border? The correct answer is: bigger than you think, but goes up and down every four years depending on random exogenous events, right?","offset":2835,"duration":16},{"text":"Rory: The US Defense Department has purchased things on cost-plus for 40 years and is wildly inefficient, and Anduril is going to let them purchase things on a Silicon Valley \"we build the product upfront and then we sell it to you on a,\" you know, per-unit basis, right? That's the big picture trend.","offset":2851,"duration":17},{"text":"Rory: So from the A on you have to have both, some near-in traction, something to hang your hat on, but then to avoid the risk you're talking about, you gotta be able to articulate an expansion story. Now the trick becomes anyone can use words.","offset":2868,"duration":13},{"text":"Rory: Like because technically take your Replit example, you're right: you-you can, yeah, if you squint one way it's a-it's in 2021 it's a tiny little tool for a niche case. If you squint another way and use big high-falutin words it's the future of software and democratization of software. And it turns out the trick in investing is to figure out which of those words is bullshit and which is not.","offset":2881,"duration":23},{"text":"Host: I-I do want to talk about Travis Kalanick, um came back in in force with Atoms. Um and to be clear, eight years in stealth, thousand employees, rebranded City Storage Systems and CloudKitchens which is more well-known into this new company Atoms building gainfully employed robots: food, mining, transport. He came out with a pretty um I don't know if you'd say scathing, but a an opinionated piece: \"I bled but I did not perish.\" He wants to be more aggressive than Waymo. How did we read this guys?","offset":2904,"duration":38},{"text":"Rory: I thought on the—I thought on the merits of what he said about robotics that he's correct, and was pleased 'cause it's something we've believed. So as again to remind the viewers it's obviously Travis Kalanick, the wildly successful founding CEO of Uber, famously terminated by the board, enduring feud with Bill Gurley, which can cycle back to the Anthropic um Pentagon discussion 'cause uh Travis's number two is now driving at the Pentagon and also showing an ability to maintain a grudge, which is just one of those things you've just gotta admire in people.","offset":2942,"duration":29},{"text":"Rory: But anyway went away, founded CloudKitchens, surfaced last week and basically said: it's not about CloudKitchens anymore, it's about robots. And Atoms is building robots for a variety of industrial use cases. And he has an investment in Pronto which is an autonomous driving um company, uh founded by Anthony I-I always mangle his last name, my Polish sucks, Levandowski, who was with him at Uber, right?","offset":2971,"duration":29},{"text":"Rory: So it's basically coming back and saying: \"I-I was doing CloudKitchens, I'm now using that information to build robots and I'm also thinking about autonomy,\" which obviously cycles back to Uber. So that's kind of the background. I thought he was spot on on the robotics call, and let's be clear what he said.","offset":3000,"duration":16},{"text":"Rory: He said he didn't fundamentally think humanoids are the answer. He thinks robots on wheels are the incremental next step. And the big aha that-that Travis had was: it's not clear if you're building an industrial machine for a lot of use cases that you add legs. The you know, the humanoid robotics that we all see, they have these legs, they consume a lot of battery life, they're pretty unstable.","offset":3016,"duration":27},{"text":"Rory: And most of the time in factory work or logistics, warehouse work, you don't want someone using—you don't need legs, you just need wheels, right? They're a lot more efficient. And I think it's a big picture insight of Travis to say this is the direction things are going.","offset":3043,"duration":15},{"text":"Rory: And you know worth pointing out is he's effectively making a call against a whole bunch of the humanoid companies. Not saying it's not going to happen ever, but saying it might take a a lot longer than you think, and the path to humanoid robotics might be through specific-purpose non-humanoid type machines maybe expanding over time. So big ass call on robotics that for what it's worth I agree with.","offset":3058,"duration":25},{"text":"Rory: And it's interesting: just one more comment is Sunday, which just raised recently, which is another one of these robotics companies focused on the home, if you actually look at the form factor they've gone with um wheels too. Right? If you look at the—it's very cute, it's a really cute robot, it's kind of nice happy plastic, but you look at the—on the ground and it's actually running on wheels.","offset":3083,"duration":21},{"text":"Rory: Because they too have recognized that spending the money to give feet to many robots is just a waste of money here, right? Because you don't need them. So I think actually on-trend he's correct.","offset":3104,"duration":10},{"text":"Jason: The main thing when I saw the T-B-N interview, the main thing I thought was um if he were running Uber today it'd be a trillion dollar company. Without que—I-I mean to me without question in today's world. It's-it's his time. Uber's 160 billion dollar company with massive free cash flow and it is epic.","offset":3114,"duration":20},{"text":"Jason: And it you know, I think the-the-the his hyper-aggressiveness which in a different era led to his downfall, which I come back to, but it worked, right? It destroyed Lyft. So his-his view that like: if you're not as a-a 57 on the 1 to 10 scale of hyper-aggressiveness you're not going to win this, and this is the era we're in today, right?","offset":3134,"duration":22},{"text":"Jason: He was just too early, like and there was toxicity to him and there's elements of, you know, treating women and other things that are probably terrible and not okay. Putting that and it's hard to, but putting that aside he-he was just early for his time. And look at Uber today, despite that, wildly successful, but mostly been engineered since then, right?","offset":3156,"duration":19},{"text":"Jason: Acquire, get into food delivery, which is huge for it, but a lot of that's through acquisition and managing his existing fleet. And when Travis was CEO, all he wanted to do was get into autonomy. He said from the beginning, \"our business is dead at its terminal state. No one is going to be driving cars in an Uber.\"","offset":3175,"duration":-1065},{"text":"Jason: And now they're years and years and-and years behind where they could have been. So when I look today, the trillion dollar companies are becoming commonplace. I think Travis' Uber would be a trillion dollar company today, because it'd be five years ahead of where it is today. And that's all I thought.","offset":2110,"duration":1095},{"text":"Jason: Do I actually think this CloudKitchens eight years out in the the-the winterland, do I think it's going to make it? Probably not, right? But that guy, that guy would be running a trillion dollar company today if Gurley and buddies didn't force him out. That's what I thought.","offset":3205,"duration":13},{"text":"Rory: I disagree. And so, picking apart the argument...","offset":3218,"duration":4},{"text":"Jason: Would you have pushed him out?","offset":3222,"duration":1},{"text":"Rory: I'll come back to that at the end of this conversation. I will answer I will answer that question. But first of all, it's interesting you made-you made a comment here: \"CloudKitchens I don't know if I believe in it, but Uber would be a million dollar a billion dollar a trillion dollar company,\" that's what you said, right?","offset":3223,"duration":14},{"text":"Rory: Implicit in that statement is a repudiation of the logic of it, which is: you're saying the great founder is everything, but what you're saying is the great founder can't make this company worth a trillion dollars. So implicitly what you're saying is it's the great founder plus a great opportunity. It's not quote unquote all about the founder.","offset":3237,"duration":15},{"text":"Jason: Well he has to start from scratch now.","offset":3252,"duration":2},{"text":"Rory: Yeah, but yes. But my point—my point—starting from 80% market share in-in rideshailing's a pretty good platform to start from if you start if you know everything about the industry every inch every-every every everything every inch of this industry you know it cold.","offset":3254,"duration":13},{"text":"Rory: So now let's talk about that, right? Dara had to drive Ubers to learn it, and bless his soul he's great, but he had to drive cabs. Travis didn't have to drive any cabs to learn how Uber Uber worked, like he already knew he already knew how it worked.","offset":3267,"duration":13},{"text":"Rory: So give-let's ask a question here: given, okay, so let's talk about that, right? And I want to leave aside the inap—the personal behavior stuff where I frankly don't have visibility and I'm genuinely not going to try and make a call on that. The hypothesis that Uber instead of being a 160 billion dollar company would be a trillion dollar company implicitly has to be some ver—the only thing that could bridge that gap would be autonomous driving, correct?","offset":3280,"duration":25},{"text":"Jason: Well, no, you would you would be five years ahead of autonomous driving, which is-is already is now taking off, and I think you would dominate food delivery more than it does. Because you only—you already had such a head start ahead of your competition. You wouldn't you wouldn't dribble-drabble into it and you wouldn't then uh go buy or do this and that. You would just dominate it and you would use capital and you would weaponize and you would use implicit and you would use some dark arts in your mobile app so that-so that the competition would get blocked and all this crap. But you would you would dominate it with.","offset":3305,"duration":33},{"text":"Jason: You would just go for 90% market share in food delivery. 'Cause it's a better market than autonomous autonomy, it in the short term, maybe not in the long term, but it's a better market in the short term than rideshailing.","offset":3338,"duration":10},{"text":"Rory: I-I agree—for what it's worth I agree with that. So two separate arguments: right, do—they had to get public. They had to get cash flow positive. Hard-nose comment: you could another spin on autonomy, you could say: \"yes we need to do this thing but we can't afford to spend at the level they were spending in 2015 on something that reminder 10 years later is still only now finally doing a meaningful number of rides sub-economically in San Francisco.\"","offset":3348,"duration":28},{"text":"Rory: Right? It's a trend, it is the future, it was 10 years away. And they had to get public and they had to have a plan to cash flow break-even to get public to dominate Lyft. And you know on-it wasn't an option then as perhaps it might be today to stay private longer.","offset":3376,"duration":13},{"text":"Rory: Do you think they had to cut back on their autonomous spend? Maybe not to zero, which I think probably was a mistake, but dramatically focusing on getting cash flow positive, giving Wall Street what it wants, to get public to have the acquisition currency to do the food things. Right?","offset":3389,"duration":16},{"text":"Rory: And-and growth at all costs had reached its limits there and maybe a different manager was the right person for the next stage of that journey.","offset":3405,"duration":6},{"text":"Jason: Listen, I-I think in this-in this universe, um outside management through-through just like many companies, performs as well or better through early 2022. Remember, it was a decade where no products changed, even Uber didn't change much, right? Uber seemed feature-complete about two years after it launched, okay? Great, they added they added UberX. Now now for five bucks I could get to work and nothing changed. Okay, these-this app was frozen in time for a decade, right?","offset":3411,"duration":26},{"text":"Jason: That's why outside management can run it. And I believe what it would probably look like is that as late as two years ago, both-both they might have led to similar outcomes or maybe even a better outcome with outside management, right?","offset":3437,"duration":12},{"text":"Jason: But today it would be a trillion dollar company. My point is: now would be his second-second time, because he wouldn't have quit, he wouldn't have stopped building. And-and frankly and one of his best friends is Elon Musk. Maybe he would have owned autonomy with Tesla in a way that that you can't—who knows? But good God, it would be a trillion dollar company today.","offset":3449,"duration":19},{"text":"Rory: I actually think now I would agree with you. I actually think there was a period of time where they needed to conform to that reality of the market at that time, get cash flow positive and run it like a financial engineer, and he didn't-he clearly was unwilling to do it. Actually and in terms of—in retrospect they should have done the Steve Jobs thing: they should have swapped him out, got it public, got it cash flow like crazy, and sometime in '22 should have got him back and said: \"now, now is the time to do autonomy.\"","offset":3468,"duration":24},{"text":"Rory: So I do agree in the last two or three years—it's still unproven by the way whether or not Uber needs to own the technology to still make autonomy work. But I agree: I like your framing that there was a period of five or six years where the best manager for a lot of companies was a, you know, professional executive with a financial bent, and I think I can see why they made that change.","offset":3492,"duration":23},{"text":"Rory: If there was no more private capital to be raised, and if your CEO just was unwilling to focus on convergence, at the expense of long-term projects, and you had a risk of going bust, I can see why you made the change. But I agree with you: now you can say in the last two or three years the financial management game is out, and the product innovation game is back in.","offset":3515,"duration":21},{"text":"Host: And accelerating, and accelerating. Rory you said you would answer the question which Jason posed: would you have made that decision and switched him out?","offset":3536,"duration":9},{"text":"Rory: You should be very, very, very wary of ever swapping out a founder, right? It's like—I tell people it's like open heart surgery and 50% of people die, right? It's a shitty business. Occasionally I've done it for a bunch of reasons, and it's hell on earth. Forget morality, forget am I a good guy or a bad guy, it's just the most exhausting thing you do. It is easier to just lose money, right? So I hate doing it.","offset":3545,"duration":23},{"text":"Rory: There's only two reasons why you do it: if the business decisions they're making is literally going to bankrupt the company, right? If you feel that, you know, they're investing in—to take a concrete example here—if they were investing in a way whereby there simply just wasn't going to be any more private capital and we could run out of money and they were unwilling to change course, then at some point you have to consider that.","offset":3568,"duration":21},{"text":"Rory: And then—let me finish—and then the second option is the thing we said we wouldn't discuss, which is if internal behavioral issues rise to the level of a really systemic problem with a high bar, right? If both if-if both—if one or both of those things is present, then wildly reluctantly you have to do it, right? And even you have to take the heat.","offset":3589,"duration":19},{"text":"Host: Would you have done it?","offset":3608,"duration":1},{"text":"Rory: If one of those two things were the thing, then reluctantly you would have. You'd move heaven on earth not to, but if it's the former: at some point you gotta say: \"we're going to run out of private capital, you're not doing what it takes to get profitable, we need to focus on profitability, give Wall Street what it wants,\" then yeah, you-you might have to. You'd hate doing it.","offset":3609,"duration":18},{"text":"Rory: And again I hate this positioning, I'm not the guy—like nine times out of ten I'd be like: sell the company, get a president, get therapy, be better, all the other things. But especially my logic is this: knowing what it's like in those board meetings and knowing if you're a founder-friendly firm, like I would say Benchmark would like themselves to be, you don't do that lightly. So you gotta believe that some one or two of those issues was on the table for them to have to do that, and they felt at least it was necessary.","offset":3627,"duration":31},{"text":"Host: And I think you obviously see that with with Adam and and WeWork being the first there in terms of just the fiduciary responsibility in terms of how they spent money and the financial profile, so totally get you there. Are we bullish on Atoms now? Do we look at this and think this is exciting, this is going to work, awesome?","offset":3658,"duration":19},{"text":"Jason: Look, I don't know. I-I-I get-I get the big bet and certainly making this bet seems to-to be a lot more make a lot more sense than betting on the WeWork founder, right, who just doesn't is not as deeply product and software focused, um, building co-working spaces and then having everyone figure out the finance.","offset":3677,"duration":19},{"text":"Jason: Listen, I can only use—if I were a huge fund and he wanted my money, I would give it to him, don't get me wrong. But my smell test from watching the interview, um, some of the things he said felt like I was back in 2017 when this happened. The world is different now, and so I-I'm just I've just got to use my G2. And the question is: do I-do I think he's past it, right? and not being not being able to execute, but being able to—at some point you-you do lose, you lose the ability to create and you're better off amalgamating, and this is in the middle, right? This is a combination of amalgamation and creation. So you just asked my opinion, would I invest based on the interview? No, I wouldn't.","offset":3696,"duration":38},{"text":"Rory: It's so funny the way you answered that question the way we pro—'cause I-I the same question I didn't process to any kind of internal analysis of Travis' calling soul. I literally found myself thinking, do I—I kind of come from the market side: do I buy the market? I think there's two businesses going on here.","offset":3734,"duration":16},{"text":"Rory: One is the Atoms/robot business. As I said I like the fo—I like-I like the approach of more bounded industrial robots versus general purpose humanoids, so I think he's on the right broad track. But I think all those markets tend to be very different and trying to do one robot for all of them is hard. So I think that's a hard road and will be less amenable to any kind of \"quote unquote\" blitz-scaling.","offset":3750,"duration":27},{"text":"Rory: And let me finish then. The autonomy thing is interesting. I think we are at the stage now—the other company that he's invested in is Pronto, or I'm sorry I should remember the name.","offset":3777,"duration":9},{"text":"Host: Pronto.","offset":3786,"duration":1},{"text":"Rory: Pronto, yeah. That's super interesting because we're now at the stage, you know, where, yeah, autonomous driving in freeways is kind of hovering on the edge of being a thing with Waymo, but autonomous driving for mining and for industrial equipment is a category now and there's some players in that space.","offset":3787,"duration":16},{"text":"Rory: So I buy that that market is there and doable. I'd have to do the next level down: why is their technology different and better? Credible market and focused for autonomy, believable market but lots of sub-segments in industrial robotics to really play there. So that's my comment on them.","offset":3803,"duration":18},{"text":"Jason: Would you invest at 20 billion post? That's probably what he's looking for. That's what Claude thinks he's looking for in the round. He's fundraising, that's why he did the interview, he's fundraising, right?","offset":3821,"duration":7},{"text":"Rory: Oh God, dear God no. No.","offset":3828,"duration":2},{"text":"Jason: Yeah because the last round was at 15. Claude thinks he's-he's looking for a flatter-up round, so up to 20 billion.","offset":3830,"duration":8},{"text":"Host: Absolutely you would do that. 100% you would do that each and every day of the week.","offset":3838,"duration":5},{"text":"Jason: You'll put in your own 20 VC money at 20 billion?","offset":3843,"duration":3},{"text":"Host: I'm absolutely not, if I'm General Catalyst raising $10 billion dollars now, or I am Coatue with the multi-b—100%. Do I want to chuck a couple hundred million into Travis, one of the greatest founders of our time? Yes, I have to move hundreds of millions of dollars a month.","offset":3846,"duration":16},{"text":"Rory: I completely agree with you from our fund size, so far yeah. This is just so-this is just so everyone's a victim of their fund. If you're a seed stage fund you assess the guy, if you're a growth stage fund you assess the opportunity to put quantities of money to work, and if you're in the middle like us you look at the market trying to be intelligent and maybe overthinking it. It's funny.","offset":3862,"duration":21},{"text":"Host: Pro—if I have $9 billion dollars in my growth fund, putting 250 million with Travis here? 100% I would do it.","offset":3883,"duration":7},{"text":"Rory: Okay, good to know.","offset":3890,"duration":1},{"text":"Host: Would you-would you not agree with that rationale, Rory?","offset":3891,"duration":3},{"text":"Rory: I always struggle with the \"oh, just have a go, it's only\"—one of the—let me-let me put it on another term for you. You've got four and a half billion dollars a year. That is $400 million dollars a month you've got to move.","offset":3894,"duration":12},{"text":"Rory: I understand, but whenever you find your—I'll give you an honest answer. If you find your logic being reduced to \"I've got to get rid of this much money this month and this entrepreneur is amazing so I'm not sure about the opportunity and I don't like the price but have a go,\" if that's your logic, let me give you some advice: halve your fund size.","offset":3906,"duration":17},{"text":"Host: And that's why you're not playing the AUM game. That's why. Now, um...","offset":3923,"duration":4},{"text":"Jason: Look, for what it's worth I'll say one thing. I-I wrote this on Quora years ago and I-I had to write so many disclaimers about it because I was going to get hazed. But I wrote that uh the question was who's the-who's the best entrepreneur you've ever met, okay? And this was this was a few years ago so it was before I met more folks. And I wrote Travis Kalanick, best one I ever met.","offset":3927,"duration":18},{"text":"Jason: I met him when he was at RedSwoosh, his startup that um mostly failed, right? His-his uh whatever.","offset":3945,"duration":6},{"text":"Rory: For the record, made money for his investors. I remember the deal, he made money for his investors.","offset":3951,"duration":5},{"text":"Jason: Yeah, I went by his office in San Mateo, he was down to two employees I think, and had lunch, and this was before even YouTube had launched, okay? Sat down, and I never met a founder that explained the entire future of video on the internet to me with the clarity and insights that he did. My jaw—it was the first time I'd met a founder that could see the future in all the elements and how it all came together and explain it in a way that kind of blew my mind.","offset":3956,"duration":26},{"text":"Jason: And that's what you-and-and I if I look at my investing mistakes it's when I've invested below that line. When a founder has not come in and utterly blown my mind for the future of voice, right? The future of sales in the age of AI. Blown my mind. And and I took some heat, but I'm like I never had—that was the first time in my life I met a founder where I walked out of the meet my jaw was just on the ground because he explained the whole future to me.","offset":3982,"duration":25},{"text":"Jason: That's why I go to Rory's point. I guess if I was General Catalyst, I'd do the bet, right? Unless I thought he was washed up, unless I thought he was washed up.","offset":4007,"duration":6},{"text":"Rory: Yeah, I-I'm going to give you shit Jason because basically you're in the category of: I Jason wouldn't invest but I'd be delighted to let you—I think General Catalyst you should stick 400 million in. Because earlier on you were like \"I don't know if it's dated or not.\"","offset":4013,"duration":10},{"text":"Jason: I just think for me to invest at 20 billion with-for me, I have to believe he's not he can still do it. I have to have 100% conviction he can still do it to justify it. I think General Catalyst does not have to have 100% conviction, or Harry's math destroys me or I end up with a 1x fund if I invest with anything less than 100%—and I mean conviction at all levels, okay? Not just believing in the invest—like I have to know Travis is a thousand percent in for doing this for 20 years, at 51 or whatever he is, 48. I have to believe it.","offset":4023,"duration":32},{"text":"Rory: We're back into Kelly betting inadvertently. What you're basically saying is the percentage of your bankroll that you play, you know, it's-it's edge over odds or whatever it is, I'd have to think again. And what you're saying is for your fund—this is where fund size is strategy, right? On-on every dimension.","offset":4055,"duration":19},{"text":"Host: Mike Maples, Mike Maples said it first.","offset":4074,"duration":2},{"text":"Rory: Yeah, it's just so true. And what you're basically saying is you wouldn't because you don't have the edge and the return and the odds aren't great. But if you have a different kind of fund where instead of being 20% of your fund it's 1% of your fund, maybe you do. I hate that logic, but I understand it.","offset":4076,"duration":15},{"text":"Jason: No no no, I'm saying if I smelled some risk Travis isn't—is like he might be a little bit in the past as well as the future. That's a flag for me at-at the rate that I have to win.","offset":4091,"duration":14},{"text":"Host: Okay we can choose one final topic. We can go for Adobe. They beat earnings, their stock tanked, and as a result CEO leaving. I bet 10 Shantanu's step down in 2026. That's my bet. 10 Shantanu's.","offset":4105,"duration":14},{"text":"Rory: I think you've got the I think the interesting comment and I want to hear Jason's comment 'cause he's worked there. Be precise in your sequencing: they beat earnings at the same time the CEO announced his resignation without a successor, and the stock tanked. It wasn't the stock tanked and then they whacked him. It was the two were announced together which is odd, and in response to one or both of those events, the stock went down. Correct?","offset":4119,"duration":26},{"text":"Host: Great. Yes, correct. Jason over to you 'cause I think your take is right here.","offset":4145,"duration":4},{"text":"Jason: Well look, there-there we don't really know exactly why he stepped down without a successor other than that it's odd, okay? It is odd because a lot of folks on the internet are saying David Wadhwani who runs Creative Cloud is going to be a successor. But this is David S—like he quit Adobe and went to AppDynamics and VC when he was passed over for CEO the first time. Then he came back to be CEO and then Shantanu steps down and he isn't made CEO.","offset":4149,"duration":25},{"text":"Jason: So that suggests to me the odds that he becomes CEO are less than 100%, right? Because certainly the most elegant thing is to hand it off to your president, right? Of your largest business unit. Then to say we need—the board's going to do a search while I step down—like there's just no way that's confidence inspiring, right?","offset":4174,"duration":18},{"text":"Jason: So I don't know what happened. There could be multiple things but to me it suggests he left the keys on the table after a very 18 years. Not five years, not was fired quietly, right? by the board. I don't think that for a million reasons, I don't think he was fired, he's very competent, right, very insightful.","offset":4192,"duration":19},{"text":"Jason: I think he left the—he calmly and respectfully left the keys, maybe after a quarter of discussion and um now they're going to go recruit somebody um and it's not a good sign. And I think we're going to see a lot of these. I mean, you know, Dustin Moskovitz quit his own company Asana in a hiss and left the keys, threw the keys on the ground, right? No successor, no anything.","offset":4211,"duration":24},{"text":"Jason: And these are not fun times to run most public companies. There's a handful—I mean Alex Karp seems to be having the time of his life, moved to a $50 million dollar mansion in Miami, he's-he's crushing it. Yeah, yeah, 'cause-'cause he's winning. But who else is having fun that's that's public? Not-not too many are having fun.","offset":4235,"duration":17},{"text":"Rory: The correlation between winning and having fun is pretty high, pretty damn high, right? And you're—and I tell you what, you're not having fun if you're the CEO of Adobe. And you're not having fun if you're any CEO who realizes—I going back to I think this you're spot on, going back to our where we started this conversation: \"oh, the only way to make my I have an obligation to my shareholders to make the stock go up, and the only way to make the stock go up given my growth rate's gone down is to sack 20% of the people I spent the last 10 years hiring.\"","offset":4252,"duration":27},{"text":"Rory: Now you might know it's the right thing to do, you might even be willing to do it, but it's not going to be your best week in the office. So I agree with you: it's a tough—yeah, I don't know if 10 quit this year, but I can totally see more than 10 saying \"should I quit this year?\" Going home and telling spouse and saying, \"now tell me exactly why you're doing this,\" right?","offset":4279,"duration":25},{"text":"Jason: I gave you 18 years.","offset":4304,"duration":2},{"text":"Rory: You know, we've all been on boards or where we've had to do CEO transitions and no matter what's going on underneath the surface, right, provided you've good relations and you've reasonable level of trust, you always go for the: leave the person in place, find the successor, announce an orderly transition, look like you have your shit together.","offset":4306,"duration":20},{"text":"Rory: 'Cause at the margin you never want to show you don't have your shit together. The only reason—so that's not what happened here. And there's only—to Jason's point, there's only two ways that that occurs: the first is if the board decides they want to make a statement, right? We-we, you know and I've been in those meetings where sometimes you're like \"you gotta go right now because there's crimes of moral turpitude, you're out, we've totally lost confidence in you,\" or much more likely \"the team's totally lost confidence in you, you're out.\" That doesn't feel like what happened here, right? Because he's staying on as chairman.","offset":4326,"duration":27},{"text":"Rory: If they've run the damn thing for 18 years, you probably should let him run it for another quarter or two while you line up their successor. So I don't know, I wasn't in the room, but it may well be some version of what Jason's saying is right, because you just go in as the CEO and say \"I my heart's not in it,\" right? It was a weird outcome.","offset":4353,"duration":21},{"text":"Jason: 'Cause it's interesting, now-now it's—someone wrote this point out that now-I mean Adobe had a great run, right? Um but now its aggregate returns are just below the S&P over the last decade or something like that. So when you look at that after 18 years and you're not really excited about agentic change—like you're not waking up each morning and saying \"I'm excited about my agents\"—this is a good time to leave the keys on the table.","offset":4374,"duration":24},{"text":"Rory: And-and to be clear, hang on, actually one thing I we're assuming something. He is continuing in the role until you get a new CEO? I just didn't check that. I think he is. Is that correct?","offset":4398,"duration":10},{"text":"Jason: I believe I think so.","offset":4408,"duration":1},{"text":"Rory: In which case it's not keys on the table, it's more making an announcement before you have the answer. It's a little less herky-jerky, uh, you know.","offset":4409,"duration":9},{"text":"Jason: I mean, it's leaving the keys on the table but still grabbing a drink at the-at the bar in the kitchen.","offset":4418,"duration":4},{"text":"Rory: Yeah no, it's \"I'll-I'll do the right thing,\" but um...","offset":4422,"duration":2},{"text":"Jason: \"I'm leaving the keys but I'm hanging out in the house until dad gets home,\" or whatever the extenuating version is.","offset":4424,"duration":5},{"text":"Rory: Yeah, yeah, metaphors never work, you should just say the thing instead. Um, it's—where-where is Adobe in five years' time?","offset":4429,"duration":5},{"text":"Jason: A massive installed base. You have a set of core—here's the meta issue. Um, someone on Twitter—the guy you just had, who'd you just have, the super smart guy, what's his name? The last one, Go—what's his name, sorry.","offset":4434,"duration":11},{"text":"Host: Gokul Rajaram.","offset":4445,"duration":1},{"text":"Jason: Yeah, super-off the charts smart. He made this thing on Twitter and everyone got it wrong, I think. Uh, he said—and-and because they misinterpreted—he basically said there's no threat to companies like Intuit and Adobe because it's so hard, but SMB is so hard to nail the price point and the motion that whether it's Adobe or Intuit which are still largely self-service businesses, right?","offset":4446,"duration":21},{"text":"Jason: Or whether it's a sales-led motion, these are almost immune from competitive threats because they're just so hard to get right, okay? And-so let me answer the question: here's the thing, there is a lot of truth to that as we've all seen. Um, I think it's true in all software. But it doesn't mean you grow.","offset":4467,"duration":16},{"text":"Jason: Just because it's hard to churn—here's the mistake so many people are making right now in the age of AI: just because your GRR stays high, just because your nominal churn is low, does not mean you're going to grow. And I see no evidence Adobe will grow. I see no products that-that show they'll grow. Nothing.","offset":4483,"duration":16},{"text":"Rory: I want to come on here and three things and then we'll wrap. Right? One is I just checked, he is actually staying on as CEO until the new successor, so it's more kind of an announcement without an answer, in which case changing my opinion here, it may well be the board also felt they wanted to send a statement, they felt the results were disappointing, they didn't want to have—they didn't want to attract a whole bunch of \"oh you need to make a change\" activists could show up.","offset":4499,"duration":23},{"text":"Rory: Maybe they thought that given these results they actually needed to state now that a change was happening.","offset":4522,"duration":5},{"text":"Jason: Pull it forward, pull it—maybe they felt they needed to pull it forward, right?","offset":4527,"duration":3},{"text":"Rory: In other words, please don't call us Elliott and you know shit Elliott Capital. We know we need to make a change, Shantanu wants to make a change, here it is. That would actually fit the facts pretty well. You are right if you've been the number two who've been passed over a second time, 'cause you know, if you need to make a change and you have a good number two and you feel the activists are circling, I tell you what you do: you-you hire the guy.","offset":4530,"duration":19},{"text":"Rory: But be that as it may, going to your second comment, the Adobe/Intuit—I really want to key on that because in my less than amazing—yeah I think Intuit has pretty durability over the next five years 'cause I think the thing they automate, which is accounting and tax, has some AI impact but it's not infinitely large and I think they can adapt to it, and we can argue that another day.","offset":4549,"duration":24},{"text":"Rory: I think the challenge for Adobe is: what kills you as a software business if the—if the—is if the if the work that you're automating gets done in a totally different way. Right? And Adobe and you know what we've seen: one of the—one of the area AI I saw it really good post on this I can't remember who wrote it: said most of the AI traction so far has been individual users, creators, you know, individuals even within the enterprise. It's not yet amazing great workflow tool, not all of it but most of it, right?","offset":4573,"duration":32},{"text":"Rory: Adobe is the classic creator tool. There is a whole new way to create. They're not—by definition they're playing catchup. So more than most companies they are under the gun to figure out how to meet their creators in a totally different way. So I think the disruption risk on those guys versus Intuit is a lot higher.","offset":4605,"duration":21},{"text":"Rory: Five years from now there will be some disruption Intuit but we'll still be moving money around, we'll still be producing quarterly accounts and I tell you we'll still be paying taxes to the US government. I don't know if we'll be doing pixel-by-pixel removing on Photoshop and therefore I don't—so I think the Adobe AI risk over the next five years is pretty large, and that actually probably should be figuring into their search.","offset":4626,"duration":24},{"text":"Host: Whew, we didn't cover much did we? Um that was uh...","offset":4650,"duration":3},{"text":"Rory: Bit more and more left.","offset":4653,"duration":1},{"text":"Host: Yeah bit of-bit of a materialist show wasn't it? Um guys thank you so much, that was fantastic.","offset":4654,"duration":15}],"logs":[{"elapsed":"0.0","message":"Downloading audio from YouTube...","detail":null},{"elapsed":"0.0","message":"Trying download with browser cookies (ad-free)...","detail":null},{"elapsed":"38.1","message":"Audio downloaded (49.3 MB) in 38.1s","detail":"File size: 49.3 MB"},{"elapsed":"38.1","message":"Video title: NVIDIA Predicts $1TRN in Revenue: Everything You Need to Know From GTC & Anduril Lands $20B Contract","detail":null},{"elapsed":"38.2","message":"Audio duration: 1:17:49 (77.8 min)","detail":null},{"elapsed":"38.2","message":"Uploading audio to Gemini File API...","detail":null},{"elapsed":"44.6","message":"Audio uploaded in 6.4s","detail":"File ref: files/y0m2z2veo2tb"},{"elapsed":"44.6","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"315.9","message":"Transcription complete in 277.8s","detail":"89289 chars received"},{"elapsed":"315.9","message":"Transcription tokens: 116,981 in / 24,058 out — cost: $0.1307","detail":null},{"elapsed":"315.9","message":"Parsed 282 transcript segments","detail":null},{"elapsed":"315.9","message":"Transcript coverage: 1:17:34 of 1:17:49 (100%) — OK","detail":null},{"elapsed":"315.9","message":"Total transcription time: 277.8s — 282 segments","detail":null},{"elapsed":"315.9","message":"Analyzing topics across 282 segments with gemini-3.1-pro-preview...","detail":null},{"elapsed":"347.0","message":"Topic analysis complete in 31.1s — found 7 topics","detail":null},{"elapsed":"347.0","message":"Analysis tokens: 25,642 in / 637 out / 2,633 thinking — cost: $0.0905","detail":null},{"elapsed":"347.0","message":"Pipeline finished in 347.0s — total cost: $0.2212 (169,951 tokens)","detail":null}]} \ No newline at end of file diff --git a/history/1775222710862-gwW8GKwHB3I.json b/history/1775222710862-gwW8GKwHB3I.json new file mode 100644 index 0000000..60b69d6 --- /dev/null +++ b/history/1775222710862-gwW8GKwHB3I.json @@ -0,0 +1 @@ +{"id":"1775222710862-gwW8GKwHB3I","videoId":"gwW8GKwHB3I","url":"https://www.youtube.com/watch?v=gwW8GKwHB3I","title":"Jensen Huang: Nvidia's Future, Physical AI, Rise of the Agent, Inference Explosion, AI PR Crisis","type":"youtube","topicCount":21,"segmentCount":189,"createdAt":"2026-04-03T13:25:10.862Z","uploadDate":"20260319","chunks":[{"title":"Introduction and Groq Banter","summary":"The hosts welcome Jensen Huang to a special episode. They briefly joke about Nvidia's acquisition of Groq and the close process.","entries":[{"text":"Host: Special episode this week. We've preempted the weekly show, and there's only three people we preempt the show for: President Trump, Jesus, and Jensen. And, uh, I'll let you pick which order we do that, but what an amazing run you've had and a great event.","offset":0,"duration":18},{"text":"Jensen Huang: Every industry's here. Every tech company's here. Every AI company's here. Incredible.","offset":18,"duration":7},{"text":"Host: Extraordinary. And one of the great announcements of the past year has been Groq. When you made the purchase of Groq, did you realize how insufferable Chamath would become?","offset":25,"duration":11},{"text":"Jensen Huang: I had a, I had an inkling that that, uh—","offset":36,"duration":4},{"text":"Host: We're his friends. We have to deal with him every week.","offset":40,"duration":3},{"text":"Jensen Huang: I know it.","offset":43,"duration":1},{"text":"Host: You had to deal with him for the six-week close.","offset":44,"duration":2},{"text":"Host: It was like two weeks.","offset":46,"duration":1},{"text":"Host: Two weeks.","offset":47,"duration":1}],"startTime":0},{"title":"Disaggregated Inference and AI Factories","summary":"Jensen explains the concept of Dynamo as the operating system for the next industrial revolution's AI factories. They discuss how disaggregated inference and allocating different workloads across specialized chips will optimize data center performance.","entries":[{"text":"Jensen Huang: It's all coming back to me now. It's making me rather uncomfortable. The thing is, many of our strategies are presented in broad daylight at GTC years in advance of when we do it. Two and a half years ago, I introduced the operating system of the AI factory, and it's called Dynamo. Dynamo, as you know, is a piece of instrument, a machine that was created by Siemens to turn essentially water into electricity. And Dynamo, uh, powered the factory of the last industrial revolution. So I thought it was the perfect name for the operating system of the next industrial revolution, the factory of that. And so inside Dynamo, the fundamental technology is disaggregated inference. Jason, I know you're super technical.","offset":48,"duration":52},{"text":"Host: Absolutely.","offset":100,"duration":1},{"text":"Jensen Huang: I'll let you take this one. Go ahead and define it for the audience. I don't want to step on you.","offset":101,"duration":4},{"text":"Host: Yeah, thanks. I knew you wanted to jump in there for a second. But it's, it's disaggregated inference, which means the, the pipeline, the processing pipeline of inference is extremely complicated. In fact, it is the most complicated computing problem today. Incredible scale, lots of mathematics of different shapes and sizes. And we came up with the idea that you would change, you would, you would disaggregate parts of the processing such that some of it can run on some GPUs, the rest of it can run on different GPUs. And that led to us realizing that maybe even disaggregated computing could make sense. That we could have different heterogeneous nature of computing. That same sensibility led us to Mellanox.","offset":105,"duration":45},{"text":"Jensen Huang: You know, today, Nvidia's computing is spread across GPUs, CPUs, switches, scale-up switches, scale-out switches, networking processors, and now we're going to add Groq to that, and we're going to put the right workload on the right chips. You know, we just really evolved from a GPU company to an AI factory company.","offset":150,"duration":21},{"text":"Host: I mean, I think that was probably the biggest takeaway that I had. You're seeing this fundamental disaggregation where we've gone from a GPU, and now you have this complexion of all these different options that will eventually exist. The thing that you guys said on stage, or you said on stage, was I, I would like the high-value inference people to take a listen to this and 25% of your data center space you said should be allocated to this Groq LPU GPU combo.","offset":171,"duration":29},{"text":"Jensen Huang: We should add Groq to about 25% of the Vera Rubins in the data center.","offset":200,"duration":6},{"text":"Host: So can you tell us about how the industry looks at this idea of now basically creating this next generation form of disaggregated, pre-filled, decode, disagg, and how people you think will react to it?","offset":206,"duration":13},{"text":"Jensen Huang: Yeah, and take a step back and at the time that we added this, we went from large language model processing to agentic processing. Now, when you're running an agent, you're accessing working memory, you're accessing long-term memory, you're using tools, you're really beating up on storage really hard. You have agents working with other agents. Some of the agents are very large models, some of them are smaller models, some of them are diffusion models, some of them are autoregressive models. And so there are all kinds of different types of models inside this data center. We created Vera Rubin to be able to run this extraordinarily diverse workload. My sense is—and so we added what used to be a one-rack company, we now add a four-more racks.","offset":219,"duration":46},{"text":"Host: Right.","offset":265,"duration":1},{"text":"Jensen Huang: So Nvidia's TAM, if you will, increased from whatever it was to probably something, call it, you know, 33%, 50% higher. Now, part of that 33% or 50%, a lot of it's going to be storage processors, it's called BlueField. Some of it will be, a lot of it I'm hoping will be Groq processors, and some of it will be CPUs, and they're all going to, and a lot of it's going to be networking processors, and so all of this is going to be running basically the computer of the AI revolution called agents. The operating system of, uh, modern industry.","offset":266,"duration":34}],"startTime":48},{"title":"The Three Computers of AI","summary":"Jensen outlines the three primary computing systems: training models, evaluating them in virtual worlds like Omniverse, and edge robotics. He also highlights how telecommunications infrastructure will integrate into the AI ecosystem.","entries":[{"text":"Host: What about, what about embedded applications? So, you know, my daughter's teddy bear at home wants to talk to her. What goes in there? Is it a custom ASIC or does there end up becoming much more kind of a broader set of TAM with developing tools that are maybe different for different use cases at the edge and in an embedded application?","offset":300,"duration":20},{"text":"Jensen Huang: We think that there's three computers in the problem. At the, at the largest, at the largest scale when you take a step back. There's one computer that's really about training the AI model, developing, creating the AI. Another computer for evaluating it. Depending on the type of problem you're having, like for example, you look around, there's all kinds of robots and cars and things like that. You have to evaluate these robots inside a virtual gym that represents the physical world. So it has to be software that obeys the laws of physics. And that's a second computer, we call that Omniverse. The third computer is the computer at the edge, the robotics computer. That robotics computer, one of them could be a self-driving car, another one's a robot, another one could be a teddy bear, little tiny one for a teddy bear. One of the most important ones is one that we're working on that basically turns the telecommunications base stations into part of the AI infrastructure. So now all of the, it's a $2 trillion industry. All of that in time will be transformed into an extension of the AI infrastructure. And so radios, radios will become edge devices. Factories, warehouses, you name it. And so, so there are three, these three basic computers, all of them, you know, are going to be necessary.","offset":320,"duration":79}],"startTime":300},{"title":"Economics of Inference Scaling","summary":"The discussion shifts to the explosive growth of inference and the economics behind it. Jensen argues that an expensive, high-throughput AI factory ultimately produces the lowest-cost compute tokens compared to cheaper alternatives.","entries":[{"text":"Host: Jensen, last, last year I think you were ahead of the the rest of the world in in in saying inference isn't going to 1000X, it's going to one billion X.","offset":399,"duration":10},{"text":"Jensen Huang: Just last year?","offset":409,"duration":1},{"text":"Host: Yes.","offset":410,"duration":1},{"text":"Host: Brad, you're hurting my feelings.","offset":411,"duration":1},{"text":"Host: Isn't, it isn't, it isn't going to 1000X, it's going to one billion X. Right, and I think people at the time thought it was pretty hyperbolic because the world was still focused on pre-scaling on training. Here we are, now inference has exploded, we're inference constrained. Um, you announced an inference factory that I think is leading edge, that's going to be 10X better in terms of throughput to the next factory. But yet, if you, if I listen to what the chatter is out there, it's that your inference factory is going to cost 40 or 50 billion and the alternatives—the custom ASICs, AMD, others—are going to cost 25 to 30 billion and you're going to lose share. So why don't you talk to us—what are you seeing, how do you think about share, and does it make sense for all these folks to pay something that's a 2X premium to what others are marketing?","offset":412,"duration":41},{"text":"Jensen Huang: The big takeaway, the big idea, is that you should not equate the price of the factory and the price of the tokens. The cost of the tokens. It is very likely that the $50 billion factory, and in fact I can prove it, that the $50 billion factory will generate for you the lowest cost tokens. And the reason for that is because we produce these tokens at extraordinary efficiency. 10 times, you know, the difference between 50 billion, now it turns out 20 billion is just lamp power and shell, right? And then on top of that, you have storage anyways, networking anyways, you got CPUs anyways, you got servers anyways, you got cooling anyways. The difference between that GPU being 1X price or half X price is not between 50 billion and 30 billion. Pick your favorite number, but let's say between 50 billion and 40 billion. That is not a large percentage when the $50 billion data center is actually 10 times the throughput. That's the reason why I said that even for most chips, if you can't keep up with the state of the technology and the pace that we're running, even when the chips are free, it's not cheap enough.","offset":453,"duration":79}],"startTime":399},{"title":"Nvidia's Strategy and Hard Problems","summary":"Jensen details his approach to decision-making as CEO. He explains that Nvidia specifically targets insanely hard, unsolved problems that tap into the company's unique superpowers.","entries":[{"text":"Host: Can I, can I just ask a general strategy question?","offset":532,"duration":3},{"text":"Jensen Huang: Yeah.","offset":535,"duration":1},{"text":"Host: I mean, you're running the most valuable company in the world. This thing is going to do 350 plus billion of revenue next year, 200 billion of free cash flow. It's compounding at these crazy rates. How do you decide what to do? Like, how do you actually get the information—I mean, it's famous now, these sort of emails that are people are meant to send you—but how do you really decide to get an intuition of how to shape the market, where to really double down, where to maybe pull back, where to actually go into a Greenfield? How does that information get to you? How do you decide these things?","offset":536,"duration":31},{"text":"Jensen Huang: In the final analysis, that's the job of the CEO. And our job is to define the strategy, define the vision, define the strategy. We're informed, of course, by amazing computer scientists, amazing technologists, great people all over the company. But we have to shape that future. Well, part of it has to do with is this something that's insanely hard to do? If it's not hard to do, we should back away from it. And the reason for that is if it's easy to do, obviously—","offset":567,"duration":25},{"text":"Host: Lots of competitors.","offset":592,"duration":1},{"text":"Jensen Huang: —a lot of competitors. Is this something that has never been done before, that's insanely hard to do, and that somehow taps into the special superpowers of our company? And so I have to find this confluence of things to do that meets this standard. And in the end, we also know that a lot of pain and suffering's going to go into it. There are no great things that are invented because it was just easy to do and just like first try, here we are. And so if it's super hard to do, nobody's ever done it before, it's very likely that you're going to have a lot of pain and suffering, and so you better enjoy it.","offset":593,"duration":32}],"startTime":532},{"title":"Physical AI and Digital Biology","summary":"Jensen shares updates on long-term bets that are now inflecting, such as physical AI for a $50 trillion industrial market. He also predicts that digital biology will soon have its own ChatGPT moment.","entries":[{"text":"Host: Can you, so can you just look at maybe three or four of the more long-tail things you announced and just talk about the long-term viability of whether it's the data centers in space, or whether it's what you're trying to do with ADAS in autos, or, you know, what you're trying to do on the biology side? Just give us a sense of like how you see some of these curves inflecting upwards in some of these longer tail businesses.","offset":625,"duration":21},{"text":"Jensen Huang: Excellent. Physical AI, large category. We believe, and I just mentioned, we have three computing systems, all the software platforms on top of it. Physical AI as a large category, it's the technology industry's first opportunity to address a $50 trillion industry that has largely been, you know, void of technology until now. And so we need to invent all of the technology necessary to do that. I felt that that was a 10-year journey. We started 10 years ago, we're seeing it inflecting now. It is a multi-billion dollar business for us, it's close to $10 billion a year now. And so it's a big business and it's growing exponentially. And so that's number one. I think in the case of digital biology, I think we are literally near the ChatGPT moment of digital biology. We're about to understand how to represent genes, proteins, cells—we already know how to understand chemistry—and so the ability for us to represent and understand the dynamics of the building blocks of biology, that's a couple, two, three, five years from now. In five years' time, I completely believe that the healthcare industry where digital biology is going to inflect. And so these are a couple of the really great ones, and you can see they're all around us.","offset":646,"duration":77},{"text":"Host: Agriculture.","offset":723,"duration":1},{"text":"Jensen Huang: Agriculture.","offset":724,"duration":1},{"text":"Host: Inflecting now.","offset":725,"duration":1},{"text":"Jensen Huang: No question.","offset":726,"duration":1}],"startTime":625},{"title":"Open Claude and Personal AI Agents","summary":"The conversation moves to the cultural and technological impact of Open Claude. Jensen explains how agentic systems are reinventing computing by functioning as a new operating system with memory, skills, scheduling, and IO.","entries":[{"text":"Host: Jensen, I want to take you from the data center to the desktop. The company was built in large part on hobbyists, video gamers, and and all those graphics cards in the beginning. And you mentioned in front of, I think, 10,000 people here, just Claude—Open Claude, Claude Code—and what a revolution agents have become. And specifically, the hobbyists who are really where a lot of energy, um, we see, you know, a lot of the innovation breaks, want desktops. You announced one here, I believe it's the Dell 6800. This is a very powerful workstation to run local models, 750 gigs of RAM. Obviously, the Mac Studio sold out everywhere in my company. We're moving to Open Claude everything. Friedberg just got Claude-pilled. You got Claude-pilled, I understand, and you're obsessed with these. What is this \"from the streets\" movement of creating open-source agents and using open-source on the desktop mean to you, and where is that going?","offset":727,"duration":58},{"text":"Jensen Huang: So great. Yeah, so great. First of all, let's take a step back. In the last two years, we saw basically three inflection points. The first one was generative. ChatGPT brought AI to the common everybody, to our awareness. But the fact of the matter is the technology sat in plain sight months before GPT. It wasn't until ChatGPT put a user interface around it, made it easy for us to use, that generative AI took off. Now, generative AI, as you know, generates tokens for internal consumption as well as external consumption. Internal consumption is thinking, which led to reasoning. O1 and O3 continue that wave of ChatGPT grounded information, made AI not only answer questions, but answer questions in a more grounded way, useful. We started seeing the revenues and the, the economic model of OpenAI start to inflect. Then the third one was only inside the industry that we saw. Claude Code, the first agentic system that was very useful. Really revolutionary stuff. But, but Claude Code was only available for enterprises. Most people outside never saw anything about Claude Code until Open Claude. Open Claude basically put into the popular consciousness what an AI agent can do. That's the reason why Open Claude's so important from a cultural perspective.","offset":785,"duration":90},{"text":"Jensen Huang: Now, the second, second reason why it's so important is that Open Claude is open, but it formulates, it structures a type of computing model that is basically reinventing computing all together. It has a memory system, scratch—is it short-term memory, file system? It has—it has—","offset":875,"duration":25},{"text":"Host: Skills.","offset":900,"duration":1},{"text":"Jensen Huang: Did you say skills or scales?","offset":901,"duration":1},{"text":"Host: Skills.","offset":902,"duration":1},{"text":"Jensen Huang: Oh, skills.","offset":903,"duration":1},{"text":"Host: They do have scales, theoretically, yeah.","offset":904,"duration":1},{"text":"Jensen Huang: Skills. So the first thing, first thing it, you know, it has resources, it manages resources. It's, it does scheduling, right? And cron jobs, it could, it could spawn off agents, it could, it could decompose a task and, and cause, and solve problems, so it does scheduling. It has IO subsystems, it could, you know, input, it has output, it could connect to WhatsApp. And also it has a, an API that allows it to run multiple types of applications called skills. These four elements fundamentally define a computer. And therefore, what do we have? We have a personal artificial intelligence computer for the very first time. Open source, it runs literally everywhere. And so this is now the, this is basically the blueprint, the operating system of modern computing. And it's going to run literally everywhere. Now, of course, one of the things that we had to help it do is whenever you have agentic software, you have to make sure that an agentic software has access to sensitive information, it executes code, it could communicate externally. We have to make sure that all of it has to be governed, all of it has to be secure, and that we have policies that, that gives these agents two of the three things, but not all three things at the same time. And so the governance part of it we contributed to Peter—Peter Steinberger was here—and so we've got a mound of great engineers working with him to help secure and keep that thing so that it could protect our privacy, protect our security.","offset":905,"duration":93}],"startTime":727},{"title":"AI Regulation and Balanced Messaging","summary":"Jensen discusses the need to educate policymakers and avoid doomerism so that the US does not fall behind in AI adoption. He advocates for a balanced, grounded approach when discussing AI's capabilities and risks.","entries":[{"text":"Host: Jensen, that paradigm shift makes some of the AI legislation that has passed around the country to regulate AI and a lot of the proposed legislation effectively moot, doesn't it? Can you just comment for a second on how quickly the paradigm shift kind of obviates a lot of the models for regulatory oversight of AI, which is becoming a very hot topic in politics right now?","offset":998,"duration":22},{"text":"Jensen Huang: Well, this is—this is the part that that, you know, just with policymakers, we need to, we need to always get in front of them, and Brad, you do a great job doing this. We had to get in front of them and inform them about the state of the technology, what it is, what it is not. It is not a biological being, it is not alien, it is not conscious, it is computer software. And it is not something that we say things like we don't understand it at all. It is not true, we don't understand it at all. We understand a lot of things about this technology. And so, so I think one, we have to make sure that we continue to inform the policymakers and not affect, not allow doomerism and extremism to affect how policymakers think and understand about this technology. However, we still have to recognize this technology's moving really fast, and don't get policy ahead of the technology too quickly. And the risk that we, we run as a nation, our greatest source of national security concern with respect to AI, is that other countries adopt this technology while we are so angry at it or afraid of it or somehow paranoid over it that our industries, our society don't take advantage of AI. And so I'm just mostly worried about the diffusion of AI here in United States.","offset":1020,"duration":84},{"text":"Host: Can you just double click, if you were in the seat in the boardroom of Anthropic over that whole scuttlebutt with the Department of War? It sort of builds on this idea of people didn't know what to think. It's sort of added to this layer of either resentment or fear or just general mistrust that people have sometimes at the software levels of AI. What would, do you think you would have told Dario and that team to do maybe differently to try to change some of this outcome and some of this perception?","offset":1104,"duration":27},{"text":"Jensen Huang: The first thing that I would, I would say about Anthropic is first of all, the technology is incredible. We are a large consumer of Anthropic technology. Really admire their focus on security, really admire their focus on safety. Um, the, the, the culture by which we're, they went about it, the technology excellence by which they went about it, really fantastic. Um, I would say that that the desire to warn people about the capability of the technology is also really terrific. We just have to make sure that we understand that the world has a spectrum and that that warning is good, scaring is less good. And because this technology is too important to us. And and I think that it is fine to predict the future, but we need to be a little bit more circumspect. We need to have a little bit more humility that in fact we can't completely predict the future, and the abil—and to say things that that are quite extreme, quite catastrophic, that there's no evidence of it happening, um, could be more damaging than people think. And of course we are technology leaders. Um, there were a time where nobody listened to us, um, but now because technology is so important in the social fabric, such an important industry, so important to national security, our words do matter. And I think we have to be much more circumspect, we have to be more moderate, we have to be more balanced, we have to be more thought—more thoughtful.","offset":1131,"duration":94}],"startTime":998},{"title":"AI ROI and Superhuman Workers","summary":"Addressing concerns about AI's return on investment, Jensen highlights the massive increase in compute needed for agentic systems. He explains that giving engineers huge token budgets creates superhuman employees capable of unprecedented productivity.","entries":[{"text":"Host: Well, I, you know, I would nominate you. I think the industry's got to get together. 17% popularity of AI in the United States. I mean, we see what happened in nuclear, right? We basically shut down the entire nuclear industry and now we have 100 fission reactors being built in China and zero in the United States. Um, we hear about moratoriums on data centers, so I think we have to be a lot more proactive about that. But but I wanted to go back to this agentic explosion that you're seeing inside your company. The efficiencies, the productivity gains inside your company. There's a lot of debate whether or not we're seeing ROI, right? And you and I, entering into this year, the big question was, are the revenues going to show up? Are the revenues going to scale like intelligence? And then we had this kind of Oppenheimer moment of five, six billion dollar month by Anthropic in February. Um, do you think as you look ahead, you announced a trillion dollar, you know, visibility into a trillion dollars of just Blackwell and Vera Rubin over the course of the next couple years. When you see this happening at Anthropic and OpenAI, do you think we're on that curve now where we're going to see revenues scale in the way that intelligence is scaling?","offset":1225,"duration":67},{"text":"Jensen Huang: When you look around, when you'll—I'll answer this in a couple of different ways. When you look around this audience, you will see that Anthropic and OpenAI is represented here, but in fact, everyb—99% of everything that is here is all AI and it's not Anthropic and OpenAI. And the reason for that is because AI is very diverse. I would say that the second most popular model as a category is open models. Open source. OpenAI's number one, open source is number two, very distant third is Anthropic. And that tells you something about the scale of all of the AI companies that are here. And so, so it's important to recognize, recognize that. Um, let me—let me come back and say a couple of things. One, when we went from generative to reasoning, the amount of computation we needed was about a hundred times. When we went from reasoning to agentic, the computation is probably another hundred times. Now we're looking at in just two years, computation went up by a fac—10,000X. Meanwhile, people pay for information, but people mostly pay for work. Talking to a chatbot and getting an answer is super great. Helping me do some research, unbelievable. But getting work done, I'll pay for. And so that's where we are. Agentic systems get work done. They're helping our software engineers get work done, and and so then you take that—you got 10,000X more compute, you get probably at this point a 100X more consumption now, and we haven't even started scaling yet. We are absolutely at a million X.","offset":1292,"duration":109},{"text":"Host: Which is I think a great place to talk about the number of engineers you have, 20, 30,000 at the company?","offset":1401,"duration":4},{"text":"Jensen Huang: We have 43,000 employees. You know, I would say 38,000 are engineers.","offset":1405,"duration":7},{"text":"Host: The conversation we've had on the pod a number of times is, oh my God, look at the token usage in our companies. It is growing massively. And some people are asking, hey, when I join a company, how many tokens do I get? Because I want to be an effective employee. And you've postulated, I believe during your two and a half hour keynote—pretty long keynote, well done.","offset":1412,"duration":23},{"text":"Jensen Huang: If it was, if it was well done, it would be shorter. I just wanted to let—I didn't have time to write a shorter one. So you guys, so you guys know, there is no practice. And so it's a grip it and rip it.","offset":1435,"duration":13},{"text":"Host: Love it.","offset":1448,"duration":1},{"text":"Jensen Huang: Yeah, yeah. And so, so I just want to let you know I was writing the speech while I was giving the speech. Okay? So never know.","offset":1449,"duration":7},{"text":"Host: But does that mean if we do back of the envelope math, 75,000 in tokens for each engineer or something like that? So are you spending in Nvidia a billion, two billion dollars on tokens for in your engineering team right now?","offset":1456,"duration":12},{"text":"Jensen Huang: We're trying to. Let me give you the thought experiment. Let's say you have a software engineer or AI researcher and you pay them $500,000 a year. We do that all the time. Okay? This is happening all the time. Um, that $500,000 engineer at the end of the year, I'm going to ask him how many to—how much did you spend in tokens? And that person said $5,000. I will go ape something else. Yes. If that—if that $500,000 engineer did not consume at least $250,000 worth of tokens, I am going to be deeply alarmed. Okay? And this is no different than one of our chip designers who says, guess what? I'm just going to use paper and pencil, I don't think I'm going to need any CAD tool.","offset":1468,"duration":43},{"text":"Host: Right.","offset":1511,"duration":1},{"text":"Jensen Huang: Okay. This is a real paradigm shift to start thinking about these all-star employees—it almost reminds me of of what we learned in the NBA where LeBron James starts spending a million dollars a year just on his health of his body, like and maintaining it. Here he is at age 41 still playing. It really is, hey, if these are incredible knowledge workers, why wouldn't we give them superhuman abilities?","offset":1512,"duration":20},{"text":"Host: And where does that go if we, if we extrapolate out two or three years from now? What is the efficiency of that all-star at an Nvidia and what they're able to accomplish? What do they look like?","offset":1532,"duration":10},{"text":"Jensen Huang: Well, first of all, things that that, \"wow, this is too hard,\" that thought is gone. \"Uh, this is going to take a long time,\" that thought is gone. \"Um, we're going to need a lot of people,\" that thought is gone. This is no different than in this—in the last industrial revolution somebody goes, \"boy, that building really looks heavy.\" Nobody says that. No—wow, \"that mountain looks too big.\" Nobody says that. Everything that's too big, too heavy, takes too long, those thought—those ideas are all gone.","offset":1542,"duration":32},{"text":"Host: You're reduced to creativity.","offset":1574,"duration":1},{"text":"Jensen Huang: That's right. Exactly. Which means now the question is how do you—how do you work with these agents? Well, it's just a new way of doing computer programming. In the—in the past we code, in the future we're going to—we're going to write ideas, architectures, specifications, we're going to organize teams, we're going to give them—we're going to help them define how to evaluate the definition of good versus bad. What's the—what does it look like when something is a great outcome, how to iterate with you, how to brainstorm. That's really what you're looking for. And I'm—I think that every engineer's going to have hundreds, a hundred agents.","offset":1575,"duration":35}],"startTime":1225},{"title":"Accelerating Science With Agentic Tools","summary":"David Friedberg shares a story about using AutoResearch to complete a theoretical seven-year genomics project in just 30 minutes. Jensen notes that AI agents will increasingly interact with existing enterprise software tools to produce ground-truth results.","entries":[{"text":"Host: Back to the PR problem the industry has right now. You have executives like David Friedberg with Ohalo who's looking at literally taking through the use of technology, your technology and AI, the number of calories produced and making high-quality calories—what is the factor you think you can bring the cost down, Friedberg, and what impact does this vision have for what you're doing?","offset":1610,"duration":26},{"text":"Friedberg: Yeah, zero—zero shot genomic modeling. And it works. And then you have that moment and you're like, holy shit. Honestly, like, and and that's after people are replacing entire enterprise software stacks in a night. I did something in 90 minutes I was telling the guys about, replaced a whole software stack and like a whole bunch of workload 90 minutes on Claude, ran this agentic system, built the whole thing, deployed it, and we got—we were on—","offset":1636,"duration":24},{"text":"Host: On a Sunday night.","offset":1660,"duration":1},{"text":"Host: 10 p.m., I was done at 11:30, I went to bed.","offset":1661,"duration":2},{"text":"Host: As the CEO, you replaced—","offset":1663,"duration":2},{"text":"Friedberg: Yeah. And everyone on my management team had to do a similar exercise over the weekend. What we saw on Monday, I was like, it's over. But, the technical stuff, the science stuff, we did something in 30 minutes using AutoResearch, and I'd love your view on AutoResearch and what that tells us about how far we still have to go in terms of efficiency. But using AutoResearch and a chunk of data, something was published internally that we said, \"Oh my God!\" and that would normally be a PhD thesis that would take seven years. It would be one of the most celebrated PhD theses we've ever seen in the field, and it was done in 30 minutes on a desktop computer running on AutoResearch with all the data we just ingested. We got it on Friday, and we're like, hey, let's try it. Tried, booted up, go into GitHub, downloaded AutoResearch and ran it. And you see everyone's face just go like—and then the potential of what this is unlocking for us is like the kind of thing that would take seven years and it happened in 30 minutes. And we're experiencing it in genomics, and we're like, this is unbelievable. So I think like the acceleration is widening the aperture for everyone in a way that like you didn't imagine a few years ago. But just going back to the AutoResearch point, can you just comment on what you think about the fact that this thing got published with 600 lines of code and a weekend and the capacity that it has to run locally and achieve what it can achieve with all these diverse data sets and what that tells us about the early stages we are in terms of optimization on algorithms and hardware to unlock—","offset":1665,"duration":86},{"text":"Jensen Huang: The fundamental reason why Open Claude is so incredible, number one, is it's—it's confluence, its timing with the breakthroughs in large language model. Its timing was perfect, it was impeccable. Now, in a lot of ways, Peter wouldn't have come up with it, probably, if not for the fact that Claude and GPT and ChatGPT have reached a level that is really very good. It is also a new capability that allows these models to tool use. The tools that we've created over time—web browsers and Excel spreadsheets and, you know, in the case of chip design, Synopsis and Cadence, Omniverse and Blender and Autodesk—all of these tools are going to continue to be used. There's some—some people say that the enterprise IT software industry's going to get destroyed. There's—it's—there's—let me give you the alternative view. The enterprise software industry is limited by butts in seats. It's about to get a hundred times more agents banging on those tools. There are going to be agents banging on SQL, they're going to be agents banging on vector databases, agents banging on Blender, agents banging on Photoshop. And the reason for that is because those tools are—first of all, do a very good job. Second, those tools are the conduit between us. In the final analysis when the work is done, it has to be represented back to me in a way that I can control. And I know how to control those tools. And so I need everything to be put back into Synopsis, I want everything to be put back into Cadence, because that's how I control it, that's how I ground truth.","offset":1751,"duration":98}],"startTime":1610},{"title":"Open Source vs Proprietary Models","summary":"Jensen argues that the future requires both proprietary models as services and open-source models for specialized tasks. He views foundational models as general capabilities, while open models allow companies to fine-tune and control specific domain expertise.","entries":[{"text":"Host: Let me ask you a question about open source. So, we have these closed source models, they're excellent. We have these open weight models—many of the Chinese models are incredible, absolutely incredible. Two days ago, you may not have seen this because you were busy on stage, but there was a training run that happened in this crypto project called BitTensor Subnet 3. They managed to train a 4 billion parameter Llama model totally distributed with a bunch of people contributing excess compute, but they were able to do it statefully and manage a training run, which I thought was like a pretty crazy technical accomplishment.","offset":1849,"duration":37},{"text":"Jensen Huang: Our—our modern version of Folding@home.","offset":1886,"duration":-1678},{"text":"Host: Exactly. So what—what do you think about the end state of open source? Do you see this decentralization of architecture as well and decentralization of compute to support open weights and a totally open source approach to making sure AI is broadly available to everyone?","offset":208,"duration":1699},{"text":"Jensen Huang: I believe we fundamentally need models as a first-class product, proprietary product, as well as models as open source. These two things are not A or B, it's A and B. There's no question about it. And the reason for that is because model's a technology, not a product. Model's a technology, not a service. For the vast majority of consumers, the horizontal layer, the general intelligence, I would really, really, really love not to go fine-tune my own. I would really love to keep using ChatGPT, I love to use Claude, I love to use Gemini, I love to use X, and they all have their own personalities as you know, which kind of depends on my mood and depends on what problem I'm trying to solve. You know, am I, you know, do it on X or am I do it on ChatGPT. And so that—that segment of the industry is thriving, it's going to be great. However, there—all these industries, their domain expertise, their specialization, has to be channeled, has to be captured in a way that they can control. And that can only come from open models. The open model industry, we're contributing tremendously to, it is near the frontier. And quite frankly, even if it reaches the frontier, I think that products-as-a-service, world-class products-as-a-product, models-as-a-product, is going to continue to thrive.","offset":1907,"duration":85},{"text":"Host: Every startup we're investing in now is open source first and then going to the proprietary model.","offset":1992,"duration":6},{"text":"Jensen Huang: Yeah, and the beautiful thing is because you have a great router, you connect to it. By—on first day every single day you're going to have access to the world's best model, and then it gives you time to cost-reduce and fine-tune and specialize. So you're going to have world-class capabilities out the shoot every single time.","offset":1998,"duration":20}],"startTime":1849},{"title":"US AI Leadership and Global Diffusion","summary":"Jensen outlines the importance of the US leading the global AI industry and spreading American tech worldwide. He discusses licensing sales to China and stresses that a globally adopted American tech stack is a national security imperative.","entries":[{"text":"Host: Jensen, can I ask—","offset":2018,"duration":1},{"text":"Jensen Huang: Of course.","offset":2019,"duration":1},{"text":"Host: Nobody wants the US to win the global AI race more than you, right? But only a year ago, the Biden era diffusion rule really was anti-American diffusion of AI around the world. So here we are a year into the new administration, give us a grade. Where—where are we in terms of global diffusion and the rate at which we're spreading US AI technology around the world? Are we an A, are we a B, are we a C? What's working, what's not working?","offset":2020,"duration":29},{"text":"Jensen Huang: Well, first of all, President Trump wants American industry to lead. He wants American technology industry to lead, he wants American technology industry to win, he wants us to spread American technology around the world, he wants United States to be the wealthiest country in the world. He wants all of that. At the current moment, as we speak, Nvidia gave up a 95% market share in the second largest market in the world and we're at 0%.","offset":2049,"duration":30},{"text":"Host: I know.","offset":2079,"duration":1},{"text":"Jensen Huang: President Trump—that's right. President Trump wants us to get back in there. And the first thing is to get license—license for the companies that we're going to be able to sell to. We've got many companies who have requested for license, we've applied for licenses for them, and we've got approved licenses from Secretary Lutnick. Now we've, we've informed the Chinese companies and many of them have given us purchase orders. And so we're going to start—we're going to—we're in the process of cranking up our supply chain again to go ship.","offset":2080,"duration":32},{"text":"Jensen Huang: I think at the highest level, Brad, I think one of the things that we should acknowledge is this. Our national security is diminished when we don't have access to miniature motors, rare earth minerals. It's diminished when we don't control our telecommunications networks. It's diminished when we can't provide for sustainable energy for our country. It is fundamentally diminished. Every single one of these industries is an example of what I don't want the AI industry to be. When we look forward in time and we say what do we want—what is the—what does it look like when American technology industry, American AI industry leads the world, we can all acknowledge that there is no way that AI models is one universally. It is—we can all acknowledge that that is an outcome that makes no sense. However, we can all imagine that the American tech stack, from chips to computing systems to the platforms, are used broadly by the world where they build their own AI, they use public AI, they use private AI, whatever, and they can build their applications in their society. I would love that the American tech stack is 90% of the world. I would love that. The alternative, if it looks like solar, rare earth, magnets, motors, telecommunications—I consider that a very bad outcome for national security.","offset":2112,"duration":94}],"startTime":2018},{"title":"Navigating Global Supply Chain Risks","summary":"The hosts ask about geopolitical tensions affecting the supply chain, including conflicts in the Middle East and Taiwan. Jensen emphasizes supporting employees, re-industrializing the US, diversifying supply chains, and acting with restraint.","entries":[{"text":"Host: How much are you monitoring the situation with the conflicts around the world right now and how much does it worry you, Jensen? So, China and Taiwan, and then helium availability coming out of the Middle East, I understand can be a supply chain risk to semiconductor manufacturing. How much do these situations worry you? How much are you spending on them?","offset":2206,"duration":20},{"text":"Jensen Huang: Well, first of all, in the Middle East, I have—we have 6,000 families there. We have a lot of Iranians at Nvidia and their families are still in Iran. And so—so we have—we have a lot of families there. The first thing that is their—they're quite anxious, they're quite concerned, quite scared. Um, we're thinking about them all the time, we're monitoring and keeping an eye on them all the time. They have 100% of our support. I've been asked several times are we still considering being in Israel. We are 100% in Israel. We are 100% behind the families there. We are 100% in the Middle East. I was also asked, you know, given what's happening in the Middle East, is that an area where we believe that we can expand artificial intelligence to. I believe that there's a reason we went to war and I believe that at the end of the war, Middle East will be more stable than before. And so if we were there before, if we were considering it before, we should absolutely be considering it after. And so I'm 100% in on that.","offset":2226,"duration":57},{"text":"Jensen Huang: With respect to Taiwan, we have to do three things. One, we have to make sure that we re-industrialize the United States as fast as we can. And whether it's the chip manufacturing plants, the computer manufacturing plants, or the AI factory—","offset":2283,"duration":16},{"text":"Host: How are we doing on that?","offset":2299,"duration":1},{"text":"Jensen Huang: We're doing excellent. With—by—by gaining the strategic support, by gaining the friendship of the supply chain of Taiwan—by gaining their friendship, by gaining their support—we were able to build Arizona and Texas, California at incredible rates. They are genuinely a strategic partner. Um, we—we—they deserve our support, they deserve our friendship, they deserve our generosity, and they're doing everything they can to accelerate the manufacturing process for us. And so I think that's number one. Number two, we ought to diversify the manufacturing supply chain and whether it's South Korea, whether it's—it's Japan, it's Europe, we ought to diversify the supply chain, make it more resilient. And number three, let's be—let's demonstrate restraint. And while we're reducing—increasing our diversity and resilience, let's not press, push, unnecessarily.","offset":2300,"duration":69},{"text":"Host: We need to be patient and thoughtful. Is helium a problem? A lot of reports on helium—","offset":2369,"duration":5},{"text":"Jensen Huang: You know, I think helium could be a problem but it's also the case that the supply chain probably has a lot of buffer in it. These kind of things tend to have a lot of buffer. Uh, but, but, you know.","offset":2374,"duration":11}],"startTime":2206},{"title":"Autonomous Vehicles and Full-Stack Advantage","summary":"Jensen discusses Nvidia's approach to self-driving technology as a platform for multiple automakers. He also explains why Nvidia continues to gain market share over custom ASICs by offering a complete, portable AI infrastructure stack.","entries":[{"text":"Host: You've made massive progress in self-driving. You made a big announcement. You've added many more partners including BYD. There was just a video of you driving around in a Mercedes. And huge announcement with Uber that you're going to have a number of cars on the road from many different manufacturers. Your bet is I believe that there's going to be an Android type open-source platform that you're going to play a major part in with dozens of car providers and then maybe on the other side there could be an iOS with Tesla or Waymo. What's your strategy thinking there and how that chess board emerges? Because it feels like you have a pretty deep stack and in some ways you're competing and in other places you're collaborative.","offset":2385,"duration":49},{"text":"Jensen Huang: Yeah. Um, it's—taking a step back, we believe that everything that moves will be autonomous completely or partly someday. Number one. Number two, we don't want to build self-driving cars, but we want to enable every car company in the world to build self-driving cars. And so we build all three computers: the training computer, the simulation computer—the valuation—evaluation computer, as well as the car computer. We developed the world's safest driving operating system. We also created the world's first reasoning autonomous vehicle so that it could decompose complicated scenarios into simpler scenarios that it knows how to navigate through, just like us, reasoning system. And so that reasoning system called Alpamayo has enabled us to achieve incredible results. We opened this platform—we vertical optimization, we horizontally innovate, and we let everybody decide. Do you want to buy one computer from us? In the case of Elon and Tesla, they buy our training computers. Um, do they want to buy our training computer and our simulation computers or do you want to let us work with us to do all three and even put the car computer in your car. And so we, you know, our attitude is we want to solve the problem, we're not the solution provider, and we're delighted however you work with us.","offset":2434,"duration":85},{"text":"Host: Let me build on this question because I think it's so—it's so fascinating. You actually do create this platform, a thousand flowers are blooming. But it's also true that some of those flowers want to now go back down in the stack and try to compete with you a little bit. Google has TPU, Amazon has Inferentia and Trainium. You know, everybody's sort of spinning up their own version of \"I think I can out-Nvidia Nvidia,\" even though they also tend to be huge customers. How do you navigate that? And what do you think happens over time and where do those things play in the complexion of this kind of vision?","offset":2519,"duration":32},{"text":"Jensen Huang: Yeah, really great. You know, first of all, um, we're the only AI company—we're an AI company. We build foundation models, we're at the frontier in many different domains. We build every single—every single layer, every single stack. Um, we're the only AI company in the world that works with every AI company in the world. They never show me what they're building and I always show them exactly what I'm building. Right. Yeah. And so—so the confidence comes from this: One, we are delighted to compete on what is the best technology and to the extent that to the extent that we can continue to run fast, I believe that buying from Nvidia still is one of the most economic things they could do. And I should say incredible confidence there. Number one. Number two, we're the only architecture that could be in every cloud. And that gives us some fundamental advantage. We're the only architecture you could take from a cloud and put into on-prem, in the car, in any region—","offset":2551,"duration":55},{"text":"Host: In space.","offset":2606,"duration":1},{"text":"Jensen Huang: That's right, in space. And so there's a whole—whole part of our market, about 40% of our market, most people don't realize this, 40% of our business, unless you have the CUDA stack, unless you can build the entire AI factory, you have the customers don't know what to do with you. They're not trying to build chips, they're not trying to buy chips, they're trying to build AI infrastructure. And so they want you to come in with the full stack and we've got the whole stack. And so surprisingly, Nvidia's gaining market share. If you look at where we are today, we're gaining share.","offset":2607,"duration":30},{"text":"Host: Do you think what happens is these guys try and they realize \"oh my God, it's too much,\" and then they come back—is that why the share grows?","offset":2637,"duration":6},{"text":"Jensen Huang: Well, we're gaining share for several reasons. One, our velocity has gone—we help people realize it's not about building the chip, it's about building the system. And that system's really hard to build. Uh, and and so their—their business with us is increasing. In the case of AWS, I think they just announced, I think it was yesterday, that they're going to buy a—a million chips uh in the next couple of years. I mean, that's a lot of chips from—from AWS, and that's on top of all the chips they've already bought. And so we're delighted to do that. But number one, we're gaining share this last couple of years because we now have Anthropic coming to Nvidia, Meta SL is coming to Nvidia, and the growth of open models is incredible and that's all on Nvidia. And so we're growing in share because of the number of models. We're also growing in share because outside all of these companies are outside of the cloud, and they're growing regionally, in enterprise, in industries, at the edge. And that entire segment of growth is, you know, really hard to do if it's just building an ASIC.","offset":2643,"duration":67}],"startTime":2385},{"title":"Nvidia's TAM vs Analyst Forecasts","summary":"When asked about conservative Wall Street forecasts, Jensen explains that analysts underestimate the scale and breadth of AI beyond big cloud hyperscalers. He asserts that Nvidia is building AI infrastructure, not just making chips.","entries":[{"text":"Host: Brad, related to that, and not to get in the weeds on the numbers, but analysts don't seem to believe, right? So if you look at the consensus forecast, you said compute could one million X, right? And yet they have you growing next year at 30%, the year after that at 20%, and in 2029, which is supposed to be a monster year, at 7%. Right? So if you just—if you take your TAM and you apply their growth numbers, it suggests that your share will plummet. Do you see anything in your future order book that would make that correct?","offset":2710,"duration":34},{"text":"Jensen Huang: Yeah, first of all, they just don't understand the scale and the breadth of AI. Yes. I think that's true. I think that's true. Most people think that AI is in the top five hyperscalers. Right. That's right. There's also an orthodoxy around these law of large numbers where, you know, they have to go back to their investment banking risk committee and show some model. They're not going to believe in their minds that 5 trillion goes to 15 trillion. They're like it can go it can go to 7. Or they can have a $10 trillion company. It's all just CYA stuff that I think—it's never happened before, so you can't say it will. And—and because because you have to redefine what it is that you do. There was somebody who made an observation recently that Nvidia—Jensen, how can you be larger than Intel in servers? And the reason for that is because the CPU market of the entire data center was about $25 billion a year. We do $25 billion a year, as you guys know, in a very—in the time that we were sitting here. And so obviously, obviously—that was a joke. All in podcast humor. No, it's roughly true. Don't worry, everything on the show is roughly true, don't worry about it. It's all—God damn. No, no, no, that was not guidance. But anyhow, anyhow, the point is how big you can be depends on what it is that you make. Nvidia's not making chips. Number one, making chips does not help you solve the AI infrastructure problem anymore. It's too complicated. Number three, most people think that AI is narrowly in the things that they talk about and hear and see. AI's much—OpenAI's incredible, they're going to be enormous. Anthropic is incredible, they're going to be enormous. But AI is going to be much, much bigger than that. And we address that segment.","offset":2744,"duration":108}],"startTime":2710},{"title":"Data Centers in Space","summary":"Jensen briefly touches on the concept of putting data centers in space. He mentions the cooling challenges of zero-gravity environments but notes the benefits of processing satellite imaging data locally in orbit.","entries":[{"text":"Host: Tell us about—tell us about data centers in space for a second.","offset":2852,"duration":3},{"text":"Jensen Huang: We are already in space.","offset":2855,"duration":1},{"text":"Host: How should the layman think about what that business is versus when you hear about these big data center build-outs that's happening in—on the ground?","offset":2856,"duration":10},{"text":"Jensen Huang: Well, we should definitely work on the ground first because we're already here. And number one. Number two, we should prepare to be out in space, and obviously there's a lot of energy in space. Um, the challenge of course is that cooling, you can't take advantage of conduction and convection. Exactly. And so you can only use radiation. And radiation requires very large surfaces. And so—now that's not an impossible thing to solve and there's lot—lot of space in space. Um, but nonetheless, the expense is still quite there, is—is there. Um, we're going to go explore it. We're already there, we're already radiation hardened. Um, we have—we have—CUDA in satellites around the world. Um, they're doing imaging, image processing, AI imaging. And—and that kind of stuff ought to be done in space instead of sending all the data back here and do imaging down here. We ought to just do imaging out in space. And so there's a lot of things that we ought to do in space. In the meantime, we're going to explore what is the architecture of data centers look like in space. And it'll take—it'll take years. It's okay. We got—I got plenty of time.","offset":2866,"duration":65}],"startTime":2852},{"title":"Transforming Healthcare With AI","summary":"The discussion turns to healthcare, where Jensen highlights three key areas of focus: AI physics for drug discovery, agentic assistants for diagnostics, and physical AI for robotic surgery.","entries":[{"text":"Host: I wanted to double click on healthcare. I know you've got a big effort there. We're all of a certain age where we're thinking about lifespan, healthspan. I mean, we all look great, I think.","offset":2931,"duration":8},{"text":"Jensen Huang: Some better than others.","offset":2939,"duration":2},{"text":"Host: Some better than others. I don't know what your secret is, Jensen. You look pretty good, these—the Asians—","offset":2941,"duration":4},{"text":"Jensen Huang: Squats and push-ups and sit-ups.","offset":2945,"duration":2},{"text":"Host: Perfect. Okay. Yeah. Um, but what you know in terms of the build-out in healthcare, where is that going and what kind of progress are we making? I was just using Claude to do some analysis and saying like, where are all these billing codes we spend twice as much money in the US, we get—seem to get half as much. It seemed like 15 to 25 percent of the dollar spent were on these first GP visits. And I think we all know like ChatGPT and a large language model does a better job, more consistently today at a first visit. So what has to happen there to kind of break through all that regulation and have AI have a true impact on the healthcare system?","offset":2947,"duration":48},{"text":"Jensen Huang: There's several areas we're involved in—in—in healthcare. One is AI physics. Uh, and and that's or AI biology. Using AI to understand, represent, predict biology, behavior, biological behavior. And so that's one, that's very important in drug discovery. There's second, which is AI agents, and that's where the assistants and helping diagnosis and things like that. Open Evidence is a really good example, Hippocratic's a really good example, love working with those companies. Um, I really think that this is an area where agentic technology is going to revolutionize how we interact with doctors and how do we interact for healthcare. The third part that we're in—involved in is physical AI. The first one's AI physics using AI to predict physics. The second one is physical AI, AI that understand the properties of the laws of physics. And that's used for agent—robotics surgery. Huge amounts of activities there. Every single instrument, whether it's ultrasound or, you know, CT or whatever instrument we interact with in a hospital in the future will be agentic. You know, Open Claude in a safe version will be inside every single instrument, and so in a lot of ways that instrument's going to be interacting with patients and nurses and doctors in a very unique way.","offset":2995,"duration":78}],"startTime":2931},{"title":"The Imminent Robotics Revolution","summary":"Jensen predicts that highly functional consumer robotics are only 3 to 5 years away, acknowledging China's strong supply chain in the space. They discuss applications ranging from factory labor to tele-operating avatars and space colonization.","entries":[{"text":"Host: Yeah, I mean we've seen so much investment in AI weapons. It would be wonderful to see some investment in AI EMTs and paramedics and saving lives, not just taking them. Uh, which I think is a great segue into robotics. You've got dozens of partners. We had this very weird, I don't know what to call it, lost decade or 20 years of Boston Dynamics, Google bought a bunch of companies, they then wound up selling them and spinning them out, where people just thought \"Ah, robotics is just not ready for prime time.\" And now here we have the world's greatest entrepreneur at this time, um, tied with you, um, Elon Musk doing—oh that was a good save I hope—Optimus, uh, pretty impressive. And then other companies in China. How close is that to actually being in our lives where we might see a chef, a robotic chef, a robotic nurse, a robotic housekeeper, you know these humanoid factors actually working in the real world knowing what you know with those partners and the fidelity especially in China where they seem to be doing as good a job as we're doing here or maybe better?","offset":3073,"duration":65},{"text":"Jensen Huang: We invented the industry largely. American invented—we—you could argue we got into it too soon. Yeah. And we got exhausted, we got tired, um, about five years before the enabling technology appeared. Yes, the brain. Yeah, yeah. And we just got tired of it just a little too soon. Okay, that's number one. But it's here now. Now, the question is how much longer? From the point of high functioning existence proof—high functioning existence proof to reasonable products technology never takes more than a couple, two-three cycles. And so a couple, two-three cycles is basically be somewhere around three years to five years. That's it. Three years to five years, we're going to have robots all over the place. Uh, I think—I think—China is is a—formidable, and the reason for that is because their microelectronics, their motors, their rare earth, their magnets, which is foundational to robotics, they are the world's best. And so in a lot of ways, our robotics industry relies deeply on their ecosystem and their supply chain, um, and and and they're, you know, obviously moving very quickly. Uh, we're going to, you know, our robotics industry will have to rely a lot on it, the world's robotics industry will have to rely on a lot on it. And so—so I think—you're going to see some fast—fast movements here.","offset":3138,"duration":84},{"text":"Host: Ultimately, one for one, Elon seems to think we're going to have one robot for every human. 7 billion for 7 billion, 8 billion for 8 billion.","offset":3222,"duration":7},{"text":"Jensen Huang: Well, I'm hoping more. Yeah. I'm hoping more. Yeah. Um, well first of all, there's a whole bunch of robots that are going to be in factories working around the clock. There's going to be a whole bunch of factories—robots that that don't move, they move a little bit. Uh, almost everything will be robotic.","offset":3229,"duration":15},{"text":"Host: What does the—","offset":3244,"duration":1},{"text":"Host: Sorry, let me just—I think like, this is one of the—robotics for me is one of the pieces that I think unlocks uh economic mobility opportunities for every individual. Everyone now—like when everyone got a car they could now go and do a lot of different jobs. When everyone gets a robot, their robot can do a lot of work for them. They can stand up an Etsy store or a Shopify store, they can create anything they want with their robot. They could do things that they independently cannot do. I think the robot is going to end up being the greatest unlock for prosperity for more people on Earth than we've ever seen with any technology before.","offset":3245,"duration":33},{"text":"Jensen Huang: Yeah, no doubt. I mean, just a simple—the simple math at the moment is we're millions of people short in labor today. Right. Yeah. Right. We're—we're actually really desperate in need of robotics so that all of these companies could grow more if they had more labor. I mean, we're—number one. Uh, some of the things that you mentioned are super fun. I mean, because of robots, we'll have virtual presence. Uh, you know, I'll be able to go into the robot at my house and virtually operate it. I'm on a business trip. Right. Tele-operate. Walk the dog. Great. Yeah, walk the dog, rake the leaves. Yeah, exactly. Freak out the dog. Maybe not quite that, but just, you know, wander around and just see what's going on in the house, you know, chat with the dogs, chat with the kids, yeah. Yeah.","offset":3278,"duration":47},{"text":"Jensen Huang: Time travel is also we're going to be able to travel at the speed of light, you know. And so—you know, clearly, we're going to send our robots ahead of us. Yeah. Not going to send myself, I'm going to send a robot. You know, check it out. Yeah, yeah. And then I'm going to upload my AI.","offset":3325,"duration":14},{"text":"Host: Well, it's inevitable. It unlocks the moon and it unlocks Mars as, um, targets for colonization, which gives us infinite resources. Getting back from the moon is effectively zero energy cost to move material back because you can use solar and accelerate. So you could have factories that make everything the world needs on the moon and the robots are going to be the unlock for enabling that.","offset":3339,"duration":18},{"text":"Jensen Huang: That's right. Distance no longer matters. Distance doesn't matter. Yeah.","offset":3357,"duration":4}],"startTime":3073},{"title":"Vertical AI and Enterprise Software Moats","summary":"Looking at non-infrastructure AI revenue, Jensen expects enterprise software companies to act as value-added resellers of AI tokens. He advises entrepreneurs that deep domain specialization will be the ultimate competitive moat.","entries":[{"text":"Host: The more—the more revenue we get out of models and agents, the more we can invest in building the infrastructure which then unlocks more capabilities on models and agents. Dario on Dwarkesh's podcast recently said by 27-28 we'll have hundreds of billions of dollars of revenue out of the model companies and the agent companies and he forecast a trillion dollars by 2030, right? This is non-infrastructure AI revenue. Um—","offset":3361,"duration":27},{"text":"Jensen Huang: I think he's—I think he's—he's being very conservative. I believe Dario and Anthropic is going to do way better than that.","offset":3388,"duration":6},{"text":"Host: Wow.","offset":3394,"duration":1},{"text":"Jensen Huang: Yeah. Um, from 30 billion to a trillion. Yeah. And not—and—and the reason for that is the one part that he hasn't considered is that I believe every single enterprise software company will also be a reseller, value-added reseller of Anthropic code, Anthropic's tokens. Value-added reseller of OpenAI. Value—that's right. Have to be. And they're going to—that—that—that part of their business is about to see logarithmic expansion.","offset":3395,"duration":26},{"text":"Host: Yes.","offset":3421,"duration":0},{"text":"Jensen Huang: Yeah. Their go-to-market is going to expand tremendously this year.","offset":3421,"duration":4},{"text":"Host: What do you think in that world is the moat? What's left over? Like, I mean, you have some moats that are frankly, I think, as this scales, almost insurmountable. The best one that nobody talks about is probably CUDA, which is just like an incredible strategic advantage. But in the future, if a model can be used to create something incredible, then the next spin of a model can be used to maybe disrupt it. Sort of in your mind, what do you think for these companies that are building at that application layer? What's their moat? Like, how do they differentiate themselves?","offset":3425,"duration":33},{"text":"Jensen Huang: Deep specialization. Deep specialization. I believe that um these models—they—they're going to have general—general models that are connected into the software company's agentic system. Right. Many of those models are cloud models and proprietary models, but many of those models are specialized sub-agents that they've trained on their own—","offset":3458,"duration":25},{"text":"Host: Right, so the call to arms for you for entrepreneurs is look, know your vertical, know it as deep and as better than everybody else, and then wait for these tools because they're catching up to you and now you can imbue it with your knowledge.","offset":3483,"duration":12},{"text":"Jensen Huang: That's right. And the sooner you connect your agent—the sooner you connect your agent with customers, that flywheel is going to cause your agent to get—","offset":3495,"duration":9},{"text":"Host: It very much is an inversion of what we do today because today we build a piece of software and we say what generalizes and then let's try to sell it as broadly as possible and then sell the customization around it.","offset":3504,"duration":10},{"text":"Jensen Huang: And we try to—and in fact—exactly right. We—we create a horizontal, but notice there are all these GSIs and all these consultants who are specialists who then take your horizontal platform and specializes it into—","offset":3514,"duration":16},{"text":"Host: Exactly. And that's arguably a five or six time bigger industry is the customization.","offset":3530,"duration":4},{"text":"Jensen Huang: It is absolutely. That's very much. That's right. So I think that these platform companies have an opportunity to become that specialist, to become that vertical. Right.","offset":3534,"duration":10}],"startTime":3361},{"title":"AI's Impact on Jobs and Education","summary":"Jensen addresses job displacement by explaining how roles will transform rather than disappear, using the historical example of radiologists who saw increased demand after AI adoption. He advises young people to focus on becoming experts at using AI tools.","entries":[{"text":"Host: You know, I just want to give you your flowers. I think it was three years ago you said you're not going to lose your job to AI, you're going to lose your job to somebody using AI. And here we are, the entire conversation has revolved around this concept of agents making people superhuman and the business opportunity expanding and entrepreneurship expanding. You actually saw it pretty clearly.","offset":3544,"duration":20},{"text":"Jensen Huang: Have you changed your view? Because you—you were—you were—doomer—Doomer Dan.","offset":3564,"duration":-3234},{"text":"Host: No, I—I—I—","offset":330,"duration":3242},{"text":"Host: This is—this is Spiral J-Cal.","offset":3572,"duration":1},{"text":"Host: No, no. There is—you can hold space for I think two ideas. One is there are going to be a large—","offset":3573,"duration":3},{"text":"Host: That's by J-Cal by the way.","offset":3576,"duration":1},{"text":"Host: No, no. There is—you can—","offset":3577,"duration":1},{"text":"Jensen Huang: But that's just because he doesn't hang out with me enough.","offset":3578,"duration":3},{"text":"Host: Well, we've—I mean, we've hung a little.","offset":3581,"duration":2},{"text":"Host: Be careful, J-Cal.","offset":3583,"duration":1},{"text":"Host: We don't talk about it.","offset":3584,"duration":1},{"text":"Jensen Huang: He will show up at your breakfast table.","offset":3585,"duration":1},{"text":"Host: He will follow you around.","offset":3586,"duration":1},{"text":"Jensen Huang: He'll follow you around.","offset":3587,"duration":1},{"text":"Host: I mean, I'm not—I'm not asking for it.","offset":3588,"duration":1},{"text":"Host: You'll follow you around.","offset":3589,"duration":1},{"text":"Jensen Huang: I'm not asking for it. I'm just saying—","offset":3590,"duration":1},{"text":"Host: You can come with me and Tucker, we ski in Japan every January.","offset":3591,"duration":2},{"text":"Jensen Huang: Oh, I would love it. Me and Tucker, we'll go on a road trip. Wow.","offset":3593,"duration":3},{"text":"Host: Okay. No, there is going to be job displacement and then the question becomes, you know, do those people have the fortitude, the resolve to then go embrace these, you know, technologies. We're going to see 100% of driving go away by humans. That's just—it—that's a beautiful thing in the lives saved, but we have to recognize that's 15 million people in the United States, 10 to 15 million who are employed in that way. And—and so that is going to happen, yes?","offset":3596,"duration":26},{"text":"Jensen Huang: I—I think that jobs will change. For example, um, there are many chauffeurs today, uh, who drive the car. I believe that those—many of those chauffeurs will actually be in the car sitting behind the dri—the steering wheel while the car is driving by itself. And the reason for that is because remember what a chauffeur does. In the end, these chauffeurs, they're helping you, they're your assistant, they're helping you with your luggage, they're helping you—I mean, they're helping you with a lot of things. And—and so I wouldn't be surprised actually if the chauffeurs of the future becomes your mobility assistant and they are helping you do on a whole bunch of other stuff—","offset":3622,"duration":36},{"text":"Host: Check you into the hotel.","offset":3658,"duration":1},{"text":"Jensen Huang: —get the—and the car's driving by itself. Right. The autopilot in planes created a lot more pilots and didn't take any of the pilots out of the cockpit even though the autopilot is flying the plane 90% of the time.","offset":3659,"duration":12},{"text":"Jensen Huang: And by the way, while that car's driving itself, that chauffeur is going to be doing a bunch of other work on his phone and he's going to be making money doing other things. Arranging for example, doing—coordinating a bunch of things for you, getting, you know, yeah. It's—the pie just grows in a way that—yes, every job will be—will be transformed. Um, some jobs will be eliminated. However, we also know that many, many jobs will be recreated—will be created.","offset":3671,"duration":29},{"text":"Jensen Huang: The one thing that I will say to young people who are coming out of school who are concern—who are anxious about AI: be the expert of using AI. Yes. How much—look, we all want our employees to be expert at using AI, and it's not—not trivial. Not trivial. And so knowing how to specify, not to over-prescribe, leaving enough room for the AI to innovate and create while we guide it to the outcome we want, evalu—all of that requires artistry.","offset":3700,"duration":26},{"text":"Host: You had—you had this great advice to when you were at Stanford I think it was, which is I wish to you pain and suffering, do you remember that?","offset":3726,"duration":5},{"text":"Jensen Huang: Yeah.","offset":3731,"duration":1},{"text":"Host: Fantastic. What's your advice to young people around what they should be studying? So if they're sort of about to leave high school, because now those are the kids that are at this like really native—they haven't made a decision about college, what to study, if at all go to college. How do you guide those kids? What would you tell them?","offset":3732,"duration":19},{"text":"Jensen Huang: I—I still believe that deep science, deep math, um, uh language skills, you know, as you know, language is the programming language of AI now.","offset":3751,"duration":12},{"text":"Host: The ultimate programming language.","offset":3763,"duration":1},{"text":"Jensen Huang: And so as it turns out, it could be that the English major could be the most successful. Yeah. And—and so—so I think—I think—uh, I would just advise whatever—whatever education you get, just make sure that you're deeply, deeply expert in using AIs.","offset":3764,"duration":15},{"text":"Jensen Huang: One of the things that I wanted to say with respect to jobs and I want everybody to hear it, that in fact at the beginning of the deep learning revolution, one of the finest computer scientists in world, deeply—deeply I—deeply um deeply uh respect, uh predicted that computer vision will completely eliminate radiologists. And that the one—the one field he advises everybody to not go into is radiology. 10 years later, his prediction was at 100% right. Computer vision has been integrated into all of the radiology technologies and radiology platforms in the world 100%. The surprising outcome is the number of radiologists actually went up and the demand for radiologists is skyrocketed. The reason for that is because everybody's job has a purpose and its task. The task that you do is studying the scans, but your purpose is to diag—helping the doctors, healing the patient, diagnose disease. Right. And so what's surprising is because the scans are now being done so quickly, they could do more scans, improving healthcare. Yes. But doing more scans more quickly allows patients to be um onboarded a lot more quick—treated a lot more quickly, and as it turns out because hospitals enjoy making money too, yeah, right, they're doing more scans, they're treating more customers and more patients, early detection becomes perfect—perfect example, perfect example. The revenues go up and guess what? Need more—yeah.","offset":3779,"duration":95},{"text":"Jensen Huang: And at—and—at a country that grows faster, productivity increases, a wealthier country can put more teachers in the classroom, not less teachers in the classroom. That's right. You just give every one of those teachers a personalized curriculum for every student in the room. It makes them all bionic and leads to a lot more. Every single student will be assisted by AI, but every single student will still need great teachers.","offset":3874,"duration":23}],"startTime":3544},{"title":"Conclusion and Final Thoughts","summary":"The hosts thank Jensen for his time and praise his optimistic, grounded perspective on the future of AI. The interview wraps up with casual banter and closing remarks.","entries":[{"text":"Host: Yeah. Amazing. Um, Jensen, congratulations on all your success and really this is an incredibly positive, uplifting discussion. We really appreciate you taking the time for us.","offset":3897,"duration":10},{"text":"Host: He is the steward we need.","offset":3907,"duration":1},{"text":"Host: You are—I think you need to be more vocal. No, I'm being very, very—be more vocal about the positive side of it. I think there's so much doomerism.","offset":3908,"duration":6},{"text":"Host: But I also think it takes the humility to have this level of success and be humble about \"we're making software, guys.\"","offset":3914,"duration":7},{"text":"Jensen Huang: Yeah.","offset":3921,"duration":1},{"text":"Host: And I think that that's actually really healthy for people to hear. We have done this before. We have invented categories and industries before. Yes. We don't need to go to this scaremongering place, it does nothing.","offset":3922,"duration":11},{"text":"Host: And we get to choose, right? We have autonomy and and agency. We get to pick how to deploy this.","offset":3933,"duration":6},{"text":"Jensen Huang: We sure do.","offset":3939,"duration":1},{"text":"Host: Okay everyone, we'll see you next time. Uh, on the All-In interview. Okay.","offset":3940,"duration":4},{"text":"Host: Well done, brother.","offset":3944,"duration":1},{"text":"Host: Thanks, man.","offset":3945,"duration":1},{"text":"Host: Good job.","offset":3946,"duration":1},{"text":"Host: Thank you, sir. That was awesome.","offset":3947,"duration":1},{"text":"Host: Appreciate you. You guys are awesome. Look at this—look at this big crowd behind you guys.","offset":3948,"duration":5},{"text":"Host: Man, I think they're here for you.","offset":3953,"duration":9},{"text":"Music: [Singing] I’m doing all in. I’m doing all in. I’m doing all in. [End of video]","offset":3962,"duration":15}],"startTime":3897}],"entries":[{"text":"Host: Special episode this week. We've preempted the weekly show, and there's only three people we preempt the show for: President Trump, Jesus, and Jensen. And, uh, I'll let you pick which order we do that, but what an amazing run you've had and a great event.","offset":0,"duration":18},{"text":"Jensen Huang: Every industry's here. Every tech company's here. Every AI company's here. Incredible.","offset":18,"duration":7},{"text":"Host: Extraordinary. And one of the great announcements of the past year has been Groq. When you made the purchase of Groq, did you realize how insufferable Chamath would become?","offset":25,"duration":11},{"text":"Jensen Huang: I had a, I had an inkling that that, uh—","offset":36,"duration":4},{"text":"Host: We're his friends. We have to deal with him every week.","offset":40,"duration":3},{"text":"Jensen Huang: I know it.","offset":43,"duration":1},{"text":"Host: You had to deal with him for the six-week close.","offset":44,"duration":2},{"text":"Host: It was like two weeks.","offset":46,"duration":1},{"text":"Host: Two weeks.","offset":47,"duration":1},{"text":"Jensen Huang: It's all coming back to me now. It's making me rather uncomfortable. The thing is, many of our strategies are presented in broad daylight at GTC years in advance of when we do it. Two and a half years ago, I introduced the operating system of the AI factory, and it's called Dynamo. Dynamo, as you know, is a piece of instrument, a machine that was created by Siemens to turn essentially water into electricity. And Dynamo, uh, powered the factory of the last industrial revolution. So I thought it was the perfect name for the operating system of the next industrial revolution, the factory of that. And so inside Dynamo, the fundamental technology is disaggregated inference. Jason, I know you're super technical.","offset":48,"duration":52},{"text":"Host: Absolutely.","offset":100,"duration":1},{"text":"Jensen Huang: I'll let you take this one. Go ahead and define it for the audience. I don't want to step on you.","offset":101,"duration":4},{"text":"Host: Yeah, thanks. I knew you wanted to jump in there for a second. But it's, it's disaggregated inference, which means the, the pipeline, the processing pipeline of inference is extremely complicated. In fact, it is the most complicated computing problem today. Incredible scale, lots of mathematics of different shapes and sizes. And we came up with the idea that you would change, you would, you would disaggregate parts of the processing such that some of it can run on some GPUs, the rest of it can run on different GPUs. And that led to us realizing that maybe even disaggregated computing could make sense. That we could have different heterogeneous nature of computing. That same sensibility led us to Mellanox.","offset":105,"duration":45},{"text":"Jensen Huang: You know, today, Nvidia's computing is spread across GPUs, CPUs, switches, scale-up switches, scale-out switches, networking processors, and now we're going to add Groq to that, and we're going to put the right workload on the right chips. You know, we just really evolved from a GPU company to an AI factory company.","offset":150,"duration":21},{"text":"Host: I mean, I think that was probably the biggest takeaway that I had. You're seeing this fundamental disaggregation where we've gone from a GPU, and now you have this complexion of all these different options that will eventually exist. The thing that you guys said on stage, or you said on stage, was I, I would like the high-value inference people to take a listen to this and 25% of your data center space you said should be allocated to this Groq LPU GPU combo.","offset":171,"duration":29},{"text":"Jensen Huang: We should add Groq to about 25% of the Vera Rubins in the data center.","offset":200,"duration":6},{"text":"Host: So can you tell us about how the industry looks at this idea of now basically creating this next generation form of disaggregated, pre-filled, decode, disagg, and how people you think will react to it?","offset":206,"duration":13},{"text":"Jensen Huang: Yeah, and take a step back and at the time that we added this, we went from large language model processing to agentic processing. Now, when you're running an agent, you're accessing working memory, you're accessing long-term memory, you're using tools, you're really beating up on storage really hard. You have agents working with other agents. Some of the agents are very large models, some of them are smaller models, some of them are diffusion models, some of them are autoregressive models. And so there are all kinds of different types of models inside this data center. We created Vera Rubin to be able to run this extraordinarily diverse workload. My sense is—and so we added what used to be a one-rack company, we now add a four-more racks.","offset":219,"duration":46},{"text":"Host: Right.","offset":265,"duration":1},{"text":"Jensen Huang: So Nvidia's TAM, if you will, increased from whatever it was to probably something, call it, you know, 33%, 50% higher. Now, part of that 33% or 50%, a lot of it's going to be storage processors, it's called BlueField. Some of it will be, a lot of it I'm hoping will be Groq processors, and some of it will be CPUs, and they're all going to, and a lot of it's going to be networking processors, and so all of this is going to be running basically the computer of the AI revolution called agents. The operating system of, uh, modern industry.","offset":266,"duration":34},{"text":"Host: What about, what about embedded applications? So, you know, my daughter's teddy bear at home wants to talk to her. What goes in there? Is it a custom ASIC or does there end up becoming much more kind of a broader set of TAM with developing tools that are maybe different for different use cases at the edge and in an embedded application?","offset":300,"duration":20},{"text":"Jensen Huang: We think that there's three computers in the problem. At the, at the largest, at the largest scale when you take a step back. There's one computer that's really about training the AI model, developing, creating the AI. Another computer for evaluating it. Depending on the type of problem you're having, like for example, you look around, there's all kinds of robots and cars and things like that. You have to evaluate these robots inside a virtual gym that represents the physical world. So it has to be software that obeys the laws of physics. And that's a second computer, we call that Omniverse. The third computer is the computer at the edge, the robotics computer. That robotics computer, one of them could be a self-driving car, another one's a robot, another one could be a teddy bear, little tiny one for a teddy bear. One of the most important ones is one that we're working on that basically turns the telecommunications base stations into part of the AI infrastructure. So now all of the, it's a $2 trillion industry. All of that in time will be transformed into an extension of the AI infrastructure. And so radios, radios will become edge devices. Factories, warehouses, you name it. And so, so there are three, these three basic computers, all of them, you know, are going to be necessary.","offset":320,"duration":79},{"text":"Host: Jensen, last, last year I think you were ahead of the the rest of the world in in in saying inference isn't going to 1000X, it's going to one billion X.","offset":399,"duration":10},{"text":"Jensen Huang: Just last year?","offset":409,"duration":1},{"text":"Host: Yes.","offset":410,"duration":1},{"text":"Host: Brad, you're hurting my feelings.","offset":411,"duration":1},{"text":"Host: Isn't, it isn't, it isn't going to 1000X, it's going to one billion X. Right, and I think people at the time thought it was pretty hyperbolic because the world was still focused on pre-scaling on training. Here we are, now inference has exploded, we're inference constrained. Um, you announced an inference factory that I think is leading edge, that's going to be 10X better in terms of throughput to the next factory. But yet, if you, if I listen to what the chatter is out there, it's that your inference factory is going to cost 40 or 50 billion and the alternatives—the custom ASICs, AMD, others—are going to cost 25 to 30 billion and you're going to lose share. So why don't you talk to us—what are you seeing, how do you think about share, and does it make sense for all these folks to pay something that's a 2X premium to what others are marketing?","offset":412,"duration":41},{"text":"Jensen Huang: The big takeaway, the big idea, is that you should not equate the price of the factory and the price of the tokens. The cost of the tokens. It is very likely that the $50 billion factory, and in fact I can prove it, that the $50 billion factory will generate for you the lowest cost tokens. And the reason for that is because we produce these tokens at extraordinary efficiency. 10 times, you know, the difference between 50 billion, now it turns out 20 billion is just lamp power and shell, right? And then on top of that, you have storage anyways, networking anyways, you got CPUs anyways, you got servers anyways, you got cooling anyways. The difference between that GPU being 1X price or half X price is not between 50 billion and 30 billion. Pick your favorite number, but let's say between 50 billion and 40 billion. That is not a large percentage when the $50 billion data center is actually 10 times the throughput. That's the reason why I said that even for most chips, if you can't keep up with the state of the technology and the pace that we're running, even when the chips are free, it's not cheap enough.","offset":453,"duration":79},{"text":"Host: Can I, can I just ask a general strategy question?","offset":532,"duration":3},{"text":"Jensen Huang: Yeah.","offset":535,"duration":1},{"text":"Host: I mean, you're running the most valuable company in the world. This thing is going to do 350 plus billion of revenue next year, 200 billion of free cash flow. It's compounding at these crazy rates. How do you decide what to do? Like, how do you actually get the information—I mean, it's famous now, these sort of emails that are people are meant to send you—but how do you really decide to get an intuition of how to shape the market, where to really double down, where to maybe pull back, where to actually go into a Greenfield? How does that information get to you? How do you decide these things?","offset":536,"duration":31},{"text":"Jensen Huang: In the final analysis, that's the job of the CEO. And our job is to define the strategy, define the vision, define the strategy. We're informed, of course, by amazing computer scientists, amazing technologists, great people all over the company. But we have to shape that future. Well, part of it has to do with is this something that's insanely hard to do? If it's not hard to do, we should back away from it. And the reason for that is if it's easy to do, obviously—","offset":567,"duration":25},{"text":"Host: Lots of competitors.","offset":592,"duration":1},{"text":"Jensen Huang: —a lot of competitors. Is this something that has never been done before, that's insanely hard to do, and that somehow taps into the special superpowers of our company? And so I have to find this confluence of things to do that meets this standard. And in the end, we also know that a lot of pain and suffering's going to go into it. There are no great things that are invented because it was just easy to do and just like first try, here we are. And so if it's super hard to do, nobody's ever done it before, it's very likely that you're going to have a lot of pain and suffering, and so you better enjoy it.","offset":593,"duration":32},{"text":"Host: Can you, so can you just look at maybe three or four of the more long-tail things you announced and just talk about the long-term viability of whether it's the data centers in space, or whether it's what you're trying to do with ADAS in autos, or, you know, what you're trying to do on the biology side? Just give us a sense of like how you see some of these curves inflecting upwards in some of these longer tail businesses.","offset":625,"duration":21},{"text":"Jensen Huang: Excellent. Physical AI, large category. We believe, and I just mentioned, we have three computing systems, all the software platforms on top of it. Physical AI as a large category, it's the technology industry's first opportunity to address a $50 trillion industry that has largely been, you know, void of technology until now. And so we need to invent all of the technology necessary to do that. I felt that that was a 10-year journey. We started 10 years ago, we're seeing it inflecting now. It is a multi-billion dollar business for us, it's close to $10 billion a year now. And so it's a big business and it's growing exponentially. And so that's number one. I think in the case of digital biology, I think we are literally near the ChatGPT moment of digital biology. We're about to understand how to represent genes, proteins, cells—we already know how to understand chemistry—and so the ability for us to represent and understand the dynamics of the building blocks of biology, that's a couple, two, three, five years from now. In five years' time, I completely believe that the healthcare industry where digital biology is going to inflect. And so these are a couple of the really great ones, and you can see they're all around us.","offset":646,"duration":77},{"text":"Host: Agriculture.","offset":723,"duration":1},{"text":"Jensen Huang: Agriculture.","offset":724,"duration":1},{"text":"Host: Inflecting now.","offset":725,"duration":1},{"text":"Jensen Huang: No question.","offset":726,"duration":1},{"text":"Host: Jensen, I want to take you from the data center to the desktop. The company was built in large part on hobbyists, video gamers, and and all those graphics cards in the beginning. And you mentioned in front of, I think, 10,000 people here, just Claude—Open Claude, Claude Code—and what a revolution agents have become. And specifically, the hobbyists who are really where a lot of energy, um, we see, you know, a lot of the innovation breaks, want desktops. You announced one here, I believe it's the Dell 6800. This is a very powerful workstation to run local models, 750 gigs of RAM. Obviously, the Mac Studio sold out everywhere in my company. We're moving to Open Claude everything. Friedberg just got Claude-pilled. You got Claude-pilled, I understand, and you're obsessed with these. What is this \"from the streets\" movement of creating open-source agents and using open-source on the desktop mean to you, and where is that going?","offset":727,"duration":58},{"text":"Jensen Huang: So great. Yeah, so great. First of all, let's take a step back. In the last two years, we saw basically three inflection points. The first one was generative. ChatGPT brought AI to the common everybody, to our awareness. But the fact of the matter is the technology sat in plain sight months before GPT. It wasn't until ChatGPT put a user interface around it, made it easy for us to use, that generative AI took off. Now, generative AI, as you know, generates tokens for internal consumption as well as external consumption. Internal consumption is thinking, which led to reasoning. O1 and O3 continue that wave of ChatGPT grounded information, made AI not only answer questions, but answer questions in a more grounded way, useful. We started seeing the revenues and the, the economic model of OpenAI start to inflect. Then the third one was only inside the industry that we saw. Claude Code, the first agentic system that was very useful. Really revolutionary stuff. But, but Claude Code was only available for enterprises. Most people outside never saw anything about Claude Code until Open Claude. Open Claude basically put into the popular consciousness what an AI agent can do. That's the reason why Open Claude's so important from a cultural perspective.","offset":785,"duration":90},{"text":"Jensen Huang: Now, the second, second reason why it's so important is that Open Claude is open, but it formulates, it structures a type of computing model that is basically reinventing computing all together. It has a memory system, scratch—is it short-term memory, file system? It has—it has—","offset":875,"duration":25},{"text":"Host: Skills.","offset":900,"duration":1},{"text":"Jensen Huang: Did you say skills or scales?","offset":901,"duration":1},{"text":"Host: Skills.","offset":902,"duration":1},{"text":"Jensen Huang: Oh, skills.","offset":903,"duration":1},{"text":"Host: They do have scales, theoretically, yeah.","offset":904,"duration":1},{"text":"Jensen Huang: Skills. So the first thing, first thing it, you know, it has resources, it manages resources. It's, it does scheduling, right? And cron jobs, it could, it could spawn off agents, it could, it could decompose a task and, and cause, and solve problems, so it does scheduling. It has IO subsystems, it could, you know, input, it has output, it could connect to WhatsApp. And also it has a, an API that allows it to run multiple types of applications called skills. These four elements fundamentally define a computer. And therefore, what do we have? We have a personal artificial intelligence computer for the very first time. Open source, it runs literally everywhere. And so this is now the, this is basically the blueprint, the operating system of modern computing. And it's going to run literally everywhere. Now, of course, one of the things that we had to help it do is whenever you have agentic software, you have to make sure that an agentic software has access to sensitive information, it executes code, it could communicate externally. We have to make sure that all of it has to be governed, all of it has to be secure, and that we have policies that, that gives these agents two of the three things, but not all three things at the same time. And so the governance part of it we contributed to Peter—Peter Steinberger was here—and so we've got a mound of great engineers working with him to help secure and keep that thing so that it could protect our privacy, protect our security.","offset":905,"duration":93},{"text":"Host: Jensen, that paradigm shift makes some of the AI legislation that has passed around the country to regulate AI and a lot of the proposed legislation effectively moot, doesn't it? Can you just comment for a second on how quickly the paradigm shift kind of obviates a lot of the models for regulatory oversight of AI, which is becoming a very hot topic in politics right now?","offset":998,"duration":22},{"text":"Jensen Huang: Well, this is—this is the part that that, you know, just with policymakers, we need to, we need to always get in front of them, and Brad, you do a great job doing this. We had to get in front of them and inform them about the state of the technology, what it is, what it is not. It is not a biological being, it is not alien, it is not conscious, it is computer software. And it is not something that we say things like we don't understand it at all. It is not true, we don't understand it at all. We understand a lot of things about this technology. And so, so I think one, we have to make sure that we continue to inform the policymakers and not affect, not allow doomerism and extremism to affect how policymakers think and understand about this technology. However, we still have to recognize this technology's moving really fast, and don't get policy ahead of the technology too quickly. And the risk that we, we run as a nation, our greatest source of national security concern with respect to AI, is that other countries adopt this technology while we are so angry at it or afraid of it or somehow paranoid over it that our industries, our society don't take advantage of AI. And so I'm just mostly worried about the diffusion of AI here in United States.","offset":1020,"duration":84},{"text":"Host: Can you just double click, if you were in the seat in the boardroom of Anthropic over that whole scuttlebutt with the Department of War? It sort of builds on this idea of people didn't know what to think. It's sort of added to this layer of either resentment or fear or just general mistrust that people have sometimes at the software levels of AI. What would, do you think you would have told Dario and that team to do maybe differently to try to change some of this outcome and some of this perception?","offset":1104,"duration":27},{"text":"Jensen Huang: The first thing that I would, I would say about Anthropic is first of all, the technology is incredible. We are a large consumer of Anthropic technology. Really admire their focus on security, really admire their focus on safety. Um, the, the, the culture by which we're, they went about it, the technology excellence by which they went about it, really fantastic. Um, I would say that that the desire to warn people about the capability of the technology is also really terrific. We just have to make sure that we understand that the world has a spectrum and that that warning is good, scaring is less good. And because this technology is too important to us. And and I think that it is fine to predict the future, but we need to be a little bit more circumspect. We need to have a little bit more humility that in fact we can't completely predict the future, and the abil—and to say things that that are quite extreme, quite catastrophic, that there's no evidence of it happening, um, could be more damaging than people think. And of course we are technology leaders. Um, there were a time where nobody listened to us, um, but now because technology is so important in the social fabric, such an important industry, so important to national security, our words do matter. And I think we have to be much more circumspect, we have to be more moderate, we have to be more balanced, we have to be more thought—more thoughtful.","offset":1131,"duration":94},{"text":"Host: Well, I, you know, I would nominate you. I think the industry's got to get together. 17% popularity of AI in the United States. I mean, we see what happened in nuclear, right? We basically shut down the entire nuclear industry and now we have 100 fission reactors being built in China and zero in the United States. Um, we hear about moratoriums on data centers, so I think we have to be a lot more proactive about that. But but I wanted to go back to this agentic explosion that you're seeing inside your company. The efficiencies, the productivity gains inside your company. There's a lot of debate whether or not we're seeing ROI, right? And you and I, entering into this year, the big question was, are the revenues going to show up? Are the revenues going to scale like intelligence? And then we had this kind of Oppenheimer moment of five, six billion dollar month by Anthropic in February. Um, do you think as you look ahead, you announced a trillion dollar, you know, visibility into a trillion dollars of just Blackwell and Vera Rubin over the course of the next couple years. When you see this happening at Anthropic and OpenAI, do you think we're on that curve now where we're going to see revenues scale in the way that intelligence is scaling?","offset":1225,"duration":67},{"text":"Jensen Huang: When you look around, when you'll—I'll answer this in a couple of different ways. When you look around this audience, you will see that Anthropic and OpenAI is represented here, but in fact, everyb—99% of everything that is here is all AI and it's not Anthropic and OpenAI. And the reason for that is because AI is very diverse. I would say that the second most popular model as a category is open models. Open source. OpenAI's number one, open source is number two, very distant third is Anthropic. And that tells you something about the scale of all of the AI companies that are here. And so, so it's important to recognize, recognize that. Um, let me—let me come back and say a couple of things. One, when we went from generative to reasoning, the amount of computation we needed was about a hundred times. When we went from reasoning to agentic, the computation is probably another hundred times. Now we're looking at in just two years, computation went up by a fac—10,000X. Meanwhile, people pay for information, but people mostly pay for work. Talking to a chatbot and getting an answer is super great. Helping me do some research, unbelievable. But getting work done, I'll pay for. And so that's where we are. Agentic systems get work done. They're helping our software engineers get work done, and and so then you take that—you got 10,000X more compute, you get probably at this point a 100X more consumption now, and we haven't even started scaling yet. We are absolutely at a million X.","offset":1292,"duration":109},{"text":"Host: Which is I think a great place to talk about the number of engineers you have, 20, 30,000 at the company?","offset":1401,"duration":4},{"text":"Jensen Huang: We have 43,000 employees. You know, I would say 38,000 are engineers.","offset":1405,"duration":7},{"text":"Host: The conversation we've had on the pod a number of times is, oh my God, look at the token usage in our companies. It is growing massively. And some people are asking, hey, when I join a company, how many tokens do I get? Because I want to be an effective employee. And you've postulated, I believe during your two and a half hour keynote—pretty long keynote, well done.","offset":1412,"duration":23},{"text":"Jensen Huang: If it was, if it was well done, it would be shorter. I just wanted to let—I didn't have time to write a shorter one. So you guys, so you guys know, there is no practice. And so it's a grip it and rip it.","offset":1435,"duration":13},{"text":"Host: Love it.","offset":1448,"duration":1},{"text":"Jensen Huang: Yeah, yeah. And so, so I just want to let you know I was writing the speech while I was giving the speech. Okay? So never know.","offset":1449,"duration":7},{"text":"Host: But does that mean if we do back of the envelope math, 75,000 in tokens for each engineer or something like that? So are you spending in Nvidia a billion, two billion dollars on tokens for in your engineering team right now?","offset":1456,"duration":12},{"text":"Jensen Huang: We're trying to. Let me give you the thought experiment. Let's say you have a software engineer or AI researcher and you pay them $500,000 a year. We do that all the time. Okay? This is happening all the time. Um, that $500,000 engineer at the end of the year, I'm going to ask him how many to—how much did you spend in tokens? And that person said $5,000. I will go ape something else. Yes. If that—if that $500,000 engineer did not consume at least $250,000 worth of tokens, I am going to be deeply alarmed. Okay? And this is no different than one of our chip designers who says, guess what? I'm just going to use paper and pencil, I don't think I'm going to need any CAD tool.","offset":1468,"duration":43},{"text":"Host: Right.","offset":1511,"duration":1},{"text":"Jensen Huang: Okay. This is a real paradigm shift to start thinking about these all-star employees—it almost reminds me of of what we learned in the NBA where LeBron James starts spending a million dollars a year just on his health of his body, like and maintaining it. Here he is at age 41 still playing. It really is, hey, if these are incredible knowledge workers, why wouldn't we give them superhuman abilities?","offset":1512,"duration":20},{"text":"Host: And where does that go if we, if we extrapolate out two or three years from now? What is the efficiency of that all-star at an Nvidia and what they're able to accomplish? What do they look like?","offset":1532,"duration":10},{"text":"Jensen Huang: Well, first of all, things that that, \"wow, this is too hard,\" that thought is gone. \"Uh, this is going to take a long time,\" that thought is gone. \"Um, we're going to need a lot of people,\" that thought is gone. This is no different than in this—in the last industrial revolution somebody goes, \"boy, that building really looks heavy.\" Nobody says that. No—wow, \"that mountain looks too big.\" Nobody says that. Everything that's too big, too heavy, takes too long, those thought—those ideas are all gone.","offset":1542,"duration":32},{"text":"Host: You're reduced to creativity.","offset":1574,"duration":1},{"text":"Jensen Huang: That's right. Exactly. Which means now the question is how do you—how do you work with these agents? Well, it's just a new way of doing computer programming. In the—in the past we code, in the future we're going to—we're going to write ideas, architectures, specifications, we're going to organize teams, we're going to give them—we're going to help them define how to evaluate the definition of good versus bad. What's the—what does it look like when something is a great outcome, how to iterate with you, how to brainstorm. That's really what you're looking for. And I'm—I think that every engineer's going to have hundreds, a hundred agents.","offset":1575,"duration":35},{"text":"Host: Back to the PR problem the industry has right now. You have executives like David Friedberg with Ohalo who's looking at literally taking through the use of technology, your technology and AI, the number of calories produced and making high-quality calories—what is the factor you think you can bring the cost down, Friedberg, and what impact does this vision have for what you're doing?","offset":1610,"duration":26},{"text":"Friedberg: Yeah, zero—zero shot genomic modeling. And it works. And then you have that moment and you're like, holy shit. Honestly, like, and and that's after people are replacing entire enterprise software stacks in a night. I did something in 90 minutes I was telling the guys about, replaced a whole software stack and like a whole bunch of workload 90 minutes on Claude, ran this agentic system, built the whole thing, deployed it, and we got—we were on—","offset":1636,"duration":24},{"text":"Host: On a Sunday night.","offset":1660,"duration":1},{"text":"Host: 10 p.m., I was done at 11:30, I went to bed.","offset":1661,"duration":2},{"text":"Host: As the CEO, you replaced—","offset":1663,"duration":2},{"text":"Friedberg: Yeah. And everyone on my management team had to do a similar exercise over the weekend. What we saw on Monday, I was like, it's over. But, the technical stuff, the science stuff, we did something in 30 minutes using AutoResearch, and I'd love your view on AutoResearch and what that tells us about how far we still have to go in terms of efficiency. But using AutoResearch and a chunk of data, something was published internally that we said, \"Oh my God!\" and that would normally be a PhD thesis that would take seven years. It would be one of the most celebrated PhD theses we've ever seen in the field, and it was done in 30 minutes on a desktop computer running on AutoResearch with all the data we just ingested. We got it on Friday, and we're like, hey, let's try it. Tried, booted up, go into GitHub, downloaded AutoResearch and ran it. And you see everyone's face just go like—and then the potential of what this is unlocking for us is like the kind of thing that would take seven years and it happened in 30 minutes. And we're experiencing it in genomics, and we're like, this is unbelievable. So I think like the acceleration is widening the aperture for everyone in a way that like you didn't imagine a few years ago. But just going back to the AutoResearch point, can you just comment on what you think about the fact that this thing got published with 600 lines of code and a weekend and the capacity that it has to run locally and achieve what it can achieve with all these diverse data sets and what that tells us about the early stages we are in terms of optimization on algorithms and hardware to unlock—","offset":1665,"duration":86},{"text":"Jensen Huang: The fundamental reason why Open Claude is so incredible, number one, is it's—it's confluence, its timing with the breakthroughs in large language model. Its timing was perfect, it was impeccable. Now, in a lot of ways, Peter wouldn't have come up with it, probably, if not for the fact that Claude and GPT and ChatGPT have reached a level that is really very good. It is also a new capability that allows these models to tool use. The tools that we've created over time—web browsers and Excel spreadsheets and, you know, in the case of chip design, Synopsis and Cadence, Omniverse and Blender and Autodesk—all of these tools are going to continue to be used. There's some—some people say that the enterprise IT software industry's going to get destroyed. There's—it's—there's—let me give you the alternative view. The enterprise software industry is limited by butts in seats. It's about to get a hundred times more agents banging on those tools. There are going to be agents banging on SQL, they're going to be agents banging on vector databases, agents banging on Blender, agents banging on Photoshop. And the reason for that is because those tools are—first of all, do a very good job. Second, those tools are the conduit between us. In the final analysis when the work is done, it has to be represented back to me in a way that I can control. And I know how to control those tools. And so I need everything to be put back into Synopsis, I want everything to be put back into Cadence, because that's how I control it, that's how I ground truth.","offset":1751,"duration":98},{"text":"Host: Let me ask you a question about open source. So, we have these closed source models, they're excellent. We have these open weight models—many of the Chinese models are incredible, absolutely incredible. Two days ago, you may not have seen this because you were busy on stage, but there was a training run that happened in this crypto project called BitTensor Subnet 3. They managed to train a 4 billion parameter Llama model totally distributed with a bunch of people contributing excess compute, but they were able to do it statefully and manage a training run, which I thought was like a pretty crazy technical accomplishment.","offset":1849,"duration":37},{"text":"Jensen Huang: Our—our modern version of Folding@home.","offset":1886,"duration":-1678},{"text":"Host: Exactly. So what—what do you think about the end state of open source? Do you see this decentralization of architecture as well and decentralization of compute to support open weights and a totally open source approach to making sure AI is broadly available to everyone?","offset":208,"duration":1699},{"text":"Jensen Huang: I believe we fundamentally need models as a first-class product, proprietary product, as well as models as open source. These two things are not A or B, it's A and B. There's no question about it. And the reason for that is because model's a technology, not a product. Model's a technology, not a service. For the vast majority of consumers, the horizontal layer, the general intelligence, I would really, really, really love not to go fine-tune my own. I would really love to keep using ChatGPT, I love to use Claude, I love to use Gemini, I love to use X, and they all have their own personalities as you know, which kind of depends on my mood and depends on what problem I'm trying to solve. You know, am I, you know, do it on X or am I do it on ChatGPT. And so that—that segment of the industry is thriving, it's going to be great. However, there—all these industries, their domain expertise, their specialization, has to be channeled, has to be captured in a way that they can control. And that can only come from open models. The open model industry, we're contributing tremendously to, it is near the frontier. And quite frankly, even if it reaches the frontier, I think that products-as-a-service, world-class products-as-a-product, models-as-a-product, is going to continue to thrive.","offset":1907,"duration":85},{"text":"Host: Every startup we're investing in now is open source first and then going to the proprietary model.","offset":1992,"duration":6},{"text":"Jensen Huang: Yeah, and the beautiful thing is because you have a great router, you connect to it. By—on first day every single day you're going to have access to the world's best model, and then it gives you time to cost-reduce and fine-tune and specialize. So you're going to have world-class capabilities out the shoot every single time.","offset":1998,"duration":20},{"text":"Host: Jensen, can I ask—","offset":2018,"duration":1},{"text":"Jensen Huang: Of course.","offset":2019,"duration":1},{"text":"Host: Nobody wants the US to win the global AI race more than you, right? But only a year ago, the Biden era diffusion rule really was anti-American diffusion of AI around the world. So here we are a year into the new administration, give us a grade. Where—where are we in terms of global diffusion and the rate at which we're spreading US AI technology around the world? Are we an A, are we a B, are we a C? What's working, what's not working?","offset":2020,"duration":29},{"text":"Jensen Huang: Well, first of all, President Trump wants American industry to lead. He wants American technology industry to lead, he wants American technology industry to win, he wants us to spread American technology around the world, he wants United States to be the wealthiest country in the world. He wants all of that. At the current moment, as we speak, Nvidia gave up a 95% market share in the second largest market in the world and we're at 0%.","offset":2049,"duration":30},{"text":"Host: I know.","offset":2079,"duration":1},{"text":"Jensen Huang: President Trump—that's right. President Trump wants us to get back in there. And the first thing is to get license—license for the companies that we're going to be able to sell to. We've got many companies who have requested for license, we've applied for licenses for them, and we've got approved licenses from Secretary Lutnick. Now we've, we've informed the Chinese companies and many of them have given us purchase orders. And so we're going to start—we're going to—we're in the process of cranking up our supply chain again to go ship.","offset":2080,"duration":32},{"text":"Jensen Huang: I think at the highest level, Brad, I think one of the things that we should acknowledge is this. Our national security is diminished when we don't have access to miniature motors, rare earth minerals. It's diminished when we don't control our telecommunications networks. It's diminished when we can't provide for sustainable energy for our country. It is fundamentally diminished. Every single one of these industries is an example of what I don't want the AI industry to be. When we look forward in time and we say what do we want—what is the—what does it look like when American technology industry, American AI industry leads the world, we can all acknowledge that there is no way that AI models is one universally. It is—we can all acknowledge that that is an outcome that makes no sense. However, we can all imagine that the American tech stack, from chips to computing systems to the platforms, are used broadly by the world where they build their own AI, they use public AI, they use private AI, whatever, and they can build their applications in their society. I would love that the American tech stack is 90% of the world. I would love that. The alternative, if it looks like solar, rare earth, magnets, motors, telecommunications—I consider that a very bad outcome for national security.","offset":2112,"duration":94},{"text":"Host: How much are you monitoring the situation with the conflicts around the world right now and how much does it worry you, Jensen? So, China and Taiwan, and then helium availability coming out of the Middle East, I understand can be a supply chain risk to semiconductor manufacturing. How much do these situations worry you? How much are you spending on them?","offset":2206,"duration":20},{"text":"Jensen Huang: Well, first of all, in the Middle East, I have—we have 6,000 families there. We have a lot of Iranians at Nvidia and their families are still in Iran. And so—so we have—we have a lot of families there. The first thing that is their—they're quite anxious, they're quite concerned, quite scared. Um, we're thinking about them all the time, we're monitoring and keeping an eye on them all the time. They have 100% of our support. I've been asked several times are we still considering being in Israel. We are 100% in Israel. We are 100% behind the families there. We are 100% in the Middle East. I was also asked, you know, given what's happening in the Middle East, is that an area where we believe that we can expand artificial intelligence to. I believe that there's a reason we went to war and I believe that at the end of the war, Middle East will be more stable than before. And so if we were there before, if we were considering it before, we should absolutely be considering it after. And so I'm 100% in on that.","offset":2226,"duration":57},{"text":"Jensen Huang: With respect to Taiwan, we have to do three things. One, we have to make sure that we re-industrialize the United States as fast as we can. And whether it's the chip manufacturing plants, the computer manufacturing plants, or the AI factory—","offset":2283,"duration":16},{"text":"Host: How are we doing on that?","offset":2299,"duration":1},{"text":"Jensen Huang: We're doing excellent. With—by—by gaining the strategic support, by gaining the friendship of the supply chain of Taiwan—by gaining their friendship, by gaining their support—we were able to build Arizona and Texas, California at incredible rates. They are genuinely a strategic partner. Um, we—we—they deserve our support, they deserve our friendship, they deserve our generosity, and they're doing everything they can to accelerate the manufacturing process for us. And so I think that's number one. Number two, we ought to diversify the manufacturing supply chain and whether it's South Korea, whether it's—it's Japan, it's Europe, we ought to diversify the supply chain, make it more resilient. And number three, let's be—let's demonstrate restraint. And while we're reducing—increasing our diversity and resilience, let's not press, push, unnecessarily.","offset":2300,"duration":69},{"text":"Host: We need to be patient and thoughtful. Is helium a problem? A lot of reports on helium—","offset":2369,"duration":5},{"text":"Jensen Huang: You know, I think helium could be a problem but it's also the case that the supply chain probably has a lot of buffer in it. These kind of things tend to have a lot of buffer. Uh, but, but, you know.","offset":2374,"duration":11},{"text":"Host: You've made massive progress in self-driving. You made a big announcement. You've added many more partners including BYD. There was just a video of you driving around in a Mercedes. And huge announcement with Uber that you're going to have a number of cars on the road from many different manufacturers. Your bet is I believe that there's going to be an Android type open-source platform that you're going to play a major part in with dozens of car providers and then maybe on the other side there could be an iOS with Tesla or Waymo. What's your strategy thinking there and how that chess board emerges? Because it feels like you have a pretty deep stack and in some ways you're competing and in other places you're collaborative.","offset":2385,"duration":49},{"text":"Jensen Huang: Yeah. Um, it's—taking a step back, we believe that everything that moves will be autonomous completely or partly someday. Number one. Number two, we don't want to build self-driving cars, but we want to enable every car company in the world to build self-driving cars. And so we build all three computers: the training computer, the simulation computer—the valuation—evaluation computer, as well as the car computer. We developed the world's safest driving operating system. We also created the world's first reasoning autonomous vehicle so that it could decompose complicated scenarios into simpler scenarios that it knows how to navigate through, just like us, reasoning system. And so that reasoning system called Alpamayo has enabled us to achieve incredible results. We opened this platform—we vertical optimization, we horizontally innovate, and we let everybody decide. Do you want to buy one computer from us? In the case of Elon and Tesla, they buy our training computers. Um, do they want to buy our training computer and our simulation computers or do you want to let us work with us to do all three and even put the car computer in your car. And so we, you know, our attitude is we want to solve the problem, we're not the solution provider, and we're delighted however you work with us.","offset":2434,"duration":85},{"text":"Host: Let me build on this question because I think it's so—it's so fascinating. You actually do create this platform, a thousand flowers are blooming. But it's also true that some of those flowers want to now go back down in the stack and try to compete with you a little bit. Google has TPU, Amazon has Inferentia and Trainium. You know, everybody's sort of spinning up their own version of \"I think I can out-Nvidia Nvidia,\" even though they also tend to be huge customers. How do you navigate that? And what do you think happens over time and where do those things play in the complexion of this kind of vision?","offset":2519,"duration":32},{"text":"Jensen Huang: Yeah, really great. You know, first of all, um, we're the only AI company—we're an AI company. We build foundation models, we're at the frontier in many different domains. We build every single—every single layer, every single stack. Um, we're the only AI company in the world that works with every AI company in the world. They never show me what they're building and I always show them exactly what I'm building. Right. Yeah. And so—so the confidence comes from this: One, we are delighted to compete on what is the best technology and to the extent that to the extent that we can continue to run fast, I believe that buying from Nvidia still is one of the most economic things they could do. And I should say incredible confidence there. Number one. Number two, we're the only architecture that could be in every cloud. And that gives us some fundamental advantage. We're the only architecture you could take from a cloud and put into on-prem, in the car, in any region—","offset":2551,"duration":55},{"text":"Host: In space.","offset":2606,"duration":1},{"text":"Jensen Huang: That's right, in space. And so there's a whole—whole part of our market, about 40% of our market, most people don't realize this, 40% of our business, unless you have the CUDA stack, unless you can build the entire AI factory, you have the customers don't know what to do with you. They're not trying to build chips, they're not trying to buy chips, they're trying to build AI infrastructure. And so they want you to come in with the full stack and we've got the whole stack. And so surprisingly, Nvidia's gaining market share. If you look at where we are today, we're gaining share.","offset":2607,"duration":30},{"text":"Host: Do you think what happens is these guys try and they realize \"oh my God, it's too much,\" and then they come back—is that why the share grows?","offset":2637,"duration":6},{"text":"Jensen Huang: Well, we're gaining share for several reasons. One, our velocity has gone—we help people realize it's not about building the chip, it's about building the system. And that system's really hard to build. Uh, and and so their—their business with us is increasing. In the case of AWS, I think they just announced, I think it was yesterday, that they're going to buy a—a million chips uh in the next couple of years. I mean, that's a lot of chips from—from AWS, and that's on top of all the chips they've already bought. And so we're delighted to do that. But number one, we're gaining share this last couple of years because we now have Anthropic coming to Nvidia, Meta SL is coming to Nvidia, and the growth of open models is incredible and that's all on Nvidia. And so we're growing in share because of the number of models. We're also growing in share because outside all of these companies are outside of the cloud, and they're growing regionally, in enterprise, in industries, at the edge. And that entire segment of growth is, you know, really hard to do if it's just building an ASIC.","offset":2643,"duration":67},{"text":"Host: Brad, related to that, and not to get in the weeds on the numbers, but analysts don't seem to believe, right? So if you look at the consensus forecast, you said compute could one million X, right? And yet they have you growing next year at 30%, the year after that at 20%, and in 2029, which is supposed to be a monster year, at 7%. Right? So if you just—if you take your TAM and you apply their growth numbers, it suggests that your share will plummet. Do you see anything in your future order book that would make that correct?","offset":2710,"duration":34},{"text":"Jensen Huang: Yeah, first of all, they just don't understand the scale and the breadth of AI. Yes. I think that's true. I think that's true. Most people think that AI is in the top five hyperscalers. Right. That's right. There's also an orthodoxy around these law of large numbers where, you know, they have to go back to their investment banking risk committee and show some model. They're not going to believe in their minds that 5 trillion goes to 15 trillion. They're like it can go it can go to 7. Or they can have a $10 trillion company. It's all just CYA stuff that I think—it's never happened before, so you can't say it will. And—and because because you have to redefine what it is that you do. There was somebody who made an observation recently that Nvidia—Jensen, how can you be larger than Intel in servers? And the reason for that is because the CPU market of the entire data center was about $25 billion a year. We do $25 billion a year, as you guys know, in a very—in the time that we were sitting here. And so obviously, obviously—that was a joke. All in podcast humor. No, it's roughly true. Don't worry, everything on the show is roughly true, don't worry about it. It's all—God damn. No, no, no, that was not guidance. But anyhow, anyhow, the point is how big you can be depends on what it is that you make. Nvidia's not making chips. Number one, making chips does not help you solve the AI infrastructure problem anymore. It's too complicated. Number three, most people think that AI is narrowly in the things that they talk about and hear and see. AI's much—OpenAI's incredible, they're going to be enormous. Anthropic is incredible, they're going to be enormous. But AI is going to be much, much bigger than that. And we address that segment.","offset":2744,"duration":108},{"text":"Host: Tell us about—tell us about data centers in space for a second.","offset":2852,"duration":3},{"text":"Jensen Huang: We are already in space.","offset":2855,"duration":1},{"text":"Host: How should the layman think about what that business is versus when you hear about these big data center build-outs that's happening in—on the ground?","offset":2856,"duration":10},{"text":"Jensen Huang: Well, we should definitely work on the ground first because we're already here. And number one. Number two, we should prepare to be out in space, and obviously there's a lot of energy in space. Um, the challenge of course is that cooling, you can't take advantage of conduction and convection. Exactly. And so you can only use radiation. And radiation requires very large surfaces. And so—now that's not an impossible thing to solve and there's lot—lot of space in space. Um, but nonetheless, the expense is still quite there, is—is there. Um, we're going to go explore it. We're already there, we're already radiation hardened. Um, we have—we have—CUDA in satellites around the world. Um, they're doing imaging, image processing, AI imaging. And—and that kind of stuff ought to be done in space instead of sending all the data back here and do imaging down here. We ought to just do imaging out in space. And so there's a lot of things that we ought to do in space. In the meantime, we're going to explore what is the architecture of data centers look like in space. And it'll take—it'll take years. It's okay. We got—I got plenty of time.","offset":2866,"duration":65},{"text":"Host: I wanted to double click on healthcare. I know you've got a big effort there. We're all of a certain age where we're thinking about lifespan, healthspan. I mean, we all look great, I think.","offset":2931,"duration":8},{"text":"Jensen Huang: Some better than others.","offset":2939,"duration":2},{"text":"Host: Some better than others. I don't know what your secret is, Jensen. You look pretty good, these—the Asians—","offset":2941,"duration":4},{"text":"Jensen Huang: Squats and push-ups and sit-ups.","offset":2945,"duration":2},{"text":"Host: Perfect. Okay. Yeah. Um, but what you know in terms of the build-out in healthcare, where is that going and what kind of progress are we making? I was just using Claude to do some analysis and saying like, where are all these billing codes we spend twice as much money in the US, we get—seem to get half as much. It seemed like 15 to 25 percent of the dollar spent were on these first GP visits. And I think we all know like ChatGPT and a large language model does a better job, more consistently today at a first visit. So what has to happen there to kind of break through all that regulation and have AI have a true impact on the healthcare system?","offset":2947,"duration":48},{"text":"Jensen Huang: There's several areas we're involved in—in—in healthcare. One is AI physics. Uh, and and that's or AI biology. Using AI to understand, represent, predict biology, behavior, biological behavior. And so that's one, that's very important in drug discovery. There's second, which is AI agents, and that's where the assistants and helping diagnosis and things like that. Open Evidence is a really good example, Hippocratic's a really good example, love working with those companies. Um, I really think that this is an area where agentic technology is going to revolutionize how we interact with doctors and how do we interact for healthcare. The third part that we're in—involved in is physical AI. The first one's AI physics using AI to predict physics. The second one is physical AI, AI that understand the properties of the laws of physics. And that's used for agent—robotics surgery. Huge amounts of activities there. Every single instrument, whether it's ultrasound or, you know, CT or whatever instrument we interact with in a hospital in the future will be agentic. You know, Open Claude in a safe version will be inside every single instrument, and so in a lot of ways that instrument's going to be interacting with patients and nurses and doctors in a very unique way.","offset":2995,"duration":78},{"text":"Host: Yeah, I mean we've seen so much investment in AI weapons. It would be wonderful to see some investment in AI EMTs and paramedics and saving lives, not just taking them. Uh, which I think is a great segue into robotics. You've got dozens of partners. We had this very weird, I don't know what to call it, lost decade or 20 years of Boston Dynamics, Google bought a bunch of companies, they then wound up selling them and spinning them out, where people just thought \"Ah, robotics is just not ready for prime time.\" And now here we have the world's greatest entrepreneur at this time, um, tied with you, um, Elon Musk doing—oh that was a good save I hope—Optimus, uh, pretty impressive. And then other companies in China. How close is that to actually being in our lives where we might see a chef, a robotic chef, a robotic nurse, a robotic housekeeper, you know these humanoid factors actually working in the real world knowing what you know with those partners and the fidelity especially in China where they seem to be doing as good a job as we're doing here or maybe better?","offset":3073,"duration":65},{"text":"Jensen Huang: We invented the industry largely. American invented—we—you could argue we got into it too soon. Yeah. And we got exhausted, we got tired, um, about five years before the enabling technology appeared. Yes, the brain. Yeah, yeah. And we just got tired of it just a little too soon. Okay, that's number one. But it's here now. Now, the question is how much longer? From the point of high functioning existence proof—high functioning existence proof to reasonable products technology never takes more than a couple, two-three cycles. And so a couple, two-three cycles is basically be somewhere around three years to five years. That's it. Three years to five years, we're going to have robots all over the place. Uh, I think—I think—China is is a—formidable, and the reason for that is because their microelectronics, their motors, their rare earth, their magnets, which is foundational to robotics, they are the world's best. And so in a lot of ways, our robotics industry relies deeply on their ecosystem and their supply chain, um, and and and they're, you know, obviously moving very quickly. Uh, we're going to, you know, our robotics industry will have to rely a lot on it, the world's robotics industry will have to rely on a lot on it. And so—so I think—you're going to see some fast—fast movements here.","offset":3138,"duration":84},{"text":"Host: Ultimately, one for one, Elon seems to think we're going to have one robot for every human. 7 billion for 7 billion, 8 billion for 8 billion.","offset":3222,"duration":7},{"text":"Jensen Huang: Well, I'm hoping more. Yeah. I'm hoping more. Yeah. Um, well first of all, there's a whole bunch of robots that are going to be in factories working around the clock. There's going to be a whole bunch of factories—robots that that don't move, they move a little bit. Uh, almost everything will be robotic.","offset":3229,"duration":15},{"text":"Host: What does the—","offset":3244,"duration":1},{"text":"Host: Sorry, let me just—I think like, this is one of the—robotics for me is one of the pieces that I think unlocks uh economic mobility opportunities for every individual. Everyone now—like when everyone got a car they could now go and do a lot of different jobs. When everyone gets a robot, their robot can do a lot of work for them. They can stand up an Etsy store or a Shopify store, they can create anything they want with their robot. They could do things that they independently cannot do. I think the robot is going to end up being the greatest unlock for prosperity for more people on Earth than we've ever seen with any technology before.","offset":3245,"duration":33},{"text":"Jensen Huang: Yeah, no doubt. I mean, just a simple—the simple math at the moment is we're millions of people short in labor today. Right. Yeah. Right. We're—we're actually really desperate in need of robotics so that all of these companies could grow more if they had more labor. I mean, we're—number one. Uh, some of the things that you mentioned are super fun. I mean, because of robots, we'll have virtual presence. Uh, you know, I'll be able to go into the robot at my house and virtually operate it. I'm on a business trip. Right. Tele-operate. Walk the dog. Great. Yeah, walk the dog, rake the leaves. Yeah, exactly. Freak out the dog. Maybe not quite that, but just, you know, wander around and just see what's going on in the house, you know, chat with the dogs, chat with the kids, yeah. Yeah.","offset":3278,"duration":47},{"text":"Jensen Huang: Time travel is also we're going to be able to travel at the speed of light, you know. And so—you know, clearly, we're going to send our robots ahead of us. Yeah. Not going to send myself, I'm going to send a robot. You know, check it out. Yeah, yeah. And then I'm going to upload my AI.","offset":3325,"duration":14},{"text":"Host: Well, it's inevitable. It unlocks the moon and it unlocks Mars as, um, targets for colonization, which gives us infinite resources. Getting back from the moon is effectively zero energy cost to move material back because you can use solar and accelerate. So you could have factories that make everything the world needs on the moon and the robots are going to be the unlock for enabling that.","offset":3339,"duration":18},{"text":"Jensen Huang: That's right. Distance no longer matters. Distance doesn't matter. Yeah.","offset":3357,"duration":4},{"text":"Host: The more—the more revenue we get out of models and agents, the more we can invest in building the infrastructure which then unlocks more capabilities on models and agents. Dario on Dwarkesh's podcast recently said by 27-28 we'll have hundreds of billions of dollars of revenue out of the model companies and the agent companies and he forecast a trillion dollars by 2030, right? This is non-infrastructure AI revenue. Um—","offset":3361,"duration":27},{"text":"Jensen Huang: I think he's—I think he's—he's being very conservative. I believe Dario and Anthropic is going to do way better than that.","offset":3388,"duration":6},{"text":"Host: Wow.","offset":3394,"duration":1},{"text":"Jensen Huang: Yeah. Um, from 30 billion to a trillion. Yeah. And not—and—and the reason for that is the one part that he hasn't considered is that I believe every single enterprise software company will also be a reseller, value-added reseller of Anthropic code, Anthropic's tokens. Value-added reseller of OpenAI. Value—that's right. Have to be. And they're going to—that—that—that part of their business is about to see logarithmic expansion.","offset":3395,"duration":26},{"text":"Host: Yes.","offset":3421,"duration":0},{"text":"Jensen Huang: Yeah. Their go-to-market is going to expand tremendously this year.","offset":3421,"duration":4},{"text":"Host: What do you think in that world is the moat? What's left over? Like, I mean, you have some moats that are frankly, I think, as this scales, almost insurmountable. The best one that nobody talks about is probably CUDA, which is just like an incredible strategic advantage. But in the future, if a model can be used to create something incredible, then the next spin of a model can be used to maybe disrupt it. Sort of in your mind, what do you think for these companies that are building at that application layer? What's their moat? Like, how do they differentiate themselves?","offset":3425,"duration":33},{"text":"Jensen Huang: Deep specialization. Deep specialization. I believe that um these models—they—they're going to have general—general models that are connected into the software company's agentic system. Right. Many of those models are cloud models and proprietary models, but many of those models are specialized sub-agents that they've trained on their own—","offset":3458,"duration":25},{"text":"Host: Right, so the call to arms for you for entrepreneurs is look, know your vertical, know it as deep and as better than everybody else, and then wait for these tools because they're catching up to you and now you can imbue it with your knowledge.","offset":3483,"duration":12},{"text":"Jensen Huang: That's right. And the sooner you connect your agent—the sooner you connect your agent with customers, that flywheel is going to cause your agent to get—","offset":3495,"duration":9},{"text":"Host: It very much is an inversion of what we do today because today we build a piece of software and we say what generalizes and then let's try to sell it as broadly as possible and then sell the customization around it.","offset":3504,"duration":10},{"text":"Jensen Huang: And we try to—and in fact—exactly right. We—we create a horizontal, but notice there are all these GSIs and all these consultants who are specialists who then take your horizontal platform and specializes it into—","offset":3514,"duration":16},{"text":"Host: Exactly. And that's arguably a five or six time bigger industry is the customization.","offset":3530,"duration":4},{"text":"Jensen Huang: It is absolutely. That's very much. That's right. So I think that these platform companies have an opportunity to become that specialist, to become that vertical. Right.","offset":3534,"duration":10},{"text":"Host: You know, I just want to give you your flowers. I think it was three years ago you said you're not going to lose your job to AI, you're going to lose your job to somebody using AI. And here we are, the entire conversation has revolved around this concept of agents making people superhuman and the business opportunity expanding and entrepreneurship expanding. You actually saw it pretty clearly.","offset":3544,"duration":20},{"text":"Jensen Huang: Have you changed your view? Because you—you were—you were—doomer—Doomer Dan.","offset":3564,"duration":-3234},{"text":"Host: No, I—I—I—","offset":330,"duration":3242},{"text":"Host: This is—this is Spiral J-Cal.","offset":3572,"duration":1},{"text":"Host: No, no. There is—you can hold space for I think two ideas. One is there are going to be a large—","offset":3573,"duration":3},{"text":"Host: That's by J-Cal by the way.","offset":3576,"duration":1},{"text":"Host: No, no. There is—you can—","offset":3577,"duration":1},{"text":"Jensen Huang: But that's just because he doesn't hang out with me enough.","offset":3578,"duration":3},{"text":"Host: Well, we've—I mean, we've hung a little.","offset":3581,"duration":2},{"text":"Host: Be careful, J-Cal.","offset":3583,"duration":1},{"text":"Host: We don't talk about it.","offset":3584,"duration":1},{"text":"Jensen Huang: He will show up at your breakfast table.","offset":3585,"duration":1},{"text":"Host: He will follow you around.","offset":3586,"duration":1},{"text":"Jensen Huang: He'll follow you around.","offset":3587,"duration":1},{"text":"Host: I mean, I'm not—I'm not asking for it.","offset":3588,"duration":1},{"text":"Host: You'll follow you around.","offset":3589,"duration":1},{"text":"Jensen Huang: I'm not asking for it. I'm just saying—","offset":3590,"duration":1},{"text":"Host: You can come with me and Tucker, we ski in Japan every January.","offset":3591,"duration":2},{"text":"Jensen Huang: Oh, I would love it. Me and Tucker, we'll go on a road trip. Wow.","offset":3593,"duration":3},{"text":"Host: Okay. No, there is going to be job displacement and then the question becomes, you know, do those people have the fortitude, the resolve to then go embrace these, you know, technologies. We're going to see 100% of driving go away by humans. That's just—it—that's a beautiful thing in the lives saved, but we have to recognize that's 15 million people in the United States, 10 to 15 million who are employed in that way. And—and so that is going to happen, yes?","offset":3596,"duration":26},{"text":"Jensen Huang: I—I think that jobs will change. For example, um, there are many chauffeurs today, uh, who drive the car. I believe that those—many of those chauffeurs will actually be in the car sitting behind the dri—the steering wheel while the car is driving by itself. And the reason for that is because remember what a chauffeur does. In the end, these chauffeurs, they're helping you, they're your assistant, they're helping you with your luggage, they're helping you—I mean, they're helping you with a lot of things. And—and so I wouldn't be surprised actually if the chauffeurs of the future becomes your mobility assistant and they are helping you do on a whole bunch of other stuff—","offset":3622,"duration":36},{"text":"Host: Check you into the hotel.","offset":3658,"duration":1},{"text":"Jensen Huang: —get the—and the car's driving by itself. Right. The autopilot in planes created a lot more pilots and didn't take any of the pilots out of the cockpit even though the autopilot is flying the plane 90% of the time.","offset":3659,"duration":12},{"text":"Jensen Huang: And by the way, while that car's driving itself, that chauffeur is going to be doing a bunch of other work on his phone and he's going to be making money doing other things. Arranging for example, doing—coordinating a bunch of things for you, getting, you know, yeah. It's—the pie just grows in a way that—yes, every job will be—will be transformed. Um, some jobs will be eliminated. However, we also know that many, many jobs will be recreated—will be created.","offset":3671,"duration":29},{"text":"Jensen Huang: The one thing that I will say to young people who are coming out of school who are concern—who are anxious about AI: be the expert of using AI. Yes. How much—look, we all want our employees to be expert at using AI, and it's not—not trivial. Not trivial. And so knowing how to specify, not to over-prescribe, leaving enough room for the AI to innovate and create while we guide it to the outcome we want, evalu—all of that requires artistry.","offset":3700,"duration":26},{"text":"Host: You had—you had this great advice to when you were at Stanford I think it was, which is I wish to you pain and suffering, do you remember that?","offset":3726,"duration":5},{"text":"Jensen Huang: Yeah.","offset":3731,"duration":1},{"text":"Host: Fantastic. What's your advice to young people around what they should be studying? So if they're sort of about to leave high school, because now those are the kids that are at this like really native—they haven't made a decision about college, what to study, if at all go to college. How do you guide those kids? What would you tell them?","offset":3732,"duration":19},{"text":"Jensen Huang: I—I still believe that deep science, deep math, um, uh language skills, you know, as you know, language is the programming language of AI now.","offset":3751,"duration":12},{"text":"Host: The ultimate programming language.","offset":3763,"duration":1},{"text":"Jensen Huang: And so as it turns out, it could be that the English major could be the most successful. Yeah. And—and so—so I think—I think—uh, I would just advise whatever—whatever education you get, just make sure that you're deeply, deeply expert in using AIs.","offset":3764,"duration":15},{"text":"Jensen Huang: One of the things that I wanted to say with respect to jobs and I want everybody to hear it, that in fact at the beginning of the deep learning revolution, one of the finest computer scientists in world, deeply—deeply I—deeply um deeply uh respect, uh predicted that computer vision will completely eliminate radiologists. And that the one—the one field he advises everybody to not go into is radiology. 10 years later, his prediction was at 100% right. Computer vision has been integrated into all of the radiology technologies and radiology platforms in the world 100%. The surprising outcome is the number of radiologists actually went up and the demand for radiologists is skyrocketed. The reason for that is because everybody's job has a purpose and its task. The task that you do is studying the scans, but your purpose is to diag—helping the doctors, healing the patient, diagnose disease. Right. And so what's surprising is because the scans are now being done so quickly, they could do more scans, improving healthcare. Yes. But doing more scans more quickly allows patients to be um onboarded a lot more quick—treated a lot more quickly, and as it turns out because hospitals enjoy making money too, yeah, right, they're doing more scans, they're treating more customers and more patients, early detection becomes perfect—perfect example, perfect example. The revenues go up and guess what? Need more—yeah.","offset":3779,"duration":95},{"text":"Jensen Huang: And at—and—at a country that grows faster, productivity increases, a wealthier country can put more teachers in the classroom, not less teachers in the classroom. That's right. You just give every one of those teachers a personalized curriculum for every student in the room. It makes them all bionic and leads to a lot more. Every single student will be assisted by AI, but every single student will still need great teachers.","offset":3874,"duration":23},{"text":"Host: Yeah. Amazing. Um, Jensen, congratulations on all your success and really this is an incredibly positive, uplifting discussion. We really appreciate you taking the time for us.","offset":3897,"duration":10},{"text":"Host: He is the steward we need.","offset":3907,"duration":1},{"text":"Host: You are—I think you need to be more vocal. No, I'm being very, very—be more vocal about the positive side of it. I think there's so much doomerism.","offset":3908,"duration":6},{"text":"Host: But I also think it takes the humility to have this level of success and be humble about \"we're making software, guys.\"","offset":3914,"duration":7},{"text":"Jensen Huang: Yeah.","offset":3921,"duration":1},{"text":"Host: And I think that that's actually really healthy for people to hear. We have done this before. We have invented categories and industries before. Yes. We don't need to go to this scaremongering place, it does nothing.","offset":3922,"duration":11},{"text":"Host: And we get to choose, right? We have autonomy and and agency. We get to pick how to deploy this.","offset":3933,"duration":6},{"text":"Jensen Huang: We sure do.","offset":3939,"duration":1},{"text":"Host: Okay everyone, we'll see you next time. Uh, on the All-In interview. Okay.","offset":3940,"duration":4},{"text":"Host: Well done, brother.","offset":3944,"duration":1},{"text":"Host: Thanks, man.","offset":3945,"duration":1},{"text":"Host: Good job.","offset":3946,"duration":1},{"text":"Host: Thank you, sir. That was awesome.","offset":3947,"duration":1},{"text":"Host: Appreciate you. You guys are awesome. Look at this—look at this big crowd behind you guys.","offset":3948,"duration":5},{"text":"Host: Man, I think they're here for you.","offset":3953,"duration":9},{"text":"Music: [Singing] I’m doing all in. I’m doing all in. I’m doing all in. [End of video]","offset":3962,"duration":15}],"logs":[{"elapsed":"0.0","message":"Downloading audio from YouTube...","detail":null},{"elapsed":"0.0","message":"Trying download with browser cookies (ad-free)...","detail":null},{"elapsed":"30.8","message":"Audio downloaded (36.3 MB) in 30.8s","detail":"File size: 36.3 MB"},{"elapsed":"30.8","message":"Video title: Jensen Huang: Nvidia's Future, Physical AI, Rise of the Agent, Inference Explosion, AI PR Crisis","detail":null},{"elapsed":"30.8","message":"Audio duration: 1:06:05 (66.1 min)","detail":null},{"elapsed":"30.8","message":"Uploading audio to Gemini File API...","detail":null},{"elapsed":"36.3","message":"Audio uploaded in 5.5s","detail":"File ref: files/pd3n0yciryg1"},{"elapsed":"36.3","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"133.7","message":"Transcription complete in 102.9s","detail":"68317 chars received"},{"elapsed":"133.7","message":"Transcription tokens: 99,384 in / 17,165 out — cost: $0.1012","detail":null},{"elapsed":"133.7","message":"Parsed 189 transcript segments","detail":null},{"elapsed":"133.7","message":"Transcript coverage: 1:06:02 of 1:06:05 (100%) — OK","detail":null},{"elapsed":"133.7","message":"Total transcription time: 102.9s — 189 segments","detail":null},{"elapsed":"133.7","message":"Analyzing topics across 189 segments with gemini-3.1-pro-preview...","detail":null},{"elapsed":"188.1","message":"Topic analysis complete in 54.4s — found 21 topics","detail":null},{"elapsed":"188.1","message":"Analysis tokens: 18,344 in / 1,737 out / 2,795 thinking — cost: $0.0911","detail":null},{"elapsed":"188.1","message":"Pipeline finished in 188.1s — total cost: $0.1923 (139,425 tokens)","detail":null}]} \ No newline at end of file diff --git a/history/1775223130960-kjQZexuV_AE.json b/history/1775223130960-kjQZexuV_AE.json new file mode 100644 index 0000000..1807cc0 --- /dev/null +++ b/history/1775223130960-kjQZexuV_AE.json @@ -0,0 +1 @@ +{"id":"1775223130960-kjQZexuV_AE","videoId":"kjQZexuV_AE","url":"https://www.youtube.com/watch?v=kjQZexuV_AE","title":"MacroVoices #524 Simon White: War + Inflation = More Inflation","type":"youtube","topicCount":29,"segmentCount":298,"createdAt":"2026-04-03T13:32:10.960Z","uploadDate":"20260319","chunks":[{"title":"Podcast Introduction and Market Scoreboard","summary":"The hosts introduce the podcast and review the week's sharp market selloffs across equities, gold, and copper, alongside crude oil's geopolitical risk premium.","entries":[{"text":"Host: This is MacroVoices, the free weekly financial podcast targeting professional finance, high net worth individuals, family offices, and other sophisticated investors. MacroVoices is all about the brightest minds in the world of finance and macroeconomics, telling it like it is. Bullish or bearish, no holds barred. Now here are your hosts, Erik Townsend and Patrick Ceresna.","offset":0,"duration":29},{"text":"Erik Townsend: MacroVoices episode 524 was produced on March 19, 2026. I'm Erik Townsend. It was a sea of red in markets on Wednesday as the Iran conflict has dragged on longer than most analysts expected, and the Fed's standing pat with no rate cut accelerated the selling.","offset":29,"duration":25},{"text":"Erik Townsend: The S&P, gold, copper, and just about everything else other than the dollar index and crude oil were down and down hard, closing on or near their lows of the day, and then selling off even more in futures trading after the 4:00 PM cash close. These are all ominous signs that more downside is likely in coming days, absent a major bullish news event.","offset":54,"duration":23},{"text":"Erik Townsend: So we've got plenty to talk about this week. Bloomberg macro strategist Simon White kicks it all off as this week's feature interview guest. Simon and I will discuss the prospects for secular inflation, and why the oil price surge might be the catalyst needed to bring it about. We'll also discuss the risk-off playbook, food price inflation, the breakdown in private credit, and much more.","offset":77,"duration":29},{"text":"Erik Townsend: We had a huge positive response to Dr. Anas Alhajji's cameo appearance updating us on the oil market disruption on last week's podcast. So this week, Commodity Context founder Rory Johnston will join us for another perspective on what the Iran conflict means to energy markets. That's coming up right after the feature interview with Simon White.","offset":106,"duration":25},{"text":"Erik Townsend: Then be sure to stay tuned for our postgame segment when Patrick's trade of the week will take a look at the inflation surge event that hasn't happened yet. Not the one in crude oil where the price already spiked, but the one in food prices, which as Simon White will explain in the feature interview, could come next. And oh by the way, Rory Johnston is going to reinforce that view in the upcoming oil market update.","offset":131,"duration":24},{"text":"Patrick Ceresna: And I'm Patrick Ceresna with the macro scoreboard week over week as of the close of Wednesday, March 18th, 2026. The S&P 500 index down 221 basis points, trading at 6625, markets now trading at multi-month lows. We'll take a closer look at that chart and the key technical levels to watch in the post-game segment.","offset":155,"duration":22},{"text":"Patrick Ceresna: The US dollar index up 97 basis points trading at 100 spot 21, attempting to bullishly breakout of a 10-month trade range. The April WTI crude oil contract up 941 basis points to 9546, the war premium remains as the uncertainty continues.","offset":177,"duration":22},{"text":"Patrick Ceresna: The May RBOB gasoline contract up 1204 basis points to 307, gasoline now trading at three-year highs. The April gold contract down 546 basis points trading at 4896, remains in consolidation after putting in the January highs.","offset":199,"duration":22},{"text":"Patrick Ceresna: The May copper contract down 509 basis points trading at 559, the March uranium contract down 111 basis points trading at 8475. The US 10-year Treasury yield up three basis points trading at 426, upticking at the end of the day in the post-FOMC window.","offset":221,"duration":21},{"text":"Patrick Ceresna: The key news to watch this week is the Friday OpEx, and next week we have the Euro and the US flash manufacturing and services PMIs. This week's feature interview guest is Bloomberg macro strategist Simon White. Erik and Simon discuss the risk of a renewed inflation cycle, why markets may be underpricing second-order effects of the Iran conflict, the parallels to the 1970s style stagflation, and how shifts in commodities, credit, and the yield curve could reshape the macro outlook.","offset":242,"duration":44},{"text":"Host: And now with this week's special guest, here's your host Erik Townsend.","offset":286,"duration":8}],"startTime":0},{"title":"Secular Inflation and the 1970s Analogy","summary":"Erik Townsend and Simon White discuss the return of secular inflation, comparing the current macro environment to the early stages of the 1970s inflation cycle.","entries":[{"text":"Erik Townsend: Joining me now is Bloomberg macro strategist Simon White. Simon prepared a slide deck to accompany this week's interview. Registered users will find the download link in your research roundup email. If you don't have a research roundup email, it means you haven't yet registered at macrovoices.com. Just go to our homepage macrovoices.com, look for the red button above Simon's picture that says \"Looking for the downloads\". Simon, it's great to get you back on the show. It's been too long. I want to dive right into your slide deck because there's so much to cover today. Let's start on page 2. You say inflation is a three-act play, that we really need to be thinking about a return to secular inflation, and a lot of people said there was no catalyst. Well, I think we got our catalyst, didn't we?","offset":294,"duration":49},{"text":"Simon White: Yeah, in spades. I think that's absolutely right, Erik. I think this is playing out in a way that's very analogous to the 70s, which is why I've referred to a three-act play there. And it certainly makes sense to start here. I think inflation is probably the most mispriced thing at the moment. I think it was mispriced before this war with Iran started and I think it's even more mispriced now.","offset":343,"duration":28},{"text":"Simon White: And it certainly seems that team transitory is back in force. If you look at the CPI fixing swaps, for instance, they show quite a sharp rise in inflation over the next few months expected, to maybe peaking out at 3 and a half percent, then very quickly it goes straight back down, and within 12 months, I think we're looking at roughly 2.8 percent in spot CPI, which is only about 40 basis points higher than it is now. So again, we're looking for quite a short-term shock, and it's even more egregious if you look at break evens.","offset":371,"duration":31},{"text":"Simon White: I mean, the shorter term break evens have moved a bit more, 2 to 5 year maybe moved 20 to 50 basis points since the war started, but the 10-year has barely budged, maybe 5 to 10 basis points. And I think the muscle memory is kicking back in that inflation will always go back to target. But I think that's you know, I think that's quite complacent. And that's why it's helpful to look at the 70s. You know, no analogy is perfect, but the 70s does have an uncanny amount of commonalities with today.","offset":402,"duration":29},{"text":"Simon White: And also the one thing that doesn't change is human nature. Human nature is immutable, and inflation is as much of a psychological thing as it is an actual you know, financial phenomenon or an economic phenomenon. So the chart on the left was something I first used in 2022, so almost 4 years ago, and it was uncanny because I updated it, and so the blue line shows the CPI level, not the growth, from the late 60s into the late 70s, early 80s, and the white line is today.","offset":431,"duration":30},{"text":"Simon White: And so I updated it, and we're kind of bang on today at the end of act 2. So the way I thought about it is act 1 was kind of when inflation first hits new highs. So this time around that was the pandemic. First time round in the 70s, it was on the back of we had a lot of fiscal easing because of the Vietnam War.","offset":461,"duration":20},{"text":"Simon White: You had LBJ's Great Society, Medicare, you already had quite loose fiscal policy. Inflation started creeping up much higher than expected. And then we went into act 2, which is kind of like the premature all-clear. And that's where it was kind of taken that inflation was a temporary phenomenon, it wasn't going to be much of a problem, it was going to go back in its box fairly quickly. And that feels like where we've been over the last couple of years. But you know, stubborn inflation as we know is proven very stubborn.","offset":481,"duration":29}],"startTime":294},{"title":"Comparing the Current Crisis to the Yom Kippur War","summary":"Simon White draws historical parallels between the current Middle East conflict and the 1973 Yom Kippur War, noting similarities in market complacency and equity leadership.","entries":[{"text":"Simon White: It's it's not gone back to target, it stayed above the target rate, it's remained elevated. And if you look actually where that act 2 ends and you match it up to the 70s, it's pretty much bang on October 1973, which is the beginning of the Yom Kippur War. And that in itself is a comparison worth looking at. There's a lot of differences obviously with that war, but there's actually a lot of commonalities that definitely makes it worth looking compared to what we're seeing today.","offset":510,"duration":32},{"text":"Simon White: So back then it was a surprise attack. It was the Arab states led by Syria and Egypt on Israel, and they attacked Israel on Yom Kippur. It was a very short war, it was only three weeks. So this war is not yet three weeks. Initially it was expected to be short, but that's looking less likely now. I think PredictIt has an end of April cease fire now down to 40 percent probability from something like 65 percent not too long ago.","offset":542,"duration":27},{"text":"Simon White: And um you had obviously a major oil shock in response to this war because what happened after the war, after the three-week war, was that the US stated aid to Israel and the Arab states decided to have an embargo on oil, and that created this huge oil shock. So oil prices managed to quadruple in a matter of months. That's quite a significant oil shock.","offset":569,"duration":27},{"text":"Simon White: And and then that led to the act 3, which is the comeback with a vengeance. You have this massive rise in inflation through the end of the decade, and it really didn't end until you got Paul Volcker in with his exceptionally high interest rate hikes, that Saturday Night Special, that really managed to break the back of inflation.","offset":596,"duration":20},{"text":"Simon White: And if you look at some of the further commonalities, it's not just obviously what happened with oil prices, not just that this was in the Middle East, not just that it involved Israel. You also if we go to the next slide in slide 3, and you look at the equity market back then. So the equity market back then, this was the time of the Nifty Fifty. So this was a set of stocks that everybody thought they had to own. You know, they had great earnings, they were great businesses, and pretty much everyone owned them.","offset":616,"duration":31},{"text":"Simon White: Excuse me, and you know, similar to today. So we had very narrow leadership. In fact, it wasn't until the time of the Bangs and the Magnificent 7 that we had such narrow leadership again as what we had back in the early 70s. You had extreme narrow leadership as well, and that Yom Kippur War just before or just after it started, stocks had already started to sell off maybe 10-15 percent in the months before the war, but in the following year they sold off another 45 percent, and that was the largest sell-off we'd seen since the Great Depression.","offset":647,"duration":34},{"text":"Simon White: Now that's not to say that we're going to get the same thing playing out here. There's a lot of differences obviously today. For instance, obviously the US is a major oil producer. This is not the same exactly the same states that are involved. The choke point here is not an embargo, it's the Strait of Hormuz. But there is still nonetheless a choke point in the supply states.","offset":681,"duration":20},{"text":"Simon White: But I think it's worth bearing in mind that you know as a non-negligible tail risk just given we are in a sort of not dissimilar situation. And the kind of nail on the coffin if you like in some ways for why you should be perking up now to be attentive to the risks is that valuations, even though we had this massive decline in stocks in this huge big bear market in 73-74, the CAPE, the cyclically adjusted price-earnings ratio, was 18. And today it's more like 40.","offset":701,"duration":31},{"text":"Simon White: And also like the you know allocation of households compared to financial assets was much lower back then, it's much much higher back today. So really there is a number of reasons why you could see things we're we're we're obviously to get more deterioration obviously to get anything like that, but given some of the commonalities I think it's worth bearing in mind. And especially when you look at the market today, it just does seem again there is some complacency in the air.","offset":732,"duration":23},{"text":"Simon White: The stock market inherently seems to believe I think that there is some sort of Fed put on the way, and therefore it's not really worth the market trading down too much. I mean even if you look at like the put-call spreads, so the VIX went up initially, a lot of that was driven by first of all it was driven by call spreads falling, then it was driven by put spreads rising, so people were putting on insurance, but then they quickly monetized I think they monetized those hedges and that put spread started to come off, and so the VIX has started to come off.","offset":755,"duration":27},{"text":"Simon White: So really I think the market's getting to the point where it feels like, you know what, this isn't going to be a major issue. You know, we don't have too much to worry about here, not ready to obviously rally and make new highs again, but this is not something to get overly your knickers in a twist about. But I'd argue again along with inflation, that's something that's beginning to look a little bit complacent.","offset":782,"duration":20}],"startTime":510},{"title":"Differences from the 1970s and the Food Price Shock","summary":"The conversation shifts to the differences from the 1970s, highlighting how the disruption in the Strait of Hormuz poses an even greater threat to fertilizer and food prices today.","entries":[{"text":"Erik Townsend: Simon, let's go a little bit deeper on some of the both differences and similarities between the Yom Kippur War and the present conflict. The Yom Kippur War was really a war of solidarity. As you said, the US had sided with Israel, basically all of the Arab states together went in on the Arab oil embargo. You have a very different situation today where the US has once again sided with Israel in a conflict with Iran, but now Iran does not have solidarity of the other Gulf states. In fact, it's attacking the other Gulf states that are allied with the United States. It seems to me there are still similarities, but there are some almost diametrical opposites in some aspects of this. How do we sort that out and make sense of to what extent the economic outcome might be the same or different?","offset":802,"duration":52},{"text":"Simon White: Yeah, I think I think that's 100 percent, you know, as I alluded to there are a number of differences, and so that puts you in a point where, you know, no analog is going to be perfect. But I think when you combine it as I say with the overall inflationary backdrop, where we are in terms of this three-act play in the 70s, you know, you could argue that what happened in the 70s were a series of kind of quote-unquote bad luck that led to inflation rising.","offset":854,"duration":27},{"text":"Simon White: So, you know, you had the kind of ex-ante conditions for inflation as I mentioned, we had already the Vietnam War, we had the fiscal expansion on the back of the Great Society stuff, and then you had the 1971 was Nixon closing the gold window, then you had the Arab oil embargo, the Yom Kippur War, you had at the end of the decade you had the Iranian Revolution. You could argue all these things are bad luck, but they were also hitting a situation where inflation was already in a different regime.","offset":881,"duration":28},{"text":"Simon White: And so I think I think that's the thing to to note the differences, that when you're in an inflationary regime, lots of things can happen, right? Things will always happen. But if they hit when you're already in an inflationary regime or more likely to have bigger inflationary impact. You know, that's where we are today. As I say, it's very uncanny we happen to look compare the two analogies that almost to the month when you get this sort of premature all-clear ending is almost to the month when the Yom Kippur War started as when the attacks on Iran started.","offset":909,"duration":31},{"text":"Simon White: Yeah, I wouldn't want to over-labor the point in terms of the analogies, but the there's there's so many precedents that makes it worthwhile looking a little bit deeper into. For instance, another one that's very interesting is an underappreciated fact that in the 70s, the food shock was actually much bigger than the energy shock in terms of on its effect on CPI. So if you look at the weighted contribution from food and from energy in the 1970s, it was much bigger than it was for energy.","offset":940,"duration":31},{"text":"Simon White: And in fact food food inflation was already rising before the the energy shock. This time around we have the disruption to the Strait of Hormuz. That obviously doesn't just affect energy prices, it affects energy products. And for instance, a lot of stuff that goes into fertilizer is either produced in that region or has to travel through that region. So Iran itself produces a lot of urea and ammonia. There's a huge amount of sulfur flows through the straits, all these things go into fertilizer.","offset":971,"duration":30},{"text":"Simon White: And in fact if we go a little bit further into the presentation, if we go to let me just find the slide, if we go to slide 8, we can see there actually you can see the two shocks. So the blue line shows the food shock after OPEC 1, the Yom Kippur shock, and you can see again after OPEC 2, the Iranian Revolution. Both times the food shock was worse.","offset":1001,"duration":24},{"text":"Simon White: And today already we have, if you look at the contribution to CPI, US CPI that is, from food, it's higher than than energy already. So if you have this effect feeding into, you know, fertilizer prices, and that's what I've tried to show on the chart on the right on slide 8, you can see this fertilizer proxy, which includes some of these inputs I mentioned along with things like potash. You know, when that starts to rise, it's a very reliable lead by about six months that food CPI will start to rise.","offset":1025,"duration":30},{"text":"Simon White: So I don't think that is also being fully priced in. And especially I think if you take account of the fact that if you have energy and food both rising, I think it's very unlikely you're not going to get some second round effect that's going to feed into core inflation and you get the sticky inflation that we saw in the 1970s. And that's a lot more troublesome for the Fed. In one sense it should make it slightly easier because the Fed can then go, \"Right, if we see sticky inflation, that's something we think we can do something about, we'll maybe hike rates.\"","offset":1055,"duration":24},{"text":"Simon White: But with the muted muted, sorry, next chair Kevin Warsh coming in, you know, whether he's going to lean towards the dovish or the hawkish spectrum, you know, I certainly think he's more likely to be more like an Arthur Burns who was in in the early 70s at a time of the Yom Kippur War than he's likely to be a Paul Volcker who was in charge after the OPEC 2 shock after the Iranian Revolution in 1979. So I think that further complicates the the matter in terms of what the Fed's reaction function is going to be.","offset":1079,"duration":41}],"startTime":802},{"title":"Duration of Oil Shocks and Yield Curve Mispricing","summary":"Simon explains how short-term conflicts can have long-lasting effects on oil prices, comparing the permanent shock of OPEC 1 to the transient shock of OPEC 2.","entries":[{"text":"Erik Townsend: Well, it seems like the analogy that's most relevant is the Yom Kippur War only lasted a few days, but the Arab oil embargo lasted quite a lot longer than that. So the question is once the direct kinetic conflict is over, how long can Iran continue to disrupt the flow of traffic through the Strait of Hormuz? Is that the right thing to focus on and if so, what's the answer?","offset":1120,"duration":25},{"text":"Simon White: Yeah, I think I think that's that's correct, Erik, in that the key message I think from that period was the war itself was very short. As you say, it was about three weeks, but the impact was felt way through all through the decade and it had a number of consequences. So again, no analogy is perfect, but the human side of things doesn't change how humans respond, human nature responds, doesn't really change.","offset":1145,"duration":30},{"text":"Simon White: In fact, I can see this this the two nature of the two different shocks. If we go to slide 6, so we've got two more charts there, and this this brings me to another point which I think needs to be made is that I don't think the yield curve is pricing in what's looking to be a much larger inflationary shock than for instance has been picked up in the break-even market.","offset":1175,"duration":20},{"text":"Simon White: And so the left chart we can see there is what break-evens did in the 1970s. So OPEC 1 and OPEC 2, both cases they ended up rising, and rising quite considerably, but long after if you like CPI had already started rising. So they were in late to the party. But both times they they did rise.","offset":1195,"duration":18},{"text":"Simon White: And if you look at the chart on the right there, you can see the two the nature of the two different shocks. So OPEC 1 was definitely more of a permanent shock to oil prices. So really oil prices never really revisited their pre-OPEC 1 or pre-war, pre-Yom Kippur War levels again. They just kept rallying through until OPEC 2 hit, the Iranian Revolution in 1979. They rose sharply again but nowhere near as much in percentage terms as they did in OPEC 1, and then they sort of gradually start decaying fairly soon after the Iranian Revolution.","offset":1213,"duration":34},{"text":"Simon White: So the OPEC 2 was more transient, was a more transient shock, but in both cases if you look at the bottom panel of that chart, you can see core and and in the interim period between OPEC 1 and OPEC 2, both made a higher low before rising again in the early 80s. And again it wasn't until Paul Volcker got his hands on monetary policy that he was really able to put an end to this huge inflation that we'd had through that decade.","offset":1247,"duration":25}],"startTime":1120},{"title":"The Vicious Cycle of Structural and Cyclical Inflation","summary":"Simon warns that structural and cyclical inflation are feeding off each other in a self-reinforcing cycle, further complicated by the impending arrival of a potentially dovish Fed Chair.","entries":[{"text":"Erik Townsend: One of the theories of secular inflation is that it's a self-reinforcing vicious cycle. So as you begin to see inflation, it changes consumer behavior. People start stocking up on things because they want to buy it while the price is still cheap before the price goes up more. That causes more consumption that is inflationary, and it all feeds on itself and it's kind of like a fire that once you've started it, you can't put it out. Are we already at that point in terms of this coming inflation cycle where the fire has been started and can't be put out, or are we still in the need to look at this and see what happens stage?","offset":1272,"duration":37},{"text":"Simon White: We're we're already in that. In my view it's quite clear that what began in 2020 with the pandemic, with the large spike in inflation, was the beginning of if you like that that cycle starting. And really what's happening underneath is that why 2 percent inflation, for whatever reason this is an arbitrary number, but 2 percent or around 2 percent inflation overall like over the whole economy tends to be fairly stable.","offset":1309,"duration":29},{"text":"Simon White: And I think that's because all the different actors that are taking price signals off one another when inflation is not moving around that much, they they tend not to get out of sync. But once it's out of the bag if you like, once you have this large rise in inflation which we saw in the early 2020s, they got all out of sync, and it takes a huge amount for them to get back in sync, and you end up with inflation remaining elevated.","offset":1338,"duration":24},{"text":"Simon White: And so you can split CPI up for instance into components. So you can look at the essentially sticky versus non-sticky components. And what you notice in 2020 is both cyclical and structural inflation rose, but cyclical started to fall and but the structural one remained more sticky.","offset":1362,"duration":19},{"text":"Simon White: And by the time the structural inflation had started to fall, cyclical inflation because of its name is cyclical, had started to rise again and started to reinforce structural inflation that was already elevated. And we're right in that period again now where structural had started to fall, a higher low, but the cyclical part of it is already rising again.","offset":1381,"duration":22},{"text":"Simon White: And this war is just going to make it worse because obviously the immediate effect is on headline inflation. So straight away you're going to see that feed into the cyclical side of things. And once again what was what 2.4 percent where we are now and CPI maybe 3 percent of PCE, you know they're going to look like again equivalent to what we saw in the mid-70s after the Yom Kippur War. This is the point where we start to see a rise again.","offset":1403,"duration":21},{"text":"Simon White: Now I don't know how far it goes. Again, the US is much more insulated than it was back then. But I think you do see a re-acceleration. And the real kind of, if you like, the real kind of tinder in this is that as I say, going back to Kevin Warsh, you've got someone that's coming in that nobody's really sure is going to be an inflation fighter. In fact quite the opposite quite possibly.","offset":1424,"duration":22},{"text":"Simon White: Which is kind of actually a bit odd just to slide deviation, but connected is it's kind of strange if you look at real yields have been rising. So real yields have been rising since the war, and that's been driven by higher rate expectations. And so that's part of the rise in nominal yields. So break evens have moved a bit, as I mentioned, but really the bulk of the move so far have been real yields, and that's on the back of as I say rate expectations are going higher.","offset":1446,"duration":26},{"text":"Simon White: But that kind of just seems a little bit incongruous, given Warsh and the conditions under his nomination and a president who still makes no bones about being absolutely determined to get lower rates immediately. I mean he was saying so only a couple of days ago on yesterday. So I feel that that is also adding to the structural kind of impediment for inflation to to keep rising.","offset":1472,"duration":26}],"startTime":1272},{"title":"Real Yields, Break-Evens, and Yield Curve Steepening","summary":"The discussion turns to the yield curve, with Simon predicting a steepener as the market begins to price in higher long-dated break-evens and inflation shocks.","entries":[{"text":"Simon White: And then go back to the yield point I was mentioning. So I think yields as I say are not priced for inflation shock, and I think one thing we'll see is the yield curve will steepen. So if we go to slide 7 on the deck and I looked at basically how break-evens and real yields behaved in the 70s. Now there was no real yield in the 70s because TIPS didn't start trading until 1997.","offset":1498,"duration":27},{"text":"Simon White: But you can synthesize a real yield so you basically look at how real yields have traded laterally versus a whole bunch of different economic and market indicators, and then you can back it out and look at how and build basically a synthetic series of real yield in the 70s. So chart on the left there we can see again the difference between OPEC 1 and OPEC 2 and how the yield behaved.","offset":1525,"duration":21},{"text":"Simon White: So in both cases, break-evens rose, but in the OPEC 1 what happened is that you had the shock to break-evens but then we had an equal and opposite shock to real yields. That's textbook stagflation. What happened in OPEC 2 is the break-evens rose, but real yields stayed largely static. And I think that was basically for two main reasons. One, the US response to OPEC 1, so the US became less energy intensive and more energy efficient, and a lot of non-OPEC production came on stream from places like Alaska and the North Sea.","offset":1546,"duration":36},{"text":"Simon White: And on top of that, you had very soon after the Iranian Revolution you had Paul Volcker at the Fed, and that really put a kind of cushion under how far real yields could fall. So in OPEC 1, the 10-year yield maybe didn't move a huge amount because the real yield and break-evens canceled one another where the nominal yield rose a little bit in OPEC 2.","offset":1582,"duration":20},{"text":"Simon White: But the difference being in OPEC 1 and OPEC 2, so the OPEC 1, the curve steepened because we had Arthur Burns, and he as I mentioned earlier, you know, was notorious for not believing that a central bank could do much for inflation, let alone a supply shock inflation. He was kind of of the view that by and large, most inflation shocks couldn't be solved by a central bank.","offset":1602,"duration":24},{"text":"Simon White: And in fact he was the guy when he was at the Fed, he got the staffers working on some of the first measures of core inflation, and through the decade he kept on taking out more and more of core inflation in a frantic hope that something would be going down, which he discovered wasn't the case. So you know, we have this very kind of dovish banker who doesn't really believe central banker doesn't really believe that inflation is something he can do much about.","offset":1626,"duration":23},{"text":"Simon White: So short yields kind of fell, so the curve steepened in OPEC 1. In OPEC 2, yes 10-year yields were rising a little bit, but you had Paul Volcker who was massively raising on the front end, so the curve the curve flattened. But this time I think in some ways it the curve response function could be more like OPEC 1 because I think that longer dated break-evens will rise. So I think that move thus far that we've seen this muted move, I don't think that'll last.","offset":1649,"duration":27},{"text":"Simon White: And that they should rise more from you know the relative static where they were before, and more likely to see as I say with Warsh, you're going to see lower rate. So I think lean towards a curve steepener this time as we saw in OPEC 1, but not just for reasons that OPEC 1 is a similar to what's happened today. There are as I covered some similarities but there's a lot of differences as well.","offset":1676,"duration":21}],"startTime":1498},{"title":"Equity Market Complacency and the Fed Put","summary":"Simon discusses why equity markets remain surprisingly complacent, heavily relying on the belief of a forthcoming \"Fed put\" despite immense geopolitical and inflationary risks.","entries":[{"text":"Erik Townsend: Well, if this was 1973 all over again, and clearly you've said that it's not exactly a perfect analogy, but to the extent that there's a lot of overlaps, 1973 was not a good time to have a long-term bullish outlook on buying and holding stocks for the long haul. What does this mean for equity markets for the rest of the decade?","offset":1697,"duration":21},{"text":"Simon White: Why, I I I think it's interesting now. I mean, depends who you speak to. I mean, so I've got like a lot of stuff you know some friends and people I know that speak to commodity people, and they're overall a lot more bearish than equity and rates people who seem to be overall less pessimistic. I think again, going back to what I said earlier, I think that's still the sort of belief that there is some sort of Fed put on the way.","offset":1718,"duration":23},{"text":"Simon White: But even more than that, I think the big difference is that ultimately there's a backstop, and that if things get really bad the Fed can step in. I'm not saying that's what's going to happen right now, but you're always going to have that kind of tail cover. So the commodity markets can really price in extreme kind of negative outcomes, but they don't have a lender of last resort, right?","offset":1741,"duration":20},{"text":"Simon White: So there's nowhere to go if you if your commodity markets seize up for whatever reason, there's no backstop in the same way that you have for financial assets. So I think that sort of explains why we have that today. And you know 1973, I don't think we we had that to the same extent. There wasn't this belief that the Fed was always going to protect equity returns.","offset":1761,"duration":22},{"text":"Simon White: So that's why you probably had that situation where you had this huge shock much bigger than the energy shock that got today, combined with a Fed that's then, yes it was overall more dovish, but this was the decade remember of go-stop monetary policy where, you know, they loosened policy, inflation came back then they tightened it, and then they're like, \"Oh right, better loosen policy again,\" back and forward, back and forward.","offset":1783,"duration":21},{"text":"Simon White: So you know, huge amount of volatility underlying there which obviously makes it more likely or or increases the chance you can have deeper steeper falls in the market. And so you don't really have some of that today, but it does seem as I say earlier, it feels like the market overall be more complacent, even with that in mind that there is a backstop, that there is still a potential for some sort of Fed put, it still seems to be some sort of complacency and as I say what drew me what draws me to that especially is just looking at what's happened to put-call skew.","offset":1804,"duration":27},{"text":"Simon White: You know, initially there was the response to like let's hedge some downside, but very quickly that reversed. It was almost as if like the market went, \"Oh maybe we don't need such deep out of the money puts here, maybe I maybe the market's not going to sell that sell off that much, in which case I don't need this insurance right now.\" So again that that smacks to me just of complacency just because the distribution of outcomes are are still very wide, right?","offset":1831,"duration":29},{"text":"Simon White: Still a lot of moving parts here, both unpredictable but the most of of course Trump himself. You know, back in the 70s we had a lot of volatility, political volatility, but again I don't think you had anyone quite as volatile and who was able to obviously voice his volatility in such a real-time manner than we've got today. So that really puts a lot of people in a sort of frozen moment. Like they want to move money, but they're also kind of fearful that they can't really put much risk on because so much could change.","offset":1860,"duration":27}],"startTime":1697},{"title":"Gold as a Tail-Risk Hedge and Ultimate Collateral","summary":"Simon explains why gold remains the ultimate form of collateral and a critical tail-risk hedge, defending its recent bull run despite short-term pullbacks and shifting correlations.","entries":[{"text":"Erik Townsend: Simon, on page 11 you say gold is a hedge against both tails. Elaborate on that please. But also I think it's it's relevant to point out if we're looking at the analog as being the 1970s, private ownership of gold wasn't relegalized until 1974. So there was a very big transition catalyst there where it became legal once again to own gold bullion, which probably disrupts the data. How should we think about this in the 2020s?","offset":1887,"duration":27},{"text":"Simon White: Yeah, that's a good point. I think I think there's also another disruption at the other side as well because the data on this chart goes back to the late 20s. And back in the 30s was when essentially the US confiscated private gold ownership, so they confiscated gold. I think they paid 20 dollars and then revalued it at 35 dollars an ounce.","offset":1914,"duration":23},{"text":"Simon White: So quite possibly gold could have went up a lot more in that deflationary period of the 30s. I think I think that's why gold's misunderstood, though, is that it is to some extent an inflation hedge. It's not a perfect inflation hedge, it's not path-dependent. But in extreme, when inflation goes very very high and you're in that sort of environment, it does a good job because you've got the debasement angle of things and just the general kind of insurance against the financial system.","offset":1937,"duration":29},{"text":"Simon White: But it's not appreciated that it's also a downside tail hedge as well. And I think what has been driving a lot of the rally recently in gold is just a lack of alternatives. If you start thinking about I don't know what's going to happen and I don't know whether we're going to be in a debasement world where there's a lot of inflation, or I don't know whether there's going to be a massive credit event and that's going to be deflationary.","offset":1966,"duration":21},{"text":"Simon White: These are potential threats to the financial system. What can I own that has you know proven record of protecting a portfolio in such an environment? And there's really not much else other than gold. I think people sort of ran through all the options and they're like, \"Right, that won't work, that won't work.\" Bitcoin? That hasn't been tested.","offset":1987,"duration":21},{"text":"Simon White: And they landed on gold. And you know, a lot of people that openly admitted they've never ever really favored gold, they've never been a fan of gold, they've never understood it, are nevertheless starting to add or have started to add some exposure to their portfolios. So I think as an unimpeachable form of collateral really is what's driving driving this move.","offset":2008,"duration":21},{"text":"Simon White: And although it struggled a little bit over the last few weeks, I think it's premature to say that's the end of the primary bull trend because kind of a lot of the main reasons that were driving it are still valid today. I mean there's still a need for diversification from the dollar system. I still think there's obviously a lot of geopolitical volatility. That hasn't changed.","offset":2029,"duration":23},{"text":"Simon White: You know, central banks, I don't think are suddenly like emerging market central banks, they were the ones that initially kicked off the rally a few years ago. I don't think they're going to turn tail and start selling in any great size. You know, they bought some and they may not buy any more, but I don't see why they would suddenly turn tail and start selling on mass. There was a story that Poland was mooting selling some of its holdings, but the reason why they were thinking of selling them was for defense. And that doesn't really strike me as a great sort of a gold bearish kind of reason for selling your gold overall.","offset":2052,"duration":37},{"text":"Simon White: So I think, yeah, the general environment's still very conducive to gold still still generally keeping to its primary bull trend. It's struggling right now perhaps because we've had some marking up of short-term rates, and the dollar's had a little bit of a rally, things like that. But overall I I don't see why. You know, it takes a big seller to come around to really force it into a massive bear market, and I just don't see where that's going to come from.","offset":2089,"duration":24},{"text":"Erik Townsend: As you said, unfortunately what has not gone away is geopolitical excitement, for lack of a better word. The thing that I've noticed just in the last few weeks is there was a very strong positive correlation, you know, the next time a bomb drops gold spikes upward. And what we've seen just in the last few weeks is a breakdown where when oil is up hard because of geopolitical, you know, bombs are dropping, gold's actually moving down. What's going on there?","offset":2113,"duration":29},{"text":"Simon White: Yeah, as I say, I think potentially it's because the real yields have risen, that could be part of it, the little bit of the rally in the dollar. It should also be in times of if there's any capital repatriation going on, maybe in the Middle East. I don't know for sure, but you know gold can often get hit in the short term. People need to liquidate.","offset":2142,"duration":20},{"text":"Simon White: That's unfortunately the problem with having an insurance asset that's also can sometimes be a very liquid asset, is it's often the one that's first to go, so it can give kind of counter-intuitive signals. But overall I just as I say, I don't know what the narrative or the argument would be to say that this is anything more than just, you know, obviously we've got to remember the market has rallied extraordinarily much in recent months and it's perfectly respectable for it to have, you know, the kind of pause it's having right now, like it can't continue in that sort of trend indefinitely.","offset":2162,"duration":38},{"text":"Simon White: But I don't think that means that the trend is over. So, yeah, I mean I think silver is a far more, obviously volatile, but a far more questionable kind of you know, response to that kind of overall idea and trade, but gold to me seems certainly more more secure just because as I say, the reasons underpinning its rally all seem to be mostly intact still now.","offset":2200,"duration":23}],"startTime":1887},{"title":"Rewriting the Risk-Off Playbook","summary":"Simon explains why traditional risk-off playbooks may fail in this environment, specifically arguing that the US dollar may not see a massive rally due to different capital flow structures.","entries":[{"text":"Erik Townsend: Simon, we've been jumping around in the slide deck. Let's go back to page 4 because you've basically said you're rewriting the risk-off playbook. It seems like an important book to read. Tell us more about it.","offset":2223,"duration":13},{"text":"Simon White: well, I'm certainly not going to rewrite it myself, but my point here is really that, you know, we talked about some historical analogs that are useful guides, but I think you have to keep an open mind as the rules can change. So I think standard you know risk-off playbook is that you see the dollar rally and Treasuries rally and risk assets sell off, and that might not be the case to the same extent this time.","offset":2236,"duration":25},{"text":"Simon White: So for instance, take the dollar. So the kind of quintessential risk-off moment really was the GFC, and in the GFC the dollar rallied. So I think that's for a lot of people's like, \"well, that that was the big one and the dollar rallied, the dollar's therefore a safe haven.\" But really if you look at what drove that, and then you compare to today, I don't think you can necessarily say the dollar's going to be in a condition to rally quite as hard as it did back then.","offset":2261,"duration":23},{"text":"Simon White: So the chart on the left there you can see that the blue line shows the bond flows, inflows from foreigners. So they they slowed. Equities were tiny back then, equities are much bigger now, as far as foreigners are concerned. But what actually drove the dollar, the rally, was repatriation of flows, so the US basically mutual funds and banks had lent to various European entities, and it was these guys repatriating that led to the dollar rally.","offset":2284,"duration":27},{"text":"Simon White: So it wasn't a case of foreigners channeling money in or needing dollars to cover structural shorts. It was really just US entities repatriating that led to the dollar rally. Now this time around, the cash flows are the structure of this is different. So bond flows are much smaller now because we've had because the US is now not see Treasuries are not seen as much of a safe haven. And equity flows are now massive.","offset":2311,"duration":32},{"text":"Simon White: And the US outflows are not as large as they were back in 2008. So the net impact means the US is much more exposed to equity outflows. So in a sort of risk-off environment that we're in right now, it's conceivable that more capital is repatriated, and some of that is equities in the US. Equity flows as I say tend to be unhedged. That is a dollar negative. And you don't have that cushion of the same cushion of dollar repatriation.","offset":2343,"duration":24},{"text":"Simon White: So, yeah, you wouldn't expect to see the dollar necessarily rallying as much. And that could be seen even more if you look at the chart on the right. So after the, you know, Mar-a-Lago Accord, you know, all the talk of the dollar disruption, the tariffs, you know, that didn't lead to a sell America trade, but I certainly think it made people think twice about their exposure to dollars.","offset":2367,"duration":20},{"text":"Simon White: And that could be seen as I say in this chart, just kind of like the dog that didn't bark. So the white line shows the dollar reversed. And what you tend to see is the blue line, which is reserves denominated in dollars. So when the dollar weakens, i.e. you see the white line rise, the reserve managers have tended to buy dollars. They tend to use the weakness in the dollar to to add to their dollar reserves.","offset":2387,"duration":26},{"text":"Simon White: And that significantly hasn't happened this time round. So we've seen this big weakening of the dollar and there's been no response yet from dollar reserve. So I think that shows like a general change in attitude to global demand for dollars. So I don't necessarily say as I think the dollar rally will be as big this time, and thus far the DXY I think is up about 1 and a half 2 percent since the war started.","offset":2413,"duration":17},{"text":"Simon White: And if we go to to slide 5 looking at say commodities, so commodities as a as a kind of risky asset is sort of seen as well should certainly sell off in a recession I think is the general interpretation. That isn't isn't always the case either. If you have a commodity induced recession, and if we are going to get recession, there's very low chance of it in the next few months, but that could change if the war continues and the negative effects spiral.","offset":2430,"duration":25},{"text":"Simon White: What often happens then is that commodities start to sell off before the slump in growth, but the that sort of sell-off in commodity prices kind of eases the growth shock and actually that allows commodities to rally through the rest of the recession. So that might well happen again. We get a commodity induced recession say later this year, next year. That's not a prediction, but if we were to get one, I wouldn't automatically assume that commodities are going to sell off through that.","offset":2455,"duration":26}],"startTime":2223},{"title":"US Economic Strength and Private Credit Vulnerability","summary":"Simon breaks down the underlying strength of the US economic cycles but warns that the massive growth in floating-rate private credit remains a deeply vulnerable underbelly.","entries":[{"text":"Erik Townsend: Simon, let's move on to page 9. The title of that slide is \"it takes a war to bring down an economy this strong\". Let's start with how strong the economy is, but then later you say it would take a protracted war. So I guess the question is how protracted does it need to be in order to take down the strength of economy that we already have, and where is this thing headed?","offset":2481,"duration":20},{"text":"Simon White: it's actually remarkably strong given I think the length of time of the cycle. And that really surprised me when I was looking at this. And it's also a little bit ironic, I guess, that coming into this war the US was firing on all cylinders. And you know as you mentioned as I mentioned the fact that war is perhaps just what it's going to take to to derail it.","offset":2501,"duration":23},{"text":"Simon White: And you have number of cycles for the US economy. Everyone knows about the business cycle. There's also the liquidity cycle, the housing cycle, the inventory cycle, and the credit cycle. And all of them are actually in in pretty good shape. So the business cycle, if you look at leading indicators, has been turning up. The liquidity cycle, so that's the chart on the left there.","offset":2524,"duration":21},{"text":"Simon White: And I look at excess liquidity, which is the difference between real money growth and economic growth. So that really gives you a measure of what impact this liquidity is going to have on markets. So the bigger the gap between liquidity and economic growth, it means the economy needs less, but that more to go into risk assets. That has been vacillating around, as you can see in the chart, but it's turned back up again.","offset":2545,"duration":22},{"text":"Simon White: And even even taking into account we've seen some tightening in financial conditions since the war, but overall they've not been massive. As I've alluded to earlier, the dollar's rally hasn't been huge either thus far. So liquidity's in in pretty good shape.","offset":2567,"duration":15},{"text":"Simon White: And the business you know the general business cycle is in pretty good shape, even taking into account the job market's slowed down. I think it's possible to have a jobless growth. And some of the things that I would look at to see if there was a slowdown in growth coming, such as temporary help, is actually rising, not falling.","offset":2582,"duration":16},{"text":"Simon White: Average hours worked is kind of static. You would normally expect to see that fall as people cut hours before they start sacking people. And I think you've got to remember that we have companies still have very strong margins, the you know their balance sheets are generally in pretty good shape.","offset":2598,"duration":20},{"text":"Simon White: And then you've got this massive amount of government money still filtering through the system. So there's maybe not the same acute needs, in the short term at least, for heavy layoffs. And that that global, the global economy is also in a good shape as well. So that's the chart on the right there. You can see that we're in the midst of this global cyclical upswing.","offset":2618,"duration":18},{"text":"Simon White: If you look at OECD leading indicators for different countries around the world, almost all of them are turning up on a six-month basis. And then if we look at the inventory cycle, that looks to be turning up as well. Leading indicators are pointing it to continue to rise. Sales to inventory ratios have started to rise.","offset":2636,"duration":18},{"text":"Simon White: The housing cycle is not as in good shape, but you know it's okay. House price growth, sales growth has slowed down and things like that. But one of the best leading indicators for housing is building permits. Building permits are are doing okay. And they're actually led by mortgage spreads. So we've seen quite a significant compression in mortgage spreads for various reasons such as falling bond volatility.","offset":2654,"duration":23},{"text":"Simon White: So you can't say that the housing cycle is in particularly bad shape either. And then we have the credit cycle. So if we go to slide 10, the listed credit market from a fundamental perspective, my my leading indicator there on the chart on the left shows that on net fundamentals are still pointing to tighter spreads. So things like bank lending conditions are particularly","offset":2677,"duration":23},{"text":"Simon White: supportive. You can see there on the chart that leading indicator typically gives about a six-month lead as to what we can expect from listed market credit spreads. So that is looking okay. But there is there is trouble brewing as well. It's not all good news. It's maybe more below the surface. So there's private credit.","offset":2700,"duration":19},{"text":"Simon White: Private credit is where we've had the most debt created recently as listed market debt creation was falling, debt overall debt creation was falling because private credit was rising so so much. And you can get a little bit of a measure on what's going on in private credit by looking at the business development company spread, the BDC spreads, so they are basically publicly listed companies that invest in unlisted entities.","offset":2719,"duration":24},{"text":"Simon White: And their spreads normally track the listed market quite quite tightly, but recently they've decoupled. So listed spreads continued to trade and to turn in lower, tighten, but the BDC spreads have decoupled and moved a little bit higher. So that suggests that there is some some problems in private credit.","offset":2743,"duration":16},{"text":"Simon White: And then the other factor is private credit as opposed to listed market credit tends to be floating rate. So high-yield listed high-yield maybe only about five percent or five to ten percent of floating rate now compared to nearly thirty percent after the GFC. Whereas private credit by its nature tends to be almost all private almost all floating rate.","offset":2759,"duration":20},{"text":"Simon White: So it's very exposed to the rise in interest rates that we've seen over the over the last year or so, and it will be obviously even more impacted if we get this re-acceleration in inflation and higher interest rates that I mentioned before. So you've got this situation where the economy is very strong overall, but it's got these sort of vulnerable underbellies such as private credit, which are already starting to hurt, as I say, if we look at the BDC spreads.","offset":2779,"duration":25},{"text":"Simon White: So that's the risk really is that a strong economy doesn't necessarily protect you from from accidents happening, and I think private credit's potentially where one of those could happen.","offset":2804,"duration":10}],"startTime":2481},{"title":"Reiterating Gold's Status vs Crypto","summary":"Erik and Simon circle back to gold, reiterating its historical outperformance during extreme inflationary or deflationary crises, contrasting it with crypto's unproven track record.","entries":[{"text":"Erik Townsend: Simon, I wanted to jump back into gold. You gave us page 11, \"the ultimate form of collateral\". We talked a little bit about the differences between now and the 70s. What are your views relative to gold and why specifically did you title this \"the ultimate form of collateral\"?","offset":2814,"duration":17},{"text":"Simon White: Well, that that's a good question. I mean the chart there on page 11 shows the performance of gold in inflationary environments and deflationary environments. And it's what I alluded to earlier, that gold performs remarkably well when inflation is very very high, above the target, so five, six, seven percent, it has historically done a really good job.","offset":2831,"duration":21},{"text":"Simon White: But it also manages a higher average return when the economy is contracting or during crises. And I think that speaks to it. In any situation where the system itself is being put under scrutiny, you know gold manages to outperform other major asset classes. It's because people don't find it particularly comfortable but they find it safe. You know, no one likes owning something that yields zero, but you know when everything else yields minus thirty, zero is an amazing amazing real yield to have in your portfolio.","offset":2852,"duration":30},{"text":"Simon White: So in that sort of scenario, people are attracted towards something that really is independent of of you know almost almost everything else. I mean, central banks have made efforts to control gold prices before. For instance, the London Gold Pool in the early 60s, but that ended in abject abject failure. So it really isn't an unimpeachable asset in that regard.","offset":2882,"duration":21},{"text":"Simon White: And I think that's why people keep coming back towards it. And especially today as I say in a position of debasement, but possibly contraction, tail risks on either side, I'll go gold's really where you you find yourself looking if you haven't yet been convinced that crypto will do the job.","offset":2903,"duration":15},{"text":"Simon White: Crypto as you look over the last last few weeks was also hit heavily. So that doesn't really smack yet for everyone as as being something that they can absolutely rely on in extreme events. I mean, look at what it did in in 2022. It didn't it certainly didn't work as a deflation hedge back then. So yeah, I still find people coming back to gold as the gold standard of unimpeachable collateral.","offset":2918,"duration":25}],"startTime":2814},{"title":"Private Credit Risks and Interview Outro","summary":"Erik formally concludes the interview with Simon before briefly returning to the topic of private credit, comparing its opaque risks to the 2007 subprime mortgage crisis.","entries":[{"text":"Erik Townsend: Simon, we're up against our time. Before I let you go, I can't think of anything more important than inflation right now. Tell us where our users can go to see more of your work and particularly work related to inflation.","offset":2943,"duration":12},{"text":"Simon White: So I publish daily on Bloomberg on the terminal and mobile and on on on the on bloomberg.com if you don't have access to the terminal. And so you know I cover all major macro areas. We look we obviously spent quite a bit of time on on the equity market over the over the coming months just as things got a little bit more heated.","offset":2955,"duration":18},{"text":"Simon White: But also focus obviously on the rates and fix income market and credit as well. So there really isn't any you know major asset class. I cover fixed commodities too as we've already done today in our talk. So yeah, we can you can catch me there.","offset":2973,"duration":13},{"text":"Erik Townsend: Simon, thanks so much for another excellent interview. Patrick Ceresna and I will be back as macro voices continues right here at macrovoices.com.","offset":2986,"duration":20},{"text":"Simon: Um, so I think, I think that does have to color your, your view and, uh, a protracted war would definitely do a lot of damage to, to the economy.","offset":3006,"duration":12},{"text":"Host (Eric): Simon, as you talked about private credit, it was kind of concerning to me because, frankly, it, it echoes in my mind to about 19 years ago, the summer of 2007, when we were also talking about an opaque, not well-understood in the broader finance community small little piece of the credit market that couldn't possibly disturb anything else. And the reassurance at the time was, don't worry, it's contained to subprime. There's nothing to worry about. Is this another setup like that?","offset":3018,"duration":32},{"text":"Simon: It looks very much like it. And I think it was Ben Bernanke himself who said, uh, subprime is contained, I think. Um, look, I, I go back to my kind of axiom that, um, the one thing that doesn't change is, is human nature. I think we're sort of seeing that even within the private credit space in terms of when people have opportunities to make money, the more kind of off-grid they are away from regulation, the standard kind of emotions of greed and fear will kick in.","offset":3050,"duration":34},{"text":"Simon: Greed initially, and people will start to take inflated risks to essentially earn money now and park what are risks later. Hopefully they can not be around when the, um, proverbial hits the fan. Um, so I don't see why, why it wouldn't be any different. I mean, there's even a story today about one of the credit funds. If you look in the private credit fund, it's, it's yet another black box, but within it there's even more black boxes.","offset":3084,"duration":29},{"text":"Simon: I mean, that straight away reminded me of CDO squared. So here we had CDOs, which were already kind of niche derivative products, but people started making up these CDOs of CDOs themselves. And, you know, I'm sure a lot of people at the time were thinking, this probably can't end well. And, you know, here we are again. There's nothing new in finance.","offset":3113,"duration":23},{"text":"Host (Eric): Simon, I can't thank you enough for a terrific interview. Before I let you go, I'm sure a lot of listeners are going to want to follow your work. You kind of have to be somebody special and have a Bloomberg terminal in order to access most of it. Tell them for those who are lucky enough to have that access, where they can find your writings.","offset":3136,"duration":20},{"text":"Simon: Sure, and thanks again for having me on the show, Eric. Uh, so on the terminal, I have a column called Macroscope. Comes out uh, twice week, Tuesday and Thursdays. And I also write for the Markets Live blog, which is a kind of 24-hour five-days-a-week markets scroll uh, that you can follow all the latest market development.","offset":3156,"duration":25},{"text":"Host (Eric): Patrick Ceresna and I will be back as MacroVoices continues right here at macrovoices.com.","offset":3181,"duration":10}],"startTime":2943},{"title":"Introducing Rory Johnston and the Strait of Hormuz Crisis","summary":"Erik introduces energy expert Rory Johnston to discuss the unprecedented and unexpected closure of the Strait of Hormuz.","entries":[{"text":"Host (Eric): It was great to have Simon White back on the show. Rory Johnston is next on deck for a special second interview on the developing Iran conflict and what it means for the oil markets. Then Eric and I will be back for our usual post-game chart deck and trade of the week.","offset":3191,"duration":21},{"text":"Host (Eric): Since the extra coverage format seems to be a hit with our listeners, we will do our best to continue it as long as the situation in the Middle East warrants. Now let's go right to Eric's interview with energy markets expert Rory Johnston.","offset":3212,"duration":22},{"text":"Host (Eric): Joining me now is Commodity Context founder Rory Johnston. Rory, uh, you, Dr. Anas Alhajji, really all of the most credible experts felt the same way, which was look, the Strait of Hormuz getting shut down is probably not that realistic of a scenario. And I'm going back to previous interviews, you know, months or years ago.","offset":3234,"duration":25},{"text":"Host (Eric): Boy, everybody got thrown a curveball. So what happened? How come all the experts, including yourself, who thought this really couldn't be shut down? Is it just about insurance? Is it about minefields? Is it about something else? How come the traffic is not flowing through the strait, first of all, and then we'll get into what does it mean?","offset":3259,"duration":22}],"startTime":3191},{"title":"The Trump Administration's Strategic Miscalculations","summary":"Rory admits his surprise at the strait's closure, arguing that the US administration blundered into a prolonged conflict expecting a quick capitulation that never arrived.","entries":[{"text":"Rory: Thanks for having me back on, Eric. As you note, I've been relatively kind of Pollyannaish about this for a long time, that...","offset":3281,"duration":10},{"text":"Rory: ...it, and the reason for it, the reason I didn't think this would happen, and to be clear, I never thought this would happen in my career. And the reason for that is because it is such a big shock. Like it's, you know, it make—it'll make the, if this continues, it'll make the 1970s look like child's play.","offset":3291,"duration":21},{"text":"Rory: And that is my concern here. And I think part of the reason that it is happening now, and the reason I didn't think it would happen is—it's not that I didn't think that Iran could close the strait, although I had my doubts because we had never seen it realized and again, the consequences are so intense.","offset":3312,"duration":19},{"text":"Rory: But I never thought a US president would engage in a war with Iran without a plan, without something in his pocket kind of ready for this moment. And what we've seen so far is that at least, here's my, my read of what's happening and how the Trump administration got into this. I do not think that the Trump administration expected to be in its third week of the Iran war.","offset":3331,"duration":27},{"text":"Rory: I do not think they did any of the things you would do if you had planned to be in this engagement for weeks and potentially months now. We saw, for instance, the IEA's coordinated strategic petroleum release last week. That was good. Uh, that's a, absolutely what we should be doing in this in this situation, but it was two weeks after the war started.","offset":3358,"duration":24},{"text":"Rory: Like, if you were, if you were planning this, you would have an IEA release lined up. You know, we saw that ahead of the Gulf War as an example. You would have had things like the marine insurance facility that Beston announced at Treasury. You would have had that lined up. You probably would have done more work to refill the Strategic Petroleum Reserve ahead of this.","offset":3382,"duration":23},{"text":"Rory: I mean, all of these things are such that it just seems insane that we entered this without—and by we, I mean the Trump administration entered into this without a plan. I think that what we've seen from the Trump administration—and very frankly, my expectation was that we were going to see something that clearly the largest military buildup in the Middle East since the invasion of Iraq in 2003 was going to lead to something.","offset":3405,"duration":27},{"text":"Rory: But right, we saw the same kind of buildup off the coast of Venezuela earlier this year or late last year. And in that moment, you know, there was blockade, there was everything else. But when it finally all went down that first weekend in January when the Trump administration, you know, uh, kidnapped Nicolas Maduro uh, and his wife...","offset":3432,"duration":21},{"text":"Rory: ...basically that happened on a Saturday, or Saturday morning, I guess. There was all this, you know, what's happening, what's happening, what's happening. And then by Monday, you know, we had Delcy Rodriguez in as the interim president. She was making a deal with President Trump and it was kind of, it was wrapped really quickly.","offset":3453,"duration":17},{"text":"Rory: The same thing happened last June when we last talked about the worry of the Strait of Hormuz, was that um, the Trump administration embarked on what at that stage was a fairly stark break from US military policy towards Iran, which is, you know, it had directly engaged in 14, dropping 14 bunker-buster bombs on uh, Natanz and Isfahan.","offset":3470,"duration":24},{"text":"Rory: And again, if you remember, and I'm sure you remember this Eric, the, like the Monday when that—or Asian markets opened at the end of the weekend, prices spiked higher as you would expect after this kind of event. And then by mid, mid, you know, by the middle of Monday, we saw this kind of symbolic retaliation from Iran. And then Trump saying we've got a peace, we've got a ceasefire.","offset":3494,"duration":22},{"text":"Rory: ...deal. And then I think crude ended the day down $10. That was kind of my framework for what was expecting out of this conflict. And by that token, I had expected that, you know, it was very clear that Cuba was next up on on the list of kind of regimes to roll over. And I think Trump planned to be basically be rolling over on Cuba by now.","offset":3516,"duration":26},{"text":"Rory: And the wrinkle here is that if they were expecting some kind of Delcy Rodriguez character to emerge in Iran, someone to say—someone to give them the opportunity to declare victory. I think he would have. And I think that what we've seen so far is that the Iranians have not done that.","offset":3542,"duration":15}],"startTime":3281},{"title":"Tanker Insurance and Expectations of a Ceasefire","summary":"Rory explains that exorbitant marine insurance premiums and the lingering hope of an imminent ceasefire are keeping tankers from braving the blockaded strait.","entries":[{"text":"Rory: And I think if Trump expected the political culture of Venezuela to be the same as the political culture of Iran, that I think is probably arguably the biggest miscalculation here from the White House. As for what's actually preventing the, the, you know, the passage through the strait. Because again, when we look historically, the strait has never been closed.","offset":3557,"duration":27},{"text":"Rory: Even when we've had acute violence, acute attacks in the strait back in the 1980s during the Iran-Iraq war, during the tanker wars, we saw hundreds of ships hit. We saw by, by the calculations I saw was 450 ships attacked. Uh, you had 250 tankers attacked and 55 of those tankers were basically either sunk or scuttled and otherwise abandoned by crews. Like we more than we've already seen now. And during that time, you never had flow halt through the strait.","offset":3584,"duration":32},{"text":"Rory: So that was our best historical parallel and quite frankly, I expected something similar to be happening here. And what we've seen so far is that no, uh, very, very few—I mean the estimates vary, but basically like between a 90 and 95% reduction structurally now through the Strait of Hormuz.","offset":3616,"duration":26},{"text":"Rory: And with things like insurance, I think there was this expectation that okay, maybe at the beginning it was the lack of insurance. Uh, we were waiting for these, you know, these tanker owners to and the insurance...","offset":3642,"duration":19},{"text":"Rory: ...providers to figure out a way to say, okay, you know, we're going to figure out a way to lift—obviously the risk is increased, so we're cancelling coverage and we're going to kind of reinstitute. But, but there was just, you know, that never happened. You ended up actually seeing, and we've seen reports more recently that, you know, the war insurance has skyrocketed.","offset":3661,"duration":19},{"text":"Rory: If it was basically 0.25% of a vessel's value kind of in the month before the war, uh, that is now by the latest estimates that I've seen published by Bloomberg jumped to 5%. So we're talking a massive, massive increase. That's like a $5 million insurance premium on a million on a $100 million vessel just to cross the strait.","offset":3680,"duration":26},{"text":"Rory: But the issue is that even at those insane levels, the arbitrage value across the strait still seems to clear. That, you know, we now have effectively negative prices on the bad side of the strait, and we have on a physical basis on Dubai, over $150 a barrel. You can very easily cover that with this insurance.","offset":3706,"duration":24},{"text":"Rory: And they're not. And I think that is where something else is happening. And I think my best explanation for this, and I think it's also an explanation you're going to hear me talk about through the financial—the relatively sanguine financial impacts that we've seen so far, is that the market continues to expect—the base case expectation is that Trump backs out here.","offset":3730,"duration":25},{"text":"Rory: That we see another taco. And if that's the case, if there's the chance that tomorrow this ends, or at least he declares it done, um, why spend the $5 million and risk your ship...","offset":3755,"duration":26},{"text":"Rory: ...and crew if this could be over tomorrow. And I think there's this continual hope that this is going to end because, as we will talk about, the consequences of it not ending are so extreme that it is unthinkable to me that a US president would bear the political cost of what's coming down the pipe.","offset":3781,"duration":23}],"startTime":3557},{"title":"Economic Calamity of a Prolonged Strait Closure","summary":"Rory details the devastating consequences of a prolonged closure, explaining that losing 15 million barrels a day would require COVID-level demand destruction and spark a global economic calamity.","entries":[{"text":"Host (Eric): Well let's talk about that specifically next then. I think you and I could easily agree that—and I'll just go to an extreme here—if this continued for a year, if there was no transit or no significant meaningful transit of the Strait of Hormuz for a year, that would result in probably a bigger than 2008 global financial crisis because it would shut down the entire global economy. There's no energy, there's no economy. That's the end of the story.","offset":3804,"duration":26},{"text":"Host (Eric): Okay, if it's—you know, we can't go a year, but we could go into next week. Okay, how long is that fuse? What—are there tipping points where after a certain point things are broken that can't be fixed because the backlog is too long? What does the timeline look like of how long this can continue before you get into a situation where it's not reversible?","offset":3830,"duration":24},{"text":"Rory: The first thing I want to say Eric is I completely agree with you. I think that if this goes on for a year, and again, I cannot imagine—like the level of economic calamity, of human catastrophe that would wrought is unimaginable to me. I mean, we'll walk through it briefly here, because I think it's important to try and imagine it. But again, I just can't imagine the political—any politicians kind of engage, you know, bearing that political consequence.","offset":3854,"duration":27},{"text":"Rory: Because what we're talking about, to your point, like I mean, I'm normally not a guy that comes, you know, comes up with like big price calls. I typically, I don't like them. But like I've been saying that yeah, $200 crude is easy in this scenario. If we're, if we're talking a year or more, like 200 is the bare minimum of what you'd expect. We need to—I've been trying to parameterize what we're actually talking about. And...","offset":3881,"duration":142},{"text":"Rory: ...if let's say, just for this heuristic here, we talk about 20 million barrels a day of oil flow through the strait. Let's even just knock it down to 15 because maybe we get, you know, the East-West pipeline and Yanbu and everything else—everything works well with the Saudi diversion plan.","offset":4023,"duration":16},{"text":"Rory: Let's say 15. That is ballpark the peak of the demand destruction we experienced in March and April of 2020 during COVID when everyone was locked in their homes, you had not an airplane in the sky, you know, major airports were effectively shuttered. That's the kind of demand destruction we would be needing to balance that market.","offset":4039,"duration":25},{"text":"Rory: But with no pandemic, and just, just purely through price mechanisms. That is an extraordinarily high price to clear that kind of demand destruction. I've been basically just kind of saying that like, you know, me, I have an extraordinarily low price sensitivity for gasoline to get my kids to school in the morning.","offset":4064,"duration":20},{"text":"Rory: But a lot of people both in wealthy countries, obviously this, you know, it's going to be effectively a massive regressive tax. Um, but I think in wealthy economies we will generally experience this as a debilitating recessionary, you know, nigh depressionary price shock that will sap consumer spending, that will have all of the normal repercussions we would think about.","offset":4084,"duration":23},{"text":"Rory: But the price spike isn't enough, because you still need to shed that much demand from the global system. And where is that going to happen? It's going to happen in poorer emerging market countries in the Global South. That when we see price shocks, they will see shortages.","offset":4107,"duration":16},{"text":"Rory: Uh, we saw this in kind of notorious fashion now in 2022 when the kind of the infamous example of the—of the committed tanker to Pakistan that they broke their commitment, uh, they paid the breakage fee and they shipped that gas to Europe because they could make a, you know, a king's ransom on the arb even factoring for the breakage fee.","offset":4123,"duration":14},{"text":"Rory: And that's how markets are going to clear. That's how they're supposed to clear in this system. So I'm not saying that's wrong per se, but there is going to be an enormous human cost here. And I think when you're talking about these fuels, you're talking about electricity, you're talking about heat, you're talking about cooking. You're talking about life. And I think that's what we're going to have to try and trim back by 15 to 20% if this persists. And that is just insane.","offset":4137,"duration":28}],"startTime":3804},{"title":"Timeline Scenarios for Supply Chain Recovery","summary":"Rory provides near-term scenarios, warning that even an immediate ceasefire would leave months of supply chain chaos, while another three weeks could easily push Brent crude past $150.","entries":[{"text":"Host (Eric): Let's try to put some specific time frames on this, which I know is difficult and I apologize for doing this to you. But as you said, what's going on here is most people are thinking, well surely this is about to be over. I mean, it's—it's crazy to continue it, it's about to be over, it must be about to be over. Just in case it's not, let's imagine both a three-weeks-more scenario and a three-months-more scenario. What do each of those—if you had to guess—the impact of three more weeks, just like the last three weeks or however long this has been? And then three more months. What—what do those scenarios look like in your mind?","offset":4165,"duration":37},{"text":"Rory: So let's actually start with the even more sanguine scenario. What happens if it ends today? Because I think there's already durable damage. And I think a lot of people just assume that we could end this tomorrow and everything goes back to normal. We're probably talking three months minimum to, to re-normalize this system, even if it stopped today and every tanker currently in the Gulf made a break for it and they all made it out and we just resume full flow and everything like nothing ever happened.","offset":4202,"duration":28},{"text":"Rory: Even in that case, we're talking about months of supply chain recovery because these ships are being piled on top of each other. You've had—you've already had roughly a 400 million barrel gap or 330-340 million barrel gap that's emerged in the, basically the normal flow of oil into the Middle East, largely to Asia.","offset":4230,"duration":22},{"text":"Rory: Right now, we're still—we still haven't felt the brunt of that because three weeks ago, we still had tankers laden with oil leaving the Gulf. Those tankers will continue to their destinations, takes three, four weeks to get where they're going. And when that air pocket finally hits land in Asia, that's when we're going to start drawing inventories at 10, 15 plus million barrels a day.","offset":4252,"duration":23},{"text":"Rory: Which again, has never happened before. We've already seen Asian refineries attempt to short—basically frontrun this, to extend their runways. They've reduced operating rates, they've cut product output. So we are talking we've seen a $150 crude in Dubai in physical crude, but we've seen over $200 a barrel jet fuel in Asia...","offset":4275,"duration":19},{"text":"Rory: ...I mean Singapore. And I think that is, that alone would take months to sort out. But let's go to that three-week scenario. Okay, so let's say we're already in this for three weeks, let's say it's double. Now you're looking at two-thirds of a billion barrels of air pocket in the system that, again, needs to get sorted out.","offset":4294,"duration":18},{"text":"Rory: By that stage, we've already seen upwards of 9 million barrels a day of crude oil production capacity shut in through the Gulf. The longer that's off, the—the longer the strait is closed, the more we're going to see that cut back. And again, as anyone familiar with this industry, it's not trivial to shut in these wells, it's not trivial to get them back on without any kind of negative repercussions.","offset":4312,"duration":19},{"text":"Rory: And all that stuff just gets worse with time and time and time. I think, you know, in terms of price call, I think in three more weeks of this, I think we could—I think we would already be over $150 Brent. We're already obviously there at the kind of physical Dubai cash market.","offset":4331,"duration":15},{"text":"Rory: And I think people are like, well, well why wouldn't, you know, why wouldn't anyone buy that that crude? Uh, why wouldn't you just...","offset":4346,"duration":6},{"text":"Rory: ...buy buy WTI? It's like $50 or $60 cheaper. And the answer is that it's in the wrong place at the wrong time. You know, if you're buying the prompt WTI—WTI futures, it's not for delivery until next month, and you need to get it from Cushing to the coast, then you need to get it from the coast to the Middle East, to Asia. That we're talking months.","offset":4352,"duration":16},{"text":"Rory: People need these barrels today. And that is why I think there was still this kind of hopium, if you will, from Asian refinery saying, like, okay, this is going on, but like surely this can't last. And what you've started to see over the last couple days—there's a Bloomberg report this morning—where Asian refineries were starting to bid into the Brent basket.","offset":4368,"duration":20},{"text":"Rory: And they're starting to kind of try and buy these fut—these other barrels, which means that they're now worrying that this is going to be going on for months. Uh, and it also means that kind of acute local scarcity in crude in the Middle East and products in Asia is also going to begin spreading out to all the rest of the world.","offset":4388,"duration":17},{"text":"Rory: And I think it's really easy for Americans and the American president to say, ah...","offset":4405,"duration":5},{"text":"Rory: ...who cares about tight oil markets in the Middle East? We're here and oil prices are still pretty low. It's because this shockwave kind of moving out through the system takes time to kind of incentivize and bid all those barrels over. And I also think back to this why aren't ships going through, because they, you know, maybe they think Trump's going to taco.","offset":4410,"duration":19},{"text":"Rory: I also think that the futures market are in the exact same situation. What we saw not, you know, two Mondays ago, the, you know, the second weekend that again, everyone thought he was going to end on the weekend. He didn't. Prices spiked higher, you hit almost $120 barrel Brent. But then you got the first kind of Trump said the—the war's almost over, and prices cratered. You had a $35 a barrel intraday spread in Brent, which I don't believe has ever happened before.","offset":4429,"duration":29},{"text":"Rory: And a lot of traders kind of lost their shirts in that because again, bidding crude higher was the obvious directional call in this environment. But the kind of constant jawboning, you know, those people got blown out of their positions, many of them lost their jobs. People are much more wary now to kind of frontrun, because normally you'd expect futures markets to frontrun the tightness in physical markets because markets are forward-looking. But I think now we have to wait for that physical market tightness to kind of fully and aggressively manifest in the West before those future prices are going to actually converge.","offset":4458,"duration":40}],"startTime":4165},{"title":"Trump's Shifting Narrative and Escalating Retaliations","summary":"Erik and Rory discuss the president's shifting rhetoric regarding oil prices and the danger of escalating retaliatory strikes involving critical Iranian and Israeli infrastructure.","entries":[{"text":"Host (Eric): Now you said earlier that you thought the Trump administration had no idea that this outcome, which has already occurred, was even possible. I want to push back slightly on that and ask you if it's possible that maybe they did see it as a possibility, but just were not as concerned by it as you and I are. I want to read you a Truth Social post from President Trump on Wednesday where he says, \"I wonder what would happen if we finished off what's left of the Iranian terror state and just let the countries that use the Strait of Hormuz—we don't—let them be responsible for the so-called strait. That would get some of our non-responsive 'allies' in quotes engaged and fast,\" signed President Donald J. Trump.","offset":4498,"duration":48},{"text":"Host (Eric): It sounds to me like he doesn't think it's a big deal for the United States since he perceives the United States to be energy independent, that if the Strait of Hormuz is closed down, it sounds like he thinks that's a problem that affects other countries but doesn't affect us. So, you know, the hell with it, let them worry about it. I don't—I'm not going to bother asking you whether we should be concerned about it, because I think you and I agree that we should be concerned about the strait needs to be open uh, for the sake of global commerce. Oil prices are set globally and so forth. But it does seem like there's room that the reason the president's not so concerned about this outcome is not that he didn't foresee it, but that he's just not as worried about it as you and I are.","offset":4546,"duration":49},{"text":"Rory: I think there's a chance of that, and I—I think again, I didn't expect him to go this far. So I'm—I can't pretend perfect knowledge of Trump's mind by any means. But I think what we've seen in those comments over the past two and a half weeks now is evidence of remarkable goal shifting.","offset":4595,"duration":16},{"text":"Rory: We had that—we had that tweet this week. End of last week, we also had the tweet about how actually high oil prices are good for the United States because the United States is the largest oil producer in the world. But that contrasts strongly with some of the earlier comments out of Trump about, you know, basically don't be a panicking, don't bid up the price of oil, you know, this is going to be fine, the war's almost over.","offset":4611,"duration":18},{"text":"Rory: Like it definitely felt like he was trying to keep the oil prices lower. And then as oil prices started to inevitably, based on this kind of physical reality we've been discussing, as those prices started to grind higher, he started to find new ways to say, oh, okay, this is actually good for us.","offset":4629,"duration":17},{"text":"Rory: And I actually think in some ways, that's actually the most worrying development in this because I think at least my mental framework here has always been that the oil market would be the single—the singular thing that would end up pushing Trump back from the edge, from really going through for a prolonged period of time, months or or longer.","offset":4646,"duration":21},{"text":"Rory: And if we're starting to see him attempt to, to change that narrative to almost convince himself—and again, like Donald Trump is an extremely public person. He's been for—he's been against high oil prices and...","offset":4667,"duration":13},{"text":"Rory: ...trying to drive them lower since the 1980s. Like low oil president is kind of like his brand. And I would say that—so I don't know how much I can really buy this. I don't even know how much he can really buy this depending how long this goes. I still think his core bias is towards low oil prices.","offset":4680,"duration":19},{"text":"Rory: Again, he was elected as kind of a pocketbook cost of living president. And I think this is just—he was also elected as a president that would get out of wars in the Middle East. But we're very—we're obviously in a very, very different timeline now from that election.","offset":4699,"duration":16},{"text":"Rory: So again, I think there's a possibility that you're right, you're right Eric. But I do think that a lot of this is him saying things after things don't go his way. For instance, the comment about the strait came mostly after he asked all of the kind of allied NATO nations and Asian nations that consume the oil to kind of come help them, and they were kind of like, no.","offset":4715,"duration":18},{"text":"Rory: Because again, I think the world, a lot of the consuming world, like I think if they knew 100% that this was going to go on for years, yeah, they're going to send their navies because again, this is untenable. But I think there's this worry, I think there I even heard this worry initially with the SPR releases, that like anything you do to ameliorate the oil price consequence to a degree short-circuits Trump's own feedback mechanism.","offset":4733,"duration":37},{"text":"Rory: That the only way he was going to back down—and this is a similar to the tariffs, that when you know the S&P was crashing, that's when he tacoed. There was an expectation that this was the same mechanism that would be seeing now but with oil. And I worry that is beginning to lose its sensitivity given that I think now it's a question of how can Trump figure out a way to declare victory? Because again, he's not going to stop this unless he can say he won. So I think he's trying to find ways, trying to find something that he can declare victory on.","offset":4770,"duration":27},{"text":"Rory: And again, I thought at the beginning, there was enough at the—at the gate...","offset":4797,"duration":4},{"text":"Rory: ...right? We wiped out the leadership, you killed the Ayatollah, all of this stuff. I think he could have declared victory on that first Monday. And I think he's like, oh, well, let's do this a little bit longer. And now we're in so deep that it feels like you need something much bigger.","offset":4801,"duration":15},{"text":"Rory: And if anything, the Iranian regime seems to be entrenching. At the beginning, you did hear—I mean, when there was a lack of centralized leadership, you had different elements that were being more negotiating or kind of conciliatory. And that it seems is beginning to fall by the wayside.","offset":4816,"duration":17},{"text":"Rory: And I think even for a while there was some hope that the number of missiles and drones that were being launched every day by Iran were dwindling over time. Like oh, is Iran running out of missiles? Are we entering the endgame?","offset":4833,"duration":11},{"text":"Rory: And over the last two days, they've shot back up. That—and again today in particular—we we were chatting about this before we started recording, but like Brent popped above 110 following Israel's attack on the South Pars gas field, which up until now we hadn't been hitting...","offset":4844,"duration":16},{"text":"Rory: ...upstream and kind of Iranian oil assets, oil and gas assets specifically. And that's why up until now, most of that production assets hadn't been hit. You've had—you had a couple refineries hit. You had Ras Tanura, you had—you've had attacks on Fujairah. But overall, there are a lot more targets across the Middle East that were very, very tempting targets. I mean, we all remember Abqaiq in 2019. Clearly the Iranians can hit it.","offset":4860,"duration":29},{"text":"Rory: They have chosen not to yet because it—again, for them, I think that they still have this conception of different degrees of escalation. And what we saw already was as soon as the South Pars gas field was hit, they were like, okay, now these bunch of petrochemical facilities and upstream facilities, they're all legitimate targets now.","offset":4889,"duration":24},{"text":"Rory: And they also warn that if Trump bombed Kharg Island, they're like, well, if you do that, then we view all other ports in the region as fair game. I think they are still trying to kind of parameterize their own escalation or retaliatory kind of spiraling here.","offset":4913,"duration":11},{"text":"Rory: But, and again, I think what we've seen so far is that in both cases where Israel and to my knowledge, these were both Israeli attacks specifically on the South Pars gas field and the fuel depot in Central Tehran, that those were kind of against the wishes of the White House.","offset":4924,"duration":16},{"text":"Rory: That, you know, there is still some kind of freelancing here on the Israeli side about like how far they're going to go and how much they want to escalate this. Clearly they want—they want more escalation, right? I think that's clear than what we've seen so far.","offset":4940,"duration":13},{"text":"Rory: But I do wor—I do wonder whether or not that's the kind of thing that's going to piss off Trump, quite frankly. We—we saw this, uh, he got really upset with the Netanyahu government last June when, you know, there was worry that they weren't going to play ball with the ceasefire or whatever else. There was like that famous comment uh, as he was trying to get on Marine One. But I do worry that that's the kind of situation we're ending up in now.","offset":4953,"duration":23}],"startTime":4498},{"title":"Dislocated Benchmarks and Physical Market Squeezes","summary":"Rory explains the severe price dislocation between global benchmarks like Brent and WTI compared to desperate physical market squeezes driving localized crude and jet fuel prices much higher.","entries":[{"text":"Host (Eric): Normally, Rory, people who are in macro markets and, you know, investors...","offset":4976,"duration":5},{"text":"Host (Eric): ...who are not specialists in oil only pay attention to two benchmarks. Brent crude, which is based on North Sea oil production, is the global benchmark and then West Texas Intermediate is the US benchmark. Uh, normally it's only professional oil traders who pay attention to any of the other prices in the oil market.","offset":4981,"duration":20},{"text":"Host (Eric): Let's talk though about some of the other prices, because really Brent and WTI only got—I guess WTI was 119. Neither one of them has gone above 120 in this. That's, uh, you know, they've gone up a lot, but they haven't gone up that much. I think it was Oman traded above 185 this week? Uh, as you said, there was jet fuel prices above 200 in Singapore.","offset":5001,"duration":25},{"text":"Host (Eric): Should we be thinking about these really high prices that are occurring in some localized markets as oh well, that's just a logistics thing, it doesn't really count? Or are those price signals that could portend what's coming for Brent and WTI?","offset":5026,"duration":15},{"text":"Rory: They're exactly what's coming for Brent and WTI. Because I think I've kind of talking around this point a little earlier, but what we're talking about right now is again, the—these markets, and you will know this well Eric, that futures and benchmarks, there is both a locational element to it and a time element.","offset":5041,"duration":19},{"text":"Rory: And where the current tightest market is right now is basically there's all these laden tanker or unladen tankers waiting to go back into the Gulf to fill up. And they're like, well, I could buy some crude off the coast of Oman and just basically turn around and head back.","offset":5060,"duration":16},{"text":"Rory: But those are the barrels that are at $150 or 100—I hadn't honestly seen Oman go up to 1—180. But yeah, that's basically, yeah, you can charge a king's ransom for any barrel that's physically available on the good side of the Gulf right now because that's where crude is in desperate, desperate supply because it's much faster to get to Asia from there than from the US Gulf or from the North Sea.","offset":5076,"duration":23},{"text":"Rory: And I think that is what we're going to see eventually for the other benchmarks. That now that Asian buyers in particular are coming to the realization that this isn't ending tomorrow and that they may need to cover not just today's crude slate but tomorrow's or next month's crude slate.","offset":5099,"duration":20},{"text":"Rory: Now they are beginning to bid on those other contracts, which again, is why we're starting to see Brent firm up so much more. That we're kind of back to above 110. WTI I think has some other potential weirdness going on. There's been a lot of talk about atte—you know, participants trying to hedge their SPR exchanges. Lots of stuff going on there as well.","offset":5119,"duration":22},{"text":"Rory: But I do think overall, the best thing that explains WTI's relative underperformance relative to Brent and certainly relative to the Middle Eastern grades is that the furthest grade away. That takes the longest to get to where you're going. And I think that's going to be something that will continue to kind of leave WTI at the back of that—of that bus, if you will.","offset":5141,"duration":19}],"startTime":4976},{"title":"The Looming Risk of US Export Controls","summary":"Rory warns of a looming political risk that the US administration might implement export controls on refined oil products to combat surging domestic pump prices.","entries":[{"text":"Rory: The other thing we haven't talked about yet, and I think where I'm especially concerned that we could be going. Because again, Trump says this is good, he doesn't care. But eventually pump prices are going to rise. We already have US average diesel prices over $5 a gallon. Gasoline's coming up there too. Diesel's going to go higher, jet fuel's going to go higher.","offset":5160,"duration":19},{"text":"Rory: I worry that we're going to see kind of a rediscussion or we've already seen musings about export controls out of the United States. That this was actually something that the Biden administration mused in 2022. They're like, well, well, could we restrict or ban the export of refined products?","offset":5179,"duration":17},{"text":"Rory: There are a lot of issues with that. It bottles up diesel in the Gulf Coast, it, it, it creates issues with potential res—reciprocal trade restrictions if then Europe decides to ban the export of gasoline to into the East Coast. There's a lot of problems there. But I do think that's where this could go.","offset":5196,"duration":17},{"text":"Rory: And I think particularly, you're seeing some of that like the framework and the kind of precursor to that argument being put out by Trump. And I think back to that question of he's saying we don't get any oil from this strait, so what do we care? And then your point, well, because markets are global. The way to solve that is to make markets not global.","offset":5213,"duration":21},{"text":"Rory: And I think that is my—is my most acute worry here going into this, is that I'd mentioned earlier that, you know, wealthy nations largely will be able to afford the oil and the products. It'll just be debilitatingly expensive.","offset":5234,"duration":13},{"text":"Rory: Once you start mucking with trade, even the United States, which is a net petroleum exporter, we you well know that that's not the same in crude or quality. That's not same in product slate by region. You've even seen the—the repeal or at least temporary waiver of the Jones Act, which is a very substantial political move for the White House.","offset":5247,"duration":20},{"text":"Rory: That really makes the most sense in the context of well, what if we ended up, you know, banning exports? Well then we could use non-Jones Act tankers to move US Gulf Coast crude to different area or US Gulf Coast oil, but also diesel to other areas of the country rather than it being bottled up.","offset":5267,"duration":12},{"text":"Rory: Because if you have no ability to shift out from those regions...","offset":5279,"duration":1},{"text":"Rory: ...you would basically end up forcing US crude production shut-ins and US particularly Gulf Coast refining shut-ins, which is the opposite of what you want. So temporarily it would lower prices, and I think that's why it would be very attractive for the White House. But in the long term, it would short-circuit wealthy markets' capacity to just pass this on through price. And then we would likely end up facing physical shortages in these advanced markets.","offset":5280,"duration":28}],"startTime":5160},{"title":"Fertilizer, Food Prices, and Severe Inflation","summary":"The conversation highlights how the disruption will ripple into fertilizer and global agriculture, causing food shortages and severe consumer inflation that could dwarf the 1970s.","entries":[{"text":"Host (Eric): Rory, when we hear about the Strait of Hormuz, what comes to investors' minds is of course crude oil. But tell me about how fertilizer plays into this story as well.","offset":5308,"duration":11},{"text":"Rory: Yeah, so I am not a fertilizer expert, but in addition—I mean, we've all been focused on oil and maybe gas, but there's a lot of other things that come from the Gulf, whether it's fertil—I think it's a third of global fertilizer supplies, the vast majority of global helium supplies. All these things are going to have their own knock-on consequences to all these other markets as well.","offset":5319,"duration":13},{"text":"Rory: I think when you think about fertilizer and even I think this ties back into to oil products as well, if this continues...","offset":5332,"duration":8},{"text":"Rory: ...we will see crop yields decline. We will see food production decline. We will see the food that does get to your plate more expensive on the commodity basis of the food itself, and being shipped there by either by truck or by plane at far more expensive rates.","offset":5340,"duration":15},{"text":"Rory: So this is absolute—I mean, again, this is, you know, our most recent experience here with—and again a where all this goes with monetary policy as well. Our most recent kind of parallel is 2022 that central banks got acutely—and I think reasonably—freaked out at the time by the explosion of inflation coming out of the COVID bullwhip effect.","offset":5355,"duration":23},{"text":"Rory: And for the first time in my life, central banks took a—took a keen interest in following the price of oil, and particularly the price of gasoline. And that's when I think the way this all feeds back into the macro side is this—you know, if there's anything that is going to unmoor long-term consumer inflation expectations, it's this kind of shock.","offset":5378,"duration":22},{"text":"Rory: It's, you know, this last time we experienced this would have been in the '70s. This shock, if continued, will make the '70s look like child's play. I think a lot of people still go back and think wow, we must have lost a massive amount of supply back in '73 or '79.","offset":5400,"duration":17},{"text":"Rory: And there were some losses, but the losses were relatively small. And the big thing was it was more of a logistical like we're not shipping to you, so that's causing gaps here and everything else. But a lot of it was, you know, the supply wasn't acutely lost to the degree that we are currently seeing it lost today.","offset":5417,"duration":17},{"text":"Rory: And it just sets us up for a much worse kind of price shock. And again, I think going back to this like even if this ended today, we're co—we're sewing the seeds of these like deep ripple effects, these deep kind of multi-industry bullwhips that are going to be working through the system. That even if you ended today, we're still going to have consequences trailing out for months.","offset":5434,"duration":20},{"text":"Rory: And if we and if this goes three weeks longer or heck, as you mentioned, three months longer, oh man, like these industries are going to break...","offset":5454,"duration":6},{"text":"Rory: ...and people will need to cut back. There will be physical losses that people will have to experience. And that's where I go back to. I don't see this as tenable long-term politically for anyone involved. But I also thought that so far and I've been wrong.","offset":5460,"duration":18}],"startTime":5308},{"title":"Desalination Vulnerabilities and Interview Outro","summary":"Erik clarifies a prior point about the vulnerability of Middle Eastern desalination plants to Iranian retaliatory strikes before Rory provides his contact information to wrap up the interview.","entries":[{"text":"Host (Eric): Rory, I can't thank you enough for a terrific interview. Before we close, I want to add a quick point just of clarification about last week's interview with Dr. Anas Alhajji. Several of you on Twitter and in email said, \"Hey, Anas was wrong when he said that Iran had a huge vulnerability if their desalination plants were attacked. Iran only gets 3% of their water from desalination.\"","offset":5478,"duration":25},{"text":"Host (Eric): I agree it was a little bit ambiguous how it was worded, but that was not Dr. Alhajji's intended point. The point that he was making is everybody presumes that Israel has a nuclear weapon and Iran doesn't. His point was Iran effectively does have a nuclear option which is the other Gulf states. Not Iran, which only needs to rely on desalination for 3% of its own water, but the other Gulf states, including Israel, are heavily dependent on desalination. So it is the risk of Iran striking the desalination plants of Israel and other countries that would be the equivalent of a nuclear escalation and would probably result in Israel responding with a nuclear response. So that was the point that Dr. Alhajji was making.","offset":5503,"duration":46},{"text":"Host (Eric): Rory, I want to come back to what you do at Commodity Context for anybody who's not familiar with it. Terrific website. Please give us your Twitter handle and tell people what they can expect to find at commoditycontext.com.","offset":5549,"duration":12},{"text":"Rory: Thanks so much for having me again Eric. I always love coming on the show. You can follow me on Twitter at uh, @Rory_Johnston. And all of my public research is published at commoditycontext.com. We've got an—the Oil Context Weekly report every Friday that covers—I currently call it the Oil of the—the Oil and Iran War Context Weekly because that's all we're talking about.","offset":5561,"duration":18},{"text":"Rory: But every Friday at 4:00 to 5:00 p.m. Eastern, uh, I publish three monthly uh, data reports on OPEC, global balances, and North American detailed balances. And then I also am doing particularly these days, a lot of thematic work on Iran, on Venezuela, and the overall insanity in this current oil market. And I encourage you to join me.","offset":5579,"duration":23},{"text":"Host (Eric): Patrick Ceresna and I will be back as MacroVoices continues. And stay tuned, folks. Case you didn't connect those dots, Simon White told me earlier in this podcast that we needed to worry about food price inflation next. That was even without considering the fertilizer angle that I just discussed with Rory. So Patrick's trade of the week is going to be about food inflation and how to hedge against it. That's coming up next right here at macrovoices.com.","offset":5602,"duration":31},{"text":"Host (Eric): Now back to your hosts, Eric Townsend and Patrick Ceresna.","offset":5633,"duration":7}],"startTime":5478},{"title":"Post-Game Analysis: Equities Outlook and Technicals","summary":"In the post-game segment, Erik and Patrick discuss the binary nature of the equity market's outlook based on the duration of the Iran conflict, noting clear technical signs of market distribution.","entries":[{"text":"Host 1: So if you think that the Trump administration has this whole situation completely under control, it's going to be over in another week or so, just like the President and Secretary Hegseth say it's going to be, then in that case, if that's what you think, then this is a terrific buy-the-dip setup. It probably sets the stage for a rally to new all-time highs.","offset":5640,"duration":26},{"text":"Host 1: If President Trump can really get this all under control and wrap it up and there's no lasting impact from it—and to be sure, in order for there to be no lasting impact, it really needs to get wrapped up pretty quickly here—if you think that's what happens, then it's time to buy this dip and buy it in size because we're going much higher.","offset":5666,"duration":18},{"text":"Host 1: On the other hand, if you don't think that, if you think that the Trump administration has started a fire that they won't be able to put out and that this is not under control and that this Iran conflict might turn into a repeat of the Iraq debacle that began in 2003, well, if that's what you think—because we're leaving my politics out of this one—that would portend a very, very different equity market outcome.","offset":5684,"duration":28},{"text":"Host 1: We could easily be looking at a cyclical bear market, and the worst case would be if oil transit through the Straits of Hormuz stays impaired for many months. In that scenario, without exaggeration, it could lead to an oil price surge well over $250 a barrel. That would cripple the global economy and lead to a global financial crisis on the scale of, if not bigger than, 2008.","offset":5712,"duration":30},{"text":"Host 1: Now, I strongly doubt that that would be the outcome because this is a problem that can be solved sooner than that. We're not going to see the Straits of Hormuz closed for years or anything like that.","offset":5742,"duration":12},{"text":"Host 1: The question is how long this goes on, how much damage it causes, and how long it takes to unwind that. In other words, how big is the backlog of global logistics that have been disrupted by the Straits of Hormuz closure? How long does it take to get things back to flowing as normal again?","offset":5754,"duration":19},{"text":"Host 1: That's really, I think, what's going to drive equity prices, and frankly, I don't think anybody knows for sure what's coming next in this market. So it really comes down to your geopolitical outlook. I think all of us are vulnerable to allowing our personal politics to bias our judgment as investors. So remember, this market reaction is not going to depend on what you think or what I think should happen. It's going to depend on what actually happens, and I don't think any of us know with any real certainty exactly how this is going to play out.","offset":5773,"duration":34},{"text":"Host 2: Eric, I'm going to keep my analysis very simple from a technical perspective. We're remaining below the 50-day moving average, we're breaking lower highs and lower lows, there is clear distribution. The bears are in control and in the driver's seat on the short term on the distribution side. We continue to see all rallies failing at Fibonacci zones, which is all indicating that generally the distribution cycle is still in play.","offset":5807,"duration":28},{"text":"Host 2: Now, while we have seen substantial increases in bearishness as the sentiment is pivoting, we've seen huge spikes in volatility index and other things that are signs that you typically would see from oversold conditions. But right now with enough of this global uncertainty here, this could be an overhang that keeps this market distributing.","offset":5835,"duration":25},{"text":"Host 2: Now, Eric, we certainly can't rule out that at some point the bulls will reverse this and counter-trend it. This is again the environment where hedges are critical, and we've talked about them the last couple weeks with our listeners, and I continue to advocate that portfolio insurance here makes a whole lot of sense. All right, Eric, let's talk about that US dollar.","offset":5860,"duration":28}],"startTime":5640},{"title":"Evaluating the US Dollar Flight-to-Safety Rally","summary":"The hosts analyze the US Dollar Index testing the 100 level, observing that the current strength is largely driven by a flight to safety and structural weakness in the Euro.","entries":[{"text":"Host 1: Now, Patrick, by recording time we were back down to a high 99 handle after surging above 100 and then below 100 intraday on Friday. I think by the cash close we were back over 100 again. So we're right on that hairy line between 99 and 100.","offset":5888,"duration":18},{"text":"Host 1: The question to ask is whether we're topping out here at overbought resistance on this technically overbought market or if the strength that we've seen in the dollar so far is just the beginning of a new bullish trend. Once again, I think the answer depends on your geopolitical outlook. Sorry folks, that's going to be the answer for most things this week, and there are plenty of strong arguments to be made in either direction.","offset":5906,"duration":25},{"text":"Host 1: I don't see any fundamental bullish drivers for the dollar here other than the flight to safety trades into the dollar, which are only going to intensify if the situation in Iran worsens from here and if equity markets take a nosedive.","offset":5931,"duration":19},{"text":"Host 1: So there's plenty of room for much, much more upside in the Dollar Index. But ultimately, I think that upside would be driven by flight to safety trades in the Iran conflict. Someday when the Iran conflict wears off or winds down, then I think it becomes a bearish... it's time to sell the dollar there because I think it will be overbought and ripe for a major correction, maybe resuming the primary downtrend that was in play before this conflict arose. The question is timing: how much longer before this Iran conflict is over? Whenever it's over, that's the time I think you want to sell the Dollar Index.","offset":5950,"duration":40},{"text":"Host 2: Well, Eric, when looking under the hood of the dollar, the key thing is to observe that the predominant weakness is coming from the Euro and the Yen, which happen to be very large weightings in the Dollar Index. But the story isn't the US dollar strength and all cross-currencies weakening against it.","offset":5990,"duration":22},{"text":"Host 2: We continue to see resilience in a lot of the commodity-based currencies like the Aussie dollar and the Canadian dollar, and that Euro is really where the drag is as there continue to be growth concerns at a time when obviously their energy prices are under a lot of pressure, which is stressing the Euro right now on the downside.","offset":6012,"duration":22},{"text":"Host 2: If we see Euro breaking some of these key levels, that then is going to be a huge bullish tailwind for this Dollar Index. Now we're at the top of an almost a 10-month trade range, and if the Dollar Index makes any progress above this 100 level with momentum, we've got ourselves some sort of a strong US dollar counter-trend move. And so we have to watch whether or not this gains momentum from here. All right, Eric, let's touch on crude oil.","offset":6034,"duration":30}],"startTime":5888},{"title":"Crude Oil's Continued Upward Pressure","summary":"Erik reiterates the logistical nightmares driving crude oil prices higher, warning that a continued surge could trigger a vicious cycle of global economic consequences.","entries":[{"text":"Host 1: Well, as I already discussed with Rory Johnston, the Oman benchmark traded over $180 this week. Obviously, logistic complications are part of that, but it's still an important price signal.","offset":6064,"duration":12},{"text":"Host 1: I'm sorry to sound like a broken record folks, but it's the geopolitical outcome with Iran that's going to drive everything. As Rory Johnston said, I think it would be foolish to assume that, hey, it's going to be just a couple more days and the Trump administration is going to completely end this thing.","offset":6076,"duration":19},{"text":"Host 1: Even if it ends this week, we still have probably a couple of months at minimum just to clear the system out and get things back to flowing as usual. And the longer that the conflict wears on, the more that effect is compounded and the more of a mess we're going to have to unwind.","offset":6095,"duration":17},{"text":"Host 1: So the longer this continues, the more it's going to affect oil prices and cause a continued increase in oil prices and the inflation signal that that drives. And eventually, it becomes a self-reinforcing vicious cycle of increasing inflation driving even more extraction cost price increases, higher oil prices, and so forth. Hopefully, we don't get to that point where that self-reinforcing cycle kicks in.","offset":6112,"duration":29}],"startTime":6064},{"title":"Gold Market Technicals and Consolidation Phase","summary":"Patrick details the technical breakdown of gold below its 50-day moving average, suggesting it may face a prolonged consolidation phase before marching to new highs.","entries":[{"text":"Host 2: All right, let's move on to gold here because we just got ourselves a little bit of a down day here on Wednesday. What's your take of what's going on?","offset":6141,"duration":8},{"text":"Host 1: The low print on the January 30th correction was 44.23, 4423. That was a near perfect test of the 50-day moving average at the time. But that happened in the middle of the night in very thin liquidity.","offset":6149,"duration":12},{"text":"Host 1: So something I said right here on MacroVoices just a few days later was we should watch for another test of the 50-day moving average during regular trading hours, not extended trading hours. Well, we got that on Wednesday, and it also coincided almost perfectly with the 38.2% Fibonacci retracement level of that January 30th correction. There was also a trendline there as well.","offset":6161,"duration":25},{"text":"Host 1: So three major support lines all broken at the same time. So there's a very good technical argument that could be made here, which is that that regular trading hours test of the 50-day moving average was the buy signal. The bottom could be in already.","offset":6186,"duration":15},{"text":"Host 1: Except we went right through it and we're trading considerably below it at recording time. I'm looking at 48.24 as we're recording right now, selling off more in futures trading after the close. These are all ominous signs and frankly, there's not a lot of obvious support until we get to the 100-day moving average at 45.91, 4591.","offset":6201,"duration":45},{"text":"Host 1: So I think we're probably headed in that direction unless there's a sudden change in the fundamentals. But it's also clear that there's been a breakdown of correlations between precious metals and the usual, you know, if it's increase in tension in Iran, more geopolitical upset, that would normally be up on precious metals.","offset":6246,"duration":21},{"text":"Host 1: That broke down on March 2nd. Gold is not trading up on geopolitical escalation the way it was before March 2nd, and frankly, I've yet to hear a really good explanation for why it isn't. So I don't pretend to know what comes next, but it sure looks to me like we might be headed towards a 45 handle, if not lower. That's the next obvious support level below the current market.","offset":6267,"duration":23},{"text":"Host 1: So either we get a bounce here and the 50-day really was the trading signal that it should have been, or if we continue to see this weakness below the 50-day continue through the day on Thursday, I think we're probably headed down to 45.91, maybe 4600 on the 100-day moving average by the time we get there.","offset":6290,"duration":19},{"text":"Host 2: Well, Eric, my view on gold has remained unchanged for the last month. After we saw that key blow-off top on gold and that huge reversion, typically if we look at the last four consolidations of gold, it took as much as two to four months of gold consolidating before it attempted to break to fresh new highs.","offset":6309,"duration":25},{"text":"Host 2: At this stage, that analog is the one that we continue to see here on gold as we saw some retesting of highs and this sideways consolidation continuing overall. After this consolidation finishes, there's lots of room for gold to go higher, but at this stage I think it'll be deeper into the second quarter before we see a meaningful turn up.","offset":6334,"duration":24},{"text":"Host 2: How low could this gold correction go? Well, the first level to watch on the support side is this 4800 level we're trading down to right now, which is a Fib zone of this retrace. If that doesn't hold, I mean there is always the possibility we head back down toward that 4500 level and $4400 level below, but if that was to happen, that would probably be a compelling buy on dip to take advantage of. All right, Eric, what are your thoughts here on the fact that Uranium continues to just consolidate sideways inactively?","offset":6358,"duration":35}],"startTime":6141},{"title":"Uranium's Resilience and Copper's Odd Correlation","summary":"The hosts observe the structural resilience of uranium miners amid the broader market selloff and puzzle over a strange, tick-by-tick correlation between copper and gold.","entries":[{"text":"Host 1: Well, Patrick, the fundamentals are uber bullish and they're only getting better by the day as we see more and more nuclear announcements. The nuclear renaissance is on and it's on strong.","offset":6393,"duration":13},{"text":"Host 1: And the market for Uranium and Uranium miners is holding up pretty darn well considering how bad everything else is going. We didn't see as big of a downside as I was fearing we might see on the Uranium stocks on Wednesday.","offset":6406,"duration":17},{"text":"Host 1: We're still looking at 49 spot 05 at the close on Wednesday on the URA ETF, which is the one that's most followed. That's still well above its 200-day moving average, whereas the indices have moved below their 200-day moving averages. But frankly, I think it's headed for its 200-day moving average, which is at 46 spot 03.","offset":6423,"duration":20},{"text":"Host 1: So we'll see what happens next. Broad market risk-off event is obviously going to take everything else down with it, including the Uranium miners. I think it just sets up better and better buy-the-dip opportunities. The question is how big is the dip before it's time to buy Uranium? I think the next obvious target is 46.03 on the URA ETF. But let's see what happens with the broader risk markets because if we get an outright market crash here, as could happen if oil prices continue to rise, particularly if they spike over $150 setting new all-time highs—at least on the major indices, we're already there with some of the other markets around the world, but if we get there on Brent and WTI above 150, that probably brings on an outright crash in equity markets and anything could happen.","offset":6443,"duration":50},{"text":"Host 2: Well, structurally the chart remains bullish. All consolidations are being held: higher highs and higher lows. But it's just been a quiet period, maybe the lack of liquidity in the broader asset markets could be just keeping this all contained. But overall the charts are still on the bull trend and at major support levels.","offset":6493,"duration":25},{"text":"Host 2: Now, Eric, I want to focus in on some bizarre price action that we've seen in Copper when it's overlaid on Gold. Now typically precious metals trade in correlation and a lot of times these industrial metals tend to march to their beat of their own drum independently.","offset":6518,"duration":34},{"text":"Host 2: But when I here show an overlay of the Gold and Copper charts, for some odd reason Copper, almost day by day, tick by tick, has actually been correlating with Gold. Now why? I really actually don't have an explanation. It's and I certainly don't know whether this will continue, but certainly as of this moment when we're looking at this chart, it's undeniable that right now Copper is just trading tick by tick with Gold. I'm very curious to see whether or not this trend continues in the weeks and months to come.","offset":6552,"duration":50}],"startTime":6393},{"title":"10-Year Treasury Yields and Podcast Outro","summary":"Patrick briefly notes the 10-year Treasury yield's upward push post-FOMC before wrapping up the episode with standard podcast disclaimers and promotional announcements.","entries":[{"text":"Host 1: Patrick, before we wrap up this week's podcast, let's hit that 10-year Treasury Note chart.","offset":6602,"duration":4},{"text":"Host 2: Well, we've seen here is that it's trading right up toward the 2.30 level. We had the FOMC meeting and the first reaction after the post-FOMC was yields rising up to their one-month ranges or multi-month ranges. It'll be very interesting to see whether this has started a new follow-through and we see yields push higher from here or whether this was going to just a fake-out retest of the highs.","offset":6606,"duration":28},{"text":"Host 1: Folks, if you enjoyed Patrick's chart decks, you can get them every single day of the week with a free trial of Big Picture Trading. The details are on the last pages of the slide deck or just go to bigpicturetrading.com. Patrick, tell them what they can expect to find in this week's Research Roundup.","offset":6634,"duration":15},{"text":"Host 2: Well, in this week's Research Roundup you're going to find the transcript for today's interview, you're going to find the slide deck that was put together by Simon White, and you'll find the Trade of the Week chartbook we just discussed here in the post-game, including a number of links to articles that we found interesting.","offset":6649,"duration":20},{"text":"Host 2: You're going to find this link and so much more in this week's Research Roundup. That does it for this week's episode. We appreciate all the feedback and support we get from our listeners and we're always looking for suggestions on how we can make the program even better.","offset":6669,"duration":17},{"text":"Host 2: Now, for those of our listeners that write or blog about the markets and would like to share that content with our listeners, send us an email at researchroundup@macrovoices.com and we will consider it for our weekly distributions.","offset":6686,"duration":15},{"text":"Host 2: If you have not already, follow our main account on X at @macrovoices for all the most recent updates and releases. You can also follow Eric on X at @EricSTownsend, that's Eric spelled with a K, and you can also follow me at @PatrickCeresna. On behalf of Eric Townsend and myself, thank you for listening and we'll see you all next week.","offset":6701,"duration":19},{"text":"[Music playing]","offset":6720,"duration":6},{"text":"Host 3: That concludes this edition of MacroVoices. Be sure to tune in each week to hear feature interviews with the brightest minds in finance and macroeconomics. MacroVoices is made possible by sponsorship from bigpicturetrading.com, the internet's premier source of online education for traders.","offset":6726,"duration":23},{"text":"Host 3: Please visit bigpicturetrading.com for more information. Please register your free account at macrovoices.com. Once registered, you'll receive our free weekly Research Roundup email containing links to supporting documents from our featured guests and the very best free financial content our volunteer research team could find on the internet each week.","offset":6749,"duration":22},{"text":"Host 3: You'll also gain access to our free listener discussion forums and research library. And the more registered users we have, the more we'll be able to recruit high-profile feature interview guests for future programs. So please register your free account today at macrovoices.com if you haven't already.","offset":6771,"duration":17},{"text":"Host 3: You can subscribe to MacroVoices on iTunes to have MacroVoices automatically delivered to your mobile device each week free of charge. You can email questions for the program to mailbox@macrovoices.com and we'll answer your questions on the air from time to time in our mailbox segment.","offset":6788,"duration":20},{"text":"Host 3: MacroVoices is presented for informational and entertainment purposes only. The information presented on MacroVoices should not be construed as investment advice. Always consult a licensed investment professional before making investment decisions. The views and opinions expressed on MacroVoices are those of the participants and do not necessarily reflect those of the show's hosts or sponsors.","offset":6808,"duration":22},{"text":"Host 3: MacroVoices, its producers, sponsors, and hosts Eric Townsend and Patrick Ceresna shall not be liable for losses resulting from investment decisions based on information or viewpoints presented on MacroVoices. MacroVoices is made possible by sponsorship from bigpicturetrading.com and by funding from Fourth Turning Capital Management, LLC. For more information, visit macrovoices.com.","offset":6830,"duration":29},{"text":"[Music continues]","offset":6859,"duration":15}],"startTime":6602}],"entries":[{"text":"Host: This is MacroVoices, the free weekly financial podcast targeting professional finance, high net worth individuals, family offices, and other sophisticated investors. MacroVoices is all about the brightest minds in the world of finance and macroeconomics, telling it like it is. Bullish or bearish, no holds barred. Now here are your hosts, Erik Townsend and Patrick Ceresna.","offset":0,"duration":29},{"text":"Erik Townsend: MacroVoices episode 524 was produced on March 19, 2026. I'm Erik Townsend. It was a sea of red in markets on Wednesday as the Iran conflict has dragged on longer than most analysts expected, and the Fed's standing pat with no rate cut accelerated the selling.","offset":29,"duration":25},{"text":"Erik Townsend: The S&P, gold, copper, and just about everything else other than the dollar index and crude oil were down and down hard, closing on or near their lows of the day, and then selling off even more in futures trading after the 4:00 PM cash close. These are all ominous signs that more downside is likely in coming days, absent a major bullish news event.","offset":54,"duration":23},{"text":"Erik Townsend: So we've got plenty to talk about this week. Bloomberg macro strategist Simon White kicks it all off as this week's feature interview guest. Simon and I will discuss the prospects for secular inflation, and why the oil price surge might be the catalyst needed to bring it about. We'll also discuss the risk-off playbook, food price inflation, the breakdown in private credit, and much more.","offset":77,"duration":29},{"text":"Erik Townsend: We had a huge positive response to Dr. Anas Alhajji's cameo appearance updating us on the oil market disruption on last week's podcast. So this week, Commodity Context founder Rory Johnston will join us for another perspective on what the Iran conflict means to energy markets. That's coming up right after the feature interview with Simon White.","offset":106,"duration":25},{"text":"Erik Townsend: Then be sure to stay tuned for our postgame segment when Patrick's trade of the week will take a look at the inflation surge event that hasn't happened yet. Not the one in crude oil where the price already spiked, but the one in food prices, which as Simon White will explain in the feature interview, could come next. And oh by the way, Rory Johnston is going to reinforce that view in the upcoming oil market update.","offset":131,"duration":24},{"text":"Patrick Ceresna: And I'm Patrick Ceresna with the macro scoreboard week over week as of the close of Wednesday, March 18th, 2026. The S&P 500 index down 221 basis points, trading at 6625, markets now trading at multi-month lows. We'll take a closer look at that chart and the key technical levels to watch in the post-game segment.","offset":155,"duration":22},{"text":"Patrick Ceresna: The US dollar index up 97 basis points trading at 100 spot 21, attempting to bullishly breakout of a 10-month trade range. The April WTI crude oil contract up 941 basis points to 9546, the war premium remains as the uncertainty continues.","offset":177,"duration":22},{"text":"Patrick Ceresna: The May RBOB gasoline contract up 1204 basis points to 307, gasoline now trading at three-year highs. The April gold contract down 546 basis points trading at 4896, remains in consolidation after putting in the January highs.","offset":199,"duration":22},{"text":"Patrick Ceresna: The May copper contract down 509 basis points trading at 559, the March uranium contract down 111 basis points trading at 8475. The US 10-year Treasury yield up three basis points trading at 426, upticking at the end of the day in the post-FOMC window.","offset":221,"duration":21},{"text":"Patrick Ceresna: The key news to watch this week is the Friday OpEx, and next week we have the Euro and the US flash manufacturing and services PMIs. This week's feature interview guest is Bloomberg macro strategist Simon White. Erik and Simon discuss the risk of a renewed inflation cycle, why markets may be underpricing second-order effects of the Iran conflict, the parallels to the 1970s style stagflation, and how shifts in commodities, credit, and the yield curve could reshape the macro outlook.","offset":242,"duration":44},{"text":"Host: And now with this week's special guest, here's your host Erik Townsend.","offset":286,"duration":8},{"text":"Erik Townsend: Joining me now is Bloomberg macro strategist Simon White. Simon prepared a slide deck to accompany this week's interview. Registered users will find the download link in your research roundup email. If you don't have a research roundup email, it means you haven't yet registered at macrovoices.com. Just go to our homepage macrovoices.com, look for the red button above Simon's picture that says \"Looking for the downloads\". Simon, it's great to get you back on the show. It's been too long. I want to dive right into your slide deck because there's so much to cover today. Let's start on page 2. You say inflation is a three-act play, that we really need to be thinking about a return to secular inflation, and a lot of people said there was no catalyst. Well, I think we got our catalyst, didn't we?","offset":294,"duration":49},{"text":"Simon White: Yeah, in spades. I think that's absolutely right, Erik. I think this is playing out in a way that's very analogous to the 70s, which is why I've referred to a three-act play there. And it certainly makes sense to start here. I think inflation is probably the most mispriced thing at the moment. I think it was mispriced before this war with Iran started and I think it's even more mispriced now.","offset":343,"duration":28},{"text":"Simon White: And it certainly seems that team transitory is back in force. If you look at the CPI fixing swaps, for instance, they show quite a sharp rise in inflation over the next few months expected, to maybe peaking out at 3 and a half percent, then very quickly it goes straight back down, and within 12 months, I think we're looking at roughly 2.8 percent in spot CPI, which is only about 40 basis points higher than it is now. So again, we're looking for quite a short-term shock, and it's even more egregious if you look at break evens.","offset":371,"duration":31},{"text":"Simon White: I mean, the shorter term break evens have moved a bit more, 2 to 5 year maybe moved 20 to 50 basis points since the war started, but the 10-year has barely budged, maybe 5 to 10 basis points. And I think the muscle memory is kicking back in that inflation will always go back to target. But I think that's you know, I think that's quite complacent. And that's why it's helpful to look at the 70s. You know, no analogy is perfect, but the 70s does have an uncanny amount of commonalities with today.","offset":402,"duration":29},{"text":"Simon White: And also the one thing that doesn't change is human nature. Human nature is immutable, and inflation is as much of a psychological thing as it is an actual you know, financial phenomenon or an economic phenomenon. So the chart on the left was something I first used in 2022, so almost 4 years ago, and it was uncanny because I updated it, and so the blue line shows the CPI level, not the growth, from the late 60s into the late 70s, early 80s, and the white line is today.","offset":431,"duration":30},{"text":"Simon White: And so I updated it, and we're kind of bang on today at the end of act 2. So the way I thought about it is act 1 was kind of when inflation first hits new highs. So this time around that was the pandemic. First time round in the 70s, it was on the back of we had a lot of fiscal easing because of the Vietnam War.","offset":461,"duration":20},{"text":"Simon White: You had LBJ's Great Society, Medicare, you already had quite loose fiscal policy. Inflation started creeping up much higher than expected. And then we went into act 2, which is kind of like the premature all-clear. And that's where it was kind of taken that inflation was a temporary phenomenon, it wasn't going to be much of a problem, it was going to go back in its box fairly quickly. And that feels like where we've been over the last couple of years. But you know, stubborn inflation as we know is proven very stubborn.","offset":481,"duration":29},{"text":"Simon White: It's it's not gone back to target, it stayed above the target rate, it's remained elevated. And if you look actually where that act 2 ends and you match it up to the 70s, it's pretty much bang on October 1973, which is the beginning of the Yom Kippur War. And that in itself is a comparison worth looking at. There's a lot of differences obviously with that war, but there's actually a lot of commonalities that definitely makes it worth looking compared to what we're seeing today.","offset":510,"duration":32},{"text":"Simon White: So back then it was a surprise attack. It was the Arab states led by Syria and Egypt on Israel, and they attacked Israel on Yom Kippur. It was a very short war, it was only three weeks. So this war is not yet three weeks. Initially it was expected to be short, but that's looking less likely now. I think PredictIt has an end of April cease fire now down to 40 percent probability from something like 65 percent not too long ago.","offset":542,"duration":27},{"text":"Simon White: And um you had obviously a major oil shock in response to this war because what happened after the war, after the three-week war, was that the US stated aid to Israel and the Arab states decided to have an embargo on oil, and that created this huge oil shock. So oil prices managed to quadruple in a matter of months. That's quite a significant oil shock.","offset":569,"duration":27},{"text":"Simon White: And and then that led to the act 3, which is the comeback with a vengeance. You have this massive rise in inflation through the end of the decade, and it really didn't end until you got Paul Volcker in with his exceptionally high interest rate hikes, that Saturday Night Special, that really managed to break the back of inflation.","offset":596,"duration":20},{"text":"Simon White: And if you look at some of the further commonalities, it's not just obviously what happened with oil prices, not just that this was in the Middle East, not just that it involved Israel. You also if we go to the next slide in slide 3, and you look at the equity market back then. So the equity market back then, this was the time of the Nifty Fifty. So this was a set of stocks that everybody thought they had to own. You know, they had great earnings, they were great businesses, and pretty much everyone owned them.","offset":616,"duration":31},{"text":"Simon White: Excuse me, and you know, similar to today. So we had very narrow leadership. In fact, it wasn't until the time of the Bangs and the Magnificent 7 that we had such narrow leadership again as what we had back in the early 70s. You had extreme narrow leadership as well, and that Yom Kippur War just before or just after it started, stocks had already started to sell off maybe 10-15 percent in the months before the war, but in the following year they sold off another 45 percent, and that was the largest sell-off we'd seen since the Great Depression.","offset":647,"duration":34},{"text":"Simon White: Now that's not to say that we're going to get the same thing playing out here. There's a lot of differences obviously today. For instance, obviously the US is a major oil producer. This is not the same exactly the same states that are involved. The choke point here is not an embargo, it's the Strait of Hormuz. But there is still nonetheless a choke point in the supply states.","offset":681,"duration":20},{"text":"Simon White: But I think it's worth bearing in mind that you know as a non-negligible tail risk just given we are in a sort of not dissimilar situation. And the kind of nail on the coffin if you like in some ways for why you should be perking up now to be attentive to the risks is that valuations, even though we had this massive decline in stocks in this huge big bear market in 73-74, the CAPE, the cyclically adjusted price-earnings ratio, was 18. And today it's more like 40.","offset":701,"duration":31},{"text":"Simon White: And also like the you know allocation of households compared to financial assets was much lower back then, it's much much higher back today. So really there is a number of reasons why you could see things we're we're we're obviously to get more deterioration obviously to get anything like that, but given some of the commonalities I think it's worth bearing in mind. And especially when you look at the market today, it just does seem again there is some complacency in the air.","offset":732,"duration":23},{"text":"Simon White: The stock market inherently seems to believe I think that there is some sort of Fed put on the way, and therefore it's not really worth the market trading down too much. I mean even if you look at like the put-call spreads, so the VIX went up initially, a lot of that was driven by first of all it was driven by call spreads falling, then it was driven by put spreads rising, so people were putting on insurance, but then they quickly monetized I think they monetized those hedges and that put spread started to come off, and so the VIX has started to come off.","offset":755,"duration":27},{"text":"Simon White: So really I think the market's getting to the point where it feels like, you know what, this isn't going to be a major issue. You know, we don't have too much to worry about here, not ready to obviously rally and make new highs again, but this is not something to get overly your knickers in a twist about. But I'd argue again along with inflation, that's something that's beginning to look a little bit complacent.","offset":782,"duration":20},{"text":"Erik Townsend: Simon, let's go a little bit deeper on some of the both differences and similarities between the Yom Kippur War and the present conflict. The Yom Kippur War was really a war of solidarity. As you said, the US had sided with Israel, basically all of the Arab states together went in on the Arab oil embargo. You have a very different situation today where the US has once again sided with Israel in a conflict with Iran, but now Iran does not have solidarity of the other Gulf states. In fact, it's attacking the other Gulf states that are allied with the United States. It seems to me there are still similarities, but there are some almost diametrical opposites in some aspects of this. How do we sort that out and make sense of to what extent the economic outcome might be the same or different?","offset":802,"duration":52},{"text":"Simon White: Yeah, I think I think that's 100 percent, you know, as I alluded to there are a number of differences, and so that puts you in a point where, you know, no analog is going to be perfect. But I think when you combine it as I say with the overall inflationary backdrop, where we are in terms of this three-act play in the 70s, you know, you could argue that what happened in the 70s were a series of kind of quote-unquote bad luck that led to inflation rising.","offset":854,"duration":27},{"text":"Simon White: So, you know, you had the kind of ex-ante conditions for inflation as I mentioned, we had already the Vietnam War, we had the fiscal expansion on the back of the Great Society stuff, and then you had the 1971 was Nixon closing the gold window, then you had the Arab oil embargo, the Yom Kippur War, you had at the end of the decade you had the Iranian Revolution. You could argue all these things are bad luck, but they were also hitting a situation where inflation was already in a different regime.","offset":881,"duration":28},{"text":"Simon White: And so I think I think that's the thing to to note the differences, that when you're in an inflationary regime, lots of things can happen, right? Things will always happen. But if they hit when you're already in an inflationary regime or more likely to have bigger inflationary impact. You know, that's where we are today. As I say, it's very uncanny we happen to look compare the two analogies that almost to the month when you get this sort of premature all-clear ending is almost to the month when the Yom Kippur War started as when the attacks on Iran started.","offset":909,"duration":31},{"text":"Simon White: Yeah, I wouldn't want to over-labor the point in terms of the analogies, but the there's there's so many precedents that makes it worthwhile looking a little bit deeper into. For instance, another one that's very interesting is an underappreciated fact that in the 70s, the food shock was actually much bigger than the energy shock in terms of on its effect on CPI. So if you look at the weighted contribution from food and from energy in the 1970s, it was much bigger than it was for energy.","offset":940,"duration":31},{"text":"Simon White: And in fact food food inflation was already rising before the the energy shock. This time around we have the disruption to the Strait of Hormuz. That obviously doesn't just affect energy prices, it affects energy products. And for instance, a lot of stuff that goes into fertilizer is either produced in that region or has to travel through that region. So Iran itself produces a lot of urea and ammonia. There's a huge amount of sulfur flows through the straits, all these things go into fertilizer.","offset":971,"duration":30},{"text":"Simon White: And in fact if we go a little bit further into the presentation, if we go to let me just find the slide, if we go to slide 8, we can see there actually you can see the two shocks. So the blue line shows the food shock after OPEC 1, the Yom Kippur shock, and you can see again after OPEC 2, the Iranian Revolution. Both times the food shock was worse.","offset":1001,"duration":24},{"text":"Simon White: And today already we have, if you look at the contribution to CPI, US CPI that is, from food, it's higher than than energy already. So if you have this effect feeding into, you know, fertilizer prices, and that's what I've tried to show on the chart on the right on slide 8, you can see this fertilizer proxy, which includes some of these inputs I mentioned along with things like potash. You know, when that starts to rise, it's a very reliable lead by about six months that food CPI will start to rise.","offset":1025,"duration":30},{"text":"Simon White: So I don't think that is also being fully priced in. And especially I think if you take account of the fact that if you have energy and food both rising, I think it's very unlikely you're not going to get some second round effect that's going to feed into core inflation and you get the sticky inflation that we saw in the 1970s. And that's a lot more troublesome for the Fed. In one sense it should make it slightly easier because the Fed can then go, \"Right, if we see sticky inflation, that's something we think we can do something about, we'll maybe hike rates.\"","offset":1055,"duration":24},{"text":"Simon White: But with the muted muted, sorry, next chair Kevin Warsh coming in, you know, whether he's going to lean towards the dovish or the hawkish spectrum, you know, I certainly think he's more likely to be more like an Arthur Burns who was in in the early 70s at a time of the Yom Kippur War than he's likely to be a Paul Volcker who was in charge after the OPEC 2 shock after the Iranian Revolution in 1979. So I think that further complicates the the matter in terms of what the Fed's reaction function is going to be.","offset":1079,"duration":41},{"text":"Erik Townsend: Well, it seems like the analogy that's most relevant is the Yom Kippur War only lasted a few days, but the Arab oil embargo lasted quite a lot longer than that. So the question is once the direct kinetic conflict is over, how long can Iran continue to disrupt the flow of traffic through the Strait of Hormuz? Is that the right thing to focus on and if so, what's the answer?","offset":1120,"duration":25},{"text":"Simon White: Yeah, I think I think that's that's correct, Erik, in that the key message I think from that period was the war itself was very short. As you say, it was about three weeks, but the impact was felt way through all through the decade and it had a number of consequences. So again, no analogy is perfect, but the human side of things doesn't change how humans respond, human nature responds, doesn't really change.","offset":1145,"duration":30},{"text":"Simon White: In fact, I can see this this the two nature of the two different shocks. If we go to slide 6, so we've got two more charts there, and this this brings me to another point which I think needs to be made is that I don't think the yield curve is pricing in what's looking to be a much larger inflationary shock than for instance has been picked up in the break-even market.","offset":1175,"duration":20},{"text":"Simon White: And so the left chart we can see there is what break-evens did in the 1970s. So OPEC 1 and OPEC 2, both cases they ended up rising, and rising quite considerably, but long after if you like CPI had already started rising. So they were in late to the party. But both times they they did rise.","offset":1195,"duration":18},{"text":"Simon White: And if you look at the chart on the right there, you can see the two the nature of the two different shocks. So OPEC 1 was definitely more of a permanent shock to oil prices. So really oil prices never really revisited their pre-OPEC 1 or pre-war, pre-Yom Kippur War levels again. They just kept rallying through until OPEC 2 hit, the Iranian Revolution in 1979. They rose sharply again but nowhere near as much in percentage terms as they did in OPEC 1, and then they sort of gradually start decaying fairly soon after the Iranian Revolution.","offset":1213,"duration":34},{"text":"Simon White: So the OPEC 2 was more transient, was a more transient shock, but in both cases if you look at the bottom panel of that chart, you can see core and and in the interim period between OPEC 1 and OPEC 2, both made a higher low before rising again in the early 80s. And again it wasn't until Paul Volcker got his hands on monetary policy that he was really able to put an end to this huge inflation that we'd had through that decade.","offset":1247,"duration":25},{"text":"Erik Townsend: One of the theories of secular inflation is that it's a self-reinforcing vicious cycle. So as you begin to see inflation, it changes consumer behavior. People start stocking up on things because they want to buy it while the price is still cheap before the price goes up more. That causes more consumption that is inflationary, and it all feeds on itself and it's kind of like a fire that once you've started it, you can't put it out. Are we already at that point in terms of this coming inflation cycle where the fire has been started and can't be put out, or are we still in the need to look at this and see what happens stage?","offset":1272,"duration":37},{"text":"Simon White: We're we're already in that. In my view it's quite clear that what began in 2020 with the pandemic, with the large spike in inflation, was the beginning of if you like that that cycle starting. And really what's happening underneath is that why 2 percent inflation, for whatever reason this is an arbitrary number, but 2 percent or around 2 percent inflation overall like over the whole economy tends to be fairly stable.","offset":1309,"duration":29},{"text":"Simon White: And I think that's because all the different actors that are taking price signals off one another when inflation is not moving around that much, they they tend not to get out of sync. But once it's out of the bag if you like, once you have this large rise in inflation which we saw in the early 2020s, they got all out of sync, and it takes a huge amount for them to get back in sync, and you end up with inflation remaining elevated.","offset":1338,"duration":24},{"text":"Simon White: And so you can split CPI up for instance into components. So you can look at the essentially sticky versus non-sticky components. And what you notice in 2020 is both cyclical and structural inflation rose, but cyclical started to fall and but the structural one remained more sticky.","offset":1362,"duration":19},{"text":"Simon White: And by the time the structural inflation had started to fall, cyclical inflation because of its name is cyclical, had started to rise again and started to reinforce structural inflation that was already elevated. And we're right in that period again now where structural had started to fall, a higher low, but the cyclical part of it is already rising again.","offset":1381,"duration":22},{"text":"Simon White: And this war is just going to make it worse because obviously the immediate effect is on headline inflation. So straight away you're going to see that feed into the cyclical side of things. And once again what was what 2.4 percent where we are now and CPI maybe 3 percent of PCE, you know they're going to look like again equivalent to what we saw in the mid-70s after the Yom Kippur War. This is the point where we start to see a rise again.","offset":1403,"duration":21},{"text":"Simon White: Now I don't know how far it goes. Again, the US is much more insulated than it was back then. But I think you do see a re-acceleration. And the real kind of, if you like, the real kind of tinder in this is that as I say, going back to Kevin Warsh, you've got someone that's coming in that nobody's really sure is going to be an inflation fighter. In fact quite the opposite quite possibly.","offset":1424,"duration":22},{"text":"Simon White: Which is kind of actually a bit odd just to slide deviation, but connected is it's kind of strange if you look at real yields have been rising. So real yields have been rising since the war, and that's been driven by higher rate expectations. And so that's part of the rise in nominal yields. So break evens have moved a bit, as I mentioned, but really the bulk of the move so far have been real yields, and that's on the back of as I say rate expectations are going higher.","offset":1446,"duration":26},{"text":"Simon White: But that kind of just seems a little bit incongruous, given Warsh and the conditions under his nomination and a president who still makes no bones about being absolutely determined to get lower rates immediately. I mean he was saying so only a couple of days ago on yesterday. So I feel that that is also adding to the structural kind of impediment for inflation to to keep rising.","offset":1472,"duration":26},{"text":"Simon White: And then go back to the yield point I was mentioning. So I think yields as I say are not priced for inflation shock, and I think one thing we'll see is the yield curve will steepen. So if we go to slide 7 on the deck and I looked at basically how break-evens and real yields behaved in the 70s. Now there was no real yield in the 70s because TIPS didn't start trading until 1997.","offset":1498,"duration":27},{"text":"Simon White: But you can synthesize a real yield so you basically look at how real yields have traded laterally versus a whole bunch of different economic and market indicators, and then you can back it out and look at how and build basically a synthetic series of real yield in the 70s. So chart on the left there we can see again the difference between OPEC 1 and OPEC 2 and how the yield behaved.","offset":1525,"duration":21},{"text":"Simon White: So in both cases, break-evens rose, but in the OPEC 1 what happened is that you had the shock to break-evens but then we had an equal and opposite shock to real yields. That's textbook stagflation. What happened in OPEC 2 is the break-evens rose, but real yields stayed largely static. And I think that was basically for two main reasons. One, the US response to OPEC 1, so the US became less energy intensive and more energy efficient, and a lot of non-OPEC production came on stream from places like Alaska and the North Sea.","offset":1546,"duration":36},{"text":"Simon White: And on top of that, you had very soon after the Iranian Revolution you had Paul Volcker at the Fed, and that really put a kind of cushion under how far real yields could fall. So in OPEC 1, the 10-year yield maybe didn't move a huge amount because the real yield and break-evens canceled one another where the nominal yield rose a little bit in OPEC 2.","offset":1582,"duration":20},{"text":"Simon White: But the difference being in OPEC 1 and OPEC 2, so the OPEC 1, the curve steepened because we had Arthur Burns, and he as I mentioned earlier, you know, was notorious for not believing that a central bank could do much for inflation, let alone a supply shock inflation. He was kind of of the view that by and large, most inflation shocks couldn't be solved by a central bank.","offset":1602,"duration":24},{"text":"Simon White: And in fact he was the guy when he was at the Fed, he got the staffers working on some of the first measures of core inflation, and through the decade he kept on taking out more and more of core inflation in a frantic hope that something would be going down, which he discovered wasn't the case. So you know, we have this very kind of dovish banker who doesn't really believe central banker doesn't really believe that inflation is something he can do much about.","offset":1626,"duration":23},{"text":"Simon White: So short yields kind of fell, so the curve steepened in OPEC 1. In OPEC 2, yes 10-year yields were rising a little bit, but you had Paul Volcker who was massively raising on the front end, so the curve the curve flattened. But this time I think in some ways it the curve response function could be more like OPEC 1 because I think that longer dated break-evens will rise. So I think that move thus far that we've seen this muted move, I don't think that'll last.","offset":1649,"duration":27},{"text":"Simon White: And that they should rise more from you know the relative static where they were before, and more likely to see as I say with Warsh, you're going to see lower rate. So I think lean towards a curve steepener this time as we saw in OPEC 1, but not just for reasons that OPEC 1 is a similar to what's happened today. There are as I covered some similarities but there's a lot of differences as well.","offset":1676,"duration":21},{"text":"Erik Townsend: Well, if this was 1973 all over again, and clearly you've said that it's not exactly a perfect analogy, but to the extent that there's a lot of overlaps, 1973 was not a good time to have a long-term bullish outlook on buying and holding stocks for the long haul. What does this mean for equity markets for the rest of the decade?","offset":1697,"duration":21},{"text":"Simon White: Why, I I I think it's interesting now. I mean, depends who you speak to. I mean, so I've got like a lot of stuff you know some friends and people I know that speak to commodity people, and they're overall a lot more bearish than equity and rates people who seem to be overall less pessimistic. I think again, going back to what I said earlier, I think that's still the sort of belief that there is some sort of Fed put on the way.","offset":1718,"duration":23},{"text":"Simon White: But even more than that, I think the big difference is that ultimately there's a backstop, and that if things get really bad the Fed can step in. I'm not saying that's what's going to happen right now, but you're always going to have that kind of tail cover. So the commodity markets can really price in extreme kind of negative outcomes, but they don't have a lender of last resort, right?","offset":1741,"duration":20},{"text":"Simon White: So there's nowhere to go if you if your commodity markets seize up for whatever reason, there's no backstop in the same way that you have for financial assets. So I think that sort of explains why we have that today. And you know 1973, I don't think we we had that to the same extent. There wasn't this belief that the Fed was always going to protect equity returns.","offset":1761,"duration":22},{"text":"Simon White: So that's why you probably had that situation where you had this huge shock much bigger than the energy shock that got today, combined with a Fed that's then, yes it was overall more dovish, but this was the decade remember of go-stop monetary policy where, you know, they loosened policy, inflation came back then they tightened it, and then they're like, \"Oh right, better loosen policy again,\" back and forward, back and forward.","offset":1783,"duration":21},{"text":"Simon White: So you know, huge amount of volatility underlying there which obviously makes it more likely or or increases the chance you can have deeper steeper falls in the market. And so you don't really have some of that today, but it does seem as I say earlier, it feels like the market overall be more complacent, even with that in mind that there is a backstop, that there is still a potential for some sort of Fed put, it still seems to be some sort of complacency and as I say what drew me what draws me to that especially is just looking at what's happened to put-call skew.","offset":1804,"duration":27},{"text":"Simon White: You know, initially there was the response to like let's hedge some downside, but very quickly that reversed. It was almost as if like the market went, \"Oh maybe we don't need such deep out of the money puts here, maybe I maybe the market's not going to sell that sell off that much, in which case I don't need this insurance right now.\" So again that that smacks to me just of complacency just because the distribution of outcomes are are still very wide, right?","offset":1831,"duration":29},{"text":"Simon White: Still a lot of moving parts here, both unpredictable but the most of of course Trump himself. You know, back in the 70s we had a lot of volatility, political volatility, but again I don't think you had anyone quite as volatile and who was able to obviously voice his volatility in such a real-time manner than we've got today. So that really puts a lot of people in a sort of frozen moment. Like they want to move money, but they're also kind of fearful that they can't really put much risk on because so much could change.","offset":1860,"duration":27},{"text":"Erik Townsend: Simon, on page 11 you say gold is a hedge against both tails. Elaborate on that please. But also I think it's it's relevant to point out if we're looking at the analog as being the 1970s, private ownership of gold wasn't relegalized until 1974. So there was a very big transition catalyst there where it became legal once again to own gold bullion, which probably disrupts the data. How should we think about this in the 2020s?","offset":1887,"duration":27},{"text":"Simon White: Yeah, that's a good point. I think I think there's also another disruption at the other side as well because the data on this chart goes back to the late 20s. And back in the 30s was when essentially the US confiscated private gold ownership, so they confiscated gold. I think they paid 20 dollars and then revalued it at 35 dollars an ounce.","offset":1914,"duration":23},{"text":"Simon White: So quite possibly gold could have went up a lot more in that deflationary period of the 30s. I think I think that's why gold's misunderstood, though, is that it is to some extent an inflation hedge. It's not a perfect inflation hedge, it's not path-dependent. But in extreme, when inflation goes very very high and you're in that sort of environment, it does a good job because you've got the debasement angle of things and just the general kind of insurance against the financial system.","offset":1937,"duration":29},{"text":"Simon White: But it's not appreciated that it's also a downside tail hedge as well. And I think what has been driving a lot of the rally recently in gold is just a lack of alternatives. If you start thinking about I don't know what's going to happen and I don't know whether we're going to be in a debasement world where there's a lot of inflation, or I don't know whether there's going to be a massive credit event and that's going to be deflationary.","offset":1966,"duration":21},{"text":"Simon White: These are potential threats to the financial system. What can I own that has you know proven record of protecting a portfolio in such an environment? And there's really not much else other than gold. I think people sort of ran through all the options and they're like, \"Right, that won't work, that won't work.\" Bitcoin? That hasn't been tested.","offset":1987,"duration":21},{"text":"Simon White: And they landed on gold. And you know, a lot of people that openly admitted they've never ever really favored gold, they've never been a fan of gold, they've never understood it, are nevertheless starting to add or have started to add some exposure to their portfolios. So I think as an unimpeachable form of collateral really is what's driving driving this move.","offset":2008,"duration":21},{"text":"Simon White: And although it struggled a little bit over the last few weeks, I think it's premature to say that's the end of the primary bull trend because kind of a lot of the main reasons that were driving it are still valid today. I mean there's still a need for diversification from the dollar system. I still think there's obviously a lot of geopolitical volatility. That hasn't changed.","offset":2029,"duration":23},{"text":"Simon White: You know, central banks, I don't think are suddenly like emerging market central banks, they were the ones that initially kicked off the rally a few years ago. I don't think they're going to turn tail and start selling in any great size. You know, they bought some and they may not buy any more, but I don't see why they would suddenly turn tail and start selling on mass. There was a story that Poland was mooting selling some of its holdings, but the reason why they were thinking of selling them was for defense. And that doesn't really strike me as a great sort of a gold bearish kind of reason for selling your gold overall.","offset":2052,"duration":37},{"text":"Simon White: So I think, yeah, the general environment's still very conducive to gold still still generally keeping to its primary bull trend. It's struggling right now perhaps because we've had some marking up of short-term rates, and the dollar's had a little bit of a rally, things like that. But overall I I don't see why. You know, it takes a big seller to come around to really force it into a massive bear market, and I just don't see where that's going to come from.","offset":2089,"duration":24},{"text":"Erik Townsend: As you said, unfortunately what has not gone away is geopolitical excitement, for lack of a better word. The thing that I've noticed just in the last few weeks is there was a very strong positive correlation, you know, the next time a bomb drops gold spikes upward. And what we've seen just in the last few weeks is a breakdown where when oil is up hard because of geopolitical, you know, bombs are dropping, gold's actually moving down. What's going on there?","offset":2113,"duration":29},{"text":"Simon White: Yeah, as I say, I think potentially it's because the real yields have risen, that could be part of it, the little bit of the rally in the dollar. It should also be in times of if there's any capital repatriation going on, maybe in the Middle East. I don't know for sure, but you know gold can often get hit in the short term. People need to liquidate.","offset":2142,"duration":20},{"text":"Simon White: That's unfortunately the problem with having an insurance asset that's also can sometimes be a very liquid asset, is it's often the one that's first to go, so it can give kind of counter-intuitive signals. But overall I just as I say, I don't know what the narrative or the argument would be to say that this is anything more than just, you know, obviously we've got to remember the market has rallied extraordinarily much in recent months and it's perfectly respectable for it to have, you know, the kind of pause it's having right now, like it can't continue in that sort of trend indefinitely.","offset":2162,"duration":38},{"text":"Simon White: But I don't think that means that the trend is over. So, yeah, I mean I think silver is a far more, obviously volatile, but a far more questionable kind of you know, response to that kind of overall idea and trade, but gold to me seems certainly more more secure just because as I say, the reasons underpinning its rally all seem to be mostly intact still now.","offset":2200,"duration":23},{"text":"Erik Townsend: Simon, we've been jumping around in the slide deck. Let's go back to page 4 because you've basically said you're rewriting the risk-off playbook. It seems like an important book to read. Tell us more about it.","offset":2223,"duration":13},{"text":"Simon White: well, I'm certainly not going to rewrite it myself, but my point here is really that, you know, we talked about some historical analogs that are useful guides, but I think you have to keep an open mind as the rules can change. So I think standard you know risk-off playbook is that you see the dollar rally and Treasuries rally and risk assets sell off, and that might not be the case to the same extent this time.","offset":2236,"duration":25},{"text":"Simon White: So for instance, take the dollar. So the kind of quintessential risk-off moment really was the GFC, and in the GFC the dollar rallied. So I think that's for a lot of people's like, \"well, that that was the big one and the dollar rallied, the dollar's therefore a safe haven.\" But really if you look at what drove that, and then you compare to today, I don't think you can necessarily say the dollar's going to be in a condition to rally quite as hard as it did back then.","offset":2261,"duration":23},{"text":"Simon White: So the chart on the left there you can see that the blue line shows the bond flows, inflows from foreigners. So they they slowed. Equities were tiny back then, equities are much bigger now, as far as foreigners are concerned. But what actually drove the dollar, the rally, was repatriation of flows, so the US basically mutual funds and banks had lent to various European entities, and it was these guys repatriating that led to the dollar rally.","offset":2284,"duration":27},{"text":"Simon White: So it wasn't a case of foreigners channeling money in or needing dollars to cover structural shorts. It was really just US entities repatriating that led to the dollar rally. Now this time around, the cash flows are the structure of this is different. So bond flows are much smaller now because we've had because the US is now not see Treasuries are not seen as much of a safe haven. And equity flows are now massive.","offset":2311,"duration":32},{"text":"Simon White: And the US outflows are not as large as they were back in 2008. So the net impact means the US is much more exposed to equity outflows. So in a sort of risk-off environment that we're in right now, it's conceivable that more capital is repatriated, and some of that is equities in the US. Equity flows as I say tend to be unhedged. That is a dollar negative. And you don't have that cushion of the same cushion of dollar repatriation.","offset":2343,"duration":24},{"text":"Simon White: So, yeah, you wouldn't expect to see the dollar necessarily rallying as much. And that could be seen even more if you look at the chart on the right. So after the, you know, Mar-a-Lago Accord, you know, all the talk of the dollar disruption, the tariffs, you know, that didn't lead to a sell America trade, but I certainly think it made people think twice about their exposure to dollars.","offset":2367,"duration":20},{"text":"Simon White: And that could be seen as I say in this chart, just kind of like the dog that didn't bark. So the white line shows the dollar reversed. And what you tend to see is the blue line, which is reserves denominated in dollars. So when the dollar weakens, i.e. you see the white line rise, the reserve managers have tended to buy dollars. They tend to use the weakness in the dollar to to add to their dollar reserves.","offset":2387,"duration":26},{"text":"Simon White: And that significantly hasn't happened this time round. So we've seen this big weakening of the dollar and there's been no response yet from dollar reserve. So I think that shows like a general change in attitude to global demand for dollars. So I don't necessarily say as I think the dollar rally will be as big this time, and thus far the DXY I think is up about 1 and a half 2 percent since the war started.","offset":2413,"duration":17},{"text":"Simon White: And if we go to to slide 5 looking at say commodities, so commodities as a as a kind of risky asset is sort of seen as well should certainly sell off in a recession I think is the general interpretation. That isn't isn't always the case either. If you have a commodity induced recession, and if we are going to get recession, there's very low chance of it in the next few months, but that could change if the war continues and the negative effects spiral.","offset":2430,"duration":25},{"text":"Simon White: What often happens then is that commodities start to sell off before the slump in growth, but the that sort of sell-off in commodity prices kind of eases the growth shock and actually that allows commodities to rally through the rest of the recession. So that might well happen again. We get a commodity induced recession say later this year, next year. That's not a prediction, but if we were to get one, I wouldn't automatically assume that commodities are going to sell off through that.","offset":2455,"duration":26},{"text":"Erik Townsend: Simon, let's move on to page 9. The title of that slide is \"it takes a war to bring down an economy this strong\". Let's start with how strong the economy is, but then later you say it would take a protracted war. So I guess the question is how protracted does it need to be in order to take down the strength of economy that we already have, and where is this thing headed?","offset":2481,"duration":20},{"text":"Simon White: it's actually remarkably strong given I think the length of time of the cycle. And that really surprised me when I was looking at this. And it's also a little bit ironic, I guess, that coming into this war the US was firing on all cylinders. And you know as you mentioned as I mentioned the fact that war is perhaps just what it's going to take to to derail it.","offset":2501,"duration":23},{"text":"Simon White: And you have number of cycles for the US economy. Everyone knows about the business cycle. There's also the liquidity cycle, the housing cycle, the inventory cycle, and the credit cycle. And all of them are actually in in pretty good shape. So the business cycle, if you look at leading indicators, has been turning up. The liquidity cycle, so that's the chart on the left there.","offset":2524,"duration":21},{"text":"Simon White: And I look at excess liquidity, which is the difference between real money growth and economic growth. So that really gives you a measure of what impact this liquidity is going to have on markets. So the bigger the gap between liquidity and economic growth, it means the economy needs less, but that more to go into risk assets. That has been vacillating around, as you can see in the chart, but it's turned back up again.","offset":2545,"duration":22},{"text":"Simon White: And even even taking into account we've seen some tightening in financial conditions since the war, but overall they've not been massive. As I've alluded to earlier, the dollar's rally hasn't been huge either thus far. So liquidity's in in pretty good shape.","offset":2567,"duration":15},{"text":"Simon White: And the business you know the general business cycle is in pretty good shape, even taking into account the job market's slowed down. I think it's possible to have a jobless growth. And some of the things that I would look at to see if there was a slowdown in growth coming, such as temporary help, is actually rising, not falling.","offset":2582,"duration":16},{"text":"Simon White: Average hours worked is kind of static. You would normally expect to see that fall as people cut hours before they start sacking people. And I think you've got to remember that we have companies still have very strong margins, the you know their balance sheets are generally in pretty good shape.","offset":2598,"duration":20},{"text":"Simon White: And then you've got this massive amount of government money still filtering through the system. So there's maybe not the same acute needs, in the short term at least, for heavy layoffs. And that that global, the global economy is also in a good shape as well. So that's the chart on the right there. You can see that we're in the midst of this global cyclical upswing.","offset":2618,"duration":18},{"text":"Simon White: If you look at OECD leading indicators for different countries around the world, almost all of them are turning up on a six-month basis. And then if we look at the inventory cycle, that looks to be turning up as well. Leading indicators are pointing it to continue to rise. Sales to inventory ratios have started to rise.","offset":2636,"duration":18},{"text":"Simon White: The housing cycle is not as in good shape, but you know it's okay. House price growth, sales growth has slowed down and things like that. But one of the best leading indicators for housing is building permits. Building permits are are doing okay. And they're actually led by mortgage spreads. So we've seen quite a significant compression in mortgage spreads for various reasons such as falling bond volatility.","offset":2654,"duration":23},{"text":"Simon White: So you can't say that the housing cycle is in particularly bad shape either. And then we have the credit cycle. So if we go to slide 10, the listed credit market from a fundamental perspective, my my leading indicator there on the chart on the left shows that on net fundamentals are still pointing to tighter spreads. So things like bank lending conditions are particularly","offset":2677,"duration":23},{"text":"Simon White: supportive. You can see there on the chart that leading indicator typically gives about a six-month lead as to what we can expect from listed market credit spreads. So that is looking okay. But there is there is trouble brewing as well. It's not all good news. It's maybe more below the surface. So there's private credit.","offset":2700,"duration":19},{"text":"Simon White: Private credit is where we've had the most debt created recently as listed market debt creation was falling, debt overall debt creation was falling because private credit was rising so so much. And you can get a little bit of a measure on what's going on in private credit by looking at the business development company spread, the BDC spreads, so they are basically publicly listed companies that invest in unlisted entities.","offset":2719,"duration":24},{"text":"Simon White: And their spreads normally track the listed market quite quite tightly, but recently they've decoupled. So listed spreads continued to trade and to turn in lower, tighten, but the BDC spreads have decoupled and moved a little bit higher. So that suggests that there is some some problems in private credit.","offset":2743,"duration":16},{"text":"Simon White: And then the other factor is private credit as opposed to listed market credit tends to be floating rate. So high-yield listed high-yield maybe only about five percent or five to ten percent of floating rate now compared to nearly thirty percent after the GFC. Whereas private credit by its nature tends to be almost all private almost all floating rate.","offset":2759,"duration":20},{"text":"Simon White: So it's very exposed to the rise in interest rates that we've seen over the over the last year or so, and it will be obviously even more impacted if we get this re-acceleration in inflation and higher interest rates that I mentioned before. So you've got this situation where the economy is very strong overall, but it's got these sort of vulnerable underbellies such as private credit, which are already starting to hurt, as I say, if we look at the BDC spreads.","offset":2779,"duration":25},{"text":"Simon White: So that's the risk really is that a strong economy doesn't necessarily protect you from from accidents happening, and I think private credit's potentially where one of those could happen.","offset":2804,"duration":10},{"text":"Erik Townsend: Simon, I wanted to jump back into gold. You gave us page 11, \"the ultimate form of collateral\". We talked a little bit about the differences between now and the 70s. What are your views relative to gold and why specifically did you title this \"the ultimate form of collateral\"?","offset":2814,"duration":17},{"text":"Simon White: Well, that that's a good question. I mean the chart there on page 11 shows the performance of gold in inflationary environments and deflationary environments. And it's what I alluded to earlier, that gold performs remarkably well when inflation is very very high, above the target, so five, six, seven percent, it has historically done a really good job.","offset":2831,"duration":21},{"text":"Simon White: But it also manages a higher average return when the economy is contracting or during crises. And I think that speaks to it. In any situation where the system itself is being put under scrutiny, you know gold manages to outperform other major asset classes. It's because people don't find it particularly comfortable but they find it safe. You know, no one likes owning something that yields zero, but you know when everything else yields minus thirty, zero is an amazing amazing real yield to have in your portfolio.","offset":2852,"duration":30},{"text":"Simon White: So in that sort of scenario, people are attracted towards something that really is independent of of you know almost almost everything else. I mean, central banks have made efforts to control gold prices before. For instance, the London Gold Pool in the early 60s, but that ended in abject abject failure. So it really isn't an unimpeachable asset in that regard.","offset":2882,"duration":21},{"text":"Simon White: And I think that's why people keep coming back towards it. And especially today as I say in a position of debasement, but possibly contraction, tail risks on either side, I'll go gold's really where you you find yourself looking if you haven't yet been convinced that crypto will do the job.","offset":2903,"duration":15},{"text":"Simon White: Crypto as you look over the last last few weeks was also hit heavily. So that doesn't really smack yet for everyone as as being something that they can absolutely rely on in extreme events. I mean, look at what it did in in 2022. It didn't it certainly didn't work as a deflation hedge back then. So yeah, I still find people coming back to gold as the gold standard of unimpeachable collateral.","offset":2918,"duration":25},{"text":"Erik Townsend: Simon, we're up against our time. Before I let you go, I can't think of anything more important than inflation right now. Tell us where our users can go to see more of your work and particularly work related to inflation.","offset":2943,"duration":12},{"text":"Simon White: So I publish daily on Bloomberg on the terminal and mobile and on on on the on bloomberg.com if you don't have access to the terminal. And so you know I cover all major macro areas. We look we obviously spent quite a bit of time on on the equity market over the over the coming months just as things got a little bit more heated.","offset":2955,"duration":18},{"text":"Simon White: But also focus obviously on the rates and fix income market and credit as well. So there really isn't any you know major asset class. I cover fixed commodities too as we've already done today in our talk. So yeah, we can you can catch me there.","offset":2973,"duration":13},{"text":"Erik Townsend: Simon, thanks so much for another excellent interview. Patrick Ceresna and I will be back as macro voices continues right here at macrovoices.com.","offset":2986,"duration":20},{"text":"Simon: Um, so I think, I think that does have to color your, your view and, uh, a protracted war would definitely do a lot of damage to, to the economy.","offset":3006,"duration":12},{"text":"Host (Eric): Simon, as you talked about private credit, it was kind of concerning to me because, frankly, it, it echoes in my mind to about 19 years ago, the summer of 2007, when we were also talking about an opaque, not well-understood in the broader finance community small little piece of the credit market that couldn't possibly disturb anything else. And the reassurance at the time was, don't worry, it's contained to subprime. There's nothing to worry about. Is this another setup like that?","offset":3018,"duration":32},{"text":"Simon: It looks very much like it. And I think it was Ben Bernanke himself who said, uh, subprime is contained, I think. Um, look, I, I go back to my kind of axiom that, um, the one thing that doesn't change is, is human nature. I think we're sort of seeing that even within the private credit space in terms of when people have opportunities to make money, the more kind of off-grid they are away from regulation, the standard kind of emotions of greed and fear will kick in.","offset":3050,"duration":34},{"text":"Simon: Greed initially, and people will start to take inflated risks to essentially earn money now and park what are risks later. Hopefully they can not be around when the, um, proverbial hits the fan. Um, so I don't see why, why it wouldn't be any different. I mean, there's even a story today about one of the credit funds. If you look in the private credit fund, it's, it's yet another black box, but within it there's even more black boxes.","offset":3084,"duration":29},{"text":"Simon: I mean, that straight away reminded me of CDO squared. So here we had CDOs, which were already kind of niche derivative products, but people started making up these CDOs of CDOs themselves. And, you know, I'm sure a lot of people at the time were thinking, this probably can't end well. And, you know, here we are again. There's nothing new in finance.","offset":3113,"duration":23},{"text":"Host (Eric): Simon, I can't thank you enough for a terrific interview. Before I let you go, I'm sure a lot of listeners are going to want to follow your work. You kind of have to be somebody special and have a Bloomberg terminal in order to access most of it. Tell them for those who are lucky enough to have that access, where they can find your writings.","offset":3136,"duration":20},{"text":"Simon: Sure, and thanks again for having me on the show, Eric. Uh, so on the terminal, I have a column called Macroscope. Comes out uh, twice week, Tuesday and Thursdays. And I also write for the Markets Live blog, which is a kind of 24-hour five-days-a-week markets scroll uh, that you can follow all the latest market development.","offset":3156,"duration":25},{"text":"Host (Eric): Patrick Ceresna and I will be back as MacroVoices continues right here at macrovoices.com.","offset":3181,"duration":10},{"text":"Host (Eric): It was great to have Simon White back on the show. Rory Johnston is next on deck for a special second interview on the developing Iran conflict and what it means for the oil markets. Then Eric and I will be back for our usual post-game chart deck and trade of the week.","offset":3191,"duration":21},{"text":"Host (Eric): Since the extra coverage format seems to be a hit with our listeners, we will do our best to continue it as long as the situation in the Middle East warrants. Now let's go right to Eric's interview with energy markets expert Rory Johnston.","offset":3212,"duration":22},{"text":"Host (Eric): Joining me now is Commodity Context founder Rory Johnston. Rory, uh, you, Dr. Anas Alhajji, really all of the most credible experts felt the same way, which was look, the Strait of Hormuz getting shut down is probably not that realistic of a scenario. And I'm going back to previous interviews, you know, months or years ago.","offset":3234,"duration":25},{"text":"Host (Eric): Boy, everybody got thrown a curveball. So what happened? How come all the experts, including yourself, who thought this really couldn't be shut down? Is it just about insurance? Is it about minefields? Is it about something else? How come the traffic is not flowing through the strait, first of all, and then we'll get into what does it mean?","offset":3259,"duration":22},{"text":"Rory: Thanks for having me back on, Eric. As you note, I've been relatively kind of Pollyannaish about this for a long time, that...","offset":3281,"duration":10},{"text":"Rory: ...it, and the reason for it, the reason I didn't think this would happen, and to be clear, I never thought this would happen in my career. And the reason for that is because it is such a big shock. Like it's, you know, it make—it'll make the, if this continues, it'll make the 1970s look like child's play.","offset":3291,"duration":21},{"text":"Rory: And that is my concern here. And I think part of the reason that it is happening now, and the reason I didn't think it would happen is—it's not that I didn't think that Iran could close the strait, although I had my doubts because we had never seen it realized and again, the consequences are so intense.","offset":3312,"duration":19},{"text":"Rory: But I never thought a US president would engage in a war with Iran without a plan, without something in his pocket kind of ready for this moment. And what we've seen so far is that at least, here's my, my read of what's happening and how the Trump administration got into this. I do not think that the Trump administration expected to be in its third week of the Iran war.","offset":3331,"duration":27},{"text":"Rory: I do not think they did any of the things you would do if you had planned to be in this engagement for weeks and potentially months now. We saw, for instance, the IEA's coordinated strategic petroleum release last week. That was good. Uh, that's a, absolutely what we should be doing in this in this situation, but it was two weeks after the war started.","offset":3358,"duration":24},{"text":"Rory: Like, if you were, if you were planning this, you would have an IEA release lined up. You know, we saw that ahead of the Gulf War as an example. You would have had things like the marine insurance facility that Beston announced at Treasury. You would have had that lined up. You probably would have done more work to refill the Strategic Petroleum Reserve ahead of this.","offset":3382,"duration":23},{"text":"Rory: I mean, all of these things are such that it just seems insane that we entered this without—and by we, I mean the Trump administration entered into this without a plan. I think that what we've seen from the Trump administration—and very frankly, my expectation was that we were going to see something that clearly the largest military buildup in the Middle East since the invasion of Iraq in 2003 was going to lead to something.","offset":3405,"duration":27},{"text":"Rory: But right, we saw the same kind of buildup off the coast of Venezuela earlier this year or late last year. And in that moment, you know, there was blockade, there was everything else. But when it finally all went down that first weekend in January when the Trump administration, you know, uh, kidnapped Nicolas Maduro uh, and his wife...","offset":3432,"duration":21},{"text":"Rory: ...basically that happened on a Saturday, or Saturday morning, I guess. There was all this, you know, what's happening, what's happening, what's happening. And then by Monday, you know, we had Delcy Rodriguez in as the interim president. She was making a deal with President Trump and it was kind of, it was wrapped really quickly.","offset":3453,"duration":17},{"text":"Rory: The same thing happened last June when we last talked about the worry of the Strait of Hormuz, was that um, the Trump administration embarked on what at that stage was a fairly stark break from US military policy towards Iran, which is, you know, it had directly engaged in 14, dropping 14 bunker-buster bombs on uh, Natanz and Isfahan.","offset":3470,"duration":24},{"text":"Rory: And again, if you remember, and I'm sure you remember this Eric, the, like the Monday when that—or Asian markets opened at the end of the weekend, prices spiked higher as you would expect after this kind of event. And then by mid, mid, you know, by the middle of Monday, we saw this kind of symbolic retaliation from Iran. And then Trump saying we've got a peace, we've got a ceasefire.","offset":3494,"duration":22},{"text":"Rory: ...deal. And then I think crude ended the day down $10. That was kind of my framework for what was expecting out of this conflict. And by that token, I had expected that, you know, it was very clear that Cuba was next up on on the list of kind of regimes to roll over. And I think Trump planned to be basically be rolling over on Cuba by now.","offset":3516,"duration":26},{"text":"Rory: And the wrinkle here is that if they were expecting some kind of Delcy Rodriguez character to emerge in Iran, someone to say—someone to give them the opportunity to declare victory. I think he would have. And I think that what we've seen so far is that the Iranians have not done that.","offset":3542,"duration":15},{"text":"Rory: And I think if Trump expected the political culture of Venezuela to be the same as the political culture of Iran, that I think is probably arguably the biggest miscalculation here from the White House. As for what's actually preventing the, the, you know, the passage through the strait. Because again, when we look historically, the strait has never been closed.","offset":3557,"duration":27},{"text":"Rory: Even when we've had acute violence, acute attacks in the strait back in the 1980s during the Iran-Iraq war, during the tanker wars, we saw hundreds of ships hit. We saw by, by the calculations I saw was 450 ships attacked. Uh, you had 250 tankers attacked and 55 of those tankers were basically either sunk or scuttled and otherwise abandoned by crews. Like we more than we've already seen now. And during that time, you never had flow halt through the strait.","offset":3584,"duration":32},{"text":"Rory: So that was our best historical parallel and quite frankly, I expected something similar to be happening here. And what we've seen so far is that no, uh, very, very few—I mean the estimates vary, but basically like between a 90 and 95% reduction structurally now through the Strait of Hormuz.","offset":3616,"duration":26},{"text":"Rory: And with things like insurance, I think there was this expectation that okay, maybe at the beginning it was the lack of insurance. Uh, we were waiting for these, you know, these tanker owners to and the insurance...","offset":3642,"duration":19},{"text":"Rory: ...providers to figure out a way to say, okay, you know, we're going to figure out a way to lift—obviously the risk is increased, so we're cancelling coverage and we're going to kind of reinstitute. But, but there was just, you know, that never happened. You ended up actually seeing, and we've seen reports more recently that, you know, the war insurance has skyrocketed.","offset":3661,"duration":19},{"text":"Rory: If it was basically 0.25% of a vessel's value kind of in the month before the war, uh, that is now by the latest estimates that I've seen published by Bloomberg jumped to 5%. So we're talking a massive, massive increase. That's like a $5 million insurance premium on a million on a $100 million vessel just to cross the strait.","offset":3680,"duration":26},{"text":"Rory: But the issue is that even at those insane levels, the arbitrage value across the strait still seems to clear. That, you know, we now have effectively negative prices on the bad side of the strait, and we have on a physical basis on Dubai, over $150 a barrel. You can very easily cover that with this insurance.","offset":3706,"duration":24},{"text":"Rory: And they're not. And I think that is where something else is happening. And I think my best explanation for this, and I think it's also an explanation you're going to hear me talk about through the financial—the relatively sanguine financial impacts that we've seen so far, is that the market continues to expect—the base case expectation is that Trump backs out here.","offset":3730,"duration":25},{"text":"Rory: That we see another taco. And if that's the case, if there's the chance that tomorrow this ends, or at least he declares it done, um, why spend the $5 million and risk your ship...","offset":3755,"duration":26},{"text":"Rory: ...and crew if this could be over tomorrow. And I think there's this continual hope that this is going to end because, as we will talk about, the consequences of it not ending are so extreme that it is unthinkable to me that a US president would bear the political cost of what's coming down the pipe.","offset":3781,"duration":23},{"text":"Host (Eric): Well let's talk about that specifically next then. I think you and I could easily agree that—and I'll just go to an extreme here—if this continued for a year, if there was no transit or no significant meaningful transit of the Strait of Hormuz for a year, that would result in probably a bigger than 2008 global financial crisis because it would shut down the entire global economy. There's no energy, there's no economy. That's the end of the story.","offset":3804,"duration":26},{"text":"Host (Eric): Okay, if it's—you know, we can't go a year, but we could go into next week. Okay, how long is that fuse? What—are there tipping points where after a certain point things are broken that can't be fixed because the backlog is too long? What does the timeline look like of how long this can continue before you get into a situation where it's not reversible?","offset":3830,"duration":24},{"text":"Rory: The first thing I want to say Eric is I completely agree with you. I think that if this goes on for a year, and again, I cannot imagine—like the level of economic calamity, of human catastrophe that would wrought is unimaginable to me. I mean, we'll walk through it briefly here, because I think it's important to try and imagine it. But again, I just can't imagine the political—any politicians kind of engage, you know, bearing that political consequence.","offset":3854,"duration":27},{"text":"Rory: Because what we're talking about, to your point, like I mean, I'm normally not a guy that comes, you know, comes up with like big price calls. I typically, I don't like them. But like I've been saying that yeah, $200 crude is easy in this scenario. If we're, if we're talking a year or more, like 200 is the bare minimum of what you'd expect. We need to—I've been trying to parameterize what we're actually talking about. And...","offset":3881,"duration":142},{"text":"Rory: ...if let's say, just for this heuristic here, we talk about 20 million barrels a day of oil flow through the strait. Let's even just knock it down to 15 because maybe we get, you know, the East-West pipeline and Yanbu and everything else—everything works well with the Saudi diversion plan.","offset":4023,"duration":16},{"text":"Rory: Let's say 15. That is ballpark the peak of the demand destruction we experienced in March and April of 2020 during COVID when everyone was locked in their homes, you had not an airplane in the sky, you know, major airports were effectively shuttered. That's the kind of demand destruction we would be needing to balance that market.","offset":4039,"duration":25},{"text":"Rory: But with no pandemic, and just, just purely through price mechanisms. That is an extraordinarily high price to clear that kind of demand destruction. I've been basically just kind of saying that like, you know, me, I have an extraordinarily low price sensitivity for gasoline to get my kids to school in the morning.","offset":4064,"duration":20},{"text":"Rory: But a lot of people both in wealthy countries, obviously this, you know, it's going to be effectively a massive regressive tax. Um, but I think in wealthy economies we will generally experience this as a debilitating recessionary, you know, nigh depressionary price shock that will sap consumer spending, that will have all of the normal repercussions we would think about.","offset":4084,"duration":23},{"text":"Rory: But the price spike isn't enough, because you still need to shed that much demand from the global system. And where is that going to happen? It's going to happen in poorer emerging market countries in the Global South. That when we see price shocks, they will see shortages.","offset":4107,"duration":16},{"text":"Rory: Uh, we saw this in kind of notorious fashion now in 2022 when the kind of the infamous example of the—of the committed tanker to Pakistan that they broke their commitment, uh, they paid the breakage fee and they shipped that gas to Europe because they could make a, you know, a king's ransom on the arb even factoring for the breakage fee.","offset":4123,"duration":14},{"text":"Rory: And that's how markets are going to clear. That's how they're supposed to clear in this system. So I'm not saying that's wrong per se, but there is going to be an enormous human cost here. And I think when you're talking about these fuels, you're talking about electricity, you're talking about heat, you're talking about cooking. You're talking about life. And I think that's what we're going to have to try and trim back by 15 to 20% if this persists. And that is just insane.","offset":4137,"duration":28},{"text":"Host (Eric): Let's try to put some specific time frames on this, which I know is difficult and I apologize for doing this to you. But as you said, what's going on here is most people are thinking, well surely this is about to be over. I mean, it's—it's crazy to continue it, it's about to be over, it must be about to be over. Just in case it's not, let's imagine both a three-weeks-more scenario and a three-months-more scenario. What do each of those—if you had to guess—the impact of three more weeks, just like the last three weeks or however long this has been? And then three more months. What—what do those scenarios look like in your mind?","offset":4165,"duration":37},{"text":"Rory: So let's actually start with the even more sanguine scenario. What happens if it ends today? Because I think there's already durable damage. And I think a lot of people just assume that we could end this tomorrow and everything goes back to normal. We're probably talking three months minimum to, to re-normalize this system, even if it stopped today and every tanker currently in the Gulf made a break for it and they all made it out and we just resume full flow and everything like nothing ever happened.","offset":4202,"duration":28},{"text":"Rory: Even in that case, we're talking about months of supply chain recovery because these ships are being piled on top of each other. You've had—you've already had roughly a 400 million barrel gap or 330-340 million barrel gap that's emerged in the, basically the normal flow of oil into the Middle East, largely to Asia.","offset":4230,"duration":22},{"text":"Rory: Right now, we're still—we still haven't felt the brunt of that because three weeks ago, we still had tankers laden with oil leaving the Gulf. Those tankers will continue to their destinations, takes three, four weeks to get where they're going. And when that air pocket finally hits land in Asia, that's when we're going to start drawing inventories at 10, 15 plus million barrels a day.","offset":4252,"duration":23},{"text":"Rory: Which again, has never happened before. We've already seen Asian refineries attempt to short—basically frontrun this, to extend their runways. They've reduced operating rates, they've cut product output. So we are talking we've seen a $150 crude in Dubai in physical crude, but we've seen over $200 a barrel jet fuel in Asia...","offset":4275,"duration":19},{"text":"Rory: ...I mean Singapore. And I think that is, that alone would take months to sort out. But let's go to that three-week scenario. Okay, so let's say we're already in this for three weeks, let's say it's double. Now you're looking at two-thirds of a billion barrels of air pocket in the system that, again, needs to get sorted out.","offset":4294,"duration":18},{"text":"Rory: By that stage, we've already seen upwards of 9 million barrels a day of crude oil production capacity shut in through the Gulf. The longer that's off, the—the longer the strait is closed, the more we're going to see that cut back. And again, as anyone familiar with this industry, it's not trivial to shut in these wells, it's not trivial to get them back on without any kind of negative repercussions.","offset":4312,"duration":19},{"text":"Rory: And all that stuff just gets worse with time and time and time. I think, you know, in terms of price call, I think in three more weeks of this, I think we could—I think we would already be over $150 Brent. We're already obviously there at the kind of physical Dubai cash market.","offset":4331,"duration":15},{"text":"Rory: And I think people are like, well, well why wouldn't, you know, why wouldn't anyone buy that that crude? Uh, why wouldn't you just...","offset":4346,"duration":6},{"text":"Rory: ...buy buy WTI? It's like $50 or $60 cheaper. And the answer is that it's in the wrong place at the wrong time. You know, if you're buying the prompt WTI—WTI futures, it's not for delivery until next month, and you need to get it from Cushing to the coast, then you need to get it from the coast to the Middle East, to Asia. That we're talking months.","offset":4352,"duration":16},{"text":"Rory: People need these barrels today. And that is why I think there was still this kind of hopium, if you will, from Asian refinery saying, like, okay, this is going on, but like surely this can't last. And what you've started to see over the last couple days—there's a Bloomberg report this morning—where Asian refineries were starting to bid into the Brent basket.","offset":4368,"duration":20},{"text":"Rory: And they're starting to kind of try and buy these fut—these other barrels, which means that they're now worrying that this is going to be going on for months. Uh, and it also means that kind of acute local scarcity in crude in the Middle East and products in Asia is also going to begin spreading out to all the rest of the world.","offset":4388,"duration":17},{"text":"Rory: And I think it's really easy for Americans and the American president to say, ah...","offset":4405,"duration":5},{"text":"Rory: ...who cares about tight oil markets in the Middle East? We're here and oil prices are still pretty low. It's because this shockwave kind of moving out through the system takes time to kind of incentivize and bid all those barrels over. And I also think back to this why aren't ships going through, because they, you know, maybe they think Trump's going to taco.","offset":4410,"duration":19},{"text":"Rory: I also think that the futures market are in the exact same situation. What we saw not, you know, two Mondays ago, the, you know, the second weekend that again, everyone thought he was going to end on the weekend. He didn't. Prices spiked higher, you hit almost $120 barrel Brent. But then you got the first kind of Trump said the—the war's almost over, and prices cratered. You had a $35 a barrel intraday spread in Brent, which I don't believe has ever happened before.","offset":4429,"duration":29},{"text":"Rory: And a lot of traders kind of lost their shirts in that because again, bidding crude higher was the obvious directional call in this environment. But the kind of constant jawboning, you know, those people got blown out of their positions, many of them lost their jobs. People are much more wary now to kind of frontrun, because normally you'd expect futures markets to frontrun the tightness in physical markets because markets are forward-looking. But I think now we have to wait for that physical market tightness to kind of fully and aggressively manifest in the West before those future prices are going to actually converge.","offset":4458,"duration":40},{"text":"Host (Eric): Now you said earlier that you thought the Trump administration had no idea that this outcome, which has already occurred, was even possible. I want to push back slightly on that and ask you if it's possible that maybe they did see it as a possibility, but just were not as concerned by it as you and I are. I want to read you a Truth Social post from President Trump on Wednesday where he says, \"I wonder what would happen if we finished off what's left of the Iranian terror state and just let the countries that use the Strait of Hormuz—we don't—let them be responsible for the so-called strait. That would get some of our non-responsive 'allies' in quotes engaged and fast,\" signed President Donald J. Trump.","offset":4498,"duration":48},{"text":"Host (Eric): It sounds to me like he doesn't think it's a big deal for the United States since he perceives the United States to be energy independent, that if the Strait of Hormuz is closed down, it sounds like he thinks that's a problem that affects other countries but doesn't affect us. So, you know, the hell with it, let them worry about it. I don't—I'm not going to bother asking you whether we should be concerned about it, because I think you and I agree that we should be concerned about the strait needs to be open uh, for the sake of global commerce. Oil prices are set globally and so forth. But it does seem like there's room that the reason the president's not so concerned about this outcome is not that he didn't foresee it, but that he's just not as worried about it as you and I are.","offset":4546,"duration":49},{"text":"Rory: I think there's a chance of that, and I—I think again, I didn't expect him to go this far. So I'm—I can't pretend perfect knowledge of Trump's mind by any means. But I think what we've seen in those comments over the past two and a half weeks now is evidence of remarkable goal shifting.","offset":4595,"duration":16},{"text":"Rory: We had that—we had that tweet this week. End of last week, we also had the tweet about how actually high oil prices are good for the United States because the United States is the largest oil producer in the world. But that contrasts strongly with some of the earlier comments out of Trump about, you know, basically don't be a panicking, don't bid up the price of oil, you know, this is going to be fine, the war's almost over.","offset":4611,"duration":18},{"text":"Rory: Like it definitely felt like he was trying to keep the oil prices lower. And then as oil prices started to inevitably, based on this kind of physical reality we've been discussing, as those prices started to grind higher, he started to find new ways to say, oh, okay, this is actually good for us.","offset":4629,"duration":17},{"text":"Rory: And I actually think in some ways, that's actually the most worrying development in this because I think at least my mental framework here has always been that the oil market would be the single—the singular thing that would end up pushing Trump back from the edge, from really going through for a prolonged period of time, months or or longer.","offset":4646,"duration":21},{"text":"Rory: And if we're starting to see him attempt to, to change that narrative to almost convince himself—and again, like Donald Trump is an extremely public person. He's been for—he's been against high oil prices and...","offset":4667,"duration":13},{"text":"Rory: ...trying to drive them lower since the 1980s. Like low oil president is kind of like his brand. And I would say that—so I don't know how much I can really buy this. I don't even know how much he can really buy this depending how long this goes. I still think his core bias is towards low oil prices.","offset":4680,"duration":19},{"text":"Rory: Again, he was elected as kind of a pocketbook cost of living president. And I think this is just—he was also elected as a president that would get out of wars in the Middle East. But we're very—we're obviously in a very, very different timeline now from that election.","offset":4699,"duration":16},{"text":"Rory: So again, I think there's a possibility that you're right, you're right Eric. But I do think that a lot of this is him saying things after things don't go his way. For instance, the comment about the strait came mostly after he asked all of the kind of allied NATO nations and Asian nations that consume the oil to kind of come help them, and they were kind of like, no.","offset":4715,"duration":18},{"text":"Rory: Because again, I think the world, a lot of the consuming world, like I think if they knew 100% that this was going to go on for years, yeah, they're going to send their navies because again, this is untenable. But I think there's this worry, I think there I even heard this worry initially with the SPR releases, that like anything you do to ameliorate the oil price consequence to a degree short-circuits Trump's own feedback mechanism.","offset":4733,"duration":37},{"text":"Rory: That the only way he was going to back down—and this is a similar to the tariffs, that when you know the S&P was crashing, that's when he tacoed. There was an expectation that this was the same mechanism that would be seeing now but with oil. And I worry that is beginning to lose its sensitivity given that I think now it's a question of how can Trump figure out a way to declare victory? Because again, he's not going to stop this unless he can say he won. So I think he's trying to find ways, trying to find something that he can declare victory on.","offset":4770,"duration":27},{"text":"Rory: And again, I thought at the beginning, there was enough at the—at the gate...","offset":4797,"duration":4},{"text":"Rory: ...right? We wiped out the leadership, you killed the Ayatollah, all of this stuff. I think he could have declared victory on that first Monday. And I think he's like, oh, well, let's do this a little bit longer. And now we're in so deep that it feels like you need something much bigger.","offset":4801,"duration":15},{"text":"Rory: And if anything, the Iranian regime seems to be entrenching. At the beginning, you did hear—I mean, when there was a lack of centralized leadership, you had different elements that were being more negotiating or kind of conciliatory. And that it seems is beginning to fall by the wayside.","offset":4816,"duration":17},{"text":"Rory: And I think even for a while there was some hope that the number of missiles and drones that were being launched every day by Iran were dwindling over time. Like oh, is Iran running out of missiles? Are we entering the endgame?","offset":4833,"duration":11},{"text":"Rory: And over the last two days, they've shot back up. That—and again today in particular—we we were chatting about this before we started recording, but like Brent popped above 110 following Israel's attack on the South Pars gas field, which up until now we hadn't been hitting...","offset":4844,"duration":16},{"text":"Rory: ...upstream and kind of Iranian oil assets, oil and gas assets specifically. And that's why up until now, most of that production assets hadn't been hit. You've had—you had a couple refineries hit. You had Ras Tanura, you had—you've had attacks on Fujairah. But overall, there are a lot more targets across the Middle East that were very, very tempting targets. I mean, we all remember Abqaiq in 2019. Clearly the Iranians can hit it.","offset":4860,"duration":29},{"text":"Rory: They have chosen not to yet because it—again, for them, I think that they still have this conception of different degrees of escalation. And what we saw already was as soon as the South Pars gas field was hit, they were like, okay, now these bunch of petrochemical facilities and upstream facilities, they're all legitimate targets now.","offset":4889,"duration":24},{"text":"Rory: And they also warn that if Trump bombed Kharg Island, they're like, well, if you do that, then we view all other ports in the region as fair game. I think they are still trying to kind of parameterize their own escalation or retaliatory kind of spiraling here.","offset":4913,"duration":11},{"text":"Rory: But, and again, I think what we've seen so far is that in both cases where Israel and to my knowledge, these were both Israeli attacks specifically on the South Pars gas field and the fuel depot in Central Tehran, that those were kind of against the wishes of the White House.","offset":4924,"duration":16},{"text":"Rory: That, you know, there is still some kind of freelancing here on the Israeli side about like how far they're going to go and how much they want to escalate this. Clearly they want—they want more escalation, right? I think that's clear than what we've seen so far.","offset":4940,"duration":13},{"text":"Rory: But I do wor—I do wonder whether or not that's the kind of thing that's going to piss off Trump, quite frankly. We—we saw this, uh, he got really upset with the Netanyahu government last June when, you know, there was worry that they weren't going to play ball with the ceasefire or whatever else. There was like that famous comment uh, as he was trying to get on Marine One. But I do worry that that's the kind of situation we're ending up in now.","offset":4953,"duration":23},{"text":"Host (Eric): Normally, Rory, people who are in macro markets and, you know, investors...","offset":4976,"duration":5},{"text":"Host (Eric): ...who are not specialists in oil only pay attention to two benchmarks. Brent crude, which is based on North Sea oil production, is the global benchmark and then West Texas Intermediate is the US benchmark. Uh, normally it's only professional oil traders who pay attention to any of the other prices in the oil market.","offset":4981,"duration":20},{"text":"Host (Eric): Let's talk though about some of the other prices, because really Brent and WTI only got—I guess WTI was 119. Neither one of them has gone above 120 in this. That's, uh, you know, they've gone up a lot, but they haven't gone up that much. I think it was Oman traded above 185 this week? Uh, as you said, there was jet fuel prices above 200 in Singapore.","offset":5001,"duration":25},{"text":"Host (Eric): Should we be thinking about these really high prices that are occurring in some localized markets as oh well, that's just a logistics thing, it doesn't really count? Or are those price signals that could portend what's coming for Brent and WTI?","offset":5026,"duration":15},{"text":"Rory: They're exactly what's coming for Brent and WTI. Because I think I've kind of talking around this point a little earlier, but what we're talking about right now is again, the—these markets, and you will know this well Eric, that futures and benchmarks, there is both a locational element to it and a time element.","offset":5041,"duration":19},{"text":"Rory: And where the current tightest market is right now is basically there's all these laden tanker or unladen tankers waiting to go back into the Gulf to fill up. And they're like, well, I could buy some crude off the coast of Oman and just basically turn around and head back.","offset":5060,"duration":16},{"text":"Rory: But those are the barrels that are at $150 or 100—I hadn't honestly seen Oman go up to 1—180. But yeah, that's basically, yeah, you can charge a king's ransom for any barrel that's physically available on the good side of the Gulf right now because that's where crude is in desperate, desperate supply because it's much faster to get to Asia from there than from the US Gulf or from the North Sea.","offset":5076,"duration":23},{"text":"Rory: And I think that is what we're going to see eventually for the other benchmarks. That now that Asian buyers in particular are coming to the realization that this isn't ending tomorrow and that they may need to cover not just today's crude slate but tomorrow's or next month's crude slate.","offset":5099,"duration":20},{"text":"Rory: Now they are beginning to bid on those other contracts, which again, is why we're starting to see Brent firm up so much more. That we're kind of back to above 110. WTI I think has some other potential weirdness going on. There's been a lot of talk about atte—you know, participants trying to hedge their SPR exchanges. Lots of stuff going on there as well.","offset":5119,"duration":22},{"text":"Rory: But I do think overall, the best thing that explains WTI's relative underperformance relative to Brent and certainly relative to the Middle Eastern grades is that the furthest grade away. That takes the longest to get to where you're going. And I think that's going to be something that will continue to kind of leave WTI at the back of that—of that bus, if you will.","offset":5141,"duration":19},{"text":"Rory: The other thing we haven't talked about yet, and I think where I'm especially concerned that we could be going. Because again, Trump says this is good, he doesn't care. But eventually pump prices are going to rise. We already have US average diesel prices over $5 a gallon. Gasoline's coming up there too. Diesel's going to go higher, jet fuel's going to go higher.","offset":5160,"duration":19},{"text":"Rory: I worry that we're going to see kind of a rediscussion or we've already seen musings about export controls out of the United States. That this was actually something that the Biden administration mused in 2022. They're like, well, well, could we restrict or ban the export of refined products?","offset":5179,"duration":17},{"text":"Rory: There are a lot of issues with that. It bottles up diesel in the Gulf Coast, it, it, it creates issues with potential res—reciprocal trade restrictions if then Europe decides to ban the export of gasoline to into the East Coast. There's a lot of problems there. But I do think that's where this could go.","offset":5196,"duration":17},{"text":"Rory: And I think particularly, you're seeing some of that like the framework and the kind of precursor to that argument being put out by Trump. And I think back to that question of he's saying we don't get any oil from this strait, so what do we care? And then your point, well, because markets are global. The way to solve that is to make markets not global.","offset":5213,"duration":21},{"text":"Rory: And I think that is my—is my most acute worry here going into this, is that I'd mentioned earlier that, you know, wealthy nations largely will be able to afford the oil and the products. It'll just be debilitatingly expensive.","offset":5234,"duration":13},{"text":"Rory: Once you start mucking with trade, even the United States, which is a net petroleum exporter, we you well know that that's not the same in crude or quality. That's not same in product slate by region. You've even seen the—the repeal or at least temporary waiver of the Jones Act, which is a very substantial political move for the White House.","offset":5247,"duration":20},{"text":"Rory: That really makes the most sense in the context of well, what if we ended up, you know, banning exports? Well then we could use non-Jones Act tankers to move US Gulf Coast crude to different area or US Gulf Coast oil, but also diesel to other areas of the country rather than it being bottled up.","offset":5267,"duration":12},{"text":"Rory: Because if you have no ability to shift out from those regions...","offset":5279,"duration":1},{"text":"Rory: ...you would basically end up forcing US crude production shut-ins and US particularly Gulf Coast refining shut-ins, which is the opposite of what you want. So temporarily it would lower prices, and I think that's why it would be very attractive for the White House. But in the long term, it would short-circuit wealthy markets' capacity to just pass this on through price. And then we would likely end up facing physical shortages in these advanced markets.","offset":5280,"duration":28},{"text":"Host (Eric): Rory, when we hear about the Strait of Hormuz, what comes to investors' minds is of course crude oil. But tell me about how fertilizer plays into this story as well.","offset":5308,"duration":11},{"text":"Rory: Yeah, so I am not a fertilizer expert, but in addition—I mean, we've all been focused on oil and maybe gas, but there's a lot of other things that come from the Gulf, whether it's fertil—I think it's a third of global fertilizer supplies, the vast majority of global helium supplies. All these things are going to have their own knock-on consequences to all these other markets as well.","offset":5319,"duration":13},{"text":"Rory: I think when you think about fertilizer and even I think this ties back into to oil products as well, if this continues...","offset":5332,"duration":8},{"text":"Rory: ...we will see crop yields decline. We will see food production decline. We will see the food that does get to your plate more expensive on the commodity basis of the food itself, and being shipped there by either by truck or by plane at far more expensive rates.","offset":5340,"duration":15},{"text":"Rory: So this is absolute—I mean, again, this is, you know, our most recent experience here with—and again a where all this goes with monetary policy as well. Our most recent kind of parallel is 2022 that central banks got acutely—and I think reasonably—freaked out at the time by the explosion of inflation coming out of the COVID bullwhip effect.","offset":5355,"duration":23},{"text":"Rory: And for the first time in my life, central banks took a—took a keen interest in following the price of oil, and particularly the price of gasoline. And that's when I think the way this all feeds back into the macro side is this—you know, if there's anything that is going to unmoor long-term consumer inflation expectations, it's this kind of shock.","offset":5378,"duration":22},{"text":"Rory: It's, you know, this last time we experienced this would have been in the '70s. This shock, if continued, will make the '70s look like child's play. I think a lot of people still go back and think wow, we must have lost a massive amount of supply back in '73 or '79.","offset":5400,"duration":17},{"text":"Rory: And there were some losses, but the losses were relatively small. And the big thing was it was more of a logistical like we're not shipping to you, so that's causing gaps here and everything else. But a lot of it was, you know, the supply wasn't acutely lost to the degree that we are currently seeing it lost today.","offset":5417,"duration":17},{"text":"Rory: And it just sets us up for a much worse kind of price shock. And again, I think going back to this like even if this ended today, we're co—we're sewing the seeds of these like deep ripple effects, these deep kind of multi-industry bullwhips that are going to be working through the system. That even if you ended today, we're still going to have consequences trailing out for months.","offset":5434,"duration":20},{"text":"Rory: And if we and if this goes three weeks longer or heck, as you mentioned, three months longer, oh man, like these industries are going to break...","offset":5454,"duration":6},{"text":"Rory: ...and people will need to cut back. There will be physical losses that people will have to experience. And that's where I go back to. I don't see this as tenable long-term politically for anyone involved. But I also thought that so far and I've been wrong.","offset":5460,"duration":18},{"text":"Host (Eric): Rory, I can't thank you enough for a terrific interview. Before we close, I want to add a quick point just of clarification about last week's interview with Dr. Anas Alhajji. Several of you on Twitter and in email said, \"Hey, Anas was wrong when he said that Iran had a huge vulnerability if their desalination plants were attacked. Iran only gets 3% of their water from desalination.\"","offset":5478,"duration":25},{"text":"Host (Eric): I agree it was a little bit ambiguous how it was worded, but that was not Dr. Alhajji's intended point. The point that he was making is everybody presumes that Israel has a nuclear weapon and Iran doesn't. His point was Iran effectively does have a nuclear option which is the other Gulf states. Not Iran, which only needs to rely on desalination for 3% of its own water, but the other Gulf states, including Israel, are heavily dependent on desalination. So it is the risk of Iran striking the desalination plants of Israel and other countries that would be the equivalent of a nuclear escalation and would probably result in Israel responding with a nuclear response. So that was the point that Dr. Alhajji was making.","offset":5503,"duration":46},{"text":"Host (Eric): Rory, I want to come back to what you do at Commodity Context for anybody who's not familiar with it. Terrific website. Please give us your Twitter handle and tell people what they can expect to find at commoditycontext.com.","offset":5549,"duration":12},{"text":"Rory: Thanks so much for having me again Eric. I always love coming on the show. You can follow me on Twitter at uh, @Rory_Johnston. And all of my public research is published at commoditycontext.com. We've got an—the Oil Context Weekly report every Friday that covers—I currently call it the Oil of the—the Oil and Iran War Context Weekly because that's all we're talking about.","offset":5561,"duration":18},{"text":"Rory: But every Friday at 4:00 to 5:00 p.m. Eastern, uh, I publish three monthly uh, data reports on OPEC, global balances, and North American detailed balances. And then I also am doing particularly these days, a lot of thematic work on Iran, on Venezuela, and the overall insanity in this current oil market. And I encourage you to join me.","offset":5579,"duration":23},{"text":"Host (Eric): Patrick Ceresna and I will be back as MacroVoices continues. And stay tuned, folks. Case you didn't connect those dots, Simon White told me earlier in this podcast that we needed to worry about food price inflation next. That was even without considering the fertilizer angle that I just discussed with Rory. So Patrick's trade of the week is going to be about food inflation and how to hedge against it. That's coming up next right here at macrovoices.com.","offset":5602,"duration":31},{"text":"Host (Eric): Now back to your hosts, Eric Townsend and Patrick Ceresna.","offset":5633,"duration":7},{"text":"Host 1: So if you think that the Trump administration has this whole situation completely under control, it's going to be over in another week or so, just like the President and Secretary Hegseth say it's going to be, then in that case, if that's what you think, then this is a terrific buy-the-dip setup. It probably sets the stage for a rally to new all-time highs.","offset":5640,"duration":26},{"text":"Host 1: If President Trump can really get this all under control and wrap it up and there's no lasting impact from it—and to be sure, in order for there to be no lasting impact, it really needs to get wrapped up pretty quickly here—if you think that's what happens, then it's time to buy this dip and buy it in size because we're going much higher.","offset":5666,"duration":18},{"text":"Host 1: On the other hand, if you don't think that, if you think that the Trump administration has started a fire that they won't be able to put out and that this is not under control and that this Iran conflict might turn into a repeat of the Iraq debacle that began in 2003, well, if that's what you think—because we're leaving my politics out of this one—that would portend a very, very different equity market outcome.","offset":5684,"duration":28},{"text":"Host 1: We could easily be looking at a cyclical bear market, and the worst case would be if oil transit through the Straits of Hormuz stays impaired for many months. In that scenario, without exaggeration, it could lead to an oil price surge well over $250 a barrel. That would cripple the global economy and lead to a global financial crisis on the scale of, if not bigger than, 2008.","offset":5712,"duration":30},{"text":"Host 1: Now, I strongly doubt that that would be the outcome because this is a problem that can be solved sooner than that. We're not going to see the Straits of Hormuz closed for years or anything like that.","offset":5742,"duration":12},{"text":"Host 1: The question is how long this goes on, how much damage it causes, and how long it takes to unwind that. In other words, how big is the backlog of global logistics that have been disrupted by the Straits of Hormuz closure? How long does it take to get things back to flowing as normal again?","offset":5754,"duration":19},{"text":"Host 1: That's really, I think, what's going to drive equity prices, and frankly, I don't think anybody knows for sure what's coming next in this market. So it really comes down to your geopolitical outlook. I think all of us are vulnerable to allowing our personal politics to bias our judgment as investors. So remember, this market reaction is not going to depend on what you think or what I think should happen. It's going to depend on what actually happens, and I don't think any of us know with any real certainty exactly how this is going to play out.","offset":5773,"duration":34},{"text":"Host 2: Eric, I'm going to keep my analysis very simple from a technical perspective. We're remaining below the 50-day moving average, we're breaking lower highs and lower lows, there is clear distribution. The bears are in control and in the driver's seat on the short term on the distribution side. We continue to see all rallies failing at Fibonacci zones, which is all indicating that generally the distribution cycle is still in play.","offset":5807,"duration":28},{"text":"Host 2: Now, while we have seen substantial increases in bearishness as the sentiment is pivoting, we've seen huge spikes in volatility index and other things that are signs that you typically would see from oversold conditions. But right now with enough of this global uncertainty here, this could be an overhang that keeps this market distributing.","offset":5835,"duration":25},{"text":"Host 2: Now, Eric, we certainly can't rule out that at some point the bulls will reverse this and counter-trend it. This is again the environment where hedges are critical, and we've talked about them the last couple weeks with our listeners, and I continue to advocate that portfolio insurance here makes a whole lot of sense. All right, Eric, let's talk about that US dollar.","offset":5860,"duration":28},{"text":"Host 1: Now, Patrick, by recording time we were back down to a high 99 handle after surging above 100 and then below 100 intraday on Friday. I think by the cash close we were back over 100 again. So we're right on that hairy line between 99 and 100.","offset":5888,"duration":18},{"text":"Host 1: The question to ask is whether we're topping out here at overbought resistance on this technically overbought market or if the strength that we've seen in the dollar so far is just the beginning of a new bullish trend. Once again, I think the answer depends on your geopolitical outlook. Sorry folks, that's going to be the answer for most things this week, and there are plenty of strong arguments to be made in either direction.","offset":5906,"duration":25},{"text":"Host 1: I don't see any fundamental bullish drivers for the dollar here other than the flight to safety trades into the dollar, which are only going to intensify if the situation in Iran worsens from here and if equity markets take a nosedive.","offset":5931,"duration":19},{"text":"Host 1: So there's plenty of room for much, much more upside in the Dollar Index. But ultimately, I think that upside would be driven by flight to safety trades in the Iran conflict. Someday when the Iran conflict wears off or winds down, then I think it becomes a bearish... it's time to sell the dollar there because I think it will be overbought and ripe for a major correction, maybe resuming the primary downtrend that was in play before this conflict arose. The question is timing: how much longer before this Iran conflict is over? Whenever it's over, that's the time I think you want to sell the Dollar Index.","offset":5950,"duration":40},{"text":"Host 2: Well, Eric, when looking under the hood of the dollar, the key thing is to observe that the predominant weakness is coming from the Euro and the Yen, which happen to be very large weightings in the Dollar Index. But the story isn't the US dollar strength and all cross-currencies weakening against it.","offset":5990,"duration":22},{"text":"Host 2: We continue to see resilience in a lot of the commodity-based currencies like the Aussie dollar and the Canadian dollar, and that Euro is really where the drag is as there continue to be growth concerns at a time when obviously their energy prices are under a lot of pressure, which is stressing the Euro right now on the downside.","offset":6012,"duration":22},{"text":"Host 2: If we see Euro breaking some of these key levels, that then is going to be a huge bullish tailwind for this Dollar Index. Now we're at the top of an almost a 10-month trade range, and if the Dollar Index makes any progress above this 100 level with momentum, we've got ourselves some sort of a strong US dollar counter-trend move. And so we have to watch whether or not this gains momentum from here. All right, Eric, let's touch on crude oil.","offset":6034,"duration":30},{"text":"Host 1: Well, as I already discussed with Rory Johnston, the Oman benchmark traded over $180 this week. Obviously, logistic complications are part of that, but it's still an important price signal.","offset":6064,"duration":12},{"text":"Host 1: I'm sorry to sound like a broken record folks, but it's the geopolitical outcome with Iran that's going to drive everything. As Rory Johnston said, I think it would be foolish to assume that, hey, it's going to be just a couple more days and the Trump administration is going to completely end this thing.","offset":6076,"duration":19},{"text":"Host 1: Even if it ends this week, we still have probably a couple of months at minimum just to clear the system out and get things back to flowing as usual. And the longer that the conflict wears on, the more that effect is compounded and the more of a mess we're going to have to unwind.","offset":6095,"duration":17},{"text":"Host 1: So the longer this continues, the more it's going to affect oil prices and cause a continued increase in oil prices and the inflation signal that that drives. And eventually, it becomes a self-reinforcing vicious cycle of increasing inflation driving even more extraction cost price increases, higher oil prices, and so forth. Hopefully, we don't get to that point where that self-reinforcing cycle kicks in.","offset":6112,"duration":29},{"text":"Host 2: All right, let's move on to gold here because we just got ourselves a little bit of a down day here on Wednesday. What's your take of what's going on?","offset":6141,"duration":8},{"text":"Host 1: The low print on the January 30th correction was 44.23, 4423. That was a near perfect test of the 50-day moving average at the time. But that happened in the middle of the night in very thin liquidity.","offset":6149,"duration":12},{"text":"Host 1: So something I said right here on MacroVoices just a few days later was we should watch for another test of the 50-day moving average during regular trading hours, not extended trading hours. Well, we got that on Wednesday, and it also coincided almost perfectly with the 38.2% Fibonacci retracement level of that January 30th correction. There was also a trendline there as well.","offset":6161,"duration":25},{"text":"Host 1: So three major support lines all broken at the same time. So there's a very good technical argument that could be made here, which is that that regular trading hours test of the 50-day moving average was the buy signal. The bottom could be in already.","offset":6186,"duration":15},{"text":"Host 1: Except we went right through it and we're trading considerably below it at recording time. I'm looking at 48.24 as we're recording right now, selling off more in futures trading after the close. These are all ominous signs and frankly, there's not a lot of obvious support until we get to the 100-day moving average at 45.91, 4591.","offset":6201,"duration":45},{"text":"Host 1: So I think we're probably headed in that direction unless there's a sudden change in the fundamentals. But it's also clear that there's been a breakdown of correlations between precious metals and the usual, you know, if it's increase in tension in Iran, more geopolitical upset, that would normally be up on precious metals.","offset":6246,"duration":21},{"text":"Host 1: That broke down on March 2nd. Gold is not trading up on geopolitical escalation the way it was before March 2nd, and frankly, I've yet to hear a really good explanation for why it isn't. So I don't pretend to know what comes next, but it sure looks to me like we might be headed towards a 45 handle, if not lower. That's the next obvious support level below the current market.","offset":6267,"duration":23},{"text":"Host 1: So either we get a bounce here and the 50-day really was the trading signal that it should have been, or if we continue to see this weakness below the 50-day continue through the day on Thursday, I think we're probably headed down to 45.91, maybe 4600 on the 100-day moving average by the time we get there.","offset":6290,"duration":19},{"text":"Host 2: Well, Eric, my view on gold has remained unchanged for the last month. After we saw that key blow-off top on gold and that huge reversion, typically if we look at the last four consolidations of gold, it took as much as two to four months of gold consolidating before it attempted to break to fresh new highs.","offset":6309,"duration":25},{"text":"Host 2: At this stage, that analog is the one that we continue to see here on gold as we saw some retesting of highs and this sideways consolidation continuing overall. After this consolidation finishes, there's lots of room for gold to go higher, but at this stage I think it'll be deeper into the second quarter before we see a meaningful turn up.","offset":6334,"duration":24},{"text":"Host 2: How low could this gold correction go? Well, the first level to watch on the support side is this 4800 level we're trading down to right now, which is a Fib zone of this retrace. If that doesn't hold, I mean there is always the possibility we head back down toward that 4500 level and $4400 level below, but if that was to happen, that would probably be a compelling buy on dip to take advantage of. All right, Eric, what are your thoughts here on the fact that Uranium continues to just consolidate sideways inactively?","offset":6358,"duration":35},{"text":"Host 1: Well, Patrick, the fundamentals are uber bullish and they're only getting better by the day as we see more and more nuclear announcements. The nuclear renaissance is on and it's on strong.","offset":6393,"duration":13},{"text":"Host 1: And the market for Uranium and Uranium miners is holding up pretty darn well considering how bad everything else is going. We didn't see as big of a downside as I was fearing we might see on the Uranium stocks on Wednesday.","offset":6406,"duration":17},{"text":"Host 1: We're still looking at 49 spot 05 at the close on Wednesday on the URA ETF, which is the one that's most followed. That's still well above its 200-day moving average, whereas the indices have moved below their 200-day moving averages. But frankly, I think it's headed for its 200-day moving average, which is at 46 spot 03.","offset":6423,"duration":20},{"text":"Host 1: So we'll see what happens next. Broad market risk-off event is obviously going to take everything else down with it, including the Uranium miners. I think it just sets up better and better buy-the-dip opportunities. The question is how big is the dip before it's time to buy Uranium? I think the next obvious target is 46.03 on the URA ETF. But let's see what happens with the broader risk markets because if we get an outright market crash here, as could happen if oil prices continue to rise, particularly if they spike over $150 setting new all-time highs—at least on the major indices, we're already there with some of the other markets around the world, but if we get there on Brent and WTI above 150, that probably brings on an outright crash in equity markets and anything could happen.","offset":6443,"duration":50},{"text":"Host 2: Well, structurally the chart remains bullish. All consolidations are being held: higher highs and higher lows. But it's just been a quiet period, maybe the lack of liquidity in the broader asset markets could be just keeping this all contained. But overall the charts are still on the bull trend and at major support levels.","offset":6493,"duration":25},{"text":"Host 2: Now, Eric, I want to focus in on some bizarre price action that we've seen in Copper when it's overlaid on Gold. Now typically precious metals trade in correlation and a lot of times these industrial metals tend to march to their beat of their own drum independently.","offset":6518,"duration":34},{"text":"Host 2: But when I here show an overlay of the Gold and Copper charts, for some odd reason Copper, almost day by day, tick by tick, has actually been correlating with Gold. Now why? I really actually don't have an explanation. It's and I certainly don't know whether this will continue, but certainly as of this moment when we're looking at this chart, it's undeniable that right now Copper is just trading tick by tick with Gold. I'm very curious to see whether or not this trend continues in the weeks and months to come.","offset":6552,"duration":50},{"text":"Host 1: Patrick, before we wrap up this week's podcast, let's hit that 10-year Treasury Note chart.","offset":6602,"duration":4},{"text":"Host 2: Well, we've seen here is that it's trading right up toward the 2.30 level. We had the FOMC meeting and the first reaction after the post-FOMC was yields rising up to their one-month ranges or multi-month ranges. It'll be very interesting to see whether this has started a new follow-through and we see yields push higher from here or whether this was going to just a fake-out retest of the highs.","offset":6606,"duration":28},{"text":"Host 1: Folks, if you enjoyed Patrick's chart decks, you can get them every single day of the week with a free trial of Big Picture Trading. The details are on the last pages of the slide deck or just go to bigpicturetrading.com. Patrick, tell them what they can expect to find in this week's Research Roundup.","offset":6634,"duration":15},{"text":"Host 2: Well, in this week's Research Roundup you're going to find the transcript for today's interview, you're going to find the slide deck that was put together by Simon White, and you'll find the Trade of the Week chartbook we just discussed here in the post-game, including a number of links to articles that we found interesting.","offset":6649,"duration":20},{"text":"Host 2: You're going to find this link and so much more in this week's Research Roundup. That does it for this week's episode. We appreciate all the feedback and support we get from our listeners and we're always looking for suggestions on how we can make the program even better.","offset":6669,"duration":17},{"text":"Host 2: Now, for those of our listeners that write or blog about the markets and would like to share that content with our listeners, send us an email at researchroundup@macrovoices.com and we will consider it for our weekly distributions.","offset":6686,"duration":15},{"text":"Host 2: If you have not already, follow our main account on X at @macrovoices for all the most recent updates and releases. You can also follow Eric on X at @EricSTownsend, that's Eric spelled with a K, and you can also follow me at @PatrickCeresna. On behalf of Eric Townsend and myself, thank you for listening and we'll see you all next week.","offset":6701,"duration":19},{"text":"[Music playing]","offset":6720,"duration":6},{"text":"Host 3: That concludes this edition of MacroVoices. Be sure to tune in each week to hear feature interviews with the brightest minds in finance and macroeconomics. MacroVoices is made possible by sponsorship from bigpicturetrading.com, the internet's premier source of online education for traders.","offset":6726,"duration":23},{"text":"Host 3: Please visit bigpicturetrading.com for more information. Please register your free account at macrovoices.com. Once registered, you'll receive our free weekly Research Roundup email containing links to supporting documents from our featured guests and the very best free financial content our volunteer research team could find on the internet each week.","offset":6749,"duration":22},{"text":"Host 3: You'll also gain access to our free listener discussion forums and research library. And the more registered users we have, the more we'll be able to recruit high-profile feature interview guests for future programs. So please register your free account today at macrovoices.com if you haven't already.","offset":6771,"duration":17},{"text":"Host 3: You can subscribe to MacroVoices on iTunes to have MacroVoices automatically delivered to your mobile device each week free of charge. You can email questions for the program to mailbox@macrovoices.com and we'll answer your questions on the air from time to time in our mailbox segment.","offset":6788,"duration":20},{"text":"Host 3: MacroVoices is presented for informational and entertainment purposes only. The information presented on MacroVoices should not be construed as investment advice. Always consult a licensed investment professional before making investment decisions. The views and opinions expressed on MacroVoices are those of the participants and do not necessarily reflect those of the show's hosts or sponsors.","offset":6808,"duration":22},{"text":"Host 3: MacroVoices, its producers, sponsors, and hosts Eric Townsend and Patrick Ceresna shall not be liable for losses resulting from investment decisions based on information or viewpoints presented on MacroVoices. MacroVoices is made possible by sponsorship from bigpicturetrading.com and by funding from Fourth Turning Capital Management, LLC. For more information, visit macrovoices.com.","offset":6830,"duration":29},{"text":"[Music continues]","offset":6859,"duration":15}],"logs":[{"elapsed":"0.0","message":"Downloading audio from YouTube...","detail":null},{"elapsed":"0.0","message":"Trying download with browser cookies (ad-free)...","detail":null},{"elapsed":"58.0","message":"Audio downloaded (61.2 MB) in 58.0s","detail":"File size: 61.2 MB"},{"elapsed":"58.0","message":"Video title: MacroVoices #524 Simon White: War + Inflation = More Inflation","detail":null},{"elapsed":"58.0","message":"Audio duration: 1:54:31 (114.5 min)","detail":null},{"elapsed":"58.0","message":"Very long audio (114.5 min) — will use chunked transcription with gemini-3-flash-preview","detail":null},{"elapsed":"58.0","message":"Skipping full-file attempt — using chunked transcription for 114.5 min audio","detail":null},{"elapsed":"58.8","message":"Split audio into 3 chunks for transcription","detail":null},{"elapsed":"58.8","message":"Transcribing chunk 1/3 (starts at 0:00)...","detail":null},{"elapsed":"58.8","message":"Uploading audio to Gemini File API...","detail":null},{"elapsed":"62.1","message":"Audio uploaded in 3.3s","detail":"File ref: files/zs2ncd0vkmjh"},{"elapsed":"62.1","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"134.0","message":"Chunk 1: 122 segments, last timestamp 49:46","detail":null},{"elapsed":"134.0","message":"Transcribing chunk 2/3 (starts at 45:00)...","detail":null},{"elapsed":"134.0","message":"Uploading audio (offset 45:00) to Gemini File API...","detail":null},{"elapsed":"138.2","message":"Audio uploaded in 4.2s","detail":"File ref: files/9focgez852j9"},{"elapsed":"138.2","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"204.0","message":"Chunk 2: 134 segments, last timestamp 46:48","detail":null},{"elapsed":"204.0","message":"Transcribing chunk 3/3 (starts at 1:30:00)...","detail":null},{"elapsed":"204.0","message":"Uploading audio (offset 1:30:00) to Gemini File API...","detail":null},{"elapsed":"207.3","message":"Audio uploaded in 3.4s","detail":"File ref: files/kkngijhhxli1"},{"elapsed":"207.3","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"239.1","message":"Chunk 3: 65 segments, last timestamp 1:54:19","detail":null},{"elapsed":"239.1","message":"Chunked transcription complete: 298 total segments","detail":null},{"elapsed":"239.1","message":"Total cost: 172,583 in / 30,533 out — cost: $0.1779","detail":null},{"elapsed":"239.1","message":"Total transcription time: 181.1s — 298 segments","detail":null},{"elapsed":"239.1","message":"Analyzing topics across 298 segments with gemini-3.1-pro-preview...","detail":null},{"elapsed":"304.2","message":"Topic analysis complete in 65.2s — found 29 topics","detail":null},{"elapsed":"304.2","message":"Analysis tokens: 30,077 in / 2,330 out / 6,943 thinking — cost: $0.1714","detail":null},{"elapsed":"304.2","message":"Pipeline finished in 304.2s — total cost: $0.3493 (242,466 tokens)","detail":null}]} \ No newline at end of file diff --git a/history/1775223278105-ovih9Xotmxg.json b/history/1775223278105-ovih9Xotmxg.json new file mode 100644 index 0000000..fef02c0 --- /dev/null +++ b/history/1775223278105-ovih9Xotmxg.json @@ -0,0 +1 @@ +{"id":"1775223278105-ovih9Xotmxg","videoId":"ovih9Xotmxg","url":"https://www.youtube.com/watch?v=ovih9Xotmxg","title":"Escalating Energy Shock Exposing Central Bank Limits | Weekly Roundup","type":"youtube","topicCount":13,"segmentCount":67,"createdAt":"2026-04-03T13:34:38.105Z","uploadDate":"20260320","chunks":[{"title":"Episode Teaser & Sponsor Disclaimers","summary":"A teaser snippet sets the tone for the episode's discussion on energy market disruptions. This is followed by a promo for the upcoming Digital Asset Summit and standard disclaimers.","entries":[{"text":"Host: I think there’s a lot of downplaying like how serious this is. The problems are here to stay and basically it’s sort of escalation mode until it’s not. Everybody was looking for a taco and you can’t taco reverse out of Qatar’s LNG facility being destroyed. The market’s screaming growth problem here. Let’s say everything goes hunky-dory and oil goes to 80. That’s still not good. The Fed’s still not cutting, liquidity picture’s still bad, foreign investors still need to pull their funds from these assets, like I just see a pretty strong ceiling on the S&P 500 for from that perspective. It’s just a disaster.","offset":0,"duration":33},{"text":"Host: Before we get started, a quick reminder that Blockwork's premiere institutional conference, the Digital Asset Summit, is returning to New York City this March 24th through 26th. This year represents more than $4.2 trillion dollars in assets under management with 150 speakers and 750 institutions attending.","offset":33,"duration":18},{"text":"Host: Speakers include SEC Chair Paul Atkins, CFTC Chair Michael Sellick, Fed Governor Steven Moran, and Tether CEO Paolo Ardoino, alongside countless other executives, asset managers, regulators, and the core crypto infrastructure builders shaping the industry. If you want serious institutional-grade view of digital assets in 2026, Digital Asset Summit is where it happens. Use code FORWARD200 for $200 off and head to blockworks.co/events for more details.","offset":51,"duration":30},{"text":"Host: Nothing said on Forward Guidance is a recommendation to buy or sell any investments or products. This podcast is for informational purposes only, and the views expressed by anyone on the show are solely their opinions, not financial advice, or necessarily the views of Blockworks. Our hosts, guests, and the Blockworks team may hold positions in the companies, funds, or projects discussed. As always, investments and blockchain technology involve risk. Terms and conditions apply. Do your own risk.","offset":81,"duration":29}],"startTime":0},{"title":"Host Catch-Up and Conference Preview","summary":"The hosts catch up on their missing co-host Tyler's absence and preview the macro track at the Digital Asset Summit in New York, highlighting the growing intersection of crypto and TradFi.","entries":[{"text":"Host: All right everybody, welcome back to another edition of Forward Guidance and, uh, for the second week in a row, sadly, we are missing our compatriot Tyler. He’s- he’s in better health, it’s not a virus this week, but, uh, he had some work stuff come up and had to go attend to it. So it’s back to just us two again, the duo. Um, what’s up Quinn?","offset":110,"duration":23},{"text":"Quinn: How you doing, man? Yeah, we need this vault to cool down so we can get our boy back. He’s just- he’s just in the trenches right now.","offset":133,"duration":6},{"text":"Host: Dude, he is heavily in the trenches. And- and Muddy Waters is putting out some big short reports, too, at the same time.","offset":139,"duration":7},{"text":"Quinn: Yeah, yeah, they, um- what was that, SoFi?","offset":146,"duration":2},{"text":"Host: SoFi, yeah, they put out a short report on SoFi, which is- I wanted- I wanted him to be on so I could just, like, pepper him with it so he could just be like, I can’t talk about it.","offset":148,"duration":9},{"text":"Quinn: I can’t say anything. Yeah, yeah, exactly. Anyway. Big boy things to attend to, but, uh, he’ll be back. Um, not next week though, because next week is the Digital Asset Summit in New York. Very, very hyped about it. Um, going to be a ton of fun next Tuesday, Wednesday, Thursday. Get your tickets if you haven’t already. I would be very surprised if you haven’t already because now prices are going up. We’re almost sold out, but you can use FORWARD200 for 200 bucks off. It’s going to be a great time. Wednesday afternoon we have an entire Forward Guidance track dedicated to macro, the intersection with everything that’s going on. I was actually just on a- on a prep call this morning with Governor Steven Moran, which was super cool. We- we were prepping for next week, so that’s going to be an awesome one. Like, I- I’m super excited to ask him about- he dissented in the recent Fed meeting which we’ll get into. But, uh, yeah, it’s just, you know, we- we have a- a sitting Fed governor, we’ve got the head of the SEC, the head of the CFTC, like, it’s just- it’s going to be awesome. Um, really looking forward to it.","offset":157,"duration":56},{"text":"Quinn: Yeah, that’s going to be fun, man. The- the macro day, like, this is- this is top-tier stuff for, especially people who are thinking, oh, it’s a crypto conference, but there’s going to be, uh, a lot- a lot to talk about there.","offset":213,"duration":13},{"text":"Host: Crypto and TradFi are coming together. It’s- you know, whether people like it or not, it’s, you know, we still got to figure out what- what it actually looks like when it comes together, whether it’s just tokenized everything, but it’s happening. Uh, yeah, I mean, pretty soon we can just tokenize oil to bypass the strait.","offset":226,"duration":9}],"startTime":110},{"title":"FOMC Meeting and Economic Projections","summary":"Analysis of the latest Fed meeting and the updated Summary of Economic Projections (SEP). The hosts discuss why the market interpreted the meeting as dovish despite upward revisions to growth and inflation forecasts.","entries":[{"text":"Quinn: Yeah, exactly. Send it over internet rails instead. Yeah, that’s all you need to do. Um, anyway, with that out of the way, let’s get into the swing of things. I want to start to talk about, it was a Fed meeting yesterday. We got- it was also an SEP day. So no surprise, no rate cuts involved there, and we got their updated summary of economic projections. So just looking through a few of the key changes here.","offset":235,"duration":36},{"text":"Host: The- the FOMC updated their GDP forecast actually upwards for 2026 from 2.3 to 2.4%, which is quite interesting. Held the unemployment rate steady at 4.4. PCE inflation from their December projection of 2.4 up to 2.7, and core PCE from 2.5 to 2.7. Their projections for rate cuts are pretty much unchanged across the board, however. This is an interesting one. I mean, obviously the- the baseline reaction is- is, if you just look at the numbers, hawkish of- of PCE going from 2.4 to 2.7, but I feel like a lot of people expected even more of a hawkish function, um, which is interesting. What- what was your read on this, Quinn?","offset":271,"duration":41},{"text":"Quinn: Yeah, I- I thought it was dovish. Every meeting, uh, I put- or at least the quarterly ones where we get the SEP, I put together my own estimates, uh, of what I think they will be based on, you know, changes in data and rhetoric, etc. And I had a more hawkish dot plot, but there’s been a lot of moving pieces so I- I wasn’t putting too much signal or like, you know, emphasis on it. What- what stood out to me is that if you just, you know, let’s say you don't know anything about what’s going on and there’s no Iran war etc. and you see them raise inflation expectations and growth expectations, GDP and PCE, you would say it would be a hawkish interest rate policy path, and it wasn’t. So, like, you still had two governors that weren't Moran expecting three cuts this year, two more expecting two cuts, and then obviously the split- split between none and one.","offset":312,"duration":65},{"text":"Quinn: But to me, it was hawkish or- really dovish, and I think also like, the- the increased PCE expectations make sense, but um, I- I would have- I would have thought there would be a little bit more consideration of the impacts of demand destruction from- from the oil price shock because that, you know, there will be inflation if there’s government response that fuels the fire, it will be more long-lasting, but if there’s not easing or fiscal stimulus that responds, it will be more transitory to some extent and it will hit demand harder, so um, I would have expected- I didn’t think growth would get brought up. But overall, dovish because I think, you know, what Powell says is one thing and, you know, at the end of the day he’s not going to be around for that much longer, so I- I was really trying to think about what the committee and the votes and their projections would signal where consensus was for when Warsh takes- takes chairmanship, and dovish to me. Like, if- if five people already think, you know, two cuts or more, like-","offset":377,"duration":73},{"text":"Host: Dude, there’s not a lot of, like, convince- like, as much sway as I would have expected that would be needed to cut, especially if labor market starts falling apart. So I- I sort of feel like on balance it’s somewhat neutral because I think for sure, like this- this SEP and the press statement that came out and everything, that was quite dovish and- and you saw that initially. Like if you’re just tracking the 2-year throughout this whole thing, 2-year treasury. Initially, yeah, it was- it’s pretty calm and then it seemed like he- it got a little bit more hawkish in the press conference because Powell was really kind of mentioning that this SEP is- is pretty stale in- like it’s not fully considering the Middle Eastern shocks, the oil shock, and I think that’s pretty valid. Like, do you really think that we can have them, like, predict what the 2026 growth outlook is going to be? Like, no, no chance. So I mean, to me it’s just- it just kind of on balance feels somewhat neutral, maybe slightly dovish because they’re not trying to front-run this reaction function. But yeah, to me it just feels like, you know, Powell’s just trying to get to the finish line in one piece.","offset":450,"duration":61},{"text":"Quinn: Yeah, they- I mean, also to be fair, he’s like- he said a couple times almost like point-blank, like we don't have any confidence in these projections because there’s so much ungo- he like, and even if consensus is around zero-one cut, that cut’s going to come late in the year, so, which is many, many months out and this will change a bunch before so. Yeah, it’s definitely not one that everything hinges off of like you sometimes get, but it was interesting. Like, yeah, whatever.","offset":511,"duration":28},{"text":"Host: I- I do think what is interesting though is how markets are reacting right now since that’s a lot more coincidental and you can see Fed funds futures. We- we went from just a couple weeks ago, we had over two cuts priced for 2026 and now we’re- we’re basically at none. So even though the Fed is still on board for maybe- maybe one cut in- in 2026, the market’s like no, it’s- it’s not happening. And that’s where the story is, right? Because, you know, real-time market data might be a bit better at trying to forecast where we’re going here. I guess my question is like, how in the world, given, you know, the private credit issues, given the now commodity price spike stuff, even if the war ends tomorrow, there’s some lasting effects, given waning liquidity broadly and slowing momentum of asset prices. Like, how does- how- how possibly could equity prices stay elevated without- without liquidity help? So when I think in that frame, it’s like, okay, well then what’s the- okay, then the forcing function is probably the equity market for cuts and then what’s that level? I don’t know. I was sort of looking at December SOFR futures as like a potential. I don't know what’s better risk-reward, shorting equities or longing those, but it’s definitely, like, push comes to shove, like, Trump’s getting cuts if- if stuff starts hitting the fan. So I think it’s getting to levels that’s sort of interesting. I haven’t pulled the trigger yet though.","offset":539,"duration":92}],"startTime":235},{"title":"Central Banks' Rigid Response to Oil Shocks","summary":"A look at how single-mandate central banks like the ECB and Bank of England are forced to hold or unexpectedly hike rates in response to inflation driven by energy supply shocks.","entries":[{"text":"Host: Yeah, it’s- it just seems like this whole thing of how difficult it is for- for how central banks are set up to react when oil supply shock, it’s- it’s just so difficult. And this is even like a- a dual mandate central bank. You know, some of these other- and this is a big topic I want to get into here, is if you- where am I looking? When you get to looking at the other central banks and how they’re reacting to the situation, it’s- a lot of these are single-mandate central banks. So all they care about is inflation. They don’t have a mandate for unemployment. So when they see inflation go up, their- their framework are basically forced towards them with a hiking bias.","offset":631,"duration":32},{"text":"Host: So you can see the Fed is, yes, it’s- it’s come back a lot in terms of the number of cuts, but we’re still on net- like we’re- we’re not pricing any hikes anywhere right now on the Fed side of things. But then you look at the ECB, we have- we have gone from pretty much flat towards almost two hikes over the next little while here. Bank of England today had their meeting and it was a huge surprise and this isn’t updated in this data yet, but they were- they were priced to pause, or sorry, they were priced to cut at this recent meeting today and they surprised by holding flat. And this really just shows how difficult and how frozen these central banks are where they- they’re at the whim of inflation. They can’t think in those second orders and, you know, us as market prognosticators can be like, oh, they should be doing this. But the fact of the matter is like, they’re mandated by- by laws and frameworks to be reacting in a certain way.","offset":663,"duration":49},{"text":"Host: So you can see this in the Bank of England, like the Gilts market just went absolutely bananas today. The 2-year just sold off like mad because it was fully priced for a cut and we didn't get that and we got this pretty hawkish retort. The entire board, um, voted to pause as well and not cut. So it was like a consensus hawkish pivot out of nowhere. And what’s- what’s so crazy to me is that most of these central banks are in economies that are also the most exposed to the oil shock. It’s just like this double-whammy situation where Europe is the most exposed and they have the least flexible central bank. It’s just- it’s just a disaster.","offset":712,"duration":42}],"startTime":631},{"title":"Currency Markets and US Export Ban Rumors","summary":"Discussion on the dollar's recent weakness and the potential market impact of rumored US export controls on refined energy products, noting the significant price moves in crack spreads.","entries":[{"text":"Quinn: Yeah, I guess this must be the catalyst for the move today in- in- in the dollar versus especially like the pound and the Yen, you know, dollar weakened really- really massively today. Also weird that the dollar weakened massively on a day gold was down huge. So it sort of says that, um, the run-at-hot trade has been stymied here where fiat actually looks all right if central banks are going to be hiking into- into this and actually attempting to get inflation down. I think, I mean, where I stand is it’s like show- I don't really have any bets on it because I want to- I want to see the proof in the pudding because it’s all talk until your equity market starts getting, you know, pummeled. And, uh, you know, everything’s pulled back, but nothing dramatically or- that signals real panic. So I- I’ll be curious to see how these rate hike expectations hold up once stocks start taking it on the chin, which I would expect soon.","offset":754,"duration":68},{"text":"Quinn: But yeah, man, it’s a- it’s a weird- like the- yeah, the energy situation is just so dire if- if the strait doesn’t open. I mean, maybe- maybe there’s some things too around these headlines where um, you know, the- the allies were saying, okay, we- we will help open the strait because like at the end of the day, you know, Trump’s definitely dangling this threat of export controls that that would really- really just really- really affect the rest of world super negatively, um, and also be bad for us and use the dollar etc. So maybe that’s also something to do with with the dollar’s fall today.","offset":822,"duration":40},{"text":"Host: Yeah, definitely an interesting one when you mentioned about, uh, the export ban situation because the- the energy secretary came out today and said we don’t plan export ban on WTI Crude, but they didn’t say anything about, uh, any sort of refined products and that’s where the meat of the situation is. There’s this good, uh, you can see the chart here, like refined products versus oil. The real move has been in those refined products, like yeah, diesel’s up way more than WTI, and so refinery margins are- are up a ton. You know, this is- this- you can see this in like the- in the crack spreads. But this is what really matters in terms of like an export ban, in terms of like protecting consumers from affordability at the pump and that sort of thing. So that’s still on the table.","offset":862,"duration":45},{"text":"Host: We- we did see this, you know, the WTI Brent spread went like absolutely nuts over the past couple days, um, and it- it seemed like a lot of that was speculation around this export ban and then as soon as you got that- that news hit the tape, you saw that start to come together. WTI started to rally and then it seemed like everything started to sell off in- in quick succession, too. So um, yeah, weird stuff afoot. How- how are you thinking about the energy situation? Like last week we were kind of in a everything’s fucked, um, and it’s just- it’s just a time thing. I’m still of that mind, I’m curious how you’re thinking about it.","offset":907,"duration":39}],"startTime":754},{"title":"Energy Infrastructure Damage & Asian Exposure","summary":"The hosts highlight the severe, long-lasting damage to Qatar's LNG facility and analyze how Asian markets are exceptionally vulnerable, evidenced by the surging prices of Dubai and Oman crude.","entries":[{"text":"Quinn: Yeah, I- I- I mean, like today, I- I had that- BB’s press conference was- I- I mean, I got to imagine that was Trump saying, you know, US saying, dude, you got to show face, where you been, go out there and- because right, that helped calm the markets today. But I mean, are you really going to believe this guy? Like they just- they just, who knows what to believe. But you know, maybe they went rogue on this natural gas facility that caused, but um, you know, the- they had to do it too because there’s- there’s reports that they’re- their big Haifa refinery got hit, which as we know is potentially what um slowed Israel’s aggression in- in the previous skirmish because they don't- I mean, they’re just like similar to other Middle Eastern countries, they don’t produce any oil and they don't have, you know, tremendous access outside of a few main key assets like that. So um, yeah, there’s- I just- this- like peo- I just don’t- like, I think there’s a lot of downplaying like how serious this is because it’s like, this isn’t playing like, you know, soldiers, you know, with your friends outside where it’s like, oh, I’m sorry I just socked you in the nose and gave you a black eye, like I promise I won’t do it again.","offset":946,"duration":75},{"text":"Quinn: And let me backtrack. And then, you know, your parents get involved and say, okay guys, cut it out. Like, we just tried to end their whole country and leadership. Like, and then now we’re going for their energy infrastructure assets. Like, oopsies don't really get a lot of, you know, you know, sympathy in- in war. And- and so I just- I just think this is- the problems are here to stay and basically it’s sort of escalation mode until it’s not and until there’s sort of a climax and regardless, even if not, every day that goes by that something like this stuff happens, it makes, you know, other energy assets globally more valuable and- and takes supply off more structurally like this, you know, Qatar gas field, like was like $70 billion over 10 years or something. This isn’t like a band-aid fix out of so. I’m still really long the natural gas torque equities in the US, long the coal equities. Those- those really had a day today, um, and then my big- big trade is the agricultural stuff. But um, I just- like I don’t- I just think people are still under-positioned. Like this- it kind of reminds me when gold first broke out like three years ago or two years ago and it was like oh wow, just- and you just doubting- doubting- doubting- doubting that it can keep going, but it just does.","offset":1021,"duration":79},{"text":"Host: Yeah, I mean the fact of the matter is everybody was looking for a taco and you can’t- you can’t taco reverse out of- out of Qatar’s LNG facility being destroyed and like they said, yeah, like three to four years to fix what’s been broken. I saw a headline, it was like it took us 26 billion to build this and this is 20 billion dollars in damage. Like if- if we end this tomorrow, the world’s largest LNG export facility is still under significant duress. Like shit’s getting real now. Um, yeah, I’m still really focused on where- where these- where these impacts start to lie. You know, I think- I think a lot of people have been really focused on- on the US and, you know, it’s like okay, if- if you’re bearish people keep going to short like Nasdaq or for example. And I think there’s just a lot more nuanced ways to look at it in terms of the rest of the world and um just want to start with this chart just looking at where do- where is the destination for the Hormuz LNG exports? And it’s, you know, South Korea, it’s- it’s China, it’s- it’s Asian markets predominantly.","offset":1100,"duration":64},{"text":"Host: And then you- you take that and let me get at slide 31 here. You take that and you look also at, okay, what are the economies that are most energy self-sufficient? So looking at oil consumption less production as a percentage of GDP versus share of oil in energy consumption mix. Uh, and again you can see in the top right there South Korea again. Like Asian markets that are highly-highly dependent on- on the Strait of Hormuz operating, they’re the most at risk here. You pair that too with the fact what we looked at earlier is a lot of these- these currencies are- are weakening relative to the dollar. The US is largely- they yes they, you know, they do import still, but- but largely they’re energy independent with reserve currency. They’re- they’re going to be the least bad of everybody I think. Um, maybe Russia and shout out Canada too on the left side of there. Hell yeah. If we can actually get- get out of the way of ourselves and actually start to- to pump some oil out of the oil sands in Alberta, that’s a different story.","offset":1164,"duration":61},{"text":"Host: But overall, it’s really important to drill down I think into these hyper-specifics of- of where the impact lies and then bring it all together is this chart’s been going somewhat viral the last few days because you know people ask what the price of oil is and it’s like well, what oil? You know, you got to be looking at Crude WTI Crudes at 95 bucks, Brent’s breaking above a hundred, but Dubai Crude and Oman Crude, like Oman is the vector to look at acute demand need for oil from Asian markets. That’s- that’s largely where it’s gone and that stuff is earlier today broke above 170 bucks. And that’s just unheard of. So you have to, you can see the dislocation here, like for months these things traded in a pretty tight range together. Um, but you really have to- you really have to drill down now and think about where the second-order effects, what- what even contract of oil am I talking about here? And really try to understand how does that impact the currencies, how does that impact their economy and therefore their- their equities? So it’s like, I don't know, if- if you want to express the short here, um, yeah Nasdaq will probably work, but there’s probably a lot more effective plays like shorting, I don't know, South Korea equities and that sort of thing.","offset":1225,"duration":67}],"startTime":946},{"title":"Agricultural Commodities Inflation Trade","summary":"Quinn details his bullish thesis on agricultural commodities, arguing that base crops like corn and wheat encapsulate the rising costs of fuel and fertilizer while farming profit margins remain deeply depressed.","entries":[{"text":"Quinn: Yeah, yeah, I’m- I’m- I’m in uh short Japan, short South Korea, short Europe, still smaller than some of my other ones, but um, I’m starting in. Because I- I’m like medium on the dollar, I don’t- I- I think there’s like we were talking about in previous shows like these- these capital flows and- and asset allocation headwinds that- that the dollar has, but you know for all these energy independence reasons it’s got some tailwinds in times of- of madness too so. Um, but I do like having some of that on. I think the other not to overly uh harp on the agriculture stuff, but I’ve- I’m seeing more people talk about it and- and people are going straight to the fertilizer tra- aspect of the trade. Um, and I looked into that as well and follow it. The thing I like better about the- the base commodities, which I think are being slept on, is the fact that what is corn, uh sugar or- or wheat? It’s just the combination of seeds, fuel, fertilizer, labor, farming profit margins, planned costs, all into one.","offset":1292,"duration":77},{"text":"Quinn: And, you know, we’re seeing the fertilizer and the fuel cost to- to plant, harvest, and grow spike, but the other side of the trade is that farming profit margins have never been worse, they’ve been in recession for three years, supply as these farms shut- shut in is falling, so there’s not a good- not a good um response effect there. And- and so it kind of encapsulates all of these things into one where the- the cure is just simply higher prices of these assets, particularly if this it’s spring planting season and so you need- need the fertilizer more acutely during this time. And you don’t have to worry about buying like equities in a fertilizer agriculture company which have already been bid up, like the um, you know, the multiples on- on a lot of these Ag companies are now much more elevated.","offset":1369,"duration":55},{"text":"Quinn: But yeah, there’s no strategic corn reserve. Um, so there’s and demand doesn’t get hit, right? If- if oil goes to 100-150 bucks, people stop driving, people stop flying, people stop vacationing, all that you hit demand. But like if your food goes up 30 percent-","offset":1424,"duration":14},{"text":"Host: South Korea’s in some ways.","offset":1438,"duration":1},{"text":"Quinn: Yeah, if your food goes up 30 percent, I mean you need food, like you can’t just- you can eat less, but you know, unfortunately, it’s the countries that are you know the- the developing and underserved parts of the world that probably get hit the hardest from this. So, um, I just don't think it- I- I don’t- I hate to use like these analogies that, you know, say that- that kind of point to it being like so similar and going to play out the same way as like Covid and- and that’s kind of become quite talked about now, but you just don’t know the second-order effects and- and you know we’re three weeks into the strait closure. This- that- and we’ve been saying every single week, two weeks. And now there’s no way to do it. Like it might be mined, the only boats getting through are going right close to Iran and sort of like ally ships. Um, it- it- it clearly shown it doesn’t take much to keep it closed.","offset":1439,"duration":52},{"text":"Quinn: So it’s- it’s seeming more and more like you need some boots-on-the-ground operation and it’s just constant fog of war propaganda to- to try and keep the markets afloat. Because at the end of the day, why would they- if- if they can just jawbone and say like send people on TV and say it’s the war’s over, it’s going to end soon, all this stuff, and the market buys it, they will never stop. That’s kind of the- the- that’s like the dichotomy of this- like paradox. It’s like, if- if they can keep the market elevated but continue to wreak havoc, they’re not going to stop. It’s until there’s a forcing function in the market. And- and you see it in oil, right? Like the jawboning works and then it gets bid up the next day, right? Like until the next attack gets televised. So I don't know, man, it’s- it’s weird how everything one has become so markets-focused and also too, how everything just moves on the whim of- of like narratives and tweets, but uh it’s- it’s driving people crazy, I know that.","offset":1491,"duration":63},{"text":"Host: Yeah, I mean it’s nuts. Like then the next impact of that too is that, like we talked about last week, now that Iran knows where Trump’s, you know, liquidation level is, markets, like that’s going to incentivize them to go after energy infrastra- infrastructure more than they would have if he wasn’t as, you know, if he didn’t care as much about markets. So, like they-","offset":1554,"duration":23},{"text":"Quinn: Yeah, you have their foreign minister tweeting like this exact stuff. It’s- it’s such a weird, I mean, it’s so- I guess that’s a part of the new- new type of fighting wars is like it’s less people on the ground and it’s more like economic and financial warfare. But you know, it’s not a- we luckily the world in general is like a positive sum, right? Like over time people get lifted out of poverty, you get more efficient productivity, um, so when we talk about like Europe and Japan being less you know disadvantaged more relatively to the US, it’s unfortunate that it’s still like you know we’re- we’re decreasing the pie with all these things instead of increasing.","offset":1577,"duration":41}],"startTime":1292},{"title":"Arkham Intelligence Sponsorship","summary":"An ad read for Arkham Intelligence, an on-chain crypto intelligence platform and exchange.","entries":[{"text":"Host: Before you place a trade, you should know who is actually moving the market. That’s where Arkham comes in. Arkham is a crypto intelligence platform and exchange that lets you see real on-chain data. Which wallets are buying, selling, and moving funds. And then trade directly on that information. Arkham was built to make blockchains human-readable. Instead of raw transaction data, you get clear profiles, visualizers, and custom dashboards that show what’s really happening beneath the surface. Tracking wallets and fund flows is becoming just as important as technical or fundamental analysis. On-chain intelligence is also one of the best tools traders have to protect themselves against hacks, rug pulls, and scams. With Arkham Exchange, you can go from insight to execution in one place. The world’s first exchange powered by crypto intelligence. Check out Arkham and start trading with real on-chain insight at arkham.com.","offset":1618,"duration":48}],"startTime":1618},{"title":"Geopolitical Winners and Secular Isolationism","summary":"A brief look at who benefits from the ongoing geopolitical conflict, including Russia. The hosts also touch on Jerome Powell's recent comments regarding the growing trend of secular isolationism.","entries":[{"text":"Host: I think what’s tough, like, I don't know, it’s just, you know, there’s a lot of stuff where it’s like reaping what you sow right now too in terms of like- this was a great actually chart and tweet from Andreas Steno Larsen looking at who’s been the big winner so far and it’s been Putin. Um, the- disc- like all- all- all you know, you have this- there’s a mention this morning from- from Treasury Secretary Scott Bessent talking about how they might lift sanctions off- off Iranian oil that’s on sea right now. And it’s like, who’s winning here? It’s- it’s that, um, it’s- it’s Russian oil that’s, uh, you know, you’re seeing the discount close here because, you know, you got India, you got these other countries that are starting to be able to buy it again. Um, you know, we’re just these tail risks that have been avoided for decades by world leaders, Western world leaders, in terms of where does our energy come from? You know, we’ve been too focused on- on ESG mandates to think about okay, well what would happen if the Strait of Hormuz closed or what would happen if we sanctioned Russian oil and these sort of things, and now a lot of these- these chickens are starting to come to roost.","offset":1666,"duration":68},{"text":"Quinn: Yeah, it was interesting and Powell, he got asked that question about like some of these longer-term things and- and one of them was, he- he gave like a- a nod or tip of the hat to these like bigger geopolitical theories that- that isolationism and- and secular conflict is increasing on a secular basis, um, which I thought was interesting. Like, it’s definitely everybody’s thinking about it. And yeah, it’s, you know, we’re still in this, I guess people, the market structure elements that are keeping the equities pinned and- and hasn’t really gotten people panicked, but it’s just so- it’s- one it’s like, you know, my portfolio is positioned in a way that benefits when the world goes to shit, which is not fun, like but I’m not going to like just sit there and like be long Nvidia amidst this. So, but you know, no one wants to root for that. That sucks. Um, but at the same time, it’s like you’re just waiting for the shoe to drop and there’s these market structure things ongoing that to me seems inevitable. I put some charts in there that- yeah I was going to say you got some charts, let’s see- let’s see what-","offset":1734,"duration":68}],"startTime":1666},{"title":"Equity Vulnerabilities and Volatility Suppression","summary":"A deep dive into market structure issues, highlighting top-heavy index concentration, record quant leverage, and the impending options expiry. The hosts also discuss how suppressing front-month oil volatility transfers risk to other markets.","entries":[{"text":"Quinn: Well start with the first one, um, I think 35. Um, yeah this- this just shows that- there’s all this talk about how you know Mag 7 and etc. is under-owned, but they’re such a large part of the S&P 500, um, and the Nifty Nifty 50, you know the top 50 stocks. Like it’s still very overweight relative to the rest of S&P 500. So you know, if you look in like 21 when we got down in 22, 23 when- when relative outperformance of large-cap mega-cap bottomed, like there’s- there’s plenty of room to go. And if you look at the next one, this- this hawkish rate move in- in yields up, like similar to what we saw BoE, has also coincided with defensives massively outperforming cyclicals and- and forward equity growth and earnings are kind of slipping. So like, the- the market’s screaming growth problem here. The market is very much- and bonds have repriced lower, yields higher to some extent, but- but big parts of market are saying growth issue.","offset":1802,"duration":69},{"text":"Quinn: And then the next slide is just- this was an interesting one from RenMac that showed that yesterday’s PPI readings pushed in the 90th percentile historically and this is before the Iran effect. Um, so this is really problematic and like we were kind of talking earlier is like whether this is transitory inflation or not is going to matter if, you know, what the- the policy response is. And it’s hard not to see it being inflationary, um, especially given we’re still working through tariff impacts and everything. I mean, it just feels like the classic scenario where they- they’re forced to hike into slowing growth and that kind of puts an end to the global cycle.","offset":1871,"duration":43},{"text":"Host: Yeah, like the best case from here obviously is war ending and we stop losing lives and- and tons of- you know, waste of money and all you know, conflict. But if- if it does end quickly, you know, maybe there’s this way that they can cadence rate cuts to soft- sort of soft-land the inflation effect, but like keep the economy afloat, but it’s going to be really hard. Um, and it’s so reflexive with- with the markets and equities. Uh, I thought it was interesting on this next slide, you know, we’ve been talking you- you walked us through the options expiry dynamics tomorrow, um, and there was a- someone sent me this on Robinhood, uh, article writing to their retail audience about the Triple Witching and, you know, how the median is down.","offset":1914,"duration":44},{"text":"Host: Yeah, they’re like stocks sometimes go down, but don’t worry about it. Moves can be exaggerated because of this. And then, um, I- the next slide is just the from Goldman, the CTA estimates. So they show in a- in a flat market and flat and down markets, they show a pretty big CTA unwind. Obviously, if the market’s up CTAs relever, but given where Vol is, it’s probably, you know, you- you’d need a really big- big event for that to kind of turn. So the- the direction of travel is- is the same lower- lower place we’ve been going.","offset":1958,"duration":33},{"text":"Quinn: On the next slide, this was an interesting chart from JPM just showing the Quant equity degrossing drawdowns and the long-short degrossing, which this is um total leverage, so this is like if you’re long a hundred and short a hundred and you’re net neutral but your- your gross is 200. We’re still at record gross, you know, leverage levels. Like people have just been sort of- people haven’t been deleveraging, they’ve been adding puts and shorts. So um, it’s usually not over until you get a proper degrossing event and we haven’t seen it yet. Like if you compare this to- to um all these historical events, it’s- it’s not even recognizable on this chart.","offset":1991,"duration":46},{"text":"Quinn: And then you have the next one, today actually kind of kicks off earnings blackout into, you know, the next six weeks and through April so you have less market support there. The options expiry passes and then top-of-book S&P futures liquidity is horrendous. Like this is rivaling some all-time low levels like last Q1 or 2022 levels. Um, and we’re seeing that, right? Like stocks are whipping around one percent a day up down up down and everyone’s losing their minds. But when you zoom out and look at like a one-day- or three-day chart, like the trend is very much down and we’re like just peaking- peaking below the 200.","offset":2037,"duration":38},{"text":"Quinn: Um, and then the last thing I would show is- is everybody’s been talking about this hedging, right? So everybody’s loaded up with puts to- to hedge upside- downside instead of selling because no one wants to sell their winners and you know recognize taxes and gains so they just buy puts. But we all know that the puts haven’t been working because the market’s been stairstepping down and theta’s burnt and now we’re to options expiration. But a- a not great sign for the market is when skew comes off this much, which it has been. So skew has fallen um dramatically, but volatility hasn’t, which basically means that the- there you know this skew referring to put skew, so when it’s elevated you know puts are in demand more- more so than calls and there’s a huge pre- there’s a- a premium paid to buy the protection to the downside.","offset":2075,"duration":53},{"text":"Quinn: So when that falls it basically just means there’s less- the market is less protected in terms of options demand and if volatility is still elevated, you know you’re still in sort of a risk-off period, um, you know the market’s more vulnerable. So everything is lining up aside from like Robinhood talking about the options expry. So that- that- I don't know what to believe anymore. I just like believe in my- my case and so I’m short the things I’m short and I’m long the things I’m long, and we’ll see. Like but it doesn’t feel like- everybody I talk to is still waiting for the taco, doesn’t want to miss the bounce, like cannot imagine sitting- like a good example is my Substack chat. Like Monday and Tuesday when we didn’t even like, you know, we just did the same exact price action of last three weeks. Everybody was losing their minds. They’re like, oh my god was this it? Yeah- yeah they’re just- and it was like one day of a bounce. Like literally three days red, one day bounce, three days red, one day bounce, and on like the one day bounce people are like it’s- I knew I should have closed. Like and so that just shows you where sentiment is whereas when you’re at a bottom people are puking, right? Like people aren't saying like it’s- it’s- so I just feel to me like we still have ways to go and that this options thing could be a catalyst. But let’s see, you know the- the admin probably knows about it too and they’re probably going to try and roll out the red carpet to try and keep- keep things afloat.","offset":2128,"duration":85},{"text":"Host: This is just my favorite chart because last week we showed this exact chart people remember talking about how, you know, it was before this reversal and it was just like put skew was like at yeah like above 1.2 is ridiculous and it’s just like we said, nobody can make money on the downside if everybody’s that bought into puts. Um, we’re just going to burn them. And then you know those- those three days down, one day up, that is just the perfect way to- to just burn through theta. Like you just- I can’t even imagine the amount of theta that’s just being burned right now with- with elevated implied vol. Like everybody bought these at- at elevated levels. I do think, yeah, like either you just you know keep your risk limits tight if you’re buying puts and know what you’re getting yourself into or you- you just go out and outright short and avoid the whole situation. Um, but people- like the fact that Robinhood is talking about this means the game is known. Um, and then you have to think through the third-order effect of that which is probably you’re right, which is that- that Scott Bessent’s probably briefing- briefing the boys about hey look you know Triple Witching’s happening this week, window of weakness is coming up and- yeah send Netanyahu out there to like try and calm, say the war’s ending- like yeah, it’s all- it’s all- it’s all on the table, man, like because they- they need the- they need the space to operate and they’re trying to keep markets elevated.","offset":2213,"duration":85},{"text":"Quinn: Like, ultimately though, you know, these are physical commodities we’re dealing with. These are like, you- you can only- there’s some- there’s some level where just kicking the can and sort of lying to save face eventually backfires because then when you actually- when there actually is good news, people won't believe you because they’re like I’m not falling for that. So I don’t know if it’s the best strategy, like um- but it’s not our- it just remind- it reminds me of what we’ve talked about before in terms of how volatility can’t be suppressed, only transferred. And you know people are- they’re trying to suppress the volatility of- of CL front-month futures, but then you look at what’s going on in- in Oman and Dubai oil and that’s above 160 bucks and, you know, I’m- I’m not smart enough to make a- a certain decision about this, but I imagine by suppressing front-month CL, you creating- you creating volatility where you can’t control it. It’s being transferred. Like you know even over the past few days you’ve seen many days where the front-month contracts have been actually coming down but the- the back months, like the 2027s and stuff, have been rising further, and I’m sure you can make the argument that look, it’s like if- if you think that your counterparty in the books is- is Scott Bessent on front-month futures, you’re going to go speculate on the back ones and that could have a whole bunch of unintended consequences. Like you can’t, yeah, you can’t suppress the volatility, you’re only transferring it to more esoteric ways.","offset":2298,"duration":84}],"startTime":1802},{"title":"Unintended Consequences for US AI Infrastructure","summary":"The hosts theorize a potential bear case for the US dollar if energy export bans are enacted. They also discuss how the Middle East conflict could derail US AI data center build-outs due to resource shortages and lost regional funding.","entries":[{"text":"Quinn: So here’s one I was just thinking through. Go to slide 45. And- and I’m kind of- I was literally just thinking through it before this so um, this might be a little green. But um, so this is the- the trade balance data which we’ve been talking about for a while. Ex-gold in the in the red there and the blue is just regular. Um, the lines there show the increasing on the left side means that the trade deficit is shrinking. So it was running on an average you know well north of 80 billion, kind of 80 to 100 billion pre- uh pre-tariff changes and some of those were front-running. But um, post that and as we kind of normalized, it’s- it’s dropped a good 30 to 40 billion, which is- is super significant from- from the levels, which we’ve talked about means, you know, if you can see on the right chart there, um, it means, you know, more exports relative to imports, um, versus the baseline levels. And um, less dollars in- in rotation globally, um, and in- and so that kind of puts a- a headwind on the dollar and you know that’s some of the probably bid behind gold.","offset":2382,"duration":71},{"text":"Quinn: But if you think about this, like if they were to put an export ban on our commodities, which are- which are sizable, so you decrease exports, so the trade balance would go further negative, meaning like our deficit would increase, which on the surface you know when your deficit- if- if trade is expanding and your deficit increases, goes further negative, you know that’s more dollars in existence globally because it’s saying imports are rising faster than exports. But in- if everything’s decreasing, meaning the trade- total trade is going down because you’re slowing growth and your exports are- are coming down as well, um, that means people need less dollars to buy. So I don- you know, that- that’s probably a negative side effect that people I haven’t heard anyone talk about. I haven’t thought this through completely, but if you did ban exports of oil and gas, people need less dollars and presumably the dollar would fall on that, um, which would have ramifications for inflation and the things other things you import as well as like capital flows because if the dollar starts falling and kicks off you know people having to kind of hedge and- and sell other US assets or something. So like you said, you can transfer the vol, but you can’t completely eliminate it, and I think that’s where people are at is like a little too much complacency around policymakers’ ability to control things that ultimately in the long run they can’t control.","offset":2453,"duration":88},{"text":"Host: That’s a great, um, yeah this first time thinking about this too, so you know we both might be missing something here, who knows what, but that to me sounds like what could be the bear case for- for US assets specifically and the dollar. Because everything else we- we’ve talked about ad nauseam about the risk for the rest of the world, Asia, Europe, etc. But what is the risk here for the US if they’re energy independent? And yeah, I do think it’s- it’s that, less dollars going out to the world, less um, and yeah, so then I add that towards what’s also going on when we look at the AI data center build-out and- and what’s financing it as well is you have okay, a lot of the capital investment has been coming from the Middle East. Um, they’re, you know, I imagine they’re marginally less interested in- in buying the next big AI data center when they’re fighting for their lives right now. Um, and then also you have key inputs into that AI data center build-out. Like helium market is, you know, everybody was all focused on oil but I think- I think we should be also equally focused on things like the helium market because that is just a one-to-one input into compute build-out.","offset":2541,"duration":69},{"text":"Host: And so if you have further shortages on those key inputs um and either the price rises or there’s shortages, both of those equal less AI data center build-out. And also at the same time, you know these- these Middle Eastern countries that have been financing a lot of this are probably going to be hoarding money because they don’t know what the hell’s about to happen to their economy. Um, you know Dubai is like- I’m sure I don’t know the numbers but I’m sure the vast majority of their revenue comes from rich people living there and spending a bunch of money and if- if they all bailed, like I’m sure their- their revenue situation is not looking too hot right now. Um, you know I’ve- I’ve even seen some people speculate that some of the- the gold price action of- has been the Middle Eastern countries selling just to hoard some cash and you know try to survive where we’re going next. Uh, there’s a, yeah, there’s just- we could- we could probably spend another 20 minutes here thinking through these unintended consequences, but there’s just- there’s so many.","offset":2610,"duration":56}],"startTime":2382},{"title":"Sovereign Wealth Liquidation & Defense Budgets","summary":"Exploring the risk of Middle Eastern nations liquidating their US assets to fund wartime economies and domestic defense. The hosts argue this creates a strong macro ceiling for the S&P 500.","entries":[{"text":"Quinn: Yeah, if you’re these countries, you know, they’re preparing for war to go start fighting against Iran as well and they’re looking at like they all own a ton of US stocks, right? And you’re seeing the S&P down 5% and your country is, you know, economically in a crisis event. You have to be liquidating these assets. You have to be and repatriating it. So, um, you know if for nothing else maybe to support your currency or you know your economy. Like it definitely creates massive isolationist deglobalization vibes that are just large moving ice cubes and glaciers, they’re not- they’re not just one-time events. Because when I think about, okay, you know, every- this war’s in everybody knows about it, it’s in plain sight, you know asset markets have responded to some extent, oil’s you know at 100 bucks. Like where- where is this wrong? Where am I wrong? Where are the holes in this? And to me, it’s like I don't really see a world given the damage done, you know, etc. to infrastructure. I don’t see oil going back to 60. Like I- my best case is like, okay, we- we lose 20% and we’re back down to 80, 80 bucks a barrel, which- which to me, yes, it takes the sting out of- of doomsday tomorrow, but it doesn’t- it still fuel to an already not great situation for risk assets.","offset":2666,"duration":92},{"text":"Quinn: And oh, by the way, like is Qatar going to want to commit $25 billion to the next OpenAI or whatever AI round or data center in the US if they have to pay 20, you know, whatever it is to rebuild these gas fields and their infrastructure? And also overnight, the other thing all these countries, they’re going to need to double-triple-quadruple their security budgets because no longer, you know, they’re going to have to start investing in Strait of Hormuz security, their own security, weapons, defense. So this is like, this is a pretty big like crowding-out effect as well from- from private investment to like sort of like public infrastructure, security, defense, safety goods um, which is not- it’s super negative for like overall productivity because you’re basically needing to finance more and more of these things from the government side. You know, they- like Congress I think is going or- admins going for a $200 billion like you know extra defense thing, you know soon.","offset":2758,"duration":55},{"text":"Host: The war’s ending soon but we need 200 billion dollars.","offset":2813,"duration":3},{"text":"Quinn: Yeah, and we need to send another warship and- and all these like. So, um, yeah, like you said man, like when I think about like where is this wrong? Like I- I don't really see how you put Humpty Dumpty back together here. It’s just like you can just slo- like you can just slo- like you can just like use glue to like make him fall apart less quickly and- and make the stairs more gradual, um, which is seemingly what they’re trying to do. But I just don't understand when I- when I zoom out, it’s like okay, let’s say everything goes hunky-dory and oil goes to 80. That’s still not good. The Fed’s still not cutting. Liquidity picture’s still bad. Foreign investors still need to pull their funds from these assets. Like I just see a pretty strong ceiling on the S&P 500 for- from that perspective.","offset":2816,"duration":55},{"text":"Host: Yeah, yeah, I think the best case right now is flat.","offset":2871,"duration":5},{"text":"Quinn: Yeah, and then you lose in real terms because there’s 4 or 5% inflation.","offset":2876,"duration":5}],"startTime":2666},{"title":"Closing Thoughts and Live Show Preview","summary":"Final reflections on the hyper-financialization of global conflicts and the anticipation of Monday's market open. The episode wraps up with a preview of next week's live show in New York.","entries":[{"text":"Host: Yeah, 100%. Yeah, well, probably leave it at that, but I think yeah the main takeaways are stuff’s still happening. You know, you can try to suppress it for so long, but things will emerge where you don’t expect them to. And you know, there’s market structure games, like we’ve hyper-financialized the world to the point where geopolitical war game theory stuff is all related to markets, which is absolutely insane. But um, that’s the world we’re in.","offset":2881,"duration":29},{"text":"Quinn: Yeah, I mean, like, uh, we’ll- we’ll each watch this Triple Witching in- in anticipation and see- see what Monday brings us.","offset":2910,"duration":12},{"text":"Host: I’m excited to see what happens. Yeah, like you know there’s obviously some people and I would say I’m in the camp that it leads to a window of weakness, but I can also be dead wrong and maybe too many people are think about that now including the Trump admin, so who knows what’ll happen when we wake up on Monday. Could be dead vol.","offset":2922,"duration":15},{"text":"Quinn: Yeah, like you said, lower your risk limits and just be able to weather anything because no one knows anything and it’s dicey. So in most of these situations, if you’re active, like you always get another crack at the apple. Like you know even the world was ending last week and then you got a chance to re-short the same level again this week and cover right now and it’s just- it’s like Trump says, like bing-bong-boom-bing. High-level chess.","offset":2937,"duration":26},{"text":"Host: All right, man, sounds good. Well listeners, we’ll see you- yeah we’ll see you in New York next week. Yeah, we’ll have Joseph Wang joining us for their live round. Sweet, that was awesome. We’ll run it back from our one last summer. Yeah, exactly. Sweet. All right. See you then. Later, bud. [49:46]","offset":2963,"duration":15}],"startTime":2881}],"entries":[{"text":"Host: I think there’s a lot of downplaying like how serious this is. The problems are here to stay and basically it’s sort of escalation mode until it’s not. Everybody was looking for a taco and you can’t taco reverse out of Qatar’s LNG facility being destroyed. The market’s screaming growth problem here. Let’s say everything goes hunky-dory and oil goes to 80. That’s still not good. The Fed’s still not cutting, liquidity picture’s still bad, foreign investors still need to pull their funds from these assets, like I just see a pretty strong ceiling on the S&P 500 for from that perspective. It’s just a disaster.","offset":0,"duration":33},{"text":"Host: Before we get started, a quick reminder that Blockwork's premiere institutional conference, the Digital Asset Summit, is returning to New York City this March 24th through 26th. This year represents more than $4.2 trillion dollars in assets under management with 150 speakers and 750 institutions attending.","offset":33,"duration":18},{"text":"Host: Speakers include SEC Chair Paul Atkins, CFTC Chair Michael Sellick, Fed Governor Steven Moran, and Tether CEO Paolo Ardoino, alongside countless other executives, asset managers, regulators, and the core crypto infrastructure builders shaping the industry. If you want serious institutional-grade view of digital assets in 2026, Digital Asset Summit is where it happens. Use code FORWARD200 for $200 off and head to blockworks.co/events for more details.","offset":51,"duration":30},{"text":"Host: Nothing said on Forward Guidance is a recommendation to buy or sell any investments or products. This podcast is for informational purposes only, and the views expressed by anyone on the show are solely their opinions, not financial advice, or necessarily the views of Blockworks. Our hosts, guests, and the Blockworks team may hold positions in the companies, funds, or projects discussed. As always, investments and blockchain technology involve risk. Terms and conditions apply. Do your own risk.","offset":81,"duration":29},{"text":"Host: All right everybody, welcome back to another edition of Forward Guidance and, uh, for the second week in a row, sadly, we are missing our compatriot Tyler. He’s- he’s in better health, it’s not a virus this week, but, uh, he had some work stuff come up and had to go attend to it. So it’s back to just us two again, the duo. Um, what’s up Quinn?","offset":110,"duration":23},{"text":"Quinn: How you doing, man? Yeah, we need this vault to cool down so we can get our boy back. He’s just- he’s just in the trenches right now.","offset":133,"duration":6},{"text":"Host: Dude, he is heavily in the trenches. And- and Muddy Waters is putting out some big short reports, too, at the same time.","offset":139,"duration":7},{"text":"Quinn: Yeah, yeah, they, um- what was that, SoFi?","offset":146,"duration":2},{"text":"Host: SoFi, yeah, they put out a short report on SoFi, which is- I wanted- I wanted him to be on so I could just, like, pepper him with it so he could just be like, I can’t talk about it.","offset":148,"duration":9},{"text":"Quinn: I can’t say anything. Yeah, yeah, exactly. Anyway. Big boy things to attend to, but, uh, he’ll be back. Um, not next week though, because next week is the Digital Asset Summit in New York. Very, very hyped about it. Um, going to be a ton of fun next Tuesday, Wednesday, Thursday. Get your tickets if you haven’t already. I would be very surprised if you haven’t already because now prices are going up. We’re almost sold out, but you can use FORWARD200 for 200 bucks off. It’s going to be a great time. Wednesday afternoon we have an entire Forward Guidance track dedicated to macro, the intersection with everything that’s going on. I was actually just on a- on a prep call this morning with Governor Steven Moran, which was super cool. We- we were prepping for next week, so that’s going to be an awesome one. Like, I- I’m super excited to ask him about- he dissented in the recent Fed meeting which we’ll get into. But, uh, yeah, it’s just, you know, we- we have a- a sitting Fed governor, we’ve got the head of the SEC, the head of the CFTC, like, it’s just- it’s going to be awesome. Um, really looking forward to it.","offset":157,"duration":56},{"text":"Quinn: Yeah, that’s going to be fun, man. The- the macro day, like, this is- this is top-tier stuff for, especially people who are thinking, oh, it’s a crypto conference, but there’s going to be, uh, a lot- a lot to talk about there.","offset":213,"duration":13},{"text":"Host: Crypto and TradFi are coming together. It’s- you know, whether people like it or not, it’s, you know, we still got to figure out what- what it actually looks like when it comes together, whether it’s just tokenized everything, but it’s happening. Uh, yeah, I mean, pretty soon we can just tokenize oil to bypass the strait.","offset":226,"duration":9},{"text":"Quinn: Yeah, exactly. Send it over internet rails instead. Yeah, that’s all you need to do. Um, anyway, with that out of the way, let’s get into the swing of things. I want to start to talk about, it was a Fed meeting yesterday. We got- it was also an SEP day. So no surprise, no rate cuts involved there, and we got their updated summary of economic projections. So just looking through a few of the key changes here.","offset":235,"duration":36},{"text":"Host: The- the FOMC updated their GDP forecast actually upwards for 2026 from 2.3 to 2.4%, which is quite interesting. Held the unemployment rate steady at 4.4. PCE inflation from their December projection of 2.4 up to 2.7, and core PCE from 2.5 to 2.7. Their projections for rate cuts are pretty much unchanged across the board, however. This is an interesting one. I mean, obviously the- the baseline reaction is- is, if you just look at the numbers, hawkish of- of PCE going from 2.4 to 2.7, but I feel like a lot of people expected even more of a hawkish function, um, which is interesting. What- what was your read on this, Quinn?","offset":271,"duration":41},{"text":"Quinn: Yeah, I- I thought it was dovish. Every meeting, uh, I put- or at least the quarterly ones where we get the SEP, I put together my own estimates, uh, of what I think they will be based on, you know, changes in data and rhetoric, etc. And I had a more hawkish dot plot, but there’s been a lot of moving pieces so I- I wasn’t putting too much signal or like, you know, emphasis on it. What- what stood out to me is that if you just, you know, let’s say you don't know anything about what’s going on and there’s no Iran war etc. and you see them raise inflation expectations and growth expectations, GDP and PCE, you would say it would be a hawkish interest rate policy path, and it wasn’t. So, like, you still had two governors that weren't Moran expecting three cuts this year, two more expecting two cuts, and then obviously the split- split between none and one.","offset":312,"duration":65},{"text":"Quinn: But to me, it was hawkish or- really dovish, and I think also like, the- the increased PCE expectations make sense, but um, I- I would have- I would have thought there would be a little bit more consideration of the impacts of demand destruction from- from the oil price shock because that, you know, there will be inflation if there’s government response that fuels the fire, it will be more long-lasting, but if there’s not easing or fiscal stimulus that responds, it will be more transitory to some extent and it will hit demand harder, so um, I would have expected- I didn’t think growth would get brought up. But overall, dovish because I think, you know, what Powell says is one thing and, you know, at the end of the day he’s not going to be around for that much longer, so I- I was really trying to think about what the committee and the votes and their projections would signal where consensus was for when Warsh takes- takes chairmanship, and dovish to me. Like, if- if five people already think, you know, two cuts or more, like-","offset":377,"duration":73},{"text":"Host: Dude, there’s not a lot of, like, convince- like, as much sway as I would have expected that would be needed to cut, especially if labor market starts falling apart. So I- I sort of feel like on balance it’s somewhat neutral because I think for sure, like this- this SEP and the press statement that came out and everything, that was quite dovish and- and you saw that initially. Like if you’re just tracking the 2-year throughout this whole thing, 2-year treasury. Initially, yeah, it was- it’s pretty calm and then it seemed like he- it got a little bit more hawkish in the press conference because Powell was really kind of mentioning that this SEP is- is pretty stale in- like it’s not fully considering the Middle Eastern shocks, the oil shock, and I think that’s pretty valid. Like, do you really think that we can have them, like, predict what the 2026 growth outlook is going to be? Like, no, no chance. So I mean, to me it’s just- it just kind of on balance feels somewhat neutral, maybe slightly dovish because they’re not trying to front-run this reaction function. But yeah, to me it just feels like, you know, Powell’s just trying to get to the finish line in one piece.","offset":450,"duration":61},{"text":"Quinn: Yeah, they- I mean, also to be fair, he’s like- he said a couple times almost like point-blank, like we don't have any confidence in these projections because there’s so much ungo- he like, and even if consensus is around zero-one cut, that cut’s going to come late in the year, so, which is many, many months out and this will change a bunch before so. Yeah, it’s definitely not one that everything hinges off of like you sometimes get, but it was interesting. Like, yeah, whatever.","offset":511,"duration":28},{"text":"Host: I- I do think what is interesting though is how markets are reacting right now since that’s a lot more coincidental and you can see Fed funds futures. We- we went from just a couple weeks ago, we had over two cuts priced for 2026 and now we’re- we’re basically at none. So even though the Fed is still on board for maybe- maybe one cut in- in 2026, the market’s like no, it’s- it’s not happening. And that’s where the story is, right? Because, you know, real-time market data might be a bit better at trying to forecast where we’re going here. I guess my question is like, how in the world, given, you know, the private credit issues, given the now commodity price spike stuff, even if the war ends tomorrow, there’s some lasting effects, given waning liquidity broadly and slowing momentum of asset prices. Like, how does- how- how possibly could equity prices stay elevated without- without liquidity help? So when I think in that frame, it’s like, okay, well then what’s the- okay, then the forcing function is probably the equity market for cuts and then what’s that level? I don’t know. I was sort of looking at December SOFR futures as like a potential. I don't know what’s better risk-reward, shorting equities or longing those, but it’s definitely, like, push comes to shove, like, Trump’s getting cuts if- if stuff starts hitting the fan. So I think it’s getting to levels that’s sort of interesting. I haven’t pulled the trigger yet though.","offset":539,"duration":92},{"text":"Host: Yeah, it’s- it just seems like this whole thing of how difficult it is for- for how central banks are set up to react when oil supply shock, it’s- it’s just so difficult. And this is even like a- a dual mandate central bank. You know, some of these other- and this is a big topic I want to get into here, is if you- where am I looking? When you get to looking at the other central banks and how they’re reacting to the situation, it’s- a lot of these are single-mandate central banks. So all they care about is inflation. They don’t have a mandate for unemployment. So when they see inflation go up, their- their framework are basically forced towards them with a hiking bias.","offset":631,"duration":32},{"text":"Host: So you can see the Fed is, yes, it’s- it’s come back a lot in terms of the number of cuts, but we’re still on net- like we’re- we’re not pricing any hikes anywhere right now on the Fed side of things. But then you look at the ECB, we have- we have gone from pretty much flat towards almost two hikes over the next little while here. Bank of England today had their meeting and it was a huge surprise and this isn’t updated in this data yet, but they were- they were priced to pause, or sorry, they were priced to cut at this recent meeting today and they surprised by holding flat. And this really just shows how difficult and how frozen these central banks are where they- they’re at the whim of inflation. They can’t think in those second orders and, you know, us as market prognosticators can be like, oh, they should be doing this. But the fact of the matter is like, they’re mandated by- by laws and frameworks to be reacting in a certain way.","offset":663,"duration":49},{"text":"Host: So you can see this in the Bank of England, like the Gilts market just went absolutely bananas today. The 2-year just sold off like mad because it was fully priced for a cut and we didn't get that and we got this pretty hawkish retort. The entire board, um, voted to pause as well and not cut. So it was like a consensus hawkish pivot out of nowhere. And what’s- what’s so crazy to me is that most of these central banks are in economies that are also the most exposed to the oil shock. It’s just like this double-whammy situation where Europe is the most exposed and they have the least flexible central bank. It’s just- it’s just a disaster.","offset":712,"duration":42},{"text":"Quinn: Yeah, I guess this must be the catalyst for the move today in- in- in the dollar versus especially like the pound and the Yen, you know, dollar weakened really- really massively today. Also weird that the dollar weakened massively on a day gold was down huge. So it sort of says that, um, the run-at-hot trade has been stymied here where fiat actually looks all right if central banks are going to be hiking into- into this and actually attempting to get inflation down. I think, I mean, where I stand is it’s like show- I don't really have any bets on it because I want to- I want to see the proof in the pudding because it’s all talk until your equity market starts getting, you know, pummeled. And, uh, you know, everything’s pulled back, but nothing dramatically or- that signals real panic. So I- I’ll be curious to see how these rate hike expectations hold up once stocks start taking it on the chin, which I would expect soon.","offset":754,"duration":68},{"text":"Quinn: But yeah, man, it’s a- it’s a weird- like the- yeah, the energy situation is just so dire if- if the strait doesn’t open. I mean, maybe- maybe there’s some things too around these headlines where um, you know, the- the allies were saying, okay, we- we will help open the strait because like at the end of the day, you know, Trump’s definitely dangling this threat of export controls that that would really- really just really- really affect the rest of world super negatively, um, and also be bad for us and use the dollar etc. So maybe that’s also something to do with with the dollar’s fall today.","offset":822,"duration":40},{"text":"Host: Yeah, definitely an interesting one when you mentioned about, uh, the export ban situation because the- the energy secretary came out today and said we don’t plan export ban on WTI Crude, but they didn’t say anything about, uh, any sort of refined products and that’s where the meat of the situation is. There’s this good, uh, you can see the chart here, like refined products versus oil. The real move has been in those refined products, like yeah, diesel’s up way more than WTI, and so refinery margins are- are up a ton. You know, this is- this- you can see this in like the- in the crack spreads. But this is what really matters in terms of like an export ban, in terms of like protecting consumers from affordability at the pump and that sort of thing. So that’s still on the table.","offset":862,"duration":45},{"text":"Host: We- we did see this, you know, the WTI Brent spread went like absolutely nuts over the past couple days, um, and it- it seemed like a lot of that was speculation around this export ban and then as soon as you got that- that news hit the tape, you saw that start to come together. WTI started to rally and then it seemed like everything started to sell off in- in quick succession, too. So um, yeah, weird stuff afoot. How- how are you thinking about the energy situation? Like last week we were kind of in a everything’s fucked, um, and it’s just- it’s just a time thing. I’m still of that mind, I’m curious how you’re thinking about it.","offset":907,"duration":39},{"text":"Quinn: Yeah, I- I- I mean, like today, I- I had that- BB’s press conference was- I- I mean, I got to imagine that was Trump saying, you know, US saying, dude, you got to show face, where you been, go out there and- because right, that helped calm the markets today. But I mean, are you really going to believe this guy? Like they just- they just, who knows what to believe. But you know, maybe they went rogue on this natural gas facility that caused, but um, you know, the- they had to do it too because there’s- there’s reports that they’re- their big Haifa refinery got hit, which as we know is potentially what um slowed Israel’s aggression in- in the previous skirmish because they don't- I mean, they’re just like similar to other Middle Eastern countries, they don’t produce any oil and they don't have, you know, tremendous access outside of a few main key assets like that. So um, yeah, there’s- I just- this- like peo- I just don’t- like, I think there’s a lot of downplaying like how serious this is because it’s like, this isn’t playing like, you know, soldiers, you know, with your friends outside where it’s like, oh, I’m sorry I just socked you in the nose and gave you a black eye, like I promise I won’t do it again.","offset":946,"duration":75},{"text":"Quinn: And let me backtrack. And then, you know, your parents get involved and say, okay guys, cut it out. Like, we just tried to end their whole country and leadership. Like, and then now we’re going for their energy infrastructure assets. Like, oopsies don't really get a lot of, you know, you know, sympathy in- in war. And- and so I just- I just think this is- the problems are here to stay and basically it’s sort of escalation mode until it’s not and until there’s sort of a climax and regardless, even if not, every day that goes by that something like this stuff happens, it makes, you know, other energy assets globally more valuable and- and takes supply off more structurally like this, you know, Qatar gas field, like was like $70 billion over 10 years or something. This isn’t like a band-aid fix out of so. I’m still really long the natural gas torque equities in the US, long the coal equities. Those- those really had a day today, um, and then my big- big trade is the agricultural stuff. But um, I just- like I don’t- I just think people are still under-positioned. Like this- it kind of reminds me when gold first broke out like three years ago or two years ago and it was like oh wow, just- and you just doubting- doubting- doubting- doubting that it can keep going, but it just does.","offset":1021,"duration":79},{"text":"Host: Yeah, I mean the fact of the matter is everybody was looking for a taco and you can’t- you can’t taco reverse out of- out of Qatar’s LNG facility being destroyed and like they said, yeah, like three to four years to fix what’s been broken. I saw a headline, it was like it took us 26 billion to build this and this is 20 billion dollars in damage. Like if- if we end this tomorrow, the world’s largest LNG export facility is still under significant duress. Like shit’s getting real now. Um, yeah, I’m still really focused on where- where these- where these impacts start to lie. You know, I think- I think a lot of people have been really focused on- on the US and, you know, it’s like okay, if- if you’re bearish people keep going to short like Nasdaq or for example. And I think there’s just a lot more nuanced ways to look at it in terms of the rest of the world and um just want to start with this chart just looking at where do- where is the destination for the Hormuz LNG exports? And it’s, you know, South Korea, it’s- it’s China, it’s- it’s Asian markets predominantly.","offset":1100,"duration":64},{"text":"Host: And then you- you take that and let me get at slide 31 here. You take that and you look also at, okay, what are the economies that are most energy self-sufficient? So looking at oil consumption less production as a percentage of GDP versus share of oil in energy consumption mix. Uh, and again you can see in the top right there South Korea again. Like Asian markets that are highly-highly dependent on- on the Strait of Hormuz operating, they’re the most at risk here. You pair that too with the fact what we looked at earlier is a lot of these- these currencies are- are weakening relative to the dollar. The US is largely- they yes they, you know, they do import still, but- but largely they’re energy independent with reserve currency. They’re- they’re going to be the least bad of everybody I think. Um, maybe Russia and shout out Canada too on the left side of there. Hell yeah. If we can actually get- get out of the way of ourselves and actually start to- to pump some oil out of the oil sands in Alberta, that’s a different story.","offset":1164,"duration":61},{"text":"Host: But overall, it’s really important to drill down I think into these hyper-specifics of- of where the impact lies and then bring it all together is this chart’s been going somewhat viral the last few days because you know people ask what the price of oil is and it’s like well, what oil? You know, you got to be looking at Crude WTI Crudes at 95 bucks, Brent’s breaking above a hundred, but Dubai Crude and Oman Crude, like Oman is the vector to look at acute demand need for oil from Asian markets. That’s- that’s largely where it’s gone and that stuff is earlier today broke above 170 bucks. And that’s just unheard of. So you have to, you can see the dislocation here, like for months these things traded in a pretty tight range together. Um, but you really have to- you really have to drill down now and think about where the second-order effects, what- what even contract of oil am I talking about here? And really try to understand how does that impact the currencies, how does that impact their economy and therefore their- their equities? So it’s like, I don't know, if- if you want to express the short here, um, yeah Nasdaq will probably work, but there’s probably a lot more effective plays like shorting, I don't know, South Korea equities and that sort of thing.","offset":1225,"duration":67},{"text":"Quinn: Yeah, yeah, I’m- I’m- I’m in uh short Japan, short South Korea, short Europe, still smaller than some of my other ones, but um, I’m starting in. Because I- I’m like medium on the dollar, I don’t- I- I think there’s like we were talking about in previous shows like these- these capital flows and- and asset allocation headwinds that- that the dollar has, but you know for all these energy independence reasons it’s got some tailwinds in times of- of madness too so. Um, but I do like having some of that on. I think the other not to overly uh harp on the agriculture stuff, but I’ve- I’m seeing more people talk about it and- and people are going straight to the fertilizer tra- aspect of the trade. Um, and I looked into that as well and follow it. The thing I like better about the- the base commodities, which I think are being slept on, is the fact that what is corn, uh sugar or- or wheat? It’s just the combination of seeds, fuel, fertilizer, labor, farming profit margins, planned costs, all into one.","offset":1292,"duration":77},{"text":"Quinn: And, you know, we’re seeing the fertilizer and the fuel cost to- to plant, harvest, and grow spike, but the other side of the trade is that farming profit margins have never been worse, they’ve been in recession for three years, supply as these farms shut- shut in is falling, so there’s not a good- not a good um response effect there. And- and so it kind of encapsulates all of these things into one where the- the cure is just simply higher prices of these assets, particularly if this it’s spring planting season and so you need- need the fertilizer more acutely during this time. And you don’t have to worry about buying like equities in a fertilizer agriculture company which have already been bid up, like the um, you know, the multiples on- on a lot of these Ag companies are now much more elevated.","offset":1369,"duration":55},{"text":"Quinn: But yeah, there’s no strategic corn reserve. Um, so there’s and demand doesn’t get hit, right? If- if oil goes to 100-150 bucks, people stop driving, people stop flying, people stop vacationing, all that you hit demand. But like if your food goes up 30 percent-","offset":1424,"duration":14},{"text":"Host: South Korea’s in some ways.","offset":1438,"duration":1},{"text":"Quinn: Yeah, if your food goes up 30 percent, I mean you need food, like you can’t just- you can eat less, but you know, unfortunately, it’s the countries that are you know the- the developing and underserved parts of the world that probably get hit the hardest from this. So, um, I just don't think it- I- I don’t- I hate to use like these analogies that, you know, say that- that kind of point to it being like so similar and going to play out the same way as like Covid and- and that’s kind of become quite talked about now, but you just don’t know the second-order effects and- and you know we’re three weeks into the strait closure. This- that- and we’ve been saying every single week, two weeks. And now there’s no way to do it. Like it might be mined, the only boats getting through are going right close to Iran and sort of like ally ships. Um, it- it- it clearly shown it doesn’t take much to keep it closed.","offset":1439,"duration":52},{"text":"Quinn: So it’s- it’s seeming more and more like you need some boots-on-the-ground operation and it’s just constant fog of war propaganda to- to try and keep the markets afloat. Because at the end of the day, why would they- if- if they can just jawbone and say like send people on TV and say it’s the war’s over, it’s going to end soon, all this stuff, and the market buys it, they will never stop. That’s kind of the- the- that’s like the dichotomy of this- like paradox. It’s like, if- if they can keep the market elevated but continue to wreak havoc, they’re not going to stop. It’s until there’s a forcing function in the market. And- and you see it in oil, right? Like the jawboning works and then it gets bid up the next day, right? Like until the next attack gets televised. So I don't know, man, it’s- it’s weird how everything one has become so markets-focused and also too, how everything just moves on the whim of- of like narratives and tweets, but uh it’s- it’s driving people crazy, I know that.","offset":1491,"duration":63},{"text":"Host: Yeah, I mean it’s nuts. Like then the next impact of that too is that, like we talked about last week, now that Iran knows where Trump’s, you know, liquidation level is, markets, like that’s going to incentivize them to go after energy infrastra- infrastructure more than they would have if he wasn’t as, you know, if he didn’t care as much about markets. So, like they-","offset":1554,"duration":23},{"text":"Quinn: Yeah, you have their foreign minister tweeting like this exact stuff. It’s- it’s such a weird, I mean, it’s so- I guess that’s a part of the new- new type of fighting wars is like it’s less people on the ground and it’s more like economic and financial warfare. But you know, it’s not a- we luckily the world in general is like a positive sum, right? Like over time people get lifted out of poverty, you get more efficient productivity, um, so when we talk about like Europe and Japan being less you know disadvantaged more relatively to the US, it’s unfortunate that it’s still like you know we’re- we’re decreasing the pie with all these things instead of increasing.","offset":1577,"duration":41},{"text":"Host: Before you place a trade, you should know who is actually moving the market. That’s where Arkham comes in. Arkham is a crypto intelligence platform and exchange that lets you see real on-chain data. Which wallets are buying, selling, and moving funds. And then trade directly on that information. Arkham was built to make blockchains human-readable. Instead of raw transaction data, you get clear profiles, visualizers, and custom dashboards that show what’s really happening beneath the surface. Tracking wallets and fund flows is becoming just as important as technical or fundamental analysis. On-chain intelligence is also one of the best tools traders have to protect themselves against hacks, rug pulls, and scams. With Arkham Exchange, you can go from insight to execution in one place. The world’s first exchange powered by crypto intelligence. Check out Arkham and start trading with real on-chain insight at arkham.com.","offset":1618,"duration":48},{"text":"Host: I think what’s tough, like, I don't know, it’s just, you know, there’s a lot of stuff where it’s like reaping what you sow right now too in terms of like- this was a great actually chart and tweet from Andreas Steno Larsen looking at who’s been the big winner so far and it’s been Putin. Um, the- disc- like all- all- all you know, you have this- there’s a mention this morning from- from Treasury Secretary Scott Bessent talking about how they might lift sanctions off- off Iranian oil that’s on sea right now. And it’s like, who’s winning here? It’s- it’s that, um, it’s- it’s Russian oil that’s, uh, you know, you’re seeing the discount close here because, you know, you got India, you got these other countries that are starting to be able to buy it again. Um, you know, we’re just these tail risks that have been avoided for decades by world leaders, Western world leaders, in terms of where does our energy come from? You know, we’ve been too focused on- on ESG mandates to think about okay, well what would happen if the Strait of Hormuz closed or what would happen if we sanctioned Russian oil and these sort of things, and now a lot of these- these chickens are starting to come to roost.","offset":1666,"duration":68},{"text":"Quinn: Yeah, it was interesting and Powell, he got asked that question about like some of these longer-term things and- and one of them was, he- he gave like a- a nod or tip of the hat to these like bigger geopolitical theories that- that isolationism and- and secular conflict is increasing on a secular basis, um, which I thought was interesting. Like, it’s definitely everybody’s thinking about it. And yeah, it’s, you know, we’re still in this, I guess people, the market structure elements that are keeping the equities pinned and- and hasn’t really gotten people panicked, but it’s just so- it’s- one it’s like, you know, my portfolio is positioned in a way that benefits when the world goes to shit, which is not fun, like but I’m not going to like just sit there and like be long Nvidia amidst this. So, but you know, no one wants to root for that. That sucks. Um, but at the same time, it’s like you’re just waiting for the shoe to drop and there’s these market structure things ongoing that to me seems inevitable. I put some charts in there that- yeah I was going to say you got some charts, let’s see- let’s see what-","offset":1734,"duration":68},{"text":"Quinn: Well start with the first one, um, I think 35. Um, yeah this- this just shows that- there’s all this talk about how you know Mag 7 and etc. is under-owned, but they’re such a large part of the S&P 500, um, and the Nifty Nifty 50, you know the top 50 stocks. Like it’s still very overweight relative to the rest of S&P 500. So you know, if you look in like 21 when we got down in 22, 23 when- when relative outperformance of large-cap mega-cap bottomed, like there’s- there’s plenty of room to go. And if you look at the next one, this- this hawkish rate move in- in yields up, like similar to what we saw BoE, has also coincided with defensives massively outperforming cyclicals and- and forward equity growth and earnings are kind of slipping. So like, the- the market’s screaming growth problem here. The market is very much- and bonds have repriced lower, yields higher to some extent, but- but big parts of market are saying growth issue.","offset":1802,"duration":69},{"text":"Quinn: And then the next slide is just- this was an interesting one from RenMac that showed that yesterday’s PPI readings pushed in the 90th percentile historically and this is before the Iran effect. Um, so this is really problematic and like we were kind of talking earlier is like whether this is transitory inflation or not is going to matter if, you know, what the- the policy response is. And it’s hard not to see it being inflationary, um, especially given we’re still working through tariff impacts and everything. I mean, it just feels like the classic scenario where they- they’re forced to hike into slowing growth and that kind of puts an end to the global cycle.","offset":1871,"duration":43},{"text":"Host: Yeah, like the best case from here obviously is war ending and we stop losing lives and- and tons of- you know, waste of money and all you know, conflict. But if- if it does end quickly, you know, maybe there’s this way that they can cadence rate cuts to soft- sort of soft-land the inflation effect, but like keep the economy afloat, but it’s going to be really hard. Um, and it’s so reflexive with- with the markets and equities. Uh, I thought it was interesting on this next slide, you know, we’ve been talking you- you walked us through the options expiry dynamics tomorrow, um, and there was a- someone sent me this on Robinhood, uh, article writing to their retail audience about the Triple Witching and, you know, how the median is down.","offset":1914,"duration":44},{"text":"Host: Yeah, they’re like stocks sometimes go down, but don’t worry about it. Moves can be exaggerated because of this. And then, um, I- the next slide is just the from Goldman, the CTA estimates. So they show in a- in a flat market and flat and down markets, they show a pretty big CTA unwind. Obviously, if the market’s up CTAs relever, but given where Vol is, it’s probably, you know, you- you’d need a really big- big event for that to kind of turn. So the- the direction of travel is- is the same lower- lower place we’ve been going.","offset":1958,"duration":33},{"text":"Quinn: On the next slide, this was an interesting chart from JPM just showing the Quant equity degrossing drawdowns and the long-short degrossing, which this is um total leverage, so this is like if you’re long a hundred and short a hundred and you’re net neutral but your- your gross is 200. We’re still at record gross, you know, leverage levels. Like people have just been sort of- people haven’t been deleveraging, they’ve been adding puts and shorts. So um, it’s usually not over until you get a proper degrossing event and we haven’t seen it yet. Like if you compare this to- to um all these historical events, it’s- it’s not even recognizable on this chart.","offset":1991,"duration":46},{"text":"Quinn: And then you have the next one, today actually kind of kicks off earnings blackout into, you know, the next six weeks and through April so you have less market support there. The options expiry passes and then top-of-book S&P futures liquidity is horrendous. Like this is rivaling some all-time low levels like last Q1 or 2022 levels. Um, and we’re seeing that, right? Like stocks are whipping around one percent a day up down up down and everyone’s losing their minds. But when you zoom out and look at like a one-day- or three-day chart, like the trend is very much down and we’re like just peaking- peaking below the 200.","offset":2037,"duration":38},{"text":"Quinn: Um, and then the last thing I would show is- is everybody’s been talking about this hedging, right? So everybody’s loaded up with puts to- to hedge upside- downside instead of selling because no one wants to sell their winners and you know recognize taxes and gains so they just buy puts. But we all know that the puts haven’t been working because the market’s been stairstepping down and theta’s burnt and now we’re to options expiration. But a- a not great sign for the market is when skew comes off this much, which it has been. So skew has fallen um dramatically, but volatility hasn’t, which basically means that the- there you know this skew referring to put skew, so when it’s elevated you know puts are in demand more- more so than calls and there’s a huge pre- there’s a- a premium paid to buy the protection to the downside.","offset":2075,"duration":53},{"text":"Quinn: So when that falls it basically just means there’s less- the market is less protected in terms of options demand and if volatility is still elevated, you know you’re still in sort of a risk-off period, um, you know the market’s more vulnerable. So everything is lining up aside from like Robinhood talking about the options expry. So that- that- I don't know what to believe anymore. I just like believe in my- my case and so I’m short the things I’m short and I’m long the things I’m long, and we’ll see. Like but it doesn’t feel like- everybody I talk to is still waiting for the taco, doesn’t want to miss the bounce, like cannot imagine sitting- like a good example is my Substack chat. Like Monday and Tuesday when we didn’t even like, you know, we just did the same exact price action of last three weeks. Everybody was losing their minds. They’re like, oh my god was this it? Yeah- yeah they’re just- and it was like one day of a bounce. Like literally three days red, one day bounce, three days red, one day bounce, and on like the one day bounce people are like it’s- I knew I should have closed. Like and so that just shows you where sentiment is whereas when you’re at a bottom people are puking, right? Like people aren't saying like it’s- it’s- so I just feel to me like we still have ways to go and that this options thing could be a catalyst. But let’s see, you know the- the admin probably knows about it too and they’re probably going to try and roll out the red carpet to try and keep- keep things afloat.","offset":2128,"duration":85},{"text":"Host: This is just my favorite chart because last week we showed this exact chart people remember talking about how, you know, it was before this reversal and it was just like put skew was like at yeah like above 1.2 is ridiculous and it’s just like we said, nobody can make money on the downside if everybody’s that bought into puts. Um, we’re just going to burn them. And then you know those- those three days down, one day up, that is just the perfect way to- to just burn through theta. Like you just- I can’t even imagine the amount of theta that’s just being burned right now with- with elevated implied vol. Like everybody bought these at- at elevated levels. I do think, yeah, like either you just you know keep your risk limits tight if you’re buying puts and know what you’re getting yourself into or you- you just go out and outright short and avoid the whole situation. Um, but people- like the fact that Robinhood is talking about this means the game is known. Um, and then you have to think through the third-order effect of that which is probably you’re right, which is that- that Scott Bessent’s probably briefing- briefing the boys about hey look you know Triple Witching’s happening this week, window of weakness is coming up and- yeah send Netanyahu out there to like try and calm, say the war’s ending- like yeah, it’s all- it’s all- it’s all on the table, man, like because they- they need the- they need the space to operate and they’re trying to keep markets elevated.","offset":2213,"duration":85},{"text":"Quinn: Like, ultimately though, you know, these are physical commodities we’re dealing with. These are like, you- you can only- there’s some- there’s some level where just kicking the can and sort of lying to save face eventually backfires because then when you actually- when there actually is good news, people won't believe you because they’re like I’m not falling for that. So I don’t know if it’s the best strategy, like um- but it’s not our- it just remind- it reminds me of what we’ve talked about before in terms of how volatility can’t be suppressed, only transferred. And you know people are- they’re trying to suppress the volatility of- of CL front-month futures, but then you look at what’s going on in- in Oman and Dubai oil and that’s above 160 bucks and, you know, I’m- I’m not smart enough to make a- a certain decision about this, but I imagine by suppressing front-month CL, you creating- you creating volatility where you can’t control it. It’s being transferred. Like you know even over the past few days you’ve seen many days where the front-month contracts have been actually coming down but the- the back months, like the 2027s and stuff, have been rising further, and I’m sure you can make the argument that look, it’s like if- if you think that your counterparty in the books is- is Scott Bessent on front-month futures, you’re going to go speculate on the back ones and that could have a whole bunch of unintended consequences. Like you can’t, yeah, you can’t suppress the volatility, you’re only transferring it to more esoteric ways.","offset":2298,"duration":84},{"text":"Quinn: So here’s one I was just thinking through. Go to slide 45. And- and I’m kind of- I was literally just thinking through it before this so um, this might be a little green. But um, so this is the- the trade balance data which we’ve been talking about for a while. Ex-gold in the in the red there and the blue is just regular. Um, the lines there show the increasing on the left side means that the trade deficit is shrinking. So it was running on an average you know well north of 80 billion, kind of 80 to 100 billion pre- uh pre-tariff changes and some of those were front-running. But um, post that and as we kind of normalized, it’s- it’s dropped a good 30 to 40 billion, which is- is super significant from- from the levels, which we’ve talked about means, you know, if you can see on the right chart there, um, it means, you know, more exports relative to imports, um, versus the baseline levels. And um, less dollars in- in rotation globally, um, and in- and so that kind of puts a- a headwind on the dollar and you know that’s some of the probably bid behind gold.","offset":2382,"duration":71},{"text":"Quinn: But if you think about this, like if they were to put an export ban on our commodities, which are- which are sizable, so you decrease exports, so the trade balance would go further negative, meaning like our deficit would increase, which on the surface you know when your deficit- if- if trade is expanding and your deficit increases, goes further negative, you know that’s more dollars in existence globally because it’s saying imports are rising faster than exports. But in- if everything’s decreasing, meaning the trade- total trade is going down because you’re slowing growth and your exports are- are coming down as well, um, that means people need less dollars to buy. So I don- you know, that- that’s probably a negative side effect that people I haven’t heard anyone talk about. I haven’t thought this through completely, but if you did ban exports of oil and gas, people need less dollars and presumably the dollar would fall on that, um, which would have ramifications for inflation and the things other things you import as well as like capital flows because if the dollar starts falling and kicks off you know people having to kind of hedge and- and sell other US assets or something. So like you said, you can transfer the vol, but you can’t completely eliminate it, and I think that’s where people are at is like a little too much complacency around policymakers’ ability to control things that ultimately in the long run they can’t control.","offset":2453,"duration":88},{"text":"Host: That’s a great, um, yeah this first time thinking about this too, so you know we both might be missing something here, who knows what, but that to me sounds like what could be the bear case for- for US assets specifically and the dollar. Because everything else we- we’ve talked about ad nauseam about the risk for the rest of the world, Asia, Europe, etc. But what is the risk here for the US if they’re energy independent? And yeah, I do think it’s- it’s that, less dollars going out to the world, less um, and yeah, so then I add that towards what’s also going on when we look at the AI data center build-out and- and what’s financing it as well is you have okay, a lot of the capital investment has been coming from the Middle East. Um, they’re, you know, I imagine they’re marginally less interested in- in buying the next big AI data center when they’re fighting for their lives right now. Um, and then also you have key inputs into that AI data center build-out. Like helium market is, you know, everybody was all focused on oil but I think- I think we should be also equally focused on things like the helium market because that is just a one-to-one input into compute build-out.","offset":2541,"duration":69},{"text":"Host: And so if you have further shortages on those key inputs um and either the price rises or there’s shortages, both of those equal less AI data center build-out. And also at the same time, you know these- these Middle Eastern countries that have been financing a lot of this are probably going to be hoarding money because they don’t know what the hell’s about to happen to their economy. Um, you know Dubai is like- I’m sure I don’t know the numbers but I’m sure the vast majority of their revenue comes from rich people living there and spending a bunch of money and if- if they all bailed, like I’m sure their- their revenue situation is not looking too hot right now. Um, you know I’ve- I’ve even seen some people speculate that some of the- the gold price action of- has been the Middle Eastern countries selling just to hoard some cash and you know try to survive where we’re going next. Uh, there’s a, yeah, there’s just- we could- we could probably spend another 20 minutes here thinking through these unintended consequences, but there’s just- there’s so many.","offset":2610,"duration":56},{"text":"Quinn: Yeah, if you’re these countries, you know, they’re preparing for war to go start fighting against Iran as well and they’re looking at like they all own a ton of US stocks, right? And you’re seeing the S&P down 5% and your country is, you know, economically in a crisis event. You have to be liquidating these assets. You have to be and repatriating it. So, um, you know if for nothing else maybe to support your currency or you know your economy. Like it definitely creates massive isolationist deglobalization vibes that are just large moving ice cubes and glaciers, they’re not- they’re not just one-time events. Because when I think about, okay, you know, every- this war’s in everybody knows about it, it’s in plain sight, you know asset markets have responded to some extent, oil’s you know at 100 bucks. Like where- where is this wrong? Where am I wrong? Where are the holes in this? And to me, it’s like I don't really see a world given the damage done, you know, etc. to infrastructure. I don’t see oil going back to 60. Like I- my best case is like, okay, we- we lose 20% and we’re back down to 80, 80 bucks a barrel, which- which to me, yes, it takes the sting out of- of doomsday tomorrow, but it doesn’t- it still fuel to an already not great situation for risk assets.","offset":2666,"duration":92},{"text":"Quinn: And oh, by the way, like is Qatar going to want to commit $25 billion to the next OpenAI or whatever AI round or data center in the US if they have to pay 20, you know, whatever it is to rebuild these gas fields and their infrastructure? And also overnight, the other thing all these countries, they’re going to need to double-triple-quadruple their security budgets because no longer, you know, they’re going to have to start investing in Strait of Hormuz security, their own security, weapons, defense. So this is like, this is a pretty big like crowding-out effect as well from- from private investment to like sort of like public infrastructure, security, defense, safety goods um, which is not- it’s super negative for like overall productivity because you’re basically needing to finance more and more of these things from the government side. You know, they- like Congress I think is going or- admins going for a $200 billion like you know extra defense thing, you know soon.","offset":2758,"duration":55},{"text":"Host: The war’s ending soon but we need 200 billion dollars.","offset":2813,"duration":3},{"text":"Quinn: Yeah, and we need to send another warship and- and all these like. So, um, yeah, like you said man, like when I think about like where is this wrong? Like I- I don't really see how you put Humpty Dumpty back together here. It’s just like you can just slo- like you can just slo- like you can just like use glue to like make him fall apart less quickly and- and make the stairs more gradual, um, which is seemingly what they’re trying to do. But I just don't understand when I- when I zoom out, it’s like okay, let’s say everything goes hunky-dory and oil goes to 80. That’s still not good. The Fed’s still not cutting. Liquidity picture’s still bad. Foreign investors still need to pull their funds from these assets. Like I just see a pretty strong ceiling on the S&P 500 for- from that perspective.","offset":2816,"duration":55},{"text":"Host: Yeah, yeah, I think the best case right now is flat.","offset":2871,"duration":5},{"text":"Quinn: Yeah, and then you lose in real terms because there’s 4 or 5% inflation.","offset":2876,"duration":5},{"text":"Host: Yeah, 100%. Yeah, well, probably leave it at that, but I think yeah the main takeaways are stuff’s still happening. You know, you can try to suppress it for so long, but things will emerge where you don’t expect them to. And you know, there’s market structure games, like we’ve hyper-financialized the world to the point where geopolitical war game theory stuff is all related to markets, which is absolutely insane. But um, that’s the world we’re in.","offset":2881,"duration":29},{"text":"Quinn: Yeah, I mean, like, uh, we’ll- we’ll each watch this Triple Witching in- in anticipation and see- see what Monday brings us.","offset":2910,"duration":12},{"text":"Host: I’m excited to see what happens. Yeah, like you know there’s obviously some people and I would say I’m in the camp that it leads to a window of weakness, but I can also be dead wrong and maybe too many people are think about that now including the Trump admin, so who knows what’ll happen when we wake up on Monday. Could be dead vol.","offset":2922,"duration":15},{"text":"Quinn: Yeah, like you said, lower your risk limits and just be able to weather anything because no one knows anything and it’s dicey. So in most of these situations, if you’re active, like you always get another crack at the apple. Like you know even the world was ending last week and then you got a chance to re-short the same level again this week and cover right now and it’s just- it’s like Trump says, like bing-bong-boom-bing. High-level chess.","offset":2937,"duration":26},{"text":"Host: All right, man, sounds good. Well listeners, we’ll see you- yeah we’ll see you in New York next week. Yeah, we’ll have Joseph Wang joining us for their live round. Sweet, that was awesome. We’ll run it back from our one last summer. Yeah, exactly. Sweet. All right. See you then. Later, bud. [49:46]","offset":2963,"duration":15}],"logs":[{"elapsed":"0.0","message":"Downloading audio from YouTube...","detail":null},{"elapsed":"0.0","message":"Trying download with browser cookies (ad-free)...","detail":null},{"elapsed":"28.7","message":"Audio downloaded (27.1 MB) in 28.7s","detail":"File size: 27.1 MB"},{"elapsed":"28.7","message":"Video title: Escalating Energy Shock Exposing Central Bank Limits | Weekly Roundup","detail":null},{"elapsed":"28.7","message":"Audio duration: 49:50 (49.8 min)","detail":null},{"elapsed":"28.7","message":"Uploading audio to Gemini File API...","detail":null},{"elapsed":"32.7","message":"Audio uploaded in 4.0s","detail":"File ref: files/qxfo5brlm8u7"},{"elapsed":"32.7","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"104.8","message":"Transcription complete in 76.1s","detail":"50225 chars received"},{"elapsed":"104.8","message":"Transcription tokens: 74,990 in / 12,708 out — cost: $0.0756","detail":null},{"elapsed":"104.8","message":"Parsed 67 transcript segments","detail":null},{"elapsed":"104.8","message":"Transcript coverage: 49:23 of 49:50 (99%) — OK","detail":null},{"elapsed":"104.8","message":"Total transcription time: 76.1s — 67 segments","detail":null},{"elapsed":"104.8","message":"Analyzing topics across 67 segments with gemini-3.1-pro-preview...","detail":null},{"elapsed":"146.8","message":"Topic analysis complete in 42.0s — found 13 topics","detail":null},{"elapsed":"146.8","message":"Analysis tokens: 13,242 in / 1,051 out / 4,244 thinking — cost: $0.0900","detail":null},{"elapsed":"146.8","message":"Pipeline finished in 146.8s — total cost: $0.1656 (106,235 tokens)","detail":null}]} \ No newline at end of file diff --git a/history/1775223585124-NDE0NjE5NDgtNDFi.json b/history/1775223585124-NDE0NjE5NDgtNDFi.json new file mode 100644 index 0000000..1c8ffba --- /dev/null +++ b/history/1775223585124-NDE0NjE5NDgtNDFi.json @@ -0,0 +1 @@ +{"id":"1775223585124-NDE0NjE5NDgtNDFi","videoId":"41461948-41b1-4ca9-bdf7-f59bc7e11956","url":"https://serve.podhome.fm/episode/8029725b-0319-44b9-4793-08dc404e83a4/63909632332260150341461948-41b1-4ca9-bdf7-f59bc7e11956.mp3","title":"CD196: EVGENY POBEREZKIN - SIMPLEX PRIVATE CHAT","type":"podcast","topicCount":19,"segmentCount":325,"createdAt":"2026-04-03T13:39:45.124Z","uploadDate":"20260320","chunks":[{"title":"Introduction and Zaps","summary":"The host welcomes viewers, thanks the audience for their support via zaps, and introduces a new Nostr-integrated website for the show.","entries":[{"text":"Host: Happy Bitcoin Friday, freaks! It's your host, Odell, here for Citadel Dispatch, the show focused on actionable Bitcoin and freedom tech discussion. A busy morning over here, I just wrapped up Rabbit Hole Recap, my other show, but we have a great show planned today. I'm very excited for it, but before we get there, as always, Dispatch is funded by our audience. We have no ads or sponsors. Thank you, freaks, for continuing to support the show.","offset":0,"duration":46},{"text":"Host: The largest two Bitcoin zaps from last episode... Our episode was Vexl, focused on no-KYC Bitcoin, Bitcoin donations. Peter Missouri: 21,000 sats. \"I have to admit that I often forget to zap because I listen to podcasts during my hour and a half long commute, and then I forget by the time I get to a stopping point. Although much of this is over my head, I'm trying to learn as much as I can, and this one definitely inspired me.\" Thank you, sir, for your support. And just on that perspective, that's how I've learned a lot of what I know today, just immerse yourself in things that are over your head, it means you're in the right room. Absolutely love to see it.","offset":46,"duration":48},{"text":"Host: And then the second largest zap was from RyderDie Freak Mapp21: 10,000 sats. He said, \"Great rip.\" As always, freaks, all relevant links are at CitadelDispatch.com. I know sats are scarce, I know Bitcoin... you're working hard to accumulate as much Bitcoin as possible. If you cannot spare the Bitcoin donations, the next best way to support the show is to share it with your friends and family. Citadel Dispatch is available on every major podcast app by searching Citadel Dispatch. Take your friends and family's phones, open the podcast app, search Citadel Dispatch, press subscribe. They won't know what hit them, but they'll be better off for it.","offset":94,"duration":48},{"text":"Host: And freaks, on that note, by the way, I've been... as you all know, I've been neck-deep in the AI world. I rebuilt CitadelDispatch.com. It still has all the relevant links you would expect, but it also is live-polling Nostr for the top zappers. So it's cumulative; the more you zap, the higher you get listed on the website. It's a little bit of a work in progress because it's polling Nostr live, and so sometimes it does different results, but the dream is that the people that support the show the most, the top 10, will always be highlighted on CitadelDispatch.com and you can just click their profile picture and it goes straight to their Nostr profile. Pretty excited about it, but work in progress, hands up.","offset":142,"duration":48}],"startTime":0},{"title":"Introduction to SimpleX","summary":"The host introduces Evgeny, the founder of SimpleX, and discusses how they initially connected using the decentralized messaging app.","entries":[{"text":"Host: Anyway, freaks, we have a great show today. A lot of you freaks have heard me talk about in the past the SimpleX encrypted chat app. You freaks know I love Signal, you know Signal... Signal has its own set of trade-offs, but it's fantastic that it exists in the marketplace. The two big ones are that it requires a centralized server and the second one is that they use phone numbers as a way to mitigate spam and bots. Fortunately, they recently removed the ability for other people you're messaging to see your phone number, but it still requires phone numbers nonetheless. SimpleX is a very exciting alternative that mitigates both of those concerns, and I'm pleased to have the founder of SimpleX here, Evgeny. How's it going, sir?","offset":190,"duration":49},{"text":"Evgeny: Hello, Matt. Thank you very much for having me. Excited to be here.","offset":239,"duration":6},{"text":"Host: It's a pleasure, sir. I... by the way, freaks, I think the way this came together is kind of cool. He found my SimpleX contact on my website, Odell.xyz, and messaged me on his own app and reached out and then we got onto a phone call, and I have to say the audio calls are working quite well now in SimpleX and we set this up pretty cool how it came together.","offset":245,"duration":31},{"text":"Evgeny: That's true, indeed. Yeah, we've been using SimpleX chat as the only communication tool, obviously, since we began building it, and yes, phone calls are fine, they're fine.","offset":276,"duration":11},{"text":"Host: I have to say, sir, my whole life I've been fortunate enough to successfully have moved the majority of my communications to Signal, which is great, massive improvement over regular phone calls and texts and email. But when that thing goes down, I feel quite vulnerable. And we've seen a couple outages lately, so I'm very grateful that you're building SimpleX. I think a great place to start here is just high-level: what is SimpleX? Why does it exist? Why should people care?","offset":287,"duration":40}],"startTime":190},{"title":"Core Philosophy: Sovereignty and Privacy","summary":"Evgeny shares his foundational motivation for building SimpleX. He emphasizes user sovereignty, trustless architecture, and privacy as an inherent right.","entries":[{"text":"Evgeny: I think my primary motivation to start this, to design the protocol and to build it, was never about technology. It was about all the sad state I've been observing the world is going to, how people were losing their jobs for stating the truths, and it all has become more and more pronounced in the last couple decades. So I... I should make some like embarrassing admissions, probably. I was never deep enough in any of the cryptocurrencies world, it was alien to me. I was never deep enough in privacy community, I didn't know it even exists. But I was in publishing. I spent a large part of my life in publishing from different angles. I worked as executive in publishing organizations, I owned magazine in my home country, then I worked as head of engineering at MailOnline, one of the largest tabloids. To me, publishing and communication was always one and the same, and to me, ability to say the truth is fundamentally foundational for the society, right?","offset":327,"duration":50},{"text":"Evgeny: If you can't say what's right, what's wrong, if you can't say what's truth, we can no longer exist even, right? Because everything breaks. And when we were building the SimpleX, retrospectively we can say it's built pretty much on the same values as Bitcoin. It's sovereignty. As primary value, primary foundational truth that we build on is sovereignty. Users should own their conversations, their channels, their connections, their identity, everything that they use. The fact that we build protocol by removing network-wide identity for the users means that now users own everything, now they are in full control in the same way you hold your Bitcoin keys. You own your SimpleX identity and your identity is what your friends see, what your contacts see, and it's not something that exists on a network, that's why you own it.","offset":377,"duration":54},{"text":"Evgeny: And the second principle was that it's trustless, right? So we always thought that I was... I just always thought that if a technology is built on the idea that for it to function I have to trust my technology provider, then it's not good enough because today technology provider can be practicing don't be evil principle, and tomorrow some pressures come along and it all ends up quite evil, and we've seen it over and over again. So the only way to make it not happen is to architecturally prevent it, right? To build technology in a way that single provider cannot act against users even if they want to, right? So it's like... and sovereignty has always been number one value here.","offset":431,"duration":43},{"text":"Evgeny: So like we had a lot of discussions with privacy community, obviously privacy community was the first to discover what we built, and obviously they had their own ideas about how we should build that, and traditional privacy messenger would be like you can always delete messages you sent even if they land on another person's device, right? And this kind of approach was kind of more and more pervasive and happens on Telegram, it happens on iMessage, and I think to this at this point we've been consistently refusing to do it this way because to me it was like I have files on my computer, I have to allow somebody else to delete those files, it's just wrong, right? So I have sovereignty on my machine, right? Why should it happen unless I agree to that? Then that was interesting. So like whenever privacy and sovereignty were in conflict, we were saying sovereignty is foundational both for security and for privacy. So fundamentally that's that's why we're building. We wrote some like philosophical almost statement recently, it's on our website, about that we don't we don't see privacy as some add-on, right? It's not like a shield and key, it's not a measure of protection, it's just literally a thing that always existed, right? We always had privacy before the internet.","offset":474,"duration":68},{"text":"Evgeny: You could talk to people, right? And nobody knew that who you were talking to or nobody was tracking where you go, nobody was tracking who you talk to, and we could have genuine conversations because this whole ability to have genuine conversation with people is predicated on the fact that nobody else knows who is talking to whom, and that was the whole the whole premise, to return it to the to return communication to pre-internet state, almost, right? When we can trust the the environment.","offset":542,"duration":38},{"text":"Host: Incredibly well said. I mean, this is something that I bring up all the time. I think first off, people don't real... the human condition is to accept the status quo as something that's always been. But we've never lived in a society that is as digital as it is today and it's getting increasingly more digital, our lives are increasingly more online. And as a result, we've lost a lot of the implicit privacy and sovereignty aspects of non-digital life and we need to protect it. I like to distill it as I say: no privacy, no freedom, and no freedom, no wealth. They're all interconnected and that no wealth piece, I think, is really important when we're bringing it back to Bitcoin specifically, but if you don't have freedom, it's not your wealth, someone else controls it.","offset":580,"duration":50}],"startTime":327},{"title":"Bitcoin Stats and Publishing Background","summary":"The host reads the current Bitcoin block stats before asking Evgeny about his career. Evgeny explains how his background in publishing and freedom of speech inspired the design of SimpleX.","entries":[{"text":"Host: I just want to apologize real quick, I did mess up the intro, um so I'm just gonna run through real quick. Today is March 20th at 1700 UTC, the current block height is 941454, current sats per dollar is 1,432. That brings us to a Bitcoin price of $69,792 and one Bitcoin will get you 15 ounces of gold right now, we're up on the one day, one week, and one month chart against gold. Um sorry about that interruption. I want to talk... so I didn't realize your background is publishing. Is it... were you act... what... were you an engineer involved with publishing? You came from the free speech side basically, not the privacy side.","offset":630,"duration":45},{"text":"Evgeny: It's hard to say what is my background. I I always enjoyed coding, but somehow it happened that I only did coding as a hobby for my own businesses. I probably am just entrepreneur who is doing what works. I spent a lot of time in different businesses, but yes, so I was in originally I was on publishing as a as an executive, not technology executive. I moved to the technology full-time about 12 years ago, or like a little bit more, maybe 14 years ago, and yes, I was working at MailOnline at on technology side. But yes, I came to this design from freedom of speech angle and interestingly SimpleX protocol was created, invented you can say, pretty much at the same time when Nostr protocol was invented.","offset":675,"duration":49},{"text":"Evgeny: But to me, you know you know this XKCD comic when one guy one nerd says to another or his computer has like you know that, right? Like 4,000, 906 bits of RSA encryption, it's kind of a trillion of years to break it...","offset":724,"duration":16},{"text":"Host: The $5 the $5 wrench the $5 wrench one, right?","offset":740,"duration":2},{"text":"Evgeny: Yeah, yeah. Go get go get $5 wrench, right?","offset":742,"duration":3},{"text":"Host: We joke around in Bitcoin that with inflation now the wrench is like $20, but yeah.","offset":745,"duration":4},{"text":"Evgeny: Yeah, exactly, yes. So and to me, to me like freedom of speech is just impossible if you cannot say say the truth without revealing who you are, right? So privacy is not about hiding, I think it's like it's in cipher from cypherpunk manifesto, right? You privacy is about selectively revealing yourself to the world, right? It's not about hiding, right? And depending on what you say, you may want to say it under your name or you may want to say it under a pseudonym, and it's essential to ability to criticize powers, it's essential to ability to share some uncomfortable truths, and that's what it all was about. But when we designed the protocol for private for for publishing that's resistant to attacks on individuals, we said oh, that's a messaging protocol clearly what we did, so why don't we make a messenger first?","offset":749,"duration":27},{"text":"Evgeny: Right. And we're just now approaching to the piece of the technology that we always originally wanted to build is effectively a publishing channels, large communities that can scale. We're like weeks away from launching the first version of scalable channels on on SimpleX network.","offset":776,"duration":34}],"startTime":630},{"title":"Comparing Telegram, Nostr, and SimpleX","summary":"The conversation contrasts Nostr's public broadcast model with SimpleX's private messaging. They explore the complexities of handling privacy within large group chats like Telegram.","entries":[{"text":"Host: Like a a better version of Telegram channels or Telegram groups, right?","offset":810,"duration":5},{"text":"Evgeny: Yeah, we had like large Telegram communities that literally tried to migrate to SimpleX network. Obviously, that didn't work because the current implementation scales to maybe thousands of members reasonably well after all the improvements, but not to tens of thousands as many Telegrams communities have. So yes, so we have a lot of interest from Telegram communities to use the network because because they would own it, right? We develop it in a way that each community can run on multiple relays, so in a way it's a it's a similar design to Nostr with regards to censorship resistance, but it's very different design with regards to privacy because to publish on Nostr you have to connect to relay, to publish on SimpleX channel, there would not be no direct connection, the connection to relay will be through the messaging network which means that privacy is preserved on a transport layer.","offset":815,"duration":51},{"text":"Host: Well, yeah, I mean, let's dive in here a little bit because to me, I've always considered the two protocols you... I mean, it is interesting how that worked out, right? That they both get birthed around the same time. That they're more complementary than competitive in terms of their feature set and use case. I mean, specifically Nostr is kind of trying to solve this one-to-many problem, it's a broadcast protocol first. If I want to broadcast to the world my thoughts, something like Twitter, right? Uh would be a comparison, that you know that's the kind of use case Nostr is trying to solve. And then also on top of that, kind of goes hand-in-hand, is an associated fixed identity that can be as public as you want it to be, right? You can be, you know, it doesn't it doesn't require permission to create these identities. You can have many disposable identities, but most people are using it in a way that they're connecting it to some elements of their real-world life and their real-world identity and then they're using it as a broadcast medium and discovery protocol.","offset":866,"duration":62},{"text":"Host: And then with SimpleX, you know, you have rotating identities, maybe you use different identities in fluid in-app with different people and different groups. And it's more like... I would compare it like if Nostr's like the soapbox that you're standing on the corner broadcasting your thoughts to the world, SimpleX is maybe the dark pub where you're with your local community having a beer and talking about really important things that maybe you don't want to be on the record about, but you just want to have free-flowing conversation.","offset":928,"duration":30},{"text":"Host: Now, when you start getting into the channels and stuff, it gets a little bit different, right? Telegram channels, I would say, Telegram's the behemoth in the room, that's why we're going to probably keep bringing them up, you know, they have two billion users at this point and they make a lot of privacy claims that technically are bullshit. Um so there's a a decent amount of overlap in the communities. But Telegram channels, so Telegram first started as DMs, then they had group chats, group chats I would say I would put more in the pub kind of scenario until they get bigger. Sometimes group chats get big, they're like a thousand-person group, then you're in like an auditorium maybe or something. But then Telegram channels are like more of a competitor to broadcast media, whether that's Twitter or Nostr or something like that, where the actual participants are not able to interact more so than maybe there's a comment box or maybe there's emojis, but it's really one person broadcasting to a bunch of people.","offset":958,"duration":58},{"text":"Host: And the reason I bring this up is because net-net you want those Telegram channels or large groups, I think you can kind of put them in the same... small groups and and personal messages, DMs, I think could be in the same group, and then large large groups and large channels can kind of be in the same group. Net-net, you want them to be end-to-end encrypted, but you always historically have the problem of all it takes is one person out of 2,000 people to be compromised uh or their their phone compromised or themselves be against whatever the group is, and they can be recording everything that's happening in there. So as you move into that feature set, how are you thinking how are you thinking about privacy in that scenario, right? Because like if if there's a thousand-person group, once again I think it's important that it's end-to-end encrypted regardless, it's the basis that everything's built on, but uh all if one journalist is in there or whatever just writing it up in the Wall Street Journal, then how much, you know, how you dealing with that? How you thinking about that?","offset":1016,"duration":64}],"startTime":810},{"title":"Participation Privacy and MLS","summary":"Evgeny critiques the Message Layer Security (MLS) protocol and highlights the importance of participation privacy. He stresses that users should be able to read and follow channels without being tracked or targeted.","entries":[{"text":"Evgeny: I think I think, Matt, you we all have tendency to conflate what what privacy means and here we're talking about two different aspects of privacy. I 100% agree with you that once group is free to join, right? And anybody can join, then it's unrealistic to expect any degree of content privacy in such group. And it's just dangerous to rely that there is a content privacy, because if you if you expect privacy but there is no privacy, then you may be saying something as if it is private conversation but like beyond thousand peop... that's, by the way, the basis of my scathing criticism of MLS specification, right? You know this message layer secrecy, I wrote...","offset":1080,"duration":41},{"text":"Host: I was gonna bring that up. By the way, it's not a surprise that you came out of publishing because your blog is one of the best blogs in tech to follow, by the way.","offset":1121,"duration":9},{"text":"Evgeny: Thank you.","offset":1130,"duration":1},{"text":"Host: But yeah, continue. You have a blog about MLS, which is what Signal wants to move to.","offset":1131,"duration":5},{"text":"Evgeny: Look, I think it's no, actually what Nostr what what was implemented on top of Nostr with White Noise is a different thing, right? Because they correctly identified the weak spot of MLS design and they completely side-stepped it because Nostr identity is the key so effectively authentication is bundled with identity. But that's a that's an I would even say it's almost like an edge case because in majority of systems people don't see key as identity, right? People don't are not hard-wired to to kind of equate identity to the key. I mean, Bitcoin community's very hard-wired to equate those things, right? Or just generally cryptocurrency community. But in normal world, identity is a name, right? And how do you know that this name...","offset":1136,"duration":41},{"text":"Host: Or a phone number.","offset":1177,"duration":1},{"text":"Evgeny: Exactly, so something secondary, something which is not cryptographically strong, and how do you equate this identity to something... so MLS MLS tries to solve the problem of key agreement in large groups, but it's kind of futile because it all depends on authentication service, which is still depends on provider, right? And the whole point of end-to-end encryption is to provide protect from provider. So effectively we need a trust to provider to protect from provider and to me it's like a logical impossibility. I only wrote this post because I was asked by like 20 different times members of our users were chasing me and asking me to explain why we're not adopting MLS at like after I explained it like 20 times I said all right, it's time I write something about this. So it's not like I had some kind of vested interest into into criticizing MLS. But the point is like once the group goes beyond thousands of members, there are two possibilities: it's a public group, it's publicly available and content is impossible to protect and there is no point trying in a strong to expect that it's protected.","offset":1178,"duration":61},{"text":"Evgeny: Another possibility: it's a corporate group, right? It's hosted on corporate servers, right? So however much we may all hate corporations, they exist, right? And if it's on their servers again, there's about protecting their servers and not end-to-end encryption.","offset":1239,"duration":14},{"text":"Host: Yeah, and to be clear here, Google has 190,000 employees, right? So you can easily imagine a 5,000 corporate group.","offset":1253,"duration":6},{"text":"Evgeny: Exactly, yeah, yeah. Exactly right, yes. So but why do they need MLS for this case, right? So they who are they who are they protecting it from, right? They they just need security of infrastructure, they need discipline, they need proper OpSec in Google, right? So they don't need MLS for that. So they may use it for some cases, but it's still it's still unclear why would they use it. So but reality the main thing about privacy is participation privacy I think, right? Because we've seen it all over and again that not only publishers are being like de-platformed, de-banked, high- fired from jobs, right? Or or worse, right? So like it doesn't matter that like the like if you're being dragged to court for whatever you said in public, right? It doesn't I mean, it's kind of great that legal system is not completely broken and eventually you are released without verdict, right? But the problem is that the whole process is the punishment, right? You're being dragged through interrogation, you're being dragged through court process, you have to waste money on lawyers, you have to engage with all that.","offset":1259,"duration":65},{"text":"Host: Time.","offset":1324,"duration":1},{"text":"Evgeny: Yeah, so so the process becomes the punishment, and that's the problem. So publishers kind of learned: if they publish something controversial, they have to do it behind a pseudonym, they have to do some reasonable OpSec to protect their identity, right? And and rather even if they say legal things, there are some strong and powerful people who don't like those legal things to be said, so they protect themselves. But their audiences may not do that, right? And we've already seen people in in various countries, it happens in some even European countries unfortunately, and it happens in in Russia, right? You like some thing and the next thing that happens...","offset":1325,"duration":37},{"text":"Host: You don't even comment on that.","offset":1362,"duration":2},{"text":"Evgeny: You don't even comment on that, you simply like something controversial and then you're being riddled with some fine for liking thing which in...","offset":1364,"duration":7},{"text":"Host: Or maybe you're not even liking it, I mean, we you can pull out this as an example... yeah, you're in a far- you're in a you're in a certain politician's Telegram channel and they're just taking a full list of who's in the group and using it against you.","offset":1371,"duration":10},{"text":"Evgeny: Exactly right, yes. And that's that's what's critically important. Privacy of participation is very... so so we currently live in a world when when some powers believe that they have to regulate not just what's being said, but also what's being listened to, and it's even more dangerous, right? So people want... and there is no law for that, right? There is no it's a completely outside of legal process, so it's completely outside of any precedent we've we've seen in history. So people reasonably want to protect their identities and they don't want to conflate their identities so the in Telegram if you follow 20 different channels then everybody knows all the channels you follow, right? There is a picture. The next thing that happens, you're branded as a conspiracy theorist and it's not the worst outcome.","offset":1381,"duration":43},{"text":"Evgeny: So and unfortunately Nostr has similar thing, right? So either I have to have a discipline and create multiple profiles, and it's just inconvenient, right? I have to think about it and I have to go through the hoops and like all the applications don't really make it simple to create alternative identities just for participating, right? So you end up just joining with the same identity and now everybody knows what what you're reading, what you're listening, what you're engaging with. So what SimpleX protocol achieves is that every time you join a community, it's a next set of keys, it's a next set of addresses, it's a next set of credentials, and your participation remains private.","offset":1424,"duration":44},{"text":"Host: If you want to. It's a new identity by default.","offset":1468,"duration":4}],"startTime":1080},{"title":"SimpleX Architecture: Addressing Connections","summary":"Evgeny dives into the technical innovation behind the SimpleX transport network. By assigning addresses to connections rather than endpoints, the protocol improves privacy and significantly reduces battery consumption.","entries":[{"text":"Evgeny: It's not even a new identity, network doesn't operate on a concept of identity. I think I think, Matt, let me explain. I think I think it's important to understand that we didn't really build one thing. People think that we build one thing, but even if you take our earliest white paper, like written in 2021, even before the business was started, so it says very clearly: so we build a network for delivering packets between applications because this is was the missing bit in the World Wide Web, right? I was web developer, I just wanted a channel on my website.","offset":1472,"duration":38},{"text":"Host: Right.","offset":1510,"duration":1},{"text":"Evgeny: Right, so how do you do it? You need a messaging protocol to achieve this. To do publishing you need messaging. So we created a transport network that allows to deliver packets between the endpoints. And this transport network today already used beyond SimpleX chat application. It's used by low-end devices, people experiment with IoT devices using SimpleX network. Uh one substantial distinction of this transport network was if you if you look at the internet, internet is a transport network. What internet does: it it has endpoints, like devices, right? And it deliver packets to the endpoints, right? And internet uses what's called endpoint addressing, right? Each network each endpoint is assigned an address, right?","offset":1511,"duration":45},{"text":"Evgeny: We flipped it upside down this design and we said all right, we're not going to assign addresses to endpoints for various reasons. It compromises their security, it also compromises their battery consumption because if you think about mobile devices, right? They don't have fixed address. They keep switching between networks, they are assigned dynamic addresses. So the problem that network initial internet was quite symmetric, right? All net point all endpoints had addresses, right? Fixed addresses. And now internet evolved to the point that some kind of nodes, we call servers, they have fixed address, but all other nodes and user devices, they don't have fixed address, they have variable addresses. And that makes addressing really hard, it makes asynchronous communication really hard, it makes all application really hard, because in order to receive messages you now have to poll, you have to go to the server and ask keep asking do I have messages, do I have messages, do I have messages? People believe that's how SimpleX network works, but that's not how it works. The problem with this asking is that you lose power every time you ask.","offset":1556,"duration":56},{"text":"Host: Right.","offset":1612,"duration":1},{"text":"Evgeny: So we said okay, what if we design transport network in a very different way and instead of assigning identities to the endpoint addresses, we assign identity addresses to connections between the endpoints. And that's how SimpleX network is built. We simply built a packet routing network when address is assigned to connections between endpoints. So every time you want to connect endpoints, you create a connector and slap an address on this connector, and that's it. That's all the innovation was about, just flip the addressing scheme upside down and instead of assigning addresses to endpoint... you said the audience is quite technical, so I hope I'm not going too deep, but you tell me if I'm going too deep. So that's that's the whole idea, right? Assign addresses to connectors between the endpoints. And it solves two problem. It solves problem of endpoint security because the second endpoint address is known to the network, it can be attacked, and it solves problem of power consumption because if endpoint cannot have fixed internet address, it becomes problematic how to connect.","offset":1613,"duration":65},{"text":"Evgeny: And what SimpleX nodes are is routers that route packets between endpoints. So endpoints use these routers or rooters however, depending on which country you are in I guess, so to to deliver packets between endpoints. That's what we built. And then we said all right, I have experience of building open-source applications and I know that if you build a component that's not used by end users, it's really hard to make it valuable, it's really hard to make it into a everyday business, it's hard to get adoption because you're effectively build technological cog in a large wheel and you have to convince people to use... I'm talking about my library for data validation, right? I built like starting from 2015, I built a JavaScript library that now has close to a billion downloads every month because it's used probably by like, I don't know, most JavaScript applications depend on it...","offset":1678,"duration":51},{"text":"Host: Which one?","offset":1729,"duration":1},{"text":"Evgeny: It is, right? It's it's one of the biggest used libraries because it's in a dependency chain of many applications, but most people don't know it exists because it's a it's a little cog well, not so little, it's a highly reliable cog in the wheel that's surviving AI-led attacks right now, people try to find highly reliable, it's been highly supported, used by lots of people. My kind of thinking when we designed this transport network is we'll have to build application in parallel, we we cannot just build transport network and hope that it somehow used, we have to build some application that uses this transport network.","offset":1730,"duration":36},{"text":"Host: You're proving the use case.","offset":1766,"duration":2},{"text":"Evgeny: Effectively. So we build SimpleX chat. And what is SimpleX chat? SimpleX chat is a peer-to-peer messenger that uses this transport network. And the fact that SimpleX chat doesn't need identities for the end users is a direct consequences of transport network not having endpoint addresses and instead having connector addresses. So and these two things have been evolving in parallel. They live in different code repositories, they obviously SimpleX chat application uses library provided by SimpleX network software, but for us it's always been like two things are evolving in parallel and try to make this whole ecosystem work but together, right? But and that's that's the foundation of technology we built.","offset":1768,"duration":53},{"text":"Host: That makes a lot of sense to me. I mean, so the dream is that you have that there'll be many different applications and use cases on top of this protocol, but SimpleX is the first one and it's paving the way and proving how it works and how how resilient it is, right?","offset":1821,"duration":19}],"startTime":1472},{"title":"SimpleX as an Application Platform","summary":"The discussion shifts to viewing SimpleX as a platform akin to a web browser. They explore exciting use cases like trust-minimized crypto swaps and interacting with AI chatbots over a secure transport layer.","entries":[{"text":"Evgeny: Correct. SimpleX yes, correct, yes. We see SimpleX chat platform also as potentially a platform for applications similar to a browser, right? We're already playing with the idea of adopting programming language that will enable to have widgets in a chat that have some custom interactivity, etc., etc. So SimpleX chat in itself is also like a platform you can develop on, and people already develop chatbots, right? So there was like I was very excited to see that guys from Unstoppable, you you know this Unstoppable wallet people probably, right? So they developed a chatbot that allows to do swaps via SimpleX chat chatbot.","offset":1840,"duration":38},{"text":"Host: Yeah.","offset":1878,"duration":1},{"text":"Evgeny: And the good thing is like you're doing swap without connecting to any server, without exposing your IP address, without sharing your transport information, you're effectively... yeah, there is it's not completely trustless, of course. Yes, you you trust some swap providers...","offset":1879,"duration":14},{"text":"Host: Right.","offset":1893,"duration":1},{"text":"Evgeny: But SimpleX chat itself is rather trustless, right? And you can...","offset":1894,"duration":4},{"text":"Host: The communication protocol is is trust-minimized.","offset":1898,"duration":4},{"text":"Evgeny: Yeah, and private. Yeah. So so we and I mean, it makes sense because I do think, you know, I think the truth is somewhere in the middle and there's a lot of hype, but I do think the UX of how people interact with a lot of these things is moving to like that AI chat interface. We're like going from we're going away from the world of point-and-click and more to the world of ask and get, you know, where you're like just asking an agent for something. And then it's the question becomes and we've seen it with the OpenCola movement, which is the fastest growing open-source project, end-user open-source project of all time, and everyone's using Telegram or Discord, centralized and not private at all, right?","offset":1902,"duration":50},{"text":"Evgeny: 100%. And I I I agree with you. You know I was a CTO at startup that was selling fashion via WhatsApp, right? To me, commerce moving to messaging environment, all interaction with services moving to messaging environment, was like inevitable future of technology because this whole kind of point-and-click interface, they requires a lot of like thinking about what to point and what to click, right? And sometimes just want to ask, and the the constraint was always an intelligence of or or like some ability to interpret our requests if they are said in plain language, right? And we certainly past the point when we can get very valuable responses from LLMs, right? But the problem now is that the whole kind of communication pipes around LLMs are extremely insecure. Not just LLM provider can read what we say, but like all the transport environment around it is not quite secure, plus we are not private with that. So I think I think what we're building can be an interesting transport layer for interacting with LLM models.","offset":1952,"duration":71},{"text":"Host: Yeah, I mean, you especially see it the commerce as messenger in the developing world. Like whenever I'm in Latin America, it's very obvious. Um and I mean, to tie it back to Bitcoin again, the number one way that people do p2p Bitcoin trades is through WhatsApp, is through existing messengers. Not through like application interfaces. They're going they're going into WhatsApp, they have their broker-dealer or whatever and they're just messaging them directly there and exchanging information.","offset":2023,"duration":33}],"startTime":1840},{"title":"Router Trust Model and Preventing Collusion","summary":"Evgeny outlines the minimal hardware requirements to run a SimpleX router. He explains how the protocol prevents servers from observing message contents or correlating IP addresses through multi-hop routing.","entries":[{"text":"Host: I uh so I want to pull it back for a second. The so the key here the the SimpleX servers, right? Anyone can run a SimpleX server. The they are they're routers, they're routing the communication between each other. Um how heavy is that burden and what trust is being put in the server by the users?","offset":2056,"duration":36},{"text":"Evgeny: The burden that router holds is very much dependent on the traffic. If you're just running a set of routers for a small group, you can have single core virtual machine with like half gigabyte of RAM or even less.","offset":2092,"duration":16},{"text":"Host: Super minimal.","offset":2108,"duration":2},{"text":"Evgeny: Yes, yes. It's it's extremely low uh resource consumption because all it does it receives a message. We our default implementation doesn't use any database layers. It can run on like it's just single executable that keeps the state in memory with a fall-back state in a append-only logs, so effectively it wouldn't lose the connections even on hard reset. It may lose some messages on hard reset, but if it if it terminates normally, it wouldn't lose any messages, it will persist them on stop. So we don't we don't run these in memory servers anymore for those that are processing up, we use Postgres uh database for that and we know quite a few people who migrated to Postgres database as well who run them in their companies or in their working groups, so they use use those routers with with Postgres database with high traffic. It's more efficient, but still we're talking about relatively low power uh machines or virtual environments that can transform millions of messages.","offset":2110,"duration":68},{"text":"Host: So I'm just trying to like I'm trying to key in here on what you perceive as... yeah, go on.","offset":2178,"duration":8},{"text":"Evgeny: You said you asked the second question was trust, right? The level of trust.","offset":2186,"duration":3},{"text":"Host: Yes.","offset":2189,"duration":2},{"text":"Evgeny: I think I think we probably thanks to our advisor, we have been very explicit about trust model. It's in our white paper. So servers obviously can routers disrupt communications, right? So we trust routers not to do it. But what they cannot do is important: they cannot compromise end-to-end encryption because they do not participate in key exchange, key exchange happens out-of-band. They cannot drop messages undetectably, they cannot insert messages undetectably. So the best the server can do is just delay communications or like send lots of spam traffic to the end-user device.","offset":2191,"duration":45},{"text":"Host: It's like reliability and uptime is the trust basically, right?","offset":2236,"duration":5},{"text":"Evgeny: Yes, yes, effectively yeah. And with server with the routers that we run we had very we had no much problem, right? I had like very funny situation when somebody who I connected like on a day of the first mobile app launch for years ago, recently messaged me and said hello, I said okay this is like four years ago, the connection somehow survived through all this time. So yes, so we we aim to minimize the trust and also if initial design had a single router in a message passing chain and obviously even though on a SimpleX protocol layer servers don't have identities there is IP protocol layer, right? And if server can if router can observe IP address of one party and IP address of another party...","offset":2241,"duration":46},{"text":"Host: My next question. Yep.","offset":2287,"duration":3},{"text":"Evgeny: Then they can see who talks to home. So on IP address level, right? So we changed the routing protocol so now messages are passed always through two routers, so even though the first router in a message passing path... okay, so each conversation we use four routers, right? When I say two routers, it's a one-way communication, right?","offset":2290,"duration":19},{"text":"Host: Okay.","offset":2309,"duration":2},{"text":"Evgeny: So I can be messaging you through one router and using anour another router to connects to yours, and when you're replying, you also would be using two routers. So effectively you choose the routers to receive messages from and I choose the routers to forward the messages to your router.","offset":2311,"duration":18},{"text":"Host: And they would all have to collude to connect the IP addresses.","offset":2329,"duration":3},{"text":"Evgeny: It's really hard, yes. They'll have to and it's really hard because it means they'll have to do some coordinated protocol changes and introduce some additional metadata in the message envelopes. So I would say it's not impossible, of course, if routers collude they can do timing correlation and compare those things. But the technical bar is quite high. And the clients are already programmed to use router not just different routers but routers of different operators. We introduced the concept of router operator, app understands that, and it will already has two preset operators right now, there will be more, so and if you add your routers then there will be third operator. So app knows this concept of not just router but of router operator and it chooses different operators, so different entities.","offset":2332,"duration":70},{"text":"Evgeny: That was my biggest criticism of Tor by the way, because Tor network is built on the idea that you choose three relays on on a packet passing path, right? But you don't control the relay choice, or you have limited control of relay choice, right? And we know that there are large entities operating those relays on Tor network, right? And we know that there are entities who sell traffic data as well, so effectively this whole kind of idea that different servers, different relays means that they don't collude is kind of questionable, right?","offset":2402,"duration":32},{"text":"Host: Right. the whole model is based on at least one honest actor in the route, but if it's all the same actor, then the the assumption breaks down.","offset":2434,"duration":8},{"text":"Evgeny: Exactly, yeah, and given that you have limited control of those again, there are some advanced settings, but by default you don't choose and it means that it means that you potentially don't don't have privacy of of the circuit. I think it's important thing for SimpleX protocols like if you compare with Tor, right? On Tor you create a persistent circuit. So you build a circuit and then all the packets come through this circuit and then this circuit can see all the packets on they understand they all understand that's the same circuit, it's persistent circuit, right? Uh so even though like for example it's a session design, right? So you may message different people through this network, but uh who the the server that receives your messages would know that they come from the same person, because they come through the same circuit. And you understand, right? Like because the session is the same, different packets come out of the same session, it means that you know at least that it's the same person communicating all these different contacts, right? With SimpleX network we designed it differently, we do the same as mixnet do, effectively there's no circuit, there is a packet level anonymity and the recipient router it doesn't know whether packets come from the same session or from different session, so it only knows that they come to different recipients, right? And the forwarding router again it doesn't know how many addresses would be because there is end-to-end encryption between sender and the receiving router, going deeper into technical details. So effectively they cannot establish who talks to home on a cryptographic level because the each each packet is anonymous in this message passing.","offset":2442,"duration":110}],"startTime":2056},{"title":"The Discovery Problem","summary":"The host asks how users find and connect with each other without centralized identifiers like phone numbers. Evgeny explains the use of QR codes and encrypted, out-of-band links to establish connections seamlessly.","entries":[{"text":"Host: That's awesome. Yeah, makes collusion significantly more difficult by default, which is key because defaults are what matter, most people are not going to actually be changing things. How do you how do you handle the like the discovery problem? And by discovery problem I mean it can mean a bunch of different things. What I mean is: you message me and I'm connected to a different router than you are. How does the path get determined? Like how does it how does it get to me? Right? You know what I mean?","offset":2552,"duration":107},{"text":"Evgeny: Your address, you publish an address, right? So we don't have have anything in the protocol or in the app to help me discover your address. That's the future uh...","offset":2659,"duration":12},{"text":"Host: That's that's a separate discovery problem, that's not what I'm talking about here. You went to my website and there was a there was my my address was there. So we just used a traditional website for that part of the discovery problem.","offset":2671,"duration":14},{"text":"Evgeny: Correct. The address... the way it works now, the way it worked before, the address itself contained the router address.","offset":2685,"duration":8},{"text":"Host: Okay.","offset":2693,"duration":1},{"text":"Evgeny: The way it works now, the address contains a a reference to an encrypted piece of data which contains the reference to the address which I have to message. So the address itself cryptographically bound to the point I have to forward my messages to. So your your router is determined by your address, and the router I choose to forward messages to this address packets is randomly chosen from my configuration from my client configuration. So my client says, okay, I will choose any router, but it will try to use router of another operator than you use.","offset":2694,"duration":40},{"text":"Host: Right.","offset":2734,"duration":1},{"text":"Evgeny: And when I send the first message to your address, when the client sends the first message, it includes the reply address end-to-end encrypted.","offset":2735,"duration":29},{"text":"Host: Got it. So it gives you a discovery path basically to get...","offset":2764,"duration":4},{"text":"Evgeny: Yeah, yeah, your client learns where it can reach me. When I message you, it's all it's all works rather seamlessly and on a technical level discovery is not a problem. Obviously, the whole idea is like for for us, right? We have a support team member who answers users' request. The most common request is how do I connect to people? Like where do I where do I type the name? Where do I type the phone number? How the hell like how is it even working, right? So the whole idea that you have to create a link and then share the link with somebody else in order to connect is is alien to absolute majority of people. We're doing a lot of redesign of this initial connecting experience right now to to make it easier to understand. We don't change anything in...","offset":2768,"duration":39},{"text":"Host: I will say the in-person is more intuitive than not because in-person you just scan a QR code boom.","offset":2807,"duration":6},{"text":"Evgeny: Yes, yes, yes, yes. But that was like literally version one of the app had nothing else, right? It you could scan a QR code and you could start sending text messages, that was what we released four years ago.","offset":2813,"duration":15}],"startTime":2552},{"title":"Scaling Encrypted Groups and Channels","summary":"Evgeny explains how the double ratchet protocol successfully scales for medium-sized groups. For massive broadcast groups, he introduces the concept of chat relays that efficiently rebroadcast messages.","entries":[{"text":"Host: But yeah, that makes sense to me. Okay, so one of the things that MLS does attempt to solve is uh is this idea of groups scaling poorly in encrypted chat. So a lot of times the most basic and you know you can correct me where I'm wrong here, my most basic interpretation of how standard encrypted group chats work, whether it's Signal or Matrix or any of the existing ones, is I'm basically if there's 50 people in the group I'm sending 50 individual encrypted messages every time I'm sending a group text, but the UI is making it look like it's just one message in a group text. But in the background what's really happening is every message has to be sent to every group member and private you know encrypted separately. My understanding is part of the MLS spec is trying to solve that scaling limitation because maybe it works at like 20 people, maybe it works at 50, but once you get to like 2,000, 5,000 people, it's insane, you're like basically DDOSing each other. Um and then the servers would obviously have a lot more overhead attached to them. So how are you thinking about that? Is that a real limitation? Is that and how are you mitigating it?","offset":2828,"duration":82},{"text":"Evgeny: Okay, so there are several questions, I'll try to answer all of them. So first, let's not that's not that's not exactly how Signal works, right? You're not sending messages to each member. What you do is you generate a random key for this message, and then you encrypt the key itself for 50 people, but the message is encrypted only once. So for example if your message is like 200 characters, but your key is rather small, you don't need to send message 50 times and you don't need to send message to 50 people in Signal. You encrypt message with the same key and then you encrypt key with different...","offset":2910,"duration":26},{"text":"Evgeny: I think realistically, to me, pairwise ratchets, like pairwise double ratchet, so for each member you encrypt separate key, it scales to quite large numbers. It scales reasonably well to even 5,000 recipients, and that's how we see large groups with end-to-end encryption in future. Not MLS spec, but effectively what Signal does. So Signal works... Signal limited it with 1,000 because they have like tens of millions of users and some of them are on really bad internet and they don't want to have and very low power devices, so they don't want to go beyond 1,000 with end-to-end encrypted groups. But I think even 5, 10,000 is a tractable approach if you only encrypt keys and not the whole message. But beyond that it's just like, it feels like you're not... you cannot remember 10,000 people. You don't know who's in a groups, you don't know who reads it, like what's the point of end-to-end encryption?","offset":2936,"duration":61},{"text":"Host: Right. So then we're moving into the channels, right?","offset":2997,"duration":2},{"text":"Evgeny: Yeah, effectively.","offset":2999,"duration":1},{"text":"Host: So then how are you envisioning the channels set up and what does that... what does that look like in practice?","offset":3000,"duration":6},{"text":"Evgeny: From user experience point of view, you just it works in a same way. You scan the link, you join the channel, you start receiving messages. The difference is that if you have right to send messages to the channel, then instead of sending it to whatever number of subscribers—1, 10, 1,000, 50,000 subscribers—you send it only to chat relays and they do rebroadcast.","offset":3006,"duration":25},{"text":"Host: The server.","offset":3031,"duration":1},{"text":"Evgeny: It is not exactly the server. It is again, it's some sort of a message... it uses client-side technology because you are not connecting to this chat relay over the internet. Effectively chat relay is a messaging client that cosplays or roleplays as a server, right? That is a router, right? So it receives your message as a SimpleX client, right? And it has... it's a special kind of client because you're never connecting to it directly. You don't know its IP address, you don't you only have its SimpleX address, forwards your messages through SimpleX network. You connect to it via SimpleX network and it forwards the messages to SimpleX network. So unlike Nostr relays, you never build direct internet connection to this relay.","offset":3032,"duration":47}],"startTime":2828},{"title":"Verifiability vs. Plausible Deniability","summary":"The speakers debate the trade-offs between verifiable cryptographic signatures and plausible deniability (repudiation). They discuss why preserving the deniability of private conversations is paramount, even in the age of AI deepfakes.","entries":[{"text":"Host: Okay, I mean to help me understand, maybe it's more helpful because if I don't understand it then it's less likely other people understand it. Let's say, I don't know, some politician wants to has a 100,000 person channel, right? Wants to broadcast to his audience 100,000 people big. What does that look like? Is he running his own chat server and who's running the chat relays and how does that all fit together?","offset":3079,"duration":31},{"text":"Evgeny: It's not different from who runs SimpleX network routers. It can be... there will be some chat relays that run by third parties pre-installed in the app. He can run his own. And each channel can have multiple. Our idea is that you want more than one chat relay in each channel for redundancy, for censorship resistance, for mitigating any trust issues. So the way we designed the protocol and already implements it is that some critical messages are signed by senders so they cannot be faked. Most messages are not signed, but they are kind of delivered redundantly and recipient clients can simply see if some relay decides to invent messages or change messages or... so we've like, that's in case they are not end-to-end encrypted, right? We're talking about public channels at this point.","offset":3110,"duration":53},{"text":"Host: Right. The big thing with public channels is not is not necessarily encryption of the content. It's verifiability of the content that it hasn't been changed in transit and privacy of the participants. Correct?","offset":3163,"duration":15},{"text":"Evgeny: Correct, yes. And end-to-end encryption between this relay and the participant helps privacy, right? Because there is end-to-end encryption between relay and participant all the traffic information is not uniform so transport network cannot observe the content, it cannot correlate the content, it cannot understand which groups you are receiving content from for the same reason it's end-to-end encrypted. So end-to-end encrypted and end-to-end between these broadcasting relay and the members helps privacy of the members. Because without end-to-end encryption transport network could see content, right? And if transport network could see content they know what you're reading, right? So this end-to-end encryption is very important to provide participation privacy.","offset":3178,"duration":51},{"text":"Host: Right, and then the members are known.","offset":3229,"duration":2},{"text":"Evgeny: Exactly, yeah. But and with end-to-end encryption transport network can see nothing, and chat relays don't see your IP address so they kind of protect you from each other.","offset":3231,"duration":11},{"text":"Host: And then from the... what why aren't all you mentioned so the broadcaster, let's call him the broadcaster in this in this scenario, the guy who owns the channel that's sending out the messages to people. You said every message isn't signed. Why isn't every message signed? Is it a is it an efficiency thing or...","offset":3242,"duration":23},{"text":"Evgeny: No, there is no cost in signing messages, but it's always a double-edged sword, right? So like one of the qualities in communication is deniability, right? So the double ratchet protocol has this quality called repudiation, which means that it's not possible to prove to a third party that you actually ever sent this message because the message is is encrypted by the key that the recipient also possesses. The second you start signing the message you're effectively putting your signature on the message saying \"I actually said that\" so you lose the deniability.","offset":3265,"duration":40},{"text":"Host: Because it's verifiable.","offset":3305,"duration":2},{"text":"Evgeny: Yeah, it's not just it's not just verifiable it's also non-repudiable. So you cannot no longer say \"I've no idea where this message come from, I never sent it\" like...","offset":3307,"duration":11},{"text":"Host: We see that issue with a separate rabbit hole that I've dove down in the past, which is the idea of of of more modern voting techniques that would involve a signed receipt, and that issue there is you could have an employer or a husband or a government come to you and be able to with with no doubt whatsoever know how you voted and then pressure you accordingly. Because on the surface it seems like such a great idea. It's like, oh, I should have a verifiable receipt so I can make sure they're not faking the votes. But then all of a sudden you realize why votes are supposed to be private in democracies.","offset":3318,"duration":40},{"text":"Evgeny: Exactly right. So we we effectively saying \"okay so some critical like for example if the command you are sending to chat relay is to remove a member it should be signed, right? because the consequences of of relay removing a member are irreversible so you have or for example you say I want to delete a channel, right? This action requires your signature because it's irreversible and it's destructive, right? So everything irreversible and destructive we add signature by default as a requirement and receiving clients will simply refuse to process the message if it's not properly signed. And your key is cryptographically bound to the channel link. So this is like we we build this whole kind of cryptographic trust chain with the channel owner that when the member when the subscriber just joins your channel they already get the key from the link, it cannot be faked, so effectively they know your credentials for this channel from the get-go from them joining, right? Relays can't fake it.","offset":3358,"duration":66},{"text":"Host: And they have that locally.","offset":3424,"duration":1},{"text":"Evgeny: Exactly, yeah. But for messages we want to make it an opt-in. If you really want to sign important messages then maybe we would provide it as as an option or as a feature, but we I believe it's wrong to make it a default. Because think about that. Let's say you already have five relays in a group, right? These five relays are operated by different entities, right? If one of them decides to substitute the message the recipient client will see it and say \"wait what's going on here?\" right? \"So there is some kind of trust violation here.\" Four said one thing and one said a different thing. Exactly. And I think it's actually better than signature because that gives them similar degree of trust right probability of four relays colluding if they are run by different parties, right, is low. Right? And especially if the politician himself runs the relay, right? So then then what's the chances of it being replaced? But at the same time the message cannot be used as you said as a signed receipt which kind of which can be used as a proof of of doing that, right? So like it...","offset":3425,"duration":74},{"text":"Host: That kind of makes sense to me. It it still solves the main underlying problem which I think is going to become a bigger concern is as digital communications become the main way people digest information, there are serious real-world consequences on what influential people say and we've seen this. Trump sends out a Truth Social post and military is moved and markets react and meanwhile there's zero way for me to know that Trump actually sent the Truth Social post, right? There's a bunch of men in the middle that could can fake that. And we haven't seen a large-scale repercussion yet of that type of attack, but I assume it's going to happen sooner rather than later and so it's important that there is at least some level of verifiability or trust here, and I see how you're kind of trying to there's trade-offs on both sides.","offset":3499,"duration":65},{"text":"Evgeny: Exactly. You know there is a value in being able to sign important messages 100%. But I believe it's wrong to make it default and rather than opt-in because like, okay, so we are like imagine this situation, right? You talk to me and we record this conversation people can listen it and obviously nobody of us can deny that this conversation happened, right? Imagine a different situation, we meet in a cafe we have a private conversation we really don't want this conversation to be public, right? Who knows what we may be discussing, right? It doesn't necessarily we're conspiring we can be just having a private conversation about our lives, right? And if any one later quotes that \"he said that\" it's unprovable. We have we have plausible deniability. Now imagine if it happens in encrypted messenger. If you use Signal you also have plausible deniability because or SimpleX because messages even though are end-to-end encrypted they are repudiable. So there is no way to prove that you actually sent this message. And we haven't seen what I hear the criticism I hear from technologists is that nobody has ever used this concept in courts, it has no legal standing and so on and so on, right? But reality is Signal is the first widely used messenger that pioneered repudiation as a as a cryptographic quality in message sending, and it only happened like 10 years ago.","offset":3564,"duration":97},{"text":"Host: Right.","offset":3661,"duration":1},{"text":"Evgeny: And before anything becomes understood by legal systems we usually observe like many many of decades of not understanding what it is and how it can be used and what legal consequences of this is. So yes, there I don't know any precedence of this concept being used but it doesn't mean it's not valuable potentially. So we we like to stick with repudiation as a cryptographic quality of the protocol.","offset":3662,"duration":28},{"text":"Host: Yeah, I mean it's it's the difference between like building the technical foundations versus real-world repercussions and the real-world repercussions always happen later. I mean this is the first administration that I know of where we've seen official business happen on Signal and there was that leak of that group chat, right? And I'm sure a bunch of those group members are grateful that at least they can technically say that they didn't send a message in there whether anyone believes that they didn't send the message is a different thing because you kind of have to modify some things in Signal to do that.","offset":3690,"duration":41},{"text":"Evgeny: Yes.","offset":3731,"duration":1},{"text":"Host: I mean and to your earlier point about different types of conversations I mean this is a perfect example right because we had a conversation on SimpleX that was off the record and then this one I will be hashing and signing with my Nostr key because as someone who has spent a lot of time broadcasting my thoughts and having candid conversations like this on the podcast it does frighten me that we could have AI deepfakes and basically me saying anything without no verifiability. So I really take that verifiability piece very seriously when it comes to these types of conversations. Like I want there to be for this conversation I want there to be a historical record of truth that if some AI in 5 years makes us say whatever it wants us to make us say you can go back and see that hash-signed version of the MP3 and know that it hasn't been changed and that's what was originally said, right?","offset":3732,"duration":67},{"text":"Evgeny: Yes.","offset":3799,"duration":1}],"startTime":3079},{"title":"Incentivizing Node Operators","summary":"The host asks about scaling the decentralized network. Evgeny notes that for privacy to reach the mass market, the network must offer financial incentives so that commercial operators can profitably run infrastructure.","entries":[{"text":"Host: Okay, this is all fascinating to me. I'm really enjoying this conversation. Uh, the the big one that will come up next is, which I mean I see all the time in distributed systems, is okay, so the system relies on people running servers and relays and whatnot. Ideally the system works best when there's many many operators doing that. And this is something that Tor for instance, I think on a widespread scale, has had a lot of issues with, right? Having more independent operators running these things. Bitcoin we've as it's a it's a major contention point on Bitcoin making sure that Bitcoin nodes are easy and accessible to run so people can use it without relying on a trusted third party. We see it in Nostr with relays. So how are you thinking about this like fundamental problem, right? Which is you need as many people running servers as possible. More the better, the more the better servers and so how do you see that scaling?","offset":3800,"duration":71},{"text":"Evgeny: Right now we see lots of communities running their own routers in SimpleX network. It's I think there are some Bitcoin communities, I think there are some Monero communities that do. There are some discussion groups that run around servers they advertise it on their website. We we cannot know exact number but I think conservatively there are over 1,000 routers in SimpleX network at this point. So and that's fine and it works and people get their own sovereignty and autonomy and independence of anything that that we may be doing or anybody else can be doing which is great. The downside of this model is that your your router because it has fixed endpoint address, right? Like the whole point of SimpleX network is protect your endpoint address, right? But if you run a router this router becomes effectively your address, right? So like if if if it... if it if it is run on public network then obviously anybody knows the IP address they somehow can link it to your identity and maybe that's not what everybody wants. If you run it on Tor then it's potentially not very usable. Even though we build internet-to-Tor routing capabilities. So for example if you send messages to Tor router it will be delivered even if you don't use Tor because SimpleX routers would they can they can connect to Tor routers. Right? So even if a router is only on Tor network then SimpleX router that has internet address will be able to forward message to Tor network. That's how that's why network remains interconnected, right? So you don't have to use Tor to deliver messages to Tor-only routers. And it's all great. But I think long-term this is not really scaling because I don't know you probably seen Moxie Marlinspike Marlinspike said once that people don't want to run their own infrastructure.","offset":3871,"duration":110},{"text":"Host: Yeah, the founder of Signal.","offset":3981,"duration":2},{"text":"Evgeny: Yes, yes. So my my view was always if we want privacy to be a norm then we have to be building technology that everybody can use, right? People who don't want to run their own server, people who don't want to think, who want to use just default software out of the box and get this privacy. And that's the only way it can be normalized, right? And I think it kind of resonates with what Cypherpunk manifesto author was writing later, right? So for just writing code is not enough. It was his later letter not the manifesto. That we have to have acceptance in the society, we have to have wide usage of those technologies. We effectively see adoption as a as a privacy feature. So so this whole idea is that in order to be autonomous you have to run the server it it is not it is not it is not scaling to the future. So so that's why we want to build a network when hundreds of commercially incentivized operators can run routers and be making more money from doing that from the network than they are spending money running this infrastructure. Bitcoin obviously has in-built monetization solution, right? You run the node it potentially can mine Bitcoin and it kind of at least covers the cost of operation.","offset":3983,"duration":86},{"text":"Host: Well, we kind of lost that to be honest. I mean most nodes are not mining nodes now.","offset":4069,"duration":5},{"text":"Evgeny: Yes, I understand that yeah, but at least you get indirect benefit that you can you can use the network without trust which is kind of what we're holding on to at this point. And then also if you hold the money the money tends to increase with purchasing power so we have that going for us.","offset":4074,"duration":18},{"text":"Evgeny: I'm I'm not quite I've I've seen some talk a couple years ago at a conference when somebody was talking about running Bitcoin miner at home and his idea was that \"okay, we can't make profit from running the miner but we can convert electricity costs to non-KYC Bitcoin and it's a great thing and let's do that.\" Right? So effectively you're...","offset":4092,"duration":22},{"text":"Host: No, we do have that aspect going well for us. And there actually is a company called Futurebit that like puts the node and the miner together in one convenient package that you can run at home. But a lot of those miners just to be clear here, and it's, you know, it's kind of a tangent it doesn't really matter that much for our conversation, a lot of those miners are they have the heater in their home but then they're connecting to someone else's node, right? So it's not their node they're not running the actual node infrastructure. More are, which is awesome to see. But yeah, fair enough.","offset":4114,"duration":90},{"text":"Evgeny: So for for SimpleX network we see the imperative to create a commercial model when anybody who wants to provide infrastructure can make more money from providing this infrastructure than running this infrastructure cost.","offset":4204,"duration":15},{"text":"Host: A financial incentive.","offset":4219,"duration":1}],"startTime":3800},{"title":"Monetization: Subsidizing the Network","summary":"Evgeny outlines SimpleX's revenue model, which mirrors web hosting. Large broadcast channels will pay for infrastructure and discovery, subsidizing the network so that standard messaging remains free.","entries":[{"text":"Evgeny: Yes, 100%. And we don't want to create any blockchains to do it. We don't want to do any mining operation. we don't want to create any... but we still need a solution and we've been discussing it with the community for quite some time. So the idea is that to answer how servers are paid we have to answer first the question is what what in the network itself is paid, right? When we were just starting developing this we were thinking okay maybe some premium features can do that maybe something else can do that, right? But then we've seen what happens with Telegram Premium. We keep talking about Telegram, right? To me Telegram...","offset":4220,"duration":33},{"text":"Host: Everyone's favorite.","offset":4253,"duration":1},{"text":"Evgeny: To me Telegram Premium is is a proof that premium model for messaging application is a dead end. Because yes you may be generating revenues and yes you may be developing the nice features but reality what happens is you're fragmenting your network, right? You very quickly as a provider of this application realize that in order to make profit you have to make your application unusable.","offset":4254,"duration":24},{"text":"Host: Yeah, the best features need to be behind the paywall basically.","offset":4278,"duration":3},{"text":"Evgeny: Uh pretty much all of them. So you already there already features when I can't message people until I have or I can't make call to this people and it's just like not because they choose to but it's just like it's just fun, right? So and to me that's kind of very much a dead end for communication network. Imagine like a web browser, right? We what we built we take lots of inspirations from the web. We we say often that what we built is a missing part of the web, the messaging part. We say a next web, right? Because web has never created messaging solution as part of it. So if you look at the web, how web is monetized? Users don't pay for the browsers, right? At all, at all. Users don't pay for using the web, at all. Uh, people may say \"oh yes we pay ISPs\" but it's different story. ISP is not the web, right? It's simply a transport network that connects you to the website. But the web itself like all the DNS systems, all the infrastructure that allows web to function, it's free, right? So who pays for all that? The answer is very simple: websites pay. People who want to host the websites they pay and because every content distribution network has this distribution when 5% of websites generate 90% of traffic.","offset":4281,"duration":77},{"text":"Host: Right.","offset":4358,"duration":1},{"text":"Evgeny: What it actually means is that it's enough to charge this 5% of websites and everybody else can be free. Right? You don't need to pay to host a small website today, right? You just go you create account you can pay either $1 a month or nothing or...","offset":4359,"duration":16},{"text":"Host: Right, it's subsidized by the big guys.","offset":4375,"duration":2},{"text":"Evgeny: Exactly, yeah. So the whole web is subsidized by the big websites, so 5% of websites create all the carry or maybe 20% of the websites carry all the costs of the web. And that's why we see channels as so important because we see channel on SimpleX network as equivalent of the website. And we believe as this part of the network grows, the the traffic distribution, the cost distribution will be similar. So uh, 10% of large channels will generate 90% of the traffic. Right? And that's who they should that's who should be paying. And they'll be paying, right? because if you say \"I'm a politician I want 100,000 100,000 people audience,\" right?","offset":4377,"duration":31},{"text":"Host: Yeah.","offset":4408,"duration":1},{"text":"Evgeny: If your choice is to be on the platform that can shut you down because the current administration doesn't like what you say, right? We've just seen it happening with Trump before.","offset":4409,"duration":12},{"text":"Host: Yep.","offset":4421,"duration":1},{"text":"Evgeny: Right, so before Twitter acquisition before...","offset":4422,"duration":3},{"text":"Host: Sitting President of the United States gets banned from Twitter and Facebook.","offset":4425,"duration":4},{"text":"Evgeny: Which is ridiculous, right? So and one of the...","offset":4429,"duration":2},{"text":"Host: And he ended up buying and building his own social media network.","offset":4431,"duration":4},{"text":"Evgeny: Exactly, yes. So what what we see is a much cheaper solution. So if you want a channel that's sovereign, that you actually own, you have to pay for it. You have to cover infrastructure costs, you have to cover discovery costs, you have to cover some costs. And that's the business model that we see for the whole SimpleX network. So messaging will remains free forever as a as a add-on service effectively, and small channels and communities can exist for free, but large channels and communities carry the whole cost. And we just need to find a solution that allows to transfer value from those channel owners to the infrastructure owners in a way that kind of preserves privacy and security of all all participants within within what's possible. So so that's our view. So our view is not... our view for the network is not that it's enthusiast-run network, but it's a professionally run network, but it's run by so many independent facility and infrastructure providers that trust is minimal because it's distributed, right? If each conversation you uses four different companies, right? And those companies are rotated on a weekly basis then your dependence on each particular company is extremely low. They get profits from doing that but they have no control over your conversation.","offset":4435,"duration":85}],"startTime":4220},{"title":"For-Profit vs. Non-Profit Models","summary":"They discuss the controversies and benefits of taking venture capital for open-source projects. Evgeny argues that non-profits are often captured by their donors and that independent, for-profit businesses can scale more effectively.","entries":[{"text":"Host: I love that. I mean look, I love from I wear two different hats. I wear my charity hat with OpenSats and I wear my for-profit hat with 1031 where we invest in for-profit businesses that are often built on top of open-source stacks. And so I see both both worlds in the greater open-source movement, the foundation-led, charity-led and then, you know, and then the opposite side, which is the for-profit-led. And oftentimes you see foundations get spun up and run donationware. I mean we've seen that with Signal is probably the best example. And it's probably the easier path for these type of things in the short term. I think long term they scale much worse. Uh, they're not sustainable. You have to go out and constantly seek donations. And the incentives aren't necessarily aligned that well. I think one of the issues you start to see is longer term it's like, okay, the employees or the stakeholders of the foundation don't necessarily need to see the thing grow significantly. And the reality is in the truth is in the reality, which is Signal is probably one of the most successful nonprofit privacy, freedom-focused projects and it's found massive success but it's at about 100 million users, maybe less. And then you have things like WhatsApp that are in, you know, 3 billion plus, you have Telegram that's 2 billion plus. And those are for-profit ventures. and I don't think it's a coincidence that those for-profit ventures tend to have significantly bigger user bases. I think it's an incentive alignment thing. So I do I have a lot of respect that you've tried you're trying to go this for-profit ethical for-profit sustainable approach. And I kind of want to dive a little bit deeper in here.","offset":4520,"duration":105},{"text":"Evgeny: Look, I think I think the challenge is that I I I can go philosophical here, Frank. I think it all comes from people seeing most choices as binary.","offset":4625,"duration":10},{"text":"Host: Right.","offset":4635,"duration":1},{"text":"Evgeny: So I have heard this in my life million times: you have to pick a lane. Right? And I refuse to pick a lane. Right? When I was building my you know, I was building like I will go again to this library that nobody knows about but it's a good example because when I was starting this library there was like 12 different competing libraries and they all were either super fast and really badly complying with the specification, or very very slow and somewhat better complying with specification. So I said, alright, how how about I just build one library that is fastest and also best in compliance with the specification? And everybody was laughing at me saying \"this is the classic also XKCD comic, right? There are 14 better frameworks, let's make one more framework.\"","offset":4636,"duration":45},{"text":"Host: Here was the 15th.","offset":4681,"duration":1},{"text":"Evgeny: Now we have 15 better frameworks. Like I was sent this comic by like 10 different people in my life. Right? But reality what I learned from this kind of retrospectively again, right? So if you refuse to compromise on important trade-off, because trade-off is artificial, right? The choice between fast and standard-compliant wasn't the real choice. It was just easy path, right? It's just harder to build something that is both fast and standard-compliant, but it's not impossible. So I built a library that came to be the only library that people use today for data validation in JavaScript world because the choice was eliminated. And again, same between like private messenger versus convenient messenger, right? So people have been trying to pigeonhole what we're building into like like some people say \"oh you're building a private messenger you shouldn't worry about convenience really you should add more privacy features,\" right? That's half of our user base what says. And some other half of user base says \"you're focusing on privacy too much you should compromise on privacy...\"","offset":4682,"duration":62},{"text":"Host: It's not convenient enough.","offset":4744,"duration":2},{"text":"Evgeny: Yeah, and instead like for example the fact how you discover people some of the hurdles, or for example that we still don't have multi-device in the messenger. I say, whatever, compromise on privacy build multi-device everybody wants multi-device. I don't know, I think my brain is wired against making such compromises and we instead find proper solution that deliver both without compromise. And it's obviously slower. The the downside is like what you compromise on is time to to working product. That's that's what have to go, right? But I think reality is by taking this slow... right, I mean...","offset":4746,"duration":33},{"text":"Host: Yeah.","offset":4779,"duration":1},{"text":"Evgeny: Signal's the perfect example here, right? Because the easy path was saying, \"okay, let's just use phone numbers as discovery.\" That's what WhatsApp does, that's what Telegram does, we can do that, my grandmother can use it. And then you're stuck.","offset":4780,"duration":14},{"text":"Host: Yeah.","offset":4794,"duration":1},{"text":"Evgeny: You took the easy path and then you're stuck with that building block. Exactly, yes. It's not something that you can revise later, it becomes a foundation of your architecture. It's used everywhere, it's pervasive, it's not removable. So I think what we're trying to build is a communication protocol and product and transport network that's used by everybody. And yeah, it may take decades to get there, but I I still have time. So and talking about private like for-profit versus non-profit, going back to your question, right? I also see it as a false trade-off, right? I was when we took venture capital money, we took it like without any control provisions. It's a proper Y Combinator SAFE agreement, there are no board seats, no control, right? I have to chase my investors for advice and they are very busy people, right? But reality is we run our business however we want. And they just trust because, you know, I think venture capital has changed dramatically after some major successes when most venture capitalists arrived to conclusion that they have to let founders do things they disagree with. Because that's the only way founders... I mean Facebook was a big one. I mean obviously it's kind of a weird example to use here because they turned into one of the most evil companies.","offset":4795,"duration":74},{"text":"Evgeny: Yes.","offset":4869,"duration":1},{"text":"Host: But Facebook early days was, \"we trust,\" you know, the investors were like, \"we trust Mark, Mark is the leader of the ship, we're not going to take any control.\" But before that historically it was like VCs would come in and they would just take full control of a company and then push the founder out.","offset":4870,"duration":16},{"text":"Evgeny: Yeah, Apple would be a classic example, right? And in this pushing the founder out pushed the Apple to the brink of bankruptcy so they had to bring the founder back, right? So so yeah, so we see world has changed. investment doesn't mean control. And yet we've been like vilified by everybody like that we did it, right? So I had to write a blog post.","offset":4886,"duration":20},{"text":"Host: For-profit capital.","offset":4906,"duration":2},{"text":"Evgeny: Yeah, I had to write a blog post about why privacy becoming a norm requires venture funding. Because to me, privacy becoming a norm requires building a mass-market, widely adopted product. The problem with this premise is that it is the costs are exponential. It's like getting like 10x more adoption is not necessarily... you know what I mean, right? So you simply cannot build a mass-market, widely adopted product on a grassroot movement. And that's what Signal observes, right? Foundation model doesn't scale, donation model doesn't scale. So either you build at some point the model that allows it to be a business that generates profit, right? And again when people say \"oh you're for-profit company it's a bad thing,\" my response was always like, what is profit, right? It's either it's independence, right? That's what I think Bitcoin community, privacy community believes in is in independence, right, in sovereignty, in ability to make their own choices. But nothing of this is impossible if you are existing handouts, right? Because you're dependent on whoever gives you handouts, right? Children are dependent on parent until they start earning their own money, right? People who get whatever social security benefits they are dependent on government to tell them what to do. And it's not a good thing. So any organization that wants to be independent has to make profit. Otherwise it becomes dependent on whoever gives its money. And that's another dark side of the kind of for-profit model non-profit model because not only you can't scale it really well, you become dependent on your donors. And those donors may have not necessarily like good motives, right? We've seen non-profits who were have been like you've seen this chat control legislation, right? The biggest lobby effort for chat control over legislation was coming from non-profits funded by big tech. So talking about non-profit being a good thing. So I honestly I honestly think that morality and integrity of what happens doesn't depend on the organization form. I think it depends on people behind this organization in the first place, right? We've seen companies doing moral things and we've seen non-profits doing immoral things. Right. And I think, yeah, so so what what we are doing right now. So we kind of understand we're building network that nobody should own. We don't want to own it, right? We want a general-purpose transport network that is run by community, operated by community, which means that the model when we control the protocol, the model we control all the licensing on the software is not sustainable long term, right? So what we are doing right now, we are we already announced to the community that we will be transitioning the governance we are transitioning the governance to consortium model, which is similar to how the web was governed until recently. It's interesting by the way I didn't know about that I only learned when was reading. So World Wide Web was governed by consortium, not an entity. like it's effectively an agreement between four different entities in different countries. Worldwide Web was governed by consortium from Netscape shut down in I think 2004 and until 2023 when W3C became a US non-profit, a single entity. Which is fun. Which means the Worldwide Web that we all believe is decentralized now have a centralized governance model. Even though it's by non-profit it's still centralized.","offset":4908,"duration":191}],"startTime":4520},{"title":"Consortium Governance","summary":"Evgeny announces plans to decentralize SimpleX's governance into a multi-entity consortium to prevent corporate capture. He cites the history of Netscape and the W3C to explain why rapid, centralized innovation must occasionally precede decentralized governance.","entries":[{"text":"Host: Right.","offset":5099,"duration":1},{"text":"Evgeny: So what we did we worked with one exceptional open-source lawyer, Heather Meeker. She has authored multiple open-source licenses such as Mozilla license, Elastic license. She participated in some exciting works. She helped us draft this agreement for consortium for SimpleX network and we are in a process of setting up the entity that will be in a consortium agreement with SimpleX the company and then we'll be setting up additional non-profits in different jurisdiction so this multiple entities will be able to run network together and this way avoid like jurisdictional pressures or risks and avoid any kind of corruption from any centralized governance model.","offset":5100,"duration":50},{"text":"Host: Like corporate capture and whatnot.","offset":5150,"duration":1},{"text":"Evgeny: Exactly, yeah. Because we've seen we've seen corporate captures happen in non-profits a lot, right? The whole Linux like look at this, you're probably observing this noise about California law of like...","offset":5151,"duration":11},{"text":"Host: Yep.","offset":5162,"duration":1},{"text":"Evgeny: ...requiring KYC to flesh Linux. This is insane. I made a tweet yesterday it resonates with lots of people. It's effectively they tell you \"you no longer own your computer,\" right? Just like we're going to break and enter into your computer and demand it's a violation of like multiple constitutional amendments like certainly First Constitution and Fourth and Fifth and god knows what else is violated and they say it's okay. What what I find completely ridiculous is that all those open-source foundations developing Linux software are just quiet. They don't say anything, right? They don't the only open-source the only privacy foundation is EFF. EFF is campaigning against this law. Linux Foundation says nothing, right? All these kind of foundations developing Linux software are saying nothing. They already commit code that implements this age control into open-source code which is just ridiculous to me.","offset":5163,"duration":56},{"text":"Host: Why do you think that is?","offset":5219,"duration":2},{"text":"Evgeny: Because they are captured. I think.","offset":5221,"duration":2},{"text":"Host: Right.","offset":5223,"duration":1},{"text":"Evgeny: Because we've seen a lot of decisions in those foundations that don't necessarily they they they have been pressuring creators of software to leave, they have been pressuring... so that's not that's not good.","offset":5224,"duration":13},{"text":"Host: They're reliant on their donors to pay their rent basically.","offset":5237,"duration":2},{"text":"Evgeny: I don't know, Matt. I I cannot say why it happens. But to me it was always like always the I don't want to go into there. But the reason I bring it up the reason I bring it up is because I'm neck-deep in this with OpenSats. You know, OpenSats we saw a concern of very centralized funding options for open-source developers building non-profit stuff in the Bitcoin ecosystem. And to be clear here, there's a bunch of foundational open-source stuff that can't be monetized. It just it cannot be monetized. It would it would ruin the value prop for something like Bitcoin protocol software to be to be monetized directly. And so we built OpenSats in a way to resist that. And I think one of the biggest thing is we're a volunteer board. We're a nine-person board that's all volunteers we make money doing other things. And it's because of that concern. You know, the concern that you get captured by your donors because you're making $500,000. Some of these non-profit boards it's insane how much money they're making. And if that donor if that donor base disappears then they lose that. If my donor base disappears, directly financially there's zero impact to me, right? And I think that's a key piece but it doesn't completely solve it. Obviously if the donors disappear OpenSats is gone. And so then I I do agree to your point that it does come down to the people in a lot of ways, right? It's like I would rather OpenSats be gone than ever take direction from a donor.","offset":5239,"duration":90},{"text":"Evgeny: Exactly, because you because you are independent because you personally making profit in your life and you wouldn't let other people run your life. That that comes to who should be on a board which is also very important question, right? We still didn't form the board but we are reaching out to various people who we believe can create value for for for governance and also it would be helpful to them as well. So yeah, so we but I think it's still important given that jurisdictional law changes quite rapidly sometimes, I think it's important to have multiple layers of decentralization of governance decision. So my initial thinking was that we should have shared ownership of IP, right? But intellectual property. The legal advice from from from our lawyer was that it's not possible really because there is no such thing, right? So shared ownership of intellectual property means that any owner can dispose of it, not just some consensus is needed. So what is going on happening is that the company will be remain the owner of IP but it will be licensed to all consortium members irreversibly. So there is a specific clause in open-source licensing when there is a lien attached. So even if the company stops existing or sold license still survives this. So effectively we will transfer licensing to multiple consortium members in a way that we can't revoke it and then bit by bit we want to transfer governance of the key protocol in the same way. Again, like Netscape has always been an inspiration to me as a company, right? Netscape built web as we know it, right? Because Netscape pick up web protocol when it was embryonic, right? Nobody like you know, who who knew about the web in 199 1995? Right? Nobody knew about the web. But they picked it up they built a browser, they added JavaScript, they added cookies, they added SSL, they added like, people think cookie is a bad thing, but cookie is a foundational piece that allows you Facebook know to you is you, right? It's verifiability, right? So without cookies Facebook doesn't know who you are. Or Twitter or whatever. They created web as we know and then they shut down in 2004. W3C took over abruptly and what happened is that all the innovation stalled completely, right? Took them like seven years to get CSS to next version.","offset":5329,"duration":159},{"text":"Host: Right.","offset":5488,"duration":1},{"text":"Evgeny: The industry was so frustrated with W3C governance so they had to hold their own working group, if you remember this WHATWG. So and they had to take matters in their own hand and it was like super frustrated for everybody, right? And that's exactly what the abrupt and that's what unfortunately we see I think with many decentralized protocol because they want to be decentralized, right? But they don't understand that from the point of early enthusiasts using this protocol to the point everybody else can use this protocol it's not just time and adoption, it's radical changes in the protocol. Yep. And these radical changes require speed, commercial incentive, funding, centralized decision-making. So you simply cannot get a protocol to mass adoption without running things as a venture-funded company would run things. That's what Netscape did, right? Netscape was doing Netscape browser at a time there like 30 other competing browsers also trying to do browsers with venture funding. It didn't occur to Netscape to ask other browsers what they think about protocol changes. They honestly didn't care.","offset":5489,"duration":62},{"text":"Host: Right.","offset":5551,"duration":1},{"text":"Evgeny: If they did, we wouldn't have the web. So that's how I see the whole kind of decentralized governance. There are some stable parts of the network and changing them should require consortium vote, right? But there are some evolving part of the network that kind of on the boundary require adoption, require radical changes, and they are not ready for decentralized governance yet.","offset":5552,"duration":21},{"text":"Host: You need to be able to move fast and adopt and...","offset":5573,"duration":3},{"text":"Evgeny: Exactly. Yes. And that's what we lost with...","offset":5576,"duration":13},{"text":"Matt: Agreed.","offset":5589,"duration":1},{"text":"Evgeny: Yes, so that's what we want, that's what we're trying to achieve.","offset":5590,"duration":2}],"startTime":5099},{"title":"Smart Contracts for Revenue Sharing","summary":"Addressing criticism from Bitcoin and Monero communities, Evgeny explains why SimpleX's infrastructure plans require smart contracts. Programmable blockchains are needed for global namespace discovery, server registries, and automatic revenue splitting.","entries":[{"text":"Matt: That's why I always use like Signal as an example, because they - once again, not perfect, but very pragmatic trade-off balance that they went with. They've had - it's funny, right, because you can look at it from both perspectives.","offset":5592,"duration":11},{"text":"Matt: You can be like, \"Oh, they're a massive success for a privacy project because it's 100 million people,\" and then you can look at it from the opposite side - \"That's nobody,\" right? Like it's still 2%, right? 100 million people is 2%, if I can count... yeah.","offset":5603,"duration":15},{"text":"Matt: Evgeny, I want to dive in just before we wrap here, I think it's important that like high-level the monetization makes sense to me. In practice, everything's harder to execute on in practice.","offset":5618,"duration":15},{"text":"Matt: So I want to dive a little bit more into the details because there was some controversy around it, about how you're thinking about implementing it. And the big one is, okay, so the main operators that are doing, you know, 90% of the traffic, these big channels, are going to be paying for things.","offset":5633,"duration":17},{"text":"Matt: You basically got flack - you know you're doing well when you get flack from everyone that has all different conflicting interests and everyone is mad at you. But the two big ones that I noticed was the Bitcoin and Monero communities, respectively.","offset":5650,"duration":15},{"text":"Matt: The Bitcoin community being saying, \"Why aren't we using Bitcoin for this?\" And the Monero community being like, \"Why aren't we using Monero for this?\" So my question to you is rather simple: why aren't you using Bitcoin for this, and what's the alternative, and why is that being chosen?","offset":5665,"duration":16},{"text":"Evgeny: Okay, so one thing at a time. To have network pay, to have network function, we need to - we don't need to just pay for servers, right? We need to have mechanism how governance layer can be paid, how software developers can be paid, and how channels can make profit.","offset":5681,"duration":17},{"text":"Evgeny: And that requires some mechanism of revenue sharing and distribution between those parties. We cannot tell channel owners, say, you have to pay this and this and this, right? So we have to create some codified approach for revenue distribution.","offset":5698,"duration":16},{"text":"Evgeny: And not just that. So we also need to solve problem of server discoverability, right? So how will people learn where the service exists? How they find them out? Right? Okay, they want to use paid service, how they find it out?","offset":5714,"duration":14},{"text":"Matt: Right.","offset":5728,"duration":1},{"text":"Evgeny: Or they want to have channel names, because again, if we're talking about usability, you need to have a name for the channel, right? Nostr keys are great, SimpleX addresses are all great, they're 100 characters of gibberish. Normal people will never ever use it.","offset":5729,"duration":17},{"text":"Evgeny: They want to type \"music\" and go to the channel with music, or they want to type \"sport\" and go to the channel with sport.","offset":5746,"duration":67},{"text":"Matt: For the same reason we don't go to direct IP addresses, we type in a domain.","offset":5813,"duration":4},{"text":"Evgeny: Exactly, we type domain names, right. So how do we do it? We need some mechanism to agree on what this address means. Because if we simply give this address to a server and say, \"Okay, I will tell you music, you will tell me the address,\" the problem with that is the server can give you any address. They can execute man-in-the-middle attack on your connection, right?","offset":5817,"duration":-38},{"text":"Evgeny: So you need some way to get trust to the information you're getting. And how internet solved this problem and world wide web solved this problem? They created like hierarchy of trust, right? Certificate authorities and domain name systems, when your trust is built ultimately because you have an authority.","offset":5779,"duration":20},{"text":"Evgeny: But that's antithetical to both Bitcoin, Monero, and to us. Because the second there is an authority, this authority will be corrupted, right? And we've already seen attacks on certificates via major certificate authorities, right?","offset":5799,"duration":15},{"text":"Matt: It's a mess.","offset":5814,"duration":1},{"text":"Evgeny: Yeah, it's a complete mess, right. So we cannot build a system based on trust or on authority. We have to build a system that's properly decentralized when any information you get about the network is trusted without having authority that you trust.","offset":5815,"duration":16},{"text":"Evgeny: And the solution exists, it's called blockchains, right? So, but I think the way I see blockchain - and that was the root cause of this misunderstanding, and the way many people see blockchain is very different.","offset":5831,"duration":14},{"text":"Evgeny: Because people see blockchain as a way to transfer value between participants, as a ledger that records transactions. But that's just one use case. Like since a lot of technology has evolved, and blockchain can act as a global distributed computer that can perform arbitrary computations and arrive to consensus about things, not just transactions, any consensus.","offset":5845,"duration":26},{"text":"Evgeny: Can execute arbitrary logic in a way that it's trusted without having a single party that you need to trust. That's what smart contracts do.","offset":5871,"duration":9},{"text":"Evgeny: Because people think contract is some sort of agreement that you sign or it's some sort of an asset, or - it's not. It's just a code, right? So when you go to the server, you run some code, it gives you some result, you have to trust the server.","offset":5880,"duration":15},{"text":"Evgeny: If you go to smart contract enabled blockchain, then you can run computation and get the result, and then your trust in this result is not based on a particular node of this blockchain, it's based on the whole decentralized blockchain.","offset":5895,"duration":14},{"text":"Matt: Yeah, the best example of that at scale, in my opinion, right now is Polymarket.","offset":5909,"duration":4},{"text":"Evgeny: Potentially, yes, I'm not that familiar with that. I know what Polymarket is.","offset":5913,"duration":3},{"text":"Matt: Well, I mean, they have a similar - I mean, they have a similar problem, right? The problem is if, you know, they can't have a centralized entity taking custody of funds and handling arbitrary code, like settling of the markets, right? If a missile strike hits or not, like it can't be a single company doing that.","offset":5916,"duration":15},{"text":"Evgeny: Correct. So when we say we need - so several things should happen for SimpleX network for it to be usable and sustainable, right? We need to have a registry of servers that can receive money and trust this registry, right?","offset":5931,"duration":18},{"text":"Evgeny: We need to have a registry of names so we can discover channels. And we also have design for private names when you can discuss people without anybody knowing their addresses. We have design for that too already.","offset":5949,"duration":15},{"text":"Evgeny: And we also have to have a way to transfer value as well, but not just transfer value, but also distribute the revenues in somewhat agreed way. So depending on - it's like programmatic value transfer, right? It's like an auto split that's going to multiple...","offset":5964,"duration":11},{"text":"Evgeny: Exactly, yeah, exactly right. So because otherwise, transfer value is a simple problem and yes, Bitcoin is the best at solving this problem and the first solved this problem. And if transferring the value would be the only problem that we needed to use, then Bitcoin is a viable solution, and likewise Monero is a viable solution, right?","offset":5975,"duration":14},{"text":"Evgeny: But that's not the problem that we need to solve. We need to have a distributed computer that we can trust that will solve all the problems that require network-wide state. Because today SimpleX network has no network-wide state. No registry of servers, there is no list of participants.","offset":5989,"duration":13},{"text":"Matt: No global state.","offset":6002,"duration":1},{"text":"Evgeny: Exactly, it's fragmented. And when people say, \"Oh, we have to bring the whole messaging on blockchain,\" that doesn't work because messaging has to be fragmented, right? Communities have to be fragmented, network - but if you want to have a global namespace that is recognized by all clients, then you suddenly want a network-wide state, right?","offset":6003,"duration":21},{"text":"Evgeny: If you want to have a server registry to which you can pay money, you want a network-wide state. And if you want an agreement with those servers that you can trust and everybody is paid who is doing the work for the network, you need some programmatic way to split revenues and distribute money. That requires smart contracts.","offset":6024,"duration":17},{"text":"Evgeny: So our whole idea is behind that to program all this logic effectively on the blockchain and have server operators and network users interface with smart contracts so that payments can be transferred from the channel owners to the servers with whatever revenue sharing agreements that can be put in place as code.","offset":6041,"duration":21},{"text":"Evgeny: Specifically, we're going to build a proof of concept quite soon on some blockchain so people can have a feel of how it's going to work. But imagine you're an operator, you're going to smart contract via some service, dApp hosted on IPFS for example, and you say, \"I want to be an operator.\" You will be asked to give your details, you will be asked to like, what are your server addresses and what not.","offset":6062,"duration":19},{"text":"Evgeny: You will be asked to sign a deed. So I believe that technical guarantees have to be supplemented by contractual guarantees. So let's say, if you want to run a server on SimpleX network, you have to guarantee the users that you're not going to sell the data, that you're not going to collude, that you're not going to - so there have to be legal remedies if you do.","offset":6081,"duration":19},{"text":"Evgeny: I think that's a big missing bit in networks like Tor, because they only - maybe because they are technologists, maybe they just don't think about it like this. But I think if I'm using the server on the network, I want not just technical guarantees, I also want contractual guarantees as well.","offset":6100,"duration":19},{"text":"Evgeny: And we want blockchain to deliver it all. So participation in network would require providing contractual guarantee in exchange for making the money, which I think is reasonable. So that requires programming, that requires writing code, that requires deploying code in a way that it's executed not on a particular computer but on a distributed network of computers.","offset":6119,"duration":18},{"text":"Matt: Independently.","offset":6137,"duration":2},{"text":"Evgeny: Yeah, and there is not a single - there are choices, right? There are multiple networks that can do it. I think it would benefit Bitcoin a lot to evolve into this direction, but it's not there yet.","offset":6139,"duration":13},{"text":"Matt: I mean, why does Bitcoin have to do all the things? I'm in the camp that like if you use - I mean, because the problem is adding that functionality reduces the robustness of whatever blockchain it has that functionality. That's always been the trade-off from Bitcoin protocol point of view.","offset":6152,"duration":22},{"text":"Matt: So like if you use like for instance - and I've gotten some shit for this and this is why I used Polymarket as an example - like Polymarket runs on I think like an Ethereum Layer 2 called Polygon, right? From a user point of view, I just need to be able to deposit Bitcoin.","offset":6174,"duration":14},{"text":"Matt: Yes.","offset":6188,"duration":1},{"text":"Matt: Like if it runs on a different tech stack, that's in a lot of ways a benefit to Bitcoin holders because it's not burdening Bitcoin with that tech stack. You just need to be able to send Bitcoin to it.","offset":6189,"duration":15},{"text":"Evgeny: 100%. And that's actually solved problem, right? The whole idea of like foreign assets have been executed in a trustless way by other blockchains. For example, I think Polkadot did it, StarkNet did it, there are some other blockchains that did it, that you can hold asset on a Bitcoin blockchain but in a way that you operate on this asset on another blockchain.","offset":6204,"duration":20},{"text":"Evgeny: So it's kind of - it's nearly non-trustless.","offset":6224,"duration":3},{"text":"Matt: No, no, there are trustless - there are trustless solutions as well.","offset":6227,"duration":2},{"text":"Evgeny: I question - I question if that's the case. There's a lot of hype around it. Look, I think it's important that you minimize the trust as much as possible for that cross-chain situation. There are atomic swaps that can handle it. You know, Boltz just released an atomic swap that moves you from, for instance, Bitcoin to Tron Tether, and in between there's no custody. But you know, trust is a hard thing.","offset":6229,"duration":34},{"text":"Evgeny: I agree that it's hard to do a completely non-trustless way. But I think they are doing something reasonable with that. But that's not the point. So what we want to do is to just have ability to transact with any currency on the entry, Bitcoin of course as well, but ultimately to have a mechanism of revenue sharing between participants that enable - like, you're using web browser, right? You're not paying to the web browser.","offset":6263,"duration":29},{"text":"Evgeny: It doesn't mean that the web browsers are not paid, right? Ultimately web browsers find a way to make revenue. So we believe that companies developing client software for networks should earn revenue from the network for doing that, right?","offset":6292,"duration":15},{"text":"Evgeny: And it's not just our company, any company that develops software should earn money proportional to the usage that they are able to generate for the network, right?","offset":6307,"duration":8},{"text":"Matt: Yeah, I mean the web browser's an interesting example, right? Because it wasn't built in a programmatic way of revenue sharing and stuff, they have to find revenue streams that are very convoluted and oftentimes have warring incentives. The best example being Chrome, which Google figured out was the way you monetize it is with search and mining data of people.","offset":6315,"duration":21},{"text":"Matt: Exactly.","offset":6336,"duration":1},{"text":"Matt: While like Internet Explorer was monetized basically through Windows and Windows lock-in and Safari is Apple's ecosystem. And as a result, we just don't have many different web browsers we can use.","offset":6337,"duration":12},{"text":"Evgeny: Exactly, exactly. So it stifles competition because there is no mechanism to get revenue for making a browser from the network that requires browser to access, right? And also all sort of perverse incentives, right? When privacy gets compromised, when security gets compromised, when users' data is being sold, and that's just corrupt model.","offset":6349,"duration":22},{"text":"Evgeny: And the only proper solution is to just build in this revenue sharing model in the network so browser developer - or whatever software developers get some share of the revenue proportionally to the value they create for the network.","offset":6371,"duration":14},{"text":"Evgeny: And likewise governance of the network, right? When we say we're establishing consortium, governance carries legal costs, right? It carries documentation costs. It may be not cost a lot of money, it may be whatever $100,000 a year, $10,000, it doesn't matter. It's still money that somebody has to pay ultimately, right?","offset":6385,"duration":23},{"text":"Evgeny: And until some point it's okay to sustain on donations, right? But beyond some point it may be hard to sustain on donations and it may require explicit revenue sharing agreement with the network. So we really - I really see it's important to have foundation that would allow it.","offset":6408,"duration":12},{"text":"Evgeny: I think it's fundamentally the vision of Tim Berners-Lee around the web, right? That's why we say that what we're building is potentially next web, because he was talking about micropayments powering the websites and generally web ecosystem from day one, right?","offset":6420,"duration":18},{"text":"Evgeny: It was way ahead of like blockchains or cryptocurrencies or even understanding what this micropayments means. But I think like he was talking about the future for which we today have technology.","offset":6438,"duration":12},{"text":"Matt: Fair enough.","offset":6450,"duration":1},{"text":"Evgeny: So, so yeah. So that's, that's, that's why we, we didn't, we didn't make a final decision. We're still iterating in which, which is the blockchain, what smart contracts. But fundamentally we're looking for solution with smart contracts.","offset":6451,"duration":16}],"startTime":5592},{"title":"A Prepaid Crypto Model Without a Token","summary":"Evgeny clarifies that SimpleX will not issue a proprietary token. Instead, they plan to build a privacy-preserving, prepaid credit system utilizing existing digital assets, emphasizing the importance of establishing product-market fit before achieving pure decentralization.","entries":[{"text":"Matt: I am - and this, I'm trying to be mindful of time because this was supposed to be a tight hour and I know time is scarce, and no, don't apologize, I was apologizing to you. But this conversation has been so fascinating that we're almost at two hours. But I still, I mean I still want to just go a little bit deeper on this before we wrap. If you have a little bit more time?","offset":6467,"duration":11},{"text":"Evgeny: I have all the time you have.","offset":6478,"duration":2},{"text":"Matt: Okay, great. Uh what thought have you given - I mean, the big concern, right? I would say, is we haven't seen - so basically there's two pieces here, right? And I think the first is the reason the community's gut reaction was outrage is because most of the time when a proprietary token scheme or credit scheme gets presented, it's very scammy.","offset":6480,"duration":35},{"text":"Matt: I don't think it inherently needs to be scammy, I just think that 99% of the time it is scammy and there aren't many examples of it not being. So people default to that. I understand why you would choose this path and I don't think it's necessarily unethical or anything.","offset":6515,"duration":16},{"text":"Evgeny: It's not even that, Matt. We're not going to do any tokens or emission for that. We see a smart contract as a holder of the existing value. We're not going to create any digital asset class.","offset":6531,"duration":12},{"text":"Matt: Okay.","offset":6543,"duration":1},{"text":"Evgeny: All we want is a scheme that allows people to deposit some existing asset - there is no final decision on what this asset is.","offset":6544,"duration":6},{"text":"Matt: But it can be multiple different assets, right? I mean...","offset":6550,"duration":2},{"text":"Evgeny: Exactly, exactly. They deposit it on smart contract simply holds it. We're not interested in emitting digital assets at all and we're not planning to issue any tokens. What we want is a autonomous smart contract on the chain when you deposit existing asset that we didn't create and then you assign it to a community using zero-knowledge proof, which already decouples your purchase from assignment.","offset":6552,"duration":21},{"text":"Evgeny: And then once community has assigned credits - and credit is existing assets, it's not our token, it's not something we created - then they can redeem it to the server and then when revenue gets distributed.","offset":6573,"duration":13},{"text":"Evgeny: What we achieve with this scheme is that privacy is preserved because it's effectively you're - think about it like prepaid telephone card, right? You go into the store, you pay cash and you get the card, and then you use the card to pay for your phone, or you may give it to your friend and your friend will pay for his phone or for her phone.","offset":6586,"duration":20},{"text":"Evgeny: So that's fundamentally what we want to develop: prepaid scheme allowing you to use existing digital assets on a blockchain to prepay server capacity and do it in a way that preserves your privacy.","offset":6606,"duration":12},{"text":"Matt: Right, but then to programmatically split it between...","offset":6618,"duration":3},{"text":"Evgeny: And programmatically split revenue. Right. So we have no interest in issuing tokens, we have no interest in creating any digital asset class. We have interest in creating a mechanism that allows people to transact in a way that protects their privacy.","offset":6621,"duration":16},{"text":"Evgeny: Because you cannot really - like yes, people go through all the hoops to have privacy, they have to think about how they connect to blockchain nodes, how they do this, how they do that. So privacy is possible with blockchain, but it's not possible for mass market users realistically, right?","offset":6637,"duration":15},{"text":"Matt: Yeah, it's quite difficult. It's been a major focus of mine.","offset":6652,"duration":4},{"text":"Evgeny: Exactly. So what we want to develop is a layer that is built on top of blockchain, uses existing blockchain primitives, existing blockchain assets, and that allows people to pay for infrastructure in the same way they would pay for telephone buying telephone prepaid card.","offset":6656,"duration":18},{"text":"Evgeny: We didn't, like if I tell you that we're doing a prepaid telephone card it doesn't mean we're printing cash. We're not printing cash, we're just doing prepaid telephone card. So we don't want to do any token that would hold value. We simply do effectively treasury contract which will hold some other tokens that already exist. We didn't know - it may be USDC, it may be some other token, it may be something that people recognize as a value and use it as a transient value store to pay for the servers.","offset":6674,"duration":30},{"text":"Matt: Well that brings me to my second piece, which I would just say as someone who is pretty excited about what you're building and understands the need for it, and I don't want you to make any bad decisions that you regret later - is you know the way Bitcoin is designed and the trade-offs Bitcoin has made make it very resistant to centralized capture.","offset":6704,"duration":24},{"text":"Matt: Both on the protocol level and then also the token itself is a native asset, right? When you're thinking about how you're going actually execute on this and build it out, I think it would - and I'm sure you're already thinking about it - there's two pieces, right? First of all, the protocol you decide to build on is going to have varying levels of centralization, right?","offset":6728,"duration":22},{"text":"Matt: So Tron for instance is an example I constantly use. Tron has $10 billion worth of Tether on it, but at the end of the day it's just Justin Sun has full control. Now regulators perceive it as federated control and he doesn't have full control, and maybe that's enough for him in his use case or whatever.","offset":6750,"duration":18},{"text":"Matt: But when it comes to something as important as SimpleX, I could easily see censorship happen on that chain. Now you could - now there's varying levels of this throughout the ecosystem, right? With I would say Bitcoin being by far the most secure but not programmatic for your use case or whatever.","offset":6768,"duration":18},{"text":"Matt: And then things like Tron being incredibly centralized but a lot of people are using them as a result. And then the second piece is the actual assets themselves, right? USDC, you know, is controlled by a centralized group of regulated institutions, right? It gets frozen all the time, so does Tether, right?","offset":6786,"duration":13},{"text":"Evgeny: We understand it.","offset":6799,"duration":1},{"text":"Matt: So you got to think through these because ultimately I mean I could imagine a world where you build this all out and then if that layer gets broken, everything starts to break around it, right? Like people it would hurt the robustness of the protocol itself. So these are things I'm sure - are you thinking about this? I assume you are.","offset":6800,"duration":24},{"text":"Evgeny: 100%. Yes. Matt, you know one of the reasons why we announced our strategy and technology direction long before we have answers is exactly that. Because we usually iterate ideas internally and then when we think, okay, we don't know how to make it better, at this point we announce.","offset":6824,"duration":15},{"text":"Evgeny: It sometimes happens months or even more than a year before we actually start building. We didn't start building it yet. We only - we only arrived recently to a cryptographic design that hits all the goals, right?","offset":6839,"duration":15},{"text":"Evgeny: We didn't even - we only recently running the review of all the blockchains that can be used for that. And Tron is disqualified, right, same as many other centralized blockchains. We absolutely don't consider high degree of decentralization.","offset":6854,"duration":16},{"text":"Evgeny: I understand that downside of so choice between USDC or Tether and other tokens is effectively volatility versus centralization. So it's a - it's very - it's a very hard choice, right? So and for many - so I would say in the same way I like reject false trade-offs and false binaries, right? Some choices are just not real, right? You just invent them and you say you cannot have both. In many cases you can have both.","offset":6870,"duration":29},{"text":"Evgeny: But sometimes there are some genuine trade-offs and they're really hard to take. And with this kind of specific technology, there are a lot of hard trade-offs. That's true. What I think - what I think is important though, we're still in enthusiast territory. I think it would be correct to see what we're building right now as a - as a prototype, right?","offset":6899,"duration":17},{"text":"Evgeny: In the same way as SimpleX v1 was a prototype. And if you compare SimpleX design on the day of launch with SimpleX network design today, it's like almost like two different products, right? We have completely different layer of security, we have completely different - and we managed to evolve it all kind of with backwards compatibility so people were effectively using a different network without changing the client without having being disrupted etc etc.","offset":6916,"duration":27},{"text":"Evgeny: So I think we can do the same with payments. So whatever we build in the first instance is likely to be a prototype we learn on and that will evolve dramatically as it gets adopted, as it gets tested.","offset":6943,"duration":15},{"text":"Evgeny: Because I think the biggest test for the product is not technology, it's market, right? We kind of hypothesized that channels will pay for servers, servers will want to participate. We hypothesized a lot about the market. And you, you know it better than anybody else, you're a VC, right? Products don't fail because technology fails. Products fail because nobody cares.","offset":6958,"duration":18},{"text":"Matt: Yep.","offset":6976,"duration":1},{"text":"Evgeny: Nobody cares to use them, nobody cares to build them. And I think at this point it's much more important to prove that our hypothesis about the world - that people will pay, that servers will want to sell - are correct, right? That there is actually a market.","offset":6977,"duration":15},{"text":"Evgeny: I think to prove this is much more important than to avoid like centralization - you understand what I mean, right? So like it's much more important to - and once we see, okay, yes there is a market, it can grow, we'll just rebuild the technology in a way to avoid the capture.","offset":6992,"duration":14},{"text":"Evgeny: You can see it's the same way as we were building SimpleX network. People were telling me from day one, \"You should create a foundation and should run protocol evolution.\" But my response was look, we don't know if anybody needs it, number one. We, we don't know what people need. It's not just we don't know. Even if we know that people need something, it's almost like you know, like your trade has an expression \"product-market fit,\" right?","offset":7006,"duration":23},{"text":"Evgeny: We've been running product-market fit experiment for four years and now we kind of have understanding of what people need in terms of messaging, right? What people need in terms of payment for infrastructure capacity, we're just in the beginning of running this experiment, right? We hypothesized, we learn, we talk to people, we believe we - it's putting the cart before the horse otherwise.","offset":7029,"duration":19},{"text":"Evgeny: Exactly, yes. So, so I think, I think it's important for community not to overvalue technology choices. Of course we'll make the best job, of course we'll do decent technology choice, of course we'll avoid obviously bad - like Tron is obvious bad choice, right? There is no way - there is no world in which we use Tron or Base or something else centralized, right? So it's literally not even on the table, right?","offset":7048,"duration":20},{"text":"Evgeny: But within reasonable choices, I think I wouldn't overindex the importance of doing it right on the first try, but rather doing something that's kind of usable - we're trying to do a good job, I think we're trying to do a good job with Version 1. But that's still...","offset":7068,"duration":13},{"text":"Matt: Directionally correct and learn from it is how I think you're thinking about it.","offset":7081,"duration":3},{"text":"Evgeny: Exactly. I think that, that's how we've been evolving the product from day one, right? We built something and then it was pulled by users into some direction and we pushed in some other, it was kind of a combined effort. And I think that's why people use it, because we tell people early what we do, we listen what they say, we learn, we do something that we think - we're building it for people, right?","offset":7084,"duration":20},{"text":"Evgeny: I'm too old to do it to be rich, right? I personally - no, come on, it's like you're not doing what you're doing to be rich, right? If you wanted to be rich you would be doing different things, I think.","offset":7104,"duration":11},{"text":"Matt: I agree with that. That is correct.","offset":7115,"duration":2},{"text":"Evgeny: Yeah, there are simple ways today to get rich, right? We really think what kind of is common between us is that you kind of dislike the place where this world arrived, right? And you do what you can in your place with your resources, with your abilities, to make this world a little bit better.","offset":7117,"duration":19},{"text":"Evgeny: I think that's why we're building communication technology because I, I care about communications, right? I experimented with page- you know, pagers like I had some was dabbling with those things so like I really care about people being able to connect to other people. There is nothing more important.","offset":7136,"duration":14},{"text":"Evgeny: And me seeing like the whole world is converted into some kind of a surveillance panopticon when like you can't really talk to anybody anymore, that's just not right. And trying to do something...","offset":7150,"duration":13},{"text":"Matt: Yeah, someone has to do something.","offset":7163,"duration":1},{"text":"Evgeny: Exactly. I was saying that something has to do something for the last 12 years. 15 years now, right? So like 4 years ago I say, alright, nobody does anything I have to do something, right?","offset":7164,"duration":12}],"startTime":6467},{"title":"Upcoming Crowdfunding and Wrap-Up","summary":"Evgeny announces an upcoming opportunity for the community to participate in crowdfunding for company equity. The host thanks him for the deep-dive conversation and wraps up the show.","entries":[{"text":"Matt: Yeah, that's what compels me too. I look, I think you're thinking about it the right way. I think it's the right perspective. Obviously you have my contact now, so if I can be helpful as you try and figure things out, don't hesitate to reach out.","offset":7176,"duration":12},{"text":"Matt: But yeah, I think it's the right perspective. I think it's I mean just really well set across the board. Evgeny, this was a great, really great conversation. I enjoyed it. Maybe we'll do a follow-up in the future like in a year or something, I don't want to like take too much of your time, but I think it'd be cool to have you know kind of like a timeline as, as you build all this out. It'd be fun.","offset":7188,"duration":24},{"text":"Evgeny: That would be fantastic, yes. So we kind of...","offset":7212,"duration":4},{"text":"Matt: Just try and make it work.","offset":7216,"duration":2},{"text":"Matt: Yeah we're past the two hour mark now. This was an epic, epic conversation. Do you have any final thoughts for the audience before we wrap? How they can be helpful? I'm going obviously link to all the important links in the show notes.","offset":7218,"duration":13},{"text":"Evgeny: We didn't do a formal announcement yet. And what we're planning this year is effectively transfer and give people more ownership of SimpleX network across multiple dimensions. So this consortium governance is one thing. Another big thing we're planning for this year is crowdfunding. It's not formally launched yet, we're kind of in testing the water phase so we're not accepting any money, we're not doing that.","offset":7231,"duration":23},{"text":"Evgeny: But we will be doing it this year. We've been criticized a lot by our users for taking private investors' money and we think it's like - I think our users have to own a piece in this network and have a say in where this network evolves and not only via non-profit governance but also via having shares in, in a company that builds this network.","offset":7254,"duration":23},{"text":"Evgeny: So we're creating this opportunity right now. It'll probably launch in like three months or so, but there will be announcement soon in the blog post, on Twitter, so yeah that's a big thing. So I really wish to see community supporting and benefiting from, from what we're building.","offset":7277,"duration":21},{"text":"Evgeny: Because we're not trying to be just non-profit entity. We believe like if what we're building is the next web and we're the company building the next web, then it may be really large business and our early investors can benefit a lot from participating in that. And I really want to see community members in their numbers.","offset":7298,"duration":16},{"text":"Matt: And I don't know if you're comfortable with sharing how that's going to be set up or like was that just a traditional equity sale or...","offset":7314,"duration":5},{"text":"Evgeny: Yes. We don't believe in tokens. We will sell company equity, it will be some sort of modified SAFE agreement. We can't use YC SAFE as is for crowdfunding. It's not decided, it's premature, it's currently what we're working with, with lawyers, but fundamentally yes it will be the community who can participate will own company equity.","offset":7319,"duration":23},{"text":"Matt: Awesome, got it.","offset":7342,"duration":2},{"text":"Evgeny: That's, that's our big news for this year. So...","offset":7344,"duration":3},{"text":"Matt: I'll keep an eye out for that.","offset":7347,"duration":1},{"text":"Evgeny: Yeah. And that's, that's - I have to say what my lawyers keep saying me: we have to say a disclaimer that this is not an investment offering and we cannot accept any money at this stage. This is just us testing the interest.","offset":7348,"duration":12},{"text":"Matt: I think that was good legal advice that you received, I'm glad you said it. Sir, it was a pleasure, thank you for joining us.","offset":7360,"duration":8},{"text":"Evgeny: It was a privilege, Matt. I really appreciate you doing that with me, thank you so much.","offset":7368,"duration":6},{"text":"Matt: Thank you. Freaks, thank you for joining us. I hope you found the show helpful or fascinating. I enjoyed it. As always, share with friends and family, search \"Citadel Dispatch\" in your favorite podcast app. All relevant links at CitadelDispatch.com. Love you all. Stay humble, stack sats. Peace.","offset":7374,"duration":15}],"startTime":7176}],"entries":[{"text":"Host: Happy Bitcoin Friday, freaks! It's your host, Odell, here for Citadel Dispatch, the show focused on actionable Bitcoin and freedom tech discussion. A busy morning over here, I just wrapped up Rabbit Hole Recap, my other show, but we have a great show planned today. I'm very excited for it, but before we get there, as always, Dispatch is funded by our audience. We have no ads or sponsors. Thank you, freaks, for continuing to support the show.","offset":0,"duration":46},{"text":"Host: The largest two Bitcoin zaps from last episode... Our episode was Vexl, focused on no-KYC Bitcoin, Bitcoin donations. Peter Missouri: 21,000 sats. \"I have to admit that I often forget to zap because I listen to podcasts during my hour and a half long commute, and then I forget by the time I get to a stopping point. Although much of this is over my head, I'm trying to learn as much as I can, and this one definitely inspired me.\" Thank you, sir, for your support. And just on that perspective, that's how I've learned a lot of what I know today, just immerse yourself in things that are over your head, it means you're in the right room. Absolutely love to see it.","offset":46,"duration":48},{"text":"Host: And then the second largest zap was from RyderDie Freak Mapp21: 10,000 sats. He said, \"Great rip.\" As always, freaks, all relevant links are at CitadelDispatch.com. I know sats are scarce, I know Bitcoin... you're working hard to accumulate as much Bitcoin as possible. If you cannot spare the Bitcoin donations, the next best way to support the show is to share it with your friends and family. Citadel Dispatch is available on every major podcast app by searching Citadel Dispatch. Take your friends and family's phones, open the podcast app, search Citadel Dispatch, press subscribe. They won't know what hit them, but they'll be better off for it.","offset":94,"duration":48},{"text":"Host: And freaks, on that note, by the way, I've been... as you all know, I've been neck-deep in the AI world. I rebuilt CitadelDispatch.com. It still has all the relevant links you would expect, but it also is live-polling Nostr for the top zappers. So it's cumulative; the more you zap, the higher you get listed on the website. It's a little bit of a work in progress because it's polling Nostr live, and so sometimes it does different results, but the dream is that the people that support the show the most, the top 10, will always be highlighted on CitadelDispatch.com and you can just click their profile picture and it goes straight to their Nostr profile. Pretty excited about it, but work in progress, hands up.","offset":142,"duration":48},{"text":"Host: Anyway, freaks, we have a great show today. A lot of you freaks have heard me talk about in the past the SimpleX encrypted chat app. You freaks know I love Signal, you know Signal... Signal has its own set of trade-offs, but it's fantastic that it exists in the marketplace. The two big ones are that it requires a centralized server and the second one is that they use phone numbers as a way to mitigate spam and bots. Fortunately, they recently removed the ability for other people you're messaging to see your phone number, but it still requires phone numbers nonetheless. SimpleX is a very exciting alternative that mitigates both of those concerns, and I'm pleased to have the founder of SimpleX here, Evgeny. How's it going, sir?","offset":190,"duration":49},{"text":"Evgeny: Hello, Matt. Thank you very much for having me. Excited to be here.","offset":239,"duration":6},{"text":"Host: It's a pleasure, sir. I... by the way, freaks, I think the way this came together is kind of cool. He found my SimpleX contact on my website, Odell.xyz, and messaged me on his own app and reached out and then we got onto a phone call, and I have to say the audio calls are working quite well now in SimpleX and we set this up pretty cool how it came together.","offset":245,"duration":31},{"text":"Evgeny: That's true, indeed. Yeah, we've been using SimpleX chat as the only communication tool, obviously, since we began building it, and yes, phone calls are fine, they're fine.","offset":276,"duration":11},{"text":"Host: I have to say, sir, my whole life I've been fortunate enough to successfully have moved the majority of my communications to Signal, which is great, massive improvement over regular phone calls and texts and email. But when that thing goes down, I feel quite vulnerable. And we've seen a couple outages lately, so I'm very grateful that you're building SimpleX. I think a great place to start here is just high-level: what is SimpleX? Why does it exist? Why should people care?","offset":287,"duration":40},{"text":"Evgeny: I think my primary motivation to start this, to design the protocol and to build it, was never about technology. It was about all the sad state I've been observing the world is going to, how people were losing their jobs for stating the truths, and it all has become more and more pronounced in the last couple decades. So I... I should make some like embarrassing admissions, probably. I was never deep enough in any of the cryptocurrencies world, it was alien to me. I was never deep enough in privacy community, I didn't know it even exists. But I was in publishing. I spent a large part of my life in publishing from different angles. I worked as executive in publishing organizations, I owned magazine in my home country, then I worked as head of engineering at MailOnline, one of the largest tabloids. To me, publishing and communication was always one and the same, and to me, ability to say the truth is fundamentally foundational for the society, right?","offset":327,"duration":50},{"text":"Evgeny: If you can't say what's right, what's wrong, if you can't say what's truth, we can no longer exist even, right? Because everything breaks. And when we were building the SimpleX, retrospectively we can say it's built pretty much on the same values as Bitcoin. It's sovereignty. As primary value, primary foundational truth that we build on is sovereignty. Users should own their conversations, their channels, their connections, their identity, everything that they use. The fact that we build protocol by removing network-wide identity for the users means that now users own everything, now they are in full control in the same way you hold your Bitcoin keys. You own your SimpleX identity and your identity is what your friends see, what your contacts see, and it's not something that exists on a network, that's why you own it.","offset":377,"duration":54},{"text":"Evgeny: And the second principle was that it's trustless, right? So we always thought that I was... I just always thought that if a technology is built on the idea that for it to function I have to trust my technology provider, then it's not good enough because today technology provider can be practicing don't be evil principle, and tomorrow some pressures come along and it all ends up quite evil, and we've seen it over and over again. So the only way to make it not happen is to architecturally prevent it, right? To build technology in a way that single provider cannot act against users even if they want to, right? So it's like... and sovereignty has always been number one value here.","offset":431,"duration":43},{"text":"Evgeny: So like we had a lot of discussions with privacy community, obviously privacy community was the first to discover what we built, and obviously they had their own ideas about how we should build that, and traditional privacy messenger would be like you can always delete messages you sent even if they land on another person's device, right? And this kind of approach was kind of more and more pervasive and happens on Telegram, it happens on iMessage, and I think to this at this point we've been consistently refusing to do it this way because to me it was like I have files on my computer, I have to allow somebody else to delete those files, it's just wrong, right? So I have sovereignty on my machine, right? Why should it happen unless I agree to that? Then that was interesting. So like whenever privacy and sovereignty were in conflict, we were saying sovereignty is foundational both for security and for privacy. So fundamentally that's that's why we're building. We wrote some like philosophical almost statement recently, it's on our website, about that we don't we don't see privacy as some add-on, right? It's not like a shield and key, it's not a measure of protection, it's just literally a thing that always existed, right? We always had privacy before the internet.","offset":474,"duration":68},{"text":"Evgeny: You could talk to people, right? And nobody knew that who you were talking to or nobody was tracking where you go, nobody was tracking who you talk to, and we could have genuine conversations because this whole ability to have genuine conversation with people is predicated on the fact that nobody else knows who is talking to whom, and that was the whole the whole premise, to return it to the to return communication to pre-internet state, almost, right? When we can trust the the environment.","offset":542,"duration":38},{"text":"Host: Incredibly well said. I mean, this is something that I bring up all the time. I think first off, people don't real... the human condition is to accept the status quo as something that's always been. But we've never lived in a society that is as digital as it is today and it's getting increasingly more digital, our lives are increasingly more online. And as a result, we've lost a lot of the implicit privacy and sovereignty aspects of non-digital life and we need to protect it. I like to distill it as I say: no privacy, no freedom, and no freedom, no wealth. They're all interconnected and that no wealth piece, I think, is really important when we're bringing it back to Bitcoin specifically, but if you don't have freedom, it's not your wealth, someone else controls it.","offset":580,"duration":50},{"text":"Host: I just want to apologize real quick, I did mess up the intro, um so I'm just gonna run through real quick. Today is March 20th at 1700 UTC, the current block height is 941454, current sats per dollar is 1,432. That brings us to a Bitcoin price of $69,792 and one Bitcoin will get you 15 ounces of gold right now, we're up on the one day, one week, and one month chart against gold. Um sorry about that interruption. I want to talk... so I didn't realize your background is publishing. Is it... were you act... what... were you an engineer involved with publishing? You came from the free speech side basically, not the privacy side.","offset":630,"duration":45},{"text":"Evgeny: It's hard to say what is my background. I I always enjoyed coding, but somehow it happened that I only did coding as a hobby for my own businesses. I probably am just entrepreneur who is doing what works. I spent a lot of time in different businesses, but yes, so I was in originally I was on publishing as a as an executive, not technology executive. I moved to the technology full-time about 12 years ago, or like a little bit more, maybe 14 years ago, and yes, I was working at MailOnline at on technology side. But yes, I came to this design from freedom of speech angle and interestingly SimpleX protocol was created, invented you can say, pretty much at the same time when Nostr protocol was invented.","offset":675,"duration":49},{"text":"Evgeny: But to me, you know you know this XKCD comic when one guy one nerd says to another or his computer has like you know that, right? Like 4,000, 906 bits of RSA encryption, it's kind of a trillion of years to break it...","offset":724,"duration":16},{"text":"Host: The $5 the $5 wrench the $5 wrench one, right?","offset":740,"duration":2},{"text":"Evgeny: Yeah, yeah. Go get go get $5 wrench, right?","offset":742,"duration":3},{"text":"Host: We joke around in Bitcoin that with inflation now the wrench is like $20, but yeah.","offset":745,"duration":4},{"text":"Evgeny: Yeah, exactly, yes. So and to me, to me like freedom of speech is just impossible if you cannot say say the truth without revealing who you are, right? So privacy is not about hiding, I think it's like it's in cipher from cypherpunk manifesto, right? You privacy is about selectively revealing yourself to the world, right? It's not about hiding, right? And depending on what you say, you may want to say it under your name or you may want to say it under a pseudonym, and it's essential to ability to criticize powers, it's essential to ability to share some uncomfortable truths, and that's what it all was about. But when we designed the protocol for private for for publishing that's resistant to attacks on individuals, we said oh, that's a messaging protocol clearly what we did, so why don't we make a messenger first?","offset":749,"duration":27},{"text":"Evgeny: Right. And we're just now approaching to the piece of the technology that we always originally wanted to build is effectively a publishing channels, large communities that can scale. We're like weeks away from launching the first version of scalable channels on on SimpleX network.","offset":776,"duration":34},{"text":"Host: Like a a better version of Telegram channels or Telegram groups, right?","offset":810,"duration":5},{"text":"Evgeny: Yeah, we had like large Telegram communities that literally tried to migrate to SimpleX network. Obviously, that didn't work because the current implementation scales to maybe thousands of members reasonably well after all the improvements, but not to tens of thousands as many Telegrams communities have. So yes, so we have a lot of interest from Telegram communities to use the network because because they would own it, right? We develop it in a way that each community can run on multiple relays, so in a way it's a it's a similar design to Nostr with regards to censorship resistance, but it's very different design with regards to privacy because to publish on Nostr you have to connect to relay, to publish on SimpleX channel, there would not be no direct connection, the connection to relay will be through the messaging network which means that privacy is preserved on a transport layer.","offset":815,"duration":51},{"text":"Host: Well, yeah, I mean, let's dive in here a little bit because to me, I've always considered the two protocols you... I mean, it is interesting how that worked out, right? That they both get birthed around the same time. That they're more complementary than competitive in terms of their feature set and use case. I mean, specifically Nostr is kind of trying to solve this one-to-many problem, it's a broadcast protocol first. If I want to broadcast to the world my thoughts, something like Twitter, right? Uh would be a comparison, that you know that's the kind of use case Nostr is trying to solve. And then also on top of that, kind of goes hand-in-hand, is an associated fixed identity that can be as public as you want it to be, right? You can be, you know, it doesn't it doesn't require permission to create these identities. You can have many disposable identities, but most people are using it in a way that they're connecting it to some elements of their real-world life and their real-world identity and then they're using it as a broadcast medium and discovery protocol.","offset":866,"duration":62},{"text":"Host: And then with SimpleX, you know, you have rotating identities, maybe you use different identities in fluid in-app with different people and different groups. And it's more like... I would compare it like if Nostr's like the soapbox that you're standing on the corner broadcasting your thoughts to the world, SimpleX is maybe the dark pub where you're with your local community having a beer and talking about really important things that maybe you don't want to be on the record about, but you just want to have free-flowing conversation.","offset":928,"duration":30},{"text":"Host: Now, when you start getting into the channels and stuff, it gets a little bit different, right? Telegram channels, I would say, Telegram's the behemoth in the room, that's why we're going to probably keep bringing them up, you know, they have two billion users at this point and they make a lot of privacy claims that technically are bullshit. Um so there's a a decent amount of overlap in the communities. But Telegram channels, so Telegram first started as DMs, then they had group chats, group chats I would say I would put more in the pub kind of scenario until they get bigger. Sometimes group chats get big, they're like a thousand-person group, then you're in like an auditorium maybe or something. But then Telegram channels are like more of a competitor to broadcast media, whether that's Twitter or Nostr or something like that, where the actual participants are not able to interact more so than maybe there's a comment box or maybe there's emojis, but it's really one person broadcasting to a bunch of people.","offset":958,"duration":58},{"text":"Host: And the reason I bring this up is because net-net you want those Telegram channels or large groups, I think you can kind of put them in the same... small groups and and personal messages, DMs, I think could be in the same group, and then large large groups and large channels can kind of be in the same group. Net-net, you want them to be end-to-end encrypted, but you always historically have the problem of all it takes is one person out of 2,000 people to be compromised uh or their their phone compromised or themselves be against whatever the group is, and they can be recording everything that's happening in there. So as you move into that feature set, how are you thinking how are you thinking about privacy in that scenario, right? Because like if if there's a thousand-person group, once again I think it's important that it's end-to-end encrypted regardless, it's the basis that everything's built on, but uh all if one journalist is in there or whatever just writing it up in the Wall Street Journal, then how much, you know, how you dealing with that? How you thinking about that?","offset":1016,"duration":64},{"text":"Evgeny: I think I think, Matt, you we all have tendency to conflate what what privacy means and here we're talking about two different aspects of privacy. I 100% agree with you that once group is free to join, right? And anybody can join, then it's unrealistic to expect any degree of content privacy in such group. And it's just dangerous to rely that there is a content privacy, because if you if you expect privacy but there is no privacy, then you may be saying something as if it is private conversation but like beyond thousand peop... that's, by the way, the basis of my scathing criticism of MLS specification, right? You know this message layer secrecy, I wrote...","offset":1080,"duration":41},{"text":"Host: I was gonna bring that up. By the way, it's not a surprise that you came out of publishing because your blog is one of the best blogs in tech to follow, by the way.","offset":1121,"duration":9},{"text":"Evgeny: Thank you.","offset":1130,"duration":1},{"text":"Host: But yeah, continue. You have a blog about MLS, which is what Signal wants to move to.","offset":1131,"duration":5},{"text":"Evgeny: Look, I think it's no, actually what Nostr what what was implemented on top of Nostr with White Noise is a different thing, right? Because they correctly identified the weak spot of MLS design and they completely side-stepped it because Nostr identity is the key so effectively authentication is bundled with identity. But that's a that's an I would even say it's almost like an edge case because in majority of systems people don't see key as identity, right? People don't are not hard-wired to to kind of equate identity to the key. I mean, Bitcoin community's very hard-wired to equate those things, right? Or just generally cryptocurrency community. But in normal world, identity is a name, right? And how do you know that this name...","offset":1136,"duration":41},{"text":"Host: Or a phone number.","offset":1177,"duration":1},{"text":"Evgeny: Exactly, so something secondary, something which is not cryptographically strong, and how do you equate this identity to something... so MLS MLS tries to solve the problem of key agreement in large groups, but it's kind of futile because it all depends on authentication service, which is still depends on provider, right? And the whole point of end-to-end encryption is to provide protect from provider. So effectively we need a trust to provider to protect from provider and to me it's like a logical impossibility. I only wrote this post because I was asked by like 20 different times members of our users were chasing me and asking me to explain why we're not adopting MLS at like after I explained it like 20 times I said all right, it's time I write something about this. So it's not like I had some kind of vested interest into into criticizing MLS. But the point is like once the group goes beyond thousands of members, there are two possibilities: it's a public group, it's publicly available and content is impossible to protect and there is no point trying in a strong to expect that it's protected.","offset":1178,"duration":61},{"text":"Evgeny: Another possibility: it's a corporate group, right? It's hosted on corporate servers, right? So however much we may all hate corporations, they exist, right? And if it's on their servers again, there's about protecting their servers and not end-to-end encryption.","offset":1239,"duration":14},{"text":"Host: Yeah, and to be clear here, Google has 190,000 employees, right? So you can easily imagine a 5,000 corporate group.","offset":1253,"duration":6},{"text":"Evgeny: Exactly, yeah, yeah. Exactly right, yes. So but why do they need MLS for this case, right? So they who are they who are they protecting it from, right? They they just need security of infrastructure, they need discipline, they need proper OpSec in Google, right? So they don't need MLS for that. So they may use it for some cases, but it's still it's still unclear why would they use it. So but reality the main thing about privacy is participation privacy I think, right? Because we've seen it all over and again that not only publishers are being like de-platformed, de-banked, high- fired from jobs, right? Or or worse, right? So like it doesn't matter that like the like if you're being dragged to court for whatever you said in public, right? It doesn't I mean, it's kind of great that legal system is not completely broken and eventually you are released without verdict, right? But the problem is that the whole process is the punishment, right? You're being dragged through interrogation, you're being dragged through court process, you have to waste money on lawyers, you have to engage with all that.","offset":1259,"duration":65},{"text":"Host: Time.","offset":1324,"duration":1},{"text":"Evgeny: Yeah, so so the process becomes the punishment, and that's the problem. So publishers kind of learned: if they publish something controversial, they have to do it behind a pseudonym, they have to do some reasonable OpSec to protect their identity, right? And and rather even if they say legal things, there are some strong and powerful people who don't like those legal things to be said, so they protect themselves. But their audiences may not do that, right? And we've already seen people in in various countries, it happens in some even European countries unfortunately, and it happens in in Russia, right? You like some thing and the next thing that happens...","offset":1325,"duration":37},{"text":"Host: You don't even comment on that.","offset":1362,"duration":2},{"text":"Evgeny: You don't even comment on that, you simply like something controversial and then you're being riddled with some fine for liking thing which in...","offset":1364,"duration":7},{"text":"Host: Or maybe you're not even liking it, I mean, we you can pull out this as an example... yeah, you're in a far- you're in a you're in a certain politician's Telegram channel and they're just taking a full list of who's in the group and using it against you.","offset":1371,"duration":10},{"text":"Evgeny: Exactly right, yes. And that's that's what's critically important. Privacy of participation is very... so so we currently live in a world when when some powers believe that they have to regulate not just what's being said, but also what's being listened to, and it's even more dangerous, right? So people want... and there is no law for that, right? There is no it's a completely outside of legal process, so it's completely outside of any precedent we've we've seen in history. So people reasonably want to protect their identities and they don't want to conflate their identities so the in Telegram if you follow 20 different channels then everybody knows all the channels you follow, right? There is a picture. The next thing that happens, you're branded as a conspiracy theorist and it's not the worst outcome.","offset":1381,"duration":43},{"text":"Evgeny: So and unfortunately Nostr has similar thing, right? So either I have to have a discipline and create multiple profiles, and it's just inconvenient, right? I have to think about it and I have to go through the hoops and like all the applications don't really make it simple to create alternative identities just for participating, right? So you end up just joining with the same identity and now everybody knows what what you're reading, what you're listening, what you're engaging with. So what SimpleX protocol achieves is that every time you join a community, it's a next set of keys, it's a next set of addresses, it's a next set of credentials, and your participation remains private.","offset":1424,"duration":44},{"text":"Host: If you want to. It's a new identity by default.","offset":1468,"duration":4},{"text":"Evgeny: It's not even a new identity, network doesn't operate on a concept of identity. I think I think, Matt, let me explain. I think I think it's important to understand that we didn't really build one thing. People think that we build one thing, but even if you take our earliest white paper, like written in 2021, even before the business was started, so it says very clearly: so we build a network for delivering packets between applications because this is was the missing bit in the World Wide Web, right? I was web developer, I just wanted a channel on my website.","offset":1472,"duration":38},{"text":"Host: Right.","offset":1510,"duration":1},{"text":"Evgeny: Right, so how do you do it? You need a messaging protocol to achieve this. To do publishing you need messaging. So we created a transport network that allows to deliver packets between the endpoints. And this transport network today already used beyond SimpleX chat application. It's used by low-end devices, people experiment with IoT devices using SimpleX network. Uh one substantial distinction of this transport network was if you if you look at the internet, internet is a transport network. What internet does: it it has endpoints, like devices, right? And it deliver packets to the endpoints, right? And internet uses what's called endpoint addressing, right? Each network each endpoint is assigned an address, right?","offset":1511,"duration":45},{"text":"Evgeny: We flipped it upside down this design and we said all right, we're not going to assign addresses to endpoints for various reasons. It compromises their security, it also compromises their battery consumption because if you think about mobile devices, right? They don't have fixed address. They keep switching between networks, they are assigned dynamic addresses. So the problem that network initial internet was quite symmetric, right? All net point all endpoints had addresses, right? Fixed addresses. And now internet evolved to the point that some kind of nodes, we call servers, they have fixed address, but all other nodes and user devices, they don't have fixed address, they have variable addresses. And that makes addressing really hard, it makes asynchronous communication really hard, it makes all application really hard, because in order to receive messages you now have to poll, you have to go to the server and ask keep asking do I have messages, do I have messages, do I have messages? People believe that's how SimpleX network works, but that's not how it works. The problem with this asking is that you lose power every time you ask.","offset":1556,"duration":56},{"text":"Host: Right.","offset":1612,"duration":1},{"text":"Evgeny: So we said okay, what if we design transport network in a very different way and instead of assigning identities to the endpoint addresses, we assign identity addresses to connections between the endpoints. And that's how SimpleX network is built. We simply built a packet routing network when address is assigned to connections between endpoints. So every time you want to connect endpoints, you create a connector and slap an address on this connector, and that's it. That's all the innovation was about, just flip the addressing scheme upside down and instead of assigning addresses to endpoint... you said the audience is quite technical, so I hope I'm not going too deep, but you tell me if I'm going too deep. So that's that's the whole idea, right? Assign addresses to connectors between the endpoints. And it solves two problem. It solves problem of endpoint security because the second endpoint address is known to the network, it can be attacked, and it solves problem of power consumption because if endpoint cannot have fixed internet address, it becomes problematic how to connect.","offset":1613,"duration":65},{"text":"Evgeny: And what SimpleX nodes are is routers that route packets between endpoints. So endpoints use these routers or rooters however, depending on which country you are in I guess, so to to deliver packets between endpoints. That's what we built. And then we said all right, I have experience of building open-source applications and I know that if you build a component that's not used by end users, it's really hard to make it valuable, it's really hard to make it into a everyday business, it's hard to get adoption because you're effectively build technological cog in a large wheel and you have to convince people to use... I'm talking about my library for data validation, right? I built like starting from 2015, I built a JavaScript library that now has close to a billion downloads every month because it's used probably by like, I don't know, most JavaScript applications depend on it...","offset":1678,"duration":51},{"text":"Host: Which one?","offset":1729,"duration":1},{"text":"Evgeny: It is, right? It's it's one of the biggest used libraries because it's in a dependency chain of many applications, but most people don't know it exists because it's a it's a little cog well, not so little, it's a highly reliable cog in the wheel that's surviving AI-led attacks right now, people try to find highly reliable, it's been highly supported, used by lots of people. My kind of thinking when we designed this transport network is we'll have to build application in parallel, we we cannot just build transport network and hope that it somehow used, we have to build some application that uses this transport network.","offset":1730,"duration":36},{"text":"Host: You're proving the use case.","offset":1766,"duration":2},{"text":"Evgeny: Effectively. So we build SimpleX chat. And what is SimpleX chat? SimpleX chat is a peer-to-peer messenger that uses this transport network. And the fact that SimpleX chat doesn't need identities for the end users is a direct consequences of transport network not having endpoint addresses and instead having connector addresses. So and these two things have been evolving in parallel. They live in different code repositories, they obviously SimpleX chat application uses library provided by SimpleX network software, but for us it's always been like two things are evolving in parallel and try to make this whole ecosystem work but together, right? But and that's that's the foundation of technology we built.","offset":1768,"duration":53},{"text":"Host: That makes a lot of sense to me. I mean, so the dream is that you have that there'll be many different applications and use cases on top of this protocol, but SimpleX is the first one and it's paving the way and proving how it works and how how resilient it is, right?","offset":1821,"duration":19},{"text":"Evgeny: Correct. SimpleX yes, correct, yes. We see SimpleX chat platform also as potentially a platform for applications similar to a browser, right? We're already playing with the idea of adopting programming language that will enable to have widgets in a chat that have some custom interactivity, etc., etc. So SimpleX chat in itself is also like a platform you can develop on, and people already develop chatbots, right? So there was like I was very excited to see that guys from Unstoppable, you you know this Unstoppable wallet people probably, right? So they developed a chatbot that allows to do swaps via SimpleX chat chatbot.","offset":1840,"duration":38},{"text":"Host: Yeah.","offset":1878,"duration":1},{"text":"Evgeny: And the good thing is like you're doing swap without connecting to any server, without exposing your IP address, without sharing your transport information, you're effectively... yeah, there is it's not completely trustless, of course. Yes, you you trust some swap providers...","offset":1879,"duration":14},{"text":"Host: Right.","offset":1893,"duration":1},{"text":"Evgeny: But SimpleX chat itself is rather trustless, right? And you can...","offset":1894,"duration":4},{"text":"Host: The communication protocol is is trust-minimized.","offset":1898,"duration":4},{"text":"Evgeny: Yeah, and private. Yeah. So so we and I mean, it makes sense because I do think, you know, I think the truth is somewhere in the middle and there's a lot of hype, but I do think the UX of how people interact with a lot of these things is moving to like that AI chat interface. We're like going from we're going away from the world of point-and-click and more to the world of ask and get, you know, where you're like just asking an agent for something. And then it's the question becomes and we've seen it with the OpenCola movement, which is the fastest growing open-source project, end-user open-source project of all time, and everyone's using Telegram or Discord, centralized and not private at all, right?","offset":1902,"duration":50},{"text":"Evgeny: 100%. And I I I agree with you. You know I was a CTO at startup that was selling fashion via WhatsApp, right? To me, commerce moving to messaging environment, all interaction with services moving to messaging environment, was like inevitable future of technology because this whole kind of point-and-click interface, they requires a lot of like thinking about what to point and what to click, right? And sometimes just want to ask, and the the constraint was always an intelligence of or or like some ability to interpret our requests if they are said in plain language, right? And we certainly past the point when we can get very valuable responses from LLMs, right? But the problem now is that the whole kind of communication pipes around LLMs are extremely insecure. Not just LLM provider can read what we say, but like all the transport environment around it is not quite secure, plus we are not private with that. So I think I think what we're building can be an interesting transport layer for interacting with LLM models.","offset":1952,"duration":71},{"text":"Host: Yeah, I mean, you especially see it the commerce as messenger in the developing world. Like whenever I'm in Latin America, it's very obvious. Um and I mean, to tie it back to Bitcoin again, the number one way that people do p2p Bitcoin trades is through WhatsApp, is through existing messengers. Not through like application interfaces. They're going they're going into WhatsApp, they have their broker-dealer or whatever and they're just messaging them directly there and exchanging information.","offset":2023,"duration":33},{"text":"Host: I uh so I want to pull it back for a second. The so the key here the the SimpleX servers, right? Anyone can run a SimpleX server. The they are they're routers, they're routing the communication between each other. Um how heavy is that burden and what trust is being put in the server by the users?","offset":2056,"duration":36},{"text":"Evgeny: The burden that router holds is very much dependent on the traffic. If you're just running a set of routers for a small group, you can have single core virtual machine with like half gigabyte of RAM or even less.","offset":2092,"duration":16},{"text":"Host: Super minimal.","offset":2108,"duration":2},{"text":"Evgeny: Yes, yes. It's it's extremely low uh resource consumption because all it does it receives a message. We our default implementation doesn't use any database layers. It can run on like it's just single executable that keeps the state in memory with a fall-back state in a append-only logs, so effectively it wouldn't lose the connections even on hard reset. It may lose some messages on hard reset, but if it if it terminates normally, it wouldn't lose any messages, it will persist them on stop. So we don't we don't run these in memory servers anymore for those that are processing up, we use Postgres uh database for that and we know quite a few people who migrated to Postgres database as well who run them in their companies or in their working groups, so they use use those routers with with Postgres database with high traffic. It's more efficient, but still we're talking about relatively low power uh machines or virtual environments that can transform millions of messages.","offset":2110,"duration":68},{"text":"Host: So I'm just trying to like I'm trying to key in here on what you perceive as... yeah, go on.","offset":2178,"duration":8},{"text":"Evgeny: You said you asked the second question was trust, right? The level of trust.","offset":2186,"duration":3},{"text":"Host: Yes.","offset":2189,"duration":2},{"text":"Evgeny: I think I think we probably thanks to our advisor, we have been very explicit about trust model. It's in our white paper. So servers obviously can routers disrupt communications, right? So we trust routers not to do it. But what they cannot do is important: they cannot compromise end-to-end encryption because they do not participate in key exchange, key exchange happens out-of-band. They cannot drop messages undetectably, they cannot insert messages undetectably. So the best the server can do is just delay communications or like send lots of spam traffic to the end-user device.","offset":2191,"duration":45},{"text":"Host: It's like reliability and uptime is the trust basically, right?","offset":2236,"duration":5},{"text":"Evgeny: Yes, yes, effectively yeah. And with server with the routers that we run we had very we had no much problem, right? I had like very funny situation when somebody who I connected like on a day of the first mobile app launch for years ago, recently messaged me and said hello, I said okay this is like four years ago, the connection somehow survived through all this time. So yes, so we we aim to minimize the trust and also if initial design had a single router in a message passing chain and obviously even though on a SimpleX protocol layer servers don't have identities there is IP protocol layer, right? And if server can if router can observe IP address of one party and IP address of another party...","offset":2241,"duration":46},{"text":"Host: My next question. Yep.","offset":2287,"duration":3},{"text":"Evgeny: Then they can see who talks to home. So on IP address level, right? So we changed the routing protocol so now messages are passed always through two routers, so even though the first router in a message passing path... okay, so each conversation we use four routers, right? When I say two routers, it's a one-way communication, right?","offset":2290,"duration":19},{"text":"Host: Okay.","offset":2309,"duration":2},{"text":"Evgeny: So I can be messaging you through one router and using anour another router to connects to yours, and when you're replying, you also would be using two routers. So effectively you choose the routers to receive messages from and I choose the routers to forward the messages to your router.","offset":2311,"duration":18},{"text":"Host: And they would all have to collude to connect the IP addresses.","offset":2329,"duration":3},{"text":"Evgeny: It's really hard, yes. They'll have to and it's really hard because it means they'll have to do some coordinated protocol changes and introduce some additional metadata in the message envelopes. So I would say it's not impossible, of course, if routers collude they can do timing correlation and compare those things. But the technical bar is quite high. And the clients are already programmed to use router not just different routers but routers of different operators. We introduced the concept of router operator, app understands that, and it will already has two preset operators right now, there will be more, so and if you add your routers then there will be third operator. So app knows this concept of not just router but of router operator and it chooses different operators, so different entities.","offset":2332,"duration":70},{"text":"Evgeny: That was my biggest criticism of Tor by the way, because Tor network is built on the idea that you choose three relays on on a packet passing path, right? But you don't control the relay choice, or you have limited control of relay choice, right? And we know that there are large entities operating those relays on Tor network, right? And we know that there are entities who sell traffic data as well, so effectively this whole kind of idea that different servers, different relays means that they don't collude is kind of questionable, right?","offset":2402,"duration":32},{"text":"Host: Right. the whole model is based on at least one honest actor in the route, but if it's all the same actor, then the the assumption breaks down.","offset":2434,"duration":8},{"text":"Evgeny: Exactly, yeah, and given that you have limited control of those again, there are some advanced settings, but by default you don't choose and it means that it means that you potentially don't don't have privacy of of the circuit. I think it's important thing for SimpleX protocols like if you compare with Tor, right? On Tor you create a persistent circuit. So you build a circuit and then all the packets come through this circuit and then this circuit can see all the packets on they understand they all understand that's the same circuit, it's persistent circuit, right? Uh so even though like for example it's a session design, right? So you may message different people through this network, but uh who the the server that receives your messages would know that they come from the same person, because they come through the same circuit. And you understand, right? Like because the session is the same, different packets come out of the same session, it means that you know at least that it's the same person communicating all these different contacts, right? With SimpleX network we designed it differently, we do the same as mixnet do, effectively there's no circuit, there is a packet level anonymity and the recipient router it doesn't know whether packets come from the same session or from different session, so it only knows that they come to different recipients, right? And the forwarding router again it doesn't know how many addresses would be because there is end-to-end encryption between sender and the receiving router, going deeper into technical details. So effectively they cannot establish who talks to home on a cryptographic level because the each each packet is anonymous in this message passing.","offset":2442,"duration":110},{"text":"Host: That's awesome. Yeah, makes collusion significantly more difficult by default, which is key because defaults are what matter, most people are not going to actually be changing things. How do you how do you handle the like the discovery problem? And by discovery problem I mean it can mean a bunch of different things. What I mean is: you message me and I'm connected to a different router than you are. How does the path get determined? Like how does it how does it get to me? Right? You know what I mean?","offset":2552,"duration":107},{"text":"Evgeny: Your address, you publish an address, right? So we don't have have anything in the protocol or in the app to help me discover your address. That's the future uh...","offset":2659,"duration":12},{"text":"Host: That's that's a separate discovery problem, that's not what I'm talking about here. You went to my website and there was a there was my my address was there. So we just used a traditional website for that part of the discovery problem.","offset":2671,"duration":14},{"text":"Evgeny: Correct. The address... the way it works now, the way it worked before, the address itself contained the router address.","offset":2685,"duration":8},{"text":"Host: Okay.","offset":2693,"duration":1},{"text":"Evgeny: The way it works now, the address contains a a reference to an encrypted piece of data which contains the reference to the address which I have to message. So the address itself cryptographically bound to the point I have to forward my messages to. So your your router is determined by your address, and the router I choose to forward messages to this address packets is randomly chosen from my configuration from my client configuration. So my client says, okay, I will choose any router, but it will try to use router of another operator than you use.","offset":2694,"duration":40},{"text":"Host: Right.","offset":2734,"duration":1},{"text":"Evgeny: And when I send the first message to your address, when the client sends the first message, it includes the reply address end-to-end encrypted.","offset":2735,"duration":29},{"text":"Host: Got it. So it gives you a discovery path basically to get...","offset":2764,"duration":4},{"text":"Evgeny: Yeah, yeah, your client learns where it can reach me. When I message you, it's all it's all works rather seamlessly and on a technical level discovery is not a problem. Obviously, the whole idea is like for for us, right? We have a support team member who answers users' request. The most common request is how do I connect to people? Like where do I where do I type the name? Where do I type the phone number? How the hell like how is it even working, right? So the whole idea that you have to create a link and then share the link with somebody else in order to connect is is alien to absolute majority of people. We're doing a lot of redesign of this initial connecting experience right now to to make it easier to understand. We don't change anything in...","offset":2768,"duration":39},{"text":"Host: I will say the in-person is more intuitive than not because in-person you just scan a QR code boom.","offset":2807,"duration":6},{"text":"Evgeny: Yes, yes, yes, yes. But that was like literally version one of the app had nothing else, right? It you could scan a QR code and you could start sending text messages, that was what we released four years ago.","offset":2813,"duration":15},{"text":"Host: But yeah, that makes sense to me. Okay, so one of the things that MLS does attempt to solve is uh is this idea of groups scaling poorly in encrypted chat. So a lot of times the most basic and you know you can correct me where I'm wrong here, my most basic interpretation of how standard encrypted group chats work, whether it's Signal or Matrix or any of the existing ones, is I'm basically if there's 50 people in the group I'm sending 50 individual encrypted messages every time I'm sending a group text, but the UI is making it look like it's just one message in a group text. But in the background what's really happening is every message has to be sent to every group member and private you know encrypted separately. My understanding is part of the MLS spec is trying to solve that scaling limitation because maybe it works at like 20 people, maybe it works at 50, but once you get to like 2,000, 5,000 people, it's insane, you're like basically DDOSing each other. Um and then the servers would obviously have a lot more overhead attached to them. So how are you thinking about that? Is that a real limitation? Is that and how are you mitigating it?","offset":2828,"duration":82},{"text":"Evgeny: Okay, so there are several questions, I'll try to answer all of them. So first, let's not that's not that's not exactly how Signal works, right? You're not sending messages to each member. What you do is you generate a random key for this message, and then you encrypt the key itself for 50 people, but the message is encrypted only once. So for example if your message is like 200 characters, but your key is rather small, you don't need to send message 50 times and you don't need to send message to 50 people in Signal. You encrypt message with the same key and then you encrypt key with different...","offset":2910,"duration":26},{"text":"Evgeny: I think realistically, to me, pairwise ratchets, like pairwise double ratchet, so for each member you encrypt separate key, it scales to quite large numbers. It scales reasonably well to even 5,000 recipients, and that's how we see large groups with end-to-end encryption in future. Not MLS spec, but effectively what Signal does. So Signal works... Signal limited it with 1,000 because they have like tens of millions of users and some of them are on really bad internet and they don't want to have and very low power devices, so they don't want to go beyond 1,000 with end-to-end encrypted groups. But I think even 5, 10,000 is a tractable approach if you only encrypt keys and not the whole message. But beyond that it's just like, it feels like you're not... you cannot remember 10,000 people. You don't know who's in a groups, you don't know who reads it, like what's the point of end-to-end encryption?","offset":2936,"duration":61},{"text":"Host: Right. So then we're moving into the channels, right?","offset":2997,"duration":2},{"text":"Evgeny: Yeah, effectively.","offset":2999,"duration":1},{"text":"Host: So then how are you envisioning the channels set up and what does that... what does that look like in practice?","offset":3000,"duration":6},{"text":"Evgeny: From user experience point of view, you just it works in a same way. You scan the link, you join the channel, you start receiving messages. The difference is that if you have right to send messages to the channel, then instead of sending it to whatever number of subscribers—1, 10, 1,000, 50,000 subscribers—you send it only to chat relays and they do rebroadcast.","offset":3006,"duration":25},{"text":"Host: The server.","offset":3031,"duration":1},{"text":"Evgeny: It is not exactly the server. It is again, it's some sort of a message... it uses client-side technology because you are not connecting to this chat relay over the internet. Effectively chat relay is a messaging client that cosplays or roleplays as a server, right? That is a router, right? So it receives your message as a SimpleX client, right? And it has... it's a special kind of client because you're never connecting to it directly. You don't know its IP address, you don't you only have its SimpleX address, forwards your messages through SimpleX network. You connect to it via SimpleX network and it forwards the messages to SimpleX network. So unlike Nostr relays, you never build direct internet connection to this relay.","offset":3032,"duration":47},{"text":"Host: Okay, I mean to help me understand, maybe it's more helpful because if I don't understand it then it's less likely other people understand it. Let's say, I don't know, some politician wants to has a 100,000 person channel, right? Wants to broadcast to his audience 100,000 people big. What does that look like? Is he running his own chat server and who's running the chat relays and how does that all fit together?","offset":3079,"duration":31},{"text":"Evgeny: It's not different from who runs SimpleX network routers. It can be... there will be some chat relays that run by third parties pre-installed in the app. He can run his own. And each channel can have multiple. Our idea is that you want more than one chat relay in each channel for redundancy, for censorship resistance, for mitigating any trust issues. So the way we designed the protocol and already implements it is that some critical messages are signed by senders so they cannot be faked. Most messages are not signed, but they are kind of delivered redundantly and recipient clients can simply see if some relay decides to invent messages or change messages or... so we've like, that's in case they are not end-to-end encrypted, right? We're talking about public channels at this point.","offset":3110,"duration":53},{"text":"Host: Right. The big thing with public channels is not is not necessarily encryption of the content. It's verifiability of the content that it hasn't been changed in transit and privacy of the participants. Correct?","offset":3163,"duration":15},{"text":"Evgeny: Correct, yes. And end-to-end encryption between this relay and the participant helps privacy, right? Because there is end-to-end encryption between relay and participant all the traffic information is not uniform so transport network cannot observe the content, it cannot correlate the content, it cannot understand which groups you are receiving content from for the same reason it's end-to-end encrypted. So end-to-end encrypted and end-to-end between these broadcasting relay and the members helps privacy of the members. Because without end-to-end encryption transport network could see content, right? And if transport network could see content they know what you're reading, right? So this end-to-end encryption is very important to provide participation privacy.","offset":3178,"duration":51},{"text":"Host: Right, and then the members are known.","offset":3229,"duration":2},{"text":"Evgeny: Exactly, yeah. But and with end-to-end encryption transport network can see nothing, and chat relays don't see your IP address so they kind of protect you from each other.","offset":3231,"duration":11},{"text":"Host: And then from the... what why aren't all you mentioned so the broadcaster, let's call him the broadcaster in this in this scenario, the guy who owns the channel that's sending out the messages to people. You said every message isn't signed. Why isn't every message signed? Is it a is it an efficiency thing or...","offset":3242,"duration":23},{"text":"Evgeny: No, there is no cost in signing messages, but it's always a double-edged sword, right? So like one of the qualities in communication is deniability, right? So the double ratchet protocol has this quality called repudiation, which means that it's not possible to prove to a third party that you actually ever sent this message because the message is is encrypted by the key that the recipient also possesses. The second you start signing the message you're effectively putting your signature on the message saying \"I actually said that\" so you lose the deniability.","offset":3265,"duration":40},{"text":"Host: Because it's verifiable.","offset":3305,"duration":2},{"text":"Evgeny: Yeah, it's not just it's not just verifiable it's also non-repudiable. So you cannot no longer say \"I've no idea where this message come from, I never sent it\" like...","offset":3307,"duration":11},{"text":"Host: We see that issue with a separate rabbit hole that I've dove down in the past, which is the idea of of of more modern voting techniques that would involve a signed receipt, and that issue there is you could have an employer or a husband or a government come to you and be able to with with no doubt whatsoever know how you voted and then pressure you accordingly. Because on the surface it seems like such a great idea. It's like, oh, I should have a verifiable receipt so I can make sure they're not faking the votes. But then all of a sudden you realize why votes are supposed to be private in democracies.","offset":3318,"duration":40},{"text":"Evgeny: Exactly right. So we we effectively saying \"okay so some critical like for example if the command you are sending to chat relay is to remove a member it should be signed, right? because the consequences of of relay removing a member are irreversible so you have or for example you say I want to delete a channel, right? This action requires your signature because it's irreversible and it's destructive, right? So everything irreversible and destructive we add signature by default as a requirement and receiving clients will simply refuse to process the message if it's not properly signed. And your key is cryptographically bound to the channel link. So this is like we we build this whole kind of cryptographic trust chain with the channel owner that when the member when the subscriber just joins your channel they already get the key from the link, it cannot be faked, so effectively they know your credentials for this channel from the get-go from them joining, right? Relays can't fake it.","offset":3358,"duration":66},{"text":"Host: And they have that locally.","offset":3424,"duration":1},{"text":"Evgeny: Exactly, yeah. But for messages we want to make it an opt-in. If you really want to sign important messages then maybe we would provide it as as an option or as a feature, but we I believe it's wrong to make it a default. Because think about that. Let's say you already have five relays in a group, right? These five relays are operated by different entities, right? If one of them decides to substitute the message the recipient client will see it and say \"wait what's going on here?\" right? \"So there is some kind of trust violation here.\" Four said one thing and one said a different thing. Exactly. And I think it's actually better than signature because that gives them similar degree of trust right probability of four relays colluding if they are run by different parties, right, is low. Right? And especially if the politician himself runs the relay, right? So then then what's the chances of it being replaced? But at the same time the message cannot be used as you said as a signed receipt which kind of which can be used as a proof of of doing that, right? So like it...","offset":3425,"duration":74},{"text":"Host: That kind of makes sense to me. It it still solves the main underlying problem which I think is going to become a bigger concern is as digital communications become the main way people digest information, there are serious real-world consequences on what influential people say and we've seen this. Trump sends out a Truth Social post and military is moved and markets react and meanwhile there's zero way for me to know that Trump actually sent the Truth Social post, right? There's a bunch of men in the middle that could can fake that. And we haven't seen a large-scale repercussion yet of that type of attack, but I assume it's going to happen sooner rather than later and so it's important that there is at least some level of verifiability or trust here, and I see how you're kind of trying to there's trade-offs on both sides.","offset":3499,"duration":65},{"text":"Evgeny: Exactly. You know there is a value in being able to sign important messages 100%. But I believe it's wrong to make it default and rather than opt-in because like, okay, so we are like imagine this situation, right? You talk to me and we record this conversation people can listen it and obviously nobody of us can deny that this conversation happened, right? Imagine a different situation, we meet in a cafe we have a private conversation we really don't want this conversation to be public, right? Who knows what we may be discussing, right? It doesn't necessarily we're conspiring we can be just having a private conversation about our lives, right? And if any one later quotes that \"he said that\" it's unprovable. We have we have plausible deniability. Now imagine if it happens in encrypted messenger. If you use Signal you also have plausible deniability because or SimpleX because messages even though are end-to-end encrypted they are repudiable. So there is no way to prove that you actually sent this message. And we haven't seen what I hear the criticism I hear from technologists is that nobody has ever used this concept in courts, it has no legal standing and so on and so on, right? But reality is Signal is the first widely used messenger that pioneered repudiation as a as a cryptographic quality in message sending, and it only happened like 10 years ago.","offset":3564,"duration":97},{"text":"Host: Right.","offset":3661,"duration":1},{"text":"Evgeny: And before anything becomes understood by legal systems we usually observe like many many of decades of not understanding what it is and how it can be used and what legal consequences of this is. So yes, there I don't know any precedence of this concept being used but it doesn't mean it's not valuable potentially. So we we like to stick with repudiation as a cryptographic quality of the protocol.","offset":3662,"duration":28},{"text":"Host: Yeah, I mean it's it's the difference between like building the technical foundations versus real-world repercussions and the real-world repercussions always happen later. I mean this is the first administration that I know of where we've seen official business happen on Signal and there was that leak of that group chat, right? And I'm sure a bunch of those group members are grateful that at least they can technically say that they didn't send a message in there whether anyone believes that they didn't send the message is a different thing because you kind of have to modify some things in Signal to do that.","offset":3690,"duration":41},{"text":"Evgeny: Yes.","offset":3731,"duration":1},{"text":"Host: I mean and to your earlier point about different types of conversations I mean this is a perfect example right because we had a conversation on SimpleX that was off the record and then this one I will be hashing and signing with my Nostr key because as someone who has spent a lot of time broadcasting my thoughts and having candid conversations like this on the podcast it does frighten me that we could have AI deepfakes and basically me saying anything without no verifiability. So I really take that verifiability piece very seriously when it comes to these types of conversations. Like I want there to be for this conversation I want there to be a historical record of truth that if some AI in 5 years makes us say whatever it wants us to make us say you can go back and see that hash-signed version of the MP3 and know that it hasn't been changed and that's what was originally said, right?","offset":3732,"duration":67},{"text":"Evgeny: Yes.","offset":3799,"duration":1},{"text":"Host: Okay, this is all fascinating to me. I'm really enjoying this conversation. Uh, the the big one that will come up next is, which I mean I see all the time in distributed systems, is okay, so the system relies on people running servers and relays and whatnot. Ideally the system works best when there's many many operators doing that. And this is something that Tor for instance, I think on a widespread scale, has had a lot of issues with, right? Having more independent operators running these things. Bitcoin we've as it's a it's a major contention point on Bitcoin making sure that Bitcoin nodes are easy and accessible to run so people can use it without relying on a trusted third party. We see it in Nostr with relays. So how are you thinking about this like fundamental problem, right? Which is you need as many people running servers as possible. More the better, the more the better servers and so how do you see that scaling?","offset":3800,"duration":71},{"text":"Evgeny: Right now we see lots of communities running their own routers in SimpleX network. It's I think there are some Bitcoin communities, I think there are some Monero communities that do. There are some discussion groups that run around servers they advertise it on their website. We we cannot know exact number but I think conservatively there are over 1,000 routers in SimpleX network at this point. So and that's fine and it works and people get their own sovereignty and autonomy and independence of anything that that we may be doing or anybody else can be doing which is great. The downside of this model is that your your router because it has fixed endpoint address, right? Like the whole point of SimpleX network is protect your endpoint address, right? But if you run a router this router becomes effectively your address, right? So like if if if it... if it if it is run on public network then obviously anybody knows the IP address they somehow can link it to your identity and maybe that's not what everybody wants. If you run it on Tor then it's potentially not very usable. Even though we build internet-to-Tor routing capabilities. So for example if you send messages to Tor router it will be delivered even if you don't use Tor because SimpleX routers would they can they can connect to Tor routers. Right? So even if a router is only on Tor network then SimpleX router that has internet address will be able to forward message to Tor network. That's how that's why network remains interconnected, right? So you don't have to use Tor to deliver messages to Tor-only routers. And it's all great. But I think long-term this is not really scaling because I don't know you probably seen Moxie Marlinspike Marlinspike said once that people don't want to run their own infrastructure.","offset":3871,"duration":110},{"text":"Host: Yeah, the founder of Signal.","offset":3981,"duration":2},{"text":"Evgeny: Yes, yes. So my my view was always if we want privacy to be a norm then we have to be building technology that everybody can use, right? People who don't want to run their own server, people who don't want to think, who want to use just default software out of the box and get this privacy. And that's the only way it can be normalized, right? And I think it kind of resonates with what Cypherpunk manifesto author was writing later, right? So for just writing code is not enough. It was his later letter not the manifesto. That we have to have acceptance in the society, we have to have wide usage of those technologies. We effectively see adoption as a as a privacy feature. So so this whole idea is that in order to be autonomous you have to run the server it it is not it is not it is not scaling to the future. So so that's why we want to build a network when hundreds of commercially incentivized operators can run routers and be making more money from doing that from the network than they are spending money running this infrastructure. Bitcoin obviously has in-built monetization solution, right? You run the node it potentially can mine Bitcoin and it kind of at least covers the cost of operation.","offset":3983,"duration":86},{"text":"Host: Well, we kind of lost that to be honest. I mean most nodes are not mining nodes now.","offset":4069,"duration":5},{"text":"Evgeny: Yes, I understand that yeah, but at least you get indirect benefit that you can you can use the network without trust which is kind of what we're holding on to at this point. And then also if you hold the money the money tends to increase with purchasing power so we have that going for us.","offset":4074,"duration":18},{"text":"Evgeny: I'm I'm not quite I've I've seen some talk a couple years ago at a conference when somebody was talking about running Bitcoin miner at home and his idea was that \"okay, we can't make profit from running the miner but we can convert electricity costs to non-KYC Bitcoin and it's a great thing and let's do that.\" Right? So effectively you're...","offset":4092,"duration":22},{"text":"Host: No, we do have that aspect going well for us. And there actually is a company called Futurebit that like puts the node and the miner together in one convenient package that you can run at home. But a lot of those miners just to be clear here, and it's, you know, it's kind of a tangent it doesn't really matter that much for our conversation, a lot of those miners are they have the heater in their home but then they're connecting to someone else's node, right? So it's not their node they're not running the actual node infrastructure. More are, which is awesome to see. But yeah, fair enough.","offset":4114,"duration":90},{"text":"Evgeny: So for for SimpleX network we see the imperative to create a commercial model when anybody who wants to provide infrastructure can make more money from providing this infrastructure than running this infrastructure cost.","offset":4204,"duration":15},{"text":"Host: A financial incentive.","offset":4219,"duration":1},{"text":"Evgeny: Yes, 100%. And we don't want to create any blockchains to do it. We don't want to do any mining operation. we don't want to create any... but we still need a solution and we've been discussing it with the community for quite some time. So the idea is that to answer how servers are paid we have to answer first the question is what what in the network itself is paid, right? When we were just starting developing this we were thinking okay maybe some premium features can do that maybe something else can do that, right? But then we've seen what happens with Telegram Premium. We keep talking about Telegram, right? To me Telegram...","offset":4220,"duration":33},{"text":"Host: Everyone's favorite.","offset":4253,"duration":1},{"text":"Evgeny: To me Telegram Premium is is a proof that premium model for messaging application is a dead end. Because yes you may be generating revenues and yes you may be developing the nice features but reality what happens is you're fragmenting your network, right? You very quickly as a provider of this application realize that in order to make profit you have to make your application unusable.","offset":4254,"duration":24},{"text":"Host: Yeah, the best features need to be behind the paywall basically.","offset":4278,"duration":3},{"text":"Evgeny: Uh pretty much all of them. So you already there already features when I can't message people until I have or I can't make call to this people and it's just like not because they choose to but it's just like it's just fun, right? So and to me that's kind of very much a dead end for communication network. Imagine like a web browser, right? We what we built we take lots of inspirations from the web. We we say often that what we built is a missing part of the web, the messaging part. We say a next web, right? Because web has never created messaging solution as part of it. So if you look at the web, how web is monetized? Users don't pay for the browsers, right? At all, at all. Users don't pay for using the web, at all. Uh, people may say \"oh yes we pay ISPs\" but it's different story. ISP is not the web, right? It's simply a transport network that connects you to the website. But the web itself like all the DNS systems, all the infrastructure that allows web to function, it's free, right? So who pays for all that? The answer is very simple: websites pay. People who want to host the websites they pay and because every content distribution network has this distribution when 5% of websites generate 90% of traffic.","offset":4281,"duration":77},{"text":"Host: Right.","offset":4358,"duration":1},{"text":"Evgeny: What it actually means is that it's enough to charge this 5% of websites and everybody else can be free. Right? You don't need to pay to host a small website today, right? You just go you create account you can pay either $1 a month or nothing or...","offset":4359,"duration":16},{"text":"Host: Right, it's subsidized by the big guys.","offset":4375,"duration":2},{"text":"Evgeny: Exactly, yeah. So the whole web is subsidized by the big websites, so 5% of websites create all the carry or maybe 20% of the websites carry all the costs of the web. And that's why we see channels as so important because we see channel on SimpleX network as equivalent of the website. And we believe as this part of the network grows, the the traffic distribution, the cost distribution will be similar. So uh, 10% of large channels will generate 90% of the traffic. Right? And that's who they should that's who should be paying. And they'll be paying, right? because if you say \"I'm a politician I want 100,000 100,000 people audience,\" right?","offset":4377,"duration":31},{"text":"Host: Yeah.","offset":4408,"duration":1},{"text":"Evgeny: If your choice is to be on the platform that can shut you down because the current administration doesn't like what you say, right? We've just seen it happening with Trump before.","offset":4409,"duration":12},{"text":"Host: Yep.","offset":4421,"duration":1},{"text":"Evgeny: Right, so before Twitter acquisition before...","offset":4422,"duration":3},{"text":"Host: Sitting President of the United States gets banned from Twitter and Facebook.","offset":4425,"duration":4},{"text":"Evgeny: Which is ridiculous, right? So and one of the...","offset":4429,"duration":2},{"text":"Host: And he ended up buying and building his own social media network.","offset":4431,"duration":4},{"text":"Evgeny: Exactly, yes. So what what we see is a much cheaper solution. So if you want a channel that's sovereign, that you actually own, you have to pay for it. You have to cover infrastructure costs, you have to cover discovery costs, you have to cover some costs. And that's the business model that we see for the whole SimpleX network. So messaging will remains free forever as a as a add-on service effectively, and small channels and communities can exist for free, but large channels and communities carry the whole cost. And we just need to find a solution that allows to transfer value from those channel owners to the infrastructure owners in a way that kind of preserves privacy and security of all all participants within within what's possible. So so that's our view. So our view is not... our view for the network is not that it's enthusiast-run network, but it's a professionally run network, but it's run by so many independent facility and infrastructure providers that trust is minimal because it's distributed, right? If each conversation you uses four different companies, right? And those companies are rotated on a weekly basis then your dependence on each particular company is extremely low. They get profits from doing that but they have no control over your conversation.","offset":4435,"duration":85},{"text":"Host: I love that. I mean look, I love from I wear two different hats. I wear my charity hat with OpenSats and I wear my for-profit hat with 1031 where we invest in for-profit businesses that are often built on top of open-source stacks. And so I see both both worlds in the greater open-source movement, the foundation-led, charity-led and then, you know, and then the opposite side, which is the for-profit-led. And oftentimes you see foundations get spun up and run donationware. I mean we've seen that with Signal is probably the best example. And it's probably the easier path for these type of things in the short term. I think long term they scale much worse. Uh, they're not sustainable. You have to go out and constantly seek donations. And the incentives aren't necessarily aligned that well. I think one of the issues you start to see is longer term it's like, okay, the employees or the stakeholders of the foundation don't necessarily need to see the thing grow significantly. And the reality is in the truth is in the reality, which is Signal is probably one of the most successful nonprofit privacy, freedom-focused projects and it's found massive success but it's at about 100 million users, maybe less. And then you have things like WhatsApp that are in, you know, 3 billion plus, you have Telegram that's 2 billion plus. And those are for-profit ventures. and I don't think it's a coincidence that those for-profit ventures tend to have significantly bigger user bases. I think it's an incentive alignment thing. So I do I have a lot of respect that you've tried you're trying to go this for-profit ethical for-profit sustainable approach. And I kind of want to dive a little bit deeper in here.","offset":4520,"duration":105},{"text":"Evgeny: Look, I think I think the challenge is that I I I can go philosophical here, Frank. I think it all comes from people seeing most choices as binary.","offset":4625,"duration":10},{"text":"Host: Right.","offset":4635,"duration":1},{"text":"Evgeny: So I have heard this in my life million times: you have to pick a lane. Right? And I refuse to pick a lane. Right? When I was building my you know, I was building like I will go again to this library that nobody knows about but it's a good example because when I was starting this library there was like 12 different competing libraries and they all were either super fast and really badly complying with the specification, or very very slow and somewhat better complying with specification. So I said, alright, how how about I just build one library that is fastest and also best in compliance with the specification? And everybody was laughing at me saying \"this is the classic also XKCD comic, right? There are 14 better frameworks, let's make one more framework.\"","offset":4636,"duration":45},{"text":"Host: Here was the 15th.","offset":4681,"duration":1},{"text":"Evgeny: Now we have 15 better frameworks. Like I was sent this comic by like 10 different people in my life. Right? But reality what I learned from this kind of retrospectively again, right? So if you refuse to compromise on important trade-off, because trade-off is artificial, right? The choice between fast and standard-compliant wasn't the real choice. It was just easy path, right? It's just harder to build something that is both fast and standard-compliant, but it's not impossible. So I built a library that came to be the only library that people use today for data validation in JavaScript world because the choice was eliminated. And again, same between like private messenger versus convenient messenger, right? So people have been trying to pigeonhole what we're building into like like some people say \"oh you're building a private messenger you shouldn't worry about convenience really you should add more privacy features,\" right? That's half of our user base what says. And some other half of user base says \"you're focusing on privacy too much you should compromise on privacy...\"","offset":4682,"duration":62},{"text":"Host: It's not convenient enough.","offset":4744,"duration":2},{"text":"Evgeny: Yeah, and instead like for example the fact how you discover people some of the hurdles, or for example that we still don't have multi-device in the messenger. I say, whatever, compromise on privacy build multi-device everybody wants multi-device. I don't know, I think my brain is wired against making such compromises and we instead find proper solution that deliver both without compromise. And it's obviously slower. The the downside is like what you compromise on is time to to working product. That's that's what have to go, right? But I think reality is by taking this slow... right, I mean...","offset":4746,"duration":33},{"text":"Host: Yeah.","offset":4779,"duration":1},{"text":"Evgeny: Signal's the perfect example here, right? Because the easy path was saying, \"okay, let's just use phone numbers as discovery.\" That's what WhatsApp does, that's what Telegram does, we can do that, my grandmother can use it. And then you're stuck.","offset":4780,"duration":14},{"text":"Host: Yeah.","offset":4794,"duration":1},{"text":"Evgeny: You took the easy path and then you're stuck with that building block. Exactly, yes. It's not something that you can revise later, it becomes a foundation of your architecture. It's used everywhere, it's pervasive, it's not removable. So I think what we're trying to build is a communication protocol and product and transport network that's used by everybody. And yeah, it may take decades to get there, but I I still have time. So and talking about private like for-profit versus non-profit, going back to your question, right? I also see it as a false trade-off, right? I was when we took venture capital money, we took it like without any control provisions. It's a proper Y Combinator SAFE agreement, there are no board seats, no control, right? I have to chase my investors for advice and they are very busy people, right? But reality is we run our business however we want. And they just trust because, you know, I think venture capital has changed dramatically after some major successes when most venture capitalists arrived to conclusion that they have to let founders do things they disagree with. Because that's the only way founders... I mean Facebook was a big one. I mean obviously it's kind of a weird example to use here because they turned into one of the most evil companies.","offset":4795,"duration":74},{"text":"Evgeny: Yes.","offset":4869,"duration":1},{"text":"Host: But Facebook early days was, \"we trust,\" you know, the investors were like, \"we trust Mark, Mark is the leader of the ship, we're not going to take any control.\" But before that historically it was like VCs would come in and they would just take full control of a company and then push the founder out.","offset":4870,"duration":16},{"text":"Evgeny: Yeah, Apple would be a classic example, right? And in this pushing the founder out pushed the Apple to the brink of bankruptcy so they had to bring the founder back, right? So so yeah, so we see world has changed. investment doesn't mean control. And yet we've been like vilified by everybody like that we did it, right? So I had to write a blog post.","offset":4886,"duration":20},{"text":"Host: For-profit capital.","offset":4906,"duration":2},{"text":"Evgeny: Yeah, I had to write a blog post about why privacy becoming a norm requires venture funding. Because to me, privacy becoming a norm requires building a mass-market, widely adopted product. The problem with this premise is that it is the costs are exponential. It's like getting like 10x more adoption is not necessarily... you know what I mean, right? So you simply cannot build a mass-market, widely adopted product on a grassroot movement. And that's what Signal observes, right? Foundation model doesn't scale, donation model doesn't scale. So either you build at some point the model that allows it to be a business that generates profit, right? And again when people say \"oh you're for-profit company it's a bad thing,\" my response was always like, what is profit, right? It's either it's independence, right? That's what I think Bitcoin community, privacy community believes in is in independence, right, in sovereignty, in ability to make their own choices. But nothing of this is impossible if you are existing handouts, right? Because you're dependent on whoever gives you handouts, right? Children are dependent on parent until they start earning their own money, right? People who get whatever social security benefits they are dependent on government to tell them what to do. And it's not a good thing. So any organization that wants to be independent has to make profit. Otherwise it becomes dependent on whoever gives its money. And that's another dark side of the kind of for-profit model non-profit model because not only you can't scale it really well, you become dependent on your donors. And those donors may have not necessarily like good motives, right? We've seen non-profits who were have been like you've seen this chat control legislation, right? The biggest lobby effort for chat control over legislation was coming from non-profits funded by big tech. So talking about non-profit being a good thing. So I honestly I honestly think that morality and integrity of what happens doesn't depend on the organization form. I think it depends on people behind this organization in the first place, right? We've seen companies doing moral things and we've seen non-profits doing immoral things. Right. And I think, yeah, so so what what we are doing right now. So we kind of understand we're building network that nobody should own. We don't want to own it, right? We want a general-purpose transport network that is run by community, operated by community, which means that the model when we control the protocol, the model we control all the licensing on the software is not sustainable long term, right? So what we are doing right now, we are we already announced to the community that we will be transitioning the governance we are transitioning the governance to consortium model, which is similar to how the web was governed until recently. It's interesting by the way I didn't know about that I only learned when was reading. So World Wide Web was governed by consortium, not an entity. like it's effectively an agreement between four different entities in different countries. Worldwide Web was governed by consortium from Netscape shut down in I think 2004 and until 2023 when W3C became a US non-profit, a single entity. Which is fun. Which means the Worldwide Web that we all believe is decentralized now have a centralized governance model. Even though it's by non-profit it's still centralized.","offset":4908,"duration":191},{"text":"Host: Right.","offset":5099,"duration":1},{"text":"Evgeny: So what we did we worked with one exceptional open-source lawyer, Heather Meeker. She has authored multiple open-source licenses such as Mozilla license, Elastic license. She participated in some exciting works. She helped us draft this agreement for consortium for SimpleX network and we are in a process of setting up the entity that will be in a consortium agreement with SimpleX the company and then we'll be setting up additional non-profits in different jurisdiction so this multiple entities will be able to run network together and this way avoid like jurisdictional pressures or risks and avoid any kind of corruption from any centralized governance model.","offset":5100,"duration":50},{"text":"Host: Like corporate capture and whatnot.","offset":5150,"duration":1},{"text":"Evgeny: Exactly, yeah. Because we've seen we've seen corporate captures happen in non-profits a lot, right? The whole Linux like look at this, you're probably observing this noise about California law of like...","offset":5151,"duration":11},{"text":"Host: Yep.","offset":5162,"duration":1},{"text":"Evgeny: ...requiring KYC to flesh Linux. This is insane. I made a tweet yesterday it resonates with lots of people. It's effectively they tell you \"you no longer own your computer,\" right? Just like we're going to break and enter into your computer and demand it's a violation of like multiple constitutional amendments like certainly First Constitution and Fourth and Fifth and god knows what else is violated and they say it's okay. What what I find completely ridiculous is that all those open-source foundations developing Linux software are just quiet. They don't say anything, right? They don't the only open-source the only privacy foundation is EFF. EFF is campaigning against this law. Linux Foundation says nothing, right? All these kind of foundations developing Linux software are saying nothing. They already commit code that implements this age control into open-source code which is just ridiculous to me.","offset":5163,"duration":56},{"text":"Host: Why do you think that is?","offset":5219,"duration":2},{"text":"Evgeny: Because they are captured. I think.","offset":5221,"duration":2},{"text":"Host: Right.","offset":5223,"duration":1},{"text":"Evgeny: Because we've seen a lot of decisions in those foundations that don't necessarily they they they have been pressuring creators of software to leave, they have been pressuring... so that's not that's not good.","offset":5224,"duration":13},{"text":"Host: They're reliant on their donors to pay their rent basically.","offset":5237,"duration":2},{"text":"Evgeny: I don't know, Matt. I I cannot say why it happens. But to me it was always like always the I don't want to go into there. But the reason I bring it up the reason I bring it up is because I'm neck-deep in this with OpenSats. You know, OpenSats we saw a concern of very centralized funding options for open-source developers building non-profit stuff in the Bitcoin ecosystem. And to be clear here, there's a bunch of foundational open-source stuff that can't be monetized. It just it cannot be monetized. It would it would ruin the value prop for something like Bitcoin protocol software to be to be monetized directly. And so we built OpenSats in a way to resist that. And I think one of the biggest thing is we're a volunteer board. We're a nine-person board that's all volunteers we make money doing other things. And it's because of that concern. You know, the concern that you get captured by your donors because you're making $500,000. Some of these non-profit boards it's insane how much money they're making. And if that donor if that donor base disappears then they lose that. If my donor base disappears, directly financially there's zero impact to me, right? And I think that's a key piece but it doesn't completely solve it. Obviously if the donors disappear OpenSats is gone. And so then I I do agree to your point that it does come down to the people in a lot of ways, right? It's like I would rather OpenSats be gone than ever take direction from a donor.","offset":5239,"duration":90},{"text":"Evgeny: Exactly, because you because you are independent because you personally making profit in your life and you wouldn't let other people run your life. That that comes to who should be on a board which is also very important question, right? We still didn't form the board but we are reaching out to various people who we believe can create value for for for governance and also it would be helpful to them as well. So yeah, so we but I think it's still important given that jurisdictional law changes quite rapidly sometimes, I think it's important to have multiple layers of decentralization of governance decision. So my initial thinking was that we should have shared ownership of IP, right? But intellectual property. The legal advice from from from our lawyer was that it's not possible really because there is no such thing, right? So shared ownership of intellectual property means that any owner can dispose of it, not just some consensus is needed. So what is going on happening is that the company will be remain the owner of IP but it will be licensed to all consortium members irreversibly. So there is a specific clause in open-source licensing when there is a lien attached. So even if the company stops existing or sold license still survives this. So effectively we will transfer licensing to multiple consortium members in a way that we can't revoke it and then bit by bit we want to transfer governance of the key protocol in the same way. Again, like Netscape has always been an inspiration to me as a company, right? Netscape built web as we know it, right? Because Netscape pick up web protocol when it was embryonic, right? Nobody like you know, who who knew about the web in 199 1995? Right? Nobody knew about the web. But they picked it up they built a browser, they added JavaScript, they added cookies, they added SSL, they added like, people think cookie is a bad thing, but cookie is a foundational piece that allows you Facebook know to you is you, right? It's verifiability, right? So without cookies Facebook doesn't know who you are. Or Twitter or whatever. They created web as we know and then they shut down in 2004. W3C took over abruptly and what happened is that all the innovation stalled completely, right? Took them like seven years to get CSS to next version.","offset":5329,"duration":159},{"text":"Host: Right.","offset":5488,"duration":1},{"text":"Evgeny: The industry was so frustrated with W3C governance so they had to hold their own working group, if you remember this WHATWG. So and they had to take matters in their own hand and it was like super frustrated for everybody, right? And that's exactly what the abrupt and that's what unfortunately we see I think with many decentralized protocol because they want to be decentralized, right? But they don't understand that from the point of early enthusiasts using this protocol to the point everybody else can use this protocol it's not just time and adoption, it's radical changes in the protocol. Yep. And these radical changes require speed, commercial incentive, funding, centralized decision-making. So you simply cannot get a protocol to mass adoption without running things as a venture-funded company would run things. That's what Netscape did, right? Netscape was doing Netscape browser at a time there like 30 other competing browsers also trying to do browsers with venture funding. It didn't occur to Netscape to ask other browsers what they think about protocol changes. They honestly didn't care.","offset":5489,"duration":62},{"text":"Host: Right.","offset":5551,"duration":1},{"text":"Evgeny: If they did, we wouldn't have the web. So that's how I see the whole kind of decentralized governance. There are some stable parts of the network and changing them should require consortium vote, right? But there are some evolving part of the network that kind of on the boundary require adoption, require radical changes, and they are not ready for decentralized governance yet.","offset":5552,"duration":21},{"text":"Host: You need to be able to move fast and adopt and...","offset":5573,"duration":3},{"text":"Evgeny: Exactly. Yes. And that's what we lost with...","offset":5576,"duration":13},{"text":"Matt: Agreed.","offset":5589,"duration":1},{"text":"Evgeny: Yes, so that's what we want, that's what we're trying to achieve.","offset":5590,"duration":2},{"text":"Matt: That's why I always use like Signal as an example, because they - once again, not perfect, but very pragmatic trade-off balance that they went with. They've had - it's funny, right, because you can look at it from both perspectives.","offset":5592,"duration":11},{"text":"Matt: You can be like, \"Oh, they're a massive success for a privacy project because it's 100 million people,\" and then you can look at it from the opposite side - \"That's nobody,\" right? Like it's still 2%, right? 100 million people is 2%, if I can count... yeah.","offset":5603,"duration":15},{"text":"Matt: Evgeny, I want to dive in just before we wrap here, I think it's important that like high-level the monetization makes sense to me. In practice, everything's harder to execute on in practice.","offset":5618,"duration":15},{"text":"Matt: So I want to dive a little bit more into the details because there was some controversy around it, about how you're thinking about implementing it. And the big one is, okay, so the main operators that are doing, you know, 90% of the traffic, these big channels, are going to be paying for things.","offset":5633,"duration":17},{"text":"Matt: You basically got flack - you know you're doing well when you get flack from everyone that has all different conflicting interests and everyone is mad at you. But the two big ones that I noticed was the Bitcoin and Monero communities, respectively.","offset":5650,"duration":15},{"text":"Matt: The Bitcoin community being saying, \"Why aren't we using Bitcoin for this?\" And the Monero community being like, \"Why aren't we using Monero for this?\" So my question to you is rather simple: why aren't you using Bitcoin for this, and what's the alternative, and why is that being chosen?","offset":5665,"duration":16},{"text":"Evgeny: Okay, so one thing at a time. To have network pay, to have network function, we need to - we don't need to just pay for servers, right? We need to have mechanism how governance layer can be paid, how software developers can be paid, and how channels can make profit.","offset":5681,"duration":17},{"text":"Evgeny: And that requires some mechanism of revenue sharing and distribution between those parties. We cannot tell channel owners, say, you have to pay this and this and this, right? So we have to create some codified approach for revenue distribution.","offset":5698,"duration":16},{"text":"Evgeny: And not just that. So we also need to solve problem of server discoverability, right? So how will people learn where the service exists? How they find them out? Right? Okay, they want to use paid service, how they find it out?","offset":5714,"duration":14},{"text":"Matt: Right.","offset":5728,"duration":1},{"text":"Evgeny: Or they want to have channel names, because again, if we're talking about usability, you need to have a name for the channel, right? Nostr keys are great, SimpleX addresses are all great, they're 100 characters of gibberish. Normal people will never ever use it.","offset":5729,"duration":17},{"text":"Evgeny: They want to type \"music\" and go to the channel with music, or they want to type \"sport\" and go to the channel with sport.","offset":5746,"duration":67},{"text":"Matt: For the same reason we don't go to direct IP addresses, we type in a domain.","offset":5813,"duration":4},{"text":"Evgeny: Exactly, we type domain names, right. So how do we do it? We need some mechanism to agree on what this address means. Because if we simply give this address to a server and say, \"Okay, I will tell you music, you will tell me the address,\" the problem with that is the server can give you any address. They can execute man-in-the-middle attack on your connection, right?","offset":5817,"duration":-38},{"text":"Evgeny: So you need some way to get trust to the information you're getting. And how internet solved this problem and world wide web solved this problem? They created like hierarchy of trust, right? Certificate authorities and domain name systems, when your trust is built ultimately because you have an authority.","offset":5779,"duration":20},{"text":"Evgeny: But that's antithetical to both Bitcoin, Monero, and to us. Because the second there is an authority, this authority will be corrupted, right? And we've already seen attacks on certificates via major certificate authorities, right?","offset":5799,"duration":15},{"text":"Matt: It's a mess.","offset":5814,"duration":1},{"text":"Evgeny: Yeah, it's a complete mess, right. So we cannot build a system based on trust or on authority. We have to build a system that's properly decentralized when any information you get about the network is trusted without having authority that you trust.","offset":5815,"duration":16},{"text":"Evgeny: And the solution exists, it's called blockchains, right? So, but I think the way I see blockchain - and that was the root cause of this misunderstanding, and the way many people see blockchain is very different.","offset":5831,"duration":14},{"text":"Evgeny: Because people see blockchain as a way to transfer value between participants, as a ledger that records transactions. But that's just one use case. Like since a lot of technology has evolved, and blockchain can act as a global distributed computer that can perform arbitrary computations and arrive to consensus about things, not just transactions, any consensus.","offset":5845,"duration":26},{"text":"Evgeny: Can execute arbitrary logic in a way that it's trusted without having a single party that you need to trust. That's what smart contracts do.","offset":5871,"duration":9},{"text":"Evgeny: Because people think contract is some sort of agreement that you sign or it's some sort of an asset, or - it's not. It's just a code, right? So when you go to the server, you run some code, it gives you some result, you have to trust the server.","offset":5880,"duration":15},{"text":"Evgeny: If you go to smart contract enabled blockchain, then you can run computation and get the result, and then your trust in this result is not based on a particular node of this blockchain, it's based on the whole decentralized blockchain.","offset":5895,"duration":14},{"text":"Matt: Yeah, the best example of that at scale, in my opinion, right now is Polymarket.","offset":5909,"duration":4},{"text":"Evgeny: Potentially, yes, I'm not that familiar with that. I know what Polymarket is.","offset":5913,"duration":3},{"text":"Matt: Well, I mean, they have a similar - I mean, they have a similar problem, right? The problem is if, you know, they can't have a centralized entity taking custody of funds and handling arbitrary code, like settling of the markets, right? If a missile strike hits or not, like it can't be a single company doing that.","offset":5916,"duration":15},{"text":"Evgeny: Correct. So when we say we need - so several things should happen for SimpleX network for it to be usable and sustainable, right? We need to have a registry of servers that can receive money and trust this registry, right?","offset":5931,"duration":18},{"text":"Evgeny: We need to have a registry of names so we can discover channels. And we also have design for private names when you can discuss people without anybody knowing their addresses. We have design for that too already.","offset":5949,"duration":15},{"text":"Evgeny: And we also have to have a way to transfer value as well, but not just transfer value, but also distribute the revenues in somewhat agreed way. So depending on - it's like programmatic value transfer, right? It's like an auto split that's going to multiple...","offset":5964,"duration":11},{"text":"Evgeny: Exactly, yeah, exactly right. So because otherwise, transfer value is a simple problem and yes, Bitcoin is the best at solving this problem and the first solved this problem. And if transferring the value would be the only problem that we needed to use, then Bitcoin is a viable solution, and likewise Monero is a viable solution, right?","offset":5975,"duration":14},{"text":"Evgeny: But that's not the problem that we need to solve. We need to have a distributed computer that we can trust that will solve all the problems that require network-wide state. Because today SimpleX network has no network-wide state. No registry of servers, there is no list of participants.","offset":5989,"duration":13},{"text":"Matt: No global state.","offset":6002,"duration":1},{"text":"Evgeny: Exactly, it's fragmented. And when people say, \"Oh, we have to bring the whole messaging on blockchain,\" that doesn't work because messaging has to be fragmented, right? Communities have to be fragmented, network - but if you want to have a global namespace that is recognized by all clients, then you suddenly want a network-wide state, right?","offset":6003,"duration":21},{"text":"Evgeny: If you want to have a server registry to which you can pay money, you want a network-wide state. And if you want an agreement with those servers that you can trust and everybody is paid who is doing the work for the network, you need some programmatic way to split revenues and distribute money. That requires smart contracts.","offset":6024,"duration":17},{"text":"Evgeny: So our whole idea is behind that to program all this logic effectively on the blockchain and have server operators and network users interface with smart contracts so that payments can be transferred from the channel owners to the servers with whatever revenue sharing agreements that can be put in place as code.","offset":6041,"duration":21},{"text":"Evgeny: Specifically, we're going to build a proof of concept quite soon on some blockchain so people can have a feel of how it's going to work. But imagine you're an operator, you're going to smart contract via some service, dApp hosted on IPFS for example, and you say, \"I want to be an operator.\" You will be asked to give your details, you will be asked to like, what are your server addresses and what not.","offset":6062,"duration":19},{"text":"Evgeny: You will be asked to sign a deed. So I believe that technical guarantees have to be supplemented by contractual guarantees. So let's say, if you want to run a server on SimpleX network, you have to guarantee the users that you're not going to sell the data, that you're not going to collude, that you're not going to - so there have to be legal remedies if you do.","offset":6081,"duration":19},{"text":"Evgeny: I think that's a big missing bit in networks like Tor, because they only - maybe because they are technologists, maybe they just don't think about it like this. But I think if I'm using the server on the network, I want not just technical guarantees, I also want contractual guarantees as well.","offset":6100,"duration":19},{"text":"Evgeny: And we want blockchain to deliver it all. So participation in network would require providing contractual guarantee in exchange for making the money, which I think is reasonable. So that requires programming, that requires writing code, that requires deploying code in a way that it's executed not on a particular computer but on a distributed network of computers.","offset":6119,"duration":18},{"text":"Matt: Independently.","offset":6137,"duration":2},{"text":"Evgeny: Yeah, and there is not a single - there are choices, right? There are multiple networks that can do it. I think it would benefit Bitcoin a lot to evolve into this direction, but it's not there yet.","offset":6139,"duration":13},{"text":"Matt: I mean, why does Bitcoin have to do all the things? I'm in the camp that like if you use - I mean, because the problem is adding that functionality reduces the robustness of whatever blockchain it has that functionality. That's always been the trade-off from Bitcoin protocol point of view.","offset":6152,"duration":22},{"text":"Matt: So like if you use like for instance - and I've gotten some shit for this and this is why I used Polymarket as an example - like Polymarket runs on I think like an Ethereum Layer 2 called Polygon, right? From a user point of view, I just need to be able to deposit Bitcoin.","offset":6174,"duration":14},{"text":"Matt: Yes.","offset":6188,"duration":1},{"text":"Matt: Like if it runs on a different tech stack, that's in a lot of ways a benefit to Bitcoin holders because it's not burdening Bitcoin with that tech stack. You just need to be able to send Bitcoin to it.","offset":6189,"duration":15},{"text":"Evgeny: 100%. And that's actually solved problem, right? The whole idea of like foreign assets have been executed in a trustless way by other blockchains. For example, I think Polkadot did it, StarkNet did it, there are some other blockchains that did it, that you can hold asset on a Bitcoin blockchain but in a way that you operate on this asset on another blockchain.","offset":6204,"duration":20},{"text":"Evgeny: So it's kind of - it's nearly non-trustless.","offset":6224,"duration":3},{"text":"Matt: No, no, there are trustless - there are trustless solutions as well.","offset":6227,"duration":2},{"text":"Evgeny: I question - I question if that's the case. There's a lot of hype around it. Look, I think it's important that you minimize the trust as much as possible for that cross-chain situation. There are atomic swaps that can handle it. You know, Boltz just released an atomic swap that moves you from, for instance, Bitcoin to Tron Tether, and in between there's no custody. But you know, trust is a hard thing.","offset":6229,"duration":34},{"text":"Evgeny: I agree that it's hard to do a completely non-trustless way. But I think they are doing something reasonable with that. But that's not the point. So what we want to do is to just have ability to transact with any currency on the entry, Bitcoin of course as well, but ultimately to have a mechanism of revenue sharing between participants that enable - like, you're using web browser, right? You're not paying to the web browser.","offset":6263,"duration":29},{"text":"Evgeny: It doesn't mean that the web browsers are not paid, right? Ultimately web browsers find a way to make revenue. So we believe that companies developing client software for networks should earn revenue from the network for doing that, right?","offset":6292,"duration":15},{"text":"Evgeny: And it's not just our company, any company that develops software should earn money proportional to the usage that they are able to generate for the network, right?","offset":6307,"duration":8},{"text":"Matt: Yeah, I mean the web browser's an interesting example, right? Because it wasn't built in a programmatic way of revenue sharing and stuff, they have to find revenue streams that are very convoluted and oftentimes have warring incentives. The best example being Chrome, which Google figured out was the way you monetize it is with search and mining data of people.","offset":6315,"duration":21},{"text":"Matt: Exactly.","offset":6336,"duration":1},{"text":"Matt: While like Internet Explorer was monetized basically through Windows and Windows lock-in and Safari is Apple's ecosystem. And as a result, we just don't have many different web browsers we can use.","offset":6337,"duration":12},{"text":"Evgeny: Exactly, exactly. So it stifles competition because there is no mechanism to get revenue for making a browser from the network that requires browser to access, right? And also all sort of perverse incentives, right? When privacy gets compromised, when security gets compromised, when users' data is being sold, and that's just corrupt model.","offset":6349,"duration":22},{"text":"Evgeny: And the only proper solution is to just build in this revenue sharing model in the network so browser developer - or whatever software developers get some share of the revenue proportionally to the value they create for the network.","offset":6371,"duration":14},{"text":"Evgeny: And likewise governance of the network, right? When we say we're establishing consortium, governance carries legal costs, right? It carries documentation costs. It may be not cost a lot of money, it may be whatever $100,000 a year, $10,000, it doesn't matter. It's still money that somebody has to pay ultimately, right?","offset":6385,"duration":23},{"text":"Evgeny: And until some point it's okay to sustain on donations, right? But beyond some point it may be hard to sustain on donations and it may require explicit revenue sharing agreement with the network. So we really - I really see it's important to have foundation that would allow it.","offset":6408,"duration":12},{"text":"Evgeny: I think it's fundamentally the vision of Tim Berners-Lee around the web, right? That's why we say that what we're building is potentially next web, because he was talking about micropayments powering the websites and generally web ecosystem from day one, right?","offset":6420,"duration":18},{"text":"Evgeny: It was way ahead of like blockchains or cryptocurrencies or even understanding what this micropayments means. But I think like he was talking about the future for which we today have technology.","offset":6438,"duration":12},{"text":"Matt: Fair enough.","offset":6450,"duration":1},{"text":"Evgeny: So, so yeah. So that's, that's, that's why we, we didn't, we didn't make a final decision. We're still iterating in which, which is the blockchain, what smart contracts. But fundamentally we're looking for solution with smart contracts.","offset":6451,"duration":16},{"text":"Matt: I am - and this, I'm trying to be mindful of time because this was supposed to be a tight hour and I know time is scarce, and no, don't apologize, I was apologizing to you. But this conversation has been so fascinating that we're almost at two hours. But I still, I mean I still want to just go a little bit deeper on this before we wrap. If you have a little bit more time?","offset":6467,"duration":11},{"text":"Evgeny: I have all the time you have.","offset":6478,"duration":2},{"text":"Matt: Okay, great. Uh what thought have you given - I mean, the big concern, right? I would say, is we haven't seen - so basically there's two pieces here, right? And I think the first is the reason the community's gut reaction was outrage is because most of the time when a proprietary token scheme or credit scheme gets presented, it's very scammy.","offset":6480,"duration":35},{"text":"Matt: I don't think it inherently needs to be scammy, I just think that 99% of the time it is scammy and there aren't many examples of it not being. So people default to that. I understand why you would choose this path and I don't think it's necessarily unethical or anything.","offset":6515,"duration":16},{"text":"Evgeny: It's not even that, Matt. We're not going to do any tokens or emission for that. We see a smart contract as a holder of the existing value. We're not going to create any digital asset class.","offset":6531,"duration":12},{"text":"Matt: Okay.","offset":6543,"duration":1},{"text":"Evgeny: All we want is a scheme that allows people to deposit some existing asset - there is no final decision on what this asset is.","offset":6544,"duration":6},{"text":"Matt: But it can be multiple different assets, right? I mean...","offset":6550,"duration":2},{"text":"Evgeny: Exactly, exactly. They deposit it on smart contract simply holds it. We're not interested in emitting digital assets at all and we're not planning to issue any tokens. What we want is a autonomous smart contract on the chain when you deposit existing asset that we didn't create and then you assign it to a community using zero-knowledge proof, which already decouples your purchase from assignment.","offset":6552,"duration":21},{"text":"Evgeny: And then once community has assigned credits - and credit is existing assets, it's not our token, it's not something we created - then they can redeem it to the server and then when revenue gets distributed.","offset":6573,"duration":13},{"text":"Evgeny: What we achieve with this scheme is that privacy is preserved because it's effectively you're - think about it like prepaid telephone card, right? You go into the store, you pay cash and you get the card, and then you use the card to pay for your phone, or you may give it to your friend and your friend will pay for his phone or for her phone.","offset":6586,"duration":20},{"text":"Evgeny: So that's fundamentally what we want to develop: prepaid scheme allowing you to use existing digital assets on a blockchain to prepay server capacity and do it in a way that preserves your privacy.","offset":6606,"duration":12},{"text":"Matt: Right, but then to programmatically split it between...","offset":6618,"duration":3},{"text":"Evgeny: And programmatically split revenue. Right. So we have no interest in issuing tokens, we have no interest in creating any digital asset class. We have interest in creating a mechanism that allows people to transact in a way that protects their privacy.","offset":6621,"duration":16},{"text":"Evgeny: Because you cannot really - like yes, people go through all the hoops to have privacy, they have to think about how they connect to blockchain nodes, how they do this, how they do that. So privacy is possible with blockchain, but it's not possible for mass market users realistically, right?","offset":6637,"duration":15},{"text":"Matt: Yeah, it's quite difficult. It's been a major focus of mine.","offset":6652,"duration":4},{"text":"Evgeny: Exactly. So what we want to develop is a layer that is built on top of blockchain, uses existing blockchain primitives, existing blockchain assets, and that allows people to pay for infrastructure in the same way they would pay for telephone buying telephone prepaid card.","offset":6656,"duration":18},{"text":"Evgeny: We didn't, like if I tell you that we're doing a prepaid telephone card it doesn't mean we're printing cash. We're not printing cash, we're just doing prepaid telephone card. So we don't want to do any token that would hold value. We simply do effectively treasury contract which will hold some other tokens that already exist. We didn't know - it may be USDC, it may be some other token, it may be something that people recognize as a value and use it as a transient value store to pay for the servers.","offset":6674,"duration":30},{"text":"Matt: Well that brings me to my second piece, which I would just say as someone who is pretty excited about what you're building and understands the need for it, and I don't want you to make any bad decisions that you regret later - is you know the way Bitcoin is designed and the trade-offs Bitcoin has made make it very resistant to centralized capture.","offset":6704,"duration":24},{"text":"Matt: Both on the protocol level and then also the token itself is a native asset, right? When you're thinking about how you're going actually execute on this and build it out, I think it would - and I'm sure you're already thinking about it - there's two pieces, right? First of all, the protocol you decide to build on is going to have varying levels of centralization, right?","offset":6728,"duration":22},{"text":"Matt: So Tron for instance is an example I constantly use. Tron has $10 billion worth of Tether on it, but at the end of the day it's just Justin Sun has full control. Now regulators perceive it as federated control and he doesn't have full control, and maybe that's enough for him in his use case or whatever.","offset":6750,"duration":18},{"text":"Matt: But when it comes to something as important as SimpleX, I could easily see censorship happen on that chain. Now you could - now there's varying levels of this throughout the ecosystem, right? With I would say Bitcoin being by far the most secure but not programmatic for your use case or whatever.","offset":6768,"duration":18},{"text":"Matt: And then things like Tron being incredibly centralized but a lot of people are using them as a result. And then the second piece is the actual assets themselves, right? USDC, you know, is controlled by a centralized group of regulated institutions, right? It gets frozen all the time, so does Tether, right?","offset":6786,"duration":13},{"text":"Evgeny: We understand it.","offset":6799,"duration":1},{"text":"Matt: So you got to think through these because ultimately I mean I could imagine a world where you build this all out and then if that layer gets broken, everything starts to break around it, right? Like people it would hurt the robustness of the protocol itself. So these are things I'm sure - are you thinking about this? I assume you are.","offset":6800,"duration":24},{"text":"Evgeny: 100%. Yes. Matt, you know one of the reasons why we announced our strategy and technology direction long before we have answers is exactly that. Because we usually iterate ideas internally and then when we think, okay, we don't know how to make it better, at this point we announce.","offset":6824,"duration":15},{"text":"Evgeny: It sometimes happens months or even more than a year before we actually start building. We didn't start building it yet. We only - we only arrived recently to a cryptographic design that hits all the goals, right?","offset":6839,"duration":15},{"text":"Evgeny: We didn't even - we only recently running the review of all the blockchains that can be used for that. And Tron is disqualified, right, same as many other centralized blockchains. We absolutely don't consider high degree of decentralization.","offset":6854,"duration":16},{"text":"Evgeny: I understand that downside of so choice between USDC or Tether and other tokens is effectively volatility versus centralization. So it's a - it's very - it's a very hard choice, right? So and for many - so I would say in the same way I like reject false trade-offs and false binaries, right? Some choices are just not real, right? You just invent them and you say you cannot have both. In many cases you can have both.","offset":6870,"duration":29},{"text":"Evgeny: But sometimes there are some genuine trade-offs and they're really hard to take. And with this kind of specific technology, there are a lot of hard trade-offs. That's true. What I think - what I think is important though, we're still in enthusiast territory. I think it would be correct to see what we're building right now as a - as a prototype, right?","offset":6899,"duration":17},{"text":"Evgeny: In the same way as SimpleX v1 was a prototype. And if you compare SimpleX design on the day of launch with SimpleX network design today, it's like almost like two different products, right? We have completely different layer of security, we have completely different - and we managed to evolve it all kind of with backwards compatibility so people were effectively using a different network without changing the client without having being disrupted etc etc.","offset":6916,"duration":27},{"text":"Evgeny: So I think we can do the same with payments. So whatever we build in the first instance is likely to be a prototype we learn on and that will evolve dramatically as it gets adopted, as it gets tested.","offset":6943,"duration":15},{"text":"Evgeny: Because I think the biggest test for the product is not technology, it's market, right? We kind of hypothesized that channels will pay for servers, servers will want to participate. We hypothesized a lot about the market. And you, you know it better than anybody else, you're a VC, right? Products don't fail because technology fails. Products fail because nobody cares.","offset":6958,"duration":18},{"text":"Matt: Yep.","offset":6976,"duration":1},{"text":"Evgeny: Nobody cares to use them, nobody cares to build them. And I think at this point it's much more important to prove that our hypothesis about the world - that people will pay, that servers will want to sell - are correct, right? That there is actually a market.","offset":6977,"duration":15},{"text":"Evgeny: I think to prove this is much more important than to avoid like centralization - you understand what I mean, right? So like it's much more important to - and once we see, okay, yes there is a market, it can grow, we'll just rebuild the technology in a way to avoid the capture.","offset":6992,"duration":14},{"text":"Evgeny: You can see it's the same way as we were building SimpleX network. People were telling me from day one, \"You should create a foundation and should run protocol evolution.\" But my response was look, we don't know if anybody needs it, number one. We, we don't know what people need. It's not just we don't know. Even if we know that people need something, it's almost like you know, like your trade has an expression \"product-market fit,\" right?","offset":7006,"duration":23},{"text":"Evgeny: We've been running product-market fit experiment for four years and now we kind of have understanding of what people need in terms of messaging, right? What people need in terms of payment for infrastructure capacity, we're just in the beginning of running this experiment, right? We hypothesized, we learn, we talk to people, we believe we - it's putting the cart before the horse otherwise.","offset":7029,"duration":19},{"text":"Evgeny: Exactly, yes. So, so I think, I think it's important for community not to overvalue technology choices. Of course we'll make the best job, of course we'll do decent technology choice, of course we'll avoid obviously bad - like Tron is obvious bad choice, right? There is no way - there is no world in which we use Tron or Base or something else centralized, right? So it's literally not even on the table, right?","offset":7048,"duration":20},{"text":"Evgeny: But within reasonable choices, I think I wouldn't overindex the importance of doing it right on the first try, but rather doing something that's kind of usable - we're trying to do a good job, I think we're trying to do a good job with Version 1. But that's still...","offset":7068,"duration":13},{"text":"Matt: Directionally correct and learn from it is how I think you're thinking about it.","offset":7081,"duration":3},{"text":"Evgeny: Exactly. I think that, that's how we've been evolving the product from day one, right? We built something and then it was pulled by users into some direction and we pushed in some other, it was kind of a combined effort. And I think that's why people use it, because we tell people early what we do, we listen what they say, we learn, we do something that we think - we're building it for people, right?","offset":7084,"duration":20},{"text":"Evgeny: I'm too old to do it to be rich, right? I personally - no, come on, it's like you're not doing what you're doing to be rich, right? If you wanted to be rich you would be doing different things, I think.","offset":7104,"duration":11},{"text":"Matt: I agree with that. That is correct.","offset":7115,"duration":2},{"text":"Evgeny: Yeah, there are simple ways today to get rich, right? We really think what kind of is common between us is that you kind of dislike the place where this world arrived, right? And you do what you can in your place with your resources, with your abilities, to make this world a little bit better.","offset":7117,"duration":19},{"text":"Evgeny: I think that's why we're building communication technology because I, I care about communications, right? I experimented with page- you know, pagers like I had some was dabbling with those things so like I really care about people being able to connect to other people. There is nothing more important.","offset":7136,"duration":14},{"text":"Evgeny: And me seeing like the whole world is converted into some kind of a surveillance panopticon when like you can't really talk to anybody anymore, that's just not right. And trying to do something...","offset":7150,"duration":13},{"text":"Matt: Yeah, someone has to do something.","offset":7163,"duration":1},{"text":"Evgeny: Exactly. I was saying that something has to do something for the last 12 years. 15 years now, right? So like 4 years ago I say, alright, nobody does anything I have to do something, right?","offset":7164,"duration":12},{"text":"Matt: Yeah, that's what compels me too. I look, I think you're thinking about it the right way. I think it's the right perspective. Obviously you have my contact now, so if I can be helpful as you try and figure things out, don't hesitate to reach out.","offset":7176,"duration":12},{"text":"Matt: But yeah, I think it's the right perspective. I think it's I mean just really well set across the board. Evgeny, this was a great, really great conversation. I enjoyed it. Maybe we'll do a follow-up in the future like in a year or something, I don't want to like take too much of your time, but I think it'd be cool to have you know kind of like a timeline as, as you build all this out. It'd be fun.","offset":7188,"duration":24},{"text":"Evgeny: That would be fantastic, yes. So we kind of...","offset":7212,"duration":4},{"text":"Matt: Just try and make it work.","offset":7216,"duration":2},{"text":"Matt: Yeah we're past the two hour mark now. This was an epic, epic conversation. Do you have any final thoughts for the audience before we wrap? How they can be helpful? I'm going obviously link to all the important links in the show notes.","offset":7218,"duration":13},{"text":"Evgeny: We didn't do a formal announcement yet. And what we're planning this year is effectively transfer and give people more ownership of SimpleX network across multiple dimensions. So this consortium governance is one thing. Another big thing we're planning for this year is crowdfunding. It's not formally launched yet, we're kind of in testing the water phase so we're not accepting any money, we're not doing that.","offset":7231,"duration":23},{"text":"Evgeny: But we will be doing it this year. We've been criticized a lot by our users for taking private investors' money and we think it's like - I think our users have to own a piece in this network and have a say in where this network evolves and not only via non-profit governance but also via having shares in, in a company that builds this network.","offset":7254,"duration":23},{"text":"Evgeny: So we're creating this opportunity right now. It'll probably launch in like three months or so, but there will be announcement soon in the blog post, on Twitter, so yeah that's a big thing. So I really wish to see community supporting and benefiting from, from what we're building.","offset":7277,"duration":21},{"text":"Evgeny: Because we're not trying to be just non-profit entity. We believe like if what we're building is the next web and we're the company building the next web, then it may be really large business and our early investors can benefit a lot from participating in that. And I really want to see community members in their numbers.","offset":7298,"duration":16},{"text":"Matt: And I don't know if you're comfortable with sharing how that's going to be set up or like was that just a traditional equity sale or...","offset":7314,"duration":5},{"text":"Evgeny: Yes. We don't believe in tokens. We will sell company equity, it will be some sort of modified SAFE agreement. We can't use YC SAFE as is for crowdfunding. It's not decided, it's premature, it's currently what we're working with, with lawyers, but fundamentally yes it will be the community who can participate will own company equity.","offset":7319,"duration":23},{"text":"Matt: Awesome, got it.","offset":7342,"duration":2},{"text":"Evgeny: That's, that's our big news for this year. So...","offset":7344,"duration":3},{"text":"Matt: I'll keep an eye out for that.","offset":7347,"duration":1},{"text":"Evgeny: Yeah. And that's, that's - I have to say what my lawyers keep saying me: we have to say a disclaimer that this is not an investment offering and we cannot accept any money at this stage. This is just us testing the interest.","offset":7348,"duration":12},{"text":"Matt: I think that was good legal advice that you received, I'm glad you said it. Sir, it was a pleasure, thank you for joining us.","offset":7360,"duration":8},{"text":"Evgeny: It was a privilege, Matt. I really appreciate you doing that with me, thank you so much.","offset":7368,"duration":6},{"text":"Matt: Thank you. Freaks, thank you for joining us. I hope you found the show helpful or fascinating. I enjoyed it. As always, share with friends and family, search \"Citadel Dispatch\" in your favorite podcast app. All relevant links at CitadelDispatch.com. Love you all. Stay humble, stack sats. Peace.","offset":7374,"duration":15}],"logs":[{"elapsed":"0.0","message":"Downloading podcast episode...","detail":null},{"elapsed":"11.0","message":"Episode downloaded (112.8 MB) in 11.0s","detail":"File size: 112.8 MB"},{"elapsed":"11.0","message":"Episode: CD196: EVGENY POBEREZKIN - SIMPLEX PRIVATE CHAT","detail":null},{"elapsed":"11.1","message":"Audio duration: 2:03:12 (123.2 min)","detail":null},{"elapsed":"11.1","message":"Very long audio (123.2 min) — will use chunked transcription with gemini-3-flash-preview","detail":null},{"elapsed":"11.1","message":"Skipping full-file attempt — using chunked transcription for 123.2 min audio","detail":null},{"elapsed":"11.9","message":"Split audio into 3 chunks for transcription","detail":null},{"elapsed":"11.9","message":"Transcribing chunk 1/3 (starts at 0:00)...","detail":null},{"elapsed":"11.9","message":"Uploading audio to Gemini File API...","detail":null},{"elapsed":"17.0","message":"Audio uploaded in 5.1s","detail":"File ref: files/yph8gb1v3n1u"},{"elapsed":"17.0","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"78.7","message":"Chunk 1: 101 segments, last timestamp 48:30","detail":null},{"elapsed":"78.7","message":"Transcribing chunk 2/3 (starts at 45:00)...","detail":null},{"elapsed":"78.7","message":"Uploading audio (offset 45:00) to Gemini File API...","detail":null},{"elapsed":"83.7","message":"Audio uploaded in 4.9s","detail":"File ref: files/mixavn9f5lbq"},{"elapsed":"83.7","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"141.0","message":"Chunk 2: 99 segments, last timestamp 1:32:56","detail":null},{"elapsed":"141.0","message":"Transcribing chunk 3/3 (starts at 1:30:00)...","detail":null},{"elapsed":"141.0","message":"Uploading audio (offset 1:30:00) to Gemini File API...","detail":null},{"elapsed":"145.4","message":"Audio uploaded in 4.4s","detail":"File ref: files/8f8az6w940zb"},{"elapsed":"145.4","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"198.0","message":"Chunk 3: 147 segments, last timestamp 2:02:54","detail":null},{"elapsed":"198.0","message":"Chunked transcription complete: 325 total segments","detail":null},{"elapsed":"198.0","message":"Total cost: 185,608 in / 31,646 out — cost: $0.1877","detail":null},{"elapsed":"198.0","message":"Total transcription time: 186.9s — 325 segments","detail":null},{"elapsed":"198.0","message":"Analyzing topics across 325 segments with gemini-3.1-pro-preview...","detail":null},{"elapsed":"306.9","message":"Topic analysis complete in 108.9s — found 19 topics","detail":null},{"elapsed":"306.9","message":"Analysis tokens: 31,343 in / 1,542 out / 4,254 thinking — cost: $0.1322","detail":null},{"elapsed":"306.9","message":"Pipeline finished in 306.9s — total cost: $0.3200 (254,393 tokens)","detail":null}]} \ No newline at end of file diff --git a/history/1775224185561-C0DMdUqF73Q.json b/history/1775224185561-C0DMdUqF73Q.json new file mode 100644 index 0000000..c806c2a --- /dev/null +++ b/history/1775224185561-C0DMdUqF73Q.json @@ -0,0 +1 @@ +{"id":"1775224185561-C0DMdUqF73Q","videoId":"C0DMdUqF73Q","url":"https://www.youtube.com/watch?v=C0DMdUqF73Q","title":"The Best Vitality & Health Protocols | Dr. Rhonda Patrick","type":"youtube","topicCount":28,"segmentCount":649,"createdAt":"2026-04-03T13:49:45.561Z","uploadDate":"20260323","chunks":[{"title":"Intro & Short Burst Exercise","summary":"Dr. Andrew Huberman introduces Dr. Rhonda Patrick, acknowledging her pioneering role in science-based health education, and briefly previews the massive benefits of short 'exercise snacks'.","entries":[{"text":"Dr. Rhonda Patrick: There's a lot of data now showing that people that are doing these, like short bursts, at least a minute long, but up to three minutes, they're moving faster with intent and it's having outsized effects on, on health outcomes. So for example, individuals that do on the high end, so they're doing, you know, three minutes of this short burst of an unstructured type of exercise snack, and they do it three times a day, so it's a total of nine minutes a day, okay? That's associated with a 40% reduction in all-cause mortality, 40% reduction in cancer-related mortality, and 50% reduction in cardiovascular-related mortality.","offset":0,"duration":36},{"text":"Host: Wow. Nine minutes a day. Welcome to the Huberman Lab Podcast, where we discuss science and science-based tools for everyday life.","offset":36,"duration":18},{"text":"Host: I'm Andrew Huberman, and I'm a professor of neurobiology and ophthalmology at Stanford School of Medicine. My guest today is Dr. Rhonda Patrick, a biomedical scientist and leading public health educator. For over a decade, Rhonda has been one of the most trusted voices in building science-based health protocols. Today we discuss what the latest and best research says we should all be doing to improve our health and vitality and avoid disease.","offset":54,"duration":27},{"text":"Host: Rhonda shares with us her exact exercise, nutrition, supplementation, and sauna protocols, and we get really detailed about the mechanisms and logic behind each one. We also discuss the things that science says you can do to significantly reduce your cancer and cardiovascular risk, including how to reduce visceral fat and arterial plaque.","offset":81,"duration":24},{"text":"Host: Today's discussion truly leaves no stone unturned. We discuss how eating can increase inflammation, believe it or not, ways to support your gut health, creatine, vitamin D, why broad vitamin and mineral and fiber support is crucial, as well as the different forms of magnesium and each of their unique effects.","offset":105,"duration":23},{"text":"Host: We also discuss omega-3s, and why prescription sources of omega-3s may be the cleanest and most cost-efficient way to obtain sufficient omega-3 intake. We also discuss the importance of prioritizing regular resistance training and HIIT workouts over protein. You still need protein, but emphasizing the exercise component is crucial.","offset":128,"duration":22},{"text":"Host: And we discuss fiber, micronutrients, and why short-term fasting can be beneficial. Dr. Rhonda Patrick is a true wealth of knowledge, and today, she generously provides us a masterclass on how you can design and adjust the exact health protocols to meet your specific needs.","offset":150,"duration":21},{"text":"Host: Before we begin, I'd like to emphasize that this podcast is separate from my teaching and research roles at Stanford. It is, however, part of my desire and effort to bring zero-cost to consumer information about science and science-related tools to the general public. In keeping with that theme, today's episode does include sponsors.","offset":171,"duration":22},{"text":"Host: And now for my discussion with Dr. Rhonda Patrick. Welcome back, Dr. Rhonda Patrick.","offset":193,"duration":6},{"text":"Dr. Rhonda Patrick: Excited to be here.","offset":199,"duration":1},{"text":"Host: It's been a while, I'm so excited, there's so much to go into. And I'll start off the same way I started last time, because it's even more true. Thank you for being first person into this public science health education business. I don't know if everyone's aware of it, but you were the first person in, which is why I didn't say first man in, because the first person in was and is a woman, and you've done a marvelous job of educating people on science, how to parse papers and data, health practices, and, you know, the rest of us are just trying to follow in your wake. So thank you very much, I just want to thank you for being first.","offset":200,"duration":42},{"text":"Dr. Rhonda Patrick: Oh man, thank you so much for that, and also thank you for doing what you do. I mean, you really do a great service for science communication, um, education, helping people love science and get healthier.","offset":242,"duration":12}],"startTime":0},{"title":"Competitive Jump Roping Background","summary":"Rhonda shares her background as a competitive jump roper, discussing the cardiovascular and bone density benefits of the activity.","entries":[{"text":"Host: Well, thank you. Well, you're the pioneer, it's not always easy being a pioneer, but we all benefit, so. Let's jump in at exercise, because, um, lately you've actually been posting your workouts, which is awesome, and you're clearly very fit. I learned before talking to you today that you were a competitive athlete, you were a long jumper or triple jumper?","offset":254,"duration":22},{"text":"Dr. Rhonda Patrick: I was a long jumper, but I would say my real competitive athleteness comes from my jump roping.","offset":276,"duration":6},{"text":"Host: Okay.","offset":282,"duration":1},{"text":"Dr. Rhonda Patrick: I was on a professional jump roping team.","offset":283,"duration":2},{"text":"Host: Professional?","offset":285,"duration":1},{"text":"Dr. Rhonda Patrick: Yes. Yeah, it was, it was we would compete, so my friend and I started the team when we were in second grade, and it was called the San Diego Sand Skippers. And it was part of the International Rope Skipping Organization, which was actually started by her uncle, but there's jump rope teams all around the world, and you know, now I think there's a new name, but like it got taken over by the universal jump rope team or something like that, I don't know exactly what it is, but so I was on a team and every year we would compete in Boulder, Colorado. There were competitions for all kinds of, you know, jumping rope, and um, I would perform and start jump rope teams around the school around different schools in San Diego. So I used to get out of school, um, you know, get out of school free card, and my partner and I would go and start workshops at other schools and help them start jump rope teams. And the idea was cardiovascular health, healthy heart, and yeah, so so that's really, I would say my, my real roots with being a competitive athlete.","offset":286,"duration":65},{"text":"Host: Awesome. I love skipping rope. Is it okay to say skipping rope or jumping rope?","offset":351,"duration":4},{"text":"Dr. Rhonda Patrick: Yeah, okay. Skipping rope, jumping rope.","offset":355,"duration":1},{"text":"Host: And actually, it's a great opportunity for me to ask you what your thoughts are about, um, exercise that isn't just linear, right? I know like real jump ropers can do crossovers and um, and these days I'm seeing a lot more about rope flow. I think it's David Weck and others online are, you know, stuff that's getting people out of the standard, you know, curls, bench press, um, lunges, you know, and getting movements that are more just for lack of a better term, across the body. Do you think there's something to that in terms of real physical benefits? I mean, I imagine there is.","offset":356,"duration":37},{"text":"Dr. Rhonda Patrick: Sure. I mean, I wouldn't be the expert to be able to give you a good answer on that, but I do think that jumping rope in general has unique benefits in addition to obviously it's a great cardiovascular exercise, you're getting the weight-bearing aspect as well for building bone density, and I think that earlier for me, you know, I was doing it as a young girl, so important, right? Because you're kind of banking that, that bone density early on, which is important because at some point, you know, menopause will hit and and estrogen goes down and and so you start to lose more bone. But um, yeah, I'm sure there's a lot of benefits to jumping rope beyond what I'm describing as cardiovascular benefits and bone benefits that someone else could answer.","offset":393,"duration":45},{"text":"Host: Well, I'm certainly going to get back to jumping rope now that we resurrected it in this conversation. And I have to say, um, bone density measurements aside, you have awesome posture. I notice people's posture.","offset":438,"duration":13},{"text":"Dr. Rhonda Patrick: Oh, really?","offset":451,"duration":1}],"startTime":254},{"title":"Vigorous Exercise Routine & Brain Health","summary":"Rhonda details her weekly exercise routine, which includes high-intensity interval training, rowing, running, and Tabata. She outlines the immediate benefits of vigorous exercise on executive function, serotonin, and impulse control.","entries":[{"text":"Host: Yeah, I didn't even mean to put you on the spot here, but yeah, when I walked in, I was like, if you've ever interacted with Rhonda in person, which I have, you have amazing posture. And these days, good posture is rare, so who knows, maybe the things are are related, I imagine they probably are, bone health and posture and so forth. In terms of the sorts of exercise that people are more familiar with, what's your routine look like? And what sorts of things in your routine are non-negotiables, and where's the place for experimentation and kind of what you're exploring now?","offset":452,"duration":39},{"text":"Dr. Rhonda Patrick: So for me, exercise is part of my personal hygiene, as you and I were discussing. It it really is a non-negotiable. I absolutely have to do exercise just like I have to brush my teeth, and um, you know, I kind of got that from Dr. Ben Levine, who is a, you know, probably one of the world-leading cardiovascular exercise physiologists. He's at UT Southwestern in Dallas. I just want to shout out his name because I've really learned a lot from him.","offset":491,"duration":27},{"text":"Dr. Rhonda Patrick: But the non-negotiables for me really are getting cardiovascular exercise and getting my my resistance training. So building muscle, maintaining muscle strength as well. So my routine for me, I work out probably about five to six hours a week, and those workouts, I largely am doing a combination of high-intensity interval training that's not necessarily like the Norwegian 4x4, where I'm going as hard as I can for one minute or four minutes and then recovering for three minutes and doing that four times. That's really, you know, the Norwegian 4x4 is a hard workout. It's really good for improving your cardiorespiratory fitness, which I think is one of the best markers for longevity. We can talk about that.","offset":518,"duration":51},{"text":"Dr. Rhonda Patrick: Um, I do a lot of, you know, it's a it's a mixture of doing, you know, rowing machine, getting on the assault bike, and then doing mixed in mixing it in with lifting weights, doing some deadlifts, you know, doing squats. Um, so it's really for me a non-negotiable to to do my my vigorous intensity exercise is what I would call it. So you're really kind of getting your heart rate up to, you know, 80% max heart rate at at points, not always, but especially during the intervals. I would say that's a non-negotiable for me.","offset":569,"duration":45},{"text":"Host: How many days a week are you doing that?","offset":614,"duration":2},{"text":"Dr. Rhonda Patrick: I do my my longer HIIT workouts, so I have four days a week where I'm doing at least an hour. So two of those two of those sessions are more of a CrossFit type of training, where I'll do the first 30 minutes will be strength training. So I'll just be lifting heavier with like, you know, fewer reps.","offset":616,"duration":19},{"text":"Host: What's the rest between sets? Sorry to get granular, but people will wonder.","offset":635,"duration":4},{"text":"Dr. Rhonda Patrick: Um, what's funny is I typically rest about two minutes between my sets. I I recover pretty quick. Um, and my I do it with a coach, and my coach usually tells me that I'm spot on. I'm like ready to go, and it's been about two minutes. So I usually that's my recovery time. And so the first 30 minutes of strength training, and that'll be like deadlifts, it'll be, you know, squats, I'll be cleaning, I'll be doing front squats, sometimes I do barbell or back squats, right? Like it's a mixture of different types of strength training. And then the last 30 minutes is more of a high-intensity interval training session. So it'll be like, you know, where I'm I'm getting my heart rate up, so I'm mixing in the rowing machine and then I have like maybe I'm doing cleans, but they're lighter, so it's like more reps, but lighter load, right?","offset":639,"duration":50},{"text":"Dr. Rhonda Patrick: So, um, that's I do that twice a week, and that each is an hour session. And then I do also twice a week, about an hour and 20 minutes of it's also more high-intensity, but I have more recovery time because I'm doing it with my girlfriends, and we kind of chit-chat a little bit, and so um, but it's very similar, we do, you know, rowing machine, assault bikes, we do the skier, you know, Rogue has that skier, and then we mix it in with, you know, chest presses, and we do, you know, assisted pull-ups, and we do, you know, lighter squats with like larger, you know, more reps.","offset":689,"duration":43},{"text":"Dr. Rhonda Patrick: So that's another, you know, two hours a week. So now I have four hours a week of just doing a lot of that sort of CrossFit, HIIT type of training. And then I mix that in with my more like runs that I do, which are I would say are still they're still considered vigorous intensity, they're just not quite as high-intensity. And I do probably I run like maybe six miles a week, so maybe maybe at my max, but these days I'm mostly running probably four like four miles a week. So um, those runs tend to be like sometimes they're two miles, sometimes they're three miles, and um, you know.","offset":732,"duration":59},{"text":"Host: Do you enjoy running?","offset":791,"duration":1},{"text":"Dr. Rhonda Patrick: I do. I do. And I think it's important as well, and sometimes I'll run with my husband and we just kind of like chill out and talk and um, you know, it's a nice time for me as well just to kind of do that with him. Um, and then on weekends I'll probably do like a hike with my family, and sometimes we'll do like a sprint up the hill and, you know, but it's more just enjoyable time in nature, um, still moving, but, you know, it's kind of family time too.","offset":792,"duration":34},{"text":"Host: Weight vests on the run or hike?","offset":826,"duration":2},{"text":"Dr. Rhonda Patrick: No, I don't, not I mean, I'm kind of wanting to experiment with that, but not really. I'm just kind of sometimes we bring our puppy and you know, so it's it's more about the experience I think than like I'm like I get a lot of workout throughout the week.","offset":828,"duration":14},{"text":"Host: Sure.","offset":842,"duration":0},{"text":"Dr. Rhonda Patrick: But it's like you said, it's non-negotiable for me, and and times when I'm like like today, so I you know, I had a long drive and so I got on my Peloton and I did a 10-minute, you know, I did a 10-minute Tabata back-to-back, so it was like two back-to-back Tabatas, right? So it was it ended up being 10 minutes, it was like 30-second recovery in between the two Tabata sessions, 2:1 ratio, 20 seconds on, 10 seconds off, but like I have to do something every day, and if I'm traveling or I have like an early podcast or something, I'll I'll just jump on the bike and I have to get that blood flow.","offset":842,"duration":38},{"text":"Dr. Rhonda Patrick: Sometimes I'm in my hotel room and I don't want to go to the gym, I don't have time, and I just in my room, you know, I do I do air squats, I'll do high knees, jumping jacks, and I repeat for 10 minutes and I'm getting my heart rate up and I'm, you know, I've got sweat on my brow, like I'm not it's not like the most intense workout, but it's so important for me, you know, it's there's there's a variety of brain benefits that have been shown with even just 10 minutes of this vigorous type of intensity of workout you do, you know, where you're I mean, you probably have seen this this data where it's like just 10 minutes of this vigorous type of exercise you're immediately increasing neuronal connections. Um, they there's been studies showing that you have an improvement in executive function by like 14%, which is pretty big.","offset":880,"duration":62},{"text":"Dr. Rhonda Patrick: I think it was like a 50 50-millisecond improvement processing speed or something, which doesn't sound a lot, but it actually translates to a big improvement in executive function. So my brain works better, I feel better, you know, better mood, um, there's even studies that have compared impulse control after various types of intensity of workout. So like there was one study that compared a more low-intensity versus moderate-intensity versus high-intensity. So you're talking about like walking versus maybe, you know, jogging slowly where you can still have a conversation versus like you're doing a HIIT workout, right? When you're on, when you're on, you're not really talking because you're going as hard as you can during that interval. And it was the high-intensity, you know, vigorous intensity exercise that really increased plasma serotonin, which has been shown to associate with brain serotonin, those studies have been done.","offset":942,"duration":69},{"text":"Dr. Rhonda Patrick: And serotonin is very important for as you know, for impulse control. I mean, a lot of people think about serotonin with respect to mood, because we have these selective serotonin reuptake inhibitors, SSRIs, that are used to treat, you know, depression, major depressive disorder. But serotonin, as you know, does so much more than that, and impulse control is one of the the the big things that serotonin plays a role in, and so those studies showed that plasma serotonin increased in the higher intensity group and that correlated with improved impulse control. So, of course, for us now in the modern day society that we live in, we're constantly being bombarded with, you know, social media and all these things and like you have to be able to kind of like filter that out and not like just go with the impulse of check my social media, check my, you know, and um, how many likes did I get or whatever, you need to just be able to focus and so that for me, you know, serotonin is important and so I like to get that vigorous intensity exercise as well.","offset":1011,"duration":68}],"startTime":452},{"title":"Sponsors: Our Place & Lingo","summary":"Huberman reads sponsor messages for Our Place cookware and the Lingo continuous glucose monitor.","entries":[{"text":"Host: I'd like to take a quick break and acknowledge our sponsor, Our Place. Surprisingly, toxic compounds such as PFASs or forever chemicals are still found in 80% of non-stick pans, as well as utensils, appliances, and countless other kitchen products. As I've discussed before on this podcast, these PFASs or forever chemicals, like Teflon, have been linked to major health issues such as hormone disruption, gut microbiome disruption, fertility issues, and many other health problems. So it's very important to avoid them.","offset":1079,"duration":33},{"text":"Host: This is why I'm a huge fan of Our Place. Our Place products are made with the highest quality materials and are all PFAS and toxin-free. I particularly love their Titanium Always Pan Pro. It's the first non-stick pan made with zero chemicals and zero coating. Instead, it uses pure titanium. That means it has no harmful forever chemicals and it does not degrade or lose its non-stick effect over time. It's also beautiful to look at. I cook my eggs in my Titanium Always Pan Pro almost every morning. The design allows for the eggs to cook perfectly without sticking to the pan.","offset":1112,"duration":35},{"text":"Host: Right now, Our Place is having their biggest sale of the season. You can save up to 40% sitewide now through April 12th. Just head to fromourplace.com/huberman. Again, that's fromourplace.com/huberman to save up to 40%.","offset":1147,"duration":18},{"text":"Host: Today's episode is also brought to us by Lingo. One of the most important factors in your short and long-term health is your body's ability to manage glucose over time. Glucose directly impacts our brain function, mood, and energy. You want your glucose relatively stable across the day, without big peaks or valleys. This is why I use the continuous glucose monitor and app from Lingo by Abbott. Lingo provides minute-by-minute glucose data directly within the app, showing you how your glucose responds to food, exercise, and stress. This information can help you make smarter choices to support your health both now and in the long term.","offset":1165,"duration":42},{"text":"Host: The CDC estimates that more than one in three American adults has pre-diabetes, and that many of these people don't know they are living with pre-diabetes. Visibility about how your diet and activity affect your glucose can be the first step toward informed conversations with your doctor and making smarter daily choices.","offset":1207,"duration":18},{"text":"Host: If you'd like to try Lingo, Lingo is offering Huberman Lab listeners in the US and UK 10% off a four-week plan. Just visit hellolingo.com/huberman for more information. Terms and conditions apply. Again, that's hellolingo.com/huberman.","offset":1225,"duration":19}],"startTime":1079},{"title":"Phone Distractions During Workouts","summary":"A brief discussion on the importance of compartmentalizing gym time and leaving smartphones behind to avoid digital distractions.","entries":[{"text":"Host: I love that you mentioned other other functions of serotonin, because as you point out, it is so heavily associated with this mood aspect and certainly has a role there, but um, the impulse control piece is I think is a non-trivial aspect to um the effects of exercise and just generally. I'm curious, do you bring your phone or feel compelled to check your phone during workouts? Are you able to just say I'm compartmentalizing now, this is the workout, you might put on music or check maybe text here or there if you need to, but are you able to compartmentalize or um do you struggle with the the phone during workouts?","offset":1244,"duration":35},{"text":"Dr. Rhonda Patrick: Oh, I don't bring my phone to my workout at all. Like I don't No, I do have a watch that I wear that, you know, if there's like an emergency I'll get a text message, oftentimes I put it on silent like on no notifications because I don't want to be bothered. But I don't I don't really check my phone. Um I I don't really like checking things like social media for me, it's just a distraction and and frankly, I think it's terribly terrible for people's brains, even though like my business kind of depends on it somewhat, I think I think social media is not really good for people to be honest. Um, so I don't really check my phone or bring my phone to my workouts. My workouts are I like to chat with my friends when I'm working out with them and that's fun.","offset":1279,"duration":45},{"text":"Host: But in real life.","offset":1324,"duration":1},{"text":"Dr. Rhonda Patrick: Yeah, so that's IRL as the kids say.","offset":1325,"duration":3},{"text":"Host: Yeah.","offset":1328,"duration":1},{"text":"Dr. Rhonda Patrick: That's in real life, and um, yeah, phones phones for me are not something that I bring to my workout.","offset":1329,"duration":6}],"startTime":1244},{"title":"Heavy Weight Training & Mental Toughness","summary":"Rhonda breaks down her strength training regimen, explaining how working down into heavy singles and doubles builds mental fortitude and enlarges the anterior midcingulate cortex.","entries":[{"text":"Host: Great. Yeah, I've um been experimenting with not allowing the phone in my gym and just the workouts go so much better and I find that the mental and physical resetting aspect of working out just seems to be enhanced. But um, sounds like you were already there and I'm just arriving, so. I have a couple other specific questions about your workouts, because uh for my own interest and I know many people will wonder, for the dedicated weight workouts, are these whole body workouts? And you said low reps, um maybe you could just tell us what low reps is for you and then the um seems like the ever-present question is to failure, close to failure, I mean, um just to you know round out that that portion of the of the workout picture.","offset":1335,"duration":41},{"text":"Dr. Rhonda Patrick: The workouts that I'm doing with my strength training workouts with my coach, you know, it it really depends most of those workouts are they're multi-joint workouts, so I am most of the time doing, you know, some either front squat, back squat, or I'm cleaning it as well, right? Which obviously the leg the weight goes down if I'm doing if I'm cleaning it because it's hard to clean. It's also the hard like it's the thing that I hate doing the most.","offset":1376,"duration":29},{"text":"Host: Cleans.","offset":1405,"duration":0},{"text":"Dr. Rhonda Patrick: Oh yeah, cleans with front squat because it's really hard, and um for me. I mean, for others who've been doing it for years, I'm sure it's like, you know, they love it. But for me, it's very hard. I've only been doing cleans since, you know, February 2024. So I'm pretty new to it and and so it's mentally like I have to overcome that challenge, which by the way once I started doing all this sort of weight training, I've always been endurance junkie, like I like I used to like to go on long runs and, you know, races and stuff like that. So for me, that's like my safe spot, right? That's what comes easy to me. Uh weight training and resistance training, strength training definitely not something that I've done my whole life. I'm so glad that I started doing it, but very very challenging for me and so I would say the biggest effect was on my brain and the ability to handle stress better where it was like unbelievable because it was so hard and I I just didn't want to do these cleans, you know, and and these front squats, um, and then the rest of my day was not as hard. And that to me was like the biggest surprise for this type of training.","offset":1405,"duration":72},{"text":"Dr. Rhonda Patrick: But anyway, so um, I do a variety of if I'm doing if I'm going heavier, then it, you know, depends. Sometimes we'll start off as okay, we start off we do five reps and then we go down to four, and then we go down to three, and then we go down to one, right?","offset":1477,"duration":14},{"text":"Host: You're doing singles.","offset":1491,"duration":1},{"text":"Dr. Rhonda Patrick: We do.","offset":1492,"duration":1},{"text":"Host: Okay.","offset":1493,"duration":1},{"text":"Dr. Rhonda Patrick: I know yeah, yeah. And that's the hardest. It's the hardest. But then there's there's like my coach will be like it's just one, it's just one. You know, sometimes we'll do like six, five, and then we do four twice, and then we do three twice, right? And so it all depends, you know, also on the day. There's some days where I'm just like, you know, can we do lower reps and like lighter weight, right? Where I'm just like it's this is the day for me. I'm I'm stressed, I'm not I'm not here like so you kind of have to modify your workout, right? According to how you feel that day. Um, but I would say that those the majority of my strength training workouts are or deadlifting, you know, I love dead deadlifting. I think I'm pretty good at at pulling that weight up, lifting that weight up.","offset":1494,"duration":45},{"text":"Host: That's with the straight bar, hex bar? Mixed grip? There's so many variables, but yeah.","offset":1539,"duration":3},{"text":"Dr. Rhonda Patrick: Straight bar. Straight bar. And um it's the same deal with that. Like most of the time with strength training we'll do, you know, we start off at like five or six and then work our way down and then I I usually do a drop set after, you know, any of those sessions where I'll do 10 and then it's like a lot lighter, right? So those those are typically my strength training sessions are multi-joint. Sometimes I'll do accessory sessions, you know, where I'm working I do, you know, the dips um or the Bulgarian, you know, the Bulgarian split squats. I mean, just the accessory stuff that you're working the like smaller stabilization muscles and stuff like that.","offset":1542,"duration":40},{"text":"Host: I love that you call Bulgarian split squats accessory smaller muscles. For a lot of people, that's the compound work, which is just I have to say I I am inside I'm just like so delighted because, I mean, obviously uh weight training is something that's caught on broadly for men and women now, but I don't know many women, and I know they're out there, but I don't know many women who are uh working down into singles on multi-joint like real multi-joint, like, you know, deadlifts, cleans. I know they're out there, but it's not that common to see in gyms and uh this is going to no doubt spark a debate because, you know, some of the older, slightly ornery, but very credentialed strength training folks have been online recently saying that as people um pass 35, that they shouldn't do squats, that they shouldn't do deadlifts, and certainly shouldn't do them heavy because it because of this whole thing of, you know, you can do higher reps and take it to failure and still get hypertrophy. But what I love is that you're not necessarily talking about hypertrophy, maybe some hypertrophy, but this is about strength. This is about building more strength and triples and doubles and singles. That's awesome.","offset":1582,"duration":70},{"text":"Dr. Rhonda Patrick: It's hard. It's so hard. And it's the part that I'm like all about let's like the last 30 minutes where it's HIIT and and that's hard too, it's a different kind of hard. But for me, the strength training is the hardest and there's definitely a mental component, right? Where I do not want to do it. It's like you talk about with cold plunging, right? Like you do you just it's so unpleasant and you don't want to do it and like you do it and it's like that mental toughness that you're building, right? That's what I experience when I'm doing these, you know, strength training exercises that I'm doing. And and I don't know if it's going to get easier, maybe it will. It hasn't yet. I still I still dread it, but I do it and um I'm proud of myself for doing it, but it is it's definitely hard and I am getting stronger I think mentally and obviously physically as well. But um, have to add in the aerobic as well though. I think that's really important.","offset":1652,"duration":53},{"text":"Host: That's your base. Yeah.","offset":1705,"duration":1},{"text":"Dr. Rhonda Patrick: Yeah.","offset":1706,"duration":1},{"text":"Host: You love it.","offset":1707,"duration":1},{"text":"Dr. Rhonda Patrick: I love it and I do think cardiorespiratory fitness is very important, you know, for for long-term health as well as, you know, obviously building muscle and strength.","offset":1708,"duration":8},{"text":"Host: Well, on the one hand I want for you as a friend to for you to hate the heavy work less. On the other hand, I don't, because of this literature I'm sure you're familiar with it, but uh the anterior midcingulate cortex. This brain area that is hyperplastic throughout the lifespan, which is rare for a brain area, and it enlarges um when we do things we don't want to do. I mean, it's so clear, it's not just about doing hard things about it's about doing the hard thing you hate. And and for you that sounds like the heavy compound movements. For me, yeah, I don't like the cold plunge, which is why I do it. I don't think it's magic. I just think it's a it's a surefire stimulus that I hate to to get mentally stronger.","offset":1716,"duration":44},{"text":"Host: And I think um having something that you really despise that you know is good for you seems to keep this anterior midcingulate cortex volume either increasing or the same, and that's actually the thing in these so-called superagers that is the strongest anatomical correlate that we have. So on the one hand I hope it gets easier, on the other hand for your sake I hope it doesn't get uh easier because it's still it's going to be so much more beneficial.","offset":1760,"duration":21},{"text":"Dr. Rhonda Patrick: Well, I have a coach who can tell when it's getting easier and she will definitely up the weight. I I mean, it keeps I mean, it keeps going up. And so it doesn't it gets easier in a sense, but it doesn't, right? So I mean, I think that's that's the whole point is you're building strength and you keep making it heavier and it becomes harder again because now it's heavier.","offset":1781,"duration":23},{"text":"Host: Awesome.","offset":1804,"duration":1},{"text":"Dr. Rhonda Patrick: But um and I haven't gotten injured, so that's also, you know, knock on wood.","offset":1805,"duration":4},{"text":"Host: Yeah, no, knock on wood. I um thank you for rounding out that picture. It's super inspiring for men and women, you know. So.","offset":1809,"duration":7},{"text":"Dr. Rhonda Patrick: It's not easy to post on social media because obviously I'm a newbie. So I have all sorts of, you know, things that I could ways I could improve, but I'm posting it, you know.","offset":1816,"duration":10},{"text":"Host: Well, and the fact that you're working down into triples, doubles, and singles, I think is something that I'm trying to do more of and I think um this notion that you can get hypertrophy with higher reps if you take it to failure, sure I totally agree, read the studies, totally agree with the data, but not everything is about hypertrophy. I think that's what people forget. It's not all about growing muscle. Um, and VO2 max, which is great, but it's it's not all about um the top contour, and I what I love about the way you approach everything is you're you go through multiple layers of the of the health strata as it were.","offset":1826,"duration":34}],"startTime":1335},{"title":"Protein Intake, Diet Composition & Fasting","summary":"Rhonda explains her approach to protein consumption and how intermittent fasting and portion control helped her reduce visceral fat. They also discuss avoiding ultra-processed carbohydrates.","entries":[{"text":"Host: This is probably a good opportunity to talk about protein, because I have a very specific question about protein. We all hear one gram of quality protein per pound of body weight or lean body weight, that's sort of what we're kind of what's thrown at us. By doing the heavier weight training, do you notice that your protein appetite has increased? Like appetite specifically for protein foods?","offset":1860,"duration":18},{"text":"Dr. Rhonda Patrick: I don't know that I have, you know, I interestingly have been doing a little bit more intermittent fasting in which, you know, people think about intermittent fasting, they think about it as just one thing, one intervention. I think it's two. There's a behavioral aspect to it where it's a tool to sort of lower the amount of calories you're taking in. The other one would be this metabolic switch. But so I've actually since I don't know, September maybe, last September of 2025, been been doing more intermittent fasting, and what I mean by that is just really just eating less. And um the reason for that is because I noticed that everything that I was doing, which was, you know, I'm I eat healthy, I exercise a lot, and yet I was sort of gaining more fat in the the belly section, right? The visceral fat.","offset":1878,"duration":55},{"text":"Dr. Rhonda Patrick: And the only thing that really helped me stop that, but the put the brakes on, was getting more in a caloric deficit. Um, so maybe my drive to do that kind of is skewing whether or not my appetite for protein would go up. But I personally am on the scale of 1.2 to 1.6 grams per kilogram body weight, which is","offset":1933,"duration":23},{"text":"Host: Per kilogram.","offset":1956,"duration":1},{"text":"Dr. Rhonda Patrick: Per kilogram, which is probably a little bit less than the pound.","offset":1957,"duration":4},{"text":"Host: You know, it's it's a kind of a throwaway statement a gram of quality protein um as defined as something with, you know, lots of the essential amino acids and uh so forth per pound or per lean pound of body mass. Um, which is something I think I and many other people shoot for, but I'm curious how religious you are about the, you know, getting a certain protein amount or per meal.","offset":1961,"duration":23},{"text":"Dr. Rhonda Patrick: Basically, it wasn't working for me in terms of like I was really trying to get aim for like the higher end of the for me, you know, 1.6 grams per kilogram body weight or even a little bit above that. And what I found what was happening is that I was actually gaining gaining more weight because I think I was consuming more calories at the same time besides if you're getting it from whole foods, right? Like that's just kind of naturally going to happen.","offset":1984,"duration":24},{"text":"Dr. Rhonda Patrick: Uh and so I had to slide down um. But I'm still like I said, I'm still getting within that range of like probably on average maybe 1.3, 1.4 grams per kilogram body weight. And it's really it's really worked well for me, but like people are different and you have different goals, right? You know, like I'm gaining muscle mass and I feel like all my training is like the most important thing, and I think that we need generally speaking, I think people should become more obsessed with training and less obsessed with protein. Like the protein will complement the training and as you mentioned, if you're training perhaps your appetite for protein will increase and so you'll start to eat, you know, more protein and less refined carbohydrates. I already wasn't eating a lot of refined ultra-processed foods in the first place.","offset":2008,"duration":45},{"text":"Dr. Rhonda Patrick: Probably not the answer you were expecting, but it's really um for me like I just focusing on getting more protein was was not working for my body um in terms of but then again I'm 47 years old.","offset":2053,"duration":12},{"text":"Host: Sure.","offset":2065,"duration":1},{"text":"Dr. Rhonda Patrick: You know, that perimenopause phase, very different than someone who's 37 maybe.","offset":2066,"duration":5},{"text":"Host: I don't know the answer to that. I I do know that I hear from more and more people these days that they are having a hard time getting that one gram of protein per pound of body weight. It feels like a lot to them, is what they're saying. They feel like they're kind of forcing themselves to do it.","offset":2071,"duration":13},{"text":"Dr. Rhonda Patrick: You shouldn't feel that way.","offset":2084,"duration":1},{"text":"Host: Exactly. So I'm actually really pleased with your answer, not because I have an agenda here, but because I and many other people seem to feel like unless there's a lot of resistance training or tremendous demands, like hiking, you know, while backpacking where you burn tons of calories, you're basically rucking like nine hours a day, right? Then um they have a hard time getting that much protein down. Um and I think that's also the case if people are eating starches, like I eat rice and oatmeal and some breads and things like that, not a lot of bread, but you know, it sounds like you eat starches.","offset":2085,"duration":34},{"text":"Dr. Rhonda Patrick: I do eat oatmeal too, it it does satiate you. These days, because I really kind of more focused a little bit on I did want to to calorically restrict somewhat without, you know, being unhealthy. Obviously you can take every stressor to a bad, unhealthy place, right? You don't want to starve yourself, you don't want to like not eat enough food. But um my my meals are mostly like healthy protein, so I have homemade turkey burgers, eat a lot of I eat a lot of those. And then I eat chicken, you know, I pasture-raised chicken, I do I do still eat wild Alaskan salmon and then I'll um also mix in some like filet mignon, like I like grass-fed steak as well. Yum.","offset":2119,"duration":39},{"text":"Dr. Rhonda Patrick: Those are my protein sources, and always I pair it with greens. So or like some sort of vegetable, most of the times it's greens because they're the most most micronutrient dense. And so these days I'm eating a lot of sautéed collard greens that are pre-prepared, has garlic and onion, and I'll put that, you know, I have that with my meal or I'll have some, you know, sautéed kale, sometimes I'll have a salad with it. But the portions are smaller, and like I said I also do a little bit of intermittent fasting, we can talk about that as well, but that's kind of these days what I'm doing for my meals.","offset":2158,"duration":33},{"text":"Dr. Rhonda Patrick: I haven't eaten as much. Sometimes I'll eat the high protein oats. They have those high protein oats that have have you seen those? They're pretty good.","offset":2191,"duration":8},{"text":"Host: No, I eat oatmeal, but I like protein foods, I like vegetables, I like fruit. I feel very lucky to like those foods mainly.","offset":2199,"duration":6},{"text":"Dr. Rhonda Patrick: Yeah.","offset":2205,"duration":1},{"text":"Host: And then the starch for me has to be very clean. I like oatmeal, rice, homemade pastas I'll eat, like if I go out I'll have sometimes I'll have some homemade pasta or or a sourdough bread or something, but I find that most starches that are out there in the world have a bunch of other junk in them, and I just feel lousy. I get kind of sleepy afterwards, it just so I it sounds like we eat pretty similarly, although I probably eat more starches than you do.","offset":2206,"duration":24},{"text":"Dr. Rhonda Patrick: It's the more processed types of carbohydrates that as you mentioned, it's like you typically you don't feel good after you eat them, and, you know, part of that's the post-prandial inflammatory response because some of those foods are a little more inflammatory. I mean, they have a lot of additives and stuff that are affecting the gut, gut permeabilization, you're leaking lipopolysaccharide into the bloodstream, right? That's activating the immune system.","offset":2230,"duration":21}],"startTime":1860},{"title":"Gut Permeability, LPS & Cardiovascular Risk","summary":"A deep dive into how refined foods and saturated fats can cause leaky gut. Rhonda explains how gut-derived lipopolysaccharides (LPS) can enter the bloodstream, trigger systemic inflammation, and lead to atherosclerosis by forming foam cells.","entries":[{"text":"Host: Yikes. We used to inject I don't do any animal experiments anymore, and I'm actually grateful to not do them. So I didn't like working on animals, but it was what we did until I decided to work on humans. But we used to inject LPS um to stimulate an inflammatory response to kind of prime a regeneration response that you could get through macrophages and things like that. And so LPS is a very potent way to generate local or even systemic inflammation. I think um hearing that some starches will stimulate LPS, that's uh interesting.","offset":2251,"duration":28},{"text":"Dr. Rhonda Patrick: Well, let me clarify.","offset":2279,"duration":1},{"text":"Host: It squares with my experience. I'm not challenging, no no no, I'm not challenging, it squares with my experience. I'm one of these I never get stomach aches, I never get headaches. If I do, something's badly wrong with my stomach or my head. But if I eat certain starches, I'll be like, oh, like I feel lousy, and I'm wondering if it's this.","offset":2280,"duration":16},{"text":"Dr. Rhonda Patrick: So we have about a gram of LPS in our gut, like that's on average because, you know, lipopolysaccharide is the outer component of a cell membrane of a gram-negative bacteria, right? And we have a lot of bacteria in our gut, gram-negative bacteria, right? Trillions of bacteria in our gut. So um when when we eat food, typically like our gut epithelial cells, they have a tight junction that's holding them together. When we eat food, they transiently open and then close. Like it's kind of a normal response, right?","offset":2296,"duration":27},{"text":"Dr. Rhonda Patrick: Um the the I would say the opposite end of the spectrum of that would be like celiac, where they eat gluten or something, it opens up and stays open and so you get like a ton of LPS leakage into the system which causes massive inflammation. It just happens with meals in general, you do get somewhat of a LPS response from a meal.","offset":2323,"duration":20},{"text":"Dr. Rhonda Patrick: Now the type of meal does matter. So what I when I say refined carbohydrates, it's not necessarily like healthy, you know, carbohydrates like vegetables. It's like you're eating something that is refined sugar, typically with saturated fat. So those types of foods really cause like LPS response, you know, it's it's inflammation, it's bad, it's hard on the gut. But the post-prandial inflammatory response essentially is that LPS getting into the system, activating the immune system, which draws the energy. I mean, it's like it's very energy consuming to activate your immune system, right? Which why that's why when you're sick, you're so sleepy too, right?","offset":2343,"duration":36},{"text":"Dr. Rhonda Patrick: Well, there's also cytokines that are somnogenic and promoting sleep, but like activating your immune system requires a ton of energy. And so when you're constantly activating the immune system, you know, that's an energy sink, right? And so you do feel tired and that's why a lot of times after a meal, you're feeling kind of lethargic.","offset":2379,"duration":21},{"text":"Host: So protein foods, uh of the sort that you listed off before, um do they cause less uh opening of the tight junctions of the gut?","offset":2400,"duration":7},{"text":"Dr. Rhonda Patrick: I think the the the big deal with it the opening of the tight junctions in the gut is, you know, I mean eating eating a big meal will do it, eating a very like ultra-processed food meal will do it. Interestingly enough, just eating a bunch of saturated fat without a fiber matrix, so like like butter, you're just like eating butter. Don't ever do that, but like if you just eat butter,","offset":2407,"duration":17},{"text":"Host: My niece when she was little, now she's all grown up, but when she was little, I uh I taught her how to eat like a little bit of Kerrygold butter and she loved it. So then we would do this thing where we'd we'd we'd do that. Um, we won't do that anymore.","offset":2424,"duration":13},{"text":"Dr. Rhonda Patrick: I mean, a little bit's fine, but like I mean, there's there's studies showing that it does, like saturated fat is hard on the gut. Like I said, it's a sliding scale. Like meals in general do it, but it's like you it's like you would think. The healthier foods that you're eating, like whole foods, you're getting less of that LPS response. And then of course there's gluten and that complicates the whole story, especially for people that are celiac, right? Because that","offset":2437,"duration":27},{"text":"Host: Which is a small percentage of people are actually celiac, right? But a lot of people seem to believe, and I believe them, that when they eat gluten they feel worse than when they don't eat gluten.","offset":2464,"duration":9},{"text":"Dr. Rhonda Patrick: I'm sure there's some people that are sensitive to gluten that do feel worse. And then I'm sure some of that's the nocebo effect, right? That's been shown with gluten in in particular. Did you have you seen that study? Where people there's been so so there were people that think they're, you know, gluten gluten sensitive and so they were enrolled in this study and um these individuals were separated into two groups. One group was given the gluten bread with gluten and the other group was given the bread without gluten. And the people that were given the bread without gluten had a terrible, you know, abdominal response, like they were bloated, they felt terrible. I mean, it was all and there was no gluten in the actual bread, but they thought there was.","offset":2473,"duration":38},{"text":"Dr. Rhonda Patrick: So it was thought that this is a nocebo effect where it's like the opposite of a placebo effect where you just you you've got that phenotype where you think things negative are going to happen and you can make them happen. You can change your immune system, you can change your brain signaling and, you know. So probably a combination of both with that regard. Um in addition to like the lethargy, so we're talking about I was talking about in the context, that's why it sparked my, you know, interest as like you were talking about feeling tired after a meal, and I do think that is part of that reason for feeling sleepy.","offset":2511,"duration":34},{"text":"Dr. Rhonda Patrick: But you know, what's interesting about LPS, you talked about injecting it to mice and I have also done experiments injecting LPS into mice. There have been studies where people have been injected with an amount of LPS that is, you know, similar to what you would find your gut releasing into your bloodstream or a placebo control which in this case was saline. And individuals that were injected with the LPS high amounts of inflammatory markers like TNF-alpha. I mean, we're talking like up to 50% increase over baseline, right?","offset":2545,"duration":33},{"text":"Dr. Rhonda Patrick: So high amounts of inflammation, which makes sense. LPS is activating the immune system, your immune system is like there's a foreign invader, right? It's not a foreign invader, it's just the food you ate that caused transient gut permeability. And those individuals also feel depressive symptoms and feelings of like social withdrawal. So the inflammation is affecting the brain, right? These inflammatory factors are getting in the brain, crossing the blood-brain barrier and affecting the way we feel.","offset":2578,"duration":25},{"text":"Dr. Rhonda Patrick: We know now that inflammation plays a big role in major depressive disorder and depression, not in all cases, but there's a subset, right? Where it's really like it does it seems to play a big role. In fact, interestingly there's been some studies showing that people that are that don't respond to SSRIs are have very high amounts of C-reactive protein. So this is the biomarker for a classical biomarker for inflammation, I would argue it's not that sensitive, but nonetheless it is a biomarker for inflammation.","offset":2603,"duration":24},{"text":"Dr. Rhonda Patrick: And so people that um don't respond to SSRIs have high amounts of inflammation which kind of raises this question of is there like this subset of depression that's really inflammatory driven, right? Um interesting. So so the LPS is affecting not only our our energy levels but also our mood. And then, you know, there's there's also evidence that so we know that LPS binds to LDL particles through lipid-lipid interactions. And in fact it's kind of part of the adaptive response.","offset":2627,"duration":29},{"text":"Dr. Rhonda Patrick: It's why you don't want to ever go get your cholesterol measured like after right after you're sick or had a very stressful event, something that causes inflammation because you will increase VLDL production increases and LDL production increases and it's sort of an an adaptive response to bind that LPS to prevent it from, you know, causing more damage. And so it actually binds to LDL particles on the ApoB protein. So ApoB is a protein that is on these lipoproteins and it's a a very important protein because that is what's used by the LDL receptors present on our liver to recycle LDL particles.","offset":2656,"duration":38},{"text":"Dr. Rhonda Patrick: And so what happens is these these LPS particles are now bound to, you know, our our lipoproteins and our lipoproteins are still doing their function, right? They're going around and they're they're donating triglycerides and and fatty acids and to some degree cholesterol to our cells that need it, right? We're constantly making new cells and repairing and we our cells need that. As they donate triglycerides and fatty acids, they get smaller in size, the lipoprotein. You probably heard of small dense LDL, right? Like that's a very dangerous type of LDL particle. And that's one that's kind of been donating along getting rid of triglycerides and um whatever. If you think about a train with cargo, it's donating the, you know, dropping off the cargo.","offset":2694,"duration":40},{"text":"Dr. Rhonda Patrick: And so um when it's time to get recycled back into the liver, what do you know, the ApoB proteins obscured by that LPS and it's not recycled. And so it gets lodged into the arterial wall and because there's an LPS bound to this, you know, small dense LDL particle, macrophages, which are as you mentioned, it's like the first line of defense against something like a bacterial invader, right? Come and chew it up, right? Gets rid of the problem. So macrophages come in because they're seeing this signal of LPS and think it's a foreign invader when it's actually just a small dense LDL particle bound to LPS that came from the gut. Tries to engulf it, but it can't because it's not bacteria, and you get the macrophage stuck to that lipoprotein LPS, you know, complex and you get the formation of a foam cell. You've probably heard of a foam cell. It's the beginning of atherosclerosis.","offset":2734,"duration":57},{"text":"Dr. Rhonda Patrick: And so this is where gut health and the food we eat is sort of it's linked to cardiovascular health, right? Gut permeability getting that LPS into our circulation's actually not a very good thing because you're you're basically, you know, slow dripping in that inflammation that inflammatory signal and it's wreaking havoc in our arteries, on our brain.","offset":2791,"duration":22}],"startTime":2251},{"title":"Sponsor: AG1","summary":"Huberman reads a sponsor message for AG1 foundational nutrition.","entries":[{"text":"Host: As many of you know, I've been taking AG1 for nearly 15 years now. I discovered it way back in 2012, long before I ever had a podcast, and I've been taking it every day since. The reason I started taking it, and the reason I still take it, is because AG1 is to my knowledge the highest quality and most comprehensive of the foundational nutritional supplements on the market. It combines vitamins, minerals, prebiotics, probiotics, and adaptogens into a single scoop that's easy to drink and it tastes great.","offset":2813,"duration":31},{"text":"Host: It's designed to support things like gut health, immune health, and overall energy. And it does so by helping to fill any gaps you might have in your daily nutrition. Now, of course everyone should strive to eat nutritious whole foods. I certainly do that every day. But I'm often asked if you could take just one supplement, what would that supplement be? And my answer is always AG1 because it has just been oh so critical to supporting all aspects of my physical health, mental health, and performance. I know this from my own experience with AG1, and I continually hear this from other people who use AG1 daily.","offset":2844,"duration":34},{"text":"Host: If you would like to try AG1, you can go to drinkag1.com/huberman to get a special offer. For a limited time, AG1 is giving away six free travel packs of AG1 and a bottle of vitamin D3K2 with your subscription. Again, that's drinkag1 with the numeral one.com/huberman to get six free travel packs and a bottle of vitamin D3K2 with your subscription.","offset":2878,"duration":25}],"startTime":2813},{"title":"L-Glutamine, Gut Health & Immune Function","summary":"After a brief recap on the vagus nerve and LPS, Rhonda shares how L-glutamine supplementation can support gut health and supercharge the immune system, particularly during times of high physical stress or pathogen exposure.","entries":[{"text":"Host: Thank you for explaining that so clearly, because I don't think anyone has ever explained how exactly gut health is signaling cardiovascular health or pushing or pulling down on or raising cardiovascular health. As a neuro guy, I think about the vagus nerve as the primary conduit between gut and brain and it I was recalling that LPS injected into the gut is how you actually experimentally induce a fever, because the and if you cut the vagus, no fever. So there's there seems to be something about the way that the gut communicates with with the brain and other organs that is critically dependent on the some threshold level of of of LPS. Um, thank you also for reminding us","offset":2903,"duration":35},{"text":"Dr. Rhonda Patrick: I have a coach who can tell when it's getting easier and she will definitely up the weight. I I mean, it keeps I mean, it keeps going up. And so it doesn't it gets easier in a sense, but it doesn't, right? So I mean, I think that's that's the whole point is you're building strength and you keep making it heavier and it becomes harder again because now it's heavier.","offset":2938,"duration":19},{"text":"Host: Awesome.","offset":2957,"duration":1},{"text":"Dr. Rhonda Patrick: But um and I haven't gotten injured, so that's also, you know, knock on wood.","offset":2958,"duration":3},{"text":"Host: Yeah, no, knock on wood. I um thank you for rounding out that picture. It's super inspiring for men and women, you know. So.","offset":2961,"duration":6},{"text":"Dr. Rhonda Patrick: It's not easy to post on social media because obviously I'm a newbie. So I have all sorts of, you know, things that I could ways I could improve, but I'm posting it, you know.","offset":2967,"duration":10},{"text":"Host: Well, and the fact that you're working down into triples, doubles, and singles, I think is something that I'm trying to do more of and I think um this notion that you can get hypertrophy with higher reps if you take it to failure, sure I totally agree, read the studies, totally agree with the data, but not everything is about hypertrophy. I think that's what people forget. It's not all about growing muscle. Um, and VO2 max, which is great, but it's it's not all about um the top contour, and I what I love about the way you approach everything is you're you go through multiple layers of the of the health strata as it were.","offset":2977,"duration":9},{"text":"Dr. Rhonda Patrick: So that was kind of always in the back of my mind. And then in my postdoc I did my postdoc with Dr. Bruce Ames and my colleague Dr. Mark Shigenaga was doing a lot of gut work and this is why I know a lot about the LPS and the gut like it's from him. Like brilliant guy he's now a photographer, like not in science at all, but brilliant guy and did a lot of really amazing experiments looking at, you know, gut permeability and things that can help buffer, you know, gut permeability.","offset":2986,"duration":29},{"text":"Dr. Rhonda Patrick: And one of those things were glutamine. So glutamine can get converted into these intermediates that are used by mitochondria in the gut epithelial cells and so it's like an easy source of energy as well for the gut. Now these are all animal studies, right? So take it with a grain of salt, right?","offset":3015,"duration":18},{"text":"Dr. Rhonda Patrick: Like cause at some point, you know, in my in my opinion animal studies are are really important for understanding the mechanism behind why things work and we need human studies, you know, as well looking at the totality of evidence is important. It's the human studies that we're lacking, there's not a ton of them there. The ones that I have found more compelling...","offset":3033,"duration":19},{"text":"Dr. Rhonda Patrick: ...not necessarily I mean with the gut health it's it's you know it's sparse with humans. Um I found more compelling with respect to glutamine and human studies was the immune system and this is where I started putting connecting the dots, right? Where I started coming across this literature of these endurance athletes who do get a higher amount of respiratory tract infections, you know.","offset":3052,"duration":22},{"text":"Dr. Rhonda Patrick: Like when I mean endurance athletes I mean these guys that are like out running marathons all year, like they're just constantly training for a marathon, right? And so they're really like they're putting a lot of demand, right? Energetic expenditure is happening at a really high rate. So um they're they're more prone to respiratory infections.","offset":3074,"duration":18},{"text":"Dr. Rhonda Patrick: And there's a few studies out there showing that if these athletes take a higher dose of glutamine, I think it's like 30 grams or something high like that, that they had a lower incidence of respiratory tract infections versus the ones that weren't doing it. And then I went back to my, \"oh I know that glutamine's really important for T-cell activation\" and I was like \"I'm going to take this because being being a mom and having a child that's bringing everything home like a vector, you know.\"","offset":3092,"duration":21},{"text":"Dr. Rhonda Patrick: You're like desperate.","offset":3113,"duration":1},{"text":"Host: You're the experiment.","offset":3114,"duration":0},{"text":"Dr. Rhonda Patrick: Yeah, exactly and I never used to get sick, ever! Like I would never get sick and then all of a sudden I was getting sick like three times a year and I was like \"Do I have cancer? Like what's going on?\" Like I literally was like worried. Um and and then I started taking glutamine. Now I take it just I only take 5 grams on a daily basis, but if if my son's sick, if there's any exposure, if it's like during the season, if I'm traveling, I go up to 15, I go up to 20.","offset":3114,"duration":25},{"text":"Host: All at once? Because it can be a little hard on the gut.","offset":3139,"duration":1},{"text":"Dr. Rhonda Patrick: No, no, not all at once. Not all at once, I usually do it like in fives. So I do 5 grams, 5 grams, 5 grams and you know I have to with the caveat of I do that, but I also take a lot of creatine as well and so I don't know which one or both, but like I really don't get sick. I'm not getting sick and even even if it's brought home in my house, I'm not getting sick and maybe it's a placebo and you know what I am A-okay with that because placebo effect is real, as long as I'm not getting sick.","offset":3140,"duration":28},{"text":"Dr. Rhonda Patrick: Um so I do think I think with the glutamine, you know, it's not something that I would feel comfortable saying that it's there's a lot of evidence, it's overwhelming and with confidence that it's improving gut health and it's improving immune, you know, it's going to help give your immune cells energy particularly if they need to be activated, you know, upon exposure to any pathogen. But I feel like it's worth experimenting with.","offset":3168,"duration":19},{"text":"Dr. Rhonda Patrick: Um perhaps maybe if someone has colon cancer that would be more of a concern because I did mention that cancer cells cancer cells love everything. Anything that's good for you, right? Folate I mean if you don't have enough folate you can cause double-stranded breaks to your DNA which lead to mutations that lead to cancer. But if you have cancer and you take a bunch of folate, you need folate to make new DNA and so they like the folate, right? So it's like...","offset":3187,"duration":22},{"text":"Host: It's an abnormal growth, so anything that's associated with... mTOR, I saw the recent study on taurine, which scared a lot of people because taurine's in a lot of energy drinks but that was an in vitro study. Uh, yes, I was going to ask, you know, um is there increased cancer risk if you're supplementing with glutamine because cancer cells love glutamine.","offset":3209,"duration":19},{"text":"Dr. Rhonda Patrick: Okay, so my personal opinion, I'm obviously not a medical physician, this is not a prescription, it's just my opinion, I I personally am not scared of getting cancer from taking glutamine. If I had a colon tumor in a tumor in my colon, the first site that the glutamine is seeing, maybe the liver as well since that's also the next step.","offset":3228,"duration":20},{"text":"Dr. Rhonda Patrick: But um barring like having a tumor already in my liver or in my colon, those would be the only you know types of situations that I would be worried about taking glutamine. I don't think it's going to cause cancer, right? Now I guess the question is like, \"what if you don't know you have one?\" Well hopefully the cost will come down on whole body MRIs. Actually the cost is coming down on whole body MRIs that hopefully more people are able to get those.","offset":3248,"duration":24},{"text":"Dr. Rhonda Patrick: It's not just such a high-end exclusive thing in the near future. Kind of like blood draws used to be like like panels of blood testing you only got them if you really needed them, now the cost of blood draws is reasonably low. So hopefully people will be more aware.","offset":3272,"duration":13}],"startTime":2903},{"title":"NAC Supplementation & Oxidative Stress","summary":"Huberman and Rhonda discuss using N-acetyl cysteine (NAC) to fend off illness, and caution against taking high-dose antioxidants daily as they can blunt beneficial exercise adaptations.","entries":[{"text":"Host: Yeah I will take a tablespoon of glutamine once or twice or three times a day if I'm feeling run down. You mentioned being exposed to pathogens from vectors of different sorts. Before we went on mic we were talking about NAC, n-acetyl cysteine. Um I take it once a day consistently, but I'll take it three times a day if I'm traveling a lot because I'm around sick people when I travel, especially in winter.","offset":3285,"duration":24},{"text":"Host: Or if I feel like I'm getting run down and there the data are pretty interesting, there's at least one study showing that it reduced flu transmission um where people were deliberately exposed to flu. I think it took the number of people that contracted flu compared to the placebo group somewhere from the high 70 percent area, um I don't remember the exact number now, we'll put a link to the study, down to maybe high 20s.","offset":3309,"duration":20},{"text":"Host: Which is pretty impressive. And an ER doc came on this podcast, Roger Seheult, who um and said he was a big proponent of of n-acetyl cysteine for people that are around sick people. Do you take NAC?","offset":3329,"duration":13},{"text":"Dr. Rhonda Patrick: So my only concern with taking it on a daily basis is it is a pretty powerful antioxidant and, you know, I think that we need to understand like antioxidants and the opposite which would be generating oxidation, right?","offset":3342,"duration":21},{"text":"Dr. Rhonda Patrick: Like it's not it's not like oxidation is bad, it's bad when it's constant slow drip oxidation that's damaging, you know, other parts of our body, DNA, proteins, lipids. Some oxidation you want like if you're exercising, right? There's a burst of oxidation.","offset":3363,"duration":12},{"text":"Host: To get the adaptation.","offset":3375,"duration":1},{"text":"Dr. Rhonda Patrick: To get the adaptations. And so my concern would be for one maybe timing it around your exercise so not taking it close to when you're exercising. And these studies come out of, you know, studies that have been done with high dose vitamin E plus vitamin C. I haven't seen a lot of vitamin C studies alone that are blunting exercise adaptations. There's maybe one at a high dose.","offset":3376,"duration":23},{"text":"Dr. Rhonda Patrick: Most of the time it's vitamin C and vitamin E. Vitamin E alpha-tocopherol, when I say high dose usually it's 400 IUs, just to give you a reference point the RDA is like 24 IUs, so we're talking high dose.","offset":3399,"duration":13},{"text":"Host: But a supplement can be 200 to 800, so it wouldn't be hard to blunt that exercise effect by accidentally. Yeah, I don't take vitamin E, it spiked my prostate specific antigen, which I was told is a is a known effect among urologists.","offset":3412,"duration":13},{"text":"Dr. Rhonda Patrick: The SELECT trial was done, so the SELECT trial was um was looking at selenium and vitamin E and if it could slow the progression of prostate cancer and it turned out that um the opposite was found and it was really kind of due to this high dose of alpha-tocopherol which also has other effects of um lowering another type of vitamin E in the body called gamma-tocopherol which is anti-inflammatory and I think that has something to do with inflammation actually can increase the the PSA, right?","offset":3425,"duration":28},{"text":"Dr. Rhonda Patrick: So anyways um the point here is that with NAC my only concern would be you know blunting the the oxidation that you're getting from beneficial because I know you're highly active.","offset":3453,"duration":11},{"text":"Host: I'm training hard, I don't want my train to be short-circuited from NAC. I'm perfectly happy to only take NAC if I'm feeling run down or exposed to um illnesses around me.","offset":3464,"duration":10},{"text":"Dr. Rhonda Patrick: So that's one that's one I take it, but it's mostly because of I wasn't familiar with the flu influenza data, that's interesting. I was just it's good for lung health, too.","offset":3474,"duration":8},{"text":"Dr. Rhonda Patrick: Like so although if smokers take it, I think it has the opposite effect where again it's like the cancer the pre-cancerous cells are using it to their benefit. You know we used to think antioxidants \"oh it's so good\" you know just more more more and it turns out it's not the case right?","offset":3482,"duration":17},{"text":"Dr. Rhonda Patrick: Like and that's why a lot of these other types of hormetic stressors or plant phytochemicals they're actually generating an antioxidant response endogenously in our body by activating these antioxidant pathways which are so much more powerful than what you would get from an antioxidant, right?","offset":3499,"duration":17},{"text":"Dr. Rhonda Patrick: And so that's kind of and it's not that you don't want some antioxidants it's just like you don't want to overdose on taking too much NAC and too much vitamin C and too much vitamin E. Because there's also something called reductive stress. So we know about oxidative stress, oxidative stress is when you're you're again you're causing these these reactive oxygen species to damage things like your DNA for example and over time eventually that happens in a part of the gene that can be oncogenic and lead to cancer.","offset":3516,"duration":28},{"text":"Dr. Rhonda Patrick: Well reductive stress is is like the opposite of that, so it's like too much of the reducing equivalents, like the you know the NADH, the NADPH, the you know so and it also has negative effects. So you kind of don't want to go too far on either ends of the of the spectrum but also you want instead of having this like slow leaking effect of these pro-oxidants that are happening from eating a bad diet, from you know inflammation, things like that, you want it to be a short burst where you switch it on, you have the adaptation, and it's off, right?","offset":3544,"duration":31},{"text":"Dr. Rhonda Patrick: And the adaptation the adaptation happens in the recovery period, right? When you're for example if you exercise that's a big burst of reactive oxygen species that is beneficial and you want it, right? And you don't want to blunt those adaptations and so that's that's kind of my concern with daily dosing of NAC.","offset":3575,"duration":17},{"text":"Host: Great. I don't cold plunge in the 6 to 8 hours after uh resistance training for exactly the reason you're talking about, yeah I want the inflammation, I want the increased blood flow, I don't want to short-circuit that. I'm perfectly happy to only take NAC under conditions where I'm run down and and that's also when I'll take glutamine. If you take L-glutamine regularly, I I personally observe that I get stronger at a steady state of starch intake.","offset":3592,"duration":23}],"startTime":3285},{"title":"Late-Night Meals & Cardiovascular Reset","summary":"Eating too close to bedtime keeps the body in a sympathetic state. Rhonda outlines new data showing that stopping eating three hours before sleep allows blood pressure to dip, significantly lowering cardiovascular risk.","entries":[{"text":"Host: And I don't like dropping starches too low because I get weak and I also can't sleep as well if my starches are too low. I just am too wired.","offset":3615,"duration":8},{"text":"Dr. Rhonda Patrick: Yeah, there's there was a new study on on eating starches and improving sleep.","offset":3623,"duration":6},{"text":"Host: Yeah and I'm so grateful for that because for several years I talked about that on the podcast and people said \"oh you know he's gorging himself with pasta and then passing out and that's the worst time.\" I wasn't saying that, I'm saying that if you're not if you're running like crazy.","offset":3629,"duration":12},{"text":"Host: I'll hear from marathoners and ultra-people and people are doing a million things and they'll say \"I'm not sleeping well\" and they're exercising like crazy, it's like \"well when was the last time you had a bowl of pasta?\" Like \"oh no, I don't eat pasta.\" And then they'll have some rice or some pasta, they're like \"oh I slept like a baby\" and they were having it at lunch!","offset":3641,"duration":13},{"text":"Host: And I just think that that the brain doesn't shut down well when you have high levels of cortisol. And the cortisol-starch thing is an interesting one.","offset":3654,"duration":10},{"text":"Dr. Rhonda Patrick: I'm so glad you brought this up because I think um this is something that I did want to talk about really and it has to do with stop eating three hours before bed for that very reason. So there was a new even a new, but there's been several studies now really showing that this is important for that cardiovascular reset, right?","offset":3664,"duration":19},{"text":"Dr. Rhonda Patrick: Your parasympathetic activity is supposed to go higher, you're in your rest and recovery phase, right? When you're eating food that's the sympathetic activity, right? You're it that's activating the sympathetic nervous system as you're eating.","offset":3683,"duration":9},{"text":"Host: As you're eating, yeah.","offset":3692,"duration":1},{"text":"Dr. Rhonda Patrick: Yeah and even as you're digesting, so you have to think about it, like you digest it what it takes like five or so hours to fully finish a meal depending on the meal. Yeah, so if you're eating, you know, right before you go to bed you are you are you are not in that parasympathetic activity, you know, part of the part of the you know cycle that you want to be in.","offset":3693,"duration":21},{"text":"Dr. Rhonda Patrick: So um there was a new even a new study that I shared like I don't know a couple days ago even showing that if you stop eating 3 hours before bed... so these people were actually, um this is interesting, they they had their blood pressure measured for starting in the mid-afternoon all the way throughout the night. So it's the first study that really not just one endpoint looking at blood pressure but just measuring it continuously.","offset":3714,"duration":24},{"text":"Dr. Rhonda Patrick: I don't know if it was every 15 minutes or something like that. But um it was found that their during sleep if they had stopped eating three hours before bed versus the group that did not stop eating three hours before bed their blood pressure dipped like lower, so you get that you know that baroreflex dipping, right?","offset":3738,"duration":19},{"text":"Dr. Rhonda Patrick: So this is like part of the parasympathetic activation as you know very important for the blood pressure to go down, heart rate went down, like you know much much lower and that reset is so so important for cardiovascular health. I think what was found was it was something like um translated to like 20% lower risk of cardiovascular events, like heart attacks.","offset":3757,"duration":22},{"text":"Dr. Rhonda Patrick: So it's really pretty significant, yeah. And it really isn't an easy thing to do to think about stopping eating, you know, 3 hours before you go to bed. Like that's that's something I think that is not that hard to implement and it will improve your sleep as well as your cardiovascular health.","offset":3779,"duration":16},{"text":"Dr. Rhonda Patrick: Although I think in that study I don't know that sleep was really it was subjective and I don't think it was really improved more but other studies have found that as well that sleep does improve. I know Satchin Panda he's been on my podcast your podcast, he's had studies showing that it seemed like stopping eating 3 hours before bed really does seem to improve sleep.","offset":3795,"duration":17},{"text":"Dr. Rhonda Patrick: But this parasympathetic activation, you know, you don't want to have a meal right before you bed because you want you want to be in the rest and recovery part, right?","offset":3812,"duration":6},{"text":"Host: Yeah I think people hear uh and I understand why the nomenclature and the buzzwords of you know \"fight or flight\" for sympathetic and \"rest and digest\" for parasympathetic but yeah the evidence shows eating stimulates the sympathetic nervous system. It's not a stress event but it's a it requires energy, anything that requires energy raises body temperature and your body's doing work.","offset":3818,"duration":318},{"text":"Dr. Rhonda Patrick: It's an awake event, right? It's an awake... you don't eat while you're sleeping. Yeah and that's why these phrases while I don't demonize anyone for creating the you know \"fight or flight\", well I mean there's ways that you want your sympathetic nervous system activated that are not about fight or flight. Like I actually think if people just got the first hour of their day more active and energized, bright light, exercise, caffeine if you're me and Lord knows I'm grateful that caffeine exists, in the first hour of the day or first hours if you can't manage that because of schedule and then the last hour of the day was strongly parasympathetic.","offset":4136,"duration":32},{"text":"Host: I mean everything would get better without having to think a ton about exactly how you're doing that because on a given day you just do what you can.","offset":4168,"duration":7}],"startTime":3615},{"title":"Cortisol Regulation & Hormetic Stress","summary":"They clarify the misunderstood role of cortisol, explaining the difference between chronic stress and the beneficial, acute cortisol spikes generated by hormetic stressors like exercise and fasting.","entries":[{"text":"Dr. Rhonda Patrick: And that's what you want, right? I mean so cortisol is circadian dependent as you know, I mean in the more like early morning of early hours of the morning that's when you want it to peak, right? Part of the awakening response like you want it to go up. And it's it's interesting I I the reason I'm going on this is because it's a little bit of a um soapbox for me but so with the with the cortisol activation um people don't realize this...","offset":4175,"duration":3025},{"text":"Dr. Rhonda Patrick: ...you know obviously it's a hormone and it's binding to diff two different receptors. There's the glucocorticoid receptor and then there's the mineralocorticoid receptor and both of those uh when cortisol binds to it they go into the nucleus of the cell and they're changing the expression, so they're activating genes and deactivating genes like 20% of the human genome. It's a large percentage, right?","offset":7200,"duration":19},{"text":"Dr. Rhonda Patrick: And this is on multiple different organs. So it's it cortisol has a very important role and you want that peak, you want that spike, right? That's what you want and then you want it to shut off. And there are things that can activate it obviously like in the morning, bright light exposure as you mentioned, like that's very important for that cortisol awakening response.","offset":7219,"duration":19},{"text":"Dr. Rhonda Patrick: But you can also ex like like intensity intensive exercise can switch it on um but what's interesting and so can intermittent fasting that it what's interesting is there's studies from Mark Mattson's lab showing that, you know, the types of of stressors that are beneficial, these hormetic stressors like exercise, like intermittent fasting...","offset":7238,"duration":22},{"text":"Dr. Rhonda Patrick: ...perhaps even cold exposure, like these types of exposures change the receptor density of these receptors. So if you if you look at what activates cortisol in a negative way, chronic stress let's say emotional, financial, psychological, um chronic sleep deprivation, right? That bad type of stress, you're getting not a big spike you're getting a slow drip of it.","offset":7260,"duration":21},{"text":"Dr. Rhonda Patrick: And so what happens is when you have that type of stress you're increasing the glucocorticoid receptors and you're decreasing the mineralocorticoid receptors. There's a different biological response in the brain, in the hypothalamus, but also in you know other organs as well when you're when you're activating cortisol through a beneficial type of stress, the hormetic stressors like like intermittent fasting, like exercise.","offset":7281,"duration":26},{"text":"Dr. Rhonda Patrick: Um I believe probably deliberate cold exposure as well, where um it's a different biological response and also if you think about it, you know, you actually want cortisol to do its, you know, function. You want it to change the expression of genes, that's what it's supposed to do, right? The problem is is when you have that slow drip, then you know not only are your you're increasing they're changing the receptor you know activation but also they become resistant to the cortisol and so you're not getting the benefits.","offset":7307,"duration":29},{"text":"Dr. Rhonda Patrick: You know cortisol represses inflammation, right? It it suppresses the immune system. But like so you're not getting that anti-inflammatory effect from cortisol, it's being disregulated. And that's what you don't want, you don't want cortisol to be disregulated in terms of like all the genes that it's supposed to activate or deactivate, you want it to be doing what it's supposed to be doing.","offset":7336,"duration":14},{"text":"Dr. Rhonda Patrick: It's supposed to regulate, we're supposed to have the cortisol, you know, activation response. So um anyways that's something that I kind of want to clear in people's minds because I feel like a lot of people get worried about \"oh my gosh I'm doing, you know, HIIT and it's activating my cortisol.\" Well that's fine, it's like, you know, I mean I guess if you do too much HIIT, right?","offset":7350,"duration":19},{"text":"Dr. Rhonda Patrick: You could always take something to the extreme okay with that caveat obviously I'm not talking about that. But with that caveat like you do you want your body to be able to turn it on and then turn it off and have the adaptation, have the response, right? And like I said it's a different biological response than than the chronic type of cortisol activation that you get with the bad types of stress.","offset":7369,"duration":20},{"text":"Host: Yeah I guess same goes for intermittent fasting. And maybe you could share with us what your intermittent fasting protocol is. I know that recently cortisol has been like increasingly demonized as this stress hormone, stress hormone, and people saw pictures of people with Cushing's disease, which is, you know, a drastically elevated cortisol and the moon face and the excessive visceral fat and and yeah this this sort of um fearmongering around cortisol was particularly directed toward women.","offset":7389,"duration":29},{"text":"Host: And this entered the health fitness space because I think in an appropriate way, I'll just be very direct here I don't like I no longer tap dance around who said you know in a very appropriate way uh that I appreciate um Dr. Stacy Sims came on the podcast and she said, \"Listen some women shouldn't train fasted because they don't feel well when they train fasted and their cortisol is too high\" and so forth.","offset":7418,"duration":24},{"text":"Host: That captured a lot of people's experience. A lot of women in particular, but some men certainly were like \"yes oh my god thank you, thank you, thank you!\" But then the they the message got contorted, right? As it does, yes. Yes! And then it became \"women shouldn't train fasted.\"","offset":7442,"duration":17},{"text":"Host: And then we had uh Lauren Colenso-Semple on this podcast, who's a you know trained as a PhD she has a background in nutrition physiology strength training coach etc. and she said \"No, listen you can train fasted or not fasted as a woman or a man, it's kind of your preference.\"","offset":7459,"duration":-2990},{"text":"Host: But that we don't need to fear these cortisol spikes. And forgive me for going long here but I think it is important that people hear this uh again, which is there's also this idea that deliberate cold exposure increases cortisol but when you look at the data it definitely increases adrenaline.","offset":4469,"duration":14},{"text":"Dr. Rhonda Patrick: Yeah.","offset":4483,"duration":1},{"text":"Host: And peripheral dopamine and probably, I'll go on record here, probably central dopamine although we don't have as good evidence for that yet. But there evidence points to the fact that deliberate cold exposure lowers cortisol.","offset":4484,"duration":14},{"text":"Host: So this then you know because I think Stacy appropriately said a lot of women who want to use cold shouldn't go as cold. But the message got contorted and it became \"women shouldn't do deliberate cold exposure because of the cortisol increase.\"","offset":4498,"duration":17},{"text":"Host: And so part of the reason I'm going long here is I'm trying to correct the narrative on her behalf. She said \"do what works for you\", right? And that's what Lauren's saying and I'm guessing um that's what you'll say as well. Um but I just need to get that out there because the message has gotten totally pretzel twisted up and cortisol is neither good nor bad. You want it high in the morning you want it low at night, um in general.","offset":4515,"duration":20}],"startTime":4175},{"title":"Visceral Fat, Fasted Training & Insulin Resistance","summary":"Rhonda details the dangers of visceral fat, explaining how it acts as a toxic endocrine organ that aggressively drives insulin resistance, NAFLD, and cognitive fatigue, even in individuals who appear lean.","entries":[{"text":"Host: Um it sounds like you train fasted?","offset":4535,"duration":3},{"text":"Dr. Rhonda Patrick: I listen to how I feel. That's exactly what I do. So what what your podcast guest and and the researchers are talking about is exactly there are times when I wake up in the morning and I'm like \"I need to eat something before I work out\" and I do. Um but I oftentimes do train fasted for one because I am practicing intermittent fasting again, but I do it I'm not like starving myself and like I said the reason there's multiple reasons I do it.","offset":4538,"duration":27},{"text":"Dr. Rhonda Patrick: One reason is because it really did help me lose the belly fat, which is visceral fat, which is like the worst kind of fat you can have. And we can talk more about that. Um but the second reason is I love the cognitive benefits I have in the morning with it. And it's the main reason I do it.","offset":4565,"duration":14},{"text":"Dr. Rhonda Patrick: And so there are many times what I do train fasted, but I am not out running 15 miles, most of my my like I said my sessions are about an hour long and am I taking a little bit of a performance hit with the high intensity? Probably. Probably yes, but it's not much to matter for me and you do burn a little bit more fat if you train fasted. I mean that's known.","offset":4579,"duration":23},{"text":"Dr. Rhonda Patrick: Um you will if it is a longer session you will take an import performance enhancement hit that is also known, right? So I think it really does come down to like \"what is your goal, how do you feel?\" and and then you kind of go with that.","offset":4602,"duration":11},{"text":"Dr. Rhonda Patrick: And I and I completely agree like there are times when, you know, I'm on my cycle and I feel fine and I'm working out just fine. And there are time other times when I'm like \"I don't feel good like I'm going to I'm going to take it easier\" but I still train, I just you listen to your body and I think that's a pretty easy I think rule of thumb.","offset":4613,"duration":16},{"text":"Dr. Rhonda Patrick: Sometimes people like to complicate things, you know, I don't know there's lots of reasons why I don't we don't need to get into that.","offset":4629,"duration":7},{"text":"Host: I have theories, yeah I have theories but they're not important right now.","offset":4636,"duration":3},{"text":"Dr. Rhonda Patrick: No, it's not important, yeah. So so yeah I do I do train fasted and it is um for me it is it is helped me tremendously change my body composition. Like I said I'm in a different part of my life than perhaps a 30-year-old woman is, right? Because when I was 30 I mean like I didn't have to train fasted. It was it was easy to keep, you know, the the belly fat, the visceral fat lower.","offset":4639,"duration":23},{"text":"Dr. Rhonda Patrick: Um hormonal changes are do play a role in the way your body... so estrogen plays a role in telling your body how to store fat. So subcutaneous fat would be the kind of fat that you can just like pinch, right? The fat that we see.","offset":4662,"duration":12},{"text":"Dr. Rhonda Patrick: The visceral fat that's that deep fat that's lining your organs, it's often belly fat, you know, and it's lining the intestines, the liver, you know, it's it's it's it's almost like an endocrine organ I mean because it is secreting hormones, it's secreting inflammatory factors, it's metabolically active, it's constantly breaking down triglycerides.","offset":4674,"duration":21},{"text":"Dr. Rhonda Patrick: It's associated with double the increased risk double the risk of early death. Um people that have high visceral fat have 44% higher chance of having cancer, many different types of cancers.","offset":4695,"duration":8},{"text":"Host: Wow.","offset":4703,"duration":1},{"text":"Dr. Rhonda Patrick: It's huge, it's huge, you know. And and of course insulin resistance is the number one problem with visceral fat, right? And I'd love to to talk about that but if you want I mean we can we can get into that. Yeah, it's so with the visceral and like I said, you know, visceral fat is something if you really directly want to measure it you do a DEXA scan.","offset":4704,"duration":18},{"text":"Dr. Rhonda Patrick: But you know for the average person that isn't going to go out and do a DEXA scan, waist circumference is a proxy, it's used in a lot of studies. So women that have a waist circumference of 35 inches or above are considered to have a higher amount of visceral fat. Men that have a waist circumference of 40 inches or above are considered to have a higher amount of visceral fat.","offset":4722,"duration":17},{"text":"Dr. Rhonda Patrick: It's also that belly fat, like you you can you just know, right? Um interestingly like 70% of women over the age of 50 have high visceral fat, 50% of men over the age of 50 do. You know again coming down to women go through menopause, estrogen plays an important role in telling the body, you know, to store the fat subcutaneously rather than viscerally deep around organs.","offset":4739,"duration":26},{"text":"Dr. Rhonda Patrick: And so as women transition to perimenopause, you know, the the years before menopause and menopause it the their estrogen goes down and that does change the way the body stores fat. And any woman that's going through either of those stages knows it. And it's also why you see often women over the age of 50 with more belly fat. Right?","offset":4765,"duration":19},{"text":"Dr. Rhonda Patrick: I mean that's something that I think it's it's hard to deny. But um it's it's one of the reasons why I kind of went back to practicing intermittent fasting because there's a there's a couple of ways that you can really powerfully lose visceral fat and one of them is doing aerobic exercise, high intensity interval training also really powerfully can do it.","offset":4784,"duration":25},{"text":"Dr. Rhonda Patrick: But also being in a caloric deficit and I think when you start to get the combination of both, that's what really worked for me. It's crazy how quickly you can gain it based on your diet as well. So it is different from the subcutaneous fat in many ways. I mentioned it's secreting these inflammatory molecules, it's you know hormones, but it's also constantly breaking down triglycerides into free fatty acids.","offset":4809,"duration":30},{"text":"Dr. Rhonda Patrick: And the location of it is very dangerous because it's right surrounding the liver, right? It's this deep organ fat. And that's very close to the portal vein and so you're constantly getting this sort of mainlining free fatty acids to the liver.","offset":4839,"duration":14},{"text":"Dr. Rhonda Patrick: And visceral fat is very different from subcutaneous fat because it doesn't respond to insulin like subcutaneous fat does. In other words when you have a meal, you eat a carbohydrate meal and you basically your body increases insulin to help take it up glucose into your liver, muscle, adipose tissue.","offset":4853,"duration":614},{"text":"Dr. Rhonda Patrick: Lipolysis shuts down, right? It's like \"okay no longer am I going to break down these fats, it's time to use this energy\", right? Visceral fat doesn't respond to insulin so it just keeps going, right? And these free fatty acids because they're going right to the liver um it's essentially antagonizing the insulin receptors.","offset":5467,"duration":14},{"text":"Dr. Rhonda Patrick: So it causes insulin receptors to become more resistant to insulin. And this is part of why people with high visceral fat... by the way you can gain visceral fat without gaining a pound.","offset":5481,"duration":12},{"text":"Dr. Rhonda Patrick: And we can talk about those studies like people people are skinny and can have high amounts of visceral fat. You've heard of like lean metabolically unhealthy but lean individuals, those people exist and so you can have a high amount of visceral fat but not really look like you do.","offset":5493,"duration":18},{"text":"Dr. Rhonda Patrick: So um when you know obviously the insulin resistance is a problem for many reasons but it also plays a role in those energy crashes that you experience, right?","offset":5511,"duration":8},{"text":"Dr. Rhonda Patrick: And that's kind of like some of the first signs of insulin resistance actually have to do with what you're feeling. So we talked about lethargy, right? So you know the inflammation that's being generated from these this visceral fat constantly making these, you know, pro-inflammatory compounds are an it's an energy sink, right?","offset":5519,"duration":16},{"text":"Dr. Rhonda Patrick: So you do constantly feel tired, but also because your cells are becoming insulin resistant, when you have a high glucose meal and you're not responding the body kind of overcompensates and produces more insulin. So it's like \"I we got to get this blood glucose out of our system\", right? It can cause a lot of damage if it sits around there.","offset":5535,"duration":18},{"text":"Dr. Rhonda Patrick: And so you make more insulin and then what happens is your you your blood glucose goes way low because it was like this overcompensation, right? And then you feel a crash, you feel like this crash and that signals to the, you know, hypothalamus part of the brain \"uh I need energy\", right? So then you you sort of crave, you get those cravings for those calorically energy dense foods.","offset":5553,"duration":20},{"text":"Dr. Rhonda Patrick: What I'm talking about is like the experience of, you know, insulin resistance. And what's interesting is that you can cause someone to gain visceral fat and their brain can become insulin resistant. So we think a lot about insulin resistance in the muscle, liver, your brain also can become insulin resistant quite quickly actually.","offset":5573,"duration":20},{"text":"Dr. Rhonda Patrick: So um insulin's very important in the brain for a lot of reasons, as you know. But you know a couple of the things relative to what we're talking about or relevant to what we're talking about would be one is it does act on the hypothalamus and help, you know, tell it to basically stop eating, be satiated. Like \"I took a meal in okay like I'm going to be satiated.\"","offset":5593,"duration":19},{"text":"Dr. Rhonda Patrick: But it also plays a role in energy storage and telling the body how to store the energy. And so when your brain becomes insulin resistant, it's not doing that and so you're not being satiated so you eat more and you're storing the fat more viscerally.","offset":5612,"duration":16},{"text":"Dr. Rhonda Patrick: And there was a study that was published actually quite recently I covered this in a in a recent newsletter. It was a really interesting study because it was healthy young men and researchers put them on a little bit of a calorically dense, so it was like they were eating 1200 to 1500 more calories a day and it was high saturated fat high sugar. So it was a processed foods ultra-processed foods like, you know, ultimate, right?","offset":5628,"duration":24},{"text":"Host: That's a lot of extra calories.","offset":5652,"duration":1},{"text":"Dr. Rhonda Patrick: A lot of extra calories for five days. It is. But what happened was their they did cause their brain to become insulin resistant and they didn't gain weight, but they gained visceral fat and they started gaining fat around their liver and that's something that happens as well because visceral fat is surrounding liver, you're getting a lot of free fatty acids and they're going right to the liver so the liver has to store it, right?","offset":5653,"duration":23},{"text":"Dr. Rhonda Patrick: So you get this non-alcoholic, you know, fatty fatty liver. But and that happened after five days. I mean without gaining weight!","offset":5676,"duration":8},{"text":"Host: In otherwise young healthy...","offset":5684,"duration":1},{"text":"Dr. Rhonda Patrick: Yeah! But you know they were eating a lot of calories extra calories.","offset":5685,"duration":4},{"text":"Host: Yeah that's like a 1200 that's like a half a pizza extra above your maintenance calories per day.","offset":5689,"duration":6},{"text":"Dr. Rhonda Patrick: And it's probably what they were doing and they were eating lots of well they were eating like saturated fat and refined sugar, so Doritos and French fries. You know I mean obviously if you're going to do the study you want to kind of do it to a high degree where you're going to see some change, right?","offset":5695,"duration":14},{"text":"Dr. Rhonda Patrick: So so maybe like maybe it's not going to happen in five days if you're if you're only eating 500 more calories a day but over time you will be gaining it visceral fat, right? So it's it's not going to be the same degree. It's something to be concerned about, it's something to think about and also because you can gain it and not really even know it like, you know, without gaining a pound.","offset":5709,"duration":23},{"text":"Dr. Rhonda Patrick: And there other things that cause it not just, you know, eating too many calories or diet composition. I mean you mentioned cortisol, I mean chronic elevated cortisol makes you store the fat around around, you know, visceral fat. Sleep loss, I mean there's also studies showing that you take healthy men, sleep deprive them for a couple of weeks I think 4 hours they're getting 4 hours of sleep a night they can start gaining visceral fat.","offset":5732,"duration":22},{"text":"Dr. Rhonda Patrick: I mean pretty rapidly with only like a pound gaining a pound of weight. So again it's like not necessarily something that you're going to see on the scale but it's happening, right? And it's affecting your short-term mood, I mean how you feel, your energy, it's affecting, you know, the way you're eating it's a vicious cycle because you start to eat more calories, right? And then it just becomes this vicious cycle of that you start to gain more visceral fat.","offset":5754,"duration":19}],"startTime":4535},{"title":"Sponsor: Element","summary":"Huberman reads a sponsor message for Element electrolyte drink mix.","entries":[{"text":"Host: I'd like to take a quick break and acknowledge one of our sponsors, Element. Element is an electrolyte drink that has everything you need and nothing you don't. That means the electrolytes, sodium, magnesium, and potassium, all in the correct ratios, but no sugar. Proper hydration is critical for brain and body function.","offset":5773,"duration":18},{"text":"Host: Even a slight degree of dehydration can diminish your cognitive and physical performance. It's also important that you get adequate electrolytes. The electrolytes, sodium, magnesium, and potassium, are vital for the functioning of all cells in your body, especially your neurons or your nerve cells.","offset":5791,"duration":16},{"text":"Host: Drinking Element makes it very easy to ensure that you're getting adequate hydration and adequate electrolytes. My days tend to start really fast, meaning I have to jump right into work or right into exercise. So to make sure that I'm hydrated and I have sufficient electrolytes, when I first wake up in the morning, I drink 16 to 32 ounces of water with an Element packet dissolved in it.","offset":5807,"duration":19},{"text":"Host: I also drink Element dissolved in water during any kind of physical exercise that I'm doing, especially on hot days when I'm sweating a lot and losing water and electrolytes. Element has a bunch of great tasting flavors. In fact I love them all. I love the watermelon, the raspberry, the citrus, and I really love the lemonade flavor.","offset":5826,"duration":16},{"text":"Host: So if you'd like to try Element, you can go to drinkelement.com/huberman to claim a free Element sample pack with any purchase. Again that's drinkelement.com/huberman to claim a free sample pack.","offset":5842,"duration":12}],"startTime":5773},{"title":"Sleep Deprivation, Cortisol & Metabolism","summary":"A discussion on how sleep deprivation chronically elevates cortisol, disrupts nocturnal metabolic recalibration, and acts as a rapid driver for the accumulation of visceral fat.","entries":[{"text":"Host: Such an important point that you can either not be gaining much or not gaining any um total body weight but gain visceral fat. I think that's um first time I've heard that and it's a vital message for people to hear because this visceral fat sounds like one of the major health hazards we need to worry about.","offset":5854,"duration":18},{"text":"Host: You mentioned elevate chronically elevated cortisol, sleep deprivation, will increase visceral fat. Once again I know I'm beating a drum here um almost to death, but having high cortisol early in the day and low cortisol in the evening is the definition of not chronically high cortisol.","offset":5872,"duration":17},{"text":"Host: The definition of chronically high cortisol is somewhat elevated or elevated cortisol in the morning, but especially in the hours before sleep and I I actually have a theory that is not a stretch that one of the main reasons why it's so detrimental to our mental and physical health in the short and long term is because of the ways it disrupts sleep.","offset":5889,"duration":19},{"text":"Host: And so and we can't tease those apart. No! You can't do a study where you spike cortisol late in the day even if you can fall asleep just fine after the end of a really stressful day the sleep is different. And people say \"well life has stress\" and I totally agree. I mean Lord knows I've experienced life has stress.","offset":5908,"duration":15},{"text":"Host: But getting that last hour of the day doing things to push down on cortisol push down on stress lower heart rate not eating in that certainly that last hour before sleep ideally 3. Um I feel like that small change can make a an outsized positive difference.","offset":5923,"duration":15},{"text":"Dr. Rhonda Patrick: That's interesting like the the correlation between the high cortisol affecting your sleep and maybe that's also like they they're related and so the sleep loss really does make you... we know, we know from, you know, you probably know who the researchers are that have done those studies on sleep loss and it affecting appetite, right? I mean...","offset":5938,"duration":17},{"text":"Host: Oh everything gets disregarded. I mean I don't want to take us off course, but I think you might find it interesting there's a beautiful study where they look measured metabolism during sleep. They basically had people breathe into a tube um during sleep, they had a mask on and it turns out that the brain cycles through all the different forms of metabolism during sleep.","offset":5955,"duration":14},{"text":"Host: There's a phase of sleep where you're essentially running on sugar, there's a then there's like it almost looks like somebody's ketogenic at one... basically the the middle of the night when we're so should be at night when you're sleeping is is kind of a test run of all the systems but they get recalibrated.","offset":5969,"duration":19},{"text":"Host: And it's so important. I actually think, you know, most of the negative effects of alcohol that people talk about, yes it's a poison, it's a class 1 carcinogen, um as classified by the World Health Organization on a... I think most of the negative effects of drinking are because of the negative effects of alcohol on sleep. I'm not telling people drink in the morning, but uh you know...","offset":5988,"duration":21},{"text":"Host: And so I think that if you get your sleep right you're not 90% of the way there, but you're halfway there. Yeah. I really do believe that. And then getting your sleep right makes you do a bunch of other things.","offset":6009,"duration":8},{"text":"Dr. Rhonda Patrick: Right, you're more you're more more motivated to exercise for one.","offset":6017,"duration":3},{"text":"Host: More motivated to exercise, your food choices, I mean and on and on. The the problem with talking about sleep is so important is people will get sleep anxiety so we tap dance around this. It's like \"oh we don't want people stress.\" Learn how to fall asleep, learn how to fall back asleep. These no one gets it perfect, yes you'll survive like with one poor night's sleep or an all-nighter, you're not going to die, like you know just get good at it on average right?","offset":6020,"duration":20}],"startTime":5854},{"title":"Intermittent Fasting, Ketosis & Mitigating Sleep Loss","summary":"Rhonda shares her intermittent fasting structure, highlighting how ketosis benefits the brain. They also discuss how a bout of exercise can effectively offset the acute insulin resistance caused by a poor night of sleep.","entries":[{"text":"Host: That's what I'd say. Could you tell us what the structure of the intermittent fasting is for you? Does that mean skipping breakfast, skipping lunch, skipping dinner because I know a number of people are sort of getting drawn back to intermittent fasting after a couple of years of it getting beat up on as like not the best way to lose fat or it is a I think it's a terrific way to do the sorts of things that you're describing and I'm learning today more about the the positive things it can do um for insulin sensitivity and so forth.","offset":6040,"duration":29},{"text":"Host: If you're on a bout of intermittent fasting are you doing it by the clock? Are you doing it by feel? What does it look like?","offset":6069,"duration":5},{"text":"Dr. Rhonda Patrick: For me it it really does depend on the day and I really do try to stop eating 3 hours before I go to bed. It doesn't always happen, you know, with family obligations, social obligations, but it's the habit that's important, right? So intermittent fasting, you know, it's more than just one intervention as I mentioned, it's a behavioral tool that you can use to limit your calorie intake without actually having to count all the calories, which some people like to do, some people don't, right?","offset":6074,"duration":24},{"text":"Dr. Rhonda Patrick: So it's a tool, but also it's really important for a metabolic switch. As you mentioned insulin sensitivity the metabolic switch is something that Dr. Mark Mattson coined and I love it because I feel like, you know, thinking about intermittent fasting in that way makes it a little more clear as to the benefits of it. It depends on the meal you have and how much exercise you do, right?","offset":6098,"duration":23},{"text":"Dr. Rhonda Patrick: But on average let's say 11, 12 hours to deplete your liver glycogen levels. And once that happens you do start to burn fat and use fatty acids as fuel and make ketone bodies so you go into ketogenesis, right? And that's a metabolic switch. Metabolic flexibility you're you're going from using carbohydrates as fuel to using fatty acids and making ketone bodies as fuel.","offset":6121,"duration":23},{"text":"Dr. Rhonda Patrick: And that's something that, you know, throughout human evolution was ingrained, right? Like we didn't always have access to Uber Eats and Instacart and you can just out of swipe you get food, right? You I mean there were many times when, you know, people had to not eat because they couldn't forge their foods, maybe the time of year or they couldn't hunt their food because they didn't get a win or whatever I don't know.","offset":6144,"duration":25},{"text":"Dr. Rhonda Patrick: So this metabolic flexibility is something that's really ingrained in our in our our DNA in a sense, right? Um one of the reasons I like to do that is the ketone production and why is that, you know, ketones are really clean they're clean a clean way to burn energy. So they generate less oxidative stress, less oxidative products, but they also are energetically favorable in that it takes less energy to use them to make energy than glucose does.","offset":6169,"duration":29},{"text":"Dr. Rhonda Patrick: So it takes more energy to use glucose as energy than it does ketones. But they're also a signaling molecule, so it's a way for the body, you know, to signal to other parts of the body like \"hey this is a stressful time, there's no food, I'm you know burn I'm in ketosis, um let's let's make you stronger\", right?","offset":6198,"duration":20},{"text":"Dr. Rhonda Patrick: Because that's kind of what evolution wants, like if you're not able to find or eat food you have to be stronger to be able to do it, right? And so that's that's kind of at the I say core of of this metabolic switch and why it's important and I think that I really like Mark Mattson being the pioneer in this and as a neuroscientist really looking at the benefits in the brain as well, you know.","offset":6218,"duration":20},{"text":"Dr. Rhonda Patrick: These ketones like beta-hydroxybutyrate are activating, you know, growth factors like brain-derived neurotrophic factor in the brain, as you know, it's very important for, you know, learning memory, you know, synapse formation and stuff this hugely important for neuroplasticity. So it's activating beneficial compounds like that and again, um it it's not going to happen if you're never going into this metabolic switch.","offset":6238,"duration":21},{"text":"Dr. Rhonda Patrick: And there's other ways to get there. So you can limit your your food go into this ketosis, right? Where you're basically depleting your liver glycogen. Or you can exercise a lot, right? So your energy expenditure goes up. So there's there's different ways to get to this metabolic switch. It doesn't necessarily have to be intermittent fasting.","offset":6259,"duration":22},{"text":"Host: Got it.","offset":6281,"duration":1},{"text":"Dr. Rhonda Patrick: And I'm telling you this because you're I want to tell you why I'm I'm sort of back back on the intermittent fasting and by the way it's not for everyone like I said, I mean I think that you can find other ways to get this metabolic switch and um for me intermittent fasting works. And so what I do typically is I will do most of the time my fasted my...","offset":6282,"duration":15},{"text":"Dr. Rhonda Patrick: But I mean, obviously we don't always want to be in a calorie deficit, but we always don't want to be constantly eating either. And that's why it comes down to I think the simple rule for people like if they're going to do some sort of metabolic switch, some sort of intermittent fast, it would be like okay let's try to at least stop eating three hours before bed.","offset":6297,"duration":18},{"text":"Dr. Rhonda Patrick: Because then you're at least going to be extending that fast somewhat by three hours, right? So I think that's and plus you're getting that the cardiovascular benefits that are really seem to be important.","offset":6315,"duration":11},{"text":"Dr. Rhonda Patrick: And then not eating at night, so there's all these studies that have come out of Israel, I think it's is it Jacobwitz, Jacobwitz and Freud are two researchers. Um, I mean Satchin Panda I remember years ago showed me one of the studies it was like published in science showing that if you have the same exact meal, same calorie intake, same composition macronutrient composition in the morning, the afternoon, in the evening, the insulin response is like com is different.","offset":6326,"duration":34},{"text":"Dr. Rhonda Patrick: Like you're the most insulin sensitive early in the morning. As you start to go towards the evening, and particularly three hours before your natural bedtime, you see your your melatonin levels naturally rise, right? And as you know, you know melatonin is important for the onset of sleep and preparing the body for sleep.","offset":6360,"duration":19},{"text":"Dr. Rhonda Patrick: But it's also preparing the other organs for rest and recovery, including the pancreas which is making insulin. And so you're not making as much insulin when it's closer to your natural bedtime because of the melatonin levels that are rising.","offset":6379,"duration":15},{"text":"Dr. Rhonda Patrick: And so you don't want to be eating, particularly a carbohydrate rich meal, but a meal, you're not going to be as as insulin sensitive in the last three hours before sleep.","offset":6394,"duration":10},{"text":"Host: Yeah, when you're starting to get into that melatonin rising phase of of you know, of your cycle. Yeah, it's interesting. I I think when people hear, okay you're most insulin sensitive in the morning, that would be the time to eat your biggest meal.","offset":6404,"duration":19},{"text":"Host: But then people say, wait but then I'm trying to fast before and I'm trying to exercise and like how do I do this? I think that's where for them the confusion comes in and it to me it's very simple. Uh, just because your insulin sensitivity is highest first thing in the morning doesn't mean you have to eat right away.","offset":6423,"duration":15},{"text":"Host: I mean it just means avoid eating too close to bedtime, right? Sometime during the day. And also if you exercise fasted or after a small snack, it was kind of interesting what Stacy Sims said, not everyone should exercise fasted. She said especially a lot of women don't like to do that. She didn't say eat a meal.","offset":6438,"duration":18},{"text":"Host: She said like have a scoop of whey protein with some I think she said with like some almond milk in it. And and you couldn't believe the response on the internet. It was like vindication, right? And I get it, it was like it vindicated people's experience, like oh thank you thank you.","offset":6456,"duration":17},{"text":"Host: And it it told me something really important about the kind of sociology of what we do, which is when something validates people's experience they they love it. But it doesn't mean that the things that work for other people don't work.","offset":6473,"duration":17},{"text":"Host: And I think that that's the part that gets lost. And so if a study shows that insulin sensitivity is highest in the morning, but you can only exercise first thing in the morning, what do you do? You know, so uh, you do the best you can, right? I think is what it comes down to.","offset":6490,"duration":16},{"text":"Host: In fact I meant to ask you earlier and it's this is a good time to uh, to talk about this. Uh, you've described that if you are slightly sleep deprived, so not four hours per night or an all-nighter, but if you've only slept five, or let's say you're getting an hour or two less than your normal ration of sleep, there's some pretty significant inflammation that's that that occurs, that's not good.","offset":6506,"duration":25},{"text":"Host: But I've heard you cover that exercising can actually offset some of that inflammation. This answers a a important and common question which is if I have to pick between sleep and exercise, what do I do? Um, and it sounds like if it's one night poor sleep, exercise. But you but you don't want to make it a habit. That's do I have that right?","offset":6531,"duration":18},{"text":"Dr. Rhonda Patrick: Yeah. I mean so this this data a lot of it actually comes from you can cause even acute insulin resistance after like a night of of sleep deprivation, certainly after two to three nights of sleep deprivation. And you know, again a lot of that's coming down to some of the things we've already talked about.","offset":6549,"duration":20},{"text":"Dr. Rhonda Patrick: And um, but exercise can help basically negate a lot of that. And I learned that first hand through experience when I was wearing a continuous glucose monitor uh, and when I was a new parent, of course you're not getting enough enough sleep.","offset":6569,"duration":17},{"text":"Dr. Rhonda Patrick: And so that's I learned it before I actually dove into the science about it, I I learned about it through my own data, where I was, you know, I wasn't exercising as much, and particularly in the first month you really like you're kind of in a cave as a new mom, you don't really you're not really exercising much at all.","offset":6586,"duration":11},{"text":"Host: Evolution wants the the baby to survive.","offset":6597,"duration":3},{"text":"Dr. Rhonda Patrick: You're recovering too. I mean childbirth is a very it's a very traumatic process on your body. And so um, I noticed that my my glucose response was like it was pre-diabetic. And I was like what is going on? And um, and that's when I started looking into the literature.","offset":6600,"duration":18},{"text":"Dr. Rhonda Patrick: And happened to be around the same time when I was then starting up my at the time I was doing spin classes, and then it was very clear to me, it was like I do these high intensity interval training classes even just twice a week, and it was like almost completely negating what I had seen previously of my my glucose being my fasting glucose being really high, and also my postprandial glucose being higher than than usual.","offset":6618,"duration":23},{"text":"Dr. Rhonda Patrick: And so um, I looked into the studies and there's now you can you can find many studies out there and it really I mean obviously exercise is one of the best things you can do to improve insulin sensitivity and to also bring glucose into your cells, right?","offset":6641,"duration":19},{"text":"Dr. Rhonda Patrick: And so that's part of what you were talking about with you're more insulin sensitive during morning, least during evening, and I also mentioned that. But guess what? There's levers you can pull that like change the equation, and exercise is a big one, right?","offset":6660,"duration":14},{"text":"Dr. Rhonda Patrick: If you're if you're exercising you're becoming more insulin sensitive, you're increasing more glucose transporters on your muscle, that's causing glucose to go in easier, right? There's so there's lots of ways around some of these rules that we hear about.","offset":6674,"duration":14},{"text":"Dr. Rhonda Patrick: But with the with the sleep loss, it really is it's interesting because people like when they don't get sleep, the last thing they want to do is work out. And obviously like you don't want to do like the hardest thing especially if you're really like sleep deprived a lot, but it really does help negate the inflammation and the insulin insensitivity that can happen after even just a single night of sleep, and there's studies out there showing that.","offset":6688,"duration":28},{"text":"Dr. Rhonda Patrick: And then there's also these longitudinal studies that have been done looking at you know, people so obviously a poor sleep is a problem, you know, in the United States, I mean a lot of people are are sleeping fewer than seven hours a night. And um, but there's studies out there that have looked at people that sleep either shorter, so fewer than seven hours a night, or they're sleeping more than ten, right?","offset":6716,"duration":20},{"text":"Dr. Rhonda Patrick: So you don't want to be on either end of the spectrum and usually like sleeping long there's like other disease states associated with it, right? But um, so people that are sleeping, you know not getting enough sleep, they have a higher all-cause mortality than people that are getting at least seven to nine hours of sleep. And the same for like more than ten, they have a higher all-cause mortality than people getting between seven and nine.","offset":6736,"duration":21},{"text":"Dr. Rhonda Patrick: But if people exercise, if they're meeting the physical activity guidelines right now, which is 75 minutes of vigorous intensity exercise and 150 minutes a week of moderate intensity exercise...","offset":6757,"duration":12},{"text":"Host: Right, well because the guidelines are helpful, but they're just guidelines because I mean doing the sort of workout that you're doing, working up to doubles and triples and singles on compound lifts and then doing uh cardio like getting your heart rate elevated and then doing addition of that and then you're hiking. I mean that it's just uh I think the guidelines are a good jumping off place for people to think about.","offset":6769,"duration":22},{"text":"Dr. Rhonda Patrick: Well, we can talk about that because there's a new study that kind of throws that on the head. But but the point is is that if they if people were exercising within the guideline range, that they basically and if they weren't getting enough sleep, if they were getting fewer than seven hours of sleep per night, that they they basically had the same mortality rate as people that were getting enough sleep.","offset":6791,"duration":18},{"text":"Dr. Rhonda Patrick: So it's offsetting some of that unhealthy stuff, the insulin resistance, you know, the inflammation that we know, you know, can lead to diseases and early mortality.","offset":6809,"duration":10},{"text":"Host: So find the time to exercise folks. But of course periods of time like after a new child, or new job, or particularly stressful time, I don't know any human being, I don't care how driven, okay there's probably Goggins and Cam Haynes being probably exceptions and a few others, you know, I don't Ken Rideout and a few others.","offset":6819,"duration":23},{"text":"Host: But people who everybody else um seems to have periods of time where they need to just back off a bit. I know I certainly do, and that I feel like I'm doing pretty well for myself despite, you know and and I think that it's important that people not hold themselves to a standard that is going to make them sick or injured or miserable beyond. Yeah, you also want to continue to enjoy health promoting activities, right?","offset":6842,"duration":24},{"text":"Dr. Rhonda Patrick: Right. I mean you gotta say like what's your goal, like your goal is to be healthy, to be happy. If you're taking it to this extreme where you're trying to just go to the extreme, like go hard, go home, and it's you're sacrificing your happiness too, I mean that then that's a problem, right? Because that's part of the equation happiness is part of that health equation.","offset":6866,"duration":20},{"text":"Host: Health is a daily and lifelong thing, but sometimes it means taking a day off. I think that's what people don't say um, and I think it's in a time when perhaps a lot of people aren't exercising enough, so promoting that no days off thing can be helpful. But for those that are already sort of you know forward center of mass, you know coming off the accelerator can be really useful.","offset":6886,"duration":21},{"text":"Dr. Rhonda Patrick: Yeah. Well I also want to just mention because you know we we talked about my you know, I I work out a lot and I'm sort of addicted to it, but like not everyone has the time and motivation to to go spend an hour block of time working out.","offset":6907,"duration":18}],"startTime":6040},{"title":"VILPA, Exercise Snacks & Cardiorespiratory Fitness","summary":"You don't always need an hour at the gym. Rhonda reveals how just a few cumulative minutes of Vigorous Intermittent Lifestyle Physical Activity (VILPA) per day can drastically reduce cancer and all-cause mortality.","entries":[{"text":"Dr. Rhonda Patrick: And this is where I think the people can sigh a sigh of relief, because there's now so much emerging data that have been coming out you know, over the last decade on these short burst of physical activity that add up.","offset":6925,"duration":15},{"text":"Dr. Rhonda Patrick: They add up and people aren't really thinking about them in you know counting towards adding up to to their physical activity you know requirements for the for the week. And so there's these a lot of studies now there's on something called vigorous intermittent lifestyle physical activity VILPA studies. Have you heard of those?","offset":6940,"duration":18},{"text":"Host: Are these the exercise snacks?","offset":6958,"duration":1},{"text":"Dr. Rhonda Patrick: They're unstructured ex they're unstructured and not everyone likes the word exercise snacks, I mean I kind of like it, but the unstructured exercise they're they're they're the moments in your life where you're taking advantage of everyday situations to get your heart rate up to move.","offset":6959,"duration":16},{"text":"Dr. Rhonda Patrick: And so that could be I'm playing with my new puppy and I'm sprinting around with my new puppy. I'm you know chasing my grandkid around playing tag or my child. I'm sprinting up the stairs to get to my office. I'm running to catch the bus. I'm moving, right?","offset":6975,"duration":17},{"text":"Dr. Rhonda Patrick: And so um, researchers and there've been several studies on this now, researchers use accelerometers rather than just relying on these questionnaires which are as you know, you know extremely unreliable. I mean it's very hard for people to to remember how much exercise you sit here asking me about my exercise I mean there's only so much you know that you can be accurate with when you're trying to recall that.","offset":6992,"duration":19},{"text":"Dr. Rhonda Patrick: So these accelerometers are are worn people's wrist and they're and they're measuring like fast movement, the movement, right? And so thousands and thousands, like hundreds of thousand participants, there's a lots of data now showing that people that are doing these like short bursts at least a minute long but up to three minutes, right?","offset":7011,"duration":21},{"text":"Dr. Rhonda Patrick: Where they're getting their they're moving, I'm saying they're getting their heart rate up they're actually not measuring the heart rate in these states they're moving faster with intent, right? They're they're jogging or they're um you know, they're not of course there's the cases where they're actually exercising, but but the short burst of it um they're doing the things that I just mentioned and it's having outsized effects on on health outcomes.","offset":7032,"duration":25},{"text":"Dr. Rhonda Patrick: So for example individuals that do on the high end so they're doing, you know, three minutes of this short burst of an unstructured type of exercise snack and they do it three times a day, so it's a total of nine minutes a day, okay this type of activity, and it's considered more vigorous because of you're the intent to move, right? That's more vigorous, even though they're not measuring heart rate.","offset":7057,"duration":22},{"text":"Dr. Rhonda Patrick: That's associated with a 40% reduction in all-cause mortality, 40% reduction in cancer related mortality, a 50% reduction in cardiovascular related mortality. Wow. Nine minutes a day. And this is even in people that don't identify as exercisers, so they're not the kind of people like you and I that go and intentionally set out time to go to the gym.","offset":7079,"duration":23},{"text":"Dr. Rhonda Patrick: They're people that just they're just take they're they're doing those things, right? They're playing with their grandkids or their kids or their puppies or whatever. And so um, these moments they add up. And I'm I'm citing one study, but you know it was a dose dependent effect even doing three minutes a day, you know there's a study in women showing you know three and a half minutes a day, I mean they were having pretty profound benefits on all-cause mortality and cancer related mortality as well.","offset":7102,"duration":26},{"text":"Dr. Rhonda Patrick: And multiple studies now have shown this. I mean this is like one study after another after another. I mean it is undeniable that these short moments of you know getting physically activity active do add up.","offset":7128,"duration":10},{"text":"Dr. Rhonda Patrick: And structured exercise snacks can be part of that, like maybe you don't have a puppy, maybe you don't have a kid yet, maybe you work from home and you're not taking the you know maybe your situation's different than what I described, but you can take these moments to do exercise snacks.","offset":7138,"duration":16},{"text":"Dr. Rhonda Patrick: And that can be a minute long and it can be like there was there's studies showing that more two two studies and I'll talk about one, showing that getting up and doing 10 body weight squats every 45 minutes over a seven and a half hour work day is better at regulating blood glucose levels than a 30 minute walk, right?","offset":7154,"duration":19},{"text":"Dr. Rhonda Patrick: So you get up and you do 10 body weight squats. Pretty easy. I mean and it's also very good to break up that sedentary time. So being sedentary means like you're not moving, that also is an independent risk factor even if you do exercise for things like cancer being the big one.","offset":7173,"duration":15},{"text":"Dr. Rhonda Patrick: Although I would say if you're doing a lot of exercise you're doing pretty good, but I just like to mention that as well. I would say being sedentary is a disease, actually. That's that's something I mean people aren't thinking about it.","offset":7188,"duration":10},{"text":"Host: Even in the absence of what uh Lane Norton calls energy toxicity, like even if somebody is uh at maintenance or below maintenance calories, if they're sedentary, that's that's problematic.","offset":7198,"duration":12},{"text":"Dr. Rhonda Patrick: We do have data for one measuring cardio cardiorespiratory fitness, which is a marker of cardiovascular health, being physically fit, right? Obviously the gold standard of that would be measuring VO2 Max, your maximal oxygen uptake during maximal exercise.","offset":7210,"duration":16},{"text":"Dr. Rhonda Patrick: A lot of studies do not actually directly measure VO2 Max, they'll do, you know, maybe sub a submaximal treadmill test or they'll estimate it, right? There's a calculation out there you can do kind of what you're if you have like an Apple watch or some sort of fitness tracker what they do is which is you know it's looking at the distance that you run and the amount of time it takes, right?","offset":7226,"duration":20},{"text":"Dr. Rhonda Patrick: So like a 12 minute run would be an example people do that, you you run as fast as you can and maintain that pace for 12 minutes, you're not going all out obviously.","offset":7246,"duration":14},{"text":"Host: You see how far you can get.","offset":7260,"duration":1},{"text":"Dr. Rhonda Patrick: Yeah, yeah. And then and there's a calculation out there that's done to kind of estimate your VO2 Max, and so some studies are a lot of studies are actually doing sort of an estimation of cardiorespiratory fitness.","offset":7261,"duration":10},{"text":"Dr. Rhonda Patrick: So cardiorespiratory fitness um is really important I think for you know marking your health and longevity. And you know, if you have a low cardiorespiratory fitness, most of the times you are not physically active, right?","offset":7271,"duration":12},{"text":"Dr. Rhonda Patrick: And there are studies showing that if you don't have any you know diagnosable diseases, so you're not insulin resistant, you don't have cardiovascular disease, you don't have cancer, all that stuff, right? You're not um obese, but you have a low cardiorespiratory fitness, it is as bad or worse in terms of your all-cause mortality, you know, predicting mortality, than having cardiovascular disease, or smoking, or having hypertension, or these things that we know that are really bad for health, right?","offset":7283,"duration":31},{"text":"Dr. Rhonda Patrick: So being sedentary, as I'm saying it's low cardiorespiratory fitness, I guess it's not exactly correct, it's a little bit of I'm stretching it a little bit. But cardiorespiratory fitness is a marker of I would say fitness.","offset":7314,"duration":14},{"text":"Dr. Rhonda Patrick: And so um, that's why I think being sedentary is a disease. And people with a low cardiorespiratory fitness, I mean if you go anywhere above that, you know if from low to like low normal, that's associated with a two-year increase in life expectancy.","offset":7328,"duration":18},{"text":"Dr. Rhonda Patrick: If you go from low to um high normal, you know that's like almost a three-year increase in life expectancy. And if you go up to high then you're talking about a five-year increase in life expectancy compared to where you were at the low. But again, I'm not talking about VO2 Max, I'm talking about cardiorespiratory fitness.","offset":7346,"duration":18},{"text":"Dr. Rhonda Patrick: And it's it's really important. Here's another reason why I think that it's it's really bad. So these studies were done, by the way cardiorespiratory fitness is improved by aerobic exercise in general. That's great.","offset":7364,"duration":15},{"text":"Dr. Rhonda Patrick: And then you know if you add if you add in high intensity interval training in there mix, that also really helps because there are some people that don't respond necessarily to just doing cardiovascular...","offset":7379,"duration":10},{"text":"Host: Slow steady state.","offset":7389,"duration":1},{"text":"Dr. Rhonda Patrick: Mm-hmm. Yeah, about 40% of people don't respond, so mixing in the high intensity is good. If you're physically active and doing that that's great, if you're doing these short bursts of physical activity also good, because it's a little bit of a high intensity you know exercise, right?","offset":7390,"duration":16},{"text":"Dr. Rhonda Patrick: A min a minute running around chasing your grandkid or your puppy or your child, you know that's that's that's a hit.","offset":7406,"duration":5},{"text":"Host: Taking the stairs is amazing. I was traveling for a team...","offset":7411,"duration":2},{"text":"Dr. Rhonda Patrick: Sprinting up the stairs.","offset":7413,"duration":1},{"text":"Host: Going sprinting up the the stairs or if you're carrying a lot of luggage in the airport like going up the stairs or down the stairs. It's wild when you go to the airport, I I like to notice this, um nobody takes the stairs.","offset":7414,"duration":13},{"text":"Dr. Rhonda Patrick: Yeah, because they're there right.","offset":7427,"duration":1},{"text":"Host: Down or up like the escalators are there. And I'm always like oh this is a great opportunity to get some extra steps and some extra work but I realize that's me. Um, but it's just it's striking.","offset":7428,"duration":9},{"text":"Host: Um, and if you're in DC ever, you know, they have these long stairwells like go um up from the from the public transport and that's a workout, you know. And and I'm always like, oh free workout. Like you know like get it in my day. I mean it sucks to arrive a little bit more sweaty than you would otherwise.","offset":7437,"duration":15},{"text":"Host: But I just think if this were an experiment, and we were looking at mice, and we were videotaping from above, I always think of myself like which mouse am I going to be? All the mice are going up the automatic elevator. It makes sense why they would want to do that, but these opportunities for exercise are clearly there.","offset":7452,"duration":14},{"text":"Host: I I feel like this is also I I would be remiss if I didn't do a quick shout out to Steve Magness. Do you follow ever see his content?","offset":7466,"duration":8},{"text":"Dr. Rhonda Patrick: I've interacted with him, yeah. Um, on Twitter I've interacted with him, on X.","offset":7474,"duration":2},{"text":"Host: Yeah, I've never met him but um people should I think give him a follow. He's a very accomplished runner in his past, a running coach I believe as well, and um and a scientist, and I think has the best take on sort of measuring VO2 Max.","offset":7476,"duration":18},{"text":"Host: It's kind of interesting you know he has a theory which I think is strongly backed that most measures of VO2 Max are not measures of VO2 Max at all. But one of the best measures of cardiorespiratory fitness is how fast can you run a mile.","offset":7494,"duration":11},{"text":"Host: Hmm. And he says people are generally surprised how easy the easy stuff should feel and how hard the hard stuff should feel. So I want to just credit Steve for saying that. So I try and keep that in mind around my cardio and do some high i do a less of what you do I I confess, um some high intensity interval training Tabata type stuff and then some a lot of walks, a lot of hikes.","offset":7505,"duration":20},{"text":"Host: Yeah. And I haven't formally measured my VO2 Max in a while but I think he just nails it with that because I think people think the 30-minute jog on the treadmill where you get sweaty and you're like ah like that's accomplishing what you want but actually there's a much easier path to better health, which is what you do and more or less what Steve is describing as well. Uh does that square with your your experience?","offset":7525,"duration":21},{"text":"Dr. Rhonda Patrick: Yeah, I think so. I mean I do I do mix in quite a bit of probably more more high intensity interval training. But um, you know, I don't feel like if I felt like it was like if I didn't feel good I would I would toggle down the the pedal right I wouldn't keep keep going on it.","offset":7546,"duration":15},{"text":"Dr. Rhonda Patrick: So I think you have to again just listen to your body, you know you don't want to overdo things. And I am I mean there are people out there that are really like endurance athletes that are, you know, like that's not me. I'm a committed exerciser, I'm not an I'm not necessarily an athlete, uh but but yeah so that would that's those different I think levels here and Steve is obviously athlete.","offset":7561,"duration":20},{"text":"Host: Anyway, I've learned from him around this topic. It's been it's been helpful.","offset":7581,"duration":6}],"startTime":6925},{"title":"Sponsor: Function","summary":"Huberman reads a sponsor message for Function Health lab testing.","entries":[{"text":"Host: I'd like to take a quick break and acknowledge one of our sponsors, Function. Last year I became a function member after searching for the most comprehensive approach to lab testing. Function provides over 100 advanced lab tests that give you a key snapshot of your entire bodily health. This snapshot offers you with insights on your heart health, hormone health, immune function, nutrient levels, and much more.","offset":7587,"duration":23},{"text":"Host: They've also recently added tests for toxins, such as BPA exposure from harmful plastics and tests for PFASes, or forever chemicals. Function not only provides testing of over 100 biomarkers key to your physical and mental health, but it also analyzes these results and provides insights from top doctors who are expert in the relevant areas.","offset":7610,"duration":19},{"text":"Host: For example, in one of my first tests with Function, I learned that I had elevated levels of mercury in my blood. Function not only helped me detect that, but offered insights into how best to reduce my mercury levels, which included limiting my tuna consumption, I'd been eating a lot of tuna, while also making an effort to eat more leafy greens and supplementing with NAC, N-acetyl cysteine, both of which can support glutathione production and detoxification. And I should say by taking a second Function test, that approach worked.","offset":7629,"duration":24},{"text":"Host: Comprehensive blood testing is vitally important. There are so many things related to your mental and physical health that can only be detected in a blood test. The problem is blood testing has always been very expensive and complicated. In contrast, I've been super impressed by Function's simplicity and at the level of cost. It is very affordable.","offset":7653,"duration":18},{"text":"Host: As a consequence, I decided to join their scientific advisory board and I'm thrilled that they're sponsoring the podcast. If you'd like to try Function, you can go to functionhealth.com/huberman. Function currently has a wait list of over 250,000 people, but they're offering early access to Huberman Podcast listeners. Again, that's functionhealth.com/huberman to get early access to Function.","offset":7671,"duration":25}],"startTime":7587},{"title":"Creatine Supplementation: Muscle & Brain Health","summary":"An extensive breakdown of creatine monohydrate. They explore its traditional use for muscle volume and dive into emerging clinical data showing its profound ability to offset cognitive deficits caused by sleep deprivation or brain aging.","entries":[{"text":"Host: I want to ask you about creatine. Yeah. I'm 50, I started taking weight training and running when I was like 16 maybe, yeah. And I started taking creatine because back then I was skinny I wanted to put on muscle.","offset":7696,"duration":12},{"text":"Host: I think creatine was sort of first discovered or released back then when I was maybe 18 or something like that, something like that, 18 19. Um so I've been taking a long long time, 5 to 10 grams.","offset":7708,"duration":13},{"text":"Host: But the original protocol, which nobody does anymore, but I confess I still do it because I enjoy it was to take 5 grams three to five times per day, there was this loading phase and you would mix it with a little bit of grape juice because the idea was you were supposed to spike your insulin and then you get more into the muscles, and then you had a maintenance dose which was 5 grams per day.","offset":7721,"duration":24},{"text":"Host: Um, and the idea back then was that you need to do a washout every 20 weeks or so where you just stop taking it, you urinate out a bunch of water and then you reload. And I confess I've continued to do this minus the grape juice, but occasionally I'll do the grape juice thing.","offset":7745,"duration":16},{"text":"Host: I don't think that there's any real merit to the loading phase maintenance phase idea, but back then and still now I feel like creatine has maybe feel great, um stronger, um I did I wasn't aware of the cognitive benefits.","offset":7761,"duration":13},{"text":"Dr. Rhonda Patrick: They weren't being studied back then.","offset":7774,"duration":2},{"text":"Host: They weren't being studied back then, but what are your thoughts on why creatine suddenly has become this like banner supplement. It's like supplement of the year, we should start a supplement of the year thing, right? For a while I think vitamin D and melatonin came first, um and we'll have to figure out what years those were.","offset":7776,"duration":20},{"text":"Host: Then I feel like creatine got supplement of the year for 2026 is unless something else comes along. So creatine, supplement of the year 2026 even though it's been around for a long long time. What do you think happened?","offset":7796,"duration":11},{"text":"Dr. Rhonda Patrick: Well, so first I want to talk about your loading phase night like that was really for the studies that were being done, right? Because if you're taking 5 grams a day of creatine it takes about three to four weeks for your for your muscle creatine stores to become saturated, and researchers aren't going to do a study where they wait that long.","offset":7807,"duration":17},{"text":"Dr. Rhonda Patrick: So the loading phase really was just...","offset":7824,"duration":3},{"text":"Host: Oh, so that's what inspired it.","offset":7827,"duration":1},{"text":"Dr. Rhonda Patrick: Yeah, it was it's in this isolated bubble of in the experimental protocol, but like in the real world you have three weeks, or if you're like an athlete and you hadn't you know taken the creatine you don't have your creatine stores up and you have to quickly rapidly like increase your stores.","offset":7828,"duration":13},{"text":"Host: Got it. I was just amazed at how quickly it worked. I I might be a hyper responder, but I legitimately put on I realize some of it was water or most of it was water, but somewhere between probably 4 and 8 pounds of of water in the muscle mass. I don't want to call it lean mass because it's you know it's water in the muscle.","offset":7841,"duration":20},{"text":"Host: Um but I just was I was like, oh my goodness this is crazy, you know. And um and then people thought maybe it was a steroid, it's not a steroid, maybe it's bad for your kidneys, turns out it's safe for your kidneys in most everyone. Um pretty remarkable molecule.","offset":7861,"duration":12},{"text":"Dr. Rhonda Patrick: Yeah. I mean obviously creatine is stored as creatine phosphate in our in our cells, we make to some degree like between 1 to 3 grams of creatine a day, our liver, our brain also makes it. It's used to make energy and so your muscles if you're working out, you're really consuming a lot of energy, right?","offset":7873,"duration":19},{"text":"Dr. Rhonda Patrick: It's very energetically demanding, so having the creatine stores higher in your muscle is beneficial because one, you're going to be able to increase your training volume, right? So it's not like creatine is anabolic in the sense that protein or amino acids are, right?","offset":7892,"duration":15},{"text":"Dr. Rhonda Patrick: It's not like directly affecting muscle protein synthesis, it's just helping you train more, getting more reps in you know in whatever it is training training your training volume's going up, and because your training volume's going up then you're obviously putting more stress on your muscles which is going to lead to increased muscle protein synthesis and you know obviously there's water probably as well.","offset":7907,"duration":21},{"text":"Dr. Rhonda Patrick: That said, you know you asked me you know what happened. So I got interested in creatine back in 20 when I started basically weight training. You know, I've obviously had heard about it forever, never took it. And as I started to get into resistance training, I was like I better start taking this.","offset":7928,"duration":16},{"text":"Dr. Rhonda Patrick: This is I'm I'm in this world now and started doing some research and taking it. So I was taking the 5 grams a day because that's really what most of the studies show creatine monohydrate that's obviously the most well researched form of creatine, and I was taking 5 grams a day because I was interested in improving my my training volume and and getting the the benefits of it, right?","offset":7944,"duration":23},{"text":"Dr. Rhonda Patrick: Um and then I had Darren Candow on the podcast. Uh, that was in 2024 I think it was, and um once I had started getting into the creatine research, I the brain stuff started his brain stuff had been coming out over the past you know few years and that's for me become very interesting.","offset":7967,"duration":20},{"text":"Dr. Rhonda Patrick: I remember the first time I heard about it years ago it was like, oh it's it's helping improve cognitive function in older older you know people.","offset":7987,"duration":7},{"text":"Host: Yeah. The phosphocreatine system seems to be somewhat um biased towards forebrain structures. You know I mean obviously it's in lots of brain areas, but that there might be a heavier reliance on it for brain areas that are associated with strategic planning and you know working memory and yeah, if you if you were to sort of just map the the sort of density of usage of the phosphocreatine system you'd you'd see a frontal bias for sure.","offset":7994,"duration":21},{"text":"Dr. Rhonda Patrick: Okay, interesting. Interesting. Um well anyways, that's kind of where my interest in in you know kind of diving deeper, anything that's helping the brain is interesting to me as I know it is to you as well.","offset":8015,"duration":13},{"text":"Dr. Rhonda Patrick: And um and so I learned a lot from this podcast I did with Darren Candow, you know researches creatine and collaborates with a lot of different researchers that are doing you know research on the brain and muscle and you know lots of the bone turns out it's beneficial for the bone as well.","offset":8028,"duration":18},{"text":"Dr. Rhonda Patrick: But the brain it's interesting we also make creatine in the brain, but um it's not like so it's kind of like the muscle, right? You're not just going to if you take creatine and you don't work out, you're not going to you're not going to get any increase in lean mass, right? It's not going to do much of anything because you're not putting in the work.","offset":8046,"duration":15},{"text":"Dr. Rhonda Patrick: I think the same goes with the brain as well, where it's like researchers started to find out that well, you can't just take creatine and it's going to enhance cognitive function, it's in the background of stressing the brain, right?","offset":8061,"duration":13},{"text":"Dr. Rhonda Patrick: You're stressing your muscles by workout, same goes for the brain. It's like in these situations of stress, whether that's sleep deprivation, whether it's you know a traumatic brain injury. I mean I would argue you know there's a lot of psychological stress, depression, constantly using your brain like you and I right now in this conversation we're we're learning, we're thinking, I mean it is stressful on the brain, right?","offset":8074,"duration":25},{"text":"Dr. Rhonda Patrick: So I mean I am obviously speculating here and taking taking I'm extrapolating, right? I'm not saying that there's studies showing that but it does seem as though that that's when creatine seems to shine in the brain.","offset":8099,"duration":14},{"text":"Dr. Rhonda Patrick: And you might go well your brain makes it and it's true, your brain does make you know again it's I think between 1 to 3 grams or something, I'm not exactly sure how much but it makes its own creatine.","offset":8113,"duration":10},{"text":"Dr. Rhonda Patrick: And it's kind of resistant to taking up the creatine that you're supplementing with, um particularly because for one the muscle is very greedy. So when you're getting to that 5 gram range muscles are really consuming it if you're working out in particular, right? Your muscles are kind of consuming that because that's they're very greedy for it, right?","offset":8123,"duration":19},{"text":"Dr. Rhonda Patrick: Uh and there have now been I think a handful of studies showing that when you start to get above that, there was a study out of Germany showing this and it's a small study. This needs to be replicated, like this is all new you know emerging data.","offset":8142,"duration":12},{"text":"Dr. Rhonda Patrick: But that study showed that once you start to get to you know 10 grams, then if you look by MRI you can start to see that creatine levels are increasing in certain brain regions and perhaps in the brain regions that you were talking about. And they're going higher than than what you would get from just your brain normally making its own creatine.","offset":8154,"duration":21},{"text":"Dr. Rhonda Patrick: So the 10 grams of creatine a day, which is now what my baseline is, is based off of that.","offset":8175,"duration":6},{"text":"Dr. Rhonda Patrick: But there's studies now showing that um if you're in this sort of stressed state, your brain is stressed, like first sleep sleep deprivation for example, you're sleep deprived for 21 hours, and your brain's not working very good after not sleeping for 21 hours, right?","offset":8181,"duration":15},{"text":"Dr. Rhonda Patrick: I mean that's obviously when I have a when I travel internationally I never really sleep good on a an international flight and so I'm like not if you were to come find me after that flight I'd be like not working very good cognitively, right?","offset":8196,"duration":13},{"text":"Host: You and everybody else.","offset":8209,"duration":1},{"text":"Dr. Rhonda Patrick: Right. Well some people can sleep great on a plane, but I'm not one of those people.","offset":8210,"duration":3},{"text":"Dr. Rhonda Patrick: So um there have now been at least one study showing that if you give someone it's like something like 0.35 grams per kilogram body weight of creatine, which comes out to a lot. I mean it's like 20 25 it depends on your body weight, right? Like 20 25 grams perhaps even more.","offset":8213,"duration":18},{"text":"Host: I mean I'm 100 kilograms, that's a lot of creatine.","offset":8231,"duration":1},{"text":"Dr. Rhonda Patrick: Yeah, so it would be a lot. So for me it's more like 20 25 grams, right?","offset":8232,"duration":4},{"text":"Dr. Rhonda Patrick: But if you give individuals that high dose in that you know sleep deprived state, that their cognitively not only performing normal, but they're performing better than their baseline.","offset":8236,"duration":13},{"text":"Dr. Rhonda Patrick: And that of course generated a lot of interest. There've been studies coming out since then showing that okay, if you give older adults with mild cognitive impairment perhaps mild you know early stage Alzheimer's disease again 20 grams, you're giving them the 20 gram range of creatine it's improving their cognitive function.","offset":8249,"duration":18},{"text":"Dr. Rhonda Patrick: Why is that? Well creatine is important to make energy and when your brain brain cells are stressed out, right? I mean like energy energetic demand goes up and if you have more creatine it's going to make things easier.","offset":8267,"duration":15},{"text":"Dr. Rhonda Patrick: There's also some inflammation that's being generated in that stressed state and it seems as though creatine is also...","offset":8282,"duration":13},{"text":"Host: Uh, I'm going to interrupt there. I don't think so. I'm not trying to just be complimentary. You know, I paid close attention to the data and it seems like in certain fields like math and physics, people tend to peak with their contributions early. There's a reason why the Fields Medal is only given to people, you know, like I think it's 40 or younger. My dad's a physicist, so he can check me on this one.","offset":8295,"duration":26},{"text":"Host: But biologists, at least the ones I know that took good care of themselves, they're known to make great discoveries, be cognitively sharp, intellectually strong well into their 70s and 80s. I mean Torsten Wiesel, who co-received the Nobel Prize for brain plasticity and vision, he's still alive and he... I think he still runs. He's in his late 90s. And he paints and he's sharp. So I just... I made a point to only interrupt here.","offset":8321,"duration":31},{"text":"Host: People can check the data on the previous portions of the podcast, but I actually think that cognitively, um, using biologists as an example, it's possible in aspects of life where you're building a base of data to pull from, which is what biology really is... just an example here... to get cognitively stronger and stronger with age.","offset":8352,"duration":23},{"text":"Host: Right. I... this is a theory, but I see you as that. And I'm again, I'm not just saying it to be complimentary, although it is a compliment. It seems like you're picking up steam, you're thinking about things you're not forgetting things from way back when, you're building on the concepts and knowledge from way back when. So I find it reassuring that biologists in particular seem to have this, you know, up-and-to-the-right trajectory for cognition.","offset":8375,"duration":25},{"text":"Dr. Patrick: It's interesting. My... my late mentor, Dr. Bruce Ames, was every bit of that. I mean, you know, he passed away a little over a year ago and he was 96. But, you know, some of his most... he claimed some of his best work was done, you know, in his late 80s.","offset":8400,"duration":13},{"text":"Host: Right. You don't see that in math or physics.","offset":8413,"duration":1},{"text":"Dr. Patrick: Yeah. So it's interesting. And you know, I don't know exactly the difference. I mean, I don't know how much learning goes into math and physics as you're... as you're... like, I just don't know. But like with biology and, I mean, we're constantly learning new things and reading new papers. And then I think even just the novelty of learning new things, I mean that's brain-derived neurotrophic factor, right? Like you're... you're... you're increasing synaptic connections and neuroplasticity and you're keeping your brain younger in that way too, right?","offset":8414,"duration":29},{"text":"Dr. Patrick: So, I think the learning process is super important whether it's biology or whatever you're passionate about, right? Like you learn new languages, whatever... like the learning process itself is something that is so important for brain aging as well. Um, and yeah, so I would agree with you. But brain aging in general, yeah, I mean, I'm obviously chronologically aging and there is some degree of aging going on in my brain.","offset":8443,"duration":24},{"text":"Dr. Patrick: But, you know, so that's I think where the creatine craze has come from is the interest in... and I've definitely played a role in some of this, you know, by talking about my experience and being super interested in it because it's felt good for me. And I've noticed this experience and this is completely anecdotal again.","offset":8467,"duration":21},{"text":"Dr. Patrick: But in addition with the small studies... and they are small. Like I don't know if you've looked at them, but they're... you can... you can poke holes in them...","offset":8488,"duration":10},{"text":"Host: Subject numbers and that...","offset":8498,"duration":1},{"text":"Dr. Patrick: Yeah, they're small sample sizes. But it is kind of a consistent trend line where we're seeing more studies come out and show the same thing, same thing. And it's like, okay, to a certain point, maybe there's something here. I think that more research is going to come out on it. And I feel great doing it. So I mean, and even to the point where if I don't have my 10 grams and it's only five, like I'll notice.","offset":8499,"duration":25},{"text":"Host: Oh, yeah?","offset":8524,"duration":1},{"text":"Dr. Patrick: Yeah, but again, it could be that placebo/nocebo thing where, who knows, who knows. But you know, let's just say it is real, you know, for me, I got to have... I got to have my 10 grams of creatine for my brain. Um, you know, who knows, I may in five years be like, I was wrong. We'll see new data come out, but I don't think so. I think we're going to have... I think this is like the next... a lot of people doing creatine research, it's the new thing. They're really because there's been a lot of work on exercise physiology and...","offset":8525,"duration":31},{"text":"Host: Yeah, the safety data are there, so it's not like they have to get a lot of, you know, human subjects clearance.","offset":8556,"duration":6},{"text":"Dr. Patrick: The safety data is there. The safety data is there. I mean, it's the most well-studied, you know, one of the most well-studied supplements out there. Like you said, you were taking it when you were 18 and it was studied back then. Yeah, and it's just been studied the, you know, for all the years that you've been taking it. So, I mean, if it was unsafe, like we'd really know. And again, I don't want to get into all the data on the safety, but I think that it's pretty solid that it's... now, of course, like if you're going to go like mainline 50 grams a day, I mean, I don't know, that's a little much...","offset":8562,"duration":31},{"text":"Host: Someone on the internet will do it. People dry... what are they? Dry scoop. I mean, people have died dry scooping energy drinks. I mean, there's always a moron or two out there that are going to take things to the extreme and harm themselves doing something that no one else is dumb enough to do. But I think we look at the center of mass for things.","offset":8593,"duration":20},{"text":"Host: You know, as we're talking about creatine, I want to talk about some other supplements, but it occurs to me that if there's some data, ideally from animal studies and humans, and something is safe, I think the question nowadays because of how broadly health and supplement and other kinds of information goes in the world... I think the question that everyone should ask themselves is, okay, do I want to be in the experimental or the control group?","offset":8613,"duration":29},{"text":"Host: That's how I think about it. So like, if there's a study about creatine, or some new molecule... I'm going to ask you about magnesium in a moment, right? Um, I look at the safety margins on magnesium... okay, that... I'm comfortable with those safety margins. So that should always be question number one. And then it's, do I want to be in the experimental or the control group?","offset":8642,"duration":21},{"text":"Host: And I think that these days people are who are against supplements or against something, they'll say, well, the effect isn't nearly as big as you get from exercise. Totally, absolutely. But that's not really what we're talking about. People love this in the cannabis and alcohol thing. Whenever I make a point about alcohol or cannabis, they'll say, well, alcohol's worse. I'm like, yeah, like, and? You know, I mean, these are two separate entities.","offset":8663,"duration":27},{"text":"Host: So I think that people should just ask themselves, are you comfortable with the safety margins and do you want to be in the experimental or the control group? And then, of course, there's the, can I afford to be in the experimental group if I do something? But those are really the only questions. No one's saying that creatine's better than anything else or worse than anything else.","offset":8690,"duration":22},{"text":"Dr. Patrick: Right.","offset":8712,"duration":1},{"text":"Host: But somehow the messaging gets all messed up. And then all these news articles get generated about what creatine is and it isn't. And I find it like, um, kind of frustrating because that's... the issue is not whether or not creatine is better than exercise and good sleep. Question is, do you want to be in the experimental or the control group and can you afford to be in the experimental group?","offset":8713,"duration":27},{"text":"Dr. Patrick: Right. I like that. I like that framework, especially if it's like, well, we know it's safe. Okay, so I can potentially be in the experimental group because that's question number one you have to have that answer first, right? At least in my book. But yeah, I mean, there's flaws with all sorts of studies, and creatine studies included, right? And people make all sorts of claims about it. And you know, you got to tone it down a little bit. I mean, it's not like the best performance enhancer ever. But it seems pretty good at, you know, improving exercise volume, recovery as well. I mean, that's also something that's been shown. And then helping with the stressed-out brain.","offset":8740,"duration":37}],"startTime":7696},{"title":"Omega-3s, Cell Membrane Fluidity & Epigenetic Aging","summary":"Rhonda highlights Omega-3s (EPA and DHA) as the ultimate low-hanging fruit for resolving inflammation, keeping endothelial cells flexible, and demonstrably slowing down epigenetic aging clocks.","entries":[{"text":"Host: On the basis of our last conversation some years ago on this podcast, I started taking Lovaza, which is a... as you know, a prescription Omega-3. So very high concentration Omega-3 because I was getting it from, you know, standard sources and I thought, well, I'm hitting 50 and my Omega-3 and I want clean Omega-3, I don't want it contaminated with mercury and other things. So I'll take Omega-3s in the form of Lovaza. It's available generically now so it's pretty inexpensive. And I have to say my blood profiles were pretty good, but they improved pretty dramatically when I started taking Lovaza. So I'm grateful to you for encouraging the Omega-3 path.","offset":8777,"duration":44},{"text":"Dr. Patrick: Have you ever had an Omega-3 index test done?","offset":8821,"duration":3},{"text":"Host: No.","offset":8824,"duration":0},{"text":"Dr. Patrick: To measure the...","offset":8824,"duration":1},{"text":"Host: Oh, oh, if it's on the function test, then it would be in normal range. I know it wasn't flagged, but I don't recall what the what the level was.","offset":8825,"duration":9},{"text":"Dr. Patrick: Yeah. You want to be in the high index, not the low, right? Well, obviously if you're taking it, you're not going to be in the low. Usually it's around 2 grams a day to get you from low to high. And I do think that's one of the low-hanging fruits in terms of like something powerful and having an outsized effect on your health that people can do that's not that much effort. It's not like exercise. Exercise is effort.","offset":8834,"duration":23},{"text":"Host: Or eating salmon. I don't like fish.","offset":8857,"duration":2},{"text":"Dr. Patrick: No. Yeah, and you know, a lot of people don't like fish and also there's now microplastic contamination in our seafood sources. There's the heavy metal, PCBs, contaminants. I mean, I still eat salmon, but like, you know, it's not like it used to be. So there are other cleaner ways to get your Omega-3 levels higher. And Omega-3 is very important for cardiovascular... it's one of the most important, I would say the most powerful naturally occurring dietary compounds for suppressing inflammation and resolving inflammation would be a better way of putting it, right?","offset":8859,"duration":34},{"text":"Dr. Patrick: I mean, and that's, again, at the core of aging. And if you look at any sort of measure of aging, whether it's even these epigenetic aging clocks, they're very sensitive to inflammation and that's why there's so many studies coming out now showing Omega-3 can slow this biological aging as measured by these epigenetic aging clocks. And that's I think even in randomized controlled trials showing this that it's doing that.","offset":8893,"duration":28},{"text":"Dr. Patrick: And that leads to functional outcomes as well. So like even if you're only slowing the clock, let's say by three months, um, you're still having outcomes like where, for example, three months slowing the epigenetic aging clock by Omega-3 only is going to get you like, you know, 16% lower pre-frailty. Or if you add in Vitamin D and resistance training because a study showed a synergy between the three, then you're talking about like lowering the chance of invasive cancer by 66%.","offset":8921,"duration":30},{"text":"Host: 66%?","offset":8951,"duration":1},{"text":"Dr. Patrick: Yeah.","offset":8952,"duration":1},{"text":"Host: So Vitamin D, resistance training, and Omega-3.","offset":8953,"duration":2},{"text":"Dr. Patrick: Yeah. And this was... this was... the trial was actually out of Switzerland, I believe. And it looked at Omega-3, Vitamin D alone, or resistance training alone. And the only thing that actually slowed the aging of the clocks was Omega-3. Now, I'll say that with a caveat, okay. The baseline exercise in this Switzerland group, 88% of these people were physically active, like doing exercise. So adding, you know, 30 minutes, three times a week of resistance training on top of that didn't slow the clock more. And I wouldn't expect it to, to be honest, when you're already physically active and that's your baseline.","offset":8955,"duration":40},{"text":"Dr. Patrick: Clearly they weren't eating enough Omega-3 because that did slow the epigenetic aging clock. Other studies have shown if you're vitamin D deficient, severely vitamin D deficient, like African Americans for example, who are obese or overweight, if they add in Vitamin D and supplement with 4,000 IUs a day for six weeks, they can actually slow their epigenetic or reverse their epigenetic aging as well. So I think it again, it's all like where you're starting from.","offset":8995,"duration":31},{"text":"Dr. Patrick: But the point is that the Omega-3 alone did slow the aging of these clocks. Um, you add in the resistance training and vitamin D, those alone didn't do it, but when you add it with the Omega-3 there was synergy. So it kept going down. And when the three combined, it slowed the epigenetic aging by like 3.8 months. But that translated to like 66% less likely to get invasive cancer. Um, and then the pre-frailty was the Omega-3 alone and there was another marker I can't remember, I covered this in a newsletter a while back.","offset":9026,"duration":36},{"text":"Dr. Patrick: But like, you know, this and this isn't the first study to show this with Omega-3. Um, Omega-3s are really... I'm so sorry, Andrew, you got me on one of my favorite topics.","offset":9062,"duration":10},{"text":"Host: No, no, it's great. I mean, I'm excited because I take Lovaza, I take Vitamin D D3. I take a lot. I take 5 to 8,000 IUs per day and I get sunlight. People actually ask me, this is just a quick window into the messaging around sunlight... some people will say, if I take Vitamin D do I still need sunlight?","offset":9072,"duration":22},{"text":"Host: And you know, a big part of my messaging is trying to tell people sunlight does a bunch of other things, but I take Vitamin D at that level, I take the Lovaza, and of course I resistance train. And the Lovaza move, and actually increasing the Vitamin D, was on the basis of, yes, blood work but also our prior conversation. I feel much better. Much better.","offset":9094,"duration":25},{"text":"Dr. Patrick: Yeah. I take about 5,000 IUs a day as well. And I do get sunlight. And I agree with you, sunlight's important for... sunlight's not in Vitamin D production is not the only thing that sunlight is doing, obviously. You've talked in great depth about that.","offset":9119,"duration":17},{"text":"Host: I'm going to go into the grave... I actually want a little window over my grave, it'll be a little macabre, so I can get morning sun. I'm just kidding folks. When I'm in the ground, I'm in the ground. No, I think the Omega-3 literature has been greatly assisted by your messaging around it because it got pretty confused out there for a while. There was the usual pushback that comes after supplement of the year is released... it's a joke folks... is the, \"Oh no, it's actually bad for us.\" You know, there's always a few of those. And then we eventually arrive at sanity again and go, no, the bulk of studies point in the direction of this being healthy.","offset":9136,"duration":39},{"text":"Dr. Patrick: Right. Randomized controlled trials showing it improves cardiovascular health, lowers the incidence of cardiovascular events including heart attacks and strokes, right. These are the gold standard. We've got the observational data. We have now looking at the molecular events... epigenetic aging. We know that it's really good at resolving inflammation. Because you want your immune system to be active, but you don't want it to be overactive. You want it to be active and then turn off, right.","offset":9175,"duration":33},{"text":"Dr. Patrick: And so the Omega-3 fatty acids like DHA and EPA which are in Lovaza are what the metabo- they're when they're metabolized, they're forming these molecules: resolvins, protectins... these things are resolving inflammation. And so I think that it's just it's one of the easiest ways that you can you can increase your anti-inflammatory response. And exercise obviously being another very powerful one.","offset":9208,"duration":29},{"text":"Dr. Patrick: But the Omega-3s, it's always easier to take a supplement and so like I have my parents taking it, you know, anyone that I care about it's like, you know, easy, easy, done. You know, take your 2 grams a day. I say 2 grams a day because Lovaza is prescribed at 4 grams a day. You know, so 2 grams is pretty on the conservative side, and that's really what's been shown by Dr. Bill Harris and some of his colleagues that can basically you can take someone from a low Omega-3 index of 4% up to a high Omega-3 index of 8% by supplementing with about 2 grams a day.","offset":9237,"duration":40},{"text":"Dr. Patrick: So, and by the way, there's all sorts of data on that front with the Omega-3 index and I think we talked about this last time, but you know, five-year increase life expectancy if you're on the high end. You're talking about 90% reduction in sudden cardiac death. Brain weight in children if pregnant women are taking... yeah. Yeah.","offset":9277,"duration":23},{"text":"Dr. Patrick: I mean, it's important throughout the lifespan. It's, you know, from in utero development throughout childhood all the way through adult life and into old age. You know, these Omega-3 fatty acids are... I'm talking about the resolving of inflammation, but they're also very important for they're incorporated into our cell membranes. DHA and to some degree EPA.","offset":9300,"duration":21},{"text":"Dr. Patrick: And that has a very important role in the fluidity of our cell membranes. And this is important for if you think about our endothelial cells lining our vascular system, our arteries, you want them to be fluid and more flexible, right. That's very important for being able to respond to a stressful situation. In fact, the stiffening of our heart with age, you know, the collagen that's surrounds our pericardium that's surrounding our heart, our myocardium... like that's that increases the risk of a heart attack, you know, a cardiovascular event. You want your cells to be more flexible.","offset":9321,"duration":39},{"text":"Dr. Patrick: So that's what, you know, these Omega-3s are also doing. That's why they're also really important for cardiovascular health in addition. And the brain as well. I mean, all of our transporters, all of our our receptors, right, they're embedded in the cell membrane. And the fluidity of that membrane is important for the structure and function of these things.","offset":9360,"duration":20},{"text":"Dr. Patrick: And that's why Omega-3 affects dopamine, serotonin, right? It's why it's affecting- it's not the only reason inflammation is also, but part of the reason is because it's changing the way our cell is like, you know, structurally composed. And if you think about trans fats, like they do the opposite, right. They stiffen the cell membranes. And that's why it's like the worst thing you could do for your cardio- one of the worst things that you could do for your cardiovascular health is eat a bunch of trans fats. Smoking is another one, smoking's terrible for your cardiovascular health.","offset":9380,"duration":31},{"text":"Host: Do people still eat trans fats?","offset":9411,"duration":2},{"text":"Dr. Patrick: No, I think they're banned.","offset":9413,"duration":1},{"text":"Host: I feel like trans fats got executed in 20- when was it that trans fats got executed?","offset":9414,"duration":4},{"text":"Dr. Patrick: When they all became... I think it was 2018 when they all were like...","offset":9418,"duration":4},{"text":"Host: Yeah, they were sentenced to death.","offset":9422,"duration":2},{"text":"Dr. Patrick: No, it's- the point is that we all know trans fats are bad for our heart, but we don't think about why. And the researchers doing it know, I mean it stiffens your cell, your endothelial cells.","offset":9424,"duration":12},{"text":"Host: With donuts, right? As in like if you go get a donut, isn't a donut have a bunch of fried food?","offset":9436,"duration":5},{"text":"Dr. Patrick: There's pro- probably some amount of trans fat that's like below the threshold of being...","offset":9441,"duration":7},{"text":"Host: It's the only bad food I miss. The late-night donut.","offset":9448,"duration":4},{"text":"Dr. Patrick: I had so much margarine as a kid. My mom used to buy it by the tub, I remember. It's like this she used to go to Costco and get like this big yellow tub of margarine. I remember those tubs. And everything was cooked in it and I mean it was like on our toast and...","offset":9452,"duration":14},{"text":"Host: This was a battle in my home. Actually, I'm going to resurrect some family battles. The butter-margarine battle was a battle. Butter won.","offset":9466,"duration":11},{"text":"Dr. Patrick: Yeah, it doesn't taste the same. But you know, that was the craze, it was the low fat like the fat was bad and butter was bad and margarine was good. And it turns out, no, trans fats are really bad. Um, but the point I was trying to make was to help contrast for people to understand sometimes when I talk cell fluidity people are like, what?","offset":9477,"duration":18},{"text":"Host: No, it's good that people... I mean, I think it's very important that people understand some of the cellular molecular underpinnings of protocols because I strongly believe that understanding mechanism, even just a little bit, or striving to understand it embeds the information for people, makes it more likely that they'll do the behaviors and gives them a logic to work from when they have to make choices because life isn't perfect. That's... I know that to be certain.","offset":9495,"duration":28},{"text":"Dr. Patrick: I completely agree with you. It's certainly for me, but I hope that if people kind of understand somewhat of the why, it's motivating to try to adopt the healthy habit, but also I think it helps them remember like why it's important, right.","offset":9523,"duration":16},{"text":"Host: And it's how the brain learns. It's the secret is context. Way to remember something is context. People always say, \"It's stories.\" No, it's context. And anyway, you and I know that to be true from our background.","offset":9539,"duration":16}],"startTime":8777},{"title":"Magnesium Forms, Sleep & Systemic Functions","summary":"They contrast different forms of magnesium (Threonate vs. Bisglycinate) for sleep and cognition, and lament the lack of large-scale clinical funding for basic nutrient trials.","entries":[{"text":"Host: If I may, I'd like to ask about magnesium. I'm very bullish on magnesium, in particular Magnesium Threonate before sleep. For sleep, I take AG-Z because I helped them build it. It just has a bunch of things like Magnesium Threonate and Saffron and Tart Cherry, the things that um have either been shown or are, you know, gradually amassing research data... the other people... studies out there to support that it can facilitate either transition to sleep or sleep, but Magnesium Threonate and Magnesium Bisglycinate to me are interchangeable with respect to sleep.","offset":9555,"duration":41},{"text":"Host: But Magnesium Threonate, I'm aware there's some studies that maybe there's some cognitive benefit. So magnesium obviously could be split into a number of things, but maybe we just start there with Threonate, Bisglycinate. I have a feeling that you're aware of some additional differences between them and I'd like to know what you prefer for sleep or for cognitive benefits and then maybe we get into the other magnesiums.","offset":9596,"duration":23},{"text":"Dr. Patrick: Yeah. I think so if we if we're comparing Magnesium Bisglycinate or Magnesium Glycinate depending on how many molecules of glycine are attached to the magnesium compared to Magnesium L-Threonate. Um, the main difference here and this is based on very limited amount of data, a lot of it animal data with respect to the Magnesium Threonate, is that that form of magnesium is supposed to get into and cross the blood-brain barrier more readily and get into the brain better.","offset":9619,"duration":35},{"text":"Dr. Patrick: And in the brain, it's you know helping facilitate neurotransmission, etc., right, helping improve cognitive function. So whereas Magnesium Glycinate or Bisglycinate, you're having the magnesium attached to the glycine... glycine also is great to take for sleep. So I like to take Magnesium Bisglycinate or Glycinate for sleep. And so that I would say if you're if you're interested in more the cognition aspect...","offset":9654,"duration":31},{"text":"Host: Well, the studies I think you're referring to, the Guosong Liu's data... you know, show some in mice, some cognitive enhancement or at least some offsetting of cognitive decline. Those are different but related, obviously. In anticipation of today's discussion, I was able to find one study seems okay, it's not a huge sample size, showing a positive reports on sleep quality after Magnesium L-Threonate.","offset":9685,"duration":36},{"text":"Host: So the studies are starting to show up. But there aren't a lot of studies on magnesium for specific outcomes in humans. And I think it's because it hits like what, 3,000 plus pathways?","offset":9721,"duration":14},{"text":"Dr. Patrick: There's a lot of pathways. Yeah. It's a cofactor for many enzymes.","offset":9735,"duration":4},{"text":"Host: So if you're taking Bisglycinate before sleep, are you taking it half hour or 60 minutes before sleep?","offset":9739,"duration":6},{"text":"Dr. Patrick: I'm usually taking it I would say like a couple of hours before bed. You know, sometimes I add a little bit more magnesium in the mix, depends on the day and if I exercise more because you do sweat out magnesium. And so if you're pretty athletic, your requirements can go up by even as much as 20%.","offset":9745,"duration":19},{"text":"Dr. Patrick: But yeah, the Magnesium L-Threonate, it's interesting I very recently got interested in experimenting with it. You know, there's a little bit of human evidence as well that it improves cognition, not strong, but again, it's that you know we just don't have a lot of people researching it. And we have the animal data, the animal data's a little stronger, don't have a lot of human data, but it seems to signal it might be important, it might help with cognition, right.","offset":9764,"duration":27},{"text":"Dr. Patrick: And so I kind of got interested in experimenting with the Magnesium L-Threonate, which I haven't usually- that it's a new thing for me. I've been doing Magnesium Glycinate for a while.","offset":9791,"duration":10},{"text":"Host: I think the study actually looked at the Magtein... Yes, I have no financial relationship to Magtein, I only want to be very clear. I just mentioned that because that's a common one out there. And as far as I know, I'll double check, but they weren't paid by Magtein, but...","offset":9801,"duration":14},{"text":"Dr. Patrick: I think the Magtein did fund the study.","offset":9815,"duration":2},{"text":"Host: Oh, they did?","offset":9817,"duration":1},{"text":"Dr. Patrick: Yeah.","offset":9818,"duration":1},{"text":"Host: Okay. All right. Well, we'll put a link to it.","offset":9819,"duration":2},{"text":"Dr. Patrick: Doesn't discredit it. Unless unless there's some, you know, bad things going on which I like to think not. I mean, you know, it's supposed to be done independently, I mean, when they pay for a group to do- I mean by law they're supposed to blind the data and not bias the outcome. I mean, that's what one hopes that's what they do.","offset":9821,"duration":15},{"text":"Host: Yeah.","offset":9836,"duration":1},{"text":"Dr. Patrick: Yeah. And I think to the most part, you're probably okay, but it is something to consider if there is a potential COI, right. Um, but yeah, so I don't know. So that was the first part of your question was the difference between the Glycinate and Threonate. And then the concern that I might have, which might be something you're not thinking about is, okay, well, I need to fulfill my magnesium requirements, right?","offset":9837,"duration":22},{"text":"Dr. Patrick: And so our daily magnesium requirements, again based on our gender and our physical activity, it's a range, it's a sliding scale. So you know women 300-350 milligrams a day, men 350-400 milligrams a day, really depending on how physically active you are. And this is just, you know, your daily requirements to have enough magnesium to run repairing DNA damage, to run you need magnesium to make energy to utilize energy, you need it for neurotransmission... like it's there's so many different important functions in our body that require magnesium to work.","offset":9859,"duration":37},{"text":"Dr. Patrick: To make Vitamin- to convert Vitamin D3 into the active steroid hormone. And this, this to me is like to some degree vindicating, but also I'm super annoyed by it because you know we have all these different studies out there on Vitamin D supplementation and is it important? And I mean there's so many negative data out there, well it doesn't do what we thought it's not doing anything.","offset":9896,"duration":28},{"text":"Dr. Patrick: But half the US population doesn't get enough magnesium. And so those enzymes that are important for converting the D3 that you're taking into the active steroid hormone are not working properly. Um, so anyways, I'm not going to go on that tangent, but I'm just saying magnesium is doing a lot of things. So if you are taking the Magnesium Threonate and let's say it is getting into the blood- sorry, the brain more readily, then the concern would be well then not enough of it is around for you know DNA repair in other organs and stuff. And so you might want to get another source of magnesium. It's all theoretical, right, and like that's not I would- there's no data on that. So just mostly because no one's looking at it. No one's investigating it.","offset":9924,"duration":47},{"text":"Host: Yeah. Not a lot of incentive. It's funny when people will always say, well, there's no incentive because the drug companies can't make a lot of money on it. And I sometimes that's true. But I have to chuckle because as a scientist, I will tell you folks, and- like I wish I could just like paint this across the sky, but then I'd get accused of being like a chemtrail person or something. Um, the reason there's no studies on BPC-157... the reason there's no like RCTs on a randomized control on different forms of magnesium and large sample size is because we barely have enough money to fund the current research.","offset":9971,"duration":40},{"text":"Host: Like, I- I'm not trying to get make this political, like we just had a 1% increase in the NIH budget but like there isn't an infinite amount of money to run studies. And so scientists are if they already work on magnesium or or it becomes interesting to them because it came up in a screen of pathways, people aren't- there are not a lot of scientists sitting around going, \"Oh, like maybe I should study- compare Magnesium Malate, Bisglycinate, Threonate in sleep in 2,000 subjects male, female like pregnant and perimenopausal...\" like, no, no, there's no money to do it.","offset":10011,"duration":33},{"text":"Host: So that's where I get back to: is it safe, do you want to be in the experimental or the control group, can you afford to be in the experimental or the control group? Yeah, I feel like that's like all we've got. And I'm only I'm chuckling out of it's a sort of like a laughter of pain because I get where people are coming from, but the drug companies are not like avoiding studying magnesium because there's no money to make, it's because what would that even look like? What endpoint, what disease?","offset":10044,"duration":32},{"text":"Dr. Patrick: Yeah, anyway. You're not going to cure you know cardiovascular disease or cancer by taking a magnesium supplement. I mean, the- these nutraceuticals, these vitamins and minerals, they're they're about prevention, really. And and and giving your body the right nutrients that it needs to do and function properly. You know, whether that is getting enough sleep... you know, when you're when you're stressed, when your cortisol goes up chronically, you're depleting magnesium. You know, it's it's- it's very like magnesium's being used to deal with that stress, right.","offset":10076,"duration":34},{"text":"Dr. Patrick: So there there's a reason that we need things like magnesium and you know, Vitamin D, it gets converted into steroid hormone changing 5% of our you know our genome. So it- yeah, it's different. It's not like a pharmaceutical where you're you don't need this you know to function optimally but it- it's the whole like, okay, I'm sick and now I need this you know or I'm overweight, right, we got the GLP-1s, right, I'm fat, I'm obese, and I need to you know help fix that. And so that's kind of a different paradigm than specific endpoint type stuff.","offset":10110,"duration":40},{"text":"Host: Yeah, exactly. Yeah. I think that's super important for people to hear that. Oh, by the way, I should just say uh for your for your sake um and for the listeners, I divide supplements into basically four categories: food replacement, like whey protein or a protein bar, obviously. Sort of general support, specific effects, and then experimental maybe.","offset":10150,"duration":33},{"text":"Host: And so I think what we're talking about here with magnesium is kind of combination of maybe helps with sleep, um specific effects that you're aware of like required and you're trying to top off, you're trying to make sure that you're covering a deficiency.","offset":10183,"duration":16},{"text":"Dr. Patrick: Yes. Yeah. You're trying to make sure you're getting enough of the magnesium, exactly.","offset":10199,"duration":5}],"startTime":9555},{"title":"Multivitamins, CoQ10, Urolithin A & Sulforaphane","summary":"Rhonda reviews the other key supplements in her routine, citing recent trials on multivitamins for memory preservation, Urolithin A for mitochondrial repair (mitophagy), and Sulforaphane for detoxifying airborne carcinogens.","entries":[{"text":"Host: Are there any other things that you take that are just trying to make sure that you're not deficient anywhere, um or for specific reasons? We've talked about a few along the way here: Glutamine, Vitamin D, Omega-3s, Creatine.","offset":10204,"duration":14},{"text":"Dr. Patrick: I take a multivitamin and that is to cover my bases because, you know, there's there's a lot of things in a multivitamin. You have to find a obviously a good quality one. But, um, and anyone that tells you that multivitamins are useless, they're wrong. I'm going to tell you that, they're wrong. Because I think now we have pretty strong data, three very large randomized controlled trials part of the Cosmos trials... have you heard of these studies?","offset":10218,"duration":42},{"text":"Dr. Patrick: And it's really I think pretty clear that in these studies, older adults, so we're talking 65 years and older that are taking a multivitamin supplement for, you know, was it a year, I think it was. Um, it could be two but I think it was a year. And it was by the way, Centrum Silver. It was like your standard, you know, anyone could afford to get it at Walmart type of vitamin.","offset":10260,"duration":24},{"text":"Dr. Patrick: Um, and after a year of taking this multivitamin, it globally reduced brain aging by about 2.1 years, from three trials globally reduced brain aging by 2.1 years. Battery of tests that are done, right. I mean it's you know I'm just talking about general here. And it also reduced episodic brain aging by 4.9 years.","offset":10284,"duration":25},{"text":"Dr. Patrick: So that would be, you know, as people probably already are familiar with that listen to this podcast, you know episodic memory, that's the part of memory that's involved in like remembering events and and people and like experiences... am I right?","offset":10309,"duration":14},{"text":"Host: Yes, sequence of things.","offset":10323,"duration":1},{"text":"Dr. Patrick: Sequence of things. Yeah. And so, you know, that's a big effect for just a daily multivitamin, you know. And so for that reason, you know, I mean I've been taking it before these these studies came out, but my parents, you know, anyone that's older adult should be taking a multivitamin. So that's another one that I take. Um, and I take it to cover my bases as well and obviously not an older adult and who knows it might not have the same effect on me, but um, you know, it's one of those that it's it's not harmful if I'm you know it's a little bit of an expensive urine, fine, but I know it is covering some of my bases in terms of some of the micronutrients in it, right.","offset":10324,"duration":46},{"text":"Dr. Patrick: The other ones that I take in besides the one that you mentioned, which is Vitamin D, Omega-3, I do Creatine, Magnesium. I do Magnesium Glycinate. I should look into the Bisglycinate because I definitely would like another molecule of glycine, I like it for my sleep.","offset":10370,"duration":17},{"text":"Dr. Patrick: But I also sometimes take another form of magnesium, which is it's like a mixture of Magnesium Malate and Threonate I think are the main- and Glycinate is also in that. But sometimes I take that for sleep. And then I take Ubiquinol, um, for mitochondrial health.","offset":10387,"duration":24},{"text":"Host: You like the data on that? Obviously if you're taking it.","offset":10411,"duration":3},{"text":"Dr. Patrick: It's- there's stronger data I think on Ubiquinone, which is the oxidized form, it's more stable. There's just when I say stronger I mean more data.","offset":10414,"duration":11},{"text":"Host: Do you take Coenzyme Q10? Co- Q10, excuse me.","offset":10425,"duration":3},{"text":"Dr. Patrick: So Co- CoQ10 is Ubiquinol.","offset":10428,"duration":2},{"text":"Host: Okay.","offset":10430,"duration":1},{"text":"Dr. Patrick: Yeah. And so and so I'm taking the reduced form of it which is Ubiquinol, the the more stable form would be Ubiquinone.","offset":10431,"duration":7},{"text":"Host: Are those trademarked names? because I take Coenzyme Q10. I'm guessing if I took a closer look at the bottle I'd see the Ubiquinone...","offset":10438,"duration":8},{"text":"Dr. Patrick: It's Ubiquinone, yeah. Ubiquinone. The Ubiquinol is a little bit more bioavailable, but yeah. So I'm pretty convinced that that helps with mitochondrial function. Um, you know, it's not like you could always have more data, right? So we'll just leave it at that.","offset":10446,"duration":19},{"text":"Dr. Patrick: The other one I take is now I'm taking Urolithin A in the form of Timeline. I'm taking Mitopure, by the way I have nothing to do with these companies. But there's now I've just been over the years increasingly interested. So Urolithin A is something that is formed from a type of polyphenol that's found in some fruits, um like pomegranate being the main one. I think raspberries may also have some, I think walnuts also, but it's ellagitannin is the polyphenol.","offset":10465,"duration":32},{"text":"Dr. Patrick: And these ellagitannins get metabolized by the gut microbiome and the metabolites that are formed, one of them is called Urolithin A. And so Urolithin A is a compound that seems to stimulate the process of mitophagy, which is a very specific form of autophagy that's that's only for mitochondria.","offset":10497,"duration":26},{"text":"Dr. Patrick: And you know that's been shown in- there have been randomized controlled trials showing this in humans. It does stimulate mitophagy um blood cells as well as a muscle biopsy. But that's a an important cleanup process for for how our mitochondria repair themselves. There's no repair enzymes, right, like they're you know part of that repair process is mitophagy where they're getting rid of selectively can get rid of parts of a mitochondria that are damaged. So it's really like a rejuvenation.","offset":10523,"duration":31},{"text":"Dr. Patrick: And some of this the clinical data I would say is emerging, more needs to be done, but it seems to in some cases improve endurance performance, which makes sense because they rely heavily on mitochondria, but even also um help with the immune system and this whole inflammaging. So it helps keep immune cells, it seems like it's helping keeping immune cells quote-unquote younger. So again, emerging data, but it's I'm in that I'm like I'm the experiment group. It seems to be safe and I'm not taking too high of a dose. So that's another one that I'm supplementing with.","offset":10554,"duration":51},{"text":"Dr. Patrick: The other one that I'm taking also is uh a very- of a form of, I'm going to call it Sulforaphane, but it's not Sulforaphane, it's the precursor to Sulforaphane, glucoraphanin because that's more stable. And so I take something called Avmacol, um, which the reason I take that one is because there's oh it's 13 now and a new study just came out 13 studies using that that form.","offset":10605,"duration":23},{"text":"Dr. Patrick: Um, and Sulforaphane is also one of those plant phytochemicals. It's formed- it's found in cruciferous vegetables as you know we've talked about this before, so I'll I'll try to leave it make it brief. But um, so glucoraphanin is in in these cruciferous vegetables like broccoli, broccoli sprouts are really really great source of it. And it- when the plant is crushed, you know like when you eat it, eat broccoli or chew it, whatever, an enzyme is activated that converts glucoraphanin into Sulforaphane.","offset":10628,"duration":31},{"text":"Dr. Patrick: The reason I take it is because I've been now convinced by I would say the limited number of human studies, clinical studies, but also the totality of evidence looking at cruciferous vegetables in general and then also animal data, that um it's really important. It's probably the the best naturally occurring dietary activator of a stress response pathway that is important for detoxification. And that that pathway is the Nrf2 pathway. I'm sure you've heard of that pathway.","offset":10659,"duration":33},{"text":"Dr. Patrick: Sulforaphane is a very very powerful activator of that pathway and what I mean by pathway is that gene is turning on and turning off many many other genes. What we know about it is that it's very important for activating the the detoxification genes that are involved in detoxifying things that are that are harmful to us.","offset":10692,"duration":21},{"text":"Dr. Patrick: And so the classic studies that have been done, some of them most of them in China where air pollution is very high, is that if you take, you know, this broccoli sprout Sulforaphane extract, you can start to excrete compounds that are found in air pollution like benzene that are carcinogenic, right, and you can start to excrete it after 24 hours by like 60%.","offset":10713,"duration":26},{"text":"Host: Great. What about plastics?","offset":10739,"duration":1},{"text":"Dr. Patrick: So that's my- that's my thing. That's why I'm taking it, my whole family. Because the same enzymes that are activated by um by the the Sulforaphane that detoxify benzene... so basically you're detoxifying it what I mean is you're basically making it water-soluble so you can excrete it through urine.","offset":10740,"duration":23},{"text":"Dr. Patrick: Okay. The same ones, that's exactly what BP- the those enzymes do to BPA. They make it water-soluble and help you excrete it through urine. There's no human data showing this yet, I want someone to do the study. But we do have animal evidence where, you know, animals are given a high dose of BPA and Sulforaphane and it protects against the toxicity.","offset":10763,"duration":26},{"text":"Dr. Patrick: I basically think that it's someone's going to show it and it's going to be clear because the the enzymes that are, you know, involved are activated by this, you know, by Sulforaphane and that's been shown with benzene and acrolein excretion, right. So why wouldn't it be BPA? Never know.","offset":10789,"duration":14},{"text":"Host: The mechanistic logic is there.","offset":10803,"duration":1},{"text":"Dr. Patrick: Yeah, yeah, exactly, exactly. So that's another reason why also it increases glut- it's been shown in human studies to very powerfully increase glutathione in both the plasma and the brain. And that's also through the Nrf2 pathway. It activates the powerful antioxidant pathway.","offset":10804,"duration":19},{"text":"Dr. Patrick: It also deactivates phase one biotransformation enzymes that are involved in um turning a pro-carcinogen into a carcinogen. So those are things like you're eating, you know, you're grilling your meat at a high temperature and you're getting heterocyclic amines, right. I mean these these things can be harmful.","offset":10823,"duration":23},{"text":"Dr. Patrick: But our body can deal with it and we had a cancer doc on here recently and I was scared to ask him the question because I didn't want the answer, but I did want the answer of, you know, the char on meat and he's like it's pretty pretty serious carcinogen. That's real. I mean the occasional thing isn't going to be a problem.","offset":10846,"duration":19}],"startTime":10204},{"title":"Microplastics, BPA & Detoxification","summary":"The conversation shifts to the ubiquity of microplastics and endocrine disruptors in clothing and everyday items, and how certain pathways may help the body excrete them.","entries":[{"text":"Host: You'll be relieved to know and this is not a promotional that the can that you're drinking out of, these are intentionally BPA, BPS, and PFAS-free. We had- we had that tested. We'd be happy to send you the results.","offset":10865,"duration":12},{"text":"Dr. Patrick: I already know, I already knew about that.","offset":10877,"duration":2},{"text":"Host: Yeah. Because I know that you and I are both- I am wary of of the BPAs and um and the rest. I think it's wild that 10 years ago people like Charles Poliquin were saying, \"Don't handle receipts.\" and you know, and everyone's like, \"This is really kooky.\" or actually back then no one even heard what he was saying it was such a niche thing.","offset":10879,"duration":21},{"text":"Host: Then people were very I think disparaging of people saying beware of receipts. Now I think um the microplastics um and the BPA BPS um PFAS concern is is really taking hold more broadly and I think that, you know, the tables have turned.","offset":10900,"duration":20},{"text":"Dr. Patrick: Yeah. And really obviously you can't eliminate them completely. It's impossible. They're everywhere. They're everywhere.","offset":10920,"duration":6},{"text":"Host: Clothing I heard was the main...","offset":10926,"duration":2},{"text":"Dr. Patrick: It's the main source of microplastics in the ocean, right, because our wash- we're washing our clothes and there's they're like this shirt that I'm wearing. I mean, it's it's got microplastics in it for sure. Um, and and so every time you're washing your clothes you're all the microplastics are coming out and getting into the ocean.","offset":10928,"duration":21},{"text":"Dr. Patrick: And also then when you put your clothes in the dryer and if your dryer is ventilating anywhere in your house, the microplast- you're breathing those in, the microplastics.","offset":10949,"duration":8},{"text":"Host: They sell these traps. When I did the episode on microplastics I found out that online you can, I think it costs, it's not cheap cheap, but it's like concerning they last a while. I think they're somewhere with refill somewhere in the neighborhood of I want to say something like $70, but it traps supposedly traps the microplastics in the wash- in the washing machine. And in Europe I think this is actually built in or is required in an- in a number of countries. Like they're way ahead of us.","offset":10957,"duration":30},{"text":"Dr. Patrick: They're always...","offset":10987,"duration":1},{"text":"Host: They're way ahead of us on a number of things. I mean, on a few things they're really they're far behind, I must say with respect to health, but on on many things they are way ahead of us.","offset":10988,"duration":11},{"text":"Dr. Patrick: Yeah. Well, clearly with the Switzerland people in Switzerland being 80% like 88% of them being physically active, they're way ahead of us on that.","offset":10999,"duration":7}],"startTime":10865},{"title":"Sponsor: Martina","summary":"Huberman reads a sponsor message for Martina yerba mate.","entries":[{"text":"Host: I'm excited to share with you that Martina, the yerba mate drink that I helped create, is now available at Sprouts Market nationwide. Longtime listeners of the Huberman Lab podcast know that yerba mate is my preferred caffeine source. It provides a smooth energy lift without giving you the jitters, and it has many other benefits such as helping regulate blood sugar, improving digestion, mild appetite suppression, and more.","offset":11006,"duration":29},{"text":"Host: Martina is my absolute favorite of all the yerba mate brands out there, and believe me, I've tried them all. The flavors are fantastic. I drink at least three cans of Martina every single day. You'll often see them on the table during our podcast recordings. I absolutely love the product and I'm proud to now have it sold at Sprouts Market.","offset":11035,"duration":24},{"text":"Host: Also, there's a great new offer. They are giving away a free can of Martina to anyone who buys it at Sprouts and sends in a photo of their receipt. To learn more about how you can get a free can of Martina, go to drinkmartina.com/offer. Again, that's drinkmartina.com/offer to get a can of Martina for free at your local Sprouts Market.","offset":11059,"duration":25}],"startTime":11006},{"title":"BPC-157, L-Carnitine, Alpha-GPC & Nicotine","summary":"Huberman and Rhonda trade thoughts on experimental compounds like BPC-157 and L-carnitine, and discuss Alpha-GPC as a healthy alternative to the current youth craze of using highly addictive nicotine for focus.","entries":[{"text":"Host: What is your threshold for you and what do you think is kind of reasonable levels of what's actionable for you? Like, how do you set that? I think it will help people kind of understand how you're approaching stuff.","offset":11084,"duration":17},{"text":"Dr. Patrick: What's actionable in terms of improving what I'm interested in improving my health like or...","offset":11101,"duration":6},{"text":"Host: Yeah, like I mean, without picking any specific example, like when you look at the literature and you see, let's say let's take BPC-157, it's kind of a fun one because everyone's excited about this now except the physicians um who don't like working with peptides besides GLPs or other FDA-approved peptides, they're like freaking out online. Heard from them all the time.","offset":11107,"duration":25},{"text":"Host: Compounding pharmacies just got the green light that they're going to be able to do basically whatever except sell Retatrutide, which is under patent. Um, so there are many many animal studies on BPC-157 showing accelerated cartilage growth, nerve growth after injury and on and on and on. And angiogenesis. So there's some potential cancer risk there, right?","offset":11132,"duration":30},{"text":"Host: But basically zero human data. There's one study weak study self-report. There's actually a clinical trial where they I'm not making this up folks is BPC enemas, very high dose it for a uh for a for some sort of bowel disease or bowel inflammation. And the study was like I don't think the study was completed or something like that. Don't ask me why, no I'm not making this up. Um, but that's pretty much the only human data that I'm aware of. Um, but tons of people injecting and swallowing BPC.","offset":11162,"duration":28},{"text":"Andrew: Have you experimented with... um, L-carnitine? Because of the mitochondrial effects, because I was able to find some good studies on sperm and egg quality, on mitochon... which are thought to be downstream of mitochondrial health.","offset":11190,"duration":15},{"text":"Rhonda: Right.","offset":11205,"duration":1},{"text":"Andrew: That's the idea.","offset":11206,"duration":1},{"text":"Rhonda: Right, it's downstream. If you can improve mitochondrial health, fertility... which is why NR is now involved with fertility, seems to be improving fertility. It's right, if you can improve mitochondrial health, then you're going to improve fertility, sperm health, right, egg health, right? Um, yeah, L-carnitine, a lot of those studies came out of my mentor's lab, Bruce Ames, so he was he looked at the combination of L-carnitine and alpha-lipoic acid improving mitochondrial health.","offset":11207,"duration":22},{"text":"Andrew: Hmm.","offset":11229,"duration":1},{"text":"Rhonda: And came up with the supplement that it's it's called Juvenon now, but it's L-carnitine with alpha-lipoic acid.","offset":11230,"duration":6},{"text":"Andrew: It's a pill.","offset":11236,"duration":1},{"text":"Rhonda: It's a supplement, yeah. And um, so yes, I have experimented with that, and in fact, my husband takes it, but I mean, I just can't take so many supplements.","offset":11237,"duration":11},{"text":"Andrew: Right. Yeah.","offset":11248,"duration":1},{"text":"Rhonda: You know, so we have our... yeah, but it is, you know, you can find you can find evidence that it improves mitochondrial health, so...","offset":11249,"duration":6},{"text":"Andrew: I was just curious.","offset":11255,"duration":1},{"text":"Rhonda: Yeah, it's just a matter of again, like what what are you what are you looking for? I I feel like I'm doing a lot of high intensity interval training too and I'm taking the Urolithin A. That's a lot, you know, I'm doing a lot of stuff to optimize mitochondrial health. I mean, at some point you have to like not can't do everything there is.","offset":11256,"duration":18},{"text":"Andrew: Sure. No, of course not.","offset":11274,"duration":1},{"text":"Rhonda: But yeah, L-carnitine...","offset":11275,"duration":1},{"text":"Andrew: And it's budget limited too.","offset":11276,"duration":1},{"text":"Rhonda: I don't know that it's going to help you live longer either. Now, it might help with your exercise recovery a bit, right? It might help improve mitochondrial function. I mean, maybe it's going to help with depleting some of the NAD stores. I mean, if you can improve mitochondrial health then, you know, you're improving things like on a small scale, right? So... mitochondrial health is at the core of everything.","offset":11277,"duration":21},{"text":"Andrew: I started experiment... I've started experimenting with it, but I take it in injectable form. It's going to shock some people. You can get away with taking much lower milligram count. Otherwise you have to take a lot of it because a lot of it just isn't absorbed if you take it orally. And then I was told that if you take it orally, you also have to do something to offset the increase in TMAO, and that worried me. So I figured, needles don't scare me, I'll just inject it.","offset":11298,"duration":26},{"text":"Rhonda: Interesting. Yeah. Yeah, the TMAO thing... I mean, so not it depends on your gut bacteria whether or not you're metabolizing the L-carnitine into TMAO. There's actually a lot of complexity involved in that whole thing. But you can get your TMAO measured. So if you were supplementing with it... I mean the same goes for choline, you know, like if you're worried like choline can be converted into TMAO.","offset":11324,"duration":21},{"text":"Andrew: I'll take Alpha-GPC before a workout sometimes or if I need to... um, if I ever need to focus late in the day, I don't want caffeine because it impedes my sleep, but I'll take Alpha-GPC because this is kind of a cool effect, Alpha-GPC actually will improve your REM sleep. It's not a huge effect, but you'll notice you'll get more REM sleep. So it's one of the few things I've found that can increase energy late in the day, do a workout or or work if I have to work later into the day, still sleep just fine and actually sleep better.","offset":11345,"duration":30},{"text":"Rhonda: What is work later into the day mean for you? Like working until like eight, nine o'clock or...","offset":11375,"duration":3},{"text":"Andrew: Yeah, well I do that um often, but but I don't like to work out after 2:00 PM, because I like caffeine before I work out. But I'll do some cardio in the afternoon or something. But if I really have to push push push, or if I've traveled and I really need exercise and I want to get a 6:00 PM workout but I also want to fall asleep at 10:30, I'll take some Alpha-GPC.","offset":11378,"duration":22},{"text":"Rhonda: I used to take that like, I don't know, it's been maybe like ten years. But... um, it's interesting, I might try experimenting with that again. I'm always looking for things that I find a little bit safer, like I don't do the nicotine as you know...","offset":11400,"duration":15},{"text":"Andrew: It is shocking how many young people are taking nicotine now.","offset":11415,"duration":3},{"text":"Rhonda: Oh, I know.","offset":11418,"duration":1},{"text":"Andrew: Yeah.","offset":11419,"duration":1},{"text":"Rhonda: I've never tried it.","offset":11420,"duration":1},{"text":"Andrew: First of all, it's highly addictive. Forget the blood pressure and the vasoconstriction, that's all bad, you know, I think the the big issue is that if I take it... um, I start getting this spasm in my throat when I don't take it, and that's because of its... I have a friend who works on these pathways and it's because of the activation of the muscarinic receptors. So so on smooth muscle you start getting a tick and kind of a clearing of your throat, and then you take more nicotine, you feel fine. So I didn't want to become dependent on it. And um, I don't I don't like it. I think it's I think it's a a bad habit that a lot of people are going to be seeking to quit later.","offset":11421,"duration":34},{"text":"Rhonda: A lot of young people.","offset":11455,"duration":1},{"text":"Andrew: Older people might benefit from it because of the cognitive enhancement, but that's a whole other story.","offset":11456,"duration":4},{"text":"Rhonda: Well maybe the Alpha-GPC and the Creatine and Magnesium L-Threonate.","offset":11460,"duration":4},{"text":"Andrew: Alpha-GPC is is very is very helpful for if you need to really lock in for a few hours and do something physically or or cognitively.","offset":11464,"duration":7},{"text":"Rhonda: How much do you take?","offset":11471,"duration":1},{"text":"Andrew: I take 600 milligrams. You can take up to 900, but I do just fine on 600. So I think I just take it in pure form and in capsule, any of them out there that come from a reputable brand is like going to work.","offset":11472,"duration":12},{"text":"Rhonda: What about like before a podcast or something like that, does that does it have any effect or what?","offset":11484,"duration":4},{"text":"Andrew: Oh yeah.","offset":11488,"duration":1},{"text":"Rhonda: It does.","offset":11489,"duration":1},{"text":"Andrew: Oh yeah, it'll put you into a... you know, I mean if you feel like you want to be heightened focus, but I rely on water, caffeine, electrolytes, and good good sleep. There's this wild study, we don't want to go... I don't want to take us too far off track here, um but there's a study out of WashU recently, really really talented researcher. I want to bring him on this podcast. He does brain imaging, and he compared um essentially the effects of drugs for ADHD versus a good night's sleep, and basically found that there's no focus enhancement of Adderall, Vyvanse, Ritalin type drugs. They mainly looked at Ritalin. All it's doing is increasing alertness to the level that you would get after after a good night's sleep. It may be that these drugs just increase alertness which allows you to dial in focus, but if you're sleeping well and enough, you make up the gap and people with ADHD might just be having some serious sleep defects. So, you know, it it speaks to this thing like, I don't know that there's a single drug that can actually increase cognition and focus. Most of them probably just get you in the plane of alertness that allows you to dial in your focus. Some people be like, \"That's BS,\" they take Modafinil, but this is just another form of increasing alertness.","offset":11490,"duration":65},{"text":"Rhonda: Well, reducing anxiety I think things that are anxiolytic help with that as well, and I think I was talking about... I don't know if I was telling you or someone else before the podcast, one of the reasons why I also like that metabolic switch with the ketosis and the beta-hydroxybutyrate, and sometimes I'll take exogenous ketones too, although if you take them in a fasted state it kind of shuts down the lipolysis. But anyways, is because it increases GABA. The beta-hydroxybutyrate increases GABA and for me it's beneficial because I am the phenotype where like, you know, I can have other things going on in my mind that it's... I don't want to say it's anxiety but it's more of that anxious phenotype, if that makes sense. And so the the increase in GABA really does um help me with focus because it's quieting down, I think...","offset":11555,"duration":46},{"text":"Andrew: I actually think that a lot of people who are very intellectually engaged, which clearly you are over many many years and very physically active and healthy, there's a lot of capacity there and unless there's something to really absorb all that capacity, you can get multiple tracks going, and we sometimes think of that as anxiety or even ADHD, some people will say it's ADHD. I don't I don't necessarily think it's that, but it's an uncomfortable state to be in, and it's so pleasurable to be like where all one's resources, physical or cognitive or both, are harnessed. It's a it's a very pleasant state. Earlier you were saying the GABA increase from the ketosis, I think more and more we're just realizing that people have differing levels of excitatory to inhibitory balance in the brain. And so some people like things that bring GABA up, some people like things that bring glutamate up, broadly speaking, and finding that sweet spot is where you go, \"Oh, like I'm alert but calm.\" And that's that's what we want.","offset":11601,"duration":53},{"text":"Rhonda: Right. That's what it does for me. Alert but calm. And for me I'm like, and I noticed that with... there was a few years ago I really experimented with a ketogenic diet. I just can't do that type of diet, but I did experiment with it and that was the one of the main things that I noticed is like, \"I'm alert but calm,\" and it's like I liked it.","offset":11654,"duration":18},{"text":"Andrew: Well then don't take nicotine, because the reason people like nicotine is it's a stimulant that calms you down. So I do think that one of the reasons it's so habit forming is because I know of nothing else that puts you in that plane of focus of alert but calm that is reasonably low cost, that is legal... I've never out- I'm come clean, I've never done amphetamine or cocaine, so I'm not... I wouldn't want to and clearly that's a path to destruction. So the reason so many young people are taking it is because it gets them right in that plane of alert but calm, but it has all these negative effects that go with it.","offset":11672,"duration":33},{"text":"Rhonda: Yeah, and that's why I've stayed away from it, because I know I'd probably love it.","offset":11705,"duration":4},{"text":"Andrew: I've asked some young folks who ask me about nicotine, \"How many milligrams are you taking?\" They'll say \"nine milligrams.\" I'll say \"How many times per day?\" and they'll say \"eight times per day.\" I'm like \"Oh my god,\" like that's crazy!","offset":11709,"duration":10},{"text":"Rhonda: But they didn't start there. You just quickly get there. You adapt.","offset":11719,"duration":4},{"text":"Andrew: Yeah, so I you know, I don't want to sound like that curmudgeon that's like \"Don't drink and don't take nicotine\" and this kind of thing, but it's a it's a slippery slope. Right. Yeah, I mean there's a very slippery slope.","offset":11723,"duration":10},{"text":"Rhonda: Right. Yeah, I mean if there's other things that you can do that maybe it's not going to be as potent, but like...","offset":11733,"duration":4},{"text":"Andrew: Alpha-GPC.","offset":11737,"duration":1},{"text":"Rhonda: Alpha-GPC, for me I like doing I like my metabolic switch and my ketones.","offset":11738,"duration":5},{"text":"Andrew: Nice. Well, I'll be curious to to hear how you feel on the Alpha-GPC.","offset":11743,"duration":5},{"text":"Rhonda: I remember liking it. I I don't know why... I think I stopped taking it because I got pregnant was probably what it was, and then I just... it's one of those things where you just forget. You go back to the basics and then like the... yeah.","offset":11748,"duration":13}],"startTime":11084},{"title":"Q&A: Nattokinase, Glass Bottles, Seed Oils & Sauna","summary":"In a rapid-fire Q&A, Rhonda fields audience questions covering nattokinase, the surprising microplastic content in glass water bottles, her stance on seed oils, and her personal hot tub and sauna routine.","entries":[{"text":"Andrew: Yeah. Different experiment. Before I came on here, I did put out a call for some questions to the world.","offset":11761,"duration":7},{"text":"Rhonda: Okay.","offset":11768,"duration":1},{"text":"Andrew: Rapid fire Q&A from the land of X and Instagram. Oh this is the... these are the students of the class, of your class, and this way I think about it. Actually, I wanted to ask about this, so I'm so grateful that this person asked about Nattokinase for improving blood lipid profiles. Is it something you're interested in or have experimented with?","offset":11769,"duration":20},{"text":"Rhonda: It's not something that I've experimented with, and I've been more interested in Natto than Nattokinase. I know some... I really would have to say I don't have enough data to really have an opinion on it.","offset":11789,"duration":12},{"text":"Andrew: Okay. Well, I don't have enough data to have an opinion on it, but I take it anyway. Lot of questions about things we already talked about, so cold plunge, um etc. But an exceptional number of questions about microplastics. And I know we touched into it, but on a scale of one to ten, ten being like you're really concerned, how concerned are you about microplastics for mental and physical health, longevity, just broadly speaking?","offset":11801,"duration":24},{"text":"Rhonda: I would say I am less concerned about microplastics than I am about not getting the right nutrients and micronutrients from from our foods, because our body can detoxify at least some of the chemicals associated with them. The microplastics themselves, I mean, I guess it's not... we don't really know what they're going to do long-term, but I'm concerned enough to try to avoid... to sorry, limit my exposure to them as much as possible.","offset":11825,"duration":26},{"text":"Andrew: So you don't drink out of plastic water bottles.","offset":11851,"duration":2},{"text":"Rhonda: I mean, I try not to as much as possible. I mean, you know, I definitely have to at some points, but um, I try not to, yeah. And when I do, I just realize it's the habit, and you kind of have to let go. I mean, I know some people that like don't drink, like they're like \"they're going to get their water from their food, their fruits while they're traveling,\" pretty extreme.","offset":11853,"duration":20},{"text":"Andrew: Yeah, that's... yeah.","offset":11873,"duration":1},{"text":"Rhonda: But I think mental health is important, so I mean it's like is the stress of avoiding the microplastics worse than the actual little bit of microplastics you're being exposed to? It might be.","offset":11874,"duration":11},{"text":"Andrew: TSA is going to hate me, but I lost a bet two days ago to a member of our podcast team. He bet me, we bet, that um, I said one couldn't bring a Mountain Valley Spring Water bottle through security at the airport, and he said you absolutely can, and I said \"There's no way,\" so I made him a bet and I lost. He brought it through.","offset":11885,"duration":22},{"text":"Rhonda: Full of water?","offset":11907,"duration":1},{"text":"Andrew: Full of water. You tell them it's for medical reasons. You don't have to state what they are. They open the cap, they take a sample out, they test it. So there's a time constraint and it's going to create more jobs for TSA. Um sorry, that was sort of a joke, sort of not a joke, TSA's been, you know, in tricky circumstances lately. And he showed up at the at the gate with it and was like \"Here's your water.\" You absolutely can bring water through in glass vessels or whatever vessel, but they're going to test it and it helps if it's a commercial vessel, it's not like your own glass water bottle.","offset":11908,"duration":36},{"text":"Rhonda: Can I pause for a minute because you mentioned a specific brand which I also when I when I...","offset":11944,"duration":4},{"text":"Andrew: Oh yeah, and no I don't make money from them.","offset":11948,"duration":1},{"text":"Rhonda: Same, I I drink when I'm traveling that's that's the brand that I go to. And there are there was a study that came out showing that there's actually a larger um volume of microplastics within this study from glass bottles versus plastic bottles, which was a very shocking finding. Um, so there was more microplastic number coming from the the glass bottles. It turns out this was a study out of France, there was a study out of France and also in the US. It's the paint on the lids... you mentioned the lid and so it's the paint on the lid that's contaminated, getting contaminated in the bottling of the whole bottling of this, you know, water, that is getting into the water. But I do want to mention that the size was was shown to be larger from the glass bottles versus the plastic, so the microplastic size was larger. And as you probably know, larger microplastics are not well absorbed through the gut epithelial cells. So when you're, you know, taking them in in the gut, they're coming out they're being excreted through your your feces. And um, less likely to be taken up into your gut and then get into your body, and that's actually well known. And so I'm actually more concerned about the size of microplastics... um, and it wasn't like the huge orders of magnitude difference between the the water from glass versus the plastic. It's so counter-intuitive you think \"Wait, what? Why is it...?\" so it's the paint that's on the lid.","offset":11949,"duration":76},{"text":"Andrew: Interesting.","offset":12025,"duration":1},{"text":"Rhonda: Anyways, I just want to mention that I still drink when I'm traveling, I still go for the glass, not the plastic because of the size of the microplastics and knowing because the size was much bigger... um, that it's very I would say more data is going to come out on this but I would be surprised if you're absorbing more of the larger particles because it's known that you absorb the smaller ones.","offset":12026,"duration":19},{"text":"Andrew: Thank you for that. And if you want, you can now take your glass bottle through security full. Seed oils. The dreaded seed oil debate. Where do you land on this?","offset":12045,"duration":15},{"text":"Rhonda: I try to avoid them... um mostly because one, if you're avoiding seed oils you're going to avoid a lot of the processed packaged foods that they come in, which I know are terrible for you. Two, because I think that cooking them or heating them, I mean, is more of my concern because they are, you know, polyunsaturated fatty acids which are very prone to oxidation. And when you're heating something that's prone to oxidation, you're accelerating that whole process. I don't want to consume oxidized lipids. I've seen I've looked into that literature and the last time I looked into it was I think 2024. At that time I was pretty convinced that if you are heating and reheating, you know, oils like they do in fast food for sure you're increasing inflammatory markers, that's been shown. And I think also when you're really having a higher level of, you know, omega-6s and stuff around, I'm not as concerned because I'm getting a lot of omega-3, but it does also re- increase your Vitamin E requirements as well, because of the oxidation of these polyunsaturated fatty acids. So do I think it's like like the worst ever? I mean, you can find all this data out there showing that, you know, if you replace, you know, saturated fat with some of these seed oils there's improvements in lipid profiles. But at the end of the day, the question is really what if like you had olive oil instead or avocado oil instead? Would it be even better? I think possibly. So if you're really trying to go for the optimal, I avoid them as much as I can for that reason. But I think there's a little bit more hype when it comes to the seed oil. But if that makes sense, you know, I'm kind of that's my that's my take.","offset":12060,"duration":102},{"text":"Andrew: Makes sense to me, for what it's worth, I stick to olive oil and small amounts of butter and that's because I also think seed oils taste terrible. How come no one talks about that? But anyway. And olive oil and butter are delicious.","offset":12162,"duration":14},{"text":"Rhonda: It's been so long since I've actually like I mean had the you know seed oil but yeah.","offset":12176,"duration":5},{"text":"Andrew: Ugh, you know, and no one can convince me that they don't taste bad to me. So then the debate just kind of falls away. How often are you doing the sauna nowadays? And what does the top contour of that protocol look like?","offset":12181,"duration":13},{"text":"Rhonda: So I've taken a little pause on the sauna right now, but typically I'm doing... I was doing it like, I would say five nights a week. And I say nights because I usually doing them in the night. And it was mixed a mixture between either getting in the sauna or hot tub. So I like I like getting in the hot tub head out under the stars there with my husband, it's like our time. So yeah, usually it's like 20 minutes and temperature-wise, you know, I don't go that hot, I honestly I'm like 180.","offset":12194,"duration":30},{"text":"Andrew: Five nights a week is great! Gosh, I I need to get back on a five-night-a-week sauna or hot tub protocol.","offset":12224,"duration":7},{"text":"Rhonda: I know, I need to get... I do like the hot tub especially, I don't know, there's something about being outside and... I think now there's just there's evidence that the the benefits are really like the same. It's the deliberate heat exposure, right? You're getting the... you're getting that through the hot tub or through the sauna.","offset":12231,"duration":14},{"text":"Andrew: Creatine for kids. Like young kids, like younger than 16. Um any data and or ideas about this, good or bad?","offset":12245,"duration":9},{"text":"Rhonda: Yeah, so there is data in the literature showing that if you give younger younger children that are doing like for example sports like soccer, it does seem to improve their agility and it seems to be safe. I do give my son 2.5 grams of Creatine, so a day.","offset":12254,"duration":18},{"text":"Andrew: Cool.","offset":12272,"duration":1},{"text":"Rhonda: So that's how I feel.","offset":12273,"duration":1},{"text":"Andrew: There's no better um indication of how you... of how one feels than what they're willing to um deliberately give their kids. I don't know where this stems from, and we can cut it if you want, but this um someone asked why did you single-handedly ruin bananas for this person? Uh, do you- did you ruin bananas?","offset":12274,"duration":17},{"text":"Rhonda: So I used to put bananas in my smoothies and there's an en- there's an enzyme that is produced in bananas that break down polyphenols, particularly ones that are found in blueberries, and the reason I was getting my smoothies was one for the greens but two for the blueberries because the polyphenols have been shown to improve cognition. Love blueberries! So... um sorry, don't mix the blueberry with the banana smoothie, because it it has been shown to decrease the the polyphenols which are important.","offset":12291,"duration":26},{"text":"Andrew: Yeah. Yeah, well the alcohol industry will come for me someday and the banana industry will come for you and um, I think we're safe for a while. Should we ignore studies that have less than X number of subjects? I think that's a really good question. Like obviously it depends, but when we're talking about human studies, where's the the line for small study versus large meaningful study for you? Obviously how strongly it's powered, but how do you think about that?","offset":12317,"duration":29},{"text":"Rhonda: Well I'll tell you when I was first looking at the sauna literature, all the studies that I were looking at were like N of 10 or smaller. And it's really the aggregate of those studies and then looking at like animal data and then you start to, you know, you start to look at observational data and the totality of evidence, and you put together this picture. I don't think you should ignore studies that are small, I think that it's part of the story. I think we're getting a little too caught up in \"It's got to be the randomized placebo-controlled trial, it's got to have lots lots of participants,\" and I mean that's great if we have that data, but we don't always have that data. and I don't know that we will always have that data with everything that we're interested in in understanding, right? So the way I look at it is if it's like just one study with an N of 10, okay, interesting. Um, like with the Creatine, right? Like I mean these studies have been small sample sizes. Now there's more than one, but you know at the end of the day, it's still very I would say in this, you know, pilot study phase where you have just small studies. So I I do not ignore them, but I also don't hedge all my bets on them either. I do know that there are a lot of people that were criticizing me on my sauna, I mean back in I you know 2014, published an article on Tim Ferriss's blog, went on Joe Rogan's podcast and talked about, you know, the benefits of sauna, and and I had people that were going \"Your studies... your sample sizes are too small.\" And now we have so much data that's come out since then really kind of validating everything and showing even more benefits. You kind of have to look at the totality of evidence and what is you're what endpoints are you looking at and how can you gather, you know, data from different sources whether it's clinical studies, observational studies, or animal studies, and and try to come up with the bigger picture, right? But then also don't be too confident in your statements.","offset":12346,"duration":106}],"startTime":11761},{"title":"Conclusion & Final Thoughts","summary":"Huberman thanks Dr. Patrick for her rigor and generosity in sharing actionable health protocols, and provides sign-off information for the podcast.","entries":[{"text":"Andrew: I'm very gratified to know that pretty much every other question you addressed the answer to in route to where we are now in the podcast, truly. And um, I'll leave them up so you can see them later if if you choose. Cold plunges notwithstanding um, Vitamin D um, exercise in all its contour, specificity, fasting, um magnesium, lots of questions about supplements which we covered, Creatine, lots of questions about inflammation, longevity... and so I just have to say first of all on behalf of everybody thank you so much. This was really an incredible tutorial and so much of it is actionable. And as you are known for, it was incredibly thorough in terms of setting the context within mechanisms of what we know, what we still don't know. And um I also personally want to thank you, because when you speak I learn, and when you speak I also learn things that change my behavior. And that's a whole other level. Uh, since our last conversation I can think of at least four and probably as many as a dozen things that I do on a daily basis as a consequence of that conversation. And just the gut-inflammation health brain-body axis uh conversation that um we had earlier, I'm going to listen to this again and take notes, because um there's just so much there and the metabolic flexibility thing as an input that can come from multiple sources, just on and on. So thank you for doing what you do. Thank you for being you, for being first-in and still going and doing things with such rigor and and really so much grace. It's just awesome. People love you... um, I certainly do and appreciate you and and it's just um it's a wonderful thing for me to have a colleague like you and you really set the standard. So thank you so much for coming here and doing this marathon and um, can't wait to do it again.","offset":12452,"duration":109},{"text":"Rhonda: Thank you so much, Andrew. It's it's really been great. I learn so much from you as well, and appreciate everything.","offset":12561,"duration":5},{"text":"Andrew: Thank you. Thank you for joining me for today's discussion with Dr. Rhonda Patrick. To learn more about her work, please see the links in the show note captions. If you're learning from and or enjoying this podcast, please subscribe to our YouTube channel. That's a terrific zero-cost way to support us. In addition, please follow the podcast by clicking the \"Follow\" button on both Spotify and Apple. and on both Spotify and Apple, you can leave us up to a five-star review. And you can now leave us comments at both Spotify and Apple. Please also check out the sponsors mentioned at the beginning and throughout today's episode. That's the best way to support this podcast. If you have questions for me or comments about the podcast, or guests or topics that you'd like me to consider for the Huberman Lab Podcast, please put those in the comment section on YouTube. I do read all the comments. For those of you that haven't heard, I have a new book coming out. It's my very first book. It's entitled \"Protocols: An Operating Manual for the Human Body.\" This is a book that I've been working on for more than five years and that's been based on more than 30 years of research and experience. And it covers protocols for everything from sleep, to exercise, to stress control, protocols related to focus and motivation, and of course I provide the scientific substantiation for the protocols that are included. The book is now available by pre-sale at protocolsbook.com. There you can find links to various vendors, you can pick the one that you like best. Again, the book is called \"Protocols: An Operating Manual for the Human Body.\" And if you're not already following me on social media, I am Huberman Lab on all social media platforms, so that's Instagram, X, Threads, Facebook, and LinkedIn. And on all those platforms, I discuss science and science-related tools, some of which overlaps with the content of the Huberman Lab podcast, but much of which is distinct from the information on the Huberman Lab podcast. Again, it's Huberman Lab on all social media platforms. And if you haven't already subscribed to our Neural Network newsletter, the Neural Network newsletter is a zero-cost monthly newsletter that includes podcast summaries as well as what we call protocols in the form of one to three-page PDFs that cover everything from how to optimize your sleep, how to optimize dopamine, deliberate cold exposure... we have a foundational fitness protocol that covers cardiovascular training and resistance training... all of that is available completely zero-cost. You simply go to hubermanlab.com, go to the menu tab in the top right corner, scroll down to \"Newsletter,\" and enter your email. And I should emphasize that we do not share your email with anybody. Thank you once again for joining me for today's discussion with Dr. Rhonda Patrick. And last but certainly not least, thank you for your interest in science.","offset":12566,"duration":15}],"startTime":12452}],"entries":[{"text":"Dr. Rhonda Patrick: There's a lot of data now showing that people that are doing these, like short bursts, at least a minute long, but up to three minutes, they're moving faster with intent and it's having outsized effects on, on health outcomes. So for example, individuals that do on the high end, so they're doing, you know, three minutes of this short burst of an unstructured type of exercise snack, and they do it three times a day, so it's a total of nine minutes a day, okay? That's associated with a 40% reduction in all-cause mortality, 40% reduction in cancer-related mortality, and 50% reduction in cardiovascular-related mortality.","offset":0,"duration":36},{"text":"Host: Wow. Nine minutes a day. Welcome to the Huberman Lab Podcast, where we discuss science and science-based tools for everyday life.","offset":36,"duration":18},{"text":"Host: I'm Andrew Huberman, and I'm a professor of neurobiology and ophthalmology at Stanford School of Medicine. My guest today is Dr. Rhonda Patrick, a biomedical scientist and leading public health educator. For over a decade, Rhonda has been one of the most trusted voices in building science-based health protocols. Today we discuss what the latest and best research says we should all be doing to improve our health and vitality and avoid disease.","offset":54,"duration":27},{"text":"Host: Rhonda shares with us her exact exercise, nutrition, supplementation, and sauna protocols, and we get really detailed about the mechanisms and logic behind each one. We also discuss the things that science says you can do to significantly reduce your cancer and cardiovascular risk, including how to reduce visceral fat and arterial plaque.","offset":81,"duration":24},{"text":"Host: Today's discussion truly leaves no stone unturned. We discuss how eating can increase inflammation, believe it or not, ways to support your gut health, creatine, vitamin D, why broad vitamin and mineral and fiber support is crucial, as well as the different forms of magnesium and each of their unique effects.","offset":105,"duration":23},{"text":"Host: We also discuss omega-3s, and why prescription sources of omega-3s may be the cleanest and most cost-efficient way to obtain sufficient omega-3 intake. We also discuss the importance of prioritizing regular resistance training and HIIT workouts over protein. You still need protein, but emphasizing the exercise component is crucial.","offset":128,"duration":22},{"text":"Host: And we discuss fiber, micronutrients, and why short-term fasting can be beneficial. Dr. Rhonda Patrick is a true wealth of knowledge, and today, she generously provides us a masterclass on how you can design and adjust the exact health protocols to meet your specific needs.","offset":150,"duration":21},{"text":"Host: Before we begin, I'd like to emphasize that this podcast is separate from my teaching and research roles at Stanford. It is, however, part of my desire and effort to bring zero-cost to consumer information about science and science-related tools to the general public. In keeping with that theme, today's episode does include sponsors.","offset":171,"duration":22},{"text":"Host: And now for my discussion with Dr. Rhonda Patrick. Welcome back, Dr. Rhonda Patrick.","offset":193,"duration":6},{"text":"Dr. Rhonda Patrick: Excited to be here.","offset":199,"duration":1},{"text":"Host: It's been a while, I'm so excited, there's so much to go into. And I'll start off the same way I started last time, because it's even more true. Thank you for being first person into this public science health education business. I don't know if everyone's aware of it, but you were the first person in, which is why I didn't say first man in, because the first person in was and is a woman, and you've done a marvelous job of educating people on science, how to parse papers and data, health practices, and, you know, the rest of us are just trying to follow in your wake. So thank you very much, I just want to thank you for being first.","offset":200,"duration":42},{"text":"Dr. Rhonda Patrick: Oh man, thank you so much for that, and also thank you for doing what you do. I mean, you really do a great service for science communication, um, education, helping people love science and get healthier.","offset":242,"duration":12},{"text":"Host: Well, thank you. Well, you're the pioneer, it's not always easy being a pioneer, but we all benefit, so. Let's jump in at exercise, because, um, lately you've actually been posting your workouts, which is awesome, and you're clearly very fit. I learned before talking to you today that you were a competitive athlete, you were a long jumper or triple jumper?","offset":254,"duration":22},{"text":"Dr. Rhonda Patrick: I was a long jumper, but I would say my real competitive athleteness comes from my jump roping.","offset":276,"duration":6},{"text":"Host: Okay.","offset":282,"duration":1},{"text":"Dr. Rhonda Patrick: I was on a professional jump roping team.","offset":283,"duration":2},{"text":"Host: Professional?","offset":285,"duration":1},{"text":"Dr. Rhonda Patrick: Yes. Yeah, it was, it was we would compete, so my friend and I started the team when we were in second grade, and it was called the San Diego Sand Skippers. And it was part of the International Rope Skipping Organization, which was actually started by her uncle, but there's jump rope teams all around the world, and you know, now I think there's a new name, but like it got taken over by the universal jump rope team or something like that, I don't know exactly what it is, but so I was on a team and every year we would compete in Boulder, Colorado. There were competitions for all kinds of, you know, jumping rope, and um, I would perform and start jump rope teams around the school around different schools in San Diego. So I used to get out of school, um, you know, get out of school free card, and my partner and I would go and start workshops at other schools and help them start jump rope teams. And the idea was cardiovascular health, healthy heart, and yeah, so so that's really, I would say my, my real roots with being a competitive athlete.","offset":286,"duration":65},{"text":"Host: Awesome. I love skipping rope. Is it okay to say skipping rope or jumping rope?","offset":351,"duration":4},{"text":"Dr. Rhonda Patrick: Yeah, okay. Skipping rope, jumping rope.","offset":355,"duration":1},{"text":"Host: And actually, it's a great opportunity for me to ask you what your thoughts are about, um, exercise that isn't just linear, right? I know like real jump ropers can do crossovers and um, and these days I'm seeing a lot more about rope flow. I think it's David Weck and others online are, you know, stuff that's getting people out of the standard, you know, curls, bench press, um, lunges, you know, and getting movements that are more just for lack of a better term, across the body. Do you think there's something to that in terms of real physical benefits? I mean, I imagine there is.","offset":356,"duration":37},{"text":"Dr. Rhonda Patrick: Sure. I mean, I wouldn't be the expert to be able to give you a good answer on that, but I do think that jumping rope in general has unique benefits in addition to obviously it's a great cardiovascular exercise, you're getting the weight-bearing aspect as well for building bone density, and I think that earlier for me, you know, I was doing it as a young girl, so important, right? Because you're kind of banking that, that bone density early on, which is important because at some point, you know, menopause will hit and and estrogen goes down and and so you start to lose more bone. But um, yeah, I'm sure there's a lot of benefits to jumping rope beyond what I'm describing as cardiovascular benefits and bone benefits that someone else could answer.","offset":393,"duration":45},{"text":"Host: Well, I'm certainly going to get back to jumping rope now that we resurrected it in this conversation. And I have to say, um, bone density measurements aside, you have awesome posture. I notice people's posture.","offset":438,"duration":13},{"text":"Dr. Rhonda Patrick: Oh, really?","offset":451,"duration":1},{"text":"Host: Yeah, I didn't even mean to put you on the spot here, but yeah, when I walked in, I was like, if you've ever interacted with Rhonda in person, which I have, you have amazing posture. And these days, good posture is rare, so who knows, maybe the things are are related, I imagine they probably are, bone health and posture and so forth. In terms of the sorts of exercise that people are more familiar with, what's your routine look like? And what sorts of things in your routine are non-negotiables, and where's the place for experimentation and kind of what you're exploring now?","offset":452,"duration":39},{"text":"Dr. Rhonda Patrick: So for me, exercise is part of my personal hygiene, as you and I were discussing. It it really is a non-negotiable. I absolutely have to do exercise just like I have to brush my teeth, and um, you know, I kind of got that from Dr. Ben Levine, who is a, you know, probably one of the world-leading cardiovascular exercise physiologists. He's at UT Southwestern in Dallas. I just want to shout out his name because I've really learned a lot from him.","offset":491,"duration":27},{"text":"Dr. Rhonda Patrick: But the non-negotiables for me really are getting cardiovascular exercise and getting my my resistance training. So building muscle, maintaining muscle strength as well. So my routine for me, I work out probably about five to six hours a week, and those workouts, I largely am doing a combination of high-intensity interval training that's not necessarily like the Norwegian 4x4, where I'm going as hard as I can for one minute or four minutes and then recovering for three minutes and doing that four times. That's really, you know, the Norwegian 4x4 is a hard workout. It's really good for improving your cardiorespiratory fitness, which I think is one of the best markers for longevity. We can talk about that.","offset":518,"duration":51},{"text":"Dr. Rhonda Patrick: Um, I do a lot of, you know, it's a it's a mixture of doing, you know, rowing machine, getting on the assault bike, and then doing mixed in mixing it in with lifting weights, doing some deadlifts, you know, doing squats. Um, so it's really for me a non-negotiable to to do my my vigorous intensity exercise is what I would call it. So you're really kind of getting your heart rate up to, you know, 80% max heart rate at at points, not always, but especially during the intervals. I would say that's a non-negotiable for me.","offset":569,"duration":45},{"text":"Host: How many days a week are you doing that?","offset":614,"duration":2},{"text":"Dr. Rhonda Patrick: I do my my longer HIIT workouts, so I have four days a week where I'm doing at least an hour. So two of those two of those sessions are more of a CrossFit type of training, where I'll do the first 30 minutes will be strength training. So I'll just be lifting heavier with like, you know, fewer reps.","offset":616,"duration":19},{"text":"Host: What's the rest between sets? Sorry to get granular, but people will wonder.","offset":635,"duration":4},{"text":"Dr. Rhonda Patrick: Um, what's funny is I typically rest about two minutes between my sets. I I recover pretty quick. Um, and my I do it with a coach, and my coach usually tells me that I'm spot on. I'm like ready to go, and it's been about two minutes. So I usually that's my recovery time. And so the first 30 minutes of strength training, and that'll be like deadlifts, it'll be, you know, squats, I'll be cleaning, I'll be doing front squats, sometimes I do barbell or back squats, right? Like it's a mixture of different types of strength training. And then the last 30 minutes is more of a high-intensity interval training session. So it'll be like, you know, where I'm I'm getting my heart rate up, so I'm mixing in the rowing machine and then I have like maybe I'm doing cleans, but they're lighter, so it's like more reps, but lighter load, right?","offset":639,"duration":50},{"text":"Dr. Rhonda Patrick: So, um, that's I do that twice a week, and that each is an hour session. And then I do also twice a week, about an hour and 20 minutes of it's also more high-intensity, but I have more recovery time because I'm doing it with my girlfriends, and we kind of chit-chat a little bit, and so um, but it's very similar, we do, you know, rowing machine, assault bikes, we do the skier, you know, Rogue has that skier, and then we mix it in with, you know, chest presses, and we do, you know, assisted pull-ups, and we do, you know, lighter squats with like larger, you know, more reps.","offset":689,"duration":43},{"text":"Dr. Rhonda Patrick: So that's another, you know, two hours a week. So now I have four hours a week of just doing a lot of that sort of CrossFit, HIIT type of training. And then I mix that in with my more like runs that I do, which are I would say are still they're still considered vigorous intensity, they're just not quite as high-intensity. And I do probably I run like maybe six miles a week, so maybe maybe at my max, but these days I'm mostly running probably four like four miles a week. So um, those runs tend to be like sometimes they're two miles, sometimes they're three miles, and um, you know.","offset":732,"duration":59},{"text":"Host: Do you enjoy running?","offset":791,"duration":1},{"text":"Dr. Rhonda Patrick: I do. I do. And I think it's important as well, and sometimes I'll run with my husband and we just kind of like chill out and talk and um, you know, it's a nice time for me as well just to kind of do that with him. Um, and then on weekends I'll probably do like a hike with my family, and sometimes we'll do like a sprint up the hill and, you know, but it's more just enjoyable time in nature, um, still moving, but, you know, it's kind of family time too.","offset":792,"duration":34},{"text":"Host: Weight vests on the run or hike?","offset":826,"duration":2},{"text":"Dr. Rhonda Patrick: No, I don't, not I mean, I'm kind of wanting to experiment with that, but not really. I'm just kind of sometimes we bring our puppy and you know, so it's it's more about the experience I think than like I'm like I get a lot of workout throughout the week.","offset":828,"duration":14},{"text":"Host: Sure.","offset":842,"duration":0},{"text":"Dr. Rhonda Patrick: But it's like you said, it's non-negotiable for me, and and times when I'm like like today, so I you know, I had a long drive and so I got on my Peloton and I did a 10-minute, you know, I did a 10-minute Tabata back-to-back, so it was like two back-to-back Tabatas, right? So it was it ended up being 10 minutes, it was like 30-second recovery in between the two Tabata sessions, 2:1 ratio, 20 seconds on, 10 seconds off, but like I have to do something every day, and if I'm traveling or I have like an early podcast or something, I'll I'll just jump on the bike and I have to get that blood flow.","offset":842,"duration":38},{"text":"Dr. Rhonda Patrick: Sometimes I'm in my hotel room and I don't want to go to the gym, I don't have time, and I just in my room, you know, I do I do air squats, I'll do high knees, jumping jacks, and I repeat for 10 minutes and I'm getting my heart rate up and I'm, you know, I've got sweat on my brow, like I'm not it's not like the most intense workout, but it's so important for me, you know, it's there's there's a variety of brain benefits that have been shown with even just 10 minutes of this vigorous type of intensity of workout you do, you know, where you're I mean, you probably have seen this this data where it's like just 10 minutes of this vigorous type of exercise you're immediately increasing neuronal connections. Um, they there's been studies showing that you have an improvement in executive function by like 14%, which is pretty big.","offset":880,"duration":62},{"text":"Dr. Rhonda Patrick: I think it was like a 50 50-millisecond improvement processing speed or something, which doesn't sound a lot, but it actually translates to a big improvement in executive function. So my brain works better, I feel better, you know, better mood, um, there's even studies that have compared impulse control after various types of intensity of workout. So like there was one study that compared a more low-intensity versus moderate-intensity versus high-intensity. So you're talking about like walking versus maybe, you know, jogging slowly where you can still have a conversation versus like you're doing a HIIT workout, right? When you're on, when you're on, you're not really talking because you're going as hard as you can during that interval. And it was the high-intensity, you know, vigorous intensity exercise that really increased plasma serotonin, which has been shown to associate with brain serotonin, those studies have been done.","offset":942,"duration":69},{"text":"Dr. Rhonda Patrick: And serotonin is very important for as you know, for impulse control. I mean, a lot of people think about serotonin with respect to mood, because we have these selective serotonin reuptake inhibitors, SSRIs, that are used to treat, you know, depression, major depressive disorder. But serotonin, as you know, does so much more than that, and impulse control is one of the the the big things that serotonin plays a role in, and so those studies showed that plasma serotonin increased in the higher intensity group and that correlated with improved impulse control. So, of course, for us now in the modern day society that we live in, we're constantly being bombarded with, you know, social media and all these things and like you have to be able to kind of like filter that out and not like just go with the impulse of check my social media, check my, you know, and um, how many likes did I get or whatever, you need to just be able to focus and so that for me, you know, serotonin is important and so I like to get that vigorous intensity exercise as well.","offset":1011,"duration":68},{"text":"Host: I'd like to take a quick break and acknowledge our sponsor, Our Place. Surprisingly, toxic compounds such as PFASs or forever chemicals are still found in 80% of non-stick pans, as well as utensils, appliances, and countless other kitchen products. As I've discussed before on this podcast, these PFASs or forever chemicals, like Teflon, have been linked to major health issues such as hormone disruption, gut microbiome disruption, fertility issues, and many other health problems. So it's very important to avoid them.","offset":1079,"duration":33},{"text":"Host: This is why I'm a huge fan of Our Place. Our Place products are made with the highest quality materials and are all PFAS and toxin-free. I particularly love their Titanium Always Pan Pro. It's the first non-stick pan made with zero chemicals and zero coating. Instead, it uses pure titanium. That means it has no harmful forever chemicals and it does not degrade or lose its non-stick effect over time. It's also beautiful to look at. I cook my eggs in my Titanium Always Pan Pro almost every morning. The design allows for the eggs to cook perfectly without sticking to the pan.","offset":1112,"duration":35},{"text":"Host: Right now, Our Place is having their biggest sale of the season. You can save up to 40% sitewide now through April 12th. Just head to fromourplace.com/huberman. Again, that's fromourplace.com/huberman to save up to 40%.","offset":1147,"duration":18},{"text":"Host: Today's episode is also brought to us by Lingo. One of the most important factors in your short and long-term health is your body's ability to manage glucose over time. Glucose directly impacts our brain function, mood, and energy. You want your glucose relatively stable across the day, without big peaks or valleys. This is why I use the continuous glucose monitor and app from Lingo by Abbott. Lingo provides minute-by-minute glucose data directly within the app, showing you how your glucose responds to food, exercise, and stress. This information can help you make smarter choices to support your health both now and in the long term.","offset":1165,"duration":42},{"text":"Host: The CDC estimates that more than one in three American adults has pre-diabetes, and that many of these people don't know they are living with pre-diabetes. Visibility about how your diet and activity affect your glucose can be the first step toward informed conversations with your doctor and making smarter daily choices.","offset":1207,"duration":18},{"text":"Host: If you'd like to try Lingo, Lingo is offering Huberman Lab listeners in the US and UK 10% off a four-week plan. Just visit hellolingo.com/huberman for more information. Terms and conditions apply. Again, that's hellolingo.com/huberman.","offset":1225,"duration":19},{"text":"Host: I love that you mentioned other other functions of serotonin, because as you point out, it is so heavily associated with this mood aspect and certainly has a role there, but um, the impulse control piece is I think is a non-trivial aspect to um the effects of exercise and just generally. I'm curious, do you bring your phone or feel compelled to check your phone during workouts? Are you able to just say I'm compartmentalizing now, this is the workout, you might put on music or check maybe text here or there if you need to, but are you able to compartmentalize or um do you struggle with the the phone during workouts?","offset":1244,"duration":35},{"text":"Dr. Rhonda Patrick: Oh, I don't bring my phone to my workout at all. Like I don't No, I do have a watch that I wear that, you know, if there's like an emergency I'll get a text message, oftentimes I put it on silent like on no notifications because I don't want to be bothered. But I don't I don't really check my phone. Um I I don't really like checking things like social media for me, it's just a distraction and and frankly, I think it's terribly terrible for people's brains, even though like my business kind of depends on it somewhat, I think I think social media is not really good for people to be honest. Um, so I don't really check my phone or bring my phone to my workouts. My workouts are I like to chat with my friends when I'm working out with them and that's fun.","offset":1279,"duration":45},{"text":"Host: But in real life.","offset":1324,"duration":1},{"text":"Dr. Rhonda Patrick: Yeah, so that's IRL as the kids say.","offset":1325,"duration":3},{"text":"Host: Yeah.","offset":1328,"duration":1},{"text":"Dr. Rhonda Patrick: That's in real life, and um, yeah, phones phones for me are not something that I bring to my workout.","offset":1329,"duration":6},{"text":"Host: Great. Yeah, I've um been experimenting with not allowing the phone in my gym and just the workouts go so much better and I find that the mental and physical resetting aspect of working out just seems to be enhanced. But um, sounds like you were already there and I'm just arriving, so. I have a couple other specific questions about your workouts, because uh for my own interest and I know many people will wonder, for the dedicated weight workouts, are these whole body workouts? And you said low reps, um maybe you could just tell us what low reps is for you and then the um seems like the ever-present question is to failure, close to failure, I mean, um just to you know round out that that portion of the of the workout picture.","offset":1335,"duration":41},{"text":"Dr. Rhonda Patrick: The workouts that I'm doing with my strength training workouts with my coach, you know, it it really depends most of those workouts are they're multi-joint workouts, so I am most of the time doing, you know, some either front squat, back squat, or I'm cleaning it as well, right? Which obviously the leg the weight goes down if I'm doing if I'm cleaning it because it's hard to clean. It's also the hard like it's the thing that I hate doing the most.","offset":1376,"duration":29},{"text":"Host: Cleans.","offset":1405,"duration":0},{"text":"Dr. Rhonda Patrick: Oh yeah, cleans with front squat because it's really hard, and um for me. I mean, for others who've been doing it for years, I'm sure it's like, you know, they love it. But for me, it's very hard. I've only been doing cleans since, you know, February 2024. So I'm pretty new to it and and so it's mentally like I have to overcome that challenge, which by the way once I started doing all this sort of weight training, I've always been endurance junkie, like I like I used to like to go on long runs and, you know, races and stuff like that. So for me, that's like my safe spot, right? That's what comes easy to me. Uh weight training and resistance training, strength training definitely not something that I've done my whole life. I'm so glad that I started doing it, but very very challenging for me and so I would say the biggest effect was on my brain and the ability to handle stress better where it was like unbelievable because it was so hard and I I just didn't want to do these cleans, you know, and and these front squats, um, and then the rest of my day was not as hard. And that to me was like the biggest surprise for this type of training.","offset":1405,"duration":72},{"text":"Dr. Rhonda Patrick: But anyway, so um, I do a variety of if I'm doing if I'm going heavier, then it, you know, depends. Sometimes we'll start off as okay, we start off we do five reps and then we go down to four, and then we go down to three, and then we go down to one, right?","offset":1477,"duration":14},{"text":"Host: You're doing singles.","offset":1491,"duration":1},{"text":"Dr. Rhonda Patrick: We do.","offset":1492,"duration":1},{"text":"Host: Okay.","offset":1493,"duration":1},{"text":"Dr. Rhonda Patrick: I know yeah, yeah. And that's the hardest. It's the hardest. But then there's there's like my coach will be like it's just one, it's just one. You know, sometimes we'll do like six, five, and then we do four twice, and then we do three twice, right? And so it all depends, you know, also on the day. There's some days where I'm just like, you know, can we do lower reps and like lighter weight, right? Where I'm just like it's this is the day for me. I'm I'm stressed, I'm not I'm not here like so you kind of have to modify your workout, right? According to how you feel that day. Um, but I would say that those the majority of my strength training workouts are or deadlifting, you know, I love dead deadlifting. I think I'm pretty good at at pulling that weight up, lifting that weight up.","offset":1494,"duration":45},{"text":"Host: That's with the straight bar, hex bar? Mixed grip? There's so many variables, but yeah.","offset":1539,"duration":3},{"text":"Dr. Rhonda Patrick: Straight bar. Straight bar. And um it's the same deal with that. Like most of the time with strength training we'll do, you know, we start off at like five or six and then work our way down and then I I usually do a drop set after, you know, any of those sessions where I'll do 10 and then it's like a lot lighter, right? So those those are typically my strength training sessions are multi-joint. Sometimes I'll do accessory sessions, you know, where I'm working I do, you know, the dips um or the Bulgarian, you know, the Bulgarian split squats. I mean, just the accessory stuff that you're working the like smaller stabilization muscles and stuff like that.","offset":1542,"duration":40},{"text":"Host: I love that you call Bulgarian split squats accessory smaller muscles. For a lot of people, that's the compound work, which is just I have to say I I am inside I'm just like so delighted because, I mean, obviously uh weight training is something that's caught on broadly for men and women now, but I don't know many women, and I know they're out there, but I don't know many women who are uh working down into singles on multi-joint like real multi-joint, like, you know, deadlifts, cleans. I know they're out there, but it's not that common to see in gyms and uh this is going to no doubt spark a debate because, you know, some of the older, slightly ornery, but very credentialed strength training folks have been online recently saying that as people um pass 35, that they shouldn't do squats, that they shouldn't do deadlifts, and certainly shouldn't do them heavy because it because of this whole thing of, you know, you can do higher reps and take it to failure and still get hypertrophy. But what I love is that you're not necessarily talking about hypertrophy, maybe some hypertrophy, but this is about strength. This is about building more strength and triples and doubles and singles. That's awesome.","offset":1582,"duration":70},{"text":"Dr. Rhonda Patrick: It's hard. It's so hard. And it's the part that I'm like all about let's like the last 30 minutes where it's HIIT and and that's hard too, it's a different kind of hard. But for me, the strength training is the hardest and there's definitely a mental component, right? Where I do not want to do it. It's like you talk about with cold plunging, right? Like you do you just it's so unpleasant and you don't want to do it and like you do it and it's like that mental toughness that you're building, right? That's what I experience when I'm doing these, you know, strength training exercises that I'm doing. And and I don't know if it's going to get easier, maybe it will. It hasn't yet. I still I still dread it, but I do it and um I'm proud of myself for doing it, but it is it's definitely hard and I am getting stronger I think mentally and obviously physically as well. But um, have to add in the aerobic as well though. I think that's really important.","offset":1652,"duration":53},{"text":"Host: That's your base. Yeah.","offset":1705,"duration":1},{"text":"Dr. Rhonda Patrick: Yeah.","offset":1706,"duration":1},{"text":"Host: You love it.","offset":1707,"duration":1},{"text":"Dr. Rhonda Patrick: I love it and I do think cardiorespiratory fitness is very important, you know, for for long-term health as well as, you know, obviously building muscle and strength.","offset":1708,"duration":8},{"text":"Host: Well, on the one hand I want for you as a friend to for you to hate the heavy work less. On the other hand, I don't, because of this literature I'm sure you're familiar with it, but uh the anterior midcingulate cortex. This brain area that is hyperplastic throughout the lifespan, which is rare for a brain area, and it enlarges um when we do things we don't want to do. I mean, it's so clear, it's not just about doing hard things about it's about doing the hard thing you hate. And and for you that sounds like the heavy compound movements. For me, yeah, I don't like the cold plunge, which is why I do it. I don't think it's magic. I just think it's a it's a surefire stimulus that I hate to to get mentally stronger.","offset":1716,"duration":44},{"text":"Host: And I think um having something that you really despise that you know is good for you seems to keep this anterior midcingulate cortex volume either increasing or the same, and that's actually the thing in these so-called superagers that is the strongest anatomical correlate that we have. So on the one hand I hope it gets easier, on the other hand for your sake I hope it doesn't get uh easier because it's still it's going to be so much more beneficial.","offset":1760,"duration":21},{"text":"Dr. Rhonda Patrick: Well, I have a coach who can tell when it's getting easier and she will definitely up the weight. I I mean, it keeps I mean, it keeps going up. And so it doesn't it gets easier in a sense, but it doesn't, right? So I mean, I think that's that's the whole point is you're building strength and you keep making it heavier and it becomes harder again because now it's heavier.","offset":1781,"duration":23},{"text":"Host: Awesome.","offset":1804,"duration":1},{"text":"Dr. Rhonda Patrick: But um and I haven't gotten injured, so that's also, you know, knock on wood.","offset":1805,"duration":4},{"text":"Host: Yeah, no, knock on wood. I um thank you for rounding out that picture. It's super inspiring for men and women, you know. So.","offset":1809,"duration":7},{"text":"Dr. Rhonda Patrick: It's not easy to post on social media because obviously I'm a newbie. So I have all sorts of, you know, things that I could ways I could improve, but I'm posting it, you know.","offset":1816,"duration":10},{"text":"Host: Well, and the fact that you're working down into triples, doubles, and singles, I think is something that I'm trying to do more of and I think um this notion that you can get hypertrophy with higher reps if you take it to failure, sure I totally agree, read the studies, totally agree with the data, but not everything is about hypertrophy. I think that's what people forget. It's not all about growing muscle. Um, and VO2 max, which is great, but it's it's not all about um the top contour, and I what I love about the way you approach everything is you're you go through multiple layers of the of the health strata as it were.","offset":1826,"duration":34},{"text":"Host: This is probably a good opportunity to talk about protein, because I have a very specific question about protein. We all hear one gram of quality protein per pound of body weight or lean body weight, that's sort of what we're kind of what's thrown at us. By doing the heavier weight training, do you notice that your protein appetite has increased? Like appetite specifically for protein foods?","offset":1860,"duration":18},{"text":"Dr. Rhonda Patrick: I don't know that I have, you know, I interestingly have been doing a little bit more intermittent fasting in which, you know, people think about intermittent fasting, they think about it as just one thing, one intervention. I think it's two. There's a behavioral aspect to it where it's a tool to sort of lower the amount of calories you're taking in. The other one would be this metabolic switch. But so I've actually since I don't know, September maybe, last September of 2025, been been doing more intermittent fasting, and what I mean by that is just really just eating less. And um the reason for that is because I noticed that everything that I was doing, which was, you know, I'm I eat healthy, I exercise a lot, and yet I was sort of gaining more fat in the the belly section, right? The visceral fat.","offset":1878,"duration":55},{"text":"Dr. Rhonda Patrick: And the only thing that really helped me stop that, but the put the brakes on, was getting more in a caloric deficit. Um, so maybe my drive to do that kind of is skewing whether or not my appetite for protein would go up. But I personally am on the scale of 1.2 to 1.6 grams per kilogram body weight, which is","offset":1933,"duration":23},{"text":"Host: Per kilogram.","offset":1956,"duration":1},{"text":"Dr. Rhonda Patrick: Per kilogram, which is probably a little bit less than the pound.","offset":1957,"duration":4},{"text":"Host: You know, it's it's a kind of a throwaway statement a gram of quality protein um as defined as something with, you know, lots of the essential amino acids and uh so forth per pound or per lean pound of body mass. Um, which is something I think I and many other people shoot for, but I'm curious how religious you are about the, you know, getting a certain protein amount or per meal.","offset":1961,"duration":23},{"text":"Dr. Rhonda Patrick: Basically, it wasn't working for me in terms of like I was really trying to get aim for like the higher end of the for me, you know, 1.6 grams per kilogram body weight or even a little bit above that. And what I found what was happening is that I was actually gaining gaining more weight because I think I was consuming more calories at the same time besides if you're getting it from whole foods, right? Like that's just kind of naturally going to happen.","offset":1984,"duration":24},{"text":"Dr. Rhonda Patrick: Uh and so I had to slide down um. But I'm still like I said, I'm still getting within that range of like probably on average maybe 1.3, 1.4 grams per kilogram body weight. And it's really it's really worked well for me, but like people are different and you have different goals, right? You know, like I'm gaining muscle mass and I feel like all my training is like the most important thing, and I think that we need generally speaking, I think people should become more obsessed with training and less obsessed with protein. Like the protein will complement the training and as you mentioned, if you're training perhaps your appetite for protein will increase and so you'll start to eat, you know, more protein and less refined carbohydrates. I already wasn't eating a lot of refined ultra-processed foods in the first place.","offset":2008,"duration":45},{"text":"Dr. Rhonda Patrick: Probably not the answer you were expecting, but it's really um for me like I just focusing on getting more protein was was not working for my body um in terms of but then again I'm 47 years old.","offset":2053,"duration":12},{"text":"Host: Sure.","offset":2065,"duration":1},{"text":"Dr. Rhonda Patrick: You know, that perimenopause phase, very different than someone who's 37 maybe.","offset":2066,"duration":5},{"text":"Host: I don't know the answer to that. I I do know that I hear from more and more people these days that they are having a hard time getting that one gram of protein per pound of body weight. It feels like a lot to them, is what they're saying. They feel like they're kind of forcing themselves to do it.","offset":2071,"duration":13},{"text":"Dr. Rhonda Patrick: You shouldn't feel that way.","offset":2084,"duration":1},{"text":"Host: Exactly. So I'm actually really pleased with your answer, not because I have an agenda here, but because I and many other people seem to feel like unless there's a lot of resistance training or tremendous demands, like hiking, you know, while backpacking where you burn tons of calories, you're basically rucking like nine hours a day, right? Then um they have a hard time getting that much protein down. Um and I think that's also the case if people are eating starches, like I eat rice and oatmeal and some breads and things like that, not a lot of bread, but you know, it sounds like you eat starches.","offset":2085,"duration":34},{"text":"Dr. Rhonda Patrick: I do eat oatmeal too, it it does satiate you. These days, because I really kind of more focused a little bit on I did want to to calorically restrict somewhat without, you know, being unhealthy. Obviously you can take every stressor to a bad, unhealthy place, right? You don't want to starve yourself, you don't want to like not eat enough food. But um my my meals are mostly like healthy protein, so I have homemade turkey burgers, eat a lot of I eat a lot of those. And then I eat chicken, you know, I pasture-raised chicken, I do I do still eat wild Alaskan salmon and then I'll um also mix in some like filet mignon, like I like grass-fed steak as well. Yum.","offset":2119,"duration":39},{"text":"Dr. Rhonda Patrick: Those are my protein sources, and always I pair it with greens. So or like some sort of vegetable, most of the times it's greens because they're the most most micronutrient dense. And so these days I'm eating a lot of sautéed collard greens that are pre-prepared, has garlic and onion, and I'll put that, you know, I have that with my meal or I'll have some, you know, sautéed kale, sometimes I'll have a salad with it. But the portions are smaller, and like I said I also do a little bit of intermittent fasting, we can talk about that as well, but that's kind of these days what I'm doing for my meals.","offset":2158,"duration":33},{"text":"Dr. Rhonda Patrick: I haven't eaten as much. Sometimes I'll eat the high protein oats. They have those high protein oats that have have you seen those? They're pretty good.","offset":2191,"duration":8},{"text":"Host: No, I eat oatmeal, but I like protein foods, I like vegetables, I like fruit. I feel very lucky to like those foods mainly.","offset":2199,"duration":6},{"text":"Dr. Rhonda Patrick: Yeah.","offset":2205,"duration":1},{"text":"Host: And then the starch for me has to be very clean. I like oatmeal, rice, homemade pastas I'll eat, like if I go out I'll have sometimes I'll have some homemade pasta or or a sourdough bread or something, but I find that most starches that are out there in the world have a bunch of other junk in them, and I just feel lousy. I get kind of sleepy afterwards, it just so I it sounds like we eat pretty similarly, although I probably eat more starches than you do.","offset":2206,"duration":24},{"text":"Dr. Rhonda Patrick: It's the more processed types of carbohydrates that as you mentioned, it's like you typically you don't feel good after you eat them, and, you know, part of that's the post-prandial inflammatory response because some of those foods are a little more inflammatory. I mean, they have a lot of additives and stuff that are affecting the gut, gut permeabilization, you're leaking lipopolysaccharide into the bloodstream, right? That's activating the immune system.","offset":2230,"duration":21},{"text":"Host: Yikes. We used to inject I don't do any animal experiments anymore, and I'm actually grateful to not do them. So I didn't like working on animals, but it was what we did until I decided to work on humans. But we used to inject LPS um to stimulate an inflammatory response to kind of prime a regeneration response that you could get through macrophages and things like that. And so LPS is a very potent way to generate local or even systemic inflammation. I think um hearing that some starches will stimulate LPS, that's uh interesting.","offset":2251,"duration":28},{"text":"Dr. Rhonda Patrick: Well, let me clarify.","offset":2279,"duration":1},{"text":"Host: It squares with my experience. I'm not challenging, no no no, I'm not challenging, it squares with my experience. I'm one of these I never get stomach aches, I never get headaches. If I do, something's badly wrong with my stomach or my head. But if I eat certain starches, I'll be like, oh, like I feel lousy, and I'm wondering if it's this.","offset":2280,"duration":16},{"text":"Dr. Rhonda Patrick: So we have about a gram of LPS in our gut, like that's on average because, you know, lipopolysaccharide is the outer component of a cell membrane of a gram-negative bacteria, right? And we have a lot of bacteria in our gut, gram-negative bacteria, right? Trillions of bacteria in our gut. So um when when we eat food, typically like our gut epithelial cells, they have a tight junction that's holding them together. When we eat food, they transiently open and then close. Like it's kind of a normal response, right?","offset":2296,"duration":27},{"text":"Dr. Rhonda Patrick: Um the the I would say the opposite end of the spectrum of that would be like celiac, where they eat gluten or something, it opens up and stays open and so you get like a ton of LPS leakage into the system which causes massive inflammation. It just happens with meals in general, you do get somewhat of a LPS response from a meal.","offset":2323,"duration":20},{"text":"Dr. Rhonda Patrick: Now the type of meal does matter. So what I when I say refined carbohydrates, it's not necessarily like healthy, you know, carbohydrates like vegetables. It's like you're eating something that is refined sugar, typically with saturated fat. So those types of foods really cause like LPS response, you know, it's it's inflammation, it's bad, it's hard on the gut. But the post-prandial inflammatory response essentially is that LPS getting into the system, activating the immune system, which draws the energy. I mean, it's like it's very energy consuming to activate your immune system, right? Which why that's why when you're sick, you're so sleepy too, right?","offset":2343,"duration":36},{"text":"Dr. Rhonda Patrick: Well, there's also cytokines that are somnogenic and promoting sleep, but like activating your immune system requires a ton of energy. And so when you're constantly activating the immune system, you know, that's an energy sink, right? And so you do feel tired and that's why a lot of times after a meal, you're feeling kind of lethargic.","offset":2379,"duration":21},{"text":"Host: So protein foods, uh of the sort that you listed off before, um do they cause less uh opening of the tight junctions of the gut?","offset":2400,"duration":7},{"text":"Dr. Rhonda Patrick: I think the the the big deal with it the opening of the tight junctions in the gut is, you know, I mean eating eating a big meal will do it, eating a very like ultra-processed food meal will do it. Interestingly enough, just eating a bunch of saturated fat without a fiber matrix, so like like butter, you're just like eating butter. Don't ever do that, but like if you just eat butter,","offset":2407,"duration":17},{"text":"Host: My niece when she was little, now she's all grown up, but when she was little, I uh I taught her how to eat like a little bit of Kerrygold butter and she loved it. So then we would do this thing where we'd we'd we'd do that. Um, we won't do that anymore.","offset":2424,"duration":13},{"text":"Dr. Rhonda Patrick: I mean, a little bit's fine, but like I mean, there's there's studies showing that it does, like saturated fat is hard on the gut. Like I said, it's a sliding scale. Like meals in general do it, but it's like you it's like you would think. The healthier foods that you're eating, like whole foods, you're getting less of that LPS response. And then of course there's gluten and that complicates the whole story, especially for people that are celiac, right? Because that","offset":2437,"duration":27},{"text":"Host: Which is a small percentage of people are actually celiac, right? But a lot of people seem to believe, and I believe them, that when they eat gluten they feel worse than when they don't eat gluten.","offset":2464,"duration":9},{"text":"Dr. Rhonda Patrick: I'm sure there's some people that are sensitive to gluten that do feel worse. And then I'm sure some of that's the nocebo effect, right? That's been shown with gluten in in particular. Did you have you seen that study? Where people there's been so so there were people that think they're, you know, gluten gluten sensitive and so they were enrolled in this study and um these individuals were separated into two groups. One group was given the gluten bread with gluten and the other group was given the bread without gluten. And the people that were given the bread without gluten had a terrible, you know, abdominal response, like they were bloated, they felt terrible. I mean, it was all and there was no gluten in the actual bread, but they thought there was.","offset":2473,"duration":38},{"text":"Dr. Rhonda Patrick: So it was thought that this is a nocebo effect where it's like the opposite of a placebo effect where you just you you've got that phenotype where you think things negative are going to happen and you can make them happen. You can change your immune system, you can change your brain signaling and, you know. So probably a combination of both with that regard. Um in addition to like the lethargy, so we're talking about I was talking about in the context, that's why it sparked my, you know, interest as like you were talking about feeling tired after a meal, and I do think that is part of that reason for feeling sleepy.","offset":2511,"duration":34},{"text":"Dr. Rhonda Patrick: But you know, what's interesting about LPS, you talked about injecting it to mice and I have also done experiments injecting LPS into mice. There have been studies where people have been injected with an amount of LPS that is, you know, similar to what you would find your gut releasing into your bloodstream or a placebo control which in this case was saline. And individuals that were injected with the LPS high amounts of inflammatory markers like TNF-alpha. I mean, we're talking like up to 50% increase over baseline, right?","offset":2545,"duration":33},{"text":"Dr. Rhonda Patrick: So high amounts of inflammation, which makes sense. LPS is activating the immune system, your immune system is like there's a foreign invader, right? It's not a foreign invader, it's just the food you ate that caused transient gut permeability. And those individuals also feel depressive symptoms and feelings of like social withdrawal. So the inflammation is affecting the brain, right? These inflammatory factors are getting in the brain, crossing the blood-brain barrier and affecting the way we feel.","offset":2578,"duration":25},{"text":"Dr. Rhonda Patrick: We know now that inflammation plays a big role in major depressive disorder and depression, not in all cases, but there's a subset, right? Where it's really like it does it seems to play a big role. In fact, interestingly there's been some studies showing that people that are that don't respond to SSRIs are have very high amounts of C-reactive protein. So this is the biomarker for a classical biomarker for inflammation, I would argue it's not that sensitive, but nonetheless it is a biomarker for inflammation.","offset":2603,"duration":24},{"text":"Dr. Rhonda Patrick: And so people that um don't respond to SSRIs have high amounts of inflammation which kind of raises this question of is there like this subset of depression that's really inflammatory driven, right? Um interesting. So so the LPS is affecting not only our our energy levels but also our mood. And then, you know, there's there's also evidence that so we know that LPS binds to LDL particles through lipid-lipid interactions. And in fact it's kind of part of the adaptive response.","offset":2627,"duration":29},{"text":"Dr. Rhonda Patrick: It's why you don't want to ever go get your cholesterol measured like after right after you're sick or had a very stressful event, something that causes inflammation because you will increase VLDL production increases and LDL production increases and it's sort of an an adaptive response to bind that LPS to prevent it from, you know, causing more damage. And so it actually binds to LDL particles on the ApoB protein. So ApoB is a protein that is on these lipoproteins and it's a a very important protein because that is what's used by the LDL receptors present on our liver to recycle LDL particles.","offset":2656,"duration":38},{"text":"Dr. Rhonda Patrick: And so what happens is these these LPS particles are now bound to, you know, our our lipoproteins and our lipoproteins are still doing their function, right? They're going around and they're they're donating triglycerides and and fatty acids and to some degree cholesterol to our cells that need it, right? We're constantly making new cells and repairing and we our cells need that. As they donate triglycerides and fatty acids, they get smaller in size, the lipoprotein. You probably heard of small dense LDL, right? Like that's a very dangerous type of LDL particle. And that's one that's kind of been donating along getting rid of triglycerides and um whatever. If you think about a train with cargo, it's donating the, you know, dropping off the cargo.","offset":2694,"duration":40},{"text":"Dr. Rhonda Patrick: And so um when it's time to get recycled back into the liver, what do you know, the ApoB proteins obscured by that LPS and it's not recycled. And so it gets lodged into the arterial wall and because there's an LPS bound to this, you know, small dense LDL particle, macrophages, which are as you mentioned, it's like the first line of defense against something like a bacterial invader, right? Come and chew it up, right? Gets rid of the problem. So macrophages come in because they're seeing this signal of LPS and think it's a foreign invader when it's actually just a small dense LDL particle bound to LPS that came from the gut. Tries to engulf it, but it can't because it's not bacteria, and you get the macrophage stuck to that lipoprotein LPS, you know, complex and you get the formation of a foam cell. You've probably heard of a foam cell. It's the beginning of atherosclerosis.","offset":2734,"duration":57},{"text":"Dr. Rhonda Patrick: And so this is where gut health and the food we eat is sort of it's linked to cardiovascular health, right? Gut permeability getting that LPS into our circulation's actually not a very good thing because you're you're basically, you know, slow dripping in that inflammation that inflammatory signal and it's wreaking havoc in our arteries, on our brain.","offset":2791,"duration":22},{"text":"Host: As many of you know, I've been taking AG1 for nearly 15 years now. I discovered it way back in 2012, long before I ever had a podcast, and I've been taking it every day since. The reason I started taking it, and the reason I still take it, is because AG1 is to my knowledge the highest quality and most comprehensive of the foundational nutritional supplements on the market. It combines vitamins, minerals, prebiotics, probiotics, and adaptogens into a single scoop that's easy to drink and it tastes great.","offset":2813,"duration":31},{"text":"Host: It's designed to support things like gut health, immune health, and overall energy. And it does so by helping to fill any gaps you might have in your daily nutrition. Now, of course everyone should strive to eat nutritious whole foods. I certainly do that every day. But I'm often asked if you could take just one supplement, what would that supplement be? And my answer is always AG1 because it has just been oh so critical to supporting all aspects of my physical health, mental health, and performance. I know this from my own experience with AG1, and I continually hear this from other people who use AG1 daily.","offset":2844,"duration":34},{"text":"Host: If you would like to try AG1, you can go to drinkag1.com/huberman to get a special offer. For a limited time, AG1 is giving away six free travel packs of AG1 and a bottle of vitamin D3K2 with your subscription. Again, that's drinkag1 with the numeral one.com/huberman to get six free travel packs and a bottle of vitamin D3K2 with your subscription.","offset":2878,"duration":25},{"text":"Host: Thank you for explaining that so clearly, because I don't think anyone has ever explained how exactly gut health is signaling cardiovascular health or pushing or pulling down on or raising cardiovascular health. As a neuro guy, I think about the vagus nerve as the primary conduit between gut and brain and it I was recalling that LPS injected into the gut is how you actually experimentally induce a fever, because the and if you cut the vagus, no fever. So there's there seems to be something about the way that the gut communicates with with the brain and other organs that is critically dependent on the some threshold level of of of LPS. Um, thank you also for reminding us","offset":2903,"duration":35},{"text":"Dr. Rhonda Patrick: I have a coach who can tell when it's getting easier and she will definitely up the weight. I I mean, it keeps I mean, it keeps going up. And so it doesn't it gets easier in a sense, but it doesn't, right? So I mean, I think that's that's the whole point is you're building strength and you keep making it heavier and it becomes harder again because now it's heavier.","offset":2938,"duration":19},{"text":"Host: Awesome.","offset":2957,"duration":1},{"text":"Dr. Rhonda Patrick: But um and I haven't gotten injured, so that's also, you know, knock on wood.","offset":2958,"duration":3},{"text":"Host: Yeah, no, knock on wood. I um thank you for rounding out that picture. It's super inspiring for men and women, you know. So.","offset":2961,"duration":6},{"text":"Dr. Rhonda Patrick: It's not easy to post on social media because obviously I'm a newbie. So I have all sorts of, you know, things that I could ways I could improve, but I'm posting it, you know.","offset":2967,"duration":10},{"text":"Host: Well, and the fact that you're working down into triples, doubles, and singles, I think is something that I'm trying to do more of and I think um this notion that you can get hypertrophy with higher reps if you take it to failure, sure I totally agree, read the studies, totally agree with the data, but not everything is about hypertrophy. I think that's what people forget. It's not all about growing muscle. Um, and VO2 max, which is great, but it's it's not all about um the top contour, and I what I love about the way you approach everything is you're you go through multiple layers of the of the health strata as it were.","offset":2977,"duration":9},{"text":"Dr. Rhonda Patrick: So that was kind of always in the back of my mind. And then in my postdoc I did my postdoc with Dr. Bruce Ames and my colleague Dr. Mark Shigenaga was doing a lot of gut work and this is why I know a lot about the LPS and the gut like it's from him. Like brilliant guy he's now a photographer, like not in science at all, but brilliant guy and did a lot of really amazing experiments looking at, you know, gut permeability and things that can help buffer, you know, gut permeability.","offset":2986,"duration":29},{"text":"Dr. Rhonda Patrick: And one of those things were glutamine. So glutamine can get converted into these intermediates that are used by mitochondria in the gut epithelial cells and so it's like an easy source of energy as well for the gut. Now these are all animal studies, right? So take it with a grain of salt, right?","offset":3015,"duration":18},{"text":"Dr. Rhonda Patrick: Like cause at some point, you know, in my in my opinion animal studies are are really important for understanding the mechanism behind why things work and we need human studies, you know, as well looking at the totality of evidence is important. It's the human studies that we're lacking, there's not a ton of them there. The ones that I have found more compelling...","offset":3033,"duration":19},{"text":"Dr. Rhonda Patrick: ...not necessarily I mean with the gut health it's it's you know it's sparse with humans. Um I found more compelling with respect to glutamine and human studies was the immune system and this is where I started putting connecting the dots, right? Where I started coming across this literature of these endurance athletes who do get a higher amount of respiratory tract infections, you know.","offset":3052,"duration":22},{"text":"Dr. Rhonda Patrick: Like when I mean endurance athletes I mean these guys that are like out running marathons all year, like they're just constantly training for a marathon, right? And so they're really like they're putting a lot of demand, right? Energetic expenditure is happening at a really high rate. So um they're they're more prone to respiratory infections.","offset":3074,"duration":18},{"text":"Dr. Rhonda Patrick: And there's a few studies out there showing that if these athletes take a higher dose of glutamine, I think it's like 30 grams or something high like that, that they had a lower incidence of respiratory tract infections versus the ones that weren't doing it. And then I went back to my, \"oh I know that glutamine's really important for T-cell activation\" and I was like \"I'm going to take this because being being a mom and having a child that's bringing everything home like a vector, you know.\"","offset":3092,"duration":21},{"text":"Dr. Rhonda Patrick: You're like desperate.","offset":3113,"duration":1},{"text":"Host: You're the experiment.","offset":3114,"duration":0},{"text":"Dr. Rhonda Patrick: Yeah, exactly and I never used to get sick, ever! Like I would never get sick and then all of a sudden I was getting sick like three times a year and I was like \"Do I have cancer? Like what's going on?\" Like I literally was like worried. Um and and then I started taking glutamine. Now I take it just I only take 5 grams on a daily basis, but if if my son's sick, if there's any exposure, if it's like during the season, if I'm traveling, I go up to 15, I go up to 20.","offset":3114,"duration":25},{"text":"Host: All at once? Because it can be a little hard on the gut.","offset":3139,"duration":1},{"text":"Dr. Rhonda Patrick: No, no, not all at once. Not all at once, I usually do it like in fives. So I do 5 grams, 5 grams, 5 grams and you know I have to with the caveat of I do that, but I also take a lot of creatine as well and so I don't know which one or both, but like I really don't get sick. I'm not getting sick and even even if it's brought home in my house, I'm not getting sick and maybe it's a placebo and you know what I am A-okay with that because placebo effect is real, as long as I'm not getting sick.","offset":3140,"duration":28},{"text":"Dr. Rhonda Patrick: Um so I do think I think with the glutamine, you know, it's not something that I would feel comfortable saying that it's there's a lot of evidence, it's overwhelming and with confidence that it's improving gut health and it's improving immune, you know, it's going to help give your immune cells energy particularly if they need to be activated, you know, upon exposure to any pathogen. But I feel like it's worth experimenting with.","offset":3168,"duration":19},{"text":"Dr. Rhonda Patrick: Um perhaps maybe if someone has colon cancer that would be more of a concern because I did mention that cancer cells cancer cells love everything. Anything that's good for you, right? Folate I mean if you don't have enough folate you can cause double-stranded breaks to your DNA which lead to mutations that lead to cancer. But if you have cancer and you take a bunch of folate, you need folate to make new DNA and so they like the folate, right? So it's like...","offset":3187,"duration":22},{"text":"Host: It's an abnormal growth, so anything that's associated with... mTOR, I saw the recent study on taurine, which scared a lot of people because taurine's in a lot of energy drinks but that was an in vitro study. Uh, yes, I was going to ask, you know, um is there increased cancer risk if you're supplementing with glutamine because cancer cells love glutamine.","offset":3209,"duration":19},{"text":"Dr. Rhonda Patrick: Okay, so my personal opinion, I'm obviously not a medical physician, this is not a prescription, it's just my opinion, I I personally am not scared of getting cancer from taking glutamine. If I had a colon tumor in a tumor in my colon, the first site that the glutamine is seeing, maybe the liver as well since that's also the next step.","offset":3228,"duration":20},{"text":"Dr. Rhonda Patrick: But um barring like having a tumor already in my liver or in my colon, those would be the only you know types of situations that I would be worried about taking glutamine. I don't think it's going to cause cancer, right? Now I guess the question is like, \"what if you don't know you have one?\" Well hopefully the cost will come down on whole body MRIs. Actually the cost is coming down on whole body MRIs that hopefully more people are able to get those.","offset":3248,"duration":24},{"text":"Dr. Rhonda Patrick: It's not just such a high-end exclusive thing in the near future. Kind of like blood draws used to be like like panels of blood testing you only got them if you really needed them, now the cost of blood draws is reasonably low. So hopefully people will be more aware.","offset":3272,"duration":13},{"text":"Host: Yeah I will take a tablespoon of glutamine once or twice or three times a day if I'm feeling run down. You mentioned being exposed to pathogens from vectors of different sorts. Before we went on mic we were talking about NAC, n-acetyl cysteine. Um I take it once a day consistently, but I'll take it three times a day if I'm traveling a lot because I'm around sick people when I travel, especially in winter.","offset":3285,"duration":24},{"text":"Host: Or if I feel like I'm getting run down and there the data are pretty interesting, there's at least one study showing that it reduced flu transmission um where people were deliberately exposed to flu. I think it took the number of people that contracted flu compared to the placebo group somewhere from the high 70 percent area, um I don't remember the exact number now, we'll put a link to the study, down to maybe high 20s.","offset":3309,"duration":20},{"text":"Host: Which is pretty impressive. And an ER doc came on this podcast, Roger Seheult, who um and said he was a big proponent of of n-acetyl cysteine for people that are around sick people. Do you take NAC?","offset":3329,"duration":13},{"text":"Dr. Rhonda Patrick: So my only concern with taking it on a daily basis is it is a pretty powerful antioxidant and, you know, I think that we need to understand like antioxidants and the opposite which would be generating oxidation, right?","offset":3342,"duration":21},{"text":"Dr. Rhonda Patrick: Like it's not it's not like oxidation is bad, it's bad when it's constant slow drip oxidation that's damaging, you know, other parts of our body, DNA, proteins, lipids. Some oxidation you want like if you're exercising, right? There's a burst of oxidation.","offset":3363,"duration":12},{"text":"Host: To get the adaptation.","offset":3375,"duration":1},{"text":"Dr. Rhonda Patrick: To get the adaptations. And so my concern would be for one maybe timing it around your exercise so not taking it close to when you're exercising. And these studies come out of, you know, studies that have been done with high dose vitamin E plus vitamin C. I haven't seen a lot of vitamin C studies alone that are blunting exercise adaptations. There's maybe one at a high dose.","offset":3376,"duration":23},{"text":"Dr. Rhonda Patrick: Most of the time it's vitamin C and vitamin E. Vitamin E alpha-tocopherol, when I say high dose usually it's 400 IUs, just to give you a reference point the RDA is like 24 IUs, so we're talking high dose.","offset":3399,"duration":13},{"text":"Host: But a supplement can be 200 to 800, so it wouldn't be hard to blunt that exercise effect by accidentally. Yeah, I don't take vitamin E, it spiked my prostate specific antigen, which I was told is a is a known effect among urologists.","offset":3412,"duration":13},{"text":"Dr. Rhonda Patrick: The SELECT trial was done, so the SELECT trial was um was looking at selenium and vitamin E and if it could slow the progression of prostate cancer and it turned out that um the opposite was found and it was really kind of due to this high dose of alpha-tocopherol which also has other effects of um lowering another type of vitamin E in the body called gamma-tocopherol which is anti-inflammatory and I think that has something to do with inflammation actually can increase the the PSA, right?","offset":3425,"duration":28},{"text":"Dr. Rhonda Patrick: So anyways um the point here is that with NAC my only concern would be you know blunting the the oxidation that you're getting from beneficial because I know you're highly active.","offset":3453,"duration":11},{"text":"Host: I'm training hard, I don't want my train to be short-circuited from NAC. I'm perfectly happy to only take NAC if I'm feeling run down or exposed to um illnesses around me.","offset":3464,"duration":10},{"text":"Dr. Rhonda Patrick: So that's one that's one I take it, but it's mostly because of I wasn't familiar with the flu influenza data, that's interesting. I was just it's good for lung health, too.","offset":3474,"duration":8},{"text":"Dr. Rhonda Patrick: Like so although if smokers take it, I think it has the opposite effect where again it's like the cancer the pre-cancerous cells are using it to their benefit. You know we used to think antioxidants \"oh it's so good\" you know just more more more and it turns out it's not the case right?","offset":3482,"duration":17},{"text":"Dr. Rhonda Patrick: Like and that's why a lot of these other types of hormetic stressors or plant phytochemicals they're actually generating an antioxidant response endogenously in our body by activating these antioxidant pathways which are so much more powerful than what you would get from an antioxidant, right?","offset":3499,"duration":17},{"text":"Dr. Rhonda Patrick: And so that's kind of and it's not that you don't want some antioxidants it's just like you don't want to overdose on taking too much NAC and too much vitamin C and too much vitamin E. Because there's also something called reductive stress. So we know about oxidative stress, oxidative stress is when you're you're again you're causing these these reactive oxygen species to damage things like your DNA for example and over time eventually that happens in a part of the gene that can be oncogenic and lead to cancer.","offset":3516,"duration":28},{"text":"Dr. Rhonda Patrick: Well reductive stress is is like the opposite of that, so it's like too much of the reducing equivalents, like the you know the NADH, the NADPH, the you know so and it also has negative effects. So you kind of don't want to go too far on either ends of the of the spectrum but also you want instead of having this like slow leaking effect of these pro-oxidants that are happening from eating a bad diet, from you know inflammation, things like that, you want it to be a short burst where you switch it on, you have the adaptation, and it's off, right?","offset":3544,"duration":31},{"text":"Dr. Rhonda Patrick: And the adaptation the adaptation happens in the recovery period, right? When you're for example if you exercise that's a big burst of reactive oxygen species that is beneficial and you want it, right? And you don't want to blunt those adaptations and so that's that's kind of my concern with daily dosing of NAC.","offset":3575,"duration":17},{"text":"Host: Great. I don't cold plunge in the 6 to 8 hours after uh resistance training for exactly the reason you're talking about, yeah I want the inflammation, I want the increased blood flow, I don't want to short-circuit that. I'm perfectly happy to only take NAC under conditions where I'm run down and and that's also when I'll take glutamine. If you take L-glutamine regularly, I I personally observe that I get stronger at a steady state of starch intake.","offset":3592,"duration":23},{"text":"Host: And I don't like dropping starches too low because I get weak and I also can't sleep as well if my starches are too low. I just am too wired.","offset":3615,"duration":8},{"text":"Dr. Rhonda Patrick: Yeah, there's there was a new study on on eating starches and improving sleep.","offset":3623,"duration":6},{"text":"Host: Yeah and I'm so grateful for that because for several years I talked about that on the podcast and people said \"oh you know he's gorging himself with pasta and then passing out and that's the worst time.\" I wasn't saying that, I'm saying that if you're not if you're running like crazy.","offset":3629,"duration":12},{"text":"Host: I'll hear from marathoners and ultra-people and people are doing a million things and they'll say \"I'm not sleeping well\" and they're exercising like crazy, it's like \"well when was the last time you had a bowl of pasta?\" Like \"oh no, I don't eat pasta.\" And then they'll have some rice or some pasta, they're like \"oh I slept like a baby\" and they were having it at lunch!","offset":3641,"duration":13},{"text":"Host: And I just think that that the brain doesn't shut down well when you have high levels of cortisol. And the cortisol-starch thing is an interesting one.","offset":3654,"duration":10},{"text":"Dr. Rhonda Patrick: I'm so glad you brought this up because I think um this is something that I did want to talk about really and it has to do with stop eating three hours before bed for that very reason. So there was a new even a new, but there's been several studies now really showing that this is important for that cardiovascular reset, right?","offset":3664,"duration":19},{"text":"Dr. Rhonda Patrick: Your parasympathetic activity is supposed to go higher, you're in your rest and recovery phase, right? When you're eating food that's the sympathetic activity, right? You're it that's activating the sympathetic nervous system as you're eating.","offset":3683,"duration":9},{"text":"Host: As you're eating, yeah.","offset":3692,"duration":1},{"text":"Dr. Rhonda Patrick: Yeah and even as you're digesting, so you have to think about it, like you digest it what it takes like five or so hours to fully finish a meal depending on the meal. Yeah, so if you're eating, you know, right before you go to bed you are you are you are not in that parasympathetic activity, you know, part of the part of the you know cycle that you want to be in.","offset":3693,"duration":21},{"text":"Dr. Rhonda Patrick: So um there was a new even a new study that I shared like I don't know a couple days ago even showing that if you stop eating 3 hours before bed... so these people were actually, um this is interesting, they they had their blood pressure measured for starting in the mid-afternoon all the way throughout the night. So it's the first study that really not just one endpoint looking at blood pressure but just measuring it continuously.","offset":3714,"duration":24},{"text":"Dr. Rhonda Patrick: I don't know if it was every 15 minutes or something like that. But um it was found that their during sleep if they had stopped eating three hours before bed versus the group that did not stop eating three hours before bed their blood pressure dipped like lower, so you get that you know that baroreflex dipping, right?","offset":3738,"duration":19},{"text":"Dr. Rhonda Patrick: So this is like part of the parasympathetic activation as you know very important for the blood pressure to go down, heart rate went down, like you know much much lower and that reset is so so important for cardiovascular health. I think what was found was it was something like um translated to like 20% lower risk of cardiovascular events, like heart attacks.","offset":3757,"duration":22},{"text":"Dr. Rhonda Patrick: So it's really pretty significant, yeah. And it really isn't an easy thing to do to think about stopping eating, you know, 3 hours before you go to bed. Like that's that's something I think that is not that hard to implement and it will improve your sleep as well as your cardiovascular health.","offset":3779,"duration":16},{"text":"Dr. Rhonda Patrick: Although I think in that study I don't know that sleep was really it was subjective and I don't think it was really improved more but other studies have found that as well that sleep does improve. I know Satchin Panda he's been on my podcast your podcast, he's had studies showing that it seemed like stopping eating 3 hours before bed really does seem to improve sleep.","offset":3795,"duration":17},{"text":"Dr. Rhonda Patrick: But this parasympathetic activation, you know, you don't want to have a meal right before you bed because you want you want to be in the rest and recovery part, right?","offset":3812,"duration":6},{"text":"Host: Yeah I think people hear uh and I understand why the nomenclature and the buzzwords of you know \"fight or flight\" for sympathetic and \"rest and digest\" for parasympathetic but yeah the evidence shows eating stimulates the sympathetic nervous system. It's not a stress event but it's a it requires energy, anything that requires energy raises body temperature and your body's doing work.","offset":3818,"duration":318},{"text":"Dr. Rhonda Patrick: It's an awake event, right? It's an awake... you don't eat while you're sleeping. Yeah and that's why these phrases while I don't demonize anyone for creating the you know \"fight or flight\", well I mean there's ways that you want your sympathetic nervous system activated that are not about fight or flight. Like I actually think if people just got the first hour of their day more active and energized, bright light, exercise, caffeine if you're me and Lord knows I'm grateful that caffeine exists, in the first hour of the day or first hours if you can't manage that because of schedule and then the last hour of the day was strongly parasympathetic.","offset":4136,"duration":32},{"text":"Host: I mean everything would get better without having to think a ton about exactly how you're doing that because on a given day you just do what you can.","offset":4168,"duration":7},{"text":"Dr. Rhonda Patrick: And that's what you want, right? I mean so cortisol is circadian dependent as you know, I mean in the more like early morning of early hours of the morning that's when you want it to peak, right? Part of the awakening response like you want it to go up. And it's it's interesting I I the reason I'm going on this is because it's a little bit of a um soapbox for me but so with the with the cortisol activation um people don't realize this...","offset":4175,"duration":3025},{"text":"Dr. Rhonda Patrick: ...you know obviously it's a hormone and it's binding to diff two different receptors. There's the glucocorticoid receptor and then there's the mineralocorticoid receptor and both of those uh when cortisol binds to it they go into the nucleus of the cell and they're changing the expression, so they're activating genes and deactivating genes like 20% of the human genome. It's a large percentage, right?","offset":7200,"duration":19},{"text":"Dr. Rhonda Patrick: And this is on multiple different organs. So it's it cortisol has a very important role and you want that peak, you want that spike, right? That's what you want and then you want it to shut off. And there are things that can activate it obviously like in the morning, bright light exposure as you mentioned, like that's very important for that cortisol awakening response.","offset":7219,"duration":19},{"text":"Dr. Rhonda Patrick: But you can also ex like like intensity intensive exercise can switch it on um but what's interesting and so can intermittent fasting that it what's interesting is there's studies from Mark Mattson's lab showing that, you know, the types of of stressors that are beneficial, these hormetic stressors like exercise, like intermittent fasting...","offset":7238,"duration":22},{"text":"Dr. Rhonda Patrick: ...perhaps even cold exposure, like these types of exposures change the receptor density of these receptors. So if you if you look at what activates cortisol in a negative way, chronic stress let's say emotional, financial, psychological, um chronic sleep deprivation, right? That bad type of stress, you're getting not a big spike you're getting a slow drip of it.","offset":7260,"duration":21},{"text":"Dr. Rhonda Patrick: And so what happens is when you have that type of stress you're increasing the glucocorticoid receptors and you're decreasing the mineralocorticoid receptors. There's a different biological response in the brain, in the hypothalamus, but also in you know other organs as well when you're when you're activating cortisol through a beneficial type of stress, the hormetic stressors like like intermittent fasting, like exercise.","offset":7281,"duration":26},{"text":"Dr. Rhonda Patrick: Um I believe probably deliberate cold exposure as well, where um it's a different biological response and also if you think about it, you know, you actually want cortisol to do its, you know, function. You want it to change the expression of genes, that's what it's supposed to do, right? The problem is is when you have that slow drip, then you know not only are your you're increasing they're changing the receptor you know activation but also they become resistant to the cortisol and so you're not getting the benefits.","offset":7307,"duration":29},{"text":"Dr. Rhonda Patrick: You know cortisol represses inflammation, right? It it suppresses the immune system. But like so you're not getting that anti-inflammatory effect from cortisol, it's being disregulated. And that's what you don't want, you don't want cortisol to be disregulated in terms of like all the genes that it's supposed to activate or deactivate, you want it to be doing what it's supposed to be doing.","offset":7336,"duration":14},{"text":"Dr. Rhonda Patrick: It's supposed to regulate, we're supposed to have the cortisol, you know, activation response. So um anyways that's something that I kind of want to clear in people's minds because I feel like a lot of people get worried about \"oh my gosh I'm doing, you know, HIIT and it's activating my cortisol.\" Well that's fine, it's like, you know, I mean I guess if you do too much HIIT, right?","offset":7350,"duration":19},{"text":"Dr. Rhonda Patrick: You could always take something to the extreme okay with that caveat obviously I'm not talking about that. But with that caveat like you do you want your body to be able to turn it on and then turn it off and have the adaptation, have the response, right? And like I said it's a different biological response than than the chronic type of cortisol activation that you get with the bad types of stress.","offset":7369,"duration":20},{"text":"Host: Yeah I guess same goes for intermittent fasting. And maybe you could share with us what your intermittent fasting protocol is. I know that recently cortisol has been like increasingly demonized as this stress hormone, stress hormone, and people saw pictures of people with Cushing's disease, which is, you know, a drastically elevated cortisol and the moon face and the excessive visceral fat and and yeah this this sort of um fearmongering around cortisol was particularly directed toward women.","offset":7389,"duration":29},{"text":"Host: And this entered the health fitness space because I think in an appropriate way, I'll just be very direct here I don't like I no longer tap dance around who said you know in a very appropriate way uh that I appreciate um Dr. Stacy Sims came on the podcast and she said, \"Listen some women shouldn't train fasted because they don't feel well when they train fasted and their cortisol is too high\" and so forth.","offset":7418,"duration":24},{"text":"Host: That captured a lot of people's experience. A lot of women in particular, but some men certainly were like \"yes oh my god thank you, thank you, thank you!\" But then the they the message got contorted, right? As it does, yes. Yes! And then it became \"women shouldn't train fasted.\"","offset":7442,"duration":17},{"text":"Host: And then we had uh Lauren Colenso-Semple on this podcast, who's a you know trained as a PhD she has a background in nutrition physiology strength training coach etc. and she said \"No, listen you can train fasted or not fasted as a woman or a man, it's kind of your preference.\"","offset":7459,"duration":-2990},{"text":"Host: But that we don't need to fear these cortisol spikes. And forgive me for going long here but I think it is important that people hear this uh again, which is there's also this idea that deliberate cold exposure increases cortisol but when you look at the data it definitely increases adrenaline.","offset":4469,"duration":14},{"text":"Dr. Rhonda Patrick: Yeah.","offset":4483,"duration":1},{"text":"Host: And peripheral dopamine and probably, I'll go on record here, probably central dopamine although we don't have as good evidence for that yet. But there evidence points to the fact that deliberate cold exposure lowers cortisol.","offset":4484,"duration":14},{"text":"Host: So this then you know because I think Stacy appropriately said a lot of women who want to use cold shouldn't go as cold. But the message got contorted and it became \"women shouldn't do deliberate cold exposure because of the cortisol increase.\"","offset":4498,"duration":17},{"text":"Host: And so part of the reason I'm going long here is I'm trying to correct the narrative on her behalf. She said \"do what works for you\", right? And that's what Lauren's saying and I'm guessing um that's what you'll say as well. Um but I just need to get that out there because the message has gotten totally pretzel twisted up and cortisol is neither good nor bad. You want it high in the morning you want it low at night, um in general.","offset":4515,"duration":20},{"text":"Host: Um it sounds like you train fasted?","offset":4535,"duration":3},{"text":"Dr. Rhonda Patrick: I listen to how I feel. That's exactly what I do. So what what your podcast guest and and the researchers are talking about is exactly there are times when I wake up in the morning and I'm like \"I need to eat something before I work out\" and I do. Um but I oftentimes do train fasted for one because I am practicing intermittent fasting again, but I do it I'm not like starving myself and like I said the reason there's multiple reasons I do it.","offset":4538,"duration":27},{"text":"Dr. Rhonda Patrick: One reason is because it really did help me lose the belly fat, which is visceral fat, which is like the worst kind of fat you can have. And we can talk more about that. Um but the second reason is I love the cognitive benefits I have in the morning with it. And it's the main reason I do it.","offset":4565,"duration":14},{"text":"Dr. Rhonda Patrick: And so there are many times what I do train fasted, but I am not out running 15 miles, most of my my like I said my sessions are about an hour long and am I taking a little bit of a performance hit with the high intensity? Probably. Probably yes, but it's not much to matter for me and you do burn a little bit more fat if you train fasted. I mean that's known.","offset":4579,"duration":23},{"text":"Dr. Rhonda Patrick: Um you will if it is a longer session you will take an import performance enhancement hit that is also known, right? So I think it really does come down to like \"what is your goal, how do you feel?\" and and then you kind of go with that.","offset":4602,"duration":11},{"text":"Dr. Rhonda Patrick: And I and I completely agree like there are times when, you know, I'm on my cycle and I feel fine and I'm working out just fine. And there are time other times when I'm like \"I don't feel good like I'm going to I'm going to take it easier\" but I still train, I just you listen to your body and I think that's a pretty easy I think rule of thumb.","offset":4613,"duration":16},{"text":"Dr. Rhonda Patrick: Sometimes people like to complicate things, you know, I don't know there's lots of reasons why I don't we don't need to get into that.","offset":4629,"duration":7},{"text":"Host: I have theories, yeah I have theories but they're not important right now.","offset":4636,"duration":3},{"text":"Dr. Rhonda Patrick: No, it's not important, yeah. So so yeah I do I do train fasted and it is um for me it is it is helped me tremendously change my body composition. Like I said I'm in a different part of my life than perhaps a 30-year-old woman is, right? Because when I was 30 I mean like I didn't have to train fasted. It was it was easy to keep, you know, the the belly fat, the visceral fat lower.","offset":4639,"duration":23},{"text":"Dr. Rhonda Patrick: Um hormonal changes are do play a role in the way your body... so estrogen plays a role in telling your body how to store fat. So subcutaneous fat would be the kind of fat that you can just like pinch, right? The fat that we see.","offset":4662,"duration":12},{"text":"Dr. Rhonda Patrick: The visceral fat that's that deep fat that's lining your organs, it's often belly fat, you know, and it's lining the intestines, the liver, you know, it's it's it's it's almost like an endocrine organ I mean because it is secreting hormones, it's secreting inflammatory factors, it's metabolically active, it's constantly breaking down triglycerides.","offset":4674,"duration":21},{"text":"Dr. Rhonda Patrick: It's associated with double the increased risk double the risk of early death. Um people that have high visceral fat have 44% higher chance of having cancer, many different types of cancers.","offset":4695,"duration":8},{"text":"Host: Wow.","offset":4703,"duration":1},{"text":"Dr. Rhonda Patrick: It's huge, it's huge, you know. And and of course insulin resistance is the number one problem with visceral fat, right? And I'd love to to talk about that but if you want I mean we can we can get into that. Yeah, it's so with the visceral and like I said, you know, visceral fat is something if you really directly want to measure it you do a DEXA scan.","offset":4704,"duration":18},{"text":"Dr. Rhonda Patrick: But you know for the average person that isn't going to go out and do a DEXA scan, waist circumference is a proxy, it's used in a lot of studies. So women that have a waist circumference of 35 inches or above are considered to have a higher amount of visceral fat. Men that have a waist circumference of 40 inches or above are considered to have a higher amount of visceral fat.","offset":4722,"duration":17},{"text":"Dr. Rhonda Patrick: It's also that belly fat, like you you can you just know, right? Um interestingly like 70% of women over the age of 50 have high visceral fat, 50% of men over the age of 50 do. You know again coming down to women go through menopause, estrogen plays an important role in telling the body, you know, to store the fat subcutaneously rather than viscerally deep around organs.","offset":4739,"duration":26},{"text":"Dr. Rhonda Patrick: And so as women transition to perimenopause, you know, the the years before menopause and menopause it the their estrogen goes down and that does change the way the body stores fat. And any woman that's going through either of those stages knows it. And it's also why you see often women over the age of 50 with more belly fat. Right?","offset":4765,"duration":19},{"text":"Dr. Rhonda Patrick: I mean that's something that I think it's it's hard to deny. But um it's it's one of the reasons why I kind of went back to practicing intermittent fasting because there's a there's a couple of ways that you can really powerfully lose visceral fat and one of them is doing aerobic exercise, high intensity interval training also really powerfully can do it.","offset":4784,"duration":25},{"text":"Dr. Rhonda Patrick: But also being in a caloric deficit and I think when you start to get the combination of both, that's what really worked for me. It's crazy how quickly you can gain it based on your diet as well. So it is different from the subcutaneous fat in many ways. I mentioned it's secreting these inflammatory molecules, it's you know hormones, but it's also constantly breaking down triglycerides into free fatty acids.","offset":4809,"duration":30},{"text":"Dr. Rhonda Patrick: And the location of it is very dangerous because it's right surrounding the liver, right? It's this deep organ fat. And that's very close to the portal vein and so you're constantly getting this sort of mainlining free fatty acids to the liver.","offset":4839,"duration":14},{"text":"Dr. Rhonda Patrick: And visceral fat is very different from subcutaneous fat because it doesn't respond to insulin like subcutaneous fat does. In other words when you have a meal, you eat a carbohydrate meal and you basically your body increases insulin to help take it up glucose into your liver, muscle, adipose tissue.","offset":4853,"duration":614},{"text":"Dr. Rhonda Patrick: Lipolysis shuts down, right? It's like \"okay no longer am I going to break down these fats, it's time to use this energy\", right? Visceral fat doesn't respond to insulin so it just keeps going, right? And these free fatty acids because they're going right to the liver um it's essentially antagonizing the insulin receptors.","offset":5467,"duration":14},{"text":"Dr. Rhonda Patrick: So it causes insulin receptors to become more resistant to insulin. And this is part of why people with high visceral fat... by the way you can gain visceral fat without gaining a pound.","offset":5481,"duration":12},{"text":"Dr. Rhonda Patrick: And we can talk about those studies like people people are skinny and can have high amounts of visceral fat. You've heard of like lean metabolically unhealthy but lean individuals, those people exist and so you can have a high amount of visceral fat but not really look like you do.","offset":5493,"duration":18},{"text":"Dr. Rhonda Patrick: So um when you know obviously the insulin resistance is a problem for many reasons but it also plays a role in those energy crashes that you experience, right?","offset":5511,"duration":8},{"text":"Dr. Rhonda Patrick: And that's kind of like some of the first signs of insulin resistance actually have to do with what you're feeling. So we talked about lethargy, right? So you know the inflammation that's being generated from these this visceral fat constantly making these, you know, pro-inflammatory compounds are an it's an energy sink, right?","offset":5519,"duration":16},{"text":"Dr. Rhonda Patrick: So you do constantly feel tired, but also because your cells are becoming insulin resistant, when you have a high glucose meal and you're not responding the body kind of overcompensates and produces more insulin. So it's like \"I we got to get this blood glucose out of our system\", right? It can cause a lot of damage if it sits around there.","offset":5535,"duration":18},{"text":"Dr. Rhonda Patrick: And so you make more insulin and then what happens is your you your blood glucose goes way low because it was like this overcompensation, right? And then you feel a crash, you feel like this crash and that signals to the, you know, hypothalamus part of the brain \"uh I need energy\", right? So then you you sort of crave, you get those cravings for those calorically energy dense foods.","offset":5553,"duration":20},{"text":"Dr. Rhonda Patrick: What I'm talking about is like the experience of, you know, insulin resistance. And what's interesting is that you can cause someone to gain visceral fat and their brain can become insulin resistant. So we think a lot about insulin resistance in the muscle, liver, your brain also can become insulin resistant quite quickly actually.","offset":5573,"duration":20},{"text":"Dr. Rhonda Patrick: So um insulin's very important in the brain for a lot of reasons, as you know. But you know a couple of the things relative to what we're talking about or relevant to what we're talking about would be one is it does act on the hypothalamus and help, you know, tell it to basically stop eating, be satiated. Like \"I took a meal in okay like I'm going to be satiated.\"","offset":5593,"duration":19},{"text":"Dr. Rhonda Patrick: But it also plays a role in energy storage and telling the body how to store the energy. And so when your brain becomes insulin resistant, it's not doing that and so you're not being satiated so you eat more and you're storing the fat more viscerally.","offset":5612,"duration":16},{"text":"Dr. Rhonda Patrick: And there was a study that was published actually quite recently I covered this in a in a recent newsletter. It was a really interesting study because it was healthy young men and researchers put them on a little bit of a calorically dense, so it was like they were eating 1200 to 1500 more calories a day and it was high saturated fat high sugar. So it was a processed foods ultra-processed foods like, you know, ultimate, right?","offset":5628,"duration":24},{"text":"Host: That's a lot of extra calories.","offset":5652,"duration":1},{"text":"Dr. Rhonda Patrick: A lot of extra calories for five days. It is. But what happened was their they did cause their brain to become insulin resistant and they didn't gain weight, but they gained visceral fat and they started gaining fat around their liver and that's something that happens as well because visceral fat is surrounding liver, you're getting a lot of free fatty acids and they're going right to the liver so the liver has to store it, right?","offset":5653,"duration":23},{"text":"Dr. Rhonda Patrick: So you get this non-alcoholic, you know, fatty fatty liver. But and that happened after five days. I mean without gaining weight!","offset":5676,"duration":8},{"text":"Host: In otherwise young healthy...","offset":5684,"duration":1},{"text":"Dr. Rhonda Patrick: Yeah! But you know they were eating a lot of calories extra calories.","offset":5685,"duration":4},{"text":"Host: Yeah that's like a 1200 that's like a half a pizza extra above your maintenance calories per day.","offset":5689,"duration":6},{"text":"Dr. Rhonda Patrick: And it's probably what they were doing and they were eating lots of well they were eating like saturated fat and refined sugar, so Doritos and French fries. You know I mean obviously if you're going to do the study you want to kind of do it to a high degree where you're going to see some change, right?","offset":5695,"duration":14},{"text":"Dr. Rhonda Patrick: So so maybe like maybe it's not going to happen in five days if you're if you're only eating 500 more calories a day but over time you will be gaining it visceral fat, right? So it's it's not going to be the same degree. It's something to be concerned about, it's something to think about and also because you can gain it and not really even know it like, you know, without gaining a pound.","offset":5709,"duration":23},{"text":"Dr. Rhonda Patrick: And there other things that cause it not just, you know, eating too many calories or diet composition. I mean you mentioned cortisol, I mean chronic elevated cortisol makes you store the fat around around, you know, visceral fat. Sleep loss, I mean there's also studies showing that you take healthy men, sleep deprive them for a couple of weeks I think 4 hours they're getting 4 hours of sleep a night they can start gaining visceral fat.","offset":5732,"duration":22},{"text":"Dr. Rhonda Patrick: I mean pretty rapidly with only like a pound gaining a pound of weight. So again it's like not necessarily something that you're going to see on the scale but it's happening, right? And it's affecting your short-term mood, I mean how you feel, your energy, it's affecting, you know, the way you're eating it's a vicious cycle because you start to eat more calories, right? And then it just becomes this vicious cycle of that you start to gain more visceral fat.","offset":5754,"duration":19},{"text":"Host: I'd like to take a quick break and acknowledge one of our sponsors, Element. Element is an electrolyte drink that has everything you need and nothing you don't. That means the electrolytes, sodium, magnesium, and potassium, all in the correct ratios, but no sugar. Proper hydration is critical for brain and body function.","offset":5773,"duration":18},{"text":"Host: Even a slight degree of dehydration can diminish your cognitive and physical performance. It's also important that you get adequate electrolytes. The electrolytes, sodium, magnesium, and potassium, are vital for the functioning of all cells in your body, especially your neurons or your nerve cells.","offset":5791,"duration":16},{"text":"Host: Drinking Element makes it very easy to ensure that you're getting adequate hydration and adequate electrolytes. My days tend to start really fast, meaning I have to jump right into work or right into exercise. So to make sure that I'm hydrated and I have sufficient electrolytes, when I first wake up in the morning, I drink 16 to 32 ounces of water with an Element packet dissolved in it.","offset":5807,"duration":19},{"text":"Host: I also drink Element dissolved in water during any kind of physical exercise that I'm doing, especially on hot days when I'm sweating a lot and losing water and electrolytes. Element has a bunch of great tasting flavors. In fact I love them all. I love the watermelon, the raspberry, the citrus, and I really love the lemonade flavor.","offset":5826,"duration":16},{"text":"Host: So if you'd like to try Element, you can go to drinkelement.com/huberman to claim a free Element sample pack with any purchase. Again that's drinkelement.com/huberman to claim a free sample pack.","offset":5842,"duration":12},{"text":"Host: Such an important point that you can either not be gaining much or not gaining any um total body weight but gain visceral fat. I think that's um first time I've heard that and it's a vital message for people to hear because this visceral fat sounds like one of the major health hazards we need to worry about.","offset":5854,"duration":18},{"text":"Host: You mentioned elevate chronically elevated cortisol, sleep deprivation, will increase visceral fat. Once again I know I'm beating a drum here um almost to death, but having high cortisol early in the day and low cortisol in the evening is the definition of not chronically high cortisol.","offset":5872,"duration":17},{"text":"Host: The definition of chronically high cortisol is somewhat elevated or elevated cortisol in the morning, but especially in the hours before sleep and I I actually have a theory that is not a stretch that one of the main reasons why it's so detrimental to our mental and physical health in the short and long term is because of the ways it disrupts sleep.","offset":5889,"duration":19},{"text":"Host: And so and we can't tease those apart. No! You can't do a study where you spike cortisol late in the day even if you can fall asleep just fine after the end of a really stressful day the sleep is different. And people say \"well life has stress\" and I totally agree. I mean Lord knows I've experienced life has stress.","offset":5908,"duration":15},{"text":"Host: But getting that last hour of the day doing things to push down on cortisol push down on stress lower heart rate not eating in that certainly that last hour before sleep ideally 3. Um I feel like that small change can make a an outsized positive difference.","offset":5923,"duration":15},{"text":"Dr. Rhonda Patrick: That's interesting like the the correlation between the high cortisol affecting your sleep and maybe that's also like they they're related and so the sleep loss really does make you... we know, we know from, you know, you probably know who the researchers are that have done those studies on sleep loss and it affecting appetite, right? I mean...","offset":5938,"duration":17},{"text":"Host: Oh everything gets disregarded. I mean I don't want to take us off course, but I think you might find it interesting there's a beautiful study where they look measured metabolism during sleep. They basically had people breathe into a tube um during sleep, they had a mask on and it turns out that the brain cycles through all the different forms of metabolism during sleep.","offset":5955,"duration":14},{"text":"Host: There's a phase of sleep where you're essentially running on sugar, there's a then there's like it almost looks like somebody's ketogenic at one... basically the the middle of the night when we're so should be at night when you're sleeping is is kind of a test run of all the systems but they get recalibrated.","offset":5969,"duration":19},{"text":"Host: And it's so important. I actually think, you know, most of the negative effects of alcohol that people talk about, yes it's a poison, it's a class 1 carcinogen, um as classified by the World Health Organization on a... I think most of the negative effects of drinking are because of the negative effects of alcohol on sleep. I'm not telling people drink in the morning, but uh you know...","offset":5988,"duration":21},{"text":"Host: And so I think that if you get your sleep right you're not 90% of the way there, but you're halfway there. Yeah. I really do believe that. And then getting your sleep right makes you do a bunch of other things.","offset":6009,"duration":8},{"text":"Dr. Rhonda Patrick: Right, you're more you're more more motivated to exercise for one.","offset":6017,"duration":3},{"text":"Host: More motivated to exercise, your food choices, I mean and on and on. The the problem with talking about sleep is so important is people will get sleep anxiety so we tap dance around this. It's like \"oh we don't want people stress.\" Learn how to fall asleep, learn how to fall back asleep. These no one gets it perfect, yes you'll survive like with one poor night's sleep or an all-nighter, you're not going to die, like you know just get good at it on average right?","offset":6020,"duration":20},{"text":"Host: That's what I'd say. Could you tell us what the structure of the intermittent fasting is for you? Does that mean skipping breakfast, skipping lunch, skipping dinner because I know a number of people are sort of getting drawn back to intermittent fasting after a couple of years of it getting beat up on as like not the best way to lose fat or it is a I think it's a terrific way to do the sorts of things that you're describing and I'm learning today more about the the positive things it can do um for insulin sensitivity and so forth.","offset":6040,"duration":29},{"text":"Host: If you're on a bout of intermittent fasting are you doing it by the clock? Are you doing it by feel? What does it look like?","offset":6069,"duration":5},{"text":"Dr. Rhonda Patrick: For me it it really does depend on the day and I really do try to stop eating 3 hours before I go to bed. It doesn't always happen, you know, with family obligations, social obligations, but it's the habit that's important, right? So intermittent fasting, you know, it's more than just one intervention as I mentioned, it's a behavioral tool that you can use to limit your calorie intake without actually having to count all the calories, which some people like to do, some people don't, right?","offset":6074,"duration":24},{"text":"Dr. Rhonda Patrick: So it's a tool, but also it's really important for a metabolic switch. As you mentioned insulin sensitivity the metabolic switch is something that Dr. Mark Mattson coined and I love it because I feel like, you know, thinking about intermittent fasting in that way makes it a little more clear as to the benefits of it. It depends on the meal you have and how much exercise you do, right?","offset":6098,"duration":23},{"text":"Dr. Rhonda Patrick: But on average let's say 11, 12 hours to deplete your liver glycogen levels. And once that happens you do start to burn fat and use fatty acids as fuel and make ketone bodies so you go into ketogenesis, right? And that's a metabolic switch. Metabolic flexibility you're you're going from using carbohydrates as fuel to using fatty acids and making ketone bodies as fuel.","offset":6121,"duration":23},{"text":"Dr. Rhonda Patrick: And that's something that, you know, throughout human evolution was ingrained, right? Like we didn't always have access to Uber Eats and Instacart and you can just out of swipe you get food, right? You I mean there were many times when, you know, people had to not eat because they couldn't forge their foods, maybe the time of year or they couldn't hunt their food because they didn't get a win or whatever I don't know.","offset":6144,"duration":25},{"text":"Dr. Rhonda Patrick: So this metabolic flexibility is something that's really ingrained in our in our our DNA in a sense, right? Um one of the reasons I like to do that is the ketone production and why is that, you know, ketones are really clean they're clean a clean way to burn energy. So they generate less oxidative stress, less oxidative products, but they also are energetically favorable in that it takes less energy to use them to make energy than glucose does.","offset":6169,"duration":29},{"text":"Dr. Rhonda Patrick: So it takes more energy to use glucose as energy than it does ketones. But they're also a signaling molecule, so it's a way for the body, you know, to signal to other parts of the body like \"hey this is a stressful time, there's no food, I'm you know burn I'm in ketosis, um let's let's make you stronger\", right?","offset":6198,"duration":20},{"text":"Dr. Rhonda Patrick: Because that's kind of what evolution wants, like if you're not able to find or eat food you have to be stronger to be able to do it, right? And so that's that's kind of at the I say core of of this metabolic switch and why it's important and I think that I really like Mark Mattson being the pioneer in this and as a neuroscientist really looking at the benefits in the brain as well, you know.","offset":6218,"duration":20},{"text":"Dr. Rhonda Patrick: These ketones like beta-hydroxybutyrate are activating, you know, growth factors like brain-derived neurotrophic factor in the brain, as you know, it's very important for, you know, learning memory, you know, synapse formation and stuff this hugely important for neuroplasticity. So it's activating beneficial compounds like that and again, um it it's not going to happen if you're never going into this metabolic switch.","offset":6238,"duration":21},{"text":"Dr. Rhonda Patrick: And there's other ways to get there. So you can limit your your food go into this ketosis, right? Where you're basically depleting your liver glycogen. Or you can exercise a lot, right? So your energy expenditure goes up. So there's there's different ways to get to this metabolic switch. It doesn't necessarily have to be intermittent fasting.","offset":6259,"duration":22},{"text":"Host: Got it.","offset":6281,"duration":1},{"text":"Dr. Rhonda Patrick: And I'm telling you this because you're I want to tell you why I'm I'm sort of back back on the intermittent fasting and by the way it's not for everyone like I said, I mean I think that you can find other ways to get this metabolic switch and um for me intermittent fasting works. And so what I do typically is I will do most of the time my fasted my...","offset":6282,"duration":15},{"text":"Dr. Rhonda Patrick: But I mean, obviously we don't always want to be in a calorie deficit, but we always don't want to be constantly eating either. And that's why it comes down to I think the simple rule for people like if they're going to do some sort of metabolic switch, some sort of intermittent fast, it would be like okay let's try to at least stop eating three hours before bed.","offset":6297,"duration":18},{"text":"Dr. Rhonda Patrick: Because then you're at least going to be extending that fast somewhat by three hours, right? So I think that's and plus you're getting that the cardiovascular benefits that are really seem to be important.","offset":6315,"duration":11},{"text":"Dr. Rhonda Patrick: And then not eating at night, so there's all these studies that have come out of Israel, I think it's is it Jacobwitz, Jacobwitz and Freud are two researchers. Um, I mean Satchin Panda I remember years ago showed me one of the studies it was like published in science showing that if you have the same exact meal, same calorie intake, same composition macronutrient composition in the morning, the afternoon, in the evening, the insulin response is like com is different.","offset":6326,"duration":34},{"text":"Dr. Rhonda Patrick: Like you're the most insulin sensitive early in the morning. As you start to go towards the evening, and particularly three hours before your natural bedtime, you see your your melatonin levels naturally rise, right? And as you know, you know melatonin is important for the onset of sleep and preparing the body for sleep.","offset":6360,"duration":19},{"text":"Dr. Rhonda Patrick: But it's also preparing the other organs for rest and recovery, including the pancreas which is making insulin. And so you're not making as much insulin when it's closer to your natural bedtime because of the melatonin levels that are rising.","offset":6379,"duration":15},{"text":"Dr. Rhonda Patrick: And so you don't want to be eating, particularly a carbohydrate rich meal, but a meal, you're not going to be as as insulin sensitive in the last three hours before sleep.","offset":6394,"duration":10},{"text":"Host: Yeah, when you're starting to get into that melatonin rising phase of of you know, of your cycle. Yeah, it's interesting. I I think when people hear, okay you're most insulin sensitive in the morning, that would be the time to eat your biggest meal.","offset":6404,"duration":19},{"text":"Host: But then people say, wait but then I'm trying to fast before and I'm trying to exercise and like how do I do this? I think that's where for them the confusion comes in and it to me it's very simple. Uh, just because your insulin sensitivity is highest first thing in the morning doesn't mean you have to eat right away.","offset":6423,"duration":15},{"text":"Host: I mean it just means avoid eating too close to bedtime, right? Sometime during the day. And also if you exercise fasted or after a small snack, it was kind of interesting what Stacy Sims said, not everyone should exercise fasted. She said especially a lot of women don't like to do that. She didn't say eat a meal.","offset":6438,"duration":18},{"text":"Host: She said like have a scoop of whey protein with some I think she said with like some almond milk in it. And and you couldn't believe the response on the internet. It was like vindication, right? And I get it, it was like it vindicated people's experience, like oh thank you thank you.","offset":6456,"duration":17},{"text":"Host: And it it told me something really important about the kind of sociology of what we do, which is when something validates people's experience they they love it. But it doesn't mean that the things that work for other people don't work.","offset":6473,"duration":17},{"text":"Host: And I think that that's the part that gets lost. And so if a study shows that insulin sensitivity is highest in the morning, but you can only exercise first thing in the morning, what do you do? You know, so uh, you do the best you can, right? I think is what it comes down to.","offset":6490,"duration":16},{"text":"Host: In fact I meant to ask you earlier and it's this is a good time to uh, to talk about this. Uh, you've described that if you are slightly sleep deprived, so not four hours per night or an all-nighter, but if you've only slept five, or let's say you're getting an hour or two less than your normal ration of sleep, there's some pretty significant inflammation that's that that occurs, that's not good.","offset":6506,"duration":25},{"text":"Host: But I've heard you cover that exercising can actually offset some of that inflammation. This answers a a important and common question which is if I have to pick between sleep and exercise, what do I do? Um, and it sounds like if it's one night poor sleep, exercise. But you but you don't want to make it a habit. That's do I have that right?","offset":6531,"duration":18},{"text":"Dr. Rhonda Patrick: Yeah. I mean so this this data a lot of it actually comes from you can cause even acute insulin resistance after like a night of of sleep deprivation, certainly after two to three nights of sleep deprivation. And you know, again a lot of that's coming down to some of the things we've already talked about.","offset":6549,"duration":20},{"text":"Dr. Rhonda Patrick: And um, but exercise can help basically negate a lot of that. And I learned that first hand through experience when I was wearing a continuous glucose monitor uh, and when I was a new parent, of course you're not getting enough enough sleep.","offset":6569,"duration":17},{"text":"Dr. Rhonda Patrick: And so that's I learned it before I actually dove into the science about it, I I learned about it through my own data, where I was, you know, I wasn't exercising as much, and particularly in the first month you really like you're kind of in a cave as a new mom, you don't really you're not really exercising much at all.","offset":6586,"duration":11},{"text":"Host: Evolution wants the the baby to survive.","offset":6597,"duration":3},{"text":"Dr. Rhonda Patrick: You're recovering too. I mean childbirth is a very it's a very traumatic process on your body. And so um, I noticed that my my glucose response was like it was pre-diabetic. And I was like what is going on? And um, and that's when I started looking into the literature.","offset":6600,"duration":18},{"text":"Dr. Rhonda Patrick: And happened to be around the same time when I was then starting up my at the time I was doing spin classes, and then it was very clear to me, it was like I do these high intensity interval training classes even just twice a week, and it was like almost completely negating what I had seen previously of my my glucose being my fasting glucose being really high, and also my postprandial glucose being higher than than usual.","offset":6618,"duration":23},{"text":"Dr. Rhonda Patrick: And so um, I looked into the studies and there's now you can you can find many studies out there and it really I mean obviously exercise is one of the best things you can do to improve insulin sensitivity and to also bring glucose into your cells, right?","offset":6641,"duration":19},{"text":"Dr. Rhonda Patrick: And so that's part of what you were talking about with you're more insulin sensitive during morning, least during evening, and I also mentioned that. But guess what? There's levers you can pull that like change the equation, and exercise is a big one, right?","offset":6660,"duration":14},{"text":"Dr. Rhonda Patrick: If you're if you're exercising you're becoming more insulin sensitive, you're increasing more glucose transporters on your muscle, that's causing glucose to go in easier, right? There's so there's lots of ways around some of these rules that we hear about.","offset":6674,"duration":14},{"text":"Dr. Rhonda Patrick: But with the with the sleep loss, it really is it's interesting because people like when they don't get sleep, the last thing they want to do is work out. And obviously like you don't want to do like the hardest thing especially if you're really like sleep deprived a lot, but it really does help negate the inflammation and the insulin insensitivity that can happen after even just a single night of sleep, and there's studies out there showing that.","offset":6688,"duration":28},{"text":"Dr. Rhonda Patrick: And then there's also these longitudinal studies that have been done looking at you know, people so obviously a poor sleep is a problem, you know, in the United States, I mean a lot of people are are sleeping fewer than seven hours a night. And um, but there's studies out there that have looked at people that sleep either shorter, so fewer than seven hours a night, or they're sleeping more than ten, right?","offset":6716,"duration":20},{"text":"Dr. Rhonda Patrick: So you don't want to be on either end of the spectrum and usually like sleeping long there's like other disease states associated with it, right? But um, so people that are sleeping, you know not getting enough sleep, they have a higher all-cause mortality than people that are getting at least seven to nine hours of sleep. And the same for like more than ten, they have a higher all-cause mortality than people getting between seven and nine.","offset":6736,"duration":21},{"text":"Dr. Rhonda Patrick: But if people exercise, if they're meeting the physical activity guidelines right now, which is 75 minutes of vigorous intensity exercise and 150 minutes a week of moderate intensity exercise...","offset":6757,"duration":12},{"text":"Host: Right, well because the guidelines are helpful, but they're just guidelines because I mean doing the sort of workout that you're doing, working up to doubles and triples and singles on compound lifts and then doing uh cardio like getting your heart rate elevated and then doing addition of that and then you're hiking. I mean that it's just uh I think the guidelines are a good jumping off place for people to think about.","offset":6769,"duration":22},{"text":"Dr. Rhonda Patrick: Well, we can talk about that because there's a new study that kind of throws that on the head. But but the point is is that if they if people were exercising within the guideline range, that they basically and if they weren't getting enough sleep, if they were getting fewer than seven hours of sleep per night, that they they basically had the same mortality rate as people that were getting enough sleep.","offset":6791,"duration":18},{"text":"Dr. Rhonda Patrick: So it's offsetting some of that unhealthy stuff, the insulin resistance, you know, the inflammation that we know, you know, can lead to diseases and early mortality.","offset":6809,"duration":10},{"text":"Host: So find the time to exercise folks. But of course periods of time like after a new child, or new job, or particularly stressful time, I don't know any human being, I don't care how driven, okay there's probably Goggins and Cam Haynes being probably exceptions and a few others, you know, I don't Ken Rideout and a few others.","offset":6819,"duration":23},{"text":"Host: But people who everybody else um seems to have periods of time where they need to just back off a bit. I know I certainly do, and that I feel like I'm doing pretty well for myself despite, you know and and I think that it's important that people not hold themselves to a standard that is going to make them sick or injured or miserable beyond. Yeah, you also want to continue to enjoy health promoting activities, right?","offset":6842,"duration":24},{"text":"Dr. Rhonda Patrick: Right. I mean you gotta say like what's your goal, like your goal is to be healthy, to be happy. If you're taking it to this extreme where you're trying to just go to the extreme, like go hard, go home, and it's you're sacrificing your happiness too, I mean that then that's a problem, right? Because that's part of the equation happiness is part of that health equation.","offset":6866,"duration":20},{"text":"Host: Health is a daily and lifelong thing, but sometimes it means taking a day off. I think that's what people don't say um, and I think it's in a time when perhaps a lot of people aren't exercising enough, so promoting that no days off thing can be helpful. But for those that are already sort of you know forward center of mass, you know coming off the accelerator can be really useful.","offset":6886,"duration":21},{"text":"Dr. Rhonda Patrick: Yeah. Well I also want to just mention because you know we we talked about my you know, I I work out a lot and I'm sort of addicted to it, but like not everyone has the time and motivation to to go spend an hour block of time working out.","offset":6907,"duration":18},{"text":"Dr. Rhonda Patrick: And this is where I think the people can sigh a sigh of relief, because there's now so much emerging data that have been coming out you know, over the last decade on these short burst of physical activity that add up.","offset":6925,"duration":15},{"text":"Dr. Rhonda Patrick: They add up and people aren't really thinking about them in you know counting towards adding up to to their physical activity you know requirements for the for the week. And so there's these a lot of studies now there's on something called vigorous intermittent lifestyle physical activity VILPA studies. Have you heard of those?","offset":6940,"duration":18},{"text":"Host: Are these the exercise snacks?","offset":6958,"duration":1},{"text":"Dr. Rhonda Patrick: They're unstructured ex they're unstructured and not everyone likes the word exercise snacks, I mean I kind of like it, but the unstructured exercise they're they're they're the moments in your life where you're taking advantage of everyday situations to get your heart rate up to move.","offset":6959,"duration":16},{"text":"Dr. Rhonda Patrick: And so that could be I'm playing with my new puppy and I'm sprinting around with my new puppy. I'm you know chasing my grandkid around playing tag or my child. I'm sprinting up the stairs to get to my office. I'm running to catch the bus. I'm moving, right?","offset":6975,"duration":17},{"text":"Dr. Rhonda Patrick: And so um, researchers and there've been several studies on this now, researchers use accelerometers rather than just relying on these questionnaires which are as you know, you know extremely unreliable. I mean it's very hard for people to to remember how much exercise you sit here asking me about my exercise I mean there's only so much you know that you can be accurate with when you're trying to recall that.","offset":6992,"duration":19},{"text":"Dr. Rhonda Patrick: So these accelerometers are are worn people's wrist and they're and they're measuring like fast movement, the movement, right? And so thousands and thousands, like hundreds of thousand participants, there's a lots of data now showing that people that are doing these like short bursts at least a minute long but up to three minutes, right?","offset":7011,"duration":21},{"text":"Dr. Rhonda Patrick: Where they're getting their they're moving, I'm saying they're getting their heart rate up they're actually not measuring the heart rate in these states they're moving faster with intent, right? They're they're jogging or they're um you know, they're not of course there's the cases where they're actually exercising, but but the short burst of it um they're doing the things that I just mentioned and it's having outsized effects on on health outcomes.","offset":7032,"duration":25},{"text":"Dr. Rhonda Patrick: So for example individuals that do on the high end so they're doing, you know, three minutes of this short burst of an unstructured type of exercise snack and they do it three times a day, so it's a total of nine minutes a day, okay this type of activity, and it's considered more vigorous because of you're the intent to move, right? That's more vigorous, even though they're not measuring heart rate.","offset":7057,"duration":22},{"text":"Dr. Rhonda Patrick: That's associated with a 40% reduction in all-cause mortality, 40% reduction in cancer related mortality, a 50% reduction in cardiovascular related mortality. Wow. Nine minutes a day. And this is even in people that don't identify as exercisers, so they're not the kind of people like you and I that go and intentionally set out time to go to the gym.","offset":7079,"duration":23},{"text":"Dr. Rhonda Patrick: They're people that just they're just take they're they're doing those things, right? They're playing with their grandkids or their kids or their puppies or whatever. And so um, these moments they add up. And I'm I'm citing one study, but you know it was a dose dependent effect even doing three minutes a day, you know there's a study in women showing you know three and a half minutes a day, I mean they were having pretty profound benefits on all-cause mortality and cancer related mortality as well.","offset":7102,"duration":26},{"text":"Dr. Rhonda Patrick: And multiple studies now have shown this. I mean this is like one study after another after another. I mean it is undeniable that these short moments of you know getting physically activity active do add up.","offset":7128,"duration":10},{"text":"Dr. Rhonda Patrick: And structured exercise snacks can be part of that, like maybe you don't have a puppy, maybe you don't have a kid yet, maybe you work from home and you're not taking the you know maybe your situation's different than what I described, but you can take these moments to do exercise snacks.","offset":7138,"duration":16},{"text":"Dr. Rhonda Patrick: And that can be a minute long and it can be like there was there's studies showing that more two two studies and I'll talk about one, showing that getting up and doing 10 body weight squats every 45 minutes over a seven and a half hour work day is better at regulating blood glucose levels than a 30 minute walk, right?","offset":7154,"duration":19},{"text":"Dr. Rhonda Patrick: So you get up and you do 10 body weight squats. Pretty easy. I mean and it's also very good to break up that sedentary time. So being sedentary means like you're not moving, that also is an independent risk factor even if you do exercise for things like cancer being the big one.","offset":7173,"duration":15},{"text":"Dr. Rhonda Patrick: Although I would say if you're doing a lot of exercise you're doing pretty good, but I just like to mention that as well. I would say being sedentary is a disease, actually. That's that's something I mean people aren't thinking about it.","offset":7188,"duration":10},{"text":"Host: Even in the absence of what uh Lane Norton calls energy toxicity, like even if somebody is uh at maintenance or below maintenance calories, if they're sedentary, that's that's problematic.","offset":7198,"duration":12},{"text":"Dr. Rhonda Patrick: We do have data for one measuring cardio cardiorespiratory fitness, which is a marker of cardiovascular health, being physically fit, right? Obviously the gold standard of that would be measuring VO2 Max, your maximal oxygen uptake during maximal exercise.","offset":7210,"duration":16},{"text":"Dr. Rhonda Patrick: A lot of studies do not actually directly measure VO2 Max, they'll do, you know, maybe sub a submaximal treadmill test or they'll estimate it, right? There's a calculation out there you can do kind of what you're if you have like an Apple watch or some sort of fitness tracker what they do is which is you know it's looking at the distance that you run and the amount of time it takes, right?","offset":7226,"duration":20},{"text":"Dr. Rhonda Patrick: So like a 12 minute run would be an example people do that, you you run as fast as you can and maintain that pace for 12 minutes, you're not going all out obviously.","offset":7246,"duration":14},{"text":"Host: You see how far you can get.","offset":7260,"duration":1},{"text":"Dr. Rhonda Patrick: Yeah, yeah. And then and there's a calculation out there that's done to kind of estimate your VO2 Max, and so some studies are a lot of studies are actually doing sort of an estimation of cardiorespiratory fitness.","offset":7261,"duration":10},{"text":"Dr. Rhonda Patrick: So cardiorespiratory fitness um is really important I think for you know marking your health and longevity. And you know, if you have a low cardiorespiratory fitness, most of the times you are not physically active, right?","offset":7271,"duration":12},{"text":"Dr. Rhonda Patrick: And there are studies showing that if you don't have any you know diagnosable diseases, so you're not insulin resistant, you don't have cardiovascular disease, you don't have cancer, all that stuff, right? You're not um obese, but you have a low cardiorespiratory fitness, it is as bad or worse in terms of your all-cause mortality, you know, predicting mortality, than having cardiovascular disease, or smoking, or having hypertension, or these things that we know that are really bad for health, right?","offset":7283,"duration":31},{"text":"Dr. Rhonda Patrick: So being sedentary, as I'm saying it's low cardiorespiratory fitness, I guess it's not exactly correct, it's a little bit of I'm stretching it a little bit. But cardiorespiratory fitness is a marker of I would say fitness.","offset":7314,"duration":14},{"text":"Dr. Rhonda Patrick: And so um, that's why I think being sedentary is a disease. And people with a low cardiorespiratory fitness, I mean if you go anywhere above that, you know if from low to like low normal, that's associated with a two-year increase in life expectancy.","offset":7328,"duration":18},{"text":"Dr. Rhonda Patrick: If you go from low to um high normal, you know that's like almost a three-year increase in life expectancy. And if you go up to high then you're talking about a five-year increase in life expectancy compared to where you were at the low. But again, I'm not talking about VO2 Max, I'm talking about cardiorespiratory fitness.","offset":7346,"duration":18},{"text":"Dr. Rhonda Patrick: And it's it's really important. Here's another reason why I think that it's it's really bad. So these studies were done, by the way cardiorespiratory fitness is improved by aerobic exercise in general. That's great.","offset":7364,"duration":15},{"text":"Dr. Rhonda Patrick: And then you know if you add if you add in high intensity interval training in there mix, that also really helps because there are some people that don't respond necessarily to just doing cardiovascular...","offset":7379,"duration":10},{"text":"Host: Slow steady state.","offset":7389,"duration":1},{"text":"Dr. Rhonda Patrick: Mm-hmm. Yeah, about 40% of people don't respond, so mixing in the high intensity is good. If you're physically active and doing that that's great, if you're doing these short bursts of physical activity also good, because it's a little bit of a high intensity you know exercise, right?","offset":7390,"duration":16},{"text":"Dr. Rhonda Patrick: A min a minute running around chasing your grandkid or your puppy or your child, you know that's that's that's a hit.","offset":7406,"duration":5},{"text":"Host: Taking the stairs is amazing. I was traveling for a team...","offset":7411,"duration":2},{"text":"Dr. Rhonda Patrick: Sprinting up the stairs.","offset":7413,"duration":1},{"text":"Host: Going sprinting up the the stairs or if you're carrying a lot of luggage in the airport like going up the stairs or down the stairs. It's wild when you go to the airport, I I like to notice this, um nobody takes the stairs.","offset":7414,"duration":13},{"text":"Dr. Rhonda Patrick: Yeah, because they're there right.","offset":7427,"duration":1},{"text":"Host: Down or up like the escalators are there. And I'm always like oh this is a great opportunity to get some extra steps and some extra work but I realize that's me. Um, but it's just it's striking.","offset":7428,"duration":9},{"text":"Host: Um, and if you're in DC ever, you know, they have these long stairwells like go um up from the from the public transport and that's a workout, you know. And and I'm always like, oh free workout. Like you know like get it in my day. I mean it sucks to arrive a little bit more sweaty than you would otherwise.","offset":7437,"duration":15},{"text":"Host: But I just think if this were an experiment, and we were looking at mice, and we were videotaping from above, I always think of myself like which mouse am I going to be? All the mice are going up the automatic elevator. It makes sense why they would want to do that, but these opportunities for exercise are clearly there.","offset":7452,"duration":14},{"text":"Host: I I feel like this is also I I would be remiss if I didn't do a quick shout out to Steve Magness. Do you follow ever see his content?","offset":7466,"duration":8},{"text":"Dr. Rhonda Patrick: I've interacted with him, yeah. Um, on Twitter I've interacted with him, on X.","offset":7474,"duration":2},{"text":"Host: Yeah, I've never met him but um people should I think give him a follow. He's a very accomplished runner in his past, a running coach I believe as well, and um and a scientist, and I think has the best take on sort of measuring VO2 Max.","offset":7476,"duration":18},{"text":"Host: It's kind of interesting you know he has a theory which I think is strongly backed that most measures of VO2 Max are not measures of VO2 Max at all. But one of the best measures of cardiorespiratory fitness is how fast can you run a mile.","offset":7494,"duration":11},{"text":"Host: Hmm. And he says people are generally surprised how easy the easy stuff should feel and how hard the hard stuff should feel. So I want to just credit Steve for saying that. So I try and keep that in mind around my cardio and do some high i do a less of what you do I I confess, um some high intensity interval training Tabata type stuff and then some a lot of walks, a lot of hikes.","offset":7505,"duration":20},{"text":"Host: Yeah. And I haven't formally measured my VO2 Max in a while but I think he just nails it with that because I think people think the 30-minute jog on the treadmill where you get sweaty and you're like ah like that's accomplishing what you want but actually there's a much easier path to better health, which is what you do and more or less what Steve is describing as well. Uh does that square with your your experience?","offset":7525,"duration":21},{"text":"Dr. Rhonda Patrick: Yeah, I think so. I mean I do I do mix in quite a bit of probably more more high intensity interval training. But um, you know, I don't feel like if I felt like it was like if I didn't feel good I would I would toggle down the the pedal right I wouldn't keep keep going on it.","offset":7546,"duration":15},{"text":"Dr. Rhonda Patrick: So I think you have to again just listen to your body, you know you don't want to overdo things. And I am I mean there are people out there that are really like endurance athletes that are, you know, like that's not me. I'm a committed exerciser, I'm not an I'm not necessarily an athlete, uh but but yeah so that would that's those different I think levels here and Steve is obviously athlete.","offset":7561,"duration":20},{"text":"Host: Anyway, I've learned from him around this topic. It's been it's been helpful.","offset":7581,"duration":6},{"text":"Host: I'd like to take a quick break and acknowledge one of our sponsors, Function. Last year I became a function member after searching for the most comprehensive approach to lab testing. Function provides over 100 advanced lab tests that give you a key snapshot of your entire bodily health. This snapshot offers you with insights on your heart health, hormone health, immune function, nutrient levels, and much more.","offset":7587,"duration":23},{"text":"Host: They've also recently added tests for toxins, such as BPA exposure from harmful plastics and tests for PFASes, or forever chemicals. Function not only provides testing of over 100 biomarkers key to your physical and mental health, but it also analyzes these results and provides insights from top doctors who are expert in the relevant areas.","offset":7610,"duration":19},{"text":"Host: For example, in one of my first tests with Function, I learned that I had elevated levels of mercury in my blood. Function not only helped me detect that, but offered insights into how best to reduce my mercury levels, which included limiting my tuna consumption, I'd been eating a lot of tuna, while also making an effort to eat more leafy greens and supplementing with NAC, N-acetyl cysteine, both of which can support glutathione production and detoxification. And I should say by taking a second Function test, that approach worked.","offset":7629,"duration":24},{"text":"Host: Comprehensive blood testing is vitally important. There are so many things related to your mental and physical health that can only be detected in a blood test. The problem is blood testing has always been very expensive and complicated. In contrast, I've been super impressed by Function's simplicity and at the level of cost. It is very affordable.","offset":7653,"duration":18},{"text":"Host: As a consequence, I decided to join their scientific advisory board and I'm thrilled that they're sponsoring the podcast. If you'd like to try Function, you can go to functionhealth.com/huberman. Function currently has a wait list of over 250,000 people, but they're offering early access to Huberman Podcast listeners. Again, that's functionhealth.com/huberman to get early access to Function.","offset":7671,"duration":25},{"text":"Host: I want to ask you about creatine. Yeah. I'm 50, I started taking weight training and running when I was like 16 maybe, yeah. And I started taking creatine because back then I was skinny I wanted to put on muscle.","offset":7696,"duration":12},{"text":"Host: I think creatine was sort of first discovered or released back then when I was maybe 18 or something like that, something like that, 18 19. Um so I've been taking a long long time, 5 to 10 grams.","offset":7708,"duration":13},{"text":"Host: But the original protocol, which nobody does anymore, but I confess I still do it because I enjoy it was to take 5 grams three to five times per day, there was this loading phase and you would mix it with a little bit of grape juice because the idea was you were supposed to spike your insulin and then you get more into the muscles, and then you had a maintenance dose which was 5 grams per day.","offset":7721,"duration":24},{"text":"Host: Um, and the idea back then was that you need to do a washout every 20 weeks or so where you just stop taking it, you urinate out a bunch of water and then you reload. And I confess I've continued to do this minus the grape juice, but occasionally I'll do the grape juice thing.","offset":7745,"duration":16},{"text":"Host: I don't think that there's any real merit to the loading phase maintenance phase idea, but back then and still now I feel like creatine has maybe feel great, um stronger, um I did I wasn't aware of the cognitive benefits.","offset":7761,"duration":13},{"text":"Dr. Rhonda Patrick: They weren't being studied back then.","offset":7774,"duration":2},{"text":"Host: They weren't being studied back then, but what are your thoughts on why creatine suddenly has become this like banner supplement. It's like supplement of the year, we should start a supplement of the year thing, right? For a while I think vitamin D and melatonin came first, um and we'll have to figure out what years those were.","offset":7776,"duration":20},{"text":"Host: Then I feel like creatine got supplement of the year for 2026 is unless something else comes along. So creatine, supplement of the year 2026 even though it's been around for a long long time. What do you think happened?","offset":7796,"duration":11},{"text":"Dr. Rhonda Patrick: Well, so first I want to talk about your loading phase night like that was really for the studies that were being done, right? Because if you're taking 5 grams a day of creatine it takes about three to four weeks for your for your muscle creatine stores to become saturated, and researchers aren't going to do a study where they wait that long.","offset":7807,"duration":17},{"text":"Dr. Rhonda Patrick: So the loading phase really was just...","offset":7824,"duration":3},{"text":"Host: Oh, so that's what inspired it.","offset":7827,"duration":1},{"text":"Dr. Rhonda Patrick: Yeah, it was it's in this isolated bubble of in the experimental protocol, but like in the real world you have three weeks, or if you're like an athlete and you hadn't you know taken the creatine you don't have your creatine stores up and you have to quickly rapidly like increase your stores.","offset":7828,"duration":13},{"text":"Host: Got it. I was just amazed at how quickly it worked. I I might be a hyper responder, but I legitimately put on I realize some of it was water or most of it was water, but somewhere between probably 4 and 8 pounds of of water in the muscle mass. I don't want to call it lean mass because it's you know it's water in the muscle.","offset":7841,"duration":20},{"text":"Host: Um but I just was I was like, oh my goodness this is crazy, you know. And um and then people thought maybe it was a steroid, it's not a steroid, maybe it's bad for your kidneys, turns out it's safe for your kidneys in most everyone. Um pretty remarkable molecule.","offset":7861,"duration":12},{"text":"Dr. Rhonda Patrick: Yeah. I mean obviously creatine is stored as creatine phosphate in our in our cells, we make to some degree like between 1 to 3 grams of creatine a day, our liver, our brain also makes it. It's used to make energy and so your muscles if you're working out, you're really consuming a lot of energy, right?","offset":7873,"duration":19},{"text":"Dr. Rhonda Patrick: It's very energetically demanding, so having the creatine stores higher in your muscle is beneficial because one, you're going to be able to increase your training volume, right? So it's not like creatine is anabolic in the sense that protein or amino acids are, right?","offset":7892,"duration":15},{"text":"Dr. Rhonda Patrick: It's not like directly affecting muscle protein synthesis, it's just helping you train more, getting more reps in you know in whatever it is training training your training volume's going up, and because your training volume's going up then you're obviously putting more stress on your muscles which is going to lead to increased muscle protein synthesis and you know obviously there's water probably as well.","offset":7907,"duration":21},{"text":"Dr. Rhonda Patrick: That said, you know you asked me you know what happened. So I got interested in creatine back in 20 when I started basically weight training. You know, I've obviously had heard about it forever, never took it. And as I started to get into resistance training, I was like I better start taking this.","offset":7928,"duration":16},{"text":"Dr. Rhonda Patrick: This is I'm I'm in this world now and started doing some research and taking it. So I was taking the 5 grams a day because that's really what most of the studies show creatine monohydrate that's obviously the most well researched form of creatine, and I was taking 5 grams a day because I was interested in improving my my training volume and and getting the the benefits of it, right?","offset":7944,"duration":23},{"text":"Dr. Rhonda Patrick: Um and then I had Darren Candow on the podcast. Uh, that was in 2024 I think it was, and um once I had started getting into the creatine research, I the brain stuff started his brain stuff had been coming out over the past you know few years and that's for me become very interesting.","offset":7967,"duration":20},{"text":"Dr. Rhonda Patrick: I remember the first time I heard about it years ago it was like, oh it's it's helping improve cognitive function in older older you know people.","offset":7987,"duration":7},{"text":"Host: Yeah. The phosphocreatine system seems to be somewhat um biased towards forebrain structures. You know I mean obviously it's in lots of brain areas, but that there might be a heavier reliance on it for brain areas that are associated with strategic planning and you know working memory and yeah, if you if you were to sort of just map the the sort of density of usage of the phosphocreatine system you'd you'd see a frontal bias for sure.","offset":7994,"duration":21},{"text":"Dr. Rhonda Patrick: Okay, interesting. Interesting. Um well anyways, that's kind of where my interest in in you know kind of diving deeper, anything that's helping the brain is interesting to me as I know it is to you as well.","offset":8015,"duration":13},{"text":"Dr. Rhonda Patrick: And um and so I learned a lot from this podcast I did with Darren Candow, you know researches creatine and collaborates with a lot of different researchers that are doing you know research on the brain and muscle and you know lots of the bone turns out it's beneficial for the bone as well.","offset":8028,"duration":18},{"text":"Dr. Rhonda Patrick: But the brain it's interesting we also make creatine in the brain, but um it's not like so it's kind of like the muscle, right? You're not just going to if you take creatine and you don't work out, you're not going to you're not going to get any increase in lean mass, right? It's not going to do much of anything because you're not putting in the work.","offset":8046,"duration":15},{"text":"Dr. Rhonda Patrick: I think the same goes with the brain as well, where it's like researchers started to find out that well, you can't just take creatine and it's going to enhance cognitive function, it's in the background of stressing the brain, right?","offset":8061,"duration":13},{"text":"Dr. Rhonda Patrick: You're stressing your muscles by workout, same goes for the brain. It's like in these situations of stress, whether that's sleep deprivation, whether it's you know a traumatic brain injury. I mean I would argue you know there's a lot of psychological stress, depression, constantly using your brain like you and I right now in this conversation we're we're learning, we're thinking, I mean it is stressful on the brain, right?","offset":8074,"duration":25},{"text":"Dr. Rhonda Patrick: So I mean I am obviously speculating here and taking taking I'm extrapolating, right? I'm not saying that there's studies showing that but it does seem as though that that's when creatine seems to shine in the brain.","offset":8099,"duration":14},{"text":"Dr. Rhonda Patrick: And you might go well your brain makes it and it's true, your brain does make you know again it's I think between 1 to 3 grams or something, I'm not exactly sure how much but it makes its own creatine.","offset":8113,"duration":10},{"text":"Dr. Rhonda Patrick: And it's kind of resistant to taking up the creatine that you're supplementing with, um particularly because for one the muscle is very greedy. So when you're getting to that 5 gram range muscles are really consuming it if you're working out in particular, right? Your muscles are kind of consuming that because that's they're very greedy for it, right?","offset":8123,"duration":19},{"text":"Dr. Rhonda Patrick: Uh and there have now been I think a handful of studies showing that when you start to get above that, there was a study out of Germany showing this and it's a small study. This needs to be replicated, like this is all new you know emerging data.","offset":8142,"duration":12},{"text":"Dr. Rhonda Patrick: But that study showed that once you start to get to you know 10 grams, then if you look by MRI you can start to see that creatine levels are increasing in certain brain regions and perhaps in the brain regions that you were talking about. And they're going higher than than what you would get from just your brain normally making its own creatine.","offset":8154,"duration":21},{"text":"Dr. Rhonda Patrick: So the 10 grams of creatine a day, which is now what my baseline is, is based off of that.","offset":8175,"duration":6},{"text":"Dr. Rhonda Patrick: But there's studies now showing that um if you're in this sort of stressed state, your brain is stressed, like first sleep sleep deprivation for example, you're sleep deprived for 21 hours, and your brain's not working very good after not sleeping for 21 hours, right?","offset":8181,"duration":15},{"text":"Dr. Rhonda Patrick: I mean that's obviously when I have a when I travel internationally I never really sleep good on a an international flight and so I'm like not if you were to come find me after that flight I'd be like not working very good cognitively, right?","offset":8196,"duration":13},{"text":"Host: You and everybody else.","offset":8209,"duration":1},{"text":"Dr. Rhonda Patrick: Right. Well some people can sleep great on a plane, but I'm not one of those people.","offset":8210,"duration":3},{"text":"Dr. Rhonda Patrick: So um there have now been at least one study showing that if you give someone it's like something like 0.35 grams per kilogram body weight of creatine, which comes out to a lot. I mean it's like 20 25 it depends on your body weight, right? Like 20 25 grams perhaps even more.","offset":8213,"duration":18},{"text":"Host: I mean I'm 100 kilograms, that's a lot of creatine.","offset":8231,"duration":1},{"text":"Dr. Rhonda Patrick: Yeah, so it would be a lot. So for me it's more like 20 25 grams, right?","offset":8232,"duration":4},{"text":"Dr. Rhonda Patrick: But if you give individuals that high dose in that you know sleep deprived state, that their cognitively not only performing normal, but they're performing better than their baseline.","offset":8236,"duration":13},{"text":"Dr. Rhonda Patrick: And that of course generated a lot of interest. There've been studies coming out since then showing that okay, if you give older adults with mild cognitive impairment perhaps mild you know early stage Alzheimer's disease again 20 grams, you're giving them the 20 gram range of creatine it's improving their cognitive function.","offset":8249,"duration":18},{"text":"Dr. Rhonda Patrick: Why is that? Well creatine is important to make energy and when your brain brain cells are stressed out, right? I mean like energy energetic demand goes up and if you have more creatine it's going to make things easier.","offset":8267,"duration":15},{"text":"Dr. Rhonda Patrick: There's also some inflammation that's being generated in that stressed state and it seems as though creatine is also...","offset":8282,"duration":13},{"text":"Host: Uh, I'm going to interrupt there. I don't think so. I'm not trying to just be complimentary. You know, I paid close attention to the data and it seems like in certain fields like math and physics, people tend to peak with their contributions early. There's a reason why the Fields Medal is only given to people, you know, like I think it's 40 or younger. My dad's a physicist, so he can check me on this one.","offset":8295,"duration":26},{"text":"Host: But biologists, at least the ones I know that took good care of themselves, they're known to make great discoveries, be cognitively sharp, intellectually strong well into their 70s and 80s. I mean Torsten Wiesel, who co-received the Nobel Prize for brain plasticity and vision, he's still alive and he... I think he still runs. He's in his late 90s. And he paints and he's sharp. So I just... I made a point to only interrupt here.","offset":8321,"duration":31},{"text":"Host: People can check the data on the previous portions of the podcast, but I actually think that cognitively, um, using biologists as an example, it's possible in aspects of life where you're building a base of data to pull from, which is what biology really is... just an example here... to get cognitively stronger and stronger with age.","offset":8352,"duration":23},{"text":"Host: Right. I... this is a theory, but I see you as that. And I'm again, I'm not just saying it to be complimentary, although it is a compliment. It seems like you're picking up steam, you're thinking about things you're not forgetting things from way back when, you're building on the concepts and knowledge from way back when. So I find it reassuring that biologists in particular seem to have this, you know, up-and-to-the-right trajectory for cognition.","offset":8375,"duration":25},{"text":"Dr. Patrick: It's interesting. My... my late mentor, Dr. Bruce Ames, was every bit of that. I mean, you know, he passed away a little over a year ago and he was 96. But, you know, some of his most... he claimed some of his best work was done, you know, in his late 80s.","offset":8400,"duration":13},{"text":"Host: Right. You don't see that in math or physics.","offset":8413,"duration":1},{"text":"Dr. Patrick: Yeah. So it's interesting. And you know, I don't know exactly the difference. I mean, I don't know how much learning goes into math and physics as you're... as you're... like, I just don't know. But like with biology and, I mean, we're constantly learning new things and reading new papers. And then I think even just the novelty of learning new things, I mean that's brain-derived neurotrophic factor, right? Like you're... you're... you're increasing synaptic connections and neuroplasticity and you're keeping your brain younger in that way too, right?","offset":8414,"duration":29},{"text":"Dr. Patrick: So, I think the learning process is super important whether it's biology or whatever you're passionate about, right? Like you learn new languages, whatever... like the learning process itself is something that is so important for brain aging as well. Um, and yeah, so I would agree with you. But brain aging in general, yeah, I mean, I'm obviously chronologically aging and there is some degree of aging going on in my brain.","offset":8443,"duration":24},{"text":"Dr. Patrick: But, you know, so that's I think where the creatine craze has come from is the interest in... and I've definitely played a role in some of this, you know, by talking about my experience and being super interested in it because it's felt good for me. And I've noticed this experience and this is completely anecdotal again.","offset":8467,"duration":21},{"text":"Dr. Patrick: But in addition with the small studies... and they are small. Like I don't know if you've looked at them, but they're... you can... you can poke holes in them...","offset":8488,"duration":10},{"text":"Host: Subject numbers and that...","offset":8498,"duration":1},{"text":"Dr. Patrick: Yeah, they're small sample sizes. But it is kind of a consistent trend line where we're seeing more studies come out and show the same thing, same thing. And it's like, okay, to a certain point, maybe there's something here. I think that more research is going to come out on it. And I feel great doing it. So I mean, and even to the point where if I don't have my 10 grams and it's only five, like I'll notice.","offset":8499,"duration":25},{"text":"Host: Oh, yeah?","offset":8524,"duration":1},{"text":"Dr. Patrick: Yeah, but again, it could be that placebo/nocebo thing where, who knows, who knows. But you know, let's just say it is real, you know, for me, I got to have... I got to have my 10 grams of creatine for my brain. Um, you know, who knows, I may in five years be like, I was wrong. We'll see new data come out, but I don't think so. I think we're going to have... I think this is like the next... a lot of people doing creatine research, it's the new thing. They're really because there's been a lot of work on exercise physiology and...","offset":8525,"duration":31},{"text":"Host: Yeah, the safety data are there, so it's not like they have to get a lot of, you know, human subjects clearance.","offset":8556,"duration":6},{"text":"Dr. Patrick: The safety data is there. The safety data is there. I mean, it's the most well-studied, you know, one of the most well-studied supplements out there. Like you said, you were taking it when you were 18 and it was studied back then. Yeah, and it's just been studied the, you know, for all the years that you've been taking it. So, I mean, if it was unsafe, like we'd really know. And again, I don't want to get into all the data on the safety, but I think that it's pretty solid that it's... now, of course, like if you're going to go like mainline 50 grams a day, I mean, I don't know, that's a little much...","offset":8562,"duration":31},{"text":"Host: Someone on the internet will do it. People dry... what are they? Dry scoop. I mean, people have died dry scooping energy drinks. I mean, there's always a moron or two out there that are going to take things to the extreme and harm themselves doing something that no one else is dumb enough to do. But I think we look at the center of mass for things.","offset":8593,"duration":20},{"text":"Host: You know, as we're talking about creatine, I want to talk about some other supplements, but it occurs to me that if there's some data, ideally from animal studies and humans, and something is safe, I think the question nowadays because of how broadly health and supplement and other kinds of information goes in the world... I think the question that everyone should ask themselves is, okay, do I want to be in the experimental or the control group?","offset":8613,"duration":29},{"text":"Host: That's how I think about it. So like, if there's a study about creatine, or some new molecule... I'm going to ask you about magnesium in a moment, right? Um, I look at the safety margins on magnesium... okay, that... I'm comfortable with those safety margins. So that should always be question number one. And then it's, do I want to be in the experimental or the control group?","offset":8642,"duration":21},{"text":"Host: And I think that these days people are who are against supplements or against something, they'll say, well, the effect isn't nearly as big as you get from exercise. Totally, absolutely. But that's not really what we're talking about. People love this in the cannabis and alcohol thing. Whenever I make a point about alcohol or cannabis, they'll say, well, alcohol's worse. I'm like, yeah, like, and? You know, I mean, these are two separate entities.","offset":8663,"duration":27},{"text":"Host: So I think that people should just ask themselves, are you comfortable with the safety margins and do you want to be in the experimental or the control group? And then, of course, there's the, can I afford to be in the experimental group if I do something? But those are really the only questions. No one's saying that creatine's better than anything else or worse than anything else.","offset":8690,"duration":22},{"text":"Dr. Patrick: Right.","offset":8712,"duration":1},{"text":"Host: But somehow the messaging gets all messed up. And then all these news articles get generated about what creatine is and it isn't. And I find it like, um, kind of frustrating because that's... the issue is not whether or not creatine is better than exercise and good sleep. Question is, do you want to be in the experimental or the control group and can you afford to be in the experimental group?","offset":8713,"duration":27},{"text":"Dr. Patrick: Right. I like that. I like that framework, especially if it's like, well, we know it's safe. Okay, so I can potentially be in the experimental group because that's question number one you have to have that answer first, right? At least in my book. But yeah, I mean, there's flaws with all sorts of studies, and creatine studies included, right? And people make all sorts of claims about it. And you know, you got to tone it down a little bit. I mean, it's not like the best performance enhancer ever. But it seems pretty good at, you know, improving exercise volume, recovery as well. I mean, that's also something that's been shown. And then helping with the stressed-out brain.","offset":8740,"duration":37},{"text":"Host: On the basis of our last conversation some years ago on this podcast, I started taking Lovaza, which is a... as you know, a prescription Omega-3. So very high concentration Omega-3 because I was getting it from, you know, standard sources and I thought, well, I'm hitting 50 and my Omega-3 and I want clean Omega-3, I don't want it contaminated with mercury and other things. So I'll take Omega-3s in the form of Lovaza. It's available generically now so it's pretty inexpensive. And I have to say my blood profiles were pretty good, but they improved pretty dramatically when I started taking Lovaza. So I'm grateful to you for encouraging the Omega-3 path.","offset":8777,"duration":44},{"text":"Dr. Patrick: Have you ever had an Omega-3 index test done?","offset":8821,"duration":3},{"text":"Host: No.","offset":8824,"duration":0},{"text":"Dr. Patrick: To measure the...","offset":8824,"duration":1},{"text":"Host: Oh, oh, if it's on the function test, then it would be in normal range. I know it wasn't flagged, but I don't recall what the what the level was.","offset":8825,"duration":9},{"text":"Dr. Patrick: Yeah. You want to be in the high index, not the low, right? Well, obviously if you're taking it, you're not going to be in the low. Usually it's around 2 grams a day to get you from low to high. And I do think that's one of the low-hanging fruits in terms of like something powerful and having an outsized effect on your health that people can do that's not that much effort. It's not like exercise. Exercise is effort.","offset":8834,"duration":23},{"text":"Host: Or eating salmon. I don't like fish.","offset":8857,"duration":2},{"text":"Dr. Patrick: No. Yeah, and you know, a lot of people don't like fish and also there's now microplastic contamination in our seafood sources. There's the heavy metal, PCBs, contaminants. I mean, I still eat salmon, but like, you know, it's not like it used to be. So there are other cleaner ways to get your Omega-3 levels higher. And Omega-3 is very important for cardiovascular... it's one of the most important, I would say the most powerful naturally occurring dietary compounds for suppressing inflammation and resolving inflammation would be a better way of putting it, right?","offset":8859,"duration":34},{"text":"Dr. Patrick: I mean, and that's, again, at the core of aging. And if you look at any sort of measure of aging, whether it's even these epigenetic aging clocks, they're very sensitive to inflammation and that's why there's so many studies coming out now showing Omega-3 can slow this biological aging as measured by these epigenetic aging clocks. And that's I think even in randomized controlled trials showing this that it's doing that.","offset":8893,"duration":28},{"text":"Dr. Patrick: And that leads to functional outcomes as well. So like even if you're only slowing the clock, let's say by three months, um, you're still having outcomes like where, for example, three months slowing the epigenetic aging clock by Omega-3 only is going to get you like, you know, 16% lower pre-frailty. Or if you add in Vitamin D and resistance training because a study showed a synergy between the three, then you're talking about like lowering the chance of invasive cancer by 66%.","offset":8921,"duration":30},{"text":"Host: 66%?","offset":8951,"duration":1},{"text":"Dr. Patrick: Yeah.","offset":8952,"duration":1},{"text":"Host: So Vitamin D, resistance training, and Omega-3.","offset":8953,"duration":2},{"text":"Dr. Patrick: Yeah. And this was... this was... the trial was actually out of Switzerland, I believe. And it looked at Omega-3, Vitamin D alone, or resistance training alone. And the only thing that actually slowed the aging of the clocks was Omega-3. Now, I'll say that with a caveat, okay. The baseline exercise in this Switzerland group, 88% of these people were physically active, like doing exercise. So adding, you know, 30 minutes, three times a week of resistance training on top of that didn't slow the clock more. And I wouldn't expect it to, to be honest, when you're already physically active and that's your baseline.","offset":8955,"duration":40},{"text":"Dr. Patrick: Clearly they weren't eating enough Omega-3 because that did slow the epigenetic aging clock. Other studies have shown if you're vitamin D deficient, severely vitamin D deficient, like African Americans for example, who are obese or overweight, if they add in Vitamin D and supplement with 4,000 IUs a day for six weeks, they can actually slow their epigenetic or reverse their epigenetic aging as well. So I think it again, it's all like where you're starting from.","offset":8995,"duration":31},{"text":"Dr. Patrick: But the point is that the Omega-3 alone did slow the aging of these clocks. Um, you add in the resistance training and vitamin D, those alone didn't do it, but when you add it with the Omega-3 there was synergy. So it kept going down. And when the three combined, it slowed the epigenetic aging by like 3.8 months. But that translated to like 66% less likely to get invasive cancer. Um, and then the pre-frailty was the Omega-3 alone and there was another marker I can't remember, I covered this in a newsletter a while back.","offset":9026,"duration":36},{"text":"Dr. Patrick: But like, you know, this and this isn't the first study to show this with Omega-3. Um, Omega-3s are really... I'm so sorry, Andrew, you got me on one of my favorite topics.","offset":9062,"duration":10},{"text":"Host: No, no, it's great. I mean, I'm excited because I take Lovaza, I take Vitamin D D3. I take a lot. I take 5 to 8,000 IUs per day and I get sunlight. People actually ask me, this is just a quick window into the messaging around sunlight... some people will say, if I take Vitamin D do I still need sunlight?","offset":9072,"duration":22},{"text":"Host: And you know, a big part of my messaging is trying to tell people sunlight does a bunch of other things, but I take Vitamin D at that level, I take the Lovaza, and of course I resistance train. And the Lovaza move, and actually increasing the Vitamin D, was on the basis of, yes, blood work but also our prior conversation. I feel much better. Much better.","offset":9094,"duration":25},{"text":"Dr. Patrick: Yeah. I take about 5,000 IUs a day as well. And I do get sunlight. And I agree with you, sunlight's important for... sunlight's not in Vitamin D production is not the only thing that sunlight is doing, obviously. You've talked in great depth about that.","offset":9119,"duration":17},{"text":"Host: I'm going to go into the grave... I actually want a little window over my grave, it'll be a little macabre, so I can get morning sun. I'm just kidding folks. When I'm in the ground, I'm in the ground. No, I think the Omega-3 literature has been greatly assisted by your messaging around it because it got pretty confused out there for a while. There was the usual pushback that comes after supplement of the year is released... it's a joke folks... is the, \"Oh no, it's actually bad for us.\" You know, there's always a few of those. And then we eventually arrive at sanity again and go, no, the bulk of studies point in the direction of this being healthy.","offset":9136,"duration":39},{"text":"Dr. Patrick: Right. Randomized controlled trials showing it improves cardiovascular health, lowers the incidence of cardiovascular events including heart attacks and strokes, right. These are the gold standard. We've got the observational data. We have now looking at the molecular events... epigenetic aging. We know that it's really good at resolving inflammation. Because you want your immune system to be active, but you don't want it to be overactive. You want it to be active and then turn off, right.","offset":9175,"duration":33},{"text":"Dr. Patrick: And so the Omega-3 fatty acids like DHA and EPA which are in Lovaza are what the metabo- they're when they're metabolized, they're forming these molecules: resolvins, protectins... these things are resolving inflammation. And so I think that it's just it's one of the easiest ways that you can you can increase your anti-inflammatory response. And exercise obviously being another very powerful one.","offset":9208,"duration":29},{"text":"Dr. Patrick: But the Omega-3s, it's always easier to take a supplement and so like I have my parents taking it, you know, anyone that I care about it's like, you know, easy, easy, done. You know, take your 2 grams a day. I say 2 grams a day because Lovaza is prescribed at 4 grams a day. You know, so 2 grams is pretty on the conservative side, and that's really what's been shown by Dr. Bill Harris and some of his colleagues that can basically you can take someone from a low Omega-3 index of 4% up to a high Omega-3 index of 8% by supplementing with about 2 grams a day.","offset":9237,"duration":40},{"text":"Dr. Patrick: So, and by the way, there's all sorts of data on that front with the Omega-3 index and I think we talked about this last time, but you know, five-year increase life expectancy if you're on the high end. You're talking about 90% reduction in sudden cardiac death. Brain weight in children if pregnant women are taking... yeah. Yeah.","offset":9277,"duration":23},{"text":"Dr. Patrick: I mean, it's important throughout the lifespan. It's, you know, from in utero development throughout childhood all the way through adult life and into old age. You know, these Omega-3 fatty acids are... I'm talking about the resolving of inflammation, but they're also very important for they're incorporated into our cell membranes. DHA and to some degree EPA.","offset":9300,"duration":21},{"text":"Dr. Patrick: And that has a very important role in the fluidity of our cell membranes. And this is important for if you think about our endothelial cells lining our vascular system, our arteries, you want them to be fluid and more flexible, right. That's very important for being able to respond to a stressful situation. In fact, the stiffening of our heart with age, you know, the collagen that's surrounds our pericardium that's surrounding our heart, our myocardium... like that's that increases the risk of a heart attack, you know, a cardiovascular event. You want your cells to be more flexible.","offset":9321,"duration":39},{"text":"Dr. Patrick: So that's what, you know, these Omega-3s are also doing. That's why they're also really important for cardiovascular health in addition. And the brain as well. I mean, all of our transporters, all of our our receptors, right, they're embedded in the cell membrane. And the fluidity of that membrane is important for the structure and function of these things.","offset":9360,"duration":20},{"text":"Dr. Patrick: And that's why Omega-3 affects dopamine, serotonin, right? It's why it's affecting- it's not the only reason inflammation is also, but part of the reason is because it's changing the way our cell is like, you know, structurally composed. And if you think about trans fats, like they do the opposite, right. They stiffen the cell membranes. And that's why it's like the worst thing you could do for your cardio- one of the worst things that you could do for your cardiovascular health is eat a bunch of trans fats. Smoking is another one, smoking's terrible for your cardiovascular health.","offset":9380,"duration":31},{"text":"Host: Do people still eat trans fats?","offset":9411,"duration":2},{"text":"Dr. Patrick: No, I think they're banned.","offset":9413,"duration":1},{"text":"Host: I feel like trans fats got executed in 20- when was it that trans fats got executed?","offset":9414,"duration":4},{"text":"Dr. Patrick: When they all became... I think it was 2018 when they all were like...","offset":9418,"duration":4},{"text":"Host: Yeah, they were sentenced to death.","offset":9422,"duration":2},{"text":"Dr. Patrick: No, it's- the point is that we all know trans fats are bad for our heart, but we don't think about why. And the researchers doing it know, I mean it stiffens your cell, your endothelial cells.","offset":9424,"duration":12},{"text":"Host: With donuts, right? As in like if you go get a donut, isn't a donut have a bunch of fried food?","offset":9436,"duration":5},{"text":"Dr. Patrick: There's pro- probably some amount of trans fat that's like below the threshold of being...","offset":9441,"duration":7},{"text":"Host: It's the only bad food I miss. The late-night donut.","offset":9448,"duration":4},{"text":"Dr. Patrick: I had so much margarine as a kid. My mom used to buy it by the tub, I remember. It's like this she used to go to Costco and get like this big yellow tub of margarine. I remember those tubs. And everything was cooked in it and I mean it was like on our toast and...","offset":9452,"duration":14},{"text":"Host: This was a battle in my home. Actually, I'm going to resurrect some family battles. The butter-margarine battle was a battle. Butter won.","offset":9466,"duration":11},{"text":"Dr. Patrick: Yeah, it doesn't taste the same. But you know, that was the craze, it was the low fat like the fat was bad and butter was bad and margarine was good. And it turns out, no, trans fats are really bad. Um, but the point I was trying to make was to help contrast for people to understand sometimes when I talk cell fluidity people are like, what?","offset":9477,"duration":18},{"text":"Host: No, it's good that people... I mean, I think it's very important that people understand some of the cellular molecular underpinnings of protocols because I strongly believe that understanding mechanism, even just a little bit, or striving to understand it embeds the information for people, makes it more likely that they'll do the behaviors and gives them a logic to work from when they have to make choices because life isn't perfect. That's... I know that to be certain.","offset":9495,"duration":28},{"text":"Dr. Patrick: I completely agree with you. It's certainly for me, but I hope that if people kind of understand somewhat of the why, it's motivating to try to adopt the healthy habit, but also I think it helps them remember like why it's important, right.","offset":9523,"duration":16},{"text":"Host: And it's how the brain learns. It's the secret is context. Way to remember something is context. People always say, \"It's stories.\" No, it's context. And anyway, you and I know that to be true from our background.","offset":9539,"duration":16},{"text":"Host: If I may, I'd like to ask about magnesium. I'm very bullish on magnesium, in particular Magnesium Threonate before sleep. For sleep, I take AG-Z because I helped them build it. It just has a bunch of things like Magnesium Threonate and Saffron and Tart Cherry, the things that um have either been shown or are, you know, gradually amassing research data... the other people... studies out there to support that it can facilitate either transition to sleep or sleep, but Magnesium Threonate and Magnesium Bisglycinate to me are interchangeable with respect to sleep.","offset":9555,"duration":41},{"text":"Host: But Magnesium Threonate, I'm aware there's some studies that maybe there's some cognitive benefit. So magnesium obviously could be split into a number of things, but maybe we just start there with Threonate, Bisglycinate. I have a feeling that you're aware of some additional differences between them and I'd like to know what you prefer for sleep or for cognitive benefits and then maybe we get into the other magnesiums.","offset":9596,"duration":23},{"text":"Dr. Patrick: Yeah. I think so if we if we're comparing Magnesium Bisglycinate or Magnesium Glycinate depending on how many molecules of glycine are attached to the magnesium compared to Magnesium L-Threonate. Um, the main difference here and this is based on very limited amount of data, a lot of it animal data with respect to the Magnesium Threonate, is that that form of magnesium is supposed to get into and cross the blood-brain barrier more readily and get into the brain better.","offset":9619,"duration":35},{"text":"Dr. Patrick: And in the brain, it's you know helping facilitate neurotransmission, etc., right, helping improve cognitive function. So whereas Magnesium Glycinate or Bisglycinate, you're having the magnesium attached to the glycine... glycine also is great to take for sleep. So I like to take Magnesium Bisglycinate or Glycinate for sleep. And so that I would say if you're if you're interested in more the cognition aspect...","offset":9654,"duration":31},{"text":"Host: Well, the studies I think you're referring to, the Guosong Liu's data... you know, show some in mice, some cognitive enhancement or at least some offsetting of cognitive decline. Those are different but related, obviously. In anticipation of today's discussion, I was able to find one study seems okay, it's not a huge sample size, showing a positive reports on sleep quality after Magnesium L-Threonate.","offset":9685,"duration":36},{"text":"Host: So the studies are starting to show up. But there aren't a lot of studies on magnesium for specific outcomes in humans. And I think it's because it hits like what, 3,000 plus pathways?","offset":9721,"duration":14},{"text":"Dr. Patrick: There's a lot of pathways. Yeah. It's a cofactor for many enzymes.","offset":9735,"duration":4},{"text":"Host: So if you're taking Bisglycinate before sleep, are you taking it half hour or 60 minutes before sleep?","offset":9739,"duration":6},{"text":"Dr. Patrick: I'm usually taking it I would say like a couple of hours before bed. You know, sometimes I add a little bit more magnesium in the mix, depends on the day and if I exercise more because you do sweat out magnesium. And so if you're pretty athletic, your requirements can go up by even as much as 20%.","offset":9745,"duration":19},{"text":"Dr. Patrick: But yeah, the Magnesium L-Threonate, it's interesting I very recently got interested in experimenting with it. You know, there's a little bit of human evidence as well that it improves cognition, not strong, but again, it's that you know we just don't have a lot of people researching it. And we have the animal data, the animal data's a little stronger, don't have a lot of human data, but it seems to signal it might be important, it might help with cognition, right.","offset":9764,"duration":27},{"text":"Dr. Patrick: And so I kind of got interested in experimenting with the Magnesium L-Threonate, which I haven't usually- that it's a new thing for me. I've been doing Magnesium Glycinate for a while.","offset":9791,"duration":10},{"text":"Host: I think the study actually looked at the Magtein... Yes, I have no financial relationship to Magtein, I only want to be very clear. I just mentioned that because that's a common one out there. And as far as I know, I'll double check, but they weren't paid by Magtein, but...","offset":9801,"duration":14},{"text":"Dr. Patrick: I think the Magtein did fund the study.","offset":9815,"duration":2},{"text":"Host: Oh, they did?","offset":9817,"duration":1},{"text":"Dr. Patrick: Yeah.","offset":9818,"duration":1},{"text":"Host: Okay. All right. Well, we'll put a link to it.","offset":9819,"duration":2},{"text":"Dr. Patrick: Doesn't discredit it. Unless unless there's some, you know, bad things going on which I like to think not. I mean, you know, it's supposed to be done independently, I mean, when they pay for a group to do- I mean by law they're supposed to blind the data and not bias the outcome. I mean, that's what one hopes that's what they do.","offset":9821,"duration":15},{"text":"Host: Yeah.","offset":9836,"duration":1},{"text":"Dr. Patrick: Yeah. And I think to the most part, you're probably okay, but it is something to consider if there is a potential COI, right. Um, but yeah, so I don't know. So that was the first part of your question was the difference between the Glycinate and Threonate. And then the concern that I might have, which might be something you're not thinking about is, okay, well, I need to fulfill my magnesium requirements, right?","offset":9837,"duration":22},{"text":"Dr. Patrick: And so our daily magnesium requirements, again based on our gender and our physical activity, it's a range, it's a sliding scale. So you know women 300-350 milligrams a day, men 350-400 milligrams a day, really depending on how physically active you are. And this is just, you know, your daily requirements to have enough magnesium to run repairing DNA damage, to run you need magnesium to make energy to utilize energy, you need it for neurotransmission... like it's there's so many different important functions in our body that require magnesium to work.","offset":9859,"duration":37},{"text":"Dr. Patrick: To make Vitamin- to convert Vitamin D3 into the active steroid hormone. And this, this to me is like to some degree vindicating, but also I'm super annoyed by it because you know we have all these different studies out there on Vitamin D supplementation and is it important? And I mean there's so many negative data out there, well it doesn't do what we thought it's not doing anything.","offset":9896,"duration":28},{"text":"Dr. Patrick: But half the US population doesn't get enough magnesium. And so those enzymes that are important for converting the D3 that you're taking into the active steroid hormone are not working properly. Um, so anyways, I'm not going to go on that tangent, but I'm just saying magnesium is doing a lot of things. So if you are taking the Magnesium Threonate and let's say it is getting into the blood- sorry, the brain more readily, then the concern would be well then not enough of it is around for you know DNA repair in other organs and stuff. And so you might want to get another source of magnesium. It's all theoretical, right, and like that's not I would- there's no data on that. So just mostly because no one's looking at it. No one's investigating it.","offset":9924,"duration":47},{"text":"Host: Yeah. Not a lot of incentive. It's funny when people will always say, well, there's no incentive because the drug companies can't make a lot of money on it. And I sometimes that's true. But I have to chuckle because as a scientist, I will tell you folks, and- like I wish I could just like paint this across the sky, but then I'd get accused of being like a chemtrail person or something. Um, the reason there's no studies on BPC-157... the reason there's no like RCTs on a randomized control on different forms of magnesium and large sample size is because we barely have enough money to fund the current research.","offset":9971,"duration":40},{"text":"Host: Like, I- I'm not trying to get make this political, like we just had a 1% increase in the NIH budget but like there isn't an infinite amount of money to run studies. And so scientists are if they already work on magnesium or or it becomes interesting to them because it came up in a screen of pathways, people aren't- there are not a lot of scientists sitting around going, \"Oh, like maybe I should study- compare Magnesium Malate, Bisglycinate, Threonate in sleep in 2,000 subjects male, female like pregnant and perimenopausal...\" like, no, no, there's no money to do it.","offset":10011,"duration":33},{"text":"Host: So that's where I get back to: is it safe, do you want to be in the experimental or the control group, can you afford to be in the experimental or the control group? Yeah, I feel like that's like all we've got. And I'm only I'm chuckling out of it's a sort of like a laughter of pain because I get where people are coming from, but the drug companies are not like avoiding studying magnesium because there's no money to make, it's because what would that even look like? What endpoint, what disease?","offset":10044,"duration":32},{"text":"Dr. Patrick: Yeah, anyway. You're not going to cure you know cardiovascular disease or cancer by taking a magnesium supplement. I mean, the- these nutraceuticals, these vitamins and minerals, they're they're about prevention, really. And and and giving your body the right nutrients that it needs to do and function properly. You know, whether that is getting enough sleep... you know, when you're when you're stressed, when your cortisol goes up chronically, you're depleting magnesium. You know, it's it's- it's very like magnesium's being used to deal with that stress, right.","offset":10076,"duration":34},{"text":"Dr. Patrick: So there there's a reason that we need things like magnesium and you know, Vitamin D, it gets converted into steroid hormone changing 5% of our you know our genome. So it- yeah, it's different. It's not like a pharmaceutical where you're you don't need this you know to function optimally but it- it's the whole like, okay, I'm sick and now I need this you know or I'm overweight, right, we got the GLP-1s, right, I'm fat, I'm obese, and I need to you know help fix that. And so that's kind of a different paradigm than specific endpoint type stuff.","offset":10110,"duration":40},{"text":"Host: Yeah, exactly. Yeah. I think that's super important for people to hear that. Oh, by the way, I should just say uh for your for your sake um and for the listeners, I divide supplements into basically four categories: food replacement, like whey protein or a protein bar, obviously. Sort of general support, specific effects, and then experimental maybe.","offset":10150,"duration":33},{"text":"Host: And so I think what we're talking about here with magnesium is kind of combination of maybe helps with sleep, um specific effects that you're aware of like required and you're trying to top off, you're trying to make sure that you're covering a deficiency.","offset":10183,"duration":16},{"text":"Dr. Patrick: Yes. Yeah. You're trying to make sure you're getting enough of the magnesium, exactly.","offset":10199,"duration":5},{"text":"Host: Are there any other things that you take that are just trying to make sure that you're not deficient anywhere, um or for specific reasons? We've talked about a few along the way here: Glutamine, Vitamin D, Omega-3s, Creatine.","offset":10204,"duration":14},{"text":"Dr. Patrick: I take a multivitamin and that is to cover my bases because, you know, there's there's a lot of things in a multivitamin. You have to find a obviously a good quality one. But, um, and anyone that tells you that multivitamins are useless, they're wrong. I'm going to tell you that, they're wrong. Because I think now we have pretty strong data, three very large randomized controlled trials part of the Cosmos trials... have you heard of these studies?","offset":10218,"duration":42},{"text":"Dr. Patrick: And it's really I think pretty clear that in these studies, older adults, so we're talking 65 years and older that are taking a multivitamin supplement for, you know, was it a year, I think it was. Um, it could be two but I think it was a year. And it was by the way, Centrum Silver. It was like your standard, you know, anyone could afford to get it at Walmart type of vitamin.","offset":10260,"duration":24},{"text":"Dr. Patrick: Um, and after a year of taking this multivitamin, it globally reduced brain aging by about 2.1 years, from three trials globally reduced brain aging by 2.1 years. Battery of tests that are done, right. I mean it's you know I'm just talking about general here. And it also reduced episodic brain aging by 4.9 years.","offset":10284,"duration":25},{"text":"Dr. Patrick: So that would be, you know, as people probably already are familiar with that listen to this podcast, you know episodic memory, that's the part of memory that's involved in like remembering events and and people and like experiences... am I right?","offset":10309,"duration":14},{"text":"Host: Yes, sequence of things.","offset":10323,"duration":1},{"text":"Dr. Patrick: Sequence of things. Yeah. And so, you know, that's a big effect for just a daily multivitamin, you know. And so for that reason, you know, I mean I've been taking it before these these studies came out, but my parents, you know, anyone that's older adult should be taking a multivitamin. So that's another one that I take. Um, and I take it to cover my bases as well and obviously not an older adult and who knows it might not have the same effect on me, but um, you know, it's one of those that it's it's not harmful if I'm you know it's a little bit of an expensive urine, fine, but I know it is covering some of my bases in terms of some of the micronutrients in it, right.","offset":10324,"duration":46},{"text":"Dr. Patrick: The other ones that I take in besides the one that you mentioned, which is Vitamin D, Omega-3, I do Creatine, Magnesium. I do Magnesium Glycinate. I should look into the Bisglycinate because I definitely would like another molecule of glycine, I like it for my sleep.","offset":10370,"duration":17},{"text":"Dr. Patrick: But I also sometimes take another form of magnesium, which is it's like a mixture of Magnesium Malate and Threonate I think are the main- and Glycinate is also in that. But sometimes I take that for sleep. And then I take Ubiquinol, um, for mitochondrial health.","offset":10387,"duration":24},{"text":"Host: You like the data on that? Obviously if you're taking it.","offset":10411,"duration":3},{"text":"Dr. Patrick: It's- there's stronger data I think on Ubiquinone, which is the oxidized form, it's more stable. There's just when I say stronger I mean more data.","offset":10414,"duration":11},{"text":"Host: Do you take Coenzyme Q10? Co- Q10, excuse me.","offset":10425,"duration":3},{"text":"Dr. Patrick: So Co- CoQ10 is Ubiquinol.","offset":10428,"duration":2},{"text":"Host: Okay.","offset":10430,"duration":1},{"text":"Dr. Patrick: Yeah. And so and so I'm taking the reduced form of it which is Ubiquinol, the the more stable form would be Ubiquinone.","offset":10431,"duration":7},{"text":"Host: Are those trademarked names? because I take Coenzyme Q10. I'm guessing if I took a closer look at the bottle I'd see the Ubiquinone...","offset":10438,"duration":8},{"text":"Dr. Patrick: It's Ubiquinone, yeah. Ubiquinone. The Ubiquinol is a little bit more bioavailable, but yeah. So I'm pretty convinced that that helps with mitochondrial function. Um, you know, it's not like you could always have more data, right? So we'll just leave it at that.","offset":10446,"duration":19},{"text":"Dr. Patrick: The other one I take is now I'm taking Urolithin A in the form of Timeline. I'm taking Mitopure, by the way I have nothing to do with these companies. But there's now I've just been over the years increasingly interested. So Urolithin A is something that is formed from a type of polyphenol that's found in some fruits, um like pomegranate being the main one. I think raspberries may also have some, I think walnuts also, but it's ellagitannin is the polyphenol.","offset":10465,"duration":32},{"text":"Dr. Patrick: And these ellagitannins get metabolized by the gut microbiome and the metabolites that are formed, one of them is called Urolithin A. And so Urolithin A is a compound that seems to stimulate the process of mitophagy, which is a very specific form of autophagy that's that's only for mitochondria.","offset":10497,"duration":26},{"text":"Dr. Patrick: And you know that's been shown in- there have been randomized controlled trials showing this in humans. It does stimulate mitophagy um blood cells as well as a muscle biopsy. But that's a an important cleanup process for for how our mitochondria repair themselves. There's no repair enzymes, right, like they're you know part of that repair process is mitophagy where they're getting rid of selectively can get rid of parts of a mitochondria that are damaged. So it's really like a rejuvenation.","offset":10523,"duration":31},{"text":"Dr. Patrick: And some of this the clinical data I would say is emerging, more needs to be done, but it seems to in some cases improve endurance performance, which makes sense because they rely heavily on mitochondria, but even also um help with the immune system and this whole inflammaging. So it helps keep immune cells, it seems like it's helping keeping immune cells quote-unquote younger. So again, emerging data, but it's I'm in that I'm like I'm the experiment group. It seems to be safe and I'm not taking too high of a dose. So that's another one that I'm supplementing with.","offset":10554,"duration":51},{"text":"Dr. Patrick: The other one that I'm taking also is uh a very- of a form of, I'm going to call it Sulforaphane, but it's not Sulforaphane, it's the precursor to Sulforaphane, glucoraphanin because that's more stable. And so I take something called Avmacol, um, which the reason I take that one is because there's oh it's 13 now and a new study just came out 13 studies using that that form.","offset":10605,"duration":23},{"text":"Dr. Patrick: Um, and Sulforaphane is also one of those plant phytochemicals. It's formed- it's found in cruciferous vegetables as you know we've talked about this before, so I'll I'll try to leave it make it brief. But um, so glucoraphanin is in in these cruciferous vegetables like broccoli, broccoli sprouts are really really great source of it. And it- when the plant is crushed, you know like when you eat it, eat broccoli or chew it, whatever, an enzyme is activated that converts glucoraphanin into Sulforaphane.","offset":10628,"duration":31},{"text":"Dr. Patrick: The reason I take it is because I've been now convinced by I would say the limited number of human studies, clinical studies, but also the totality of evidence looking at cruciferous vegetables in general and then also animal data, that um it's really important. It's probably the the best naturally occurring dietary activator of a stress response pathway that is important for detoxification. And that that pathway is the Nrf2 pathway. I'm sure you've heard of that pathway.","offset":10659,"duration":33},{"text":"Dr. Patrick: Sulforaphane is a very very powerful activator of that pathway and what I mean by pathway is that gene is turning on and turning off many many other genes. What we know about it is that it's very important for activating the the detoxification genes that are involved in detoxifying things that are that are harmful to us.","offset":10692,"duration":21},{"text":"Dr. Patrick: And so the classic studies that have been done, some of them most of them in China where air pollution is very high, is that if you take, you know, this broccoli sprout Sulforaphane extract, you can start to excrete compounds that are found in air pollution like benzene that are carcinogenic, right, and you can start to excrete it after 24 hours by like 60%.","offset":10713,"duration":26},{"text":"Host: Great. What about plastics?","offset":10739,"duration":1},{"text":"Dr. Patrick: So that's my- that's my thing. That's why I'm taking it, my whole family. Because the same enzymes that are activated by um by the the Sulforaphane that detoxify benzene... so basically you're detoxifying it what I mean is you're basically making it water-soluble so you can excrete it through urine.","offset":10740,"duration":23},{"text":"Dr. Patrick: Okay. The same ones, that's exactly what BP- the those enzymes do to BPA. They make it water-soluble and help you excrete it through urine. There's no human data showing this yet, I want someone to do the study. But we do have animal evidence where, you know, animals are given a high dose of BPA and Sulforaphane and it protects against the toxicity.","offset":10763,"duration":26},{"text":"Dr. Patrick: I basically think that it's someone's going to show it and it's going to be clear because the the enzymes that are, you know, involved are activated by this, you know, by Sulforaphane and that's been shown with benzene and acrolein excretion, right. So why wouldn't it be BPA? Never know.","offset":10789,"duration":14},{"text":"Host: The mechanistic logic is there.","offset":10803,"duration":1},{"text":"Dr. Patrick: Yeah, yeah, exactly, exactly. So that's another reason why also it increases glut- it's been shown in human studies to very powerfully increase glutathione in both the plasma and the brain. And that's also through the Nrf2 pathway. It activates the powerful antioxidant pathway.","offset":10804,"duration":19},{"text":"Dr. Patrick: It also deactivates phase one biotransformation enzymes that are involved in um turning a pro-carcinogen into a carcinogen. So those are things like you're eating, you know, you're grilling your meat at a high temperature and you're getting heterocyclic amines, right. I mean these these things can be harmful.","offset":10823,"duration":23},{"text":"Dr. Patrick: But our body can deal with it and we had a cancer doc on here recently and I was scared to ask him the question because I didn't want the answer, but I did want the answer of, you know, the char on meat and he's like it's pretty pretty serious carcinogen. That's real. I mean the occasional thing isn't going to be a problem.","offset":10846,"duration":19},{"text":"Host: You'll be relieved to know and this is not a promotional that the can that you're drinking out of, these are intentionally BPA, BPS, and PFAS-free. We had- we had that tested. We'd be happy to send you the results.","offset":10865,"duration":12},{"text":"Dr. Patrick: I already know, I already knew about that.","offset":10877,"duration":2},{"text":"Host: Yeah. Because I know that you and I are both- I am wary of of the BPAs and um and the rest. I think it's wild that 10 years ago people like Charles Poliquin were saying, \"Don't handle receipts.\" and you know, and everyone's like, \"This is really kooky.\" or actually back then no one even heard what he was saying it was such a niche thing.","offset":10879,"duration":21},{"text":"Host: Then people were very I think disparaging of people saying beware of receipts. Now I think um the microplastics um and the BPA BPS um PFAS concern is is really taking hold more broadly and I think that, you know, the tables have turned.","offset":10900,"duration":20},{"text":"Dr. Patrick: Yeah. And really obviously you can't eliminate them completely. It's impossible. They're everywhere. They're everywhere.","offset":10920,"duration":6},{"text":"Host: Clothing I heard was the main...","offset":10926,"duration":2},{"text":"Dr. Patrick: It's the main source of microplastics in the ocean, right, because our wash- we're washing our clothes and there's they're like this shirt that I'm wearing. I mean, it's it's got microplastics in it for sure. Um, and and so every time you're washing your clothes you're all the microplastics are coming out and getting into the ocean.","offset":10928,"duration":21},{"text":"Dr. Patrick: And also then when you put your clothes in the dryer and if your dryer is ventilating anywhere in your house, the microplast- you're breathing those in, the microplastics.","offset":10949,"duration":8},{"text":"Host: They sell these traps. When I did the episode on microplastics I found out that online you can, I think it costs, it's not cheap cheap, but it's like concerning they last a while. I think they're somewhere with refill somewhere in the neighborhood of I want to say something like $70, but it traps supposedly traps the microplastics in the wash- in the washing machine. And in Europe I think this is actually built in or is required in an- in a number of countries. Like they're way ahead of us.","offset":10957,"duration":30},{"text":"Dr. Patrick: They're always...","offset":10987,"duration":1},{"text":"Host: They're way ahead of us on a number of things. I mean, on a few things they're really they're far behind, I must say with respect to health, but on on many things they are way ahead of us.","offset":10988,"duration":11},{"text":"Dr. Patrick: Yeah. Well, clearly with the Switzerland people in Switzerland being 80% like 88% of them being physically active, they're way ahead of us on that.","offset":10999,"duration":7},{"text":"Host: I'm excited to share with you that Martina, the yerba mate drink that I helped create, is now available at Sprouts Market nationwide. Longtime listeners of the Huberman Lab podcast know that yerba mate is my preferred caffeine source. It provides a smooth energy lift without giving you the jitters, and it has many other benefits such as helping regulate blood sugar, improving digestion, mild appetite suppression, and more.","offset":11006,"duration":29},{"text":"Host: Martina is my absolute favorite of all the yerba mate brands out there, and believe me, I've tried them all. The flavors are fantastic. I drink at least three cans of Martina every single day. You'll often see them on the table during our podcast recordings. I absolutely love the product and I'm proud to now have it sold at Sprouts Market.","offset":11035,"duration":24},{"text":"Host: Also, there's a great new offer. They are giving away a free can of Martina to anyone who buys it at Sprouts and sends in a photo of their receipt. To learn more about how you can get a free can of Martina, go to drinkmartina.com/offer. Again, that's drinkmartina.com/offer to get a can of Martina for free at your local Sprouts Market.","offset":11059,"duration":25},{"text":"Host: What is your threshold for you and what do you think is kind of reasonable levels of what's actionable for you? Like, how do you set that? I think it will help people kind of understand how you're approaching stuff.","offset":11084,"duration":17},{"text":"Dr. Patrick: What's actionable in terms of improving what I'm interested in improving my health like or...","offset":11101,"duration":6},{"text":"Host: Yeah, like I mean, without picking any specific example, like when you look at the literature and you see, let's say let's take BPC-157, it's kind of a fun one because everyone's excited about this now except the physicians um who don't like working with peptides besides GLPs or other FDA-approved peptides, they're like freaking out online. Heard from them all the time.","offset":11107,"duration":25},{"text":"Host: Compounding pharmacies just got the green light that they're going to be able to do basically whatever except sell Retatrutide, which is under patent. Um, so there are many many animal studies on BPC-157 showing accelerated cartilage growth, nerve growth after injury and on and on and on. And angiogenesis. So there's some potential cancer risk there, right?","offset":11132,"duration":30},{"text":"Host: But basically zero human data. There's one study weak study self-report. There's actually a clinical trial where they I'm not making this up folks is BPC enemas, very high dose it for a uh for a for some sort of bowel disease or bowel inflammation. And the study was like I don't think the study was completed or something like that. Don't ask me why, no I'm not making this up. Um, but that's pretty much the only human data that I'm aware of. Um, but tons of people injecting and swallowing BPC.","offset":11162,"duration":28},{"text":"Andrew: Have you experimented with... um, L-carnitine? Because of the mitochondrial effects, because I was able to find some good studies on sperm and egg quality, on mitochon... which are thought to be downstream of mitochondrial health.","offset":11190,"duration":15},{"text":"Rhonda: Right.","offset":11205,"duration":1},{"text":"Andrew: That's the idea.","offset":11206,"duration":1},{"text":"Rhonda: Right, it's downstream. If you can improve mitochondrial health, fertility... which is why NR is now involved with fertility, seems to be improving fertility. It's right, if you can improve mitochondrial health, then you're going to improve fertility, sperm health, right, egg health, right? Um, yeah, L-carnitine, a lot of those studies came out of my mentor's lab, Bruce Ames, so he was he looked at the combination of L-carnitine and alpha-lipoic acid improving mitochondrial health.","offset":11207,"duration":22},{"text":"Andrew: Hmm.","offset":11229,"duration":1},{"text":"Rhonda: And came up with the supplement that it's it's called Juvenon now, but it's L-carnitine with alpha-lipoic acid.","offset":11230,"duration":6},{"text":"Andrew: It's a pill.","offset":11236,"duration":1},{"text":"Rhonda: It's a supplement, yeah. And um, so yes, I have experimented with that, and in fact, my husband takes it, but I mean, I just can't take so many supplements.","offset":11237,"duration":11},{"text":"Andrew: Right. Yeah.","offset":11248,"duration":1},{"text":"Rhonda: You know, so we have our... yeah, but it is, you know, you can find you can find evidence that it improves mitochondrial health, so...","offset":11249,"duration":6},{"text":"Andrew: I was just curious.","offset":11255,"duration":1},{"text":"Rhonda: Yeah, it's just a matter of again, like what what are you what are you looking for? I I feel like I'm doing a lot of high intensity interval training too and I'm taking the Urolithin A. That's a lot, you know, I'm doing a lot of stuff to optimize mitochondrial health. I mean, at some point you have to like not can't do everything there is.","offset":11256,"duration":18},{"text":"Andrew: Sure. No, of course not.","offset":11274,"duration":1},{"text":"Rhonda: But yeah, L-carnitine...","offset":11275,"duration":1},{"text":"Andrew: And it's budget limited too.","offset":11276,"duration":1},{"text":"Rhonda: I don't know that it's going to help you live longer either. Now, it might help with your exercise recovery a bit, right? It might help improve mitochondrial function. I mean, maybe it's going to help with depleting some of the NAD stores. I mean, if you can improve mitochondrial health then, you know, you're improving things like on a small scale, right? So... mitochondrial health is at the core of everything.","offset":11277,"duration":21},{"text":"Andrew: I started experiment... I've started experimenting with it, but I take it in injectable form. It's going to shock some people. You can get away with taking much lower milligram count. Otherwise you have to take a lot of it because a lot of it just isn't absorbed if you take it orally. And then I was told that if you take it orally, you also have to do something to offset the increase in TMAO, and that worried me. So I figured, needles don't scare me, I'll just inject it.","offset":11298,"duration":26},{"text":"Rhonda: Interesting. Yeah. Yeah, the TMAO thing... I mean, so not it depends on your gut bacteria whether or not you're metabolizing the L-carnitine into TMAO. There's actually a lot of complexity involved in that whole thing. But you can get your TMAO measured. So if you were supplementing with it... I mean the same goes for choline, you know, like if you're worried like choline can be converted into TMAO.","offset":11324,"duration":21},{"text":"Andrew: I'll take Alpha-GPC before a workout sometimes or if I need to... um, if I ever need to focus late in the day, I don't want caffeine because it impedes my sleep, but I'll take Alpha-GPC because this is kind of a cool effect, Alpha-GPC actually will improve your REM sleep. It's not a huge effect, but you'll notice you'll get more REM sleep. So it's one of the few things I've found that can increase energy late in the day, do a workout or or work if I have to work later into the day, still sleep just fine and actually sleep better.","offset":11345,"duration":30},{"text":"Rhonda: What is work later into the day mean for you? Like working until like eight, nine o'clock or...","offset":11375,"duration":3},{"text":"Andrew: Yeah, well I do that um often, but but I don't like to work out after 2:00 PM, because I like caffeine before I work out. But I'll do some cardio in the afternoon or something. But if I really have to push push push, or if I've traveled and I really need exercise and I want to get a 6:00 PM workout but I also want to fall asleep at 10:30, I'll take some Alpha-GPC.","offset":11378,"duration":22},{"text":"Rhonda: I used to take that like, I don't know, it's been maybe like ten years. But... um, it's interesting, I might try experimenting with that again. I'm always looking for things that I find a little bit safer, like I don't do the nicotine as you know...","offset":11400,"duration":15},{"text":"Andrew: It is shocking how many young people are taking nicotine now.","offset":11415,"duration":3},{"text":"Rhonda: Oh, I know.","offset":11418,"duration":1},{"text":"Andrew: Yeah.","offset":11419,"duration":1},{"text":"Rhonda: I've never tried it.","offset":11420,"duration":1},{"text":"Andrew: First of all, it's highly addictive. Forget the blood pressure and the vasoconstriction, that's all bad, you know, I think the the big issue is that if I take it... um, I start getting this spasm in my throat when I don't take it, and that's because of its... I have a friend who works on these pathways and it's because of the activation of the muscarinic receptors. So so on smooth muscle you start getting a tick and kind of a clearing of your throat, and then you take more nicotine, you feel fine. So I didn't want to become dependent on it. And um, I don't I don't like it. I think it's I think it's a a bad habit that a lot of people are going to be seeking to quit later.","offset":11421,"duration":34},{"text":"Rhonda: A lot of young people.","offset":11455,"duration":1},{"text":"Andrew: Older people might benefit from it because of the cognitive enhancement, but that's a whole other story.","offset":11456,"duration":4},{"text":"Rhonda: Well maybe the Alpha-GPC and the Creatine and Magnesium L-Threonate.","offset":11460,"duration":4},{"text":"Andrew: Alpha-GPC is is very is very helpful for if you need to really lock in for a few hours and do something physically or or cognitively.","offset":11464,"duration":7},{"text":"Rhonda: How much do you take?","offset":11471,"duration":1},{"text":"Andrew: I take 600 milligrams. You can take up to 900, but I do just fine on 600. So I think I just take it in pure form and in capsule, any of them out there that come from a reputable brand is like going to work.","offset":11472,"duration":12},{"text":"Rhonda: What about like before a podcast or something like that, does that does it have any effect or what?","offset":11484,"duration":4},{"text":"Andrew: Oh yeah.","offset":11488,"duration":1},{"text":"Rhonda: It does.","offset":11489,"duration":1},{"text":"Andrew: Oh yeah, it'll put you into a... you know, I mean if you feel like you want to be heightened focus, but I rely on water, caffeine, electrolytes, and good good sleep. There's this wild study, we don't want to go... I don't want to take us too far off track here, um but there's a study out of WashU recently, really really talented researcher. I want to bring him on this podcast. He does brain imaging, and he compared um essentially the effects of drugs for ADHD versus a good night's sleep, and basically found that there's no focus enhancement of Adderall, Vyvanse, Ritalin type drugs. They mainly looked at Ritalin. All it's doing is increasing alertness to the level that you would get after after a good night's sleep. It may be that these drugs just increase alertness which allows you to dial in focus, but if you're sleeping well and enough, you make up the gap and people with ADHD might just be having some serious sleep defects. So, you know, it it speaks to this thing like, I don't know that there's a single drug that can actually increase cognition and focus. Most of them probably just get you in the plane of alertness that allows you to dial in your focus. Some people be like, \"That's BS,\" they take Modafinil, but this is just another form of increasing alertness.","offset":11490,"duration":65},{"text":"Rhonda: Well, reducing anxiety I think things that are anxiolytic help with that as well, and I think I was talking about... I don't know if I was telling you or someone else before the podcast, one of the reasons why I also like that metabolic switch with the ketosis and the beta-hydroxybutyrate, and sometimes I'll take exogenous ketones too, although if you take them in a fasted state it kind of shuts down the lipolysis. But anyways, is because it increases GABA. The beta-hydroxybutyrate increases GABA and for me it's beneficial because I am the phenotype where like, you know, I can have other things going on in my mind that it's... I don't want to say it's anxiety but it's more of that anxious phenotype, if that makes sense. And so the the increase in GABA really does um help me with focus because it's quieting down, I think...","offset":11555,"duration":46},{"text":"Andrew: I actually think that a lot of people who are very intellectually engaged, which clearly you are over many many years and very physically active and healthy, there's a lot of capacity there and unless there's something to really absorb all that capacity, you can get multiple tracks going, and we sometimes think of that as anxiety or even ADHD, some people will say it's ADHD. I don't I don't necessarily think it's that, but it's an uncomfortable state to be in, and it's so pleasurable to be like where all one's resources, physical or cognitive or both, are harnessed. It's a it's a very pleasant state. Earlier you were saying the GABA increase from the ketosis, I think more and more we're just realizing that people have differing levels of excitatory to inhibitory balance in the brain. And so some people like things that bring GABA up, some people like things that bring glutamate up, broadly speaking, and finding that sweet spot is where you go, \"Oh, like I'm alert but calm.\" And that's that's what we want.","offset":11601,"duration":53},{"text":"Rhonda: Right. That's what it does for me. Alert but calm. And for me I'm like, and I noticed that with... there was a few years ago I really experimented with a ketogenic diet. I just can't do that type of diet, but I did experiment with it and that was the one of the main things that I noticed is like, \"I'm alert but calm,\" and it's like I liked it.","offset":11654,"duration":18},{"text":"Andrew: Well then don't take nicotine, because the reason people like nicotine is it's a stimulant that calms you down. So I do think that one of the reasons it's so habit forming is because I know of nothing else that puts you in that plane of focus of alert but calm that is reasonably low cost, that is legal... I've never out- I'm come clean, I've never done amphetamine or cocaine, so I'm not... I wouldn't want to and clearly that's a path to destruction. So the reason so many young people are taking it is because it gets them right in that plane of alert but calm, but it has all these negative effects that go with it.","offset":11672,"duration":33},{"text":"Rhonda: Yeah, and that's why I've stayed away from it, because I know I'd probably love it.","offset":11705,"duration":4},{"text":"Andrew: I've asked some young folks who ask me about nicotine, \"How many milligrams are you taking?\" They'll say \"nine milligrams.\" I'll say \"How many times per day?\" and they'll say \"eight times per day.\" I'm like \"Oh my god,\" like that's crazy!","offset":11709,"duration":10},{"text":"Rhonda: But they didn't start there. You just quickly get there. You adapt.","offset":11719,"duration":4},{"text":"Andrew: Yeah, so I you know, I don't want to sound like that curmudgeon that's like \"Don't drink and don't take nicotine\" and this kind of thing, but it's a it's a slippery slope. Right. Yeah, I mean there's a very slippery slope.","offset":11723,"duration":10},{"text":"Rhonda: Right. Yeah, I mean if there's other things that you can do that maybe it's not going to be as potent, but like...","offset":11733,"duration":4},{"text":"Andrew: Alpha-GPC.","offset":11737,"duration":1},{"text":"Rhonda: Alpha-GPC, for me I like doing I like my metabolic switch and my ketones.","offset":11738,"duration":5},{"text":"Andrew: Nice. Well, I'll be curious to to hear how you feel on the Alpha-GPC.","offset":11743,"duration":5},{"text":"Rhonda: I remember liking it. I I don't know why... I think I stopped taking it because I got pregnant was probably what it was, and then I just... it's one of those things where you just forget. You go back to the basics and then like the... yeah.","offset":11748,"duration":13},{"text":"Andrew: Yeah. Different experiment. Before I came on here, I did put out a call for some questions to the world.","offset":11761,"duration":7},{"text":"Rhonda: Okay.","offset":11768,"duration":1},{"text":"Andrew: Rapid fire Q&A from the land of X and Instagram. Oh this is the... these are the students of the class, of your class, and this way I think about it. Actually, I wanted to ask about this, so I'm so grateful that this person asked about Nattokinase for improving blood lipid profiles. Is it something you're interested in or have experimented with?","offset":11769,"duration":20},{"text":"Rhonda: It's not something that I've experimented with, and I've been more interested in Natto than Nattokinase. I know some... I really would have to say I don't have enough data to really have an opinion on it.","offset":11789,"duration":12},{"text":"Andrew: Okay. Well, I don't have enough data to have an opinion on it, but I take it anyway. Lot of questions about things we already talked about, so cold plunge, um etc. But an exceptional number of questions about microplastics. And I know we touched into it, but on a scale of one to ten, ten being like you're really concerned, how concerned are you about microplastics for mental and physical health, longevity, just broadly speaking?","offset":11801,"duration":24},{"text":"Rhonda: I would say I am less concerned about microplastics than I am about not getting the right nutrients and micronutrients from from our foods, because our body can detoxify at least some of the chemicals associated with them. The microplastics themselves, I mean, I guess it's not... we don't really know what they're going to do long-term, but I'm concerned enough to try to avoid... to sorry, limit my exposure to them as much as possible.","offset":11825,"duration":26},{"text":"Andrew: So you don't drink out of plastic water bottles.","offset":11851,"duration":2},{"text":"Rhonda: I mean, I try not to as much as possible. I mean, you know, I definitely have to at some points, but um, I try not to, yeah. And when I do, I just realize it's the habit, and you kind of have to let go. I mean, I know some people that like don't drink, like they're like \"they're going to get their water from their food, their fruits while they're traveling,\" pretty extreme.","offset":11853,"duration":20},{"text":"Andrew: Yeah, that's... yeah.","offset":11873,"duration":1},{"text":"Rhonda: But I think mental health is important, so I mean it's like is the stress of avoiding the microplastics worse than the actual little bit of microplastics you're being exposed to? It might be.","offset":11874,"duration":11},{"text":"Andrew: TSA is going to hate me, but I lost a bet two days ago to a member of our podcast team. He bet me, we bet, that um, I said one couldn't bring a Mountain Valley Spring Water bottle through security at the airport, and he said you absolutely can, and I said \"There's no way,\" so I made him a bet and I lost. He brought it through.","offset":11885,"duration":22},{"text":"Rhonda: Full of water?","offset":11907,"duration":1},{"text":"Andrew: Full of water. You tell them it's for medical reasons. You don't have to state what they are. They open the cap, they take a sample out, they test it. So there's a time constraint and it's going to create more jobs for TSA. Um sorry, that was sort of a joke, sort of not a joke, TSA's been, you know, in tricky circumstances lately. And he showed up at the at the gate with it and was like \"Here's your water.\" You absolutely can bring water through in glass vessels or whatever vessel, but they're going to test it and it helps if it's a commercial vessel, it's not like your own glass water bottle.","offset":11908,"duration":36},{"text":"Rhonda: Can I pause for a minute because you mentioned a specific brand which I also when I when I...","offset":11944,"duration":4},{"text":"Andrew: Oh yeah, and no I don't make money from them.","offset":11948,"duration":1},{"text":"Rhonda: Same, I I drink when I'm traveling that's that's the brand that I go to. And there are there was a study that came out showing that there's actually a larger um volume of microplastics within this study from glass bottles versus plastic bottles, which was a very shocking finding. Um, so there was more microplastic number coming from the the glass bottles. It turns out this was a study out of France, there was a study out of France and also in the US. It's the paint on the lids... you mentioned the lid and so it's the paint on the lid that's contaminated, getting contaminated in the bottling of the whole bottling of this, you know, water, that is getting into the water. But I do want to mention that the size was was shown to be larger from the glass bottles versus the plastic, so the microplastic size was larger. And as you probably know, larger microplastics are not well absorbed through the gut epithelial cells. So when you're, you know, taking them in in the gut, they're coming out they're being excreted through your your feces. And um, less likely to be taken up into your gut and then get into your body, and that's actually well known. And so I'm actually more concerned about the size of microplastics... um, and it wasn't like the huge orders of magnitude difference between the the water from glass versus the plastic. It's so counter-intuitive you think \"Wait, what? Why is it...?\" so it's the paint that's on the lid.","offset":11949,"duration":76},{"text":"Andrew: Interesting.","offset":12025,"duration":1},{"text":"Rhonda: Anyways, I just want to mention that I still drink when I'm traveling, I still go for the glass, not the plastic because of the size of the microplastics and knowing because the size was much bigger... um, that it's very I would say more data is going to come out on this but I would be surprised if you're absorbing more of the larger particles because it's known that you absorb the smaller ones.","offset":12026,"duration":19},{"text":"Andrew: Thank you for that. And if you want, you can now take your glass bottle through security full. Seed oils. The dreaded seed oil debate. Where do you land on this?","offset":12045,"duration":15},{"text":"Rhonda: I try to avoid them... um mostly because one, if you're avoiding seed oils you're going to avoid a lot of the processed packaged foods that they come in, which I know are terrible for you. Two, because I think that cooking them or heating them, I mean, is more of my concern because they are, you know, polyunsaturated fatty acids which are very prone to oxidation. And when you're heating something that's prone to oxidation, you're accelerating that whole process. I don't want to consume oxidized lipids. I've seen I've looked into that literature and the last time I looked into it was I think 2024. At that time I was pretty convinced that if you are heating and reheating, you know, oils like they do in fast food for sure you're increasing inflammatory markers, that's been shown. And I think also when you're really having a higher level of, you know, omega-6s and stuff around, I'm not as concerned because I'm getting a lot of omega-3, but it does also re- increase your Vitamin E requirements as well, because of the oxidation of these polyunsaturated fatty acids. So do I think it's like like the worst ever? I mean, you can find all this data out there showing that, you know, if you replace, you know, saturated fat with some of these seed oils there's improvements in lipid profiles. But at the end of the day, the question is really what if like you had olive oil instead or avocado oil instead? Would it be even better? I think possibly. So if you're really trying to go for the optimal, I avoid them as much as I can for that reason. But I think there's a little bit more hype when it comes to the seed oil. But if that makes sense, you know, I'm kind of that's my that's my take.","offset":12060,"duration":102},{"text":"Andrew: Makes sense to me, for what it's worth, I stick to olive oil and small amounts of butter and that's because I also think seed oils taste terrible. How come no one talks about that? But anyway. And olive oil and butter are delicious.","offset":12162,"duration":14},{"text":"Rhonda: It's been so long since I've actually like I mean had the you know seed oil but yeah.","offset":12176,"duration":5},{"text":"Andrew: Ugh, you know, and no one can convince me that they don't taste bad to me. So then the debate just kind of falls away. How often are you doing the sauna nowadays? And what does the top contour of that protocol look like?","offset":12181,"duration":13},{"text":"Rhonda: So I've taken a little pause on the sauna right now, but typically I'm doing... I was doing it like, I would say five nights a week. And I say nights because I usually doing them in the night. And it was mixed a mixture between either getting in the sauna or hot tub. So I like I like getting in the hot tub head out under the stars there with my husband, it's like our time. So yeah, usually it's like 20 minutes and temperature-wise, you know, I don't go that hot, I honestly I'm like 180.","offset":12194,"duration":30},{"text":"Andrew: Five nights a week is great! Gosh, I I need to get back on a five-night-a-week sauna or hot tub protocol.","offset":12224,"duration":7},{"text":"Rhonda: I know, I need to get... I do like the hot tub especially, I don't know, there's something about being outside and... I think now there's just there's evidence that the the benefits are really like the same. It's the deliberate heat exposure, right? You're getting the... you're getting that through the hot tub or through the sauna.","offset":12231,"duration":14},{"text":"Andrew: Creatine for kids. Like young kids, like younger than 16. Um any data and or ideas about this, good or bad?","offset":12245,"duration":9},{"text":"Rhonda: Yeah, so there is data in the literature showing that if you give younger younger children that are doing like for example sports like soccer, it does seem to improve their agility and it seems to be safe. I do give my son 2.5 grams of Creatine, so a day.","offset":12254,"duration":18},{"text":"Andrew: Cool.","offset":12272,"duration":1},{"text":"Rhonda: So that's how I feel.","offset":12273,"duration":1},{"text":"Andrew: There's no better um indication of how you... of how one feels than what they're willing to um deliberately give their kids. I don't know where this stems from, and we can cut it if you want, but this um someone asked why did you single-handedly ruin bananas for this person? Uh, do you- did you ruin bananas?","offset":12274,"duration":17},{"text":"Rhonda: So I used to put bananas in my smoothies and there's an en- there's an enzyme that is produced in bananas that break down polyphenols, particularly ones that are found in blueberries, and the reason I was getting my smoothies was one for the greens but two for the blueberries because the polyphenols have been shown to improve cognition. Love blueberries! So... um sorry, don't mix the blueberry with the banana smoothie, because it it has been shown to decrease the the polyphenols which are important.","offset":12291,"duration":26},{"text":"Andrew: Yeah. Yeah, well the alcohol industry will come for me someday and the banana industry will come for you and um, I think we're safe for a while. Should we ignore studies that have less than X number of subjects? I think that's a really good question. Like obviously it depends, but when we're talking about human studies, where's the the line for small study versus large meaningful study for you? Obviously how strongly it's powered, but how do you think about that?","offset":12317,"duration":29},{"text":"Rhonda: Well I'll tell you when I was first looking at the sauna literature, all the studies that I were looking at were like N of 10 or smaller. And it's really the aggregate of those studies and then looking at like animal data and then you start to, you know, you start to look at observational data and the totality of evidence, and you put together this picture. I don't think you should ignore studies that are small, I think that it's part of the story. I think we're getting a little too caught up in \"It's got to be the randomized placebo-controlled trial, it's got to have lots lots of participants,\" and I mean that's great if we have that data, but we don't always have that data. and I don't know that we will always have that data with everything that we're interested in in understanding, right? So the way I look at it is if it's like just one study with an N of 10, okay, interesting. Um, like with the Creatine, right? Like I mean these studies have been small sample sizes. Now there's more than one, but you know at the end of the day, it's still very I would say in this, you know, pilot study phase where you have just small studies. So I I do not ignore them, but I also don't hedge all my bets on them either. I do know that there are a lot of people that were criticizing me on my sauna, I mean back in I you know 2014, published an article on Tim Ferriss's blog, went on Joe Rogan's podcast and talked about, you know, the benefits of sauna, and and I had people that were going \"Your studies... your sample sizes are too small.\" And now we have so much data that's come out since then really kind of validating everything and showing even more benefits. You kind of have to look at the totality of evidence and what is you're what endpoints are you looking at and how can you gather, you know, data from different sources whether it's clinical studies, observational studies, or animal studies, and and try to come up with the bigger picture, right? But then also don't be too confident in your statements.","offset":12346,"duration":106},{"text":"Andrew: I'm very gratified to know that pretty much every other question you addressed the answer to in route to where we are now in the podcast, truly. And um, I'll leave them up so you can see them later if if you choose. Cold plunges notwithstanding um, Vitamin D um, exercise in all its contour, specificity, fasting, um magnesium, lots of questions about supplements which we covered, Creatine, lots of questions about inflammation, longevity... and so I just have to say first of all on behalf of everybody thank you so much. This was really an incredible tutorial and so much of it is actionable. And as you are known for, it was incredibly thorough in terms of setting the context within mechanisms of what we know, what we still don't know. And um I also personally want to thank you, because when you speak I learn, and when you speak I also learn things that change my behavior. And that's a whole other level. Uh, since our last conversation I can think of at least four and probably as many as a dozen things that I do on a daily basis as a consequence of that conversation. And just the gut-inflammation health brain-body axis uh conversation that um we had earlier, I'm going to listen to this again and take notes, because um there's just so much there and the metabolic flexibility thing as an input that can come from multiple sources, just on and on. So thank you for doing what you do. Thank you for being you, for being first-in and still going and doing things with such rigor and and really so much grace. It's just awesome. People love you... um, I certainly do and appreciate you and and it's just um it's a wonderful thing for me to have a colleague like you and you really set the standard. So thank you so much for coming here and doing this marathon and um, can't wait to do it again.","offset":12452,"duration":109},{"text":"Rhonda: Thank you so much, Andrew. It's it's really been great. I learn so much from you as well, and appreciate everything.","offset":12561,"duration":5},{"text":"Andrew: Thank you. Thank you for joining me for today's discussion with Dr. Rhonda Patrick. To learn more about her work, please see the links in the show note captions. If you're learning from and or enjoying this podcast, please subscribe to our YouTube channel. That's a terrific zero-cost way to support us. In addition, please follow the podcast by clicking the \"Follow\" button on both Spotify and Apple. and on both Spotify and Apple, you can leave us up to a five-star review. And you can now leave us comments at both Spotify and Apple. Please also check out the sponsors mentioned at the beginning and throughout today's episode. That's the best way to support this podcast. If you have questions for me or comments about the podcast, or guests or topics that you'd like me to consider for the Huberman Lab Podcast, please put those in the comment section on YouTube. I do read all the comments. For those of you that haven't heard, I have a new book coming out. It's my very first book. It's entitled \"Protocols: An Operating Manual for the Human Body.\" This is a book that I've been working on for more than five years and that's been based on more than 30 years of research and experience. And it covers protocols for everything from sleep, to exercise, to stress control, protocols related to focus and motivation, and of course I provide the scientific substantiation for the protocols that are included. The book is now available by pre-sale at protocolsbook.com. There you can find links to various vendors, you can pick the one that you like best. Again, the book is called \"Protocols: An Operating Manual for the Human Body.\" And if you're not already following me on social media, I am Huberman Lab on all social media platforms, so that's Instagram, X, Threads, Facebook, and LinkedIn. And on all those platforms, I discuss science and science-related tools, some of which overlaps with the content of the Huberman Lab podcast, but much of which is distinct from the information on the Huberman Lab podcast. Again, it's Huberman Lab on all social media platforms. And if you haven't already subscribed to our Neural Network newsletter, the Neural Network newsletter is a zero-cost monthly newsletter that includes podcast summaries as well as what we call protocols in the form of one to three-page PDFs that cover everything from how to optimize your sleep, how to optimize dopamine, deliberate cold exposure... we have a foundational fitness protocol that covers cardiovascular training and resistance training... all of that is available completely zero-cost. You simply go to hubermanlab.com, go to the menu tab in the top right corner, scroll down to \"Newsletter,\" and enter your email. And I should emphasize that we do not share your email with anybody. Thank you once again for joining me for today's discussion with Dr. Rhonda Patrick. And last but certainly not least, thank you for your interest in science.","offset":12566,"duration":15}],"logs":[{"elapsed":"0.0","message":"Downloading audio from YouTube...","detail":null},{"elapsed":"0.0","message":"Trying download with browser cookies (ad-free)...","detail":null},{"elapsed":"93.2","message":"Audio downloaded (125.9 MB) in 93.2s","detail":"File size: 125.9 MB"},{"elapsed":"93.2","message":"Video title: The Best Vitality & Health Protocols | Dr. Rhonda Patrick","detail":null},{"elapsed":"93.2","message":"Audio duration: 3:31:07 (211.1 min)","detail":null},{"elapsed":"93.2","message":"Very long audio (211.1 min) — will use chunked transcription with gemini-3-flash-preview","detail":null},{"elapsed":"93.2","message":"Skipping full-file attempt — using chunked transcription for 211.1 min audio","detail":null},{"elapsed":"95.2","message":"Split audio into 5 chunks for transcription","detail":null},{"elapsed":"95.2","message":"Transcribing chunk 1/5 (starts at 0:00)...","detail":null},{"elapsed":"95.2","message":"Uploading audio to Gemini File API...","detail":null},{"elapsed":"99.2","message":"Audio uploaded in 4.0s","detail":"File ref: files/ftv2kd6nzbz5"},{"elapsed":"99.2","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"183.7","message":"Chunk 1: 133 segments, last timestamp 49:37","detail":null},{"elapsed":"183.7","message":"Transcribing chunk 2/5 (starts at 45:00)...","detail":null},{"elapsed":"183.7","message":"Uploading audio (offset 45:00) to Gemini File API...","detail":null},{"elapsed":"187.6","message":"Audio uploaded in 3.9s","detail":"File ref: files/2b8s80ugcbe4"},{"elapsed":"187.6","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"319.8","message":"Chunk 2: 159 segments, last timestamp 1:44:42","detail":null},{"elapsed":"319.8","message":"Transcribing chunk 3/5 (starts at 1:30:00)...","detail":null},{"elapsed":"319.8","message":"Uploading audio (offset 1:30:00) to Gemini File API...","detail":null},{"elapsed":"325.6","message":"Audio uploaded in 5.7s","detail":"File ref: files/x1v9f4sx6ebc"},{"elapsed":"325.6","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"405.5","message":"Chunk 3: 187 segments, last timestamp 2:18:02","detail":null},{"elapsed":"405.5","message":"Transcribing chunk 4/5 (starts at 2:15:00)...","detail":null},{"elapsed":"405.5","message":"Uploading audio (offset 2:15:00) to Gemini File API...","detail":null},{"elapsed":"409.2","message":"Audio uploaded in 3.7s","detail":"File ref: files/ttnl90lhyo65"},{"elapsed":"409.2","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"482.4","message":"Chunk 4: 162 segments, last timestamp 3:06:02","detail":null},{"elapsed":"482.4","message":"Transcribing chunk 5/5 (starts at 3:00:00)...","detail":null},{"elapsed":"482.4","message":"Uploading audio (offset 3:00:00) to Gemini File API...","detail":null},{"elapsed":"485.8","message":"Audio uploaded in 3.5s","detail":"File ref: files/pegv3dxzn1b5"},{"elapsed":"485.8","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"540.3","message":"Chunk 5: 104 segments, last timestamp 3:29:26","detail":null},{"elapsed":"540.3","message":"Chunked transcription complete: 649 total segments","detail":null},{"elapsed":"540.3","message":"Total cost: 318,023 in / 65,158 out — cost: $0.3545","detail":null},{"elapsed":"540.3","message":"Total transcription time: 447.1s — 649 segments","detail":null},{"elapsed":"540.3","message":"Analyzing topics across 649 segments with gemini-3.1-pro-preview...","detail":null},{"elapsed":"600.2","message":"Topic analysis complete in 59.9s — found 28 topics","detail":null},{"elapsed":"600.2","message":"Analysis tokens: 59,332 in / 2,229 out / 5,649 thinking — cost: $0.2132","detail":null},{"elapsed":"600.2","message":"Pipeline finished in 600.2s — total cost: $0.5677 (450,391 tokens)","detail":null}]} \ No newline at end of file diff --git a/history/1775224371563-Qc6hjJ9Zze0.json b/history/1775224371563-Qc6hjJ9Zze0.json new file mode 100644 index 0000000..c4d03f1 --- /dev/null +++ b/history/1775224371563-Qc6hjJ9Zze0.json @@ -0,0 +1 @@ +{"id":"1775224371563-Qc6hjJ9Zze0","videoId":"Qc6hjJ9Zze0","url":"https://www.youtube.com/watch?v=Qc6hjJ9Zze0","title":"99% of Drone Companies Will Die & Why Anduril’s Products Aren’t an Ethics Debate | Matthew Steckman","type":"youtube","topicCount":16,"segmentCount":153,"createdAt":"2026-04-03T13:52:51.563Z","uploadDate":"20260323","chunks":[{"title":"Introduction & Guest Welcome","summary":"The host introduces Matthew Steckman, referencing Anduril's massive recent defense contract, and kicks off the conversation.","entries":[{"text":"Matthew Steckman: You basically can't have a defense company if you don't have a large US business. The government thinks that we can deliver some pretty major stuff, now and in the future.","offset":0,"duration":8},{"text":"Host: I am so excited, we've got Matthew Steckman, President and Chief Business Officer for Anduril. Just last week they announced a monster $20 billion dollar contract with the US military, one of the largest ever. We could not have a more apt or pertinent guest, as he takes us behind the scenes of both the contract and of Anduril.","offset":8,"duration":18},{"text":"Matthew Steckman: There are very few drone programs that would create a material enough amount of revenue to actually create a real business. You have to create a monopoly. There are lots of VC companies I would love to buy if I had an unlimited checkbook.","offset":26,"duration":13},{"text":"Host: Is there ever like an ethical question of, do we agree with sending thousands of missiles to Iran?","offset":39,"duration":21},{"text":"Host: Matt, I am so excited for this, dude. I just got off a chat with Christian Garrett and Matt Grimm and they gave me, like, incredibly tough questions, so this is going to be a grueling hour for you. But thank you for joining me, dude.","offset":60,"duration":13},{"text":"Matthew Steckman: Yeah, thanks for having me. It's really great to be here.","offset":73,"duration":3}],"startTime":0},{"title":"The Anduril Founding Team","summary":"Matthew shares anecdotes about his co-founders and explains why a blend of inside defense knowledge and outside tech perspective is vital.","entries":[{"text":"Host: I actually want to start with Trey, weirdly, which was Christian Garrett said that I had to ask this. He said, what was Trey like at Georgetown? And what is it about the Anduril founding team that has made Anduril so successful?","offset":76,"duration":15},{"text":"Matthew Steckman: Well, Trey and I were, were classmates, um, met freshman year, um, played Ultimate Frisbee together on the team. Um, so went on a lot of road trips with one another. Um, you know, I don't think Trey has changed at all. You ever seen the movie Hot Tub Time Machine?","offset":91,"duration":17},{"text":"Host: Yeah, great movie.","offset":108,"duration":2},{"text":"Matthew Steckman: Yeah, there's a line in it that's, like, \"every group of friends has an asshole, but Trey is our asshole,\" you know, you know what I'm saying? Yeah, that's Trey in a nutshell.","offset":110,"duration":12},{"text":"Host: And he's gone on to such things.","offset":122,"duration":2},{"text":"Matthew Steckman: It's crazy how that works, yeah.","offset":124,"duration":2},{"text":"Host: It has hope for you. You know, I've never had such a weird start to a show.","offset":126,"duration":5},{"text":"Matthew Steckman: There you go. No, we're kicking this off right.","offset":131,"duration":2},{"text":"Host: It's like a movie reference and then \"Trey is our asshole.\" Yeah, yeah, he'll love that one. Yeah. In terms of the team itself, I have so many defense companies pitch me, and I think bluntly the team is always lacking. What do you think it is about the team that Anduril has in terms of founding team, that has made it so successful?","offset":133,"duration":24},{"text":"Matthew Steckman: Well, first, like, there's kind of some magic in the fact that it's the same leadership team today as it was when we started the company. Um, that, that implies a whole lot of things, I think, um, mainly it's that we're all friends. So I think that's actually pretty critical. Um, there, there's a bond there that basically can't be separated by business or stress, um, or life. Um, we, we all know each other really well. Um, but then on top of that, um, we all come at the industry from really different backgrounds and lenses. And especially in defense, which is, um, it's like everything works against you to get into the defense market. There, it's like every headwind you could possibly imagine. If you don't have a lot of perspective and knowledge about what's about to come, it's hard to think around corners and you get yourself kind of mixed up and gummed up a lot. Founding teams, one of the most important things in, in defense is some of them can be outsiders and, you know, brilliant technologists, um, and thinkers. Um, it does take a lot of inside knowledge. Um, and I think that, um, one of the things we, we got right and keep getting right is that blend of, um, like the outside-inside process. Um, who can think, um, differently, um, and bring in sort of commercial perspective, high tech perspective, uh, add kind of entropy into the system. Um, and then who can really deeply represent, um, our customers, how they think, how does that come together uniquely? That, that becomes super important to, to having any success in the defense world.","offset":157,"duration":109}],"startTime":76},{"title":"Go-To-Market in Defense Startups","summary":"The conversation highlights the crucial need for defense founding teams to possess go-to-market expertise and a deep understanding of government procurement.","entries":[{"text":"Host: I think one of the things I most look for honestly is like GTM experience and ability in a team that I'm looking at in defense. Um, how should we think about analyzing teams for their ability to actually sell and go through procurement? Does it matter if you've got technologists and people with military and combat experience but no one with GTM experience? I know procurement better than fucking anyone.","offset":266,"duration":24},{"text":"Matthew Steckman: It's multidisciplinary, right? So the, the challenge becomes in defense that if you're missing any of the 12 different types of disciplines it takes to really capture a large program, you will fail. Um, and so one of the things that we've done is over the years we've built up a pretty sophisticated apparatus to kind of round out these teams with all of the various skills in acquisition and budgeting and technology, um, and then again, mission and operational analysis and doctrinally how these types of technologies will integrate into the military. You have to have it all. I think the one, um, maybe, uh, interesting piece here is there aren't actually a lot of big programs in government. And so one of the things you don't need to necessarily look for, I think, which you would in a traditional hiring process, you would look for someone who has demonstrated the ability to capture a large program in the past. But, but since there's so few of these things, you, you can't really look for that. Sometimes you luck into it and like, great, you should certainly hire people who have shown to be able to capture large programs. Um, you generally don't actually have that in the hiring pool. And so what you ultimately have to do is piece together the right puzzle for everything that you're going after.","offset":290,"duration":79},{"text":"Host: Does it matter if the founding team doesn't have that experience in terms of going through procurement and GTM?","offset":369,"duration":5},{"text":"Matthew Steckman: I think it does. Um, and I think that, you know, I advise a lot of, of companies and um, if I notice that the founding team, at least a portion of it or a person on it hasn't kind of been there, done that, the first thing I recommend is they have to find someone who represents that piece of the puzzle that, that's missing to their team.","offset":374,"duration":23}],"startTime":266},{"title":"Red Flags for Defense Startups","summary":"Matthew discusses common mistakes emerging defense companies make, such as technological hubris and overestimating their total addressable market outside the US.","entries":[{"text":"Host: When you meet all of the defense companies that you meet today— again, I'm an, you know, I'm an investor, I do— we have so many different European drone companies, every fucking UAV— I, dude, I don't, I honestly don't get it at all, they come with some other thing and I'm just like, \"Matt Grimm, please tell me if this is good.\" No, I really do, I ask Matt about it, it's very funny. Um, he sees everything in Europe because of me. Um, and tells me that it's shit. Um, but like when you look at them, what is the most common red flag that you see when you look at the emerging class of defense companies trying to be, as awful as it sounds, the next Anduril?","offset":397,"duration":34},{"text":"Matthew Steckman: I think it's basically two things. It's, um, uh, not realizing that what they are doing, uh, already exists. There's too much hubris, I think, in the technology market that, um, as high tech people we can, we can do everything better than everybody else. I think, um, that causes, uh, some companies to think they have an idea that isn't actually an idea because it already exists and that's pretty common. Uh, I'll give you an example. I, years and years ago I, you know, was looking at a pitch or I forgot, maybe I was advising someone and, \"Here's my idea,\" and I said, \"Well, the thing you don't know is in the 1960s we invented that.\" And so, so there's a, there's kind of a hubris to thinking like, um, the technology sector has all the answers when, like, actually since the '50s we've had the most brilliant people in the world working on these problems and a heck of a lot already exists. And this is sort of the point of like, if you don't actually have the inside knowledge you don't know what mistakes you're making. So that's one. The second, uh, which will be more familiar to you, is, is addressable market. Um, I think there's, uh, in many cases an overestimation of addressable market where like actually what ultimately they're going after is a very small sliver of a problem, um, which might materialize in a, a single large contract, but a single large contract is not an enduring business.","offset":431,"duration":91},{"text":"Host: And this is one of the big challenges that I face, is when we see a company that in France is saying \"we're selling to the French military.\" Dude, I don't know how to say with— I upset everyone these days, I just get used to it. The French military spend less than I do in Chanel for my mother. I mean, it's like fuck all. And so my point is, like, can you be a European-only next-gen prime or do you have to be selling to the US as well? How do you think about that?","offset":522,"duration":25},{"text":"Matthew Steckman: Yeah, I mean, you basically can't have a defense company if you don't have a large US business, right? So 50% of defense spending is in the US and 50% is in the rest of the world. And so if you are cutting off half of your market from the get-go, that's, that's probably a big problem. The, the challenge in Europe is it's not, it's not like a European Union in defense spend, right? Each country has its own sovereign, uh, companies and has its own sovereign agenda and so you keep getting winnowed and winnowed and winnowed and you're like, \"Oh, well Europe is my market.\" Well, if you're a French company, it kind of isn't, right? France is your, your market. Um, and so you have to be really careful around how you're actually analyzing who your ultimate customers can be.","offset":547,"duration":45}],"startTime":397},{"title":"Unpacking the $20 Billion Contract","summary":"Matthew clarifies the details of Anduril's major US military contract, explaining that it acts like a credit card limit to streamline future procurement.","entries":[{"text":"Host: You mentioned 50% of that spend is in the US. You guys signed a $20 billion dollar contract. Um, it's pretty incredible. It made me feel thoroughly irrelevant when I look at my companies going from 1 to 4 million in ARR for an HR software company and the whole team's like, \"Ah, bugger.\" Um, my question to you is, what's actually entailed in the $20 billion dollars? Was it like an accumulation of all the little contracts brought together? 'Cause it's a big headline number but I didn't actually get it and I don't think a lot of people did.","offset":592,"duration":32},{"text":"Matthew Steckman: Yeah, yeah. So let's, let's, like, actually define it because the stuff I saw posted about it was all over the place. It was like a rainbow of interpretations. So this is, think about this as like a, um, a credit card limit. Um, so the government has said up to $20 billion dollars they can spend on a class of Anduril's commercial technology. Um, there's no obligated money, but it basically creates, uh, a process that reduces a ton of friction that you would ordinarily see in defense procurement, where each individual office would have to go through financing and contracting and evaluation. Um, and all of these repeatable things now, can now only have to happen once. And they did, and they just did. And so, um, maybe a fast track is probably the wrong word, it's more like in the arduous process to actually get something contracted we've cut a lot of the first steps out. Um, there's still a lot of hard work. We've just made it slightly easier for the government to access all of our gear.","offset":624,"duration":70},{"text":"Host: When they say, like, \"dependent on delivery,\" what does \"delivery\" mean?","offset":694,"duration":4},{"text":"Matthew Steckman: They will obligate the dollars as the products, which is hardware and software, are actually materialized. So delivery is revenue to us, right, in our world. So when I deliver something I recognize the revenue, um, same thing in government. When we deliver something, they actually then the actual procurement orders and dollars flow.","offset":698,"duration":20},{"text":"Host: Again, I'm so sorry for being dumb or naive, I'm a venture capitalist for a living, you should be used to us by now. Um, is this replacing prime spending? Is this net additional? How should we think about this? And is this just the sign that Anduril is now another prime?","offset":718,"duration":16},{"text":"Matthew Steckman: Yeah. It basically means that we have enough business with the federal government to justify putting together what is a fairly sophisticated contracting vehicle. Um, so yeah, the short version of it is like, yeah, the government thinks that we can deliver some pretty major stuff, uh, now and in the future. Um, it took a lot of work by a lot of people on the government side to actually make this thing happen. They are not going to do that unless they think that it's worth it.","offset":734,"duration":26},{"text":"Host: What do they spend with, like, a Lockheed or a Northrop for, like, comparison?","offset":760,"duration":5},{"text":"Matthew Steckman: So Lockheed I think is in the, like, 100 billion revenue a year. Um, I think we'll do a couple billion in revenue this year. So we're still, you know, small in the grand scheme of things.","offset":765,"duration":10}],"startTime":592},{"title":"Business Models & Contracting Challenges","summary":"Matthew explains how Anduril flexibly offers hardware, software, and services, and discusses the difficulty of surviving the unpredictable periods between large government contracts.","entries":[{"text":"Host: When you look at the software and the hardware element, how do you guys sit internally? Are you a hardware company? Are you a software company? Are you a services company? Ultimately, how do you sit?","offset":775,"duration":11},{"text":"Matthew Steckman: There's a lot of ways to look at it. So I think one of the things we've done maybe uniquely is we've given our customers a lot of ways to access our company. So what I mean by that is, um, um, we've been very creative in, \"Okay, a customer wants a piece of software, uh, but it's difficult in government to contract for software.\" And so we can wrap it in a hardware appliance, right? Or they want a piece of hardware but they know the software is the sophisticated piece of it, um, and so they're willing to pay more for it because of that sophistication. Or, uh, in government, um, you get these weird things where, uh, money is, it's called \"the color of money,\" so money is obligated to certain types of spend. So maybe a customer only has money that they can spend on services. Well, okay, can I do an as-a-service product? Um, and actually one of our, our first major contracts was with, uh, US Special Forces, uh, for, uh, all of their counter-UAS, uh, systems. That started as an as-a-service contract where they weren't buying hardware, they weren't buying software, they were literally buying, uh, a service that obligated us to defend certain sites from certain types of threats. And as long as we were meeting the KPIs on the contract, um, we were fulfilling the obligations of the agreement. Um, so quite novel, uh, and that contract has, you know, since gone in a lot of different directions and we do a lot of different things on it, not just that, but we have been kind of dogged in our, uh, approach to this by basically realizing that the more ways we give our customers to get at us, the better it's going to go.","offset":786,"duration":106},{"text":"Host: What's the hardest thing about working with the government when you look at the structures that you have to contort yourself in to get a deal done? What's the hardest thing? I've interviewed Shyam, who I presume you work with from Palantir.","offset":892,"duration":15},{"text":"Matthew Steckman: Yeah, yeah, I worked for Shyam for a really long time. He's a good friend of mine. Um, there's a lot of answers to this question, but maybe from my lens, uh, it is, uh, it is how few and far between the large wins are and how hard it is in between those periods of time. So if you look at our business, you know, this year we'll do a couple billion in revenue. We'll do 600 separate contracts this year. Um, only 20 of those are probably of material revenue size. I think the hardest thing is, like, what happens in between the 20? And what are you doing to position yourself for the 21st? And because it's so concentrated, every single one of those deals is considered risk to the business, right, if it goes right or if it goes wrong. So.","offset":907,"duration":49},{"text":"Host: Why specifically is it hard in between? Is that morale? Is that revenue predictability? What is it that's hard in between?","offset":956,"duration":8},{"text":"Matthew Steckman: The government can sometimes tell you where they want you to go, but often times they don't. And so a lot of this, uh, is trying to predict an unpredictable system, right? So how many lenses can you look at at sort of the next couple of years? I can look at it through what the government is saying through their rhetoric and through their budgeting. I can look at it through a war fighting lens and what general officers are saying and what, um, military theorists are saying. I can look at it through a technology lens, like what technologies do I, I think are going to influence the battlefield in the future. And I need to kind of blend all of that together today to make decisions on what I want to build that will be available, you know, five to seven years from now. Um, no one is saying today, \"this is what I need five to seven years from now.\" It's, it's all sort of a, an educated guessing game over time.","offset":964,"duration":54}],"startTime":775},{"title":"Offensive Cyber Warfare","summary":"Matthew reflects on the missed opportunity to enter offensive cyber warfare earlier, explaining its asymmetric threat and the urgent need for robust capabilities.","entries":[{"text":"Host: What did you not do that with the benefit of hindsight you wish you had done, and what did you learn?","offset":1018,"duration":8},{"text":"Matthew Steckman: Um, there's been a couple of areas that, you know, have, have kind of emerged that maybe we were a bit slow in, that we would have accelerated. I'll give you an example. Um, uh, there's a huge movement in, uh, not just in the US but NATO and the rest of the allies, um, into offensive cyber warfare. Um, and you're seeing this now becoming public for the first time, which is really, really interesting. Um, you know, to date this has been one of the, the spookiest of all spooky things, right? Like something that just no one ever talks about and now you're, you're literally seeing public officials talking about it for the first time. We should have moved into that seven years ago and been the first, the first in it. We weren't big enough probably to really even understand it seven years ago, but like in hindsight it was kind of obvious. Um, you know, we'll probably try and play some catch-up here and, and get into the game, but, you know, there's a couple of examples like that where you see these things kind of thematically in hindsight, um, and you're like, \"Well, obviously five years ago I should have done it,\" right, and you only realize that today.","offset":1026,"duration":64},{"text":"Host: What is the fear with offensive cyber, when we look at, like, the worst case scenario? Just so I understand it.","offset":1090,"duration":6},{"text":"Matthew Steckman: Well, it's a lot of things. So it's both what are our adversaries doing and do we understand it, and are they asymmetrically influencing, uh, battlefield tactics? And the answer is yes, they are. Um, and then it's, okay, well if our capability—","offset":1096,"duration":18},{"text":"Host: Sorry, sorry, can I just stop you again before I get lost in your next statement. What does it mean like \"asymmetrically influencing battlefield tactics?\"","offset":1114,"duration":6},{"text":"Matthew Steckman: Yep. So for a very, uh, one version to think about this is just cost. For a very low cost they can create an effect that has, uh, major implications for us, NATO and our allies. That's asymmetric. So, uh, often people refer to terrorism as an asymmetric tactic, right? For a minimal set of people—","offset":1120,"duration":22},{"text":"Host: But this would be like a $10,000 dollar drone that hits a $1 million dollar—","offset":1142,"duration":5},{"text":"Matthew Steckman: Drone warfare is as— an asymmetric battlefield tactic, exactly. Um, and cyber being not only asymmetric but you'll often hear the term \"non-kinetic\" associated with it. So I'm asymmetric as in I'm, I'm cheaper and more, more nimble and I can get a large effect, but I'm also non-kinetic. And, and why is that so, so dangerous? Well, when something explodes, uh, we react to it and we react to it, uh, with the full force of, uh, of the military. When things are kind of simmering beneath the surface, and sort of a cold war-ish type of a way, it actually becomes really hard to react. And so in cyber warfare in particular, if assets are affected that we care about, well can we— can we do attribution? Do we know where it came from? How do we respond? Do you respond with a non-kinetic attack by going kinetic? Is that an escalation of force? How is that perceived by the global community? Right? So you, you get into all of these really challenging doctrinal, uh, positions because of, uh, just sort of unexplored offensive cyber is. Um, and then on the flip side, right, it's like do we have the ability to amass cyber effects on our own? Right? 'Cause what you would want to do is you would want to do tit for tat. You wouldn't want to do, in- for the most part, a set of like escalatory decisions. You would want to, you know, match force with force. Do we have the ability to amass the same kind of force non-kinetically? Right? So all of these are super important questions that, uh, in my opinion to date have not been debated publicly and, and absolutely need, need to be.","offset":1147,"duration":103},{"text":"Host: Can I ask you what cyber assets do we care about versus not care about?","offset":1250,"duration":5},{"text":"Matthew Steckman: What do we care about protecting or what do we care about affecting?","offset":1255,"duration":4},{"text":"Host: Both actually, if that's—","offset":1259,"duration":1},{"text":"Matthew Steckman: Yeah, well protecting, right, probably the main one is like the list of critical industries. Um, the military is included on that list. Um, but think about infrastructure, think about power, think about, um, energy, think about all these things, right?","offset":1260,"duration":14},{"text":"Host: Okay, so it's like a foreign adversary impacting energy supplies in large cities or water supplies. For sure. Um, healthcare data or financial systems, I guess.","offset":1274,"duration":12},{"text":"Matthew Steckman: Yep, yep. But even, even now though on the battlefield, it's a foreign adversary impacting our military systems such that we can either not mount an offense or we can, uh, not, uh, successfully defend ourselves.","offset":1286,"duration":12},{"text":"Host: Okay, gotcha. And so that, that's the cyber assets that matter on the defense side. On the kind of offense side?","offset":1298,"duration":6},{"text":"Matthew Steckman: Everything that they would do we would do too. Yeah, exactly. That's the way to think about it.","offset":1304,"duration":7},{"text":"Host: Is there any part of you that's like, Northrop or Lockheed have a $100 billion dollar spend, with the greatest of respects we have a $20 billion dollar spend, we're nowhere in offensive cyber, fuck it, let's not try and catch up. No, I mean in the nice way, you can laugh at me and maybe I'm going to get killed for this but I don't really care. Like, let's just accelerate where we're doing great. Like why bother catching up when you're 70 years behind?","offset":1311,"duration":24}],"startTime":1018},{"title":"Horizontal Strategy & The Drone Market","summary":"Matthew outlines Anduril's strategy of building the horizontal Lattice platform to support multiple products, and predicts that the crowded drone market will inevitably consolidate to a single winner.","entries":[{"text":"Matthew Steckman: Well let's like talk about just like our strategy as a whole. So when we started the company we knew we had to go really wide really quickly, right? 'Cause to the point of like what do other defense companies or newer founders get wrong, it's that addressable market question. So in every technology class in defense there's probably one, sometimes two actual programs that if you capture them you have a business and if you don't you have no business. Um, so take small drones as an example. There are very few drone programs for small drones that, uh, would create a material enough, uh, amount of revenue to like actually create a real business, right? And so like you're basically shooting the moon, uh, you have to create a monopoly. We knew that and so what we did is we created a bunch of fundamental technologies that are applicable to a lot of different types of problems. Um, if you read about us, um, this is called Lattice in a lot of our, like, published literature. Fundamental tech that allows you to consume data, make sense of it, and then, uh, manipulate robots basically, like that's what it is. Those technologies apply to tons of different things and so we have 20 different P&Ls at the company, uh, all that are going after different parts of the defense apparatus that take a lot of these fundamental technologies that we built and kind of piece them together in different ways. And so.","offset":1335,"duration":91},{"text":"Host: So just so I understand, so it's kind of like a horizontal foundational technology that you then verticalize and specialize to fit individual P&Ls.","offset":1426,"duration":8},{"text":"Matthew Steckman: Lattice is a software platform, exactly. Like, uh, I can talk about software platforms with you. It's hard to actually talk about software platforms with a lot of people 'cause it's, like, if you don't actually understand, like, what we're talking about it's, it gets a bit weird. But yeah, Lattice is basically just a software platform that we can branch from. Um, and it's led us into all of these, uh, interesting places. So, like, um, as a really crazy example, uh, the first product we built was a sensing tower, uh, that just allowed us to automatically through a bunch of computer vision technologies— and this was by the way pre-like cool AI, this was like old school CV AI, um, in 2017— just allowed you to spot threats at distance, right, but automatically without a person having to look at a screen. There are pieces of that technology that are resident in our autonomous jet fighter today. Right? Not, not all of it, right? Like there's been a lot of advancements since then, but there are code blocks, right, that are, are shared in common between all of our pieces of technology. That becomes like pretty magical when you approach whatever the next problem is, because you've already got pieces of it solved. Um, gives us a head start, allows us to get to market at usually reduced cost, usually a better schedule, kind of hitting all of the performance characteristics that our customers care about. So. Okay, so back to the actual question on cyber, right? So, so why go after it? Like we, we kind of have to go wide and we have to believe that we have parts of the problem already solved with the platform in order to even approach a market. We wouldn't get into a market if we didn't think we already had applicable technology or a technology tailwind, but where we do, we're, we're definitely going to go after it.","offset":1434,"duration":106},{"text":"Host: What you said was, was fascinating to me. You were like, \"basically you have to assume a monopoly market if you want to build a big enough company for drones.\" Why the fuck are there so many drone companies then?","offset":1540,"duration":10},{"text":"Matthew Steckman: Yeah. Um, I don't know.","offset":1550,"duration":4},{"text":"Host: I mean— I've seen— I've seen so many, like 30, 40 in Europe, just European ones.","offset":1554,"duration":6},{"text":"Matthew Steckman: Yeah. It'll be one that wins, right? It's, it's going to be really hard to pick it, I think is the problem. Um, like there will definitely be one winner. Um, I think the challenge for investors is actually figuring out which one it is.","offset":1560,"duration":13}],"startTime":1335},{"title":"R&D and Internal Capital Allocation","summary":"The discussion turns to Anduril's process for greenlighting new projects using internal tiger teams, rapid prototyping, and a venture-style investment committee.","entries":[{"text":"Host: So we should invest in, you know, offensive cyber and defensive cyber. How do we think next-gen? You're CBO, you're president. You like, \"Great, we should put a billion dollars against it and build that out as a separate business unit.\" Like, and please tell me where I'm wrong. Like what's the subsequent thought to that?","offset":1573,"duration":18},{"text":"Matthew Steckman: Yeah, so the way that we do this is, um, when we have a new idea, um, we basically start a really small tiger team that we generally piece together from various parts of the business. Um, and we, we kind of match our own internal motivation and, and spend, our own IR&D, um, to what the market is whispering to us. So in government what this generally looks like is you, you piece together, uh, some tech really, really quickly so that you have a demonstrator or at least a dart to throw. Um, and then you start to pulse the market and you see how, how close was that dart throw to what the customer actually cares about, how they think about the problem. Do you modify it? Were you totally off and you just need to scrap it and start over again? Um, and I think in government uniquely you know you have something when the customer's excitement starts to match your own and all of a sudden you're kind of walking down a path together as opposed to this weird like vendor-customer relationship. That's always how we kind of identify that we're on to something. I would say all of these things can be characterized by, like, a singular champion on the other side of the table that gets it, that believes in it, that wants to shepherd it. Uh, actually you mentioned Shyam, he talks a lot about this kind of heroism, like it actually comes down to a single person in government a lot of times. Same experience for us. Um, and if you do it right, it kind of tracks similarly. You know, the first year's low dollar spend but there's a lot of learning. Um, and you sort of jump from— I, I tend to use this like lily pad example, you kind of jump from pad to pad and this is what I mean by the 600 contracts in between the 20 that matter. You're basically jumping from contract to contract trying to figure out \"Do I have it right? Is the customer excited? Are they telling me things? Do we keep going? Do we keep spending?\" and ultimately the thing you're trying to jump at is something very large.","offset":1591,"duration":137},{"text":"Host: How do you know when you have something really special and when you should concentrate capital? Again, I think the best founding teams are the best resource allocators. When do you unleash the funding tap and open it up versus constrain and move from little lily pad to lily pad?","offset":1728,"duration":15},{"text":"Matthew Steckman: Yeah, there's a lot of ways to look at our business, but, but one way I think you hit on it is we've been very good at allocating capital. Like, we basically guess right most of the time. If you do this correctly you have enough data to develop conviction to open the tap, right? And so I think in the beginning we were working in areas where if we made a mistake, um, it wasn't, we weren't like too far in on spend that if we pulled back it wasn't like a disaster for the company. I think a lot of the stuff we're building now is quite sizable and expensive and so you're looking for certain proof points along the way and that can be, um, formal, uh, feedback from a customer. That can be informal. That can be, um, um, successful operator, uh, feedback. That can be, uh, successful engagements, um, with the legislative branch— like remember in the US, like your funder is, is the Congress, right, and so they have a say in all of this. What actually it is, it's all of those things pieced together. And so we run like basically an investment committee internally where, uh, these tiger teams ultimately have to present, \"Here's what we did, here's what we discovered, here's what we want to do next, here are the gates, here's what it'll cost.\" Um, and very similarly to how, you know, most financial institutions do it, um, the investment committee says, \"Go.\" And I think maybe uniquely when we say \"Go,\" um, we have the ability to do it faster and at a higher level of spend than most of our peers, which is a huge advantage. And so when we actually develop conviction in something, we pretty much believe we can get there faster than everybody else because of it.","offset":1743,"duration":101},{"text":"Host: If we think about it as an investment committee, we're speaking a language that I know now. Which tiger team was the most successful bet and which was the least successful bet?","offset":1844,"duration":10}],"startTime":1573},{"title":"Disrupting Missile Manufacturing","summary":"Matthew shares the surprising success of Anduril's Barracuda missile portfolio, which leverages commercial manufacturing to achieve scale, elasticity, and solid gross margins.","entries":[{"text":"Matthew Steckman: The most surprising, uh, cases to the upside right now, uh, is in our missiles portfolio. So we started our missiles business a couple of years ago. Um, if you read about us, um, the best example we call the Barracuda family of systems. So it's, uh, it's basically a, a set of, uh, cruise missile, uh, systems, different sizes, different shapes and things like that. We basically got into the missiles business, um, looking mainly at, um, sort of this, the actual like military warfare lens. Like there is clearly a gap in capability, we clearly believe that we can be ahead of everybody else if we've already developed it and when the customer asks for it we'll have it. And that turned out to be quite, like, quite prescient. Now, uh, I don't know if you've seen but there's like a war going with Iran. Um—","offset":1854,"duration":58},{"text":"Host: I, uh— have seen, yeah.","offset":1912,"duration":2},{"text":"Matthew Steckman: Yeah, and so it's like okay, so we, we got into this market years ago with a certain set of theses and geopolitics now has dramatically changed what those theses are, to the upside.","offset":1914,"duration":17},{"text":"Host: When you say it's changed them, do you mean it's confirmed them?","offset":1931,"duration":2},{"text":"Matthew Steckman: It's confirmed them, but it's confirmed them in such a way where it feels wholly different. You know, I think the original theory was we have to get low cost, we have to get more ubiquitous, um, we have to have a mix of exquisite systems and mass, um, like all of these kind of major theories of warfare are kind of all converging at the same time. Um, we have to be able to build something that takes advantage of commercial supply, uh, and commercial manufacturing techniques as opposed to aerospace and defense supply and technique. You know, this kind of like crazy crystallization of a lot of things at the same time. And now, okay, we, uh, there's a war in Iran, we fire a lot of our arsenal. Um, you know, now there's public reporting that, um, you know, large percentages of our offensive and defensive missile systems have been expended. And they're really hard to replace. They take a really long time and they're very expensive because they take advantage of parts of the market that are kind of strange and very specific and very exquisite. You know, just to give you an example, the cruise missile we build, the, the actual airframe is built like you build a bathtub. Um, and so we can take advantage of tons of contract manufacturers in the United States that can actually build a bathtub, right? So just thinking through the design differently from the very beginning has led us to build something that we can just turn on. It's like, uh, another way to think about it is you can handle elasticity of demand for the first time. Um, and that, that's not really a thing that's ever existed in the missiles business, right, where you have a fairly, uh, labor intensive process to increase or, or frankly sometimes decrease demand. Um, I think we've, we are on to something and that we've built kind of a first-of-its-kind that can handle the ebb and flow of geopolitics and warfare. Uh, we can turn lines on and off, we can scale up and down based on the number of contract manufacturers that we engage.","offset":1933,"duration":126},{"text":"Host: What do margins look like for these types of products? What, what is good?","offset":2059,"duration":6},{"text":"Matthew Steckman: Yeah. As a business we run, uh, sort of 40% plus gross margin across the board. Um, and which by the way in hardware and defense is quite good. Um, uh, but every product like kind of lives along a spectrum as you can imagine. The best way to think about this is things that you make more of, like missiles where you're selling thousands and thousands, tend to be a little bit lower gross margin, um, and things that you make less of, uh, you can, you can tend to, to get a decent price for it.","offset":2065,"duration":32},{"text":"Host: Sorry, I'm naive. Why is that? I thought the more you produce, the better the margin would be because you have bulk materials, bulk buying. No? Like help me understand that.","offset":2097,"duration":10},{"text":"Matthew Steckman: It mostly comes down to customer expectation for what these things like should cost over time and then your ability to, uh, gain back margin by cost saving in the long run. Yes, you can close a firm fixed price contract, it doesn't necessarily mean that you can fix that cost forever. Um, and again, it's just like another weird aspect of government business.","offset":2107,"duration":21}],"startTime":1854},{"title":"Ethics & Geopolitical Conflicts","summary":"Matthew addresses the moral framework of working in defense, the company's long-term perspective on global conflicts, and their defensive footprint in the Middle East.","entries":[{"text":"Host: Can I ask you a weird one? But Matt did say I could ask it. Is there ever like an ethical question of, like, \"Do we agree with sending thousands of missiles to Iran?\" I'm not saying right or wrong, but is there ever an ethical question of how your products are used?","offset":2128,"duration":16},{"text":"Matthew Steckman: If you, um, if you work in defense and if you start a defense company your moral compass tends to be pretty clear on this question, which is we have a democratically elected set of governments that represent the US, the alliance, NATO, all of the countries participating. They set the rules. Uh, and we abide by those rules. Um, and if you start to mess around with anything within that framework you create a, a pretty dramatic set of slippery slopes that, that if you play the actual thought experiment to its end, um, end up in a pretty messy situation. And so the, the key here is people that live in the world that I live in, we, we tend to think a little bit differently than, um, uh, a person not connected to the national security community on this front. We tend to think a bit more long term as well, where I'm building missile systems that might only field in 2035. All right? And so if you fundamentally lack a trust in democratic institutions, this is not the game and this is not the business for you.","offset":2144,"duration":69},{"text":"Host: As weird as it sounds and as horrible as it sounds, is war not great for business?","offset":2213,"duration":5},{"text":"Matthew Steckman: I think that's the wrong view. I, I think, um, if you look at, again, if you look at things that span multiple decades, which is probably the right horizon to think through, everything kind of nets out. Um, and so yes, you'll have spikes in, in conflict. Um, but like as an example, there are many companies that are, uh, profiting off of, uh, the war in Ukraine. Um, and I would posit that for the most part if those companies are myopically focused on that conflict they will not have a business coming out the other end. So it's very— you have to be very careful around over rotating on the problems of today, um, because it can, it can really mess up your strategic thinking.","offset":2218,"duration":45},{"text":"Host: Do you think you took advantage enough of the opportunity in Ukraine?","offset":2263,"duration":4},{"text":"Matthew Steckman: We were still a baby company when the conflict started. Um, so just as a reminder, we were zero people in 2017 when we started the company. Uh, we're about 8,000 people today. Um, we were quite small, a couple hundred people when, um, when the war in Ukraine started. Um, and just sort of as a reminder and now this is kind of lived experience for me and my colleagues: you go to war with what you have. Like that, that saying is very, very true. Like, you, you do not invent new stuff along the way. Um, you, you, you take what you have and you, you see if it works and then you adjust. And so we, we had some stuff in Ukraine but we were just too small. Um, I think if you, I, I think if you play that forward to today, we're heavy participants in the current conflict in the Middle East, um, mainly on the defensive side. We build, um, some pretty sophisticated air defense systems that are widely deployed. So it's a wholly different experience because we're a wholly different company.","offset":2267,"duration":61},{"text":"Host: Are Anduril drones used in Iran?","offset":2328,"duration":3},{"text":"Matthew Steckman: I can't speak to specific weapon systems used in specific situations, uh, but we are for the most part a defensive company in the Middle East, as in we are defending against, uh, incoming threats. So if you've read about, uh, the Shahed drone as an example— yeah— um, we're one of the principal systems today to defend against, uh, that threat in the Middle East. Yeah, other than that, it's, you know, it's hard to get into specifics.","offset":2331,"duration":25},{"text":"Host: Yeah, I would hate for you to reveal some inherent military secrets on 20VC.","offset":2356,"duration":5},{"text":"Matthew Steckman: You become, you become pretty good at talking around these things when, when you do this work.","offset":2361,"duration":3}],"startTime":2128},{"title":"M&A Strategy & Space Innovation","summary":"Matthew explains why high VC multiples make startup acquisitions difficult for Anduril, and identifies the space domain as a prime area for future technological disruption.","entries":[{"text":"Host: I'm going to be totally honest, that's not in my interest either. Please don't. I'm really comfortable with my nice life. Um, can I ask you, if I gave you an unlimited checkbook, what would you spend on that you're not spending on today?","offset":2364,"duration":20},{"text":"Matthew Steckman: I think there are some venture capitalist-backed defense companies that are making some really, really awesome technology and they are entirely unaffordable to us today because of—","offset":2384,"duration":12},{"text":"Host: And when you say they're unaffordable, you mean they won't sell at an appetizing price to you given the amount of money that they've raised.","offset":2396,"duration":6},{"text":"Matthew Steckman: Correct. Yeah, yeah, the, their valuations are just too high for us to justify the buy. We, we've bought, I think, almost a dozen companies, maybe more, um, but for the most part they've been more traditional style defense companies, um, with what you would command in the commercial market for that type of company. There are lots of VC companies I would love to buy if I had an unlimited checkbook, but right now the multiples today are, they put them out of reach for us.","offset":2402,"duration":29},{"text":"Host: This was going to be one of my questions, which is is there a universe of buyers for the mass of VC funded companies that have been generated in the last few years, and what happens to them?","offset":2431,"duration":12},{"text":"Matthew Steckman: Actually, um, Trey, uh, I, I will always remember when he said this: that, um, never be surprised around how long a company can continue to exist. Uh, meaning like, you know, I think we were sitting around a table being like, \"Oh, like, uh, it's going to come to the point where the multiples will, you know, decrease\" and all this stuff and, and Trey's point was— and, you know, Trey has this annoying tendency to mostly be right, I don't know, I don't know if you know that about him.","offset":2443,"duration":29},{"text":"Host: But he's our— yeah, exactly. He's our asshole.","offset":2472,"duration":3},{"text":"Matthew Steckman: Yeah, he's our asshole. Um, his point was like, we don't know, but it might be a while before we can actually buy these companies. And so I, I don't know. Uh, there's still a lot of investment in defense tech. Multiples are still very high. I actually think our multiple's quite low compared to most of them.","offset":2475,"duration":16},{"text":"Host: Why would you say your multiple is low?","offset":2491,"duration":3},{"text":"Matthew Steckman: Because it is.","offset":2494,"duration":1},{"text":"Host: Hit me. At, like, what, 10 or 14X forward, something like that? Um, but you're seeing deals in 20, 30, 40X forward.","offset":2495,"duration":13},{"text":"Host: My dear friend, you're seeing deals a lot more than that. Like, you, I think you're sorely mistaken on that one.","offset":2508,"duration":5},{"text":"Matthew Steckman: Great. So it's even worse.","offset":2513,"duration":2},{"text":"Host: 20, 30, 40— why don't you times that by 5? Dude, I see like 200. Who would you most like to buy but can't?","offset":2515,"duration":9},{"text":"Matthew Steckman: Oh, man. No, that's a tough one for me to answer. I, like— I would probably either compliment or offend people that I don't want to compliment or offend. Um, but I'll give you like the classes of technology. Super interested in space domain, like the— there's a— a couple of companies that are doing some absolutely fascinating things both ground segment and on orbit. Um, there's a couple of companies flying fast and—","offset":2524,"duration":24},{"text":"Host: Why is ground segment and on orbit interesting?","offset":2548,"duration":4},{"text":"Matthew Steckman: There's this like interesting thing happening in space domain where, um, you've got the legacy primes on the military side that have these very large contracts, um, but they, they perform sort of traditionally, right? So it's going to be very, very high performance but it'll come at a, a cost and it'll probably take a while to get there, right? And then you have, um, SpaceX which is just dominating on the commercial side and when their commercial tech applies, um, you know, they do a bunch of government business as well. There's a weird kind of gap in between those two types of companies where the government wants to move really fast, um, but it's not necessarily commercially adjacent to what SpaceX is doing. And so there's a, kind of a dearth of providers. And, and, you know, it's certainly something that we want to run at. Right now we do a bunch of partnerships. Um, we build a bunch of our own stuff, we, we integrate a bunch of really interesting technologies. But it's a— it's a huge open hole I think in the market that is something we definitely would run at.","offset":2552,"duration":72},{"text":"Host: So we have that as one. Any other categories that you're like, \"that's, like, prime for the taking, I wish we had more money for that?\"","offset":2624,"duration":5},{"text":"Matthew Steckman: Most of the rest are like kind of uninteresting. It's just consolidating around where we're already winning.","offset":2629,"duration":9}],"startTime":2364},{"title":"Competitors & Capital Discipline","summary":"The conversation covers the importance of respecting competitors and avoiding hubris, as Matthew details Anduril's conservative capital management and long-term corporate vision.","entries":[{"text":"Host: Do you respect Helsing as a competitor?","offset":2638,"duration":2},{"text":"Matthew Steckman: I respect everybody as a competitor. I think the worst thing you can do in this business— again, you know, I at the start of the conversation I mentioned hubris— I think it's like the second you start to have, you think you're better than everybody else, you're, you're going to get knocked in your ass. And so I think I in particular on our leadership team hopefully people would agree I provide a check against the hubris. You have to respect everyone.","offset":2640,"duration":26},{"text":"Host: You do, you're unusually humble for the Anduril founding team. You are, honestly, dude. Like I love Grimm, but I wouldn't say he's like super humble. I don't think I would say it either. I know Palmer, great dude, wouldn't say he's super humble either. Takes all types, I know, it takes all types. And you are so thoughtful and kind. You're nice.","offset":2666,"duration":25},{"text":"Matthew Steckman: Never forget I am an international arms dealer, so just keep that in the back of your mind, you know?","offset":2691,"duration":5},{"text":"Host: Oh, well there we go. It's like the Nicholas Cage movie. Have you seen this movie?","offset":2696,"duration":3},{"text":"Matthew Steckman: Yeah, yeah, yeah.","offset":2699,"duration":2},{"text":"Host: That's amazing. But okay, I will push back on you, dude, you're Anduril's one of the hottest companies in a world where capital concentrates towards the few outcomes that are interesting. You could raise— I mean, you don't need to comment on the fundraises, but like it's reportedly raised 4 or 5 or 6 billion or whatever it is, at 60 billion. The amount of SPVs for Anduril— Matt Grimm tweets about it all the time, I see it. Like, you could raise another billion or two billion on some crazy price and go buy these companies. Why don't you?","offset":2701,"duration":33},{"text":"Matthew Steckman: It's not the company we want to run. Um, we want to create an enduring public company and so we're running it like that. We're running it like that right now even, even though we're pre-public. And so, um, I think protecting the valuation is important, um, not getting over our skis is important. The work is still hard. We will get knocked back if we make a mistake. We don't have the luxury of making mistakes. You know, a lot of our competitors, the really big ones, if they make a mistake they get paid to fix it. I think if we make a mistake, we lose money and we, we lose contracts. So there is a bit of conservatism on the team but I think it's warranted in terms of the market and in general, right? It's like we want to be a company in 2050 and 2060, um, and we're already thinking like that.","offset":2734,"duration":49}],"startTime":2638},{"title":"IPO Strategy & Product J-Curves","summary":"Matthew explains the rationale for eventually taking Anduril public, detailing the immense capital required to accelerate defense products through a shortened development J-curve.","entries":[{"text":"Host: Totally understand, but what I don't understand is why you want to go public. We see companies like Stripe who are able to not go public, be a brilliant business, uh, and avoid the glare of public markets very efficiently. Why would you want to go public?","offset":2783,"duration":17},{"text":"Matthew Steckman: There's a pedigree to it in the work that we do. And ultimately if you are a part of the national security apparatus in the United States, I wouldn't say it's like an expectation and no one would ever say it out loud, but when you are a public company there is an additional level of trust that is afforded to you that you don't have when you're a private company.","offset":2800,"duration":20},{"text":"Host: Do you want to go public in '26?","offset":2820,"duration":2},{"text":"Matthew Steckman: Still a couple years out, but we're close. We're in the window.","offset":2822,"duration":4},{"text":"Host: It's in the sniff zone, it's, like, close enough.","offset":2826,"duration":3},{"text":"Matthew Steckman: Yeah, yeah, yeah. Like we're already spending an insane amount of money trying to, trying to do all the internal system stuff and all that kind of stuff.","offset":2829,"duration":6},{"text":"Host: What do you not have ready yet that needs to be ready to be public?","offset":2835,"duration":3},{"text":"Matthew Steckman: So I mentioned we have 20 products, um, and um, only about a quarter of those are in any kind of rate production and throwing money back to the business. Everything else is in low rate or development, meaning they're losing money. Um, and so, right, it's, it's kind of your standard product J-curve. So we need more of those 20 core products to come up the curve to throw money back to the business and then, and then you trigger the, the public event.","offset":2838,"duration":33},{"text":"Host: What does that J-curve look like from a duration standpoint? Is it, is it months? Is it years? And then how long do you put up with a losing product before you shoot it?","offset":2871,"duration":8},{"text":"Matthew Steckman: Yeah. So in defense, typically in a traditional sort of product curve it's 7 to 10 years. Um, we're doing it in 3 to 5, which is kind of part of the magic of the company and the thing we've become known, known for with our customers is like you're effectively halving the traditional path to rate production. Roadrunner is a good example. Roadrunner was I think 24 months from like a back of a napkin drawing to a fielded system.","offset":2879,"duration":34},{"text":"Host: How much goes in in that 3 to 5 year period?","offset":2913,"duration":3},{"text":"Matthew Steckman: Oh so much. It's crazy amount of money.","offset":2916,"duration":2},{"text":"Host: But just like for my naive brain, is it 100 million or like 500 million or like a billion?","offset":2918,"duration":4},{"text":"Matthew Steckman: Yes, so Roadrunner is a moderately sized, uh, air defense kinetic intercept system and that's, you're over 100 million easily before you're generating revenue.","offset":2922,"duration":12},{"text":"Host: And we have 20 of these separate products?","offset":2934,"duration":2},{"text":"Matthew Steckman: Yeah, so it's a lot of investment, right? So you really have to believe that they're going to come up the curve. Um, and then to your other question about like when do you, when do you schwack a product, we schwack it before we even, like, the better way to think about it is like don't even enter the curve if you don't have faith that it's going to come through the other end. And so we kill a lot of developmental products well before they ever get into high spend because once you get into that curve you're, you know, 10, 20, 50, 100 million dollar plus in.","offset":2936,"duration":27}],"startTime":2783},{"title":"Learning from Early Mistakes","summary":"Matthew shares the story of an expensive early failure with an aerial system, noting how that misstep ultimately paved the way for their successful autonomous jet fighter program.","entries":[{"text":"Host: We spoke about like what did you not do and you said like offensive cyber and the cyber that we discussed earlier. What did you do that you shouldn't have done, and what do you learn from that?","offset":2963,"duration":8},{"text":"Matthew Steckman: That's a good question. Um, way early, I mean we, we got into some tech that we weren't ready for, um, we got into some markets that we weren't ready for. We tried to early on build a pretty sophisticated aerial system, we didn't have the core building blocks, we didn't have the core team. Um, I think we were 20 million or 40 million in before we kind of realized that it was, it was a scrap. We didn't have the sophistication with the customer, we didn't know how the customer was going to buy a, a vehicle of that sophistication. The kind of crazy part about all of this is like, well okay, given all of that and given that that was not a good business decision like clearly by most metrics, do we even get to build the autonomous jet fighter if we had never made that mistake? And so like it's hard to replay history sort of perfectly, right, and it's like I don't think so. I think part of that failure was a stepping stone to getting to success. Um, yeah we probably spent too much money on it and could have gotten out quicker, but like I think we had to learn that lesson in order to then re-approach the aviation market in a new way, which obviously has, has been quite successful for us, um, you know in recent history. And so if you, if you look at a lot of these failed things that we've done, it's hard to separate that from what came after it.","offset":2971,"duration":81},{"text":"Host: Final one before we do a quick fire. I always think to this question of, like, the biggest challenges in life are not like— it sounds so corny— but like, not iron or gold but unmade decisions. I never made the decision to move to Silicon Valley and everyone always reminds me that it will be the decision that haunts my career. Is there an unmade decision that ever haunts you?","offset":3052,"duration":22},{"text":"Matthew Steckman: No, but I'm kind of weird that way. I have trouble separating indecision and failed decisions from the current success that we're actually seeing as a company. I, I just do. And so people talk a lot about, um, I think like these overblown, uh, sort of ideas around like, \"Oh you have to learn from failure and fail fast,\" like yes, all of that's true. Most people suck at actually doing that. And, you know, so for me it's I deeply learn from indecision and from bad decisions, um, but it doesn't like haunt me and it doesn't, like, I'm not going to like kill myself over it, right? I'm going to, I'm going to move on and I'm going to make the next best decision.","offset":3074,"duration":42}],"startTime":2963},{"title":"Quick-Fire Questions & Outro","summary":"In a rapid-fire closing segment, Matthew discusses the future of autonomous warfare, offers career advice, and jokes about choosing a co-founder for a hypothetical future startup.","entries":[{"text":"Host: Dude, I want to do a quick fire with you. So I say a short statement, you give me your immediate thoughts. Does that sound okay?","offset":3116,"duration":3},{"text":"Matthew Steckman: Sure.","offset":3119,"duration":2},{"text":"Host: What's one belief you have about modern warfare that most people think is insane?","offset":3121,"duration":5},{"text":"Matthew Steckman: I think a lot of my beliefs and our beliefs, uh, that we started the company on are now becoming a bit more commonplace. You know, when we started the company maybe we were a bit out of on a limb of like, \"Could I replace every single mission that the current set of technology provides us with an autonomous system?\" I believe that that is true in the long run. I also believe that we're not even close to where a lot of people think we are on it. I think we're still in the early days on, on tons of this tech. Um, but as time goes to infinity, like absolutely every single mission can be replaced, uh, with this new way of thinking. In 2017 when we started the company not only was that not widely held, you know, that, that was a headwind for us. I think that's changed pretty dramatically.","offset":3126,"duration":53},{"text":"Host: What do VCs fund in defense that you think will most go to shit? What are you like, \"Oh—\"","offset":3179,"duration":8},{"text":"Matthew Steckman: It's really companies that there is only one large program to capture. That's like fundamentally what it is. Um, in defense you have to be wide by the very nature of how acquisitions occur. Um, and so I think anything is a risk where it's like, \"Nope, there's kind of one program and if you don't win it, you're not a good company.\"","offset":3187,"duration":22},{"text":"Host: When you think about your kids, what do you tell your kids or kids graduating college about the world when it comes to career advice, knowing and seeing all that you do?","offset":3209,"duration":12},{"text":"Matthew Steckman: Yeah, I mostly say, um, a couple of, of things. I think it's about the community that you surround yourself with. Uh, I, and that, that's a reflection on sort of my own personal story. I mean everything that I've done in my career, um, has been the community of people around me that, um, have helped me, have gotten me jobs, have afforded me responsibility. You know, it's not like some big machine or process, it's, it's really just the people you surround yourself with and um, I like to think I made some pretty good choices early on that helped. And then the other piece would be, I think people tend to overthink a lot of their steps and don't appreciate how much you just can learn along the way. Um, you know, I talk to a lot of, um, military folks that are transitioning out into the commercial world and I would say for the most part they, they kind of like hem and haw over what company they should go to and, you know, my main advice is I actually think you just need to start. And you're actually a really smart person. Um, if you don't like it you can leave. If you like it you got lucky. And you should talk to a lot of companies, you should pick, and you should change your mind when you need to. And I think, uh, often times there's a hesitancy to change your mind, right? And I, I don't think that's actually true. It doesn't need to be true.","offset":3221,"duration":84},{"text":"Host: Final one for you and this is the most unfair of all and that will get you in most in trouble. When you look at the founding team, in a hypothetical world in 10 years time you start another company but you can only take one of them with you as your co-founder. Um, which, which one and why?","offset":3305,"duration":22},{"text":"Matthew Steckman: I can't take them all?","offset":3327,"duration":1},{"text":"Host: No.","offset":3328,"duration":2},{"text":"Matthew Steckman: No? Huh. It's a trick question 'cause there's no way that I'm starting another company after Anduril. I don't know if you know this, but starting companies is really tiring. Um.","offset":3330,"duration":11},{"text":"Host: No, I'm a venture capitalist, we, we don't, we don't know that. We know it's tiring, so we're much wiser than you.","offset":3341,"duration":7},{"text":"Matthew Steckman: I'm just gonna— I'm just gonna retire to the countryside and live with my family and I'm gonna do that.","offset":3348,"duration":5},{"text":"Host: Dude, you've got to choose one.","offset":3353,"duration":1},{"text":"Matthew Steckman: Yeah. I'm not choosing. Don't make me choose. You know I live in Washington DC, I'm very good at not answering questions. Maybe it's Bobik just 'cause the contrast of his baldness and my hair would make us a pretty, pretty formidable duo.","offset":3354,"duration":13},{"text":"Host: Do you think Palmer's brand is helpful?","offset":3367,"duration":1},{"text":"Matthew Steckman: I do. Unequivocally. In defense anything highly regulated, right? Every single thing is a headwind. And so the main thing you do to cut through headwind is you try and establish trust relationships with people who matter. Um, I think Palmer is an N of 1 when it comes to establishing trust relationships with people who matter.","offset":3368,"duration":22},{"text":"Host: I, I've loved this. This is so not how I thought it would be, to be totally honest. It was so nice, it was so fun. I learned, I totally didn't do anything that I kind of thought I would, but thank you. This, like— it reminds me why I love doing what I do.","offset":3390,"duration":13},{"text":"Matthew Steckman: This was great. It— honestly it was great to meet you. I do listen to the pod most episodes, um, I love listening to it. Um, so thanks for having me on. It was cool.","offset":3403,"duration":15}],"startTime":3116}],"entries":[{"text":"Matthew Steckman: You basically can't have a defense company if you don't have a large US business. The government thinks that we can deliver some pretty major stuff, now and in the future.","offset":0,"duration":8},{"text":"Host: I am so excited, we've got Matthew Steckman, President and Chief Business Officer for Anduril. Just last week they announced a monster $20 billion dollar contract with the US military, one of the largest ever. We could not have a more apt or pertinent guest, as he takes us behind the scenes of both the contract and of Anduril.","offset":8,"duration":18},{"text":"Matthew Steckman: There are very few drone programs that would create a material enough amount of revenue to actually create a real business. You have to create a monopoly. There are lots of VC companies I would love to buy if I had an unlimited checkbook.","offset":26,"duration":13},{"text":"Host: Is there ever like an ethical question of, do we agree with sending thousands of missiles to Iran?","offset":39,"duration":21},{"text":"Host: Matt, I am so excited for this, dude. I just got off a chat with Christian Garrett and Matt Grimm and they gave me, like, incredibly tough questions, so this is going to be a grueling hour for you. But thank you for joining me, dude.","offset":60,"duration":13},{"text":"Matthew Steckman: Yeah, thanks for having me. It's really great to be here.","offset":73,"duration":3},{"text":"Host: I actually want to start with Trey, weirdly, which was Christian Garrett said that I had to ask this. He said, what was Trey like at Georgetown? And what is it about the Anduril founding team that has made Anduril so successful?","offset":76,"duration":15},{"text":"Matthew Steckman: Well, Trey and I were, were classmates, um, met freshman year, um, played Ultimate Frisbee together on the team. Um, so went on a lot of road trips with one another. Um, you know, I don't think Trey has changed at all. You ever seen the movie Hot Tub Time Machine?","offset":91,"duration":17},{"text":"Host: Yeah, great movie.","offset":108,"duration":2},{"text":"Matthew Steckman: Yeah, there's a line in it that's, like, \"every group of friends has an asshole, but Trey is our asshole,\" you know, you know what I'm saying? Yeah, that's Trey in a nutshell.","offset":110,"duration":12},{"text":"Host: And he's gone on to such things.","offset":122,"duration":2},{"text":"Matthew Steckman: It's crazy how that works, yeah.","offset":124,"duration":2},{"text":"Host: It has hope for you. You know, I've never had such a weird start to a show.","offset":126,"duration":5},{"text":"Matthew Steckman: There you go. No, we're kicking this off right.","offset":131,"duration":2},{"text":"Host: It's like a movie reference and then \"Trey is our asshole.\" Yeah, yeah, he'll love that one. Yeah. In terms of the team itself, I have so many defense companies pitch me, and I think bluntly the team is always lacking. What do you think it is about the team that Anduril has in terms of founding team, that has made it so successful?","offset":133,"duration":24},{"text":"Matthew Steckman: Well, first, like, there's kind of some magic in the fact that it's the same leadership team today as it was when we started the company. Um, that, that implies a whole lot of things, I think, um, mainly it's that we're all friends. So I think that's actually pretty critical. Um, there, there's a bond there that basically can't be separated by business or stress, um, or life. Um, we, we all know each other really well. Um, but then on top of that, um, we all come at the industry from really different backgrounds and lenses. And especially in defense, which is, um, it's like everything works against you to get into the defense market. There, it's like every headwind you could possibly imagine. If you don't have a lot of perspective and knowledge about what's about to come, it's hard to think around corners and you get yourself kind of mixed up and gummed up a lot. Founding teams, one of the most important things in, in defense is some of them can be outsiders and, you know, brilliant technologists, um, and thinkers. Um, it does take a lot of inside knowledge. Um, and I think that, um, one of the things we, we got right and keep getting right is that blend of, um, like the outside-inside process. Um, who can think, um, differently, um, and bring in sort of commercial perspective, high tech perspective, uh, add kind of entropy into the system. Um, and then who can really deeply represent, um, our customers, how they think, how does that come together uniquely? That, that becomes super important to, to having any success in the defense world.","offset":157,"duration":109},{"text":"Host: I think one of the things I most look for honestly is like GTM experience and ability in a team that I'm looking at in defense. Um, how should we think about analyzing teams for their ability to actually sell and go through procurement? Does it matter if you've got technologists and people with military and combat experience but no one with GTM experience? I know procurement better than fucking anyone.","offset":266,"duration":24},{"text":"Matthew Steckman: It's multidisciplinary, right? So the, the challenge becomes in defense that if you're missing any of the 12 different types of disciplines it takes to really capture a large program, you will fail. Um, and so one of the things that we've done is over the years we've built up a pretty sophisticated apparatus to kind of round out these teams with all of the various skills in acquisition and budgeting and technology, um, and then again, mission and operational analysis and doctrinally how these types of technologies will integrate into the military. You have to have it all. I think the one, um, maybe, uh, interesting piece here is there aren't actually a lot of big programs in government. And so one of the things you don't need to necessarily look for, I think, which you would in a traditional hiring process, you would look for someone who has demonstrated the ability to capture a large program in the past. But, but since there's so few of these things, you, you can't really look for that. Sometimes you luck into it and like, great, you should certainly hire people who have shown to be able to capture large programs. Um, you generally don't actually have that in the hiring pool. And so what you ultimately have to do is piece together the right puzzle for everything that you're going after.","offset":290,"duration":79},{"text":"Host: Does it matter if the founding team doesn't have that experience in terms of going through procurement and GTM?","offset":369,"duration":5},{"text":"Matthew Steckman: I think it does. Um, and I think that, you know, I advise a lot of, of companies and um, if I notice that the founding team, at least a portion of it or a person on it hasn't kind of been there, done that, the first thing I recommend is they have to find someone who represents that piece of the puzzle that, that's missing to their team.","offset":374,"duration":23},{"text":"Host: When you meet all of the defense companies that you meet today— again, I'm an, you know, I'm an investor, I do— we have so many different European drone companies, every fucking UAV— I, dude, I don't, I honestly don't get it at all, they come with some other thing and I'm just like, \"Matt Grimm, please tell me if this is good.\" No, I really do, I ask Matt about it, it's very funny. Um, he sees everything in Europe because of me. Um, and tells me that it's shit. Um, but like when you look at them, what is the most common red flag that you see when you look at the emerging class of defense companies trying to be, as awful as it sounds, the next Anduril?","offset":397,"duration":34},{"text":"Matthew Steckman: I think it's basically two things. It's, um, uh, not realizing that what they are doing, uh, already exists. There's too much hubris, I think, in the technology market that, um, as high tech people we can, we can do everything better than everybody else. I think, um, that causes, uh, some companies to think they have an idea that isn't actually an idea because it already exists and that's pretty common. Uh, I'll give you an example. I, years and years ago I, you know, was looking at a pitch or I forgot, maybe I was advising someone and, \"Here's my idea,\" and I said, \"Well, the thing you don't know is in the 1960s we invented that.\" And so, so there's a, there's kind of a hubris to thinking like, um, the technology sector has all the answers when, like, actually since the '50s we've had the most brilliant people in the world working on these problems and a heck of a lot already exists. And this is sort of the point of like, if you don't actually have the inside knowledge you don't know what mistakes you're making. So that's one. The second, uh, which will be more familiar to you, is, is addressable market. Um, I think there's, uh, in many cases an overestimation of addressable market where like actually what ultimately they're going after is a very small sliver of a problem, um, which might materialize in a, a single large contract, but a single large contract is not an enduring business.","offset":431,"duration":91},{"text":"Host: And this is one of the big challenges that I face, is when we see a company that in France is saying \"we're selling to the French military.\" Dude, I don't know how to say with— I upset everyone these days, I just get used to it. The French military spend less than I do in Chanel for my mother. I mean, it's like fuck all. And so my point is, like, can you be a European-only next-gen prime or do you have to be selling to the US as well? How do you think about that?","offset":522,"duration":25},{"text":"Matthew Steckman: Yeah, I mean, you basically can't have a defense company if you don't have a large US business, right? So 50% of defense spending is in the US and 50% is in the rest of the world. And so if you are cutting off half of your market from the get-go, that's, that's probably a big problem. The, the challenge in Europe is it's not, it's not like a European Union in defense spend, right? Each country has its own sovereign, uh, companies and has its own sovereign agenda and so you keep getting winnowed and winnowed and winnowed and you're like, \"Oh, well Europe is my market.\" Well, if you're a French company, it kind of isn't, right? France is your, your market. Um, and so you have to be really careful around how you're actually analyzing who your ultimate customers can be.","offset":547,"duration":45},{"text":"Host: You mentioned 50% of that spend is in the US. You guys signed a $20 billion dollar contract. Um, it's pretty incredible. It made me feel thoroughly irrelevant when I look at my companies going from 1 to 4 million in ARR for an HR software company and the whole team's like, \"Ah, bugger.\" Um, my question to you is, what's actually entailed in the $20 billion dollars? Was it like an accumulation of all the little contracts brought together? 'Cause it's a big headline number but I didn't actually get it and I don't think a lot of people did.","offset":592,"duration":32},{"text":"Matthew Steckman: Yeah, yeah. So let's, let's, like, actually define it because the stuff I saw posted about it was all over the place. It was like a rainbow of interpretations. So this is, think about this as like a, um, a credit card limit. Um, so the government has said up to $20 billion dollars they can spend on a class of Anduril's commercial technology. Um, there's no obligated money, but it basically creates, uh, a process that reduces a ton of friction that you would ordinarily see in defense procurement, where each individual office would have to go through financing and contracting and evaluation. Um, and all of these repeatable things now, can now only have to happen once. And they did, and they just did. And so, um, maybe a fast track is probably the wrong word, it's more like in the arduous process to actually get something contracted we've cut a lot of the first steps out. Um, there's still a lot of hard work. We've just made it slightly easier for the government to access all of our gear.","offset":624,"duration":70},{"text":"Host: When they say, like, \"dependent on delivery,\" what does \"delivery\" mean?","offset":694,"duration":4},{"text":"Matthew Steckman: They will obligate the dollars as the products, which is hardware and software, are actually materialized. So delivery is revenue to us, right, in our world. So when I deliver something I recognize the revenue, um, same thing in government. When we deliver something, they actually then the actual procurement orders and dollars flow.","offset":698,"duration":20},{"text":"Host: Again, I'm so sorry for being dumb or naive, I'm a venture capitalist for a living, you should be used to us by now. Um, is this replacing prime spending? Is this net additional? How should we think about this? And is this just the sign that Anduril is now another prime?","offset":718,"duration":16},{"text":"Matthew Steckman: Yeah. It basically means that we have enough business with the federal government to justify putting together what is a fairly sophisticated contracting vehicle. Um, so yeah, the short version of it is like, yeah, the government thinks that we can deliver some pretty major stuff, uh, now and in the future. Um, it took a lot of work by a lot of people on the government side to actually make this thing happen. They are not going to do that unless they think that it's worth it.","offset":734,"duration":26},{"text":"Host: What do they spend with, like, a Lockheed or a Northrop for, like, comparison?","offset":760,"duration":5},{"text":"Matthew Steckman: So Lockheed I think is in the, like, 100 billion revenue a year. Um, I think we'll do a couple billion in revenue this year. So we're still, you know, small in the grand scheme of things.","offset":765,"duration":10},{"text":"Host: When you look at the software and the hardware element, how do you guys sit internally? Are you a hardware company? Are you a software company? Are you a services company? Ultimately, how do you sit?","offset":775,"duration":11},{"text":"Matthew Steckman: There's a lot of ways to look at it. So I think one of the things we've done maybe uniquely is we've given our customers a lot of ways to access our company. So what I mean by that is, um, um, we've been very creative in, \"Okay, a customer wants a piece of software, uh, but it's difficult in government to contract for software.\" And so we can wrap it in a hardware appliance, right? Or they want a piece of hardware but they know the software is the sophisticated piece of it, um, and so they're willing to pay more for it because of that sophistication. Or, uh, in government, um, you get these weird things where, uh, money is, it's called \"the color of money,\" so money is obligated to certain types of spend. So maybe a customer only has money that they can spend on services. Well, okay, can I do an as-a-service product? Um, and actually one of our, our first major contracts was with, uh, US Special Forces, uh, for, uh, all of their counter-UAS, uh, systems. That started as an as-a-service contract where they weren't buying hardware, they weren't buying software, they were literally buying, uh, a service that obligated us to defend certain sites from certain types of threats. And as long as we were meeting the KPIs on the contract, um, we were fulfilling the obligations of the agreement. Um, so quite novel, uh, and that contract has, you know, since gone in a lot of different directions and we do a lot of different things on it, not just that, but we have been kind of dogged in our, uh, approach to this by basically realizing that the more ways we give our customers to get at us, the better it's going to go.","offset":786,"duration":106},{"text":"Host: What's the hardest thing about working with the government when you look at the structures that you have to contort yourself in to get a deal done? What's the hardest thing? I've interviewed Shyam, who I presume you work with from Palantir.","offset":892,"duration":15},{"text":"Matthew Steckman: Yeah, yeah, I worked for Shyam for a really long time. He's a good friend of mine. Um, there's a lot of answers to this question, but maybe from my lens, uh, it is, uh, it is how few and far between the large wins are and how hard it is in between those periods of time. So if you look at our business, you know, this year we'll do a couple billion in revenue. We'll do 600 separate contracts this year. Um, only 20 of those are probably of material revenue size. I think the hardest thing is, like, what happens in between the 20? And what are you doing to position yourself for the 21st? And because it's so concentrated, every single one of those deals is considered risk to the business, right, if it goes right or if it goes wrong. So.","offset":907,"duration":49},{"text":"Host: Why specifically is it hard in between? Is that morale? Is that revenue predictability? What is it that's hard in between?","offset":956,"duration":8},{"text":"Matthew Steckman: The government can sometimes tell you where they want you to go, but often times they don't. And so a lot of this, uh, is trying to predict an unpredictable system, right? So how many lenses can you look at at sort of the next couple of years? I can look at it through what the government is saying through their rhetoric and through their budgeting. I can look at it through a war fighting lens and what general officers are saying and what, um, military theorists are saying. I can look at it through a technology lens, like what technologies do I, I think are going to influence the battlefield in the future. And I need to kind of blend all of that together today to make decisions on what I want to build that will be available, you know, five to seven years from now. Um, no one is saying today, \"this is what I need five to seven years from now.\" It's, it's all sort of a, an educated guessing game over time.","offset":964,"duration":54},{"text":"Host: What did you not do that with the benefit of hindsight you wish you had done, and what did you learn?","offset":1018,"duration":8},{"text":"Matthew Steckman: Um, there's been a couple of areas that, you know, have, have kind of emerged that maybe we were a bit slow in, that we would have accelerated. I'll give you an example. Um, uh, there's a huge movement in, uh, not just in the US but NATO and the rest of the allies, um, into offensive cyber warfare. Um, and you're seeing this now becoming public for the first time, which is really, really interesting. Um, you know, to date this has been one of the, the spookiest of all spooky things, right? Like something that just no one ever talks about and now you're, you're literally seeing public officials talking about it for the first time. We should have moved into that seven years ago and been the first, the first in it. We weren't big enough probably to really even understand it seven years ago, but like in hindsight it was kind of obvious. Um, you know, we'll probably try and play some catch-up here and, and get into the game, but, you know, there's a couple of examples like that where you see these things kind of thematically in hindsight, um, and you're like, \"Well, obviously five years ago I should have done it,\" right, and you only realize that today.","offset":1026,"duration":64},{"text":"Host: What is the fear with offensive cyber, when we look at, like, the worst case scenario? Just so I understand it.","offset":1090,"duration":6},{"text":"Matthew Steckman: Well, it's a lot of things. So it's both what are our adversaries doing and do we understand it, and are they asymmetrically influencing, uh, battlefield tactics? And the answer is yes, they are. Um, and then it's, okay, well if our capability—","offset":1096,"duration":18},{"text":"Host: Sorry, sorry, can I just stop you again before I get lost in your next statement. What does it mean like \"asymmetrically influencing battlefield tactics?\"","offset":1114,"duration":6},{"text":"Matthew Steckman: Yep. So for a very, uh, one version to think about this is just cost. For a very low cost they can create an effect that has, uh, major implications for us, NATO and our allies. That's asymmetric. So, uh, often people refer to terrorism as an asymmetric tactic, right? For a minimal set of people—","offset":1120,"duration":22},{"text":"Host: But this would be like a $10,000 dollar drone that hits a $1 million dollar—","offset":1142,"duration":5},{"text":"Matthew Steckman: Drone warfare is as— an asymmetric battlefield tactic, exactly. Um, and cyber being not only asymmetric but you'll often hear the term \"non-kinetic\" associated with it. So I'm asymmetric as in I'm, I'm cheaper and more, more nimble and I can get a large effect, but I'm also non-kinetic. And, and why is that so, so dangerous? Well, when something explodes, uh, we react to it and we react to it, uh, with the full force of, uh, of the military. When things are kind of simmering beneath the surface, and sort of a cold war-ish type of a way, it actually becomes really hard to react. And so in cyber warfare in particular, if assets are affected that we care about, well can we— can we do attribution? Do we know where it came from? How do we respond? Do you respond with a non-kinetic attack by going kinetic? Is that an escalation of force? How is that perceived by the global community? Right? So you, you get into all of these really challenging doctrinal, uh, positions because of, uh, just sort of unexplored offensive cyber is. Um, and then on the flip side, right, it's like do we have the ability to amass cyber effects on our own? Right? 'Cause what you would want to do is you would want to do tit for tat. You wouldn't want to do, in- for the most part, a set of like escalatory decisions. You would want to, you know, match force with force. Do we have the ability to amass the same kind of force non-kinetically? Right? So all of these are super important questions that, uh, in my opinion to date have not been debated publicly and, and absolutely need, need to be.","offset":1147,"duration":103},{"text":"Host: Can I ask you what cyber assets do we care about versus not care about?","offset":1250,"duration":5},{"text":"Matthew Steckman: What do we care about protecting or what do we care about affecting?","offset":1255,"duration":4},{"text":"Host: Both actually, if that's—","offset":1259,"duration":1},{"text":"Matthew Steckman: Yeah, well protecting, right, probably the main one is like the list of critical industries. Um, the military is included on that list. Um, but think about infrastructure, think about power, think about, um, energy, think about all these things, right?","offset":1260,"duration":14},{"text":"Host: Okay, so it's like a foreign adversary impacting energy supplies in large cities or water supplies. For sure. Um, healthcare data or financial systems, I guess.","offset":1274,"duration":12},{"text":"Matthew Steckman: Yep, yep. But even, even now though on the battlefield, it's a foreign adversary impacting our military systems such that we can either not mount an offense or we can, uh, not, uh, successfully defend ourselves.","offset":1286,"duration":12},{"text":"Host: Okay, gotcha. And so that, that's the cyber assets that matter on the defense side. On the kind of offense side?","offset":1298,"duration":6},{"text":"Matthew Steckman: Everything that they would do we would do too. Yeah, exactly. That's the way to think about it.","offset":1304,"duration":7},{"text":"Host: Is there any part of you that's like, Northrop or Lockheed have a $100 billion dollar spend, with the greatest of respects we have a $20 billion dollar spend, we're nowhere in offensive cyber, fuck it, let's not try and catch up. No, I mean in the nice way, you can laugh at me and maybe I'm going to get killed for this but I don't really care. Like, let's just accelerate where we're doing great. Like why bother catching up when you're 70 years behind?","offset":1311,"duration":24},{"text":"Matthew Steckman: Well let's like talk about just like our strategy as a whole. So when we started the company we knew we had to go really wide really quickly, right? 'Cause to the point of like what do other defense companies or newer founders get wrong, it's that addressable market question. So in every technology class in defense there's probably one, sometimes two actual programs that if you capture them you have a business and if you don't you have no business. Um, so take small drones as an example. There are very few drone programs for small drones that, uh, would create a material enough, uh, amount of revenue to like actually create a real business, right? And so like you're basically shooting the moon, uh, you have to create a monopoly. We knew that and so what we did is we created a bunch of fundamental technologies that are applicable to a lot of different types of problems. Um, if you read about us, um, this is called Lattice in a lot of our, like, published literature. Fundamental tech that allows you to consume data, make sense of it, and then, uh, manipulate robots basically, like that's what it is. Those technologies apply to tons of different things and so we have 20 different P&Ls at the company, uh, all that are going after different parts of the defense apparatus that take a lot of these fundamental technologies that we built and kind of piece them together in different ways. And so.","offset":1335,"duration":91},{"text":"Host: So just so I understand, so it's kind of like a horizontal foundational technology that you then verticalize and specialize to fit individual P&Ls.","offset":1426,"duration":8},{"text":"Matthew Steckman: Lattice is a software platform, exactly. Like, uh, I can talk about software platforms with you. It's hard to actually talk about software platforms with a lot of people 'cause it's, like, if you don't actually understand, like, what we're talking about it's, it gets a bit weird. But yeah, Lattice is basically just a software platform that we can branch from. Um, and it's led us into all of these, uh, interesting places. So, like, um, as a really crazy example, uh, the first product we built was a sensing tower, uh, that just allowed us to automatically through a bunch of computer vision technologies— and this was by the way pre-like cool AI, this was like old school CV AI, um, in 2017— just allowed you to spot threats at distance, right, but automatically without a person having to look at a screen. There are pieces of that technology that are resident in our autonomous jet fighter today. Right? Not, not all of it, right? Like there's been a lot of advancements since then, but there are code blocks, right, that are, are shared in common between all of our pieces of technology. That becomes like pretty magical when you approach whatever the next problem is, because you've already got pieces of it solved. Um, gives us a head start, allows us to get to market at usually reduced cost, usually a better schedule, kind of hitting all of the performance characteristics that our customers care about. So. Okay, so back to the actual question on cyber, right? So, so why go after it? Like we, we kind of have to go wide and we have to believe that we have parts of the problem already solved with the platform in order to even approach a market. We wouldn't get into a market if we didn't think we already had applicable technology or a technology tailwind, but where we do, we're, we're definitely going to go after it.","offset":1434,"duration":106},{"text":"Host: What you said was, was fascinating to me. You were like, \"basically you have to assume a monopoly market if you want to build a big enough company for drones.\" Why the fuck are there so many drone companies then?","offset":1540,"duration":10},{"text":"Matthew Steckman: Yeah. Um, I don't know.","offset":1550,"duration":4},{"text":"Host: I mean— I've seen— I've seen so many, like 30, 40 in Europe, just European ones.","offset":1554,"duration":6},{"text":"Matthew Steckman: Yeah. It'll be one that wins, right? It's, it's going to be really hard to pick it, I think is the problem. Um, like there will definitely be one winner. Um, I think the challenge for investors is actually figuring out which one it is.","offset":1560,"duration":13},{"text":"Host: So we should invest in, you know, offensive cyber and defensive cyber. How do we think next-gen? You're CBO, you're president. You like, \"Great, we should put a billion dollars against it and build that out as a separate business unit.\" Like, and please tell me where I'm wrong. Like what's the subsequent thought to that?","offset":1573,"duration":18},{"text":"Matthew Steckman: Yeah, so the way that we do this is, um, when we have a new idea, um, we basically start a really small tiger team that we generally piece together from various parts of the business. Um, and we, we kind of match our own internal motivation and, and spend, our own IR&D, um, to what the market is whispering to us. So in government what this generally looks like is you, you piece together, uh, some tech really, really quickly so that you have a demonstrator or at least a dart to throw. Um, and then you start to pulse the market and you see how, how close was that dart throw to what the customer actually cares about, how they think about the problem. Do you modify it? Were you totally off and you just need to scrap it and start over again? Um, and I think in government uniquely you know you have something when the customer's excitement starts to match your own and all of a sudden you're kind of walking down a path together as opposed to this weird like vendor-customer relationship. That's always how we kind of identify that we're on to something. I would say all of these things can be characterized by, like, a singular champion on the other side of the table that gets it, that believes in it, that wants to shepherd it. Uh, actually you mentioned Shyam, he talks a lot about this kind of heroism, like it actually comes down to a single person in government a lot of times. Same experience for us. Um, and if you do it right, it kind of tracks similarly. You know, the first year's low dollar spend but there's a lot of learning. Um, and you sort of jump from— I, I tend to use this like lily pad example, you kind of jump from pad to pad and this is what I mean by the 600 contracts in between the 20 that matter. You're basically jumping from contract to contract trying to figure out \"Do I have it right? Is the customer excited? Are they telling me things? Do we keep going? Do we keep spending?\" and ultimately the thing you're trying to jump at is something very large.","offset":1591,"duration":137},{"text":"Host: How do you know when you have something really special and when you should concentrate capital? Again, I think the best founding teams are the best resource allocators. When do you unleash the funding tap and open it up versus constrain and move from little lily pad to lily pad?","offset":1728,"duration":15},{"text":"Matthew Steckman: Yeah, there's a lot of ways to look at our business, but, but one way I think you hit on it is we've been very good at allocating capital. Like, we basically guess right most of the time. If you do this correctly you have enough data to develop conviction to open the tap, right? And so I think in the beginning we were working in areas where if we made a mistake, um, it wasn't, we weren't like too far in on spend that if we pulled back it wasn't like a disaster for the company. I think a lot of the stuff we're building now is quite sizable and expensive and so you're looking for certain proof points along the way and that can be, um, formal, uh, feedback from a customer. That can be informal. That can be, um, um, successful operator, uh, feedback. That can be, uh, successful engagements, um, with the legislative branch— like remember in the US, like your funder is, is the Congress, right, and so they have a say in all of this. What actually it is, it's all of those things pieced together. And so we run like basically an investment committee internally where, uh, these tiger teams ultimately have to present, \"Here's what we did, here's what we discovered, here's what we want to do next, here are the gates, here's what it'll cost.\" Um, and very similarly to how, you know, most financial institutions do it, um, the investment committee says, \"Go.\" And I think maybe uniquely when we say \"Go,\" um, we have the ability to do it faster and at a higher level of spend than most of our peers, which is a huge advantage. And so when we actually develop conviction in something, we pretty much believe we can get there faster than everybody else because of it.","offset":1743,"duration":101},{"text":"Host: If we think about it as an investment committee, we're speaking a language that I know now. Which tiger team was the most successful bet and which was the least successful bet?","offset":1844,"duration":10},{"text":"Matthew Steckman: The most surprising, uh, cases to the upside right now, uh, is in our missiles portfolio. So we started our missiles business a couple of years ago. Um, if you read about us, um, the best example we call the Barracuda family of systems. So it's, uh, it's basically a, a set of, uh, cruise missile, uh, systems, different sizes, different shapes and things like that. We basically got into the missiles business, um, looking mainly at, um, sort of this, the actual like military warfare lens. Like there is clearly a gap in capability, we clearly believe that we can be ahead of everybody else if we've already developed it and when the customer asks for it we'll have it. And that turned out to be quite, like, quite prescient. Now, uh, I don't know if you've seen but there's like a war going with Iran. Um—","offset":1854,"duration":58},{"text":"Host: I, uh— have seen, yeah.","offset":1912,"duration":2},{"text":"Matthew Steckman: Yeah, and so it's like okay, so we, we got into this market years ago with a certain set of theses and geopolitics now has dramatically changed what those theses are, to the upside.","offset":1914,"duration":17},{"text":"Host: When you say it's changed them, do you mean it's confirmed them?","offset":1931,"duration":2},{"text":"Matthew Steckman: It's confirmed them, but it's confirmed them in such a way where it feels wholly different. You know, I think the original theory was we have to get low cost, we have to get more ubiquitous, um, we have to have a mix of exquisite systems and mass, um, like all of these kind of major theories of warfare are kind of all converging at the same time. Um, we have to be able to build something that takes advantage of commercial supply, uh, and commercial manufacturing techniques as opposed to aerospace and defense supply and technique. You know, this kind of like crazy crystallization of a lot of things at the same time. And now, okay, we, uh, there's a war in Iran, we fire a lot of our arsenal. Um, you know, now there's public reporting that, um, you know, large percentages of our offensive and defensive missile systems have been expended. And they're really hard to replace. They take a really long time and they're very expensive because they take advantage of parts of the market that are kind of strange and very specific and very exquisite. You know, just to give you an example, the cruise missile we build, the, the actual airframe is built like you build a bathtub. Um, and so we can take advantage of tons of contract manufacturers in the United States that can actually build a bathtub, right? So just thinking through the design differently from the very beginning has led us to build something that we can just turn on. It's like, uh, another way to think about it is you can handle elasticity of demand for the first time. Um, and that, that's not really a thing that's ever existed in the missiles business, right, where you have a fairly, uh, labor intensive process to increase or, or frankly sometimes decrease demand. Um, I think we've, we are on to something and that we've built kind of a first-of-its-kind that can handle the ebb and flow of geopolitics and warfare. Uh, we can turn lines on and off, we can scale up and down based on the number of contract manufacturers that we engage.","offset":1933,"duration":126},{"text":"Host: What do margins look like for these types of products? What, what is good?","offset":2059,"duration":6},{"text":"Matthew Steckman: Yeah. As a business we run, uh, sort of 40% plus gross margin across the board. Um, and which by the way in hardware and defense is quite good. Um, uh, but every product like kind of lives along a spectrum as you can imagine. The best way to think about this is things that you make more of, like missiles where you're selling thousands and thousands, tend to be a little bit lower gross margin, um, and things that you make less of, uh, you can, you can tend to, to get a decent price for it.","offset":2065,"duration":32},{"text":"Host: Sorry, I'm naive. Why is that? I thought the more you produce, the better the margin would be because you have bulk materials, bulk buying. No? Like help me understand that.","offset":2097,"duration":10},{"text":"Matthew Steckman: It mostly comes down to customer expectation for what these things like should cost over time and then your ability to, uh, gain back margin by cost saving in the long run. Yes, you can close a firm fixed price contract, it doesn't necessarily mean that you can fix that cost forever. Um, and again, it's just like another weird aspect of government business.","offset":2107,"duration":21},{"text":"Host: Can I ask you a weird one? But Matt did say I could ask it. Is there ever like an ethical question of, like, \"Do we agree with sending thousands of missiles to Iran?\" I'm not saying right or wrong, but is there ever an ethical question of how your products are used?","offset":2128,"duration":16},{"text":"Matthew Steckman: If you, um, if you work in defense and if you start a defense company your moral compass tends to be pretty clear on this question, which is we have a democratically elected set of governments that represent the US, the alliance, NATO, all of the countries participating. They set the rules. Uh, and we abide by those rules. Um, and if you start to mess around with anything within that framework you create a, a pretty dramatic set of slippery slopes that, that if you play the actual thought experiment to its end, um, end up in a pretty messy situation. And so the, the key here is people that live in the world that I live in, we, we tend to think a little bit differently than, um, uh, a person not connected to the national security community on this front. We tend to think a bit more long term as well, where I'm building missile systems that might only field in 2035. All right? And so if you fundamentally lack a trust in democratic institutions, this is not the game and this is not the business for you.","offset":2144,"duration":69},{"text":"Host: As weird as it sounds and as horrible as it sounds, is war not great for business?","offset":2213,"duration":5},{"text":"Matthew Steckman: I think that's the wrong view. I, I think, um, if you look at, again, if you look at things that span multiple decades, which is probably the right horizon to think through, everything kind of nets out. Um, and so yes, you'll have spikes in, in conflict. Um, but like as an example, there are many companies that are, uh, profiting off of, uh, the war in Ukraine. Um, and I would posit that for the most part if those companies are myopically focused on that conflict they will not have a business coming out the other end. So it's very— you have to be very careful around over rotating on the problems of today, um, because it can, it can really mess up your strategic thinking.","offset":2218,"duration":45},{"text":"Host: Do you think you took advantage enough of the opportunity in Ukraine?","offset":2263,"duration":4},{"text":"Matthew Steckman: We were still a baby company when the conflict started. Um, so just as a reminder, we were zero people in 2017 when we started the company. Uh, we're about 8,000 people today. Um, we were quite small, a couple hundred people when, um, when the war in Ukraine started. Um, and just sort of as a reminder and now this is kind of lived experience for me and my colleagues: you go to war with what you have. Like that, that saying is very, very true. Like, you, you do not invent new stuff along the way. Um, you, you, you take what you have and you, you see if it works and then you adjust. And so we, we had some stuff in Ukraine but we were just too small. Um, I think if you, I, I think if you play that forward to today, we're heavy participants in the current conflict in the Middle East, um, mainly on the defensive side. We build, um, some pretty sophisticated air defense systems that are widely deployed. So it's a wholly different experience because we're a wholly different company.","offset":2267,"duration":61},{"text":"Host: Are Anduril drones used in Iran?","offset":2328,"duration":3},{"text":"Matthew Steckman: I can't speak to specific weapon systems used in specific situations, uh, but we are for the most part a defensive company in the Middle East, as in we are defending against, uh, incoming threats. So if you've read about, uh, the Shahed drone as an example— yeah— um, we're one of the principal systems today to defend against, uh, that threat in the Middle East. Yeah, other than that, it's, you know, it's hard to get into specifics.","offset":2331,"duration":25},{"text":"Host: Yeah, I would hate for you to reveal some inherent military secrets on 20VC.","offset":2356,"duration":5},{"text":"Matthew Steckman: You become, you become pretty good at talking around these things when, when you do this work.","offset":2361,"duration":3},{"text":"Host: I'm going to be totally honest, that's not in my interest either. Please don't. I'm really comfortable with my nice life. Um, can I ask you, if I gave you an unlimited checkbook, what would you spend on that you're not spending on today?","offset":2364,"duration":20},{"text":"Matthew Steckman: I think there are some venture capitalist-backed defense companies that are making some really, really awesome technology and they are entirely unaffordable to us today because of—","offset":2384,"duration":12},{"text":"Host: And when you say they're unaffordable, you mean they won't sell at an appetizing price to you given the amount of money that they've raised.","offset":2396,"duration":6},{"text":"Matthew Steckman: Correct. Yeah, yeah, the, their valuations are just too high for us to justify the buy. We, we've bought, I think, almost a dozen companies, maybe more, um, but for the most part they've been more traditional style defense companies, um, with what you would command in the commercial market for that type of company. There are lots of VC companies I would love to buy if I had an unlimited checkbook, but right now the multiples today are, they put them out of reach for us.","offset":2402,"duration":29},{"text":"Host: This was going to be one of my questions, which is is there a universe of buyers for the mass of VC funded companies that have been generated in the last few years, and what happens to them?","offset":2431,"duration":12},{"text":"Matthew Steckman: Actually, um, Trey, uh, I, I will always remember when he said this: that, um, never be surprised around how long a company can continue to exist. Uh, meaning like, you know, I think we were sitting around a table being like, \"Oh, like, uh, it's going to come to the point where the multiples will, you know, decrease\" and all this stuff and, and Trey's point was— and, you know, Trey has this annoying tendency to mostly be right, I don't know, I don't know if you know that about him.","offset":2443,"duration":29},{"text":"Host: But he's our— yeah, exactly. He's our asshole.","offset":2472,"duration":3},{"text":"Matthew Steckman: Yeah, he's our asshole. Um, his point was like, we don't know, but it might be a while before we can actually buy these companies. And so I, I don't know. Uh, there's still a lot of investment in defense tech. Multiples are still very high. I actually think our multiple's quite low compared to most of them.","offset":2475,"duration":16},{"text":"Host: Why would you say your multiple is low?","offset":2491,"duration":3},{"text":"Matthew Steckman: Because it is.","offset":2494,"duration":1},{"text":"Host: Hit me. At, like, what, 10 or 14X forward, something like that? Um, but you're seeing deals in 20, 30, 40X forward.","offset":2495,"duration":13},{"text":"Host: My dear friend, you're seeing deals a lot more than that. Like, you, I think you're sorely mistaken on that one.","offset":2508,"duration":5},{"text":"Matthew Steckman: Great. So it's even worse.","offset":2513,"duration":2},{"text":"Host: 20, 30, 40— why don't you times that by 5? Dude, I see like 200. Who would you most like to buy but can't?","offset":2515,"duration":9},{"text":"Matthew Steckman: Oh, man. No, that's a tough one for me to answer. I, like— I would probably either compliment or offend people that I don't want to compliment or offend. Um, but I'll give you like the classes of technology. Super interested in space domain, like the— there's a— a couple of companies that are doing some absolutely fascinating things both ground segment and on orbit. Um, there's a couple of companies flying fast and—","offset":2524,"duration":24},{"text":"Host: Why is ground segment and on orbit interesting?","offset":2548,"duration":4},{"text":"Matthew Steckman: There's this like interesting thing happening in space domain where, um, you've got the legacy primes on the military side that have these very large contracts, um, but they, they perform sort of traditionally, right? So it's going to be very, very high performance but it'll come at a, a cost and it'll probably take a while to get there, right? And then you have, um, SpaceX which is just dominating on the commercial side and when their commercial tech applies, um, you know, they do a bunch of government business as well. There's a weird kind of gap in between those two types of companies where the government wants to move really fast, um, but it's not necessarily commercially adjacent to what SpaceX is doing. And so there's a, kind of a dearth of providers. And, and, you know, it's certainly something that we want to run at. Right now we do a bunch of partnerships. Um, we build a bunch of our own stuff, we, we integrate a bunch of really interesting technologies. But it's a— it's a huge open hole I think in the market that is something we definitely would run at.","offset":2552,"duration":72},{"text":"Host: So we have that as one. Any other categories that you're like, \"that's, like, prime for the taking, I wish we had more money for that?\"","offset":2624,"duration":5},{"text":"Matthew Steckman: Most of the rest are like kind of uninteresting. It's just consolidating around where we're already winning.","offset":2629,"duration":9},{"text":"Host: Do you respect Helsing as a competitor?","offset":2638,"duration":2},{"text":"Matthew Steckman: I respect everybody as a competitor. I think the worst thing you can do in this business— again, you know, I at the start of the conversation I mentioned hubris— I think it's like the second you start to have, you think you're better than everybody else, you're, you're going to get knocked in your ass. And so I think I in particular on our leadership team hopefully people would agree I provide a check against the hubris. You have to respect everyone.","offset":2640,"duration":26},{"text":"Host: You do, you're unusually humble for the Anduril founding team. You are, honestly, dude. Like I love Grimm, but I wouldn't say he's like super humble. I don't think I would say it either. I know Palmer, great dude, wouldn't say he's super humble either. Takes all types, I know, it takes all types. And you are so thoughtful and kind. You're nice.","offset":2666,"duration":25},{"text":"Matthew Steckman: Never forget I am an international arms dealer, so just keep that in the back of your mind, you know?","offset":2691,"duration":5},{"text":"Host: Oh, well there we go. It's like the Nicholas Cage movie. Have you seen this movie?","offset":2696,"duration":3},{"text":"Matthew Steckman: Yeah, yeah, yeah.","offset":2699,"duration":2},{"text":"Host: That's amazing. But okay, I will push back on you, dude, you're Anduril's one of the hottest companies in a world where capital concentrates towards the few outcomes that are interesting. You could raise— I mean, you don't need to comment on the fundraises, but like it's reportedly raised 4 or 5 or 6 billion or whatever it is, at 60 billion. The amount of SPVs for Anduril— Matt Grimm tweets about it all the time, I see it. Like, you could raise another billion or two billion on some crazy price and go buy these companies. Why don't you?","offset":2701,"duration":33},{"text":"Matthew Steckman: It's not the company we want to run. Um, we want to create an enduring public company and so we're running it like that. We're running it like that right now even, even though we're pre-public. And so, um, I think protecting the valuation is important, um, not getting over our skis is important. The work is still hard. We will get knocked back if we make a mistake. We don't have the luxury of making mistakes. You know, a lot of our competitors, the really big ones, if they make a mistake they get paid to fix it. I think if we make a mistake, we lose money and we, we lose contracts. So there is a bit of conservatism on the team but I think it's warranted in terms of the market and in general, right? It's like we want to be a company in 2050 and 2060, um, and we're already thinking like that.","offset":2734,"duration":49},{"text":"Host: Totally understand, but what I don't understand is why you want to go public. We see companies like Stripe who are able to not go public, be a brilliant business, uh, and avoid the glare of public markets very efficiently. Why would you want to go public?","offset":2783,"duration":17},{"text":"Matthew Steckman: There's a pedigree to it in the work that we do. And ultimately if you are a part of the national security apparatus in the United States, I wouldn't say it's like an expectation and no one would ever say it out loud, but when you are a public company there is an additional level of trust that is afforded to you that you don't have when you're a private company.","offset":2800,"duration":20},{"text":"Host: Do you want to go public in '26?","offset":2820,"duration":2},{"text":"Matthew Steckman: Still a couple years out, but we're close. We're in the window.","offset":2822,"duration":4},{"text":"Host: It's in the sniff zone, it's, like, close enough.","offset":2826,"duration":3},{"text":"Matthew Steckman: Yeah, yeah, yeah. Like we're already spending an insane amount of money trying to, trying to do all the internal system stuff and all that kind of stuff.","offset":2829,"duration":6},{"text":"Host: What do you not have ready yet that needs to be ready to be public?","offset":2835,"duration":3},{"text":"Matthew Steckman: So I mentioned we have 20 products, um, and um, only about a quarter of those are in any kind of rate production and throwing money back to the business. Everything else is in low rate or development, meaning they're losing money. Um, and so, right, it's, it's kind of your standard product J-curve. So we need more of those 20 core products to come up the curve to throw money back to the business and then, and then you trigger the, the public event.","offset":2838,"duration":33},{"text":"Host: What does that J-curve look like from a duration standpoint? Is it, is it months? Is it years? And then how long do you put up with a losing product before you shoot it?","offset":2871,"duration":8},{"text":"Matthew Steckman: Yeah. So in defense, typically in a traditional sort of product curve it's 7 to 10 years. Um, we're doing it in 3 to 5, which is kind of part of the magic of the company and the thing we've become known, known for with our customers is like you're effectively halving the traditional path to rate production. Roadrunner is a good example. Roadrunner was I think 24 months from like a back of a napkin drawing to a fielded system.","offset":2879,"duration":34},{"text":"Host: How much goes in in that 3 to 5 year period?","offset":2913,"duration":3},{"text":"Matthew Steckman: Oh so much. It's crazy amount of money.","offset":2916,"duration":2},{"text":"Host: But just like for my naive brain, is it 100 million or like 500 million or like a billion?","offset":2918,"duration":4},{"text":"Matthew Steckman: Yes, so Roadrunner is a moderately sized, uh, air defense kinetic intercept system and that's, you're over 100 million easily before you're generating revenue.","offset":2922,"duration":12},{"text":"Host: And we have 20 of these separate products?","offset":2934,"duration":2},{"text":"Matthew Steckman: Yeah, so it's a lot of investment, right? So you really have to believe that they're going to come up the curve. Um, and then to your other question about like when do you, when do you schwack a product, we schwack it before we even, like, the better way to think about it is like don't even enter the curve if you don't have faith that it's going to come through the other end. And so we kill a lot of developmental products well before they ever get into high spend because once you get into that curve you're, you know, 10, 20, 50, 100 million dollar plus in.","offset":2936,"duration":27},{"text":"Host: We spoke about like what did you not do and you said like offensive cyber and the cyber that we discussed earlier. What did you do that you shouldn't have done, and what do you learn from that?","offset":2963,"duration":8},{"text":"Matthew Steckman: That's a good question. Um, way early, I mean we, we got into some tech that we weren't ready for, um, we got into some markets that we weren't ready for. We tried to early on build a pretty sophisticated aerial system, we didn't have the core building blocks, we didn't have the core team. Um, I think we were 20 million or 40 million in before we kind of realized that it was, it was a scrap. We didn't have the sophistication with the customer, we didn't know how the customer was going to buy a, a vehicle of that sophistication. The kind of crazy part about all of this is like, well okay, given all of that and given that that was not a good business decision like clearly by most metrics, do we even get to build the autonomous jet fighter if we had never made that mistake? And so like it's hard to replay history sort of perfectly, right, and it's like I don't think so. I think part of that failure was a stepping stone to getting to success. Um, yeah we probably spent too much money on it and could have gotten out quicker, but like I think we had to learn that lesson in order to then re-approach the aviation market in a new way, which obviously has, has been quite successful for us, um, you know in recent history. And so if you, if you look at a lot of these failed things that we've done, it's hard to separate that from what came after it.","offset":2971,"duration":81},{"text":"Host: Final one before we do a quick fire. I always think to this question of, like, the biggest challenges in life are not like— it sounds so corny— but like, not iron or gold but unmade decisions. I never made the decision to move to Silicon Valley and everyone always reminds me that it will be the decision that haunts my career. Is there an unmade decision that ever haunts you?","offset":3052,"duration":22},{"text":"Matthew Steckman: No, but I'm kind of weird that way. I have trouble separating indecision and failed decisions from the current success that we're actually seeing as a company. I, I just do. And so people talk a lot about, um, I think like these overblown, uh, sort of ideas around like, \"Oh you have to learn from failure and fail fast,\" like yes, all of that's true. Most people suck at actually doing that. And, you know, so for me it's I deeply learn from indecision and from bad decisions, um, but it doesn't like haunt me and it doesn't, like, I'm not going to like kill myself over it, right? I'm going to, I'm going to move on and I'm going to make the next best decision.","offset":3074,"duration":42},{"text":"Host: Dude, I want to do a quick fire with you. So I say a short statement, you give me your immediate thoughts. Does that sound okay?","offset":3116,"duration":3},{"text":"Matthew Steckman: Sure.","offset":3119,"duration":2},{"text":"Host: What's one belief you have about modern warfare that most people think is insane?","offset":3121,"duration":5},{"text":"Matthew Steckman: I think a lot of my beliefs and our beliefs, uh, that we started the company on are now becoming a bit more commonplace. You know, when we started the company maybe we were a bit out of on a limb of like, \"Could I replace every single mission that the current set of technology provides us with an autonomous system?\" I believe that that is true in the long run. I also believe that we're not even close to where a lot of people think we are on it. I think we're still in the early days on, on tons of this tech. Um, but as time goes to infinity, like absolutely every single mission can be replaced, uh, with this new way of thinking. In 2017 when we started the company not only was that not widely held, you know, that, that was a headwind for us. I think that's changed pretty dramatically.","offset":3126,"duration":53},{"text":"Host: What do VCs fund in defense that you think will most go to shit? What are you like, \"Oh—\"","offset":3179,"duration":8},{"text":"Matthew Steckman: It's really companies that there is only one large program to capture. That's like fundamentally what it is. Um, in defense you have to be wide by the very nature of how acquisitions occur. Um, and so I think anything is a risk where it's like, \"Nope, there's kind of one program and if you don't win it, you're not a good company.\"","offset":3187,"duration":22},{"text":"Host: When you think about your kids, what do you tell your kids or kids graduating college about the world when it comes to career advice, knowing and seeing all that you do?","offset":3209,"duration":12},{"text":"Matthew Steckman: Yeah, I mostly say, um, a couple of, of things. I think it's about the community that you surround yourself with. Uh, I, and that, that's a reflection on sort of my own personal story. I mean everything that I've done in my career, um, has been the community of people around me that, um, have helped me, have gotten me jobs, have afforded me responsibility. You know, it's not like some big machine or process, it's, it's really just the people you surround yourself with and um, I like to think I made some pretty good choices early on that helped. And then the other piece would be, I think people tend to overthink a lot of their steps and don't appreciate how much you just can learn along the way. Um, you know, I talk to a lot of, um, military folks that are transitioning out into the commercial world and I would say for the most part they, they kind of like hem and haw over what company they should go to and, you know, my main advice is I actually think you just need to start. And you're actually a really smart person. Um, if you don't like it you can leave. If you like it you got lucky. And you should talk to a lot of companies, you should pick, and you should change your mind when you need to. And I think, uh, often times there's a hesitancy to change your mind, right? And I, I don't think that's actually true. It doesn't need to be true.","offset":3221,"duration":84},{"text":"Host: Final one for you and this is the most unfair of all and that will get you in most in trouble. When you look at the founding team, in a hypothetical world in 10 years time you start another company but you can only take one of them with you as your co-founder. Um, which, which one and why?","offset":3305,"duration":22},{"text":"Matthew Steckman: I can't take them all?","offset":3327,"duration":1},{"text":"Host: No.","offset":3328,"duration":2},{"text":"Matthew Steckman: No? Huh. It's a trick question 'cause there's no way that I'm starting another company after Anduril. I don't know if you know this, but starting companies is really tiring. Um.","offset":3330,"duration":11},{"text":"Host: No, I'm a venture capitalist, we, we don't, we don't know that. We know it's tiring, so we're much wiser than you.","offset":3341,"duration":7},{"text":"Matthew Steckman: I'm just gonna— I'm just gonna retire to the countryside and live with my family and I'm gonna do that.","offset":3348,"duration":5},{"text":"Host: Dude, you've got to choose one.","offset":3353,"duration":1},{"text":"Matthew Steckman: Yeah. I'm not choosing. Don't make me choose. You know I live in Washington DC, I'm very good at not answering questions. Maybe it's Bobik just 'cause the contrast of his baldness and my hair would make us a pretty, pretty formidable duo.","offset":3354,"duration":13},{"text":"Host: Do you think Palmer's brand is helpful?","offset":3367,"duration":1},{"text":"Matthew Steckman: I do. Unequivocally. In defense anything highly regulated, right? Every single thing is a headwind. And so the main thing you do to cut through headwind is you try and establish trust relationships with people who matter. Um, I think Palmer is an N of 1 when it comes to establishing trust relationships with people who matter.","offset":3368,"duration":22},{"text":"Host: I, I've loved this. This is so not how I thought it would be, to be totally honest. It was so nice, it was so fun. I learned, I totally didn't do anything that I kind of thought I would, but thank you. This, like— it reminds me why I love doing what I do.","offset":3390,"duration":13},{"text":"Matthew Steckman: This was great. It— honestly it was great to meet you. I do listen to the pod most episodes, um, I love listening to it. Um, so thanks for having me on. It was cool.","offset":3403,"duration":15}],"logs":[{"elapsed":"0.0","message":"Downloading audio from YouTube...","detail":null},{"elapsed":"0.0","message":"Trying download with browser cookies (ad-free)...","detail":null},{"elapsed":"30.4","message":"Audio downloaded (39.6 MB) in 30.4s","detail":"File size: 39.6 MB"},{"elapsed":"30.4","message":"Video title: 99% of Drone Companies Will Die & Why Anduril’s Products Aren’t an Ethics Debate | Matthew Steckman","detail":null},{"elapsed":"30.4","message":"Audio duration: 57:03 (57.1 min)","detail":null},{"elapsed":"30.4","message":"Uploading audio to Gemini File API...","detail":null},{"elapsed":"35.4","message":"Audio uploaded in 5.0s","detail":"File ref: files/dwjw9tfnwdvn"},{"elapsed":"35.4","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"117.3","message":"Transcription complete in 86.8s","detail":"58005 chars received"},{"elapsed":"117.3","message":"Transcription tokens: 85,829 in / 14,901 out — cost: $0.0876","detail":null},{"elapsed":"117.3","message":"Parsed 153 transcript segments","detail":null},{"elapsed":"117.3","message":"Transcript coverage: 56:43 of 57:03 (99%) — OK","detail":null},{"elapsed":"117.3","message":"Total transcription time: 86.8s — 153 segments","detail":null},{"elapsed":"117.3","message":"Analyzing topics across 153 segments with gemini-3.1-pro-preview...","detail":null},{"elapsed":"185.5","message":"Topic analysis complete in 68.2s — found 16 topics","detail":null},{"elapsed":"185.5","message":"Analysis tokens: 15,796 in / 1,174 out / 7,117 thinking — cost: $0.1311","detail":null},{"elapsed":"185.5","message":"Pipeline finished in 185.5s — total cost: $0.2187 (124,817 tokens)","detail":null}]} \ No newline at end of file diff --git a/history/1775246692426-m3uwf5BZy1Y.json b/history/1775246692426-m3uwf5BZy1Y.json new file mode 100644 index 0000000..d46e768 --- /dev/null +++ b/history/1775246692426-m3uwf5BZy1Y.json @@ -0,0 +1 @@ +{"id":"1775246692426-m3uwf5BZy1Y","videoId":"m3uwf5BZy1Y","url":"https://www.youtube.com/watch?v=m3uwf5BZy1Y","title":"Market Structure is Distorting Reality as Inflation Builds | Weekly Roundup","type":"youtube","topicCount":14,"segmentCount":124,"createdAt":"2026-04-03T20:04:52.426Z","uploadDate":"20260403","chunks":[{"title":"Teasers, Disclaimer & Intro","summary":"The episode begins with a few teaser quotes from the hosts, a standard legal and financial disclaimer, and the podcast intro music.","entries":[{"text":"Tyler: This is wartime allocation of capital. And this isn't just about the Iran situation. This is about what's been building for three years, four years, five years. It just favors scarce resources you can't print.","offset":0,"duration":12},{"text":"Felix: Oil prices aren't high enough for demand destruction, but they're high enough for inflation. You could make the argument it's actually almost better for it to go higher, then you get the demand destruction like central bank's gonna actually fucking do something. We're stuck in the corridor of everybody's frozen.","offset":12,"duration":14},{"text":"Quinn: The incentives here point to inflation, and inflation is really bad for risk assets because it sends bond yields higher and equity multiples lower. I think the outlook is horrendous.","offset":26,"duration":16},{"text":"Quinn: Nothing said on Forward Guidance is a recommendation to buy or sell any investments or products. This podcast is for informational purposes only, and the views expressed by anyone on the show are solely their opinions, not financial advice or necessarily the views of Blockworks. Our hosts, guests, and the Blockworks team may hold positions in the companies, funds, or projects discussed. As always, investments in blockchain technology involve risk. Terms and conditions apply. Do your own research.","offset":42,"duration":24},{"text":"[intro music plays]","offset":66,"duration":7}],"startTime":0},{"title":"Welcome Back & Tyler's Illness","summary":"The hosts reunite after a week apart. They exchange banter about Tyler's significant weight loss following a severe bout with a virus.","entries":[{"text":"Felix: All right, what's going on everybody? Welcome back to another roundup edition of Forward Guidance and we are back with the trio. We're back at home. No more conference, no more sick Tyler. The boys are back, the trio's back. Kind of feels like we didn't miss anything. Oil's still at 100 bucks. It's like nothing's changed in the last three weeks, so I guess we didn't miss anything in that whole time.","offset":73,"duration":23},{"text":"Tyler: It was at 110 now. There you go, yeah, it is. Did you guys notice I'm a little more svelte from my weeklong hiatus from food?","offset":96,"duration":10},{"text":"Felix: You look so good dude. It's not the red light tree tied? You're not on the GLPs or what?","offset":106,"duration":5},{"text":"Tyler: No, I lost like 10 pounds from that virus. I couldn't eat for like six days. It was terrible.","offset":111,"duration":7},{"text":"Felix: That's brutal.","offset":118,"duration":1},{"text":"Tyler: Yeah, it wasn't fun.","offset":119,"duration":0}],"startTime":73},{"title":"Market Chop & Hedge Fund Performance","summary":"The trio discusses the volatile, sideways market that is currently crushing options premiums and causing drawdowns for multi-manager podshops, while contrasting it with Pierre Andurand's aggressive and successful oil trades.","entries":[{"text":"Quinn: It is kind of groundhog day-esque because when I look at the Russell, we're closed basically smack dab where we were on Friday, March 6th. So it's like we just chopped everybody to shreds over the course of the month.","offset":119,"duration":13},{"text":"Felix: That's that's my whole thing is just like burning at the stake of put premium, even call premium, just premium everywhere just getting smoked as we just chop around. Like it's just brutal out there.","offset":132,"duration":10},{"text":"Tyler: You know what is so fascinating is like from an index basis, things - not much happens. But underneath the hood, if you look on like a sectoral basis, everything happens and that's really where all the alpha is generated. But you even notice from, you know, the - like you said, the indexes are unchanged, but some of the hedge fund performance numbers came out and some of these multi-platform funds got absolutely rocked, even in, you know, because single stock vol's super high and factor volatility's super high.","offset":142,"duration":29},{"text":"Felix: Yeah, the the potshops are all down like 4% over the last month or so, which is kind of nuts. You know who I saw was at the top, though, is Pierre Andurand, the French oil trader. He's up 30% month over month, which is kind of sick. Even though I mean, he was down like 50% last year. I don't know, his Sharpe ratio, I don't even know.","offset":171,"duration":20},{"text":"Tyler: Yeah, he's got an iron stomach, dude.","offset":191,"duration":3},{"text":"Felix: Oh, dude, it's insane.","offset":194,"duration":1},{"text":"Tyler: We were talking about that is like, it's pretty incredible. Like you have to consistently manage risk to get to that point of success, to then have enough of your LPs to stick with you through that volatility. Like they - it's not like you're going to get like a billion dollars if you're that volatile at the start of your career. So you have to be doing something right to take those drawdowns and anyway, it's just kind of -","offset":195,"duration":21},{"text":"Felix: Yeah. It is an interesting comparison compared to the potshop model, where their drawdowns are pretty limited honestly, past that 4% because, you know, if you max out your risk limits there, you just get fired. So you know, there's probably a whole new cohort at the potshops for April. Um, the rest of those guys who are down 4% have all been fired. So you know, it's a new cohort in and, you know, just roll the dice once again.","offset":216,"duration":22},{"text":"Tyler: Absolutely.","offset":238,"duration":1},{"text":"Quinn: That must be the most stressful job in the whole entire world if in this market if you can't have any any lean.","offset":239,"duration":7},{"text":"Felix: You're down 1% this week. You're like, oh god. You're getting smoked by Trump tweets and then you just get carried out of your pod like man. I yeah, you know, it's the cool place these days, but that's a lot to handle.","offset":246,"duration":15},{"text":"Tyler: You know what existentially it's just not in my DNA because like I - I'd like to think like investing that's a risk management job. Like you - you might as well be like an insurance, you know, risk person, rather than like the whole point of investing is to grow the economy and be risk-forward. And if you have one good year as like a growth investor, you can like compound that. Although the guys that are the heads of the multi-platform funds and have figured out are clearly like, you know, what's just men of the world. But like if you're just a risk manager PM, like these these long-only guys, long-only schlobs that ride like, you know, frontier assets may crush it comparatively, with way less stress.","offset":261,"duration":47},{"text":"Felix: Yeah, I mean their mandate's long-only, you're just like, well, everything's down.","offset":308,"duration":4},{"text":"Tyler: Yeah, just buy it, it's going up. You know, like, oh let's - we're going to invest in space stocks, yeah, let's go, let's keep going, pump this thing.","offset":312,"duration":9}],"startTime":119},{"title":"Deleveraging & Bearish Conviction","summary":"After a brief catch-up on a recent conference, the hosts analyze how geopolitical news and a lack of fresh information have impacted the market. Quinn breaks down charts showing extreme CTA deleveraging and a heavily hedged environment.","entries":[{"text":"Felix: Yeah, yeah, all right. Um, anyway we're back from DAS. Great time, had some great interviews. Quinn had a great interview with with Tony G, TG Macro. We had a good roundup at Joseph Wang. I had my my fireside chat with Fed Governor Stephen Ryan, that was super cool. We put that out on the platform yesterday or Wednesday, this is coming out Friday. So check that out. But yeah, man, Tyler we missed you there.","offset":321,"duration":20},{"text":"Tyler: Yeah, I really missed you guys. It was uh, you know, tough traveling these days, but I'm kind of getting out of it. Eventually I'll be -","offset":341,"duration":10},{"text":"Felix: Fed life.","offset":351,"duration":0},{"text":"Tyler: Yeah, yeah, exactly. Um, all right well why don't we talk about where the market's at. Obviously like we were just saying, it's it's somewhat Groundhog Day in terms of the geopolitical headlines. Like we had this this big Trump speech last night, addressing the nation. Not a lot not a lot of new news, but it's always interesting to contrast that with positioning where we had, you know, off the back of two days of rallying going into that point and a lot of expectations it felt like baked into the market that he's going to potentially announce some sort of ceasefire. Um, just the fact that there's no new information still, you know, reiterating this idea of a couple more weeks and and all of that and markets sold off and here we are again just mental and just chopping around. Um, Quinn, what's your read on the markets? Start with you here, what's going on?","offset":351,"duration":45},{"text":"Quinn: Yeah, I I mean, my conviction has waned in terms of near-term direction. Have been very decidedly and convictedly bearish for the whole start of the year pretty much. I mean, playing it long short from the metals longs to the energy longs and pretty much short tech and related things the whole whole way down. But um, here I just think that like the market is so hedged and you kind of have to have - I wrote in in this morning - you kind of have to have an egg timer on your plays. Like we've been pounding the table bearish Mag 7 and things for for like three or four months and and they're kind of not going down anymore. Like I - I had some charts if we want to start on those.","offset":396,"duration":53},{"text":"Felix: Yeah, let's see them.","offset":449,"duration":1},{"text":"Quinn: So maybe start with slide 30. I - this one is global CTA positioning, basically just showing and these these might be like a week old, so for probably from last Friday. So just you know, maybe even more degrossing has happened this week. But this is CTA showing just a very extreme deleveraging. Positioning isn't at lows, but you know, in terms of one-month change is very low. The the next slide shows the CTA positioning's very very flat to short. Um, the next one is the the implied moves of of S&P one-week straddle cost, which is extremely elevated. Um, you can kind of see 2022 as a pretty good comp for probably the environment we're going into there with just structurally elevated for the year. The next one is uh, the Move index, one-month change, which is bond volatility. Obviously, you know, this is like fourth highest in the last number of years. Um, so that's a pretty big jump. Um, the next one is S&P futures asset manager positioning, uh rolling three-week change, huge huge decline. And then on the sentiment stuff, you have AAII bearish, next next slide, bearish sentiments moving up. Next one, consolidated positioning moving down. Fundamental long short on the next one are, you know, sharpest weekly reduction since Liberation Day. And then the last one is uh, Nasdaq members above the 50-day moving average, which is which is extremely low. So it you know, a lot of these kind of saying the same thing, but to me it's it's the market has delevered and degrossed a a fair bit amount. Like so much so that shorting at these areas is a very tough place to make money when when you see these types of of moves and factor in on top of that volatility skew and put uh, put um, demand is still very high. So we've degrossed tremendously the last, a lot of the long-onlys, the trend followers, systematics, and the market is still very hedged. So like it was an obvious short to me when the market wasn't so hedged, VIX was lower and no one had delevered and degrossed and now it's kind of like eh, I don't want to be the last guy at the party and I've I've pretty much used this week to trim. It was kind of funny because coming into the week, I stayed short over last weekend, which was kind of different because every Monday we got a bounce and I stayed short, kind of covered early in the week and I was like so fatigued from - I was carrying very large risk on on this these positions for like two, three months straight. I was like all right, I'm going to just kind of wrap it up for for a week and reset, rejuvenate, write, think. And then the next two days, we just get the mother of all squeezes on completely BS news going into this Telegraph Trump press conference. And yesterday I'm sitting there I'm like I gotta short this thing again. I have to. There's no way a 9 p.m. press conference is to announce something good. You set up a 9 p.m.er to announce, you know, something bad. If it was good, he would have just telegraphed it to the world via Twitter and the market's kind of rising on lower volume. So I was like ah fuck it, I'll short again. And then this morning I the markets didn't open fast enough to cover and like I'm like all right, time to go enjoy Easter holy weekend and so I'm just waiting for the next fat pitch. I I don't I'm I still have stuff on, but it's it's very flat and way degrossed. So I don't know, like I think April's the best chance for a bounce out of any month. I don't think the medium-term picture's pretty at all. Like Trump told us point blank there's a month left to the war, which probably means two or three or more. So it's not going to be great, but I just don't see where the incremental selling comes from. I think everybody knows uh, all the information's out there. So I'm just waiting to watch and I'd love to short another couple percentage points higher on on risk again is is what I'd look for.","offset":450,"duration":261}],"startTime":321},{"title":"Market Structure & Options Volatility","summary":"Tyler and Felix break down market structure mechanics, including how retail 0DTE options decay and JPMorgan's collar rolls systematically drive market squeezes, causing volatility disconnects.","entries":[{"text":"Tyler: I think part of the uh, the problem is the market got overhedged and index actual index realized volatility did not rise commensurately with the implied volatility. So you know, implied volatility is forward looking, realized volatility is backward looking. And like we said, the index actual trading did not really move that much. So you know, the implied volatility rolls off as time goes on, causes that short squeeze effect that we saw today a little bit. So it's more of like the, you know, because of all the systematic trading, these things get so exacerbated in either direction and we saw like the VIX curve invert, that's usually a gr- my favorite sign for like when things are overhedged to the downside. I will say this though, the market was on the precipice of some sort of like if you looked at the dollar breaking out to new highs, if you looked at the yen at 160, like that could have broken out and caused a major credit vol and what what did we see? We saw the Bank of Japan lower their quantitative easing to so so the yen squeezed, right? The vol controllers always know these levels and and I guess it's a good thing that things don't just get completely derailed, your pr- they're proactive now with policy rather than reactive, which is you know, historically way different. So you have to think about that, you know, when you're at these levels. If they don't break through on high volume, that means they're probably going to reverse. So that's you know, I try to point them out on Twitter where I can, you know, when when I feel like this is a breaking point and obviously you know, the dollar rolled over, the yen squeezed and then all the vol metrics kind of rolled off after that. So it was a really bipolar outcome, you could have seen the market kind of cave and you still can, like you gotta watch the dollar and oil here, they're we're still not out of you know, the woods by any means. Um, and then I just wanted to show you this. Go to slide 56. There's a phenomenon, I'm like I'm always watching market structure and obviously retail has become a bigger component of uh, the market now in since retail's been conditioned to buy the dip. You know, we dr- generally have seen and you also have the zero days till expiry options. So this is from Citadel Securities, but you can see over the month of March, Monday has been up on S&P, Nasdaq, and the Russell and then you can see as those options bleed because retail traders are morons and they can't actually understand that like your theta your theta decay happens and then they're waiting for the end of the week where oh, it's just a Hail Mary, right? Like they need the call options, it's usually buying call options, right? And then the call options bleed and then the delta sell the dealer sells the delta once the retail gets stomped out on a Friday. So I think that was largely this month's whole um, that was what we saw continuously for the month of March and now I think a lot of those volatility things have reset, retail's really take gotten hammered here and we'll see what happens uh looking forward based on the geopolitics. But I don't know, a lot of the it feels like you need a little consolidation before you have another roll lower. And then I wanted to show these other two things where it's all - it's not all bearish, it's primarily in tech. So if you go to slide 51, there's a couple interesting things going on. It's like i- there's this guy was named Diego Parrilla and he called about the he called the bubble economy and then the anti-bubble economy and so the bubble economy was all the non-profitable stuff going up, like the tech tech things and the real economy was the inverse, which is like you know, natural resources, metals, etc. Um, but we can actually see you know, global manufacturing PMIs going up here and at the same time you know, central banks are are not easing anymore. So um, and you if that rolls over, that's I think that's really pressuring like the high multiple type sectors. But if you go go to the next slide, this is the uh, Goldman Sachs industrial metals index. Like this is not a bearish chart, right? And there's a lot of things happening in the real economy. And like and then if you go to the next slide, the Dow Transports. Like that's a gr- there's money leaving tech and going into like real things now. Um, and interestingly enough I'll give a shout out to these guys because they're moving to Austin, Texas, but there's a hedge fund down here I think it's called Schottenfeld Capital and their whole premise is to to invest in things that are real. And so this you know, if you get this you know, not only are they nailing the macro trade Austin, Texas, but they're nailing this generational trade from like you know, high multiple software stuff to like real things that you need for the economy. And I think like that that is a secular play here that's really kind of you know, important. Um, and we're seeing that on the ground. And then if you let's see, the last one is tr- if you go to the next one, I did the tran- transportation index versus QQQ and you can kind of see I circled the low, it's a little hard to see here, but this is the ratio between the two and we we're at a low where in 2000 we saw you know, the tech bubble burst and then the Dow Transports took off. So the the bottom green part is the ratio of when when that green line is rising, that means transports are outperforming and when it's falling, that means tech is outperforming. So we're you know, if this keeps up and you see the capital concentration out of tech into like real stuff, I think this you know, I think this line should should mean revert to the upside.","offset":711,"duration":363},{"text":"Felix: That's a sick, I like the way you put that all together with the market structure initially, too, because I think it really it leads into also what Quinn's talking about, just being neutral on the whole punting on on Iran situation here where it just like the easy shorts have happened, there's been so much degrossing, hedging. Um, I mean another one, too, is also this uh JPMorgan collar trade that that expired on Tuesday. That's that's you know, increasingly moving- I mean this is the whole theme, right? Is that there's these these macro ideas, but then the markets are so dislocated from those fundamentals and everybody goes insane because we're actually just being driven by these Opex flows, these CTAs, these uh JPMorgan collars that act as magnets to around expiry. So you know, you can see where actually, hold on, let me get this chart here. Um, this is a sweet chart from our our buddy Andy Constan, just looking at tracking that collar. And you can see right on the expiry on Tuesday, it we kind of expired right at it on the on the long put side and then as soon as that began the roll, markets rallied like crazy on that Tuesday. And you know, everybody's attributing it to it to like a single head like where's the news, what's the news, what did Trump say? And it's just like dude, this is just market structure. Like there's just it's just like every like it's just a game it's just a, you know, it's a Ponzi like you say Tyler. Like it's just all these like quant-driven flows and passive flows. It's just a - I don't know -","offset":1074,"duration":85},{"text":"Tyler: It's just a different management. If you think about it like I've been trying to relate it to if you think about it as if like a a manufacturing um plant for automobiles 50 years ago. You know, it was used to you had to manually put these cars together with hands on a on a conveyor belt. Now they're automated by robots and that's essentially kind of like the stock market's gotten way more efficient, but in that efficiency, you still have these moments where when stuff breaks down, when the robot breaks down, you really have drastic outcomes where that really can screw things up uh, because there's you know, it was my whole point about when you have a heterogeneous market with thousands of different things interacting, you don't really have systemic risk. But when you have a homogeneous market where all these things are have the same incentives and they have the same programmatic quant things, it makes for more sys- systemic risk, which is like that robot breaks down on a conveyor line and then you don't know what to do, right? Like you're then you have to buy all sorts of insurance and everyone rushes to buy the insurance, you know, because the supply chains are messed up. And so I think that's like the new because the world is so centralized and so efficient in a lot of ways, it causes when things start getting rocked it it makes me just want to start like a long vol fund and whenever whenever vol just spikes, oh you just sell it. Like you just sit there and you own insurance when it's cheap and you sell the insurance when it's expensive and you know it's going to happen because of these market structure types of things. So reach out to me if you want to - I'm just kidding.","offset":1159,"duration":98},{"text":"Felix: Yeah, go go talk to Nassim Taleb about that or something.","offset":1257,"duration":3},{"text":"Tyler: Yeah, yeah, exactly. But it's happening more frequently because of centralized, I think.","offset":1260,"duration":8},{"text":"Quinn: Yeah. I mean it it's like when people want a reason why, you know, what did Trump say or whatever that the market's up um both days, it's like look at the VIX, it's down huge. So it's just this mechanical rebuying and no news, nothing changed. In fact, Trump's still saying throughout the whole time like, you know, aggressive things and it it just kind of I think you just need to see either the labor market deteriorate or you know, maybe it's boots on the ground, maybe it's whatever to to really frighten people. Like we all know that people I think there's still enough belief that things are not going to get extremely worse from here. I I think the outlook is horrendous. I mean, I think the inflation outlook is is totally being slept on for how for what oil prices are doing. I I think bonds are the next year to drop.","offset":1268,"duration":54}],"startTime":711},{"title":"Oil Prices & Alternative Energy Future","summary":"The conversation shifts to oil price manipulation, the lack of a U.S. supply response, and Pippa Malmgren's thesis that the U.S. might leverage nuclear fusion to counter geopolitical energy threats.","entries":[{"text":"Felix: That's the thing oil - oil prices aren't high enough for demand destruction but they're high enough for inflation. And that's actually the double-edged sword of what they're trying to do with manipulating these markets of trying to keep oil suppressed is that you're actually you're keeping it in the corridor of inflation without getting to the corridor of demand destruction. You could make the argument it's actually almost better for it to go higher because then it then you get the demand destruction like central bank's can actually fucking do something, but we're stuck in the corridor of of everybody's frozen and then we just have the inflationary side.","offset":1322,"duration":29},{"text":"Quinn: Well you also get the you also get the supply response if you let the market do its thing and find natural prices. But if you suppress prices and don't let it trade freely, there's no production response. If you look at rig counts, there's no uptick in U.S. rig counts in the Permian nowhere. No one is this whole month. Yes, it takes some time, you know, you you can't just get on the horn and mobilize dozens of rigs, but it's one month in and and there's no supply response in the U.S. and that that's not good. So you have to let -","offset":1351,"duration":36},{"text":"Felix: Yeah. I mean how do you plan a rig count coming online when you're when you're you know the other side of your trade is Scott Bessent in the front months or something?","offset":1387,"duration":7},{"text":"Quinn: Yeah, right. And so then and then you still have people hedging out in the back end. I think back to Andy uh a trade I - so yesterday I loaded up on front-dated oil um because you know part of the thesis that he wasn't going to end the war and it was it's not endable right now. And um, that paid huge and then I that idea floating around a about the huge differential because you know front months at like 110 but then December's only at 70 bucks. And so then like but but the things they're doing, selling front, buying back, doing these like basis trades, like manipulating the market, it you're on the same side as them then if you're buying the long-dated stuff because it like you said, Felix, it basically keeps demand in and helps prices stay higher for longer. So there's no you can't control inflation when the cat's out of the bag like this, even though they're going to try.","offset":1394,"duration":55},{"text":"Tyler: You know what on that point, this this was a really divergent view was I read Pippa Malmgren's last piece and who I want to ask her to come hopefully she can come in the next couple weeks, but she talked about maybe maybe this is all planned because like what does you know high oil prices really in from the Straits of Hormuz really kills China more and what if the biggest news she said that everyone missed was there was a I believe it was like a nuclear fusion breakthrough in late March, or maybe it was late February, where we figured out how to like unlock nuclear fusion in SMRs. So essentially like you could have nuclear power on a small basis. So what hurts China the most when we have this huge generational unlock from you know nuclear fusion and and small modular reactors, where it's like we're moving into the 21st century and the as in the U.S. and if you want to be in, you know, she calls it from molecules to atoms. We're we're moving from molecules to atoms meaning being stuck on an oil type uh petrodollar versus being stuck on, you know, a nuclear new type of of you know backing energy backing to whatever currency's going to win, right? And I think this is a really interesting divergent point, which is like maybe they don't want to rush to get oil prices lower because that we're a relative winner in that game and especially when you have this new technological unlock, it lowers our cost of capital at if your energy goes from you know old school oil to a nuclear solar type thing. I mean, what that makes us win the 21st century game. I don't know if that's it sounds nice.","offset":1449,"duration":111},{"text":"Felix: But I will say yeah, she's good at putting out those divergent mapping ideas. I I don't know about the track record of them, but they're how's the global peace dividend working? Yeah, that one didn't that one didn't - well but you know like these things are all I think from if you zoom out -","offset":1560,"duration":15},{"text":"Quinn: But China's ahead of us in nuclear, they're ahead of us in solar, they're ahead of us in using natural gas for transportation. China's absolutely eating our lunch on every one of these other energy sources.","offset":1575,"duration":12},{"text":"Tyler: That's why I would love to have her on and like kind of -","offset":1587,"duration":3},{"text":"Felix: That would be great, yeah. I would love that, that would be awesome.","offset":1590,"duration":3}],"startTime":1322},{"title":"Fuel Surcharges & Rising Treasury Yields","summary":"The hosts note Amazon's new fuel surcharge as a sign of incoming inflation inputs. They analyze rising U.S. Treasury yields bear-flattening the curve before pausing for an ad break.","entries":[{"text":"Tyler: - to to hear the contra, but like from I could see that future if that's really like the age of abundance and we move into this new frontier society, that's great. But you also have to deal with like the credit problems if you're in this giant debt bubble and credit constricts and you can't grow your way out of it, then you know, shit goes south real fast. Um, I think um to earlier point about the inflationary dynamic is yeah, like war is inflationary, plus when it's focused on an oil shock like this. And there's been a couple different news headlines come out today I want to get you guys's take on. The first one is that Amazon is actually putting on a 3.5% fuel surcharge on their fulfillment. So you know, it's like here we are, if if oil was 150, you know, maybe people wouldn't be buying as many things from Amazon, but because it's at 100, instead we're getting a 3.5% surcharge.","offset":1593,"duration":53},{"text":"Tyler: You know what on a small basis, I got a buddy who runs a landscaping company in Massachusetts and he puts he's putting a surcharge on his all the oil he uses for you know cutting people's lawns, doing you know all sorts of yard work. And you know, so this is this is going to factor into inflation in the future, which makes me really suspect of uh yields. And I actually got a good chart on uh let's see, this is from my buddy John at BTIG. He uh he's got one of the a really good note morning note, but if you go to slide 50, he shows you since the beginning of the war, this is how much U.S. treasuries have have risen across the yield curve and you can kind of see um you know this is pretty consistent and now you're getting the the cost spiral on from Amazon. I'm sure it's everybody you know tacking on some of the oil tax.","offset":1646,"duration":63},{"text":"Felix: Yeah.","offset":1709,"duration":1},{"text":"Tyler: Jordi Vistor said basically these inputs we're going to see flow through you know for the next couple months into CPI. So things can get a little funky on - what what this chart shows too, that's important to keep in mind, is that all the short-dated stuff uh except for the 12 months, the white line, but the two-year, the five-year, um they've risen much more than the 30-year and 10-year. So the curve is flattened through this period, basically people investors saying this is going to keep policy restrictive longer and therefore growth is going to be hurt by it. But it's bear flattened as every all yields have moved up. And the real problem I think is what happens when presumably you know June comes around, first first new Fed meeting, uh you're going to get policy response into the election, oil's still trading elevated, the inflation's kind of being pushed through at that point and then you start to cut and stimulate. You know assuming I'd imagine they also we haven't seen it yet, but probably do some sort of fiscal stimulus into the election. So then you get a bear steepening because so it's just yeah, the bonds are awfully here, awful awful awful.","offset":1710,"duration":78},{"text":"Quinn: [Ad break for Arkham Intelligence]","offset":1788,"duration":48},{"text":"[Ad break for Blockworks Investor Relations]","offset":1836,"duration":49}],"startTime":1593},{"title":"Yield Regimes & Radical Debt Policies","summary":"Felix shares a yield curve regime map, prompting a discussion on Jeffrey Gundlach's suggestion that the government might eventually have to cut Treasury coupons to manage the spiraling national debt.","entries":[{"text":"Felix: So this is a I've been considering on my Claude journey. I I made a twos-tens regime map. I just realized the way I screenshotted this it doesn't show the color codes, but yeah -","offset":1885,"duration":11},{"text":"Tyler: I was like what is this?","offset":1896,"duration":1},{"text":"Felix: Pretty, it's very pretty Felix.","offset":1897,"duration":1},{"text":"Felix: Thank you. I'll I'll say it verbally, but the green, so this is a rolling five day and it shows the green is the bear flattener. Um, the pink is bull bull flattener, the rest is yeah, the the pink one which is around what you were saying, Quinn, is the bear steepener. So um, you can see it's come down a lot. Um, and I've been thinking a lot about where does that go from here and if you look at like inflation swaps, contrasting that with what we just looked at with the yields, it's an interesting situation. You can see like the the one-year, two-year is up a lot, the five-year is up modestly since the since the war. Um, 30 years actually continued the trend down. So I don't know, kind of in the same camp where I see a lot of folks trying to bid the long end on this idea of like a recession play, but I think you're in this again in this weird corridor where you need things to get worse for that to happen. Um, so you're sort of in the doldrums.","offset":1898,"duration":54},{"text":"Quinn: But not worse enough where it brings down receipts and it's this double-edged sword of all assets up or all down because bonds if you plot them next to stock the indices, they've been trading like the indices. So -","offset":1952,"duration":14},{"text":"Tyler: Gundlach had a interesting call. He was on this podcast with I think her name's Julia LaRoche. He said this is the first time we've seen you know in these crisis scenarios bond yields have risen and there's no way out. Like they are so screwed here and he's he's basically saying they're going to have to do something crazy and he was even calling for everyone who has treasuries, all of a sudden oh your your coupon is cut by say like 50%. Imagine if you woke up overnight, it was just this giant like overnight policy where they just said oh by the way, your treasuries are down by 50% and the dollar rolls out of bed, like gold doubles. Like you could have there's a it's essentially a debt jubilee, right? Where they have to get the rates down on in debt and treasury debt because it's getting egregious and if you have a recession it's going to get more egregious. So you have to get you're going we're going to get into wacky wacky policy mode here.","offset":1966,"duration":62},{"text":"Felix: Gundlach - Gundlach, those words came out of his mouth, he said what if what if they cut coupons?","offset":2028,"duration":7},{"text":"Felix: Yes, he did, but he -","offset":2035,"duration":1},{"text":"Tyler: I've heard him say this before about um he does think this is like a medium or like a a something that's on the cards at some point down the line.","offset":2036,"duration":8},{"text":"Quinn: And he's legitimate. He's he's the Bond King, or one of them.","offset":2044,"duration":5},{"text":"Tyler: And you know Lyn Alden's been saying the same thing. She had a great interview with uh was it Peter McCormack, too, and I I I'm seeing the same thing, but here's a good chart for that. Go to 62. So this is uh this is gold. You can see gold, there's secular stuff going on that's probably going to work. So gold producer cash flow is the dark blue line, that's on the left, so you can see their like margins are huge. But then if you look to the the relative performance of gold equities versus gold bullion, we're at even though you know margins are more than double what they were at in 2020, the the ratio is still the same. So like if you have some sort of crazy policy like a yield curve control or like a tax on boomers vi- via like you know they won't even know if you just cut their divi- you know cut their you know treasuries by all a percentage point, oh by the way your coupon's 3% instead of 2%. Sorry, the dollar would roll over and I mean god you're looking at some crazy stuff happening and I just don't you know that's why I think you got to look at what displays relative strength in sell-offs and that's where you want to be going forward.","offset":2049,"duration":78}],"startTime":1885},{"title":"Bitcoin & Wartime Capital Allocation","summary":"The group examines Bitcoin's relative stability and the shift back to positive stock-bond correlations. They emphasize the importance of allocating capital into scarce, real-world assets during times of geopolitical conflict.","entries":[{"text":"Felix: Well you know what's been holding up okay is Bitcoin. I feel like we we've stopped talking about it for the last while, I've seen we've gotten a little bit of shit for that from some people. But it's just been chopping around, but it hasn't been breaking down lower either. And you know it's not getting the big sexy gains either, but -","offset":2127,"duration":15},{"text":"Tyler: It makes me nervous, which means it's either a low or there's one last big -","offset":2142,"duration":4},{"text":"Felix: That's that's always what's so hard, right? Because it was the thing that sold off first even before this whole thing, you know, January and all of that. Um, so either it's just technical support, though, that's what makes me nervous is like if you look at gold's got great support, defended it you know big. But Bitcoin has - I agree - relatively thin. But any time we start talking about haircuts on sovereign debt, I'm like hm, you know, you start you have to at least put it into the conversation. I don't know where it sits with it, but -","offset":2146,"duration":26},{"text":"Tyler: You know what people are figuring out, though, is go to this last slide, slide 63. I think they're figuring out that you can't actually save money in fixed income anymore because look at stocks as a percentage of household financial assets and like in a world where the policy is getting wonky like Gundlach and Lyn Alden everyone kind of sees, I don't know where you put your money besides stocks. And maybe that's the phenomenon of why things mean revert higher anyway is because it's just this is the great rotation out of debt.","offset":2172,"duration":37},{"text":"Felix: You know what's I have another one here just to bounce off of that. But you know what's so insane is that like the entire modern financial system was based on this little phase here where stocks and bonds are negatively correlated and like we completely ignored history where it's like mostly positively correlated and then we just built up every portfolio on this idea of like a negative correlation between stocks and bonds and now we're just we're not going to this new weird regime, we're going back to normal.","offset":2209,"duration":31},{"text":"Tyler: Yeah, yeah, it's a really good point. It's a really good point.","offset":2240,"duration":1},{"text":"Quinn: I mean, where people are putting their money, Tyler, is when I mean the labor market's horrendous, savings rate is falling, stock market is at all-time highs. So people need to spend and they're putting the their money from financial assets and financial market that market capitalization, which is at the most extreme level it's ever been in history relative to real things, they're they're taking the money and putting it in in things they have to buy to live and enjoy life and so that's what makes these periods so tough because like post-COVID -","offset":2241,"duration":37},{"text":"Felix: Or hedge their employment with the AI supply chain. That's what I'm doing.","offset":2278,"duration":6},{"text":"Quinn: That's what makes these periods so tough to for investors because it's everything that's it's very difficult to to maneuver and the things that work over the periods are are like the least sexy, the places no one's ever no one's been and you know think are very just left for dead and but look at what's worked over the last it's like all the most boring businesses, people said oil is never going above $60 a barrel again. Like I'm I'm more in the camp of Michael Howell had a a nice piece. I'm in the I'm a like mean reversion guy uh over over long periods of time. Like if history's given you a hundred years of trading look back in in the gold-oil ratio. Like I'm gonna bet that it's gonna adhere to the to that decades-long trend line and so what Michael Howell kind of was arguing for in the piece, not not that it's going to happen today or tomorrow, but that gold implies the gold-oil ratio implies $250 oil sometime in the next you know multiple years. And and so if you think about it like from the Bitcoin perspective, okay yes um debasement, monetization of debt, right. Bitcoin's price at some point will stop going down in nominal terms because the the denominator's getting debased. So - but that doesn't necessarily mean that in real terms it will be a good investment because you need peace, you need um animal spirits, you need you know fun times and you'll get countertrend bounces here. But over the next if you look out over the next year, like do you envision us immediately anytime soon going back to a place where you know everyone just relies on globalization and believes shipping lanes are open and you know my neighbor's gonna give me that commodity that scarce one when I need it and I trust the the U.S. treasury to hold my funds in treasury? No, none of this stuff. So when you think about this is wartime allocation of capital. And and this isn't just about the Iran situation. This is about what's been building for three years, four years, five years and it just favors scarce resources you can't print. And right now leading up to this, it was gold and metals, now it's oil and energy. You know soon it might be food, it might go back to metals, but these are things you need. And if everybody's piled in the gold, that's why it's not working, it's trading like equities because at some point these countries gotta spend their gold, they bought gold as a fiat hedge, as a store of value. And at some point if they aren't getting oil, you know UK just announced some stimulus measures for their citizens, some people I know there said there's lines at every gas station and four of the five are out of like gasoline. Like wow these are there's serious issues and people are going to throw the kitchen sink at it.","offset":2284,"duration":188}],"startTime":2127},{"title":"Distressed Debt & Demand Destruction","summary":"Looking at the rising high-yield distressed debt universe, the hosts discuss how prolonged high commodity prices drain consumer wealth, leading to demand destruction in areas like expensive, unhedged airline travel.","entries":[{"text":"Tyler: Check this, go to slide 57, JPMorgan had their uh default monitor this week, their note and this is the combined high-yield loan distressed universe, it's hit it's highest level since June of 2023. You know if they can't figure out how to get policy rates lower, these things have a tendency to spiral and we saw a little bit of loosening from the credit spreads this week, that keeps going you could see a major squeeze in risk assets, but this definitely these things are hard to unwind and we've seen obviously what so there was a great tweet it said something like if Iran never happened all we'd be talking about is like Blue Owl distressed debt and private equity problems because like that's really a huge issue that's not going away anytime soon and can really spiral. But and that'll affect like all sorts of asset classes eventually, but it could just be a slow default, it's really I don't know it's hard to decipher, but I do know that's a real big issue underlying this all.","offset":2472,"duration":69},{"text":"Quinn: Yeah I I think one of the things I actually wrote about this week I haven't put it out yet, but um I was just kind of like blank sheet of paper, it's like if I look into the into the future what what are the things I see most clearly? And one of them is sustained higher for longer commodity prices. Like yeah okay, we get a resolution oil drops 20 bucks, I'm not talking about that, but we're not going back to 60. Maybe it goes to 80, you know that's probably a great dip to buy um and the whole complex is now a scarce thing that you have to put a premium on. So I see higher for longer there. Uh and the other thing I see is kind of tangential is like conflict not going away and in one of the best ways to play that in addition to I mentioned the long-dated oil futures contracts is credit problems because the consumer's getting hit both two ways, one um it's a it's a demand destruction because higher prices, inflation, they can't travel, the things more expensive, it costs them more money to get to work. So higher gas energy food prices really affects consumers, but then two the negative reflexive wealth effect as as already going into this savings rate was falling, so people were dipping into their wealth via assets and savings and that's falling reflexively via lower asset prices. So now their their kitty to to spend from is also lower. So what does that look like in the future? Like that looks like cutting back your summer vacation plans, that looks like you know kids aren't getting you know the extra thing. And so that's just weaker and that's credit credit problems. At the end of the day, like I I think financials like I don't really see a good case to be made for financials here um and so I in small caps and all these sort of cyclical uh we were saying a couple weeks ago before the war, we said the cyclical reacceleration, yes there's some bright spots, green shoots, but without Fed accommodation and and follow through it's it's dicey and now it's -","offset":2541,"duration":121},{"text":"Felix: Yeah, yeah, we get the emerging little sprinkles of it and then now it's totally smoked. You know, like we went from quite a few cuts priced to almost zero cuts priced, you know. You have a doubling of oil price you just can't you just can't get that sort of a reacceleration when it's like just barely alive. Um, it's yeah, it's it's done.","offset":2662,"duration":20},{"text":"Tyler: Here's a good snippet, I have to fly home to Jersey uh just from Jersey to Austin and we were booking flights for my family, you guys this is little microcosm, guess guess give me a guess on how many for five people how much the flights were all together round trip?","offset":2682,"duration":20},{"text":"Felix: Three grand.","offset":2702,"duration":1},{"text":"Tyler: 3,500 bucks. Bro, stick for lower for one round trip flight and you're just like eventually that's gotta cause demand destruction, you know.","offset":2703,"duration":12},{"text":"Felix: Totally. I guess yeah, I mean to earlier point, like the 150-dollar barrel situation, that's like the very quick demand destruction but there is these more long-tailed ones. Um, you know, you're starting to see different airlines start to cancel these flights uh you know these flight routes that just aren't as profitable now at at this sort of level. And you know what I realized too is over the past few years, airlines have stopped hedging their jet fuel. Have you guys heard about this? Like for whatever for whatever reason the trend these days in the airline industry's to not hedge your jet fuel, so none of them are hedged going into this.","offset":2715,"duration":31},{"text":"Tyler: Scary. Yeah, there's you know what else you know what else I've been thinking about too is like so you have the price insensitive buyer and then you have like stuff like Hyperliquid that you can take out 40x leverage on, you know, oil contracts. It's like how how much more volatile we're going to be in certain asset classes. Like this is all the market structure stuff, but -","offset":2746,"duration":25},{"text":"Quinn: I mean it's just classic it's how cycles work because they probably got berated for last few years like why are you hedging oil, it only goes down, aren't you don't you know this, you're stupid and then right when they it's just classic. Like that it's just how cycles always work.","offset":2771,"duration":16},{"text":"Felix: Yeah. You hedge after the crisis and then right before the crisis you're you're like wait why am I paying all this carry so then you yeah.","offset":2787,"duration":9}],"startTime":2472},{"title":"AI Compute Demand & Infrastructure","summary":"Despite macro headwinds, Tyler and Felix highlight the explosive demand for GPU rentals and AI computing power, questioning how data center infrastructure will continue to be financed.","entries":[{"text":"Tyler: You try to get the max P multiple off your you know by cutting little corners and then it's a sharp reversal. But this is to to that point, this is very typical late cycle. You have the dollar rallying, the oil rallying, credit spreads widening. Like the these things they take a while to play out before they really hit earnings. Uh the one thing that's really confusing me on check this out, this is uh last chart I promise and then I'll stop. But this is the GPU rentals, slide 45. Like we're clearly in some sort of secular growth in AI. Like there's no doubt about it. Will the credit markets completely punish these these stocks before they can build out the infrastructure? Possibly. But look at the demand for this stuff. I mean it's your GPUs are rentals are rising and I mean from from the OpenAI raises $100 billion. Like that's that's kind of nuts. Like that money's got to go somewhere and have a multiplier effect to it. So -","offset":2796,"duration":65},{"text":"Felix: And Anthropic, yeah. I continue to be in the camp that like the demand for compute is way higher than we expect because like if you look at actually what's going on right now, like ever since the AI agent wave that started a few months ago, like dude the I'm getting smoked on my Claude usage. I have a max plan and like all this stuff and suddenly it's like I do I try to do a few things and I'm and and my I get smoked on my usage. So like there's I imagine everybody like this right now is that they're throttling the usage because suddenly everybody's trying to actually do things with it. Um and so it's limiting the amount of innovation that you can do, but if you increase the compute, new innovation, new ideas. So I don't know, I I don't want to completely fade it.","offset":2861,"duration":42},{"text":"Tyler: I don't either. I think I think that's something that you have to really it's going to be volatile in the macro, but like underneath fundamentals are pretty damn good.","offset":2903,"duration":12},{"text":"Felix: Yeah, I guess I guess the big question is who's who's the one underwriting that compute, these data centers, right? And and what are the cost inputs? Because you know it's stuff like, you know, semis which is related to helium, which is related to the Middle East where there's these helium- like there's that stuff, there's the fact that like the financing deals are coming from the big dogs in Dubai and now nobody's actually living in Dubai, so suddenly tax revenues are down, so suddenly you can't finance- like it just it's a cascade, right? And that's why -","offset":2915,"duration":28}],"startTime":2796},{"title":"Politics, Interventions & Inflation Risks","summary":"The conversation shifts to how the Trump administration might handle credit market breakdowns and AI transitions. The hosts weigh the inflationary risks of desperate macro interventions and the potential for severe social backlash.","entries":[{"text":"Tyler: Well I was going to say, that's why I'm watching the macro so hard here and these levels and in particular FX. If you start to see funky FX vol and you get that repatriation, it could p- put the nail in the coffin on a lot of stuff. But given the genesis plan, this is the Manhattan Project, right? They ha- they can't derail the capital markets and so I bet Trump would just if it got to that level where the credit markets started shutting off, he would probably say we're out of we're out of Iran, we're going back and like you know we're going to unleash all of our reserves and by the way, no one has to pay taxes and by the way you know like that's the vol controller thing that you it's really hard to play, but secularly you know you have to pick. I think there's there's a couple themes that that work and it's just going to be really hard through the vol. You know like the gold gold is is I feel like it's secular here, I feel like AI's probably secular, I feel like space is probably secular, but you're going to have these vicious drawdowns.","offset":2943,"duration":69},{"text":"Quinn: That that's what we're getting into a difficult period though because it's not guaranteed that those mechanisms work when inflation is spiraling and you try price controls that make production worse and then stimulate like because if Trump announces stimu- stimulus tomorrow and forces the Fed down 75 basis points and all these things, I'm not buying semiconductors, I'm buying I'm buying Main Street stuff, I'm buying inflation protection, I'm buying I'm selling bonds, I'm buying I'm buying real real things that everyone can go get their hands on. I'm not I'm selling semis. So that's why I just it's such a delicate back against the wall balance right now. And I'm not saying -","offset":3012,"duration":48},{"text":"Felix: Yeah.","offset":3060,"duration":1},{"text":"Quinn: - actually right now I have I went into the weekend with zero semiconductor shorts on, I I covered my Nvidia, so I'm you know that's not even just I actually think there's a little bit of a with how beaten down Mag 7 and you know the megacaps have become, I think people might actually seek them out as safe havens over over the next few weeks if we get a bounce and you know flight to quality and safety type of thing. So I don't love that that play right here, but -","offset":3061,"duration":29},{"text":"Tyler: I do think it sets up because really what you do, right, Tyler, if you if we're go- if credit spreads are blowing out, if um the labor market's weakening and they step in to support AI in a time where Main Street's already just been getting the hammer for two two years straight, you're just guaranteeing sowing the seeds with a bow on top the demise -","offset":3090,"duration":25},{"text":"Tyler: French Revolution.","offset":3115,"duration":1},{"text":"Felix: Yeah, I mean the Main Street hates AI, you know. They're they're protesting data centers in their towns and losing the yeah.","offset":3116,"duration":7},{"text":"Quinn: Yeah. So if which I'm not this is not I actually think you're probably right that they will do everything to to support but the second they do that and you play that maybe you play that bounce or if you don't you just wait for the short again, it will sow the seeds politically and societally for that demise to be even worse because it it will be just an absolute slap in the face times a million if unemployment's you know shooting up to five.","offset":3123,"duration":30},{"text":"Tyler: Our biggest problem with that is you have a guy in office that will he's like the lowest ratings of any president in history I think it just came out today. And if you want to message that this is really important from a geopolitical standpoint to win in AI, you have to have a high trust rating and you have to be able to like say, hey we're going to take a pain as a team. You know we're going to do this together and then this is a national priority as a labor and we're going to make sure we listen to the labor pool and and say, hey we're watching out for you and like when things get bad enough we're going to pass policies that take care of you in this transition. You have to have this messaging way you got to be way out ahead of it and and this is part of the situational awareness piece is like you're going to have people fall through the cracks as this stuff is so productive. But you need to b- you need to be out there in policy and already formulating ideas and messaging it. And he's he's behind on Iran messaging like he could have messaged this way better. And and it's because he's like a he's like a TV star or like a reality TV star that likes drama rather than like actually keeping the social fabric together. And so I don't know he's going your propensity my point is your propensity for these things to break with Trump is way higher even though he might have the national like geopolitical priority correct. He doesn't have the capability of actually doing that. And it's based off the you know his polls are showing that like he's kind of just a narcissistic loser in that sense and like maybe it works, you know, maybe it works and he's in 10 years we think he's the greatest thing ever even though you know right now we I like to fade the extremes, right? And everyone hates him so much right now, maybe maybe there's some genius to it. But I don't know, I the Epstein stuff really the fucking lost me. Excuse my Fr- and like now he you know he throws Pam Bondi out to dry the whole thing is -","offset":3153,"duration":129},{"text":"Felix: That's that's because we lost the the key level at 50,000 on the Dow so she had to go.","offset":3282,"duration":6},{"text":"Tyler: Yeah, yeah, you know what that might be a great point. In hindsight like watching that and be like that was the top of the market. That was the absolute top. Imagine.","offset":3288,"duration":10},{"text":"Felix: Yeah, yeah, oh man. And now that she's fired, it's like yeah.","offset":3298,"duration":3},{"text":"Quinn: Yeah. The the thing is that you know put the politics aside like emotions and I don't like him and I like her better and whatever, at the end of the day, the the incentives here point to inflation. And inflation is really bad for risk assets because it sends bond yields higher and equity multiples lower and nobody wins. And so whether or not like what we think he's doing is good or dumb or bad or crazy, like that's that's kind of the direction we're headed. Like they're going to stimulate, they're going to figure out ways to try and support markets and support the economy and it's just like the path is sort of paved. It's just kind of like or the destination is is kind of paved, it's sort of the path now. And so he's like, well we might as well make the path bumpy so we can insider trade it. But like yeah, it's there's not a lot they can do um and I think that's that's why as an investor you should be more cautious going into into the midterms because you have this huge vol event sitting out on the horizon and the stakes are you know fever pitch record stakes like he's going to get impeached if he loses, yada yada yada and the the you know the desperation is rising with it. And and so you're just not saying go buy volatility here because it's super elevated, but that's why volatility is so high is because it's correlated, it's people have no idea, people are expecting wilder and wilder things. Uh you know we thought Venezuela was still this year, that we thought that was crazy and that was literally still this year and then we said it's going to get crazier and then Iran happened. And it's going to still get crazier. And so cash is a big position and you know sometimes it's just it's just better to to know that these are this is what's going on and and not try and you know get too cute about it because it's just frankly not going to be good for most most people in the markets. Unless you have inside information and you're out you're out of the administration. But Hedgesat tried it and he he he tried to front run some defense spending and then still got murked. So that just shows how hard it is to be in the markets.","offset":3301,"duration":150}],"startTime":2943},{"title":"Geopolitical Desperation on Social Media","summary":"The hosts briefly critique the bizarre, desperate, and overly aggressive behavior seen on political Twitter regarding global conflicts.","entries":[{"text":"Tyler: You know I gotta I gotta say this is just like Hedgesat had this tweet that he said it's like into the Stone Ages or something. And I just I never like I think of maybe it's me getting older and being more like I never root for death. And it's such a weird you know -","offset":3451,"duration":22},{"text":"Felix: Dude they make Twitter video montages of them like killing people. Are you kidding me?","offset":3473,"duration":4},{"text":"Tyler: Yeah it's it's really bizarre. And I just I'm not like you know I don't get it. And it desperate it desperation causes you know irrational thinking.","offset":3477,"duration":11},{"text":"Quinn: It feels it feels like beta male to me where I'm like you know the alpha male sits there and he's quiet and he's you know lets his confidence speak for himself. It's just so beta and it's sorry.","offset":3488,"duration":12},{"text":"Felix: Yeah, we just need to get somebody under 30 years old on here to explain us if this is cool or not because I don't see it anyway.","offset":3500,"duration":7},{"text":"Quinn: It's it's it's it's what anyone would do in these this position is what it is. It's just when your back's against the wall, when you not when you don't have the winning cards, you lost all your leverage, you lost approval, you lost confidence in yourself, you know, it's what humans do in these situations. I I think it's a ugly side of humans for sure.","offset":3507,"duration":23}],"startTime":3451},{"title":"Outro Banter: Haircuts & Houseplants","summary":"The episode wraps up with lighthearted jokes about Felix's slicked-back hairstyle, interior design in bachelor pads, and how having children will eventually disrupt their sleep schedules.","entries":[{"text":"Tyler: I I'm open to the contra and proven wrong in hindsight, like honestly like I try to keep you as an investor you can't be too dogmatic about these things. If there is a bigger geopolitical 4D chess thing going on right now with Saudi Arabia and all these other countries that we don't know about, totally in hindsight that'll I can admit that, but right now it's not looking good. And and lastly before we end, how come I didn't get the slick back hair black shirt note? Like what is this is this like Johnny Depp and you know Cusack getting together like you got you even got the little swirl coming down, it's great.","offset":3530,"duration":38},{"text":"Felix: Look at this thing, I know dude.","offset":3568,"duration":2},{"text":"Quinn: Next week we'll plan something and loop you in this time.","offset":3570,"duration":3},{"text":"Felix: And you guys on my side I gotta start tanning because like you guys down in the South are just looking good. I'm up here in Canada looking pretty rough.","offset":3573,"duration":8},{"text":"Tyler: You're pasty, bro. I will say you guys are definitely, you know, I know how you you you're in serious relationships is that you guys have plants. No single male has a plant. It's like -","offset":3581,"duration":14},{"text":"Quinn: I actually went to this nursery last weekend to to accumulate more plants.","offset":3595,"duration":4},{"text":"Tyler: Yeah, every every bachelor just got like it's like the most stone-cold room, nothing on the walls, it's like just a TV and a seat.","offset":3599,"duration":12},{"text":"Felix: Yeah, TV, a campy chair and then like your your computer.","offset":3611,"duration":5},{"text":"Tyler: Dude yeah all grown up man. Just trying to be like you. Yeah now you got art and you got like plants and stuff, it's great. Look at you guys.","offset":3616,"duration":8},{"text":"Felix: We're trying, we're trying out here. Appreciate it.","offset":3624,"duration":3},{"text":"Quinn: Doing our best.","offset":3627,"duration":1},{"text":"Felix: We missed you, Tyler, glad you're back.","offset":3628,"duration":1},{"text":"Tyler: All right bro. I can't wait to roast you guys when you have kids because you're going to come in and be like, I didn't sleep, I got I didn't sleep with take two hours of sleep, how do you do this?","offset":3629,"duration":12},{"text":"Felix: Yeah the show's going to fall apart, you're just going to be there laughing at us and be like see!","offset":3641,"duration":3},{"text":"Tyler: I'll have to carry it. All right good, it's good to be back, that was awesome.","offset":3644,"duration":5},{"text":"Felix: All right fellas. Have a good weekend, Happy Easter everybody.","offset":3649,"duration":3},{"text":"Quinn: Yeah, Happy long weekend everybody, yeah. Happy Easter.","offset":3652,"duration":3},{"text":"[outro music plays]","offset":3655,"duration":15}],"startTime":3530}],"entries":[{"text":"Tyler: This is wartime allocation of capital. And this isn't just about the Iran situation. This is about what's been building for three years, four years, five years. It just favors scarce resources you can't print.","offset":0,"duration":12},{"text":"Felix: Oil prices aren't high enough for demand destruction, but they're high enough for inflation. You could make the argument it's actually almost better for it to go higher, then you get the demand destruction like central bank's gonna actually fucking do something. We're stuck in the corridor of everybody's frozen.","offset":12,"duration":14},{"text":"Quinn: The incentives here point to inflation, and inflation is really bad for risk assets because it sends bond yields higher and equity multiples lower. I think the outlook is horrendous.","offset":26,"duration":16},{"text":"Quinn: Nothing said on Forward Guidance is a recommendation to buy or sell any investments or products. This podcast is for informational purposes only, and the views expressed by anyone on the show are solely their opinions, not financial advice or necessarily the views of Blockworks. Our hosts, guests, and the Blockworks team may hold positions in the companies, funds, or projects discussed. As always, investments in blockchain technology involve risk. Terms and conditions apply. Do your own research.","offset":42,"duration":24},{"text":"[intro music plays]","offset":66,"duration":7},{"text":"Felix: All right, what's going on everybody? Welcome back to another roundup edition of Forward Guidance and we are back with the trio. We're back at home. No more conference, no more sick Tyler. The boys are back, the trio's back. Kind of feels like we didn't miss anything. Oil's still at 100 bucks. It's like nothing's changed in the last three weeks, so I guess we didn't miss anything in that whole time.","offset":73,"duration":23},{"text":"Tyler: It was at 110 now. There you go, yeah, it is. Did you guys notice I'm a little more svelte from my weeklong hiatus from food?","offset":96,"duration":10},{"text":"Felix: You look so good dude. It's not the red light tree tied? You're not on the GLPs or what?","offset":106,"duration":5},{"text":"Tyler: No, I lost like 10 pounds from that virus. I couldn't eat for like six days. It was terrible.","offset":111,"duration":7},{"text":"Felix: That's brutal.","offset":118,"duration":1},{"text":"Tyler: Yeah, it wasn't fun.","offset":119,"duration":0},{"text":"Quinn: It is kind of groundhog day-esque because when I look at the Russell, we're closed basically smack dab where we were on Friday, March 6th. So it's like we just chopped everybody to shreds over the course of the month.","offset":119,"duration":13},{"text":"Felix: That's that's my whole thing is just like burning at the stake of put premium, even call premium, just premium everywhere just getting smoked as we just chop around. Like it's just brutal out there.","offset":132,"duration":10},{"text":"Tyler: You know what is so fascinating is like from an index basis, things - not much happens. But underneath the hood, if you look on like a sectoral basis, everything happens and that's really where all the alpha is generated. But you even notice from, you know, the - like you said, the indexes are unchanged, but some of the hedge fund performance numbers came out and some of these multi-platform funds got absolutely rocked, even in, you know, because single stock vol's super high and factor volatility's super high.","offset":142,"duration":29},{"text":"Felix: Yeah, the the potshops are all down like 4% over the last month or so, which is kind of nuts. You know who I saw was at the top, though, is Pierre Andurand, the French oil trader. He's up 30% month over month, which is kind of sick. Even though I mean, he was down like 50% last year. I don't know, his Sharpe ratio, I don't even know.","offset":171,"duration":20},{"text":"Tyler: Yeah, he's got an iron stomach, dude.","offset":191,"duration":3},{"text":"Felix: Oh, dude, it's insane.","offset":194,"duration":1},{"text":"Tyler: We were talking about that is like, it's pretty incredible. Like you have to consistently manage risk to get to that point of success, to then have enough of your LPs to stick with you through that volatility. Like they - it's not like you're going to get like a billion dollars if you're that volatile at the start of your career. So you have to be doing something right to take those drawdowns and anyway, it's just kind of -","offset":195,"duration":21},{"text":"Felix: Yeah. It is an interesting comparison compared to the potshop model, where their drawdowns are pretty limited honestly, past that 4% because, you know, if you max out your risk limits there, you just get fired. So you know, there's probably a whole new cohort at the potshops for April. Um, the rest of those guys who are down 4% have all been fired. So you know, it's a new cohort in and, you know, just roll the dice once again.","offset":216,"duration":22},{"text":"Tyler: Absolutely.","offset":238,"duration":1},{"text":"Quinn: That must be the most stressful job in the whole entire world if in this market if you can't have any any lean.","offset":239,"duration":7},{"text":"Felix: You're down 1% this week. You're like, oh god. You're getting smoked by Trump tweets and then you just get carried out of your pod like man. I yeah, you know, it's the cool place these days, but that's a lot to handle.","offset":246,"duration":15},{"text":"Tyler: You know what existentially it's just not in my DNA because like I - I'd like to think like investing that's a risk management job. Like you - you might as well be like an insurance, you know, risk person, rather than like the whole point of investing is to grow the economy and be risk-forward. And if you have one good year as like a growth investor, you can like compound that. Although the guys that are the heads of the multi-platform funds and have figured out are clearly like, you know, what's just men of the world. But like if you're just a risk manager PM, like these these long-only guys, long-only schlobs that ride like, you know, frontier assets may crush it comparatively, with way less stress.","offset":261,"duration":47},{"text":"Felix: Yeah, I mean their mandate's long-only, you're just like, well, everything's down.","offset":308,"duration":4},{"text":"Tyler: Yeah, just buy it, it's going up. You know, like, oh let's - we're going to invest in space stocks, yeah, let's go, let's keep going, pump this thing.","offset":312,"duration":9},{"text":"Felix: Yeah, yeah, all right. Um, anyway we're back from DAS. Great time, had some great interviews. Quinn had a great interview with with Tony G, TG Macro. We had a good roundup at Joseph Wang. I had my my fireside chat with Fed Governor Stephen Ryan, that was super cool. We put that out on the platform yesterday or Wednesday, this is coming out Friday. So check that out. But yeah, man, Tyler we missed you there.","offset":321,"duration":20},{"text":"Tyler: Yeah, I really missed you guys. It was uh, you know, tough traveling these days, but I'm kind of getting out of it. Eventually I'll be -","offset":341,"duration":10},{"text":"Felix: Fed life.","offset":351,"duration":0},{"text":"Tyler: Yeah, yeah, exactly. Um, all right well why don't we talk about where the market's at. Obviously like we were just saying, it's it's somewhat Groundhog Day in terms of the geopolitical headlines. Like we had this this big Trump speech last night, addressing the nation. Not a lot not a lot of new news, but it's always interesting to contrast that with positioning where we had, you know, off the back of two days of rallying going into that point and a lot of expectations it felt like baked into the market that he's going to potentially announce some sort of ceasefire. Um, just the fact that there's no new information still, you know, reiterating this idea of a couple more weeks and and all of that and markets sold off and here we are again just mental and just chopping around. Um, Quinn, what's your read on the markets? Start with you here, what's going on?","offset":351,"duration":45},{"text":"Quinn: Yeah, I I mean, my conviction has waned in terms of near-term direction. Have been very decidedly and convictedly bearish for the whole start of the year pretty much. I mean, playing it long short from the metals longs to the energy longs and pretty much short tech and related things the whole whole way down. But um, here I just think that like the market is so hedged and you kind of have to have - I wrote in in this morning - you kind of have to have an egg timer on your plays. Like we've been pounding the table bearish Mag 7 and things for for like three or four months and and they're kind of not going down anymore. Like I - I had some charts if we want to start on those.","offset":396,"duration":53},{"text":"Felix: Yeah, let's see them.","offset":449,"duration":1},{"text":"Quinn: So maybe start with slide 30. I - this one is global CTA positioning, basically just showing and these these might be like a week old, so for probably from last Friday. So just you know, maybe even more degrossing has happened this week. But this is CTA showing just a very extreme deleveraging. Positioning isn't at lows, but you know, in terms of one-month change is very low. The the next slide shows the CTA positioning's very very flat to short. Um, the next one is the the implied moves of of S&P one-week straddle cost, which is extremely elevated. Um, you can kind of see 2022 as a pretty good comp for probably the environment we're going into there with just structurally elevated for the year. The next one is uh, the Move index, one-month change, which is bond volatility. Obviously, you know, this is like fourth highest in the last number of years. Um, so that's a pretty big jump. Um, the next one is S&P futures asset manager positioning, uh rolling three-week change, huge huge decline. And then on the sentiment stuff, you have AAII bearish, next next slide, bearish sentiments moving up. Next one, consolidated positioning moving down. Fundamental long short on the next one are, you know, sharpest weekly reduction since Liberation Day. And then the last one is uh, Nasdaq members above the 50-day moving average, which is which is extremely low. So it you know, a lot of these kind of saying the same thing, but to me it's it's the market has delevered and degrossed a a fair bit amount. Like so much so that shorting at these areas is a very tough place to make money when when you see these types of of moves and factor in on top of that volatility skew and put uh, put um, demand is still very high. So we've degrossed tremendously the last, a lot of the long-onlys, the trend followers, systematics, and the market is still very hedged. So like it was an obvious short to me when the market wasn't so hedged, VIX was lower and no one had delevered and degrossed and now it's kind of like eh, I don't want to be the last guy at the party and I've I've pretty much used this week to trim. It was kind of funny because coming into the week, I stayed short over last weekend, which was kind of different because every Monday we got a bounce and I stayed short, kind of covered early in the week and I was like so fatigued from - I was carrying very large risk on on this these positions for like two, three months straight. I was like all right, I'm going to just kind of wrap it up for for a week and reset, rejuvenate, write, think. And then the next two days, we just get the mother of all squeezes on completely BS news going into this Telegraph Trump press conference. And yesterday I'm sitting there I'm like I gotta short this thing again. I have to. There's no way a 9 p.m. press conference is to announce something good. You set up a 9 p.m.er to announce, you know, something bad. If it was good, he would have just telegraphed it to the world via Twitter and the market's kind of rising on lower volume. So I was like ah fuck it, I'll short again. And then this morning I the markets didn't open fast enough to cover and like I'm like all right, time to go enjoy Easter holy weekend and so I'm just waiting for the next fat pitch. I I don't I'm I still have stuff on, but it's it's very flat and way degrossed. So I don't know, like I think April's the best chance for a bounce out of any month. I don't think the medium-term picture's pretty at all. Like Trump told us point blank there's a month left to the war, which probably means two or three or more. So it's not going to be great, but I just don't see where the incremental selling comes from. I think everybody knows uh, all the information's out there. So I'm just waiting to watch and I'd love to short another couple percentage points higher on on risk again is is what I'd look for.","offset":450,"duration":261},{"text":"Tyler: I think part of the uh, the problem is the market got overhedged and index actual index realized volatility did not rise commensurately with the implied volatility. So you know, implied volatility is forward looking, realized volatility is backward looking. And like we said, the index actual trading did not really move that much. So you know, the implied volatility rolls off as time goes on, causes that short squeeze effect that we saw today a little bit. So it's more of like the, you know, because of all the systematic trading, these things get so exacerbated in either direction and we saw like the VIX curve invert, that's usually a gr- my favorite sign for like when things are overhedged to the downside. I will say this though, the market was on the precipice of some sort of like if you looked at the dollar breaking out to new highs, if you looked at the yen at 160, like that could have broken out and caused a major credit vol and what what did we see? We saw the Bank of Japan lower their quantitative easing to so so the yen squeezed, right? The vol controllers always know these levels and and I guess it's a good thing that things don't just get completely derailed, your pr- they're proactive now with policy rather than reactive, which is you know, historically way different. So you have to think about that, you know, when you're at these levels. If they don't break through on high volume, that means they're probably going to reverse. So that's you know, I try to point them out on Twitter where I can, you know, when when I feel like this is a breaking point and obviously you know, the dollar rolled over, the yen squeezed and then all the vol metrics kind of rolled off after that. So it was a really bipolar outcome, you could have seen the market kind of cave and you still can, like you gotta watch the dollar and oil here, they're we're still not out of you know, the woods by any means. Um, and then I just wanted to show you this. Go to slide 56. There's a phenomenon, I'm like I'm always watching market structure and obviously retail has become a bigger component of uh, the market now in since retail's been conditioned to buy the dip. You know, we dr- generally have seen and you also have the zero days till expiry options. So this is from Citadel Securities, but you can see over the month of March, Monday has been up on S&P, Nasdaq, and the Russell and then you can see as those options bleed because retail traders are morons and they can't actually understand that like your theta your theta decay happens and then they're waiting for the end of the week where oh, it's just a Hail Mary, right? Like they need the call options, it's usually buying call options, right? And then the call options bleed and then the delta sell the dealer sells the delta once the retail gets stomped out on a Friday. So I think that was largely this month's whole um, that was what we saw continuously for the month of March and now I think a lot of those volatility things have reset, retail's really take gotten hammered here and we'll see what happens uh looking forward based on the geopolitics. But I don't know, a lot of the it feels like you need a little consolidation before you have another roll lower. And then I wanted to show these other two things where it's all - it's not all bearish, it's primarily in tech. So if you go to slide 51, there's a couple interesting things going on. It's like i- there's this guy was named Diego Parrilla and he called about the he called the bubble economy and then the anti-bubble economy and so the bubble economy was all the non-profitable stuff going up, like the tech tech things and the real economy was the inverse, which is like you know, natural resources, metals, etc. Um, but we can actually see you know, global manufacturing PMIs going up here and at the same time you know, central banks are are not easing anymore. So um, and you if that rolls over, that's I think that's really pressuring like the high multiple type sectors. But if you go go to the next slide, this is the uh, Goldman Sachs industrial metals index. Like this is not a bearish chart, right? And there's a lot of things happening in the real economy. And like and then if you go to the next slide, the Dow Transports. Like that's a gr- there's money leaving tech and going into like real things now. Um, and interestingly enough I'll give a shout out to these guys because they're moving to Austin, Texas, but there's a hedge fund down here I think it's called Schottenfeld Capital and their whole premise is to to invest in things that are real. And so this you know, if you get this you know, not only are they nailing the macro trade Austin, Texas, but they're nailing this generational trade from like you know, high multiple software stuff to like real things that you need for the economy. And I think like that that is a secular play here that's really kind of you know, important. Um, and we're seeing that on the ground. And then if you let's see, the last one is tr- if you go to the next one, I did the tran- transportation index versus QQQ and you can kind of see I circled the low, it's a little hard to see here, but this is the ratio between the two and we we're at a low where in 2000 we saw you know, the tech bubble burst and then the Dow Transports took off. So the the bottom green part is the ratio of when when that green line is rising, that means transports are outperforming and when it's falling, that means tech is outperforming. So we're you know, if this keeps up and you see the capital concentration out of tech into like real stuff, I think this you know, I think this line should should mean revert to the upside.","offset":711,"duration":363},{"text":"Felix: That's a sick, I like the way you put that all together with the market structure initially, too, because I think it really it leads into also what Quinn's talking about, just being neutral on the whole punting on on Iran situation here where it just like the easy shorts have happened, there's been so much degrossing, hedging. Um, I mean another one, too, is also this uh JPMorgan collar trade that that expired on Tuesday. That's that's you know, increasingly moving- I mean this is the whole theme, right? Is that there's these these macro ideas, but then the markets are so dislocated from those fundamentals and everybody goes insane because we're actually just being driven by these Opex flows, these CTAs, these uh JPMorgan collars that act as magnets to around expiry. So you know, you can see where actually, hold on, let me get this chart here. Um, this is a sweet chart from our our buddy Andy Constan, just looking at tracking that collar. And you can see right on the expiry on Tuesday, it we kind of expired right at it on the on the long put side and then as soon as that began the roll, markets rallied like crazy on that Tuesday. And you know, everybody's attributing it to it to like a single head like where's the news, what's the news, what did Trump say? And it's just like dude, this is just market structure. Like there's just it's just like every like it's just a game it's just a, you know, it's a Ponzi like you say Tyler. Like it's just all these like quant-driven flows and passive flows. It's just a - I don't know -","offset":1074,"duration":85},{"text":"Tyler: It's just a different management. If you think about it like I've been trying to relate it to if you think about it as if like a a manufacturing um plant for automobiles 50 years ago. You know, it was used to you had to manually put these cars together with hands on a on a conveyor belt. Now they're automated by robots and that's essentially kind of like the stock market's gotten way more efficient, but in that efficiency, you still have these moments where when stuff breaks down, when the robot breaks down, you really have drastic outcomes where that really can screw things up uh, because there's you know, it was my whole point about when you have a heterogeneous market with thousands of different things interacting, you don't really have systemic risk. But when you have a homogeneous market where all these things are have the same incentives and they have the same programmatic quant things, it makes for more sys- systemic risk, which is like that robot breaks down on a conveyor line and then you don't know what to do, right? Like you're then you have to buy all sorts of insurance and everyone rushes to buy the insurance, you know, because the supply chains are messed up. And so I think that's like the new because the world is so centralized and so efficient in a lot of ways, it causes when things start getting rocked it it makes me just want to start like a long vol fund and whenever whenever vol just spikes, oh you just sell it. Like you just sit there and you own insurance when it's cheap and you sell the insurance when it's expensive and you know it's going to happen because of these market structure types of things. So reach out to me if you want to - I'm just kidding.","offset":1159,"duration":98},{"text":"Felix: Yeah, go go talk to Nassim Taleb about that or something.","offset":1257,"duration":3},{"text":"Tyler: Yeah, yeah, exactly. But it's happening more frequently because of centralized, I think.","offset":1260,"duration":8},{"text":"Quinn: Yeah. I mean it it's like when people want a reason why, you know, what did Trump say or whatever that the market's up um both days, it's like look at the VIX, it's down huge. So it's just this mechanical rebuying and no news, nothing changed. In fact, Trump's still saying throughout the whole time like, you know, aggressive things and it it just kind of I think you just need to see either the labor market deteriorate or you know, maybe it's boots on the ground, maybe it's whatever to to really frighten people. Like we all know that people I think there's still enough belief that things are not going to get extremely worse from here. I I think the outlook is horrendous. I mean, I think the inflation outlook is is totally being slept on for how for what oil prices are doing. I I think bonds are the next year to drop.","offset":1268,"duration":54},{"text":"Felix: That's the thing oil - oil prices aren't high enough for demand destruction but they're high enough for inflation. And that's actually the double-edged sword of what they're trying to do with manipulating these markets of trying to keep oil suppressed is that you're actually you're keeping it in the corridor of inflation without getting to the corridor of demand destruction. You could make the argument it's actually almost better for it to go higher because then it then you get the demand destruction like central bank's can actually fucking do something, but we're stuck in the corridor of of everybody's frozen and then we just have the inflationary side.","offset":1322,"duration":29},{"text":"Quinn: Well you also get the you also get the supply response if you let the market do its thing and find natural prices. But if you suppress prices and don't let it trade freely, there's no production response. If you look at rig counts, there's no uptick in U.S. rig counts in the Permian nowhere. No one is this whole month. Yes, it takes some time, you know, you you can't just get on the horn and mobilize dozens of rigs, but it's one month in and and there's no supply response in the U.S. and that that's not good. So you have to let -","offset":1351,"duration":36},{"text":"Felix: Yeah. I mean how do you plan a rig count coming online when you're when you're you know the other side of your trade is Scott Bessent in the front months or something?","offset":1387,"duration":7},{"text":"Quinn: Yeah, right. And so then and then you still have people hedging out in the back end. I think back to Andy uh a trade I - so yesterday I loaded up on front-dated oil um because you know part of the thesis that he wasn't going to end the war and it was it's not endable right now. And um, that paid huge and then I that idea floating around a about the huge differential because you know front months at like 110 but then December's only at 70 bucks. And so then like but but the things they're doing, selling front, buying back, doing these like basis trades, like manipulating the market, it you're on the same side as them then if you're buying the long-dated stuff because it like you said, Felix, it basically keeps demand in and helps prices stay higher for longer. So there's no you can't control inflation when the cat's out of the bag like this, even though they're going to try.","offset":1394,"duration":55},{"text":"Tyler: You know what on that point, this this was a really divergent view was I read Pippa Malmgren's last piece and who I want to ask her to come hopefully she can come in the next couple weeks, but she talked about maybe maybe this is all planned because like what does you know high oil prices really in from the Straits of Hormuz really kills China more and what if the biggest news she said that everyone missed was there was a I believe it was like a nuclear fusion breakthrough in late March, or maybe it was late February, where we figured out how to like unlock nuclear fusion in SMRs. So essentially like you could have nuclear power on a small basis. So what hurts China the most when we have this huge generational unlock from you know nuclear fusion and and small modular reactors, where it's like we're moving into the 21st century and the as in the U.S. and if you want to be in, you know, she calls it from molecules to atoms. We're we're moving from molecules to atoms meaning being stuck on an oil type uh petrodollar versus being stuck on, you know, a nuclear new type of of you know backing energy backing to whatever currency's going to win, right? And I think this is a really interesting divergent point, which is like maybe they don't want to rush to get oil prices lower because that we're a relative winner in that game and especially when you have this new technological unlock, it lowers our cost of capital at if your energy goes from you know old school oil to a nuclear solar type thing. I mean, what that makes us win the 21st century game. I don't know if that's it sounds nice.","offset":1449,"duration":111},{"text":"Felix: But I will say yeah, she's good at putting out those divergent mapping ideas. I I don't know about the track record of them, but they're how's the global peace dividend working? Yeah, that one didn't that one didn't - well but you know like these things are all I think from if you zoom out -","offset":1560,"duration":15},{"text":"Quinn: But China's ahead of us in nuclear, they're ahead of us in solar, they're ahead of us in using natural gas for transportation. China's absolutely eating our lunch on every one of these other energy sources.","offset":1575,"duration":12},{"text":"Tyler: That's why I would love to have her on and like kind of -","offset":1587,"duration":3},{"text":"Felix: That would be great, yeah. I would love that, that would be awesome.","offset":1590,"duration":3},{"text":"Tyler: - to to hear the contra, but like from I could see that future if that's really like the age of abundance and we move into this new frontier society, that's great. But you also have to deal with like the credit problems if you're in this giant debt bubble and credit constricts and you can't grow your way out of it, then you know, shit goes south real fast. Um, I think um to earlier point about the inflationary dynamic is yeah, like war is inflationary, plus when it's focused on an oil shock like this. And there's been a couple different news headlines come out today I want to get you guys's take on. The first one is that Amazon is actually putting on a 3.5% fuel surcharge on their fulfillment. So you know, it's like here we are, if if oil was 150, you know, maybe people wouldn't be buying as many things from Amazon, but because it's at 100, instead we're getting a 3.5% surcharge.","offset":1593,"duration":53},{"text":"Tyler: You know what on a small basis, I got a buddy who runs a landscaping company in Massachusetts and he puts he's putting a surcharge on his all the oil he uses for you know cutting people's lawns, doing you know all sorts of yard work. And you know, so this is this is going to factor into inflation in the future, which makes me really suspect of uh yields. And I actually got a good chart on uh let's see, this is from my buddy John at BTIG. He uh he's got one of the a really good note morning note, but if you go to slide 50, he shows you since the beginning of the war, this is how much U.S. treasuries have have risen across the yield curve and you can kind of see um you know this is pretty consistent and now you're getting the the cost spiral on from Amazon. I'm sure it's everybody you know tacking on some of the oil tax.","offset":1646,"duration":63},{"text":"Felix: Yeah.","offset":1709,"duration":1},{"text":"Tyler: Jordi Vistor said basically these inputs we're going to see flow through you know for the next couple months into CPI. So things can get a little funky on - what what this chart shows too, that's important to keep in mind, is that all the short-dated stuff uh except for the 12 months, the white line, but the two-year, the five-year, um they've risen much more than the 30-year and 10-year. So the curve is flattened through this period, basically people investors saying this is going to keep policy restrictive longer and therefore growth is going to be hurt by it. But it's bear flattened as every all yields have moved up. And the real problem I think is what happens when presumably you know June comes around, first first new Fed meeting, uh you're going to get policy response into the election, oil's still trading elevated, the inflation's kind of being pushed through at that point and then you start to cut and stimulate. You know assuming I'd imagine they also we haven't seen it yet, but probably do some sort of fiscal stimulus into the election. So then you get a bear steepening because so it's just yeah, the bonds are awfully here, awful awful awful.","offset":1710,"duration":78},{"text":"Quinn: [Ad break for Arkham Intelligence]","offset":1788,"duration":48},{"text":"[Ad break for Blockworks Investor Relations]","offset":1836,"duration":49},{"text":"Felix: So this is a I've been considering on my Claude journey. I I made a twos-tens regime map. I just realized the way I screenshotted this it doesn't show the color codes, but yeah -","offset":1885,"duration":11},{"text":"Tyler: I was like what is this?","offset":1896,"duration":1},{"text":"Felix: Pretty, it's very pretty Felix.","offset":1897,"duration":1},{"text":"Felix: Thank you. I'll I'll say it verbally, but the green, so this is a rolling five day and it shows the green is the bear flattener. Um, the pink is bull bull flattener, the rest is yeah, the the pink one which is around what you were saying, Quinn, is the bear steepener. So um, you can see it's come down a lot. Um, and I've been thinking a lot about where does that go from here and if you look at like inflation swaps, contrasting that with what we just looked at with the yields, it's an interesting situation. You can see like the the one-year, two-year is up a lot, the five-year is up modestly since the since the war. Um, 30 years actually continued the trend down. So I don't know, kind of in the same camp where I see a lot of folks trying to bid the long end on this idea of like a recession play, but I think you're in this again in this weird corridor where you need things to get worse for that to happen. Um, so you're sort of in the doldrums.","offset":1898,"duration":54},{"text":"Quinn: But not worse enough where it brings down receipts and it's this double-edged sword of all assets up or all down because bonds if you plot them next to stock the indices, they've been trading like the indices. So -","offset":1952,"duration":14},{"text":"Tyler: Gundlach had a interesting call. He was on this podcast with I think her name's Julia LaRoche. He said this is the first time we've seen you know in these crisis scenarios bond yields have risen and there's no way out. Like they are so screwed here and he's he's basically saying they're going to have to do something crazy and he was even calling for everyone who has treasuries, all of a sudden oh your your coupon is cut by say like 50%. Imagine if you woke up overnight, it was just this giant like overnight policy where they just said oh by the way, your treasuries are down by 50% and the dollar rolls out of bed, like gold doubles. Like you could have there's a it's essentially a debt jubilee, right? Where they have to get the rates down on in debt and treasury debt because it's getting egregious and if you have a recession it's going to get more egregious. So you have to get you're going we're going to get into wacky wacky policy mode here.","offset":1966,"duration":62},{"text":"Felix: Gundlach - Gundlach, those words came out of his mouth, he said what if what if they cut coupons?","offset":2028,"duration":7},{"text":"Felix: Yes, he did, but he -","offset":2035,"duration":1},{"text":"Tyler: I've heard him say this before about um he does think this is like a medium or like a a something that's on the cards at some point down the line.","offset":2036,"duration":8},{"text":"Quinn: And he's legitimate. He's he's the Bond King, or one of them.","offset":2044,"duration":5},{"text":"Tyler: And you know Lyn Alden's been saying the same thing. She had a great interview with uh was it Peter McCormack, too, and I I I'm seeing the same thing, but here's a good chart for that. Go to 62. So this is uh this is gold. You can see gold, there's secular stuff going on that's probably going to work. So gold producer cash flow is the dark blue line, that's on the left, so you can see their like margins are huge. But then if you look to the the relative performance of gold equities versus gold bullion, we're at even though you know margins are more than double what they were at in 2020, the the ratio is still the same. So like if you have some sort of crazy policy like a yield curve control or like a tax on boomers vi- via like you know they won't even know if you just cut their divi- you know cut their you know treasuries by all a percentage point, oh by the way your coupon's 3% instead of 2%. Sorry, the dollar would roll over and I mean god you're looking at some crazy stuff happening and I just don't you know that's why I think you got to look at what displays relative strength in sell-offs and that's where you want to be going forward.","offset":2049,"duration":78},{"text":"Felix: Well you know what's been holding up okay is Bitcoin. I feel like we we've stopped talking about it for the last while, I've seen we've gotten a little bit of shit for that from some people. But it's just been chopping around, but it hasn't been breaking down lower either. And you know it's not getting the big sexy gains either, but -","offset":2127,"duration":15},{"text":"Tyler: It makes me nervous, which means it's either a low or there's one last big -","offset":2142,"duration":4},{"text":"Felix: That's that's always what's so hard, right? Because it was the thing that sold off first even before this whole thing, you know, January and all of that. Um, so either it's just technical support, though, that's what makes me nervous is like if you look at gold's got great support, defended it you know big. But Bitcoin has - I agree - relatively thin. But any time we start talking about haircuts on sovereign debt, I'm like hm, you know, you start you have to at least put it into the conversation. I don't know where it sits with it, but -","offset":2146,"duration":26},{"text":"Tyler: You know what people are figuring out, though, is go to this last slide, slide 63. I think they're figuring out that you can't actually save money in fixed income anymore because look at stocks as a percentage of household financial assets and like in a world where the policy is getting wonky like Gundlach and Lyn Alden everyone kind of sees, I don't know where you put your money besides stocks. And maybe that's the phenomenon of why things mean revert higher anyway is because it's just this is the great rotation out of debt.","offset":2172,"duration":37},{"text":"Felix: You know what's I have another one here just to bounce off of that. But you know what's so insane is that like the entire modern financial system was based on this little phase here where stocks and bonds are negatively correlated and like we completely ignored history where it's like mostly positively correlated and then we just built up every portfolio on this idea of like a negative correlation between stocks and bonds and now we're just we're not going to this new weird regime, we're going back to normal.","offset":2209,"duration":31},{"text":"Tyler: Yeah, yeah, it's a really good point. It's a really good point.","offset":2240,"duration":1},{"text":"Quinn: I mean, where people are putting their money, Tyler, is when I mean the labor market's horrendous, savings rate is falling, stock market is at all-time highs. So people need to spend and they're putting the their money from financial assets and financial market that market capitalization, which is at the most extreme level it's ever been in history relative to real things, they're they're taking the money and putting it in in things they have to buy to live and enjoy life and so that's what makes these periods so tough because like post-COVID -","offset":2241,"duration":37},{"text":"Felix: Or hedge their employment with the AI supply chain. That's what I'm doing.","offset":2278,"duration":6},{"text":"Quinn: That's what makes these periods so tough to for investors because it's everything that's it's very difficult to to maneuver and the things that work over the periods are are like the least sexy, the places no one's ever no one's been and you know think are very just left for dead and but look at what's worked over the last it's like all the most boring businesses, people said oil is never going above $60 a barrel again. Like I'm I'm more in the camp of Michael Howell had a a nice piece. I'm in the I'm a like mean reversion guy uh over over long periods of time. Like if history's given you a hundred years of trading look back in in the gold-oil ratio. Like I'm gonna bet that it's gonna adhere to the to that decades-long trend line and so what Michael Howell kind of was arguing for in the piece, not not that it's going to happen today or tomorrow, but that gold implies the gold-oil ratio implies $250 oil sometime in the next you know multiple years. And and so if you think about it like from the Bitcoin perspective, okay yes um debasement, monetization of debt, right. Bitcoin's price at some point will stop going down in nominal terms because the the denominator's getting debased. So - but that doesn't necessarily mean that in real terms it will be a good investment because you need peace, you need um animal spirits, you need you know fun times and you'll get countertrend bounces here. But over the next if you look out over the next year, like do you envision us immediately anytime soon going back to a place where you know everyone just relies on globalization and believes shipping lanes are open and you know my neighbor's gonna give me that commodity that scarce one when I need it and I trust the the U.S. treasury to hold my funds in treasury? No, none of this stuff. So when you think about this is wartime allocation of capital. And and this isn't just about the Iran situation. This is about what's been building for three years, four years, five years and it just favors scarce resources you can't print. And right now leading up to this, it was gold and metals, now it's oil and energy. You know soon it might be food, it might go back to metals, but these are things you need. And if everybody's piled in the gold, that's why it's not working, it's trading like equities because at some point these countries gotta spend their gold, they bought gold as a fiat hedge, as a store of value. And at some point if they aren't getting oil, you know UK just announced some stimulus measures for their citizens, some people I know there said there's lines at every gas station and four of the five are out of like gasoline. Like wow these are there's serious issues and people are going to throw the kitchen sink at it.","offset":2284,"duration":188},{"text":"Tyler: Check this, go to slide 57, JPMorgan had their uh default monitor this week, their note and this is the combined high-yield loan distressed universe, it's hit it's highest level since June of 2023. You know if they can't figure out how to get policy rates lower, these things have a tendency to spiral and we saw a little bit of loosening from the credit spreads this week, that keeps going you could see a major squeeze in risk assets, but this definitely these things are hard to unwind and we've seen obviously what so there was a great tweet it said something like if Iran never happened all we'd be talking about is like Blue Owl distressed debt and private equity problems because like that's really a huge issue that's not going away anytime soon and can really spiral. But and that'll affect like all sorts of asset classes eventually, but it could just be a slow default, it's really I don't know it's hard to decipher, but I do know that's a real big issue underlying this all.","offset":2472,"duration":69},{"text":"Quinn: Yeah I I think one of the things I actually wrote about this week I haven't put it out yet, but um I was just kind of like blank sheet of paper, it's like if I look into the into the future what what are the things I see most clearly? And one of them is sustained higher for longer commodity prices. Like yeah okay, we get a resolution oil drops 20 bucks, I'm not talking about that, but we're not going back to 60. Maybe it goes to 80, you know that's probably a great dip to buy um and the whole complex is now a scarce thing that you have to put a premium on. So I see higher for longer there. Uh and the other thing I see is kind of tangential is like conflict not going away and in one of the best ways to play that in addition to I mentioned the long-dated oil futures contracts is credit problems because the consumer's getting hit both two ways, one um it's a it's a demand destruction because higher prices, inflation, they can't travel, the things more expensive, it costs them more money to get to work. So higher gas energy food prices really affects consumers, but then two the negative reflexive wealth effect as as already going into this savings rate was falling, so people were dipping into their wealth via assets and savings and that's falling reflexively via lower asset prices. So now their their kitty to to spend from is also lower. So what does that look like in the future? Like that looks like cutting back your summer vacation plans, that looks like you know kids aren't getting you know the extra thing. And so that's just weaker and that's credit credit problems. At the end of the day, like I I think financials like I don't really see a good case to be made for financials here um and so I in small caps and all these sort of cyclical uh we were saying a couple weeks ago before the war, we said the cyclical reacceleration, yes there's some bright spots, green shoots, but without Fed accommodation and and follow through it's it's dicey and now it's -","offset":2541,"duration":121},{"text":"Felix: Yeah, yeah, we get the emerging little sprinkles of it and then now it's totally smoked. You know, like we went from quite a few cuts priced to almost zero cuts priced, you know. You have a doubling of oil price you just can't you just can't get that sort of a reacceleration when it's like just barely alive. Um, it's yeah, it's it's done.","offset":2662,"duration":20},{"text":"Tyler: Here's a good snippet, I have to fly home to Jersey uh just from Jersey to Austin and we were booking flights for my family, you guys this is little microcosm, guess guess give me a guess on how many for five people how much the flights were all together round trip?","offset":2682,"duration":20},{"text":"Felix: Three grand.","offset":2702,"duration":1},{"text":"Tyler: 3,500 bucks. Bro, stick for lower for one round trip flight and you're just like eventually that's gotta cause demand destruction, you know.","offset":2703,"duration":12},{"text":"Felix: Totally. I guess yeah, I mean to earlier point, like the 150-dollar barrel situation, that's like the very quick demand destruction but there is these more long-tailed ones. Um, you know, you're starting to see different airlines start to cancel these flights uh you know these flight routes that just aren't as profitable now at at this sort of level. And you know what I realized too is over the past few years, airlines have stopped hedging their jet fuel. Have you guys heard about this? Like for whatever for whatever reason the trend these days in the airline industry's to not hedge your jet fuel, so none of them are hedged going into this.","offset":2715,"duration":31},{"text":"Tyler: Scary. Yeah, there's you know what else you know what else I've been thinking about too is like so you have the price insensitive buyer and then you have like stuff like Hyperliquid that you can take out 40x leverage on, you know, oil contracts. It's like how how much more volatile we're going to be in certain asset classes. Like this is all the market structure stuff, but -","offset":2746,"duration":25},{"text":"Quinn: I mean it's just classic it's how cycles work because they probably got berated for last few years like why are you hedging oil, it only goes down, aren't you don't you know this, you're stupid and then right when they it's just classic. Like that it's just how cycles always work.","offset":2771,"duration":16},{"text":"Felix: Yeah. You hedge after the crisis and then right before the crisis you're you're like wait why am I paying all this carry so then you yeah.","offset":2787,"duration":9},{"text":"Tyler: You try to get the max P multiple off your you know by cutting little corners and then it's a sharp reversal. But this is to to that point, this is very typical late cycle. You have the dollar rallying, the oil rallying, credit spreads widening. Like the these things they take a while to play out before they really hit earnings. Uh the one thing that's really confusing me on check this out, this is uh last chart I promise and then I'll stop. But this is the GPU rentals, slide 45. Like we're clearly in some sort of secular growth in AI. Like there's no doubt about it. Will the credit markets completely punish these these stocks before they can build out the infrastructure? Possibly. But look at the demand for this stuff. I mean it's your GPUs are rentals are rising and I mean from from the OpenAI raises $100 billion. Like that's that's kind of nuts. Like that money's got to go somewhere and have a multiplier effect to it. So -","offset":2796,"duration":65},{"text":"Felix: And Anthropic, yeah. I continue to be in the camp that like the demand for compute is way higher than we expect because like if you look at actually what's going on right now, like ever since the AI agent wave that started a few months ago, like dude the I'm getting smoked on my Claude usage. I have a max plan and like all this stuff and suddenly it's like I do I try to do a few things and I'm and and my I get smoked on my usage. So like there's I imagine everybody like this right now is that they're throttling the usage because suddenly everybody's trying to actually do things with it. Um and so it's limiting the amount of innovation that you can do, but if you increase the compute, new innovation, new ideas. So I don't know, I I don't want to completely fade it.","offset":2861,"duration":42},{"text":"Tyler: I don't either. I think I think that's something that you have to really it's going to be volatile in the macro, but like underneath fundamentals are pretty damn good.","offset":2903,"duration":12},{"text":"Felix: Yeah, I guess I guess the big question is who's who's the one underwriting that compute, these data centers, right? And and what are the cost inputs? Because you know it's stuff like, you know, semis which is related to helium, which is related to the Middle East where there's these helium- like there's that stuff, there's the fact that like the financing deals are coming from the big dogs in Dubai and now nobody's actually living in Dubai, so suddenly tax revenues are down, so suddenly you can't finance- like it just it's a cascade, right? And that's why -","offset":2915,"duration":28},{"text":"Tyler: Well I was going to say, that's why I'm watching the macro so hard here and these levels and in particular FX. If you start to see funky FX vol and you get that repatriation, it could p- put the nail in the coffin on a lot of stuff. But given the genesis plan, this is the Manhattan Project, right? They ha- they can't derail the capital markets and so I bet Trump would just if it got to that level where the credit markets started shutting off, he would probably say we're out of we're out of Iran, we're going back and like you know we're going to unleash all of our reserves and by the way, no one has to pay taxes and by the way you know like that's the vol controller thing that you it's really hard to play, but secularly you know you have to pick. I think there's there's a couple themes that that work and it's just going to be really hard through the vol. You know like the gold gold is is I feel like it's secular here, I feel like AI's probably secular, I feel like space is probably secular, but you're going to have these vicious drawdowns.","offset":2943,"duration":69},{"text":"Quinn: That that's what we're getting into a difficult period though because it's not guaranteed that those mechanisms work when inflation is spiraling and you try price controls that make production worse and then stimulate like because if Trump announces stimu- stimulus tomorrow and forces the Fed down 75 basis points and all these things, I'm not buying semiconductors, I'm buying I'm buying Main Street stuff, I'm buying inflation protection, I'm buying I'm selling bonds, I'm buying I'm buying real real things that everyone can go get their hands on. I'm not I'm selling semis. So that's why I just it's such a delicate back against the wall balance right now. And I'm not saying -","offset":3012,"duration":48},{"text":"Felix: Yeah.","offset":3060,"duration":1},{"text":"Quinn: - actually right now I have I went into the weekend with zero semiconductor shorts on, I I covered my Nvidia, so I'm you know that's not even just I actually think there's a little bit of a with how beaten down Mag 7 and you know the megacaps have become, I think people might actually seek them out as safe havens over over the next few weeks if we get a bounce and you know flight to quality and safety type of thing. So I don't love that that play right here, but -","offset":3061,"duration":29},{"text":"Tyler: I do think it sets up because really what you do, right, Tyler, if you if we're go- if credit spreads are blowing out, if um the labor market's weakening and they step in to support AI in a time where Main Street's already just been getting the hammer for two two years straight, you're just guaranteeing sowing the seeds with a bow on top the demise -","offset":3090,"duration":25},{"text":"Tyler: French Revolution.","offset":3115,"duration":1},{"text":"Felix: Yeah, I mean the Main Street hates AI, you know. They're they're protesting data centers in their towns and losing the yeah.","offset":3116,"duration":7},{"text":"Quinn: Yeah. So if which I'm not this is not I actually think you're probably right that they will do everything to to support but the second they do that and you play that maybe you play that bounce or if you don't you just wait for the short again, it will sow the seeds politically and societally for that demise to be even worse because it it will be just an absolute slap in the face times a million if unemployment's you know shooting up to five.","offset":3123,"duration":30},{"text":"Tyler: Our biggest problem with that is you have a guy in office that will he's like the lowest ratings of any president in history I think it just came out today. And if you want to message that this is really important from a geopolitical standpoint to win in AI, you have to have a high trust rating and you have to be able to like say, hey we're going to take a pain as a team. You know we're going to do this together and then this is a national priority as a labor and we're going to make sure we listen to the labor pool and and say, hey we're watching out for you and like when things get bad enough we're going to pass policies that take care of you in this transition. You have to have this messaging way you got to be way out ahead of it and and this is part of the situational awareness piece is like you're going to have people fall through the cracks as this stuff is so productive. But you need to b- you need to be out there in policy and already formulating ideas and messaging it. And he's he's behind on Iran messaging like he could have messaged this way better. And and it's because he's like a he's like a TV star or like a reality TV star that likes drama rather than like actually keeping the social fabric together. And so I don't know he's going your propensity my point is your propensity for these things to break with Trump is way higher even though he might have the national like geopolitical priority correct. He doesn't have the capability of actually doing that. And it's based off the you know his polls are showing that like he's kind of just a narcissistic loser in that sense and like maybe it works, you know, maybe it works and he's in 10 years we think he's the greatest thing ever even though you know right now we I like to fade the extremes, right? And everyone hates him so much right now, maybe maybe there's some genius to it. But I don't know, I the Epstein stuff really the fucking lost me. Excuse my Fr- and like now he you know he throws Pam Bondi out to dry the whole thing is -","offset":3153,"duration":129},{"text":"Felix: That's that's because we lost the the key level at 50,000 on the Dow so she had to go.","offset":3282,"duration":6},{"text":"Tyler: Yeah, yeah, you know what that might be a great point. In hindsight like watching that and be like that was the top of the market. That was the absolute top. Imagine.","offset":3288,"duration":10},{"text":"Felix: Yeah, yeah, oh man. And now that she's fired, it's like yeah.","offset":3298,"duration":3},{"text":"Quinn: Yeah. The the thing is that you know put the politics aside like emotions and I don't like him and I like her better and whatever, at the end of the day, the the incentives here point to inflation. And inflation is really bad for risk assets because it sends bond yields higher and equity multiples lower and nobody wins. And so whether or not like what we think he's doing is good or dumb or bad or crazy, like that's that's kind of the direction we're headed. Like they're going to stimulate, they're going to figure out ways to try and support markets and support the economy and it's just like the path is sort of paved. It's just kind of like or the destination is is kind of paved, it's sort of the path now. And so he's like, well we might as well make the path bumpy so we can insider trade it. But like yeah, it's there's not a lot they can do um and I think that's that's why as an investor you should be more cautious going into into the midterms because you have this huge vol event sitting out on the horizon and the stakes are you know fever pitch record stakes like he's going to get impeached if he loses, yada yada yada and the the you know the desperation is rising with it. And and so you're just not saying go buy volatility here because it's super elevated, but that's why volatility is so high is because it's correlated, it's people have no idea, people are expecting wilder and wilder things. Uh you know we thought Venezuela was still this year, that we thought that was crazy and that was literally still this year and then we said it's going to get crazier and then Iran happened. And it's going to still get crazier. And so cash is a big position and you know sometimes it's just it's just better to to know that these are this is what's going on and and not try and you know get too cute about it because it's just frankly not going to be good for most most people in the markets. Unless you have inside information and you're out you're out of the administration. But Hedgesat tried it and he he he tried to front run some defense spending and then still got murked. So that just shows how hard it is to be in the markets.","offset":3301,"duration":150},{"text":"Tyler: You know I gotta I gotta say this is just like Hedgesat had this tweet that he said it's like into the Stone Ages or something. And I just I never like I think of maybe it's me getting older and being more like I never root for death. And it's such a weird you know -","offset":3451,"duration":22},{"text":"Felix: Dude they make Twitter video montages of them like killing people. Are you kidding me?","offset":3473,"duration":4},{"text":"Tyler: Yeah it's it's really bizarre. And I just I'm not like you know I don't get it. And it desperate it desperation causes you know irrational thinking.","offset":3477,"duration":11},{"text":"Quinn: It feels it feels like beta male to me where I'm like you know the alpha male sits there and he's quiet and he's you know lets his confidence speak for himself. It's just so beta and it's sorry.","offset":3488,"duration":12},{"text":"Felix: Yeah, we just need to get somebody under 30 years old on here to explain us if this is cool or not because I don't see it anyway.","offset":3500,"duration":7},{"text":"Quinn: It's it's it's it's what anyone would do in these this position is what it is. It's just when your back's against the wall, when you not when you don't have the winning cards, you lost all your leverage, you lost approval, you lost confidence in yourself, you know, it's what humans do in these situations. I I think it's a ugly side of humans for sure.","offset":3507,"duration":23},{"text":"Tyler: I I'm open to the contra and proven wrong in hindsight, like honestly like I try to keep you as an investor you can't be too dogmatic about these things. If there is a bigger geopolitical 4D chess thing going on right now with Saudi Arabia and all these other countries that we don't know about, totally in hindsight that'll I can admit that, but right now it's not looking good. And and lastly before we end, how come I didn't get the slick back hair black shirt note? Like what is this is this like Johnny Depp and you know Cusack getting together like you got you even got the little swirl coming down, it's great.","offset":3530,"duration":38},{"text":"Felix: Look at this thing, I know dude.","offset":3568,"duration":2},{"text":"Quinn: Next week we'll plan something and loop you in this time.","offset":3570,"duration":3},{"text":"Felix: And you guys on my side I gotta start tanning because like you guys down in the South are just looking good. I'm up here in Canada looking pretty rough.","offset":3573,"duration":8},{"text":"Tyler: You're pasty, bro. I will say you guys are definitely, you know, I know how you you you're in serious relationships is that you guys have plants. No single male has a plant. It's like -","offset":3581,"duration":14},{"text":"Quinn: I actually went to this nursery last weekend to to accumulate more plants.","offset":3595,"duration":4},{"text":"Tyler: Yeah, every every bachelor just got like it's like the most stone-cold room, nothing on the walls, it's like just a TV and a seat.","offset":3599,"duration":12},{"text":"Felix: Yeah, TV, a campy chair and then like your your computer.","offset":3611,"duration":5},{"text":"Tyler: Dude yeah all grown up man. Just trying to be like you. Yeah now you got art and you got like plants and stuff, it's great. Look at you guys.","offset":3616,"duration":8},{"text":"Felix: We're trying, we're trying out here. Appreciate it.","offset":3624,"duration":3},{"text":"Quinn: Doing our best.","offset":3627,"duration":1},{"text":"Felix: We missed you, Tyler, glad you're back.","offset":3628,"duration":1},{"text":"Tyler: All right bro. I can't wait to roast you guys when you have kids because you're going to come in and be like, I didn't sleep, I got I didn't sleep with take two hours of sleep, how do you do this?","offset":3629,"duration":12},{"text":"Felix: Yeah the show's going to fall apart, you're just going to be there laughing at us and be like see!","offset":3641,"duration":3},{"text":"Tyler: I'll have to carry it. All right good, it's good to be back, that was awesome.","offset":3644,"duration":5},{"text":"Felix: All right fellas. Have a good weekend, Happy Easter everybody.","offset":3649,"duration":3},{"text":"Quinn: Yeah, Happy long weekend everybody, yeah. Happy Easter.","offset":3652,"duration":3},{"text":"[outro music plays]","offset":3655,"duration":15}],"logs":[{"elapsed":"0.0","message":"Downloading audio from YouTube...","detail":null},{"elapsed":"0.0","message":"Trying download with browser cookies (ad-free)...","detail":null},{"elapsed":"4.1","message":"⚠ Cookie download failed: WARNING: [youtube] [jsc] Error solving n challenge request using \"deno\" provider: Error running deno process (returncode: 1): \u001b[0m\u001b[1m\u001b[31merror\u001b[0m: Uncaught (in promise) TypeError: Cannot read prope","detail":null},{"elapsed":"4.1","message":"Retrying without cookies...","detail":null},{"elapsed":"36.1","message":"⚠ Downloaded without cookies — audio may contain ads","detail":null},{"elapsed":"36.1","message":"Audio downloaded (31.6 MB) in 36.1s","detail":"File size: 31.6 MB"},{"elapsed":"36.1","message":"Video title: Market Structure is Distorting Reality as Inflation Builds | Weekly Roundup","detail":null},{"elapsed":"36.1","message":"Audio duration: 1:01:05 (61.1 min)","detail":null},{"elapsed":"36.1","message":"Uploading audio to Gemini File API...","detail":null},{"elapsed":"40.3","message":"Audio uploaded in 4.2s","detail":"File ref: files/bfg7vby51k7z"},{"elapsed":"40.3","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"124.2","message":"Transcription complete in 88.1s","detail":"58705 chars received"},{"elapsed":"124.3","message":"Transcription tokens: 91,857 in / 14,751 out — cost: $0.0902","detail":null},{"elapsed":"124.3","message":"Parsed 124 transcript segments","detail":null},{"elapsed":"124.3","message":"Transcript coverage: 1:00:55 of 1:01:05 (100%) — OK","detail":null},{"elapsed":"124.3","message":"Total transcription time: 88.2s — 124 segments","detail":null},{"elapsed":"124.3","message":"Analyzing topics across 124 segments with gemini-3.1-pro-preview...","detail":null},{"elapsed":"152.9","message":"Topic analysis complete in 28.6s — found 14 topics","detail":null},{"elapsed":"152.9","message":"Analysis tokens: 15,517 in / 1,122 out / 2,376 thinking — cost: $0.0730","detail":null},{"elapsed":"152.9","message":"Pipeline finished in 152.9s — total cost: $0.1632 (125,623 tokens)","detail":null}]} \ No newline at end of file diff --git a/history/1775274863397-N-pust8qtGI.json b/history/1775274863397-N-pust8qtGI.json new file mode 100644 index 0000000..6cd43b6 --- /dev/null +++ b/history/1775274863397-N-pust8qtGI.json @@ -0,0 +1 @@ +{"id":"1775274863397-N-pust8qtGI","videoId":"N-pust8qtGI","url":"https://youtu.be/N-pust8qtGI?si=cbvgov4JY1cOHn7E","title":"SpaceX IPO, Iran War Fallout, Quantum Bitcoin Hack, The Space Opportunity","type":"youtube","topicCount":10,"segmentCount":327,"createdAt":"2026-04-04T03:54:23.397Z","uploadDate":"20260403","chunks":[{"title":"SpaceX IPO & Potential Tesla Merger","summary":"The hosts discuss SpaceX's upcoming IPO targeting a massive valuation and the likelihood of the company merging with Tesla. They explore how combining the companies could reduce shareholder lawsuits and leverage shared robotics and AI capabilities.","entries":[{"text":"Host: All right, everybody, welcome back to the number one podcast in the world, the All-In Podcast. David Sacks couldn't make it this week, but we have the trio: David Freeberg is here, your Sultan of Science; Chamath Palihapitiya.","offset":0,"duration":13},{"text":"Host: SpaceX filed confidentially to go public on April 1st, targeting a $1.75 trillion (with a T) valuation. When SpaceX goes public, if it's at that $1.75 trillion valuation—so weird to say trillion-dollar valuation for an IPO—they would be the eighth largest company in the world right behind TSMC and Saudi Aramco; they're both worth 1.7x at the taping of this podcast.","offset":13,"duration":31},{"text":"Host: Tesla is number 10 with a $1.37 trillion valuation. Hey, if you were to combine those two, as many people are speculating will happen at some point and you can buy the stock ticker ELON, that would be a $3.1 trillion company and that would make them the fourth largest company ahead of Microsoft.","offset":44,"duration":18},{"text":"Host: They're aiming to raise, Chamath, $75 billion, which would be by far the biggest raise ever in an IPO. Uh, expected to go out in June. I think they were trying to hit the 4/20 date because that would have been even more hilarious, but uh, they're not going to be able to do that.","offset":62,"duration":15},{"text":"Host: SpaceX uh, recently acquired X.ai for $250 billion. That includes X and Twitter and the X.ai large language model AI company. Starlink, generating between 50 and 80 percent of SpaceX's revenue. We'll have all those details shortly. Um, and it'll be close to $20 billion a year according to reports. Launch of rockets is the other 40 percent of the business, $5 billion in 2024 according to reports.","offset":77,"duration":25},{"text":"Host: Total revenue 2025: $15 to $16 billion with $8 billion in profit according to Reuters. So let's stop there. Uh, and we're going to talk about all the other IPOs that could be coming. Chamath, I think people really want to know—and you may have mentioned this on an earlier episode—what are the chances that Tesla and SpaceX could wind up being the same company? We saw they're collaborating on a fab...","offset":102,"duration":26},{"text":"Chamath: 100 percent.","offset":128,"duration":1},{"text":"Host: 100 percent is what you're putting it on? Okay.","offset":129,"duration":2},{"text":"Chamath: Okay, sorry. Let me—let me be clear: 99.999 percent.","offset":131,"duration":4},{"text":"Host: Okay. What will that mean when—if those two companies, or when those two companies merge?","offset":135,"duration":7},{"text":"Chamath: One of the great things that happened in my career was there was a point where, you know how like you grind at a level and then you know, you just get exposed to things at a different level, and then you grind for years and you get exposed to things at yet another level.","offset":142,"duration":15},{"text":"Chamath: In one of those steps, I was very fortunate to be introduced by Thomas LaFont, actually, to the head of Wachtell Lipton—this is a law firm—and his name is Ed Herlihy. And he said, \"This is the most important, well-known, well-run, powerful law firm in America.\"","offset":157,"duration":24},{"text":"Chamath: Then I looked at the transactions and they're just in the middle of everything. And now, you know, my lawyer, Raj Narayan, who does everything for me, one of the senior partners at Wachtell, I can attest are incredible.","offset":181,"duration":13},{"text":"Chamath: And they said to me, in the middle of all of this stuff when I was doing a bunch of deals, they said, \"Chamath, just get ready to pay a tax.\" And I said, \"What does that mean?\" They said, \"The way that the American capital markets are set up is both that you can be incredibly creative and do incredible things, but—and we talked about this a little bit last week—there's a bunch of tort that allows folks to hang around the hoop and get paid no matter what.\"","offset":194,"duration":28},{"text":"Chamath: You see this in all IPOs: shareholder lawsuits abound. And they try to create a class out of it. And the reason they do that is that there's D&O insurance that then will pay out some number of millions of dollars, the attorneys take 40 or 50 percent, and then these plaintiffs get a few bucks.","offset":222,"duration":17},{"text":"Host: Which is a shakedown.","offset":239,"duration":0},{"text":"Chamath: It was a shakedown. Call it what it is. Why am I bringing this up? If you take the Raj and Ed example of this, this SpaceX IPO is going to set up a couple of things.","offset":239,"duration":15},{"text":"Chamath: The first is there's just going to be the natural noise in the market and Elon will have to sort through all of the little ticky-tacky things. But the most important positive thing that will happen from the IPO is a validated external mark-to-market valuation of SpaceX.","offset":254,"duration":24},{"text":"Chamath: And the market every day in real time gives you a valid mark-to-market assessment of the value of Tesla. And this allows you to put these two things together to minimize these lawsuits. Yes.","offset":278,"duration":14},{"text":"Chamath: And I think that's what Elon really needs: it'll make his life tremendously simpler from a governance perspective. It'll make the companies—and this quibbling about his time—a non-issue because again, nobody talks about Zuck or Satya or Sundar or Jensen allocating time across various projects inside of Meta or Google or Microsoft or Nvidia.","offset":292,"duration":29},{"text":"Chamath: Nor should they really make this claim for Elon because, as you're seeing, there's actually an enormous overlap and commonality to the various things that he is doing. He's building the robots, but they're used inside of SpaceX. He's building a terafab, they're used inside of Tesla. He's building X.ai, they're used across both.","offset":321,"duration":22},{"text":"Chamath: So I think we need to do this. It'll minimize the shareholder noise because it'll give less room to somebody that says, \"Hey, he set a valuation out of thin air.\" But dollars-to-donuts, these things are going to merge.","offset":343,"duration":11},{"text":"Host: Well, and it speaks to the singularity that's going on right now. You know, you had a car company, you had a space company. Okay, how do those two things overlap? And it's like AI, data centers in space, where do you get chips from, and then actually going to raw materials inside of one factory, going out the other.","offset":354,"duration":23},{"text":"Host: Having discussed it with Elon many times, what he learned at Tesla or SpaceX about advanced materials informed different products at the different companies. And now you just—you'll have all of that in one place. And then you think about the brain trust that he built at those two companies, plus Boring Company, plus Neuralink. If they're all in there, all this cross-disciplinary learning is going to compound and compound and compound.","offset":377,"duration":20},{"text":"Host: Elon knows more about factories than probably anybody. Like there are some people in China who have, you know, Foxconn knows a lot about factories. You know, so there are some people who know as much or probably even a little bit more about some aspects of it, but that's a true advantage of bringing those two teams together.","offset":397,"duration":19}],"startTime":0},{"title":"Space Economy & Lunar Manufacturing","summary":"Friedberg shares his vision for the industrialization of the Moon and the economic advantages of low-gravity manufacturing. The group discusses how SpaceX is acting as a railroad to space, opening doors for asteroid mining and extraterrestrial infrastructure.","entries":[{"text":"Host: And you saw it: people would go from one company to the other. Freeberg, my question for you, very acutely with your NASA hat and, you know, your background today is: 20 years ago, he started trying to get to space with SpaceX and here we go. There's more rockets going off in a month now than there are days in the month for the entire country. And he's got rockets going up every two or three days. You can just basically hop on a SpaceX flight and get to space.","offset":416,"duration":27},{"text":"Host: Maybe you could just use your vision there to tell the audience what could things look like in another 20 years if SpaceX continues at this cadence or even, you know, goes faster because of AI?","offset":443,"duration":10},{"text":"Freeberg: Well, this week's a pretty important milestone for that point because we just launched Artemis 2 yesterday, which is man's return to the moon. So the United States shipped this rocket with four astronauts on board. They're going to do an orbit around the Earth, head to the Moon, come back around, and come back to Earth in anticipation of landing on the Moon in about two years.","offset":453,"duration":26},{"text":"Freeberg: And getting to the Moon, I think, is going to be very important, not just because there's this important social milestone and race happening right now with China, but I think the Moon could end up being kind of the next industrial frontier for humanity.","offset":479,"duration":15},{"text":"Freeberg: And the reason is, if you can get to the Moon, the Moon has an extraordinary abundance of material that we can mine, process, and manufacture into goods. And ultimately, the cost to ship those goods back to the Earth is zero. It will cost less to move goods, manufactured goods, processed or precious metals from the Moon to a specific point on Earth. It will cost less to do that than to ship it using any other terrestrial conventional method, whether that's a boat, an airplane, or a railroad.","offset":494,"duration":35},{"text":"Freeberg: And the reason is that on the Moon, you can take advantage of the low gravity—it's about one-sixth the gravity—and the complete lack of an atmosphere, meaning that it's frictionless to move material off of the Moon and very low energy to move it off of the Moon. You do not need to use a rocket propellant with high energy like we have to do to move things off of the Earth.","offset":529,"duration":19},{"text":"Freeberg: In fact, the design for moving material off of the Moon is to use what's called a mass driver, which is like a train track, like a rail, like an electric rail. You kind of see these in, you know, high-speed trains that work on kind of magnetic levitation. And you could put a package on that rail and use electricity to accelerate that package to 100 G-force, shoot it back to the Earth or theoretically shoot it to Mars, and it will go to the exact point on the Earth you want it to go to, re-enters the atmosphere, and lands with a simple parachute where you want it to go.","offset":548,"duration":31},{"text":"Freeberg: So we could run continuous mining, continuous manufacturing processes on the Moon at a fraction of the cost of what it would take to do it here on Earth. The biggest limiting factor: getting people to the Moon. And that is largely solved or will be solved in the next few years by robotics.","offset":579,"duration":17},{"text":"Freeberg: So I think that there's this pretty profound intersection with what's going on in robotics with this moment for space industrialization and moving to the Moon. So, you know, Tesla, I think 20 years from now is actually a more interesting story whether they're the same independent company or the same company. I think we're going to look back one day and have this kind of laughing observation that Tesla started out as an electric car company, ended up becoming an autonomous car company, and the autonomous competency is what led to the robotics revolution.","offset":596,"duration":32},{"text":"Freeberg: And the robotics revolution—even if the socialists ban robotics on Earth and tell us, \"No robots allowed, they're taking all the jobs\"—you could ship all those robots to the Moon and they could get to work and create an entirely new manufacturing frontier for our civilization, for humanity. That frontier can manufacture precious metals and other goods and ship them back. You could manufacture semiconductors on the Moon. All that's missing is the robot.","offset":628,"duration":24},{"text":"Freeberg: So moving the robots to the Moon or setting up the materials for robots to build themselves on the Moon is kind of the first phase of this transition. You know, asking about 20 years from now, and then the next phase is $100 billion sold out.","offset":652,"duration":9},{"text":"Freeberg: So look, I mean, I think that this may not be—and it certainly won't be—limited to just SpaceX, but SpaceX has demonstrated its capacity at being effectively the railroads. You know, what the railroads were to the West and to the frontier in the West, you know, in the last generation, SpaceX will be to the Moon and ultimately to Mars. And there's going to be an extraordinary abundance of production that's going to come out of the Moon.","offset":661,"duration":20},{"text":"Freeberg: The Moon has everything, by the way. And I'll say one more thing about SpaceX: SpaceX has also created—and this is going to be a big part of the valuation analysis that many are doing—they've created a backup to the Internet. You know, the Internet is fundamentally limited by all of the nodes on the network and the connectivity amongst all those nodes. And that connectivity is largely driven by copper and fiber optic cables.","offset":681,"duration":21},{"text":"Freeberg: So in space, what the number of satellites going up with Starlink and to actually deploy data centers that can output data on those nodes on that network, SpaceX has largely built a backup Internet. And that backup Internet can coincide with the Earth's Internet, but it creates this extraterrestrial communication network that gives us theoretically the ability to think about, \"Hey, if governments collapse, if there's civilizational upheaval, etc., etc., etc., this becomes, I think, a fundamentally kind of important technology infrastructure that's going to exist in parallel.\"","offset":702,"duration":31},{"text":"Freeberg: So I'm pretty excited about like these two separate paths for SpaceX and where they intersect with Tesla. I think it's pretty profound at the moment.","offset":733,"duration":7},{"text":"Host: Yeah, and it can't be understated what lowering the cost per kilogram to get to space has done to entrepreneurs around the company. There's multiple entrepreneurs who are now doing asteroid mining or Varda doing experimentation in space. And I have a—I've been doing some late-stage stuff, Chamath, with my syndicate, and one of the interesting companies we syndicated, we did Zipline, which is a great company, but we also did this company called Vast, Vast Space. Jed is the founder, he created Ripple and and some other crypto projects, and he put a lot of his money, hundreds of millions of dollars, into this company Vast Space.","offset":740,"duration":38},{"text":"Host: And they're designing a space station. How did they do it? Well, they just bought carriage on SpaceX rockets and they paid in advance, they have their slot, and now they're doing this massive innovation to make modular space station components. And the thesis is, \"Hey, what if Google or Amazon want to have a space station in space?\" You know, it's completely possible they may want that.","offset":778,"duration":25},{"text":"Chamath: Here's what I'll say: I think sometimes it's better to be lucky than good. There are all of these ways that so many people will end up with participation into SpaceX. I think we all owe Elon an enormous thanks. I think that this is going to unleash just an unbelievably large economy of things that we have no idea about.","offset":803,"duration":25},{"text":"Chamath: And when I see this thing, that video that you just showed, what it reminds me is that we have an over-very rudimentary capability in space. What does that mean? If you take, if you catch a ride on Falcon 9 or Falcon Heavy, basically it's dropping you off at 550 kilometers, I think. You have a different problem if you're trying to get to GEO.","offset":828,"duration":21},{"text":"Chamath: But even if you get dropped off at 500 or 550, how do you get to your actual orbital plane? Right? So meaning, if you think of Elon as like the big container ships that go from China to America, once it gets to Long Beach, you need FedEx. There's an entire infrastructure there that's going to get all of this logistics built last mile.","offset":849,"duration":22},{"text":"Chamath: There's a huge garbage collection problem that's getting built up. We still haven't technically solved how to do garbage collection in space. There's nets, there's magnetic plates—all of that is getting fixed. Then there's going to be an explosion in actual power generation.","offset":871,"duration":16},{"text":"Chamath: The cell composition of solar cells up in space are materially different. It's a really incredible thing. You look at these thin sheets—they are like 1 millimeter thick. You, if you carried it on your hand, the glass breaks, yet you can smash a meteor into it when it's lead and laminated and nothing happens. It's like the cra- so my point is in every single dimension of what the earthly economy looks like, it's now going to go and get rebuilt in space.","offset":887,"duration":32},{"text":"Chamath: There'll be a FedEx of space, there'll be a Maersk of space, there'll be a—I don't know what the garbage collection companies are—Allied Waste of space. There's going to be everything of space that exists in the United States. Freeberg just talked about the Freeport-McMoRan of space, like everything. And that we owe to him.","offset":919,"duration":18},{"text":"Chamath: And I hope he gets that credit because the amount of businesses I think that can get created and the amount of value that will be created on top of SpaceX's shoulders is vast. It's the beginning of the beginning of the beginning, and it's going to create enormous opportunities for people who are smart and resourceful.","offset":937,"duration":18},{"text":"Host: And Freeberg, maybe you could comment on the PGMs, the palladium that's on asteroids and just they're rare here on Earth. If we had an unlimited supply or a continuous supply of those minerals, you know, what what could the downstream effect of that be? And then what if we find things in space that we are unaware of? There are unknown unknowns, correct Freeberg, when you start to conceptualize this?","offset":955,"duration":26},{"text":"Freeberg: I do think like the asteroid mining is an interesting concept, but I do think it's going to be more likely that we'll have the need for infrastructure so we can produce ores and refine and so on versus, you know, bringing a chunky rock back. I think that you could do this very effectively on the Moon.","offset":981,"duration":16},{"text":"Freeberg: The primary elements that are missing from the Moon that we have on Earth are, you know, carbon, nitrogen, hydrogen, and oxygen—basically these things that make life on Earth. But that's because they primarily exist in a gaseous form and the Earth has enough gravity to retain those gases and have an atmosphere.","offset":997,"duration":22},{"text":"Freeberg: The Moon is too small to maintain an atmosphere. The gravity's too low, so those gases all kind of went away, they evaporated away in the early formation of the Earth and the Moon. But on the Moon, there's everything else: there's aluminum, there's silicon, there's palladium, there's platinum, there's gold, there's everything you possibly need.","offset":1019,"duration":19},{"text":"Freeberg: So I think as we do the calculus on all of this, we'll end up realizing that the Moon is probably the best frontier. One of the biggest issues is dissipating heat because you don't have an atmosphere, but theoretically you could recapture that heat and use like helium gas or something to turn a turbine and actually run production of even more electricity.","offset":1038,"duration":17},{"text":"Freeberg: You just put a couple solar panels out. I did the math on this: it's like 500 square meters of solar panels will let you run a 4 kilometer mass driver to ship material back to the Earth every 10 to 15 minutes. One ton of material every 10 to 15 minutes.","offset":1055,"duration":11},{"text":"Host: On the sled you described earlier that Elon's been talking about as well, yeah.","offset":1066,"duration":4},{"text":"Freeberg: So you could think about having autonomous mining vehicles deployed on the Moon processing the ore and then sending completely processed material back. And then for a heat shield for re-entry to the Earth, you just use Moon rock. You only need about 15 centimeters of Moon rock at the front of the package and then that'll burn up when it re-enters the atmosphere and the package, you know, kind of parachutes down and lands where you want it to land in your industrial shipyard or whatever.","offset":1070,"duration":23},{"text":"Freeberg: So there's just like, you know, I think we'll continue to kind of iterate on this. I'm speculating in a bunch of different ways.","offset":1093,"duration":4},{"text":"Chamath: The beginning of the beginning, the beginning of the beginning.","offset":1097,"duration":5},{"text":"Host: Gosh, I mean, can you imagine having a Moon base and America is just permanently present on the Moon? It's just and factories on the Moon, it's just wild to consider.","offset":1102,"duration":10},{"text":"Freeberg: Wild.","offset":1112,"duration":0},{"text":"Host: Can you guys just imagine like the middle or the early 19th century, like the late 1700s, early 1800s in America? And there's like all this land out on the West and like whatever people were contemplating in that moment about what they were going to go do with that land on the West and they started to travel West. Their minds would have been blown to see what happened 100 years later or now 150 years later.","offset":1112,"duration":22},{"text":"Freeberg: You know, like it's just that's the moment that we're at right now. And the railroads are being built to get us to this next great frontier, they're being laid out before us. And the opportunity is really limited only by our imagination. And before, we would have never been able to tackle these great frontiers, but this magical new technology came about called robots. And these robots are what are going to allow us to actually make use of these frontiers and explore them and develop them.","offset":1134,"duration":26},{"text":"Freeberg: And that's why this is such an incredible moment where this intersection of autonomy and robotics and space traversal kind of drive forward humanity into this new era. And it's not—again, this is not a zero-sum game, this is expanding humanity's potential, expanding production, which is so different than the way the socialists on Earth are talking about it, where everyone's fighting against progress because they think that progress is some people taking things from other people. And the truth is, it's about everyone building stuff that's new and everyone benefiting from this.","offset":1160,"duration":30},{"text":"Host: Well said.","offset":1190,"duration":1},{"text":"Chamath: I'm going to open a hotel-casino in space.","offset":1191,"duration":3},{"text":"Host: I'll be—oh, we go, that would be so sick.","offset":1194,"duration":1},{"text":"Chamath: No, I'm serious.","offset":1195,"duration":1},{"text":"Host: Absolutely.","offset":1196,"duration":0},{"text":"Freeberg: I would love that.","offset":1196,"duration":1},{"text":"Host: Yeah, and then—no rake? No rake? No gravity? No rake? No gravity?","offset":1197,"duration":7},{"text":"Chamath: No tax. No tax.","offset":1204,"duration":1},{"text":"Host: No tax! No tax on tips or poker winnings! I love it.","offset":1205,"duration":6},{"text":"Chamath: Whoever implements the red-light district in space is going to become a trillionaire.","offset":1211,"duration":4},{"text":"Host: Oh! Wow, that's—yeah, with the robotics and the uh pleasure-droids, replicants... Oh man, it could get crazy. All right, well let's just hope you're—we're not the Donner party on the way there. Um, 2026...","offset":1215,"duration":13},{"text":"Chamath: Don't worry, you'll be safely on the ground schlubbing syndicates. You'll be fine.","offset":1228,"duration":6},{"text":"Host: I'll tell you something, uh thank you. Shout out thesyndicate.com apply to join me in great companies, Chamath. Do you own thesyndicate.com?","offset":1234,"duration":7},{"text":"Chamath: No way.","offset":1241,"duration":0},{"text":"Host: Listen, I'm still working. You guys might be retired, but I'm in the game. I'm in the arena trying things, Chamath.","offset":1241,"duration":5},{"text":"Chamath: I'm selling—I'm selling enterprise software every day, that's what I do.","offset":1246,"duration":4},{"text":"Host: I mean, he literally—Chamath said, \"Hey J-Cal, can we wrap this up real quick because I got to get on a sales call? I got a discovery call.\" Listen, I like the fact that we're all working. We're working into our 50s, I love it.","offset":1250,"duration":8}],"startTime":416},{"title":"AI IPO Pipeline & Market Liquidity Risks","summary":"The group evaluates the potential 2026 IPOs of AI giants like OpenAI and Anthropic. They debate whether the public market can absorb these trillion-dollar valuations and warn of a looming capital crunch as Middle Eastern investments potentially dry up.","entries":[{"text":"Host: Hey, 2026 could be an all-time record for IPOs. Looks like it uh will be. Anthropic, OpenAI, Databricks—I mean these are all nine- and possibly ten-figure IPOs in terms of the valuations. Long tail of other companies: Stripe, Cerebras, Canva, Discord, lots of people waiting. Here's your Polymarket: SpaceX 94% obviously, that looks like it's—we just talked about that for 20 minutes. Anthropic 41% in people were saying 70% in February, OpenAI 38%, Databricks 32%.","offset":1258,"duration":40},{"text":"Host: People are wondering what could uh derail this. Obviously we we have a very pro-business group of people in Washington DC, but you have potentially this uh Iran war and we'll talk about that later in the program could potentially push us back if God forbid it was to spiral out of control. Or there was a recession, uh maybe the Democrats you know taking control of Congress, Senate, etc.","offset":1298,"duration":26},{"text":"Host: What are your thoughts here on the flurry of potential IPOs? We're talking about trillions of dollars of companies, Chamath, and if that does happen, let's start talking second- and third-order impact of that kind of distribution chain that could happen for LPs and then also all these employees uh and then a currency for these companies. We go from a Mag 7 to a Mag 17 it looks like.","offset":1324,"duration":22},{"text":"Chamath: I think that we have a bit of a risk problem. And I think this is why it makes so much sense for Elon to get out first. If you think about appetite as equivalent to like a person at a Thanksgiving dinner: when you first come in and you see all of this stuff, it's so plentiful, your eyes are bigger than your stomach.","offset":1346,"duration":20},{"text":"Chamath: And I think in a moment like that, you want to be the one that is consumed first. And I think the risk increases when you are at the tail end because the risk is that the diners will run out of space.","offset":1366,"duration":15},{"text":"Host: Plate fills up, yeah.","offset":1381,"duration":1},{"text":"Chamath: And if you use that analogy, I think the reason why people's plates will get full are probably twofold and maybe threefold. The first and most important thing is there's enough tactical event risk that people generally want to be risk-off and have more margin of safety.","offset":1382,"duration":22},{"text":"Chamath: I think the Iran thing is kind of in there, but I think the big tactical event risk is that we have a lot of these really important financial moments tied to this concept of AGI, ASI. I don't know if you saw the OpenAI announcement on their final terms, but you know, a huge slug of Amazon's capital is tied to a 2028 IPO or a moment that calls for this.","offset":1404,"duration":27},{"text":"Chamath: Then there was a bunch of leaked text messages or whatever that said that there's a version of some AGI running inside of Anthropic. Then there was the fact that, you know, the leak of Claude code basically demonstrated that they had feature-flagged away a bunch of improvements, so if you stack up all these improvements, they're actually much further ahead than the models realized.","offset":1431,"duration":23},{"text":"Chamath: If you take all of that as a basket, it goes back to what I said last week, which is: we have a real pricing problem. If AGI is real, the durability of most companies is slim to none. If AGI is not real, then the fundraising capacity of these companies that are now raising hundreds of billions of dollars needs to get questioned and inspected thoroughly.","offset":1454,"duration":21},{"text":"Chamath: History will sort out which one is right, but both cannot be right. So in that vein, I actually think J-Cal, I don't think we're going to have like these \"quote-unquote\" blockbuster stream of IPOs. I think what happens is SpaceX is going to get out, they're going to do great. And then maybe the next one does good to great. Then the next one will do good.","offset":1475,"duration":20},{"text":"Chamath: And then the appetite runs out because you just can't absorb incrementally trillions of dollars of new demand. And if you think about it, where is it going to come from? Is it going to come from the sidelines? I don't know, I think it's more of a reallocation exercise.","offset":1495,"duration":15},{"text":"Chamath: But if you look at the S&P, while most people are now defensively moving away from these kinds of things towards the things that are more protected, what the industry calls \"Halo,\" right? High asset, low obsolescence kind of businesses. Those things trade for zero today, Jason. You can buy hundreds of millions of dollars of year of cash flow for two to five times right now in the stock market.","offset":1510,"duration":25},{"text":"Chamath: And so why are you going to go way out on the risk curve and buy something at 200 times revs, let alone earnings? Yeah, the so- I don't know, I'm more in the camp of: I think it's good to be first. It's pretty decent to be second, but if I were you, I would get the heck out and get public and get your money and fortify your balance sheet ASAP because I think the risk builds the further down the IPO chain you're in.","offset":1535,"duration":27},{"text":"Host: Yeah, there's going to be a competition for investor dollars, whether it's retail or it's institutional or sovereign wealth funds, they're going to have a lot of choices here: do you want to be in Nvidia, do you want to be in SpaceX? Maybe you have to rotate out of Amazon or Google or Disney in order to take on those opportunities, and that's going to be a great competition. Probably we could see a lot of these IPOs, Freeberg, trade below their IPO price in the year or two after they come out and get repriced, yeah? Like we've seen before.","offset":1562,"duration":32},{"text":"Freeberg: I think the market's going to need to find a price. Remember, the share owners in a lot of these companies have held on to these shares for a long period of time and the valuations are extraordinary. I mean, hundreds of billions of dollars in market value coming to market liquid for the first time. Some of these investors, regardless of whatever their entry price was, are going to be looking for liquidity.","offset":1594,"duration":22},{"text":"Freeberg: So there's only so much capital to absorb those shares on the buy-side. Meaning, if the buyers and the bid is not there to fulfill all of the selling, then you're going to see the share price decline and the market's going to find a price. And so I think this idea that like an IPO is, you know, just a step in driving the price or value of a company up is a pretty false sense, and I think we'll realize it's pretty false as some of these IPOs take place because there is so much pent-up selling demand, there is so much value that's being created, there's going to be so much selling pressure, and then there's going to be very little buying activity on some of these because anyone that could have bought at scale on the buy-side post-public were already in a lot of these companies pre-public as private companies.","offset":1616,"duration":50},{"text":"Freeberg: And so I don't know who the big buyers are that everyone's expecting are going to show up. They're probably thinking, \"Hey, it's going to be retail.\" Retail, yeah. I mean, it's like- yeah, but how much money does retail have left? I mean, if you look at retail investors, they have a certain amount of powder and it's probably deployed. It's not like they have unlimited places to look for that.","offset":1666,"duration":16},{"text":"Host: And you know, there's some evidence of this: Bloomberg ran an article on Wednesday (we tape on Thursday, folks, and you get to listen to the pod on Fridays) OpenAI is falling out of favor with secondary buyers. According to a report, OpenAI investors can't find buyers at the new $850 billion valuation that Chamath referenced earlier. Investors Bloomberg spoke to are looking to sell $600 million worth of shares. People are looking for liquidity and said they were institutional investors.","offset":1682,"duration":29},{"text":"Host: Anthropic, currently valued at $300 billion, is seeing major secondary bids at a $600 billion valuation. So I think Chamath, what this shows us is you're correct: there, you know, OpenAI and Anthropic are the two next cards, that's your turn and river, folks, if SpaceX is the flop.","offset":1711,"duration":15},{"text":"Host: And maybe they're massively overvalued right now. Maybe they're $300, $400, $500 billion companies, not trillion-dollar companies. And if you look at the amount of revenue—$24 billion for OpenAI at $852 billion, that's 35 times price-to-sales ratio, and that is a absurd price-to-sales ratio depending on if the growth keeps happening.","offset":1726,"duration":22},{"text":"Host: And as you referenced, Chamath, what if we are at Artificial General Intelligence, AGI, and the moats on these things is de minimis or or there is no moat? Anthropic just got hacked. All their secrets are out. Somebody transmuted the code into another language, posted it on GitHub, can't be stopped. I don't know if you saw that story, Freeberg, but this was kind of mind-blowing: somebody took the Anthropic code—I don't know what it was written in and then basically just put it into another language, reposted it.","offset":1748,"duration":32},{"text":"Host: If Anthropic comes and says, \"Hey, you can't do this,\" well, that negates their argument, Chamath, that they're allowed to train on other people's data and then spit out a different output. So this is a very weird moment in time, right?","offset":1780,"duration":14},{"text":"Chamath: It is. I think you're bringing up a bunch of different points, so let me just sort them out in the order that I think is important. Is there a market for OpenAI at 800 billion? Yes, and there should be. When I read that press release, my mind was blown. This is a- I've never seen a business like this. And I'd say the same thing of Anthropic.","offset":1794,"duration":23},{"text":"Chamath: What an incredible thing that both of these two companies have been able to create. Nobody in the history of the world has ever seen two businesses like this at this scale. Okay? It's unbelievable. These are trillion-dollar companies. They both are and they both deserve to be. How profitable they are, I don't know. What their terminal valuation is, I don't know. What will people pay for it at IPO? I don't know.","offset":1817,"duration":25},{"text":"Chamath: But Nick, I just shared something with you. These two companies need to get out as quickly as possible. And the reason is every single company that comes after it, all those companies that you just named, Jason, are not nearly as important and do not need the money nearly as badly as these guys do.","offset":1842,"duration":16},{"text":"Chamath: And where will it come from? The specific answer to your question when you look at this chart is: the tech sector PE is going to shrink faster, in my opinion, than the non-tech PE. And the reason is because as these companies come out, the combination of SpaceX, OpenAI, and Anthropic—all three are baking an AI technology that first and foremost will go after the tech sector.","offset":1858,"duration":28},{"text":"Chamath: It will eliminate and it will cannibalize and it will erode most of the moats that support this differential trading. So if I were a betting man, my first bet is as those three companies come out, these software businesses are going to approach the rest of the non-tech PE. Okay, that's the first step that has to happen.","offset":1886,"duration":22},{"text":"Chamath: So the rate of change of of the multiple erosion will basically say to the world, \"Hey, these tech companies are, I don't know, I'll buy the first five or six years of this story, but I'm not buying year 15 of this anymore because these three guys are going to build something.\"","offset":1908,"duration":14},{"text":"Chamath: So that's where the money comes from. That's why I think after SpaceX, these two guys need to get their act together, file quickly, get out, and just get the money, fortify their balance sheets, and be in a position. Everything that happens after that is a total coin toss because once these three companies are public, I think the blue line will converge to the orange line and it's going to be nasty.","offset":1922,"duration":24},{"text":"Host: Yeah, and Freeberg, just looking at this: do you believe that secondary market is a canary in the coal mine here with OpenAI? Because if we- and we've gone through this year after year here. These are exceptional businesses, they've grown incredibly, customers love their products, but the burn is brutal, the circular financing problem is still out there like what's reality here.","offset":1946,"duration":23},{"text":"Host: And that's going to all come out when these S1s get filed and they're publicly traded companies and they have quarterly earnings reports. Market share for these could be flipping: Anthropic and Gemini, other players coming into the market. What are your thoughts here on Anthropic and OpenAI post the SpaceX IPO?","offset":1969,"duration":19},{"text":"Freeberg: Like I said, there's only so much capital in the world. So I do think one of the things that's probably being underestimated at the moment is the liquidity crunch that's ahead for capital-intensive technology businesses given the conflict in the Middle East.","offset":1988,"duration":17},{"text":"Freeberg: I don't think that Qatar and certain Saudi offices and certain offices in UAE and Oman are as eager as they were or, you know, have been to provide large slugs of capital to support these initiatives. And remember, that capital moves its way through the markets, whether it's through JP Morgan in a loan to SoftBank which then gets paid to OpenAI. At the end of the day, there has to be unencumbered debt-free capital that's being provided to these systems from somewhere in the world.","offset":2005,"duration":36},{"text":"Freeberg: And the- if you trace all of it back, like a large chunk of it has historically in the last couple of years come from Middle East sovereigns and family offices. And I think that those are likely going to tighten up in the near term. That being the case, it's probably less demand.","offset":2041,"duration":13},{"text":"Freeberg: I do think that there's a lot of secondary demand coming from family offices in Europe and Singapore, places like that that generally have not had great access or early-stage access to private companies, but at some point there's only so much demand there.","offset":2054,"duration":11},{"text":"Freeberg: So I don't know like how far this is going to go or when this capital crunch that's going to emerge, I think from the Middle East. I don't think we've really felt the shock wave yet on what's happening because remember a lot of these Middle East capital commitments were made in the last cycle as LP commitments or whatever. And you know, if they stop, if they downscale LP commitments or they stop doing primary and secondary transactions, you know, takes a little bit of time before the market feels that and then it's like, \"Oh, the reliable go-to are gone.\"","offset":2065,"duration":25},{"text":"Freeberg: And a lot of the big funds, the the megafunds that are out there that have Middle East LPs are gone. And suddenly everyone's going to be like, \"Whoa!\" and the shock wave will hit. So let's see. It is a risk for the United States because China, I don't think, is going to be as challenged. We're so dependent on Middle East capital, it may be that China has a- a capital advantage actually going into this next phase.","offset":2090,"duration":24},{"text":"Host: Me- I mean, and we talked about force majeure could come into play here if this Iran thing spirals, God forbid, out of control or gets worse. People could say, \"You know what? We're we're going to downscale our commitments and hey, there's a war so we don't have to fund this.\"","offset":2114,"duration":14},{"text":"Chamath: I think the markets- I think the markets have shook that off, Jason. I don't think that they they view this Iran thing as a big thing. I think the big event risk in the market is: is AI real or not real? And if it's real, what are all of these companies worth? That is the big sword of Damocles over the stock market.","offset":2128,"duration":15}],"startTime":1258},{"title":"Escalating Iran Conflict & Energy Independence","summary":"The conversation shifts to the ongoing military operation in Iran, its rising financial costs, and Trump's recent national address. Chamath emphasizes the urgent need for Western nations to achieve energy independence to insulate themselves from geopolitical shocks.","entries":[{"text":"Host: Yeah. All right, well that's a good segue I think into talking uh a bit about Iran. We took the week off from it last week and we're going to catch up here this week.","offset":2143,"duration":11},{"text":"Chamath: By the way, not because we intended to, just to be clear—not because we intended to, which all the comments railed us on, but we literally—Jason did a terrible job moderating. It was on the freaking docket, we were supposed to talk about it, we didn't get to it, we went way over.","offset":2154,"duration":15},{"text":"Host: He DMV'd it. He DMV'd it, you know, like \"come back later.\" Come back next week.","offset":2169,"duration":2},{"text":"Chamath: It's it's clearly my fault.","offset":2171,"duration":2},{"text":"Host: I'm just protecting Trump. I'm out here getting cover for Trump's mistake. Yeah. Everybody knows I'm in the pocket of President Trump. You're like, \"Take a ticket, take a ticket. Oh, you have an issue? Okay, well your issue number 17.\"","offset":2173,"duration":13},{"text":"Host: Trump DM'd me and said, \"Can you please take this off the docket?\" I was like, \"You got it, boss.\" And then you're like, \"Oh, sorry, office is closed, come back tomorrow.\"","offset":2186,"duration":7},{"text":"Host: Today is day 34 of the Iran war slash military operation. Trump addressed the nation Wednesday night for a brisk 18 minutes. Here's a 40-second clip.","offset":2193,"duration":10},{"text":"Trump: We're now totally independent of the Middle East, and yet we are there to help. We don't have to be there, we don't need their oil, we don't need anything they have, but we're there to help our allies. For years everyone has said that Iran cannot have nuclear weapons, but in the end those are just words if you're not willing to take action when the time comes. Our objectives are very simple and clear: we are systematically dismantling the regime's ability to threaten America or project power outside of their borders. And tonight I'm pleased to say that these core strategic objectives are nearing completion.","offset":2203,"duration":41},{"text":"Host: All right, the costs here are mounting. War is a very serious business: 13 American service members have tragically died, over 200 have been injured. On the other side of the ledger, 3,500 Iranians have died, including 1,600 civilians and over 200 children. 1,200 people in Lebanon have died from Israeli strikes, and we now have 50,000 troops deployed to the Middle East.","offset":2244,"duration":27},{"text":"Host: Chances of a ground invasion are increasing. War has cost $70 billion so far—that's assuming $2 billion a day, which there seems to be consensus on via the Department of War. Pentagon has asked Congress for another $200 billion. To put that in context, the war in Ukraine was $113 billion in the first year. This could quickly exceed it when we hit 50 days.","offset":2271,"duration":30},{"text":"Host: This isn't cheap. There are lots of costs. Here's uh your Polymarket on a ceasefire: 25% chance of a ceasefire by the end of April, 47% chance by the end of May. The sharps are are thinking this could wrap up. But ground invasion, which would be just really impactful I think, 63% chance by the end of April, 71% chance by the end of December.","offset":2301,"duration":30},{"text":"Host: I'm going to get into the second-order effects, but what do you think, Chamath? Uh, this obviously is super unpopular war.","offset":2331,"duration":7},{"text":"Chamath: I think two things, and the President kind of alluded to one that I think is very important, which is: if you are not energy independent, you are at risk. And I don't know how many more examples now that world leaders need to be shown to get their act together.","offset":2338,"duration":17},{"text":"Chamath: So if the Ukraine-Russian conflict didn't show Europe, then this should show not just Europe but the rest of the world: you need to be in control of your own energy infrastructure and energy independence because stuff happens in the world, and you're not always in control or can shape how that stuff can indirectly or directly affect you.","offset":2355,"duration":17},{"text":"Chamath: The United States has energy independence. It's an incredible situation. What was interesting to me is if you look at Europe, you know, they gutted a couple of their energy markets and they essentially ceded control to a combination of very expensive imports and China.","offset":2372,"duration":21},{"text":"Chamath: They did that in markets like nuclear where they just went out of it. They did that in things like nat gas where—again, we can debate—but where did Nord Stream 2 go? We don't know. And they did that in things like solar, where they just gutted all of the credits.","offset":2393,"duration":14},{"text":"Chamath: But what's interesting is they're starting to turn that around. I think Italy just reintroduced effectively what's called investment tax credits, Spain just did as well, Germany is restarting nuclear. So if you just took the last few months, just that change is incredibly important because our largest ally, Europe, should be fundamentally energy independent so that they preserve complete and total optionality like we do in how we respond to these situations. That I think is a critical thing that is a positive output of what's happening.","offset":2407,"duration":37},{"text":"Chamath: And then the second, Jason, which I think is a huge question mark and it builds on what Freeberg said before: the Middle Eastern states, specifically the UAE and Saudi, Qatar, Kuwait—they are our most important financing and banking partner in the future.","offset":2444,"duration":19},{"text":"Chamath: And I think we need to see a conclusive end to this war because they need to be in a position to monetize these critical assets. Because at the same time, if you see these big pools of demand start to become energy independent by either accelerating nuclear—but again, that's problematic and slow—but frankly, they're just going to ramp up solar. That's the only way that you can dispatch energy quickly.","offset":2463,"duration":23},{"text":"Chamath: I think what that does is it decreases hydrocarbon demand over the long run. That then decreases the monetization capacity for these countries. So if you put these two things together, all of these folks in the region want safety, security, and they need a quick end to this thing now. And I think that they're more incentivized to put boots on the ground, Jason, than America is. That's the point I was trying to make.","offset":2486,"duration":22}],"startTime":2143},{"title":"Global Fertilizer Crisis & Agricultural Impact","summary":"Friedberg breaks down how the Middle East conflict and the closure of the Strait of Hormuz are disrupting the global nitrogen fertilizer supply. They discuss the cascading effects on food production, American farmers, and vulnerabilities in natural gas supply chains.","entries":[{"text":"Host: Freeberg, let's talk a little bit about fertilizer. You had brought up when we had the start of the Ukraine war, \"Hey, this is the bread basket, we could have a massive famine.\" Thankfully that was avoided, there were carve-outs for getting wheat and other crops out of Ukraine. But here we are again with a significant amount of fertilizer comes out of that region and it's not flowing right now. Do you have concerns this time around that we could see something similar?","offset":2508,"duration":35},{"text":"Freeberg: Fertilizer is made up of three elements: there's different fertilizers. The one element is N for nitrogen, P for phosphorus, and K for potassium. Ukraine is the largest producer of the K, the potassium, the potash. But the N in fertilizer is nitrogen, and that is about 60 percent of what goes into the ground. That's 60 to 65 percent of global fertilizer is the nitrogen. That's what really drives agricultural productivity. And we need nitrogen fertilizer to grow crops everywhere on Earth that we're growing crops to feed people at scale.","offset":2543,"duration":37},{"text":"Freeberg: That nitrogen is primarily made where natural gas is produced and processed. And the reason is that they use the natural gas as an input to the production process. They get the the carbon, the hydrogen, the oxygen, and then they compress—remember 70 percent of our atmosphere is made up of nitrogen gas—so they compress the nitrogen in the air to 200 times atmospheric pressure, run it over a an electrical current with a metal catalyst, and you break apart the N2 so you have just single nitrogen atoms, and then you combine it back and you end up getting ammonia out of the other end.","offset":2580,"duration":39},{"text":"Freeberg: That's why nitrogen fertilizers are produced where natural gas is processed. So the Middle East obviously is a massive producer, particularly in Qatar, of natural gas. And that's why so much of the world's nitrogen fertilizer is made in the Middle East. In fact, about 35 percent of the world's nitrogen fertilizer goes through the Strait of Hormuz. And it is then shipped to countries around the world that farm and that need it to grow their crops.","offset":2619,"duration":24},{"text":"Freeberg: The swing producer in the world is China. China historically makes about 15 percent of the world's nitrogen fertilizer. And when the war started, a few days after it began, China shut down exports of their nitrogen fertilizer. And so they basically choked out the rest of the world. And so when the Strait of Hormuz shut, the nitrogen stopped flowing.","offset":2643,"duration":19},{"text":"Freeberg: Here you can see the price spike that happened: as the war began, this is urea. Urea is the solid form of nitrogen fertilizer. So urea was trading at about 350 bucks a ton before the conflict kind of took off, and it continues to spike up. It reached over $700 a ton in the last two days.","offset":2662,"duration":20},{"text":"Freeberg: And this is really, really, really impactful. It's not just like, \"Oh, the price has doubled.\" Number one, there's a supply deficiency. So farmers in places like Africa and South Asia are not getting the urea that they need to farm. That is going to have a massive follow-on problem. And in markets where they have access, because the price has... [fades out]","offset":2682,"duration":18},{"text":"Jason: ...like in the United States, our biggest crop is corn. You need about 200 pounds of that urea per acre for corn.","offset":2700,"duration":10},{"text":"Jason: And that cost basically makes you unprofitable. There is no way you can make a profitable crop of corn. The other thing that China did at the same time is they stopped buying corn.","offset":2710,"duration":13},{"text":"Jason: So corn prices would normally spike up, and corn prices have remained low while the input prices have spiked for American farmers. So American farmers are in a real pickle.","offset":2723,"duration":14},{"text":"Jason: Fortunately for this spring planting, which is happening right now, about two-thirds of American farmers had already secured their fertilizer before this began. But a third did not.","offset":2737,"duration":13},{"text":"Jason: And they're switching crops, typically to soybeans. But we have a fall planting coming up in a couple of months here, and the choke points on production is going to keep prices very high.","offset":2750,"duration":14},{"text":"Jason: In the United States, we make a lot of our own ammonia at our natural gas facilities in places like Oklahoma and Texas and Wyoming and other places. And then it ships directly to the farms.","offset":2764,"duration":13},{"text":"Jason: But the cost is so high because of the global market that it's going to become very hard for farmers to make a profit. And around the world, there are many farmers, millions and millions of farmers, that can't access this fertilizer now.","offset":2777,"duration":14},{"text":"Jason: So the choke point in the Strait of Hormuz is turning out to be a real critical global food supply crisis yet again, similar to Ukraine. And remember there was about 400 million people, following the Ukraine war, globally, that we saw enter into a state of malnourishment.","offset":2791,"duration":19},{"text":"Jason: This means more than one year of 1,200 calories or less per day for a year. 400 million people after Ukraine. So coming out of this crisis, it could be even more severe given the criticality of nitrogen-based fertilizers and the shutdown of the Strait.","offset":2810,"duration":18},{"text":"Jason: Let me make two more points on this. You would think, okay, well we'll make more nitrogen fertilizer. The facilities take at least three to five years to fix when they break, which is what just happened in Qatar. That facility got damaged, the main facility that's being used to make fertilizer.","offset":2828,"duration":17},{"text":"Jason: So that is the largest producer of urea in the world that's now going to be incapacitated for three to five years. And if you want to build a new facility it takes about seven years.","offset":2845,"duration":13},{"text":"Jason: All the facilities around the world that make urea and ammonia, these nitrogen fertilizers, typically run 24/7/365 at full capacity. There is no downtime where you could just turn on excess production in the world.","offset":2858,"duration":15},{"text":"Jason: So, you know, the world is very delicate in its balance of inputs and food production and outputs. The whole world has like less than 30 days of food, of calories stored up.","offset":2873,"duration":12},{"text":"Jason: So as these kind of supply chain problems start to percolate, there's shockwaves that start to get felt around the world. So it's a pretty serious crisis ahead, and it'll take a few months before it'll be fully realized.","offset":2885,"duration":13},{"text":"Jason: In the meantime, US farmers are getting their asses handed to them, they can't make money. And China is using this as a moment for extraordinary leverage over America and taking advantage of the situation by shutting down exports of their fertilizer and at the same time not buying American production of corn.","offset":2898,"duration":20},{"text":"Chamath: We probably need Friedberg to have some sort of resiliency here and address this like we did with pharmaceuticals, PPE, all these other things. Yeah, we should have some sort of stockpile of fertilizer.","offset":2918,"duration":14},{"text":"Jason: To Chamath’s point is absolutely correct. Natural gas reservoirs exist around the world, and we've been loathe to exploit them or develop them because of the climate change carbon risks and issues.","offset":2932,"duration":15},{"text":"Jason: But I think what we're realizing is that those are luxury beliefs to an extent. You can only say let's not exploit carbon resources until you hit a shockwave like this and then people are like, wait a second, we really do need to have these systems up and running, and we need to have excess capacity and local capacity in the system.","offset":2947,"duration":19},{"text":"Jason: Because single points of failure for the whole world's food supply is not going to cut it anymore, particularly as the world is becoming more fragmented and multipolar and there's less US policing of the world that's going to happen, and so on.","offset":2966,"duration":14},{"text":"Jason: It's going to be very critical that everyone starts to think about doubling down not just on energy production, but some of these other critical inputs like fertilizer. And another output, just as a quick side story on nat gas production, is when you pull nat gas out of the ground, that's the primary place we find helium.","offset":2980,"duration":20},{"text":"Jason: And helium, we're all waking up to the fact, you know, we never really think about helium, we think about kids' balloons at birthday parties. But helium goes into MRI machines, helium goes into semiconductor manufacturing, helium goes into mass spec machines that are used in chemical analysis with a lot of applications around the world.","offset":3000,"duration":18},{"text":"Jason: Helium is a critical input to medical equipment, to manufacturing equipment, and all of a sudden a third of the world's helium coming out of Qatar is not making it out. And so we're now going to have a helium supply shock that's going to affect the world.","offset":3018,"duration":15},{"text":"Jason: So we're starting to wake up to the fact that perhaps these nat gas fields that we've allowed to kind of turn a blind eye and say let one country exploit them and let them make all the nat gas—the US is actively developing.","offset":3033,"duration":14},{"text":"Jason: You know, I went down and visited that Cheniere facility in Louisiana with Doug Burgum a couple months ago, which was an amazing site to see where we do all the LNG exporting. But the US has extraordinary nat gas reserves, so do many other places in the world that have failed to take advantage of developing them. And I think we're realizing the criticality of doing so at this moment.","offset":3047,"duration":22}],"startTime":2508},{"title":"Trump's Approval Ratings & Iran Conflict Fallout","summary":"The hosts review Trump's plummeting approval ratings and speculate on the political consequences of the Iran conflict ahead of the midterms. They debate the strategic motivations behind the military strikes, concluding with a humorous tangent on a viral internet video.","entries":[{"text":"JCal: Looking at this, I think we'll have Trump pivot extremely soon. I've brought this chart up now. This will be the fourth time I've brought it up.","offset":3069,"duration":8},{"text":"Jason: Is that your prediction JCal? You think he's going to wrap this up?","offset":3077,"duration":4},{"text":"JCal: He's 100% going to wrap this up and I can show why. I mean, just basically look at the history of this. You guys remember I brought up this chart with Trump's net approval rating.","offset":3081,"duration":12},{"text":"JCal: And you look at how this has changed over the three times I brought it up. First time in June last year, then October, and again I'm going to bring it up here.","offset":3093,"duration":11},{"text":"JCal: The stuff with ICE, the, you know, the Epstein files, and just going right down the line of unpopular decisions. Trump's net approval rating now has just plummeted to negative 17. This is the least popular he's ever been.","offset":3104,"duration":15},{"text":"JCal: And he's had to pivot here. Pam Bondi, at the time we are recording this as I predicted on a previous episode that Kristi Noem and Pam Bondi would be fired or, in I guess Trump's terms, he likes to get them a new job and give them a window seat.","offset":3119,"duration":17},{"text":"JCal: This is absolutely going to result in a quick pivot. Who knows what the downstream effects are, but the inflation three handle is coming back. According to PolyMarket, gas is over $4 a gallon.","offset":3136,"duration":12},{"text":"JCal: And then, you know, it's easy to mock like we did earlier these no-kings protests. But 8 million people came out for that. That's a large number.","offset":3148,"duration":10},{"text":"JCal: And if you look at the PolyMarket for what's going to happen in the midterms, 51% chance now that the Dems take the Senate, 86% that they take the House. And, you know, what you're going to take from that is...","offset":3158,"duration":13},{"text":"Chamath: Wait, sorry, PolyMarket is now showing the Democrats winning both houses?","offset":3171,"duration":5},{"text":"JCal: Yeah, pull it up Nick. Significant chance of that. And you know when this happens...","offset":3176,"duration":5},{"text":"Chamath: How much money is being bet on that? Let's just see. 51% they take the Senate, 86% they take the House, and four and a half million volume.","offset":3181,"duration":10},{"text":"Chamath: There's four and a half million dollars on this? Oh gosh.","offset":3191,"duration":4},{"text":"JCal: I tend to filter how seriously I take PolyMarket just based on the total quantum. But this is a big number.","offset":3195,"duration":8},{"text":"JCal: Yeah, and, you know, listen, this is not me trying to dunk on Trump and my personal beliefs. I think when you lose Tucker, when you lose Megyn Kelly, when you lose Joe Rogan, you know, and people are looking at who Trump's surrounded with.","offset":3203,"duration":17},{"text":"JCal: There's really just two groups. You have these super highly qualified people, Bessent, Lutnick, obviously David Sacks. You got really highly qualified people, JD, you know, who I think the world of. I think these people are great.","offset":3220,"duration":17},{"text":"JCal: But then he puts some people in positions that I think weren't up to the task. Pam Bondi, Kristi, I'll put Stephen Miller and Kash in that as well, it’s my personal belief in that case.","offset":3237,"duration":14},{"text":"JCal: And those people have not served him well. And they need to get this presidency back on track because what's going to happen is we're going to have two more years of impeachments and investigations and the whole thing's going to be derided.","offset":3251,"duration":15},{"text":"JCal: And we really need to start thinking about what who's making these decisions. Who made this decision to go into Iran and why? Who made these decisions to have ICE go into Minnesota and why?","offset":3266,"duration":13},{"text":"JCal: And I think a lot of it goes back to Stephen Miller. I got mocked a bit here on the pod for blaming him, but you can correlate Stephen Miller, Kristi Noem, Kash Patel, and Pam Bondi with all of the downside of this presidency and the plummeting ratings.","offset":3279,"duration":16},{"text":"JCal: Trump's going to need to clear house. He's cleared out two of four. I predict he'll clear out the other two and get great leadership in there and turn this presidency around because, listen, this is going to be socialism now, and AOC's going to win.","offset":3295,"duration":14},{"text":"JCal: This is going to cause massive chaos if he doesn't get out of Iran and do it soon. Just my handicapping of the situation. Hegseth, I'm not so sure. I'm not sure if I, you know, what I think of him yet.","offset":3309,"duration":12},{"text":"JCal: But, you know, we don't have information on why Trump did this. That's going to be the next shoe to drop.","offset":3321,"duration":6},{"text":"Jason: On why he did it? Friedberg, I think, you know, this is the point I made the second this war happened or military operation—I mean, let's call it what it is, this is a war. When you kill the top 100 people, it's a war.","offset":3327,"duration":13},{"text":"Jason: I said, I don't have the information of why he did this. Like, he might have information, Friedberg, that we don't have that made this an absolute must for us to do.","offset":3340,"duration":9},{"text":"Jason: But we haven't revealed that information. He hasn't explained it well to the American people. I think that's why the ratings are—and I don't want to make the ratings like a TV ratings—his popularity's getting crushed.","offset":3349,"duration":13},{"text":"Jason: The way this was explained to Americans, and again, I'm not inserting my position here, I'm just talking about the disconnect right now, is that Operation Midnight Hammer was supposed to have just decimated this.","offset":3362,"duration":13},{"text":"Jason: So why did we do this again? And we don't have the information. This is why I try to stay humble in this and say like, what information does Trump have that we don't have?","offset":3375,"duration":11},{"text":"Jason: Some people seem to think, Chamath, this was overconfidence, there's obviously this debate, did we get baited into this by Israel and get pushed into it and is he a Manchurian candidate etc.?","offset":3386,"duration":13},{"text":"Jason: That's above my pay grade too. I don't have any information on that. I'm not in the CIA.","offset":3399,"duration":6},{"text":"Jason: It's hard to be an armchair critic on this stuff in both senses. Like, I think it's hard to say, hey, this guy got talked into doing this, Israel manipulated him into it. It's easy to say that.","offset":3405,"duration":11},{"text":"Jason: It's also easy to say, hey, we should go get rid of the country that's made all the nuclear weapons. Both of those are easy to say without all of the texture of the relationships and the details and what really went on. None of us know shit, is the truth.","offset":3416,"duration":14},{"text":"JCal: That's literally the point I've been trying to make here. Same thing with Venezuela, like how do we know, we don't have any intelligence, Chamath, we're not in the CIA, we don't have any of these insights that Mossad or the Israeli intelligence services has.","offset":3430,"duration":16},{"text":"JCal: How do we know how this was going to go down? And, you know, that's all going to come out I think when this all gets investigated. Yeah.","offset":3446,"duration":8},{"text":"Chamath: I think Trump is and has been the most consistent anti-war president of modern history. Yes.","offset":3454,"duration":10},{"text":"Chamath: And I think that it's fair to say that he has and has had and has demonstrated enormous restraint and has the highest bar thus far of folks for actually getting into conflict.","offset":3464,"duration":13},{"text":"Chamath: So I do think that what Friedberg says is very important. There's just so much we don't know and I think that he doesn't want to stain his legacy with a typical American, you know...","offset":3477,"duration":15},{"text":"Jason: Forever war. Yeah.","offset":3492,"duration":2},{"text":"Chamath: He doesn't want that. I don't think he needs to be anywhere near that. So there is obviously stuff that we don't know.","offset":3494,"duration":8},{"text":"Chamath: I still think that there's a short-term problem, which is not just the threat that Iran poses to Israel, but there's a threat that Iran poses to the rest of the Middle Eastern community.","offset":3502,"duration":12},{"text":"Chamath: That neighborhood is a complicated place. There was an interview that MBS did on Saudi television, Nick maybe you can find it. It's in Arabic but there's a good version of it that I saw with subtitles.","offset":3514,"duration":15},{"text":"Chamath: And if you hear MBS's telling of what the Iranian threat is, it's not dissimilar to how the Israelis would characterize the threat. And so I think it's important to understand that unpredictable actors should not be given an opportunity to have a cataclysmic weapon that can just completely destroy the earth as we know it.","offset":3529,"duration":21},{"text":"Chamath: That just doesn't make sense. And I think if you can intervene to prevent that, we're now aware of the damages of what this can do to enough of a degree where there should be enough of nuclear disarmament from here on out.","offset":3550,"duration":14},{"text":"Chamath: The six, seven, eight, nine countries that have it, okay. There's all kinds of reasons why maybe we could have remade those decisions over the intervening 70 years. Maybe there's some that we never should have let have it, the Pakistan-India thing is a good example of one.","offset":3564,"duration":15},{"text":"Chamath: But we are where we are, and I think we can all agree no more country should incrementally get access to this thing. Absolutely not.","offset":3579,"duration":9},{"text":"JCal: And this regime specifically believes that anybody who is not part of this specific religion needs to die, and the whole world...","offset":3588,"duration":10},{"text":"Chamath: Well, the world of Islam needs to be reunited in order to take on anybody who's not part of their version of radical Islam.","offset":3598,"duration":10},{"text":"Chamath: Like it’s a religious lunacy in that country that I think everybody else should be murdered if they don't convert.","offset":3608,"duration":7},{"text":"Chamath: I think it's important to say that the overwhelming majority of Sunnis and the overwhelming majority of Shiites are peaceful observant people. Yes. There are fringes in every religion.","offset":3615,"duration":11},{"text":"Chamath: And specifically this, I think the most important thing is to not take your word or anybody else's word. I do think it's important to listen to somebody like MBS because I think it's the lived experience of having to run a country in that neighborhood and what it means.","offset":3626,"duration":15},{"text":"Chamath: And I think what you see is as you're articulating many layers of complexity that again I think that most of us in the West have zero appreciation for. All of this goes to in the short term I think that they've forced themselves into a corner.","offset":3641,"duration":18},{"text":"Chamath: I think we can go back and relitigate why did Obama let them out? That was a really, really stupid idea. We probably should have kept our thumb on the scale and had them close to teetering on economic insolvency. That's the only thing that has kept them in check.","offset":3659,"duration":15},{"text":"Chamath: They veered wildly away the minute we let them out of the disarmament agreements that we had. But we are where we are, we gotta put the genie back in the bottle and we cannot look to other countries and tolerate this idea that they also want to build the kinds of weapons that can literally destroy the face of the planet as we know it.","offset":3674,"duration":21},{"text":"Chamath: It's a non-starter. And then the second-order effect is how do we make sure that folks that are participating in all of this broader seeds of sowing chaos, how do we hem them in?","offset":3695,"duration":15},{"text":"Chamath: And how do we create a more reasonable world order? And I think that the second-order effects and I've said this before kind of bring this back to China.","offset":3710,"duration":10},{"text":"Chamath: And I think a world where it's bipolar, where it's the United States and China roughly as the two leading statesmen of the world is probably the Nash equilibrium here.","offset":3720,"duration":11},{"text":"Jason: So I think getting China in a position where they need to do a deal. And remember I said this, the worst thing that could happen for China was the president delaying the summit and here we are, now it's delayed for six weeks, it's going to go into mid-May.","offset":3731,"duration":16},{"text":"Jason: If you think the Strait of Hormuz numbers as it relates to energy prices in Europe or anywhere else are crazy, look at what's happening inside of China right now. It is a no-bueno situation.","offset":3747,"duration":14},{"text":"Jason: And so in May if we can re-establish a set of operating criteria that keeps normalcy in check, no more of this rapid random expansion everywhere where the Chinese are trying to build bases near us and now we have to have a point of view near them. We don't need any of that.","offset":3761,"duration":18},{"text":"Jason: So I think if we can use this as an opportunity to de-escalate I think we should.","offset":3779,"duration":5},{"text":"JCal: Yeah. We seem to have moved from, I mean I think this is the question, there's a doctrine, I don't know if you guys heard this one before, of Mowing the Lawn.","offset":3784,"duration":9},{"text":"JCal: Which is the Israelis' view of Hezbollah, Hamas, and even Iran which is just, hey, we have to take away their progress, the last 30 or 40% of their progress towards nuclear bombs and we just do that consistently and we contain them.","offset":3793,"duration":13},{"text":"JCal: This has tipped over into regime change, and so I think that's the wild card that none of us can predict what happens from this point forward.","offset":3806,"duration":10},{"text":"JCal: I don't know how you leave Iran in this state if they're going to take over the Strait and charge everybody a dollar a barrel, is that going to be tenable? Are they going to keep blowing stuff up? This is uncharted territory and very high stakes.","offset":3816,"duration":16},{"text":"JCal: President Trump also reiterated the US doesn't need Middle East oil and that Europeans should go straight to the Strait and just take it. He said that the Strait will open naturally because, quote...","offset":3832,"duration":11},{"text":"Chamath: Why do we always focus on the Straits of Hormuz Jason? I'm focused on the Strait? I think you're over-focused on the Strait. I think you're always over-looking the gays of Hormuz as an example.","offset":3843,"duration":11},{"text":"JCal: That's true, and the non-binaries of Hormuz. They all count.","offset":3854,"duration":6},{"text":"Chamath: Well why is it all about the Straits of Hormuz all the time with you? Well, listen, I don't want to get canceled here because I'm talking about—I don't know the pronouns to use for these straits of Hormuz but yes.","offset":3860,"duration":11},{"text":"JCal: The Straits in Hormuz... I don't think you're allowed to be gay in Hormuz. I think you have to keep that pretty quiet there, don't you? That was the greatest clip ever.","offset":3871,"duration":10},{"text":"JCal: If you don't know what we're referring to it’s a viral clip. It’s incredible.","offset":3881,"duration":6},{"text":"JCal: Purple-haired people... no, not purple-haired, this was a young Indian lady. And we all thought the same thing, Indians are so smart, what happened to her? What happened?","offset":3887,"duration":13},{"text":"Jason: She's... they found an Indian who didn't understand the question. They found the one dumb Indian. They found her.","offset":3900,"duration":13},{"text":"Jason: This was... she's been absolutely... I mean, isn't it a little bit homophobic that it was so focused on just the straits of Hormuz and not the gays of Hormuz? Yes, I agree. Yeah, for sure.","offset":3913,"duration":9},{"text":"Jason: Is that why you're choosing to leave the gays of Hormuz behind? I think it's just history.","offset":3922,"duration":5},{"text":"Jason: Which Ivy League do you think she went to? Brown. 100%, Brown or Columbia. Oh yeah, that's a good call. I would say Columbia. She, yeah, she might have gone to Vassar actually. I think that might have been her safety school.","offset":3927,"duration":14},{"text":"Jason: That's the best, not Borat, Bruno impersonation I've heard in a long time. So, Friedberg, why are you so gay? Do you think the strait of... are you making your potatoes non-binary?","offset":3941,"duration":17}],"startTime":3069},{"title":"Quantum Computing's Threat to Bitcoin","summary":"Chamath warns that quantum computing advancements could break modern encryption standards within five to seven years. The group discusses the immediate need for the crypto community to transition to quantum-resistant architectures to protect their networks.","entries":[{"text":"Jason: It was like literally Bruno. You got 10 minutes Chamath, you want to do your Bitcoin thing or you want to just break?","offset":3958,"duration":10},{"text":"Chamath: The Bitcoin thing was interesting because I think in the last couple of months what we've started to see is an increasing amount of research that says that the scheduled eventuality of a quantum chip, a functional chip, is probably not 25 or 30 years away. It's probably now in the next five to seven years if I had to guess.","offset":3968,"duration":28},{"text":"Chamath: And I think that because that event horizon has moved in, in these next five to seven years, for those that follow Bitcoin and care about it, my only advice on this topic is that the leaders of the Bitcoin ecosystem need to organize themselves and need to make sure that they have an answer to the question of is this stuff quantum resistant?","offset":3996,"duration":25},{"text":"Chamath: Because if the answer is no, they are a very visible and obvious honeypot. Now there is the answer that then a lot of the Bitcoin community gives which is, well everything is screwed.","offset":4021,"duration":14},{"text":"Chamath: And my only advice is, possibly. But if a non-state actor gets a hold of quantum technology that can defeat crypto as we know it today, SHA-256, you know, ECDSA like the elliptical curve stuff, the run-of-the-mill stuff that we all rely on.","offset":4035,"duration":19},{"text":"Chamath: A non-state actor's incentive will first be to drain the obvious honeypots and then tell everybody that it's broken so that then everything goes to shit, all the prices go to zero, and then they have all the money and then they can buy stuff.","offset":4054,"duration":14},{"text":"Chamath: That would be the sequence of events if you were a non-state actor. So, yes you're right, the banks get hacked, yes you're right all this other stuff goes kaput, but I think you first go and you exploit the obvious places and I think crypto is the most obvious honeypot in a world where you can defeat encryption.","offset":4068,"duration":17},{"text":"Chamath: Now, in fairness, the crypto community, this was much, much earlier, had to deal with this, they had to migrate from different encryption schemes in the early parts of Bitcoin and they were able to self-organize.","offset":4085,"duration":13},{"text":"Chamath: The difficulty here is you're talking about a big technological lift. You're talking about all the wallets being re-architected, you're talking about all the transactional flows, all the processing nodes. These are complicated things that need to happen.","offset":4098,"duration":13},{"text":"Chamath: And I would just tell the crypto community you have five to seven years to get your shit in order. That's it.","offset":4111,"duration":6},{"text":"Friedberg: Quantum computing just generally speaking, you feel it's going to have a major impact in the short term? Do you think it's actually going to become viable in the midterm? Where do you think about it? Because it's always been 10 years out, but it feels like we're making some progress.","offset":4117,"duration":15},{"text":"Jason: Well, it's... yeah, there's a lot that's changed. I mean, so the primary mechanism of modern encryption standards relates to factoring primes of an integer, discovering the prime factors of an integer would give you the ability to theoretically crack encryption.","offset":4132,"duration":20},{"text":"Jason: There was an algorithm that was theorized by a guy named Peter Shor. I think I talked about this on a prior episode back in 1994 called Shor's algorithm.","offset":4152,"duration":8},{"text":"Jason: Today it's kind of the commonly well-known model for how you could do this and it's a... you could watch a YouTube video on it. There's some YouTube videos that explain it pretty clearly, takes a bit of time to understand it.","offset":4160,"duration":11},{"text":"Jason: And then a couple years ago, I think in 2023, there was another computer scientist named Oded Regev from NYU who published another paper that showed a faster different approach to Shor's algorithm.","offset":4171,"duration":12},{"text":"Jason: It was an improvement on Shor's algorithm that basically reduced the number of quantum operations required to factor a large integer significantly.","offset":4183,"duration":11},{"text":"Jason: We went from 28 million of those operations down to 500,000. Yeah, and so there's this a lot of work going on right now, even before we have industrial-scale quantum computers.","offset":4194,"duration":10},{"text":"Jason: A lot of work going on in quantum computing theory and building models and algorithms, a lot of this is rooted in pure mathematics and statistics and whatnot. That work is making progress in building better algorithms even before the compute comes online.","offset":4204,"duration":15},{"text":"Jason: And then there's this separate set of things that you can track but, you know, the market if you want to trust the market is betting that we are within spitting distance of quantum computers reaching an industrial scale at this moment.","offset":4219,"duration":14},{"text":"Jason: So those two things intersect at some moment in the near term where you have algorithms that are low demand, low latency, that can crack modern encryption standards and then the compute comes online and someone is going to execute.","offset":4233,"duration":19},{"text":"Jason: The real thing is what do you do about it? There's a whole bunch of research that's been going on for 20 plus years on quantum algorithms, quantum encryption standards.","offset":4252,"duration":11},{"text":"Jason: And so to Chamath's point, these things exist, it's just a heavy lift and so there's going to be this heavy lift, probably, you know, pretty good business to be made in the next couple of years in all of the changes that are going to need to happen across all encryption standards across the whole internet, across how we do communications and so on.","offset":4263,"duration":16},{"text":"Jason: In a crazy way, Friedberg, crypto's in the same place as all these software stocks, meaning if AGI and ASI are real, these software companies are not what we thought they were. Yeah.","offset":4279,"duration":12},{"text":"Jason: If quantum is real, a bunch of these crypto projects are not what we thought they were. And so you can't have both, guys. You gotta choose. Pick one. Yeah.","offset":4291,"duration":10}],"startTime":3958},{"title":"Outsourced Executive Assistants via Athena","summary":"The hosts share their positive experiences using Athena to hire highly capable executive assistants from the Philippines. They reflect on the rising costs of administrative support in the US and how global talent is reshaping personal productivity.","entries":[{"text":"Jason: All right everybody, this has been... Oh hey we listen, you know I have an incredible EA? Executive Assistant.","offset":4301,"duration":8},{"text":"Chamath: It's really been like, you know, everybody talks about like agents, agents, agents, agents and this was the pre-agent agent. You know my EA's averaged around 188 to 200k a year and...","offset":4309,"duration":16},{"text":"JCal: People right now their heads are exploding in middle America.","offset":4325,"duration":4},{"text":"Chamath: Plus the truth I was paying 188 to 200,000 dollars a year. They were wonderful, okay.","offset":4329,"duration":6},{"text":"Chamath: And then JCal was like, try this thing called Athena, Athena, Athena. I'm like what is it? So I called the guys and they're like, yeah, we have these really well-trained folks, they're like geniuses that work in the Philippines. It's 3,000 a month and we're building all this tooling.","offset":4335,"duration":14},{"text":"Chamath: And so as all these agents get better and all these AI's get better, they'll get the advantage of that. I said, okay, I'll give it a try. This is the first time I've had a male assistant. His name is Lei.","offset":4349,"duration":9},{"text":"Chamath: Lei's fabulous. He's a math grad, math and computer science in the Philippines, okay. And he's excellent. I love Lei too, somebody just put it in the chat, I love Lei. From Nick. Nick, do you love Lei?","offset":4358,"duration":13},{"text":"JCal: I love Lei, coming to NBC this fall. These guys are incredible. They do everything for me. It's like the most incredible hack and arbitrage I've ever seen.","offset":4371,"duration":12},{"text":"JCal: Then now then I can direct a bonus to Lei at the end of the year which is great because then it allows me to feel like I'm giving him really, you know, good support. He works my hours from the Philippines, have not looked back.","offset":4383,"duration":11},{"text":"JCal: Go Athena. That's great. I used it as well. I was the first investor.","offset":4394,"duration":6},{"text":"Chamath: You were the first? You were the first? How many Athena's you have, one or two? I have one.","offset":4400,"duration":4},{"text":"JCal: I had two for a long time. I think I might get a second one. And then that person moved on. You split it between like work and personal or no?","offset":4404,"duration":7},{"text":"JCal: Yeah, it's work and personal. As an example, like there's an incredible bakery where I live, like out in Dripping Springs, called Abbey Jane Bakery. They don't take orders.","offset":4411,"duration":10},{"text":"JCal: But every Thursday, my Athena assistant calls at 8:00 AM, asks them what's on the menu because they change the menu every week. And then they send me the menu, I order the bakeries, and then he calls an Uber courier to pick it up and drop it off because they're not on DoorDash or Uber Eats.","offset":4421,"duration":19},{"text":"JCal: It's just a stupid example of something that made our lives incredible to have the best bakery in all of Austin in the house every weekend for the girls and everything. Everyday problems, yeah everyday problems.","offset":4440,"duration":11},{"text":"JCal: Anyway, it's a silly example, but I was having to go make that run and I did it every like fourth or fifth week as a treat. Now it's every week.","offset":4451,"duration":8},{"text":"JCal: So you just look at what you're doing. The other thing we're doing is they've been able to—we had Americans who were researchers sorting through the inbound applications from founders.","offset":4459,"duration":12},{"text":"JCal: We were able to put an Athena assistant on that and then define it and then they're learning how to use OpenCloak. So the Athena OpenCloak merger is kind of happening in real time.","offset":4471,"duration":9},{"text":"Chamath: Yeah, no, I have Lei doing a bunch of advanced tasks that I typically wouldn't give to my EA. And then he also deals with sort of just the more practical day-to-day tasks scheduling all that stuff.","offset":4480,"duration":12},{"text":"Chamath: Anyways, it's been an incredible eye-opening thing because it sets a very good example where, you know, you can be cost-effective and still get your work done. And it was really bothering me actually because like the amount of cost inflation for that role because I don't think I've ever needed an EA.","offset":4492,"duration":14},{"text":"Chamath: I'll just be honest, I'm going to put it out there. I think I've always needed an AA. And I would title them differently and sometimes I would call, you know, the... I mean, I've said this before, but like even like roles like Chief of Staff, they just don't make sense. Like the Chief of Staff should be the second most powerful person in the world because they work for the President of the United States.","offset":4506,"duration":22},{"text":"Chamath: Everybody else should not have a Chief of Staff in my opinion, okay. It's a major unlock and the problem is we have the lowest unemployment of our lifetimes and it's just people don't want to take the EA or the administrative assistant position in America. They just don't.","offset":4528,"duration":15},{"text":"Chamath: They want to do something higher up the stack but the people in the Philippines, you know, they do want that job. Lei's crushing. I love Lei. RJ's my guy.","offset":4543,"duration":9},{"text":"JCal: And yeah, first time... You got a guy too? I got a guy too and he is also very technical. So anyway, shout out to Athena. Shout out to Athena. Thank you guys, thank you Athena.","offset":4552,"duration":11}],"startTime":4301},{"title":"Ohalo Potatoes & High-Stakes Poker Stories","summary":"Friedberg provides a quick update on shipping Ohalo potato seeds to farmers across North America. Jason then recounts a recent high-stakes poker game featuring Phil Hellmuth and a notable dirt farmer.","entries":[{"text":"JCal: Friedberg, I know you're making great progress. You showed me some pictures of potatoes from Ohalo. How's that going?","offset":4563,"duration":10},{"text":"Friedberg: Just shipping seed this week to farmers all over North America, so we're getting going. Are you sending seed to our friend Roger the dirt farmer? He is, his son, yeah.","offset":4573,"duration":9},{"text":"JCal: Oh that's so great. Dirt Roger? I love him. Roger the dirt farmer's a phenomenal poker player, he and Keating often play in the game together. Ah.","offset":4582,"duration":10},{"text":"JCal: How'd they do? A couple weeks ago they came up. They came and visited me the next day. Both of those two goofballs ran over the game. It's so frustrating. It's frustrating playing with Keating.","offset":4592,"duration":11},{"text":"JCal: Roger is much more of a tag, you know, a tight-aggressive player, so it's no picnic. There's no free lunch when both of those two guys are in the game. And then on top of that, you know, Helmuth, Kuhn, Roble, it’s like it’s not a winning game. It's murder's row.","offset":4603,"duration":13},{"text":"JCal: I got... I made a late trip to the valley. I'm like, hey, Chamath, I'm in town, I get to play. Chamath's like, uh I got some bad news for you. You're no longer on the list and I filled the game up plus two.","offset":4616,"duration":14},{"text":"JCal: So I squeak into the game. I've run up a quick 20, 25 dime-skies and then Helmuth, passive-aggressive Helmuth, who cannot handle the fact that I'm more famous than him now. It's just totally tweaked him that Chamath and I and you, Friedberg, are so much more famous than him.","offset":4630,"duration":13},{"text":"JCal: It's broken his brain. He says like, uh okay, a car dealer, car dealer you're supposed to have a seat and JCal doesn't. And I literally just doubled up at that point and Chamath's like, okay I guess you can book the win, JCal, because you know it's like poor taste to double up and then leave.","offset":4643,"duration":17},{"text":"Chamath: How much did you win, 40, 50k? It was only like 25 dimes. It was, you know, like a used Model Y, yeah yeah.","offset":4660,"duration":9}],"startTime":4563},{"title":"All-In Summit Events & Closing Banter","summary":"The hosts plug their upcoming sold-out Liquidity event and detail an Ira Sohn-style pitch competition. The episode wraps up with a discussion on distributed computing projects like Tao and some lighthearted banter about internet culture.","entries":[{"text":"JCal: Hey, Chamath, we're here at the end of the show. I just wanted to make sure people know that the liquidity event that we're hosting, you can go to all-in.com/events has sold out and we've started a waitlist.","offset":4669,"duration":12},{"text":"Chamath: So this is the quickest we've ever sold out. I asked Kimber and Lisa to try to find another 100 seats. I think there's like 7.7 trillion dollars of money that want to attend. We can't get everybody in, so we're trying to get everybody together.","offset":4681,"duration":15},{"text":"Chamath: We announced Bill Ackman and Andrej Karpathy last week. Incredible. We're going to do an Ira Sohn-like pitch competition. There's like four whiz-bang hot fund managers.","offset":4696,"duration":13},{"text":"JCal: Can you explain what that is for folks who don't know? Yeah. I know a bunch of these guys but four of them in particular are running super hot right now, like taking in 50 million, run it up to a billion to three billion.","offset":4709,"duration":9},{"text":"Chamath: They're just ripping. And they're going to go on stage and they're going to give us their best ideas pitch and the three of us plus I think as many of the guests that can do it will vote.","offset":4718,"duration":12},{"text":"Chamath: And then maybe we can even publish these ideas so that folks can try to follow them. They can vet them, right? It’s a real brave thing to do to get on stage and say, hey, I'm making this bet.","offset":4730,"duration":9},{"text":"JCal: Like how's that? I did it four times. I mean, I just spanked it but hopefully these guys can do the same thing. But listen, we have a natural resources pitch, we have something in healthcare, we have something in tech, we have something in crypto.","offset":4739,"duration":13},{"text":"Jason: Genius. It's great. It's like all the big categories. We have something in crypto, so it's you're going to get every shade of every whippy big alpha market.","offset":4752,"duration":10},{"text":"JCal: By the way, you created a bit of a storm on the interwebs with your Tao mention in the Jensen interview.","offset":4762,"duration":8},{"text":"Chamath: I just asked Jensen a question, I'm not long Tao. He'd redirected it to something which is Folding at Home which I think if you don't know it you should look it up but it's how you can allocate compute to helping solve health problems.","offset":4770,"duration":13},{"text":"Chamath: The point is these open-source projects or these distributed compute projects are the future. The real question is what is the architecture and the incentives? None of us knows that.","offset":4783,"duration":11},{"text":"Chamath: Yeah. But man I think it's so important. And then all these goons went crazy. Well, I mean, the reason is because I did a piece of that on Tao like a couple of weeks ago I went public with, hey yeah I've got a small bet here because I think these subnets are fascinating and distributed computing.","offset":4794,"duration":15},{"text":"Jason: You're a Tao maxi? Your Tao maxi? I mean I'm not Tao, I mean it's like I might be 500, 600 thousand dollars, a tiny bet. You're syndicate maxi.","offset":4809,"duration":8},{"text":"Jason: No, I did it myself. I did it myself. I made a small bet on Tao because I watched exactly... This retard is syndicate maxi. I'm not... it's not... I'm not retard maxi here.","offset":4817,"duration":8},{"text":"Jason: But I am certainly not doing any introspection, I am just doing deals on great founders and companies.","offset":4825,"duration":5},{"text":"Chamath: Okay. Andreessen has been rage tweeting about this guy that he watches. Oh so great. A genius. Who posts these videos about retard maxing. Yes.","offset":4830,"duration":9},{"text":"Chamath: I watched the video, it's incredible. This guy is... What is the guy's name I don't know what the guy's name is.","offset":4839,"duration":6},{"text":"Jason: I don't know, but he goes on his back deck, he's got a Weber grill, smoking a cigar, he pops out a cigar and he says, listen it doesn't matter, just go to work and enjoy your life.","offset":4845,"duration":8},{"text":"Jason: That may be the most incredible interwebs contribution Andreessen may be making to culture and society in America, not the browser, he found this guy. I encourage you, Nick, find the video please, post the links.","offset":4853,"duration":12},{"text":"Jason: This guy is incredible. Because you're overthinking it folks, just enjoy your life. Oh my god he’s so good. He’s so good. and work hard and don't think it through because look what happened to Friedberg, he starts ruminating.","offset":4865,"duration":11},{"text":"Jason: I gotta sell software. Love you boys. Don't ruminate, just go sell software and go make better potatoes, Friedberg. No more ruminating and therapy for you Friedberg.","offset":4876,"duration":8},{"text":"JCal: Come on the program anytime Marc Andreessen. Go retard max with us here on the All-In pod. Love you boys. Bye bye.","offset":4884,"duration":15}],"startTime":4669}],"entries":[{"text":"Host: All right, everybody, welcome back to the number one podcast in the world, the All-In Podcast. David Sacks couldn't make it this week, but we have the trio: David Freeberg is here, your Sultan of Science; Chamath Palihapitiya.","offset":0,"duration":13},{"text":"Host: SpaceX filed confidentially to go public on April 1st, targeting a $1.75 trillion (with a T) valuation. When SpaceX goes public, if it's at that $1.75 trillion valuation—so weird to say trillion-dollar valuation for an IPO—they would be the eighth largest company in the world right behind TSMC and Saudi Aramco; they're both worth 1.7x at the taping of this podcast.","offset":13,"duration":31},{"text":"Host: Tesla is number 10 with a $1.37 trillion valuation. Hey, if you were to combine those two, as many people are speculating will happen at some point and you can buy the stock ticker ELON, that would be a $3.1 trillion company and that would make them the fourth largest company ahead of Microsoft.","offset":44,"duration":18},{"text":"Host: They're aiming to raise, Chamath, $75 billion, which would be by far the biggest raise ever in an IPO. Uh, expected to go out in June. I think they were trying to hit the 4/20 date because that would have been even more hilarious, but uh, they're not going to be able to do that.","offset":62,"duration":15},{"text":"Host: SpaceX uh, recently acquired X.ai for $250 billion. That includes X and Twitter and the X.ai large language model AI company. Starlink, generating between 50 and 80 percent of SpaceX's revenue. We'll have all those details shortly. Um, and it'll be close to $20 billion a year according to reports. Launch of rockets is the other 40 percent of the business, $5 billion in 2024 according to reports.","offset":77,"duration":25},{"text":"Host: Total revenue 2025: $15 to $16 billion with $8 billion in profit according to Reuters. So let's stop there. Uh, and we're going to talk about all the other IPOs that could be coming. Chamath, I think people really want to know—and you may have mentioned this on an earlier episode—what are the chances that Tesla and SpaceX could wind up being the same company? We saw they're collaborating on a fab...","offset":102,"duration":26},{"text":"Chamath: 100 percent.","offset":128,"duration":1},{"text":"Host: 100 percent is what you're putting it on? Okay.","offset":129,"duration":2},{"text":"Chamath: Okay, sorry. Let me—let me be clear: 99.999 percent.","offset":131,"duration":4},{"text":"Host: Okay. What will that mean when—if those two companies, or when those two companies merge?","offset":135,"duration":7},{"text":"Chamath: One of the great things that happened in my career was there was a point where, you know how like you grind at a level and then you know, you just get exposed to things at a different level, and then you grind for years and you get exposed to things at yet another level.","offset":142,"duration":15},{"text":"Chamath: In one of those steps, I was very fortunate to be introduced by Thomas LaFont, actually, to the head of Wachtell Lipton—this is a law firm—and his name is Ed Herlihy. And he said, \"This is the most important, well-known, well-run, powerful law firm in America.\"","offset":157,"duration":24},{"text":"Chamath: Then I looked at the transactions and they're just in the middle of everything. And now, you know, my lawyer, Raj Narayan, who does everything for me, one of the senior partners at Wachtell, I can attest are incredible.","offset":181,"duration":13},{"text":"Chamath: And they said to me, in the middle of all of this stuff when I was doing a bunch of deals, they said, \"Chamath, just get ready to pay a tax.\" And I said, \"What does that mean?\" They said, \"The way that the American capital markets are set up is both that you can be incredibly creative and do incredible things, but—and we talked about this a little bit last week—there's a bunch of tort that allows folks to hang around the hoop and get paid no matter what.\"","offset":194,"duration":28},{"text":"Chamath: You see this in all IPOs: shareholder lawsuits abound. And they try to create a class out of it. And the reason they do that is that there's D&O insurance that then will pay out some number of millions of dollars, the attorneys take 40 or 50 percent, and then these plaintiffs get a few bucks.","offset":222,"duration":17},{"text":"Host: Which is a shakedown.","offset":239,"duration":0},{"text":"Chamath: It was a shakedown. Call it what it is. Why am I bringing this up? If you take the Raj and Ed example of this, this SpaceX IPO is going to set up a couple of things.","offset":239,"duration":15},{"text":"Chamath: The first is there's just going to be the natural noise in the market and Elon will have to sort through all of the little ticky-tacky things. But the most important positive thing that will happen from the IPO is a validated external mark-to-market valuation of SpaceX.","offset":254,"duration":24},{"text":"Chamath: And the market every day in real time gives you a valid mark-to-market assessment of the value of Tesla. And this allows you to put these two things together to minimize these lawsuits. Yes.","offset":278,"duration":14},{"text":"Chamath: And I think that's what Elon really needs: it'll make his life tremendously simpler from a governance perspective. It'll make the companies—and this quibbling about his time—a non-issue because again, nobody talks about Zuck or Satya or Sundar or Jensen allocating time across various projects inside of Meta or Google or Microsoft or Nvidia.","offset":292,"duration":29},{"text":"Chamath: Nor should they really make this claim for Elon because, as you're seeing, there's actually an enormous overlap and commonality to the various things that he is doing. He's building the robots, but they're used inside of SpaceX. He's building a terafab, they're used inside of Tesla. He's building X.ai, they're used across both.","offset":321,"duration":22},{"text":"Chamath: So I think we need to do this. It'll minimize the shareholder noise because it'll give less room to somebody that says, \"Hey, he set a valuation out of thin air.\" But dollars-to-donuts, these things are going to merge.","offset":343,"duration":11},{"text":"Host: Well, and it speaks to the singularity that's going on right now. You know, you had a car company, you had a space company. Okay, how do those two things overlap? And it's like AI, data centers in space, where do you get chips from, and then actually going to raw materials inside of one factory, going out the other.","offset":354,"duration":23},{"text":"Host: Having discussed it with Elon many times, what he learned at Tesla or SpaceX about advanced materials informed different products at the different companies. And now you just—you'll have all of that in one place. And then you think about the brain trust that he built at those two companies, plus Boring Company, plus Neuralink. If they're all in there, all this cross-disciplinary learning is going to compound and compound and compound.","offset":377,"duration":20},{"text":"Host: Elon knows more about factories than probably anybody. Like there are some people in China who have, you know, Foxconn knows a lot about factories. You know, so there are some people who know as much or probably even a little bit more about some aspects of it, but that's a true advantage of bringing those two teams together.","offset":397,"duration":19},{"text":"Host: And you saw it: people would go from one company to the other. Freeberg, my question for you, very acutely with your NASA hat and, you know, your background today is: 20 years ago, he started trying to get to space with SpaceX and here we go. There's more rockets going off in a month now than there are days in the month for the entire country. And he's got rockets going up every two or three days. You can just basically hop on a SpaceX flight and get to space.","offset":416,"duration":27},{"text":"Host: Maybe you could just use your vision there to tell the audience what could things look like in another 20 years if SpaceX continues at this cadence or even, you know, goes faster because of AI?","offset":443,"duration":10},{"text":"Freeberg: Well, this week's a pretty important milestone for that point because we just launched Artemis 2 yesterday, which is man's return to the moon. So the United States shipped this rocket with four astronauts on board. They're going to do an orbit around the Earth, head to the Moon, come back around, and come back to Earth in anticipation of landing on the Moon in about two years.","offset":453,"duration":26},{"text":"Freeberg: And getting to the Moon, I think, is going to be very important, not just because there's this important social milestone and race happening right now with China, but I think the Moon could end up being kind of the next industrial frontier for humanity.","offset":479,"duration":15},{"text":"Freeberg: And the reason is, if you can get to the Moon, the Moon has an extraordinary abundance of material that we can mine, process, and manufacture into goods. And ultimately, the cost to ship those goods back to the Earth is zero. It will cost less to move goods, manufactured goods, processed or precious metals from the Moon to a specific point on Earth. It will cost less to do that than to ship it using any other terrestrial conventional method, whether that's a boat, an airplane, or a railroad.","offset":494,"duration":35},{"text":"Freeberg: And the reason is that on the Moon, you can take advantage of the low gravity—it's about one-sixth the gravity—and the complete lack of an atmosphere, meaning that it's frictionless to move material off of the Moon and very low energy to move it off of the Moon. You do not need to use a rocket propellant with high energy like we have to do to move things off of the Earth.","offset":529,"duration":19},{"text":"Freeberg: In fact, the design for moving material off of the Moon is to use what's called a mass driver, which is like a train track, like a rail, like an electric rail. You kind of see these in, you know, high-speed trains that work on kind of magnetic levitation. And you could put a package on that rail and use electricity to accelerate that package to 100 G-force, shoot it back to the Earth or theoretically shoot it to Mars, and it will go to the exact point on the Earth you want it to go to, re-enters the atmosphere, and lands with a simple parachute where you want it to go.","offset":548,"duration":31},{"text":"Freeberg: So we could run continuous mining, continuous manufacturing processes on the Moon at a fraction of the cost of what it would take to do it here on Earth. The biggest limiting factor: getting people to the Moon. And that is largely solved or will be solved in the next few years by robotics.","offset":579,"duration":17},{"text":"Freeberg: So I think that there's this pretty profound intersection with what's going on in robotics with this moment for space industrialization and moving to the Moon. So, you know, Tesla, I think 20 years from now is actually a more interesting story whether they're the same independent company or the same company. I think we're going to look back one day and have this kind of laughing observation that Tesla started out as an electric car company, ended up becoming an autonomous car company, and the autonomous competency is what led to the robotics revolution.","offset":596,"duration":32},{"text":"Freeberg: And the robotics revolution—even if the socialists ban robotics on Earth and tell us, \"No robots allowed, they're taking all the jobs\"—you could ship all those robots to the Moon and they could get to work and create an entirely new manufacturing frontier for our civilization, for humanity. That frontier can manufacture precious metals and other goods and ship them back. You could manufacture semiconductors on the Moon. All that's missing is the robot.","offset":628,"duration":24},{"text":"Freeberg: So moving the robots to the Moon or setting up the materials for robots to build themselves on the Moon is kind of the first phase of this transition. You know, asking about 20 years from now, and then the next phase is $100 billion sold out.","offset":652,"duration":9},{"text":"Freeberg: So look, I mean, I think that this may not be—and it certainly won't be—limited to just SpaceX, but SpaceX has demonstrated its capacity at being effectively the railroads. You know, what the railroads were to the West and to the frontier in the West, you know, in the last generation, SpaceX will be to the Moon and ultimately to Mars. And there's going to be an extraordinary abundance of production that's going to come out of the Moon.","offset":661,"duration":20},{"text":"Freeberg: The Moon has everything, by the way. And I'll say one more thing about SpaceX: SpaceX has also created—and this is going to be a big part of the valuation analysis that many are doing—they've created a backup to the Internet. You know, the Internet is fundamentally limited by all of the nodes on the network and the connectivity amongst all those nodes. And that connectivity is largely driven by copper and fiber optic cables.","offset":681,"duration":21},{"text":"Freeberg: So in space, what the number of satellites going up with Starlink and to actually deploy data centers that can output data on those nodes on that network, SpaceX has largely built a backup Internet. And that backup Internet can coincide with the Earth's Internet, but it creates this extraterrestrial communication network that gives us theoretically the ability to think about, \"Hey, if governments collapse, if there's civilizational upheaval, etc., etc., etc., this becomes, I think, a fundamentally kind of important technology infrastructure that's going to exist in parallel.\"","offset":702,"duration":31},{"text":"Freeberg: So I'm pretty excited about like these two separate paths for SpaceX and where they intersect with Tesla. I think it's pretty profound at the moment.","offset":733,"duration":7},{"text":"Host: Yeah, and it can't be understated what lowering the cost per kilogram to get to space has done to entrepreneurs around the company. There's multiple entrepreneurs who are now doing asteroid mining or Varda doing experimentation in space. And I have a—I've been doing some late-stage stuff, Chamath, with my syndicate, and one of the interesting companies we syndicated, we did Zipline, which is a great company, but we also did this company called Vast, Vast Space. Jed is the founder, he created Ripple and and some other crypto projects, and he put a lot of his money, hundreds of millions of dollars, into this company Vast Space.","offset":740,"duration":38},{"text":"Host: And they're designing a space station. How did they do it? Well, they just bought carriage on SpaceX rockets and they paid in advance, they have their slot, and now they're doing this massive innovation to make modular space station components. And the thesis is, \"Hey, what if Google or Amazon want to have a space station in space?\" You know, it's completely possible they may want that.","offset":778,"duration":25},{"text":"Chamath: Here's what I'll say: I think sometimes it's better to be lucky than good. There are all of these ways that so many people will end up with participation into SpaceX. I think we all owe Elon an enormous thanks. I think that this is going to unleash just an unbelievably large economy of things that we have no idea about.","offset":803,"duration":25},{"text":"Chamath: And when I see this thing, that video that you just showed, what it reminds me is that we have an over-very rudimentary capability in space. What does that mean? If you take, if you catch a ride on Falcon 9 or Falcon Heavy, basically it's dropping you off at 550 kilometers, I think. You have a different problem if you're trying to get to GEO.","offset":828,"duration":21},{"text":"Chamath: But even if you get dropped off at 500 or 550, how do you get to your actual orbital plane? Right? So meaning, if you think of Elon as like the big container ships that go from China to America, once it gets to Long Beach, you need FedEx. There's an entire infrastructure there that's going to get all of this logistics built last mile.","offset":849,"duration":22},{"text":"Chamath: There's a huge garbage collection problem that's getting built up. We still haven't technically solved how to do garbage collection in space. There's nets, there's magnetic plates—all of that is getting fixed. Then there's going to be an explosion in actual power generation.","offset":871,"duration":16},{"text":"Chamath: The cell composition of solar cells up in space are materially different. It's a really incredible thing. You look at these thin sheets—they are like 1 millimeter thick. You, if you carried it on your hand, the glass breaks, yet you can smash a meteor into it when it's lead and laminated and nothing happens. It's like the cra- so my point is in every single dimension of what the earthly economy looks like, it's now going to go and get rebuilt in space.","offset":887,"duration":32},{"text":"Chamath: There'll be a FedEx of space, there'll be a Maersk of space, there'll be a—I don't know what the garbage collection companies are—Allied Waste of space. There's going to be everything of space that exists in the United States. Freeberg just talked about the Freeport-McMoRan of space, like everything. And that we owe to him.","offset":919,"duration":18},{"text":"Chamath: And I hope he gets that credit because the amount of businesses I think that can get created and the amount of value that will be created on top of SpaceX's shoulders is vast. It's the beginning of the beginning of the beginning, and it's going to create enormous opportunities for people who are smart and resourceful.","offset":937,"duration":18},{"text":"Host: And Freeberg, maybe you could comment on the PGMs, the palladium that's on asteroids and just they're rare here on Earth. If we had an unlimited supply or a continuous supply of those minerals, you know, what what could the downstream effect of that be? And then what if we find things in space that we are unaware of? There are unknown unknowns, correct Freeberg, when you start to conceptualize this?","offset":955,"duration":26},{"text":"Freeberg: I do think like the asteroid mining is an interesting concept, but I do think it's going to be more likely that we'll have the need for infrastructure so we can produce ores and refine and so on versus, you know, bringing a chunky rock back. I think that you could do this very effectively on the Moon.","offset":981,"duration":16},{"text":"Freeberg: The primary elements that are missing from the Moon that we have on Earth are, you know, carbon, nitrogen, hydrogen, and oxygen—basically these things that make life on Earth. But that's because they primarily exist in a gaseous form and the Earth has enough gravity to retain those gases and have an atmosphere.","offset":997,"duration":22},{"text":"Freeberg: The Moon is too small to maintain an atmosphere. The gravity's too low, so those gases all kind of went away, they evaporated away in the early formation of the Earth and the Moon. But on the Moon, there's everything else: there's aluminum, there's silicon, there's palladium, there's platinum, there's gold, there's everything you possibly need.","offset":1019,"duration":19},{"text":"Freeberg: So I think as we do the calculus on all of this, we'll end up realizing that the Moon is probably the best frontier. One of the biggest issues is dissipating heat because you don't have an atmosphere, but theoretically you could recapture that heat and use like helium gas or something to turn a turbine and actually run production of even more electricity.","offset":1038,"duration":17},{"text":"Freeberg: You just put a couple solar panels out. I did the math on this: it's like 500 square meters of solar panels will let you run a 4 kilometer mass driver to ship material back to the Earth every 10 to 15 minutes. One ton of material every 10 to 15 minutes.","offset":1055,"duration":11},{"text":"Host: On the sled you described earlier that Elon's been talking about as well, yeah.","offset":1066,"duration":4},{"text":"Freeberg: So you could think about having autonomous mining vehicles deployed on the Moon processing the ore and then sending completely processed material back. And then for a heat shield for re-entry to the Earth, you just use Moon rock. You only need about 15 centimeters of Moon rock at the front of the package and then that'll burn up when it re-enters the atmosphere and the package, you know, kind of parachutes down and lands where you want it to land in your industrial shipyard or whatever.","offset":1070,"duration":23},{"text":"Freeberg: So there's just like, you know, I think we'll continue to kind of iterate on this. I'm speculating in a bunch of different ways.","offset":1093,"duration":4},{"text":"Chamath: The beginning of the beginning, the beginning of the beginning.","offset":1097,"duration":5},{"text":"Host: Gosh, I mean, can you imagine having a Moon base and America is just permanently present on the Moon? It's just and factories on the Moon, it's just wild to consider.","offset":1102,"duration":10},{"text":"Freeberg: Wild.","offset":1112,"duration":0},{"text":"Host: Can you guys just imagine like the middle or the early 19th century, like the late 1700s, early 1800s in America? And there's like all this land out on the West and like whatever people were contemplating in that moment about what they were going to go do with that land on the West and they started to travel West. Their minds would have been blown to see what happened 100 years later or now 150 years later.","offset":1112,"duration":22},{"text":"Freeberg: You know, like it's just that's the moment that we're at right now. And the railroads are being built to get us to this next great frontier, they're being laid out before us. And the opportunity is really limited only by our imagination. And before, we would have never been able to tackle these great frontiers, but this magical new technology came about called robots. And these robots are what are going to allow us to actually make use of these frontiers and explore them and develop them.","offset":1134,"duration":26},{"text":"Freeberg: And that's why this is such an incredible moment where this intersection of autonomy and robotics and space traversal kind of drive forward humanity into this new era. And it's not—again, this is not a zero-sum game, this is expanding humanity's potential, expanding production, which is so different than the way the socialists on Earth are talking about it, where everyone's fighting against progress because they think that progress is some people taking things from other people. And the truth is, it's about everyone building stuff that's new and everyone benefiting from this.","offset":1160,"duration":30},{"text":"Host: Well said.","offset":1190,"duration":1},{"text":"Chamath: I'm going to open a hotel-casino in space.","offset":1191,"duration":3},{"text":"Host: I'll be—oh, we go, that would be so sick.","offset":1194,"duration":1},{"text":"Chamath: No, I'm serious.","offset":1195,"duration":1},{"text":"Host: Absolutely.","offset":1196,"duration":0},{"text":"Freeberg: I would love that.","offset":1196,"duration":1},{"text":"Host: Yeah, and then—no rake? No rake? No gravity? No rake? No gravity?","offset":1197,"duration":7},{"text":"Chamath: No tax. No tax.","offset":1204,"duration":1},{"text":"Host: No tax! No tax on tips or poker winnings! I love it.","offset":1205,"duration":6},{"text":"Chamath: Whoever implements the red-light district in space is going to become a trillionaire.","offset":1211,"duration":4},{"text":"Host: Oh! Wow, that's—yeah, with the robotics and the uh pleasure-droids, replicants... Oh man, it could get crazy. All right, well let's just hope you're—we're not the Donner party on the way there. Um, 2026...","offset":1215,"duration":13},{"text":"Chamath: Don't worry, you'll be safely on the ground schlubbing syndicates. You'll be fine.","offset":1228,"duration":6},{"text":"Host: I'll tell you something, uh thank you. Shout out thesyndicate.com apply to join me in great companies, Chamath. Do you own thesyndicate.com?","offset":1234,"duration":7},{"text":"Chamath: No way.","offset":1241,"duration":0},{"text":"Host: Listen, I'm still working. You guys might be retired, but I'm in the game. I'm in the arena trying things, Chamath.","offset":1241,"duration":5},{"text":"Chamath: I'm selling—I'm selling enterprise software every day, that's what I do.","offset":1246,"duration":4},{"text":"Host: I mean, he literally—Chamath said, \"Hey J-Cal, can we wrap this up real quick because I got to get on a sales call? I got a discovery call.\" Listen, I like the fact that we're all working. We're working into our 50s, I love it.","offset":1250,"duration":8},{"text":"Host: Hey, 2026 could be an all-time record for IPOs. Looks like it uh will be. Anthropic, OpenAI, Databricks—I mean these are all nine- and possibly ten-figure IPOs in terms of the valuations. Long tail of other companies: Stripe, Cerebras, Canva, Discord, lots of people waiting. Here's your Polymarket: SpaceX 94% obviously, that looks like it's—we just talked about that for 20 minutes. Anthropic 41% in people were saying 70% in February, OpenAI 38%, Databricks 32%.","offset":1258,"duration":40},{"text":"Host: People are wondering what could uh derail this. Obviously we we have a very pro-business group of people in Washington DC, but you have potentially this uh Iran war and we'll talk about that later in the program could potentially push us back if God forbid it was to spiral out of control. Or there was a recession, uh maybe the Democrats you know taking control of Congress, Senate, etc.","offset":1298,"duration":26},{"text":"Host: What are your thoughts here on the flurry of potential IPOs? We're talking about trillions of dollars of companies, Chamath, and if that does happen, let's start talking second- and third-order impact of that kind of distribution chain that could happen for LPs and then also all these employees uh and then a currency for these companies. We go from a Mag 7 to a Mag 17 it looks like.","offset":1324,"duration":22},{"text":"Chamath: I think that we have a bit of a risk problem. And I think this is why it makes so much sense for Elon to get out first. If you think about appetite as equivalent to like a person at a Thanksgiving dinner: when you first come in and you see all of this stuff, it's so plentiful, your eyes are bigger than your stomach.","offset":1346,"duration":20},{"text":"Chamath: And I think in a moment like that, you want to be the one that is consumed first. And I think the risk increases when you are at the tail end because the risk is that the diners will run out of space.","offset":1366,"duration":15},{"text":"Host: Plate fills up, yeah.","offset":1381,"duration":1},{"text":"Chamath: And if you use that analogy, I think the reason why people's plates will get full are probably twofold and maybe threefold. The first and most important thing is there's enough tactical event risk that people generally want to be risk-off and have more margin of safety.","offset":1382,"duration":22},{"text":"Chamath: I think the Iran thing is kind of in there, but I think the big tactical event risk is that we have a lot of these really important financial moments tied to this concept of AGI, ASI. I don't know if you saw the OpenAI announcement on their final terms, but you know, a huge slug of Amazon's capital is tied to a 2028 IPO or a moment that calls for this.","offset":1404,"duration":27},{"text":"Chamath: Then there was a bunch of leaked text messages or whatever that said that there's a version of some AGI running inside of Anthropic. Then there was the fact that, you know, the leak of Claude code basically demonstrated that they had feature-flagged away a bunch of improvements, so if you stack up all these improvements, they're actually much further ahead than the models realized.","offset":1431,"duration":23},{"text":"Chamath: If you take all of that as a basket, it goes back to what I said last week, which is: we have a real pricing problem. If AGI is real, the durability of most companies is slim to none. If AGI is not real, then the fundraising capacity of these companies that are now raising hundreds of billions of dollars needs to get questioned and inspected thoroughly.","offset":1454,"duration":21},{"text":"Chamath: History will sort out which one is right, but both cannot be right. So in that vein, I actually think J-Cal, I don't think we're going to have like these \"quote-unquote\" blockbuster stream of IPOs. I think what happens is SpaceX is going to get out, they're going to do great. And then maybe the next one does good to great. Then the next one will do good.","offset":1475,"duration":20},{"text":"Chamath: And then the appetite runs out because you just can't absorb incrementally trillions of dollars of new demand. And if you think about it, where is it going to come from? Is it going to come from the sidelines? I don't know, I think it's more of a reallocation exercise.","offset":1495,"duration":15},{"text":"Chamath: But if you look at the S&P, while most people are now defensively moving away from these kinds of things towards the things that are more protected, what the industry calls \"Halo,\" right? High asset, low obsolescence kind of businesses. Those things trade for zero today, Jason. You can buy hundreds of millions of dollars of year of cash flow for two to five times right now in the stock market.","offset":1510,"duration":25},{"text":"Chamath: And so why are you going to go way out on the risk curve and buy something at 200 times revs, let alone earnings? Yeah, the so- I don't know, I'm more in the camp of: I think it's good to be first. It's pretty decent to be second, but if I were you, I would get the heck out and get public and get your money and fortify your balance sheet ASAP because I think the risk builds the further down the IPO chain you're in.","offset":1535,"duration":27},{"text":"Host: Yeah, there's going to be a competition for investor dollars, whether it's retail or it's institutional or sovereign wealth funds, they're going to have a lot of choices here: do you want to be in Nvidia, do you want to be in SpaceX? Maybe you have to rotate out of Amazon or Google or Disney in order to take on those opportunities, and that's going to be a great competition. Probably we could see a lot of these IPOs, Freeberg, trade below their IPO price in the year or two after they come out and get repriced, yeah? Like we've seen before.","offset":1562,"duration":32},{"text":"Freeberg: I think the market's going to need to find a price. Remember, the share owners in a lot of these companies have held on to these shares for a long period of time and the valuations are extraordinary. I mean, hundreds of billions of dollars in market value coming to market liquid for the first time. Some of these investors, regardless of whatever their entry price was, are going to be looking for liquidity.","offset":1594,"duration":22},{"text":"Freeberg: So there's only so much capital to absorb those shares on the buy-side. Meaning, if the buyers and the bid is not there to fulfill all of the selling, then you're going to see the share price decline and the market's going to find a price. And so I think this idea that like an IPO is, you know, just a step in driving the price or value of a company up is a pretty false sense, and I think we'll realize it's pretty false as some of these IPOs take place because there is so much pent-up selling demand, there is so much value that's being created, there's going to be so much selling pressure, and then there's going to be very little buying activity on some of these because anyone that could have bought at scale on the buy-side post-public were already in a lot of these companies pre-public as private companies.","offset":1616,"duration":50},{"text":"Freeberg: And so I don't know who the big buyers are that everyone's expecting are going to show up. They're probably thinking, \"Hey, it's going to be retail.\" Retail, yeah. I mean, it's like- yeah, but how much money does retail have left? I mean, if you look at retail investors, they have a certain amount of powder and it's probably deployed. It's not like they have unlimited places to look for that.","offset":1666,"duration":16},{"text":"Host: And you know, there's some evidence of this: Bloomberg ran an article on Wednesday (we tape on Thursday, folks, and you get to listen to the pod on Fridays) OpenAI is falling out of favor with secondary buyers. According to a report, OpenAI investors can't find buyers at the new $850 billion valuation that Chamath referenced earlier. Investors Bloomberg spoke to are looking to sell $600 million worth of shares. People are looking for liquidity and said they were institutional investors.","offset":1682,"duration":29},{"text":"Host: Anthropic, currently valued at $300 billion, is seeing major secondary bids at a $600 billion valuation. So I think Chamath, what this shows us is you're correct: there, you know, OpenAI and Anthropic are the two next cards, that's your turn and river, folks, if SpaceX is the flop.","offset":1711,"duration":15},{"text":"Host: And maybe they're massively overvalued right now. Maybe they're $300, $400, $500 billion companies, not trillion-dollar companies. And if you look at the amount of revenue—$24 billion for OpenAI at $852 billion, that's 35 times price-to-sales ratio, and that is a absurd price-to-sales ratio depending on if the growth keeps happening.","offset":1726,"duration":22},{"text":"Host: And as you referenced, Chamath, what if we are at Artificial General Intelligence, AGI, and the moats on these things is de minimis or or there is no moat? Anthropic just got hacked. All their secrets are out. Somebody transmuted the code into another language, posted it on GitHub, can't be stopped. I don't know if you saw that story, Freeberg, but this was kind of mind-blowing: somebody took the Anthropic code—I don't know what it was written in and then basically just put it into another language, reposted it.","offset":1748,"duration":32},{"text":"Host: If Anthropic comes and says, \"Hey, you can't do this,\" well, that negates their argument, Chamath, that they're allowed to train on other people's data and then spit out a different output. So this is a very weird moment in time, right?","offset":1780,"duration":14},{"text":"Chamath: It is. I think you're bringing up a bunch of different points, so let me just sort them out in the order that I think is important. Is there a market for OpenAI at 800 billion? Yes, and there should be. When I read that press release, my mind was blown. This is a- I've never seen a business like this. And I'd say the same thing of Anthropic.","offset":1794,"duration":23},{"text":"Chamath: What an incredible thing that both of these two companies have been able to create. Nobody in the history of the world has ever seen two businesses like this at this scale. Okay? It's unbelievable. These are trillion-dollar companies. They both are and they both deserve to be. How profitable they are, I don't know. What their terminal valuation is, I don't know. What will people pay for it at IPO? I don't know.","offset":1817,"duration":25},{"text":"Chamath: But Nick, I just shared something with you. These two companies need to get out as quickly as possible. And the reason is every single company that comes after it, all those companies that you just named, Jason, are not nearly as important and do not need the money nearly as badly as these guys do.","offset":1842,"duration":16},{"text":"Chamath: And where will it come from? The specific answer to your question when you look at this chart is: the tech sector PE is going to shrink faster, in my opinion, than the non-tech PE. And the reason is because as these companies come out, the combination of SpaceX, OpenAI, and Anthropic—all three are baking an AI technology that first and foremost will go after the tech sector.","offset":1858,"duration":28},{"text":"Chamath: It will eliminate and it will cannibalize and it will erode most of the moats that support this differential trading. So if I were a betting man, my first bet is as those three companies come out, these software businesses are going to approach the rest of the non-tech PE. Okay, that's the first step that has to happen.","offset":1886,"duration":22},{"text":"Chamath: So the rate of change of of the multiple erosion will basically say to the world, \"Hey, these tech companies are, I don't know, I'll buy the first five or six years of this story, but I'm not buying year 15 of this anymore because these three guys are going to build something.\"","offset":1908,"duration":14},{"text":"Chamath: So that's where the money comes from. That's why I think after SpaceX, these two guys need to get their act together, file quickly, get out, and just get the money, fortify their balance sheets, and be in a position. Everything that happens after that is a total coin toss because once these three companies are public, I think the blue line will converge to the orange line and it's going to be nasty.","offset":1922,"duration":24},{"text":"Host: Yeah, and Freeberg, just looking at this: do you believe that secondary market is a canary in the coal mine here with OpenAI? Because if we- and we've gone through this year after year here. These are exceptional businesses, they've grown incredibly, customers love their products, but the burn is brutal, the circular financing problem is still out there like what's reality here.","offset":1946,"duration":23},{"text":"Host: And that's going to all come out when these S1s get filed and they're publicly traded companies and they have quarterly earnings reports. Market share for these could be flipping: Anthropic and Gemini, other players coming into the market. What are your thoughts here on Anthropic and OpenAI post the SpaceX IPO?","offset":1969,"duration":19},{"text":"Freeberg: Like I said, there's only so much capital in the world. So I do think one of the things that's probably being underestimated at the moment is the liquidity crunch that's ahead for capital-intensive technology businesses given the conflict in the Middle East.","offset":1988,"duration":17},{"text":"Freeberg: I don't think that Qatar and certain Saudi offices and certain offices in UAE and Oman are as eager as they were or, you know, have been to provide large slugs of capital to support these initiatives. And remember, that capital moves its way through the markets, whether it's through JP Morgan in a loan to SoftBank which then gets paid to OpenAI. At the end of the day, there has to be unencumbered debt-free capital that's being provided to these systems from somewhere in the world.","offset":2005,"duration":36},{"text":"Freeberg: And the- if you trace all of it back, like a large chunk of it has historically in the last couple of years come from Middle East sovereigns and family offices. And I think that those are likely going to tighten up in the near term. That being the case, it's probably less demand.","offset":2041,"duration":13},{"text":"Freeberg: I do think that there's a lot of secondary demand coming from family offices in Europe and Singapore, places like that that generally have not had great access or early-stage access to private companies, but at some point there's only so much demand there.","offset":2054,"duration":11},{"text":"Freeberg: So I don't know like how far this is going to go or when this capital crunch that's going to emerge, I think from the Middle East. I don't think we've really felt the shock wave yet on what's happening because remember a lot of these Middle East capital commitments were made in the last cycle as LP commitments or whatever. And you know, if they stop, if they downscale LP commitments or they stop doing primary and secondary transactions, you know, takes a little bit of time before the market feels that and then it's like, \"Oh, the reliable go-to are gone.\"","offset":2065,"duration":25},{"text":"Freeberg: And a lot of the big funds, the the megafunds that are out there that have Middle East LPs are gone. And suddenly everyone's going to be like, \"Whoa!\" and the shock wave will hit. So let's see. It is a risk for the United States because China, I don't think, is going to be as challenged. We're so dependent on Middle East capital, it may be that China has a- a capital advantage actually going into this next phase.","offset":2090,"duration":24},{"text":"Host: Me- I mean, and we talked about force majeure could come into play here if this Iran thing spirals, God forbid, out of control or gets worse. People could say, \"You know what? We're we're going to downscale our commitments and hey, there's a war so we don't have to fund this.\"","offset":2114,"duration":14},{"text":"Chamath: I think the markets- I think the markets have shook that off, Jason. I don't think that they they view this Iran thing as a big thing. I think the big event risk in the market is: is AI real or not real? And if it's real, what are all of these companies worth? That is the big sword of Damocles over the stock market.","offset":2128,"duration":15},{"text":"Host: Yeah. All right, well that's a good segue I think into talking uh a bit about Iran. We took the week off from it last week and we're going to catch up here this week.","offset":2143,"duration":11},{"text":"Chamath: By the way, not because we intended to, just to be clear—not because we intended to, which all the comments railed us on, but we literally—Jason did a terrible job moderating. It was on the freaking docket, we were supposed to talk about it, we didn't get to it, we went way over.","offset":2154,"duration":15},{"text":"Host: He DMV'd it. He DMV'd it, you know, like \"come back later.\" Come back next week.","offset":2169,"duration":2},{"text":"Chamath: It's it's clearly my fault.","offset":2171,"duration":2},{"text":"Host: I'm just protecting Trump. I'm out here getting cover for Trump's mistake. Yeah. Everybody knows I'm in the pocket of President Trump. You're like, \"Take a ticket, take a ticket. Oh, you have an issue? Okay, well your issue number 17.\"","offset":2173,"duration":13},{"text":"Host: Trump DM'd me and said, \"Can you please take this off the docket?\" I was like, \"You got it, boss.\" And then you're like, \"Oh, sorry, office is closed, come back tomorrow.\"","offset":2186,"duration":7},{"text":"Host: Today is day 34 of the Iran war slash military operation. Trump addressed the nation Wednesday night for a brisk 18 minutes. Here's a 40-second clip.","offset":2193,"duration":10},{"text":"Trump: We're now totally independent of the Middle East, and yet we are there to help. We don't have to be there, we don't need their oil, we don't need anything they have, but we're there to help our allies. For years everyone has said that Iran cannot have nuclear weapons, but in the end those are just words if you're not willing to take action when the time comes. Our objectives are very simple and clear: we are systematically dismantling the regime's ability to threaten America or project power outside of their borders. And tonight I'm pleased to say that these core strategic objectives are nearing completion.","offset":2203,"duration":41},{"text":"Host: All right, the costs here are mounting. War is a very serious business: 13 American service members have tragically died, over 200 have been injured. On the other side of the ledger, 3,500 Iranians have died, including 1,600 civilians and over 200 children. 1,200 people in Lebanon have died from Israeli strikes, and we now have 50,000 troops deployed to the Middle East.","offset":2244,"duration":27},{"text":"Host: Chances of a ground invasion are increasing. War has cost $70 billion so far—that's assuming $2 billion a day, which there seems to be consensus on via the Department of War. Pentagon has asked Congress for another $200 billion. To put that in context, the war in Ukraine was $113 billion in the first year. This could quickly exceed it when we hit 50 days.","offset":2271,"duration":30},{"text":"Host: This isn't cheap. There are lots of costs. Here's uh your Polymarket on a ceasefire: 25% chance of a ceasefire by the end of April, 47% chance by the end of May. The sharps are are thinking this could wrap up. But ground invasion, which would be just really impactful I think, 63% chance by the end of April, 71% chance by the end of December.","offset":2301,"duration":30},{"text":"Host: I'm going to get into the second-order effects, but what do you think, Chamath? Uh, this obviously is super unpopular war.","offset":2331,"duration":7},{"text":"Chamath: I think two things, and the President kind of alluded to one that I think is very important, which is: if you are not energy independent, you are at risk. And I don't know how many more examples now that world leaders need to be shown to get their act together.","offset":2338,"duration":17},{"text":"Chamath: So if the Ukraine-Russian conflict didn't show Europe, then this should show not just Europe but the rest of the world: you need to be in control of your own energy infrastructure and energy independence because stuff happens in the world, and you're not always in control or can shape how that stuff can indirectly or directly affect you.","offset":2355,"duration":17},{"text":"Chamath: The United States has energy independence. It's an incredible situation. What was interesting to me is if you look at Europe, you know, they gutted a couple of their energy markets and they essentially ceded control to a combination of very expensive imports and China.","offset":2372,"duration":21},{"text":"Chamath: They did that in markets like nuclear where they just went out of it. They did that in things like nat gas where—again, we can debate—but where did Nord Stream 2 go? We don't know. And they did that in things like solar, where they just gutted all of the credits.","offset":2393,"duration":14},{"text":"Chamath: But what's interesting is they're starting to turn that around. I think Italy just reintroduced effectively what's called investment tax credits, Spain just did as well, Germany is restarting nuclear. So if you just took the last few months, just that change is incredibly important because our largest ally, Europe, should be fundamentally energy independent so that they preserve complete and total optionality like we do in how we respond to these situations. That I think is a critical thing that is a positive output of what's happening.","offset":2407,"duration":37},{"text":"Chamath: And then the second, Jason, which I think is a huge question mark and it builds on what Freeberg said before: the Middle Eastern states, specifically the UAE and Saudi, Qatar, Kuwait—they are our most important financing and banking partner in the future.","offset":2444,"duration":19},{"text":"Chamath: And I think we need to see a conclusive end to this war because they need to be in a position to monetize these critical assets. Because at the same time, if you see these big pools of demand start to become energy independent by either accelerating nuclear—but again, that's problematic and slow—but frankly, they're just going to ramp up solar. That's the only way that you can dispatch energy quickly.","offset":2463,"duration":23},{"text":"Chamath: I think what that does is it decreases hydrocarbon demand over the long run. That then decreases the monetization capacity for these countries. So if you put these two things together, all of these folks in the region want safety, security, and they need a quick end to this thing now. And I think that they're more incentivized to put boots on the ground, Jason, than America is. That's the point I was trying to make.","offset":2486,"duration":22},{"text":"Host: Freeberg, let's talk a little bit about fertilizer. You had brought up when we had the start of the Ukraine war, \"Hey, this is the bread basket, we could have a massive famine.\" Thankfully that was avoided, there were carve-outs for getting wheat and other crops out of Ukraine. But here we are again with a significant amount of fertilizer comes out of that region and it's not flowing right now. Do you have concerns this time around that we could see something similar?","offset":2508,"duration":35},{"text":"Freeberg: Fertilizer is made up of three elements: there's different fertilizers. The one element is N for nitrogen, P for phosphorus, and K for potassium. Ukraine is the largest producer of the K, the potassium, the potash. But the N in fertilizer is nitrogen, and that is about 60 percent of what goes into the ground. That's 60 to 65 percent of global fertilizer is the nitrogen. That's what really drives agricultural productivity. And we need nitrogen fertilizer to grow crops everywhere on Earth that we're growing crops to feed people at scale.","offset":2543,"duration":37},{"text":"Freeberg: That nitrogen is primarily made where natural gas is produced and processed. And the reason is that they use the natural gas as an input to the production process. They get the the carbon, the hydrogen, the oxygen, and then they compress—remember 70 percent of our atmosphere is made up of nitrogen gas—so they compress the nitrogen in the air to 200 times atmospheric pressure, run it over a an electrical current with a metal catalyst, and you break apart the N2 so you have just single nitrogen atoms, and then you combine it back and you end up getting ammonia out of the other end.","offset":2580,"duration":39},{"text":"Freeberg: That's why nitrogen fertilizers are produced where natural gas is processed. So the Middle East obviously is a massive producer, particularly in Qatar, of natural gas. And that's why so much of the world's nitrogen fertilizer is made in the Middle East. In fact, about 35 percent of the world's nitrogen fertilizer goes through the Strait of Hormuz. And it is then shipped to countries around the world that farm and that need it to grow their crops.","offset":2619,"duration":24},{"text":"Freeberg: The swing producer in the world is China. China historically makes about 15 percent of the world's nitrogen fertilizer. And when the war started, a few days after it began, China shut down exports of their nitrogen fertilizer. And so they basically choked out the rest of the world. And so when the Strait of Hormuz shut, the nitrogen stopped flowing.","offset":2643,"duration":19},{"text":"Freeberg: Here you can see the price spike that happened: as the war began, this is urea. Urea is the solid form of nitrogen fertilizer. So urea was trading at about 350 bucks a ton before the conflict kind of took off, and it continues to spike up. It reached over $700 a ton in the last two days.","offset":2662,"duration":20},{"text":"Freeberg: And this is really, really, really impactful. It's not just like, \"Oh, the price has doubled.\" Number one, there's a supply deficiency. So farmers in places like Africa and South Asia are not getting the urea that they need to farm. That is going to have a massive follow-on problem. And in markets where they have access, because the price has... [fades out]","offset":2682,"duration":18},{"text":"Jason: ...like in the United States, our biggest crop is corn. You need about 200 pounds of that urea per acre for corn.","offset":2700,"duration":10},{"text":"Jason: And that cost basically makes you unprofitable. There is no way you can make a profitable crop of corn. The other thing that China did at the same time is they stopped buying corn.","offset":2710,"duration":13},{"text":"Jason: So corn prices would normally spike up, and corn prices have remained low while the input prices have spiked for American farmers. So American farmers are in a real pickle.","offset":2723,"duration":14},{"text":"Jason: Fortunately for this spring planting, which is happening right now, about two-thirds of American farmers had already secured their fertilizer before this began. But a third did not.","offset":2737,"duration":13},{"text":"Jason: And they're switching crops, typically to soybeans. But we have a fall planting coming up in a couple of months here, and the choke points on production is going to keep prices very high.","offset":2750,"duration":14},{"text":"Jason: In the United States, we make a lot of our own ammonia at our natural gas facilities in places like Oklahoma and Texas and Wyoming and other places. And then it ships directly to the farms.","offset":2764,"duration":13},{"text":"Jason: But the cost is so high because of the global market that it's going to become very hard for farmers to make a profit. And around the world, there are many farmers, millions and millions of farmers, that can't access this fertilizer now.","offset":2777,"duration":14},{"text":"Jason: So the choke point in the Strait of Hormuz is turning out to be a real critical global food supply crisis yet again, similar to Ukraine. And remember there was about 400 million people, following the Ukraine war, globally, that we saw enter into a state of malnourishment.","offset":2791,"duration":19},{"text":"Jason: This means more than one year of 1,200 calories or less per day for a year. 400 million people after Ukraine. So coming out of this crisis, it could be even more severe given the criticality of nitrogen-based fertilizers and the shutdown of the Strait.","offset":2810,"duration":18},{"text":"Jason: Let me make two more points on this. You would think, okay, well we'll make more nitrogen fertilizer. The facilities take at least three to five years to fix when they break, which is what just happened in Qatar. That facility got damaged, the main facility that's being used to make fertilizer.","offset":2828,"duration":17},{"text":"Jason: So that is the largest producer of urea in the world that's now going to be incapacitated for three to five years. And if you want to build a new facility it takes about seven years.","offset":2845,"duration":13},{"text":"Jason: All the facilities around the world that make urea and ammonia, these nitrogen fertilizers, typically run 24/7/365 at full capacity. There is no downtime where you could just turn on excess production in the world.","offset":2858,"duration":15},{"text":"Jason: So, you know, the world is very delicate in its balance of inputs and food production and outputs. The whole world has like less than 30 days of food, of calories stored up.","offset":2873,"duration":12},{"text":"Jason: So as these kind of supply chain problems start to percolate, there's shockwaves that start to get felt around the world. So it's a pretty serious crisis ahead, and it'll take a few months before it'll be fully realized.","offset":2885,"duration":13},{"text":"Jason: In the meantime, US farmers are getting their asses handed to them, they can't make money. And China is using this as a moment for extraordinary leverage over America and taking advantage of the situation by shutting down exports of their fertilizer and at the same time not buying American production of corn.","offset":2898,"duration":20},{"text":"Chamath: We probably need Friedberg to have some sort of resiliency here and address this like we did with pharmaceuticals, PPE, all these other things. Yeah, we should have some sort of stockpile of fertilizer.","offset":2918,"duration":14},{"text":"Jason: To Chamath’s point is absolutely correct. Natural gas reservoirs exist around the world, and we've been loathe to exploit them or develop them because of the climate change carbon risks and issues.","offset":2932,"duration":15},{"text":"Jason: But I think what we're realizing is that those are luxury beliefs to an extent. You can only say let's not exploit carbon resources until you hit a shockwave like this and then people are like, wait a second, we really do need to have these systems up and running, and we need to have excess capacity and local capacity in the system.","offset":2947,"duration":19},{"text":"Jason: Because single points of failure for the whole world's food supply is not going to cut it anymore, particularly as the world is becoming more fragmented and multipolar and there's less US policing of the world that's going to happen, and so on.","offset":2966,"duration":14},{"text":"Jason: It's going to be very critical that everyone starts to think about doubling down not just on energy production, but some of these other critical inputs like fertilizer. And another output, just as a quick side story on nat gas production, is when you pull nat gas out of the ground, that's the primary place we find helium.","offset":2980,"duration":20},{"text":"Jason: And helium, we're all waking up to the fact, you know, we never really think about helium, we think about kids' balloons at birthday parties. But helium goes into MRI machines, helium goes into semiconductor manufacturing, helium goes into mass spec machines that are used in chemical analysis with a lot of applications around the world.","offset":3000,"duration":18},{"text":"Jason: Helium is a critical input to medical equipment, to manufacturing equipment, and all of a sudden a third of the world's helium coming out of Qatar is not making it out. And so we're now going to have a helium supply shock that's going to affect the world.","offset":3018,"duration":15},{"text":"Jason: So we're starting to wake up to the fact that perhaps these nat gas fields that we've allowed to kind of turn a blind eye and say let one country exploit them and let them make all the nat gas—the US is actively developing.","offset":3033,"duration":14},{"text":"Jason: You know, I went down and visited that Cheniere facility in Louisiana with Doug Burgum a couple months ago, which was an amazing site to see where we do all the LNG exporting. But the US has extraordinary nat gas reserves, so do many other places in the world that have failed to take advantage of developing them. And I think we're realizing the criticality of doing so at this moment.","offset":3047,"duration":22},{"text":"JCal: Looking at this, I think we'll have Trump pivot extremely soon. I've brought this chart up now. This will be the fourth time I've brought it up.","offset":3069,"duration":8},{"text":"Jason: Is that your prediction JCal? You think he's going to wrap this up?","offset":3077,"duration":4},{"text":"JCal: He's 100% going to wrap this up and I can show why. I mean, just basically look at the history of this. You guys remember I brought up this chart with Trump's net approval rating.","offset":3081,"duration":12},{"text":"JCal: And you look at how this has changed over the three times I brought it up. First time in June last year, then October, and again I'm going to bring it up here.","offset":3093,"duration":11},{"text":"JCal: The stuff with ICE, the, you know, the Epstein files, and just going right down the line of unpopular decisions. Trump's net approval rating now has just plummeted to negative 17. This is the least popular he's ever been.","offset":3104,"duration":15},{"text":"JCal: And he's had to pivot here. Pam Bondi, at the time we are recording this as I predicted on a previous episode that Kristi Noem and Pam Bondi would be fired or, in I guess Trump's terms, he likes to get them a new job and give them a window seat.","offset":3119,"duration":17},{"text":"JCal: This is absolutely going to result in a quick pivot. Who knows what the downstream effects are, but the inflation three handle is coming back. According to PolyMarket, gas is over $4 a gallon.","offset":3136,"duration":12},{"text":"JCal: And then, you know, it's easy to mock like we did earlier these no-kings protests. But 8 million people came out for that. That's a large number.","offset":3148,"duration":10},{"text":"JCal: And if you look at the PolyMarket for what's going to happen in the midterms, 51% chance now that the Dems take the Senate, 86% that they take the House. And, you know, what you're going to take from that is...","offset":3158,"duration":13},{"text":"Chamath: Wait, sorry, PolyMarket is now showing the Democrats winning both houses?","offset":3171,"duration":5},{"text":"JCal: Yeah, pull it up Nick. Significant chance of that. And you know when this happens...","offset":3176,"duration":5},{"text":"Chamath: How much money is being bet on that? Let's just see. 51% they take the Senate, 86% they take the House, and four and a half million volume.","offset":3181,"duration":10},{"text":"Chamath: There's four and a half million dollars on this? Oh gosh.","offset":3191,"duration":4},{"text":"JCal: I tend to filter how seriously I take PolyMarket just based on the total quantum. But this is a big number.","offset":3195,"duration":8},{"text":"JCal: Yeah, and, you know, listen, this is not me trying to dunk on Trump and my personal beliefs. I think when you lose Tucker, when you lose Megyn Kelly, when you lose Joe Rogan, you know, and people are looking at who Trump's surrounded with.","offset":3203,"duration":17},{"text":"JCal: There's really just two groups. You have these super highly qualified people, Bessent, Lutnick, obviously David Sacks. You got really highly qualified people, JD, you know, who I think the world of. I think these people are great.","offset":3220,"duration":17},{"text":"JCal: But then he puts some people in positions that I think weren't up to the task. Pam Bondi, Kristi, I'll put Stephen Miller and Kash in that as well, it’s my personal belief in that case.","offset":3237,"duration":14},{"text":"JCal: And those people have not served him well. And they need to get this presidency back on track because what's going to happen is we're going to have two more years of impeachments and investigations and the whole thing's going to be derided.","offset":3251,"duration":15},{"text":"JCal: And we really need to start thinking about what who's making these decisions. Who made this decision to go into Iran and why? Who made these decisions to have ICE go into Minnesota and why?","offset":3266,"duration":13},{"text":"JCal: And I think a lot of it goes back to Stephen Miller. I got mocked a bit here on the pod for blaming him, but you can correlate Stephen Miller, Kristi Noem, Kash Patel, and Pam Bondi with all of the downside of this presidency and the plummeting ratings.","offset":3279,"duration":16},{"text":"JCal: Trump's going to need to clear house. He's cleared out two of four. I predict he'll clear out the other two and get great leadership in there and turn this presidency around because, listen, this is going to be socialism now, and AOC's going to win.","offset":3295,"duration":14},{"text":"JCal: This is going to cause massive chaos if he doesn't get out of Iran and do it soon. Just my handicapping of the situation. Hegseth, I'm not so sure. I'm not sure if I, you know, what I think of him yet.","offset":3309,"duration":12},{"text":"JCal: But, you know, we don't have information on why Trump did this. That's going to be the next shoe to drop.","offset":3321,"duration":6},{"text":"Jason: On why he did it? Friedberg, I think, you know, this is the point I made the second this war happened or military operation—I mean, let's call it what it is, this is a war. When you kill the top 100 people, it's a war.","offset":3327,"duration":13},{"text":"Jason: I said, I don't have the information of why he did this. Like, he might have information, Friedberg, that we don't have that made this an absolute must for us to do.","offset":3340,"duration":9},{"text":"Jason: But we haven't revealed that information. He hasn't explained it well to the American people. I think that's why the ratings are—and I don't want to make the ratings like a TV ratings—his popularity's getting crushed.","offset":3349,"duration":13},{"text":"Jason: The way this was explained to Americans, and again, I'm not inserting my position here, I'm just talking about the disconnect right now, is that Operation Midnight Hammer was supposed to have just decimated this.","offset":3362,"duration":13},{"text":"Jason: So why did we do this again? And we don't have the information. This is why I try to stay humble in this and say like, what information does Trump have that we don't have?","offset":3375,"duration":11},{"text":"Jason: Some people seem to think, Chamath, this was overconfidence, there's obviously this debate, did we get baited into this by Israel and get pushed into it and is he a Manchurian candidate etc.?","offset":3386,"duration":13},{"text":"Jason: That's above my pay grade too. I don't have any information on that. I'm not in the CIA.","offset":3399,"duration":6},{"text":"Jason: It's hard to be an armchair critic on this stuff in both senses. Like, I think it's hard to say, hey, this guy got talked into doing this, Israel manipulated him into it. It's easy to say that.","offset":3405,"duration":11},{"text":"Jason: It's also easy to say, hey, we should go get rid of the country that's made all the nuclear weapons. Both of those are easy to say without all of the texture of the relationships and the details and what really went on. None of us know shit, is the truth.","offset":3416,"duration":14},{"text":"JCal: That's literally the point I've been trying to make here. Same thing with Venezuela, like how do we know, we don't have any intelligence, Chamath, we're not in the CIA, we don't have any of these insights that Mossad or the Israeli intelligence services has.","offset":3430,"duration":16},{"text":"JCal: How do we know how this was going to go down? And, you know, that's all going to come out I think when this all gets investigated. Yeah.","offset":3446,"duration":8},{"text":"Chamath: I think Trump is and has been the most consistent anti-war president of modern history. Yes.","offset":3454,"duration":10},{"text":"Chamath: And I think that it's fair to say that he has and has had and has demonstrated enormous restraint and has the highest bar thus far of folks for actually getting into conflict.","offset":3464,"duration":13},{"text":"Chamath: So I do think that what Friedberg says is very important. There's just so much we don't know and I think that he doesn't want to stain his legacy with a typical American, you know...","offset":3477,"duration":15},{"text":"Jason: Forever war. Yeah.","offset":3492,"duration":2},{"text":"Chamath: He doesn't want that. I don't think he needs to be anywhere near that. So there is obviously stuff that we don't know.","offset":3494,"duration":8},{"text":"Chamath: I still think that there's a short-term problem, which is not just the threat that Iran poses to Israel, but there's a threat that Iran poses to the rest of the Middle Eastern community.","offset":3502,"duration":12},{"text":"Chamath: That neighborhood is a complicated place. There was an interview that MBS did on Saudi television, Nick maybe you can find it. It's in Arabic but there's a good version of it that I saw with subtitles.","offset":3514,"duration":15},{"text":"Chamath: And if you hear MBS's telling of what the Iranian threat is, it's not dissimilar to how the Israelis would characterize the threat. And so I think it's important to understand that unpredictable actors should not be given an opportunity to have a cataclysmic weapon that can just completely destroy the earth as we know it.","offset":3529,"duration":21},{"text":"Chamath: That just doesn't make sense. And I think if you can intervene to prevent that, we're now aware of the damages of what this can do to enough of a degree where there should be enough of nuclear disarmament from here on out.","offset":3550,"duration":14},{"text":"Chamath: The six, seven, eight, nine countries that have it, okay. There's all kinds of reasons why maybe we could have remade those decisions over the intervening 70 years. Maybe there's some that we never should have let have it, the Pakistan-India thing is a good example of one.","offset":3564,"duration":15},{"text":"Chamath: But we are where we are, and I think we can all agree no more country should incrementally get access to this thing. Absolutely not.","offset":3579,"duration":9},{"text":"JCal: And this regime specifically believes that anybody who is not part of this specific religion needs to die, and the whole world...","offset":3588,"duration":10},{"text":"Chamath: Well, the world of Islam needs to be reunited in order to take on anybody who's not part of their version of radical Islam.","offset":3598,"duration":10},{"text":"Chamath: Like it’s a religious lunacy in that country that I think everybody else should be murdered if they don't convert.","offset":3608,"duration":7},{"text":"Chamath: I think it's important to say that the overwhelming majority of Sunnis and the overwhelming majority of Shiites are peaceful observant people. Yes. There are fringes in every religion.","offset":3615,"duration":11},{"text":"Chamath: And specifically this, I think the most important thing is to not take your word or anybody else's word. I do think it's important to listen to somebody like MBS because I think it's the lived experience of having to run a country in that neighborhood and what it means.","offset":3626,"duration":15},{"text":"Chamath: And I think what you see is as you're articulating many layers of complexity that again I think that most of us in the West have zero appreciation for. All of this goes to in the short term I think that they've forced themselves into a corner.","offset":3641,"duration":18},{"text":"Chamath: I think we can go back and relitigate why did Obama let them out? That was a really, really stupid idea. We probably should have kept our thumb on the scale and had them close to teetering on economic insolvency. That's the only thing that has kept them in check.","offset":3659,"duration":15},{"text":"Chamath: They veered wildly away the minute we let them out of the disarmament agreements that we had. But we are where we are, we gotta put the genie back in the bottle and we cannot look to other countries and tolerate this idea that they also want to build the kinds of weapons that can literally destroy the face of the planet as we know it.","offset":3674,"duration":21},{"text":"Chamath: It's a non-starter. And then the second-order effect is how do we make sure that folks that are participating in all of this broader seeds of sowing chaos, how do we hem them in?","offset":3695,"duration":15},{"text":"Chamath: And how do we create a more reasonable world order? And I think that the second-order effects and I've said this before kind of bring this back to China.","offset":3710,"duration":10},{"text":"Chamath: And I think a world where it's bipolar, where it's the United States and China roughly as the two leading statesmen of the world is probably the Nash equilibrium here.","offset":3720,"duration":11},{"text":"Jason: So I think getting China in a position where they need to do a deal. And remember I said this, the worst thing that could happen for China was the president delaying the summit and here we are, now it's delayed for six weeks, it's going to go into mid-May.","offset":3731,"duration":16},{"text":"Jason: If you think the Strait of Hormuz numbers as it relates to energy prices in Europe or anywhere else are crazy, look at what's happening inside of China right now. It is a no-bueno situation.","offset":3747,"duration":14},{"text":"Jason: And so in May if we can re-establish a set of operating criteria that keeps normalcy in check, no more of this rapid random expansion everywhere where the Chinese are trying to build bases near us and now we have to have a point of view near them. We don't need any of that.","offset":3761,"duration":18},{"text":"Jason: So I think if we can use this as an opportunity to de-escalate I think we should.","offset":3779,"duration":5},{"text":"JCal: Yeah. We seem to have moved from, I mean I think this is the question, there's a doctrine, I don't know if you guys heard this one before, of Mowing the Lawn.","offset":3784,"duration":9},{"text":"JCal: Which is the Israelis' view of Hezbollah, Hamas, and even Iran which is just, hey, we have to take away their progress, the last 30 or 40% of their progress towards nuclear bombs and we just do that consistently and we contain them.","offset":3793,"duration":13},{"text":"JCal: This has tipped over into regime change, and so I think that's the wild card that none of us can predict what happens from this point forward.","offset":3806,"duration":10},{"text":"JCal: I don't know how you leave Iran in this state if they're going to take over the Strait and charge everybody a dollar a barrel, is that going to be tenable? Are they going to keep blowing stuff up? This is uncharted territory and very high stakes.","offset":3816,"duration":16},{"text":"JCal: President Trump also reiterated the US doesn't need Middle East oil and that Europeans should go straight to the Strait and just take it. He said that the Strait will open naturally because, quote...","offset":3832,"duration":11},{"text":"Chamath: Why do we always focus on the Straits of Hormuz Jason? I'm focused on the Strait? I think you're over-focused on the Strait. I think you're always over-looking the gays of Hormuz as an example.","offset":3843,"duration":11},{"text":"JCal: That's true, and the non-binaries of Hormuz. They all count.","offset":3854,"duration":6},{"text":"Chamath: Well why is it all about the Straits of Hormuz all the time with you? Well, listen, I don't want to get canceled here because I'm talking about—I don't know the pronouns to use for these straits of Hormuz but yes.","offset":3860,"duration":11},{"text":"JCal: The Straits in Hormuz... I don't think you're allowed to be gay in Hormuz. I think you have to keep that pretty quiet there, don't you? That was the greatest clip ever.","offset":3871,"duration":10},{"text":"JCal: If you don't know what we're referring to it’s a viral clip. It’s incredible.","offset":3881,"duration":6},{"text":"JCal: Purple-haired people... no, not purple-haired, this was a young Indian lady. And we all thought the same thing, Indians are so smart, what happened to her? What happened?","offset":3887,"duration":13},{"text":"Jason: She's... they found an Indian who didn't understand the question. They found the one dumb Indian. They found her.","offset":3900,"duration":13},{"text":"Jason: This was... she's been absolutely... I mean, isn't it a little bit homophobic that it was so focused on just the straits of Hormuz and not the gays of Hormuz? Yes, I agree. Yeah, for sure.","offset":3913,"duration":9},{"text":"Jason: Is that why you're choosing to leave the gays of Hormuz behind? I think it's just history.","offset":3922,"duration":5},{"text":"Jason: Which Ivy League do you think she went to? Brown. 100%, Brown or Columbia. Oh yeah, that's a good call. I would say Columbia. She, yeah, she might have gone to Vassar actually. I think that might have been her safety school.","offset":3927,"duration":14},{"text":"Jason: That's the best, not Borat, Bruno impersonation I've heard in a long time. So, Friedberg, why are you so gay? Do you think the strait of... are you making your potatoes non-binary?","offset":3941,"duration":17},{"text":"Jason: It was like literally Bruno. You got 10 minutes Chamath, you want to do your Bitcoin thing or you want to just break?","offset":3958,"duration":10},{"text":"Chamath: The Bitcoin thing was interesting because I think in the last couple of months what we've started to see is an increasing amount of research that says that the scheduled eventuality of a quantum chip, a functional chip, is probably not 25 or 30 years away. It's probably now in the next five to seven years if I had to guess.","offset":3968,"duration":28},{"text":"Chamath: And I think that because that event horizon has moved in, in these next five to seven years, for those that follow Bitcoin and care about it, my only advice on this topic is that the leaders of the Bitcoin ecosystem need to organize themselves and need to make sure that they have an answer to the question of is this stuff quantum resistant?","offset":3996,"duration":25},{"text":"Chamath: Because if the answer is no, they are a very visible and obvious honeypot. Now there is the answer that then a lot of the Bitcoin community gives which is, well everything is screwed.","offset":4021,"duration":14},{"text":"Chamath: And my only advice is, possibly. But if a non-state actor gets a hold of quantum technology that can defeat crypto as we know it today, SHA-256, you know, ECDSA like the elliptical curve stuff, the run-of-the-mill stuff that we all rely on.","offset":4035,"duration":19},{"text":"Chamath: A non-state actor's incentive will first be to drain the obvious honeypots and then tell everybody that it's broken so that then everything goes to shit, all the prices go to zero, and then they have all the money and then they can buy stuff.","offset":4054,"duration":14},{"text":"Chamath: That would be the sequence of events if you were a non-state actor. So, yes you're right, the banks get hacked, yes you're right all this other stuff goes kaput, but I think you first go and you exploit the obvious places and I think crypto is the most obvious honeypot in a world where you can defeat encryption.","offset":4068,"duration":17},{"text":"Chamath: Now, in fairness, the crypto community, this was much, much earlier, had to deal with this, they had to migrate from different encryption schemes in the early parts of Bitcoin and they were able to self-organize.","offset":4085,"duration":13},{"text":"Chamath: The difficulty here is you're talking about a big technological lift. You're talking about all the wallets being re-architected, you're talking about all the transactional flows, all the processing nodes. These are complicated things that need to happen.","offset":4098,"duration":13},{"text":"Chamath: And I would just tell the crypto community you have five to seven years to get your shit in order. That's it.","offset":4111,"duration":6},{"text":"Friedberg: Quantum computing just generally speaking, you feel it's going to have a major impact in the short term? Do you think it's actually going to become viable in the midterm? Where do you think about it? Because it's always been 10 years out, but it feels like we're making some progress.","offset":4117,"duration":15},{"text":"Jason: Well, it's... yeah, there's a lot that's changed. I mean, so the primary mechanism of modern encryption standards relates to factoring primes of an integer, discovering the prime factors of an integer would give you the ability to theoretically crack encryption.","offset":4132,"duration":20},{"text":"Jason: There was an algorithm that was theorized by a guy named Peter Shor. I think I talked about this on a prior episode back in 1994 called Shor's algorithm.","offset":4152,"duration":8},{"text":"Jason: Today it's kind of the commonly well-known model for how you could do this and it's a... you could watch a YouTube video on it. There's some YouTube videos that explain it pretty clearly, takes a bit of time to understand it.","offset":4160,"duration":11},{"text":"Jason: And then a couple years ago, I think in 2023, there was another computer scientist named Oded Regev from NYU who published another paper that showed a faster different approach to Shor's algorithm.","offset":4171,"duration":12},{"text":"Jason: It was an improvement on Shor's algorithm that basically reduced the number of quantum operations required to factor a large integer significantly.","offset":4183,"duration":11},{"text":"Jason: We went from 28 million of those operations down to 500,000. Yeah, and so there's this a lot of work going on right now, even before we have industrial-scale quantum computers.","offset":4194,"duration":10},{"text":"Jason: A lot of work going on in quantum computing theory and building models and algorithms, a lot of this is rooted in pure mathematics and statistics and whatnot. That work is making progress in building better algorithms even before the compute comes online.","offset":4204,"duration":15},{"text":"Jason: And then there's this separate set of things that you can track but, you know, the market if you want to trust the market is betting that we are within spitting distance of quantum computers reaching an industrial scale at this moment.","offset":4219,"duration":14},{"text":"Jason: So those two things intersect at some moment in the near term where you have algorithms that are low demand, low latency, that can crack modern encryption standards and then the compute comes online and someone is going to execute.","offset":4233,"duration":19},{"text":"Jason: The real thing is what do you do about it? There's a whole bunch of research that's been going on for 20 plus years on quantum algorithms, quantum encryption standards.","offset":4252,"duration":11},{"text":"Jason: And so to Chamath's point, these things exist, it's just a heavy lift and so there's going to be this heavy lift, probably, you know, pretty good business to be made in the next couple of years in all of the changes that are going to need to happen across all encryption standards across the whole internet, across how we do communications and so on.","offset":4263,"duration":16},{"text":"Jason: In a crazy way, Friedberg, crypto's in the same place as all these software stocks, meaning if AGI and ASI are real, these software companies are not what we thought they were. Yeah.","offset":4279,"duration":12},{"text":"Jason: If quantum is real, a bunch of these crypto projects are not what we thought they were. And so you can't have both, guys. You gotta choose. Pick one. Yeah.","offset":4291,"duration":10},{"text":"Jason: All right everybody, this has been... Oh hey we listen, you know I have an incredible EA? Executive Assistant.","offset":4301,"duration":8},{"text":"Chamath: It's really been like, you know, everybody talks about like agents, agents, agents, agents and this was the pre-agent agent. You know my EA's averaged around 188 to 200k a year and...","offset":4309,"duration":16},{"text":"JCal: People right now their heads are exploding in middle America.","offset":4325,"duration":4},{"text":"Chamath: Plus the truth I was paying 188 to 200,000 dollars a year. They were wonderful, okay.","offset":4329,"duration":6},{"text":"Chamath: And then JCal was like, try this thing called Athena, Athena, Athena. I'm like what is it? So I called the guys and they're like, yeah, we have these really well-trained folks, they're like geniuses that work in the Philippines. It's 3,000 a month and we're building all this tooling.","offset":4335,"duration":14},{"text":"Chamath: And so as all these agents get better and all these AI's get better, they'll get the advantage of that. I said, okay, I'll give it a try. This is the first time I've had a male assistant. His name is Lei.","offset":4349,"duration":9},{"text":"Chamath: Lei's fabulous. He's a math grad, math and computer science in the Philippines, okay. And he's excellent. I love Lei too, somebody just put it in the chat, I love Lei. From Nick. Nick, do you love Lei?","offset":4358,"duration":13},{"text":"JCal: I love Lei, coming to NBC this fall. These guys are incredible. They do everything for me. It's like the most incredible hack and arbitrage I've ever seen.","offset":4371,"duration":12},{"text":"JCal: Then now then I can direct a bonus to Lei at the end of the year which is great because then it allows me to feel like I'm giving him really, you know, good support. He works my hours from the Philippines, have not looked back.","offset":4383,"duration":11},{"text":"JCal: Go Athena. That's great. I used it as well. I was the first investor.","offset":4394,"duration":6},{"text":"Chamath: You were the first? You were the first? How many Athena's you have, one or two? I have one.","offset":4400,"duration":4},{"text":"JCal: I had two for a long time. I think I might get a second one. And then that person moved on. You split it between like work and personal or no?","offset":4404,"duration":7},{"text":"JCal: Yeah, it's work and personal. As an example, like there's an incredible bakery where I live, like out in Dripping Springs, called Abbey Jane Bakery. They don't take orders.","offset":4411,"duration":10},{"text":"JCal: But every Thursday, my Athena assistant calls at 8:00 AM, asks them what's on the menu because they change the menu every week. And then they send me the menu, I order the bakeries, and then he calls an Uber courier to pick it up and drop it off because they're not on DoorDash or Uber Eats.","offset":4421,"duration":19},{"text":"JCal: It's just a stupid example of something that made our lives incredible to have the best bakery in all of Austin in the house every weekend for the girls and everything. Everyday problems, yeah everyday problems.","offset":4440,"duration":11},{"text":"JCal: Anyway, it's a silly example, but I was having to go make that run and I did it every like fourth or fifth week as a treat. Now it's every week.","offset":4451,"duration":8},{"text":"JCal: So you just look at what you're doing. The other thing we're doing is they've been able to—we had Americans who were researchers sorting through the inbound applications from founders.","offset":4459,"duration":12},{"text":"JCal: We were able to put an Athena assistant on that and then define it and then they're learning how to use OpenCloak. So the Athena OpenCloak merger is kind of happening in real time.","offset":4471,"duration":9},{"text":"Chamath: Yeah, no, I have Lei doing a bunch of advanced tasks that I typically wouldn't give to my EA. And then he also deals with sort of just the more practical day-to-day tasks scheduling all that stuff.","offset":4480,"duration":12},{"text":"Chamath: Anyways, it's been an incredible eye-opening thing because it sets a very good example where, you know, you can be cost-effective and still get your work done. And it was really bothering me actually because like the amount of cost inflation for that role because I don't think I've ever needed an EA.","offset":4492,"duration":14},{"text":"Chamath: I'll just be honest, I'm going to put it out there. I think I've always needed an AA. And I would title them differently and sometimes I would call, you know, the... I mean, I've said this before, but like even like roles like Chief of Staff, they just don't make sense. Like the Chief of Staff should be the second most powerful person in the world because they work for the President of the United States.","offset":4506,"duration":22},{"text":"Chamath: Everybody else should not have a Chief of Staff in my opinion, okay. It's a major unlock and the problem is we have the lowest unemployment of our lifetimes and it's just people don't want to take the EA or the administrative assistant position in America. They just don't.","offset":4528,"duration":15},{"text":"Chamath: They want to do something higher up the stack but the people in the Philippines, you know, they do want that job. Lei's crushing. I love Lei. RJ's my guy.","offset":4543,"duration":9},{"text":"JCal: And yeah, first time... You got a guy too? I got a guy too and he is also very technical. So anyway, shout out to Athena. Shout out to Athena. Thank you guys, thank you Athena.","offset":4552,"duration":11},{"text":"JCal: Friedberg, I know you're making great progress. You showed me some pictures of potatoes from Ohalo. How's that going?","offset":4563,"duration":10},{"text":"Friedberg: Just shipping seed this week to farmers all over North America, so we're getting going. Are you sending seed to our friend Roger the dirt farmer? He is, his son, yeah.","offset":4573,"duration":9},{"text":"JCal: Oh that's so great. Dirt Roger? I love him. Roger the dirt farmer's a phenomenal poker player, he and Keating often play in the game together. Ah.","offset":4582,"duration":10},{"text":"JCal: How'd they do? A couple weeks ago they came up. They came and visited me the next day. Both of those two goofballs ran over the game. It's so frustrating. It's frustrating playing with Keating.","offset":4592,"duration":11},{"text":"JCal: Roger is much more of a tag, you know, a tight-aggressive player, so it's no picnic. There's no free lunch when both of those two guys are in the game. And then on top of that, you know, Helmuth, Kuhn, Roble, it’s like it’s not a winning game. It's murder's row.","offset":4603,"duration":13},{"text":"JCal: I got... I made a late trip to the valley. I'm like, hey, Chamath, I'm in town, I get to play. Chamath's like, uh I got some bad news for you. You're no longer on the list and I filled the game up plus two.","offset":4616,"duration":14},{"text":"JCal: So I squeak into the game. I've run up a quick 20, 25 dime-skies and then Helmuth, passive-aggressive Helmuth, who cannot handle the fact that I'm more famous than him now. It's just totally tweaked him that Chamath and I and you, Friedberg, are so much more famous than him.","offset":4630,"duration":13},{"text":"JCal: It's broken his brain. He says like, uh okay, a car dealer, car dealer you're supposed to have a seat and JCal doesn't. And I literally just doubled up at that point and Chamath's like, okay I guess you can book the win, JCal, because you know it's like poor taste to double up and then leave.","offset":4643,"duration":17},{"text":"Chamath: How much did you win, 40, 50k? It was only like 25 dimes. It was, you know, like a used Model Y, yeah yeah.","offset":4660,"duration":9},{"text":"JCal: Hey, Chamath, we're here at the end of the show. I just wanted to make sure people know that the liquidity event that we're hosting, you can go to all-in.com/events has sold out and we've started a waitlist.","offset":4669,"duration":12},{"text":"Chamath: So this is the quickest we've ever sold out. I asked Kimber and Lisa to try to find another 100 seats. I think there's like 7.7 trillion dollars of money that want to attend. We can't get everybody in, so we're trying to get everybody together.","offset":4681,"duration":15},{"text":"Chamath: We announced Bill Ackman and Andrej Karpathy last week. Incredible. We're going to do an Ira Sohn-like pitch competition. There's like four whiz-bang hot fund managers.","offset":4696,"duration":13},{"text":"JCal: Can you explain what that is for folks who don't know? Yeah. I know a bunch of these guys but four of them in particular are running super hot right now, like taking in 50 million, run it up to a billion to three billion.","offset":4709,"duration":9},{"text":"Chamath: They're just ripping. And they're going to go on stage and they're going to give us their best ideas pitch and the three of us plus I think as many of the guests that can do it will vote.","offset":4718,"duration":12},{"text":"Chamath: And then maybe we can even publish these ideas so that folks can try to follow them. They can vet them, right? It’s a real brave thing to do to get on stage and say, hey, I'm making this bet.","offset":4730,"duration":9},{"text":"JCal: Like how's that? I did it four times. I mean, I just spanked it but hopefully these guys can do the same thing. But listen, we have a natural resources pitch, we have something in healthcare, we have something in tech, we have something in crypto.","offset":4739,"duration":13},{"text":"Jason: Genius. It's great. It's like all the big categories. We have something in crypto, so it's you're going to get every shade of every whippy big alpha market.","offset":4752,"duration":10},{"text":"JCal: By the way, you created a bit of a storm on the interwebs with your Tao mention in the Jensen interview.","offset":4762,"duration":8},{"text":"Chamath: I just asked Jensen a question, I'm not long Tao. He'd redirected it to something which is Folding at Home which I think if you don't know it you should look it up but it's how you can allocate compute to helping solve health problems.","offset":4770,"duration":13},{"text":"Chamath: The point is these open-source projects or these distributed compute projects are the future. The real question is what is the architecture and the incentives? None of us knows that.","offset":4783,"duration":11},{"text":"Chamath: Yeah. But man I think it's so important. And then all these goons went crazy. Well, I mean, the reason is because I did a piece of that on Tao like a couple of weeks ago I went public with, hey yeah I've got a small bet here because I think these subnets are fascinating and distributed computing.","offset":4794,"duration":15},{"text":"Jason: You're a Tao maxi? Your Tao maxi? I mean I'm not Tao, I mean it's like I might be 500, 600 thousand dollars, a tiny bet. You're syndicate maxi.","offset":4809,"duration":8},{"text":"Jason: No, I did it myself. I did it myself. I made a small bet on Tao because I watched exactly... This retard is syndicate maxi. I'm not... it's not... I'm not retard maxi here.","offset":4817,"duration":8},{"text":"Jason: But I am certainly not doing any introspection, I am just doing deals on great founders and companies.","offset":4825,"duration":5},{"text":"Chamath: Okay. Andreessen has been rage tweeting about this guy that he watches. Oh so great. A genius. Who posts these videos about retard maxing. Yes.","offset":4830,"duration":9},{"text":"Chamath: I watched the video, it's incredible. This guy is... What is the guy's name I don't know what the guy's name is.","offset":4839,"duration":6},{"text":"Jason: I don't know, but he goes on his back deck, he's got a Weber grill, smoking a cigar, he pops out a cigar and he says, listen it doesn't matter, just go to work and enjoy your life.","offset":4845,"duration":8},{"text":"Jason: That may be the most incredible interwebs contribution Andreessen may be making to culture and society in America, not the browser, he found this guy. I encourage you, Nick, find the video please, post the links.","offset":4853,"duration":12},{"text":"Jason: This guy is incredible. Because you're overthinking it folks, just enjoy your life. Oh my god he’s so good. He’s so good. and work hard and don't think it through because look what happened to Friedberg, he starts ruminating.","offset":4865,"duration":11},{"text":"Jason: I gotta sell software. Love you boys. Don't ruminate, just go sell software and go make better potatoes, Friedberg. No more ruminating and therapy for you Friedberg.","offset":4876,"duration":8},{"text":"JCal: Come on the program anytime Marc Andreessen. Go retard max with us here on the All-In pod. Love you boys. Bye bye.","offset":4884,"duration":15}],"logs":[{"elapsed":"0.0","message":"Downloading audio from YouTube...","detail":null},{"elapsed":"0.0","message":"Trying download with browser cookies (ad-free)...","detail":null},{"elapsed":"3.6","message":"⚠ Cookie download failed: WARNING: [youtube] [jsc] Error solving n challenge request using \"deno\" provider: Error running deno process (returncode: 1): \u001b[0m\u001b[1m\u001b[31merror\u001b[0m: Uncaught (in promise) TypeError: Cannot read prope","detail":null},{"elapsed":"3.6","message":"Retrying without cookies...","detail":null},{"elapsed":"42.1","message":"⚠ Downloaded without cookies — audio may contain ads","detail":null},{"elapsed":"42.1","message":"Audio downloaded (46.5 MB) in 42.1s","detail":"File size: 46.5 MB"},{"elapsed":"42.1","message":"Video title: SpaceX IPO, Iran War Fallout, Quantum Bitcoin Hack, The Space Opportunity","detail":null},{"elapsed":"42.2","message":"Audio duration: 1:20:31 (80.5 min)","detail":null},{"elapsed":"42.2","message":"Large audio (80.5 min) — will use chunked transcription with gemini-3-flash-preview","detail":null},{"elapsed":"42.2","message":"Skipping full-file attempt — using chunked transcription for 80.5 min audio","detail":null},{"elapsed":"42.6","message":"Split audio into 2 chunks for transcription","detail":null},{"elapsed":"42.6","message":"Transcribing chunk 1/2 (starts at 0:00)...","detail":null},{"elapsed":"42.6","message":"Uploading audio to Gemini File API...","detail":null},{"elapsed":"46.4","message":"Audio uploaded in 3.8s","detail":"File ref: files/3a5bgzk02cnp"},{"elapsed":"46.4","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"113.6","message":"Chunk 1: 148 segments, last timestamp 44:42","detail":null},{"elapsed":"113.6","message":"Transcribing chunk 2/2 (starts at 45:00)...","detail":null},{"elapsed":"113.6","message":"Uploading audio (offset 45:00) to Gemini File API...","detail":null},{"elapsed":"116.9","message":"Audio uploaded in 3.3s","detail":"File ref: files/lj4tnd63782h"},{"elapsed":"116.9","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"177.9","message":"Chunk 2: 179 segments, last timestamp 1:21:24","detail":null},{"elapsed":"177.9","message":"Chunked transcription complete: 327 total segments","detail":null},{"elapsed":"178.0","message":"Total cost: 121,282 in / 22,474 out — cost: $0.1281","detail":null},{"elapsed":"178.0","message":"Total transcription time: 135.8s — 327 segments","detail":null},{"elapsed":"178.0","message":"Analyzing topics across 327 segments with gemini-3.1-pro-preview...","detail":null},{"elapsed":"218.3","message":"Topic analysis complete in 40.3s — found 10 topics","detail":null},{"elapsed":"218.3","message":"Analysis tokens: 24,112 in / 908 out / 4,575 thinking — cost: $0.1140","detail":null},{"elapsed":"218.3","message":"Pipeline finished in 218.3s — total cost: $0.2421 (173,351 tokens)","detail":null}]} \ No newline at end of file diff --git a/history/1775275709956-d01H-T3-frg.json b/history/1775275709956-d01H-T3-frg.json new file mode 100644 index 0000000..8c0d5bb --- /dev/null +++ b/history/1775275709956-d01H-T3-frg.json @@ -0,0 +1 @@ +{"id":"1775275709956-d01H-T3-frg","videoId":"d01H-T3-frg","url":"https://www.youtube.com/watch?v=d01H-T3-frg","title":"Fed Governor Miran on Why Inflation Fears Are Overstated","type":"youtube","topicCount":9,"segmentCount":97,"createdAt":"2026-04-04T04:08:29.956Z","uploadDate":"20260401","chunks":[{"title":"Cold Open & Podcast Disclaimer","summary":"A preview of Governor Miran's remarks on monetary policy, inflation, and supply shocks, followed by a standard podcast disclaimer from the narrator.","entries":[{"text":"Governor Miran: Oil moving higher now has very little inflationary consequence 12 to 18 months out, all the inflation happens up front. And so that's part of why a central bank should look through an oil shock as the Federal Reserve has historically done.","offset":0,"duration":11},{"text":"Governor Miran: Forward inflation expectations a year out, two years out, three years out are all pretty much unaffected by what's been going on and in fact a lot of them are lower since the FOMC met in January.","offset":11,"duration":10},{"text":"Governor Miran: My view is that the economy can bear additional support for the labor market from monetary policy. With the labor market very gradually cooling and declining wage pressures, you just are not going to get a wage price spiral that a central bank would normally respond to.","offset":21,"duration":13},{"text":"Governor Miran: When you start to say something like running it hot, it's wildly imprecise because it's a statement that sort of assumes that supply is constant, that you can't increase the horsepower of the car.","offset":34,"duration":9},{"text":"Governor Miran: I don't think the economy needs monetary policy to be slamming on the gas and accelerating the economy like it was in 2021 or 2022, but I also don't think it needs to be holding the economy back. And right now it is modestly restrictive and it is holding the economy back and I don't think that's consistent with the macroeconomic backdrop.","offset":43,"duration":16},{"text":"Governor Miran: What matters when you think about shocks to the supply side, whether they're AI, oil, regulation, no matter what the shock is what matters when you think about this is-","offset":59,"duration":11},{"text":"Narrator: Nothing said on Forward Guidance is a recommendation to buy or sell any investments or products. This podcast is for informational purposes only, and the views expressed by anyone on the show are solely their opinions, not financial advice or necessarily the views of Blockworks. Our hosts, guests, and the Blockworks team may hold positions in the companies, funds, or projects discussed. As always, investments in blockchain technology involve risk. Terms and conditions apply. Do your own research.","offset":70,"duration":27}],"startTime":0},{"title":"FOMC Dissent & Monetary Framework","summary":"After being introduced, Governor Miran explains his rationale for dissenting at the recent FOMC meeting. He argues that inflation measurement quirks and a cooling labor market justify support for a rate cut, and that the Fed should look past short-term oil shocks.","entries":[{"text":"Host: Governor Miran, great to have you to the Digital Summit. Welcome.","offset":97,"duration":9},{"text":"Governor Miran: Thanks for having me and let me just clarify that I'm one member of a Board of seven governors, there are seven of us. I'm not a governor in the sense of a governor of the Bank of England or something like that.","offset":106,"duration":10},{"text":"Host: That's a good clear, hey Governor. Governor Miran, would love to just start by unpacking the most recent FOMC meeting that occurred last week. You dissented in support of a 25 basis rate cut, so I'd just love for you to unpack your current framework and why you dissented there.","offset":116,"duration":16},{"text":"Governor Miran: Sure, thanks. Look, you know at the Federal Reserve we have a dual mandate. We are tasked by Congress with paying attention to inflation, stable prices, and to the labor market. My view is that the inflation side of the mandate has, despite high measured inflation, has not been so problematic.","offset":132,"duration":17},{"text":"Governor Miran: Because a lot of the inflation excess over target has been as a result of some quirks of measurement of things like portfolio management services, which is basically just the stock market going up, biasing the way we measure inflation by 30 to 40 basis points.","offset":149,"duration":15},{"text":"Governor Miran: Once you correct for those things, I do not view inflation as being overly problematic, whereas the labor market has been on a very gradual trend of weakening over the course of the last three years. That trend has been in place, it's been continual, you see it in increasing difficulty of finding jobs for new entrants to the labor market.","offset":164,"duration":16},{"text":"Governor Miran: You see it in increasing length of time and people spend between jobs during unemployment. And so my view is that the economy can bear additional support for the labor market from monetary policy. Now a lot of what's been going on in the last few weeks is of course been tied to the war in Iran.","offset":180,"duration":17},{"text":"Governor Miran: And I think what's going on in oil prices has spooked a lot of people. Uh, you know, and I understand from a trading perspective, from a markets perspective, things whip around wildly in both directions, you get headline ping-pong and that pushes markets. And if you have leveraged positions, that can feel very, uh, you know, sort of very intense.","offset":197,"duration":16},{"text":"Governor Miran: But from a monetary policy perspective, we have to make policy for 12 to 18 months from now because there are big lags with which monetary policy hits the economy. If we adjust interest rates, it doesn't feed through into actual economic growth into actual unemployment and inflation for at least a year.","offset":213,"duration":19},{"text":"Governor Miran: So we need to set policy for a year, to a year and a half out. And the way that changes in oil prices affect the economy is actually much faster than that. When you get a spike up in oil prices, when you get a move higher in oil from something like what's going on in Iran, the oil price goes up immediately and headline inflation goes up a lot in the short term.","offset":232,"duration":20},{"text":"Governor Miran: But as you look a year, two year, a year and a half out, it's very unlikely that that causes subsequent effects that are affecting the economy a year, two year, a year and a half out, which is when monetary policy can affect the economy. And so that's part of why the classic reasoning of why a central bank should look through an oil shock as the Federal Reserve has historically done.","offset":252,"duration":16}],"startTime":97},{"title":"Positive vs. Negative Supply Shocks","summary":"Governor Miran details how short-term negative supply shocks, like oil price spikes, do not fuel long-term inflation. He contrasts this with positive supply shocks such as AI and deregulation, which drive persistent disinflationary trends.","entries":[{"text":"Host: So that idea of looking through an oil shock was something that's really come forth in terms of recent discussions here. It seems like every few years we have some sort of shock that we have to navigate through. And I'm curious if you could just unpack it, you know, the discussion seems to be that a lot of these supply shocks seem to go in one direction, one being higher inflation. How do you think about that?","offset":268,"duration":24},{"text":"Governor Miran: Yeah, so I'll say a couple things. Uh, one is when you think about how these negative supply shocks are hitting the economy, things like oil prices moving higher, uh, as I said before it affects headline inflation very much in the short term but as you look further out it doesn't affect anything.","offset":292,"duration":15},{"text":"Governor Miran: And that is if you were to get concerned about these negative supply shocks, that's what you would be looking for. You'd be looking for a rise in inflation expectations further out in time. And if you look at the inflation swap market, you see that forward inflation expectations a year out, two years out, three years out are all pretty much unaffected by what's been going on.","offset":307,"duration":20},{"text":"Governor Miran: And in fact a lot of them are lower since the start of since- sorry, a lot of them are lower since we met in January, since the FOMC met in January. And so there's been zero bleed through of the of the negative supply shock of oil prices into inflation expectations further out, uh, you know sort of further out in time which which again is when monetary policy would be able to affect.","offset":327,"duration":19},{"text":"Governor Miran: The other thing you'd be concerned about is if there were a wage price spiral. If prices go higher and then wages go higher and that pushes prices higher again, you get a negative feedback loop that just creates a self-fulfilling inflationary spiral that requires tightening from the monetary, uh, authority to offset and to and to squash.","offset":346,"duration":19},{"text":"Governor Miran: That's not something that we see happening right now because the labor market, as I said before, has been on this very gradual cooling trend for about three for about three years now. And with the labor market very gradually cooling and declining wage pressures, you just are not going to get a wage price spiral that would be the type of thing that would get- that a that a central bank would normally respond to.","offset":365,"duration":24},{"text":"Governor Miran: Now you said something else that I'd like to pick up on, which is that a lot of we've had a lot of negative supply shocks, uh, you know sort of over time. And I think that there's a tendency to think that they that those are the only supply shocks that we've that we've experienced. And that's not the case. There are also positive supply shocks that are hitting the economy too.","offset":389,"duration":19},{"text":"Governor Miran: And these get a lot of attention too. So one of them is AI, right? AI is a positive supply shock, it increases the productive capacity of the economy, it lets people produce more with less inputs into production. That's a positive supply shock. Another very powerful positive supply shock that's been hitting the economy has been the trend in deregulation.","offset":408,"duration":20},{"text":"Governor Miran: Now I think this is a- this is a group of people who are focused on crypto, regulations have probably played a large part in a number of your business models. And having to deal with those regulations has probably for a number of people in this room at some point slowed you down, reduced the amount of things you can produce, increased the cost of production.","offset":428,"duration":14},{"text":"Governor Miran: And as those regulatory barriers recede, it becomes easier for you to make products that people want to buy. And so as the regulatory, as the regulatory backdrop becomes easier, that's a positive supply shock that hits the economy too. Now I gave a speech in January in Greece where I looked at the literature, the modern literature on regulation and it's very difficult to sort of quantify the federal regulatory code and turn that into a number in a way that economists would like to do rigorous empirical studies.","offset":442,"duration":31},{"text":"Governor Miran: But I looked at the modern literature that sort of uses AI and machine learning tools to do so. And I calculated that the deregulatory wave that's been hitting the economy over the last 15 months or so would ultimately drag on inflation by about half a percent a year for the next few years, right?","offset":473,"duration":18},{"text":"Governor Miran: So that's that's that's quite chunky. Now just a couple of weeks ago, there was a new Federal Reserve staff research paper released by two staff economists at the Fed, uh, Danilo, um, uh, Cascaldi Garcia and Matteo Iacoviello. And what this Fed research paper on deregulation uh found is they they did a they did a entirely different estimation method than the previous literature and they did an entirely different measurement method for regulations than the previous literature.","offset":491,"duration":33},{"text":"Governor Miran: And when you apply their results to the scope of the deregulatory shock that we've seen over the last 15 months or so, it implies a roughly uh 0.3% drag on inflation each year for the next few years, right? So that's not just a one-off effect, that's a persistent uh disinflationary effect from the receding regulatory backdrop.","offset":524,"duration":19},{"text":"Governor Miran: Now using an entirely different literature, entirely different estimation methods, I calculated 0.5, they calculated 0.3. I think those are probably within noise of each other, they're certainly within confidence bands, I wouldn't be able to reject one in favor of the other. But either of them are very big and I think very substantial and of the types of shocks that policymakers ought to take into account when we're thinking about the correct settings for monetary policy.","offset":543,"duration":22},{"text":"Governor Miran: So yes, it is the case that we have had a number of negative supply shocks hit the economy, things like oil moving higher. Um, but it's also the case that we have very powerful positive supply shocks hitting the economy too. And unlike oil, I expect some of these, like deregulation and AI, to be persistent in their disinflationary effects.","offset":565,"duration":19}],"startTime":268},{"title":"Federal Funds Rate Forecast","summary":"Discussing the Summary of Economic Projections, Miran outlines his forecast for the federal funds rate. He contends that current monetary policy is modestly restrictive and should be adjusted back to a neutral rate to avoid unnecessarily slowing the economy.","entries":[{"text":"Host: So last week's meeting was a summary of economic projections update meeting. I would love to just hear about when you balance out the context of either these positive or negative supply shocks, how does that characterize your forecast for the federal funds rate for the next year?","offset":584,"duration":18},{"text":"Governor Miran: So in the last uh summary of projections, because of the oil shock, right, that hits the economy very quickly whereas I think some of these other shocks play out over time, I did raise my inflation projection for my headline inflation projection for this year to 2.7%, right?","offset":602,"duration":17},{"text":"Governor Miran: So I moved it a little bit higher because of the oil shock. However, as I said before, this is not the type of thing that policy should respond to because that happens all up front and policy affects the economy 12 to 18 months out. It has very oil moving higher now has very little inflationary consequence 12 to 18 months out, all the inflation happens up front.","offset":619,"duration":22},{"text":"Governor Miran: What does happen 12 to 18 months out is the economy might be weaker because the because every dollar that people put into, you know filling their gas tanks is a dollar they're not spending on other goods and services. And so that might put upward pressure on the unemployment rate. So in the the March summary of economic projections, I boosted my policy rate by half a percent not due to oil in Iran but due to the inflation data that we received in between the December summary projections and the March summary projections.","offset":641,"duration":27},{"text":"Governor Miran: That puts me at- that puts my my projection at about neutral, right? So the neutral policy rate is the monetary policy interest rate that's neither stimulative nor accommodative. Right now I think that's probably about two and a half percent. Uh, two and a half to to two and three quarters percent. We're about 75 basis points above that level.","offset":668,"duration":24},{"text":"Governor Miran: Uh, so you know I think it's- sorry, yeah we're about sorry, we're about a percentage point above that level right now. Uh, I think it's appropriate over the course of this year to just get back to neutral. I don't think the economy needs monetary policy to be slamming on the gas and and accelerating the economy uh like it was in 2021 or 2022.","offset":692,"duration":19},{"text":"Governor Miran: Um, but I also don't think it needs to be holding the economy back. And right now it is modestly restrictive and it is holding the economy back and and I don't think that's consistent with the macroeconomic backdrop.","offset":711,"duration":8}],"startTime":584},{"title":"AI, Demographics, and the Neutral Rate","summary":"Miran explores the competing forces that influence the long-term neutral interest rate (R-star). While the AI productivity boom pushes the rate higher, crashing population growth and an improving fiscal deficit exert strong downward pressure.","entries":[{"text":"Host: So earlier in there you mentioned this idea of a AI potential productivity boom and how it could be much more durable than something like a negative oil supply shock. And the first thing that comes to my mind there when I think about a durable shock like that is what is its potential impact on the long-term economic neutral rate or R Star? I'd be curious to hear about how what's your perspective on the more long-term forecasts of the neutral rate in light of such a potentially powerful shock positive shock such as the AI productivity boom.","offset":719,"duration":31},{"text":"Governor Miran: Yeah, so look, uh you know I think that the AI productivity boom um does unambiguously push the neutral rate higher. Uh however I think there's a lot of other countervailing factors that have been weighing on the neutral rate. And so it is the case that if if investing becomes more profitable over time, if investing becomes more productive over time, that raises the long-term neutral, you know, uh neutral rate of interest that you get on capital on investing.","offset":750,"duration":26},{"text":"Governor Miran: And that boost that boosts neutral, but there's other things that have been weighing on it. And one thing that I've been trying to draw attention to that's been weighing on it I think quite quite powerfully is the change in population growth. We lived through the biggest shocks to the population growth rate in both directions in certainly in my lifetime, probably in the lifetimes of many many folks in this room uh within the course of a few years.","offset":776,"duration":23},{"text":"Governor Miran: Right, we had a period of of massively growing population in 2021 to 2023 or so, and then in 2024 to five six uh that population growth plummeted pretty much to, you know, working age population growth is is probably, you know, pretty close to flat now.","offset":799,"duration":21},{"text":"Governor Miran: And so that was a huge spike up in growth and then a huge spike down. And just as the neutral interest rate is a function of the equilibrium returns in capital that are affected by productivity, it's also affected by the growth rate in the economy which is affected by uh population growth. And so that in my view is a is a very big thing weighing on interest rates.","offset":820,"duration":18},{"text":"Governor Miran: And you see that uh across the world. We spent many years before the pandemic discussing discussing Japanization of global interest rates. You know declining fertility rates, declining, you know aging populations around the world, declining population growth led to lower interest rates in a lot of countries.","offset":838,"duration":21},{"text":"Governor Miran: And we and there was a lot of time spent discussing is this is everybody going in this direction, right? I think that those channels, those pathways were always valid economic pathways and maybe they were they were of primary importance sort of before the pandemic and a lot of people were talking about them.","offset":859,"duration":16},{"text":"Governor Miran: And then during the pandemic, a lot of other things started to matter, mostly related to the pandemic and then the massive uh economic support programs that were launched after that. Um, but those the connection between population, aging, demographic growth, and interest rates didn't go away, right?","offset":875,"duration":16},{"text":"Governor Miran: It just, you know, other things occupied our attention but those pathways are still valid. And I think that we'll see in coming years that they they matter again because of the the size of the shocks that we've experienced to population growth. The other thing that I think weighs on the interest rate is the improving fiscal deficit.","offset":891,"duration":14},{"text":"Governor Miran: And so uh, you know I think that if you look at the fiscal deficit in Q2 through Q4 of last year versus the fiscal deficit of Q2 through Q4 of the previous year uh and of course I think the major Delta is the biggest delta is tariffs, it's not all tariffs but the biggest delta is tariffs.","offset":905,"duration":21},{"text":"Governor Miran: Um, the fiscal deficit came in quite a bit and at an annualized rate it's probably, if I remember correctly, about 450 but that 450 billion but um that's off the top of my head so that might not be correct. It's it's it's a significant decline if you look at Q2 through Q4 of 2025 calendar Q2 through Q4 of 2025 versus calendar Q2 through Q4 of 2024.","offset":926,"duration":26},{"text":"Governor Miran: And I think the major delta is tariffs, right? So that declining uh that decline in fiscal borrowing is something that pushes around the neutral rate too and that is something that I think will also weigh on it. So uh, you know so my view of the neutral rate is towards the bottom of the range of where my colleagues' view is if you look at the SEP but I'm not outside of the range.","offset":952,"duration":19}],"startTime":719},{"title":"Podcast Ad Break","summary":"A brief intermission featuring promotional spots for Arkham's crypto intelligence platform and Blockworks Investor Relations.","entries":[{"text":"Host: Before you place a trade, you should know who is actually moving the market. That's where Arkham comes in. Arkham is a crypto intelligence platform and exchange that lets you see real on-chain data: which wallets are buying, selling, and moving funds, and then trade directly on that information. Arkham was built to make blockchains human-readable. Instead of raw transaction data, you get clear profiles, visualizers, and custom dashboards that show what's really happening beneath the surface. Tracking wallets and fund flows is becoming just as important as technical or fundamental analysis. On-chain intelligence is also one of the best tools traders have to protect themselves against hacks, rugs, and scams. With Arkham exchange, you can go from insight to execution in one place. The world's first exchange powered by crypto intelligence. Check out Arkham and start trading with real on-chain insight at arkham.com.","offset":971,"duration":50},{"text":"Host: Hey all, Blockworks co-founder Michael Ippolito here. Quick break to talk about something we've just launched, Blockworks Investor Relations. As the market shifts toward institutional capital, investors want more transparency, more standardization, and a higher level of professionalism. But the traditional IR model is slow, manual, and not built for how crypto works. If you're building on-chain, your data is already live, your business is already transparent, the challenge is turning that into a clear, credible story for investors. That's exactly what we're solving with Blockworks IR. It's a single platform that brings together real-time analytics, branded investor portals, and hands-on advisory support so you can communicate what matters. If you're an on-chain business looking to level up your investor strategy, check out Blockworks Investor Relations at blockworks.co/investor-relations. Alright, back to the episode.","offset":1021,"duration":48}],"startTime":971},{"title":"Deregulation & the Output Gap","summary":"Critiquing the metaphor of 'running the economy hot,' Miran explains that expanding supply capacity via deregulation and capital deepening is like adding horsepower to a car. He explores how these supply-side policies alter potential GDP and allow demand to grow without triggering inflation.","entries":[{"text":"Host: So the other major durable trend you mentioned was this idea of deregulation. And just last week the Federal Reserve put out some initial asked for consultation on this update to the Federal Reserve's perspective on how it contributes to that, you know, update on deregulation. And I'm curious if you could just provide your perspective on that and how you're thinking about it.","offset":1069,"duration":23},{"text":"Governor Miran: So if you look if you take an economics class there's supply and demand, right? And if you hold supply constant and you slam your foot on the gas for demand and you push demand out, you get inflation. And if you push supply out, then you don't get inflation, you can produce more with less. And I think, you know one expression that that people online use a lot is running it hot, right?","offset":1092,"duration":29},{"text":"Governor Miran: I think that running it hot is you're sort of if you use that expression, you're conditioning upon what the engine is. And if you're trying to go 60 miles an hour in a car with a handful of horsepower, you know you're probably running it hot. But if you're trying to go 60 miles an hour in a car with a large number of horsepower, hundreds of horsepower, you're not running it hot, right?","offset":1121,"duration":21},{"text":"Governor Miran: That car can handle that speed. And this is the difference between pushing the supply side out versus restricting the supply side. If you push the supply side out of out of the economy and supply is growing quickly, then demand can grow quickly too and it's not inflationary. If you're holding the supply side in and and the economy can't produce supply to meet demand then you're going to get inflation.","offset":1142,"duration":21},{"text":"Governor Miran: And I think that's the difference and that's where things like AI and things like deregulation come into play is because they allow the economy to produce more with less. And that's also true of capital deepening. If you look at the incentives for investment uh that that were in part of the tax legislation last year, uh you know they full expensing on on full expensing on equipment and full expensing on R&D.","offset":1163,"duration":24},{"text":"Governor Miran: Uh these incentivize investment in productive capital. And when you have more productive capital you can produce more, right? And so I think it's all it's all a function of of so when you sort of say something like running it hot it's wildly imprecise because it's a statement that sort of assumes that supply is constant, that you can't increase the horsepower of the car.","offset":1187,"duration":17},{"text":"Governor Miran: But if you go through deregulation, if you go through AI, if you go through capital deepening, you're increasing the horsepower of the car and you can produce more with less and therefore demand can grow faster and the engine doesn't heat up when you go fast. So I think that that metaphor needs needs some adjustment.","offset":1204,"duration":14},{"text":"Governor Miran: But when I think about these supply side policies and their interaction with monetary policy, a lot of it flows through what we call- so there's there's two primary channels. One is what happens to prices, right? I talked a little bit about that with deregulation. If you can produce more with less, you have you lower the cost of production that feeds through into consumer prices.","offset":1218,"duration":23},{"text":"Governor Miran: If you're removing barriers to entry because regulations can serve as barriers to entry and I talked a lot about this in my January regulation speech, um you're creating more competition, more competition will lower prices, it will lower it will lower markups, it will lower monopoly profits. The other channel through which the through which I think a lot of the supply side stuff affects um things that we care about from monetary policy is through what we would call the output gap.","offset":1241,"duration":24},{"text":"Governor Miran: And the output gap is the difference between potential growth what the economy can produce uh with unemployment at its natural level and where actual output is. And so if you've got the unemployment rate at 8% there's tons of unused slack in the economy, there's tons of unused resources, the economy is producing below potential, there's a lot more it can produce.","offset":1265,"duration":23},{"text":"Governor Miran: If you've got the unemployment rate at 3%, you're above potential because you're trying to produce more than the economy can produce in a non-inflationary way and you get price pressures as a result. Now what matters when you think about shocks to the supply side, whether they're AI, oil, regulation, no matter what the shock is what matters when you think about this is is it pushing out or pulling in actual supply or potential supply or actual GDP or potential GDP by more or less?","offset":1288,"duration":31},{"text":"Governor Miran: And so if you have a situation like uh you know and one assumption that a lot of people make is that actual and potential move out by roughly the same amount in response to a lot of these productivity shocks. There are times when I think that that's a good assumption. And so for example if you think about uh the Greenspan productivity story in the 90s where uh former chairman Greenspan was making uh was making the case that improvements in productivity were going to lead to high GDP growth that was non-inflationary.","offset":1319,"duration":34},{"text":"Governor Miran: And therefore policy doesn't really need to respond. Now I think that argument I think makes a lot of sense in the context of the telecoms revolution because if you're building lots of telecom capacity, you have to tear up streets, lay telecom wire, put the streets back together, there's a lot of investment activity that occurs.","offset":1353,"duration":19},{"text":"Governor Miran: And so you get the increase in demand because of the investment activity and you get the increase in supply because you have a productivity enhancement from the from the increased internet connectivity. The net change in the output gap, I think it's a fair assumption to assume it could be zero- sorry, it could be neutral. Uh, with other type of shocks that might not be the case.","offset":1372,"duration":20},{"text":"Governor Miran: Certainly with the case of a regulation shock, I think I think that actual- I think that actual GDP will move out by a lot less than potential GDP. So for example if you've got a smokestack that you can run 8 hours a day with strict carbon regulations and then the carbon regulations ease and you can run it 16 hours a day, you don't need to do additional investment because you've got the capital stock already there.","offset":1392,"duration":24},{"text":"Governor Miran: You've got the smokestack, it's just that you can run the smokestack more hours a day. And so that's a case in which potential GDP goes up I think by a lot more than actual GDP. The amount of supply you can produce has gone up by a lot but the amount of demand has not gone up by a lot because all you've done is ease ease production constraints, you haven't increased a lot of investment demand.","offset":1416,"duration":18},{"text":"Governor Miran: AI, I don't know. Uh AI could be somewhere in between. So certainly AI creates a huge amount of investment demand in the form of uh you know GPUs in data you know in data centers. A lot of the GPU demand I think gets leaked overseas. You know a lot of the GPUs are not they're not made in the United States, right? Uh certainly data center demand does lead to investment activity in the United States.","offset":1434,"duration":25},{"text":"Governor Miran: Uh certainly we pay a lot of of of employee compensation to people who are working on on developing AI, integrating AI into into existing company workstreams. Um but where does it shake out on potential GDP versus actual GDP? I don't really have a a firm view.","offset":1459,"duration":18}],"startTime":1069},{"title":"Skinny Master Accounts & Stablecoins","summary":"Transitioning to digital assets, Miran shares his views on skinny master accounts and the immense potential for stablecoins to serve global populations. He notes that providing unbanked or highly restricted regions with access to dollar savings could create a new global savings glut.","entries":[{"text":"Host: So I want to shift gears here into the heart of what we're truly here for this conference, which is digital assets and and your perspective on them. And I want to start with this introduction of these skinny master accounts that have been begun rolling out, we've seen Kraken get approved for one. And so I would just love to get your perspective on how you think about the role of these skinny master accounts with respect to where it sits in comparison to a full-fledged master account.","offset":1477,"duration":25},{"text":"Governor Miran: Sure, so this this ties into the previous conversation nicely because we were talking about productivity growth and we were talking about technological advancements. And if you look over the very very long term of human history, it is technological advancements that drive all of all of the growth in human prosperity that we've experienced.","offset":1502,"duration":16},{"text":"Governor Miran: Um, and I do and and I think that's true of a wide variety of technological advances and I think that financial innovation is an important part of that. Because financial innovation and and advances in financial technology and financial capabilities help to allocate capital to where it needs to be to make the economy produce efficiently, produce more and and generally drive human prosperity.","offset":1518,"duration":22},{"text":"Governor Miran: So I do think that financial innovation is important too. Um, I think that introducing these skinny master accounts for stablecoins will be uh will be an important step uh in the direction of of allowing that type of innovation to occur. The Federal Reserve recently put out a request for information for comments on skinny master accounts and we received a large volume of these comments.","offset":1540,"duration":27},{"text":"Governor Miran: The staff are going through the comments now. Uh, I've I've I've looked at a few of them a few of the comments. Some of things that stuck out at me were things like ACH access and um caps on and and caps on the the balances uh the size of the of the skinny master accounts. Um but this is an area of of this is an area of of active examination and and active rulemaking.","offset":1567,"duration":23},{"text":"Governor Miran: And so you know it is it is something that is moving ahead. I'm excited for Governor Waller who leads the payments committee to put uh to sort of to push this to next steps and and I think it's got a lot of potential.","offset":1590,"duration":11},{"text":"Host: The other big trend that we're seeing is of course around stablecoins. You had a landmark speech about stablecoins recently. And I would love to just hear about how you're evolving your thinking there and its role within the broader financial system, where you see it being incorporated, where you see think it complements what already exists there and yeah just how you're thinking about that.","offset":1601,"duration":20},{"text":"Governor Miran: Thanks, so I gave a speech in November, I think. About stablecoins. And and you know I I made a couple of arguments about stablecoins in that speech. Um the major argument that I made was that if you've got uh G-SAX compliant stablecoins, um they help you they help facilitate digital payments.","offset":1621,"duration":28},{"text":"Governor Miran: But from a savings pool of capital perspective in the United States, in Europe, in places that already have access to dollar denominated savings accounts, dollar denominated money market funds, treasury bills, if you have a system with with open capital- and open capital markets, from a savings perspective stablecoins don't I think add as much.","offset":1649,"duration":26},{"text":"Governor Miran: From a payments perspective they do because they're facilitating digital payments. But if you've got a huge pool of capital, I don't know that stablecoins are adding are adding that much. Now that's not true in places with capital controls and it's not true in places where the banking system struggles to penetrate because of geography or development, right?","offset":1675,"duration":21},{"text":"Governor Miran: And so you've got large parts of the world where people are living behind capital controls where if they wanted access to dollar savings instruments like dollar deposits, treasury bills, money market funds, they don't have access- they they don't have the capacity to do so because the country they're living in, the law is you just can't move your money into dollars, we're not going to let you.","offset":1696,"duration":18},{"text":"Governor Miran: And it doesn't matter how bad the people want access to dollars, they're just not allowed to. There are other parts of the world where it's very rural and there may not be banking services. And maybe people have a cell phone and so they, you know have a satellite link on their cell phone but they have no access to actual banking banking services.","offset":1714,"duration":17},{"text":"Governor Miran: Or the banking services in the country are too unreliable and volatile and or there maybe too much inflation and they don't want to use the banking services. So my perspective is that is that I'm very optimistic about stablecoin growth. But I think that a lot of the stablecoin uptake is actually going to come from large volumes of money that want to be denominated in dollars, that want to sit in dollars, and are currently unable to sit in dollars, right?","offset":1731,"duration":30},{"text":"Governor Miran: Huge pools of savings that have no other way of getting into the into the dollar system suddenly there's a way of doing it. And of course you still need to get onto the crypto ecosystem to do that so there is still an entry wheel issue but I think it makes the- I think it makes the problem easier. And I I sort of think of it a bit like, you know a ride-share app sort of being a new technology that broke up the monopoly of a taxicab medallion.","offset":1761,"duration":23},{"text":"Governor Miran: It's that type of thing that sort of that creates that ability to sort of start circumventing barriers to dollar deposits that people didn't have access to before. Now of course tying this back to neutral rate that we were discussing before, if you have huge inflows from the rest of the world into US dollar denominated savings, that's going to weigh on the neutral rate, right?","offset":1784,"duration":19},{"text":"Governor Miran: This is what happened in the late 90s and early 2000s, uh what former chairman Ben Bernanke called the global savings glut. Um if we hit the more optimistic projections of stablecoin growth, you could be looking at at magnitudes that are that are, you know maybe not quite as big as the global savings glut but let's say half as big.","offset":1803,"duration":20},{"text":"Governor Miran: So you know there is the scope for these to matter uh you know very substantially for monetary policy as well, which of course would be a very, you know which would be a very powerful force weighing on interest rates, keeping them lower.","offset":1823,"duration":12}],"startTime":1477},{"title":"Tokenized Deposits & Parting Advice","summary":"Miran briefly shares his initial impressions of tokenized deposits as an incremental improvement to banking. He concludes by encouraging crypto innovators to actively participate in regulatory comment periods to help shape more efficient rules.","entries":[{"text":"Host: Yeah, I completely agree that I I think a lot about stablecoins as being this this huge tailwind for the rest of the world to be able to gain entry to the dollar system. I'm curious how do you think about the other side of the equation, which I think goes understated, which is tokenized deposits? What do you think about those?","offset":1835,"duration":16},{"text":"Governor Miran: Yeah, so tokenized deposits strike me as a and to be clear I have not made a I have not made an extensive study of tokenized deposits in particular, but what I know about them, which is probably less than you do, um is that they strike me as an improve- an improvement on services that are already being offered by banks, right?","offset":1851,"duration":22},{"text":"Governor Miran: Um, is that something that um is that something that ultimately ends up revolutionizing the banking system? Um, I don't know, but this tokenized deposits strike me as as, you know another step in a long line of improving the financial services that that banks offer um by by utilizing technology. But I haven't made an extensive study of it and I would be open to changing my mind based on things you tell me.","offset":1873,"duration":27},{"text":"Host: Yeah we'll have to have you back again for another conversation on that one but about that. Um just for for the folks out there who are core to the crypto industry and you know potential founders etc that are working towards this this huge, you know tailwind that is going on of financial innovation, we'd just love to hear any sort of parting words to those that are trying to build and innovate in the space in in the US financial system of, yeah just your final words to them.","offset":1900,"duration":25},{"text":"Governor Miran: Uh so I'll repeat what I said before which is that innovation is the driver is the main driver of long-run human prosperity. So if you are working on innovation thank you, um for for doing what you do. Um and with respect to issues in payments and payments technologies, you know when the Federal Reserve makes policy we we follow the Administrative Procedure Act which is what all regulatory agencies have to do and we issue uh we issue, you know sort of notices of proposed rulemaking, we issue requests for information.","offset":1925,"duration":36},{"text":"Governor Miran: Respond to those, give us comments. You know we we search for comments from industry, from stakeholders, from innovators so that we can know whether the regulations are doing the job that they are supposed to or where they need to be pushed or pulled to get them into a place to make the economy more efficient. So you know we we put out these notices, um you know let us let us know what need- you know let us know what needs changed to make the economy more efficient.","offset":1961,"duration":20},{"text":"Host: Incredible. Well uh can't thank you enough for coming here and talking at the Digital Assets Summit Governor Miran, that was incredible. Thank you.","offset":1981,"duration":10},{"text":"Governor Miran: Thanks for having me.","offset":1991,"duration":15}],"startTime":1835}],"entries":[{"text":"Governor Miran: Oil moving higher now has very little inflationary consequence 12 to 18 months out, all the inflation happens up front. And so that's part of why a central bank should look through an oil shock as the Federal Reserve has historically done.","offset":0,"duration":11},{"text":"Governor Miran: Forward inflation expectations a year out, two years out, three years out are all pretty much unaffected by what's been going on and in fact a lot of them are lower since the FOMC met in January.","offset":11,"duration":10},{"text":"Governor Miran: My view is that the economy can bear additional support for the labor market from monetary policy. With the labor market very gradually cooling and declining wage pressures, you just are not going to get a wage price spiral that a central bank would normally respond to.","offset":21,"duration":13},{"text":"Governor Miran: When you start to say something like running it hot, it's wildly imprecise because it's a statement that sort of assumes that supply is constant, that you can't increase the horsepower of the car.","offset":34,"duration":9},{"text":"Governor Miran: I don't think the economy needs monetary policy to be slamming on the gas and accelerating the economy like it was in 2021 or 2022, but I also don't think it needs to be holding the economy back. And right now it is modestly restrictive and it is holding the economy back and I don't think that's consistent with the macroeconomic backdrop.","offset":43,"duration":16},{"text":"Governor Miran: What matters when you think about shocks to the supply side, whether they're AI, oil, regulation, no matter what the shock is what matters when you think about this is-","offset":59,"duration":11},{"text":"Narrator: Nothing said on Forward Guidance is a recommendation to buy or sell any investments or products. This podcast is for informational purposes only, and the views expressed by anyone on the show are solely their opinions, not financial advice or necessarily the views of Blockworks. Our hosts, guests, and the Blockworks team may hold positions in the companies, funds, or projects discussed. As always, investments in blockchain technology involve risk. Terms and conditions apply. Do your own research.","offset":70,"duration":27},{"text":"Host: Governor Miran, great to have you to the Digital Summit. Welcome.","offset":97,"duration":9},{"text":"Governor Miran: Thanks for having me and let me just clarify that I'm one member of a Board of seven governors, there are seven of us. I'm not a governor in the sense of a governor of the Bank of England or something like that.","offset":106,"duration":10},{"text":"Host: That's a good clear, hey Governor. Governor Miran, would love to just start by unpacking the most recent FOMC meeting that occurred last week. You dissented in support of a 25 basis rate cut, so I'd just love for you to unpack your current framework and why you dissented there.","offset":116,"duration":16},{"text":"Governor Miran: Sure, thanks. Look, you know at the Federal Reserve we have a dual mandate. We are tasked by Congress with paying attention to inflation, stable prices, and to the labor market. My view is that the inflation side of the mandate has, despite high measured inflation, has not been so problematic.","offset":132,"duration":17},{"text":"Governor Miran: Because a lot of the inflation excess over target has been as a result of some quirks of measurement of things like portfolio management services, which is basically just the stock market going up, biasing the way we measure inflation by 30 to 40 basis points.","offset":149,"duration":15},{"text":"Governor Miran: Once you correct for those things, I do not view inflation as being overly problematic, whereas the labor market has been on a very gradual trend of weakening over the course of the last three years. That trend has been in place, it's been continual, you see it in increasing difficulty of finding jobs for new entrants to the labor market.","offset":164,"duration":16},{"text":"Governor Miran: You see it in increasing length of time and people spend between jobs during unemployment. And so my view is that the economy can bear additional support for the labor market from monetary policy. Now a lot of what's been going on in the last few weeks is of course been tied to the war in Iran.","offset":180,"duration":17},{"text":"Governor Miran: And I think what's going on in oil prices has spooked a lot of people. Uh, you know, and I understand from a trading perspective, from a markets perspective, things whip around wildly in both directions, you get headline ping-pong and that pushes markets. And if you have leveraged positions, that can feel very, uh, you know, sort of very intense.","offset":197,"duration":16},{"text":"Governor Miran: But from a monetary policy perspective, we have to make policy for 12 to 18 months from now because there are big lags with which monetary policy hits the economy. If we adjust interest rates, it doesn't feed through into actual economic growth into actual unemployment and inflation for at least a year.","offset":213,"duration":19},{"text":"Governor Miran: So we need to set policy for a year, to a year and a half out. And the way that changes in oil prices affect the economy is actually much faster than that. When you get a spike up in oil prices, when you get a move higher in oil from something like what's going on in Iran, the oil price goes up immediately and headline inflation goes up a lot in the short term.","offset":232,"duration":20},{"text":"Governor Miran: But as you look a year, two year, a year and a half out, it's very unlikely that that causes subsequent effects that are affecting the economy a year, two year, a year and a half out, which is when monetary policy can affect the economy. And so that's part of why the classic reasoning of why a central bank should look through an oil shock as the Federal Reserve has historically done.","offset":252,"duration":16},{"text":"Host: So that idea of looking through an oil shock was something that's really come forth in terms of recent discussions here. It seems like every few years we have some sort of shock that we have to navigate through. And I'm curious if you could just unpack it, you know, the discussion seems to be that a lot of these supply shocks seem to go in one direction, one being higher inflation. How do you think about that?","offset":268,"duration":24},{"text":"Governor Miran: Yeah, so I'll say a couple things. Uh, one is when you think about how these negative supply shocks are hitting the economy, things like oil prices moving higher, uh, as I said before it affects headline inflation very much in the short term but as you look further out it doesn't affect anything.","offset":292,"duration":15},{"text":"Governor Miran: And that is if you were to get concerned about these negative supply shocks, that's what you would be looking for. You'd be looking for a rise in inflation expectations further out in time. And if you look at the inflation swap market, you see that forward inflation expectations a year out, two years out, three years out are all pretty much unaffected by what's been going on.","offset":307,"duration":20},{"text":"Governor Miran: And in fact a lot of them are lower since the start of since- sorry, a lot of them are lower since we met in January, since the FOMC met in January. And so there's been zero bleed through of the of the negative supply shock of oil prices into inflation expectations further out, uh, you know sort of further out in time which which again is when monetary policy would be able to affect.","offset":327,"duration":19},{"text":"Governor Miran: The other thing you'd be concerned about is if there were a wage price spiral. If prices go higher and then wages go higher and that pushes prices higher again, you get a negative feedback loop that just creates a self-fulfilling inflationary spiral that requires tightening from the monetary, uh, authority to offset and to and to squash.","offset":346,"duration":19},{"text":"Governor Miran: That's not something that we see happening right now because the labor market, as I said before, has been on this very gradual cooling trend for about three for about three years now. And with the labor market very gradually cooling and declining wage pressures, you just are not going to get a wage price spiral that would be the type of thing that would get- that a that a central bank would normally respond to.","offset":365,"duration":24},{"text":"Governor Miran: Now you said something else that I'd like to pick up on, which is that a lot of we've had a lot of negative supply shocks, uh, you know sort of over time. And I think that there's a tendency to think that they that those are the only supply shocks that we've that we've experienced. And that's not the case. There are also positive supply shocks that are hitting the economy too.","offset":389,"duration":19},{"text":"Governor Miran: And these get a lot of attention too. So one of them is AI, right? AI is a positive supply shock, it increases the productive capacity of the economy, it lets people produce more with less inputs into production. That's a positive supply shock. Another very powerful positive supply shock that's been hitting the economy has been the trend in deregulation.","offset":408,"duration":20},{"text":"Governor Miran: Now I think this is a- this is a group of people who are focused on crypto, regulations have probably played a large part in a number of your business models. And having to deal with those regulations has probably for a number of people in this room at some point slowed you down, reduced the amount of things you can produce, increased the cost of production.","offset":428,"duration":14},{"text":"Governor Miran: And as those regulatory barriers recede, it becomes easier for you to make products that people want to buy. And so as the regulatory, as the regulatory backdrop becomes easier, that's a positive supply shock that hits the economy too. Now I gave a speech in January in Greece where I looked at the literature, the modern literature on regulation and it's very difficult to sort of quantify the federal regulatory code and turn that into a number in a way that economists would like to do rigorous empirical studies.","offset":442,"duration":31},{"text":"Governor Miran: But I looked at the modern literature that sort of uses AI and machine learning tools to do so. And I calculated that the deregulatory wave that's been hitting the economy over the last 15 months or so would ultimately drag on inflation by about half a percent a year for the next few years, right?","offset":473,"duration":18},{"text":"Governor Miran: So that's that's that's quite chunky. Now just a couple of weeks ago, there was a new Federal Reserve staff research paper released by two staff economists at the Fed, uh, Danilo, um, uh, Cascaldi Garcia and Matteo Iacoviello. And what this Fed research paper on deregulation uh found is they they did a they did a entirely different estimation method than the previous literature and they did an entirely different measurement method for regulations than the previous literature.","offset":491,"duration":33},{"text":"Governor Miran: And when you apply their results to the scope of the deregulatory shock that we've seen over the last 15 months or so, it implies a roughly uh 0.3% drag on inflation each year for the next few years, right? So that's not just a one-off effect, that's a persistent uh disinflationary effect from the receding regulatory backdrop.","offset":524,"duration":19},{"text":"Governor Miran: Now using an entirely different literature, entirely different estimation methods, I calculated 0.5, they calculated 0.3. I think those are probably within noise of each other, they're certainly within confidence bands, I wouldn't be able to reject one in favor of the other. But either of them are very big and I think very substantial and of the types of shocks that policymakers ought to take into account when we're thinking about the correct settings for monetary policy.","offset":543,"duration":22},{"text":"Governor Miran: So yes, it is the case that we have had a number of negative supply shocks hit the economy, things like oil moving higher. Um, but it's also the case that we have very powerful positive supply shocks hitting the economy too. And unlike oil, I expect some of these, like deregulation and AI, to be persistent in their disinflationary effects.","offset":565,"duration":19},{"text":"Host: So last week's meeting was a summary of economic projections update meeting. I would love to just hear about when you balance out the context of either these positive or negative supply shocks, how does that characterize your forecast for the federal funds rate for the next year?","offset":584,"duration":18},{"text":"Governor Miran: So in the last uh summary of projections, because of the oil shock, right, that hits the economy very quickly whereas I think some of these other shocks play out over time, I did raise my inflation projection for my headline inflation projection for this year to 2.7%, right?","offset":602,"duration":17},{"text":"Governor Miran: So I moved it a little bit higher because of the oil shock. However, as I said before, this is not the type of thing that policy should respond to because that happens all up front and policy affects the economy 12 to 18 months out. It has very oil moving higher now has very little inflationary consequence 12 to 18 months out, all the inflation happens up front.","offset":619,"duration":22},{"text":"Governor Miran: What does happen 12 to 18 months out is the economy might be weaker because the because every dollar that people put into, you know filling their gas tanks is a dollar they're not spending on other goods and services. And so that might put upward pressure on the unemployment rate. So in the the March summary of economic projections, I boosted my policy rate by half a percent not due to oil in Iran but due to the inflation data that we received in between the December summary projections and the March summary projections.","offset":641,"duration":27},{"text":"Governor Miran: That puts me at- that puts my my projection at about neutral, right? So the neutral policy rate is the monetary policy interest rate that's neither stimulative nor accommodative. Right now I think that's probably about two and a half percent. Uh, two and a half to to two and three quarters percent. We're about 75 basis points above that level.","offset":668,"duration":24},{"text":"Governor Miran: Uh, so you know I think it's- sorry, yeah we're about sorry, we're about a percentage point above that level right now. Uh, I think it's appropriate over the course of this year to just get back to neutral. I don't think the economy needs monetary policy to be slamming on the gas and and accelerating the economy uh like it was in 2021 or 2022.","offset":692,"duration":19},{"text":"Governor Miran: Um, but I also don't think it needs to be holding the economy back. And right now it is modestly restrictive and it is holding the economy back and and I don't think that's consistent with the macroeconomic backdrop.","offset":711,"duration":8},{"text":"Host: So earlier in there you mentioned this idea of a AI potential productivity boom and how it could be much more durable than something like a negative oil supply shock. And the first thing that comes to my mind there when I think about a durable shock like that is what is its potential impact on the long-term economic neutral rate or R Star? I'd be curious to hear about how what's your perspective on the more long-term forecasts of the neutral rate in light of such a potentially powerful shock positive shock such as the AI productivity boom.","offset":719,"duration":31},{"text":"Governor Miran: Yeah, so look, uh you know I think that the AI productivity boom um does unambiguously push the neutral rate higher. Uh however I think there's a lot of other countervailing factors that have been weighing on the neutral rate. And so it is the case that if if investing becomes more profitable over time, if investing becomes more productive over time, that raises the long-term neutral, you know, uh neutral rate of interest that you get on capital on investing.","offset":750,"duration":26},{"text":"Governor Miran: And that boost that boosts neutral, but there's other things that have been weighing on it. And one thing that I've been trying to draw attention to that's been weighing on it I think quite quite powerfully is the change in population growth. We lived through the biggest shocks to the population growth rate in both directions in certainly in my lifetime, probably in the lifetimes of many many folks in this room uh within the course of a few years.","offset":776,"duration":23},{"text":"Governor Miran: Right, we had a period of of massively growing population in 2021 to 2023 or so, and then in 2024 to five six uh that population growth plummeted pretty much to, you know, working age population growth is is probably, you know, pretty close to flat now.","offset":799,"duration":21},{"text":"Governor Miran: And so that was a huge spike up in growth and then a huge spike down. And just as the neutral interest rate is a function of the equilibrium returns in capital that are affected by productivity, it's also affected by the growth rate in the economy which is affected by uh population growth. And so that in my view is a is a very big thing weighing on interest rates.","offset":820,"duration":18},{"text":"Governor Miran: And you see that uh across the world. We spent many years before the pandemic discussing discussing Japanization of global interest rates. You know declining fertility rates, declining, you know aging populations around the world, declining population growth led to lower interest rates in a lot of countries.","offset":838,"duration":21},{"text":"Governor Miran: And we and there was a lot of time spent discussing is this is everybody going in this direction, right? I think that those channels, those pathways were always valid economic pathways and maybe they were they were of primary importance sort of before the pandemic and a lot of people were talking about them.","offset":859,"duration":16},{"text":"Governor Miran: And then during the pandemic, a lot of other things started to matter, mostly related to the pandemic and then the massive uh economic support programs that were launched after that. Um, but those the connection between population, aging, demographic growth, and interest rates didn't go away, right?","offset":875,"duration":16},{"text":"Governor Miran: It just, you know, other things occupied our attention but those pathways are still valid. And I think that we'll see in coming years that they they matter again because of the the size of the shocks that we've experienced to population growth. The other thing that I think weighs on the interest rate is the improving fiscal deficit.","offset":891,"duration":14},{"text":"Governor Miran: And so uh, you know I think that if you look at the fiscal deficit in Q2 through Q4 of last year versus the fiscal deficit of Q2 through Q4 of the previous year uh and of course I think the major Delta is the biggest delta is tariffs, it's not all tariffs but the biggest delta is tariffs.","offset":905,"duration":21},{"text":"Governor Miran: Um, the fiscal deficit came in quite a bit and at an annualized rate it's probably, if I remember correctly, about 450 but that 450 billion but um that's off the top of my head so that might not be correct. It's it's it's a significant decline if you look at Q2 through Q4 of 2025 calendar Q2 through Q4 of 2025 versus calendar Q2 through Q4 of 2024.","offset":926,"duration":26},{"text":"Governor Miran: And I think the major delta is tariffs, right? So that declining uh that decline in fiscal borrowing is something that pushes around the neutral rate too and that is something that I think will also weigh on it. So uh, you know so my view of the neutral rate is towards the bottom of the range of where my colleagues' view is if you look at the SEP but I'm not outside of the range.","offset":952,"duration":19},{"text":"Host: Before you place a trade, you should know who is actually moving the market. That's where Arkham comes in. Arkham is a crypto intelligence platform and exchange that lets you see real on-chain data: which wallets are buying, selling, and moving funds, and then trade directly on that information. Arkham was built to make blockchains human-readable. Instead of raw transaction data, you get clear profiles, visualizers, and custom dashboards that show what's really happening beneath the surface. Tracking wallets and fund flows is becoming just as important as technical or fundamental analysis. On-chain intelligence is also one of the best tools traders have to protect themselves against hacks, rugs, and scams. With Arkham exchange, you can go from insight to execution in one place. The world's first exchange powered by crypto intelligence. Check out Arkham and start trading with real on-chain insight at arkham.com.","offset":971,"duration":50},{"text":"Host: Hey all, Blockworks co-founder Michael Ippolito here. Quick break to talk about something we've just launched, Blockworks Investor Relations. As the market shifts toward institutional capital, investors want more transparency, more standardization, and a higher level of professionalism. But the traditional IR model is slow, manual, and not built for how crypto works. If you're building on-chain, your data is already live, your business is already transparent, the challenge is turning that into a clear, credible story for investors. That's exactly what we're solving with Blockworks IR. It's a single platform that brings together real-time analytics, branded investor portals, and hands-on advisory support so you can communicate what matters. If you're an on-chain business looking to level up your investor strategy, check out Blockworks Investor Relations at blockworks.co/investor-relations. Alright, back to the episode.","offset":1021,"duration":48},{"text":"Host: So the other major durable trend you mentioned was this idea of deregulation. And just last week the Federal Reserve put out some initial asked for consultation on this update to the Federal Reserve's perspective on how it contributes to that, you know, update on deregulation. And I'm curious if you could just provide your perspective on that and how you're thinking about it.","offset":1069,"duration":23},{"text":"Governor Miran: So if you look if you take an economics class there's supply and demand, right? And if you hold supply constant and you slam your foot on the gas for demand and you push demand out, you get inflation. And if you push supply out, then you don't get inflation, you can produce more with less. And I think, you know one expression that that people online use a lot is running it hot, right?","offset":1092,"duration":29},{"text":"Governor Miran: I think that running it hot is you're sort of if you use that expression, you're conditioning upon what the engine is. And if you're trying to go 60 miles an hour in a car with a handful of horsepower, you know you're probably running it hot. But if you're trying to go 60 miles an hour in a car with a large number of horsepower, hundreds of horsepower, you're not running it hot, right?","offset":1121,"duration":21},{"text":"Governor Miran: That car can handle that speed. And this is the difference between pushing the supply side out versus restricting the supply side. If you push the supply side out of out of the economy and supply is growing quickly, then demand can grow quickly too and it's not inflationary. If you're holding the supply side in and and the economy can't produce supply to meet demand then you're going to get inflation.","offset":1142,"duration":21},{"text":"Governor Miran: And I think that's the difference and that's where things like AI and things like deregulation come into play is because they allow the economy to produce more with less. And that's also true of capital deepening. If you look at the incentives for investment uh that that were in part of the tax legislation last year, uh you know they full expensing on on full expensing on equipment and full expensing on R&D.","offset":1163,"duration":24},{"text":"Governor Miran: Uh these incentivize investment in productive capital. And when you have more productive capital you can produce more, right? And so I think it's all it's all a function of of so when you sort of say something like running it hot it's wildly imprecise because it's a statement that sort of assumes that supply is constant, that you can't increase the horsepower of the car.","offset":1187,"duration":17},{"text":"Governor Miran: But if you go through deregulation, if you go through AI, if you go through capital deepening, you're increasing the horsepower of the car and you can produce more with less and therefore demand can grow faster and the engine doesn't heat up when you go fast. So I think that that metaphor needs needs some adjustment.","offset":1204,"duration":14},{"text":"Governor Miran: But when I think about these supply side policies and their interaction with monetary policy, a lot of it flows through what we call- so there's there's two primary channels. One is what happens to prices, right? I talked a little bit about that with deregulation. If you can produce more with less, you have you lower the cost of production that feeds through into consumer prices.","offset":1218,"duration":23},{"text":"Governor Miran: If you're removing barriers to entry because regulations can serve as barriers to entry and I talked a lot about this in my January regulation speech, um you're creating more competition, more competition will lower prices, it will lower it will lower markups, it will lower monopoly profits. The other channel through which the through which I think a lot of the supply side stuff affects um things that we care about from monetary policy is through what we would call the output gap.","offset":1241,"duration":24},{"text":"Governor Miran: And the output gap is the difference between potential growth what the economy can produce uh with unemployment at its natural level and where actual output is. And so if you've got the unemployment rate at 8% there's tons of unused slack in the economy, there's tons of unused resources, the economy is producing below potential, there's a lot more it can produce.","offset":1265,"duration":23},{"text":"Governor Miran: If you've got the unemployment rate at 3%, you're above potential because you're trying to produce more than the economy can produce in a non-inflationary way and you get price pressures as a result. Now what matters when you think about shocks to the supply side, whether they're AI, oil, regulation, no matter what the shock is what matters when you think about this is is it pushing out or pulling in actual supply or potential supply or actual GDP or potential GDP by more or less?","offset":1288,"duration":31},{"text":"Governor Miran: And so if you have a situation like uh you know and one assumption that a lot of people make is that actual and potential move out by roughly the same amount in response to a lot of these productivity shocks. There are times when I think that that's a good assumption. And so for example if you think about uh the Greenspan productivity story in the 90s where uh former chairman Greenspan was making uh was making the case that improvements in productivity were going to lead to high GDP growth that was non-inflationary.","offset":1319,"duration":34},{"text":"Governor Miran: And therefore policy doesn't really need to respond. Now I think that argument I think makes a lot of sense in the context of the telecoms revolution because if you're building lots of telecom capacity, you have to tear up streets, lay telecom wire, put the streets back together, there's a lot of investment activity that occurs.","offset":1353,"duration":19},{"text":"Governor Miran: And so you get the increase in demand because of the investment activity and you get the increase in supply because you have a productivity enhancement from the from the increased internet connectivity. The net change in the output gap, I think it's a fair assumption to assume it could be zero- sorry, it could be neutral. Uh, with other type of shocks that might not be the case.","offset":1372,"duration":20},{"text":"Governor Miran: Certainly with the case of a regulation shock, I think I think that actual- I think that actual GDP will move out by a lot less than potential GDP. So for example if you've got a smokestack that you can run 8 hours a day with strict carbon regulations and then the carbon regulations ease and you can run it 16 hours a day, you don't need to do additional investment because you've got the capital stock already there.","offset":1392,"duration":24},{"text":"Governor Miran: You've got the smokestack, it's just that you can run the smokestack more hours a day. And so that's a case in which potential GDP goes up I think by a lot more than actual GDP. The amount of supply you can produce has gone up by a lot but the amount of demand has not gone up by a lot because all you've done is ease ease production constraints, you haven't increased a lot of investment demand.","offset":1416,"duration":18},{"text":"Governor Miran: AI, I don't know. Uh AI could be somewhere in between. So certainly AI creates a huge amount of investment demand in the form of uh you know GPUs in data you know in data centers. A lot of the GPU demand I think gets leaked overseas. You know a lot of the GPUs are not they're not made in the United States, right? Uh certainly data center demand does lead to investment activity in the United States.","offset":1434,"duration":25},{"text":"Governor Miran: Uh certainly we pay a lot of of of employee compensation to people who are working on on developing AI, integrating AI into into existing company workstreams. Um but where does it shake out on potential GDP versus actual GDP? I don't really have a a firm view.","offset":1459,"duration":18},{"text":"Host: So I want to shift gears here into the heart of what we're truly here for this conference, which is digital assets and and your perspective on them. And I want to start with this introduction of these skinny master accounts that have been begun rolling out, we've seen Kraken get approved for one. And so I would just love to get your perspective on how you think about the role of these skinny master accounts with respect to where it sits in comparison to a full-fledged master account.","offset":1477,"duration":25},{"text":"Governor Miran: Sure, so this this ties into the previous conversation nicely because we were talking about productivity growth and we were talking about technological advancements. And if you look over the very very long term of human history, it is technological advancements that drive all of all of the growth in human prosperity that we've experienced.","offset":1502,"duration":16},{"text":"Governor Miran: Um, and I do and and I think that's true of a wide variety of technological advances and I think that financial innovation is an important part of that. Because financial innovation and and advances in financial technology and financial capabilities help to allocate capital to where it needs to be to make the economy produce efficiently, produce more and and generally drive human prosperity.","offset":1518,"duration":22},{"text":"Governor Miran: So I do think that financial innovation is important too. Um, I think that introducing these skinny master accounts for stablecoins will be uh will be an important step uh in the direction of of allowing that type of innovation to occur. The Federal Reserve recently put out a request for information for comments on skinny master accounts and we received a large volume of these comments.","offset":1540,"duration":27},{"text":"Governor Miran: The staff are going through the comments now. Uh, I've I've I've looked at a few of them a few of the comments. Some of things that stuck out at me were things like ACH access and um caps on and and caps on the the balances uh the size of the of the skinny master accounts. Um but this is an area of of this is an area of of active examination and and active rulemaking.","offset":1567,"duration":23},{"text":"Governor Miran: And so you know it is it is something that is moving ahead. I'm excited for Governor Waller who leads the payments committee to put uh to sort of to push this to next steps and and I think it's got a lot of potential.","offset":1590,"duration":11},{"text":"Host: The other big trend that we're seeing is of course around stablecoins. You had a landmark speech about stablecoins recently. And I would love to just hear about how you're evolving your thinking there and its role within the broader financial system, where you see it being incorporated, where you see think it complements what already exists there and yeah just how you're thinking about that.","offset":1601,"duration":20},{"text":"Governor Miran: Thanks, so I gave a speech in November, I think. About stablecoins. And and you know I I made a couple of arguments about stablecoins in that speech. Um the major argument that I made was that if you've got uh G-SAX compliant stablecoins, um they help you they help facilitate digital payments.","offset":1621,"duration":28},{"text":"Governor Miran: But from a savings pool of capital perspective in the United States, in Europe, in places that already have access to dollar denominated savings accounts, dollar denominated money market funds, treasury bills, if you have a system with with open capital- and open capital markets, from a savings perspective stablecoins don't I think add as much.","offset":1649,"duration":26},{"text":"Governor Miran: From a payments perspective they do because they're facilitating digital payments. But if you've got a huge pool of capital, I don't know that stablecoins are adding are adding that much. Now that's not true in places with capital controls and it's not true in places where the banking system struggles to penetrate because of geography or development, right?","offset":1675,"duration":21},{"text":"Governor Miran: And so you've got large parts of the world where people are living behind capital controls where if they wanted access to dollar savings instruments like dollar deposits, treasury bills, money market funds, they don't have access- they they don't have the capacity to do so because the country they're living in, the law is you just can't move your money into dollars, we're not going to let you.","offset":1696,"duration":18},{"text":"Governor Miran: And it doesn't matter how bad the people want access to dollars, they're just not allowed to. There are other parts of the world where it's very rural and there may not be banking services. And maybe people have a cell phone and so they, you know have a satellite link on their cell phone but they have no access to actual banking banking services.","offset":1714,"duration":17},{"text":"Governor Miran: Or the banking services in the country are too unreliable and volatile and or there maybe too much inflation and they don't want to use the banking services. So my perspective is that is that I'm very optimistic about stablecoin growth. But I think that a lot of the stablecoin uptake is actually going to come from large volumes of money that want to be denominated in dollars, that want to sit in dollars, and are currently unable to sit in dollars, right?","offset":1731,"duration":30},{"text":"Governor Miran: Huge pools of savings that have no other way of getting into the into the dollar system suddenly there's a way of doing it. And of course you still need to get onto the crypto ecosystem to do that so there is still an entry wheel issue but I think it makes the- I think it makes the problem easier. And I I sort of think of it a bit like, you know a ride-share app sort of being a new technology that broke up the monopoly of a taxicab medallion.","offset":1761,"duration":23},{"text":"Governor Miran: It's that type of thing that sort of that creates that ability to sort of start circumventing barriers to dollar deposits that people didn't have access to before. Now of course tying this back to neutral rate that we were discussing before, if you have huge inflows from the rest of the world into US dollar denominated savings, that's going to weigh on the neutral rate, right?","offset":1784,"duration":19},{"text":"Governor Miran: This is what happened in the late 90s and early 2000s, uh what former chairman Ben Bernanke called the global savings glut. Um if we hit the more optimistic projections of stablecoin growth, you could be looking at at magnitudes that are that are, you know maybe not quite as big as the global savings glut but let's say half as big.","offset":1803,"duration":20},{"text":"Governor Miran: So you know there is the scope for these to matter uh you know very substantially for monetary policy as well, which of course would be a very, you know which would be a very powerful force weighing on interest rates, keeping them lower.","offset":1823,"duration":12},{"text":"Host: Yeah, I completely agree that I I think a lot about stablecoins as being this this huge tailwind for the rest of the world to be able to gain entry to the dollar system. I'm curious how do you think about the other side of the equation, which I think goes understated, which is tokenized deposits? What do you think about those?","offset":1835,"duration":16},{"text":"Governor Miran: Yeah, so tokenized deposits strike me as a and to be clear I have not made a I have not made an extensive study of tokenized deposits in particular, but what I know about them, which is probably less than you do, um is that they strike me as an improve- an improvement on services that are already being offered by banks, right?","offset":1851,"duration":22},{"text":"Governor Miran: Um, is that something that um is that something that ultimately ends up revolutionizing the banking system? Um, I don't know, but this tokenized deposits strike me as as, you know another step in a long line of improving the financial services that that banks offer um by by utilizing technology. But I haven't made an extensive study of it and I would be open to changing my mind based on things you tell me.","offset":1873,"duration":27},{"text":"Host: Yeah we'll have to have you back again for another conversation on that one but about that. Um just for for the folks out there who are core to the crypto industry and you know potential founders etc that are working towards this this huge, you know tailwind that is going on of financial innovation, we'd just love to hear any sort of parting words to those that are trying to build and innovate in the space in in the US financial system of, yeah just your final words to them.","offset":1900,"duration":25},{"text":"Governor Miran: Uh so I'll repeat what I said before which is that innovation is the driver is the main driver of long-run human prosperity. So if you are working on innovation thank you, um for for doing what you do. Um and with respect to issues in payments and payments technologies, you know when the Federal Reserve makes policy we we follow the Administrative Procedure Act which is what all regulatory agencies have to do and we issue uh we issue, you know sort of notices of proposed rulemaking, we issue requests for information.","offset":1925,"duration":36},{"text":"Governor Miran: Respond to those, give us comments. You know we we search for comments from industry, from stakeholders, from innovators so that we can know whether the regulations are doing the job that they are supposed to or where they need to be pushed or pulled to get them into a place to make the economy more efficient. So you know we we put out these notices, um you know let us let us know what need- you know let us know what needs changed to make the economy more efficient.","offset":1961,"duration":20},{"text":"Host: Incredible. Well uh can't thank you enough for coming here and talking at the Digital Assets Summit Governor Miran, that was incredible. Thank you.","offset":1981,"duration":10},{"text":"Governor Miran: Thanks for having me.","offset":1991,"duration":15}],"logs":[{"elapsed":"0.0","message":"Downloading audio from YouTube...","detail":null},{"elapsed":"0.0","message":"Trying download with browser cookies (ad-free)...","detail":null},{"elapsed":"4.2","message":"⚠ Cookie download failed: WARNING: [youtube] [jsc] Error solving n challenge request using \"deno\" provider: Error running deno process (returncode: 1): \u001b[0m\u001b[1m\u001b[31merror\u001b[0m: Uncaught (in promise) TypeError: Cannot read prope","detail":null},{"elapsed":"4.2","message":"Retrying without cookies...","detail":null},{"elapsed":"22.9","message":"⚠ Downloaded without cookies — audio may contain ads","detail":null},{"elapsed":"22.9","message":"Audio downloaded (19.2 MB) in 22.9s","detail":"File size: 19.2 MB"},{"elapsed":"22.9","message":"Video title: Fed Governor Miran on Why Inflation Fears Are Overstated","detail":null},{"elapsed":"23.0","message":"Audio duration: 33:17 (33.3 min)","detail":null},{"elapsed":"23.0","message":"Uploading audio to Gemini File API...","detail":null},{"elapsed":"26.6","message":"Audio uploaded in 3.6s","detail":"File ref: files/l55u76lj6x8j"},{"elapsed":"26.6","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"73.7","message":"Transcription complete in 50.7s","detail":"37821 chars received"},{"elapsed":"73.7","message":"Transcription tokens: 50,157 in / 8,783 out — cost: $0.0514","detail":null},{"elapsed":"73.7","message":"Parsed 97 transcript segments","detail":null},{"elapsed":"73.7","message":"Transcript coverage: 33:11 of 33:17 (100%) — OK","detail":null},{"elapsed":"73.7","message":"Total transcription time: 50.7s — 97 segments","detail":null},{"elapsed":"73.7","message":"Analyzing topics across 97 segments with gemini-3.1-pro-preview...","detail":null},{"elapsed":"108.9","message":"Topic analysis complete in 35.2s — found 9 topics","detail":null},{"elapsed":"108.9","message":"Analysis tokens: 9,358 in / 776 out / 3,512 thinking — cost: $0.0702","detail":null},{"elapsed":"108.9","message":"Pipeline finished in 108.9s — total cost: $0.1216 (72,586 tokens)","detail":null}]} \ No newline at end of file diff --git a/history/1775430216753-Axpnkqd-Agk.json b/history/1775430216753-Axpnkqd-Agk.json new file mode 100644 index 0000000..7cd82ed --- /dev/null +++ b/history/1775430216753-Axpnkqd-Agk.json @@ -0,0 +1 @@ +{"id":"1775430216753-Axpnkqd-Agk","videoId":"Axpnkqd-Agk","url":"https://www.youtube.com/watch?v=Axpnkqd-Agk","title":"Bryan Johnson: I Just Took the Most Powerful Dose of DMT in the World... Here's What It Was Like","type":"youtube","topicCount":16,"segmentCount":186,"createdAt":"2026-04-05T23:03:36.753Z","uploadDate":"20260326","chunks":[{"title":"Introduction & 5-MeO-DMT","summary":"The host welcomes Bryan Johnson, who briefly introduces his recent experience taking 5-MeO-DMT 48 hours prior to the interview.","entries":[{"text":"Host: Bryan Johnson, thanks for being here.","offset":0,"duration":1},{"text":"Bryan: Yeah, it's good to see you.","offset":1,"duration":1},{"text":"Host: How are you feeling? Maybe just share with us what you did a few days ago, and let's get into it.","offset":2,"duration":4},{"text":"Bryan: Yeah, I did a— I did five MeO-DMT, which is the most powerful psychedelic on the planet. It’s somewhere between five and ten times more powerful than DMT. And so, yeah, it’s been 48 hours. I’m still learning how to talk about it.","offset":6,"duration":24}],"startTime":0},{"title":"Eight Sleep Ad","summary":"A brief advertisement for Eight Sleep's cooling and AI-adjusted mattress cover.","entries":[{"text":"Host: You know what many of the biggest tech CEOs and VCs have in common? They sleep on the Pod by Eight Sleep. It’s become tech’s favorite way to sleep, and for good reason. A cover that goes on any mattress, cools it down to 55 degrees, and uses AI to adjust your temperature all night. Up to 34% more deep sleep. No wearable needed. Go to eightsleep.com/all-in and use code ALLIN for up to $350 off your Pod purchase today.","offset":30,"duration":26}],"startTime":30},{"title":"Psychedelics for Longevity","summary":"Bryan explains how his longevity protocol initially excluded psychedelics, but compelling animal data and previous psilocybin experiments led him to test them for rejuvenation.","entries":[{"text":"Host: Before we get into your experience, why did you choose to do it?","offset":56,"duration":4},{"text":"Bryan: Two things: one, mostly as a longevity experiment. So when we— when I started this project five years ago, the approach we had was go through all the scientific evidence ever published on health and longevity, try to find the interventions that have the best evidence for effect size. And we just went down the list from the top-performing on down. So of course you start with exercise, nutrition, you know, sleep, and you work your way down to things like hyperbaric oxygen therapy and sauna and then rapamycin, metformin. And so we never actually had on our radar psychedelics. They were always either an ancient medicine, you know, being used in ritualistic practices, or being pointed at things like depression and anxiety in certain trials. But it was never understood as a rejuvenation protocol, something that was for anti-aging. And so we found a pre-clinical evidence in mice on psilocybin, and we thought, \"That's interesting.\" Uh, and so we did the world's most studied— the most quantified experiment doing psilocybin, three doses at 25 milligrams of psilocybin.","offset":60,"duration":60},{"text":"Host: Which are pretty high doses.","offset":120,"duration":1},{"text":"Bryan: It's— yeah, a clinical dose, very, very close to a hero dose. And we found that we think it's a longevity therapy.","offset":121,"duration":6},{"text":"Host: Let's get to that data in a minute, but then you decided to try 5-MeO this weekend.","offset":127,"duration":4},{"text":"Bryan: Yes.","offset":131,"duration":1}],"startTime":56},{"title":"The 5-MeO-DMT Experience","summary":"Bryan describes his 5-MeO-DMT trip as an overwhelming encounter with raw consciousness, noting that releasing all ego and desire resulted in unparalleled euphoria.","entries":[{"text":"Host: Walk me through the experience, because you televised the whole thing. It was live-streamed. You looked amazingly calm going into it and going through the process. Walk us through your experience.","offset":132,"duration":15},{"text":"Bryan: Yeah, I think those who have done 5-MeO would probably relate with me that it feels like an impossible task to explain what it's like. So that caveat said, I'll give it a go. I'm stunned, absolutely floored, speechless. You basically experience raw consciousness and raw intelligence. It's this— so whatever— when I say these words, take these words that I convey to you, take that idea, multiply it by a thousand, and then move out infinite depth, infinite width and depth and then dimensions, and like, that gives you kind of like a rough map of the size and space that you deal with.","offset":147,"duration":52},{"text":"Bryan: And it was incredibly hard, because you get blasted into this space that is so foreign, you don't even know what's happening.","offset":199,"duration":6},{"text":"Host: It happens very quickly.","offset":205,"duration":1},{"text":"Bryan: Like you inhale it— I did 9 milligrams of intramuscular and then 18 of vaporized— and it hits you within 10 seconds. You're just absolutely— you're out. And so, um, but what happens is you get in that space and then you—","offset":206,"duration":16},{"text":"Host: Visual changes? Everything?","offset":222,"duration":2},{"text":"Bryan: Very— very little visual. Uh, like you see on DMT, it's a very visual, you'll meet the, you know, like the elves or whatever else. This is not a visual experience. But you get in this world and you lock into basically you either panic because you feel like the gates of hell are going to open, that the stream of existence is just going to just tear you to shreds, it's going to shard you. And if you give up—","offset":224,"duration":29},{"text":"Host: Like break your brain.","offset":253,"duration":1},{"text":"Bryan: Yeah, like you feel like it's going to like threaten your sanity. Like is it going to chop you up into little pieces? And so in that moment you have to say, \"Do I try to wrestle this and I need to just like wait it out until it's over?\" or you just relent and you say yes. And you have to in that moment, you have to say yes so thoroughly. You have to release all attachment, all preconditions, all want, all desire. You have to release self, ego, control. You just have to just relent entirely. And then when you do that, it opened up this unimaginable bliss and euphoria. And again, this is like a V1 of trying to explain this, but if I list out the most dynamic experiences I've had as a human, you know, uh, like certain accomplishments or getting married or having a child or overcoming a difficulty or, like, you know, state your list of things, this is without question the most dynamic experience I've ever experienced as a human.","offset":254,"duration":64},{"text":"Host: Does the internal chatter, the internal monologue of the ego turn off?","offset":318,"duration":3},{"text":"Bryan: It does.","offset":321,"duration":1},{"text":"Host: So you can't hear yourself speaking. How do you rationalize what's going on if you don't have a dialogue going?","offset":322,"duration":5},{"text":"Bryan: It's this visceral feeling. Like you're hyper-aware of what's happening. It's not like you block out in the first like— when you take a very high dose, you don't really know what's happening in the first few minutes, but then you kind of come to and you're hyper-aware of everything. It's not visual, but it's this uh— you're in the depths of existence. It's just the most majestic thing ever seen, achievable by an intelligence— by intelligent life. I just can't imagine anything more miraculous.","offset":327,"duration":42}],"startTime":132},{"title":"Rewiring the Default Mode Network","summary":"They discuss how psychedelics disrupt the brain's default mode network. Scrambling these rigid thought patterns fosters neuroplasticity and restores a child-like sense of openness.","entries":[{"text":"Host: You've studied the biology, the biochemistry, what goes on in the brain as this molecule hits your neurons?","offset":369,"duration":9},{"text":"Bryan: Yeah, I mean, like, it um— I mean one, it completely dissolves your default mode network.","offset":378,"duration":5},{"text":"Host: Describe what that is.","offset":383,"duration":1},{"text":"Bryan: So like uh— it’s this engine that constructs self and ego. And so as you ruminate, you know, like you're going through—","offset":384,"duration":9},{"text":"Host: Thinking through your day, what’s next, how am I feeling, what should I be doing right now, constant conversation internally.","offset":393,"duration":5},{"text":"Bryan: Yeah, \"Do I feel bad about myself? Do I feel, you know, like I'm— am I shy? Am I like do I feel bad about whatever?\" Like you're doing this rumination stuff. Uh, kids don't have this rumination loop. Their default mode network is quiet. And as you age, you basically build up this default mode network into more stiffer patterns. And so as you age, your experience of reality becomes increasingly narrow. You have these big ruts that form. And so you can just see people in their patterns, like how open a child is to say very random things and as adults you're just very— you're shut in. Like when I did psilocybin, one of the reasons why we did it is because it does have this effect where it dampens the default mode network. And we could pick this up with Kernel, the brain interface. You can see how the default mode network weakens.","offset":398,"duration":49},{"text":"Bryan: Like, so basically think of the brain like a globe with airports scattered about. And you have certain traffic patterns like New York to London. You have a certain number of flights every day. That's like a very strong connection. But New York to um, you know, some small town in Arkansas has a very uh low traffic map. And so when you do something like psilocybin, it basically takes the airports, picks them up and then repositions them around the world. So they're just all scrambled. So the traffic patterns aren't the same.","offset":447,"duration":24},{"text":"Host: The neurons don't physically move, but the activity shifts around, right? The neurons are a little bit more random than they normally would be, which arguably drives neuroplasticity, causes those neurons to reach out for new connections. And when new connections are made, new behaviors, new ways of thinking emerge coming out of these therapeutics. Is that a fair way to describe it?","offset":471,"duration":23},{"text":"Bryan: Exactly right. Exactly right. So you look at my brain on psilocybin from Kernel, you see my patterns before, like the New York to London connection, you see my brain afterwards, and it's exactly what you said. New patterns are emergent, the old ones have quieted down. So a new map of connectivity. And so we saw that happen and that does generate a lot of neuroplasticity.","offset":494,"duration":19},{"text":"Host: And obviously this neuroplasticity, rewiring these connections in the brain, is what allows trauma victims or folks that have a certain wiring that they keep repeating in their brain, which causes the trauma and the anxiety in their lives, to get rewired, and then that trauma and that anxiety feels like it dissolves or melts away. Is that a fair—?","offset":513,"duration":19},{"text":"Bryan: Exactly right.","offset":532,"duration":1},{"text":"Host: Yeah. And so this— this has been documented in psilocybin. It's kind of well understood. How did you connect that psilocybin data to an effort in longevity, or was this just like a random idea, \"Let's try it out\"?","offset":533,"duration":13},{"text":"Bryan: Yeah, I mean well so we saw some mouse data that it had these effects. It also showed reduced inflammation. Uh, so we said like this is interesting because most longevity therapies do something with inflammation, right? Like inflammaging is the killer. So if you can lower inflammation, it's a very good sign. Uh, if you can do something that makes the brain more youthful and takes down those big ruts, that's also useful.","offset":546,"duration":24},{"text":"Bryan: What we found at psilocybin though is that it had— we found a first in human observation: it had this metabolic reset in the brain, where my blood glucose before this was in the top 99.5 percentile of all the population. After, it went to the top 99.9 percentile. Like, to move my blood glucose from that level is very, very hard. But it basically like uh— not like metformin where you're doing something with blood glucose, this just had a reset across the body. Also changed my microbiome. Uh, so we saw full-on effects. So then we said, \"Okay, if that had that consequence, 5-MeO may have some similar characteristics.\"","offset":570,"duration":37},{"text":"Host: But no one had done this in 5-MeO before.","offset":607,"duration":1},{"text":"Bryan: Exactly. So there’s— there’s some animal evidence, um, but it’s the— the similar dynamics of like, \"Can you take the brain and can you basically like smooth out the barnacles that accumulate?\" And 5-MeO-DMT compared to psilocybin, like just absolutely like blasted clean my default mode network.","offset":608,"duration":21},{"text":"Host: Turned it off completely.","offset":629,"duration":2},{"text":"Bryan: Yeah. It just doesn't run the same way. Uh, like for an example, like uh, this morning I woke up catching myself laughing in a dream. I have not laughed in a dream— I don't even know when I've ever laughed in a dream— but that is— after I woke up, I was like, \"That's really weird. Like, I don't remember laughing.\" I looked it up and like, that is a characteristic of a child.","offset":631,"duration":24},{"text":"Host: Right.","offset":655,"duration":1},{"text":"Bryan: And so you are restored to this child-like state. And I mean the past couple days I have felt child-like. You know, like yesterday morning I felt that, you know, emergent excitement, the bubbling of like, \"Today is so exciting. I'm going to do new things. I'm going to have new experiences.\" Uh, that you're just excited about all things. I haven't felt that— I don't even know when, you know, for so many years. So like, it really was uh profound on every layer. And I see and I'm stumbling through this because I don't even know how to talk about it yet.","offset":656,"duration":31},{"text":"Host: During the day, you're hanging out, you're walking around. Is your brain having the same normal chatter that it did before, or do you think that there's a persistent change in that default mode network?","offset":687,"duration":11},{"text":"Bryan: Yeah, definitely a change. Like without— I was with my partner Kate yesterday and we uh, I did something that made her upset. And so like in that situation, you know, like when couples are in that moment, you have like this negotiation: \"How do I sort this?\" And it all just became so clear to me, like when children have a fight, you have it out and then it’s just like done. And you move on. But then adults take that and they like package it up and they like weaponize it, be like, \"I got something on you and I'm going to move the chess pieces and like try to leverage this.\"","offset":698,"duration":35},{"text":"Host: Or they store it up like a snake in one of those things that pops out all the snakes later. You know, it's like—","offset":733,"duration":5},{"text":"Bryan: Exactly. Package it all up. Exactly. And so like we had this and I just felt uh absolutely like no need to escalate or to defend or to— like it was just easy. And uh, it was a breakthrough in our relationship, where I was able to communicate with her in a way. And so it's like laughing in my sleep, it's how I deal with my partner. When I walk around, I just feel so much— I feel so much more funny. You know, like my ability to make quips that are just immediate uh, you know. Like so yeah, I just feel renewed as a person in a way that I just really didn't imagine.","offset":738,"duration":38}],"startTime":369},{"title":"Past Psychedelic Experiences","summary":"Bryan reflects on his earlier, therapeutic use of psychedelics and ketamine after selling his company, contrasting those milder experiences with the raw power of 5-MeO-DMT.","entries":[{"text":"Host: Have you tried hallucinogenics before you started your longevity path a couple of years ago?","offset":776,"duration":7},{"text":"Bryan: Yeah.","offset":783,"duration":1},{"text":"Host: And did you do that recreationally or therapeutically?","offset":784,"duration":2},{"text":"Bryan: It was mostly therapeutic in that I had sold my company Braintree/Venmo, I got a divorce, I left the Mormon church, and I was trying to remap like, \"What is life? Who am I? What do I do?\" So it was in that rebuilding stage where I just dabbled of like— you know, I did ketamine at Kernel. So one of our first studies at Kernel is we said— ketamine was a up-and-coming therapy for depression— and we posed the question: \"What happens when you do ketamine?\" And so we did the world's most extensive measurement of ketamine with Kernel, before, during and after. And so that was interesting, like and it had some kind of you know, transient effect, but that's like a— a little league relative to 5-MeO.","offset":786,"duration":42}],"startTime":776},{"title":"Brain Mapping & Data Collection","summary":"Bryan outlines the extensive MRI, EEG, and Kernel data he collected to quantify his brain's rejuvenation, emphasizing the potential of psychedelics in longevity therapies.","entries":[{"text":"Host: And so as you've gone through this, maybe share a little bit of the MRI data that you're gathering and the other data mapping neurological effects and tell us a little bit about what you've learned.","offset":828,"duration":10},{"text":"Bryan: So far, nothing. Uh, I have my subjective experience to share, but we— we have a structural brain MRI, we have a functional brain MRI, we did Kernel which is like an optical interface, and then I did real-time EEG capture.","offset":838,"duration":12},{"text":"Host: And we should just talk about— I think it's important— structural, you can see the— the physical brain; functional, you can see the activity in the brain, so neurons firing and neurons that are not firing, right? And then electrical actions that are measured by electrical devices.","offset":850,"duration":17},{"text":"Bryan: Exactly. So we basically like wanted— because the brain is very— so we've had a lot of success rejuvenating my heart and my lungs and muscle and body fat, but rejuvenating the brain is very hard.","offset":867,"duration":13},{"text":"Host: Right.","offset":880,"duration":1},{"text":"Bryan: And so we— this is why this is such a promising therapy. So we wanted to look at the brain uh through every modality possible. We wanted to look at the blood flow, structural, molecular, you know, the wave patterns. So it's a— it's a very high-fidelity quantification. And so we'll see what the data comes out. Uh, I'm very excited.","offset":881,"duration":16},{"text":"Host: You did this on psilocybin as well, right? You mapped the brain over time. What did you learn there?","offset":897,"duration":5},{"text":"Bryan: Dramatic uh restoration of youthful brain patterns.","offset":902,"duration":4},{"text":"Host: Yeah, right. Yeah. And what comes after 5-MeO? Like how far do you take this?","offset":906,"duration":9},{"text":"Bryan: Honestly, uh, I am so encouraged by psychedelics. I, you know, like in— in the community where I hang out, psychedelics have always been understood as, you know, it's like a retreat or it's like a— a ritual you go to like do various explorations, but never in the world of longevity. It's never been understood as that thing. And now after seeing the data, I— and of course you have to be very careful when talking about psychedelics because they're extremely powerful. It's not like go out and do them everybody, right? It's like it needs to be done properly with a licensed professional, it needs to be done carefully, the person needs to be in the right state. Like it is not to be taken lightly. But I am uh more interested than ever in psychedelic compounds. They're just uniquely powerful.","offset":915,"duration":50}],"startTime":828},{"title":"Psychedelic Risks & Life Changes","summary":"The host raises concerns about psychedelics causing psychosis or leading people to abandon their families and companies. Bryan acknowledges these risks, though he personally feels more motivated.","entries":[{"text":"Host: There's some arguments to be made that psychedelics can induce permanent psychosis, cause functional changes and drive some people that might be predisposed into schizophrenic states. How did you get over those risks? Because for a lot of people that would turn them off to trying psychedelics, and it's not a non-zero percentage of people that suffer these consequences.","offset":965,"duration":23},{"text":"Bryan: Yeah. I agree. And also the people who have really bad trips that leave them scarred. So it— there really is— and I think in part of it is uh what could be contributing to this is uh people who for example have tried magic mushrooms, you know, it's in a social situation, someone's got a bag, you pull out some mushrooms, it's like, \"Yeah, like weigh's blank,\" and they pop it in, but they have no idea what kind of mushroom strain they're eating, they don't know what the dose of psilocybin is. And so it's like unquantified, unsupervised, wrong set and setting. And so as much of it I think you can— the risk persists, but I don't think we've— we've approached psychedelics with the appropriate rigor that we should to make it safe. And so it's not to say that we can solve for the safety issues for all people. Some people just may not be the appropriate candidate for it. But I think if we do create a safety structure around it, they could deliver the benefits people want uh without you know, less of the risk. But definitely I agree with you, like it again, it deserves all the caution in the world.","offset":988,"duration":59},{"text":"Host: Do you think it's neurogenic, neuroplasticity, trauma resolution? I mean what is the way that this is going to be allowed to become call it a medical therapeutic that can be more broadly trialed and then eventually figure out how to bring it to people without it being carrying all the risks and burdens that it does today?","offset":1047,"duration":21},{"text":"Bryan: I mean if I just subjectively compare my experience with 5-MeO to having a better diet and exercising every day and uh sleeping well and doing the sauna and doing hyperbaric oxygen therapy, this was more efficacious than all of them in terms of the reset of me as a human. It— it just is incomparable. And I guess I'm— I'm really left pondering— for this molecule to have such a gigantic impact. Now like how long will it last? What's the decay curve like? You know, will I find uh I become the former Bryan within 30 days, 60 days? I have to repeat this again? I don't know. But it really is, you know, when you sleep well you feel great. When you exercise, great. But like nothing like what 5-MeO did in terms of— of like the reset of me as a human.","offset":1068,"duration":47},{"text":"Host: So let's just talk about the consequences outside of the physiological, which is life. There are lots of stories and friends that I have that and people that I know that have tried a heavy psychedelic, like an ayahuasca or something. They were the CEO of a company, and then they quit their company and they go off to the jungle, leave their family, divorce their— their partner, uh make such dramatic life changes because their perspective has been shifted so much that they reevaluate what matters in life to such a degree that they give up a lot of the things that mattered before. In the wake of that, there are people that feel they're a victim of that behavioral shift: the investors in the company, the employees, the family members, etc. Can you just talk a little bit about those broad risks because we've seen it and I'm— and I don't know if you've seen the same, but friends that have kind of like said, \"I have this new perspective, I'm giving up my life.\"","offset":1115,"duration":59},{"text":"Bryan: I've seen the same thing, and I think uh one investor told me that he even put it in the deal docs: that, you know, if we invest, you're not going to do these psychedelics. Because they wanted to minimize the risk profile. It's a thing.","offset":1174,"duration":14},{"text":"Host: In your— in an investment in you?","offset":1188,"duration":1},{"text":"Bryan: No, I just— because I've been doing this, uh people bring this up as a topic of conversation, and so they say like, \"I see you doing this for longevity, but you know, like I've seen so many examples where people put money in, then you lose the founder. Like they're off, and now everyone's high and dry.\" And so they were telling me that they put into deal docs that they can't do this for the duration of the company.","offset":1189,"duration":24},{"text":"Bryan: And so it is a thing, and you know, I— I have nothing to say about it other than I know it happens. Uh, also I would say that most people in the tech world that I'm familiar with, again they've done this in retreat centers or in social environments. It's not quantified, it's not set and setting. I mean so it's a different thing.","offset":1213,"duration":21},{"text":"Bryan: But I will say like, you know, I— I guess me as a person, what I'm trying to focus on, I came back even more motivated to do what I'm doing now. Uh, I don't have a desire to go off in the woods, you know, and like live that kind of life. It— it emboldened me to work on these things, but no question about it, you— you do have a dramatic shift in perspective, and it's— it's very hard to get around.","offset":1234,"duration":22}],"startTime":965},{"title":"Identity, Values & AI","summary":"They explore the philosophical implications of rapidly rewiring one's brain and values. Bryan considers whether psychedelics might be a necessary tool for humans to adapt to an AI-driven world.","entries":[{"text":"Host: It begs a very important philosophical question: who am I? If I'm defined by my experiences, it roughly equates to my neurons are wired in a way that's a consequence of my experiences. And if I go in and take a drug and in a few hours rewire all my neurons, am I the same person? What makes Bryan Bryan? You can maybe recall some memories of Bryan prior to taking the psychedelic, but Bryan as a person has been rewired. Are you a different person now and what does that say about are we ever a persistent person?","offset":1256,"duration":42},{"text":"Bryan: Yeah. Your question is spot-on. Probably the most dramatic reconstruction of your 60-plus trillion cells than anything you can do in life. You know, like maybe like a near-death experience, you know, would maybe uh be close, but it's a dramatic rewiring of you as a human.","offset":1298,"duration":17},{"text":"Host: Your values can change too.","offset":1315,"duration":1},{"text":"Bryan: That's right.","offset":1316,"duration":1},{"text":"Host: And you could judge the values pre and post, right? You could judge values ascribed to you by a religion or perhaps values ascribed to you by responsibility to family members, children, spouses, partners, what have you. You abandon them after you go through this change. So your values have changed. Is it right or wrong? I think is another important question that comes out of all this.","offset":1317,"duration":21},{"text":"Bryan: I agree, and like you now like you now think about that— that's through the frame where the world changes at a certain speed. Now you take the world where it's changing faster. So we now know that it's hard to predict what's going to happen two weeks from now or a month, right? Like things are changing very quickly. And so now you come up with this practical question: can humans change fast enough in the world where AI is the dominant engine of innovation?","offset":1338,"duration":28},{"text":"Bryan: And so in that case like you may want psychedelics as your ally to say, \"As a human I'm struggling to like move with the change.\" Uh, so there's potentially where it— it flips from a liability to an asset where like now I do want that restructure changing even though you have some tail risk of like maybe my priorities will shift.","offset":1366,"duration":20}],"startTime":1256},{"title":"Psychoflexibility & Extreme Biohacking","summary":"Bryan shares his willingness to try transgenics and neural implants, explaining how his open-minded playfulness balances with his responsibilities as a father.","entries":[{"text":"Host: I think you have profound what I would call psychoflexibility, and I think most people don't. They have either a disinterest in changing who they are overnight or they're fearful of the— the ramifications or the experience and that they wouldn't go through it. How far would you take it? Would you wire yourself up to a Neuralink or neural enhancement device that would give you the ability to have information on demand and maybe change your personality and capacity as a human through an implant? Would you consider doing something like that?","offset":1386,"duration":30},{"text":"Bryan: Yes.","offset":1416,"duration":1},{"text":"Host: You would. Would you consider a transgenic system where you basically take a plasmid which would then express a set of proteins in your body and change uh gene expression profiles and cells in your body and basically could rewire you as a different person?","offset":1417,"duration":14},{"text":"Bryan: Yes.","offset":1431,"duration":1},{"text":"Host: Yes. Is there a limit to what you would try?","offset":1432,"duration":2},{"text":"Bryan: No.","offset":1434,"duration":1},{"text":"Host: Interesting. Where do you think that comes from?","offset":1435,"duration":1},{"text":"Bryan: I think I uh I find it to be the most exciting configuration of life. Uh, the ability to play on the frontier. Uh, novelty and expedition and challenge. That's really my—","offset":1436,"duration":13},{"text":"Host: Did you always have it, or are you responding to childhood suppression of those opportunities?","offset":1449,"duration":6},{"text":"Bryan: I mean it's— it's probably— it's probably an overcompensation of— of trauma response like most things are. And so you know, as a child I lived in a very structured religious environment where things were cemented. Like here's the story, here's the plan, here's what you do and what you don't do. Uh, and so yeah maybe it's probably just I'm now uh flipped in the opposite. And so I mean that's like probably true that I really uh I don't trust my internal generation of reality. You know, I know I'm always making things up. I've got 188 chronic biases like all humans do. So I'm just I'm generally suspicious of all things all time and I don't take myself very seriously. So I just find the frontier play space to be like right now, I mean you know, what you're doing in building companies, like you just open up a— a toolkit and say like, \"What can I build? And how do I modify?\" And uh so I agree with you, I do have a strong proclivity towards openness to play.","offset":1455,"duration":51},{"text":"Host: Do you find that you've been challenged in maintaining I would call it external responsibility? As you explore and enhance yourself so much, do you give up the responsibility to others around you who maybe are dependent on you or or in need of you?","offset":1506,"duration":14},{"text":"Bryan: Yeah. I have three kids. And so uh I do think about them a lot. And uh being a father is a really important thing to me and it's an important part of my identity. And so that has not changed. So I've never uh vacillated on that or changed my disposition towards that. For those around me, I guess fortunately I have a social group that just says \"Go and play.\" There's really no one in my life that tries to claw me back. There's no velcro. Yeah. It's just all encouraging. And so that I guess I feel very fortunate that everyone around me and they're willing to take the risks. I mean this is you know when I sat down for 5-MeO, I mean my partner Kate, like she's got a ton of risk. Like what if it goes poorly? What if I change my perspectives? What if something bad happens? So—","offset":1520,"duration":45},{"text":"Host: Well, one could make an argument that taking that degree of risk where something could have gone wrong, the people around you are enabling versus being supportive. I mean that’s a consequence.","offset":1565,"duration":10}],"startTime":1386},{"title":"Mitochondrial Rejuvenation Therapy","summary":"The conversation shifts to upcoming therapies, including a plan to extract and multiply youthful mitochondria from a family member to transplant into Bryan.","entries":[{"text":"Host: But let's shift topics to other uh modalities for longevity. What else is on the horizon? So you've had this profound set of experiences with psychedelics. You've documented in a very extraordinary and exquisite fashion all of the other things that you've been doing as interventions. Are there other things that are on the horizon that you're either excited about or that you're considering yourself?","offset":1575,"duration":25},{"text":"Bryan: Yeah, I mean two of the ones that we've spoken about, cell therapy and gene therapy. Yeah. Uh, they um they're all in the pipeline. And so they're not ready yet. We've knocked out all the stuff you can do today. Like we've gone through it all, done it all. Uh, the next-gen therapies are just not there yet. So we're looking at mitochondrial rejuvenation.","offset":1600,"duration":19},{"text":"Host: I think that's incredible. I think mitochondrial augmentation therapy and there was a paper I saw where in order to get the mitochondria in the cell, they coated the mitochondria in effectively a red blood cell envelope which made it more transportable into cells and less uh attack by the immune system, which is incredible. And I— I'm a big, big, big believer in this— this— this course of therapy. I think this is going to be a whole therapeutic modality that no one has even recognized.","offset":1619,"duration":24},{"text":"Bryan: I agree. We have our first uh mitochondria therapy lined up. So.","offset":1643,"duration":3},{"text":"Host: How are you going to do it? You're— you’re like 99.9%. You need someone who's like 48.7% to try the mitochondrial augment—. Particularly like you know, I think they tried it in Parkinson's patients, Alzheimer's patients, that's where you could really see profound shifts in in certain metrics. For you, it's like 99.9 to what? Like.","offset":1646,"duration":18},{"text":"Bryan: Yeah. Yeah, I mean I have the mitochondria you know of a 48-year-old, right? Like so what if— what if I could—","offset":1664,"duration":6},{"text":"Host: Your siblings?","offset":1670,"duration":1},{"text":"Bryan: Yes.","offset":1671,"duration":0},{"text":"Host: You could go to your sibling's child because the mitochondria is passed maternally, because it’s in the— it’s in the egg cell. So it's the mother's mitochondria. So if you go down the mother's line maternally, if you have a sister who has a kid, they're going to have very young mitochondria. You can take a little blood sample and then grow their mitochondria extensively and use that as a biological match to you.","offset":1671,"duration":22},{"text":"Bryan: This is a perfect extension. I've had a blood boy as a son, so now I'm just going to go to the extended family and be like, \"Guys, it's a— it’s a family project.\"","offset":1693,"duration":9},{"text":"Host: Yeah, family project. Exactly. Yeah, well that one's super interesting.","offset":1702,"duration":2},{"text":"Bryan: And we also have one that we're doing— I'm now building—","offset":1704,"duration":3},{"text":"Host: Sorry, are you going to do your own mitochondrial transplantation and you're going to build a bioreactor, or you using working with one of the third parties that are already doing this?","offset":1707,"duration":5},{"text":"Bryan: A third company, yes. So I'll give— we'll do a blood draw in the next week or two. They'll spin up—","offset":1712,"duration":4},{"text":"Host: They'll do it.","offset":1716,"duration":1},{"text":"Bryan: They'll do it. Okay. Yep.","offset":1717,"duration":2},{"text":"Host: So you're going to get your mitochondria, which have some you know the problem with mitochondria as you know is mitochondrial DNA degradation over time, right? It accelerates for certain people, but that way if you go back to a young person you have young mitochondria, but then you're going to multiply yours out.","offset":1719,"duration":15},{"text":"Bryan: Yes.","offset":1734,"duration":1},{"text":"Host: And probably select a little bit or for healthier ones?","offset":1735,"duration":2},{"text":"Bryan: Exactly.","offset":1737,"duration":1},{"text":"Host: Right, okay. And then put it back in.","offset":1738,"duration":1},{"text":"Bryan: Yep. So it's very— I mean exploratory. You know, we don't know. Uh we're one of the first. They're in Phase 2 now.","offset":1739,"duration":6},{"text":"Host: Do you sprint?","offset":1745,"duration":1},{"text":"Bryan: Yes, I do.","offset":1746,"duration":1},{"text":"Host: So you could probably score if you did it intramuscular like mitochondrial therapy you could sprint see your score.","offset":1747,"duration":5},{"text":"Bryan: That's a great idea.","offset":1752,"duration":1},{"text":"Host: Yeah, thank you. Yeah, we could do that for you. Yeah, that would be a great way to measure it from a rather than just a basic biomarker perspective. It'd be really interesting to see.","offset":1753,"duration":6},{"text":"Bryan: Yeah. Sprinting is one of the most underappreciated longevity therapies.","offset":1759,"duration":5},{"text":"Host: Yeah, I don't do it. Um, I've got the the age of a 74-year-old uh roughly.","offset":1764,"duration":6},{"text":"Bryan: Is that right?","offset":1770,"duration":1},{"text":"Host: No, no. Not personally. I'm— I'm definitely not keeping track with you.","offset":1771,"duration":5}],"startTime":1575},{"title":"Gene Therapy & Tissue Regeneration","summary":"They discuss the profound potential of plasmid-based gene therapies like Follistatin expression for tissue regeneration, and the use of AI to accelerate these medical projects.","entries":[{"text":"Host: Would you consider or have you looked at any plasmids where you take a gene as DNA, put it in your body and then that gene makes a protein in your body that that does something?","offset":1776,"duration":9},{"text":"Bryan: Yeah. Like the one we were looking at in the Follistatin expression. Yeah, exactly. So the mesenchymal stem cells packaged up with the Follistatin delivery. Uh, you know that showed that over 50% of tissues getting that rejuvenation.","offset":1785,"duration":10},{"text":"Host: It’s unbelievable. Unbelievable.","offset":1795,"duration":1},{"text":"Bryan: Unbelievable. It's like the best— it’s the best demonstration in the entire world.","offset":1796,"duration":2},{"text":"Host: That's perfect for tissue regeneration. Like as a particular application set, tissue regeneration using that sort of system seems like a no-brainer.","offset":1798,"duration":7},{"text":"Bryan: It's— it’s safe, right? So yeah so I— reached out to that Chinese professor. I'm really interested in seeing it replicated. I would love—","offset":1805,"duration":8},{"text":"Host: You reached out to the Chinese professor?","offset":1813,"duration":2},{"text":"Bryan: Yeah.","offset":1815,"duration":0},{"text":"Host: That’s awesome. We sent that paper back and forth. Yeah, yeah exactly. That's awesome. Did he respond?","offset":1815,"duration":5},{"text":"Bryan: Uh, yeah.","offset":1820,"duration":0},{"text":"Host: Awesome. Good. Uh, so we I'd love to do that. Uh, I'd love to actually build it ourselves. But that's like a two-year project. So uh.","offset":1820,"duration":10},{"text":"Host: AI can help.","offset":1830,"duration":1},{"text":"Bryan: Make it faster.","offset":1831,"duration":1},{"text":"Host: That's true. Yeah actually that's true.","offset":1832,"duration":1},{"text":"Bryan: AI as a project manager for these sorts of programs is—","offset":1833,"duration":2},{"text":"Host: You know that's true. We spoke about this six months ago and things are so different.","offset":1835,"duration":3},{"text":"Bryan: So different now six months later in terms of standing that up.","offset":1838,"duration":3},{"text":"Host: Um, so that one's cool. So I think that's a good a good option.","offset":1841,"duration":3}],"startTime":1776},{"title":"Stem Cell Organoid Testing","summary":"Bryan reveals his team has created organoids from his own reprogrammed stem cells, allowing them to safely test drugs in a petri dish before human trials.","entries":[{"text":"Bryan: Also I'm doing uh Bryan Johnson organoids. So uh we took my iPSCs.","offset":1844,"duration":5},{"text":"Host: Induced pluripotent stem cells.","offset":1849,"duration":1},{"text":"Bryan: Exactly.","offset":1850,"duration":1},{"text":"Host: So you took your cells, turned them into stem cells.","offset":1851,"duration":2},{"text":"Bryan: Yeah.","offset":1853,"duration":0},{"text":"Bryan: So now we're doing in-dish. So now we have like a Bryan Johnson heart, liver, lungs and now we're going to try molecules on me in in-dish.","offset":1853,"duration":7},{"text":"Host: So you've app— so so let me just walk the audience through this. So you take cells off of your skin or something?","offset":1860,"duration":6},{"text":"Bryan: Blood.","offset":1866,"duration":1},{"text":"Host: Blood. And then you put these Yamanaka factor proteins on those cells, causes those cells to become stem cells, which means they can then turn into any other cell. And then you put other proteins on them to turn them into a heart cell or a eye cell or or what have you. And now you've got a store of these tissue-specific Bryan Johnson cells that you then use for—?","offset":1867,"duration":19},{"text":"Bryan: Like you can say, \"Okay, uh what if you give Bryan Johnson blank, you know drug? What is— what happens? Is it good? Is it bad? What are the side effects? What are the complications?\"","offset":1886,"duration":9},{"text":"Host: In the petri dish, you put the drug in there, see what happens.","offset":1895,"duration":2},{"text":"Bryan: Exactly.","offset":1897,"duration":1},{"text":"Host: Okay, got it.","offset":1898,"duration":1},{"text":"Bryan: So you just like you can simulate all these experiments. So now you you get the advantage of time of acceleration of like what to take, why, what dose, uh what combinatorial things to consider. And so we have the organoids stood up. We haven't done our first tests yet. So that's interesting because now I have to do this old-school methodology like put it in my body, wait to see what happens, is it good, is it bad, what you know how does it affect everything? So.","offset":1899,"duration":25},{"text":"Host: That's a good one. But I mean I don't know. We'll see. It’s cool in concept. I mean TBD if it actually works, so we'll see.","offset":1924,"duration":2}],"startTime":1844},{"title":"Yamanaka Factors & Societal Abundance","summary":"A discussion on the progress and dosing challenges of cellular reprogramming using Yamanaka factors, and how biological abundance could cure society's psychological malaise.","entries":[{"text":"Host: Have you tracked any of the alternatives to Yamanaka factors, the factor discovery work that's going on, and do you think there's anything worth testing at this stage?","offset":1926,"duration":9},{"text":"Bryan: Yeah, I'm an investor in New Limit. So I've talked to them about where they're at and—","offset":1935,"duration":4},{"text":"Host: Blake and Brian's company.","offset":1939,"duration":2},{"text":"Bryan: They've done uh I mean they've made remarkable progress. They— they figured out how to computationally solve the discovery process. And so I they uh they're much faster than they initially thought. And so that's very encouraging.","offset":1941,"duration":11},{"text":"Host: You know the big challenge with Yamanaka factors is always dosing. If you over-dose a cell, a one cell, that cell can become a cancer cell and take off as a tumor. So the sensitivity that you need to have to get the right number of the factors, which is a protein, into the cell needs to be perfectly tuned. So I have a theory that this will end up being solved by cellular switches. That we'll end up putting machinery into the cells that can turn on or off the protein synthesis at the right dosing based on the measurement of gene expression in the cell. That's my theory on where this will end up.","offset":1952,"duration":29},{"text":"Bryan: That makes a lot of sense. Any other control mechanism will be inadequate.","offset":1981,"duration":3},{"text":"Host: That's right. The feedback loop just— All you need is one error and you're you're in trouble. But it is the most profound I think technology that humanity's dealing with today besides AI. We're not quite there with fusion, which I would argue is probably a distant third, but it is very powerful what's possible.","offset":1984,"duration":18},{"text":"Bryan: I agree. And like in the future like I think we'll look back and we'll see GLP-1s as the first big drop of like, \"What? I can just inject myself and like it solves hunger and. Totally.\" And then the second will probably be something like New Limit or one of these Follistatin or one of these plasmid-based Follistatin-3 therapies where it will show real-life like dramatic changes. And then humanity will shift as uh longevity being a vision of sci-fi rich people pursuit to something that is truly— I mean go back to like the conversation on on the temptation towards socialism. Right, like if you can feel robust in your ability to pursue life and be healthy and vibrant and uh in control, I think these things could have dramatic changes to society, not just in health but like in our mentality.","offset":2002,"duration":47},{"text":"Host: Any form of abundance, whether it's abundance in food, in energy, in housing, in mobility, in lifespan, the more abundance people get, the happier they are. And the more you're improving abundance in the world, the the better we are going to live as a group of people together on planet Earth. The the happier we will all be with each other.","offset":2049,"duration":17},{"text":"Bryan: But I think like honestly like a lot of the the external conflict only comes from internal unhappiness.","offset":2066,"duration":6},{"text":"Host: 100%.","offset":2072,"duration":1},{"text":"Bryan: And so if you look at the general malaise of like American society, like no wonder uh things are shitty, right? You've got metabo— 84% of people have metabolic disorder, over 40% of people are obese, like we're just in really poor health. Nobody's sleeping. Everyone's on their phone. We have mental health issues. Like no wonder you have the proclivity towards these kinds of outcomes. Like so if you could get the health in check, it changes the psychological disposition of you, your community, your country, like you have much more of a can-do attitude, like \"I can take on the world and I can do hard things,\" but when you're not feeling well like it's just everything is just so much harder.","offset":2073,"duration":34},{"text":"Host: 100%.","offset":2107,"duration":1}],"startTime":1926},{"title":"Psychedelics for Psychological Youth","summary":"Bryan explains that while physical therapies heal the body, psychedelics are uniquely capable of restoring the youthful, can-do psychological ambition that fades with age.","entries":[{"text":"Host: And in light of all of these new therapeutic modalities and these new opportunities that seem to be biologically proven and have these profound effects, why continue to tinker with psychedelics? Like are they as profound or are they a complement, or like how do you think about fitting all of this portfolio of things that you're looking at together?","offset":2108,"duration":17},{"text":"Bryan: I mean I guess the question is uh I forget on the Follistatin-3 study, I don't know if they saw brain rejuvenation.","offset":2125,"duration":6},{"text":"Host: Didn't see that.","offset":2131,"duration":1},{"text":"Bryan: I did not see that. And I don't I don't remember. I mean it is a very complicated organ.","offset":2132,"duration":4},{"text":"Host: Yeah, exactly.","offset":2136,"duration":1},{"text":"Bryan: And it's insane, like you know you can grow muscle tissue back and you can grow skin tissue back and it's kind of like okay I grew a little ex—. Like if you grow the the neurons back maybe in the wrong way or like we don't know because it's never been done before. So understanding the consequence of neuro-regeneration is like—","offset":2137,"duration":20},{"text":"Bryan: So I wonder like if the role that might play, like you know maybe psilocybin and 5-MeO won't be uh meaningful for like basic functions of the body, but maybe it's the uh the outperformer in youthfulness of your uh of your disposition towards reality. Like one thing I'm apprehensive about is you know I'm 48, and so as you start climbing to your 50s, 60s, you do really narrow. Like your ambition goes from \"I can do anything\" to start you know narrowing down further and further, and I worry about using— losing a youthful disposition of a can-do attitude of anything is possible.","offset":2157,"duration":46},{"text":"Host: Totally.","offset":2203,"duration":1},{"text":"Bryan: And maybe that's the role of psychedelics is you just get a wash of like the snapback of like \"I can\" and \"I can bounce.\" That definitely been the case for me. So I think they do probably play a really important role of like they're probably a set of things that for certain people that will um basically like I feel like it was like 30, 40 years of psychological rejuvenation. Like you to transport me back to a child-like state. That is insane. I don't get that from the sauna or from eating well or from sleeping well. Like I'm still— so definitely just unique.","offset":2204,"duration":35}],"startTime":2108},{"title":"Conclusion","summary":"The host jokingly contrasts his own unhealthy habits with Bryan's rigorous regimen as they conclude the interview.","entries":[{"text":"Host: Amazing. Well listen, I'm going to go drink alcohol and eat carbs and stay out late. I don't know, what are you going to do?","offset":2239,"duration":6},{"text":"Bryan: I'm going to go to bed on time and do do my wind down routine.","offset":2245,"duration":2},{"text":"Host: Yeah, you do you.","offset":2247,"duration":1},{"text":"Bryan: And you you as well. Enjoy it.","offset":2248,"duration":1},{"text":"Host: I will. I appreciate it. This has been great. Bryan Johnson, thank you.","offset":2249,"duration":3},{"text":"Bryan: Yeah, thanks.","offset":2252,"duration":1},{"text":"Host: That was awesome.","offset":2253,"duration":1},{"text":"Bryan: That was great.","offset":2254,"duration":15}],"startTime":2239}],"entries":[{"text":"Host: Bryan Johnson, thanks for being here.","offset":0,"duration":1},{"text":"Bryan: Yeah, it's good to see you.","offset":1,"duration":1},{"text":"Host: How are you feeling? Maybe just share with us what you did a few days ago, and let's get into it.","offset":2,"duration":4},{"text":"Bryan: Yeah, I did a— I did five MeO-DMT, which is the most powerful psychedelic on the planet. It’s somewhere between five and ten times more powerful than DMT. And so, yeah, it’s been 48 hours. I’m still learning how to talk about it.","offset":6,"duration":24},{"text":"Host: You know what many of the biggest tech CEOs and VCs have in common? They sleep on the Pod by Eight Sleep. It’s become tech’s favorite way to sleep, and for good reason. A cover that goes on any mattress, cools it down to 55 degrees, and uses AI to adjust your temperature all night. Up to 34% more deep sleep. No wearable needed. Go to eightsleep.com/all-in and use code ALLIN for up to $350 off your Pod purchase today.","offset":30,"duration":26},{"text":"Host: Before we get into your experience, why did you choose to do it?","offset":56,"duration":4},{"text":"Bryan: Two things: one, mostly as a longevity experiment. So when we— when I started this project five years ago, the approach we had was go through all the scientific evidence ever published on health and longevity, try to find the interventions that have the best evidence for effect size. And we just went down the list from the top-performing on down. So of course you start with exercise, nutrition, you know, sleep, and you work your way down to things like hyperbaric oxygen therapy and sauna and then rapamycin, metformin. And so we never actually had on our radar psychedelics. They were always either an ancient medicine, you know, being used in ritualistic practices, or being pointed at things like depression and anxiety in certain trials. But it was never understood as a rejuvenation protocol, something that was for anti-aging. And so we found a pre-clinical evidence in mice on psilocybin, and we thought, \"That's interesting.\" Uh, and so we did the world's most studied— the most quantified experiment doing psilocybin, three doses at 25 milligrams of psilocybin.","offset":60,"duration":60},{"text":"Host: Which are pretty high doses.","offset":120,"duration":1},{"text":"Bryan: It's— yeah, a clinical dose, very, very close to a hero dose. And we found that we think it's a longevity therapy.","offset":121,"duration":6},{"text":"Host: Let's get to that data in a minute, but then you decided to try 5-MeO this weekend.","offset":127,"duration":4},{"text":"Bryan: Yes.","offset":131,"duration":1},{"text":"Host: Walk me through the experience, because you televised the whole thing. It was live-streamed. You looked amazingly calm going into it and going through the process. Walk us through your experience.","offset":132,"duration":15},{"text":"Bryan: Yeah, I think those who have done 5-MeO would probably relate with me that it feels like an impossible task to explain what it's like. So that caveat said, I'll give it a go. I'm stunned, absolutely floored, speechless. You basically experience raw consciousness and raw intelligence. It's this— so whatever— when I say these words, take these words that I convey to you, take that idea, multiply it by a thousand, and then move out infinite depth, infinite width and depth and then dimensions, and like, that gives you kind of like a rough map of the size and space that you deal with.","offset":147,"duration":52},{"text":"Bryan: And it was incredibly hard, because you get blasted into this space that is so foreign, you don't even know what's happening.","offset":199,"duration":6},{"text":"Host: It happens very quickly.","offset":205,"duration":1},{"text":"Bryan: Like you inhale it— I did 9 milligrams of intramuscular and then 18 of vaporized— and it hits you within 10 seconds. You're just absolutely— you're out. And so, um, but what happens is you get in that space and then you—","offset":206,"duration":16},{"text":"Host: Visual changes? Everything?","offset":222,"duration":2},{"text":"Bryan: Very— very little visual. Uh, like you see on DMT, it's a very visual, you'll meet the, you know, like the elves or whatever else. This is not a visual experience. But you get in this world and you lock into basically you either panic because you feel like the gates of hell are going to open, that the stream of existence is just going to just tear you to shreds, it's going to shard you. And if you give up—","offset":224,"duration":29},{"text":"Host: Like break your brain.","offset":253,"duration":1},{"text":"Bryan: Yeah, like you feel like it's going to like threaten your sanity. Like is it going to chop you up into little pieces? And so in that moment you have to say, \"Do I try to wrestle this and I need to just like wait it out until it's over?\" or you just relent and you say yes. And you have to in that moment, you have to say yes so thoroughly. You have to release all attachment, all preconditions, all want, all desire. You have to release self, ego, control. You just have to just relent entirely. And then when you do that, it opened up this unimaginable bliss and euphoria. And again, this is like a V1 of trying to explain this, but if I list out the most dynamic experiences I've had as a human, you know, uh, like certain accomplishments or getting married or having a child or overcoming a difficulty or, like, you know, state your list of things, this is without question the most dynamic experience I've ever experienced as a human.","offset":254,"duration":64},{"text":"Host: Does the internal chatter, the internal monologue of the ego turn off?","offset":318,"duration":3},{"text":"Bryan: It does.","offset":321,"duration":1},{"text":"Host: So you can't hear yourself speaking. How do you rationalize what's going on if you don't have a dialogue going?","offset":322,"duration":5},{"text":"Bryan: It's this visceral feeling. Like you're hyper-aware of what's happening. It's not like you block out in the first like— when you take a very high dose, you don't really know what's happening in the first few minutes, but then you kind of come to and you're hyper-aware of everything. It's not visual, but it's this uh— you're in the depths of existence. It's just the most majestic thing ever seen, achievable by an intelligence— by intelligent life. I just can't imagine anything more miraculous.","offset":327,"duration":42},{"text":"Host: You've studied the biology, the biochemistry, what goes on in the brain as this molecule hits your neurons?","offset":369,"duration":9},{"text":"Bryan: Yeah, I mean, like, it um— I mean one, it completely dissolves your default mode network.","offset":378,"duration":5},{"text":"Host: Describe what that is.","offset":383,"duration":1},{"text":"Bryan: So like uh— it’s this engine that constructs self and ego. And so as you ruminate, you know, like you're going through—","offset":384,"duration":9},{"text":"Host: Thinking through your day, what’s next, how am I feeling, what should I be doing right now, constant conversation internally.","offset":393,"duration":5},{"text":"Bryan: Yeah, \"Do I feel bad about myself? Do I feel, you know, like I'm— am I shy? Am I like do I feel bad about whatever?\" Like you're doing this rumination stuff. Uh, kids don't have this rumination loop. Their default mode network is quiet. And as you age, you basically build up this default mode network into more stiffer patterns. And so as you age, your experience of reality becomes increasingly narrow. You have these big ruts that form. And so you can just see people in their patterns, like how open a child is to say very random things and as adults you're just very— you're shut in. Like when I did psilocybin, one of the reasons why we did it is because it does have this effect where it dampens the default mode network. And we could pick this up with Kernel, the brain interface. You can see how the default mode network weakens.","offset":398,"duration":49},{"text":"Bryan: Like, so basically think of the brain like a globe with airports scattered about. And you have certain traffic patterns like New York to London. You have a certain number of flights every day. That's like a very strong connection. But New York to um, you know, some small town in Arkansas has a very uh low traffic map. And so when you do something like psilocybin, it basically takes the airports, picks them up and then repositions them around the world. So they're just all scrambled. So the traffic patterns aren't the same.","offset":447,"duration":24},{"text":"Host: The neurons don't physically move, but the activity shifts around, right? The neurons are a little bit more random than they normally would be, which arguably drives neuroplasticity, causes those neurons to reach out for new connections. And when new connections are made, new behaviors, new ways of thinking emerge coming out of these therapeutics. Is that a fair way to describe it?","offset":471,"duration":23},{"text":"Bryan: Exactly right. Exactly right. So you look at my brain on psilocybin from Kernel, you see my patterns before, like the New York to London connection, you see my brain afterwards, and it's exactly what you said. New patterns are emergent, the old ones have quieted down. So a new map of connectivity. And so we saw that happen and that does generate a lot of neuroplasticity.","offset":494,"duration":19},{"text":"Host: And obviously this neuroplasticity, rewiring these connections in the brain, is what allows trauma victims or folks that have a certain wiring that they keep repeating in their brain, which causes the trauma and the anxiety in their lives, to get rewired, and then that trauma and that anxiety feels like it dissolves or melts away. Is that a fair—?","offset":513,"duration":19},{"text":"Bryan: Exactly right.","offset":532,"duration":1},{"text":"Host: Yeah. And so this— this has been documented in psilocybin. It's kind of well understood. How did you connect that psilocybin data to an effort in longevity, or was this just like a random idea, \"Let's try it out\"?","offset":533,"duration":13},{"text":"Bryan: Yeah, I mean well so we saw some mouse data that it had these effects. It also showed reduced inflammation. Uh, so we said like this is interesting because most longevity therapies do something with inflammation, right? Like inflammaging is the killer. So if you can lower inflammation, it's a very good sign. Uh, if you can do something that makes the brain more youthful and takes down those big ruts, that's also useful.","offset":546,"duration":24},{"text":"Bryan: What we found at psilocybin though is that it had— we found a first in human observation: it had this metabolic reset in the brain, where my blood glucose before this was in the top 99.5 percentile of all the population. After, it went to the top 99.9 percentile. Like, to move my blood glucose from that level is very, very hard. But it basically like uh— not like metformin where you're doing something with blood glucose, this just had a reset across the body. Also changed my microbiome. Uh, so we saw full-on effects. So then we said, \"Okay, if that had that consequence, 5-MeO may have some similar characteristics.\"","offset":570,"duration":37},{"text":"Host: But no one had done this in 5-MeO before.","offset":607,"duration":1},{"text":"Bryan: Exactly. So there’s— there’s some animal evidence, um, but it’s the— the similar dynamics of like, \"Can you take the brain and can you basically like smooth out the barnacles that accumulate?\" And 5-MeO-DMT compared to psilocybin, like just absolutely like blasted clean my default mode network.","offset":608,"duration":21},{"text":"Host: Turned it off completely.","offset":629,"duration":2},{"text":"Bryan: Yeah. It just doesn't run the same way. Uh, like for an example, like uh, this morning I woke up catching myself laughing in a dream. I have not laughed in a dream— I don't even know when I've ever laughed in a dream— but that is— after I woke up, I was like, \"That's really weird. Like, I don't remember laughing.\" I looked it up and like, that is a characteristic of a child.","offset":631,"duration":24},{"text":"Host: Right.","offset":655,"duration":1},{"text":"Bryan: And so you are restored to this child-like state. And I mean the past couple days I have felt child-like. You know, like yesterday morning I felt that, you know, emergent excitement, the bubbling of like, \"Today is so exciting. I'm going to do new things. I'm going to have new experiences.\" Uh, that you're just excited about all things. I haven't felt that— I don't even know when, you know, for so many years. So like, it really was uh profound on every layer. And I see and I'm stumbling through this because I don't even know how to talk about it yet.","offset":656,"duration":31},{"text":"Host: During the day, you're hanging out, you're walking around. Is your brain having the same normal chatter that it did before, or do you think that there's a persistent change in that default mode network?","offset":687,"duration":11},{"text":"Bryan: Yeah, definitely a change. Like without— I was with my partner Kate yesterday and we uh, I did something that made her upset. And so like in that situation, you know, like when couples are in that moment, you have like this negotiation: \"How do I sort this?\" And it all just became so clear to me, like when children have a fight, you have it out and then it’s just like done. And you move on. But then adults take that and they like package it up and they like weaponize it, be like, \"I got something on you and I'm going to move the chess pieces and like try to leverage this.\"","offset":698,"duration":35},{"text":"Host: Or they store it up like a snake in one of those things that pops out all the snakes later. You know, it's like—","offset":733,"duration":5},{"text":"Bryan: Exactly. Package it all up. Exactly. And so like we had this and I just felt uh absolutely like no need to escalate or to defend or to— like it was just easy. And uh, it was a breakthrough in our relationship, where I was able to communicate with her in a way. And so it's like laughing in my sleep, it's how I deal with my partner. When I walk around, I just feel so much— I feel so much more funny. You know, like my ability to make quips that are just immediate uh, you know. Like so yeah, I just feel renewed as a person in a way that I just really didn't imagine.","offset":738,"duration":38},{"text":"Host: Have you tried hallucinogenics before you started your longevity path a couple of years ago?","offset":776,"duration":7},{"text":"Bryan: Yeah.","offset":783,"duration":1},{"text":"Host: And did you do that recreationally or therapeutically?","offset":784,"duration":2},{"text":"Bryan: It was mostly therapeutic in that I had sold my company Braintree/Venmo, I got a divorce, I left the Mormon church, and I was trying to remap like, \"What is life? Who am I? What do I do?\" So it was in that rebuilding stage where I just dabbled of like— you know, I did ketamine at Kernel. So one of our first studies at Kernel is we said— ketamine was a up-and-coming therapy for depression— and we posed the question: \"What happens when you do ketamine?\" And so we did the world's most extensive measurement of ketamine with Kernel, before, during and after. And so that was interesting, like and it had some kind of you know, transient effect, but that's like a— a little league relative to 5-MeO.","offset":786,"duration":42},{"text":"Host: And so as you've gone through this, maybe share a little bit of the MRI data that you're gathering and the other data mapping neurological effects and tell us a little bit about what you've learned.","offset":828,"duration":10},{"text":"Bryan: So far, nothing. Uh, I have my subjective experience to share, but we— we have a structural brain MRI, we have a functional brain MRI, we did Kernel which is like an optical interface, and then I did real-time EEG capture.","offset":838,"duration":12},{"text":"Host: And we should just talk about— I think it's important— structural, you can see the— the physical brain; functional, you can see the activity in the brain, so neurons firing and neurons that are not firing, right? And then electrical actions that are measured by electrical devices.","offset":850,"duration":17},{"text":"Bryan: Exactly. So we basically like wanted— because the brain is very— so we've had a lot of success rejuvenating my heart and my lungs and muscle and body fat, but rejuvenating the brain is very hard.","offset":867,"duration":13},{"text":"Host: Right.","offset":880,"duration":1},{"text":"Bryan: And so we— this is why this is such a promising therapy. So we wanted to look at the brain uh through every modality possible. We wanted to look at the blood flow, structural, molecular, you know, the wave patterns. So it's a— it's a very high-fidelity quantification. And so we'll see what the data comes out. Uh, I'm very excited.","offset":881,"duration":16},{"text":"Host: You did this on psilocybin as well, right? You mapped the brain over time. What did you learn there?","offset":897,"duration":5},{"text":"Bryan: Dramatic uh restoration of youthful brain patterns.","offset":902,"duration":4},{"text":"Host: Yeah, right. Yeah. And what comes after 5-MeO? Like how far do you take this?","offset":906,"duration":9},{"text":"Bryan: Honestly, uh, I am so encouraged by psychedelics. I, you know, like in— in the community where I hang out, psychedelics have always been understood as, you know, it's like a retreat or it's like a— a ritual you go to like do various explorations, but never in the world of longevity. It's never been understood as that thing. And now after seeing the data, I— and of course you have to be very careful when talking about psychedelics because they're extremely powerful. It's not like go out and do them everybody, right? It's like it needs to be done properly with a licensed professional, it needs to be done carefully, the person needs to be in the right state. Like it is not to be taken lightly. But I am uh more interested than ever in psychedelic compounds. They're just uniquely powerful.","offset":915,"duration":50},{"text":"Host: There's some arguments to be made that psychedelics can induce permanent psychosis, cause functional changes and drive some people that might be predisposed into schizophrenic states. How did you get over those risks? Because for a lot of people that would turn them off to trying psychedelics, and it's not a non-zero percentage of people that suffer these consequences.","offset":965,"duration":23},{"text":"Bryan: Yeah. I agree. And also the people who have really bad trips that leave them scarred. So it— there really is— and I think in part of it is uh what could be contributing to this is uh people who for example have tried magic mushrooms, you know, it's in a social situation, someone's got a bag, you pull out some mushrooms, it's like, \"Yeah, like weigh's blank,\" and they pop it in, but they have no idea what kind of mushroom strain they're eating, they don't know what the dose of psilocybin is. And so it's like unquantified, unsupervised, wrong set and setting. And so as much of it I think you can— the risk persists, but I don't think we've— we've approached psychedelics with the appropriate rigor that we should to make it safe. And so it's not to say that we can solve for the safety issues for all people. Some people just may not be the appropriate candidate for it. But I think if we do create a safety structure around it, they could deliver the benefits people want uh without you know, less of the risk. But definitely I agree with you, like it again, it deserves all the caution in the world.","offset":988,"duration":59},{"text":"Host: Do you think it's neurogenic, neuroplasticity, trauma resolution? I mean what is the way that this is going to be allowed to become call it a medical therapeutic that can be more broadly trialed and then eventually figure out how to bring it to people without it being carrying all the risks and burdens that it does today?","offset":1047,"duration":21},{"text":"Bryan: I mean if I just subjectively compare my experience with 5-MeO to having a better diet and exercising every day and uh sleeping well and doing the sauna and doing hyperbaric oxygen therapy, this was more efficacious than all of them in terms of the reset of me as a human. It— it just is incomparable. And I guess I'm— I'm really left pondering— for this molecule to have such a gigantic impact. Now like how long will it last? What's the decay curve like? You know, will I find uh I become the former Bryan within 30 days, 60 days? I have to repeat this again? I don't know. But it really is, you know, when you sleep well you feel great. When you exercise, great. But like nothing like what 5-MeO did in terms of— of like the reset of me as a human.","offset":1068,"duration":47},{"text":"Host: So let's just talk about the consequences outside of the physiological, which is life. There are lots of stories and friends that I have that and people that I know that have tried a heavy psychedelic, like an ayahuasca or something. They were the CEO of a company, and then they quit their company and they go off to the jungle, leave their family, divorce their— their partner, uh make such dramatic life changes because their perspective has been shifted so much that they reevaluate what matters in life to such a degree that they give up a lot of the things that mattered before. In the wake of that, there are people that feel they're a victim of that behavioral shift: the investors in the company, the employees, the family members, etc. Can you just talk a little bit about those broad risks because we've seen it and I'm— and I don't know if you've seen the same, but friends that have kind of like said, \"I have this new perspective, I'm giving up my life.\"","offset":1115,"duration":59},{"text":"Bryan: I've seen the same thing, and I think uh one investor told me that he even put it in the deal docs: that, you know, if we invest, you're not going to do these psychedelics. Because they wanted to minimize the risk profile. It's a thing.","offset":1174,"duration":14},{"text":"Host: In your— in an investment in you?","offset":1188,"duration":1},{"text":"Bryan: No, I just— because I've been doing this, uh people bring this up as a topic of conversation, and so they say like, \"I see you doing this for longevity, but you know, like I've seen so many examples where people put money in, then you lose the founder. Like they're off, and now everyone's high and dry.\" And so they were telling me that they put into deal docs that they can't do this for the duration of the company.","offset":1189,"duration":24},{"text":"Bryan: And so it is a thing, and you know, I— I have nothing to say about it other than I know it happens. Uh, also I would say that most people in the tech world that I'm familiar with, again they've done this in retreat centers or in social environments. It's not quantified, it's not set and setting. I mean so it's a different thing.","offset":1213,"duration":21},{"text":"Bryan: But I will say like, you know, I— I guess me as a person, what I'm trying to focus on, I came back even more motivated to do what I'm doing now. Uh, I don't have a desire to go off in the woods, you know, and like live that kind of life. It— it emboldened me to work on these things, but no question about it, you— you do have a dramatic shift in perspective, and it's— it's very hard to get around.","offset":1234,"duration":22},{"text":"Host: It begs a very important philosophical question: who am I? If I'm defined by my experiences, it roughly equates to my neurons are wired in a way that's a consequence of my experiences. And if I go in and take a drug and in a few hours rewire all my neurons, am I the same person? What makes Bryan Bryan? You can maybe recall some memories of Bryan prior to taking the psychedelic, but Bryan as a person has been rewired. Are you a different person now and what does that say about are we ever a persistent person?","offset":1256,"duration":42},{"text":"Bryan: Yeah. Your question is spot-on. Probably the most dramatic reconstruction of your 60-plus trillion cells than anything you can do in life. You know, like maybe like a near-death experience, you know, would maybe uh be close, but it's a dramatic rewiring of you as a human.","offset":1298,"duration":17},{"text":"Host: Your values can change too.","offset":1315,"duration":1},{"text":"Bryan: That's right.","offset":1316,"duration":1},{"text":"Host: And you could judge the values pre and post, right? You could judge values ascribed to you by a religion or perhaps values ascribed to you by responsibility to family members, children, spouses, partners, what have you. You abandon them after you go through this change. So your values have changed. Is it right or wrong? I think is another important question that comes out of all this.","offset":1317,"duration":21},{"text":"Bryan: I agree, and like you now like you now think about that— that's through the frame where the world changes at a certain speed. Now you take the world where it's changing faster. So we now know that it's hard to predict what's going to happen two weeks from now or a month, right? Like things are changing very quickly. And so now you come up with this practical question: can humans change fast enough in the world where AI is the dominant engine of innovation?","offset":1338,"duration":28},{"text":"Bryan: And so in that case like you may want psychedelics as your ally to say, \"As a human I'm struggling to like move with the change.\" Uh, so there's potentially where it— it flips from a liability to an asset where like now I do want that restructure changing even though you have some tail risk of like maybe my priorities will shift.","offset":1366,"duration":20},{"text":"Host: I think you have profound what I would call psychoflexibility, and I think most people don't. They have either a disinterest in changing who they are overnight or they're fearful of the— the ramifications or the experience and that they wouldn't go through it. How far would you take it? Would you wire yourself up to a Neuralink or neural enhancement device that would give you the ability to have information on demand and maybe change your personality and capacity as a human through an implant? Would you consider doing something like that?","offset":1386,"duration":30},{"text":"Bryan: Yes.","offset":1416,"duration":1},{"text":"Host: You would. Would you consider a transgenic system where you basically take a plasmid which would then express a set of proteins in your body and change uh gene expression profiles and cells in your body and basically could rewire you as a different person?","offset":1417,"duration":14},{"text":"Bryan: Yes.","offset":1431,"duration":1},{"text":"Host: Yes. Is there a limit to what you would try?","offset":1432,"duration":2},{"text":"Bryan: No.","offset":1434,"duration":1},{"text":"Host: Interesting. Where do you think that comes from?","offset":1435,"duration":1},{"text":"Bryan: I think I uh I find it to be the most exciting configuration of life. Uh, the ability to play on the frontier. Uh, novelty and expedition and challenge. That's really my—","offset":1436,"duration":13},{"text":"Host: Did you always have it, or are you responding to childhood suppression of those opportunities?","offset":1449,"duration":6},{"text":"Bryan: I mean it's— it's probably— it's probably an overcompensation of— of trauma response like most things are. And so you know, as a child I lived in a very structured religious environment where things were cemented. Like here's the story, here's the plan, here's what you do and what you don't do. Uh, and so yeah maybe it's probably just I'm now uh flipped in the opposite. And so I mean that's like probably true that I really uh I don't trust my internal generation of reality. You know, I know I'm always making things up. I've got 188 chronic biases like all humans do. So I'm just I'm generally suspicious of all things all time and I don't take myself very seriously. So I just find the frontier play space to be like right now, I mean you know, what you're doing in building companies, like you just open up a— a toolkit and say like, \"What can I build? And how do I modify?\" And uh so I agree with you, I do have a strong proclivity towards openness to play.","offset":1455,"duration":51},{"text":"Host: Do you find that you've been challenged in maintaining I would call it external responsibility? As you explore and enhance yourself so much, do you give up the responsibility to others around you who maybe are dependent on you or or in need of you?","offset":1506,"duration":14},{"text":"Bryan: Yeah. I have three kids. And so uh I do think about them a lot. And uh being a father is a really important thing to me and it's an important part of my identity. And so that has not changed. So I've never uh vacillated on that or changed my disposition towards that. For those around me, I guess fortunately I have a social group that just says \"Go and play.\" There's really no one in my life that tries to claw me back. There's no velcro. Yeah. It's just all encouraging. And so that I guess I feel very fortunate that everyone around me and they're willing to take the risks. I mean this is you know when I sat down for 5-MeO, I mean my partner Kate, like she's got a ton of risk. Like what if it goes poorly? What if I change my perspectives? What if something bad happens? So—","offset":1520,"duration":45},{"text":"Host: Well, one could make an argument that taking that degree of risk where something could have gone wrong, the people around you are enabling versus being supportive. I mean that’s a consequence.","offset":1565,"duration":10},{"text":"Host: But let's shift topics to other uh modalities for longevity. What else is on the horizon? So you've had this profound set of experiences with psychedelics. You've documented in a very extraordinary and exquisite fashion all of the other things that you've been doing as interventions. Are there other things that are on the horizon that you're either excited about or that you're considering yourself?","offset":1575,"duration":25},{"text":"Bryan: Yeah, I mean two of the ones that we've spoken about, cell therapy and gene therapy. Yeah. Uh, they um they're all in the pipeline. And so they're not ready yet. We've knocked out all the stuff you can do today. Like we've gone through it all, done it all. Uh, the next-gen therapies are just not there yet. So we're looking at mitochondrial rejuvenation.","offset":1600,"duration":19},{"text":"Host: I think that's incredible. I think mitochondrial augmentation therapy and there was a paper I saw where in order to get the mitochondria in the cell, they coated the mitochondria in effectively a red blood cell envelope which made it more transportable into cells and less uh attack by the immune system, which is incredible. And I— I'm a big, big, big believer in this— this— this course of therapy. I think this is going to be a whole therapeutic modality that no one has even recognized.","offset":1619,"duration":24},{"text":"Bryan: I agree. We have our first uh mitochondria therapy lined up. So.","offset":1643,"duration":3},{"text":"Host: How are you going to do it? You're— you’re like 99.9%. You need someone who's like 48.7% to try the mitochondrial augment—. Particularly like you know, I think they tried it in Parkinson's patients, Alzheimer's patients, that's where you could really see profound shifts in in certain metrics. For you, it's like 99.9 to what? Like.","offset":1646,"duration":18},{"text":"Bryan: Yeah. Yeah, I mean I have the mitochondria you know of a 48-year-old, right? Like so what if— what if I could—","offset":1664,"duration":6},{"text":"Host: Your siblings?","offset":1670,"duration":1},{"text":"Bryan: Yes.","offset":1671,"duration":0},{"text":"Host: You could go to your sibling's child because the mitochondria is passed maternally, because it’s in the— it’s in the egg cell. So it's the mother's mitochondria. So if you go down the mother's line maternally, if you have a sister who has a kid, they're going to have very young mitochondria. You can take a little blood sample and then grow their mitochondria extensively and use that as a biological match to you.","offset":1671,"duration":22},{"text":"Bryan: This is a perfect extension. I've had a blood boy as a son, so now I'm just going to go to the extended family and be like, \"Guys, it's a— it’s a family project.\"","offset":1693,"duration":9},{"text":"Host: Yeah, family project. Exactly. Yeah, well that one's super interesting.","offset":1702,"duration":2},{"text":"Bryan: And we also have one that we're doing— I'm now building—","offset":1704,"duration":3},{"text":"Host: Sorry, are you going to do your own mitochondrial transplantation and you're going to build a bioreactor, or you using working with one of the third parties that are already doing this?","offset":1707,"duration":5},{"text":"Bryan: A third company, yes. So I'll give— we'll do a blood draw in the next week or two. They'll spin up—","offset":1712,"duration":4},{"text":"Host: They'll do it.","offset":1716,"duration":1},{"text":"Bryan: They'll do it. Okay. Yep.","offset":1717,"duration":2},{"text":"Host: So you're going to get your mitochondria, which have some you know the problem with mitochondria as you know is mitochondrial DNA degradation over time, right? It accelerates for certain people, but that way if you go back to a young person you have young mitochondria, but then you're going to multiply yours out.","offset":1719,"duration":15},{"text":"Bryan: Yes.","offset":1734,"duration":1},{"text":"Host: And probably select a little bit or for healthier ones?","offset":1735,"duration":2},{"text":"Bryan: Exactly.","offset":1737,"duration":1},{"text":"Host: Right, okay. And then put it back in.","offset":1738,"duration":1},{"text":"Bryan: Yep. So it's very— I mean exploratory. You know, we don't know. Uh we're one of the first. They're in Phase 2 now.","offset":1739,"duration":6},{"text":"Host: Do you sprint?","offset":1745,"duration":1},{"text":"Bryan: Yes, I do.","offset":1746,"duration":1},{"text":"Host: So you could probably score if you did it intramuscular like mitochondrial therapy you could sprint see your score.","offset":1747,"duration":5},{"text":"Bryan: That's a great idea.","offset":1752,"duration":1},{"text":"Host: Yeah, thank you. Yeah, we could do that for you. Yeah, that would be a great way to measure it from a rather than just a basic biomarker perspective. It'd be really interesting to see.","offset":1753,"duration":6},{"text":"Bryan: Yeah. Sprinting is one of the most underappreciated longevity therapies.","offset":1759,"duration":5},{"text":"Host: Yeah, I don't do it. Um, I've got the the age of a 74-year-old uh roughly.","offset":1764,"duration":6},{"text":"Bryan: Is that right?","offset":1770,"duration":1},{"text":"Host: No, no. Not personally. I'm— I'm definitely not keeping track with you.","offset":1771,"duration":5},{"text":"Host: Would you consider or have you looked at any plasmids where you take a gene as DNA, put it in your body and then that gene makes a protein in your body that that does something?","offset":1776,"duration":9},{"text":"Bryan: Yeah. Like the one we were looking at in the Follistatin expression. Yeah, exactly. So the mesenchymal stem cells packaged up with the Follistatin delivery. Uh, you know that showed that over 50% of tissues getting that rejuvenation.","offset":1785,"duration":10},{"text":"Host: It’s unbelievable. Unbelievable.","offset":1795,"duration":1},{"text":"Bryan: Unbelievable. It's like the best— it’s the best demonstration in the entire world.","offset":1796,"duration":2},{"text":"Host: That's perfect for tissue regeneration. Like as a particular application set, tissue regeneration using that sort of system seems like a no-brainer.","offset":1798,"duration":7},{"text":"Bryan: It's— it’s safe, right? So yeah so I— reached out to that Chinese professor. I'm really interested in seeing it replicated. I would love—","offset":1805,"duration":8},{"text":"Host: You reached out to the Chinese professor?","offset":1813,"duration":2},{"text":"Bryan: Yeah.","offset":1815,"duration":0},{"text":"Host: That’s awesome. We sent that paper back and forth. Yeah, yeah exactly. That's awesome. Did he respond?","offset":1815,"duration":5},{"text":"Bryan: Uh, yeah.","offset":1820,"duration":0},{"text":"Host: Awesome. Good. Uh, so we I'd love to do that. Uh, I'd love to actually build it ourselves. But that's like a two-year project. So uh.","offset":1820,"duration":10},{"text":"Host: AI can help.","offset":1830,"duration":1},{"text":"Bryan: Make it faster.","offset":1831,"duration":1},{"text":"Host: That's true. Yeah actually that's true.","offset":1832,"duration":1},{"text":"Bryan: AI as a project manager for these sorts of programs is—","offset":1833,"duration":2},{"text":"Host: You know that's true. We spoke about this six months ago and things are so different.","offset":1835,"duration":3},{"text":"Bryan: So different now six months later in terms of standing that up.","offset":1838,"duration":3},{"text":"Host: Um, so that one's cool. So I think that's a good a good option.","offset":1841,"duration":3},{"text":"Bryan: Also I'm doing uh Bryan Johnson organoids. So uh we took my iPSCs.","offset":1844,"duration":5},{"text":"Host: Induced pluripotent stem cells.","offset":1849,"duration":1},{"text":"Bryan: Exactly.","offset":1850,"duration":1},{"text":"Host: So you took your cells, turned them into stem cells.","offset":1851,"duration":2},{"text":"Bryan: Yeah.","offset":1853,"duration":0},{"text":"Bryan: So now we're doing in-dish. So now we have like a Bryan Johnson heart, liver, lungs and now we're going to try molecules on me in in-dish.","offset":1853,"duration":7},{"text":"Host: So you've app— so so let me just walk the audience through this. So you take cells off of your skin or something?","offset":1860,"duration":6},{"text":"Bryan: Blood.","offset":1866,"duration":1},{"text":"Host: Blood. And then you put these Yamanaka factor proteins on those cells, causes those cells to become stem cells, which means they can then turn into any other cell. And then you put other proteins on them to turn them into a heart cell or a eye cell or or what have you. And now you've got a store of these tissue-specific Bryan Johnson cells that you then use for—?","offset":1867,"duration":19},{"text":"Bryan: Like you can say, \"Okay, uh what if you give Bryan Johnson blank, you know drug? What is— what happens? Is it good? Is it bad? What are the side effects? What are the complications?\"","offset":1886,"duration":9},{"text":"Host: In the petri dish, you put the drug in there, see what happens.","offset":1895,"duration":2},{"text":"Bryan: Exactly.","offset":1897,"duration":1},{"text":"Host: Okay, got it.","offset":1898,"duration":1},{"text":"Bryan: So you just like you can simulate all these experiments. So now you you get the advantage of time of acceleration of like what to take, why, what dose, uh what combinatorial things to consider. And so we have the organoids stood up. We haven't done our first tests yet. So that's interesting because now I have to do this old-school methodology like put it in my body, wait to see what happens, is it good, is it bad, what you know how does it affect everything? So.","offset":1899,"duration":25},{"text":"Host: That's a good one. But I mean I don't know. We'll see. It’s cool in concept. I mean TBD if it actually works, so we'll see.","offset":1924,"duration":2},{"text":"Host: Have you tracked any of the alternatives to Yamanaka factors, the factor discovery work that's going on, and do you think there's anything worth testing at this stage?","offset":1926,"duration":9},{"text":"Bryan: Yeah, I'm an investor in New Limit. So I've talked to them about where they're at and—","offset":1935,"duration":4},{"text":"Host: Blake and Brian's company.","offset":1939,"duration":2},{"text":"Bryan: They've done uh I mean they've made remarkable progress. They— they figured out how to computationally solve the discovery process. And so I they uh they're much faster than they initially thought. And so that's very encouraging.","offset":1941,"duration":11},{"text":"Host: You know the big challenge with Yamanaka factors is always dosing. If you over-dose a cell, a one cell, that cell can become a cancer cell and take off as a tumor. So the sensitivity that you need to have to get the right number of the factors, which is a protein, into the cell needs to be perfectly tuned. So I have a theory that this will end up being solved by cellular switches. That we'll end up putting machinery into the cells that can turn on or off the protein synthesis at the right dosing based on the measurement of gene expression in the cell. That's my theory on where this will end up.","offset":1952,"duration":29},{"text":"Bryan: That makes a lot of sense. Any other control mechanism will be inadequate.","offset":1981,"duration":3},{"text":"Host: That's right. The feedback loop just— All you need is one error and you're you're in trouble. But it is the most profound I think technology that humanity's dealing with today besides AI. We're not quite there with fusion, which I would argue is probably a distant third, but it is very powerful what's possible.","offset":1984,"duration":18},{"text":"Bryan: I agree. And like in the future like I think we'll look back and we'll see GLP-1s as the first big drop of like, \"What? I can just inject myself and like it solves hunger and. Totally.\" And then the second will probably be something like New Limit or one of these Follistatin or one of these plasmid-based Follistatin-3 therapies where it will show real-life like dramatic changes. And then humanity will shift as uh longevity being a vision of sci-fi rich people pursuit to something that is truly— I mean go back to like the conversation on on the temptation towards socialism. Right, like if you can feel robust in your ability to pursue life and be healthy and vibrant and uh in control, I think these things could have dramatic changes to society, not just in health but like in our mentality.","offset":2002,"duration":47},{"text":"Host: Any form of abundance, whether it's abundance in food, in energy, in housing, in mobility, in lifespan, the more abundance people get, the happier they are. And the more you're improving abundance in the world, the the better we are going to live as a group of people together on planet Earth. The the happier we will all be with each other.","offset":2049,"duration":17},{"text":"Bryan: But I think like honestly like a lot of the the external conflict only comes from internal unhappiness.","offset":2066,"duration":6},{"text":"Host: 100%.","offset":2072,"duration":1},{"text":"Bryan: And so if you look at the general malaise of like American society, like no wonder uh things are shitty, right? You've got metabo— 84% of people have metabolic disorder, over 40% of people are obese, like we're just in really poor health. Nobody's sleeping. Everyone's on their phone. We have mental health issues. Like no wonder you have the proclivity towards these kinds of outcomes. Like so if you could get the health in check, it changes the psychological disposition of you, your community, your country, like you have much more of a can-do attitude, like \"I can take on the world and I can do hard things,\" but when you're not feeling well like it's just everything is just so much harder.","offset":2073,"duration":34},{"text":"Host: 100%.","offset":2107,"duration":1},{"text":"Host: And in light of all of these new therapeutic modalities and these new opportunities that seem to be biologically proven and have these profound effects, why continue to tinker with psychedelics? Like are they as profound or are they a complement, or like how do you think about fitting all of this portfolio of things that you're looking at together?","offset":2108,"duration":17},{"text":"Bryan: I mean I guess the question is uh I forget on the Follistatin-3 study, I don't know if they saw brain rejuvenation.","offset":2125,"duration":6},{"text":"Host: Didn't see that.","offset":2131,"duration":1},{"text":"Bryan: I did not see that. And I don't I don't remember. I mean it is a very complicated organ.","offset":2132,"duration":4},{"text":"Host: Yeah, exactly.","offset":2136,"duration":1},{"text":"Bryan: And it's insane, like you know you can grow muscle tissue back and you can grow skin tissue back and it's kind of like okay I grew a little ex—. Like if you grow the the neurons back maybe in the wrong way or like we don't know because it's never been done before. So understanding the consequence of neuro-regeneration is like—","offset":2137,"duration":20},{"text":"Bryan: So I wonder like if the role that might play, like you know maybe psilocybin and 5-MeO won't be uh meaningful for like basic functions of the body, but maybe it's the uh the outperformer in youthfulness of your uh of your disposition towards reality. Like one thing I'm apprehensive about is you know I'm 48, and so as you start climbing to your 50s, 60s, you do really narrow. Like your ambition goes from \"I can do anything\" to start you know narrowing down further and further, and I worry about using— losing a youthful disposition of a can-do attitude of anything is possible.","offset":2157,"duration":46},{"text":"Host: Totally.","offset":2203,"duration":1},{"text":"Bryan: And maybe that's the role of psychedelics is you just get a wash of like the snapback of like \"I can\" and \"I can bounce.\" That definitely been the case for me. So I think they do probably play a really important role of like they're probably a set of things that for certain people that will um basically like I feel like it was like 30, 40 years of psychological rejuvenation. Like you to transport me back to a child-like state. That is insane. I don't get that from the sauna or from eating well or from sleeping well. Like I'm still— so definitely just unique.","offset":2204,"duration":35},{"text":"Host: Amazing. Well listen, I'm going to go drink alcohol and eat carbs and stay out late. I don't know, what are you going to do?","offset":2239,"duration":6},{"text":"Bryan: I'm going to go to bed on time and do do my wind down routine.","offset":2245,"duration":2},{"text":"Host: Yeah, you do you.","offset":2247,"duration":1},{"text":"Bryan: And you you as well. Enjoy it.","offset":2248,"duration":1},{"text":"Host: I will. I appreciate it. This has been great. Bryan Johnson, thank you.","offset":2249,"duration":3},{"text":"Bryan: Yeah, thanks.","offset":2252,"duration":1},{"text":"Host: That was awesome.","offset":2253,"duration":1},{"text":"Bryan: That was great.","offset":2254,"duration":15}],"logs":[{"elapsed":"0.0","message":"Downloading audio from YouTube...","detail":null},{"elapsed":"0.0","message":"Trying download with browser cookies (ad-free)...","detail":null},{"elapsed":"4.2","message":"⚠ Cookie download failed: WARNING: [youtube] [jsc] Error solving n challenge request using \"deno\" provider: Error running deno process (returncode: 1): \u001b[0m\u001b[1m\u001b[31merror\u001b[0m: Uncaught (in promise) TypeError: Cannot read prope","detail":null},{"elapsed":"4.2","message":"Retrying without cookies...","detail":null},{"elapsed":"24.7","message":"⚠ Downloaded without cookies — audio may contain ads","detail":null},{"elapsed":"24.7","message":"Audio downloaded (24.7 MB) in 24.7s","detail":"File size: 24.7 MB"},{"elapsed":"24.7","message":"Video title: Bryan Johnson: I Just Took the Most Powerful Dose of DMT in the World... Here's What It Was Like","detail":null},{"elapsed":"24.8","message":"Audio duration: 37:57 (38.0 min)","detail":null},{"elapsed":"24.8","message":"Uploading audio to Gemini File API...","detail":null},{"elapsed":"28.8","message":"Audio uploaded in 4.0s","detail":"File ref: files/6401bnfx8hr3"},{"elapsed":"28.8","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"88.8","message":"Transcription complete in 64.0s","detail":"41613 chars received"},{"elapsed":"88.8","message":"Transcription tokens: 57,162 in / 11,172 out — cost: $0.0621","detail":null},{"elapsed":"88.8","message":"Parsed 186 transcript segments","detail":null},{"elapsed":"88.8","message":"Transcript coverage: 37:34 of 37:57 (99%) — OK","detail":null},{"elapsed":"88.8","message":"Total transcription time: 64.0s — 186 segments","detail":null},{"elapsed":"88.8","message":"Analyzing topics across 186 segments with gemini-3.1-pro-preview...","detail":null},{"elapsed":"133.2","message":"Topic analysis complete in 44.4s — found 16 topics","detail":null},{"elapsed":"133.2","message":"Analysis tokens: 12,175 in / 1,184 out / 4,497 thinking — cost: $0.0925","detail":null},{"elapsed":"133.2","message":"Pipeline finished in 133.2s — total cost: $0.1546 (86,190 tokens)","detail":null}]} \ No newline at end of file diff --git a/history/1775430672822-lclDwnfnOGc.json b/history/1775430672822-lclDwnfnOGc.json new file mode 100644 index 0000000..74be575 --- /dev/null +++ b/history/1775430672822-lclDwnfnOGc.json @@ -0,0 +1 @@ +{"id":"1775430672822-lclDwnfnOGc","videoId":"lclDwnfnOGc","url":"https://www.youtube.com/watch?v=lclDwnfnOGc","title":"MacroVoices #526 Matt Barrie: Pay To PrAI","type":"youtube","topicCount":19,"segmentCount":139,"createdAt":"2026-04-05T23:11:12.823Z","uploadDate":"20260402","chunks":[{"title":"Introduction and Episode Preview","summary":"Eric Townsend previews the episode's double-header format. He introduces upcoming segments featuring Matt Barrie on artificial intelligence and Dr. Anas Alhajji on the escalating Iran conflict following President Trump's recent speech.","entries":[{"text":"Host: This is MacroVoices, the free weekly financial podcast targeting professional finance, high net-worth individuals, family offices, and other sophisticated investors. MacroVoices is all about the brightest minds in the world of finance and macroeconomics telling it like it is, bullish or bearish, no holds barred. Now, here are your hosts, Eric Townsend and Patrick Ceresna.","offset":0,"duration":28},{"text":"Eric: MacroVoices episode 526 was produced on April 2nd, 2026. I'm Eric Townsend. We've got another MacroVoices double header lined up for you, and it's going to be a doozy. President Trump gave an address Wednesday night that surprised the markets. So I'm recording earlier than usual this week on Wednesday night about an hour after President Trump's speech, in which he said that if no deal can be reached, the US plans include targeting all of Iran's civilian electric power generation plants, probably simultaneously. That's exactly the red line that Iran has previously said would cause it to retaliate by targeting desalination plants and the UAE's Barakah nuclear power station.","offset":28,"duration":53},{"text":"Eric: Now we know the president's negotiating style is to make dire threats and then walk them back once a deal is reached. So hopefully the threat of targeting civilian power generation infrastructure will come off the table soon. But overall, my take is that this conflict is heating up, not cooling down as the market was interpreting before President Trump's Wednesday evening speech. And the president was clear in that speech in saying that the US would be hitting Iran very hard over the next two weeks if no deal is reached.","offset":81,"duration":37},{"text":"Eric: We're going to kick things off with an exceptional performance by freelancer.com CEO Matt Barrie, who returns as this week's feature interview guest for a full interview on the latest developments on artificial intelligence, what they mean for private credit markets, why the AI business model is setting the stage for an eventual market dislocation on the scale of the 2000 .com bust, why paper-token inference pricing is inevitable and why it will collapse the current AI business model, and much more.","offset":118,"duration":39},{"text":"Eric: Then for this week's Iran conflict update, Energy Outlook Advisors founder and managing partner Dr. Anas Alhajji returns as this week's second feature interview guest, and it's going to run just as long as our first feature interview because there was so much to cover after the president's Wednesday night address. So this is going to be a long episode, but a very important one. So sit back, relax, and expect some really exceptional content from both of our guests.","offset":157,"duration":32}],"startTime":0},{"title":"Weekly Macro Scoreboard","summary":"Patrick Ceresna provides the weekly macro scoreboard, detailing the latest price action for the S&P 500, US Dollar Index, and key commodities, while previewing the week's economic data.","entries":[{"text":"Patrick: And I'm Patrick Ceresna with the macro scoreboard week over week as of the close of Wednesday, April 2nd, 2026. The S&P 500 index down 24 basis points, trading at 65.75. Markets put together an oversold bounce, but will rallies fail with this geopolitical backdrop? We'll take a closer look at that chart and the key technical levels to watch in the post-game segment.","offset":189,"duration":27},{"text":"Patrick: The US Dollar Index down nine basis points, trading at 99.55. The May WTI crude oil contract up 1085 basis points to 100 spot 12. The May RBOB gasoline up 439 basis points, trading at 3.09. The June gold contract up 500 basis points to 48.13. Gold's approaching its 50-day moving average, bouncing from its oversold conditions.","offset":216,"duration":48},{"text":"Patrick: The May copper contract up 162 basis points, trading at 5.65. The April uranium contract down 12 basis points, trading at 84.30. And the US 10-year treasury yield up four basis points, trading at 4.37. The key news to watch this week is Friday's jobs numbers, and next week we have the ISM services PMIs, the core PCE and CPI inflation numbers, and the FOMC meeting minutes.","offset":264,"duration":28},{"text":"Patrick: This week's feature interview guest is freelancer.com founder Matt Barrie. Eric and Matt discuss the sustainability of the AI business model, why rising risks and weak unit economics could lead to a shakeout similar to the .com era, and how AI's impact on software and private credit could create broader market stress. And stay tuned for a special follow-up with Dr. Anas Alhajji where we break down the escalating Iran conflict and its implications on global energy markets. Eric's interview with Matt Barrie is coming up as MacroVoices continues right here at MacroVoices.com.","offset":292,"duration":48}],"startTime":189},{"title":"OpenAI's $122 Billion Fundraising Round","summary":"Matt Barrie breaks down OpenAI's massive $122 billion bridge round ahead of its anticipated IPO. He highlights the extreme reliance on vendor financing from tech giants like Amazon and Nvidia over actual cash.","entries":[{"text":"Eric: And now with this week's special guest, here is your host, Eric Townsend. Joining me now is freelancer.com founder Matt Barrie. As usual, Matt has written an excellent paper about AI. This one is called \"Pay to PrAI,\" that's pay to P-R-A-I. You can find that linked in your research roundup email. If you don't have a research roundup email, it means you're not yet registered at MacroVoices.com. Just go to our homepage, MacroVoices.com, look for the red button above Matt's picture on the homepage that says \"Looking for the downloads.\"","offset":340,"duration":43},{"text":"Eric: Matt, before we even get into all of what's going on in AI, we've got some news just as we're recording this on Tuesday evening US time. There's some recent news just in the last day or so, which is, you know, a lot of companies before they IPO, they'll do a little bridge round, maybe 10-20 million bucks just to cover some expenses until they get to their actual IPO. OpenAI is planning an IPO. They did a little bridge round, 122 billion with a B dollars. All-time record for a private fundraising round. And what is that, something like 100 times bigger than any private fundraising round has ever occurred like before 2025. Why did they need 122 billion just to bridge them from now to their IPO, which is expected in less than a year?","offset":383,"duration":45},{"text":"Matt: Thanks for having me. It truly is stupendous. I mean, before 2025, the largest sort of private venture rounds were in the single-digit billions. The headline number is 122 billion raised on a 730 billion pre-money valuation. When you get down to the actual segmentation of kind of what's going on, it seems that it's only about 25 billion dollars worth of cash. It seems to be more of a vendor financing than an actual straight cash injection.","offset":428,"duration":33},{"text":"Matt: You've got Amazon, Nvidia, and SoftBank primarily putting the money, or the in-kind, in. Amazon's putting in 50 billion, but that's contingent on OpenAI spending 100 billion, I think over the next eight years on their compute, which I'm sure won't make Microsoft happy, and it seems like a good deal, at least on paper, for Amazon. So there's 15 billion going in up front and 35 billion is furthermore contingent on the company either going public by 2028 or achieving artificial general intelligence. I'm not sure how they're going to really define that. I think the underlying definition is a panel of experts will make a decision, yes or no, which is a bit strange for a financial decision.","offset":461,"duration":33},{"text":"Matt: There's 15 billion down up front, 35 billion contingent on going public or AGI for a 100 billion commitment the other way around, so it's a bit like a procurement round. SoftBank loves doing this sort of, I like to call them Russian stands, where they kind of lead rounds and mark up valuations to the moon. We saw it with WeWork, we're seeing it again with Enron, I mean OpenAI. They've already put in about 40 billion, they're putting another 30 billion in. But to raise that money, they don't actually have the cash on the balance sheet, so they've taken a 12-month bridge loan for 40 billion and they're tranching in 10 billion at a time over the course of the year for a total of 30 billion.","offset":494,"duration":37},{"text":"Matt: And obviously that's kind of just getting them through to the IPO so they've got a liquidity event. And then Nvidia is putting in in-kind, as they tend to be doing in all these sort of circular economy sort of deals in the AI space, where GPUs and infrastructure will be provided to the tune of 30 billion into the round. So it's about a 25 billion dollar round of cash sort of up front, 10 from SoftBank, 15 from Amazon. We'll see if the rest of the money comes in, but the rest is in-kind.","offset":531,"duration":27},{"text":"Matt: So it seems from looking at this, and if you look at the compute numbers, I mean they truly are astronomical that are being contributed in the form of, you know, either Nvidia credits, I think there's like three gigawatts of inference and two gigawatts of training capacity as part of this investment. You know, that's sort of the power that gets drawn by a small country. So it seems to be what they're trying to do is scale up the spend on compute so much that they can find a way to bring the unit economics down because that's really the key problem in the space, that nobody in the AI compute space is making any money other than really Nvidia who does about 160 billion of revenue and 100 billion of earnings, and then TSMC who provide the chips to Nvidia, but the rest of the space is actually negative on using the product in terms of the unit economics. So the more you use the product, the more you lose the money. So I think they're trying to make it up on volume.","offset":558,"duration":49}],"startTime":340},{"title":"The Unsustainable Economics of Consumer AI","summary":"Matt details the massive cash burn required to train and run foundational AI models. He explains how computing costs drastically outpace Moore's Law, rendering popular consumer subscription tiers highly unprofitable.","entries":[{"text":"Eric: Matt, I can't imagine any responsible business executive signing off on 122 billion dollar deal unless the underlying business model was rock-solid and it didn't have any major risks in it. Just happens that you wrote this missive over the last couple of weeks called \"Pay to PrAI.\" I don't think that's actually the conclusion that you reached. Tell us about the economics of the, I'll call it the consumer AI business model, offering AI through chat to people like me who sign up for a Max subscription on Claude or a Pro subscription on OpenAI. How much money are they making or losing on that?","offset":607,"duration":37},{"text":"Matt: The AI industry is consuming an absolute bonfire of money. It's about 600 billion dollars a year that's being spent by the hyperscalers on CapEx. It's reaching a kind of a point now which is kind of incredible where, you know, the CapEx is higher than their internal free cash flow. You know, the fundamental business model that's being pushed in the consumer market and the software development market up until now has really been a venture capital style subsidized model where you pay, you either use the free product and then hopefully upgrade to the 20 dollar a month product, or you use the 20 dollar a month product if you're a consumer or a 200 dollar a month product if you're a power user or if you're starting to do programming.","offset":644,"duration":38},{"text":"Matt: But the problem with these models are that they take an incredible amount of money to train, and I think we've talked about that in previous episodes where you've got training runs North of 100 million dollars a run, you know approaching half a billion dollars a training run. That requires a huge amount of data center build-out, a whole lot, an incredible stupendous amount of data needs to go into these models. And so, you know, because the cheap data that's scraped off the internet for free is basically sort of, you know, drilled out to an extent, they have to do licensing deals to get access to that data. Sometimes they do dodgy things like Anthropic, you know, scraped a whole bunch of books and scanned them in and then they got caught and they had to pay the biggest, I think, fine in copyright history, I think it was about 1.5 billion dollars for the illegal scanning of all that data, etc.","offset":682,"duration":42},{"text":"Matt: So it's incredibly expensive to train. But the fundamental problem is that when you actually use the inference, you basically put queries into GPT or queries into Claude and you run them, those queries are loss-making. You can't make it up on volume under the current models. While we do see, you know, the underlying hardware is on sort of a Moore's Law sort of trend, and Moore's Law for those of you that don't know what it is is, you know, every 18 months to two years or so, effectively the technology that goes into chips allows semiconductors to be produced with finer and finer feature sizes, which effectively allows the compute capability in terms of processing power to effectively double or the cost to half every 18 months.","offset":724,"duration":44},{"text":"Matt: While you are riding on that sort of silicon Moore's Law trend, because the models are in such a brutally competitive environment where there's literally zero lock-in, there's almost zero switching costs, so I can, if one day ChatGPT 5 comes out I'll switch to that, but then Claude 4.6 opus comes out and that's better, I'll switch to that, and so there's nothing stopping me overnight really just changing the models. Because of the competitive environment and so forth, what the situation basically is that each generation of model is being rushed out to kind of get the top of the scoreboard so that all the customers flock to that.","offset":768,"duration":35},{"text":"Matt: And as a result of that, the actual amount of inference or tokens burned, if you will, per useful query with each generation of model, while the underlying compute is getting cheaper and cheaper in terms of what you can get done on the chips, the amount of inference you have to burn for a useful query is actually going up quite dramatically. And so you're actually not seeing a reduction in the cost of inference, you're seeing an increase. And that's before you consider the issue with energy and constrained build capacity for building data centers and power gear and all the other things.","offset":803,"duration":36},{"text":"Matt: And so, you know, a few people have done various models of how much it costs for GPT to deliver their 20 dollar plans, and even if you ask Claude itself, you type a query into Claude saying how much is the underlying compute costs for on a 20 dollar plan with Claude, it will tell you, you know, 15 to 20 dollars, maybe 18 dollars, maybe a bit more. So effectively there's no money being made on these 20 dollar plans and when you're a power user you can burn up to several hundred dollars on a 20 dollar plan. And it gets even worse on these 200 dollar plans which are used by programmers now, because the nature of programming is you're streaming tokens almost forever, and you know, the average user on a 200 dollar plan can burn, you know, many thousands of dollars of underlying compute, and in fact there's a, there's a leaderboard called VibeRank where people compete to see how much underlying compute they can burn on a 200 dollar plan. The leading guy on the leaderboard has burnt 51,000 US dollars in a single month on a 200 dollar plan.","offset":839,"duration":60},{"text":"Matt: So the issue is that as these models get more and more competitive and new versions come out, you know, you're getting an exponential increase in the amount of inference you've got to burn, and that is meaning that these models are not getting cheaper and you're not making up on unit economics. And so it kind of feels like this funding round, especially with the amount of vendor financing that's packed into it, it feels like this is an attempt to really try and scale up the underlying infrastructure and GPU capability so that potentially you know, some sort of threshold can be crossed in the underlying economics so inference could be profitable. But there's one big problem with all that, which is is the demand there? And and that's where we are.","offset":899,"duration":44}],"startTime":607},{"title":"AI Valuations and Dot-Com Bubble Parallels","summary":"Eric and Matt compare the current AI funding frenzy to the late 90s dot-com boom. They debate whether companies like OpenAI can justify trillion-dollar valuations given the lack of sustainable competitive moats against open-source alternatives.","entries":[{"text":"Eric: Matt, you said it's 122 billion dollar capital raise on a pre-money of 730, so I get 852 billion is the current enterprise value. Assuming an up round, which is what everybody assumes, we're going to go just let's call it an even trillion for the IPO because hey what's, you know, 100 billion here, 100 billion there, you know, eventually you're talking about real money. But holy cow, let's say that OpenAI goes ahead and IPOs sometime this year for 1 trillion dollars. Are you going to be long, short, or flat, and why?","offset":943,"duration":37},{"text":"Matt: It really does feel in the space that we're really in the moment where a supernova is starting to explode and we're probably going to end up with a giant black hole like we did in the .com boom the first time around. I mean a trillion dollar valuation at IPO is absolutely gigantic. You know, they've raised 122 billion here in this round. They were mooting that the IPO earlier in the year was going to be a 60 billion dollar raise on about a trillion, but you could probably imagine that that number has possibly scaled up a little bit or they want to keep it tight obviously because once it gets to public markets you don't want to have too much stock unload onto the market.","offset":980,"duration":36},{"text":"Matt: But a bigger problem for them is the fact that you've got Elon Musk in the wings who's not just suing OpenAI because it turns out you can't IPO a charity and they've converted OpenAI to a for-profit model and there's a lot of complications around that, but he's also IPOing his SpaceX for I think it's 1.75 trillion valuation. So there's a big possibility that a lot of the heat's going to be taken out of the market when he does his 75 billion on a 1.75 trillion dollar raise, and it looks like he's going to beat OpenAI to to going public because if you kind of look at the news and you know what's all happening with the ETFs and the allocations and so forth, he's a lot further along.","offset":1016,"duration":40},{"text":"Matt: I don't know, in the olden days, you know, if you were to invest in Amazon when it went public or Microsoft when it went public, you know, you had the ability to make a lot of money. I don't know how much is left on the table for the general public when the company's being valued at a trillion dollars when it goes public, you know, what are you going to do? Get to two trillion, 10 trillion? I think Nvidia is what, four or four and a half trillion valuation, and they're the only ones making money in the space.","offset":1056,"duration":26},{"text":"Eric: Matt, the parallels between this and the late 1990s .com boom before the 2000 .com bust are just striking to me. And it occurs to me before I go on that we probably have listeners that weren't even born when that happened. So for anyone who's not familiar with what happened there, Wall Street became absolutely obsessed with the idea that the internet is going to be a really big deal. And the thing that's really important to understand about this is they got that call exactly right. The internet, the public internet was going to change the world we lived in in ways beyond what anyone could even conceive and they got the call right that it was a really big deal.","offset":1082,"duration":44},{"text":"Eric: And I think they're getting the call right again that AI is a really big deal, maybe as big or bigger than the public internet. But the thing is, even though they got the call right, they started throwing money at dumb ideas without thinking and it just turned into a complete frenzy. It seems like that's happening again here, but in the late 90s, it was every tiny little company that had .com in its name and it didn't really matter whether they had a business model. It's different here. It's the big players, which frankly have a business model. But as you very eloquently explain in this excellent piece I recommend everyone read called \"Pay to PrAI,\" that business model isn't viable for the reasons that you just described, or it's not profitable or not likely to be sustainable.","offset":1126,"duration":50},{"text":"Eric: How should we think about this? Is it inevitable that a .com bust like we had in 2000 is coming for AI, and does it have the same dimensions as the one in 2000? Is it bigger, smaller, worse, better? What do you think?","offset":1176,"duration":16},{"text":"Matt: So if you think about the .com boom, and I was there actually in Silicon Valley in '97, '98, '99, 2000, I saw it all. There was a hypothesis the internet was going to be a big thing and it turned out to be a enormous thing in terms of the benefits to humanity and society and will continue to grow in terms of its applications. And AI is the same thing. AI is going to be absolutely transformative for humanity in terms of what it can do. At that time, you know, a company whose valuation went through the roof was Cisco, and their tagline was \"We network networks.\" We talked about it I think last MacroVoices. Every time you plugged in a bit of the internet, you needed to have a router to connect up the network and Cisco equipment was going to be everywhere and why wouldn't it be the most valuable company in the world, right?","offset":1192,"duration":42},{"text":"Matt: And the same as with OpenAI in a to an extent, you think okay, well they've got the best AI models, AI is going to be everywhere, why wouldn't OpenAI be the most valuable company in the world? But then at the same time, you also had AT&T, and up until about 1996 AT&T had a 60% market share. It basically built the network using Cisco equipment to connect up the world. You had three players in the market and I think it was mentioned at the time by an analyst that they had margins that would make drug dealers blush.","offset":1234,"duration":25},{"text":"Matt: But the problem was that in 1996 the Telecommunications Act, Regulation Act came in and deregulated the market. And you started having fourth entrants and fifth entrants and so forth and and people buying and selling capacity to each other etc. and when you started having the fourth entrant come in and competing on cost, the unit economics fell apart. And if you think about the AI compute space, well Amazon had it pretty good up until the AI boom, I think its its CapEx as a percentage of earnings was down to about 6% at one point.","offset":1259,"duration":30},{"text":"Matt: Now these hyperscalers are spending, or the cloud computing companies are spending, 60% of earnings on CapEx, over 100% of earnings on CapEx. They're spending 600 billion dollars a year at the moment in terms of a run rate in CapEx and it's hypothesized that by 2030 it's going to be 5.2 trillion dollars of CapEx, right? Now when you just had Amazon, you know, really dominating in terms of of cloud, you know, it was sitting pretty and I think it had about 60% market share.","offset":1289,"duration":26},{"text":"Matt: Now you've got Microsoft who's taken over and they're market leader and so forth. Now you've got entrants such as Oracle that's competing on price and you've got CoreWeave and the Neo clouds and the unit economics are starting to look a little bit shaky. And then you had a big bust in the .com bust where, you know, all these companies had money being thrown at them and you're seeing that right now. Any company that kind of has AI in its business plan is getting these stupid, you know, seed rounds in the hundreds of millions of dollars. I remember when seed rounds were hundreds of thousands of dollars, now you have hundreds of millions of dollars.","offset":1315,"duration":36},{"text":"Matt: And you know through the early 2000s you had a real trough in the technology space where where everything blew up and was somewhat uninvestable for a period of time. But through that period of time, you had companies like Google and Amazon continue to grow and double down and Microsoft and so forth and ultimately today became very very big companies. So I think we're seeing this on steroids right now with AI CapEx and compute and the OpenAI funding rounds and so forth. And you know it's unquestionable AI is going to be completely enduring and just absolutely game-changing for society. But I think the kind of circle jerk of money that's sloshing around between a very very small number of companies at stupidly high valuations and at a scale that is just stupendous is going to potentially end up in a big bust.","offset":1351,"duration":51},{"text":"Eric: Matt, I want to focus on that because a lot of people are going to mishear what you just said and they're going to say Matt Barrie said imminently tomorrow there's about to be a great big bust in all of the AI stocks. That's not what you said and it really rings home for me because the reason that my partners and I sold our software company in the summer of 1998 is because we knew it was a bubble. And my plan at the time was to take all of the proceeds and short the NASDAQ because I knew it was a bubble.","offset":1402,"duration":33},{"text":"Eric: Fortunately I got talked out of that, but if I hadn't, I would have lost everything because even though we were right, basically the NASDAQ doubled between '98 and 2000 before it crashed exactly like I predicted it was going to crash. What do we do here? I mean, do you go long, do you go short? And I'll say I'll ask the question this way: OpenAI and Anthropic are both expected to IPO probably in 2026. When they do, you know, is it time to go long or is it time to go short? Because you know I could make either argument. It seems to me eventually you want to be short, but how do you time that?","offset":1435,"duration":37},{"text":"Matt: That's the trillion dollar question, right? You've got SpaceX going public which obviously has Grok and xAI within it. You've got Anthropic going public and you've got OpenAI going public and that's why I think it feels a bit like a supernova, so we'll end up with a big bang in one way or or another. I mean, you know, I think the issue is going to be, I mean that some of these valuations like the OpenAI valuation is kind of predicated on the fact that it's going to capture an enormous amount of value out of the world in order to justify these valuations, right? You know, these funding rounds are so large and the valuations are so high that you need to pitch a revenue line that matches them.","offset":1472,"duration":36},{"text":"Matt: And you know at the moment OpenAI is doing about 2 billion a month in revenue, I think it's at about a run rate of about 25 billion, I wish they'd stop using the word run rate because I think you've actually got to recur once before you can call something annual recurring revenue. So it's doing about 2 billion a month of revenue, losing you know 14 billion this year, I think the burn rate that came out today was is expected to lose 70 million dollars a day this year scaling to 156 million a day lost next year. But in order to to, you know, cross the valley of death and get to the promised land, they've got to show a business model that makes sense.","offset":1508,"duration":34},{"text":"Matt: And I think what their business model is going to is twofold. One is that they're going to take a substantial amount of white-collar jobs away from humans, you know some substantial percentage of jobs in the world are going to go to AI and that's kind of the top-line revenue number. And then the in terms of generating earnings out the other side, the justification is that the infrastructure that's being contributed as part of this 122 billion dollar round is at such a scale that only OpenAI will have the unit economics that will make the inference profitable. So in a combination of taking everyone's job and having the only infrastructure that can run this stuff profitably, I think that's the argument for justifying these sort of trillion dollar valuations.","offset":1542,"duration":42},{"text":"Matt: Now I don't think OpenAI is going to capture, for example hypothetically, you know the value in the AI-powered drug discovery market anymore than AT&T captured the value of the iPhone, right, you know? The underlying technology phenomenal, but as Ilya Sutskever said himself, who was one of the founders of OpenAI, that you can just read 40 academic papers and 95% of what's out there in AI is is published in in the public domain. And that's why every couple of weeks there's a kind of a new foundational model that's top of the leaderboard and every once in a while there's a team of people that you've never heard of, that 160 engineers in a room in Hangzhou like like DeepSeek that comes out of nowhere and suddenly leads in the leaderboard because it turns out that there's no sustainable competitive advantage in the underlying foundational models and what you do need though is access to data.","offset":1584,"duration":44},{"text":"Matt: Those data sets are now kind of out there in public or in the case of the Chinese they probably don't care too much about copyright so they'll always have a sustainable competitive advantage. And I think there's incredible and tremendous opportunity in AI, but it's probably not going to be in these models that that haven't really figured out what the business model is.","offset":1628,"duration":23}],"startTime":943},{"title":"Apple's Edge AI Strategy vs. Cloud Compute","summary":"The conversation shifts to Apple's potential to capitalize on a future AI market correction. Matt suggests Apple can avoid the data center capital expenditure bonfire by pushing AI workloads directly to local edge devices.","entries":[{"text":"Eric: Matt, I think there is a very distinct difference between this scenario and the late 90s to 2000 .com story, and that is this. Let's say that we don't know whether it's '97, '98, or '99 right now, but we know that March of 2000 is coming at some point. There's going to be a washout in this commercial AI space where they just realize that the business model wasn't sustainable. Well what happened in the .com bust is we went really a good solid couple of years of kind of a technology recession where there wasn't a whole lot of progress on the public internet because we had to basically shake that malinvestment out of the system, get back to efficient capital allocation, and then you know after 2002, 2003 things started to really take off again.","offset":1651,"duration":51},{"text":"Eric: What if the US government steps in and says, now wait a minute, the military applications of AI create an existential threat to the country if we don't stay ahead of this? We can't tolerate a 2000 to 2003 pause. You must continue, you must do it under US government funding, but we're not going to fund the giving away stuff for free to Max subscribers on Claude. We're going to take it over and you know it's just for the military now. We're not going to have consumer AI anymore. Is that a realistic scenario, or do we need consumer AI in order to train the models in order for the military to get the benefit, you know, what would happen in that scenario where the military says no, we we can't allow a stock market crash to slow down progress on the military applications of AI?","offset":1702,"duration":49},{"text":"Matt: So I don't think it's realistic that we're not going to have consumer AI. I mean the Chinese are open sourcing their models and in fact they've got their strategy to open source both the software and the hardware. You know, and there's been previous leaks of Meta's Llama and and so forth. I think the interesting thing here is that it won't be the government stepping in. I think there's one big company that's kind of been sitting in the wings that has a God-awful AI product and it's in everyone's pockets and that's Apple and the iPhone.","offset":1751,"duration":25},{"text":"Matt: I think in our last chat we talked about how goddamn awful Siri is for supposedly being your original chatbot AI assistant and we hypothesized that it will continue to be awful in the next year and here we are and it it continues to be pretty bad. But they've kind of avoided this whole getting sucked into this whole CapEx bonfire and they've really got two levers they can pull. One is is they're sitting on this cash and they've kind of they can sit back and watch and and as with the .com bust, there was a lot of infrastructure that went through to the second and third owners where you know maybe the first owner that builds out the optical fiber network goes bust and the second owner comes in and tries to make it break even after after purchasing it at a at a cheaper price and washing out the underlying sunk costs, and then the third owner comes in and makes some money out of it.","offset":1776,"duration":46},{"text":"Matt: And I think you might have that situation in the AI compute space where if there is a problem with some of these large foundational model companies, there might be a second or third owner and Apple would be ideal for that. At the same time, what they've been doing is they've been putting in some AI silicon into their products and a lot of this compute that's currently being done in a data centers, you know, by OpenAI, by Anthropic, etc. is going to go to the edge and it's going to go to the edge for a variety of different reasons. One is that you don't want Sam Altman training on your data, and I think we've talked about before that I think an emperor has no clothes moment is heading into into SaaS where you know I think large enterprises are starting starting to think to themselves, you know what, I don't want my data in Google Drive and Gmail, you know it might get trained on.","offset":1822,"duration":44},{"text":"Matt: And you're certainly seeing all the major SaaS companies quietly flicking on a switch in the settings without telling you where they're saying by default now we can train on your data potentially, and then you flick it off but by then it's too late and all your data has been sucked down. So a lot of that compute is going to go the edge, it's going to go to on-prem, you know in the enterprise on compute devices so it doesn't go into the cloud. It's going to be on your phone, it's going to be on your MacBook, it's going to be on your Mac Studio or whatever it may be for privacy, for confidentiality, for latency reasons and the fact that there's some models now that can actually fit on that silicon.","offset":1866,"duration":34},{"text":"Matt: And you know while it might be you know one or two generations away, you know at some point I think real soon a lot of that load and a lot of that compute that's going to AWS data centers and Azure data centers to run Anthropic and to run OpenAI is going to go to the edge. It's going to be on Apple's devices, it's going to be on Apple's laptops, it's going to be on-prem, at the same time Apple's cashed up and might end up being the second or third owner of some of these companies.","offset":1900,"duration":26}],"startTime":1651},{"title":"The Inevitability of Per-Token AI Pricing","summary":"Matt predicts AI platforms will eventually be forced to abandon subscription plans in favor of pay-per-token pricing. He argues this dynamic will turn software development into an expensive, unpredictable financial slot machine.","entries":[{"text":"Eric: Matt, the title of your missive that you just written, \"Pay to PrAI\" or \"Pay to PrAI\" P-R-A-I is actually a reference to the inevitability in your prediction of something called paper-token monetization. What does that mean, how does that relevant, explain what that's about?","offset":1926,"duration":19},{"text":"Matt: Well, the fundamental business model of Silicon Valley venture capitalists is to try and win markets by financing companies with astronomical amounts of money such that that money gets spent on marketing and subsidization of the product to such a scale that nobody can compete with these Silicon Valley invested companies or unicorns. And so total nuclear war is launched on a market, so you can think maybe Uber and free rides in China or whatever it may be or you know DoorDash delivering noodles to people in Indonesia or you know Grab or whatever whatever it may be.","offset":1945,"duration":35},{"text":"Matt: So what we have here in the AI space, the subsidization model is that you have a free product being GPT or what have you, and then you've got a 20 dollar a month product which I've said earlier probably costs them 20 dollars to serve, and a 200 dollar a month product which probably costs them 2000 dollars to serve. You just can't continue forever. At some point, so the so the question is going to be can we get the unit economics down to do inference to such a point that these models are profitable before these companies run out of funding?","offset":1980,"duration":30},{"text":"Matt: Now the problem is that as we've moved into for example software development which consumes a never-ending amount of tokens to write code because every company in the world is powered by software now, you know there's this huge token burn that's happening in these 200 dollar plans. And if you were to try and make some sort of reasonable software-like margin, like 80% etc., you would have to price these plans not at 200 dollars a month but maybe a thousand or two thousand dollars a month or higher.","offset":2010,"duration":30},{"text":"Matt: At some point the money is going to run out and I think they had a near-death experience in the last couple of weeks. Anyone who and I know you're constantly using GPT and Claude etc. and you probably noticed the same thing, you know in the last couple of weeks there seems to have been a bit of a panic from these companies where you know you log into your 200 dollar plan, you type a couple of queries and then you run out of credit. You've always known that these companies aren't making money on the inference because instead of saying put your credit card in and top up your credit, it puts you in the naughty corner for seven hours or longer.","offset":2040,"duration":31},{"text":"Matt: The inevitable destination for these subscription models which are basically massively subsidized Silicon Valley financed and increasingly debt-financed business models is that they're going to have to move to a per-token pricing. Now and that is going to cost a lot of money. I think there was some comments in the last couple of weeks on Reddit where someone who's on a 200 dollar plan ran out of credit pretty quickly, he had to get it done he had to get something done you know that night, and so he moved to the API pricing which is in the programming interface and that was costing 200 dollars an hour instead of 200 dollars a month.","offset":2071,"duration":34},{"text":"Matt: And he thought gee, I've just you know used a couple hours used 5, 600 dollars. The problem with that sort of pricing has several dimensions. The first is that already at 20 dollars a month for a plan which is 240 US dollars a year, that already prices the product out from over half the world's population. I mean the median global income in the world is about 2.5 thousand dollars a year so at 240 dollars a year you're already 10% of the pre-tax income for half the people on the planet, right? So you're already quite expensive.","offset":2105,"duration":33},{"text":"Matt: The second point problem here is that you know in these programming models which which realistically to make any sort of margin need to be priced in the thousands of dollars a month or maybe 10,000 dollars a month, you have a bit of a problem in the fact that you know these models do hallucinate. And when they do hallucinate and throw errors, they're very different from human. When you use hire a freelancer for example on my website freelancer.com, you know you put in some money, okay I'm going to pay you 200 dollars to build a website for me and you don't release that milestone until the job is done.","offset":2138,"duration":33},{"text":"Matt: And if the human can't figure out a problem, you know they'll they'll ask their friends, they'll try and find a more senior engineer for advice, they'll get on a forums and ask other people how to solve problems, they'll browse the internet, they'll they'll kind of hill-climb their way out of solving problems. And look, they may they may ultimately not get there and you might get frustrated with them and want to find another developer to do the job, but ultimately their failure modes are very different from AI. With with AI, sometimes when it hallucinates, it can do wildly crazy things.","offset":2171,"duration":28},{"text":"Matt: About three weeks ago, I had a problem with my with my VPN on my computer, I was using Claude to kind of help me through figuring out how to get it fixed. I'm a software developer by background, I've got electrical engineering degree from Stanford, you know I I do know how to program quite well, but I kind of veered into PowerShell commands in Windows 11 which I don't know very well and I was blindly pasting in Claude and it made me delete my entire networking stack.","offset":2199,"duration":26},{"text":"Matt: And so you have these very crazy failure modes with AI where you either go in loops or it goes away and thinking and and you know burns you know 10x the inference you know try you know these reasoning chains trying to figure out what's going on, or it just has these crazy suggestions and and it will look at you in the eye with the the eyes of a sociopath on a first date in some regards trying to you know gaslight you into thinking that its answer is is true when it's clearly not the case, it's just hallucinated something or rather.","offset":2225,"duration":32},{"text":"Matt: And the issue here is that in a paper-token pricing model, it really turns software development into a slot machine in that if the if ultimately you know you're writing your app and you you kind of need to get Claude to do something or rather, you're really pulling the slot machine handle, you don't know how much it's going to cost you by the time the tokens are all burned and you don't know if you're actually going to get a solution at the end of the day. And so, you know I guess only in Silicon Valley could they turn software development into degenerate gambling because that's that's kind of where you end up.","offset":2257,"duration":33},{"text":"Matt: And the frustrating thing I think will happen is when you're on the 200 dollar plan you've got a certain amount of capacity and maybe it tells you to time out or what have you, you kind of know, you're capped at 200 dollars, right? It's very frustrating what it runs out of credit you gotta find alternative ways potentially of doing things, but you kind of know what you're what you're up for. When you're pulling the handle under the paper-token model, it could be 50 dollars per spin, you may go in a circle, you may go in a circle 10 times, you know there's all these examples of people get over X of of radical crazy things that that that Claude does to your codebase.","offset":2290,"duration":36},{"text":"Matt: And I think people are going to get very very frustrated if they have to kind of put a coin in the machine, pull the handle every time and they get a non-deterministic outcome of whether they're moving forward in a hill-climbing sense to to their final solution and their final app or their final bit of software being developed or whether they're going in circles you know round and round and round round again. And I think people are going to get frustrated, they're going to go try and find open source models, they're going to try and find alternative ways to get things done and I and I think at that point, that's where the bubble starts to pop, it's really the problem.","offset":2326,"duration":40},{"text":"Matt: And while the hallucinations are reducing as part of you know each new generation in terms of the engineering of the infrastructure around the foundational models to reduce those hallucinations, what is actually happening is the token spend is going up exponentially because you're doing more and more complex things, so you have a much bigger surface area in which you could generate an error. So what I mean by that is, you know, while the probability of a failure pulling the pulling the handle on the slot machine is getting reduced with the you know the engineering from each subsequent generation of model, the number of handle pulls you need to make is is going up exponentially and so you've got a multiplicative effect in terms of potentially the impact of errors.","offset":2366,"duration":30},{"text":"Matt: I just think it's going to, the question that basically needs to be solved now with this 122 billion dollar fundraise is can you get the cost of compute way down to get this whole model profitable and will the market tolerate software development as a slot machine.","offset":2396,"duration":6}],"startTime":1926},{"title":"AI Dependence and Token Budget Constraints","summary":"Eric shares his anxiety over recent Claude outages and professional dependence on AI. Matt explains how AI companies are quietly restricting user token budgets to survive their aggressive cash burn rates.","entries":[{"text":"Eric: A lot has been said already by lots of people about the incredible rate of progress and how quickly AI itself is getting smarter. What I don't think has been discussed enough and I'd like to get your comment on is the rate to which professionals are becoming dependent on it. I think more than you know this it's more addictive than cocaine. I remember our first interview on AI when ChatGPT had just come out and I remember thinking to myself, boy Matt's really into this stuff, to me it's a novelty but I don't think I'd ever pay 20 bucks a month for it. I mean it's just it passed a Turing test, big deal but I don't think I'd ever buy a subscription.","offset":2402,"duration":46},{"text":"Eric: I'll tell you Matt, in the last several weeks, there's been a lot of stress in my life because of this war and family that are affected by the war and waking up double digit percentages down on a percentage basis on my net worth because of something that happened in the market overnight. Okay look, I'm a big boy I've been through that stuff before, I've been through the 2008 crisis, it's not that big of a deal. But Claude 4.6 was going offline and the server wasn't available and I was freaking the F out. I couldn't handle it. I was losing, and don't you dare insult me by suggesting that I go back to ChatGPT 5.4. I don't drink Pabst Blue Ribbon and I don't do ChatGPT, okay? I mean I've gotten to the point where I can't live without Claude. This is this seems like a risk.","offset":2448,"duration":55},{"text":"Matt: When Claude went down, it's quite interesting actually because the first time it had a bit of an outage was when the data centers got blown up in in Dubai and you kind of have to wonder to yourself what potentially was being run in those data centers in the Middle East that caused the outage of Claude. And I do think those companies did have a bit of a near-death experience in the last couple of weeks. Anyone who and I know you're constantly using GPT and Claude etc. and you probably noticed the same thing, you know in the last couple of weeks there seems to have been a bit of a panic from these companies where you know Sam Altman killed Sora which was this hyped-up video modality model where you could generate you know clips or you know the whole point was you were supposed to be able to type in a prompt and get a movie out the other side.","offset":2503,"duration":31},{"text":"Matt: In fact Disney paid a billion dollars to OpenAI for use of the technology and only found out half an hour before a meeting that the whole thing was going to be canceled. At the same time Sam Altman killed instant check-out, he's working on some sort of erotic model as well which is a bit strange but I think it's probably one of the big markets is pornography and he thought maybe we could make some money there. He killed that as well and at the same time Claude had these big changes in terms of how they did the plans and they were giving out you know extra tokens in off-peak but in peak they'll kind of cutting you back etc. and then ultimately it seems that they've they've cut back a lot of lot of the token budget you get in these models and on the path to this sort of paper-PrAI paper-token sort of business model.","offset":2534,"duration":40},{"text":"Matt: So I do think they all had a bit of a near-death experience and that near-death experience obviously is what I was feeling or what you've been feeling when you kind of see these models you start using them and going, gee is my access going to start getting restricted, you know will I have to pay a lot more money, will I have to add a zero to my to my monthly subscription, what what's going on. And then of course you've got this financing round which is less cash and more infrastructure and perhaps it's a way to kind of help the company kind of limp towards IPO so there's liquidity event so the you know original investor can kind of make a bit of a return.","offset":2574,"duration":28},{"text":"Matt: It turns out that you know this whole, it's pretty funny that this whole AI compute space is predicated on 600 billion dollars a year of CapEx which is incredibly energy-intensive when at the same time you're bombing the you know an area where 48% of the world's energy is and you know you're relying on energy being cheap in order to have this AI AI boom work.","offset":2602,"duration":24}],"startTime":2402},{"title":"AI's Threat to Private Credit Markets","summary":"Matt explains how massive debt financing for data centers threatens to destabilize private credit markets, particularly because AI pitches aim to disrupt the very SaaS companies underpinning these debt portfolios.","entries":[{"text":"Eric: Let's move on to private credit. There's a lot that's been said already as a lot of private credit funds are gating investors that this is AI driven or it's related to Claude Code specifically creating fears that software companies would no longer be profitable. And I have a hard time with this one because this sounds like the claim I remember hearing in the 1970s when supposedly the introduction of the Hewlett Packard electronic calculator was supposedly going to put every accountant out of business and create vast unemployment of bookkeepers and so on and so forth and it was the exact opposite. It created more productivity. It seems to me that Claude Code just gave the software industry the biggest productivity boosting tool that they've ever had, and that's the reason that private credit is blowing up? Is that really right? Am I missing something?","offset":2626,"duration":54},{"text":"Matt: Well, I mean there's a few things going on. First of all, the these funding rounds are getting too big for equity, so as we saw with 122 billion and all the infrastructure, the vendor financing in there. And so you've increasingly these companies are turning to debt, even Meta had to go and get 30 billion from Blue Owl not so long ago in order to fund data centers because it's [44:59]","offset":2680,"duration":20},{"text":"Host: ...not do it off the balance sheet anymore and the numbers are starting to get too big for equity raising, so they're borrowing the money. And not just are we seeing record equity rounds, we're seeing record debt rounds. That BlueOwl financing of Meta was the biggest private credit round ever.","offset":2700,"duration":25},{"text":"Host: The problem is that private credit in these portfolios has got SaaS businesses and one of the big pitches that these AI compute companies has is that SaaS is dead, which is kind of ironic when ChatGPT on a $20 a month subscription is a SaaS business.","offset":2725,"duration":22},{"text":"Host: So it's kind of funny that they're saying SaaS is dead when they actually are SaaS businesses themselves. But there's been some warnings that have come out around these private credit portfolios that pack in the AI debt as well as the SaaS debt, because AI is actively pitching the future of these SaaS companies will be eroded by the fact that AI is coming.","offset":2747,"duration":26},{"text":"Host: So it's causing some instability in the private debt markets. And of course, what else is causing instability is rising interest rates in an uncertain world and a war in Iran amongst other things.","offset":2773,"duration":18}],"startTime":2626},{"title":"Middle East Conflict's Risk to AI","summary":"The discussion pivots to how the escalating war in the Middle East threatens the AI boom. A prolonged conflict could divert regional investment capital away from tech while massively spiking essential computing energy costs.","entries":[{"text":"Host: Matt, speaking of data centers blowing up, let's talk about the Iran conflict, its connection to AI, and particularly in your latest missive, you express some concerns that there's a risk that potentially this Iran conflict kind of pulls the rug on the whole AI business model. What do you mean, what's going on?","offset":2791,"duration":29},{"text":"Matt Barrie: Well, this is where the Fifth Industrial Revolution meets the Islamic Revolution, right? Um, a lot of the financing for AI has come from the Middle East. And you can imagine now if you're Saudi Arabia or you're the UAE and you have a fiduciary duty to protect your nation and your citizens and your economy, are you going to be putting it into hyper-rounds of Sam Altman's highly inflated valuations, or will you spend it on defense, energy, rebuilding your civilian and industrial infrastructure and potentially going to war to fund an army?","offset":2820,"duration":45},{"text":"Matt Barrie: You know, it's quite problematic when you've got a country that sits right in the middle of, you know, 48 percent of the world's energy infrastructure, that controls a strait where 21 million barrels of oil goes through every day, that can fire $20,000 drones at scale into anything within a 2,000 kilometer range and migrate not just your data centers in the region, but potentially your energy infrastructure into the cloud, literally in a puff of smoke.","offset":2865,"duration":37}],"startTime":2791},{"title":"AI Productivity and the K-Shaped Economy","summary":"Matt argues that AI acts as a powerful tool that exponentially boosts the output of highly skilled workers. He warns this dynamic will fuel explosive entrepreneurship but drastically widen the K-shaped economic divide.","entries":[{"text":"Host: Matt, another theme that you have in your latest missive is that you've got to be pretty smart to really get the most out of AI. What do you mean by that and what are the consequences?","offset":2902,"duration":16},{"text":"Matt Barrie: When I look at, deep down, at kind of what what's happening in the space, I mean, despite you've got a conflation of few things happening right now. You've got the AI companies trying to justify these huge valuation rounds and they're doing that by saying they're going to take away a lot of the world's work. Then at the same time, you've got sort of mass layoffs happening in the market with Block today, with Oracle, I don't know if you saw overnight, but Oracle has announced 18 percent of their workforce has been cut, etc.","offset":2918,"duration":37},{"text":"Matt Barrie: And so you would not be surprised that the general market has kind of conflated these things and thinking that AI is taking people's jobs away. Now, I see AI instead as a tool. It's a very, very powerful tool. It's, you know, but it's a productivity tool, much like the world was, you know, when you went to work and there was no computer on your desk and then you went to work and there was a computer at your desk or you didn't have mobile phones and you have mobile phones or you didn't have the internet and then you have the internet. Yes, there is incredibly disruptive and transformative time and some jobs are lost, but just like pretty much all forms of technology, more jobs are created over time.","offset":2955,"duration":51},{"text":"Matt Barrie: And what I mean essentially by you've got to be smart to use AI is, you know, AI is a power tool and so is a chainsaw, right? You give a chainsaw to a carpenter and they can do, a skilled carpenter, and they can do amazing things. You give a chainsaw to a novice and you can cause all sorts of problems, right? And so what I am observing, both across my platform as well as within my engineering team, is the people who are benefiting most from AI are the ones that are highly skilled and intelligent and know how to use the AI.","offset":3006,"duration":43},{"text":"Matt Barrie: And they're seeing productivity gains which are astronomical. They're seeing, you know, double to triple their productivity and you can measure that in different ways in terms of what they're achieving. And then as you go down the skill level, you do, you know, it is a rising tide lifts all boats. So if you're an average copywriter, you can now be a good copywriter. If you're an average illustrator, you can be a good illustrator using these various tools. If you, I make a joke, if you're an average programmer, well, you certainly are a confident programmer now using these tools. But to really get the best out of them, the people who are highly skilled are the ones that are really, really driving the outcomes. And I see that for example with your work and what you do, you writing these missives and books and so forth. And so I think just like technology has over time created a bifurcation in society where you have the people who are skilled and can create technology and that's where all the wealth flows.","offset":3049,"duration":68},{"text":"Matt Barrie: And that's why you see these companies with huge valuations and, you know, the ultra-high net worths in the technology industry, and then you see a general deterioration at the lower end of society. I think this is going to drive even further to an extent. People who really, really know how to use AI well are going to capture incredible opportunities in all sorts of different market segments where they can control that customer interface.","offset":3117,"duration":30},{"text":"Host: Well, I definitely agree with you. I just finished a writing project, or I should say Claude and I just finished a writing project that was considerably bigger than writing my book Beyond Blockchain. It required a lot more research because Beyond Blockchain was just my own opinions. It was a lot to it. And Beyond Blockchain took me more than three months, this project took me less than two weeks. And it's just amazing how much you can accomplish, although you definitely, as you say, it takes some skill to learn how to manage context window exhaustion and recognize symptoms of it occurring and so forth. So I couldn't agree with you more.","offset":3147,"duration":51},{"text":"Host: It kind of scares me though, Matt, because I think one of the biggest problems that society faces in the mid-2020s is the K-shaped economy. The tendency that the rich get richer and the poor get poorer. It sounds to me like AI really is going to exacerbate that in the sense that the smartest people are going to really benefit in productivity from AI. They're going to be a whole lot smarter and more capable than they used to be. One guy will be able to do the job of 10 or 12 guys. But the 10 or 12 guys that weren't that bright and really didn't figure out how to recognize the symptoms of context window exhaustion in their LLM, I think it really does take their jobs. And it seems to me like this could become the basis for deeper division in society.","offset":3198,"duration":55},{"text":"Host: So, Matt, I want to ask you this, because as the CEO of Freelancer.com, and for any listeners who aren't familiar with Freelancer, it's basically a marketplace where people can hire independent workers, whether they be high-end expert consultants in their field who are the leaders of their field, or if it's just a guy who'll design a logo for you for five bucks. You can hire all those different people on Freelancer. Matt has a very unique perspective on AI because first of all, he's running a company that uses AI, so he leads an engineering team that's building AI-based solutions. But some of the people that his customers are hiring are AI experts that are helping companies to implement AI at a corporate level. And then some of the more mass freelancer, larger group of graphic designers and people that are making logos and so forth, are users of AI that are leveraging their logo design contests and all that. So Matt sees all these different dimensions of different people using AI in different ways, corporations and organizations adopting it, versus an individual guy in Indonesia who's just trying to make a buck as a graphic designer suddenly becoming much more productive and being able to work in different languages that he doesn't even speak. So Matt sees all these different dimensions. Matt, from that vantage point that you have, what would you say are the top three things that you've become aware of that the average person who can't see all that stuff probably wouldn't think of?","offset":3253,"duration":122},{"text":"Matt Barrie: Well, the amazing thing is we're going to see the ability for you to get things done that you could never possibly think of before, right? Rather than just getting a website built, you'd get a whole business built. The ability for, you know, I think we're going to enter a whole new world of explosive entrepreneurship where now you really just need to have an idea to start a company and the ability for you to be able to execute on that using both AI and also access to humans powered by AI will be unprecedented. You'll be able to do it at a cost that's cheaper than ever before. So we're going to enter, I think, into an explosion period of hyper-competition and, you know, thanks to the internet and the ability to distribute products or services over the internet at scale so quickly, if you've got a great idea, that great idea can take off and you can make a billion dollars faster than any time ever in the history before.","offset":3375,"duration":57},{"text":"Matt Barrie: So I think it is an incredible time. I certainly haven't seen as yet the complete replacement of someone in a job. I don't know, you know, if you ask around, does anyone know any graphic designers that completely lost their job? Where the dislocation will occur is where you've got highly paralyzable workflows where you've got thousands of people or hundreds of people doing the same job. So maybe in a call center, where there might be 10,000 people or 1,000 people in a call center doing the same workflow which is customer support, answering a phones, etc. With AI, you'll be able to take it from 1,000 people down to maybe 100 people. You know, if you've got 30 junior lawyers drafting legal agreements in a room, maybe you'll be able to take it down to 13 people in a room.","offset":3432,"duration":53},{"text":"Matt Barrie: But I don't see, because of the way AI works and goes in circles and the failure mode and the fact that as you burn more tokens you've got more chance, even though the unit rate of errors goes down, the fact you're burning all these extra tokens means that ultimately, you know, an error becomes more catastrophic in a way that a human never would make an error. What that means is that I think the ultimate combination is humans and AI. I think it's probably one of the greatest productivity tools known to man and I think it's going to open up a whole amazing golden age of building and creating businesses and hyper-competition.","offset":3485,"duration":46}],"startTime":2902},{"title":"Freelancer.com Innovation and Guest Outro","summary":"Matt shares recent Freelancer.com milestones, including crowdsourcing projects for NASA and the NIH, before wrapping up his segment of the podcast.","entries":[{"text":"Host: Well, Matt, I can't thank you enough for a terrific interview. Before I let you go, you run Freelancer.com, a public company that trades under ticker symbol FLN on the Australian Stock Exchange. Tell people for who are not familiar with it what Freelancer does and how to follow your work. Your latest piece, again, it's linked in the research roundup email, it's published on Medium, it's called Pay to Pray. You write quite a bit of interesting stuff for people who want to follow your work and learn more about Freelancer.com, tell us about it.","offset":3531,"duration":49},{"text":"Matt Barrie: Well, we run the world's largest cloud workforce, so it's about 87 million people in that marketplace. We can do any job you can possibly think of from $10 jobs to $10 million jobs. You know, the mainstream jobs are things like build me a website or build me an app or, basically help me start a company or grow my company. The biggest things we run, we've got a moonshot innovation challenge program at the high end where we help all sorts of US government departments and enterprises around the world solve scientific and technological challenges. So, you know, give us your hardest scientific or technological challenge and we'll solve it or you don't have to pay the prize out. So the biggest thing we've got running right now is the seven and a half million US dollar gene editing challenge for the central nervous system of humans, which we're doing for the National Institute of Health and also working with NASA.","offset":3580,"duration":66},{"text":"Matt Barrie: Actually, ironically, when Artemis goes up in the next 24 hours into space, we worked with NASA to crowdsource the mascot from kids all around the world that's going up with the astronauts to basically inspire kids about space and so forth. If you want to get anything done, you come to our site, we can get it done, and no job is too small or too big or too complex and it ranges through to mechanical engineering or electronic design or whatever you need. And if you want to follow my writing on AI, there's a series of, obviously a podcast that we've done together on MacroVoices on AI, I think this is maybe the fifth or the sixth. And if you go to Medium or Substack you'll be able to find me and see my essays.","offset":3646,"duration":59},{"text":"Host: And if you just put Matt's name in, Matt Barrie, at the search bar at macrovoices.com, you'll see a list of all of the previous AI interviews that we've done right here on MacroVoices. Patrick Ceresna and I will be back as MacroVoices continues right here at macrovoices.com.","offset":3705,"duration":26}],"startTime":3531},{"title":"Iran War Update and Trump Speech Reaction","summary":"Dr. Anas Alhajji joins the show to react to President Trump's latest address. He criticizes the speech for ignoring the realities of the conflict and suggests the world is entering a prolonged global crisis.","entries":[{"text":"Host: Eric, it was great to have Matt back on the show. Now Dr. Anas Alhajji is next on deck for a special second feature interview on the developing Iran conflict and what it means for the oil markets. Then Eric and I will be back for our usual postgame chart deck and trader of the week. Since this extra coverage format seems to be a hit with listeners, we'll do our best to continue it for as long as the situation in the Middle East warrants. Now let's go right to Eric's interview with Anas.","offset":3731,"duration":63},{"text":"Host: Joining me now is Energy Outlook Advisors founder and managing partner Dr. Anas Alhajji. Anas, it's been three weeks since we had you on the program for the first Iran war update. It's been one month since this conflict started. President Trump just moments before we began recording this segment gave an address to the American people. Let's start with the big picture update since this began. How has everything evolved, how have your views evolved since we had you on three weeks ago, and what did President Trump need to achieve in this address and did he achieve that?","offset":3794,"duration":43},{"text":"Dr. Anas Alhajji: Well generally speaking, we got to frame what has been going on and President Trump basically did not frame it. So, either this is about Iran and its nuclear and he tried to make it that way, or Iran part of a bigger picture and the audience basically can choose one of those two. So either it is about Iran and its nuclear program and the outcome of that basically and its impact on the market are completely different from the idea that Iran is part of a big picture. If you look at trade wars, tariffs, sanctions, Venezuela, Panama, Red Sea, China, Greenland, etc., so is Iran and this war is part of it or Iran is completely separate. The president today basically tried to make it about Iran, but all of a sudden he deviated from that and he started talking about we don't need the Middle East, we don't need oil from there, buy oil from me. And this makes the second option basically kind of more credible in this case.","offset":3837,"duration":70},{"text":"Dr. Anas Alhajji: Anyway, we'll go back to that later on. And the other issue is, who closed the Hormuz Strait? You have only two answers. It's either the United States through the insurance companies or Iran. And it's up to you, the audience, basically to believe one of them. There are evidence on both sides. But one of the ironies here is that when we talk about the details of who closed the Hormuz Strait and we say Iran has no power to close it, then people say, well this is a conspiracy theory. It turns out it's a bigger conspiracy theory to say Iran closed the strait. And we heard the president today saying that Iran's navy is gone. Literally said that. And he said they have no radars, he talked about the total devastation of course their leadership is gone, all that stuff. So to believe that we have all these attacks and the aftermath of this devastation that happened to Iran.","offset":3907,"duration":64},{"text":"Dr. Anas Alhajji: We have 28 countries are in charge of protecting the Gulf and the Hormuz Strait through an organization that is based in Bahrain. You have the US navy, you have the Indian navy, you have the British navy, you have the French navy, you have the Saudi navy, you have all the other countries' navies in the area. And then after all this devastation Iran still control the Hormuz Strait? This goes against everything that President Trump said today. So the story does not match in this case. So to sum up, either you look at this war as it's either Iran and nuclear or it is part of a bigger picture of the changes going in the world and then you look at Hormuz Strait and say well it's either the United States and the insurance companies closed it and the main beneficiary of this is the United States and we heard President Trump talking about it today. Or Iran closed it but that does not make any sense and that is a bigger conspiracy theory because how was Iran able to do that after what we heard from President Trump today and the existence of all the other navies.","offset":3971,"duration":64},{"text":"Dr. Anas Alhajji: Unfortunately President Trump today failed to deliver to the nation the message why the war is still going. Many people basically expected that he will announce some sort of an end to the war. We told our clients couple of weeks ago that all the indications point to a long war, and today we got the confirmation. This is not going to end soon. And if it's not going to end soon, there is another question mark about what President Trump said. If everything is destroyed in Iran, then why is this war continuing? What is left to be destroyed? So the impression I got out of this speech is that the people around President Trump are not telling him the truth and he is living in his own ivory tower without looking at what's going on in reality. And we have countries around the world that are literally having blackouts, country do not have propane to cook, countries basically are struggling to get petroleum products, etc. Many countries are worried about food supplies and the president did not even mention it today. This is a global crisis. This is the largest global crisis we have in our lifetime. And the president even did not talk about it and he did not explain to the American people why this war is still going until now. If everything is destroyed why the war is not ending?","offset":4035,"duration":93}],"startTime":3731},{"title":"Leadership and Control Within Iran","summary":"Anas clarifies the internal power dynamics in Iran. He explains that the Iranian Revolutionary Guard has effectively seized full control of the government following recent leadership casualties.","entries":[{"text":"Host: Anas, who is actually in charge in Iran and calling the shots? Because we've seen so much conflicting news in the last few days. President Trump before this speech had said very clearly in his Truth Social posts that what the speech was likely to be about is that Iran had requested a ceasefire and that Trump was likely to agree to that ceasefire. Now preempt, apparently trying to preempt this speech, the guy who is still technically the president of Iran, although the president is not really the head of state who's in charge in Iran, it's really the Supreme Leader who calls the shots. But this guy who is the president issued a letter to the American people in which he says look we don't want any ceasefire, we would not agree to a ceasefire, we want the war to be completely over and we won't accept any end until we have a promise of no further attacks.","offset":4128,"duration":59},{"text":"Host: So it seems like if nothing else that whether that was a true statement that's reflecting the Iranian government or just the guy who's not really in power anymore expressing his view isn't clear, but it seems like it did have the effect of taking the ceasefire discussion out of President Trump's speech. Meanwhile, we're told that who's really in charge of Iran is the Supreme Leader, but that would now be the killed Supreme Leader Ayatollah Khamenei's son. Nobody's seen him since he supposedly took power. Nobody's heard from him. We're told that he's still alive, but we don't know that for sure. Who's calling the shots in Iran and how should we interpret the various messages that we're hearing out of the media?","offset":4187,"duration":53},{"text":"Dr. Anas Alhajji: The reason why we call it the Iranian regime while in other places we call it government, but in Iran we call it a regime, because we have the official government and then we have the support coming from various militias and groups of that government. If you sum them up we call that a regime. So the Iranian revolutionary guard are not part of the government, but once you put them together they become a regime. And what we've seen historically is that there are of course differences between the government itself, the official government where you have prime minister and you have president and you have a foreign minister, they are more diplomatic. While most of the military actions and the attacks and everything else comes from the revolutionary guards who are not part of the government. So historically we've seen that division.","offset":4240,"duration":56},{"text":"Dr. Anas Alhajji: But even within the revolutionary guard they are not really one unit. And what happened is that after the killing of most of the leadership including Ayatollah Khamenei who the religious leader, they decided to at least for a short period of time to work independently. So they told them okay we have no leadership at this stage so every group you are on your own. So we've seen various groups basically acting on their own, attacking on their own, based on their location, based on their beliefs, based on whatever their leaders basically believe about other countries. So we've seen attacks on the Gulf nations, we've seen more attack on some relative to the others, etc. And then the foreign minister came in and said we know nothing about it. Probably he's right because there was a complete disintegration of the system at least for that period of time.","offset":4296,"duration":65},{"text":"Dr. Anas Alhajji: At this stage, it's very clear that the revolutionary guard basically took over the government. So now we can say that unlike in the past where we have a government and then we have the revolutionary guard and the others, now the revolutionary guard basically literally took over the government, so they are one unit right now. And the whatever kind of nice messages we get, we get from people who have no actual power on the ground. And so everything you hear about the Iranian parliament, this is just a joke. This has no impact. So when they say oh we are going to install a tollbooth for example and we got to charge $2 million per ship, etc., this is coming from people who have no power on the ground at all. Unfortunately the western media basically took them seriously and spread the misinformation all over the world. But they have no power.","offset":4361,"duration":62},{"text":"Dr. Anas Alhajji: And speaking about Iran's ability to charge for it, under international law there is no way that they can charge. There is no way they can charge. And whatever they are doing if they are getting any money from anyone, this is an extortion. And the funny part here is if there are governments that are literally cooperating with Iran and paying them so their ships can pass, so we are talking here about Pakistan, we are talking about India, we're talking about Malaysia and probably others, why President Trump is not mad at them? Because they are cooperating with those terrorist and the regime that is killing people who killed 40,000 people of its own people. Why? Because if they are paying them money then they are supporting the regime. Why we did not hear a word about that? Simply because probably it does not exist in the first place.","offset":4423,"duration":59}],"startTime":4128},{"title":"Crossing Red Lines and Escalating Attacks","summary":"The conversation explores the unprecedented nature of the war as both sides abandon established red lines. Anas notes this has led to the nonsensical targeting of regional assets across the Middle East.","entries":[{"text":"Host: Anas, I want to follow up on a really important point that you made in your last interview three weeks ago. What you explained is that most people assume that Israel has nuclear weapons that they could use against Iran but Iran doesn't have a nuclear weapon that they could use in retaliation. You explained that Iran really does have the equivalent of a nuclear weapon in terms of the consequence of using it, which is that Iran could target the desalination facilities of both Israel and other allied Gulf countries which unlike Iran itself which only gets 3 percent of its drinking water from desalination, Israel and other countries in the region are extremely dependent on desalination. So if Iran attacks their desalination they are forcing starvation and just horrible, horrible humanitarian outcomes. They don't have that same vulnerability with their own desalination plants because they only get 3 percent of their own water from desalination. And so you made the argument that Iran could potentially if they really wanted to use the proverbial nuclear option they could escalate to targeting desalination facilities.","offset":4482,"duration":79},{"text":"Host: Now about a week after you made that prediction, Iran made a formal announcement saying if our energy, our civilian energy infrastructure is targeted, we will respond by targeting the enemy's desalination facilities which could bring about that horrific humanitarian outcome that you described. So it seems like this is escalating and escalating quickly. Do I have that right and how do you see this playing out? How serious of a risk is this?","offset":4561,"duration":35},{"text":"Dr. Anas Alhajji: Yes, you are absolutely right. And one of the issues that we have to really realize is when we say this is a historic event, it's not only in term of impact. It is historic in various ways. One of them is there are no red lines. There are no, no one basically has any red lines, the United States, Israel and the Iranians. No red lines. And if you look at the attacks of the other countries in the Gulf etc. there were no red lines. So on every part on the parts of everyone there are no red lines and that make it more, in a sense, another reason to be historic. But one of the other reasons why it is historic because of the nonsense, there are a lot of nonsense going on that we cannot even explain at this stage. We don't know what's going on. For example, Iran is hitting the GCC countries, that's the six countries in the Gulf and some targets in Iraq.","offset":4596,"duration":57},{"text":"Dr. Anas Alhajji: They are hitting them because they said oh you are cooperating with the Americans and the Israelis and therefore we got to hit you. Well if that's the logic then we need to explain this. The Israeli planes that are hitting the targets in Iran and the Israeli rockets basically that are using the fuel, that fuel is some of it is coming from Azerbaijan and Azerbaijan is next to Iran. It's a neighbor. And Chevron is the largest oil company operating there in an oil field. So it is an American company. We saw Iran hitting for example a Ruwais refinery in the UAE. Ruwais refinery is a joint venture between ADNOC and European companies, so there are no American presence there and there are no military bases there. Yet they attacked it.","offset":4653,"duration":55},{"text":"Dr. Anas Alhajji: But why they are not attacking Azerbaijan who is literally giving the oil to Israel to bomb targets in Iran? Same thing for Kazakhstan, the same thing for Turkey because that oil coming from Azerbaijan basically is coming through Turkey. People saying well Turkey is a NATO member. Well I can tell you we know that Trump does not care about NATO and Trump does not care about Turkey if Iran attacks Turkey. But there are, all this confusion and all those issues that do not make sense at all. For example, attacking Salalah oil depots in Oman. Salalah is like, if you are in Iran Salalah is at the other side of the world. And it's an oil depot. Why you are hitting it? There are no Americans there, there are no Israelis there, there's no military base there. And how come literally a drone will go all the way across the Emirates, across Saudi Arabia, across the empty quarter, go all the way to the end of Oman to the other side where Yemen is and hit the target precisely?","offset":4708,"duration":67},{"text":"Dr. Anas Alhajji: So there are too many questions, there are too many things that do not make, do not make sense. For example, hitting this refinery. If Hormuz Strait is closed and the refinery cannot export, why you are wasting ammunition, why you are wasting drones or rockets to hit it while the refinery basically is useless? Why hitting a tanker like the Kuwaiti tanker yesterday that's been in the same place for a month? It's 200 mile away from Hormuz Strait. It cannot go away, it cannot go through the Hormuz Strait, is not even moving. Why hitting it while you know it's not going to go anywhere? And was it a mistake, was it, was the objective something else? What, whatever the case is there are too many questions that have no, no answers. But the bottom line here is the Hormuz Strait is still closed and that is a big failure for the US policy in the region regardless of what Trump claimed earlier in the speech.","offset":4775,"duration":69}],"startTime":4482},{"title":"Geopolitics and the Hormuz Strait Closure","summary":"Anas argues the effective closure of the Strait of Hormuz is driven by a lack of shipping insurance rather than Iranian naval power. He also highlights how China proactively stockpiled energy before the conflict began.","entries":[{"text":"Dr. Anas Alhajji: The fact that the Hormuz Strait is closed, even at this moment, regardless of who closed it, is a failure of US policy. And there are strange things again when we talk about historic event, there are some very strange things. I'm going to tell you some. For example, if we go back to the national security strategy, it was released in November about four months before the war. So I'm going to read this to you from that strategy. So I'm reading right now. \"America will always have core interest in ensuring that Gulf energy supplies do not fall into the hands of an outright enemy. That the strait of Hormuz remain open, that the Red Sea remain navigable, that the region not be an incubator or exporter of terror against American interest or the American homeland, and that Israel remain secure.\"","offset":4844,"duration":62},{"text":"Dr. Anas Alhajji: Let's look at this one because this is kind of really strange statement. President Trump today said we don't need the Hormuz Strait, we don't need the Gulf, we don't need any of that. The strategy said we don't want it to fall into enemies' hand. And he did not say that today. This was one of the biggest failures of the speech. He should have said that. But here is the strangest statement in the strategy. Of course the strategy is really conclusions of a larger document that remains secret. We don't know what's in it. And therefore this, this paragraph, several paragraphs that been omitted. And here is why I'm saying this. The United States historically if you look at various strategies over the last 50 years, always talked about freedom of navigation in those waterways or the choke points. Notice the following.","offset":4906,"duration":54},{"text":"Dr. Anas Alhajji: This is the first time we are, we see a document like this, four months before the closure of Hormuz Strait, saying \"The Strait of Hormuz remain open.\" It never been closed. This statement makes sense if the Hormuz Strait was closed just once in history. So whoever wrote that statement there they must have something before this paragraph, \"open.\" If it wasn't closed in history, why you are using this statement, \"remain open\"? And the other thing is you are talking about Hormuz Strait, why you are tying Israel to it? You look at what we have in actual life, we have Israel basically attacking Iran right now and the Hormuz Strait basically is part of it. But the question here is if Anas Alhajji wrote in June and July, that months away, months before the war, months before the closure of Hormuz Strait.","offset":4960,"duration":61},{"text":"Dr. Anas Alhajji: And people who they can go to our daily energy report and they can go to our newsletter and they can see it. I wrote the 12-day war. In June Israel attacked Iran. China had no problem. Everyone was expecting Israel to attack Iran for the last 20 years and finally they did. But once the Trump administration started attacking Iran, that changed everything. And China was ahead, they knew in advance what's going on. So China basically stopped importing LNG from the United States, stopped importing oil from the United States, they were ahead on Venezuela before the blockade, they were ahead on Venezuela before the death of Maduro, etc. But they been and if you go back to the previous shows we had probably the last three shows or four, we've been talking about how China was building those massive inventories, oil inventories and everything else, in preparation for either war, sanctions or a major interruption.","offset":5021,"duration":62},{"text":"Dr. Anas Alhajji: Now we know. China knew. And China one of the least impacted countries by the closure of the Hormuz Strait right now at least in the short run. Once we look at those events and look at the 12-day war, what I've written was the China got the message out of the stories that been published in major news media outlets and very prestigious outlets. We've seen a number of stories talking about Iran closing the Hormuz Strait. Again we are talking about June. And if you look at those stories you will find something kind of very strange about them because all of them have the same talking point, some of them in the same sequence. That means there is a public relation company basically was directing that. Why they were doing it? So what I wrote at that time was China got the message and the message was the Hormuz Strait will be closed, but it's not Iran who is going to close the Hormuz Strait, it is the United States.","offset":5083,"duration":65},{"text":"Dr. Anas Alhajji: Again this is written in June and July. So we have the November document after that talking about the keeping the strait open and the strait never been closed. And then in June and July we were talking about the United States basically closing the Hormuz Strait. And then we have the insurance fiasco that we've seen until now. I know that many people were pushing against this, this idea, calling it a conspiracy theory etc. and they tried really hard to debunk this idea. Here is the issue that they need really to answer. The issue is this. Even if you send the navy to escort ships out of the Hormuz, ships are not going to move without insurance. If the insurance remains non-existent or extremely expensive, ships are not going to go along with the navy. Because shippers are going to tell Trump or Modi or anyone else who wants to send those navy vessels, telling them look, if I go with you and I get attacked and I lose my ship and I lose everything on it, will you compensate me? And Trump is going to tell them no, Modi is going to tell them no, I'm just providing a service for you you should pay me for it I don't have to compensate.","offset":5148,"duration":73},{"text":"Dr. Anas Alhajji: They are not going to go. They need that insurance to exist and to be cheap enough for them to move. So any way you look at it you say it's conspiracy theory or not it doesn't matter. They need that insurance. So it is an insurance story anyway you look at it. On the other side those who are claiming that Iran closed the Hormuz Strait again Trump told us today that Iran has no navy, has no power, Iran, we heard the whole talk. So either someone is lying to President Trump or Iran has no power.","offset":5221,"duration":39}],"startTime":4844},{"title":"The Risk of Targeting Nuclear Facilities","summary":"Anas warns of severe market panic and potential humanitarian disasters resulting from military strikes against civilian infrastructure, specifically referencing attacks on Iran's Bushehr nuclear power plant.","entries":[{"text":"Host: Anas, there's one more nuclear option that we need to talk about which is so far in human history, no military force has ever intentionally targeted an operating nuclear reactor. In other words the horror scenario, the terrorism scenario of intentionally dropping a bunker buster bomb on top of an operating nuclear reactor to turn it into a dirty bomb of sorts. Now one of the things that has already occurred, and by the way article 56 of the Geneva Convention very clearly prohibits the intentional targeting of any nuclear electrical generation station. You cannot target nuclear electrical generation stations by international law. Except either the United States or Israel, I'm not sure who, has already made at least three attacks, air strikes on the Bushehr nuclear power plant which is Iran's one operating nuclear power plant.","offset":5260,"duration":63},{"text":"Host: Now those were not targeting the reactor. If they had intended to blow up the reactor and breach its containment they would have succeeded, so they weren't trying to do that. They were probably trying to take out the infrastructure and prevent it from generating electricity and supplying it to the grid. But it does seem that they're already violating the Geneva Conventions by targeting a nuclear power plant. Where is this headed? I'm just really concerned about the escalation that could occur from here.","offset":5323,"duration":33},{"text":"Dr. Anas Alhajji: Again this is a historic event for several reasons and one of the reasons why because there are no red lines. And what you described is a red line that's been crossed and is going to be crossed again and again and as a result Iran is going to cross this red line on the other side. Because as you know they already listed the four reactors in the UAE as a target, the stations like you said probably not the reactors because they need kind of special bomb busters or others etc. But they literally put that as a target. So there are no red lines and with a war with no red lines everything is possible.","offset":5356,"duration":42},{"text":"Dr. Anas Alhajji: The issue that I experienced firsthand was when I woke up in the morning here in Dallas and I got flood of messages and emails, people scared to death from oh what if Bushehr basically explodes and would we get nuclear and literally some high net worth individuals basically sent me messages and said should I put my family in a car and leave to Oman or any other country. So people basically being panic and that panic alone could cause massive problem because if you are talking about millions of people taking the highways, the rumor on its own is enough to cause problems let alone if it, if it becomes reality.","offset":5398,"duration":48},{"text":"Host: Well as you said Anas, Iran has announced that if their civilian power generation infrastructure is targeted, they will respond number one by targeting the desalination facilities of neighboring countries which you've described as a nuclear-like option because of its consequences. Number two that they will target the United Arab Emirates operating nuclear power station at Barakah, or the Barakah nuclear power station which is outside of Abu Dhabi. They've already said that will be a target. And then in tonight's, this is Wednesday night that we're recording, in tonight's address from President Trump, he said very soon and possibly simultaneously that the United States might target all of Iran's civilian power generation stations. So it sounds like the event that Iran said they would respond to by targeting both desalination and nuclear power plants is one that President Trump just signaled his intention to escalate to. This is a very scary moment. This feels like, you know, a replay of the Cuban Missile Crisis except this time we actually know about it. Am I exaggerating to say it's that big of a deal?","offset":5446,"duration":72},{"text":"Dr. Anas Alhajji: No, but I think we should be very aware of the fact that today after Trump speech, I am completely convinced that the people around him are not telling him the right picture. The way he described things are far away from reality. Let me give you another example on how far away from trade reality he said drill baby drill. Okay, drilling activities in the United States been down since he came to office. US production been declining in recent months. So he is completely out of reality and I am afraid that the people around him are not telling him the truth. Before this speech oil prices were down. Right now after the speech oil prices are 5 percent higher and they are going up. So the message, the main message of the speech basically is that this is a long war and this is going to continue and the market is pricing it.","offset":5518,"duration":57},{"text":"Dr. Anas Alhajji: And I think by tomorrow morning probably many people who were counting on probably it will be a matter of days is going to change their mind. And that will impact of course the markets whether you talk about oil gas LNG or anything else.","offset":5575,"duration":14}],"startTime":5260},{"title":"Global Energy Markets and Naval Strategy","summary":"The interview concludes with Anas assessing the global energy market implications if the US follows through on President Trump's suggestion to abandon its protection of the Strait of Hormuz.","entries":[{"text":"Host: Anas let's move on now to what everyone's waiting for, which is how do we bring this all together in terms of the outlook for oil prices, LNG, energy markets generally. If the US is basically from what President Trump said very directly in tonight's public address, he said the US will probably walk away from the situation in the Hormuz Strait, leave it to other countries that depend on it. It sounds again as you suggested that maybe President Trump isn't getting the full story from the people around him because of course oil prices are set globally. If the Hormuz Strait is not reopened, energy prices are going to stay high for everyone, including US voters through the midterm elections. So it seems like the story doesn't add up.","offset":5589,"duration":55},{"text":"Host: But it does seem like the president intends to walk away from the situation in the Hormuz Strait once they've finished their military operations against Iran and it's unspecified exactly what that is, but the one thing he did say that was a specific indication of intentions was to target potentially simultaneously all of Iran's civilian energy production capabilities, exactly the thing that Iran has said if it happens is what's going to cause them to target desalination and nuclear power plants. What does this mean for energy prices and what does this mean for global energy markets more broadly?","offset":5644,"duration":36},{"text":"Dr. Anas Alhajji: When President Trump is talking about others basically coming and protecting the Gulf and opening the strait, he means only the people he know and he is talking about European leaders. He's not talking about China. He's not talking about the rest of Asia. So let's be clear about that. China will be happy to bring its navy and and have control of the strait. This will never happen and the United States will...","offset":5680,"duration":25},{"text":"Host: The audio cuts there.","offset":5705,"duration":2395}],"startTime":5589},{"title":"Episode Outro and Disclaimers","summary":"The hosts wrap up the episode with standard podcast legal disclaimers, sponsor acknowledgments, and closing music.","entries":[{"text":"...or sponsors. MacroVoices, its producers, sponsors, and hosts Eric Townsend and Patrick Ceresna shall not be liable for losses resulting from investment decisions based on information or viewpoints presented on MacroVoices.","offset":8100,"duration":15},{"text":"MacroVoices is made possible by sponsorship from bigpicturetrading.com and by funding from Fourth Turning Capital Management LLC. For more information, visit macrovoices.com.","offset":8115,"duration":15},{"text":"[Intro Music]","offset":8130,"duration":15},{"text":"[Intro Music continues]","offset":8145,"duration":15},{"text":"[Intro Music fades out]","offset":8160,"duration":15}],"startTime":8100}],"entries":[{"text":"Host: This is MacroVoices, the free weekly financial podcast targeting professional finance, high net-worth individuals, family offices, and other sophisticated investors. MacroVoices is all about the brightest minds in the world of finance and macroeconomics telling it like it is, bullish or bearish, no holds barred. Now, here are your hosts, Eric Townsend and Patrick Ceresna.","offset":0,"duration":28},{"text":"Eric: MacroVoices episode 526 was produced on April 2nd, 2026. I'm Eric Townsend. We've got another MacroVoices double header lined up for you, and it's going to be a doozy. President Trump gave an address Wednesday night that surprised the markets. So I'm recording earlier than usual this week on Wednesday night about an hour after President Trump's speech, in which he said that if no deal can be reached, the US plans include targeting all of Iran's civilian electric power generation plants, probably simultaneously. That's exactly the red line that Iran has previously said would cause it to retaliate by targeting desalination plants and the UAE's Barakah nuclear power station.","offset":28,"duration":53},{"text":"Eric: Now we know the president's negotiating style is to make dire threats and then walk them back once a deal is reached. So hopefully the threat of targeting civilian power generation infrastructure will come off the table soon. But overall, my take is that this conflict is heating up, not cooling down as the market was interpreting before President Trump's Wednesday evening speech. And the president was clear in that speech in saying that the US would be hitting Iran very hard over the next two weeks if no deal is reached.","offset":81,"duration":37},{"text":"Eric: We're going to kick things off with an exceptional performance by freelancer.com CEO Matt Barrie, who returns as this week's feature interview guest for a full interview on the latest developments on artificial intelligence, what they mean for private credit markets, why the AI business model is setting the stage for an eventual market dislocation on the scale of the 2000 .com bust, why paper-token inference pricing is inevitable and why it will collapse the current AI business model, and much more.","offset":118,"duration":39},{"text":"Eric: Then for this week's Iran conflict update, Energy Outlook Advisors founder and managing partner Dr. Anas Alhajji returns as this week's second feature interview guest, and it's going to run just as long as our first feature interview because there was so much to cover after the president's Wednesday night address. So this is going to be a long episode, but a very important one. So sit back, relax, and expect some really exceptional content from both of our guests.","offset":157,"duration":32},{"text":"Patrick: And I'm Patrick Ceresna with the macro scoreboard week over week as of the close of Wednesday, April 2nd, 2026. The S&P 500 index down 24 basis points, trading at 65.75. Markets put together an oversold bounce, but will rallies fail with this geopolitical backdrop? We'll take a closer look at that chart and the key technical levels to watch in the post-game segment.","offset":189,"duration":27},{"text":"Patrick: The US Dollar Index down nine basis points, trading at 99.55. The May WTI crude oil contract up 1085 basis points to 100 spot 12. The May RBOB gasoline up 439 basis points, trading at 3.09. The June gold contract up 500 basis points to 48.13. Gold's approaching its 50-day moving average, bouncing from its oversold conditions.","offset":216,"duration":48},{"text":"Patrick: The May copper contract up 162 basis points, trading at 5.65. The April uranium contract down 12 basis points, trading at 84.30. And the US 10-year treasury yield up four basis points, trading at 4.37. The key news to watch this week is Friday's jobs numbers, and next week we have the ISM services PMIs, the core PCE and CPI inflation numbers, and the FOMC meeting minutes.","offset":264,"duration":28},{"text":"Patrick: This week's feature interview guest is freelancer.com founder Matt Barrie. Eric and Matt discuss the sustainability of the AI business model, why rising risks and weak unit economics could lead to a shakeout similar to the .com era, and how AI's impact on software and private credit could create broader market stress. And stay tuned for a special follow-up with Dr. Anas Alhajji where we break down the escalating Iran conflict and its implications on global energy markets. Eric's interview with Matt Barrie is coming up as MacroVoices continues right here at MacroVoices.com.","offset":292,"duration":48},{"text":"Eric: And now with this week's special guest, here is your host, Eric Townsend. Joining me now is freelancer.com founder Matt Barrie. As usual, Matt has written an excellent paper about AI. This one is called \"Pay to PrAI,\" that's pay to P-R-A-I. You can find that linked in your research roundup email. If you don't have a research roundup email, it means you're not yet registered at MacroVoices.com. Just go to our homepage, MacroVoices.com, look for the red button above Matt's picture on the homepage that says \"Looking for the downloads.\"","offset":340,"duration":43},{"text":"Eric: Matt, before we even get into all of what's going on in AI, we've got some news just as we're recording this on Tuesday evening US time. There's some recent news just in the last day or so, which is, you know, a lot of companies before they IPO, they'll do a little bridge round, maybe 10-20 million bucks just to cover some expenses until they get to their actual IPO. OpenAI is planning an IPO. They did a little bridge round, 122 billion with a B dollars. All-time record for a private fundraising round. And what is that, something like 100 times bigger than any private fundraising round has ever occurred like before 2025. Why did they need 122 billion just to bridge them from now to their IPO, which is expected in less than a year?","offset":383,"duration":45},{"text":"Matt: Thanks for having me. It truly is stupendous. I mean, before 2025, the largest sort of private venture rounds were in the single-digit billions. The headline number is 122 billion raised on a 730 billion pre-money valuation. When you get down to the actual segmentation of kind of what's going on, it seems that it's only about 25 billion dollars worth of cash. It seems to be more of a vendor financing than an actual straight cash injection.","offset":428,"duration":33},{"text":"Matt: You've got Amazon, Nvidia, and SoftBank primarily putting the money, or the in-kind, in. Amazon's putting in 50 billion, but that's contingent on OpenAI spending 100 billion, I think over the next eight years on their compute, which I'm sure won't make Microsoft happy, and it seems like a good deal, at least on paper, for Amazon. So there's 15 billion going in up front and 35 billion is furthermore contingent on the company either going public by 2028 or achieving artificial general intelligence. I'm not sure how they're going to really define that. I think the underlying definition is a panel of experts will make a decision, yes or no, which is a bit strange for a financial decision.","offset":461,"duration":33},{"text":"Matt: There's 15 billion down up front, 35 billion contingent on going public or AGI for a 100 billion commitment the other way around, so it's a bit like a procurement round. SoftBank loves doing this sort of, I like to call them Russian stands, where they kind of lead rounds and mark up valuations to the moon. We saw it with WeWork, we're seeing it again with Enron, I mean OpenAI. They've already put in about 40 billion, they're putting another 30 billion in. But to raise that money, they don't actually have the cash on the balance sheet, so they've taken a 12-month bridge loan for 40 billion and they're tranching in 10 billion at a time over the course of the year for a total of 30 billion.","offset":494,"duration":37},{"text":"Matt: And obviously that's kind of just getting them through to the IPO so they've got a liquidity event. And then Nvidia is putting in in-kind, as they tend to be doing in all these sort of circular economy sort of deals in the AI space, where GPUs and infrastructure will be provided to the tune of 30 billion into the round. So it's about a 25 billion dollar round of cash sort of up front, 10 from SoftBank, 15 from Amazon. We'll see if the rest of the money comes in, but the rest is in-kind.","offset":531,"duration":27},{"text":"Matt: So it seems from looking at this, and if you look at the compute numbers, I mean they truly are astronomical that are being contributed in the form of, you know, either Nvidia credits, I think there's like three gigawatts of inference and two gigawatts of training capacity as part of this investment. You know, that's sort of the power that gets drawn by a small country. So it seems to be what they're trying to do is scale up the spend on compute so much that they can find a way to bring the unit economics down because that's really the key problem in the space, that nobody in the AI compute space is making any money other than really Nvidia who does about 160 billion of revenue and 100 billion of earnings, and then TSMC who provide the chips to Nvidia, but the rest of the space is actually negative on using the product in terms of the unit economics. So the more you use the product, the more you lose the money. So I think they're trying to make it up on volume.","offset":558,"duration":49},{"text":"Eric: Matt, I can't imagine any responsible business executive signing off on 122 billion dollar deal unless the underlying business model was rock-solid and it didn't have any major risks in it. Just happens that you wrote this missive over the last couple of weeks called \"Pay to PrAI.\" I don't think that's actually the conclusion that you reached. Tell us about the economics of the, I'll call it the consumer AI business model, offering AI through chat to people like me who sign up for a Max subscription on Claude or a Pro subscription on OpenAI. How much money are they making or losing on that?","offset":607,"duration":37},{"text":"Matt: The AI industry is consuming an absolute bonfire of money. It's about 600 billion dollars a year that's being spent by the hyperscalers on CapEx. It's reaching a kind of a point now which is kind of incredible where, you know, the CapEx is higher than their internal free cash flow. You know, the fundamental business model that's being pushed in the consumer market and the software development market up until now has really been a venture capital style subsidized model where you pay, you either use the free product and then hopefully upgrade to the 20 dollar a month product, or you use the 20 dollar a month product if you're a consumer or a 200 dollar a month product if you're a power user or if you're starting to do programming.","offset":644,"duration":38},{"text":"Matt: But the problem with these models are that they take an incredible amount of money to train, and I think we've talked about that in previous episodes where you've got training runs North of 100 million dollars a run, you know approaching half a billion dollars a training run. That requires a huge amount of data center build-out, a whole lot, an incredible stupendous amount of data needs to go into these models. And so, you know, because the cheap data that's scraped off the internet for free is basically sort of, you know, drilled out to an extent, they have to do licensing deals to get access to that data. Sometimes they do dodgy things like Anthropic, you know, scraped a whole bunch of books and scanned them in and then they got caught and they had to pay the biggest, I think, fine in copyright history, I think it was about 1.5 billion dollars for the illegal scanning of all that data, etc.","offset":682,"duration":42},{"text":"Matt: So it's incredibly expensive to train. But the fundamental problem is that when you actually use the inference, you basically put queries into GPT or queries into Claude and you run them, those queries are loss-making. You can't make it up on volume under the current models. While we do see, you know, the underlying hardware is on sort of a Moore's Law sort of trend, and Moore's Law for those of you that don't know what it is is, you know, every 18 months to two years or so, effectively the technology that goes into chips allows semiconductors to be produced with finer and finer feature sizes, which effectively allows the compute capability in terms of processing power to effectively double or the cost to half every 18 months.","offset":724,"duration":44},{"text":"Matt: While you are riding on that sort of silicon Moore's Law trend, because the models are in such a brutally competitive environment where there's literally zero lock-in, there's almost zero switching costs, so I can, if one day ChatGPT 5 comes out I'll switch to that, but then Claude 4.6 opus comes out and that's better, I'll switch to that, and so there's nothing stopping me overnight really just changing the models. Because of the competitive environment and so forth, what the situation basically is that each generation of model is being rushed out to kind of get the top of the scoreboard so that all the customers flock to that.","offset":768,"duration":35},{"text":"Matt: And as a result of that, the actual amount of inference or tokens burned, if you will, per useful query with each generation of model, while the underlying compute is getting cheaper and cheaper in terms of what you can get done on the chips, the amount of inference you have to burn for a useful query is actually going up quite dramatically. And so you're actually not seeing a reduction in the cost of inference, you're seeing an increase. And that's before you consider the issue with energy and constrained build capacity for building data centers and power gear and all the other things.","offset":803,"duration":36},{"text":"Matt: And so, you know, a few people have done various models of how much it costs for GPT to deliver their 20 dollar plans, and even if you ask Claude itself, you type a query into Claude saying how much is the underlying compute costs for on a 20 dollar plan with Claude, it will tell you, you know, 15 to 20 dollars, maybe 18 dollars, maybe a bit more. So effectively there's no money being made on these 20 dollar plans and when you're a power user you can burn up to several hundred dollars on a 20 dollar plan. And it gets even worse on these 200 dollar plans which are used by programmers now, because the nature of programming is you're streaming tokens almost forever, and you know, the average user on a 200 dollar plan can burn, you know, many thousands of dollars of underlying compute, and in fact there's a, there's a leaderboard called VibeRank where people compete to see how much underlying compute they can burn on a 200 dollar plan. The leading guy on the leaderboard has burnt 51,000 US dollars in a single month on a 200 dollar plan.","offset":839,"duration":60},{"text":"Matt: So the issue is that as these models get more and more competitive and new versions come out, you know, you're getting an exponential increase in the amount of inference you've got to burn, and that is meaning that these models are not getting cheaper and you're not making up on unit economics. And so it kind of feels like this funding round, especially with the amount of vendor financing that's packed into it, it feels like this is an attempt to really try and scale up the underlying infrastructure and GPU capability so that potentially you know, some sort of threshold can be crossed in the underlying economics so inference could be profitable. But there's one big problem with all that, which is is the demand there? And and that's where we are.","offset":899,"duration":44},{"text":"Eric: Matt, you said it's 122 billion dollar capital raise on a pre-money of 730, so I get 852 billion is the current enterprise value. Assuming an up round, which is what everybody assumes, we're going to go just let's call it an even trillion for the IPO because hey what's, you know, 100 billion here, 100 billion there, you know, eventually you're talking about real money. But holy cow, let's say that OpenAI goes ahead and IPOs sometime this year for 1 trillion dollars. Are you going to be long, short, or flat, and why?","offset":943,"duration":37},{"text":"Matt: It really does feel in the space that we're really in the moment where a supernova is starting to explode and we're probably going to end up with a giant black hole like we did in the .com boom the first time around. I mean a trillion dollar valuation at IPO is absolutely gigantic. You know, they've raised 122 billion here in this round. They were mooting that the IPO earlier in the year was going to be a 60 billion dollar raise on about a trillion, but you could probably imagine that that number has possibly scaled up a little bit or they want to keep it tight obviously because once it gets to public markets you don't want to have too much stock unload onto the market.","offset":980,"duration":36},{"text":"Matt: But a bigger problem for them is the fact that you've got Elon Musk in the wings who's not just suing OpenAI because it turns out you can't IPO a charity and they've converted OpenAI to a for-profit model and there's a lot of complications around that, but he's also IPOing his SpaceX for I think it's 1.75 trillion valuation. So there's a big possibility that a lot of the heat's going to be taken out of the market when he does his 75 billion on a 1.75 trillion dollar raise, and it looks like he's going to beat OpenAI to to going public because if you kind of look at the news and you know what's all happening with the ETFs and the allocations and so forth, he's a lot further along.","offset":1016,"duration":40},{"text":"Matt: I don't know, in the olden days, you know, if you were to invest in Amazon when it went public or Microsoft when it went public, you know, you had the ability to make a lot of money. I don't know how much is left on the table for the general public when the company's being valued at a trillion dollars when it goes public, you know, what are you going to do? Get to two trillion, 10 trillion? I think Nvidia is what, four or four and a half trillion valuation, and they're the only ones making money in the space.","offset":1056,"duration":26},{"text":"Eric: Matt, the parallels between this and the late 1990s .com boom before the 2000 .com bust are just striking to me. And it occurs to me before I go on that we probably have listeners that weren't even born when that happened. So for anyone who's not familiar with what happened there, Wall Street became absolutely obsessed with the idea that the internet is going to be a really big deal. And the thing that's really important to understand about this is they got that call exactly right. The internet, the public internet was going to change the world we lived in in ways beyond what anyone could even conceive and they got the call right that it was a really big deal.","offset":1082,"duration":44},{"text":"Eric: And I think they're getting the call right again that AI is a really big deal, maybe as big or bigger than the public internet. But the thing is, even though they got the call right, they started throwing money at dumb ideas without thinking and it just turned into a complete frenzy. It seems like that's happening again here, but in the late 90s, it was every tiny little company that had .com in its name and it didn't really matter whether they had a business model. It's different here. It's the big players, which frankly have a business model. But as you very eloquently explain in this excellent piece I recommend everyone read called \"Pay to PrAI,\" that business model isn't viable for the reasons that you just described, or it's not profitable or not likely to be sustainable.","offset":1126,"duration":50},{"text":"Eric: How should we think about this? Is it inevitable that a .com bust like we had in 2000 is coming for AI, and does it have the same dimensions as the one in 2000? Is it bigger, smaller, worse, better? What do you think?","offset":1176,"duration":16},{"text":"Matt: So if you think about the .com boom, and I was there actually in Silicon Valley in '97, '98, '99, 2000, I saw it all. There was a hypothesis the internet was going to be a big thing and it turned out to be a enormous thing in terms of the benefits to humanity and society and will continue to grow in terms of its applications. And AI is the same thing. AI is going to be absolutely transformative for humanity in terms of what it can do. At that time, you know, a company whose valuation went through the roof was Cisco, and their tagline was \"We network networks.\" We talked about it I think last MacroVoices. Every time you plugged in a bit of the internet, you needed to have a router to connect up the network and Cisco equipment was going to be everywhere and why wouldn't it be the most valuable company in the world, right?","offset":1192,"duration":42},{"text":"Matt: And the same as with OpenAI in a to an extent, you think okay, well they've got the best AI models, AI is going to be everywhere, why wouldn't OpenAI be the most valuable company in the world? But then at the same time, you also had AT&T, and up until about 1996 AT&T had a 60% market share. It basically built the network using Cisco equipment to connect up the world. You had three players in the market and I think it was mentioned at the time by an analyst that they had margins that would make drug dealers blush.","offset":1234,"duration":25},{"text":"Matt: But the problem was that in 1996 the Telecommunications Act, Regulation Act came in and deregulated the market. And you started having fourth entrants and fifth entrants and so forth and and people buying and selling capacity to each other etc. and when you started having the fourth entrant come in and competing on cost, the unit economics fell apart. And if you think about the AI compute space, well Amazon had it pretty good up until the AI boom, I think its its CapEx as a percentage of earnings was down to about 6% at one point.","offset":1259,"duration":30},{"text":"Matt: Now these hyperscalers are spending, or the cloud computing companies are spending, 60% of earnings on CapEx, over 100% of earnings on CapEx. They're spending 600 billion dollars a year at the moment in terms of a run rate in CapEx and it's hypothesized that by 2030 it's going to be 5.2 trillion dollars of CapEx, right? Now when you just had Amazon, you know, really dominating in terms of of cloud, you know, it was sitting pretty and I think it had about 60% market share.","offset":1289,"duration":26},{"text":"Matt: Now you've got Microsoft who's taken over and they're market leader and so forth. Now you've got entrants such as Oracle that's competing on price and you've got CoreWeave and the Neo clouds and the unit economics are starting to look a little bit shaky. And then you had a big bust in the .com bust where, you know, all these companies had money being thrown at them and you're seeing that right now. Any company that kind of has AI in its business plan is getting these stupid, you know, seed rounds in the hundreds of millions of dollars. I remember when seed rounds were hundreds of thousands of dollars, now you have hundreds of millions of dollars.","offset":1315,"duration":36},{"text":"Matt: And you know through the early 2000s you had a real trough in the technology space where where everything blew up and was somewhat uninvestable for a period of time. But through that period of time, you had companies like Google and Amazon continue to grow and double down and Microsoft and so forth and ultimately today became very very big companies. So I think we're seeing this on steroids right now with AI CapEx and compute and the OpenAI funding rounds and so forth. And you know it's unquestionable AI is going to be completely enduring and just absolutely game-changing for society. But I think the kind of circle jerk of money that's sloshing around between a very very small number of companies at stupidly high valuations and at a scale that is just stupendous is going to potentially end up in a big bust.","offset":1351,"duration":51},{"text":"Eric: Matt, I want to focus on that because a lot of people are going to mishear what you just said and they're going to say Matt Barrie said imminently tomorrow there's about to be a great big bust in all of the AI stocks. That's not what you said and it really rings home for me because the reason that my partners and I sold our software company in the summer of 1998 is because we knew it was a bubble. And my plan at the time was to take all of the proceeds and short the NASDAQ because I knew it was a bubble.","offset":1402,"duration":33},{"text":"Eric: Fortunately I got talked out of that, but if I hadn't, I would have lost everything because even though we were right, basically the NASDAQ doubled between '98 and 2000 before it crashed exactly like I predicted it was going to crash. What do we do here? I mean, do you go long, do you go short? And I'll say I'll ask the question this way: OpenAI and Anthropic are both expected to IPO probably in 2026. When they do, you know, is it time to go long or is it time to go short? Because you know I could make either argument. It seems to me eventually you want to be short, but how do you time that?","offset":1435,"duration":37},{"text":"Matt: That's the trillion dollar question, right? You've got SpaceX going public which obviously has Grok and xAI within it. You've got Anthropic going public and you've got OpenAI going public and that's why I think it feels a bit like a supernova, so we'll end up with a big bang in one way or or another. I mean, you know, I think the issue is going to be, I mean that some of these valuations like the OpenAI valuation is kind of predicated on the fact that it's going to capture an enormous amount of value out of the world in order to justify these valuations, right? You know, these funding rounds are so large and the valuations are so high that you need to pitch a revenue line that matches them.","offset":1472,"duration":36},{"text":"Matt: And you know at the moment OpenAI is doing about 2 billion a month in revenue, I think it's at about a run rate of about 25 billion, I wish they'd stop using the word run rate because I think you've actually got to recur once before you can call something annual recurring revenue. So it's doing about 2 billion a month of revenue, losing you know 14 billion this year, I think the burn rate that came out today was is expected to lose 70 million dollars a day this year scaling to 156 million a day lost next year. But in order to to, you know, cross the valley of death and get to the promised land, they've got to show a business model that makes sense.","offset":1508,"duration":34},{"text":"Matt: And I think what their business model is going to is twofold. One is that they're going to take a substantial amount of white-collar jobs away from humans, you know some substantial percentage of jobs in the world are going to go to AI and that's kind of the top-line revenue number. And then the in terms of generating earnings out the other side, the justification is that the infrastructure that's being contributed as part of this 122 billion dollar round is at such a scale that only OpenAI will have the unit economics that will make the inference profitable. So in a combination of taking everyone's job and having the only infrastructure that can run this stuff profitably, I think that's the argument for justifying these sort of trillion dollar valuations.","offset":1542,"duration":42},{"text":"Matt: Now I don't think OpenAI is going to capture, for example hypothetically, you know the value in the AI-powered drug discovery market anymore than AT&T captured the value of the iPhone, right, you know? The underlying technology phenomenal, but as Ilya Sutskever said himself, who was one of the founders of OpenAI, that you can just read 40 academic papers and 95% of what's out there in AI is is published in in the public domain. And that's why every couple of weeks there's a kind of a new foundational model that's top of the leaderboard and every once in a while there's a team of people that you've never heard of, that 160 engineers in a room in Hangzhou like like DeepSeek that comes out of nowhere and suddenly leads in the leaderboard because it turns out that there's no sustainable competitive advantage in the underlying foundational models and what you do need though is access to data.","offset":1584,"duration":44},{"text":"Matt: Those data sets are now kind of out there in public or in the case of the Chinese they probably don't care too much about copyright so they'll always have a sustainable competitive advantage. And I think there's incredible and tremendous opportunity in AI, but it's probably not going to be in these models that that haven't really figured out what the business model is.","offset":1628,"duration":23},{"text":"Eric: Matt, I think there is a very distinct difference between this scenario and the late 90s to 2000 .com story, and that is this. Let's say that we don't know whether it's '97, '98, or '99 right now, but we know that March of 2000 is coming at some point. There's going to be a washout in this commercial AI space where they just realize that the business model wasn't sustainable. Well what happened in the .com bust is we went really a good solid couple of years of kind of a technology recession where there wasn't a whole lot of progress on the public internet because we had to basically shake that malinvestment out of the system, get back to efficient capital allocation, and then you know after 2002, 2003 things started to really take off again.","offset":1651,"duration":51},{"text":"Eric: What if the US government steps in and says, now wait a minute, the military applications of AI create an existential threat to the country if we don't stay ahead of this? We can't tolerate a 2000 to 2003 pause. You must continue, you must do it under US government funding, but we're not going to fund the giving away stuff for free to Max subscribers on Claude. We're going to take it over and you know it's just for the military now. We're not going to have consumer AI anymore. Is that a realistic scenario, or do we need consumer AI in order to train the models in order for the military to get the benefit, you know, what would happen in that scenario where the military says no, we we can't allow a stock market crash to slow down progress on the military applications of AI?","offset":1702,"duration":49},{"text":"Matt: So I don't think it's realistic that we're not going to have consumer AI. I mean the Chinese are open sourcing their models and in fact they've got their strategy to open source both the software and the hardware. You know, and there's been previous leaks of Meta's Llama and and so forth. I think the interesting thing here is that it won't be the government stepping in. I think there's one big company that's kind of been sitting in the wings that has a God-awful AI product and it's in everyone's pockets and that's Apple and the iPhone.","offset":1751,"duration":25},{"text":"Matt: I think in our last chat we talked about how goddamn awful Siri is for supposedly being your original chatbot AI assistant and we hypothesized that it will continue to be awful in the next year and here we are and it it continues to be pretty bad. But they've kind of avoided this whole getting sucked into this whole CapEx bonfire and they've really got two levers they can pull. One is is they're sitting on this cash and they've kind of they can sit back and watch and and as with the .com bust, there was a lot of infrastructure that went through to the second and third owners where you know maybe the first owner that builds out the optical fiber network goes bust and the second owner comes in and tries to make it break even after after purchasing it at a at a cheaper price and washing out the underlying sunk costs, and then the third owner comes in and makes some money out of it.","offset":1776,"duration":46},{"text":"Matt: And I think you might have that situation in the AI compute space where if there is a problem with some of these large foundational model companies, there might be a second or third owner and Apple would be ideal for that. At the same time, what they've been doing is they've been putting in some AI silicon into their products and a lot of this compute that's currently being done in a data centers, you know, by OpenAI, by Anthropic, etc. is going to go to the edge and it's going to go to the edge for a variety of different reasons. One is that you don't want Sam Altman training on your data, and I think we've talked about before that I think an emperor has no clothes moment is heading into into SaaS where you know I think large enterprises are starting starting to think to themselves, you know what, I don't want my data in Google Drive and Gmail, you know it might get trained on.","offset":1822,"duration":44},{"text":"Matt: And you're certainly seeing all the major SaaS companies quietly flicking on a switch in the settings without telling you where they're saying by default now we can train on your data potentially, and then you flick it off but by then it's too late and all your data has been sucked down. So a lot of that compute is going to go the edge, it's going to go to on-prem, you know in the enterprise on compute devices so it doesn't go into the cloud. It's going to be on your phone, it's going to be on your MacBook, it's going to be on your Mac Studio or whatever it may be for privacy, for confidentiality, for latency reasons and the fact that there's some models now that can actually fit on that silicon.","offset":1866,"duration":34},{"text":"Matt: And you know while it might be you know one or two generations away, you know at some point I think real soon a lot of that load and a lot of that compute that's going to AWS data centers and Azure data centers to run Anthropic and to run OpenAI is going to go to the edge. It's going to be on Apple's devices, it's going to be on Apple's laptops, it's going to be on-prem, at the same time Apple's cashed up and might end up being the second or third owner of some of these companies.","offset":1900,"duration":26},{"text":"Eric: Matt, the title of your missive that you just written, \"Pay to PrAI\" or \"Pay to PrAI\" P-R-A-I is actually a reference to the inevitability in your prediction of something called paper-token monetization. What does that mean, how does that relevant, explain what that's about?","offset":1926,"duration":19},{"text":"Matt: Well, the fundamental business model of Silicon Valley venture capitalists is to try and win markets by financing companies with astronomical amounts of money such that that money gets spent on marketing and subsidization of the product to such a scale that nobody can compete with these Silicon Valley invested companies or unicorns. And so total nuclear war is launched on a market, so you can think maybe Uber and free rides in China or whatever it may be or you know DoorDash delivering noodles to people in Indonesia or you know Grab or whatever whatever it may be.","offset":1945,"duration":35},{"text":"Matt: So what we have here in the AI space, the subsidization model is that you have a free product being GPT or what have you, and then you've got a 20 dollar a month product which I've said earlier probably costs them 20 dollars to serve, and a 200 dollar a month product which probably costs them 2000 dollars to serve. You just can't continue forever. At some point, so the so the question is going to be can we get the unit economics down to do inference to such a point that these models are profitable before these companies run out of funding?","offset":1980,"duration":30},{"text":"Matt: Now the problem is that as we've moved into for example software development which consumes a never-ending amount of tokens to write code because every company in the world is powered by software now, you know there's this huge token burn that's happening in these 200 dollar plans. And if you were to try and make some sort of reasonable software-like margin, like 80% etc., you would have to price these plans not at 200 dollars a month but maybe a thousand or two thousand dollars a month or higher.","offset":2010,"duration":30},{"text":"Matt: At some point the money is going to run out and I think they had a near-death experience in the last couple of weeks. Anyone who and I know you're constantly using GPT and Claude etc. and you probably noticed the same thing, you know in the last couple of weeks there seems to have been a bit of a panic from these companies where you know you log into your 200 dollar plan, you type a couple of queries and then you run out of credit. You've always known that these companies aren't making money on the inference because instead of saying put your credit card in and top up your credit, it puts you in the naughty corner for seven hours or longer.","offset":2040,"duration":31},{"text":"Matt: The inevitable destination for these subscription models which are basically massively subsidized Silicon Valley financed and increasingly debt-financed business models is that they're going to have to move to a per-token pricing. Now and that is going to cost a lot of money. I think there was some comments in the last couple of weeks on Reddit where someone who's on a 200 dollar plan ran out of credit pretty quickly, he had to get it done he had to get something done you know that night, and so he moved to the API pricing which is in the programming interface and that was costing 200 dollars an hour instead of 200 dollars a month.","offset":2071,"duration":34},{"text":"Matt: And he thought gee, I've just you know used a couple hours used 5, 600 dollars. The problem with that sort of pricing has several dimensions. The first is that already at 20 dollars a month for a plan which is 240 US dollars a year, that already prices the product out from over half the world's population. I mean the median global income in the world is about 2.5 thousand dollars a year so at 240 dollars a year you're already 10% of the pre-tax income for half the people on the planet, right? So you're already quite expensive.","offset":2105,"duration":33},{"text":"Matt: The second point problem here is that you know in these programming models which which realistically to make any sort of margin need to be priced in the thousands of dollars a month or maybe 10,000 dollars a month, you have a bit of a problem in the fact that you know these models do hallucinate. And when they do hallucinate and throw errors, they're very different from human. When you use hire a freelancer for example on my website freelancer.com, you know you put in some money, okay I'm going to pay you 200 dollars to build a website for me and you don't release that milestone until the job is done.","offset":2138,"duration":33},{"text":"Matt: And if the human can't figure out a problem, you know they'll they'll ask their friends, they'll try and find a more senior engineer for advice, they'll get on a forums and ask other people how to solve problems, they'll browse the internet, they'll they'll kind of hill-climb their way out of solving problems. And look, they may they may ultimately not get there and you might get frustrated with them and want to find another developer to do the job, but ultimately their failure modes are very different from AI. With with AI, sometimes when it hallucinates, it can do wildly crazy things.","offset":2171,"duration":28},{"text":"Matt: About three weeks ago, I had a problem with my with my VPN on my computer, I was using Claude to kind of help me through figuring out how to get it fixed. I'm a software developer by background, I've got electrical engineering degree from Stanford, you know I I do know how to program quite well, but I kind of veered into PowerShell commands in Windows 11 which I don't know very well and I was blindly pasting in Claude and it made me delete my entire networking stack.","offset":2199,"duration":26},{"text":"Matt: And so you have these very crazy failure modes with AI where you either go in loops or it goes away and thinking and and you know burns you know 10x the inference you know try you know these reasoning chains trying to figure out what's going on, or it just has these crazy suggestions and and it will look at you in the eye with the the eyes of a sociopath on a first date in some regards trying to you know gaslight you into thinking that its answer is is true when it's clearly not the case, it's just hallucinated something or rather.","offset":2225,"duration":32},{"text":"Matt: And the issue here is that in a paper-token pricing model, it really turns software development into a slot machine in that if the if ultimately you know you're writing your app and you you kind of need to get Claude to do something or rather, you're really pulling the slot machine handle, you don't know how much it's going to cost you by the time the tokens are all burned and you don't know if you're actually going to get a solution at the end of the day. And so, you know I guess only in Silicon Valley could they turn software development into degenerate gambling because that's that's kind of where you end up.","offset":2257,"duration":33},{"text":"Matt: And the frustrating thing I think will happen is when you're on the 200 dollar plan you've got a certain amount of capacity and maybe it tells you to time out or what have you, you kind of know, you're capped at 200 dollars, right? It's very frustrating what it runs out of credit you gotta find alternative ways potentially of doing things, but you kind of know what you're what you're up for. When you're pulling the handle under the paper-token model, it could be 50 dollars per spin, you may go in a circle, you may go in a circle 10 times, you know there's all these examples of people get over X of of radical crazy things that that that Claude does to your codebase.","offset":2290,"duration":36},{"text":"Matt: And I think people are going to get very very frustrated if they have to kind of put a coin in the machine, pull the handle every time and they get a non-deterministic outcome of whether they're moving forward in a hill-climbing sense to to their final solution and their final app or their final bit of software being developed or whether they're going in circles you know round and round and round round again. And I think people are going to get frustrated, they're going to go try and find open source models, they're going to try and find alternative ways to get things done and I and I think at that point, that's where the bubble starts to pop, it's really the problem.","offset":2326,"duration":40},{"text":"Matt: And while the hallucinations are reducing as part of you know each new generation in terms of the engineering of the infrastructure around the foundational models to reduce those hallucinations, what is actually happening is the token spend is going up exponentially because you're doing more and more complex things, so you have a much bigger surface area in which you could generate an error. So what I mean by that is, you know, while the probability of a failure pulling the pulling the handle on the slot machine is getting reduced with the you know the engineering from each subsequent generation of model, the number of handle pulls you need to make is is going up exponentially and so you've got a multiplicative effect in terms of potentially the impact of errors.","offset":2366,"duration":30},{"text":"Matt: I just think it's going to, the question that basically needs to be solved now with this 122 billion dollar fundraise is can you get the cost of compute way down to get this whole model profitable and will the market tolerate software development as a slot machine.","offset":2396,"duration":6},{"text":"Eric: A lot has been said already by lots of people about the incredible rate of progress and how quickly AI itself is getting smarter. What I don't think has been discussed enough and I'd like to get your comment on is the rate to which professionals are becoming dependent on it. I think more than you know this it's more addictive than cocaine. I remember our first interview on AI when ChatGPT had just come out and I remember thinking to myself, boy Matt's really into this stuff, to me it's a novelty but I don't think I'd ever pay 20 bucks a month for it. I mean it's just it passed a Turing test, big deal but I don't think I'd ever buy a subscription.","offset":2402,"duration":46},{"text":"Eric: I'll tell you Matt, in the last several weeks, there's been a lot of stress in my life because of this war and family that are affected by the war and waking up double digit percentages down on a percentage basis on my net worth because of something that happened in the market overnight. Okay look, I'm a big boy I've been through that stuff before, I've been through the 2008 crisis, it's not that big of a deal. But Claude 4.6 was going offline and the server wasn't available and I was freaking the F out. I couldn't handle it. I was losing, and don't you dare insult me by suggesting that I go back to ChatGPT 5.4. I don't drink Pabst Blue Ribbon and I don't do ChatGPT, okay? I mean I've gotten to the point where I can't live without Claude. This is this seems like a risk.","offset":2448,"duration":55},{"text":"Matt: When Claude went down, it's quite interesting actually because the first time it had a bit of an outage was when the data centers got blown up in in Dubai and you kind of have to wonder to yourself what potentially was being run in those data centers in the Middle East that caused the outage of Claude. And I do think those companies did have a bit of a near-death experience in the last couple of weeks. Anyone who and I know you're constantly using GPT and Claude etc. and you probably noticed the same thing, you know in the last couple of weeks there seems to have been a bit of a panic from these companies where you know Sam Altman killed Sora which was this hyped-up video modality model where you could generate you know clips or you know the whole point was you were supposed to be able to type in a prompt and get a movie out the other side.","offset":2503,"duration":31},{"text":"Matt: In fact Disney paid a billion dollars to OpenAI for use of the technology and only found out half an hour before a meeting that the whole thing was going to be canceled. At the same time Sam Altman killed instant check-out, he's working on some sort of erotic model as well which is a bit strange but I think it's probably one of the big markets is pornography and he thought maybe we could make some money there. He killed that as well and at the same time Claude had these big changes in terms of how they did the plans and they were giving out you know extra tokens in off-peak but in peak they'll kind of cutting you back etc. and then ultimately it seems that they've they've cut back a lot of lot of the token budget you get in these models and on the path to this sort of paper-PrAI paper-token sort of business model.","offset":2534,"duration":40},{"text":"Matt: So I do think they all had a bit of a near-death experience and that near-death experience obviously is what I was feeling or what you've been feeling when you kind of see these models you start using them and going, gee is my access going to start getting restricted, you know will I have to pay a lot more money, will I have to add a zero to my to my monthly subscription, what what's going on. And then of course you've got this financing round which is less cash and more infrastructure and perhaps it's a way to kind of help the company kind of limp towards IPO so there's liquidity event so the you know original investor can kind of make a bit of a return.","offset":2574,"duration":28},{"text":"Matt: It turns out that you know this whole, it's pretty funny that this whole AI compute space is predicated on 600 billion dollars a year of CapEx which is incredibly energy-intensive when at the same time you're bombing the you know an area where 48% of the world's energy is and you know you're relying on energy being cheap in order to have this AI AI boom work.","offset":2602,"duration":24},{"text":"Eric: Let's move on to private credit. There's a lot that's been said already as a lot of private credit funds are gating investors that this is AI driven or it's related to Claude Code specifically creating fears that software companies would no longer be profitable. And I have a hard time with this one because this sounds like the claim I remember hearing in the 1970s when supposedly the introduction of the Hewlett Packard electronic calculator was supposedly going to put every accountant out of business and create vast unemployment of bookkeepers and so on and so forth and it was the exact opposite. It created more productivity. It seems to me that Claude Code just gave the software industry the biggest productivity boosting tool that they've ever had, and that's the reason that private credit is blowing up? Is that really right? Am I missing something?","offset":2626,"duration":54},{"text":"Matt: Well, I mean there's a few things going on. First of all, the these funding rounds are getting too big for equity, so as we saw with 122 billion and all the infrastructure, the vendor financing in there. And so you've increasingly these companies are turning to debt, even Meta had to go and get 30 billion from Blue Owl not so long ago in order to fund data centers because it's [44:59]","offset":2680,"duration":20},{"text":"Host: ...not do it off the balance sheet anymore and the numbers are starting to get too big for equity raising, so they're borrowing the money. And not just are we seeing record equity rounds, we're seeing record debt rounds. That BlueOwl financing of Meta was the biggest private credit round ever.","offset":2700,"duration":25},{"text":"Host: The problem is that private credit in these portfolios has got SaaS businesses and one of the big pitches that these AI compute companies has is that SaaS is dead, which is kind of ironic when ChatGPT on a $20 a month subscription is a SaaS business.","offset":2725,"duration":22},{"text":"Host: So it's kind of funny that they're saying SaaS is dead when they actually are SaaS businesses themselves. But there's been some warnings that have come out around these private credit portfolios that pack in the AI debt as well as the SaaS debt, because AI is actively pitching the future of these SaaS companies will be eroded by the fact that AI is coming.","offset":2747,"duration":26},{"text":"Host: So it's causing some instability in the private debt markets. And of course, what else is causing instability is rising interest rates in an uncertain world and a war in Iran amongst other things.","offset":2773,"duration":18},{"text":"Host: Matt, speaking of data centers blowing up, let's talk about the Iran conflict, its connection to AI, and particularly in your latest missive, you express some concerns that there's a risk that potentially this Iran conflict kind of pulls the rug on the whole AI business model. What do you mean, what's going on?","offset":2791,"duration":29},{"text":"Matt Barrie: Well, this is where the Fifth Industrial Revolution meets the Islamic Revolution, right? Um, a lot of the financing for AI has come from the Middle East. And you can imagine now if you're Saudi Arabia or you're the UAE and you have a fiduciary duty to protect your nation and your citizens and your economy, are you going to be putting it into hyper-rounds of Sam Altman's highly inflated valuations, or will you spend it on defense, energy, rebuilding your civilian and industrial infrastructure and potentially going to war to fund an army?","offset":2820,"duration":45},{"text":"Matt Barrie: You know, it's quite problematic when you've got a country that sits right in the middle of, you know, 48 percent of the world's energy infrastructure, that controls a strait where 21 million barrels of oil goes through every day, that can fire $20,000 drones at scale into anything within a 2,000 kilometer range and migrate not just your data centers in the region, but potentially your energy infrastructure into the cloud, literally in a puff of smoke.","offset":2865,"duration":37},{"text":"Host: Matt, another theme that you have in your latest missive is that you've got to be pretty smart to really get the most out of AI. What do you mean by that and what are the consequences?","offset":2902,"duration":16},{"text":"Matt Barrie: When I look at, deep down, at kind of what what's happening in the space, I mean, despite you've got a conflation of few things happening right now. You've got the AI companies trying to justify these huge valuation rounds and they're doing that by saying they're going to take away a lot of the world's work. Then at the same time, you've got sort of mass layoffs happening in the market with Block today, with Oracle, I don't know if you saw overnight, but Oracle has announced 18 percent of their workforce has been cut, etc.","offset":2918,"duration":37},{"text":"Matt Barrie: And so you would not be surprised that the general market has kind of conflated these things and thinking that AI is taking people's jobs away. Now, I see AI instead as a tool. It's a very, very powerful tool. It's, you know, but it's a productivity tool, much like the world was, you know, when you went to work and there was no computer on your desk and then you went to work and there was a computer at your desk or you didn't have mobile phones and you have mobile phones or you didn't have the internet and then you have the internet. Yes, there is incredibly disruptive and transformative time and some jobs are lost, but just like pretty much all forms of technology, more jobs are created over time.","offset":2955,"duration":51},{"text":"Matt Barrie: And what I mean essentially by you've got to be smart to use AI is, you know, AI is a power tool and so is a chainsaw, right? You give a chainsaw to a carpenter and they can do, a skilled carpenter, and they can do amazing things. You give a chainsaw to a novice and you can cause all sorts of problems, right? And so what I am observing, both across my platform as well as within my engineering team, is the people who are benefiting most from AI are the ones that are highly skilled and intelligent and know how to use the AI.","offset":3006,"duration":43},{"text":"Matt Barrie: And they're seeing productivity gains which are astronomical. They're seeing, you know, double to triple their productivity and you can measure that in different ways in terms of what they're achieving. And then as you go down the skill level, you do, you know, it is a rising tide lifts all boats. So if you're an average copywriter, you can now be a good copywriter. If you're an average illustrator, you can be a good illustrator using these various tools. If you, I make a joke, if you're an average programmer, well, you certainly are a confident programmer now using these tools. But to really get the best out of them, the people who are highly skilled are the ones that are really, really driving the outcomes. And I see that for example with your work and what you do, you writing these missives and books and so forth. And so I think just like technology has over time created a bifurcation in society where you have the people who are skilled and can create technology and that's where all the wealth flows.","offset":3049,"duration":68},{"text":"Matt Barrie: And that's why you see these companies with huge valuations and, you know, the ultra-high net worths in the technology industry, and then you see a general deterioration at the lower end of society. I think this is going to drive even further to an extent. People who really, really know how to use AI well are going to capture incredible opportunities in all sorts of different market segments where they can control that customer interface.","offset":3117,"duration":30},{"text":"Host: Well, I definitely agree with you. I just finished a writing project, or I should say Claude and I just finished a writing project that was considerably bigger than writing my book Beyond Blockchain. It required a lot more research because Beyond Blockchain was just my own opinions. It was a lot to it. And Beyond Blockchain took me more than three months, this project took me less than two weeks. And it's just amazing how much you can accomplish, although you definitely, as you say, it takes some skill to learn how to manage context window exhaustion and recognize symptoms of it occurring and so forth. So I couldn't agree with you more.","offset":3147,"duration":51},{"text":"Host: It kind of scares me though, Matt, because I think one of the biggest problems that society faces in the mid-2020s is the K-shaped economy. The tendency that the rich get richer and the poor get poorer. It sounds to me like AI really is going to exacerbate that in the sense that the smartest people are going to really benefit in productivity from AI. They're going to be a whole lot smarter and more capable than they used to be. One guy will be able to do the job of 10 or 12 guys. But the 10 or 12 guys that weren't that bright and really didn't figure out how to recognize the symptoms of context window exhaustion in their LLM, I think it really does take their jobs. And it seems to me like this could become the basis for deeper division in society.","offset":3198,"duration":55},{"text":"Host: So, Matt, I want to ask you this, because as the CEO of Freelancer.com, and for any listeners who aren't familiar with Freelancer, it's basically a marketplace where people can hire independent workers, whether they be high-end expert consultants in their field who are the leaders of their field, or if it's just a guy who'll design a logo for you for five bucks. You can hire all those different people on Freelancer. Matt has a very unique perspective on AI because first of all, he's running a company that uses AI, so he leads an engineering team that's building AI-based solutions. But some of the people that his customers are hiring are AI experts that are helping companies to implement AI at a corporate level. And then some of the more mass freelancer, larger group of graphic designers and people that are making logos and so forth, are users of AI that are leveraging their logo design contests and all that. So Matt sees all these different dimensions of different people using AI in different ways, corporations and organizations adopting it, versus an individual guy in Indonesia who's just trying to make a buck as a graphic designer suddenly becoming much more productive and being able to work in different languages that he doesn't even speak. So Matt sees all these different dimensions. Matt, from that vantage point that you have, what would you say are the top three things that you've become aware of that the average person who can't see all that stuff probably wouldn't think of?","offset":3253,"duration":122},{"text":"Matt Barrie: Well, the amazing thing is we're going to see the ability for you to get things done that you could never possibly think of before, right? Rather than just getting a website built, you'd get a whole business built. The ability for, you know, I think we're going to enter a whole new world of explosive entrepreneurship where now you really just need to have an idea to start a company and the ability for you to be able to execute on that using both AI and also access to humans powered by AI will be unprecedented. You'll be able to do it at a cost that's cheaper than ever before. So we're going to enter, I think, into an explosion period of hyper-competition and, you know, thanks to the internet and the ability to distribute products or services over the internet at scale so quickly, if you've got a great idea, that great idea can take off and you can make a billion dollars faster than any time ever in the history before.","offset":3375,"duration":57},{"text":"Matt Barrie: So I think it is an incredible time. I certainly haven't seen as yet the complete replacement of someone in a job. I don't know, you know, if you ask around, does anyone know any graphic designers that completely lost their job? Where the dislocation will occur is where you've got highly paralyzable workflows where you've got thousands of people or hundreds of people doing the same job. So maybe in a call center, where there might be 10,000 people or 1,000 people in a call center doing the same workflow which is customer support, answering a phones, etc. With AI, you'll be able to take it from 1,000 people down to maybe 100 people. You know, if you've got 30 junior lawyers drafting legal agreements in a room, maybe you'll be able to take it down to 13 people in a room.","offset":3432,"duration":53},{"text":"Matt Barrie: But I don't see, because of the way AI works and goes in circles and the failure mode and the fact that as you burn more tokens you've got more chance, even though the unit rate of errors goes down, the fact you're burning all these extra tokens means that ultimately, you know, an error becomes more catastrophic in a way that a human never would make an error. What that means is that I think the ultimate combination is humans and AI. I think it's probably one of the greatest productivity tools known to man and I think it's going to open up a whole amazing golden age of building and creating businesses and hyper-competition.","offset":3485,"duration":46},{"text":"Host: Well, Matt, I can't thank you enough for a terrific interview. Before I let you go, you run Freelancer.com, a public company that trades under ticker symbol FLN on the Australian Stock Exchange. Tell people for who are not familiar with it what Freelancer does and how to follow your work. Your latest piece, again, it's linked in the research roundup email, it's published on Medium, it's called Pay to Pray. You write quite a bit of interesting stuff for people who want to follow your work and learn more about Freelancer.com, tell us about it.","offset":3531,"duration":49},{"text":"Matt Barrie: Well, we run the world's largest cloud workforce, so it's about 87 million people in that marketplace. We can do any job you can possibly think of from $10 jobs to $10 million jobs. You know, the mainstream jobs are things like build me a website or build me an app or, basically help me start a company or grow my company. The biggest things we run, we've got a moonshot innovation challenge program at the high end where we help all sorts of US government departments and enterprises around the world solve scientific and technological challenges. So, you know, give us your hardest scientific or technological challenge and we'll solve it or you don't have to pay the prize out. So the biggest thing we've got running right now is the seven and a half million US dollar gene editing challenge for the central nervous system of humans, which we're doing for the National Institute of Health and also working with NASA.","offset":3580,"duration":66},{"text":"Matt Barrie: Actually, ironically, when Artemis goes up in the next 24 hours into space, we worked with NASA to crowdsource the mascot from kids all around the world that's going up with the astronauts to basically inspire kids about space and so forth. If you want to get anything done, you come to our site, we can get it done, and no job is too small or too big or too complex and it ranges through to mechanical engineering or electronic design or whatever you need. And if you want to follow my writing on AI, there's a series of, obviously a podcast that we've done together on MacroVoices on AI, I think this is maybe the fifth or the sixth. And if you go to Medium or Substack you'll be able to find me and see my essays.","offset":3646,"duration":59},{"text":"Host: And if you just put Matt's name in, Matt Barrie, at the search bar at macrovoices.com, you'll see a list of all of the previous AI interviews that we've done right here on MacroVoices. Patrick Ceresna and I will be back as MacroVoices continues right here at macrovoices.com.","offset":3705,"duration":26},{"text":"Host: Eric, it was great to have Matt back on the show. Now Dr. Anas Alhajji is next on deck for a special second feature interview on the developing Iran conflict and what it means for the oil markets. Then Eric and I will be back for our usual postgame chart deck and trader of the week. Since this extra coverage format seems to be a hit with listeners, we'll do our best to continue it for as long as the situation in the Middle East warrants. Now let's go right to Eric's interview with Anas.","offset":3731,"duration":63},{"text":"Host: Joining me now is Energy Outlook Advisors founder and managing partner Dr. Anas Alhajji. Anas, it's been three weeks since we had you on the program for the first Iran war update. It's been one month since this conflict started. President Trump just moments before we began recording this segment gave an address to the American people. Let's start with the big picture update since this began. How has everything evolved, how have your views evolved since we had you on three weeks ago, and what did President Trump need to achieve in this address and did he achieve that?","offset":3794,"duration":43},{"text":"Dr. Anas Alhajji: Well generally speaking, we got to frame what has been going on and President Trump basically did not frame it. So, either this is about Iran and its nuclear and he tried to make it that way, or Iran part of a bigger picture and the audience basically can choose one of those two. So either it is about Iran and its nuclear program and the outcome of that basically and its impact on the market are completely different from the idea that Iran is part of a big picture. If you look at trade wars, tariffs, sanctions, Venezuela, Panama, Red Sea, China, Greenland, etc., so is Iran and this war is part of it or Iran is completely separate. The president today basically tried to make it about Iran, but all of a sudden he deviated from that and he started talking about we don't need the Middle East, we don't need oil from there, buy oil from me. And this makes the second option basically kind of more credible in this case.","offset":3837,"duration":70},{"text":"Dr. Anas Alhajji: Anyway, we'll go back to that later on. And the other issue is, who closed the Hormuz Strait? You have only two answers. It's either the United States through the insurance companies or Iran. And it's up to you, the audience, basically to believe one of them. There are evidence on both sides. But one of the ironies here is that when we talk about the details of who closed the Hormuz Strait and we say Iran has no power to close it, then people say, well this is a conspiracy theory. It turns out it's a bigger conspiracy theory to say Iran closed the strait. And we heard the president today saying that Iran's navy is gone. Literally said that. And he said they have no radars, he talked about the total devastation of course their leadership is gone, all that stuff. So to believe that we have all these attacks and the aftermath of this devastation that happened to Iran.","offset":3907,"duration":64},{"text":"Dr. Anas Alhajji: We have 28 countries are in charge of protecting the Gulf and the Hormuz Strait through an organization that is based in Bahrain. You have the US navy, you have the Indian navy, you have the British navy, you have the French navy, you have the Saudi navy, you have all the other countries' navies in the area. And then after all this devastation Iran still control the Hormuz Strait? This goes against everything that President Trump said today. So the story does not match in this case. So to sum up, either you look at this war as it's either Iran and nuclear or it is part of a bigger picture of the changes going in the world and then you look at Hormuz Strait and say well it's either the United States and the insurance companies closed it and the main beneficiary of this is the United States and we heard President Trump talking about it today. Or Iran closed it but that does not make any sense and that is a bigger conspiracy theory because how was Iran able to do that after what we heard from President Trump today and the existence of all the other navies.","offset":3971,"duration":64},{"text":"Dr. Anas Alhajji: Unfortunately President Trump today failed to deliver to the nation the message why the war is still going. Many people basically expected that he will announce some sort of an end to the war. We told our clients couple of weeks ago that all the indications point to a long war, and today we got the confirmation. This is not going to end soon. And if it's not going to end soon, there is another question mark about what President Trump said. If everything is destroyed in Iran, then why is this war continuing? What is left to be destroyed? So the impression I got out of this speech is that the people around President Trump are not telling him the truth and he is living in his own ivory tower without looking at what's going on in reality. And we have countries around the world that are literally having blackouts, country do not have propane to cook, countries basically are struggling to get petroleum products, etc. Many countries are worried about food supplies and the president did not even mention it today. This is a global crisis. This is the largest global crisis we have in our lifetime. And the president even did not talk about it and he did not explain to the American people why this war is still going until now. If everything is destroyed why the war is not ending?","offset":4035,"duration":93},{"text":"Host: Anas, who is actually in charge in Iran and calling the shots? Because we've seen so much conflicting news in the last few days. President Trump before this speech had said very clearly in his Truth Social posts that what the speech was likely to be about is that Iran had requested a ceasefire and that Trump was likely to agree to that ceasefire. Now preempt, apparently trying to preempt this speech, the guy who is still technically the president of Iran, although the president is not really the head of state who's in charge in Iran, it's really the Supreme Leader who calls the shots. But this guy who is the president issued a letter to the American people in which he says look we don't want any ceasefire, we would not agree to a ceasefire, we want the war to be completely over and we won't accept any end until we have a promise of no further attacks.","offset":4128,"duration":59},{"text":"Host: So it seems like if nothing else that whether that was a true statement that's reflecting the Iranian government or just the guy who's not really in power anymore expressing his view isn't clear, but it seems like it did have the effect of taking the ceasefire discussion out of President Trump's speech. Meanwhile, we're told that who's really in charge of Iran is the Supreme Leader, but that would now be the killed Supreme Leader Ayatollah Khamenei's son. Nobody's seen him since he supposedly took power. Nobody's heard from him. We're told that he's still alive, but we don't know that for sure. Who's calling the shots in Iran and how should we interpret the various messages that we're hearing out of the media?","offset":4187,"duration":53},{"text":"Dr. Anas Alhajji: The reason why we call it the Iranian regime while in other places we call it government, but in Iran we call it a regime, because we have the official government and then we have the support coming from various militias and groups of that government. If you sum them up we call that a regime. So the Iranian revolutionary guard are not part of the government, but once you put them together they become a regime. And what we've seen historically is that there are of course differences between the government itself, the official government where you have prime minister and you have president and you have a foreign minister, they are more diplomatic. While most of the military actions and the attacks and everything else comes from the revolutionary guards who are not part of the government. So historically we've seen that division.","offset":4240,"duration":56},{"text":"Dr. Anas Alhajji: But even within the revolutionary guard they are not really one unit. And what happened is that after the killing of most of the leadership including Ayatollah Khamenei who the religious leader, they decided to at least for a short period of time to work independently. So they told them okay we have no leadership at this stage so every group you are on your own. So we've seen various groups basically acting on their own, attacking on their own, based on their location, based on their beliefs, based on whatever their leaders basically believe about other countries. So we've seen attacks on the Gulf nations, we've seen more attack on some relative to the others, etc. And then the foreign minister came in and said we know nothing about it. Probably he's right because there was a complete disintegration of the system at least for that period of time.","offset":4296,"duration":65},{"text":"Dr. Anas Alhajji: At this stage, it's very clear that the revolutionary guard basically took over the government. So now we can say that unlike in the past where we have a government and then we have the revolutionary guard and the others, now the revolutionary guard basically literally took over the government, so they are one unit right now. And the whatever kind of nice messages we get, we get from people who have no actual power on the ground. And so everything you hear about the Iranian parliament, this is just a joke. This has no impact. So when they say oh we are going to install a tollbooth for example and we got to charge $2 million per ship, etc., this is coming from people who have no power on the ground at all. Unfortunately the western media basically took them seriously and spread the misinformation all over the world. But they have no power.","offset":4361,"duration":62},{"text":"Dr. Anas Alhajji: And speaking about Iran's ability to charge for it, under international law there is no way that they can charge. There is no way they can charge. And whatever they are doing if they are getting any money from anyone, this is an extortion. And the funny part here is if there are governments that are literally cooperating with Iran and paying them so their ships can pass, so we are talking here about Pakistan, we are talking about India, we're talking about Malaysia and probably others, why President Trump is not mad at them? Because they are cooperating with those terrorist and the regime that is killing people who killed 40,000 people of its own people. Why? Because if they are paying them money then they are supporting the regime. Why we did not hear a word about that? Simply because probably it does not exist in the first place.","offset":4423,"duration":59},{"text":"Host: Anas, I want to follow up on a really important point that you made in your last interview three weeks ago. What you explained is that most people assume that Israel has nuclear weapons that they could use against Iran but Iran doesn't have a nuclear weapon that they could use in retaliation. You explained that Iran really does have the equivalent of a nuclear weapon in terms of the consequence of using it, which is that Iran could target the desalination facilities of both Israel and other allied Gulf countries which unlike Iran itself which only gets 3 percent of its drinking water from desalination, Israel and other countries in the region are extremely dependent on desalination. So if Iran attacks their desalination they are forcing starvation and just horrible, horrible humanitarian outcomes. They don't have that same vulnerability with their own desalination plants because they only get 3 percent of their own water from desalination. And so you made the argument that Iran could potentially if they really wanted to use the proverbial nuclear option they could escalate to targeting desalination facilities.","offset":4482,"duration":79},{"text":"Host: Now about a week after you made that prediction, Iran made a formal announcement saying if our energy, our civilian energy infrastructure is targeted, we will respond by targeting the enemy's desalination facilities which could bring about that horrific humanitarian outcome that you described. So it seems like this is escalating and escalating quickly. Do I have that right and how do you see this playing out? How serious of a risk is this?","offset":4561,"duration":35},{"text":"Dr. Anas Alhajji: Yes, you are absolutely right. And one of the issues that we have to really realize is when we say this is a historic event, it's not only in term of impact. It is historic in various ways. One of them is there are no red lines. There are no, no one basically has any red lines, the United States, Israel and the Iranians. No red lines. And if you look at the attacks of the other countries in the Gulf etc. there were no red lines. So on every part on the parts of everyone there are no red lines and that make it more, in a sense, another reason to be historic. But one of the other reasons why it is historic because of the nonsense, there are a lot of nonsense going on that we cannot even explain at this stage. We don't know what's going on. For example, Iran is hitting the GCC countries, that's the six countries in the Gulf and some targets in Iraq.","offset":4596,"duration":57},{"text":"Dr. Anas Alhajji: They are hitting them because they said oh you are cooperating with the Americans and the Israelis and therefore we got to hit you. Well if that's the logic then we need to explain this. The Israeli planes that are hitting the targets in Iran and the Israeli rockets basically that are using the fuel, that fuel is some of it is coming from Azerbaijan and Azerbaijan is next to Iran. It's a neighbor. And Chevron is the largest oil company operating there in an oil field. So it is an American company. We saw Iran hitting for example a Ruwais refinery in the UAE. Ruwais refinery is a joint venture between ADNOC and European companies, so there are no American presence there and there are no military bases there. Yet they attacked it.","offset":4653,"duration":55},{"text":"Dr. Anas Alhajji: But why they are not attacking Azerbaijan who is literally giving the oil to Israel to bomb targets in Iran? Same thing for Kazakhstan, the same thing for Turkey because that oil coming from Azerbaijan basically is coming through Turkey. People saying well Turkey is a NATO member. Well I can tell you we know that Trump does not care about NATO and Trump does not care about Turkey if Iran attacks Turkey. But there are, all this confusion and all those issues that do not make sense at all. For example, attacking Salalah oil depots in Oman. Salalah is like, if you are in Iran Salalah is at the other side of the world. And it's an oil depot. Why you are hitting it? There are no Americans there, there are no Israelis there, there's no military base there. And how come literally a drone will go all the way across the Emirates, across Saudi Arabia, across the empty quarter, go all the way to the end of Oman to the other side where Yemen is and hit the target precisely?","offset":4708,"duration":67},{"text":"Dr. Anas Alhajji: So there are too many questions, there are too many things that do not make, do not make sense. For example, hitting this refinery. If Hormuz Strait is closed and the refinery cannot export, why you are wasting ammunition, why you are wasting drones or rockets to hit it while the refinery basically is useless? Why hitting a tanker like the Kuwaiti tanker yesterday that's been in the same place for a month? It's 200 mile away from Hormuz Strait. It cannot go away, it cannot go through the Hormuz Strait, is not even moving. Why hitting it while you know it's not going to go anywhere? And was it a mistake, was it, was the objective something else? What, whatever the case is there are too many questions that have no, no answers. But the bottom line here is the Hormuz Strait is still closed and that is a big failure for the US policy in the region regardless of what Trump claimed earlier in the speech.","offset":4775,"duration":69},{"text":"Dr. Anas Alhajji: The fact that the Hormuz Strait is closed, even at this moment, regardless of who closed it, is a failure of US policy. And there are strange things again when we talk about historic event, there are some very strange things. I'm going to tell you some. For example, if we go back to the national security strategy, it was released in November about four months before the war. So I'm going to read this to you from that strategy. So I'm reading right now. \"America will always have core interest in ensuring that Gulf energy supplies do not fall into the hands of an outright enemy. That the strait of Hormuz remain open, that the Red Sea remain navigable, that the region not be an incubator or exporter of terror against American interest or the American homeland, and that Israel remain secure.\"","offset":4844,"duration":62},{"text":"Dr. Anas Alhajji: Let's look at this one because this is kind of really strange statement. President Trump today said we don't need the Hormuz Strait, we don't need the Gulf, we don't need any of that. The strategy said we don't want it to fall into enemies' hand. And he did not say that today. This was one of the biggest failures of the speech. He should have said that. But here is the strangest statement in the strategy. Of course the strategy is really conclusions of a larger document that remains secret. We don't know what's in it. And therefore this, this paragraph, several paragraphs that been omitted. And here is why I'm saying this. The United States historically if you look at various strategies over the last 50 years, always talked about freedom of navigation in those waterways or the choke points. Notice the following.","offset":4906,"duration":54},{"text":"Dr. Anas Alhajji: This is the first time we are, we see a document like this, four months before the closure of Hormuz Strait, saying \"The Strait of Hormuz remain open.\" It never been closed. This statement makes sense if the Hormuz Strait was closed just once in history. So whoever wrote that statement there they must have something before this paragraph, \"open.\" If it wasn't closed in history, why you are using this statement, \"remain open\"? And the other thing is you are talking about Hormuz Strait, why you are tying Israel to it? You look at what we have in actual life, we have Israel basically attacking Iran right now and the Hormuz Strait basically is part of it. But the question here is if Anas Alhajji wrote in June and July, that months away, months before the war, months before the closure of Hormuz Strait.","offset":4960,"duration":61},{"text":"Dr. Anas Alhajji: And people who they can go to our daily energy report and they can go to our newsletter and they can see it. I wrote the 12-day war. In June Israel attacked Iran. China had no problem. Everyone was expecting Israel to attack Iran for the last 20 years and finally they did. But once the Trump administration started attacking Iran, that changed everything. And China was ahead, they knew in advance what's going on. So China basically stopped importing LNG from the United States, stopped importing oil from the United States, they were ahead on Venezuela before the blockade, they were ahead on Venezuela before the death of Maduro, etc. But they been and if you go back to the previous shows we had probably the last three shows or four, we've been talking about how China was building those massive inventories, oil inventories and everything else, in preparation for either war, sanctions or a major interruption.","offset":5021,"duration":62},{"text":"Dr. Anas Alhajji: Now we know. China knew. And China one of the least impacted countries by the closure of the Hormuz Strait right now at least in the short run. Once we look at those events and look at the 12-day war, what I've written was the China got the message out of the stories that been published in major news media outlets and very prestigious outlets. We've seen a number of stories talking about Iran closing the Hormuz Strait. Again we are talking about June. And if you look at those stories you will find something kind of very strange about them because all of them have the same talking point, some of them in the same sequence. That means there is a public relation company basically was directing that. Why they were doing it? So what I wrote at that time was China got the message and the message was the Hormuz Strait will be closed, but it's not Iran who is going to close the Hormuz Strait, it is the United States.","offset":5083,"duration":65},{"text":"Dr. Anas Alhajji: Again this is written in June and July. So we have the November document after that talking about the keeping the strait open and the strait never been closed. And then in June and July we were talking about the United States basically closing the Hormuz Strait. And then we have the insurance fiasco that we've seen until now. I know that many people were pushing against this, this idea, calling it a conspiracy theory etc. and they tried really hard to debunk this idea. Here is the issue that they need really to answer. The issue is this. Even if you send the navy to escort ships out of the Hormuz, ships are not going to move without insurance. If the insurance remains non-existent or extremely expensive, ships are not going to go along with the navy. Because shippers are going to tell Trump or Modi or anyone else who wants to send those navy vessels, telling them look, if I go with you and I get attacked and I lose my ship and I lose everything on it, will you compensate me? And Trump is going to tell them no, Modi is going to tell them no, I'm just providing a service for you you should pay me for it I don't have to compensate.","offset":5148,"duration":73},{"text":"Dr. Anas Alhajji: They are not going to go. They need that insurance to exist and to be cheap enough for them to move. So any way you look at it you say it's conspiracy theory or not it doesn't matter. They need that insurance. So it is an insurance story anyway you look at it. On the other side those who are claiming that Iran closed the Hormuz Strait again Trump told us today that Iran has no navy, has no power, Iran, we heard the whole talk. So either someone is lying to President Trump or Iran has no power.","offset":5221,"duration":39},{"text":"Host: Anas, there's one more nuclear option that we need to talk about which is so far in human history, no military force has ever intentionally targeted an operating nuclear reactor. In other words the horror scenario, the terrorism scenario of intentionally dropping a bunker buster bomb on top of an operating nuclear reactor to turn it into a dirty bomb of sorts. Now one of the things that has already occurred, and by the way article 56 of the Geneva Convention very clearly prohibits the intentional targeting of any nuclear electrical generation station. You cannot target nuclear electrical generation stations by international law. Except either the United States or Israel, I'm not sure who, has already made at least three attacks, air strikes on the Bushehr nuclear power plant which is Iran's one operating nuclear power plant.","offset":5260,"duration":63},{"text":"Host: Now those were not targeting the reactor. If they had intended to blow up the reactor and breach its containment they would have succeeded, so they weren't trying to do that. They were probably trying to take out the infrastructure and prevent it from generating electricity and supplying it to the grid. But it does seem that they're already violating the Geneva Conventions by targeting a nuclear power plant. Where is this headed? I'm just really concerned about the escalation that could occur from here.","offset":5323,"duration":33},{"text":"Dr. Anas Alhajji: Again this is a historic event for several reasons and one of the reasons why because there are no red lines. And what you described is a red line that's been crossed and is going to be crossed again and again and as a result Iran is going to cross this red line on the other side. Because as you know they already listed the four reactors in the UAE as a target, the stations like you said probably not the reactors because they need kind of special bomb busters or others etc. But they literally put that as a target. So there are no red lines and with a war with no red lines everything is possible.","offset":5356,"duration":42},{"text":"Dr. Anas Alhajji: The issue that I experienced firsthand was when I woke up in the morning here in Dallas and I got flood of messages and emails, people scared to death from oh what if Bushehr basically explodes and would we get nuclear and literally some high net worth individuals basically sent me messages and said should I put my family in a car and leave to Oman or any other country. So people basically being panic and that panic alone could cause massive problem because if you are talking about millions of people taking the highways, the rumor on its own is enough to cause problems let alone if it, if it becomes reality.","offset":5398,"duration":48},{"text":"Host: Well as you said Anas, Iran has announced that if their civilian power generation infrastructure is targeted, they will respond number one by targeting the desalination facilities of neighboring countries which you've described as a nuclear-like option because of its consequences. Number two that they will target the United Arab Emirates operating nuclear power station at Barakah, or the Barakah nuclear power station which is outside of Abu Dhabi. They've already said that will be a target. And then in tonight's, this is Wednesday night that we're recording, in tonight's address from President Trump, he said very soon and possibly simultaneously that the United States might target all of Iran's civilian power generation stations. So it sounds like the event that Iran said they would respond to by targeting both desalination and nuclear power plants is one that President Trump just signaled his intention to escalate to. This is a very scary moment. This feels like, you know, a replay of the Cuban Missile Crisis except this time we actually know about it. Am I exaggerating to say it's that big of a deal?","offset":5446,"duration":72},{"text":"Dr. Anas Alhajji: No, but I think we should be very aware of the fact that today after Trump speech, I am completely convinced that the people around him are not telling him the right picture. The way he described things are far away from reality. Let me give you another example on how far away from trade reality he said drill baby drill. Okay, drilling activities in the United States been down since he came to office. US production been declining in recent months. So he is completely out of reality and I am afraid that the people around him are not telling him the truth. Before this speech oil prices were down. Right now after the speech oil prices are 5 percent higher and they are going up. So the message, the main message of the speech basically is that this is a long war and this is going to continue and the market is pricing it.","offset":5518,"duration":57},{"text":"Dr. Anas Alhajji: And I think by tomorrow morning probably many people who were counting on probably it will be a matter of days is going to change their mind. And that will impact of course the markets whether you talk about oil gas LNG or anything else.","offset":5575,"duration":14},{"text":"Host: Anas let's move on now to what everyone's waiting for, which is how do we bring this all together in terms of the outlook for oil prices, LNG, energy markets generally. If the US is basically from what President Trump said very directly in tonight's public address, he said the US will probably walk away from the situation in the Hormuz Strait, leave it to other countries that depend on it. It sounds again as you suggested that maybe President Trump isn't getting the full story from the people around him because of course oil prices are set globally. If the Hormuz Strait is not reopened, energy prices are going to stay high for everyone, including US voters through the midterm elections. So it seems like the story doesn't add up.","offset":5589,"duration":55},{"text":"Host: But it does seem like the president intends to walk away from the situation in the Hormuz Strait once they've finished their military operations against Iran and it's unspecified exactly what that is, but the one thing he did say that was a specific indication of intentions was to target potentially simultaneously all of Iran's civilian energy production capabilities, exactly the thing that Iran has said if it happens is what's going to cause them to target desalination and nuclear power plants. What does this mean for energy prices and what does this mean for global energy markets more broadly?","offset":5644,"duration":36},{"text":"Dr. Anas Alhajji: When President Trump is talking about others basically coming and protecting the Gulf and opening the strait, he means only the people he know and he is talking about European leaders. He's not talking about China. He's not talking about the rest of Asia. So let's be clear about that. China will be happy to bring its navy and and have control of the strait. This will never happen and the United States will...","offset":5680,"duration":25},{"text":"Host: The audio cuts there.","offset":5705,"duration":2395},{"text":"...or sponsors. MacroVoices, its producers, sponsors, and hosts Eric Townsend and Patrick Ceresna shall not be liable for losses resulting from investment decisions based on information or viewpoints presented on MacroVoices.","offset":8100,"duration":15},{"text":"MacroVoices is made possible by sponsorship from bigpicturetrading.com and by funding from Fourth Turning Capital Management LLC. For more information, visit macrovoices.com.","offset":8115,"duration":15},{"text":"[Intro Music]","offset":8130,"duration":15},{"text":"[Intro Music continues]","offset":8145,"duration":15},{"text":"[Intro Music fades out]","offset":8160,"duration":15}],"logs":[{"elapsed":"0.0","message":"Downloading audio from YouTube...","detail":null},{"elapsed":"0.0","message":"Trying download with browser cookies (ad-free)...","detail":null},{"elapsed":"2.8","message":"⚠ Cookie download failed: WARNING: [youtube] [jsc] Error solving 2 challenge requests using \"deno\" provider: Error running deno process (returncode: 1): \u001b[0m\u001b[1m\u001b[31merror\u001b[0m: Uncaught (in promise) TypeError: Cannot read prop","detail":null},{"elapsed":"2.8","message":"Retrying without cookies...","detail":null},{"elapsed":"68.0","message":"⚠ Downloaded without cookies — audio may contain ads","detail":null},{"elapsed":"68.0","message":"Audio downloaded (74.9 MB) in 68.0s","detail":"File size: 74.9 MB"},{"elapsed":"68.0","message":"Video title: MacroVoices #526 Matt Barrie: Pay To PrAI","detail":null},{"elapsed":"68.1","message":"Audio duration: 2:15:41 (135.7 min)","detail":null},{"elapsed":"68.1","message":"Large audio (135.7 min) — will use chunked transcription with gemini-3-flash-preview","detail":null},{"elapsed":"68.1","message":"Skipping full-file attempt — using chunked transcription for 135.7 min audio","detail":null},{"elapsed":"69.3","message":"Split audio into 4 chunks for transcription","detail":null},{"elapsed":"69.3","message":"Transcribing chunk 1/4 (starts at 0:00)...","detail":null},{"elapsed":"69.3","message":"Uploading audio to Gemini File API...","detail":null},{"elapsed":"73.0","message":"Audio uploaded in 3.7s","detail":"File ref: files/4lxpyom0ebzz"},{"elapsed":"73.0","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"133.7","message":"Chunk 1: 75 segments, last timestamp 44:40","detail":null},{"elapsed":"133.7","message":"Transcribing chunk 2/4 (starts at 45:00)...","detail":null},{"elapsed":"133.7","message":"Uploading audio (offset 45:00) to Gemini File API...","detail":null},{"elapsed":"136.9","message":"Audio uploaded in 3.2s","detail":"File ref: files/a0pg2gieccn7"},{"elapsed":"136.9","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"188.0","message":"Chunk 2: 59 segments, last timestamp 1:35:05","detail":null},{"elapsed":"188.0","message":"Transcribing chunk 3/4 (starts at 1:30:00)...","detail":null},{"elapsed":"188.0","message":"Uploading audio (offset 1:30:00) to Gemini File API...","detail":null},{"elapsed":"192.8","message":"Audio uploaded in 4.8s","detail":"File ref: files/n381uljlnyfr"},{"elapsed":"192.8","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"245.2","message":"⚠ Empty response (attempt 1/3) — finishReason: RECITATION, blockReason: none","detail":null},{"elapsed":"245.2","message":"Waiting 10s before retry...","detail":null},{"elapsed":"307.9","message":"⚠ Empty response (attempt 2/3) — finishReason: RECITATION, blockReason: none","detail":null},{"elapsed":"307.9","message":"Waiting 20s before retry...","detail":null},{"elapsed":"375.5","message":"⚠ Empty response (attempt 3/3) — finishReason: RECITATION, blockReason: none","detail":null},{"elapsed":"376.0","message":"⚠ Chunk 3 returned empty response — skipping","detail":null},{"elapsed":"376.0","message":"Transcribing chunk 4/4 (starts at 2:15:00)...","detail":null},{"elapsed":"376.0","message":"Uploading audio (offset 2:15:00) to Gemini File API...","detail":null},{"elapsed":"377.4","message":"Audio uploaded in 1.4s","detail":"File ref: files/f5diboye4trt"},{"elapsed":"377.4","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"380.8","message":"Chunk 4: 5 segments, last timestamp 2:16:00","detail":null},{"elapsed":"380.8","message":"Chunked transcription complete: 139 total segments","detail":null},{"elapsed":"380.8","message":"Total cost: 204,608 in / 21,281 out — cost: $0.1661","detail":null},{"elapsed":"380.8","message":"Total transcription time: 312.7s — 139 segments","detail":null},{"elapsed":"380.8","message":"Analyzing topics across 139 segments with gemini-3.1-pro-preview...","detail":null},{"elapsed":"435.0","message":"Topic analysis complete in 54.2s — found 19 topics","detail":null},{"elapsed":"435.0","message":"Analysis tokens: 22,053 in / 1,560 out / 5,828 thinking — cost: $0.1328","detail":null},{"elapsed":"435.0","message":"Pipeline finished in 435.0s — total cost: $0.2989 (255,330 tokens)","detail":null}]} \ No newline at end of file diff --git a/history/1775477439435-HMTrd9Hn3e8.json b/history/1775477439435-HMTrd9Hn3e8.json new file mode 100644 index 0000000..be7ba8d --- /dev/null +++ b/history/1775477439435-HMTrd9Hn3e8.json @@ -0,0 +1 @@ +{"id":"1775477439435-HMTrd9Hn3e8","videoId":"HMTrd9Hn3e8","url":"https://www.youtube.com/watch?v=HMTrd9Hn3e8","title":"OpenAI Kills Sora & Hits $100M ARR on Ads | Oura Going Public & Whoop Raises at $10BN","type":"youtube","topicCount":16,"segmentCount":235,"createdAt":"2026-04-06T12:10:39.435Z","uploadDate":"20260402","chunks":[{"title":"Introduction & Anthropic's Record February","summary":"The host kicks off the episode and highlights Anthropic's unbelievable $6 billion revenue month in February.","entries":[{"text":"Host: So, we start with Anthropic’s monster week. We may be at the stage where we throw the humans under the bus, not the AI anymore, which I think at some level is pretty terrifying. We move to OpenAI killing Sora. I think shooting in the head is even more significant. A big part of the whole strategic direction of the company was flawed. Agreed. You’re saying the economists, the accountants have wandered into the room and they said, \"We have a scarce resource here, let’s optimize it, let’s devote this compute to the people who can pay the most for it.\" And then we finish on the man with the biggest balls in tech, Masa. You haven’t lived until you’ve seen an 85% decline in an index. This is one where it’s just back-asswards. I don’t believe there’s right or wrong in money, there’s just money. I just don’t think raising at 5 or 8 billion when you’re at 80 million or 100 million of suspect ARR is the most exciting accomplishment in the world. But let me be direct: get the fuck over it. You should conform your company around your customers and your model, not your VCs. Being mean to a billionaire is actually a feature. Ready to go?","offset":0,"duration":65},{"text":"Host: Boys, welcome back. It is this week in Anthropic, otherwise known as the SaaSstoberfest, which has been renamed. Uh, I want to start with, you guessed it, Anthropic. Unbelievable 28-day month of February where they did 6 billion in revenue, which was more than Databricks has done in their entire lifetime.","offset":65,"duration":25}],"startTime":0},{"title":"Anthropic's Claude Mythos Leak & Autonomous Agents","summary":"The hosts discuss the inadvertent leak of Anthropic's Claude Mythos model. They reflect on the irony of a security model leaking and predict that such leaks will become commonplace in the era of autonomous AI agents.","entries":[{"text":"Host: Do you know what I think was the most interesting news out of Anthropic this week? It was actually the—the accidental leak of Claude Mythos, essentially 3,000 unpublished assets leaked. Uh, it’s a 10 trillion parameter model, apparently, that is this next-level step change in capabilities that they’re not releasing because of how powerful it is. This is by far the most interesting to me. Jason, how did you think about this news?","offset":90,"duration":29},{"text":"Jason: Well, look, obviously it’s embarrassing, right? To—to Anthropic to—to leak it. Uh, I actually just think we’re going to see more and more of this accelerate. Uh, the faster we vibe code, the faster we ship, the more corners we cut in general on application-level security. It happens. I mean, so many folks are accidentally uploading code to insecure GitHubs, to—to databases, to Supabases that are by default open.","offset":119,"duration":34},{"text":"Jason: So this is—this is accelerating. Uh, our data which is just open on the internet. And—and you could say, \"God, it shouldn’t happen at the Anthropic level,\" and I’m sure someone will get—will get scolded, right? I’m sure it will. But overall, this is accelerating, and it’s going to accelerate even more as we let our AI agents make decisions. Our agents are going to decide where to put code, they’re going to decide what level of security to use, and this is going to become happenstance.","offset":153,"duration":27},{"text":"Jason: And, you know, it’s funny, I mean, uh, people are like, \"Oh, how could Anthropic have a new, uh, security agent and have this happen at the same time?\" I think they—they—I think it makes perfect sense. The Anthropic AI security agents, which are basically used in Replit, are very, very good, and it also makes sense as we rush, we’re going to leak source code, data, PII, right? It was—I don’t know whether it’s happened, it was reported today all of Mercure’s data leaked. It’s being held hostage, all of it, every single interview, every single piece of PII, every single piece of humans.","offset":180,"duration":43},{"text":"Jason: And so, uh, you know, we used to mock these. I think it’s going to start happening daily and weekly in the agentic era, and it doesn’t excuse it, but—but it’s—uh—it’s a reality. Agents—agents are goal-seeking and agents are going to make—not only are they going to make the same mistake as humans, they’re going to work a thousand times faster. So even if they make the mistakes 10% as often, Rory, help me with the math, if they do a thousand times more productive, they’re still going to make a hundred times more mistakes. So we’re going to see it everywhere.","offset":223,"duration":34},{"text":"Rory: Again, just for perspective, because there’s two things going on here: Anthropic—some data leak from Anthropic about their new model Mythos, which of itself is meant to be amazingly powerful in dealing with cybersecurity, and there was a whole consequence that we’ll talk about in a second in terms of how that impacted cybersecurity stocks. But as Jason pointed out, the level of irony here is acute because it was an inadvertent leak. So you had the situation where a model that’s meant to be amazing for cybersecurity actually leaks via cybersecurity leak. So that kind—so we’re toggling between the two.","offset":257,"duration":39},{"text":"Rory: On the cybersecurity leak, it was noteworthy that Anthropic, quote-unquote, \"blamed human error,\" right? We may be at the stage where we throw the humans under the bus, not the AI anymore, which I think at some level is pretty terrifying. But—and you know exactly what happened. You see this, I mean, uh, down in the weeds. You often see this where, you know, you’re about to do a big announcement, you have your content management system, you stage all the assets, you know, be it the Fed press release. In the UK, it happened on the budget, if you remember, Harry. The budget—you have the press release ready to hit play the minute the budget is ended and someone inadvertently forgets and puts it on the public site in advance. It’s the same thing here. So it probably was a human error. There was a whole bunch of content ready for, I don’t know, pick a date though, March the—May 15th announcement of Mythos, they forget to secure it correctly and out it goes.","offset":296,"duration":58},{"text":"Rory: So—so that’s the first thing, right? So that’s kind of—that’s the embarrassing part of it. And then the interesting part of it, and you really do have to do this without sniggering, despite the fact that it all leaked, you also have to separately talk about the fact there’s some big claims on Mythos, right? At—at Anthropic were making via, again, via this leaked memo. Reminder, no one else has seen it, uh, the—the actual model—um—at least not publicly available, obviously some people have seen it, but not publicly available. And even I was trying to get copies of the leaked memo. There’s just a few screenshots at this stage; it’s hard to track it down, at least quickly anyway.","offset":354,"duration":42},{"text":"Rory: But the statement is: it’s way more powerful. Second thing is it’s going to be way more expensive for them to serve, and therefore it’s going to be way more expensive for customers to buy. And then the third thing is a particular focus on cybersecurity. It’s meant to be, quote-unquote, \"extremely good\" at detecting cyber issues, and the result of that, and—the result of that was an eight, four or five percent decline in the average cybersecurity stock last Friday when this leak happened.","offset":396,"duration":34},{"text":"Jason: Yeah, just two, maybe two other things on the leak, just for—this tradeoff, um, you know, I’m dating myself, but when I was at Adobe and we were acquired, we were an early customer of GitHub. Um, and so we were putting source code in the cloud, and that was banned at Adobe at the time. It was banned because their source code was their crown jewel. It was pretty easy to—to make a crappy PDF reader or a crappy image generator, but to do what Photoshop or Adobe Acrobat did, all the exceptions, all the corner—the thousand—tens of thousands of corner cases was the crown jewel, right? Of the company.","offset":430,"duration":43},{"text":"Jason: And so everything—we got the first exemption to be able to use source code in the cloud, and pros and cons. But when—when they use this on-premise source code management tool, it took a month to do a release. A month. A month, okay? Now we’re doing 60 releases a day, right? Or even Anthropic, fastest-growing enterprise company of all time, is still doing massive releases every month or two and dropping features every day, right? So we went to something that took 30 days at a tech leader to something that takes hours. There’s trade—there’s tradeoffs there, and I’ll—I’ll take them.","offset":473,"duration":45},{"text":"Jason: But we’re going to see it explode. In terms of, like, the stuff that was published today, going back a few threads on show number 50 to Rory, one of the things that I thought was pretty cool in Kairos was two things: um, always-on background assistant that works constantly. Our AI is working with us 24/7. And agents that can sleep, wake, and self-resume without any prompt. The autonomous agents, which I’ve been talking about how this is going to consume orders of magnitude more tokens and change our lives, I’m—I’m excited to see more coming.","offset":518,"duration":46},{"text":"Jason: And, you know, Open Claude was just this—this brief thing that woke us up to what Anthropic appears to be all-in on. Truly autonomous agents running 24/7, hopefully more safely, hopefully not leaking all of our source code. But it’s coming soon, right? Not these—you know, this whole idea that we’ve been doing—since when we started this podcast, you went onto ChatGPT or Claude—no one had heard of Claude when we started this, I was the quirky guy using Claude—and you’d talk to it and go back the next day. The next release is going to be on all the time, all the time, debating Harry’s latest investment. Was it big enough? Is he too concentrated in the fund? Where should he go? What was Rory thinking on that deal, right?","offset":564,"duration":40},{"text":"Host: Why was Rory abusing Harry by email again for the second time in a day?","offset":604,"duration":5},{"text":"Jason: Again, we laugh, but this is the future. I—I’m excited to see it coming sooner when our agents are 24/7. Like, they’re literally around us and we give up all of our personal freedoms and autonomy as part of it.","offset":609,"duration":15}],"startTime":90},{"title":"OpenAI's Strategic Shift: Killing Sora & Embracing Ads","summary":"The discussion contrasts Anthropic's momentum with OpenAI's decision to kill its Sora model. The hosts analyze OpenAI's pivot away from costly consumer experiments toward establishing a viable ad-supported business model.","entries":[{"text":"Host: I hear you on the embarrassment of it being leaked and, you know, the human error element. But while Anthropic has Mythos, which is supposedly as powerful as it is, you’re juxtaposing that with OpenAI fucking around with killing Sora, kind of ads not really working and people being unhappy with it, and it seeming like this massive chasm of the progression of force that is Dario and Anthropic continuing faster and harder than ever with a faltering, confused, and dazed OpenAI wandering around the product desert trying to find some water.","offset":624,"duration":42},{"text":"Rory: You’re just being mean. I mean, again, as I said last week—and I’m sorry to repeat myself—","offset":666,"duration":7},{"text":"Host: Is that not fair?","offset":673,"duration":2},{"text":"Rory: Yeah, but—again, narrative is overdone on both sides, right? So—I think some parts of it are true. Obviously, you throw in a bunch of different things. The decision to shoot Sora in the head, right? Almost certainly a good decision. Look, it’s obviously embarrassing to say something is going to be amazing less than four or five months ago and then shoot it in the head. But if it’s a mistake, give them credit for at least saying it’s a mistake, move on, right?","offset":675,"duration":28},{"text":"Rory: And yeah, that relationship with Disney—again, I think I’m going to give you—it wasn’t me, I was sneering at it in real time when it happened, I think someone else on this podcast said it’s really significant, just saying, right? It’s Crotchety—","offset":703,"duration":16},{"text":"Jason: I do, I—I think it’s massively significant. I think shooting in the head is even more significant. Um, I think saying that the entire—a big part of the whole strategic direction of the company was flawed. Agreed. The whole that we are going all-in on consumer, the—from what I read, Sora made single-digit millions of revenue, right? And was consuming a million a week, which actually sounds way too low, right? It must—it must have consumed billions and made single-digit millions. It makes no sense as a product, either in the short term or the long term.","offset":719,"duration":39},{"text":"Jason: But if you want to own the whole consumer experience with AI, you’ve—they decided we have to own image and video, and Anthropic never even attempted to do it, right? So it’s a massive retreat. It doesn’t mean it’s the right—it’s probably the right decision, to your point, in fact almost certainly is. But man, that’s a—\"Our strategy was wrong.\" Like, this is a huge own goal. \"Our strategy was wrong.\"","offset":758,"duration":25},{"text":"Rory: Agreed. But I—and I agree with that, but I still think—as I say, I still think Harry’s over—kind of overegging it a little bit because, look, you made a comment about ads that I think is—uh—hypothetically—um—effectively implying that the ad strategy hasn’t worked. That’s a bit of a bigger leap. I mean, Sora hasn’t worked, they’ve killed it. I think I’m with Jason, I think that’s smart because I think one of the things you’re seeing right now is in a world of scarce compute—and astonishingly, despite all the investments that we’ve seen in terms of actual available compute for people to sell AI on, we’re in a scarcity mode. You don’t devote compute to things that are highly compute-intensive and low revenue-intensive. I mean, it—and Sora was almost the definition of that. Video generation is extraordinarily compute-intensive, relatively speaking, and the revenue is almost minuscule.","offset":783,"duration":71},{"text":"Rory: Conversely, you know, CoGen, while it is compute-intensive, is orders of magnitude less compute-intensive and there’s real dollars attached to it. So you’re literally—what’s happening right now, I actually think at a higher level, it’s actually very healthy. You’re seeing the economists, the accountants have wandered into the room and they said, \"We have a scarce resource here, let’s optimize it, let’s devote this compute to the people who can pay the most for it.\" So that’s the Sora comment.","offset":854,"duration":56},{"text":"Rory: On the ads comment, Harry, yeah, it’s early days for, you know, ChatGPT ads. But again, I cite that quote that Brian Kimball did that was really good. Of course they’re going to run damn ads because there’s no other way to build a mass consumer business, and they’ve no choice, right? Because, you know, their consumer conversion rates run roughly 5%. It gets them to a—I think a roughly 10, 15 billion dollar consumer business, right? Out of their 500 million uniques or whatever it is.","offset":910,"duration":36},{"text":"Rory: So one of two things has to happen in the consumer business—again, I’m going to leave the enterprise business out. On a consumer business, either A, they take that conversion rate to a number we’ve never seen before from a typical consumer business—I think that’s unlikely, I don’t think most consumers are going to pay 20 bucks a month for this—or option B is you make an ad business work. They’ve got no choice but to make it work. And by working, I don’t mean a hundred million dollars. People are kind of ragging on the hundred million—it’s in the noise, it’s scale. Big picture here: Facebook and Google each do 200 billion, plus or minus, a year in digital ads. If these guys aren’t doing 20 billion within a couple years, they’re not even in the game. And to get to the market cap of—I mean, remember, Facebook has a 1.7 whatever it is trillion market cap doing 200 billion. Alphabet/Google has a 3 trillion market cap doing 260 billion plus thing. If they’re going to grow into their market cap on the consumer side, 20 billion’s not enough. They have to do 50 billion, 70 billion of ads. So unlike Sora, this is not going to be a \"try the ads and then fold.\" This is a—there’s only two existential bets for this company: one of them is ads to make the consumer business work, and then the other is \"Oh my god, we should have done coding all along. Let’s get a competitive coding and enterprise model out there and compete with Anthropic on that side.\"","offset":946,"duration":89},{"text":"Rory: So those are the only two things they’re doing and they’re the only two things they should be doing. It’s straightforward. I mean, I actually see this as good news. Like, at least they’ve—like, we’ve gone from the \"let’s wander around the woods feeling cool building shit\" to \"there’s only two things to do, let’s get them done.\" I—it’s net—it’s a positive. Better late than never.","offset":1035,"duration":20}],"startTime":624},{"title":"The WSJ Report on OpenAI's Internal Drama","summary":"The hosts react to a Wall Street Journal article detailing the leadership turnover and intense interpersonal drama at OpenAI. They discuss the massive toll this infighting takes on CEO Sam Altman's time and execution.","entries":[{"text":"Jason: Man, did you—did they had the Wall Street Journal this week? They had—they had a story of why Dario left—OpenAI. Did you see that story?","offset":1055,"duration":9},{"text":"Rory: Oh, that was juicy. Yeah.","offset":1064,"duration":2},{"text":"Jason: Yes, I did. I mean, the amount of tension at OpenAI. The fact that Greg Brockman attempted—recruited them and no one would work for him. He and—and his sister would not work for Greg Brockman, would not talk to him, they would not allow him to be part of the LLM or G-T-P groups. Then Sam had to constantly tell each of them that they were in charge, right? Told Dario he was the boss, then told Ilya and Greg they could fire him at any time if they wanted to fire Sam, right? Then begging—then Dario to come back, then Dario saying he would stay only if he directly reported to the board and nobody else. I mean, the level—and then—and then finally firing Sam and then bringing him back and then Sora and de-Sora and we’re not doing coding. It’s just—I mean, I’m exhausted.","offset":1066,"duration":55},{"text":"Jason: I—maybe I’m wrong. I have to think at least someone like me would feel much more comfortable in Anthropic where it appears there’s a much more consistent process and leadership, right? Same founders, same things, same goals. It just—I have to think a company organized like that is just going to ex—out-execute someone with that level of drama. I—I almost can’t take it.","offset":1121,"duration":26},{"text":"Host: You’re going to kill me for this, Rory. Is the best thing for OpenAI not to buy Sierra, incorporate that as its customer support product, and have Bret Taylor come in as the day-to-day CEO and Sam can be fundraiser, Sam can be master of—","offset":1147,"duration":17},{"text":"Rory: I’m not in the boardroom, so—you know, I hear—look, at the end of the day—at the end of the day, I think you’re right, Harry, and I would favor that as a board member, but I’m not going to say that publicly because I don’t want Sam to break my balls. I am too unimportant for Sam to even give a shit about, right? So I don’t worry about that at all.","offset":1164,"duration":36},{"text":"Rory: So let me say this delicately. That amount of board-level and senior-team-level turnover over an extended period of time is probably the highest warning signal that you could have as a board member about how your CEO’s doing, right? And if it was anything other than a founder—let’s put it this way, if it was anything other than a founder-led company and this level of drama was going on, you’d probably be having—you’d probably sit down with the CEO and asking how’s it going, at least, and what are you thinking of doing about this? I don’t think you turn on people just when things go to shit, but you probably want to cut down the drama from here, build a team, and try and call a shot and play it for more than 24—you know, for more than six months at a time.","offset":1200,"duration":49},{"text":"Jason: Well, when you’ve—when you’ve worked at or observed startups where the CEO is spending so much of their time load balancing talent that can’t work together versus when you’ve worked at one or with one where the talent’s rowing in the same direction—to say that it’s night and day would be an understatement, right? It’s like the—the back side of Pluto and the front side of Mercury. And it’s just—and I think Sam—we could criticize him, actually when I read the—everything I’ve seen and then when I read the Wall Street Journal article, it’s like, \"My God, this guy has to spend so much time load balancing the drama of these extremely brilliant personalities that just, oh my god, that can consume number—most of your time as CEO. Most of your time load balancing.\"","offset":1249,"duration":45},{"text":"Rory: You’re exactly right. It is the drama of—we’re not dealing with a bunch of people just trying to crank out some B2B software and make a paycheck, we’re dealing with people who are angsting about whether this is going to change the world, who have fears about the technology, who have, yeah, desires to be seen as credited for the technology despite their fears about it. This is a—I mean, as is often the case, extraordinary talented people come in an extraordinary high bandwidth—a—demand on attention and care and feeding. It’s probably—it’s been a real slog, I’d say.","offset":1294,"duration":33}],"startTime":1055},{"title":"Masa Son's Leveraged Bet on OpenAI","summary":"SoftBank's Masa Son takes out a $40 billion bridge loan to buy OpenAI stock. The hosts evaluate the extreme leverage and risk involved in this investment strategy.","entries":[{"text":"Host: Okay, the man with the most balls in investing, Masa Son. SoftBank gets $40 billion bridge loan to buy OpenAI stock. How deep can Masa go?","offset":1327,"duration":17},{"text":"Rory: He’ll go as deep as they let him. I mean, that’s the one thing we know: if they give him another 20, he’ll borrow that too, right? I mean, look, this is a—I actually checked the SoftBank—you’ve got SoftBank holdings—I have to be careful, there’s the Telco Group which is mod—reasonably levered at the Japan level, and then SoftBank Group is around 2x levered. One and a half to 2x levered in terms of equity, right? What that means is a 30-40% decline, you know, wipes them out, right? It’s a very aggressive stance, right?","offset":1344,"duration":37},{"text":"Rory: It would be like me taking our $800 million venture—$900 million venture fund, borrowing 1.8 billion, and investing it all, and if, yeah, if it works I make—you know, I really juice my return, but if it goes wrong by 30% I’m done, right? And it’s just—it’s super aggressive. I mean, I suppose his lesson is Masa survived 2002 when I remind everyone the NASDAQ went down 85%. You haven’t lived until you’ve seen an 85% decline in an index, right? And obviously if that happened or anything like it, um, you’d just be way underwater. Right? So it’s a—it’s a fairly high amount of leverage for an investment fund to say the least.","offset":1381,"duration":43},{"text":"Jason: Yeah, I mean, for—for sure it’s dramatic. Having said that, you know, real estate investment funds get the maximum leverage they can by design, right? They—that is how they work. I would imagine if venture had access to more debt, we—we’d all—we’d all load up on it. If we all could—if we all could do the growth rounds in your hottest company and uh maybe we would—and we could get—and we could get all the carry from it with the—and the worst thing is we leave the keys to fund seven on the table, we might—we might load up too. I’m not sure. But certainly, real estate funds load up as much as they can.","offset":1424,"duration":35},{"text":"Rory: But just pushing back again, because real estate funds load up because the cash flows are predictable, right? At the end of the day, I mean, look, in a—","offset":1459,"duration":9},{"text":"Jason: Oh, they—and they can, but they can because the cash flows are predictable, they can load up. Agreed. Right? We don’t—it’s just harder for my little fund to go to Silicon Valley Bank and borrow 200 million against—","offset":1468,"duration":11},{"text":"Rory: In the continuum of risk, I would argue the SoftBank portfolio, not the Telco company at the subsidiary level, but I would argue the SoftBank portfolio is more like Jason’s fund than it is a real estate fund. So I think it’s a high level of risk.","offset":1479,"duration":15},{"text":"Jason: Well, plus what did he lose on WeWork? 12 billion. He—he knows. He knows what it’s like.","offset":1494,"duration":7},{"text":"Rory: The two big assets from memory are uh obviously the OpenAI position and I think the Arm position, which I still think is in um the—the—the—in the holding company. And yeah, but I mean, amazing companies, world-class companies, easily imaginable a blow up with a decline 30%. So, yeah, it’s a hell of a way to live.","offset":1501,"duration":30}],"startTime":1327},{"title":"The Mythos Leak's Impact on Cybersecurity Stocks","summary":"Following the Claude Mythos leak, cybersecurity stocks like CrowdStrike and Palo Alto took a hit. Jason argues the market reaction is backward, as the proliferation of AI agents should usher in a golden age for cybersecurity firms.","entries":[{"text":"Host: Speaking of declining 30% and being in the hole, we—we touched on it earlier, but obviously Mythos leak hammered cyber stocks. CrowdStrike, Palo Alto, Zscaler all down 6%. Okta, Netscaler down 7%, Tenable down 9%. Was this a justified dip, or is this an unjust reaction to Anthropic news?","offset":1531,"duration":24},{"text":"Rory: I was listening carefully to the name because I was listening carefully to the names and there’s different aspects of security, and some of them I can say, \"Yeah, maybe that overlaps,\" and then some where I go, \"That’s just a different thing,\" right? And when you listen to all the names being thrown out, you say that’s just, you know, baby with the bathwater. Because step back: how does—how does Anthropic, you know, make security better? At the code development stage, they can look at code and find security flaws. So there are companies that upfront do something like that and, you know, application security companies, and you could argue that this is a different way of doing that, maybe some of those guys will be impacted, right?","offset":1555,"duration":43},{"text":"Rory: What they’re not doing, for example, is real-time perimeter defense. They’re not in a—in a real-time basis, you know, blocking people like a firewall, right? Nor are they doing what, for example, Okta does, right? Which is single sign-on and authentication. That’s simply not what they do; it’s a different thing. And the fact that both of those kind of stocks sold off says it’s just a kind of knee-jerk reaction rather than anything thought-through.","offset":1598,"duration":29},{"text":"Rory: It will have an impact. If you were doing application security or code review for—security code review, you’re probably going to have to either incorporate how this works in your analysis or you’ll be redundant. Just as the—the coding companies, anyone kind of—just as GitHub had to roll in complete models and figure out how to adopt it, right? So for some of them, this is really going to matter, and then for others it’s like, it’s just a different thing.","offset":1627,"duration":28},{"text":"Rory: Stepping back, I think we’re in the panicky stage, right? I think we’re in the stage of because these companies are doing so well, because they’re private no one sees the numbers, because AI is so sexy and so potentially amazing, we’re at the stage now where everything can—anything can cause a panic.","offset":1655,"duration":18},{"text":"Host: Robinhood was down like 10% because Elon didn’t potentially give them the tender and was going straight through E*Trade. And that alone was like a massive blow for them.","offset":1673,"duration":14},{"text":"Jason: Obviously, there’s a panic in the market and the question is, is the panic justified, right? The panic is that this revenue is not durable, right? That’s the panic. The cybersecurity one’s really interesting. In my—in my experience and opinion, this is one where it’s just back-asswards. Um, because if you’re in the agentic world, this is the golden age of security. The number of security threats and issues is going up orders of magnitude. Claude leaking its source code, it doesn’t matter. The number of—of apps exploding, the number of—like, there’s so many mobile apps that App Store is like—it’s like a month to get your app reviewed versus a week. It is—everything is exploding. These apps are being built by agents. They’re being built in unpredictable ways. Folks aren’t looking at the code. The pace of features being shipped, products being shipped, corners being cut. This is a golden age of taking any mature category and acknowledging, \"Good news for us, there’s more threats.\"","offset":1687,"duration":53},{"text":"Jason: Good—whether—I don’t care whether it’s application level, perimeter, like—the good news is threats are exploding and the whole shtick of cybersecurity—I’m not a real cybersecurity expert, although I’m doing another investment right now for just this reason—the whole shtick in my whole lifetime has been, \"Look, you’ve got to constantly buy new products because new threats keep emerging.\" Like, this has been a golden goose of cybersecurity that has allowed new entrants to come into a conservative category. Someone like Wiz will show up and say, \"Guys, we know how to do this on the web,\" and people are so terrified of new threats they’ll take the meeting, right? This should be the golden age for new and existing investors because the threats are terrifying and you can’t stop the rogue engineers that vibe-coded something that accessed your data. This—this should benefit everybody. Like, everyone should be a rocket ship like everybody built—like everybody monetizing GPUs is a rocket ship. And the fact that the market doesn’t see it shows we’re in a—in my opinion, we’re in a true panic, which is hard to predict a bottom. But I don’t get it. Everyone should be benefiting when you see an explosion in application production and a change in the paradigm. The change in the paradigm’s good for everybody except, you know, Windows Defender from 1996. Like, it probably doesn’t help that product or whatever the hell they have, but anyone—everyone with engineers should benefit.","offset":1740,"duration":86},{"text":"Rory: I broadly agree with Jason. I mean, there might be—there are more than Windows Defender 2006 that might be impacted. As I say, some of the application security code review stuff could be. But big picture Jason’s right. Instead of having people trying to get in through your firewall, we’re everyone is now downloading an agent, giving it full root access to their computer, and telling it have a go, and as Jason just pointed out, work overnight. It’s going to—I mean, no one yet—it’s funny, we—my colleague Errol who does a lot in the security side, we’ve been looking at a lot of these companies. No one yet knows the exact approach that we’re going to have to take to defend against agents running within the organization, but everyone 100% understands that this is a—emerging mega-threat because of the velocity of adoption times the power of the solution.","offset":1826,"duration":52},{"text":"Rory: So I agree with Jason. It mightn’t be the old guard that takes advantage of it, but there’s no—but they tend to be pro—one of the things I admire about the security companies is the CrowdStrikes, the Palo Alto Networks of this world is they know damn fine that when a new threat emerges and a new solution emerges for that threat, when an earlier winner comes out, you better spend your 300 million bucks, your 500 million bucks, and just swoop up the winner and add it to your product, right? So I think there’ll be a ton of fast acquisitions as agent security solutions emerge, you know, and at—and people will be doing, if they’re smart—and I think those two companies are extraordinarily smart—they’ll be doing acquisitions long before it’s, quote, \"certain,\" because you’re going to have CIOs coming and talk to you.","offset":1878,"duration":36},{"text":"Rory: Right? One thing worth mentioning on that is it was interesting—again, I—in some of the leaked information from Anthropic—they are masters at selling fear. One of the things they’re doing is they’re releasing the Mythos model first to CISOs within companies. It’s kind of like, \"Oh, it’s so scary, we’re going to give you this model and give you time to figure out how to use it.\" Of course, part of that time will involve giving a million bucks to Anthropic for—so it’s just great marketing. So they’re actually leaning into that and saying to the CISOs, \"You’re going to have to figure this out. This is the new terrifying weapon we’ve invented. Please give us a million dollars and we’ll let you defend yourself with it also.\" Great marketing. Uh, but it speaks to the perceived—to Jason’s point—it speaks to how correctly afraid every security for—CISO should be given the pace of agentic AI adoption in the enterprise.","offset":1914,"duration":57},{"text":"Host: In the golden age of cyber, I wish I’d bought more.","offset":1971,"duration":4},{"text":"Jason: I mean, it’s just—it’s just how hard is it to get a meeting? Whoever you are, if you have any established brand, \"We—we’ve got a new agentic product, we’re going to help protect you from this.\" You’re going to get a meeting that afternoon.","offset":1975,"duration":9},{"text":"Host: Wish I bought them over Figma, that’s a depressing chart that I’m looking at.","offset":1984,"duration":6},{"text":"Rory: You need to let—you need to let go, Harry. You need to let go.","offset":1990,"duration":4},{"text":"Host: I’m—I’m down 30% in a month, Rory. It’s hard to let go after 30% in a month.","offset":1994,"duration":5},{"text":"Rory: Okay, no crying in the casino. Move on.","offset":1999,"duration":5}],"startTime":1531},{"title":"Questionable AI Revenue Recognition and ARR Metrics","summary":"The hosts break down how Anthropic and OpenAI calculate their annual recurring revenue (ARR) differently. They also note that reselling the same compute tokens artificially inflates revenue across the AI startup ecosystem.","entries":[{"text":"Host: Uh, we—I—I do want to discuss revenue kind of questionability. Uh, we’ve got Anthropic recognizing revenue in a very different way to OpenAI. And then you also have questionability around Emergent Labs, um, and is it okay if ARR is kind of questionable in—sort of how it’s accounted for? Um, how do we think about that? You can choose which one you want to take.","offset":2004,"duration":24},{"text":"Jason: Let me just—can I just—I—maybe Rory can dig into it, but I’ll tell you there’s one startup I invested in that’s over a hundred million ARR. And I get the—I—I—I own just enough to get the investor updates. It’s not—I’m not on the board. And I get three numbers every month. Three revenue numbers. I—I don’t know what the hell they are, over a hundred million, but the smallest one is ARR. Now I invested in Seed, I don’t really care, I’m in the money, I don’t—I don’t have a choice. But I—I can’t understand—this company’s doing great, but I can’t understand for the life of me these three numbers and there’s asterisks and daggers and there’s charts that go everywhere, but they keep going up and to the right, which I think was on this Emergent thing we could talk about next. I think that’s what some of the investors said, \"Who cares?\" But I can’t tell the hell the difference what—what an ARR is in 2027.","offset":2028,"duration":43},{"text":"Host: Well, what—what I always get is like \"pipe,\" which is complete bullshit, then \"contracted,\" and then there’s \"live.\"","offset":2071,"duration":7},{"text":"Rory: So, first of all, stepping back, both—to be fair to both Anthropic and OpenAI, they have a very clear and sensible way they define ARR. What they take is they take the last—the average of the last four weeks to smooth out, times 13, because there are 13 four-week periods in a year. Which is more sensible than monthly because you have these varying months. So they basically—what they’re saying is realized revenue for the last four weeks averaged, you know, the average of the last four weeks—sorry, obviously if it’s the average it’s times 52—but basically it’s actual GAAP revenue. What did we bill for the last four—the average across the last four weeks to take into account holidays? That’s their run rate. Right? So it’s actually pretty—it’s not committed or any of the bullshit kind of higher-level stuff. It’s actual money flowing through the system.","offset":2078,"duration":58},{"text":"Rory: Anthropic is roughly at 19 billion according—based on that kind of trailing four-month—four-week metric, and OpenAI is around 25. But now let’s talk about your thing. There was this kind of whole meme of OpenAI reports net on their partner revenue and Anthropic reports gross. And what they’re saying there is if OpenAI sells through Microsoft and Microsoft takes some money off the top, OpenAI only reports the net amount. If Anthropic sells through AWS and they sell a hundred dollars worth of revenue, they report the gross amount and then they give 20—20 dollars back to Amazon as a cost of sale. So there’s two different methods for what look like the same revenue kind of nix—or same revenue approach.","offset":2136,"duration":44},{"text":"Jason: I thought you were going to extend that. I thought part of where you were going was to Michael Cannon-Brookes’ point on the show was that a lot of this revenue is getting doubled or triple-counted because of how it’s being recognized. And not only does this happen, then Cursor’s selling it again and recognizing the revenue, right? The same—people keep reselling these tokens again and again and recognizing them as their own ARR. Um, how many times do we get to resell these—these poor little tokens?","offset":2180,"duration":30},{"text":"Rory: I think that’s actually a great point, Jason. I hadn’t thought about that, but you’re exactly right. No, it’s like the—everyone’s got amazing revenue growth because it’s the same little token going through different—I can just picture this little token.","offset":2210,"duration":14},{"text":"Jason: I mean, if we all agree to have essentially 0% gross margins, an infinite number of us can keep reselling tokens to each other, can’t we? This is our new 20 VC scale SaaSster demo day. We all resell a million tokens to each other on the first week, so everyone in Batch 001 has a million ARR its first week, because we just resold our tokens to each other. So and it’s completely fair. The VCs don’t mind.","offset":2224,"duration":27},{"text":"Rory: And—and you’re exactly right, and the sentence that you added in passing is the key one: \"until we all have to get profitable.\" All this, you know, can continue. And then at some point, that’s why I said I think you’re starting to see it, someone’s going to have to say, \"Assuming we want to have a net present value and a cash flow, what’s going on here?\" And then—and then all this becomes more clear.","offset":2251,"duration":23}],"startTime":2004},{"title":"Emergent Labs and Deceptive PLG Billing Practices","summary":"A look into Emergent Labs' claim of reaching $100 million ARR in just eight months. The hosts criticize deceptive product-led growth (PLG) billing practices that instantly log free trials as paid recurring revenue.","entries":[{"text":"Rory: I—I didn’t comment on the Emergent Labs fastest to a hundred million. Jason, you—you actually tried it, didn’t you? You thought it was good.","offset":2274,"duration":6},{"text":"Jason: I did. I thought—I mean, listen, it’s hard for me to know the criticism, right? You know, some folks in the press and the India B2B environment tried to make this some sort of scandal, right? Because—and in a sense, fair enough. If you go to Emergent Labs—and Emergent Labs is sort of an Indian competitor Replit and Loveable, which I’ll show you what I learned in a minute, right? And if you go right now to the homepage they say \"0 to 100 million,\" I think in eight months. It’s right there, it’s the biggest banner. So in all fairness, if you’re going to put yourself out there, not—not just as a tweet, but if it’s going to be right there on your website, one would expect 70 to 80 percent accuracy in that number, ideally higher, right?","offset":2280,"duration":43},{"text":"Jason: So if it’s lower than that, I think it’s fair that some daggers came out. But I was curious—um—but I don’t actually know what happened. Is it triple counting to—I—I can tell you one thing that I learned, which I don’t love, which is that what a—and a lot of AI startups do this. So this is not unique to Emergent. They kind of hot—instead of getting you to use the free version, they try to get you to immediately do a free trial, instantly that says it’s zero dollars and twenty dollars a month thereafter. Now so many folks do this. It is not unique to them; it’s probably best practice in most accelerators. But I’m pretty sure that means they recognize twenty—240 dollars in ARR that first month when you’re paying zero. And they trick you because you don’t even—yeah, you do have to click on the Stripe link, but you almost think you’re just using the free product.","offset":2323,"duration":52},{"text":"Jason: So is that—if I do a zero dollar a month product um that’s discounted as a marketing cost and I churn after 30 days, does that count as 240 dollars of ARR? I think for a lot of startups it does. Okay? So—that—that’s a fair criticism. I’m not saying this is what Emergent did, but a lot of startups will instantly recognize that as 240 dollars in ARR, which is how they rocket if you’re self-serve. That’s how you—otherwise you can’t get there that quickly, right? So they clearly did that.","offset":2375,"duration":37},{"text":"Jason: I will say what was interesting is I—I thought the product was pretty good. Much better than Make. Like an order of magnitude better than the disaster of Make. Um, because I—I do a five-part test, a six-part test. The first part is awareness test. So I ask it to redo the SaaSster.ai homepage. Uh, actually of all the platforms it did the best job. It—it beat—it beat—it beat all of them. All of the leaders, because I redid this recently. I redid this and Replit, Loveable, VZero, they’re all good at—they all pass the test, but it actually—it actually was probably the best and it—it passed a bunch of the other tests.","offset":2412,"duration":49},{"text":"Jason: So I’m not going to switch to Emergent Labs, but I would say it’s in the top 10% of vibe-coding apps. That’s pretty good. So that tells me it’s a legit business. Like they did—they did the work and a lot of these they’re just—the truth is if you play with a lot of these even from leaders, like Make’s not the only one that’s crappy, okay? Because they’re basically relying on the fact that Claude code does 90% of the work for you. Right? They’re just putting the simplest wrapper around this and so they did a good job. But is—I really didn’t like the way they do the billing, but we’d probably have to shoot half our portfolio companies that do like PLG AI because I think it’s a sus practice. I just don’t like tricking you with this zero dollar for the first month when you think you’re using a free trial, right? That’s the sus part. I don’t—I don’t love that kind of gray art. Um, but the product’s pretty good.","offset":2461,"duration":71}],"startTime":2274},{"title":"The Optics and Gamification of VC Tranche Rounds","summary":"Harry vents about the misleading nature of venture capital tranche rounds, where blended entry prices are used to artificially inflate headline valuations. The hosts agree that founders and investors are increasingly prioritizing gamified valuation optics over reality.","entries":[{"text":"Host: You know what I didn’t like when it comes to confusing? I was wondering whether to go off on one in this show and then I thought, \"Fuck it, let’s go off on one. It’s been a long day.\" I’m pissed off by these tranche rounds. I see them all the freaking time. The amount of Sequoia rounds where it’s like, \"Oh, you know, X raises money from Sequoia at five billion.\" Trust me, Sequoia got in at one, but they just club it together and then announce the sum and then the latest valuation. And it’s just very misleading. The tier ones get in early, a tier two, tier three instantly marks it up same day.","offset":2532,"duration":35},{"text":"Jason: Same as crypto, isn’t it? For years. What’s the difference? We’ll give the Andreessen crypto fund the, you know, essentially 80% off the token. What’s the difference? You’re paying for the—paying for the signal.","offset":2567,"duration":11},{"text":"Rory: I think if you break it down, first of all, just so everyone’s on the same page, because interestingly neither Claude nor GPT was on the same page and didn’t know what a tranche round was, and they gave the old conventional venture tranche round based on performance milestones, you know, BS from back in the day when we actually ran businesses, right? So they didn’t have a clue about this.","offset":2578,"duration":26},{"text":"Rory: So let’s be clear on the practice here. The practice here is when a company, a hot company raises a round where there are effectively two different prices per share—a first—let’s call it a first close and a second close, even if they are at or near contemporaneous—where the first one might be at 250 pre and the second one is at a billion pre and, you know, the highlight and the headline is they raised at a billion pre. There’s two imp—impacts of this.","offset":2604,"duration":33},{"text":"Rory: First of all, let’s do the simple one where there’s just a single participant in the round. That’s where, you know, if I’m the new investor, I want to pay 600. The company wants a headline of a billion. And to win the deal someone says, \"Okay, let me put some money in at 250, some money in at a billion.\" I can do math because I’m paid to do math because I’m an investor, so I know my overall basis is a billion—sorry, obviously if it’s the average it’s 600 million. So I’m getting what I want, and the company’s getting what it wants, which is a headline number of a billion, right? It’s silly, but that’s all that’s happening in that case. That’s the single participant tranche deal, right? And it’s just—and for some if a company wants a headline that’s what they get, right?","offset":2637,"duration":57},{"text":"Rory: Generally those things come back to bite you because by definition if you’re the company, just as the investor can do math presumably you can do math. If you accept that combined deal you’re implicitly saying, \"I know I’m only worth 600 but I’d like the optics of a billion.\" You better be damn sure that your next round you’re at one and a half billion, otherwise you’ll have the optics of a down round, and if you’re an optics believer that’s probably worse than the uptick, right?","offset":2694,"duration":32},{"text":"Rory: So that’s kind of the single participant version. The much more annoying version that Harry clearly was getting on his high horse about is when you have the same structure but access to those rounds where the—the lead investor maybe does all of the 250 pre-round and only half of the billion round, and then some new investors just get to do the billion round. So literally at the same time, the lead investor is investing at 600 billion—I mean, million—and the follower investor, less marquee investor, is investing in the same asset at a billion. And there—I don’t believe there’s right or wrong in money, there’s just money, right?","offset":2726,"duration":45},{"text":"Rory: That’s where at the minimum you have to look yourself in the mirror as the other investor and say, \"Wow, that’s the price of being cool.\" Right? \"That’s the price of access. I’m paying 50% more because I just can’t access that deal.\" Right? And that feels like pretty invidious thing to—I mean, again, going back to the comment, the—you’ve got to remember if you think about—and again, try to avoid morality and saying, \"Oh, it felt shitty,\" because it really—it would feel like a loser if you did that. But let’s play it out. In this situation where the—the lead investor, let’s say it’s Sequoia because everything good and strong should be Sequoia, they’re admitting it’s only worth 600 on average and they’re just doing this fakey transaction. The company is admitting it’s only worth 600 on average because they’re taking the money at a blended cost of 600. So what you’re saying doing it at a billion is you’re either saying, \"Either I have a lower cost of capital and I’m willing to take a lower return than everyone else,\" or the only positive spin you can come up with is the company thinks it’s worth 600, Sequoia thinks it’s worth 600, but I am smart enough, even though I don’t have access, I am smart enough and clever enough to know that it’s really worth a billion and I should do it at a billion even though I can’t get to 600. And I’m willing to put up with the upfront tax and foolishness look because I think 6-12 months from now it’ll be obvious that I bought it at a great price and maybe I’ll look like a genius.","offset":2771,"duration":99},{"text":"Jason: Yeah, but we’ve—but we’ve entered an era though, the—one—I think the meta thing—maybe this wasn’t exactly what you were queuing up, Harry, but it is tough. We’ve entered an era where so many founders are obsessed about headline prices. Obsessed. They’re obsessed coming out of Demo Day, they’re obsessed—they’re obsessed. Once they cross a billion, which I think should be a moment to take a pause because of an M&A options, they’re obsessed about driving to 11 billion and 9 billion and one-upping their competition. And the numbers have become a joke to many founders, right? They just don’t—maybe joke’s the wrong term. They don’t think through the—any of the ramifications of the valuation they’re hiring, they don’t care.","offset":2870,"duration":48},{"text":"Jason: And I’m not even saying that’s bad. I mean, I think burning the bridges is a good way to have a big outcome, but it’s become utterly gamified on many levels, right? It’s just become gamified. And so this—11-teen tranches and around is just part of gamifying it, right? It’s been true of YC since I started investing. There—there was always a cheaper price before Demo Day if you’re reasonably hot, a higher price at Demo Day, and then a 20% or 30% after Demo Day. So that version has just become institutionalized and so be it if it’s what the founders want. If they want to gamify it, so be it, right? I just don’t think raising at 5 or 8 billion when you’re at 80 million or 100 million of suspect ARR is the most exciting accomplishment in the world. Like, I’m not going to—like, I’m—I’m going to send a few thumbs emojis on the email, but that’s about it.","offset":2918,"duration":55},{"text":"Host: That’s about it. They’re all—they’re all fake anyway, they’re all just bets, right? These are not public companies. It goes back to your point on Emergent Labs and the graph of the eight months to 100 million and the gamification of, like, the race to 100 million. I’m not choosing Emergent Labs, but listen, I think they built a good product. I think—I’m sure they’ve been overly lambasted because whether it’s 100 or 80 or 60, I don’t care, it’s pretty damn good, right? Whatever it is. But if you’re going to—if you’re going to do that, you deserve the daggers to come out when it’s not 100%, right?","offset":2973,"duration":38}],"startTime":2532},{"title":"Wearables Valuations and the Risk of Hardware Faddishness","summary":"Sparked by Whoop's $10 billion valuation and Oura's potential IPO, the group discusses the health data wearables market. They debate whether consumer hardware revenue is too faddish and susceptible to disruption compared to software.","entries":[{"text":"Host: One that I thought was fantastic, exciting, I would like to see a potential IPO or to IPO shortly. I thought this was fascinating. This has been an incredible journey, actually, from, you know, Scandinavia, these founders building this business. It’s had a couple of CEO changes. Uh, the business is actually in incredible shape. Both—actually, and Whoop announced today that they raised, I think it was 500 million at 10 billion. Fitness and health data—do you know what, actually, Rory? Jason’s annoyingly right again. I don’t know if you remember his predictions, but he predicted, if I’m not wrong, that 2027 would be the year for, like, human healthcare data and longevity.","offset":3011,"duration":41},{"text":"Jason: Yes, and it looks like it might even be 2026. And yeah, no—and the great thing about both stories is very defensible—I mean, you know, Jony Ive's side—very defensible from an—this is not an AI envy story, this is—I mean, they use AI in what they do, but these are fundamentally standalone products with a clear consumer value proposition and they’re, you know, they’re not going to be Claude-coded on Friday. I totally see it and they clearly have had critical mass in terms of revenues. I think it’s awesome.","offset":3052,"duration":35},{"text":"Jason: I think the question—listen, the interesting thing for for these products, obviously it’s exploded, is they are—they are recurring rev—you know, going back to the topic of ARR, these are recurring revenue products, right? Um, for the most part, right? Um, fairly expensive subscriptions, um, and they’re exciting until like Peloton when they aren’t, right? Now there—there’s not a $2,000 cost here, um, but—um—and I’m not being critical. I—I think that they’re exciting. But there’s also a faddishness-ism. People can switch. So the RR, the ARR, the pirate R, um, what multiples do these companies deserve? What it is, I—I’m not smart enough to know, but the—but the acceleration is a force of nature, right? I’d love to be a Seed investor, don’t get me wrong.","offset":3087,"duration":49},{"text":"Rory: Do you think there’s a faddishness in the same way? I think we—","offset":3136,"duration":2},{"text":"Jason: I think you can switch from vend—Harry, you’re into fitness. I—I’m not so much, but I run 360 days a year, five miles a day for 10 years. So if there’s a better treadmill, a better device, a better thing, I would switch. And whatever you’re—you’re fairly fit, Harry, like if you—if you were Oura and you love it, but Whoop is—is better and you care, you’re going to switch. So it’s not ServiceNow ARR, right? You—you’re loyal, you’re loyal, but—but there’s just some disruption risk. Like, look at Peloton. When Peloton blew up, but actually as the world changed, even though people love Peloton, right? Super high NPS, they—remember the Peloton addicts of 2020 on Zoom? They—they loved it, but when the world changed they just—","offset":3138,"duration":10}],"startTime":3011},{"title":"Epic Games Layoffs and Tech Overstaffing","summary":"Prompted by Epic Games laying off 25% of its workforce, the hosts recall Mark Andreessen's assertion that tech companies were vastly over-hired during 2021. Harry and Rory jokingly spar over their own daily workloads.","entries":[{"text":"Harry: But he helps me put together some of the schedules too. And he was like, \"Whoa, I had no idea about this.\" He was like, \"Whoa, Epic Games laid off 25%.\" I didn't even hear about that.","offset":3148,"duration":13},{"text":"Jason: Yeah, and then—and then I had—had Mark Andreessen on your last pod sort of laughing about how we all over-hired in 2021.","offset":3161,"duration":7},{"text":"Harry: Well, Mark Andreessen was—was very clear. He thought that we were all using AI as an excuse and that we were all over-staffed by 50 or at least 75%.","offset":3168,"duration":10},{"text":"Rory: Uh, by the way, Harry, just logically it's—it would be 75 or at least 50% overstaffed by 50 or at least 75. This doesn't make any logical sense, but keep going. Just picking up on the errors here.","offset":3178,"duration":13},{"text":"Harry: Rory.","offset":3191,"duration":1},{"text":"Jason: He's pissed now. He's pissed.","offset":3192,"duration":2},{"text":"Harry: I would love to see you do a day of my life. I would love to—","offset":3194,"duration":3},{"text":"Rory: Give me a fucking break.","offset":3197,"duration":1},{"text":"Harry: Uh, actually fair.","offset":3198,"duration":1},{"text":"Rory: I now feel guilty.","offset":3199,"duration":1},{"text":"Harry: You've been cranking.","offset":3200,"duration":1},{"text":"Rory: I now feel guilty.","offset":3201,"duration":1},{"text":"Harry: I will give you two hours sleep for six hours a day running two companies at once.","offset":3202,"duration":4},{"text":"Rory: Okay. Now I'm feeling guilty. Move on.","offset":3206,"duration":2},{"text":"Harry: Don't worry. But—but point being, like... point completely under the radar.","offset":3208,"duration":8},{"text":"Rory: They didn't try and do an AI bullshit story. They basically said, you know, active—daily active use of their Fortnite game and their games is down, so your revenue's down, so you take your expenses down.","offset":3216,"duration":13},{"text":"Rory: It was—struck me as a no-bullshit layoff announcement. It's like, you know, \"We sell less stuff, we have less people.\" It sucks. You know, and again, I really do try never to be cavalier about people losing their jobs because every one of those has to put food on the table, they're not earning the kind of money we're earning and now they've got to go out and find another job in a shitty job market. It sucks.","offset":3229,"duration":19},{"text":"Rory: But the lesson is—and that's why I respected them—it's like, we're selling less, so we gotta do what we gotta do to keep the company profitable. But I agree with you, this kind of pretend it's ARR but then next year we hate ARR, it's just a total waste of time for entrepreneurs. Things are what they are and you do best in business if you actually say what they are and just live and die by that. Most consumer products have high volatility associated with them. You better have a damn good R&D function and continue to build great products.","offset":3248,"duration":52},{"text":"Jason: Well, DJI might disagree with you. I mean, there was a whole step function in the industry that they got—they got left behind, right?","offset":3300,"duration":6},{"text":"Rory: Yeah. Would you prefer $2 billion in consumer hardware revenue or $2 billion worth of five-year contracts, um, like Palantir? Yeah, I'll take the contracts with the 90% gross margin and the five-year lock-in, please. Your starter for 10.","offset":3306,"duration":14}],"startTime":3148},{"title":"Durable Software ARR vs. Consumer Hardware","summary":"The conversation shifts to whether the market still values durable software ARR over volatile consumer hardware revenue. They compare the predictable lock-in of B2B contracts with the vulnerability of hardware products like Allbirds shoes and wearables.","entries":[{"text":"Jason: I think maybe the more interesting question, Rory, that you brought up, um, because so much has changed—this is our 50th show, so much has changed, right? When we started this show, uh, public—durable public company revenue despite slowdown in the top line was the gold standard, right? It was the best revenue out there.","offset":3320,"duration":20},{"text":"Jason: Fast forward to today, do we—Oura going public—do we give a crap what type of R it is because the durable software stuff is trading lower than the S&P 500? Maybe I'd rather have Ring revenue and um, with a somewhat suspect, uh, customer lifetime value because the software value is so low. Maybe I don't care where my R comes from, right?","offset":3340,"duration":20},{"text":"Jason: It used to matter. It used to matter, right? We were so—we'd be in board meetings where you would torture companies so that they would have more ARR and that they would have less variable revenue. I mean, that—that seems like archaic today.","offset":3360,"duration":12},{"text":"Rory: Yeah, and—and I remember doing that and I remember telling people not to do that because I'm a big believer as you can't make—you should sell your product the way the customer wants to buy it, not your VCs.","offset":3372,"duration":9},{"text":"Rory: Because I agree with you, this kind of pretend it's ARR but then next year we hate ARR, it's just a total waste of time for entrepreneurs. Things are what they are and you do best in business if you actually say what they are and just live and die by that.","offset":3381,"duration":11},{"text":"Rory: Most consumer products have high volatility associated with them. You better have a damn good R&D function and continue to build great products.","offset":3392,"duration":7},{"text":"Jason: We looked today—this week they also talked about how I think Allbirds was—was it acquired for less than 30 million?","offset":3399,"duration":6},{"text":"Harry: It was—it—yeah, I was literally about to bring this up, Jason. It was acquired by Ames for $39 million.","offset":3405,"duration":6},{"text":"Jason: So my question is, if a company like Oura goes public and you see weakness in a quarter, should you dump this thing instantly, like Allbirds, um, versus forgive a little bit of weakness in a Salesforce or ServiceNow?","offset":3411,"duration":15},{"text":"Rory: Again, I'm going to avoid any specifics—genuine comment here, right? Because it's not appropriate. But I would say something. Unlike you guys, I've run a textile manufacturing company 30 years ago.","offset":3426,"duration":10},{"text":"Rory: The technology required to make an Allbirds or a shoe is not the same as the technology required to make a modern electronic device that sits on the human finger and measures blood.","offset":3436,"duration":11},{"text":"Rory: Either of these kind of consumer electronic products—they're not a monopoly in the same way Nvidia is, but they're pretty—it's a pretty rare number of companies that can do that. Now, go down—for—put it this way, Jason: I'll name a wearable, you'll name a wearable, and then I'll name a sneaker and you'll name a sneaker.","offset":3447,"duration":17},{"text":"Rory: We'll be done with wearables long before we're done with sneakers because there's a lot of different sneaker companies. And yeah, it turns out sneakers are easier to make than wearables, which are easier to make than Nvidia GPU chips.","offset":3464,"duration":12}],"startTime":3320},{"title":"Labor Market Impacts of Epic Games Layoffs","summary":"Returning to the Epic Games layoffs, the hosts explore the broader macroeconomic consequences for the entertainment labor market. They note that AI and content creator platforms are structurally shrinking Hollywood and traditional gaming employment.","entries":[{"text":"Harry: Speaking of like \"do we care, what do we actually care about,\" there were two that I—I don't know if you guys know this, but I have wonderful partners and one of my partners is much more intelligent than me, which Rory, you're going to make some form of gag about.","offset":3476,"duration":13},{"text":"Harry: But he helps me put together some of the schedules too. And he was like, \"Whoa, I had no idea about this.\" He was like, \"Whoa, Epic Games laid off 25%.\" I didn't even hear about that.","offset":3489,"duration":12},{"text":"Jason: Yeah, and then—and then I had—had Mark Andreessen on your last pod sort of laughing about how we all over-hired in 2021.","offset":3501,"duration":8},{"text":"Harry: Well, Mark Andreessen was—was very clear. He thought that we were all using AI as an excuse and that we were all over-staffed by 50 or at least 75%.","offset":3509,"duration":10},{"text":"Rory: Uh, by the way, Harry, just logically it's—it would be 75 or at least 50% overstaffed by 50 or at least 75. This doesn't make any logical sense, but keep going. Just picking up on the errors here.","offset":3519,"duration":13},{"text":"Harry: Rory.","offset":3532,"duration":1},{"text":"Jason: He's pissed now. He's pissed.","offset":3533,"duration":2},{"text":"Harry: I would love to see you do a day of my life. I would love to—","offset":3535,"duration":3},{"text":"Rory: Give me a fucking break.","offset":3538,"duration":1},{"text":"Harry: Uh, actually fair.","offset":3539,"duration":1},{"text":"Rory: I now feel guilty.","offset":3540,"duration":1},{"text":"Harry: You've been cranking.","offset":3541,"duration":1},{"text":"Rory: I now feel guilty.","offset":3542,"duration":1},{"text":"Harry: I will give you two hours sleep for six hours a day running two companies at once.","offset":3543,"duration":4},{"text":"Rory: Okay. Now I'm feeling guilty. Move on.","offset":3547,"duration":2},{"text":"Harry: Don't worry. But—but point being, like... point completely under the radar.","offset":3549,"duration":8},{"text":"Rory: They didn't try and do an AI bullshit story. They basically said, you know, active—daily active use of their Fortnite game and their games is down, so your revenue's down, so you take your expenses down.","offset":3557,"duration":12},{"text":"Rory: It was—struck me as a no-bullshit layoff announcement. It's like, you know, \"We sell less stuff, we have less people.\" It sucks. You know, and again, I really do try never to be cavalier about people losing their jobs because every one of those has to put food on the table, they're not earning the kind of money we're earning and now they've got to go out and find another job in a shitty job market. It sucks.","offset":3569,"duration":15},{"text":"Rory: But the lesson is—and that's why I respected them—it's like, we're selling less, so we gotta do what we gotta do to keep the company profitable.","offset":3584,"duration":8},{"text":"Harry: Guys, we keep talking about these layoffs and these big numbers. I mean, it was over a thousand people laid off in this layoff. A thousand. And the numbers are relatively meaningless and we've had so many of these conversations.","offset":3592,"duration":14},{"text":"Harry: What happens to the labor markets?","offset":3606,"duration":2},{"text":"Jason: Well, one thing on—on the Epic thing, if you—and the Wall Street Journal did a good article on this one too this week on the permanent decline of Hollywood employment. It's permanently in decline. It's not—there—it is on—it is in decline because fewer movies and TV shows are being made, TikToks and YouTubes are doing it, and it's in permanent decline because every other country provides larger subsidies, right?","offset":3608,"duration":24},{"text":"Jason: And so there's this permanent decline in Hollywood labor. I think entertainment is—is sort of a—shows us the future. Epic Games is entertainment too, right? And uh, they will absorb as much AI and technologies as they can to address the—to adapt, and it's just early. It's just early. They've had to adapt to YouTube, they've had to adapt to social gaming.","offset":3632,"duration":22},{"text":"Jason: And I think we talk about these, uh, thousand people at Last year or whatever, but I think Epic Games is just—it's—I think it's a more interesting view of the future than Block. We talk about folks might vibe-code a B2B app, but content's already being massively disrupted.","offset":3654,"duration":14},{"text":"Rory: And some part of that is as you pointed out to me when I got it wrong a few episodes back, AI related in terms of recommendation engines. But I think a lot of it is just, you know, a very competitive attention economy. You're right. Fortnite was the—was the game everyone talked about now it's not. It's the nature of the gaming industry. So yes. What—what does that mean?","offset":3668,"duration":19},{"text":"Jason: It's the Fortnite circle coming for everybody at the end.","offset":3687,"duration":4},{"text":"Rory: Oh, yeah, yeah. The little circle.","offset":3691,"duration":2},{"text":"Jason: For everybody, even Fortnite. The Fortnite circle has come to Fortnite itself. It is surrounded itself. Poor Epic Games is in the middle of its—of its endgame of Fortnite.","offset":3693,"duration":10},{"text":"Rory: It's just hidden content creators shooting it out at the very end. It's coming for all the—the Fortnite circle's coming for all of us.","offset":3703,"duration":8}],"startTime":3476},{"title":"Geopolitical Risk: Mannus Founders Trapped in China","summary":"Meta's acquisition of the AI startup Mannus hits a snag when the Chinese government reportedly detains the founders. The hosts reflect on the severe geopolitical risks of \"Singapore washing\" and investing in Chinese-founded companies.","entries":[{"text":"Harry: The other one that—relatively was—I think maybe a little bit overlooked is reports of Mannus founders—Mannus obviously for context being bought by Meta recently. Um, Mannus founders trapped or kept in China.","offset":3711,"duration":14},{"text":"Harry: So just again, give people context and then put out one question mark there. Mannus was a company originally based in China, had some Chinese investors, then redomiciled to Singapore, Benchmark invested, effectively refounded as a US-Singapore company, Meta acquired it.","offset":3725,"duration":19},{"text":"Harry: I want to say—and I use the word past tense \"acquired\" because my understanding is the transaction's closed and the money's moved, though interestingly, not a ChatGPT nor Anthropic were clear on that, but my understanding is that's what happened.","offset":3744,"duration":13},{"text":"Harry: But then now the latest thing is two of the—the Chinese government has—takes a dim view of this because they don't want Chinese talent leaching overseas and going to the US and effectively not being Chinese anymore and they—they—they feel it as a brain drain.","offset":3757,"duration":17},{"text":"Harry: So they did something that was, you know, pretty coercive in the sense of two of the key founders of Mannus, I think, were either in China or summoned to China and they're no longer able to leave.","offset":3774,"duration":13},{"text":"Harry: So that's—those are the facts. And of course you care. I mean, I think that—well, starting from the scratch. I mean, that sucks.","offset":3787,"duration":7},{"text":"Rory: I wish them the best because that's not a pleasant place to be. I mean, I think you've had the Jack Ma thing of, you know, at Alibaba, of effectively going as it were under the radar for a few years when you kind of incurred the displeasure of the administration. You also have people who've had significantly worse consequences than that. So let's start with the basic: you wish them all the best, right?","offset":3794,"duration":22},{"text":"Jason: I don't think another deal like this would happen, do you? I think this whole Singapore washing thing is over. It's over.","offset":3816,"duration":6},{"text":"Rory: I totally agree. That's where I was going to go with that long preamble. I'll tell you who didn't notice: maybe no one in America spent any time thinking about it, but every Chinese founder who was thinking about doing this is going, \"Hmm. Hmm. I don't know how I feel about this. I don't know if I can do this deal. I do know if I do this deal, I am never going home again.\"","offset":3822,"duration":17},{"text":"Rory: I'm with you, Jason. I think all these other China washing deals, they're put on pause or they're put on reevaluation. It's—next thing it's going to sound harsh. It's a fairly coercive regime. If your family's not out of the country, do you have exposure there? Right?","offset":3839,"duration":15},{"text":"Rory: I think it puts—it just shows, I mean, authoritarian governments can take pretty dramatic steps to impact their citizenry if they want to. And I agree, Jason, it makes it really hard to imagine doing another one of these deals without being worried about this consequence. And hopefully they'll kind of go \"naughty you,\" pay a 50%—like, you know, California makes it hard to leave too, but if you pay them 13%, they'll let you go to Nevada, right? Yeah, hopefully it turns out to be something like that and please God it's not something more, you know, coercive. But I agree, Jason, wouldn't do another one.","offset":3854,"duration":33},{"text":"Jason: You know, in venture you take risk, right? It's part of the job. So we've all had deals where there's some rule, some corner that was cut and we talked ourselves into it's okay, right?","offset":3887,"duration":11},{"text":"Jason: This is—companies—something weird about this company but—and we convince ourselves as—as—talking to some mediocre lawyer or asking an LLM today that it's okay. So like this Singapore washing must work, right? They've moved to Singapore, it's got to work.","offset":3898,"duration":15},{"text":"Jason: And you convince yourself, you talk to a few people and you take the risk and it—it—it appears to have bounced the right way for Benchmark and friends, right? It appears they've gotten their money. But you don't do the next one, right?","offset":3913,"duration":11},{"text":"Jason: And there's 242 millionaires in Singapore, the majority of the inflow is Chinese. You don't do the next deal. I mean—and that—maybe other capital does the deal and that's fine, right? Capital is fungible, but you just—in venture you just don't—you just can't do the next one like this. It's too risky.","offset":3924,"duration":13},{"text":"Harry: What do you do if you're Meta? Part of the asset you're acquiring is the team.","offset":3937,"duration":4},{"text":"Jason: 2 billion's not a lot for Meta and they have the product.","offset":3941,"duration":3},{"text":"Rory: Yeah, what are you going to do, Harry? What would you recommend? Getting angry at the Chinese? That'll work well, right? I mean, I think it'll be, you know, a yet another acquisition that looked clever, but in retrospect wasn't anything.","offset":3944,"duration":15},{"text":"Jason: Well, listen, for Meta, I'll just say one thing. I—I only have a tiny bit of information, but I—it appears to me Mannus is running mostly smoothly as an application and a company. Now, I don't know if the founders are working out of, you know—I certainly feel strongly when you lose your founders you lose your heart and soul of your company, but in the short term, I—I don't think it's a big deal for Meta outside of the founders because it's running smoothly, right? That—that's my—in the short term. The—the—it's not down, the team's functioning, they're running. And um, but it's crazy.","offset":3959,"duration":30},{"text":"Rory: And at the risk of being Pollyanna but also wanting to assume the best of people, I would hope that the Meta management team and board, to the extent they do have any influence, can help these guys come to an amicable end and if it requires a tax settlement or whatever, you know, just—you don't want to leave—you don't want to leave people you just acquired in limbo.","offset":3989,"duration":19},{"text":"Rory: At some zoom out level, when you listen to the rhetoric in both capitals, you just have to realize that trying to tread between those two—these two countries is pretty hard right now.","offset":4008,"duration":10},{"text":"Rory: Right, you know, yeah, we have China Hawks in the US government, they obviously have a whole ton of US Hawks or whatever the equivalent is. There's a real perception of competition. Yeah, we don't let them buy the Nvidia chips, etc., etc. You're playing with fire in that thing and sometimes it bites you.","offset":4018,"duration":17},{"text":"Jason: I just think overall, it's natural in given the outcomes in AI and given the growth, that I think it's tied to taking the highest levels of risk we've also taken because the payoffs seem to be there. And when this deal happened, folks kind of thought this was aggressive, Benchmark's never done a deal like this, why are they doing a deal like this? It's not even very cheap, right?","offset":4035,"duration":18},{"text":"Jason: It seems a little crazy. And they're like, \"Well, we've never seen anything grow like this and the team's incredibly talented,\" right? So they took a little bit of risk and um, and they made their—made their profit. We're all taking more and more risk. Folks that, you know, now it's a week of revenue at a Demo Day. I did a million dollars my first week. It's amazing. What about the second one? I don't know.","offset":4053,"duration":18},{"text":"Jason: Like, uh—but as long as it all works out in the aggregate. And I think this is why nobody cares to Harry's point. I cared about Mannus, I added it to the list. I don't think anybody cares. We're all focused on getting a million dollars our first week.","offset":4071,"duration":13},{"text":"Rory: Just good realization that the worst thing that can happen is not just, \"Oh, you lose your money.\" There are worse outcomes than that.","offset":4084,"duration":10}],"startTime":3711},{"title":"Capital Flight and California's Wealth Taxes","summary":"Steve Jurvetson relocates from California to a tax-friendly Nevada residence ahead of major liquidity events. The group debates how aggressive state wealth taxes ultimately drive ultra-high-net-worth individuals away, resulting in lost tax revenue.","entries":[{"text":"Harry: I mean, speaking about cooling their shot on making billions of dollars, Steve Jurvetson... he's tied his career to Elon very smartly, so that's not in any negative way in terms of the investments that he has plowed, trebled, doubled, quadrupled, everything in between.","offset":4094,"duration":16},{"text":"Harry: Uh, leaves California, buys most expensive home in Incline Village. And—and these were Jason's words—will anyone with liquidity be left in California? What if California is structurally bankrupt?","offset":4110,"duration":14},{"text":"Jason: Well, I mean, yeah, it's not a great sign when they keep leaving, is it? It's not a—it's not a positive.","offset":4124,"duration":7},{"text":"Harry: But Rory's staying, Jason.","offset":4131,"duration":1},{"text":"Rory: I mean, look, all—first of all, you're exactly right. All credit to Steve and all power to him. Known him intermittently for 30 years. He made a brilliant call to align with SpaceX, being on the board of Tesla and SpaceX.","offset":4132,"duration":15},{"text":"Rory: Tesla for a while and then came off obviously for those back in the day, but SpaceX too. Yeah, he's—he's put his money in a compounding machine and now he's clearly hit the DPI moment.","offset":4147,"duration":9},{"text":"Rory: Right, but yeah, going back to the thing. Yes, capital—I mean, the truth is this: that's why we said last week, high—ultra high net worth people have a high degree of mobility and unfortunately, if you put the hammer up too high, they can leave and choose to go across the border to Incline Village and save 13% on, um, any realized gains, plus as we've pointed out, 5% on all gains if this wealth tax passes.","offset":4156,"duration":26},{"text":"Rory: You know, at the margin, why wouldn't you? You know, it's not like you need to be in California to be a Tesla board member or a SpaceX board member given they're down in Texas. So yeah, actions have consequences.","offset":4182,"duration":13},{"text":"Jason: Well, it's interesting also this week, um, Washington state did pass their 9.9% state income tax for millionaires. And the governor said—the—the reason the governor said it's signed because there were a lot of folks who said, \"Don't do it,\" right? It's already Howard Schultz left.","offset":4195,"duration":14},{"text":"Jason: He said today, he said, \"Well, they just deserve to pay more.\" And that may well be true. It may well be true. Like, I don't want to debate that. This is not political, right? I'm—I'm more concerned about the tipping point when uh, we kill golden geese.","offset":4209,"duration":16},{"text":"Jason: You know, there's been—Washington and California and to a lesser extent New York have been the gold—golden geese. It's, uh, you know, Washington said they're going to lose money, they're not going to make money on this. It—it appears that most folks that are neutral or right have said California will lose money on the billionaire tax, everyone's left.","offset":4225,"duration":16},{"text":"Jason: And the tax itself assumed massive amounts from Larry Ellison who's been gone a half decade, right? So no one's going—it's just I do—I do worry they're all—they're all—they're all leaving.","offset":4241,"duration":11},{"text":"Jason: Everyone that doesn't work at OpenAI and Anthropic. Uh, you know, on this show we've done it 50 and I said in the beginning of this that you leave after the series B and I—now I see that used again and again by these folks who are on the right on it. They say all the founders leave after the series B, but it may happen by show 100.","offset":4252,"duration":17},{"text":"Rory: And one of the arguments I'd make is, because you know, the truth is this: articulating the argument to the—to, you know, the activist on the other side as being, \"You're being mean to the billionaires,\" is of genuine no interest. In being mean to a billionaire is actually a feature, right?","offset":4269,"duration":18},{"text":"Rory: But I think the real articulation is this: if you—you actually are losing revenue that won't be available to California and the marginal dollar in California probably goes into home—you know, payment for homelessness, payment for young—kids, payment for foster homes, payment for marginal social welfare services that are easy to defund when times are tough, right?","offset":4287,"duration":18},{"text":"Rory: And by choosing to obtusely tax without any attention to ability to collect that money, you've actually reduced the revenue that's available to you, right? And that's the argument you have to make to the—to someone on the other side of the table: You have literally chosen something.","offset":4305,"duration":13},{"text":"Rory: Instead of getting, you know, 250 million—I don't know, pick a number, 50 million from the Larry and Serges and the Jurvetsons of this world, you went for 200 million and now you're going to get zero.","offset":4318,"duration":11},{"text":"Rory: And what that means in real terms is somewhere down the line, long after all these changes have been made, somewhere in Sacramento, someone will zero out a line item on the budget and let me give you a clue: it won't be payments to the teachers, it won't be payments to the firemen, it'll be marginal services to marginal people that your crass stupidity and desire to make a political point has ended up costing them money. And that's the only argument that moves the needle because it—because it's true. And you're right, Jason, you're saying is that it will have a net negative return. How do—now do you feel good?","offset":4329,"duration":35},{"text":"Harry: Rory, if you were Steve, would you have left?","offset":4364,"duration":3},{"text":"Rory: I think from my perspective, I'm just so glad to be in California. It's so wonderful. I moved around a lot early in my life. I have my friends here, I have my life here. At the margin, the whole point of having money is to be able to do what you want, and for three or four or five or even 13% of your income, do you really want to leave?","offset":4367,"duration":16},{"text":"Rory: Now, I will say this, that's why you can tax income relatively highly because it comes all the time and you can't control timing and therefore you have to uproot your whole life for the rest of your life to avoid it, and I don't think it's worth it. So I wouldn't move to avoid income tax.","offset":4383,"duration":16},{"text":"Rory: Conversely, if you have this pending capital event where literally in one year you're going to sell quote all your SpaceX stock and realize a $2 billion gain and you're going to pay an extra 13% of that in California, it's $260 million. Maybe you turn to your wife and say, \"Honey, for the next two years, why don't we live in Incline Village 165 days? I'll pay for the plane, we'll go back every week, you won't lose contact with anyone and we will save $260 million.\"","offset":4399,"duration":23},{"text":"Rory: And you go, \"Hmm. That's real coin.\" So and that's the point about, you know, that's not the life I lead, that's not the situation I'm in, but that's the argument you make. It's like, it's not crazy.","offset":4422,"duration":12},{"text":"Harry: That's real coin, baby.","offset":4434,"duration":2},{"text":"Jason: That's real coin.","offset":4436,"duration":1}],"startTime":4094},{"title":"The Myth of VC Value Add","summary":"A humorous exchange between VC Ron Conway and Cloudflare CEO Matthew Prince sparks a discussion on venture capital value add. The hosts concede that while VCs love to feel helpful, founders rarely remember their minor contributions in the grand scheme of building a company.","entries":[{"text":"Harry: Is—is there any story that I haven't hit on, guys, that we should hit on?","offset":4437,"duration":3},{"text":"Jason: I just have to bring up the Ron Conway Matthew Prince one because it was so—I highlighted that one on Twitter. It was just the funniest thing in the world.","offset":4440,"duration":10},{"text":"Harry: And uh, you know—","offset":4450,"duration":1},{"text":"Harry: Just for context, do you want to provide some context?","offset":4451,"duration":2},{"text":"Jason: Yeah, I don't know Ron Conway, but he's certainly viewed as one of the Silicon Valley gems, right? Seed investor in so many leaders. Always out there as an advocate everywhere, um, probably could have retired years ago, right? Very founder-centric.","offset":4453,"duration":14},{"text":"Jason: And he wrote that he had helped Cloudflare navigate some very significant issues earlier in the day. I think on Jack Altman's podcast, yeah, on Uncapped. And they asked Matthew Prince, CEO of Cloudflare, the question, he said, \"Well, maybe, I don't remember any of that.\"","offset":4467,"duration":14},{"text":"Jason: And it's just—it's not—and he wasn't mean. Matthew can be fairly, uh, sharp as—as Harry knows these days. It wasn't meant mean, the tweet was not mean. He literally just memory couldn't remember getting any help from this beloved VC.","offset":4481,"duration":14},{"text":"Jason: And I think it just said so much to me about VCs adding value, but also VCs thinking they add value. VCs possibly adding a modest amount of value but founders not really thinking that modest value was consistent with the bravado of the VC.","offset":4495,"duration":14},{"text":"Jason: It just—it just—it just crystallized the whole value add idea to be in a single tweet. It wasn't mean, it's just, \"I don't remember any of—I don't remember Ron helping, but maybe he did.\"","offset":4509,"duration":10},{"text":"Rory: Yeah, I—you're right, Jason. I—I did laugh at that. And I think it does—I think actually my big takeaway to your point is both to some extent are right is that, you know, as a—we all want to have agency, we all want to feel we help and, you know, want to be good people and you look and you go, \"Hey, I spent some of my time helping this CEO. I feel I helped.\"","offset":4519,"duration":18},{"text":"Rory: But from the company's perspective, they're founding a company, they're doing a million things. On one or two things on a 10-year journey you helped, you remember that vividly. They're like, \"Dude, it just fades into the background of, you know, a hundred things,\" and you know better than me, Jason, they have to do every day, right?","offset":4537,"duration":16},{"text":"Rory: And the truth is this. I—one of the proofs of this is—interest the way to check it—is I often read business biographies and business stories of great companies, venture-backed companies, and how they were formed and what happened.","offset":4553,"duration":18},{"text":"Rory: And you know what I notice in them? Every single one of them: very few little mention of the VCs. If you just read them, you—you eyeball them, see says, \"Oh, there's a biography they—\" Yeah, and they crop in and come out a couple times, right?","offset":4571,"duration":13},{"text":"Rory: And I think that's right because realistically in the journey of what's going on, the only significant things we do—and I said this before in the podcast—we put in the money and we put in more money when they need it. We decide to hire or not hire or fire the CEO, we agree the broad strategic direction, and anything after that is at best an assist, right?","offset":4584,"duration":20},{"text":"Rory: And if you read the biographies of businesses, what you generally see is the only time the VCs come in is on some version of those, right? And it's, you know, five pages of the journey early on interspersed over 200 pages in the first five chapters, and by the time they get to the IPO, don't even rise to the level of a thing, right?","offset":4604,"duration":15},{"text":"Rory: I was reading the, you know, the OpenAI biography, the—a bunch of them recently. And that's just the way it is. Microsoft biography, same thing, right? You know, so don't—I mean, and you—the VC can feel those five minutes of impact were amazing and they feel really good about them and you feel warm and fuzzy but, you know, the only thing founders really remember for better or ill is, \"Oh my God, our backs were to the wall and no one would put in money and they put in money.\" They remember that.","offset":4619,"duration":29},{"text":"Jason: Some—some—sometimes. In my experience, sometimes, Rory.","offset":4648,"duration":3},{"text":"Rory: Sometimes they even forget that. Well, but to your point, Jason, if they forget—","offset":4651,"duration":3},{"text":"Jason: At least half the time they forget that.","offset":4654,"duration":1},{"text":"Rory: If they forget that, they're definitely going to forget the time you made that phone call to help them connect with XYZ and that helped them do something because that's something that happens a hundred times a day. No, you're right.","offset":4655,"duration":10},{"text":"Jason: Yeah.","offset":4665,"duration":1},{"text":"Rory: We're not the stars in the drama. We're—we're just bit players who get well paid for our part.","offset":4666,"duration":6},{"text":"Harry: Boys, as always, the most humbling 90 minutes of my week.","offset":4672,"duration":3},{"text":"Jason: I'm afraid you'll get more.","offset":4675,"duration":2},{"text":"Rory: You'll be humbled tomorrow.","offset":4677,"duration":2},{"text":"Harry: You'd be surprised.","offset":4679,"duration":2},{"text":"(Audio ends)","offset":4681,"duration":15}],"startTime":4437}],"entries":[{"text":"Host: So, we start with Anthropic’s monster week. We may be at the stage where we throw the humans under the bus, not the AI anymore, which I think at some level is pretty terrifying. We move to OpenAI killing Sora. I think shooting in the head is even more significant. A big part of the whole strategic direction of the company was flawed. Agreed. You’re saying the economists, the accountants have wandered into the room and they said, \"We have a scarce resource here, let’s optimize it, let’s devote this compute to the people who can pay the most for it.\" And then we finish on the man with the biggest balls in tech, Masa. You haven’t lived until you’ve seen an 85% decline in an index. This is one where it’s just back-asswards. I don’t believe there’s right or wrong in money, there’s just money. I just don’t think raising at 5 or 8 billion when you’re at 80 million or 100 million of suspect ARR is the most exciting accomplishment in the world. But let me be direct: get the fuck over it. You should conform your company around your customers and your model, not your VCs. Being mean to a billionaire is actually a feature. Ready to go?","offset":0,"duration":65},{"text":"Host: Boys, welcome back. It is this week in Anthropic, otherwise known as the SaaSstoberfest, which has been renamed. Uh, I want to start with, you guessed it, Anthropic. Unbelievable 28-day month of February where they did 6 billion in revenue, which was more than Databricks has done in their entire lifetime.","offset":65,"duration":25},{"text":"Host: Do you know what I think was the most interesting news out of Anthropic this week? It was actually the—the accidental leak of Claude Mythos, essentially 3,000 unpublished assets leaked. Uh, it’s a 10 trillion parameter model, apparently, that is this next-level step change in capabilities that they’re not releasing because of how powerful it is. This is by far the most interesting to me. Jason, how did you think about this news?","offset":90,"duration":29},{"text":"Jason: Well, look, obviously it’s embarrassing, right? To—to Anthropic to—to leak it. Uh, I actually just think we’re going to see more and more of this accelerate. Uh, the faster we vibe code, the faster we ship, the more corners we cut in general on application-level security. It happens. I mean, so many folks are accidentally uploading code to insecure GitHubs, to—to databases, to Supabases that are by default open.","offset":119,"duration":34},{"text":"Jason: So this is—this is accelerating. Uh, our data which is just open on the internet. And—and you could say, \"God, it shouldn’t happen at the Anthropic level,\" and I’m sure someone will get—will get scolded, right? I’m sure it will. But overall, this is accelerating, and it’s going to accelerate even more as we let our AI agents make decisions. Our agents are going to decide where to put code, they’re going to decide what level of security to use, and this is going to become happenstance.","offset":153,"duration":27},{"text":"Jason: And, you know, it’s funny, I mean, uh, people are like, \"Oh, how could Anthropic have a new, uh, security agent and have this happen at the same time?\" I think they—they—I think it makes perfect sense. The Anthropic AI security agents, which are basically used in Replit, are very, very good, and it also makes sense as we rush, we’re going to leak source code, data, PII, right? It was—I don’t know whether it’s happened, it was reported today all of Mercure’s data leaked. It’s being held hostage, all of it, every single interview, every single piece of PII, every single piece of humans.","offset":180,"duration":43},{"text":"Jason: And so, uh, you know, we used to mock these. I think it’s going to start happening daily and weekly in the agentic era, and it doesn’t excuse it, but—but it’s—uh—it’s a reality. Agents—agents are goal-seeking and agents are going to make—not only are they going to make the same mistake as humans, they’re going to work a thousand times faster. So even if they make the mistakes 10% as often, Rory, help me with the math, if they do a thousand times more productive, they’re still going to make a hundred times more mistakes. So we’re going to see it everywhere.","offset":223,"duration":34},{"text":"Rory: Again, just for perspective, because there’s two things going on here: Anthropic—some data leak from Anthropic about their new model Mythos, which of itself is meant to be amazingly powerful in dealing with cybersecurity, and there was a whole consequence that we’ll talk about in a second in terms of how that impacted cybersecurity stocks. But as Jason pointed out, the level of irony here is acute because it was an inadvertent leak. So you had the situation where a model that’s meant to be amazing for cybersecurity actually leaks via cybersecurity leak. So that kind—so we’re toggling between the two.","offset":257,"duration":39},{"text":"Rory: On the cybersecurity leak, it was noteworthy that Anthropic, quote-unquote, \"blamed human error,\" right? We may be at the stage where we throw the humans under the bus, not the AI anymore, which I think at some level is pretty terrifying. But—and you know exactly what happened. You see this, I mean, uh, down in the weeds. You often see this where, you know, you’re about to do a big announcement, you have your content management system, you stage all the assets, you know, be it the Fed press release. In the UK, it happened on the budget, if you remember, Harry. The budget—you have the press release ready to hit play the minute the budget is ended and someone inadvertently forgets and puts it on the public site in advance. It’s the same thing here. So it probably was a human error. There was a whole bunch of content ready for, I don’t know, pick a date though, March the—May 15th announcement of Mythos, they forget to secure it correctly and out it goes.","offset":296,"duration":58},{"text":"Rory: So—so that’s the first thing, right? So that’s kind of—that’s the embarrassing part of it. And then the interesting part of it, and you really do have to do this without sniggering, despite the fact that it all leaked, you also have to separately talk about the fact there’s some big claims on Mythos, right? At—at Anthropic were making via, again, via this leaked memo. Reminder, no one else has seen it, uh, the—the actual model—um—at least not publicly available, obviously some people have seen it, but not publicly available. And even I was trying to get copies of the leaked memo. There’s just a few screenshots at this stage; it’s hard to track it down, at least quickly anyway.","offset":354,"duration":42},{"text":"Rory: But the statement is: it’s way more powerful. Second thing is it’s going to be way more expensive for them to serve, and therefore it’s going to be way more expensive for customers to buy. And then the third thing is a particular focus on cybersecurity. It’s meant to be, quote-unquote, \"extremely good\" at detecting cyber issues, and the result of that, and—the result of that was an eight, four or five percent decline in the average cybersecurity stock last Friday when this leak happened.","offset":396,"duration":34},{"text":"Jason: Yeah, just two, maybe two other things on the leak, just for—this tradeoff, um, you know, I’m dating myself, but when I was at Adobe and we were acquired, we were an early customer of GitHub. Um, and so we were putting source code in the cloud, and that was banned at Adobe at the time. It was banned because their source code was their crown jewel. It was pretty easy to—to make a crappy PDF reader or a crappy image generator, but to do what Photoshop or Adobe Acrobat did, all the exceptions, all the corner—the thousand—tens of thousands of corner cases was the crown jewel, right? Of the company.","offset":430,"duration":43},{"text":"Jason: And so everything—we got the first exemption to be able to use source code in the cloud, and pros and cons. But when—when they use this on-premise source code management tool, it took a month to do a release. A month. A month, okay? Now we’re doing 60 releases a day, right? Or even Anthropic, fastest-growing enterprise company of all time, is still doing massive releases every month or two and dropping features every day, right? So we went to something that took 30 days at a tech leader to something that takes hours. There’s trade—there’s tradeoffs there, and I’ll—I’ll take them.","offset":473,"duration":45},{"text":"Jason: But we’re going to see it explode. In terms of, like, the stuff that was published today, going back a few threads on show number 50 to Rory, one of the things that I thought was pretty cool in Kairos was two things: um, always-on background assistant that works constantly. Our AI is working with us 24/7. And agents that can sleep, wake, and self-resume without any prompt. The autonomous agents, which I’ve been talking about how this is going to consume orders of magnitude more tokens and change our lives, I’m—I’m excited to see more coming.","offset":518,"duration":46},{"text":"Jason: And, you know, Open Claude was just this—this brief thing that woke us up to what Anthropic appears to be all-in on. Truly autonomous agents running 24/7, hopefully more safely, hopefully not leaking all of our source code. But it’s coming soon, right? Not these—you know, this whole idea that we’ve been doing—since when we started this podcast, you went onto ChatGPT or Claude—no one had heard of Claude when we started this, I was the quirky guy using Claude—and you’d talk to it and go back the next day. The next release is going to be on all the time, all the time, debating Harry’s latest investment. Was it big enough? Is he too concentrated in the fund? Where should he go? What was Rory thinking on that deal, right?","offset":564,"duration":40},{"text":"Host: Why was Rory abusing Harry by email again for the second time in a day?","offset":604,"duration":5},{"text":"Jason: Again, we laugh, but this is the future. I—I’m excited to see it coming sooner when our agents are 24/7. Like, they’re literally around us and we give up all of our personal freedoms and autonomy as part of it.","offset":609,"duration":15},{"text":"Host: I hear you on the embarrassment of it being leaked and, you know, the human error element. But while Anthropic has Mythos, which is supposedly as powerful as it is, you’re juxtaposing that with OpenAI fucking around with killing Sora, kind of ads not really working and people being unhappy with it, and it seeming like this massive chasm of the progression of force that is Dario and Anthropic continuing faster and harder than ever with a faltering, confused, and dazed OpenAI wandering around the product desert trying to find some water.","offset":624,"duration":42},{"text":"Rory: You’re just being mean. I mean, again, as I said last week—and I’m sorry to repeat myself—","offset":666,"duration":7},{"text":"Host: Is that not fair?","offset":673,"duration":2},{"text":"Rory: Yeah, but—again, narrative is overdone on both sides, right? So—I think some parts of it are true. Obviously, you throw in a bunch of different things. The decision to shoot Sora in the head, right? Almost certainly a good decision. Look, it’s obviously embarrassing to say something is going to be amazing less than four or five months ago and then shoot it in the head. But if it’s a mistake, give them credit for at least saying it’s a mistake, move on, right?","offset":675,"duration":28},{"text":"Rory: And yeah, that relationship with Disney—again, I think I’m going to give you—it wasn’t me, I was sneering at it in real time when it happened, I think someone else on this podcast said it’s really significant, just saying, right? It’s Crotchety—","offset":703,"duration":16},{"text":"Jason: I do, I—I think it’s massively significant. I think shooting in the head is even more significant. Um, I think saying that the entire—a big part of the whole strategic direction of the company was flawed. Agreed. The whole that we are going all-in on consumer, the—from what I read, Sora made single-digit millions of revenue, right? And was consuming a million a week, which actually sounds way too low, right? It must—it must have consumed billions and made single-digit millions. It makes no sense as a product, either in the short term or the long term.","offset":719,"duration":39},{"text":"Jason: But if you want to own the whole consumer experience with AI, you’ve—they decided we have to own image and video, and Anthropic never even attempted to do it, right? So it’s a massive retreat. It doesn’t mean it’s the right—it’s probably the right decision, to your point, in fact almost certainly is. But man, that’s a—\"Our strategy was wrong.\" Like, this is a huge own goal. \"Our strategy was wrong.\"","offset":758,"duration":25},{"text":"Rory: Agreed. But I—and I agree with that, but I still think—as I say, I still think Harry’s over—kind of overegging it a little bit because, look, you made a comment about ads that I think is—uh—hypothetically—um—effectively implying that the ad strategy hasn’t worked. That’s a bit of a bigger leap. I mean, Sora hasn’t worked, they’ve killed it. I think I’m with Jason, I think that’s smart because I think one of the things you’re seeing right now is in a world of scarce compute—and astonishingly, despite all the investments that we’ve seen in terms of actual available compute for people to sell AI on, we’re in a scarcity mode. You don’t devote compute to things that are highly compute-intensive and low revenue-intensive. I mean, it—and Sora was almost the definition of that. Video generation is extraordinarily compute-intensive, relatively speaking, and the revenue is almost minuscule.","offset":783,"duration":71},{"text":"Rory: Conversely, you know, CoGen, while it is compute-intensive, is orders of magnitude less compute-intensive and there’s real dollars attached to it. So you’re literally—what’s happening right now, I actually think at a higher level, it’s actually very healthy. You’re seeing the economists, the accountants have wandered into the room and they said, \"We have a scarce resource here, let’s optimize it, let’s devote this compute to the people who can pay the most for it.\" So that’s the Sora comment.","offset":854,"duration":56},{"text":"Rory: On the ads comment, Harry, yeah, it’s early days for, you know, ChatGPT ads. But again, I cite that quote that Brian Kimball did that was really good. Of course they’re going to run damn ads because there’s no other way to build a mass consumer business, and they’ve no choice, right? Because, you know, their consumer conversion rates run roughly 5%. It gets them to a—I think a roughly 10, 15 billion dollar consumer business, right? Out of their 500 million uniques or whatever it is.","offset":910,"duration":36},{"text":"Rory: So one of two things has to happen in the consumer business—again, I’m going to leave the enterprise business out. On a consumer business, either A, they take that conversion rate to a number we’ve never seen before from a typical consumer business—I think that’s unlikely, I don’t think most consumers are going to pay 20 bucks a month for this—or option B is you make an ad business work. They’ve got no choice but to make it work. And by working, I don’t mean a hundred million dollars. People are kind of ragging on the hundred million—it’s in the noise, it’s scale. Big picture here: Facebook and Google each do 200 billion, plus or minus, a year in digital ads. If these guys aren’t doing 20 billion within a couple years, they’re not even in the game. And to get to the market cap of—I mean, remember, Facebook has a 1.7 whatever it is trillion market cap doing 200 billion. Alphabet/Google has a 3 trillion market cap doing 260 billion plus thing. If they’re going to grow into their market cap on the consumer side, 20 billion’s not enough. They have to do 50 billion, 70 billion of ads. So unlike Sora, this is not going to be a \"try the ads and then fold.\" This is a—there’s only two existential bets for this company: one of them is ads to make the consumer business work, and then the other is \"Oh my god, we should have done coding all along. Let’s get a competitive coding and enterprise model out there and compete with Anthropic on that side.\"","offset":946,"duration":89},{"text":"Rory: So those are the only two things they’re doing and they’re the only two things they should be doing. It’s straightforward. I mean, I actually see this as good news. Like, at least they’ve—like, we’ve gone from the \"let’s wander around the woods feeling cool building shit\" to \"there’s only two things to do, let’s get them done.\" I—it’s net—it’s a positive. Better late than never.","offset":1035,"duration":20},{"text":"Jason: Man, did you—did they had the Wall Street Journal this week? They had—they had a story of why Dario left—OpenAI. Did you see that story?","offset":1055,"duration":9},{"text":"Rory: Oh, that was juicy. Yeah.","offset":1064,"duration":2},{"text":"Jason: Yes, I did. I mean, the amount of tension at OpenAI. The fact that Greg Brockman attempted—recruited them and no one would work for him. He and—and his sister would not work for Greg Brockman, would not talk to him, they would not allow him to be part of the LLM or G-T-P groups. Then Sam had to constantly tell each of them that they were in charge, right? Told Dario he was the boss, then told Ilya and Greg they could fire him at any time if they wanted to fire Sam, right? Then begging—then Dario to come back, then Dario saying he would stay only if he directly reported to the board and nobody else. I mean, the level—and then—and then finally firing Sam and then bringing him back and then Sora and de-Sora and we’re not doing coding. It’s just—I mean, I’m exhausted.","offset":1066,"duration":55},{"text":"Jason: I—maybe I’m wrong. I have to think at least someone like me would feel much more comfortable in Anthropic where it appears there’s a much more consistent process and leadership, right? Same founders, same things, same goals. It just—I have to think a company organized like that is just going to ex—out-execute someone with that level of drama. I—I almost can’t take it.","offset":1121,"duration":26},{"text":"Host: You’re going to kill me for this, Rory. Is the best thing for OpenAI not to buy Sierra, incorporate that as its customer support product, and have Bret Taylor come in as the day-to-day CEO and Sam can be fundraiser, Sam can be master of—","offset":1147,"duration":17},{"text":"Rory: I’m not in the boardroom, so—you know, I hear—look, at the end of the day—at the end of the day, I think you’re right, Harry, and I would favor that as a board member, but I’m not going to say that publicly because I don’t want Sam to break my balls. I am too unimportant for Sam to even give a shit about, right? So I don’t worry about that at all.","offset":1164,"duration":36},{"text":"Rory: So let me say this delicately. That amount of board-level and senior-team-level turnover over an extended period of time is probably the highest warning signal that you could have as a board member about how your CEO’s doing, right? And if it was anything other than a founder—let’s put it this way, if it was anything other than a founder-led company and this level of drama was going on, you’d probably be having—you’d probably sit down with the CEO and asking how’s it going, at least, and what are you thinking of doing about this? I don’t think you turn on people just when things go to shit, but you probably want to cut down the drama from here, build a team, and try and call a shot and play it for more than 24—you know, for more than six months at a time.","offset":1200,"duration":49},{"text":"Jason: Well, when you’ve—when you’ve worked at or observed startups where the CEO is spending so much of their time load balancing talent that can’t work together versus when you’ve worked at one or with one where the talent’s rowing in the same direction—to say that it’s night and day would be an understatement, right? It’s like the—the back side of Pluto and the front side of Mercury. And it’s just—and I think Sam—we could criticize him, actually when I read the—everything I’ve seen and then when I read the Wall Street Journal article, it’s like, \"My God, this guy has to spend so much time load balancing the drama of these extremely brilliant personalities that just, oh my god, that can consume number—most of your time as CEO. Most of your time load balancing.\"","offset":1249,"duration":45},{"text":"Rory: You’re exactly right. It is the drama of—we’re not dealing with a bunch of people just trying to crank out some B2B software and make a paycheck, we’re dealing with people who are angsting about whether this is going to change the world, who have fears about the technology, who have, yeah, desires to be seen as credited for the technology despite their fears about it. This is a—I mean, as is often the case, extraordinary talented people come in an extraordinary high bandwidth—a—demand on attention and care and feeding. It’s probably—it’s been a real slog, I’d say.","offset":1294,"duration":33},{"text":"Host: Okay, the man with the most balls in investing, Masa Son. SoftBank gets $40 billion bridge loan to buy OpenAI stock. How deep can Masa go?","offset":1327,"duration":17},{"text":"Rory: He’ll go as deep as they let him. I mean, that’s the one thing we know: if they give him another 20, he’ll borrow that too, right? I mean, look, this is a—I actually checked the SoftBank—you’ve got SoftBank holdings—I have to be careful, there’s the Telco Group which is mod—reasonably levered at the Japan level, and then SoftBank Group is around 2x levered. One and a half to 2x levered in terms of equity, right? What that means is a 30-40% decline, you know, wipes them out, right? It’s a very aggressive stance, right?","offset":1344,"duration":37},{"text":"Rory: It would be like me taking our $800 million venture—$900 million venture fund, borrowing 1.8 billion, and investing it all, and if, yeah, if it works I make—you know, I really juice my return, but if it goes wrong by 30% I’m done, right? And it’s just—it’s super aggressive. I mean, I suppose his lesson is Masa survived 2002 when I remind everyone the NASDAQ went down 85%. You haven’t lived until you’ve seen an 85% decline in an index, right? And obviously if that happened or anything like it, um, you’d just be way underwater. Right? So it’s a—it’s a fairly high amount of leverage for an investment fund to say the least.","offset":1381,"duration":43},{"text":"Jason: Yeah, I mean, for—for sure it’s dramatic. Having said that, you know, real estate investment funds get the maximum leverage they can by design, right? They—that is how they work. I would imagine if venture had access to more debt, we—we’d all—we’d all load up on it. If we all could—if we all could do the growth rounds in your hottest company and uh maybe we would—and we could get—and we could get all the carry from it with the—and the worst thing is we leave the keys to fund seven on the table, we might—we might load up too. I’m not sure. But certainly, real estate funds load up as much as they can.","offset":1424,"duration":35},{"text":"Rory: But just pushing back again, because real estate funds load up because the cash flows are predictable, right? At the end of the day, I mean, look, in a—","offset":1459,"duration":9},{"text":"Jason: Oh, they—and they can, but they can because the cash flows are predictable, they can load up. Agreed. Right? We don’t—it’s just harder for my little fund to go to Silicon Valley Bank and borrow 200 million against—","offset":1468,"duration":11},{"text":"Rory: In the continuum of risk, I would argue the SoftBank portfolio, not the Telco company at the subsidiary level, but I would argue the SoftBank portfolio is more like Jason’s fund than it is a real estate fund. So I think it’s a high level of risk.","offset":1479,"duration":15},{"text":"Jason: Well, plus what did he lose on WeWork? 12 billion. He—he knows. He knows what it’s like.","offset":1494,"duration":7},{"text":"Rory: The two big assets from memory are uh obviously the OpenAI position and I think the Arm position, which I still think is in um the—the—the—in the holding company. And yeah, but I mean, amazing companies, world-class companies, easily imaginable a blow up with a decline 30%. So, yeah, it’s a hell of a way to live.","offset":1501,"duration":30},{"text":"Host: Speaking of declining 30% and being in the hole, we—we touched on it earlier, but obviously Mythos leak hammered cyber stocks. CrowdStrike, Palo Alto, Zscaler all down 6%. Okta, Netscaler down 7%, Tenable down 9%. Was this a justified dip, or is this an unjust reaction to Anthropic news?","offset":1531,"duration":24},{"text":"Rory: I was listening carefully to the name because I was listening carefully to the names and there’s different aspects of security, and some of them I can say, \"Yeah, maybe that overlaps,\" and then some where I go, \"That’s just a different thing,\" right? And when you listen to all the names being thrown out, you say that’s just, you know, baby with the bathwater. Because step back: how does—how does Anthropic, you know, make security better? At the code development stage, they can look at code and find security flaws. So there are companies that upfront do something like that and, you know, application security companies, and you could argue that this is a different way of doing that, maybe some of those guys will be impacted, right?","offset":1555,"duration":43},{"text":"Rory: What they’re not doing, for example, is real-time perimeter defense. They’re not in a—in a real-time basis, you know, blocking people like a firewall, right? Nor are they doing what, for example, Okta does, right? Which is single sign-on and authentication. That’s simply not what they do; it’s a different thing. And the fact that both of those kind of stocks sold off says it’s just a kind of knee-jerk reaction rather than anything thought-through.","offset":1598,"duration":29},{"text":"Rory: It will have an impact. If you were doing application security or code review for—security code review, you’re probably going to have to either incorporate how this works in your analysis or you’ll be redundant. Just as the—the coding companies, anyone kind of—just as GitHub had to roll in complete models and figure out how to adopt it, right? So for some of them, this is really going to matter, and then for others it’s like, it’s just a different thing.","offset":1627,"duration":28},{"text":"Rory: Stepping back, I think we’re in the panicky stage, right? I think we’re in the stage of because these companies are doing so well, because they’re private no one sees the numbers, because AI is so sexy and so potentially amazing, we’re at the stage now where everything can—anything can cause a panic.","offset":1655,"duration":18},{"text":"Host: Robinhood was down like 10% because Elon didn’t potentially give them the tender and was going straight through E*Trade. And that alone was like a massive blow for them.","offset":1673,"duration":14},{"text":"Jason: Obviously, there’s a panic in the market and the question is, is the panic justified, right? The panic is that this revenue is not durable, right? That’s the panic. The cybersecurity one’s really interesting. In my—in my experience and opinion, this is one where it’s just back-asswards. Um, because if you’re in the agentic world, this is the golden age of security. The number of security threats and issues is going up orders of magnitude. Claude leaking its source code, it doesn’t matter. The number of—of apps exploding, the number of—like, there’s so many mobile apps that App Store is like—it’s like a month to get your app reviewed versus a week. It is—everything is exploding. These apps are being built by agents. They’re being built in unpredictable ways. Folks aren’t looking at the code. The pace of features being shipped, products being shipped, corners being cut. This is a golden age of taking any mature category and acknowledging, \"Good news for us, there’s more threats.\"","offset":1687,"duration":53},{"text":"Jason: Good—whether—I don’t care whether it’s application level, perimeter, like—the good news is threats are exploding and the whole shtick of cybersecurity—I’m not a real cybersecurity expert, although I’m doing another investment right now for just this reason—the whole shtick in my whole lifetime has been, \"Look, you’ve got to constantly buy new products because new threats keep emerging.\" Like, this has been a golden goose of cybersecurity that has allowed new entrants to come into a conservative category. Someone like Wiz will show up and say, \"Guys, we know how to do this on the web,\" and people are so terrified of new threats they’ll take the meeting, right? This should be the golden age for new and existing investors because the threats are terrifying and you can’t stop the rogue engineers that vibe-coded something that accessed your data. This—this should benefit everybody. Like, everyone should be a rocket ship like everybody built—like everybody monetizing GPUs is a rocket ship. And the fact that the market doesn’t see it shows we’re in a—in my opinion, we’re in a true panic, which is hard to predict a bottom. But I don’t get it. Everyone should be benefiting when you see an explosion in application production and a change in the paradigm. The change in the paradigm’s good for everybody except, you know, Windows Defender from 1996. Like, it probably doesn’t help that product or whatever the hell they have, but anyone—everyone with engineers should benefit.","offset":1740,"duration":86},{"text":"Rory: I broadly agree with Jason. I mean, there might be—there are more than Windows Defender 2006 that might be impacted. As I say, some of the application security code review stuff could be. But big picture Jason’s right. Instead of having people trying to get in through your firewall, we’re everyone is now downloading an agent, giving it full root access to their computer, and telling it have a go, and as Jason just pointed out, work overnight. It’s going to—I mean, no one yet—it’s funny, we—my colleague Errol who does a lot in the security side, we’ve been looking at a lot of these companies. No one yet knows the exact approach that we’re going to have to take to defend against agents running within the organization, but everyone 100% understands that this is a—emerging mega-threat because of the velocity of adoption times the power of the solution.","offset":1826,"duration":52},{"text":"Rory: So I agree with Jason. It mightn’t be the old guard that takes advantage of it, but there’s no—but they tend to be pro—one of the things I admire about the security companies is the CrowdStrikes, the Palo Alto Networks of this world is they know damn fine that when a new threat emerges and a new solution emerges for that threat, when an earlier winner comes out, you better spend your 300 million bucks, your 500 million bucks, and just swoop up the winner and add it to your product, right? So I think there’ll be a ton of fast acquisitions as agent security solutions emerge, you know, and at—and people will be doing, if they’re smart—and I think those two companies are extraordinarily smart—they’ll be doing acquisitions long before it’s, quote, \"certain,\" because you’re going to have CIOs coming and talk to you.","offset":1878,"duration":36},{"text":"Rory: Right? One thing worth mentioning on that is it was interesting—again, I—in some of the leaked information from Anthropic—they are masters at selling fear. One of the things they’re doing is they’re releasing the Mythos model first to CISOs within companies. It’s kind of like, \"Oh, it’s so scary, we’re going to give you this model and give you time to figure out how to use it.\" Of course, part of that time will involve giving a million bucks to Anthropic for—so it’s just great marketing. So they’re actually leaning into that and saying to the CISOs, \"You’re going to have to figure this out. This is the new terrifying weapon we’ve invented. Please give us a million dollars and we’ll let you defend yourself with it also.\" Great marketing. Uh, but it speaks to the perceived—to Jason’s point—it speaks to how correctly afraid every security for—CISO should be given the pace of agentic AI adoption in the enterprise.","offset":1914,"duration":57},{"text":"Host: In the golden age of cyber, I wish I’d bought more.","offset":1971,"duration":4},{"text":"Jason: I mean, it’s just—it’s just how hard is it to get a meeting? Whoever you are, if you have any established brand, \"We—we’ve got a new agentic product, we’re going to help protect you from this.\" You’re going to get a meeting that afternoon.","offset":1975,"duration":9},{"text":"Host: Wish I bought them over Figma, that’s a depressing chart that I’m looking at.","offset":1984,"duration":6},{"text":"Rory: You need to let—you need to let go, Harry. You need to let go.","offset":1990,"duration":4},{"text":"Host: I’m—I’m down 30% in a month, Rory. It’s hard to let go after 30% in a month.","offset":1994,"duration":5},{"text":"Rory: Okay, no crying in the casino. Move on.","offset":1999,"duration":5},{"text":"Host: Uh, we—I—I do want to discuss revenue kind of questionability. Uh, we’ve got Anthropic recognizing revenue in a very different way to OpenAI. And then you also have questionability around Emergent Labs, um, and is it okay if ARR is kind of questionable in—sort of how it’s accounted for? Um, how do we think about that? You can choose which one you want to take.","offset":2004,"duration":24},{"text":"Jason: Let me just—can I just—I—maybe Rory can dig into it, but I’ll tell you there’s one startup I invested in that’s over a hundred million ARR. And I get the—I—I—I own just enough to get the investor updates. It’s not—I’m not on the board. And I get three numbers every month. Three revenue numbers. I—I don’t know what the hell they are, over a hundred million, but the smallest one is ARR. Now I invested in Seed, I don’t really care, I’m in the money, I don’t—I don’t have a choice. But I—I can’t understand—this company’s doing great, but I can’t understand for the life of me these three numbers and there’s asterisks and daggers and there’s charts that go everywhere, but they keep going up and to the right, which I think was on this Emergent thing we could talk about next. I think that’s what some of the investors said, \"Who cares?\" But I can’t tell the hell the difference what—what an ARR is in 2027.","offset":2028,"duration":43},{"text":"Host: Well, what—what I always get is like \"pipe,\" which is complete bullshit, then \"contracted,\" and then there’s \"live.\"","offset":2071,"duration":7},{"text":"Rory: So, first of all, stepping back, both—to be fair to both Anthropic and OpenAI, they have a very clear and sensible way they define ARR. What they take is they take the last—the average of the last four weeks to smooth out, times 13, because there are 13 four-week periods in a year. Which is more sensible than monthly because you have these varying months. So they basically—what they’re saying is realized revenue for the last four weeks averaged, you know, the average of the last four weeks—sorry, obviously if it’s the average it’s times 52—but basically it’s actual GAAP revenue. What did we bill for the last four—the average across the last four weeks to take into account holidays? That’s their run rate. Right? So it’s actually pretty—it’s not committed or any of the bullshit kind of higher-level stuff. It’s actual money flowing through the system.","offset":2078,"duration":58},{"text":"Rory: Anthropic is roughly at 19 billion according—based on that kind of trailing four-month—four-week metric, and OpenAI is around 25. But now let’s talk about your thing. There was this kind of whole meme of OpenAI reports net on their partner revenue and Anthropic reports gross. And what they’re saying there is if OpenAI sells through Microsoft and Microsoft takes some money off the top, OpenAI only reports the net amount. If Anthropic sells through AWS and they sell a hundred dollars worth of revenue, they report the gross amount and then they give 20—20 dollars back to Amazon as a cost of sale. So there’s two different methods for what look like the same revenue kind of nix—or same revenue approach.","offset":2136,"duration":44},{"text":"Jason: I thought you were going to extend that. I thought part of where you were going was to Michael Cannon-Brookes’ point on the show was that a lot of this revenue is getting doubled or triple-counted because of how it’s being recognized. And not only does this happen, then Cursor’s selling it again and recognizing the revenue, right? The same—people keep reselling these tokens again and again and recognizing them as their own ARR. Um, how many times do we get to resell these—these poor little tokens?","offset":2180,"duration":30},{"text":"Rory: I think that’s actually a great point, Jason. I hadn’t thought about that, but you’re exactly right. No, it’s like the—everyone’s got amazing revenue growth because it’s the same little token going through different—I can just picture this little token.","offset":2210,"duration":14},{"text":"Jason: I mean, if we all agree to have essentially 0% gross margins, an infinite number of us can keep reselling tokens to each other, can’t we? This is our new 20 VC scale SaaSster demo day. We all resell a million tokens to each other on the first week, so everyone in Batch 001 has a million ARR its first week, because we just resold our tokens to each other. So and it’s completely fair. The VCs don’t mind.","offset":2224,"duration":27},{"text":"Rory: And—and you’re exactly right, and the sentence that you added in passing is the key one: \"until we all have to get profitable.\" All this, you know, can continue. And then at some point, that’s why I said I think you’re starting to see it, someone’s going to have to say, \"Assuming we want to have a net present value and a cash flow, what’s going on here?\" And then—and then all this becomes more clear.","offset":2251,"duration":23},{"text":"Rory: I—I didn’t comment on the Emergent Labs fastest to a hundred million. Jason, you—you actually tried it, didn’t you? You thought it was good.","offset":2274,"duration":6},{"text":"Jason: I did. I thought—I mean, listen, it’s hard for me to know the criticism, right? You know, some folks in the press and the India B2B environment tried to make this some sort of scandal, right? Because—and in a sense, fair enough. If you go to Emergent Labs—and Emergent Labs is sort of an Indian competitor Replit and Loveable, which I’ll show you what I learned in a minute, right? And if you go right now to the homepage they say \"0 to 100 million,\" I think in eight months. It’s right there, it’s the biggest banner. So in all fairness, if you’re going to put yourself out there, not—not just as a tweet, but if it’s going to be right there on your website, one would expect 70 to 80 percent accuracy in that number, ideally higher, right?","offset":2280,"duration":43},{"text":"Jason: So if it’s lower than that, I think it’s fair that some daggers came out. But I was curious—um—but I don’t actually know what happened. Is it triple counting to—I—I can tell you one thing that I learned, which I don’t love, which is that what a—and a lot of AI startups do this. So this is not unique to Emergent. They kind of hot—instead of getting you to use the free version, they try to get you to immediately do a free trial, instantly that says it’s zero dollars and twenty dollars a month thereafter. Now so many folks do this. It is not unique to them; it’s probably best practice in most accelerators. But I’m pretty sure that means they recognize twenty—240 dollars in ARR that first month when you’re paying zero. And they trick you because you don’t even—yeah, you do have to click on the Stripe link, but you almost think you’re just using the free product.","offset":2323,"duration":52},{"text":"Jason: So is that—if I do a zero dollar a month product um that’s discounted as a marketing cost and I churn after 30 days, does that count as 240 dollars of ARR? I think for a lot of startups it does. Okay? So—that—that’s a fair criticism. I’m not saying this is what Emergent did, but a lot of startups will instantly recognize that as 240 dollars in ARR, which is how they rocket if you’re self-serve. That’s how you—otherwise you can’t get there that quickly, right? So they clearly did that.","offset":2375,"duration":37},{"text":"Jason: I will say what was interesting is I—I thought the product was pretty good. Much better than Make. Like an order of magnitude better than the disaster of Make. Um, because I—I do a five-part test, a six-part test. The first part is awareness test. So I ask it to redo the SaaSster.ai homepage. Uh, actually of all the platforms it did the best job. It—it beat—it beat—it beat all of them. All of the leaders, because I redid this recently. I redid this and Replit, Loveable, VZero, they’re all good at—they all pass the test, but it actually—it actually was probably the best and it—it passed a bunch of the other tests.","offset":2412,"duration":49},{"text":"Jason: So I’m not going to switch to Emergent Labs, but I would say it’s in the top 10% of vibe-coding apps. That’s pretty good. So that tells me it’s a legit business. Like they did—they did the work and a lot of these they’re just—the truth is if you play with a lot of these even from leaders, like Make’s not the only one that’s crappy, okay? Because they’re basically relying on the fact that Claude code does 90% of the work for you. Right? They’re just putting the simplest wrapper around this and so they did a good job. But is—I really didn’t like the way they do the billing, but we’d probably have to shoot half our portfolio companies that do like PLG AI because I think it’s a sus practice. I just don’t like tricking you with this zero dollar for the first month when you think you’re using a free trial, right? That’s the sus part. I don’t—I don’t love that kind of gray art. Um, but the product’s pretty good.","offset":2461,"duration":71},{"text":"Host: You know what I didn’t like when it comes to confusing? I was wondering whether to go off on one in this show and then I thought, \"Fuck it, let’s go off on one. It’s been a long day.\" I’m pissed off by these tranche rounds. I see them all the freaking time. The amount of Sequoia rounds where it’s like, \"Oh, you know, X raises money from Sequoia at five billion.\" Trust me, Sequoia got in at one, but they just club it together and then announce the sum and then the latest valuation. And it’s just very misleading. The tier ones get in early, a tier two, tier three instantly marks it up same day.","offset":2532,"duration":35},{"text":"Jason: Same as crypto, isn’t it? For years. What’s the difference? We’ll give the Andreessen crypto fund the, you know, essentially 80% off the token. What’s the difference? You’re paying for the—paying for the signal.","offset":2567,"duration":11},{"text":"Rory: I think if you break it down, first of all, just so everyone’s on the same page, because interestingly neither Claude nor GPT was on the same page and didn’t know what a tranche round was, and they gave the old conventional venture tranche round based on performance milestones, you know, BS from back in the day when we actually ran businesses, right? So they didn’t have a clue about this.","offset":2578,"duration":26},{"text":"Rory: So let’s be clear on the practice here. The practice here is when a company, a hot company raises a round where there are effectively two different prices per share—a first—let’s call it a first close and a second close, even if they are at or near contemporaneous—where the first one might be at 250 pre and the second one is at a billion pre and, you know, the highlight and the headline is they raised at a billion pre. There’s two imp—impacts of this.","offset":2604,"duration":33},{"text":"Rory: First of all, let’s do the simple one where there’s just a single participant in the round. That’s where, you know, if I’m the new investor, I want to pay 600. The company wants a headline of a billion. And to win the deal someone says, \"Okay, let me put some money in at 250, some money in at a billion.\" I can do math because I’m paid to do math because I’m an investor, so I know my overall basis is a billion—sorry, obviously if it’s the average it’s 600 million. So I’m getting what I want, and the company’s getting what it wants, which is a headline number of a billion, right? It’s silly, but that’s all that’s happening in that case. That’s the single participant tranche deal, right? And it’s just—and for some if a company wants a headline that’s what they get, right?","offset":2637,"duration":57},{"text":"Rory: Generally those things come back to bite you because by definition if you’re the company, just as the investor can do math presumably you can do math. If you accept that combined deal you’re implicitly saying, \"I know I’m only worth 600 but I’d like the optics of a billion.\" You better be damn sure that your next round you’re at one and a half billion, otherwise you’ll have the optics of a down round, and if you’re an optics believer that’s probably worse than the uptick, right?","offset":2694,"duration":32},{"text":"Rory: So that’s kind of the single participant version. The much more annoying version that Harry clearly was getting on his high horse about is when you have the same structure but access to those rounds where the—the lead investor maybe does all of the 250 pre-round and only half of the billion round, and then some new investors just get to do the billion round. So literally at the same time, the lead investor is investing at 600 billion—I mean, million—and the follower investor, less marquee investor, is investing in the same asset at a billion. And there—I don’t believe there’s right or wrong in money, there’s just money, right?","offset":2726,"duration":45},{"text":"Rory: That’s where at the minimum you have to look yourself in the mirror as the other investor and say, \"Wow, that’s the price of being cool.\" Right? \"That’s the price of access. I’m paying 50% more because I just can’t access that deal.\" Right? And that feels like pretty invidious thing to—I mean, again, going back to the comment, the—you’ve got to remember if you think about—and again, try to avoid morality and saying, \"Oh, it felt shitty,\" because it really—it would feel like a loser if you did that. But let’s play it out. In this situation where the—the lead investor, let’s say it’s Sequoia because everything good and strong should be Sequoia, they’re admitting it’s only worth 600 on average and they’re just doing this fakey transaction. The company is admitting it’s only worth 600 on average because they’re taking the money at a blended cost of 600. So what you’re saying doing it at a billion is you’re either saying, \"Either I have a lower cost of capital and I’m willing to take a lower return than everyone else,\" or the only positive spin you can come up with is the company thinks it’s worth 600, Sequoia thinks it’s worth 600, but I am smart enough, even though I don’t have access, I am smart enough and clever enough to know that it’s really worth a billion and I should do it at a billion even though I can’t get to 600. And I’m willing to put up with the upfront tax and foolishness look because I think 6-12 months from now it’ll be obvious that I bought it at a great price and maybe I’ll look like a genius.","offset":2771,"duration":99},{"text":"Jason: Yeah, but we’ve—but we’ve entered an era though, the—one—I think the meta thing—maybe this wasn’t exactly what you were queuing up, Harry, but it is tough. We’ve entered an era where so many founders are obsessed about headline prices. Obsessed. They’re obsessed coming out of Demo Day, they’re obsessed—they’re obsessed. Once they cross a billion, which I think should be a moment to take a pause because of an M&A options, they’re obsessed about driving to 11 billion and 9 billion and one-upping their competition. And the numbers have become a joke to many founders, right? They just don’t—maybe joke’s the wrong term. They don’t think through the—any of the ramifications of the valuation they’re hiring, they don’t care.","offset":2870,"duration":48},{"text":"Jason: And I’m not even saying that’s bad. I mean, I think burning the bridges is a good way to have a big outcome, but it’s become utterly gamified on many levels, right? It’s just become gamified. And so this—11-teen tranches and around is just part of gamifying it, right? It’s been true of YC since I started investing. There—there was always a cheaper price before Demo Day if you’re reasonably hot, a higher price at Demo Day, and then a 20% or 30% after Demo Day. So that version has just become institutionalized and so be it if it’s what the founders want. If they want to gamify it, so be it, right? I just don’t think raising at 5 or 8 billion when you’re at 80 million or 100 million of suspect ARR is the most exciting accomplishment in the world. Like, I’m not going to—like, I’m—I’m going to send a few thumbs emojis on the email, but that’s about it.","offset":2918,"duration":55},{"text":"Host: That’s about it. They’re all—they’re all fake anyway, they’re all just bets, right? These are not public companies. It goes back to your point on Emergent Labs and the graph of the eight months to 100 million and the gamification of, like, the race to 100 million. I’m not choosing Emergent Labs, but listen, I think they built a good product. I think—I’m sure they’ve been overly lambasted because whether it’s 100 or 80 or 60, I don’t care, it’s pretty damn good, right? Whatever it is. But if you’re going to—if you’re going to do that, you deserve the daggers to come out when it’s not 100%, right?","offset":2973,"duration":38},{"text":"Host: One that I thought was fantastic, exciting, I would like to see a potential IPO or to IPO shortly. I thought this was fascinating. This has been an incredible journey, actually, from, you know, Scandinavia, these founders building this business. It’s had a couple of CEO changes. Uh, the business is actually in incredible shape. Both—actually, and Whoop announced today that they raised, I think it was 500 million at 10 billion. Fitness and health data—do you know what, actually, Rory? Jason’s annoyingly right again. I don’t know if you remember his predictions, but he predicted, if I’m not wrong, that 2027 would be the year for, like, human healthcare data and longevity.","offset":3011,"duration":41},{"text":"Jason: Yes, and it looks like it might even be 2026. And yeah, no—and the great thing about both stories is very defensible—I mean, you know, Jony Ive's side—very defensible from an—this is not an AI envy story, this is—I mean, they use AI in what they do, but these are fundamentally standalone products with a clear consumer value proposition and they’re, you know, they’re not going to be Claude-coded on Friday. I totally see it and they clearly have had critical mass in terms of revenues. I think it’s awesome.","offset":3052,"duration":35},{"text":"Jason: I think the question—listen, the interesting thing for for these products, obviously it’s exploded, is they are—they are recurring rev—you know, going back to the topic of ARR, these are recurring revenue products, right? Um, for the most part, right? Um, fairly expensive subscriptions, um, and they’re exciting until like Peloton when they aren’t, right? Now there—there’s not a $2,000 cost here, um, but—um—and I’m not being critical. I—I think that they’re exciting. But there’s also a faddishness-ism. People can switch. So the RR, the ARR, the pirate R, um, what multiples do these companies deserve? What it is, I—I’m not smart enough to know, but the—but the acceleration is a force of nature, right? I’d love to be a Seed investor, don’t get me wrong.","offset":3087,"duration":49},{"text":"Rory: Do you think there’s a faddishness in the same way? I think we—","offset":3136,"duration":2},{"text":"Jason: I think you can switch from vend—Harry, you’re into fitness. I—I’m not so much, but I run 360 days a year, five miles a day for 10 years. So if there’s a better treadmill, a better device, a better thing, I would switch. And whatever you’re—you’re fairly fit, Harry, like if you—if you were Oura and you love it, but Whoop is—is better and you care, you’re going to switch. So it’s not ServiceNow ARR, right? You—you’re loyal, you’re loyal, but—but there’s just some disruption risk. Like, look at Peloton. When Peloton blew up, but actually as the world changed, even though people love Peloton, right? Super high NPS, they—remember the Peloton addicts of 2020 on Zoom? They—they loved it, but when the world changed they just—","offset":3138,"duration":10},{"text":"Harry: But he helps me put together some of the schedules too. And he was like, \"Whoa, I had no idea about this.\" He was like, \"Whoa, Epic Games laid off 25%.\" I didn't even hear about that.","offset":3148,"duration":13},{"text":"Jason: Yeah, and then—and then I had—had Mark Andreessen on your last pod sort of laughing about how we all over-hired in 2021.","offset":3161,"duration":7},{"text":"Harry: Well, Mark Andreessen was—was very clear. He thought that we were all using AI as an excuse and that we were all over-staffed by 50 or at least 75%.","offset":3168,"duration":10},{"text":"Rory: Uh, by the way, Harry, just logically it's—it would be 75 or at least 50% overstaffed by 50 or at least 75. This doesn't make any logical sense, but keep going. Just picking up on the errors here.","offset":3178,"duration":13},{"text":"Harry: Rory.","offset":3191,"duration":1},{"text":"Jason: He's pissed now. He's pissed.","offset":3192,"duration":2},{"text":"Harry: I would love to see you do a day of my life. I would love to—","offset":3194,"duration":3},{"text":"Rory: Give me a fucking break.","offset":3197,"duration":1},{"text":"Harry: Uh, actually fair.","offset":3198,"duration":1},{"text":"Rory: I now feel guilty.","offset":3199,"duration":1},{"text":"Harry: You've been cranking.","offset":3200,"duration":1},{"text":"Rory: I now feel guilty.","offset":3201,"duration":1},{"text":"Harry: I will give you two hours sleep for six hours a day running two companies at once.","offset":3202,"duration":4},{"text":"Rory: Okay. Now I'm feeling guilty. Move on.","offset":3206,"duration":2},{"text":"Harry: Don't worry. But—but point being, like... point completely under the radar.","offset":3208,"duration":8},{"text":"Rory: They didn't try and do an AI bullshit story. They basically said, you know, active—daily active use of their Fortnite game and their games is down, so your revenue's down, so you take your expenses down.","offset":3216,"duration":13},{"text":"Rory: It was—struck me as a no-bullshit layoff announcement. It's like, you know, \"We sell less stuff, we have less people.\" It sucks. You know, and again, I really do try never to be cavalier about people losing their jobs because every one of those has to put food on the table, they're not earning the kind of money we're earning and now they've got to go out and find another job in a shitty job market. It sucks.","offset":3229,"duration":19},{"text":"Rory: But the lesson is—and that's why I respected them—it's like, we're selling less, so we gotta do what we gotta do to keep the company profitable. But I agree with you, this kind of pretend it's ARR but then next year we hate ARR, it's just a total waste of time for entrepreneurs. Things are what they are and you do best in business if you actually say what they are and just live and die by that. Most consumer products have high volatility associated with them. You better have a damn good R&D function and continue to build great products.","offset":3248,"duration":52},{"text":"Jason: Well, DJI might disagree with you. I mean, there was a whole step function in the industry that they got—they got left behind, right?","offset":3300,"duration":6},{"text":"Rory: Yeah. Would you prefer $2 billion in consumer hardware revenue or $2 billion worth of five-year contracts, um, like Palantir? Yeah, I'll take the contracts with the 90% gross margin and the five-year lock-in, please. Your starter for 10.","offset":3306,"duration":14},{"text":"Jason: I think maybe the more interesting question, Rory, that you brought up, um, because so much has changed—this is our 50th show, so much has changed, right? When we started this show, uh, public—durable public company revenue despite slowdown in the top line was the gold standard, right? It was the best revenue out there.","offset":3320,"duration":20},{"text":"Jason: Fast forward to today, do we—Oura going public—do we give a crap what type of R it is because the durable software stuff is trading lower than the S&P 500? Maybe I'd rather have Ring revenue and um, with a somewhat suspect, uh, customer lifetime value because the software value is so low. Maybe I don't care where my R comes from, right?","offset":3340,"duration":20},{"text":"Jason: It used to matter. It used to matter, right? We were so—we'd be in board meetings where you would torture companies so that they would have more ARR and that they would have less variable revenue. I mean, that—that seems like archaic today.","offset":3360,"duration":12},{"text":"Rory: Yeah, and—and I remember doing that and I remember telling people not to do that because I'm a big believer as you can't make—you should sell your product the way the customer wants to buy it, not your VCs.","offset":3372,"duration":9},{"text":"Rory: Because I agree with you, this kind of pretend it's ARR but then next year we hate ARR, it's just a total waste of time for entrepreneurs. Things are what they are and you do best in business if you actually say what they are and just live and die by that.","offset":3381,"duration":11},{"text":"Rory: Most consumer products have high volatility associated with them. You better have a damn good R&D function and continue to build great products.","offset":3392,"duration":7},{"text":"Jason: We looked today—this week they also talked about how I think Allbirds was—was it acquired for less than 30 million?","offset":3399,"duration":6},{"text":"Harry: It was—it—yeah, I was literally about to bring this up, Jason. It was acquired by Ames for $39 million.","offset":3405,"duration":6},{"text":"Jason: So my question is, if a company like Oura goes public and you see weakness in a quarter, should you dump this thing instantly, like Allbirds, um, versus forgive a little bit of weakness in a Salesforce or ServiceNow?","offset":3411,"duration":15},{"text":"Rory: Again, I'm going to avoid any specifics—genuine comment here, right? Because it's not appropriate. But I would say something. Unlike you guys, I've run a textile manufacturing company 30 years ago.","offset":3426,"duration":10},{"text":"Rory: The technology required to make an Allbirds or a shoe is not the same as the technology required to make a modern electronic device that sits on the human finger and measures blood.","offset":3436,"duration":11},{"text":"Rory: Either of these kind of consumer electronic products—they're not a monopoly in the same way Nvidia is, but they're pretty—it's a pretty rare number of companies that can do that. Now, go down—for—put it this way, Jason: I'll name a wearable, you'll name a wearable, and then I'll name a sneaker and you'll name a sneaker.","offset":3447,"duration":17},{"text":"Rory: We'll be done with wearables long before we're done with sneakers because there's a lot of different sneaker companies. And yeah, it turns out sneakers are easier to make than wearables, which are easier to make than Nvidia GPU chips.","offset":3464,"duration":12},{"text":"Harry: Speaking of like \"do we care, what do we actually care about,\" there were two that I—I don't know if you guys know this, but I have wonderful partners and one of my partners is much more intelligent than me, which Rory, you're going to make some form of gag about.","offset":3476,"duration":13},{"text":"Harry: But he helps me put together some of the schedules too. And he was like, \"Whoa, I had no idea about this.\" He was like, \"Whoa, Epic Games laid off 25%.\" I didn't even hear about that.","offset":3489,"duration":12},{"text":"Jason: Yeah, and then—and then I had—had Mark Andreessen on your last pod sort of laughing about how we all over-hired in 2021.","offset":3501,"duration":8},{"text":"Harry: Well, Mark Andreessen was—was very clear. He thought that we were all using AI as an excuse and that we were all over-staffed by 50 or at least 75%.","offset":3509,"duration":10},{"text":"Rory: Uh, by the way, Harry, just logically it's—it would be 75 or at least 50% overstaffed by 50 or at least 75. This doesn't make any logical sense, but keep going. Just picking up on the errors here.","offset":3519,"duration":13},{"text":"Harry: Rory.","offset":3532,"duration":1},{"text":"Jason: He's pissed now. He's pissed.","offset":3533,"duration":2},{"text":"Harry: I would love to see you do a day of my life. I would love to—","offset":3535,"duration":3},{"text":"Rory: Give me a fucking break.","offset":3538,"duration":1},{"text":"Harry: Uh, actually fair.","offset":3539,"duration":1},{"text":"Rory: I now feel guilty.","offset":3540,"duration":1},{"text":"Harry: You've been cranking.","offset":3541,"duration":1},{"text":"Rory: I now feel guilty.","offset":3542,"duration":1},{"text":"Harry: I will give you two hours sleep for six hours a day running two companies at once.","offset":3543,"duration":4},{"text":"Rory: Okay. Now I'm feeling guilty. Move on.","offset":3547,"duration":2},{"text":"Harry: Don't worry. But—but point being, like... point completely under the radar.","offset":3549,"duration":8},{"text":"Rory: They didn't try and do an AI bullshit story. They basically said, you know, active—daily active use of their Fortnite game and their games is down, so your revenue's down, so you take your expenses down.","offset":3557,"duration":12},{"text":"Rory: It was—struck me as a no-bullshit layoff announcement. It's like, you know, \"We sell less stuff, we have less people.\" It sucks. You know, and again, I really do try never to be cavalier about people losing their jobs because every one of those has to put food on the table, they're not earning the kind of money we're earning and now they've got to go out and find another job in a shitty job market. It sucks.","offset":3569,"duration":15},{"text":"Rory: But the lesson is—and that's why I respected them—it's like, we're selling less, so we gotta do what we gotta do to keep the company profitable.","offset":3584,"duration":8},{"text":"Harry: Guys, we keep talking about these layoffs and these big numbers. I mean, it was over a thousand people laid off in this layoff. A thousand. And the numbers are relatively meaningless and we've had so many of these conversations.","offset":3592,"duration":14},{"text":"Harry: What happens to the labor markets?","offset":3606,"duration":2},{"text":"Jason: Well, one thing on—on the Epic thing, if you—and the Wall Street Journal did a good article on this one too this week on the permanent decline of Hollywood employment. It's permanently in decline. It's not—there—it is on—it is in decline because fewer movies and TV shows are being made, TikToks and YouTubes are doing it, and it's in permanent decline because every other country provides larger subsidies, right?","offset":3608,"duration":24},{"text":"Jason: And so there's this permanent decline in Hollywood labor. I think entertainment is—is sort of a—shows us the future. Epic Games is entertainment too, right? And uh, they will absorb as much AI and technologies as they can to address the—to adapt, and it's just early. It's just early. They've had to adapt to YouTube, they've had to adapt to social gaming.","offset":3632,"duration":22},{"text":"Jason: And I think we talk about these, uh, thousand people at Last year or whatever, but I think Epic Games is just—it's—I think it's a more interesting view of the future than Block. We talk about folks might vibe-code a B2B app, but content's already being massively disrupted.","offset":3654,"duration":14},{"text":"Rory: And some part of that is as you pointed out to me when I got it wrong a few episodes back, AI related in terms of recommendation engines. But I think a lot of it is just, you know, a very competitive attention economy. You're right. Fortnite was the—was the game everyone talked about now it's not. It's the nature of the gaming industry. So yes. What—what does that mean?","offset":3668,"duration":19},{"text":"Jason: It's the Fortnite circle coming for everybody at the end.","offset":3687,"duration":4},{"text":"Rory: Oh, yeah, yeah. The little circle.","offset":3691,"duration":2},{"text":"Jason: For everybody, even Fortnite. The Fortnite circle has come to Fortnite itself. It is surrounded itself. Poor Epic Games is in the middle of its—of its endgame of Fortnite.","offset":3693,"duration":10},{"text":"Rory: It's just hidden content creators shooting it out at the very end. It's coming for all the—the Fortnite circle's coming for all of us.","offset":3703,"duration":8},{"text":"Harry: The other one that—relatively was—I think maybe a little bit overlooked is reports of Mannus founders—Mannus obviously for context being bought by Meta recently. Um, Mannus founders trapped or kept in China.","offset":3711,"duration":14},{"text":"Harry: So just again, give people context and then put out one question mark there. Mannus was a company originally based in China, had some Chinese investors, then redomiciled to Singapore, Benchmark invested, effectively refounded as a US-Singapore company, Meta acquired it.","offset":3725,"duration":19},{"text":"Harry: I want to say—and I use the word past tense \"acquired\" because my understanding is the transaction's closed and the money's moved, though interestingly, not a ChatGPT nor Anthropic were clear on that, but my understanding is that's what happened.","offset":3744,"duration":13},{"text":"Harry: But then now the latest thing is two of the—the Chinese government has—takes a dim view of this because they don't want Chinese talent leaching overseas and going to the US and effectively not being Chinese anymore and they—they—they feel it as a brain drain.","offset":3757,"duration":17},{"text":"Harry: So they did something that was, you know, pretty coercive in the sense of two of the key founders of Mannus, I think, were either in China or summoned to China and they're no longer able to leave.","offset":3774,"duration":13},{"text":"Harry: So that's—those are the facts. And of course you care. I mean, I think that—well, starting from the scratch. I mean, that sucks.","offset":3787,"duration":7},{"text":"Rory: I wish them the best because that's not a pleasant place to be. I mean, I think you've had the Jack Ma thing of, you know, at Alibaba, of effectively going as it were under the radar for a few years when you kind of incurred the displeasure of the administration. You also have people who've had significantly worse consequences than that. So let's start with the basic: you wish them all the best, right?","offset":3794,"duration":22},{"text":"Jason: I don't think another deal like this would happen, do you? I think this whole Singapore washing thing is over. It's over.","offset":3816,"duration":6},{"text":"Rory: I totally agree. That's where I was going to go with that long preamble. I'll tell you who didn't notice: maybe no one in America spent any time thinking about it, but every Chinese founder who was thinking about doing this is going, \"Hmm. Hmm. I don't know how I feel about this. I don't know if I can do this deal. I do know if I do this deal, I am never going home again.\"","offset":3822,"duration":17},{"text":"Rory: I'm with you, Jason. I think all these other China washing deals, they're put on pause or they're put on reevaluation. It's—next thing it's going to sound harsh. It's a fairly coercive regime. If your family's not out of the country, do you have exposure there? Right?","offset":3839,"duration":15},{"text":"Rory: I think it puts—it just shows, I mean, authoritarian governments can take pretty dramatic steps to impact their citizenry if they want to. And I agree, Jason, it makes it really hard to imagine doing another one of these deals without being worried about this consequence. And hopefully they'll kind of go \"naughty you,\" pay a 50%—like, you know, California makes it hard to leave too, but if you pay them 13%, they'll let you go to Nevada, right? Yeah, hopefully it turns out to be something like that and please God it's not something more, you know, coercive. But I agree, Jason, wouldn't do another one.","offset":3854,"duration":33},{"text":"Jason: You know, in venture you take risk, right? It's part of the job. So we've all had deals where there's some rule, some corner that was cut and we talked ourselves into it's okay, right?","offset":3887,"duration":11},{"text":"Jason: This is—companies—something weird about this company but—and we convince ourselves as—as—talking to some mediocre lawyer or asking an LLM today that it's okay. So like this Singapore washing must work, right? They've moved to Singapore, it's got to work.","offset":3898,"duration":15},{"text":"Jason: And you convince yourself, you talk to a few people and you take the risk and it—it—it appears to have bounced the right way for Benchmark and friends, right? It appears they've gotten their money. But you don't do the next one, right?","offset":3913,"duration":11},{"text":"Jason: And there's 242 millionaires in Singapore, the majority of the inflow is Chinese. You don't do the next deal. I mean—and that—maybe other capital does the deal and that's fine, right? Capital is fungible, but you just—in venture you just don't—you just can't do the next one like this. It's too risky.","offset":3924,"duration":13},{"text":"Harry: What do you do if you're Meta? Part of the asset you're acquiring is the team.","offset":3937,"duration":4},{"text":"Jason: 2 billion's not a lot for Meta and they have the product.","offset":3941,"duration":3},{"text":"Rory: Yeah, what are you going to do, Harry? What would you recommend? Getting angry at the Chinese? That'll work well, right? I mean, I think it'll be, you know, a yet another acquisition that looked clever, but in retrospect wasn't anything.","offset":3944,"duration":15},{"text":"Jason: Well, listen, for Meta, I'll just say one thing. I—I only have a tiny bit of information, but I—it appears to me Mannus is running mostly smoothly as an application and a company. Now, I don't know if the founders are working out of, you know—I certainly feel strongly when you lose your founders you lose your heart and soul of your company, but in the short term, I—I don't think it's a big deal for Meta outside of the founders because it's running smoothly, right? That—that's my—in the short term. The—the—it's not down, the team's functioning, they're running. And um, but it's crazy.","offset":3959,"duration":30},{"text":"Rory: And at the risk of being Pollyanna but also wanting to assume the best of people, I would hope that the Meta management team and board, to the extent they do have any influence, can help these guys come to an amicable end and if it requires a tax settlement or whatever, you know, just—you don't want to leave—you don't want to leave people you just acquired in limbo.","offset":3989,"duration":19},{"text":"Rory: At some zoom out level, when you listen to the rhetoric in both capitals, you just have to realize that trying to tread between those two—these two countries is pretty hard right now.","offset":4008,"duration":10},{"text":"Rory: Right, you know, yeah, we have China Hawks in the US government, they obviously have a whole ton of US Hawks or whatever the equivalent is. There's a real perception of competition. Yeah, we don't let them buy the Nvidia chips, etc., etc. You're playing with fire in that thing and sometimes it bites you.","offset":4018,"duration":17},{"text":"Jason: I just think overall, it's natural in given the outcomes in AI and given the growth, that I think it's tied to taking the highest levels of risk we've also taken because the payoffs seem to be there. And when this deal happened, folks kind of thought this was aggressive, Benchmark's never done a deal like this, why are they doing a deal like this? It's not even very cheap, right?","offset":4035,"duration":18},{"text":"Jason: It seems a little crazy. And they're like, \"Well, we've never seen anything grow like this and the team's incredibly talented,\" right? So they took a little bit of risk and um, and they made their—made their profit. We're all taking more and more risk. Folks that, you know, now it's a week of revenue at a Demo Day. I did a million dollars my first week. It's amazing. What about the second one? I don't know.","offset":4053,"duration":18},{"text":"Jason: Like, uh—but as long as it all works out in the aggregate. And I think this is why nobody cares to Harry's point. I cared about Mannus, I added it to the list. I don't think anybody cares. We're all focused on getting a million dollars our first week.","offset":4071,"duration":13},{"text":"Rory: Just good realization that the worst thing that can happen is not just, \"Oh, you lose your money.\" There are worse outcomes than that.","offset":4084,"duration":10},{"text":"Harry: I mean, speaking about cooling their shot on making billions of dollars, Steve Jurvetson... he's tied his career to Elon very smartly, so that's not in any negative way in terms of the investments that he has plowed, trebled, doubled, quadrupled, everything in between.","offset":4094,"duration":16},{"text":"Harry: Uh, leaves California, buys most expensive home in Incline Village. And—and these were Jason's words—will anyone with liquidity be left in California? What if California is structurally bankrupt?","offset":4110,"duration":14},{"text":"Jason: Well, I mean, yeah, it's not a great sign when they keep leaving, is it? It's not a—it's not a positive.","offset":4124,"duration":7},{"text":"Harry: But Rory's staying, Jason.","offset":4131,"duration":1},{"text":"Rory: I mean, look, all—first of all, you're exactly right. All credit to Steve and all power to him. Known him intermittently for 30 years. He made a brilliant call to align with SpaceX, being on the board of Tesla and SpaceX.","offset":4132,"duration":15},{"text":"Rory: Tesla for a while and then came off obviously for those back in the day, but SpaceX too. Yeah, he's—he's put his money in a compounding machine and now he's clearly hit the DPI moment.","offset":4147,"duration":9},{"text":"Rory: Right, but yeah, going back to the thing. Yes, capital—I mean, the truth is this: that's why we said last week, high—ultra high net worth people have a high degree of mobility and unfortunately, if you put the hammer up too high, they can leave and choose to go across the border to Incline Village and save 13% on, um, any realized gains, plus as we've pointed out, 5% on all gains if this wealth tax passes.","offset":4156,"duration":26},{"text":"Rory: You know, at the margin, why wouldn't you? You know, it's not like you need to be in California to be a Tesla board member or a SpaceX board member given they're down in Texas. So yeah, actions have consequences.","offset":4182,"duration":13},{"text":"Jason: Well, it's interesting also this week, um, Washington state did pass their 9.9% state income tax for millionaires. And the governor said—the—the reason the governor said it's signed because there were a lot of folks who said, \"Don't do it,\" right? It's already Howard Schultz left.","offset":4195,"duration":14},{"text":"Jason: He said today, he said, \"Well, they just deserve to pay more.\" And that may well be true. It may well be true. Like, I don't want to debate that. This is not political, right? I'm—I'm more concerned about the tipping point when uh, we kill golden geese.","offset":4209,"duration":16},{"text":"Jason: You know, there's been—Washington and California and to a lesser extent New York have been the gold—golden geese. It's, uh, you know, Washington said they're going to lose money, they're not going to make money on this. It—it appears that most folks that are neutral or right have said California will lose money on the billionaire tax, everyone's left.","offset":4225,"duration":16},{"text":"Jason: And the tax itself assumed massive amounts from Larry Ellison who's been gone a half decade, right? So no one's going—it's just I do—I do worry they're all—they're all—they're all leaving.","offset":4241,"duration":11},{"text":"Jason: Everyone that doesn't work at OpenAI and Anthropic. Uh, you know, on this show we've done it 50 and I said in the beginning of this that you leave after the series B and I—now I see that used again and again by these folks who are on the right on it. They say all the founders leave after the series B, but it may happen by show 100.","offset":4252,"duration":17},{"text":"Rory: And one of the arguments I'd make is, because you know, the truth is this: articulating the argument to the—to, you know, the activist on the other side as being, \"You're being mean to the billionaires,\" is of genuine no interest. In being mean to a billionaire is actually a feature, right?","offset":4269,"duration":18},{"text":"Rory: But I think the real articulation is this: if you—you actually are losing revenue that won't be available to California and the marginal dollar in California probably goes into home—you know, payment for homelessness, payment for young—kids, payment for foster homes, payment for marginal social welfare services that are easy to defund when times are tough, right?","offset":4287,"duration":18},{"text":"Rory: And by choosing to obtusely tax without any attention to ability to collect that money, you've actually reduced the revenue that's available to you, right? And that's the argument you have to make to the—to someone on the other side of the table: You have literally chosen something.","offset":4305,"duration":13},{"text":"Rory: Instead of getting, you know, 250 million—I don't know, pick a number, 50 million from the Larry and Serges and the Jurvetsons of this world, you went for 200 million and now you're going to get zero.","offset":4318,"duration":11},{"text":"Rory: And what that means in real terms is somewhere down the line, long after all these changes have been made, somewhere in Sacramento, someone will zero out a line item on the budget and let me give you a clue: it won't be payments to the teachers, it won't be payments to the firemen, it'll be marginal services to marginal people that your crass stupidity and desire to make a political point has ended up costing them money. And that's the only argument that moves the needle because it—because it's true. And you're right, Jason, you're saying is that it will have a net negative return. How do—now do you feel good?","offset":4329,"duration":35},{"text":"Harry: Rory, if you were Steve, would you have left?","offset":4364,"duration":3},{"text":"Rory: I think from my perspective, I'm just so glad to be in California. It's so wonderful. I moved around a lot early in my life. I have my friends here, I have my life here. At the margin, the whole point of having money is to be able to do what you want, and for three or four or five or even 13% of your income, do you really want to leave?","offset":4367,"duration":16},{"text":"Rory: Now, I will say this, that's why you can tax income relatively highly because it comes all the time and you can't control timing and therefore you have to uproot your whole life for the rest of your life to avoid it, and I don't think it's worth it. So I wouldn't move to avoid income tax.","offset":4383,"duration":16},{"text":"Rory: Conversely, if you have this pending capital event where literally in one year you're going to sell quote all your SpaceX stock and realize a $2 billion gain and you're going to pay an extra 13% of that in California, it's $260 million. Maybe you turn to your wife and say, \"Honey, for the next two years, why don't we live in Incline Village 165 days? I'll pay for the plane, we'll go back every week, you won't lose contact with anyone and we will save $260 million.\"","offset":4399,"duration":23},{"text":"Rory: And you go, \"Hmm. That's real coin.\" So and that's the point about, you know, that's not the life I lead, that's not the situation I'm in, but that's the argument you make. It's like, it's not crazy.","offset":4422,"duration":12},{"text":"Harry: That's real coin, baby.","offset":4434,"duration":2},{"text":"Jason: That's real coin.","offset":4436,"duration":1},{"text":"Harry: Is—is there any story that I haven't hit on, guys, that we should hit on?","offset":4437,"duration":3},{"text":"Jason: I just have to bring up the Ron Conway Matthew Prince one because it was so—I highlighted that one on Twitter. It was just the funniest thing in the world.","offset":4440,"duration":10},{"text":"Harry: And uh, you know—","offset":4450,"duration":1},{"text":"Harry: Just for context, do you want to provide some context?","offset":4451,"duration":2},{"text":"Jason: Yeah, I don't know Ron Conway, but he's certainly viewed as one of the Silicon Valley gems, right? Seed investor in so many leaders. Always out there as an advocate everywhere, um, probably could have retired years ago, right? Very founder-centric.","offset":4453,"duration":14},{"text":"Jason: And he wrote that he had helped Cloudflare navigate some very significant issues earlier in the day. I think on Jack Altman's podcast, yeah, on Uncapped. And they asked Matthew Prince, CEO of Cloudflare, the question, he said, \"Well, maybe, I don't remember any of that.\"","offset":4467,"duration":14},{"text":"Jason: And it's just—it's not—and he wasn't mean. Matthew can be fairly, uh, sharp as—as Harry knows these days. It wasn't meant mean, the tweet was not mean. He literally just memory couldn't remember getting any help from this beloved VC.","offset":4481,"duration":14},{"text":"Jason: And I think it just said so much to me about VCs adding value, but also VCs thinking they add value. VCs possibly adding a modest amount of value but founders not really thinking that modest value was consistent with the bravado of the VC.","offset":4495,"duration":14},{"text":"Jason: It just—it just—it just crystallized the whole value add idea to be in a single tweet. It wasn't mean, it's just, \"I don't remember any of—I don't remember Ron helping, but maybe he did.\"","offset":4509,"duration":10},{"text":"Rory: Yeah, I—you're right, Jason. I—I did laugh at that. And I think it does—I think actually my big takeaway to your point is both to some extent are right is that, you know, as a—we all want to have agency, we all want to feel we help and, you know, want to be good people and you look and you go, \"Hey, I spent some of my time helping this CEO. I feel I helped.\"","offset":4519,"duration":18},{"text":"Rory: But from the company's perspective, they're founding a company, they're doing a million things. On one or two things on a 10-year journey you helped, you remember that vividly. They're like, \"Dude, it just fades into the background of, you know, a hundred things,\" and you know better than me, Jason, they have to do every day, right?","offset":4537,"duration":16},{"text":"Rory: And the truth is this. I—one of the proofs of this is—interest the way to check it—is I often read business biographies and business stories of great companies, venture-backed companies, and how they were formed and what happened.","offset":4553,"duration":18},{"text":"Rory: And you know what I notice in them? Every single one of them: very few little mention of the VCs. If you just read them, you—you eyeball them, see says, \"Oh, there's a biography they—\" Yeah, and they crop in and come out a couple times, right?","offset":4571,"duration":13},{"text":"Rory: And I think that's right because realistically in the journey of what's going on, the only significant things we do—and I said this before in the podcast—we put in the money and we put in more money when they need it. We decide to hire or not hire or fire the CEO, we agree the broad strategic direction, and anything after that is at best an assist, right?","offset":4584,"duration":20},{"text":"Rory: And if you read the biographies of businesses, what you generally see is the only time the VCs come in is on some version of those, right? And it's, you know, five pages of the journey early on interspersed over 200 pages in the first five chapters, and by the time they get to the IPO, don't even rise to the level of a thing, right?","offset":4604,"duration":15},{"text":"Rory: I was reading the, you know, the OpenAI biography, the—a bunch of them recently. And that's just the way it is. Microsoft biography, same thing, right? You know, so don't—I mean, and you—the VC can feel those five minutes of impact were amazing and they feel really good about them and you feel warm and fuzzy but, you know, the only thing founders really remember for better or ill is, \"Oh my God, our backs were to the wall and no one would put in money and they put in money.\" They remember that.","offset":4619,"duration":29},{"text":"Jason: Some—some—sometimes. In my experience, sometimes, Rory.","offset":4648,"duration":3},{"text":"Rory: Sometimes they even forget that. Well, but to your point, Jason, if they forget—","offset":4651,"duration":3},{"text":"Jason: At least half the time they forget that.","offset":4654,"duration":1},{"text":"Rory: If they forget that, they're definitely going to forget the time you made that phone call to help them connect with XYZ and that helped them do something because that's something that happens a hundred times a day. No, you're right.","offset":4655,"duration":10},{"text":"Jason: Yeah.","offset":4665,"duration":1},{"text":"Rory: We're not the stars in the drama. We're—we're just bit players who get well paid for our part.","offset":4666,"duration":6},{"text":"Harry: Boys, as always, the most humbling 90 minutes of my week.","offset":4672,"duration":3},{"text":"Jason: I'm afraid you'll get more.","offset":4675,"duration":2},{"text":"Rory: You'll be humbled tomorrow.","offset":4677,"duration":2},{"text":"Harry: You'd be surprised.","offset":4679,"duration":2},{"text":"(Audio ends)","offset":4681,"duration":15}],"logs":[{"elapsed":"0.0","message":"Downloading audio from YouTube...","detail":null},{"elapsed":"0.0","message":"Trying download with browser cookies (ad-free)...","detail":null},{"elapsed":"2.8","message":"⚠ Cookie download failed: WARNING: [youtube] [jsc] Error solving n challenge request using \"deno\" provider: Error running deno process (returncode: 1): \u001b[0m\u001b[1m\u001b[31merror\u001b[0m: Uncaught (in promise) TypeError: Cannot read prope","detail":null},{"elapsed":"2.8","message":"Retrying without cookies...","detail":null},{"elapsed":"35.4","message":"⚠ Downloaded without cookies — audio may contain ads","detail":null},{"elapsed":"35.4","message":"Audio downloaded (42.4 MB) in 35.4s","detail":"File size: 42.4 MB"},{"elapsed":"35.4","message":"Video title: OpenAI Kills Sora & Hits $100M ARR on Ads | Oura Going Public & Whoop Raises at $10BN","detail":null},{"elapsed":"35.4","message":"Audio duration: 1:12:40 (72.7 min)","detail":null},{"elapsed":"35.4","message":"Large audio (72.7 min) — will use chunked transcription with gemini-3-flash-preview","detail":null},{"elapsed":"35.4","message":"Skipping full-file attempt — using chunked transcription for 72.7 min audio","detail":null},{"elapsed":"35.8","message":"Split audio into 2 chunks for transcription","detail":null},{"elapsed":"35.8","message":"Transcribing chunk 1/2 (starts at 0:00)...","detail":null},{"elapsed":"35.8","message":"Uploading audio to Gemini File API...","detail":null},{"elapsed":"39.9","message":"Audio uploaded in 4.1s","detail":"File ref: files/qayd4s5cwjo9"},{"elapsed":"39.9","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"111.8","message":"Chunk 1: 95 segments, last timestamp 52:18","detail":null},{"elapsed":"111.8","message":"Transcribing chunk 2/2 (starts at 45:00)...","detail":null},{"elapsed":"111.8","message":"Uploading audio (offset 45:00) to Gemini File API...","detail":null},{"elapsed":"114.7","message":"Audio uploaded in 2.9s","detail":"File ref: files/zx2q22hqixbw"},{"elapsed":"114.7","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"171.4","message":"Chunk 2: 172 segments, last timestamp 1:18:01","detail":null},{"elapsed":"171.4","message":"Chunked transcription complete: 235 total segments","detail":null},{"elapsed":"171.4","message":"Total cost: 109,552 in / 24,064 out — cost: $0.1270","detail":null},{"elapsed":"171.4","message":"Total transcription time: 136.0s — 235 segments","detail":null},{"elapsed":"171.4","message":"Analyzing topics across 235 segments with gemini-3.1-pro-preview...","detail":null},{"elapsed":"228.2","message":"Topic analysis complete in 56.8s — found 16 topics","detail":null},{"elapsed":"228.2","message":"Analysis tokens: 22,865 in / 1,436 out / 6,374 thinking — cost: $0.1395","detail":null},{"elapsed":"228.2","message":"Pipeline finished in 228.2s — total cost: $0.2664 (164,291 tokens)","detail":null}]} \ No newline at end of file diff --git a/history/1775587377519-Rc9lTSs7wgI.json b/history/1775587377519-Rc9lTSs7wgI.json new file mode 100644 index 0000000..e23f1d8 --- /dev/null +++ b/history/1775587377519-Rc9lTSs7wgI.json @@ -0,0 +1 @@ +{"id":"1775587377519-Rc9lTSs7wgI","videoId":"Rc9lTSs7wgI","url":"https://www.youtube.com/watch?v=Rc9lTSs7wgI","title":"While Everyone Was Watching Iran, They Missed This","type":"youtube","topicCount":6,"segmentCount":15,"createdAt":"2026-04-07T18:42:57.519Z","uploadDate":"20260406","chunks":[{"title":"Introduction and Weekend Catch-up","summary":"The host and Arnold briefly discuss their Easter weekend and joke about the increasing number of Catholic converts before diving into the episode's main topics.","entries":[{"text":"Host: Mr. Arnold, here we are again, another Monday morning. How was your weekend?","offset":0,"duration":5},{"text":"Arnold: Terrific, great Easter, hope everyone else had a great Easter as well. Got to mass, jam-packed as we were talking about before we started. So very bullish in a world with not a, not always a ton to be bullish about... that was bullish.","offset":5,"duration":13}],"startTime":0},{"title":"Navigating Geopolitical Noise","summary":"The hosts discuss the difficulty of interpreting the Trump administration's erratic geopolitical messaging. They emphasize the need to look past confusing headlines and focus on concrete data points to understand actual policy logic.","entries":[{"text":"Host: Yeah, if there is one number going up, it is Catholic converts in recent years. But we are not here to discuss Catholicism, we're here to talk Bitcoin markets and what's going on in the world. You titled this week's 10:31 timestamp, \"Schrödinger's Regime Change,\" and basically highlighted that it's very hard to discern what's going on if you're simply looking at the headlines coming out of the Trump administration. Particularly and the IRGC for that matter, obviously we have two sides of a war that have very specific motives to try to get what they want in terms of leverage and that is leading to a lot of chaos and uncertainty in markets. And a lot of your focus this week is what should we be focusing on to actually discern some signal from all the noise out there?","offset":18,"duration":47},{"text":"Arnold: Yeah, absolutely. In putting this newsletter together week to week, it's just gotten to the point where, you know, you try to stay on top of all the headlines and all the data points that could be pointing one way or another, and it's just gotten to the point where it almost all feels kind of pointless to really follow it all that closely. If you pull up the first slide for today, I just kind of screen capped a piece of the newsletter with the bullet points showing all the different ways that Trump and the administration more broadly seem to have flip-flopped, intentionally or not, often within the same hour on key things, like whether the Iranian regime has changed or not, whether he's now working with people who want to make a sensible deal or whether they're doubling down, whether we're going to force the Strait of Hormuz to be reopened and take all the oil, or make other people do it, or we're just going to leave without dealing with it. You know, you can see all these things every single, basically every single hour there's a version of this. And it feels very, for the under-50 crowd, maybe under-40 crowd, there's an image you can hear on the left side of the screen here, and the over-50s probably will not even be able to relate to it even if they look it up. But for anyone who's aware of Leroy Jenkins, that's what it all feels like, right? Whether intentionally or not, whether you're a plan-truster or a panicker, whether you think that there's a bunch of strategic logic under the hood, or whether Trump is in the early stages of dementia and is flushing the country down the drain as a result. It feels from the outside like a lot of Leroy Jenkins with everything that's going on. And so it just got to the point where I was like, okay, well what are the concrete data points that we should be focusing on, what can we attach to to figure out what might be actionable or happening under the hood as a derivative result of all this, regardless of what happens from here, regardless of what kind of logic might exist or not in the plan such as it is. So that was kind of my focus for this week and I definitely think there are a few big things we can dive into that are worth thinking about that are going to be relevant, regardless of what happens with Hormuz, regardless of what happens with Trump and Israel and the IRGC.","offset":65,"duration":121}],"startTime":18},{"title":"Strait of Hormuz and Global Sanctions","summary":"Analyzing a recent analyst report, the hosts discuss the nuanced reality of oil flows through the Strait of Hormuz. They note that countries like Japan and France are prioritizing their physical energy needs over strict adherence to Western sanction regimes.","entries":[{"text":"Host: Yeah, I think maybe starting with barrels of oil and how much are actually, not only being produced, but actually being delivered from that part of the world. And you touched on this: roughly four million barrels of oil exited the waterway on Thursday, the largest outflow since the start of the conflict. At the same time, the French-owned container ship crossed the strait, marking the first explicitly Western crossing since February. And so it seems like the activity in terms of ships actually making it through the strait is beginning to increase consistently. And I was telling you before we hit record, I thought it was very fitting that Citrini released their report of analyst number three heading to that part of the world to observe with his own eyes what was going on. Because it essentially confirms what you wrote about this week, which is that it seems like activity is increasing and I think not only did it confirm that quantitative data, but I think the qualitative data of this is not really a binary situation here. It's very nuanced, there are obviously multiple players and different incentives at play. And I think the most important incentive that was highlighted by Citrini in their report was that Iran wants to keep the strait open because they need to project that they actually have control and are acting as a responsible actor in that part of the world. Sort of enticing countries that need oil to work with them to create this tollway that many people have discussed.","offset":186,"duration":85},{"text":"Arnold: Yeah, for sure. It's a great piece, everyone should go read it, highly recommend paying for a Citrini subscription to do that. But yeah, I think the big takeaway, you know, this won't be spoiling anything and there's a lot more alpha in there that you can go read about, but I think the big, interesting takeaway from it is everyone on the ground seems to think both that we're going to get messy military escalation that will not end soon, and more oil is going to progressively flow out of the strait. Because as you said, there are a lot of interests aligned on all sides to keep oil moving through the strait. Iran wants to do that both to project an image of itself as kind of the wise governor of those resources in that waterway in opposition to the crazy Leroy Jenkins US, also a key source of revenue for the country. So shutting down oil flows there and also for its adversaries that may get even more aggressive with it if they literally can't ship massive amounts of oil through that strait for a meaningful amount of time... that all leads in a very bad path for everyone, so there's this kind of tacit desire and understanding to that everyone wants oil to flow out of the strait in one way or another. And Iran has thus far, it seems like erected some sort of like toll booth system that you can go read about that seems to be getting broader and broader in the participants that are allowed to be involved in that. But I think that the piece also has an interesting set of implications that they outline at the end, which is basically kind of undermining both poles of like reading what's going on. You know, there's been on one side kind of this very, you know, frankly like you see it a lot in our camp, you see it a lot in the kind of pro-Bitcoin or pro-gold sound money like death of the dollar type camp saying like, \"This is the beginning of the petro-yuan and all the only tankers that can get through are paying in yuan and this is the beginning of China dominating global oil flows and energy markets.\" And on the other side you've got and perhaps it's not even appropriate to call it the other side but guys that we flagged on this podcast before like Anas Alhajji who are, you know, real experts in global energy markets kind of saying that this Western consensus reading of what's going on is basically all a sham, and the only reason that you're not seeing ships flow through is because of the issues in the insurance market with all these tankers, which maybe is driven by US interest. And so in some sense, the US is kind of driving all this. And I think the report's interesting because it basically puts both of those somewhat, it really undermines both of those to some degree. Interestingly, Citrini's analyst, unclear who that guy is, I have to think he's not a denizen of traditional finance because I can't imagine anyone who actually worked on Wall Street doing what this dude did... very entertaining stuff, again I recommend people read. But you know, what he found was that yeah, there's a little Chinese yuan facilitating payments, but a huge amount of it is through diplomatic channels. You know, back-channeling between different countries and different quid pro quo trades being made totally out of band between those countries to guarantee safe passage for tankers that are aligned with different countries or different groups. There does appear to be ongoing fear of OFAC sanctions and so that's forcing different ways of facilitating this. I think that's interesting and relevant as it relates to how dominant the US dollar system still realistically is globally. On the flip side, also a lot of locals are reporting that their main concern is not getting killed, right? Not getting blown up drafting through the strait, and insurance is kind of a secondary concern. Also some interesting data points in there on the rates that some of these tankers are getting paid just to basically be floating storage in kind of the current disrupted market and how that also is kind of a disincentive, insurance or not, to go through and risk your life and risk your ship. So all that is to say like I think this just highlights what we've been saying the last few weeks: the simple stories just like don't really work. You're going to have to have like an interpretive lens that's kind of multivariate and doesn't isn't reducible to kind of one simple story. And so I again think that just further highlights the need to focus on data points outside of like the constant stream of of headlines, whether pro-Trump or anti-Trump, pro-Iran or anti-Iran, and look at what's actually happening in other markets that are maybe downstream of this or potentially orthogonal to this and flow that back to the decision tree that the US is going to be looking at over the next month or two.","offset":271,"duration":255},{"text":"Host: Yeah, I thought after having read the piece that the tidbit here, which you've highlighted a bit, I don't think the direct highlight, but some countries are unfreezing sanctioned assets, Iranian assets, to let things flow. And to your point, that does throw a wrench in the US and Western sanction regime. And it really highlights like when push comes to shove, this rule-based order that many people have talked about for decades and Trump specifically called out in his national strategic or security strategy letter last year, it definitely seems to be fading away. And this is yet another data point that proves okay, this this sanction regime that has existed that's been dominated by the West seems to be dissolving in front of our eyes and push is coming to shove, whether the US likes it or not. The countries that are working with the IRGC right now need the oil. And I thought two names on the list and they've made the headlines the last couple of weeks, but I think this report verified it... I mean Japan and France are essentially forced to play ball. They're deciding, hey we need this oil more than we need the sort of social cachet with with the United States right now. Like we need to make sure that our systems are operating and our economy can actually function. And so you're seeing this sort of physical reality enter into the realm of geopolitics and a reshuffling of the board in real time. And we're you posted this as well, but obviously again Leroy Jenkins on Easter, Trump is praising Allah and saying that we're going to blow up power plants, \"Open the fucking strait, you crazy bastards, you'll be living in hell.\" Very Caligula-esque as some some were describing yesterday. I was not on Twitter much, but I did catch this. Bitcoin reacted to this. Who knows if it reacted to this, but coincidentally after this Truth Social post was sent out, Bitcoin rallied a bit.","offset":526,"duration":119}],"startTime":186},{"title":"Critical Materials and Supply Chains","summary":"Arnold highlights key physical world developments to monitor, including helium shortages, a new US-Qatar LNG facility in Texas, Alberta's separatist movement, and Western efforts to secure rare earth refining.","entries":[{"text":"Arnold: Yeah, you know my my guys out here having a normal one on Easter morning with with this tweet. But you know, I threw the Bitcoin chart in there just because I think it's an interesting direction for it to move... this is the 24 hours after this this tweet was posted. So do I think it was popping on this exactly? Like no. But this is the kind of thing that I think my knee-jerk would have been like, okay we're going to dump another couple couple grand on a comment like that. And we kind of did the opposite, even over the weekend in kind of a liquidity-constrained time when most markets aren't open. So you know, an interesting counterfactual data point. We'll see if it ultimately means anything. But yeah, I think it's you know, gets to the same Leroy Jenkins point we've been talking about. And I think you know that maybe we can jump in from there... like a couple slides down, some of the the physical world realities that that you're talking about that I highlighted in the piece and we've mentioned this before on the show, but just just a couple to flag. You're really starting to see headlines about helium production shortages biting. This is a key input to among other things, semiconductor manufacturing, which is you know, among the most sensitive, perhaps the most sensitive advanced manufacturing industry in the world right now. The split there is basically a huge amount from Qatar. A lot of that's offline now with all the damage to infrastructure in the Gulf. And that leaves basically the US in pole position to kind of control flows of this this critical input. And you also see interestingly this past week Qatar and Exxon's joint venture to produce LNG, 18 million metric tons per year, which would more than offset the amount that's currently offline as a result of the attacks on Qatar's facilities in the Gulf. That's coming online and interestingly, that is not a replacement facility in the Middle East or somewhere else. It's in Texas. It's a 70-30 joint venture between Qatar Energy and Exxon, and headlines I've seen suggest that's going to ramp up to full capacity over the next 12 months, roughly. So we'll see if that happens. But interestingly highlighting like the cards to some extent that the US does have to play right on the physical production reality side. Definitely does not mean that the US is out of the woods, but things like this are I think going to be increasingly important to watch as supply chains fracture and basic materials that a lot of us either took for granted or had never really heard of or thought of before kind of become the poles along which this fight is progresses and along which countries kind of try to exercise leverage on on one another. And you know, the next slide shows the same thing in kind of different ways. These are not again things to like necessarily trade on or to construct a thesis on, but I think they're all like collectively they form an interesting mosaic for what the US might be trying to do TBD whether they can. But our friends to the north in the the province of Canada that produces most of Canada's oil, Alberta, seem to be on a separatist path, a secessionist path that is not going away. And they've got apparently the required signatures now to launch a referendum vote on starting a separation process. That vote will take place in October and it seems like there's a decent amount of linkage, perhaps engineered by the CIA, perhaps not. But a decent amount of linkage between Alberta separatists and the Trump administration. And on the rare earth side, you see on on the right-hand side a couple headlines from last week about the US kind of moving aggressively to gain some control over some some key rare earth materials. A key question here is still the the refining of these things. They're actually not that rare in terms of deposits, but actually getting them refined is a very messy and difficult process that China has gladly you know, taken taken up over the last 20 years as the West was collectively kind of casting out all quote-unquote dirty industries. So moving in a you know, strategically relevant direction, still very much like first or second inning on on those things. But collectively, I just think like those are key data points to be watching. Like things like that are, I think, are forming the base that we should be watching more and more closely and are kind of telling you collectively as a mosaic you know, where things might might be going over the next 12 months.","offset":645,"duration":246}],"startTime":645},{"title":"The Quantum Computing Threat to Bitcoin","summary":"The conversation shifts to recent advancements in quantum computing and the resulting panic over Bitcoin's cryptographic security. The hosts advocate for a methodical, panic-free approach to implementing post-quantum signature schemes, emphasizing trust in specialized developers.","entries":[{"text":"Host: Add a few tallies to the 4D chess column right there. I mean, again, that's why I love doing this show with you every Monday because I think you do a good job of zooming out and really trying to filter. And I think these are definitely things that make me believe okay, maybe there is a plan here despite what Trump may be posting on any given day or any given hour of any given day. These are strategic moves to re-industrialize and create alliances, whether it's in Africa, Latin America or soon to be our neighbors to the north. Alberta, it's always been on my mind... there's so much potential there and the the sort of thirst for freedom that that exists in that particular province is palpable, knowing some Albertans ourselves. Having having one very staunch Albertan in the portfolio and Steve Barber and Upstream Data. I'm cheering for them, if I'm being honest. I'm letting my bias shine through here. But I think we risk becoming too much of a macro-geopolitical think-tank podcast and so I think we should shift to some Bitcoin-specific topics. And I think the big one last week was the reemergence of quantum fud. It seems like that is reemerging at a quickened pace as as new papers are released. And obviously, I'm sure most of you know, Google released a paper last week that basically cited or basically claimed that the amount of theoretical or the amount of logical theoretically the amount of logical qubits that would be needed to use Shor's algorithm to break ECDSA was reduced significantly. And this led many of the quantum panickers to come out and say that Bitcoin needs to upgrade as quickly as possible to be quantum-resistant because it seems like a cryptographically relevant quantum computer may be on the horizon. And so this started a lot of conversation last week. I had Brandon Black, also known as Rearden Code on the TFTC podcast, that episode dropped Saturday morning and we tried to do our best to to do a methodical walk-through of the spectrum of the quantum debate as it relates to Bitcoin and where we actually sit. I will put a hand up and say obviously I think Brandon and I are a bit biased towards the \"it's not as big of a worry as many are making it out to be,\" but I think we tried to to cover all the bases there. What are your thoughts on the quantum debate?","offset":891,"duration":149},{"text":"Arnold: Yeah, I mean it's funny like as it relates to the theme of what can we actually know? Like what can we actually reasonably assess? You know, that's why I titled the essay this week \"Schrödinger's Regime Change\" and said the subtitle was like \"A Superposition of Hot Takes\" because you very much have that on the geopolitical macro scale of kind of what's actually happening. Is there a plan? Is there not a plan? Is Iran almost as strong as they've ever been or are they about to fall? Kind of both of those things are the case at once. Like there's kind of a superposition as well of takes on quantum... you know where we are almost there and Bitcoin's cooked, or this is literally never going to happen and it's all fairy dust and anyone thinking about it is completely wasting their time. I think you your episode with Brandon did a really good job of, you know, he's he's very skeptical of the the claims here. I think I would put myself in that camp as well. But you know, I think you guys did a balanced job of walking through the puts and takes and the the pros and cons and the different cases that one could make, as well as you know, realistic mitigation strategies. And you know, I recommend people go listen to that. And I also recommend people you know, take as middle-of-the-road an approach as is possible here. Generally, I think both of those poles that I mentioned are probably not the place you want to be even though I would probably say if you gun to my head, I wouldn't make the bet that if you said is it ever going to happen is a CRQC ever actually going to be instantiated in physical reality? I would probably still shade to no. That said, you made a really good point I think over the weekend that there's we should already be assuming that ECDSA is not going to last forever, right? There are always advancements in cryptography, advancements in technology. You never want to short human ingenuity especially when there's you know, value involved and in any kind of system that is monetary in nature or that has an incentive to be attacked, you know, whether that's Bitcoin or any other system that depends on ECDSA or RSA or any other cryptographic scheme. So generally, I think it it makes sense to have some level of you know, preparation, some level of understanding of the problem space. I think it's important for people to look who see the scary headlines from Google and QuEra to like Brandon recommended kind of think through: there's the mathematical and theoretical side of things and then there's the actual physical reality, like we talked about earlier with other elements of the world, you know, the physical reality of bringing this into into being. And the advancements on the latter have not been nearly as impressive as the advancements on the former of kind of the the theory of how this could work on a machine that does not exist. But regardless of what your ultimate view on all that is, I think the the thing that you can most clearly like anchor to as something that's observable is that there has been a lot of work done on this by Bitcoin devs and people who are generally just around the cryptography space. I listed a bunch of them in the newsletter that people can go back and look at. Jonas Nick had a proposal just last week, coincidentally timed I think on the same day as these papers dropped, for he's calling it \"SHRIMP\"... and you know, you can just go go look at kind of what that involves but basically would be post-quantum signatures on Bitcoin that are substantially smaller in terms of data requirement than prior prior proposals. That's a relevant trade-off for us to think through as we add any novel cryptography to Bitcoin, the the way that heavier signatures to to have quantum security might affect throughput. So that's one of the trade-offs to think about. Another big one, the last thing I'll say that I think people need to always keep in mind with this or any other situation is like we as humans naturally have action bias toward any problem. I think we all saw that especially during COVID. But you see it during any kind of crisis event, the impulse is to do something, just literally do anything. And oftentimes like it's very easy to forget that doing something is is not itself risk-less and you know, can carry especially if you if the thing that you do is very rushed in in nature and done in a sense of panic or false urgency, you know, that can carry its own downsides that need to be thought through, right? And you know, I've said this elsewhere and I think you've said it too, but if I were a state actor and I wanted to disrupt Bitcoin, one of the things that I would definitely do would be to engineer some sort of panic state that would make people add untested novel cryptography to Bitcoin, right? And make people rely on that, and you potentially have you know, the possibility for backdoors that are undiscovered due to being you know, untested or not tested sufficiently. So not at all saying that that's my base case for like what is happening here, not attributing any bad faith to anyone who is involved in quantum projects or talking about this on Twitter or elsewhere. But simply just stating that's an example of like an unintended consequence, a potential downside that needs to be thought through as we look to kind of restrain our action bias and just approach things you know, from from as sober a lens as possible.","offset":1040,"duration":284},{"text":"Host: Yeah, completely agree there. I would just add just to clarify, like to me and you referenced the tweet I sent out, but I think, and again not a quantum physicist, I'm not a cryptographer, but from what I can gather the theoretical side of quantum computing is advancing at a rapid clip, which is great. You have some of the smartest people in the world working on these theoretical physics problems and they're making strong advancements. But the physical applied physics side of things just hasn't made the same advancements and again, Brandon said it during our conversation, there hasn't even been one sort of standardized quantum computer that you could benchmark to itself that has made progress consistently over a certain period of time. And the way he put it is until you see one standard set and being iterated on and improved at a consistent pace then there it seems like you're panicking for for no reason. Just to steelman it, or to be fair to both sides, the other side will say well we're not going to get the warnings that these advancements on the physical applied side are being made and Q-Day is coming faster so you have to prepare now. And I'm not convinced. I think methodical, consistent progress towards a solution, like you said many Bitcoin developers think on a long enough timeline ECDSA will be broken eventually and they've already been preparing for new cryptographic signature schemes that we will transition to. You mentioned Jonas Nick's SHRIMPs paper that he released, I think one sort of point of context I wanted to add to that: it was an iteration on \"SHRINKS+\", which was a solution that Jonas Nick and Mikhail Kudinov came up with through their research of hash-based signature schemes that could be added to Bitcoin and make it quantum-resistant. They released that paper in December, and so here we are, beginning of April, end of March, a quarter later, Jonas is already sort of advanced that primitive idea and made it more efficient. And so the progress is being made on the research side of what we need to do to upgrade Bitcoin's signature scheme for a world in which ECDSA is broken, or a world in which quantum computers manifest, exist, and are scalable and efficient. And so yeah, I think I think a level-headed approach to this is is the best way. And another thing, last thing I'll say on this, the when you're out there and you're not immersed in this debate and you're an outside observer looking at this and you have Chamath Palihapitiya, you have Nick Carter and others saying we need to do this now and they're saying \"Bitcoin developers need to get together and solve this problem\"... I think one thing to understand is that not every Bitcoin developer is qualified or equipped to solve this specific problem. There are many different parts of the Bitcoin stack, people working on the P2P layer, initial block download, networking between nodes, wallet GUIs, all of that... and there is a subset of a subset of Bitcoin developers that really understand the cryptography, and then within that subset of a subset, a subset that understands how to make it quantum-resistant. So finger-wagging at every Bitcoin developer and saying do something is completely unproductive because not every Bitcoin developer is focused on this specific part of the Bitcoin stack. The people who are are making progress.","offset":1324,"duration":189},{"text":"Arnold: Yeah, I mean the last thing I'll say is to that point: there's a concept called a \"load-bearing internet person,\" someone who's just like 10,000x the the median engineer or the median computer scientist on questions of the design of the internet, internet protocol. I think there's very much like a similar concept here of a \"load-bearing cryptography person.\" I mean, there are literally like probably under 50 people in the world who are truly like masters of this this domain, you know, or maybe under 1,000, I don't know however you would frame it. But you know, to the extent that you think that that's like a risk to Bitcoin, it's also a risk to every digital system that we have in the world. There are so few people who are really equipped to to think through all this stuff. But it's so worth noting as you just ask yourself, to that point, like \"Why isn't this solved?\" Well, it's a very thorny question that not everyone in the world or even a majority of people who are deeply involved in Bitcoin are really qualified to you know, weigh in on and opine on. So all the more reason then, right, to be methodical about it and to make sure that nothing is getting kind of rushed or pushed faster than you know, it needs to go, particularly given some of the questions that you highlighted around the actual physical scaling progress of of getting this stuff out into the real world. So yeah again, you know, avoid the black boxes, focus on what you can actually analyze and get your hands around and try not to weigh in on the stuff that's borderline impossible to really figure out.","offset":1513,"duration":78},{"text":"Host: Yeah, and to flip the frame there: the fact that Bitcoin, the Bitcoin project has a few of these individuals who are qualified and equipped to do this work is high signal that it is a very valuable protocol. The fact that it's able to attract that type of talent that can actually solve these problems is an endorsement in and of itself.","offset":1591,"duration":20},{"text":"Arnold: Yep, co-sign.","offset":1611,"duration":1}],"startTime":891},{"title":"Outro","summary":"The host concludes the discussion and signs off until the following week.","entries":[{"text":"Host: All right, see you guys next week.","offset":1612,"duration":15}],"startTime":1612}],"entries":[{"text":"Host: Mr. Arnold, here we are again, another Monday morning. How was your weekend?","offset":0,"duration":5},{"text":"Arnold: Terrific, great Easter, hope everyone else had a great Easter as well. Got to mass, jam-packed as we were talking about before we started. So very bullish in a world with not a, not always a ton to be bullish about... that was bullish.","offset":5,"duration":13},{"text":"Host: Yeah, if there is one number going up, it is Catholic converts in recent years. But we are not here to discuss Catholicism, we're here to talk Bitcoin markets and what's going on in the world. You titled this week's 10:31 timestamp, \"Schrödinger's Regime Change,\" and basically highlighted that it's very hard to discern what's going on if you're simply looking at the headlines coming out of the Trump administration. Particularly and the IRGC for that matter, obviously we have two sides of a war that have very specific motives to try to get what they want in terms of leverage and that is leading to a lot of chaos and uncertainty in markets. And a lot of your focus this week is what should we be focusing on to actually discern some signal from all the noise out there?","offset":18,"duration":47},{"text":"Arnold: Yeah, absolutely. In putting this newsletter together week to week, it's just gotten to the point where, you know, you try to stay on top of all the headlines and all the data points that could be pointing one way or another, and it's just gotten to the point where it almost all feels kind of pointless to really follow it all that closely. If you pull up the first slide for today, I just kind of screen capped a piece of the newsletter with the bullet points showing all the different ways that Trump and the administration more broadly seem to have flip-flopped, intentionally or not, often within the same hour on key things, like whether the Iranian regime has changed or not, whether he's now working with people who want to make a sensible deal or whether they're doubling down, whether we're going to force the Strait of Hormuz to be reopened and take all the oil, or make other people do it, or we're just going to leave without dealing with it. You know, you can see all these things every single, basically every single hour there's a version of this. And it feels very, for the under-50 crowd, maybe under-40 crowd, there's an image you can hear on the left side of the screen here, and the over-50s probably will not even be able to relate to it even if they look it up. But for anyone who's aware of Leroy Jenkins, that's what it all feels like, right? Whether intentionally or not, whether you're a plan-truster or a panicker, whether you think that there's a bunch of strategic logic under the hood, or whether Trump is in the early stages of dementia and is flushing the country down the drain as a result. It feels from the outside like a lot of Leroy Jenkins with everything that's going on. And so it just got to the point where I was like, okay, well what are the concrete data points that we should be focusing on, what can we attach to to figure out what might be actionable or happening under the hood as a derivative result of all this, regardless of what happens from here, regardless of what kind of logic might exist or not in the plan such as it is. So that was kind of my focus for this week and I definitely think there are a few big things we can dive into that are worth thinking about that are going to be relevant, regardless of what happens with Hormuz, regardless of what happens with Trump and Israel and the IRGC.","offset":65,"duration":121},{"text":"Host: Yeah, I think maybe starting with barrels of oil and how much are actually, not only being produced, but actually being delivered from that part of the world. And you touched on this: roughly four million barrels of oil exited the waterway on Thursday, the largest outflow since the start of the conflict. At the same time, the French-owned container ship crossed the strait, marking the first explicitly Western crossing since February. And so it seems like the activity in terms of ships actually making it through the strait is beginning to increase consistently. And I was telling you before we hit record, I thought it was very fitting that Citrini released their report of analyst number three heading to that part of the world to observe with his own eyes what was going on. Because it essentially confirms what you wrote about this week, which is that it seems like activity is increasing and I think not only did it confirm that quantitative data, but I think the qualitative data of this is not really a binary situation here. It's very nuanced, there are obviously multiple players and different incentives at play. And I think the most important incentive that was highlighted by Citrini in their report was that Iran wants to keep the strait open because they need to project that they actually have control and are acting as a responsible actor in that part of the world. Sort of enticing countries that need oil to work with them to create this tollway that many people have discussed.","offset":186,"duration":85},{"text":"Arnold: Yeah, for sure. It's a great piece, everyone should go read it, highly recommend paying for a Citrini subscription to do that. But yeah, I think the big takeaway, you know, this won't be spoiling anything and there's a lot more alpha in there that you can go read about, but I think the big, interesting takeaway from it is everyone on the ground seems to think both that we're going to get messy military escalation that will not end soon, and more oil is going to progressively flow out of the strait. Because as you said, there are a lot of interests aligned on all sides to keep oil moving through the strait. Iran wants to do that both to project an image of itself as kind of the wise governor of those resources in that waterway in opposition to the crazy Leroy Jenkins US, also a key source of revenue for the country. So shutting down oil flows there and also for its adversaries that may get even more aggressive with it if they literally can't ship massive amounts of oil through that strait for a meaningful amount of time... that all leads in a very bad path for everyone, so there's this kind of tacit desire and understanding to that everyone wants oil to flow out of the strait in one way or another. And Iran has thus far, it seems like erected some sort of like toll booth system that you can go read about that seems to be getting broader and broader in the participants that are allowed to be involved in that. But I think that the piece also has an interesting set of implications that they outline at the end, which is basically kind of undermining both poles of like reading what's going on. You know, there's been on one side kind of this very, you know, frankly like you see it a lot in our camp, you see it a lot in the kind of pro-Bitcoin or pro-gold sound money like death of the dollar type camp saying like, \"This is the beginning of the petro-yuan and all the only tankers that can get through are paying in yuan and this is the beginning of China dominating global oil flows and energy markets.\" And on the other side you've got and perhaps it's not even appropriate to call it the other side but guys that we flagged on this podcast before like Anas Alhajji who are, you know, real experts in global energy markets kind of saying that this Western consensus reading of what's going on is basically all a sham, and the only reason that you're not seeing ships flow through is because of the issues in the insurance market with all these tankers, which maybe is driven by US interest. And so in some sense, the US is kind of driving all this. And I think the report's interesting because it basically puts both of those somewhat, it really undermines both of those to some degree. Interestingly, Citrini's analyst, unclear who that guy is, I have to think he's not a denizen of traditional finance because I can't imagine anyone who actually worked on Wall Street doing what this dude did... very entertaining stuff, again I recommend people read. But you know, what he found was that yeah, there's a little Chinese yuan facilitating payments, but a huge amount of it is through diplomatic channels. You know, back-channeling between different countries and different quid pro quo trades being made totally out of band between those countries to guarantee safe passage for tankers that are aligned with different countries or different groups. There does appear to be ongoing fear of OFAC sanctions and so that's forcing different ways of facilitating this. I think that's interesting and relevant as it relates to how dominant the US dollar system still realistically is globally. On the flip side, also a lot of locals are reporting that their main concern is not getting killed, right? Not getting blown up drafting through the strait, and insurance is kind of a secondary concern. Also some interesting data points in there on the rates that some of these tankers are getting paid just to basically be floating storage in kind of the current disrupted market and how that also is kind of a disincentive, insurance or not, to go through and risk your life and risk your ship. So all that is to say like I think this just highlights what we've been saying the last few weeks: the simple stories just like don't really work. You're going to have to have like an interpretive lens that's kind of multivariate and doesn't isn't reducible to kind of one simple story. And so I again think that just further highlights the need to focus on data points outside of like the constant stream of of headlines, whether pro-Trump or anti-Trump, pro-Iran or anti-Iran, and look at what's actually happening in other markets that are maybe downstream of this or potentially orthogonal to this and flow that back to the decision tree that the US is going to be looking at over the next month or two.","offset":271,"duration":255},{"text":"Host: Yeah, I thought after having read the piece that the tidbit here, which you've highlighted a bit, I don't think the direct highlight, but some countries are unfreezing sanctioned assets, Iranian assets, to let things flow. And to your point, that does throw a wrench in the US and Western sanction regime. And it really highlights like when push comes to shove, this rule-based order that many people have talked about for decades and Trump specifically called out in his national strategic or security strategy letter last year, it definitely seems to be fading away. And this is yet another data point that proves okay, this this sanction regime that has existed that's been dominated by the West seems to be dissolving in front of our eyes and push is coming to shove, whether the US likes it or not. The countries that are working with the IRGC right now need the oil. And I thought two names on the list and they've made the headlines the last couple of weeks, but I think this report verified it... I mean Japan and France are essentially forced to play ball. They're deciding, hey we need this oil more than we need the sort of social cachet with with the United States right now. Like we need to make sure that our systems are operating and our economy can actually function. And so you're seeing this sort of physical reality enter into the realm of geopolitics and a reshuffling of the board in real time. And we're you posted this as well, but obviously again Leroy Jenkins on Easter, Trump is praising Allah and saying that we're going to blow up power plants, \"Open the fucking strait, you crazy bastards, you'll be living in hell.\" Very Caligula-esque as some some were describing yesterday. I was not on Twitter much, but I did catch this. Bitcoin reacted to this. Who knows if it reacted to this, but coincidentally after this Truth Social post was sent out, Bitcoin rallied a bit.","offset":526,"duration":119},{"text":"Arnold: Yeah, you know my my guys out here having a normal one on Easter morning with with this tweet. But you know, I threw the Bitcoin chart in there just because I think it's an interesting direction for it to move... this is the 24 hours after this this tweet was posted. So do I think it was popping on this exactly? Like no. But this is the kind of thing that I think my knee-jerk would have been like, okay we're going to dump another couple couple grand on a comment like that. And we kind of did the opposite, even over the weekend in kind of a liquidity-constrained time when most markets aren't open. So you know, an interesting counterfactual data point. We'll see if it ultimately means anything. But yeah, I think it's you know, gets to the same Leroy Jenkins point we've been talking about. And I think you know that maybe we can jump in from there... like a couple slides down, some of the the physical world realities that that you're talking about that I highlighted in the piece and we've mentioned this before on the show, but just just a couple to flag. You're really starting to see headlines about helium production shortages biting. This is a key input to among other things, semiconductor manufacturing, which is you know, among the most sensitive, perhaps the most sensitive advanced manufacturing industry in the world right now. The split there is basically a huge amount from Qatar. A lot of that's offline now with all the damage to infrastructure in the Gulf. And that leaves basically the US in pole position to kind of control flows of this this critical input. And you also see interestingly this past week Qatar and Exxon's joint venture to produce LNG, 18 million metric tons per year, which would more than offset the amount that's currently offline as a result of the attacks on Qatar's facilities in the Gulf. That's coming online and interestingly, that is not a replacement facility in the Middle East or somewhere else. It's in Texas. It's a 70-30 joint venture between Qatar Energy and Exxon, and headlines I've seen suggest that's going to ramp up to full capacity over the next 12 months, roughly. So we'll see if that happens. But interestingly highlighting like the cards to some extent that the US does have to play right on the physical production reality side. Definitely does not mean that the US is out of the woods, but things like this are I think going to be increasingly important to watch as supply chains fracture and basic materials that a lot of us either took for granted or had never really heard of or thought of before kind of become the poles along which this fight is progresses and along which countries kind of try to exercise leverage on on one another. And you know, the next slide shows the same thing in kind of different ways. These are not again things to like necessarily trade on or to construct a thesis on, but I think they're all like collectively they form an interesting mosaic for what the US might be trying to do TBD whether they can. But our friends to the north in the the province of Canada that produces most of Canada's oil, Alberta, seem to be on a separatist path, a secessionist path that is not going away. And they've got apparently the required signatures now to launch a referendum vote on starting a separation process. That vote will take place in October and it seems like there's a decent amount of linkage, perhaps engineered by the CIA, perhaps not. But a decent amount of linkage between Alberta separatists and the Trump administration. And on the rare earth side, you see on on the right-hand side a couple headlines from last week about the US kind of moving aggressively to gain some control over some some key rare earth materials. A key question here is still the the refining of these things. They're actually not that rare in terms of deposits, but actually getting them refined is a very messy and difficult process that China has gladly you know, taken taken up over the last 20 years as the West was collectively kind of casting out all quote-unquote dirty industries. So moving in a you know, strategically relevant direction, still very much like first or second inning on on those things. But collectively, I just think like those are key data points to be watching. Like things like that are, I think, are forming the base that we should be watching more and more closely and are kind of telling you collectively as a mosaic you know, where things might might be going over the next 12 months.","offset":645,"duration":246},{"text":"Host: Add a few tallies to the 4D chess column right there. I mean, again, that's why I love doing this show with you every Monday because I think you do a good job of zooming out and really trying to filter. And I think these are definitely things that make me believe okay, maybe there is a plan here despite what Trump may be posting on any given day or any given hour of any given day. These are strategic moves to re-industrialize and create alliances, whether it's in Africa, Latin America or soon to be our neighbors to the north. Alberta, it's always been on my mind... there's so much potential there and the the sort of thirst for freedom that that exists in that particular province is palpable, knowing some Albertans ourselves. Having having one very staunch Albertan in the portfolio and Steve Barber and Upstream Data. I'm cheering for them, if I'm being honest. I'm letting my bias shine through here. But I think we risk becoming too much of a macro-geopolitical think-tank podcast and so I think we should shift to some Bitcoin-specific topics. And I think the big one last week was the reemergence of quantum fud. It seems like that is reemerging at a quickened pace as as new papers are released. And obviously, I'm sure most of you know, Google released a paper last week that basically cited or basically claimed that the amount of theoretical or the amount of logical theoretically the amount of logical qubits that would be needed to use Shor's algorithm to break ECDSA was reduced significantly. And this led many of the quantum panickers to come out and say that Bitcoin needs to upgrade as quickly as possible to be quantum-resistant because it seems like a cryptographically relevant quantum computer may be on the horizon. And so this started a lot of conversation last week. I had Brandon Black, also known as Rearden Code on the TFTC podcast, that episode dropped Saturday morning and we tried to do our best to to do a methodical walk-through of the spectrum of the quantum debate as it relates to Bitcoin and where we actually sit. I will put a hand up and say obviously I think Brandon and I are a bit biased towards the \"it's not as big of a worry as many are making it out to be,\" but I think we tried to to cover all the bases there. What are your thoughts on the quantum debate?","offset":891,"duration":149},{"text":"Arnold: Yeah, I mean it's funny like as it relates to the theme of what can we actually know? Like what can we actually reasonably assess? You know, that's why I titled the essay this week \"Schrödinger's Regime Change\" and said the subtitle was like \"A Superposition of Hot Takes\" because you very much have that on the geopolitical macro scale of kind of what's actually happening. Is there a plan? Is there not a plan? Is Iran almost as strong as they've ever been or are they about to fall? Kind of both of those things are the case at once. Like there's kind of a superposition as well of takes on quantum... you know where we are almost there and Bitcoin's cooked, or this is literally never going to happen and it's all fairy dust and anyone thinking about it is completely wasting their time. I think you your episode with Brandon did a really good job of, you know, he's he's very skeptical of the the claims here. I think I would put myself in that camp as well. But you know, I think you guys did a balanced job of walking through the puts and takes and the the pros and cons and the different cases that one could make, as well as you know, realistic mitigation strategies. And you know, I recommend people go listen to that. And I also recommend people you know, take as middle-of-the-road an approach as is possible here. Generally, I think both of those poles that I mentioned are probably not the place you want to be even though I would probably say if you gun to my head, I wouldn't make the bet that if you said is it ever going to happen is a CRQC ever actually going to be instantiated in physical reality? I would probably still shade to no. That said, you made a really good point I think over the weekend that there's we should already be assuming that ECDSA is not going to last forever, right? There are always advancements in cryptography, advancements in technology. You never want to short human ingenuity especially when there's you know, value involved and in any kind of system that is monetary in nature or that has an incentive to be attacked, you know, whether that's Bitcoin or any other system that depends on ECDSA or RSA or any other cryptographic scheme. So generally, I think it it makes sense to have some level of you know, preparation, some level of understanding of the problem space. I think it's important for people to look who see the scary headlines from Google and QuEra to like Brandon recommended kind of think through: there's the mathematical and theoretical side of things and then there's the actual physical reality, like we talked about earlier with other elements of the world, you know, the physical reality of bringing this into into being. And the advancements on the latter have not been nearly as impressive as the advancements on the former of kind of the the theory of how this could work on a machine that does not exist. But regardless of what your ultimate view on all that is, I think the the thing that you can most clearly like anchor to as something that's observable is that there has been a lot of work done on this by Bitcoin devs and people who are generally just around the cryptography space. I listed a bunch of them in the newsletter that people can go back and look at. Jonas Nick had a proposal just last week, coincidentally timed I think on the same day as these papers dropped, for he's calling it \"SHRIMP\"... and you know, you can just go go look at kind of what that involves but basically would be post-quantum signatures on Bitcoin that are substantially smaller in terms of data requirement than prior prior proposals. That's a relevant trade-off for us to think through as we add any novel cryptography to Bitcoin, the the way that heavier signatures to to have quantum security might affect throughput. So that's one of the trade-offs to think about. Another big one, the last thing I'll say that I think people need to always keep in mind with this or any other situation is like we as humans naturally have action bias toward any problem. I think we all saw that especially during COVID. But you see it during any kind of crisis event, the impulse is to do something, just literally do anything. And oftentimes like it's very easy to forget that doing something is is not itself risk-less and you know, can carry especially if you if the thing that you do is very rushed in in nature and done in a sense of panic or false urgency, you know, that can carry its own downsides that need to be thought through, right? And you know, I've said this elsewhere and I think you've said it too, but if I were a state actor and I wanted to disrupt Bitcoin, one of the things that I would definitely do would be to engineer some sort of panic state that would make people add untested novel cryptography to Bitcoin, right? And make people rely on that, and you potentially have you know, the possibility for backdoors that are undiscovered due to being you know, untested or not tested sufficiently. So not at all saying that that's my base case for like what is happening here, not attributing any bad faith to anyone who is involved in quantum projects or talking about this on Twitter or elsewhere. But simply just stating that's an example of like an unintended consequence, a potential downside that needs to be thought through as we look to kind of restrain our action bias and just approach things you know, from from as sober a lens as possible.","offset":1040,"duration":284},{"text":"Host: Yeah, completely agree there. I would just add just to clarify, like to me and you referenced the tweet I sent out, but I think, and again not a quantum physicist, I'm not a cryptographer, but from what I can gather the theoretical side of quantum computing is advancing at a rapid clip, which is great. You have some of the smartest people in the world working on these theoretical physics problems and they're making strong advancements. But the physical applied physics side of things just hasn't made the same advancements and again, Brandon said it during our conversation, there hasn't even been one sort of standardized quantum computer that you could benchmark to itself that has made progress consistently over a certain period of time. And the way he put it is until you see one standard set and being iterated on and improved at a consistent pace then there it seems like you're panicking for for no reason. Just to steelman it, or to be fair to both sides, the other side will say well we're not going to get the warnings that these advancements on the physical applied side are being made and Q-Day is coming faster so you have to prepare now. And I'm not convinced. I think methodical, consistent progress towards a solution, like you said many Bitcoin developers think on a long enough timeline ECDSA will be broken eventually and they've already been preparing for new cryptographic signature schemes that we will transition to. You mentioned Jonas Nick's SHRIMPs paper that he released, I think one sort of point of context I wanted to add to that: it was an iteration on \"SHRINKS+\", which was a solution that Jonas Nick and Mikhail Kudinov came up with through their research of hash-based signature schemes that could be added to Bitcoin and make it quantum-resistant. They released that paper in December, and so here we are, beginning of April, end of March, a quarter later, Jonas is already sort of advanced that primitive idea and made it more efficient. And so the progress is being made on the research side of what we need to do to upgrade Bitcoin's signature scheme for a world in which ECDSA is broken, or a world in which quantum computers manifest, exist, and are scalable and efficient. And so yeah, I think I think a level-headed approach to this is is the best way. And another thing, last thing I'll say on this, the when you're out there and you're not immersed in this debate and you're an outside observer looking at this and you have Chamath Palihapitiya, you have Nick Carter and others saying we need to do this now and they're saying \"Bitcoin developers need to get together and solve this problem\"... I think one thing to understand is that not every Bitcoin developer is qualified or equipped to solve this specific problem. There are many different parts of the Bitcoin stack, people working on the P2P layer, initial block download, networking between nodes, wallet GUIs, all of that... and there is a subset of a subset of Bitcoin developers that really understand the cryptography, and then within that subset of a subset, a subset that understands how to make it quantum-resistant. So finger-wagging at every Bitcoin developer and saying do something is completely unproductive because not every Bitcoin developer is focused on this specific part of the Bitcoin stack. The people who are are making progress.","offset":1324,"duration":189},{"text":"Arnold: Yeah, I mean the last thing I'll say is to that point: there's a concept called a \"load-bearing internet person,\" someone who's just like 10,000x the the median engineer or the median computer scientist on questions of the design of the internet, internet protocol. I think there's very much like a similar concept here of a \"load-bearing cryptography person.\" I mean, there are literally like probably under 50 people in the world who are truly like masters of this this domain, you know, or maybe under 1,000, I don't know however you would frame it. But you know, to the extent that you think that that's like a risk to Bitcoin, it's also a risk to every digital system that we have in the world. There are so few people who are really equipped to to think through all this stuff. But it's so worth noting as you just ask yourself, to that point, like \"Why isn't this solved?\" Well, it's a very thorny question that not everyone in the world or even a majority of people who are deeply involved in Bitcoin are really qualified to you know, weigh in on and opine on. So all the more reason then, right, to be methodical about it and to make sure that nothing is getting kind of rushed or pushed faster than you know, it needs to go, particularly given some of the questions that you highlighted around the actual physical scaling progress of of getting this stuff out into the real world. So yeah again, you know, avoid the black boxes, focus on what you can actually analyze and get your hands around and try not to weigh in on the stuff that's borderline impossible to really figure out.","offset":1513,"duration":78},{"text":"Host: Yeah, and to flip the frame there: the fact that Bitcoin, the Bitcoin project has a few of these individuals who are qualified and equipped to do this work is high signal that it is a very valuable protocol. The fact that it's able to attract that type of talent that can actually solve these problems is an endorsement in and of itself.","offset":1591,"duration":20},{"text":"Arnold: Yep, co-sign.","offset":1611,"duration":1},{"text":"Host: All right, see you guys next week.","offset":1612,"duration":15}],"logs":[{"elapsed":"0.0","message":"Downloading audio from YouTube...","detail":null},{"elapsed":"0.0","message":"Trying download with browser cookies (ad-free)...","detail":null},{"elapsed":"3.9","message":"⚠ Cookie download failed: WARNING: [youtube] [jsc] Error solving n challenge request using \"deno\" provider: Error running deno process (returncode: 1): \u001b[0m\u001b[1m\u001b[31merror\u001b[0m: Uncaught (in promise) TypeError: Cannot read prope","detail":null},{"elapsed":"3.9","message":"Retrying without cookies...","detail":null},{"elapsed":"19.1","message":"⚠ Downloaded without cookies — audio may contain ads","detail":null},{"elapsed":"19.1","message":"Audio downloaded (16.4 MB) in 19.1s","detail":"File size: 16.4 MB"},{"elapsed":"19.1","message":"Video title: While Everyone Was Watching Iran, They Missed This","detail":null},{"elapsed":"19.1","message":"Audio duration: 27:03 (27.1 min)","detail":null},{"elapsed":"19.1","message":"Uploading audio to Gemini File API...","detail":null},{"elapsed":"22.6","message":"Audio uploaded in 3.4s","detail":"File ref: files/0pux57h4vh8d"},{"elapsed":"22.6","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"61.9","message":"Transcription complete in 42.8s","detail":"29489 chars received"},{"elapsed":"62.0","message":"Transcription tokens: 40,802 in / 6,397 out — cost: $0.0396","detail":null},{"elapsed":"62.0","message":"Parsed 15 transcript segments","detail":null},{"elapsed":"62.0","message":"Transcript coverage: 26:52 of 27:03 (99%) — OK","detail":null},{"elapsed":"62.0","message":"Total transcription time: 42.8s — 15 segments","detail":null},{"elapsed":"62.0","message":"Analyzing topics across 15 segments with gemini-3.1-pro-preview...","detail":null},{"elapsed":"137.3","message":"Topic analysis complete in 75.3s — found 6 topics","detail":null},{"elapsed":"137.3","message":"Analysis tokens: 6,750 in / 463 out / 3,097 thinking — cost: $0.0562","detail":null},{"elapsed":"137.3","message":"Pipeline finished in 137.3s — total cost: $0.0958 (57,509 tokens)","detail":null}]} \ No newline at end of file diff --git a/history/1775588353507-mjNP5IOzCbA.json b/history/1775588353507-mjNP5IOzCbA.json new file mode 100644 index 0000000..fd837fe --- /dev/null +++ b/history/1775588353507-mjNP5IOzCbA.json @@ -0,0 +1 @@ +{"id":"1775588353507-mjNP5IOzCbA","videoId":"mjNP5IOzCbA","url":"https://www.youtube.com/watch?v=mjNP5IOzCbA","title":"The State of Modern War: Palantir & Anduril Execs on Drones, AI, and the End of Traditional Warfare","type":"youtube","topicCount":20,"segmentCount":166,"createdAt":"2026-04-07T18:59:13.507Z","uploadDate":"20260406","chunks":[{"title":"Introductions and Palantir's Origins","summary":"The host introduces Trae Stephens and Shyam Sankar, who share the story of how they met. They discuss the early days of Palantir and its focus on solving post-9/11 counterterrorism problems.","entries":[{"text":"Host: Trey Stevens, Shyam Sankar, welcome to the All-In Podcast at the Hill and Valley Forum. Thank you guys for being here. What's up? How are you guys doing?","offset":0,"duration":7},{"text":"Shyam Sankar: Thanks for having us.","offset":7,"duration":1},{"text":"Trae Stephens: Doing great.","offset":8,"duration":1},{"text":"Shyam Sankar: Good to be here too.","offset":9,"duration":1},{"text":"Host: You guys are friends, right? You guys go back, like, a long time?","offset":10,"duration":2},{"text":"Trae Stephens: A really long time.","offset":12,"duration":2},{"text":"Host: Okay, tell us how you guys know each other. Palantir, Anduril, what's the connection and the history?","offset":14,"duration":5},{"text":"Shyam Sankar: Well, I'll start, you can fill in all the gaps.","offset":19,"duration":3},{"text":"Trae Stephens: I feel like I know the story you're going to tell and it's going to be very uncomfortable.","offset":22,"duration":32},{"text":"Shyam Sankar: So, Trae, I think, you know, in the early days of Palantir, I was roaming around giving demos to anyone who could possibly want to see them. Trae was working in an Intel agency and happened to see one of these demos, and he should tell you his version of it, his side of it, his frustration with bureaucracy, but I think he realized, like, hey, this- this might be really cool. Maybe I should leave the hellhole I'm in in the basement of this building getting nothing done, talking about sports with other people, to go join this crusade. So Trae reached out and applied. Uh, he- he made a big faux pas. He came all the way to Palo Alto and he- he wore a full-on suit, tie, cufflinks, CIA cufflinks, mind you, to- to come to interview with, I don't know, we were probably 20 people, you know, who wore T-shirts and, you know, secondhand hand-me-down clothes. Um, and- and I think, you know, he was intercepted in the lobby by a receptionist who- who really cared about him and told him to get- ditch the tie and try to dress down and don't screw it up too bad. But we loved him immediately and he helped us build the- the government business.","offset":54,"duration":65},{"text":"Host: So this was at Palantir. You were there employee 13, 2006, right? So this was pretty early on.","offset":119,"duration":6},{"text":"Trae Stephens: Yeah, I- I came in in early 2008, but there were still, you know, 25, 30 people at that point.","offset":125,"duration":5},{"text":"Host: Pretty small. And Peter kind of incubated it, was involved at the beginning, right? Peter Thiel? Maybe you could just recap because I know a lot of folks know the history of Palantir, but just kind of, like, the early stand-up of Palantir and how things got going during that era with that small group, how you guys kind of figured out how to build the business.","offset":130,"duration":19},{"text":"Shyam Sankar: Yeah, it was- it was one of those things that was kind of a slow start. It was- there was a real idea amongst the five co-founders, including Peter, that, you know, it's kind of insane to live in a world post-9/11 where people are arguing about what's more important, privacy or security. Like, aren't they both really important and who is actually spending time pushing out the efficient frontier? For any amount of given security, you should have more privacy than you had before, or any amount of given privacy, you should have more security. And- and this sort of changing the dialectic there was really the entire impetus of- of what we started with. And now there's a technical approach that follows from that, there's an approach to privacy and civil liberties that are around that. Um, but really we started as a business that was pretty myopically focused on solving a handful of problems in counterterrorism for a handful of institutions in the world.","offset":149,"duration":43}],"startTime":0},{"title":"The Philosophical Justification for Defense","summary":"The guests share their philosophical views on war and defense. They argue that while war is fundamentally awful, maintaining a strong defense posture is necessary for deterrence.","entries":[{"text":"Host: Let me start by asking a question that I think is important to ask, particularly for a broad audience, and for the two of you to frame your personal philosophical views. Is war good? There's a lot of conversation about there is a military-industrial complex that has an incentive for war. What's your view, your philosophical motivation for why you do what you do, what your view is of war and defense, and- and the work that your business has kind of pursued?","offset":192,"duration":29},{"text":"Shyam Sankar: Well, any- anyone who's been to war would tell you that war is awful. War is bad, categorically bad. That doesn't mean it's always avoidable. And that, um, you know, there will- there are people who will want to use might to make right, to define a set of rules. Um, and you have to be in a position to protect your people and your interests accordingly.","offset":221,"duration":17},{"text":"Trae Stephens: At the end of the day, it's all about deterrence. You don't want to go to war, but you want to be prepared so that if you do have to go to war, that you will win decisively and quickly. Um, I've never met a general that has said, you know what I really want to do today? I want to make phone calls letting parents know that their children have died in combat. Nobody wants to do that. Um, and- and I think that that's really the goal of everything we were working on at Palantir, it's what we're working on at Anduril, which is make it unthinkable to your adversaries that they should ever challenge you.","offset":238,"duration":29}],"startTime":192},{"title":"Silicon Valley's Changing Stance on Defense","summary":"The discussion shifts to why Silicon Valley historically viewed defense tech as taboo. The guests note that global geopolitical shifts, like the invasion of Ukraine, helped awaken the tech industry to real-world threats.","entries":[{"text":"Host: Why do you think it became taboo and became so negative, particularly in Silicon Valley, that building a defense company or a company building technology to service the defense sector was viewed with- with such disdain and was an untouchable sector for so long?","offset":267,"duration":16},{"text":"Shyam Sankar: I think it's a beautiful consequence, and I mean it- unironically, of kind of the peaceful world that we lived in. The origin story of Silicon Valley is actually defense. You know, Lockheed was the largest employer in- in Silicon Valley in the 1950s. The Corona spy satellites were built there. So in a world that was, um, gripped by the threat of the Soviet Union, you know, you had a very different posture in Silicon Valley. But in a world post-the end of the Cold War, the end of history, kind of a view of globalism that it's all going to be great that we exist beyond the confines of our country, um, these things were viewed much more cynically and the threats didn't seem very real. And I think you could even backtest this through the moment where Silicon Valley kind of really woke up and realized, hey, maybe these things are real, are when the Russian tanks rolled across the Ukraine border. You know, it's when they realized there are a lot of Ukrainians, Eastern Europeans, there are a lot of people who were affected by that in Silicon Valley, who started to realize that, um, maybe there's a more nuanced issue here than just simply the simple Eisenhower quote of the military-industrial complex.","offset":283,"duration":60},{"text":"Trae Stephens: Yeah, I think many of the people who were protesting Silicon Valley's involvement in working on national security priorities were the exact same people that had Ukraine flag in bio. Um, so there's clearly just like a policy mismatch or an understanding mismatch. The other thing that I would mention is that these large tech companies, unlike many epics prior, uh, were global technology companies. They didn't necessarily view themselves as American. Um, and so if you go and you look at, you know, where these protests came from, you have to keep in mind that a lot of the signatures that they had on these, you know, protests, uh, were not coming from US citizens. And so there's like a global character to those companies that probably was not the case during the Cold War.","offset":343,"duration":42},{"text":"Host: Do you think that's changed recently?","offset":385,"duration":1},{"text":"Trae Stephens: I mean, to Shyam's point, I think that there's just an increased awareness of the complexity of the geopolitical situation. Um, and- and I think it's certainly a lot less controversial work on these topics than it was in 2017, 2018.","offset":386,"duration":13}],"startTime":267},{"title":"The Atrophy of the American Industrial Base","summary":"Trae and Shyam contrast the broad American industrial base of World War II with today's consolidated defense industry. They highlight the urgent need to rebuild manufacturing capacity to sustain military readiness.","entries":[{"text":"Host: You know, it's a 20-year overnight success, right? And Anduril's now reportedly raising money at a $60 billion valuation, just landed a $20 billion Army contract, Palantir today is worth $400 billion. The flip side of what I just said is that some people are saying that Silicon Valley is taking over defense and Silicon Valley is the next story of the American war machine. This has become sort of a popular narrative. Can you just respond a little bit to kind of where we were coming out of World War II from a defense industry perspective, where we find ourselves where Silicon Valley seems to be at the center of this today?","offset":399,"duration":43},{"text":"Shyam Sankar: You know, the industrial base that won World War II and the early Cold War was not a defense industrial base. It was an American industrial base. You know, Chrysler made the Minuteman ICBM, they were the prime contractor on it, and they make minivans. General Mills, the cereal company, had a mechanics division. Everything they learned doing R&D to process grains, they actually used to build torpedoes and inertial guidance systems. Ford built satellites until 1990. So the entire economy was invested not only in economic prosperity but also underwriting the freedom that allowed us to have economic prosperity. It's really a consequence of the end of the Cold War. So when the Berlin Wall still stood in 1989, only 6% of spending on major weapons systems went to pure-play defense specialists. 94% of it went to what I call as dual-purpose companies. You know, yeah, a missile is single-use, it's not a dual-use product, you're not going to buy it at Walmart, but that actually these companies were invested in both parts of this. That figure today is 86% goes to defense specialists. So we have a very different structure of the US economy as a result. and I think it leads to very perverse narratives of what would it be like to mobilize. If- if things got really bad, we'll just flip a switch and our auto factories will magically turn into enabling us provide for our defense and security. And- and I think a- cold-eyed look at history is it took 18 months to do that. We actually started ramping up to provide this stuff for our allies, for the Brits and the Soviets in the context of World War II, and that we've actually missed some of those signals today. When- when Ukraine went through 10 years of production in 10 weeks of fighting, that probably should have been a five-alarm fire that we got the fundamental calculus on deterrence wrong. We thought the stockpile was going to deter our adversaries. It was always the factory, it was the ability to generate and regenerate the stockpile.","offset":442,"duration":100},{"text":"Host: Right. And Trae, you've talked about this. You wrote an article, \"No Solvency, No Security\". Just share with us your view on the importance of this industrial base and what it takes for us to have strong defense requisite in a strong manufacturing industrial base.","offset":542,"duration":111},{"text":"Trae Stephens: I- I mean, we really kind of sent most of these capabilities away, um, during the last 30 years of globalism. Uh, and that gutted entire communities in the United States. You know, I mention in this article that just in my immediate family, like grandparents, aunts, uncles, uh, I have family members that worked at GM, at Ford, at Frigidaire, at National Cash Register, at Armco Steel. Every single one of these factories in Ohio closed. Not a single one still exists. And they all have different places they've gone around the world. Um, but, you know, one of the things we're doing with Anduril right now is we're building out a 5 million square foot factory campus in Columbus, Ohio. And we have the benefit of going back and tapping into that knowledge base that exists that's underemployed at the moment because those the factories that kept them busy for many, many years are- are closed. Um, and I think this is the story all over America. Like if you think about the at-scale manufacturing for a new company started in the this century, uh, in the 2000s, um, there's really only one that comes to mind: just Tesla. That's it. And so we haven't really built any muscle around a new manufacturing capacity. Um, and- and I think that as you spin things up, to Shyam's point, we don't have the ability to do that quickly because we've atrophied massively by- by turning all this away globally. So, um, I think readiness is a real problem and- uh we have to start investing ahead of the the, you know, conflict being- being there because you can't just start at the moment that it's absolutely needed.","offset":653,"duration":95}],"startTime":399},{"title":"Anduril's Arsenal 1 and Manufacturing Modularity","summary":"Trae explains Anduril's Arsenal 1 factory in Ohio, which operates similarly to a commercial contract manufacturer. This modular approach allows for rapid production scaling of whatever autonomous systems are needed during a conflict.","entries":[{"text":"Host: Tell us about the Arsenal 1 and then the manufacturing behind it. And then I want to just understand a little bit about is this product-led or production-capacity led. Do we need to make selections and have capital committed to bringing product to market before we start to build out the base, or is there an alternative way to get ready?","offset":748,"duration":17},{"text":"Trae Stephens: Arsenal 1 is our- the factory campus that we're building in Columbus. Um, the operating system for that, the Arsenal platform, um, is really intended to reduce the- the cost, the overhead, that's required to automate and- uh, you know, handle these processes in the most efficient way possible. So there's like kind of the software layer that sits behind that. We're actually working with Palantir, uh, the Foundry platform, on some of these programs as well. And, uh, the idea behind this is that you want it to be as modular as possible. If we built out the factory campus and we said we're just going to build Furies here, or we're just going to build Roadrunners here, we're just going to build Barracudas here, that provides a- tremendous limitation in a- in the moment of a conflict to be able to be responsive to the demand for specific things that are relevant to that conflict. And so we're kind of thinking about this more like contract manufacturers think about building assembly capacity where they say, yep, we make, you know, this VR headset for Facebook, we make this- this VR headset for Samsung, we make this- this VR headset for Apple. Uh, we build a skill set around building optics systems, um, but we're going to build a bunch of them. And we're going- we're going to be much more effective at doing that by hitting the network of scale, uh, you know, get lower costs on all the individual parts, you're going to build out a supply chain to- to work through that. That's roughly what we're doing in this case, as we're saying, like a contract manufacturer, we want to be able to pivot on a dime into ramping up production of Roadrunners if we need Roadrunners or ramping up production of Barracudas if we need Barracudas. Um, the counterexample to this, of course, is what we saw in the early days of Ukraine, where what they really wanted was more Stingers and Javelins. The problem is is that we once- once we burned through our inventory in the warehouses of Stingers and Javelins, the assembly line to build Stingers and Javelins didn't exist! All the people that worked on those assembly lines were retired! And so the primes were literally calling people out of retirement to come back and teach them how to build Stingers and Javelins again. Um, and so these are problems that we're trying to avoid by the design of the factory as- as an initial concept.","offset":765,"duration":123}],"startTime":748},{"title":"Navigating the Defense Monopsony","summary":"The guests contrast Anduril's private R&D approach with the traditional model of prime contractors. They explain the challenges of selling to a government monopsony that typically buys to strict specs rather than investing in innovative products.","entries":[{"text":"Host: Who funds it? So is there a government contract that supports the production of these facilities and are multiple companies going to be able to afford to- to stand these up, to make these investments, or is this just going to end up being an Anduril play because you've got most of the capital and you guys are going to roll these facilities out? How do we make this kind of a national interest?","offset":888,"duration":18},{"text":"Trae Stephens: Well, our business model is definitely very different from the primes, uh, who are basically responding to things as requirements directly from their customer. So they're not really investing a whole lot forward of the capability. Anduril, on the other hand, we're doing all of this as private R&D investment and then we're selling the outcome, the output of that, as a product. So this is fundamentally a different business model. Um, but I do think that there's a tremendous amount of capital that's required to pull this off uh, as a new entrant to the space. Uh, I don't think that the market is going to support 100 new primes or something like that. Uh, I'm hopeful that it's not just Anduril. I think it would be healthy if there was more competition in the space. Um, but, you know, being able to raise that amount of capital, hire the people that you need to actually pull it off, uh, this is not- it's not like building a- a normal tech company. It's not just the development of a product. It's- you know, there's a lot that goes into this.","offset":906,"duration":53},{"text":"Shyam Sankar: Trae's point might seem kind of obvious or simple, particularly to an audience that's largely coming from tech or Silicon Valley, but that's not how defense works. People don't build products. People build to a spec that the government says, \"this is what I want to buy,\" and then you kind of say yes. You- you have to think about defense as a monopsony where there's a single buyer for the thing, and that concentrates an enormous amount of power in the buyer, whether they're right or wrong. And if you look at the history of defense innovation, typically the monopsony's wrong. You know, it was Churchill as the head of the Royal Navy who built the tank, because the British Army was not smart enough to realize that in the next battle having horses was not going to work. So every one of these innovations is kind of an act of heresy. There's- there's a founder-like figure who is so committed pathologically to a different heretical concept, they see it through and only in combat or only when it meets the moment is it actually validated. Now, a- grave threat like the Soviet Union is a sort of forcing function that allows- allows you to innovate. When we were building ICBMs, we had eight competing programs. Today in peacetime, that would be viewed facilely as wasteful. Why should you have eight competing things? Why can't you just pick the right one and put- you know, spend less or put all your wood behind one arrow? And of course, that kind of turns its back on our fundamental belief in America on the free market, that there's a competition of ideas, there's fundamental uncertainty, there's quality- like variance in the quality of the execution and that you need this competition. And it's not just principally competition amongst the primes or new entrants, it's also competition inside of government.","offset":959,"duration":86}],"startTime":888},{"title":"Capital Concentration and the Power Law","summary":"Addressing the flow of venture capital into defense, the guests argue this sector mirrors traditional power laws. They assert that capital and contracts must eventually concentrate on a few companies that execute the best.","entries":[{"text":"Host: And there were originally, I think, or at one point 51 major defense contractors. And just for the audience to understand, they reduced down to roughly five or six primes. That's- that's the term \"prime\" is one of these prime contractors and then they subcontract out to other companies uh to develop componentry parts. My understanding in Anduril was to do exactly this: build a product, show up with something that's cheaper, better, faster and actually competes on the merits rather than be caught in this kind of prime landscape. And that work clearly worked. But over time, there seems to be a lot of capital concentrating into the \"new primes\". You guys, you guys, SpaceX, OpenAI, maybe one or two others. Is the landscape going to emerge that it- we're going to just look like the same old way of operating where we have a handful of primes that all have these trusted relationships with the government agencies, or how do we kind of create that competitive environment to continue to drive innovation and make things affordable for the US government and the taxpayer going forward?","offset":1045,"duration":59},{"text":"Shyam Sankar: Well, just like- and- and I interviewed Trae in- in my new book on this, like- just like venture, there's going to be a power law here. You- so one of the- grave mistakes we've made as we think about innovation which has resulted essentially in innovation theater is this idea that you're going to just peanut butter spread around the capital you have for innovation. That, you know, every company's going to get roughly the same amount. It's not enough to hit scale. It doesn't reflect actually the relative performance differences, because there's an authentic power law curve. Like any venture capitalist would- would realize that, you know, your- your biggest winners are going to return your whole fund. There's- there's something authentic here as well, which is like, yeah, you may have 10 bets, but you're- at some point you're going to have to get smart about concentrating down on the things that are actually working.","offset":1104,"duration":39},{"text":"Trae Stephens: Yeah, I mean, this is a- kind of a great point about any category. It's like if you're a space tech investor and you didn't invest in SpaceX, you probably lost money. If you're a crypto infrastructure investor and you didn't invest in Coinbase, you probably lost money. If you're a social media investor and you didn't invest in Facebook, you probably lost money. And yet for some reason, capital allocators have a very short memory. They don't have the ability to go back to the- the prior- boom cycle and say, oh wait, I remember what happened that last time we had to concentrate capital down to the winner. Um, and- and I think that this- this isn't any different.","offset":1143,"duration":32}],"startTime":1045},{"title":"Overcoming Defense Procurement Sclerosis","summary":"Shyam and Trae recount the historic consolidation of defense primes and the grueling process of proving Palantir's software in the field. They explain how their early struggles paved the way for Anduril's faster growth by establishing new precedents.","entries":[{"text":"Host: So what was the motivator then for change in the construction of the landscape of defense contracting? Was it software that takes us from the old primes to the new primes? Is that really what kind of triggered this cascade evolution?","offset":1175,"duration":12},{"text":"Shyam Sankar: Consolidation. So in '93, having won the Cold War in '91 or I think more accurately the Soviets lost the Cold War. You know, by '93, we expected as a nation a kind of peace dividend. We don't have an adversary now, we should be able to spend less on defense. And- the department had this famous dinner where they brought 15 of the 51 primes together and said, \"this is going to happen, the budget's going to get slashed, we're not going to save you guys, you have our permission to consolidate, some of you are going to go out of business, some of you should try to make a commercial business,\" which didn't really work. Uh, and that's what led down to five. It was actually there was going to be- we were going to go from five to four in '99, the Justice Department put their foot down and said, \"we're not going to let Lockheed and Northrop consolidate.\"","offset":1187,"duration":39},{"text":"Host: Right. And then today, so the changeover, what gave you guys the window, what gave you guys the window to build the business that you've built? I mean, what did you see early on 20 years ago and continued forward in the hardware side that made you say this is- this is the moment. Is it software that enabled this?","offset":1226,"duration":18},{"text":"Trae Stephens: Well, I'm going to throw you under the bus a little bit on this.","offset":1244,"duration":2},{"text":"Shyam Sankar: Okay.","offset":1246,"duration":1},{"text":"Trae Stephens: It was not obvious from the beginning that this was going to work. Um, I can't tell you how many meetings even we had together where we'd walk out and be like, this is not going to work, this is very bad.","offset":1247,"duration":11},{"text":"Shyam Sankar: We were not welcomed with open arms. Right. You know, early days at Palantir. Yeah. Early days, mid-days, maybe late days, you know, famously we had to sue our customer just for the right to compete. Um, that- that's the strength of the monopsony, right? And- and really, I'd say our- entire business was validated from the field backwards, right? It was in DC that- the doors were closed to us, no one wanted to interact with us, they're like- we're- the monopsony's strongest. At the margin, in the field, where people are- are saying like, well, I'm on this deployment, I'm on this rotation, and I- there is more free market system. Like what I'm being given doesn't work, I'd like to come home, how do I like bend the rules, figure out how to get the software I need. That allowed us to empirically show, you know, create facts on the ground, that this stuff worked. It was a long road to hell. I think this is part of why it took 20 years to kind of get to this sort of point here.","offset":1258,"duration":48},{"text":"Trae Stephens: And yeah, I think that a lot of those lessons that were learned were not only like educational for Anduril, but it also created a precedence that already existed by the time that we showed up where we didn't have to go through all of those same growing pains. So, you know, what took Palantir, I guess, probably about five years to get to $10 million annually in revenue, we did that in 22 months. But I don't think that was a credit to Anduril. I think it was mostly a credit to me, Matt, and Brian lived the five years at Palantir.","offset":1306,"duration":26},{"text":"Shyam Sankar: Five years plus 22 months.","offset":1332,"duration":1},{"text":"Trae Stephens: Yeah, exactly. Exactly. And so we kind of had a bit of a cheat code. But I don't think it's like culturally shifted to the point where it's like actually just easy to do this now. It's not like the government has fixed all of their problems. I think it's just that there's enough people out there who have seen it, that understand how to make it work, um, that you can work within the system rather than as Shyam said trying to constantly fight from the outside in.","offset":1333,"duration":23}],"startTime":1175},{"title":"Why Hardware is Easier to Sell to Government","summary":"The guests explain why Anduril focused on hardware instead of software. They note the government struggles to value software, whereas hardware has a bill of materials that fits traditional procurement models.","entries":[{"text":"Host: Was there a view at that time in these years building Palantir where you saw an opportunity in hardware? Is that kind of the motivation for Anduril, that we've got software but there's more to do and hardware could be reinvented and we could build systems? I mean, help us understand the connection.","offset":1356,"duration":13},{"text":"Trae Stephens: Yeah, in the very early days, actually, I came by to pitch Shyam um, before we officially started the company. Uh, and I think part of that pitch was we said, uh, we know how hard software is. We don't want to do that again. We believe hardware would be less hard. Um, and I think we ended up being right from like a getting going perspective. Um, but yeah, it's just- you know, the government doesn't know how to think about the value that's created by software. Maybe you feel like they're a little bit better now, but it was really hard in the early days of Palantir to convince them to think about it as anything other than lines of code. For example, or some like metrics that anyone that works in tech knows doesn't matter. But for hardware, they know. There's a bill of materials. Uh, in fact, the government made stuff for a long time. During the Cold War, there were literally ammunition factories that were owned and operated by the United States government. Um, so they can kind of go through a spreadsheet and say, okay, I know how much it costs for you to build this, I know how much margin I am comfortable paying you. Uh, and it's a much easier, you know, crossing of the Rubicon. With software, it never felt like that.","offset":1369,"duration":63},{"text":"Shyam Sankar: Yeah, it's still very hard. I mean, people want to pay for software in government on a cost-plus basis, which doesn't make any sense if you think about the R&D that you put into software. Like the marginal price you're paying is a small fraction of the R&D we're amortizing across commercial and government customers. And I think maybe Trae, it's worth telling the story of how when you got to Founders Fund, you were looking for defense companies to invest in and hitting so many dry holes is- is part of what led to the idea.","offset":1432,"duration":27},{"text":"Trae Stephens: Yeah. Yeah, I mean, I have no- I had, maybe still don't, have any interest in venture capital. Um, and so when Peter asked me to come over to Founders Fund, the only thing I knew to do was just to look at the category of things I felt like I understood pretty well, which was GovTech. And so I, incidentally, you can look up who bids on federal contracts. And so I pulled that list and then at the time I was using Crunchbase and then I just started outbounding to companies that were bidding on federal contracts. And I met with hundreds of companies in the first three years that I was at Founders Fund. We made- ended up making one investment in KDM, which was renamed Expanse and acquired by Palo Alto Networks. Um, but otherwise that was it. There was nothing else. And even like looking in retrospect at- like we didn't miss anything. There was just nothing worth investing in. It turns out no one was building in this category. Um, and so I went back to the Founders Fund investment team and said, man, I feel like someone should be building a next-gen prime that builds hardware but it's software-defined and hardware-enabled rather than being hardware-defined and software-enabled. Um, and- uh to my surprise, the team was like, yeah, sounds like you're probably the guy that would know that that's the gap and I don't know, maybe you should start a company. And I'm like, oh no, you guys hire me to work on the investment team at Founders Fund. Like, yeah, that's fine. You can- you can do that too. It's all good. So, yeah, it was kind of an accidental founding in many ways.","offset":1459,"duration":80}],"startTime":1356},{"title":"Venture Capital Dynamics in Defense Tech","summary":"Using examples like Fairchild Semiconductor and SpaceX, Shyam explains how relying on government R&D stifles price-performance curves. Trae cautions new defense startups against raising capital at unsustainable valuations.","entries":[{"text":"Host: The capital requirements for hardware business are notably higher. If you didn't have the success you had building the manufacturing facility you're building and I'm assuming all the R&D cycles are longer and require more capital to get to a point of product. Does it make sense for venture capital to be the funder of the next gen of hardware defense tech companies? How does the economics and the capital markets fit here?","offset":1539,"duration":22},{"text":"Shyam Sankar: Uh, I'll take- take here and then- you. So I think, um, if you back up a little bit, if you look at Fairchild, if you look at integrated circuits in 1968, 96% of all integrated circuits sold were sold to the Apollo program. There was effectively a monopsony. There was one buyer for this thing. But Bob Noyce, who was at Fairchild at the time and co-inventor of the transistor, he was so maniacally committed to a future that semiconductors and integrated circuits would be in everything, that he never let more than 4% of his R&D be paid for by the government. He was going to be- like, why should I have some PM tell me what my R&D roadmap- I invented the thing. So he kept executing that. And that's- he so chased Moore's Law mercilessly. And that meant in the 80s, when the government needed precision-guided munitions for assault breaker to compete against the Soviets, we had the price-performance we needed. Uh, so this idea that- you know, because when you get stuck inside the government loop of what they want, you never hit the price-performance.","offset":1561,"duration":52},{"text":"Trae Stephens: By the way, there's a good modern analogy which is Jensen and NVIDIA, right? '93, graphics chips, sold them as an OE- almost like an OEM type solution and- until here we are.","offset":1613,"duration":9},{"text":"Shyam Sankar: The- the one that speaks to my heart as a child who grew up in the shadow of the space coast is Shuttle. You know, Shuttle is- is beautiful, but it's $50,000 a kilogram to get to orbit. Starship heavy reuse will be under 20 bucks a kilogram. You know, and there's no way that you will achieve that vision if you're in a cost-plus world, because every day you're actually deleting your cost, which means you'd be deleting your profit. Instead of deleting your cost, turning that into margin that you can provide a better price-performance on and keep riding that curve down.","offset":1622,"duration":27},{"text":"Trae Stephens: Right. Although to be fair, SpaceX sued their customer, in the Air Force, on the basis of the exact same federal procurement law um that Palantir did. Um, and so, you know, even with that massive cost- uh costing down, they were in the same position as Palantir was in the early days.","offset":1649,"duration":16},{"text":"Host: Let's go back to the venture capital. At this conference that we're at, there's dozens of VCs now. This has clearly become a hot space as defined by your successes. What's going to happen? So these VCs are plowing money into hundreds of defense tech companies, from drones to satellites to weapons systems to software tools. How does this going to play out over the next couple of years? As a venture investor with your knowledge about Anduril.","offset":1665,"duration":24},{"text":"Trae Stephens: I remember when I first got my offer letter from- from Palantir, um, there- we had this kind of high-low mix of salary versus equity compensation, and it gave three examples of how much your equity at your- that was on your offer would be worth at different valuations. It was I think it was 1, 5, and 10 maybe, or 1, 5, and 20, something like that. And I remember talking to people around the company, they're like, hah, 20? That's ridiculous. We're never going to be worth $20 billion. Um, and- uh you know, I feel like now it's like people are going out and they're like, our seed round will be priced at $20 billion. Um, so I think there's- there's been a big shift in just like the way that people think about these things. Um, some of that is good, some of it's bad. I think on the good side, they're- you know, they're able to look at companies like Palantir, like SpaceX, like Anduril and say there is actually a path to success. This isn't like an impossible market to innovate in. But at the same time, um, you know, there's a real tension around amount of capital raised and the valuations that are being applied to these rounds that- add a tremendous amount of risk to the company that doesn't have to exist. You know, there's this favorite- there's this famous scene from HBO's Silicon Valley where CEO gets fired um for- uh kind of underperformance on the plan that they had presented. Uh, and Richard Hendricks, the main character, says, \"You know you could have raised less at a lower price.\" And he said, \"What do you mean? No one ever told me I could have raised less at a lower price!\" And I think that's ultimately what my advice is to these companies, is like, look, your product might be awesome, seems like you're building a good team, I like the vision for what you're doing in the mission, but you can also raise less at a lower price. And I think that avoids, you know, playing chicken ultimately with trying to hit numbers that frankly don't even make sense. Um, one of the things that we've been focused on at Anduril that I think maps back to our experience at Palantir actually is climbing down the multiples tree uh with every round. We never want to go and raise the next round at a higher revenue multiple than the prior round. Um, and even the Series H that you mentioned before uh is is down pretty significantly from the Series G. And we're not doing that because investors wouldn't be willing to pay higher multiples, we're doing that because I believe the discipline is really, really important especially heading into a- you know, medium-term IPO.","offset":1689,"duration":139},{"text":"Host: Emil Michael talked about this $200 billions of capital he wants to deploy. It's been reported he's hiring bankers to help him deploy it. To counter your point, if there's a lot of capital flowing from the monopsony, if there's a, you know, a big market that's growing aggressively, you've got a $200 billion TAM to go after now. Shouldn't that justify the venture capital coming in, maybe even justify going at a higher price? Is this department of war investment activity really going to kind of change the landscape and increase more venture capital flow?","offset":1828,"duration":29},{"text":"Shyam Sankar: I think it's- it's going to help out tremendously. First of all, I love the nickname that this team has, which is \"Deal Team Six\". So, uh, you know, I'd be honored to be part of that team. Uh, but I think if even if you look back at the titanium supply chain in the 50s, 60s, it was- it was bootstrapped by the Air Force in a similar way where they strategically injected capital down the supply chain to enable the aerospace industry to be created. So I think there's a tremendous opportunity with the Office of Strategic Capital to think about what are the structural bottlenecks in the production. You can have a lot of drone companies, and they're all going to bottleneck on brushless motors. There's going to be certain key parts of the supply chain that we don't have enough capacity to produce here in the US and they're going to need a bolus of investment. And just like integrated circuits, the first customer is going to be less economical than the end customer. So I think that's one part. Then I the other story that I love is where we really screwed this up. The drone is an American birthright. Abe Kareem and the Predator, we- we built it, General Atomics, but of course then the government got in the way. The government said, hey, a drone is a flying missile. This thing needs to be ITAR controlled. Also the FAA got in the way and said, no beyond line-of-sight operations. Right? So you basically killed the domestic drone market. There is a counterfactual world where General Atomics had a commercial subsidiary called DJI, and the consumer drone market was entirely owned by the US and it provided for economic prosperity for America and wrote us down the price production curve that we could be using these things in innovation for national security as well.","offset":1857,"duration":82}],"startTime":1539},{"title":"Supply Chain Risks in Pharmaceuticals and Semiconductors","summary":"The conversation moves beyond defense hardware to broader supply chain vulnerabilities. Shyam and Trae express concern over America's reliance on foreign manufacturing for generic drugs and advanced semiconductors.","entries":[{"text":"Host: What's the next market where you're worried that's going to happen?","offset":1939,"duration":2},{"text":"Shyam Sankar: I have a lot of markets. So I mean we- we're talking a lot about, um, weapons of war here. I'm worried about things that go beyond weapons of war that affect our will to fight. Uh, pharmaceuticals is one that's close to my heart. My father was a pharmacist and one of the things he always wanted me to work on was bringing pharmaceutical production back home. 80% of APIs for generic drugs are produced by China. What do you think the American people are going to think when they have to choose between defending the free world, defending American sovereignty, and their five-year-old dying of an ear infection that we would have thought of as trivially cured? And so I think there're these- these things where we've just imbibed the globalist vision that hey, we'll do the innovation, they'll do the production, without realizing that innovation is a consequence of productivity. Probably to put it in terms that the- that the tech community would really understand is like, what motivated Google to do the research in 2017 behind the paper \"Attention is All You Need\"? A desire for a 3% incremental improvement in Google Translate. You can think of nothing more banal leading to something more revolutionary. And we have ceded all of those opportunities to realize and harness that innovation. Now, if we stick with pharmaceuticals, there's a reason 50% of all clinical trials, new clinical trials, are happening in China and not in the US.","offset":1941,"duration":68},{"text":"Host: Do you have a view on a technology or product that's developed in the US that we're at risk of getting regulated out and we're- or are we kind of going on the right direction at this moment?","offset":2009,"duration":9},{"text":"Trae Stephens: I would say that, like, semiconductors is actually a really interesting one back to your- your point about uh Fairchild. Is that, you know, we were the- the home of the semiconductor industry for many, many years. And, um, you know, once TSMC got- got, you know, ahead of- seam in Taiwan, uh they kind of ran away with it. And we didn't, rather than investing in a domestic competitor, uh there are all sorts of reasons for this that we could spend hours talking about. Um, we basically just allowed that to happen somewhere else. And now we're in a position where almost no amount of money is going to fix this problem for us, certainly on a timeline of relevance as it pertains to the risk that Taiwan has, um, in 2027. So I- I would say that's like another really big one.","offset":2018,"duration":39}],"startTime":1939},{"title":"Software, Hardware, and Decision Advantage","summary":"Shyam outlines the third offset strategy, emphasizing the integration of hardware and software to achieve a strategic decision advantage. He argues that systems must prove their interoperability in combat and field exercises rather than through rigid bureaucracies.","entries":[{"text":"Host: Getting back to defense. How does the hardware and software fit together in this, um, kind of emerging war technology landscape? You guys are building software, you're building hardware, like help us understand a little bit about what the systems of war look like in the decades ahead.","offset":2057,"duration":14},{"text":"Shyam Sankar: Well, I think the- the starting premise would be where does it give us an advantage. And, uh, you know, we had the first offset which was nuclear weapons, the second offset, precision-guided munitions and stealth. Really the third offset is decision advantage. How can we outthink and out-execute the adversary. That's where these things fit together. That's like the thesis of even having them to begin with. And I think the reality is that there's kind of a messy overlap of these things. Like all innovation is messy and chaotic and maybe the department suffers at times because it tries to have a- a framework based approach. Like we're going to have MOSA, modular open standards architecture, something like that. You know, it's like we're going to avoid all of the pain and messiness by having some sort of process. But in reality, the process always destroys all of the innovation. And so there- there's obviously a very tight thesis where these things need to coexist and build off one- one another. They need to be interoperable. But you have to earn that. You have to earn that opinion in the exercises and the tests and the evaluation and combat would be my- my humble suggestion.","offset":2071,"duration":60}],"startTime":2057},{"title":"Reforming Bureaucracy with Heretics and Heroes","summary":"The guests praise recent government efforts to streamline procurement and treat munitions as consumables. They emphasize that overcoming bureaucratic sclerosis relies on strong, founder-like leadership rather than political affiliations.","entries":[{"text":"Host: Do you think that outside of what Anduril's building, there's actions that this administration should be taking or that the private market should be taking to solve this hardware manufacturing and capacity gap that we have right now?","offset":2131,"duration":16},{"text":"Shyam Sankar: My view is they're actually taking a lot of actions. Not all of them have come to see the day of light here, but, you know, even something as simple as reimagining munitions and drones as consumables. They're not things that you build and then stock on a shelf. They're things that you- at the time of ordering them, you already have an exercise test plan where you plan to expend them. Which means that you're going to have to replenish them, which means there's a demand signal to industry to keep going. and- in a buying cycle that means that you can buy the next generation rather than having the old generation. Uh, and I think this department sees that in a very clear-eyed way and is doing the yeoman's work of like stitching that through through all the services, all the portfolio acquisition executives. To the point of not believing in process, they've moved from a world where you have a very rigid, \"hey, I said I was going to buy X of Y and I can't change my mind,\" to a world where there's more autonomy and authority for the people who are buying things to say, \"I told you I was going to buy something that accomplished this goal. I can change my mind about how I'm going to accomplish this goal.\" Which, you know, can you imagine trying to run any private sector business without that degree of autonomy and- and flexibility in your decision-making.","offset":2147,"duration":62},{"text":"Trae Stephens: To echo Shyam's point about what the administration is doing, there are a bunch of swings that they're taking. It- it wasn't that long ago that, uh, in the Obama administration there was kind of the Solyndra failure where they invested in this solar panel company and it ended up being a bad investment for the US taxpayer. Um, but now the Office of Strategic Capital is taking a really hard look at critical minerals. They're looking at, you know, refining of- of minerals. And- uh they're engaging directly with the private sector to come alongside them in doing deals to get offtake agreements on these things. So, uh, I think there is some really clever thinking going on. Um, and then in addition to that, I think the procurement process is sort of up for revision constantly. Um, and Ash Carter started pulling a lot of these threads during the Obama administration. That was the third offset initiative. Um, but, you know, we're in a- in a world today where there's kind of a renewed vigor around being asked- private industry being asked, \"What do you need? Like tell us what you need to be changed about the way that we do business in order to streamline this and make it go faster.\" So I think there's a lot of positive momentum.","offset":2209,"duration":60},{"text":"Host: Do you guys think these changes have been institutionalized or are they political party dependent? If the Republicans lose the midterms and there's a Democrat president in 2028, do you think that there's a reversion to the old way of operating that's going to have some political influence and change things, or do you think we've really changed how things are running in the government here?","offset":2269,"duration":22},{"text":"Trae Stephens: I don't think it's political, but I think it's people. So you can go back to, again, Ash Carter, Democratic administration, highly focused on fixing these problems. The current Trump administration highly focused on fixing these problems. And, you know, there are a lot of people that live in- that were in the middle of that that didn't prioritize this, it wasn't- it didn't rise to the top of the stack. And so I think we always think of like the bureaucracy as being a political infrastructure or an institution or, you know, a bureaucracy. I actually just think at the end of the day it's about leadership. It's just do we have the right people that understand the set of the problems that we're- we're facing.","offset":2291,"duration":37},{"text":"Shyam Sankar: I couldn't agree more. I mean, I- I call them \"heretics and heroes\". Like, you- you know, the entropy of the bureaucracy is always towards some sort of sclerosis, it doesn't- it's not a political statement, it just is what bureaucracy does. When David Packard, who is probably the last major technology co-founder who served in the Department of Defense, when he came up with the 5000 series on acquisition, which today we view as just sclerotic BS that's- that's tied us down. Well, he- his document was seven pages long. In the- in the years between when he wrote that and now, it's 2,000 pages. So did he really screw us or did just the entropy take hold? And there was no strong leadership in between to go do the bush-whacking and mow the lawn and- and make the right decisions. Now, you know, this- this administration's blown up JCIDS, which is kind of- one of these insane bureaucratic processes, like can you just take a- forget a scalpel, take a machete and start clearing the jungle and re-earn some of these lessons as you go through it. If you look at Kelly Johnson, who was the founder of Skunk Works, he built 41 airframes in his career, including the SR-71, still the fastest flying manned aircraft, and- the U-2, which we still fly. Like one of- you look at his rules, one of his rules was he had to play defense to keep the government bureaucrats out of his program. And I think you could, okay, it's not a critique of government. You can think of big corporations. When the big corporations' bureaucracy gets into the innovation folks, the innovation stops.","offset":2328,"duration":77},{"text":"Trae Stephens: And the heretics and heroes were really founders. They were founders. It's like from a tech perspective, that's exactly what they were. And like to the Kelly Johnson point, the U-2 did not start as a US military aircraft, because they didn't want it. Uh, he ended up going through the intelligence community to get his start there, uh, and in- it was kind of finding the right person that was willing to take the risk to do the thing rather than relying on the system or the institution to do that. This is the same with Bennie Schriever with ICBMs, Admiral Rickover with the nuclear Navy. Um, it used to be about people. But today, if you were to go to the Pentagon and say, \"Who's responsible for the F-35?\" I'm not sure they even know. Who is responsible for the F-35? We're- we're building systems by- by committee rather than trusting founders and people who want to build them.","offset":2405,"duration":45},{"text":"Host: Yeah, I mean, there's- there's like a proclamation, \"it's so great, it's this X, Y, or Z project is built in all 50 states.\" Like the objective is- it's being- the money's being spread around versus how do you achieve the objective.","offset":2450,"duration":12},{"text":"Trae Stephens: The F-35 has components manufactured in 400 congressional districts. Right. I mean, that's like- that's a political project.","offset":2462,"duration":8},{"text":"Host: We had this A/B test with SLS and Starship, right? Like SLS had to have subs in all 50 states. But this A/B test has been played out.","offset":2470,"duration":6},{"text":"Shyam Sankar: I do think there's something about the kind of Calvinist spirit of America that sometimes gets us to misunderstand. You know, we call it the Apollo program, but it was probably- it's really the James Webb program. You know, uh, it's the F-16, but it's really John Boyd's plane. And and there's like a humility where we'd never want to call it, you know, it- you wouldn't call it, although I maybe the nuclear Navy we kind of do call it Rickover's Navy. But there's an element of like it's obviously both things. It's bigger than the person, but actually the starting conditions require the founder figure.","offset":2476,"duration":28}],"startTime":2131},{"title":"Military Readiness and Attritable Mass Systems","summary":"Addressing America's state of military readiness, Trae highlights the need to shift from solely exquisite, expensive systems to lower-cost, attritable autonomous mass. They stress the urgency of scaling production immediately to prepare for future conflicts.","entries":[{"text":"Host: So tell me about where we are in the state of readiness. You know, we highlighted some of the statistics. But if you guys were to think about what we need to accomplish, the infrastructure we need to stand up to have production lines that can be turned on to support munitions capacity for conflict in, you know, pick your region, let's say more than one region around the world, and the US needs to sustain those conflicts to defend the United States. How far are we from being ready based on what's going on in the investments that are being made today across the sector?","offset":2504,"duration":31},{"text":"Shyam Sankar: I think the- the way I think about it is if you thought about this as a spear, the tip of the spear is incredibly sharp. The shaft of the spear needs a lot of work here. Um, you know, the Department of Defense is such a- big organization, it- it's structurally supply and demand is not integrated. You know, the demand side is the real-world events that happen at the combatant commands. The- the supply side are what the services and the industrial base build, demand, train, and equip, and how you're actually producing that material. And the ability to drive consensus, which is really the beating heart of any private sector company, of like how do supply and demand come together, what's our view of it, is kind of managed with- with great difficulty in the Pentagon. And your ability, your agility to respond to scenarios is- is weak. That's- that's where we can have a lot more precision, because if you can start changing your mind and saying, \"Actually, I thought I needed X Barracudas, but now I need Y Barracudas and Z Furies,\" how quickly does that take to percolate through the supply base? You know, instead we get locked into these like, \"Hey, we've made a decision. The decision really can't be revisited.\" Uh, and then you start over time the entropy is like, \"Hey, let- I need- I have an unexpected bill. Let's just take a little bit of money away from these programs,\" and everything starts getting down to minimum rate production, which is this idea of what can I produce to just keep the line open, which is not deterrence. That's how we've frog-boiled our way here. And this is where my- my idea of like you've got to tie this into consumption. Like everything you're building, particularly on the munition side, needs to be consumable such that you know you're going to replenish it, such that the primes and the neo-primes all have the demand signal they need to keep going and have a reason to produce them cheaper in order to make more money. My most contrarian idea is like- the cynical view that like you have the military-industrial complex and they're just in it to make money, well it- it's kind of a crappy business. Like, you know, these companies trade at like less than two times revenue. The problem is it's not profitable enough, actually.","offset":2535,"duration":111},{"text":"Host: But Trae, Shyam said in the past we have eight days of munitions on hand for a major conflict with China versus 800 days needed. How far away do you think we are to having the supply chain built and the production capacity built to meet that objective?","offset":2646,"duration":16},{"text":"Trae Stephens: Well, I mean one of the other things Shyam just said in this conversation is that there's a high-low mix question as well. Like there are exquisite systems that are like the multi-million dollar interceptor missiles, and then you have, you know, dumb munitions, things- like bombs that are being dropped and things like that. And it's not the same across that entire stack. You know, there are some- some munitions that are woefully undersupplied and we have very low readiness on, and there are others where I actually feel pretty good. Um, from an Anduril perspective, you know, we're looking at ramping as fast as we can. We just opened Arsenal yesterday uh to start producing Furies. Um, and, you know, looking out over the next 18 months, we're not taking our- our foot off the gas. And yet, there's a lot of work to do.","offset":2662,"duration":38},{"text":"Trae: There's still a run rate capacity that we're running into as we ramp. Like, it just takes time to get all these lines stood up. Um, so you know, if we were to start today with unlimited cash, I think over the next 18 months as a country, we could get to the point where we were on track for having a sustainable industrial base.","offset":2700,"duration":22},{"text":"Trae: But we're not going to do that. We're going to trickle it out over time and, uh, and I think that unless there's real political leadership that steps up to drive this forward, we will likely be in a similar situation for a long time. Um, and so I think we really need to take advantage of this specific moment where there's clearly urgency that is understood by leadership across the administration.","offset":2722,"duration":21},{"text":"Host: How much of the spear is autonomous systems? Is everything going autonomous? Is it just drones or is there on the ground autonomous right now?","offset":2743,"duration":8},{"text":"Trae: Well, I would actually argue that like, the wars of today are fought with the weapons of yesterday. That's like, just a fundamental truth. And some of our weapons of yesterday are awesome. Like, B2s are incredible. Uh, the bombs that we dropped last summer in Iran, incredible. Like, these are very high-tech, exquisite systems.","offset":2751,"duration":22},{"text":"Trae: Patriot missiles, incredible. They're very performant. Uh, they hit their targets almost every time. I mean, these are great systems. The problem is is that they're incredibly expensive and we can't resupply. Like, we're just, we're way behind the eight ball on that. And so, uh, you know, thinking about the wars of the future, it means that we need to start building these attritable mass systems today so that they're in inventory to be used for those conflicts.","offset":2773,"duration":23},{"text":"Trae: There are a number of Anduril systems that are at a readiness level, at a level of deployment that they're active and being used in combat today, but it's still a very small percentage of the way that the wars are being waged. Um, over, you know, the next five to ten years, that high-low mix is going to have to shift massively. I mean, this is just like, clearly evident in Ukraine, it's clearly evident in Iran.","offset":2796,"duration":24},{"text":"Trae: Uh, and I think the Department is making steps to ensuring that they have, uh, a better divide of low-cost attritable systems and those high-cost exquisite systems. Um, but uh, you know, as I said, it's going to take political leadership to get there. Uh, but we, we have the ability to do it.","offset":2820,"duration":14}],"startTime":2504},{"title":"The Ethics of AI and Autonomous Weapons","summary":"In response to concerns about AI in warfare, Shyam argues that autonomous systems will always have human accountability baked in. He asserts that using AI for precise, ethical decision-making is morally superior to older, less accurate methods of conflict.","entries":[{"text":"Host: The reason I ask is I want to talk a little bit about the ethics of technology to war, the Anthropic run-in with the Department of War recently. And I think you guys have both talked publicly about this. But Anthropic refused to let its Claude model be used in Maven without human oversight constraints, this is what's been reported, what Emil Michael has said.","offset":2834,"duration":21},{"text":"Host: And the Pentagon labeled them a supply chain risk. Both AI and generally autonomous systems beg the question, what role should humans have and who should have the right to play that role of hitting the kill switch? What's your view on the role of the technology vendor to the Department of War and where you guys draw your line on what your responsibilities are with respect to ethics?","offset":2855,"duration":21},{"text":"Shyam: Well, my, my view on my responsibility to ethics is a slightly different question than my belief in democracy, which is a different thing. Um, so maybe starting on the democracy point, um, I believe that the people of America have elected representatives to make really hard decisions about how we engage in combat. Full stop.","offset":2876,"duration":19},{"text":"Shyam: Um, fully autonomous weapons are not new. We've had autonomous systems in operation like CIWS, which is deployed on, uh, naval vessels that shoot down aerial threats fully autonomously. You don't have time to make decisions about, you know, incoming missiles or threats to your ship, you just have to shoot it down. So that's what CIWS does.","offset":2895,"duration":18},{"text":"Shyam: Now, CIWS has accountability in the system. There's a person on that boat that is responsible for whatever actions that weapon system takes. And I believe that this is the future of autonomous systems is that, just like any other system, whether it's a soldier carrying a gun, they are accountable for what happens with that gun, or, uh, you know, the captain of a naval vessel, they are responsible for what happens with that CIWS.","offset":2913,"duration":21},{"text":"Shyam: All of your autonomous systems are going to have accountability baked in. Now, ethically, how do I think about this? You know, I believe that, you know, what Shyam was saying about the first offset, the second offset, and the third offset, um, is you know, we have, we, as a society, went from like rocks and sticks to, you know, knives to guns to bombs and then in World War II we kind of plateaued with nuclear weapons.","offset":2934,"duration":25},{"text":"Shyam: And we all looked around at each other and we said, \"Wow, that's pretty crazy. I don't think we want to make more and more powerful nuclear weapons forever.\" And so actually our engagement in combat has come back down the chain. Uh, we're doing precision-guided weapons, we're shooting non-explosive missiles into windows of apartment buildings, avoiding casualties, unintended casualties.","offset":2959,"duration":21},{"text":"Shyam: And I think that's really the goal. And if you look at AI as the command center for making better decisions with better precision, with better discrimination, with, uh, less the less civilian casualties, this is good. It's actually ethically far improved from just dropping dumb bombs on areas of cities to eliminate military facilities. So, uh, I don't think abstention from participating in the building of technology for national security is a morally neutral decision.","offset":2980,"duration":27},{"text":"Shyam: You are making a moral decision when you decide to abstain. And I am making a moral decision as a private citizen building a company in this space that I believe that this is ethically just, and uh, I trust in our democracy to deploy those tools with the interest of the American people at heart.","offset":3007,"duration":16}],"startTime":2834},{"title":"Palantir, Surveillance, and Legal Accountability","summary":"The guests address accusations that Palantir enables a surveillance state, clarifying that the platform enforces legal policies and enhances data security. They also outline the established Inspector General mechanisms for reporting illegal government activities.","entries":[{"text":"Host: There's a lot that's said about Palantir enabling a surveillance state. We had the All-In Summit in September, Alex Karp, your CEO, spoke, and there was a protest group outside protesting Palantir powering a surveillance state. I just want to give you a chance to respond to that, number one.","offset":3023,"duration":18},{"text":"Host: And number two, if you saw that Palantir's tools were being used in an illegal way, where's the responsibility for Palantir as a technology vendor in addressing those concerns?","offset":3041,"duration":9},{"text":"Shyam: It's almost hard to respond to because it's very unclear what surveillance people think we're doing. You know, there's just like a broad, almost maybe an outgrowth of Terminator fear around technology.","offset":3050,"duration":10},{"text":"Host: And I want to get into that cultural question next. I think it's very important to understand.","offset":3060,"duration":4},{"text":"Shyam: We don't collect data, we don't have any data. It'd be like, it'd be like accusing Excel of being a surveillance tool, right? It's like, this is a way of bringing your own data that you have lawful authorities to collect together to make decisions. Sounds a lot like Excel. Um, but it's, you know, because we are unabashedly patriotic and serve the US military, I think people have a kind of colored view of these things.","offset":3064,"duration":22},{"text":"Shyam: I would argue that it's actually Excel with cell-by-cell security with way more security, way more accountability. You know, it'd be as Karp says, it's the most insane platform in the world to try to do something illegal in because you are going to be caught. You know, like, that was part of the idea of how do you enhance privacy and security? It's how do you build more civil liberties protections in?","offset":3086,"duration":22},{"text":"Shyam: How do you have a normative view that enables a democracy to say, \"These are our laws and rules, the system will enforce it,\" we're not just relying on people happening to do the correct thing. Uh, so that's one piece of it. The other piece of it to come back to this broader point is the need for epistemic humility. Like, one of the, to the point of we have elected officials, they are accountable for these policy decisions.","offset":3108,"duration":21},{"text":"Shyam: I think at the limit, it's actually kind of indefensible to have a perspective other than lawful use, because if you are salami-slicing the policy, that's actually tyranny by tech bro. You know, a small number of people are constraining the maneuver space of a democracy with no accountability to the populace. So, I think that's a pretty challenging perspective to be in.","offset":3129,"duration":20},{"text":"Shyam: And we've been in this perspective before, if you go back to how did the Soviets get the nuclear bomb? You know, there was really, there were two sources of treason. One was committed communists like Klaus Fuchs who was always a spy. But the other were people like Theodore Hall. He was one of the youngest scientists in the Manhattan Project at 18 years old. Uh, his brother Edward Hall built the Minuteman missile. His brother was, you know, kind of a heretic and hero in my terms.","offset":3149,"duration":21},{"text":"Shyam: But Theodore said, \"You know, I'm one of the best physicists in the world, I'm probably also one of the best geopolitical strategists in the world. And I think the only way to have world peace is if two countries have the bomb.\" So in 1944 Theodore Hall walked into the Soviet trade mission in New York and gave them critical secrets to the bomb. Now, Theodore thought he was going to deliver world peace. Instead, every death from communism since 1949 is actually on his hands. And there's no accountability for that.","offset":3170,"duration":26},{"text":"Trae: Yeah, I think one of the other things that comes up in these, uh, these conversations about powering the surveillance state is this belief that we have policies, but we don't actually want our civil servants to have the best technology to enforce those policies. And it's almost like a lack of belief in the institution of democracy.","offset":3196,"duration":19},{"text":"Trae: It's like, you know, traffic cameras for example. It's like, man, I'm sort of libertarian in some ways, I don't love traffic cameras, but if traffic cameras say, \"I'm going to send a ticket to every single person that blows through this red light,\" I don't know, maybe we have to change the policy around red lights if you don't like that.","offset":3215,"duration":14},{"text":"Host: I've gotten three speeding tickets in San Francisco from autonomous cameras in the last month.","offset":3229,"duration":5},{"text":"Trae: Well, they did ramp it up significantly, which is incredible that they're enforcing laws at all, if we're being honest.","offset":3234,"duration":5},{"text":"Host: I mean, like, here's my ticket, and then I'm literally watching the guy while I'm doing three miles over the speed limit, you know, take heroin needles out of his arms and put it on the floor next to an elementary school. And I'm like, \"Probably fine, yeah.\"","offset":3239,"duration":12},{"text":"Trae: That's our problem. But it's the same thing with like, you know, using tech for better enforcement of tax law or something like that. Like, do you, is what we're saying by criticizing what Palantir's doing, is what we're saying that we don't want our civil servants to have the best tools possible? Because you can have that position. I tend to think that that position is pretty morally bankrupt, but I guess you could have that position, but ultimately I think that's what it is.","offset":3251,"duration":34},{"text":"Host: Scenario play this for me, because there's a public perception, I don't know how far-reaching it is, that there's some tied corruption between government officials that use technology that's super advanced, that's hard for people to understand, and the technology vendors. If you saw government agencies using your technology, either of you, in an illegal way that you knew broke the law, do you report it?","offset":3285,"duration":19},{"text":"Shyam: 100%.","offset":3304,"duration":0},{"text":"Trae: Yeah, to the IG. There's an entire mechanism for that, absolutely.","offset":3304,"duration":3},{"text":"Host: Right, so can just, just explain that for a second. The Inspector General, maybe?","offset":3307,"duration":5},{"text":"Shyam: Yeah, so every agency has an Inspector General who's an independent organization that you can provide anonymous or non-anonymous complaints to that then have the ability, the statutory ability to do an investigation in an unfettered way inside of that organization, whether it's the Department of War or, uh, Housing and Urban Development, like literally every single agency.","offset":3312,"duration":21},{"text":"Shyam: Uh, and this mechanism is used. I actually, you know, in this case it was weaponized against one of my favorite heretics and heroes, Colonel Drew Cukor, who invented Maven, the founder of Maven really, but you know, people would file complaints claiming that he was uh hiding illegal immigrants in his basement, a basement that he doesn't really have. You know, but but all of those things were investigated, Naval Criminal Investigative Services went out to his house and actually looked into these things. So people take this incredibly seriously.","offset":3333,"duration":24}],"startTime":3023},{"title":"Anti-Defense Culture and Foreign Disinformation","summary":"Shyam and Trae trace the roots of anti-defense sentiment to the Vietnam War and the widening gap between the military and elite universities. They note that foreign adversaries actively fund disinformation campaigns to sow domestic division and fear.","entries":[{"text":"Host: Where does the culture come from? The anti-defense tech alignment culture? Is it because of the peace era that we had and folks took for granted national security?","offset":3357,"duration":10},{"text":"Shyam: I think the first schism was really during Vietnam where people felt like, uh, they were lied to about the war. It it drove a fundamental schism between academia and defense. And that we've never really healed from that schism. And so there's this this kind of sense, this distrust that's brewed there and kind of escalates through society.","offset":3367,"duration":21},{"text":"Shyam: The second schism is like the number of people who are prior service or are connected to this community who actually see these people as humans and have a fully informed mental model of how diligent they are, how the work actually gets done, what do these words actually mean, what is the process like, has evaporated.","offset":3388,"duration":18},{"text":"Shyam: So then their own fears fill how they think it happens and it seems like maybe it's happening more in a cowboy way, maybe it's happening in a way without oversight, that there is no such thing as doctrine. Like it's kind of a cartoon version of what's actually happening that I think you're unable to reconcile.","offset":3406,"duration":15},{"text":"Trae: Yeah, I think if you even look back at what happened with Snowden, uh, you know, what was that, 15 years ago now? Something like that. Uh, you know, that there was almost no discussion about the investigations that went into like, was the data collection actually abuse? And the answer is like, basically not at all.","offset":3421,"duration":18},{"text":"Trae: There were like less than 12 documented cases where someone got access to data that they shouldn't have, and it was because of like technology errors, not because of the policies that were implemented. Um, and so we can have disagreements about whether or not the intelligence community should have collected the data and stored it, uh, but that was that policy was renewed multiple times by multiple administrations, multiple political parties that had the majority in Congress over decades.","offset":3439,"duration":30},{"text":"Trae: And so apparently our elected representatives thought that it was important enough to keep in the system. Um, so I think it ends up being this kind of weird policy discussion. Uh, but the second point that you make I completely agree with about like the kind of distrust of the institution in creating the stories for themselves.","offset":3469,"duration":16},{"text":"Trae: I often times go and do guest lectures at Stanford and I always try to ask, like, raise your hand if you have an immediate family member that serves in the military. No one ever raises their hand. It's crazy. Like at Stanford, there are veterans that come in that go to the GSB and things like that, but in like the undergraduate undergraduate student population, it's incredibly rare for anyone to have any connection whatsoever in their immediate family to the military.","offset":3485,"duration":29},{"text":"Trae: And I think there's like, you know, some of this goes back to criticisms that people like JD Vance, uh, the Vice President, has made about, you know, elites in America and things like that, but there's just this incredible divide that has happened. Um, and we're kind of losing touch with that kind of salt of the earth, middle of the country, you know, veteran community that I feel like was way more present during the the Cold War, uh, and and you know the World War II before that.","offset":3514,"duration":21},{"text":"Host: Do you think that there's any external influence that's driving this culture? Are there influences on social media, in mainstream media? And maybe just talk about destabilization and the attack vectors. I've seen it in other areas of science. I don't want to spend time on this show talking about it, but there have been traces that I've found on external folks that want to destabilize American science and industry progress, and they create fear and they put out articles and then they go social and they they become viral and suddenly everyone believes it even though it's not true. Do you see that and have you actually kind of seen that in the sense of like attacking the the tech companies that are now supporting American defense?","offset":3535,"duration":39},{"text":"Shyam: 100%. Even if you go back to, let's stick with Vietnam, uh, the Soviets spent seven billion dollars in 2026 dollars funding the peace movement, the anti-war protests. Now, there's obviously some there is an organic element to it, but this is just dumping gasoline on the fire to sow division and discord. Uh, and I think in the present day I I think, you know, certainly we see it against Palantir where there's CCP money flowing to organizations that are protesting us for various domestic issues here. It's not isolated. It's broadly a successful strategy for our adversaries to sow division.","offset":3574,"duration":34},{"text":"Host: No one will believe it because no one wants to believe that they're being influenced.","offset":3608,"duration":3},{"text":"Trae: Right, but I I think Shyam's point is exactly right, it's like, it's actually a brilliant strategy. Like, good for them. They are they are not our friends, they're our adversaries. What would you do if you were in their shoes? It makes a ton of sense.","offset":3611,"duration":12},{"text":"Host: Do we do that?","offset":3623,"duration":1},{"text":"Shyam: I mean, look, we have all sorts of counter-intelligence operations operating. The modern art movement was really funded by the CIA to undermine the kind of Soviet control of art. You know, and it was it was broadly funded and it wasn't it wasn't directed by CIA, but you you can see how we have cultural values that we want to inculcate and spread.","offset":3624,"duration":20}],"startTime":3357},{"title":"Rebuilding Trust and Overcoming Nihilism","summary":"The guests discuss the importance of making American institutions functional to combat societal nihilism. They address the rise of socialism as a symptom of internal discord, broken promises to the middle class, and a failure of empathy-driven policies.","entries":[{"text":"Host: Do you think we have a shot at recasting the defense industry, the tech industry that's addressing defense, and aligning it with a notion of patriotism? And what is it going to take to make that happen?","offset":3644,"duration":12},{"text":"Shyam: I don't know, maybe writing a book called \"The Mobilized\"?","offset":3656,"duration":4},{"text":"Host: Oh yeah, you have a book! That's right. That's right.","offset":3660,"duration":2},{"text":"Shyam: I'm trying to do exactly that. You know, look, if if we look at it clear-eyed sense of the world and how much deterrence we've lost, you know, you could you could really say like maybe World War III's already started and 10 years from now we'll look back and and be able to perceive that, right?","offset":3662,"duration":13},{"text":"Shyam: And I I think you don't need literally everyone to view this, but if you can if you can create a more clear-eyed view of what's at stake here not only for you but for your children and their future, I I think you can you can get people to show up and participate. And this is this has been America's story all the time, you know, and usually when we start these things we are the underdog.","offset":3675,"duration":17},{"text":"Shyam: All periods of American greatness have started when we realize that we're the underdog. We were the 17th largest army in the world at the beginning of World War II. You know, and what did a ragtag bunch of farmers and random tradesmen have taking on the world's largest army in the British during the Revolutionary War?","offset":3692,"duration":20},{"text":"Shyam: You know, and I I think um having some clarity about what's at stake, what the counterfactual is. It's so easy when you're successful to kind of let the nihilism grow and say like, look how imperfect we are. This like the self-loathing creeps in. And this is where I take coming back to your point on the legitimacy of our institutions, like should these institutions work, do they deserve the best software?","offset":3712,"duration":19},{"text":"Shyam: I mean, look, if they're public or private, you can't have doors falling off planes, you know, our government organizations need to provide the basic services they've signed up to do without fraud, without corruption in an efficient way. And the reason is not just an aesthetic, it's like in the absence of that, it breeds nihilism. And the younger generations look at that and say, \"You know, we should just tear all of this down.\" And things will absolutely get worse in a world that looks like that. So it's incumbent on us to wake up every day and fight for the legitimacy of these institutions, to make them more functional.","offset":3731,"duration":26},{"text":"Host: America's story's never written, it's every chapter seems to be a whole new arc. And we're in one right now. There's a rising socialist movement in the United States. Can you guys just comment on how much you think that that socialist movement, cast with whatever term they want to use, is going to affect our capacity for defense and resiliency going into the next decade, particularly as our adversaries are rising?","offset":3757,"duration":25},{"text":"Shyam: Well, the argument I've always made is I think our greatest threat as a nation is not homicide, it's suicide. And it's it's in this vein, it's the internal discord, it's the division, it's the the self-loathing, it's um things like the socialist movement, which I think are symptomatic of this internal discord and ensuring opportunity for our people.","offset":3782,"duration":20},{"text":"Shyam: To the point of a functioning elite, if you were to go backwards and think about the root cause, like maybe we don't have an elite that cares enough about the prosperity of the American people. And we've made decisions through globalization, we were told NAFTA was going to be a great thing, that actually if you lost your job in manufacturing, why don't you just learn how to code?","offset":3802,"duration":19},{"text":"Shyam: You know, there there's a certain sort of callousness in that. And, you know, I'm not an unabashed free market and I'm clearly not a communist, but there's a sense of where the decision on the margin actually really does matter and that comes down to leadership.","offset":3821,"duration":9},{"text":"Trae: I think one thing that makes me a little hopeful is that socialism literally doesn't work. Um, and so you know you look at you know what happened in San Francisco even where, you know, we elect Chesa Boudin as the district attorney and then we're like, \"Oh wow, this is not going well, recall him.\"","offset":3830,"duration":16},{"text":"Host: Rooted in a selling point of empathy, right? Fundamentally.","offset":3846,"duration":2},{"text":"Trae: Yeah, exactly. Yeah. Uh, you know, what happened with the Board of Education getting recalled, you know, Daniel Lurie coming in as the mayor, uh, you know, we felt like we kind of went into this valley and sort of hit rock bottom, um, but I do think that people eventually realize that it doesn't it just fundamentally doesn't work.","offset":3848,"duration":18},{"text":"Host: Seattle and Washington state are likely going to lose a large number of their biggest employers. And as that happens, they'll come through on the other side, probably might take them 7 to 10 years to get there.","offset":3866,"duration":10},{"text":"Trae: Yeah, it might be painful and it might take them a long time, but I think they'll eventually come to their senses.","offset":3876,"duration":5}],"startTime":3644},{"title":"Disagreements on Communications Strategy","summary":"When asked what they disagree on, Trae reveals they clashed over Palantir's secretive communications strategy. He explains how Anduril adopted a more public-facing approach to tell its own story and control the narrative.","entries":[{"text":"Host: What do you two disagree on?","offset":3881,"duration":3},{"text":"Trae: That's a great question. Yeah. Um, we actually, I'll be honest, we bickered with each other quite a bit at Palantir. Um, and usually it was Shyam being right about something and me taking a long time to come come along to his point of view. Uh, but uh, yeah, I think, you know, any of these cultures that are like well-functioning are rooted in debate, um, and eventually—","offset":3884,"duration":20},{"text":"Host: But you're avoiding my question. Whether it's actions or outlooks. Whether you should show up to your interview at a tech company in a suit.","offset":3904,"duration":10},{"text":"Trae: I know. Well, no, I will say this, because it actually is part of the story of Anduril. I thought that it was a bad decision at Palantir to be as quiet as we were. I thought that we needed to get out there and tell the story so that there would be data that says things like what Shyam said about like we don't have any data, we are Excel.","offset":3914,"duration":22},{"text":"Trae: Um, and we had a very kind of quiet, reserved comms strategy. Um, and we went back and forth on that a lot. And uh when I started Anduril, I was like, you know, all the positive things we learned about uh doing business with the government from Palantir, the one lesson that I learned that we didn't implement at Palantir is we're going to go out there and tell our story. Um, and I think that's worked for us incredibly well, and I'll be honest, I think Palantir has come along to my my side of of that debate.","offset":3936,"duration":22}],"startTime":3881},{"title":"Vision for 2040 and American Primacy","summary":"Looking ahead to 2040, the guests warn against a unipolar Chinese century and advocate for massive American re-industrialization. They conclude that maintaining a leadership position is crucial for setting global rules and ensuring ongoing economic prosperity.","entries":[{"text":"Host: And last question, if we don't do things right, what does 2040 look like? And if we do do things right, what does 2040 look like? Economic and defense.","offset":3958,"duration":9},{"text":"Shyam: Well, the the economic part is I think the critical one because national security is not an end unto itself, it's a means to an end and that that end is economic prosperity, the prosperity of the American people. Uh, you know, I think no country has done more to develop the world, like how did integrated circuits and microelectronics get to Southeast Asia? We sent them there.","offset":3967,"duration":19},{"text":"Shyam: Yeah, we benefited in terms of trade there, but you know, like which other winner in a war spent their own capital to rebuild the conquered, in Japan and Germany? And and now you have this stability as a result of it. So when I think about what could go wrong is you actually have a Chinese century that we never recover from, that literally everyone in the world is a vassal state to China and might makes right in their sort of world.","offset":3986,"duration":24},{"text":"Shyam: You know, and we shouldn't forget is like it's very clear even in the present moment that for the CCP it's not enough for China to prosper, America must fall. That's an explicit part of the strategy. Look, it is a business decision if you want to buy American or Brazilian soybeans. I actually don't begrudge you one iota which decision you make there.","offset":4010,"duration":15},{"text":"Shyam: It's an entirely different decision when you're smuggling agricultural funguses into the US so that we can't grow soybeans. That's the sort of zero-sum frame that I think 2040 will look like if we get this wrong. And if we get it right, I think what we actually see is a massive re-industrialization of America followed by the West.","offset":4025,"duration":15},{"text":"Shyam: Um, we see a thriving middle class, which I define qualitatively as a middle class that believes their children's future will be better than their future, which is something that I feel is a fundamental promise that's broken down over the last 30 years or so. Uh, and a belief in our institutions once again.","offset":4040,"duration":15},{"text":"Trae: Yeah, no, completely agree with all those points. Uh, I think there's a big component here around education that we haven't talked about as well where we figured out a way to educate and successfully enter our young people into a marketplace that uh needs them and that benefits from their services.","offset":4055,"duration":16},{"text":"Trae: Um, and I think that we haven't quite nailed that. Um, but I do think that the re-industrialization point of this is going to be kind of the central point of uh making sure that China's many, many decade belt and road strategy is not going to put us in a position where we literally just can't do anything.","offset":4071,"duration":17},{"text":"Host: Do we need military and industrial primacy or can we operate in a multipolar world where the US can share influence and economic prosperity with China, perhaps Russia, perhaps one or two other nation-states?","offset":4088,"duration":16},{"text":"Trae: Well, the challenge with not being the leader is that you don't get to set the terms of engagement. And so I think the benefit that we have had uh since really the end of World War II is that we've had the primary seat at the table to say this is how we're going to do uh, you know, semiconductors, this is how we're going to do supply chain, this is how we're going to protect trade lanes. And I think the moment that you step back from that, uh, and someone else has all those incentives, uh, you start playing the rules of their game, and it doesn't stay multipolar for long.","offset":4104,"duration":28},{"text":"Host: Well, I really appreciate the two of you being here, Trae, Shyam, thank you guys, this has been great.","offset":4132,"duration":4},{"text":"Trae: Thank you.","offset":4136,"duration":0},{"text":"Shyam: Thank you, guys.","offset":4136,"duration":15}],"startTime":3958}],"entries":[{"text":"Host: Trey Stevens, Shyam Sankar, welcome to the All-In Podcast at the Hill and Valley Forum. Thank you guys for being here. What's up? How are you guys doing?","offset":0,"duration":7},{"text":"Shyam Sankar: Thanks for having us.","offset":7,"duration":1},{"text":"Trae Stephens: Doing great.","offset":8,"duration":1},{"text":"Shyam Sankar: Good to be here too.","offset":9,"duration":1},{"text":"Host: You guys are friends, right? You guys go back, like, a long time?","offset":10,"duration":2},{"text":"Trae Stephens: A really long time.","offset":12,"duration":2},{"text":"Host: Okay, tell us how you guys know each other. Palantir, Anduril, what's the connection and the history?","offset":14,"duration":5},{"text":"Shyam Sankar: Well, I'll start, you can fill in all the gaps.","offset":19,"duration":3},{"text":"Trae Stephens: I feel like I know the story you're going to tell and it's going to be very uncomfortable.","offset":22,"duration":32},{"text":"Shyam Sankar: So, Trae, I think, you know, in the early days of Palantir, I was roaming around giving demos to anyone who could possibly want to see them. Trae was working in an Intel agency and happened to see one of these demos, and he should tell you his version of it, his side of it, his frustration with bureaucracy, but I think he realized, like, hey, this- this might be really cool. Maybe I should leave the hellhole I'm in in the basement of this building getting nothing done, talking about sports with other people, to go join this crusade. So Trae reached out and applied. Uh, he- he made a big faux pas. He came all the way to Palo Alto and he- he wore a full-on suit, tie, cufflinks, CIA cufflinks, mind you, to- to come to interview with, I don't know, we were probably 20 people, you know, who wore T-shirts and, you know, secondhand hand-me-down clothes. Um, and- and I think, you know, he was intercepted in the lobby by a receptionist who- who really cared about him and told him to get- ditch the tie and try to dress down and don't screw it up too bad. But we loved him immediately and he helped us build the- the government business.","offset":54,"duration":65},{"text":"Host: So this was at Palantir. You were there employee 13, 2006, right? So this was pretty early on.","offset":119,"duration":6},{"text":"Trae Stephens: Yeah, I- I came in in early 2008, but there were still, you know, 25, 30 people at that point.","offset":125,"duration":5},{"text":"Host: Pretty small. And Peter kind of incubated it, was involved at the beginning, right? Peter Thiel? Maybe you could just recap because I know a lot of folks know the history of Palantir, but just kind of, like, the early stand-up of Palantir and how things got going during that era with that small group, how you guys kind of figured out how to build the business.","offset":130,"duration":19},{"text":"Shyam Sankar: Yeah, it was- it was one of those things that was kind of a slow start. It was- there was a real idea amongst the five co-founders, including Peter, that, you know, it's kind of insane to live in a world post-9/11 where people are arguing about what's more important, privacy or security. Like, aren't they both really important and who is actually spending time pushing out the efficient frontier? For any amount of given security, you should have more privacy than you had before, or any amount of given privacy, you should have more security. And- and this sort of changing the dialectic there was really the entire impetus of- of what we started with. And now there's a technical approach that follows from that, there's an approach to privacy and civil liberties that are around that. Um, but really we started as a business that was pretty myopically focused on solving a handful of problems in counterterrorism for a handful of institutions in the world.","offset":149,"duration":43},{"text":"Host: Let me start by asking a question that I think is important to ask, particularly for a broad audience, and for the two of you to frame your personal philosophical views. Is war good? There's a lot of conversation about there is a military-industrial complex that has an incentive for war. What's your view, your philosophical motivation for why you do what you do, what your view is of war and defense, and- and the work that your business has kind of pursued?","offset":192,"duration":29},{"text":"Shyam Sankar: Well, any- anyone who's been to war would tell you that war is awful. War is bad, categorically bad. That doesn't mean it's always avoidable. And that, um, you know, there will- there are people who will want to use might to make right, to define a set of rules. Um, and you have to be in a position to protect your people and your interests accordingly.","offset":221,"duration":17},{"text":"Trae Stephens: At the end of the day, it's all about deterrence. You don't want to go to war, but you want to be prepared so that if you do have to go to war, that you will win decisively and quickly. Um, I've never met a general that has said, you know what I really want to do today? I want to make phone calls letting parents know that their children have died in combat. Nobody wants to do that. Um, and- and I think that that's really the goal of everything we were working on at Palantir, it's what we're working on at Anduril, which is make it unthinkable to your adversaries that they should ever challenge you.","offset":238,"duration":29},{"text":"Host: Why do you think it became taboo and became so negative, particularly in Silicon Valley, that building a defense company or a company building technology to service the defense sector was viewed with- with such disdain and was an untouchable sector for so long?","offset":267,"duration":16},{"text":"Shyam Sankar: I think it's a beautiful consequence, and I mean it- unironically, of kind of the peaceful world that we lived in. The origin story of Silicon Valley is actually defense. You know, Lockheed was the largest employer in- in Silicon Valley in the 1950s. The Corona spy satellites were built there. So in a world that was, um, gripped by the threat of the Soviet Union, you know, you had a very different posture in Silicon Valley. But in a world post-the end of the Cold War, the end of history, kind of a view of globalism that it's all going to be great that we exist beyond the confines of our country, um, these things were viewed much more cynically and the threats didn't seem very real. And I think you could even backtest this through the moment where Silicon Valley kind of really woke up and realized, hey, maybe these things are real, are when the Russian tanks rolled across the Ukraine border. You know, it's when they realized there are a lot of Ukrainians, Eastern Europeans, there are a lot of people who were affected by that in Silicon Valley, who started to realize that, um, maybe there's a more nuanced issue here than just simply the simple Eisenhower quote of the military-industrial complex.","offset":283,"duration":60},{"text":"Trae Stephens: Yeah, I think many of the people who were protesting Silicon Valley's involvement in working on national security priorities were the exact same people that had Ukraine flag in bio. Um, so there's clearly just like a policy mismatch or an understanding mismatch. The other thing that I would mention is that these large tech companies, unlike many epics prior, uh, were global technology companies. They didn't necessarily view themselves as American. Um, and so if you go and you look at, you know, where these protests came from, you have to keep in mind that a lot of the signatures that they had on these, you know, protests, uh, were not coming from US citizens. And so there's like a global character to those companies that probably was not the case during the Cold War.","offset":343,"duration":42},{"text":"Host: Do you think that's changed recently?","offset":385,"duration":1},{"text":"Trae Stephens: I mean, to Shyam's point, I think that there's just an increased awareness of the complexity of the geopolitical situation. Um, and- and I think it's certainly a lot less controversial work on these topics than it was in 2017, 2018.","offset":386,"duration":13},{"text":"Host: You know, it's a 20-year overnight success, right? And Anduril's now reportedly raising money at a $60 billion valuation, just landed a $20 billion Army contract, Palantir today is worth $400 billion. The flip side of what I just said is that some people are saying that Silicon Valley is taking over defense and Silicon Valley is the next story of the American war machine. This has become sort of a popular narrative. Can you just respond a little bit to kind of where we were coming out of World War II from a defense industry perspective, where we find ourselves where Silicon Valley seems to be at the center of this today?","offset":399,"duration":43},{"text":"Shyam Sankar: You know, the industrial base that won World War II and the early Cold War was not a defense industrial base. It was an American industrial base. You know, Chrysler made the Minuteman ICBM, they were the prime contractor on it, and they make minivans. General Mills, the cereal company, had a mechanics division. Everything they learned doing R&D to process grains, they actually used to build torpedoes and inertial guidance systems. Ford built satellites until 1990. So the entire economy was invested not only in economic prosperity but also underwriting the freedom that allowed us to have economic prosperity. It's really a consequence of the end of the Cold War. So when the Berlin Wall still stood in 1989, only 6% of spending on major weapons systems went to pure-play defense specialists. 94% of it went to what I call as dual-purpose companies. You know, yeah, a missile is single-use, it's not a dual-use product, you're not going to buy it at Walmart, but that actually these companies were invested in both parts of this. That figure today is 86% goes to defense specialists. So we have a very different structure of the US economy as a result. and I think it leads to very perverse narratives of what would it be like to mobilize. If- if things got really bad, we'll just flip a switch and our auto factories will magically turn into enabling us provide for our defense and security. And- and I think a- cold-eyed look at history is it took 18 months to do that. We actually started ramping up to provide this stuff for our allies, for the Brits and the Soviets in the context of World War II, and that we've actually missed some of those signals today. When- when Ukraine went through 10 years of production in 10 weeks of fighting, that probably should have been a five-alarm fire that we got the fundamental calculus on deterrence wrong. We thought the stockpile was going to deter our adversaries. It was always the factory, it was the ability to generate and regenerate the stockpile.","offset":442,"duration":100},{"text":"Host: Right. And Trae, you've talked about this. You wrote an article, \"No Solvency, No Security\". Just share with us your view on the importance of this industrial base and what it takes for us to have strong defense requisite in a strong manufacturing industrial base.","offset":542,"duration":111},{"text":"Trae Stephens: I- I mean, we really kind of sent most of these capabilities away, um, during the last 30 years of globalism. Uh, and that gutted entire communities in the United States. You know, I mention in this article that just in my immediate family, like grandparents, aunts, uncles, uh, I have family members that worked at GM, at Ford, at Frigidaire, at National Cash Register, at Armco Steel. Every single one of these factories in Ohio closed. Not a single one still exists. And they all have different places they've gone around the world. Um, but, you know, one of the things we're doing with Anduril right now is we're building out a 5 million square foot factory campus in Columbus, Ohio. And we have the benefit of going back and tapping into that knowledge base that exists that's underemployed at the moment because those the factories that kept them busy for many, many years are- are closed. Um, and I think this is the story all over America. Like if you think about the at-scale manufacturing for a new company started in the this century, uh, in the 2000s, um, there's really only one that comes to mind: just Tesla. That's it. And so we haven't really built any muscle around a new manufacturing capacity. Um, and- and I think that as you spin things up, to Shyam's point, we don't have the ability to do that quickly because we've atrophied massively by- by turning all this away globally. So, um, I think readiness is a real problem and- uh we have to start investing ahead of the the, you know, conflict being- being there because you can't just start at the moment that it's absolutely needed.","offset":653,"duration":95},{"text":"Host: Tell us about the Arsenal 1 and then the manufacturing behind it. And then I want to just understand a little bit about is this product-led or production-capacity led. Do we need to make selections and have capital committed to bringing product to market before we start to build out the base, or is there an alternative way to get ready?","offset":748,"duration":17},{"text":"Trae Stephens: Arsenal 1 is our- the factory campus that we're building in Columbus. Um, the operating system for that, the Arsenal platform, um, is really intended to reduce the- the cost, the overhead, that's required to automate and- uh, you know, handle these processes in the most efficient way possible. So there's like kind of the software layer that sits behind that. We're actually working with Palantir, uh, the Foundry platform, on some of these programs as well. And, uh, the idea behind this is that you want it to be as modular as possible. If we built out the factory campus and we said we're just going to build Furies here, or we're just going to build Roadrunners here, we're just going to build Barracudas here, that provides a- tremendous limitation in a- in the moment of a conflict to be able to be responsive to the demand for specific things that are relevant to that conflict. And so we're kind of thinking about this more like contract manufacturers think about building assembly capacity where they say, yep, we make, you know, this VR headset for Facebook, we make this- this VR headset for Samsung, we make this- this VR headset for Apple. Uh, we build a skill set around building optics systems, um, but we're going to build a bunch of them. And we're going- we're going to be much more effective at doing that by hitting the network of scale, uh, you know, get lower costs on all the individual parts, you're going to build out a supply chain to- to work through that. That's roughly what we're doing in this case, as we're saying, like a contract manufacturer, we want to be able to pivot on a dime into ramping up production of Roadrunners if we need Roadrunners or ramping up production of Barracudas if we need Barracudas. Um, the counterexample to this, of course, is what we saw in the early days of Ukraine, where what they really wanted was more Stingers and Javelins. The problem is is that we once- once we burned through our inventory in the warehouses of Stingers and Javelins, the assembly line to build Stingers and Javelins didn't exist! All the people that worked on those assembly lines were retired! And so the primes were literally calling people out of retirement to come back and teach them how to build Stingers and Javelins again. Um, and so these are problems that we're trying to avoid by the design of the factory as- as an initial concept.","offset":765,"duration":123},{"text":"Host: Who funds it? So is there a government contract that supports the production of these facilities and are multiple companies going to be able to afford to- to stand these up, to make these investments, or is this just going to end up being an Anduril play because you've got most of the capital and you guys are going to roll these facilities out? How do we make this kind of a national interest?","offset":888,"duration":18},{"text":"Trae Stephens: Well, our business model is definitely very different from the primes, uh, who are basically responding to things as requirements directly from their customer. So they're not really investing a whole lot forward of the capability. Anduril, on the other hand, we're doing all of this as private R&D investment and then we're selling the outcome, the output of that, as a product. So this is fundamentally a different business model. Um, but I do think that there's a tremendous amount of capital that's required to pull this off uh, as a new entrant to the space. Uh, I don't think that the market is going to support 100 new primes or something like that. Uh, I'm hopeful that it's not just Anduril. I think it would be healthy if there was more competition in the space. Um, but, you know, being able to raise that amount of capital, hire the people that you need to actually pull it off, uh, this is not- it's not like building a- a normal tech company. It's not just the development of a product. It's- you know, there's a lot that goes into this.","offset":906,"duration":53},{"text":"Shyam Sankar: Trae's point might seem kind of obvious or simple, particularly to an audience that's largely coming from tech or Silicon Valley, but that's not how defense works. People don't build products. People build to a spec that the government says, \"this is what I want to buy,\" and then you kind of say yes. You- you have to think about defense as a monopsony where there's a single buyer for the thing, and that concentrates an enormous amount of power in the buyer, whether they're right or wrong. And if you look at the history of defense innovation, typically the monopsony's wrong. You know, it was Churchill as the head of the Royal Navy who built the tank, because the British Army was not smart enough to realize that in the next battle having horses was not going to work. So every one of these innovations is kind of an act of heresy. There's- there's a founder-like figure who is so committed pathologically to a different heretical concept, they see it through and only in combat or only when it meets the moment is it actually validated. Now, a- grave threat like the Soviet Union is a sort of forcing function that allows- allows you to innovate. When we were building ICBMs, we had eight competing programs. Today in peacetime, that would be viewed facilely as wasteful. Why should you have eight competing things? Why can't you just pick the right one and put- you know, spend less or put all your wood behind one arrow? And of course, that kind of turns its back on our fundamental belief in America on the free market, that there's a competition of ideas, there's fundamental uncertainty, there's quality- like variance in the quality of the execution and that you need this competition. And it's not just principally competition amongst the primes or new entrants, it's also competition inside of government.","offset":959,"duration":86},{"text":"Host: And there were originally, I think, or at one point 51 major defense contractors. And just for the audience to understand, they reduced down to roughly five or six primes. That's- that's the term \"prime\" is one of these prime contractors and then they subcontract out to other companies uh to develop componentry parts. My understanding in Anduril was to do exactly this: build a product, show up with something that's cheaper, better, faster and actually competes on the merits rather than be caught in this kind of prime landscape. And that work clearly worked. But over time, there seems to be a lot of capital concentrating into the \"new primes\". You guys, you guys, SpaceX, OpenAI, maybe one or two others. Is the landscape going to emerge that it- we're going to just look like the same old way of operating where we have a handful of primes that all have these trusted relationships with the government agencies, or how do we kind of create that competitive environment to continue to drive innovation and make things affordable for the US government and the taxpayer going forward?","offset":1045,"duration":59},{"text":"Shyam Sankar: Well, just like- and- and I interviewed Trae in- in my new book on this, like- just like venture, there's going to be a power law here. You- so one of the- grave mistakes we've made as we think about innovation which has resulted essentially in innovation theater is this idea that you're going to just peanut butter spread around the capital you have for innovation. That, you know, every company's going to get roughly the same amount. It's not enough to hit scale. It doesn't reflect actually the relative performance differences, because there's an authentic power law curve. Like any venture capitalist would- would realize that, you know, your- your biggest winners are going to return your whole fund. There's- there's something authentic here as well, which is like, yeah, you may have 10 bets, but you're- at some point you're going to have to get smart about concentrating down on the things that are actually working.","offset":1104,"duration":39},{"text":"Trae Stephens: Yeah, I mean, this is a- kind of a great point about any category. It's like if you're a space tech investor and you didn't invest in SpaceX, you probably lost money. If you're a crypto infrastructure investor and you didn't invest in Coinbase, you probably lost money. If you're a social media investor and you didn't invest in Facebook, you probably lost money. And yet for some reason, capital allocators have a very short memory. They don't have the ability to go back to the- the prior- boom cycle and say, oh wait, I remember what happened that last time we had to concentrate capital down to the winner. Um, and- and I think that this- this isn't any different.","offset":1143,"duration":32},{"text":"Host: So what was the motivator then for change in the construction of the landscape of defense contracting? Was it software that takes us from the old primes to the new primes? Is that really what kind of triggered this cascade evolution?","offset":1175,"duration":12},{"text":"Shyam Sankar: Consolidation. So in '93, having won the Cold War in '91 or I think more accurately the Soviets lost the Cold War. You know, by '93, we expected as a nation a kind of peace dividend. We don't have an adversary now, we should be able to spend less on defense. And- the department had this famous dinner where they brought 15 of the 51 primes together and said, \"this is going to happen, the budget's going to get slashed, we're not going to save you guys, you have our permission to consolidate, some of you are going to go out of business, some of you should try to make a commercial business,\" which didn't really work. Uh, and that's what led down to five. It was actually there was going to be- we were going to go from five to four in '99, the Justice Department put their foot down and said, \"we're not going to let Lockheed and Northrop consolidate.\"","offset":1187,"duration":39},{"text":"Host: Right. And then today, so the changeover, what gave you guys the window, what gave you guys the window to build the business that you've built? I mean, what did you see early on 20 years ago and continued forward in the hardware side that made you say this is- this is the moment. Is it software that enabled this?","offset":1226,"duration":18},{"text":"Trae Stephens: Well, I'm going to throw you under the bus a little bit on this.","offset":1244,"duration":2},{"text":"Shyam Sankar: Okay.","offset":1246,"duration":1},{"text":"Trae Stephens: It was not obvious from the beginning that this was going to work. Um, I can't tell you how many meetings even we had together where we'd walk out and be like, this is not going to work, this is very bad.","offset":1247,"duration":11},{"text":"Shyam Sankar: We were not welcomed with open arms. Right. You know, early days at Palantir. Yeah. Early days, mid-days, maybe late days, you know, famously we had to sue our customer just for the right to compete. Um, that- that's the strength of the monopsony, right? And- and really, I'd say our- entire business was validated from the field backwards, right? It was in DC that- the doors were closed to us, no one wanted to interact with us, they're like- we're- the monopsony's strongest. At the margin, in the field, where people are- are saying like, well, I'm on this deployment, I'm on this rotation, and I- there is more free market system. Like what I'm being given doesn't work, I'd like to come home, how do I like bend the rules, figure out how to get the software I need. That allowed us to empirically show, you know, create facts on the ground, that this stuff worked. It was a long road to hell. I think this is part of why it took 20 years to kind of get to this sort of point here.","offset":1258,"duration":48},{"text":"Trae Stephens: And yeah, I think that a lot of those lessons that were learned were not only like educational for Anduril, but it also created a precedence that already existed by the time that we showed up where we didn't have to go through all of those same growing pains. So, you know, what took Palantir, I guess, probably about five years to get to $10 million annually in revenue, we did that in 22 months. But I don't think that was a credit to Anduril. I think it was mostly a credit to me, Matt, and Brian lived the five years at Palantir.","offset":1306,"duration":26},{"text":"Shyam Sankar: Five years plus 22 months.","offset":1332,"duration":1},{"text":"Trae Stephens: Yeah, exactly. Exactly. And so we kind of had a bit of a cheat code. But I don't think it's like culturally shifted to the point where it's like actually just easy to do this now. It's not like the government has fixed all of their problems. I think it's just that there's enough people out there who have seen it, that understand how to make it work, um, that you can work within the system rather than as Shyam said trying to constantly fight from the outside in.","offset":1333,"duration":23},{"text":"Host: Was there a view at that time in these years building Palantir where you saw an opportunity in hardware? Is that kind of the motivation for Anduril, that we've got software but there's more to do and hardware could be reinvented and we could build systems? I mean, help us understand the connection.","offset":1356,"duration":13},{"text":"Trae Stephens: Yeah, in the very early days, actually, I came by to pitch Shyam um, before we officially started the company. Uh, and I think part of that pitch was we said, uh, we know how hard software is. We don't want to do that again. We believe hardware would be less hard. Um, and I think we ended up being right from like a getting going perspective. Um, but yeah, it's just- you know, the government doesn't know how to think about the value that's created by software. Maybe you feel like they're a little bit better now, but it was really hard in the early days of Palantir to convince them to think about it as anything other than lines of code. For example, or some like metrics that anyone that works in tech knows doesn't matter. But for hardware, they know. There's a bill of materials. Uh, in fact, the government made stuff for a long time. During the Cold War, there were literally ammunition factories that were owned and operated by the United States government. Um, so they can kind of go through a spreadsheet and say, okay, I know how much it costs for you to build this, I know how much margin I am comfortable paying you. Uh, and it's a much easier, you know, crossing of the Rubicon. With software, it never felt like that.","offset":1369,"duration":63},{"text":"Shyam Sankar: Yeah, it's still very hard. I mean, people want to pay for software in government on a cost-plus basis, which doesn't make any sense if you think about the R&D that you put into software. Like the marginal price you're paying is a small fraction of the R&D we're amortizing across commercial and government customers. And I think maybe Trae, it's worth telling the story of how when you got to Founders Fund, you were looking for defense companies to invest in and hitting so many dry holes is- is part of what led to the idea.","offset":1432,"duration":27},{"text":"Trae Stephens: Yeah. Yeah, I mean, I have no- I had, maybe still don't, have any interest in venture capital. Um, and so when Peter asked me to come over to Founders Fund, the only thing I knew to do was just to look at the category of things I felt like I understood pretty well, which was GovTech. And so I, incidentally, you can look up who bids on federal contracts. And so I pulled that list and then at the time I was using Crunchbase and then I just started outbounding to companies that were bidding on federal contracts. And I met with hundreds of companies in the first three years that I was at Founders Fund. We made- ended up making one investment in KDM, which was renamed Expanse and acquired by Palo Alto Networks. Um, but otherwise that was it. There was nothing else. And even like looking in retrospect at- like we didn't miss anything. There was just nothing worth investing in. It turns out no one was building in this category. Um, and so I went back to the Founders Fund investment team and said, man, I feel like someone should be building a next-gen prime that builds hardware but it's software-defined and hardware-enabled rather than being hardware-defined and software-enabled. Um, and- uh to my surprise, the team was like, yeah, sounds like you're probably the guy that would know that that's the gap and I don't know, maybe you should start a company. And I'm like, oh no, you guys hire me to work on the investment team at Founders Fund. Like, yeah, that's fine. You can- you can do that too. It's all good. So, yeah, it was kind of an accidental founding in many ways.","offset":1459,"duration":80},{"text":"Host: The capital requirements for hardware business are notably higher. If you didn't have the success you had building the manufacturing facility you're building and I'm assuming all the R&D cycles are longer and require more capital to get to a point of product. Does it make sense for venture capital to be the funder of the next gen of hardware defense tech companies? How does the economics and the capital markets fit here?","offset":1539,"duration":22},{"text":"Shyam Sankar: Uh, I'll take- take here and then- you. So I think, um, if you back up a little bit, if you look at Fairchild, if you look at integrated circuits in 1968, 96% of all integrated circuits sold were sold to the Apollo program. There was effectively a monopsony. There was one buyer for this thing. But Bob Noyce, who was at Fairchild at the time and co-inventor of the transistor, he was so maniacally committed to a future that semiconductors and integrated circuits would be in everything, that he never let more than 4% of his R&D be paid for by the government. He was going to be- like, why should I have some PM tell me what my R&D roadmap- I invented the thing. So he kept executing that. And that's- he so chased Moore's Law mercilessly. And that meant in the 80s, when the government needed precision-guided munitions for assault breaker to compete against the Soviets, we had the price-performance we needed. Uh, so this idea that- you know, because when you get stuck inside the government loop of what they want, you never hit the price-performance.","offset":1561,"duration":52},{"text":"Trae Stephens: By the way, there's a good modern analogy which is Jensen and NVIDIA, right? '93, graphics chips, sold them as an OE- almost like an OEM type solution and- until here we are.","offset":1613,"duration":9},{"text":"Shyam Sankar: The- the one that speaks to my heart as a child who grew up in the shadow of the space coast is Shuttle. You know, Shuttle is- is beautiful, but it's $50,000 a kilogram to get to orbit. Starship heavy reuse will be under 20 bucks a kilogram. You know, and there's no way that you will achieve that vision if you're in a cost-plus world, because every day you're actually deleting your cost, which means you'd be deleting your profit. Instead of deleting your cost, turning that into margin that you can provide a better price-performance on and keep riding that curve down.","offset":1622,"duration":27},{"text":"Trae Stephens: Right. Although to be fair, SpaceX sued their customer, in the Air Force, on the basis of the exact same federal procurement law um that Palantir did. Um, and so, you know, even with that massive cost- uh costing down, they were in the same position as Palantir was in the early days.","offset":1649,"duration":16},{"text":"Host: Let's go back to the venture capital. At this conference that we're at, there's dozens of VCs now. This has clearly become a hot space as defined by your successes. What's going to happen? So these VCs are plowing money into hundreds of defense tech companies, from drones to satellites to weapons systems to software tools. How does this going to play out over the next couple of years? As a venture investor with your knowledge about Anduril.","offset":1665,"duration":24},{"text":"Trae Stephens: I remember when I first got my offer letter from- from Palantir, um, there- we had this kind of high-low mix of salary versus equity compensation, and it gave three examples of how much your equity at your- that was on your offer would be worth at different valuations. It was I think it was 1, 5, and 10 maybe, or 1, 5, and 20, something like that. And I remember talking to people around the company, they're like, hah, 20? That's ridiculous. We're never going to be worth $20 billion. Um, and- uh you know, I feel like now it's like people are going out and they're like, our seed round will be priced at $20 billion. Um, so I think there's- there's been a big shift in just like the way that people think about these things. Um, some of that is good, some of it's bad. I think on the good side, they're- you know, they're able to look at companies like Palantir, like SpaceX, like Anduril and say there is actually a path to success. This isn't like an impossible market to innovate in. But at the same time, um, you know, there's a real tension around amount of capital raised and the valuations that are being applied to these rounds that- add a tremendous amount of risk to the company that doesn't have to exist. You know, there's this favorite- there's this famous scene from HBO's Silicon Valley where CEO gets fired um for- uh kind of underperformance on the plan that they had presented. Uh, and Richard Hendricks, the main character, says, \"You know you could have raised less at a lower price.\" And he said, \"What do you mean? No one ever told me I could have raised less at a lower price!\" And I think that's ultimately what my advice is to these companies, is like, look, your product might be awesome, seems like you're building a good team, I like the vision for what you're doing in the mission, but you can also raise less at a lower price. And I think that avoids, you know, playing chicken ultimately with trying to hit numbers that frankly don't even make sense. Um, one of the things that we've been focused on at Anduril that I think maps back to our experience at Palantir actually is climbing down the multiples tree uh with every round. We never want to go and raise the next round at a higher revenue multiple than the prior round. Um, and even the Series H that you mentioned before uh is is down pretty significantly from the Series G. And we're not doing that because investors wouldn't be willing to pay higher multiples, we're doing that because I believe the discipline is really, really important especially heading into a- you know, medium-term IPO.","offset":1689,"duration":139},{"text":"Host: Emil Michael talked about this $200 billions of capital he wants to deploy. It's been reported he's hiring bankers to help him deploy it. To counter your point, if there's a lot of capital flowing from the monopsony, if there's a, you know, a big market that's growing aggressively, you've got a $200 billion TAM to go after now. Shouldn't that justify the venture capital coming in, maybe even justify going at a higher price? Is this department of war investment activity really going to kind of change the landscape and increase more venture capital flow?","offset":1828,"duration":29},{"text":"Shyam Sankar: I think it's- it's going to help out tremendously. First of all, I love the nickname that this team has, which is \"Deal Team Six\". So, uh, you know, I'd be honored to be part of that team. Uh, but I think if even if you look back at the titanium supply chain in the 50s, 60s, it was- it was bootstrapped by the Air Force in a similar way where they strategically injected capital down the supply chain to enable the aerospace industry to be created. So I think there's a tremendous opportunity with the Office of Strategic Capital to think about what are the structural bottlenecks in the production. You can have a lot of drone companies, and they're all going to bottleneck on brushless motors. There's going to be certain key parts of the supply chain that we don't have enough capacity to produce here in the US and they're going to need a bolus of investment. And just like integrated circuits, the first customer is going to be less economical than the end customer. So I think that's one part. Then I the other story that I love is where we really screwed this up. The drone is an American birthright. Abe Kareem and the Predator, we- we built it, General Atomics, but of course then the government got in the way. The government said, hey, a drone is a flying missile. This thing needs to be ITAR controlled. Also the FAA got in the way and said, no beyond line-of-sight operations. Right? So you basically killed the domestic drone market. There is a counterfactual world where General Atomics had a commercial subsidiary called DJI, and the consumer drone market was entirely owned by the US and it provided for economic prosperity for America and wrote us down the price production curve that we could be using these things in innovation for national security as well.","offset":1857,"duration":82},{"text":"Host: What's the next market where you're worried that's going to happen?","offset":1939,"duration":2},{"text":"Shyam Sankar: I have a lot of markets. So I mean we- we're talking a lot about, um, weapons of war here. I'm worried about things that go beyond weapons of war that affect our will to fight. Uh, pharmaceuticals is one that's close to my heart. My father was a pharmacist and one of the things he always wanted me to work on was bringing pharmaceutical production back home. 80% of APIs for generic drugs are produced by China. What do you think the American people are going to think when they have to choose between defending the free world, defending American sovereignty, and their five-year-old dying of an ear infection that we would have thought of as trivially cured? And so I think there're these- these things where we've just imbibed the globalist vision that hey, we'll do the innovation, they'll do the production, without realizing that innovation is a consequence of productivity. Probably to put it in terms that the- that the tech community would really understand is like, what motivated Google to do the research in 2017 behind the paper \"Attention is All You Need\"? A desire for a 3% incremental improvement in Google Translate. You can think of nothing more banal leading to something more revolutionary. And we have ceded all of those opportunities to realize and harness that innovation. Now, if we stick with pharmaceuticals, there's a reason 50% of all clinical trials, new clinical trials, are happening in China and not in the US.","offset":1941,"duration":68},{"text":"Host: Do you have a view on a technology or product that's developed in the US that we're at risk of getting regulated out and we're- or are we kind of going on the right direction at this moment?","offset":2009,"duration":9},{"text":"Trae Stephens: I would say that, like, semiconductors is actually a really interesting one back to your- your point about uh Fairchild. Is that, you know, we were the- the home of the semiconductor industry for many, many years. And, um, you know, once TSMC got- got, you know, ahead of- seam in Taiwan, uh they kind of ran away with it. And we didn't, rather than investing in a domestic competitor, uh there are all sorts of reasons for this that we could spend hours talking about. Um, we basically just allowed that to happen somewhere else. And now we're in a position where almost no amount of money is going to fix this problem for us, certainly on a timeline of relevance as it pertains to the risk that Taiwan has, um, in 2027. So I- I would say that's like another really big one.","offset":2018,"duration":39},{"text":"Host: Getting back to defense. How does the hardware and software fit together in this, um, kind of emerging war technology landscape? You guys are building software, you're building hardware, like help us understand a little bit about what the systems of war look like in the decades ahead.","offset":2057,"duration":14},{"text":"Shyam Sankar: Well, I think the- the starting premise would be where does it give us an advantage. And, uh, you know, we had the first offset which was nuclear weapons, the second offset, precision-guided munitions and stealth. Really the third offset is decision advantage. How can we outthink and out-execute the adversary. That's where these things fit together. That's like the thesis of even having them to begin with. And I think the reality is that there's kind of a messy overlap of these things. Like all innovation is messy and chaotic and maybe the department suffers at times because it tries to have a- a framework based approach. Like we're going to have MOSA, modular open standards architecture, something like that. You know, it's like we're going to avoid all of the pain and messiness by having some sort of process. But in reality, the process always destroys all of the innovation. And so there- there's obviously a very tight thesis where these things need to coexist and build off one- one another. They need to be interoperable. But you have to earn that. You have to earn that opinion in the exercises and the tests and the evaluation and combat would be my- my humble suggestion.","offset":2071,"duration":60},{"text":"Host: Do you think that outside of what Anduril's building, there's actions that this administration should be taking or that the private market should be taking to solve this hardware manufacturing and capacity gap that we have right now?","offset":2131,"duration":16},{"text":"Shyam Sankar: My view is they're actually taking a lot of actions. Not all of them have come to see the day of light here, but, you know, even something as simple as reimagining munitions and drones as consumables. They're not things that you build and then stock on a shelf. They're things that you- at the time of ordering them, you already have an exercise test plan where you plan to expend them. Which means that you're going to have to replenish them, which means there's a demand signal to industry to keep going. and- in a buying cycle that means that you can buy the next generation rather than having the old generation. Uh, and I think this department sees that in a very clear-eyed way and is doing the yeoman's work of like stitching that through through all the services, all the portfolio acquisition executives. To the point of not believing in process, they've moved from a world where you have a very rigid, \"hey, I said I was going to buy X of Y and I can't change my mind,\" to a world where there's more autonomy and authority for the people who are buying things to say, \"I told you I was going to buy something that accomplished this goal. I can change my mind about how I'm going to accomplish this goal.\" Which, you know, can you imagine trying to run any private sector business without that degree of autonomy and- and flexibility in your decision-making.","offset":2147,"duration":62},{"text":"Trae Stephens: To echo Shyam's point about what the administration is doing, there are a bunch of swings that they're taking. It- it wasn't that long ago that, uh, in the Obama administration there was kind of the Solyndra failure where they invested in this solar panel company and it ended up being a bad investment for the US taxpayer. Um, but now the Office of Strategic Capital is taking a really hard look at critical minerals. They're looking at, you know, refining of- of minerals. And- uh they're engaging directly with the private sector to come alongside them in doing deals to get offtake agreements on these things. So, uh, I think there is some really clever thinking going on. Um, and then in addition to that, I think the procurement process is sort of up for revision constantly. Um, and Ash Carter started pulling a lot of these threads during the Obama administration. That was the third offset initiative. Um, but, you know, we're in a- in a world today where there's kind of a renewed vigor around being asked- private industry being asked, \"What do you need? Like tell us what you need to be changed about the way that we do business in order to streamline this and make it go faster.\" So I think there's a lot of positive momentum.","offset":2209,"duration":60},{"text":"Host: Do you guys think these changes have been institutionalized or are they political party dependent? If the Republicans lose the midterms and there's a Democrat president in 2028, do you think that there's a reversion to the old way of operating that's going to have some political influence and change things, or do you think we've really changed how things are running in the government here?","offset":2269,"duration":22},{"text":"Trae Stephens: I don't think it's political, but I think it's people. So you can go back to, again, Ash Carter, Democratic administration, highly focused on fixing these problems. The current Trump administration highly focused on fixing these problems. And, you know, there are a lot of people that live in- that were in the middle of that that didn't prioritize this, it wasn't- it didn't rise to the top of the stack. And so I think we always think of like the bureaucracy as being a political infrastructure or an institution or, you know, a bureaucracy. I actually just think at the end of the day it's about leadership. It's just do we have the right people that understand the set of the problems that we're- we're facing.","offset":2291,"duration":37},{"text":"Shyam Sankar: I couldn't agree more. I mean, I- I call them \"heretics and heroes\". Like, you- you know, the entropy of the bureaucracy is always towards some sort of sclerosis, it doesn't- it's not a political statement, it just is what bureaucracy does. When David Packard, who is probably the last major technology co-founder who served in the Department of Defense, when he came up with the 5000 series on acquisition, which today we view as just sclerotic BS that's- that's tied us down. Well, he- his document was seven pages long. In the- in the years between when he wrote that and now, it's 2,000 pages. So did he really screw us or did just the entropy take hold? And there was no strong leadership in between to go do the bush-whacking and mow the lawn and- and make the right decisions. Now, you know, this- this administration's blown up JCIDS, which is kind of- one of these insane bureaucratic processes, like can you just take a- forget a scalpel, take a machete and start clearing the jungle and re-earn some of these lessons as you go through it. If you look at Kelly Johnson, who was the founder of Skunk Works, he built 41 airframes in his career, including the SR-71, still the fastest flying manned aircraft, and- the U-2, which we still fly. Like one of- you look at his rules, one of his rules was he had to play defense to keep the government bureaucrats out of his program. And I think you could, okay, it's not a critique of government. You can think of big corporations. When the big corporations' bureaucracy gets into the innovation folks, the innovation stops.","offset":2328,"duration":77},{"text":"Trae Stephens: And the heretics and heroes were really founders. They were founders. It's like from a tech perspective, that's exactly what they were. And like to the Kelly Johnson point, the U-2 did not start as a US military aircraft, because they didn't want it. Uh, he ended up going through the intelligence community to get his start there, uh, and in- it was kind of finding the right person that was willing to take the risk to do the thing rather than relying on the system or the institution to do that. This is the same with Bennie Schriever with ICBMs, Admiral Rickover with the nuclear Navy. Um, it used to be about people. But today, if you were to go to the Pentagon and say, \"Who's responsible for the F-35?\" I'm not sure they even know. Who is responsible for the F-35? We're- we're building systems by- by committee rather than trusting founders and people who want to build them.","offset":2405,"duration":45},{"text":"Host: Yeah, I mean, there's- there's like a proclamation, \"it's so great, it's this X, Y, or Z project is built in all 50 states.\" Like the objective is- it's being- the money's being spread around versus how do you achieve the objective.","offset":2450,"duration":12},{"text":"Trae Stephens: The F-35 has components manufactured in 400 congressional districts. Right. I mean, that's like- that's a political project.","offset":2462,"duration":8},{"text":"Host: We had this A/B test with SLS and Starship, right? Like SLS had to have subs in all 50 states. But this A/B test has been played out.","offset":2470,"duration":6},{"text":"Shyam Sankar: I do think there's something about the kind of Calvinist spirit of America that sometimes gets us to misunderstand. You know, we call it the Apollo program, but it was probably- it's really the James Webb program. You know, uh, it's the F-16, but it's really John Boyd's plane. And and there's like a humility where we'd never want to call it, you know, it- you wouldn't call it, although I maybe the nuclear Navy we kind of do call it Rickover's Navy. But there's an element of like it's obviously both things. It's bigger than the person, but actually the starting conditions require the founder figure.","offset":2476,"duration":28},{"text":"Host: So tell me about where we are in the state of readiness. You know, we highlighted some of the statistics. But if you guys were to think about what we need to accomplish, the infrastructure we need to stand up to have production lines that can be turned on to support munitions capacity for conflict in, you know, pick your region, let's say more than one region around the world, and the US needs to sustain those conflicts to defend the United States. How far are we from being ready based on what's going on in the investments that are being made today across the sector?","offset":2504,"duration":31},{"text":"Shyam Sankar: I think the- the way I think about it is if you thought about this as a spear, the tip of the spear is incredibly sharp. The shaft of the spear needs a lot of work here. Um, you know, the Department of Defense is such a- big organization, it- it's structurally supply and demand is not integrated. You know, the demand side is the real-world events that happen at the combatant commands. The- the supply side are what the services and the industrial base build, demand, train, and equip, and how you're actually producing that material. And the ability to drive consensus, which is really the beating heart of any private sector company, of like how do supply and demand come together, what's our view of it, is kind of managed with- with great difficulty in the Pentagon. And your ability, your agility to respond to scenarios is- is weak. That's- that's where we can have a lot more precision, because if you can start changing your mind and saying, \"Actually, I thought I needed X Barracudas, but now I need Y Barracudas and Z Furies,\" how quickly does that take to percolate through the supply base? You know, instead we get locked into these like, \"Hey, we've made a decision. The decision really can't be revisited.\" Uh, and then you start over time the entropy is like, \"Hey, let- I need- I have an unexpected bill. Let's just take a little bit of money away from these programs,\" and everything starts getting down to minimum rate production, which is this idea of what can I produce to just keep the line open, which is not deterrence. That's how we've frog-boiled our way here. And this is where my- my idea of like you've got to tie this into consumption. Like everything you're building, particularly on the munition side, needs to be consumable such that you know you're going to replenish it, such that the primes and the neo-primes all have the demand signal they need to keep going and have a reason to produce them cheaper in order to make more money. My most contrarian idea is like- the cynical view that like you have the military-industrial complex and they're just in it to make money, well it- it's kind of a crappy business. Like, you know, these companies trade at like less than two times revenue. The problem is it's not profitable enough, actually.","offset":2535,"duration":111},{"text":"Host: But Trae, Shyam said in the past we have eight days of munitions on hand for a major conflict with China versus 800 days needed. How far away do you think we are to having the supply chain built and the production capacity built to meet that objective?","offset":2646,"duration":16},{"text":"Trae Stephens: Well, I mean one of the other things Shyam just said in this conversation is that there's a high-low mix question as well. Like there are exquisite systems that are like the multi-million dollar interceptor missiles, and then you have, you know, dumb munitions, things- like bombs that are being dropped and things like that. And it's not the same across that entire stack. You know, there are some- some munitions that are woefully undersupplied and we have very low readiness on, and there are others where I actually feel pretty good. Um, from an Anduril perspective, you know, we're looking at ramping as fast as we can. We just opened Arsenal yesterday uh to start producing Furies. Um, and, you know, looking out over the next 18 months, we're not taking our- our foot off the gas. And yet, there's a lot of work to do.","offset":2662,"duration":38},{"text":"Trae: There's still a run rate capacity that we're running into as we ramp. Like, it just takes time to get all these lines stood up. Um, so you know, if we were to start today with unlimited cash, I think over the next 18 months as a country, we could get to the point where we were on track for having a sustainable industrial base.","offset":2700,"duration":22},{"text":"Trae: But we're not going to do that. We're going to trickle it out over time and, uh, and I think that unless there's real political leadership that steps up to drive this forward, we will likely be in a similar situation for a long time. Um, and so I think we really need to take advantage of this specific moment where there's clearly urgency that is understood by leadership across the administration.","offset":2722,"duration":21},{"text":"Host: How much of the spear is autonomous systems? Is everything going autonomous? Is it just drones or is there on the ground autonomous right now?","offset":2743,"duration":8},{"text":"Trae: Well, I would actually argue that like, the wars of today are fought with the weapons of yesterday. That's like, just a fundamental truth. And some of our weapons of yesterday are awesome. Like, B2s are incredible. Uh, the bombs that we dropped last summer in Iran, incredible. Like, these are very high-tech, exquisite systems.","offset":2751,"duration":22},{"text":"Trae: Patriot missiles, incredible. They're very performant. Uh, they hit their targets almost every time. I mean, these are great systems. The problem is is that they're incredibly expensive and we can't resupply. Like, we're just, we're way behind the eight ball on that. And so, uh, you know, thinking about the wars of the future, it means that we need to start building these attritable mass systems today so that they're in inventory to be used for those conflicts.","offset":2773,"duration":23},{"text":"Trae: There are a number of Anduril systems that are at a readiness level, at a level of deployment that they're active and being used in combat today, but it's still a very small percentage of the way that the wars are being waged. Um, over, you know, the next five to ten years, that high-low mix is going to have to shift massively. I mean, this is just like, clearly evident in Ukraine, it's clearly evident in Iran.","offset":2796,"duration":24},{"text":"Trae: Uh, and I think the Department is making steps to ensuring that they have, uh, a better divide of low-cost attritable systems and those high-cost exquisite systems. Um, but uh, you know, as I said, it's going to take political leadership to get there. Uh, but we, we have the ability to do it.","offset":2820,"duration":14},{"text":"Host: The reason I ask is I want to talk a little bit about the ethics of technology to war, the Anthropic run-in with the Department of War recently. And I think you guys have both talked publicly about this. But Anthropic refused to let its Claude model be used in Maven without human oversight constraints, this is what's been reported, what Emil Michael has said.","offset":2834,"duration":21},{"text":"Host: And the Pentagon labeled them a supply chain risk. Both AI and generally autonomous systems beg the question, what role should humans have and who should have the right to play that role of hitting the kill switch? What's your view on the role of the technology vendor to the Department of War and where you guys draw your line on what your responsibilities are with respect to ethics?","offset":2855,"duration":21},{"text":"Shyam: Well, my, my view on my responsibility to ethics is a slightly different question than my belief in democracy, which is a different thing. Um, so maybe starting on the democracy point, um, I believe that the people of America have elected representatives to make really hard decisions about how we engage in combat. Full stop.","offset":2876,"duration":19},{"text":"Shyam: Um, fully autonomous weapons are not new. We've had autonomous systems in operation like CIWS, which is deployed on, uh, naval vessels that shoot down aerial threats fully autonomously. You don't have time to make decisions about, you know, incoming missiles or threats to your ship, you just have to shoot it down. So that's what CIWS does.","offset":2895,"duration":18},{"text":"Shyam: Now, CIWS has accountability in the system. There's a person on that boat that is responsible for whatever actions that weapon system takes. And I believe that this is the future of autonomous systems is that, just like any other system, whether it's a soldier carrying a gun, they are accountable for what happens with that gun, or, uh, you know, the captain of a naval vessel, they are responsible for what happens with that CIWS.","offset":2913,"duration":21},{"text":"Shyam: All of your autonomous systems are going to have accountability baked in. Now, ethically, how do I think about this? You know, I believe that, you know, what Shyam was saying about the first offset, the second offset, and the third offset, um, is you know, we have, we, as a society, went from like rocks and sticks to, you know, knives to guns to bombs and then in World War II we kind of plateaued with nuclear weapons.","offset":2934,"duration":25},{"text":"Shyam: And we all looked around at each other and we said, \"Wow, that's pretty crazy. I don't think we want to make more and more powerful nuclear weapons forever.\" And so actually our engagement in combat has come back down the chain. Uh, we're doing precision-guided weapons, we're shooting non-explosive missiles into windows of apartment buildings, avoiding casualties, unintended casualties.","offset":2959,"duration":21},{"text":"Shyam: And I think that's really the goal. And if you look at AI as the command center for making better decisions with better precision, with better discrimination, with, uh, less the less civilian casualties, this is good. It's actually ethically far improved from just dropping dumb bombs on areas of cities to eliminate military facilities. So, uh, I don't think abstention from participating in the building of technology for national security is a morally neutral decision.","offset":2980,"duration":27},{"text":"Shyam: You are making a moral decision when you decide to abstain. And I am making a moral decision as a private citizen building a company in this space that I believe that this is ethically just, and uh, I trust in our democracy to deploy those tools with the interest of the American people at heart.","offset":3007,"duration":16},{"text":"Host: There's a lot that's said about Palantir enabling a surveillance state. We had the All-In Summit in September, Alex Karp, your CEO, spoke, and there was a protest group outside protesting Palantir powering a surveillance state. I just want to give you a chance to respond to that, number one.","offset":3023,"duration":18},{"text":"Host: And number two, if you saw that Palantir's tools were being used in an illegal way, where's the responsibility for Palantir as a technology vendor in addressing those concerns?","offset":3041,"duration":9},{"text":"Shyam: It's almost hard to respond to because it's very unclear what surveillance people think we're doing. You know, there's just like a broad, almost maybe an outgrowth of Terminator fear around technology.","offset":3050,"duration":10},{"text":"Host: And I want to get into that cultural question next. I think it's very important to understand.","offset":3060,"duration":4},{"text":"Shyam: We don't collect data, we don't have any data. It'd be like, it'd be like accusing Excel of being a surveillance tool, right? It's like, this is a way of bringing your own data that you have lawful authorities to collect together to make decisions. Sounds a lot like Excel. Um, but it's, you know, because we are unabashedly patriotic and serve the US military, I think people have a kind of colored view of these things.","offset":3064,"duration":22},{"text":"Shyam: I would argue that it's actually Excel with cell-by-cell security with way more security, way more accountability. You know, it'd be as Karp says, it's the most insane platform in the world to try to do something illegal in because you are going to be caught. You know, like, that was part of the idea of how do you enhance privacy and security? It's how do you build more civil liberties protections in?","offset":3086,"duration":22},{"text":"Shyam: How do you have a normative view that enables a democracy to say, \"These are our laws and rules, the system will enforce it,\" we're not just relying on people happening to do the correct thing. Uh, so that's one piece of it. The other piece of it to come back to this broader point is the need for epistemic humility. Like, one of the, to the point of we have elected officials, they are accountable for these policy decisions.","offset":3108,"duration":21},{"text":"Shyam: I think at the limit, it's actually kind of indefensible to have a perspective other than lawful use, because if you are salami-slicing the policy, that's actually tyranny by tech bro. You know, a small number of people are constraining the maneuver space of a democracy with no accountability to the populace. So, I think that's a pretty challenging perspective to be in.","offset":3129,"duration":20},{"text":"Shyam: And we've been in this perspective before, if you go back to how did the Soviets get the nuclear bomb? You know, there was really, there were two sources of treason. One was committed communists like Klaus Fuchs who was always a spy. But the other were people like Theodore Hall. He was one of the youngest scientists in the Manhattan Project at 18 years old. Uh, his brother Edward Hall built the Minuteman missile. His brother was, you know, kind of a heretic and hero in my terms.","offset":3149,"duration":21},{"text":"Shyam: But Theodore said, \"You know, I'm one of the best physicists in the world, I'm probably also one of the best geopolitical strategists in the world. And I think the only way to have world peace is if two countries have the bomb.\" So in 1944 Theodore Hall walked into the Soviet trade mission in New York and gave them critical secrets to the bomb. Now, Theodore thought he was going to deliver world peace. Instead, every death from communism since 1949 is actually on his hands. And there's no accountability for that.","offset":3170,"duration":26},{"text":"Trae: Yeah, I think one of the other things that comes up in these, uh, these conversations about powering the surveillance state is this belief that we have policies, but we don't actually want our civil servants to have the best technology to enforce those policies. And it's almost like a lack of belief in the institution of democracy.","offset":3196,"duration":19},{"text":"Trae: It's like, you know, traffic cameras for example. It's like, man, I'm sort of libertarian in some ways, I don't love traffic cameras, but if traffic cameras say, \"I'm going to send a ticket to every single person that blows through this red light,\" I don't know, maybe we have to change the policy around red lights if you don't like that.","offset":3215,"duration":14},{"text":"Host: I've gotten three speeding tickets in San Francisco from autonomous cameras in the last month.","offset":3229,"duration":5},{"text":"Trae: Well, they did ramp it up significantly, which is incredible that they're enforcing laws at all, if we're being honest.","offset":3234,"duration":5},{"text":"Host: I mean, like, here's my ticket, and then I'm literally watching the guy while I'm doing three miles over the speed limit, you know, take heroin needles out of his arms and put it on the floor next to an elementary school. And I'm like, \"Probably fine, yeah.\"","offset":3239,"duration":12},{"text":"Trae: That's our problem. But it's the same thing with like, you know, using tech for better enforcement of tax law or something like that. Like, do you, is what we're saying by criticizing what Palantir's doing, is what we're saying that we don't want our civil servants to have the best tools possible? Because you can have that position. I tend to think that that position is pretty morally bankrupt, but I guess you could have that position, but ultimately I think that's what it is.","offset":3251,"duration":34},{"text":"Host: Scenario play this for me, because there's a public perception, I don't know how far-reaching it is, that there's some tied corruption between government officials that use technology that's super advanced, that's hard for people to understand, and the technology vendors. If you saw government agencies using your technology, either of you, in an illegal way that you knew broke the law, do you report it?","offset":3285,"duration":19},{"text":"Shyam: 100%.","offset":3304,"duration":0},{"text":"Trae: Yeah, to the IG. There's an entire mechanism for that, absolutely.","offset":3304,"duration":3},{"text":"Host: Right, so can just, just explain that for a second. The Inspector General, maybe?","offset":3307,"duration":5},{"text":"Shyam: Yeah, so every agency has an Inspector General who's an independent organization that you can provide anonymous or non-anonymous complaints to that then have the ability, the statutory ability to do an investigation in an unfettered way inside of that organization, whether it's the Department of War or, uh, Housing and Urban Development, like literally every single agency.","offset":3312,"duration":21},{"text":"Shyam: Uh, and this mechanism is used. I actually, you know, in this case it was weaponized against one of my favorite heretics and heroes, Colonel Drew Cukor, who invented Maven, the founder of Maven really, but you know, people would file complaints claiming that he was uh hiding illegal immigrants in his basement, a basement that he doesn't really have. You know, but but all of those things were investigated, Naval Criminal Investigative Services went out to his house and actually looked into these things. So people take this incredibly seriously.","offset":3333,"duration":24},{"text":"Host: Where does the culture come from? The anti-defense tech alignment culture? Is it because of the peace era that we had and folks took for granted national security?","offset":3357,"duration":10},{"text":"Shyam: I think the first schism was really during Vietnam where people felt like, uh, they were lied to about the war. It it drove a fundamental schism between academia and defense. And that we've never really healed from that schism. And so there's this this kind of sense, this distrust that's brewed there and kind of escalates through society.","offset":3367,"duration":21},{"text":"Shyam: The second schism is like the number of people who are prior service or are connected to this community who actually see these people as humans and have a fully informed mental model of how diligent they are, how the work actually gets done, what do these words actually mean, what is the process like, has evaporated.","offset":3388,"duration":18},{"text":"Shyam: So then their own fears fill how they think it happens and it seems like maybe it's happening more in a cowboy way, maybe it's happening in a way without oversight, that there is no such thing as doctrine. Like it's kind of a cartoon version of what's actually happening that I think you're unable to reconcile.","offset":3406,"duration":15},{"text":"Trae: Yeah, I think if you even look back at what happened with Snowden, uh, you know, what was that, 15 years ago now? Something like that. Uh, you know, that there was almost no discussion about the investigations that went into like, was the data collection actually abuse? And the answer is like, basically not at all.","offset":3421,"duration":18},{"text":"Trae: There were like less than 12 documented cases where someone got access to data that they shouldn't have, and it was because of like technology errors, not because of the policies that were implemented. Um, and so we can have disagreements about whether or not the intelligence community should have collected the data and stored it, uh, but that was that policy was renewed multiple times by multiple administrations, multiple political parties that had the majority in Congress over decades.","offset":3439,"duration":30},{"text":"Trae: And so apparently our elected representatives thought that it was important enough to keep in the system. Um, so I think it ends up being this kind of weird policy discussion. Uh, but the second point that you make I completely agree with about like the kind of distrust of the institution in creating the stories for themselves.","offset":3469,"duration":16},{"text":"Trae: I often times go and do guest lectures at Stanford and I always try to ask, like, raise your hand if you have an immediate family member that serves in the military. No one ever raises their hand. It's crazy. Like at Stanford, there are veterans that come in that go to the GSB and things like that, but in like the undergraduate undergraduate student population, it's incredibly rare for anyone to have any connection whatsoever in their immediate family to the military.","offset":3485,"duration":29},{"text":"Trae: And I think there's like, you know, some of this goes back to criticisms that people like JD Vance, uh, the Vice President, has made about, you know, elites in America and things like that, but there's just this incredible divide that has happened. Um, and we're kind of losing touch with that kind of salt of the earth, middle of the country, you know, veteran community that I feel like was way more present during the the Cold War, uh, and and you know the World War II before that.","offset":3514,"duration":21},{"text":"Host: Do you think that there's any external influence that's driving this culture? Are there influences on social media, in mainstream media? And maybe just talk about destabilization and the attack vectors. I've seen it in other areas of science. I don't want to spend time on this show talking about it, but there have been traces that I've found on external folks that want to destabilize American science and industry progress, and they create fear and they put out articles and then they go social and they they become viral and suddenly everyone believes it even though it's not true. Do you see that and have you actually kind of seen that in the sense of like attacking the the tech companies that are now supporting American defense?","offset":3535,"duration":39},{"text":"Shyam: 100%. Even if you go back to, let's stick with Vietnam, uh, the Soviets spent seven billion dollars in 2026 dollars funding the peace movement, the anti-war protests. Now, there's obviously some there is an organic element to it, but this is just dumping gasoline on the fire to sow division and discord. Uh, and I think in the present day I I think, you know, certainly we see it against Palantir where there's CCP money flowing to organizations that are protesting us for various domestic issues here. It's not isolated. It's broadly a successful strategy for our adversaries to sow division.","offset":3574,"duration":34},{"text":"Host: No one will believe it because no one wants to believe that they're being influenced.","offset":3608,"duration":3},{"text":"Trae: Right, but I I think Shyam's point is exactly right, it's like, it's actually a brilliant strategy. Like, good for them. They are they are not our friends, they're our adversaries. What would you do if you were in their shoes? It makes a ton of sense.","offset":3611,"duration":12},{"text":"Host: Do we do that?","offset":3623,"duration":1},{"text":"Shyam: I mean, look, we have all sorts of counter-intelligence operations operating. The modern art movement was really funded by the CIA to undermine the kind of Soviet control of art. You know, and it was it was broadly funded and it wasn't it wasn't directed by CIA, but you you can see how we have cultural values that we want to inculcate and spread.","offset":3624,"duration":20},{"text":"Host: Do you think we have a shot at recasting the defense industry, the tech industry that's addressing defense, and aligning it with a notion of patriotism? And what is it going to take to make that happen?","offset":3644,"duration":12},{"text":"Shyam: I don't know, maybe writing a book called \"The Mobilized\"?","offset":3656,"duration":4},{"text":"Host: Oh yeah, you have a book! That's right. That's right.","offset":3660,"duration":2},{"text":"Shyam: I'm trying to do exactly that. You know, look, if if we look at it clear-eyed sense of the world and how much deterrence we've lost, you know, you could you could really say like maybe World War III's already started and 10 years from now we'll look back and and be able to perceive that, right?","offset":3662,"duration":13},{"text":"Shyam: And I I think you don't need literally everyone to view this, but if you can if you can create a more clear-eyed view of what's at stake here not only for you but for your children and their future, I I think you can you can get people to show up and participate. And this is this has been America's story all the time, you know, and usually when we start these things we are the underdog.","offset":3675,"duration":17},{"text":"Shyam: All periods of American greatness have started when we realize that we're the underdog. We were the 17th largest army in the world at the beginning of World War II. You know, and what did a ragtag bunch of farmers and random tradesmen have taking on the world's largest army in the British during the Revolutionary War?","offset":3692,"duration":20},{"text":"Shyam: You know, and I I think um having some clarity about what's at stake, what the counterfactual is. It's so easy when you're successful to kind of let the nihilism grow and say like, look how imperfect we are. This like the self-loathing creeps in. And this is where I take coming back to your point on the legitimacy of our institutions, like should these institutions work, do they deserve the best software?","offset":3712,"duration":19},{"text":"Shyam: I mean, look, if they're public or private, you can't have doors falling off planes, you know, our government organizations need to provide the basic services they've signed up to do without fraud, without corruption in an efficient way. And the reason is not just an aesthetic, it's like in the absence of that, it breeds nihilism. And the younger generations look at that and say, \"You know, we should just tear all of this down.\" And things will absolutely get worse in a world that looks like that. So it's incumbent on us to wake up every day and fight for the legitimacy of these institutions, to make them more functional.","offset":3731,"duration":26},{"text":"Host: America's story's never written, it's every chapter seems to be a whole new arc. And we're in one right now. There's a rising socialist movement in the United States. Can you guys just comment on how much you think that that socialist movement, cast with whatever term they want to use, is going to affect our capacity for defense and resiliency going into the next decade, particularly as our adversaries are rising?","offset":3757,"duration":25},{"text":"Shyam: Well, the argument I've always made is I think our greatest threat as a nation is not homicide, it's suicide. And it's it's in this vein, it's the internal discord, it's the division, it's the the self-loathing, it's um things like the socialist movement, which I think are symptomatic of this internal discord and ensuring opportunity for our people.","offset":3782,"duration":20},{"text":"Shyam: To the point of a functioning elite, if you were to go backwards and think about the root cause, like maybe we don't have an elite that cares enough about the prosperity of the American people. And we've made decisions through globalization, we were told NAFTA was going to be a great thing, that actually if you lost your job in manufacturing, why don't you just learn how to code?","offset":3802,"duration":19},{"text":"Shyam: You know, there there's a certain sort of callousness in that. And, you know, I'm not an unabashed free market and I'm clearly not a communist, but there's a sense of where the decision on the margin actually really does matter and that comes down to leadership.","offset":3821,"duration":9},{"text":"Trae: I think one thing that makes me a little hopeful is that socialism literally doesn't work. Um, and so you know you look at you know what happened in San Francisco even where, you know, we elect Chesa Boudin as the district attorney and then we're like, \"Oh wow, this is not going well, recall him.\"","offset":3830,"duration":16},{"text":"Host: Rooted in a selling point of empathy, right? Fundamentally.","offset":3846,"duration":2},{"text":"Trae: Yeah, exactly. Yeah. Uh, you know, what happened with the Board of Education getting recalled, you know, Daniel Lurie coming in as the mayor, uh, you know, we felt like we kind of went into this valley and sort of hit rock bottom, um, but I do think that people eventually realize that it doesn't it just fundamentally doesn't work.","offset":3848,"duration":18},{"text":"Host: Seattle and Washington state are likely going to lose a large number of their biggest employers. And as that happens, they'll come through on the other side, probably might take them 7 to 10 years to get there.","offset":3866,"duration":10},{"text":"Trae: Yeah, it might be painful and it might take them a long time, but I think they'll eventually come to their senses.","offset":3876,"duration":5},{"text":"Host: What do you two disagree on?","offset":3881,"duration":3},{"text":"Trae: That's a great question. Yeah. Um, we actually, I'll be honest, we bickered with each other quite a bit at Palantir. Um, and usually it was Shyam being right about something and me taking a long time to come come along to his point of view. Uh, but uh, yeah, I think, you know, any of these cultures that are like well-functioning are rooted in debate, um, and eventually—","offset":3884,"duration":20},{"text":"Host: But you're avoiding my question. Whether it's actions or outlooks. Whether you should show up to your interview at a tech company in a suit.","offset":3904,"duration":10},{"text":"Trae: I know. Well, no, I will say this, because it actually is part of the story of Anduril. I thought that it was a bad decision at Palantir to be as quiet as we were. I thought that we needed to get out there and tell the story so that there would be data that says things like what Shyam said about like we don't have any data, we are Excel.","offset":3914,"duration":22},{"text":"Trae: Um, and we had a very kind of quiet, reserved comms strategy. Um, and we went back and forth on that a lot. And uh when I started Anduril, I was like, you know, all the positive things we learned about uh doing business with the government from Palantir, the one lesson that I learned that we didn't implement at Palantir is we're going to go out there and tell our story. Um, and I think that's worked for us incredibly well, and I'll be honest, I think Palantir has come along to my my side of of that debate.","offset":3936,"duration":22},{"text":"Host: And last question, if we don't do things right, what does 2040 look like? And if we do do things right, what does 2040 look like? Economic and defense.","offset":3958,"duration":9},{"text":"Shyam: Well, the the economic part is I think the critical one because national security is not an end unto itself, it's a means to an end and that that end is economic prosperity, the prosperity of the American people. Uh, you know, I think no country has done more to develop the world, like how did integrated circuits and microelectronics get to Southeast Asia? We sent them there.","offset":3967,"duration":19},{"text":"Shyam: Yeah, we benefited in terms of trade there, but you know, like which other winner in a war spent their own capital to rebuild the conquered, in Japan and Germany? And and now you have this stability as a result of it. So when I think about what could go wrong is you actually have a Chinese century that we never recover from, that literally everyone in the world is a vassal state to China and might makes right in their sort of world.","offset":3986,"duration":24},{"text":"Shyam: You know, and we shouldn't forget is like it's very clear even in the present moment that for the CCP it's not enough for China to prosper, America must fall. That's an explicit part of the strategy. Look, it is a business decision if you want to buy American or Brazilian soybeans. I actually don't begrudge you one iota which decision you make there.","offset":4010,"duration":15},{"text":"Shyam: It's an entirely different decision when you're smuggling agricultural funguses into the US so that we can't grow soybeans. That's the sort of zero-sum frame that I think 2040 will look like if we get this wrong. And if we get it right, I think what we actually see is a massive re-industrialization of America followed by the West.","offset":4025,"duration":15},{"text":"Shyam: Um, we see a thriving middle class, which I define qualitatively as a middle class that believes their children's future will be better than their future, which is something that I feel is a fundamental promise that's broken down over the last 30 years or so. Uh, and a belief in our institutions once again.","offset":4040,"duration":15},{"text":"Trae: Yeah, no, completely agree with all those points. Uh, I think there's a big component here around education that we haven't talked about as well where we figured out a way to educate and successfully enter our young people into a marketplace that uh needs them and that benefits from their services.","offset":4055,"duration":16},{"text":"Trae: Um, and I think that we haven't quite nailed that. Um, but I do think that the re-industrialization point of this is going to be kind of the central point of uh making sure that China's many, many decade belt and road strategy is not going to put us in a position where we literally just can't do anything.","offset":4071,"duration":17},{"text":"Host: Do we need military and industrial primacy or can we operate in a multipolar world where the US can share influence and economic prosperity with China, perhaps Russia, perhaps one or two other nation-states?","offset":4088,"duration":16},{"text":"Trae: Well, the challenge with not being the leader is that you don't get to set the terms of engagement. And so I think the benefit that we have had uh since really the end of World War II is that we've had the primary seat at the table to say this is how we're going to do uh, you know, semiconductors, this is how we're going to do supply chain, this is how we're going to protect trade lanes. And I think the moment that you step back from that, uh, and someone else has all those incentives, uh, you start playing the rules of their game, and it doesn't stay multipolar for long.","offset":4104,"duration":28},{"text":"Host: Well, I really appreciate the two of you being here, Trae, Shyam, thank you guys, this has been great.","offset":4132,"duration":4},{"text":"Trae: Thank you.","offset":4136,"duration":0},{"text":"Shyam: Thank you, guys.","offset":4136,"duration":15}],"logs":[{"elapsed":"0.0","message":"Downloading audio from YouTube...","detail":null},{"elapsed":"0.0","message":"Trying download with browser cookies (ad-free)...","detail":null},{"elapsed":"2.5","message":"⚠ Cookie download failed: WARNING: [youtube] [jsc] Error solving n challenge request using \"deno\" provider: Error running deno process (returncode: 1): \u001b[0m\u001b[1m\u001b[31merror\u001b[0m: Uncaught (in promise) TypeError: Cannot read prope","detail":null},{"elapsed":"2.5","message":"Retrying without cookies...","detail":null},{"elapsed":"36.6","message":"⚠ Downloaded without cookies — audio may contain ads","detail":null},{"elapsed":"36.6","message":"Audio downloaded (46.3 MB) in 36.6s","detail":"File size: 46.3 MB"},{"elapsed":"36.6","message":"Video title: The State of Modern War: Palantir & Anduril Execs on Drones, AI, and the End of Traditional Warfare","detail":null},{"elapsed":"36.6","message":"Audio duration: 1:09:21 (69.3 min)","detail":null},{"elapsed":"36.6","message":"Large audio (69.3 min) — will use chunked transcription with gemini-3-flash-preview","detail":null},{"elapsed":"36.6","message":"Skipping full-file attempt — using chunked transcription for 69.3 min audio","detail":null},{"elapsed":"37.1","message":"Split audio into 2 chunks for transcription","detail":null},{"elapsed":"37.1","message":"Transcribing chunk 1/2 (starts at 0:00)...","detail":null},{"elapsed":"37.1","message":"Uploading audio to Gemini File API...","detail":null},{"elapsed":"42.2","message":"Audio uploaded in 5.1s","detail":"File ref: files/wtuods7e75ub"},{"elapsed":"42.2","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"109.1","message":"Chunk 1: 78 segments, last timestamp 44:22","detail":null},{"elapsed":"109.1","message":"Transcribing chunk 2/2 (starts at 45:00)...","detail":null},{"elapsed":"109.1","message":"Uploading audio (offset 45:00) to Gemini File API...","detail":null},{"elapsed":"112.5","message":"Audio uploaded in 3.4s","detail":"File ref: files/lpnph8rn2n3u"},{"elapsed":"112.5","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"150.7","message":"Chunk 2: 88 segments, last timestamp 1:08:56","detail":null},{"elapsed":"150.7","message":"Chunked transcription complete: 166 total segments","detail":null},{"elapsed":"150.7","message":"Total cost: 104,554 in / 19,747 out — cost: $0.1115","detail":null},{"elapsed":"150.7","message":"Total transcription time: 114.0s — 166 segments","detail":null},{"elapsed":"150.7","message":"Analyzing topics across 166 segments with gemini-3.1-pro-preview...","detail":null},{"elapsed":"214.9","message":"Topic analysis complete in 64.2s — found 20 topics","detail":null},{"elapsed":"214.9","message":"Analysis tokens: 20,841 in / 1,743 out / 6,722 thinking — cost: $0.1433","detail":null},{"elapsed":"214.9","message":"Pipeline finished in 214.9s — total cost: $0.2548 (153,607 tokens)","detail":null}]} \ No newline at end of file diff --git a/history/1775588771329-NBu8G-5YpGI.json b/history/1775588771329-NBu8G-5YpGI.json new file mode 100644 index 0000000..db2e825 --- /dev/null +++ b/history/1775588771329-NBu8G-5YpGI.json @@ -0,0 +1 @@ +{"id":"1775588771329-NBu8G-5YpGI","videoId":"NBu8G-5YpGI","url":"https://www.youtube.com/watch?v=NBu8G-5YpGI","title":"The Iran War is Accelerating the End of Globalism | Jacob Shapiro","type":"youtube","topicCount":13,"segmentCount":206,"createdAt":"2026-04-07T19:06:11.329Z","uploadDate":"20260407","chunks":[{"title":"Introduction and Show Teaser","summary":"The host introduces the episode with a teaser from geopolitical analyst Jacob Shapiro. They discuss the recent resurgence of geopolitics, setting the stage for a deep dive into the Iran crisis and its global market impacts.","entries":[{"text":"Jacob Shapiro: It literally did not come into my imagination that this would be a longer war, that this would be a war for longer than three to four weeks, because the asymmetry of the advantages here go in Iran's favor. But all that really matters right now is how many ships are going in and out of the strait.","offset":0,"duration":13},{"text":"Jacob Shapiro: Physical shortages are starting to show up in East Asian economies. And if we keep going on this path, if we are still here in a month talking about this, we'll be talking about those shortages moving from East Asia to Europe, even to the Western Hemisphere.","offset":13,"duration":12},{"text":"Jacob Shapiro: There's a scenario here where maybe President Trump talks tomorrow or in the next week or two, and yet the disruptions that we're talking about are only just beginning because the global supply chain disruptions will move from a conversation about the Strait of Hormuz to what Ukraine is doing to Russia.","offset":25,"duration":18},{"text":"Jacob Shapiro: So it's an acceleration of deglobalization, it's an acceleration of multipolarity. You are looking for those places in the world that are on a relative basis will perform better when there is an energy choke point disruption.","offset":43,"duration":8},{"text":"Jacob Shapiro: Certainty and stability will not be coming from Washington or will not be guaranteed by Washington going forward. It's the end of an era. But it seems to me that the best case scenario coming out of all this is...","offset":51,"duration":12},{"text":"Host: Nothing said on Forward Guidance is a recommendation to buy or sell any investments or products. This podcast is for informational purposes only, and the views expressed by NOM on the show are solely their opinions, not financial advice or necessarily the views of Blockworks.","offset":63,"duration":7},{"text":"Host: Our hosts, guests, and the Blockworks team may hold positions in the companies, funds, or projects discussed. As always, investments and blockchain technology involve risk. Terms and conditions apply. Do your own research.","offset":70,"duration":26},{"text":"Host: All right everybody, welcome back to another episode of Forward Guidance. And joining me this week is Jacob Shapiro, independent geopolitical analyst, as well as the host of the Jacob Shapiro podcast and Geopolitical Cousins, which is by far my favorite geopolitical podcast.","offset":96,"duration":10},{"text":"Host: I do not miss an episode. You and Marco are just awesome. Reminds me a lot of what I do on the Roundup every week with the other co-hosts Quinn and Tyler, where we just chop it up, banter, and try to navigate the endless headlines. So super excited to have you on.","offset":106,"duration":16},{"text":"Host: You know, it's always funny when—it would be interesting to look at the correlation of when geopolitical experts come on podcasts versus like the degree of, I don't know, shit hitting the fan in the world. I'm sure it's just—I'm sure you've looked at it before, but it's always interesting. But yeah, excited to have you on the show, Jacob.","offset":122,"duration":16},{"text":"Jacob Shapiro: Thanks for having me. I don't know that I can promise much guidance, but it can certainly be forward. And yeah, I find that the pace of—I mean, obviously the last month has been nuts, but really ever since Russia invaded Ukraine, it feels like it has not let up in terms of being asked to come on and speak to either audiences or to do interviews. Like that was, that was definitely the moment where the world woke up and said, \"Geopolitics is back.\"","offset":138,"duration":26},{"text":"Host: Yeah, yeah, 100%. Geopolitics is back. And back more than ever right now over the last month. So obviously the topic du jour is Iran and everything going on there and the Strait of Hormuz.","offset":164,"duration":12}],"startTime":0},{"title":"The US-Iran Conflict and Asymmetric Warfare","summary":"Jacob details his initial framework for the US-Iran conflict, explaining why he didn't foresee a long war. He highlights Iran's asymmetric advantages, specifically its control over the Strait of Hormuz and its use of cost-effective military hardware against expensive US weaponry.","entries":[{"text":"Host: Would love for for those that just have not been as tuned into how you've been thinking about this crisis and the development of it. If you could just walk through your initial framework going into the initial strikes day in February, and then just how the sequence of events have evolved and how your framework has evolved up to basically now the first week of April.","offset":176,"duration":14},{"text":"Jacob Shapiro: Yeah, I'll try to make this succinct, and if I'm failing, I hope you will, you know, get the hook in here and get me off or tell me to be quiet. And I'll also just give you by way of background, I'm a global analyst now, and I'm especially in the last couple of years have been directly tying geopolitical analysis to active investing and investment positions and things like that.","offset":190,"duration":22},{"text":"Jacob Shapiro: But I cut my teeth as a Middle East analyst. My academic training is in the Middle East, my languages expertise is all in the Middle East. And it's always been funny to me that as a geopolitical analyst, in some sense the Middle East—I think I certainly analyze it and understand it well.","offset":212,"duration":16},{"text":"Jacob Shapiro: From a predictive standpoint, it's—by far my worst region. And I think there's something to be said for knowing too much about a thing. It puts you too close to the action, you're almost too smart for your own good. You can't get that same degree of global macro when you're too attached to it.","offset":228,"duration":18},{"text":"Jacob Shapiro: Which is my way of excusing myself for thinking I didn't think that the United States was going to undertake this war. I didn't think that because I thought they knew that the implications would be, well, I didn't even think catastrophic. I thought that they knew that it would be a short-term war and that they probably wouldn't be able to achieve their objectives.","offset":246,"duration":13},{"text":"Jacob Shapiro: It literally did not come into my imagination that this would be a longer war, that this would be a war for longer than three to four weeks, because the asymmetry of the advantages here go in Iran's favor.","offset":259,"duration":12},{"text":"Jacob Shapiro: For the first two or three weeks, the United States and Israel together lit up Iran, and it was all about firepower, epic fury. I'm old enough to remember when we did this in the second Gulf War. That was the period of the war that was always going to be very successful and very impressive for the United States military.","offset":271,"duration":16},{"text":"Jacob Shapiro: But two to three weeks in, then Iran's asymmetric advantages start to assert themselves. Their first and most important advantage is the Strait of Hormuz, is geography. And unless the United States has invented a weapon that separates Iran from control of the Strait of Hormuz, you can have all the shiny weapons you want and blow up all the power plants you want.","offset":287,"duration":20},{"text":"Jacob Shapiro: You're going to be fighting with a power that can upend the global economy by saying no ship shall go through the strait, which is exactly kind of what we're living through right this moment.","offset":307,"duration":9},{"text":"Jacob Shapiro: And then the second asymmetric advantage, and this is something we already saw with Russia and Ukraine, we saw it with the Houthis being able to resist the United States and block shipping through the Red Sea. We've seen it in all kinds of conflicts in recent years.","offset":316,"duration":11},{"text":"Jacob Shapiro: The United States may have very fancy interceptors and F-35s and all sorts of things that cost all amounts of money to develop. The Iranians have relatively, by comparison, unsophisticated rockets and missiles and drones and they cost far less.","offset":327,"duration":16},{"text":"Jacob Shapiro: And they can deploy much higher numbers of these things versus very fancy and expensive US military hardware where you get to the point where they're now beginning to see more bang for their buck or their rial or their yuan or Bitcoin, whatever you want to throw in there.","offset":343,"duration":15},{"text":"Jacob Shapiro: They're getting more bang for their buck because we've exhausted a lot of those higher-end things and they can just keep throwing out the cheap stuff. And that means that even as you decimate their navy and their air force and their launchers, as long as they've got a certain capacity left and people willing to fire them, they're going to keep firing.","offset":358,"duration":16},{"text":"Jacob Shapiro: And you're seeing that happen in real time right now. So that's a big intro by way of saying that I didn't think this was going to happen because I thought the United States had learned from previous mistakes.","offset":374,"duration":10},{"text":"Jacob Shapiro: I also took President Trump—my bad—at his word that this was a guy who campaigned on not going into wars in the Middle East and wasting trillions of dollars on American lives on fools' errands in the Middle East. And he got me, the bait and switch is on.","offset":384,"duration":12},{"text":"Jacob Shapiro: And it's, nope, it's war in the Middle East and this is absolutely critical. And by the way, the last thing I'd just say is, you know, second Iraq war at least you had the excuse of US energy insecurity being the geopolitical reasoning behind it.","offset":396,"duration":15},{"text":"Jacob Shapiro: There's no reason for the United States to be messing around the Strait of Hormuz. Since the shale revolution, the United States is a net exporter of crude, it's been keeping the lights on in Europe by exporting LNG. Yes, there are still global economic exposures based on the things that are blocked out of the Strait of Hormuz, but there's no compelling reason to be obsessed with Persian Gulf oil if you're the United States, which took another geopolitical reason off the board to engage in this conflict.","offset":411,"duration":17},{"text":"Jacob Shapiro: But yet, it's April 6th, the war's been going on for, what, five, six weeks now, and we're 24 hours from a Trump taco or from Trump obliterating the country or something in between. So there we are.","offset":428,"duration":15}],"startTime":176},{"title":"Tracking Geopolitics for Macro Investors","summary":"Jacob provides a framework for analyzing geopolitical events, splitting his focus into macro trends like multipolarity and short-term indicators. He emphasizes that the most critical metric right now is the physical volume of shipping through the Strait of Hormuz.","entries":[{"text":"Host: There we are. Okay, that's a great foundation. I want to move in and isolate towards understanding what are the actual important things to look at for economic slash market consequences.","offset":443,"duration":11},{"text":"Host: So you mentioned how you are very focused on understanding how to track these geopolitical events and in moving them towards some sort of tangible investment frameworks or macro analysis. Obviously this is a macro podcast, so the number one question I think that people listening to this are trying to figure out is: Okay, there's a million headlines a day right now, some of them move markets, some of them don't. There's a lot of stuff moving in a lot of different parts here. How do you isolate into the things that are actually meaningful towards global macroeconomics and markets?","offset":454,"duration":31},{"text":"Jacob Shapiro: Yeah, I want to answer that question in two ways. The first is at a—is at a macro time horizon. And when I say macro time horizon, I mean over a three to five year time horizon. So I did not think the United States was going to invade Iran, but from a positional perspective, I'm doing okay because I was long energy, I was long fertilizer, I was long food.","offset":485,"duration":21},{"text":"Jacob Shapiro: Like all of the things that are being affected by this, I was long for other reasons entirely, which tells you that this is exacerbating those things. It's making things move more quickly than I expected. But if anything, it's an accelerant, it's not a disruptor in that sense.","offset":506,"duration":13},{"text":"Jacob Shapiro: We were already moving towards deglobalization. We were already moving towards multipolarity of supply chains. We were already seeing the securitization of things like food and semiconductors and feedstocks.","offset":519,"duration":13},{"text":"Jacob Shapiro: All these things becoming part of the conversation about national security and countries that can protect those supply chains or make themselves self-sufficient in them, you were seeing those moves anyway.","offset":532,"duration":7},{"text":"Jacob Shapiro: And so I think over a three to five year time horizon, all that's happened is an acceleration of those trends that we were already watching. So it's an acceleration of deglobalization, it's an acceleration of multipolarity. You are looking for those places in the world that are on a relative basis will perform better when there is an energy choke point disruption in the Middle East, or who are going to perform better when there is—when there are rising food prices.","offset":539,"duration":22},{"text":"Jacob Shapiro: And conversely, you're also looking for those markets and countries that are not going to perform well. The countries that are able to assure cheap supply and secure supply of energy, cheap and secure supply of food, and are able to invest in the cutting edge of technology. Those are your countries that are going to be net winners over a three to five year time horizon. We could talk about those countries, those markets, those companies, verticals if you want.","offset":561,"duration":21},{"text":"Jacob Shapiro: Then there's our shorter term time horizon, which is: There's a lot of noise in the media and it's being generated by the White House, it's being generated by the IRGC, it's being generated by governments all over the place.","offset":582,"duration":11},{"text":"Jacob Shapiro: But all that really matters is how many ships are going in and out of the strait. And a week ago it was basically zero. It has ticked up a little bit in the last two to three days. Whether that is because the Iranians have this tolling system active and they are accepting payment for that, or whether it's ships that are running through because they think the Iranians can't cash the threats that they're making.","offset":593,"duration":18},{"text":"Jacob Shapiro: There's probably some combination of both there. You are seeing an uptick in the ships that are going through the Strait of Hormuz. Now, we are still at something like 20% of what is normal. So don't think for a second that this is normalized.","offset":611,"duration":13},{"text":"Jacob Shapiro: And don't think for a second, by the way, that we have up-to-date information on the damage that has already been done to infrastructure in the region. Let's say the war stopped in an hour. The first thing I want to know is: Okay, how damaged are the LNG facilities in Qatar? How damaged are the gas fields in Iran and some of these other places?","offset":624,"duration":17},{"text":"Jacob Shapiro: How long will it take to fix these things? Are we talking about turbines that have to be reordered, or are we talking about fixes that can happen on a time span of months? So there just is a lot of uncertainty that we're dealing with there. And I think the market is communicating that uncertainty to you in a bit.","offset":641,"duration":14},{"text":"Jacob Shapiro: Markets have been sanguine and almost delusional from my perspective. The disconnect between markets and the physical economies has never been more obvious, because the physical economy, especially in places that were over—overdependent on the region for a lot of these things.","offset":655,"duration":14},{"text":"Jacob Shapiro: The physical economies are starting to show the cracks. I mean, physical shortages are starting to show up in East Asian economies. And if we keep going on this path, if we are still here in a month talking about this, we'll be talking about those shortages moving from East Asia to Europe, even to the Western Hemisphere for all of the talk about US energy self-sufficiency as well.","offset":669,"duration":22},{"text":"Jacob Shapiro: So at the long-term perspective, you have to have that macro model about where the world is moving. Mine is multipolarity. There are others out there. And then for the short term, it's really just are ships going in and out of the strait. Period. And those are the things that I'm trying to keep my mind on at the same time.","offset":691,"duration":16}],"startTime":443},{"title":"The End of US Maritime Security","summary":"Discussing reports of ships paying tolls to bypass blockades, Jacob suggests this signifies a transition away from US-guaranteed maritime security. He expects a new, localized tolling structure to emerge as the best-case scenario for stability.","entries":[{"text":"Host: Yeah, 100%. I totally agree that the main vector to look at is counting ships. And it's an interesting one when I look at how the market has been digesting that idea over the last few weeks.","offset":707,"duration":11},{"text":"Host: As it feels like over the last three weeks or so there is an acceptance that there was almost no flow through the strait. And then over the past few days, I've started to see two vectors start to accelerate.","offset":718,"duration":11},{"text":"Host: One of those vectors being this idea of a dark fleet that is turning off their AIS and running the strait, whether they just had some sort of, you know, under the table agreement with Iran to let them go through. Or there's the more formal pact of what's going on with, say, you know, what you would assume are US allies, like France, have struck a deal with Iran to be able to start to move some of their oil through.","offset":729,"duration":20},{"text":"Host: So I'm curious: How do you think about those two vectors and how do you discount the validity or just quantify how to measure those?","offset":749,"duration":9},{"text":"Jacob Shapiro: It's really difficult and I'm not brave enough to go to the strait myself and test some of these things against each other. But you have reputable sources that are saying that at least some ships are paying a toll, and that they're paying the toll in yuan to get through.","offset":758,"duration":15},{"text":"Jacob Shapiro: And that the IRGC has a system for doing this, that they have country rankings based on how close they are to the United States or how Iran views their relationships with that country, and that affects the fee that you have to pay. So there are, you know, open-source reports from reputable sources that say that is happening.","offset":773,"duration":16},{"text":"Jacob Shapiro: Now, you have to take everything with a grain of salt here because it's the fog of war, but that's happening. Then you also, to your point, have reports about, you know, ships that are just running—are making a run for it. And they're getting through. Is that a testament to their bravery?","offset":789,"duration":12},{"text":"Jacob Shapiro: Is that because to your point they have a tacit understanding that the IRGC is not going to go after them at this point in time? Maybe they can't. Maybe they're focused on other things. Okay, like all open questions here.","offset":801,"duration":14},{"text":"Jacob Shapiro: But yeah, I don't have a solid answer for you. Like we have to be comfortable I think with the uncertainty. But it seems to me that the best case scenario coming out of all this is some type of tolling structure, whether it's wholly Iran or whether it's some kind of Iran-GCC combo toll, that returns certainty to transiting the Strait of Hormuz.","offset":815,"duration":21},{"text":"Jacob Shapiro: And it's crazy to me because that means the best case scenario we're talking about is: You're no longer thinking that the United States Navy is there to guarantee global shipping lanes and maritime choke points.","offset":836,"duration":12},{"text":"Jacob Shapiro: You want there to be some kind of localized tolling facility, even if it's with the ayatollahs of Iran, a group of not particularly nice people. Like you'd rather know, \"Okay, this is what I pay, this is what I do, and I get through the Strait of Hormuz.\" Like certainty and stability is what's going to be the best case scenario coming out of this.","offset":848,"duration":15},{"text":"Jacob Shapiro: And that certainty and stability will not be coming from Washington or will not be guaranteed by Washington going forward. And for some countries I guess that'll be good, but for most of the world and for the United States, which has profited off of US-led and protected globalization, it's the end of an era in some sense.","offset":863,"duration":18}],"startTime":707},{"title":"Conflict Contagion and Supply Chain Brittleness","summary":"Zooming out to the broader geopolitical landscape, Jacob explains how regional conflicts are bleeding into one another, such as Ukraine targeting Russian petrochemicals. He warns that already brittle global supply chains are highly vulnerable to secondary shocks like extreme weather.","entries":[{"text":"Host: Mm-hmm. Yeah, I think that's a great point and just to zoom out into this secular trend that you mentioned of deglobalization and multipolarity is: Okay, you have this basis that the Strait of Hormuz has had this degree of security guarantees from the overall American apparatus for decades now.","offset":881,"duration":19},{"text":"Host: And that apparatus and those security guarantees are on the margin moving away. And then we have to figure out and discount: Okay, how much is it going to move towards this new world where Iran is the one or maybe in some sort of agreement with Oman, they're the ones running the toll booth now?","offset":900,"duration":13},{"text":"Host: And pairing that with who are actually dependent on the strait, which is, i.e., you know, Europe and they have to decide who do they align with, and then also East Asian markets and who they have to decide who to align with.","offset":913,"duration":13},{"text":"Host: And I'm curious about how you're thinking about how all these different countries net out. Because again, there's—you know, there's been interesting stuff what's been going on with the UN Security Council this week where you had them trying to vote about whether to intervene with outright force or not.","offset":926,"duration":16},{"text":"Host: And you saw actually, you know, France aligning with China and Russia for example. So these traditional lines of, you know, the West versus the East or however you want to define it just don't seem as consistent anymore. So I'm just curious: How do you see this whole framing net out over the next few years? It just seems completely convoluted.","offset":942,"duration":17},{"text":"Jacob Shapiro: Yeah, well first things first, like who cares what the United Nations says. I mean, it's like the Dave Chappelle Black Bush sketch, like \"Sanction me! Sanction me with your army! Oh, you don't have an army! Okay, cool.\" So I don't really care what the UN says.","offset":959,"duration":13},{"text":"Jacob Shapiro: No, I think here we also have to widen the aperture a little bit because the Russia-Ukraine war is also ongoing. And one of the things that has made me more optimistic in a multipolar world is that I expected you would get these types of small regional conflicts, but that they would be relatively self-contained.","offset":972,"duration":17},{"text":"Jacob Shapiro: So the Russia-Ukraine war, despite—you know—myriad articles written about the beginning of World War III, it's a Russia-Ukraine war. It's a war between those two actors. Yes, some countries are supporting the other side with weapons, but it's Russian soldiers, Ukrainian soldiers, and those poor North Koreans that the Russians imported.","offset":989,"duration":16},{"text":"Jacob Shapiro: One of the things that's different about this conflict is you're starting to see the bleed over. And this is something I don't think markets have really quite gotten through their head. Because Ukraine is watching everything that's happening in the Strait of Hormuz, and I imagine that Zelenskyy—you know—I'm imagining here, I don't—I don't know this for sure.","offset":1005,"duration":14},{"text":"Jacob Shapiro: But I imagine Zelenskyy's watching the situation and watching Iran's asymmetric—asymmetric advantage work and thinking to himself, \"Oh, if I can affect the global price of oil or petrochemical supply chains or things like that, people will listen to me even if I'm being blown up by the United States and Israel, even though my air force is gone and everything else like that.\"","offset":1019,"duration":19},{"text":"Jacob Shapiro: \"Cool. So instead of hitting Russian energy infrastructure that makes life harder for the everyday Russian citizen,\" which is what Ukraine has been doing for the past 12 months, trying to drive up the price of gasoline for the average Russian consumer, hitting that infrastructure.","offset":1038,"duration":13},{"text":"Jacob Shapiro: \"I'm going to go after Russian oil export infrastructure. I'm going to go after Russian petrochemical export infrastructure because then maybe people will start listening to what I want.\"","offset":1051,"duration":11},{"text":"Jacob Shapiro: \"I also don't want Vladimir Putin to profit from higher oil prices. I don't want the Europeans to hang me out to dry by having to go back to Moscow and saying, 'We really don't like you, but we kind of need your oil and natural gas and fertilizers and everything else again. So let's let bygones be bygones and we'll try and muzzle the Ukrainians and threaten support and things like that.'\"","offset":1062,"duration":17},{"text":"Jacob Shapiro: All of which is to say this now goes from Russia—excuse me—Israel-US versus Iran with some GCC states game theory into also Russia versus Ukraine and the powers that are on either side of that.","offset":1079,"duration":15},{"text":"Jacob Shapiro: And it just starts to get unwieldy when you think about all the different circumstances that are there. So yeah, I mean, there is a—there is a scenario here where maybe President Trump talks tomorrow or in the next week or two, and yet the disruptions that we're talking about are only just beginning because the global supply chain disruptions will move from a conversation about the Strait of Hormuz to what Ukraine is doing to Russia and what that means in general.","offset":1094,"duration":24},{"text":"Jacob Shapiro: And then just layer on top of that—I'm not usually a doomer here, but it's very hard not to at least engage in the doomer scenarios to be ready for them. I mean, let's say all that's happening and then it's hurricane season in the United States, and what if a hurricane, you know, hits the Gulf and some capacity of US exports goes offline?","offset":1118,"duration":18},{"text":"Jacob Shapiro: Like we don't even have to do anything nefarious about cyberattacks or electromagnetic pulses or all the crazy things that the doomers want to do. Let's just say it's a weather formation and a storm knocks off some percentage of US exports.","offset":1136,"duration":11},{"text":"Jacob Shapiro: Now you're dealing with a global economy where things are already very lean, everybody's already on edge, and that one sort of bastion of supply that is far away from the geopolitical conflict gets hit. Okay, and now we're off to the races.","offset":1147,"duration":14},{"text":"Jacob Shapiro: So just every single one of these things increases the brittleness of global supply chains. And that's a story that we've—you know—I've also been tracking for quite some time as well. So that's how I would think about widening the aperture and thinking about international interest. Certainly don't think about what the UN has to say. They have no power here.","offset":1161,"duration":17}],"startTime":881},{"title":"Supply Chain Risks: LNG, Fertilizer, and Plastics","summary":"Jacob breaks down the global supply chains most at risk from ongoing conflicts. While less concerned about oil due to strategic reserves, he highlights severe vulnerabilities in LNG, agricultural fertilizers, and lower-tier petrochemicals like plastics.","entries":[{"text":"Host: That's super helpful. Okay, yeah, I do want to ratchet down one level towards those specific supply chains and understand and map out.","offset":1178,"duration":8},{"text":"Host: You know, I feel like just as a general tourist to this space and trying to read the news articles and understand what's going on, a lot of headlines are really focused on the price of oil and less so on some of these more downstream impacts, whether it's the fertilizer market or helium and the LNG space and things like that.","offset":1186,"duration":17},{"text":"Host: So I'm just curious if you could just map out for us when you look at these different lists of supply chain issues, which ones do you feel like are rightly an issue? Which ones do you feel like are not being paid enough attention to? And yeah, like which ones are you most concerned about here?","offset":1203,"duration":17},{"text":"Jacob Shapiro: Yeah, um, I mean, it's impossible to map them all out without putting listeners to sleep. But let's sort of talk about some of the big categories. The big ones. Because even in a crisis, like supply chains are for nerds. Like this is—you don't go into college being like, \"I'm going to be an expert on supply chains.\"","offset":1220,"duration":17},{"text":"Jacob Shapiro: Oil, look, oil's important. In some ways, it's the one that I'm least worried about, not least because you have countries with strategic reserves. Four to five million barrels per day are crossing that pipeline and getting out through Yanbu, at least for now.","offset":1237,"duration":14},{"text":"Jacob Shapiro: If the Houthis get involved and if the Red Sea is shut, okay, like we can—we can start sounding the alarm there. I certainly think we'll see elevated oil prices through the end of the year. But in some sense, like that's the one that maybe I'm least worried about.","offset":1251,"duration":12},{"text":"Jacob Shapiro: LNG is a—is different because you're not piping LNG to Yanbu across—across the desert. And Europe really—like Europe was depending on access to all the LNG capacity coming online out of this.","offset":1263,"duration":16},{"text":"Jacob Shapiro: That's how they were going to balance the lack of supply that was coming from Russia. And that doesn't mean that the Europeans are going to go cold in the winter. What it means is they're going to pay higher spot prices for these things, even if it's from China rerouting some of what they're getting over there.","offset":1279,"duration":13},{"text":"Jacob Shapiro: And that means your emerging markets that were betting that they were going to have access to some of this LNG are going to have to start scrambling themselves, whether that's, you know, coal or what Pakistan has done with solar in the last couple of years. They're the ones that are going to be scrambling, that are going to be hurt the worst.","offset":1292,"duration":17},{"text":"Jacob Shapiro: Fertilizer's a big deal. Fertilizer is another one of these very lean supply chains where you don't have strategic fertilizer reserves. Fertilizer's really only relevant one or two times a year based on when farmers are planting and when they need the fertilizer.","offset":1309,"duration":12},{"text":"Jacob Shapiro: And so that's when the supply chain is there for them. We already missed the window for many farmers throughout the world to apply fertilizer. So you can book in now lower yields in many parts of the world and rising food prices in those parts of the world.","offset":1321,"duration":15},{"text":"Jacob Shapiro: And we won't know the full impact of that from six to nine months till now. But just a reminder that the Arab Spring began with rising food prices in the Middle East. It was a Tunisian vegetable salesman who self-immolated that started the Arab Spring because food prices were too high and because that vegetable salesman didn't feel like they could make a living and then they got insulted by police and we were off to the races.","offset":1336,"duration":15},{"text":"Jacob Shapiro: Um, so I think that potential six to nine months down the road in emerging markets for thinking about some of that type of political disruption, that's there and that ties directly to fertilizer. And then the last major category is the petrochemical complex.","offset":1351,"duration":14},{"text":"Jacob Shapiro: And that spans everything from, you know, boring things like plastic and plastics and resins to higher value input things like helium that you're talking about that are critical for semiconductor manufacturing.","offset":1365,"duration":13},{"text":"Jacob Shapiro: And, I mean, this is still a thesis that I'm building, but in some sense I'm less worried about things like helium because helium's important enough that there are strategic reserves out there. And at least the reporting I've seen and my contacts in the space seem to be—I mean, optimistic is the wrong point of view—but not freaking out.","offset":1378,"duration":16},{"text":"Jacob Shapiro: In my Rolodex, the folks that are freaking out are those ones for those mid-to-lower tier petrochemical products that you would think are boring, like the plastic that's in everything in your life, which you're seeing doubling and tripling of prices.","offset":1394,"duration":15},{"text":"Jacob Shapiro: Or you're seeing companies that are saying, \"I just can't get it. Like it's not available for any price, or I have to go to China or I have to go to some weird place before that maybe that's going to run afoul of global sanctions in order to—in order to get it.\"","offset":1409,"duration":12},{"text":"Jacob Shapiro: And that again is—these are products for which there's no strategic reserve. Nobody was sitting there being like, \"Yeah, I need a strategic plastic polymer reserve because I need to make sure that I have plastics that I can wrap the food in that I'm selling at the grocery store.\"","offset":1421,"duration":12},{"text":"Jacob Shapiro: But that's where it's going to start showing up, because those are the things where things are very lean. And by the way, like the whatever you think about globalization and free trade, we could argue till we're blue in the face: Is it good, is it bad?","offset":1433,"duration":11},{"text":"Jacob Shapiro: The thing about free trade, the thing that makes it efficient, that the bulls will say about free trade is, yeah, that's exactly how it's supposed to work. You produce what you need, when you need it, for the cheapest price possible, in the geographies that are most optimized for that production.","offset":1444,"duration":15},{"text":"Jacob Shapiro: And that's the way a lot of supply chains are. Even though the world is moving multipolar, lots of supply chains still function like it's a globalized world. So when you have this kind of crisis and this level of supply chain disruption, you're dealing with supply chains that are expecting a perfect globalized free trade world of the 1990s.","offset":1459,"duration":15},{"text":"Jacob Shapiro: And instead they're getting this version of multipolarity and regional warfare and return of great power politics of 2026. Now, those supply chains will change. Trade is like water, it will find cracks, it will figure out the way it needs to get from Point A to Point B.","offset":1474,"duration":15},{"text":"Jacob Shapiro: But just like water, water can be very destructive when it's trying to find those cracks. Levees can break, walls can crash down, you can inundate entire areas as those things try and get from Point A to Point B.","offset":1489,"duration":10},{"text":"Jacob Shapiro: And usually it's your emerging markets, your countries that have lower buffers, that don't have strategic reserves, that are already constrained from a fiscal position. Those are the countries that are going to be front and center, and then you'll get relative degrees of pain depending on where you are and what your self-sufficiency is. So that's—that's my best way of trying to very succinctly putting a bow around global supply chains and which ones are affected.","offset":1499,"duration":22}],"startTime":1178},{"title":"Podcast Sponsor Ad Break","summary":"The host reads promotional messages for the podcast's sponsors, Arkham and Blockworks Investor Relations.","entries":[{"text":"Host: Before you place a trade, you should know who is actually moving the market. That's where Arkham comes in. Arkham is a crypto intelligence platform and exchange that lets you see real on-chain data, which wallets are buying, selling, and moving funds, and then trade directly on that information.","offset":1521,"duration":15},{"text":"Host: Arkham was built to make blockchains human readable. Instead of raw transaction data, you get clear profiles, visualizers, and custom dashboards that show what's really happening beneath the surface. Tracking wallets and fund flows is becoming just as important as technical or fundamental analysis.","offset":1536,"duration":15},{"text":"Host: On-chain intelligence is also one of the best tools traders have to protect themselves against hacks, rugs, and scams. With Arkham Exchange, you can go from insight to execution in one place: the world's first exchange powered by crypto intelligence. Check out Arkham and start trading with real on-chain insight at arkham.com.","offset":1551,"duration":18},{"text":"Host: Blockworks co-founder Michael Ippolito here. Quick break to talk about something we've just launched: Blockworks Investor Relations. As the market shifts toward institutional capital, investors want more transparency, more standardization, and a higher level of professionalism.","offset":1569,"duration":13},{"text":"Host: But the traditional IR model is slow, manual, and not built for how crypto works. If you're building on-chain, your data is already live, your business is already transparent. The challenge is turning that into a clear, credible story for investors. That's exactly what we're solving with Blockworks IR.","offset":1582,"duration":16},{"text":"Host: It's a single platform that brings together real-time analytics, branded investor portals, and hands-on advisory support so you can communicate what matters. If you're an on-chain business looking to level up your investor strategy, check out Blockworks Investor Relations at blockworks.com/investor-relations. All right, back to the episode.","offset":1598,"duration":19}],"startTime":1521},{"title":"Economic Timelines and US Political Constraints","summary":"Discussing how long the global economy can endure disruptions before structural damage occurs, Jacob points to the political vulnerability of the US administration. He notes that domestic inflation and high gas prices pose severe risks for the incumbent party heading into the midterms.","entries":[{"text":"Host: Awesome, that's great. I don't think we put anybody to sleep there. That was compelling to myself anyway, so I'm sure everybody's still awake.","offset":1617,"duration":7},{"text":"Host: The big question that hand that comes from that for me is understanding the timeline that we have that we can work around this. You know, obviously you mentioned a lot of the really key strategic ones have those reserves associated with it, and then there's the more downstream ones that don't have any reserves associated with it.","offset":1624,"duration":16},{"text":"Host: So I'm just curious: How do you think about the timeline for how much working time we have? Or how much you—how much you think maybe the Trump and Israel are thinking about how much time they have for this operation before it's like, \"Oh crap, we're really doing some structural damage. Like, there is no inventory in these certain important assets and we're really screwed here.\" What does that timeline look like for you?","offset":1640,"duration":22},{"text":"Jacob Shapiro: Well, let's break those in two, because Israel doesn't care. Israel cares that this rival that has threatened to wipe it off the map—so I'm not ascribing a value judgment here—but Israel views Iran as an existential threat, and all it wants to see, if not regime change, then it will take chaos and obliteration. Like that is a net positive from Israel's point of view. It will deal with the economic catastrophe that comes in.","offset":1662,"duration":21},{"text":"Jacob Shapiro: Israel is a country that is relatively well-off. Ever since their discovery of offshore gas, it's removed one of their key vulnerabilities in terms of inputs, and they're actually in a pretty good position.","offset":1683,"duration":11},{"text":"Jacob Shapiro: As for the United States, I mean, this really comes down to psychoanalysis on some level and who Trump is listening to and what he thinks. Because based on what I understand, I think we're already flirting with disaster.","offset":1694,"duration":13},{"text":"Jacob Shapiro: Um, you know, I think if you're looking at most of these things, if you don't have this war wrapped up in two to three weeks, you know, you're probably talking about physical shortages for many of the things that we just talked about.","offset":1707,"duration":12},{"text":"Jacob Shapiro: And when I say two-three weeks, like you have to then assume that there is an escalation in that time period or that you don't get further damage to infrastructure that makes restarting all that much harder, which is pretty hard to imagine considering the rhetoric that is going back and forth between the sides.","offset":1719,"duration":14},{"text":"Jacob Shapiro: All of which is to say, you know, the constraints point to this being resolved two weeks ago. But President Trump has not resolved it. He's doubled down and tripled down and he's, you know, he's threatening—I mean, I forget the exact words that he used in that tweet yesterday—but I mean, just kind of insane the level of threats that he's raising against Iran.","offset":1733,"duration":18},{"text":"Jacob Shapiro: You've got a trillion and a half dollar defense budget that's coming—I mean, he's not acting like somebody who's about to throw in the towel. Now, maybe it's the art of the deal. Maybe the art of the deal is beyond me. But there's that.","offset":1751,"duration":11},{"text":"Jacob Shapiro: But yeah, if we're here two-three weeks from now talking about the same things, and you know, we could still be talking about the war and shipping has gone back not to normal, but goes back to 60-70% and the Iranians are only striking certain types of targets that are connected to Israel and the United States.","offset":1762,"duration":16},{"text":"Jacob Shapiro: Okay, like now we're talking about some kind of resumption. But yeah, I'm worried that we're already off the cliff, and even the folks I think that are pretty sober and optimistic about this would be the first to admit, \"Yeah, if we're here on May 1st and we're still talking about this, the global economy is going to be—is going to be majorly affected.\"","offset":1778,"duration":16},{"text":"Jacob Shapiro: And as for the last thing just, it is obvious to me that President Trump and this administration is thinking that the United States is safe from this because of the shale revolution and because the United States is not dependent on importing oil and LNG from the Persian Gulf.","offset":1794,"duration":15},{"text":"Jacob Shapiro: And it's just such a facile and feeble point of view. You can argue that the United States needs to Make America Great Again and nearshore or reshore all this industrial capacity back to the United States and everything else. Cool, it hasn't happened yet in the Year of Our Lord 2026, and this supply chain disruption is here right now.","offset":1809,"duration":20},{"text":"Jacob Shapiro: The United States is exposed to the global economy. And yes, maybe the United States has some fundamental factors that mean it can weather it on paper a little bit better, but Joe Biden learned just how hard it is to weather things on paper versus when people are at the gas pump and being like, \"Hey, it's five dollars to pump at the gas tank,\" or eggs have gone to this.","offset":1829,"duration":23},{"text":"Jacob Shapiro: Watching President Trump try and lecture the American public that everything's fine with the economy. I mean, he's doing the exact same thing that Biden did in 2022, which is the exact reason that we have President Trump 2.0 in the first place.","offset":1852,"duration":14},{"text":"Jacob Shapiro: All of which is to say, US politics is way more brittle than the US strategic position. We're going into the midterms. Trump is at terribly low approval ratings, and even worse for him, he's at terribly low approval ratings on his handling of the economy.","offset":1866,"duration":14},{"text":"Jacob Shapiro: No matter what people thought about him, he always got good ratings on, \"Oh, this guy is going to handle the economy better than Joe Biden or Kamala Harris or Hillary Clinton or any of these others.\" Those numbers are now where they were at for Joe Biden in 2022.","offset":1880,"duration":13},{"text":"Jacob Shapiro: Um, so at least from a domestic political constraint point of view, you would think that he would see the disaster that is coming in November and would start to change course. But it seems, you know, if I'm just doing psychoanalysis and reading what he's doing, it doesn't seem to me like it's art of the deal.","offset":1893,"duration":13},{"text":"Jacob Shapiro: It seems to me like he really believes that the tariffs worked and that America is great again and that he is presiding over the greatest—you know—economic Renaissance in the history of the country. And I'm sorry, like I'll take the other side. I don't think that's true. But I think he's operating from that standpoint.","offset":1906,"duration":14},{"text":"Host: Yeah. I mean, that's the ultimate head-scratcher is that it's—I mean, yeah, you just set to pull a polymarket look for two seconds and you're going to see that they're the polling is going to go terrible for the midterms for them. And it's just such a—it's just such a head-scratcher.","offset":1920,"duration":13}],"startTime":1617},{"title":"Ignoring Geopolitical Noise for Real Indicators","summary":"The host asks about impending negotiation deadlines between the US and Iran. Jacob advises ignoring political posturing and reality TV ultimatums, reiterating the importance of tracking physical shortages and real commodity prices instead.","entries":[{"text":"Host: I'm curious so: Yeah, what is your—what is your framework for heading into the \"quote-unquote\" negotiations happening right now between Iran and the US via Pakistan and this—this potential deadline approach of tomorrow, so Tuesday, I think at 8 o'clock or something like that Eastern, is sort of this—this do-or-die moment for getting some sort of agreement between the two parties.","offset":1933,"duration":25},{"text":"Host: And I'm just curious like: How do you view the framework to head into that negotiation and what's actually really going on there? Because there's just so much noise around it. So is it—you know—you just look at this timeline acuteness that we just unpacked? Is it something to do with: Okay, we really got to get this wrapped up in the next couple weeks or so because midterms are in November and we need to try to, you know, put out the fires that we've just self-inflicted on ourselves by then or, you know, just have enough runway? Like, how do you think about all that?","offset":1958,"duration":24},{"text":"Jacob Shapiro: I'm opting out of the reality TV show presidency. I stayed up late what was that Friday or whatever he was doing the White House press—you know—the press conference from the Oval or from the White House or whatever it was because he was going to make some announcement it was going to be ground troops.","offset":1982,"duration":12},{"text":"Jacob Shapiro: And it wasn't, it was just President Trump being President Trump. And he has a knack for creating these inflection points, these moments where everybody's talking about him and everybody's focused on this thing. I'm not buying it. Like I'm buying our ships coming out in and out of the Strait of Hormuz.","offset":1994,"duration":14},{"text":"Jacob Shapiro: Does Iran feel like it's done enough to either re-establish deterrence or is it making progress in getting reaching some kind of modus vivendi with Oman and GCC states about where this goes from here?","offset":2008,"duration":12},{"text":"Jacob Shapiro: If you're just reading the plain objectives of both sides, I don't think Iran feels like it has caused enough pain to the global economy to re-establish deterrence, and I don't think the United States is acting like a country that is able to declare mission achieved or—you know—mission objectives achieved quite yet.","offset":2020,"duration":17},{"text":"Jacob Shapiro: So that tells me that, you know, maybe there's negotiations going on, but it doesn't look like either side is ready to bend. Maybe I'm reading that wrong. Maybe Iran actually is hurting much worse than I think, and Iran feels like it's done enough and maybe it's got, you know, back channelers from the—from the Gulf states that make them feel like they can do that.","offset":2037,"duration":17},{"text":"Jacob Shapiro: Maybe President Trump really does believe like he's achieved his objectives and he can end this particular season of the reality TV show and move on to the next episode. But yeah, I'm opting out of these \"Oh, tomorrow's the inflection point.\"","offset":2054,"duration":12},{"text":"Jacob Shapiro: Because for all we know, he'll come on tomorrow and be like, \"I've extended the deadline another two days, but Thursday is now, you know, bridge obliteration day.\" Like, okay. How many straits are coming in or—excuse me—how many ships are coming in and out of the Strait of Hormuz?","offset":2066,"duration":14},{"text":"Jacob Shapiro: What is the price of jet fuel in Singapore? What is the difference between, you know, Asian futures and and what Brent crude is showing us: market versus physical shortages. Like that's what I'm interested ultimately. And when that stuff starts going back, you'll probably be able to see the politicians starting to change their tunes.","offset":2080,"duration":15}],"startTime":1933},{"title":"Global Winners and Losers in a Multipolar World","summary":"Jacob assesses how different regions will fare amid ongoing supply chain disruptions. He remains bullish on the long-term economic prospects of the US and China, identifies emerging opportunities in countries like Chile, and expresses optimism for Europe's ability to adapt.","entries":[{"text":"Host: Hmm. To that point, obviously, yeah, there's a lot of more esoteric markets like you mentioned, like Singapore jet oil, that have gone absolutely bananas.","offset":2095,"duration":10},{"text":"Host: But then there's also other things like, you know, US equities are, you know, barely down from all-time highs. And I'm just curious about: When you net out everything that exists today and how it's—how it's been discounted?","offset":2105,"duration":10},{"text":"Host: And if we can get to this point where markets can forward-look to a point where there is this like weird new world of a gray zone around the Strait of Hormuz where there is partly this toll thing, but then also not?","offset":2115,"duration":11},{"text":"Host: And, you know, when you net it all out stuff is getting through the strait. Like that world that we get into and you net it with all the damage that has been done—you know—there was like 20 billion dollars of damage done to the Qatar LNG facility.","offset":2126,"duration":14},{"text":"Host: There's—there's still durable damage as well. When you put that all together, like do you—what do you see the probability of markets just trying to look past this whole thing and and move on? Or how much of it is like, \"Okay, we've done too much damage, we need to discount this further.\"","offset":2140,"duration":15},{"text":"Jacob Shapiro: Yeah, I never try to denigrate Mr. Market because Mr. Market is probably smarter than all of us are. At least to some—at least at some level. That said, you know, markets can also be overly optimistic even as things are starting to break.","offset":2155,"duration":18},{"text":"Jacob Shapiro: Like think about how long it took for markets to appreciate the risk of the Russia-Ukraine war, or to appreciate what was happening in 2007, 2008. It's not like markets are always the leading indicator, and sometimes they lag considerably in terms with that.","offset":2173,"duration":16},{"text":"Jacob Shapiro: I also think you have to think in terms—you know—this is—I was relatively optimistic about the US economy going forward. And I was optimistic for precisely some of the reasons that we already talked about. Like multipolarity and deglobalization means that within these regional spheres of influence that are powered by these regional potential regional hegemons, you're going to get more investment and more capex and government support of technology and also some of these physical parts of the economy.","offset":2189,"duration":27},{"text":"Jacob Shapiro: So I think even with, as we're talking about, the long-term ramifications of the disruption in the Middle East, everybody's going to be worse for it. Like nobody is walking out of this conflict better for there having been a disruption.","offset":2216,"duration":13},{"text":"Jacob Shapiro: But at a relative level, some countries will have done better than others. The United States is a country that is poised to do better than most others in the world. It's far away from geopolitical zones of conflict. It has cheap and secure access to energy and to food. It is still in many ways at the commanding heights of technological innovation.","offset":2229,"duration":17},{"text":"Jacob Shapiro: There's a lot going for the United States. And that's one of the reasons why it's so baffling that the United States did this. Like if President Trump had just kept doing what he was doing, if Cuba had been next rather than Iran, you know, we might have been talking about a very different economy going into the midterms.","offset":2246,"duration":16},{"text":"Jacob Shapiro: China is a country that I think is going to do relatively well. And I know that some people will now like say, \"Oh, he's a CCP shill\" or whatever, and don't worry, I'm—I'm still waiting for my CCP payments for saying bullish things about China.","offset":2262,"duration":11},{"text":"Jacob Shapiro: But China, I think, is well—has been preparing for this for years. Who's leading the world in terms of rolling out renewable capacity? It's China. China's not doing that because it makes sense from an economic perspective to do so.","offset":2273,"duration":12},{"text":"Jacob Shapiro: That is because the communists on high said, \"We will do this, because we watched the Americans in the Middle East for 20 and 30 years and we don't want to participate in that.\" Yes, we are still dependent on importing from the Persian Gulf, but we envision a world 10-15 years from now where we've got nuclear and solar and wind and everything else and that we become a center of green, you know, energy technology.","offset":2285,"duration":20},{"text":"Jacob Shapiro: A, because that's nice, but B, because this is an existential issue for us. We don't want to have our energy blocked because of something that's happening in the Strait of Hormuz.","offset":2305,"duration":8},{"text":"Jacob Shapiro: Then you've got countries like—I mean—Saudi Arabia used to be on this list. I don't know that it still can be. But say a country like Chile, which is far away from geopolitical zones of conflict, which can have incredibly low cost of energy because of the solar, wind, geothermal potential that lies there.","offset":2313,"duration":13},{"text":"Jacob Shapiro: And so that's going to be an ideal case for you to do things with data centers or internet of things or automation or robotics and things like that. So I think you will find pockets of opportunity throughout the world, and it's about, you know, putting perspective on which places are going to do relatively better than others even despite this disruption.","offset":2326,"duration":21},{"text":"Jacob Shapiro: The one that is most out there is—is Europe. And I—I remain pretty optimistic about Europe's future. I think Europe gets left for dead too often and Europe's obvious flaws overshadow its strengths, which is: It's still an incredibly rich and wealthy place. It's a place that thinks it's geopolitically relevant that has lots of technological advantages that it can deploy.","offset":2347,"duration":22},{"text":"Jacob Shapiro: If you're in Central or Eastern Europe and you've bet your energy future on first Russia and then on cheap energy supply coming out of the Middle East, okay, you're going to be in for some tough years. But that's not the story of France, that's not the story of Spain, that's not the story of some of these other countries.","offset":2369,"duration":14},{"text":"Jacob Shapiro: And they exist not—I mean, I wish it was a confederation, it would make it easier—but they exist in this European Union. And so those countries are going to have to look at each other and say, \"We have to stop letting Hungary hijack our priorities going forward and make some pretty serious decisions about where we're—what we're going to do to stay relevant.\"","offset":2383,"duration":16},{"text":"Jacob Shapiro: I think the EU will do that. You can make a very compelling case that they won't and that I'm just whistling into the wind here. But that I think is a block that could use the—the impetus of this crisis to do things that people today maybe aren't appreciating as possible. Like those are places that I'm going to be interested in going forward.","offset":2399,"duration":19}],"startTime":2095},{"title":"China's Grand Strategy and Pragmatic Diplomacy","summary":"Jacob analyzes China's response to US sanctions on Iran and Venezuela, noting that these moves hurt US allies more than China. He dismisses fears of an imminent invasion of Taiwan, arguing China prefers economic isolation tactics and diplomatic pragmatism.","entries":[{"text":"Host: Interesting. Okay, I want to double-click on the China thing a little bit because there's two things that are interesting to me that I've been noticing. One of them is just how quiet they've been throughout this whole crisis. Um, really haven't been that verbose or explicit about the whole thing.","offset":2418,"duration":14},{"text":"Host: And the other one too is if you rewind pre-Iran strikes when the Venezuela thing was happening, there was this whole emergence of the Donroe Doctrines, spheres of influence and a lot of speculation that it's like we're, you know, aligning the chess pieces to go after the—the big dog that is China.","offset":2432,"duration":17},{"text":"Host: Um, and you know we want to cut off all their oil supply. So we're cutting Venezuela and now we're going to Iran and now we're going to cut off the Strait of Hormuz and all that oil going to China. How are you thinking about those two dynamics?","offset":2449,"duration":10},{"text":"Jacob Shapiro: Well, let's take the last one first. We hurt over Japan, South Korea, India way more than we did China. Remember, when Vladimir Putin invaded Ukraine, all he did was turn Russia from a great power into a Chinese gas station.","offset":2459,"duration":15},{"text":"Jacob Shapiro: So China's—I'm not saying that China's energy secure, but they have more reserves, more renewable capacity online and a relationship with Russia. That is not something that your Japans and South Koreas and Indias can say.","offset":2474,"duration":19},{"text":"Jacob Shapiro: So in that sense, okay, if you're trying to hurt China with that 5D chess, you actually hurt your allies much more. Um, if you think I'm being too hysterical about that, think about what's happened in the Philippines over the past couple of weeks.","offset":2493,"duration":12},{"text":"Jacob Shapiro: The Philippines was one of the first countries in Asia to declare an energy emergency because of what's happening in the Hormuz—in the Strait of Hormuz. A couple days after that, the Marcos Jr. government announced that they were restarting talks with China about joint exploration in the West Philippine Sea and the South China Sea for offshore energy deposits.","offset":2505,"duration":16},{"text":"Jacob Shapiro: That's wild. The Philippines is a US defense treaty ally. We spent years worrying about the Duterte administration getting friendlier with China and doing exactly this. It took just a couple of weeks and this war of choice in Iran for the Philippines to start looking at China and saying, \"Huh, maybe we should have a more pragmatic relationship with China. Maybe this is a country that we can do business with even in the South China Sea, even around Taiwan.\"","offset":2521,"duration":25},{"text":"Jacob Shapiro: So you've—you've hurt the allies more than you've hurt China there. And I think China has more reserves than folks expected. Also as for the Taiwan issue, man, can we just put it to bed finally?","offset":2546,"duration":12},{"text":"Jacob Shapiro: Because if China's not going to invade Taiwan now, with the United States bogged down in the Middle East and using all the Tomahawk missiles and everything else like that, okay, I'm waiting. Are they going to go for it? Is now the time?","offset":2558,"duration":-1069},{"text":"Jacob Shapiro: No, now's not the time, because they're not thinking about it that way. They're thinking about Taiwan the way they thought about Hong Kong in the 70s and 80s. They want to isolate it economically, they want to isolate it politically.","offset":1489,"duration":1091},{"text":"Jacob Shapiro: They want to get to the point where nobody cares enough about Taiwan so that when they announce that they are taking it, nobody puts up a fight to stop them, which is exactly what happened with Hong Kong.","offset":2580,"duration":9},{"text":"Jacob Shapiro: The UK went back to renew the lease, Margaret Thatcher—that great British nationalist herself—Deng Xiaoping said, \"Cool, we'll cut off the energy and the infrastructure and the water and we'll blockade it if that's what you want to do. Is that what you want?\"","offset":2589,"duration":15},{"text":"Jacob Shapiro: And Thatcher said, \"I think I'll go to the Falklands to wave the British flag around. Like you can have it.\" And then we had, you know, one country, two systems, blah, blah, blah. That is the move that China's playing for when it comes to Taiwan.","offset":2604,"duration":10},{"text":"Jacob Shapiro: I don't think there's any universe in which China was going to invade Taiwan. The most interesting thing I think that's gone unreported in all this, and obviously lots of things have to go unreported because the war is that important. It's crowding out a lot of things.","offset":2614,"duration":12},{"text":"Jacob Shapiro: But before the war started, you had a huge diplomatic dust-up between Japan and China. The Takeichi government really pushing China's buttons on Taiwan and some of these things.","offset":2626,"duration":10},{"text":"Jacob Shapiro: And Japan has been deploying long-range missiles and military capacity to places that China doesn't like. And so China has announced, \"Oh, okay. Well now for the next 40 days, we're going to be controlling airspace in areas of the East China Sea as we do some things that we're not going to tell you about.\"","offset":2636,"duration":15},{"text":"Jacob Shapiro: So some interesting friction back and forth there between China and Japan. So there are things to watch for. I'm not saying that China is some benevolent power that isn't scheming here, but they are scheming to take Taiwan by not firing a shot.","offset":2651,"duration":12},{"text":"Jacob Shapiro: And ironically, everything the United States is doing is helping that future come into being. But I think China's watching, you know, Russia's failed attempt to take Ukraine, the US's failed attempt at least thus far to, you know, change the regime in Iran and saying, \"Okay, well why would we try to do something that's orders of magnitude harder, which is an amphibious invasion of a hardened island that, you know, we're not going to be able to take without destroying the things that make it valuable in the first place.\" Like I just don't think China thinks that—thinks strategically that way. I think they're thinking longer term.","offset":2663,"duration":33},{"text":"Host: Yeah, I mean, yeah, seems like the easy narrative is that China's always just thinking longer term. But I—but I am curious...","offset":2696,"duration":4},{"text":"Host: What about, like, the next couple years? Like right now, you know, is their main priority just, you know, what's the quote again? Of, you know, \"don't interrupt your enemy when they're making a mistake.\" Are they just kind of sitting by the sidelines and just watching this all happen? And they're like, \"Well, you know, eventually this is just going to make... it's probably going to make it easier for us in one form or another, not sure how, but I'm just going to wait for the dust to settle.\" What do you think?","offset":2700,"duration":22},{"text":"Jacob: There's a couple ways I would answer that question. The first is, even though China really is only communist in name and form, like China's economic policies are not communist, they're sort of a weird state capitalism, like authoritarianism plus Ronald Reagan supply-side reforms in a weird bastardization together, but the form of Chinese politics is still very Marxist and very communist.","offset":2722,"duration":22},{"text":"Jacob: And if you've been raised as a Marxist, um, then you look at the United States and say, \"Oh, this is late-stage capitalism. This is the late-stage capitalist hegemon basically destroying itself.\" So to your point, why would we want to get in the way of that? I think Xi Jinping also realized, um, towards the end of the 2010s and into the early 2020s that he made a mistake.","offset":2744,"duration":24},{"text":"Jacob: He thought China was stronger maybe than it was. You had the wolf warrior diplomacy happening all over the place and China starting to, uh, bare its teeth a little bit. Um, and I think he was able to walk that back and see that China wasn't quite ready for that. That China needed to be more accommodating, that it needed to be a pragmatic partner, and that there was actually an opportunity in US political volatility and instability to be that.","offset":2768,"duration":25},{"text":"Jacob: And it's been very successful over the past couple of years. Uh, remember the biggest geopolitical story of this year before the war, um, was not Venezuela, it was not Greenland, it was Mark Carney going to Davos and saying, \"I'm taking the sign out of the window. I think China's a more reliable partner right now than the United States is. And we have to think about Canadian national self-interest in that context.\"","offset":2793,"duration":22},{"text":"Jacob: That's a huge diplomatic win for China, that it has been able to seem more stable and more accommodating in a global international political system to a country like Canada than the United States. I think that's a very important signal. So, China's not without mistakes, and it's a huge and arguably sclerotic bureaucratic authoritarian system, so it can and will make more mistakes.","offset":2815,"duration":24},{"text":"Jacob: But I think you've definitely seen a shift in Chinese policy, uh, from the wolf warriors at the end of the 2010s to right now, which is to your point, hey, how can we work with some of these other countries? How can we figure out a way, um, to create these economic relationships with them that are not tied to political ideology, that are not tied to overt asks, that don't involve us raising tariffs or threatening to do things against countries who don't do the things that we want? I think that's working for them, and I think that's what they'll continue to do here going forward.","offset":2839,"duration":30}],"startTime":2418},{"title":"Long-Term Optimism and the Energy Transition","summary":"Concluding on an optimistic note, Jacob compares the current era to the 1890s, a period of massive technological and energy transformation. He advises macro investors to focus on AI, automation, and the shift toward deflationary energy sources.","entries":[{"text":"Host: Awesome. Um, alright, we'll just kind of conclude here with just your final parting words or thoughts or recommendations for, for those of us like myself who are, you know, mostly focused on, on macro trading and we are, we are self-admitted tourists within this space and just trying to figure out what the hell is going on. Any final words on how to navigate this whole thing?","offset":2869,"duration":22},{"text":"Jacob: The, the last thing I would just say, and I know it's, I know it probably sounds silly to say this, like, 47 minutes into our conversation, um, but I'm still very optimistic about the global economy over the next five to ten years. I think a lot of the dynamics that we're talking about, they will be bad for some people, they will be great for others. They will be bad for some industries, they will be transformative for others.","offset":2891,"duration":24},{"text":"Jacob: I think there's a lot of comparison out there, uh, between our current time and the 1930s, uh, for folks that are thinking, \"Oh my god, like, we're on the cusp of another World War.\" I don't think that at all. I, I think the right frame of reference, and it's not a perfect historical analogy, but is the 1890s because you had rising and falling great powers. You had, uh, a generational shift in energy from coal to oil.","offset":2915,"duration":26},{"text":"Jacob: Um, you had technological innovation, you had the rollout of electricity over a 20 to 30 year time horizon, which changed everything. You had the advent of modern fertilizers, which for the first time disconnected population growth from just how much you could grow in your own regional market. Um, it was an absolutely transformative time. Now, at the end of that period, yes, there was a World War because some countries got powerful enough that they thought that they could dominate the world, or there were these weird alliance structures that forced things into a, a structure.","offset":2941,"duration":30},{"text":"Jacob: And by the way, that was a war where nobody thought that war was going to last for four years, everybody thought it was going to be a short conflict, and then once they were in it, they all had to triple, quadruple down. Um, sound familiar to you? Anyway. My point is just that I think we're on the cusp of the 1890s. So, I have to keep in touch with everything that's going on in the headlines on a daily basis.","offset":2971,"duration":23},{"text":"Jacob: I find it truly annoying because the real stuff is happening in technological innovation. What is AI doing? How is it transforming our lives? How is it transforming productivity? What is next with robotics? What is next with automation? What is next with Internet of Things? Changing everything. I want to spend all of my brain power doing that, not on parsing IRGC propaganda or White House propaganda.","offset":2994,"duration":24},{"text":"Jacob: The energy transition is real, and it's not going to be like the switch from coal to oil. That's a lay-up, like, I wish I had been, you know, investing in the 1890s and I could have been like, \"Yes, buy shares of Standard Oil and then we will go to golf and not touch them for another 60 years,\" like, probably would have been the best trade ever, right? But we're not going from oil to something else, we're going from oil to everything else.","offset":3018,"duration":23},{"text":"Jacob: So does that mean that you invest in the energy technologies themselves? Does that mean you invest in the picks and shovels that build the energy themselves? Is this a story about electrification and the grid and everything that it has to do to support this? Is it all the above? Is it really just you want the companies that are going to benefit from, and it's hard to think about this in 2026, but cheaper energy?","offset":3041,"duration":20},{"text":"Jacob: Because by 2030, 2035, probably energy is deflationary, no matter what's happening in the Strait of Hormuz. That's something I want to spend my time talking about. Um, so, you know, you can get wrapped up in everything that's happening in headlines and you can't ignore it because if you ignore it, you ignore potential challenges to those theses or data points that you really need in terms to update that.","offset":3061,"duration":23},{"text":"Jacob: But I, I am sticking to my guns and I would encourage your listeners to stick to their guns. Develop a macro viewpoint, uh, create scenarios for that, and then start to see is this true or is there or is this not true? Even with all the doom and gloom that I've talked about here, I'm optimistic. I'm looking for opportunities to deploy capital in technological innovation, in the energy revolution, in electrification, uh, and in the recession of US global power into a multipolar world and the markets that are best-posed to benefit from that. That's what I do when I'm not forced to talk about whatever strange things are happening in the Middle East.","offset":3084,"duration":41},{"text":"Host: Boom. Very well said. I, yeah, could not agree more with that. Um, yeah, I feel like the thing I, I keep trying to remind myself, I don't know if you agree with this or not, is that look, despite everything going on, all these shortages, like, don't short human ingenuity and, you know, all shortages are followed by gluts is something that I've heard talked about. I don't know if you agree with that or not, but it just feels like interesting framing to at least try to anchor yourself to what's going to happen on the 5 to 10 year horizon here.","offset":3125,"duration":27},{"text":"Jacob: Yeah, I mean, I, I always... uh, I like Jimmy Carr, the, the comedian, and he had some... somebody asked him some question about optimism in the current world, and he had this great... he had this great answer. He was like, \"You know, 100 years ago, nobody really knew what a hot shower was. Like, just, like, you get hot showers all... like, we live in a world, like, I can go to my TV right now and stream anything I want in the entire world, and I can order some, you know, chicken wings on my phone to my house so I can eat them while I'm watching whatever I want on my TV.\"","offset":3152,"duration":25},{"text":"Jacob: I was talking to Claude earlier about, like, taking everything I've written for the last 20 years and putting it into a database, it's like, doing that right now. Um, I mean, life is, like, really incredible. I feel like we're, we're missing... that we're uh, actually in the good times right now.","offset":3177,"duration":17}],"startTime":2869},{"title":"Conclusion and Guest Contact Information","summary":"The host and Jacob wrap up the conversation and share final thoughts. Jacob provides his website and contact information for listeners interested in following his geopolitical research.","entries":[{"text":"Host: Yeah. Couldn't agree more. Awesome, Jacob. Well, uh, where can folks go if they want to see more of your work and what you got going on?","offset":3194,"duration":6},{"text":"Jacob: Pretty simple. Just go to jacobshapiro.com or you can email me at jacob@jacobshapiro.com. There's the podcast, research, speaking, um, and maybe doing some interesting things, uh, sort of in-between things when it comes to investment, but but cooking on some things there. So, follow me there and and you'll see where the journey goes.","offset":3200,"duration":19},{"text":"Host: Awesome. Love it. Well, thanks for joining on here and giving us the geopolitical update. Appreciate it.","offset":3219,"duration":5},{"text":"Jacob: It's my pleasure, and we'll have to get, uh, cousin Marko on either individually or maybe we'll, uh, we'll force ourselves, the both of you, uh, on you. I'm not sure your hair will be able to handle...","offset":3224,"duration":9},{"text":"Host: That would be... that would be unreal. I, I would love that. Yeah. My hair will probably be on fire afterwards, but I'll just be a vessel for it and just enjoy the ride. But that would be awesome.","offset":3233,"duration":9},{"text":"Jacob: Yeah. Sounds good. Cheers.","offset":3242,"duration":2},{"text":"Host: Thank you.","offset":3244,"duration":15}],"startTime":3194}],"entries":[{"text":"Jacob Shapiro: It literally did not come into my imagination that this would be a longer war, that this would be a war for longer than three to four weeks, because the asymmetry of the advantages here go in Iran's favor. But all that really matters right now is how many ships are going in and out of the strait.","offset":0,"duration":13},{"text":"Jacob Shapiro: Physical shortages are starting to show up in East Asian economies. And if we keep going on this path, if we are still here in a month talking about this, we'll be talking about those shortages moving from East Asia to Europe, even to the Western Hemisphere.","offset":13,"duration":12},{"text":"Jacob Shapiro: There's a scenario here where maybe President Trump talks tomorrow or in the next week or two, and yet the disruptions that we're talking about are only just beginning because the global supply chain disruptions will move from a conversation about the Strait of Hormuz to what Ukraine is doing to Russia.","offset":25,"duration":18},{"text":"Jacob Shapiro: So it's an acceleration of deglobalization, it's an acceleration of multipolarity. You are looking for those places in the world that are on a relative basis will perform better when there is an energy choke point disruption.","offset":43,"duration":8},{"text":"Jacob Shapiro: Certainty and stability will not be coming from Washington or will not be guaranteed by Washington going forward. It's the end of an era. But it seems to me that the best case scenario coming out of all this is...","offset":51,"duration":12},{"text":"Host: Nothing said on Forward Guidance is a recommendation to buy or sell any investments or products. This podcast is for informational purposes only, and the views expressed by NOM on the show are solely their opinions, not financial advice or necessarily the views of Blockworks.","offset":63,"duration":7},{"text":"Host: Our hosts, guests, and the Blockworks team may hold positions in the companies, funds, or projects discussed. As always, investments and blockchain technology involve risk. Terms and conditions apply. Do your own research.","offset":70,"duration":26},{"text":"Host: All right everybody, welcome back to another episode of Forward Guidance. And joining me this week is Jacob Shapiro, independent geopolitical analyst, as well as the host of the Jacob Shapiro podcast and Geopolitical Cousins, which is by far my favorite geopolitical podcast.","offset":96,"duration":10},{"text":"Host: I do not miss an episode. You and Marco are just awesome. Reminds me a lot of what I do on the Roundup every week with the other co-hosts Quinn and Tyler, where we just chop it up, banter, and try to navigate the endless headlines. So super excited to have you on.","offset":106,"duration":16},{"text":"Host: You know, it's always funny when—it would be interesting to look at the correlation of when geopolitical experts come on podcasts versus like the degree of, I don't know, shit hitting the fan in the world. I'm sure it's just—I'm sure you've looked at it before, but it's always interesting. But yeah, excited to have you on the show, Jacob.","offset":122,"duration":16},{"text":"Jacob Shapiro: Thanks for having me. I don't know that I can promise much guidance, but it can certainly be forward. And yeah, I find that the pace of—I mean, obviously the last month has been nuts, but really ever since Russia invaded Ukraine, it feels like it has not let up in terms of being asked to come on and speak to either audiences or to do interviews. Like that was, that was definitely the moment where the world woke up and said, \"Geopolitics is back.\"","offset":138,"duration":26},{"text":"Host: Yeah, yeah, 100%. Geopolitics is back. And back more than ever right now over the last month. So obviously the topic du jour is Iran and everything going on there and the Strait of Hormuz.","offset":164,"duration":12},{"text":"Host: Would love for for those that just have not been as tuned into how you've been thinking about this crisis and the development of it. If you could just walk through your initial framework going into the initial strikes day in February, and then just how the sequence of events have evolved and how your framework has evolved up to basically now the first week of April.","offset":176,"duration":14},{"text":"Jacob Shapiro: Yeah, I'll try to make this succinct, and if I'm failing, I hope you will, you know, get the hook in here and get me off or tell me to be quiet. And I'll also just give you by way of background, I'm a global analyst now, and I'm especially in the last couple of years have been directly tying geopolitical analysis to active investing and investment positions and things like that.","offset":190,"duration":22},{"text":"Jacob Shapiro: But I cut my teeth as a Middle East analyst. My academic training is in the Middle East, my languages expertise is all in the Middle East. And it's always been funny to me that as a geopolitical analyst, in some sense the Middle East—I think I certainly analyze it and understand it well.","offset":212,"duration":16},{"text":"Jacob Shapiro: From a predictive standpoint, it's—by far my worst region. And I think there's something to be said for knowing too much about a thing. It puts you too close to the action, you're almost too smart for your own good. You can't get that same degree of global macro when you're too attached to it.","offset":228,"duration":18},{"text":"Jacob Shapiro: Which is my way of excusing myself for thinking I didn't think that the United States was going to undertake this war. I didn't think that because I thought they knew that the implications would be, well, I didn't even think catastrophic. I thought that they knew that it would be a short-term war and that they probably wouldn't be able to achieve their objectives.","offset":246,"duration":13},{"text":"Jacob Shapiro: It literally did not come into my imagination that this would be a longer war, that this would be a war for longer than three to four weeks, because the asymmetry of the advantages here go in Iran's favor.","offset":259,"duration":12},{"text":"Jacob Shapiro: For the first two or three weeks, the United States and Israel together lit up Iran, and it was all about firepower, epic fury. I'm old enough to remember when we did this in the second Gulf War. That was the period of the war that was always going to be very successful and very impressive for the United States military.","offset":271,"duration":16},{"text":"Jacob Shapiro: But two to three weeks in, then Iran's asymmetric advantages start to assert themselves. Their first and most important advantage is the Strait of Hormuz, is geography. And unless the United States has invented a weapon that separates Iran from control of the Strait of Hormuz, you can have all the shiny weapons you want and blow up all the power plants you want.","offset":287,"duration":20},{"text":"Jacob Shapiro: You're going to be fighting with a power that can upend the global economy by saying no ship shall go through the strait, which is exactly kind of what we're living through right this moment.","offset":307,"duration":9},{"text":"Jacob Shapiro: And then the second asymmetric advantage, and this is something we already saw with Russia and Ukraine, we saw it with the Houthis being able to resist the United States and block shipping through the Red Sea. We've seen it in all kinds of conflicts in recent years.","offset":316,"duration":11},{"text":"Jacob Shapiro: The United States may have very fancy interceptors and F-35s and all sorts of things that cost all amounts of money to develop. The Iranians have relatively, by comparison, unsophisticated rockets and missiles and drones and they cost far less.","offset":327,"duration":16},{"text":"Jacob Shapiro: And they can deploy much higher numbers of these things versus very fancy and expensive US military hardware where you get to the point where they're now beginning to see more bang for their buck or their rial or their yuan or Bitcoin, whatever you want to throw in there.","offset":343,"duration":15},{"text":"Jacob Shapiro: They're getting more bang for their buck because we've exhausted a lot of those higher-end things and they can just keep throwing out the cheap stuff. And that means that even as you decimate their navy and their air force and their launchers, as long as they've got a certain capacity left and people willing to fire them, they're going to keep firing.","offset":358,"duration":16},{"text":"Jacob Shapiro: And you're seeing that happen in real time right now. So that's a big intro by way of saying that I didn't think this was going to happen because I thought the United States had learned from previous mistakes.","offset":374,"duration":10},{"text":"Jacob Shapiro: I also took President Trump—my bad—at his word that this was a guy who campaigned on not going into wars in the Middle East and wasting trillions of dollars on American lives on fools' errands in the Middle East. And he got me, the bait and switch is on.","offset":384,"duration":12},{"text":"Jacob Shapiro: And it's, nope, it's war in the Middle East and this is absolutely critical. And by the way, the last thing I'd just say is, you know, second Iraq war at least you had the excuse of US energy insecurity being the geopolitical reasoning behind it.","offset":396,"duration":15},{"text":"Jacob Shapiro: There's no reason for the United States to be messing around the Strait of Hormuz. Since the shale revolution, the United States is a net exporter of crude, it's been keeping the lights on in Europe by exporting LNG. Yes, there are still global economic exposures based on the things that are blocked out of the Strait of Hormuz, but there's no compelling reason to be obsessed with Persian Gulf oil if you're the United States, which took another geopolitical reason off the board to engage in this conflict.","offset":411,"duration":17},{"text":"Jacob Shapiro: But yet, it's April 6th, the war's been going on for, what, five, six weeks now, and we're 24 hours from a Trump taco or from Trump obliterating the country or something in between. So there we are.","offset":428,"duration":15},{"text":"Host: There we are. Okay, that's a great foundation. I want to move in and isolate towards understanding what are the actual important things to look at for economic slash market consequences.","offset":443,"duration":11},{"text":"Host: So you mentioned how you are very focused on understanding how to track these geopolitical events and in moving them towards some sort of tangible investment frameworks or macro analysis. Obviously this is a macro podcast, so the number one question I think that people listening to this are trying to figure out is: Okay, there's a million headlines a day right now, some of them move markets, some of them don't. There's a lot of stuff moving in a lot of different parts here. How do you isolate into the things that are actually meaningful towards global macroeconomics and markets?","offset":454,"duration":31},{"text":"Jacob Shapiro: Yeah, I want to answer that question in two ways. The first is at a—is at a macro time horizon. And when I say macro time horizon, I mean over a three to five year time horizon. So I did not think the United States was going to invade Iran, but from a positional perspective, I'm doing okay because I was long energy, I was long fertilizer, I was long food.","offset":485,"duration":21},{"text":"Jacob Shapiro: Like all of the things that are being affected by this, I was long for other reasons entirely, which tells you that this is exacerbating those things. It's making things move more quickly than I expected. But if anything, it's an accelerant, it's not a disruptor in that sense.","offset":506,"duration":13},{"text":"Jacob Shapiro: We were already moving towards deglobalization. We were already moving towards multipolarity of supply chains. We were already seeing the securitization of things like food and semiconductors and feedstocks.","offset":519,"duration":13},{"text":"Jacob Shapiro: All these things becoming part of the conversation about national security and countries that can protect those supply chains or make themselves self-sufficient in them, you were seeing those moves anyway.","offset":532,"duration":7},{"text":"Jacob Shapiro: And so I think over a three to five year time horizon, all that's happened is an acceleration of those trends that we were already watching. So it's an acceleration of deglobalization, it's an acceleration of multipolarity. You are looking for those places in the world that are on a relative basis will perform better when there is an energy choke point disruption in the Middle East, or who are going to perform better when there is—when there are rising food prices.","offset":539,"duration":22},{"text":"Jacob Shapiro: And conversely, you're also looking for those markets and countries that are not going to perform well. The countries that are able to assure cheap supply and secure supply of energy, cheap and secure supply of food, and are able to invest in the cutting edge of technology. Those are your countries that are going to be net winners over a three to five year time horizon. We could talk about those countries, those markets, those companies, verticals if you want.","offset":561,"duration":21},{"text":"Jacob Shapiro: Then there's our shorter term time horizon, which is: There's a lot of noise in the media and it's being generated by the White House, it's being generated by the IRGC, it's being generated by governments all over the place.","offset":582,"duration":11},{"text":"Jacob Shapiro: But all that really matters is how many ships are going in and out of the strait. And a week ago it was basically zero. It has ticked up a little bit in the last two to three days. Whether that is because the Iranians have this tolling system active and they are accepting payment for that, or whether it's ships that are running through because they think the Iranians can't cash the threats that they're making.","offset":593,"duration":18},{"text":"Jacob Shapiro: There's probably some combination of both there. You are seeing an uptick in the ships that are going through the Strait of Hormuz. Now, we are still at something like 20% of what is normal. So don't think for a second that this is normalized.","offset":611,"duration":13},{"text":"Jacob Shapiro: And don't think for a second, by the way, that we have up-to-date information on the damage that has already been done to infrastructure in the region. Let's say the war stopped in an hour. The first thing I want to know is: Okay, how damaged are the LNG facilities in Qatar? How damaged are the gas fields in Iran and some of these other places?","offset":624,"duration":17},{"text":"Jacob Shapiro: How long will it take to fix these things? Are we talking about turbines that have to be reordered, or are we talking about fixes that can happen on a time span of months? So there just is a lot of uncertainty that we're dealing with there. And I think the market is communicating that uncertainty to you in a bit.","offset":641,"duration":14},{"text":"Jacob Shapiro: Markets have been sanguine and almost delusional from my perspective. The disconnect between markets and the physical economies has never been more obvious, because the physical economy, especially in places that were over—overdependent on the region for a lot of these things.","offset":655,"duration":14},{"text":"Jacob Shapiro: The physical economies are starting to show the cracks. I mean, physical shortages are starting to show up in East Asian economies. And if we keep going on this path, if we are still here in a month talking about this, we'll be talking about those shortages moving from East Asia to Europe, even to the Western Hemisphere for all of the talk about US energy self-sufficiency as well.","offset":669,"duration":22},{"text":"Jacob Shapiro: So at the long-term perspective, you have to have that macro model about where the world is moving. Mine is multipolarity. There are others out there. And then for the short term, it's really just are ships going in and out of the strait. Period. And those are the things that I'm trying to keep my mind on at the same time.","offset":691,"duration":16},{"text":"Host: Yeah, 100%. I totally agree that the main vector to look at is counting ships. And it's an interesting one when I look at how the market has been digesting that idea over the last few weeks.","offset":707,"duration":11},{"text":"Host: As it feels like over the last three weeks or so there is an acceptance that there was almost no flow through the strait. And then over the past few days, I've started to see two vectors start to accelerate.","offset":718,"duration":11},{"text":"Host: One of those vectors being this idea of a dark fleet that is turning off their AIS and running the strait, whether they just had some sort of, you know, under the table agreement with Iran to let them go through. Or there's the more formal pact of what's going on with, say, you know, what you would assume are US allies, like France, have struck a deal with Iran to be able to start to move some of their oil through.","offset":729,"duration":20},{"text":"Host: So I'm curious: How do you think about those two vectors and how do you discount the validity or just quantify how to measure those?","offset":749,"duration":9},{"text":"Jacob Shapiro: It's really difficult and I'm not brave enough to go to the strait myself and test some of these things against each other. But you have reputable sources that are saying that at least some ships are paying a toll, and that they're paying the toll in yuan to get through.","offset":758,"duration":15},{"text":"Jacob Shapiro: And that the IRGC has a system for doing this, that they have country rankings based on how close they are to the United States or how Iran views their relationships with that country, and that affects the fee that you have to pay. So there are, you know, open-source reports from reputable sources that say that is happening.","offset":773,"duration":16},{"text":"Jacob Shapiro: Now, you have to take everything with a grain of salt here because it's the fog of war, but that's happening. Then you also, to your point, have reports about, you know, ships that are just running—are making a run for it. And they're getting through. Is that a testament to their bravery?","offset":789,"duration":12},{"text":"Jacob Shapiro: Is that because to your point they have a tacit understanding that the IRGC is not going to go after them at this point in time? Maybe they can't. Maybe they're focused on other things. Okay, like all open questions here.","offset":801,"duration":14},{"text":"Jacob Shapiro: But yeah, I don't have a solid answer for you. Like we have to be comfortable I think with the uncertainty. But it seems to me that the best case scenario coming out of all this is some type of tolling structure, whether it's wholly Iran or whether it's some kind of Iran-GCC combo toll, that returns certainty to transiting the Strait of Hormuz.","offset":815,"duration":21},{"text":"Jacob Shapiro: And it's crazy to me because that means the best case scenario we're talking about is: You're no longer thinking that the United States Navy is there to guarantee global shipping lanes and maritime choke points.","offset":836,"duration":12},{"text":"Jacob Shapiro: You want there to be some kind of localized tolling facility, even if it's with the ayatollahs of Iran, a group of not particularly nice people. Like you'd rather know, \"Okay, this is what I pay, this is what I do, and I get through the Strait of Hormuz.\" Like certainty and stability is what's going to be the best case scenario coming out of this.","offset":848,"duration":15},{"text":"Jacob Shapiro: And that certainty and stability will not be coming from Washington or will not be guaranteed by Washington going forward. And for some countries I guess that'll be good, but for most of the world and for the United States, which has profited off of US-led and protected globalization, it's the end of an era in some sense.","offset":863,"duration":18},{"text":"Host: Mm-hmm. Yeah, I think that's a great point and just to zoom out into this secular trend that you mentioned of deglobalization and multipolarity is: Okay, you have this basis that the Strait of Hormuz has had this degree of security guarantees from the overall American apparatus for decades now.","offset":881,"duration":19},{"text":"Host: And that apparatus and those security guarantees are on the margin moving away. And then we have to figure out and discount: Okay, how much is it going to move towards this new world where Iran is the one or maybe in some sort of agreement with Oman, they're the ones running the toll booth now?","offset":900,"duration":13},{"text":"Host: And pairing that with who are actually dependent on the strait, which is, i.e., you know, Europe and they have to decide who do they align with, and then also East Asian markets and who they have to decide who to align with.","offset":913,"duration":13},{"text":"Host: And I'm curious about how you're thinking about how all these different countries net out. Because again, there's—you know, there's been interesting stuff what's been going on with the UN Security Council this week where you had them trying to vote about whether to intervene with outright force or not.","offset":926,"duration":16},{"text":"Host: And you saw actually, you know, France aligning with China and Russia for example. So these traditional lines of, you know, the West versus the East or however you want to define it just don't seem as consistent anymore. So I'm just curious: How do you see this whole framing net out over the next few years? It just seems completely convoluted.","offset":942,"duration":17},{"text":"Jacob Shapiro: Yeah, well first things first, like who cares what the United Nations says. I mean, it's like the Dave Chappelle Black Bush sketch, like \"Sanction me! Sanction me with your army! Oh, you don't have an army! Okay, cool.\" So I don't really care what the UN says.","offset":959,"duration":13},{"text":"Jacob Shapiro: No, I think here we also have to widen the aperture a little bit because the Russia-Ukraine war is also ongoing. And one of the things that has made me more optimistic in a multipolar world is that I expected you would get these types of small regional conflicts, but that they would be relatively self-contained.","offset":972,"duration":17},{"text":"Jacob Shapiro: So the Russia-Ukraine war, despite—you know—myriad articles written about the beginning of World War III, it's a Russia-Ukraine war. It's a war between those two actors. Yes, some countries are supporting the other side with weapons, but it's Russian soldiers, Ukrainian soldiers, and those poor North Koreans that the Russians imported.","offset":989,"duration":16},{"text":"Jacob Shapiro: One of the things that's different about this conflict is you're starting to see the bleed over. And this is something I don't think markets have really quite gotten through their head. Because Ukraine is watching everything that's happening in the Strait of Hormuz, and I imagine that Zelenskyy—you know—I'm imagining here, I don't—I don't know this for sure.","offset":1005,"duration":14},{"text":"Jacob Shapiro: But I imagine Zelenskyy's watching the situation and watching Iran's asymmetric—asymmetric advantage work and thinking to himself, \"Oh, if I can affect the global price of oil or petrochemical supply chains or things like that, people will listen to me even if I'm being blown up by the United States and Israel, even though my air force is gone and everything else like that.\"","offset":1019,"duration":19},{"text":"Jacob Shapiro: \"Cool. So instead of hitting Russian energy infrastructure that makes life harder for the everyday Russian citizen,\" which is what Ukraine has been doing for the past 12 months, trying to drive up the price of gasoline for the average Russian consumer, hitting that infrastructure.","offset":1038,"duration":13},{"text":"Jacob Shapiro: \"I'm going to go after Russian oil export infrastructure. I'm going to go after Russian petrochemical export infrastructure because then maybe people will start listening to what I want.\"","offset":1051,"duration":11},{"text":"Jacob Shapiro: \"I also don't want Vladimir Putin to profit from higher oil prices. I don't want the Europeans to hang me out to dry by having to go back to Moscow and saying, 'We really don't like you, but we kind of need your oil and natural gas and fertilizers and everything else again. So let's let bygones be bygones and we'll try and muzzle the Ukrainians and threaten support and things like that.'\"","offset":1062,"duration":17},{"text":"Jacob Shapiro: All of which is to say this now goes from Russia—excuse me—Israel-US versus Iran with some GCC states game theory into also Russia versus Ukraine and the powers that are on either side of that.","offset":1079,"duration":15},{"text":"Jacob Shapiro: And it just starts to get unwieldy when you think about all the different circumstances that are there. So yeah, I mean, there is a—there is a scenario here where maybe President Trump talks tomorrow or in the next week or two, and yet the disruptions that we're talking about are only just beginning because the global supply chain disruptions will move from a conversation about the Strait of Hormuz to what Ukraine is doing to Russia and what that means in general.","offset":1094,"duration":24},{"text":"Jacob Shapiro: And then just layer on top of that—I'm not usually a doomer here, but it's very hard not to at least engage in the doomer scenarios to be ready for them. I mean, let's say all that's happening and then it's hurricane season in the United States, and what if a hurricane, you know, hits the Gulf and some capacity of US exports goes offline?","offset":1118,"duration":18},{"text":"Jacob Shapiro: Like we don't even have to do anything nefarious about cyberattacks or electromagnetic pulses or all the crazy things that the doomers want to do. Let's just say it's a weather formation and a storm knocks off some percentage of US exports.","offset":1136,"duration":11},{"text":"Jacob Shapiro: Now you're dealing with a global economy where things are already very lean, everybody's already on edge, and that one sort of bastion of supply that is far away from the geopolitical conflict gets hit. Okay, and now we're off to the races.","offset":1147,"duration":14},{"text":"Jacob Shapiro: So just every single one of these things increases the brittleness of global supply chains. And that's a story that we've—you know—I've also been tracking for quite some time as well. So that's how I would think about widening the aperture and thinking about international interest. Certainly don't think about what the UN has to say. They have no power here.","offset":1161,"duration":17},{"text":"Host: That's super helpful. Okay, yeah, I do want to ratchet down one level towards those specific supply chains and understand and map out.","offset":1178,"duration":8},{"text":"Host: You know, I feel like just as a general tourist to this space and trying to read the news articles and understand what's going on, a lot of headlines are really focused on the price of oil and less so on some of these more downstream impacts, whether it's the fertilizer market or helium and the LNG space and things like that.","offset":1186,"duration":17},{"text":"Host: So I'm just curious if you could just map out for us when you look at these different lists of supply chain issues, which ones do you feel like are rightly an issue? Which ones do you feel like are not being paid enough attention to? And yeah, like which ones are you most concerned about here?","offset":1203,"duration":17},{"text":"Jacob Shapiro: Yeah, um, I mean, it's impossible to map them all out without putting listeners to sleep. But let's sort of talk about some of the big categories. The big ones. Because even in a crisis, like supply chains are for nerds. Like this is—you don't go into college being like, \"I'm going to be an expert on supply chains.\"","offset":1220,"duration":17},{"text":"Jacob Shapiro: Oil, look, oil's important. In some ways, it's the one that I'm least worried about, not least because you have countries with strategic reserves. Four to five million barrels per day are crossing that pipeline and getting out through Yanbu, at least for now.","offset":1237,"duration":14},{"text":"Jacob Shapiro: If the Houthis get involved and if the Red Sea is shut, okay, like we can—we can start sounding the alarm there. I certainly think we'll see elevated oil prices through the end of the year. But in some sense, like that's the one that maybe I'm least worried about.","offset":1251,"duration":12},{"text":"Jacob Shapiro: LNG is a—is different because you're not piping LNG to Yanbu across—across the desert. And Europe really—like Europe was depending on access to all the LNG capacity coming online out of this.","offset":1263,"duration":16},{"text":"Jacob Shapiro: That's how they were going to balance the lack of supply that was coming from Russia. And that doesn't mean that the Europeans are going to go cold in the winter. What it means is they're going to pay higher spot prices for these things, even if it's from China rerouting some of what they're getting over there.","offset":1279,"duration":13},{"text":"Jacob Shapiro: And that means your emerging markets that were betting that they were going to have access to some of this LNG are going to have to start scrambling themselves, whether that's, you know, coal or what Pakistan has done with solar in the last couple of years. They're the ones that are going to be scrambling, that are going to be hurt the worst.","offset":1292,"duration":17},{"text":"Jacob Shapiro: Fertilizer's a big deal. Fertilizer is another one of these very lean supply chains where you don't have strategic fertilizer reserves. Fertilizer's really only relevant one or two times a year based on when farmers are planting and when they need the fertilizer.","offset":1309,"duration":12},{"text":"Jacob Shapiro: And so that's when the supply chain is there for them. We already missed the window for many farmers throughout the world to apply fertilizer. So you can book in now lower yields in many parts of the world and rising food prices in those parts of the world.","offset":1321,"duration":15},{"text":"Jacob Shapiro: And we won't know the full impact of that from six to nine months till now. But just a reminder that the Arab Spring began with rising food prices in the Middle East. It was a Tunisian vegetable salesman who self-immolated that started the Arab Spring because food prices were too high and because that vegetable salesman didn't feel like they could make a living and then they got insulted by police and we were off to the races.","offset":1336,"duration":15},{"text":"Jacob Shapiro: Um, so I think that potential six to nine months down the road in emerging markets for thinking about some of that type of political disruption, that's there and that ties directly to fertilizer. And then the last major category is the petrochemical complex.","offset":1351,"duration":14},{"text":"Jacob Shapiro: And that spans everything from, you know, boring things like plastic and plastics and resins to higher value input things like helium that you're talking about that are critical for semiconductor manufacturing.","offset":1365,"duration":13},{"text":"Jacob Shapiro: And, I mean, this is still a thesis that I'm building, but in some sense I'm less worried about things like helium because helium's important enough that there are strategic reserves out there. And at least the reporting I've seen and my contacts in the space seem to be—I mean, optimistic is the wrong point of view—but not freaking out.","offset":1378,"duration":16},{"text":"Jacob Shapiro: In my Rolodex, the folks that are freaking out are those ones for those mid-to-lower tier petrochemical products that you would think are boring, like the plastic that's in everything in your life, which you're seeing doubling and tripling of prices.","offset":1394,"duration":15},{"text":"Jacob Shapiro: Or you're seeing companies that are saying, \"I just can't get it. Like it's not available for any price, or I have to go to China or I have to go to some weird place before that maybe that's going to run afoul of global sanctions in order to—in order to get it.\"","offset":1409,"duration":12},{"text":"Jacob Shapiro: And that again is—these are products for which there's no strategic reserve. Nobody was sitting there being like, \"Yeah, I need a strategic plastic polymer reserve because I need to make sure that I have plastics that I can wrap the food in that I'm selling at the grocery store.\"","offset":1421,"duration":12},{"text":"Jacob Shapiro: But that's where it's going to start showing up, because those are the things where things are very lean. And by the way, like the whatever you think about globalization and free trade, we could argue till we're blue in the face: Is it good, is it bad?","offset":1433,"duration":11},{"text":"Jacob Shapiro: The thing about free trade, the thing that makes it efficient, that the bulls will say about free trade is, yeah, that's exactly how it's supposed to work. You produce what you need, when you need it, for the cheapest price possible, in the geographies that are most optimized for that production.","offset":1444,"duration":15},{"text":"Jacob Shapiro: And that's the way a lot of supply chains are. Even though the world is moving multipolar, lots of supply chains still function like it's a globalized world. So when you have this kind of crisis and this level of supply chain disruption, you're dealing with supply chains that are expecting a perfect globalized free trade world of the 1990s.","offset":1459,"duration":15},{"text":"Jacob Shapiro: And instead they're getting this version of multipolarity and regional warfare and return of great power politics of 2026. Now, those supply chains will change. Trade is like water, it will find cracks, it will figure out the way it needs to get from Point A to Point B.","offset":1474,"duration":15},{"text":"Jacob Shapiro: But just like water, water can be very destructive when it's trying to find those cracks. Levees can break, walls can crash down, you can inundate entire areas as those things try and get from Point A to Point B.","offset":1489,"duration":10},{"text":"Jacob Shapiro: And usually it's your emerging markets, your countries that have lower buffers, that don't have strategic reserves, that are already constrained from a fiscal position. Those are the countries that are going to be front and center, and then you'll get relative degrees of pain depending on where you are and what your self-sufficiency is. So that's—that's my best way of trying to very succinctly putting a bow around global supply chains and which ones are affected.","offset":1499,"duration":22},{"text":"Host: Before you place a trade, you should know who is actually moving the market. That's where Arkham comes in. Arkham is a crypto intelligence platform and exchange that lets you see real on-chain data, which wallets are buying, selling, and moving funds, and then trade directly on that information.","offset":1521,"duration":15},{"text":"Host: Arkham was built to make blockchains human readable. Instead of raw transaction data, you get clear profiles, visualizers, and custom dashboards that show what's really happening beneath the surface. Tracking wallets and fund flows is becoming just as important as technical or fundamental analysis.","offset":1536,"duration":15},{"text":"Host: On-chain intelligence is also one of the best tools traders have to protect themselves against hacks, rugs, and scams. With Arkham Exchange, you can go from insight to execution in one place: the world's first exchange powered by crypto intelligence. Check out Arkham and start trading with real on-chain insight at arkham.com.","offset":1551,"duration":18},{"text":"Host: Blockworks co-founder Michael Ippolito here. Quick break to talk about something we've just launched: Blockworks Investor Relations. As the market shifts toward institutional capital, investors want more transparency, more standardization, and a higher level of professionalism.","offset":1569,"duration":13},{"text":"Host: But the traditional IR model is slow, manual, and not built for how crypto works. If you're building on-chain, your data is already live, your business is already transparent. The challenge is turning that into a clear, credible story for investors. That's exactly what we're solving with Blockworks IR.","offset":1582,"duration":16},{"text":"Host: It's a single platform that brings together real-time analytics, branded investor portals, and hands-on advisory support so you can communicate what matters. If you're an on-chain business looking to level up your investor strategy, check out Blockworks Investor Relations at blockworks.com/investor-relations. All right, back to the episode.","offset":1598,"duration":19},{"text":"Host: Awesome, that's great. I don't think we put anybody to sleep there. That was compelling to myself anyway, so I'm sure everybody's still awake.","offset":1617,"duration":7},{"text":"Host: The big question that hand that comes from that for me is understanding the timeline that we have that we can work around this. You know, obviously you mentioned a lot of the really key strategic ones have those reserves associated with it, and then there's the more downstream ones that don't have any reserves associated with it.","offset":1624,"duration":16},{"text":"Host: So I'm just curious: How do you think about the timeline for how much working time we have? Or how much you—how much you think maybe the Trump and Israel are thinking about how much time they have for this operation before it's like, \"Oh crap, we're really doing some structural damage. Like, there is no inventory in these certain important assets and we're really screwed here.\" What does that timeline look like for you?","offset":1640,"duration":22},{"text":"Jacob Shapiro: Well, let's break those in two, because Israel doesn't care. Israel cares that this rival that has threatened to wipe it off the map—so I'm not ascribing a value judgment here—but Israel views Iran as an existential threat, and all it wants to see, if not regime change, then it will take chaos and obliteration. Like that is a net positive from Israel's point of view. It will deal with the economic catastrophe that comes in.","offset":1662,"duration":21},{"text":"Jacob Shapiro: Israel is a country that is relatively well-off. Ever since their discovery of offshore gas, it's removed one of their key vulnerabilities in terms of inputs, and they're actually in a pretty good position.","offset":1683,"duration":11},{"text":"Jacob Shapiro: As for the United States, I mean, this really comes down to psychoanalysis on some level and who Trump is listening to and what he thinks. Because based on what I understand, I think we're already flirting with disaster.","offset":1694,"duration":13},{"text":"Jacob Shapiro: Um, you know, I think if you're looking at most of these things, if you don't have this war wrapped up in two to three weeks, you know, you're probably talking about physical shortages for many of the things that we just talked about.","offset":1707,"duration":12},{"text":"Jacob Shapiro: And when I say two-three weeks, like you have to then assume that there is an escalation in that time period or that you don't get further damage to infrastructure that makes restarting all that much harder, which is pretty hard to imagine considering the rhetoric that is going back and forth between the sides.","offset":1719,"duration":14},{"text":"Jacob Shapiro: All of which is to say, you know, the constraints point to this being resolved two weeks ago. But President Trump has not resolved it. He's doubled down and tripled down and he's, you know, he's threatening—I mean, I forget the exact words that he used in that tweet yesterday—but I mean, just kind of insane the level of threats that he's raising against Iran.","offset":1733,"duration":18},{"text":"Jacob Shapiro: You've got a trillion and a half dollar defense budget that's coming—I mean, he's not acting like somebody who's about to throw in the towel. Now, maybe it's the art of the deal. Maybe the art of the deal is beyond me. But there's that.","offset":1751,"duration":11},{"text":"Jacob Shapiro: But yeah, if we're here two-three weeks from now talking about the same things, and you know, we could still be talking about the war and shipping has gone back not to normal, but goes back to 60-70% and the Iranians are only striking certain types of targets that are connected to Israel and the United States.","offset":1762,"duration":16},{"text":"Jacob Shapiro: Okay, like now we're talking about some kind of resumption. But yeah, I'm worried that we're already off the cliff, and even the folks I think that are pretty sober and optimistic about this would be the first to admit, \"Yeah, if we're here on May 1st and we're still talking about this, the global economy is going to be—is going to be majorly affected.\"","offset":1778,"duration":16},{"text":"Jacob Shapiro: And as for the last thing just, it is obvious to me that President Trump and this administration is thinking that the United States is safe from this because of the shale revolution and because the United States is not dependent on importing oil and LNG from the Persian Gulf.","offset":1794,"duration":15},{"text":"Jacob Shapiro: And it's just such a facile and feeble point of view. You can argue that the United States needs to Make America Great Again and nearshore or reshore all this industrial capacity back to the United States and everything else. Cool, it hasn't happened yet in the Year of Our Lord 2026, and this supply chain disruption is here right now.","offset":1809,"duration":20},{"text":"Jacob Shapiro: The United States is exposed to the global economy. And yes, maybe the United States has some fundamental factors that mean it can weather it on paper a little bit better, but Joe Biden learned just how hard it is to weather things on paper versus when people are at the gas pump and being like, \"Hey, it's five dollars to pump at the gas tank,\" or eggs have gone to this.","offset":1829,"duration":23},{"text":"Jacob Shapiro: Watching President Trump try and lecture the American public that everything's fine with the economy. I mean, he's doing the exact same thing that Biden did in 2022, which is the exact reason that we have President Trump 2.0 in the first place.","offset":1852,"duration":14},{"text":"Jacob Shapiro: All of which is to say, US politics is way more brittle than the US strategic position. We're going into the midterms. Trump is at terribly low approval ratings, and even worse for him, he's at terribly low approval ratings on his handling of the economy.","offset":1866,"duration":14},{"text":"Jacob Shapiro: No matter what people thought about him, he always got good ratings on, \"Oh, this guy is going to handle the economy better than Joe Biden or Kamala Harris or Hillary Clinton or any of these others.\" Those numbers are now where they were at for Joe Biden in 2022.","offset":1880,"duration":13},{"text":"Jacob Shapiro: Um, so at least from a domestic political constraint point of view, you would think that he would see the disaster that is coming in November and would start to change course. But it seems, you know, if I'm just doing psychoanalysis and reading what he's doing, it doesn't seem to me like it's art of the deal.","offset":1893,"duration":13},{"text":"Jacob Shapiro: It seems to me like he really believes that the tariffs worked and that America is great again and that he is presiding over the greatest—you know—economic Renaissance in the history of the country. And I'm sorry, like I'll take the other side. I don't think that's true. But I think he's operating from that standpoint.","offset":1906,"duration":14},{"text":"Host: Yeah. I mean, that's the ultimate head-scratcher is that it's—I mean, yeah, you just set to pull a polymarket look for two seconds and you're going to see that they're the polling is going to go terrible for the midterms for them. And it's just such a—it's just such a head-scratcher.","offset":1920,"duration":13},{"text":"Host: I'm curious so: Yeah, what is your—what is your framework for heading into the \"quote-unquote\" negotiations happening right now between Iran and the US via Pakistan and this—this potential deadline approach of tomorrow, so Tuesday, I think at 8 o'clock or something like that Eastern, is sort of this—this do-or-die moment for getting some sort of agreement between the two parties.","offset":1933,"duration":25},{"text":"Host: And I'm just curious like: How do you view the framework to head into that negotiation and what's actually really going on there? Because there's just so much noise around it. So is it—you know—you just look at this timeline acuteness that we just unpacked? Is it something to do with: Okay, we really got to get this wrapped up in the next couple weeks or so because midterms are in November and we need to try to, you know, put out the fires that we've just self-inflicted on ourselves by then or, you know, just have enough runway? Like, how do you think about all that?","offset":1958,"duration":24},{"text":"Jacob Shapiro: I'm opting out of the reality TV show presidency. I stayed up late what was that Friday or whatever he was doing the White House press—you know—the press conference from the Oval or from the White House or whatever it was because he was going to make some announcement it was going to be ground troops.","offset":1982,"duration":12},{"text":"Jacob Shapiro: And it wasn't, it was just President Trump being President Trump. And he has a knack for creating these inflection points, these moments where everybody's talking about him and everybody's focused on this thing. I'm not buying it. Like I'm buying our ships coming out in and out of the Strait of Hormuz.","offset":1994,"duration":14},{"text":"Jacob Shapiro: Does Iran feel like it's done enough to either re-establish deterrence or is it making progress in getting reaching some kind of modus vivendi with Oman and GCC states about where this goes from here?","offset":2008,"duration":12},{"text":"Jacob Shapiro: If you're just reading the plain objectives of both sides, I don't think Iran feels like it has caused enough pain to the global economy to re-establish deterrence, and I don't think the United States is acting like a country that is able to declare mission achieved or—you know—mission objectives achieved quite yet.","offset":2020,"duration":17},{"text":"Jacob Shapiro: So that tells me that, you know, maybe there's negotiations going on, but it doesn't look like either side is ready to bend. Maybe I'm reading that wrong. Maybe Iran actually is hurting much worse than I think, and Iran feels like it's done enough and maybe it's got, you know, back channelers from the—from the Gulf states that make them feel like they can do that.","offset":2037,"duration":17},{"text":"Jacob Shapiro: Maybe President Trump really does believe like he's achieved his objectives and he can end this particular season of the reality TV show and move on to the next episode. But yeah, I'm opting out of these \"Oh, tomorrow's the inflection point.\"","offset":2054,"duration":12},{"text":"Jacob Shapiro: Because for all we know, he'll come on tomorrow and be like, \"I've extended the deadline another two days, but Thursday is now, you know, bridge obliteration day.\" Like, okay. How many straits are coming in or—excuse me—how many ships are coming in and out of the Strait of Hormuz?","offset":2066,"duration":14},{"text":"Jacob Shapiro: What is the price of jet fuel in Singapore? What is the difference between, you know, Asian futures and and what Brent crude is showing us: market versus physical shortages. Like that's what I'm interested ultimately. And when that stuff starts going back, you'll probably be able to see the politicians starting to change their tunes.","offset":2080,"duration":15},{"text":"Host: Hmm. To that point, obviously, yeah, there's a lot of more esoteric markets like you mentioned, like Singapore jet oil, that have gone absolutely bananas.","offset":2095,"duration":10},{"text":"Host: But then there's also other things like, you know, US equities are, you know, barely down from all-time highs. And I'm just curious about: When you net out everything that exists today and how it's—how it's been discounted?","offset":2105,"duration":10},{"text":"Host: And if we can get to this point where markets can forward-look to a point where there is this like weird new world of a gray zone around the Strait of Hormuz where there is partly this toll thing, but then also not?","offset":2115,"duration":11},{"text":"Host: And, you know, when you net it all out stuff is getting through the strait. Like that world that we get into and you net it with all the damage that has been done—you know—there was like 20 billion dollars of damage done to the Qatar LNG facility.","offset":2126,"duration":14},{"text":"Host: There's—there's still durable damage as well. When you put that all together, like do you—what do you see the probability of markets just trying to look past this whole thing and and move on? Or how much of it is like, \"Okay, we've done too much damage, we need to discount this further.\"","offset":2140,"duration":15},{"text":"Jacob Shapiro: Yeah, I never try to denigrate Mr. Market because Mr. Market is probably smarter than all of us are. At least to some—at least at some level. That said, you know, markets can also be overly optimistic even as things are starting to break.","offset":2155,"duration":18},{"text":"Jacob Shapiro: Like think about how long it took for markets to appreciate the risk of the Russia-Ukraine war, or to appreciate what was happening in 2007, 2008. It's not like markets are always the leading indicator, and sometimes they lag considerably in terms with that.","offset":2173,"duration":16},{"text":"Jacob Shapiro: I also think you have to think in terms—you know—this is—I was relatively optimistic about the US economy going forward. And I was optimistic for precisely some of the reasons that we already talked about. Like multipolarity and deglobalization means that within these regional spheres of influence that are powered by these regional potential regional hegemons, you're going to get more investment and more capex and government support of technology and also some of these physical parts of the economy.","offset":2189,"duration":27},{"text":"Jacob Shapiro: So I think even with, as we're talking about, the long-term ramifications of the disruption in the Middle East, everybody's going to be worse for it. Like nobody is walking out of this conflict better for there having been a disruption.","offset":2216,"duration":13},{"text":"Jacob Shapiro: But at a relative level, some countries will have done better than others. The United States is a country that is poised to do better than most others in the world. It's far away from geopolitical zones of conflict. It has cheap and secure access to energy and to food. It is still in many ways at the commanding heights of technological innovation.","offset":2229,"duration":17},{"text":"Jacob Shapiro: There's a lot going for the United States. And that's one of the reasons why it's so baffling that the United States did this. Like if President Trump had just kept doing what he was doing, if Cuba had been next rather than Iran, you know, we might have been talking about a very different economy going into the midterms.","offset":2246,"duration":16},{"text":"Jacob Shapiro: China is a country that I think is going to do relatively well. And I know that some people will now like say, \"Oh, he's a CCP shill\" or whatever, and don't worry, I'm—I'm still waiting for my CCP payments for saying bullish things about China.","offset":2262,"duration":11},{"text":"Jacob Shapiro: But China, I think, is well—has been preparing for this for years. Who's leading the world in terms of rolling out renewable capacity? It's China. China's not doing that because it makes sense from an economic perspective to do so.","offset":2273,"duration":12},{"text":"Jacob Shapiro: That is because the communists on high said, \"We will do this, because we watched the Americans in the Middle East for 20 and 30 years and we don't want to participate in that.\" Yes, we are still dependent on importing from the Persian Gulf, but we envision a world 10-15 years from now where we've got nuclear and solar and wind and everything else and that we become a center of green, you know, energy technology.","offset":2285,"duration":20},{"text":"Jacob Shapiro: A, because that's nice, but B, because this is an existential issue for us. We don't want to have our energy blocked because of something that's happening in the Strait of Hormuz.","offset":2305,"duration":8},{"text":"Jacob Shapiro: Then you've got countries like—I mean—Saudi Arabia used to be on this list. I don't know that it still can be. But say a country like Chile, which is far away from geopolitical zones of conflict, which can have incredibly low cost of energy because of the solar, wind, geothermal potential that lies there.","offset":2313,"duration":13},{"text":"Jacob Shapiro: And so that's going to be an ideal case for you to do things with data centers or internet of things or automation or robotics and things like that. So I think you will find pockets of opportunity throughout the world, and it's about, you know, putting perspective on which places are going to do relatively better than others even despite this disruption.","offset":2326,"duration":21},{"text":"Jacob Shapiro: The one that is most out there is—is Europe. And I—I remain pretty optimistic about Europe's future. I think Europe gets left for dead too often and Europe's obvious flaws overshadow its strengths, which is: It's still an incredibly rich and wealthy place. It's a place that thinks it's geopolitically relevant that has lots of technological advantages that it can deploy.","offset":2347,"duration":22},{"text":"Jacob Shapiro: If you're in Central or Eastern Europe and you've bet your energy future on first Russia and then on cheap energy supply coming out of the Middle East, okay, you're going to be in for some tough years. But that's not the story of France, that's not the story of Spain, that's not the story of some of these other countries.","offset":2369,"duration":14},{"text":"Jacob Shapiro: And they exist not—I mean, I wish it was a confederation, it would make it easier—but they exist in this European Union. And so those countries are going to have to look at each other and say, \"We have to stop letting Hungary hijack our priorities going forward and make some pretty serious decisions about where we're—what we're going to do to stay relevant.\"","offset":2383,"duration":16},{"text":"Jacob Shapiro: I think the EU will do that. You can make a very compelling case that they won't and that I'm just whistling into the wind here. But that I think is a block that could use the—the impetus of this crisis to do things that people today maybe aren't appreciating as possible. Like those are places that I'm going to be interested in going forward.","offset":2399,"duration":19},{"text":"Host: Interesting. Okay, I want to double-click on the China thing a little bit because there's two things that are interesting to me that I've been noticing. One of them is just how quiet they've been throughout this whole crisis. Um, really haven't been that verbose or explicit about the whole thing.","offset":2418,"duration":14},{"text":"Host: And the other one too is if you rewind pre-Iran strikes when the Venezuela thing was happening, there was this whole emergence of the Donroe Doctrines, spheres of influence and a lot of speculation that it's like we're, you know, aligning the chess pieces to go after the—the big dog that is China.","offset":2432,"duration":17},{"text":"Host: Um, and you know we want to cut off all their oil supply. So we're cutting Venezuela and now we're going to Iran and now we're going to cut off the Strait of Hormuz and all that oil going to China. How are you thinking about those two dynamics?","offset":2449,"duration":10},{"text":"Jacob Shapiro: Well, let's take the last one first. We hurt over Japan, South Korea, India way more than we did China. Remember, when Vladimir Putin invaded Ukraine, all he did was turn Russia from a great power into a Chinese gas station.","offset":2459,"duration":15},{"text":"Jacob Shapiro: So China's—I'm not saying that China's energy secure, but they have more reserves, more renewable capacity online and a relationship with Russia. That is not something that your Japans and South Koreas and Indias can say.","offset":2474,"duration":19},{"text":"Jacob Shapiro: So in that sense, okay, if you're trying to hurt China with that 5D chess, you actually hurt your allies much more. Um, if you think I'm being too hysterical about that, think about what's happened in the Philippines over the past couple of weeks.","offset":2493,"duration":12},{"text":"Jacob Shapiro: The Philippines was one of the first countries in Asia to declare an energy emergency because of what's happening in the Hormuz—in the Strait of Hormuz. A couple days after that, the Marcos Jr. government announced that they were restarting talks with China about joint exploration in the West Philippine Sea and the South China Sea for offshore energy deposits.","offset":2505,"duration":16},{"text":"Jacob Shapiro: That's wild. The Philippines is a US defense treaty ally. We spent years worrying about the Duterte administration getting friendlier with China and doing exactly this. It took just a couple of weeks and this war of choice in Iran for the Philippines to start looking at China and saying, \"Huh, maybe we should have a more pragmatic relationship with China. Maybe this is a country that we can do business with even in the South China Sea, even around Taiwan.\"","offset":2521,"duration":25},{"text":"Jacob Shapiro: So you've—you've hurt the allies more than you've hurt China there. And I think China has more reserves than folks expected. Also as for the Taiwan issue, man, can we just put it to bed finally?","offset":2546,"duration":12},{"text":"Jacob Shapiro: Because if China's not going to invade Taiwan now, with the United States bogged down in the Middle East and using all the Tomahawk missiles and everything else like that, okay, I'm waiting. Are they going to go for it? Is now the time?","offset":2558,"duration":-1069},{"text":"Jacob Shapiro: No, now's not the time, because they're not thinking about it that way. They're thinking about Taiwan the way they thought about Hong Kong in the 70s and 80s. They want to isolate it economically, they want to isolate it politically.","offset":1489,"duration":1091},{"text":"Jacob Shapiro: They want to get to the point where nobody cares enough about Taiwan so that when they announce that they are taking it, nobody puts up a fight to stop them, which is exactly what happened with Hong Kong.","offset":2580,"duration":9},{"text":"Jacob Shapiro: The UK went back to renew the lease, Margaret Thatcher—that great British nationalist herself—Deng Xiaoping said, \"Cool, we'll cut off the energy and the infrastructure and the water and we'll blockade it if that's what you want to do. Is that what you want?\"","offset":2589,"duration":15},{"text":"Jacob Shapiro: And Thatcher said, \"I think I'll go to the Falklands to wave the British flag around. Like you can have it.\" And then we had, you know, one country, two systems, blah, blah, blah. That is the move that China's playing for when it comes to Taiwan.","offset":2604,"duration":10},{"text":"Jacob Shapiro: I don't think there's any universe in which China was going to invade Taiwan. The most interesting thing I think that's gone unreported in all this, and obviously lots of things have to go unreported because the war is that important. It's crowding out a lot of things.","offset":2614,"duration":12},{"text":"Jacob Shapiro: But before the war started, you had a huge diplomatic dust-up between Japan and China. The Takeichi government really pushing China's buttons on Taiwan and some of these things.","offset":2626,"duration":10},{"text":"Jacob Shapiro: And Japan has been deploying long-range missiles and military capacity to places that China doesn't like. And so China has announced, \"Oh, okay. Well now for the next 40 days, we're going to be controlling airspace in areas of the East China Sea as we do some things that we're not going to tell you about.\"","offset":2636,"duration":15},{"text":"Jacob Shapiro: So some interesting friction back and forth there between China and Japan. So there are things to watch for. I'm not saying that China is some benevolent power that isn't scheming here, but they are scheming to take Taiwan by not firing a shot.","offset":2651,"duration":12},{"text":"Jacob Shapiro: And ironically, everything the United States is doing is helping that future come into being. But I think China's watching, you know, Russia's failed attempt to take Ukraine, the US's failed attempt at least thus far to, you know, change the regime in Iran and saying, \"Okay, well why would we try to do something that's orders of magnitude harder, which is an amphibious invasion of a hardened island that, you know, we're not going to be able to take without destroying the things that make it valuable in the first place.\" Like I just don't think China thinks that—thinks strategically that way. I think they're thinking longer term.","offset":2663,"duration":33},{"text":"Host: Yeah, I mean, yeah, seems like the easy narrative is that China's always just thinking longer term. But I—but I am curious...","offset":2696,"duration":4},{"text":"Host: What about, like, the next couple years? Like right now, you know, is their main priority just, you know, what's the quote again? Of, you know, \"don't interrupt your enemy when they're making a mistake.\" Are they just kind of sitting by the sidelines and just watching this all happen? And they're like, \"Well, you know, eventually this is just going to make... it's probably going to make it easier for us in one form or another, not sure how, but I'm just going to wait for the dust to settle.\" What do you think?","offset":2700,"duration":22},{"text":"Jacob: There's a couple ways I would answer that question. The first is, even though China really is only communist in name and form, like China's economic policies are not communist, they're sort of a weird state capitalism, like authoritarianism plus Ronald Reagan supply-side reforms in a weird bastardization together, but the form of Chinese politics is still very Marxist and very communist.","offset":2722,"duration":22},{"text":"Jacob: And if you've been raised as a Marxist, um, then you look at the United States and say, \"Oh, this is late-stage capitalism. This is the late-stage capitalist hegemon basically destroying itself.\" So to your point, why would we want to get in the way of that? I think Xi Jinping also realized, um, towards the end of the 2010s and into the early 2020s that he made a mistake.","offset":2744,"duration":24},{"text":"Jacob: He thought China was stronger maybe than it was. You had the wolf warrior diplomacy happening all over the place and China starting to, uh, bare its teeth a little bit. Um, and I think he was able to walk that back and see that China wasn't quite ready for that. That China needed to be more accommodating, that it needed to be a pragmatic partner, and that there was actually an opportunity in US political volatility and instability to be that.","offset":2768,"duration":25},{"text":"Jacob: And it's been very successful over the past couple of years. Uh, remember the biggest geopolitical story of this year before the war, um, was not Venezuela, it was not Greenland, it was Mark Carney going to Davos and saying, \"I'm taking the sign out of the window. I think China's a more reliable partner right now than the United States is. And we have to think about Canadian national self-interest in that context.\"","offset":2793,"duration":22},{"text":"Jacob: That's a huge diplomatic win for China, that it has been able to seem more stable and more accommodating in a global international political system to a country like Canada than the United States. I think that's a very important signal. So, China's not without mistakes, and it's a huge and arguably sclerotic bureaucratic authoritarian system, so it can and will make more mistakes.","offset":2815,"duration":24},{"text":"Jacob: But I think you've definitely seen a shift in Chinese policy, uh, from the wolf warriors at the end of the 2010s to right now, which is to your point, hey, how can we work with some of these other countries? How can we figure out a way, um, to create these economic relationships with them that are not tied to political ideology, that are not tied to overt asks, that don't involve us raising tariffs or threatening to do things against countries who don't do the things that we want? I think that's working for them, and I think that's what they'll continue to do here going forward.","offset":2839,"duration":30},{"text":"Host: Awesome. Um, alright, we'll just kind of conclude here with just your final parting words or thoughts or recommendations for, for those of us like myself who are, you know, mostly focused on, on macro trading and we are, we are self-admitted tourists within this space and just trying to figure out what the hell is going on. Any final words on how to navigate this whole thing?","offset":2869,"duration":22},{"text":"Jacob: The, the last thing I would just say, and I know it's, I know it probably sounds silly to say this, like, 47 minutes into our conversation, um, but I'm still very optimistic about the global economy over the next five to ten years. I think a lot of the dynamics that we're talking about, they will be bad for some people, they will be great for others. They will be bad for some industries, they will be transformative for others.","offset":2891,"duration":24},{"text":"Jacob: I think there's a lot of comparison out there, uh, between our current time and the 1930s, uh, for folks that are thinking, \"Oh my god, like, we're on the cusp of another World War.\" I don't think that at all. I, I think the right frame of reference, and it's not a perfect historical analogy, but is the 1890s because you had rising and falling great powers. You had, uh, a generational shift in energy from coal to oil.","offset":2915,"duration":26},{"text":"Jacob: Um, you had technological innovation, you had the rollout of electricity over a 20 to 30 year time horizon, which changed everything. You had the advent of modern fertilizers, which for the first time disconnected population growth from just how much you could grow in your own regional market. Um, it was an absolutely transformative time. Now, at the end of that period, yes, there was a World War because some countries got powerful enough that they thought that they could dominate the world, or there were these weird alliance structures that forced things into a, a structure.","offset":2941,"duration":30},{"text":"Jacob: And by the way, that was a war where nobody thought that war was going to last for four years, everybody thought it was going to be a short conflict, and then once they were in it, they all had to triple, quadruple down. Um, sound familiar to you? Anyway. My point is just that I think we're on the cusp of the 1890s. So, I have to keep in touch with everything that's going on in the headlines on a daily basis.","offset":2971,"duration":23},{"text":"Jacob: I find it truly annoying because the real stuff is happening in technological innovation. What is AI doing? How is it transforming our lives? How is it transforming productivity? What is next with robotics? What is next with automation? What is next with Internet of Things? Changing everything. I want to spend all of my brain power doing that, not on parsing IRGC propaganda or White House propaganda.","offset":2994,"duration":24},{"text":"Jacob: The energy transition is real, and it's not going to be like the switch from coal to oil. That's a lay-up, like, I wish I had been, you know, investing in the 1890s and I could have been like, \"Yes, buy shares of Standard Oil and then we will go to golf and not touch them for another 60 years,\" like, probably would have been the best trade ever, right? But we're not going from oil to something else, we're going from oil to everything else.","offset":3018,"duration":23},{"text":"Jacob: So does that mean that you invest in the energy technologies themselves? Does that mean you invest in the picks and shovels that build the energy themselves? Is this a story about electrification and the grid and everything that it has to do to support this? Is it all the above? Is it really just you want the companies that are going to benefit from, and it's hard to think about this in 2026, but cheaper energy?","offset":3041,"duration":20},{"text":"Jacob: Because by 2030, 2035, probably energy is deflationary, no matter what's happening in the Strait of Hormuz. That's something I want to spend my time talking about. Um, so, you know, you can get wrapped up in everything that's happening in headlines and you can't ignore it because if you ignore it, you ignore potential challenges to those theses or data points that you really need in terms to update that.","offset":3061,"duration":23},{"text":"Jacob: But I, I am sticking to my guns and I would encourage your listeners to stick to their guns. Develop a macro viewpoint, uh, create scenarios for that, and then start to see is this true or is there or is this not true? Even with all the doom and gloom that I've talked about here, I'm optimistic. I'm looking for opportunities to deploy capital in technological innovation, in the energy revolution, in electrification, uh, and in the recession of US global power into a multipolar world and the markets that are best-posed to benefit from that. That's what I do when I'm not forced to talk about whatever strange things are happening in the Middle East.","offset":3084,"duration":41},{"text":"Host: Boom. Very well said. I, yeah, could not agree more with that. Um, yeah, I feel like the thing I, I keep trying to remind myself, I don't know if you agree with this or not, is that look, despite everything going on, all these shortages, like, don't short human ingenuity and, you know, all shortages are followed by gluts is something that I've heard talked about. I don't know if you agree with that or not, but it just feels like interesting framing to at least try to anchor yourself to what's going to happen on the 5 to 10 year horizon here.","offset":3125,"duration":27},{"text":"Jacob: Yeah, I mean, I, I always... uh, I like Jimmy Carr, the, the comedian, and he had some... somebody asked him some question about optimism in the current world, and he had this great... he had this great answer. He was like, \"You know, 100 years ago, nobody really knew what a hot shower was. Like, just, like, you get hot showers all... like, we live in a world, like, I can go to my TV right now and stream anything I want in the entire world, and I can order some, you know, chicken wings on my phone to my house so I can eat them while I'm watching whatever I want on my TV.\"","offset":3152,"duration":25},{"text":"Jacob: I was talking to Claude earlier about, like, taking everything I've written for the last 20 years and putting it into a database, it's like, doing that right now. Um, I mean, life is, like, really incredible. I feel like we're, we're missing... that we're uh, actually in the good times right now.","offset":3177,"duration":17},{"text":"Host: Yeah. Couldn't agree more. Awesome, Jacob. Well, uh, where can folks go if they want to see more of your work and what you got going on?","offset":3194,"duration":6},{"text":"Jacob: Pretty simple. Just go to jacobshapiro.com or you can email me at jacob@jacobshapiro.com. There's the podcast, research, speaking, um, and maybe doing some interesting things, uh, sort of in-between things when it comes to investment, but but cooking on some things there. So, follow me there and and you'll see where the journey goes.","offset":3200,"duration":19},{"text":"Host: Awesome. Love it. Well, thanks for joining on here and giving us the geopolitical update. Appreciate it.","offset":3219,"duration":5},{"text":"Jacob: It's my pleasure, and we'll have to get, uh, cousin Marko on either individually or maybe we'll, uh, we'll force ourselves, the both of you, uh, on you. I'm not sure your hair will be able to handle...","offset":3224,"duration":9},{"text":"Host: That would be... that would be unreal. I, I would love that. Yeah. My hair will probably be on fire afterwards, but I'll just be a vessel for it and just enjoy the ride. But that would be awesome.","offset":3233,"duration":9},{"text":"Jacob: Yeah. Sounds good. Cheers.","offset":3242,"duration":2},{"text":"Host: Thank you.","offset":3244,"duration":15}],"logs":[{"elapsed":"0.0","message":"Downloading audio from YouTube...","detail":null},{"elapsed":"0.0","message":"Trying download with browser cookies (ad-free)...","detail":null},{"elapsed":"4.0","message":"⚠ Cookie download failed: WARNING: [youtube] [jsc] Error solving n challenge request using \"deno\" provider: Error running deno process (returncode: 1): \u001b[0m\u001b[1m\u001b[31merror\u001b[0m: Uncaught (in promise) TypeError: Cannot read prope","detail":null},{"elapsed":"4.0","message":"Retrying without cookies...","detail":null},{"elapsed":"32.8","message":"⚠ Downloaded without cookies — audio may contain ads","detail":null},{"elapsed":"32.8","message":"Audio downloaded (30.4 MB) in 32.8s","detail":"File size: 30.4 MB"},{"elapsed":"32.8","message":"Video title: The Iran War is Accelerating the End of Globalism | Jacob Shapiro","detail":null},{"elapsed":"32.9","message":"Audio duration: 53:23 (53.4 min)","detail":null},{"elapsed":"32.9","message":"Large audio (30.4 MB) — will use chunked transcription with gemini-3-flash-preview","detail":null},{"elapsed":"32.9","message":"Skipping full-file attempt — using chunked transcription for 53.4 min audio","detail":null},{"elapsed":"33.3","message":"Split audio into 2 chunks for transcription","detail":null},{"elapsed":"33.3","message":"Transcribing chunk 1/2 (starts at 0:00)...","detail":null},{"elapsed":"33.3","message":"Uploading audio to Gemini File API...","detail":null},{"elapsed":"38.5","message":"Audio uploaded in 5.2s","detail":"File ref: files/ra9jec8b78hr"},{"elapsed":"38.5","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"125.9","message":"Chunk 1: 179 segments, last timestamp 44:56","detail":null},{"elapsed":"125.9","message":"Transcribing chunk 2/2 (starts at 45:00)...","detail":null},{"elapsed":"125.9","message":"Uploading audio (offset 45:00) to Gemini File API...","detail":null},{"elapsed":"127.8","message":"Audio uploaded in 1.9s","detail":"File ref: files/5aq5a9l6urn0"},{"elapsed":"127.8","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"143.8","message":"Chunk 2: 27 segments, last timestamp 54:04","detail":null},{"elapsed":"143.8","message":"Chunked transcription complete: 206 total segments","detail":null},{"elapsed":"143.8","message":"Total cost: 80,588 in / 16,538 out — cost: $0.0899","detail":null},{"elapsed":"143.8","message":"Total transcription time: 110.9s — 206 segments","detail":null},{"elapsed":"143.8","message":"Analyzing topics across 206 segments with gemini-3.1-pro-preview...","detail":null},{"elapsed":"194.2","message":"Topic analysis complete in 50.5s — found 13 topics","detail":null},{"elapsed":"194.2","message":"Analysis tokens: 17,569 in / 1,166 out / 5,055 thinking — cost: $0.1098","detail":null},{"elapsed":"194.2","message":"Pipeline finished in 194.2s — total cost: $0.1997 (120,916 tokens)","detail":null}]} \ No newline at end of file diff --git a/history/1775589068370-UmLdukkI0IU.json b/history/1775589068370-UmLdukkI0IU.json new file mode 100644 index 0000000..3df5ea1 --- /dev/null +++ b/history/1775589068370-UmLdukkI0IU.json @@ -0,0 +1 @@ +{"id":"1775589068370-UmLdukkI0IU","videoId":"UmLdukkI0IU","url":"https://www.youtube.com/watch?v=UmLdukkI0IU","title":"Why You Can't Relax, Sleep Or Focus! - Do This 5 Minute Habit To Feel ALIVE Again | Brian Mckenzie","type":"youtube","topicCount":15,"segmentCount":305,"createdAt":"2026-04-07T19:11:08.370Z","uploadDate":"20250416","chunks":[{"title":"The Root of Emotional Pain and Breathing","summary":"The host and Brian discuss how breath is intimately linked to metabolic, cognitive, and hormonal health. They explore how unresolved childhood pain and trauma create defensive behavioral patterns that cannot be bypassed with superficial breathwork alone.","entries":[{"text":"Host: Breathing is not just about your ability to run a fast 5k on Saturday or your ability to relax in yoga. It is metabolic health, it's cognitive health, it's hormonal health. Like, your breath is at the center of everything. And therefore it's striking that so many of us don't pay attention to our breath, or even know how to manipulate our breath to change our states, right?","offset":0,"duration":26},{"text":"Brian: Yeah. Yeah, yes, and the real thing that I feel would benefit most people is being aware of it, right? And my understanding of really being aware of one's breathing is, if you can be aware of it, you can let it happen and pay attention. And there are times, yes, you can use breathing to regulate and and become more aware of what's going on.","offset":26,"duration":28},{"text":"Brian: But if you're not willing to confront the pain that has you in this reactive state to stress—from wherever that originates, typically childhood—um, and you don't that doesn't mean you need to go relive childhood, it's like \"Well, oh, I was in a defensive pattern because my environment was incredibly hostile and everybody was fighting when I was young, so no wonder why I've got my dukes up all the time in anything in what I do,\" right?","offset":54,"duration":27},{"text":"Brian: Um, I'm really at a point where it's like if if you're just going around that shit, if you're going around that and just trying to control breathing and and go about it that way, you're not going to find that root. The root will be disguised. It'll be camouflaged.","offset":81,"duration":22},{"text":"Host: You've said, haven't you previously, there is no amount of breathing that will change the pain you are not willing to confront.","offset":103,"duration":5},{"text":"Brian: Yeah.","offset":108,"duration":1},{"text":"Host: One of the things I wanted to talk to you about today is this idea that our breath is intimately linked with our nervous system and how we then view the world. So if we talk about the pain that we are not willing to confront, right? So let's say there is pain from childhood because of A, B, and C, right?","offset":109,"duration":22},{"text":"Host: That can then result in some sort of dysfunctional breathing patterns potentially, I'm guessing, as a consequence. So then if you have compensatory breathing patterns because of trauma, let's say, then it can be hard to address the pain sometimes if you're in this constantly wired state.","offset":131,"duration":26},{"text":"Host: So presumably, being able to work on your breath and maybe change things a little bit can change the state of your nervous system which might then allow you to go inwards and confront the pain.","offset":157,"duration":14},{"text":"Brian: Yes. What you first touched on when you when you began the question was, you know, we we've gotten to a place where we're kind of just we want to just fix the problem or we want to fix how we feel. That's what I run into is people just want to feel differently. People don't want to actually change their behavior.","offset":171,"duration":26},{"text":"Brian: Um, and what we're talking about right now is a behavioral pattern that breathing follows and although you could there there is some school of thought that breathing is behavioral, I'm far more under the impression that that physiology has more to do with it.","offset":197,"duration":19},{"text":"Host: What does that mean for people?","offset":216,"duration":1}],"startTime":0},{"title":"The Hardwired Stress Response","summary":"Brian breaks down the three stages of the body's natural stress response, contrasting life-or-death situations with modern stressors like being cut off in traffic. While physiological reactions to stress are automatic and universal, our subsequent behavior remains a choice.","entries":[{"text":"Brian: So, uh, you know, if pretending that a, you know, lion walks into the room, there is a heightened arousal state, there is a sympathetic response to that. Um, and the first stage of that is there is the stimulus, right? So we've got some sort of stimulus. Somebody cuts in front of me while I'm driving. There's a stimulus.","offset":217,"duration":23},{"text":"Brian: Um, the second part of that is the nervous system's response to that. My sensory system which operates through communication through an electrical network that is firing things, it goes on high alert pretending as though somebody cut in front of me. The first thing anybody does when they're driving if they see that is they grab the wheel and they hit the brakes, right? That is your nervous system responding, reacting to that stimulus.","offset":240,"duration":26},{"text":"Brian: After that, the third part of this is the physiological processes involved in that and and the driving of behavior. So my sympathetic nervous system goes up. I'm releasing neuro-neurotransmitters and hormones, adrenaline, right, norepinephrine—these things are released real-time. And so that third part of the stimulus response now becomes the first part of the stress reaction.","offset":266,"duration":28},{"text":"Brian: And each of these is universal to us all. And I've got this happening and somebody cuts in front of me and this stuff happens. So all of these chemicals in my biochemistry is changing in order to manage what it is my system is putting off, right?","offset":294,"duration":18},{"text":"Brian: So let's just go with adrenaline as an easy one. My response to adrenaline in anything when I'm not prepared for it is \"dukes up,\" per se. It's confrontation, it's personal. So then the second part of that is the recovery phase should happen.","offset":312,"duration":20},{"text":"Brian: So it's like if somebody cut in front of me and I didn't actually get pissed off, I'm like \"Oh, whatever, let them go.\" That is a response that's like going and lifting some weights and and resting between sets.","offset":332,"duration":14},{"text":"Host: Okay, let's just pause there, Brian, because this is really interesting. Yeah. Our stress response is hardwired within us. Okay, so—","offset":346,"duration":8},{"text":"Brian: No avoidance.","offset":354,"duration":1},{"text":"Host: Yes, if there was a lion that just came into this room now, we probably would change quite significantly in terms of how how our being is, how we're interacting, our posture, our muscle tension, everything will change, okay. You're driving on a road, wherever you live in the world, and someone suddenly cuts in front of you, so you slam on the brakes, okay. That's an automatic response, right? You've slammed on the brakes.","offset":355,"duration":26},{"text":"Host: Is it possible to get to a point where that doesn't even generate the physiological changes? So if you work on this enough—and we're going to through loads of practical things in this conversation—is it that everyone will have the physiological response and then we train ourselves to not respond to the adrenaline, or is it different?","offset":381,"duration":24},{"text":"Brian: Here's what's, you know, so funny enough, you know, part of Andrew Huberman's research before he had his podcast at his lab when I was involved with his lab, they were in that they were in his VR looking at stress from everybody. From people who were who are on anxiety medications all the way up to like Navy Seals.","offset":405,"duration":22},{"text":"Brian: Everybody responds to stress. Everybody responds to the stress. In what capacity and how they come off that stress is the important part.","offset":427,"duration":11},{"text":"Host: Okay, so even if you're a calm, non-reactive person—","offset":438,"duration":4},{"text":"Brian: You're going to. The when the lion comes in the room or somebody cuts you off, you will, your body naturally reacts to it. It's the behavior that you choose to follow as a result of that.","offset":442,"duration":11},{"text":"Host: Got it. So it is what Viktor Frankl says. Um.","offset":453,"duration":3},{"text":"Brian: This is where choice happens, right?","offset":456,"duration":1}],"startTime":217},{"title":"Breathwork and Cognitive Reframing","summary":"The conversation explores how breathwork and cognitive reframing can disrupt chronic stress patterns. By pausing to breathe and observing the stories we attach to triggers, we can choose to respond authentically rather than reactively to the world around us.","entries":[{"text":"Host: Is that where breathwork can potentially come in for some people?","offset":457,"duration":4},{"text":"Brian: A hundred percent. This is where, this is where breathwork does come in. So this is where intervention comes in. When I have an emotional reaction to something that I don't like or I don't like the way I feel, or I don't like what I said, um, and I want to work on that, that is where the opportunity for intervention comes in.","offset":461,"duration":19},{"text":"Brian: So I can take a breath, I can take several breaths, I can come down. And if I can bring myself down, then I might have the opportunity to bring reality on. Did that person who cut in front of me start their day by going \"I'm going to go find Brian McKenzie and I'm going to cut in front of him today and I'm going to intentionally piss him off\"? No, that is not what happened.","offset":480,"duration":26},{"text":"Brian: In at least in my this world I currently live in, now the old world I existed in, I might narcissistically have pulled that one off, right? But in the moment you will start to arc stories for the emotional reaction that you have to things and that's where the breathing is starting to get away from you as well. So my breathing tends your breathing will do things in these places. It's simply responding to the activity and the change that's going on.","offset":506,"duration":29},{"text":"Host: These things are so linked, physiology and psychology, psychology and physiology. Oh, yeah. And the thing I've really been thinking a lot about, Brian, and I'd I'd love to hear your perspective on this, is I feel compared to who I was five years ago that I interact with the world in a completely different way. Most of the time I actually feel really calm and I feel that when the stimulus is happening, I seem to have this ability now to know that there is a space and go \"Yeah, I'm not reacting to that,\" right?","offset":535,"duration":42},{"text":"Host: Now people will say, like, I've covered trauma on this podcast on many occasions with people like Gabor Maté, Dan Siegel, Bessel van der Kolk, all these kind of greats in the trauma world, right? And a lot of people will say, and I agree, that trauma can be stored in the body. Yeah. With our certain patterns, our breathing patterns, maybe we're slightly more flexed, whatever it might be, we have these patterns.","offset":577,"duration":21},{"text":"Host: And so there's a school of thought saying that you can't change that trauma with the mind, you do it through the body. And I believe for some people that is the mechanism to change it, not that you can separate the body and the mind, okay. I feel in my life a lot of it has been cognitive. So I had a conversation a few years ago with an Auschwitz survivor, Edith Eger, when she was 93.","offset":598,"duration":32},{"text":"Host: That conversation changed my life, Brian, because she was able to reframe her whole existence in Auschwitz to the point where she said to me that the greatest prison you'll ever live inside is the prison you create inside your own mind. And that's from someone who lived in the hell of Auschwitz, right? So that really landed for me.","offset":630,"duration":18},{"text":"Host: So I would for years practice if I ever got emotionally triggered in the day—I perhaps couldn't do it in the moment—that evening I'd reflect and go \"Ah, that situation was not inherently triggering, that situation was not inherently offensive, if it was, everybody would get triggered to it, everyone would take offense at it. No, no, there's something in me that is being activated by that stimulus. So if I want to change, I have to find in me, instead of putting the blame elsewhere, externally, I have to figure out what insecurity, what inadequacy, what is being triggered inside of you.\"","offset":648,"duration":37},{"text":"Host: And by doing that regularly, I now feel that it's become my default response. Now at the same time, I also do work on my body. I have an amazing movement coach, I work on my breathing. I now have access to certain movement patterns that I didn't have five years ago, so I can't say what exactly it was. But I don't buy that it necessarily always has to come from the body or always from the mind. These things are connected. Does does that make sense, Brian?","offset":685,"duration":26},{"text":"Brian: Oh, yeah.","offset":711,"duration":1},{"text":"Host: Because I don't know, people say \"Well, how how come you're so calm these days?\" I'm like \"I have done a combination of things. I've done the work, I've constantly looked inwards at my triggers.\" Now breathwork, I would say that's a very big term that people interpret, you know, in all kinds of different ways. Yeah, for sure, that has helped me as well, but so has cognitive reframing.","offset":712,"duration":23},{"text":"Brian: Yes. Yes.","offset":735,"duration":1},{"text":"Host: So I don't know if you can sort of pass through that through the lens of what you're saying now about we encounter a stressor and our stress response goes up. So how come I can be calm now?","offset":736,"duration":10},{"text":"Brian: The simplified version of, you know, how I was getting complex is, is it's like if I choose not to respond to somebody cutting me off—and this is just you know insert whatever you want, insert whatever you want: your father saying something to you you know or what your—","offset":746,"duration":18},{"text":"Host: Whatever it is that triggers you.","offset":764,"duration":1},{"text":"Brian: Your wife or your husband saying something to you that's popping you, right? If you choose not to allow that to go beyond that moment, you've now learned how to adapt. You've now learned how to stay with it and and you don't have to take that personally, right?","offset":765,"duration":23},{"text":"Brian: So if I choose to let the guy cutting me off go, I now adapt and I now am over here in the logical side of something, real I'm rooted in reality. And I think what what's really important here is that over here my core values are are the anchor point. For me, my core values sit with things like authenticity. It's like \"Just be real, just be authentic and you're in my world if we meet.\" And I'm I'm happy to in and if it's just if it's not authentic I'm out, I don't have time for that right now.","offset":788,"duration":40},{"text":"Host: Here's a question, Brian. Yeah. If your nervous system is constantly wired, uh chronically activated, and you've never learned how to switch it off or calm it down, is it even possible to know what being authentic is?","offset":828,"duration":19},{"text":"Brian: No, not in that state, no. Because you're in a chronic stress response.","offset":847,"duration":4},{"text":"Host: Yeah. And then if everyone's if everyone's walking around in a chronic stress state, of course no one's being authentic.","offset":851,"duration":5}],"startTime":457},{"title":"Chronic Stress and True Performance","summary":"Brian uses the analogy of continuously squatting to describe how high achievers often stay stuck in an unyielding state of chronic stress. He shares his experience working in San Quentin prison to illustrate how true performance involves internal growth and mental freedom.","entries":[{"text":"Brian: I mean a lot of my this is what a lot of my clients actually—not the professional athlete side, I mean although on occasion I'll get a professional athlete that's dealing with something like this—but most it this is more of the you know private the clients that are like the executives, right? These are the guys and gals that are functioning up here all day all night and then they go and train and the way they train mimics the way they work and and they don't realize that they're they're in this heightened stress state, right?","offset":856,"duration":28},{"text":"Brian: And so the third part of that stress reaction—so let's just pretend you I didn't let go of the guy cutting me off. I've now brought in more hormones and neurotransmitters that are now blocking an adaptive process. Now we've onboarded adrenaline again because we're now making up a story about what we're going to do to this person, or they're taking advantage of me, or they're doing this to me. I'm essentially victimizing myself in some capacity, right?","offset":884,"duration":35},{"text":"Brian: And so I now go at this with a non-adaptive process that if I repeat this enough and I don't let that go, I remain in what's called chronic stress. That does not allow for that parasympathetic arm of my autonomic nervous system to come back online as well. And that if that goes on long enough I can have a multitude of different responses that occur with that. I can stay in a heightened stress state or I can actually retreat and then be pulled down into this more depressed nervous system state where I I can't get out of bed, I can't do these you know.","offset":919,"duration":39},{"text":"Host: You you say it's non-adaptive, but could we not make the case that we're always adapting, the question is what are we adapting to and what is our response?","offset":958,"duration":10},{"text":"Brian: Yeah. So the new adaptation becomes this heightened or or whatever state that is now not allowing me to recover. It it'd be the equivalent of just lifting weights. Like I I go to lift weigh—I just go I go squat. And I just keep squatting all day. And I keep every set after set after in I'm fatigued but I'm still going and I'm still going and I'm still going.","offset":968,"duration":30},{"text":"Brian: And then I might let off the brakes that evening and decide to go home and sleep if I can because my nervous system's now just torched and I'm hungry and I gotta eat, and then I'll wake up the next day and I start doing it all over again the moment I get to the gym.","offset":998,"duration":13},{"text":"Host: Yeah. This is such a great analogy because what you just said through the lens of you squatting is how many people are living their daily lives. Now through the lens of what we've just been talking about, you're known for many things around the world. Um many people would regard you as a expert in human performance. What does human performance mean to you?","offset":1011,"duration":25},{"text":"Brian: Um, well, I don't think I'm an expert, I'm more of like a specialist. Um, I'm still learning every single day about this. Um, performance for me is a path towards growth. And most of what I've found even at the elite level is that if we can unlock a lot of the mental constructs that we've built, then there's a freedom in that that allows us to really see where the limitations are in what we're doing.","offset":1036,"duration":41},{"text":"Brian: When I went and worked at San Quentin Prison for six months, I ran a program, and um I'd go in every Friday and work with these guys. And I when I first went in there I, you know, it had occurred to me I'm like \"Okay, so these guys are in prison, most of these guys are doing you know 25 or more. Um but I do know the effect of men in men and women in prison to the outside world.\"","offset":1077,"duration":28},{"text":"Brian: So if you don't understand that, take the time to kind of understand that, which is part of the reason why I was going into these prisons was to kind of help help affect some sort of change in that or growth in that place. But the thing I thought about when I went in there was I explained to these guys: \"Look, every year there are a group of individuals that decide they no longer want to participate in society, and so what they do is they get they give away everything they have and they typically will move to the mountains of Asia somewhere, they will isolate themselves with a few other people, they'll eat once or twice a day and they'll breathe and meditate most of the day and at the end of this they find enlightenment.\"","offset":1105,"duration":43},{"text":"Brian: \"What is the difference between you and them? They committed a crime and they are stuck in a place. How do you want to do your time? Do you want to figure this out? Do you want to figure out how you're doing this? Do you want to evolve and grow towards something differently? Because there are people choosing to live the life you're living for like punishment and they're finding enlightenment through that process, right?\"","offset":1148,"duration":32},{"text":"Brian: \"However, that's what I think about with anybody and everybody. How do you want to win? Do you want to win and be miserable?\" I mean, I seen the Michael Phelps documentary and I've worked with some of the athletes that were in that documentary and I'm like \"I know what this is. It's the same thing going on out here. Just because they're competing in a physical aspect at something doesn't mean there isn't something in that mind that's kind of—\"","offset":1180,"duration":28},{"text":"Host: So so so make it relevant for someone who's listening, Brian, who is kind of they're not an elite sportsman, okay. They just want to live a better life, right? They they they don't want to be reactive all the time and chronically stressed and unable to switch off and snapping at their partner or their kids. What is the relevance of what you do that's going to help that person?","offset":1208,"duration":23}],"startTime":856},{"title":"Finding Joy in the Process","summary":"Drawing on Eastern philosophy and Bruce Lee, Brian emphasizes the importance of valuing the process over the end goal. The host and Brian discuss finding genuine joy and purpose in mundane tasks by changing your internal narrative.","entries":[{"text":"Brian: I guide people towards a process. Tao Te Ching, Sun Tzu, Bruce Lee were very impactful for me and there's a very famous Bruce Lee quote that I have everywhere: \"All goals apart from the means are an illusion. Becoming is a denial of being.\"","offset":1231,"duration":25},{"text":"Host: Why does that mean so much to you?","offset":1256,"duration":4},{"text":"Brian: That gives you unlimited possibility. If I'm not invested in the process, I'm somewhere else. Look, I was doing the dishes this morning and putting away the dishes as I do most mornings when the dishes are done. If there are dishes I go and I put them away. And I don't get upset in the slightest about the fact that I have to put them away. In fact, I found myself in joy. Oh, man, as I was putting away and I was reflecting on the fact that I had earned the money because I valued myself to purchase these dishes.","offset":1260,"duration":38},{"text":"Brian: I've been able to afford dishes for probably 30 or 40 years. Why am I thinking that? Because I'm in a place where I enjoy going and doing this thing and being invested in the process of putting these things away. How am I putting them away? I didn't just arrive at that. That became \"Why am I so pissed off that I'm putting away the dishes right now? Why am I pissed off I'm doing my laundry right now? This is a part of my life, this is a part of my existence. Like what what am I tied up in? Where do I think I'm going to arrive at to where I don't want to do this? What what is that point?\" And and I really looked at that in the reality of it and I find joy in just about every moment of my day when I'm not busy.","offset":1298,"duration":59},{"text":"Host: Yeah, man. I I cannot tell you how much I resonate with that. It's all story, right? As I mentioned to you on Monday, like on the plane over to LA this time I just had this clarity when you're 30,000 feet up in the air, right, you have this big picture perspect—I thought \"Life is simply a set of experiences and the story we put on those experiences is ultimately what determines the quality of our life.\" Boom. You can wash your dishes every night and be pissed off that you have to do it, that your partner didn't do it, that they should have done it, that you whatever story you want to make, or you can change your perspective and like you have done, you—it is possible.","offset":1357,"duration":49},{"text":"Host: Oh. And the problem is, and this is why I wanted to talk to you, I don't think until you've stepped out of it and realized that you're choosing the narrative on every situation, you think you're in it, you think you're a victim to the world, that the way you feel is down to everyone around you without realizing \"Oh, I can change this.\"","offset":1406,"duration":18},{"text":"Host: I was chatting to someone about purpose yesterday and I said for me it's it's less about finding my purpose, life is more about how do I find purpose in everything I do. So you wash the dishes and it's like \"No, this is an opportunity to be mindful and present and feel the dishes.\" If someone had told me that 10 years ago, Brian, I would have thought \"What are you talking about, mate? Like, the dishes are the dishes.\" But I honestly feel that doing the dishes can be the most enjoyable experience in the world if you've reframed it.","offset":1424,"duration":32}],"startTime":1231},{"title":"Three Stages of Emotional Regulation","summary":"Brian details three specific scenarios where breathwork can regulate emotions: preemptively before a stressful event, real-time during a trigger, and post-stress to return to reality. They emphasize the goal of making emotional responses short-lived without carrying baggage.","entries":[{"text":"Host: So what I want to talk to you, Brian, about because we could go even deeper than we've already gone, right? I really want to make this practical for people where possible. There is no quick fix here. No. I'd love to tie in breathing and how we breathe to the concepts that we've been talking about, our stress response, our nervous system. So can you sort of simplify that for someone?","offset":1456,"duration":19},{"text":"Brian: Oh, oh, yeah. Oh, easy. You know, it's um you go through this process that I've talked about where you've got you know the stimulus response and then the stress reaction after that stimulus response and the we've walked through this. And as you know like as I've learned, if I don't like what I'm feeling then that's where the opportunity is, okay.","offset":1475,"duration":27},{"text":"Brian: Eckhart Tolle: \"In a healthy organism, an emotion is a short-lived response.\" Okay. I I 100% agree with that. There's no baggage with that. There's no dragging an experience that happened yesterday or 50 years ago through every day of my life. There's no reason I need to do that to where I can't live in total joy.","offset":1502,"duration":29},{"text":"Brian: And if I'm stuck in sadness, if I'm stuck in—if I'm stuck in excitement, ooh, there's one. This is where I usually throw out to clients: \"Here I I know all this other stuff sounds hard. Let's start with excitement. Let's look at the things that bring you excitement. Let's let's slow down there. Let's bring that down a level to actually see it for what it really is, see what the—because there are far too many of us that are getting very excited over really sexy shiny things that inevitably we didn't actually want to be doing or involved in because we didn't take the time to bring it down enough to go 'Oh, anything that goes up comes down, right?'\"","offset":1531,"duration":42},{"text":"Brian: So and that doesn't mean you can't get excited about things. Yes. How make it a short-lived response. How do you make that happen? Well, when I get excited I slow it down. I intentionally slow it down. So if I know I'm going into a situation—so here there's three ways we can go about this. If I know I'm going into a situation that could be difficult—work, home, whatever, or you're going to go do something that you really didn't want to do—that's where breathwork comes in stage one. I'm going to do that to bring myself down a bit to jump over and go \"What is the reality of this?\" versus the emotion of it.","offset":1573,"duration":41},{"text":"Host: I spoke to a friend last week who was getting really triggered by an email from his boss. Yeah. And I said \"Mate, you know that that email in and of itself is not problematic,\" right? He showed me. I'm like \"That's just neutral email. That's just information.\" Yeah. You're choosing to put this story on it and amping yourself up, you don't have to.","offset":1614,"duration":23},{"text":"Host: And I guess one of the things I think is most powerful about becoming aware of your breath is is that deep knowledge where you know I can actually change the tightness of my nervous system.","offset":1637,"duration":15},{"text":"Brian: Look, Kasper van der Meulen was the one who coined the \"Breathing is the remote control to the nervous system.\" So you can toggle that nervous system if you're willing to sit in it and control it before you go into something that you know could be difficult.","offset":1652,"duration":18},{"text":"Brian: Now the second part of that where this could come in is if you get good at the first process, then you can go in to an actual situation you had not planned for, didn't know was coming and real-time regulate. \"Oh, I can feel that I can feel my adrenaline coming up. I can feel I'm getting I'm getting emotional. I'm getting angry right now. I'm getting frustrated right now.\" Breathe into that if you've if you've got it.","offset":1670,"duration":33},{"text":"Brian: But if you don't, the third part is if the the reaction that you've had you didn't enjoy, now you've got an opportunity when it's over to regulate and go look at the reality of that. So in either any one of those three, reality has to come into play. You've got to be able to jump out of the story or the narrative that you're in and breathing is the thing that can typically allow for that to happen if you're actually applying this. But you've got to be consistent with it.","offset":1703,"duration":38}],"startTime":1456},{"title":"Simple Breathing Practices for Beginners","summary":"For beginners, Brian recommends simple practices like prolonging the nasal exhale or gently observing the belly, chest, and nostrils. They discuss the profound benefits of a five-minute morning breathing routine to intentionally ground yourself for the day.","entries":[{"text":"Host: Okay, so let's talk about something practical then. You got to be consistent with it. So there's our ability to use our breath in the moment, like let's say we've developed and cultivated the self-awareness, so \"Oh, yeah, I can feel something's happening there, oh okay, I'm not going to say anything, let me just calm it down, let me breathe into it, okay.\" But for that person who's never ever paid attention to their breath and is kind of resonating with something going \"Alright, well, where do I start, Brian?\" Where do they start?","offset":1741,"duration":31},{"text":"Brian: I think the simplest thing to do—and this is what I'll show with people if I if I go do a talk so they have something to walk away with—is if you can just inhale through your nose and exhale through your nose a little bit slower each time until you find a place where you're most comfortable with the exhale. But continue to just inhale and then slowly exhale. You're going to bring it down.","offset":1772,"duration":32},{"text":"Host: So your exhale is longer than your inhale.","offset":1804,"duration":3},{"text":"Brian: Yeah, you want to prolong the exhale just slightly, right? Or even even more, as long as you're comfortable. You don't want to you don't want to do this and to the degree that you're hit hit hitting panic switches.","offset":1807,"duration":11},{"text":"Host: Okay, but I think that's a really good point because um one of the breathing techniques that has taken off over the past decade, which has um elevated this topic of breathwork in many people's consciousness is Wim Hof. Yeah. And yes, there's upsides and downsides for sure of that kind of breathing.","offset":1818,"duration":24},{"text":"Host: But I believe that many people think that breathwork has to be hard. I have to be pushing it, I have to be holding my breath, I have to go \"Ugh, now I can keep going,\" right? And what you're saying there is that \"Wait wait wait, you don't need any of that necessarily. You can start off in a very comfortable way just breathing in and breathing out for a little bit longer but you don't have to feel uncomfortable.\" Is is that right?","offset":1842,"duration":25},{"text":"Brian: Correct. That is controlled breathing.","offset":1867,"duration":4},{"text":"Host: Do you sometimes find it difficult to find time to fit wellness into your life? I know many of us do, we feel our lives are too busy. Bon Charge are a wellness brand who have a fantastic range of products to help you feel better, sleep better, and live better. And I've been using many of their products for well over five years now. What I love the most is that they don't require me to find extra time in my life.","offset":1871,"duration":26},{"text":"Host: I think their blue light blocking glasses are some of the highest quality out there. I've been wearing them for years in the evening, also when I go traveling. I also love their infrared sauna blanket, which is much cheaper and more accessible than having a sauna in your own home. It's really easy to set up and you can have a quick 30-minute session whilst relaxing, reading, or watching television. And this sauna blanket is going to help you with recovery, relaxation, and sleep.","offset":1897,"duration":29},{"text":"Host: Bon Charge are giving my audience an incredible 20% off everything on their website. All you have to do is go to boncharge.com/livemore and use the coupons livemore to get your 20% off, or just click on the link in the description box below.","offset":1926,"duration":20},{"text":"Brian: And then another simple thing that you can do is just sit there, shut your eyes and pay attention to your belly moving every single time you breathe. You breathe in and out and that's all you do for about 30 seconds or so. And after about 30 seconds you're just you're going to switch that over to paying attention to your chest and how your chest moves through every breath. You'll do that for 30 seconds. Not forcing anything, let it happen. Just allowing it to happen. And then I would move people into \"Now I want you to pay attention to the air moving through your nostrils. Just the air moving through your nostrils.\"","offset":1946,"duration":51},{"text":"Brian: So if you can do this without having to control your breathing, you're becoming highly focused on something, but you're calming yourself instantaneously down without having to control your breathing at all and your breathing naturally just starts to drop.","offset":1997,"duration":17},{"text":"Host: So would it be a helpful practice let's say as part of a morning routine? Maybe after they wake up for five minutes doing what you just said? Oh, yeah. Make the case for someone if you don't mind, why they should give up five minutes of their precious morning to do that? What are the potential implications later on in their life, later on that day, for example?","offset":2014,"duration":23},{"text":"Brian: You're going to yeah, uh, simple: you're going to change what's going on metabolically real quick. So you're going to start activating things and getting more more oxygen used up because you're changing how the chemistry happens. So you're actually regulating your nervous system.","offset":2037,"duration":14},{"text":"Host: Okay, so let's say you don't have much time, you do five minutes of this kind of calming, grounding, breathwork practice every morning. As someone who does that, or similar versions of that, I feel there's so many potential benefits. A, I think it's a beautiful way to start your day, it's a very intentional way to start your day instead of reacting to the news headlines and the social media, the noise—you're just like \"Oh, I'm going to start—whatever noise is out there—yeah, I'm going to gently just bring myself into the day.\"","offset":2051,"duration":33},{"text":"Host: For example, I think it's also in a world where so many of us are focused outwards on more information and more expertise and more opinions, which then become confusing, I think a practice like this brings you inwards, you starting to pay attention to what's going on inside your body, right? You start to understand \"Oh,\" like even I know this stuff, but even when you were going through it, I started to do it.","offset":2084,"duration":28},{"text":"Brian: Yeah, yeah.","offset":2112,"duration":1},{"text":"Host: And I'm like \"Oh, wow, I'm in my head at the moment. Like, I forgot what was going on in my body. Of course, I'm talking to you.\" Yeah, yeah. But it was a nice reminder. And I think that—","offset":2113,"duration":8},{"text":"Brian: Such a this is so I'll layer this stuff in for people throughout their day. Like \"Hey, man, like as soon as you get off that call, like boom! As soon as out of that meeting, boom! This is where you go do at least just do like three minutes.\"","offset":2121,"duration":8}],"startTime":1741},{"title":"Down-Regulating the Nervous System","summary":"Brian explains why chronically stressed individuals lose the ability to nap or switch off. They discuss the importance of intentionally down-regulating after intense work periods and creating strict boundaries to separate work life from rest, creativity, and play.","entries":[{"text":"Host: Yeah. Am I remembering correctly a few months ago on Instagram, I think you said something to the effect of: if you have a well-functioning nervous system, then you will be able to take a nap at 1 PM. What I understood from that post was many people say that they can't nap. They're tired, but they can't nap. And I appreciate not everyone has the opportunity to nap because of their work pressures, etc., etc. But some people who are working from home and potentially could have the time say that they're too wired to switch off.","offset":2129,"duration":33},{"text":"Brian: I mean look, a healthy functioning animal can take a nap at any point after a stress response, right? What does a lion do after it misses the kill? It goes and lies down and then takes a nap. I remember going to general quarters—so I was in the Navy—and I remember going to general quarters which is, you know, a drill for we're going to war, or something's happening, you're going to your station. And it would be held for a certain amount of time and most of the time it was for a prolonged amount of time. And I remember vividly I was like \"Perfect, I'm going to take a nap.\" And I would literally take a nap when we'd go to GQ because I was going to be stuck in this place for so long and none of my superior officers were going to be there or anything, so they weren't going to see me, they're going to be at their general quarter station, you know, but I was going to take a nap. And I would take a nap.","offset":2162,"duration":67},{"text":"Brian: And then I got out of the Navy and then I started working. I was becoming successful and all of these things and then all of a sudden I couldn't switch off. I couldn't take a nap. I remember all of this.","offset":2229,"duration":12},{"text":"Host: So what happened? What was the switch in you?","offset":2241,"duration":4},{"text":"Brian: I just kept turning it on. I took on every opportunity I could get. I said yes to everything. I didn't learn how to say no. I didn't slow it down from the excitement of everything and the new thing, and that doesn't mean the do go do new things, it's like did I have the bandwidth? And I didn't have the bandwidth. I didn't have the bandwidth because I was burning myself out all day and then I was still trying to train, right?","offset":2245,"duration":23},{"text":"Brian: So I was still trying to work out and do everything I was doing at the time while working out and then I'd do the physical stuff because damn, I felt good after that, but not realizing \"Oh, this is going to have compounding residual effects.\" The interesting was is I was doing a lot of long-slow distance in the early stages of that stuff.","offset":2268,"duration":10},{"text":"Host: You mean endurance training.","offset":2278,"duration":1},{"text":"Brian: Yeah, yeah, yeah. And this is where I started to evolve things um not just for myself but a lot of the athletes I was working because they were burnt. And so it was like \"Well, what can we chip down?\" So we started chipping things down and it was less and less and less and it was like having some great effect. But turns out that if you don't turn it off, if you don't have time throughout the day where you're able to shut it down—and that doesn't mean you need to take a nap. It means can you regulate, can you bring it down?","offset":2279,"duration":26},{"text":"Host: And that's why you're so passionate about the breath, because the breath once you become intimate and pay attention to your own breath and what's happening in your nostrils and your chest and your abdomen, like you just mentioned.","offset":2305,"duration":14},{"text":"Brian: What's the—like if I'm talking or if I'm speaking or if I'm going and teaching, like man, I'm on! What am I doing right after that? Am I going to go have multiple conversations with people? Because I might, because people just saw me do something and so they have questions and they want to talk to me and it's like I'm on again. Then it's like \"Okay, what do I do as soon as after that?\" Oh, I'm jacked up! I was working with some stand-up comedians and none of these guys and gals can shut off after they do a set because they're so wired from being on stage. So a lot of these guys go and play video games and stuff or they're drink and you know and and it's like \"Dude, go regulate! Like, go bring yourself down.\"","offset":2319,"duration":37},{"text":"Host: Okay, this is a great example. So a performer, you know, they finish let's say on stage at 10:30 PM. They're amped up, maybe it's not as different as the person who's still working late into the evening on emails, whatever it might be, maybe you know to make it really practical for people, they can't switch off. So and I know performers who say that their bad habits come in when they're on the road. Like how what is a healthier way for them to um down-regulate at 11:00 PM instead of the bottle of wine, for example?","offset":2356,"duration":31},{"text":"Brian: Go back to the green room or wherever you've got an opportunity to separate yourself from people and just take five or 10 minutes and bring it down, regulate.","offset":2387,"duration":11},{"text":"Host: So what? Breathing.","offset":2398,"duration":1},{"text":"Brian: Do some breathing, do some breathing. You could even do breathhold work if you wanted to, that's going to change some things and bring it down a bit, but that is going to bring the nervous system down and it's going to allow you to actually not be in a reactive place. That's the problem is that we get in when we get into this heightened heightened arousal state you can only react in those places. If you do bring it down you can respond you can be like \"Oh,\" but maybe I don't do that versus like \"No, I'm not doing that. Yes, I am doing that.\" Like, you know.","offset":2399,"duration":36},{"text":"Host: The amount of patients over the years, Brian, who came in to see me um with sleep issues, and of course there's a whole variety of different reasons why one may be struggling with one's sleep, right? But so many of them and this is one of the probably unintended or maybe intended consequences of the digital world in which we now live is that these boundaries between work and home have kind of vanished in a way that you know 20 years ago you left the office, you there's stuff you couldn't really do at home, you had to be in the office to do it, so there would be a natural boundary.","offset":2435,"duration":37},{"text":"Host: Whereas now people can work and do their emails into the evening and one of the things I I realized after a while I was telling my patients a lot is that you know you're struggling to switch off and sleep. They're literally doing work emails, firing them off and then going to bed and saying \"Hey, I'm struggling to sleep,\" okay. And I'm like \"If you're doing that and you're really activated,\" now some people can switch it off quickly, for sure.","offset":2472,"duration":23},{"text":"Brian: My wife can.","offset":2495,"duration":1},{"text":"Host: But many people can't. And I'm like, for me personally, I have to have I don't have to anymore, but I chose a few years ago to go \"You know what, once it hits 7:00 PM, that's it, I'm done. Like, that's the day done. Now everything is chill mode. It's relaxing, it's reading, it's music, it's doing some stretches, it's chatting with my wife, it's not work-related.\" It was a choice that I made.","offset":2496,"duration":25},{"text":"Host: And what I used to say to these guys is \"Look, have you got kids?\" He said \"Yeah.\" I said \"With your kids, just before they go to bed, what do you do? You don't put all the lights on full, give them a load of sugar, put the music up loud. You don't activate them, do you? No. You dim the lights, you soften your tone, you might read them a bedtime story. You're creating this kind of environment around them that is conducive to falling asleep.\"","offset":2521,"duration":30},{"text":"Host: But as adults we kind of think that we don't need that. I'm like \"Your kids need a bedtime routine, you might benefit from a similar bedtime routine to your children.\" It's about what is the signal you're giving to your nervous system, isn't it?","offset":2551,"duration":14},{"text":"Brian: Oh, yeah. Oh, yeah. We create more stimulus through the unprocessed junk, whatever we're not dealing with, and it's this compensation of just trying to get as much done as we can because in the world we live in, it's just like it's this barrage of information that we're all aware of and we all talk about it like we understand it, however, when you don't have boundaries like you've talked about how you have boundaries—like 7:00 PM comes you're done, like it's done, right?","offset":2565,"duration":31},{"text":"Host: It's early these days to be fair.","offset":2596,"duration":1},{"text":"Brian: Well, for for me it's really 4 or 5:00. Like, it's really 4 or 5:00 because I if I'll obsess, I'll I will obsess on my work and about you know like look, I tested you and I'll keep going and looking at your data and bringing it in and working on it because I'm in in a space where I'm like \"Yeah, yeah, yeah.\" But that'll also be there tomorrow and I really enjoy a lot of the other hobbies and things that I do and one of them's like cooking. So I get to go home and I get to start cooking. The way I cook is isn't pre-planned. It's \"What's what do we have and what can I create?\" And—","offset":2597,"duration":46},{"text":"Host: So you've but you're changing your nervous system's state.","offset":2643,"duration":3},{"text":"Brian: I am boom! going from work into no! now I'm in the kitchen, play, creativity, and when it's a little warmer I typically will come home and because it gets it gets dark later, I'll go home, grab Tiana and I'll be like \"We're going to the beach!\" and we will go body surf for like 45 minutes or an hour. But my mornings are the same way. Like, I don't actually go and sit and do breathwork all very often in the morning because I head out the door and I go walk for 60 to 90 minutes.","offset":2646,"duration":26}],"startTime":2129},{"title":"Unstructured Play and Setting Boundaries","summary":"The discussion moves to Brian's daily walking habit and his priority for unstructured play like surfing. They touch on the negative impacts of smartphones, the need to reclaim our attention, and how setting clear personal boundaries allows you to truly show up for others.","entries":[{"text":"Host: Yeah, I want to talk about this. This is really important. So there's doing breathwork whilst you're sitting down and still. Um. And the exercise you kind of illustrated and took people through before is it's kind of about paying attention and just sort of starting to notice what's happening. But there's also breathwork or paying attention to your breathing when you're moving, right? So—","offset":2672,"duration":28},{"text":"Brian: Correct. Correct.","offset":2700,"duration":7},{"text":"Brian McKenzie: Oh, I mean, I’m—I think my average is something like 17 or 18,000 steps a day.","offset":2707,"duration":6},{"text":"Host: And this is something different from five years ago.","offset":2713,"duration":3},{"text":"Brian McKenzie: Oh God, yeah. Okay. Yeah. Well, I mean look, I’ve been walking for quite some time. It’s just the level of walking because of what happens, what I’ve really invested in with walking is the same thing I’m invested in with cooking and/or going bodysurfing or even surfing, for that matter. Like, I didn’t even throw in, if there is a big enough swell, I shut off everything. I cancel appointments with clients. I will, like, and anybody who’s a surfer understands this, like, it’s done. Like, it’s out.","offset":2716,"duration":35},{"text":"Host: The thought that just jumped into my head was, it’s so counter to what we think life should be, which is about seriousness, and if you have a meeting or something there, you have to do it. And I understand that many people have jobs where they have to. Maybe, you know, you work for yourself, so you have the autonomy to do that whereas many people don’t. I accept all of that. But it just makes me think about culture and actually how the playfulness, the things that truly nourish us, those are the things that everyone tries to fit in on their one-week vacation, or maybe on a Sunday afternoon. Do you know what I mean? It says something about culture where these things have been relegated to being only when you have time, only when you’ve finished your emails.","offset":2751,"duration":47},{"text":"Brian McKenzie: See, this is—goes right back to process, in what we were talking about in the beginning. My work is the same way. I’m literally having fun like a kid with what I’m doing. And I’m enjoying that. And I’m not losing sight of that. I feel like at this point in my life, at 50 years old, I got rid of the kid that was a tortured soul and brought back the kid that was playing. And I’ve taken the things that I have learned and that I’m very passionate about, and I’ve learned to apply that to everything I’m doing. But I have set hard lines in the sand with these things.","offset":2798,"duration":46},{"text":"Host: Like what?","offset":2844,"duration":1},{"text":"Brian McKenzie: You don’t get me when I’m surfing. You don’t get me after 4:00 PM. My time is the most valuable thing I have, and your time is the most valuable thing you have. And attention is finite. Where I choose to spend my time, I choose to be there and invested in it in the most creative way that I can. And that’s just presence. I can’t do that without presence. If I’m thinking about the next meeting I’ve got to go to, and the deal I’ve got to close, and whoever I’ve got to—uh-uh. That’s not going to work. It doesn’t work for me like that. And then I love the job I’m at, but more importantly, I love every single person that is in my life, no matter how short that is. And then third, I feel like I’m a kid—and you’ll like this—I’ll feel like I’m a kid in the ‘80s playing again. The ‘80s, bro. The ‘80s.","offset":2845,"duration":56},{"text":"Host: Pre-smartphones.","offset":2901,"duration":1},{"text":"Brian McKenzie: Bro, the innocence and the risk-taking that I was in up to when I was living at that time. The craziness of it. But the—just the drive to explore. And that’s what walking does for me. The walking in the morning reminds me of when I was a kid and I lived behind this forest and I would just go—I was out, I was gone. At like six years old. Eight years old, I’d go walk out the back and I’d go into the forest and I’d go scurry around building tree forts, all this stuff. You know how hard that is right now for people and their kids? Like, to allow even a 10-year-old or an 8-year-old to be on their own?","offset":2902,"duration":47},{"text":"Host: Jonathan Haidt writes about this in *The Anxious Generation*. He’s talking about, you know, the negatives of smartphones at an early age and social media at an early age. But for him, the case he makes is not only about reducing that, it’s at the same time we need to increase free play, give our children independence, get them out taking risks, playing. The world is actually a lot safer for most of us than it used to be. Yet we’re behaving—like, I think he says something to the effect of, we are underprotecting kids in the online world and overprotecting them in the offline world. And I think he’s—I think he’s really onto something.","offset":2949,"duration":41},{"text":"Brian McKenzie: I—I don’t think he’s wrong. I mean, I read Johann Hari, you know, did a book—*Stolen Focus*. Yeah, *Stolen Focus*. That was a fantastic book as well. But, um, you know, and all of that’s provided me with information that I’ve been able to utilize, right? Like, I’m able to take steps to understand these things. It’s like, you know, I don’t have a true existence on social media anymore. It’s like from afar. And, you know, if I go post a video that I have to get on the app for to post that, I actually have to go to the App Store, install the app, and then I delete the app after I’ve done that. And I don’t go through and start scrolling ‘cause I know what’s going to happen to me. I’m not—I’m not immune to the things that are going on with you on there if you’re actually on there. I know—I go through the same thing where I get caught in the infinite scroll and I’m—I’m emotionally getting triggered by things and it’s like, oh that’s interesting, that’s going on. And people pretend like that’s not happening to them. And literally, there are people I have had conversations with that think that’s not affecting them. And they’re full of shit. It’s affecting all of us in a certain way. And real life, real life is with the people you’re closest to and the able—the ability to show up in an interaction. But that doesn’t mean you can’t go on social media and do the thing. It’s just like getting caught in that loop and going, oh there it is, I’m out.","offset":2990,"duration":94},{"text":"Host: It’s interesting you spoke about the boundaries you put in place, the clear boundaries you put in place, and boundaries are something that many people struggle with.","offset":3084,"duration":9},{"text":"Brian McKenzie: Oh yeah.","offset":3093,"duration":0},{"text":"Host: I used to struggle with, for sure.","offset":3093,"duration":2},{"text":"Brian McKenzie: Yeah.","offset":3095,"duration":0},{"text":"Host: And a lot of the time, there’s a pushback sometimes that it’s selfish. But the funny thing is that I imagine, and I put it to you, like, putting in boundaries is actually one of the most selfless things you can do.","offset":3095,"duration":15},{"text":"Brian McKenzie: Oh, yeah.","offset":3110,"duration":0}],"startTime":2672},{"title":"The Five-Gear Breathing System","summary":"Brian introduces his five-gear breathing system for exercise, ranging from strictly nasal breathing at low intensity to heavy mouth breathing at high intensity. They explore how these gears correlate to heart rate zones, metabolic efficiency, and fat burning.","entries":[{"text":"Host: Because what people don’t realize on the other side of boundaries is that you then—you then have something to give to the people you want to give to. Let’s talk about your gear system here, right? Because I think it’s—it’s really practical, and I think it’s going to be a tool that people can take away ‘cause we’ve gone pretty deep, right? And I think you can go that deep, but having some practical activities that you can start, you know, playing around with each day, I think it helps people go to that deepness. Do you know what I mean? It’s like, it’s easy to hear these concepts and go, well yeah, Brian, Rangan, alright for you guys, like, I don’t know, like, you enjoy doing the dishes. What are you guys talking about? I hate doing the dishes. So let’s bring in these five gear systems because I think they’re useful. Everyone moves their bodies. Maybe some not as much as others. But what are they and why do you think they’re so important for people to know?","offset":3110,"duration":60},{"text":"Brian McKenzie: Well, we developed the breathing gear system out of a discrepancy that we found in observing breathing as a dynamic through low, moderate, and high-intensity exercise.","offset":3170,"duration":15},{"text":"Host: So the gear systems apply to when we’re moving our body.","offset":3185,"duration":3},{"text":"Brian McKenzie: Correct.","offset":3188,"duration":0},{"text":"Host: It’s not about waking up and actually paying attention—no. So we’ve parked that. We’re now moving our bodies. Let’s say we’re going for a walk.","offset":3188,"duration":7},{"text":"Brian McKenzie: It’s about exercise. Go for a walk. And this is a perfect example, is if gear one cannot be used while someone is walking, we have a very big limitation, which is nothing but an opportunity. Don’t look at limiter as a negative. Limiter is an opportunity. So I have an immediate opportunity if I can’t have somebody in gear one. And breathing gear one is simple. It’s can you maintain one breath cycle in and out of your nose for greater than four seconds? So that would be like a two in, two out, right? Two—two-count in, two-count out. I get that upwards to somewhere around eight seconds for walking level, maybe ten seconds walking level effort for people. But that’s a good check. Does that mean you should go on a 90-minute walk while trying to apply gear one? Absolutely not. That means go spend like 10, 20 minutes really focusing, or from time to time every few minutes checking in and applying that breathing pattern to the effort you’re at with walking.","offset":3195,"duration":78},{"text":"Host: Okay, so let me frame it my way and see if this makes sense. Okay, so walking is, of course, it depends whether there’s an incline or it depends on the speed, but it’s, you know, it’s not the most intense of movement activities, right? So you’re saying you’re going for a walk around your block. Gear one is the ability to maintain a nasal in-breath and a nasal out-breath, so you’re not opening your mouth, and you want that in and out breath to be at least four seconds.","offset":3273,"duration":28},{"text":"Brian McKenzie: Yep.","offset":3301,"duration":1},{"text":"Host: Okay. If you cannot do that—okay, so it could be that you can only manage two seconds, or it could be that I can only walk around the block by opening my mouth.","offset":3302,"duration":10},{"text":"Brian McKenzie: That would be gear four.","offset":3312,"duration":2},{"text":"Host: Okay, so let’s work through this. Okay, so why is that a problem then? If someone can’t go around the block on a flat pavement and keep their mouth shut while they’re doing it, so exclusively nasal breathing, if they can’t do that, why is that something they should be paying attention to?","offset":3314,"duration":17},{"text":"Brian McKenzie: They’re not utilizing oxygen real well. Okay, to make sure you’re taking action after watching this video, I’ve created a free breathing guide that’s going to help you reduce stress, calm your minds, and boost your energy. In this guide, I share with you six really simple breathing practices that work immediately. Even just one minute a day will start to make a big difference. To receive your free guide, all you have to do is click on the link in the description box below.","offset":3331,"duration":30},{"text":"Host: Can we think about these five breathing gear systems like a car? You know, gear one to five, where, you know, we start off the car in first gear, and we go to second gear, and third gear, and fourth gear, and fifth gear? Is—can—is that—does that make sense?","offset":3361,"duration":18},{"text":"Brian McKenzie: Sort of. It sort of, because gear one would be much—you’d be in gear one should be primarily most of what you’re doing throughout your day. So gear two is a transition from gear one, obviously, to where I go from that four-count, and now I’m down and I’m probably more like three—two to three seconds per breath cycle.","offset":3379,"duration":26},{"text":"Host: But still nasal in and out?","offset":3405,"duration":2},{"text":"Brian McKenzie: Yes, I’m still nasal, right? Still nasal.","offset":3407,"duration":2},{"text":"Host: So gears one and gear two are both nasal.","offset":3409,"duration":2},{"text":"Brian McKenzie: And what I’ve found—what I have found over the last several years is that gear two is actually pretty limited. And you’re probably more effective if you’re—if you’re going to be prolonged at gear two, you’re actually more effective at jumping up to a gear four. So see, I’m skipping gear three. Because gear three is nose in, mouth out. And that’s largely a transitional gear for coming down.","offset":3411,"duration":35},{"text":"Host: And we’re going to go through this, but for people who like want to learn more, it’s all on your website, isn’t it? Like, you’ve got the gear system, and that is shiftadapt.com.","offset":3446,"duration":12},{"text":"Brian McKenzie: ShiftAdapt.com, right. So if they go to shiftadapt.com, you’ve clearly got the five gear systems there.","offset":3458,"duration":5},{"text":"Brian McKenzie: Yeah, I think we have it—I have that up—we have that up somewhere on that site. Um, if not, they can go to actually my—my X handle and it is literally pinned at the top of my—of my profile. And there is a systematic breakdown of it and where it relates and how it can work. Okay.","offset":3463,"duration":27},{"text":"Brian McKenzie: That said, skip gear three going up. So I’m in gear two, if I’m going to be there for more than a minute or two, I’m going to have somebody go to gear four.","offset":3490,"duration":10},{"text":"Host: And that is what? In and out through the mouth?","offset":3500,"duration":3},{"text":"Brian McKenzie: Yeah, it’s just relaxed mouth breathing.","offset":3503,"duration":3},{"text":"Host: Okay. So as your intensity is going up, you’ve moved from gear one to gear two, you’re saying on the way up, jump and skip gear three, and you’re now at gear four. So you’ve gone from nasal breathing in and out to mouth breathing in and out, but in a relaxed way. And then gear five is—","offset":3506,"duration":15},{"text":"Brian McKenzie: For—yeah, and for heart rate zone junkies, people who actually understand heart rate zones, gear four is happening somewhere between heart rate zone three and four. Okay. That is where that is occurring. Gear five is power mouth breathing. Meaning I’m actually really moving air like [breathing sound]. This is heavy-duty strength and conditioning sets. This is sprinting. At the end of sprints, if they’re short, or you’re talking 400-meter, 800-meter efforts, you’re going to hit those. If you’re hitting those for high intensity, gear five is coming into play. Okay. Gear five is something that I realized there were a lot of problems with not just myself that I noticed, but other people I’ve noticed who were not able to get that respiration rate above about 40, 45.","offset":3521,"duration":65},{"text":"Host: Yeah, okay. And we’ll come to my test here.","offset":3586,"duration":2},{"text":"Brian McKenzie: Uh-huh.","offset":3588,"duration":1},{"text":"Host: But just again, to make sure everyone’s following along. Right, so there are these five gear systems that you’ve gone through. As our intensity of movement increases, we in essence move up through the gears, just like we would in a car. Right. Why is it important for someone to know that? So what I mean by that is, let’s say someone is using gears four and five exclusively, i.e., they’re never nasal breathing, okay? They’re—they go for a walk around the block on a flat, in perfect weather conditions, and they’re breathing in and out through their mouth. Okay, so they’re not using one, two, or three, they’re straight into four. ‘Cause I think people need to know that to encourage them to start.","offset":3589,"duration":40},{"text":"Brian McKenzie: For the hundreds, if not thousands, of people that I’ve tested or looked at the—the data on currently, um, you have a breathing-related issue when exercising. And you have a big opportunity in maximizing your performance and output by—either and—look, I—I tested, um—so I tested Kawhi Leonard this morning, who’s an NBA player for the Clippers. Um, and he asked this very question, well how’s this going to help my performance? And I explained to him, well think of it like a season, right? If I can give you a tool that’s going to allow you to be more efficient with your breathing, you’re not losing that blood to your locomotor muscles. So you’re not getting more stressed sooner. You’re using energy a bit more efficiently. So game after game, if you don’t change this, by the time playoffs come, you’re pretty tired, you’re pretty exhausted, it’s pretty hard, versus you now have—you’re now recovering faster because you’ve got more capacity ‘cause you’re using oxygen later than you were earlier.","offset":3629,"duration":80},{"text":"Host: Yeah. So there’s a performance benefit, there’s a capacity benefit, you can go for longer before you fatigue. Someone we both follow on X, Alan Cousins, my interpretation of what I’ve read from Alan is, you know, if you’re keeping at that low heart rate, if you’re walking to the mailbox, if you can keep it all nasal breathing and at a low heart rate, that’s going to help you burn fat. There’s a metabolic benefit. And so for some people who maybe don’t want performance or not NBA players, well many people are trying to lose fat off their bodies, right? And there’s a metabolic reason to be able to access gears one and two, isn’t there? You’re going to—it’s going to help you burn fat.","offset":3709,"duration":41},{"text":"Brian McKenzie: You know, we definitively understand that if you’re breathing through your nose, you’re more aerobic than you are if you’re—","offset":3750,"duration":7},{"text":"Host: Which means you’re using up fat.","offset":3757,"duration":2},{"text":"Brian McKenzie: Correct. So think of your aerobic system is kind of like your—your checking account, right? And your anaerobic systems are your savings account. If I’m constant—my mouth—my mouth open is my savings account. You’re on limited time. You’re incinerating carbohydrates when that mouth’s open. So you’re using up—that’s not a bad thing. It’s just a thing. But I’m on limited time. If I’m more aerobic, I’m utilizing fatty acids more. So I’m burning fat, right?","offset":3759,"duration":33}],"startTime":3110},{"title":"The Pitfalls of Exclusive Nasal Breathing","summary":"Using the host's personal metabolic assessment, Brian explains the downside of exclusively nasal breathing during high-intensity exercise. They discuss how neglecting upper breathing gears limits oxygen utilization and VO2 max, and how developing all gears builds resilience to stress.","entries":[{"text":"Host: Okay. Now, I love all this. Right, so we’re in a situation where—and this is how the—the breathwork landscape has changed over the last five or 10 years, of which I’m a prime example. Okay, so—","offset":3792,"duration":13},{"text":"Brian McKenzie: Yeah, this is good.","offset":3805,"duration":1},{"text":"Host: Let’s go back 10 years. A decade ago, I can’t quite remember what was happening, but breathwork wasn’t as popular as it is now. Mm-mm. In my own journey through this podcast, which has been going for seven years now, the first time I really dealt with nasal breathing on the show was with Patrick McKeown many years ago. I had a lovely chat with Patrick. Um, he spoke to me about the BOLT score and, you know, the benefits of nasal breathing. And that progressed to me talking to you and all kinds of people about breathwork. James Nestor then releases this blow-up book globally, *Breath*, and talks about the benefits of nasal breathing. Is it fair to say that that message was needed because the vast majority of people were overbreathing and using their mouths more than their nose? But something has shifted where some people who get a bit obsessed like me take that nasal breathing message and try and do everything in our lives with nasal breathing and then we start to have problems in somewhere like a gear five, which is what I think you’re finding with me.","offset":3806,"duration":65},{"text":"Brian McKenzie: Correct. Yes. And—and I experienced the same thing. I did the same thing.","offset":3871,"duration":6},{"text":"Host: But it doesn’t mean nasal breathing is not important. It’s just that—","offset":3877,"duration":4},{"text":"Brian McKenzie: No, no, no. There’s a limitation, for sure.","offset":3881,"duration":2},{"text":"Host: Can—can we say this? That there was a deficiency of nasal breathing in society. The increased awareness has—has meant that less people are deficient now because they’re aware of it. But the problem is is that they’ve tipped it too far where they’ve actually now neglected mouth breathing, which is also important.","offset":3883,"duration":21},{"text":"Brian McKenzie: Correct. Go look at a tour cyclist who climbs Alpe d’Huez or whatever climb you want to talk about and they’re punching it. Their jaw is on the—their jaw is open and they are and they are moving that air fast.","offset":3904,"duration":14},{"text":"Host: Okay. So let’s talk about that then through the lens of the testing you did on me, right? So ‘cause I think this kind of illustrates this quite well.","offset":3918,"duration":7},{"text":"Brian McKenzie: Yeah. You were—you were not able to get above a 42 respiration rate, and you were at tidal volume, but I’m pretty sure you could get deeper.","offset":3925,"duration":12},{"text":"Host: Let’s break that down. Like some people won’t know what tidal volume is and what these terms—","offset":3937,"duration":4},{"text":"Brian McKenzie: Tidal volume just talks about how much air’s in the lungs, right?","offset":3941,"duration":4},{"text":"Host: So are we saying that I was good at the lower gears?","offset":3945,"duration":3},{"text":"Brian McKenzie: You were good at the lower gears. Oh yeah. Yeah, yeah, yeah.","offset":3948,"duration":2},{"text":"Host: So—so because I’ve put in the work at the lower gears and I’ve focused on nasal breathing, so it looked as though you were really happy with that.","offset":3950,"duration":7},{"text":"Brian McKenzie: Yeah. And metabolically speaking, look, like based on—you—you were between 0.95 and 1.0 for like 15 minutes.","offset":3957,"duration":11},{"text":"Host: And what does that mean for people who don’t know those terms?","offset":3968,"duration":2},{"text":"Brian McKenzie: So Rangan was at a low to moderate, moderate, moderate, high level. He was staying under 1.0 RER, which is respiratory exchange ratio, which means once you hit 1.0, you’re burning carbohydrates.","offset":3970,"duration":14},{"text":"Host: So I was able to burn fat.","offset":3984,"duration":3},{"text":"Brian McKenzie: You were still had some fatty ac—you were still burning some fat even at relatively, you know, moderate, moderate to high intensities, which I probably wasn’t doing five years ago. From a systems level, a metabo—so just that’s just looking at the metabolic. Now, here’s where—here’s where part of the assessment is different that I that I’m doing. And endurance community will understand this. I’m looking at tissue utilization of oxygen and I’m looking at delivery of oxygen. Okay? So I’m seeing how the hemoglobin is getting delivered, the oxygen’s getting delivered to the tissue, and I’m seeing how well that tissue’s actually utilizing that oxygen.","offset":3987,"duration":42},{"text":"Host: Okay. So many of us understand that oxygen comes into our lungs, right? And then from our lungs, it gets into our blood. You’re saying there’s two things to think about. Yes, you have to get the oxygen from the lungs to, let’s say, your muscles, right?","offset":4029,"duration":16},{"text":"Brian McKenzie: As soon as you start working, the muscles demand goes up.","offset":4045,"duration":3},{"text":"Host: Right. So the oxygen gets to the muscles. But you’re also saying that even if it gets there, it may not be being used efficiently.","offset":4048,"duration":7},{"text":"Brian McKenzie: Correct.","offset":4055,"duration":0},{"text":"Host: Right. So this is the kind of nuance that I think many of us are not thinking about. So okay, let’s go back to my test then. What was I doing? Am I getting oxygen there and it’s not being used efficiently, or am I not even getting oxygen there?","offset":4055,"duration":12},{"text":"Brian McKenzie: You’re getting oxygen there. However, you weren’t utilizing the oxygen well at these places.","offset":4067,"duration":7},{"text":"Host: Why?","offset":4074,"duration":1},{"text":"Brian McKenzie: The mitochondria aerobic system wasn’t getting enough oxygen or hadn’t been for for long enough because the nose breathing is happening with everything, and you’re more than likely doing it at higher efforts, which you confirmed with me. Yes, you are. So you’re not actually bringing in enough oxygen to actually help that so you’re the system can’t—or the tissue can’t, but the system’s fine.","offset":4075,"duration":25},{"text":"Host: It’s funny, a few years ago I went to Salford University in Manchester to do my lactate threshold testing, and I was right in the middle of my nasal breathing passion. And I was nasal breathing till right at the very end. And it’s really interesting. These guys have done thousands of lactate threshold tests. My test confused them because they weren’t seeing what they’re used to. They weren’t seeing the usual step changes. I don’t think at that time they’d seen someone who was nasal breathing right until the very, very final speed. And they were going to do some more work on me and then COVID happened, nothing—we didn’t actually do anything. But now it’s all starting to—the penny’s starting to drop now, where I’m like, ah, maybe—not maybe, I was overly nasal breathing, so they couldn’t even get the data they wanted to give me my training zones. Does that—is that making sense?","offset":4100,"duration":54},{"text":"Brian McKenzie: Dude, I watched this exact thing with—so I I have a pretty good relationship with the UFC PI and one of my—one of my clients owns the UFC so we went over to the PI to do all of our testing there with Roman, um, who who’s the exercise lead physiologist there. And he he did this exact same thing and literally with a minute and a half left, he decided to start mouth breathing—","offset":4154,"duration":27},{"text":"Host: That was me. That was exactly me.","offset":4181,"duration":2},{"text":"Brian McKenzie: And it that’s all it lasted. He fell off a cliff immediately afterwards and yeah, you were struggling your ass off because you didn’t—you didn’t have enough oxygen on board. And you haven’t actually developed the the the the muscles to be able to move that fast.","offset":4183,"duration":16},{"text":"Host: So I’ve developed the lower end, which is great and has metabolic benefits and performance benefits, but I’ve sacrificed or underdeveloped the top end.","offset":4199,"duration":9},{"text":"Brian McKenzie: Yeah, it’s like doing yoga with your primary breathing muscles and then asking yourself to go, you know, do powerlifting, right? It it’s just those two very different worlds, right? Or—","offset":4208,"duration":11},{"text":"Host: But you need both. It’s not—","offset":4219,"duration":1},{"text":"Brian McKenzie: Oh, correct.","offset":4220,"duration":1},{"text":"Host: So I was right to focus on the nasal breathing and correct that deficiency in my life.","offset":4221,"duration":4},{"text":"Brian McKenzie: Yes.","offset":4225,"duration":0},{"text":"Host: But now it’s like, hey Rangan, you’ve got that one. That’s okay. Keep doing that, but now we need to bring in—","offset":4225,"duration":5},{"text":"Brian McKenzie: Yeah. And the series of questions that I ask based on what I see is what validates what we see, right? And that was the questions that I had for you was like, hey, you know, are you doing any mouth breathing? You’re like, oh no, no, no, no. I don’t do you know, like I’m, you know, this is what I’m doing. And I’m like, okay, that’s what I thought.","offset":4230,"duration":19},{"text":"Host: Okay, so let’s say you’re going to give me a program and I’m going to work on certain things to do. And I guess some of that’s—well, maybe you can share. What are some of the things you would ideally have me work on?","offset":4249,"duration":11},{"text":"Brian McKenzie: We would, one, have you uh work at just above gear two. So working to like heart rate zone two, heart rate to heart rate zone four. We’d be doing some intervals there with mouth breathing, particularly gear four, not gear five. Gear five we would touch. We’ll touch with things like strength and conditioning. So I threw in with your program, at the—the—one of the main points of the limiters was let’s do some real str—let’s do some strength and conditioning at least twice a week where you’re getting that intensity up to where you are mou—wanting to move air like [breathing sound]. And that may just be after you finish squatting, but it hits that. And then we can gear down as a result of that. So I get up to a point to where I hit that when I’m lifting heavy and then that doesn’t mean the whole workout’s gear five at all. It’s we’re hitting those stages. You’re also doing structured cardio throughout the week at least twice a week to where we’re doing some interval type work where you’re working for a few minutes in gear four and then coming back into a gear one for some easier stuff. And making sure that we’ve got the the you know the working gear one in there.","offset":4260,"duration":86},{"text":"Host: So the gears that I have um underdeveloped over the past few years, the gear four and five, right? In essence, you’re saying now we’re going to start um redeveloping them. You’re going to now—you’ve got gear one and two going pretty well. Let’s now get gears four and five going well so I’ve got this real variety and depth in my system. I want to know what the benefits for me of doing that are. Like why should I do it? I feel good. Um, I can nasal breathe at low intensities. I’m going to do it, Brian. It’s not that. For the purpose of the conversation, why should I? Why shouldn’t I just keep doing what I’m doing?","offset":4346,"duration":42},{"text":"Brian McKenzie: You’re going to most likely see an increase in VO2 max.","offset":4388,"duration":4},{"text":"Host: Could you explain to my audience what a VO2 max is?","offset":4392,"duration":2},{"text":"Brian McKenzie: Maximum amount of oxygen you’re able to utilize, um, in liters per kilogram a minute. So your your body weight in kilograms and how many liters you’re using of oxygen or can you use in a minute. That’s just a rough reference point of the higher that VO2 max is, the less likely it is that that’s going to slip into a dangerous zone as you get older. The good news is you’re probably not in any danger. The the even better news is is that following what I’m going to lay out is going to most likely increase that exponentially. Meaning when you go on a walk, it’s even easier. You’re not using high-stress energy in the places you used to.","offset":4394,"duration":46},{"text":"Host: Is it fair to say that if you can develop this five-gear system with a variety of different movements and a variety of different breathing gears and heart rate intensity, you’re working out your stress response system?","offset":4440,"duration":16},{"text":"Brian McKenzie: Oh, oh yes.","offset":4456,"duration":1},{"text":"Host: Right. So how—look, given what we spent the first hour talking about, which is the way we respond to stress, the choice or perhaps not the choice, depending on how you want to frame it. In terms of we have a stressor and we have a response to that and we can train our response, we can get more helpful responses over time. Do you think that if people develop their five-gear breathing system, it would help them better manage stress in their own lives?","offset":4457,"duration":27},{"text":"Brian McKenzie: Across the board, yes.","offset":4484,"duration":2},{"text":"Host: ‘Cause it’s not separate, is it? It’s not how you deal with the driver who cuts you off is actually related to how you move your body.","offset":4486,"duration":7},{"text":"Brian McKenzie: Correct. And your—well, your breathing is a respondent to all of that. Breathing’s playing a role in all of that. So me learning how to actually—and this doesn’t—like, I want to be very clear. I don’t—I don’t, nor do I expect clients to go into the gym and or go and do cardio every time they go and work out that they’re implementing the gear system. A small portion of that training I will integrate the gear system and breathing into, but not the whole thing. It’s like if I’ve got a guy playing, you know, in the NFL or NBA, whatever, I do not want them thinking about the gears when they’re playing. No. Not at all. Not at all. That is part of training and then it should transcend over into is the is my client now seeing differences in how they’re playing and intuitively picking up on this process as they walk—as they go through that, right? Are they as soon as a play ends and you know, in NFL or are they immediately into [heavy breathing sound]. Do they do that intuitively, right? That’s where that should happen. However, the crossover is how I’m managing my day-to-day stress is going to show up in my training. And if I can’t maintain a gear one in something I should be able to maintain a gear one in, I now know I’m probably a little more smoked than I normally am, or if I had a a workout I was going to do that had some sort of gear in it, and that’s much harder, you are now seeing a response to stress that you have a feedback loop to to understand, oh wow, this is a lot more difficult or this is much easier today. I am really able to get work harder in this gear, right? That is a very—that is a crossover point for understanding, oh, I’m actually making some adaptations here towards expanding my potential for stress. Like, I I’m able to handle far more than I was prior to this. And here’s the thing, if I don’t use oxygen well, your physiology will catch you. We call these metabolic disorders. Like, it will catch you. And that doesn’t mean your breathing is the culprit here. It means, yeah, your breathing’s probably affected, your food’s probably affected because you’re making fast choices on that and you don’t care about where you’re getting your food from, just hypothesizing. Your training is too intense or it’s not intense enough, right? Like, the there’s all these variant—like, look you go look at research like it comes out all the time, but variance to training is the thing that is typically the best stimulus, not the same thing over and over and over repeating.","offset":4493,"duration":176},{"text":"Host: It’s so interesting this stuff. I mean, I’m I’m deeply fascinated like you about human behavior. A big part of my job for many years as a doctor has been to help patients make better lifestyle choices. And I used to think that knowledge was all the people needed. And I’m like, no, no, no. People need knowledge for sure, they need external knowledge, but what they need more than anything I believe these days is internal knowledge, that awareness of why am I going to this behavior. So let’s take sugar for example, right? And I think this relates to your work and the gear systems. If you’re chronically stressed and generating emotional stress by every way you interact with life—the the drivers, the boss, the traffic—and you’re thinking you’re a victim to the world, you did the math, you’re going to consume more sugar because you you’re using up sugar.","offset":4669,"duration":54},{"text":"Brian McKenzie: Your body needs sugar.","offset":4723,"duration":2},{"text":"Host: Exactly. And so you keep thinking that you need to hear another podcast on the on the negatives of sugar, but the problem is you already know that. You need to understand why do you need that sugar. What is going on upstream that is naturally means you’re going to consume that sugar and you can apply that to alcohol or three hours scrolling social media, whatever it might be. Like, what’s the upstream driver? Hey guys, I really hope you’re finding this useful. If you are and you want more content like it, please do check out my book, *Make Change That Lasts: Nine Simple Ways to Break Free From the Habits That Are Holding You Back*. It’s in all the usual places as a paperback, ebook, and as an audiobook which I’m narrating now. Back to the video.","offset":4725,"duration":45}],"startTime":3792},{"title":"Building Capacity Through Daily Walking","summary":"Brian provides practical advice to integrate the gear system into daily life, starting with a 45-minute daily walk using nasal breathing. They discuss how this baseline movement improves VO2 max, builds self-awareness, and acts as a powerful stress regulator.","entries":[{"text":"Host: Is it fair to say, Brian, then, because not everyone who um who is listening to this right now is going to be able to come to your facility, okay? Um, so in terms of practical advice that may work for most people—","offset":4770,"duration":17},{"text":"Brian McKenzie: Yeah.","offset":4787,"duration":0},{"text":"Host: I think a conclusion that I’m drawing is that everyone should be able to walk around their block keeping their mouth shut.","offset":4787,"duration":11},{"text":"Brian McKenzie: If you can’t go walk for at least 45 minutes a day, you’ve got—I my suggestion is find the time to walk for at least 45 minutes a day with your mouth shut and not on a screen. You’re laying the beginnings of a metabolic foundation, the stuff Alan Cousins talks in in like so well about. I actually believe it’s more—so do I. Yeah, you’re going to need more than—but if you can get 45, that’s a good start. But go get lost in that 45 minutes. Go explore.","offset":4798,"duration":38},{"text":"Host: But keep your mouth shut.","offset":4836,"duration":1},{"text":"Brian McKenzie: Keep your mouth shut and explore.","offset":4837,"duration":2},{"text":"Host: Okay, now let’s say someone tries that and goes, hey Brian, I’m really struggling, like I’m trying to go for a walk, I have to open my mouth after 10 minutes.","offset":4839,"duration":8},{"text":"Brian McKenzie: Take a few mouth breaths and go right back to nose breathing.","offset":4847,"duration":3},{"text":"Host: So it’s training. You’re like you don’t have the skill now but you can develop and cultivate it.","offset":4850,"duration":4},{"text":"Brian McKenzie: Take a few mouth breaths, go back to nose—go back to gear one.","offset":4854,"duration":3},{"text":"Host: Okay. So practice nasal breathing at low intensity.","offset":4857,"duration":2},{"text":"Brian McKenzie: At low—it it’s 80% of what you should be doing, right? So 80% of what you should be doing is really underneath that nose breathing thing. Then there’s the hey, if you can get that 45 minutes, great. Go work, spend your day paying attention to how much you’re talking, how much you’re getting stressed out. Find pieces of time where you can just bring it down for a minute or five. Just in just start with a consistent habit of controlling some breathing or paying attention to your breathing through your belly, your chest, your nose if you want, throughout your day if you can. Then, if you’re going to go train, if you’re going to go exercise and you really want to exercise, use your walking, the end of your walk and how you feel after walking as a basis for how hard you can train or what you can do that day. You’ll know. Your body is going to tell you through that walk how good you feel, if you feel great like and and try and mix up things. Like, try and do some strength training. We know definitively strength training is as important as VO2 max. Having muscle tissue so that you can get up off your your tail is is just as important as having a VO2 max, right? So maintaining strength, that doesn’t mean you need to go into a powerlifting meet. Like, it doesn’t mean you need to become a powerlifter. But finding complex movements and applying them, do that throughout the week. Maybe at least twice, if not three or four times a week if that’s your MO.","offset":4859,"duration":103},{"text":"Host: So you’re saying the 45-minute walk, right, or whatever you can manage, you’re saying have that daily walk. Yep. That daily walk does several things. Yes, it’s training you metabolically, it’s training your stress response system, but it’s also helping you tune into yourself. Because if you do it every day, and this is why I like repetition, you start to feel if the practice is the same and you feel different, you know that something else is causing you to feel different. i.e., oh I didn’t sleep well last night or I’ve got a lot of stress in my life at the moment. That walk felt a bit harder today than yesterday, it’s the same place that you’ve gone. So you’re starting to understand yourself better and the state of your nervous system through that daily walk.","offset":4962,"duration":41},{"text":"Brian McKenzie: 100%. 100%. Yeah. And for 20 minutes of calm just sitting, the brain looks looks looks good. But the brain after 20 minutes of walking looks real good. Real good. You start to see things because of blood flow changes and metabolic changes that start to happen that aren’t requiring high stress from that, and you kind of start to work through creatively a lot of the stuff that you’re working—whatever you’re working on, whether that’s work, whether that’s life, whether that’s whatever. And I’ve found that that is the place where I can really tap in and I I’m also very aware of like, you know what, I am definitely not lifting today. I’m still a mess and there’s no reason why I’m going to put load on my back or you know, pull heavy off the ground, whatever. Um for I’m going to do some probably some low-level cardio later or I’m going to go swim, right? Like um you know, or I’m just going to surf.","offset":5003,"duration":61},{"text":"Host: You’re getting in tune with yourself.","offset":5064,"duration":1},{"text":"Brian McKenzie: Yeah. I’m just—","offset":5065,"duration":1},{"text":"Host: You’re starting to learn about yourself. It’s paying attention to what’s going on inside.","offset":5066,"duration":3},{"text":"Brian McKenzie: You’ll start—you’ll start to figure out that that um when you don’t move, when you don’t walk, when you don’t exercise, your body starts to take a nosedive. Your stress levels go up through the roof, your HRV starts to drop, your resting heart rate starts to increase, your blood pressure starts to increase. Literally, I can watch this with I watch this with myself. My resting my morning lactate reading goes up if I don’t do anything the day before, right? If I don’t do any walking, if I don’t do anything the day before and I was talking and I was engaged in work or I was flying and all that dude, the next morning, I’m hot. I’m running hot. So I’ve got to go you know I don’t have to, I go walk and then I’m like, I don’t go crush it the next day. Like I have clients I manage their pro—like this is what I do, is I’m like yo, you’re landing in Abu Dhabi, you are not going and training hard. Yeah, yeah, yeah, I am. And I’m like, no, you’re not—like not if you want to sleep. Like, if you really want to get adjusted sooner, we’re going to get light, we’re going to go walk around, then it’s going to be hey here’s this low-level thing.","offset":5069,"duration":73},{"text":"Host: Yeah. It’s interesting that we we have all this data now coming out, well for many years, that um exercise is as good as an antidepressant or better. You know, we we—but the point I’m trying to make is that we’re so used to being a sedentary society that doesn’t move, we talk about all the benefits of exercise, but actually if you flip it, it’s like if we were all moving, it’s not that exercise has the benefits, it’s that not moving has all these disadvantages. It’s the same thing but reframed.","offset":5142,"duration":30}],"startTime":4770},{"title":"Light Exposure and Groundedness","summary":"Brian highlights the metabolic importance of morning light exposure and avoiding artificial blue light at night. They draw parallels between grounded cultures, like the Maasai, and Eastern philosophies, noting that true grounding always involves physical movement.","entries":[{"text":"Brian McKenzie: And and if you want to have if you want to do this even even at a higher level, get your ass outside and do it. Get exposed to the light, the morning light. Like it it’s critical that you’re doing this stuff. This is like how we were de—how we evolved, this is how we became what we are, as a result of being outside and having to go walk towards something to get it and then bring it back or however we were doing it. And I mean look, my house when it gets dark, it gets red. The only lights that come on are red. You know, I I’m ahead of this because I noticed the sensitivities I have towards the light. I I really get sensitive towards light in the dark. Like when I was driving at night, I would notice I would just be like, God I’m this is sucks because of headlights.","offset":5172,"duration":54},{"text":"Host: Yeah, light—light is as powerful as a drug. We just don’t see it like that.","offset":5226,"duration":3},{"text":"Brian McKenzie: 100%. Forget the name of the book, I read one, it was great on on on light and um sleep and you know light being the original uh toxic thing.","offset":5229,"duration":14},{"text":"Host: When you—I’ve got this—I think it’s a I think it’s within the iPhone you can put this like heavy red filter on your phone. And so I triple triple-click in the evening and it goes red. And then if you ever just put it back, you can feel the eye strain.","offset":5243,"duration":17},{"text":"Brian McKenzie: My my phone’s mostly red is is red most the time.","offset":5260,"duration":2},{"text":"Host: But you don’t—people we don’t realize how much we’re being strained and stimulated until you change it and then you flip back, you’re like wow, this is what most people are looking at.","offset":5262,"duration":8},{"text":"Brian McKenzie: What’s wild is I used to watch—so I’m a big entertainment guy, like I love movies, I love good shows, um and I grew up that way. Um I when I watch on the television now, I can’t watch on the TV for very long because it’s so stimulating. I watch on my iPad which I can put in red. So I everything’s in red. That light thing has a huge impact on the, you know, on the metabolic system. Like, how everything’s functioning.","offset":5270,"duration":32},{"text":"Host: Yeah, it’s so interesting, like thinking about our evolution um and how we live. It strikes me that because we’re so disconnected from, let’s say, our food supply, because we’re so disconnected from how we used to live, because our lives are so overly busy and chronically stressed now, it’s as if we all need education now on what diet we should be consuming, how we should be breathing, how much we should be moving. Whereas, I remember last summer, uh my family and I went to Kenya for four weeks, and we went on safari, and one day we spent at uh a Maasai camp. And there’s many things I noticed, but one of the things that struck me, hanging out and interacting with some of the Maasai that morning, was there was just a quietness, a groundedness. I was just struck by this kind of grounded presence that you don’t often see in the modern world. Yeah. But a lot of people around you you meet in in modern life now are quite they’re like I used to be, in your head, you’re not grounded, you’re anything but. Do you know what I mean? How how do you think about being grounded and its relationship with the breath?","offset":5302,"duration":77},{"text":"Brian McKenzie: Um, I mean, there’s nothing to fix with any of us, to be clear. But when you’re grounded in yourself and you’re living, you know, how you truly want to be living, you don’t need to change you don’t need to change a whole lot because the process of what you’re doing already involves all of that. I haven’t met anybody—I’ve yet to meet someone who is totally grounded that is not highly physically active in some way. I have not. There is no Eastern philosophy without a physical practice. None of them. None. Why? I’ve looked. Why? Because they understood. It was about like monks up in isolation that I brought up with the, you know the the prison before, they walk every day. They’ve got some sort of practice. Go look at the Shaolin monks, for crying out loud. You know, um you go look every philosophy you’ve got yoga, like it was about movement. And moving into positions, asanas.","offset":5379,"duration":21},{"text":"Brian: ...and getting into position and being able to breathe in that position. Because if you can't breathe in that position, you don't own that position. That position owns you. Yeah. You know? And so anyway, it's I'm I'm very interested in people that that are very grounded and I'm like I'm I'm blessed with what I get to do and how I get to do it.","offset":5400,"duration":26},{"text":"Brian: Um, but I'm more so just I'm I'm just playing, man. That's all I'm doing.","offset":5426,"duration":5}],"startTime":5172},{"title":"Oxygen Delivery and the Bohr Effect","summary":"Returning to the host's metabolic assessment, Brian explains the Bohr effect and the critical relationship between CO2 and oxygen utilization. They conclude that balancing breathing gears aligns the aerobic system with the parasympathetic nervous system.","entries":[{"text":"Host: Yeah, I love it, Brian. Absolutely love it. Couple of loose ends in my head I just want to tie off before we end the conversation. We spoke before about we get oxygen into our lungs and then we have to deliver it to our tissues or our muscles, but then utilize it when it's there as well. And I think you said that with me, I'm able to get it to the tissues and muscles, but I'm perhaps not as efficient as I could be at using it there. First of all, is my recollection correct?","offset":5431,"duration":30},{"text":"Brian: Correct.","offset":5461,"duration":1},{"text":"Host: Okay. So how am I and through me then the people listening, if they have the same problem, how are they going to improve, you know, the usage of that oxygen at the tissues? For me, is it that high intensity? Is that what it is?","offset":5462,"duration":16},{"text":"Brian: It's not just high intensity. It's it's even moderate intensity and bringing on enough oxygen for the for the tissue to use it, versus limiting what you're you're doing, right?","offset":5478,"duration":13},{"text":"Host: So I'm artificially limiting...","offset":5491,"duration":2},{"text":"Brian: Mm-hmm. You are you are controlling things too much.","offset":5493,"duration":5},{"text":"Host: Yeah, doesn't sound like me.","offset":5498,"duration":2},{"text":"Brian: You have controlled things too much and not allowed the system to do its job.","offset":5500,"duration":7},{"text":"Host: So I need to let go.","offset":5507,"duration":1},{"text":"Brian: What it was communicating. Let go. Let go. When when the when you feel the change, that's we're just re-aligning feeling that change.","offset":5508,"duration":11},{"text":"Host: So as I start to let go and allow myself to breathe in a whole variety of different ways, at a whole variety of different intensities. So appropriate breathing for the level of movement and intensity. Are you saying that because those things start to then match up, that then means that my oxygen delivery to the tissues and the usage is also going to start to match up? Whereas now there's a discrepancy.","offset":5519,"duration":27},{"text":"Brian: Yeah. And because of that under-utilization issue, that's probably over time created the issue with your tissue being able to use that oxygen even at lower rates, right? So the ability to get that going again is what we want that's what we're trying to train. But the strength training actually helps with that as well, right? Because we're looking for better mitochondrial development, and that comes in many different fashions. Walking, yes. However, strength training, yes. It just comes in a different way. It's just high intensity, right?","offset":5546,"duration":48},{"text":"Host: And I've heard you say, Brian, the greatest hack for your mitochondria is working on your breath.","offset":5594,"duration":6},{"text":"Brian: Yes. Well, yeah.","offset":5600,"duration":1},{"text":"Host: Which again, I don't think a lot of people are thinking about. And sort of tying this up to the start of the conversation, breath is that central piece that so many of our behaviors, our emotions, our ability to perform, they come off as a byproduct of our ability to, like, breathe appropriately and efficiently, right?","offset":5601,"duration":20},{"text":"Brian: Yep. And I don't, you know I mean, I don't know how many people have your issue. I've only seen it, like, four or five times. Um, granted every person has been very aware of the breath game for quite some time, right?","offset":5621,"duration":16},{"text":"Host: Yeah, because I guess people like me who are really interested...","offset":5637,"duration":3},{"text":"Brian: Well, anybody who read Breath typically was like nasal breathing's everything, and that's not on James, James wasn't saying that's everything...","offset":5640,"duration":9},{"text":"Host: I was ever since I first came across Patrick McKeown however many years ago, like, I have been oh, right, I'm going to go and walk nasal breathing, but I probably overdone it. And I get that.","offset":5649,"duration":11},{"text":"Brian: Look, man, I've been staring at this down the down the lens of a metabolic cart for quite some time and seeing the changes and and what it like I mean the changes simply in walking with one's mouth open versus one's mouth shut were eye-popping.","offset":5660,"duration":19},{"text":"Host: In terms, and make that really practical, in what? In terms of your ability to burn carbs or fats?","offset":5679,"duration":5},{"text":"Brian: So if I'm overbreathing, which isn't what your problem is, right?","offset":5684,"duration":4},{"text":"Host: So that's not my problem.","offset":5688,"duration":2},{"text":"Brian: Which most people, most people are have an overbreathing issue. Yeah. So if I'm overbreathing, I'm definitely not getting oxygen to the tissue, right? So I'm I'm the sympathetic nervous system clamps down and I'm point I'm not going to be I am going to be screwing up the the dissociative curve of oxygen's utilization because I have I'm getting rid of excess CO2. So if I overbreathe, and if anybody wants to do if anybody's done Wim Hof, they've felt what overbreathing feels like. That's where that high starts to to kick in. But what's happening is is things are clamping down, right? And so we're limiting how oxygen gets used and so the red blood cell can't offload as much oxygen because there's not enough CO2. Oxygen is a useless, destructive molecule without CO2, and CO2 is what knocks that helps knocks that oxygen molecule out of the red blood cell to go to the cell to be used.","offset":5690,"duration":68},{"text":"Host: Also, Brian, just to finish off that loop as well, given what I shared with you right at the start, which is that I feel compared to last time I was here in LA with you that I'm a different person. My nervous system sits differently. I'm calmer, I'm more present. Do you think in any way that matches my journey with breathing, i.e., perhaps I was overbreathing like most of us five-six years ago, and by working on the lower ends and the nasal breathing, maybe neglecting the higher ends, but by working on that lower end, do you think there's any correlation between that and the fact that I'm less reactive these days?","offset":5758,"duration":42},{"text":"Brian: There's direct correlation between aerobic and parasympathetic nervous system, and sympathetic nervous system and anaerobic.","offset":5800,"duration":9},{"text":"Host: So if so it completely matches up.","offset":5809,"duration":2},{"text":"Brian: It it is direct correlation.","offset":5811,"duration":1},{"text":"Host: As I've worked on this lower end, my parasympathetic nervous system's much better able to function.","offset":5812,"duration":5},{"text":"Brian: If the lion walks in the room, your system goes oh, we need immediate action. You think it's going to go use fatty acids for that? It can't.","offset":5817,"duration":10},{"text":"Host: Needs carbs for that, it needs to go to sympathetic.","offset":5827,"duration":2},{"text":"Brian: More carbohydrates or it needs, yeah, creatine phosphate system. It needs instantaneous, but oxygen's a part of that, in when I go use tissue, it it'll deplete that. Like we've seen that. Like, uh, there is no one or the other, it's like how quick that's going to happen.","offset":5829,"duration":23}],"startTime":5431},{"title":"Conclusion: The Freedom of Saying No","summary":"Brian shares where listeners can find his courses and offers final words of wisdom on learning to say no. He encourages the audience to reframe daily obligations from 'I have to' to 'I get to,' cultivating true freedom and presence.","entries":[{"text":"Host: Well Brian, I love talking to you, I love hanging out with you. Um, we've covered so much, we've gone into so many different areas. As we wind this down, if people want to learn more about you, they want to work with you, they want to do your online courses that you guys run, where should people go?","offset":5852,"duration":16},{"text":"Brian: shiftadapt.com. So s-h-i-f-t-a-d-a-p-t dot com.","offset":5868,"duration":9},{"text":"Host: And and what's on there, what can they like...","offset":5877,"duration":2},{"text":"Brian: We we we still have a membership site, and we have a lot of stuff a lot of courses, things like that or webinars we've done that we talk about a lot of this stuff. We'll be releasing a a number of programs etc., that'll be on a little bit higher level than that that people can go do. And then on the upper tier of all of that is actually hiring my business partner and or I.","offset":5879,"duration":26},{"text":"Host: To actually work with you one-on-one.","offset":5905,"duration":1},{"text":"Brian: Yeah, so Emily Hightower who I work with, uh, she's on the other end of the stress here where she's helping with developing tools and regulating nervous system on the day-to-day throughout, you know, like hey, how are you managing this at in the moment type of stuff? Like what's your life look you know what's going on in life?","offset":5906,"duration":23},{"text":"Host: Yeah, amazing. We've covered so much. Um, emotional reactivity, the power to choose our response, breathwork, the different gears, the metabolic benefits of being able to access all the gears, etc. etc. To bring it all together, like Brian, if there's someone who has followed our conversation and still with us, and is like, yeah, you know there's something there for me, right, there's something Brian was talking about that applies to me. I haven't taken my breath seriously, I haven't taken my levels of physical activity seriously, or whatever it might be. How would you help that person? They feel stuck, they feel lost, they feel unmotivated. But at the same Brian, give me some inspiration, what is your final piece of advice? What would you say to that individual?","offset":5929,"duration":52},{"text":"Brian: Learn to say no. Learn to say no to the things you don't want to do. And that is a very that actually goes far deeper than just saying no to something you instantaneously know you don't want to do. It's it's looking at those sexy shiny things that are of excitement and being able to slow it down enough to say no to maybe getting into a business deal or taking a job that you really don't want to take, um, but you think you do because you got to make the money and maybe you could go figure that out another way, or you know, can you change some lifestyle habits? Um, I think no is the path to freedom. Because you'll only be doing the things you truly want to be doing if you learn to say no to the things you don't. And I have found that because of that, I'm surrounded by the people I want to be surrounded by. And and that's it. Um, it's simple. So um, if you can live the life you want, but I mean just applying the principles of making your day a process. Like literally make it a process. Like the dishes, right? Like I get to go drive to work. Yeah, you get to. Or yeah, I get to have a job. Or yeah, I get to drive in traffic. Because I get to live here, because I get to do these things. It's very different than I have to.","offset":5981,"duration":83},{"text":"Host: Yeah, love it, Brian. Thanks for everything you do. Thanks for the help you're giving me personally and for coming back on the show. Really appreciate it.","offset":6064,"duration":8},{"text":"Brian: Thanks for having me, love you dude.","offset":6072,"duration":2},{"text":"Host: If you enjoyed that conversation, then I think you're really going to enjoy this one.","offset":6074,"duration":4},{"text":"Guest: I want people to wake up and realize the creative nature of love, health, harmony, because that is available, and yet we struggle.","offset":6078,"duration":15}],"startTime":5852}],"entries":[{"text":"Host: Breathing is not just about your ability to run a fast 5k on Saturday or your ability to relax in yoga. It is metabolic health, it's cognitive health, it's hormonal health. Like, your breath is at the center of everything. And therefore it's striking that so many of us don't pay attention to our breath, or even know how to manipulate our breath to change our states, right?","offset":0,"duration":26},{"text":"Brian: Yeah. Yeah, yes, and the real thing that I feel would benefit most people is being aware of it, right? And my understanding of really being aware of one's breathing is, if you can be aware of it, you can let it happen and pay attention. And there are times, yes, you can use breathing to regulate and and become more aware of what's going on.","offset":26,"duration":28},{"text":"Brian: But if you're not willing to confront the pain that has you in this reactive state to stress—from wherever that originates, typically childhood—um, and you don't that doesn't mean you need to go relive childhood, it's like \"Well, oh, I was in a defensive pattern because my environment was incredibly hostile and everybody was fighting when I was young, so no wonder why I've got my dukes up all the time in anything in what I do,\" right?","offset":54,"duration":27},{"text":"Brian: Um, I'm really at a point where it's like if if you're just going around that shit, if you're going around that and just trying to control breathing and and go about it that way, you're not going to find that root. The root will be disguised. It'll be camouflaged.","offset":81,"duration":22},{"text":"Host: You've said, haven't you previously, there is no amount of breathing that will change the pain you are not willing to confront.","offset":103,"duration":5},{"text":"Brian: Yeah.","offset":108,"duration":1},{"text":"Host: One of the things I wanted to talk to you about today is this idea that our breath is intimately linked with our nervous system and how we then view the world. So if we talk about the pain that we are not willing to confront, right? So let's say there is pain from childhood because of A, B, and C, right?","offset":109,"duration":22},{"text":"Host: That can then result in some sort of dysfunctional breathing patterns potentially, I'm guessing, as a consequence. So then if you have compensatory breathing patterns because of trauma, let's say, then it can be hard to address the pain sometimes if you're in this constantly wired state.","offset":131,"duration":26},{"text":"Host: So presumably, being able to work on your breath and maybe change things a little bit can change the state of your nervous system which might then allow you to go inwards and confront the pain.","offset":157,"duration":14},{"text":"Brian: Yes. What you first touched on when you when you began the question was, you know, we we've gotten to a place where we're kind of just we want to just fix the problem or we want to fix how we feel. That's what I run into is people just want to feel differently. People don't want to actually change their behavior.","offset":171,"duration":26},{"text":"Brian: Um, and what we're talking about right now is a behavioral pattern that breathing follows and although you could there there is some school of thought that breathing is behavioral, I'm far more under the impression that that physiology has more to do with it.","offset":197,"duration":19},{"text":"Host: What does that mean for people?","offset":216,"duration":1},{"text":"Brian: So, uh, you know, if pretending that a, you know, lion walks into the room, there is a heightened arousal state, there is a sympathetic response to that. Um, and the first stage of that is there is the stimulus, right? So we've got some sort of stimulus. Somebody cuts in front of me while I'm driving. There's a stimulus.","offset":217,"duration":23},{"text":"Brian: Um, the second part of that is the nervous system's response to that. My sensory system which operates through communication through an electrical network that is firing things, it goes on high alert pretending as though somebody cut in front of me. The first thing anybody does when they're driving if they see that is they grab the wheel and they hit the brakes, right? That is your nervous system responding, reacting to that stimulus.","offset":240,"duration":26},{"text":"Brian: After that, the third part of this is the physiological processes involved in that and and the driving of behavior. So my sympathetic nervous system goes up. I'm releasing neuro-neurotransmitters and hormones, adrenaline, right, norepinephrine—these things are released real-time. And so that third part of the stimulus response now becomes the first part of the stress reaction.","offset":266,"duration":28},{"text":"Brian: And each of these is universal to us all. And I've got this happening and somebody cuts in front of me and this stuff happens. So all of these chemicals in my biochemistry is changing in order to manage what it is my system is putting off, right?","offset":294,"duration":18},{"text":"Brian: So let's just go with adrenaline as an easy one. My response to adrenaline in anything when I'm not prepared for it is \"dukes up,\" per se. It's confrontation, it's personal. So then the second part of that is the recovery phase should happen.","offset":312,"duration":20},{"text":"Brian: So it's like if somebody cut in front of me and I didn't actually get pissed off, I'm like \"Oh, whatever, let them go.\" That is a response that's like going and lifting some weights and and resting between sets.","offset":332,"duration":14},{"text":"Host: Okay, let's just pause there, Brian, because this is really interesting. Yeah. Our stress response is hardwired within us. Okay, so—","offset":346,"duration":8},{"text":"Brian: No avoidance.","offset":354,"duration":1},{"text":"Host: Yes, if there was a lion that just came into this room now, we probably would change quite significantly in terms of how how our being is, how we're interacting, our posture, our muscle tension, everything will change, okay. You're driving on a road, wherever you live in the world, and someone suddenly cuts in front of you, so you slam on the brakes, okay. That's an automatic response, right? You've slammed on the brakes.","offset":355,"duration":26},{"text":"Host: Is it possible to get to a point where that doesn't even generate the physiological changes? So if you work on this enough—and we're going to through loads of practical things in this conversation—is it that everyone will have the physiological response and then we train ourselves to not respond to the adrenaline, or is it different?","offset":381,"duration":24},{"text":"Brian: Here's what's, you know, so funny enough, you know, part of Andrew Huberman's research before he had his podcast at his lab when I was involved with his lab, they were in that they were in his VR looking at stress from everybody. From people who were who are on anxiety medications all the way up to like Navy Seals.","offset":405,"duration":22},{"text":"Brian: Everybody responds to stress. Everybody responds to the stress. In what capacity and how they come off that stress is the important part.","offset":427,"duration":11},{"text":"Host: Okay, so even if you're a calm, non-reactive person—","offset":438,"duration":4},{"text":"Brian: You're going to. The when the lion comes in the room or somebody cuts you off, you will, your body naturally reacts to it. It's the behavior that you choose to follow as a result of that.","offset":442,"duration":11},{"text":"Host: Got it. So it is what Viktor Frankl says. Um.","offset":453,"duration":3},{"text":"Brian: This is where choice happens, right?","offset":456,"duration":1},{"text":"Host: Is that where breathwork can potentially come in for some people?","offset":457,"duration":4},{"text":"Brian: A hundred percent. This is where, this is where breathwork does come in. So this is where intervention comes in. When I have an emotional reaction to something that I don't like or I don't like the way I feel, or I don't like what I said, um, and I want to work on that, that is where the opportunity for intervention comes in.","offset":461,"duration":19},{"text":"Brian: So I can take a breath, I can take several breaths, I can come down. And if I can bring myself down, then I might have the opportunity to bring reality on. Did that person who cut in front of me start their day by going \"I'm going to go find Brian McKenzie and I'm going to cut in front of him today and I'm going to intentionally piss him off\"? No, that is not what happened.","offset":480,"duration":26},{"text":"Brian: In at least in my this world I currently live in, now the old world I existed in, I might narcissistically have pulled that one off, right? But in the moment you will start to arc stories for the emotional reaction that you have to things and that's where the breathing is starting to get away from you as well. So my breathing tends your breathing will do things in these places. It's simply responding to the activity and the change that's going on.","offset":506,"duration":29},{"text":"Host: These things are so linked, physiology and psychology, psychology and physiology. Oh, yeah. And the thing I've really been thinking a lot about, Brian, and I'd I'd love to hear your perspective on this, is I feel compared to who I was five years ago that I interact with the world in a completely different way. Most of the time I actually feel really calm and I feel that when the stimulus is happening, I seem to have this ability now to know that there is a space and go \"Yeah, I'm not reacting to that,\" right?","offset":535,"duration":42},{"text":"Host: Now people will say, like, I've covered trauma on this podcast on many occasions with people like Gabor Maté, Dan Siegel, Bessel van der Kolk, all these kind of greats in the trauma world, right? And a lot of people will say, and I agree, that trauma can be stored in the body. Yeah. With our certain patterns, our breathing patterns, maybe we're slightly more flexed, whatever it might be, we have these patterns.","offset":577,"duration":21},{"text":"Host: And so there's a school of thought saying that you can't change that trauma with the mind, you do it through the body. And I believe for some people that is the mechanism to change it, not that you can separate the body and the mind, okay. I feel in my life a lot of it has been cognitive. So I had a conversation a few years ago with an Auschwitz survivor, Edith Eger, when she was 93.","offset":598,"duration":32},{"text":"Host: That conversation changed my life, Brian, because she was able to reframe her whole existence in Auschwitz to the point where she said to me that the greatest prison you'll ever live inside is the prison you create inside your own mind. And that's from someone who lived in the hell of Auschwitz, right? So that really landed for me.","offset":630,"duration":18},{"text":"Host: So I would for years practice if I ever got emotionally triggered in the day—I perhaps couldn't do it in the moment—that evening I'd reflect and go \"Ah, that situation was not inherently triggering, that situation was not inherently offensive, if it was, everybody would get triggered to it, everyone would take offense at it. No, no, there's something in me that is being activated by that stimulus. So if I want to change, I have to find in me, instead of putting the blame elsewhere, externally, I have to figure out what insecurity, what inadequacy, what is being triggered inside of you.\"","offset":648,"duration":37},{"text":"Host: And by doing that regularly, I now feel that it's become my default response. Now at the same time, I also do work on my body. I have an amazing movement coach, I work on my breathing. I now have access to certain movement patterns that I didn't have five years ago, so I can't say what exactly it was. But I don't buy that it necessarily always has to come from the body or always from the mind. These things are connected. Does does that make sense, Brian?","offset":685,"duration":26},{"text":"Brian: Oh, yeah.","offset":711,"duration":1},{"text":"Host: Because I don't know, people say \"Well, how how come you're so calm these days?\" I'm like \"I have done a combination of things. I've done the work, I've constantly looked inwards at my triggers.\" Now breathwork, I would say that's a very big term that people interpret, you know, in all kinds of different ways. Yeah, for sure, that has helped me as well, but so has cognitive reframing.","offset":712,"duration":23},{"text":"Brian: Yes. Yes.","offset":735,"duration":1},{"text":"Host: So I don't know if you can sort of pass through that through the lens of what you're saying now about we encounter a stressor and our stress response goes up. So how come I can be calm now?","offset":736,"duration":10},{"text":"Brian: The simplified version of, you know, how I was getting complex is, is it's like if I choose not to respond to somebody cutting me off—and this is just you know insert whatever you want, insert whatever you want: your father saying something to you you know or what your—","offset":746,"duration":18},{"text":"Host: Whatever it is that triggers you.","offset":764,"duration":1},{"text":"Brian: Your wife or your husband saying something to you that's popping you, right? If you choose not to allow that to go beyond that moment, you've now learned how to adapt. You've now learned how to stay with it and and you don't have to take that personally, right?","offset":765,"duration":23},{"text":"Brian: So if I choose to let the guy cutting me off go, I now adapt and I now am over here in the logical side of something, real I'm rooted in reality. And I think what what's really important here is that over here my core values are are the anchor point. For me, my core values sit with things like authenticity. It's like \"Just be real, just be authentic and you're in my world if we meet.\" And I'm I'm happy to in and if it's just if it's not authentic I'm out, I don't have time for that right now.","offset":788,"duration":40},{"text":"Host: Here's a question, Brian. Yeah. If your nervous system is constantly wired, uh chronically activated, and you've never learned how to switch it off or calm it down, is it even possible to know what being authentic is?","offset":828,"duration":19},{"text":"Brian: No, not in that state, no. Because you're in a chronic stress response.","offset":847,"duration":4},{"text":"Host: Yeah. And then if everyone's if everyone's walking around in a chronic stress state, of course no one's being authentic.","offset":851,"duration":5},{"text":"Brian: I mean a lot of my this is what a lot of my clients actually—not the professional athlete side, I mean although on occasion I'll get a professional athlete that's dealing with something like this—but most it this is more of the you know private the clients that are like the executives, right? These are the guys and gals that are functioning up here all day all night and then they go and train and the way they train mimics the way they work and and they don't realize that they're they're in this heightened stress state, right?","offset":856,"duration":28},{"text":"Brian: And so the third part of that stress reaction—so let's just pretend you I didn't let go of the guy cutting me off. I've now brought in more hormones and neurotransmitters that are now blocking an adaptive process. Now we've onboarded adrenaline again because we're now making up a story about what we're going to do to this person, or they're taking advantage of me, or they're doing this to me. I'm essentially victimizing myself in some capacity, right?","offset":884,"duration":35},{"text":"Brian: And so I now go at this with a non-adaptive process that if I repeat this enough and I don't let that go, I remain in what's called chronic stress. That does not allow for that parasympathetic arm of my autonomic nervous system to come back online as well. And that if that goes on long enough I can have a multitude of different responses that occur with that. I can stay in a heightened stress state or I can actually retreat and then be pulled down into this more depressed nervous system state where I I can't get out of bed, I can't do these you know.","offset":919,"duration":39},{"text":"Host: You you say it's non-adaptive, but could we not make the case that we're always adapting, the question is what are we adapting to and what is our response?","offset":958,"duration":10},{"text":"Brian: Yeah. So the new adaptation becomes this heightened or or whatever state that is now not allowing me to recover. It it'd be the equivalent of just lifting weights. Like I I go to lift weigh—I just go I go squat. And I just keep squatting all day. And I keep every set after set after in I'm fatigued but I'm still going and I'm still going and I'm still going.","offset":968,"duration":30},{"text":"Brian: And then I might let off the brakes that evening and decide to go home and sleep if I can because my nervous system's now just torched and I'm hungry and I gotta eat, and then I'll wake up the next day and I start doing it all over again the moment I get to the gym.","offset":998,"duration":13},{"text":"Host: Yeah. This is such a great analogy because what you just said through the lens of you squatting is how many people are living their daily lives. Now through the lens of what we've just been talking about, you're known for many things around the world. Um many people would regard you as a expert in human performance. What does human performance mean to you?","offset":1011,"duration":25},{"text":"Brian: Um, well, I don't think I'm an expert, I'm more of like a specialist. Um, I'm still learning every single day about this. Um, performance for me is a path towards growth. And most of what I've found even at the elite level is that if we can unlock a lot of the mental constructs that we've built, then there's a freedom in that that allows us to really see where the limitations are in what we're doing.","offset":1036,"duration":41},{"text":"Brian: When I went and worked at San Quentin Prison for six months, I ran a program, and um I'd go in every Friday and work with these guys. And I when I first went in there I, you know, it had occurred to me I'm like \"Okay, so these guys are in prison, most of these guys are doing you know 25 or more. Um but I do know the effect of men in men and women in prison to the outside world.\"","offset":1077,"duration":28},{"text":"Brian: So if you don't understand that, take the time to kind of understand that, which is part of the reason why I was going into these prisons was to kind of help help affect some sort of change in that or growth in that place. But the thing I thought about when I went in there was I explained to these guys: \"Look, every year there are a group of individuals that decide they no longer want to participate in society, and so what they do is they get they give away everything they have and they typically will move to the mountains of Asia somewhere, they will isolate themselves with a few other people, they'll eat once or twice a day and they'll breathe and meditate most of the day and at the end of this they find enlightenment.\"","offset":1105,"duration":43},{"text":"Brian: \"What is the difference between you and them? They committed a crime and they are stuck in a place. How do you want to do your time? Do you want to figure this out? Do you want to figure out how you're doing this? Do you want to evolve and grow towards something differently? Because there are people choosing to live the life you're living for like punishment and they're finding enlightenment through that process, right?\"","offset":1148,"duration":32},{"text":"Brian: \"However, that's what I think about with anybody and everybody. How do you want to win? Do you want to win and be miserable?\" I mean, I seen the Michael Phelps documentary and I've worked with some of the athletes that were in that documentary and I'm like \"I know what this is. It's the same thing going on out here. Just because they're competing in a physical aspect at something doesn't mean there isn't something in that mind that's kind of—\"","offset":1180,"duration":28},{"text":"Host: So so so make it relevant for someone who's listening, Brian, who is kind of they're not an elite sportsman, okay. They just want to live a better life, right? They they they don't want to be reactive all the time and chronically stressed and unable to switch off and snapping at their partner or their kids. What is the relevance of what you do that's going to help that person?","offset":1208,"duration":23},{"text":"Brian: I guide people towards a process. Tao Te Ching, Sun Tzu, Bruce Lee were very impactful for me and there's a very famous Bruce Lee quote that I have everywhere: \"All goals apart from the means are an illusion. Becoming is a denial of being.\"","offset":1231,"duration":25},{"text":"Host: Why does that mean so much to you?","offset":1256,"duration":4},{"text":"Brian: That gives you unlimited possibility. If I'm not invested in the process, I'm somewhere else. Look, I was doing the dishes this morning and putting away the dishes as I do most mornings when the dishes are done. If there are dishes I go and I put them away. And I don't get upset in the slightest about the fact that I have to put them away. In fact, I found myself in joy. Oh, man, as I was putting away and I was reflecting on the fact that I had earned the money because I valued myself to purchase these dishes.","offset":1260,"duration":38},{"text":"Brian: I've been able to afford dishes for probably 30 or 40 years. Why am I thinking that? Because I'm in a place where I enjoy going and doing this thing and being invested in the process of putting these things away. How am I putting them away? I didn't just arrive at that. That became \"Why am I so pissed off that I'm putting away the dishes right now? Why am I pissed off I'm doing my laundry right now? This is a part of my life, this is a part of my existence. Like what what am I tied up in? Where do I think I'm going to arrive at to where I don't want to do this? What what is that point?\" And and I really looked at that in the reality of it and I find joy in just about every moment of my day when I'm not busy.","offset":1298,"duration":59},{"text":"Host: Yeah, man. I I cannot tell you how much I resonate with that. It's all story, right? As I mentioned to you on Monday, like on the plane over to LA this time I just had this clarity when you're 30,000 feet up in the air, right, you have this big picture perspect—I thought \"Life is simply a set of experiences and the story we put on those experiences is ultimately what determines the quality of our life.\" Boom. You can wash your dishes every night and be pissed off that you have to do it, that your partner didn't do it, that they should have done it, that you whatever story you want to make, or you can change your perspective and like you have done, you—it is possible.","offset":1357,"duration":49},{"text":"Host: Oh. And the problem is, and this is why I wanted to talk to you, I don't think until you've stepped out of it and realized that you're choosing the narrative on every situation, you think you're in it, you think you're a victim to the world, that the way you feel is down to everyone around you without realizing \"Oh, I can change this.\"","offset":1406,"duration":18},{"text":"Host: I was chatting to someone about purpose yesterday and I said for me it's it's less about finding my purpose, life is more about how do I find purpose in everything I do. So you wash the dishes and it's like \"No, this is an opportunity to be mindful and present and feel the dishes.\" If someone had told me that 10 years ago, Brian, I would have thought \"What are you talking about, mate? Like, the dishes are the dishes.\" But I honestly feel that doing the dishes can be the most enjoyable experience in the world if you've reframed it.","offset":1424,"duration":32},{"text":"Host: So what I want to talk to you, Brian, about because we could go even deeper than we've already gone, right? I really want to make this practical for people where possible. There is no quick fix here. No. I'd love to tie in breathing and how we breathe to the concepts that we've been talking about, our stress response, our nervous system. So can you sort of simplify that for someone?","offset":1456,"duration":19},{"text":"Brian: Oh, oh, yeah. Oh, easy. You know, it's um you go through this process that I've talked about where you've got you know the stimulus response and then the stress reaction after that stimulus response and the we've walked through this. And as you know like as I've learned, if I don't like what I'm feeling then that's where the opportunity is, okay.","offset":1475,"duration":27},{"text":"Brian: Eckhart Tolle: \"In a healthy organism, an emotion is a short-lived response.\" Okay. I I 100% agree with that. There's no baggage with that. There's no dragging an experience that happened yesterday or 50 years ago through every day of my life. There's no reason I need to do that to where I can't live in total joy.","offset":1502,"duration":29},{"text":"Brian: And if I'm stuck in sadness, if I'm stuck in—if I'm stuck in excitement, ooh, there's one. This is where I usually throw out to clients: \"Here I I know all this other stuff sounds hard. Let's start with excitement. Let's look at the things that bring you excitement. Let's let's slow down there. Let's bring that down a level to actually see it for what it really is, see what the—because there are far too many of us that are getting very excited over really sexy shiny things that inevitably we didn't actually want to be doing or involved in because we didn't take the time to bring it down enough to go 'Oh, anything that goes up comes down, right?'\"","offset":1531,"duration":42},{"text":"Brian: So and that doesn't mean you can't get excited about things. Yes. How make it a short-lived response. How do you make that happen? Well, when I get excited I slow it down. I intentionally slow it down. So if I know I'm going into a situation—so here there's three ways we can go about this. If I know I'm going into a situation that could be difficult—work, home, whatever, or you're going to go do something that you really didn't want to do—that's where breathwork comes in stage one. I'm going to do that to bring myself down a bit to jump over and go \"What is the reality of this?\" versus the emotion of it.","offset":1573,"duration":41},{"text":"Host: I spoke to a friend last week who was getting really triggered by an email from his boss. Yeah. And I said \"Mate, you know that that email in and of itself is not problematic,\" right? He showed me. I'm like \"That's just neutral email. That's just information.\" Yeah. You're choosing to put this story on it and amping yourself up, you don't have to.","offset":1614,"duration":23},{"text":"Host: And I guess one of the things I think is most powerful about becoming aware of your breath is is that deep knowledge where you know I can actually change the tightness of my nervous system.","offset":1637,"duration":15},{"text":"Brian: Look, Kasper van der Meulen was the one who coined the \"Breathing is the remote control to the nervous system.\" So you can toggle that nervous system if you're willing to sit in it and control it before you go into something that you know could be difficult.","offset":1652,"duration":18},{"text":"Brian: Now the second part of that where this could come in is if you get good at the first process, then you can go in to an actual situation you had not planned for, didn't know was coming and real-time regulate. \"Oh, I can feel that I can feel my adrenaline coming up. I can feel I'm getting I'm getting emotional. I'm getting angry right now. I'm getting frustrated right now.\" Breathe into that if you've if you've got it.","offset":1670,"duration":33},{"text":"Brian: But if you don't, the third part is if the the reaction that you've had you didn't enjoy, now you've got an opportunity when it's over to regulate and go look at the reality of that. So in either any one of those three, reality has to come into play. You've got to be able to jump out of the story or the narrative that you're in and breathing is the thing that can typically allow for that to happen if you're actually applying this. But you've got to be consistent with it.","offset":1703,"duration":38},{"text":"Host: Okay, so let's talk about something practical then. You got to be consistent with it. So there's our ability to use our breath in the moment, like let's say we've developed and cultivated the self-awareness, so \"Oh, yeah, I can feel something's happening there, oh okay, I'm not going to say anything, let me just calm it down, let me breathe into it, okay.\" But for that person who's never ever paid attention to their breath and is kind of resonating with something going \"Alright, well, where do I start, Brian?\" Where do they start?","offset":1741,"duration":31},{"text":"Brian: I think the simplest thing to do—and this is what I'll show with people if I if I go do a talk so they have something to walk away with—is if you can just inhale through your nose and exhale through your nose a little bit slower each time until you find a place where you're most comfortable with the exhale. But continue to just inhale and then slowly exhale. You're going to bring it down.","offset":1772,"duration":32},{"text":"Host: So your exhale is longer than your inhale.","offset":1804,"duration":3},{"text":"Brian: Yeah, you want to prolong the exhale just slightly, right? Or even even more, as long as you're comfortable. You don't want to you don't want to do this and to the degree that you're hit hit hitting panic switches.","offset":1807,"duration":11},{"text":"Host: Okay, but I think that's a really good point because um one of the breathing techniques that has taken off over the past decade, which has um elevated this topic of breathwork in many people's consciousness is Wim Hof. Yeah. And yes, there's upsides and downsides for sure of that kind of breathing.","offset":1818,"duration":24},{"text":"Host: But I believe that many people think that breathwork has to be hard. I have to be pushing it, I have to be holding my breath, I have to go \"Ugh, now I can keep going,\" right? And what you're saying there is that \"Wait wait wait, you don't need any of that necessarily. You can start off in a very comfortable way just breathing in and breathing out for a little bit longer but you don't have to feel uncomfortable.\" Is is that right?","offset":1842,"duration":25},{"text":"Brian: Correct. That is controlled breathing.","offset":1867,"duration":4},{"text":"Host: Do you sometimes find it difficult to find time to fit wellness into your life? I know many of us do, we feel our lives are too busy. Bon Charge are a wellness brand who have a fantastic range of products to help you feel better, sleep better, and live better. And I've been using many of their products for well over five years now. What I love the most is that they don't require me to find extra time in my life.","offset":1871,"duration":26},{"text":"Host: I think their blue light blocking glasses are some of the highest quality out there. I've been wearing them for years in the evening, also when I go traveling. I also love their infrared sauna blanket, which is much cheaper and more accessible than having a sauna in your own home. It's really easy to set up and you can have a quick 30-minute session whilst relaxing, reading, or watching television. And this sauna blanket is going to help you with recovery, relaxation, and sleep.","offset":1897,"duration":29},{"text":"Host: Bon Charge are giving my audience an incredible 20% off everything on their website. All you have to do is go to boncharge.com/livemore and use the coupons livemore to get your 20% off, or just click on the link in the description box below.","offset":1926,"duration":20},{"text":"Brian: And then another simple thing that you can do is just sit there, shut your eyes and pay attention to your belly moving every single time you breathe. You breathe in and out and that's all you do for about 30 seconds or so. And after about 30 seconds you're just you're going to switch that over to paying attention to your chest and how your chest moves through every breath. You'll do that for 30 seconds. Not forcing anything, let it happen. Just allowing it to happen. And then I would move people into \"Now I want you to pay attention to the air moving through your nostrils. Just the air moving through your nostrils.\"","offset":1946,"duration":51},{"text":"Brian: So if you can do this without having to control your breathing, you're becoming highly focused on something, but you're calming yourself instantaneously down without having to control your breathing at all and your breathing naturally just starts to drop.","offset":1997,"duration":17},{"text":"Host: So would it be a helpful practice let's say as part of a morning routine? Maybe after they wake up for five minutes doing what you just said? Oh, yeah. Make the case for someone if you don't mind, why they should give up five minutes of their precious morning to do that? What are the potential implications later on in their life, later on that day, for example?","offset":2014,"duration":23},{"text":"Brian: You're going to yeah, uh, simple: you're going to change what's going on metabolically real quick. So you're going to start activating things and getting more more oxygen used up because you're changing how the chemistry happens. So you're actually regulating your nervous system.","offset":2037,"duration":14},{"text":"Host: Okay, so let's say you don't have much time, you do five minutes of this kind of calming, grounding, breathwork practice every morning. As someone who does that, or similar versions of that, I feel there's so many potential benefits. A, I think it's a beautiful way to start your day, it's a very intentional way to start your day instead of reacting to the news headlines and the social media, the noise—you're just like \"Oh, I'm going to start—whatever noise is out there—yeah, I'm going to gently just bring myself into the day.\"","offset":2051,"duration":33},{"text":"Host: For example, I think it's also in a world where so many of us are focused outwards on more information and more expertise and more opinions, which then become confusing, I think a practice like this brings you inwards, you starting to pay attention to what's going on inside your body, right? You start to understand \"Oh,\" like even I know this stuff, but even when you were going through it, I started to do it.","offset":2084,"duration":28},{"text":"Brian: Yeah, yeah.","offset":2112,"duration":1},{"text":"Host: And I'm like \"Oh, wow, I'm in my head at the moment. Like, I forgot what was going on in my body. Of course, I'm talking to you.\" Yeah, yeah. But it was a nice reminder. And I think that—","offset":2113,"duration":8},{"text":"Brian: Such a this is so I'll layer this stuff in for people throughout their day. Like \"Hey, man, like as soon as you get off that call, like boom! As soon as out of that meeting, boom! This is where you go do at least just do like three minutes.\"","offset":2121,"duration":8},{"text":"Host: Yeah. Am I remembering correctly a few months ago on Instagram, I think you said something to the effect of: if you have a well-functioning nervous system, then you will be able to take a nap at 1 PM. What I understood from that post was many people say that they can't nap. They're tired, but they can't nap. And I appreciate not everyone has the opportunity to nap because of their work pressures, etc., etc. But some people who are working from home and potentially could have the time say that they're too wired to switch off.","offset":2129,"duration":33},{"text":"Brian: I mean look, a healthy functioning animal can take a nap at any point after a stress response, right? What does a lion do after it misses the kill? It goes and lies down and then takes a nap. I remember going to general quarters—so I was in the Navy—and I remember going to general quarters which is, you know, a drill for we're going to war, or something's happening, you're going to your station. And it would be held for a certain amount of time and most of the time it was for a prolonged amount of time. And I remember vividly I was like \"Perfect, I'm going to take a nap.\" And I would literally take a nap when we'd go to GQ because I was going to be stuck in this place for so long and none of my superior officers were going to be there or anything, so they weren't going to see me, they're going to be at their general quarter station, you know, but I was going to take a nap. And I would take a nap.","offset":2162,"duration":67},{"text":"Brian: And then I got out of the Navy and then I started working. I was becoming successful and all of these things and then all of a sudden I couldn't switch off. I couldn't take a nap. I remember all of this.","offset":2229,"duration":12},{"text":"Host: So what happened? What was the switch in you?","offset":2241,"duration":4},{"text":"Brian: I just kept turning it on. I took on every opportunity I could get. I said yes to everything. I didn't learn how to say no. I didn't slow it down from the excitement of everything and the new thing, and that doesn't mean the do go do new things, it's like did I have the bandwidth? And I didn't have the bandwidth. I didn't have the bandwidth because I was burning myself out all day and then I was still trying to train, right?","offset":2245,"duration":23},{"text":"Brian: So I was still trying to work out and do everything I was doing at the time while working out and then I'd do the physical stuff because damn, I felt good after that, but not realizing \"Oh, this is going to have compounding residual effects.\" The interesting was is I was doing a lot of long-slow distance in the early stages of that stuff.","offset":2268,"duration":10},{"text":"Host: You mean endurance training.","offset":2278,"duration":1},{"text":"Brian: Yeah, yeah, yeah. And this is where I started to evolve things um not just for myself but a lot of the athletes I was working because they were burnt. And so it was like \"Well, what can we chip down?\" So we started chipping things down and it was less and less and less and it was like having some great effect. But turns out that if you don't turn it off, if you don't have time throughout the day where you're able to shut it down—and that doesn't mean you need to take a nap. It means can you regulate, can you bring it down?","offset":2279,"duration":26},{"text":"Host: And that's why you're so passionate about the breath, because the breath once you become intimate and pay attention to your own breath and what's happening in your nostrils and your chest and your abdomen, like you just mentioned.","offset":2305,"duration":14},{"text":"Brian: What's the—like if I'm talking or if I'm speaking or if I'm going and teaching, like man, I'm on! What am I doing right after that? Am I going to go have multiple conversations with people? Because I might, because people just saw me do something and so they have questions and they want to talk to me and it's like I'm on again. Then it's like \"Okay, what do I do as soon as after that?\" Oh, I'm jacked up! I was working with some stand-up comedians and none of these guys and gals can shut off after they do a set because they're so wired from being on stage. So a lot of these guys go and play video games and stuff or they're drink and you know and and it's like \"Dude, go regulate! Like, go bring yourself down.\"","offset":2319,"duration":37},{"text":"Host: Okay, this is a great example. So a performer, you know, they finish let's say on stage at 10:30 PM. They're amped up, maybe it's not as different as the person who's still working late into the evening on emails, whatever it might be, maybe you know to make it really practical for people, they can't switch off. So and I know performers who say that their bad habits come in when they're on the road. Like how what is a healthier way for them to um down-regulate at 11:00 PM instead of the bottle of wine, for example?","offset":2356,"duration":31},{"text":"Brian: Go back to the green room or wherever you've got an opportunity to separate yourself from people and just take five or 10 minutes and bring it down, regulate.","offset":2387,"duration":11},{"text":"Host: So what? Breathing.","offset":2398,"duration":1},{"text":"Brian: Do some breathing, do some breathing. You could even do breathhold work if you wanted to, that's going to change some things and bring it down a bit, but that is going to bring the nervous system down and it's going to allow you to actually not be in a reactive place. That's the problem is that we get in when we get into this heightened heightened arousal state you can only react in those places. If you do bring it down you can respond you can be like \"Oh,\" but maybe I don't do that versus like \"No, I'm not doing that. Yes, I am doing that.\" Like, you know.","offset":2399,"duration":36},{"text":"Host: The amount of patients over the years, Brian, who came in to see me um with sleep issues, and of course there's a whole variety of different reasons why one may be struggling with one's sleep, right? But so many of them and this is one of the probably unintended or maybe intended consequences of the digital world in which we now live is that these boundaries between work and home have kind of vanished in a way that you know 20 years ago you left the office, you there's stuff you couldn't really do at home, you had to be in the office to do it, so there would be a natural boundary.","offset":2435,"duration":37},{"text":"Host: Whereas now people can work and do their emails into the evening and one of the things I I realized after a while I was telling my patients a lot is that you know you're struggling to switch off and sleep. They're literally doing work emails, firing them off and then going to bed and saying \"Hey, I'm struggling to sleep,\" okay. And I'm like \"If you're doing that and you're really activated,\" now some people can switch it off quickly, for sure.","offset":2472,"duration":23},{"text":"Brian: My wife can.","offset":2495,"duration":1},{"text":"Host: But many people can't. And I'm like, for me personally, I have to have I don't have to anymore, but I chose a few years ago to go \"You know what, once it hits 7:00 PM, that's it, I'm done. Like, that's the day done. Now everything is chill mode. It's relaxing, it's reading, it's music, it's doing some stretches, it's chatting with my wife, it's not work-related.\" It was a choice that I made.","offset":2496,"duration":25},{"text":"Host: And what I used to say to these guys is \"Look, have you got kids?\" He said \"Yeah.\" I said \"With your kids, just before they go to bed, what do you do? You don't put all the lights on full, give them a load of sugar, put the music up loud. You don't activate them, do you? No. You dim the lights, you soften your tone, you might read them a bedtime story. You're creating this kind of environment around them that is conducive to falling asleep.\"","offset":2521,"duration":30},{"text":"Host: But as adults we kind of think that we don't need that. I'm like \"Your kids need a bedtime routine, you might benefit from a similar bedtime routine to your children.\" It's about what is the signal you're giving to your nervous system, isn't it?","offset":2551,"duration":14},{"text":"Brian: Oh, yeah. Oh, yeah. We create more stimulus through the unprocessed junk, whatever we're not dealing with, and it's this compensation of just trying to get as much done as we can because in the world we live in, it's just like it's this barrage of information that we're all aware of and we all talk about it like we understand it, however, when you don't have boundaries like you've talked about how you have boundaries—like 7:00 PM comes you're done, like it's done, right?","offset":2565,"duration":31},{"text":"Host: It's early these days to be fair.","offset":2596,"duration":1},{"text":"Brian: Well, for for me it's really 4 or 5:00. Like, it's really 4 or 5:00 because I if I'll obsess, I'll I will obsess on my work and about you know like look, I tested you and I'll keep going and looking at your data and bringing it in and working on it because I'm in in a space where I'm like \"Yeah, yeah, yeah.\" But that'll also be there tomorrow and I really enjoy a lot of the other hobbies and things that I do and one of them's like cooking. So I get to go home and I get to start cooking. The way I cook is isn't pre-planned. It's \"What's what do we have and what can I create?\" And—","offset":2597,"duration":46},{"text":"Host: So you've but you're changing your nervous system's state.","offset":2643,"duration":3},{"text":"Brian: I am boom! going from work into no! now I'm in the kitchen, play, creativity, and when it's a little warmer I typically will come home and because it gets it gets dark later, I'll go home, grab Tiana and I'll be like \"We're going to the beach!\" and we will go body surf for like 45 minutes or an hour. But my mornings are the same way. Like, I don't actually go and sit and do breathwork all very often in the morning because I head out the door and I go walk for 60 to 90 minutes.","offset":2646,"duration":26},{"text":"Host: Yeah, I want to talk about this. This is really important. So there's doing breathwork whilst you're sitting down and still. Um. And the exercise you kind of illustrated and took people through before is it's kind of about paying attention and just sort of starting to notice what's happening. But there's also breathwork or paying attention to your breathing when you're moving, right? So—","offset":2672,"duration":28},{"text":"Brian: Correct. Correct.","offset":2700,"duration":7},{"text":"Brian McKenzie: Oh, I mean, I’m—I think my average is something like 17 or 18,000 steps a day.","offset":2707,"duration":6},{"text":"Host: And this is something different from five years ago.","offset":2713,"duration":3},{"text":"Brian McKenzie: Oh God, yeah. Okay. Yeah. Well, I mean look, I’ve been walking for quite some time. It’s just the level of walking because of what happens, what I’ve really invested in with walking is the same thing I’m invested in with cooking and/or going bodysurfing or even surfing, for that matter. Like, I didn’t even throw in, if there is a big enough swell, I shut off everything. I cancel appointments with clients. I will, like, and anybody who’s a surfer understands this, like, it’s done. Like, it’s out.","offset":2716,"duration":35},{"text":"Host: The thought that just jumped into my head was, it’s so counter to what we think life should be, which is about seriousness, and if you have a meeting or something there, you have to do it. And I understand that many people have jobs where they have to. Maybe, you know, you work for yourself, so you have the autonomy to do that whereas many people don’t. I accept all of that. But it just makes me think about culture and actually how the playfulness, the things that truly nourish us, those are the things that everyone tries to fit in on their one-week vacation, or maybe on a Sunday afternoon. Do you know what I mean? It says something about culture where these things have been relegated to being only when you have time, only when you’ve finished your emails.","offset":2751,"duration":47},{"text":"Brian McKenzie: See, this is—goes right back to process, in what we were talking about in the beginning. My work is the same way. I’m literally having fun like a kid with what I’m doing. And I’m enjoying that. And I’m not losing sight of that. I feel like at this point in my life, at 50 years old, I got rid of the kid that was a tortured soul and brought back the kid that was playing. And I’ve taken the things that I have learned and that I’m very passionate about, and I’ve learned to apply that to everything I’m doing. But I have set hard lines in the sand with these things.","offset":2798,"duration":46},{"text":"Host: Like what?","offset":2844,"duration":1},{"text":"Brian McKenzie: You don’t get me when I’m surfing. You don’t get me after 4:00 PM. My time is the most valuable thing I have, and your time is the most valuable thing you have. And attention is finite. Where I choose to spend my time, I choose to be there and invested in it in the most creative way that I can. And that’s just presence. I can’t do that without presence. If I’m thinking about the next meeting I’ve got to go to, and the deal I’ve got to close, and whoever I’ve got to—uh-uh. That’s not going to work. It doesn’t work for me like that. And then I love the job I’m at, but more importantly, I love every single person that is in my life, no matter how short that is. And then third, I feel like I’m a kid—and you’ll like this—I’ll feel like I’m a kid in the ‘80s playing again. The ‘80s, bro. The ‘80s.","offset":2845,"duration":56},{"text":"Host: Pre-smartphones.","offset":2901,"duration":1},{"text":"Brian McKenzie: Bro, the innocence and the risk-taking that I was in up to when I was living at that time. The craziness of it. But the—just the drive to explore. And that’s what walking does for me. The walking in the morning reminds me of when I was a kid and I lived behind this forest and I would just go—I was out, I was gone. At like six years old. Eight years old, I’d go walk out the back and I’d go into the forest and I’d go scurry around building tree forts, all this stuff. You know how hard that is right now for people and their kids? Like, to allow even a 10-year-old or an 8-year-old to be on their own?","offset":2902,"duration":47},{"text":"Host: Jonathan Haidt writes about this in *The Anxious Generation*. He’s talking about, you know, the negatives of smartphones at an early age and social media at an early age. But for him, the case he makes is not only about reducing that, it’s at the same time we need to increase free play, give our children independence, get them out taking risks, playing. The world is actually a lot safer for most of us than it used to be. Yet we’re behaving—like, I think he says something to the effect of, we are underprotecting kids in the online world and overprotecting them in the offline world. And I think he’s—I think he’s really onto something.","offset":2949,"duration":41},{"text":"Brian McKenzie: I—I don’t think he’s wrong. I mean, I read Johann Hari, you know, did a book—*Stolen Focus*. Yeah, *Stolen Focus*. That was a fantastic book as well. But, um, you know, and all of that’s provided me with information that I’ve been able to utilize, right? Like, I’m able to take steps to understand these things. It’s like, you know, I don’t have a true existence on social media anymore. It’s like from afar. And, you know, if I go post a video that I have to get on the app for to post that, I actually have to go to the App Store, install the app, and then I delete the app after I’ve done that. And I don’t go through and start scrolling ‘cause I know what’s going to happen to me. I’m not—I’m not immune to the things that are going on with you on there if you’re actually on there. I know—I go through the same thing where I get caught in the infinite scroll and I’m—I’m emotionally getting triggered by things and it’s like, oh that’s interesting, that’s going on. And people pretend like that’s not happening to them. And literally, there are people I have had conversations with that think that’s not affecting them. And they’re full of shit. It’s affecting all of us in a certain way. And real life, real life is with the people you’re closest to and the able—the ability to show up in an interaction. But that doesn’t mean you can’t go on social media and do the thing. It’s just like getting caught in that loop and going, oh there it is, I’m out.","offset":2990,"duration":94},{"text":"Host: It’s interesting you spoke about the boundaries you put in place, the clear boundaries you put in place, and boundaries are something that many people struggle with.","offset":3084,"duration":9},{"text":"Brian McKenzie: Oh yeah.","offset":3093,"duration":0},{"text":"Host: I used to struggle with, for sure.","offset":3093,"duration":2},{"text":"Brian McKenzie: Yeah.","offset":3095,"duration":0},{"text":"Host: And a lot of the time, there’s a pushback sometimes that it’s selfish. But the funny thing is that I imagine, and I put it to you, like, putting in boundaries is actually one of the most selfless things you can do.","offset":3095,"duration":15},{"text":"Brian McKenzie: Oh, yeah.","offset":3110,"duration":0},{"text":"Host: Because what people don’t realize on the other side of boundaries is that you then—you then have something to give to the people you want to give to. Let’s talk about your gear system here, right? Because I think it’s—it’s really practical, and I think it’s going to be a tool that people can take away ‘cause we’ve gone pretty deep, right? And I think you can go that deep, but having some practical activities that you can start, you know, playing around with each day, I think it helps people go to that deepness. Do you know what I mean? It’s like, it’s easy to hear these concepts and go, well yeah, Brian, Rangan, alright for you guys, like, I don’t know, like, you enjoy doing the dishes. What are you guys talking about? I hate doing the dishes. So let’s bring in these five gear systems because I think they’re useful. Everyone moves their bodies. Maybe some not as much as others. But what are they and why do you think they’re so important for people to know?","offset":3110,"duration":60},{"text":"Brian McKenzie: Well, we developed the breathing gear system out of a discrepancy that we found in observing breathing as a dynamic through low, moderate, and high-intensity exercise.","offset":3170,"duration":15},{"text":"Host: So the gear systems apply to when we’re moving our body.","offset":3185,"duration":3},{"text":"Brian McKenzie: Correct.","offset":3188,"duration":0},{"text":"Host: It’s not about waking up and actually paying attention—no. So we’ve parked that. We’re now moving our bodies. Let’s say we’re going for a walk.","offset":3188,"duration":7},{"text":"Brian McKenzie: It’s about exercise. Go for a walk. And this is a perfect example, is if gear one cannot be used while someone is walking, we have a very big limitation, which is nothing but an opportunity. Don’t look at limiter as a negative. Limiter is an opportunity. So I have an immediate opportunity if I can’t have somebody in gear one. And breathing gear one is simple. It’s can you maintain one breath cycle in and out of your nose for greater than four seconds? So that would be like a two in, two out, right? Two—two-count in, two-count out. I get that upwards to somewhere around eight seconds for walking level, maybe ten seconds walking level effort for people. But that’s a good check. Does that mean you should go on a 90-minute walk while trying to apply gear one? Absolutely not. That means go spend like 10, 20 minutes really focusing, or from time to time every few minutes checking in and applying that breathing pattern to the effort you’re at with walking.","offset":3195,"duration":78},{"text":"Host: Okay, so let me frame it my way and see if this makes sense. Okay, so walking is, of course, it depends whether there’s an incline or it depends on the speed, but it’s, you know, it’s not the most intense of movement activities, right? So you’re saying you’re going for a walk around your block. Gear one is the ability to maintain a nasal in-breath and a nasal out-breath, so you’re not opening your mouth, and you want that in and out breath to be at least four seconds.","offset":3273,"duration":28},{"text":"Brian McKenzie: Yep.","offset":3301,"duration":1},{"text":"Host: Okay. If you cannot do that—okay, so it could be that you can only manage two seconds, or it could be that I can only walk around the block by opening my mouth.","offset":3302,"duration":10},{"text":"Brian McKenzie: That would be gear four.","offset":3312,"duration":2},{"text":"Host: Okay, so let’s work through this. Okay, so why is that a problem then? If someone can’t go around the block on a flat pavement and keep their mouth shut while they’re doing it, so exclusively nasal breathing, if they can’t do that, why is that something they should be paying attention to?","offset":3314,"duration":17},{"text":"Brian McKenzie: They’re not utilizing oxygen real well. Okay, to make sure you’re taking action after watching this video, I’ve created a free breathing guide that’s going to help you reduce stress, calm your minds, and boost your energy. In this guide, I share with you six really simple breathing practices that work immediately. Even just one minute a day will start to make a big difference. To receive your free guide, all you have to do is click on the link in the description box below.","offset":3331,"duration":30},{"text":"Host: Can we think about these five breathing gear systems like a car? You know, gear one to five, where, you know, we start off the car in first gear, and we go to second gear, and third gear, and fourth gear, and fifth gear? Is—can—is that—does that make sense?","offset":3361,"duration":18},{"text":"Brian McKenzie: Sort of. It sort of, because gear one would be much—you’d be in gear one should be primarily most of what you’re doing throughout your day. So gear two is a transition from gear one, obviously, to where I go from that four-count, and now I’m down and I’m probably more like three—two to three seconds per breath cycle.","offset":3379,"duration":26},{"text":"Host: But still nasal in and out?","offset":3405,"duration":2},{"text":"Brian McKenzie: Yes, I’m still nasal, right? Still nasal.","offset":3407,"duration":2},{"text":"Host: So gears one and gear two are both nasal.","offset":3409,"duration":2},{"text":"Brian McKenzie: And what I’ve found—what I have found over the last several years is that gear two is actually pretty limited. And you’re probably more effective if you’re—if you’re going to be prolonged at gear two, you’re actually more effective at jumping up to a gear four. So see, I’m skipping gear three. Because gear three is nose in, mouth out. And that’s largely a transitional gear for coming down.","offset":3411,"duration":35},{"text":"Host: And we’re going to go through this, but for people who like want to learn more, it’s all on your website, isn’t it? Like, you’ve got the gear system, and that is shiftadapt.com.","offset":3446,"duration":12},{"text":"Brian McKenzie: ShiftAdapt.com, right. So if they go to shiftadapt.com, you’ve clearly got the five gear systems there.","offset":3458,"duration":5},{"text":"Brian McKenzie: Yeah, I think we have it—I have that up—we have that up somewhere on that site. Um, if not, they can go to actually my—my X handle and it is literally pinned at the top of my—of my profile. And there is a systematic breakdown of it and where it relates and how it can work. Okay.","offset":3463,"duration":27},{"text":"Brian McKenzie: That said, skip gear three going up. So I’m in gear two, if I’m going to be there for more than a minute or two, I’m going to have somebody go to gear four.","offset":3490,"duration":10},{"text":"Host: And that is what? In and out through the mouth?","offset":3500,"duration":3},{"text":"Brian McKenzie: Yeah, it’s just relaxed mouth breathing.","offset":3503,"duration":3},{"text":"Host: Okay. So as your intensity is going up, you’ve moved from gear one to gear two, you’re saying on the way up, jump and skip gear three, and you’re now at gear four. So you’ve gone from nasal breathing in and out to mouth breathing in and out, but in a relaxed way. And then gear five is—","offset":3506,"duration":15},{"text":"Brian McKenzie: For—yeah, and for heart rate zone junkies, people who actually understand heart rate zones, gear four is happening somewhere between heart rate zone three and four. Okay. That is where that is occurring. Gear five is power mouth breathing. Meaning I’m actually really moving air like [breathing sound]. This is heavy-duty strength and conditioning sets. This is sprinting. At the end of sprints, if they’re short, or you’re talking 400-meter, 800-meter efforts, you’re going to hit those. If you’re hitting those for high intensity, gear five is coming into play. Okay. Gear five is something that I realized there were a lot of problems with not just myself that I noticed, but other people I’ve noticed who were not able to get that respiration rate above about 40, 45.","offset":3521,"duration":65},{"text":"Host: Yeah, okay. And we’ll come to my test here.","offset":3586,"duration":2},{"text":"Brian McKenzie: Uh-huh.","offset":3588,"duration":1},{"text":"Host: But just again, to make sure everyone’s following along. Right, so there are these five gear systems that you’ve gone through. As our intensity of movement increases, we in essence move up through the gears, just like we would in a car. Right. Why is it important for someone to know that? So what I mean by that is, let’s say someone is using gears four and five exclusively, i.e., they’re never nasal breathing, okay? They’re—they go for a walk around the block on a flat, in perfect weather conditions, and they’re breathing in and out through their mouth. Okay, so they’re not using one, two, or three, they’re straight into four. ‘Cause I think people need to know that to encourage them to start.","offset":3589,"duration":40},{"text":"Brian McKenzie: For the hundreds, if not thousands, of people that I’ve tested or looked at the—the data on currently, um, you have a breathing-related issue when exercising. And you have a big opportunity in maximizing your performance and output by—either and—look, I—I tested, um—so I tested Kawhi Leonard this morning, who’s an NBA player for the Clippers. Um, and he asked this very question, well how’s this going to help my performance? And I explained to him, well think of it like a season, right? If I can give you a tool that’s going to allow you to be more efficient with your breathing, you’re not losing that blood to your locomotor muscles. So you’re not getting more stressed sooner. You’re using energy a bit more efficiently. So game after game, if you don’t change this, by the time playoffs come, you’re pretty tired, you’re pretty exhausted, it’s pretty hard, versus you now have—you’re now recovering faster because you’ve got more capacity ‘cause you’re using oxygen later than you were earlier.","offset":3629,"duration":80},{"text":"Host: Yeah. So there’s a performance benefit, there’s a capacity benefit, you can go for longer before you fatigue. Someone we both follow on X, Alan Cousins, my interpretation of what I’ve read from Alan is, you know, if you’re keeping at that low heart rate, if you’re walking to the mailbox, if you can keep it all nasal breathing and at a low heart rate, that’s going to help you burn fat. There’s a metabolic benefit. And so for some people who maybe don’t want performance or not NBA players, well many people are trying to lose fat off their bodies, right? And there’s a metabolic reason to be able to access gears one and two, isn’t there? You’re going to—it’s going to help you burn fat.","offset":3709,"duration":41},{"text":"Brian McKenzie: You know, we definitively understand that if you’re breathing through your nose, you’re more aerobic than you are if you’re—","offset":3750,"duration":7},{"text":"Host: Which means you’re using up fat.","offset":3757,"duration":2},{"text":"Brian McKenzie: Correct. So think of your aerobic system is kind of like your—your checking account, right? And your anaerobic systems are your savings account. If I’m constant—my mouth—my mouth open is my savings account. You’re on limited time. You’re incinerating carbohydrates when that mouth’s open. So you’re using up—that’s not a bad thing. It’s just a thing. But I’m on limited time. If I’m more aerobic, I’m utilizing fatty acids more. So I’m burning fat, right?","offset":3759,"duration":33},{"text":"Host: Okay. Now, I love all this. Right, so we’re in a situation where—and this is how the—the breathwork landscape has changed over the last five or 10 years, of which I’m a prime example. Okay, so—","offset":3792,"duration":13},{"text":"Brian McKenzie: Yeah, this is good.","offset":3805,"duration":1},{"text":"Host: Let’s go back 10 years. A decade ago, I can’t quite remember what was happening, but breathwork wasn’t as popular as it is now. Mm-mm. In my own journey through this podcast, which has been going for seven years now, the first time I really dealt with nasal breathing on the show was with Patrick McKeown many years ago. I had a lovely chat with Patrick. Um, he spoke to me about the BOLT score and, you know, the benefits of nasal breathing. And that progressed to me talking to you and all kinds of people about breathwork. James Nestor then releases this blow-up book globally, *Breath*, and talks about the benefits of nasal breathing. Is it fair to say that that message was needed because the vast majority of people were overbreathing and using their mouths more than their nose? But something has shifted where some people who get a bit obsessed like me take that nasal breathing message and try and do everything in our lives with nasal breathing and then we start to have problems in somewhere like a gear five, which is what I think you’re finding with me.","offset":3806,"duration":65},{"text":"Brian McKenzie: Correct. Yes. And—and I experienced the same thing. I did the same thing.","offset":3871,"duration":6},{"text":"Host: But it doesn’t mean nasal breathing is not important. It’s just that—","offset":3877,"duration":4},{"text":"Brian McKenzie: No, no, no. There’s a limitation, for sure.","offset":3881,"duration":2},{"text":"Host: Can—can we say this? That there was a deficiency of nasal breathing in society. The increased awareness has—has meant that less people are deficient now because they’re aware of it. But the problem is is that they’ve tipped it too far where they’ve actually now neglected mouth breathing, which is also important.","offset":3883,"duration":21},{"text":"Brian McKenzie: Correct. Go look at a tour cyclist who climbs Alpe d’Huez or whatever climb you want to talk about and they’re punching it. Their jaw is on the—their jaw is open and they are and they are moving that air fast.","offset":3904,"duration":14},{"text":"Host: Okay. So let’s talk about that then through the lens of the testing you did on me, right? So ‘cause I think this kind of illustrates this quite well.","offset":3918,"duration":7},{"text":"Brian McKenzie: Yeah. You were—you were not able to get above a 42 respiration rate, and you were at tidal volume, but I’m pretty sure you could get deeper.","offset":3925,"duration":12},{"text":"Host: Let’s break that down. Like some people won’t know what tidal volume is and what these terms—","offset":3937,"duration":4},{"text":"Brian McKenzie: Tidal volume just talks about how much air’s in the lungs, right?","offset":3941,"duration":4},{"text":"Host: So are we saying that I was good at the lower gears?","offset":3945,"duration":3},{"text":"Brian McKenzie: You were good at the lower gears. Oh yeah. Yeah, yeah, yeah.","offset":3948,"duration":2},{"text":"Host: So—so because I’ve put in the work at the lower gears and I’ve focused on nasal breathing, so it looked as though you were really happy with that.","offset":3950,"duration":7},{"text":"Brian McKenzie: Yeah. And metabolically speaking, look, like based on—you—you were between 0.95 and 1.0 for like 15 minutes.","offset":3957,"duration":11},{"text":"Host: And what does that mean for people who don’t know those terms?","offset":3968,"duration":2},{"text":"Brian McKenzie: So Rangan was at a low to moderate, moderate, moderate, high level. He was staying under 1.0 RER, which is respiratory exchange ratio, which means once you hit 1.0, you’re burning carbohydrates.","offset":3970,"duration":14},{"text":"Host: So I was able to burn fat.","offset":3984,"duration":3},{"text":"Brian McKenzie: You were still had some fatty ac—you were still burning some fat even at relatively, you know, moderate, moderate to high intensities, which I probably wasn’t doing five years ago. From a systems level, a metabo—so just that’s just looking at the metabolic. Now, here’s where—here’s where part of the assessment is different that I that I’m doing. And endurance community will understand this. I’m looking at tissue utilization of oxygen and I’m looking at delivery of oxygen. Okay? So I’m seeing how the hemoglobin is getting delivered, the oxygen’s getting delivered to the tissue, and I’m seeing how well that tissue’s actually utilizing that oxygen.","offset":3987,"duration":42},{"text":"Host: Okay. So many of us understand that oxygen comes into our lungs, right? And then from our lungs, it gets into our blood. You’re saying there’s two things to think about. Yes, you have to get the oxygen from the lungs to, let’s say, your muscles, right?","offset":4029,"duration":16},{"text":"Brian McKenzie: As soon as you start working, the muscles demand goes up.","offset":4045,"duration":3},{"text":"Host: Right. So the oxygen gets to the muscles. But you’re also saying that even if it gets there, it may not be being used efficiently.","offset":4048,"duration":7},{"text":"Brian McKenzie: Correct.","offset":4055,"duration":0},{"text":"Host: Right. So this is the kind of nuance that I think many of us are not thinking about. So okay, let’s go back to my test then. What was I doing? Am I getting oxygen there and it’s not being used efficiently, or am I not even getting oxygen there?","offset":4055,"duration":12},{"text":"Brian McKenzie: You’re getting oxygen there. However, you weren’t utilizing the oxygen well at these places.","offset":4067,"duration":7},{"text":"Host: Why?","offset":4074,"duration":1},{"text":"Brian McKenzie: The mitochondria aerobic system wasn’t getting enough oxygen or hadn’t been for for long enough because the nose breathing is happening with everything, and you’re more than likely doing it at higher efforts, which you confirmed with me. Yes, you are. So you’re not actually bringing in enough oxygen to actually help that so you’re the system can’t—or the tissue can’t, but the system’s fine.","offset":4075,"duration":25},{"text":"Host: It’s funny, a few years ago I went to Salford University in Manchester to do my lactate threshold testing, and I was right in the middle of my nasal breathing passion. And I was nasal breathing till right at the very end. And it’s really interesting. These guys have done thousands of lactate threshold tests. My test confused them because they weren’t seeing what they’re used to. They weren’t seeing the usual step changes. I don’t think at that time they’d seen someone who was nasal breathing right until the very, very final speed. And they were going to do some more work on me and then COVID happened, nothing—we didn’t actually do anything. But now it’s all starting to—the penny’s starting to drop now, where I’m like, ah, maybe—not maybe, I was overly nasal breathing, so they couldn’t even get the data they wanted to give me my training zones. Does that—is that making sense?","offset":4100,"duration":54},{"text":"Brian McKenzie: Dude, I watched this exact thing with—so I I have a pretty good relationship with the UFC PI and one of my—one of my clients owns the UFC so we went over to the PI to do all of our testing there with Roman, um, who who’s the exercise lead physiologist there. And he he did this exact same thing and literally with a minute and a half left, he decided to start mouth breathing—","offset":4154,"duration":27},{"text":"Host: That was me. That was exactly me.","offset":4181,"duration":2},{"text":"Brian McKenzie: And it that’s all it lasted. He fell off a cliff immediately afterwards and yeah, you were struggling your ass off because you didn’t—you didn’t have enough oxygen on board. And you haven’t actually developed the the the the muscles to be able to move that fast.","offset":4183,"duration":16},{"text":"Host: So I’ve developed the lower end, which is great and has metabolic benefits and performance benefits, but I’ve sacrificed or underdeveloped the top end.","offset":4199,"duration":9},{"text":"Brian McKenzie: Yeah, it’s like doing yoga with your primary breathing muscles and then asking yourself to go, you know, do powerlifting, right? It it’s just those two very different worlds, right? Or—","offset":4208,"duration":11},{"text":"Host: But you need both. It’s not—","offset":4219,"duration":1},{"text":"Brian McKenzie: Oh, correct.","offset":4220,"duration":1},{"text":"Host: So I was right to focus on the nasal breathing and correct that deficiency in my life.","offset":4221,"duration":4},{"text":"Brian McKenzie: Yes.","offset":4225,"duration":0},{"text":"Host: But now it’s like, hey Rangan, you’ve got that one. That’s okay. Keep doing that, but now we need to bring in—","offset":4225,"duration":5},{"text":"Brian McKenzie: Yeah. And the series of questions that I ask based on what I see is what validates what we see, right? And that was the questions that I had for you was like, hey, you know, are you doing any mouth breathing? You’re like, oh no, no, no, no. I don’t do you know, like I’m, you know, this is what I’m doing. And I’m like, okay, that’s what I thought.","offset":4230,"duration":19},{"text":"Host: Okay, so let’s say you’re going to give me a program and I’m going to work on certain things to do. And I guess some of that’s—well, maybe you can share. What are some of the things you would ideally have me work on?","offset":4249,"duration":11},{"text":"Brian McKenzie: We would, one, have you uh work at just above gear two. So working to like heart rate zone two, heart rate to heart rate zone four. We’d be doing some intervals there with mouth breathing, particularly gear four, not gear five. Gear five we would touch. We’ll touch with things like strength and conditioning. So I threw in with your program, at the—the—one of the main points of the limiters was let’s do some real str—let’s do some strength and conditioning at least twice a week where you’re getting that intensity up to where you are mou—wanting to move air like [breathing sound]. And that may just be after you finish squatting, but it hits that. And then we can gear down as a result of that. So I get up to a point to where I hit that when I’m lifting heavy and then that doesn’t mean the whole workout’s gear five at all. It’s we’re hitting those stages. You’re also doing structured cardio throughout the week at least twice a week to where we’re doing some interval type work where you’re working for a few minutes in gear four and then coming back into a gear one for some easier stuff. And making sure that we’ve got the the you know the working gear one in there.","offset":4260,"duration":86},{"text":"Host: So the gears that I have um underdeveloped over the past few years, the gear four and five, right? In essence, you’re saying now we’re going to start um redeveloping them. You’re going to now—you’ve got gear one and two going pretty well. Let’s now get gears four and five going well so I’ve got this real variety and depth in my system. I want to know what the benefits for me of doing that are. Like why should I do it? I feel good. Um, I can nasal breathe at low intensities. I’m going to do it, Brian. It’s not that. For the purpose of the conversation, why should I? Why shouldn’t I just keep doing what I’m doing?","offset":4346,"duration":42},{"text":"Brian McKenzie: You’re going to most likely see an increase in VO2 max.","offset":4388,"duration":4},{"text":"Host: Could you explain to my audience what a VO2 max is?","offset":4392,"duration":2},{"text":"Brian McKenzie: Maximum amount of oxygen you’re able to utilize, um, in liters per kilogram a minute. So your your body weight in kilograms and how many liters you’re using of oxygen or can you use in a minute. That’s just a rough reference point of the higher that VO2 max is, the less likely it is that that’s going to slip into a dangerous zone as you get older. The good news is you’re probably not in any danger. The the even better news is is that following what I’m going to lay out is going to most likely increase that exponentially. Meaning when you go on a walk, it’s even easier. You’re not using high-stress energy in the places you used to.","offset":4394,"duration":46},{"text":"Host: Is it fair to say that if you can develop this five-gear system with a variety of different movements and a variety of different breathing gears and heart rate intensity, you’re working out your stress response system?","offset":4440,"duration":16},{"text":"Brian McKenzie: Oh, oh yes.","offset":4456,"duration":1},{"text":"Host: Right. So how—look, given what we spent the first hour talking about, which is the way we respond to stress, the choice or perhaps not the choice, depending on how you want to frame it. In terms of we have a stressor and we have a response to that and we can train our response, we can get more helpful responses over time. Do you think that if people develop their five-gear breathing system, it would help them better manage stress in their own lives?","offset":4457,"duration":27},{"text":"Brian McKenzie: Across the board, yes.","offset":4484,"duration":2},{"text":"Host: ‘Cause it’s not separate, is it? It’s not how you deal with the driver who cuts you off is actually related to how you move your body.","offset":4486,"duration":7},{"text":"Brian McKenzie: Correct. And your—well, your breathing is a respondent to all of that. Breathing’s playing a role in all of that. So me learning how to actually—and this doesn’t—like, I want to be very clear. I don’t—I don’t, nor do I expect clients to go into the gym and or go and do cardio every time they go and work out that they’re implementing the gear system. A small portion of that training I will integrate the gear system and breathing into, but not the whole thing. It’s like if I’ve got a guy playing, you know, in the NFL or NBA, whatever, I do not want them thinking about the gears when they’re playing. No. Not at all. Not at all. That is part of training and then it should transcend over into is the is my client now seeing differences in how they’re playing and intuitively picking up on this process as they walk—as they go through that, right? Are they as soon as a play ends and you know, in NFL or are they immediately into [heavy breathing sound]. Do they do that intuitively, right? That’s where that should happen. However, the crossover is how I’m managing my day-to-day stress is going to show up in my training. And if I can’t maintain a gear one in something I should be able to maintain a gear one in, I now know I’m probably a little more smoked than I normally am, or if I had a a workout I was going to do that had some sort of gear in it, and that’s much harder, you are now seeing a response to stress that you have a feedback loop to to understand, oh wow, this is a lot more difficult or this is much easier today. I am really able to get work harder in this gear, right? That is a very—that is a crossover point for understanding, oh, I’m actually making some adaptations here towards expanding my potential for stress. Like, I I’m able to handle far more than I was prior to this. And here’s the thing, if I don’t use oxygen well, your physiology will catch you. We call these metabolic disorders. Like, it will catch you. And that doesn’t mean your breathing is the culprit here. It means, yeah, your breathing’s probably affected, your food’s probably affected because you’re making fast choices on that and you don’t care about where you’re getting your food from, just hypothesizing. Your training is too intense or it’s not intense enough, right? Like, the there’s all these variant—like, look you go look at research like it comes out all the time, but variance to training is the thing that is typically the best stimulus, not the same thing over and over and over repeating.","offset":4493,"duration":176},{"text":"Host: It’s so interesting this stuff. I mean, I’m I’m deeply fascinated like you about human behavior. A big part of my job for many years as a doctor has been to help patients make better lifestyle choices. And I used to think that knowledge was all the people needed. And I’m like, no, no, no. People need knowledge for sure, they need external knowledge, but what they need more than anything I believe these days is internal knowledge, that awareness of why am I going to this behavior. So let’s take sugar for example, right? And I think this relates to your work and the gear systems. If you’re chronically stressed and generating emotional stress by every way you interact with life—the the drivers, the boss, the traffic—and you’re thinking you’re a victim to the world, you did the math, you’re going to consume more sugar because you you’re using up sugar.","offset":4669,"duration":54},{"text":"Brian McKenzie: Your body needs sugar.","offset":4723,"duration":2},{"text":"Host: Exactly. And so you keep thinking that you need to hear another podcast on the on the negatives of sugar, but the problem is you already know that. You need to understand why do you need that sugar. What is going on upstream that is naturally means you’re going to consume that sugar and you can apply that to alcohol or three hours scrolling social media, whatever it might be. Like, what’s the upstream driver? Hey guys, I really hope you’re finding this useful. If you are and you want more content like it, please do check out my book, *Make Change That Lasts: Nine Simple Ways to Break Free From the Habits That Are Holding You Back*. It’s in all the usual places as a paperback, ebook, and as an audiobook which I’m narrating now. Back to the video.","offset":4725,"duration":45},{"text":"Host: Is it fair to say, Brian, then, because not everyone who um who is listening to this right now is going to be able to come to your facility, okay? Um, so in terms of practical advice that may work for most people—","offset":4770,"duration":17},{"text":"Brian McKenzie: Yeah.","offset":4787,"duration":0},{"text":"Host: I think a conclusion that I’m drawing is that everyone should be able to walk around their block keeping their mouth shut.","offset":4787,"duration":11},{"text":"Brian McKenzie: If you can’t go walk for at least 45 minutes a day, you’ve got—I my suggestion is find the time to walk for at least 45 minutes a day with your mouth shut and not on a screen. You’re laying the beginnings of a metabolic foundation, the stuff Alan Cousins talks in in like so well about. I actually believe it’s more—so do I. Yeah, you’re going to need more than—but if you can get 45, that’s a good start. But go get lost in that 45 minutes. Go explore.","offset":4798,"duration":38},{"text":"Host: But keep your mouth shut.","offset":4836,"duration":1},{"text":"Brian McKenzie: Keep your mouth shut and explore.","offset":4837,"duration":2},{"text":"Host: Okay, now let’s say someone tries that and goes, hey Brian, I’m really struggling, like I’m trying to go for a walk, I have to open my mouth after 10 minutes.","offset":4839,"duration":8},{"text":"Brian McKenzie: Take a few mouth breaths and go right back to nose breathing.","offset":4847,"duration":3},{"text":"Host: So it’s training. You’re like you don’t have the skill now but you can develop and cultivate it.","offset":4850,"duration":4},{"text":"Brian McKenzie: Take a few mouth breaths, go back to nose—go back to gear one.","offset":4854,"duration":3},{"text":"Host: Okay. So practice nasal breathing at low intensity.","offset":4857,"duration":2},{"text":"Brian McKenzie: At low—it it’s 80% of what you should be doing, right? So 80% of what you should be doing is really underneath that nose breathing thing. Then there’s the hey, if you can get that 45 minutes, great. Go work, spend your day paying attention to how much you’re talking, how much you’re getting stressed out. Find pieces of time where you can just bring it down for a minute or five. Just in just start with a consistent habit of controlling some breathing or paying attention to your breathing through your belly, your chest, your nose if you want, throughout your day if you can. Then, if you’re going to go train, if you’re going to go exercise and you really want to exercise, use your walking, the end of your walk and how you feel after walking as a basis for how hard you can train or what you can do that day. You’ll know. Your body is going to tell you through that walk how good you feel, if you feel great like and and try and mix up things. Like, try and do some strength training. We know definitively strength training is as important as VO2 max. Having muscle tissue so that you can get up off your your tail is is just as important as having a VO2 max, right? So maintaining strength, that doesn’t mean you need to go into a powerlifting meet. Like, it doesn’t mean you need to become a powerlifter. But finding complex movements and applying them, do that throughout the week. Maybe at least twice, if not three or four times a week if that’s your MO.","offset":4859,"duration":103},{"text":"Host: So you’re saying the 45-minute walk, right, or whatever you can manage, you’re saying have that daily walk. Yep. That daily walk does several things. Yes, it’s training you metabolically, it’s training your stress response system, but it’s also helping you tune into yourself. Because if you do it every day, and this is why I like repetition, you start to feel if the practice is the same and you feel different, you know that something else is causing you to feel different. i.e., oh I didn’t sleep well last night or I’ve got a lot of stress in my life at the moment. That walk felt a bit harder today than yesterday, it’s the same place that you’ve gone. So you’re starting to understand yourself better and the state of your nervous system through that daily walk.","offset":4962,"duration":41},{"text":"Brian McKenzie: 100%. 100%. Yeah. And for 20 minutes of calm just sitting, the brain looks looks looks good. But the brain after 20 minutes of walking looks real good. Real good. You start to see things because of blood flow changes and metabolic changes that start to happen that aren’t requiring high stress from that, and you kind of start to work through creatively a lot of the stuff that you’re working—whatever you’re working on, whether that’s work, whether that’s life, whether that’s whatever. And I’ve found that that is the place where I can really tap in and I I’m also very aware of like, you know what, I am definitely not lifting today. I’m still a mess and there’s no reason why I’m going to put load on my back or you know, pull heavy off the ground, whatever. Um for I’m going to do some probably some low-level cardio later or I’m going to go swim, right? Like um you know, or I’m just going to surf.","offset":5003,"duration":61},{"text":"Host: You’re getting in tune with yourself.","offset":5064,"duration":1},{"text":"Brian McKenzie: Yeah. I’m just—","offset":5065,"duration":1},{"text":"Host: You’re starting to learn about yourself. It’s paying attention to what’s going on inside.","offset":5066,"duration":3},{"text":"Brian McKenzie: You’ll start—you’ll start to figure out that that um when you don’t move, when you don’t walk, when you don’t exercise, your body starts to take a nosedive. Your stress levels go up through the roof, your HRV starts to drop, your resting heart rate starts to increase, your blood pressure starts to increase. Literally, I can watch this with I watch this with myself. My resting my morning lactate reading goes up if I don’t do anything the day before, right? If I don’t do any walking, if I don’t do anything the day before and I was talking and I was engaged in work or I was flying and all that dude, the next morning, I’m hot. I’m running hot. So I’ve got to go you know I don’t have to, I go walk and then I’m like, I don’t go crush it the next day. Like I have clients I manage their pro—like this is what I do, is I’m like yo, you’re landing in Abu Dhabi, you are not going and training hard. Yeah, yeah, yeah, I am. And I’m like, no, you’re not—like not if you want to sleep. Like, if you really want to get adjusted sooner, we’re going to get light, we’re going to go walk around, then it’s going to be hey here’s this low-level thing.","offset":5069,"duration":73},{"text":"Host: Yeah. It’s interesting that we we have all this data now coming out, well for many years, that um exercise is as good as an antidepressant or better. You know, we we—but the point I’m trying to make is that we’re so used to being a sedentary society that doesn’t move, we talk about all the benefits of exercise, but actually if you flip it, it’s like if we were all moving, it’s not that exercise has the benefits, it’s that not moving has all these disadvantages. It’s the same thing but reframed.","offset":5142,"duration":30},{"text":"Brian McKenzie: And and if you want to have if you want to do this even even at a higher level, get your ass outside and do it. Get exposed to the light, the morning light. Like it it’s critical that you’re doing this stuff. This is like how we were de—how we evolved, this is how we became what we are, as a result of being outside and having to go walk towards something to get it and then bring it back or however we were doing it. And I mean look, my house when it gets dark, it gets red. The only lights that come on are red. You know, I I’m ahead of this because I noticed the sensitivities I have towards the light. I I really get sensitive towards light in the dark. Like when I was driving at night, I would notice I would just be like, God I’m this is sucks because of headlights.","offset":5172,"duration":54},{"text":"Host: Yeah, light—light is as powerful as a drug. We just don’t see it like that.","offset":5226,"duration":3},{"text":"Brian McKenzie: 100%. Forget the name of the book, I read one, it was great on on on light and um sleep and you know light being the original uh toxic thing.","offset":5229,"duration":14},{"text":"Host: When you—I’ve got this—I think it’s a I think it’s within the iPhone you can put this like heavy red filter on your phone. And so I triple triple-click in the evening and it goes red. And then if you ever just put it back, you can feel the eye strain.","offset":5243,"duration":17},{"text":"Brian McKenzie: My my phone’s mostly red is is red most the time.","offset":5260,"duration":2},{"text":"Host: But you don’t—people we don’t realize how much we’re being strained and stimulated until you change it and then you flip back, you’re like wow, this is what most people are looking at.","offset":5262,"duration":8},{"text":"Brian McKenzie: What’s wild is I used to watch—so I’m a big entertainment guy, like I love movies, I love good shows, um and I grew up that way. Um I when I watch on the television now, I can’t watch on the TV for very long because it’s so stimulating. I watch on my iPad which I can put in red. So I everything’s in red. That light thing has a huge impact on the, you know, on the metabolic system. Like, how everything’s functioning.","offset":5270,"duration":32},{"text":"Host: Yeah, it’s so interesting, like thinking about our evolution um and how we live. It strikes me that because we’re so disconnected from, let’s say, our food supply, because we’re so disconnected from how we used to live, because our lives are so overly busy and chronically stressed now, it’s as if we all need education now on what diet we should be consuming, how we should be breathing, how much we should be moving. Whereas, I remember last summer, uh my family and I went to Kenya for four weeks, and we went on safari, and one day we spent at uh a Maasai camp. And there’s many things I noticed, but one of the things that struck me, hanging out and interacting with some of the Maasai that morning, was there was just a quietness, a groundedness. I was just struck by this kind of grounded presence that you don’t often see in the modern world. Yeah. But a lot of people around you you meet in in modern life now are quite they’re like I used to be, in your head, you’re not grounded, you’re anything but. Do you know what I mean? How how do you think about being grounded and its relationship with the breath?","offset":5302,"duration":77},{"text":"Brian McKenzie: Um, I mean, there’s nothing to fix with any of us, to be clear. But when you’re grounded in yourself and you’re living, you know, how you truly want to be living, you don’t need to change you don’t need to change a whole lot because the process of what you’re doing already involves all of that. I haven’t met anybody—I’ve yet to meet someone who is totally grounded that is not highly physically active in some way. I have not. There is no Eastern philosophy without a physical practice. None of them. None. Why? I’ve looked. Why? Because they understood. It was about like monks up in isolation that I brought up with the, you know the the prison before, they walk every day. They’ve got some sort of practice. Go look at the Shaolin monks, for crying out loud. You know, um you go look every philosophy you’ve got yoga, like it was about movement. And moving into positions, asanas.","offset":5379,"duration":21},{"text":"Brian: ...and getting into position and being able to breathe in that position. Because if you can't breathe in that position, you don't own that position. That position owns you. Yeah. You know? And so anyway, it's I'm I'm very interested in people that that are very grounded and I'm like I'm I'm blessed with what I get to do and how I get to do it.","offset":5400,"duration":26},{"text":"Brian: Um, but I'm more so just I'm I'm just playing, man. That's all I'm doing.","offset":5426,"duration":5},{"text":"Host: Yeah, I love it, Brian. Absolutely love it. Couple of loose ends in my head I just want to tie off before we end the conversation. We spoke before about we get oxygen into our lungs and then we have to deliver it to our tissues or our muscles, but then utilize it when it's there as well. And I think you said that with me, I'm able to get it to the tissues and muscles, but I'm perhaps not as efficient as I could be at using it there. First of all, is my recollection correct?","offset":5431,"duration":30},{"text":"Brian: Correct.","offset":5461,"duration":1},{"text":"Host: Okay. So how am I and through me then the people listening, if they have the same problem, how are they going to improve, you know, the usage of that oxygen at the tissues? For me, is it that high intensity? Is that what it is?","offset":5462,"duration":16},{"text":"Brian: It's not just high intensity. It's it's even moderate intensity and bringing on enough oxygen for the for the tissue to use it, versus limiting what you're you're doing, right?","offset":5478,"duration":13},{"text":"Host: So I'm artificially limiting...","offset":5491,"duration":2},{"text":"Brian: Mm-hmm. You are you are controlling things too much.","offset":5493,"duration":5},{"text":"Host: Yeah, doesn't sound like me.","offset":5498,"duration":2},{"text":"Brian: You have controlled things too much and not allowed the system to do its job.","offset":5500,"duration":7},{"text":"Host: So I need to let go.","offset":5507,"duration":1},{"text":"Brian: What it was communicating. Let go. Let go. When when the when you feel the change, that's we're just re-aligning feeling that change.","offset":5508,"duration":11},{"text":"Host: So as I start to let go and allow myself to breathe in a whole variety of different ways, at a whole variety of different intensities. So appropriate breathing for the level of movement and intensity. Are you saying that because those things start to then match up, that then means that my oxygen delivery to the tissues and the usage is also going to start to match up? Whereas now there's a discrepancy.","offset":5519,"duration":27},{"text":"Brian: Yeah. And because of that under-utilization issue, that's probably over time created the issue with your tissue being able to use that oxygen even at lower rates, right? So the ability to get that going again is what we want that's what we're trying to train. But the strength training actually helps with that as well, right? Because we're looking for better mitochondrial development, and that comes in many different fashions. Walking, yes. However, strength training, yes. It just comes in a different way. It's just high intensity, right?","offset":5546,"duration":48},{"text":"Host: And I've heard you say, Brian, the greatest hack for your mitochondria is working on your breath.","offset":5594,"duration":6},{"text":"Brian: Yes. Well, yeah.","offset":5600,"duration":1},{"text":"Host: Which again, I don't think a lot of people are thinking about. And sort of tying this up to the start of the conversation, breath is that central piece that so many of our behaviors, our emotions, our ability to perform, they come off as a byproduct of our ability to, like, breathe appropriately and efficiently, right?","offset":5601,"duration":20},{"text":"Brian: Yep. And I don't, you know I mean, I don't know how many people have your issue. I've only seen it, like, four or five times. Um, granted every person has been very aware of the breath game for quite some time, right?","offset":5621,"duration":16},{"text":"Host: Yeah, because I guess people like me who are really interested...","offset":5637,"duration":3},{"text":"Brian: Well, anybody who read Breath typically was like nasal breathing's everything, and that's not on James, James wasn't saying that's everything...","offset":5640,"duration":9},{"text":"Host: I was ever since I first came across Patrick McKeown however many years ago, like, I have been oh, right, I'm going to go and walk nasal breathing, but I probably overdone it. And I get that.","offset":5649,"duration":11},{"text":"Brian: Look, man, I've been staring at this down the down the lens of a metabolic cart for quite some time and seeing the changes and and what it like I mean the changes simply in walking with one's mouth open versus one's mouth shut were eye-popping.","offset":5660,"duration":19},{"text":"Host: In terms, and make that really practical, in what? In terms of your ability to burn carbs or fats?","offset":5679,"duration":5},{"text":"Brian: So if I'm overbreathing, which isn't what your problem is, right?","offset":5684,"duration":4},{"text":"Host: So that's not my problem.","offset":5688,"duration":2},{"text":"Brian: Which most people, most people are have an overbreathing issue. Yeah. So if I'm overbreathing, I'm definitely not getting oxygen to the tissue, right? So I'm I'm the sympathetic nervous system clamps down and I'm point I'm not going to be I am going to be screwing up the the dissociative curve of oxygen's utilization because I have I'm getting rid of excess CO2. So if I overbreathe, and if anybody wants to do if anybody's done Wim Hof, they've felt what overbreathing feels like. That's where that high starts to to kick in. But what's happening is is things are clamping down, right? And so we're limiting how oxygen gets used and so the red blood cell can't offload as much oxygen because there's not enough CO2. Oxygen is a useless, destructive molecule without CO2, and CO2 is what knocks that helps knocks that oxygen molecule out of the red blood cell to go to the cell to be used.","offset":5690,"duration":68},{"text":"Host: Also, Brian, just to finish off that loop as well, given what I shared with you right at the start, which is that I feel compared to last time I was here in LA with you that I'm a different person. My nervous system sits differently. I'm calmer, I'm more present. Do you think in any way that matches my journey with breathing, i.e., perhaps I was overbreathing like most of us five-six years ago, and by working on the lower ends and the nasal breathing, maybe neglecting the higher ends, but by working on that lower end, do you think there's any correlation between that and the fact that I'm less reactive these days?","offset":5758,"duration":42},{"text":"Brian: There's direct correlation between aerobic and parasympathetic nervous system, and sympathetic nervous system and anaerobic.","offset":5800,"duration":9},{"text":"Host: So if so it completely matches up.","offset":5809,"duration":2},{"text":"Brian: It it is direct correlation.","offset":5811,"duration":1},{"text":"Host: As I've worked on this lower end, my parasympathetic nervous system's much better able to function.","offset":5812,"duration":5},{"text":"Brian: If the lion walks in the room, your system goes oh, we need immediate action. You think it's going to go use fatty acids for that? It can't.","offset":5817,"duration":10},{"text":"Host: Needs carbs for that, it needs to go to sympathetic.","offset":5827,"duration":2},{"text":"Brian: More carbohydrates or it needs, yeah, creatine phosphate system. It needs instantaneous, but oxygen's a part of that, in when I go use tissue, it it'll deplete that. Like we've seen that. Like, uh, there is no one or the other, it's like how quick that's going to happen.","offset":5829,"duration":23},{"text":"Host: Well Brian, I love talking to you, I love hanging out with you. Um, we've covered so much, we've gone into so many different areas. As we wind this down, if people want to learn more about you, they want to work with you, they want to do your online courses that you guys run, where should people go?","offset":5852,"duration":16},{"text":"Brian: shiftadapt.com. So s-h-i-f-t-a-d-a-p-t dot com.","offset":5868,"duration":9},{"text":"Host: And and what's on there, what can they like...","offset":5877,"duration":2},{"text":"Brian: We we we still have a membership site, and we have a lot of stuff a lot of courses, things like that or webinars we've done that we talk about a lot of this stuff. We'll be releasing a a number of programs etc., that'll be on a little bit higher level than that that people can go do. And then on the upper tier of all of that is actually hiring my business partner and or I.","offset":5879,"duration":26},{"text":"Host: To actually work with you one-on-one.","offset":5905,"duration":1},{"text":"Brian: Yeah, so Emily Hightower who I work with, uh, she's on the other end of the stress here where she's helping with developing tools and regulating nervous system on the day-to-day throughout, you know, like hey, how are you managing this at in the moment type of stuff? Like what's your life look you know what's going on in life?","offset":5906,"duration":23},{"text":"Host: Yeah, amazing. We've covered so much. Um, emotional reactivity, the power to choose our response, breathwork, the different gears, the metabolic benefits of being able to access all the gears, etc. etc. To bring it all together, like Brian, if there's someone who has followed our conversation and still with us, and is like, yeah, you know there's something there for me, right, there's something Brian was talking about that applies to me. I haven't taken my breath seriously, I haven't taken my levels of physical activity seriously, or whatever it might be. How would you help that person? They feel stuck, they feel lost, they feel unmotivated. But at the same Brian, give me some inspiration, what is your final piece of advice? What would you say to that individual?","offset":5929,"duration":52},{"text":"Brian: Learn to say no. Learn to say no to the things you don't want to do. And that is a very that actually goes far deeper than just saying no to something you instantaneously know you don't want to do. It's it's looking at those sexy shiny things that are of excitement and being able to slow it down enough to say no to maybe getting into a business deal or taking a job that you really don't want to take, um, but you think you do because you got to make the money and maybe you could go figure that out another way, or you know, can you change some lifestyle habits? Um, I think no is the path to freedom. Because you'll only be doing the things you truly want to be doing if you learn to say no to the things you don't. And I have found that because of that, I'm surrounded by the people I want to be surrounded by. And and that's it. Um, it's simple. So um, if you can live the life you want, but I mean just applying the principles of making your day a process. Like literally make it a process. Like the dishes, right? Like I get to go drive to work. Yeah, you get to. Or yeah, I get to have a job. Or yeah, I get to drive in traffic. Because I get to live here, because I get to do these things. It's very different than I have to.","offset":5981,"duration":83},{"text":"Host: Yeah, love it, Brian. Thanks for everything you do. Thanks for the help you're giving me personally and for coming back on the show. Really appreciate it.","offset":6064,"duration":8},{"text":"Brian: Thanks for having me, love you dude.","offset":6072,"duration":2},{"text":"Host: If you enjoyed that conversation, then I think you're really going to enjoy this one.","offset":6074,"duration":4},{"text":"Guest: I want people to wake up and realize the creative nature of love, health, harmony, because that is available, and yet we struggle.","offset":6078,"duration":15}],"logs":[{"elapsed":"0.0","message":"Downloading audio from YouTube...","detail":null},{"elapsed":"0.0","message":"Trying download with browser cookies (ad-free)...","detail":null},{"elapsed":"2.6","message":"⚠ Cookie download failed: WARNING: [youtube] [jsc] Error solving n challenge request using \"deno\" provider: Error running deno process (returncode: 1): \u001b[0m\u001b[1m\u001b[31merror\u001b[0m: Uncaught (in promise) TypeError: Cannot read prope","detail":null},{"elapsed":"2.6","message":"Retrying without cookies...","detail":null},{"elapsed":"49.6","message":"⚠ Downloaded without cookies — audio may contain ads","detail":null},{"elapsed":"49.6","message":"Audio downloaded (62.3 MB) in 49.6s","detail":"File size: 62.3 MB"},{"elapsed":"49.6","message":"Video title: Why You Can't Relax, Sleep Or Focus! - Do This 5 Minute Habit To Feel ALIVE Again | Brian Mckenzie","detail":null},{"elapsed":"49.6","message":"Audio duration: 1:40:48 (100.8 min)","detail":null},{"elapsed":"49.6","message":"Large audio (100.8 min) — will use chunked transcription with gemini-3-flash-preview","detail":null},{"elapsed":"49.6","message":"Skipping full-file attempt — using chunked transcription for 100.8 min audio","detail":null},{"elapsed":"50.5","message":"Split audio into 3 chunks for transcription","detail":null},{"elapsed":"50.5","message":"Transcribing chunk 1/3 (starts at 0:00)...","detail":null},{"elapsed":"50.5","message":"Uploading audio to Gemini File API...","detail":null},{"elapsed":"55.5","message":"Audio uploaded in 5.0s","detail":"File ref: files/qa4n6etr6qsq"},{"elapsed":"55.5","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"126.6","message":"Chunk 1: 125 segments, last timestamp 45:00","detail":null},{"elapsed":"126.6","message":"Transcribing chunk 2/3 (starts at 45:00)...","detail":null},{"elapsed":"126.6","message":"Uploading audio (offset 45:00) to Gemini File API...","detail":null},{"elapsed":"132.2","message":"Audio uploaded in 5.6s","detail":"File ref: files/bfmj2aqm5e1b"},{"elapsed":"132.2","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"207.0","message":"Chunk 2: 135 segments, last timestamp 1:29:39","detail":null},{"elapsed":"207.0","message":"Transcribing chunk 3/3 (starts at 1:30:00)...","detail":null},{"elapsed":"207.0","message":"Uploading audio (offset 1:30:00) to Gemini File API...","detail":null},{"elapsed":"209.7","message":"Audio uploaded in 2.8s","detail":"File ref: files/a2toh0pzykbq"},{"elapsed":"209.8","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"227.3","message":"Chunk 3: 46 segments, last timestamp 1:41:18","detail":null},{"elapsed":"227.3","message":"Chunked transcription complete: 305 total segments","detail":null},{"elapsed":"227.3","message":"Total cost: 152,041 in / 25,663 out — cost: $0.1530","detail":null},{"elapsed":"227.3","message":"Total transcription time: 177.7s — 305 segments","detail":null},{"elapsed":"227.3","message":"Analyzing topics across 305 segments with gemini-3.1-pro-preview...","detail":null},{"elapsed":"276.2","message":"Topic analysis complete in 48.9s — found 15 topics","detail":null},{"elapsed":"276.2","message":"Analysis tokens: 27,235 in / 1,363 out / 5,455 thinking — cost: $0.1363","detail":null},{"elapsed":"276.2","message":"Pipeline finished in 276.2s — total cost: $0.2893 (211,757 tokens)","detail":null}]} \ No newline at end of file diff --git a/history/1775589261845-wO5iES4qjwE.json b/history/1775589261845-wO5iES4qjwE.json new file mode 100644 index 0000000..06c9e00 --- /dev/null +++ b/history/1775589261845-wO5iES4qjwE.json @@ -0,0 +1 @@ +{"id":"1775589261845-wO5iES4qjwE","videoId":"wO5iES4qjwE","url":"https://www.youtube.com/watch?v=wO5iES4qjwE","title":"Brian Mackenzie Reveals Single Best Way to Increase Fitness Level without Steroids","type":"youtube","topicCount":11,"segmentCount":108,"createdAt":"2026-04-07T19:14:21.845Z","uploadDate":"20250101","chunks":[{"title":"The Role of CO2 Tolerance in Stress","summary":"Brian explains that CO2 tolerance is the biggest encumbrance to downregulating stress. He notes that modern respiration rates are often unnaturally high due to chronic stress and overbreathing.","entries":[{"text":"Host: Brian Mackenzie, what would you say the number one thing, if you had to—if you had to pick one, that is the biggest encumbrance to people being able to properly downregulate, maybe relieve some stress, consequently improve their performance?","offset":0,"duration":14},{"text":"Brian Mackenzie: At a physiological level, uh, it is a tolerance to CO2, which has to do with their nervous system. Um, so, you know, an interesting—I was just on a call with a friend of mine who’s writing a book on, um, walking, and she wanted to go over some stuff with the breathing, and she’s like, \"You know,\" and she’s a DPT, so she’s, you know, a doctorate in physical therapy, so she’s well educated inside the world of, um, you know, all of this stuff.","offset":14,"duration":40},{"text":"Brian Mackenzie: And she’s like, \"Are our normal respiration rates that the medical community says are 12 to 18 breaths a minute, is that normal?\" And I’m like, \"Well, it’s normal for the culture that we’re in.\" And I’m like, \"But I mean, my respiration rate’s around seven, and I don’t do a tremendous amount of breathwork. However, I’ve done enough and I apply the principles of this stuff into what it is I’m doing.\"","offset":54,"duration":37},{"text":"Brian Mackenzie: And that just, you know, that is alluding to the fact that most people are so, um, hot—running hot, or stressed, that their nervous system’s pretty, you know, fried. Or, and/or they’ve become so CO2 intolerant. So we respond to carbon dioxide—it’s the large—it’s a big, big, if not the biggest, player in driver for, um, breathing while we’re awake. Um, and it’s not the only one, but it’s one of the main ones.","offset":91,"duration":41},{"text":"Brian Mackenzie: And when we become sensitive to this, rightfully so, our breathing changes. The dynamics of our breathing change. Um, if our mouth is open, we instantly change our respiration rate, and that’s more to do with, um, baroreception, which is not chemoreception, which is where CO2 fits in—meaning pressure change. But, a lot of people are talking all day long, which is mouth breathing, so my respiration rate’s up.","offset":132,"duration":32},{"text":"Brian Mackenzie: A lot of people are very stressed; they just mouth breathe in general. So they go exercise and they’re not doing a whole lot, or they’re walking around and their mouth is open. Um, that all can move towards being, um, you’re offloading excessive CO2 at that point. So when you’re overbreathing, what we’re doing is you offload—you, you get rid of more CO2. You don’t bring on more O2.","offset":164,"duration":29},{"text":"Brian Mackenzie: In fact, you and I right now are—uh, we exhale roughly 80% of the oxygen that’s coming in. So we don’t need it, right? We don’t need all that oxygen because there’s enough—there’s plenty. It’s just only when exercise or movement goes up that that changes. So what happens is we change the dissociative curve of what’s going on with our breathing, and when we become a little less—uh, we’re not using oxygen as well and we still continue to get stressed, our breathing goes up.","offset":193,"duration":38},{"text":"Brian Mackenzie: And so we just kind of—the system self-adjusts and tries to balance itself out in what it does. And part of that process is that our breathing changes. The dynamics of our breathing change, and it just gets easier to breathe like that versus taking, you know—and you don’t need to be taking a full inhale while we’re sitting here. You know, you’re breathing perfectly fine as we’re sitting here.","offset":231,"duration":31},{"text":"Brian Mackenzie: But the vast majority of people are not.","offset":262,"duration":3}],"startTime":0},{"title":"Thrive Market Sponsor Break","summary":"The host shares a promotional message for Thrive Market, highlighting their healthy pantry staples, snacks, and a discount code for viewers.","entries":[{"text":"Host: While I’m at it, one of the things that I do like about Thrive Market, which I talk about all the time on my channel—and I know you’re thinking, \"Oh, here comes the plug.\" Well, you’re right. Is that Thrive Market doesn’t have a bunch of stuff that has weird added ingredients into it. Like, they adopt a lot of what, sort of, the EU puts into place for their processed foods. So, like, packaged foods at Thrive Market don’t have weird additives, there’s no red dyes and crazy stuff.","offset":265,"duration":36},{"text":"Host: So, at least even if some of the stuff is processed, like maybe some pantry staples and stuff like that, it’s the way that it should be. Processed because you’re processing it, not because you’re adulterating it and turning it into some hyper-palatable nonsense. So, that link that I put down below is for a 30% off discount link for anything from Thrive Market. So when you go ahead and you use Thrive Market, you get 30% off your entire grocery order when you use that link that’s down below.","offset":301,"duration":38},{"text":"Host: They also have frozen meat and seafood options. They’re starting to roll out fresh options for some people; you might not see it reflected on your account or not. But bottom line is, they’ve got really good stuff, and they’ve got canned fish, so they’ve got the tuna, they’ve got Wild Planet sardines and anchovies—I mean, all that stuff if you’re into that and you’re trying to live more Mediterranean.","offset":339,"duration":27},{"text":"Host: But some of the things that I love the most are just being able to get healthier snack options for my kids because I don’t want to just go to regular Vons or Safeway here in California and get something that has a load of garbage and MSG and stuff in it. If I’m going to get them a snack, I want something that I feel like, I don’t know, I don’t feel bad about giving them. So that’s the whole idea behind Thrive Market is being able to bring healthier options to the consumer at a decent price, right?","offset":366,"duration":34},{"text":"Host: So that link down below gets you 30% off plus a free gift. I really do recommend that you check them out. Check them out; they’ve been a sponsor on this channel for over half a decade, and I wouldn’t be recommending them if it wasn’t something that I honestly used myself. So that link is in the top line of the description.","offset":400,"duration":17}],"startTime":265},{"title":"Measuring and Improving Respiration Rates","summary":"Brian discusses the inaccuracies of wearable tech for measuring respiration rates and suggests better methods. He emphasizes that slowing down breathing and increasing CO2 tolerance is low-hanging fruit for improving overall physiological function.","entries":[{"text":"Brian Mackenzie: And so that overbreathing thing, the 12 to 18 breaths a minute—a lot of that’s done on data that’s being collected from something called respiratory sinus arrhythmia, which isn’t exactly the most effective way, or the algorithms off of a lot of the technologies that are on the periphery, which is not very accurate in terms of understanding a respiration rate. So, meaning like if you’re wearing an Oura or a Whoop, your respiration rate is probably not what that is telling you.","offset":417,"duration":44},{"text":"Brian Mackenzie: Um, there’s a good chance it’s not. Um, that said, the data with those things is also—but not also, the data with those sort of things are consistent. Meaning, if there’s a change, there’s a change inside that. So they can, you know, they might be inaccurate, they’re just consistently inaccurate, which is—which is a good thing. Um, and they’re different.","offset":461,"duration":33},{"text":"Brian Mackenzie: But if you—you would want to, if you really wanted to understand respiration rate, since I talked about it, since I brought this up, it’s—you, you would get that—you, you would get something, a strap or something that would actually measure, like, as your ribcage begins to move, the, you know, the depth of that. Or you get on a resting metabolic—you, you do a resting metabolic test assessment, and that’ll actually capture your breathing rate, um, and what’s going on.","offset":494,"duration":46},{"text":"Brian Mackenzie: And that’s not the be-all end-all here. What is, is that, well, with people who have dysfunctional breath—and that is, by the way, dysfunctional breathing, any—in my opinion, anything above 15 breaths a minute is dysfunctional. Um, you, you have a massive gap in how your physiology’s going to operate, and we can—we can make major changes very quickly. And that would be through things like going for a walk and shutting your mouth, or doing a little breathwork and slowing down your breathing to a degree, or doing some breath hold work, um, that actually helped us increase the CO2 in the system so that we actually were using the oxygen a bit more.","offset":540,"duration":64},{"text":"Brian Mackenzie: And it’s not just about the oxygen. That CO2—oxygen’s a worthless, destructive molecule without carbon dioxide inside of this system. Um, in fact, it’s largely a destructive—oxygen is very destructive itself, far more destructive than CO2. Um, it’s just how that CO2 is getting used, right? Um, and if I don’t have enough of it in the system, the vasculature constricts more, right?","offset":604,"duration":44},{"text":"Brian Mackenzie: So if I have more of it in the system, the vasculature opens up, we vasidilate. So we—we—we start to—to train the system as a whole when we actually bring on an adequate amount of that. So I think, you know, to answer your question, CO2 tolerance becomes a very big player in some of the lowest-hanging fruit that people could actually go and understand, and that is simply by just slowing down your breathing a few times a day, maybe.","offset":648,"duration":39},{"text":"Brian Mackenzie: Doing some breathing protocols that you like, maybe not doing some hyperventilation stuff if you’ve got any issues going on just until you’ve addressed this stuff. Um, and then applying this into your current, you know, movement strategy. Like go for a walk, you know, 20, 30, 45 minutes and shut your mouth and see how you feel after that. And there’ll be a very big difference if it’s the first time you’ve really done something like that.","offset":687,"duration":39}],"startTime":417},{"title":"CO2, the Amygdala, and Anxiety","summary":"Brian details research showing the amygdala's role as a CO2 modulator and its connection to fear and anxiety. He explains how increasing CO2 tolerance can make individuals calmer and less reactive.","entries":[{"text":"Host: What is—what’s happening in the brain when CO2 builds?","offset":726,"duration":4},{"text":"Brian Mackenzie: That’s a good question. So, um, a—a very—a good friend of mine, his name’s Dr. Justin Feinstein, did some work around, uh, studying the amygdala. He—uh, he—uh, he originally was doing research around, like, float tank therapy, stuff like that, and people get downregulating, but he—he got curious about this breathing thing. Um, and he ended up studying two sets of twins that had calcified amygdalas, and he was studying people that had anxiety, um, high levels, medical—like medically treated people with anxiety, okay?","offset":730,"duration":67},{"text":"Brian Mackenzie: Um, and if you have a calcified amygdala, you’re pretty much—you are a danger to yourself. Um, you don’t interpret fear as well, right? So you’ll put your hand, like, on a stove and not think about that, right? Like it’s—it’s just not something that kind of equates, you know, um. You—you—you just become a little bit of a danger to yourself, right? Um, and he was exposing people with anxiety to bolus hits of carbon dioxide.","offset":797,"duration":57},{"text":"Brian Mackenzie: And if—he inevitably ended up exposing these two sets of twins to, um, CO2 as well. And the twins had some of the most profound fear that they had ever experienced ever in their lives when exposed to the CO2. And it turns out the amygdala, even though it’s part of the limbic system and has this kind of, like, fear center in it, it also is a modulator of CO2, carbon dioxide.","offset":854,"duration":56},{"text":"Brian Mackenzie: And when my nervous system—when I’m hot, like if I’m—if I’m upset or I’ve, you know, I’m—I’ve been doing way too much, you know, I worked out a ton, like and in—and I need to recover, you know, I’ve been multiple days and I’ve been training, you know, I get—your nervous system gets a bit fried. You—you will notice that you are more reactive. All of that plays into how CO2 is actually operating as well.","offset":910,"duration":53},{"text":"Brian Mackenzie: My nervous system can be running hot, and you can bet your tolerance to CO2 has gone down, meaning you are much more sensitive to that. So the chemoreceptors and everything that’s going on in that brain is now more sensitive to this stuff. However, if I can bring it down enough and I can expose myself to an adequate amount of CO2—let’s just go back into, let’s go back in time, when people used to have panic attacks, what would they do, let’s just say in the 70s and 80s, if somebody was having a panic attack?","offset":963,"duration":58},{"text":"Host: Stop and breathe?","offset":1021,"duration":3},{"text":"Brian Mackenzie: They’d hand them a paper bag and tell them to breathe into the paper bag.","offset":1024,"duration":5},{"text":"Host: Oh, that's true.","offset":1029,"duration":2},{"text":"Brian Mackenzie: Why would they have somebody do that? CO2. Turns out that you can slow things down and calm down a bit more when you add a bit more CO2 into the system. Um, this isn’t necessarily, like, hey, go—go out and buy CO2 tanks and start, you know, huffing CO2. You know, this is like, hey, what’s going on here? What could I toggle or introduce into what I’m doing in order to learn more about why I’m a little sensitive to this?","offset":1031,"duration":57},{"text":"Brian Mackenzie: You know, um, it’s—it’s interesting. We’ve—uh, at—at Andy Galpin’s old lab, one of his, uh, students, uh, Preston did a—did a—his thesis on a lot of this on some of this stuff where we’re doing an exhale assess—we do this exhale test where it’s a max exhale. Um, you, you know, inhale and then you exhale as long and slow—the redundancy of that is—as—as possible, right? And he found out that—I’ve been using this assessment for years now, um, and I—I figured this out, but we wanted him to—we wanted somebody else to kind of play with this as well.","offset":1088,"duration":67},{"text":"Brian Mackenzie: And he found out that the athletes he was testing, those who had a low CO2 tolerance score, so a low exhale assessment, had a—had more anxiety, and that was very much indicative of that. Their state anxiety was predictable by this score, by this test. So I can basically—and that doesn’t mean I’m diagnosing you with anxiety, by the way. That is—that just means from a nervous system standpoint, anxiety sits on the nervous system. Like, anxiousness is a point where you’re beyond, like, it’s a nervous system response.","offset":1155,"duration":64},{"text":"Brian Mackenzie: Um, so it’s not every day you’re going to be dealing with this, but you can bet that if you learn to stop overshooting the mark and getting anxious or taking on or worrying too much, you, you know, when you’re in those moments, you’re going to find out if you do an exhale or you try and hold your breath like or test this, like, you—it’s going to be real low. When you get a hold of that and you can remain calm, it’s going to go up.","offset":1219,"duration":52},{"text":"Brian Mackenzie: Um, but this is a very trainable thing to a degree that, like, you know, the vast majority of people as a, you know, just kind of a—a blanket statement here, like the vast majority of people if I had them hold their breath aren’t going to hold their breath much longer than 90 seconds, right? CO2 tolerance plays—CO2 tolerance plays a very big role in your ability to hold your breath, right? Part of that is your ability to deal with the pain and the panic that’s starting to shoot up and go off.","offset":1271,"duration":53},{"text":"Brian Mackenzie: But large majority of that is an adaptive process to this and being able to tolerate more CO2 in the system and get—getting used to that. So the vast majority of people hold their breath for 90 seconds, yet there are human beings holding their breath for seven minutes, no problem. So that’s a large gap, right? And I’m not suggestive that anybody go out and learn to hold their breath for seven minutes, but it could be a cool fun time to go do that.","offset":1324,"duration":46},{"text":"Brian Mackenzie: But at any rate, you get that breath hold up to two, three, maybe four minutes? I—I can—you can bet you’re going to be a calmer, less reactive person. 100%.","offset":1370,"duration":17}],"startTime":726},{"title":"Inhale vs. Exhale Breath Holds","summary":"Brian breaks down the differences between holding your breath on a full inhale versus an empty exhale. Inhale holds impact blood pressure and parasympathetic response, while exhale holds trigger a faster psychological panic and immediate CO2 response.","entries":[{"text":"Host: What’s the—benefit to doing a hold on full versus a hold on empty?","offset":1387,"duration":6},{"text":"Brian Mackenzie: The hold on f—I mean, a—a number of things. Um, you know, within like the yogic world, they’ve—they’ve long started with things with on an exhale hold. Um, I’ve found that the inhale hold is a lot easier to work with people um, just because it allows for you an off switch—like let go. So if I’m holding up top, it’s [exhales] right, to let go versus [inhales sharply]. Right, um, the inhale is typically, um, the problem for people in my—a lot of my work.","offset":1393,"duration":97},{"text":"Brian Mackenzie: So, meaning, people inhale rather quickly versus the ability to inhale slowly, right? And then there are those of us that, you know, will struggle a bit with an exhale. But that’s largely a CO2 tolerance thing. Um, so the inhale hold is more of a pressure thing. You’re going to see blood pressure, you’re going to see pressure changes as a result of that. People who struggle with bring the—with bringing their parasympathetic nervous system on board—so high-stress people—are going they—they might have some issues with the inhale breath hold, meaning they’ll get—they’ll get woozy real quick.","offset":1490,"duration":66},{"text":"Brian Mackenzie: Um, they’ll—um, you know, it—there—there will be a disconnect from the heart to the brain as a result of that because of the pressure changes. Um, but I don’t work to do like maximal like stuff the lung type of stuff and, you know, a lot of this stuff with inhale breath holds, what I have people do is simply to first and like strong urge to breathe, not panic urge to breathe. Um, those seem to have the biggest impacts with people.","offset":1556,"duration":60},{"text":"Brian Mackenzie: So just repeating, like, an on the minute. Like, hey, I’m going to breathe for a minute or two and then I’m going to hold my breath until a strong urge to breathe and doing that for five or six sets is a very, very big downregulating, um, tool. Now, if somebody’s tuned up that’s pretty anxious, that may not be the thing to do. Um, it may be go the other way to the negative—is you’re working with dead space mostly.","offset":1616,"duration":54},{"text":"Brian Mackenzie: Now, there’s still some air in there in the lungs on an exhale, but you got to be pretty, pretty damn tuned in like a Mark Healey or like a, you know, yogi from India to get all that air out of your lungs. Um, you know, other than that, you know, let’s just say we just [exhales] and I hold. There’s not as much of a—of a blood pressure change that’s occurring; there’s more of a—we’re kind of working on the immediacy of CO2’s response to the system.","offset":1670,"duration":54},{"text":"Brian Mackenzie: So you’re going to actually work more on the psyche with a negative breath hold in my opinion, because people aren’t—I mean, if people right now were to go and go ahead and dump all the air you’ve got and hold your breath, see how quickly panic comes on. Now, relax after you heard that and did that, take a few breaths, and then go do it with an inhale. You’re not going to panic as quick.","offset":1724,"duration":37},{"text":"Brian Mackenzie: Yeah. It’s just not going to happen. So I kind of look at it in terms of, you know, working more on the mental with the negative and working more on the physiological with the positive. However, there are definitely, you know, there’s—some differ—there’s some differences but there’s also much crossover. You hold your breath enough on either end with very few breaths, you’re going to get hypoxic. Um, you’ll—introduce hypoxia, but most people will never reach that point because they’re so CO2—I wouldn’t say so, but they’re CO2 intolerant enough to where CO2 is convincing them to take a breath well before oxygen is going lights out.","offset":1761,"duration":47}],"startTime":1387},{"title":"Hypoxia and Mitochondrial Efficiency","summary":"Brian cites a study comparing an elite triathlete and a freediver to illustrate metabolic efficiency. The freediver's hypoxic training allowed them to produce more ATP using less oxygen.","entries":[{"text":"Host: Is there a—is there a metabolic interplay here as well, like the—of the mitochondria’s ability to kind of function in this hypoxic state?","offset":1808,"duration":9},{"text":"Brian Mackenzie: Yes. Yeah. The beauty of this, and there’s a great paper out there, uh—I forget what it—I—I’m paraphrasing, but it—I think it’s called \"The Tortoise and the Hare\". There’s an actual paper, um, where these guys in Sweden, I believe it was Sweden, they studied, um, two of the people who were at the university were at the time—one was an elite triathlete and one was an elite freediver.","offset":1817,"duration":57},{"text":"Brian Mackenzie: And they were both competing that year and they wanted to test, well, what’s the difference between mitochondria and the aerobic function of these? And one would have suspected and been correct that the triathlete who’s at an elite level has far greater what we would assume metabolic health and the ability to function aerobically at higher states. Correct. There’s the—the one major caveat here, and this is where hypoxia becomes a very, very potent tool.","offset":1874,"duration":44},{"text":"Brian Mackenzie: Um, and there’s much more to hypoxia that we could go into a rabbit hole on. However, um, the breath holding and learning to hold one’s breath and get to hypoxia in particular they found that the freediver is able to use less oxygen with more—for more ATP.","offset":1918,"duration":40},{"text":"Host: Hmm.","offset":1958,"duration":2},{"text":"Brian Mackenzie: So, they are far more efficient on that end of energy—getting energy off of that electron transport chain than the aerobically inclined athlete. Now, I wouldn’t suggest that, um, you do one of the other; I would suggest you do both.","offset":1960,"duration":34}],"startTime":1808},{"title":"Integrating Breath Holds into Training","summary":"Brian explains how to incorporate breath holds into existing physical training routines, such as holding breath at the end of sprint intervals. This practice can stimulate short-term EPO and red blood cell responses.","entries":[{"text":"Host: Yeah. What about concurrently? I mean, what about literally—this might be more advanced so I mean, disclosure there, but someone that is, um, you know, maybe doing Zone 2, maybe they’re doing their base training—is there some form of benefit to doing occasional holds while actually training?","offset":1994,"duration":24},{"text":"Brian Mackenzie: Oh, I—yes. I—I have people do this all—yeah. This is part of training regiment like 101 with me. It’s just like, yeah, hey, we’re going to be doing this, you’re also doing this. Like, we’re—we’re targeting these things in many aspects, like most of my clients—","offset":2018,"duration":17},{"text":"Host: So they’re, like, holding their breath while you’re running, kind of?","offset":2035,"duration":1},{"text":"Brian Mackenzie: Yeah, most of my clients don’t just do strength and conditioning and endurance work; they do strength conditioning, endurance work, breath hold work, etc. Like, they’re getting the whole—but, it’s a lot, you know, if I were to start dumping out everything we do, it’s—you know, heat training, cold training, like all of—where’s the time for—well, that’s the thing is the art is in, hey, what—what’s this person’s schedule look like? Where can we insert these things so that they’re actually effective? Because if they’re not—if we can’t, there’s no sense. Like why would we implement this? Like, you know, breath hold is just a very simple thing to implement for anybody.","offset":2036,"duration":59},{"text":"Host: If you were to say—I mean this is a hypothetical situation where you’re going to, you know, hop on an assault bike, let’s say, do a 20-calorie hit on an assault bike and then hop off—is there a benefit at an advanced level to attempting a—a hold during your recovery there?","offset":2095,"duration":15},{"text":"Brian Mackenzie: Oh yeah, no. No, there’s research that support—well, I—I would go about it, um, in a way of, like—go—do—do a sprint, short sprint, right? Warmed up, going into some sprints. Like, I—what I like—here’s what I like to do, um, is like five minutes very, very—every five minutes you’re hitting anywhere from 6 to 15 seconds, right? Hard. And you could definitely go out to 90 seconds or three minutes if you want for intervals, but by all means hold your breath on the last six seconds.","offset":2110,"duration":56},{"text":"Brian Mackenzie: Just hold it. Just lock it down. You’ll be able to get through it. Um, hold it and then you’ll start to see you can end up holding it a little bit longer and a little bit longer. That has very big impacts with stuff like this. You may not get—you’re not going to really get hypoxic from stuff like this, like what I was bringing up with the \"The Tortoise and the Hare\". What you’re going to do is you’re going to—you’re going to start getting probably some boosts in EPO and some red blood cell responses short-term, and then long-term you’re going to get some—some of that stuff that’ll hold on.","offset":2166,"duration":52},{"text":"Brian Mackenzie: Um, it’s not going to be something I think that I would use for hyp—you know, going to altitude, but it will help for sure—for—100% it will help. Um, it’s not going to be the thing that, you know, you would want to be doing for altitude exposure, though.","offset":2218,"duration":27}],"startTime":1994},{"title":"Nasal vs. Mouth Breathing During Exercise","summary":"Brian discusses the physiological differences between nasal and mouth exhalations, emphasizing that dumping CO2 via mouth breathing alters the dissociative curve. He recommends nasal breathing for moderate exercise but warns against forcing it during high-intensity training.","entries":[{"text":"Host: If we pivot for a second to talk, you know, nasal versus mouth?","offset":2245,"duration":4},{"text":"Brian Mackenzie: Yeah.","offset":2249,"duration":1},{"text":"Host: I think one of the things that I’ve personally—I’ll just use my own experience here is—um, my ability to inhale through the nose through activity is fine. It’s exhalation through the nose that, um, becomes almost restricted; it’s just harder. It’s just, like, takes more time and by the time all the air is out of my nose, I’m hypox—it’s like I’m, you know, it’s taking so long for the air to physically come out of my nose that then I’m almost going into oxygen debt, right? So—or what feels like it. So then it’s like then you’re almost going into—","offset":2250,"duration":49},{"text":"Brian Mackenzie: Yeah, it's just CO2. That's the carbon dioxide screaming at you there.","offset":2299,"duration":10},{"text":"Host: So it's—is there—I'm sure there's different modalities, but if you're working on quote-unquote \"nasal breathing\", is it okay to exhale through the mouth during activity? So inhale nose, exhale mouth, or is that a completely different response than if you also exhale through the nose?","offset":2309,"duration":23},{"text":"Brian Mackenzie: Well, if you’re going to—if—so, nose breathing we know is parasympathetic—has more parasympathetic tone. It’s that exhale that’s the most important part of that.","offset":2332,"duration":14},{"text":"Host: Okay.","offset":2346,"duration":2},{"text":"Brian Mackenzie: Here’s why. Anything below moderate levels of exercise, I’m getting the same amount of oxygen in. I do not need to switch over until beyond moderate levels of exercise to [panting] to onboard more oxygen. Okay. It’s the CO2 coming out that is really the player in this game to where [exhales through nose] versus [panting].","offset":2348,"duration":63},{"text":"Brian Mackenzie: Yeah, I just dumped all that CO2. So that in—and so now we start to mess with that dissociative curve that I was kind of talking about, right? Um, and not in all cases, but most cases, like if you’re—if—if you have to mouth breathe at less than moderate levels of exercise, I—you can bet you’re—you’re messing with, uh, aerobic stuff. Yeah, mm-hmm. Maybe not a ton, but enough. And if that’s your goal, then—and that would be my goal if I was somebody who was exercising.","offset":2411,"duration":53},{"text":"Brian Mackenzie: Um, I’d use high intensity for high intensity and we get into mouth breathing plenty. I see many, many people who are glued to the concept of nose breathing till the end. Like, it’s just they nose breathe even at high intensity. Um, and you are doing the exact same thing but in an opposite way of overbreathing now. You are literally not able to use oxygen the way it was used in your system’s getting more acidic than it actually needs to.","offset":2464,"duration":47},{"text":"Brian Mackenzie: So, pH is changing, hydrogen’s not getting dealt with as well. All the—you know, all of this stuff—is—I’ve seen the crossovers in—on the metabolic stuff, you know, where people are limiting themselves. And they lack the ability to sustain higher respiration rates at higher intensities.","offset":2511,"duration":49}],"startTime":2245},{"title":"Regulating Training Intensity and Adaptation","summary":"Brian addresses how to balance different training intensities and adapt to stressors. He advises testing individual adaptations by isolating variables, like adding daily walking, rather than constantly increasing training volume.","entries":[{"text":"Host: Do you, with your training in that case, are you—do you have a pretty clear line of delineation between \"hey, here's—here's my aerobic stuff and here's my high intensity stuff\"? Like not sitting in that kind of—there's some people out there that'll believe that, like, if you train within that gray area, sort of, you know, lactate threshold area, that's like really a sweet spot where you're—and then there's others that are saying like, \"Hey, no, we've got a very clear—it's a very clear line of delineation where we don't sit in that gray area, we either go extreme high intensity or we go lower intensity, and the magic ends up naturally happening by training those two systems.\" I'm just curious your take on that.","offset":2560,"duration":36},{"text":"Brian Mackenzie: Uh, no. I don’t think any manmade thought on how my body should respond to things should be limited. That doesn’t mean—and—and I’m very, very, very careful to watch what it is I, in particular, inevitably get enamored with. I’ve been enamored with low intensity. I’ve been enamored with high intensity.","offset":2596,"duration":46},{"text":"Host: Yeah.","offset":2642,"duration":1},{"text":"Brian Mackenzie: And—and I’ve done moderate intensity. Um, you know, I’ve been enamored with that as well. Um, it all plays a critical role. Um, I don’t consider like walking low intensity. No. I consider that the buy-in for you and anybody to manage, uh, any and all activity. Um, you know, that doesn’t mean like I’ve got, you know, like I wouldn’t ask an NFLer to be walking 90 minutes a day because they’re probably at practice and they’re probably getting 10,000 steps in a day anyway.","offset":2643,"duration":53},{"text":"Brian Mackenzie: So like, you know, I just want them to do like 15, 20 minutes in the morning or something just to clear, you know—get lactate levels down, get cortisol levels down, um, in the morning so that we’re kind of stabilized and ready to go. Um, but, yeah. I—I think the full spectrum, however, I’m very careful to—I would say look—80% of what you’re doing, if you’re—your mouth should be shut.","offset":2696,"duration":51},{"text":"Brian Mackenzie: But you had—you would be best being mouth open several times a week for very short periods of time.","offset":2747,"duration":10},{"text":"Host: Yeah. And I think being able to—how do you suggest that someone that maybe isn’t as in tune with their body be able to regulate and understand, like, when they need to throttle down their training versus throttle it up? Because I have found that that is a very confusing place for most people, and it’s on both ends of the spectrum, whether it’s an extreme or an elite athlete versus someone that’s a newbie. It’s very difficult to really ascertain, like, okay, when is it time to throttle down? When am I doing—like when your sort of allostatic load is so high already, like do you throttle down your training or do you try to increase your training to deal with it? Like, what’s—how does someone kind of regulate that? What would you suggest to someone?","offset":2757,"duration":50},{"text":"Brian Mackenzie: Uh, I mean it’s a great question. Um, I—people really need to spend time learning what adaptation looks like with one thing at a time. Um, so, you know, like I brought up the walking thing before with you, right? Like I get people to walk. I want you to just implement that right now. And then, you know, whatever else you’re doing, just keep doing that, but we’re walking.","offset":2807,"duration":46},{"text":"Brian Mackenzie: You’re going to find out if you can do the other stuff if you’ve added in walk—you know, 45 minutes to 90 minutes of walking a day, right? Like you will find out if you can continue to have that stuff. Then it’s like, okay, well what’s the goal? You know, I just—I was talking to a buddy of mine who’s down in Australia, um, last week. And I hadn’t seen him in a—in a number of months, um, and we do video chat. And—um, he—it came on and I was like, \"Whoa, somebody put on some weight.\"","offset":2853,"duration":49},{"text":"Brian Mackenzie: And not—not fat. He definitely put on muscle. Like I was like, \"Damn!\" And he’s like, \"Yeah.\" He goes, \"It’s interesting, I’m only lifting three days a week.\" And he goes, you know—and he’s 35. And he’s like, \"You know what’s interesting is—is that I’m lifting far less than I did when I was in my 20s and I’m putting on more muscle now than I was then.\" Am I getting that interesting? Like, how many of us think we just need to go do more, more, more, more and literally aren’t miss—are missing adaptive processes because we’re just continuing to add in a stressor, be it weightlifting, right, as the example.","offset":2902,"duration":71},{"text":"Brian Mackenzie: Like I know a lot of people who train six days a week, right, and continue to do it. And there’s a—there’s a sharp ramp up at first with that, and then it just [gestures] peters out and does its thing. And then it’s real hard to make gains. Um, you know, versus like, hey, how about three days a week of that? You know, um, what happens with that? Are people willing to toggle or screw around with things to learn where that—where that is?","offset":2973,"duration":42},{"text":"Brian Mackenzie: What can you get away with? What is still creating the gains that you want? What do you want? All right, well let’s put one thing down first. Let’s go after that thing and let’s screw around to find out where that sweet spot is with this. And the reality is, is that’s what life’s about. Being able to creatively figure out what works and what doesn’t so that you’re doing the things you want versus not doing the things you’re not—you don’t want to be doing.","offset":3015,"duration":57},{"text":"Brian Mackenzie: Like, I’m continuing to work out all the time and do all this stuff that—because I’m doing everything. I’m doing the ice bath, I’m doing the sauna, I’m doing the hyperbaric chamber, I’m doing the hypoxico, I’m doing strength and conditioning. Like, dude, like I get it, because I do all that stuff. However, it all comes in little segments. Like it’s not all going on at the same time. There’s, you know, it’s all adjusted because I’ve been at it for like 25 years and I know when—you can’t do it all at the same time.","offset":3072,"duration":48}],"startTime":2560},{"title":"Finding the True Motivation for Training","summary":"The host and Brian explore the deeper psychological reasons behind wanting a specific body composition, touching on vanity, eating disorders, and self-acceptance. They advocate for letting a good physique be a natural byproduct of a healthy, performance-focused lifestyle.","entries":[{"text":"Host: And it's kind of funny, like, when you ask—if I ask someone, \"Okay, well why do you want to get in shape?\" \"Well, I want to have a six-pack.\" \"Well, why do you want to have a six-pack?\" \"Well, because I think it looks cool.\" \"Well, why do you think it looks cool?\" \"I don't know, because I think my wife will like me more.\" \"Why do you think your wife will like you more?\" \"Good question. Yeah. Maybe I'm afraid she's sleeping with the neighbor.\" \"Why do you think she's sleeping with the neighbor? Because I'm a d—.\"","offset":3120,"duration":27},{"text":"Host: You know what I mean, right? Like it's—it's—maybe that's not the exact situation, but it's kind of, it's like when you start asking these, okay, why are you actually doing this? Why are you actually doing this? And it's—asking those five or six layers of \"why\" someone's doing something to really understand like, okay, well here's, like you're mentioning, this is your driving force behind why you want to do something, so let's just hone in on that. So when you get down to it, it sounds like you actually just need to pressure release and you want to, uh, just feel healthy and feel good in your own skin. You don't necessarily want the six-pack per se, and maybe we need to kind of investigate that a little bit more so that you're not going to the gym destroying yourself. Volume, volume, volume, volume, volume to get shredded because that a, might happen with that quick ramp-up that you talk about, but then you're going to destroy yourself pretty damn quick and then you're going to be right back to square one trying to learn about, \"Okay, well now I want to get mobile because I've spent the last—\"","offset":3147,"duration":61},{"text":"Brian Mackenzie: Yeah, I mean—I mean, there are what—when I hear that, and it’s—it’s happening everywhere, um, I just think about the amount of men and women with eating disorders like that are just trying to look a specific way. Yep. And I say men because there are a lot of men who literally have eating—eating disorders um, and because they want to look a specific way because they don’t like who they are.","offset":3208,"duration":28},{"text":"Brian Mackenzie: Yep. And they don’t—they are not addressing the fundamental—that fundamental layer of why they don’t like who they are and because of the decisions they continue to make or that, you know, they’re insulating themselves around that whole vanity thing, right? Like if I just look the part or if I look like I fit in, I won’t have to be me. Yeah. Why wouldn’t you want to be you? Like, that’s all I—that’s all you should be.","offset":3236,"duration":31},{"text":"Host: Yeah. And it's like the guys that need to put on a certain amount of muscle or need to look a certain way, and I was certainly that way before, right? Because it almost is—makes it as though you don't have to—you can talk the talk without actually walking the walk. And when you ask yourself like, \"Well, did it actually take walking the walk to be able to talk this talk, or could I talk this talk without walking the walk?\" In other words, I think that a lot of people focus on the body composition piece because they're not really willing to look inside and see like why they actually want to focus on the body composition piece.","offset":3267,"duration":53},{"text":"Brian Mackenzie: Yeah, and I mean, you know—you’re not saying and I’m going to be perfectly clear—what I’m not—what I am not saying is that you can’t have that. You can have that. For sure. You can have the abs, you can have the muscle, you can have all that. However, let that be the byproduct of how you feel about yourself and what you’re willing to commit to. Yep. Right? And then watch how that—like I had—I had a guy who literally was like, \"These workouts, you keep sending me these workouts, that like they’re so confusing, but it’s like I’m not used to this. I’m just used to this, like, you know, bodybuilding type, you know, the like sets and reps and d-d-d.\" And I, you know, I like to mix things up a lot and um, you know, and I’m like, \"All right, I—I understand it can be a little confusing and, you know, look, you know, we’ll just—we just want to stick at this, we—you know, keep up with the walking, d-d-d.\"","offset":3320,"duration":59},{"text":"Brian Mackenzie: And like two months later he’s like, \"You know what’s funny?\" He goes, \"I was b—ing about all that and yet I get more compliments now about what I look like, and I cared more about what I looked like when I was doing the other s— that I was trying to look a specific way and now I actually look better and am getting compliments from people that I wasn’t expecting I was going to get.\" I’m like, \"See? See how that works?\"","offset":3379,"duration":30},{"text":"Host: Yeah. It's wild. I mean, you look at one way of—for me having to take a stop, reverse engineer a little bit and reorient my focus a little bit more. I think at the end of the day, all I ever wanted was the performance side of things and my body to perform the way I wanted it to perform with no arbitrary number. The way I wanted it to perform at that point in time, whether it was to go climb a mountain or to go for a—I'm like, okay, deep down it's always about performing. And the physical aspect was a way of me being able to look in the mirror, see a certain look, and tell myself that I'm performing even if I'm not performing because I have the physique of someone that's performing when in reality that was all just like an image, right? And then when focusing on performance—when I say performance, relative, not like some again, specific number—focusing on performance suddenly all of that falls in line effortlessly without the extra 90% of my energy focused on body composition just by focusing on the sole thing that I'm actually after when it comes down to my training.","offset":3409,"duration":62},{"text":"Host: And also being able to have the energy to give to my wife and give to my family and give to the things that I truly love and enjoy, which actually made training more about empowering and getting stronger and enjoying it versus constant punishment. Yeah. And it's amazing, especially when we talk about the eating disorders with guys, how much of them view their training subconsciously as a punishment versus something that they get to do and something that this amazing body gets to be able to do. And when you empower it like that and you treat it as such, it's amazing, amazing how much it changes.","offset":3471,"duration":79},{"text":"Brian Mackenzie: Oh, yeah. You nailed it on the head with that. I mean, that’s—that’s it. It’s—yeah. Um, people are not taking the time to look at why they’re doing what they’re doing and understanding that if it—if it’s for these, you know, attachment issues they’re not willing to look at and these material things, it’s going to come apart. Yeah. It will come apart. It might not be for 5, 10, 15, 20 years, but it’s going to. And it ain’t going to be pretty the longer it goes.","offset":3550,"duration":41},{"text":"Brian Mackenzie: And then it’s going to be so hard to unspool that that it’s, you know, it’s going to be this devastating—more of a devastating process. So it gets harder and harder as it goes. It’s still possible. And I see it. And—and it’s actually quite inspiring um, to see that. But I think people are looking far too much to be motivated into something. Yeah. Instead of just committed to the process, you know?","offset":3591,"duration":43}],"startTime":3120},{"title":"Embracing the Process and Finding Meaning","summary":"The conversation shifts to the philosophy of training, referencing Bruce Lee and the importance of committing to the process rather than illusionary goals. Breath is presented as the ultimate, undeniable feedback mechanism in life and training.","entries":[{"text":"Brian Mackenzie: And, you know, Bruce Lee is a very famous quote that, you know, all—all goals are an illusion apart—you know, apart from the—the means is apart from the means, right? And the means is the process. If what you’re doing ain’t about the process, you—you—you’re fooling yourself. We’re all lying to ourselves with this whole thing with—with meaninglessness. Like even I—I don’t kid myself right now with what it is I do. It’s—it’s quite literally meaningless.","offset":3634,"duration":40},{"text":"Brian Mackenzie: It—I exist in a world where we’re just all running around doing some bunch of meaningless crap.","offset":3674,"duration":7},{"text":"Host: Hedonic treadmill.","offset":3681,"duration":1},{"text":"Brian Mackenzie: Yeah. Yeah. To exist in a—like—so, but—but, that doesn’t mean stop doing it. It means why am I doing this thing? Am I passionate about it? Do I care about it? Great! Then that gives me ultimate power of being able to do something very, very creative and powerful with it. And it at the end of the day it’s not going to matter. Like what will matter is who—who I am and what I care about.","offset":3682,"duration":40},{"text":"Brian Mackenzie: And I think the people that you surround yourself with will be a reflection of that. And then it’s like, uh, coming back to this whole like, hey, what’s the lowest—you know, what are the things that we can look at? Like what—what is it like about CO2 tolerance? Why would I bring that up? And it’s like, well, this is just a gateway into understanding where all this—where you’re at, right? Like an—a door opening in order to bring it down a beat, to toggle that lever down and go, \"Oh, there’s an opportunity here.\" Not, \"Oh my god, this sucks.\" Like, you know, no.","offset":3722,"duration":60},{"text":"Brian Mackenzie: The—the process of understanding is lifelong. It will never end. It will not. And the thing with CO2 is it’s never ever ever ever ever going to lie to you. Because weights can even be—I used to say—I used to say like, \"50 pounds is always going to be 50 pounds, that’s the nice thing. Is like the weights will never lie to you.\" Except there’s so many ways to override your system to get through a workout or to push weight that although it is pretty solid at giving you feedback, it’s not as solid as breath. It’s not as solid as the need to breathe.","offset":3782,"duration":60},{"text":"Host: Because that is as—as fundamental and base level as it possibly gets because without that, you will die.","offset":3842,"duration":8},{"text":"Brian Mackenzie: Yeah. Well, you’re going to. I mean—you’re going to breathe. I mean, the—the reality is is you have to breathe and that’s one of the very few things you have to do. And you can try and stop yourself from doing that; it’s all right. There’s mechanisms in place that’ll take you out, that’ll shut you down, and the first thing that’ll happen when you go unconscious is you’ll start to breathe. And until this life’s over, you know, and then you’ll pass on and, you know, whatever.","offset":3850,"duration":41},{"text":"Brian Mackenzie: Um, if you’re not having fun while you’re doing this, you know, if you’re not into the—kind of the core of of why you’re training and the process of that, like it’s just going to be this hamster wheel of just psychoticness living inside of you.","offset":3891,"duration":21},{"text":"Host: It’s the—was the—you’ve heard of the gap theory of happiness?","offset":3912,"duration":3},{"text":"Brian Mackenzie: Yeah.","offset":3915,"duration":1},{"text":"Host: Yeah. And I don’t know how much, like, Seneca you’ve read or any—any stoic stuff—","offset":3916,"duration":5},{"text":"Brian Mackenzie: A little bit.","offset":3921,"duration":1},{"text":"Host: —but, you know, it’s kind of like the gap theory of happiness and, like, I—I think about this a lot when it comes to training. The gap theory of happiness essentially, like, we’re always living in that gap but between, like, the next thing that’s going to—","offset":3922,"duration":15}],"startTime":3634}],"entries":[{"text":"Host: Brian Mackenzie, what would you say the number one thing, if you had to—if you had to pick one, that is the biggest encumbrance to people being able to properly downregulate, maybe relieve some stress, consequently improve their performance?","offset":0,"duration":14},{"text":"Brian Mackenzie: At a physiological level, uh, it is a tolerance to CO2, which has to do with their nervous system. Um, so, you know, an interesting—I was just on a call with a friend of mine who’s writing a book on, um, walking, and she wanted to go over some stuff with the breathing, and she’s like, \"You know,\" and she’s a DPT, so she’s, you know, a doctorate in physical therapy, so she’s well educated inside the world of, um, you know, all of this stuff.","offset":14,"duration":40},{"text":"Brian Mackenzie: And she’s like, \"Are our normal respiration rates that the medical community says are 12 to 18 breaths a minute, is that normal?\" And I’m like, \"Well, it’s normal for the culture that we’re in.\" And I’m like, \"But I mean, my respiration rate’s around seven, and I don’t do a tremendous amount of breathwork. However, I’ve done enough and I apply the principles of this stuff into what it is I’m doing.\"","offset":54,"duration":37},{"text":"Brian Mackenzie: And that just, you know, that is alluding to the fact that most people are so, um, hot—running hot, or stressed, that their nervous system’s pretty, you know, fried. Or, and/or they’ve become so CO2 intolerant. So we respond to carbon dioxide—it’s the large—it’s a big, big, if not the biggest, player in driver for, um, breathing while we’re awake. Um, and it’s not the only one, but it’s one of the main ones.","offset":91,"duration":41},{"text":"Brian Mackenzie: And when we become sensitive to this, rightfully so, our breathing changes. The dynamics of our breathing change. Um, if our mouth is open, we instantly change our respiration rate, and that’s more to do with, um, baroreception, which is not chemoreception, which is where CO2 fits in—meaning pressure change. But, a lot of people are talking all day long, which is mouth breathing, so my respiration rate’s up.","offset":132,"duration":32},{"text":"Brian Mackenzie: A lot of people are very stressed; they just mouth breathe in general. So they go exercise and they’re not doing a whole lot, or they’re walking around and their mouth is open. Um, that all can move towards being, um, you’re offloading excessive CO2 at that point. So when you’re overbreathing, what we’re doing is you offload—you, you get rid of more CO2. You don’t bring on more O2.","offset":164,"duration":29},{"text":"Brian Mackenzie: In fact, you and I right now are—uh, we exhale roughly 80% of the oxygen that’s coming in. So we don’t need it, right? We don’t need all that oxygen because there’s enough—there’s plenty. It’s just only when exercise or movement goes up that that changes. So what happens is we change the dissociative curve of what’s going on with our breathing, and when we become a little less—uh, we’re not using oxygen as well and we still continue to get stressed, our breathing goes up.","offset":193,"duration":38},{"text":"Brian Mackenzie: And so we just kind of—the system self-adjusts and tries to balance itself out in what it does. And part of that process is that our breathing changes. The dynamics of our breathing change, and it just gets easier to breathe like that versus taking, you know—and you don’t need to be taking a full inhale while we’re sitting here. You know, you’re breathing perfectly fine as we’re sitting here.","offset":231,"duration":31},{"text":"Brian Mackenzie: But the vast majority of people are not.","offset":262,"duration":3},{"text":"Host: While I’m at it, one of the things that I do like about Thrive Market, which I talk about all the time on my channel—and I know you’re thinking, \"Oh, here comes the plug.\" Well, you’re right. Is that Thrive Market doesn’t have a bunch of stuff that has weird added ingredients into it. Like, they adopt a lot of what, sort of, the EU puts into place for their processed foods. So, like, packaged foods at Thrive Market don’t have weird additives, there’s no red dyes and crazy stuff.","offset":265,"duration":36},{"text":"Host: So, at least even if some of the stuff is processed, like maybe some pantry staples and stuff like that, it’s the way that it should be. Processed because you’re processing it, not because you’re adulterating it and turning it into some hyper-palatable nonsense. So, that link that I put down below is for a 30% off discount link for anything from Thrive Market. So when you go ahead and you use Thrive Market, you get 30% off your entire grocery order when you use that link that’s down below.","offset":301,"duration":38},{"text":"Host: They also have frozen meat and seafood options. They’re starting to roll out fresh options for some people; you might not see it reflected on your account or not. But bottom line is, they’ve got really good stuff, and they’ve got canned fish, so they’ve got the tuna, they’ve got Wild Planet sardines and anchovies—I mean, all that stuff if you’re into that and you’re trying to live more Mediterranean.","offset":339,"duration":27},{"text":"Host: But some of the things that I love the most are just being able to get healthier snack options for my kids because I don’t want to just go to regular Vons or Safeway here in California and get something that has a load of garbage and MSG and stuff in it. If I’m going to get them a snack, I want something that I feel like, I don’t know, I don’t feel bad about giving them. So that’s the whole idea behind Thrive Market is being able to bring healthier options to the consumer at a decent price, right?","offset":366,"duration":34},{"text":"Host: So that link down below gets you 30% off plus a free gift. I really do recommend that you check them out. Check them out; they’ve been a sponsor on this channel for over half a decade, and I wouldn’t be recommending them if it wasn’t something that I honestly used myself. So that link is in the top line of the description.","offset":400,"duration":17},{"text":"Brian Mackenzie: And so that overbreathing thing, the 12 to 18 breaths a minute—a lot of that’s done on data that’s being collected from something called respiratory sinus arrhythmia, which isn’t exactly the most effective way, or the algorithms off of a lot of the technologies that are on the periphery, which is not very accurate in terms of understanding a respiration rate. So, meaning like if you’re wearing an Oura or a Whoop, your respiration rate is probably not what that is telling you.","offset":417,"duration":44},{"text":"Brian Mackenzie: Um, there’s a good chance it’s not. Um, that said, the data with those things is also—but not also, the data with those sort of things are consistent. Meaning, if there’s a change, there’s a change inside that. So they can, you know, they might be inaccurate, they’re just consistently inaccurate, which is—which is a good thing. Um, and they’re different.","offset":461,"duration":33},{"text":"Brian Mackenzie: But if you—you would want to, if you really wanted to understand respiration rate, since I talked about it, since I brought this up, it’s—you, you would get that—you, you would get something, a strap or something that would actually measure, like, as your ribcage begins to move, the, you know, the depth of that. Or you get on a resting metabolic—you, you do a resting metabolic test assessment, and that’ll actually capture your breathing rate, um, and what’s going on.","offset":494,"duration":46},{"text":"Brian Mackenzie: And that’s not the be-all end-all here. What is, is that, well, with people who have dysfunctional breath—and that is, by the way, dysfunctional breathing, any—in my opinion, anything above 15 breaths a minute is dysfunctional. Um, you, you have a massive gap in how your physiology’s going to operate, and we can—we can make major changes very quickly. And that would be through things like going for a walk and shutting your mouth, or doing a little breathwork and slowing down your breathing to a degree, or doing some breath hold work, um, that actually helped us increase the CO2 in the system so that we actually were using the oxygen a bit more.","offset":540,"duration":64},{"text":"Brian Mackenzie: And it’s not just about the oxygen. That CO2—oxygen’s a worthless, destructive molecule without carbon dioxide inside of this system. Um, in fact, it’s largely a destructive—oxygen is very destructive itself, far more destructive than CO2. Um, it’s just how that CO2 is getting used, right? Um, and if I don’t have enough of it in the system, the vasculature constricts more, right?","offset":604,"duration":44},{"text":"Brian Mackenzie: So if I have more of it in the system, the vasculature opens up, we vasidilate. So we—we—we start to—to train the system as a whole when we actually bring on an adequate amount of that. So I think, you know, to answer your question, CO2 tolerance becomes a very big player in some of the lowest-hanging fruit that people could actually go and understand, and that is simply by just slowing down your breathing a few times a day, maybe.","offset":648,"duration":39},{"text":"Brian Mackenzie: Doing some breathing protocols that you like, maybe not doing some hyperventilation stuff if you’ve got any issues going on just until you’ve addressed this stuff. Um, and then applying this into your current, you know, movement strategy. Like go for a walk, you know, 20, 30, 45 minutes and shut your mouth and see how you feel after that. And there’ll be a very big difference if it’s the first time you’ve really done something like that.","offset":687,"duration":39},{"text":"Host: What is—what’s happening in the brain when CO2 builds?","offset":726,"duration":4},{"text":"Brian Mackenzie: That’s a good question. So, um, a—a very—a good friend of mine, his name’s Dr. Justin Feinstein, did some work around, uh, studying the amygdala. He—uh, he—uh, he originally was doing research around, like, float tank therapy, stuff like that, and people get downregulating, but he—he got curious about this breathing thing. Um, and he ended up studying two sets of twins that had calcified amygdalas, and he was studying people that had anxiety, um, high levels, medical—like medically treated people with anxiety, okay?","offset":730,"duration":67},{"text":"Brian Mackenzie: Um, and if you have a calcified amygdala, you’re pretty much—you are a danger to yourself. Um, you don’t interpret fear as well, right? So you’ll put your hand, like, on a stove and not think about that, right? Like it’s—it’s just not something that kind of equates, you know, um. You—you—you just become a little bit of a danger to yourself, right? Um, and he was exposing people with anxiety to bolus hits of carbon dioxide.","offset":797,"duration":57},{"text":"Brian Mackenzie: And if—he inevitably ended up exposing these two sets of twins to, um, CO2 as well. And the twins had some of the most profound fear that they had ever experienced ever in their lives when exposed to the CO2. And it turns out the amygdala, even though it’s part of the limbic system and has this kind of, like, fear center in it, it also is a modulator of CO2, carbon dioxide.","offset":854,"duration":56},{"text":"Brian Mackenzie: And when my nervous system—when I’m hot, like if I’m—if I’m upset or I’ve, you know, I’m—I’ve been doing way too much, you know, I worked out a ton, like and in—and I need to recover, you know, I’ve been multiple days and I’ve been training, you know, I get—your nervous system gets a bit fried. You—you will notice that you are more reactive. All of that plays into how CO2 is actually operating as well.","offset":910,"duration":53},{"text":"Brian Mackenzie: My nervous system can be running hot, and you can bet your tolerance to CO2 has gone down, meaning you are much more sensitive to that. So the chemoreceptors and everything that’s going on in that brain is now more sensitive to this stuff. However, if I can bring it down enough and I can expose myself to an adequate amount of CO2—let’s just go back into, let’s go back in time, when people used to have panic attacks, what would they do, let’s just say in the 70s and 80s, if somebody was having a panic attack?","offset":963,"duration":58},{"text":"Host: Stop and breathe?","offset":1021,"duration":3},{"text":"Brian Mackenzie: They’d hand them a paper bag and tell them to breathe into the paper bag.","offset":1024,"duration":5},{"text":"Host: Oh, that's true.","offset":1029,"duration":2},{"text":"Brian Mackenzie: Why would they have somebody do that? CO2. Turns out that you can slow things down and calm down a bit more when you add a bit more CO2 into the system. Um, this isn’t necessarily, like, hey, go—go out and buy CO2 tanks and start, you know, huffing CO2. You know, this is like, hey, what’s going on here? What could I toggle or introduce into what I’m doing in order to learn more about why I’m a little sensitive to this?","offset":1031,"duration":57},{"text":"Brian Mackenzie: You know, um, it’s—it’s interesting. We’ve—uh, at—at Andy Galpin’s old lab, one of his, uh, students, uh, Preston did a—did a—his thesis on a lot of this on some of this stuff where we’re doing an exhale assess—we do this exhale test where it’s a max exhale. Um, you, you know, inhale and then you exhale as long and slow—the redundancy of that is—as—as possible, right? And he found out that—I’ve been using this assessment for years now, um, and I—I figured this out, but we wanted him to—we wanted somebody else to kind of play with this as well.","offset":1088,"duration":67},{"text":"Brian Mackenzie: And he found out that the athletes he was testing, those who had a low CO2 tolerance score, so a low exhale assessment, had a—had more anxiety, and that was very much indicative of that. Their state anxiety was predictable by this score, by this test. So I can basically—and that doesn’t mean I’m diagnosing you with anxiety, by the way. That is—that just means from a nervous system standpoint, anxiety sits on the nervous system. Like, anxiousness is a point where you’re beyond, like, it’s a nervous system response.","offset":1155,"duration":64},{"text":"Brian Mackenzie: Um, so it’s not every day you’re going to be dealing with this, but you can bet that if you learn to stop overshooting the mark and getting anxious or taking on or worrying too much, you, you know, when you’re in those moments, you’re going to find out if you do an exhale or you try and hold your breath like or test this, like, you—it’s going to be real low. When you get a hold of that and you can remain calm, it’s going to go up.","offset":1219,"duration":52},{"text":"Brian Mackenzie: Um, but this is a very trainable thing to a degree that, like, you know, the vast majority of people as a, you know, just kind of a—a blanket statement here, like the vast majority of people if I had them hold their breath aren’t going to hold their breath much longer than 90 seconds, right? CO2 tolerance plays—CO2 tolerance plays a very big role in your ability to hold your breath, right? Part of that is your ability to deal with the pain and the panic that’s starting to shoot up and go off.","offset":1271,"duration":53},{"text":"Brian Mackenzie: But large majority of that is an adaptive process to this and being able to tolerate more CO2 in the system and get—getting used to that. So the vast majority of people hold their breath for 90 seconds, yet there are human beings holding their breath for seven minutes, no problem. So that’s a large gap, right? And I’m not suggestive that anybody go out and learn to hold their breath for seven minutes, but it could be a cool fun time to go do that.","offset":1324,"duration":46},{"text":"Brian Mackenzie: But at any rate, you get that breath hold up to two, three, maybe four minutes? I—I can—you can bet you’re going to be a calmer, less reactive person. 100%.","offset":1370,"duration":17},{"text":"Host: What’s the—benefit to doing a hold on full versus a hold on empty?","offset":1387,"duration":6},{"text":"Brian Mackenzie: The hold on f—I mean, a—a number of things. Um, you know, within like the yogic world, they’ve—they’ve long started with things with on an exhale hold. Um, I’ve found that the inhale hold is a lot easier to work with people um, just because it allows for you an off switch—like let go. So if I’m holding up top, it’s [exhales] right, to let go versus [inhales sharply]. Right, um, the inhale is typically, um, the problem for people in my—a lot of my work.","offset":1393,"duration":97},{"text":"Brian Mackenzie: So, meaning, people inhale rather quickly versus the ability to inhale slowly, right? And then there are those of us that, you know, will struggle a bit with an exhale. But that’s largely a CO2 tolerance thing. Um, so the inhale hold is more of a pressure thing. You’re going to see blood pressure, you’re going to see pressure changes as a result of that. People who struggle with bring the—with bringing their parasympathetic nervous system on board—so high-stress people—are going they—they might have some issues with the inhale breath hold, meaning they’ll get—they’ll get woozy real quick.","offset":1490,"duration":66},{"text":"Brian Mackenzie: Um, they’ll—um, you know, it—there—there will be a disconnect from the heart to the brain as a result of that because of the pressure changes. Um, but I don’t work to do like maximal like stuff the lung type of stuff and, you know, a lot of this stuff with inhale breath holds, what I have people do is simply to first and like strong urge to breathe, not panic urge to breathe. Um, those seem to have the biggest impacts with people.","offset":1556,"duration":60},{"text":"Brian Mackenzie: So just repeating, like, an on the minute. Like, hey, I’m going to breathe for a minute or two and then I’m going to hold my breath until a strong urge to breathe and doing that for five or six sets is a very, very big downregulating, um, tool. Now, if somebody’s tuned up that’s pretty anxious, that may not be the thing to do. Um, it may be go the other way to the negative—is you’re working with dead space mostly.","offset":1616,"duration":54},{"text":"Brian Mackenzie: Now, there’s still some air in there in the lungs on an exhale, but you got to be pretty, pretty damn tuned in like a Mark Healey or like a, you know, yogi from India to get all that air out of your lungs. Um, you know, other than that, you know, let’s just say we just [exhales] and I hold. There’s not as much of a—of a blood pressure change that’s occurring; there’s more of a—we’re kind of working on the immediacy of CO2’s response to the system.","offset":1670,"duration":54},{"text":"Brian Mackenzie: So you’re going to actually work more on the psyche with a negative breath hold in my opinion, because people aren’t—I mean, if people right now were to go and go ahead and dump all the air you’ve got and hold your breath, see how quickly panic comes on. Now, relax after you heard that and did that, take a few breaths, and then go do it with an inhale. You’re not going to panic as quick.","offset":1724,"duration":37},{"text":"Brian Mackenzie: Yeah. It’s just not going to happen. So I kind of look at it in terms of, you know, working more on the mental with the negative and working more on the physiological with the positive. However, there are definitely, you know, there’s—some differ—there’s some differences but there’s also much crossover. You hold your breath enough on either end with very few breaths, you’re going to get hypoxic. Um, you’ll—introduce hypoxia, but most people will never reach that point because they’re so CO2—I wouldn’t say so, but they’re CO2 intolerant enough to where CO2 is convincing them to take a breath well before oxygen is going lights out.","offset":1761,"duration":47},{"text":"Host: Is there a—is there a metabolic interplay here as well, like the—of the mitochondria’s ability to kind of function in this hypoxic state?","offset":1808,"duration":9},{"text":"Brian Mackenzie: Yes. Yeah. The beauty of this, and there’s a great paper out there, uh—I forget what it—I—I’m paraphrasing, but it—I think it’s called \"The Tortoise and the Hare\". There’s an actual paper, um, where these guys in Sweden, I believe it was Sweden, they studied, um, two of the people who were at the university were at the time—one was an elite triathlete and one was an elite freediver.","offset":1817,"duration":57},{"text":"Brian Mackenzie: And they were both competing that year and they wanted to test, well, what’s the difference between mitochondria and the aerobic function of these? And one would have suspected and been correct that the triathlete who’s at an elite level has far greater what we would assume metabolic health and the ability to function aerobically at higher states. Correct. There’s the—the one major caveat here, and this is where hypoxia becomes a very, very potent tool.","offset":1874,"duration":44},{"text":"Brian Mackenzie: Um, and there’s much more to hypoxia that we could go into a rabbit hole on. However, um, the breath holding and learning to hold one’s breath and get to hypoxia in particular they found that the freediver is able to use less oxygen with more—for more ATP.","offset":1918,"duration":40},{"text":"Host: Hmm.","offset":1958,"duration":2},{"text":"Brian Mackenzie: So, they are far more efficient on that end of energy—getting energy off of that electron transport chain than the aerobically inclined athlete. Now, I wouldn’t suggest that, um, you do one of the other; I would suggest you do both.","offset":1960,"duration":34},{"text":"Host: Yeah. What about concurrently? I mean, what about literally—this might be more advanced so I mean, disclosure there, but someone that is, um, you know, maybe doing Zone 2, maybe they’re doing their base training—is there some form of benefit to doing occasional holds while actually training?","offset":1994,"duration":24},{"text":"Brian Mackenzie: Oh, I—yes. I—I have people do this all—yeah. This is part of training regiment like 101 with me. It’s just like, yeah, hey, we’re going to be doing this, you’re also doing this. Like, we’re—we’re targeting these things in many aspects, like most of my clients—","offset":2018,"duration":17},{"text":"Host: So they’re, like, holding their breath while you’re running, kind of?","offset":2035,"duration":1},{"text":"Brian Mackenzie: Yeah, most of my clients don’t just do strength and conditioning and endurance work; they do strength conditioning, endurance work, breath hold work, etc. Like, they’re getting the whole—but, it’s a lot, you know, if I were to start dumping out everything we do, it’s—you know, heat training, cold training, like all of—where’s the time for—well, that’s the thing is the art is in, hey, what—what’s this person’s schedule look like? Where can we insert these things so that they’re actually effective? Because if they’re not—if we can’t, there’s no sense. Like why would we implement this? Like, you know, breath hold is just a very simple thing to implement for anybody.","offset":2036,"duration":59},{"text":"Host: If you were to say—I mean this is a hypothetical situation where you’re going to, you know, hop on an assault bike, let’s say, do a 20-calorie hit on an assault bike and then hop off—is there a benefit at an advanced level to attempting a—a hold during your recovery there?","offset":2095,"duration":15},{"text":"Brian Mackenzie: Oh yeah, no. No, there’s research that support—well, I—I would go about it, um, in a way of, like—go—do—do a sprint, short sprint, right? Warmed up, going into some sprints. Like, I—what I like—here’s what I like to do, um, is like five minutes very, very—every five minutes you’re hitting anywhere from 6 to 15 seconds, right? Hard. And you could definitely go out to 90 seconds or three minutes if you want for intervals, but by all means hold your breath on the last six seconds.","offset":2110,"duration":56},{"text":"Brian Mackenzie: Just hold it. Just lock it down. You’ll be able to get through it. Um, hold it and then you’ll start to see you can end up holding it a little bit longer and a little bit longer. That has very big impacts with stuff like this. You may not get—you’re not going to really get hypoxic from stuff like this, like what I was bringing up with the \"The Tortoise and the Hare\". What you’re going to do is you’re going to—you’re going to start getting probably some boosts in EPO and some red blood cell responses short-term, and then long-term you’re going to get some—some of that stuff that’ll hold on.","offset":2166,"duration":52},{"text":"Brian Mackenzie: Um, it’s not going to be something I think that I would use for hyp—you know, going to altitude, but it will help for sure—for—100% it will help. Um, it’s not going to be the thing that, you know, you would want to be doing for altitude exposure, though.","offset":2218,"duration":27},{"text":"Host: If we pivot for a second to talk, you know, nasal versus mouth?","offset":2245,"duration":4},{"text":"Brian Mackenzie: Yeah.","offset":2249,"duration":1},{"text":"Host: I think one of the things that I’ve personally—I’ll just use my own experience here is—um, my ability to inhale through the nose through activity is fine. It’s exhalation through the nose that, um, becomes almost restricted; it’s just harder. It’s just, like, takes more time and by the time all the air is out of my nose, I’m hypox—it’s like I’m, you know, it’s taking so long for the air to physically come out of my nose that then I’m almost going into oxygen debt, right? So—or what feels like it. So then it’s like then you’re almost going into—","offset":2250,"duration":49},{"text":"Brian Mackenzie: Yeah, it's just CO2. That's the carbon dioxide screaming at you there.","offset":2299,"duration":10},{"text":"Host: So it's—is there—I'm sure there's different modalities, but if you're working on quote-unquote \"nasal breathing\", is it okay to exhale through the mouth during activity? So inhale nose, exhale mouth, or is that a completely different response than if you also exhale through the nose?","offset":2309,"duration":23},{"text":"Brian Mackenzie: Well, if you’re going to—if—so, nose breathing we know is parasympathetic—has more parasympathetic tone. It’s that exhale that’s the most important part of that.","offset":2332,"duration":14},{"text":"Host: Okay.","offset":2346,"duration":2},{"text":"Brian Mackenzie: Here’s why. Anything below moderate levels of exercise, I’m getting the same amount of oxygen in. I do not need to switch over until beyond moderate levels of exercise to [panting] to onboard more oxygen. Okay. It’s the CO2 coming out that is really the player in this game to where [exhales through nose] versus [panting].","offset":2348,"duration":63},{"text":"Brian Mackenzie: Yeah, I just dumped all that CO2. So that in—and so now we start to mess with that dissociative curve that I was kind of talking about, right? Um, and not in all cases, but most cases, like if you’re—if—if you have to mouth breathe at less than moderate levels of exercise, I—you can bet you’re—you’re messing with, uh, aerobic stuff. Yeah, mm-hmm. Maybe not a ton, but enough. And if that’s your goal, then—and that would be my goal if I was somebody who was exercising.","offset":2411,"duration":53},{"text":"Brian Mackenzie: Um, I’d use high intensity for high intensity and we get into mouth breathing plenty. I see many, many people who are glued to the concept of nose breathing till the end. Like, it’s just they nose breathe even at high intensity. Um, and you are doing the exact same thing but in an opposite way of overbreathing now. You are literally not able to use oxygen the way it was used in your system’s getting more acidic than it actually needs to.","offset":2464,"duration":47},{"text":"Brian Mackenzie: So, pH is changing, hydrogen’s not getting dealt with as well. All the—you know, all of this stuff—is—I’ve seen the crossovers in—on the metabolic stuff, you know, where people are limiting themselves. And they lack the ability to sustain higher respiration rates at higher intensities.","offset":2511,"duration":49},{"text":"Host: Do you, with your training in that case, are you—do you have a pretty clear line of delineation between \"hey, here's—here's my aerobic stuff and here's my high intensity stuff\"? Like not sitting in that kind of—there's some people out there that'll believe that, like, if you train within that gray area, sort of, you know, lactate threshold area, that's like really a sweet spot where you're—and then there's others that are saying like, \"Hey, no, we've got a very clear—it's a very clear line of delineation where we don't sit in that gray area, we either go extreme high intensity or we go lower intensity, and the magic ends up naturally happening by training those two systems.\" I'm just curious your take on that.","offset":2560,"duration":36},{"text":"Brian Mackenzie: Uh, no. I don’t think any manmade thought on how my body should respond to things should be limited. That doesn’t mean—and—and I’m very, very, very careful to watch what it is I, in particular, inevitably get enamored with. I’ve been enamored with low intensity. I’ve been enamored with high intensity.","offset":2596,"duration":46},{"text":"Host: Yeah.","offset":2642,"duration":1},{"text":"Brian Mackenzie: And—and I’ve done moderate intensity. Um, you know, I’ve been enamored with that as well. Um, it all plays a critical role. Um, I don’t consider like walking low intensity. No. I consider that the buy-in for you and anybody to manage, uh, any and all activity. Um, you know, that doesn’t mean like I’ve got, you know, like I wouldn’t ask an NFLer to be walking 90 minutes a day because they’re probably at practice and they’re probably getting 10,000 steps in a day anyway.","offset":2643,"duration":53},{"text":"Brian Mackenzie: So like, you know, I just want them to do like 15, 20 minutes in the morning or something just to clear, you know—get lactate levels down, get cortisol levels down, um, in the morning so that we’re kind of stabilized and ready to go. Um, but, yeah. I—I think the full spectrum, however, I’m very careful to—I would say look—80% of what you’re doing, if you’re—your mouth should be shut.","offset":2696,"duration":51},{"text":"Brian Mackenzie: But you had—you would be best being mouth open several times a week for very short periods of time.","offset":2747,"duration":10},{"text":"Host: Yeah. And I think being able to—how do you suggest that someone that maybe isn’t as in tune with their body be able to regulate and understand, like, when they need to throttle down their training versus throttle it up? Because I have found that that is a very confusing place for most people, and it’s on both ends of the spectrum, whether it’s an extreme or an elite athlete versus someone that’s a newbie. It’s very difficult to really ascertain, like, okay, when is it time to throttle down? When am I doing—like when your sort of allostatic load is so high already, like do you throttle down your training or do you try to increase your training to deal with it? Like, what’s—how does someone kind of regulate that? What would you suggest to someone?","offset":2757,"duration":50},{"text":"Brian Mackenzie: Uh, I mean it’s a great question. Um, I—people really need to spend time learning what adaptation looks like with one thing at a time. Um, so, you know, like I brought up the walking thing before with you, right? Like I get people to walk. I want you to just implement that right now. And then, you know, whatever else you’re doing, just keep doing that, but we’re walking.","offset":2807,"duration":46},{"text":"Brian Mackenzie: You’re going to find out if you can do the other stuff if you’ve added in walk—you know, 45 minutes to 90 minutes of walking a day, right? Like you will find out if you can continue to have that stuff. Then it’s like, okay, well what’s the goal? You know, I just—I was talking to a buddy of mine who’s down in Australia, um, last week. And I hadn’t seen him in a—in a number of months, um, and we do video chat. And—um, he—it came on and I was like, \"Whoa, somebody put on some weight.\"","offset":2853,"duration":49},{"text":"Brian Mackenzie: And not—not fat. He definitely put on muscle. Like I was like, \"Damn!\" And he’s like, \"Yeah.\" He goes, \"It’s interesting, I’m only lifting three days a week.\" And he goes, you know—and he’s 35. And he’s like, \"You know what’s interesting is—is that I’m lifting far less than I did when I was in my 20s and I’m putting on more muscle now than I was then.\" Am I getting that interesting? Like, how many of us think we just need to go do more, more, more, more and literally aren’t miss—are missing adaptive processes because we’re just continuing to add in a stressor, be it weightlifting, right, as the example.","offset":2902,"duration":71},{"text":"Brian Mackenzie: Like I know a lot of people who train six days a week, right, and continue to do it. And there’s a—there’s a sharp ramp up at first with that, and then it just [gestures] peters out and does its thing. And then it’s real hard to make gains. Um, you know, versus like, hey, how about three days a week of that? You know, um, what happens with that? Are people willing to toggle or screw around with things to learn where that—where that is?","offset":2973,"duration":42},{"text":"Brian Mackenzie: What can you get away with? What is still creating the gains that you want? What do you want? All right, well let’s put one thing down first. Let’s go after that thing and let’s screw around to find out where that sweet spot is with this. And the reality is, is that’s what life’s about. Being able to creatively figure out what works and what doesn’t so that you’re doing the things you want versus not doing the things you’re not—you don’t want to be doing.","offset":3015,"duration":57},{"text":"Brian Mackenzie: Like, I’m continuing to work out all the time and do all this stuff that—because I’m doing everything. I’m doing the ice bath, I’m doing the sauna, I’m doing the hyperbaric chamber, I’m doing the hypoxico, I’m doing strength and conditioning. Like, dude, like I get it, because I do all that stuff. However, it all comes in little segments. Like it’s not all going on at the same time. There’s, you know, it’s all adjusted because I’ve been at it for like 25 years and I know when—you can’t do it all at the same time.","offset":3072,"duration":48},{"text":"Host: And it's kind of funny, like, when you ask—if I ask someone, \"Okay, well why do you want to get in shape?\" \"Well, I want to have a six-pack.\" \"Well, why do you want to have a six-pack?\" \"Well, because I think it looks cool.\" \"Well, why do you think it looks cool?\" \"I don't know, because I think my wife will like me more.\" \"Why do you think your wife will like you more?\" \"Good question. Yeah. Maybe I'm afraid she's sleeping with the neighbor.\" \"Why do you think she's sleeping with the neighbor? Because I'm a d—.\"","offset":3120,"duration":27},{"text":"Host: You know what I mean, right? Like it's—it's—maybe that's not the exact situation, but it's kind of, it's like when you start asking these, okay, why are you actually doing this? Why are you actually doing this? And it's—asking those five or six layers of \"why\" someone's doing something to really understand like, okay, well here's, like you're mentioning, this is your driving force behind why you want to do something, so let's just hone in on that. So when you get down to it, it sounds like you actually just need to pressure release and you want to, uh, just feel healthy and feel good in your own skin. You don't necessarily want the six-pack per se, and maybe we need to kind of investigate that a little bit more so that you're not going to the gym destroying yourself. Volume, volume, volume, volume, volume to get shredded because that a, might happen with that quick ramp-up that you talk about, but then you're going to destroy yourself pretty damn quick and then you're going to be right back to square one trying to learn about, \"Okay, well now I want to get mobile because I've spent the last—\"","offset":3147,"duration":61},{"text":"Brian Mackenzie: Yeah, I mean—I mean, there are what—when I hear that, and it’s—it’s happening everywhere, um, I just think about the amount of men and women with eating disorders like that are just trying to look a specific way. Yep. And I say men because there are a lot of men who literally have eating—eating disorders um, and because they want to look a specific way because they don’t like who they are.","offset":3208,"duration":28},{"text":"Brian Mackenzie: Yep. And they don’t—they are not addressing the fundamental—that fundamental layer of why they don’t like who they are and because of the decisions they continue to make or that, you know, they’re insulating themselves around that whole vanity thing, right? Like if I just look the part or if I look like I fit in, I won’t have to be me. Yeah. Why wouldn’t you want to be you? Like, that’s all I—that’s all you should be.","offset":3236,"duration":31},{"text":"Host: Yeah. And it's like the guys that need to put on a certain amount of muscle or need to look a certain way, and I was certainly that way before, right? Because it almost is—makes it as though you don't have to—you can talk the talk without actually walking the walk. And when you ask yourself like, \"Well, did it actually take walking the walk to be able to talk this talk, or could I talk this talk without walking the walk?\" In other words, I think that a lot of people focus on the body composition piece because they're not really willing to look inside and see like why they actually want to focus on the body composition piece.","offset":3267,"duration":53},{"text":"Brian Mackenzie: Yeah, and I mean, you know—you’re not saying and I’m going to be perfectly clear—what I’m not—what I am not saying is that you can’t have that. You can have that. For sure. You can have the abs, you can have the muscle, you can have all that. However, let that be the byproduct of how you feel about yourself and what you’re willing to commit to. Yep. Right? And then watch how that—like I had—I had a guy who literally was like, \"These workouts, you keep sending me these workouts, that like they’re so confusing, but it’s like I’m not used to this. I’m just used to this, like, you know, bodybuilding type, you know, the like sets and reps and d-d-d.\" And I, you know, I like to mix things up a lot and um, you know, and I’m like, \"All right, I—I understand it can be a little confusing and, you know, look, you know, we’ll just—we just want to stick at this, we—you know, keep up with the walking, d-d-d.\"","offset":3320,"duration":59},{"text":"Brian Mackenzie: And like two months later he’s like, \"You know what’s funny?\" He goes, \"I was b—ing about all that and yet I get more compliments now about what I look like, and I cared more about what I looked like when I was doing the other s— that I was trying to look a specific way and now I actually look better and am getting compliments from people that I wasn’t expecting I was going to get.\" I’m like, \"See? See how that works?\"","offset":3379,"duration":30},{"text":"Host: Yeah. It's wild. I mean, you look at one way of—for me having to take a stop, reverse engineer a little bit and reorient my focus a little bit more. I think at the end of the day, all I ever wanted was the performance side of things and my body to perform the way I wanted it to perform with no arbitrary number. The way I wanted it to perform at that point in time, whether it was to go climb a mountain or to go for a—I'm like, okay, deep down it's always about performing. And the physical aspect was a way of me being able to look in the mirror, see a certain look, and tell myself that I'm performing even if I'm not performing because I have the physique of someone that's performing when in reality that was all just like an image, right? And then when focusing on performance—when I say performance, relative, not like some again, specific number—focusing on performance suddenly all of that falls in line effortlessly without the extra 90% of my energy focused on body composition just by focusing on the sole thing that I'm actually after when it comes down to my training.","offset":3409,"duration":62},{"text":"Host: And also being able to have the energy to give to my wife and give to my family and give to the things that I truly love and enjoy, which actually made training more about empowering and getting stronger and enjoying it versus constant punishment. Yeah. And it's amazing, especially when we talk about the eating disorders with guys, how much of them view their training subconsciously as a punishment versus something that they get to do and something that this amazing body gets to be able to do. And when you empower it like that and you treat it as such, it's amazing, amazing how much it changes.","offset":3471,"duration":79},{"text":"Brian Mackenzie: Oh, yeah. You nailed it on the head with that. I mean, that’s—that’s it. It’s—yeah. Um, people are not taking the time to look at why they’re doing what they’re doing and understanding that if it—if it’s for these, you know, attachment issues they’re not willing to look at and these material things, it’s going to come apart. Yeah. It will come apart. It might not be for 5, 10, 15, 20 years, but it’s going to. And it ain’t going to be pretty the longer it goes.","offset":3550,"duration":41},{"text":"Brian Mackenzie: And then it’s going to be so hard to unspool that that it’s, you know, it’s going to be this devastating—more of a devastating process. So it gets harder and harder as it goes. It’s still possible. And I see it. And—and it’s actually quite inspiring um, to see that. But I think people are looking far too much to be motivated into something. Yeah. Instead of just committed to the process, you know?","offset":3591,"duration":43},{"text":"Brian Mackenzie: And, you know, Bruce Lee is a very famous quote that, you know, all—all goals are an illusion apart—you know, apart from the—the means is apart from the means, right? And the means is the process. If what you’re doing ain’t about the process, you—you—you’re fooling yourself. We’re all lying to ourselves with this whole thing with—with meaninglessness. Like even I—I don’t kid myself right now with what it is I do. It’s—it’s quite literally meaningless.","offset":3634,"duration":40},{"text":"Brian Mackenzie: It—I exist in a world where we’re just all running around doing some bunch of meaningless crap.","offset":3674,"duration":7},{"text":"Host: Hedonic treadmill.","offset":3681,"duration":1},{"text":"Brian Mackenzie: Yeah. Yeah. To exist in a—like—so, but—but, that doesn’t mean stop doing it. It means why am I doing this thing? Am I passionate about it? Do I care about it? Great! Then that gives me ultimate power of being able to do something very, very creative and powerful with it. And it at the end of the day it’s not going to matter. Like what will matter is who—who I am and what I care about.","offset":3682,"duration":40},{"text":"Brian Mackenzie: And I think the people that you surround yourself with will be a reflection of that. And then it’s like, uh, coming back to this whole like, hey, what’s the lowest—you know, what are the things that we can look at? Like what—what is it like about CO2 tolerance? Why would I bring that up? And it’s like, well, this is just a gateway into understanding where all this—where you’re at, right? Like an—a door opening in order to bring it down a beat, to toggle that lever down and go, \"Oh, there’s an opportunity here.\" Not, \"Oh my god, this sucks.\" Like, you know, no.","offset":3722,"duration":60},{"text":"Brian Mackenzie: The—the process of understanding is lifelong. It will never end. It will not. And the thing with CO2 is it’s never ever ever ever ever going to lie to you. Because weights can even be—I used to say—I used to say like, \"50 pounds is always going to be 50 pounds, that’s the nice thing. Is like the weights will never lie to you.\" Except there’s so many ways to override your system to get through a workout or to push weight that although it is pretty solid at giving you feedback, it’s not as solid as breath. It’s not as solid as the need to breathe.","offset":3782,"duration":60},{"text":"Host: Because that is as—as fundamental and base level as it possibly gets because without that, you will die.","offset":3842,"duration":8},{"text":"Brian Mackenzie: Yeah. Well, you’re going to. I mean—you’re going to breathe. I mean, the—the reality is is you have to breathe and that’s one of the very few things you have to do. And you can try and stop yourself from doing that; it’s all right. There’s mechanisms in place that’ll take you out, that’ll shut you down, and the first thing that’ll happen when you go unconscious is you’ll start to breathe. And until this life’s over, you know, and then you’ll pass on and, you know, whatever.","offset":3850,"duration":41},{"text":"Brian Mackenzie: Um, if you’re not having fun while you’re doing this, you know, if you’re not into the—kind of the core of of why you’re training and the process of that, like it’s just going to be this hamster wheel of just psychoticness living inside of you.","offset":3891,"duration":21},{"text":"Host: It’s the—was the—you’ve heard of the gap theory of happiness?","offset":3912,"duration":3},{"text":"Brian Mackenzie: Yeah.","offset":3915,"duration":1},{"text":"Host: Yeah. And I don’t know how much, like, Seneca you’ve read or any—any stoic stuff—","offset":3916,"duration":5},{"text":"Brian Mackenzie: A little bit.","offset":3921,"duration":1},{"text":"Host: —but, you know, it’s kind of like the gap theory of happiness and, like, I—I think about this a lot when it comes to training. The gap theory of happiness essentially, like, we’re always living in that gap but between, like, the next thing that’s going to—","offset":3922,"duration":15}],"logs":[{"elapsed":"0.0","message":"Downloading audio from YouTube...","detail":null},{"elapsed":"0.0","message":"Trying download with browser cookies (ad-free)...","detail":null},{"elapsed":"2.4","message":"⚠ Cookie download failed: WARNING: [youtube] [jsc] Error solving n challenge request using \"deno\" provider: Error running deno process (returncode: 1): \u001b[0m\u001b[1m\u001b[31merror\u001b[0m: Uncaught (in promise) TypeError: Cannot read prope","detail":null},{"elapsed":"2.4","message":"Retrying without cookies...","detail":null},{"elapsed":"26.4","message":"⚠ Downloaded without cookies — audio may contain ads","detail":null},{"elapsed":"26.4","message":"Audio downloaded (32.4 MB) in 26.4s","detail":"File size: 32.4 MB"},{"elapsed":"26.4","message":"Video title: Brian Mackenzie Reveals Single Best Way to Increase Fitness Level without Steroids","detail":null},{"elapsed":"26.5","message":"Audio duration: 50:35 (50.6 min)","detail":null},{"elapsed":"26.5","message":"Large audio (32.4 MB) — will use chunked transcription with gemini-3-flash-preview","detail":null},{"elapsed":"26.5","message":"Skipping full-file attempt — using chunked transcription for 50.6 min audio","detail":null},{"elapsed":"26.9","message":"Split audio into 2 chunks for transcription","detail":null},{"elapsed":"26.9","message":"Transcribing chunk 1/2 (starts at 0:00)...","detail":null},{"elapsed":"26.9","message":"Uploading audio to Gemini File API...","detail":null},{"elapsed":"32.1","message":"Audio uploaded in 5.3s","detail":"File ref: files/jcpngmvytrx3"},{"elapsed":"32.1","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"95.7","message":"Chunk 1: 108 segments, last timestamp 1:05:22","detail":null},{"elapsed":"95.7","message":"Transcribing chunk 2/2 (starts at 45:00)...","detail":null},{"elapsed":"95.7","message":"Uploading audio (offset 45:00) to Gemini File API...","detail":null},{"elapsed":"97.6","message":"Audio uploaded in 1.9s","detail":"File ref: files/jeq1axdd05o0"},{"elapsed":"97.6","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"111.0","message":"Chunk 2: 14 segments, last timestamp 50:14","detail":null},{"elapsed":"111.0","message":"Chunked transcription complete: 108 total segments","detail":null},{"elapsed":"111.0","message":"Total cost: 76,389 in / 12,890 out — cost: $0.0769","detail":null},{"elapsed":"111.0","message":"Total transcription time: 84.5s — 108 segments","detail":null},{"elapsed":"111.0","message":"Analyzing topics across 108 segments with gemini-3.1-pro-preview...","detail":null},{"elapsed":"167.0","message":"Topic analysis complete in 56.0s — found 11 topics","detail":null},{"elapsed":"167.0","message":"Analysis tokens: 12,204 in / 913 out / 2,297 thinking — cost: $0.0629","detail":null},{"elapsed":"167.0","message":"Pipeline finished in 167.0s — total cost: $0.1398 (104,693 tokens)","detail":null}]} \ No newline at end of file diff --git a/history/1775599688621-Tmw2dW0a9DY.json b/history/1775599688621-Tmw2dW0a9DY.json new file mode 100644 index 0000000..54d25bc --- /dev/null +++ b/history/1775599688621-Tmw2dW0a9DY.json @@ -0,0 +1 @@ +{"id":"1775599688621-Tmw2dW0a9DY","videoId":"Tmw2dW0a9DY","url":"https://www.youtube.com/watch?v=Tmw2dW0a9DY","title":"Cultivating Awe & Emotional Connection in Daily Life | Dr. Dacher Keltner","type":"youtube","topicCount":27,"segmentCount":398,"createdAt":"2026-04-07T22:08:08.621Z","uploadDate":"20260406","chunks":[{"title":"Introduction & Guest Overview","summary":"Andrew Huberman introduces Dr. Dacher Keltner, a professor of psychology and expert in the science of emotions. They preview the episode's focus on awe, social bonding, and the science of human connection.","entries":[{"text":"Guest: Awe is good for reduced inflammation, elevated vagal tone, reduced long COVID symptoms. We have people with long COVID, just a minute of awe a day reduced long COVID symptoms. It's good news, right? And, and there's so much science on it that I just now, I think medical doctors are starting to think like, I'm going to prescribe nature, I'll prescribe music, through awe, right? Um as a mechanism.","offset":0,"duration":27},{"text":"Host (Andrew Huberman): Welcome to the Huberman Lab Podcast where we discuss science and science-based tools for everyday life. I'm Andrew Huberman and I'm a professor of neurobiology and ophthalmology at Stanford School of Medicine. My guest today is Dr. Dacher Keltner.","offset":27,"duration":19},{"text":"Andrew Huberman: Dr. Dacher Keltner is a professor of psychology and the co-director of the Greater Good Science Center at the University of California Berkeley. Dacher is an expert in the science of emotions and their role in social dynamics and bonding.","offset":46,"duration":17},{"text":"Andrew Huberman: Today we discuss his fascinating work on the science of emotions including the role of teasing in social bonding, the role of embarrassment in social bonding and his fascinating work on awe and the things that lead to awe. As he describes, awe is not elusive. It happens when we shift our perception from a very small scale to a very large scale or back again, such as when we suddenly reach a new horizon or visual vista.","offset":63,"duration":31},{"text":"Andrew Huberman: Today you'll understand what all of that really means and more importantly, how you can create this incredible thing that we call awe in everyday life. We also talk about the critical aspect of human bonding in groups and the things that both establish and inhibit deep human bonds.","offset":94,"duration":18},{"text":"Andrew Huberman: So today is a very practical as well as conceptual conversation that no doubt will change the way that you think about your life everyday and think about opportunities for awe everyday. As you’ll soon see, Dacher Keltner is a truly special scientist known for his incredible rigor and creativity in the study of emotion but also continually offering you, the public, ways to be and feel genuinely better and to get more out of life. It was a true honor and pleasure to host him.","offset":112,"duration":35},{"text":"Andrew Huberman: Before we begin, I'd like to emphasize that this podcast is separate from my teaching and research roles at Stanford. It is however part of my desire and effort to bring zero cost to consumer information about science and science-related tools to the general public. In keeping with that theme, today's episode does include sponsors.","offset":147,"duration":19},{"text":"Andrew Huberman: And now for my discussion with Dr. Dacher Keltner. Dr. Dacher Keltner, welcome.","offset":166,"duration":5}],"startTime":0},{"title":"Shifting Focus to Awe","summary":"Dr. Keltner discusses his early career studying negative emotions and how his unconventional upbringing inspired him to pivot toward researching awe, beauty, and human connection.","entries":[{"text":"Guest (Dacher Keltner): Good to be with you, Andrew.","offset":171,"duration":2},{"text":"Andrew Huberman: Awe. Yeah. I think we all intuitively know what it is and yet we also don’t know how to articulate it. Yeah. I want to say the words overwhelmed, excited, I get the physical sensation of a lift. I don’t think anyone ever said the word awe and then collapsed into a turtle position. Maybe we could explore that in your thoughts about that. But what got you into awe?","offset":173,"duration":29},{"text":"Dacher Keltner: Yeah, and, and I love the word lift. That’s really interesting. Uh, yeah, I was a young scholar in the science of emotion that really Paul Ekman was a pioneer in, you know. And, and that field in the, you know, 90s and early 2000s was uh really focused on negative emotions, you know.","offset":202,"duration":19},{"text":"Dacher Keltner: And and you know this science, right? Anger, fear, fight or flight physiology, amygdala, cortisol, uh disgust, you know, Paul Rozin and John Haidt. Um and thinking about emotions from that lens and and it as a young scientist um and given the powerful tools of emotion science of Darwin and Ekman and how to just observe phenomena uh it didn’t make contact with my life and my own experience, you know.","offset":221,"duration":29},{"text":"Dacher Keltner: I was raised as a wild child in the late 60s in Laurel Canyon and, you know, it was like music and social change and protest and uh you know and beauty and I was raised by a dad who’s a visual artist and my mom taught romanticism and Virginia Woolf and awe and the mind and and I was like wow there’s all this stuff that our science, my science, can’t speak to, music and visual patterns and dance and collective movement and, you know, someone like Martin Luther King and why he makes me cry, you know.","offset":250,"duration":37},{"text":"Dacher Keltner: And I remember feeling this and asking Paul Ekman, I was like, you know what should I do with my career? and he’s like “study awe”, you know, and uh so that got me going.","offset":287,"duration":11}],"startTime":171},{"title":"Facial Expressions & Universal Emotions","summary":"The conversation shifts to Paul Ekman's pioneering work on facial expressions. Keltner explains how modern research, including AI analysis, has expanded the recognized spectrum of universal human emotions to around 20 distinct states.","entries":[{"text":"Andrew Huberman: If we could let maybe we could talk about the faces for a moment. You know, I think every psychology and neuroscience student sees these faces of disgust, of of pleasure, uh Darwin talked about this. Babies are often presented in parallel with those pictures of adults where they’ll show a baby like, you know, recoiling from something or you know wide-eyed and leaning in, you know.","offset":298,"duration":29},{"text":"Andrew Huberman: There always seems to be a motor component to this that maybe isn’t as captured in those two-dimensional photographs but what’s the story about kind of hard-wired facial emotions and what are the revisions to that story that I’m probably not aware of?","offset":327,"duration":17},{"text":"Dacher Keltner: Yeah, thank you for asking that um, you know, I’ve spent 30 years working on that very problem. Um Paul Ekman came in and, you know, as as you suggested, right? He did this revolutionary work in New Guinea, you know, showed photos of six emotions, static photographs of anger, fear, sadness, disgust, surprise, and a smile.","offset":344,"duration":22},{"text":"Dacher Keltner: They kind of interpreted the faces like you or I would um naming it using the right words to describe those faces and that you know and this is how science occasionally works which is just by accident that became the field. And there are a lot of debates about how reliable those faces are, how universal are they in different cultures.","offset":366,"duration":24},{"text":"Dacher Keltner: Ekman really posited sort of a strong universality, that’s been contested by Jim Russell, Lisa Feldman Barrett, and others. Um but since then there are controversies around how hard how hard-wired they are, do they occur reliably in a child’s development? Yes and no.","offset":390,"duration":21},{"text":"Dacher Keltner: You know, young children show disgust expressions uh like social mammals do, they wince at bad smells just like you or I would. Um anger’s a little bit trickier to pin down developmentally. But then our lab and several labs around the world, you know, Jess Tracy at UBC (British Columbia), Disa Sauter, uh and I want to talk about this computational work, started to expand the vocabulary of faces.","offset":411,"duration":27},{"text":"Dacher Keltner: And now we there’s a lot of data that suggests there are 20 different facial expressions. Laughter, love, compassion, awe, you know “whoa”, um embarrassment, shame, pain um you know and that in some sense has broadened the taxonomy of emotions. We used to think of six, now there are probably 20 distinct states in the mind.","offset":438,"duration":28},{"text":"Dacher Keltner: And that’s where the field is heading is to really start to think about physiological patterns, brain patterns um of of these distinct states. And and I’ll tell you um the hard-wiring question, I mean it’s hard science to do, right? Just to imagine videotaping people from five different countries, getting their emotional expressions, and then making sense of them.","offset":466,"duration":28},{"text":"Dacher Keltner: It used to take one hour to code the facial muscle movements of of one minute, right? So this is slow science. And I would really encourage listeners um and viewers to go to alancowan.com and I had a grad student at Berkeley, Alan Cowan, who you know he’s a computational genius and he looked at our old science and said, “we can use AI to code the face” and he did it with Google engineers.","offset":494,"duration":28},{"text":"Dacher Keltner: He coded 144 um two million videos from 144 cultures and 16 facial expressions, 75% overlap across cultures in how we show awe at fireworks, concentration on a test, you know, laugh at friends. So right now I would say 50 to 60% is hard-wired as part of who we are in our evolutionary history and then the rest is subject to variation in interesting ways.","offset":522,"duration":-28}],"startTime":298},{"title":"Sponsor Break: Joovv & Helix Sleep","summary":"Andrew Huberman reads sponsor messages for Joovv red light therapy devices and Helix Sleep mattresses.","entries":[{"text":"Andrew Huberman: I’d like to take a quick break and acknowledge one of our sponsors, Joovv. Joovv makes medical grade red light therapy devices. Now if there’s one thing that I have consistently emphasized on this podcast is the incredible impact that light can have on our biology and our health. Now in addition to sunlight, which I’ve talked about a lot on this podcast, red light, near-infrared, and infrared light have been specifically shown to have positive effects on improving numerous aspects of cellular and organ health.","offset":494,"duration":90},{"text":"Andrew Huberman: These include faster muscle recovery, improved skin health, wound healing, improvements in acne, reduced pain and inflammation, improved mitochondrial function, and even improvements in vision. Nowadays there are a lot of red light devices out there, but what sets Joovv lights apart and why they’re my preferred red light therapy device is that they use clinically proven wavelengths, meaning they use the specific wavelengths of red light, near-infrared and infrared light in combination to trigger the optimal cellular adaptations.","offset":584,"duration":27},{"text":"Andrew Huberman: Personally I use the Joovv whole body panel about three to four times a week, usually for about 10 to 20 minutes per session, and I use the Joovv handheld light both at home and when I travel. If you’d like to try Joovv, they’re offering up to $400 off select products for listeners of this podcast. To learn more, visit joovv, spelled J-O-O-V-V.com/huberman. Again that’s J-O-O-V-V.com/huberman.","offset":611,"duration":28},{"text":"Andrew Huberman: Today’s episode is also brought to us by Helix Sleep. Helix Sleep makes mattresses and pillows that are customized to your unique sleep needs. Now I’ve spoken many times before on this and on other podcasts about the fact that getting a great night’s sleep is the foundation of mental health, physical health, and performance. When we aren’t getting great sleep on a consistent basis, everything suffers, and when we are sleeping well and enough, our mental health, physical health, and performance in all endeavors improve markedly.","offset":639,"duration":27},{"text":"Andrew Huberman: Now the mattress you sleep on makes a huge difference in the quality of sleep that you get each night. How soft it is or how firm it is all play into your comfort and need to be tailored to your unique sleep needs. If you go to the Helix website, you can take a brief two minute quiz and it will ask you questions such as do you sleep on your back, your side, or your stomach, maybe you know maybe you don’t, do you tend to run hot or cold during the night, things of that sort.","offset":666,"duration":22},{"text":"Andrew Huberman: You answer those questions and Helix will match you to the ideal mattress for you. For me that turned out to be the Dusk, D-U-S-K mattress. I’ve been sleeping on a Dusk mattress for more than four years now and it’s been far and away the best sleep that I’ve ever had. If you’d like to try Helix, you can go to helixsleep.com/huberman, take that two minute sleep quiz and Helix will match you to a mattress that’s customized for you.","offset":688,"duration":23},{"text":"Andrew Huberman: Right now Helix is giving up to 27% off their entire site. Helix has also teamed up with Truemed, which allows you to use your HSA FSA dollars to shop Helix’s award winning mattresses. Again that’s helixsleep.com/huberman to get up to 27% off.","offset":711,"duration":21}],"startTime":494},{"title":"Motor Patterns, Language, and Feeling","summary":"Huberman and Keltner explore how emotions are expressed through motor patterns, language, and physiological feeling, noting that conscious feeling remains one of the hardest aspects to study.","entries":[{"text":"Andrew Huberman: I’m going to ask a question that may or may not be possible to answer, but if anyone could it would be you. And it’s not a test, but here’s what I’m thinking. The relationship between emotions and what we call motor patterns, movement, is obviously very close, right? Disgust a recoil, uh we’ll explore awe, um anger, etc.","offset":732,"duration":26},{"text":"Andrew Huberman: And then there’s this other node which is language. Right? So we have like emotions, motor, language. Obviously those can’t be dissociated, but can we imagine somebody let’s just like hypothetical person who can keep their body very still while they’re angry and be very articulate, that includes not moving their hands, we’d probably think perhaps that person’s like sociopathic but that’s not the picture I’m trying to paint.","offset":758,"duration":28},{"text":"Andrew Huberman: Then on the other extreme, can imagine somebody who um is very angry and is gesticulating a lot and moving around, you know we can immediately “yeah, that makes that makes sense.” And we could do this for any emotion. Yep. So how should we think about emotion as an experience and how it’s expressed along these three axes, right? Which is motor, language, and then the emotion itself.","offset":786,"duration":24},{"text":"Andrew Huberman: I feel like without um conceptualizing that, I as a true novice of this, right? this isn’t my area of of understanding or expertise, I can’t really understand what an emotion is. But if I understand how those are linked, maybe maybe that’s a portal into that.","offset":810,"duration":18},{"text":"Dacher Keltner: Yeah, no, I mean it’s a profound question, Andrew, and it and it’s central to our field, which is you know the and and I appreciate it coming out of your scientific background of studying other mammals and other species and and and there are these motor patterns that you see in emotion around the world.","offset":828,"duration":22},{"text":"Dacher Keltner: When you soothe a child that’s crying, right? you’re going to bring it in close and caress and touch and have emotion when you’re, you know, when you’re uh fighting a rival or when you you see rotten food, you’re going to that motor pattern will be there. You know, and that’s part of our research that 75% of that is this motor pattern of facial musculature and body and skeletal muscles and how we respond to the emotional events of life.","offset":850,"duration":31},{"text":"Dacher Keltner: And then we have this massively complicated, you know, conceptual system that puts words to experience and that’s mainly what we study in psychological sciences, just “oh, I’m feeling angry or ashamed or embarrassed or love or compassion.”","offset":881,"duration":17},{"text":"Dacher Keltner: And we know and your question points to this like very often they’re disconnected, right? the motor pattern and the language we use and how I would interpret it in another person. Um on balance they correlate .2, so they’re just weakly they’re kind of these streams of behavior that are part of who we are, right? Our motor patterns and language.","offset":898,"duration":23},{"text":"Dacher Keltner: And there are a lot of ways to think about it. You could think about cultures that value being calm, like a lot of East Asian cultures. Be calm, don’t disrupt things, don’t blurt out, don’t protest, right? and and you’ll see this disconnect. Um you can think about certain people who they just are more authentic and their motor patterns come out in expressions and they will tell you how they feel.","offset":921,"duration":25},{"text":"Dacher Keltner: Uh so it’s a central problem that we grapple with. And then I love your your third part of this equation of emotion science, which is the feeling. The emotion. Michael Pollan is right, you know, this new book on consciousness, the conscious feeling of something. We think we can get to it with words, I don’t think so. Um you probably wouldn’t either, right? studying the other species you’ve studied, right?","offset":946,"duration":29},{"text":"Dacher Keltner: Um it’s some weird mixture of everything that’s happening in your body. And ironically the emotion or the feeling is still one of the uncharted territories of our field as why as these complicated motor patterns take unfold and words are unfolding and images and memories and visual things that you study, how does that all come together in my feeling of compassion or awe? And we barely know, you know, we just we don’t know.","offset":975,"duration":32}],"startTime":732},{"title":"Physiology of Emotion & Vagal Tone","summary":"They discuss how esoteric concepts like chakras align with physiological realities like vagal tone and breath. Keltner explains how multiple bodily metrics are used to measure emotional responses.","entries":[{"text":"Andrew Huberman: Every once in a while I’ll try and think about a concept from way outside of standard science, like the chakras or something. Yeah. And it’s kind of interesting, right? I mean even if just if one looks at it just purely as a Western scientist, this idea that maybe there is a confluence of of nerves and of vasculature and stuff that makes you feel kind of like rooted at like and and calm, right?","offset":1007,"duration":23},{"text":"Andrew Huberman: Versus like up in your head, I uh I’ve been watching this really interesting Instagram channel, it’s a woman who does voices for cartoons and she has the most incredible understanding of voice. And she’s commenting a lot of the time on people in shows that I don’t watch but they have little excerpts of where like I guess there’s this doctor on the this it’s like an ER type show, it’s like a revisiting of the show ER but she talks about how as he’s matured from season to season in his role on the show and he’s mentoring how she literally talks about how uh his larynx and pharynx are how he’s controlling those differently as he matures and then when he has a breakdown how the voice moves further up into his head and what and what that’s about.","offset":1030,"duration":43},{"text":"Andrew Huberman: And I so I was thinking about this I’m like, you know, here’s somebody that’s a very unique, you know window into all of this, but we sort of know this intuitively. Like when we’re excited like there’s this kind of rising from the bottom and when we’re relaxed everything just kind of sinks down to a the diaphragmatic breathing and things.","offset":1073,"duration":20},{"text":"Andrew Huberman: As a scientist who studies emotion, how do you sort of decide what what uh which lens to look at things through um because a lot of the stuff I’m talking about might sound a little esoteric but it’s actually the stuff that’s easiest to measure. Yeah. Presumably you can quantitatively measure like breaths per minute when somebody’s looking at an awe inspiring image versus like a trivial image.","offset":1093,"duration":25},{"text":"Dacher Keltner: I love your reference to chakras and you know the older I get, you know I’ve been doing emotion science for 34 years or five years, it’s good to think about the other traditions, you know. We wouldn’t have thought about the breath, the power of the breath uh without the contemplative meditation traditions that you’ve in part tested and Richie Davidson and others.","offset":1118,"duration":25},{"text":"Dacher Keltner: And lo and behold the breath, deep exhalation, activates the vagus nerve, calms us down. That activation of the vagus nerve gives people a sense of warmth in your chest, which kind of sounds like the heart chakra and all the speculation around how your soul is in your heart. Well there’s a neurophysiological correlate of that. Um I love the paintings of Alex Grey, the psychedelic artist, like if you want an image of what our neurophysiology is as it synchronizes in love, you could it’s pretty close, or it’s interesting, right? So it’s good to find inspiration in that.","offset":1143,"duration":32},{"text":"Dacher Keltner: One of the great things about the science of emotion and and I brought these tools into the study of awe, you know, which is we have learned a lot about how to measure emotion. You know, you can measure it with facial muscles and gaze patterns and coloration of the face and breath patterns and you know different measures of vagal tone uh and immune system activation and activation in the gut and of course brain activation and the voice, which is one of my favorite modalities.","offset":1175,"duration":31},{"text":"Dacher Keltner: I learned this in some sense from Darwin, Darwin’s “expression of emotion in man and animal” is in my view and we’re just publishing a paper on this uh on everything that he said about human emotion. 53 emotions annotated with eight modalities of expressive behavior. I wrote it with Darwin scholar Frank Sulloway, who knows everything about Darwin. And I choose how to study an emotion based on what’s what’s happening out in our lives and our the phenomena out there, right?","offset":1206,"duration":32},{"text":"Dacher Keltner: So if you’re studying awe you should get people around big trees or in musical concerts or in museums, right? Uh if you’re I studied embarrassment early in my career and modesty and I’m like I gotta study young men teasing each other because we embarrass each other, you know intentionally.","offset":1238,"duration":18},{"text":"Andrew Huberman: Oh my goodness, we have to hear about that that work again. It’s become very relevant nowadays because of the because of the I’ll just call it what it is, it’s not dread-it, it’s the dreadful man-o-sphere, you know, which people use very broadly but I think now it’s being you know allocated to the the worst of the worst.","offset":1256,"duration":22},{"text":"Andrew Huberman: But then there is this phenomenon among males where they’ll rib each other and you know and there’s there’s a healthy version of males interacting too, right? you know uh so we’ll get back to that.","offset":1278,"duration":8},{"text":"Dacher Keltner: I base it on what’s the phenomenon of interest, right? That that speaks to humanity and then what are our best measures that we can go after it.","offset":1286,"duration":9}],"startTime":1007},{"title":"Eliciting and Measuring Awe","summary":"Keltner details the field research methods his lab uses to study awe. They measure responses to vast natural stimuli, concerts, and life-changing experiences like river rafting.","entries":[{"text":"Andrew Huberman: These days if you want to measure awe, what’s your favorite awe stimulus?","offset":1295,"duration":5},{"text":"Dacher Keltner: First off and thank you for asking about measurement, like it’s interesting like people are like “oh, you can’t study awe, you know you don’t know how to measure it, it’s ineffable, it’s mysterious, it’s spiritual.” We can measure awe really well, you know, the vocalization “whoa”, you know, the facial expression uh activation part parts of the brain are deactivated, uh vagal tone, the goosebumps is a good uh part of the awe response.","offset":1300,"duration":29},{"text":"Dacher Keltner: As we started to study awe, we did two things. And one is typical West you know science, which is get your most cool awe videos, show them to people, you know, and I had some missteps in this science. I had a woman who was an honors student at Berkeley who was coming back from Burning Man and you know she’s like “I’m going to show engineers fractal imagery” and you know and the engineers are like “who is this woman?”","offset":1329,"duration":29},{"text":"Andrew Huberman: I mean there is the I’ve never been to Burning Man but there is the post Burning Man glow that people come back with that is for understandable reason hard for most people to enter with them. It’s like a kid coming back from summer camp.","offset":1358,"duration":12},{"text":"Dacher Keltner: There’s great visual imagery, you know BBC Earth is awesome and it it uh makes people feel awe. Slow motion guys, I don’t know if you know these guys, they film wild things in slow motion, like you know dropping a wine glass in this spectacular photography and just you know you’re like “whoa.”","offset":1370,"duration":20},{"text":"Andrew Huberman: Cool, we’ll put a link to that. I I love super slow mo.","offset":1390,"duration":3},{"text":"Dacher Keltner: Yeah. Um and that fits our definition which is like you don’t understand what’s happening, it’s vast, it’s mysterious. But what I’m really proud of Andrew is the work we did out in the field, right? So one of our first studies on the Berkeley campus that you frequented and got your Master’s degree at and headed into neuroscience was uh in our paleontology museum there’s a replica of a T-Rex skeleton.","offset":1393,"duration":26},{"text":"Dacher Keltner: When I was five years old and and I learned about dinosaurs it changed my life. It was just in the LA Natural History Museum like “wow!” So we studied people standing near the T-Rex skeleton and they became expansive and collective. We studied people near giant eucalyptus trees. We studied people at Yosemite, you know, Yang Bai a student in my lab stopped hundreds of travelers from all over the world right when you see Yosemite and she said, “how do you feel about yourself right now?” And they’re like “I feel small and quiet but part of something really large”, right?","offset":1419,"duration":35},{"text":"Dacher Keltner: Um subsequent to that there are scientists who are studying mosh pits at concerts and, you know, surfers and, you know, rock clim- I mean it’s, you know, backpackers and, you know, we studied one of my favorite studies later with Stacy Bare, who’s a veteran who ran the who’s an amazing human being, an awe pioneer, we studied people rafting down the American River, you know, veterans just like “whoa.” We’ve studied people in art museums, Carnegie Hall, you know, so it’s it you know one of the joys is when science you know just in the spirit of your questions, it’s like “well what should I really do here, right? I could stay in the lab” it’s like “no, you know, we gotta go do stuff”, you know, that that uh my dream study was to like have a participant come in and in engage a conversation the other participant is Shaquille O’Neal, right? And it’s like 7’2”, 350 pounds, you’d be like “whoa!” but couldn’t do that. So uh so they it’s been fun. It’s been a wild ride.","offset":1454,"duration":64}],"startTime":1295},{"title":"Visual Aperture & Transitions to Vastness","summary":"Huberman describes how shifting from a narrow visual focus to a broad horizon alters the nervous system. Keltner confirms that transitioning from small to vast perception is a fundamental trigger for awe.","entries":[{"text":"Andrew Huberman: And so many thoughts uh first one um I’m lucky I didn’t rotate through your lab because I uh would have never become a neuroscientist but I’m unlucky because it would have been so much fun to because I while I loved the wet lab as they call it getting into these experiments would just be incredible.","offset":1518,"duration":21},{"text":"Andrew Huberman: Couple things uh the Shaquille O’Neal thing I um, you know I think we’re all moved by these uh I guess they used to call them Make A Wish Foundation things where a kid who sadly is dying gets some last wish and it’s a tragic circumstance but then you get to observe these kids and most importantly they get to experience something that they never could have imagined happening like like a Shaquille O’Neal walking in, I feel like that’s probably happened or something.","offset":1539,"duration":31},{"text":"Andrew Huberman: And I think what we’re witnessing in those moments has to be awe. Like they can’t believe that this human or this event, whatever it is that they wish for is happening there. And so it’s layers upon layers, there’s like a grief component for those of us watching.","offset":1570,"duration":14},{"text":"Dacher Keltner: Well put.","offset":1584,"duration":1},{"text":"Andrew Huberman: But a huge aspect of the of just how touching it is is the fact that like for those moments they’re not thinking about their mortality and no kid should have to think about their mortality right I mean even as I talk about it it’s like uh yeah it’s just it’s like uh there’s an overwhelming in the opposite direction, right?","offset":1585,"duration":17},{"text":"Andrew Huberman: That’s an in particularly uh complicated and and interesting uh case where you’ve got two things colliding, right? Because I feel like awe is so life affirming. Yeah, it is. It is. And uh anyway that’s just an in observation but horizons are something that fascinate me for a long time as a vision scientist because when we see a horizon our visual uh angle widens.","offset":1602,"duration":22},{"text":"Dacher Keltner: That’s cool.","offset":1624,"duration":1},{"text":"Andrew Huberman: We become more parasympathetic. There’s a whole coming off the accelerator of the sympathetic nervous system so we relax by virtue of coming off the focusing component. When we focus in through a tunnel we it’s quite the opposite.","offset":1625,"duration":12},{"text":"Dacher Keltner: Nice.","offset":1637,"duration":1},{"text":"Andrew Huberman: But I feel like there’s something unique to this experience of being in a tunnel, I’m thinking about Yosemite, or in a bunch of trees or hike and then the horizon opens up. Yeah. There’s this transformation of visual space and those moments at least for me are the moments. Like I can hike along a ridgeline for a long time like “this is amazing” but there’s something distinctly bigger in the experience of going from confinement to openness.","offset":1638,"duration":30},{"text":"Andrew Huberman: It could be brought to the lab but do you think that’s what’s going on in in Yosemite or the Grand Canyon? Right? Do people work in Yosemite and the Grand Canyon do they attenuate? They’re like “oh, yeah, like another horizon.”","offset":1668,"duration":11},{"text":"Dacher Keltner: I don’t know, you know, working with rangers right now and they I think I think the big expansive forms of awe that those places provide is attenuated but I think they’re still finding it in subtler ways. Yeah, that’s really interesting and, you know, it’s interesting I was uh I’ve been privileged to know Pete Docter at Pixar for 15 years and worked on some of his films, Inside Out and Inside Out 2 and Soul.","offset":1679,"duration":25},{"text":"Andrew Huberman: You played a big role in that.","offset":1704,"duration":2},{"text":"Dacher Keltner: Yeah, and through this science of emotion. And I was like, you know in one of our conversations I was like “tell me about some techniques for producing awe in children’s films, animated films” and he described first just what you said like, you know, the film is narrow like a certain kind of attention, you know sort of sympathetic, fearful, checking things, and then boom it comes it suddenly you see the vastness of something and it’s true, it is awe inspiring.","offset":1706,"duration":29},{"text":"Dacher Keltner: When you think about it neuroscientifically as a very basic form of awe is shifting from small to vast in terms of vision and perception and then it becomes metaphorical, right? It’s like “god I’m thinking about” like I love one of the wonders of life that uh that makes us feel awe is big ideas and epiphanies and very often people will be like “god I’ve been working so hard at this, you know working on a a paper, something in technology or some part of my life” and then you suddenly realize it’s part of something large, right?","offset":1735,"duration":32},{"text":"Dacher Keltner: One of the musicians that I interviewed, Yumi Kendall, in the book in the chapter on musical awe said, “you know” she’s a cellist for the Philadelphia Symphony said, “you know I practice for five hours a day, it’s hard man and it’s small and narrow and where’s my finger? and then when I’m on stage and I and I feel the notes go out into this space”, the vastness you’re talking about, “I feel like I’m part of history”, right? And I tear up and cry.","offset":1767,"duration":29},{"text":"Dacher Keltner: Um so I think your I think I you gotta send me those papers Andrew because I think it’s fundamental which is from small to vast. And in fact we did this really cool study with Virginia Sturm at UC San Francisco Brain Health, old people go out on an awe walk once a week for eight weeks, 75 years old or older, and all we asked them to do is to go from small to vast and how they looked at things, you know. Look at a tree, look at a leaf, go out to the pattern of leaves. It brought them awe and less physical pain uh over eight weeks and now we’re finding six years later better brain health, right? So small to vast is a big part of it.","offset":1796,"duration":39}],"startTime":1518},{"title":"Awe Walks & Health Benefits","summary":"Keltner outlines the practice of 'awe walks' and their profound health benefits. Regular exposure to awe is linked to reduced inflammation, less physical pain, and improved brain health.","entries":[{"text":"Andrew Huberman: I’m um struck by the by the awe walk um and and I know this comes up in your book and elsewhere and you’ve done a lot of research on this. Um for those listening um what would an awe walk look like and um what are some of the health benefits? You just mentioned a few that that have been observed both in the short and the long term.","offset":1835,"duration":18},{"text":"Dacher Keltner: Yeah, thank you, you know, uh we we are a walking species, you know, it is just in our DNA to walk. We meandered from Africa all to all the continents. A lot of people, Rebecca Solnit writes about this like “walking is almost sacred, it’s a kind of consciousness” like you’re saying like “whoa, I’m I’m picking up a vaster view of what’s around me.”","offset":1853,"duration":25},{"text":"Dacher Keltner: And I uh decided to just create this awe walk, you know, and I did it for a meditation group the or Mindful Magazine. You just slow down, you a lot of people walk, hundreds of, you know, tens of millions of people have regular walks in the United States. Uh it’s good for you, you know, so we just added awe.","offset":1878,"duration":19},{"text":"Dacher Keltner: Like on your regular walk, once a week in our study, uh go somewhere you wouldn’t ordinarily go, go some place that may surprise you. Uh I walk around Berkeley a lot and I was like “well I’m going to go past the little playground that my daughters played at when they were young and just feel that”, you know, Cordornices Park.","offset":1897,"duration":19},{"text":"Andrew Huberman: Yeah. With the rock slide.","offset":1916,"duration":2},{"text":"Dacher Keltner: And the tunnel.","offset":1918,"duration":1},{"text":"Andrew Huberman: Exactly.","offset":1919,"duration":1},{"text":"Dacher Keltner: I love that place.","offset":1920,"duration":1},{"text":"Andrew Huberman: Near the rose garden.","offset":1921,"duration":2},{"text":"Dacher Keltner: Exactly.","offset":1923,"duration":1},{"text":"Andrew Huberman: And there’s a secret, should we give this away? Yeah. There’s a secret hiking trail through it’s actually through a private property’s backyard and they allow you to go through if you are quiet and you pick up your trash and there’s an incredible waterfall and place to stand at the top, there’s a beam there, you’ve been there I’m sure where you can look out over this what is kind of like a trench of tree- it’s a total transformation of one space to the next if you if you look for it properly, I’m sure now it’s on the internet. Um it’s in kind of swinging gates, not locked, and uh so hard to find.","offset":1924,"duration":37},{"text":"Dacher Keltner: And and there’s a little monastery maybe nearby and uh and you might and you might see me a couple years ago you would have seen me and my dog, but you might see me uh eating a slice of pizza from the Cheese Board sitting on that log. I spent a lot of time there.","offset":1961,"duration":15},{"text":"Andrew Huberman: I’m getting goosebumps Andrew, that is just pure Berkeley, thank you. So yeah, so in this study awe walk go on your walk, find a place that’s going to be a little surprising where it may make you feel a little bit of childlike wonder.","offset":1976,"duration":14},{"text":"Dacher Keltner: And it’s interesting, no one’s asked me this question, you know your observation about small to vast and we just said slow down, deepen your breathing, sync it up with your your walking, which you’ve studied empirically the breath. And then um go from small to vast, you know.","offset":1990,"duration":18},{"text":"Dacher Keltner: Look at clouds, look at the whole pattern of clouds, just slow it down. Look at trees, look at the light on the trees and look at points of light and then patterns of light. Look at, you know I love walking past playgrounds as one of my favorite sources of awe, listen to one laugh and then listen to the whole symphony of laughter of kids, right?","offset":2008,"duration":22},{"text":"Dacher Keltner: That’s all. And they walk through uh they do that for half an hour and what we find in that study is is they become more vast in their consciousness. They’re more aware in the photographs that they provided of what’s around them. They feel more kindness over the eight weeks. They feel more awe over an eight week period, it rises.","offset":2030,"duration":20},{"text":"Dacher Keltner: And then the the finding that was you know important for people who are elderly is less physical pain. You know, your body starts to ache when you’re 75, you know, uh or earlier and awe I think through the inflammation process, you know in reducing it, caused less pain.","offset":2050,"duration":21},{"text":"Dacher Keltner: You know this dovetails with other health benefits, awe is good for reduced inflammation, elevated vagal tone, reduced long COVID symptoms. We have people with long COVID, just a minute of awe a day reduced long COVID symptoms. It’s good news, right?","offset":2071,"duration":18},{"text":"Dacher Keltner: And and there’s so much science on it that I just now, I think medical doctors are starting to think like “I’m going to prescribe nature, I’ll prescribe music” through awe, right? Uh as a mechanism.","offset":2089,"duration":16}],"startTime":1835},{"title":"Visual Aperture, Time & Consciousness","summary":"Huberman shares his 'Space-Time Bridging' concept, linking visual aperture to time perception. They discuss how awe fosters equanimity by connecting us to longer time scales and shifting our perception from small to vast.","entries":[{"text":"Andrew Huberman: I have a lot of thoughts about um this going from uh small to large. Yeah, I’d love to hear them. But before I do, um I have an- I have another question. I think for a lot of people, um including myself, we assume that awe is this kind of forgetting of ourselves. Like see- like getting outside of ourselves.","offset":2105,"duration":23},{"text":"Andrew Huberman: But I’m starting to think based on the way you’re describing it that it’s about being tethered to the larger picture. That it’s not a get- yes it’s getting out of our heads quote unquote, but it’s actually very much an embodied experience. It’s very like it’s almost like full body. Yeah, so now I’ll answer your question, this is usually where people start putting in the comments like “you talk too much, let your your guest talk” but trying folks, he asked me twice.","offset":2128,"duration":26},{"text":"Andrew Huberman: So you asked me a question, I’m going to answer it. Anyone that knows me you know if I- Okay, so I’ve thought about this this relationship between visual aperture and uh time perception.","offset":2154,"duration":15},{"text":"Dacher Keltner: Cool.","offset":2169,"duration":1},{"text":"Andrew Huberman: This is my my deepest obsession and it uh gets a little bit into the book I’m writing but it but it’s probably reserved for after there’s some experiments. And and I um to the fear of my podcast crew, I actually am considering going back into the lab to do this experiment.","offset":2170,"duration":16},{"text":"Andrew Huberman: Okay. So we know what do we know for certain? We know for certain that when your visual aperture is small, like looking through a soda straw view or watchmaker type aperture, or um you’re in a let’s just say a pleasant or unpleasant text communication that’s going back and forth, that your perception of time is different. You’re fine-slicing. Those dot-dot-dots coming through, yeah it’s just it feels like an eternity.","offset":2186,"duration":26},{"text":"Dacher Keltner: Yeah, just it’s like.","offset":2212,"duration":1},{"text":"Andrew Huberman: And it’s bidirectional with your let’s just call it level of alertness, it doesn’t even have to be stress but sympathetic nervous system, right? So if I’m in line at the store and and I have some place to be, my visual aperture shrinks and then it feels like the person in front of me is taking forever. Yeah because you’re in these little micro.","offset":2213,"duration":16},{"text":"Andrew Huberman: When I’m relaxed it feels like I’m I’m slicing time differently. Okay. When we see a horizon and and our aperture opens up as I mentioned then we relax, but we also are taking fewer time bin snapshots. So people might think “oh fewer you’re in slow motion” because the word “no”, you’re it’s the opposite, right? Slow motion is high frame rate.","offset":2229,"duration":25},{"text":"Andrew Huberman: This thing about video where you can catch slow motion, you need high frame rate. This is why when people experience uh like a car crash they’ll often say that things felt like they were slowing down. More snapshots.","offset":2254,"duration":12},{"text":"Dacher Keltner: That’s cool.","offset":2266,"duration":1},{"text":"Andrew Huberman: So when I think about this relationship between visual aperture and time, and it also exists in the auditory domain. So if I’m listening to a specific conversation at a party, I’m fine-slicing my perception of auditory space. Our friend Erv Hafter taught me this.","offset":2267,"duration":16},{"text":"Andrew Huberman: When I listen to everything and I take it in as a whole, it’s it’s a more relaxed experience but okay. So a long time ago I was because I was experiencing stress, I started reading about meditation types and different things and and I I came up with this meditation, but it’s not a meditation at all and some of my listeners will be familiar with it, I decided to call it for lack of a better term Space-Time Bridging.","offset":2283,"duration":23},{"text":"Andrew Huberman: The meditation is very simple. You um close your eyes and you do three breaths thinking about your skin inward, so interoception. You open your eyes and you look at your hand and you take three breaths, but you’re creating a visual tether between you and your hand. Then you look some distance, maybe eight or 10 feet away, you do the same. Then you find a horizon, and then you think about the sort of pale blue dot phenomenon like you’re just on a planet floating in space and like every single one of these things is a form of meditation or a meme or or whatever.","offset":2306,"duration":23},{"text":"Andrew Huberman: And then you get right back to yourself. And so what the idea here is that it helped me a lot because I noticed that meditations where I was completely focused inward made me more focused inward. Going for a run I could get outside my head but it and I started to play with the idea that maybe it’s not about having a small aperture or a big aperture per se, yeah but it’s the like every great thing in biology or psychology, it’s the process, it’s not an event.","offset":2329,"duration":26},{"text":"Andrew Huberman: It’s the process of going from one aperture to the next. And that’s kind of what life is about. That’s cool. Yeah. Absolutely. Like when “this too shall pass” is really about taking a broader time snapshot, like eventually this thing, which is visual as well.","offset":2355,"duration":16},{"text":"Dacher Keltner: Which is visual as well.","offset":2371,"duration":1},{"text":"Andrew Huberman: And so this is a long answer to your question, but um this is why it’s so important for me to see a horizon if I can in the morning um but it’s also very important to go indoors and just like focus on what I’m working on. Like there is no place or event in a day or in life that that’s actually the right way to live. Like you can go to Big Sur and if you’re lucky enough to go to Esalen like you’re like “this is it” but it’s only it because you came from your office, in my opinion, and then you go back again.","offset":2372,"duration":30},{"text":"Andrew Huberman: You’ve figured this out, like you have this- the title of this paper for which you’re the senior author is “A Balanced Mind: Awe Fosters Equanimity via Temporal Distancing.” So it’s so it’s about time, not about space.","offset":2402,"duration":15},{"text":"Dacher Keltner: It is. That’s fascinating.","offset":2417,"duration":2},{"text":"Andrew Huberman: Okay, so that’s so that’s how I think about this. Now maybe you can tell us about this paper because I’m getting embarrassed that I’ve been going way too long.","offset":2419,"duration":5},{"text":"Dacher Keltner: This is why we’re in conversation, Andrew, which is, you know, you’ve studied the visual system and and we need more of that knowledge in the science of awe. And I will just make one parenthetical note, which is I was interviewing Pete Docter at Pixar for 15 years and worked on some of his films, Inside Out and Inside Out 2 and Soul.","offset":2424,"duration":22},{"text":"Andrew Huberman: You played a big role in that.","offset":2446,"duration":2},{"text":"Dacher Keltner: Yeah, and through this science of emotion. And I was like, you know in one of our conversations I was like “tell me about some techniques for producing awe in children’s films, animated films” and he described first just what you said like, you know, the film is narrow like a certain kind of attention, you know sort of sympathetic, fearful, checking things, and then boom it comes it suddenly you see the vastness of something and it’s true, it is awe inspiring.","offset":2448,"duration":29},{"text":"Dacher Keltner: When you think about it neuroscientifically as a very basic form of awe is shifting from small to vast in terms of vision and perception and then it becomes metaphorical, right? It’s like “god I’m thinking about” like I love one of the wonders of life that uh that makes us feel awe is big ideas and epiphanies and very often people will be like “god I’ve been working so hard at this, you know working on a a paper, something in technology or some part of my life” and then you suddenly realize it’s part of something large, right?","offset":2477,"duration":32},{"text":"Dacher Keltner: One of the musicians that I interviewed, Yumi Kendall, in the book in the chapter on musical awe said, “you know” she’s a cellist for the Philadelphia Symphony said, “you know I practice for five hours a day, it’s hard man and it’s small and narrow and where’s my finger? and then when I’m on stage and I and I feel the notes go out into this space”, the vastness you’re talking about, “I feel like I’m part of history”, right? And I tear up and cry.","offset":2509,"duration":30},{"text":"Dacher Keltner: Um so I think your I think I you gotta send me those papers Andrew because I think it’s fundamental which is from small to vast. And in fact we did this really cool study with Virginia Sturm at UC San Francisco Brain Health, old people go out on an awe walk once a week for eight weeks, 75 years old or older, and all we asked them to do is to go from small to vast and how they looked at things, you know. Look at a tree, look at a leaf, go out to the pattern of leaves. It brought them awe and less physical pain uh over eight weeks and now we’re finding six years later better brain health, right? So small to vast is a big part of it.","offset":2539,"duration":22},{"text":"Andrew Huberman: I didn’t expect that we would land here, at least not so early in the conversation but you know we we’ve had Christoph Koch on this podcast talking about consciousness, you know, incredible neuroscientist and really thinker, I mean I’ve watched his career evolve over the years and and he’s continued to evolve his concepts of how to think about consciousness and uh and you’ll hear nowadays about “oh like maybe consciousness is outside the brain” and I think if nothing else our brains are important components in it, heck yeah I don’t want to do the experiment on myself to find out like if I was decerebrated or something, which basically means having your cortex removed, sorry for the nerd speak.","offset":2561,"duration":37},{"text":"Andrew Huberman: But the idea is connecting through time like in our own lives is a very unique form of awe. So like if I hear a song and it reminds me of when I was like 15 and then all of a sudden all the the mat- as I call it video whatever it is that they wish for is happening there. And so it’s layers upon layers, there’s like a grief component for those of us watching.","offset":2598,"duration":19},{"text":"Dacher Keltner: Well put.","offset":2617,"duration":1},{"text":"Andrew Huberman: But a huge aspect of the of just how touching it is is the fact that like for those moments they’re not thinking about their mortality and no kid should have to think about their mortality right I mean even as I talk about it it’s like uh yeah it’s just it’s like uh there’s an overwhelming in the opposite direction, right?","offset":2618,"duration":17},{"text":"Andrew Huberman: That’s an in particularly uh complicated and and interesting uh case where you’ve got two things colliding, right? Because I feel like awe is so life affirming. Yeah, it is. It is. And uh anyway that’s just an in observation but horizons are something that fascinate me for a long time as a vision scientist because when we see a horizon our visual uh angle widens.","offset":2635,"duration":22},{"text":"Dacher Keltner: That’s cool.","offset":2657,"duration":1},{"text":"Andrew Huberman: We become more parasympathetic. There’s a whole coming off the accelerator of the sympathetic nervous system so we relax by virtue of coming off the focusing component. When we focus in through a tunnel we it’s quite the opposite.","offset":2658,"duration":13},{"text":"Dacher Keltner: Nice.","offset":2671,"duration":1},{"text":"Andrew Huberman: But I feel like there’s something unique to this experience of being in a tunnel, I’m thinking about Yosemite, or in a bunch of trees or hike and then the horizon opens up. Yeah. There’s this transformation of visual space and those moments at least for me are the moments. Like I can hike along a ridgeline for a long time like “this is amazing” but there’s something distinctly bigger in the experience of going from confinement to openness.","offset":2672,"duration":29},{"text":"Andrew Huberman: It could be brought to the lab but do you think that’s what’s going on in in Yosemite or the Grand Canyon? Right? Do people work in Yosemite and the Grand Canyon do they attenuate? They’re like “oh, yeah, like another horizon.”","offset":2701,"duration":11},{"text":"Dacher Keltner: I don’t know, you know, working with rangers right now and they I think I think the big expansive forms of awe that those places provide is attenuated but I think they’re still finding it in subtler ways. Yeah, that’s really interesting and, you know, it’s interesting I was uh I’ve been privileged to know Pete Docter at Pixar for 15 years and worked on some of his films, Inside Out and Inside Out 2 and Soul.","offset":2712,"duration":26},{"text":"Andrew Huberman: You played a big role in that.","offset":2738,"duration":2},{"text":"Dacher Keltner: Yeah, and through this science of emotion. And I was like, you know in one of our conversations I was like “tell me about some techniques for producing awe in children’s films, animated films” and he described first just what you said like, you know, the film is narrow like a certain kind of attention, you know sort of sympathetic, fearful, checking things, and then boom it comes it suddenly you see the vastness of something and it’s true, it is awe inspiring.","offset":2740,"duration":28},{"text":"Dacher Keltner: When you think about it neuroscientifically as a very basic form of awe is shifting from small to vast in terms of vision and perception and then it becomes metaphorical, right? It’s like “god I’m thinking about” like I love one of the wonders of life that uh that makes us feel awe is big ideas and epiphanies and very often people will be like “god I’ve been working so hard at this, you know working on a a paper, something in technology or some part of my life” and then you suddenly realize it’s part of something large, right?","offset":2768,"duration":32},{"text":"Dacher Keltner: One of the musicians that I interviewed, Yumi Kendall, in the book in the chapter on musical awe said, “you know” she’s a cellist for the Philadelphia Symphony said, “you know I practice for five hours a day, it’s hard man and it’s small and narrow and where’s my finger? and then when I’m on stage and I and I feel the notes go out into this space”, the vastness you’re talking about, “I feel like I’m part of history”, right? And I tear up and cry.","offset":2800,"duration":29},{"text":"Dacher Keltner: Um so I think your I think I you gotta send me those papers Andrew because I think it’s fundamental which is from small to vast. And in fact we did this really cool study with Virginia Sturm at UC San Francisco Brain Health, old people go out on an awe walk once a week for eight weeks, 75 years old or older, and all we asked them to do is to go from small to vast and how they looked at things, you know. Look at a tree, look at a leaf, go out to the pattern of leaves. It brought them awe and less physical pain uh over eight weeks and now we’re finding six years later better brain health, right? So small to vast is a big part of it.","offset":2829,"duration":20}],"startTime":2105},{"title":"Sponsor Break: AG1","summary":"Andrew Huberman reads a sponsor message for the AG1 nutritional supplement.","entries":[{"text":"Andrew Huberman: As many of you know, I’ve been taking AG1 for nearly 15 years now. I discovered it way back in 2012 long before I ever had a podcast and I’ve been taking it every day since. The reason I started taking it and the reason I still take it is because AG1 is to my knowledge the highest quality and most comprehensive of the foundational nutritional supplements on the market.","offset":2849,"duration":24},{"text":"Andrew Huberman: It combines vitamins, minerals, prebiotics, probiotics, and adaptogens into a single scoop that’s easy to drink and it tastes great. It’s designed to support things like gut health, immune health, and overall energy and it does so by helping to fill any gaps you might have in your daily nutrition. Now of course everyone should strive to eat nutritious whole foods, I certainly do that every day, but I’m often asked if you could take just one supplement what would that supplement be and my answer is always AG1 because it has just been oh so critical to supporting all aspects of my physical health, mental health, and performance.","offset":2873,"duration":37},{"text":"Andrew Huberman: I know this from my own experience with AG1 and I continually hear this from other people who use AG1 daily. If you would like to try AG1, you can go to drinkAG1, with the numeral one, .com/huberman to get a special offer. For a limited time AG1 is giving away six free travel packs of AG1 and a bottle of vitamin D3 K2 with your subscription. Again that’s drinkAG1, with the numeral one, .com/huberman to get six free travel packs and a bottle of vitamin D3 K2 with your subscription.","offset":2910,"duration":33}],"startTime":2849},{"title":"Awe, Time, and Consciousness (Continued)","summary":"Following the sponsor break, the discussion on consciousness continues, touching on how shifting perceptual boundaries and connecting to the past plays a key role in experiencing awe.","entries":[{"text":"Andrew Huberman: I didn’t expect that we would land here, at least not so early in the conversation but you know we we’ve had Christoph Koch on this podcast talking about consciousness, you know, incredible neuroscientist and really thinker, I mean I’ve watched his career evolve over the years and and he’s continued to evolve his concepts of how to think about consciousness and uh and you’ll hear nowadays about “oh like maybe consciousness is outside the brain” and I think if nothing else our brains are important components in it, heck yeah I don’t want to do the experiment on myself to find out like if I was decerebrated or something, which basically means having your cortex removed, sorry for the nerd speak.","offset":2943,"duration":37},{"text":"Andrew Huberman: But the idea is connecting through time like in our own lives is a very unique form of awe. So like if I hear a song and it reminds me of when I was like 15 and then all of a sudden all the the mat- as I call it video whatever it is that they wish for is happening there. And so it’s layers upon layers, there’s like a grief component for those of us watching.","offset":2980,"duration":19},{"text":"Dacher Keltner: Well put.","offset":2999,"duration":1},{"text":"Andrew Huberman: But a huge aspect of the of just how touching it is is the fact that like for those moments they’re not thinking about their mortality and no kid should have to think about their mortality right I mean even as I talk about it it’s like uh yeah it’s just it’s like uh there’s an overwhelming in the opposite direction, right?","offset":3000,"duration":17},{"text":"Andrew Huberman: That’s an in particularly uh complicated and and interesting uh case where you’ve got two things colliding, right? Because I feel like awe is so life affirming. Yeah, it is. It is. And uh anyway that’s just an in observation but horizons are something that fascinate me for a long time as a vision scientist because when we see a horizon our visual uh angle widens.","offset":3017,"duration":20},{"text":"Dacher Keltner: That’s cool.","offset":3037,"duration":1},{"text":"Andrew Huberman: We become more parasympathetic. There’s a whole coming off the accelerator of the sympathetic nervous system so we relax by virtue of coming off the focusing component. When we focus in through a tunnel we it’s quite the opposite.","offset":3038,"duration":13},{"text":"Dacher Keltner: Nice.","offset":3051,"duration":1},{"text":"Andrew Huberman: But I feel like there’s something unique to this experience of being in a tunnel, I’m thinking about Yosemite, or in a bunch of trees or hike and then the horizon opens up. Yeah. There’s this transformation of visual space and those moments at least for me are the moments. Like I can hike along a ridgeline for a long time like “this is amazing” but there’s something distinctly bigger in the experience of going from confinement to openness.","offset":3052,"duration":29},{"text":"Andrew Huberman: It could be brought to the lab but do you think that’s what’s going on in in Yosemite or the Grand Canyon? Right? Do people work in Yosemite and the Grand Canyon do they attenuate? They’re like “oh, yeah, like another horizon.”","offset":3081,"duration":11},{"text":"Dacher Keltner: I don’t know, you know, working with rangers right now and they I think I think the big expansive forms of awe that those places provide is attenuated but I think they’re still finding it in subtler ways. Yeah, that’s really interesting and, you know, it’s interesting I was uh I’ve been privileged to know Pete Docter at Pixar for 15 years and worked on some of his films, Inside Out and Inside Out 2 and Soul.","offset":3092,"duration":26},{"text":"Andrew Huberman: You played a big role in that.","offset":3118,"duration":2},{"text":"Dacher Keltner: Yeah, and through this science of emotion. And I was like, you know in one of our conversations I was like “tell me about some techniques for producing awe in children’s films, animated films” and he described first just what you said like, you know, the film is narrow like a certain kind of attention, you know sort of sympathetic, fearful, checking things, and then boom it comes it suddenly you see the vastness of something and it’s true, it is awe inspiring.","offset":3120,"duration":28},{"text":"Dacher Keltner: When you think about it neuroscientifically as a very basic form of awe is shifting from small to vast in terms of vision and perception and then it becomes metaphorical, right? It’s like “god I’m thinking about” like I love one of the wonders of life that uh that makes us feel awe is big ideas and epiphanies and very often people will be like “god I’ve been working so hard at this, you know working on a a paper, something in technology or some part of my life” and then you suddenly realize it’s part of something large, right?","offset":3148,"duration":32},{"text":"Dacher Keltner: One of the musicians that I interviewed, Yumi Kendall, in the book in the chapter on musical awe said, “you know” she’s a cellist for the Philadelphia Symphony said, “you know I practice for five hours a day, it’s hard man and it’s small and narrow and where’s my finger? and then when I’m on stage and I and I feel the notes go out into this space”, the vastness you’re talking about, “I feel like I’m part of history”, right? And I tear up and cry.","offset":3180,"duration":30},{"text":"Dacher Keltner: Um so I think your I think I you gotta send me those papers Andrew because I think it’s fundamental which is from small to vast. And in fact we did this really cool study with Virginia Sturm at UC San Francisco Brain Health, old people go out on an awe walk once a week for eight weeks, 75 years old or older, and all we asked them to do is to go from small to vast and how they looked at things, you know. Look at a tree, look at a leaf, go out to the pattern of leaves. It brought them awe and less physical pain uh over eight weeks and now we’re finding six years later better brain health, right? So small to vast is a big part of it.","offset":3210,"duration":21}],"startTime":2943},{"title":"Music as a Catalyst for Awe","summary":"Keltner reflects on growing up in Laurel Canyon surrounded by iconic musicians. They discuss how music serves as a tonal language of emotion and identity that connects people to something larger than themselves.","entries":[{"text":"Andrew: And I think it was just you know the I just got the adrenaline back. And there's a little bit of you don't know what it is going to happen and it feels a little dangerous, but it's mostly benevolent and um it's an irreplaceable feeling and and I think about it sometimes uh I think about a lot of the time.","offset":3231,"duration":20},{"text":"Dacher: Yeah, and you know, thank you. And I, you know, when I was writing this book on awe, some forms of awe, you know there are eight wonders that give us awe, you know, some are you kind of understand them, nature's pretty straightforward, spirituality, meditation, you know. And music and your description of it exactly exactly captures how rich it is and complicated.","offset":3251,"duration":23},{"text":"Dacher: Which is there is something about that sound and the acoustic patterns that come through your eardrums and head into your auditory cortex and you give it meaning and suddenly you're remembering things and bonding with people and insta-friends, like you said, for life. You know, brothers and sisters almost that and you're like this is what life's about.","offset":3274,"duration":25},{"text":"Dacher: And Susanne Langer, a philosopher, really got it right. She's like music is this tonal language of emotion and identity. And awe in music, very fitting with our conversation, is when those sounds come into you, move you, and connect you to something that is what you care about in life. You know, I remember I grew up I was very lucky to grow up in Laurel Canyon in the late 60s and there was more music there than I almost anywhere in human history.","offset":3299,"duration":34},{"text":"Dacher: You know, from you know, the Mamas & the Papas and Frank Zappa and Jim Morrison was living there.","offset":3333,"duration":6},{"text":"Andrew: Jim Morrison was out there.","offset":3339,"duration":1},{"text":"Dacher: And the Doors, and the you know, Bob Dylan was passing through, and the Birds, it's a joke, you know. It was everywhere.","offset":3340,"duration":6},{"text":"Andrew: That's wild just to think about how much incredible music was being created.","offset":3346,"duration":5},{"text":"Dacher: Oh man, you know, the Beach Boys were, you know, at I mean weren't Fleetwood Mac back in Topanga. Yeah. I mean it was like and I was eight and nine and just a you know, to grow up on Bob Dylan. And when I saw the recent film with Timothée Chalamet, I start crying, you know I was just like this is life, you know.","offset":3351,"duration":20},{"text":"Dacher: Yeah, and so that's why we study awe, you know. It it and and you know music is one of our great technologies. Uh, there's now research showing it's good for chronic pain. I think it's a frontier in healthcare and, you know, just giving people contemplative meditative approaches to music and and awe is part of the answer.","offset":3371,"duration":22},{"text":"Dacher: And you and I shared yet another thing, Andrew. You know, when I uh grew up in the foothills of the Sierras as a teenager, Ted Nugent and you know this poor white you know area, Ted Nugent, AC/DC, and that's all fine. And when I first heard the Sex Pistols in I was lucky to be in England when Never Mind the Bollocks came out and I was in a working class fighting town and I heard that.","offset":3393,"duration":29},{"text":"Dacher: I was like that's it. And then that led me to Iggy Pop, who's one of my moral heroes. So you know, um...","offset":3422,"duration":7},{"text":"Andrew: Amazing. Who's really into Qigong apparently. I heard him like years ago on the radio and and someone was asking him like how does he stay in such good shape and he's just does tons of Qigong breathing.","offset":3429,"duration":10},{"text":"Dacher: Yeah.","offset":3439,"duration":1}],"startTime":3231},{"title":"Transcending Language Through Physicality","summary":"Huberman brings up martial arts and sparring as deeply bonding, non-verbal experiences. Keltner compares this to mosh pits, highlighting how intense physical encounters can create transcendent connections.","entries":[{"text":"Andrew: Wild, wild, wild. You know, it's interesting because a lot of music has lyrics and a lot doesn't. But there's something that feels kind of um divorced from language about the experience that we're talking about even though there's lyrics tied in there. And what brings that to mind is there's a really good book, one that I like anyway, um called A Fighter's Heart by a guy named Sam Sheridan.","offset":3440,"duration":24},{"text":"Andrew: His wife actually wrote that movie Monster um with Charlize Theron, I think is uh the actress that played her. And uh and I don't know Sam but but there's this description of all these different martial arts forms and he explores them all and um there's this great line in there.","offset":3464,"duration":16},{"text":"Andrew: Because I've done a little bit of boxing um and sparred a bit. I don't recommend as a neuroscientist how can I recommend it, right?","offset":3480,"duration":9},{"text":"Dacher: Yeah, what were you doing?","offset":3489,"duration":1},{"text":"Andrew: You get hit. Oh, I was and that was actually in my 30s. But anyway, I was working some stuff out. But uh do not recommend uh the sport yeah, the training yeah, but you don't want to get hit in the head. Not good for your brain whatsoever. But he talks about how um fighting with someone, sparring or a fighting with someone is uh he said it's like a it's one of the most bonding experiences that you'll ever have because you're in this primitive non-language state.","offset":3490,"duration":25},{"text":"Andrew: Yeah. I mean he actually likens it to a one-night stand. He says something like, oh you know you're sharing bodily fluids with somebody that you barely know but you you feel connected you know. So I don't know if that's the best certainly not the most politically correct uh way of put it.","offset":3515,"duration":16},{"text":"Dacher: Definitely.","offset":3531,"duration":1},{"text":"Andrew: But I understand what he's talking about, right? You're you're in this moment of you're both vulnerable. In the case of the fighting, you're both vulnerable, you're both trying to hurt each other, you're also obeying some rules, right? It's not not an anything goes.","offset":3532,"duration":14},{"text":"Andrew: And he talks about how it transcends language. And that creates a forever bond. And it's true, right? I didn't do a ton of sparring but you have a respect. Yep. You went through something hard together even if it's only three three-minute rounds. Like that's a it's real. But it's separate from language. And earlier we were talking about the exper- the experience of emotion as this kind of triad of the feeling, the motor component to it, and language, but I do think that maybe the language piece can go.","offset":3546,"duration":33},{"text":"Dacher: I'm with you in some sense. Darwin wrote about the motor components, got a lot of it right, William James was about the body, you know, and the physiology, and you know, language is what we rely on as social scientists, but it I think it's as William James said when he tried to describe his experience of transcendence uh when he took laughing gas and it led him down the path to understand spirituality.","offset":3579,"duration":26},{"text":"Dacher: He's like words are tattered fragments. They they barely touch the real thing. Um, yeah, and and I just want to dwell for a moment, you know, part of awe and I learned this like talking to veterans, you know, and I I did work with Stacy Bare and we did this Sierra Club research getting veterans out on the rivers.","offset":3605,"duration":19},{"text":"Dacher: And he's one of my heroes in the book of getting helping tens of thousands of veterans to find their awe in nature, you know. And these are guys who've lost limbs and they're rock climbing, you know, and it's just like like there's a lot of awe when you're right at the edge of life and there's violence and and there's a lot of horror, carnage, etc. but there's awe.","offset":3624,"duration":19},{"text":"Dacher: Uh, and I love your idea and and I think any teacher of the of the martial arts would say that's the point, is that we can transcend death or violence by martial arts, by performing them and uh and putting them into a contemplative form for the body.","offset":3643,"duration":22},{"text":"Dacher: One of my favorite movies, if not my favorite movie, is Raging Bull, man, and Martin Scorsese, like Jake LaMotta and Sugar Ray have these epic battles and they look at each other, you know, in one of the great scenes, and they're just like we're united. This is all we're way beyond the fight, you know.","offset":3665,"duration":21},{"text":"Dacher: I think you're right. I think it's part of this transcendent moment that of people crashing into each other. Mosh pits. They are one of my favorite objects of study in awe. And mosh pits have a law, a set of laws to them.","offset":3686,"duration":18},{"text":"Andrew: Yeah, people have studied like the physics or the physics.","offset":3704,"duration":2},{"text":"Dacher: Yeah, no, it's like and you think you're crashing and you are, you're bruising yourself, you know, but there's something transcendent there about what we find.","offset":3706,"duration":10},{"text":"Andrew: I could be wrong, but I think um Raging Bull, I think the the soundtrack was Clash inspired. Was it? There's something about it in the documentary which I highly recommend, uh called The Future Is Unwritten, which is the Joe Strummer thing where some there's some link up between The Clash. I think Scorsese says, you know, The Clash inspired the soundtrack to Raging Bull or something like that.","offset":3716,"duration":19},{"text":"Dacher: Really?","offset":3735,"duration":1},{"text":"Andrew: Anyway, he's a big Clash fan, so um or yeah. So...","offset":3736,"duration":3}],"startTime":3440},{"title":"Moral Beauty & Joe Strummer","summary":"Huberman explains why Joe Strummer of The Clash is one of his moral heroes. They explore how Strummer communicated profound, authentic emotion that transcended pure language.","entries":[{"text":"Dacher: All right, Andrew, I get to ask you one more question.","offset":3739,"duration":2},{"text":"Andrew: Yeah, yeah.","offset":3741,"duration":1},{"text":"Dacher: So why is Joe Strummer a person of moral beauty to you? One of the sources of awe is we're amazed by people's courage and strength and kindness and justice. So why Joe Strummer?","offset":3742,"duration":10},{"text":"Andrew: Oof, man. All right, I'm going to try and keep this brief. Um, I mean just to give you a sense of how what an impact he's had on me. I mean, I've always worn these button-down black shirts even before I was public-facing, uh because I saw him do a show, um a Mescaleros show. I wasn't there, but he and by the way, Joe Strummer and the Mescaleros I actually think is better than The Clash.","offset":3752,"duration":26},{"text":"Dacher: Wow.","offset":3778,"duration":2},{"text":"Andrew: Clash was a short run. It was only five years. Yep. Only five years, pretty much, and then they're done. So it was 101'ers, Clash and then and then he came back with the Mescaleros and just incredible. I mean, they're masterpieces. Yep. Produced in part by my friend Tim Armstrong here on Hellcat Records.","offset":3780,"duration":14},{"text":"Andrew: He went to a small label. Um, he also sang songs with Johnny Cash for with Rick Rubin. I actually know the story of that because I'm friends with Rick and I insisted on him telling me the story. So sometime I tell you that. But I mean masterpieces late in life. And there was a show that that Strummer played where he was wearing his black button-down soaking in sweat, like soaked in sweat.","offset":3794,"duration":22},{"text":"Andrew: And he just wouldn't take the thing off. I think he might have rolled up like one cuff. And I was like that's punk as fuck. I was like that guy is so rad and he was in his he died at 50, we're the same I'm 50 now. He died at 50. I go see the mural of him right off um it's right off Tompkins Square Park uh in Alphabet City every time I'm in New York just go like see it. Where the aviator says future is unwritten. You can go there pay your respects.","offset":3816,"duration":23},{"text":"Andrew: I've talked to Rick about this a lot. Like what was it about him? Because they were close friends. And I never met Strummer. But I think there's three reasons. One is um he had that Bob Dylan-like ability to write lyrics that you're not especially with Mescaleros where you're not really sure what the song's about, but it makes sense, not just because it's beautiful but you feel like he's tapping into something more fundamental than what the lyrics are actually saying.","offset":3839,"duration":26},{"text":"Dacher: Beyond language. The theme we're talking.","offset":3865,"duration":2},{"text":"Andrew: Yeah, like a great song um for instance would be like On the Road to Rock 'n' Roll. Like that could be about on being on tour or something, but it it transcends something obvious.","offset":3867,"duration":10},{"text":"Dacher: Nice.","offset":3877,"duration":1},{"text":"Andrew: The other thing is is the way he he uh used his breath was um like there was a his intonation is like unparalleled. Yep. And then Rick was the one who really helped me understand, because during the summer I go hang out with Rick whenever I can. And winter too. Um, and we watch documentaries, including Clash documentaries.","offset":3878,"duration":22},{"text":"Andrew: And I asked him I was like what was it? Like why does he have this thing? Because he said these incredible things, you know. He would say things like, you know, you got to bring humanity back into the center of the and those are really beautiful quotes. But like a lot of people give beautiful quotes.","offset":3900,"duration":15},{"text":"Andrew: And Rick in very Rick Rubin style said, everything he said he brought his whole life experience into those statements. And I was like just the statements like the quotes, you know like the you know we got to bring the humanity back into the the and he goes no everything he said. It was like you got the sense that he was bringing all of himself to it even if he was being kind of quiet.","offset":3915,"duration":24},{"text":"Dacher: That's cool.","offset":3939,"duration":1},{"text":"Andrew: And I go, okay, so this is clearly on a plane of understanding that I can't put language to, right? What does that even mean? That's like half the things Rick says, it's like a riddle mixed up in a poem, you know put out there as you know as a as like a as a principle and you're just like what the hell's that mean? But it feels true.","offset":3940,"duration":18},{"text":"Andrew: And I think that, you know, and and Rick's superpower,","offset":3958,"duration":1},{"text":"Dacher: Yeah.","offset":3959,"duration":1},{"text":"Andrew: is that Rick knows what a true feeling feels like. Yeah. And he knows what a false feeling feels like. And he's only interested in truths, period.","offset":3960,"duration":13},{"text":"Dacher: And that's the challenge of the science that I'm part of is exactly that. It's like there are all these layers to meaning and representation and, you know, and we try to figure out true moments of awe with all of our measures and and it is this like it's all coming together as a uh a package that tells us it's happened.","offset":3973,"duration":19}],"startTime":3739},{"title":"Narcissism and the Enemies of Awe","summary":"The discussion turns to the inhibitors of awe, specifically self-focus, narcissism, and drugs like cocaine that promote ego. Keltner explains how modern society's obsession with the self undermines our ability to feel awe.","entries":[{"text":"Andrew: So we can think about things that promote awe, the awe walk, going small to large aperture maybe back again. Like I guess we shouldn't assume that it's unidirectional. You know, coming back into our home after something big is there's nothing like that, right?","offset":3992,"duration":14},{"text":"Dacher: Ah!","offset":4006,"duration":1},{"text":"Andrew: The dog, the kids, the the spouse, the whatever, you know, like the those little thing, the plants even you know the the the you know, so it runs both ways. It's no fun, but we should probably talk about some of the inhibitors of awe. Because as I step back from what we're talking about today and I think okay language, it can be part of it but it can also in molecular biology or genetics we call it a dominant negative.","offset":4007,"duration":24},{"text":"Andrew: It's like a gene that basically suppresses a set of functions. A ton of stuff. And there's a joke around molecular labs and neuroscience labs that you'd be like that person's a dominant negative, you know. I now have a new phrase I can use. Yeah, yeah, you don't want to be called a dominant negative. Um, I call people that in my head a lot online.","offset":4031,"duration":17},{"text":"Andrew: I go, oh man that person's a dominant negative, they're not contributing to the greater good, they're just like so there's, you know, language can be that, um or be neutral or be positive but can definitely be that. And then there's something about being over-identified with self.","offset":4048,"duration":20},{"text":"Andrew: You know, I so on the recommendation of Tim Armstrong, someone you wouldn't associate with the Grateful Dead, he was like, \"You gotta listen to the Grateful Dead!\" and I was like, what? This is Tim, the Tim Armstrong Transplants, Rancid, Operation Ivy, telling me I should listen to the Grateful Dead. He's big great he's a huge music fan of all sorts of things.","offset":4068,"duration":18},{"text":"Andrew: I said why? And he said uh he said, \"They're punk rockers.\" And I said how what are you talking about? And he said he said, \"Yeah they they played a different show every night.\" That's how they're I'm not going to keep doing his I can do a pretty decent Tim for those...","offset":4086,"duration":16},{"text":"Dacher: Nice.","offset":4102,"duration":1},{"text":"Andrew: uh but apparently they're the the people that followed them, that was a big part of it. It was all all new, right? Every show was unique. Started getting really into listening to the Grateful Dead in the last couple years and then I started listening to documentaries, biographies of them. And there's this amazing moment in one of them, I can't remember which where somebody says what killed it?","offset":4103,"duration":28},{"text":"Andrew: What killed the collective of music? Like that that feeling? And uh the answer someone gave was cocaine. And then the question was why cocaine? Yep. And someone said because cocaine's all about me. It's the me drug. So I was like, whoa, I'm a neuroscientist so I can tack that to you're talking about dopamine and adrenaline. And it's when dopamine and adrenaline are elevated that's a very I mean amphetamines especially but it it becomes a me thing.","offset":4131,"duration":35},{"text":"Dacher: Yeah, that's true.","offset":4166,"duration":1},{"text":"Andrew: Every idea that's mine is the thing that needs to happen. It's the important thing. If not out there, it needs to hap- like that's the only thing that matters. Very different than cannabis, very different than psychedelics, very different than just the sober experience where it's kind of a downer, but then the non-intoxicated experience of just being with the music no substances.","offset":4167,"duration":20},{"text":"Andrew: So I'd love your thoughts on how certain chemical states and but more broadly how me-ness self-interested states are a dominant negative for awe.","offset":4187,"duration":11},{"text":"Dacher: That was the best entrance into that question I've ever encountered. You know, it's amazing Andrew. You know, I grew up for three years formative years in Laurel Canyon '68 to '70 and then we moved to the foothills of the Sierras in Northern California and it was peak Laurel Canyon, Joni Mitchell and the Birds and the Beach Boys and you know, it's just","offset":4198,"duration":21},{"text":"Andrew: Jealous. Envious in a positive way.","offset":4219,"duration":2},{"text":"Dacher: When my brother passed away and he was my brother of awe, you know 14 months younger and I was in this reflective period, I started reading a lot about Laurel Canyon and they made the same point which is kind of things shifted after we, you know, in the early '70s. And the historian said it's cocaine.","offset":4221,"duration":21},{"text":"Dacher: That it moved from, you know, marijuana and mushrooms and psychedelics a bit but really, you know, people playing music, you know, Joni Mitchell or Graham Nash or whomever it is. And then suddenly cocaine comes and the the whole spirit changed.","offset":4242,"duration":15},{"text":"Dacher: Yeah, I think the great enemy of awe is me-ness is what Ralph Waldo Emerson who was one of our great writers of awe, you know, he has this moment out in nature cold day in Massachusetts sees this forest and he you know he's like standing on the bare ground my head bathed by blithe air and uplifted into infinite space.","offset":4257,"duration":22},{"text":"Dacher: And there's that uplift that you described earlier of awe. All mean egotism vanishes. And that's all, you know. Awe quiets the self. And when you look at where we are, you know, Jean Twenge, you know, longitudinal data, we're more self-focused, you know.","offset":4279,"duration":23},{"text":"Dacher: We're taking a quarter of the pictures that we take are of the self. It's preposterous! It's pretty crazy. It's half of the photos we take are of the self or the self with another person or another thing. It's perverse, you know. Uh, the world has become more narcissistic. We're led by narcissists.","offset":4302,"duration":19},{"text":"Dacher: It's been, you know, it's just taken as a default and it's not a default. It's a it's a corruption of of our minds. Because the mind, as you described earlier, is very good at looking at other people, at making eye contact, at seeing their beauty, at hearing their words, at looking at collectives, discerning patterns of nature, collectives, and all of that works against awe, right?","offset":4321,"duration":25},{"text":"Dacher: That you know, if I am focused on myself I'll feel less awe, if I am worried about my striving in society or my bottom line in my bank account, you know, or thinking about money, it countervails awe. So yeah, I I think, you know, that's why awe's important for our times. We are in this for various reasons, this period of too much self-focus.","offset":4346,"duration":28},{"text":"Dacher: Uh, it's costing young people, it makes them anxious, you know, and they got to they got to they got to go dance, they got to hear some music, they got to share stuff and go backpacking or whatever it is, you know, and just to get out of the self.","offset":4374,"duration":14}],"startTime":3992},{"title":"Sponsor Break: Function","summary":"Andrew Huberman reads a sponsor message for Function lab testing.","entries":[{"text":"Andrew: I'd like to take a quick break and acknowledge our sponsor, Function. Function provides over 160 advanced lab tests to give you a clear snapshot of your bodily health. This snapshot gives insights into your heart health, hormone health, autoimmune function, nutrient levels, and much more. They've also recently added access to advanced MRI and CT scans.","offset":4388,"duration":21},{"text":"Andrew: Function not only provides testing of over 160 biomarkers key to your physical and mental health, it also analyzes these results and provides recommendations for improving your health from top doctors. For example, in a recent test with Function, I learned that some of my blood lipids were slightly out of range. As a result, I decided to start supplementing with nattokinase, which can naturally help reduce LDL cholesterol, and it did.","offset":4409,"duration":23},{"text":"Andrew: In a follow-up test, I could confirm that this strategy worked, my blood lipids are now back where I want them in range. Comprehensive lab testing of the sort that Function offers is so important for health, and while I've been doing it for years, it's always been overly complicated and expensive. But now with Function, it's extremely easy and affordable. To learn more, visit functionhealth.com/huberman and use the code Huberman for a $50 credit towards your membership.","offset":4432,"duration":27}],"startTime":4388},{"title":"Sports as Collective Awe","summary":"Keltner and Huberman discuss the profound emotional and communal elements of sports fandom. Rooting for a team serves as a secular religion, providing fans with shared rituals and collective effervescence.","entries":[{"text":"Andrew: The example you gave of sports earlier I think is is an important one um only because I think some people not me, but some people will all right I don't really want to go camping or backpacking. I do. I spend as much time in Yosemite as I can. The dancing, concert, you you maybe that's not for them.","offset":4459,"duration":17},{"text":"Andrew: I do think I'm not a big professional sports fan. Um, I like a few things, but but it is kind of interesting to put this lens on like when I see a game, one of our members of our podcast team that's not here today is like just obsessively excited about professional football and uh Seattle Seahawks.","offset":4476,"duration":20},{"text":"Andrew: So this was a big year for him. And I have to believe that when he goes to see his favorite team play in the Super Bowl and win the Super Bowl that it's not just about his relationship to his team and it's about it's about being a kid and and everyone else there in a Seahawks jersey is like they have to they must feel a connection because they presumably the super fans know that the other super fans know the history, they know how important this is, they know all the trials and tribulations of the team and on and on.","offset":4496,"duration":30},{"text":"Andrew: And so it's um gosh, it's so different. I'm just realized like it's the it's the furthest thing from like doing a PhD in the sciences. The folks doing a PhD in the sciences is a lot of fun, it's a hell of a lot of work. And there's nothing else quite like it. I it's irreplaceable, I wouldn't redo it for in any other way. But it is a very like you're it's a very solitary thing.","offset":4526,"duration":22},{"text":"Dacher: It is.","offset":4548,"duration":1},{"text":"Andrew: Like you don't even cross you cross finish line, your advisor's there, your family comes but it's like it is a tunnel like this big. Going to the Super Bowl to watch your favorite team play is you're going through that tunnel with you know millions of people.","offset":4549,"duration":16},{"text":"Dacher: One of the joys of awe science, you know, we gathered stories of awe from 26 countries. And it's one of my favorite parts of this research. And this is like India and Brazil and Poland and Chile and Mexico and Japan and Korea and South Korea and Russia. And we everybody.","offset":4565,"duration":16},{"text":"Dacher: We brought them in, got these stories and you know like what is vast and mysterious? What gives you goosebumps? What's amazing or awesome to you? And when you get stories from Brazil or Argentina, they're going to write about so they they're going to tell you about football, you know.","offset":4581,"duration":16},{"text":"Dacher: And, you know, when you get stories from parts of the United States they're going to talk about you know American football and baseball. You get stories from Boston it's there's going to be a Red Sox story.","offset":4597,"duration":12},{"text":"Dacher: And we have not studied sports in my emotion science because most emotion scientists are not good athletes. They're picked last in grammar school. They're grouchy about sports. And yet it's super emotional.","offset":4609,"duration":13},{"text":"Dacher: And I will tell you a story that has science and uh personal wisdom. Uh, as I I gathered these stories like God, you know, part of collective effervescence just like Taylor Swift or being in a punk mosh pit is also sports. And and just like uh it is awesome to follow a sports team and be there live.","offset":4622,"duration":26},{"text":"Dacher: And there's this great obscure sociology paper that said being a fan of the Pittsburgh Steelers is like being in a religion. Because you have your rituals, they have these towels they they sing around, you think of yourself as the Steeler nation, they talk about godlike experiences on the field, they have these spiritual moments where in freezing days they'll take off their clothes and cheer and cry together.","offset":4648,"duration":25},{"text":"Dacher: Um, and I was teaching this recently and there were two Steeler fans in the audience. And they were like that's exactly it. But I'll tell you more like everywhere you go if you're a fan a Steeler fan there are Steeler bars that you can go to.","offset":4673,"duration":16},{"text":"Dacher: And when the Steelers play they're going to be Steelers fans and if you're a kid and the Steelers lose somebody who's old will tell you I remember when we lost in 1983 and we'll recover we'll you know have this expansion of time. It was so rich to me, you know.","offset":4689,"duration":14},{"text":"Dacher: It's like we love sports, you know. Sports the Olympics are old, they're 3,000 years old. The ball court games in the Maya you know in the Mayan traditions are were amazing ways to gather community and and become collective, right? So, you know, uh it was really eye-opening for me just to sense the awesomeness of sports.","offset":4703,"duration":25},{"text":"Dacher: And one of my great joys of writing the book was to talk with Steve Kerr, who was coaching the Warriors at the time. He's a righteous guy, you know. Uh, he is a person of truth and just getting his sense of like how awesome it is to I mean for him to coach a game and the Warriors were in this amazing period and look up into the stands and 10,000 people are dancing because of your coaching, you know, I was like that's pretty good.","offset":4728,"duration":28},{"text":"Andrew: Yeah, he's really tapped in, isn't he? He's a meditator and wildlife experience and...","offset":4756,"duration":7},{"text":"Dacher: And trauma early, you know, his dad losing his dad.","offset":4763,"duration":4},{"text":"Andrew: Yeah.","offset":4767,"duration":1},{"text":"Dacher: And and that orienting him to what really matters.","offset":4768,"duration":3}],"startTime":4459},{"title":"Community Health & The Social Media Dilemma","summary":"They explore how communal wellness practices like saunas combat the modern epidemic of loneliness. Keltner highlights the severe health costs of isolation and the challenge of designing social media platforms to foster true connection.","entries":[{"text":"Andrew: I'm thinking about the things that inhibit awe, but I'm also thinking about solutions.","offset":4771,"duration":5},{"text":"Dacher: Yeah.","offset":4776,"duration":1},{"text":"Andrew: You know, it's springing to mind that you know, uh it's it's funny sometimes I get tacked to like ice baths for some Well, folks, that was Wim, right? I mean, that was Wim. I mean, sure, I've done some cold plunges, I like I do the cold.","offset":4777,"duration":10},{"text":"Dacher: I gotta do them. It sounds good.","offset":4787,"duration":2},{"text":"Andrew: Yeah, it's fun. I mean, you know, it it's psychologically painful and you feel better afterwards and um it'll make you it'll make anyone mentally stronger because cold is a universal stressor. Um, but you know, it it gets kind of a bad rap because mostly because people don't like doing it. Everyone loves the sauna. It's kind of funny.","offset":4789,"duration":18},{"text":"Andrew: Everyone's cool with sauna. And the Finns love the sauna, and it's a social thing for them. And one thing that I think has been overlooked and it just sprang to mind now. Um, so I overlooked it as well is that you know there's this thing that's wonderful about experiences that we can have with other people, but that we can also do on our own and when we do them on our own we know other people are doing it on their own too.","offset":4807,"duration":23},{"text":"Andrew: And so it's it's kind of a it's a different version of what we've been talking about. And you know, the quote-unquote health and wellness community they take some heat like people oh it's all about supplements, all about cold plunges, you know and I've got a like a like a particular finger I hold up when I hear that. But it's not about that.","offset":4830,"duration":18},{"text":"Andrew: There's this deeper layer that's much more important that's formed over the last I would say 5 to 10 years, because it used to be meditation, breathwork, Esalen, great love Esalen, like amazing but incredible place.","offset":4848,"duration":11},{"text":"Dacher: Historic.","offset":4859,"duration":1},{"text":"Andrew: Historic and many important things actually happened there that people don't even realize in terms of shifting world politics and world peace that maybe some","offset":4860,"duration":8},{"text":"Dacher: Oh my god, yeah! You brought the Russians in there for instance.","offset":4868,"duration":6},{"text":"Andrew: But you know so it used to be these isolated pockets, but now, you know, people get together to sauna, people get together to do breathwork, people get together to cold plunge. And of course for thousands of years humans have been doing this. This is not a new thing. And people look at that and they go this is wacky or it's about the marketing of this.","offset":4874,"duration":17},{"text":"Andrew: Actually, I I think that there's a connection that's formed among people who want to take good care of their health, they want to have some control over their state, um because otherwise the world will take control of it for you. Yep. And meditating is a very solitary experience for most people. So there's something pretty nice about going to a banya. I love banyas, Russian banyas, and then also doing the sauna on your own or cold plunge on your own.","offset":4891,"duration":25},{"text":"Andrew: And I think that what it builds is a community that is linked on social media. So from now on when I see people doing things that I go oh cool like I like a bit of that I don't maybe do it every day or I do that every day too get see my morning sunlight. The notion that there's a community being built. That was the original intention of social media.","offset":4916,"duration":16},{"text":"Andrew: And so I think social media can have this dominant negative effect on awe and day-to-day experience. So a question is are there ways? Surely there are, but how how could we build more of a sense of of like this communal feeling leveraging what people are already doing? They're already on their phones and scrolling. Hopefully they're also doing things to benefit their health. To make them feel less isolated because as Jonathan Haidt and others have pointed out quite correctly, it can really fracture us into the the the me, the ego version where it's but it's kind of the perfect venue to connect people also.","offset":4932,"duration":39},{"text":"Dacher: It is. I agree.","offset":4971,"duration":1},{"text":"Andrew: So I don't expect you to come up with any answers right on the on the fly, but I feel like it's not going anywhere. So how how could we build or glean a more sense of a community through things that we're doing actually doing in our daily lives? Is I think a question that's worth exploring.","offset":4972,"duration":16},{"text":"Dacher: Profoundly important. You know, um the you know and the preceding question is like what are the enemies of awe? What gets in the way or the the barriers? And and you just nailed a couple is you know online life. You know and I think Jonathan Haidt is right that it's not only anxiety-producing but we don't think about the opportunity costs of like it deprives me of awe, you know.","offset":4988,"duration":27},{"text":"Dacher: And in our study of 2,600 people around the world of what makes them feel awe, no one ever said being on Meta or Facebook or, you know, or uh, you know, or Instagram. There are a couple reason worries I have about online life and I'm kind of working on this now. You know, and one is is the content itself, which is, you know, it's been algorithmically designed.","offset":5015,"duration":28},{"text":"Dacher: I was at Facebook when some of those algorithms I was advising there were set in place of like making people hate each other and not demonstrate all of our all the wonderful things about human beings, which are um ample. And then online life disrupts sharing and the technologies of today have disrupted sharing. So we don't share music like we used to share. We used to listen to music together.","offset":5043,"duration":24},{"text":"Dacher: That's down. Going to movies is down 40%, right? That used to be a very important collective cultural experience. Did you see the latest Scorsese or Pixar or whatever? Now it's streaming, right? So I really worry about that. And I think the next challenge in in the technological world in the new the social media and the platforms is is like you said, how do you enable the sharing of experience? Um, you are absolutely right.","offset":5067,"duration":31},{"text":"Dacher: A lot of what we do for our bodies and the wellness space has a massively important community basis to it. where suddenly you're not, you know, meditating and breathing but you're also sharing your mind and your experience. You're not, you know, listening to music you're sharing an understanding of the music together and its cultural history.","offset":5098,"duration":24},{"text":"Dacher: One of my favorite examples is farmers' markets. They were nonexistent in the '90s, right? And they used to be very common in American culture and now there are 9,000 farmers' markets growing. And yeah, people go to buy kale and get the honey and you know the fresh bread or whatever, but they're also going because it's community. It's profound community. Uh, and we derive a lot of benefits from that. Profound benefits. 10 years of life expectancy, community.","offset":5122,"duration":29},{"text":"Andrew: 10 years?","offset":5151,"duration":1},{"text":"Dacher: 10 years.","offset":5152,"duration":1},{"text":"Andrew: My goodness! There's so much obsession these days around what sport allows you to live the longest? Turns out it's like pole vaulting which most people aren't going to do. Um, sprinting, gymnastics. Stuff that involves a lot of jumping and landing.","offset":5153,"duration":11},{"text":"Dacher: Is that right? Really?","offset":5164,"duration":1},{"text":"Andrew: And and fast twitch activity. Yeah. I mean there are a bunch of other features there about like who's biased to go into those sports and whatnot. But I mean I think it's in keeping with this idea that like getting your heart rate way way up and moving quickly as as quickly as you safely can like once a week at something is probably a good idea.","offset":5165,"duration":15},{"text":"Dacher: Cool.","offset":5180,"duration":1},{"text":"Andrew: But the greatest benefit seen there is something like five to eight years. So you're talking about a 10-year benefit?","offset":5181,"duration":6},{"text":"Dacher: 10 years. And that's a meta-analysis of 350,000 participants. So that's that you can go to the bank with that. Like social community very good for the body. I think it's the greatest challenge of our our social media and our our platforms. And I've advised at Facebook 2010 to 2015, Google, Pinterest, a little bit of Apple, and I keep telling them like, you know, this is the singular challenge.","offset":5187,"duration":24},{"text":"Dacher: And it's so it's hard. It's, you know, a technologies are asynchronous. You know, \"Hey I send you a text\" and 18 hours later I hear from you. You're not making eye contact. The visual connection is degraded. You know, Steve Pinker observed rightly so, like when I'm on Zoom I have to look at the down to see the camera or whatever or I look at the screen, so my eye contact is going down.","offset":5211,"duration":24},{"text":"Dacher: I'm not making eye contact like we are. It's just the technology works against it. And I think it's the hard problem of the social media platforms is can they do what you're aspirationally asking for which is like get us to feel connected? Um, you know, Mark Zuckerberg's original statement about Facebook was open and connected. Um, and I think they failed. And I think we got to we it's it's the challenge of our times.","offset":5235,"duration":34},{"text":"Andrew: I know Mark a bit and I think I know you know I trust he wants that.","offset":5269,"duration":5},{"text":"Dacher: I know.","offset":5274,"duration":1},{"text":"Andrew: I really do. I know some people will will push back on that statement, but I actually know that he wants that. And I know some of the folks in the leadership at Instagram they want that. Like these people actually have very healthy personal lives. They understand the value of connection both at the level of the family, friendships, but also um at large. They they want that.","offset":5275,"duration":25}],"startTime":4771},{"title":"Awe Design in the Modern World","summary":"Keltner discusses his work with architects to build 'Cities of Awe' by incorporating nature, art, and communal spaces. They consider whether technology can be leveraged to expand our temporal and visual apertures.","entries":[{"text":"Andrew: I think that maybe I'm being optimistic here, but maybe AI will offer an opportunity for that as opposed to divorcing us from um gathering and and seeing facial expressions and hearing of voices together or observing other things. You know, the I do think that right now the way that most social media experiences land is the exact opposite of awe.","offset":5300,"duration":25},{"text":"Andrew: I will say that. Because and I can say that with a fair degree of certainty because I spend a good amount of time on social media teaching, learning, and looking for entertainment, trying not to get uh, you know rage-baited or numbing out. Those are the two things I look out for. Rage-baiting and numbing out.","offset":5325,"duration":13},{"text":"Dacher: Well put.","offset":5338,"duration":4},{"text":"Andrew: There's a version of social media that's happening right now where we're going further and further into our silos. Yep. But I don't think it has to be that. Not at all. I don't. I think it could be really leveraged to connect people.","offset":5342,"duration":9},{"text":"Dacher: You know, when I started advising at Facebook 2010 to 20 it was like Arab Spring and democracy was spreading and and in many ways we've had this great democratization of things of people sharing music, you know, instantaneously I can hear music from any part of the world, uh which you know that's profound and visual art and and knowledge and podcasts.","offset":5351,"duration":20},{"text":"Dacher: And we've got to be nuanced about this. But we do need, you know, to think intentionally about design, you know. And that, you know, I really worry about the privileging of hate I forgot what you called it but that has been privileged. Uh, and that's not human nature. We we aren't all trolls and, you know, tracking people.","offset":5371,"duration":29},{"text":"Dacher: Video title: Andrew: What an amazing talk.","offset":5400,"duration":1},{"text":"Dacher: Thanks.","offset":5401,"duration":1},{"text":"Andrew: This really touched me and helped me think about some of the more practical ways of doing this. I really do hope that we can build some of those pathways through all this technology as opposed to getting more fractured.","offset":5402,"duration":10},{"text":"Dacher: Me too.","offset":5412,"duration":1},{"text":"Andrew: Thank you for coming today.","offset":5413,"duration":1},{"text":"Dacher: It's an honor. Thank you.","offset":5414,"duration":1},{"text":"Andrew: Appreciate it.","offset":5415,"duration":1},{"text":"Dacher: Yeah.","offset":5416,"duration":1},{"text":"Andrew: Joe Strummer would be proud.","offset":5417,"duration":1},{"text":"Dacher: Amen.","offset":5418,"duration":2},{"text":"Dr. Andrew Huberman: I've had this thought uh that the way social media is now...","offset":5420,"duration":34},{"text":"Dr. Andrew Huberman: I sometimes do the test of myself. I go, \"Okay, I spent I don't know how much time on social media yesterday, but do I remember anything specific?\"","offset":5454,"duration":20},{"text":"Dr. Andrew Huberman: And so that's scary.","offset":5474,"duration":49},{"text":"Dr. Andrew Huberman: And I do think that the people who built it want it to be impactful on the day-to-day uh scale, but also...","offset":5523,"duration":19},{"text":"Dr. Dacher Keltner: Well, you know, one of the things I'm really interested in right now, Andrew, is is awe design, right? And, you know, I'm working with Gehl Architects in Copenhagen. Like, how do you design cities for more awe? It's not hard, and it's good for people, right? A little bit of music, a little bit of green space, a little bit of art, get people looking at each other and talking and buzzing, right? Easy to do.","offset":5542,"duration":24},{"text":"Dr. Dacher Keltner: And I think you've just laid out, you know, and someone could write a manifesto, like, maybe my life on the smartphone is the antithesis of awe. It's small, awe's vast. It's sped up, awe slows things down. It has a fragmentation to it, awe integrates, right? It's about micro-things, awe's about systems. Like, when you feel awe towards music, it's like, \"I get it all here, right now.\" Its content is is not inspiring very often. And it could all be.","offset":5566,"duration":36},{"text":"Dr. Andrew Huberman: Sometimes it is. I I think that that the space-time aperture that we talked about before, I think the problem with social media is actually its power to bring the whole space-time into an aperture this big. I actually think, crazy hypothesis, happy to be wrong, I actually think the whole problem with it has to do with the fact that it brings long time scales, past, present, and future, different aper - different frame rates into one real-world visual aperture. Because when I haven't been to the Sphere in Las Vegas, but friends of mine who are musicians who love live music, who are producers who love live music, tell me it is incredible.","offset":5602,"duration":60},{"text":"Dr. Dacher Keltner: Yeah, it should and and I think and we have to, you know, we just have to take a step back and these conversations, right? There's, you know, there's new work out about AI helping medical doctors and it's, you know, and the writer of this book coming out of UC San Francisco's like, \"It's like having the best brain trust about medicine right with you all the time.\" Who wouldn't want that, you know? And I think let's remember that. And yeah, I think that's the challenge, is to have these AI and the devices that it is manifest on get us to what's awesome. And uh, we'll see, you know, I hope so.","offset":5662,"duration":34}],"startTime":5300},{"title":"Sponsor Break: Our Place","summary":"Andrew Huberman reads a sponsor message for Our Place cookware.","entries":[{"text":"Dr. Andrew Huberman: I'd like to take a quick break and acknowledge our sponsor, Our Place. Surprisingly, toxic compounds such as PFASs, or \"forever chemicals,\" are still found in 80% of non-stick pans, as well as utensils, appliances, and countless other kitchen products. As I've discussed before on this podcast, these PFASs, or forever chemicals, like Teflon, have been linked to major health issues such as hormone disruption, gut microbiome disruption, fertility issues, and many other health problems. So it's very important to avoid them.","offset":5696,"duration":34},{"text":"Dr. Andrew Huberman: This is why I'm a huge fan of Our Place. Our Place products are made with the highest quality materials and are all PFAS and toxin-free. I particularly love their Titanium Always Pan Pro. It's the first non-stick pan made with zero chemicals and zero coating. Instead, it uses pure titanium. That means it has no harmful forever chemicals and it does not degrade or lose its non-stick effect over time. I cook my eggs in my Titanium Always Pan Pro almost every morning. The design allows for the eggs to cook perfectly without sticking to the pan.","offset":5730,"duration":28},{"text":"Dr. Andrew Huberman: Right now Our Place is having their biggest sale of the season. You can save up to 40% sitewide, now through April 12th. Just head to fromourplace.com/huberman. Again, that's fromourplace.com/huberman to save up to 40%.","offset":5758,"duration":20}],"startTime":5696},{"title":"The Social Value of Embarrassment & Teasing","summary":"Keltner shares his research on embarrassment and teasing, explaining how they function as social glue. Playful teasing and the ability to feel embarrassed signal a person's commitment to group norms.","entries":[{"text":"Dr. Andrew Huberman: Can we talk about embarrassment?","offset":5778,"duration":27},{"text":"Dr. Dacher Keltner: I know. Well, you know, it it all begins really in my - like, when I started scientifically to depart from the Ekman canon, if you will, of those six emotions we talked about earlier. And I was doing a project in his lab and we were startling people and studying the startle response. A seven-muscle movement motor pattern built into the nervous system. And I noticed people got embarrassed after they were startled unexpectedly, you know, you'd blast 'em with a noise out of the blue in the lab and they'd be like, \"Whoa, I think I spit and, you know, peed my pants,\" or whatever. They'd show this response.","offset":5805,"duration":38},{"text":"Dr. Dacher Keltner: And I took it to Ekman and it's the blush, and people avert their gaze and they look away and they hide their face, you know? And he's like, \"That's a motor pattern of emotion, you should go study it.\" And I did. And and then I started to notice, and there's a really rich literature on that, that and Darwin wrote about this, that a person's embarrassment is a sign of their commitment to the collective, right? Like, man, you know, I called you by the wrong name, or I, you know, I farted in the yoga class, or whatever it is, and I'm embarrassed, like, \"I'm sorry, man,\" you know, \"I apologize.\"","offset":5843,"duration":33},{"text":"Dr. Dacher Keltner: That really matters. And when you see people get embarrassed, you like them more and you trust them more and you give resources to them and you think they're a good group member. And then I was like, man, you know, like I've played a lot of pickup basketball in my life, thousands of games, and you're banging into - and there's just a lot of teasing and taunting, and you know, people I admire, you know, great athletes tease and taunt, you know, it's just part of what we do when we're banging into each other.","offset":5876,"duration":30},{"text":"Dr. Dacher Keltner: And I started to put it together, like, you know, the right kind of teasing within a collective, you're kind of provoking people to see if they care about the group, right? And then the wrong kind of teasing, which we documented in our lab's, like, that's bullying and harassment and we can pinpoint, like, \"That's inappropriate,\" you know? You're trying to you're not keeping people in the group, you're excluding them or humiliating them.","offset":5906,"duration":24},{"text":"Dr. Dacher Keltner: So we did this study, was one of my first studies, we brought four fraternity - we brought groups of fraternity - four fraternity guys in each interaction uh from this fraternity house at the University of Wisconsin. And we gave them each nicknames, or we gave them each initials, and we had them make up nicknames based on the initials. So two two letters of a nick - were \"A.D.\" And I'm not sure I can say what the nicknames were like, but it, you know, \"Another Drunk,\" and it gets pretty profane.","offset":5930,"duration":37},{"text":"Dr. Dacher Keltner: And so we let 'em tease each other. And they start teasing each other and they are really, like, these young men coming out of a fraternity house teasing each other. There are funny stories, people got embarrassed. Uh the the stories and the teasing was kind of about, like, \"I'm gonna accuse you of something that you shouldn't do in this group,\" right? Like pass out drunk naked, you know, in the streets of Wisconsin. \"Don't do that,\" right?","offset":5967,"duration":29},{"text":"Dr. Dacher Keltner: And then they get embarrassed and they say, \"I'm not gonna do that.\" And what we found is the more that they got embarrassed, the better they liked each other, because it's turning into this motor pattern of, like, \"Wow, I'm showing you that I care about what you're accusing me of and I'll get embarrassed, you see that in me, we become closer.\" The the guys who were better teasers and that were more playful and funny and made people aware of the norms that matter to the group but not really humiliate people, those guys were more popular in the group.","offset":5996,"duration":37},{"text":"Dr. Dacher Keltner: And that's been replicated, right? Just storytelling and and ribbing each other and and it was part of healthy group functioning is just embarrassing each other. You think about roasts, you know, at the end of your career, you're gonna get that someone's gonna talk about your career, you're gonna get hammered. And it's wonderful.","offset":6033,"duration":52},{"text":"Dr. Andrew Huberman: I bet. I mean, I grew up in a big big packs of boys, I mean on my street growing up...","offset":6085,"duration":26},{"text":"Dr. Andrew Huberman: Uh a former guest on this podcast who's a psychiatrist who's also very versed in Eastern philosophy, Dr. K, as they call him, um said that embarrassment is important because it also signals that you're not a creep. Especially, he was referring to heterosexual relationships where, you know, a guy says something trying to be uh, you know, trying to flirt basically or pick up on someone, and then uh the woman says something back and he, like, gets embarrassed, he realizes, like, he said the wrong thing. If he doesn't show embarrassment, he's creepy. If he does, it verifies that he has a certain degree of empathy and self-reflection. No, so that was his point, but it it feels relevant here. So...","offset":6111,"duration":40},{"text":"Dr. Dacher Keltner: And he's right. I mean, you know, uh Darwin early on wrote about the blush being a sign of your healthy character, your moral virtue almost. And in non-human species, the facial reddening is associated with physical robustness and then in humans we think of it as moral robustness like, \"Yeah, I care about stuff.\" We did work early on, Bob Knight at Berkeley, orbital frontal patients. The orbital frontal cortex is in part where your ethical consideration takes place. And if you have damage to that region of the brain through brain trauma - you fall off a motorcycle or, you know, fall off a ladder - you don't show embarrassment where you should. And they feel creepy, if you will, or just like, \"Hey, they're not playing by the rules.\" So it's a very subtle thing. Erving Goffman wrote a lot about it, the great sociologist, like, our embarrassment is telling people like, \"I know what the rules are and I care about them, I'm committed to them.\" So your psychiatrist friend is right.","offset":6151,"duration":63},{"text":"Dr. Andrew Huberman: Along the lines of of teasing, um uh someone I'm I'm proud to call a friend who's also public facing uh Jocko Willink, who's also it turns out one of our - were friends for a bunch of reasons but one of them is that he grew up really into East Coast hardcore music. Not not a genre I I gravitated towards, but there's some marginal overlap um with the types of music um I'm into. We've gone to shows together and um, he put something up, you know, every once in a while on social media somebody posts something that that really lands, Naval or or Jocko and he's a Jocko's a man of few words, so I'm gonna put more words to it than than he was able to.","offset":6214,"duration":40},{"text":"Dr. Andrew Huberman: Um but the quote was something like, um \"You know, if you want to understand,\" and he's a former Navy SEAL, SEAL team operator most people know know that, but \"If you want to understand uh males in groups and healthy uh masculine friendship, guys are going to tease each other relentlessly in front of each other, but they'll never tease behind somebody's back and they'll back the other person who they were just teasing in person against the rest,\" you know, \"They'll buffer them against any kind of criticism.\" So it's a very interesting um kind of uh contrast there that I think is true. Like, you you know, it's not like you tease your friend behind his back. It's the teasing to his face that actually builds the bond.","offset":6254,"duration":45},{"text":"Dr. Dacher Keltner: Yeah, well put.","offset":6299,"duration":36},{"text":"Dr. Dacher Keltner: We documented that in the fraternity study, that, you know, when you when you tease somebody and you're like, \"Hey man, do you see this guy's dance moves?\" or \"You see this guy shoot free throw,\" whatever it is, you're just making light of human foible and and all the funny things that we do. And there's there's there's just this really subtle repair work where they're saying like, \"I'm teasing you, but I know you got it,\" you know, \"And I'll support you.\" And I agree, I think that, you know, part of what teasing does is it says like, \"What do we as a collective really care about?\" And let's surface those norms in a lighthearted way and we know 'em together. And and if you make mistakes, you should be apologetic about it, but part of it also is just uh this sort of \"I got your back\" repair work that they did. Um and it's profound.","offset":6335,"duration":51},{"text":"Dr. Dacher Keltner: It, you know, was interesting. I was kind of this shy kid and I was very small growing up and kind of the teasing often crossed lines in high school, just, you know, bullying and so forth. And then I started to play basketball and, you know, um and I realized, like, a lot of it's just just men making sure they know the rules of the game, you know, and showing also in those moments of the joys of laughing together like, \"I support you, I'm with you,\" right? Uh what a sophisticated thing to do um compared to the alternatives.","offset":6386,"duration":38},{"text":"Dr. Andrew Huberman: I have a sister, so I was always struck by the brothers in my neighborhood. Yeah, there were two in particular, like, I would hear screaming outside, go outside, it was an older brother, his name was Peter, holding Michael's face in the sprinklers. His brother's just crying and crying, screaming, I mean relentless older brother torture. Some people hear this and probably be like, \"Oh, call the cops,\" you know, and I don't know what the reaction is nowadays, I'll try not to be genera - generationally biased, I don't know. Yeah, he was he was abusing his younger brother. And but if anyone said or tried to do anything to either one of them, they would immediately pair up and fight anyone. It was interesting, right? Uh for a guy who had an older sister, was a very different experience, right? I mean, she had her own form of older sister kind of hazing um to her younger brother.","offset":6424,"duration":49},{"text":"Dr. Andrew Huberman: But there really does seem to be something critical about kind of defining the relationship with people one-on-one, in groups, versus when there's an outside threat. And and not that we want outside threat, but as long as we're talking about the sort of...I don't want to say disintegration, that's too pessimistic. The sort of gradual erosion of this collective feeling, is there less just kind of grouping up together and doing things?","offset":6473,"duration":30}],"startTime":5778},{"title":"Combating the Epidemic of Loneliness","summary":"Despite concerning trends of isolation and declining institutional participation, Keltner and Huberman see hope in younger generations recreating community through shared living, yoga, and group activities.","entries":[{"text":"Dr. Dacher Keltner: Yeah, you know, I um 10 years ago, uh 15 years ago, 10 years ago, uh first there was the science of loneliness and isolation, John Cacioppo uh and then those who followed, like, \"Whoa, we are fragmenting.\" And we spend much too much time alone, isolated. And then COVID hit, lockdown, etc. And our Surgeon General, former Surgeon General Vivek Murthy got it right, like, it's an epidemic of loneliness. And I as a social psychologist, you know, interested in these social emotions am like, you know, you just look at the basic raw facts, like, picnics are down by half. We don't go to movies like we used to. We don't um we don't listen to music together. We don't...30 the estimate is that 30% of meals in the United States people eat them by themselves, you know? I eat a lot of my meals by myself. Uh we go on walks by ourselves, we don't go to church, church is way down. Um so the kind of the broad sociological trends are alarming on that fragmentation.","offset":6503,"duration":72},{"text":"Dr. Dacher Keltner: But I think the young generation is putting it back together in really interesting ways. You know, we know from survey data that 25-year-olds, 30-year-olds are really interested in game nights, you know, those are coming back. They're interested in living together, cooperative living. They're cooking more with each other. Value-wise they care more about community than my generation. I was the great explosion of individualism and they're kind of like, \"You know, if I if I choose a job, I want to make sure I'm working with other people I like.\" I didn't even I didn't think about that. I don't know if you, you know...uh so I think it's coming back.","offset":6575,"duration":39},{"text":"Dr. Dacher Keltner: And and I love the signs of, you know, festivals are reappearing now, the farmer's market that I've talked about, the, you know, the dance groups that are now returning, contact dance. I see, I mean these yoga studios, one out of eight Americans does yoga. You know, I do yoga two to three times a week.","offset":6614,"duration":29},{"text":"Dr. Andrew Huberman: Also 15 years ago, no one would have predicted that the single we're being told that one of the single most important health interventions that women and men should do is, like, lift weights. The only people lifted weights when I was growing up were bodybuilders and preseason football players.","offset":6643,"duration":60},{"text":"Dr. Dacher Keltner: I think Vivek Murthy in particular, who I deeply admire and have worked with a bit, you know, he he got our health world - think about it. Surgeon General of the United States, the first one to come out of public health traditions. Did work in India, right? And he's like, \"There's this social side that you've covered in your show like to health, to physical health, to the telomeres of your cells, your DNA and the vagus nerve and so forth, oxytocin, cortisol. It's social.\" Uh there's there are social dimensions to our nervous system.","offset":6703,"duration":38},{"text":"Dr. Dacher Keltner: And I think that's coming, Andrew. Like, we're starting to see, \"Why do I go to a farmer's market?\" because I feel a sense of community. And \"Why do I love yoga?\" because I'm doing these postures all synchronized with people I don't know and I feel a sense of awe and transcendence. \"Why do I lift weights,\" right? There's the banter and the discussion and the the history and the sense of, you know, of what this all means culturally. I think that's coming. I think the gyms are appealing to it in some sense, right? A little bit more community activity and I think it's good news, you know?","offset":6741,"duration":37},{"text":"Dr. Dacher Keltner: I love the Japanese onsen. Uh you go for the water, you know, and the the springs and the heat and so forth, but they in their wisdom have built entire community experiences around it. Where you you wash yourself and you bathe together and you eat together and there's sayings up on the walls and you spend a little time with your kids there, right? So I hope we we learn um because I think it's important.","offset":6778,"duration":29},{"text":"Dr. Andrew Huberman: Yeah, I'm thinking a lot now about how we can bridge between these incredible technologies, because I I am a fan, um and but also the non-negotiable technology of our our nervous system and our biology and our psychology, right? Lately, because I have a quarium, I'm really into this thing called aquascaping, which is this Japanese form of, like, plants and and freshwater fish and um just obsessed with it. But and and when the ecosystem is doing well, I'm like, \"Oh,\" like, I feel it's a form of it's brought me some awe at times when, like, things are going well in there, I'm like, \"Wow, it's just beautiful.\"","offset":6807,"duration":34},{"text":"Dr. Andrew Huberman: And um, and I think there are things that I would never do to my fish. I would never isolate them from one another. But I give them enough places to hide from one another because there's a lot of dominance hierarchy stuff being worked out between these discus. Um I make sure they're on a light cycle. I make sure they're fed, but not overfed or underfed, right? And um I wouldn't do most of the things that we do to ourselves to my fish. [Laughs] You know, I wouldn't isolate them and give them like little videos of other fish to look at, like, I know that wouldn't that wouldn't work. Um I know that they would die. I I know. The uh and so I think we can learn a lot from more uh simpler organisms and and the sort of basic units of of care and community. They're very similar. I mean, it gets played out differently, but but they're very similar uh because obviously we we evolved similar nervous systems, let alone similar needs.","offset":6841,"duration":59}],"startTime":6503},{"title":"Psychedelics & Awe","summary":"They discuss the resurgence of psychedelics, emphasizing their potential to dissolve the ego and generate awe when used therapeutically. Keltner shares his concerns about microdosing and stresses the importance of honoring indigenous traditions.","entries":[{"text":"Dr. Andrew Huberman: I would like to talk about psychedelics if you're willing.","offset":6900,"duration":29},{"text":"Dr. Andrew Huberman: So some people will say, \"Okay, they just send you inward.\" And that's the opposite of what we're talking about, like getting all the awe inside like, \"Okay, that's I mean that's pretty extreme.\" Um other people will say that their experiences with psychedelics allowed them to come out of that experience and really have a a felt connection to people, to plants, to animals, to life that is um profoundly positive for their feelings of connection and seeing awe perhaps even in lots of things.","offset":6929,"duration":38},{"text":"Dr. Andrew Huberman: So how should we think about psychedelics? And we should probably constrain the question a little bit, like, I'm not talking about MDMA, which is not a psychedelic, it's an empathogen. Ketamine's not a psychedelic, it's a dissociative anesthetic. I'm trying to do this now because people start to lump and it's actually causing issues for the potential legalization for...so we need to be splitters, not lumpers here. So I'm talking about LSD, psilocybin, maybe DMT, ayahuasca, the the classic psychedelics. Yeah, what are your thoughts on these?","offset":6967,"duration":29},{"text":"Dr. Dacher Keltner: Yeah, and I'm good friends with Michael Pollan and was, you know, kind of walking the Berkeley Hills as he was producing that book and, you know, watched as we started a center for psychedelics uh at Berkeley. And um and, you know, it's a revolution. I mean, it's psychedelic use is up, you know, 40% since his book. I mean, it's incredible to watch.","offset":6996,"duration":22},{"text":"Dr. Dacher Keltner: And I I have a few thoughts, you know, one is, you know, make sure to honor the indigenous traditions out of which they come. Uh those are spirit medicines in their communities that are part of deep ethical traditions um, you know, and to honor that with, you know, uh re - you know, uh sharing of resources and knowledge and and the right kind of acknowledgment. That's really important.","offset":7018,"duration":26},{"text":"Dr. Dacher Keltner: Um I I think in some sense uh and, you know, David Yaden at Johns Hopkins and others uh and some of the early Roland Griffiths' work spoke to this, that they are about awe um fundamentally, you know? They open up your mind and you see all life forms and time is different and your sense of self vanishes, Robin Carhart-Harris, you know, and you're just connected to vast things, ecosystems and sense of humanity. And I think in some sense and done when done in the right way, that's good news.","offset":7044,"duration":35},{"text":"Dr. Dacher Keltner: You know, Molly Crockett and her team at Princeton like, you go to a festival and you have psychedelics, a year later you're kinder uh through awe, right? Uh so I think that's important. Uh I think it's great news what it does for the hard problems of the mind, you know? Death anxiety, addiction, trauma, uh maybe veterans who are suffering twice the rates of PTSD, they're drawn to this, you know, and the VA is working on this. So and the data look pretty good. OCD, right, hard problems of the mind. Panic, right, that um I've in part dealt with. That is good news.","offset":7079,"duration":44},{"text":"Dr. Dacher Keltner: Um I worry about microdosing. You know, I think people are taking um these things like coffee, and it's not coffee, you know?","offset":7123,"duration":45},{"text":"Dr. Dacher Keltner: And I, you know, they changed my life. I I got to them early uh, you know, in my late teens, 17, 18, 19. I was a very anxious obsessive kid and I think they opened up my mind in this perspective way we've been talking about. I don't really do them now, you know, they gave me a lot and that's why they're here.","offset":7168,"duration":21},{"text":"Dr. Dacher Keltner: You know, it's funny, you know, Andrew, like when I was doing them, we were reading Castaneda who's been debunked, you know, and we're reading the traditions and thinking about them spiritually and the Doors of Perception and all this good stuff, right? We were they were embedded in a a culture of trying to find mysticism or whatever it is, and I hope people are doing that, you know, if they're going to be doing them, make it a form of inquiry. It's a complicated story, like everything, like technology.","offset":7189,"duration":30},{"text":"Dr. Andrew Huberman: Well, they're a form of plant technologies, right? Plant - which uh quick vignette on that. We had someone here um Chris McCurdy, who runs a lab out in Florida, studies kratom and other compounds from plants. The pharma companies, they bioprospect. They send people looking for plants that then they can find isolates and everything from aspirin to uh kratom to anesthetics like cocaine - I'm not suggesting people use as an anesthetic - they come from plants. But they're isolated and then synthesized and and enriched and that's where the opiate the extreme opiate, the extreme stimulant, you know, that's where it comes from. But they all come from plant al- many of them come from plant alkaloids, which is interesting in its own right.","offset":7219,"duration":40},{"text":"Dr. Andrew Huberman: But the I share your feelings about microdosing. Um the data Robin Carhart-Harris tells me, and he's the real expert of course, the data say there's no um evidence of benefit from microdosing, at least on major depression as compared to, like, two rounds of psilocybin with a guide, therapy before, during, and after and on and on.","offset":7259,"duration":23},{"text":"Dr. Andrew Huberman: Um I had the opposite experience as you. Um I actually regret having done psychedelics when I was younger. They were terrifying, I didn't have a good experience. I stopped, didn't go anywhere near them. And then later in a therapeutic setting um had a few experiences with them, not many, but that were immensely beneficial for me. Um so kind of the opposite direction there.","offset":7282,"duration":27}],"startTime":6900},{"title":"Fostering Connection for Future Generations","summary":"Huberman asks how older generations can help younger people flourish amidst technological challenges. Keltner suggests prioritizing shared, collective experiences like campfires, public art, and communal spaces.","entries":[{"text":"Dr. Andrew Huberman: But what we're talking about now about kind of, \"Okay, you know, there's this problem with certain technologies, there's the the culture wars, there's the political wars, there's the actual war that's also going on right now.\" A lot of ways this resembles, like, the 70s, 80s. There's not that - I mean, I remember a time when you had yuppies and you had hippies and you had punk rockers. I mean, you watch a John Hughes film, it was like the idea was was like, \"Oh, we're actually similar,\" right? You know, the extent to which those films like showed people, \"Hey, like people were actually similar along certain dimensions as opposed to so different.\"","offset":7309,"duration":31},{"text":"Dr. Andrew Huberman: But, you know, I I wonder because I think about the not-so-recent and recent history of things, everything from breathwork, cold plunges, psychedelics, um awe, music, the collective consciousness. I mean, it's gonna look different now, the same way that it it looked different back then, right? Like, I'm I'm trying to get outside my Gen X self these days and think like, \"So what would it look like?\" Like, I'm the old guy now. So what would it look like if these technologies, I just mentioned a few, but all of them including social media, what would it look like if those were all used to the greatest benefit? Like, what would that look like? Can we be the open-minded parents of the 80s? You know?","offset":7340,"duration":44},{"text":"Dr. Andrew Huberman: Um can we be the can yeah, like because I feel like I can scream all day or about what I think about the science of this and that to younger people, but the only thing I actually have control over is, like, me. How do we um let's say 40 to 100-year-olds - let's really lean it on the 40 to 70. Okay. How do we create the environment so that younger people can flourish with these technologies as opposed to being like the parents of the 70s and 80s that are like, \"Oh, they got long hair and like what is this like punk rock thing?\" Like, I don't want to be that person. That sucks.","offset":7384,"duration":44},{"text":"Dr. Andrew Huberman: I also don't want to be the and I see this a lot, unfortunately, people who were part of those movements and then they they're just like toeing the party line because oh they're like wholeheartedly adhering to one political group without thinking about whether or not there's any any hint of rational argument on the other side, right? The whole point is not to be against, the whole point is to be for what you believe is right. And so I don't know how to do this. You're older than I am by a bit, you're clearly wiser than I am, seriously, and you have more life experience. So what do we do? Like, really like what what on the help can we do? Because I don't like this, \"You guys are all on your phones, you're like,\" that doesn't feel good to me, because they were telling us when we were younger, like, \"This is ridiculous,\" like the older guys were like, you know, small wheels on skateb- they were right about the small wheels thing, turns out the wheels got too small. But Jim will understand that joke. But what do we do?","offset":7428,"duration":60},{"text":"Dr. Dacher Keltner: I think we're in this moment, you know, with everything going on, you know, with AI and being online and polarization and climate crisis and um, you know, the things that we worry about, the rise of white supremacy politics, etc. Everybody's asking this question of, like, what how do we kind of move forward.","offset":7488,"duration":22},{"text":"Dr. Dacher Keltner: And and, you know, in light of many of the things that we've talked in this conversation, I'm most focused on um what Robert Putnam started to write about and other people started to write about, like the just the breakdown of collective life and shared life. And I think that's the defining issue of our times, as well as our relationship to the natural world.","offset":7510,"duration":28},{"text":"Dr. Dacher Keltner: And I find awe, as do other people, really refreshing. It it provides a road map which is, you know, and I'll give you a very concrete example. I'm working with Gehl Architects on a \"Cities of Awe\" initiative. And they do amazing work, hundreds of cities around the world. 70% of human population is in cities, most of our carbon emissions come out of cities. And this is this is a place we can redesign and and make it better, right?","offset":7538,"duration":31},{"text":"Dr. Dacher Keltner: And awe is a wonderful lens. So you can ask, and you could ask the same of like, \"What do you give to a teenager who's suffering suicidal ideation?\" or \"What do you give to a veteran who is coming back and feeling alienated from the world?\" You give them awe, right? And what does that mean? It's like, well, you give them a little nature. And that's you re-wild part of a city, right? You give them some public art. We love art, you know, we love visual art.","offset":7569,"duration":30},{"text":"Dr. Dacher Keltner: You give them uh the opportunity to recognize the moral beauty, you found it in Joe Strummer, just get them to interact with other people, some face-to-face. You give them uh a little collective stuff, right? You, \"Hey, we're gonna have the yoga class in the town square,\" or the Mexican Zocalo everybody walks together at a certain hour of the day and they suddenly feel peaceful, right?","offset":7599,"duration":26},{"text":"Dr. Dacher Keltner: Uh you give them ideas about big ideas and and life. You give them a little bit of opportunity for meditation and reflection. Um that's easy to do. And when I, you know, was writing this book and just teaching social science for 30 years, it's like, \"Man, you know, we used to do this really well and it used to be temples and church. You know, that's where it all was brought together. And now we don't go there.\" 55% of Americans go to church. It used to be 90. Or temple. Um I don't, I never did, you know, and I and I in some sense miss it, you know? I see my one of my best friends very religious, he few of them and they they have so much.","offset":7625,"duration":45},{"text":"Dr. Dacher Keltner: And we're recreating that right now, right? And we've got to do it in a coherent way. If it's the place where people are lifting weights, there should be music there, there should be visual stuff, there should be some art, nature, there should be some wisdom and some moral beauty, right? That's uh I love ironworks where I go climbing because you go there and it's like people are climbing but there's you get to see the there's the art exhibit each month of a local artist. There's some music going on, you get to listen to music.","offset":7670,"duration":33},{"text":"Dr. Dacher Keltner: So this isn't that hard to do, Andrew. And I think the awe science gives us a road map to think about what we share.","offset":7703,"duration":9},{"text":"Dr. Andrew Huberman: Love that. Um I was not into CrossFit, but a next girlfriend of mine when I met her was, like, really into CrossFit and they would do barbecues and they'd clean the gym and they would dress up in costumes and stuff. I remember this is when I moved to San Diego to start my lab down there before moved to Stanford. And and I remember thinking, like, \"This kind of crazy,\" like I went to the gym growing up, I s- always since I was in my teens, and I'm like, \"Really? You guys are social?\" and they had this awesome social community. I know CrossFit is somewhat fallen out of favor now. Uh I think the pandemic brought us into our isolation.","offset":7712,"duration":33},{"text":"Dr. Andrew Huberman: You may be uh pleased to hear, I I just thought of this, I can't remember I can't believe that I didn't uh remember this earlier. Um one of the things that Joe Strummer was famous for after the Clash, cuz you know he went into the kind of void of, like, he wasn't doing anything. He he wandered for a long time. He went to Spain, oh he grew out a beard, moved to Spain and um didn't tell anyone who he was and they they kind of realized who he was eventually. He was really searching, you know, his life had he lost his brother to suicide, I believe. Um he ran the um the Paris Marathon, this kind of famous, I think while smoking a cigarette. Um people always say and I don't think he did any training.","offset":7745,"duration":39},{"text":"Dr. Andrew Huberman: One thing that he was very well known for until his death was he would do campfires. In Manhattan, he would take people down to the river and and he had some famous friends like Jim Jarmusch and and, you know, and um well-known people in in that world. Um but he would invite whoever. And there were kids - you gotta see this documentary, it's so good. We'll put a link to it um for people want to see it, it's so good. Um there were kids, there were adults, um and they'd stay out to like two or three in the morning playing music, singing, drumming, uh people get up and talk. And so he was constantly doing these campfires his entire life.","offset":7784,"duration":38},{"text":"Dr. Andrew Huberman: Knowing close friends of his, it's like, \"This actually what he did.\" And he wasn't getting - they they were able to film a few of these, but that was not the point. And he would bring out a radio cuz he thought, like, maybe you could, like, make it like a radio show of the thing. And but it was not to record and distribute, it was just...so I don't know, I got this crazy idea in the back of my mind that maybe, like, I'm gonna start doing campfires.","offset":7822,"duration":21},{"text":"Dr. Dacher Keltner: I have to weigh in on some science. Okay.","offset":7843,"duration":43},{"text":"Dr. Dacher Keltner: Um when I go to the climbing gym, we all take saunas. You know, I do probably four saunas a week.","offset":7886,"duration":29},{"text":"Dr. Andrew Huberman: Awesome. Uh campfire also great red light therapy, no joke. Long wavelength light only coming out of that fire. And you know everyone's obsessed with, like, red light therapy. You can get from the sun when you don't want to get too much UV, but yeah, you get tons of long wavelength light exposure, which is great for which is known to be great for mitochondria. I mean, don't get me I don't want to get going on this as too much of a tangent. We've had guests on here from University College London. I mean, the long wavelength light actually goes all the way through your body, even in light clothing, and is absorbed by the water in your mitochondria, which actually improves mitochondrial function in every single every single cell that has a mitochondria.","offset":7915,"duration":36},{"text":"Dr. Dacher Keltner: And where do we get this light from?","offset":7951,"duration":34},{"text":"Dr. Dacher Keltner: Yeah. And people love campfires.","offset":7985,"duration":56}],"startTime":7309},{"title":"Perspectives on Life After Death","summary":"Huberman asks Keltner if he believes in life after death. Keltner shares a profound personal experience following his brother's passing that opened his mind to realities beyond standard physical laws.","entries":[{"text":"Dr. Andrew Huberman: Do you believe in life after death? I don't ask every guest that, by the way. You're the only person I've ever asked that. Do you believe that something happens after all this?","offset":8041,"duration":8},{"text":"Dr. Dacher Keltner: I do. I do. Um yeah, you know, when I write about this in \"Awe,\" when my brother Rolf passed away, colon cancer, 55 or so, uh you know, and I watched the whole transition and, you know, his battle against it and his acceptance and then his leaving. And I had this profound experience that night, you know, a transcendent experience. And I'm like you, you know, Andrew, it's like neurons and statistics and cells and we can figure it all out and characterize everything. And I's like, I saw space in a different way, I saw something alive in him, and then afterward I had a lot of people have this kind of grief experience of, he was around, his voice, his hand was on my back. And...","offset":8049,"duration":51},{"text":"Dacher Keltner: I’ve thought for several years, and still to this day, of, you know, quantum reality and things beyond our three-dimensional, four-dimensional view of time and space and, you know, those basic laws. And that there is, you know, consciousness, maybe patterns of, you know, electromagnetic waves around our minds and bodies that are syncing up with other people that transcend the Newtonian world of the brain. And I believe that. And I don’t know how to study it. I sense it in life. I think a lot of other people do, too. And so that keeps me open to it. And now I’ve moved from, you know, being a skeptical but open, you know, agnostic to like, yeah, there’s something there that’s beyond what we know. So I believe it.","offset":8100,"duration":63}],"startTime":8041},{"title":"Conclusion & Final Thoughts","summary":"Huberman thanks Keltner for his impactful work and career. He then provides closing remarks, promotes his upcoming book, and shares ways listeners can support the podcast.","entries":[{"text":"Andrew Huberman: Very cool. I hope you’re right. I believe it too, but I just hope you’re right. I sense you’re right. Dacher, thank you so much for making the trip down here to talk with us today and share what you’ve been up to for all these years. You’ve had and continue to have a magnificent career. You know, it’s really hard to do really good science, and it’s even harder to do really good science with a purpose. And you’re doing that, and you continue to, and you just have a way about you that everyone now has been able to experience first-hand. That, like, you really care, that’s clear. You put a ton of thought into the work that you’re doing. You’ve raised 25 professors, which is no small feat, I’ll tell you. That’s a monumental feat, which means that the work will continue. And you’re still going, and I’m grateful for your book and that you’re continuing to do this. And I hope you take that trip too, maybe if you can’t do it around the entire country, you know, hit some pick-up basketball games, because I think there’s something to be learned there for sure, I sense it. And thanks for inspiring me, and I know you’ve inspired a ton of other people. So we’ll put links to everything that you discussed and to your book. But you’ve definitely inspired us to think more deeply about basically what it is to be human and where to take all this technology that we have and this opportunity that we have and really do real good with it. So I’m very grateful to you. Thank you.","offset":8163,"duration":99},{"text":"Dacher Keltner: Well, thank you, Andrew. It’s been an incredible conversation. Let’s do more.","offset":8262,"duration":2},{"text":"Andrew Huberman: Definitely do it again.","offset":8264,"duration":1},{"text":"Dacher Keltner: Yeah, thank you.","offset":8265,"duration":1},{"text":"Andrew Huberman: Thank you for joining me for today’s discussion with Dr. Dacher Keltner. To learn more about his work and to find links to his books, including his book on awe, please see the links in the show note captions. If you’re learning from and/or enjoying this podcast, please subscribe to our YouTube channel. That’s a terrific zero-cost way to support us. In addition, please follow the podcast by clicking the follow button on both Spotify and Apple. And on both Spotify and Apple, you can leave us up to a five-star review. And you can now leave us comments at both Spotify and Apple. Please also check out the sponsors mentioned at the beginning and throughout today’s episode. That’s the best way to support this podcast. If you have questions for me or comments about the podcast, or guests or topics that you’d like me to consider for the Huberman Lab Podcast, please put those in the comment section on YouTube. I do read all the comments.","offset":8266,"duration":46},{"text":"For those of you that haven’t heard, I have a new book coming out. It’s my very first book. It’s entitled \"Protocols: An Operating Manual for the Human Body.\" This is a book that I’ve been working on for more than five years, and that’s been based on more than 30 years of research and experience. And it covers protocols for everything from sleep to exercise to stress control, protocols related to focus and motivation, and of course, I provide the scientific substantiation for the protocols that are included. The book is now available by pre-sale at protocolsbook.com. There you can find links to various vendors; you can pick the one that you like best. Again, the book is called \"Protocols: An Operating Manual for the Human Body.\"","offset":8312,"duration":39},{"text":"And if you’re not already following me on social media, I am @HubermanLab on all social media platforms. So that’s Instagram, X, Threads, Facebook, and LinkedIn. And on all those platforms, I discuss science and science-related tools, some of which overlaps with the content of the Huberman Lab Podcast, but much of which is distinct from the information on the Huberman Lab Podcast. Again, it’s @HubermanLab on all social media platforms.","offset":8351,"duration":23},{"text":"And if you haven’t already subscribed to our Neural Network newsletter, the Neural Network newsletter is a zero-cost monthly newsletter that includes podcast summaries as well as what we call protocols in the form of one- to three-page PDFs that cover everything from how to optimize your sleep, how to optimize dopamine, deliberate cold exposure. We have a foundational fitness protocol that covers cardiovascular training and resistance training. All of that is available completely zero-cost. You simply go to hubermanlab.com, go to the menu tab in the top right corner, scroll down to newsletter, and enter your email. And I should emphasize that we do not share your email with anybody. Thank you once again for joining me for today’s discussion with Dr. Dacher Keltner. And last, but certainly not least, thank you for your interest in science.","offset":8374,"duration":15}],"startTime":8163}],"entries":[{"text":"Guest: Awe is good for reduced inflammation, elevated vagal tone, reduced long COVID symptoms. We have people with long COVID, just a minute of awe a day reduced long COVID symptoms. It's good news, right? And, and there's so much science on it that I just now, I think medical doctors are starting to think like, I'm going to prescribe nature, I'll prescribe music, through awe, right? Um as a mechanism.","offset":0,"duration":27},{"text":"Host (Andrew Huberman): Welcome to the Huberman Lab Podcast where we discuss science and science-based tools for everyday life. I'm Andrew Huberman and I'm a professor of neurobiology and ophthalmology at Stanford School of Medicine. My guest today is Dr. Dacher Keltner.","offset":27,"duration":19},{"text":"Andrew Huberman: Dr. Dacher Keltner is a professor of psychology and the co-director of the Greater Good Science Center at the University of California Berkeley. Dacher is an expert in the science of emotions and their role in social dynamics and bonding.","offset":46,"duration":17},{"text":"Andrew Huberman: Today we discuss his fascinating work on the science of emotions including the role of teasing in social bonding, the role of embarrassment in social bonding and his fascinating work on awe and the things that lead to awe. As he describes, awe is not elusive. It happens when we shift our perception from a very small scale to a very large scale or back again, such as when we suddenly reach a new horizon or visual vista.","offset":63,"duration":31},{"text":"Andrew Huberman: Today you'll understand what all of that really means and more importantly, how you can create this incredible thing that we call awe in everyday life. We also talk about the critical aspect of human bonding in groups and the things that both establish and inhibit deep human bonds.","offset":94,"duration":18},{"text":"Andrew Huberman: So today is a very practical as well as conceptual conversation that no doubt will change the way that you think about your life everyday and think about opportunities for awe everyday. As you’ll soon see, Dacher Keltner is a truly special scientist known for his incredible rigor and creativity in the study of emotion but also continually offering you, the public, ways to be and feel genuinely better and to get more out of life. It was a true honor and pleasure to host him.","offset":112,"duration":35},{"text":"Andrew Huberman: Before we begin, I'd like to emphasize that this podcast is separate from my teaching and research roles at Stanford. It is however part of my desire and effort to bring zero cost to consumer information about science and science-related tools to the general public. In keeping with that theme, today's episode does include sponsors.","offset":147,"duration":19},{"text":"Andrew Huberman: And now for my discussion with Dr. Dacher Keltner. Dr. Dacher Keltner, welcome.","offset":166,"duration":5},{"text":"Guest (Dacher Keltner): Good to be with you, Andrew.","offset":171,"duration":2},{"text":"Andrew Huberman: Awe. Yeah. I think we all intuitively know what it is and yet we also don’t know how to articulate it. Yeah. I want to say the words overwhelmed, excited, I get the physical sensation of a lift. I don’t think anyone ever said the word awe and then collapsed into a turtle position. Maybe we could explore that in your thoughts about that. But what got you into awe?","offset":173,"duration":29},{"text":"Dacher Keltner: Yeah, and, and I love the word lift. That’s really interesting. Uh, yeah, I was a young scholar in the science of emotion that really Paul Ekman was a pioneer in, you know. And, and that field in the, you know, 90s and early 2000s was uh really focused on negative emotions, you know.","offset":202,"duration":19},{"text":"Dacher Keltner: And and you know this science, right? Anger, fear, fight or flight physiology, amygdala, cortisol, uh disgust, you know, Paul Rozin and John Haidt. Um and thinking about emotions from that lens and and it as a young scientist um and given the powerful tools of emotion science of Darwin and Ekman and how to just observe phenomena uh it didn’t make contact with my life and my own experience, you know.","offset":221,"duration":29},{"text":"Dacher Keltner: I was raised as a wild child in the late 60s in Laurel Canyon and, you know, it was like music and social change and protest and uh you know and beauty and I was raised by a dad who’s a visual artist and my mom taught romanticism and Virginia Woolf and awe and the mind and and I was like wow there’s all this stuff that our science, my science, can’t speak to, music and visual patterns and dance and collective movement and, you know, someone like Martin Luther King and why he makes me cry, you know.","offset":250,"duration":37},{"text":"Dacher Keltner: And I remember feeling this and asking Paul Ekman, I was like, you know what should I do with my career? and he’s like “study awe”, you know, and uh so that got me going.","offset":287,"duration":11},{"text":"Andrew Huberman: If we could let maybe we could talk about the faces for a moment. You know, I think every psychology and neuroscience student sees these faces of disgust, of of pleasure, uh Darwin talked about this. Babies are often presented in parallel with those pictures of adults where they’ll show a baby like, you know, recoiling from something or you know wide-eyed and leaning in, you know.","offset":298,"duration":29},{"text":"Andrew Huberman: There always seems to be a motor component to this that maybe isn’t as captured in those two-dimensional photographs but what’s the story about kind of hard-wired facial emotions and what are the revisions to that story that I’m probably not aware of?","offset":327,"duration":17},{"text":"Dacher Keltner: Yeah, thank you for asking that um, you know, I’ve spent 30 years working on that very problem. Um Paul Ekman came in and, you know, as as you suggested, right? He did this revolutionary work in New Guinea, you know, showed photos of six emotions, static photographs of anger, fear, sadness, disgust, surprise, and a smile.","offset":344,"duration":22},{"text":"Dacher Keltner: They kind of interpreted the faces like you or I would um naming it using the right words to describe those faces and that you know and this is how science occasionally works which is just by accident that became the field. And there are a lot of debates about how reliable those faces are, how universal are they in different cultures.","offset":366,"duration":24},{"text":"Dacher Keltner: Ekman really posited sort of a strong universality, that’s been contested by Jim Russell, Lisa Feldman Barrett, and others. Um but since then there are controversies around how hard how hard-wired they are, do they occur reliably in a child’s development? Yes and no.","offset":390,"duration":21},{"text":"Dacher Keltner: You know, young children show disgust expressions uh like social mammals do, they wince at bad smells just like you or I would. Um anger’s a little bit trickier to pin down developmentally. But then our lab and several labs around the world, you know, Jess Tracy at UBC (British Columbia), Disa Sauter, uh and I want to talk about this computational work, started to expand the vocabulary of faces.","offset":411,"duration":27},{"text":"Dacher Keltner: And now we there’s a lot of data that suggests there are 20 different facial expressions. Laughter, love, compassion, awe, you know “whoa”, um embarrassment, shame, pain um you know and that in some sense has broadened the taxonomy of emotions. We used to think of six, now there are probably 20 distinct states in the mind.","offset":438,"duration":28},{"text":"Dacher Keltner: And that’s where the field is heading is to really start to think about physiological patterns, brain patterns um of of these distinct states. And and I’ll tell you um the hard-wiring question, I mean it’s hard science to do, right? Just to imagine videotaping people from five different countries, getting their emotional expressions, and then making sense of them.","offset":466,"duration":28},{"text":"Dacher Keltner: It used to take one hour to code the facial muscle movements of of one minute, right? So this is slow science. And I would really encourage listeners um and viewers to go to alancowan.com and I had a grad student at Berkeley, Alan Cowan, who you know he’s a computational genius and he looked at our old science and said, “we can use AI to code the face” and he did it with Google engineers.","offset":494,"duration":28},{"text":"Dacher Keltner: He coded 144 um two million videos from 144 cultures and 16 facial expressions, 75% overlap across cultures in how we show awe at fireworks, concentration on a test, you know, laugh at friends. So right now I would say 50 to 60% is hard-wired as part of who we are in our evolutionary history and then the rest is subject to variation in interesting ways.","offset":522,"duration":-28},{"text":"Andrew Huberman: I’d like to take a quick break and acknowledge one of our sponsors, Joovv. Joovv makes medical grade red light therapy devices. Now if there’s one thing that I have consistently emphasized on this podcast is the incredible impact that light can have on our biology and our health. Now in addition to sunlight, which I’ve talked about a lot on this podcast, red light, near-infrared, and infrared light have been specifically shown to have positive effects on improving numerous aspects of cellular and organ health.","offset":494,"duration":90},{"text":"Andrew Huberman: These include faster muscle recovery, improved skin health, wound healing, improvements in acne, reduced pain and inflammation, improved mitochondrial function, and even improvements in vision. Nowadays there are a lot of red light devices out there, but what sets Joovv lights apart and why they’re my preferred red light therapy device is that they use clinically proven wavelengths, meaning they use the specific wavelengths of red light, near-infrared and infrared light in combination to trigger the optimal cellular adaptations.","offset":584,"duration":27},{"text":"Andrew Huberman: Personally I use the Joovv whole body panel about three to four times a week, usually for about 10 to 20 minutes per session, and I use the Joovv handheld light both at home and when I travel. If you’d like to try Joovv, they’re offering up to $400 off select products for listeners of this podcast. To learn more, visit joovv, spelled J-O-O-V-V.com/huberman. Again that’s J-O-O-V-V.com/huberman.","offset":611,"duration":28},{"text":"Andrew Huberman: Today’s episode is also brought to us by Helix Sleep. Helix Sleep makes mattresses and pillows that are customized to your unique sleep needs. Now I’ve spoken many times before on this and on other podcasts about the fact that getting a great night’s sleep is the foundation of mental health, physical health, and performance. When we aren’t getting great sleep on a consistent basis, everything suffers, and when we are sleeping well and enough, our mental health, physical health, and performance in all endeavors improve markedly.","offset":639,"duration":27},{"text":"Andrew Huberman: Now the mattress you sleep on makes a huge difference in the quality of sleep that you get each night. How soft it is or how firm it is all play into your comfort and need to be tailored to your unique sleep needs. If you go to the Helix website, you can take a brief two minute quiz and it will ask you questions such as do you sleep on your back, your side, or your stomach, maybe you know maybe you don’t, do you tend to run hot or cold during the night, things of that sort.","offset":666,"duration":22},{"text":"Andrew Huberman: You answer those questions and Helix will match you to the ideal mattress for you. For me that turned out to be the Dusk, D-U-S-K mattress. I’ve been sleeping on a Dusk mattress for more than four years now and it’s been far and away the best sleep that I’ve ever had. If you’d like to try Helix, you can go to helixsleep.com/huberman, take that two minute sleep quiz and Helix will match you to a mattress that’s customized for you.","offset":688,"duration":23},{"text":"Andrew Huberman: Right now Helix is giving up to 27% off their entire site. Helix has also teamed up with Truemed, which allows you to use your HSA FSA dollars to shop Helix’s award winning mattresses. Again that’s helixsleep.com/huberman to get up to 27% off.","offset":711,"duration":21},{"text":"Andrew Huberman: I’m going to ask a question that may or may not be possible to answer, but if anyone could it would be you. And it’s not a test, but here’s what I’m thinking. The relationship between emotions and what we call motor patterns, movement, is obviously very close, right? Disgust a recoil, uh we’ll explore awe, um anger, etc.","offset":732,"duration":26},{"text":"Andrew Huberman: And then there’s this other node which is language. Right? So we have like emotions, motor, language. Obviously those can’t be dissociated, but can we imagine somebody let’s just like hypothetical person who can keep their body very still while they’re angry and be very articulate, that includes not moving their hands, we’d probably think perhaps that person’s like sociopathic but that’s not the picture I’m trying to paint.","offset":758,"duration":28},{"text":"Andrew Huberman: Then on the other extreme, can imagine somebody who um is very angry and is gesticulating a lot and moving around, you know we can immediately “yeah, that makes that makes sense.” And we could do this for any emotion. Yep. So how should we think about emotion as an experience and how it’s expressed along these three axes, right? Which is motor, language, and then the emotion itself.","offset":786,"duration":24},{"text":"Andrew Huberman: I feel like without um conceptualizing that, I as a true novice of this, right? this isn’t my area of of understanding or expertise, I can’t really understand what an emotion is. But if I understand how those are linked, maybe maybe that’s a portal into that.","offset":810,"duration":18},{"text":"Dacher Keltner: Yeah, no, I mean it’s a profound question, Andrew, and it and it’s central to our field, which is you know the and and I appreciate it coming out of your scientific background of studying other mammals and other species and and and there are these motor patterns that you see in emotion around the world.","offset":828,"duration":22},{"text":"Dacher Keltner: When you soothe a child that’s crying, right? you’re going to bring it in close and caress and touch and have emotion when you’re, you know, when you’re uh fighting a rival or when you you see rotten food, you’re going to that motor pattern will be there. You know, and that’s part of our research that 75% of that is this motor pattern of facial musculature and body and skeletal muscles and how we respond to the emotional events of life.","offset":850,"duration":31},{"text":"Dacher Keltner: And then we have this massively complicated, you know, conceptual system that puts words to experience and that’s mainly what we study in psychological sciences, just “oh, I’m feeling angry or ashamed or embarrassed or love or compassion.”","offset":881,"duration":17},{"text":"Dacher Keltner: And we know and your question points to this like very often they’re disconnected, right? the motor pattern and the language we use and how I would interpret it in another person. Um on balance they correlate .2, so they’re just weakly they’re kind of these streams of behavior that are part of who we are, right? Our motor patterns and language.","offset":898,"duration":23},{"text":"Dacher Keltner: And there are a lot of ways to think about it. You could think about cultures that value being calm, like a lot of East Asian cultures. Be calm, don’t disrupt things, don’t blurt out, don’t protest, right? and and you’ll see this disconnect. Um you can think about certain people who they just are more authentic and their motor patterns come out in expressions and they will tell you how they feel.","offset":921,"duration":25},{"text":"Dacher Keltner: Uh so it’s a central problem that we grapple with. And then I love your your third part of this equation of emotion science, which is the feeling. The emotion. Michael Pollan is right, you know, this new book on consciousness, the conscious feeling of something. We think we can get to it with words, I don’t think so. Um you probably wouldn’t either, right? studying the other species you’ve studied, right?","offset":946,"duration":29},{"text":"Dacher Keltner: Um it’s some weird mixture of everything that’s happening in your body. And ironically the emotion or the feeling is still one of the uncharted territories of our field as why as these complicated motor patterns take unfold and words are unfolding and images and memories and visual things that you study, how does that all come together in my feeling of compassion or awe? And we barely know, you know, we just we don’t know.","offset":975,"duration":32},{"text":"Andrew Huberman: Every once in a while I’ll try and think about a concept from way outside of standard science, like the chakras or something. Yeah. And it’s kind of interesting, right? I mean even if just if one looks at it just purely as a Western scientist, this idea that maybe there is a confluence of of nerves and of vasculature and stuff that makes you feel kind of like rooted at like and and calm, right?","offset":1007,"duration":23},{"text":"Andrew Huberman: Versus like up in your head, I uh I’ve been watching this really interesting Instagram channel, it’s a woman who does voices for cartoons and she has the most incredible understanding of voice. And she’s commenting a lot of the time on people in shows that I don’t watch but they have little excerpts of where like I guess there’s this doctor on the this it’s like an ER type show, it’s like a revisiting of the show ER but she talks about how as he’s matured from season to season in his role on the show and he’s mentoring how she literally talks about how uh his larynx and pharynx are how he’s controlling those differently as he matures and then when he has a breakdown how the voice moves further up into his head and what and what that’s about.","offset":1030,"duration":43},{"text":"Andrew Huberman: And I so I was thinking about this I’m like, you know, here’s somebody that’s a very unique, you know window into all of this, but we sort of know this intuitively. Like when we’re excited like there’s this kind of rising from the bottom and when we’re relaxed everything just kind of sinks down to a the diaphragmatic breathing and things.","offset":1073,"duration":20},{"text":"Andrew Huberman: As a scientist who studies emotion, how do you sort of decide what what uh which lens to look at things through um because a lot of the stuff I’m talking about might sound a little esoteric but it’s actually the stuff that’s easiest to measure. Yeah. Presumably you can quantitatively measure like breaths per minute when somebody’s looking at an awe inspiring image versus like a trivial image.","offset":1093,"duration":25},{"text":"Dacher Keltner: I love your reference to chakras and you know the older I get, you know I’ve been doing emotion science for 34 years or five years, it’s good to think about the other traditions, you know. We wouldn’t have thought about the breath, the power of the breath uh without the contemplative meditation traditions that you’ve in part tested and Richie Davidson and others.","offset":1118,"duration":25},{"text":"Dacher Keltner: And lo and behold the breath, deep exhalation, activates the vagus nerve, calms us down. That activation of the vagus nerve gives people a sense of warmth in your chest, which kind of sounds like the heart chakra and all the speculation around how your soul is in your heart. Well there’s a neurophysiological correlate of that. Um I love the paintings of Alex Grey, the psychedelic artist, like if you want an image of what our neurophysiology is as it synchronizes in love, you could it’s pretty close, or it’s interesting, right? So it’s good to find inspiration in that.","offset":1143,"duration":32},{"text":"Dacher Keltner: One of the great things about the science of emotion and and I brought these tools into the study of awe, you know, which is we have learned a lot about how to measure emotion. You know, you can measure it with facial muscles and gaze patterns and coloration of the face and breath patterns and you know different measures of vagal tone uh and immune system activation and activation in the gut and of course brain activation and the voice, which is one of my favorite modalities.","offset":1175,"duration":31},{"text":"Dacher Keltner: I learned this in some sense from Darwin, Darwin’s “expression of emotion in man and animal” is in my view and we’re just publishing a paper on this uh on everything that he said about human emotion. 53 emotions annotated with eight modalities of expressive behavior. I wrote it with Darwin scholar Frank Sulloway, who knows everything about Darwin. And I choose how to study an emotion based on what’s what’s happening out in our lives and our the phenomena out there, right?","offset":1206,"duration":32},{"text":"Dacher Keltner: So if you’re studying awe you should get people around big trees or in musical concerts or in museums, right? Uh if you’re I studied embarrassment early in my career and modesty and I’m like I gotta study young men teasing each other because we embarrass each other, you know intentionally.","offset":1238,"duration":18},{"text":"Andrew Huberman: Oh my goodness, we have to hear about that that work again. It’s become very relevant nowadays because of the because of the I’ll just call it what it is, it’s not dread-it, it’s the dreadful man-o-sphere, you know, which people use very broadly but I think now it’s being you know allocated to the the worst of the worst.","offset":1256,"duration":22},{"text":"Andrew Huberman: But then there is this phenomenon among males where they’ll rib each other and you know and there’s there’s a healthy version of males interacting too, right? you know uh so we’ll get back to that.","offset":1278,"duration":8},{"text":"Dacher Keltner: I base it on what’s the phenomenon of interest, right? That that speaks to humanity and then what are our best measures that we can go after it.","offset":1286,"duration":9},{"text":"Andrew Huberman: These days if you want to measure awe, what’s your favorite awe stimulus?","offset":1295,"duration":5},{"text":"Dacher Keltner: First off and thank you for asking about measurement, like it’s interesting like people are like “oh, you can’t study awe, you know you don’t know how to measure it, it’s ineffable, it’s mysterious, it’s spiritual.” We can measure awe really well, you know, the vocalization “whoa”, you know, the facial expression uh activation part parts of the brain are deactivated, uh vagal tone, the goosebumps is a good uh part of the awe response.","offset":1300,"duration":29},{"text":"Dacher Keltner: As we started to study awe, we did two things. And one is typical West you know science, which is get your most cool awe videos, show them to people, you know, and I had some missteps in this science. I had a woman who was an honors student at Berkeley who was coming back from Burning Man and you know she’s like “I’m going to show engineers fractal imagery” and you know and the engineers are like “who is this woman?”","offset":1329,"duration":29},{"text":"Andrew Huberman: I mean there is the I’ve never been to Burning Man but there is the post Burning Man glow that people come back with that is for understandable reason hard for most people to enter with them. It’s like a kid coming back from summer camp.","offset":1358,"duration":12},{"text":"Dacher Keltner: There’s great visual imagery, you know BBC Earth is awesome and it it uh makes people feel awe. Slow motion guys, I don’t know if you know these guys, they film wild things in slow motion, like you know dropping a wine glass in this spectacular photography and just you know you’re like “whoa.”","offset":1370,"duration":20},{"text":"Andrew Huberman: Cool, we’ll put a link to that. I I love super slow mo.","offset":1390,"duration":3},{"text":"Dacher Keltner: Yeah. Um and that fits our definition which is like you don’t understand what’s happening, it’s vast, it’s mysterious. But what I’m really proud of Andrew is the work we did out in the field, right? So one of our first studies on the Berkeley campus that you frequented and got your Master’s degree at and headed into neuroscience was uh in our paleontology museum there’s a replica of a T-Rex skeleton.","offset":1393,"duration":26},{"text":"Dacher Keltner: When I was five years old and and I learned about dinosaurs it changed my life. It was just in the LA Natural History Museum like “wow!” So we studied people standing near the T-Rex skeleton and they became expansive and collective. We studied people near giant eucalyptus trees. We studied people at Yosemite, you know, Yang Bai a student in my lab stopped hundreds of travelers from all over the world right when you see Yosemite and she said, “how do you feel about yourself right now?” And they’re like “I feel small and quiet but part of something really large”, right?","offset":1419,"duration":35},{"text":"Dacher Keltner: Um subsequent to that there are scientists who are studying mosh pits at concerts and, you know, surfers and, you know, rock clim- I mean it’s, you know, backpackers and, you know, we studied one of my favorite studies later with Stacy Bare, who’s a veteran who ran the who’s an amazing human being, an awe pioneer, we studied people rafting down the American River, you know, veterans just like “whoa.” We’ve studied people in art museums, Carnegie Hall, you know, so it’s it you know one of the joys is when science you know just in the spirit of your questions, it’s like “well what should I really do here, right? I could stay in the lab” it’s like “no, you know, we gotta go do stuff”, you know, that that uh my dream study was to like have a participant come in and in engage a conversation the other participant is Shaquille O’Neal, right? And it’s like 7’2”, 350 pounds, you’d be like “whoa!” but couldn’t do that. So uh so they it’s been fun. It’s been a wild ride.","offset":1454,"duration":64},{"text":"Andrew Huberman: And so many thoughts uh first one um I’m lucky I didn’t rotate through your lab because I uh would have never become a neuroscientist but I’m unlucky because it would have been so much fun to because I while I loved the wet lab as they call it getting into these experiments would just be incredible.","offset":1518,"duration":21},{"text":"Andrew Huberman: Couple things uh the Shaquille O’Neal thing I um, you know I think we’re all moved by these uh I guess they used to call them Make A Wish Foundation things where a kid who sadly is dying gets some last wish and it’s a tragic circumstance but then you get to observe these kids and most importantly they get to experience something that they never could have imagined happening like like a Shaquille O’Neal walking in, I feel like that’s probably happened or something.","offset":1539,"duration":31},{"text":"Andrew Huberman: And I think what we’re witnessing in those moments has to be awe. Like they can’t believe that this human or this event, whatever it is that they wish for is happening there. And so it’s layers upon layers, there’s like a grief component for those of us watching.","offset":1570,"duration":14},{"text":"Dacher Keltner: Well put.","offset":1584,"duration":1},{"text":"Andrew Huberman: But a huge aspect of the of just how touching it is is the fact that like for those moments they’re not thinking about their mortality and no kid should have to think about their mortality right I mean even as I talk about it it’s like uh yeah it’s just it’s like uh there’s an overwhelming in the opposite direction, right?","offset":1585,"duration":17},{"text":"Andrew Huberman: That’s an in particularly uh complicated and and interesting uh case where you’ve got two things colliding, right? Because I feel like awe is so life affirming. Yeah, it is. It is. And uh anyway that’s just an in observation but horizons are something that fascinate me for a long time as a vision scientist because when we see a horizon our visual uh angle widens.","offset":1602,"duration":22},{"text":"Dacher Keltner: That’s cool.","offset":1624,"duration":1},{"text":"Andrew Huberman: We become more parasympathetic. There’s a whole coming off the accelerator of the sympathetic nervous system so we relax by virtue of coming off the focusing component. When we focus in through a tunnel we it’s quite the opposite.","offset":1625,"duration":12},{"text":"Dacher Keltner: Nice.","offset":1637,"duration":1},{"text":"Andrew Huberman: But I feel like there’s something unique to this experience of being in a tunnel, I’m thinking about Yosemite, or in a bunch of trees or hike and then the horizon opens up. Yeah. There’s this transformation of visual space and those moments at least for me are the moments. Like I can hike along a ridgeline for a long time like “this is amazing” but there’s something distinctly bigger in the experience of going from confinement to openness.","offset":1638,"duration":30},{"text":"Andrew Huberman: It could be brought to the lab but do you think that’s what’s going on in in Yosemite or the Grand Canyon? Right? Do people work in Yosemite and the Grand Canyon do they attenuate? They’re like “oh, yeah, like another horizon.”","offset":1668,"duration":11},{"text":"Dacher Keltner: I don’t know, you know, working with rangers right now and they I think I think the big expansive forms of awe that those places provide is attenuated but I think they’re still finding it in subtler ways. Yeah, that’s really interesting and, you know, it’s interesting I was uh I’ve been privileged to know Pete Docter at Pixar for 15 years and worked on some of his films, Inside Out and Inside Out 2 and Soul.","offset":1679,"duration":25},{"text":"Andrew Huberman: You played a big role in that.","offset":1704,"duration":2},{"text":"Dacher Keltner: Yeah, and through this science of emotion. And I was like, you know in one of our conversations I was like “tell me about some techniques for producing awe in children’s films, animated films” and he described first just what you said like, you know, the film is narrow like a certain kind of attention, you know sort of sympathetic, fearful, checking things, and then boom it comes it suddenly you see the vastness of something and it’s true, it is awe inspiring.","offset":1706,"duration":29},{"text":"Dacher Keltner: When you think about it neuroscientifically as a very basic form of awe is shifting from small to vast in terms of vision and perception and then it becomes metaphorical, right? It’s like “god I’m thinking about” like I love one of the wonders of life that uh that makes us feel awe is big ideas and epiphanies and very often people will be like “god I’ve been working so hard at this, you know working on a a paper, something in technology or some part of my life” and then you suddenly realize it’s part of something large, right?","offset":1735,"duration":32},{"text":"Dacher Keltner: One of the musicians that I interviewed, Yumi Kendall, in the book in the chapter on musical awe said, “you know” she’s a cellist for the Philadelphia Symphony said, “you know I practice for five hours a day, it’s hard man and it’s small and narrow and where’s my finger? and then when I’m on stage and I and I feel the notes go out into this space”, the vastness you’re talking about, “I feel like I’m part of history”, right? And I tear up and cry.","offset":1767,"duration":29},{"text":"Dacher Keltner: Um so I think your I think I you gotta send me those papers Andrew because I think it’s fundamental which is from small to vast. And in fact we did this really cool study with Virginia Sturm at UC San Francisco Brain Health, old people go out on an awe walk once a week for eight weeks, 75 years old or older, and all we asked them to do is to go from small to vast and how they looked at things, you know. Look at a tree, look at a leaf, go out to the pattern of leaves. It brought them awe and less physical pain uh over eight weeks and now we’re finding six years later better brain health, right? So small to vast is a big part of it.","offset":1796,"duration":39},{"text":"Andrew Huberman: I’m um struck by the by the awe walk um and and I know this comes up in your book and elsewhere and you’ve done a lot of research on this. Um for those listening um what would an awe walk look like and um what are some of the health benefits? You just mentioned a few that that have been observed both in the short and the long term.","offset":1835,"duration":18},{"text":"Dacher Keltner: Yeah, thank you, you know, uh we we are a walking species, you know, it is just in our DNA to walk. We meandered from Africa all to all the continents. A lot of people, Rebecca Solnit writes about this like “walking is almost sacred, it’s a kind of consciousness” like you’re saying like “whoa, I’m I’m picking up a vaster view of what’s around me.”","offset":1853,"duration":25},{"text":"Dacher Keltner: And I uh decided to just create this awe walk, you know, and I did it for a meditation group the or Mindful Magazine. You just slow down, you a lot of people walk, hundreds of, you know, tens of millions of people have regular walks in the United States. Uh it’s good for you, you know, so we just added awe.","offset":1878,"duration":19},{"text":"Dacher Keltner: Like on your regular walk, once a week in our study, uh go somewhere you wouldn’t ordinarily go, go some place that may surprise you. Uh I walk around Berkeley a lot and I was like “well I’m going to go past the little playground that my daughters played at when they were young and just feel that”, you know, Cordornices Park.","offset":1897,"duration":19},{"text":"Andrew Huberman: Yeah. With the rock slide.","offset":1916,"duration":2},{"text":"Dacher Keltner: And the tunnel.","offset":1918,"duration":1},{"text":"Andrew Huberman: Exactly.","offset":1919,"duration":1},{"text":"Dacher Keltner: I love that place.","offset":1920,"duration":1},{"text":"Andrew Huberman: Near the rose garden.","offset":1921,"duration":2},{"text":"Dacher Keltner: Exactly.","offset":1923,"duration":1},{"text":"Andrew Huberman: And there’s a secret, should we give this away? Yeah. There’s a secret hiking trail through it’s actually through a private property’s backyard and they allow you to go through if you are quiet and you pick up your trash and there’s an incredible waterfall and place to stand at the top, there’s a beam there, you’ve been there I’m sure where you can look out over this what is kind of like a trench of tree- it’s a total transformation of one space to the next if you if you look for it properly, I’m sure now it’s on the internet. Um it’s in kind of swinging gates, not locked, and uh so hard to find.","offset":1924,"duration":37},{"text":"Dacher Keltner: And and there’s a little monastery maybe nearby and uh and you might and you might see me a couple years ago you would have seen me and my dog, but you might see me uh eating a slice of pizza from the Cheese Board sitting on that log. I spent a lot of time there.","offset":1961,"duration":15},{"text":"Andrew Huberman: I’m getting goosebumps Andrew, that is just pure Berkeley, thank you. So yeah, so in this study awe walk go on your walk, find a place that’s going to be a little surprising where it may make you feel a little bit of childlike wonder.","offset":1976,"duration":14},{"text":"Dacher Keltner: And it’s interesting, no one’s asked me this question, you know your observation about small to vast and we just said slow down, deepen your breathing, sync it up with your your walking, which you’ve studied empirically the breath. And then um go from small to vast, you know.","offset":1990,"duration":18},{"text":"Dacher Keltner: Look at clouds, look at the whole pattern of clouds, just slow it down. Look at trees, look at the light on the trees and look at points of light and then patterns of light. Look at, you know I love walking past playgrounds as one of my favorite sources of awe, listen to one laugh and then listen to the whole symphony of laughter of kids, right?","offset":2008,"duration":22},{"text":"Dacher Keltner: That’s all. And they walk through uh they do that for half an hour and what we find in that study is is they become more vast in their consciousness. They’re more aware in the photographs that they provided of what’s around them. They feel more kindness over the eight weeks. They feel more awe over an eight week period, it rises.","offset":2030,"duration":20},{"text":"Dacher Keltner: And then the the finding that was you know important for people who are elderly is less physical pain. You know, your body starts to ache when you’re 75, you know, uh or earlier and awe I think through the inflammation process, you know in reducing it, caused less pain.","offset":2050,"duration":21},{"text":"Dacher Keltner: You know this dovetails with other health benefits, awe is good for reduced inflammation, elevated vagal tone, reduced long COVID symptoms. We have people with long COVID, just a minute of awe a day reduced long COVID symptoms. It’s good news, right?","offset":2071,"duration":18},{"text":"Dacher Keltner: And and there’s so much science on it that I just now, I think medical doctors are starting to think like “I’m going to prescribe nature, I’ll prescribe music” through awe, right? Uh as a mechanism.","offset":2089,"duration":16},{"text":"Andrew Huberman: I have a lot of thoughts about um this going from uh small to large. Yeah, I’d love to hear them. But before I do, um I have an- I have another question. I think for a lot of people, um including myself, we assume that awe is this kind of forgetting of ourselves. Like see- like getting outside of ourselves.","offset":2105,"duration":23},{"text":"Andrew Huberman: But I’m starting to think based on the way you’re describing it that it’s about being tethered to the larger picture. That it’s not a get- yes it’s getting out of our heads quote unquote, but it’s actually very much an embodied experience. It’s very like it’s almost like full body. Yeah, so now I’ll answer your question, this is usually where people start putting in the comments like “you talk too much, let your your guest talk” but trying folks, he asked me twice.","offset":2128,"duration":26},{"text":"Andrew Huberman: So you asked me a question, I’m going to answer it. Anyone that knows me you know if I- Okay, so I’ve thought about this this relationship between visual aperture and uh time perception.","offset":2154,"duration":15},{"text":"Dacher Keltner: Cool.","offset":2169,"duration":1},{"text":"Andrew Huberman: This is my my deepest obsession and it uh gets a little bit into the book I’m writing but it but it’s probably reserved for after there’s some experiments. And and I um to the fear of my podcast crew, I actually am considering going back into the lab to do this experiment.","offset":2170,"duration":16},{"text":"Andrew Huberman: Okay. So we know what do we know for certain? We know for certain that when your visual aperture is small, like looking through a soda straw view or watchmaker type aperture, or um you’re in a let’s just say a pleasant or unpleasant text communication that’s going back and forth, that your perception of time is different. You’re fine-slicing. Those dot-dot-dots coming through, yeah it’s just it feels like an eternity.","offset":2186,"duration":26},{"text":"Dacher Keltner: Yeah, just it’s like.","offset":2212,"duration":1},{"text":"Andrew Huberman: And it’s bidirectional with your let’s just call it level of alertness, it doesn’t even have to be stress but sympathetic nervous system, right? So if I’m in line at the store and and I have some place to be, my visual aperture shrinks and then it feels like the person in front of me is taking forever. Yeah because you’re in these little micro.","offset":2213,"duration":16},{"text":"Andrew Huberman: When I’m relaxed it feels like I’m I’m slicing time differently. Okay. When we see a horizon and and our aperture opens up as I mentioned then we relax, but we also are taking fewer time bin snapshots. So people might think “oh fewer you’re in slow motion” because the word “no”, you’re it’s the opposite, right? Slow motion is high frame rate.","offset":2229,"duration":25},{"text":"Andrew Huberman: This thing about video where you can catch slow motion, you need high frame rate. This is why when people experience uh like a car crash they’ll often say that things felt like they were slowing down. More snapshots.","offset":2254,"duration":12},{"text":"Dacher Keltner: That’s cool.","offset":2266,"duration":1},{"text":"Andrew Huberman: So when I think about this relationship between visual aperture and time, and it also exists in the auditory domain. So if I’m listening to a specific conversation at a party, I’m fine-slicing my perception of auditory space. Our friend Erv Hafter taught me this.","offset":2267,"duration":16},{"text":"Andrew Huberman: When I listen to everything and I take it in as a whole, it’s it’s a more relaxed experience but okay. So a long time ago I was because I was experiencing stress, I started reading about meditation types and different things and and I I came up with this meditation, but it’s not a meditation at all and some of my listeners will be familiar with it, I decided to call it for lack of a better term Space-Time Bridging.","offset":2283,"duration":23},{"text":"Andrew Huberman: The meditation is very simple. You um close your eyes and you do three breaths thinking about your skin inward, so interoception. You open your eyes and you look at your hand and you take three breaths, but you’re creating a visual tether between you and your hand. Then you look some distance, maybe eight or 10 feet away, you do the same. Then you find a horizon, and then you think about the sort of pale blue dot phenomenon like you’re just on a planet floating in space and like every single one of these things is a form of meditation or a meme or or whatever.","offset":2306,"duration":23},{"text":"Andrew Huberman: And then you get right back to yourself. And so what the idea here is that it helped me a lot because I noticed that meditations where I was completely focused inward made me more focused inward. Going for a run I could get outside my head but it and I started to play with the idea that maybe it’s not about having a small aperture or a big aperture per se, yeah but it’s the like every great thing in biology or psychology, it’s the process, it’s not an event.","offset":2329,"duration":26},{"text":"Andrew Huberman: It’s the process of going from one aperture to the next. And that’s kind of what life is about. That’s cool. Yeah. Absolutely. Like when “this too shall pass” is really about taking a broader time snapshot, like eventually this thing, which is visual as well.","offset":2355,"duration":16},{"text":"Dacher Keltner: Which is visual as well.","offset":2371,"duration":1},{"text":"Andrew Huberman: And so this is a long answer to your question, but um this is why it’s so important for me to see a horizon if I can in the morning um but it’s also very important to go indoors and just like focus on what I’m working on. Like there is no place or event in a day or in life that that’s actually the right way to live. Like you can go to Big Sur and if you’re lucky enough to go to Esalen like you’re like “this is it” but it’s only it because you came from your office, in my opinion, and then you go back again.","offset":2372,"duration":30},{"text":"Andrew Huberman: You’ve figured this out, like you have this- the title of this paper for which you’re the senior author is “A Balanced Mind: Awe Fosters Equanimity via Temporal Distancing.” So it’s so it’s about time, not about space.","offset":2402,"duration":15},{"text":"Dacher Keltner: It is. That’s fascinating.","offset":2417,"duration":2},{"text":"Andrew Huberman: Okay, so that’s so that’s how I think about this. Now maybe you can tell us about this paper because I’m getting embarrassed that I’ve been going way too long.","offset":2419,"duration":5},{"text":"Dacher Keltner: This is why we’re in conversation, Andrew, which is, you know, you’ve studied the visual system and and we need more of that knowledge in the science of awe. And I will just make one parenthetical note, which is I was interviewing Pete Docter at Pixar for 15 years and worked on some of his films, Inside Out and Inside Out 2 and Soul.","offset":2424,"duration":22},{"text":"Andrew Huberman: You played a big role in that.","offset":2446,"duration":2},{"text":"Dacher Keltner: Yeah, and through this science of emotion. And I was like, you know in one of our conversations I was like “tell me about some techniques for producing awe in children’s films, animated films” and he described first just what you said like, you know, the film is narrow like a certain kind of attention, you know sort of sympathetic, fearful, checking things, and then boom it comes it suddenly you see the vastness of something and it’s true, it is awe inspiring.","offset":2448,"duration":29},{"text":"Dacher Keltner: When you think about it neuroscientifically as a very basic form of awe is shifting from small to vast in terms of vision and perception and then it becomes metaphorical, right? It’s like “god I’m thinking about” like I love one of the wonders of life that uh that makes us feel awe is big ideas and epiphanies and very often people will be like “god I’ve been working so hard at this, you know working on a a paper, something in technology or some part of my life” and then you suddenly realize it’s part of something large, right?","offset":2477,"duration":32},{"text":"Dacher Keltner: One of the musicians that I interviewed, Yumi Kendall, in the book in the chapter on musical awe said, “you know” she’s a cellist for the Philadelphia Symphony said, “you know I practice for five hours a day, it’s hard man and it’s small and narrow and where’s my finger? and then when I’m on stage and I and I feel the notes go out into this space”, the vastness you’re talking about, “I feel like I’m part of history”, right? And I tear up and cry.","offset":2509,"duration":30},{"text":"Dacher Keltner: Um so I think your I think I you gotta send me those papers Andrew because I think it’s fundamental which is from small to vast. And in fact we did this really cool study with Virginia Sturm at UC San Francisco Brain Health, old people go out on an awe walk once a week for eight weeks, 75 years old or older, and all we asked them to do is to go from small to vast and how they looked at things, you know. Look at a tree, look at a leaf, go out to the pattern of leaves. It brought them awe and less physical pain uh over eight weeks and now we’re finding six years later better brain health, right? So small to vast is a big part of it.","offset":2539,"duration":22},{"text":"Andrew Huberman: I didn’t expect that we would land here, at least not so early in the conversation but you know we we’ve had Christoph Koch on this podcast talking about consciousness, you know, incredible neuroscientist and really thinker, I mean I’ve watched his career evolve over the years and and he’s continued to evolve his concepts of how to think about consciousness and uh and you’ll hear nowadays about “oh like maybe consciousness is outside the brain” and I think if nothing else our brains are important components in it, heck yeah I don’t want to do the experiment on myself to find out like if I was decerebrated or something, which basically means having your cortex removed, sorry for the nerd speak.","offset":2561,"duration":37},{"text":"Andrew Huberman: But the idea is connecting through time like in our own lives is a very unique form of awe. So like if I hear a song and it reminds me of when I was like 15 and then all of a sudden all the the mat- as I call it video whatever it is that they wish for is happening there. And so it’s layers upon layers, there’s like a grief component for those of us watching.","offset":2598,"duration":19},{"text":"Dacher Keltner: Well put.","offset":2617,"duration":1},{"text":"Andrew Huberman: But a huge aspect of the of just how touching it is is the fact that like for those moments they’re not thinking about their mortality and no kid should have to think about their mortality right I mean even as I talk about it it’s like uh yeah it’s just it’s like uh there’s an overwhelming in the opposite direction, right?","offset":2618,"duration":17},{"text":"Andrew Huberman: That’s an in particularly uh complicated and and interesting uh case where you’ve got two things colliding, right? Because I feel like awe is so life affirming. Yeah, it is. It is. And uh anyway that’s just an in observation but horizons are something that fascinate me for a long time as a vision scientist because when we see a horizon our visual uh angle widens.","offset":2635,"duration":22},{"text":"Dacher Keltner: That’s cool.","offset":2657,"duration":1},{"text":"Andrew Huberman: We become more parasympathetic. There’s a whole coming off the accelerator of the sympathetic nervous system so we relax by virtue of coming off the focusing component. When we focus in through a tunnel we it’s quite the opposite.","offset":2658,"duration":13},{"text":"Dacher Keltner: Nice.","offset":2671,"duration":1},{"text":"Andrew Huberman: But I feel like there’s something unique to this experience of being in a tunnel, I’m thinking about Yosemite, or in a bunch of trees or hike and then the horizon opens up. Yeah. There’s this transformation of visual space and those moments at least for me are the moments. Like I can hike along a ridgeline for a long time like “this is amazing” but there’s something distinctly bigger in the experience of going from confinement to openness.","offset":2672,"duration":29},{"text":"Andrew Huberman: It could be brought to the lab but do you think that’s what’s going on in in Yosemite or the Grand Canyon? Right? Do people work in Yosemite and the Grand Canyon do they attenuate? They’re like “oh, yeah, like another horizon.”","offset":2701,"duration":11},{"text":"Dacher Keltner: I don’t know, you know, working with rangers right now and they I think I think the big expansive forms of awe that those places provide is attenuated but I think they’re still finding it in subtler ways. Yeah, that’s really interesting and, you know, it’s interesting I was uh I’ve been privileged to know Pete Docter at Pixar for 15 years and worked on some of his films, Inside Out and Inside Out 2 and Soul.","offset":2712,"duration":26},{"text":"Andrew Huberman: You played a big role in that.","offset":2738,"duration":2},{"text":"Dacher Keltner: Yeah, and through this science of emotion. And I was like, you know in one of our conversations I was like “tell me about some techniques for producing awe in children’s films, animated films” and he described first just what you said like, you know, the film is narrow like a certain kind of attention, you know sort of sympathetic, fearful, checking things, and then boom it comes it suddenly you see the vastness of something and it’s true, it is awe inspiring.","offset":2740,"duration":28},{"text":"Dacher Keltner: When you think about it neuroscientifically as a very basic form of awe is shifting from small to vast in terms of vision and perception and then it becomes metaphorical, right? It’s like “god I’m thinking about” like I love one of the wonders of life that uh that makes us feel awe is big ideas and epiphanies and very often people will be like “god I’ve been working so hard at this, you know working on a a paper, something in technology or some part of my life” and then you suddenly realize it’s part of something large, right?","offset":2768,"duration":32},{"text":"Dacher Keltner: One of the musicians that I interviewed, Yumi Kendall, in the book in the chapter on musical awe said, “you know” she’s a cellist for the Philadelphia Symphony said, “you know I practice for five hours a day, it’s hard man and it’s small and narrow and where’s my finger? and then when I’m on stage and I and I feel the notes go out into this space”, the vastness you’re talking about, “I feel like I’m part of history”, right? And I tear up and cry.","offset":2800,"duration":29},{"text":"Dacher Keltner: Um so I think your I think I you gotta send me those papers Andrew because I think it’s fundamental which is from small to vast. And in fact we did this really cool study with Virginia Sturm at UC San Francisco Brain Health, old people go out on an awe walk once a week for eight weeks, 75 years old or older, and all we asked them to do is to go from small to vast and how they looked at things, you know. Look at a tree, look at a leaf, go out to the pattern of leaves. It brought them awe and less physical pain uh over eight weeks and now we’re finding six years later better brain health, right? So small to vast is a big part of it.","offset":2829,"duration":20},{"text":"Andrew Huberman: As many of you know, I’ve been taking AG1 for nearly 15 years now. I discovered it way back in 2012 long before I ever had a podcast and I’ve been taking it every day since. The reason I started taking it and the reason I still take it is because AG1 is to my knowledge the highest quality and most comprehensive of the foundational nutritional supplements on the market.","offset":2849,"duration":24},{"text":"Andrew Huberman: It combines vitamins, minerals, prebiotics, probiotics, and adaptogens into a single scoop that’s easy to drink and it tastes great. It’s designed to support things like gut health, immune health, and overall energy and it does so by helping to fill any gaps you might have in your daily nutrition. Now of course everyone should strive to eat nutritious whole foods, I certainly do that every day, but I’m often asked if you could take just one supplement what would that supplement be and my answer is always AG1 because it has just been oh so critical to supporting all aspects of my physical health, mental health, and performance.","offset":2873,"duration":37},{"text":"Andrew Huberman: I know this from my own experience with AG1 and I continually hear this from other people who use AG1 daily. If you would like to try AG1, you can go to drinkAG1, with the numeral one, .com/huberman to get a special offer. For a limited time AG1 is giving away six free travel packs of AG1 and a bottle of vitamin D3 K2 with your subscription. Again that’s drinkAG1, with the numeral one, .com/huberman to get six free travel packs and a bottle of vitamin D3 K2 with your subscription.","offset":2910,"duration":33},{"text":"Andrew Huberman: I didn’t expect that we would land here, at least not so early in the conversation but you know we we’ve had Christoph Koch on this podcast talking about consciousness, you know, incredible neuroscientist and really thinker, I mean I’ve watched his career evolve over the years and and he’s continued to evolve his concepts of how to think about consciousness and uh and you’ll hear nowadays about “oh like maybe consciousness is outside the brain” and I think if nothing else our brains are important components in it, heck yeah I don’t want to do the experiment on myself to find out like if I was decerebrated or something, which basically means having your cortex removed, sorry for the nerd speak.","offset":2943,"duration":37},{"text":"Andrew Huberman: But the idea is connecting through time like in our own lives is a very unique form of awe. So like if I hear a song and it reminds me of when I was like 15 and then all of a sudden all the the mat- as I call it video whatever it is that they wish for is happening there. And so it’s layers upon layers, there’s like a grief component for those of us watching.","offset":2980,"duration":19},{"text":"Dacher Keltner: Well put.","offset":2999,"duration":1},{"text":"Andrew Huberman: But a huge aspect of the of just how touching it is is the fact that like for those moments they’re not thinking about their mortality and no kid should have to think about their mortality right I mean even as I talk about it it’s like uh yeah it’s just it’s like uh there’s an overwhelming in the opposite direction, right?","offset":3000,"duration":17},{"text":"Andrew Huberman: That’s an in particularly uh complicated and and interesting uh case where you’ve got two things colliding, right? Because I feel like awe is so life affirming. Yeah, it is. It is. And uh anyway that’s just an in observation but horizons are something that fascinate me for a long time as a vision scientist because when we see a horizon our visual uh angle widens.","offset":3017,"duration":20},{"text":"Dacher Keltner: That’s cool.","offset":3037,"duration":1},{"text":"Andrew Huberman: We become more parasympathetic. There’s a whole coming off the accelerator of the sympathetic nervous system so we relax by virtue of coming off the focusing component. When we focus in through a tunnel we it’s quite the opposite.","offset":3038,"duration":13},{"text":"Dacher Keltner: Nice.","offset":3051,"duration":1},{"text":"Andrew Huberman: But I feel like there’s something unique to this experience of being in a tunnel, I’m thinking about Yosemite, or in a bunch of trees or hike and then the horizon opens up. Yeah. There’s this transformation of visual space and those moments at least for me are the moments. Like I can hike along a ridgeline for a long time like “this is amazing” but there’s something distinctly bigger in the experience of going from confinement to openness.","offset":3052,"duration":29},{"text":"Andrew Huberman: It could be brought to the lab but do you think that’s what’s going on in in Yosemite or the Grand Canyon? Right? Do people work in Yosemite and the Grand Canyon do they attenuate? They’re like “oh, yeah, like another horizon.”","offset":3081,"duration":11},{"text":"Dacher Keltner: I don’t know, you know, working with rangers right now and they I think I think the big expansive forms of awe that those places provide is attenuated but I think they’re still finding it in subtler ways. Yeah, that’s really interesting and, you know, it’s interesting I was uh I’ve been privileged to know Pete Docter at Pixar for 15 years and worked on some of his films, Inside Out and Inside Out 2 and Soul.","offset":3092,"duration":26},{"text":"Andrew Huberman: You played a big role in that.","offset":3118,"duration":2},{"text":"Dacher Keltner: Yeah, and through this science of emotion. And I was like, you know in one of our conversations I was like “tell me about some techniques for producing awe in children’s films, animated films” and he described first just what you said like, you know, the film is narrow like a certain kind of attention, you know sort of sympathetic, fearful, checking things, and then boom it comes it suddenly you see the vastness of something and it’s true, it is awe inspiring.","offset":3120,"duration":28},{"text":"Dacher Keltner: When you think about it neuroscientifically as a very basic form of awe is shifting from small to vast in terms of vision and perception and then it becomes metaphorical, right? It’s like “god I’m thinking about” like I love one of the wonders of life that uh that makes us feel awe is big ideas and epiphanies and very often people will be like “god I’ve been working so hard at this, you know working on a a paper, something in technology or some part of my life” and then you suddenly realize it’s part of something large, right?","offset":3148,"duration":32},{"text":"Dacher Keltner: One of the musicians that I interviewed, Yumi Kendall, in the book in the chapter on musical awe said, “you know” she’s a cellist for the Philadelphia Symphony said, “you know I practice for five hours a day, it’s hard man and it’s small and narrow and where’s my finger? and then when I’m on stage and I and I feel the notes go out into this space”, the vastness you’re talking about, “I feel like I’m part of history”, right? And I tear up and cry.","offset":3180,"duration":30},{"text":"Dacher Keltner: Um so I think your I think I you gotta send me those papers Andrew because I think it’s fundamental which is from small to vast. And in fact we did this really cool study with Virginia Sturm at UC San Francisco Brain Health, old people go out on an awe walk once a week for eight weeks, 75 years old or older, and all we asked them to do is to go from small to vast and how they looked at things, you know. Look at a tree, look at a leaf, go out to the pattern of leaves. It brought them awe and less physical pain uh over eight weeks and now we’re finding six years later better brain health, right? So small to vast is a big part of it.","offset":3210,"duration":21},{"text":"Andrew: And I think it was just you know the I just got the adrenaline back. And there's a little bit of you don't know what it is going to happen and it feels a little dangerous, but it's mostly benevolent and um it's an irreplaceable feeling and and I think about it sometimes uh I think about a lot of the time.","offset":3231,"duration":20},{"text":"Dacher: Yeah, and you know, thank you. And I, you know, when I was writing this book on awe, some forms of awe, you know there are eight wonders that give us awe, you know, some are you kind of understand them, nature's pretty straightforward, spirituality, meditation, you know. And music and your description of it exactly exactly captures how rich it is and complicated.","offset":3251,"duration":23},{"text":"Dacher: Which is there is something about that sound and the acoustic patterns that come through your eardrums and head into your auditory cortex and you give it meaning and suddenly you're remembering things and bonding with people and insta-friends, like you said, for life. You know, brothers and sisters almost that and you're like this is what life's about.","offset":3274,"duration":25},{"text":"Dacher: And Susanne Langer, a philosopher, really got it right. She's like music is this tonal language of emotion and identity. And awe in music, very fitting with our conversation, is when those sounds come into you, move you, and connect you to something that is what you care about in life. You know, I remember I grew up I was very lucky to grow up in Laurel Canyon in the late 60s and there was more music there than I almost anywhere in human history.","offset":3299,"duration":34},{"text":"Dacher: You know, from you know, the Mamas & the Papas and Frank Zappa and Jim Morrison was living there.","offset":3333,"duration":6},{"text":"Andrew: Jim Morrison was out there.","offset":3339,"duration":1},{"text":"Dacher: And the Doors, and the you know, Bob Dylan was passing through, and the Birds, it's a joke, you know. It was everywhere.","offset":3340,"duration":6},{"text":"Andrew: That's wild just to think about how much incredible music was being created.","offset":3346,"duration":5},{"text":"Dacher: Oh man, you know, the Beach Boys were, you know, at I mean weren't Fleetwood Mac back in Topanga. Yeah. I mean it was like and I was eight and nine and just a you know, to grow up on Bob Dylan. And when I saw the recent film with Timothée Chalamet, I start crying, you know I was just like this is life, you know.","offset":3351,"duration":20},{"text":"Dacher: Yeah, and so that's why we study awe, you know. It it and and you know music is one of our great technologies. Uh, there's now research showing it's good for chronic pain. I think it's a frontier in healthcare and, you know, just giving people contemplative meditative approaches to music and and awe is part of the answer.","offset":3371,"duration":22},{"text":"Dacher: And you and I shared yet another thing, Andrew. You know, when I uh grew up in the foothills of the Sierras as a teenager, Ted Nugent and you know this poor white you know area, Ted Nugent, AC/DC, and that's all fine. And when I first heard the Sex Pistols in I was lucky to be in England when Never Mind the Bollocks came out and I was in a working class fighting town and I heard that.","offset":3393,"duration":29},{"text":"Dacher: I was like that's it. And then that led me to Iggy Pop, who's one of my moral heroes. So you know, um...","offset":3422,"duration":7},{"text":"Andrew: Amazing. Who's really into Qigong apparently. I heard him like years ago on the radio and and someone was asking him like how does he stay in such good shape and he's just does tons of Qigong breathing.","offset":3429,"duration":10},{"text":"Dacher: Yeah.","offset":3439,"duration":1},{"text":"Andrew: Wild, wild, wild. You know, it's interesting because a lot of music has lyrics and a lot doesn't. But there's something that feels kind of um divorced from language about the experience that we're talking about even though there's lyrics tied in there. And what brings that to mind is there's a really good book, one that I like anyway, um called A Fighter's Heart by a guy named Sam Sheridan.","offset":3440,"duration":24},{"text":"Andrew: His wife actually wrote that movie Monster um with Charlize Theron, I think is uh the actress that played her. And uh and I don't know Sam but but there's this description of all these different martial arts forms and he explores them all and um there's this great line in there.","offset":3464,"duration":16},{"text":"Andrew: Because I've done a little bit of boxing um and sparred a bit. I don't recommend as a neuroscientist how can I recommend it, right?","offset":3480,"duration":9},{"text":"Dacher: Yeah, what were you doing?","offset":3489,"duration":1},{"text":"Andrew: You get hit. Oh, I was and that was actually in my 30s. But anyway, I was working some stuff out. But uh do not recommend uh the sport yeah, the training yeah, but you don't want to get hit in the head. Not good for your brain whatsoever. But he talks about how um fighting with someone, sparring or a fighting with someone is uh he said it's like a it's one of the most bonding experiences that you'll ever have because you're in this primitive non-language state.","offset":3490,"duration":25},{"text":"Andrew: Yeah. I mean he actually likens it to a one-night stand. He says something like, oh you know you're sharing bodily fluids with somebody that you barely know but you you feel connected you know. So I don't know if that's the best certainly not the most politically correct uh way of put it.","offset":3515,"duration":16},{"text":"Dacher: Definitely.","offset":3531,"duration":1},{"text":"Andrew: But I understand what he's talking about, right? You're you're in this moment of you're both vulnerable. In the case of the fighting, you're both vulnerable, you're both trying to hurt each other, you're also obeying some rules, right? It's not not an anything goes.","offset":3532,"duration":14},{"text":"Andrew: And he talks about how it transcends language. And that creates a forever bond. And it's true, right? I didn't do a ton of sparring but you have a respect. Yep. You went through something hard together even if it's only three three-minute rounds. Like that's a it's real. But it's separate from language. And earlier we were talking about the exper- the experience of emotion as this kind of triad of the feeling, the motor component to it, and language, but I do think that maybe the language piece can go.","offset":3546,"duration":33},{"text":"Dacher: I'm with you in some sense. Darwin wrote about the motor components, got a lot of it right, William James was about the body, you know, and the physiology, and you know, language is what we rely on as social scientists, but it I think it's as William James said when he tried to describe his experience of transcendence uh when he took laughing gas and it led him down the path to understand spirituality.","offset":3579,"duration":26},{"text":"Dacher: He's like words are tattered fragments. They they barely touch the real thing. Um, yeah, and and I just want to dwell for a moment, you know, part of awe and I learned this like talking to veterans, you know, and I I did work with Stacy Bare and we did this Sierra Club research getting veterans out on the rivers.","offset":3605,"duration":19},{"text":"Dacher: And he's one of my heroes in the book of getting helping tens of thousands of veterans to find their awe in nature, you know. And these are guys who've lost limbs and they're rock climbing, you know, and it's just like like there's a lot of awe when you're right at the edge of life and there's violence and and there's a lot of horror, carnage, etc. but there's awe.","offset":3624,"duration":19},{"text":"Dacher: Uh, and I love your idea and and I think any teacher of the of the martial arts would say that's the point, is that we can transcend death or violence by martial arts, by performing them and uh and putting them into a contemplative form for the body.","offset":3643,"duration":22},{"text":"Dacher: One of my favorite movies, if not my favorite movie, is Raging Bull, man, and Martin Scorsese, like Jake LaMotta and Sugar Ray have these epic battles and they look at each other, you know, in one of the great scenes, and they're just like we're united. This is all we're way beyond the fight, you know.","offset":3665,"duration":21},{"text":"Dacher: I think you're right. I think it's part of this transcendent moment that of people crashing into each other. Mosh pits. They are one of my favorite objects of study in awe. And mosh pits have a law, a set of laws to them.","offset":3686,"duration":18},{"text":"Andrew: Yeah, people have studied like the physics or the physics.","offset":3704,"duration":2},{"text":"Dacher: Yeah, no, it's like and you think you're crashing and you are, you're bruising yourself, you know, but there's something transcendent there about what we find.","offset":3706,"duration":10},{"text":"Andrew: I could be wrong, but I think um Raging Bull, I think the the soundtrack was Clash inspired. Was it? There's something about it in the documentary which I highly recommend, uh called The Future Is Unwritten, which is the Joe Strummer thing where some there's some link up between The Clash. I think Scorsese says, you know, The Clash inspired the soundtrack to Raging Bull or something like that.","offset":3716,"duration":19},{"text":"Dacher: Really?","offset":3735,"duration":1},{"text":"Andrew: Anyway, he's a big Clash fan, so um or yeah. So...","offset":3736,"duration":3},{"text":"Dacher: All right, Andrew, I get to ask you one more question.","offset":3739,"duration":2},{"text":"Andrew: Yeah, yeah.","offset":3741,"duration":1},{"text":"Dacher: So why is Joe Strummer a person of moral beauty to you? One of the sources of awe is we're amazed by people's courage and strength and kindness and justice. So why Joe Strummer?","offset":3742,"duration":10},{"text":"Andrew: Oof, man. All right, I'm going to try and keep this brief. Um, I mean just to give you a sense of how what an impact he's had on me. I mean, I've always worn these button-down black shirts even before I was public-facing, uh because I saw him do a show, um a Mescaleros show. I wasn't there, but he and by the way, Joe Strummer and the Mescaleros I actually think is better than The Clash.","offset":3752,"duration":26},{"text":"Dacher: Wow.","offset":3778,"duration":2},{"text":"Andrew: Clash was a short run. It was only five years. Yep. Only five years, pretty much, and then they're done. So it was 101'ers, Clash and then and then he came back with the Mescaleros and just incredible. I mean, they're masterpieces. Yep. Produced in part by my friend Tim Armstrong here on Hellcat Records.","offset":3780,"duration":14},{"text":"Andrew: He went to a small label. Um, he also sang songs with Johnny Cash for with Rick Rubin. I actually know the story of that because I'm friends with Rick and I insisted on him telling me the story. So sometime I tell you that. But I mean masterpieces late in life. And there was a show that that Strummer played where he was wearing his black button-down soaking in sweat, like soaked in sweat.","offset":3794,"duration":22},{"text":"Andrew: And he just wouldn't take the thing off. I think he might have rolled up like one cuff. And I was like that's punk as fuck. I was like that guy is so rad and he was in his he died at 50, we're the same I'm 50 now. He died at 50. I go see the mural of him right off um it's right off Tompkins Square Park uh in Alphabet City every time I'm in New York just go like see it. Where the aviator says future is unwritten. You can go there pay your respects.","offset":3816,"duration":23},{"text":"Andrew: I've talked to Rick about this a lot. Like what was it about him? Because they were close friends. And I never met Strummer. But I think there's three reasons. One is um he had that Bob Dylan-like ability to write lyrics that you're not especially with Mescaleros where you're not really sure what the song's about, but it makes sense, not just because it's beautiful but you feel like he's tapping into something more fundamental than what the lyrics are actually saying.","offset":3839,"duration":26},{"text":"Dacher: Beyond language. The theme we're talking.","offset":3865,"duration":2},{"text":"Andrew: Yeah, like a great song um for instance would be like On the Road to Rock 'n' Roll. Like that could be about on being on tour or something, but it it transcends something obvious.","offset":3867,"duration":10},{"text":"Dacher: Nice.","offset":3877,"duration":1},{"text":"Andrew: The other thing is is the way he he uh used his breath was um like there was a his intonation is like unparalleled. Yep. And then Rick was the one who really helped me understand, because during the summer I go hang out with Rick whenever I can. And winter too. Um, and we watch documentaries, including Clash documentaries.","offset":3878,"duration":22},{"text":"Andrew: And I asked him I was like what was it? Like why does he have this thing? Because he said these incredible things, you know. He would say things like, you know, you got to bring humanity back into the center of the and those are really beautiful quotes. But like a lot of people give beautiful quotes.","offset":3900,"duration":15},{"text":"Andrew: And Rick in very Rick Rubin style said, everything he said he brought his whole life experience into those statements. And I was like just the statements like the quotes, you know like the you know we got to bring the humanity back into the the and he goes no everything he said. It was like you got the sense that he was bringing all of himself to it even if he was being kind of quiet.","offset":3915,"duration":24},{"text":"Dacher: That's cool.","offset":3939,"duration":1},{"text":"Andrew: And I go, okay, so this is clearly on a plane of understanding that I can't put language to, right? What does that even mean? That's like half the things Rick says, it's like a riddle mixed up in a poem, you know put out there as you know as a as like a as a principle and you're just like what the hell's that mean? But it feels true.","offset":3940,"duration":18},{"text":"Andrew: And I think that, you know, and and Rick's superpower,","offset":3958,"duration":1},{"text":"Dacher: Yeah.","offset":3959,"duration":1},{"text":"Andrew: is that Rick knows what a true feeling feels like. Yeah. And he knows what a false feeling feels like. And he's only interested in truths, period.","offset":3960,"duration":13},{"text":"Dacher: And that's the challenge of the science that I'm part of is exactly that. It's like there are all these layers to meaning and representation and, you know, and we try to figure out true moments of awe with all of our measures and and it is this like it's all coming together as a uh a package that tells us it's happened.","offset":3973,"duration":19},{"text":"Andrew: So we can think about things that promote awe, the awe walk, going small to large aperture maybe back again. Like I guess we shouldn't assume that it's unidirectional. You know, coming back into our home after something big is there's nothing like that, right?","offset":3992,"duration":14},{"text":"Dacher: Ah!","offset":4006,"duration":1},{"text":"Andrew: The dog, the kids, the the spouse, the whatever, you know, like the those little thing, the plants even you know the the the you know, so it runs both ways. It's no fun, but we should probably talk about some of the inhibitors of awe. Because as I step back from what we're talking about today and I think okay language, it can be part of it but it can also in molecular biology or genetics we call it a dominant negative.","offset":4007,"duration":24},{"text":"Andrew: It's like a gene that basically suppresses a set of functions. A ton of stuff. And there's a joke around molecular labs and neuroscience labs that you'd be like that person's a dominant negative, you know. I now have a new phrase I can use. Yeah, yeah, you don't want to be called a dominant negative. Um, I call people that in my head a lot online.","offset":4031,"duration":17},{"text":"Andrew: I go, oh man that person's a dominant negative, they're not contributing to the greater good, they're just like so there's, you know, language can be that, um or be neutral or be positive but can definitely be that. And then there's something about being over-identified with self.","offset":4048,"duration":20},{"text":"Andrew: You know, I so on the recommendation of Tim Armstrong, someone you wouldn't associate with the Grateful Dead, he was like, \"You gotta listen to the Grateful Dead!\" and I was like, what? This is Tim, the Tim Armstrong Transplants, Rancid, Operation Ivy, telling me I should listen to the Grateful Dead. He's big great he's a huge music fan of all sorts of things.","offset":4068,"duration":18},{"text":"Andrew: I said why? And he said uh he said, \"They're punk rockers.\" And I said how what are you talking about? And he said he said, \"Yeah they they played a different show every night.\" That's how they're I'm not going to keep doing his I can do a pretty decent Tim for those...","offset":4086,"duration":16},{"text":"Dacher: Nice.","offset":4102,"duration":1},{"text":"Andrew: uh but apparently they're the the people that followed them, that was a big part of it. It was all all new, right? Every show was unique. Started getting really into listening to the Grateful Dead in the last couple years and then I started listening to documentaries, biographies of them. And there's this amazing moment in one of them, I can't remember which where somebody says what killed it?","offset":4103,"duration":28},{"text":"Andrew: What killed the collective of music? Like that that feeling? And uh the answer someone gave was cocaine. And then the question was why cocaine? Yep. And someone said because cocaine's all about me. It's the me drug. So I was like, whoa, I'm a neuroscientist so I can tack that to you're talking about dopamine and adrenaline. And it's when dopamine and adrenaline are elevated that's a very I mean amphetamines especially but it it becomes a me thing.","offset":4131,"duration":35},{"text":"Dacher: Yeah, that's true.","offset":4166,"duration":1},{"text":"Andrew: Every idea that's mine is the thing that needs to happen. It's the important thing. If not out there, it needs to hap- like that's the only thing that matters. Very different than cannabis, very different than psychedelics, very different than just the sober experience where it's kind of a downer, but then the non-intoxicated experience of just being with the music no substances.","offset":4167,"duration":20},{"text":"Andrew: So I'd love your thoughts on how certain chemical states and but more broadly how me-ness self-interested states are a dominant negative for awe.","offset":4187,"duration":11},{"text":"Dacher: That was the best entrance into that question I've ever encountered. You know, it's amazing Andrew. You know, I grew up for three years formative years in Laurel Canyon '68 to '70 and then we moved to the foothills of the Sierras in Northern California and it was peak Laurel Canyon, Joni Mitchell and the Birds and the Beach Boys and you know, it's just","offset":4198,"duration":21},{"text":"Andrew: Jealous. Envious in a positive way.","offset":4219,"duration":2},{"text":"Dacher: When my brother passed away and he was my brother of awe, you know 14 months younger and I was in this reflective period, I started reading a lot about Laurel Canyon and they made the same point which is kind of things shifted after we, you know, in the early '70s. And the historian said it's cocaine.","offset":4221,"duration":21},{"text":"Dacher: That it moved from, you know, marijuana and mushrooms and psychedelics a bit but really, you know, people playing music, you know, Joni Mitchell or Graham Nash or whomever it is. And then suddenly cocaine comes and the the whole spirit changed.","offset":4242,"duration":15},{"text":"Dacher: Yeah, I think the great enemy of awe is me-ness is what Ralph Waldo Emerson who was one of our great writers of awe, you know, he has this moment out in nature cold day in Massachusetts sees this forest and he you know he's like standing on the bare ground my head bathed by blithe air and uplifted into infinite space.","offset":4257,"duration":22},{"text":"Dacher: And there's that uplift that you described earlier of awe. All mean egotism vanishes. And that's all, you know. Awe quiets the self. And when you look at where we are, you know, Jean Twenge, you know, longitudinal data, we're more self-focused, you know.","offset":4279,"duration":23},{"text":"Dacher: We're taking a quarter of the pictures that we take are of the self. It's preposterous! It's pretty crazy. It's half of the photos we take are of the self or the self with another person or another thing. It's perverse, you know. Uh, the world has become more narcissistic. We're led by narcissists.","offset":4302,"duration":19},{"text":"Dacher: It's been, you know, it's just taken as a default and it's not a default. It's a it's a corruption of of our minds. Because the mind, as you described earlier, is very good at looking at other people, at making eye contact, at seeing their beauty, at hearing their words, at looking at collectives, discerning patterns of nature, collectives, and all of that works against awe, right?","offset":4321,"duration":25},{"text":"Dacher: That you know, if I am focused on myself I'll feel less awe, if I am worried about my striving in society or my bottom line in my bank account, you know, or thinking about money, it countervails awe. So yeah, I I think, you know, that's why awe's important for our times. We are in this for various reasons, this period of too much self-focus.","offset":4346,"duration":28},{"text":"Dacher: Uh, it's costing young people, it makes them anxious, you know, and they got to they got to they got to go dance, they got to hear some music, they got to share stuff and go backpacking or whatever it is, you know, and just to get out of the self.","offset":4374,"duration":14},{"text":"Andrew: I'd like to take a quick break and acknowledge our sponsor, Function. Function provides over 160 advanced lab tests to give you a clear snapshot of your bodily health. This snapshot gives insights into your heart health, hormone health, autoimmune function, nutrient levels, and much more. They've also recently added access to advanced MRI and CT scans.","offset":4388,"duration":21},{"text":"Andrew: Function not only provides testing of over 160 biomarkers key to your physical and mental health, it also analyzes these results and provides recommendations for improving your health from top doctors. For example, in a recent test with Function, I learned that some of my blood lipids were slightly out of range. As a result, I decided to start supplementing with nattokinase, which can naturally help reduce LDL cholesterol, and it did.","offset":4409,"duration":23},{"text":"Andrew: In a follow-up test, I could confirm that this strategy worked, my blood lipids are now back where I want them in range. Comprehensive lab testing of the sort that Function offers is so important for health, and while I've been doing it for years, it's always been overly complicated and expensive. But now with Function, it's extremely easy and affordable. To learn more, visit functionhealth.com/huberman and use the code Huberman for a $50 credit towards your membership.","offset":4432,"duration":27},{"text":"Andrew: The example you gave of sports earlier I think is is an important one um only because I think some people not me, but some people will all right I don't really want to go camping or backpacking. I do. I spend as much time in Yosemite as I can. The dancing, concert, you you maybe that's not for them.","offset":4459,"duration":17},{"text":"Andrew: I do think I'm not a big professional sports fan. Um, I like a few things, but but it is kind of interesting to put this lens on like when I see a game, one of our members of our podcast team that's not here today is like just obsessively excited about professional football and uh Seattle Seahawks.","offset":4476,"duration":20},{"text":"Andrew: So this was a big year for him. And I have to believe that when he goes to see his favorite team play in the Super Bowl and win the Super Bowl that it's not just about his relationship to his team and it's about it's about being a kid and and everyone else there in a Seahawks jersey is like they have to they must feel a connection because they presumably the super fans know that the other super fans know the history, they know how important this is, they know all the trials and tribulations of the team and on and on.","offset":4496,"duration":30},{"text":"Andrew: And so it's um gosh, it's so different. I'm just realized like it's the it's the furthest thing from like doing a PhD in the sciences. The folks doing a PhD in the sciences is a lot of fun, it's a hell of a lot of work. And there's nothing else quite like it. I it's irreplaceable, I wouldn't redo it for in any other way. But it is a very like you're it's a very solitary thing.","offset":4526,"duration":22},{"text":"Dacher: It is.","offset":4548,"duration":1},{"text":"Andrew: Like you don't even cross you cross finish line, your advisor's there, your family comes but it's like it is a tunnel like this big. Going to the Super Bowl to watch your favorite team play is you're going through that tunnel with you know millions of people.","offset":4549,"duration":16},{"text":"Dacher: One of the joys of awe science, you know, we gathered stories of awe from 26 countries. And it's one of my favorite parts of this research. And this is like India and Brazil and Poland and Chile and Mexico and Japan and Korea and South Korea and Russia. And we everybody.","offset":4565,"duration":16},{"text":"Dacher: We brought them in, got these stories and you know like what is vast and mysterious? What gives you goosebumps? What's amazing or awesome to you? And when you get stories from Brazil or Argentina, they're going to write about so they they're going to tell you about football, you know.","offset":4581,"duration":16},{"text":"Dacher: And, you know, when you get stories from parts of the United States they're going to talk about you know American football and baseball. You get stories from Boston it's there's going to be a Red Sox story.","offset":4597,"duration":12},{"text":"Dacher: And we have not studied sports in my emotion science because most emotion scientists are not good athletes. They're picked last in grammar school. They're grouchy about sports. And yet it's super emotional.","offset":4609,"duration":13},{"text":"Dacher: And I will tell you a story that has science and uh personal wisdom. Uh, as I I gathered these stories like God, you know, part of collective effervescence just like Taylor Swift or being in a punk mosh pit is also sports. And and just like uh it is awesome to follow a sports team and be there live.","offset":4622,"duration":26},{"text":"Dacher: And there's this great obscure sociology paper that said being a fan of the Pittsburgh Steelers is like being in a religion. Because you have your rituals, they have these towels they they sing around, you think of yourself as the Steeler nation, they talk about godlike experiences on the field, they have these spiritual moments where in freezing days they'll take off their clothes and cheer and cry together.","offset":4648,"duration":25},{"text":"Dacher: Um, and I was teaching this recently and there were two Steeler fans in the audience. And they were like that's exactly it. But I'll tell you more like everywhere you go if you're a fan a Steeler fan there are Steeler bars that you can go to.","offset":4673,"duration":16},{"text":"Dacher: And when the Steelers play they're going to be Steelers fans and if you're a kid and the Steelers lose somebody who's old will tell you I remember when we lost in 1983 and we'll recover we'll you know have this expansion of time. It was so rich to me, you know.","offset":4689,"duration":14},{"text":"Dacher: It's like we love sports, you know. Sports the Olympics are old, they're 3,000 years old. The ball court games in the Maya you know in the Mayan traditions are were amazing ways to gather community and and become collective, right? So, you know, uh it was really eye-opening for me just to sense the awesomeness of sports.","offset":4703,"duration":25},{"text":"Dacher: And one of my great joys of writing the book was to talk with Steve Kerr, who was coaching the Warriors at the time. He's a righteous guy, you know. Uh, he is a person of truth and just getting his sense of like how awesome it is to I mean for him to coach a game and the Warriors were in this amazing period and look up into the stands and 10,000 people are dancing because of your coaching, you know, I was like that's pretty good.","offset":4728,"duration":28},{"text":"Andrew: Yeah, he's really tapped in, isn't he? He's a meditator and wildlife experience and...","offset":4756,"duration":7},{"text":"Dacher: And trauma early, you know, his dad losing his dad.","offset":4763,"duration":4},{"text":"Andrew: Yeah.","offset":4767,"duration":1},{"text":"Dacher: And and that orienting him to what really matters.","offset":4768,"duration":3},{"text":"Andrew: I'm thinking about the things that inhibit awe, but I'm also thinking about solutions.","offset":4771,"duration":5},{"text":"Dacher: Yeah.","offset":4776,"duration":1},{"text":"Andrew: You know, it's springing to mind that you know, uh it's it's funny sometimes I get tacked to like ice baths for some Well, folks, that was Wim, right? I mean, that was Wim. I mean, sure, I've done some cold plunges, I like I do the cold.","offset":4777,"duration":10},{"text":"Dacher: I gotta do them. It sounds good.","offset":4787,"duration":2},{"text":"Andrew: Yeah, it's fun. I mean, you know, it it's psychologically painful and you feel better afterwards and um it'll make you it'll make anyone mentally stronger because cold is a universal stressor. Um, but you know, it it gets kind of a bad rap because mostly because people don't like doing it. Everyone loves the sauna. It's kind of funny.","offset":4789,"duration":18},{"text":"Andrew: Everyone's cool with sauna. And the Finns love the sauna, and it's a social thing for them. And one thing that I think has been overlooked and it just sprang to mind now. Um, so I overlooked it as well is that you know there's this thing that's wonderful about experiences that we can have with other people, but that we can also do on our own and when we do them on our own we know other people are doing it on their own too.","offset":4807,"duration":23},{"text":"Andrew: And so it's it's kind of a it's a different version of what we've been talking about. And you know, the quote-unquote health and wellness community they take some heat like people oh it's all about supplements, all about cold plunges, you know and I've got a like a like a particular finger I hold up when I hear that. But it's not about that.","offset":4830,"duration":18},{"text":"Andrew: There's this deeper layer that's much more important that's formed over the last I would say 5 to 10 years, because it used to be meditation, breathwork, Esalen, great love Esalen, like amazing but incredible place.","offset":4848,"duration":11},{"text":"Dacher: Historic.","offset":4859,"duration":1},{"text":"Andrew: Historic and many important things actually happened there that people don't even realize in terms of shifting world politics and world peace that maybe some","offset":4860,"duration":8},{"text":"Dacher: Oh my god, yeah! You brought the Russians in there for instance.","offset":4868,"duration":6},{"text":"Andrew: But you know so it used to be these isolated pockets, but now, you know, people get together to sauna, people get together to do breathwork, people get together to cold plunge. And of course for thousands of years humans have been doing this. This is not a new thing. And people look at that and they go this is wacky or it's about the marketing of this.","offset":4874,"duration":17},{"text":"Andrew: Actually, I I think that there's a connection that's formed among people who want to take good care of their health, they want to have some control over their state, um because otherwise the world will take control of it for you. Yep. And meditating is a very solitary experience for most people. So there's something pretty nice about going to a banya. I love banyas, Russian banyas, and then also doing the sauna on your own or cold plunge on your own.","offset":4891,"duration":25},{"text":"Andrew: And I think that what it builds is a community that is linked on social media. So from now on when I see people doing things that I go oh cool like I like a bit of that I don't maybe do it every day or I do that every day too get see my morning sunlight. The notion that there's a community being built. That was the original intention of social media.","offset":4916,"duration":16},{"text":"Andrew: And so I think social media can have this dominant negative effect on awe and day-to-day experience. So a question is are there ways? Surely there are, but how how could we build more of a sense of of like this communal feeling leveraging what people are already doing? They're already on their phones and scrolling. Hopefully they're also doing things to benefit their health. To make them feel less isolated because as Jonathan Haidt and others have pointed out quite correctly, it can really fracture us into the the the me, the ego version where it's but it's kind of the perfect venue to connect people also.","offset":4932,"duration":39},{"text":"Dacher: It is. I agree.","offset":4971,"duration":1},{"text":"Andrew: So I don't expect you to come up with any answers right on the on the fly, but I feel like it's not going anywhere. So how how could we build or glean a more sense of a community through things that we're doing actually doing in our daily lives? Is I think a question that's worth exploring.","offset":4972,"duration":16},{"text":"Dacher: Profoundly important. You know, um the you know and the preceding question is like what are the enemies of awe? What gets in the way or the the barriers? And and you just nailed a couple is you know online life. You know and I think Jonathan Haidt is right that it's not only anxiety-producing but we don't think about the opportunity costs of like it deprives me of awe, you know.","offset":4988,"duration":27},{"text":"Dacher: And in our study of 2,600 people around the world of what makes them feel awe, no one ever said being on Meta or Facebook or, you know, or uh, you know, or Instagram. There are a couple reason worries I have about online life and I'm kind of working on this now. You know, and one is is the content itself, which is, you know, it's been algorithmically designed.","offset":5015,"duration":28},{"text":"Dacher: I was at Facebook when some of those algorithms I was advising there were set in place of like making people hate each other and not demonstrate all of our all the wonderful things about human beings, which are um ample. And then online life disrupts sharing and the technologies of today have disrupted sharing. So we don't share music like we used to share. We used to listen to music together.","offset":5043,"duration":24},{"text":"Dacher: That's down. Going to movies is down 40%, right? That used to be a very important collective cultural experience. Did you see the latest Scorsese or Pixar or whatever? Now it's streaming, right? So I really worry about that. And I think the next challenge in in the technological world in the new the social media and the platforms is is like you said, how do you enable the sharing of experience? Um, you are absolutely right.","offset":5067,"duration":31},{"text":"Dacher: A lot of what we do for our bodies and the wellness space has a massively important community basis to it. where suddenly you're not, you know, meditating and breathing but you're also sharing your mind and your experience. You're not, you know, listening to music you're sharing an understanding of the music together and its cultural history.","offset":5098,"duration":24},{"text":"Dacher: One of my favorite examples is farmers' markets. They were nonexistent in the '90s, right? And they used to be very common in American culture and now there are 9,000 farmers' markets growing. And yeah, people go to buy kale and get the honey and you know the fresh bread or whatever, but they're also going because it's community. It's profound community. Uh, and we derive a lot of benefits from that. Profound benefits. 10 years of life expectancy, community.","offset":5122,"duration":29},{"text":"Andrew: 10 years?","offset":5151,"duration":1},{"text":"Dacher: 10 years.","offset":5152,"duration":1},{"text":"Andrew: My goodness! There's so much obsession these days around what sport allows you to live the longest? Turns out it's like pole vaulting which most people aren't going to do. Um, sprinting, gymnastics. Stuff that involves a lot of jumping and landing.","offset":5153,"duration":11},{"text":"Dacher: Is that right? Really?","offset":5164,"duration":1},{"text":"Andrew: And and fast twitch activity. Yeah. I mean there are a bunch of other features there about like who's biased to go into those sports and whatnot. But I mean I think it's in keeping with this idea that like getting your heart rate way way up and moving quickly as as quickly as you safely can like once a week at something is probably a good idea.","offset":5165,"duration":15},{"text":"Dacher: Cool.","offset":5180,"duration":1},{"text":"Andrew: But the greatest benefit seen there is something like five to eight years. So you're talking about a 10-year benefit?","offset":5181,"duration":6},{"text":"Dacher: 10 years. And that's a meta-analysis of 350,000 participants. So that's that you can go to the bank with that. Like social community very good for the body. I think it's the greatest challenge of our our social media and our our platforms. And I've advised at Facebook 2010 to 2015, Google, Pinterest, a little bit of Apple, and I keep telling them like, you know, this is the singular challenge.","offset":5187,"duration":24},{"text":"Dacher: And it's so it's hard. It's, you know, a technologies are asynchronous. You know, \"Hey I send you a text\" and 18 hours later I hear from you. You're not making eye contact. The visual connection is degraded. You know, Steve Pinker observed rightly so, like when I'm on Zoom I have to look at the down to see the camera or whatever or I look at the screen, so my eye contact is going down.","offset":5211,"duration":24},{"text":"Dacher: I'm not making eye contact like we are. It's just the technology works against it. And I think it's the hard problem of the social media platforms is can they do what you're aspirationally asking for which is like get us to feel connected? Um, you know, Mark Zuckerberg's original statement about Facebook was open and connected. Um, and I think they failed. And I think we got to we it's it's the challenge of our times.","offset":5235,"duration":34},{"text":"Andrew: I know Mark a bit and I think I know you know I trust he wants that.","offset":5269,"duration":5},{"text":"Dacher: I know.","offset":5274,"duration":1},{"text":"Andrew: I really do. I know some people will will push back on that statement, but I actually know that he wants that. And I know some of the folks in the leadership at Instagram they want that. Like these people actually have very healthy personal lives. They understand the value of connection both at the level of the family, friendships, but also um at large. They they want that.","offset":5275,"duration":25},{"text":"Andrew: I think that maybe I'm being optimistic here, but maybe AI will offer an opportunity for that as opposed to divorcing us from um gathering and and seeing facial expressions and hearing of voices together or observing other things. You know, the I do think that right now the way that most social media experiences land is the exact opposite of awe.","offset":5300,"duration":25},{"text":"Andrew: I will say that. Because and I can say that with a fair degree of certainty because I spend a good amount of time on social media teaching, learning, and looking for entertainment, trying not to get uh, you know rage-baited or numbing out. Those are the two things I look out for. Rage-baiting and numbing out.","offset":5325,"duration":13},{"text":"Dacher: Well put.","offset":5338,"duration":4},{"text":"Andrew: There's a version of social media that's happening right now where we're going further and further into our silos. Yep. But I don't think it has to be that. Not at all. I don't. I think it could be really leveraged to connect people.","offset":5342,"duration":9},{"text":"Dacher: You know, when I started advising at Facebook 2010 to 20 it was like Arab Spring and democracy was spreading and and in many ways we've had this great democratization of things of people sharing music, you know, instantaneously I can hear music from any part of the world, uh which you know that's profound and visual art and and knowledge and podcasts.","offset":5351,"duration":20},{"text":"Dacher: And we've got to be nuanced about this. But we do need, you know, to think intentionally about design, you know. And that, you know, I really worry about the privileging of hate I forgot what you called it but that has been privileged. Uh, and that's not human nature. We we aren't all trolls and, you know, tracking people.","offset":5371,"duration":29},{"text":"Dacher: Video title: Andrew: What an amazing talk.","offset":5400,"duration":1},{"text":"Dacher: Thanks.","offset":5401,"duration":1},{"text":"Andrew: This really touched me and helped me think about some of the more practical ways of doing this. I really do hope that we can build some of those pathways through all this technology as opposed to getting more fractured.","offset":5402,"duration":10},{"text":"Dacher: Me too.","offset":5412,"duration":1},{"text":"Andrew: Thank you for coming today.","offset":5413,"duration":1},{"text":"Dacher: It's an honor. Thank you.","offset":5414,"duration":1},{"text":"Andrew: Appreciate it.","offset":5415,"duration":1},{"text":"Dacher: Yeah.","offset":5416,"duration":1},{"text":"Andrew: Joe Strummer would be proud.","offset":5417,"duration":1},{"text":"Dacher: Amen.","offset":5418,"duration":2},{"text":"Dr. Andrew Huberman: I've had this thought uh that the way social media is now...","offset":5420,"duration":34},{"text":"Dr. Andrew Huberman: I sometimes do the test of myself. I go, \"Okay, I spent I don't know how much time on social media yesterday, but do I remember anything specific?\"","offset":5454,"duration":20},{"text":"Dr. Andrew Huberman: And so that's scary.","offset":5474,"duration":49},{"text":"Dr. Andrew Huberman: And I do think that the people who built it want it to be impactful on the day-to-day uh scale, but also...","offset":5523,"duration":19},{"text":"Dr. Dacher Keltner: Well, you know, one of the things I'm really interested in right now, Andrew, is is awe design, right? And, you know, I'm working with Gehl Architects in Copenhagen. Like, how do you design cities for more awe? It's not hard, and it's good for people, right? A little bit of music, a little bit of green space, a little bit of art, get people looking at each other and talking and buzzing, right? Easy to do.","offset":5542,"duration":24},{"text":"Dr. Dacher Keltner: And I think you've just laid out, you know, and someone could write a manifesto, like, maybe my life on the smartphone is the antithesis of awe. It's small, awe's vast. It's sped up, awe slows things down. It has a fragmentation to it, awe integrates, right? It's about micro-things, awe's about systems. Like, when you feel awe towards music, it's like, \"I get it all here, right now.\" Its content is is not inspiring very often. And it could all be.","offset":5566,"duration":36},{"text":"Dr. Andrew Huberman: Sometimes it is. I I think that that the space-time aperture that we talked about before, I think the problem with social media is actually its power to bring the whole space-time into an aperture this big. I actually think, crazy hypothesis, happy to be wrong, I actually think the whole problem with it has to do with the fact that it brings long time scales, past, present, and future, different aper - different frame rates into one real-world visual aperture. Because when I haven't been to the Sphere in Las Vegas, but friends of mine who are musicians who love live music, who are producers who love live music, tell me it is incredible.","offset":5602,"duration":60},{"text":"Dr. Dacher Keltner: Yeah, it should and and I think and we have to, you know, we just have to take a step back and these conversations, right? There's, you know, there's new work out about AI helping medical doctors and it's, you know, and the writer of this book coming out of UC San Francisco's like, \"It's like having the best brain trust about medicine right with you all the time.\" Who wouldn't want that, you know? And I think let's remember that. And yeah, I think that's the challenge, is to have these AI and the devices that it is manifest on get us to what's awesome. And uh, we'll see, you know, I hope so.","offset":5662,"duration":34},{"text":"Dr. Andrew Huberman: I'd like to take a quick break and acknowledge our sponsor, Our Place. Surprisingly, toxic compounds such as PFASs, or \"forever chemicals,\" are still found in 80% of non-stick pans, as well as utensils, appliances, and countless other kitchen products. As I've discussed before on this podcast, these PFASs, or forever chemicals, like Teflon, have been linked to major health issues such as hormone disruption, gut microbiome disruption, fertility issues, and many other health problems. So it's very important to avoid them.","offset":5696,"duration":34},{"text":"Dr. Andrew Huberman: This is why I'm a huge fan of Our Place. Our Place products are made with the highest quality materials and are all PFAS and toxin-free. I particularly love their Titanium Always Pan Pro. It's the first non-stick pan made with zero chemicals and zero coating. Instead, it uses pure titanium. That means it has no harmful forever chemicals and it does not degrade or lose its non-stick effect over time. I cook my eggs in my Titanium Always Pan Pro almost every morning. The design allows for the eggs to cook perfectly without sticking to the pan.","offset":5730,"duration":28},{"text":"Dr. Andrew Huberman: Right now Our Place is having their biggest sale of the season. You can save up to 40% sitewide, now through April 12th. Just head to fromourplace.com/huberman. Again, that's fromourplace.com/huberman to save up to 40%.","offset":5758,"duration":20},{"text":"Dr. Andrew Huberman: Can we talk about embarrassment?","offset":5778,"duration":27},{"text":"Dr. Dacher Keltner: I know. Well, you know, it it all begins really in my - like, when I started scientifically to depart from the Ekman canon, if you will, of those six emotions we talked about earlier. And I was doing a project in his lab and we were startling people and studying the startle response. A seven-muscle movement motor pattern built into the nervous system. And I noticed people got embarrassed after they were startled unexpectedly, you know, you'd blast 'em with a noise out of the blue in the lab and they'd be like, \"Whoa, I think I spit and, you know, peed my pants,\" or whatever. They'd show this response.","offset":5805,"duration":38},{"text":"Dr. Dacher Keltner: And I took it to Ekman and it's the blush, and people avert their gaze and they look away and they hide their face, you know? And he's like, \"That's a motor pattern of emotion, you should go study it.\" And I did. And and then I started to notice, and there's a really rich literature on that, that and Darwin wrote about this, that a person's embarrassment is a sign of their commitment to the collective, right? Like, man, you know, I called you by the wrong name, or I, you know, I farted in the yoga class, or whatever it is, and I'm embarrassed, like, \"I'm sorry, man,\" you know, \"I apologize.\"","offset":5843,"duration":33},{"text":"Dr. Dacher Keltner: That really matters. And when you see people get embarrassed, you like them more and you trust them more and you give resources to them and you think they're a good group member. And then I was like, man, you know, like I've played a lot of pickup basketball in my life, thousands of games, and you're banging into - and there's just a lot of teasing and taunting, and you know, people I admire, you know, great athletes tease and taunt, you know, it's just part of what we do when we're banging into each other.","offset":5876,"duration":30},{"text":"Dr. Dacher Keltner: And I started to put it together, like, you know, the right kind of teasing within a collective, you're kind of provoking people to see if they care about the group, right? And then the wrong kind of teasing, which we documented in our lab's, like, that's bullying and harassment and we can pinpoint, like, \"That's inappropriate,\" you know? You're trying to you're not keeping people in the group, you're excluding them or humiliating them.","offset":5906,"duration":24},{"text":"Dr. Dacher Keltner: So we did this study, was one of my first studies, we brought four fraternity - we brought groups of fraternity - four fraternity guys in each interaction uh from this fraternity house at the University of Wisconsin. And we gave them each nicknames, or we gave them each initials, and we had them make up nicknames based on the initials. So two two letters of a nick - were \"A.D.\" And I'm not sure I can say what the nicknames were like, but it, you know, \"Another Drunk,\" and it gets pretty profane.","offset":5930,"duration":37},{"text":"Dr. Dacher Keltner: And so we let 'em tease each other. And they start teasing each other and they are really, like, these young men coming out of a fraternity house teasing each other. There are funny stories, people got embarrassed. Uh the the stories and the teasing was kind of about, like, \"I'm gonna accuse you of something that you shouldn't do in this group,\" right? Like pass out drunk naked, you know, in the streets of Wisconsin. \"Don't do that,\" right?","offset":5967,"duration":29},{"text":"Dr. Dacher Keltner: And then they get embarrassed and they say, \"I'm not gonna do that.\" And what we found is the more that they got embarrassed, the better they liked each other, because it's turning into this motor pattern of, like, \"Wow, I'm showing you that I care about what you're accusing me of and I'll get embarrassed, you see that in me, we become closer.\" The the guys who were better teasers and that were more playful and funny and made people aware of the norms that matter to the group but not really humiliate people, those guys were more popular in the group.","offset":5996,"duration":37},{"text":"Dr. Dacher Keltner: And that's been replicated, right? Just storytelling and and ribbing each other and and it was part of healthy group functioning is just embarrassing each other. You think about roasts, you know, at the end of your career, you're gonna get that someone's gonna talk about your career, you're gonna get hammered. And it's wonderful.","offset":6033,"duration":52},{"text":"Dr. Andrew Huberman: I bet. I mean, I grew up in a big big packs of boys, I mean on my street growing up...","offset":6085,"duration":26},{"text":"Dr. Andrew Huberman: Uh a former guest on this podcast who's a psychiatrist who's also very versed in Eastern philosophy, Dr. K, as they call him, um said that embarrassment is important because it also signals that you're not a creep. Especially, he was referring to heterosexual relationships where, you know, a guy says something trying to be uh, you know, trying to flirt basically or pick up on someone, and then uh the woman says something back and he, like, gets embarrassed, he realizes, like, he said the wrong thing. If he doesn't show embarrassment, he's creepy. If he does, it verifies that he has a certain degree of empathy and self-reflection. No, so that was his point, but it it feels relevant here. So...","offset":6111,"duration":40},{"text":"Dr. Dacher Keltner: And he's right. I mean, you know, uh Darwin early on wrote about the blush being a sign of your healthy character, your moral virtue almost. And in non-human species, the facial reddening is associated with physical robustness and then in humans we think of it as moral robustness like, \"Yeah, I care about stuff.\" We did work early on, Bob Knight at Berkeley, orbital frontal patients. The orbital frontal cortex is in part where your ethical consideration takes place. And if you have damage to that region of the brain through brain trauma - you fall off a motorcycle or, you know, fall off a ladder - you don't show embarrassment where you should. And they feel creepy, if you will, or just like, \"Hey, they're not playing by the rules.\" So it's a very subtle thing. Erving Goffman wrote a lot about it, the great sociologist, like, our embarrassment is telling people like, \"I know what the rules are and I care about them, I'm committed to them.\" So your psychiatrist friend is right.","offset":6151,"duration":63},{"text":"Dr. Andrew Huberman: Along the lines of of teasing, um uh someone I'm I'm proud to call a friend who's also public facing uh Jocko Willink, who's also it turns out one of our - were friends for a bunch of reasons but one of them is that he grew up really into East Coast hardcore music. Not not a genre I I gravitated towards, but there's some marginal overlap um with the types of music um I'm into. We've gone to shows together and um, he put something up, you know, every once in a while on social media somebody posts something that that really lands, Naval or or Jocko and he's a Jocko's a man of few words, so I'm gonna put more words to it than than he was able to.","offset":6214,"duration":40},{"text":"Dr. Andrew Huberman: Um but the quote was something like, um \"You know, if you want to understand,\" and he's a former Navy SEAL, SEAL team operator most people know know that, but \"If you want to understand uh males in groups and healthy uh masculine friendship, guys are going to tease each other relentlessly in front of each other, but they'll never tease behind somebody's back and they'll back the other person who they were just teasing in person against the rest,\" you know, \"They'll buffer them against any kind of criticism.\" So it's a very interesting um kind of uh contrast there that I think is true. Like, you you know, it's not like you tease your friend behind his back. It's the teasing to his face that actually builds the bond.","offset":6254,"duration":45},{"text":"Dr. Dacher Keltner: Yeah, well put.","offset":6299,"duration":36},{"text":"Dr. Dacher Keltner: We documented that in the fraternity study, that, you know, when you when you tease somebody and you're like, \"Hey man, do you see this guy's dance moves?\" or \"You see this guy shoot free throw,\" whatever it is, you're just making light of human foible and and all the funny things that we do. And there's there's there's just this really subtle repair work where they're saying like, \"I'm teasing you, but I know you got it,\" you know, \"And I'll support you.\" And I agree, I think that, you know, part of what teasing does is it says like, \"What do we as a collective really care about?\" And let's surface those norms in a lighthearted way and we know 'em together. And and if you make mistakes, you should be apologetic about it, but part of it also is just uh this sort of \"I got your back\" repair work that they did. Um and it's profound.","offset":6335,"duration":51},{"text":"Dr. Dacher Keltner: It, you know, was interesting. I was kind of this shy kid and I was very small growing up and kind of the teasing often crossed lines in high school, just, you know, bullying and so forth. And then I started to play basketball and, you know, um and I realized, like, a lot of it's just just men making sure they know the rules of the game, you know, and showing also in those moments of the joys of laughing together like, \"I support you, I'm with you,\" right? Uh what a sophisticated thing to do um compared to the alternatives.","offset":6386,"duration":38},{"text":"Dr. Andrew Huberman: I have a sister, so I was always struck by the brothers in my neighborhood. Yeah, there were two in particular, like, I would hear screaming outside, go outside, it was an older brother, his name was Peter, holding Michael's face in the sprinklers. His brother's just crying and crying, screaming, I mean relentless older brother torture. Some people hear this and probably be like, \"Oh, call the cops,\" you know, and I don't know what the reaction is nowadays, I'll try not to be genera - generationally biased, I don't know. Yeah, he was he was abusing his younger brother. And but if anyone said or tried to do anything to either one of them, they would immediately pair up and fight anyone. It was interesting, right? Uh for a guy who had an older sister, was a very different experience, right? I mean, she had her own form of older sister kind of hazing um to her younger brother.","offset":6424,"duration":49},{"text":"Dr. Andrew Huberman: But there really does seem to be something critical about kind of defining the relationship with people one-on-one, in groups, versus when there's an outside threat. And and not that we want outside threat, but as long as we're talking about the sort of...I don't want to say disintegration, that's too pessimistic. The sort of gradual erosion of this collective feeling, is there less just kind of grouping up together and doing things?","offset":6473,"duration":30},{"text":"Dr. Dacher Keltner: Yeah, you know, I um 10 years ago, uh 15 years ago, 10 years ago, uh first there was the science of loneliness and isolation, John Cacioppo uh and then those who followed, like, \"Whoa, we are fragmenting.\" And we spend much too much time alone, isolated. And then COVID hit, lockdown, etc. And our Surgeon General, former Surgeon General Vivek Murthy got it right, like, it's an epidemic of loneliness. And I as a social psychologist, you know, interested in these social emotions am like, you know, you just look at the basic raw facts, like, picnics are down by half. We don't go to movies like we used to. We don't um we don't listen to music together. We don't...30 the estimate is that 30% of meals in the United States people eat them by themselves, you know? I eat a lot of my meals by myself. Uh we go on walks by ourselves, we don't go to church, church is way down. Um so the kind of the broad sociological trends are alarming on that fragmentation.","offset":6503,"duration":72},{"text":"Dr. Dacher Keltner: But I think the young generation is putting it back together in really interesting ways. You know, we know from survey data that 25-year-olds, 30-year-olds are really interested in game nights, you know, those are coming back. They're interested in living together, cooperative living. They're cooking more with each other. Value-wise they care more about community than my generation. I was the great explosion of individualism and they're kind of like, \"You know, if I if I choose a job, I want to make sure I'm working with other people I like.\" I didn't even I didn't think about that. I don't know if you, you know...uh so I think it's coming back.","offset":6575,"duration":39},{"text":"Dr. Dacher Keltner: And and I love the signs of, you know, festivals are reappearing now, the farmer's market that I've talked about, the, you know, the dance groups that are now returning, contact dance. I see, I mean these yoga studios, one out of eight Americans does yoga. You know, I do yoga two to three times a week.","offset":6614,"duration":29},{"text":"Dr. Andrew Huberman: Also 15 years ago, no one would have predicted that the single we're being told that one of the single most important health interventions that women and men should do is, like, lift weights. The only people lifted weights when I was growing up were bodybuilders and preseason football players.","offset":6643,"duration":60},{"text":"Dr. Dacher Keltner: I think Vivek Murthy in particular, who I deeply admire and have worked with a bit, you know, he he got our health world - think about it. Surgeon General of the United States, the first one to come out of public health traditions. Did work in India, right? And he's like, \"There's this social side that you've covered in your show like to health, to physical health, to the telomeres of your cells, your DNA and the vagus nerve and so forth, oxytocin, cortisol. It's social.\" Uh there's there are social dimensions to our nervous system.","offset":6703,"duration":38},{"text":"Dr. Dacher Keltner: And I think that's coming, Andrew. Like, we're starting to see, \"Why do I go to a farmer's market?\" because I feel a sense of community. And \"Why do I love yoga?\" because I'm doing these postures all synchronized with people I don't know and I feel a sense of awe and transcendence. \"Why do I lift weights,\" right? There's the banter and the discussion and the the history and the sense of, you know, of what this all means culturally. I think that's coming. I think the gyms are appealing to it in some sense, right? A little bit more community activity and I think it's good news, you know?","offset":6741,"duration":37},{"text":"Dr. Dacher Keltner: I love the Japanese onsen. Uh you go for the water, you know, and the the springs and the heat and so forth, but they in their wisdom have built entire community experiences around it. Where you you wash yourself and you bathe together and you eat together and there's sayings up on the walls and you spend a little time with your kids there, right? So I hope we we learn um because I think it's important.","offset":6778,"duration":29},{"text":"Dr. Andrew Huberman: Yeah, I'm thinking a lot now about how we can bridge between these incredible technologies, because I I am a fan, um and but also the non-negotiable technology of our our nervous system and our biology and our psychology, right? Lately, because I have a quarium, I'm really into this thing called aquascaping, which is this Japanese form of, like, plants and and freshwater fish and um just obsessed with it. But and and when the ecosystem is doing well, I'm like, \"Oh,\" like, I feel it's a form of it's brought me some awe at times when, like, things are going well in there, I'm like, \"Wow, it's just beautiful.\"","offset":6807,"duration":34},{"text":"Dr. Andrew Huberman: And um, and I think there are things that I would never do to my fish. I would never isolate them from one another. But I give them enough places to hide from one another because there's a lot of dominance hierarchy stuff being worked out between these discus. Um I make sure they're on a light cycle. I make sure they're fed, but not overfed or underfed, right? And um I wouldn't do most of the things that we do to ourselves to my fish. [Laughs] You know, I wouldn't isolate them and give them like little videos of other fish to look at, like, I know that wouldn't that wouldn't work. Um I know that they would die. I I know. The uh and so I think we can learn a lot from more uh simpler organisms and and the sort of basic units of of care and community. They're very similar. I mean, it gets played out differently, but but they're very similar uh because obviously we we evolved similar nervous systems, let alone similar needs.","offset":6841,"duration":59},{"text":"Dr. Andrew Huberman: I would like to talk about psychedelics if you're willing.","offset":6900,"duration":29},{"text":"Dr. Andrew Huberman: So some people will say, \"Okay, they just send you inward.\" And that's the opposite of what we're talking about, like getting all the awe inside like, \"Okay, that's I mean that's pretty extreme.\" Um other people will say that their experiences with psychedelics allowed them to come out of that experience and really have a a felt connection to people, to plants, to animals, to life that is um profoundly positive for their feelings of connection and seeing awe perhaps even in lots of things.","offset":6929,"duration":38},{"text":"Dr. Andrew Huberman: So how should we think about psychedelics? And we should probably constrain the question a little bit, like, I'm not talking about MDMA, which is not a psychedelic, it's an empathogen. Ketamine's not a psychedelic, it's a dissociative anesthetic. I'm trying to do this now because people start to lump and it's actually causing issues for the potential legalization for...so we need to be splitters, not lumpers here. So I'm talking about LSD, psilocybin, maybe DMT, ayahuasca, the the classic psychedelics. Yeah, what are your thoughts on these?","offset":6967,"duration":29},{"text":"Dr. Dacher Keltner: Yeah, and I'm good friends with Michael Pollan and was, you know, kind of walking the Berkeley Hills as he was producing that book and, you know, watched as we started a center for psychedelics uh at Berkeley. And um and, you know, it's a revolution. I mean, it's psychedelic use is up, you know, 40% since his book. I mean, it's incredible to watch.","offset":6996,"duration":22},{"text":"Dr. Dacher Keltner: And I I have a few thoughts, you know, one is, you know, make sure to honor the indigenous traditions out of which they come. Uh those are spirit medicines in their communities that are part of deep ethical traditions um, you know, and to honor that with, you know, uh re - you know, uh sharing of resources and knowledge and and the right kind of acknowledgment. That's really important.","offset":7018,"duration":26},{"text":"Dr. Dacher Keltner: Um I I think in some sense uh and, you know, David Yaden at Johns Hopkins and others uh and some of the early Roland Griffiths' work spoke to this, that they are about awe um fundamentally, you know? They open up your mind and you see all life forms and time is different and your sense of self vanishes, Robin Carhart-Harris, you know, and you're just connected to vast things, ecosystems and sense of humanity. And I think in some sense and done when done in the right way, that's good news.","offset":7044,"duration":35},{"text":"Dr. Dacher Keltner: You know, Molly Crockett and her team at Princeton like, you go to a festival and you have psychedelics, a year later you're kinder uh through awe, right? Uh so I think that's important. Uh I think it's great news what it does for the hard problems of the mind, you know? Death anxiety, addiction, trauma, uh maybe veterans who are suffering twice the rates of PTSD, they're drawn to this, you know, and the VA is working on this. So and the data look pretty good. OCD, right, hard problems of the mind. Panic, right, that um I've in part dealt with. That is good news.","offset":7079,"duration":44},{"text":"Dr. Dacher Keltner: Um I worry about microdosing. You know, I think people are taking um these things like coffee, and it's not coffee, you know?","offset":7123,"duration":45},{"text":"Dr. Dacher Keltner: And I, you know, they changed my life. I I got to them early uh, you know, in my late teens, 17, 18, 19. I was a very anxious obsessive kid and I think they opened up my mind in this perspective way we've been talking about. I don't really do them now, you know, they gave me a lot and that's why they're here.","offset":7168,"duration":21},{"text":"Dr. Dacher Keltner: You know, it's funny, you know, Andrew, like when I was doing them, we were reading Castaneda who's been debunked, you know, and we're reading the traditions and thinking about them spiritually and the Doors of Perception and all this good stuff, right? We were they were embedded in a a culture of trying to find mysticism or whatever it is, and I hope people are doing that, you know, if they're going to be doing them, make it a form of inquiry. It's a complicated story, like everything, like technology.","offset":7189,"duration":30},{"text":"Dr. Andrew Huberman: Well, they're a form of plant technologies, right? Plant - which uh quick vignette on that. We had someone here um Chris McCurdy, who runs a lab out in Florida, studies kratom and other compounds from plants. The pharma companies, they bioprospect. They send people looking for plants that then they can find isolates and everything from aspirin to uh kratom to anesthetics like cocaine - I'm not suggesting people use as an anesthetic - they come from plants. But they're isolated and then synthesized and and enriched and that's where the opiate the extreme opiate, the extreme stimulant, you know, that's where it comes from. But they all come from plant al- many of them come from plant alkaloids, which is interesting in its own right.","offset":7219,"duration":40},{"text":"Dr. Andrew Huberman: But the I share your feelings about microdosing. Um the data Robin Carhart-Harris tells me, and he's the real expert of course, the data say there's no um evidence of benefit from microdosing, at least on major depression as compared to, like, two rounds of psilocybin with a guide, therapy before, during, and after and on and on.","offset":7259,"duration":23},{"text":"Dr. Andrew Huberman: Um I had the opposite experience as you. Um I actually regret having done psychedelics when I was younger. They were terrifying, I didn't have a good experience. I stopped, didn't go anywhere near them. And then later in a therapeutic setting um had a few experiences with them, not many, but that were immensely beneficial for me. Um so kind of the opposite direction there.","offset":7282,"duration":27},{"text":"Dr. Andrew Huberman: But what we're talking about now about kind of, \"Okay, you know, there's this problem with certain technologies, there's the the culture wars, there's the political wars, there's the actual war that's also going on right now.\" A lot of ways this resembles, like, the 70s, 80s. There's not that - I mean, I remember a time when you had yuppies and you had hippies and you had punk rockers. I mean, you watch a John Hughes film, it was like the idea was was like, \"Oh, we're actually similar,\" right? You know, the extent to which those films like showed people, \"Hey, like people were actually similar along certain dimensions as opposed to so different.\"","offset":7309,"duration":31},{"text":"Dr. Andrew Huberman: But, you know, I I wonder because I think about the not-so-recent and recent history of things, everything from breathwork, cold plunges, psychedelics, um awe, music, the collective consciousness. I mean, it's gonna look different now, the same way that it it looked different back then, right? Like, I'm I'm trying to get outside my Gen X self these days and think like, \"So what would it look like?\" Like, I'm the old guy now. So what would it look like if these technologies, I just mentioned a few, but all of them including social media, what would it look like if those were all used to the greatest benefit? Like, what would that look like? Can we be the open-minded parents of the 80s? You know?","offset":7340,"duration":44},{"text":"Dr. Andrew Huberman: Um can we be the can yeah, like because I feel like I can scream all day or about what I think about the science of this and that to younger people, but the only thing I actually have control over is, like, me. How do we um let's say 40 to 100-year-olds - let's really lean it on the 40 to 70. Okay. How do we create the environment so that younger people can flourish with these technologies as opposed to being like the parents of the 70s and 80s that are like, \"Oh, they got long hair and like what is this like punk rock thing?\" Like, I don't want to be that person. That sucks.","offset":7384,"duration":44},{"text":"Dr. Andrew Huberman: I also don't want to be the and I see this a lot, unfortunately, people who were part of those movements and then they they're just like toeing the party line because oh they're like wholeheartedly adhering to one political group without thinking about whether or not there's any any hint of rational argument on the other side, right? The whole point is not to be against, the whole point is to be for what you believe is right. And so I don't know how to do this. You're older than I am by a bit, you're clearly wiser than I am, seriously, and you have more life experience. So what do we do? Like, really like what what on the help can we do? Because I don't like this, \"You guys are all on your phones, you're like,\" that doesn't feel good to me, because they were telling us when we were younger, like, \"This is ridiculous,\" like the older guys were like, you know, small wheels on skateb- they were right about the small wheels thing, turns out the wheels got too small. But Jim will understand that joke. But what do we do?","offset":7428,"duration":60},{"text":"Dr. Dacher Keltner: I think we're in this moment, you know, with everything going on, you know, with AI and being online and polarization and climate crisis and um, you know, the things that we worry about, the rise of white supremacy politics, etc. Everybody's asking this question of, like, what how do we kind of move forward.","offset":7488,"duration":22},{"text":"Dr. Dacher Keltner: And and, you know, in light of many of the things that we've talked in this conversation, I'm most focused on um what Robert Putnam started to write about and other people started to write about, like the just the breakdown of collective life and shared life. And I think that's the defining issue of our times, as well as our relationship to the natural world.","offset":7510,"duration":28},{"text":"Dr. Dacher Keltner: And I find awe, as do other people, really refreshing. It it provides a road map which is, you know, and I'll give you a very concrete example. I'm working with Gehl Architects on a \"Cities of Awe\" initiative. And they do amazing work, hundreds of cities around the world. 70% of human population is in cities, most of our carbon emissions come out of cities. And this is this is a place we can redesign and and make it better, right?","offset":7538,"duration":31},{"text":"Dr. Dacher Keltner: And awe is a wonderful lens. So you can ask, and you could ask the same of like, \"What do you give to a teenager who's suffering suicidal ideation?\" or \"What do you give to a veteran who is coming back and feeling alienated from the world?\" You give them awe, right? And what does that mean? It's like, well, you give them a little nature. And that's you re-wild part of a city, right? You give them some public art. We love art, you know, we love visual art.","offset":7569,"duration":30},{"text":"Dr. Dacher Keltner: You give them uh the opportunity to recognize the moral beauty, you found it in Joe Strummer, just get them to interact with other people, some face-to-face. You give them uh a little collective stuff, right? You, \"Hey, we're gonna have the yoga class in the town square,\" or the Mexican Zocalo everybody walks together at a certain hour of the day and they suddenly feel peaceful, right?","offset":7599,"duration":26},{"text":"Dr. Dacher Keltner: Uh you give them ideas about big ideas and and life. You give them a little bit of opportunity for meditation and reflection. Um that's easy to do. And when I, you know, was writing this book and just teaching social science for 30 years, it's like, \"Man, you know, we used to do this really well and it used to be temples and church. You know, that's where it all was brought together. And now we don't go there.\" 55% of Americans go to church. It used to be 90. Or temple. Um I don't, I never did, you know, and I and I in some sense miss it, you know? I see my one of my best friends very religious, he few of them and they they have so much.","offset":7625,"duration":45},{"text":"Dr. Dacher Keltner: And we're recreating that right now, right? And we've got to do it in a coherent way. If it's the place where people are lifting weights, there should be music there, there should be visual stuff, there should be some art, nature, there should be some wisdom and some moral beauty, right? That's uh I love ironworks where I go climbing because you go there and it's like people are climbing but there's you get to see the there's the art exhibit each month of a local artist. There's some music going on, you get to listen to music.","offset":7670,"duration":33},{"text":"Dr. Dacher Keltner: So this isn't that hard to do, Andrew. And I think the awe science gives us a road map to think about what we share.","offset":7703,"duration":9},{"text":"Dr. Andrew Huberman: Love that. Um I was not into CrossFit, but a next girlfriend of mine when I met her was, like, really into CrossFit and they would do barbecues and they'd clean the gym and they would dress up in costumes and stuff. I remember this is when I moved to San Diego to start my lab down there before moved to Stanford. And and I remember thinking, like, \"This kind of crazy,\" like I went to the gym growing up, I s- always since I was in my teens, and I'm like, \"Really? You guys are social?\" and they had this awesome social community. I know CrossFit is somewhat fallen out of favor now. Uh I think the pandemic brought us into our isolation.","offset":7712,"duration":33},{"text":"Dr. Andrew Huberman: You may be uh pleased to hear, I I just thought of this, I can't remember I can't believe that I didn't uh remember this earlier. Um one of the things that Joe Strummer was famous for after the Clash, cuz you know he went into the kind of void of, like, he wasn't doing anything. He he wandered for a long time. He went to Spain, oh he grew out a beard, moved to Spain and um didn't tell anyone who he was and they they kind of realized who he was eventually. He was really searching, you know, his life had he lost his brother to suicide, I believe. Um he ran the um the Paris Marathon, this kind of famous, I think while smoking a cigarette. Um people always say and I don't think he did any training.","offset":7745,"duration":39},{"text":"Dr. Andrew Huberman: One thing that he was very well known for until his death was he would do campfires. In Manhattan, he would take people down to the river and and he had some famous friends like Jim Jarmusch and and, you know, and um well-known people in in that world. Um but he would invite whoever. And there were kids - you gotta see this documentary, it's so good. We'll put a link to it um for people want to see it, it's so good. Um there were kids, there were adults, um and they'd stay out to like two or three in the morning playing music, singing, drumming, uh people get up and talk. And so he was constantly doing these campfires his entire life.","offset":7784,"duration":38},{"text":"Dr. Andrew Huberman: Knowing close friends of his, it's like, \"This actually what he did.\" And he wasn't getting - they they were able to film a few of these, but that was not the point. And he would bring out a radio cuz he thought, like, maybe you could, like, make it like a radio show of the thing. And but it was not to record and distribute, it was just...so I don't know, I got this crazy idea in the back of my mind that maybe, like, I'm gonna start doing campfires.","offset":7822,"duration":21},{"text":"Dr. Dacher Keltner: I have to weigh in on some science. Okay.","offset":7843,"duration":43},{"text":"Dr. Dacher Keltner: Um when I go to the climbing gym, we all take saunas. You know, I do probably four saunas a week.","offset":7886,"duration":29},{"text":"Dr. Andrew Huberman: Awesome. Uh campfire also great red light therapy, no joke. Long wavelength light only coming out of that fire. And you know everyone's obsessed with, like, red light therapy. You can get from the sun when you don't want to get too much UV, but yeah, you get tons of long wavelength light exposure, which is great for which is known to be great for mitochondria. I mean, don't get me I don't want to get going on this as too much of a tangent. We've had guests on here from University College London. I mean, the long wavelength light actually goes all the way through your body, even in light clothing, and is absorbed by the water in your mitochondria, which actually improves mitochondrial function in every single every single cell that has a mitochondria.","offset":7915,"duration":36},{"text":"Dr. Dacher Keltner: And where do we get this light from?","offset":7951,"duration":34},{"text":"Dr. Dacher Keltner: Yeah. And people love campfires.","offset":7985,"duration":56},{"text":"Dr. Andrew Huberman: Do you believe in life after death? I don't ask every guest that, by the way. You're the only person I've ever asked that. Do you believe that something happens after all this?","offset":8041,"duration":8},{"text":"Dr. Dacher Keltner: I do. I do. Um yeah, you know, when I write about this in \"Awe,\" when my brother Rolf passed away, colon cancer, 55 or so, uh you know, and I watched the whole transition and, you know, his battle against it and his acceptance and then his leaving. And I had this profound experience that night, you know, a transcendent experience. And I'm like you, you know, Andrew, it's like neurons and statistics and cells and we can figure it all out and characterize everything. And I's like, I saw space in a different way, I saw something alive in him, and then afterward I had a lot of people have this kind of grief experience of, he was around, his voice, his hand was on my back. And...","offset":8049,"duration":51},{"text":"Dacher Keltner: I’ve thought for several years, and still to this day, of, you know, quantum reality and things beyond our three-dimensional, four-dimensional view of time and space and, you know, those basic laws. And that there is, you know, consciousness, maybe patterns of, you know, electromagnetic waves around our minds and bodies that are syncing up with other people that transcend the Newtonian world of the brain. And I believe that. And I don’t know how to study it. I sense it in life. I think a lot of other people do, too. And so that keeps me open to it. And now I’ve moved from, you know, being a skeptical but open, you know, agnostic to like, yeah, there’s something there that’s beyond what we know. So I believe it.","offset":8100,"duration":63},{"text":"Andrew Huberman: Very cool. I hope you’re right. I believe it too, but I just hope you’re right. I sense you’re right. Dacher, thank you so much for making the trip down here to talk with us today and share what you’ve been up to for all these years. You’ve had and continue to have a magnificent career. You know, it’s really hard to do really good science, and it’s even harder to do really good science with a purpose. And you’re doing that, and you continue to, and you just have a way about you that everyone now has been able to experience first-hand. That, like, you really care, that’s clear. You put a ton of thought into the work that you’re doing. You’ve raised 25 professors, which is no small feat, I’ll tell you. That’s a monumental feat, which means that the work will continue. And you’re still going, and I’m grateful for your book and that you’re continuing to do this. And I hope you take that trip too, maybe if you can’t do it around the entire country, you know, hit some pick-up basketball games, because I think there’s something to be learned there for sure, I sense it. And thanks for inspiring me, and I know you’ve inspired a ton of other people. So we’ll put links to everything that you discussed and to your book. But you’ve definitely inspired us to think more deeply about basically what it is to be human and where to take all this technology that we have and this opportunity that we have and really do real good with it. So I’m very grateful to you. Thank you.","offset":8163,"duration":99},{"text":"Dacher Keltner: Well, thank you, Andrew. It’s been an incredible conversation. Let’s do more.","offset":8262,"duration":2},{"text":"Andrew Huberman: Definitely do it again.","offset":8264,"duration":1},{"text":"Dacher Keltner: Yeah, thank you.","offset":8265,"duration":1},{"text":"Andrew Huberman: Thank you for joining me for today’s discussion with Dr. Dacher Keltner. To learn more about his work and to find links to his books, including his book on awe, please see the links in the show note captions. If you’re learning from and/or enjoying this podcast, please subscribe to our YouTube channel. That’s a terrific zero-cost way to support us. In addition, please follow the podcast by clicking the follow button on both Spotify and Apple. And on both Spotify and Apple, you can leave us up to a five-star review. And you can now leave us comments at both Spotify and Apple. Please also check out the sponsors mentioned at the beginning and throughout today’s episode. That’s the best way to support this podcast. If you have questions for me or comments about the podcast, or guests or topics that you’d like me to consider for the Huberman Lab Podcast, please put those in the comment section on YouTube. I do read all the comments.","offset":8266,"duration":46},{"text":"For those of you that haven’t heard, I have a new book coming out. It’s my very first book. It’s entitled \"Protocols: An Operating Manual for the Human Body.\" This is a book that I’ve been working on for more than five years, and that’s been based on more than 30 years of research and experience. And it covers protocols for everything from sleep to exercise to stress control, protocols related to focus and motivation, and of course, I provide the scientific substantiation for the protocols that are included. The book is now available by pre-sale at protocolsbook.com. There you can find links to various vendors; you can pick the one that you like best. Again, the book is called \"Protocols: An Operating Manual for the Human Body.\"","offset":8312,"duration":39},{"text":"And if you’re not already following me on social media, I am @HubermanLab on all social media platforms. So that’s Instagram, X, Threads, Facebook, and LinkedIn. And on all those platforms, I discuss science and science-related tools, some of which overlaps with the content of the Huberman Lab Podcast, but much of which is distinct from the information on the Huberman Lab Podcast. Again, it’s @HubermanLab on all social media platforms.","offset":8351,"duration":23},{"text":"And if you haven’t already subscribed to our Neural Network newsletter, the Neural Network newsletter is a zero-cost monthly newsletter that includes podcast summaries as well as what we call protocols in the form of one- to three-page PDFs that cover everything from how to optimize your sleep, how to optimize dopamine, deliberate cold exposure. We have a foundational fitness protocol that covers cardiovascular training and resistance training. All of that is available completely zero-cost. You simply go to hubermanlab.com, go to the menu tab in the top right corner, scroll down to newsletter, and enter your email. And I should emphasize that we do not share your email with anybody. Thank you once again for joining me for today’s discussion with Dr. Dacher Keltner. And last, but certainly not least, thank you for your interest in science.","offset":8374,"duration":15}],"logs":[{"elapsed":"0.0","message":"Downloading audio from YouTube...","detail":null},{"elapsed":"0.0","message":"Trying download with browser cookies (ad-free)...","detail":null},{"elapsed":"2.8","message":"⚠ Cookie download failed: WARNING: [youtube] [jsc] Error solving n challenge request using \"deno\" provider: Error running deno process (returncode: 1): \u001b[0m\u001b[1m\u001b[31merror\u001b[0m: Uncaught (in promise) TypeError: Cannot read prope","detail":null},{"elapsed":"2.8","message":"Retrying without cookies...","detail":null},{"elapsed":"67.8","message":"⚠ Downloaded without cookies — audio may contain ads","detail":null},{"elapsed":"67.8","message":"Audio downloaded (89.4 MB) in 67.8s","detail":"File size: 89.4 MB"},{"elapsed":"67.8","message":"Video title: Cultivating Awe & Emotional Connection in Daily Life | Dr. Dacher Keltner","detail":null},{"elapsed":"67.9","message":"Audio duration: 2:20:19 (140.3 min)","detail":null},{"elapsed":"67.9","message":"Large audio (140.3 min) — will use chunked transcription with gemini-3-flash-preview","detail":null},{"elapsed":"67.9","message":"Skipping full-file attempt — using chunked transcription for 140.3 min audio","detail":null},{"elapsed":"69.5","message":"Split audio into 4 chunks for transcription","detail":null},{"elapsed":"69.5","message":"Transcribing chunk 1/4 (starts at 0:00)...","detail":null},{"elapsed":"69.5","message":"Uploading audio to Gemini File API...","detail":null},{"elapsed":"74.5","message":"Audio uploaded in 5.1s","detail":"File ref: files/k2bk455voeet"},{"elapsed":"74.5","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"146.6","message":"Chunk 1: 161 segments, last timestamp 53:30","detail":null},{"elapsed":"146.6","message":"Transcribing chunk 2/4 (starts at 45:00)...","detail":null},{"elapsed":"146.6","message":"Uploading audio (offset 45:00) to Gemini File API...","detail":null},{"elapsed":"152.9","message":"Audio uploaded in 6.3s","detail":"File ref: files/gupwohhlonyw"},{"elapsed":"152.9","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"219.7","message":"Adjusted chunk 2 timestamps by +45:00","detail":null},{"elapsed":"219.7","message":"Chunk 2: 189 segments, last timestamp 1:30:18","detail":null},{"elapsed":"219.7","message":"Transcribing chunk 3/4 (starts at 1:30:00)...","detail":null},{"elapsed":"219.7","message":"Uploading audio (offset 1:30:00) to Gemini File API...","detail":null},{"elapsed":"224.8","message":"Audio uploaded in 5.2s","detail":"File ref: files/wbr5p8gcy2sf"},{"elapsed":"224.8","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"292.4","message":"Adjusted chunk 3 timestamps by +1:30:00","detail":null},{"elapsed":"292.4","message":"Chunk 3: 76 segments, last timestamp 2:14:09","detail":null},{"elapsed":"292.4","message":"Transcribing chunk 4/4 (starts at 2:15:00)...","detail":null},{"elapsed":"292.4","message":"Uploading audio (offset 2:15:00) to Gemini File API...","detail":null},{"elapsed":"294.1","message":"Audio uploaded in 1.7s","detail":"File ref: files/5pm58lj9dd47"},{"elapsed":"294.1","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"303.6","message":"Adjusted chunk 4 timestamps by +2:15:00","detail":null},{"elapsed":"303.6","message":"Chunk 4: 9 segments, last timestamp 2:19:34","detail":null},{"elapsed":"303.6","message":"Chunked transcription complete: 398 total segments","detail":null},{"elapsed":"303.6","message":"Total cost: 211,410 in / 40,541 out — cost: $0.2273","detail":null},{"elapsed":"303.6","message":"Total transcription time: 235.7s — 398 segments","detail":null},{"elapsed":"303.6","message":"Analyzing topics across 398 segments with gemini-3.1-pro-preview...","detail":null},{"elapsed":"354.4","message":"Topic analysis complete in 50.7s — found 27 topics","detail":null},{"elapsed":"354.4","message":"Analysis tokens: 37,601 in / 2,151 out / 5,449 thinking — cost: $0.1664","detail":null},{"elapsed":"354.4","message":"Pipeline finished in 354.4s — total cost: $0.3937 (297,152 tokens)","detail":null}]} \ No newline at end of file diff --git a/history/1775603102882-yLmM3M7d9v8.json b/history/1775603102882-yLmM3M7d9v8.json new file mode 100644 index 0000000..9fd1301 --- /dev/null +++ b/history/1775603102882-yLmM3M7d9v8.json @@ -0,0 +1 @@ +{"id":"1775603102882-yLmM3M7d9v8","videoId":"yLmM3M7d9v8","url":"https://www.youtube.com/watch?v=yLmM3M7d9v8","title":"Why You Need a $1B Fund To Do Series A | SpaceX at $2TRN & Data Centers in Space | Groq's $20BN Deal","type":"youtube","topicCount":9,"segmentCount":241,"createdAt":"2026-04-07T23:05:02.883Z","uploadDate":"20260326","chunks":[{"title":"Introduction & Episode Agenda","summary":"The hosts banter about market overreactions and outline the week's agenda, including Anthropic's enterprise gains, Jeff Bezos's mega-fund, SpaceX's valuation, and Groq's acquisition.","entries":[{"text":"Jason: On the Stitch Figma thing, on the one hand, massive market overreaction to a proof of concept, give me an f-ing break. On the other hand...","offset":0,"duration":8},{"text":"Harry: On the agenda this week, Anthropic: are they eating OpenAI's lunch when it comes to enterprise? Jeff Bezos seeks $100 billion for his latest project. SpaceX at $2 trillion after TerraFab. The debrief on Groq's $20 billion deal to Nvidia, and much, much more.","offset":8,"duration":15},{"text":"Rory: If you're a software product and you don't think AI is going to disrupt not just how you build, but what you build, then you actually probably want to actively short it.","offset":23,"duration":8},{"text":"Jason: I think every VC is stressed right now. Let's be honest, who the hell is going to buy them if they don't IPO? I just worry there's some ratio of potential acquirers divided by unicorns, and I think we're at the lowest ratio of our careers. I just don't believe the hyperscalers are going to buy these companies. Basically, it's win or die. Ready to go?","offset":31,"duration":29}],"startTime":0},{"title":"Anthropic Overtakes OpenAI in Enterprise","summary":"Following Ramp's data showing Anthropic capturing 73% of new enterprise AI spend, the hosts discuss OpenAI's defensive response. They debate whether OpenAI's shifting strategies are causing them to lose their enterprise foothold.","entries":[{"text":"Harry: Guys, it is so good to be back. We had, we had a lot of shit go down this week. Um, I think there's a couple of places we could start. To the arbiter of economic justice and revelations, which is Ramp, who revealed recently with, I think they're about 0.5% to 1% of US GDP transactions or whatever it is that Ramp uses as a statement to validate themselves.","offset":60,"duration":25},{"text":"Harry: Ramp data suggested that Anthropic now captures 73% of all spending among companies buying AI tools. 10 weeks ago, it was 50-50 with OpenAI. Early December, it was 60-40 in OpenAI's favor. Are we seeing Anthropic run away with the enterprise lunch, so to speak?","offset":85,"duration":18},{"text":"Rory: Just to start with the facts, they actually said 73% of new spending, right? And what they said, and the same graph shows OpenAI is still actually ahead of Anthropic in terms of total spend, but the marginal buyer in the last 6, 8, 10 weeks has massively shifted, which is obviously the most leading indicator.","offset":103,"duration":21},{"text":"Rory: You know, people in the market today for new AI went 70% Anthropic. So, just in the interest of being precise. Yes, the claim from Ramp, I thought the OpenAI response of, it's not, you know, the snarky comment about extrapolating from a lemonade stand was just a bad look, right?","offset":124,"duration":18},{"text":"Rory: First of all, it kind of doesn't really understand statistics. I would argue Ramp is probably a pretty accurate statistical reflection of especially digital company spend in the US. I think they have got a pretty diversified customer base and they probably have decent data and they've got good data scientists.","offset":142,"duration":23},{"text":"Rory: So it was, so OpenAI trying to be snark, I think was a mistake. I think the real, I think it does represent the facts, which is in the last three months, there's been a shift in the zeitgeist, and I do believe that the marginal user, the marginal person opting for AI today or even people switching today, the switchers are moving towards Claude and they're moving away from OpenAI. That doesn't mean it's the end of the world, but sometimes the first thing you've got to do in dealing with a problem is to face the hard facts in the face. And I think the data was good and the conclusion is real.","offset":165,"duration":30},{"text":"Jason: If Anthropic now is maybe a $20 billion run rate, the revenue does tie to these to conclusions too. Certainly isn't inconsistent with it, right? The only thing I might say, I don't want to spend all our time... I think it's possible they're both right, like OpenAI and Ramp are both right. And what I mean is in some ways this felt to me like the Cursor debate.","offset":195,"duration":19},{"text":"Jason: Because if we walk into our portfolio companies, barely anyone's using Cursor today in my own portfolio, and people said it on Twitter too, like Cursor's dead, no one's using it, they've all moved to Claude. And I would say in that ecosystem, it's true. And maybe if a lot of Ramp's data is still biased toward tech, they might see this same trend.","offset":214,"duration":18},{"text":"Jason: I mean, Claude has, if you just look at why everything's accelerated since December, it is Opus 3.5 and after. It is crystal clear. As soon as Opus came out, it was another step function that was under-discussed, everyone's PRs exploded, everything got better. But for the normal world, they live in ChatGPT.","offset":232,"duration":17},{"text":"Jason: So I don't want to say for sure that the Cursor experience isn't happening here. So in my point is they both could be right. They both could be right. But it's certainly everything, what I don't like is how OpenAI is acting wounded, to Rory's point. I don't like it.","offset":249,"duration":17},{"text":"Jason: When we started this pod, OpenAI seemed invincible no matter what Anthropic did. It seemed utterly... and everything you can just smell this aura, this air of desperation. Oh, we're going to keep head count flat to manage costs, to we're doubling head count. To we're going really deep on agentic commerce, to we're basically canceling it and Walmart says it doesn't work.","offset":266,"duration":19},{"text":"Jason: It feels very inconsistent and what I thought about this, the one thing that I love about Anthropic is it's very consistent about its ICP and goals. It has been very consistent. We know what it stands for, we know what it's trying to do. Yeah, it launches new features, I mean, it's got its new like open, its next version of open Claude launched yesterday as we record this, but you know what's coming with Claude and Anthropic. OpenAI I'm getting whiplash from everything.","offset":285,"duration":25},{"text":"Jason: And the Debbie Downer-ism, it's not... going to last week we talked about the air of invincibility at GTC and Nvidia. It doesn't smell like that at OpenAI today, does it? It's just like a downer to be around and I don't want to try their products because of it, honestly. I actually don't want to try their new products and I literally last night I'm DMing with our chief AI officer, we're trying the new Claude app that just launched. But it ain't gonna hap... we don't want to hang out with Debbie Downers.","offset":310,"duration":29},{"text":"Harry: If we just kind of put that into strategic takeaways, in terms of their pivot, now Sora is getting folded into ChatGPT rather than being a standalone app. Hardware ambitions are being deprioritized and they're really kind of trying to consolidate efforts, stop having such a diverse product set.","offset":339,"duration":19},{"text":"Harry: And then they're also to your point on head count, they now plan to nearly double head count to 8,000 by the end of the year, having said before that they were actually going to keep it flat. Is there a question?","offset":358,"duration":13},{"text":"Jason: No, I just want people to understand the context rather than... you know what it feels like to me in all seriousness, it feels like the... it felt like when we started this podcast quite a while ago, but but not a year ago, I don't think, that OpenAI was an exception to the rule.","offset":371,"duration":15},{"text":"Jason: You could have massive founder turnover, you could have massive management team turnover, you could have an unusual... like the amount of drama with kicking Sam Altman out and then bringing him back and a dysfunctional board and like it seemed to be the exception that made the rule that if you had so much momentum in a consumer... like you could overcome it.","offset":386,"duration":19},{"text":"Jason: Now I feel like the downside is rearing its mind of inconsistency. This inconsistency is damaging the company today in spades. We can see the downstream impacts of that massive turmoil.","offset":405,"duration":11},{"text":"Chamath: Yeah, and I'm going to come in here and try and say something positive, but start by pointing out if we do go back to those first 10 podcasts, they announced the hardware deal with Jony Ive. If you recollect, I was like this will never ship.","offset":416,"duration":15},{"text":"Chamath: I said at the time, and I actually said right when he was on a high that I don't envy Sam because the press only has two stories: we love you, we hate you. And once they've written we love you, there's only one story left. So they're just moving through the to-do list: we've done the we love you Sam, now we hate you Sam, right?","offset":431,"duration":16},{"text":"Chamath: And he has brought on it, you know, you spend a year talking to the prince of fill-in-the-blank, the president of France, instead of staying at home and shipping product, eventually things get defocused, right? But things are never as good or as bad as they seem. That's just one of my rules. It was never as good as people thought a year ago.","offset":447,"duration":17},{"text":"Chamath: They still have, to your point Jason, they still own the consumer business, right? And you know, there's, and so job one is figuring out how to monetize that and make that a big asset business. You know, it's hard to believe that the business, the advertising effort seems to be struggling now, but that's job one to figure out.","offset":464,"duration":15},{"text":"Chamath: And then you're right, job two is to figure out enterprise and in particular coding. I mean, they're doing finally the right stuff, you know, perhaps a year, a year and a half later, but it's still clear to me that if you just take a big deep breath and you were running that organization, focus on the two or three things, get a little more sensible on your financial trajectory, you still have a comfortable chance to be the winner. In other words, to exit two, three years from now as the largest market cap standalone foundation model player, right? You blow it for another year and you won't.","offset":479,"duration":30}],"startTime":60},{"title":"Model Lock-in & Token Economics","summary":"Jason and Rory analyze why developers are locking into Claude's models rather than switching for cheaper alternatives. They explain how the hassle of QAing outputs creates stickiness, making token costs less relevant for high-value applications.","entries":[{"text":"Jason: You know what's interesting is, there's sort of two things going on here that I see in the data, right? If you look at OpenRouter's data, it has exploded since the start of the year. So what that is saying is folks are aggressively switching between models for cost and output, especially cost. Like that's saying there are a large set of customers who are optimizing when to use Glimmy and when to use Haiku and when to use Mini, and and that that model has exploded, right? And we can see it in a lot of our more mature customers, I mean companies that are trying to optimize their spend.","offset":509,"duration":33},{"text":"Jason: On the other hand, so much of us have said listen, I mean, Claude Sonnet and Opus since 3.5 and 3.6 are so good, I want to stick there. It's so... like if you're not deep into coding or vibe coding, you don't see how much better it is in the last 90 days. And I have no desire to screw around when something gets their hooks it... it's so good.","offset":542,"duration":21},{"text":"Jason: And so I want to build all my scaffolding, I want to build my apps, I want to build my AI agents about something that isn't just good, but now is epically good. And so you'd really... there are a lot of even with the OpenRouter data, like I think what I mean is there's this there's these two things happening.","offset":563,"duration":14},{"text":"Jason: On the one hand, the soft costs are very low to pick a different model. But on the other hand, there are high soft costs for managing the outputs and QAing it and qualifying it to make it great. And I don't want to do anything except Sonnet and Opus now. I don't want to spend any time on it. It's not worth... it's not worth the soft cost. And I think that's where the panic is. They can smell that they're losing that even as cost sensitive customers will rotate through the cheapest possible thing.","offset":577,"duration":25},{"text":"Rory: I think true. And I think it speaks to the, you know, you have these discussions, you know, do you want to be first to market or do you want to be second and you know more and you don't, you know, pioneers get arrows in the back and all those clichés. But I think the real truth is if you are first to a market with the right product, you do you you grab that early mind share and market share and then it's theirs to lose.","offset":602,"duration":18},{"text":"Rory: And just contrast the two markets, because it's pretty clear the two potential mega markets here are the consumer market where OpenAI grabbed the mind share with ChatGPT and despite they haven't monetized it yet, no one's really taken that away from them at scale.","offset":620,"duration":15},{"text":"Rory: And then the other mega market is not just enterprise, but within enterprise coding. And you're right, Jason, the scary thing is today it's maybe 6, 12 months ago was up for grabs, today kind of your description's right. It's half up for grabs, people are starting to lock in.","offset":635,"duration":13},{"text":"Rory: And you know, if OpenAI allows Claude to become the default for another year and the perceived best for another year, I don't think you get to show up after a whole bunch of people have made enterprise decisions and say oh now we finally got our shit together, we're good too now I promise, please pick me, right?","offset":648,"duration":18},{"text":"Rory: There is a moment, there is a tide in the affairs of men as Shakespeare says, right? This has been the last six months of coding lock-in, right? Just the recognition that coding is the mother lode app within the enterprise spend. And you're right, if you let Claude run away with that for another six or 12 months, you've probably sacrificed value that you'll never get back.","offset":666,"duration":24},{"text":"Jason: You know let me just give you one small example, like because these because they're the models are so much better since December. So since then, we've built we have built an AI VP of marketing and an AI VP of customer success for real, and they're really, really good.","offset":690,"duration":13},{"text":"Jason: But here is the meta point: our AI VP of marketing defines every day, every single marketing activity, it wakes up in the morning and gives us Slack updates, it runs our weekly team meetings. Our AI VP of success, we have like 200 sponsors for SaaStr and all the humans would quit because it was too much work. It does it 24/7 and the sponsors love it, okay?","offset":703,"duration":18},{"text":"Jason: Now here this so these are great. It runs on Sonnet 3.6 sorry 3.7 and and maybe a little bit of Opus. There is no way we're going to switch the model. This is dialed in, it works. Now we're going to have to deal with QA when it goes to 3.8 and 4.01. There's a little bit of QA and it does change. But my God there's no these apps which we rely on every day, there's no way we're going to switch them to Codex because it took us weeks to dial it in and you have to train it and you have to do it and then now that they're great.","offset":721,"duration":27},{"text":"Jason: Once there's a certain level, I'm not saying that other folks won't, but that is a lock-in since the latest models that I think deserve a code red. We will not invest the time after we've dialed because they're so good, the models today. So that's a risk. I would have a code red on this.","offset":748,"duration":22},{"text":"Chamath: Agreed. And because and again just donning my economics of industry hat, you're exactly. You're an individual enterprise, right? Maybe if you were a SaaS vendor of these products to a thousand enterprises, you might have a big enough engineering team where it'd be worth your while six, 12 months from now to evaluate new models.","offset":770,"duration":20},{"text":"Chamath: But you're right, you've built a business that works for you, right? And it's you're right, unless they're extorting you on token costs, it ain't broke, so you ain't going to want to fix it six months from now. I agree.","offset":790,"duration":10},{"text":"Chamath: And that's why, just like on the consumer side, every time you lock in muscle memory, I mean, I'm using Claude all the time now in Coherence but I will admit when I'm doing my random research for this sort of thing, I still go to ChatGPT. I'm used to it, I got a lot of stuff in there. Every time you lock in behaviors like that and let them settle in for 6, 12 months, you're just, yeah, you're losing lifetime value that's nontrivial.","offset":800,"duration":22},{"text":"Jason: There are applications, if we just stick to B2B and AI for a while, there are applications that are very sensitive to token costs, okay? Um, we've all, you know, even things like support are super sensitive, right? Because they're using so many tokens.","offset":822,"duration":16},{"text":"Jason: But I got to tell you there are so many applications like the ones I described that were not that sensitive to token costs. If you use $200, $400, $2,000, $10,000 of tokens per month for these it just doesn't matter. And so there's the OpenRouter world where costs are super sensitive, but there are plenty of applications that will deliver epic value on these LLMs where it's not worth...","offset":838,"duration":20},{"text":"Jason: You want to reduce my token cost from $2,000 a month to $1,500? I'm not... leave me alone. Leave your Glimmys and all these leave I don't care, like I got 99 problems this isn't on one of them, right? And there are going to be more of those apps than we think.","offset":858,"duration":14},{"text":"Rory: You're exactly right. One of the things I've been thinking about for our for our software apps investments is just having this mental model of, you know, what's the what's the token spend as a percentage of revenue?","offset":872,"duration":9},{"text":"Rory: And you're exactly right Jason, there's a ton of really interesting apps that you know for 5, 7, 8% of revenue on tokens are building huge value, which my sense at least is very different than the coding apps where you might be at 40 or 50%.","offset":881,"duration":13},{"text":"Rory: And if you're at 5% of revenue and you're growing really quickly, you got a lot of better things to be doing with your life than over-optimizing the models. And I think, you know, and if you get around to it you might use some open source. Yeah, exactly.","offset":894,"duration":14},{"text":"Rory: Maybe even more, maybe even 20%. But I think that metric I've actually meant to do this work and if someone has done it out there in internet land I'd love to see it, just looking at a couple of hundred AI apps and just literally looking at the AI token spend as a percentage of revenue across them all. I'd love to know what the pattern is, because I totally see very different percentages depending on the token intensity.","offset":908,"duration":23}],"startTime":509},{"title":"SpaceX TerraFab & $2 Trillion Valuation","summary":"Elon Musk's plans to build a massive chip fab for Tesla and SpaceX prompt a debate over SpaceX's rumored $2 trillion valuation. The group weighs the credibility of Musk's timeline against his history of achieving massive step-function engineering goals.","entries":[{"text":"Harry: SpaceX, TerraFab, potentially $2 trillion. We're reaching new highs. We started off at a trillion two, a trillion five, now TerraFab and the $2 trillion number is being mentioned. Rory why don't we start with some context from you, you're the best at providing succinct...","offset":931,"duration":19},{"text":"Rory: I'm... okay. I mean, the big picture context is context is that Elon made an announcement that they're going to build a fab, effectively build the equivalent I think almost 70% of the volume of all of TSMC, right? In the US near the Gigafactory because across the chip need for Tesla and the perceived and the potential chip need, I'm picking my words carefully, for SpaceX to the extent that they build data centers in space, he doesn't think TSMC will be able to make enough chips to support his needs, and therefore continuing a pattern of vertical integration which they've had for an extended period of time, they're going to build a fab.","offset":950,"duration":44},{"text":"Rory: Right, not just any fab, but the most advanced modern fab on the planet for probably CapEx costs of $25 billion. Right, that's the announcement. So I can't and and it's not clear the ownership by the way, but it's i think the usage, the idea I saw some number like 20% it's kind of some kind of joint Tesla-SpaceX venture, 20% of the volume in the end will go to Tesla, 80% will go to SpaceX and data centers.","offset":994,"duration":28},{"text":"Rory: So that's the story. That's the second piece of context is Harry you said SpaceX now being talked about at $2 trillion. Let's be clear what you're saying about that is because i'm going to push back strong. PolyMarket said the probability of SpaceX being worth $2 trillion on the IPO went up to 50-60%, right? From a lower number, right?","offset":1022,"duration":21},{"text":"Rory: And that's what Harry's attributing information signal to. I would point out that Tesla stock didn't move. So if this really is even if it's 80% SpaceX, 20% Tesla in the market nobody blinked, right? Where actual money's significant money's changing hands. So I am significantly more skeptical that six months from now people are going to attribute another $400 billion of value to a statement that I'm going to build a fab.","offset":1043,"duration":26},{"text":"Jason: Unless they unless they saw your math the 80/20 and really thought of all the value going to SpaceX, right?","offset":1069,"duration":5},{"text":"Rory: Even if all by I mean, yeah, yes, okay. Yes. So again, it's back to the same eternal Elon discussion, at every point in time with every one of his companies, you have things he's already done that you can value on a revenue multiple, things that have been announced or are in process and they're various stages of doneness and in that case you have to assign a probability of getting it done.","offset":1074,"duration":21},{"text":"Rory: And if the probability is 100%, then announcing a fab means you're worth the fab. If the probability is 1%, then announcing a fab means you're worth 1% of the fab, right? And everybody gets to pick their percentage in that continuum, right?","offset":1095,"duration":14},{"text":"Rory: Right now, I mean TSMC itself is just over a trillion in market cap. It's like basically saying if it really popped up by $400 billion of value, it's like basically saying TSMC has spent 30 years building the most modern fabs out there, you've announced that you're going to do the same, you do have customers for those chips in the main, so I'm going to give you a 50% probability of getting it done. It's a pretty high Elon-attributed probability number.","offset":1109,"duration":23},{"text":"Harry: But do you think that's unfair? I wouldn't bet against it. I mean, it's very... I always struggle to describe this. He is the person who's achieved more than anything else entrepreneurially in the world today, period full stop, on hard engineering problems far beyond any piece of software, right?","offset":1132,"duration":18},{"text":"Harry: So that is is it rational to say that if anyone can do it he can? Yes, because he's done it two or three times with cars, with rockets. Not irrational from that perspective. You still have to say is his record on timing of being right about when things happen and when they come a little more spotty, right?","offset":1150,"duration":23},{"text":"Harry: I mean I actually just went into ChatGPT and said make me a chronological list of every prediction from Elon about full self-driving, and then i did another one, make me a chronological prediction of every prediction from Elon about when Starship will be flying and we'll be able to reach, you know, Mars. It's a long line of it's going to happen three years from now in the case of FSD.","offset":1173,"duration":20},{"text":"Harry: So i think with the caveat that we're dealing with the most accomplished entrepreneur probably of at least the last 30 years, maybe one of the top two or three ever, you still have to say his record of predicting timeliness in terms of these things takes a lot longer than you think up front. And you've got to figure out as an investor how you factor that into the valuation. And everyone's entitled... the beautiful thing about markets is everybody gets to play their own way. Right?","offset":1193,"duration":30},{"text":"Jason: I'll tell you what was interesting to me, I watched yesterday on YouTube, they had a Jay Leno where he was the first one to test the new Tesla Semi, okay? And the team from Tesla came over, Franz the head designer and the head PM for Tesla Semi, and they were talking about it and they were talking about energy, and the designer said: Yeah, we strongly believe across all of Tesla the future is fusion.","offset":1223,"duration":22},{"text":"Jason: It is fusion to power our trucks. It's just we believe the fusion's from the sun. There's no point in doing it on earth, and we will soon power all of our semis through fusion. And this isn't this is a thoughtful lead designer saying this vision that has been there and they believe it.","offset":1245,"duration":17},{"text":"Jason: I think it's a great story that can happen, that we're going to build more power than I guess exists in the world today, and 80% of it's going to space. 80% of these chips that come out of this are going to space to power a fusion. You could you could mock that or say it's going to take nine more years than we thought, but it does if it does create a pretty powerful vision for the IPO and beyond and beyond.","offset":1262,"duration":27},{"text":"Jason: I mean, that's pretty now you see it all coming together for SpaceX for real for the first time, well rather than we've got internet satellites and spaceships. Like it sort of made sense, but when we're harnessing the entire sun because it's pretty doable because we've built a lot of it already... starting to sound cheap at $2 trillion. Who else can harness the sun?","offset":1289,"duration":23},{"text":"Rory: Just to push back a little on one word, I you know because i i i think it does all make directional sense, but i'm just going to call you on the word mock, because i didn't mock. I was very clear and i didn't say you some some some, right?","offset":1312,"duration":12},{"text":"Rory: I think you've just got to say look, someone can be 10x more accomplished than you, right? As an entrepreneur and a human being, but when you're investing money you're still entitled to say what probability do i say ascribe to that 10x more accomplished person being able to do the next thing?","offset":1324,"duration":16},{"text":"Rory: And therefore you have to look at this and say for how long will this be supported by a future statement and when will it be worth something on 20 times free cash flow?","offset":1340,"duration":12},{"text":"Jason: But you know why it's interesting, if you really believe in DCF and free cash flow for real in the public markets, and I still get confused, if Starlink really has 53% profit margins and is wildly profitable, the fact that this extends the Starlink vision two orders of five orders of magnitude, it's actually a reason to say hey, if I believe in this at all my my DCF has gone up. How much I don't know.","offset":1352,"duration":24},{"text":"Jason: It's gone up because this is a ma... Starlink is so profitable at scale, like jaw-droppingly profitable, right?","offset":1376,"duration":8},{"text":"Rory: Two comments. First of all, big picture, you are correct. The reason Elon can do it and no one else can is he can articulate these big step-function stories, where as one investor in one of many of his companies pointed out to me, it's a great point he made of this: they're not like software companies that incrementally grow every year, they're kind of step-function technical challenges that you accomplish maybe every five or seven years and then you harvest on that while you're building the next step-function challenge, and then that gives the next lift.","offset":1384,"duration":30},{"text":"Rory: And i mean I think Starship's a great example of that, you had the hey i launch rockets and all i do is get government contracts, and then you're like no i launch rockets and now i have a cellular service for remote for remote cellular, and now the next turn of the crank is maybe if i can get Starship working you can have cellular for everywhere and data centers in space.","offset":1414,"duration":21},{"text":"Rory: So you are right, these are big chunky visions, each of which if realized gives you an extra pick a number $100 billion, $200 billion, $300 billion of net present value of thing. But you just got so i agree i no one else can tell the story and no one else is credible to tell those stories. You've still got to go back to what's the probability of happening when does it happen and what's your cost of capital between now and there.","offset":1435,"duration":23},{"text":"Jason: Yeah, and I I would just argue if you're being if you're the classic optimistic analyst, Wall Street analyst, you can probably justify the $2 trillion Harry's $2 trillion valuation by saying the odds that this occurs are 80%, but but we're ascribing only a 30% chance it happens on time, there's an 80% chance and within five years it achieves similar profit margins to Starlink, and you roll it all back and you can justify $2 billion over 1.x trillion, right? I think you could do it on a spreadsheet.","offset":1458,"duration":27},{"text":"Rory: And that bet will be available to you, and have at it.","offset":1485,"duration":4}],"startTime":931},{"title":"Bezos' $100B Fund & Billionaire Migration","summary":"The hosts unpack Jeff Bezos's attempt to raise a $100 billion fund to inject AI into legacy manufacturing. The conversation shifts to the broader trend of billionaires relocating to Miami to escape vilification and high taxes in traditional tech hubs.","entries":[{"text":"Harry: In the in the in the week of bold $100 billion bets and why the fuck are we doing seed-stage SaaS investing, Jason? Jeff Bezos seeks $100 billion to buy and AI-transform manufacturing. Wall Street Journal broke this one, Jeff Bezos raising $100 billion: manufacturing transformation fund, and acquire companies across semiconductors, space, defense, inject AI into their operations and make them much more efficient. Um, he's apparently been touring Singapore and the Middle East to charm some sovereign wealth funds to give him the money. How did we think about this? Again, it was another week of I feel irrelevant at early-stage VCs.","offset":1489,"duration":38},{"text":"Jason: I think it's a great classic Indian Creek Island investment. So you're sitting in Miami in your couple hundred million dollar home, you've got Jassy and team running the hard business, you don't have to do that that much. Luckily they're doing the hard work and this now I get to think big. I get to think big at Carbone or on the yacht and i don't want to go small anymore and i've already done it, you know, i've already built Amazon.","offset":1527,"duration":24},{"text":"Jason: So you know what i want to do? I'm going to remake some industries. I you know i was with my friends at Pura Vida getting our smoothies and we're all going to remake industries and this is the Indian Creek Island bet. And I get it, right? You don't want to screw around anymore on on at billionaire's bunker, you just don't want to.","offset":1551,"duration":21},{"text":"Harry: Do you think he'll be able to raise the $100 billion?","offset":1572,"duration":4},{"text":"Jason: He could just sell stock if he wants $100 billion he can get it himself, so I'm sure he'll get some significant slug of capital. I mean it's hard i mean i don't know $100 billion i yeah it's so out of my pay grade but...","offset":1576,"duration":12},{"text":"Jason: The only problem is SoftBank seems to be tapped out, they're hitting their debt limits, they just announced this week, right? That they're flashing above their covenants. Um, but I don't think he would announce it if there wasn't a re... that he didn't believe he could do it, right? So you got to announce a decent probability.","offset":1588,"duration":17},{"text":"Rory: I want to come back to what you said Jason. I thought that was actually very insightful, the Indian Creek comment, right? In you do see this of, you know, i did it the hard way, i'm now 50, i'm 60, i'm not 22 anymore, i've got more money and less time so i'd like to insert myself further along in the value creation process to make it happen quickly is the logic.","offset":1605,"duration":22},{"text":"Rory: Because i was reflecting back, AI is this cool new technology that could transform all loads of industries. Just like 20, 30 years ago, the internet was this cool new technology that could transform a whole load of different industries, right?","offset":1627,"duration":14},{"text":"Rory: And if you think you had really and when Jeff Bezos was starting out, there was three different plays you could make. You could say: Hey, internet's going to transform retail and let's focus on retail, I should build software and sell it to retailers so they can kind of move onto the internet. Build Shopify, right?","offset":1641,"duration":18},{"text":"Rory: The second thing you could do is say: Hey, the internet is going to transform retail, I should buy Walmart because I'll kick ass and I'll make them become an internet company and I'll do it that way. Or the third you can do is to say i'm going to do the hard thing for the most amount of money, i'm going to transform retail myself by building a full-stack retailer, i'm going to call it Amazon and i'm just going to kill everyone, right?","offset":1659,"duration":22},{"text":"Rory: And only the and the last one was it turns out the $2 trillion opportunity, right? From zero, so your IRR is from effectively no money in, you make a couple of trillion bucks from a value creation perspective. Shopify, roughly a couple hundred billion dollars, a great because that's the best e-commerce technology provider.","offset":1681,"duration":19},{"text":"Rory: And you know, to be fair to Walmart, if you'd had half a trillion dollars lying around at the time you could have scored a double because it's finally adopted the internet and you know you make a 2x on on a lot of money and you make half a trillion bucks. Because now Walmart's got a market cap plus or minus of a trillion dollars and they're very much a winner in the internet age.","offset":1700,"duration":20},{"text":"Rory: And I was just thinking those are the three games that you play. And back when you're 25 and you have incredible drive, you don't have half a half a trillion dollars lying around, you do Amazon. But you're exactly right, if you're in Indian Creek and you're like oh i don't have 25 years of you know working out of a desk, i'm like a 2x on a 100... you know, taking $100 billion and buying a bunch companies and you know injecting AI into them like i could have injected internet into Walmart, maybe that's the play.","offset":1720,"duration":33},{"text":"Rory: It's inherently less disruptive and more financial engineering than doing either of the Shopify play or the Amazon play. So yeah i agree, i like the framing of the... it's what you do when you have too much money to want to do it the hard way.","offset":1753,"duration":18},{"text":"Jason: If you talk to billionaires today that aren't pulling their hairs out because they're running public SaaS companies, okay? It... the vibe is similar, they want to do something huge in AI right now. They don't necessarily want to run it themselves, they don't want to be CEO again, right? But they're very motivated to do one of these plays. So we're going to see a bunch of these plays, it's what everybody wants to do. It's logical, it's logical from from a billionaire... it's logical.","offset":1771,"duration":24},{"text":"Harry: Yeah, I i love seeing Sergey Brin rock up to a random hackathon in Miami. I'm not sure if you guys saw this? Yeah! But in Miami he came out at the end and you know was a judge or whatever standing on ceremony of a very grassroots hackathon in, you know, a random part of Miami.","offset":1795,"duration":18},{"text":"Jason: Maybe the only only place left in the country hospitable to billionaires, so we'll watch we're going to watch it accelerate.","offset":1813,"duration":6},{"text":"Harry: Oh my god the oppressed species of billionaires.","offset":1819,"duration":2},{"text":"Jason: No no, I do think you know when i think about this the New York QSBS and other stuff, not not we don't have to do it. What i do think when you saw Sergey there, right? And he did he didn't even move to the billionaire bunker he moved to a different different part of Miami Beach, but um um...","offset":1821,"duration":16},{"text":"Jason: I I do think what we're missing is I i think that it is the only place maybe become the only place in the US over the next couple years that is welcoming billionaires. Texas does but Austin even doesn't. Austin does not Austin has mixed views.","offset":1837,"duration":15},{"text":"Jason: But say what you will and I know it's hor... i mean you know Florida welcomes i mean look i mean it's terrible the OnlyFans guy I mean very very controversial subject matter, but where did he live? Pompano Beach, Florida, okay? Florida said you be a billionaire here, okay?","offset":1852,"duration":17},{"text":"Jason: And so we are seeing we're underestimating it's not just taxes, with Sergey it is you may only feel comfortable if you're Bezos or Sergey in Miami soon. Why would you feel comfortable in California or Washington or New York? Seriously why would you feel comfortable? Maybe Utah. I would feel you just don't want to be attacked constantly. No human being wants to feel that way. You want to go where people will just let you be yourself and raise $100 billion or do whatever, like leave me alone, let me let me live. And that's what I think people are missing with the Golden Goose. They're making billionaires uncomfortable, and it's not just the money. It's being uncom... that Sergey, he's he's gone. He ain't coming back except for staff meetings and hackathons in in Mountain View. He's gone.","offset":1869,"duration":44},{"text":"Jason: I'll tell you yesterday I'm here in Utah and i saw Ryan Smith yesterday, i love him right? Founder of Qualtrics, okay? People love Ryan here, and he took his money and bought the Jazz as well as Hockey Team, and he had a rough first year with the Jazz because he traded some top players, but I i they love him here. They love Ryan here, and i don't think in the Bay Area anyone by people are vilified. The billionaires are vilified. Why would you stay?","offset":1913,"duration":30},{"text":"Jason: And so it's only going to accelerate, so it's here's the thing, it's hard to predict the outcome, right? I really don't think adding QSBS to New York is going to lead to the exodus that the people wanted to do. We can talk about why, but they did it in California and it that alone didn't work. But when you are uncomfortable living somewhere, you leave. And it is Ryan Smith is beloved here in Provo where I am today, and Sam Altman is vilified and Dario gets a pass maybe because he gave away 80% but um it's who wants to live there? Who the hell wants to live where you're vilified? Who the hell wants to live there?","offset":1943,"duration":35},{"text":"Rory: Cut put Sam some slack, he apparently has no OpenAI to give away so it's...","offset":1978,"duration":4},{"text":"Jason: Howard Marks left. I mean he's old but he did leave. Um, it's you want to be where you're comfortable.","offset":1982,"duration":5}],"startTime":1489},{"title":"Groq's $20B Nvidia Deal & Antitrust Avoidance","summary":"Nvidia's $20 billion acquisition of Groq sparks a discussion on massive M&A valuation multiples for early-revenue startups. The hosts highlight the highly tax-inefficient structure of the deal, designed specifically to bypass government antitrust delays.","entries":[{"text":"Harry: Speaking of like the world hating billionaires, Groq announced essentially the debrief on the $20 billion deal to Nvidia. Less than $100 million in ARR being acquired. Jonathan the founder is going to make about $950 million after what will be a double taxation. Showing it's quite a costly thing taxes in terms of the IP and team aqua-hires that we've seen.","offset":1987,"duration":26},{"text":"Harry: How did we think and then Chamath also reportedly made $950 million to which he responded on Twitter he made much much more. How did we think about the analysis of this breakdown?","offset":2013,"duration":10},{"text":"Rory: I think there's three different things you said we talk about and i think you should break them apart. You know, one is um how often do you see this kind of sub-$100 million ARR revenue businesses going for this kind of value?","offset":2023,"duration":16},{"text":"Rory: Then the second thing is what was the structure and why does it result in double taxation? And then maybe the third thing is why does poor Chamath need to tell us he's rich all the time? It's okay, we believe you're rich. You know, you may have made you may have made other people poor but we stipulate that you are rich and even you are smart, you did a great deal here. You know, let it go poor guy, therapy will help.","offset":2039,"duration":20},{"text":"Rory: But let's go back to the first one, right? Um how you know, how often because the first question you asked in the notes which you always ignore when it comes to the show is when do you see this kind of transaction price as if revenue doesn't matter?","offset":2059,"duration":12},{"text":"Rory: That was the question, right? When does someone pay $20 billion for $100 million in revenue? And I was thinking about that, it's easy. The answer is when the value to the acquirer is so high and they have the market cap to do it.","offset":2071,"duration":15},{"text":"Rory: And Nvidia with a $5 trillion market cap can pay $20 billion for something that's valuable. And there is another good example i thought of at scale, because it happens a lot at small scale. There are loads of tech M&A where you know some shit little company's doing less than a million in revenue and someone buys it for $100 million, which you know is a 100, 200x revenue multiple, but we don't make a noise about it because it's just so small.","offset":2086,"duration":26},{"text":"Rory: And the reason they're doing that is because they can run it through their channel and they can convert that million in revenue into 20, 30, 40 million very quickly, or it has strategic value to them, right? The number of times it happens at $20 billion is low, but WhatsApp is the other great example of that. Um, Facebook paid $16 billion for WhatsApp and it didn't have a dime of revenue, right? And it was a great deal and it's still a great deal. So it does happen, but there's only a few number of buyers who can afford to do that.","offset":2112,"duration":29},{"text":"Jason: The Groq one, you know they just announced at GDC last week that it's going into production. So that's different, okay? The I don't I and i'll tell you what i find interesting in general for venture, so look they had $100 million in revenue, they proved the concept, they proved it sort of works and Jensen said within a year we can get this into production.","offset":2141,"duration":18},{"text":"Jason: Um, that's worth billions, right? And so it illustrates how weird M&A is so weird. Um this deal probably was a multiple of the last round. The the last round was at $6.9 billion. The there are this is less common these days, but classically rounds would be 2 to 3x the last of a growth round, okay? That that has collapsed for some reason recently.","offset":2159,"duration":21},{"text":"Jason: But my my first startup was acquired for exactly 3x our round, literally our acquirer downloaded our certificate of incorporation, found our per-share price and showed up unsolicited with an offer 3x, okay? That's what i think hap- happened here.","offset":2180,"duration":14},{"text":"Jason: What is so weird though is that it's a reminder that so much of M&A one way or another is focused on revenue multiples, either directly or potentially, and then they're just abandoned after the deal. They're just: You're worth the you're worth 10.2x ARR and then we fire the sales and marketing team after the deal closes and roll it up into our core product. It's uh it's an odd thing, uh necessary but odd, right? There's so many weird ways they are valued.","offset":2194,"duration":28},{"text":"Rory: Agreed and yeah and it's a weird thing because there's often a huge gap between what you're worth standalone might be $2 or $3 billion, what you're worth to your acquirer might be $20 billion, and it's a question of how does that $17 billion of value get allocated?","offset":2222,"duration":16},{"text":"Rory: And obviously sometimes the buyer is trying to grind you down to one dollar more than your standalone value, and then sometimes like in this case they're like: Hey we will pay you a fair amount of what it's worth to us, which is way more than you're worth on a standalone basis.","offset":2238,"duration":15},{"text":"Rory: But kind of segueing to the next thing, in return for that you're going to use this structure which is wildly tax inefficient, but it's the only way for us to get this thing done quickly and without government review. Which is the next thing to say here, which is the point the other point you're trying to make is that you know the CEO, i mean no one's going to cry for someone who made $950 million and they're not even a billionaire so no one'll hate them so that's great. I mean it's actually a win-win, good another $50 million and Jason the pitchforks would be out.","offset":2253,"duration":31},{"text":"Rory: But these transactions are very capital in at tax inefficient because what happens is the company sells the assets to Nvidia, books a gain because the assets were in the books at a sub-billion and now they're getting sold for $20 billion, so you have to pay tax at the company level on that, and then you dividend or redeem the money out and individual investors have to pay tax on the gain.","offset":2284,"duration":21},{"text":"Rory: So it's fairly inefficient, so you're probably wasting plus or minus $4 or $5 billion bucks on a $20 billion transaction because of double taxation.","offset":2305,"duration":8},{"text":"Jason: And it's probably to the founder, Jonathan, it's it's roughly 60% effective tax rate. And and you can't hold Nvidia stock. You're cashed out. Like there's a lot of in there's so many inefficiencies in this deal. One, you don't even get the IP, right? You don't you don't get the company, you don't get anything, and it's a 60% tax rate to the founders and no ability to roll over the stock.","offset":2313,"duration":26},{"text":"Jason: Uh you know avoiding antitrust is it worth it? Probably for the $950 million, but man this this has got to be the most inefficient thing ever convoluted to avoid antitrust. It's so expensive.","offset":2339,"duration":8},{"text":"Rory: And it is worth pointing out it's just quite terrifying from a government perspective, you now have a process whereby the government makes the rules that enforces the antitrust and the government and basically you've got two choices. It would appear you either lobby extensively at the highest levels of the administration and you get a waiver from the top down per that Wall Street Journal article this week, which was pretty good.","offset":2347,"duration":20},{"text":"Rory: Option B is you um pay double you do it this way and then you pay double taxation and the government wins either way. You know wire me the money and I'll let you off or wire me the money after it closes, but wire me the money either way, you know? It's a really perverse incentive. I mean whoever comes into the antitrust division next time and says i think we should clean up the rules and make it much more transparent is probably going to cost the government $20, $30 billion bucks in terms of you know some combination of kickback and tax avoidance. There you go.","offset":2367,"duration":32},{"text":"Harry: I have to say I do like it. Jonathan was in the desert and the dark for many years and he is a founder who's been a real respectfully cockroach who's gone through the hard times, who's gone through the criticism. He's also just a good dude, I like him a lot. And yeah, he's so it's nice to see good people win.","offset":2399,"duration":18},{"text":"Rory: And you're right, just like Chamath, another good guy who's been through the wilderness and has now got his $950 million so they I'm sure that's the point you're trying to make Harry.","offset":2417,"duration":9}],"startTime":1987},{"title":"Figma's Stock Plunge & Incumbent AI Struggles","summary":"Google's launch of Stitch sends Figma's stock tumbling, prompting a debate on whether the market is overreacting. The hosts critique Figma's AI product, discuss the trap of servicing an installed base, and explain why failing to monetize AI features is a major red flag.","entries":[{"text":"Harry: Much more, he needs money Rory, okay? He could he could. He now can now buy some some Loro Piana. Rory you brilliantly say it to me, you know that's great but what about me? I I own stock in Amazon and I own stock in Figma, okay?","offset":2426,"duration":17},{"text":"Harry: Google launches Stitch, Figma tumbles. Figma tumbles is an understatement. I saw a tweet where it was actually an announcement that someone posted and Sequoia were buying $35 million bucks of Figma stock and i was like fuck if Sequoia and Andre are buying $35 million bucks, i'll put in some of my money, that's a good sign for me. I'm down 22%, 22%.","offset":2443,"duration":26},{"text":"Rory: Yeah, looks like about... yeah it's $21.66 a share. I remember, look when it was at 108 and you asked me what i thought it'd be i said 35 and i was wrong, i was you laughed at me and i because i was so pessimistic and i was wrong it's 21. Wow.","offset":2469,"duration":16},{"text":"Rory: No it's does this have a floor? Of course it has a floor. I mean stop you know like the again it's it has a floor based on its cash flow which is strong, it has a floor versus its growth rate of that cash flow. The third element is the probability of disruption and you know right it's the tricky thing about the equity business in the short term is everybody gets to speculate on that probability of disruption.","offset":2485,"duration":24},{"text":"Rory: So you take the cash flows and then if you love the story you apply uplift, see Elon for details, you take the cash flow and then if you're really scared about the story you apply terror downlift, which is what's going on here.","offset":2509,"duration":12},{"text":"Rory: Now in the end, you say is there floor, in the end if the business is worth it, it will grow and it will generate the cash and they'll get to do what the Palantir guy does which i so love which is every earnings call he basically slams all the haters and says basically fuck you i'm making money and you all were wrong.","offset":2521,"duration":17},{"text":"Rory: Until you're in the short term, the market gets to bitch and moan and have its opinion, but the floor doesn't come because the market changes its mind, maybe it will maybe it won't but that's not in your control. If you're running Figma, the floor comes if you execute, you demonstrate that you've been able to adopt, you know, to an AI-native AI-first world, you generate the growth, you generate the cash flows and eventually it'll turn. But that's why drawdowns are shitty, that's why drawdowns are hard.","offset":2538,"duration":29},{"text":"Jason: Well you know on this on this on the Stitch Figma thing, i mean i've used Stitch of course as you would imagine. Um i don't i think most folks that that chimed in on this never used it. Um i'm confident 98%.","offset":2567,"duration":14},{"text":"Harry: Just for those that don't know, Stitch is what for those that don't know?","offset":2581,"duration":2},{"text":"Jason: It is a new design tool that Google launched, and the bar at Google to launch a new AI tool is pretty low. They try a lot of stuff and they abandon almost all of it because then they focus on a few core products. So you literally cannot take it seriously when Google launches a product because you have no idea whether they will stick to it. They launched a Suna, is it Suna sorry i keep getting this wrong Harry, the the audio one, what's the one?","offset":2583,"duration":23},{"text":"Harry: Suno.","offset":2606,"duration":1},{"text":"Jason: Suno, so Google launched a Suno competitor. It's like cool, but it's not nearly as good, like it doesn't really work. And and will they keep with it for five years? I'll bet you dollars to donuts they don't because it's not core, okay?","offset":2607,"duration":13},{"text":"Jason: I used Stitch, I've used all of Google's design products, I think the odds that they design decide to build a Figma competitor from this for a decade approach zero. So on the one hand, massive market overreaction to a to a proof of concept, give me an f-ing break if i'm Sequoia or whatever.","offset":2620,"duration":18},{"text":"Jason: On the other hand, the markets are saying we are extremely worried about disruption. We are extremely worried about disruption. You better prove to us, Figma, Atlassian, Salesforce, you are ahead of disruption and not behind it.","offset":2638,"duration":16},{"text":"Jason: And the market said: We don't believe it. And i agree with the markets here because Figma Make is one of the worst products i've used in the last six months. But this but Stitch on its own at least it's better than Make, at least it can take context from a website and and not hallucinate.","offset":2654,"duration":16},{"text":"Jason: But the market should be like where show me the money again, where is Figma's $300 million of revenue from disrupting Replit and Lovable like we talked before? And so if you haven't delivered like Palantir or started to deliver like Salesforce, the markets are going to freaking panic that your revenue is not that durable.","offset":2670,"duration":19},{"text":"Jason: This is what i think it all like i didn't get the 2026 panic for a long time, i was slow. Now i get it, the markets are rationally saying we no longer believe this revenue is particularly durable.","offset":2689,"duration":11},{"text":"Jason: Old old SaaS people, PE doesn't believe it, Qualtrics couldn't finish its debt offering this week, Salesforce barely got its debt done and why? They don't... the markets just... it's not that they think that Figma is a bad company, they just don't believe this revenue's going to last a decade anymore. They don't believe it. And so you're going to see more more of these panics for anyone not accelerating. People... they're just going to panic every time it happens.","offset":2700,"duration":24},{"text":"Harry: Jason, we just released the show with the CRO of Figma and I asked him how he's seeing AI implemented into your sales teams and he said, honestly, we don't really have that ability and we haven't done it yet, um, oh and and we're hiring a lot more in sales, by the way. We're not reducing headcount at all. That... we're not seeing that. Uh, and oh by the way, we're not seeing seat pricing change at all. How do you feel when you hear that? Because...","offset":2724,"duration":29},{"text":"Jason: Oh, you're just... you're just serving it up. That one ironically, Harry, ironically, that one does not worry me as much as the product. Okay. I will tell you what I've learned. You you and I... you formerly on the other 20VC, me in Farmland, I've talked... I know a lot of the CROs and CMOs at leading AI companies.","offset":2753,"duration":20},{"text":"Jason: The ones I'm close to are pretty good, but I also see tons of folks I call recycled mediocre. They are folks that bombed out of old B2B companies, they barely did anything there, but because they have the right logo, got hired to a super... they're all over the hot AI companies. So many recycled mediocre. And they're going to hire 250 reps and not train them. And they're going to build infographics.","offset":2773,"duration":23},{"text":"Jason: But the products are so strong and the demand is so strong, it doesn't eff-ing matter. So if the guy if if if Figma make was so great and and their AI product was doing 500 million, you you could you could sell it with folks fresh out of a non-technical junior college. It'd be fine, right? Um, so my point is, even though I talk a lot about AI go-to-market agents and I believe they're great and they work, they don't fix product-market fit. In AI sales, it doesn't fix product-market fit. And we're seeing broken... we're seeing decaying product-market fit. That's why the market panicked on Figma. They're seeing hints, just hints, of decaying product-market fit in the AI era and you should panic.","offset":2796,"duration":38},{"text":"Rory: Yeah. I... Harry, just to pile in on that because I actually have these conversations at my companies all the time. I actually to... I didn't think I... I totally agree with what Jason said. It's like when my companies come and say, \"Hey, you've got this problem, we want to talk about AI,\" and they say what, you know, \"Hey look at us, we're using AI in go-to-market,\" or they say, \"Look at us, we're using AI to build engineering,\" I'm like that's great but nobody gives a rat's ass. That... that's like jacks to open. That's not solving the core problem.","offset":2834,"duration":26},{"text":"Rory: The core prob-... unless you're making like cars where it doesn't matter, it's just back-office efficiency. If you're a software company, the number one question is how does AI change the end product you deliver your customers? That's what's going to determine success or failure. So I... I thought I'm fun-... I had a guest you would have piled on to that guy and kind of bludgeoned him while he was down because I thought Harry served you up a softball for you to say, \"Hey the idiot is not using AI,\" and I'd have argued with you, but I think you nailed it. Look.","offset":2860,"duration":28},{"text":"Rory: You could be using AI well or badly in go-to-market. You can be using AI well or badly in engineering. It will catch up with you over time if you're not using it well. But that's not what's driving, you know, 30, 40 percent price declines. What's driving that is exactly what Jason said is the market looks at this and says there's disruption risk here. I don't know the terminal value here. I... I'm just nervous. So I've got to be paid for that risk.","offset":2888,"duration":30},{"text":"Harry: I got... he didn't take my softball, did he, Rory? That was... normally he's so disciplined. He took it...","offset":2918,"duration":3},{"text":"Jason: But Rory's got the important point. You you've got to have the right AI or your company's going to decline. Listen, would I would listen... I'm sure the Figma guy's great, but honestly, if I interviewed a CRO today and didn't have any AI agents that he here or she had brought in to our last podcast, I would recommend to the CEO \"don't hire her or him,\" okay, for sure. But would I think this was... would I be much more worried than if I talked to a CTO and the the new CTO they wanted to hire didn't really believe in in using agentic coding, then then I would ask for my money back. Can I have all of my investment back and 1x? You can keep your mark-up, just give me my 5 million back.","offset":2921,"duration":38},{"text":"Jason: I'm going to go one level more than that, is that you're right. Not using AI in go-to-market, bad. Not using AI to build product, maybe I want my money back. But if you're a software product and you don't think AI is going to disrupt not just how you build but what you build, then you actually probably want to actively short it. Like for example, they're not doing that, but if Figma or Salesforce or someone were to say, \"I don't think AI is relative is relevant for our customer base and they don't want to use AI in design,\" if someone was to say that today, you'd be like, \"Oh my god, you're just going to be, you know, just left behind.\"","offset":2959,"duration":26},{"text":"Jason: Now... and that's why Figma's insensitivity to how mediocre Make is really worries me. I wouldn't care if if Dylan or the team said, \"Listen, Make isn't good enough but wait give me time. Give me six months, it's going to be great.\" But saying this product that is the worst vibe coding tool I have used... that I have used in the last six months, the fact that there is no public awareness that this is an issue really worries me.","offset":2985,"duration":27},{"text":"Harry: Jason, can you help me understand that? Because Dylan is a is a good CEO. I don't... you know...","offset":3012,"duration":4},{"text":"Jason: Excellent CEO. I think we all have listen... I don't know for sure, okay, um, but I think everyone at scale has a trap, which is their installed base is a trap. It is an opportunity and a trap. It is the greatest thing in the world to sell your agentic product to, to sell Agentforce to, is the 44 billion of ARR that Sell-... it's the greatest opportunity because you don't have to earn that base, right? But it is also 50 years of debt, 50 years of features, 50 years of of offline integrations, non-agentic gaps they want, 50 years of of endless work. And if you're not careful, it will consume 98 percent of your resources is that installed base, right? They need so much attention.","offset":3016,"duration":35},{"text":"Jason: And I do think literally Make is the only vibe coding product that I have used where you say, build me a website for 20VC, use 20vc.com as a template, and it can't go to 20vc.com and pull the context to make the website. Now Replit could do this in June of 2025, Lovable could, but anybody can do it today, right? Uh, so including you know who could do it pretty good was um Stitch. Stitch got the context right of the design projects I get it. And that just shows to me whoever's running it doesn't care about these use cases. They just don't care. It has fallen behind and I real-... my guess is, my guess is there's a small team on this.","offset":3051,"duration":43},{"text":"Jason: You know, they're still growing what, 35 percent? Right? I mean this is this is one of the best out there. But the dema-... here's the trap and we all have portfolio companies like this. The trap of of earning that 35 percent imperil can imperil your agentic growth. It can consume more than 100 percent of all the product and engineering and CS resources you have, right? Even Mike Cannon-Brookes when he was on the show, he alluded to it right and then they did the layoffs. He's like, \"I've got to get these resources because otherwise Jira and Confluence and everyone's going to suck it all up and I have no people.\"","offset":3094,"duration":31},{"text":"Rory: Super interesting.","offset":3125,"duration":2},{"text":"Jason: It's a trap, it's a trap, and think of some of your portfolio companies at scale. North of 100 million, they don't describe it this way, but you know it's a trap, especially when they have a mediocre like VP present at the at the board meeting and the mediocre VP is like, \"I just I want to do it but I don't have the people, I need another 700 people to build that.\" And you're like, \"Ugh, it's a trap.\"","offset":3127,"duration":19},{"text":"Rory: It is so hard to say I'll allocate to the new thing first and allocate the residual to the old thing. And you're right, the instinctive is to say I'll deal with the old thing and then I'll find some people for the new. You're right, it's a mindset. It's an interesting point.","offset":3146,"duration":12},{"text":"Jason: Harry, just to pile in on that, because I actually have this conversation. And you know, I don't want to overstate the Intercom example, um, just because you know it's enough already, okay? But but if you want to use it as a case study, it does illustrate what you have to do here. And and Eoghan was clear, we let our core business go into partial decline. It's very hard for al- almost impossible for a public company though. It's lucky being private because you you've got to have a lot of guts to say we're going to let a 1.something billion dollar design business decline a little bit so we can build our agentic product. It's tough when you're public, right? Um, but it's what you've got to do.","offset":3158,"duration":33},{"text":"Harry: Figma's at 21 today, 12 billion market cap. Would you buy it today?","offset":3191,"duration":7},{"text":"Jason: No. I don't see any evidence of turn- of of of these agentic investments working. I would rather miss miss out on the the bounce, right, off the hard deck, than than invest in something that may fall below it. The reason is there's too much change. My god, there's so much change. It's so fast. Make would have been a great product in August of 2025. It's just not today.","offset":3198,"duration":23},{"text":"Rory: The problem with the bounce, and it's a first world problem, is say you buy at 21, the concerns are overdone, you're back up to 24, 25, 26. So you've made some decent money but you sell it, you get ordinary income, blah blah blah. You actually, net of taxes risk adjusted, is it worth it, right? The only way you buy is, and I'm not saying I have the answer to this, when you buy stocks because you want to hold them for five or ten years, you just do better, especially tax adjusted, than when you buy things because you think there's a short-term bounce, right? I personally think that almost all of this stuff is overdone, right, and there probably will be 5, 10, 20 percent bounces across a number of these companies, but to want to buy it I'd have... I haven't done the work that Jason's done. But he is right, you only should buy things if you think five years from now they'll be a winner in the future. I think it's totally plausible Figma could be, but Jason's right, until you've used the product, until you've seen what they do, I I wouldn't make that decision especially at scale.","offset":3221,"duration":58},{"text":"Jason: Well here's the tough thing is Figma's clear, you just had them on. Harry, are they materially charging for their agentic product? So are they monetizing it?","offset":3279,"duration":8},{"text":"Harry: I have no idea.","offset":3287,"duration":1},{"text":"Jason: No, they're not even really charging. Why do you why look at your portfolio companies. Why the hell would you not charge for your AI product today? Agent- why the hell when when Anthropic's doing 22 billion in the blink of an eye, when people are lining up out the door to buy agentic legal products and healthcare products and OpenEvidence, why would you charge almost nothing for your AI product? Why?","offset":3288,"duration":21},{"text":"Jason: It's not good enough. Literally, I was with a founder this last week who was us- who used Make and got very far with it. If nothing else existed, it would be amazing. If Make if if Make was if this was 14 months ago and they built their own LLM and they could do this on their own, our jaws would drop, right? But it's not. It's not good enough to charge for. If it's not good enough to charge for, it doesn't count. You're not an AI company if you can't charge for it. Very few public companies can effectively monetize AI. And that's why they're all in terminal decline. Almost all of them at the moment are in terminal decline. Will they pull off pull it back? I I'm not going to buy their stocks until they do. I don't see any point.","offset":3309,"duration":42},{"text":"Rory: For the record, that's an excellent test.","offset":3351,"duration":3},{"text":"Jason: Yeah, you can't... they even Figma can't charge for it. It's a bad sign, it's a very very bad sign going into the middle of 2026. It's a terrible sign. Terrible sign.","offset":3354,"duration":11},{"text":"Harry: I'm I'm naive here so forgive me for this. Are Notion charging for it? You've spoken before about Notion's brilliance in the integration of that AI capabilities. Are Notion charging additional for that AI capability or is it just a superior product?","offset":3365,"duration":13},{"text":"Jason: Well first off, if I said I thought it was truly brilliant, like I misspoke. I barely we I use Notion all the time. I think the they're good. I don't think it changes the the game in way other products do. But the simple answer to your question is they have been able, look they're not public, right, but if you combine what they've said with their pricing page and their announcements of acceleration and the fact that they have effectively doubled ARPU from it. Doubling ARPU for for-... here's a way to look at an SMB product today. Is your ARPU 50 percent or higher than it was pre-AI? It's a really simple test. Can you drive ARPU up 50 percent or more? It's very different at Salesforce or ServiceNow. It appears that Notion has done that, in which case they they pass the test, right? But I want to see 50 percent or more ARPU growth due to AI or it's just a feature. It's it's just a feature like an integration. Great, hard work, good job guys, let's have beers but it doesn't count.","offset":3378,"duration":57},{"text":"Rory: Yeah. I mean re-acceleration is the aggregate test, to your point two weeks ago, Jason, right? Something's got to be going b- I mean that's been sticking with me too. Something's got to be going better across the marketing KPIs. It can be charging for your AI product. It can be re-acceleration. It can be ACV but something has got to be working and getting traction, otherwise you are falling behind because the AI-first players are delivering utility to their customers and that's manifesting in them those customers giving them money. So if you if you can't make the same phenomenon happen one way or the other, you're falling behind.","offset":3435,"duration":33},{"text":"Jason: Well obviously the market rejected Microsoft Copilot products as things they didn't want to pay more for, right? That's the example of of stumbling. Notion is Notion with AI is 20 bucks a month, the basic is 10. If if everything ties, and private companies have an incentive to be honest but but polish the numbers a little bit, right, to...","offset":3468,"duration":19},{"text":"Rory: See our prior conversation.","offset":3487,"duration":2},{"text":"Jason: Yeah, but assuming there's at least a substantial amount of truth in what they've said, then it then it's working, right? They are able to charge 20 dollars a month for their agentic product, not because they they splashed an AI label on it, but because it's so much better that it is worth it to talk to your docs, to have to have stuff flow into your database autonomously. It's worth 20 bucks. Um, and I suspect we're going to find this I don't love the pricing. I suspect as the year goes on we're going to see the same thing at Slack because most folks haven't used it, we're on it. The AI version of Slack for certain use cases is so much better. I don't love that they're not just charging another four bucks a month, but we I wouldn't be surprised if it's a dramat- if it's like Notion, like they're able to to do it, right?","offset":3489,"duration":42}],"startTime":2426},{"title":"Broken VC Math & The Exit Drought","summary":"Prompted by Mamoon's new $1B fund, the group explores how inflated round sizes are breaking traditional venture capital mathematics. They express deep concern over a severe lack of M&A acquirers for AI unicorns, warning that startups valued at $9B face a \"win or die\" IPO scenario.","entries":[{"text":"Harry: Speaking of Figma, I I'm going to go a little bit off piste but I think it's worthy. Jason, we were on Twitter about it earlier joking. Um, Mamoon announced raising the new KP funds. A billion dollars for the early, two and a half billion for the growth. Um, growth seems small. I mentioned meeting him for the first time at SaaStr, Jason, if you'll believe 10, 10, 11 years ago, in a side room. Kind enough to give me time. My my takeaway is honestly you can't do early and you're going to kill me, Rory, with less than a billion if you're going to compete to lead As. And my reasoning for that is As now a 30 to 40 million and if you want to lead them you need to be able to write 25 to 30 million dollar checks. I think you need 20 across a firm, so if you need 20, 30 million dollar checks you're at 600 million. I would argue that your fund scale is as small as it could be to lead As today.","offset":3531,"duration":61},{"text":"Rory: I don't entirely disagree in the sense that, you know, it's a 900 million dollar fund and you're exactly right. I mean the math of what you threw out is correct. Series As ten to you you're writing an an average of a 20 million dollar check. Our reserves have...","offset":3592,"duration":15},{"text":"Harry: But I don't even think 20 is enough these days.","offset":3607,"duration":2},{"text":"Rory: I know, I know. Let me just let me just take an average, right, because you know if you if you hustle, if you find some deals where it's a little off the beaten track, I've written... I've written As where we've gotten 20 percent ownership for 12 or 15, right? So it's not all but but let's just go at your average, Harry, because rather than arguing the right? You know, it's 50 percent reserves. We you know over like six or seven funds we've been 50 percent reserves. So you end up with 30 million dollars in the average deal. You know, then the last component is a portfolio concentration versus diversification question. I I think given the higher time to exits you probably tend to be nearer to 30 than 20. So yes, I I think, you know, there's a there's a certain small-s scale required to play meaningfully in the Series A business. Yes.","offset":3609,"duration":42},{"text":"Harry: Rory, can I ask you, you've got 720 of investible, you can't have a reserves of 50-50 and be right?","offset":3651,"duration":6},{"text":"Rory: 720? No, I didn't say 50-50, you didn't pay attention, Harry. 50 percent of it... because there's two ways of expressing reserves. It's just simple math, let me help you. Um, one way is expressing it as a percentage of original capital and in other words if I put in 20 do I reserve 10? That's 50 percent of initial capital. And and mathematically that's the same as saying two thirds of the money goes in on the first check and one third goes in in the later check. You're right, I'm not reserving 50 percent of the total amount. Do you understand me? Those are literally just...","offset":3657,"duration":29},{"text":"Harry: I I now I do with that clarification. Thank thank you for clarifying.","offset":3686,"duration":4},{"text":"Rory: I did I used the prepositions correctly the first time as well. But okay, it's good to be clarified. But to be fair to you people do express it both ways and sometimes precision is important. I always think of it as the amount of money you've put in and then the amount of money you have in your back pocket to defend that money if you need to or expand on that position if you want to. So I always think first check.","offset":3690,"duration":18},{"text":"Rory: And what it says is, and this is another insight, unlike for seed where you also have a big fund, for that kind of Series A game, the Series A is not for us, especially for a firm that just has, you know, checks for As and Bs and of this size, it's not an option value on putting a ton of money in later. Most of your value is made on that first check, right? Whereas these folks who have seed or even A funds where their real plan is to put 200 million in at the B or C when it's working, right? To some extent the A is an option value, but just as Jason's for Jason the seed check is the check. For us the A or B, because we're roughly about half and half, is the check. You're not saying oh I'll put in a little now and write more later. That's that's not the way the game can be played.","offset":3708,"duration":46},{"text":"Harry: Rory, are you finding it increasingly uncomfortable with the expansion of Series A rounds because our checks are getting stretched bigger and bigger and it's ruining our math?","offset":3754,"duration":10},{"text":"Rory: I mean it is somewhat uncomfortable but I think you have to find the deals where that's not the case or decide in some cases to reach. I mean and that's I'm going to put both s- both sides of the challenge out there. You know, there may be some deals that are too capital intensive and you decide I don't want to do that because I'm just not getting paid for that risk. But you're right, the average I looked at this math just last week, the average round that we play in has crept up. Right, not just the amount we do but the average round that we play in has crept up over the last year, year and a half. Right, so yes, it's not I would say to the acute level of oh my god, you know, we're perfectly happy with the checks we're writing and the round sizes, but yes, there are times, especially for example, you know, we haven't done any at scale of the kind of the Neo Labs seed checks where you just so outclassed with your 30 or 40 million dollar check, it's barely worth playing.","offset":3764,"duration":53},{"text":"Jason: How big's the Hummingbird fund they just announced?","offset":3817,"duration":3},{"text":"Rory: It's 800.","offset":3820,"duration":1},{"text":"Jason: 800. What was their what what where have they grown their fund size from over time, from doing inception investing?","offset":3821,"duration":6},{"text":"Rory: It's it's 2, 300 of I think initial capital. It's the same fund they always had but adding a growth fund to a rounding error. Right.","offset":3827,"duration":9},{"text":"Jason: Yeah. And then didn't Balderton lead the seed in Revolut?","offset":3836,"duration":3},{"text":"Rory: Yes.","offset":3839,"duration":1},{"text":"Jason: And then who did they just do a billion this week? It's just the the game is it has changed. We were really good at doing Revolut at four, now now billion dollar rounds are a good entry point for us. It's just a lot of change, isn't it?","offset":3840,"duration":15},{"text":"Rory: Yes. There's no anyone look we track it on aggregate, right, versus our 2010 checks you're probably up roughly 2x in terms of the valuation and I think that's significantly lower than the industry as a whole.","offset":3855,"duration":16},{"text":"Jason: Whose point's hard to argue with, which is if you want to own 15 percent of a company or whatever your target number is and deal sizes have inflated, that there's a basic math you have to do, right, with reserves. And that math is in many cases highly stressed in the market today. It's just a f- like it's a fact like, you know, you used to sol- it was very easy to solve your fund size before, right? It was 60 million per partner for seed, maybe 100 for A or B and then it would go up a bit. The math was so simple, all these funds were but that math just is is broken today and it creates interesting I don't find it super interesting but it it is a little bit broken, right? And so if you're Garry Tan you say the 100 billion dollar outcomes make it irrelevant, right?","offset":3871,"duration":38},{"text":"Jason: And I don't know how they work but I was just looking and I was writing an ans- I was writing something up on Wiz and Cyberstarts owned 4 percent at exit, okay? So that that I don't know whether that's dilution or as model back then, but the model still works for a seed fund at 4 percent of 30-some-odd billion, right? Um, but that I think we're going to see more and more of those, right? Dilution in time we'll see more and more seed investments eroded to 3, 4 percent, right? And if they I'm just doing one example, they'll be eroded and and if the exits are uh, you know, north of 10 billion it's okay for a seed fund, right? But the it it's tough.","offset":3909,"duration":47},{"text":"Jason: I don't have the answers. I just think the the old math was easy, right? We need to do 15 to 20 investments per fund, 15 million the average check size and you could roll up into fund sizes that that didn't make you fall out of your chair.","offset":3956,"duration":15},{"text":"Rory: At the risk of being a dick, the math is easy both times because math is independent, you just don't like the answer, right? Multiplying multiplying a pre-money of 50 is no harder than multiplying a pre-money of a billion.","offset":3971,"duration":9},{"text":"Jason: I think the math inherently creates more risk unless the outcomes are massively high.","offset":3980,"duration":4},{"text":"Rory: That's the point.","offset":3984,"duration":1},{"text":"Jason: We are levering up our risk to Harry's point. We're levering up our risk.","offset":3985,"duration":3},{"text":"Rory: I totally agree. I was just being a mild little jerk because I'm think I'm getting grumpy. Exac- it's not that the math is complex, it's just that the consequences are unpleasant and it's what you say. Everyone look we said it over and over again. Everyone's been pushed out on the risk continuum. The whole.","offset":3988,"duration":17},{"text":"Harry: But it does feel like times are changing faster than fund sizes are able to adapt in a way that they haven't done in previous cycles. Like our normalization of billion dollar plus rounds, 100 billion dollar plus raises.","offset":4005,"duration":15},{"text":"Rory: I think that's well put.","offset":4020,"duration":1},{"text":"Harry: So much quicker than fund sizes.","offset":4021,"duration":2},{"text":"Rory: I think that's actually true. The pa- that's actually a good reflection. The pace of change because I've lived through 95 to 99, the run up and the billion dollar funds and I also lived through unwinding watching all those funds being unwound in '02. I remember and then, you know, obviously 2007 that unwinding. This and even 2021, this feels faster than that, right? The action on the table and the need to play at a high. Yes. I think which is why I think every VC is stressed right now. No matter how successful you are, no matter how well your last deal a deal that you did three years ago is doing, everyone wrestling with doing deals now is grumpy, stressed and feeling feeling the pressure.","offset":4023,"duration":35},{"text":"Jason: But I think there's one risk that is under-discussed, okay? All this fund math can lead to concentration risk or ownership risk. Like at least for a smaller fund, I I have to deal with concentration risk or ownership risk. That's the that's the simple trade-off, you can't own that's my math, right?","offset":4058,"duration":14},{"text":"Rory: Agreed.","offset":4072,"duration":1},{"text":"Jason: The one that we are just ignoring because times are so good on paper is who the hell's going to buy these companies if they don't IPO? What the hell are Replit, LangChain, Harvey, Lovable... what how much is Lovable worth in the last round? 8 billion?","offset":4073,"duration":14},{"text":"Harry: 6.5.","offset":4087,"duration":1},{"text":"Jason: Okay, let's be honest, who the hell is going to buy them if they don't IPO? You really think Google's going to buy them for 32 billion? It could don't get me wrong. It could happen. And the and acquisitions are not up, right? Uh, dollars are up. So I just my point that is under-discussed is we are doing these these post-billion dollar deals like like candy. And at least in the in the bubble of '21 there were PE exits, there were many exits out there. We have outstripped any current ability for these companies to have any exit. So you are going all in on the IPO and not without any worry, rhyme or reason and I think so many folks sub-Anthropic are going to get their arses burned because they'll end up in the dead zone. They'll have great companies without great IPOs and zero M&A opportunities. And I'm not saying don't do it, I want my mark-ups on paper, I've got to do it an LP announcement this week. I want my my TVPI and my IRR to look good. But it's also terrible. It's terrible to raise north of a billion. It's terrible because you just out- str- there's just those they're not, you know, Salesforce and and Amaz- I mean Groq is great but a lot of the stuff is not Groq.","offset":4088,"duration":74},{"text":"Rory: Agree with everything you're saying and what's hard about what you're saying is that the strategy that has worked has been precisely the strategy of doing those rounds above a billion and getting the round beyond it. And but you're right, it's all predicated on being able to exit these companies in an IPO. And I will say just to remind you you can imagine a world of IPOs where some of these companies exit. But if the last rounds don't have a block, it's not necessarily going to be above the last rounds. There are some awesome AI applications companies where you kind of go I totally see how that's worth 5 billion dollars in three years based on fundamentals and right now it's valued at 10. And three years from now I could contemplate it going public at 5 billion dollars and you kind of go that last round the 10 is going to have to convert and take 50 cents on the dollars unless it has a meaningful block, in which case they will get more of the company.","offset":4162,"duration":49},{"text":"Jason: Yeah, for sure. I just worry there's some ratio, Rory you can name it, but there's some ratio of potential acquirers real divided by unicorns. And I think we're at the lowest ratio of our careers.","offset":4211,"duration":12},{"text":"Rory: Yeah no absolutely.","offset":4223,"duration":1},{"text":"Jason: The lowest ratio of potential acquirers divided by unicorn unicorn plus up to decacorn that are just not there. We've lost all of PE and Nvidia isn't buying 100 companies, Microsoft is not buying 100 companies.","offset":4224,"duration":13},{"text":"Harry: So what is the subsequent thought then, Jason? Sell aggressively into secondary markets which are more liquid than ever? Like help me understand...","offset":4237,"duration":7},{"text":"Jason: Well probably for early stage investors sure, sell while the that's the Hoppin lesson. I know you love to talk about it, Harry. Maybe that's the lesson. Um...","offset":4244,"duration":7},{"text":"Harry: I don't think it is. Can I just push? I don't actually I'm going to I don't want to use the Hoppin example because then people will because I actually think it I'm going to make it a more interesting discussion. Because when you do Hoppin, people go, \"Well my company's not Hoppin,\" um no pun intended. I think you're saying even for your fucking great company, excuse my language, great company where you know in the end they're not going to be Hoppin, they're not going to a, you know, vanish in a puff of blue smoke, you're still right, which is those last rounds might be a prices you'll never see again. And what should you do as a seed investor? I mean what would you do if a company where you invested at 50, you thought it was worth it could be an M&A at 2 billion at some point in time and suddenly you get a round at 5 billion of new money and there's a secondary opportunity. You're starter for 10, what do you advise?","offset":4251,"duration":45},{"text":"Jason: Yeah. And and listen maybe down maybe just as we're now okay with down IPOs like we're okay with it's just mathematically true, maybe we'll all be chill with down M&As and all these folks raising at 9 and 10 can sell for 1 or 2 in a few years and everyone will be happy. I'm just not so sure that they will and I'm but I'm more worried there's just not going to be a lot a lot of acquisitions. They're very specific. They're very specific to either we're desperately behind on AI or we need to jump forward years. That is a very narrow subset versus uh making sure accounting software at 5 billion is better for accountants. I believe that's a great market, I just don't believe the hyperscalers are going to buy these companies.","offset":4296,"duration":40},{"text":"Rory: No. And the yes because by definition at the app layer, you're not getting the hyperscalers. And the odd thing is, I just realized this for the first time, the odd thing is because of this story of eat the work, the TAM is meant to be larger. That's the whole point of these application-less and I believe it. But Jason to your point what it means is you are definitionally therefore the new company is larger in terms of value than the old company you're replacing, which means the old company can't afford to buy you, right? No chance. If you're Harvey and you're worth 10 billion and West it's not really worth more but if you know the old practice management law software is only worth 2 billion, they're not going to buy you, right? You've got it's basically it's win or die, to your point. I think you're exactly right, Jason, because because these TAMs are bigger in when the TAM becomes bigger the new company has gets marked up and has more has potential to be a bigger outcome. But what it means is once it gets marked to that bigger outcome via late-stage round, it precludes the prior generation buying in. If I was running one of those prior generation companies, right, as if I was the system of record, you what you need to be doing is buying the not marked up, you know, 500 million valuation company and getting something out there. Right but you can't aff-... no matter how hard you try as the old generation legal software company you can't afford Harvey at 10 billion. So doesn't matter what you want they can't you can't afford to buy them and they can't afford to sell to you. I think you're exactly right, Jason. It's kind of structural.","offset":4336,"duration":90},{"text":"Jason: I just wish listen even if IPO markets are barely barely functioning, they're open, but they're barely functioning. If the M&A markets were on fire I'd be good with everything. If we were turning around and these companies were being bought for 10 billion cash each week, I'd be like this is this is awesome man. Um but it it does worry me a little bit that it's so easy to get a 9 billion dollar valuation. It's so much easier to get a 9 billion dollar valuation than a billion dollar exit.","offset":4426,"duration":25},{"text":"Rory: Which should be terrifying if you're the people giving the 9 billion dollar valuation.","offset":4451,"duration":6},{"text":"Jason: I mean you got to play the game on the field but...","offset":4457,"duration":3},{"text":"Rory: Well you actually for the record sometimes you can stick your money in your pocket and not play the game on the field, but that's okay.","offset":4460,"duration":6},{"text":"Harry: But you're playing the game on the field, Rory.","offset":4466,"duration":2},{"text":"Rory: Part of it. And the bits I haven't played have been we you know we haven't done a deals at a billion dollars above. We've you know kept it in that 100 to 3, 400 million dollar pre-money valuation and right now that's been the wrong play. Just to put it out there, right? I mean look I give all credit to for example Spark, the Jasmine there at Spark who broke all the rules and said 4 billion for a pre-revenue company Anthropic. That's paid off, right? I think it'll be interesting for Matt Murphy at Menlo.","offset":4468,"duration":29},{"text":"Harry: Matt Matt has a concept.","offset":4497,"duration":1},{"text":"Rory: Absolutely Matt did it too totally yeah. So my point is some of the late stage bets have paid off. On average I think it's a tough I share the concern. So to your question on playing the game in field, we're playing part of the game on the field but we're a bit scared of certain parts of the valuation curve. I think that will probably across the cycle be the right decision. I'm not sure in the last year or two it's been the right decision, which is always a challenging thing about valuation.","offset":4498,"duration":25},{"text":"Harry: I shouldn't be so honest but I fuck it we'll be it's the end of the day here. My biggest regret with our Series A fund is not being more elastic, disregarding the Series A mandate and just saying I'm going to leverage the brand and the access that I have arrogantly forgive me for that to get into super hot companies like your ElevenLabs, your LangChains, your you name it see Lovables much earlier and being a momentum investor in a hot environment.","offset":4523,"duration":25},{"text":"Rory: I'm going to paraphrase what you said is I have the right to I'm my current plan is to write 20 million dollar checks in Series A investments where I get 10 or 15 10 to 20 percent ownership, right, and I can write 20 of those checks. In retrospect you're saying I should have taken five of those checks, the full 20, not a bitty check but a full ticket, a full ticket or maybe even double down and used a two-ticketer and done Cs, Ds and Es at 1 billion, 2 billion pre and got two mark-ups already, right?","offset":4548,"duration":30},{"text":"Rory: And the interesting question is if your mandate because I wrestle with this a lot so I know it's an interesting question is if your mandate is to do 20 Series As where you get 10 percent to 20 percent ownership and you stick to your knitting and you do your do, right, should you have taken five of those slots and used same check size or maybe even larger check size and done Cs, Ds and Es at 1 billion, 2 billion pre and got two mark-ups already, right? And the truth is in some cases not only will you get mark-ups but you'll get returns commensurate with Series A but at much lower risk. And Anthropic will be the definitive version of that forever. Not actually the round Spark and Menlo did first because that really was risky but kind of the rounds at 14 and 16 billion were risk-adjusted freaking awesome. I wonder will to your point now back to your point I wonder will all of those rounds in those other AI apps companies be as good for precisely the reason you articulated which is that maybe the TAM doesn't support that exit. But right now Harry's right you do you look at the la- yeah Lovable at 6, maybe you could have done it at 1 or 2, you'd have a 3x step up with no hassle, no fear, no early stage. The sweet spot of investing, I mean it's something you said Harry and it was true but tautological, I wish I'd been a mom-... I you said I wish I'd been a momentum player in a rising market. The definition of a momentum strategy is it only works in a rising market, right? But yes, in the market we've been in for the last three years, it's hard to distinguish momentum players from very shrewd players. Both of them have worked out really well. That's the that's the kind of step back from it.","offset":4578,"duration":98},{"text":"Harry: I don't think shrewd players have, actually. That's that's my point. I think shrewd players have appeared disciplined, remained temporally diverse like me and you are, Rory, remained with our high ownership targets and you've had players abscond with AUMs like never before, pay insane prices and get fast mark-ups and in a lot of cases DPI because Zuck buys you at an insane price.","offset":4676,"duration":25},{"text":"Rory: Brutal comment, Harry, then maybe you and I aren't shrewd. Look in the mirror. I you know right?","offset":4701,"duration":5},{"text":"Harry: Very possibly and that's the self-reflective question as I introspect which Mark Andreessen doesn't do clearly.","offset":4706,"duration":8},{"text":"Jason: No, introspection here please.","offset":4714,"duration":2},{"text":"Rory: No. Look look the truth is that is the question everyone wrestles with as you when do you stick with your strategy and when do you break it and what are the and you know what's a good reason to break it. Absolutely, no we all agonize with. And that's why Jason I said the kind of trivial breaking it just to be silly doesn't isn't that interesting, but the sometimes breaking it could be the right strategy and that's the hard one.","offset":4716,"duration":23}],"startTime":3531},{"title":"Episode Outro","summary":"Harry wraps up the episode as the hosts run out of time.","entries":[{"text":"Harry: There we go. Okay, boys it has been a pleasure. Thank you so much as always.","offset":4739,"duration":5},{"text":"Rory: Jesus that was quick. We ran out of time.","offset":4744,"duration":15}],"startTime":4739}],"entries":[{"text":"Jason: On the Stitch Figma thing, on the one hand, massive market overreaction to a proof of concept, give me an f-ing break. On the other hand...","offset":0,"duration":8},{"text":"Harry: On the agenda this week, Anthropic: are they eating OpenAI's lunch when it comes to enterprise? Jeff Bezos seeks $100 billion for his latest project. SpaceX at $2 trillion after TerraFab. The debrief on Groq's $20 billion deal to Nvidia, and much, much more.","offset":8,"duration":15},{"text":"Rory: If you're a software product and you don't think AI is going to disrupt not just how you build, but what you build, then you actually probably want to actively short it.","offset":23,"duration":8},{"text":"Jason: I think every VC is stressed right now. Let's be honest, who the hell is going to buy them if they don't IPO? I just worry there's some ratio of potential acquirers divided by unicorns, and I think we're at the lowest ratio of our careers. I just don't believe the hyperscalers are going to buy these companies. Basically, it's win or die. Ready to go?","offset":31,"duration":29},{"text":"Harry: Guys, it is so good to be back. We had, we had a lot of shit go down this week. Um, I think there's a couple of places we could start. To the arbiter of economic justice and revelations, which is Ramp, who revealed recently with, I think they're about 0.5% to 1% of US GDP transactions or whatever it is that Ramp uses as a statement to validate themselves.","offset":60,"duration":25},{"text":"Harry: Ramp data suggested that Anthropic now captures 73% of all spending among companies buying AI tools. 10 weeks ago, it was 50-50 with OpenAI. Early December, it was 60-40 in OpenAI's favor. Are we seeing Anthropic run away with the enterprise lunch, so to speak?","offset":85,"duration":18},{"text":"Rory: Just to start with the facts, they actually said 73% of new spending, right? And what they said, and the same graph shows OpenAI is still actually ahead of Anthropic in terms of total spend, but the marginal buyer in the last 6, 8, 10 weeks has massively shifted, which is obviously the most leading indicator.","offset":103,"duration":21},{"text":"Rory: You know, people in the market today for new AI went 70% Anthropic. So, just in the interest of being precise. Yes, the claim from Ramp, I thought the OpenAI response of, it's not, you know, the snarky comment about extrapolating from a lemonade stand was just a bad look, right?","offset":124,"duration":18},{"text":"Rory: First of all, it kind of doesn't really understand statistics. I would argue Ramp is probably a pretty accurate statistical reflection of especially digital company spend in the US. I think they have got a pretty diversified customer base and they probably have decent data and they've got good data scientists.","offset":142,"duration":23},{"text":"Rory: So it was, so OpenAI trying to be snark, I think was a mistake. I think the real, I think it does represent the facts, which is in the last three months, there's been a shift in the zeitgeist, and I do believe that the marginal user, the marginal person opting for AI today or even people switching today, the switchers are moving towards Claude and they're moving away from OpenAI. That doesn't mean it's the end of the world, but sometimes the first thing you've got to do in dealing with a problem is to face the hard facts in the face. And I think the data was good and the conclusion is real.","offset":165,"duration":30},{"text":"Jason: If Anthropic now is maybe a $20 billion run rate, the revenue does tie to these to conclusions too. Certainly isn't inconsistent with it, right? The only thing I might say, I don't want to spend all our time... I think it's possible they're both right, like OpenAI and Ramp are both right. And what I mean is in some ways this felt to me like the Cursor debate.","offset":195,"duration":19},{"text":"Jason: Because if we walk into our portfolio companies, barely anyone's using Cursor today in my own portfolio, and people said it on Twitter too, like Cursor's dead, no one's using it, they've all moved to Claude. And I would say in that ecosystem, it's true. And maybe if a lot of Ramp's data is still biased toward tech, they might see this same trend.","offset":214,"duration":18},{"text":"Jason: I mean, Claude has, if you just look at why everything's accelerated since December, it is Opus 3.5 and after. It is crystal clear. As soon as Opus came out, it was another step function that was under-discussed, everyone's PRs exploded, everything got better. But for the normal world, they live in ChatGPT.","offset":232,"duration":17},{"text":"Jason: So I don't want to say for sure that the Cursor experience isn't happening here. So in my point is they both could be right. They both could be right. But it's certainly everything, what I don't like is how OpenAI is acting wounded, to Rory's point. I don't like it.","offset":249,"duration":17},{"text":"Jason: When we started this pod, OpenAI seemed invincible no matter what Anthropic did. It seemed utterly... and everything you can just smell this aura, this air of desperation. Oh, we're going to keep head count flat to manage costs, to we're doubling head count. To we're going really deep on agentic commerce, to we're basically canceling it and Walmart says it doesn't work.","offset":266,"duration":19},{"text":"Jason: It feels very inconsistent and what I thought about this, the one thing that I love about Anthropic is it's very consistent about its ICP and goals. It has been very consistent. We know what it stands for, we know what it's trying to do. Yeah, it launches new features, I mean, it's got its new like open, its next version of open Claude launched yesterday as we record this, but you know what's coming with Claude and Anthropic. OpenAI I'm getting whiplash from everything.","offset":285,"duration":25},{"text":"Jason: And the Debbie Downer-ism, it's not... going to last week we talked about the air of invincibility at GTC and Nvidia. It doesn't smell like that at OpenAI today, does it? It's just like a downer to be around and I don't want to try their products because of it, honestly. I actually don't want to try their new products and I literally last night I'm DMing with our chief AI officer, we're trying the new Claude app that just launched. But it ain't gonna hap... we don't want to hang out with Debbie Downers.","offset":310,"duration":29},{"text":"Harry: If we just kind of put that into strategic takeaways, in terms of their pivot, now Sora is getting folded into ChatGPT rather than being a standalone app. Hardware ambitions are being deprioritized and they're really kind of trying to consolidate efforts, stop having such a diverse product set.","offset":339,"duration":19},{"text":"Harry: And then they're also to your point on head count, they now plan to nearly double head count to 8,000 by the end of the year, having said before that they were actually going to keep it flat. Is there a question?","offset":358,"duration":13},{"text":"Jason: No, I just want people to understand the context rather than... you know what it feels like to me in all seriousness, it feels like the... it felt like when we started this podcast quite a while ago, but but not a year ago, I don't think, that OpenAI was an exception to the rule.","offset":371,"duration":15},{"text":"Jason: You could have massive founder turnover, you could have massive management team turnover, you could have an unusual... like the amount of drama with kicking Sam Altman out and then bringing him back and a dysfunctional board and like it seemed to be the exception that made the rule that if you had so much momentum in a consumer... like you could overcome it.","offset":386,"duration":19},{"text":"Jason: Now I feel like the downside is rearing its mind of inconsistency. This inconsistency is damaging the company today in spades. We can see the downstream impacts of that massive turmoil.","offset":405,"duration":11},{"text":"Chamath: Yeah, and I'm going to come in here and try and say something positive, but start by pointing out if we do go back to those first 10 podcasts, they announced the hardware deal with Jony Ive. If you recollect, I was like this will never ship.","offset":416,"duration":15},{"text":"Chamath: I said at the time, and I actually said right when he was on a high that I don't envy Sam because the press only has two stories: we love you, we hate you. And once they've written we love you, there's only one story left. So they're just moving through the to-do list: we've done the we love you Sam, now we hate you Sam, right?","offset":431,"duration":16},{"text":"Chamath: And he has brought on it, you know, you spend a year talking to the prince of fill-in-the-blank, the president of France, instead of staying at home and shipping product, eventually things get defocused, right? But things are never as good or as bad as they seem. That's just one of my rules. It was never as good as people thought a year ago.","offset":447,"duration":17},{"text":"Chamath: They still have, to your point Jason, they still own the consumer business, right? And you know, there's, and so job one is figuring out how to monetize that and make that a big asset business. You know, it's hard to believe that the business, the advertising effort seems to be struggling now, but that's job one to figure out.","offset":464,"duration":15},{"text":"Chamath: And then you're right, job two is to figure out enterprise and in particular coding. I mean, they're doing finally the right stuff, you know, perhaps a year, a year and a half later, but it's still clear to me that if you just take a big deep breath and you were running that organization, focus on the two or three things, get a little more sensible on your financial trajectory, you still have a comfortable chance to be the winner. In other words, to exit two, three years from now as the largest market cap standalone foundation model player, right? You blow it for another year and you won't.","offset":479,"duration":30},{"text":"Jason: You know what's interesting is, there's sort of two things going on here that I see in the data, right? If you look at OpenRouter's data, it has exploded since the start of the year. So what that is saying is folks are aggressively switching between models for cost and output, especially cost. Like that's saying there are a large set of customers who are optimizing when to use Glimmy and when to use Haiku and when to use Mini, and and that that model has exploded, right? And we can see it in a lot of our more mature customers, I mean companies that are trying to optimize their spend.","offset":509,"duration":33},{"text":"Jason: On the other hand, so much of us have said listen, I mean, Claude Sonnet and Opus since 3.5 and 3.6 are so good, I want to stick there. It's so... like if you're not deep into coding or vibe coding, you don't see how much better it is in the last 90 days. And I have no desire to screw around when something gets their hooks it... it's so good.","offset":542,"duration":21},{"text":"Jason: And so I want to build all my scaffolding, I want to build my apps, I want to build my AI agents about something that isn't just good, but now is epically good. And so you'd really... there are a lot of even with the OpenRouter data, like I think what I mean is there's this there's these two things happening.","offset":563,"duration":14},{"text":"Jason: On the one hand, the soft costs are very low to pick a different model. But on the other hand, there are high soft costs for managing the outputs and QAing it and qualifying it to make it great. And I don't want to do anything except Sonnet and Opus now. I don't want to spend any time on it. It's not worth... it's not worth the soft cost. And I think that's where the panic is. They can smell that they're losing that even as cost sensitive customers will rotate through the cheapest possible thing.","offset":577,"duration":25},{"text":"Rory: I think true. And I think it speaks to the, you know, you have these discussions, you know, do you want to be first to market or do you want to be second and you know more and you don't, you know, pioneers get arrows in the back and all those clichés. But I think the real truth is if you are first to a market with the right product, you do you you grab that early mind share and market share and then it's theirs to lose.","offset":602,"duration":18},{"text":"Rory: And just contrast the two markets, because it's pretty clear the two potential mega markets here are the consumer market where OpenAI grabbed the mind share with ChatGPT and despite they haven't monetized it yet, no one's really taken that away from them at scale.","offset":620,"duration":15},{"text":"Rory: And then the other mega market is not just enterprise, but within enterprise coding. And you're right, Jason, the scary thing is today it's maybe 6, 12 months ago was up for grabs, today kind of your description's right. It's half up for grabs, people are starting to lock in.","offset":635,"duration":13},{"text":"Rory: And you know, if OpenAI allows Claude to become the default for another year and the perceived best for another year, I don't think you get to show up after a whole bunch of people have made enterprise decisions and say oh now we finally got our shit together, we're good too now I promise, please pick me, right?","offset":648,"duration":18},{"text":"Rory: There is a moment, there is a tide in the affairs of men as Shakespeare says, right? This has been the last six months of coding lock-in, right? Just the recognition that coding is the mother lode app within the enterprise spend. And you're right, if you let Claude run away with that for another six or 12 months, you've probably sacrificed value that you'll never get back.","offset":666,"duration":24},{"text":"Jason: You know let me just give you one small example, like because these because they're the models are so much better since December. So since then, we've built we have built an AI VP of marketing and an AI VP of customer success for real, and they're really, really good.","offset":690,"duration":13},{"text":"Jason: But here is the meta point: our AI VP of marketing defines every day, every single marketing activity, it wakes up in the morning and gives us Slack updates, it runs our weekly team meetings. Our AI VP of success, we have like 200 sponsors for SaaStr and all the humans would quit because it was too much work. It does it 24/7 and the sponsors love it, okay?","offset":703,"duration":18},{"text":"Jason: Now here this so these are great. It runs on Sonnet 3.6 sorry 3.7 and and maybe a little bit of Opus. There is no way we're going to switch the model. This is dialed in, it works. Now we're going to have to deal with QA when it goes to 3.8 and 4.01. There's a little bit of QA and it does change. But my God there's no these apps which we rely on every day, there's no way we're going to switch them to Codex because it took us weeks to dial it in and you have to train it and you have to do it and then now that they're great.","offset":721,"duration":27},{"text":"Jason: Once there's a certain level, I'm not saying that other folks won't, but that is a lock-in since the latest models that I think deserve a code red. We will not invest the time after we've dialed because they're so good, the models today. So that's a risk. I would have a code red on this.","offset":748,"duration":22},{"text":"Chamath: Agreed. And because and again just donning my economics of industry hat, you're exactly. You're an individual enterprise, right? Maybe if you were a SaaS vendor of these products to a thousand enterprises, you might have a big enough engineering team where it'd be worth your while six, 12 months from now to evaluate new models.","offset":770,"duration":20},{"text":"Chamath: But you're right, you've built a business that works for you, right? And it's you're right, unless they're extorting you on token costs, it ain't broke, so you ain't going to want to fix it six months from now. I agree.","offset":790,"duration":10},{"text":"Chamath: And that's why, just like on the consumer side, every time you lock in muscle memory, I mean, I'm using Claude all the time now in Coherence but I will admit when I'm doing my random research for this sort of thing, I still go to ChatGPT. I'm used to it, I got a lot of stuff in there. Every time you lock in behaviors like that and let them settle in for 6, 12 months, you're just, yeah, you're losing lifetime value that's nontrivial.","offset":800,"duration":22},{"text":"Jason: There are applications, if we just stick to B2B and AI for a while, there are applications that are very sensitive to token costs, okay? Um, we've all, you know, even things like support are super sensitive, right? Because they're using so many tokens.","offset":822,"duration":16},{"text":"Jason: But I got to tell you there are so many applications like the ones I described that were not that sensitive to token costs. If you use $200, $400, $2,000, $10,000 of tokens per month for these it just doesn't matter. And so there's the OpenRouter world where costs are super sensitive, but there are plenty of applications that will deliver epic value on these LLMs where it's not worth...","offset":838,"duration":20},{"text":"Jason: You want to reduce my token cost from $2,000 a month to $1,500? I'm not... leave me alone. Leave your Glimmys and all these leave I don't care, like I got 99 problems this isn't on one of them, right? And there are going to be more of those apps than we think.","offset":858,"duration":14},{"text":"Rory: You're exactly right. One of the things I've been thinking about for our for our software apps investments is just having this mental model of, you know, what's the what's the token spend as a percentage of revenue?","offset":872,"duration":9},{"text":"Rory: And you're exactly right Jason, there's a ton of really interesting apps that you know for 5, 7, 8% of revenue on tokens are building huge value, which my sense at least is very different than the coding apps where you might be at 40 or 50%.","offset":881,"duration":13},{"text":"Rory: And if you're at 5% of revenue and you're growing really quickly, you got a lot of better things to be doing with your life than over-optimizing the models. And I think, you know, and if you get around to it you might use some open source. Yeah, exactly.","offset":894,"duration":14},{"text":"Rory: Maybe even more, maybe even 20%. But I think that metric I've actually meant to do this work and if someone has done it out there in internet land I'd love to see it, just looking at a couple of hundred AI apps and just literally looking at the AI token spend as a percentage of revenue across them all. I'd love to know what the pattern is, because I totally see very different percentages depending on the token intensity.","offset":908,"duration":23},{"text":"Harry: SpaceX, TerraFab, potentially $2 trillion. We're reaching new highs. We started off at a trillion two, a trillion five, now TerraFab and the $2 trillion number is being mentioned. Rory why don't we start with some context from you, you're the best at providing succinct...","offset":931,"duration":19},{"text":"Rory: I'm... okay. I mean, the big picture context is context is that Elon made an announcement that they're going to build a fab, effectively build the equivalent I think almost 70% of the volume of all of TSMC, right? In the US near the Gigafactory because across the chip need for Tesla and the perceived and the potential chip need, I'm picking my words carefully, for SpaceX to the extent that they build data centers in space, he doesn't think TSMC will be able to make enough chips to support his needs, and therefore continuing a pattern of vertical integration which they've had for an extended period of time, they're going to build a fab.","offset":950,"duration":44},{"text":"Rory: Right, not just any fab, but the most advanced modern fab on the planet for probably CapEx costs of $25 billion. Right, that's the announcement. So I can't and and it's not clear the ownership by the way, but it's i think the usage, the idea I saw some number like 20% it's kind of some kind of joint Tesla-SpaceX venture, 20% of the volume in the end will go to Tesla, 80% will go to SpaceX and data centers.","offset":994,"duration":28},{"text":"Rory: So that's the story. That's the second piece of context is Harry you said SpaceX now being talked about at $2 trillion. Let's be clear what you're saying about that is because i'm going to push back strong. PolyMarket said the probability of SpaceX being worth $2 trillion on the IPO went up to 50-60%, right? From a lower number, right?","offset":1022,"duration":21},{"text":"Rory: And that's what Harry's attributing information signal to. I would point out that Tesla stock didn't move. So if this really is even if it's 80% SpaceX, 20% Tesla in the market nobody blinked, right? Where actual money's significant money's changing hands. So I am significantly more skeptical that six months from now people are going to attribute another $400 billion of value to a statement that I'm going to build a fab.","offset":1043,"duration":26},{"text":"Jason: Unless they unless they saw your math the 80/20 and really thought of all the value going to SpaceX, right?","offset":1069,"duration":5},{"text":"Rory: Even if all by I mean, yeah, yes, okay. Yes. So again, it's back to the same eternal Elon discussion, at every point in time with every one of his companies, you have things he's already done that you can value on a revenue multiple, things that have been announced or are in process and they're various stages of doneness and in that case you have to assign a probability of getting it done.","offset":1074,"duration":21},{"text":"Rory: And if the probability is 100%, then announcing a fab means you're worth the fab. If the probability is 1%, then announcing a fab means you're worth 1% of the fab, right? And everybody gets to pick their percentage in that continuum, right?","offset":1095,"duration":14},{"text":"Rory: Right now, I mean TSMC itself is just over a trillion in market cap. It's like basically saying if it really popped up by $400 billion of value, it's like basically saying TSMC has spent 30 years building the most modern fabs out there, you've announced that you're going to do the same, you do have customers for those chips in the main, so I'm going to give you a 50% probability of getting it done. It's a pretty high Elon-attributed probability number.","offset":1109,"duration":23},{"text":"Harry: But do you think that's unfair? I wouldn't bet against it. I mean, it's very... I always struggle to describe this. He is the person who's achieved more than anything else entrepreneurially in the world today, period full stop, on hard engineering problems far beyond any piece of software, right?","offset":1132,"duration":18},{"text":"Harry: So that is is it rational to say that if anyone can do it he can? Yes, because he's done it two or three times with cars, with rockets. Not irrational from that perspective. You still have to say is his record on timing of being right about when things happen and when they come a little more spotty, right?","offset":1150,"duration":23},{"text":"Harry: I mean I actually just went into ChatGPT and said make me a chronological list of every prediction from Elon about full self-driving, and then i did another one, make me a chronological prediction of every prediction from Elon about when Starship will be flying and we'll be able to reach, you know, Mars. It's a long line of it's going to happen three years from now in the case of FSD.","offset":1173,"duration":20},{"text":"Harry: So i think with the caveat that we're dealing with the most accomplished entrepreneur probably of at least the last 30 years, maybe one of the top two or three ever, you still have to say his record of predicting timeliness in terms of these things takes a lot longer than you think up front. And you've got to figure out as an investor how you factor that into the valuation. And everyone's entitled... the beautiful thing about markets is everybody gets to play their own way. Right?","offset":1193,"duration":30},{"text":"Jason: I'll tell you what was interesting to me, I watched yesterday on YouTube, they had a Jay Leno where he was the first one to test the new Tesla Semi, okay? And the team from Tesla came over, Franz the head designer and the head PM for Tesla Semi, and they were talking about it and they were talking about energy, and the designer said: Yeah, we strongly believe across all of Tesla the future is fusion.","offset":1223,"duration":22},{"text":"Jason: It is fusion to power our trucks. It's just we believe the fusion's from the sun. There's no point in doing it on earth, and we will soon power all of our semis through fusion. And this isn't this is a thoughtful lead designer saying this vision that has been there and they believe it.","offset":1245,"duration":17},{"text":"Jason: I think it's a great story that can happen, that we're going to build more power than I guess exists in the world today, and 80% of it's going to space. 80% of these chips that come out of this are going to space to power a fusion. You could you could mock that or say it's going to take nine more years than we thought, but it does if it does create a pretty powerful vision for the IPO and beyond and beyond.","offset":1262,"duration":27},{"text":"Jason: I mean, that's pretty now you see it all coming together for SpaceX for real for the first time, well rather than we've got internet satellites and spaceships. Like it sort of made sense, but when we're harnessing the entire sun because it's pretty doable because we've built a lot of it already... starting to sound cheap at $2 trillion. Who else can harness the sun?","offset":1289,"duration":23},{"text":"Rory: Just to push back a little on one word, I you know because i i i think it does all make directional sense, but i'm just going to call you on the word mock, because i didn't mock. I was very clear and i didn't say you some some some, right?","offset":1312,"duration":12},{"text":"Rory: I think you've just got to say look, someone can be 10x more accomplished than you, right? As an entrepreneur and a human being, but when you're investing money you're still entitled to say what probability do i say ascribe to that 10x more accomplished person being able to do the next thing?","offset":1324,"duration":16},{"text":"Rory: And therefore you have to look at this and say for how long will this be supported by a future statement and when will it be worth something on 20 times free cash flow?","offset":1340,"duration":12},{"text":"Jason: But you know why it's interesting, if you really believe in DCF and free cash flow for real in the public markets, and I still get confused, if Starlink really has 53% profit margins and is wildly profitable, the fact that this extends the Starlink vision two orders of five orders of magnitude, it's actually a reason to say hey, if I believe in this at all my my DCF has gone up. How much I don't know.","offset":1352,"duration":24},{"text":"Jason: It's gone up because this is a ma... Starlink is so profitable at scale, like jaw-droppingly profitable, right?","offset":1376,"duration":8},{"text":"Rory: Two comments. First of all, big picture, you are correct. The reason Elon can do it and no one else can is he can articulate these big step-function stories, where as one investor in one of many of his companies pointed out to me, it's a great point he made of this: they're not like software companies that incrementally grow every year, they're kind of step-function technical challenges that you accomplish maybe every five or seven years and then you harvest on that while you're building the next step-function challenge, and then that gives the next lift.","offset":1384,"duration":30},{"text":"Rory: And i mean I think Starship's a great example of that, you had the hey i launch rockets and all i do is get government contracts, and then you're like no i launch rockets and now i have a cellular service for remote for remote cellular, and now the next turn of the crank is maybe if i can get Starship working you can have cellular for everywhere and data centers in space.","offset":1414,"duration":21},{"text":"Rory: So you are right, these are big chunky visions, each of which if realized gives you an extra pick a number $100 billion, $200 billion, $300 billion of net present value of thing. But you just got so i agree i no one else can tell the story and no one else is credible to tell those stories. You've still got to go back to what's the probability of happening when does it happen and what's your cost of capital between now and there.","offset":1435,"duration":23},{"text":"Jason: Yeah, and I I would just argue if you're being if you're the classic optimistic analyst, Wall Street analyst, you can probably justify the $2 trillion Harry's $2 trillion valuation by saying the odds that this occurs are 80%, but but we're ascribing only a 30% chance it happens on time, there's an 80% chance and within five years it achieves similar profit margins to Starlink, and you roll it all back and you can justify $2 billion over 1.x trillion, right? I think you could do it on a spreadsheet.","offset":1458,"duration":27},{"text":"Rory: And that bet will be available to you, and have at it.","offset":1485,"duration":4},{"text":"Harry: In the in the in the week of bold $100 billion bets and why the fuck are we doing seed-stage SaaS investing, Jason? Jeff Bezos seeks $100 billion to buy and AI-transform manufacturing. Wall Street Journal broke this one, Jeff Bezos raising $100 billion: manufacturing transformation fund, and acquire companies across semiconductors, space, defense, inject AI into their operations and make them much more efficient. Um, he's apparently been touring Singapore and the Middle East to charm some sovereign wealth funds to give him the money. How did we think about this? Again, it was another week of I feel irrelevant at early-stage VCs.","offset":1489,"duration":38},{"text":"Jason: I think it's a great classic Indian Creek Island investment. So you're sitting in Miami in your couple hundred million dollar home, you've got Jassy and team running the hard business, you don't have to do that that much. Luckily they're doing the hard work and this now I get to think big. I get to think big at Carbone or on the yacht and i don't want to go small anymore and i've already done it, you know, i've already built Amazon.","offset":1527,"duration":24},{"text":"Jason: So you know what i want to do? I'm going to remake some industries. I you know i was with my friends at Pura Vida getting our smoothies and we're all going to remake industries and this is the Indian Creek Island bet. And I get it, right? You don't want to screw around anymore on on at billionaire's bunker, you just don't want to.","offset":1551,"duration":21},{"text":"Harry: Do you think he'll be able to raise the $100 billion?","offset":1572,"duration":4},{"text":"Jason: He could just sell stock if he wants $100 billion he can get it himself, so I'm sure he'll get some significant slug of capital. I mean it's hard i mean i don't know $100 billion i yeah it's so out of my pay grade but...","offset":1576,"duration":12},{"text":"Jason: The only problem is SoftBank seems to be tapped out, they're hitting their debt limits, they just announced this week, right? That they're flashing above their covenants. Um, but I don't think he would announce it if there wasn't a re... that he didn't believe he could do it, right? So you got to announce a decent probability.","offset":1588,"duration":17},{"text":"Rory: I want to come back to what you said Jason. I thought that was actually very insightful, the Indian Creek comment, right? In you do see this of, you know, i did it the hard way, i'm now 50, i'm 60, i'm not 22 anymore, i've got more money and less time so i'd like to insert myself further along in the value creation process to make it happen quickly is the logic.","offset":1605,"duration":22},{"text":"Rory: Because i was reflecting back, AI is this cool new technology that could transform all loads of industries. Just like 20, 30 years ago, the internet was this cool new technology that could transform a whole load of different industries, right?","offset":1627,"duration":14},{"text":"Rory: And if you think you had really and when Jeff Bezos was starting out, there was three different plays you could make. You could say: Hey, internet's going to transform retail and let's focus on retail, I should build software and sell it to retailers so they can kind of move onto the internet. Build Shopify, right?","offset":1641,"duration":18},{"text":"Rory: The second thing you could do is say: Hey, the internet is going to transform retail, I should buy Walmart because I'll kick ass and I'll make them become an internet company and I'll do it that way. Or the third you can do is to say i'm going to do the hard thing for the most amount of money, i'm going to transform retail myself by building a full-stack retailer, i'm going to call it Amazon and i'm just going to kill everyone, right?","offset":1659,"duration":22},{"text":"Rory: And only the and the last one was it turns out the $2 trillion opportunity, right? From zero, so your IRR is from effectively no money in, you make a couple of trillion bucks from a value creation perspective. Shopify, roughly a couple hundred billion dollars, a great because that's the best e-commerce technology provider.","offset":1681,"duration":19},{"text":"Rory: And you know, to be fair to Walmart, if you'd had half a trillion dollars lying around at the time you could have scored a double because it's finally adopted the internet and you know you make a 2x on on a lot of money and you make half a trillion bucks. Because now Walmart's got a market cap plus or minus of a trillion dollars and they're very much a winner in the internet age.","offset":1700,"duration":20},{"text":"Rory: And I was just thinking those are the three games that you play. And back when you're 25 and you have incredible drive, you don't have half a half a trillion dollars lying around, you do Amazon. But you're exactly right, if you're in Indian Creek and you're like oh i don't have 25 years of you know working out of a desk, i'm like a 2x on a 100... you know, taking $100 billion and buying a bunch companies and you know injecting AI into them like i could have injected internet into Walmart, maybe that's the play.","offset":1720,"duration":33},{"text":"Rory: It's inherently less disruptive and more financial engineering than doing either of the Shopify play or the Amazon play. So yeah i agree, i like the framing of the... it's what you do when you have too much money to want to do it the hard way.","offset":1753,"duration":18},{"text":"Jason: If you talk to billionaires today that aren't pulling their hairs out because they're running public SaaS companies, okay? It... the vibe is similar, they want to do something huge in AI right now. They don't necessarily want to run it themselves, they don't want to be CEO again, right? But they're very motivated to do one of these plays. So we're going to see a bunch of these plays, it's what everybody wants to do. It's logical, it's logical from from a billionaire... it's logical.","offset":1771,"duration":24},{"text":"Harry: Yeah, I i love seeing Sergey Brin rock up to a random hackathon in Miami. I'm not sure if you guys saw this? Yeah! But in Miami he came out at the end and you know was a judge or whatever standing on ceremony of a very grassroots hackathon in, you know, a random part of Miami.","offset":1795,"duration":18},{"text":"Jason: Maybe the only only place left in the country hospitable to billionaires, so we'll watch we're going to watch it accelerate.","offset":1813,"duration":6},{"text":"Harry: Oh my god the oppressed species of billionaires.","offset":1819,"duration":2},{"text":"Jason: No no, I do think you know when i think about this the New York QSBS and other stuff, not not we don't have to do it. What i do think when you saw Sergey there, right? And he did he didn't even move to the billionaire bunker he moved to a different different part of Miami Beach, but um um...","offset":1821,"duration":16},{"text":"Jason: I I do think what we're missing is I i think that it is the only place maybe become the only place in the US over the next couple years that is welcoming billionaires. Texas does but Austin even doesn't. Austin does not Austin has mixed views.","offset":1837,"duration":15},{"text":"Jason: But say what you will and I know it's hor... i mean you know Florida welcomes i mean look i mean it's terrible the OnlyFans guy I mean very very controversial subject matter, but where did he live? Pompano Beach, Florida, okay? Florida said you be a billionaire here, okay?","offset":1852,"duration":17},{"text":"Jason: And so we are seeing we're underestimating it's not just taxes, with Sergey it is you may only feel comfortable if you're Bezos or Sergey in Miami soon. Why would you feel comfortable in California or Washington or New York? Seriously why would you feel comfortable? Maybe Utah. I would feel you just don't want to be attacked constantly. No human being wants to feel that way. You want to go where people will just let you be yourself and raise $100 billion or do whatever, like leave me alone, let me let me live. And that's what I think people are missing with the Golden Goose. They're making billionaires uncomfortable, and it's not just the money. It's being uncom... that Sergey, he's he's gone. He ain't coming back except for staff meetings and hackathons in in Mountain View. He's gone.","offset":1869,"duration":44},{"text":"Jason: I'll tell you yesterday I'm here in Utah and i saw Ryan Smith yesterday, i love him right? Founder of Qualtrics, okay? People love Ryan here, and he took his money and bought the Jazz as well as Hockey Team, and he had a rough first year with the Jazz because he traded some top players, but I i they love him here. They love Ryan here, and i don't think in the Bay Area anyone by people are vilified. The billionaires are vilified. Why would you stay?","offset":1913,"duration":30},{"text":"Jason: And so it's only going to accelerate, so it's here's the thing, it's hard to predict the outcome, right? I really don't think adding QSBS to New York is going to lead to the exodus that the people wanted to do. We can talk about why, but they did it in California and it that alone didn't work. But when you are uncomfortable living somewhere, you leave. And it is Ryan Smith is beloved here in Provo where I am today, and Sam Altman is vilified and Dario gets a pass maybe because he gave away 80% but um it's who wants to live there? Who the hell wants to live where you're vilified? Who the hell wants to live there?","offset":1943,"duration":35},{"text":"Rory: Cut put Sam some slack, he apparently has no OpenAI to give away so it's...","offset":1978,"duration":4},{"text":"Jason: Howard Marks left. I mean he's old but he did leave. Um, it's you want to be where you're comfortable.","offset":1982,"duration":5},{"text":"Harry: Speaking of like the world hating billionaires, Groq announced essentially the debrief on the $20 billion deal to Nvidia. Less than $100 million in ARR being acquired. Jonathan the founder is going to make about $950 million after what will be a double taxation. Showing it's quite a costly thing taxes in terms of the IP and team aqua-hires that we've seen.","offset":1987,"duration":26},{"text":"Harry: How did we think and then Chamath also reportedly made $950 million to which he responded on Twitter he made much much more. How did we think about the analysis of this breakdown?","offset":2013,"duration":10},{"text":"Rory: I think there's three different things you said we talk about and i think you should break them apart. You know, one is um how often do you see this kind of sub-$100 million ARR revenue businesses going for this kind of value?","offset":2023,"duration":16},{"text":"Rory: Then the second thing is what was the structure and why does it result in double taxation? And then maybe the third thing is why does poor Chamath need to tell us he's rich all the time? It's okay, we believe you're rich. You know, you may have made you may have made other people poor but we stipulate that you are rich and even you are smart, you did a great deal here. You know, let it go poor guy, therapy will help.","offset":2039,"duration":20},{"text":"Rory: But let's go back to the first one, right? Um how you know, how often because the first question you asked in the notes which you always ignore when it comes to the show is when do you see this kind of transaction price as if revenue doesn't matter?","offset":2059,"duration":12},{"text":"Rory: That was the question, right? When does someone pay $20 billion for $100 million in revenue? And I was thinking about that, it's easy. The answer is when the value to the acquirer is so high and they have the market cap to do it.","offset":2071,"duration":15},{"text":"Rory: And Nvidia with a $5 trillion market cap can pay $20 billion for something that's valuable. And there is another good example i thought of at scale, because it happens a lot at small scale. There are loads of tech M&A where you know some shit little company's doing less than a million in revenue and someone buys it for $100 million, which you know is a 100, 200x revenue multiple, but we don't make a noise about it because it's just so small.","offset":2086,"duration":26},{"text":"Rory: And the reason they're doing that is because they can run it through their channel and they can convert that million in revenue into 20, 30, 40 million very quickly, or it has strategic value to them, right? The number of times it happens at $20 billion is low, but WhatsApp is the other great example of that. Um, Facebook paid $16 billion for WhatsApp and it didn't have a dime of revenue, right? And it was a great deal and it's still a great deal. So it does happen, but there's only a few number of buyers who can afford to do that.","offset":2112,"duration":29},{"text":"Jason: The Groq one, you know they just announced at GDC last week that it's going into production. So that's different, okay? The I don't I and i'll tell you what i find interesting in general for venture, so look they had $100 million in revenue, they proved the concept, they proved it sort of works and Jensen said within a year we can get this into production.","offset":2141,"duration":18},{"text":"Jason: Um, that's worth billions, right? And so it illustrates how weird M&A is so weird. Um this deal probably was a multiple of the last round. The the last round was at $6.9 billion. The there are this is less common these days, but classically rounds would be 2 to 3x the last of a growth round, okay? That that has collapsed for some reason recently.","offset":2159,"duration":21},{"text":"Jason: But my my first startup was acquired for exactly 3x our round, literally our acquirer downloaded our certificate of incorporation, found our per-share price and showed up unsolicited with an offer 3x, okay? That's what i think hap- happened here.","offset":2180,"duration":14},{"text":"Jason: What is so weird though is that it's a reminder that so much of M&A one way or another is focused on revenue multiples, either directly or potentially, and then they're just abandoned after the deal. They're just: You're worth the you're worth 10.2x ARR and then we fire the sales and marketing team after the deal closes and roll it up into our core product. It's uh it's an odd thing, uh necessary but odd, right? There's so many weird ways they are valued.","offset":2194,"duration":28},{"text":"Rory: Agreed and yeah and it's a weird thing because there's often a huge gap between what you're worth standalone might be $2 or $3 billion, what you're worth to your acquirer might be $20 billion, and it's a question of how does that $17 billion of value get allocated?","offset":2222,"duration":16},{"text":"Rory: And obviously sometimes the buyer is trying to grind you down to one dollar more than your standalone value, and then sometimes like in this case they're like: Hey we will pay you a fair amount of what it's worth to us, which is way more than you're worth on a standalone basis.","offset":2238,"duration":15},{"text":"Rory: But kind of segueing to the next thing, in return for that you're going to use this structure which is wildly tax inefficient, but it's the only way for us to get this thing done quickly and without government review. Which is the next thing to say here, which is the point the other point you're trying to make is that you know the CEO, i mean no one's going to cry for someone who made $950 million and they're not even a billionaire so no one'll hate them so that's great. I mean it's actually a win-win, good another $50 million and Jason the pitchforks would be out.","offset":2253,"duration":31},{"text":"Rory: But these transactions are very capital in at tax inefficient because what happens is the company sells the assets to Nvidia, books a gain because the assets were in the books at a sub-billion and now they're getting sold for $20 billion, so you have to pay tax at the company level on that, and then you dividend or redeem the money out and individual investors have to pay tax on the gain.","offset":2284,"duration":21},{"text":"Rory: So it's fairly inefficient, so you're probably wasting plus or minus $4 or $5 billion bucks on a $20 billion transaction because of double taxation.","offset":2305,"duration":8},{"text":"Jason: And it's probably to the founder, Jonathan, it's it's roughly 60% effective tax rate. And and you can't hold Nvidia stock. You're cashed out. Like there's a lot of in there's so many inefficiencies in this deal. One, you don't even get the IP, right? You don't you don't get the company, you don't get anything, and it's a 60% tax rate to the founders and no ability to roll over the stock.","offset":2313,"duration":26},{"text":"Jason: Uh you know avoiding antitrust is it worth it? Probably for the $950 million, but man this this has got to be the most inefficient thing ever convoluted to avoid antitrust. It's so expensive.","offset":2339,"duration":8},{"text":"Rory: And it is worth pointing out it's just quite terrifying from a government perspective, you now have a process whereby the government makes the rules that enforces the antitrust and the government and basically you've got two choices. It would appear you either lobby extensively at the highest levels of the administration and you get a waiver from the top down per that Wall Street Journal article this week, which was pretty good.","offset":2347,"duration":20},{"text":"Rory: Option B is you um pay double you do it this way and then you pay double taxation and the government wins either way. You know wire me the money and I'll let you off or wire me the money after it closes, but wire me the money either way, you know? It's a really perverse incentive. I mean whoever comes into the antitrust division next time and says i think we should clean up the rules and make it much more transparent is probably going to cost the government $20, $30 billion bucks in terms of you know some combination of kickback and tax avoidance. There you go.","offset":2367,"duration":32},{"text":"Harry: I have to say I do like it. Jonathan was in the desert and the dark for many years and he is a founder who's been a real respectfully cockroach who's gone through the hard times, who's gone through the criticism. He's also just a good dude, I like him a lot. And yeah, he's so it's nice to see good people win.","offset":2399,"duration":18},{"text":"Rory: And you're right, just like Chamath, another good guy who's been through the wilderness and has now got his $950 million so they I'm sure that's the point you're trying to make Harry.","offset":2417,"duration":9},{"text":"Harry: Much more, he needs money Rory, okay? He could he could. He now can now buy some some Loro Piana. Rory you brilliantly say it to me, you know that's great but what about me? I I own stock in Amazon and I own stock in Figma, okay?","offset":2426,"duration":17},{"text":"Harry: Google launches Stitch, Figma tumbles. Figma tumbles is an understatement. I saw a tweet where it was actually an announcement that someone posted and Sequoia were buying $35 million bucks of Figma stock and i was like fuck if Sequoia and Andre are buying $35 million bucks, i'll put in some of my money, that's a good sign for me. I'm down 22%, 22%.","offset":2443,"duration":26},{"text":"Rory: Yeah, looks like about... yeah it's $21.66 a share. I remember, look when it was at 108 and you asked me what i thought it'd be i said 35 and i was wrong, i was you laughed at me and i because i was so pessimistic and i was wrong it's 21. Wow.","offset":2469,"duration":16},{"text":"Rory: No it's does this have a floor? Of course it has a floor. I mean stop you know like the again it's it has a floor based on its cash flow which is strong, it has a floor versus its growth rate of that cash flow. The third element is the probability of disruption and you know right it's the tricky thing about the equity business in the short term is everybody gets to speculate on that probability of disruption.","offset":2485,"duration":24},{"text":"Rory: So you take the cash flows and then if you love the story you apply uplift, see Elon for details, you take the cash flow and then if you're really scared about the story you apply terror downlift, which is what's going on here.","offset":2509,"duration":12},{"text":"Rory: Now in the end, you say is there floor, in the end if the business is worth it, it will grow and it will generate the cash and they'll get to do what the Palantir guy does which i so love which is every earnings call he basically slams all the haters and says basically fuck you i'm making money and you all were wrong.","offset":2521,"duration":17},{"text":"Rory: Until you're in the short term, the market gets to bitch and moan and have its opinion, but the floor doesn't come because the market changes its mind, maybe it will maybe it won't but that's not in your control. If you're running Figma, the floor comes if you execute, you demonstrate that you've been able to adopt, you know, to an AI-native AI-first world, you generate the growth, you generate the cash flows and eventually it'll turn. But that's why drawdowns are shitty, that's why drawdowns are hard.","offset":2538,"duration":29},{"text":"Jason: Well you know on this on this on the Stitch Figma thing, i mean i've used Stitch of course as you would imagine. Um i don't i think most folks that that chimed in on this never used it. Um i'm confident 98%.","offset":2567,"duration":14},{"text":"Harry: Just for those that don't know, Stitch is what for those that don't know?","offset":2581,"duration":2},{"text":"Jason: It is a new design tool that Google launched, and the bar at Google to launch a new AI tool is pretty low. They try a lot of stuff and they abandon almost all of it because then they focus on a few core products. So you literally cannot take it seriously when Google launches a product because you have no idea whether they will stick to it. They launched a Suna, is it Suna sorry i keep getting this wrong Harry, the the audio one, what's the one?","offset":2583,"duration":23},{"text":"Harry: Suno.","offset":2606,"duration":1},{"text":"Jason: Suno, so Google launched a Suno competitor. It's like cool, but it's not nearly as good, like it doesn't really work. And and will they keep with it for five years? I'll bet you dollars to donuts they don't because it's not core, okay?","offset":2607,"duration":13},{"text":"Jason: I used Stitch, I've used all of Google's design products, I think the odds that they design decide to build a Figma competitor from this for a decade approach zero. So on the one hand, massive market overreaction to a to a proof of concept, give me an f-ing break if i'm Sequoia or whatever.","offset":2620,"duration":18},{"text":"Jason: On the other hand, the markets are saying we are extremely worried about disruption. We are extremely worried about disruption. You better prove to us, Figma, Atlassian, Salesforce, you are ahead of disruption and not behind it.","offset":2638,"duration":16},{"text":"Jason: And the market said: We don't believe it. And i agree with the markets here because Figma Make is one of the worst products i've used in the last six months. But this but Stitch on its own at least it's better than Make, at least it can take context from a website and and not hallucinate.","offset":2654,"duration":16},{"text":"Jason: But the market should be like where show me the money again, where is Figma's $300 million of revenue from disrupting Replit and Lovable like we talked before? And so if you haven't delivered like Palantir or started to deliver like Salesforce, the markets are going to freaking panic that your revenue is not that durable.","offset":2670,"duration":19},{"text":"Jason: This is what i think it all like i didn't get the 2026 panic for a long time, i was slow. Now i get it, the markets are rationally saying we no longer believe this revenue is particularly durable.","offset":2689,"duration":11},{"text":"Jason: Old old SaaS people, PE doesn't believe it, Qualtrics couldn't finish its debt offering this week, Salesforce barely got its debt done and why? They don't... the markets just... it's not that they think that Figma is a bad company, they just don't believe this revenue's going to last a decade anymore. They don't believe it. And so you're going to see more more of these panics for anyone not accelerating. People... they're just going to panic every time it happens.","offset":2700,"duration":24},{"text":"Harry: Jason, we just released the show with the CRO of Figma and I asked him how he's seeing AI implemented into your sales teams and he said, honestly, we don't really have that ability and we haven't done it yet, um, oh and and we're hiring a lot more in sales, by the way. We're not reducing headcount at all. That... we're not seeing that. Uh, and oh by the way, we're not seeing seat pricing change at all. How do you feel when you hear that? Because...","offset":2724,"duration":29},{"text":"Jason: Oh, you're just... you're just serving it up. That one ironically, Harry, ironically, that one does not worry me as much as the product. Okay. I will tell you what I've learned. You you and I... you formerly on the other 20VC, me in Farmland, I've talked... I know a lot of the CROs and CMOs at leading AI companies.","offset":2753,"duration":20},{"text":"Jason: The ones I'm close to are pretty good, but I also see tons of folks I call recycled mediocre. They are folks that bombed out of old B2B companies, they barely did anything there, but because they have the right logo, got hired to a super... they're all over the hot AI companies. So many recycled mediocre. And they're going to hire 250 reps and not train them. And they're going to build infographics.","offset":2773,"duration":23},{"text":"Jason: But the products are so strong and the demand is so strong, it doesn't eff-ing matter. So if the guy if if if Figma make was so great and and their AI product was doing 500 million, you you could you could sell it with folks fresh out of a non-technical junior college. It'd be fine, right? Um, so my point is, even though I talk a lot about AI go-to-market agents and I believe they're great and they work, they don't fix product-market fit. In AI sales, it doesn't fix product-market fit. And we're seeing broken... we're seeing decaying product-market fit. That's why the market panicked on Figma. They're seeing hints, just hints, of decaying product-market fit in the AI era and you should panic.","offset":2796,"duration":38},{"text":"Rory: Yeah. I... Harry, just to pile in on that because I actually have these conversations at my companies all the time. I actually to... I didn't think I... I totally agree with what Jason said. It's like when my companies come and say, \"Hey, you've got this problem, we want to talk about AI,\" and they say what, you know, \"Hey look at us, we're using AI in go-to-market,\" or they say, \"Look at us, we're using AI to build engineering,\" I'm like that's great but nobody gives a rat's ass. That... that's like jacks to open. That's not solving the core problem.","offset":2834,"duration":26},{"text":"Rory: The core prob-... unless you're making like cars where it doesn't matter, it's just back-office efficiency. If you're a software company, the number one question is how does AI change the end product you deliver your customers? That's what's going to determine success or failure. So I... I thought I'm fun-... I had a guest you would have piled on to that guy and kind of bludgeoned him while he was down because I thought Harry served you up a softball for you to say, \"Hey the idiot is not using AI,\" and I'd have argued with you, but I think you nailed it. Look.","offset":2860,"duration":28},{"text":"Rory: You could be using AI well or badly in go-to-market. You can be using AI well or badly in engineering. It will catch up with you over time if you're not using it well. But that's not what's driving, you know, 30, 40 percent price declines. What's driving that is exactly what Jason said is the market looks at this and says there's disruption risk here. I don't know the terminal value here. I... I'm just nervous. So I've got to be paid for that risk.","offset":2888,"duration":30},{"text":"Harry: I got... he didn't take my softball, did he, Rory? That was... normally he's so disciplined. He took it...","offset":2918,"duration":3},{"text":"Jason: But Rory's got the important point. You you've got to have the right AI or your company's going to decline. Listen, would I would listen... I'm sure the Figma guy's great, but honestly, if I interviewed a CRO today and didn't have any AI agents that he here or she had brought in to our last podcast, I would recommend to the CEO \"don't hire her or him,\" okay, for sure. But would I think this was... would I be much more worried than if I talked to a CTO and the the new CTO they wanted to hire didn't really believe in in using agentic coding, then then I would ask for my money back. Can I have all of my investment back and 1x? You can keep your mark-up, just give me my 5 million back.","offset":2921,"duration":38},{"text":"Jason: I'm going to go one level more than that, is that you're right. Not using AI in go-to-market, bad. Not using AI to build product, maybe I want my money back. But if you're a software product and you don't think AI is going to disrupt not just how you build but what you build, then you actually probably want to actively short it. Like for example, they're not doing that, but if Figma or Salesforce or someone were to say, \"I don't think AI is relative is relevant for our customer base and they don't want to use AI in design,\" if someone was to say that today, you'd be like, \"Oh my god, you're just going to be, you know, just left behind.\"","offset":2959,"duration":26},{"text":"Jason: Now... and that's why Figma's insensitivity to how mediocre Make is really worries me. I wouldn't care if if Dylan or the team said, \"Listen, Make isn't good enough but wait give me time. Give me six months, it's going to be great.\" But saying this product that is the worst vibe coding tool I have used... that I have used in the last six months, the fact that there is no public awareness that this is an issue really worries me.","offset":2985,"duration":27},{"text":"Harry: Jason, can you help me understand that? Because Dylan is a is a good CEO. I don't... you know...","offset":3012,"duration":4},{"text":"Jason: Excellent CEO. I think we all have listen... I don't know for sure, okay, um, but I think everyone at scale has a trap, which is their installed base is a trap. It is an opportunity and a trap. It is the greatest thing in the world to sell your agentic product to, to sell Agentforce to, is the 44 billion of ARR that Sell-... it's the greatest opportunity because you don't have to earn that base, right? But it is also 50 years of debt, 50 years of features, 50 years of of offline integrations, non-agentic gaps they want, 50 years of of endless work. And if you're not careful, it will consume 98 percent of your resources is that installed base, right? They need so much attention.","offset":3016,"duration":35},{"text":"Jason: And I do think literally Make is the only vibe coding product that I have used where you say, build me a website for 20VC, use 20vc.com as a template, and it can't go to 20vc.com and pull the context to make the website. Now Replit could do this in June of 2025, Lovable could, but anybody can do it today, right? Uh, so including you know who could do it pretty good was um Stitch. Stitch got the context right of the design projects I get it. And that just shows to me whoever's running it doesn't care about these use cases. They just don't care. It has fallen behind and I real-... my guess is, my guess is there's a small team on this.","offset":3051,"duration":43},{"text":"Jason: You know, they're still growing what, 35 percent? Right? I mean this is this is one of the best out there. But the dema-... here's the trap and we all have portfolio companies like this. The trap of of earning that 35 percent imperil can imperil your agentic growth. It can consume more than 100 percent of all the product and engineering and CS resources you have, right? Even Mike Cannon-Brookes when he was on the show, he alluded to it right and then they did the layoffs. He's like, \"I've got to get these resources because otherwise Jira and Confluence and everyone's going to suck it all up and I have no people.\"","offset":3094,"duration":31},{"text":"Rory: Super interesting.","offset":3125,"duration":2},{"text":"Jason: It's a trap, it's a trap, and think of some of your portfolio companies at scale. North of 100 million, they don't describe it this way, but you know it's a trap, especially when they have a mediocre like VP present at the at the board meeting and the mediocre VP is like, \"I just I want to do it but I don't have the people, I need another 700 people to build that.\" And you're like, \"Ugh, it's a trap.\"","offset":3127,"duration":19},{"text":"Rory: It is so hard to say I'll allocate to the new thing first and allocate the residual to the old thing. And you're right, the instinctive is to say I'll deal with the old thing and then I'll find some people for the new. You're right, it's a mindset. It's an interesting point.","offset":3146,"duration":12},{"text":"Jason: Harry, just to pile in on that, because I actually have this conversation. And you know, I don't want to overstate the Intercom example, um, just because you know it's enough already, okay? But but if you want to use it as a case study, it does illustrate what you have to do here. And and Eoghan was clear, we let our core business go into partial decline. It's very hard for al- almost impossible for a public company though. It's lucky being private because you you've got to have a lot of guts to say we're going to let a 1.something billion dollar design business decline a little bit so we can build our agentic product. It's tough when you're public, right? Um, but it's what you've got to do.","offset":3158,"duration":33},{"text":"Harry: Figma's at 21 today, 12 billion market cap. Would you buy it today?","offset":3191,"duration":7},{"text":"Jason: No. I don't see any evidence of turn- of of of these agentic investments working. I would rather miss miss out on the the bounce, right, off the hard deck, than than invest in something that may fall below it. The reason is there's too much change. My god, there's so much change. It's so fast. Make would have been a great product in August of 2025. It's just not today.","offset":3198,"duration":23},{"text":"Rory: The problem with the bounce, and it's a first world problem, is say you buy at 21, the concerns are overdone, you're back up to 24, 25, 26. So you've made some decent money but you sell it, you get ordinary income, blah blah blah. You actually, net of taxes risk adjusted, is it worth it, right? The only way you buy is, and I'm not saying I have the answer to this, when you buy stocks because you want to hold them for five or ten years, you just do better, especially tax adjusted, than when you buy things because you think there's a short-term bounce, right? I personally think that almost all of this stuff is overdone, right, and there probably will be 5, 10, 20 percent bounces across a number of these companies, but to want to buy it I'd have... I haven't done the work that Jason's done. But he is right, you only should buy things if you think five years from now they'll be a winner in the future. I think it's totally plausible Figma could be, but Jason's right, until you've used the product, until you've seen what they do, I I wouldn't make that decision especially at scale.","offset":3221,"duration":58},{"text":"Jason: Well here's the tough thing is Figma's clear, you just had them on. Harry, are they materially charging for their agentic product? So are they monetizing it?","offset":3279,"duration":8},{"text":"Harry: I have no idea.","offset":3287,"duration":1},{"text":"Jason: No, they're not even really charging. Why do you why look at your portfolio companies. Why the hell would you not charge for your AI product today? Agent- why the hell when when Anthropic's doing 22 billion in the blink of an eye, when people are lining up out the door to buy agentic legal products and healthcare products and OpenEvidence, why would you charge almost nothing for your AI product? Why?","offset":3288,"duration":21},{"text":"Jason: It's not good enough. Literally, I was with a founder this last week who was us- who used Make and got very far with it. If nothing else existed, it would be amazing. If Make if if Make was if this was 14 months ago and they built their own LLM and they could do this on their own, our jaws would drop, right? But it's not. It's not good enough to charge for. If it's not good enough to charge for, it doesn't count. You're not an AI company if you can't charge for it. Very few public companies can effectively monetize AI. And that's why they're all in terminal decline. Almost all of them at the moment are in terminal decline. Will they pull off pull it back? I I'm not going to buy their stocks until they do. I don't see any point.","offset":3309,"duration":42},{"text":"Rory: For the record, that's an excellent test.","offset":3351,"duration":3},{"text":"Jason: Yeah, you can't... they even Figma can't charge for it. It's a bad sign, it's a very very bad sign going into the middle of 2026. It's a terrible sign. Terrible sign.","offset":3354,"duration":11},{"text":"Harry: I'm I'm naive here so forgive me for this. Are Notion charging for it? You've spoken before about Notion's brilliance in the integration of that AI capabilities. Are Notion charging additional for that AI capability or is it just a superior product?","offset":3365,"duration":13},{"text":"Jason: Well first off, if I said I thought it was truly brilliant, like I misspoke. I barely we I use Notion all the time. I think the they're good. I don't think it changes the the game in way other products do. But the simple answer to your question is they have been able, look they're not public, right, but if you combine what they've said with their pricing page and their announcements of acceleration and the fact that they have effectively doubled ARPU from it. Doubling ARPU for for-... here's a way to look at an SMB product today. Is your ARPU 50 percent or higher than it was pre-AI? It's a really simple test. Can you drive ARPU up 50 percent or more? It's very different at Salesforce or ServiceNow. It appears that Notion has done that, in which case they they pass the test, right? But I want to see 50 percent or more ARPU growth due to AI or it's just a feature. It's it's just a feature like an integration. Great, hard work, good job guys, let's have beers but it doesn't count.","offset":3378,"duration":57},{"text":"Rory: Yeah. I mean re-acceleration is the aggregate test, to your point two weeks ago, Jason, right? Something's got to be going b- I mean that's been sticking with me too. Something's got to be going better across the marketing KPIs. It can be charging for your AI product. It can be re-acceleration. It can be ACV but something has got to be working and getting traction, otherwise you are falling behind because the AI-first players are delivering utility to their customers and that's manifesting in them those customers giving them money. So if you if you can't make the same phenomenon happen one way or the other, you're falling behind.","offset":3435,"duration":33},{"text":"Jason: Well obviously the market rejected Microsoft Copilot products as things they didn't want to pay more for, right? That's the example of of stumbling. Notion is Notion with AI is 20 bucks a month, the basic is 10. If if everything ties, and private companies have an incentive to be honest but but polish the numbers a little bit, right, to...","offset":3468,"duration":19},{"text":"Rory: See our prior conversation.","offset":3487,"duration":2},{"text":"Jason: Yeah, but assuming there's at least a substantial amount of truth in what they've said, then it then it's working, right? They are able to charge 20 dollars a month for their agentic product, not because they they splashed an AI label on it, but because it's so much better that it is worth it to talk to your docs, to have to have stuff flow into your database autonomously. It's worth 20 bucks. Um, and I suspect we're going to find this I don't love the pricing. I suspect as the year goes on we're going to see the same thing at Slack because most folks haven't used it, we're on it. The AI version of Slack for certain use cases is so much better. I don't love that they're not just charging another four bucks a month, but we I wouldn't be surprised if it's a dramat- if it's like Notion, like they're able to to do it, right?","offset":3489,"duration":42},{"text":"Harry: Speaking of Figma, I I'm going to go a little bit off piste but I think it's worthy. Jason, we were on Twitter about it earlier joking. Um, Mamoon announced raising the new KP funds. A billion dollars for the early, two and a half billion for the growth. Um, growth seems small. I mentioned meeting him for the first time at SaaStr, Jason, if you'll believe 10, 10, 11 years ago, in a side room. Kind enough to give me time. My my takeaway is honestly you can't do early and you're going to kill me, Rory, with less than a billion if you're going to compete to lead As. And my reasoning for that is As now a 30 to 40 million and if you want to lead them you need to be able to write 25 to 30 million dollar checks. I think you need 20 across a firm, so if you need 20, 30 million dollar checks you're at 600 million. I would argue that your fund scale is as small as it could be to lead As today.","offset":3531,"duration":61},{"text":"Rory: I don't entirely disagree in the sense that, you know, it's a 900 million dollar fund and you're exactly right. I mean the math of what you threw out is correct. Series As ten to you you're writing an an average of a 20 million dollar check. Our reserves have...","offset":3592,"duration":15},{"text":"Harry: But I don't even think 20 is enough these days.","offset":3607,"duration":2},{"text":"Rory: I know, I know. Let me just let me just take an average, right, because you know if you if you hustle, if you find some deals where it's a little off the beaten track, I've written... I've written As where we've gotten 20 percent ownership for 12 or 15, right? So it's not all but but let's just go at your average, Harry, because rather than arguing the right? You know, it's 50 percent reserves. We you know over like six or seven funds we've been 50 percent reserves. So you end up with 30 million dollars in the average deal. You know, then the last component is a portfolio concentration versus diversification question. I I think given the higher time to exits you probably tend to be nearer to 30 than 20. So yes, I I think, you know, there's a there's a certain small-s scale required to play meaningfully in the Series A business. Yes.","offset":3609,"duration":42},{"text":"Harry: Rory, can I ask you, you've got 720 of investible, you can't have a reserves of 50-50 and be right?","offset":3651,"duration":6},{"text":"Rory: 720? No, I didn't say 50-50, you didn't pay attention, Harry. 50 percent of it... because there's two ways of expressing reserves. It's just simple math, let me help you. Um, one way is expressing it as a percentage of original capital and in other words if I put in 20 do I reserve 10? That's 50 percent of initial capital. And and mathematically that's the same as saying two thirds of the money goes in on the first check and one third goes in in the later check. You're right, I'm not reserving 50 percent of the total amount. Do you understand me? Those are literally just...","offset":3657,"duration":29},{"text":"Harry: I I now I do with that clarification. Thank thank you for clarifying.","offset":3686,"duration":4},{"text":"Rory: I did I used the prepositions correctly the first time as well. But okay, it's good to be clarified. But to be fair to you people do express it both ways and sometimes precision is important. I always think of it as the amount of money you've put in and then the amount of money you have in your back pocket to defend that money if you need to or expand on that position if you want to. So I always think first check.","offset":3690,"duration":18},{"text":"Rory: And what it says is, and this is another insight, unlike for seed where you also have a big fund, for that kind of Series A game, the Series A is not for us, especially for a firm that just has, you know, checks for As and Bs and of this size, it's not an option value on putting a ton of money in later. Most of your value is made on that first check, right? Whereas these folks who have seed or even A funds where their real plan is to put 200 million in at the B or C when it's working, right? To some extent the A is an option value, but just as Jason's for Jason the seed check is the check. For us the A or B, because we're roughly about half and half, is the check. You're not saying oh I'll put in a little now and write more later. That's that's not the way the game can be played.","offset":3708,"duration":46},{"text":"Harry: Rory, are you finding it increasingly uncomfortable with the expansion of Series A rounds because our checks are getting stretched bigger and bigger and it's ruining our math?","offset":3754,"duration":10},{"text":"Rory: I mean it is somewhat uncomfortable but I think you have to find the deals where that's not the case or decide in some cases to reach. I mean and that's I'm going to put both s- both sides of the challenge out there. You know, there may be some deals that are too capital intensive and you decide I don't want to do that because I'm just not getting paid for that risk. But you're right, the average I looked at this math just last week, the average round that we play in has crept up. Right, not just the amount we do but the average round that we play in has crept up over the last year, year and a half. Right, so yes, it's not I would say to the acute level of oh my god, you know, we're perfectly happy with the checks we're writing and the round sizes, but yes, there are times, especially for example, you know, we haven't done any at scale of the kind of the Neo Labs seed checks where you just so outclassed with your 30 or 40 million dollar check, it's barely worth playing.","offset":3764,"duration":53},{"text":"Jason: How big's the Hummingbird fund they just announced?","offset":3817,"duration":3},{"text":"Rory: It's 800.","offset":3820,"duration":1},{"text":"Jason: 800. What was their what what where have they grown their fund size from over time, from doing inception investing?","offset":3821,"duration":6},{"text":"Rory: It's it's 2, 300 of I think initial capital. It's the same fund they always had but adding a growth fund to a rounding error. Right.","offset":3827,"duration":9},{"text":"Jason: Yeah. And then didn't Balderton lead the seed in Revolut?","offset":3836,"duration":3},{"text":"Rory: Yes.","offset":3839,"duration":1},{"text":"Jason: And then who did they just do a billion this week? It's just the the game is it has changed. We were really good at doing Revolut at four, now now billion dollar rounds are a good entry point for us. It's just a lot of change, isn't it?","offset":3840,"duration":15},{"text":"Rory: Yes. There's no anyone look we track it on aggregate, right, versus our 2010 checks you're probably up roughly 2x in terms of the valuation and I think that's significantly lower than the industry as a whole.","offset":3855,"duration":16},{"text":"Jason: Whose point's hard to argue with, which is if you want to own 15 percent of a company or whatever your target number is and deal sizes have inflated, that there's a basic math you have to do, right, with reserves. And that math is in many cases highly stressed in the market today. It's just a f- like it's a fact like, you know, you used to sol- it was very easy to solve your fund size before, right? It was 60 million per partner for seed, maybe 100 for A or B and then it would go up a bit. The math was so simple, all these funds were but that math just is is broken today and it creates interesting I don't find it super interesting but it it is a little bit broken, right? And so if you're Garry Tan you say the 100 billion dollar outcomes make it irrelevant, right?","offset":3871,"duration":38},{"text":"Jason: And I don't know how they work but I was just looking and I was writing an ans- I was writing something up on Wiz and Cyberstarts owned 4 percent at exit, okay? So that that I don't know whether that's dilution or as model back then, but the model still works for a seed fund at 4 percent of 30-some-odd billion, right? Um, but that I think we're going to see more and more of those, right? Dilution in time we'll see more and more seed investments eroded to 3, 4 percent, right? And if they I'm just doing one example, they'll be eroded and and if the exits are uh, you know, north of 10 billion it's okay for a seed fund, right? But the it it's tough.","offset":3909,"duration":47},{"text":"Jason: I don't have the answers. I just think the the old math was easy, right? We need to do 15 to 20 investments per fund, 15 million the average check size and you could roll up into fund sizes that that didn't make you fall out of your chair.","offset":3956,"duration":15},{"text":"Rory: At the risk of being a dick, the math is easy both times because math is independent, you just don't like the answer, right? Multiplying multiplying a pre-money of 50 is no harder than multiplying a pre-money of a billion.","offset":3971,"duration":9},{"text":"Jason: I think the math inherently creates more risk unless the outcomes are massively high.","offset":3980,"duration":4},{"text":"Rory: That's the point.","offset":3984,"duration":1},{"text":"Jason: We are levering up our risk to Harry's point. We're levering up our risk.","offset":3985,"duration":3},{"text":"Rory: I totally agree. I was just being a mild little jerk because I'm think I'm getting grumpy. Exac- it's not that the math is complex, it's just that the consequences are unpleasant and it's what you say. Everyone look we said it over and over again. Everyone's been pushed out on the risk continuum. The whole.","offset":3988,"duration":17},{"text":"Harry: But it does feel like times are changing faster than fund sizes are able to adapt in a way that they haven't done in previous cycles. Like our normalization of billion dollar plus rounds, 100 billion dollar plus raises.","offset":4005,"duration":15},{"text":"Rory: I think that's well put.","offset":4020,"duration":1},{"text":"Harry: So much quicker than fund sizes.","offset":4021,"duration":2},{"text":"Rory: I think that's actually true. The pa- that's actually a good reflection. The pace of change because I've lived through 95 to 99, the run up and the billion dollar funds and I also lived through unwinding watching all those funds being unwound in '02. I remember and then, you know, obviously 2007 that unwinding. This and even 2021, this feels faster than that, right? The action on the table and the need to play at a high. Yes. I think which is why I think every VC is stressed right now. No matter how successful you are, no matter how well your last deal a deal that you did three years ago is doing, everyone wrestling with doing deals now is grumpy, stressed and feeling feeling the pressure.","offset":4023,"duration":35},{"text":"Jason: But I think there's one risk that is under-discussed, okay? All this fund math can lead to concentration risk or ownership risk. Like at least for a smaller fund, I I have to deal with concentration risk or ownership risk. That's the that's the simple trade-off, you can't own that's my math, right?","offset":4058,"duration":14},{"text":"Rory: Agreed.","offset":4072,"duration":1},{"text":"Jason: The one that we are just ignoring because times are so good on paper is who the hell's going to buy these companies if they don't IPO? What the hell are Replit, LangChain, Harvey, Lovable... what how much is Lovable worth in the last round? 8 billion?","offset":4073,"duration":14},{"text":"Harry: 6.5.","offset":4087,"duration":1},{"text":"Jason: Okay, let's be honest, who the hell is going to buy them if they don't IPO? You really think Google's going to buy them for 32 billion? It could don't get me wrong. It could happen. And the and acquisitions are not up, right? Uh, dollars are up. So I just my point that is under-discussed is we are doing these these post-billion dollar deals like like candy. And at least in the in the bubble of '21 there were PE exits, there were many exits out there. We have outstripped any current ability for these companies to have any exit. So you are going all in on the IPO and not without any worry, rhyme or reason and I think so many folks sub-Anthropic are going to get their arses burned because they'll end up in the dead zone. They'll have great companies without great IPOs and zero M&A opportunities. And I'm not saying don't do it, I want my mark-ups on paper, I've got to do it an LP announcement this week. I want my my TVPI and my IRR to look good. But it's also terrible. It's terrible to raise north of a billion. It's terrible because you just out- str- there's just those they're not, you know, Salesforce and and Amaz- I mean Groq is great but a lot of the stuff is not Groq.","offset":4088,"duration":74},{"text":"Rory: Agree with everything you're saying and what's hard about what you're saying is that the strategy that has worked has been precisely the strategy of doing those rounds above a billion and getting the round beyond it. And but you're right, it's all predicated on being able to exit these companies in an IPO. And I will say just to remind you you can imagine a world of IPOs where some of these companies exit. But if the last rounds don't have a block, it's not necessarily going to be above the last rounds. There are some awesome AI applications companies where you kind of go I totally see how that's worth 5 billion dollars in three years based on fundamentals and right now it's valued at 10. And three years from now I could contemplate it going public at 5 billion dollars and you kind of go that last round the 10 is going to have to convert and take 50 cents on the dollars unless it has a meaningful block, in which case they will get more of the company.","offset":4162,"duration":49},{"text":"Jason: Yeah, for sure. I just worry there's some ratio, Rory you can name it, but there's some ratio of potential acquirers real divided by unicorns. And I think we're at the lowest ratio of our careers.","offset":4211,"duration":12},{"text":"Rory: Yeah no absolutely.","offset":4223,"duration":1},{"text":"Jason: The lowest ratio of potential acquirers divided by unicorn unicorn plus up to decacorn that are just not there. We've lost all of PE and Nvidia isn't buying 100 companies, Microsoft is not buying 100 companies.","offset":4224,"duration":13},{"text":"Harry: So what is the subsequent thought then, Jason? Sell aggressively into secondary markets which are more liquid than ever? Like help me understand...","offset":4237,"duration":7},{"text":"Jason: Well probably for early stage investors sure, sell while the that's the Hoppin lesson. I know you love to talk about it, Harry. Maybe that's the lesson. Um...","offset":4244,"duration":7},{"text":"Harry: I don't think it is. Can I just push? I don't actually I'm going to I don't want to use the Hoppin example because then people will because I actually think it I'm going to make it a more interesting discussion. Because when you do Hoppin, people go, \"Well my company's not Hoppin,\" um no pun intended. I think you're saying even for your fucking great company, excuse my language, great company where you know in the end they're not going to be Hoppin, they're not going to a, you know, vanish in a puff of blue smoke, you're still right, which is those last rounds might be a prices you'll never see again. And what should you do as a seed investor? I mean what would you do if a company where you invested at 50, you thought it was worth it could be an M&A at 2 billion at some point in time and suddenly you get a round at 5 billion of new money and there's a secondary opportunity. You're starter for 10, what do you advise?","offset":4251,"duration":45},{"text":"Jason: Yeah. And and listen maybe down maybe just as we're now okay with down IPOs like we're okay with it's just mathematically true, maybe we'll all be chill with down M&As and all these folks raising at 9 and 10 can sell for 1 or 2 in a few years and everyone will be happy. I'm just not so sure that they will and I'm but I'm more worried there's just not going to be a lot a lot of acquisitions. They're very specific. They're very specific to either we're desperately behind on AI or we need to jump forward years. That is a very narrow subset versus uh making sure accounting software at 5 billion is better for accountants. I believe that's a great market, I just don't believe the hyperscalers are going to buy these companies.","offset":4296,"duration":40},{"text":"Rory: No. And the yes because by definition at the app layer, you're not getting the hyperscalers. And the odd thing is, I just realized this for the first time, the odd thing is because of this story of eat the work, the TAM is meant to be larger. That's the whole point of these application-less and I believe it. But Jason to your point what it means is you are definitionally therefore the new company is larger in terms of value than the old company you're replacing, which means the old company can't afford to buy you, right? No chance. If you're Harvey and you're worth 10 billion and West it's not really worth more but if you know the old practice management law software is only worth 2 billion, they're not going to buy you, right? You've got it's basically it's win or die, to your point. I think you're exactly right, Jason, because because these TAMs are bigger in when the TAM becomes bigger the new company has gets marked up and has more has potential to be a bigger outcome. But what it means is once it gets marked to that bigger outcome via late-stage round, it precludes the prior generation buying in. If I was running one of those prior generation companies, right, as if I was the system of record, you what you need to be doing is buying the not marked up, you know, 500 million valuation company and getting something out there. Right but you can't aff-... no matter how hard you try as the old generation legal software company you can't afford Harvey at 10 billion. So doesn't matter what you want they can't you can't afford to buy them and they can't afford to sell to you. I think you're exactly right, Jason. It's kind of structural.","offset":4336,"duration":90},{"text":"Jason: I just wish listen even if IPO markets are barely barely functioning, they're open, but they're barely functioning. If the M&A markets were on fire I'd be good with everything. If we were turning around and these companies were being bought for 10 billion cash each week, I'd be like this is this is awesome man. Um but it it does worry me a little bit that it's so easy to get a 9 billion dollar valuation. It's so much easier to get a 9 billion dollar valuation than a billion dollar exit.","offset":4426,"duration":25},{"text":"Rory: Which should be terrifying if you're the people giving the 9 billion dollar valuation.","offset":4451,"duration":6},{"text":"Jason: I mean you got to play the game on the field but...","offset":4457,"duration":3},{"text":"Rory: Well you actually for the record sometimes you can stick your money in your pocket and not play the game on the field, but that's okay.","offset":4460,"duration":6},{"text":"Harry: But you're playing the game on the field, Rory.","offset":4466,"duration":2},{"text":"Rory: Part of it. And the bits I haven't played have been we you know we haven't done a deals at a billion dollars above. We've you know kept it in that 100 to 3, 400 million dollar pre-money valuation and right now that's been the wrong play. Just to put it out there, right? I mean look I give all credit to for example Spark, the Jasmine there at Spark who broke all the rules and said 4 billion for a pre-revenue company Anthropic. That's paid off, right? I think it'll be interesting for Matt Murphy at Menlo.","offset":4468,"duration":29},{"text":"Harry: Matt Matt has a concept.","offset":4497,"duration":1},{"text":"Rory: Absolutely Matt did it too totally yeah. So my point is some of the late stage bets have paid off. On average I think it's a tough I share the concern. So to your question on playing the game in field, we're playing part of the game on the field but we're a bit scared of certain parts of the valuation curve. I think that will probably across the cycle be the right decision. I'm not sure in the last year or two it's been the right decision, which is always a challenging thing about valuation.","offset":4498,"duration":25},{"text":"Harry: I shouldn't be so honest but I fuck it we'll be it's the end of the day here. My biggest regret with our Series A fund is not being more elastic, disregarding the Series A mandate and just saying I'm going to leverage the brand and the access that I have arrogantly forgive me for that to get into super hot companies like your ElevenLabs, your LangChains, your you name it see Lovables much earlier and being a momentum investor in a hot environment.","offset":4523,"duration":25},{"text":"Rory: I'm going to paraphrase what you said is I have the right to I'm my current plan is to write 20 million dollar checks in Series A investments where I get 10 or 15 10 to 20 percent ownership, right, and I can write 20 of those checks. In retrospect you're saying I should have taken five of those checks, the full 20, not a bitty check but a full ticket, a full ticket or maybe even double down and used a two-ticketer and done Cs, Ds and Es at 1 billion, 2 billion pre and got two mark-ups already, right?","offset":4548,"duration":30},{"text":"Rory: And the interesting question is if your mandate because I wrestle with this a lot so I know it's an interesting question is if your mandate is to do 20 Series As where you get 10 percent to 20 percent ownership and you stick to your knitting and you do your do, right, should you have taken five of those slots and used same check size or maybe even larger check size and done Cs, Ds and Es at 1 billion, 2 billion pre and got two mark-ups already, right? And the truth is in some cases not only will you get mark-ups but you'll get returns commensurate with Series A but at much lower risk. And Anthropic will be the definitive version of that forever. Not actually the round Spark and Menlo did first because that really was risky but kind of the rounds at 14 and 16 billion were risk-adjusted freaking awesome. I wonder will to your point now back to your point I wonder will all of those rounds in those other AI apps companies be as good for precisely the reason you articulated which is that maybe the TAM doesn't support that exit. But right now Harry's right you do you look at the la- yeah Lovable at 6, maybe you could have done it at 1 or 2, you'd have a 3x step up with no hassle, no fear, no early stage. The sweet spot of investing, I mean it's something you said Harry and it was true but tautological, I wish I'd been a mom-... I you said I wish I'd been a momentum player in a rising market. The definition of a momentum strategy is it only works in a rising market, right? But yes, in the market we've been in for the last three years, it's hard to distinguish momentum players from very shrewd players. Both of them have worked out really well. That's the that's the kind of step back from it.","offset":4578,"duration":98},{"text":"Harry: I don't think shrewd players have, actually. That's that's my point. I think shrewd players have appeared disciplined, remained temporally diverse like me and you are, Rory, remained with our high ownership targets and you've had players abscond with AUMs like never before, pay insane prices and get fast mark-ups and in a lot of cases DPI because Zuck buys you at an insane price.","offset":4676,"duration":25},{"text":"Rory: Brutal comment, Harry, then maybe you and I aren't shrewd. Look in the mirror. I you know right?","offset":4701,"duration":5},{"text":"Harry: Very possibly and that's the self-reflective question as I introspect which Mark Andreessen doesn't do clearly.","offset":4706,"duration":8},{"text":"Jason: No, introspection here please.","offset":4714,"duration":2},{"text":"Rory: No. Look look the truth is that is the question everyone wrestles with as you when do you stick with your strategy and when do you break it and what are the and you know what's a good reason to break it. Absolutely, no we all agonize with. And that's why Jason I said the kind of trivial breaking it just to be silly doesn't isn't that interesting, but the sometimes breaking it could be the right strategy and that's the hard one.","offset":4716,"duration":23},{"text":"Harry: There we go. Okay, boys it has been a pleasure. Thank you so much as always.","offset":4739,"duration":5},{"text":"Rory: Jesus that was quick. We ran out of time.","offset":4744,"duration":15}],"logs":[{"elapsed":"0.0","message":"Downloading audio from YouTube...","detail":null},{"elapsed":"0.0","message":"Trying download with browser cookies (ad-free)...","detail":null},{"elapsed":"2.9","message":"⚠ Cookie download failed: WARNING: [youtube] [jsc] Error solving n challenge request using \"deno\" provider: Error running deno process (returncode: 1): \u001b[0m\u001b[1m\u001b[31merror\u001b[0m: Uncaught (in promise) TypeError: Cannot read prope","detail":null},{"elapsed":"2.9","message":"Retrying without cookies...","detail":null},{"elapsed":"41.3","message":"⚠ Downloaded without cookies — audio may contain ads","detail":null},{"elapsed":"41.3","message":"Audio downloaded (48.0 MB) in 41.3s","detail":"File size: 48.0 MB"},{"elapsed":"41.3","message":"Video title: Why You Need a $1B Fund To Do Series A | SpaceX at $2TRN & Data Centers in Space | Groq's $20BN Deal","detail":null},{"elapsed":"41.3","message":"Audio duration: 1:19:18 (79.3 min)","detail":null},{"elapsed":"41.3","message":"Large audio (79.3 min) — will use chunked transcription with gemini-3-flash-preview","detail":null},{"elapsed":"41.3","message":"Skipping full-file attempt — using chunked transcription for 79.3 min audio","detail":null},{"elapsed":"41.9","message":"Split audio into 2 chunks for transcription","detail":null},{"elapsed":"41.9","message":"Transcribing chunk 1/2 (starts at 0:00)...","detail":null},{"elapsed":"41.9","message":"Uploading audio to Gemini File API...","detail":null},{"elapsed":"46.2","message":"Audio uploaded in 4.3s","detail":"File ref: files/pmmnnz1hze62"},{"elapsed":"46.2","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"115.6","message":"Chunk 1: 143 segments, last timestamp 44:49","detail":null},{"elapsed":"115.6","message":"Transcribing chunk 2/2 (starts at 45:00)...","detail":null},{"elapsed":"115.6","message":"Uploading audio (offset 45:00) to Gemini File API...","detail":null},{"elapsed":"118.9","message":"Audio uploaded in 3.2s","detail":"File ref: files/6oddh9e5ay2e"},{"elapsed":"118.9","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"176.1","message":"Adjusted chunk 2 timestamps by +45:00","detail":null},{"elapsed":"176.1","message":"Chunk 2: 98 segments, last timestamp 1:19:04","detail":null},{"elapsed":"176.1","message":"Chunked transcription complete: 241 total segments","detail":null},{"elapsed":"176.1","message":"Total cost: 119,448 in / 23,256 out — cost: $0.1295","detail":null},{"elapsed":"176.1","message":"Total transcription time: 134.7s — 241 segments","detail":null},{"elapsed":"176.1","message":"Analyzing topics across 241 segments with gemini-3.1-pro-preview...","detail":null},{"elapsed":"225.2","message":"Topic analysis complete in 49.2s — found 9 topics","detail":null},{"elapsed":"225.2","message":"Analysis tokens: 24,676 in / 844 out / 4,927 thinking — cost: $0.1186","detail":null},{"elapsed":"225.2","message":"Pipeline finished in 225.2s — total cost: $0.2481 (173,151 tokens)","detail":null}]} \ No newline at end of file diff --git a/history/1775672308695-kwSVtQ7dziU.json b/history/1775672308695-kwSVtQ7dziU.json new file mode 100644 index 0000000..08870c3 --- /dev/null +++ b/history/1775672308695-kwSVtQ7dziU.json @@ -0,0 +1 @@ +{"id":"1775672308695-kwSVtQ7dziU","videoId":"kwSVtQ7dziU","url":"https://youtu.be/kwSVtQ7dziU?si=GEPNaFHphC6LZrwm","title":"Skill Issue: Andrej Karpathy on Code Agents, AutoResearch, and the Loopy Era of AI","type":"youtube","topicCount":16,"segmentCount":429,"createdAt":"2026-04-08T18:18:28.695Z","uploadDate":"20260320","chunks":[{"title":"Introduction and the Shift to AI Agents","summary":"Andrej Karpathy is introduced and discusses how the default workflow of coding has shifted. He describes the process as manifesting intent to AI agents for 16 hours a day.","entries":[{"text":"Andrej Karpathy: Code's not even the right verb anymore, right? But I have to, um, express my will to my agents for 16 hours a day. Manifest.","offset":0,"duration":10},{"text":"Andrej Karpathy: How can I have not just a single session of, you know, Claude code or Codex or some of these agent harnesses, how can I have more of them? How can I do that appropriately?","offset":10,"duration":4},{"text":"Andrej Karpathy: The agent part is now taken for granted. Now the claw-like entities are taken for granted, and now you can have multiple of them, and now you can have instructions to them, and now you can have optimization over the instructions.","offset":14,"duration":9},{"text":"Andrej Karpathy: But there—I mean, this is what gets to the psychosis, is that this is like infinite, and everything is skill issue.","offset":23,"duration":7},{"text":"Host: Hi listeners, welcome back to No Priors. Today I'm here with Andrej Karpathy, and we have a wide-ranging conversation for you about code agents, the future of engineering, and AI research.","offset":30,"duration":11},{"text":"Host: How more people can contribute to research, what's happening in robotics, his prediction for how agents can reach out into the real world, and education in this next age. Welcome, Andrej.","offset":41,"duration":13},{"text":"Host: Andrej, thanks for doing this.","offset":54,"duration":1},{"text":"Andrej Karpathy: Yeah, thank you for having me.","offset":55,"duration":2},{"text":"Host: Uh, so it's been a very exciting couple of months in AI.","offset":57,"duration":2},{"text":"Andrej Karpathy: Oh yeah, you could say that.","offset":59,"duration":2},{"text":"Host: I remember, um, walking into the office at some point and you were like, really locked in, and I was asking what you were up to and you're like, \"I just—I have to code for 16 hours a day,\" or code's not even the right verb anymore, right?","offset":61,"duration":12},{"text":"Host: But I have to, um, express my will to my agents for 16 hours a day. Manifest. Um, because like there's been a jump in capability. Uh, what's happening? Tell me about your experience.","offset":73,"duration":12}],"startTime":0},{"title":"AI Psychosis and Delegating Code to Agents","summary":"Andrej describes his state of \"AI psychosis,\" where software engineering is now bottlenecked by a human's ability to parallelize and instruct agents rather than typing code manually.","entries":[{"text":"Andrej Karpathy: Yeah, I kind of feel like I was just in this perpetual—I still am often—in this state of AI psychosis just like all the time, uh, because there was a huge unlock in what you can achieve as a person, as an individual, right?","offset":85,"duration":14},{"text":"Andrej Karpathy: Because you were bottlenecked by, you know, your typing speed and so on. But now with these agents, it really—I would say in December is when it really just—something flipped, where I kind of went from 80/20 of like, you know, uh, to like 20/80 of writing code by myself versus just delegating to agents.","offset":99,"duration":15},{"text":"Andrej Karpathy: And I don't even think it's 20/80 by now, I think it's a lot more than that. I don't think I've typed like a line of code probably since December basically. Uh, which is like an extremely large, uh, change.","offset":114,"duration":14},{"text":"Andrej Karpathy: Um, I was talking to it like for example, I was talking about it to for example my parents and so on, and I don't think like a normal person actually realizes that this happened or how dramatic it was.","offset":128,"duration":10},{"text":"Andrej Karpathy: Like literally like if you just find a random software engineer or something like that at their—at their desk and what they're doing, like their default workflow of, you know, building software is completely different as of basically December.","offset":138,"duration":14},{"text":"Andrej Karpathy: Uh, so I'm just like in this state of psychosis of trying to figure out like what's possible, uh, trying to push it to the limit. How is—how can I have not just a single session of, you know, um, Claude code or Codex or some of these agent harnesses?","offset":152,"duration":12},{"text":"Andrej Karpathy: How can I have more of them? How can I do that appropriately? And then how can I use these claws? What are these claws? Uh, and uh, so there's like a lot of new things. I want to be at the forefront of it, you know?","offset":164,"duration":10},{"text":"Andrej Karpathy: And I'm very antsy that I'm not at the forefront of it. And I see lots of people on Twitter doing all kinds of things and they all sound like really good ideas, and I need to be at the forefront or I feel extremely nervous.","offset":174,"duration":6},{"text":"Andrej Karpathy: And so I guess I'm just in this psychosis of like what's possible, like because it's unexplored fundamentally.","offset":180,"duration":2},{"text":"Host: Well, if you're nervous, the rest of us are—are nervous. We have a—uh, we have a team that we work with at Conviction that their setup is everybody is like, you know, none of the engineers write code by hand and they're all microphoned and they just like whisper to their agents all the time.","offset":182,"duration":17},{"text":"Host: It's the strangest work setting ever, uh, and I thought they were crazy and now I like fully accept I was like, oh this was the way. Like you're just ahead of it. Um, what—uh, how do you think about your own capacity now to like explore or to do new projects? Like what—what is it limited by?","offset":199,"duration":18},{"text":"Andrej Karpathy: Yeah, what is it limited by? Uh, just I think everything, like so many things, even if they don't work, I think to a large extent you feel like it's skill issue. It's not that the capability's not there.","offset":217,"duration":12},{"text":"Andrej Karpathy: It's that you just haven't found a way to string it together of what's available. Like I just didn't give good enough instructions in the agents' MD file or whatever it may be. I don't have a nice enough memory tool that I put in there or something like that.","offset":229,"duration":13},{"text":"Andrej Karpathy: So it all kind of feels like skill issue when it doesn't work to some extent. You want to see how you can paralyze them etc. and you want to be Peter Steinberg basically. Uh, so Peter is famous, he has a funny photo where he's in front of a monitor with lots of like—uh, he uses Codex.","offset":242,"duration":13},{"text":"Andrej Karpathy: So lots of Codex agents tiling the—the monitor, and they all take about 20 minutes if you prompt them correctly and you use the high effort, and so they all take about 20 minutes. So you have multiple, you know, 10, uh, repos checked out, and so he's just, um, going between them and giving them work.","offset":255,"duration":15},{"text":"Andrej Karpathy: It's just like you can—you can move in much larger macro actions. It's not just like here's a line of code, here's a new function, it's like here's a new functionality and delegate it to agent one.","offset":270,"duration":10},{"text":"Andrej Karpathy: Here's a new functionality that's not going to interfere with the other one, give it to agent two, and then try to, uh, review their work as best as you can depending on how much you care about that code.","offset":280,"duration":8},{"text":"Andrej Karpathy: Like what are these macro actions that I can like manipulate my software repository by? And like another agent is doing some like research, another agent is writing code, another one is coming up with a plan for some new implementation.","offset":288,"duration":13},{"text":"Andrej Karpathy: And so everything is just like happening in these like macro actions over your repository. Um, and you're just trying to become like really good at it and develop like a muscle memory for it is extremely, um—yeah, it's very rewarding number one because it actually works.","offset":301,"duration":14},{"text":"Andrej Karpathy: But it's also kind of like the new thing to learn. So that's why hence the psychosis.","offset":315,"duration":4},{"text":"Host: Yeah, I—I do feel like my instinct is like whenever I am waiting for an agent to complete something, the obvious thing to do is like well I can do more work, right?","offset":319,"duration":8},{"text":"Host: Like if I have access to more tokens then like I should just parallelize and tasks. And so that—that's very stressful because if you don't feel very bounded by your ability to spend on tokens, then you know you are the bottleneck in this system that is max capability.","offset":327,"duration":15},{"text":"Andrej Karpathy: Yeah, if you're not maximizing your subscription at least, and uh, so ideally for multiple agents, like if you run out of the quota on Codex you should switch to Claude or whatnot, I don't know, like that's what I've been trying to do a little bit.","offset":342,"duration":9},{"text":"Andrej Karpathy: And I feel nervous when I have subscription left over, uh, that just means I haven't maximized my token throughput. So I actually kind of experienced this when I was a PhD student, you would feel nervous when your GPUs are not running.","offset":351,"duration":8},{"text":"Andrej Karpathy: Like you have GPU capability and you're not maximized to the available flops to you. But now it's not about flops, it's about tokens. Uh, so what is your token throughput and what token throughput do you command?","offset":359,"duration":10},{"text":"Host: I would actually argue that it's very interesting that we had, you know, at least 10 years where in many engineering tasks people just didn't—they didn't feel compute bound, right?","offset":369,"duration":12},{"text":"Host: Um, and like the entire industry feels that now. They feel like—they felt resource bound. Uh, and now that you have this big capability jump, you're like, oh actually it's not, you know, my ability to access the compute anymore, like I—I'm the binding constraint.","offset":381,"duration":12},{"text":"Andrej Karpathy: Yeah, it's a skill issue, which is very empowering cause, uh, yeah cause you could be getting better. So that's why—that's why I think it's very addictive because there's unlocks when—when you get better.","offset":393,"duration":7},{"text":"Host: Where do you think it goes? Like if you just think about like okay, you know, Andrej's iterating and everybody else's for 16 hours a day getting better at using coding agents, like what does it look like in a year of like you've reached mastery?","offset":400,"duration":12}],"startTime":85},{"title":"Open Claw and AI Agent Personalities","summary":"The conversation shifts to \"Claw-like\" entities—persistent, autonomous agents that operate in sandboxes. Andrej compares how they differ from single-session agents like Codex, particularly in their distinct and compelling personalities.","entries":[{"text":"Andrej Karpathy: Yeah, what does mastery look like, right? At the end of the year or like two, three, years, five years, ten years etc. Well I think everyone is basically interested in like going up the stack.","offset":412,"duration":9},{"text":"Andrej Karpathy: So I would say, yeah, it's not about a single session with your agent. Um, multiple agents, how do they collaborate and teams and so on. So everyone's trying to figure out what that looks like.","offset":421,"duration":8},{"text":"Andrej Karpathy: And then I would say Claw is also kind of an interesting direction because it really—when I say a Claw, I mean this like layer that uh kind of takes persistence to a whole new level.","offset":429,"duration":9},{"text":"Andrej Karpathy: Like it's something that like keeps looping, is—is um, it's not something that you are interactively in the middle of. It kind of like has its own little sandbox, its own little, you know, it kind of like does stuff on your behalf even if you're not looking kind of thing.","offset":438,"duration":10},{"text":"Andrej Karpathy: Um, and then also has like maybe more sophisticated memory systems etc. that are not yet implemented in agents. So, uh, Open Claw has a lot more sophisticated memory I would say than what you would get by default, uh, which is just a memory compaction when your context runs out, right?","offset":448,"duration":13},{"text":"Host: You think that's the piece that resonated for more users versus like perhaps like broader tool access?","offset":461,"duration":5},{"text":"Andrej Karpathy: For Open Claw?","offset":466,"duration":1},{"text":"Host: Yeah.","offset":467,"duration":1},{"text":"Andrej Karpathy: Uh, there's—like I think there's at least five things that resonated with users. Yeah, good job, Peter. I mean Peter has done a really amazing job.","offset":468,"duration":6},{"text":"Andrej Karpathy: Um, I saw him recently, uh, and I talked to him about it and I—he's very humble about it, but I think he innovated simultaneously in like five different ways and put it all together. Uh, so for example like the soul MD document, like he actually really crafted a personality that is kind of compelling and interesting.","offset":474,"duration":14},{"text":"Andrej Karpathy: And I feel like a lot of the current agents they don't get this correctly. I actually think Claude has a pretty good personality, it feels like a teammate. Uh, and uh, it's excited with you etc.","offset":488,"duration":10},{"text":"Andrej Karpathy: I would say, for example, Codex is a lot more dry, um, which is kind of interesting because in ChatGPT, Codex is like a lot more upbeat and highly sycophantic. But I would say Codex the coding agent is very dry.","offset":498,"duration":11},{"text":"Andrej Karpathy: It doesn't—it doesn't seem to care about what you're creating. It's kind of like, \"Oh, I implemented it.\" It's like, okay, but do you understand what we're building?","offset":509,"duration":6},{"text":"Host: It's true.","offset":515,"duration":1},{"text":"Andrej Karpathy: You know, it doesn't—um—and the other thing I would say is for example with Claude, I think they dialed the sycophancy fairly well, where when Claude gives me praise, I do feel like I slightly deserve it.","offset":516,"duration":9},{"text":"Andrej Karpathy: Um, because sometimes I kind of give it like not very well-formed thoughts, and uh I give it an idea that I don't think is fully baked and it doesn't actually react very strongly. It's like, \"Oh yeah, we can implement that.\"","offset":525,"duration":9},{"text":"Andrej Karpathy: But when it's a really good idea by my own account, it does uh seem to reward it a bit more, and so I kind of feel like I'm trying to like earn its praise, which is really weird.","offset":534,"duration":8},{"text":"Andrej Karpathy: And so I do think the personality matters a lot. Uh, and I think uh a lot of the other, uh, tools maybe don't appreciate it as much, and I think in this aspect also Peter really cares about this and so that was correct.","offset":542,"duration":7},{"text":"Andrej Karpathy: And then the memory system and then uh just you know he's just having fun with this. Um, and then the the single WhatsApp portal to all of the automation.","offset":549,"duration":9},{"text":"Host: Yeah. Is there something that you have done personally with your Claws beyond software engineering that you think is fun or interesting?","offset":558,"duration":9}],"startTime":412},{"title":"Home Automation and the End of Apps","summary":"Andrej shares his experience building \"Dobby,\" a Claw that autonomously reverse-engineered his home network to control smart devices via a unified WhatsApp interface. He suggests this agent-first paradigm renders bespoke apps obsolete.","entries":[{"text":"Andrej Karpathy: Yeah, so in January I had Claude—I went through a period of Claude psychosis, so I built a—um, I have a Claw basically that takes care of my home, and I call him Dobby the Elf Claw. Um, and uh basically I used uh the agents to find all of the smart home subsystems of my home on the local area network, which I was kind of surprised that worked out of the box.","offset":567,"duration":20},{"text":"Andrej Karpathy: Like I just told it that I think I have Sonos at home, like can you try to find it? And it goes and it did like IP scan of all of the um, basically um computers on the local area network, and it found the Sonos thing, uh the Sonos uh system.","offset":587,"duration":12},{"text":"Andrej Karpathy: And it turned out that there's no password protection or anything like that, it just logged in and it's like, \"Oh yeah, you have these Sonos systems installed. Uh, let me try to reverse engineer how it's uh working.\"","offset":599,"duration":10},{"text":"Andrej Karpathy: It does some web searches and it finds like, \"Okay, these are the API endpoints.\" And then it's like, \"Do you want to try it?\" and I'm like, \"Whoa, like you just did that.\" And I'm like, \"Yeah, can you try to play something in the study?\"","offset":609,"duration":9},{"text":"Andrej Karpathy: And uh it does, and music comes out. And I'm like, I can't believe I just—","offset":618,"duration":1},{"text":"Host: That's crazy, that's like three prompts.","offset":619,"duration":2},{"text":"Andrej Karpathy: I can't believe I just typed in like, \"Can you find my Sonos?\" and that suddenly it's playing music. And it did the same for lights. And so basically like it kind of hacked in, figured out the whole thing, uh created APIs, created a dashboard, so I could see the command kind of center of like all of my lights in the home.","offset":621,"duration":12},{"text":"Andrej Karpathy: And then it was like switching lights on and off and, you know, uh so I can ask it like Dobby at sleepy time, and when it's sleepy time that just means all the lights go off etc. and so on.","offset":633,"duration":11},{"text":"Andrej Karpathy: So it controls all of my lights, my HVAC, my shades, uh the pool and uh the spa, and also my security system. So I have a camera pointed outside of the house and anytime someone rolls in, I have a Quen—uh, a Quen uh model that looks at the videos.","offset":644,"duration":13},{"text":"Andrej Karpathy: So first of all there's change detection.","offset":657,"duration":2},{"text":"Host: Right.","offset":659,"duration":1},{"text":"Andrej Karpathy: And then based on change detection, it goes to Quen, and then it actually like tells me, uh it sends me a text to my WhatsApp, it shows an image from the outside, and it says, \"Hey FedEx truck just pulled up, FedEx truck just pulled up and you might want to check it and you got new mail or something like that.\"","offset":660,"duration":15},{"text":"Andrej Karpathy: And Dobby just texts me this. This is extremely incredible. Um, so so Dobby is in charge of the house, I text through with it through WhatsApp. Uh, and it's been like really fun to have these macro actions that maintain my house.","offset":675,"duration":14},{"text":"Andrej Karpathy: I haven't like really pushed it uh like way more beyond that, and I think people are doing a lot more crazy things with it, but for me even just the home automation setup, I used to use like six apps, uh completely different apps, and I don't have to use these apps anymore.","offset":689,"duration":13},{"text":"Andrej Karpathy: Like Dobby controls everything in natural language, it's amazing. Um, and so I think like I haven't even pushed the paradigm fully, but already that is so helpful and so inspiring I would say.","offset":702,"duration":9},{"text":"Host: Do you think that's indicative of like what people want from a user experience perspective with software?","offset":711,"duration":6},{"text":"Host: Right, because I—I don't think, you know, it's pretty ignored that it takes humans effort to like learn new software, like new UI.","offset":717,"duration":8},{"text":"Andrej Karpathy: Yeah, I think uh to some extent that's right. It's like working backwards from how people think an AI should be, because what people have in their mind of like what an AI is, is not actually what an LLM is by—like in the raw sense.","offset":725,"duration":10},{"text":"Andrej Karpathy: Like LLM is a token generator, you know, like more tokens come out. But what they think of is like this pers—this persona identity that they can tell stuff and it remembers it, you know, and uh is just an entity behind a WhatsApp. It's like a lot more understandable.","offset":735,"duration":13},{"text":"Andrej Karpathy: Um, so I think to some extent it's like matching the expectations that humans already have for what an AI should behave, but under the hood it's like a lot of technical details go into that. And LLMs are too raw of a primitive, uh to actually, uh type check as AI I think for most people if that makes sense.","offset":748,"duration":13},{"text":"Host: Yeah, I—I think that's like how we understand what the AI is, and like the description of it as Dobby or some persona obviously resonates with people.","offset":761,"duration":10},{"text":"Host: Um, I also think that it—uh the unification that you did across your six different software systems for your home automation speaks to a different question of like do people really want all of this software that we have today?","offset":771,"duration":11},{"text":"Andrej Karpathy: Yeah.","offset":782,"duration":1},{"text":"Host: Um, because I would argue like well you have the hardware, but you've now thrown away the software or the the UX layer of it. Um, do you think that's what people want?","offset":783,"duration":11},{"text":"Andrej Karpathy: Yeah, I think there's this like there's this sense that these apps that are on the app store for using these smart home devices etc., uh these shouldn't even exist kind of in a certain sense.","offset":794,"duration":9},{"text":"Andrej Karpathy: Like shouldn't it just be APIs and shouldn't agents be just using it directly? And uh wouldn't it like—I can do all kinds of home automation stuff that uh any individual app will not be able to do, right?","offset":803,"duration":10},{"text":"Andrej Karpathy: Um, and an LLM can actually drive the tools and call all the right tools and do do pretty complicated things. Um, and so in a certain sense it does point to this like maybe there's like an overproduction of lots of custom bespoke apps that shouldn't exist because agents kind of like crumble them up.","offset":813,"duration":13},{"text":"Andrej Karpathy: And everything should be a lot more just like exposed API endpoints, and agents are the glue of the intelligence that actually like tool calls all the all the parts. Um, another example is like my treadmill.","offset":826,"duration":12},{"text":"Andrej Karpathy: Uh, there's an app for my treadmill, and I wanted to like keep track of how often I do my cardio, uh but like I don't want to like log into a web UI and go through a flow and etc. Like all this should just be like make APIs available.","offset":838,"duration":12},{"text":"Andrej Karpathy: And this is kind of, you know, going towards the agentic, uh sort of web or like agent first, uh tools and all this kind of stuff. So I think the industry just has to reconfigure in so many ways that it's like the customer is not the human anymore.","offset":850,"duration":12},{"text":"Andrej Karpathy: It's like agents who are acting on behalf of humans, and this refactoring will be will probably be substantial in a certain sense.","offset":862,"duration":6},{"text":"Host: One way that people sometimes push back on this is like do people, do we expect people to vibe code some of these tools?","offset":868,"duration":6},{"text":"Host: Do we expect normal people to do this kind of stuff that I described? But I think to some extent this is just, you know, technology as it exists today, and right now there is some vibe coding and I'm actually watching it and I'm working with the system.","offset":874,"duration":14},{"text":"Andrej Karpathy: But I kind of feel like the kind of stuff that I just talked about, this should be free, like in a year or two or three. There's no vibe coding involved. This is trivial, this is table stakes. This is like any AI, even the open source models etc. can like do this.","offset":888,"duration":11},{"text":"Host: You should be able to translate from a less technical human's intent very easily to this outcome.","offset":899,"duration":6},{"text":"Andrej Karpathy: Extremely easily. Yeah. Today it's vibe coding and some involved and not many people are going to do it, but—","offset":905,"duration":3},{"text":"Host: And you still have to make some design decisions, right? We were talking about like what you take frames, for example.","offset":908,"duration":5},{"text":"Andrej Karpathy: Yeah. But I kind of feel like this will just uh start to the barrier will just come down and it's just ephemeral software on your behalf and some kind of like Claw is handling all the details for you, but you're not involved. Claw has a Claw has a machine and it will figure it out, and it's just presenting you UIs and you're like saying stuff, you know.","offset":913,"duration":14}],"startTime":567},{"title":"Privacy and Time Constraints on Personal Agents","summary":"Andrej explains why he hasn't integrated Claws into more aspects of his personal digital life yet, citing security, privacy concerns, and general distraction from other projects.","entries":[{"text":"Host: Why haven't you uh I guess like pushed the boundaries of what you can do personally with Claws like is it, you know, you're focusing on more important projects? AutoResearch etc. or uh you're climbing the hill to mastery or something else, right?","offset":927,"duration":15},{"text":"Andrej Karpathy: Yeah, I just feel like I'm so distracted by everything. So I spent I spent like a week on the Claw stuff and I I have more to-dos almost, um but I will say that—","offset":942,"duration":11},{"text":"Host: It's like Jensen told us, we're all just busier, unfortunately.","offset":953,"duration":2},{"text":"Andrej Karpathy: Yeah. Uh, I didn't really take advantage of a lot of like email and calendar and all this other stuff, and I didn't give it access because I'm still a little bit like suspicious and it's still very new and rough around the edges, so I didn't want to give it like full access to my digital life yet.","offset":955,"duration":14},{"text":"Andrej Karpathy: And part of it is just security privacy and uh just being very cautious in that in that realm. And uh so some of it is like held back by that I would say. Yeah maybe that's like the dominant dominant feature, but some of it is also just I feel so distracted because I feel like I had a week of Claw and then other stuff is happening and—","offset":969,"duration":13}],"startTime":927},{"title":"AutoResearch and Removing Humans From the Loop","summary":"Andrej outlines his AutoResearch project, highlighting the necessity of removing human bottlenecks to maximize token throughput. This allows agents to recursively self-improve and autonomously tune models overnight.","entries":[{"text":"Host: What was the um—I mean, you have talked about like being able to train or at least optimize a uh a model as a task that you want to see agents do for a long time. Like what was the motivation behind AutoResearch?","offset":982,"duration":13},{"text":"Andrej Karpathy: AutoResearch, yeah. So I think like I had a tweet earlier where I kind of like said something along the lines of to get the most out of the tools that are becoming available now, you have to remove yourself as the as the bottleneck.","offset":995,"duration":12},{"text":"Andrej Karpathy: You can't be there to prompt the next thing. You're you need to take yourself outside um. You have to arrange things such that they are completely autonomous and the more you know, how can you maximize your token throughput and not be in the loop?","offset":1007,"duration":12},{"text":"Andrej Karpathy: This is the this is the goal. And so I kind of mentioned that the the name of the game now is to increase your leverage. Uh, I put in just very few tokens just once in a while and a huge amount of stuff happens on my behalf.","offset":1019,"duration":9},{"text":"Andrej Karpathy: And so AutoResearch, like I tweeted that and I think people liked it and whatnot, but—","offset":1028,"duration":4},{"text":"Host: They haven't like maybe worked through like the implications of that.","offset":1032,"duration":3},{"text":"Andrej Karpathy: And for me AutoResearch is an example of like an implication of that where it's like I don't want to be like the researcher in the loop like looking at results etc. like I'm I'm holding the system back.","offset":1035,"duration":8},{"text":"Andrej Karpathy: So the question is how do I refactor all the abstractions so that I'm not—I have to arrange it once and hit go. The name of the game is how can you get more agents running for longer periods of time without your involvement doing stuff on your behalf?","offset":1043,"duration":12},{"text":"Andrej Karpathy: And AutoResearch is just, yeah, here's an objective, here's a metric, here's your boundaries of what you can and cannot do and go. And uh yeah, it worked.","offset":1055,"duration":7},{"text":"Host: You were surprised at its effectiveness.","offset":1062,"duration":3},{"text":"Andrej Karpathy: Yeah, I I didn't expect uh it to work because so I have the project Nanochat, um and fundamentally like I think a lot of people are very confused with my obsession for like training GPT-2 models and so on, but for me uh training GPT models and so on is just a little harness, a little playground for training LLMs.","offset":1065,"duration":15},{"text":"Andrej Karpathy: And fundamentally what I'm more interested in is like this idea of recursive self-improvement and to what extent can you actually have LLMs improving LLMs? Because I think all the frontier labs this is like the thing, um for obvious reasons.","offset":1080,"duration":9},{"text":"Andrej Karpathy: And they're all trying to recursively self-improve roughly speaking. And so for me this is kind of like uh a little playpen of that. Um, and I guess I like tuned Nanochat already quite a bit by hand in a good old-fashioned way that I'm used to.","offset":1089,"duration":13},{"text":"Andrej Karpathy: Like I'm a researcher, I've done this for like you know two decades, I have some amount of like—","offset":1102,"duration":3},{"text":"Host: What is the opposite of hubris? Uh, yeah.","offset":1105,"duration":2},{"text":"Host: Earned confidence.","offset":1107,"duration":1},{"text":"Andrej Karpathy: Okay. Of like two decades of like oh I've trained this model like thousands of times of like um so I've done a bunch of experiments, I've done hyperparameter tuning, I've done all the things I'm very used to and I've done for two decades.","offset":1108,"duration":13},{"text":"Andrej Karpathy: Yeah. And I've gotten to a certain point and I thought it was like fairly well-tuned, and then I let AutoResearch go for like overnight and it came back with like tunings that I didn't see. And yeah I did forget like the weight decay on the value embeddings, and my Adam betas were not sufficiently tuned, and these things jointly interact.","offset":1121,"duration":18},{"text":"Andrej Karpathy: So like once you tune one thing the other things have to potentially change too. You know, I shouldn't be a bottleneck, I shouldn't be running these hyperparameter search optimizations, I shouldn't be looking at the results.","offset":1139,"duration":8},{"text":"Andrej Karpathy: There's objective criteria in this case. Uh, so you just let you just have to arrange it so that it can just go forever. So that's a single sort of version of AutoResearch of like a single loop trying to improve.","offset":1147,"duration":8},{"text":"Andrej Karpathy: And I was surprised that it um it found these things that I you know the repo is already fairly well-tuned and still found something. And that's just a single it's a single loop.","offset":1155,"duration":6},{"text":"Andrej Karpathy: Like these frontier labs they have GPU clusters of tens of thousands of them, and so it's very easy to imagine how you would basically get a lot of this automation on um smaller models, and fundamentally everything around like frontier-level intelligence is about extrapolation and scaling laws.","offset":1161,"duration":18},{"text":"Andrej Karpathy: And so you basically do a ton of the exploration on the smaller models and then you try to uh extrapolate out.","offset":1179,"duration":4},{"text":"Host: So you're saying our research efforts are going to get more efficient, like we're going to have better direction for when we scale as well if we can do this experimentation better.","offset":1183,"duration":8},{"text":"Andrej Karpathy: Yeah, I would say that like the most interesting project and probably what the frontier labs are working on is um you know you experiment on small models, you try to make it as autonomous as possible, remove researchers—","offset":1191,"duration":8},{"text":"Host: From the loop.","offset":1199,"duration":2},{"text":"Andrej Karpathy: —they have way too much—","offset":1201,"duration":2},{"text":"Host: What is the opposite of—which—","offset":1203,"duration":1},{"text":"Host: Earned confidence.","offset":1204,"duration":1},{"text":"Andrej Karpathy: Yeah, they don't know. They shouldn't be touching any of this really. And so you have to like rewrite the whole thing because right now I mean certainly they can contribute ideas.","offset":1205,"duration":7},{"text":"Andrej Karpathy: But okay uh they shouldn't actually be enacting these ideas. There's a queue of ideas, and there's maybe an automated scientist that comes up with ideas based on all the archive papers and GitHub repos and it funnels ideas in, or researchers can contribute ideas.","offset":1212,"duration":13},{"text":"Andrej Karpathy: But it's a single queue and there are workers that pull uh items and they try them out, and uh whatever works just gets uh sort of put on the feature branch and maybe some people like uh monitor the feature branch and merge to the main branch sometimes.","offset":1225,"duration":14},{"text":"Andrej Karpathy: So yeah just removing humans uh from all the processes and automating as much as possible and getting high to tokens per second throughputs and it does require rethinking of all the abstractions uh and uh everything has to be reshuffled so yeah I think it's very exciting.","offset":1239,"duration":15}],"startTime":982},{"title":"Meta-Optimizing the AI Research Process","summary":"The discussion dives deeper into meta-optimization and recursive self-improvement. Andrej explores how research organizations could be defined as markdown files that AI models evaluate and improve over time.","entries":[{"text":"Host: Take one more recursive step here. Um, uh when is the model going to write a better Program MD than you?","offset":1254,"duration":5},{"text":"Andrej Karpathy: Yeah.","offset":1259,"duration":1},{"text":"Host: We're not in the loop.","offset":1260,"duration":1},{"text":"Andrej Karpathy: Yeah, exactly. Uh, so Program MD is my crappy attempt at describing like how the AutoResearcher should work. Like oh do this, then do that and that and then try these kinds of ideas.","offset":1261,"duration":10},{"text":"Andrej Karpathy: Like here's maybe some ideas like look at architecture, look at optimizer etc. but I just came up with this in Markdown, right? Um, and uh so yeah exactly.","offset":1271,"duration":9},{"text":"Andrej Karpathy: You want some kind of an AutoResearch loop maybe that looks for—you can imagine that different Program MDs would um would give you different uh progress. So you basically every research organization is described by Program MD.","offset":1280,"duration":15},{"text":"Host: Yeah.","offset":1295,"duration":1},{"text":"Andrej Karpathy: A research organization is a set of Markdown files that describe all the roles and how the whole thing connects. Um, and you can imagine having a better research organization.","offset":1296,"duration":10},{"text":"Andrej Karpathy: So maybe they do fewer stand-ups in the morning because they're useless. Uh, and this is all just code, right? Um, and so you can so one organization can have fewer stand-ups, one organization can have more, uh one organization can be very risk-taking, one organization can be less.","offset":1306,"duration":13},{"text":"Andrej Karpathy: And so you can definitely imagine that you have multiple research orgs, um and then they all have code. And once you have code then you can imagine tuning the code. So 100% there's like the meta layer of it uh uh.","offset":1319,"duration":10},{"text":"Host: Did you see my text about my contest idea? My contest idea was uh like let people write uh different Program MDs, right?","offset":1329,"duration":9},{"text":"Host: And so for same hardware where do you get most improvement?","offset":1338,"duration":2},{"text":"Andrej Karpathy: Oh, I see.","offset":1340,"duration":1},{"text":"Host: And then you can take all that data and then give it to the model and say write a better Program MD.","offset":1341,"duration":4},{"text":"Andrej Karpathy: Yes, yes. Yeah, exactly.","offset":1345,"duration":3},{"text":"Host: We're going to get something better. Like there's no way we don't, right?","offset":1348,"duration":1},{"text":"Andrej Karpathy: You can 100% look at uh where the improvements came from and like can I change the Program MD such that more of these kinds of things would be done, or like things that didn't work uh etc. Meta optimization.","offset":1349,"duration":13},{"text":"Host: Yeah.","offset":1362,"duration":1},{"text":"Andrej Karpathy: You can 100% imagine doing that. So I think this is a great idea. But it's like you know I think you sort of go one step at a time where you sort of have one process and then second process and then the next process, and these are all layers of an onion.","offset":1363,"duration":10},{"text":"Andrej Karpathy: Like the LLM sort of part is now taken for granted, the agent part is now taken for granted, now the claw-like entities are taken for granted, and now you can have multiple of them, and now you can have instructions to them, and now you can have optimization over the instructions, and it's just a little too much, you know?","offset":1373,"duration":14},{"text":"Andrej Karpathy: But they I mean this is what gets to the psychosis, is that this is like infinite and everything is skill issue, and that's why I feel yeah that's just coming back to this is why it's so insane.","offset":1387,"duration":-1191},{"text":"Host: Okay, well if we're we're just trying to like diagnose the current moment and uh what is a relevant skill right now, what do you like what do you think is the implication that this um that this is the loop we should be trying to achieve in different areas?","offset":196,"duration":1213},{"text":"Host: And that it works, right? Like remove—create the metric or create the ability for um agents to continue working on it without you. Do we still have performance engineering? Like what—","offset":1409,"duration":11}],"startTime":1254},{"title":"Capability Jaggedness and Limitations of AI","summary":"Andrej outlines the caveats of autonomous research, noting that AI capabilities remain extremely \"jagged.\" While agents excel at verifiable tasks like code efficiency, they struggle with softer domains and humor because those elements are not heavily optimized via reinforcement learning.","entries":[{"text":"Andrej Karpathy: Yeah, I mean so there's a few caveats that I would put on top of the LM psychosis. So number one, uh this is extremely well suited to anything that has objective uh metrics that are easy to evaluate.","offset":1420,"duration":9},{"text":"Host: Hmm.","offset":1429,"duration":1},{"text":"Andrej Karpathy: So for example like writing kernels for more efficient CUDA, uh you know code for various parts of a model etc. are the perfect fit. Um, because you have inefficient code and then you want efficient code that has the exact same behavior but is much faster. Perfect fit.","offset":1430,"duration":16},{"text":"Andrej Karpathy: Uh, so a lot of things that like are perfect fit for AutoResearch, but many things will not be. And so they it's just if you can't evaluate it then you can't AutoResearch it, right? Uh, so that's like caveat number one.","offset":1446,"duration":10},{"text":"Andrej Karpathy: And then maybe caveat number two I would say is you know we're we're kind of talking about next steps and we kind of see what next steps are, but fundamentally the whole thing still doesn't it still kind of like bursting at the seams a little bit and there's cracks and it doesn't fully work.","offset":1456,"duration":12},{"text":"Andrej Karpathy: And if you kind of try to go too far ahead the whole thing is actually net not useful, if that makes sense. Um because these models like still are not you know they've improved a lot but they're still like rough around the edges as maybe the way I would describe it.","offset":1468,"duration":12},{"text":"Andrej Karpathy: I simultaneously feel like I'm talking to an extremely brilliant PhD student who's been like a systems programmer for their entire life and a 10-year-old. And it's so weird because humans like there's—","offset":1480,"duration":12},{"text":"Host: Yes you wouldn't you wouldn't encounter that combination.","offset":1492,"duration":2},{"text":"Andrej Karpathy: This jaggedness is really strange and humans have a lot less of that kind of jaggedness although they definitely have some. But humans have a lot more jaggedness—uh sorry the agents have a lot more jaggedness where uh sometimes like you know I ask for functionality and it like comes back with something that is just like totally wrong.","offset":1494,"duration":16},{"text":"Andrej Karpathy: And then we get into loops that are totally wrong and then I'm just I get so frustrated with the agents all the time still because you feel the power of it but you also there's still like it does nonsensical things once in a while for me uh still as well.","offset":1510,"duration":14},{"text":"Host: I get very annoyed when uh uh I feel like the agent wasted a lot of compute on something it should have recognized was an obvious problem.","offset":1524,"duration":8},{"text":"Andrej Karpathy: Yeah. I think like some of the bigger things is like maybe what's under underneath it, if I could hypothesize, is fundamentally these models are trained via reinforcement learning.","offset":1532,"duration":9},{"text":"Andrej Karpathy: So they're actually struggling with the exact same thing we just talked about which is the labs can improve the models in anything that is verifiable or that has rewards. So did you write the program correctly and does it do the unit tests check out, yes or no?","offset":1541,"duration":13},{"text":"Andrej Karpathy: But some of the things where they're struggling is like for example I think they have a tough time with like nuance of maybe what I what I had in mind or what I intended and when to ask clarifying questions.","offset":1554,"duration":11},{"text":"Andrej Karpathy: Uh, like or where the—yeah, it's just um anything that feels softer is like worse. And so you're kind of like you're either on rails and you're part of the superintelligence circuits or you're not on rails and you're outside of the verifiable domains and suddenly everything kind of just like meanders.","offset":1565,"duration":-1187},{"text":"Andrej Karpathy: Like maybe another way to put it is if you go to if today if you go to like state-of-the-art model ChatGPT and you ask it tell me a joke, um do you know what joke you're going to get? There's the joke.","offset":378,"duration":1209},{"text":"Host: The joke. I do feel I I can't tell you like the you know standard form of it, but I do feel like ChatGPT has like three jokes.","offset":1587,"duration":8},{"text":"Andrej Karpathy: Yeah, yeah. So the the joke that apparently all the LLMs like love the most is why do scientists uh not trust atoms?","offset":1595,"duration":6},{"text":"Host: Okay.","offset":1601,"duration":1},{"text":"Andrej Karpathy: Because they make everything up.","offset":1602,"duration":1},{"text":"Host: Okay.","offset":1603,"duration":1},{"text":"Andrej Karpathy: They make everything up. So this is still—","offset":1604,"duration":2},{"text":"Host: Why'd that emerge?","offset":1606,"duration":2},{"text":"Andrej Karpathy: So this is the joke you would get three or four years ago and this is the joke you still get today.","offset":1608,"duration":3},{"text":"Host: Okay.","offset":1611,"duration":1},{"text":"Andrej Karpathy: So even though the models have improved tremendously and if you give them an agentic task they will just go for hours and move mountains for you, and then you ask for like a joke and it has a stupid joke, a crappy joke from five years ago.","offset":1612,"duration":14},{"text":"Andrej Karpathy: And it's because it's outside of the it's outside of the RL. It's outside of what's being improved, it's like and it's part of the jaggedness of like shouldn't you expect models as they get better to also have like better jokes or more diversity of them or it's just it's not being optimized and it's stuck.","offset":1626,"duration":15},{"text":"Host: Do you uh uh think that that implies that we are not seeing like generalization in the sense of like broader intelligence of joke smartness being attached to code smartness?","offset":1641,"duration":14},{"text":"Andrej Karpathy: Yeah, I think there's some decoupling where some things are verifiable and some things are not and some things are optimized for arbitrarily by the labs depending on like what data went in and some things are not.","offset":1655,"duration":11},{"text":"Host: But I mean the premise, there's a you know premise from some research groups that if you are smarter at code generation or in these verifiable fields you should be better at everything.","offset":1666,"duration":11},{"text":"Host: And like the the joke situation suggests that that's not happening in Auto—","offset":1677,"duration":2},{"text":"Andrej Karpathy: I don't think that's happening.","offset":1679,"duration":1},{"text":"Host: Okay.","offset":1680,"duration":1},{"text":"Andrej Karpathy: Yeah, I don't think that's happening. I think I think maybe we're seeing like a little bit of that, but not like a satisfying amount.","offset":1681,"duration":5},{"text":"Host: Yeah. That jaggedness exists in humans. You can be very, very good at math and still tell really bad jokes.","offset":1686,"duration":7},{"text":"Andrej Karpathy: Yeah, that's true, yeah. But it just it still means that we're not getting like the story is that we're getting a lot of the intelligence and capabilities in all the domains of society like for free as we get better and better models, and that's not like exactly fundamentally what's going on.","offset":1693,"duration":13},{"text":"Andrej Karpathy: And there's some blind spots and some things are not being optimized for and this is all clustered up in these neural net opaque models, right?","offset":1706,"duration":8},{"text":"Andrej Karpathy: So you're either on rails of what it was trained for and everything is like you're going at speed of light or you're not. Um, and so it's the jaggedness.","offset":1714,"duration":8},{"text":"Andrej Karpathy: So um so that's why I think like even though the the progression is obvious what should happen, you can't let it fully go there yet because it doesn't fully work, or it's a skill issue and we just haven't like figured out how to use it, so you know it's hard to tell.","offset":1722,"duration":14}],"startTime":1420},{"title":"Model Monoculture vs. Domain Speciation","summary":"The host and Andrej consider whether AI models will eventually unbundle into specialized \"expert\" domains. Andrej believes speciation makes sense for efficiency, but notes that labs are currently focused on a monoculture of arbitrarily intelligent models.","entries":[{"text":"Host: Can I ask kind of a blasphemous question which is like if this jaggedness is persistent um and it's all rolled up in a at least monolithic interface, right?","offset":1736,"duration":12},{"text":"Host: But you know single model, um does that make sense or do you should it be unbundled into things that are can be optimized and improved against different domains of intelligence?","offset":1748,"duration":8},{"text":"Andrej Karpathy: Uh like unbundling the models into multiple experts in different areas etc. more directly? Yeah.","offset":1756,"duration":5},{"text":"Host: Yeah. Instead of just MOE that we have no exposure to.","offset":1761,"duration":3},{"text":"Host: Because that can be like confusing as a user from the outside which is like why is it so good at this but not at this other thing.","offset":1764,"duration":8},{"text":"Andrej Karpathy: Yeah, I think currently my impression is uh the labs are trying to have a single sort of monoculture of a model that is arbitrarily intelligent in all these different domains and they just stuff it into the parameters.","offset":1772,"duration":11},{"text":"Andrej Karpathy: I do think that we will I do think we should expect more speciation in the intelligence. Um like you know the animal kingdom is extremely diverse in the brains that exist and there's lots of different niches of of nature, and some animals have overdeveloped visual cortex or other kind of parts.","offset":1783,"duration":16},{"text":"Andrej Karpathy: And I think we we should be able to see more speciation and um you don't need like this oracle that knows everything you kind of speciate it and then you put it on a specific task.","offset":1799,"duration":9},{"text":"Andrej Karpathy: And we should be seeing some of that because you should be able to have like much smaller models that still have the cognitive core like they're still competent but then they specialize and then um and then they can become more efficient in terms of latency or throughput on uh specific tasks that you really care about.","offset":1808,"duration":15},{"text":"Andrej Karpathy: Like if you're a mathematician working in Lean. I saw for example there's a few releases that really like target that as in the domain. Um so there's a probably going to be a few examples like that where the unbundling kind of makes sense.","offset":1823,"duration":10},{"text":"Host: One question I have is whether or not uh the capacity constraint on available compute infrastructure drives more of this.","offset":1833,"duration":8},{"text":"Host: Because efficiency actually matters more, right? Like you're if financing aside though financing is involved in all of this, if you have access to full compute for anything you do like leaving the one single model, right?","offset":1841,"duration":13},{"text":"Host: But if you actually feel pressure where you're like I can't serve um model of massive size for every use case like do you think that leads to any speciation?","offset":1854,"duration":12},{"text":"Host: Does that question make sense to you?","offset":1866,"duration":1},{"text":"Andrej Karpathy: The question makes sense. And I guess like what I'm what I'm what I'm struggling with is I don't think we've seen too much speciation just yet, right?","offset":1867,"duration":6},{"text":"Host: No.","offset":1873,"duration":1},{"text":"Andrej Karpathy: Uh we're seeing a monoculture of models.","offset":1874,"duration":1},{"text":"Host: Yeah.","offset":1875,"duration":1},{"text":"Andrej Karpathy: And there's like clearly pressure for like make a good code model put it back in the main merge again.","offset":1876,"duration":6},{"text":"Host: Yeah, yeah.","offset":1882,"duration":1},{"text":"Andrej Karpathy: Even though there already is pressure on the models. Uh I guess perhaps I I feel like there's a lot of very short-term supply crunch and like maybe that causes more speciation now.","offset":1883,"duration":12},{"text":"Andrej Karpathy: Yeah, I think fundamentally like the model the labs are serving a model and they don't really know what the end user is going to be asking about. Uh so maybe that's like some part of it because they kind of have to multitask over all the possible things they could be asked.","offset":1895,"duration":13},{"text":"Andrej Karpathy: But I think if you're coming to a business and maybe partnering on some specific problems you care about then maybe you would see that there. Uh or there would be some very high-value applications that are like more niche. Um but uh I think right now they're kind of like going after the totality of what's available.","offset":1908,"duration":15},{"text":"Andrej Karpathy: I don't think that the science of manipulating the brains is like fully developed yet partly.","offset":1923,"duration":4},{"text":"Host: What do you mean manipulating?","offset":1927,"duration":1},{"text":"Andrej Karpathy: Uh so like so fine-tuning without losing capabilities as an example. And I we don't have these primitives for actually like working with the intelligences in ways other than just context windows.","offset":1928,"duration":11},{"text":"Andrej Karpathy: Like context windows kind of just work and it's very cheap to manipulate etc. and this is how we're getting some of the customization etc. but I think if it was I think it's a bit more of a developing science of how you like more deeply adjust the models.","offset":1939,"duration":9},{"text":"Andrej Karpathy: How you have continuous learning maybe or how you uh how you fine-tune in certain area, how you get better in certain area or like how you actually touch the weights, not just the context windows.","offset":1948,"duration":10},{"text":"Andrej Karpathy: And so it's a lot more tricky I would say to touch the weights than just the context window uh because you're actually fundamentally changing the full model and potentially its intelligence.","offset":1958,"duration":-529},{"text":"Andrej Karpathy: And so uh so maybe it's just like not a fully developed science if that makes sense of speciation.","offset":1429,"duration":2},{"text":"Host: And it also has to be like cheap enough.","offset":1431,"duration":542},{"text":"Andrej Karpathy: Yeah.","offset":1973,"duration":1}],"startTime":1736},{"title":"Decentralized Swarms for AI Research","summary":"Andrej envisions a decentralized \"swarm\" approach to AutoResearch, similar to Folding@home. He theorizes that an untrusted pool of internet workers could contribute compute cycles to iteratively improve models, treating flops as a primary currency.","entries":[{"text":"Host: For that speciation to be worthwhile in these given contexts. Can I ask a question about uh like an extension to AutoResearch that you described in terms of um open ground you say okay well you know we have this thing um we need more collaboration surface around it essentially for people to contribute.","offset":1974,"duration":19},{"text":"Host: Um to research overall. Can you talk about that?","offset":1993,"duration":2},{"text":"Andrej Karpathy: Yeah, so we talked about AutoResearch has a single thread of like I'm going to try stuff in a loop. Uh but fundamentally the parallelization of this is like the interesting component.","offset":1995,"duration":9},{"text":"Andrej Karpathy: Uh and I guess I was trying to like play around with a few ideas but I don't have anything that like clicks as simply as like I don't have something that I'm like super happy with just yet, but it's something I'm like working on on the side when I'm not working on my Claw.","offset":2004,"duration":11},{"text":"Andrej Karpathy: Uh so I think like one issue is if you have a bunch of nodes uh of parallelization available to you, then it's very easy to just have multiple AutoResearchers talking through a uh a common system or something like that.","offset":2015,"duration":13},{"text":"Andrej Karpathy: What I was more interested in is how you can have an untrusted pool of workers out there on the internet.","offset":2028,"duration":5},{"text":"Host: Hmm.","offset":2033,"duration":1},{"text":"Andrej Karpathy: So for example in AutoResearch, um you're just trying to find uh the piece of code that trains a model to a very low validation loss.","offset":2034,"duration":6},{"text":"Andrej Karpathy: If anyone gives you a candidate commit, it's very easy to verify that that commit is correct is good. Like they somehow could claim from the internet that this piece of code will optimize uh much better and give you much better performance.","offset":2040,"duration":12},{"text":"Andrej Karpathy: You could just check. It's very easy. But probably a lot of work goes into that checking. Uh but fundamentally they could lie and etc. So you're basically dealing with a similar kind of pro—it's almost actually like looks a little bit like—","offset":2052,"duration":12},{"text":"Andrej Karpathy: My designs that incorporate an untrusted pool of workers actually like a little bit more like a blockchain a little bit. Uh because instead of blocks you have commits and these commits can build on each other and they contain like changes to the code as you're improving it.","offset":2064,"duration":16},{"text":"Andrej Karpathy: Uh and the proof of work is basically doing tons of experimentation to find the commits that work. Uh and that's hard. Um and then the reward is just being on the leaderboard right now.","offset":2080,"duration":10},{"text":"Andrej Karpathy: There's no monetary reward whatsoever. Uh but I don't want to push the analogy too far, but it fundamentally has this issue where huge amount of search goes into it, but it's very cheap to verify that a candidate solution is indeed good because you can just train a single, you know, someone had to try 10,000 ideas but you just have to check that the thing that they produced actually works.","offset":2090,"duration":15},{"text":"Andrej Karpathy: Because the 9,999 of them didn't work, you know? Um and so basically long story short it's like you have to come up with a system where an untrusted pool of workers can collaborate with a trusted pool of workers uh that do the verification and the whole thing is kind of like asynchronous and works and uh and so on.","offset":2105,"duration":18},{"text":"Andrej Karpathy: And is is like safe from a security perspective because if anyone sends you arbitrary code and you're going to run it, that's very sketchy and dodgy. So um but fundamentally it should be totally possible.","offset":2123,"duration":10},{"text":"Andrej Karpathy: So you're familiar with projects like SETI@home and Folding@home. All of these problems have a similar kind of uh setup. So Folding@home, you're folding a protein um and it's very hard to find a configuration that is low energy.","offset":2133,"duration":13},{"text":"Andrej Karpathy: But if someone finds a configuration that they evaluate to be low energy, that's perfect. You can just use it. You can easily verify it. So a lot of things have this property that, you know, very expensive to come up with but very cheap to verify.","offset":2146,"duration":11},{"text":"Andrej Karpathy: And so in all those cases things like Folding@home or SETI@home or AutoResearch@home will be good fits. And so um long story short a swarm of agents on the internet could collaborate to improve LLMs and could potentially even like run circles around frontier labs.","offset":2157,"duration":16},{"text":"Andrej Karpathy: Like who knows, you know? Um yeah like maybe that's even possible. Like frontier labs have a huge amount of trusted compute, but the Earth is much bigger and has huge amount of untrusted compute. But if you put systems in check, systems in place that, you know, deal with this, then maybe it is possible that the swarm out there could uh could come up with a with better with better solutions.","offset":2173,"duration":16},{"text":"Andrej Karpathy: And people just kind of like contribute cycles um to a thing that they care about. And so sorry so the last thought is lots of companies or whatnot they could maybe have like their own uh things that they care about, and you if you have compute capacity you could contribute to different kind of AutoResearch tracks.","offset":2189,"duration":17},{"text":"Andrej Karpathy: Like maybe you care about certain you know you care about like cancer or something like that of certain type. You don't have to just donate money to an institution, you actually could like purchase compute and then you could join the AutoResearch swarm for that project, you know?","offset":2206,"duration":13},{"text":"Andrej Karpathy: Um so if everything is rebundled into AutoResearchers then compute becomes the thing that you're contributing to the pool.","offset":2219,"duration":6},{"text":"Host: Yeah, that's very inspiring and it's also interesting. Like I don't I don't know how far this goes, but it is interesting that at least some audience of people, you know, here in Silicon Valley or lining up at um retail stores in China have discovered that like having access to personal compute is interesting again.","offset":2225,"duration":17},{"text":"Host: Yeah. So maybe they're really motivated to do that for their Claws and then they can uh contribute to AutoResearch.","offset":2242,"duration":4},{"text":"Andrej Karpathy: It's almost like dollar is the thing everyone cares about, but is flop the thing that actually everyone cares about in the future? Like is there going to be like a flippening almost of like what the thing that you care about?","offset":2246,"duration":10},{"text":"Andrej Karpathy: Like right now for example it's really hard to get compute even if you have money. Yeah. So actually it almost seems like the flop is like dominant uh in a certain sense. Um yes so uh so maybe that's kind of like kind of like that. Like how much how many flops do you control instead of like what wealth do you control?","offset":2256,"duration":14},{"text":"Andrej Karpathy: I don't actually think that's true, but it's kind of interesting to think about.","offset":2270,"duration":2}],"startTime":1974},{"title":"AI Labor Market Impact and Jevons Paradox","summary":"Andrej unpacks his analysis of BLS jobs data, predicting that AI will primarily unhobble digital information processing first. He also notes that the demand for software engineers will paradoxically increase as code becomes cheaper and easier to produce.","entries":[{"text":"Host: The last thing you released was like a little bit of jobs data analysis. Is that right?","offset":2272,"duration":5},{"text":"Andrej Karpathy: Yeah.","offset":2277,"duration":1},{"text":"Host: What um and it touched a nerve even though you were just like visualizing some public data. Uh what was you know what were you curious about?","offset":2278,"duration":9},{"text":"Andrej Karpathy: Yeah, I guess I was curious to um I mean everyone is like really it's everyone is really thinking about the impacts of AI on the job market and what it's going to look like. So I was just interested to take a look like what does the job market look like?","offset":2287,"duration":11},{"text":"Andrej Karpathy: Where are the different roles? Um and how many people are in different professions? And I was like really just interested to like look through uh the individual cases and try to think myself about like you know with these AIs and how they're likely to evolve like are these going to be tools that people are using? Are these going to be displacing tools for these uh professions?","offset":2298,"duration":22},{"text":"Andrej Karpathy: And like what are the current professions and how are they going to change? Are they going to grow or uh adjust to a large extent? Or like what could be new professions? So it was really just like a way to fuel my own chain of thought about the industry I suppose.","offset":2320,"duration":12},{"text":"Andrej Karpathy: Um and so uh yeah the jobs data basically is just a Bureau of Labor Statistics. Uh they actually have a percent outlook for each profession about how much it's expected to grow over the next I think almost a decade.","offset":2332,"duration":11},{"text":"Host: We need a lot of healthcare workers.","offset":2343,"duration":1},{"text":"Andrej Karpathy: Yeah, so so they've already made those projections and I'm not sure actually 100% what the methodology was that they that they put into the projections. Um I guess I was interested to color things by like if people think that what's primarily being um developed now is this kind of like more digital AI that is kind of like almost like these ghost or spirit entities that can like interact in the digital world and uh manipulate a lot of like digital information.","offset":2344,"duration":23},{"text":"Andrej Karpathy: And they currently don't really have a physical embodiment uh or presence. And the physical stuff is probably going to go slightly slower because you're manipulating atoms. So flipping flipping bits and and the ability to copy paste digital information is like makes everything a million times faster than accelerating matter, you know?","offset":2367,"duration":17},{"text":"Andrej Karpathy: So um so energetically I just think we're going to see a huge amount of activity in the digital space, huge amount of rewriting, huge amount of activity boiling soup.","offset":2384,"duration":7},{"text":"Andrej Karpathy: And I think the we're going to see something that in the digital space goes at the speed of light compared to I think what's going to happen in the physical world to some extent if would be the extrapolation.","offset":2391,"duration":8},{"text":"Andrej Karpathy: And so I think like um there's currently kind of like I think an overhang where there can be like a lot of unhobbling almost potentially of like a lot of digital information processing that used to be done by computers and people.","offset":2399,"duration":14},{"text":"Andrej Karpathy: And now with AIs as like a third kind of manipulator of digital information there's going to be a lot of refactoring in those in those uh disciplines. Um but the physical world is actually going to be I think behind that by some amount of time.","offset":2413,"duration":11},{"text":"Andrej Karpathy: And so I think what's really fascinating to me is like so that's why I was highlighting the professions that fundamentally manipulate digital information. This is work you could do from your home etc. because I feel like those will be like things will change.","offset":2424,"duration":12},{"text":"Andrej Karpathy: And that doesn't mean that there's going to be less of those jobs or more of those jobs because it that has to do with like demand elasticity and many other factors, but things will change in these professions because of these new tools and uh because of this upgrade to the nervous system of the human superorganism if you want to think of it that way.","offset":2436,"duration":15},{"text":"Host: Given the look you had at the data, do you have either any observations or um uh guidance for people facing the job market or thinking about what to study now or what skills to develop?","offset":2451,"duration":3},{"text":"Host: I mean we can all go get like I'm very thankful that I have to like meet people for my job right now. Uh we can be more physical, yeah.","offset":2454,"duration":15},{"text":"Andrej Karpathy: Could you do your work from home though? Uh I could.","offset":2469,"duration":3},{"text":"Host: I think there are relationship parts of it that are hard, but most of it I could.","offset":2472,"duration":5},{"text":"Andrej Karpathy: Yeah, I think it's really hard to tell because again like the job market is extremely diverse and I think the answers will probably vary, but to a large extent like these tools are extremely new, extremely powerful, and so just being you know just trying to keep up with it is like the first thing.","offset":2477,"duration":14},{"text":"Andrej Karpathy: Um and uh yeah because I think a lot of people kind of like dismiss it—","offset":2491,"duration":2},{"text":"Host: Or they're afraid of it.","offset":2493,"duration":1},{"text":"Andrej Karpathy: —or they're afraid of it etc. which is totally understandable of course. Yeah I think like um it's fundamentally an empowering tool at the moment.","offset":2494,"duration":8},{"text":"Andrej Karpathy: Um and these jobs are bundles of tasks, and some of these tasks can go a lot faster, and so people should think of it as primarily a tool that it is right now. Um and I think the long-term future of that is uncertain.","offset":2502,"duration":9},{"text":"Andrej Karpathy: Yeah it's kind of really hard to forecast to be honest and like I'm not professionally like doing that really and I think this is a job of like economists to do properly.","offset":2511,"duration":9},{"text":"Host: You are an engineer though, uh and like one thing I thought was interesting is that like the the demand for engineering jobs is continuing to increase.","offset":2520,"duration":8},{"text":"Host: Um I I can't tell if that's like a temporary phenomenon I'm not sure how I feel about it yet, do you know?","offset":2528,"duration":5},{"text":"Andrej Karpathy: Yeah, that's like the demand elasticity almost. Like uh software was scarce, right? And so the reason we don't have more demand for software is just scarcity and it's too expensive.","offset":2533,"duration":8},{"text":"Host: It's too expensive, yeah.","offset":2541,"duration":1},{"text":"Andrej Karpathy: So if the barrier comes down then actually you have the Jevons paradox which is like, you know, actually the demand for software actually goes up. It's cheaper and there's more more for it, more powerful.","offset":2542,"duration":7},{"text":"Andrej Karpathy: The classical example of this always is the ATMs and the bank tellers. Because there was a lot of like fear that uh ATMs and computers basically uh would displace tellers, but what happened is they made like the cost of operation of uh of a bank branch much cheaper and so there were more bank branches so there were more tellers is like the canonical example people cite.","offset":2549,"duration":22},{"text":"Andrej Karpathy: But basically it's just Jevons paradox. Like something becomes cheaper so there's a lot of unlocked demand for it. So I do think that that's probably I do have like a cautiously optimistic view of this in software engineering where I do think the uh it does seem to me like the demand for software will be extremely large.","offset":2571,"duration":17},{"text":"Andrej Karpathy: Um and it's just become a lot cheaper. And um so I do think that for quite some time, um it's very hard to forecast, but it does seem to me like right now at least locally there's going to be more demand for software.","offset":2588,"duration":10},{"text":"Andrej Karpathy: Uh because software is amazing. It's like, you know, digital information processing, you're not forced to use like arbitrary tools that were given to you that are imperfect in various ways. You're not forced to subscribe to what exists.","offset":2598,"duration":12},{"text":"Andrej Karpathy: Uh code is now ephemeral and it can change and it can be modified. Um and so I think there's going to be a lot of activity in the digital space to like rewire everything in a certain sense, and I think it's going to create a lot of demand for for this kind of stuff.","offset":2610,"duration":13}],"startTime":2272},{"title":"The Conundrum of Working at Frontier Labs","summary":"Andrej reflects on the tension of working at a frontier AI lab versus operating as an independent researcher. He discusses balancing the need to stay connected to cutting-edge capabilities against the desire for unconstrained alignment with humanity.","entries":[{"text":"Andrej Karpathy: I think long term, uh yeah obviously even with AutoResearch like OpenAI or or, you know, Anthropic or these other labs like they're employing what like a thousand something researchers, right? These researchers are basically like glorified AutoResearcher—","offset":2623,"duration":16},{"text":"Host: You know?","offset":2639,"duration":1},{"text":"Andrej Karpathy: They're like automating themselves away like actively and this is like the thing they're all trying to do.","offset":2640,"duration":4},{"text":"Host: Yeah. Some of those researchers also fear fear the psychosis, right? Because they can it's working.","offset":2644,"duration":7},{"text":"Host: And so they're like uh it's over for me too.","offset":2651,"duration":1},{"text":"Andrej Karpathy: I did spend a bunch of time going around OpenAI and I was like, you guys realize if we're successful like we're all out of job, like like just going we're just building automation for Sam or something like that, like oh or the board I'm not sure, but like uh just building this automation for yeah the board or the CEO or something like that and we're all out of our job and maybe contributing on sides.","offset":2652,"duration":20},{"text":"Andrej Karpathy: And so yeah it's kind of un-unnerving from that perspective.","offset":2672,"duration":4},{"text":"Host: Is it okay if I ask a NOMS question? Um you know you could be doing that, right? AutoResearching with a lot of compute scale and a bunch of colleagues at one of the frontier labs. Like why not?","offset":2676,"duration":9},{"text":"Andrej Karpathy: Well I was there for a while, right? Like and I did re-enter. So to some extent I agree and I think that there are many ways to slice this question. It's a very loaded question a little bit.","offset":2685,"duration":9},{"text":"Andrej Karpathy: Um I will say that I feel very good about like what people can contribute and their impact uh outside of the frontier labs obviously.","offset":2694,"duration":6},{"text":"Andrej: ...not in the industry, but also in like more ecosystem level roles. Um, so your role, for example, is more like ecosystem level. My role currently is also kind of more on ecosystem level. And I feel very good about like impact that people can have in those kinds of roles.","offset":2700,"duration":12},{"text":"Andrej: I think conversely, there's there are definite problems in my mind for um basically aligning yourself way too much with the frontier labs too. So fundamentally, I mean, you're, you have a huge amount of financial incentive to um with these frontier labs.","offset":2712,"duration":12},{"text":"Andrej: And by your own admission, the the AIs are going to like really change humanity and society in very dramatic ways, and here you are basically like building the technology and benefiting from it, like and being like very allied to it through financial means.","offset":2724,"duration":17},{"text":"Andrej: Like this was the conundrum that was in um at the heart of, you know, how OpenAI was started in the beginning, like this was the conundrum that were trying to solve. Um, and so, you know, that so it's kind of...","offset":2741,"duration":10},{"text":"Host: It's still not resolved.","offset":2751,"duration":1},{"text":"Andrej: The conundrum is still not like fully resolved. So that's number one. You can't you're not a completely free agent, and you can't actually like be part of that conversation in a fully autonomous, um, free way. Like if you're inside one of the frontier labs, like there's some things that you can't say,","offset":2752,"duration":18},{"text":"Andrej: ...and conversely, there are certain things that the organization wants you to say, and, you know, they're not going to twist your arm, but you feel the pressure of like what you should be saying, you know, because like obviously, otherwise, like really awkward conversations, strange side-eye, like what are you doing, you know?","offset":2770,"duration":11},{"text":"Andrej: So you can't like really be an independent agent. And I feel like a bit more like aligned with humanity in certain sense outside of the frontier lab, because I don't I'm not subject to those pressures almost, right? And I can say whatever I want, or...","offset":2781,"duration":13},{"text":"Andrej: Yeah, I would say in the frontier labs, like, um, you can have like impact there, of course, as well. So um, but there's many researchers, and maybe you're one of them, maybe your ideas are really good, etc.","offset":2794,"duration":10},{"text":"Andrej: Maybe there's a lot of decision making to to do, and you want to be in a position where you are in the room with those conversations when they come up. I do think that currently the stakes are like overall fairly low, and so everything is kind of like nice.","offset":2804,"duration":10},{"text":"Andrej: But ultimately, at the end of the day, like when the stakes are really high, etc., if you're an employee at an organization, I don't actually know how much sway you're going to have on the organization, what it's going to do. Like fundamentally, at the end of the day, um, it's you're not like really in charge.","offset":2814,"duration":14},{"text":"Andrej: You're like in the room and you're contributing ideas, but you're not like really in charge of that entity that you're that you're a part of. So those are like some sources of misalignment, I think, to some extent.","offset":2828,"duration":10},{"text":"Andrej: I will say that like in one way I do agree a lot with that sentiment that um I do feel like in the like the labs for better or worse, they're opaque and a lot of work is there, and they're kind of like at the edge of capability and what's possible,","offset":2838,"duration":14},{"text":"Andrej: ...and they're working on what's coming down the line. And I think if you're outside of the frontier lab, uh your your judgment fundamentally will start to drift, because you're not part of the, you know, what's coming down the line.","offset":2852,"duration":12},{"text":"Host: Right.","offset":2864,"duration":1},{"text":"Andrej: And so I feel like my judgment will inevitably start to drift as well, and I won't actually have an understanding of how these systems actually work under the hood. It's an opaque system. Um, I won't have a good understanding of how it's going to develop, and etc.","offset":2865,"duration":12},{"text":"Andrej: And so I do think that in that sense, I agree, and something I'm nervous about. I think it's worth basically basically being in touch with what's actually happening, and actually being in the frontier lab.","offset":2877,"duration":10},{"text":"Andrej: And if if some of the frontier labs would have me come for, you know, some amount of time and do really good work for them, and then maybe come in...","offset":2887,"duration":6},{"text":"Host: Guys, he's looking for a job! This is super exciting.","offset":2893,"duration":2},{"text":"Andrej: ...then I think that's maybe a good setup, because I kind of feel like it kind of, um, you know, maybe that's like one way um to actually be connected to what's actually happening, but also not feel like you're necessarily fully controlled by by those entities.","offset":2895,"duration":11},{"text":"Andrej: So I think honestly, in my mind, like Noam can probably get do extremely good work at OpenAI, but also I think his most um impactful work could very well be outside of OpenAI.","offset":2906,"duration":13},{"text":"Host: Noam, that's a call to be an independent researcher with AutoResearch.","offset":2919,"duration":2},{"text":"Andrej: Yeah, there's many things to do on the outside, and it's a and I think ultimately I think the ideal solution maybe is like yeah, going back and forth, uh or um yeah, and I think fundamentally you can have really amazing impact in both places.","offset":2921,"duration":11},{"text":"Andrej: So very complicate- I don't know, like it's a very loaded question a little bit, but I mean I joined the frontier lab and now I'm outside, and then maybe in the future I'll want to join again, and I think um that's kind of like how I look at it.","offset":2932,"duration":13}],"startTime":2623},{"title":"The Trajectory of Open Source AI","summary":"The conversation turns to the evolving gap between closed frontier models and open-source alternatives. Andrej argues that open-source AI is functionally acting as the \"Linux\" of intelligence and is crucial for avoiding a dangerous centralization of power.","entries":[{"text":"Host: One question related to what visibility does the world or the AI ecosystem have into um the frontier is like how how close open source is to the frontier, um and how sustainable that is.","offset":2945,"duration":14},{"text":"Host: I I think it is quite surprising, the entire sequence of events actually, from like having a handful of Chinese models and global models, and I think people are going to continue releasing here in the near term that are closer than much of the industry anticipated from a capability perspective.","offset":2959,"duration":17},{"text":"Host: Um, I don't know if you're surprised by that, you're a long term contributor to open source, like what's your prediction here?","offset":2976,"duration":6},{"text":"Andrej: Yeah, so roughly speaking, basically, the um, yeah, the closed models are ahead, but like people are monitoring the number of months that sort of like open source models are behind.","offset":2982,"duration":10},{"text":"Host: And it started with there's nothing, and then it went to 18 months, and now it's like our convergence.","offset":2992,"duration":4},{"text":"Andrej: Yeah, and then a convergence, right? So um, maybe they're behind by like what is the latest? Maybe like eight months, six months, eight months kind of right now. Yeah, I'm a huge fan of open source, obviously.","offset":2996,"duration":10},{"text":"Andrej: So for example, in operating systems, you have like closed source like, you know, Windows and macOS, these are large software projects, kind of like what LLMs are going to become. And there's Linux.","offset":3006,"duration":9},{"text":"Andrej: But Linux is very easy, like actually Linux is an extremely successful project. It runs on the vast majority of computers. Like last time I checked, was it like 60 percent or something like run Linux?","offset":3015,"duration":10},{"text":"Andrej: Um, and that's because there is a need in industry to have a common open platform that everyone feels um sort of safe using. I would say like the industry has always felt a demand for that kind of a project to exist.","offset":3025,"duration":11},{"text":"Andrej: Um, and I think the same is true now, and that's why businesses actually want- there's demand for this kind of a um a thing to exist. The big difference is that everything is capital um there's large CapEx that goes into this. Um, so I think that's where things like fall apart a little bit, and make it a bit harder to to compete in some sense.","offset":3036,"duration":18},{"text":"Andrej: Um, I I do think that the current models are very good. The other thing that I think is like really interesting is that for the vast majority of like consumer use cases and things like that, even like current open source models are actually quite good, I would say.","offset":3054,"duration":12},{"text":"Andrej: And I think like if you go forward like more um more years, it does seem to me like a huge amount of like simple use cases are going to be well covered and actually even run locally.","offset":3066,"duration":11},{"text":"Andrej: Um, but there's going to be always like some demand for like frontier intelligence, and that that can actually be an extremely large piece of the pie. But it could be that the frontier, the need for frontier intelligence is going to be like, you know, Nobel Prize kind of work, or like let's move Linux from C to Rust is going to be like bigger projects, you know, like scoped in that kind of a way.","offset":3077,"duration":19},{"text":"Andrej: And there's going to be maybe more um and maybe that's where a lot of the frontier closed intelligences were going are going to be interacting with. And open source kind of like going to eat through a lot of the more basic use cases or something like that.","offset":3096,"duration":14},{"text":"Andrej: You know, at some point, what is frontier today is going to be, you know, probably later this year what's frontier today in terms of what I'm using right now from the closed labs might be open source, and that's going to be doing a lot of work.","offset":3110,"duration":11},{"text":"Andrej: So I kind of expect that this dynamic will actually basically continue. Like we'll have frontier labs that have closed um AIs that are kind of like these oracles, and then we'll have open source kind of like behind by some amount of months.","offset":3121,"duration":10},{"text":"Andrej: And I kind of expect that to uh to continue. And I actually think that's like a pretty pretty good setup um overall, um because I I'm a little bit hesitant of having um I don't actually think it's like structurally, I think there's some systemic risk attached to just having intelligences that are closed, and that's like that's it.","offset":3131,"duration":16},{"text":"Host: Mm-hmm.","offset":3147,"duration":0},{"text":"Andrej: And I think that that's a, you know, centralization has a very poor track record in my view, um in the in the past.","offset":3147,"duration":7},{"text":"Host: You mean like in political or economic systems? In general?","offset":3154,"duration":2},{"text":"Andrej: Yes. Exactly.","offset":3156,"duration":1},{"text":"Host: Spoken like an Eastern European, yes.","offset":3157,"duration":3},{"text":"Andrej: Okay, exactly. I think there's like a lot of pretty bad precedents, and so I want there to be a thing that is maybe not at the edge of capability because it's new and unexplored etc., but I want there to be a thing that's behind and that is kind of like a common working space for intelligences that the entire industry has access to. Yeah, that seems to me like a pretty decent power balance for the industry.","offset":3160,"duration":16},{"text":"Host: Yeah.","offset":3176,"duration":5},{"text":"Andrej: Yeah. I also think there's just like there are many problems to solve, right? Like if you keep advancing intelligence from the frontier, we can do new things and there are a lot of like very big problems for humanity, right?","offset":3181,"duration":11},{"text":"Host: Yeah.","offset":3192,"duration":1},{"text":"Andrej: And so like it seems that that will continue to be a very expensive game, and so I want to like root for labs that are doing that, because there are problems we cannot solve without continuing to advance the models in a very expensive way.","offset":3193,"duration":11},{"text":"Host: And yet, as you point out, like if what we have today as frontier is open, that's a lot of capability.","offset":3204,"duration":9},{"text":"Andrej: Yeah.","offset":3213,"duration":1},{"text":"Host: Right. And and so I think, you know, the power of that or the democratization of that seems like very useful and also healthy.","offset":3214,"duration":8},{"text":"Andrej: Yeah. I think basically by accident we're actually like in an okay spot in an optimal yeah, yeah. By accident we are happen to be in a good spot in a certain sense.","offset":3222,"duration":10},{"text":"Host: Um well, and and to some degree, the the longer this endures, like this dynamic, um the the healthier of a spot like the ecosystem might be in, right? Because you have more and more area under the curve.","offset":3232,"duration":13},{"text":"Andrej: And I will say that even on the closed side, I almost feel like it's been like even further centralizing in recently, because I think a lot of the frontrunners are like not necessarily like the top tier.","offset":3245,"duration":9},{"text":"Andrej: And so um yeah, I like in that sense I think it's um not super ideal. I would love there to be more more frontier labs because, yeah, I'm like by default very suspicious of like um I want there to be more people in the room, I want-","offset":3254,"duration":13},{"text":"Andrej: I think like in machine learning, ensembles always outperform any individual model, and so I want there to be ensembles of people thinking about all the hardest problems, and I want there to be ensembles of people in a room when they um to be all well-informed and to make all those decisions, you know, so...","offset":3267,"duration":17},{"text":"Andrej: I don't want it to be like a closed doors with two people or three people. I feel like that's like not a good not a good future. I almost wish like there were more labs is long story short, and I all- I do think that the open source um has a uh has a place to play. I hope it sticks around, and I basically- it's currently slightly behind and that's actually kind of a good thing.","offset":3284,"duration":15}],"startTime":2945},{"title":"Robotics and Interfacing with the Physical World","summary":"Andrej compares the timeline of AI in the physical world to digital advancements, explaining why interacting with atoms will lag behind bits. However, he notes that creating interfaces to feed physical data to models will be a massive upcoming opportunity.","entries":[{"text":"Host: Okay, you worked on the precursor to generalized robotics, autonomy, um in cars, right? Um, a a lot has happened in the last couple months with robotics companies as well, like acceleration of really impressive generalization of environment, of tasks, like increasing long horizon tasks, lots of money going into the space. Like is it going to happen? Has anything in your view changed recently?","offset":3299,"duration":29},{"text":"Andrej: Um, so like my view is kind of informed by what I saw in self-driving. And I do feel like self-driving is the first robotics application. So probably what I saw is at the time, like 10 years ago, there were a large number of startups, and I kind of feel like um like most of them basically didn't long-term make it.","offset":3328,"duration":17},{"text":"Andrej: Um, and what I saw is that like a lot of capital expenditure had to go in, and a lot of time. And so um I think it like I think robotics because it's so difficult and so messy and requires huge amount of capital investment and a lot of like conviction, um just it's like a big problem.","offset":3345,"duration":15},{"text":"Andrej: And I think atoms are really hard. So I kind of feel like they will lag- it will lag behind what's going to happen in the digital space. And in digital space, there's going to be a huge amount of unhobbling.","offset":3360,"duration":10},{"text":"Andrej: Basically like things that weren't super efficient becoming a lot more efficient by like a factor of a hundred because bits are so much easier. And so I think currently in terms of what's going to change and like where the activity is, I kind of feel like digital space is going to like change a huge amount, and then the physical space will lag behind.","offset":3370,"duration":17},{"text":"Andrej: And what I find very interesting is like this interface in between them as well. Because I think in this like if we do have more agents acting on behalf of humans and more agents kind of like talking to each other and and doing tasks and participating in the kind of economy of agents etc., um you're going to run out of things that you're going to do purely in the digital space.","offset":3387,"duration":20},{"text":"Andrej: At some point you have to go to the universe and you have to ask it questions. Um you have to run an experiment and see what the universe tells you to get back to learn something. And so we currently have a huge amount of like digital work uh because there's an overhang in how much we collectively thought about what already is digital.","offset":3407,"duration":18},{"text":"Andrej: So we just didn't have enough thinking cycles among the humans to think about all the information that is already digital and already uploaded. Um and so we're going to start running out of stuff that is actually like um already up- uploaded. Uh so you're going to at some point read all the papers and process them and have some ideas about what to try.","offset":3425,"duration":16},{"text":"Andrej: But um yeah, we're just going- I don't actually know how much you can like get intelligence that's like fully closed off and with just the information that's available to it, you know? And so I think what's going to happen is first there's going to be huge amount of unhobbling, and I think there's huge amount of work there.","offset":3441,"duration":14},{"text":"Andrej: Then actually it's going to move to like the interfaces between physical and digital. So I and that's like sensors of like seeing the world and actuators of like doing something to the world.","offset":3455,"duration":9},{"text":"Andrej: So I think a lot of interesting companies will actually come from that interface of like can we feed the superintelligence in a certain sense data, and can we actually like take data out and manipulate the physical world um per its bidding, if you want to like anthropomorphize the whole thing, right?","offset":3464,"duration":16},{"text":"Andrej: And then the physical world actually I almost feel like the total addressable market etc. in terms of like the amount of work and so on is is massive, possibly even much larger maybe what can happen in digital space.","offset":3480,"duration":12},{"text":"Andrej: So I actually think it's like a much bigger opportunity as well, but um I do feel like it's huge amount of work and in my my view the atoms are just like a a million times harder. So um so it will lag behind, but it's also I think a little bit of a bigger market.","offset":3492,"duration":13},{"text":"Andrej: So it's kind of like uh yeah I think the opportunity is kind of like follow that kind of trajectory. So right now this digital is like my main interest, then interfaces would be like after that, and then maybe like some of the physical things, um like their time will come and they'll be huge uh when they do come.","offset":3505,"duration":17},{"text":"Host: Well it's an interesting framework for it too because uh certain things, not the things I'm working on right now, but certain things are much easier even in the world of atoms, right? Like if you just think about like read and write to the physical world, like read, like sensors, cameras, like there's a lot of existing hardware and you can imagine like enriching agent capabilities or capturing a lot of new data if you're just clever about it and like you don't necessarily have to invest a lot to like get something valuable.","offset":3522,"duration":28},{"text":"Andrej: Yeah.","offset":3550,"duration":1},{"text":"Host: Yeah.","offset":3551,"duration":1},{"text":"Andrej: So like examples of this that I saw for example are, you know, um a friend of mine, Liam, is run- is a CEO of Periodical. Um I visited them last week, so it's just on top of mind. Like they're trying to do auto research for material science. Um and so in that case it's like the sensors to the intelligence are actually like pretty expensive lab equipment.","offset":3552,"duration":16},{"text":"Andrej: And the same is true in biology, I think a lot of people are very interested in engineering biology, and, you know, the sensors will be more than just like video cameras if that makes sense. And then the other thing I I saw, for example, is companies that are trying to have um like you basically pay people for training data...","offset":3568,"duration":14},{"text":"Host: Yeah. Programmatically.","offset":3582,"duration":1},{"text":"Andrej: ...as an example to feed... Yeah, to feed- to feed the borg. Um and so like these are all examples of like sensors in a certain sense. So they take many diverse shapes and forms, if that makes sense.","offset":3583,"duration":9},{"text":"Host: Hmm. Yeah, so I'm looking forward to the point where I can ask for a task in the physical world and I can put a price on it and just tell the agent like, you know, you figure out how to do it. Go get the data.","offset":3592,"duration":12},{"text":"Andrej: I'm actually kind of surprised we don't have enough like information markets. Like for example, if Polymarket or other betting markets or even stocks etc., if they have so much autonomous activity and rising amount of activity, like uh why should- like for example, if Iran was just happening now, like how come there isn't a process where like taking a photo or video from somewhere in Tehran should cost like 10 bucks.","offset":3604,"duration":19},{"text":"Andrej: Like someone should be able to pay for that, you know? And that's an example of like feeding the intelligence. There's not going to be a human looking at it, it's going to be like agents who are trying to guess the betting games and stock markets and so on.","offset":3623,"duration":12},{"text":"Andrej: Hmm. So I kind of feel like the agentic vibe is still like fairly new that there's no like mechanisms for this, but this is an example of what I think might happen. There's a good um book that maybe is inspiring called Daemon. Uh-huh. You've potentially read it?","offset":3635,"duration":12},{"text":"Host: In Daemon the intelligence um ends up like puppeteering almost a little bit like humanity in certain sense, you know? And so humans are kind of like its actuators, but humans are also like its sensors. Um and so maybe I think like collectively like society will kind of like reshape in a certain way in uh to serve that kind of a uh that will kind of like end up happening collectively across the industry where, yeah, there's just a lot more automation and it has certain needs and kind of humans will be serving those needs of that of that machine, not necessarily like to each other.","offset":3647,"duration":24},{"text":"Host: Well we were um on this very specific point of uh like missing pieces of training data, we needed um we needed something like auto research, right? Like we need the training cycle or the SFTP piece to be um far more mechanized.","offset":3671,"duration":14},{"text":"Andrej: Uh-huh. For for which part?","offset":3685,"duration":2},{"text":"Host: In order to make the um collection, like to in order to take the human out of the loop to ask for a task that is just like improve my model quality with new data, right?","offset":3687,"duration":9},{"text":"Andrej: Um, yes.","offset":3696,"duration":1},{"text":"Host: Does that make sense to you? Like we um, if you can't have the model do the training runs by itself, then your ability to do this as a like closed-loop task with uh by pricing data is um more challenged.","offset":3697,"duration":14},{"text":"Andrej: Uh, yes, 100%. Yeah. But the thing is-","offset":3711,"duration":3},{"text":"Host: But now we go.","offset":3714,"duration":2},{"text":"Andrej: The thing is for LLM training, it actually is like very easily it like really fits the paradigm. Um, so you'd actually expect-","offset":3716,"duration":7},{"text":"Host: Yeah, clean metric.","offset":3723,"duration":1},{"text":"Andrej: Yeah, like LLM training actually fits the paradigm really well, really easily. Like all the optimization of all the code and so it runs faster, and then you also have like metrics that you can optimize against.","offset":3724,"duration":9},{"text":"Andrej: I do think that if you had an autonomous loop over those metrics, there's going to be a lot of like goodhearting going on where the system will like overfit to those metrics. And so but then you can use the system to devise more metrics and you just have really good coverage. So it's kind of hard to tell but um in a certain sense it's like a pretty pretty good fit.","offset":3733,"duration":17}],"startTime":3299},{"title":"MicroGPT and the Future of AI Education","summary":"Andrej discusses MicroGPT, a project distilling neural network training into 200 lines of code. He explains how AI agents are fundamentally reshaping education by serving as personalized, infinitely patient teachers, shifting the focus from human-readable documentation to agent-readable instructions.","entries":[{"text":"Host: I want to talk about a little um tiny side project you have before we end. Um tell me about the MicroGPT effort.","offset":3750,"duration":8},{"text":"Andrej: Oh yeah. Okay, so MicroGPT. So, I have this like running obsession of like maybe a decade or two of just like simplifying and boiling down the basically LLMs uh to like their bare essence. And I've had a number of projects along these lines, so like NanoGPT and um MakeMore and uh Micro- Micrograd etc.","offset":3758,"duration":20},{"text":"Andrej: So I feel like MicroGPT is now the state of the art of me trying to like just boil it down to the essence. Because the thing is like training neural nets and LLMs specifically um is huge amount of code, but all of that code is actually complexity from efficiency.","offset":3778,"duration":13},{"text":"Host: Hmm.","offset":3791,"duration":1},{"text":"Andrej: It's just because you need it to go fast. If you don't need it to go fast and you just care about the algorithm, then that algorithm actually is 200 lines of Python. Very simple to read. And this includes comments and everything.","offset":3792,"duration":10},{"text":"Andrej: Um, because you just have like uh your data set which is a text, um and you need your neural network architecture which is like 50 lines, you need to do your forward pass, and then you have to do your backward pass to calculate the gradients.","offset":3802,"duration":9},{"text":"Andrej: And so an auto-grad engine uh to calculate the gradients like 100 lines, and then you need an optimizer, an Adam, for example, uh which is like again 10 lines, really. And so putting everything together in a training loop is like, yeah, 200 lines.","offset":3811,"duration":12},{"text":"Andrej: And what was interesting to me like normally before like maybe a year ago or more, if I had come up with MicroGPT, I would be tempted to basically explain to people like have a video like stepping through it or something like that, um and I actually tried to make that video a little bit, and I tried to make like a little guide to it and so on.","offset":3823,"duration":16},{"text":"Andrej: But I kind of realized that this is is not really is not really adding too much because people because it's already so simple that it's 200 lines, that anyone could ask their agent to explain it in various ways and the agents- like I'm not explaining to people anymore, I'm explaining it to agents.","offset":3839,"duration":16},{"text":"Andrej: If you can explain it to agents, then agents can be the router and they can actually target it to the human in their language with infinite, um you know, patience and uh just at their capability and so on.","offset":3855,"duration":11},{"text":"Host: Right, if I don't understand um this particular function, I can ask the agent to explain it to me like three different ways, and I'm not going to get that from you.","offset":3866,"duration":7},{"text":"Andrej: Yeah. Exactly. Yeah. And so I kind of feel like, you know, what is education? Like it used to be guides, it used to be lectures, it used to be this thing, but now I feel like now more I'm explaining things to agents.","offset":3873,"duration":8},{"text":"Andrej: And maybe I'm coming up with skills um where like um so basically skill is just a way to instruct the agent how to teach the thing. So maybe I could have a skill for MicroGPT of the progression I imagine the agent should take you through if you're interested in understanding the codebase.","offset":3881,"duration":13},{"text":"Andrej: And it's just like hints to the model to like oh first start off with this and then with that, and so I could just script the curriculum a little bit as a skill. Um so so I don't feel like um yeah I feel like there's going to be less of like explaining things directly to people and it's going to be more of just like does the agent get it?","offset":3894,"duration":16},{"text":"Andrej: And if the agent gets it they'll do the explanation. And we're not fully there yet because they I still can I still think I can probably explain things a little bit better than the agents, but I still feel like the models are improving so rapidly that um I feel like it's a losing battle to some to some extent.","offset":3910,"duration":15},{"text":"Andrej: Um and so I think education is going to be kind of like reshuffled by this uh quite substantially um where it's the end of like teaching each other things almost a little bit. Like if I have a uh library, for example, of code or something like that, it used to be that you have documentation for other people who are going to use your library.","offset":3925,"duration":16},{"text":"Andrej: But like you shouldn't do that anymore. Like you should have instead of HTML documents for humans, you have markdown documents for agents, because if agents get it, then they can just explain all the different parts of it.","offset":3941,"duration":9},{"text":"Andrej: So it's this redirection through agents, you know? Um and that's like why so I think we're going to see a lot more of that playing out.","offset":3950,"duration":10},{"text":"Host: Well we'll see if the great teachers know like to develop intuition for how to explain things to agents differently.","offset":3960,"duration":5},{"text":"Andrej: Oh yeah. Ultimately, so for example, MicroGPT, like I asked I tried to get an agent to write MicroGPT. So I told it like try to boil down the simplest things, like try to boil down micro- neural network training to the simplest thing and it can't do it.","offset":3965,"duration":14},{"text":"Andrej: Like MicroGPT is like my is it's like my end of my obsession. It's the 200 lines. I thought about this for a long time. I've obsessed about this for a long time. This is this is the solution. Trust me it can't get simpler.","offset":3979,"duration":10},{"text":"Andrej: And this is this is my value add. Everything else like agent gets it. It just can't come up with it but it totally gets it and understands why it's done in a certain way, etc. So like my contribution is kind of like these few bits, but everything else in terms of like the education that goes on after that is like not my domain anymore.","offset":3989,"duration":17},{"text":"Andrej: So maybe yeah it's like education kind of changes in those ways where you kind of have to infuse the few bits that you feel strongly about the curriculum or the the better way of explaining it or something like that. The things that agents can't do is your job now.","offset":4006,"duration":13},{"text":"Host: Hmm.","offset":4019,"duration":1},{"text":"Andrej: The things that agents can do they can probably do better than you or like very soon. And so you should be strategic about what you're actually spending time on.","offset":4020,"duration":7}],"startTime":3750},{"title":"Podcast Outro","summary":"The host thanks Andrej for his time and provides sign-off details, social media handles, and website links for the podcast.","entries":[{"text":"Host: Well we appreciate the few bits. Thank you Andrej.","offset":4027,"duration":4},{"text":"Andrej: Okay.","offset":4031,"duration":1},{"text":"Host: Find us on Twitter at NoPriorsPod. Subscribe to our YouTube channel if you want to see our faces. Follow the show on Apple Podcasts, Spotify, or wherever you listen. That way you get a new episode every week. And sign up for emails or find transcripts for every episode at no-priors.com.","offset":4032,"duration":15}],"startTime":4027}],"entries":[{"text":"Andrej Karpathy: Code's not even the right verb anymore, right? But I have to, um, express my will to my agents for 16 hours a day. Manifest.","offset":0,"duration":10},{"text":"Andrej Karpathy: How can I have not just a single session of, you know, Claude code or Codex or some of these agent harnesses, how can I have more of them? How can I do that appropriately?","offset":10,"duration":4},{"text":"Andrej Karpathy: The agent part is now taken for granted. Now the claw-like entities are taken for granted, and now you can have multiple of them, and now you can have instructions to them, and now you can have optimization over the instructions.","offset":14,"duration":9},{"text":"Andrej Karpathy: But there—I mean, this is what gets to the psychosis, is that this is like infinite, and everything is skill issue.","offset":23,"duration":7},{"text":"Host: Hi listeners, welcome back to No Priors. Today I'm here with Andrej Karpathy, and we have a wide-ranging conversation for you about code agents, the future of engineering, and AI research.","offset":30,"duration":11},{"text":"Host: How more people can contribute to research, what's happening in robotics, his prediction for how agents can reach out into the real world, and education in this next age. Welcome, Andrej.","offset":41,"duration":13},{"text":"Host: Andrej, thanks for doing this.","offset":54,"duration":1},{"text":"Andrej Karpathy: Yeah, thank you for having me.","offset":55,"duration":2},{"text":"Host: Uh, so it's been a very exciting couple of months in AI.","offset":57,"duration":2},{"text":"Andrej Karpathy: Oh yeah, you could say that.","offset":59,"duration":2},{"text":"Host: I remember, um, walking into the office at some point and you were like, really locked in, and I was asking what you were up to and you're like, \"I just—I have to code for 16 hours a day,\" or code's not even the right verb anymore, right?","offset":61,"duration":12},{"text":"Host: But I have to, um, express my will to my agents for 16 hours a day. Manifest. Um, because like there's been a jump in capability. Uh, what's happening? Tell me about your experience.","offset":73,"duration":12},{"text":"Andrej Karpathy: Yeah, I kind of feel like I was just in this perpetual—I still am often—in this state of AI psychosis just like all the time, uh, because there was a huge unlock in what you can achieve as a person, as an individual, right?","offset":85,"duration":14},{"text":"Andrej Karpathy: Because you were bottlenecked by, you know, your typing speed and so on. But now with these agents, it really—I would say in December is when it really just—something flipped, where I kind of went from 80/20 of like, you know, uh, to like 20/80 of writing code by myself versus just delegating to agents.","offset":99,"duration":15},{"text":"Andrej Karpathy: And I don't even think it's 20/80 by now, I think it's a lot more than that. I don't think I've typed like a line of code probably since December basically. Uh, which is like an extremely large, uh, change.","offset":114,"duration":14},{"text":"Andrej Karpathy: Um, I was talking to it like for example, I was talking about it to for example my parents and so on, and I don't think like a normal person actually realizes that this happened or how dramatic it was.","offset":128,"duration":10},{"text":"Andrej Karpathy: Like literally like if you just find a random software engineer or something like that at their—at their desk and what they're doing, like their default workflow of, you know, building software is completely different as of basically December.","offset":138,"duration":14},{"text":"Andrej Karpathy: Uh, so I'm just like in this state of psychosis of trying to figure out like what's possible, uh, trying to push it to the limit. How is—how can I have not just a single session of, you know, um, Claude code or Codex or some of these agent harnesses?","offset":152,"duration":12},{"text":"Andrej Karpathy: How can I have more of them? How can I do that appropriately? And then how can I use these claws? What are these claws? Uh, and uh, so there's like a lot of new things. I want to be at the forefront of it, you know?","offset":164,"duration":10},{"text":"Andrej Karpathy: And I'm very antsy that I'm not at the forefront of it. And I see lots of people on Twitter doing all kinds of things and they all sound like really good ideas, and I need to be at the forefront or I feel extremely nervous.","offset":174,"duration":6},{"text":"Andrej Karpathy: And so I guess I'm just in this psychosis of like what's possible, like because it's unexplored fundamentally.","offset":180,"duration":2},{"text":"Host: Well, if you're nervous, the rest of us are—are nervous. We have a—uh, we have a team that we work with at Conviction that their setup is everybody is like, you know, none of the engineers write code by hand and they're all microphoned and they just like whisper to their agents all the time.","offset":182,"duration":17},{"text":"Host: It's the strangest work setting ever, uh, and I thought they were crazy and now I like fully accept I was like, oh this was the way. Like you're just ahead of it. Um, what—uh, how do you think about your own capacity now to like explore or to do new projects? Like what—what is it limited by?","offset":199,"duration":18},{"text":"Andrej Karpathy: Yeah, what is it limited by? Uh, just I think everything, like so many things, even if they don't work, I think to a large extent you feel like it's skill issue. It's not that the capability's not there.","offset":217,"duration":12},{"text":"Andrej Karpathy: It's that you just haven't found a way to string it together of what's available. Like I just didn't give good enough instructions in the agents' MD file or whatever it may be. I don't have a nice enough memory tool that I put in there or something like that.","offset":229,"duration":13},{"text":"Andrej Karpathy: So it all kind of feels like skill issue when it doesn't work to some extent. You want to see how you can paralyze them etc. and you want to be Peter Steinberg basically. Uh, so Peter is famous, he has a funny photo where he's in front of a monitor with lots of like—uh, he uses Codex.","offset":242,"duration":13},{"text":"Andrej Karpathy: So lots of Codex agents tiling the—the monitor, and they all take about 20 minutes if you prompt them correctly and you use the high effort, and so they all take about 20 minutes. So you have multiple, you know, 10, uh, repos checked out, and so he's just, um, going between them and giving them work.","offset":255,"duration":15},{"text":"Andrej Karpathy: It's just like you can—you can move in much larger macro actions. It's not just like here's a line of code, here's a new function, it's like here's a new functionality and delegate it to agent one.","offset":270,"duration":10},{"text":"Andrej Karpathy: Here's a new functionality that's not going to interfere with the other one, give it to agent two, and then try to, uh, review their work as best as you can depending on how much you care about that code.","offset":280,"duration":8},{"text":"Andrej Karpathy: Like what are these macro actions that I can like manipulate my software repository by? And like another agent is doing some like research, another agent is writing code, another one is coming up with a plan for some new implementation.","offset":288,"duration":13},{"text":"Andrej Karpathy: And so everything is just like happening in these like macro actions over your repository. Um, and you're just trying to become like really good at it and develop like a muscle memory for it is extremely, um—yeah, it's very rewarding number one because it actually works.","offset":301,"duration":14},{"text":"Andrej Karpathy: But it's also kind of like the new thing to learn. So that's why hence the psychosis.","offset":315,"duration":4},{"text":"Host: Yeah, I—I do feel like my instinct is like whenever I am waiting for an agent to complete something, the obvious thing to do is like well I can do more work, right?","offset":319,"duration":8},{"text":"Host: Like if I have access to more tokens then like I should just parallelize and tasks. And so that—that's very stressful because if you don't feel very bounded by your ability to spend on tokens, then you know you are the bottleneck in this system that is max capability.","offset":327,"duration":15},{"text":"Andrej Karpathy: Yeah, if you're not maximizing your subscription at least, and uh, so ideally for multiple agents, like if you run out of the quota on Codex you should switch to Claude or whatnot, I don't know, like that's what I've been trying to do a little bit.","offset":342,"duration":9},{"text":"Andrej Karpathy: And I feel nervous when I have subscription left over, uh, that just means I haven't maximized my token throughput. So I actually kind of experienced this when I was a PhD student, you would feel nervous when your GPUs are not running.","offset":351,"duration":8},{"text":"Andrej Karpathy: Like you have GPU capability and you're not maximized to the available flops to you. But now it's not about flops, it's about tokens. Uh, so what is your token throughput and what token throughput do you command?","offset":359,"duration":10},{"text":"Host: I would actually argue that it's very interesting that we had, you know, at least 10 years where in many engineering tasks people just didn't—they didn't feel compute bound, right?","offset":369,"duration":12},{"text":"Host: Um, and like the entire industry feels that now. They feel like—they felt resource bound. Uh, and now that you have this big capability jump, you're like, oh actually it's not, you know, my ability to access the compute anymore, like I—I'm the binding constraint.","offset":381,"duration":12},{"text":"Andrej Karpathy: Yeah, it's a skill issue, which is very empowering cause, uh, yeah cause you could be getting better. So that's why—that's why I think it's very addictive because there's unlocks when—when you get better.","offset":393,"duration":7},{"text":"Host: Where do you think it goes? Like if you just think about like okay, you know, Andrej's iterating and everybody else's for 16 hours a day getting better at using coding agents, like what does it look like in a year of like you've reached mastery?","offset":400,"duration":12},{"text":"Andrej Karpathy: Yeah, what does mastery look like, right? At the end of the year or like two, three, years, five years, ten years etc. Well I think everyone is basically interested in like going up the stack.","offset":412,"duration":9},{"text":"Andrej Karpathy: So I would say, yeah, it's not about a single session with your agent. Um, multiple agents, how do they collaborate and teams and so on. So everyone's trying to figure out what that looks like.","offset":421,"duration":8},{"text":"Andrej Karpathy: And then I would say Claw is also kind of an interesting direction because it really—when I say a Claw, I mean this like layer that uh kind of takes persistence to a whole new level.","offset":429,"duration":9},{"text":"Andrej Karpathy: Like it's something that like keeps looping, is—is um, it's not something that you are interactively in the middle of. It kind of like has its own little sandbox, its own little, you know, it kind of like does stuff on your behalf even if you're not looking kind of thing.","offset":438,"duration":10},{"text":"Andrej Karpathy: Um, and then also has like maybe more sophisticated memory systems etc. that are not yet implemented in agents. So, uh, Open Claw has a lot more sophisticated memory I would say than what you would get by default, uh, which is just a memory compaction when your context runs out, right?","offset":448,"duration":13},{"text":"Host: You think that's the piece that resonated for more users versus like perhaps like broader tool access?","offset":461,"duration":5},{"text":"Andrej Karpathy: For Open Claw?","offset":466,"duration":1},{"text":"Host: Yeah.","offset":467,"duration":1},{"text":"Andrej Karpathy: Uh, there's—like I think there's at least five things that resonated with users. Yeah, good job, Peter. I mean Peter has done a really amazing job.","offset":468,"duration":6},{"text":"Andrej Karpathy: Um, I saw him recently, uh, and I talked to him about it and I—he's very humble about it, but I think he innovated simultaneously in like five different ways and put it all together. Uh, so for example like the soul MD document, like he actually really crafted a personality that is kind of compelling and interesting.","offset":474,"duration":14},{"text":"Andrej Karpathy: And I feel like a lot of the current agents they don't get this correctly. I actually think Claude has a pretty good personality, it feels like a teammate. Uh, and uh, it's excited with you etc.","offset":488,"duration":10},{"text":"Andrej Karpathy: I would say, for example, Codex is a lot more dry, um, which is kind of interesting because in ChatGPT, Codex is like a lot more upbeat and highly sycophantic. But I would say Codex the coding agent is very dry.","offset":498,"duration":11},{"text":"Andrej Karpathy: It doesn't—it doesn't seem to care about what you're creating. It's kind of like, \"Oh, I implemented it.\" It's like, okay, but do you understand what we're building?","offset":509,"duration":6},{"text":"Host: It's true.","offset":515,"duration":1},{"text":"Andrej Karpathy: You know, it doesn't—um—and the other thing I would say is for example with Claude, I think they dialed the sycophancy fairly well, where when Claude gives me praise, I do feel like I slightly deserve it.","offset":516,"duration":9},{"text":"Andrej Karpathy: Um, because sometimes I kind of give it like not very well-formed thoughts, and uh I give it an idea that I don't think is fully baked and it doesn't actually react very strongly. It's like, \"Oh yeah, we can implement that.\"","offset":525,"duration":9},{"text":"Andrej Karpathy: But when it's a really good idea by my own account, it does uh seem to reward it a bit more, and so I kind of feel like I'm trying to like earn its praise, which is really weird.","offset":534,"duration":8},{"text":"Andrej Karpathy: And so I do think the personality matters a lot. Uh, and I think uh a lot of the other, uh, tools maybe don't appreciate it as much, and I think in this aspect also Peter really cares about this and so that was correct.","offset":542,"duration":7},{"text":"Andrej Karpathy: And then the memory system and then uh just you know he's just having fun with this. Um, and then the the single WhatsApp portal to all of the automation.","offset":549,"duration":9},{"text":"Host: Yeah. Is there something that you have done personally with your Claws beyond software engineering that you think is fun or interesting?","offset":558,"duration":9},{"text":"Andrej Karpathy: Yeah, so in January I had Claude—I went through a period of Claude psychosis, so I built a—um, I have a Claw basically that takes care of my home, and I call him Dobby the Elf Claw. Um, and uh basically I used uh the agents to find all of the smart home subsystems of my home on the local area network, which I was kind of surprised that worked out of the box.","offset":567,"duration":20},{"text":"Andrej Karpathy: Like I just told it that I think I have Sonos at home, like can you try to find it? And it goes and it did like IP scan of all of the um, basically um computers on the local area network, and it found the Sonos thing, uh the Sonos uh system.","offset":587,"duration":12},{"text":"Andrej Karpathy: And it turned out that there's no password protection or anything like that, it just logged in and it's like, \"Oh yeah, you have these Sonos systems installed. Uh, let me try to reverse engineer how it's uh working.\"","offset":599,"duration":10},{"text":"Andrej Karpathy: It does some web searches and it finds like, \"Okay, these are the API endpoints.\" And then it's like, \"Do you want to try it?\" and I'm like, \"Whoa, like you just did that.\" And I'm like, \"Yeah, can you try to play something in the study?\"","offset":609,"duration":9},{"text":"Andrej Karpathy: And uh it does, and music comes out. And I'm like, I can't believe I just—","offset":618,"duration":1},{"text":"Host: That's crazy, that's like three prompts.","offset":619,"duration":2},{"text":"Andrej Karpathy: I can't believe I just typed in like, \"Can you find my Sonos?\" and that suddenly it's playing music. And it did the same for lights. And so basically like it kind of hacked in, figured out the whole thing, uh created APIs, created a dashboard, so I could see the command kind of center of like all of my lights in the home.","offset":621,"duration":12},{"text":"Andrej Karpathy: And then it was like switching lights on and off and, you know, uh so I can ask it like Dobby at sleepy time, and when it's sleepy time that just means all the lights go off etc. and so on.","offset":633,"duration":11},{"text":"Andrej Karpathy: So it controls all of my lights, my HVAC, my shades, uh the pool and uh the spa, and also my security system. So I have a camera pointed outside of the house and anytime someone rolls in, I have a Quen—uh, a Quen uh model that looks at the videos.","offset":644,"duration":13},{"text":"Andrej Karpathy: So first of all there's change detection.","offset":657,"duration":2},{"text":"Host: Right.","offset":659,"duration":1},{"text":"Andrej Karpathy: And then based on change detection, it goes to Quen, and then it actually like tells me, uh it sends me a text to my WhatsApp, it shows an image from the outside, and it says, \"Hey FedEx truck just pulled up, FedEx truck just pulled up and you might want to check it and you got new mail or something like that.\"","offset":660,"duration":15},{"text":"Andrej Karpathy: And Dobby just texts me this. This is extremely incredible. Um, so so Dobby is in charge of the house, I text through with it through WhatsApp. Uh, and it's been like really fun to have these macro actions that maintain my house.","offset":675,"duration":14},{"text":"Andrej Karpathy: I haven't like really pushed it uh like way more beyond that, and I think people are doing a lot more crazy things with it, but for me even just the home automation setup, I used to use like six apps, uh completely different apps, and I don't have to use these apps anymore.","offset":689,"duration":13},{"text":"Andrej Karpathy: Like Dobby controls everything in natural language, it's amazing. Um, and so I think like I haven't even pushed the paradigm fully, but already that is so helpful and so inspiring I would say.","offset":702,"duration":9},{"text":"Host: Do you think that's indicative of like what people want from a user experience perspective with software?","offset":711,"duration":6},{"text":"Host: Right, because I—I don't think, you know, it's pretty ignored that it takes humans effort to like learn new software, like new UI.","offset":717,"duration":8},{"text":"Andrej Karpathy: Yeah, I think uh to some extent that's right. It's like working backwards from how people think an AI should be, because what people have in their mind of like what an AI is, is not actually what an LLM is by—like in the raw sense.","offset":725,"duration":10},{"text":"Andrej Karpathy: Like LLM is a token generator, you know, like more tokens come out. But what they think of is like this pers—this persona identity that they can tell stuff and it remembers it, you know, and uh is just an entity behind a WhatsApp. It's like a lot more understandable.","offset":735,"duration":13},{"text":"Andrej Karpathy: Um, so I think to some extent it's like matching the expectations that humans already have for what an AI should behave, but under the hood it's like a lot of technical details go into that. And LLMs are too raw of a primitive, uh to actually, uh type check as AI I think for most people if that makes sense.","offset":748,"duration":13},{"text":"Host: Yeah, I—I think that's like how we understand what the AI is, and like the description of it as Dobby or some persona obviously resonates with people.","offset":761,"duration":10},{"text":"Host: Um, I also think that it—uh the unification that you did across your six different software systems for your home automation speaks to a different question of like do people really want all of this software that we have today?","offset":771,"duration":11},{"text":"Andrej Karpathy: Yeah.","offset":782,"duration":1},{"text":"Host: Um, because I would argue like well you have the hardware, but you've now thrown away the software or the the UX layer of it. Um, do you think that's what people want?","offset":783,"duration":11},{"text":"Andrej Karpathy: Yeah, I think there's this like there's this sense that these apps that are on the app store for using these smart home devices etc., uh these shouldn't even exist kind of in a certain sense.","offset":794,"duration":9},{"text":"Andrej Karpathy: Like shouldn't it just be APIs and shouldn't agents be just using it directly? And uh wouldn't it like—I can do all kinds of home automation stuff that uh any individual app will not be able to do, right?","offset":803,"duration":10},{"text":"Andrej Karpathy: Um, and an LLM can actually drive the tools and call all the right tools and do do pretty complicated things. Um, and so in a certain sense it does point to this like maybe there's like an overproduction of lots of custom bespoke apps that shouldn't exist because agents kind of like crumble them up.","offset":813,"duration":13},{"text":"Andrej Karpathy: And everything should be a lot more just like exposed API endpoints, and agents are the glue of the intelligence that actually like tool calls all the all the parts. Um, another example is like my treadmill.","offset":826,"duration":12},{"text":"Andrej Karpathy: Uh, there's an app for my treadmill, and I wanted to like keep track of how often I do my cardio, uh but like I don't want to like log into a web UI and go through a flow and etc. Like all this should just be like make APIs available.","offset":838,"duration":12},{"text":"Andrej Karpathy: And this is kind of, you know, going towards the agentic, uh sort of web or like agent first, uh tools and all this kind of stuff. So I think the industry just has to reconfigure in so many ways that it's like the customer is not the human anymore.","offset":850,"duration":12},{"text":"Andrej Karpathy: It's like agents who are acting on behalf of humans, and this refactoring will be will probably be substantial in a certain sense.","offset":862,"duration":6},{"text":"Host: One way that people sometimes push back on this is like do people, do we expect people to vibe code some of these tools?","offset":868,"duration":6},{"text":"Host: Do we expect normal people to do this kind of stuff that I described? But I think to some extent this is just, you know, technology as it exists today, and right now there is some vibe coding and I'm actually watching it and I'm working with the system.","offset":874,"duration":14},{"text":"Andrej Karpathy: But I kind of feel like the kind of stuff that I just talked about, this should be free, like in a year or two or three. There's no vibe coding involved. This is trivial, this is table stakes. This is like any AI, even the open source models etc. can like do this.","offset":888,"duration":11},{"text":"Host: You should be able to translate from a less technical human's intent very easily to this outcome.","offset":899,"duration":6},{"text":"Andrej Karpathy: Extremely easily. Yeah. Today it's vibe coding and some involved and not many people are going to do it, but—","offset":905,"duration":3},{"text":"Host: And you still have to make some design decisions, right? We were talking about like what you take frames, for example.","offset":908,"duration":5},{"text":"Andrej Karpathy: Yeah. But I kind of feel like this will just uh start to the barrier will just come down and it's just ephemeral software on your behalf and some kind of like Claw is handling all the details for you, but you're not involved. Claw has a Claw has a machine and it will figure it out, and it's just presenting you UIs and you're like saying stuff, you know.","offset":913,"duration":14},{"text":"Host: Why haven't you uh I guess like pushed the boundaries of what you can do personally with Claws like is it, you know, you're focusing on more important projects? AutoResearch etc. or uh you're climbing the hill to mastery or something else, right?","offset":927,"duration":15},{"text":"Andrej Karpathy: Yeah, I just feel like I'm so distracted by everything. So I spent I spent like a week on the Claw stuff and I I have more to-dos almost, um but I will say that—","offset":942,"duration":11},{"text":"Host: It's like Jensen told us, we're all just busier, unfortunately.","offset":953,"duration":2},{"text":"Andrej Karpathy: Yeah. Uh, I didn't really take advantage of a lot of like email and calendar and all this other stuff, and I didn't give it access because I'm still a little bit like suspicious and it's still very new and rough around the edges, so I didn't want to give it like full access to my digital life yet.","offset":955,"duration":14},{"text":"Andrej Karpathy: And part of it is just security privacy and uh just being very cautious in that in that realm. And uh so some of it is like held back by that I would say. Yeah maybe that's like the dominant dominant feature, but some of it is also just I feel so distracted because I feel like I had a week of Claw and then other stuff is happening and—","offset":969,"duration":13},{"text":"Host: What was the um—I mean, you have talked about like being able to train or at least optimize a uh a model as a task that you want to see agents do for a long time. Like what was the motivation behind AutoResearch?","offset":982,"duration":13},{"text":"Andrej Karpathy: AutoResearch, yeah. So I think like I had a tweet earlier where I kind of like said something along the lines of to get the most out of the tools that are becoming available now, you have to remove yourself as the as the bottleneck.","offset":995,"duration":12},{"text":"Andrej Karpathy: You can't be there to prompt the next thing. You're you need to take yourself outside um. You have to arrange things such that they are completely autonomous and the more you know, how can you maximize your token throughput and not be in the loop?","offset":1007,"duration":12},{"text":"Andrej Karpathy: This is the this is the goal. And so I kind of mentioned that the the name of the game now is to increase your leverage. Uh, I put in just very few tokens just once in a while and a huge amount of stuff happens on my behalf.","offset":1019,"duration":9},{"text":"Andrej Karpathy: And so AutoResearch, like I tweeted that and I think people liked it and whatnot, but—","offset":1028,"duration":4},{"text":"Host: They haven't like maybe worked through like the implications of that.","offset":1032,"duration":3},{"text":"Andrej Karpathy: And for me AutoResearch is an example of like an implication of that where it's like I don't want to be like the researcher in the loop like looking at results etc. like I'm I'm holding the system back.","offset":1035,"duration":8},{"text":"Andrej Karpathy: So the question is how do I refactor all the abstractions so that I'm not—I have to arrange it once and hit go. The name of the game is how can you get more agents running for longer periods of time without your involvement doing stuff on your behalf?","offset":1043,"duration":12},{"text":"Andrej Karpathy: And AutoResearch is just, yeah, here's an objective, here's a metric, here's your boundaries of what you can and cannot do and go. And uh yeah, it worked.","offset":1055,"duration":7},{"text":"Host: You were surprised at its effectiveness.","offset":1062,"duration":3},{"text":"Andrej Karpathy: Yeah, I I didn't expect uh it to work because so I have the project Nanochat, um and fundamentally like I think a lot of people are very confused with my obsession for like training GPT-2 models and so on, but for me uh training GPT models and so on is just a little harness, a little playground for training LLMs.","offset":1065,"duration":15},{"text":"Andrej Karpathy: And fundamentally what I'm more interested in is like this idea of recursive self-improvement and to what extent can you actually have LLMs improving LLMs? Because I think all the frontier labs this is like the thing, um for obvious reasons.","offset":1080,"duration":9},{"text":"Andrej Karpathy: And they're all trying to recursively self-improve roughly speaking. And so for me this is kind of like uh a little playpen of that. Um, and I guess I like tuned Nanochat already quite a bit by hand in a good old-fashioned way that I'm used to.","offset":1089,"duration":13},{"text":"Andrej Karpathy: Like I'm a researcher, I've done this for like you know two decades, I have some amount of like—","offset":1102,"duration":3},{"text":"Host: What is the opposite of hubris? Uh, yeah.","offset":1105,"duration":2},{"text":"Host: Earned confidence.","offset":1107,"duration":1},{"text":"Andrej Karpathy: Okay. Of like two decades of like oh I've trained this model like thousands of times of like um so I've done a bunch of experiments, I've done hyperparameter tuning, I've done all the things I'm very used to and I've done for two decades.","offset":1108,"duration":13},{"text":"Andrej Karpathy: Yeah. And I've gotten to a certain point and I thought it was like fairly well-tuned, and then I let AutoResearch go for like overnight and it came back with like tunings that I didn't see. And yeah I did forget like the weight decay on the value embeddings, and my Adam betas were not sufficiently tuned, and these things jointly interact.","offset":1121,"duration":18},{"text":"Andrej Karpathy: So like once you tune one thing the other things have to potentially change too. You know, I shouldn't be a bottleneck, I shouldn't be running these hyperparameter search optimizations, I shouldn't be looking at the results.","offset":1139,"duration":8},{"text":"Andrej Karpathy: There's objective criteria in this case. Uh, so you just let you just have to arrange it so that it can just go forever. So that's a single sort of version of AutoResearch of like a single loop trying to improve.","offset":1147,"duration":8},{"text":"Andrej Karpathy: And I was surprised that it um it found these things that I you know the repo is already fairly well-tuned and still found something. And that's just a single it's a single loop.","offset":1155,"duration":6},{"text":"Andrej Karpathy: Like these frontier labs they have GPU clusters of tens of thousands of them, and so it's very easy to imagine how you would basically get a lot of this automation on um smaller models, and fundamentally everything around like frontier-level intelligence is about extrapolation and scaling laws.","offset":1161,"duration":18},{"text":"Andrej Karpathy: And so you basically do a ton of the exploration on the smaller models and then you try to uh extrapolate out.","offset":1179,"duration":4},{"text":"Host: So you're saying our research efforts are going to get more efficient, like we're going to have better direction for when we scale as well if we can do this experimentation better.","offset":1183,"duration":8},{"text":"Andrej Karpathy: Yeah, I would say that like the most interesting project and probably what the frontier labs are working on is um you know you experiment on small models, you try to make it as autonomous as possible, remove researchers—","offset":1191,"duration":8},{"text":"Host: From the loop.","offset":1199,"duration":2},{"text":"Andrej Karpathy: —they have way too much—","offset":1201,"duration":2},{"text":"Host: What is the opposite of—which—","offset":1203,"duration":1},{"text":"Host: Earned confidence.","offset":1204,"duration":1},{"text":"Andrej Karpathy: Yeah, they don't know. They shouldn't be touching any of this really. And so you have to like rewrite the whole thing because right now I mean certainly they can contribute ideas.","offset":1205,"duration":7},{"text":"Andrej Karpathy: But okay uh they shouldn't actually be enacting these ideas. There's a queue of ideas, and there's maybe an automated scientist that comes up with ideas based on all the archive papers and GitHub repos and it funnels ideas in, or researchers can contribute ideas.","offset":1212,"duration":13},{"text":"Andrej Karpathy: But it's a single queue and there are workers that pull uh items and they try them out, and uh whatever works just gets uh sort of put on the feature branch and maybe some people like uh monitor the feature branch and merge to the main branch sometimes.","offset":1225,"duration":14},{"text":"Andrej Karpathy: So yeah just removing humans uh from all the processes and automating as much as possible and getting high to tokens per second throughputs and it does require rethinking of all the abstractions uh and uh everything has to be reshuffled so yeah I think it's very exciting.","offset":1239,"duration":15},{"text":"Host: Take one more recursive step here. Um, uh when is the model going to write a better Program MD than you?","offset":1254,"duration":5},{"text":"Andrej Karpathy: Yeah.","offset":1259,"duration":1},{"text":"Host: We're not in the loop.","offset":1260,"duration":1},{"text":"Andrej Karpathy: Yeah, exactly. Uh, so Program MD is my crappy attempt at describing like how the AutoResearcher should work. Like oh do this, then do that and that and then try these kinds of ideas.","offset":1261,"duration":10},{"text":"Andrej Karpathy: Like here's maybe some ideas like look at architecture, look at optimizer etc. but I just came up with this in Markdown, right? Um, and uh so yeah exactly.","offset":1271,"duration":9},{"text":"Andrej Karpathy: You want some kind of an AutoResearch loop maybe that looks for—you can imagine that different Program MDs would um would give you different uh progress. So you basically every research organization is described by Program MD.","offset":1280,"duration":15},{"text":"Host: Yeah.","offset":1295,"duration":1},{"text":"Andrej Karpathy: A research organization is a set of Markdown files that describe all the roles and how the whole thing connects. Um, and you can imagine having a better research organization.","offset":1296,"duration":10},{"text":"Andrej Karpathy: So maybe they do fewer stand-ups in the morning because they're useless. Uh, and this is all just code, right? Um, and so you can so one organization can have fewer stand-ups, one organization can have more, uh one organization can be very risk-taking, one organization can be less.","offset":1306,"duration":13},{"text":"Andrej Karpathy: And so you can definitely imagine that you have multiple research orgs, um and then they all have code. And once you have code then you can imagine tuning the code. So 100% there's like the meta layer of it uh uh.","offset":1319,"duration":10},{"text":"Host: Did you see my text about my contest idea? My contest idea was uh like let people write uh different Program MDs, right?","offset":1329,"duration":9},{"text":"Host: And so for same hardware where do you get most improvement?","offset":1338,"duration":2},{"text":"Andrej Karpathy: Oh, I see.","offset":1340,"duration":1},{"text":"Host: And then you can take all that data and then give it to the model and say write a better Program MD.","offset":1341,"duration":4},{"text":"Andrej Karpathy: Yes, yes. Yeah, exactly.","offset":1345,"duration":3},{"text":"Host: We're going to get something better. Like there's no way we don't, right?","offset":1348,"duration":1},{"text":"Andrej Karpathy: You can 100% look at uh where the improvements came from and like can I change the Program MD such that more of these kinds of things would be done, or like things that didn't work uh etc. Meta optimization.","offset":1349,"duration":13},{"text":"Host: Yeah.","offset":1362,"duration":1},{"text":"Andrej Karpathy: You can 100% imagine doing that. So I think this is a great idea. But it's like you know I think you sort of go one step at a time where you sort of have one process and then second process and then the next process, and these are all layers of an onion.","offset":1363,"duration":10},{"text":"Andrej Karpathy: Like the LLM sort of part is now taken for granted, the agent part is now taken for granted, now the claw-like entities are taken for granted, and now you can have multiple of them, and now you can have instructions to them, and now you can have optimization over the instructions, and it's just a little too much, you know?","offset":1373,"duration":14},{"text":"Andrej Karpathy: But they I mean this is what gets to the psychosis, is that this is like infinite and everything is skill issue, and that's why I feel yeah that's just coming back to this is why it's so insane.","offset":1387,"duration":-1191},{"text":"Host: Okay, well if we're we're just trying to like diagnose the current moment and uh what is a relevant skill right now, what do you like what do you think is the implication that this um that this is the loop we should be trying to achieve in different areas?","offset":196,"duration":1213},{"text":"Host: And that it works, right? Like remove—create the metric or create the ability for um agents to continue working on it without you. Do we still have performance engineering? Like what—","offset":1409,"duration":11},{"text":"Andrej Karpathy: Yeah, I mean so there's a few caveats that I would put on top of the LM psychosis. So number one, uh this is extremely well suited to anything that has objective uh metrics that are easy to evaluate.","offset":1420,"duration":9},{"text":"Host: Hmm.","offset":1429,"duration":1},{"text":"Andrej Karpathy: So for example like writing kernels for more efficient CUDA, uh you know code for various parts of a model etc. are the perfect fit. Um, because you have inefficient code and then you want efficient code that has the exact same behavior but is much faster. Perfect fit.","offset":1430,"duration":16},{"text":"Andrej Karpathy: Uh, so a lot of things that like are perfect fit for AutoResearch, but many things will not be. And so they it's just if you can't evaluate it then you can't AutoResearch it, right? Uh, so that's like caveat number one.","offset":1446,"duration":10},{"text":"Andrej Karpathy: And then maybe caveat number two I would say is you know we're we're kind of talking about next steps and we kind of see what next steps are, but fundamentally the whole thing still doesn't it still kind of like bursting at the seams a little bit and there's cracks and it doesn't fully work.","offset":1456,"duration":12},{"text":"Andrej Karpathy: And if you kind of try to go too far ahead the whole thing is actually net not useful, if that makes sense. Um because these models like still are not you know they've improved a lot but they're still like rough around the edges as maybe the way I would describe it.","offset":1468,"duration":12},{"text":"Andrej Karpathy: I simultaneously feel like I'm talking to an extremely brilliant PhD student who's been like a systems programmer for their entire life and a 10-year-old. And it's so weird because humans like there's—","offset":1480,"duration":12},{"text":"Host: Yes you wouldn't you wouldn't encounter that combination.","offset":1492,"duration":2},{"text":"Andrej Karpathy: This jaggedness is really strange and humans have a lot less of that kind of jaggedness although they definitely have some. But humans have a lot more jaggedness—uh sorry the agents have a lot more jaggedness where uh sometimes like you know I ask for functionality and it like comes back with something that is just like totally wrong.","offset":1494,"duration":16},{"text":"Andrej Karpathy: And then we get into loops that are totally wrong and then I'm just I get so frustrated with the agents all the time still because you feel the power of it but you also there's still like it does nonsensical things once in a while for me uh still as well.","offset":1510,"duration":14},{"text":"Host: I get very annoyed when uh uh I feel like the agent wasted a lot of compute on something it should have recognized was an obvious problem.","offset":1524,"duration":8},{"text":"Andrej Karpathy: Yeah. I think like some of the bigger things is like maybe what's under underneath it, if I could hypothesize, is fundamentally these models are trained via reinforcement learning.","offset":1532,"duration":9},{"text":"Andrej Karpathy: So they're actually struggling with the exact same thing we just talked about which is the labs can improve the models in anything that is verifiable or that has rewards. So did you write the program correctly and does it do the unit tests check out, yes or no?","offset":1541,"duration":13},{"text":"Andrej Karpathy: But some of the things where they're struggling is like for example I think they have a tough time with like nuance of maybe what I what I had in mind or what I intended and when to ask clarifying questions.","offset":1554,"duration":11},{"text":"Andrej Karpathy: Uh, like or where the—yeah, it's just um anything that feels softer is like worse. And so you're kind of like you're either on rails and you're part of the superintelligence circuits or you're not on rails and you're outside of the verifiable domains and suddenly everything kind of just like meanders.","offset":1565,"duration":-1187},{"text":"Andrej Karpathy: Like maybe another way to put it is if you go to if today if you go to like state-of-the-art model ChatGPT and you ask it tell me a joke, um do you know what joke you're going to get? There's the joke.","offset":378,"duration":1209},{"text":"Host: The joke. I do feel I I can't tell you like the you know standard form of it, but I do feel like ChatGPT has like three jokes.","offset":1587,"duration":8},{"text":"Andrej Karpathy: Yeah, yeah. So the the joke that apparently all the LLMs like love the most is why do scientists uh not trust atoms?","offset":1595,"duration":6},{"text":"Host: Okay.","offset":1601,"duration":1},{"text":"Andrej Karpathy: Because they make everything up.","offset":1602,"duration":1},{"text":"Host: Okay.","offset":1603,"duration":1},{"text":"Andrej Karpathy: They make everything up. So this is still—","offset":1604,"duration":2},{"text":"Host: Why'd that emerge?","offset":1606,"duration":2},{"text":"Andrej Karpathy: So this is the joke you would get three or four years ago and this is the joke you still get today.","offset":1608,"duration":3},{"text":"Host: Okay.","offset":1611,"duration":1},{"text":"Andrej Karpathy: So even though the models have improved tremendously and if you give them an agentic task they will just go for hours and move mountains for you, and then you ask for like a joke and it has a stupid joke, a crappy joke from five years ago.","offset":1612,"duration":14},{"text":"Andrej Karpathy: And it's because it's outside of the it's outside of the RL. It's outside of what's being improved, it's like and it's part of the jaggedness of like shouldn't you expect models as they get better to also have like better jokes or more diversity of them or it's just it's not being optimized and it's stuck.","offset":1626,"duration":15},{"text":"Host: Do you uh uh think that that implies that we are not seeing like generalization in the sense of like broader intelligence of joke smartness being attached to code smartness?","offset":1641,"duration":14},{"text":"Andrej Karpathy: Yeah, I think there's some decoupling where some things are verifiable and some things are not and some things are optimized for arbitrarily by the labs depending on like what data went in and some things are not.","offset":1655,"duration":11},{"text":"Host: But I mean the premise, there's a you know premise from some research groups that if you are smarter at code generation or in these verifiable fields you should be better at everything.","offset":1666,"duration":11},{"text":"Host: And like the the joke situation suggests that that's not happening in Auto—","offset":1677,"duration":2},{"text":"Andrej Karpathy: I don't think that's happening.","offset":1679,"duration":1},{"text":"Host: Okay.","offset":1680,"duration":1},{"text":"Andrej Karpathy: Yeah, I don't think that's happening. I think I think maybe we're seeing like a little bit of that, but not like a satisfying amount.","offset":1681,"duration":5},{"text":"Host: Yeah. That jaggedness exists in humans. You can be very, very good at math and still tell really bad jokes.","offset":1686,"duration":7},{"text":"Andrej Karpathy: Yeah, that's true, yeah. But it just it still means that we're not getting like the story is that we're getting a lot of the intelligence and capabilities in all the domains of society like for free as we get better and better models, and that's not like exactly fundamentally what's going on.","offset":1693,"duration":13},{"text":"Andrej Karpathy: And there's some blind spots and some things are not being optimized for and this is all clustered up in these neural net opaque models, right?","offset":1706,"duration":8},{"text":"Andrej Karpathy: So you're either on rails of what it was trained for and everything is like you're going at speed of light or you're not. Um, and so it's the jaggedness.","offset":1714,"duration":8},{"text":"Andrej Karpathy: So um so that's why I think like even though the the progression is obvious what should happen, you can't let it fully go there yet because it doesn't fully work, or it's a skill issue and we just haven't like figured out how to use it, so you know it's hard to tell.","offset":1722,"duration":14},{"text":"Host: Can I ask kind of a blasphemous question which is like if this jaggedness is persistent um and it's all rolled up in a at least monolithic interface, right?","offset":1736,"duration":12},{"text":"Host: But you know single model, um does that make sense or do you should it be unbundled into things that are can be optimized and improved against different domains of intelligence?","offset":1748,"duration":8},{"text":"Andrej Karpathy: Uh like unbundling the models into multiple experts in different areas etc. more directly? Yeah.","offset":1756,"duration":5},{"text":"Host: Yeah. Instead of just MOE that we have no exposure to.","offset":1761,"duration":3},{"text":"Host: Because that can be like confusing as a user from the outside which is like why is it so good at this but not at this other thing.","offset":1764,"duration":8},{"text":"Andrej Karpathy: Yeah, I think currently my impression is uh the labs are trying to have a single sort of monoculture of a model that is arbitrarily intelligent in all these different domains and they just stuff it into the parameters.","offset":1772,"duration":11},{"text":"Andrej Karpathy: I do think that we will I do think we should expect more speciation in the intelligence. Um like you know the animal kingdom is extremely diverse in the brains that exist and there's lots of different niches of of nature, and some animals have overdeveloped visual cortex or other kind of parts.","offset":1783,"duration":16},{"text":"Andrej Karpathy: And I think we we should be able to see more speciation and um you don't need like this oracle that knows everything you kind of speciate it and then you put it on a specific task.","offset":1799,"duration":9},{"text":"Andrej Karpathy: And we should be seeing some of that because you should be able to have like much smaller models that still have the cognitive core like they're still competent but then they specialize and then um and then they can become more efficient in terms of latency or throughput on uh specific tasks that you really care about.","offset":1808,"duration":15},{"text":"Andrej Karpathy: Like if you're a mathematician working in Lean. I saw for example there's a few releases that really like target that as in the domain. Um so there's a probably going to be a few examples like that where the unbundling kind of makes sense.","offset":1823,"duration":10},{"text":"Host: One question I have is whether or not uh the capacity constraint on available compute infrastructure drives more of this.","offset":1833,"duration":8},{"text":"Host: Because efficiency actually matters more, right? Like you're if financing aside though financing is involved in all of this, if you have access to full compute for anything you do like leaving the one single model, right?","offset":1841,"duration":13},{"text":"Host: But if you actually feel pressure where you're like I can't serve um model of massive size for every use case like do you think that leads to any speciation?","offset":1854,"duration":12},{"text":"Host: Does that question make sense to you?","offset":1866,"duration":1},{"text":"Andrej Karpathy: The question makes sense. And I guess like what I'm what I'm what I'm struggling with is I don't think we've seen too much speciation just yet, right?","offset":1867,"duration":6},{"text":"Host: No.","offset":1873,"duration":1},{"text":"Andrej Karpathy: Uh we're seeing a monoculture of models.","offset":1874,"duration":1},{"text":"Host: Yeah.","offset":1875,"duration":1},{"text":"Andrej Karpathy: And there's like clearly pressure for like make a good code model put it back in the main merge again.","offset":1876,"duration":6},{"text":"Host: Yeah, yeah.","offset":1882,"duration":1},{"text":"Andrej Karpathy: Even though there already is pressure on the models. Uh I guess perhaps I I feel like there's a lot of very short-term supply crunch and like maybe that causes more speciation now.","offset":1883,"duration":12},{"text":"Andrej Karpathy: Yeah, I think fundamentally like the model the labs are serving a model and they don't really know what the end user is going to be asking about. Uh so maybe that's like some part of it because they kind of have to multitask over all the possible things they could be asked.","offset":1895,"duration":13},{"text":"Andrej Karpathy: But I think if you're coming to a business and maybe partnering on some specific problems you care about then maybe you would see that there. Uh or there would be some very high-value applications that are like more niche. Um but uh I think right now they're kind of like going after the totality of what's available.","offset":1908,"duration":15},{"text":"Andrej Karpathy: I don't think that the science of manipulating the brains is like fully developed yet partly.","offset":1923,"duration":4},{"text":"Host: What do you mean manipulating?","offset":1927,"duration":1},{"text":"Andrej Karpathy: Uh so like so fine-tuning without losing capabilities as an example. And I we don't have these primitives for actually like working with the intelligences in ways other than just context windows.","offset":1928,"duration":11},{"text":"Andrej Karpathy: Like context windows kind of just work and it's very cheap to manipulate etc. and this is how we're getting some of the customization etc. but I think if it was I think it's a bit more of a developing science of how you like more deeply adjust the models.","offset":1939,"duration":9},{"text":"Andrej Karpathy: How you have continuous learning maybe or how you uh how you fine-tune in certain area, how you get better in certain area or like how you actually touch the weights, not just the context windows.","offset":1948,"duration":10},{"text":"Andrej Karpathy: And so it's a lot more tricky I would say to touch the weights than just the context window uh because you're actually fundamentally changing the full model and potentially its intelligence.","offset":1958,"duration":-529},{"text":"Andrej Karpathy: And so uh so maybe it's just like not a fully developed science if that makes sense of speciation.","offset":1429,"duration":2},{"text":"Host: And it also has to be like cheap enough.","offset":1431,"duration":542},{"text":"Andrej Karpathy: Yeah.","offset":1973,"duration":1},{"text":"Host: For that speciation to be worthwhile in these given contexts. Can I ask a question about uh like an extension to AutoResearch that you described in terms of um open ground you say okay well you know we have this thing um we need more collaboration surface around it essentially for people to contribute.","offset":1974,"duration":19},{"text":"Host: Um to research overall. Can you talk about that?","offset":1993,"duration":2},{"text":"Andrej Karpathy: Yeah, so we talked about AutoResearch has a single thread of like I'm going to try stuff in a loop. Uh but fundamentally the parallelization of this is like the interesting component.","offset":1995,"duration":9},{"text":"Andrej Karpathy: Uh and I guess I was trying to like play around with a few ideas but I don't have anything that like clicks as simply as like I don't have something that I'm like super happy with just yet, but it's something I'm like working on on the side when I'm not working on my Claw.","offset":2004,"duration":11},{"text":"Andrej Karpathy: Uh so I think like one issue is if you have a bunch of nodes uh of parallelization available to you, then it's very easy to just have multiple AutoResearchers talking through a uh a common system or something like that.","offset":2015,"duration":13},{"text":"Andrej Karpathy: What I was more interested in is how you can have an untrusted pool of workers out there on the internet.","offset":2028,"duration":5},{"text":"Host: Hmm.","offset":2033,"duration":1},{"text":"Andrej Karpathy: So for example in AutoResearch, um you're just trying to find uh the piece of code that trains a model to a very low validation loss.","offset":2034,"duration":6},{"text":"Andrej Karpathy: If anyone gives you a candidate commit, it's very easy to verify that that commit is correct is good. Like they somehow could claim from the internet that this piece of code will optimize uh much better and give you much better performance.","offset":2040,"duration":12},{"text":"Andrej Karpathy: You could just check. It's very easy. But probably a lot of work goes into that checking. Uh but fundamentally they could lie and etc. So you're basically dealing with a similar kind of pro—it's almost actually like looks a little bit like—","offset":2052,"duration":12},{"text":"Andrej Karpathy: My designs that incorporate an untrusted pool of workers actually like a little bit more like a blockchain a little bit. Uh because instead of blocks you have commits and these commits can build on each other and they contain like changes to the code as you're improving it.","offset":2064,"duration":16},{"text":"Andrej Karpathy: Uh and the proof of work is basically doing tons of experimentation to find the commits that work. Uh and that's hard. Um and then the reward is just being on the leaderboard right now.","offset":2080,"duration":10},{"text":"Andrej Karpathy: There's no monetary reward whatsoever. Uh but I don't want to push the analogy too far, but it fundamentally has this issue where huge amount of search goes into it, but it's very cheap to verify that a candidate solution is indeed good because you can just train a single, you know, someone had to try 10,000 ideas but you just have to check that the thing that they produced actually works.","offset":2090,"duration":15},{"text":"Andrej Karpathy: Because the 9,999 of them didn't work, you know? Um and so basically long story short it's like you have to come up with a system where an untrusted pool of workers can collaborate with a trusted pool of workers uh that do the verification and the whole thing is kind of like asynchronous and works and uh and so on.","offset":2105,"duration":18},{"text":"Andrej Karpathy: And is is like safe from a security perspective because if anyone sends you arbitrary code and you're going to run it, that's very sketchy and dodgy. So um but fundamentally it should be totally possible.","offset":2123,"duration":10},{"text":"Andrej Karpathy: So you're familiar with projects like SETI@home and Folding@home. All of these problems have a similar kind of uh setup. So Folding@home, you're folding a protein um and it's very hard to find a configuration that is low energy.","offset":2133,"duration":13},{"text":"Andrej Karpathy: But if someone finds a configuration that they evaluate to be low energy, that's perfect. You can just use it. You can easily verify it. So a lot of things have this property that, you know, very expensive to come up with but very cheap to verify.","offset":2146,"duration":11},{"text":"Andrej Karpathy: And so in all those cases things like Folding@home or SETI@home or AutoResearch@home will be good fits. And so um long story short a swarm of agents on the internet could collaborate to improve LLMs and could potentially even like run circles around frontier labs.","offset":2157,"duration":16},{"text":"Andrej Karpathy: Like who knows, you know? Um yeah like maybe that's even possible. Like frontier labs have a huge amount of trusted compute, but the Earth is much bigger and has huge amount of untrusted compute. But if you put systems in check, systems in place that, you know, deal with this, then maybe it is possible that the swarm out there could uh could come up with a with better with better solutions.","offset":2173,"duration":16},{"text":"Andrej Karpathy: And people just kind of like contribute cycles um to a thing that they care about. And so sorry so the last thought is lots of companies or whatnot they could maybe have like their own uh things that they care about, and you if you have compute capacity you could contribute to different kind of AutoResearch tracks.","offset":2189,"duration":17},{"text":"Andrej Karpathy: Like maybe you care about certain you know you care about like cancer or something like that of certain type. You don't have to just donate money to an institution, you actually could like purchase compute and then you could join the AutoResearch swarm for that project, you know?","offset":2206,"duration":13},{"text":"Andrej Karpathy: Um so if everything is rebundled into AutoResearchers then compute becomes the thing that you're contributing to the pool.","offset":2219,"duration":6},{"text":"Host: Yeah, that's very inspiring and it's also interesting. Like I don't I don't know how far this goes, but it is interesting that at least some audience of people, you know, here in Silicon Valley or lining up at um retail stores in China have discovered that like having access to personal compute is interesting again.","offset":2225,"duration":17},{"text":"Host: Yeah. So maybe they're really motivated to do that for their Claws and then they can uh contribute to AutoResearch.","offset":2242,"duration":4},{"text":"Andrej Karpathy: It's almost like dollar is the thing everyone cares about, but is flop the thing that actually everyone cares about in the future? Like is there going to be like a flippening almost of like what the thing that you care about?","offset":2246,"duration":10},{"text":"Andrej Karpathy: Like right now for example it's really hard to get compute even if you have money. Yeah. So actually it almost seems like the flop is like dominant uh in a certain sense. Um yes so uh so maybe that's kind of like kind of like that. Like how much how many flops do you control instead of like what wealth do you control?","offset":2256,"duration":14},{"text":"Andrej Karpathy: I don't actually think that's true, but it's kind of interesting to think about.","offset":2270,"duration":2},{"text":"Host: The last thing you released was like a little bit of jobs data analysis. Is that right?","offset":2272,"duration":5},{"text":"Andrej Karpathy: Yeah.","offset":2277,"duration":1},{"text":"Host: What um and it touched a nerve even though you were just like visualizing some public data. Uh what was you know what were you curious about?","offset":2278,"duration":9},{"text":"Andrej Karpathy: Yeah, I guess I was curious to um I mean everyone is like really it's everyone is really thinking about the impacts of AI on the job market and what it's going to look like. So I was just interested to take a look like what does the job market look like?","offset":2287,"duration":11},{"text":"Andrej Karpathy: Where are the different roles? Um and how many people are in different professions? And I was like really just interested to like look through uh the individual cases and try to think myself about like you know with these AIs and how they're likely to evolve like are these going to be tools that people are using? Are these going to be displacing tools for these uh professions?","offset":2298,"duration":22},{"text":"Andrej Karpathy: And like what are the current professions and how are they going to change? Are they going to grow or uh adjust to a large extent? Or like what could be new professions? So it was really just like a way to fuel my own chain of thought about the industry I suppose.","offset":2320,"duration":12},{"text":"Andrej Karpathy: Um and so uh yeah the jobs data basically is just a Bureau of Labor Statistics. Uh they actually have a percent outlook for each profession about how much it's expected to grow over the next I think almost a decade.","offset":2332,"duration":11},{"text":"Host: We need a lot of healthcare workers.","offset":2343,"duration":1},{"text":"Andrej Karpathy: Yeah, so so they've already made those projections and I'm not sure actually 100% what the methodology was that they that they put into the projections. Um I guess I was interested to color things by like if people think that what's primarily being um developed now is this kind of like more digital AI that is kind of like almost like these ghost or spirit entities that can like interact in the digital world and uh manipulate a lot of like digital information.","offset":2344,"duration":23},{"text":"Andrej Karpathy: And they currently don't really have a physical embodiment uh or presence. And the physical stuff is probably going to go slightly slower because you're manipulating atoms. So flipping flipping bits and and the ability to copy paste digital information is like makes everything a million times faster than accelerating matter, you know?","offset":2367,"duration":17},{"text":"Andrej Karpathy: So um so energetically I just think we're going to see a huge amount of activity in the digital space, huge amount of rewriting, huge amount of activity boiling soup.","offset":2384,"duration":7},{"text":"Andrej Karpathy: And I think the we're going to see something that in the digital space goes at the speed of light compared to I think what's going to happen in the physical world to some extent if would be the extrapolation.","offset":2391,"duration":8},{"text":"Andrej Karpathy: And so I think like um there's currently kind of like I think an overhang where there can be like a lot of unhobbling almost potentially of like a lot of digital information processing that used to be done by computers and people.","offset":2399,"duration":14},{"text":"Andrej Karpathy: And now with AIs as like a third kind of manipulator of digital information there's going to be a lot of refactoring in those in those uh disciplines. Um but the physical world is actually going to be I think behind that by some amount of time.","offset":2413,"duration":11},{"text":"Andrej Karpathy: And so I think what's really fascinating to me is like so that's why I was highlighting the professions that fundamentally manipulate digital information. This is work you could do from your home etc. because I feel like those will be like things will change.","offset":2424,"duration":12},{"text":"Andrej Karpathy: And that doesn't mean that there's going to be less of those jobs or more of those jobs because it that has to do with like demand elasticity and many other factors, but things will change in these professions because of these new tools and uh because of this upgrade to the nervous system of the human superorganism if you want to think of it that way.","offset":2436,"duration":15},{"text":"Host: Given the look you had at the data, do you have either any observations or um uh guidance for people facing the job market or thinking about what to study now or what skills to develop?","offset":2451,"duration":3},{"text":"Host: I mean we can all go get like I'm very thankful that I have to like meet people for my job right now. Uh we can be more physical, yeah.","offset":2454,"duration":15},{"text":"Andrej Karpathy: Could you do your work from home though? Uh I could.","offset":2469,"duration":3},{"text":"Host: I think there are relationship parts of it that are hard, but most of it I could.","offset":2472,"duration":5},{"text":"Andrej Karpathy: Yeah, I think it's really hard to tell because again like the job market is extremely diverse and I think the answers will probably vary, but to a large extent like these tools are extremely new, extremely powerful, and so just being you know just trying to keep up with it is like the first thing.","offset":2477,"duration":14},{"text":"Andrej Karpathy: Um and uh yeah because I think a lot of people kind of like dismiss it—","offset":2491,"duration":2},{"text":"Host: Or they're afraid of it.","offset":2493,"duration":1},{"text":"Andrej Karpathy: —or they're afraid of it etc. which is totally understandable of course. Yeah I think like um it's fundamentally an empowering tool at the moment.","offset":2494,"duration":8},{"text":"Andrej Karpathy: Um and these jobs are bundles of tasks, and some of these tasks can go a lot faster, and so people should think of it as primarily a tool that it is right now. Um and I think the long-term future of that is uncertain.","offset":2502,"duration":9},{"text":"Andrej Karpathy: Yeah it's kind of really hard to forecast to be honest and like I'm not professionally like doing that really and I think this is a job of like economists to do properly.","offset":2511,"duration":9},{"text":"Host: You are an engineer though, uh and like one thing I thought was interesting is that like the the demand for engineering jobs is continuing to increase.","offset":2520,"duration":8},{"text":"Host: Um I I can't tell if that's like a temporary phenomenon I'm not sure how I feel about it yet, do you know?","offset":2528,"duration":5},{"text":"Andrej Karpathy: Yeah, that's like the demand elasticity almost. Like uh software was scarce, right? And so the reason we don't have more demand for software is just scarcity and it's too expensive.","offset":2533,"duration":8},{"text":"Host: It's too expensive, yeah.","offset":2541,"duration":1},{"text":"Andrej Karpathy: So if the barrier comes down then actually you have the Jevons paradox which is like, you know, actually the demand for software actually goes up. It's cheaper and there's more more for it, more powerful.","offset":2542,"duration":7},{"text":"Andrej Karpathy: The classical example of this always is the ATMs and the bank tellers. Because there was a lot of like fear that uh ATMs and computers basically uh would displace tellers, but what happened is they made like the cost of operation of uh of a bank branch much cheaper and so there were more bank branches so there were more tellers is like the canonical example people cite.","offset":2549,"duration":22},{"text":"Andrej Karpathy: But basically it's just Jevons paradox. Like something becomes cheaper so there's a lot of unlocked demand for it. So I do think that that's probably I do have like a cautiously optimistic view of this in software engineering where I do think the uh it does seem to me like the demand for software will be extremely large.","offset":2571,"duration":17},{"text":"Andrej Karpathy: Um and it's just become a lot cheaper. And um so I do think that for quite some time, um it's very hard to forecast, but it does seem to me like right now at least locally there's going to be more demand for software.","offset":2588,"duration":10},{"text":"Andrej Karpathy: Uh because software is amazing. It's like, you know, digital information processing, you're not forced to use like arbitrary tools that were given to you that are imperfect in various ways. You're not forced to subscribe to what exists.","offset":2598,"duration":12},{"text":"Andrej Karpathy: Uh code is now ephemeral and it can change and it can be modified. Um and so I think there's going to be a lot of activity in the digital space to like rewire everything in a certain sense, and I think it's going to create a lot of demand for for this kind of stuff.","offset":2610,"duration":13},{"text":"Andrej Karpathy: I think long term, uh yeah obviously even with AutoResearch like OpenAI or or, you know, Anthropic or these other labs like they're employing what like a thousand something researchers, right? These researchers are basically like glorified AutoResearcher—","offset":2623,"duration":16},{"text":"Host: You know?","offset":2639,"duration":1},{"text":"Andrej Karpathy: They're like automating themselves away like actively and this is like the thing they're all trying to do.","offset":2640,"duration":4},{"text":"Host: Yeah. Some of those researchers also fear fear the psychosis, right? Because they can it's working.","offset":2644,"duration":7},{"text":"Host: And so they're like uh it's over for me too.","offset":2651,"duration":1},{"text":"Andrej Karpathy: I did spend a bunch of time going around OpenAI and I was like, you guys realize if we're successful like we're all out of job, like like just going we're just building automation for Sam or something like that, like oh or the board I'm not sure, but like uh just building this automation for yeah the board or the CEO or something like that and we're all out of our job and maybe contributing on sides.","offset":2652,"duration":20},{"text":"Andrej Karpathy: And so yeah it's kind of un-unnerving from that perspective.","offset":2672,"duration":4},{"text":"Host: Is it okay if I ask a NOMS question? Um you know you could be doing that, right? AutoResearching with a lot of compute scale and a bunch of colleagues at one of the frontier labs. Like why not?","offset":2676,"duration":9},{"text":"Andrej Karpathy: Well I was there for a while, right? Like and I did re-enter. So to some extent I agree and I think that there are many ways to slice this question. It's a very loaded question a little bit.","offset":2685,"duration":9},{"text":"Andrej Karpathy: Um I will say that I feel very good about like what people can contribute and their impact uh outside of the frontier labs obviously.","offset":2694,"duration":6},{"text":"Andrej: ...not in the industry, but also in like more ecosystem level roles. Um, so your role, for example, is more like ecosystem level. My role currently is also kind of more on ecosystem level. And I feel very good about like impact that people can have in those kinds of roles.","offset":2700,"duration":12},{"text":"Andrej: I think conversely, there's there are definite problems in my mind for um basically aligning yourself way too much with the frontier labs too. So fundamentally, I mean, you're, you have a huge amount of financial incentive to um with these frontier labs.","offset":2712,"duration":12},{"text":"Andrej: And by your own admission, the the AIs are going to like really change humanity and society in very dramatic ways, and here you are basically like building the technology and benefiting from it, like and being like very allied to it through financial means.","offset":2724,"duration":17},{"text":"Andrej: Like this was the conundrum that was in um at the heart of, you know, how OpenAI was started in the beginning, like this was the conundrum that were trying to solve. Um, and so, you know, that so it's kind of...","offset":2741,"duration":10},{"text":"Host: It's still not resolved.","offset":2751,"duration":1},{"text":"Andrej: The conundrum is still not like fully resolved. So that's number one. You can't you're not a completely free agent, and you can't actually like be part of that conversation in a fully autonomous, um, free way. Like if you're inside one of the frontier labs, like there's some things that you can't say,","offset":2752,"duration":18},{"text":"Andrej: ...and conversely, there are certain things that the organization wants you to say, and, you know, they're not going to twist your arm, but you feel the pressure of like what you should be saying, you know, because like obviously, otherwise, like really awkward conversations, strange side-eye, like what are you doing, you know?","offset":2770,"duration":11},{"text":"Andrej: So you can't like really be an independent agent. And I feel like a bit more like aligned with humanity in certain sense outside of the frontier lab, because I don't I'm not subject to those pressures almost, right? And I can say whatever I want, or...","offset":2781,"duration":13},{"text":"Andrej: Yeah, I would say in the frontier labs, like, um, you can have like impact there, of course, as well. So um, but there's many researchers, and maybe you're one of them, maybe your ideas are really good, etc.","offset":2794,"duration":10},{"text":"Andrej: Maybe there's a lot of decision making to to do, and you want to be in a position where you are in the room with those conversations when they come up. I do think that currently the stakes are like overall fairly low, and so everything is kind of like nice.","offset":2804,"duration":10},{"text":"Andrej: But ultimately, at the end of the day, like when the stakes are really high, etc., if you're an employee at an organization, I don't actually know how much sway you're going to have on the organization, what it's going to do. Like fundamentally, at the end of the day, um, it's you're not like really in charge.","offset":2814,"duration":14},{"text":"Andrej: You're like in the room and you're contributing ideas, but you're not like really in charge of that entity that you're that you're a part of. So those are like some sources of misalignment, I think, to some extent.","offset":2828,"duration":10},{"text":"Andrej: I will say that like in one way I do agree a lot with that sentiment that um I do feel like in the like the labs for better or worse, they're opaque and a lot of work is there, and they're kind of like at the edge of capability and what's possible,","offset":2838,"duration":14},{"text":"Andrej: ...and they're working on what's coming down the line. And I think if you're outside of the frontier lab, uh your your judgment fundamentally will start to drift, because you're not part of the, you know, what's coming down the line.","offset":2852,"duration":12},{"text":"Host: Right.","offset":2864,"duration":1},{"text":"Andrej: And so I feel like my judgment will inevitably start to drift as well, and I won't actually have an understanding of how these systems actually work under the hood. It's an opaque system. Um, I won't have a good understanding of how it's going to develop, and etc.","offset":2865,"duration":12},{"text":"Andrej: And so I do think that in that sense, I agree, and something I'm nervous about. I think it's worth basically basically being in touch with what's actually happening, and actually being in the frontier lab.","offset":2877,"duration":10},{"text":"Andrej: And if if some of the frontier labs would have me come for, you know, some amount of time and do really good work for them, and then maybe come in...","offset":2887,"duration":6},{"text":"Host: Guys, he's looking for a job! This is super exciting.","offset":2893,"duration":2},{"text":"Andrej: ...then I think that's maybe a good setup, because I kind of feel like it kind of, um, you know, maybe that's like one way um to actually be connected to what's actually happening, but also not feel like you're necessarily fully controlled by by those entities.","offset":2895,"duration":11},{"text":"Andrej: So I think honestly, in my mind, like Noam can probably get do extremely good work at OpenAI, but also I think his most um impactful work could very well be outside of OpenAI.","offset":2906,"duration":13},{"text":"Host: Noam, that's a call to be an independent researcher with AutoResearch.","offset":2919,"duration":2},{"text":"Andrej: Yeah, there's many things to do on the outside, and it's a and I think ultimately I think the ideal solution maybe is like yeah, going back and forth, uh or um yeah, and I think fundamentally you can have really amazing impact in both places.","offset":2921,"duration":11},{"text":"Andrej: So very complicate- I don't know, like it's a very loaded question a little bit, but I mean I joined the frontier lab and now I'm outside, and then maybe in the future I'll want to join again, and I think um that's kind of like how I look at it.","offset":2932,"duration":13},{"text":"Host: One question related to what visibility does the world or the AI ecosystem have into um the frontier is like how how close open source is to the frontier, um and how sustainable that is.","offset":2945,"duration":14},{"text":"Host: I I think it is quite surprising, the entire sequence of events actually, from like having a handful of Chinese models and global models, and I think people are going to continue releasing here in the near term that are closer than much of the industry anticipated from a capability perspective.","offset":2959,"duration":17},{"text":"Host: Um, I don't know if you're surprised by that, you're a long term contributor to open source, like what's your prediction here?","offset":2976,"duration":6},{"text":"Andrej: Yeah, so roughly speaking, basically, the um, yeah, the closed models are ahead, but like people are monitoring the number of months that sort of like open source models are behind.","offset":2982,"duration":10},{"text":"Host: And it started with there's nothing, and then it went to 18 months, and now it's like our convergence.","offset":2992,"duration":4},{"text":"Andrej: Yeah, and then a convergence, right? So um, maybe they're behind by like what is the latest? Maybe like eight months, six months, eight months kind of right now. Yeah, I'm a huge fan of open source, obviously.","offset":2996,"duration":10},{"text":"Andrej: So for example, in operating systems, you have like closed source like, you know, Windows and macOS, these are large software projects, kind of like what LLMs are going to become. And there's Linux.","offset":3006,"duration":9},{"text":"Andrej: But Linux is very easy, like actually Linux is an extremely successful project. It runs on the vast majority of computers. Like last time I checked, was it like 60 percent or something like run Linux?","offset":3015,"duration":10},{"text":"Andrej: Um, and that's because there is a need in industry to have a common open platform that everyone feels um sort of safe using. I would say like the industry has always felt a demand for that kind of a project to exist.","offset":3025,"duration":11},{"text":"Andrej: Um, and I think the same is true now, and that's why businesses actually want- there's demand for this kind of a um a thing to exist. The big difference is that everything is capital um there's large CapEx that goes into this. Um, so I think that's where things like fall apart a little bit, and make it a bit harder to to compete in some sense.","offset":3036,"duration":18},{"text":"Andrej: Um, I I do think that the current models are very good. The other thing that I think is like really interesting is that for the vast majority of like consumer use cases and things like that, even like current open source models are actually quite good, I would say.","offset":3054,"duration":12},{"text":"Andrej: And I think like if you go forward like more um more years, it does seem to me like a huge amount of like simple use cases are going to be well covered and actually even run locally.","offset":3066,"duration":11},{"text":"Andrej: Um, but there's going to be always like some demand for like frontier intelligence, and that that can actually be an extremely large piece of the pie. But it could be that the frontier, the need for frontier intelligence is going to be like, you know, Nobel Prize kind of work, or like let's move Linux from C to Rust is going to be like bigger projects, you know, like scoped in that kind of a way.","offset":3077,"duration":19},{"text":"Andrej: And there's going to be maybe more um and maybe that's where a lot of the frontier closed intelligences were going are going to be interacting with. And open source kind of like going to eat through a lot of the more basic use cases or something like that.","offset":3096,"duration":14},{"text":"Andrej: You know, at some point, what is frontier today is going to be, you know, probably later this year what's frontier today in terms of what I'm using right now from the closed labs might be open source, and that's going to be doing a lot of work.","offset":3110,"duration":11},{"text":"Andrej: So I kind of expect that this dynamic will actually basically continue. Like we'll have frontier labs that have closed um AIs that are kind of like these oracles, and then we'll have open source kind of like behind by some amount of months.","offset":3121,"duration":10},{"text":"Andrej: And I kind of expect that to uh to continue. And I actually think that's like a pretty pretty good setup um overall, um because I I'm a little bit hesitant of having um I don't actually think it's like structurally, I think there's some systemic risk attached to just having intelligences that are closed, and that's like that's it.","offset":3131,"duration":16},{"text":"Host: Mm-hmm.","offset":3147,"duration":0},{"text":"Andrej: And I think that that's a, you know, centralization has a very poor track record in my view, um in the in the past.","offset":3147,"duration":7},{"text":"Host: You mean like in political or economic systems? In general?","offset":3154,"duration":2},{"text":"Andrej: Yes. Exactly.","offset":3156,"duration":1},{"text":"Host: Spoken like an Eastern European, yes.","offset":3157,"duration":3},{"text":"Andrej: Okay, exactly. I think there's like a lot of pretty bad precedents, and so I want there to be a thing that is maybe not at the edge of capability because it's new and unexplored etc., but I want there to be a thing that's behind and that is kind of like a common working space for intelligences that the entire industry has access to. Yeah, that seems to me like a pretty decent power balance for the industry.","offset":3160,"duration":16},{"text":"Host: Yeah.","offset":3176,"duration":5},{"text":"Andrej: Yeah. I also think there's just like there are many problems to solve, right? Like if you keep advancing intelligence from the frontier, we can do new things and there are a lot of like very big problems for humanity, right?","offset":3181,"duration":11},{"text":"Host: Yeah.","offset":3192,"duration":1},{"text":"Andrej: And so like it seems that that will continue to be a very expensive game, and so I want to like root for labs that are doing that, because there are problems we cannot solve without continuing to advance the models in a very expensive way.","offset":3193,"duration":11},{"text":"Host: And yet, as you point out, like if what we have today as frontier is open, that's a lot of capability.","offset":3204,"duration":9},{"text":"Andrej: Yeah.","offset":3213,"duration":1},{"text":"Host: Right. And and so I think, you know, the power of that or the democratization of that seems like very useful and also healthy.","offset":3214,"duration":8},{"text":"Andrej: Yeah. I think basically by accident we're actually like in an okay spot in an optimal yeah, yeah. By accident we are happen to be in a good spot in a certain sense.","offset":3222,"duration":10},{"text":"Host: Um well, and and to some degree, the the longer this endures, like this dynamic, um the the healthier of a spot like the ecosystem might be in, right? Because you have more and more area under the curve.","offset":3232,"duration":13},{"text":"Andrej: And I will say that even on the closed side, I almost feel like it's been like even further centralizing in recently, because I think a lot of the frontrunners are like not necessarily like the top tier.","offset":3245,"duration":9},{"text":"Andrej: And so um yeah, I like in that sense I think it's um not super ideal. I would love there to be more more frontier labs because, yeah, I'm like by default very suspicious of like um I want there to be more people in the room, I want-","offset":3254,"duration":13},{"text":"Andrej: I think like in machine learning, ensembles always outperform any individual model, and so I want there to be ensembles of people thinking about all the hardest problems, and I want there to be ensembles of people in a room when they um to be all well-informed and to make all those decisions, you know, so...","offset":3267,"duration":17},{"text":"Andrej: I don't want it to be like a closed doors with two people or three people. I feel like that's like not a good not a good future. I almost wish like there were more labs is long story short, and I all- I do think that the open source um has a uh has a place to play. I hope it sticks around, and I basically- it's currently slightly behind and that's actually kind of a good thing.","offset":3284,"duration":15},{"text":"Host: Okay, you worked on the precursor to generalized robotics, autonomy, um in cars, right? Um, a a lot has happened in the last couple months with robotics companies as well, like acceleration of really impressive generalization of environment, of tasks, like increasing long horizon tasks, lots of money going into the space. Like is it going to happen? Has anything in your view changed recently?","offset":3299,"duration":29},{"text":"Andrej: Um, so like my view is kind of informed by what I saw in self-driving. And I do feel like self-driving is the first robotics application. So probably what I saw is at the time, like 10 years ago, there were a large number of startups, and I kind of feel like um like most of them basically didn't long-term make it.","offset":3328,"duration":17},{"text":"Andrej: Um, and what I saw is that like a lot of capital expenditure had to go in, and a lot of time. And so um I think it like I think robotics because it's so difficult and so messy and requires huge amount of capital investment and a lot of like conviction, um just it's like a big problem.","offset":3345,"duration":15},{"text":"Andrej: And I think atoms are really hard. So I kind of feel like they will lag- it will lag behind what's going to happen in the digital space. And in digital space, there's going to be a huge amount of unhobbling.","offset":3360,"duration":10},{"text":"Andrej: Basically like things that weren't super efficient becoming a lot more efficient by like a factor of a hundred because bits are so much easier. And so I think currently in terms of what's going to change and like where the activity is, I kind of feel like digital space is going to like change a huge amount, and then the physical space will lag behind.","offset":3370,"duration":17},{"text":"Andrej: And what I find very interesting is like this interface in between them as well. Because I think in this like if we do have more agents acting on behalf of humans and more agents kind of like talking to each other and and doing tasks and participating in the kind of economy of agents etc., um you're going to run out of things that you're going to do purely in the digital space.","offset":3387,"duration":20},{"text":"Andrej: At some point you have to go to the universe and you have to ask it questions. Um you have to run an experiment and see what the universe tells you to get back to learn something. And so we currently have a huge amount of like digital work uh because there's an overhang in how much we collectively thought about what already is digital.","offset":3407,"duration":18},{"text":"Andrej: So we just didn't have enough thinking cycles among the humans to think about all the information that is already digital and already uploaded. Um and so we're going to start running out of stuff that is actually like um already up- uploaded. Uh so you're going to at some point read all the papers and process them and have some ideas about what to try.","offset":3425,"duration":16},{"text":"Andrej: But um yeah, we're just going- I don't actually know how much you can like get intelligence that's like fully closed off and with just the information that's available to it, you know? And so I think what's going to happen is first there's going to be huge amount of unhobbling, and I think there's huge amount of work there.","offset":3441,"duration":14},{"text":"Andrej: Then actually it's going to move to like the interfaces between physical and digital. So I and that's like sensors of like seeing the world and actuators of like doing something to the world.","offset":3455,"duration":9},{"text":"Andrej: So I think a lot of interesting companies will actually come from that interface of like can we feed the superintelligence in a certain sense data, and can we actually like take data out and manipulate the physical world um per its bidding, if you want to like anthropomorphize the whole thing, right?","offset":3464,"duration":16},{"text":"Andrej: And then the physical world actually I almost feel like the total addressable market etc. in terms of like the amount of work and so on is is massive, possibly even much larger maybe what can happen in digital space.","offset":3480,"duration":12},{"text":"Andrej: So I actually think it's like a much bigger opportunity as well, but um I do feel like it's huge amount of work and in my my view the atoms are just like a a million times harder. So um so it will lag behind, but it's also I think a little bit of a bigger market.","offset":3492,"duration":13},{"text":"Andrej: So it's kind of like uh yeah I think the opportunity is kind of like follow that kind of trajectory. So right now this digital is like my main interest, then interfaces would be like after that, and then maybe like some of the physical things, um like their time will come and they'll be huge uh when they do come.","offset":3505,"duration":17},{"text":"Host: Well it's an interesting framework for it too because uh certain things, not the things I'm working on right now, but certain things are much easier even in the world of atoms, right? Like if you just think about like read and write to the physical world, like read, like sensors, cameras, like there's a lot of existing hardware and you can imagine like enriching agent capabilities or capturing a lot of new data if you're just clever about it and like you don't necessarily have to invest a lot to like get something valuable.","offset":3522,"duration":28},{"text":"Andrej: Yeah.","offset":3550,"duration":1},{"text":"Host: Yeah.","offset":3551,"duration":1},{"text":"Andrej: So like examples of this that I saw for example are, you know, um a friend of mine, Liam, is run- is a CEO of Periodical. Um I visited them last week, so it's just on top of mind. Like they're trying to do auto research for material science. Um and so in that case it's like the sensors to the intelligence are actually like pretty expensive lab equipment.","offset":3552,"duration":16},{"text":"Andrej: And the same is true in biology, I think a lot of people are very interested in engineering biology, and, you know, the sensors will be more than just like video cameras if that makes sense. And then the other thing I I saw, for example, is companies that are trying to have um like you basically pay people for training data...","offset":3568,"duration":14},{"text":"Host: Yeah. Programmatically.","offset":3582,"duration":1},{"text":"Andrej: ...as an example to feed... Yeah, to feed- to feed the borg. Um and so like these are all examples of like sensors in a certain sense. So they take many diverse shapes and forms, if that makes sense.","offset":3583,"duration":9},{"text":"Host: Hmm. Yeah, so I'm looking forward to the point where I can ask for a task in the physical world and I can put a price on it and just tell the agent like, you know, you figure out how to do it. Go get the data.","offset":3592,"duration":12},{"text":"Andrej: I'm actually kind of surprised we don't have enough like information markets. Like for example, if Polymarket or other betting markets or even stocks etc., if they have so much autonomous activity and rising amount of activity, like uh why should- like for example, if Iran was just happening now, like how come there isn't a process where like taking a photo or video from somewhere in Tehran should cost like 10 bucks.","offset":3604,"duration":19},{"text":"Andrej: Like someone should be able to pay for that, you know? And that's an example of like feeding the intelligence. There's not going to be a human looking at it, it's going to be like agents who are trying to guess the betting games and stock markets and so on.","offset":3623,"duration":12},{"text":"Andrej: Hmm. So I kind of feel like the agentic vibe is still like fairly new that there's no like mechanisms for this, but this is an example of what I think might happen. There's a good um book that maybe is inspiring called Daemon. Uh-huh. You've potentially read it?","offset":3635,"duration":12},{"text":"Host: In Daemon the intelligence um ends up like puppeteering almost a little bit like humanity in certain sense, you know? And so humans are kind of like its actuators, but humans are also like its sensors. Um and so maybe I think like collectively like society will kind of like reshape in a certain way in uh to serve that kind of a uh that will kind of like end up happening collectively across the industry where, yeah, there's just a lot more automation and it has certain needs and kind of humans will be serving those needs of that of that machine, not necessarily like to each other.","offset":3647,"duration":24},{"text":"Host: Well we were um on this very specific point of uh like missing pieces of training data, we needed um we needed something like auto research, right? Like we need the training cycle or the SFTP piece to be um far more mechanized.","offset":3671,"duration":14},{"text":"Andrej: Uh-huh. For for which part?","offset":3685,"duration":2},{"text":"Host: In order to make the um collection, like to in order to take the human out of the loop to ask for a task that is just like improve my model quality with new data, right?","offset":3687,"duration":9},{"text":"Andrej: Um, yes.","offset":3696,"duration":1},{"text":"Host: Does that make sense to you? Like we um, if you can't have the model do the training runs by itself, then your ability to do this as a like closed-loop task with uh by pricing data is um more challenged.","offset":3697,"duration":14},{"text":"Andrej: Uh, yes, 100%. Yeah. But the thing is-","offset":3711,"duration":3},{"text":"Host: But now we go.","offset":3714,"duration":2},{"text":"Andrej: The thing is for LLM training, it actually is like very easily it like really fits the paradigm. Um, so you'd actually expect-","offset":3716,"duration":7},{"text":"Host: Yeah, clean metric.","offset":3723,"duration":1},{"text":"Andrej: Yeah, like LLM training actually fits the paradigm really well, really easily. Like all the optimization of all the code and so it runs faster, and then you also have like metrics that you can optimize against.","offset":3724,"duration":9},{"text":"Andrej: I do think that if you had an autonomous loop over those metrics, there's going to be a lot of like goodhearting going on where the system will like overfit to those metrics. And so but then you can use the system to devise more metrics and you just have really good coverage. So it's kind of hard to tell but um in a certain sense it's like a pretty pretty good fit.","offset":3733,"duration":17},{"text":"Host: I want to talk about a little um tiny side project you have before we end. Um tell me about the MicroGPT effort.","offset":3750,"duration":8},{"text":"Andrej: Oh yeah. Okay, so MicroGPT. So, I have this like running obsession of like maybe a decade or two of just like simplifying and boiling down the basically LLMs uh to like their bare essence. And I've had a number of projects along these lines, so like NanoGPT and um MakeMore and uh Micro- Micrograd etc.","offset":3758,"duration":20},{"text":"Andrej: So I feel like MicroGPT is now the state of the art of me trying to like just boil it down to the essence. Because the thing is like training neural nets and LLMs specifically um is huge amount of code, but all of that code is actually complexity from efficiency.","offset":3778,"duration":13},{"text":"Host: Hmm.","offset":3791,"duration":1},{"text":"Andrej: It's just because you need it to go fast. If you don't need it to go fast and you just care about the algorithm, then that algorithm actually is 200 lines of Python. Very simple to read. And this includes comments and everything.","offset":3792,"duration":10},{"text":"Andrej: Um, because you just have like uh your data set which is a text, um and you need your neural network architecture which is like 50 lines, you need to do your forward pass, and then you have to do your backward pass to calculate the gradients.","offset":3802,"duration":9},{"text":"Andrej: And so an auto-grad engine uh to calculate the gradients like 100 lines, and then you need an optimizer, an Adam, for example, uh which is like again 10 lines, really. And so putting everything together in a training loop is like, yeah, 200 lines.","offset":3811,"duration":12},{"text":"Andrej: And what was interesting to me like normally before like maybe a year ago or more, if I had come up with MicroGPT, I would be tempted to basically explain to people like have a video like stepping through it or something like that, um and I actually tried to make that video a little bit, and I tried to make like a little guide to it and so on.","offset":3823,"duration":16},{"text":"Andrej: But I kind of realized that this is is not really is not really adding too much because people because it's already so simple that it's 200 lines, that anyone could ask their agent to explain it in various ways and the agents- like I'm not explaining to people anymore, I'm explaining it to agents.","offset":3839,"duration":16},{"text":"Andrej: If you can explain it to agents, then agents can be the router and they can actually target it to the human in their language with infinite, um you know, patience and uh just at their capability and so on.","offset":3855,"duration":11},{"text":"Host: Right, if I don't understand um this particular function, I can ask the agent to explain it to me like three different ways, and I'm not going to get that from you.","offset":3866,"duration":7},{"text":"Andrej: Yeah. Exactly. Yeah. And so I kind of feel like, you know, what is education? Like it used to be guides, it used to be lectures, it used to be this thing, but now I feel like now more I'm explaining things to agents.","offset":3873,"duration":8},{"text":"Andrej: And maybe I'm coming up with skills um where like um so basically skill is just a way to instruct the agent how to teach the thing. So maybe I could have a skill for MicroGPT of the progression I imagine the agent should take you through if you're interested in understanding the codebase.","offset":3881,"duration":13},{"text":"Andrej: And it's just like hints to the model to like oh first start off with this and then with that, and so I could just script the curriculum a little bit as a skill. Um so so I don't feel like um yeah I feel like there's going to be less of like explaining things directly to people and it's going to be more of just like does the agent get it?","offset":3894,"duration":16},{"text":"Andrej: And if the agent gets it they'll do the explanation. And we're not fully there yet because they I still can I still think I can probably explain things a little bit better than the agents, but I still feel like the models are improving so rapidly that um I feel like it's a losing battle to some to some extent.","offset":3910,"duration":15},{"text":"Andrej: Um and so I think education is going to be kind of like reshuffled by this uh quite substantially um where it's the end of like teaching each other things almost a little bit. Like if I have a uh library, for example, of code or something like that, it used to be that you have documentation for other people who are going to use your library.","offset":3925,"duration":16},{"text":"Andrej: But like you shouldn't do that anymore. Like you should have instead of HTML documents for humans, you have markdown documents for agents, because if agents get it, then they can just explain all the different parts of it.","offset":3941,"duration":9},{"text":"Andrej: So it's this redirection through agents, you know? Um and that's like why so I think we're going to see a lot more of that playing out.","offset":3950,"duration":10},{"text":"Host: Well we'll see if the great teachers know like to develop intuition for how to explain things to agents differently.","offset":3960,"duration":5},{"text":"Andrej: Oh yeah. Ultimately, so for example, MicroGPT, like I asked I tried to get an agent to write MicroGPT. So I told it like try to boil down the simplest things, like try to boil down micro- neural network training to the simplest thing and it can't do it.","offset":3965,"duration":14},{"text":"Andrej: Like MicroGPT is like my is it's like my end of my obsession. It's the 200 lines. I thought about this for a long time. I've obsessed about this for a long time. This is this is the solution. Trust me it can't get simpler.","offset":3979,"duration":10},{"text":"Andrej: And this is this is my value add. Everything else like agent gets it. It just can't come up with it but it totally gets it and understands why it's done in a certain way, etc. So like my contribution is kind of like these few bits, but everything else in terms of like the education that goes on after that is like not my domain anymore.","offset":3989,"duration":17},{"text":"Andrej: So maybe yeah it's like education kind of changes in those ways where you kind of have to infuse the few bits that you feel strongly about the curriculum or the the better way of explaining it or something like that. The things that agents can't do is your job now.","offset":4006,"duration":13},{"text":"Host: Hmm.","offset":4019,"duration":1},{"text":"Andrej: The things that agents can do they can probably do better than you or like very soon. And so you should be strategic about what you're actually spending time on.","offset":4020,"duration":7},{"text":"Host: Well we appreciate the few bits. Thank you Andrej.","offset":4027,"duration":4},{"text":"Andrej: Okay.","offset":4031,"duration":1},{"text":"Host: Find us on Twitter at NoPriorsPod. Subscribe to our YouTube channel if you want to see our faces. Follow the show on Apple Podcasts, Spotify, or wherever you listen. That way you get a new episode every week. And sign up for emails or find transcripts for every episode at no-priors.com.","offset":4032,"duration":15}],"logs":[{"elapsed":"0.0","message":"Downloading audio from YouTube...","detail":null},{"elapsed":"0.0","message":"Trying download with browser cookies (ad-free)...","detail":null},{"elapsed":"2.7","message":"⚠ Cookie download failed: WARNING: [youtube] [jsc] Error solving n challenge request using \"deno\" provider: Error running deno process (returncode: 1): \u001b[0m\u001b[1m\u001b[31merror\u001b[0m: Uncaught (in promise) TypeError: Cannot read prope","detail":null},{"elapsed":"2.7","message":"Retrying without cookies...","detail":null},{"elapsed":"36.4","message":"⚠ Downloaded without cookies — audio may contain ads","detail":null},{"elapsed":"36.4","message":"Audio downloaded (42.8 MB) in 36.4s","detail":"File size: 42.8 MB"},{"elapsed":"36.4","message":"Video title: Skill Issue: Andrej Karpathy on Code Agents, AutoResearch, and the Loopy Era of AI","detail":null},{"elapsed":"36.4","message":"Audio duration: 1:06:31 (66.5 min)","detail":null},{"elapsed":"36.4","message":"Large audio (66.5 min) — will use chunked transcription with gemini-3-flash-preview","detail":null},{"elapsed":"36.4","message":"Skipping full-file attempt — using chunked transcription for 66.5 min audio","detail":null},{"elapsed":"36.9","message":"Split audio into 2 chunks for transcription","detail":null},{"elapsed":"36.9","message":"Transcribing chunk 1/2 (starts at 0:00)...","detail":null},{"elapsed":"36.9","message":"Uploading audio to Gemini File API...","detail":null},{"elapsed":"41.5","message":"Audio uploaded in 4.7s","detail":"File ref: files/932y2h9jszr9"},{"elapsed":"41.5","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"134.7","message":"Chunk 1: 304 segments, last timestamp 44:54","detail":null},{"elapsed":"134.7","message":"Transcribing chunk 2/2 (starts at 45:00)...","detail":null},{"elapsed":"134.7","message":"Uploading audio (offset 45:00) to Gemini File API...","detail":null},{"elapsed":"137.6","message":"Audio uploaded in 2.9s","detail":"File ref: files/7yinj5oev3rq"},{"elapsed":"137.6","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"189.4","message":"Adjusted chunk 2 timestamps by +45:00","detail":null},{"elapsed":"189.4","message":"Chunk 2: 125 segments, last timestamp 1:07:12","detail":null},{"elapsed":"189.4","message":"Chunked transcription complete: 429 total segments","detail":null},{"elapsed":"189.4","message":"Total cost: 100,249 in / 23,853 out — cost: $0.1217","detail":null},{"elapsed":"189.4","message":"Total transcription time: 153.0s — 429 segments","detail":null},{"elapsed":"189.4","message":"Analyzing topics across 429 segments with gemini-3.1-pro-preview...","detail":null},{"elapsed":"241.2","message":"Topic analysis complete in 51.8s — found 16 topics","detail":null},{"elapsed":"241.2","message":"Analysis tokens: 26,023 in / 1,412 out / 5,051 thinking — cost: $0.1296","detail":null},{"elapsed":"241.2","message":"Pipeline finished in 241.2s — total cost: $0.2513 (156,588 tokens)","detail":null}]} \ No newline at end of file diff --git a/history/1775678510294-Mv4cF13glBo.json b/history/1775678510294-Mv4cF13glBo.json new file mode 100644 index 0000000..2d2f663 --- /dev/null +++ b/history/1775678510294-Mv4cF13glBo.json @@ -0,0 +1 @@ +{"id":"1775678510294-Mv4cF13glBo","videoId":"Mv4cF13glBo","url":"https://www.youtube.com/watch?v=Mv4cF13glBo","title":"PMPC217: Beating Fatigue with Dr. Craig Heller","type":"youtube","topicCount":15,"segmentCount":155,"createdAt":"2026-04-08T20:01:50.294Z","uploadDate":"20240610","chunks":[{"title":"Sponsor & Episode Introduction","summary":"The host reads a sponsor message from Victory Grips and introduces Dr. Craig Heller, outlining the podcast's focus on fitness recovery and the CoolMitt system.","entries":[{"text":"Host: This episode is sponsored by Victory Grips. Victory Grips are the standard in hand protection. Plus, they just launched their new gym affiliate program. As affiliate owners, they understand the demands of gym owners. Their goal is to keep their gym referral program process as simple as possible. You'll receive educational content, early access to upcoming releases, and exclusive discounts for your members, plus receive a percentage of the net sales. Find out more at victorygrips.com.","offset":0,"duration":30},{"text":"Host: Welcome to the Power Monkey podcast, where we chat with the best in the world of fitness about what they do. I'm host Dave Durante, with my co-host this week being Jordan Samuel and Mike Service. And today, our guest is Dr. Craig Heller. Dr. Heller is the Lory Lokey Business Wire Professor of Biological Sciences and Human Biology at Stanford University. I was lucky enough to study under Dr. Heller when I was a Human Biology major at Stanford many, many years ago, and it's an absolute honor to have him on the podcast to speak about one of his companies working in the fitness recovery space, CoolMitt.","offset":30,"duration":40},{"text":"Host: Dr. Heller discusses what's really going on in your muscles when you work out, what causes fatigue to set in, and how the CoolMitt system can assist in helping to not only recover faster but also increase your gains. I found this to be an absolutely fascinating conversation, and it helped clear up some misconceptions around fatigue-causing factors. Dr. Heller takes some very complex internal functions and makes them accessible to the general population. I know we'll be making a more concerted effort to recover differently during our workouts after this conversation. We hope you enjoy this one as much as we did.","offset":70,"duration":40}],"startTime":0},{"title":"Welcoming Dr. Craig Heller","summary":"Dave Durante welcomes Dr. Heller to the show, reminiscing about being his student at Stanford. Dr. Heller shares a brief anecdote about running into former students.","entries":[{"text":"Dave Durante: Dr. Heller, thank you so much for being on the podcast with us. It's an honor to have you, and it's a pleasure to see you again. I don't know if this was passed along, but I was a student of yours 25-some years ago as a Hum Bio major at Stanford. And so to see your face again and to see you a part of now the fitness community is a pleasure, so thank you for being with us.","offset":110,"duration":25},{"text":"Dr. Craig Heller: Great to see you. I'll tell you a funny story if we have a minute. Last week I had to get some cortisone injections in my back, and I was lying on a gurney outside of the operating room, and two other surgeons came up to me and said, \"We want you to know you wrote our letters of recommendation to medical school.\"","offset":135,"duration":25},{"text":"Dave Durante: I'm sure the number of people you've impacted in that way has been numerous. So, it's great to see you and thank you so much for taking the time. Well, it's very interesting, the product... we'll get into CoolMitt and what you guys are doing in the recovery space here, but we want to take it back a little bit and just talk a little bit first about failure in the body and why there's a need for something like this.","offset":160,"duration":20}],"startTime":110},{"title":"Muscle Failure and Temperature Regulation","summary":"Dr. Heller explains how muscles generate excess heat during exercise, which deactivates the pyruvate kinase enzyme and causes muscle failure. The group also briefly discusses the prevalence of rhabdomyolysis in the CrossFit community.","entries":[{"text":"Dave Durante: So, could we talk about just the different ways that muscle and the body fails in terms of physical activity, whether that be temperature regulation or lack of strength or lack of recovery? Can we just go through different methods in terms of how the body might fail when it comes to physical activity?","offset":180,"duration":15},{"text":"Dr. Craig Heller: Sure. Well, temperature is of course what we're concerned with. And most people don't realize that we can cook our own muscles. The metabolism of one of our large dynamic muscles can go up much higher than the blood flow to that muscle. And the only way the heat that's generated gets out of the muscle is in the blood.","offset":195,"duration":25},{"text":"Dr. Craig Heller: So, we literally have the capacity... and this is the condition known as rhabdomyolysis, where you actually overwork a muscle, it gets hyperthermic, and it causes the muscle cells to die. So, we have a fail-safe mechanism, and that fail-safe mechanism is the inhibition, the temperature inhibition of a critical enzyme. And when that enzyme gets up to about 39 degrees centigrade, it inactivates.","offset":220,"duration":30},{"text":"Dr. Craig Heller: And once it inactivates, the fuel can't go into the mitochondria, and the mitochondria can't produce ATP, and without ATP, the muscle can't contract. So, if we extract that heat efficiently, we can reactivate the enzyme or we can prevent it from inactivating, and then the muscle just keeps on working. So, I've had some freshman women, for example—maybe your classmates—who were doing over 800 pushups.","offset":250,"duration":35},{"text":"Dr. Craig Heller: So, these were not athletes, these were just normal freshman students. And we've had professional athletes come in, pick an activity they're good at, and that day we can double their normal work volume. And when you get that kind of an increase in your work volume, you get a huge conditioning effect. So, that's one of the limitations.","offset":285,"duration":25},{"text":"Dr. Craig Heller: Now, of course, hypoxia is another limitation. Now, that's not a critical issue for anaerobic activities like lifting, but it is certainly a big deal for anyone who's doing endurance work. And essentially, if you shut off the supply of oxygen to the muscle, once again you can't produce ATP. So, we're not addressing that issue.","offset":310,"duration":25},{"text":"Dr. Craig Heller: That issue you have to address by choosing your altitude and breathing well and conditioning as best you can to operate at maximum levels.","offset":335,"duration":15},{"text":"Dave Durante: There were a couple of things you mentioned in there. One, what is the enzyme that is triggered, just so that we can give it to our listeners, something to be aware of when it comes to some of the science behind what's happening in the mechanism?","offset":350,"duration":15},{"text":"Dr. Craig Heller: It's pyruvate kinase. So, when glucose goes into the cell, it goes through a series of steps called glycolysis, and the bottom step is pyruvate. But just before pyruvate, it's phosphoenolpyruvate that has to be converted to pyruvate. So, it's that conversion step that shuts off the supply of pyruvate to the mitochondria.","offset":365,"duration":35},{"text":"Dr. Craig Heller: This is all our hypothesis. I can't give you data other than the biophysical data that shows the temperature sensitivity of pyruvate kinase. But maybe there are other temperature-sensitive steps that just haven't been investigated yet.","offset":400,"duration":15},{"text":"Dave Durante: It's interesting that you mentioned rhabdo, rhabdomyolysis. It's actually quite common... I don't know how aware you are, but within the CrossFit community it's, especially early on 15-plus years ago, 20 years ago when people didn't know that they could push themselves to the point of cooking their own muscles. It was rather common to see athletes have rhabdo and became part of the lexicon within the CrossFit community early on. And I actually, unfortunately, had a bout of it myself early on when I was first starting CrossFit. Not something you want to go through in terms of the recovery portion if you get it severe.","offset":415,"duration":40},{"text":"Dr. Craig Heller: No, that's pretty bad stuff.","offset":455,"duration":5}],"startTime":180},{"title":"The Discovery of Palmar Cooling","summary":"Dr. Heller details how his research shifted from treating surgery-induced hypothermia to discovering heat-exchanging blood vessels in the palms. He shares the dramatic performance gains seen when cooling a lab assistant's hands between pull-up sets.","entries":[{"text":"Dave Durante: Yeah. So, taking it back even further, I think I heard you talk a little bit about some of the research that you've done on bears and how that research led to some of the thinking around how this could be applied to human performance. Would you mind just telling a little bit of a some some stories of some background in terms of how that research led you to where you are now on this?","offset":460,"duration":15},{"text":"Dr. Craig Heller: Actually, it goes back even farther than that, and it all started with a bet. So, I had studied for many years how the brain controls body temperature, and that's what led to working on hibernation. So, I was very familiar with hibernating animals. But one day, a colleague who's an anesthesiologist said to my colleague and I—my colleague Dennis Grahn, who's my partner in all of this—our friend, the anesthesiologist, said, \"You think you know so much about temperature regulation. I bet you couldn't solve a problem we have in the recovery room.\"","offset":475,"duration":40},{"text":"Dr. Craig Heller: \"Well, what's that?\" \"Patients come out of surgery hypothermic, cold, and as the anesthesia wears off, they shiver violently and it takes the nurses hours to get them to stop shivering. And it's very uncomfortable for not only the patient but for the nurses too.\" So, we said, \"Ah, that's not a hard problem.\" But it was, because if you're hypothermic coming out of anesthesia, what happens is you tightly vasoconstrict and sequester your blood in the core of your body.","offset":515,"duration":30},{"text":"Dr. Craig Heller: Okay, that's the 10% of your body that's critical: the liver, the lungs, the heart, the brain. So, it's very hard to get heat into the body when the blood flow is all concentrated in the core. So, we got an idea that if we put an arm in a negative pressure environment, we could pull blood into the arm, heat the arm, that would go back and heat the core of the body. And we did it, and it worked beautifully.","offset":545,"duration":30},{"text":"Dr. Craig Heller: First patient, less than 10 minutes, was back to normal temperature. And then we found out it had nothing to do with the arm; it was only the hand. And that led to the realization that we have these special blood vessels in the palms of the hands, the soles of the feet, and the face. And these blood vessels are shunts between the arteries and the veins. So, when they open up, the hand gets warm and we dissipate heat.","offset":575,"duration":30},{"text":"Dr. Craig Heller: When you shake someone's hand, you know immediately what their thermal status is, right? So, all of a sudden it dawned on us that what we were doing is using a mammalian adaptation for heat loss in reverse. So, then we started working on treating hyperthermia. And in order to treat hyperthermia, you have to have someone hot. So, how do you get hot? You exercise.","offset":605,"duration":30},{"text":"Dr. Craig Heller: So, we had a lab assistant who was a gym rat, and he would go to the gym every day after work. So, we got him to do some of his workout in the lab. We put up a pull-up bar and had him do sets of pull-ups to muscle failure just to raise his temperature. And one day, for no reason, after we cooled him, after we did the heat extraction, he went back to the pull-up bar and did the same number of pull-ups as in his first set.","offset":635,"duration":25},{"text":"Dr. Craig Heller: And we said, \"Holy crow, what does that mean?\" It means the muscle failure must be due to rise in temperature of the muscle. So, then we started cooling him after every other set of pull-ups, and his performance plateaued, and in that one transition from one day to the next, his work volume went up by—I think it was like 25% something like that. But then we started cooling him after every other set of pull-ups, okay, that's what we were doing.","offset":660,"duration":35},{"text":"Dr. Craig Heller: And in the next in that six-week period... well, go back. The first six weeks we worked on him twice a week, he went from doing 100 pull-ups to 180. But then the next six weeks after we made this realization of what the heat extraction could do, he went from doing 180 to 618.","offset":695,"duration":25},{"text":"Dave Durante: I mean, that's extraordinary. Over what over what period of time and like sets and reps, things like that?","offset":720,"duration":5},{"text":"Dr. Craig Heller: About an hour, 45 minutes to an hour. So, it's 10 sets, maybe it was 12, I don't know, nine or 10 or 12, with three-minute rest. And the rests were either cooling or not cooling. So, when he cooled his volume went up, and that was a gain, and then you keep the gain. If the next time he wasn't cooled, he showed that he had improved his conditioning. So, whenever we cooled, he increased his number.","offset":725,"duration":35},{"text":"Jordan Samuel: I mean, that's extraordinary numbers. Those are... Jordan, you look like you're wanting to chime in there. Well, I guess I wanted to ask a question about about that. So, when you say he kept his gains, um, does that mean that he kept the gain from set to set, like if you did a let's say he did 20 reps and then you cooled him and then he was able to, you know, keep 20 reps and then he comes back the next day and you he did the same two sets but without cooling at that point he's able to maintain 20 reps both times?","offset":760,"duration":30},{"text":"Dr. Craig Heller: Right. It's a real conditioning effect. Adaptation, yeah. In all of these experiments you get a you get a continuous curve over a period of time that you're engaged in the conditioning. So, we've seen it with so many different individ- so many ath- so many ex- exercises: dips, push-ups, bench press, so forth.","offset":790,"duration":35}],"startTime":460},{"title":"Finding the Optimal Cooling Temperature","summary":"A brief discussion on discovering the optimal cooling temperature through trial and error. They settled on 12 degrees Celsius to maximize heat extraction without triggering vasoconstriction.","entries":[{"text":"Dave Durante: Can you give us a little bit of insight into that early strategy around how to cool the body? I mean, to where you are today, um, how did you find the perfect temperature? I mean, uh, you've talked about it, that just cooling as as low as possible is not ideal, sticking your hand in a bucket of ice. How did you go about finding the optimal temperature, and what was that first iteration looking like in terms of how you applied it to an athlete?","offset":825,"duration":25},{"text":"Dr. Craig Heller: It's mostly trial and error. If you do if you do something enough times, you'll make all the possible mistakes. Then you learn from that. So, essentially, um, our first efforts for cooling were just, I just, we just chose a temperature and did it. But then we found that individuals differ. So, for example, when we applied the technology to multiple sclerosis patients, these individuals are very temperature sensitive.","offset":850,"duration":35},{"text":"Dr. Craig Heller: Even a little rise in temperature makes it impossible for them to be active. Uh, so we found that we could only cool them down to about 20, 22 degrees centigrade, or else they would vasoconstrict, they'd shut off the blood supply to the hands. Uh, others, uh, highly performing athletes working hard, we could cool them down to 10 or 12 degrees.","offset":885,"duration":30},{"text":"Dr. Craig Heller: So, for the CoolMitt we just selected 12 degrees as being an optimal temperature. So, for some individuals it might be too cold. Uh, but what you want is you want to get the maximum temperature differential between the device and the blood without causing vasoconstriction.","offset":915,"duration":20}],"startTime":825},{"title":"Alternative Cooling Sites and Adaptations","summary":"The group discusses how calluses, grips, and athletic tape can limit palm cooling. Dr. Heller explains that the feet and face can also be used for cooling, making the technology highly beneficial for amputees and adaptive athletes.","entries":[{"text":"Dave Durante: I have to say, um, I was on the gymnastics team at Stanford, and I remember us testing out this product early on. And there was it just, you know, was there, I don't know who had brought it in, and I was even speaking to some of my former teammates about it recently. I was like, \"Do you guys remember using something that we had our hand kind of in a something the form of a hand and it was meant to kind of cool us down between sessions, between turns?\"","offset":935,"duration":30},{"text":"Dave Durante: And they're like, \"Yeah, we had that as part of our training.\" And it just jogged my memory that we actually were some of the guinea pigs for for this early product that you had so many years ago.","offset":965,"duration":10},{"text":"Dr. Craig Heller: Well, you guys weren't very good guinea pigs because your hands are so calloused. No, that's interesting. Does that play into- does that play into an effect, yeah? Oh, and same thing for football, for example, if they're taped. I mean, you- that's going to block the the heat flow. So, what you can do is you can of course wet it, uh, minimize the tapes, or lower the temperature of the device.","offset":975,"duration":25},{"text":"Dave Durante: Well, I want to come back to some of the things you mentioned. But since we're talking about it, one of my questions was maybe specific to gymnastics but also we're seeing it quite a bit in our world of functional fitness and CrossFit, people wearing a lot of devices around their wrists: grips or tight wraps, uh, just for, you know, wrist protection or hand protection on the bar. And in gymnastics we have a tendency to tie it very tight to the point where we're, you know, restricting blood flow to that area.","offset":1000,"duration":35},{"text":"Dave Durante: Would that impact the ability for us to uh, basically transfer heat or dissipate heat as needed, let alone using the product? But does that actually limit our ability to recover?","offset":1035,"duration":5},{"text":"Dr. Craig Heller: Yes, it it it does. Uh, so what you can do is not make it as tight, uh, but also you keep you have to keep in mind that you have other body surfaces. So, just for recovery without using a device, uh, you have your feet, you have your face in addition to your hands. So, there are five sites where you have these blood vessels that can greatly enhance your heat flow. So, if you concentrate- if you constrict the blood flow to your palms, you're not doing anything to your feet, so you still have some heat loss capacity.","offset":1040,"duration":40},{"text":"Jordan Samuel: You know, it's interesting, uh, in the CrossFit world, it's really common when somebody finishes a very hard workout and they collapse on the floor that one of the first things people do is they kick their shoes off. And I don't think they realize why they're doing it, they just instinctively do it, and I see it all the time. Even to the point where the person's so tired they can't do it, somebody comes over and pulls their shoes off for them.","offset":1080,"duration":25},{"text":"Jordan Samuel: But I eventually got to the point where I don't work out with my shoes tied at all. Like I I don't like that constriction, and maybe that comes back to subconsciously feeling like, you know, it's it's making me hotter or something like that. But people yell at me all the time, say, \"Tie your damn shoes,\" and I'm like, \"I don't want to, it doesn't feel good.\" So, I feel like now I've got some scientific backing from an actual doctor so I can go back and tell them to shut up.","offset":1105,"duration":20},{"text":"Dr. Craig Heller: Yeah. Well, a good illustration of how important these various sites are is working with amputees. So, if you have lost one hand or one foot, that's 25% of your heat loss capacity. So, if you lose, you know, two feet, we worked with amputees at Walter Reed, and uh, they have these silastic socks—not socks, they're like coverings that go over the stump just to cushion it.","offset":1125,"duration":35},{"text":"Dr. Craig Heller: And after an exercise bout, they would take off that silicone shape and just pour the water out of it. It just...","offset":1160,"duration":5},{"text":"Dave Durante: So, it's interesting you bring that up. We work with a lot of adaptive athletes too, into within our community, and we have a big fitness camp that we put on a couple of times a year, and the next one's coming up in a few weeks, and we'll have a few adaptive athletes that fall into this category of being an amputee.","offset":1165,"duration":15},{"text":"Dave Durante: In those situations, what is recommended? I mean, if they're not able to regulate heat as effectively or as efficiently as someone that has all five sites available to themselves, what's a recommendation for them to be able to, you know, recover as quickly as they can?","offset":1180,"duration":15},{"text":"Dr. Craig Heller: Well, to use the maximize the use of the sites they do have, and that's what CoolMitt would do. If they still have- if they have their hands, uh, now we should be coming out uh, sometime in not too distant future with versions for the feet. So, we we actually did some experiments many years ago on uh, spinal cord patients in which they lose the ability to control the blood flow to the lower body.","offset":1195,"duration":35},{"text":"Dr. Craig Heller: And we- these were wheelchair basketball players, and we built essentially what we called Frankenstein boots that went on the wheelchair and cooled them through the feet, and that did wonders for for for their performance.","offset":1230,"duration":15}],"startTime":935},{"title":"When to Cool and the Role of Warm-Ups","summary":"Dr. Heller clarifies that cooling should be applied between sets or after exercise, not before. He explains how warm-ups add a heat load that can limit performance in hot, humid environments.","entries":[{"text":"Dave Durante: Yeah, I was curious about that too, from a gymnastics perspective. We use our hands a lot, right? Our hands are our feet essentially as gymnasts, hanging and swinging. And personally, and I believe this is fairly common within our community, if you go to any gymnastics competition, you're going to see guys wearing gloves before they go.","offset":1245,"duration":20},{"text":"Dave Durante: Because cold hands are not very effective in terms of us being able to feel the apparatus. And so I was always thinking, you know, I don't want to put my hand in something that's going to cool it down right before I perform. I would prefer to be able to do something on maybe my foot so that I can keep my hands prepared for any any activity that I need. Would you say that that's a strategy that's that for someone who uses their hands would be a better route to go?","offset":1265,"duration":25},{"text":"Dr. Craig Heller: You want to cool after, okay, after. Well, it's between your rotations, between your performances that you would cool. And it's the same way with, let's say, any sport where you're coming on and off the field or the court. It's when you come off that you want to cool. Cooling before you go in doesn't do you any good.","offset":1290,"duration":30},{"text":"Dr. Craig Heller: Uh, if you're already at normal body temperature, the CoolMitt can't drive your temperature below normal. Uh, so it can have an advantage in that it could cool some of your periphery, uh, but as soon as you get below normal, you vasoconstrict. Right. So you don't going to get any effective heat exchange.","offset":1320,"duration":20},{"text":"Dave Durante: Okay, so that's why there's that optimal temperature at 55 degrees that you guys like to use.","offset":1340,"duration":5},{"text":"Dr. Craig Heller: Right. Uh, in the past, we had, for example, a cross country team. And what they would do is they would do their their warm up, their their pre-event warm-up, and then they would cool before the beginning of the race. So, what they're doing is they're getting the benefit of the warm-up, the flexibility and so forth, but they're eliminating that extra heat load that they accumulated as a result of the warm-up. So, the body has a higher scope for absorbing the heat of the event.","offset":1345,"duration":40},{"text":"Dave Durante: This was interesting. We were actually talking about this before you came on in terms of warming up properly. And a lot of times, I think we hear coaches and trainers talk about warm-up being \"let's get your core temperature up,\" uh, and that's kind of the primary use of a warm-up. But we heard you maybe speak a little differently on this in terms of the benefits that come along with a warm-up. Can you speak a little bit about where you see the benefits of taking that time?","offset":1385,"duration":25},{"text":"Dr. Craig Heller: Well, if you're in an environment where you can dissipate heat, then you can do the warm-up, that's going to get everything more flexible, that's going to get your muscles at a peak operating temperature, which is actually very close to the temperature which is going to result in failure. I mean, we live on the thermal edge, because, you know, if you think about it, our normal body temperature is 37 degrees or 98.6, and that's only a few degrees below the point where you have heat illness, where you can have heat stroke.","offset":1410,"duration":35},{"text":"Dr. Craig Heller: So, uh, we we maximize our metabolic efficiency by staying at this high core temperature, but then the scope for going higher is very, very limited. So, if you're in an environment where you can dissipate heat efficiently, then sure, a warm-up is not going to give you much of a heat burden. But if you're in a very hot humid environment, that warm-up is going to impair your capacity to absorb the excess heat of exercise.","offset":1445,"duration":35},{"text":"Dr. Craig Heller: People don't realize that. 35 degrees ambient temperature at 100% humidity is lethal for humans.","offset":1480,"duration":15},{"text":"Dave Durante: I think you need to repeat that, just so we're aware.","offset":1495,"duration":0},{"text":"Dr. Craig Heller: Okay, 35 degree ambient temperature, that's 35 degrees Celsius or 95 degree Fahrenheit at 100% humidity, which you certainly have in many places, that is lethal. Because that doesn't give you the capacity to even dissipate the heat of your resting metabolism, your basal metabolic heat. And you will just continue to heat up, heat up, heat up.","offset":1495,"duration":30},{"text":"Dave Durante: So ambient temperature plays a critical role here in terms of... so these are going to be more effective in situations in temperature zones in sports that are maybe outdoors, that are in, you know, places closer to summer events, those types of things in terms of being able to understand where your temperature is with regards to outdoor temperature.","offset":1525,"duration":25},{"text":"Dr. Craig Heller: Yeah. For example, various tennis opens, they're usually in very hot weather and can be in very hot places.","offset":1550,"duration":10},{"text":"Dave Durante: Have you- have you tested this out at all with... I'm just curious, having watched the Formula 1 race this weekend and those drivers in the cars with their full suits on. We had Melbourne over the weekend, it was extraordinarily hot plus being in those hot cars with full suits on. Would you find this to be beneficial? I don't know how you would enact it, but it seems like those drivers would benefit from it.","offset":1560,"duration":20},{"text":"Dr. Craig Heller: We actually did a little bit of that a number of years ago, but you're right, it at that time it wasn't possible to actually incorporate the devices into the car. There's not much space, and of course you don't have the flexibility of losing the use of a hand. So, that is an area where there could be a wearable application which would be very useful.","offset":1580,"duration":-1173},{"text":"Jordan Samuel: You just turn that steering wheel into a water-cooled device. Yep, yep.","offset":407,"duration":1208}],"startTime":1245},{"title":"The Dangers of Cooling the Head","summary":"Dr. Heller warns against cooling the head or neck during exercise, as it tricks the brain's thermostat into shutting down the body's natural heat loss mechanisms. The group also discusses the insulating effects of sauna hats.","entries":[{"text":"Jordan Samuel: Um, I have a question for you since we're talking about potential lethal situations or or bad ways to cool. Like we see people in sports cooling in all sorts of various ways, like cold towel on the back of the head or just like running your head under cold water or these other sorts of things. Is that just not effective or is it- is it bad?","offset":1615,"duration":25},{"text":"Dr. Craig Heller: Well, there are some things that are ineffective and they can be bad. And uh, if you cool your head, if you do it, you know, put your head under a water faucet or put an ice towel around your neck, what you're essentially doing is you're cooling your thermostat. The thermostat is in the brain and it's close to where the major arteries are bringing blood into the brain.","offset":1640,"duration":30},{"text":"Dr. Craig Heller: So, if your house is overheated, would you go and put a wet washcloth over the thermostat? No. Do exactly the opposite. So what we see in many applications of peripheral cooling, even ice vests, that if you cool the surface the trunk surface or you cool the brain, what you do is you shut off these heat loss systems. The system says, \"We're okay, you don't need to have all of that heat loss.\"","offset":1670,"duration":25},{"text":"Dr. Craig Heller: So it shuts it off. We've actually seen athletes in the lab testing out various kind of cooling vests and, you know, they will do repeated sprints on a fixed bike, for example, and as with each sprint they're getting higher and higher, and then the intervals between the sprints, they'll wear the air-cooled vest or something like that. And they say, \"Oh, feels great, this is wonderful.\" And we're watching their temperature continue to go up as the heat comes out of the muscles.","offset":1695,"duration":40},{"text":"Dr. Craig Heller: So, yeah, there are things that you can do... a couple weeks ago, I got an email from somebody who said, \"You know, I really know that saunas are very healthy and they're good for us. So, if we spend more time in the sauna, that should be even better. So, can't we use a cooling cap which would make it possible to stay longer in the sauna?\" I thought, oh my god, what a good way to kill yourself.","offset":1735,"duration":30},{"text":"Dr. Craig Heller: Because what you do is you shut off the thermostat, in other words you inactivate the thermostat, your core temperature is going higher and higher and higher, and then you go out of the sauna, you take off the cap, and boom, all of that hot blood goes to the brain. Not a good- not a good idea.","offset":1765,"duration":20},{"text":"Jordan Samuel: That's something that I mean in general I think people are doing- they wear a hat, they wear what's called a sauna hat to do the same thing. And maybe it's not to the same extreme because you're not cooling it, but you're insulating it a little bit. But yeah, I mean people do that all the time.","offset":1785,"duration":10},{"text":"Dave Durante: Yeah, no, no, that's an important point to make because there's a difference between wearing something to cool your head to be able to stay in a sauna longer or one to insulate to basically allow the thermostat to work more correctly or to tell you, \"Hey, you might be overheating yourself, it's time to get out of the sauna.\" Is that- is that correct to assume that a sauna hat is more used to protect than it is to keep you in the sauna for longer?","offset":1795,"duration":27},{"text":"Dr. Craig Heller: Well, it's actually going to block the heat flow into the brain from the ambient. It's going to decrease that heat flow in. You're insulating. I mean, insulation works both directions. Right.","offset":1822,"duration":16}],"startTime":1615},{"title":"Ice Baths and Water Circulation","summary":"The conversation shifts to the effectiveness of ice baths and cold plunges. Dr. Heller emphasizes the importance of moving in cold water to break the insulating boundary layer that forms directly over the skin.","entries":[{"text":"Jordan Samuel: Yeah, and that's... go ahead Jordan. I was going to say if we're still on this whole subject of temperature regulation and saunas and maybe like in our world, cold ice barrels, ice baths are a big thing too. And I'm curious to get your take on that and whether or not you see a benefit there or if you think it's overkill or not needed or maybe it's not good for you. Um, what's your take?","offset":1838,"duration":24},{"text":"Dr. Craig Heller: I think ice bath, ice barrel, ice pads that would go on elbows, shoulders, knees for inflammation, they're all good. Okay. They're not necessarily good for regulating temperature. So sure, if you could jump in an ice bath between each set of lifts, for example, yeah, you'd see a benefit. But that's not convenient.","offset":1862,"duration":30},{"text":"Jordan Samuel: What about using it just for lifestyle improvement or these other sorts of things?","offset":1892,"duration":6},{"text":"Dr. Craig Heller: Yeah, well, just at the- if you're looking at the about the ice bath, using it after a particular workout would help prevent inflammation, okay? That's the major benefit. The NCAA actually has as their standard of care for hyperthermia, for heat exhaustion, ice bath or cold water bath. Now, that's great because if you put your whole body in a tub of cold water, the total surface area over which you're losing heat is enormous.","offset":1898,"duration":37},{"text":"Dr. Craig Heller: So yeah, that's effective. But you don't always have a ice bath available, okay? And we've had examples where athletes have gone down in practice or competition and they've called the ambulance and in- used the the palmar cooling device and they're back to practically normal before the ambulance can even get there, let alone get them to a ice bath.","offset":1935,"duration":30},{"text":"Dr. Craig Heller: So, yeah, ice baths are great but they're not the best way to have really timely treatment of the hyperthermic condition, which is critical. It's not just the temperature, it's the duration of the time you're at that temperature which can have negative effects.","offset":1965,"duration":20},{"text":"Dave Durante: Can we also talk really quick, I think it's beneficial for our audience to hear this about the circulation of the water and how that's important. Stagnant water creates kind of a barrier between skin temperature and the water itself. And I noticed this as well when I was living at the Olympic Training Center, we would do a lot of contrast therapy of jumping between a hot tub and a cold tub and how beneficial that was for recovery purposes.","offset":1985,"duration":27},{"text":"Dave Durante: And we use it actually quite often here, but we were always told \"keep moving.\" We had to walk within the water. Keep moving, keep all the limbs continuing to circulate. And I hated doing that, right? It was almost like the easiest way just go in and sit and just don't move. But obviously it's not beneficial. So, can you talk a little bit about the importance of the water being circulated and why that actually happens within the CoolMitt as well?","offset":2012,"duration":23},{"text":"Dr. Craig Heller: Sure. Well, Dave, what you're referring to is boundary layer formation. And you described it well. Anytime you get into a hot bath, it's going to be really painfully hot until you sit there for a couple minutes, and then you have a boundary layer of still water around your skin, and that is insulating, okay? So, if you use a heat exchange device like a phase change material that you can get in, you know, pads that you can buy in the in the in the drugstore, the problem with them is that they very rapidly develop a boundary layer so that as the phase change material is melting, the phase change material that's right next to the surface is still, and it heats up slowly, and that is essentially increasing the insulation between the phase change material and your skin.","offset":2035,"duration":55},{"text":"Dr. Craig Heller: So, it's very important to have your heat sink material circulating so that you continually disrupt the boundary layer, prevent it from forming.","offset":2090,"duration":14},{"text":"Dave Durante: I know a lot of listeners are going to hate hearing that, the people that are in plunges often, because it's such an uncomfortable thing to constantly in contact with the coldest parts of the water, but that's where you get the benefits from. So, everyone listening, keep moving when you're in those tubs.","offset":2104,"duration":14},{"text":"Dr. Craig Heller: Yeah. Well, the other thing is the extreme exposure to cold that some people are saying has benefits. I don't- I don't think so. I think if you go into extreme cold, what essentially you get is a shot of adrenaline. Right. And sure, you're going to get out of that and you say, \"Oh, I feel energized.\" Sure you will, you've just gotten a shot of adrenaline.","offset":2118,"duration":27},{"text":"Jordan Samuel: What would you consider an extreme temperature for that situation?","offset":2145,"duration":5},{"text":"Dr. Craig Heller: Oh, the some of the things which are being used in cryotherapy, which are, you know, extremely cold and there the boundary layer protects you. So, you're not going to come into contact with the walls because that would cause freezing. So what you're you have a boundary layer, so you get that cold shock, but the boundary layer then protects you from losing heat really fast.","offset":2150,"duration":28},{"text":"Jordan Samuel: So something that's like below zero is what you're talking about as opposed to just an ice bath would not necessarily fall into that category.","offset":2178,"duration":12},{"text":"Dr. Craig Heller: Right. And zero, I mean, that's what people are using with a with a ice barrel, an ice tub. And yeah, you can deal with that. I mean, I've been swimming at the North Pole, so I know you can survive it. That could be a good commercial for your CoolMitt when you eventually get it out there. That new WarmMitt. Right. Exactly.","offset":2190,"duration":25}],"startTime":1838},{"title":"Cooling, Hypertrophy, and Weightlifting","summary":"Mike Service asks about cooling's effect on muscle mass and weightlifting. Dr. Heller notes that while cooling increases hypertrophy and strength, it also allows athletes to practice technique more efficiently under less fatigue.","entries":[{"text":"Mike Service: Dr. Heller, I have maybe a slight change of pace question for you. It's very biased to me coming from the weightlifting side of things. So you were talking about, like, for the example the lab assistant you had that did the pull-ups and increased their capacity like a lot in that session. And I'm thinking about it from a weightlifting side of things.","offset":2215,"duration":27},{"text":"Mike Service: We would be wanting to get as strong as possible without putting on too much mass because we lift in weight categories. So I'm actually pretty curious in any of your studies, do you measure muscle mass from beginning the experiments to then maybe over the course of six weeks? Is there a noticeable change in muscle mass? Does muscle mass stay the same but then the capacity, the output is much greater?","offset":2242,"duration":28},{"text":"Dr. Craig Heller: Well, if you do strength training, the only way you're increasing strength is by increasing the cross-sectional area of the muscle. So hypertrophy is actually the end product of conditioning. Now, what you want to do is you want to put on that increased muscle mass as contractile fibers, not as water or not as fascia. So we definitely see increases in muscle mass, that's for sure.","offset":2270,"duration":35},{"text":"Dr. Craig Heller: But we have done some comparisons between our work and the data published in the literature. And specifically bench press studies because that's something that you can reasonably expect is going to be controlled and the replications. And I think we've found about 10 or 12 papers in the literature which looked at the effects of bench press on individuals with anabolic steroids, okay?","offset":2305,"duration":35},{"text":"Dr. Craig Heller: And what they were getting in all of those studies is about 1% improvement per week, okay? We get much, much, much greater than that, 5%, 10% improvement per week, or even doubling from one day to to another for a given activity. So sure, it's going to cause an increase in muscle mass, but it must be that it's more effective muscle mass because we see much greater gains in strength.","offset":2340,"duration":35},{"text":"Dr. Craig Heller: I'll tell you a story. I mentioned earlier on we had some women in a class that we were studying and they were doing push-ups as their metric of improvement. And one day they came in and they said, \"Dr. Heller, you cost us a lot of money.\" \"Why?\" \"We had a formal dance this weekend. We all had to buy new sleeveless dresses.\" Some bigger shoulders.","offset":2375,"duration":30},{"text":"Mike Service: Yeah, and I- and I asked because, like, one curiosity I would have, so I would think of it, let's say, for an Olympic weightlifter, you're often trying to increase your leg strength. So for me to make a big increase in leg strength, I might end up taking like a full year of trying to increase volume and manage recovery and have some increased calories, all of these things.","offset":2405,"duration":20},{"text":"Mike Service: But if I was able to use a cooling strategy to see bigger gains in a shorter amount of time, I would assume that I might put a little less mass on, so then be able to potentially compete in my weight class. So let's say that I would in six weeks make bigger gains with the cooling than I would have made in six months with my normal programming. So I would be like one of those hopeful athletes that would think this could really maybe help me for peaking for certain competitions without having to stress so much about muscle mass management or weight management.","offset":2425,"duration":45},{"text":"Dr. Craig Heller: Yeah, I think that that's highly likely. I don't have any data which contributes to an analyzing that proposition. All I can say is that still strength boils down to cross-sectional area of the muscle. Uh, so you are going to have to have hypertrophy in order to increase. But I would imagine that that hypertrophy can vary with respect to the contribution of water versus fat versus protein.","offset":2470,"duration":65},{"text":"Mike Service: Yeah, definitely. This is really interesting for for me on that side of things from a training aspect, and then even for us from a technique application to how we train people. A lot of times technique suffers from fatigue. So you're tired and you can't perform the same movement with the same intensity. Exactly.","offset":2535,"duration":15},{"text":"Mike Service: Yep. And this is another... so like that would be a lot of times again in weightlifting, you get very good by moving really heavy weight with good technique. So if you can recover well, you can lift that heavy weight and learn a better technique without potentially having to put on more muscle. You just move better. And that's another really interesting component or perspective that I could imagine has a lot more potential to be studied and applied.","offset":2550,"duration":35},{"text":"Dr. Craig Heller: Yeah, definitely.","offset":2585,"duration":3}],"startTime":2215},{"title":"Debunking the Lactate Misconception","summary":"Dr. Heller clarifies a common misconception, stating that lactate does not cause fatigue. Instead, temperature-induced fatigue causes lactate build-up, and lactate actually acts as a metabolic fuel for the body and brain.","entries":[{"text":"Jordan Samuel: Um, I have a question for you. I did a test with your product just doing max sets of push-ups and so forth. And I guess I felt when I would do my each set I'd go to failure, I felt like it was the thing that was limiting me was a build-up of lactate. And maybe I'm wrong, but does the cooling mechanism that you have play a role in like shunting out lactate as well, or am I way off base? I could very well be.","offset":2588,"duration":2},{"text":"Dr. Craig Heller: You you are common with the vast majority of people who think that lactate causes fatigue. It doesn't. Okay. You can actually infuse lactate and it doesn't cause fatigue. Really? Wow. Okay. But it's the opposite: that fatigue causes lactate. And we're actually studying that right now. And what we find is that the lactate threshold is temperature sensitive.","offset":2590,"duration":35},{"text":"Dr. Craig Heller: So the build-up of lactate must have something to do with that blockage of fuel going into the mitochondria. And we are looking into the possible pathway whereby that situation results in increased lactate production. But the lactate doesn't cause the fatigue. It's the fatigue due to temperature which causes the lactate formation.","offset":2625,"duration":30},{"text":"Dave Durante: I think this is incredibly critical for listeners out there to hear this again, and maybe it comes back to the starting conversation around what's happening from the enzyme perspective as to why the muscle is failing. Correct? So it's not due to lactate, it's due to a temperature increase which then has a cascading effect within the muscle fiber itself. Is that correct?","offset":2655,"duration":30},{"text":"Dr. Craig Heller: Yeah, and that results in the increased lactate production.","offset":2685,"duration":5},{"text":"Dave Durante: And what does the lactate then do to assist in bringing maybe minimizing the effect of the fatigue that's setting in?","offset":2690,"duration":5},{"text":"Dr. Craig Heller: Well, lactate is a metabolic intermediate and it gets metabolized. So that's why you have, you know, lactic acid debt and alactic acid debt after working hard. You can restore your red blood cell oxygen binding in a short period of time, but you can't metabolize lactate...","offset":2695,"duration":5},{"text":"Dr. Craig Heller: That excess lactate in a short period of time. So your temperature will remain a little higher, your metabolism will remain a little higher, uh, while you're undergoing this recovery. Uh, so essentially lactate is a metabolic fuel, so it gets converted back to glucose and uh, transported back to the muscles. And uh, lactate is also critical for the brain. It's an important fuel for the brain. It's produced by the uh, the white matter, the astrocytes, the uh, glial cells, uh, they produce lactate and feed it to the neurons.","offset":2700,"duration":37}],"startTime":2588},{"title":"Cooling to Prevent Muscle Soreness (DOMS)","summary":"The group discusses Delayed Onset Muscle Soreness (DOMS). Dr. Heller explains his upcoming research on how cooling enhances muscle repair and prevents the inflammation that causes soreness.","entries":[{"text":"Host: That's such a critical uh understanding versus what uh, you know, a lot of people out there within the community think some of these mechanisms and how they work. But I think it feeds into maybe one of my last questions here around uh soreness and DOMS and delayed onset muscle soreness with regards to how this system can maybe lessen the effects of soreness that come along with high-fatiguing workouts. Can you talk a little bit about how this has been shown to be beneficial in that sense?","offset":2737,"duration":28},{"text":"Dr. Craig Heller: Sure, uh we're actually very timely. We're about to begin this summer a research project on DOMS and it's stimulated by the fact that so many times we'll have well-trained athletes come into the lab and uh, they will double their work volume, you know, in that day, and I can always expect them to say, \"I'm going to be so sore tomorrow,\" and they never are. Okay? So that led me to hypothesize that uh the soreness is actually due to the unresolved healing of the microtears in the muscle. Okay?","offset":2765,"duration":52},{"text":"Dr. Craig Heller: So what does cooling do? Cooling decreases, it prevents that inflammation. Uh, it also, uh, in a way that's a little bit complicated, uh facilitates the healing. So if you go to a very high temperature, the healing is going to be impaired, and that's going to result in inflammation. So if you uh, have very healthy repair, uh, you don't get the inflammation and you don't get the soreness. So what we're doing this summer is we're doing a series of studies in which we actually drive people to do a workout that will be expected to cause delayed onset muscle soreness and either cool them during the workouts or not cool them during the workouts to see if we have uh an effect on the development of DOMS.","offset":2817,"duration":43},{"text":"Host: That's fascinating. Uh, it's a little counterintuitive sometimes, right? Because you think that getting the muscle, for a muscle to grow or to gain strength you need to, you know, you need to uh have that muscle tear and then repair itself, tear and repair itself, correct? And you're saying that the inflammation that comes along with those tears is what we're trying to prevent from being, I don't know, to me it's it's almost a healing mechanism, like the inflammation is about healing the process. But if you're saying that we want to stop the inflammation from happening, shouldn't it also prevent the healing process or you're trying to speed up that process?","offset":2860,"duration":39},{"text":"Dr. Craig Heller: Well, uh, it's it's a little bit complicated because what you're doing is you're looking at two different things happening at the same time, and it doesn't necessarily mean that they're causally related. Okay? So sure, you generate the microtears in the muscle, they have to be repaired, but what I'm saying is that by uh administering the cooling, you're enhancing that repair without getting the inflammation. So uh, there are many many things in the body that result or they get inflamed and it's not good. It's not healthy. You don't have to have inflammation to get healing.","offset":2899,"duration":40},{"text":"Host: Sure. Sure. I think it's just uh, yeah, go ahead Jordan.","offset":2939,"duration":3},{"text":"Jordan: A follow-up to that that you just said, um is there a potential health benefit to using the CoolMitt outside of exercise if you're saying that it can help reduce inflammation throughout the body potentially, other, you know, pathology?","offset":2942,"duration":19},{"text":"Dr. Craig Heller: Well, uh, what you have to keep in mind with the CoolMitt, and this is for even exercise benefits, is that all it can do is eliminate the effect of high temperature. So if you don't have high temperature, you're not going to get an effect. You're not going to get, so if you're a couch potato and you can do five push-ups, cooling between your five push-ups is not going to do you any good, because it's not the heat which is limiting your performance, okay?","offset":2961,"duration":38},{"text":"Dr. Craig Heller: So if you get to a stage where you're actually producing significant amount of heat during your exercise, that gets to the point where it affects your performance. They say, well if I measure my oral temperature or ear temperature, I don't see an increase. No, for for this kind of activity, for anaerobic exercise, it's the temperature of the working muscle. And the temperature of that muscle can go up much faster than the overall body temperature. If you're doing an endurance sport, then it's the gradual increase of your entire body which is uh the critical variable. But for anaerobic activity, uh it's the build-up of temperature in the working muscle itself.","offset":2999,"duration":42}],"startTime":2737},{"title":"Dr. Heller's Training and Gymnastics vs. Weightlifting","summary":"Dr. Heller shares details about his own physical training, including doing 1,000 push-ups for his 60th birthday. He also humorously answers the hosts' ongoing debate about preferring gymnastics or weightlifting.","entries":[{"text":"Host: So Dr. Heller, we're coming towards the end of our hour together but I am curious about your own physical training. You mentioned swimming in the Arctic and uh, being fairly physical yourself. Do you use the CoolMitt product and if so what type of workouts are you using it with?","offset":3041,"duration":17},{"text":"Dr. Craig Heller: Well, uh, I'm a little bit too old to be worrying about that now, you know, I'm 80.","offset":3058,"duration":6},{"text":"Host: Oh my goodness.","offset":3064,"duration":2},{"text":"Dr. Craig Heller: But I do work out uh on occasion and uh my one very proud moment was when my students challenged me to be their age control for a experiment they were doing, and that experiment was push-ups and the effect of cooling on the build-up strength and uh, I accepted their challenge and on my 60th birthday I did a thousand push-ups.","offset":3066,"duration":27},{"text":"Jordan: Wow. That's incredible. How long did that take you to do?","offset":3093,"duration":5},{"text":"Dr. Craig Heller: I can still do if I only do one set now, I don't do it routinely, but if I do once I can still go over a hundred.","offset":3098,"duration":7},{"text":"Host: Wow.","offset":3105,"duration":1},{"text":"Jordan: That's incredible.","offset":3106,"duration":1},{"text":"Host: That's really phenomenal. So uh you have a little bit of a, were you an athlete when you were younger?","offset":3107,"duration":6},{"text":"Dr. Craig Heller: Uh, not really. I've always enjoyed you know hiking and skiing and swimming and outdoor activities, but uh when I was in school I was cross country runner but I didn't excel for sure.","offset":3113,"duration":16},{"text":"Host: Well we have a fun uh question that we always ask our guests and uh not quite sure if you'll have uh an answer from your experience as an athlete, but is there a sport that you prefer either weightlifting or gymnastics? This is a competition that me and Mike have going back and forth with our guests and we have a tally. Weightlifting or gymnastics, what do you prefer?","offset":3129,"duration":21},{"text":"Dr. Craig Heller: Uh, well I guess weightlifting.","offset":3150,"duration":3},{"text":"Mike: I knew I loved you Dr. Heller. Thank you so much for that.","offset":3153,"duration":5},{"text":"Dr. Craig Heller: I translate that into the resistance type activities that I enjoy doing uh in the gym, you know whether it's uh you know dips or or uh pull-ups or push-ups or sit-ups or...","offset":3158,"duration":13},{"text":"Mike: I mean, everything you just mentioned is bodyweight movements. Those are all gymnastics movements.","offset":3171,"duration":5}],"startTime":3041},{"title":"DIY Cooling and Hyperthermia Treatment","summary":"For listeners without a CoolMitt, Dr. Heller suggests using room-temperature water to cool down and avoid vasoconstriction. He also explains why treating hyperthermia by cooling the palms, soles, and face is far more effective than standard medical care.","entries":[{"text":"Host: I'm going to take them. I guess you each get a point there, but before we ask the rest of our last minute questions, I do want to ask one more question for Dr. Heller and that's for our listeners who don't have um the ability to get their hands on a CoolMitt, um what sort of protocol can you recommend they try to see if they can elicit the similar response?","offset":3176,"duration":25},{"text":"Dr. Craig Heller: Good question, uh we should have mentioned that earlier. And that is the first impulse people have is, \"oh I'll just get a bucket of ice water,\" and that doesn't work. And the reason is it's too cold. That if you dip your hands in ice water you get reflex vasoconstriction to prevent you from getting hypothermic, right? So if you have a bucket of water at room temperature uh tap water temperature uh you know your bathroom basin water temperature, uh just putting your hands in that will help.","offset":3201,"duration":39},{"text":"Host: Okay.","offset":3240,"duration":1},{"text":"Jordan: Cool.","offset":3241,"duration":1},{"text":"Host: Thank you. Keep them moving.","offset":3242,"duration":2},{"text":"Jordan: Right. I I really would love to uh have this product, uh have CoolMitt out at our Power Monkey camp. Uh I mentioned it earlier, but we have like a full week-long adult fitness camp out in the woods of Tennessee and we bring out about 150 people and for a full week of training this is like an ideal product for people to test with the type of workouts that we do out there. So I I just think we have such a good community that would benefit from testing this out with the types of workouts that we have within the CrossFit and the functional fitness community. So hopefully we can...","offset":3244,"duration":29},{"text":"Dr. Craig Heller: I can give you one bit of advice on that.","offset":3273,"duration":3},{"text":"Host: Let's hear it.","offset":3276,"duration":1},{"text":"Dr. Craig Heller: And that is if you do have people becoming hyperthermic, okay, uh the standard of care is ice packs on the groin, the axilla, and the the the neck, right? Okay? So we've done experiments where we've made people hyperthermic, hyperthermic, and then we have cooled them by either putting the ice packs in the standard of care position or putting the same ice packs just on the palms, the soles, and the face. And the rate of recovery is about double if you use them on the face, the palms, and the soles rather than here.","offset":3277,"duration":45},{"text":"Host: Now we got to test it out. We got to test it out with our crew.","offset":3322,"duration":3},{"text":"Dr. Craig Heller: And it makes good sense because if your car is overheating and you have a garden hose, are you going to spray the tubes going in and out of the radiator or you going to spray the radiator? Right? So these are the tubes going in and out of the radiator. This is the radiator.","offset":3325,"duration":18}],"startTime":3176},{"title":"Guest Recommendations and Closing Remarks","summary":"The host asks for final book and guest recommendations. Dr. Heller suggests guests who study the microbiome and diet, shares his contact information, and the hosts wrap up the episode.","entries":[{"text":"Host: I mean, that's just important to understand anatomy too, like what what those systems are actually doing versus just saying, hey I'm sweating from these areas so this is where my temperature's being regulated from. Right. Right. Uh Dr. Heller, one or two more questions, quick ones for you, if there's a guest that you think would be great to have on the podcast, maybe someone that works in your lab or another professor out at at Stanford, someone that would be a good interview, anyone that you would recommend to have on the podcast?","offset":3343,"duration":28},{"text":"Dr. Craig Heller: Uh yeah, um we have one uh actually a couple, Erica and Justin Sonnenburg uh who work on work on the microbiome. And uh the microbiome is something that I think needs a lot more attention with respect to uh our health and our fitness. Uh, so they would be good. Another person uh is Christopher Gardner. And Chris is a nutritionist, so uh he he would be very uh very helpful. I mean the big deal is comparing our current Western industrialized diet with uh healthier diets that uh are seen elsewhere in the world.","offset":3371,"duration":47},{"text":"Host: Perfect. Uh Jordan's taking those notes and be able to reach out. We appreciate those. Uh last question for you, uh if you're a book reader which I'm sure you are, is there anything that it could be something around uh the technology and what goes into uh CoolMitt technology, but is there a book that you would recommend our our listeners check into?","offset":3418,"duration":22},{"text":"Dr. Craig Heller: Oh, golly. I wish there were. Um I can't come up with one other than writing it. Uh I've had trouble finding time to write it.","offset":3440,"duration":9},{"text":"Host: Maybe we can pass along the research studies on some of these things so people could have a little bit more of a scientific understanding of what's happening.","offset":3449,"duration":7},{"text":"Dr. Craig Heller: But the Sonnenburgs have uh written a recent and a very good book uh essentially on the relevance of the microbiome and diet. So that would be a good book, I'm blocking on the name of it right now.","offset":3456,"duration":14},{"text":"Host: We'll make sure to to link it in with the the podcast itself. Uh last question, with all the amazing things you got going on, where can people follow along with you personally along with the CoolMitt? Where's the best place for our listeners to follow up with uh anything that they might want to have question-wise?","offset":3470,"duration":16},{"text":"Dr. Craig Heller: Well coolmitt.com uh will get you right to uh whatever is current, whatever is local. If people have specific questions they can try emailing me, hcheller@stanford.edu. Can't promise I can respond quickly, but I try.","offset":3486,"duration":24},{"text":"Host: Perfect. Well Dr. Heller, it was a pleasure. I really appreciate the time. Uh we can't wait to continue to test the CoolMitt product. Uh all the great results and uh for the listeners out there, we will be giving this a try at our Power Monkey camp. Uh this is going to be coming out right around when we have our next camp out in Tennessee. So listen closely, follow along at powermonkeyfitness.com and @powermonkeyfitness on Instagram and uh for our listeners, thank you all for listening.","offset":3510,"duration":15}],"startTime":3343}],"entries":[{"text":"Host: This episode is sponsored by Victory Grips. Victory Grips are the standard in hand protection. Plus, they just launched their new gym affiliate program. As affiliate owners, they understand the demands of gym owners. Their goal is to keep their gym referral program process as simple as possible. You'll receive educational content, early access to upcoming releases, and exclusive discounts for your members, plus receive a percentage of the net sales. Find out more at victorygrips.com.","offset":0,"duration":30},{"text":"Host: Welcome to the Power Monkey podcast, where we chat with the best in the world of fitness about what they do. I'm host Dave Durante, with my co-host this week being Jordan Samuel and Mike Service. And today, our guest is Dr. Craig Heller. Dr. Heller is the Lory Lokey Business Wire Professor of Biological Sciences and Human Biology at Stanford University. I was lucky enough to study under Dr. Heller when I was a Human Biology major at Stanford many, many years ago, and it's an absolute honor to have him on the podcast to speak about one of his companies working in the fitness recovery space, CoolMitt.","offset":30,"duration":40},{"text":"Host: Dr. Heller discusses what's really going on in your muscles when you work out, what causes fatigue to set in, and how the CoolMitt system can assist in helping to not only recover faster but also increase your gains. I found this to be an absolutely fascinating conversation, and it helped clear up some misconceptions around fatigue-causing factors. Dr. Heller takes some very complex internal functions and makes them accessible to the general population. I know we'll be making a more concerted effort to recover differently during our workouts after this conversation. We hope you enjoy this one as much as we did.","offset":70,"duration":40},{"text":"Dave Durante: Dr. Heller, thank you so much for being on the podcast with us. It's an honor to have you, and it's a pleasure to see you again. I don't know if this was passed along, but I was a student of yours 25-some years ago as a Hum Bio major at Stanford. And so to see your face again and to see you a part of now the fitness community is a pleasure, so thank you for being with us.","offset":110,"duration":25},{"text":"Dr. Craig Heller: Great to see you. I'll tell you a funny story if we have a minute. Last week I had to get some cortisone injections in my back, and I was lying on a gurney outside of the operating room, and two other surgeons came up to me and said, \"We want you to know you wrote our letters of recommendation to medical school.\"","offset":135,"duration":25},{"text":"Dave Durante: I'm sure the number of people you've impacted in that way has been numerous. So, it's great to see you and thank you so much for taking the time. Well, it's very interesting, the product... we'll get into CoolMitt and what you guys are doing in the recovery space here, but we want to take it back a little bit and just talk a little bit first about failure in the body and why there's a need for something like this.","offset":160,"duration":20},{"text":"Dave Durante: So, could we talk about just the different ways that muscle and the body fails in terms of physical activity, whether that be temperature regulation or lack of strength or lack of recovery? Can we just go through different methods in terms of how the body might fail when it comes to physical activity?","offset":180,"duration":15},{"text":"Dr. Craig Heller: Sure. Well, temperature is of course what we're concerned with. And most people don't realize that we can cook our own muscles. The metabolism of one of our large dynamic muscles can go up much higher than the blood flow to that muscle. And the only way the heat that's generated gets out of the muscle is in the blood.","offset":195,"duration":25},{"text":"Dr. Craig Heller: So, we literally have the capacity... and this is the condition known as rhabdomyolysis, where you actually overwork a muscle, it gets hyperthermic, and it causes the muscle cells to die. So, we have a fail-safe mechanism, and that fail-safe mechanism is the inhibition, the temperature inhibition of a critical enzyme. And when that enzyme gets up to about 39 degrees centigrade, it inactivates.","offset":220,"duration":30},{"text":"Dr. Craig Heller: And once it inactivates, the fuel can't go into the mitochondria, and the mitochondria can't produce ATP, and without ATP, the muscle can't contract. So, if we extract that heat efficiently, we can reactivate the enzyme or we can prevent it from inactivating, and then the muscle just keeps on working. So, I've had some freshman women, for example—maybe your classmates—who were doing over 800 pushups.","offset":250,"duration":35},{"text":"Dr. Craig Heller: So, these were not athletes, these were just normal freshman students. And we've had professional athletes come in, pick an activity they're good at, and that day we can double their normal work volume. And when you get that kind of an increase in your work volume, you get a huge conditioning effect. So, that's one of the limitations.","offset":285,"duration":25},{"text":"Dr. Craig Heller: Now, of course, hypoxia is another limitation. Now, that's not a critical issue for anaerobic activities like lifting, but it is certainly a big deal for anyone who's doing endurance work. And essentially, if you shut off the supply of oxygen to the muscle, once again you can't produce ATP. So, we're not addressing that issue.","offset":310,"duration":25},{"text":"Dr. Craig Heller: That issue you have to address by choosing your altitude and breathing well and conditioning as best you can to operate at maximum levels.","offset":335,"duration":15},{"text":"Dave Durante: There were a couple of things you mentioned in there. One, what is the enzyme that is triggered, just so that we can give it to our listeners, something to be aware of when it comes to some of the science behind what's happening in the mechanism?","offset":350,"duration":15},{"text":"Dr. Craig Heller: It's pyruvate kinase. So, when glucose goes into the cell, it goes through a series of steps called glycolysis, and the bottom step is pyruvate. But just before pyruvate, it's phosphoenolpyruvate that has to be converted to pyruvate. So, it's that conversion step that shuts off the supply of pyruvate to the mitochondria.","offset":365,"duration":35},{"text":"Dr. Craig Heller: This is all our hypothesis. I can't give you data other than the biophysical data that shows the temperature sensitivity of pyruvate kinase. But maybe there are other temperature-sensitive steps that just haven't been investigated yet.","offset":400,"duration":15},{"text":"Dave Durante: It's interesting that you mentioned rhabdo, rhabdomyolysis. It's actually quite common... I don't know how aware you are, but within the CrossFit community it's, especially early on 15-plus years ago, 20 years ago when people didn't know that they could push themselves to the point of cooking their own muscles. It was rather common to see athletes have rhabdo and became part of the lexicon within the CrossFit community early on. And I actually, unfortunately, had a bout of it myself early on when I was first starting CrossFit. Not something you want to go through in terms of the recovery portion if you get it severe.","offset":415,"duration":40},{"text":"Dr. Craig Heller: No, that's pretty bad stuff.","offset":455,"duration":5},{"text":"Dave Durante: Yeah. So, taking it back even further, I think I heard you talk a little bit about some of the research that you've done on bears and how that research led to some of the thinking around how this could be applied to human performance. Would you mind just telling a little bit of a some some stories of some background in terms of how that research led you to where you are now on this?","offset":460,"duration":15},{"text":"Dr. Craig Heller: Actually, it goes back even farther than that, and it all started with a bet. So, I had studied for many years how the brain controls body temperature, and that's what led to working on hibernation. So, I was very familiar with hibernating animals. But one day, a colleague who's an anesthesiologist said to my colleague and I—my colleague Dennis Grahn, who's my partner in all of this—our friend, the anesthesiologist, said, \"You think you know so much about temperature regulation. I bet you couldn't solve a problem we have in the recovery room.\"","offset":475,"duration":40},{"text":"Dr. Craig Heller: \"Well, what's that?\" \"Patients come out of surgery hypothermic, cold, and as the anesthesia wears off, they shiver violently and it takes the nurses hours to get them to stop shivering. And it's very uncomfortable for not only the patient but for the nurses too.\" So, we said, \"Ah, that's not a hard problem.\" But it was, because if you're hypothermic coming out of anesthesia, what happens is you tightly vasoconstrict and sequester your blood in the core of your body.","offset":515,"duration":30},{"text":"Dr. Craig Heller: Okay, that's the 10% of your body that's critical: the liver, the lungs, the heart, the brain. So, it's very hard to get heat into the body when the blood flow is all concentrated in the core. So, we got an idea that if we put an arm in a negative pressure environment, we could pull blood into the arm, heat the arm, that would go back and heat the core of the body. And we did it, and it worked beautifully.","offset":545,"duration":30},{"text":"Dr. Craig Heller: First patient, less than 10 minutes, was back to normal temperature. And then we found out it had nothing to do with the arm; it was only the hand. And that led to the realization that we have these special blood vessels in the palms of the hands, the soles of the feet, and the face. And these blood vessels are shunts between the arteries and the veins. So, when they open up, the hand gets warm and we dissipate heat.","offset":575,"duration":30},{"text":"Dr. Craig Heller: When you shake someone's hand, you know immediately what their thermal status is, right? So, all of a sudden it dawned on us that what we were doing is using a mammalian adaptation for heat loss in reverse. So, then we started working on treating hyperthermia. And in order to treat hyperthermia, you have to have someone hot. So, how do you get hot? You exercise.","offset":605,"duration":30},{"text":"Dr. Craig Heller: So, we had a lab assistant who was a gym rat, and he would go to the gym every day after work. So, we got him to do some of his workout in the lab. We put up a pull-up bar and had him do sets of pull-ups to muscle failure just to raise his temperature. And one day, for no reason, after we cooled him, after we did the heat extraction, he went back to the pull-up bar and did the same number of pull-ups as in his first set.","offset":635,"duration":25},{"text":"Dr. Craig Heller: And we said, \"Holy crow, what does that mean?\" It means the muscle failure must be due to rise in temperature of the muscle. So, then we started cooling him after every other set of pull-ups, and his performance plateaued, and in that one transition from one day to the next, his work volume went up by—I think it was like 25% something like that. But then we started cooling him after every other set of pull-ups, okay, that's what we were doing.","offset":660,"duration":35},{"text":"Dr. Craig Heller: And in the next in that six-week period... well, go back. The first six weeks we worked on him twice a week, he went from doing 100 pull-ups to 180. But then the next six weeks after we made this realization of what the heat extraction could do, he went from doing 180 to 618.","offset":695,"duration":25},{"text":"Dave Durante: I mean, that's extraordinary. Over what over what period of time and like sets and reps, things like that?","offset":720,"duration":5},{"text":"Dr. Craig Heller: About an hour, 45 minutes to an hour. So, it's 10 sets, maybe it was 12, I don't know, nine or 10 or 12, with three-minute rest. And the rests were either cooling or not cooling. So, when he cooled his volume went up, and that was a gain, and then you keep the gain. If the next time he wasn't cooled, he showed that he had improved his conditioning. So, whenever we cooled, he increased his number.","offset":725,"duration":35},{"text":"Jordan Samuel: I mean, that's extraordinary numbers. Those are... Jordan, you look like you're wanting to chime in there. Well, I guess I wanted to ask a question about about that. So, when you say he kept his gains, um, does that mean that he kept the gain from set to set, like if you did a let's say he did 20 reps and then you cooled him and then he was able to, you know, keep 20 reps and then he comes back the next day and you he did the same two sets but without cooling at that point he's able to maintain 20 reps both times?","offset":760,"duration":30},{"text":"Dr. Craig Heller: Right. It's a real conditioning effect. Adaptation, yeah. In all of these experiments you get a you get a continuous curve over a period of time that you're engaged in the conditioning. So, we've seen it with so many different individ- so many ath- so many ex- exercises: dips, push-ups, bench press, so forth.","offset":790,"duration":35},{"text":"Dave Durante: Can you give us a little bit of insight into that early strategy around how to cool the body? I mean, to where you are today, um, how did you find the perfect temperature? I mean, uh, you've talked about it, that just cooling as as low as possible is not ideal, sticking your hand in a bucket of ice. How did you go about finding the optimal temperature, and what was that first iteration looking like in terms of how you applied it to an athlete?","offset":825,"duration":25},{"text":"Dr. Craig Heller: It's mostly trial and error. If you do if you do something enough times, you'll make all the possible mistakes. Then you learn from that. So, essentially, um, our first efforts for cooling were just, I just, we just chose a temperature and did it. But then we found that individuals differ. So, for example, when we applied the technology to multiple sclerosis patients, these individuals are very temperature sensitive.","offset":850,"duration":35},{"text":"Dr. Craig Heller: Even a little rise in temperature makes it impossible for them to be active. Uh, so we found that we could only cool them down to about 20, 22 degrees centigrade, or else they would vasoconstrict, they'd shut off the blood supply to the hands. Uh, others, uh, highly performing athletes working hard, we could cool them down to 10 or 12 degrees.","offset":885,"duration":30},{"text":"Dr. Craig Heller: So, for the CoolMitt we just selected 12 degrees as being an optimal temperature. So, for some individuals it might be too cold. Uh, but what you want is you want to get the maximum temperature differential between the device and the blood without causing vasoconstriction.","offset":915,"duration":20},{"text":"Dave Durante: I have to say, um, I was on the gymnastics team at Stanford, and I remember us testing out this product early on. And there was it just, you know, was there, I don't know who had brought it in, and I was even speaking to some of my former teammates about it recently. I was like, \"Do you guys remember using something that we had our hand kind of in a something the form of a hand and it was meant to kind of cool us down between sessions, between turns?\"","offset":935,"duration":30},{"text":"Dave Durante: And they're like, \"Yeah, we had that as part of our training.\" And it just jogged my memory that we actually were some of the guinea pigs for for this early product that you had so many years ago.","offset":965,"duration":10},{"text":"Dr. Craig Heller: Well, you guys weren't very good guinea pigs because your hands are so calloused. No, that's interesting. Does that play into- does that play into an effect, yeah? Oh, and same thing for football, for example, if they're taped. I mean, you- that's going to block the the heat flow. So, what you can do is you can of course wet it, uh, minimize the tapes, or lower the temperature of the device.","offset":975,"duration":25},{"text":"Dave Durante: Well, I want to come back to some of the things you mentioned. But since we're talking about it, one of my questions was maybe specific to gymnastics but also we're seeing it quite a bit in our world of functional fitness and CrossFit, people wearing a lot of devices around their wrists: grips or tight wraps, uh, just for, you know, wrist protection or hand protection on the bar. And in gymnastics we have a tendency to tie it very tight to the point where we're, you know, restricting blood flow to that area.","offset":1000,"duration":35},{"text":"Dave Durante: Would that impact the ability for us to uh, basically transfer heat or dissipate heat as needed, let alone using the product? But does that actually limit our ability to recover?","offset":1035,"duration":5},{"text":"Dr. Craig Heller: Yes, it it it does. Uh, so what you can do is not make it as tight, uh, but also you keep you have to keep in mind that you have other body surfaces. So, just for recovery without using a device, uh, you have your feet, you have your face in addition to your hands. So, there are five sites where you have these blood vessels that can greatly enhance your heat flow. So, if you concentrate- if you constrict the blood flow to your palms, you're not doing anything to your feet, so you still have some heat loss capacity.","offset":1040,"duration":40},{"text":"Jordan Samuel: You know, it's interesting, uh, in the CrossFit world, it's really common when somebody finishes a very hard workout and they collapse on the floor that one of the first things people do is they kick their shoes off. And I don't think they realize why they're doing it, they just instinctively do it, and I see it all the time. Even to the point where the person's so tired they can't do it, somebody comes over and pulls their shoes off for them.","offset":1080,"duration":25},{"text":"Jordan Samuel: But I eventually got to the point where I don't work out with my shoes tied at all. Like I I don't like that constriction, and maybe that comes back to subconsciously feeling like, you know, it's it's making me hotter or something like that. But people yell at me all the time, say, \"Tie your damn shoes,\" and I'm like, \"I don't want to, it doesn't feel good.\" So, I feel like now I've got some scientific backing from an actual doctor so I can go back and tell them to shut up.","offset":1105,"duration":20},{"text":"Dr. Craig Heller: Yeah. Well, a good illustration of how important these various sites are is working with amputees. So, if you have lost one hand or one foot, that's 25% of your heat loss capacity. So, if you lose, you know, two feet, we worked with amputees at Walter Reed, and uh, they have these silastic socks—not socks, they're like coverings that go over the stump just to cushion it.","offset":1125,"duration":35},{"text":"Dr. Craig Heller: And after an exercise bout, they would take off that silicone shape and just pour the water out of it. It just...","offset":1160,"duration":5},{"text":"Dave Durante: So, it's interesting you bring that up. We work with a lot of adaptive athletes too, into within our community, and we have a big fitness camp that we put on a couple of times a year, and the next one's coming up in a few weeks, and we'll have a few adaptive athletes that fall into this category of being an amputee.","offset":1165,"duration":15},{"text":"Dave Durante: In those situations, what is recommended? I mean, if they're not able to regulate heat as effectively or as efficiently as someone that has all five sites available to themselves, what's a recommendation for them to be able to, you know, recover as quickly as they can?","offset":1180,"duration":15},{"text":"Dr. Craig Heller: Well, to use the maximize the use of the sites they do have, and that's what CoolMitt would do. If they still have- if they have their hands, uh, now we should be coming out uh, sometime in not too distant future with versions for the feet. So, we we actually did some experiments many years ago on uh, spinal cord patients in which they lose the ability to control the blood flow to the lower body.","offset":1195,"duration":35},{"text":"Dr. Craig Heller: And we- these were wheelchair basketball players, and we built essentially what we called Frankenstein boots that went on the wheelchair and cooled them through the feet, and that did wonders for for for their performance.","offset":1230,"duration":15},{"text":"Dave Durante: Yeah, I was curious about that too, from a gymnastics perspective. We use our hands a lot, right? Our hands are our feet essentially as gymnasts, hanging and swinging. And personally, and I believe this is fairly common within our community, if you go to any gymnastics competition, you're going to see guys wearing gloves before they go.","offset":1245,"duration":20},{"text":"Dave Durante: Because cold hands are not very effective in terms of us being able to feel the apparatus. And so I was always thinking, you know, I don't want to put my hand in something that's going to cool it down right before I perform. I would prefer to be able to do something on maybe my foot so that I can keep my hands prepared for any any activity that I need. Would you say that that's a strategy that's that for someone who uses their hands would be a better route to go?","offset":1265,"duration":25},{"text":"Dr. Craig Heller: You want to cool after, okay, after. Well, it's between your rotations, between your performances that you would cool. And it's the same way with, let's say, any sport where you're coming on and off the field or the court. It's when you come off that you want to cool. Cooling before you go in doesn't do you any good.","offset":1290,"duration":30},{"text":"Dr. Craig Heller: Uh, if you're already at normal body temperature, the CoolMitt can't drive your temperature below normal. Uh, so it can have an advantage in that it could cool some of your periphery, uh, but as soon as you get below normal, you vasoconstrict. Right. So you don't going to get any effective heat exchange.","offset":1320,"duration":20},{"text":"Dave Durante: Okay, so that's why there's that optimal temperature at 55 degrees that you guys like to use.","offset":1340,"duration":5},{"text":"Dr. Craig Heller: Right. Uh, in the past, we had, for example, a cross country team. And what they would do is they would do their their warm up, their their pre-event warm-up, and then they would cool before the beginning of the race. So, what they're doing is they're getting the benefit of the warm-up, the flexibility and so forth, but they're eliminating that extra heat load that they accumulated as a result of the warm-up. So, the body has a higher scope for absorbing the heat of the event.","offset":1345,"duration":40},{"text":"Dave Durante: This was interesting. We were actually talking about this before you came on in terms of warming up properly. And a lot of times, I think we hear coaches and trainers talk about warm-up being \"let's get your core temperature up,\" uh, and that's kind of the primary use of a warm-up. But we heard you maybe speak a little differently on this in terms of the benefits that come along with a warm-up. Can you speak a little bit about where you see the benefits of taking that time?","offset":1385,"duration":25},{"text":"Dr. Craig Heller: Well, if you're in an environment where you can dissipate heat, then you can do the warm-up, that's going to get everything more flexible, that's going to get your muscles at a peak operating temperature, which is actually very close to the temperature which is going to result in failure. I mean, we live on the thermal edge, because, you know, if you think about it, our normal body temperature is 37 degrees or 98.6, and that's only a few degrees below the point where you have heat illness, where you can have heat stroke.","offset":1410,"duration":35},{"text":"Dr. Craig Heller: So, uh, we we maximize our metabolic efficiency by staying at this high core temperature, but then the scope for going higher is very, very limited. So, if you're in an environment where you can dissipate heat efficiently, then sure, a warm-up is not going to give you much of a heat burden. But if you're in a very hot humid environment, that warm-up is going to impair your capacity to absorb the excess heat of exercise.","offset":1445,"duration":35},{"text":"Dr. Craig Heller: People don't realize that. 35 degrees ambient temperature at 100% humidity is lethal for humans.","offset":1480,"duration":15},{"text":"Dave Durante: I think you need to repeat that, just so we're aware.","offset":1495,"duration":0},{"text":"Dr. Craig Heller: Okay, 35 degree ambient temperature, that's 35 degrees Celsius or 95 degree Fahrenheit at 100% humidity, which you certainly have in many places, that is lethal. Because that doesn't give you the capacity to even dissipate the heat of your resting metabolism, your basal metabolic heat. And you will just continue to heat up, heat up, heat up.","offset":1495,"duration":30},{"text":"Dave Durante: So ambient temperature plays a critical role here in terms of... so these are going to be more effective in situations in temperature zones in sports that are maybe outdoors, that are in, you know, places closer to summer events, those types of things in terms of being able to understand where your temperature is with regards to outdoor temperature.","offset":1525,"duration":25},{"text":"Dr. Craig Heller: Yeah. For example, various tennis opens, they're usually in very hot weather and can be in very hot places.","offset":1550,"duration":10},{"text":"Dave Durante: Have you- have you tested this out at all with... I'm just curious, having watched the Formula 1 race this weekend and those drivers in the cars with their full suits on. We had Melbourne over the weekend, it was extraordinarily hot plus being in those hot cars with full suits on. Would you find this to be beneficial? I don't know how you would enact it, but it seems like those drivers would benefit from it.","offset":1560,"duration":20},{"text":"Dr. Craig Heller: We actually did a little bit of that a number of years ago, but you're right, it at that time it wasn't possible to actually incorporate the devices into the car. There's not much space, and of course you don't have the flexibility of losing the use of a hand. So, that is an area where there could be a wearable application which would be very useful.","offset":1580,"duration":-1173},{"text":"Jordan Samuel: You just turn that steering wheel into a water-cooled device. Yep, yep.","offset":407,"duration":1208},{"text":"Jordan Samuel: Um, I have a question for you since we're talking about potential lethal situations or or bad ways to cool. Like we see people in sports cooling in all sorts of various ways, like cold towel on the back of the head or just like running your head under cold water or these other sorts of things. Is that just not effective or is it- is it bad?","offset":1615,"duration":25},{"text":"Dr. Craig Heller: Well, there are some things that are ineffective and they can be bad. And uh, if you cool your head, if you do it, you know, put your head under a water faucet or put an ice towel around your neck, what you're essentially doing is you're cooling your thermostat. The thermostat is in the brain and it's close to where the major arteries are bringing blood into the brain.","offset":1640,"duration":30},{"text":"Dr. Craig Heller: So, if your house is overheated, would you go and put a wet washcloth over the thermostat? No. Do exactly the opposite. So what we see in many applications of peripheral cooling, even ice vests, that if you cool the surface the trunk surface or you cool the brain, what you do is you shut off these heat loss systems. The system says, \"We're okay, you don't need to have all of that heat loss.\"","offset":1670,"duration":25},{"text":"Dr. Craig Heller: So it shuts it off. We've actually seen athletes in the lab testing out various kind of cooling vests and, you know, they will do repeated sprints on a fixed bike, for example, and as with each sprint they're getting higher and higher, and then the intervals between the sprints, they'll wear the air-cooled vest or something like that. And they say, \"Oh, feels great, this is wonderful.\" And we're watching their temperature continue to go up as the heat comes out of the muscles.","offset":1695,"duration":40},{"text":"Dr. Craig Heller: So, yeah, there are things that you can do... a couple weeks ago, I got an email from somebody who said, \"You know, I really know that saunas are very healthy and they're good for us. So, if we spend more time in the sauna, that should be even better. So, can't we use a cooling cap which would make it possible to stay longer in the sauna?\" I thought, oh my god, what a good way to kill yourself.","offset":1735,"duration":30},{"text":"Dr. Craig Heller: Because what you do is you shut off the thermostat, in other words you inactivate the thermostat, your core temperature is going higher and higher and higher, and then you go out of the sauna, you take off the cap, and boom, all of that hot blood goes to the brain. Not a good- not a good idea.","offset":1765,"duration":20},{"text":"Jordan Samuel: That's something that I mean in general I think people are doing- they wear a hat, they wear what's called a sauna hat to do the same thing. And maybe it's not to the same extreme because you're not cooling it, but you're insulating it a little bit. But yeah, I mean people do that all the time.","offset":1785,"duration":10},{"text":"Dave Durante: Yeah, no, no, that's an important point to make because there's a difference between wearing something to cool your head to be able to stay in a sauna longer or one to insulate to basically allow the thermostat to work more correctly or to tell you, \"Hey, you might be overheating yourself, it's time to get out of the sauna.\" Is that- is that correct to assume that a sauna hat is more used to protect than it is to keep you in the sauna for longer?","offset":1795,"duration":27},{"text":"Dr. Craig Heller: Well, it's actually going to block the heat flow into the brain from the ambient. It's going to decrease that heat flow in. You're insulating. I mean, insulation works both directions. Right.","offset":1822,"duration":16},{"text":"Jordan Samuel: Yeah, and that's... go ahead Jordan. I was going to say if we're still on this whole subject of temperature regulation and saunas and maybe like in our world, cold ice barrels, ice baths are a big thing too. And I'm curious to get your take on that and whether or not you see a benefit there or if you think it's overkill or not needed or maybe it's not good for you. Um, what's your take?","offset":1838,"duration":24},{"text":"Dr. Craig Heller: I think ice bath, ice barrel, ice pads that would go on elbows, shoulders, knees for inflammation, they're all good. Okay. They're not necessarily good for regulating temperature. So sure, if you could jump in an ice bath between each set of lifts, for example, yeah, you'd see a benefit. But that's not convenient.","offset":1862,"duration":30},{"text":"Jordan Samuel: What about using it just for lifestyle improvement or these other sorts of things?","offset":1892,"duration":6},{"text":"Dr. Craig Heller: Yeah, well, just at the- if you're looking at the about the ice bath, using it after a particular workout would help prevent inflammation, okay? That's the major benefit. The NCAA actually has as their standard of care for hyperthermia, for heat exhaustion, ice bath or cold water bath. Now, that's great because if you put your whole body in a tub of cold water, the total surface area over which you're losing heat is enormous.","offset":1898,"duration":37},{"text":"Dr. Craig Heller: So yeah, that's effective. But you don't always have a ice bath available, okay? And we've had examples where athletes have gone down in practice or competition and they've called the ambulance and in- used the the palmar cooling device and they're back to practically normal before the ambulance can even get there, let alone get them to a ice bath.","offset":1935,"duration":30},{"text":"Dr. Craig Heller: So, yeah, ice baths are great but they're not the best way to have really timely treatment of the hyperthermic condition, which is critical. It's not just the temperature, it's the duration of the time you're at that temperature which can have negative effects.","offset":1965,"duration":20},{"text":"Dave Durante: Can we also talk really quick, I think it's beneficial for our audience to hear this about the circulation of the water and how that's important. Stagnant water creates kind of a barrier between skin temperature and the water itself. And I noticed this as well when I was living at the Olympic Training Center, we would do a lot of contrast therapy of jumping between a hot tub and a cold tub and how beneficial that was for recovery purposes.","offset":1985,"duration":27},{"text":"Dave Durante: And we use it actually quite often here, but we were always told \"keep moving.\" We had to walk within the water. Keep moving, keep all the limbs continuing to circulate. And I hated doing that, right? It was almost like the easiest way just go in and sit and just don't move. But obviously it's not beneficial. So, can you talk a little bit about the importance of the water being circulated and why that actually happens within the CoolMitt as well?","offset":2012,"duration":23},{"text":"Dr. Craig Heller: Sure. Well, Dave, what you're referring to is boundary layer formation. And you described it well. Anytime you get into a hot bath, it's going to be really painfully hot until you sit there for a couple minutes, and then you have a boundary layer of still water around your skin, and that is insulating, okay? So, if you use a heat exchange device like a phase change material that you can get in, you know, pads that you can buy in the in the in the drugstore, the problem with them is that they very rapidly develop a boundary layer so that as the phase change material is melting, the phase change material that's right next to the surface is still, and it heats up slowly, and that is essentially increasing the insulation between the phase change material and your skin.","offset":2035,"duration":55},{"text":"Dr. Craig Heller: So, it's very important to have your heat sink material circulating so that you continually disrupt the boundary layer, prevent it from forming.","offset":2090,"duration":14},{"text":"Dave Durante: I know a lot of listeners are going to hate hearing that, the people that are in plunges often, because it's such an uncomfortable thing to constantly in contact with the coldest parts of the water, but that's where you get the benefits from. So, everyone listening, keep moving when you're in those tubs.","offset":2104,"duration":14},{"text":"Dr. Craig Heller: Yeah. Well, the other thing is the extreme exposure to cold that some people are saying has benefits. I don't- I don't think so. I think if you go into extreme cold, what essentially you get is a shot of adrenaline. Right. And sure, you're going to get out of that and you say, \"Oh, I feel energized.\" Sure you will, you've just gotten a shot of adrenaline.","offset":2118,"duration":27},{"text":"Jordan Samuel: What would you consider an extreme temperature for that situation?","offset":2145,"duration":5},{"text":"Dr. Craig Heller: Oh, the some of the things which are being used in cryotherapy, which are, you know, extremely cold and there the boundary layer protects you. So, you're not going to come into contact with the walls because that would cause freezing. So what you're you have a boundary layer, so you get that cold shock, but the boundary layer then protects you from losing heat really fast.","offset":2150,"duration":28},{"text":"Jordan Samuel: So something that's like below zero is what you're talking about as opposed to just an ice bath would not necessarily fall into that category.","offset":2178,"duration":12},{"text":"Dr. Craig Heller: Right. And zero, I mean, that's what people are using with a with a ice barrel, an ice tub. And yeah, you can deal with that. I mean, I've been swimming at the North Pole, so I know you can survive it. That could be a good commercial for your CoolMitt when you eventually get it out there. That new WarmMitt. Right. Exactly.","offset":2190,"duration":25},{"text":"Mike Service: Dr. Heller, I have maybe a slight change of pace question for you. It's very biased to me coming from the weightlifting side of things. So you were talking about, like, for the example the lab assistant you had that did the pull-ups and increased their capacity like a lot in that session. And I'm thinking about it from a weightlifting side of things.","offset":2215,"duration":27},{"text":"Mike Service: We would be wanting to get as strong as possible without putting on too much mass because we lift in weight categories. So I'm actually pretty curious in any of your studies, do you measure muscle mass from beginning the experiments to then maybe over the course of six weeks? Is there a noticeable change in muscle mass? Does muscle mass stay the same but then the capacity, the output is much greater?","offset":2242,"duration":28},{"text":"Dr. Craig Heller: Well, if you do strength training, the only way you're increasing strength is by increasing the cross-sectional area of the muscle. So hypertrophy is actually the end product of conditioning. Now, what you want to do is you want to put on that increased muscle mass as contractile fibers, not as water or not as fascia. So we definitely see increases in muscle mass, that's for sure.","offset":2270,"duration":35},{"text":"Dr. Craig Heller: But we have done some comparisons between our work and the data published in the literature. And specifically bench press studies because that's something that you can reasonably expect is going to be controlled and the replications. And I think we've found about 10 or 12 papers in the literature which looked at the effects of bench press on individuals with anabolic steroids, okay?","offset":2305,"duration":35},{"text":"Dr. Craig Heller: And what they were getting in all of those studies is about 1% improvement per week, okay? We get much, much, much greater than that, 5%, 10% improvement per week, or even doubling from one day to to another for a given activity. So sure, it's going to cause an increase in muscle mass, but it must be that it's more effective muscle mass because we see much greater gains in strength.","offset":2340,"duration":35},{"text":"Dr. Craig Heller: I'll tell you a story. I mentioned earlier on we had some women in a class that we were studying and they were doing push-ups as their metric of improvement. And one day they came in and they said, \"Dr. Heller, you cost us a lot of money.\" \"Why?\" \"We had a formal dance this weekend. We all had to buy new sleeveless dresses.\" Some bigger shoulders.","offset":2375,"duration":30},{"text":"Mike Service: Yeah, and I- and I asked because, like, one curiosity I would have, so I would think of it, let's say, for an Olympic weightlifter, you're often trying to increase your leg strength. So for me to make a big increase in leg strength, I might end up taking like a full year of trying to increase volume and manage recovery and have some increased calories, all of these things.","offset":2405,"duration":20},{"text":"Mike Service: But if I was able to use a cooling strategy to see bigger gains in a shorter amount of time, I would assume that I might put a little less mass on, so then be able to potentially compete in my weight class. So let's say that I would in six weeks make bigger gains with the cooling than I would have made in six months with my normal programming. So I would be like one of those hopeful athletes that would think this could really maybe help me for peaking for certain competitions without having to stress so much about muscle mass management or weight management.","offset":2425,"duration":45},{"text":"Dr. Craig Heller: Yeah, I think that that's highly likely. I don't have any data which contributes to an analyzing that proposition. All I can say is that still strength boils down to cross-sectional area of the muscle. Uh, so you are going to have to have hypertrophy in order to increase. But I would imagine that that hypertrophy can vary with respect to the contribution of water versus fat versus protein.","offset":2470,"duration":65},{"text":"Mike Service: Yeah, definitely. This is really interesting for for me on that side of things from a training aspect, and then even for us from a technique application to how we train people. A lot of times technique suffers from fatigue. So you're tired and you can't perform the same movement with the same intensity. Exactly.","offset":2535,"duration":15},{"text":"Mike Service: Yep. And this is another... so like that would be a lot of times again in weightlifting, you get very good by moving really heavy weight with good technique. So if you can recover well, you can lift that heavy weight and learn a better technique without potentially having to put on more muscle. You just move better. And that's another really interesting component or perspective that I could imagine has a lot more potential to be studied and applied.","offset":2550,"duration":35},{"text":"Dr. Craig Heller: Yeah, definitely.","offset":2585,"duration":3},{"text":"Jordan Samuel: Um, I have a question for you. I did a test with your product just doing max sets of push-ups and so forth. And I guess I felt when I would do my each set I'd go to failure, I felt like it was the thing that was limiting me was a build-up of lactate. And maybe I'm wrong, but does the cooling mechanism that you have play a role in like shunting out lactate as well, or am I way off base? I could very well be.","offset":2588,"duration":2},{"text":"Dr. Craig Heller: You you are common with the vast majority of people who think that lactate causes fatigue. It doesn't. Okay. You can actually infuse lactate and it doesn't cause fatigue. Really? Wow. Okay. But it's the opposite: that fatigue causes lactate. And we're actually studying that right now. And what we find is that the lactate threshold is temperature sensitive.","offset":2590,"duration":35},{"text":"Dr. Craig Heller: So the build-up of lactate must have something to do with that blockage of fuel going into the mitochondria. And we are looking into the possible pathway whereby that situation results in increased lactate production. But the lactate doesn't cause the fatigue. It's the fatigue due to temperature which causes the lactate formation.","offset":2625,"duration":30},{"text":"Dave Durante: I think this is incredibly critical for listeners out there to hear this again, and maybe it comes back to the starting conversation around what's happening from the enzyme perspective as to why the muscle is failing. Correct? So it's not due to lactate, it's due to a temperature increase which then has a cascading effect within the muscle fiber itself. Is that correct?","offset":2655,"duration":30},{"text":"Dr. Craig Heller: Yeah, and that results in the increased lactate production.","offset":2685,"duration":5},{"text":"Dave Durante: And what does the lactate then do to assist in bringing maybe minimizing the effect of the fatigue that's setting in?","offset":2690,"duration":5},{"text":"Dr. Craig Heller: Well, lactate is a metabolic intermediate and it gets metabolized. So that's why you have, you know, lactic acid debt and alactic acid debt after working hard. You can restore your red blood cell oxygen binding in a short period of time, but you can't metabolize lactate...","offset":2695,"duration":5},{"text":"Dr. Craig Heller: That excess lactate in a short period of time. So your temperature will remain a little higher, your metabolism will remain a little higher, uh, while you're undergoing this recovery. Uh, so essentially lactate is a metabolic fuel, so it gets converted back to glucose and uh, transported back to the muscles. And uh, lactate is also critical for the brain. It's an important fuel for the brain. It's produced by the uh, the white matter, the astrocytes, the uh, glial cells, uh, they produce lactate and feed it to the neurons.","offset":2700,"duration":37},{"text":"Host: That's such a critical uh understanding versus what uh, you know, a lot of people out there within the community think some of these mechanisms and how they work. But I think it feeds into maybe one of my last questions here around uh soreness and DOMS and delayed onset muscle soreness with regards to how this system can maybe lessen the effects of soreness that come along with high-fatiguing workouts. Can you talk a little bit about how this has been shown to be beneficial in that sense?","offset":2737,"duration":28},{"text":"Dr. Craig Heller: Sure, uh we're actually very timely. We're about to begin this summer a research project on DOMS and it's stimulated by the fact that so many times we'll have well-trained athletes come into the lab and uh, they will double their work volume, you know, in that day, and I can always expect them to say, \"I'm going to be so sore tomorrow,\" and they never are. Okay? So that led me to hypothesize that uh the soreness is actually due to the unresolved healing of the microtears in the muscle. Okay?","offset":2765,"duration":52},{"text":"Dr. Craig Heller: So what does cooling do? Cooling decreases, it prevents that inflammation. Uh, it also, uh, in a way that's a little bit complicated, uh facilitates the healing. So if you go to a very high temperature, the healing is going to be impaired, and that's going to result in inflammation. So if you uh, have very healthy repair, uh, you don't get the inflammation and you don't get the soreness. So what we're doing this summer is we're doing a series of studies in which we actually drive people to do a workout that will be expected to cause delayed onset muscle soreness and either cool them during the workouts or not cool them during the workouts to see if we have uh an effect on the development of DOMS.","offset":2817,"duration":43},{"text":"Host: That's fascinating. Uh, it's a little counterintuitive sometimes, right? Because you think that getting the muscle, for a muscle to grow or to gain strength you need to, you know, you need to uh have that muscle tear and then repair itself, tear and repair itself, correct? And you're saying that the inflammation that comes along with those tears is what we're trying to prevent from being, I don't know, to me it's it's almost a healing mechanism, like the inflammation is about healing the process. But if you're saying that we want to stop the inflammation from happening, shouldn't it also prevent the healing process or you're trying to speed up that process?","offset":2860,"duration":39},{"text":"Dr. Craig Heller: Well, uh, it's it's a little bit complicated because what you're doing is you're looking at two different things happening at the same time, and it doesn't necessarily mean that they're causally related. Okay? So sure, you generate the microtears in the muscle, they have to be repaired, but what I'm saying is that by uh administering the cooling, you're enhancing that repair without getting the inflammation. So uh, there are many many things in the body that result or they get inflamed and it's not good. It's not healthy. You don't have to have inflammation to get healing.","offset":2899,"duration":40},{"text":"Host: Sure. Sure. I think it's just uh, yeah, go ahead Jordan.","offset":2939,"duration":3},{"text":"Jordan: A follow-up to that that you just said, um is there a potential health benefit to using the CoolMitt outside of exercise if you're saying that it can help reduce inflammation throughout the body potentially, other, you know, pathology?","offset":2942,"duration":19},{"text":"Dr. Craig Heller: Well, uh, what you have to keep in mind with the CoolMitt, and this is for even exercise benefits, is that all it can do is eliminate the effect of high temperature. So if you don't have high temperature, you're not going to get an effect. You're not going to get, so if you're a couch potato and you can do five push-ups, cooling between your five push-ups is not going to do you any good, because it's not the heat which is limiting your performance, okay?","offset":2961,"duration":38},{"text":"Dr. Craig Heller: So if you get to a stage where you're actually producing significant amount of heat during your exercise, that gets to the point where it affects your performance. They say, well if I measure my oral temperature or ear temperature, I don't see an increase. No, for for this kind of activity, for anaerobic exercise, it's the temperature of the working muscle. And the temperature of that muscle can go up much faster than the overall body temperature. If you're doing an endurance sport, then it's the gradual increase of your entire body which is uh the critical variable. But for anaerobic activity, uh it's the build-up of temperature in the working muscle itself.","offset":2999,"duration":42},{"text":"Host: So Dr. Heller, we're coming towards the end of our hour together but I am curious about your own physical training. You mentioned swimming in the Arctic and uh, being fairly physical yourself. Do you use the CoolMitt product and if so what type of workouts are you using it with?","offset":3041,"duration":17},{"text":"Dr. Craig Heller: Well, uh, I'm a little bit too old to be worrying about that now, you know, I'm 80.","offset":3058,"duration":6},{"text":"Host: Oh my goodness.","offset":3064,"duration":2},{"text":"Dr. Craig Heller: But I do work out uh on occasion and uh my one very proud moment was when my students challenged me to be their age control for a experiment they were doing, and that experiment was push-ups and the effect of cooling on the build-up strength and uh, I accepted their challenge and on my 60th birthday I did a thousand push-ups.","offset":3066,"duration":27},{"text":"Jordan: Wow. That's incredible. How long did that take you to do?","offset":3093,"duration":5},{"text":"Dr. Craig Heller: I can still do if I only do one set now, I don't do it routinely, but if I do once I can still go over a hundred.","offset":3098,"duration":7},{"text":"Host: Wow.","offset":3105,"duration":1},{"text":"Jordan: That's incredible.","offset":3106,"duration":1},{"text":"Host: That's really phenomenal. So uh you have a little bit of a, were you an athlete when you were younger?","offset":3107,"duration":6},{"text":"Dr. Craig Heller: Uh, not really. I've always enjoyed you know hiking and skiing and swimming and outdoor activities, but uh when I was in school I was cross country runner but I didn't excel for sure.","offset":3113,"duration":16},{"text":"Host: Well we have a fun uh question that we always ask our guests and uh not quite sure if you'll have uh an answer from your experience as an athlete, but is there a sport that you prefer either weightlifting or gymnastics? This is a competition that me and Mike have going back and forth with our guests and we have a tally. Weightlifting or gymnastics, what do you prefer?","offset":3129,"duration":21},{"text":"Dr. Craig Heller: Uh, well I guess weightlifting.","offset":3150,"duration":3},{"text":"Mike: I knew I loved you Dr. Heller. Thank you so much for that.","offset":3153,"duration":5},{"text":"Dr. Craig Heller: I translate that into the resistance type activities that I enjoy doing uh in the gym, you know whether it's uh you know dips or or uh pull-ups or push-ups or sit-ups or...","offset":3158,"duration":13},{"text":"Mike: I mean, everything you just mentioned is bodyweight movements. Those are all gymnastics movements.","offset":3171,"duration":5},{"text":"Host: I'm going to take them. I guess you each get a point there, but before we ask the rest of our last minute questions, I do want to ask one more question for Dr. Heller and that's for our listeners who don't have um the ability to get their hands on a CoolMitt, um what sort of protocol can you recommend they try to see if they can elicit the similar response?","offset":3176,"duration":25},{"text":"Dr. Craig Heller: Good question, uh we should have mentioned that earlier. And that is the first impulse people have is, \"oh I'll just get a bucket of ice water,\" and that doesn't work. And the reason is it's too cold. That if you dip your hands in ice water you get reflex vasoconstriction to prevent you from getting hypothermic, right? So if you have a bucket of water at room temperature uh tap water temperature uh you know your bathroom basin water temperature, uh just putting your hands in that will help.","offset":3201,"duration":39},{"text":"Host: Okay.","offset":3240,"duration":1},{"text":"Jordan: Cool.","offset":3241,"duration":1},{"text":"Host: Thank you. Keep them moving.","offset":3242,"duration":2},{"text":"Jordan: Right. I I really would love to uh have this product, uh have CoolMitt out at our Power Monkey camp. Uh I mentioned it earlier, but we have like a full week-long adult fitness camp out in the woods of Tennessee and we bring out about 150 people and for a full week of training this is like an ideal product for people to test with the type of workouts that we do out there. So I I just think we have such a good community that would benefit from testing this out with the types of workouts that we have within the CrossFit and the functional fitness community. So hopefully we can...","offset":3244,"duration":29},{"text":"Dr. Craig Heller: I can give you one bit of advice on that.","offset":3273,"duration":3},{"text":"Host: Let's hear it.","offset":3276,"duration":1},{"text":"Dr. Craig Heller: And that is if you do have people becoming hyperthermic, okay, uh the standard of care is ice packs on the groin, the axilla, and the the the neck, right? Okay? So we've done experiments where we've made people hyperthermic, hyperthermic, and then we have cooled them by either putting the ice packs in the standard of care position or putting the same ice packs just on the palms, the soles, and the face. And the rate of recovery is about double if you use them on the face, the palms, and the soles rather than here.","offset":3277,"duration":45},{"text":"Host: Now we got to test it out. We got to test it out with our crew.","offset":3322,"duration":3},{"text":"Dr. Craig Heller: And it makes good sense because if your car is overheating and you have a garden hose, are you going to spray the tubes going in and out of the radiator or you going to spray the radiator? Right? So these are the tubes going in and out of the radiator. This is the radiator.","offset":3325,"duration":18},{"text":"Host: I mean, that's just important to understand anatomy too, like what what those systems are actually doing versus just saying, hey I'm sweating from these areas so this is where my temperature's being regulated from. Right. Right. Uh Dr. Heller, one or two more questions, quick ones for you, if there's a guest that you think would be great to have on the podcast, maybe someone that works in your lab or another professor out at at Stanford, someone that would be a good interview, anyone that you would recommend to have on the podcast?","offset":3343,"duration":28},{"text":"Dr. Craig Heller: Uh yeah, um we have one uh actually a couple, Erica and Justin Sonnenburg uh who work on work on the microbiome. And uh the microbiome is something that I think needs a lot more attention with respect to uh our health and our fitness. Uh, so they would be good. Another person uh is Christopher Gardner. And Chris is a nutritionist, so uh he he would be very uh very helpful. I mean the big deal is comparing our current Western industrialized diet with uh healthier diets that uh are seen elsewhere in the world.","offset":3371,"duration":47},{"text":"Host: Perfect. Uh Jordan's taking those notes and be able to reach out. We appreciate those. Uh last question for you, uh if you're a book reader which I'm sure you are, is there anything that it could be something around uh the technology and what goes into uh CoolMitt technology, but is there a book that you would recommend our our listeners check into?","offset":3418,"duration":22},{"text":"Dr. Craig Heller: Oh, golly. I wish there were. Um I can't come up with one other than writing it. Uh I've had trouble finding time to write it.","offset":3440,"duration":9},{"text":"Host: Maybe we can pass along the research studies on some of these things so people could have a little bit more of a scientific understanding of what's happening.","offset":3449,"duration":7},{"text":"Dr. Craig Heller: But the Sonnenburgs have uh written a recent and a very good book uh essentially on the relevance of the microbiome and diet. So that would be a good book, I'm blocking on the name of it right now.","offset":3456,"duration":14},{"text":"Host: We'll make sure to to link it in with the the podcast itself. Uh last question, with all the amazing things you got going on, where can people follow along with you personally along with the CoolMitt? Where's the best place for our listeners to follow up with uh anything that they might want to have question-wise?","offset":3470,"duration":16},{"text":"Dr. Craig Heller: Well coolmitt.com uh will get you right to uh whatever is current, whatever is local. If people have specific questions they can try emailing me, hcheller@stanford.edu. Can't promise I can respond quickly, but I try.","offset":3486,"duration":24},{"text":"Host: Perfect. Well Dr. Heller, it was a pleasure. I really appreciate the time. Uh we can't wait to continue to test the CoolMitt product. Uh all the great results and uh for the listeners out there, we will be giving this a try at our Power Monkey camp. Uh this is going to be coming out right around when we have our next camp out in Tennessee. So listen closely, follow along at powermonkeyfitness.com and @powermonkeyfitness on Instagram and uh for our listeners, thank you all for listening.","offset":3510,"duration":15}],"logs":[{"elapsed":"0.0","message":"Downloading audio from YouTube...","detail":null},{"elapsed":"0.0","message":"Trying download with browser cookies (ad-free)...","detail":null},{"elapsed":"2.8","message":"⚠ Cookie download failed: WARNING: [youtube] [jsc] Error solving n challenge request using \"deno\" provider: Error running deno process (returncode: 1): \u001b[0m\u001b[1m\u001b[31merror\u001b[0m: Uncaught (in promise) TypeError: Cannot read prope","detail":null},{"elapsed":"2.8","message":"Retrying without cookies...","detail":null},{"elapsed":"30.1","message":"⚠ Downloaded without cookies — audio may contain ads","detail":null},{"elapsed":"30.1","message":"Audio downloaded (33.4 MB) in 30.1s","detail":"File size: 33.4 MB"},{"elapsed":"30.1","message":"Video title: PMPC217: Beating Fatigue with Dr. Craig Heller","detail":null},{"elapsed":"30.2","message":"Audio duration: 59:10 (59.2 min)","detail":null},{"elapsed":"30.2","message":"Large audio (33.4 MB) — will use chunked transcription with gemini-3-flash-preview","detail":null},{"elapsed":"30.2","message":"Skipping full-file attempt — using chunked transcription for 59.2 min audio","detail":null},{"elapsed":"30.6","message":"Split audio into 2 chunks for transcription","detail":null},{"elapsed":"30.6","message":"Transcribing chunk 1/2 (starts at 0:00)...","detail":null},{"elapsed":"30.6","message":"Uploading audio to Gemini File API...","detail":null},{"elapsed":"34.9","message":"Audio uploaded in 4.3s","detail":"File ref: files/6212yw31khpu"},{"elapsed":"34.9","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"102.0","message":"Chunk 1: 110 segments, last timestamp 44:55","detail":null},{"elapsed":"102.0","message":"Transcribing chunk 2/2 (starts at 45:00)...","detail":null},{"elapsed":"102.0","message":"Uploading audio (offset 45:00) to Gemini File API...","detail":null},{"elapsed":"104.3","message":"Audio uploaded in 2.3s","detail":"File ref: files/3nq3hpi2mgvm"},{"elapsed":"104.3","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"125.8","message":"Adjusted chunk 2 timestamps by +45:00","detail":null},{"elapsed":"125.8","message":"Chunk 2: 45 segments, last timestamp 58:30","detail":null},{"elapsed":"125.8","message":"Chunked transcription complete: 155 total segments","detail":null},{"elapsed":"125.8","message":"Total cost: 89,214 in / 13,401 out — cost: $0.0848","detail":null},{"elapsed":"125.8","message":"Total transcription time: 95.6s — 155 segments","detail":null},{"elapsed":"125.8","message":"Analyzing topics across 155 segments with gemini-3.1-pro-preview...","detail":null},{"elapsed":"192.8","message":"Topic analysis complete in 67.0s — found 15 topics","detail":null},{"elapsed":"192.8","message":"Analysis tokens: 14,239 in / 1,287 out / 4,791 thinking — cost: $0.1014","detail":null},{"elapsed":"192.8","message":"Pipeline finished in 192.8s — total cost: $0.1862 (122,932 tokens)","detail":null}]} \ No newline at end of file diff --git a/history/1775679261151-MPAsUZEJHiM.json b/history/1775679261151-MPAsUZEJHiM.json new file mode 100644 index 0000000..25febd7 --- /dev/null +++ b/history/1775679261151-MPAsUZEJHiM.json @@ -0,0 +1 @@ +{"id":"1775679261151-MPAsUZEJHiM","videoId":"MPAsUZEJHiM","url":"https://www.youtube.com/watch?v=MPAsUZEJHiM","title":"Josh Shapiro on Trump, Iran War Chaos, Israel's Failure, the Economy, and 2028 Race","type":"youtube","topicCount":10,"segmentCount":117,"createdAt":"2026-04-08T20:14:21.151Z","uploadDate":"20260408","chunks":[{"title":"Introduction and Basketball Banter","summary":"The host introduces Governor Josh Shapiro and plays a vintage clip of him playing basketball. They exchange lighthearted banter about their rival NBA teams.","entries":[{"text":"Host: Alright everybody, we’ve got an incredible guest today. Governor Josh Shapiro is here, obviously Governor of Pennsylvania. He’s got record-setting popularity in Pennsylvania right now, 60% approval at least. He’s a moderate, he’s focused on getting [ __ ] done, GSD. He’s tough on crime, ranked number one according to my notes on charging Medicaid fraud. He’s pro-data center, he’s got a nuanced take on Israel, and he’s a baller, apparently. Cuts to the tape.","offset":0,"duration":29},{"text":"Host: Got him! There it is.","offset":29,"duration":3},{"text":"Host: Oh my god.","offset":32,"duration":1},{"text":"Host: There’s your Governor.","offset":33,"duration":1},{"text":"Host: Look at those short shorts. Holy [ __ ]. Incredible, wow. It’s the late 80s?","offset":34,"duration":9},{"text":"Host: And based on the VHS tape, this looks like the 80s.","offset":43,"duration":3},{"text":"Host: Yeah, that was 1990, I think.","offset":46,"duration":4},{"text":"Host: Look at that, playing the point.","offset":50,"duration":2},{"text":"Host: There you go. Very nice, very nice.","offset":52,"duration":8},{"text":"Host: All right, enough of that. That was back when, that was back when people shot mid-range jumpers. They don’t do that anymore, man. They don’t do that.","offset":60,"duration":3},{"text":"Josh Shapiro: They should. All threes, yeah. I mean, we have a couple of players and we were talking before the show started, you’re obviously a big Philly fan and I’m a big Knicks fan, so I will see you at the games. We’re on a collision course.","offset":63,"duration":11},{"text":"Josh Shapiro: I, by the way, with all due respect and I hope we have a good conversation here, I hope to never see you at the games. Because if you’re showing up in Philly with all your Knicks crap on, I’m not going to be a happy guy.","offset":74,"duration":7},{"text":"Host: Oh, look at the selfie courtside with my friend Dave, who is one of the co-owners of the team who is our mutual friend of ours, who I think egged you on a little bit to come on the program here, which I appreciate.","offset":81,"duration":10},{"text":"Josh Shapiro: He did. He said go on All-In, they have thoughtful conversations and anxious to have one with you. So thanks for having me.","offset":91,"duration":6}],"startTime":0},{"title":"Economic Growth and Permitting Reform in PA","summary":"Shapiro outlines Pennsylvania's pro-growth strategies, emphasizing a streamlined permitting process with a money-back guarantee. He explains how improving government efficiency creates jobs and reduces voter cynicism.","entries":[{"text":"Host: Yeah, there’s so much for us to talk about but I thought I would start with your track record in Pennsylvania. And the reason I wanted to start there is because there’s a bit of a collision course happening right now between you and Gavin. Gavin’s got what I would describe as a variable tenure here in California. I left California for Texas because I just thought it was a bit of a disaster. But you’re doing great in your state and that’s in the face of New York, my hometown, New Jersey, Boston, like losing a lot of business leaders. And you’ve been scoring, you know, some big wins. So when you look at your track record, maybe you could just educate the audience on what you’ve gotten done and maybe in comparison to what’s happening in those other states with other Democratic leaders, because you seem to be maybe the exception to this rule that Democrats aren’t getting it done on a business level.","offset":97,"duration":52},{"text":"Josh Shapiro: Look, I’m proud of what we’ve done. I’m not in comparison with Gavin or any other Democratic governor. I’ll just talk about what we’ve done here in Pennsylvania. We are a pro-growth state. We want businesses to come here and grow. I’m proud of the fact that we’ve created more jobs than all but two states in the entire country. We’ve cut taxes seven different times to be more competitive. Cut taxes for small businesses, also for families trying to afford childcare, for seniors, for working Pennsylvanians. We’ve taken our permitting process, that’s the usually the the ticket you need say to build your building, right, if you’re trying to build something here in Pennsylvania, we were bottom five in the country. I think we’re now a national model, easily top five in terms of speed. We’ve got a money-back guarantee on all of our permits. If we don’t get you your permit in time, we’ll give your money back. And fun fact, we’ve issued 40 million permits during my time as governor, we’ve only had to issue five refunds, meaning only five of those permits were late. We are now the only growing economy in the northeastern part of the United States. At the same time, we’re investing in workforce development, especially if you don’t have a college degree, tripling funding for Vo-Tech and apprenticeship programs and understanding the need to take the workforce we have today and prepare them for jobs here in the Commonwealth of Pennsylvania. Proud that we’ve got an unemployment rate below the national rate consistently over the last 32 months. I think it is really critical that every kid born in Pennsylvania gets a great quality education, that that kid has a safe street to walk down to get to school or wherever else they’re going, and that they’ve got a job in the community that they love. Those to me are the core foundational principles. It’s what we focus on every single day. Our mantra, as you said at the top, is GSD, get [ __ ] done. Those are the areas where we focus on getting [ __ ] done and I think we’re putting a lot of points on the board every single day that’s having a meaningful difference in people’s lives.","offset":149,"duration":126},{"text":"Host: How are you getting that done? Let’s just take the permitting as an example. Why is it so dysfunctional in California? You know, obviously I’m an investor in technology companies and we just saw red tape after red tape, then on housing, it’s incredibly hard to build anything. The NIMBYism, you know, if you cast a shadow, nothing can be built and then housing prices keep going up. And you know, if you want to hire a nanny or a teacher or you know, if a firefighter moves in, they can’t even afford a home in the community that they’re servicing. So how did you fix this and why can’t other states not fix it?","offset":275,"duration":38},{"text":"Josh Shapiro: I mean, look, I can’t speak to how it’s done in California. I’ll just tell you in Pennsylvania, the way we start the conversation is by recognizing permits are critically important to economic development and to creating jobs, right? If we the government can move at the speed of business, if I can give you as a CEO predictability to know your business is going to be open in six months instead of three years, right, because the permit took too long, then you’re going to want to invest here. So we sort of start with the important idea that permits matter. Second, when you come into our state government to get your permit, let’s just use building a building as an example, right, we want to get to yes. We still want to protect the environment and public health and public safety, and we do that, but we want to get to yes. So our attitude has shifted. Third, we’ve got to have that money-back guarantee, because that money-back guarantee holds the bureaucracy accountable. Now, I will tell you that some of this we’ve done administratively, meaning I’ve signed executive orders and we’ve made those changes. But other things, we’ve worked with the legislature to pass new laws to speed up our permitting. And it hasn’t always been easy. Understand I’m a Democrat as governor, I’ve got a divided legislature. I was the only governor for a while with a divided legislature, now there’s one other. I’ve got a Senate led by Republicans by just two seats and a House led by Democrats by just one seat. But this is an area where I’ve been able to bring Democrats and Republicans together in order to make progress in terms of passing this this permitting reform. And again, proof is in the pudding. What we are seeing is that businesses are coming here and the economy’s growing. Let me give you one more example. This may seem really small to you, but it’s a big deal, okay? When I talk about a permit, if you want to be a barber in Pennsylvania, you need a permit, or technically it’s called a license, but I put it all under my...","offset":313,"duration":101},{"text":"Host: Yeah, some kind of certificate, yeah.","offset":414,"duration":1},{"text":"Josh Shapiro: Right. The day I took office, it took 20 days for a barber to get their permit to be able to go out and cut hair. Today you get it same day, you get it within that day. That may seem silly to you, but but understand, I called my barber. I asked him, I said, how many heads do you cut a day? He said about 10 a day. At 20 bucks a pop, 200 bucks a day for for 20 days, that’s real money. That’s thousands of dollars that we’re putting into that barber’s pocket just because we got them their permit more quickly. So I know it may sound nerdy, it may sound wonky, but whether you’re building some big building that’s going to house hundreds of workers or thousands of people who are living there, or whether you’re the local barber that everybody needs to go to to get to get their haircut, this stuff matters. And the quicker you are, the more jobs you create and the more money you put in people’s pockets.","offset":415,"duration":58},{"text":"Host: It also matters I think on a philosophical basis of who is the government working for? Themselves and their timelines, or for the people who put them in office? And I think that’s the philosophy, just watching it happen in New York and California, it’s the opposite of what you described. There’s no sense of urgency and there’s almost a situation where people believe it’s intractable, that they can’t change it. And so that’s I think such an important point is that you actually made it happen.","offset":473,"duration":31},{"text":"Josh Shapiro: I think that’s a great point. I want to focus on what you just said there. First off, I start the conversation believing that government can be a force for good in people’s lives. Second, that we’ve got to figure out a way to get to yes. Whether it’s building a building or whether it’s getting that mom the support she needs for her kid with autism who needs support. We’ve got to figure out a way to get to yes and get them that help. And then you mentioned in your question the way people get, I don’t recall if you used the word frustrated or or they feel, you know, that government’s sort of holding them back, right?","offset":504,"duration":34},{"text":"Host: It’s oppressive in a way, right? Just if you have that experience three or four times, whether it’s at the airport or getting your driver’s license or getting the haircutting, you know, certificate, like it’s just oppressive over time, you just feel like the government’s working against you.","offset":538,"duration":14},{"text":"Josh Shapiro: Yeah, and what does that, what does that person feel after they try and get their permit, they can’t get it, they try and open up their small business, it won’t work? They get frustrated. By the way, they get pissed. And then not only are they pissed at that agency or that governor, or they’re pissed at that state government, they also grow, and this is an important point, a little more cynical about government and a little more frustrated about the process. And when that happens, I think that that creates more distrust in our system and it creates more opportunity for, I think frankly dark voices on extremes to come in and take advantage of people. I I find that, you know, if we get it done the right way, if we process things quicker, if we get people to yes, then maybe a byproduct of that is a little bit less cynicism in our system.","offset":552,"duration":52}],"startTime":97},{"title":"Rooting Out Waste and Medicaid Fraud","summary":"The host asks about eliminating government waste and fraud. Shapiro highlights his record of prosecuting PPP loan fraud as Attorney General and his ongoing efforts to target Medicaid fraud.","entries":[{"text":"Host: Yeah, and the horseshoe theory that you’re kind of referencing there, these two extremes just taking over the conversation, that’s not what the majority of the country wants. They they want to just live in a high-functioning society. I was curious how you look at fraud, waste fraud and abuse. My friend Elon, to drop a name, you know, did this doge thing, was a little controversial, but I think what we’ve seen is hey, 20-30% of every tax dollar collected is wasted. Some of it’s fraud, some of it’s just incompetence, it could be anything on that spectrum. And this seems to be the Republican party’s rallying cry to beat the Democrats, going into California and prosecuting people, Michigan, etc. You have seemed to have gotten ahead of this, you’ve been doing this for years. So maybe you could explain your take on fighting fraud specifically, healthcare or in other areas.","offset":604,"duration":53},{"text":"Josh Shapiro: Look, I think we’ve got to focus on rooting fraud out of the system. Now, you and I may differ on hey, should we spend a dollar on that initiative or not? And by the way, those are super healthy differences and we should argue that out, we should debate that. But where we should have no difference is if someone’s stealing that dollar instead of going to its intended purpose, we should be against that. And and I am. Prior to serving as governor and having the privilege of sitting here in this office serving the good people of Pennsylvania, I was the state’s Attorney General. And you’ll remember back during COVID, there were those PPP loans to help our small businesses and other businesses stay afloat. We’d probably agree like, good idea, right? We’ve got to keep businesses afloat. But during that time, I went out and prosecuted a whole bunch of people for stealing that PPP money, for not using it for its intended purposes. Here as governor, I’ve maintained a similar focus through my office of Inspector General rooting out fraud, through making sure, by the way, we’re not fronting you money when you’re going out and providing say human services, you have to submit for reimbursements and you’ve got to make sure you prove that you did that work. When we find that someone took advantage of the system, we’re referring them to prosecutors. I’m proud of the fact that we’ve had more Medicaid fraud prosecutions in Pennsylvania than I think any other state, maybe there was one other. We’re we’re certainly toward the top of that list. Proud of the fact that we’ve identified that, we’ve sent it to prosecutors and we’ve addressed it. If we can address it administratively, we do. If not, we understand that those things need to be prosecuted. We should have a zero-tolerance policy for that and we should make sure that if we’re going to utilize a hard-earned dollar of a taxpayer for a purpose like providing someone with healthcare, that we’ve got to make sure that that dollar makes its way to that person so they get their healthcare. And, you know, our folks are working really hard on that in Pennsylvania.","offset":657,"duration":114}],"startTime":604},{"title":"State Tax Policy and Wealth Disparity","summary":"Addressing concerns about wealth taxes, Shapiro details Pennsylvania's tax cuts and the Working Pennsylvanians Tax Credit. He contrasts his approach with Donald Trump's tax cuts, which he argues disproportionately benefit the wealthy and harm healthcare access.","entries":[{"text":"Host: So pro-business, less regulation, lowering taxes, eliminating fraud, and all of this is just getting done in the state. And then, you know, the next piece that in at least my community, people who are creators of businesses, venture capitalists, angel investors, founders, we pay our taxes, pay a lot of taxes depending on which state you live in. And then there’s this movement...","offset":771,"duration":26},{"text":"Josh Shapiro: You should be paying more taxes in Pennsylvania, man, stop paying them elsewhere.","offset":797,"duration":2},{"text":"Host: Yeah, well, the and you know, we then get struck with this California law and a lot of my friends have moved to Austin where I live now, they just said suddenly hey, we want to seize 5% of whatever you got. You already paid your taxes, you haven’t paid capital gains on some of this equity you own in your company, maybe it’s paper wealth, maybe your company went public now and you could sell some of it, but you might crater the stock if you do. And Elizabeth Warren, Bernie Sanders, and California all trying to seize assets on gains they’ve never received. It’s a, it seems to be getting momentum.","offset":799,"duration":60},{"text":"Josh Shapiro: I mean, I would just tell you, we’ve cut taxes seven times in Pennsylvania. We’ve got one of the lowest income taxes in the entire country, that’s why I’m joking with you, you should come to Pennsylvania and relocate here. And and look, I mean, that kind of tax that you’re describing is not something we have here, it’s certainly not something on on my agenda. I do think people need to pay their fair share. I think you’d agree with that. We need to make sure that we are easing the burden on those who are working and who are at the lowest, you know, sort of economic point on the scale. And we’ve got to make sure that folks at the top are paying their their fair share in order to to sustain our society. And I think we’ve struck a really good balance here in Pennsylvania. And I think our growth numbers bear that out. I think seeing more people coming to this state bears that out. And I think there’s an important stat, one of the things you you cited in those entrepreneurs as you were going through your question is, you know, these are people who kind of started with a dream, with an idea that, you know, someone might have looked at and said, jeez, I I don’t know about that, but they stuck with it and and they built up their companies. We see here in Pennsylvania, particularly when it comes to life sciences, right, we’re seeing people plant a flag here in Pennsylvania, start with an idea that others might think, boy, I I don’t know about that, but then because of our tax environment in Pennsylvania, because of our pro-growth approach in Pennsylvania, we’re seeing more of those small businesses, more of those small companies, especially in life sciences, survive that sort of valley where a lot of those companies go out of business and sustain themselves here because again, I think we’re showing that we’re pro-growth, we’ve got a smart tax environment for them, and by the way, after we invest in them, after we give them a shot, and after they do well, we expect them to pay their fair share back to the Commonwealth of Pennsylvania. And I think that’s that’s the approach we’ve taken and it’s working.","offset":859,"duration":118},{"text":"Host: Yeah, and so if you’re not in favor of a wealth tax, what would you do to deal with maybe this disparity in wealth that we’re seeing? There was just some statistics that came out the other day, I’m sure you saw them, the upper-middle class has just been surging, middle class going down a bit, and people in the lower rungs going down as well. So people may feel like they’re not making enough money, but in reality what’s happening is people feel other people have made a tremendous amount of money, which is true because of equity holdings are growing much better than salaries ever will and only 40% of only 50% of the country really participates in a meaningful way in equities, the other 40-50% don’t have any exposure to that. So how would you deal with somebody making, you know, 100 billion dollars, 500 billion dollars, a trillion dollars and never selling their equity or maybe not selling it for 20 years? How do you think about that?","offset":977,"duration":58},{"text":"Josh Shapiro: Let let me make three points, a Pennsylvania point and a couple broader points. One, you cannot have a national economy that works if it’s only working for the 1%. And you pointed out in your question the wage disparity and the disparity of income. You have to make sure that there is opportunity for those at all different income levels. And look, as we sit here today, if you’re making a million dollars versus fifty thousand dollars, if you make a million dollars you’re going to be able to buy some stuff that someone at fifty thousand dollars can’t buy, right? We sort of understand that, but you’ve got to have opportunity and you’ve got to have a level playing field, and you’ve got to have a fair shot, and you’ve got to have a tax system that works in a fair way. So that’s sort of point one. Point two is here in Pennsylvania, we’ve tried to address some of that economic disparity by passing the first-ever Working Pennsylvanians Tax Credit, sort of a state-side earned income tax credit. So what we’re saying is if you’re working, if you’re going out and busting your hump, we’re going to put some money back in your pocket. About 940,000, almost a million Pennsylvanians are going to qualify for a little over 800 bucks back in their pockets. So that’s going to help not only today with rising costs due to a lot of these federal policies, but it’s going to put money back in people’s pockets, allow them to make, you know, the the the investments they need to make in their everyday lives. Here’s the third point. What I would not do, because you asked what I would do, what I would not do is what President Trump did at the federal level with an aid and assist from a whole bunch of sycophants in Congress by passing that budget bill, the beautiful budget bill, whatever the hell they called it. In effect, what they did was they gave a tax cut for those who simply do not need it, right? And by the way, in the palace of truth and justice, you talk to those folks, they know that they didn’t need that tax cut. And what happened as a result of that is I’ve got 500,000 Pennsylvanians who are going to lose their healthcare. I’ve got 120,000 who have already lost their healthcare, about another 320,000 or so are likely to lose Medicaid next year. I’ve got 26 rural hospitals that are likely to shutter because these are rural hospitals that are working at an operating deficit and they’re relying so much on Medicaid, which has been slashed by the federal government. So the idea that Donald Trump thought it was smart economic policy to give a tax cut to those who don’t need it and pay for it with those who are struggling where and and create even greater economic disparities, that is going to hold back our entire economy. Just take those 500,000 people who aren’t going to have healthcare. You’re paying for that, and I’m paying for that, with our private insurance premiums. So what Donald Trump has done is shifted that burden onto those who are struggling, making it harder for them, adding additional costs to the middle class, and I think that that is that lacks frankly it’s just dumb economic policy and I think it’s going to set us back.","offset":1035,"duration":181}],"startTime":771},{"title":"Democratic Strategy and the VP Selection Process","summary":"The host questions the Democratic Party's primary process and whether Shapiro was passed over for Vice President due to his Jewish faith. Shapiro clarifies that he voluntarily withdrew from consideration to continue serving as Governor.","entries":[{"text":"Host: So here we are, politics is on the table. Incredible track record you have, but let’s dive into the Democratic Party. I’m an independent, but grew up Irish Catholic in Brooklyn, so grew up a Democrat. Probably have voted, you know, 60-40 Democrat to Republican, but always for a moderate, somebody who can get stuff done, that’s why I find you quite appealing. But let’s talk about the Democratic Party and the shellacking they got in the last election and specifically what really troubled me, Biden didn’t look like he was all there and I think we’ve all come to some consensus that he probably should have dropped out early. But what was really disheartening to me was that they didn’t do the speed run primary, they didn’t do, you know, a capsule primary over that July-August period and gave you a shot and other people a shot, Pritzker, Buttigieg, whoever, to to compete for the nomination. Was that a huge mistake for the Democratic Party and and when you look back on it, do you think that might have cost you all the election?","offset":1216,"duration":62},{"text":"Josh Shapiro: Well, look, I mean I actually wrote about this in in the book I recently published where, you know, it it became clear to me that, you know, Joe Biden seeking another term was probably not in the best interest of the party or the country and I spoke to him directly about that and bluntly about that. Once he made the decision to drop back with a hundred and whatever days to go, you know, there there were not many opportunities I think to have the kind of primary process that you’re talking about. I think it is important to look forward, right, and not look backward and you said in the last election Democrats took a shellacking. Actually, if you look at 2025, it was the opposite. I mean the President’s party, the Republican Party, got beat in New Jersey, got beat in Virginia, got beat here in Pennsylvania where we won three state supreme court seats. So obviously there’s a pendulum in in American politics and it’s clearly swinging back and forth. I think what’s important is that we look forward and I think it’s also really important for our party to have for my party to have a real debate and to have a real discussion about ideas. What are we for? And what are we willing to fight for? And I realize that process may at times look a little messy, I realize and I mean this with the utmost respect, it gives folks like you on a podcast or on a show the ability to sort of pick apart, maybe try and, you know, sort of parse words or point one Democrat at another and try and create conflict. But I would just say that overall, having this debate and having these issues be raised and having disagreements, that’s healthy for our party and ultimately I think our party’s poised to take back power and that will make us better at governing. To me, the whole purpose of running in an election is getting the chance to govern, not just winning the election. And so having these debates right now puts us in a better position when we win those elections and I’m running for reelection right now in Pennsylvania, going to work my ass off to win another term and earn the support of the people of Pennsylvania again and I want to continue to deliver, continue to, you know, focus on these issues that matter most and having that debate I think is really healthy.","offset":1278,"duration":123},{"text":"Host: I understand looking forward is most important, but I got I gotta go one more time in the rearview mirror here, which is Kamala Harris was picked because Biden had put out a criteria hey, I want to have a woman of color as my Vice President, he was very explicit about that. She could be quite qualified, unqualified, you know, moderately qualified, but then when she went out to pick her VP, everybody was saying hey, Josh Shapiro should be really in that running and she didn’t pick you specifically because she didn’t think she could win with a Jewish Vice President.","offset":1401,"duration":30},{"text":"Josh Shapiro: Yeah, I I don’t, respectfully, I gotta push back on that. And again, I’ve been very, very open about this.","offset":1431,"duration":6},{"text":"Host: Okay, push back on it, yeah, let’s go.","offset":1437,"duration":1},{"text":"Josh Shapiro: Yeah, and respectfully, I’m not looking to be argumentative with you, but I was very, very detailed and very specific in my book about this process and I was very grateful to the Vice President for being considered and grateful to her for the candid dialogue we had and about 48 hours before she picked Tim Walz, I pulled out and made clear that that was not something I was interested in doing. I thought I could serve the good people of Pennsylvania and do my best serving here as Governor in a job that I absolutely love. So this wasn’t about her not picking me because of my faith, this was about me in the end not being interested in in that job.","offset":1438,"duration":41},{"text":"Host: Really? Sincerely, yes? Because it did seem like you wanted to to be considered for that VP position.","offset":1479,"duration":7},{"text":"Josh Shapiro: I I called Sunday evening after she and I met and had a really candid conversation to inform her that I did not want to be considered. I thought she had some really good people to choose from.","offset":1486,"duration":11}],"startTime":1216},{"title":"Democratic Platform and Expanding Opportunities","summary":"Discussing the path forward for Democrats, Shapiro outlines a platform centered on education, safety, economic opportunity, and freedom. He highlights his work expanding housing, funding vocational training, and removing college degree requirements for state jobs.","entries":[{"text":"Host: All right, so let’s move forward then, looking at winning. You’re gonna run for Governor again. I assume that’s gonna be a shoo-in, you know, you gotta do the work, but it’s pretty clear you’re gonna win.","offset":1497,"duration":8},{"text":"Josh Shapiro: I appreciate your your confidence there, my man.","offset":1505,"duration":3},{"text":"Host: No, it’s clear. But let’s talk a little bit about if you were to run for President, which people seem to think you’ve got a really good shot, but you’re below maybe national recognition right now or a little bit far behind. Gavin has come out hey, I’m running, I’m running, here I am, he’s obviously in the pole position for now. I want to understand the Democratic Party and how they should proceed because just like the right seemed to separate and you had this MAGA coalition and you had, you know, the traditional Republicans who were just aghast at Trump and his style and his behavior, etc., now that seems to have fractured again. You have America First, America Only, all the supporters who were supporting Trump now have come out vocally against him because of the war in Iran. And then you have on your side this Socialist Democrat movement, which I think a lot of moderates are like, well that’s confusing, we don’t want to have more Mondames and that doesn’t seem super appealing to a lot of moderates, and the moderates are the ones who flipped this election and they went, the last election, they went with Trump largely as opposed to going with Kamala. So handicap for me what has to happen in the Democratic Party to win in 2028?","offset":1508,"duration":76},{"text":"Josh Shapiro: I understand why you’re asking that, and I will answer your question. I don’t think anyone should be looking past these midterms. And while I appreciate the confidence you have in me and and maybe in the broader dynamics here, I think we need to have a national referendum in these midterms on what people see happening in Washington, D.C. The chaos and the corruption that exists there. I think people need to show up in record numbers and vote their concerns. And so I’m not looking past the midterms. I do think it is important that we acknowledge Donald Trump has injected chaos and corruption into everything he touched. And I think it’s important for me, for other Democratic leaders in this country, to be able to show what calm, competent governance can actually deliver for people. That’s what I’m going to be talking about in these midterms as I seek reelection. I think it is important to paint an alternative picture to the chaos Donald Trump has created. One where you can actually grow the economy. You can make our communities safer. We didn’t talk about this yet, but we’ve hired 2,000 more police officers, invested in community violence prevention, and violent crime is down 12%, fatal gun violence is down 42% in our Commonwealth. We’ve invested in public education and by the way, scores are up, truancy is down, we’re moving up on the list, we’re about 10th according to Consumer Affairs in the quality of public education. I think we’ve got to show that there is an alternative to Donald Trump’s chaos, to his cruelty, to his corruption and you’re seeing that I think certainly in my state and I think you’re seeing it in other states as well. And we need to paint that alternative picture.","offset":1584,"duration":107},{"text":"Host: So 2026 is certainly going to be a referendum on the first two years of this presidency, which was extremely popular for the first nine months or so. People felt really good about the economy and that had well...","offset":1691,"duration":13},{"text":"Josh Shapiro: Some people.","offset":1704,"duration":1},{"text":"Host: Well, I think his polling was great, but there was this tinge, I think it’s pretty accurate to say the tariffs felt like those were chaotic. Then you get the ICE situation, that feels very chaotic. Then you go to this war with Iran, and that feels like a peak chaotic moment that we’re in here in week six of this. So it’s certainly going to be a referendum on Trump, and it feels like all the Democrats have to do is sit back and say like look, is this what you want? Gas prices up, inflation. But you’re saying they have to paint another picture. Paint that picture for me, what is that picture?","offset":1705,"duration":34},{"text":"Josh Shapiro: I think on both sides of what you just said, Donald Trump chose to push the tariff button, right? And as a result, here in Pennsylvania, what we’re seeing is coffee prices are up 30%, beef is up 19%, OJ, orange juice is up 9%. The fertilizers my farmers rely on here in Pennsylvania up 36%. So we’re seeing whether you’re a farmer, whether you’re, you know, a dad just trying to cook dinner for his kids, whatever the case may be, everything costs more because of the recklessness and the chaotic approach Donald Trump’s taking our economy with these tariffs. Obviously this war has spiked gas prices, up today about 4:15, 4:16 here in Pennsylvania, similar across the country. Probably years before those gas prices come down, even if the war, you know, hopefully ends, you know, very very soon. And so I think it is important yes, to point that out. The way Donald Trump’s policies have hurt the American people, have hurt our farmers, have hurt our small businesses. The point I was making a moment ago is I think that’s part of the conversation. The other part of the conversation is okay, well what are you doing to make people’s lives better?","offset":1739,"duration":72},{"text":"Host: Yeah well so what should the top three things be? Like if you were running the Democratic Party and everybody got in a room and said you know what, we really are going to take winning seriously, not getting into this like purity test for everybody in the party and you know, everybody’s gotta be perfect and Joe Rogan’s not good enough to go on air with because he’s a lifelong Democrat but he said something about COVID we don’t agree with, therefore he’s out of the party. Elon Musk is a little bit weird on the well, but the Democrats did. And then oh Elon Musk waited hours to and had Obama at SpaceX and then all of a sudden he can’t come to the White House for the EV summit, the category he created. Like it’s pretty obvious the Democratic Party had some real dysfunction in there in terms of building a bigger tent. And I can tell you, I have never felt more courted in my life than the Republican Party trying to get me to be part of the the Trump movement, which I demurred and declined, it wasn’t my style. Right. But they are trying to build the biggest tent possible. They’re like oh you agree with 14% of what we do? You’re in. Okay. Yeah, so walk me through what the top thing should be, yeah.","offset":1811,"duration":68},{"text":"Josh Shapiro: So let’s dissect that a little bit. First off, you attribute a number of things to Democrats that I didn’t say. So um you’re here interviewing me, so let’s focus on the things I say. Number two, they went and they courted you, and you demurred, but by the way, even had you not demurred, had you signed up, I don’t know that your life would be better off after a year and a half of Trump’s policies. What I am for here in Pennsylvania, the ultimate swing state, the toughest state to win in, an incredibly tough state to govern in, particularly with a divided legislature. I’m for investing in public education giving every child a God-given opportunity. I’m for safe communities and we’re building that here and we’re reducing crime in all of our communities. I’m for a pro-growth economy where we generate more energy, we generate more jobs, where we create more opportunities particularly in our rural communities and forgotten communities that have been too often left behind. And here’s the fourth thing I’m for, I am for freedom. And I’ll tell you what, this president represents a party that used to be known as the party of freedom, and now they have turned their backs on that. They want to tell my kids what books they’re allowed to read, they want to tell women what medicines they can take and what they can do with their bodies, they want to control the way I raise my child, they want to say, you know, every day that yeah you can vote but we’re going to set the rules and try and rig them in a way where you’re not going to be successful. They are not the party of freedom. And I think the Democratic Party has an opportunity to be the party of education, safety, economic opportunity and freedom. That’s what we’re doing here in Pennsylvania and that’s what I’m going to continue to put forth.","offset":1879,"duration":103},{"text":"Host: I think it’s a great platform. I would add to it housing. The thing I hear about from young people all the time is, you know, just I’ll never be able to afford a house, the American Dream’s a bit of a scam, and college is overpriced. So how do you think about housing and what is is that an issue in your state or?","offset":1982,"duration":18},{"text":"Josh Shapiro: Yeah, let’s talk about housing, let’s also talk about college because you raised both of them in your question.","offset":2000,"duration":5},{"text":"Host: The two hard I mean that has disinfected by the way just like two generations who are like you guys tricked us on housing, you told us we’d be able to get a home, and you won’t sell your home, boomers, and and you told us we could always make more than our college education cost, and that was a lie too.","offset":2005,"duration":14},{"text":"Josh Shapiro: Yeah. When I was talking about economic opportunity, it’s somewhat shorthand, if you will, for also being able to afford that community. Affording that community can be healthcare, it can be housing, right? But let’s talk about housing. Here in Pennsylvania, I’ve asked the legislature for a 1 billion dollar fund to be able to build more housing in Pennsylvania and repair existing housing. 50% of my housing was built prior to 1950. You can invest a few thousand bucks in a new boiler, a new roof, some new windows, actually keep people in their homes and not have to build new homes. We also have to eliminate or damn near eliminate the red tape that exists when it comes to building housing. We’ve got to be able to build this faster and so I put forth a regulatory reform plan to be able to build more housing. I think that is really, really crucial. And let’s talk about college for a minute. The first day I was Governor, the first executive order I signed was to do away with the college degree requirement to work for state government. We have 80,000 employees, damn near all now you do not have to have a college degree. Other than say the doctors and lawyers and people like that who require advanced degrees. Right. So now 60%, 6-0, 60% of all of our hires in state government don’t have a college degree. We followed up on that by tripling our funding for Vo-Tech and CTE in our high schools, you know dramatically increasing our funding for apprenticeship programs. 62% of my adult population here in Pennsylvania do not have a college degree. So we need to make sure we’re investing in them so that they have opportunity. You want to go learn to be a welder, you’re going to make six figures working at a shipyard in South Philadelphia. You want to go and you want to work on HVAC system, you’re going to work in some of our most complex life sciences construction jobs and you’re going to make six figures doing that. So for us, we fundamentally believe that you’ve got many pathways to opportunity here in Pennsylvania. For some, it’s going to college, great, and for others, if you choose not to go to college, that’s also great, we’re going to make sure that we pave the way for you and give you that opportunity.","offset":2019,"duration":132},{"text":"Host: Yeah, the generation tool belt movement is well upon us. People are starting to figure out going in debt 100 to 200k versus getting a plumber job, carpenter job, HVAC, whatever for six figures out of the gate is a much better opportunity.","offset":2151,"duration":15},{"text":"Josh Shapiro: Yeah, and to be clear, I’m not [ __ ] on people that go to college. I went to college, I presume you went to go to college. But for too long, by the way, politicians in both parties defined success exclusively around the idea of you having to have a college degree. And then set up arbitrary barriers to entry. Hey, if you don’t have a college degree, you can’t apply here. Or what about the skills that you developed in the military? What about the skills you developed at a trade school or the skills that you developed working in the private sector? Those skills should matter. And now they do in Pennsylvania, and we’re no longer taking an elitist approach that shuts people out just because they don’t have a college degree. We’re giving them the keys to opportunity and we’re giving them opportunities to pursue more success here in Pennsylvania.","offset":2166,"duration":46},{"text":"Host: Does the Socialist Democratic movement worry you, Mondame and the crew, and how do you think about that in terms of the party dynamics?","offset":2212,"duration":11},{"text":"Josh Shapiro: I mean, remember the question you asked me I don’t know three or four questions ago about you said well I only agree with 14% of what you agree with, you know come join the party. Look, my view is that we’ve got to have a big tent and my view is that we’ve got to have a real debate around different ideas and just because I might not agree with you on these three things, I might agree with you on something else. Listen, I’m sitting behind my desk here in the Governor’s office. This is where I negotiate bills and budgets and other things. If I threw everybody out of my office that I didn’t agree with 100% of the time, we’d never get anything done. When I sit down across a table from a Republican lawmaker, say what are the 10 things you want to accomplish? I tell him the 10 things I want to accomplish and you know what, we’re not going to agree on all 10, but if we agree on three or four, I’d rather focus on those three or four things where we can find common ground than the five, six, seven things where we’re just going to disagree. And so I think if you want to make progress, you’ve got to figure out how to create, you know, majorities whether it’s a majority in the legislature to get a bill to my desk, a majority come election time to win an election. You’ve got to find ways to bring people together and find common ground and not just focus exclusively on our differences.","offset":2223,"duration":70}],"startTime":1497},{"title":"Congressional Dysfunction and Executive Corruption","summary":"Shapiro criticizes Republican leadership in Congress for abandoning their constitutional duties to act as a check on the executive branch. He condemns the Trump administration's alleged corruption, self-dealing, and abuse of the presidential pardon power.","entries":[{"text":"Host: What’s your take on what’s going on in Congress, Senate, in terms of Trump and getting alignment there because hey, when you go to war or you do tariffs, um this was something we had a consultation between these different branches of our government. And we had other presidents on the Democrat side, etc., you know, say we’re going to just get rid of student loan, I’m doing an executive order. Curious your take on the balance of of our different branches of government and the lack of collaboration because this is particularly disturbing, we’re both Gen Xers, we grew up watching the Democrats and the Republicans argue, but then they all got together, had lunch, and they negotiated. Where is that esprit de corps of everybody rowing in the same direction for all Americans versus this toxic you know, we’re just going to block each other at every and do character assassination at every single turn? It’s it’s the most polarized of our lifetimes for sure.","offset":2293,"duration":56},{"text":"Josh Shapiro: I actually think the Congress of the United States, the leadership there, I mean they are frankly kind of sad, pathetic people. And let me explain why, right?","offset":2349,"duration":10},{"text":"Host: Please.","offset":2359,"duration":0},{"text":"Josh Shapiro: You put uh what’s his name, Johnson in as Speaker, and he’s effectively a rubber stamp for anything Donald Trump wants. And by the way, whether you agree with Trump or not, I think you can agree that you’d like your member of Congress to at least meet the burdens that they have on them in the Constitution of the United States, which is to be a check, which is to be a separate branch of government. And a branch of government that has meaningful responsibilities here. When the Congress of the United States walks away from their responsibilities, whether on tariffs or whether on declaring war, and ultimately just kind of empower the president, again, agree or disagree, I obviously have profound disagreements from the president on on those things, then what you’ve really done is you’ve limited the power of the Congress, and what you’ve really done is you’ve seen a whole bunch of people that put Donald Trump before the oath of office they take to the Constitution. And I think that’s just pathetic. And it’s weak. And I think our country’s suffering as a result of it. Look, I’m here in Pennsylvania, where where it all began 250 years ago. And the brilliance of our founders was that they left so much of the work to the next generation and the generation after that to pick up the baton and continue to perfect our union. Our founders though, always contemplated two things. One, that there would be honorable people in office. And two, that the people in office would exercise their power and be a check on one another. And in some cases, slow things down to make sure that bad things didn’t occur, bad things couldn’t get through the process. I think what Americans are confronting now is a realization that we don’t really have all honorable people in positions of authority in the federal government. And that that checks and balance system that was constructed here in Pennsylvania is not standing the test of time because you’ve got these profoundly and pathetically weak people like Johnson and others who just simply give away their power to folks who are corrupt and to folks who are not acting in an honorable way.","offset":2359,"duration":156},{"text":"Host: You keep bringing up that corruption, explain to me what corrupt things you know that the Trump administration has done.","offset":2515,"duration":3},{"text":"Josh Shapiro: I think to me there has been an extraordinary amount of self-dealing. There there has been a good bit of family members doing quite well in this in this environment. I think you’re seeing more and more people who have the president’s ear being able to lobby him at his swim club to get a pardon for someone that frankly doesn’t deserve a pardon. I mean I think the list goes on and on and on, but those are some examples that I think the American people see with their own eyes. Taking a a billion-dollar jet from the Qataris and thinking there’s nothing attached to that, right? I mean I think that there’s just a lot of that that moves so fast that the American people are having a hard time keeping up with it, but there will be a reckoning on this one day.","offset":2518,"duration":51},{"text":"Host: Yeah so on the pardons I’m strongly agreeing, feels like the pardon power is super abused. Is there a path to refine that tool? Because it relies on norms, right? And ever since Bill Clinton, you know, did some you know friends and then obviously Biden did his son and then Trump’s doing his you know folks. It feels like now this is just a get-out-of-jail card, you come into an administration and then everybody from Fauci to you know Hunter Biden, everybody else is just going to get a pardon on the way out. How would you reshape that tool?","offset":2569,"duration":37},{"text":"Josh Shapiro: Well let’s be clear, and I don’t think you’re suggesting this, but um and I was critical of Joe Biden when he pardoned his son, right? I was critical of him publicly. What we are seeing under Donald Trump, you have to admit, is next level when it comes to the abuse.","offset":2606,"duration":14},{"text":"Host: I mean it’s on the way it’s yes, it’s literally it’s in the first year, it’s not on the last day even, it’s like an ongoing tool here. We had CZ, who was a crypto person who got pardoned, and Trump didn’t even know who he was. He was just like oh I heard he’s a good guy.","offset":2620,"duration":13},{"text":"Josh Shapiro: Right. I mean I will tell you, I sit at this desk here and I sign pardons and clemencies. And I take that responsibility so seriously. And I agonize over these decisions. And and I pray that I get these decisions right. And I believe I have. And I’m transparent about why I viewed someone as worthy to get a clemency and also worthy of not getting one, or not earning one. And these are tough, tough decisions. Goes back to what I said a moment ago, our founders when they vested that kind of authority in an executive, didn’t necessarily do something wrong by giving the executive that power. But they were leaning on the assumption that the executive would be honorable. That the executive would would do this with morality and real scruples in mind. And and I think what we’re seeing with the President is if you sidle up to him at his swim club, you donate a certain amount of money maybe, or you have his ear for some other social reason, you can usually get him to do what you want him to do. And that’s simply an abuse of power, man. It’s wrong and and it’s something that the American people I think should take issue with.","offset":2633,"duration":67},{"text":"Host: ...give a pardon to someone who's important to you.","offset":2700,"duration":2},{"text":"Josh Shapiro: Yeah, the pardons are definitely super troubling.","offset":2702,"duration":3},{"text":"Host: How do you deal with the family members and the kids enriching themselves? Obviously nothing has been done by a court or an investigation into Trump's kids at this point, so we just want to be clear about that. You know, we had Hunter Biden getting a ridiculous million dollar board seat. I've never seen anybody get paid a million dollars to be on a board. That was obviously corrupt in some way, or somebody trying to curry favor. Doesn't mean that President Biden was, but definitely was corruption there.","offset":2705,"duration":36},{"text":"Host: How do you deal with kids of - and this has been going on for a while - these kinds of allegations. If we can't rely on honor and norms, is there another proposal here that the kids of people in office can't make money? Your kids can't make money if I was running for office? My kids couldn't make money in the free market. How do you - is there any kind of solution you can think of?","offset":2741,"duration":19},{"text":"Josh Shapiro: I think it is important, you cited Hunter Biden. They went through a legal process. There was an investigation by the Department of Justice. I think there has to be a real look - I say this as a former prosecutor - a real look at some of this stuff and follow the evidence, follow the law. And if charges are warranted, bring them, and by the way, if charges are not warranted, don't bring them. Do not use the rule of law as a tool to go against political opponents in any way.","offset":2760,"duration":31},{"text":"Josh Shapiro: But I think what you've got to have here are people who are operating with real morality. And you do have to figure out a way to operate within the norms again. I'm unwilling to accept that that is gone. It may be temporarily suspended under Donald Trump, but I'm hopeful that we can find our way back to that. Let me be clear about something else here, that finding our way back to that is a bipartisan exercise.","offset":2791,"duration":25},{"text":"Josh Shapiro: It's going to require Republicans and Democrats and independents all demanding when they go to the ballot box that we want to elevate people who are ethical, people who are honest, people who are focused on doing their jobs with integrity. And then when those people are in office, rewarded with the votes of the public and in these positions of public trust, to hold them accountable as well.","offset":2816,"duration":22},{"text":"Host: And you believe that can happen in a post-Trump world?","offset":2838,"duration":3},{"text":"Josh Shapiro: I do. I do.","offset":2841,"duration":1}],"startTime":2293},{"title":"Condemning Anti-Semitism Without Nuance","summary":"The host brings up the recent firebombing of Shapiro's home and rising anti-Semitism. Shapiro asserts that anti-Semitism must be universally condemned without nuance, regardless of whether it originates on the political left or right.","entries":[{"text":"Host: I strongly agree. Hey, it's a year since your home was firebombed by an insane person who was anti-Semitic. Your faith comes up over and over again. I personally think people are a little obsessed with it, but here we are. And the Democratic Party has been split apart as well over this support of Israel issue. You have a very nuanced position. Number one, how are you dealing with that personally, the anti-Semitism, which to me as somebody who grew up in Brooklyn with lots of Jewish friends and all kinds of different people, just insane to think that Jewish students are being - or any particular group of students - being chased by the other students at Columbia University because they're Jewish? This chaoticness is just heartbreaking. But as a Jewish person and literally experiencing it first-hand, I mean, how are you doing with that?","offset":2842,"duration":48},{"text":"Josh Shapiro: Yeah, I appreciate that. Look, we should separate this and have two conversations: one about Israel and one about anti-Semitism, because you kind of blurred both in the question. Let's focus first on anti-Semitism. I have been very outspoken about those who are engaging in anti-Semitism, peddling words that are anti-Semitic. And importantly, I've been critical of people on the political left and on the political right.","offset":2890,"duration":28},{"text":"Josh Shapiro: And I think anti-Semitism is a problem in our society and it's a problem on the left and it is a problem on the right. And I think it is important that we call it out. We call it out whether we're in an interview - not accusing you by any stretch - conversation, yeah. Call it out on social media, and then we just call it out in our communities and our daily lives where we see it. On that, there should be no nuance.","offset":2918,"duration":22},{"text":"Josh Shapiro: We should be able to come together, people who are Jewish, people who are Christian, Muslim, and all agree that hatred, bigotry in any form directed at a Jew, a Muslim, a Christian, anyone, it has no place. And by the way, it makes us all less safe. And so we have to focus on speaking out against that. No nuance on that.","offset":2940,"duration":22},{"text":"Host: Yeah, Trump.","offset":2962,"duration":2},{"text":"Josh Shapiro: On the issue of Israel and the Middle East and the war in Iran and Gaza, there's a lot of nuance there. I'm happy to answer your questions on that, but I think on the issue of anti-Semitism, we have got to be in a place where we universally condemn it.","offset":2964,"duration":7},{"text":"Josh Shapiro: And I think what you're seeing from some folks on the right and some folks on the left is they'll only call it out if it's said by a political opponent or someone they disagree with. And I frankly respect people on the right, like Ted Cruz, who have called it out within the Republican party. I've tried to call it out when it rears its ugly head in my party. It is important that it be universally condemned.","offset":2971,"duration":26}],"startTime":2842},{"title":"U.S. Policy on Israel and the War in Iran","summary":"Shapiro criticizes Israeli Prime Minister Benjamin Netanyahu while separating legitimate policy critiques from anti-Semitism. He also condemns Donald Trump for leading the U.S. into a war with Iran, describing it as a war of choice with no defined mission.","entries":[{"text":"Host: So easy to do. Let's tackle the issue of Israel and I would say, yeah, every Jewish person, Jewish American person who I know, when I ask them about this issue, obviously incredible tragedy October 7th, going and collecting the hostages seems like a reasonable thing to do. I was there for 9/11, you know, it seems like a pretty analogous situation. This has to be settled and the United States went and did what it had to do in Afghanistan and took out Iraq for extra measure, that's a whole other diversion.","offset":2997,"duration":32},{"text":"Host: But 100% of folks say they don't agree with Netanyahu's approach to what happened in Gaza. And then folks feel a decent number of people, whether it's reality or not, that America's getting dragged into this war with Iran not under false pretenses and because Israel is pushing us to do it. So let's take these two issues separately and I'm just curious in understanding your position on this. Are you part of the Jewish American diaspora that believes hey, Israel has a right to defend itself, but maybe Gaza went too far?","offset":3029,"duration":34},{"text":"Josh Shapiro: Okay. Well, first off, let me say this: I don't view this issue as a Jewish American, as you said. I view this issue as an American. And I view this issue in a way of trying to understand what is the best thing for America, which to me is having peace and stability in the Middle East. Okay? That's how I approach these issues.","offset":3063,"duration":28},{"text":"Josh Shapiro: It is - and I've been clear and consistent about this long before October 7th - that I think Netanyahu, the leader of Israel, is someone who's been leading Israel down a dangerous and isolated path. I think he has made Israel more isolated in the world community. He has fractured really what used to be a nonpartisan or bipartisan American support for Israel. And I think he has put Israel in a very dangerous place.","offset":3091,"duration":30},{"text":"Josh Shapiro: And of course, he was the leader of Israel who wasn't minding the shop when October 7th happened. So I've been very critical of Netanyahu for years and years and years. I've also for years made very clear that I think America's interest in the region should be for stability and peace. And that it would be my hope that you would have two states living peacefully side by side, Israel and a Palestinian state.","offset":3121,"duration":30},{"text":"Josh Shapiro: Now, I realize that is a long way off given where we are right now. But it is clear that we need to work toward that. And obviously that Palestinian state cannot be led by Hamas, which is a terrorist organization, and there has to be some structure that is put in place in order - in order to create that.","offset":3151,"duration":19},{"text":"Josh Shapiro: As it relates to the war, which you also asked about in - in your question, I mean, this was a war of choice. The president never defined the objectives. It is clear he doesn't know how the hell to get out of this. We'll see what he ultimately does with his big threats, you know, we're recording this on the eve of his - of his big threat...","offset":3170,"duration":18},{"text":"Host: Ultimatum.","offset":3188,"duration":2},{"text":"Josh Shapiro: ...using language, using language that was so [expletive] offensive, you'll excuse my language, that diminished the value of human life. We'll see what he ultimately does. Does he chicken out as he usually does, or does - God forbid - he - he go through with that? But this was a war of choice. He didn't know why he got into it. He doesn't know how...","offset":3190,"duration":23},{"text":"Host: Why did he get into it? Handicap it. Why did he do it?","offset":3213,"duration":2},{"text":"Josh Shapiro: America's national security interests have not been well-served by this. And economically, you've talked about this, economically we are worse off because of this war. I'm sorry, I didn't mean to speak over you.","offset":3215,"duration":10},{"text":"Host: No, no. No, I mean, listen, I appreciate your candidness, Governor. Why did he do it? If you had to handicap it, or what are you hearing when you talk - because you have obviously a lot more information than the average American. Why now? Why did we do this?","offset":3225,"duration":17},{"text":"Host: Now, we had done, you know, the strategic trimming of the hedges, mowing of the lawn, whatever the term is, to get rid of the nuclear progress. That containment seemed like a perfect strategy and then all of a sudden we decide we're going to do regime change. This is after Trump promised that he would never get an - do an intervention like this in the Middle East. This is after we were told by the Republicans, do not vote for a crazy Democrat who will take us to war with Iran. And here we are in month 14, 13 of the Trump presidency and he started a war.","offset":3242,"duration":35},{"text":"Host: His own biggest advocates, from Megyn Kelly to Tucker Carlson and, you know, people on the fringe, Alex Jones and everybody in the middle, the comedians who supported him, the podcast diaspora or the podcast bros, they're all fleeing the ship. They did not want this. So here we are. Why did he do it? Why now? What is your handicapping of it?","offset":3277,"duration":18},{"text":"Josh Shapiro: Well, I'll answer that. I will just say it's yet another broken promise to the people who put him in power. He screwed over the farmers who put him in power. He told people he wouldn't slash Medicaid, he cut Medicaid. He told people he'd bring down prices, prices have skyrocketed because of his tariffs. He - he's got this long string of broken promises. Now, why did he break this particular promise? You know, let's - let's examine the record.","offset":3295,"duration":28},{"text":"Josh Shapiro: First, Rubio went out and said he did it because if we didn't move then Netanyahu was going to move and was going to force our hand. Then they walked it back. He said seven or eight months ago that they destroyed their nuclear capabilities. And then came back seven or eight months later and said we had to go in because we had to destroy their nuclear capabilities. I don't know.","offset":3323,"duration":22},{"text":"Josh Shapiro: Then they said it was about regime change. Well, great. I mean, we went from like an 80-something year old Ayatollah to a 60-something year old Ayatollah who by all accounts seems to be far more hardline. I'd hardly call that successful regime change. So to me, it is hard to - and I think you've seen I've been trying to be very forthright in answering your questions. You're doing great.","offset":3345,"duration":23},{"text":"Josh Shapiro: I don't know how you answer that question because the President never answered that question. He never sat in the Oval Office and looked the American people in the eye and said, this is why we're going in. And you know what? This isn't semantics. This isn't politics. If you don't know why you're going in, you don't know how the hell to get out. You don't know how to instruct the military, our brave military, including those 13 souls who did not make it home to their families because they went on a mission that the President never defined.","offset":3368,"duration":28},{"text":"Josh Shapiro: And we mourn their loss, we thank our military heroes for what they did, and we thank our military who are out working every day on behalf of our freedom and our safety and our security, but they deserve a Commander-in-Chief who would have defined the mission. And if you define the mission, you know how to get out, and he never defined the mission. I don't know ultimately if he will follow through on his threat again. It's, you know, it's Tuesday afternoon, you and I are talking. We'll see ultimately what he does here, but to me, this has been a failed and compromised mission from the beginning because he never made clear why he was going in.","offset":3396,"duration":39},{"text":"Host: Yeah, and I know you got to go in a moment. It does seem to me that first explanation, sometimes people, you hear their first reaction and their first statement is the true statement, just in general. And it does seem like Israel was going to do this and we joined them and we didn't need to.","offset":3435,"duration":16},{"text":"Josh Shapiro: No, America should never - pardon me, America should never be led around by any other nation. It should always be about America's interest, our national security interest, the interest of expanding freedom and opportunity for the American people. We should never, ever be bullied as maybe President Trump was by any other world leader.","offset":3451,"duration":20},{"text":"Host: Back to the anti-Semitism we're experiencing now. You said hey, let's address them separately. But I don't think you can separate them if we're getting pulled into this war by another nation and people believe, like you and I do, hey, Netanyahu maybe went a little too far here. That is what's causing the anti-Semitism in this country, don't you think? This relationship with Israel, the state of Israel and Netanyahu, our undying support for Netanyahu, that's not causing the anti-Semitism here? That's what these young people seem to be saying is, we don't want to vote for somebody who supports Netanyahu.","offset":3471,"duration":37},{"text":"Josh Shapiro: Well, I think you've got to be real careful on that. You, the collective, not you individually. I mean, if you're suggesting say that Jews are Israel and reflect Israeli policies and support everything Israel does, I mean, that's one of the oldest anti-Semitic tropes out there, this sort of notion of dual loyalty. I think it is fair to vote on the issue of do we support what Donald Trump is doing relative to Netanyahu.","offset":3508,"duration":34},{"text":"Josh Shapiro: That's fair. But to suggest that somehow it's, you know, because Jews are tied to Israel and that's why we're doing what we're doing...","offset":3542,"duration":7},{"text":"Host: Well, you and I can parse this issue I think very easily. But young people at Columbia or Harvard, where all this is going on and these, you know, pro-Palestine protests are going on, they don't seem to be able to make that parse. That seems to be one of the roots of the problems here, is that people do put together - these young people, they could be stupid, they could be misinformed - but they do put together what the state of Israel is doing and they equate it with Judaism.","offset":3549,"duration":22},{"text":"Josh Shapiro: And that's why I've tried - and that's why I've tried to be so outspoken on this in making clear that on anti-Semitism there should be no nuance. And that's a conversation where we should all be able to unite. And that we have to protect a place for nuance when it comes to Mideast policy, when it comes to Israel, when it comes to Iran and - and anything happening in the Middle East. And we need to give space for those who want to peacefully - and I want to stress peacefully - protest.","offset":3571,"duration":28},{"text":"Josh Shapiro: We want to give space to those who differ from the administration and frankly, those who support the administration to be able to go out and to protest peacefully. And that is I think an - an important part of the fabric of our American society. I just think it's important - and I try and do this work every day as Governor - to keep those conversations separate. Because when they get blended, that's where I think it gets dangerous and that's where - uh, I - I think it - it really crosses a line into something we don't want to see in our society.","offset":3599,"duration":28},{"text":"Host: And you could be super critical of Israel and you could love your Jewish neighbors and friends. These are - this is a very simple concept here.","offset":3627,"duration":8},{"text":"Josh Shapiro: Absolutely. And I think that reflects where I am on many things. I've been super critical of the Israeli government, the Netanyahu government. Um, and - and I'm someone who loves Israel, someone who has spent time in Israel. I wrote a whole book about - uh, I proposed to my wife there and how I think the - the idea of it is - is important. We've got to figure out ways to keep those two conversations - not separate, but - but blurring the lines in a way that creates some dangers I think is something we have to guard against.","offset":3635,"duration":34}],"startTime":2997},{"title":"Conclusion and Final Banter","summary":"The host thanks Governor Shapiro for the interview. They conclude the discussion with a friendly exchange about the upcoming NBA playoffs.","entries":[{"text":"Host: Yeah, lots of education, lots of opportunities. Josh Shapiro, thank you so much for coming on \"All In\" and we look forward to having you on again and good luck with your race. Good luck with your 76ers. I will see you in the second round, it looks like.","offset":3669,"duration":13},{"text":"Josh Shapiro: Next year - next time I'm on, I'll be wearing a Sixers hoodie. So go Knicks!","offset":3682,"duration":6},{"text":"Host: There you go. I'll see you courtside, my friend. You go to the games.","offset":3688,"duration":3},{"text":"Host: I'm going all in!","offset":3691,"duration":15}],"startTime":3669}],"entries":[{"text":"Host: Alright everybody, we’ve got an incredible guest today. Governor Josh Shapiro is here, obviously Governor of Pennsylvania. He’s got record-setting popularity in Pennsylvania right now, 60% approval at least. He’s a moderate, he’s focused on getting [ __ ] done, GSD. He’s tough on crime, ranked number one according to my notes on charging Medicaid fraud. He’s pro-data center, he’s got a nuanced take on Israel, and he’s a baller, apparently. Cuts to the tape.","offset":0,"duration":29},{"text":"Host: Got him! There it is.","offset":29,"duration":3},{"text":"Host: Oh my god.","offset":32,"duration":1},{"text":"Host: There’s your Governor.","offset":33,"duration":1},{"text":"Host: Look at those short shorts. Holy [ __ ]. Incredible, wow. It’s the late 80s?","offset":34,"duration":9},{"text":"Host: And based on the VHS tape, this looks like the 80s.","offset":43,"duration":3},{"text":"Host: Yeah, that was 1990, I think.","offset":46,"duration":4},{"text":"Host: Look at that, playing the point.","offset":50,"duration":2},{"text":"Host: There you go. Very nice, very nice.","offset":52,"duration":8},{"text":"Host: All right, enough of that. That was back when, that was back when people shot mid-range jumpers. They don’t do that anymore, man. They don’t do that.","offset":60,"duration":3},{"text":"Josh Shapiro: They should. All threes, yeah. I mean, we have a couple of players and we were talking before the show started, you’re obviously a big Philly fan and I’m a big Knicks fan, so I will see you at the games. We’re on a collision course.","offset":63,"duration":11},{"text":"Josh Shapiro: I, by the way, with all due respect and I hope we have a good conversation here, I hope to never see you at the games. Because if you’re showing up in Philly with all your Knicks crap on, I’m not going to be a happy guy.","offset":74,"duration":7},{"text":"Host: Oh, look at the selfie courtside with my friend Dave, who is one of the co-owners of the team who is our mutual friend of ours, who I think egged you on a little bit to come on the program here, which I appreciate.","offset":81,"duration":10},{"text":"Josh Shapiro: He did. He said go on All-In, they have thoughtful conversations and anxious to have one with you. So thanks for having me.","offset":91,"duration":6},{"text":"Host: Yeah, there’s so much for us to talk about but I thought I would start with your track record in Pennsylvania. And the reason I wanted to start there is because there’s a bit of a collision course happening right now between you and Gavin. Gavin’s got what I would describe as a variable tenure here in California. I left California for Texas because I just thought it was a bit of a disaster. But you’re doing great in your state and that’s in the face of New York, my hometown, New Jersey, Boston, like losing a lot of business leaders. And you’ve been scoring, you know, some big wins. So when you look at your track record, maybe you could just educate the audience on what you’ve gotten done and maybe in comparison to what’s happening in those other states with other Democratic leaders, because you seem to be maybe the exception to this rule that Democrats aren’t getting it done on a business level.","offset":97,"duration":52},{"text":"Josh Shapiro: Look, I’m proud of what we’ve done. I’m not in comparison with Gavin or any other Democratic governor. I’ll just talk about what we’ve done here in Pennsylvania. We are a pro-growth state. We want businesses to come here and grow. I’m proud of the fact that we’ve created more jobs than all but two states in the entire country. We’ve cut taxes seven different times to be more competitive. Cut taxes for small businesses, also for families trying to afford childcare, for seniors, for working Pennsylvanians. We’ve taken our permitting process, that’s the usually the the ticket you need say to build your building, right, if you’re trying to build something here in Pennsylvania, we were bottom five in the country. I think we’re now a national model, easily top five in terms of speed. We’ve got a money-back guarantee on all of our permits. If we don’t get you your permit in time, we’ll give your money back. And fun fact, we’ve issued 40 million permits during my time as governor, we’ve only had to issue five refunds, meaning only five of those permits were late. We are now the only growing economy in the northeastern part of the United States. At the same time, we’re investing in workforce development, especially if you don’t have a college degree, tripling funding for Vo-Tech and apprenticeship programs and understanding the need to take the workforce we have today and prepare them for jobs here in the Commonwealth of Pennsylvania. Proud that we’ve got an unemployment rate below the national rate consistently over the last 32 months. I think it is really critical that every kid born in Pennsylvania gets a great quality education, that that kid has a safe street to walk down to get to school or wherever else they’re going, and that they’ve got a job in the community that they love. Those to me are the core foundational principles. It’s what we focus on every single day. Our mantra, as you said at the top, is GSD, get [ __ ] done. Those are the areas where we focus on getting [ __ ] done and I think we’re putting a lot of points on the board every single day that’s having a meaningful difference in people’s lives.","offset":149,"duration":126},{"text":"Host: How are you getting that done? Let’s just take the permitting as an example. Why is it so dysfunctional in California? You know, obviously I’m an investor in technology companies and we just saw red tape after red tape, then on housing, it’s incredibly hard to build anything. The NIMBYism, you know, if you cast a shadow, nothing can be built and then housing prices keep going up. And you know, if you want to hire a nanny or a teacher or you know, if a firefighter moves in, they can’t even afford a home in the community that they’re servicing. So how did you fix this and why can’t other states not fix it?","offset":275,"duration":38},{"text":"Josh Shapiro: I mean, look, I can’t speak to how it’s done in California. I’ll just tell you in Pennsylvania, the way we start the conversation is by recognizing permits are critically important to economic development and to creating jobs, right? If we the government can move at the speed of business, if I can give you as a CEO predictability to know your business is going to be open in six months instead of three years, right, because the permit took too long, then you’re going to want to invest here. So we sort of start with the important idea that permits matter. Second, when you come into our state government to get your permit, let’s just use building a building as an example, right, we want to get to yes. We still want to protect the environment and public health and public safety, and we do that, but we want to get to yes. So our attitude has shifted. Third, we’ve got to have that money-back guarantee, because that money-back guarantee holds the bureaucracy accountable. Now, I will tell you that some of this we’ve done administratively, meaning I’ve signed executive orders and we’ve made those changes. But other things, we’ve worked with the legislature to pass new laws to speed up our permitting. And it hasn’t always been easy. Understand I’m a Democrat as governor, I’ve got a divided legislature. I was the only governor for a while with a divided legislature, now there’s one other. I’ve got a Senate led by Republicans by just two seats and a House led by Democrats by just one seat. But this is an area where I’ve been able to bring Democrats and Republicans together in order to make progress in terms of passing this this permitting reform. And again, proof is in the pudding. What we are seeing is that businesses are coming here and the economy’s growing. Let me give you one more example. This may seem really small to you, but it’s a big deal, okay? When I talk about a permit, if you want to be a barber in Pennsylvania, you need a permit, or technically it’s called a license, but I put it all under my...","offset":313,"duration":101},{"text":"Host: Yeah, some kind of certificate, yeah.","offset":414,"duration":1},{"text":"Josh Shapiro: Right. The day I took office, it took 20 days for a barber to get their permit to be able to go out and cut hair. Today you get it same day, you get it within that day. That may seem silly to you, but but understand, I called my barber. I asked him, I said, how many heads do you cut a day? He said about 10 a day. At 20 bucks a pop, 200 bucks a day for for 20 days, that’s real money. That’s thousands of dollars that we’re putting into that barber’s pocket just because we got them their permit more quickly. So I know it may sound nerdy, it may sound wonky, but whether you’re building some big building that’s going to house hundreds of workers or thousands of people who are living there, or whether you’re the local barber that everybody needs to go to to get to get their haircut, this stuff matters. And the quicker you are, the more jobs you create and the more money you put in people’s pockets.","offset":415,"duration":58},{"text":"Host: It also matters I think on a philosophical basis of who is the government working for? Themselves and their timelines, or for the people who put them in office? And I think that’s the philosophy, just watching it happen in New York and California, it’s the opposite of what you described. There’s no sense of urgency and there’s almost a situation where people believe it’s intractable, that they can’t change it. And so that’s I think such an important point is that you actually made it happen.","offset":473,"duration":31},{"text":"Josh Shapiro: I think that’s a great point. I want to focus on what you just said there. First off, I start the conversation believing that government can be a force for good in people’s lives. Second, that we’ve got to figure out a way to get to yes. Whether it’s building a building or whether it’s getting that mom the support she needs for her kid with autism who needs support. We’ve got to figure out a way to get to yes and get them that help. And then you mentioned in your question the way people get, I don’t recall if you used the word frustrated or or they feel, you know, that government’s sort of holding them back, right?","offset":504,"duration":34},{"text":"Host: It’s oppressive in a way, right? Just if you have that experience three or four times, whether it’s at the airport or getting your driver’s license or getting the haircutting, you know, certificate, like it’s just oppressive over time, you just feel like the government’s working against you.","offset":538,"duration":14},{"text":"Josh Shapiro: Yeah, and what does that, what does that person feel after they try and get their permit, they can’t get it, they try and open up their small business, it won’t work? They get frustrated. By the way, they get pissed. And then not only are they pissed at that agency or that governor, or they’re pissed at that state government, they also grow, and this is an important point, a little more cynical about government and a little more frustrated about the process. And when that happens, I think that that creates more distrust in our system and it creates more opportunity for, I think frankly dark voices on extremes to come in and take advantage of people. I I find that, you know, if we get it done the right way, if we process things quicker, if we get people to yes, then maybe a byproduct of that is a little bit less cynicism in our system.","offset":552,"duration":52},{"text":"Host: Yeah, and the horseshoe theory that you’re kind of referencing there, these two extremes just taking over the conversation, that’s not what the majority of the country wants. They they want to just live in a high-functioning society. I was curious how you look at fraud, waste fraud and abuse. My friend Elon, to drop a name, you know, did this doge thing, was a little controversial, but I think what we’ve seen is hey, 20-30% of every tax dollar collected is wasted. Some of it’s fraud, some of it’s just incompetence, it could be anything on that spectrum. And this seems to be the Republican party’s rallying cry to beat the Democrats, going into California and prosecuting people, Michigan, etc. You have seemed to have gotten ahead of this, you’ve been doing this for years. So maybe you could explain your take on fighting fraud specifically, healthcare or in other areas.","offset":604,"duration":53},{"text":"Josh Shapiro: Look, I think we’ve got to focus on rooting fraud out of the system. Now, you and I may differ on hey, should we spend a dollar on that initiative or not? And by the way, those are super healthy differences and we should argue that out, we should debate that. But where we should have no difference is if someone’s stealing that dollar instead of going to its intended purpose, we should be against that. And and I am. Prior to serving as governor and having the privilege of sitting here in this office serving the good people of Pennsylvania, I was the state’s Attorney General. And you’ll remember back during COVID, there were those PPP loans to help our small businesses and other businesses stay afloat. We’d probably agree like, good idea, right? We’ve got to keep businesses afloat. But during that time, I went out and prosecuted a whole bunch of people for stealing that PPP money, for not using it for its intended purposes. Here as governor, I’ve maintained a similar focus through my office of Inspector General rooting out fraud, through making sure, by the way, we’re not fronting you money when you’re going out and providing say human services, you have to submit for reimbursements and you’ve got to make sure you prove that you did that work. When we find that someone took advantage of the system, we’re referring them to prosecutors. I’m proud of the fact that we’ve had more Medicaid fraud prosecutions in Pennsylvania than I think any other state, maybe there was one other. We’re we’re certainly toward the top of that list. Proud of the fact that we’ve identified that, we’ve sent it to prosecutors and we’ve addressed it. If we can address it administratively, we do. If not, we understand that those things need to be prosecuted. We should have a zero-tolerance policy for that and we should make sure that if we’re going to utilize a hard-earned dollar of a taxpayer for a purpose like providing someone with healthcare, that we’ve got to make sure that that dollar makes its way to that person so they get their healthcare. And, you know, our folks are working really hard on that in Pennsylvania.","offset":657,"duration":114},{"text":"Host: So pro-business, less regulation, lowering taxes, eliminating fraud, and all of this is just getting done in the state. And then, you know, the next piece that in at least my community, people who are creators of businesses, venture capitalists, angel investors, founders, we pay our taxes, pay a lot of taxes depending on which state you live in. And then there’s this movement...","offset":771,"duration":26},{"text":"Josh Shapiro: You should be paying more taxes in Pennsylvania, man, stop paying them elsewhere.","offset":797,"duration":2},{"text":"Host: Yeah, well, the and you know, we then get struck with this California law and a lot of my friends have moved to Austin where I live now, they just said suddenly hey, we want to seize 5% of whatever you got. You already paid your taxes, you haven’t paid capital gains on some of this equity you own in your company, maybe it’s paper wealth, maybe your company went public now and you could sell some of it, but you might crater the stock if you do. And Elizabeth Warren, Bernie Sanders, and California all trying to seize assets on gains they’ve never received. It’s a, it seems to be getting momentum.","offset":799,"duration":60},{"text":"Josh Shapiro: I mean, I would just tell you, we’ve cut taxes seven times in Pennsylvania. We’ve got one of the lowest income taxes in the entire country, that’s why I’m joking with you, you should come to Pennsylvania and relocate here. And and look, I mean, that kind of tax that you’re describing is not something we have here, it’s certainly not something on on my agenda. I do think people need to pay their fair share. I think you’d agree with that. We need to make sure that we are easing the burden on those who are working and who are at the lowest, you know, sort of economic point on the scale. And we’ve got to make sure that folks at the top are paying their their fair share in order to to sustain our society. And I think we’ve struck a really good balance here in Pennsylvania. And I think our growth numbers bear that out. I think seeing more people coming to this state bears that out. And I think there’s an important stat, one of the things you you cited in those entrepreneurs as you were going through your question is, you know, these are people who kind of started with a dream, with an idea that, you know, someone might have looked at and said, jeez, I I don’t know about that, but they stuck with it and and they built up their companies. We see here in Pennsylvania, particularly when it comes to life sciences, right, we’re seeing people plant a flag here in Pennsylvania, start with an idea that others might think, boy, I I don’t know about that, but then because of our tax environment in Pennsylvania, because of our pro-growth approach in Pennsylvania, we’re seeing more of those small businesses, more of those small companies, especially in life sciences, survive that sort of valley where a lot of those companies go out of business and sustain themselves here because again, I think we’re showing that we’re pro-growth, we’ve got a smart tax environment for them, and by the way, after we invest in them, after we give them a shot, and after they do well, we expect them to pay their fair share back to the Commonwealth of Pennsylvania. And I think that’s that’s the approach we’ve taken and it’s working.","offset":859,"duration":118},{"text":"Host: Yeah, and so if you’re not in favor of a wealth tax, what would you do to deal with maybe this disparity in wealth that we’re seeing? There was just some statistics that came out the other day, I’m sure you saw them, the upper-middle class has just been surging, middle class going down a bit, and people in the lower rungs going down as well. So people may feel like they’re not making enough money, but in reality what’s happening is people feel other people have made a tremendous amount of money, which is true because of equity holdings are growing much better than salaries ever will and only 40% of only 50% of the country really participates in a meaningful way in equities, the other 40-50% don’t have any exposure to that. So how would you deal with somebody making, you know, 100 billion dollars, 500 billion dollars, a trillion dollars and never selling their equity or maybe not selling it for 20 years? How do you think about that?","offset":977,"duration":58},{"text":"Josh Shapiro: Let let me make three points, a Pennsylvania point and a couple broader points. One, you cannot have a national economy that works if it’s only working for the 1%. And you pointed out in your question the wage disparity and the disparity of income. You have to make sure that there is opportunity for those at all different income levels. And look, as we sit here today, if you’re making a million dollars versus fifty thousand dollars, if you make a million dollars you’re going to be able to buy some stuff that someone at fifty thousand dollars can’t buy, right? We sort of understand that, but you’ve got to have opportunity and you’ve got to have a level playing field, and you’ve got to have a fair shot, and you’ve got to have a tax system that works in a fair way. So that’s sort of point one. Point two is here in Pennsylvania, we’ve tried to address some of that economic disparity by passing the first-ever Working Pennsylvanians Tax Credit, sort of a state-side earned income tax credit. So what we’re saying is if you’re working, if you’re going out and busting your hump, we’re going to put some money back in your pocket. About 940,000, almost a million Pennsylvanians are going to qualify for a little over 800 bucks back in their pockets. So that’s going to help not only today with rising costs due to a lot of these federal policies, but it’s going to put money back in people’s pockets, allow them to make, you know, the the the investments they need to make in their everyday lives. Here’s the third point. What I would not do, because you asked what I would do, what I would not do is what President Trump did at the federal level with an aid and assist from a whole bunch of sycophants in Congress by passing that budget bill, the beautiful budget bill, whatever the hell they called it. In effect, what they did was they gave a tax cut for those who simply do not need it, right? And by the way, in the palace of truth and justice, you talk to those folks, they know that they didn’t need that tax cut. And what happened as a result of that is I’ve got 500,000 Pennsylvanians who are going to lose their healthcare. I’ve got 120,000 who have already lost their healthcare, about another 320,000 or so are likely to lose Medicaid next year. I’ve got 26 rural hospitals that are likely to shutter because these are rural hospitals that are working at an operating deficit and they’re relying so much on Medicaid, which has been slashed by the federal government. So the idea that Donald Trump thought it was smart economic policy to give a tax cut to those who don’t need it and pay for it with those who are struggling where and and create even greater economic disparities, that is going to hold back our entire economy. Just take those 500,000 people who aren’t going to have healthcare. You’re paying for that, and I’m paying for that, with our private insurance premiums. So what Donald Trump has done is shifted that burden onto those who are struggling, making it harder for them, adding additional costs to the middle class, and I think that that is that lacks frankly it’s just dumb economic policy and I think it’s going to set us back.","offset":1035,"duration":181},{"text":"Host: So here we are, politics is on the table. Incredible track record you have, but let’s dive into the Democratic Party. I’m an independent, but grew up Irish Catholic in Brooklyn, so grew up a Democrat. Probably have voted, you know, 60-40 Democrat to Republican, but always for a moderate, somebody who can get stuff done, that’s why I find you quite appealing. But let’s talk about the Democratic Party and the shellacking they got in the last election and specifically what really troubled me, Biden didn’t look like he was all there and I think we’ve all come to some consensus that he probably should have dropped out early. But what was really disheartening to me was that they didn’t do the speed run primary, they didn’t do, you know, a capsule primary over that July-August period and gave you a shot and other people a shot, Pritzker, Buttigieg, whoever, to to compete for the nomination. Was that a huge mistake for the Democratic Party and and when you look back on it, do you think that might have cost you all the election?","offset":1216,"duration":62},{"text":"Josh Shapiro: Well, look, I mean I actually wrote about this in in the book I recently published where, you know, it it became clear to me that, you know, Joe Biden seeking another term was probably not in the best interest of the party or the country and I spoke to him directly about that and bluntly about that. Once he made the decision to drop back with a hundred and whatever days to go, you know, there there were not many opportunities I think to have the kind of primary process that you’re talking about. I think it is important to look forward, right, and not look backward and you said in the last election Democrats took a shellacking. Actually, if you look at 2025, it was the opposite. I mean the President’s party, the Republican Party, got beat in New Jersey, got beat in Virginia, got beat here in Pennsylvania where we won three state supreme court seats. So obviously there’s a pendulum in in American politics and it’s clearly swinging back and forth. I think what’s important is that we look forward and I think it’s also really important for our party to have for my party to have a real debate and to have a real discussion about ideas. What are we for? And what are we willing to fight for? And I realize that process may at times look a little messy, I realize and I mean this with the utmost respect, it gives folks like you on a podcast or on a show the ability to sort of pick apart, maybe try and, you know, sort of parse words or point one Democrat at another and try and create conflict. But I would just say that overall, having this debate and having these issues be raised and having disagreements, that’s healthy for our party and ultimately I think our party’s poised to take back power and that will make us better at governing. To me, the whole purpose of running in an election is getting the chance to govern, not just winning the election. And so having these debates right now puts us in a better position when we win those elections and I’m running for reelection right now in Pennsylvania, going to work my ass off to win another term and earn the support of the people of Pennsylvania again and I want to continue to deliver, continue to, you know, focus on these issues that matter most and having that debate I think is really healthy.","offset":1278,"duration":123},{"text":"Host: I understand looking forward is most important, but I got I gotta go one more time in the rearview mirror here, which is Kamala Harris was picked because Biden had put out a criteria hey, I want to have a woman of color as my Vice President, he was very explicit about that. She could be quite qualified, unqualified, you know, moderately qualified, but then when she went out to pick her VP, everybody was saying hey, Josh Shapiro should be really in that running and she didn’t pick you specifically because she didn’t think she could win with a Jewish Vice President.","offset":1401,"duration":30},{"text":"Josh Shapiro: Yeah, I I don’t, respectfully, I gotta push back on that. And again, I’ve been very, very open about this.","offset":1431,"duration":6},{"text":"Host: Okay, push back on it, yeah, let’s go.","offset":1437,"duration":1},{"text":"Josh Shapiro: Yeah, and respectfully, I’m not looking to be argumentative with you, but I was very, very detailed and very specific in my book about this process and I was very grateful to the Vice President for being considered and grateful to her for the candid dialogue we had and about 48 hours before she picked Tim Walz, I pulled out and made clear that that was not something I was interested in doing. I thought I could serve the good people of Pennsylvania and do my best serving here as Governor in a job that I absolutely love. So this wasn’t about her not picking me because of my faith, this was about me in the end not being interested in in that job.","offset":1438,"duration":41},{"text":"Host: Really? Sincerely, yes? Because it did seem like you wanted to to be considered for that VP position.","offset":1479,"duration":7},{"text":"Josh Shapiro: I I called Sunday evening after she and I met and had a really candid conversation to inform her that I did not want to be considered. I thought she had some really good people to choose from.","offset":1486,"duration":11},{"text":"Host: All right, so let’s move forward then, looking at winning. You’re gonna run for Governor again. I assume that’s gonna be a shoo-in, you know, you gotta do the work, but it’s pretty clear you’re gonna win.","offset":1497,"duration":8},{"text":"Josh Shapiro: I appreciate your your confidence there, my man.","offset":1505,"duration":3},{"text":"Host: No, it’s clear. But let’s talk a little bit about if you were to run for President, which people seem to think you’ve got a really good shot, but you’re below maybe national recognition right now or a little bit far behind. Gavin has come out hey, I’m running, I’m running, here I am, he’s obviously in the pole position for now. I want to understand the Democratic Party and how they should proceed because just like the right seemed to separate and you had this MAGA coalition and you had, you know, the traditional Republicans who were just aghast at Trump and his style and his behavior, etc., now that seems to have fractured again. You have America First, America Only, all the supporters who were supporting Trump now have come out vocally against him because of the war in Iran. And then you have on your side this Socialist Democrat movement, which I think a lot of moderates are like, well that’s confusing, we don’t want to have more Mondames and that doesn’t seem super appealing to a lot of moderates, and the moderates are the ones who flipped this election and they went, the last election, they went with Trump largely as opposed to going with Kamala. So handicap for me what has to happen in the Democratic Party to win in 2028?","offset":1508,"duration":76},{"text":"Josh Shapiro: I understand why you’re asking that, and I will answer your question. I don’t think anyone should be looking past these midterms. And while I appreciate the confidence you have in me and and maybe in the broader dynamics here, I think we need to have a national referendum in these midterms on what people see happening in Washington, D.C. The chaos and the corruption that exists there. I think people need to show up in record numbers and vote their concerns. And so I’m not looking past the midterms. I do think it is important that we acknowledge Donald Trump has injected chaos and corruption into everything he touched. And I think it’s important for me, for other Democratic leaders in this country, to be able to show what calm, competent governance can actually deliver for people. That’s what I’m going to be talking about in these midterms as I seek reelection. I think it is important to paint an alternative picture to the chaos Donald Trump has created. One where you can actually grow the economy. You can make our communities safer. We didn’t talk about this yet, but we’ve hired 2,000 more police officers, invested in community violence prevention, and violent crime is down 12%, fatal gun violence is down 42% in our Commonwealth. We’ve invested in public education and by the way, scores are up, truancy is down, we’re moving up on the list, we’re about 10th according to Consumer Affairs in the quality of public education. I think we’ve got to show that there is an alternative to Donald Trump’s chaos, to his cruelty, to his corruption and you’re seeing that I think certainly in my state and I think you’re seeing it in other states as well. And we need to paint that alternative picture.","offset":1584,"duration":107},{"text":"Host: So 2026 is certainly going to be a referendum on the first two years of this presidency, which was extremely popular for the first nine months or so. People felt really good about the economy and that had well...","offset":1691,"duration":13},{"text":"Josh Shapiro: Some people.","offset":1704,"duration":1},{"text":"Host: Well, I think his polling was great, but there was this tinge, I think it’s pretty accurate to say the tariffs felt like those were chaotic. Then you get the ICE situation, that feels very chaotic. Then you go to this war with Iran, and that feels like a peak chaotic moment that we’re in here in week six of this. So it’s certainly going to be a referendum on Trump, and it feels like all the Democrats have to do is sit back and say like look, is this what you want? Gas prices up, inflation. But you’re saying they have to paint another picture. Paint that picture for me, what is that picture?","offset":1705,"duration":34},{"text":"Josh Shapiro: I think on both sides of what you just said, Donald Trump chose to push the tariff button, right? And as a result, here in Pennsylvania, what we’re seeing is coffee prices are up 30%, beef is up 19%, OJ, orange juice is up 9%. The fertilizers my farmers rely on here in Pennsylvania up 36%. So we’re seeing whether you’re a farmer, whether you’re, you know, a dad just trying to cook dinner for his kids, whatever the case may be, everything costs more because of the recklessness and the chaotic approach Donald Trump’s taking our economy with these tariffs. Obviously this war has spiked gas prices, up today about 4:15, 4:16 here in Pennsylvania, similar across the country. Probably years before those gas prices come down, even if the war, you know, hopefully ends, you know, very very soon. And so I think it is important yes, to point that out. The way Donald Trump’s policies have hurt the American people, have hurt our farmers, have hurt our small businesses. The point I was making a moment ago is I think that’s part of the conversation. The other part of the conversation is okay, well what are you doing to make people’s lives better?","offset":1739,"duration":72},{"text":"Host: Yeah well so what should the top three things be? Like if you were running the Democratic Party and everybody got in a room and said you know what, we really are going to take winning seriously, not getting into this like purity test for everybody in the party and you know, everybody’s gotta be perfect and Joe Rogan’s not good enough to go on air with because he’s a lifelong Democrat but he said something about COVID we don’t agree with, therefore he’s out of the party. Elon Musk is a little bit weird on the well, but the Democrats did. And then oh Elon Musk waited hours to and had Obama at SpaceX and then all of a sudden he can’t come to the White House for the EV summit, the category he created. Like it’s pretty obvious the Democratic Party had some real dysfunction in there in terms of building a bigger tent. And I can tell you, I have never felt more courted in my life than the Republican Party trying to get me to be part of the the Trump movement, which I demurred and declined, it wasn’t my style. Right. But they are trying to build the biggest tent possible. They’re like oh you agree with 14% of what we do? You’re in. Okay. Yeah, so walk me through what the top thing should be, yeah.","offset":1811,"duration":68},{"text":"Josh Shapiro: So let’s dissect that a little bit. First off, you attribute a number of things to Democrats that I didn’t say. So um you’re here interviewing me, so let’s focus on the things I say. Number two, they went and they courted you, and you demurred, but by the way, even had you not demurred, had you signed up, I don’t know that your life would be better off after a year and a half of Trump’s policies. What I am for here in Pennsylvania, the ultimate swing state, the toughest state to win in, an incredibly tough state to govern in, particularly with a divided legislature. I’m for investing in public education giving every child a God-given opportunity. I’m for safe communities and we’re building that here and we’re reducing crime in all of our communities. I’m for a pro-growth economy where we generate more energy, we generate more jobs, where we create more opportunities particularly in our rural communities and forgotten communities that have been too often left behind. And here’s the fourth thing I’m for, I am for freedom. And I’ll tell you what, this president represents a party that used to be known as the party of freedom, and now they have turned their backs on that. They want to tell my kids what books they’re allowed to read, they want to tell women what medicines they can take and what they can do with their bodies, they want to control the way I raise my child, they want to say, you know, every day that yeah you can vote but we’re going to set the rules and try and rig them in a way where you’re not going to be successful. They are not the party of freedom. And I think the Democratic Party has an opportunity to be the party of education, safety, economic opportunity and freedom. That’s what we’re doing here in Pennsylvania and that’s what I’m going to continue to put forth.","offset":1879,"duration":103},{"text":"Host: I think it’s a great platform. I would add to it housing. The thing I hear about from young people all the time is, you know, just I’ll never be able to afford a house, the American Dream’s a bit of a scam, and college is overpriced. So how do you think about housing and what is is that an issue in your state or?","offset":1982,"duration":18},{"text":"Josh Shapiro: Yeah, let’s talk about housing, let’s also talk about college because you raised both of them in your question.","offset":2000,"duration":5},{"text":"Host: The two hard I mean that has disinfected by the way just like two generations who are like you guys tricked us on housing, you told us we’d be able to get a home, and you won’t sell your home, boomers, and and you told us we could always make more than our college education cost, and that was a lie too.","offset":2005,"duration":14},{"text":"Josh Shapiro: Yeah. When I was talking about economic opportunity, it’s somewhat shorthand, if you will, for also being able to afford that community. Affording that community can be healthcare, it can be housing, right? But let’s talk about housing. Here in Pennsylvania, I’ve asked the legislature for a 1 billion dollar fund to be able to build more housing in Pennsylvania and repair existing housing. 50% of my housing was built prior to 1950. You can invest a few thousand bucks in a new boiler, a new roof, some new windows, actually keep people in their homes and not have to build new homes. We also have to eliminate or damn near eliminate the red tape that exists when it comes to building housing. We’ve got to be able to build this faster and so I put forth a regulatory reform plan to be able to build more housing. I think that is really, really crucial. And let’s talk about college for a minute. The first day I was Governor, the first executive order I signed was to do away with the college degree requirement to work for state government. We have 80,000 employees, damn near all now you do not have to have a college degree. Other than say the doctors and lawyers and people like that who require advanced degrees. Right. So now 60%, 6-0, 60% of all of our hires in state government don’t have a college degree. We followed up on that by tripling our funding for Vo-Tech and CTE in our high schools, you know dramatically increasing our funding for apprenticeship programs. 62% of my adult population here in Pennsylvania do not have a college degree. So we need to make sure we’re investing in them so that they have opportunity. You want to go learn to be a welder, you’re going to make six figures working at a shipyard in South Philadelphia. You want to go and you want to work on HVAC system, you’re going to work in some of our most complex life sciences construction jobs and you’re going to make six figures doing that. So for us, we fundamentally believe that you’ve got many pathways to opportunity here in Pennsylvania. For some, it’s going to college, great, and for others, if you choose not to go to college, that’s also great, we’re going to make sure that we pave the way for you and give you that opportunity.","offset":2019,"duration":132},{"text":"Host: Yeah, the generation tool belt movement is well upon us. People are starting to figure out going in debt 100 to 200k versus getting a plumber job, carpenter job, HVAC, whatever for six figures out of the gate is a much better opportunity.","offset":2151,"duration":15},{"text":"Josh Shapiro: Yeah, and to be clear, I’m not [ __ ] on people that go to college. I went to college, I presume you went to go to college. But for too long, by the way, politicians in both parties defined success exclusively around the idea of you having to have a college degree. And then set up arbitrary barriers to entry. Hey, if you don’t have a college degree, you can’t apply here. Or what about the skills that you developed in the military? What about the skills you developed at a trade school or the skills that you developed working in the private sector? Those skills should matter. And now they do in Pennsylvania, and we’re no longer taking an elitist approach that shuts people out just because they don’t have a college degree. We’re giving them the keys to opportunity and we’re giving them opportunities to pursue more success here in Pennsylvania.","offset":2166,"duration":46},{"text":"Host: Does the Socialist Democratic movement worry you, Mondame and the crew, and how do you think about that in terms of the party dynamics?","offset":2212,"duration":11},{"text":"Josh Shapiro: I mean, remember the question you asked me I don’t know three or four questions ago about you said well I only agree with 14% of what you agree with, you know come join the party. Look, my view is that we’ve got to have a big tent and my view is that we’ve got to have a real debate around different ideas and just because I might not agree with you on these three things, I might agree with you on something else. Listen, I’m sitting behind my desk here in the Governor’s office. This is where I negotiate bills and budgets and other things. If I threw everybody out of my office that I didn’t agree with 100% of the time, we’d never get anything done. When I sit down across a table from a Republican lawmaker, say what are the 10 things you want to accomplish? I tell him the 10 things I want to accomplish and you know what, we’re not going to agree on all 10, but if we agree on three or four, I’d rather focus on those three or four things where we can find common ground than the five, six, seven things where we’re just going to disagree. And so I think if you want to make progress, you’ve got to figure out how to create, you know, majorities whether it’s a majority in the legislature to get a bill to my desk, a majority come election time to win an election. You’ve got to find ways to bring people together and find common ground and not just focus exclusively on our differences.","offset":2223,"duration":70},{"text":"Host: What’s your take on what’s going on in Congress, Senate, in terms of Trump and getting alignment there because hey, when you go to war or you do tariffs, um this was something we had a consultation between these different branches of our government. And we had other presidents on the Democrat side, etc., you know, say we’re going to just get rid of student loan, I’m doing an executive order. Curious your take on the balance of of our different branches of government and the lack of collaboration because this is particularly disturbing, we’re both Gen Xers, we grew up watching the Democrats and the Republicans argue, but then they all got together, had lunch, and they negotiated. Where is that esprit de corps of everybody rowing in the same direction for all Americans versus this toxic you know, we’re just going to block each other at every and do character assassination at every single turn? It’s it’s the most polarized of our lifetimes for sure.","offset":2293,"duration":56},{"text":"Josh Shapiro: I actually think the Congress of the United States, the leadership there, I mean they are frankly kind of sad, pathetic people. And let me explain why, right?","offset":2349,"duration":10},{"text":"Host: Please.","offset":2359,"duration":0},{"text":"Josh Shapiro: You put uh what’s his name, Johnson in as Speaker, and he’s effectively a rubber stamp for anything Donald Trump wants. And by the way, whether you agree with Trump or not, I think you can agree that you’d like your member of Congress to at least meet the burdens that they have on them in the Constitution of the United States, which is to be a check, which is to be a separate branch of government. And a branch of government that has meaningful responsibilities here. When the Congress of the United States walks away from their responsibilities, whether on tariffs or whether on declaring war, and ultimately just kind of empower the president, again, agree or disagree, I obviously have profound disagreements from the president on on those things, then what you’ve really done is you’ve limited the power of the Congress, and what you’ve really done is you’ve seen a whole bunch of people that put Donald Trump before the oath of office they take to the Constitution. And I think that’s just pathetic. And it’s weak. And I think our country’s suffering as a result of it. Look, I’m here in Pennsylvania, where where it all began 250 years ago. And the brilliance of our founders was that they left so much of the work to the next generation and the generation after that to pick up the baton and continue to perfect our union. Our founders though, always contemplated two things. One, that there would be honorable people in office. And two, that the people in office would exercise their power and be a check on one another. And in some cases, slow things down to make sure that bad things didn’t occur, bad things couldn’t get through the process. I think what Americans are confronting now is a realization that we don’t really have all honorable people in positions of authority in the federal government. And that that checks and balance system that was constructed here in Pennsylvania is not standing the test of time because you’ve got these profoundly and pathetically weak people like Johnson and others who just simply give away their power to folks who are corrupt and to folks who are not acting in an honorable way.","offset":2359,"duration":156},{"text":"Host: You keep bringing up that corruption, explain to me what corrupt things you know that the Trump administration has done.","offset":2515,"duration":3},{"text":"Josh Shapiro: I think to me there has been an extraordinary amount of self-dealing. There there has been a good bit of family members doing quite well in this in this environment. I think you’re seeing more and more people who have the president’s ear being able to lobby him at his swim club to get a pardon for someone that frankly doesn’t deserve a pardon. I mean I think the list goes on and on and on, but those are some examples that I think the American people see with their own eyes. Taking a a billion-dollar jet from the Qataris and thinking there’s nothing attached to that, right? I mean I think that there’s just a lot of that that moves so fast that the American people are having a hard time keeping up with it, but there will be a reckoning on this one day.","offset":2518,"duration":51},{"text":"Host: Yeah so on the pardons I’m strongly agreeing, feels like the pardon power is super abused. Is there a path to refine that tool? Because it relies on norms, right? And ever since Bill Clinton, you know, did some you know friends and then obviously Biden did his son and then Trump’s doing his you know folks. It feels like now this is just a get-out-of-jail card, you come into an administration and then everybody from Fauci to you know Hunter Biden, everybody else is just going to get a pardon on the way out. How would you reshape that tool?","offset":2569,"duration":37},{"text":"Josh Shapiro: Well let’s be clear, and I don’t think you’re suggesting this, but um and I was critical of Joe Biden when he pardoned his son, right? I was critical of him publicly. What we are seeing under Donald Trump, you have to admit, is next level when it comes to the abuse.","offset":2606,"duration":14},{"text":"Host: I mean it’s on the way it’s yes, it’s literally it’s in the first year, it’s not on the last day even, it’s like an ongoing tool here. We had CZ, who was a crypto person who got pardoned, and Trump didn’t even know who he was. He was just like oh I heard he’s a good guy.","offset":2620,"duration":13},{"text":"Josh Shapiro: Right. I mean I will tell you, I sit at this desk here and I sign pardons and clemencies. And I take that responsibility so seriously. And I agonize over these decisions. And and I pray that I get these decisions right. And I believe I have. And I’m transparent about why I viewed someone as worthy to get a clemency and also worthy of not getting one, or not earning one. And these are tough, tough decisions. Goes back to what I said a moment ago, our founders when they vested that kind of authority in an executive, didn’t necessarily do something wrong by giving the executive that power. But they were leaning on the assumption that the executive would be honorable. That the executive would would do this with morality and real scruples in mind. And and I think what we’re seeing with the President is if you sidle up to him at his swim club, you donate a certain amount of money maybe, or you have his ear for some other social reason, you can usually get him to do what you want him to do. And that’s simply an abuse of power, man. It’s wrong and and it’s something that the American people I think should take issue with.","offset":2633,"duration":67},{"text":"Host: ...give a pardon to someone who's important to you.","offset":2700,"duration":2},{"text":"Josh Shapiro: Yeah, the pardons are definitely super troubling.","offset":2702,"duration":3},{"text":"Host: How do you deal with the family members and the kids enriching themselves? Obviously nothing has been done by a court or an investigation into Trump's kids at this point, so we just want to be clear about that. You know, we had Hunter Biden getting a ridiculous million dollar board seat. I've never seen anybody get paid a million dollars to be on a board. That was obviously corrupt in some way, or somebody trying to curry favor. Doesn't mean that President Biden was, but definitely was corruption there.","offset":2705,"duration":36},{"text":"Host: How do you deal with kids of - and this has been going on for a while - these kinds of allegations. If we can't rely on honor and norms, is there another proposal here that the kids of people in office can't make money? Your kids can't make money if I was running for office? My kids couldn't make money in the free market. How do you - is there any kind of solution you can think of?","offset":2741,"duration":19},{"text":"Josh Shapiro: I think it is important, you cited Hunter Biden. They went through a legal process. There was an investigation by the Department of Justice. I think there has to be a real look - I say this as a former prosecutor - a real look at some of this stuff and follow the evidence, follow the law. And if charges are warranted, bring them, and by the way, if charges are not warranted, don't bring them. Do not use the rule of law as a tool to go against political opponents in any way.","offset":2760,"duration":31},{"text":"Josh Shapiro: But I think what you've got to have here are people who are operating with real morality. And you do have to figure out a way to operate within the norms again. I'm unwilling to accept that that is gone. It may be temporarily suspended under Donald Trump, but I'm hopeful that we can find our way back to that. Let me be clear about something else here, that finding our way back to that is a bipartisan exercise.","offset":2791,"duration":25},{"text":"Josh Shapiro: It's going to require Republicans and Democrats and independents all demanding when they go to the ballot box that we want to elevate people who are ethical, people who are honest, people who are focused on doing their jobs with integrity. And then when those people are in office, rewarded with the votes of the public and in these positions of public trust, to hold them accountable as well.","offset":2816,"duration":22},{"text":"Host: And you believe that can happen in a post-Trump world?","offset":2838,"duration":3},{"text":"Josh Shapiro: I do. I do.","offset":2841,"duration":1},{"text":"Host: I strongly agree. Hey, it's a year since your home was firebombed by an insane person who was anti-Semitic. Your faith comes up over and over again. I personally think people are a little obsessed with it, but here we are. And the Democratic Party has been split apart as well over this support of Israel issue. You have a very nuanced position. Number one, how are you dealing with that personally, the anti-Semitism, which to me as somebody who grew up in Brooklyn with lots of Jewish friends and all kinds of different people, just insane to think that Jewish students are being - or any particular group of students - being chased by the other students at Columbia University because they're Jewish? This chaoticness is just heartbreaking. But as a Jewish person and literally experiencing it first-hand, I mean, how are you doing with that?","offset":2842,"duration":48},{"text":"Josh Shapiro: Yeah, I appreciate that. Look, we should separate this and have two conversations: one about Israel and one about anti-Semitism, because you kind of blurred both in the question. Let's focus first on anti-Semitism. I have been very outspoken about those who are engaging in anti-Semitism, peddling words that are anti-Semitic. And importantly, I've been critical of people on the political left and on the political right.","offset":2890,"duration":28},{"text":"Josh Shapiro: And I think anti-Semitism is a problem in our society and it's a problem on the left and it is a problem on the right. And I think it is important that we call it out. We call it out whether we're in an interview - not accusing you by any stretch - conversation, yeah. Call it out on social media, and then we just call it out in our communities and our daily lives where we see it. On that, there should be no nuance.","offset":2918,"duration":22},{"text":"Josh Shapiro: We should be able to come together, people who are Jewish, people who are Christian, Muslim, and all agree that hatred, bigotry in any form directed at a Jew, a Muslim, a Christian, anyone, it has no place. And by the way, it makes us all less safe. And so we have to focus on speaking out against that. No nuance on that.","offset":2940,"duration":22},{"text":"Host: Yeah, Trump.","offset":2962,"duration":2},{"text":"Josh Shapiro: On the issue of Israel and the Middle East and the war in Iran and Gaza, there's a lot of nuance there. I'm happy to answer your questions on that, but I think on the issue of anti-Semitism, we have got to be in a place where we universally condemn it.","offset":2964,"duration":7},{"text":"Josh Shapiro: And I think what you're seeing from some folks on the right and some folks on the left is they'll only call it out if it's said by a political opponent or someone they disagree with. And I frankly respect people on the right, like Ted Cruz, who have called it out within the Republican party. I've tried to call it out when it rears its ugly head in my party. It is important that it be universally condemned.","offset":2971,"duration":26},{"text":"Host: So easy to do. Let's tackle the issue of Israel and I would say, yeah, every Jewish person, Jewish American person who I know, when I ask them about this issue, obviously incredible tragedy October 7th, going and collecting the hostages seems like a reasonable thing to do. I was there for 9/11, you know, it seems like a pretty analogous situation. This has to be settled and the United States went and did what it had to do in Afghanistan and took out Iraq for extra measure, that's a whole other diversion.","offset":2997,"duration":32},{"text":"Host: But 100% of folks say they don't agree with Netanyahu's approach to what happened in Gaza. And then folks feel a decent number of people, whether it's reality or not, that America's getting dragged into this war with Iran not under false pretenses and because Israel is pushing us to do it. So let's take these two issues separately and I'm just curious in understanding your position on this. Are you part of the Jewish American diaspora that believes hey, Israel has a right to defend itself, but maybe Gaza went too far?","offset":3029,"duration":34},{"text":"Josh Shapiro: Okay. Well, first off, let me say this: I don't view this issue as a Jewish American, as you said. I view this issue as an American. And I view this issue in a way of trying to understand what is the best thing for America, which to me is having peace and stability in the Middle East. Okay? That's how I approach these issues.","offset":3063,"duration":28},{"text":"Josh Shapiro: It is - and I've been clear and consistent about this long before October 7th - that I think Netanyahu, the leader of Israel, is someone who's been leading Israel down a dangerous and isolated path. I think he has made Israel more isolated in the world community. He has fractured really what used to be a nonpartisan or bipartisan American support for Israel. And I think he has put Israel in a very dangerous place.","offset":3091,"duration":30},{"text":"Josh Shapiro: And of course, he was the leader of Israel who wasn't minding the shop when October 7th happened. So I've been very critical of Netanyahu for years and years and years. I've also for years made very clear that I think America's interest in the region should be for stability and peace. And that it would be my hope that you would have two states living peacefully side by side, Israel and a Palestinian state.","offset":3121,"duration":30},{"text":"Josh Shapiro: Now, I realize that is a long way off given where we are right now. But it is clear that we need to work toward that. And obviously that Palestinian state cannot be led by Hamas, which is a terrorist organization, and there has to be some structure that is put in place in order - in order to create that.","offset":3151,"duration":19},{"text":"Josh Shapiro: As it relates to the war, which you also asked about in - in your question, I mean, this was a war of choice. The president never defined the objectives. It is clear he doesn't know how the hell to get out of this. We'll see what he ultimately does with his big threats, you know, we're recording this on the eve of his - of his big threat...","offset":3170,"duration":18},{"text":"Host: Ultimatum.","offset":3188,"duration":2},{"text":"Josh Shapiro: ...using language, using language that was so [expletive] offensive, you'll excuse my language, that diminished the value of human life. We'll see what he ultimately does. Does he chicken out as he usually does, or does - God forbid - he - he go through with that? But this was a war of choice. He didn't know why he got into it. He doesn't know how...","offset":3190,"duration":23},{"text":"Host: Why did he get into it? Handicap it. Why did he do it?","offset":3213,"duration":2},{"text":"Josh Shapiro: America's national security interests have not been well-served by this. And economically, you've talked about this, economically we are worse off because of this war. I'm sorry, I didn't mean to speak over you.","offset":3215,"duration":10},{"text":"Host: No, no. No, I mean, listen, I appreciate your candidness, Governor. Why did he do it? If you had to handicap it, or what are you hearing when you talk - because you have obviously a lot more information than the average American. Why now? Why did we do this?","offset":3225,"duration":17},{"text":"Host: Now, we had done, you know, the strategic trimming of the hedges, mowing of the lawn, whatever the term is, to get rid of the nuclear progress. That containment seemed like a perfect strategy and then all of a sudden we decide we're going to do regime change. This is after Trump promised that he would never get an - do an intervention like this in the Middle East. This is after we were told by the Republicans, do not vote for a crazy Democrat who will take us to war with Iran. And here we are in month 14, 13 of the Trump presidency and he started a war.","offset":3242,"duration":35},{"text":"Host: His own biggest advocates, from Megyn Kelly to Tucker Carlson and, you know, people on the fringe, Alex Jones and everybody in the middle, the comedians who supported him, the podcast diaspora or the podcast bros, they're all fleeing the ship. They did not want this. So here we are. Why did he do it? Why now? What is your handicapping of it?","offset":3277,"duration":18},{"text":"Josh Shapiro: Well, I'll answer that. I will just say it's yet another broken promise to the people who put him in power. He screwed over the farmers who put him in power. He told people he wouldn't slash Medicaid, he cut Medicaid. He told people he'd bring down prices, prices have skyrocketed because of his tariffs. He - he's got this long string of broken promises. Now, why did he break this particular promise? You know, let's - let's examine the record.","offset":3295,"duration":28},{"text":"Josh Shapiro: First, Rubio went out and said he did it because if we didn't move then Netanyahu was going to move and was going to force our hand. Then they walked it back. He said seven or eight months ago that they destroyed their nuclear capabilities. And then came back seven or eight months later and said we had to go in because we had to destroy their nuclear capabilities. I don't know.","offset":3323,"duration":22},{"text":"Josh Shapiro: Then they said it was about regime change. Well, great. I mean, we went from like an 80-something year old Ayatollah to a 60-something year old Ayatollah who by all accounts seems to be far more hardline. I'd hardly call that successful regime change. So to me, it is hard to - and I think you've seen I've been trying to be very forthright in answering your questions. You're doing great.","offset":3345,"duration":23},{"text":"Josh Shapiro: I don't know how you answer that question because the President never answered that question. He never sat in the Oval Office and looked the American people in the eye and said, this is why we're going in. And you know what? This isn't semantics. This isn't politics. If you don't know why you're going in, you don't know how the hell to get out. You don't know how to instruct the military, our brave military, including those 13 souls who did not make it home to their families because they went on a mission that the President never defined.","offset":3368,"duration":28},{"text":"Josh Shapiro: And we mourn their loss, we thank our military heroes for what they did, and we thank our military who are out working every day on behalf of our freedom and our safety and our security, but they deserve a Commander-in-Chief who would have defined the mission. And if you define the mission, you know how to get out, and he never defined the mission. I don't know ultimately if he will follow through on his threat again. It's, you know, it's Tuesday afternoon, you and I are talking. We'll see ultimately what he does here, but to me, this has been a failed and compromised mission from the beginning because he never made clear why he was going in.","offset":3396,"duration":39},{"text":"Host: Yeah, and I know you got to go in a moment. It does seem to me that first explanation, sometimes people, you hear their first reaction and their first statement is the true statement, just in general. And it does seem like Israel was going to do this and we joined them and we didn't need to.","offset":3435,"duration":16},{"text":"Josh Shapiro: No, America should never - pardon me, America should never be led around by any other nation. It should always be about America's interest, our national security interest, the interest of expanding freedom and opportunity for the American people. We should never, ever be bullied as maybe President Trump was by any other world leader.","offset":3451,"duration":20},{"text":"Host: Back to the anti-Semitism we're experiencing now. You said hey, let's address them separately. But I don't think you can separate them if we're getting pulled into this war by another nation and people believe, like you and I do, hey, Netanyahu maybe went a little too far here. That is what's causing the anti-Semitism in this country, don't you think? This relationship with Israel, the state of Israel and Netanyahu, our undying support for Netanyahu, that's not causing the anti-Semitism here? That's what these young people seem to be saying is, we don't want to vote for somebody who supports Netanyahu.","offset":3471,"duration":37},{"text":"Josh Shapiro: Well, I think you've got to be real careful on that. You, the collective, not you individually. I mean, if you're suggesting say that Jews are Israel and reflect Israeli policies and support everything Israel does, I mean, that's one of the oldest anti-Semitic tropes out there, this sort of notion of dual loyalty. I think it is fair to vote on the issue of do we support what Donald Trump is doing relative to Netanyahu.","offset":3508,"duration":34},{"text":"Josh Shapiro: That's fair. But to suggest that somehow it's, you know, because Jews are tied to Israel and that's why we're doing what we're doing...","offset":3542,"duration":7},{"text":"Host: Well, you and I can parse this issue I think very easily. But young people at Columbia or Harvard, where all this is going on and these, you know, pro-Palestine protests are going on, they don't seem to be able to make that parse. That seems to be one of the roots of the problems here, is that people do put together - these young people, they could be stupid, they could be misinformed - but they do put together what the state of Israel is doing and they equate it with Judaism.","offset":3549,"duration":22},{"text":"Josh Shapiro: And that's why I've tried - and that's why I've tried to be so outspoken on this in making clear that on anti-Semitism there should be no nuance. And that's a conversation where we should all be able to unite. And that we have to protect a place for nuance when it comes to Mideast policy, when it comes to Israel, when it comes to Iran and - and anything happening in the Middle East. And we need to give space for those who want to peacefully - and I want to stress peacefully - protest.","offset":3571,"duration":28},{"text":"Josh Shapiro: We want to give space to those who differ from the administration and frankly, those who support the administration to be able to go out and to protest peacefully. And that is I think an - an important part of the fabric of our American society. I just think it's important - and I try and do this work every day as Governor - to keep those conversations separate. Because when they get blended, that's where I think it gets dangerous and that's where - uh, I - I think it - it really crosses a line into something we don't want to see in our society.","offset":3599,"duration":28},{"text":"Host: And you could be super critical of Israel and you could love your Jewish neighbors and friends. These are - this is a very simple concept here.","offset":3627,"duration":8},{"text":"Josh Shapiro: Absolutely. And I think that reflects where I am on many things. I've been super critical of the Israeli government, the Netanyahu government. Um, and - and I'm someone who loves Israel, someone who has spent time in Israel. I wrote a whole book about - uh, I proposed to my wife there and how I think the - the idea of it is - is important. We've got to figure out ways to keep those two conversations - not separate, but - but blurring the lines in a way that creates some dangers I think is something we have to guard against.","offset":3635,"duration":34},{"text":"Host: Yeah, lots of education, lots of opportunities. Josh Shapiro, thank you so much for coming on \"All In\" and we look forward to having you on again and good luck with your race. Good luck with your 76ers. I will see you in the second round, it looks like.","offset":3669,"duration":13},{"text":"Josh Shapiro: Next year - next time I'm on, I'll be wearing a Sixers hoodie. So go Knicks!","offset":3682,"duration":6},{"text":"Host: There you go. I'll see you courtside, my friend. You go to the games.","offset":3688,"duration":3},{"text":"Host: I'm going all in!","offset":3691,"duration":15}],"logs":[{"elapsed":"0.0","message":"Downloading audio from YouTube...","detail":null},{"elapsed":"0.0","message":"Trying download with browser cookies (ad-free)...","detail":null},{"elapsed":"2.7","message":"⚠ Cookie download failed: WARNING: [youtube] [jsc] Error solving n challenge request using \"deno\" provider: Error running deno process (returncode: 1): \u001b[0m\u001b[1m\u001b[31merror\u001b[0m: Uncaught (in promise) TypeError: Cannot read prope","detail":null},{"elapsed":"2.7","message":"Retrying without cookies...","detail":null},{"elapsed":"30.7","message":"⚠ Downloaded without cookies — audio may contain ads","detail":null},{"elapsed":"30.7","message":"Audio downloaded (33.7 MB) in 30.7s","detail":"File size: 33.7 MB"},{"elapsed":"30.7","message":"Video title: Josh Shapiro on Trump, Iran War Chaos, Israel's Failure, the Economy, and 2028 Race","detail":null},{"elapsed":"30.8","message":"Audio duration: 1:01:51 (61.9 min)","detail":null},{"elapsed":"30.8","message":"Large audio (61.9 min) — will use chunked transcription with gemini-3-flash-preview","detail":null},{"elapsed":"30.8","message":"Skipping full-file attempt — using chunked transcription for 61.9 min audio","detail":null},{"elapsed":"31.2","message":"Split audio into 2 chunks for transcription","detail":null},{"elapsed":"31.2","message":"Transcribing chunk 1/2 (starts at 0:00)...","detail":null},{"elapsed":"31.2","message":"Uploading audio to Gemini File API...","detail":null},{"elapsed":"34.8","message":"Audio uploaded in 3.6s","detail":"File ref: files/pjkvf3xqiro0"},{"elapsed":"34.8","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"114.7","message":"Chunk 1: 68 segments, last timestamp 43:53","detail":null},{"elapsed":"114.7","message":"Transcribing chunk 2/2 (starts at 45:00)...","detail":null},{"elapsed":"114.7","message":"Uploading audio (offset 45:00) to Gemini File API...","detail":null},{"elapsed":"117.3","message":"Audio uploaded in 2.6s","detail":"File ref: files/4zm4bxgo0t1i"},{"elapsed":"117.3","message":"Audio processed in 0.0s. Transcribing with gemini-3-flash-preview...","detail":null},{"elapsed":"145.1","message":"Adjusted chunk 2 timestamps by +45:00","detail":null},{"elapsed":"145.1","message":"Chunk 2: 49 segments, last timestamp 1:01:31","detail":null},{"elapsed":"145.1","message":"Chunked transcription complete: 117 total segments","detail":null},{"elapsed":"145.1","message":"Total cost: 93,271 in / 15,594 out — cost: $0.0934","detail":null},{"elapsed":"145.1","message":"Total transcription time: 114.4s — 117 segments","detail":null},{"elapsed":"145.1","message":"Analyzing topics across 117 segments with gemini-3.1-pro-preview...","detail":null},{"elapsed":"166.2","message":"Topic analysis complete in 21.1s — found 10 topics","detail":null},{"elapsed":"166.2","message":"Analysis tokens: 16,346 in / 847 out / 2,005 thinking — cost: $0.0669","detail":null},{"elapsed":"166.2","message":"Pipeline finished in 166.2s — total cost: $0.1603 (128,063 tokens)","detail":null}]} \ No newline at end of file diff --git a/history/_meta.json b/history/_meta.json new file mode 100644 index 0000000..a413c8c --- /dev/null +++ b/history/_meta.json @@ -0,0 +1,40 @@ +{ + "folders": [], + "uncategorized": [ + "1775679261151-MPAsUZEJHiM", + "1775678510294-Mv4cF13glBo", + "1775672308695-kwSVtQ7dziU", + "1775603102882-yLmM3M7d9v8", + "1775599688621-Tmw2dW0a9DY", + "1775589261845-wO5iES4qjwE", + "1775589068370-UmLdukkI0IU", + "1775588771329-NBu8G-5YpGI", + "1775588353507-mjNP5IOzCbA", + "1775587377519-Rc9lTSs7wgI", + "1775477439435-HMTrd9Hn3e8", + "1775430672822-lclDwnfnOGc", + "1775430216753-Axpnkqd-Agk", + "1775275709956-d01H-T3-frg", + "1775274863397-N-pust8qtGI", + "1775246692426-m3uwf5BZy1Y", + "1775224371563-Qc6hjJ9Zze0", + "1775224185561-C0DMdUqF73Q", + "1775223585124-NDE0NjE5NDgtNDFi", + "1775223278105-ovih9Xotmxg", + "1775223130960-kjQZexuV_AE", + "1775222710862-gwW8GKwHB3I", + "1775222522683-lTuS7Ns8cZg", + "1775222175607-91up0VxYeNw", + "1775221783211-YTVSwOY19Qs", + "1775221563723-9ZbbxSgrjhw", + "1774302030087--JBhTBu9ZbA", + "1774289546791-rngx_PsPxkg", + "1773858934218--dgsZ0O-lZQ", + "1773775610426-xaNl2EY8b-c", + "1773695002747-hlOA8ObQJXo", + "1773694605993-Yzg3YjFlODQtYWNl", + "1773185576199-YThlOTAyMWYtOTU4", + "1773021528170-MjczYmIzZjgtZjg1", + "1772740338135-2JiMmye2ezg" + ] +} \ No newline at end of file diff --git a/history/auto-queue.json b/history/auto-queue.json new file mode 100644 index 0000000..ce1ab63 --- /dev/null +++ b/history/auto-queue.json @@ -0,0 +1,14 @@ +{ + "items": [ + { + "id": "auto-1775757891625-_5-lc6c0e2Y", + "videoId": "_5-lc6c0e2Y", + "url": "https://www.youtube.com/watch?v=_5-lc6c0e2Y", + "title": "MacroVoices #527 Adam Rozencwajg & Jim Bianco: What Comes Next After The Iran Crisis", + "uploadDate": "20260409", + "subscriptionId": "sub-1772423650145", + "subscriptionName": "Macro Voices", + "status": "pending" + } + ] +} \ No newline at end of file diff --git a/history/seen-list.json b/history/seen-list.json new file mode 100644 index 0000000..2327092 --- /dev/null +++ b/history/seen-list.json @@ -0,0 +1 @@ +{"videoIds":["VB7taeOBHZE","LpoQDsbhGkw","74INAXFKphU","sd-ViOH8Wzc","GCPD9wG3_IQ","ICwwu7uN_NU","L7FqnIk5xNE","eE4l4AiMg78","GYNI7vJ9hf8","9kTIJ-21A-A","zCANeUbKIgE","KZiITcXHB6s","lRDMPJesNwY","eFR33lfVEBY","a4MygDLd9_U","CUoxi0mKvR4","5VTMAILzO_8","LsIkM6SE1B8","D8FXQBmDBNg","YhLVa3G2jo0","YdmvXkuHOec","QIDukxMh4Pg","_TLGmHBe_u8","kKINHmqqseg","HkhyuZHJiN4","Jx5BiuLUbHE","xJ6fRNHT_KU","9u7dc0EiYzg","u_w7Hhbxn3Y","uzeJzDMN8eg","WSJavPMb1Ck","UYvPdo8VHCA","bNFmRvqsI2s","iHiVFJEKKuc","Nt3TeLmXKWU","nZX0Rco7-WA","ayxk0SYLfBE","6uTOn0j5dlc","D5MLR4Pmr-E","pE6sw_E9Gh0","yLTSqBzKG2s","hUJz55AsUz4","fTqINzeudJ4","X52BNWZrXSk","IOoRXSyezBE","4JA7n0wTChw","4qG_f2DY_3M","K2cpSUpdIOs","SPfE5SS7fc0","b0DO0tP06eQ","ymEtsnDif5M","75Azta2EDoI","1Hil9D4PYwc","p6kBKSZqjn4","ftZnXFT9gmc","Sujfz1pESVc","Cw7IuB_YxQg","zvX5NuIFq6Y","LHS8hsNOiqM","w3OmZMPgApE","LQfAyzfp_kU","3kgpeH9MOg0","Z55drsUfIos","URA8PB-Afhc","NAmuZLQgvhE","9LQ4AElWDMc","UGmOYNWiV1A","j8chNXhA8o8","KYzYOPkxLis","yPD1qEbeyac","DoitlIIsOW4","QVcSBHhcFbg","9NtsnzRFJ_o","-7bJtS7koQM","SewIKjE1Lec","tBU5UPI03Rg","Z77jZkYDpIE","bUrCR4jQQg8","D7ZKbMWUjsM","TYCTfrec6FE","5LYZCoDysLs","o9e1SDPc6Pc","-8rMn2pk5qU","Xuurlc-V2Jg","nrDudJtKpiE","oHYoSBixdPI","iTwZzUApGkA","D4BQCaVMjg4","g1C_5cbKd5E","YPt6Cs1hd2k","bD1rrBBcJSA","-i9AGk3DJ90","xgvoYJvbNT8","Wu_LF-VoB94","BRG4_KfTxbs","lEULFeUVYf0","iNL_BFlHYZ8","qzXU390N3vs","RmwbNdyrilk","t6RCTP4fc9Q","23t_ynq2tmk","bdsc3Spm6Sw","fh2dBmLN-ZM","qGb7hYMlA3o","fYhY-vC000A","bz66w9rR36Q","v3JNZXjCLzg","SNHDQkJujH0","cy6dnFAsM68","eaoSE7v0ndM","nSZ24qYN38M","R-LD8xWOxm4","tiqbPfieB0M","FAHPF8K7TZU","9cTbZiLl7ag","WTjWgp70uiA","XApHvZ2elm0","UWk0E1WeY3s","XKPC4E-Ck1M","LueOWT6nSV8","70FxXhbh38E","ejytZZ8hfgs","pqKnrtGCrII","U1-AYKLgtM4","i6PXbA4wzoM","9tmDsaieAtU","TuQ_aeD4uc4","s7Re3uyOoPQ","aBB-nIPkQrY","i6Rtyl6jmAg","TrXsc7RuBh4","rG-IWfD3qhU","Hh29qPrcJlg","7feba3b6-e4c9-4495-80cb-fb5ec7496e29","d741be8f-eb86-4d2d-9367-19c59b4fe666","2e4a43df-d9b5-46d7-b59f-feb5cba8b555","475fc02f-d21d-4b7a-87c4-785000e36c58","31ad0b9b-99a9-49f3-abf5-de39d9afd74f","7583bee5-43d5-491d-a191-9a43f4c92121","0acc079b-02c8-4f11-a793-967f0b63ddb6","a4fbafa0-1ab1-4fb2-bac5-e9c36da33bcf","69aae99a-a1d6-4ac2-a675-154baa5484d0","036ab83f-6808-425b-bdf3-4be376ddfc27","b196b8b5-2d10-4220-8b6f-86f1b18d7462","72b80db6-4c2a-4519-9666-ab70bd49c624","bf5eea29-bf1e-4773-a7f9-46167f4a3ec6","4dacef5d-17fd-451a-9616-3792d617b0d4","14a1e295-cd87-4964-85fd-b790a0fe4268","4d57d704-585d-4ce3-86e7-d632171707df","e1093ba0-30b8-47b1-b681-2ab61b34f261","eb6fcc7b-2e30-4a7e-b9fa-388982edf027","5109f5ad-87cd-4156-89ee-f02811f5bbe6","9ab00971-f888-4eca-9798-21bb5fab4042","eb475aa4-be22-495c-adaa-511d30179dae","16b0ead0-2113-4d21-be0b-0cd5efe07c81","0c3a99b1-56a0-45b4-ad80-5ee8210074e1","a517dfd1-f1ab-44d6-baa7-bfc94341f84b","68149f1c-cae4-4c7b-a493-87cf56d2101f","8a8ae9e9-8b13-4cba-abd8-0fb0dc2641bb","aa58ee9c-e861-4623-8e8b-2aecc8824a90","f9225958-e942-46de-9641-82c338f15722","c3b5b6f3-bc57-4049-a81f-4ac9ca727f14","86571302-b523-41b1-a41b-295549e856fc","6facb929-2e92-4d64-a8a8-7e1a4a26ce9f","63b37132-c989-4d61-87b6-9b01f6dd9408","8df854af-68d3-4fbc-8145-6fcb1ce0496c","2a07da51-201e-4c97-b050-2dc9791227e7","9c6d4850-00c0-47ac-873b-5f744d7dd482","08317737-de6c-4047-882d-1b4e0d3d4dab","987e0493-30cf-4cd0-9b1f-7b5ecdbf5990","5cf3553c-b85d-4efa-9e87-f886e44cb887","bae9a26a-97af-4754-9c43-4fcb87c65205","0792151f-5290-42c2-87a1-595862a5d39a","45f3c2eb-b292-47e4-9dad-e7e034796684","38392781-7331-4421-a7d8-087f875b0bb7","1421a616-17ac-42ec-b4c4-f95a4d6ecfe4","c85543e1-aa1d-4e3b-977f-a04dc1d22963","df8da274-7920-4b6b-b1fc-a715076e89a8","674fa8ed-e34e-4305-8ae6-dfa76bc753d8","ce454ab7-7912-4656-b02a-157c5d18b847","5ed0c393-51e9-4e96-be2a-b9d9e4a9ecf1","aba69029-6b70-4ac5-8534-b518b1d17af4","53b66eda-766b-499e-8439-198cd278682b","7ce646da-ee64-427c-8c0f-e30c07a126ef","aef472d7-fcf4-4dd6-9951-16010bfca842","0f1e60ae-aecf-4c0d-990b-45f6b9865e13","222e6adb-1cac-4767-8d5a-89363749bc5c","68838df4-0435-4fdd-a483-06de4f45c1f3","9e928b73-260a-4fad-bb14-822ce14cc92f","4b2ab52a-2cc7-4d35-8eb6-a9e6845323a5","6f351646-0de0-494f-8293-659760b8a751","dbf85570-7d69-4da1-9e63-9f456fe1504f","8ceff625-bd62-4ea9-aab8-94f939c38601","790a2d84-446f-4fb8-a2d8-5c324cc4fce1","f68f44e5-20b1-49f7-8ee1-5fe77ae8005b","6ae80027-2b52-4f93-b3c8-34208584a2ce","bca172b2-6410-4510-8f05-af0895e216b7","4fbea603-8123-46df-b25a-6fd427c0b61d","2dcf29c3-f5db-475f-be5e-b8f578d36052","f03d3b4a-47fe-4143-9d12-7b11fff91019","85fe6410-7c3b-4613-b133-e106cfcb857f","0d3e2916-f99f-40a1-8781-8f2bdfb70dc9","236c515f-eb4b-4836-80ee-550fcf67cc0f","7a2aec6e-e27d-47c3-a3e3-a03e3072fe69","4423dd7d-62fe-4bc8-8ccd-3ae841d4a329","3ba913d7-bf01-4f65-a7f7-9fbe898c4c28","d6f33086-3bc1-443e-9893-a9664c6e7eab","451c11ab-c396-4262-bb6a-c9f3071460e6","c8411fcb-653e-44ba-94d1-f603c35560d3","640d5b47-bdf7-4863-be51-ac3ae5d74547","d98d189b-dc7b-45b1-8720-d4b98690f31f","ce152bc8-8868-43e6-963f-bb5891ae88f7","800a95fa-820b-4b2d-a9e9-e1bd409b74f8","94fc697d-4773-4c0d-ab62-5926e71262ef","326f7464-66f3-4bae-9f47-15573f186fe5","2f89fcc1-cc73-4907-8cff-e0441abe7538","75a0b5d5-e0a3-4252-b75b-ae08715f2dc1","ccffe82f-1333-44de-94af-ba7f1e0a836d","b477e8cc-2274-450c-b5e7-de59c32d2cb5","d2fc4984-8155-4979-891e-a574c3f71bf1","2f02cc61-baed-4516-919b-51ec5118d40a","a08ec5a4-07fc-478b-8ad4-a31688a77b99","213e79a8-0701-4530-a97a-7c03b8181f11","7cd1ad4f-dc96-4d0a-9248-adac0aec4364","cdb61bea-534c-4102-9985-8d4ef80ebe50","57811cfe-7240-400d-810e-1b5037434649","533f7ba3-f0fa-43bb-a357-f978bd891db1","8a249205-0410-4ddd-ab89-733e13823e9f","2c66c599-3f1a-4d02-9c62-f8a655398431","cb7fadaf-8cce-4419-b90c-62504361f69c","d71c49d8-3910-431f-8cdc-c5c3a3baa004","95b53fdb-d268-4288-9cbd-091c82f74ff0","f13e7f02-52f1-4c7e-be78-0210c2de8e18","a7e7376e-3c1f-4c58-8f34-c00f1028756b","d5ecabf5-5921-4eb6-b406-3a00718123fe","3671435b-b701-48b1-ac1a-c83ec923880f","9bf0b3fe-29bf-4520-a4d4-73d8e7c09c03","7a3ea2a8-7971-49ac-8495-c138cf9040a6","d900e61c-1339-4558-b00e-f933a6506939","c14d92be-057f-4c39-a54e-ed9302cd0c84","20c3b784-271c-4810-bcfe-f3f3040ed0cb","be0f5081-6c1a-42bf-8748-bd25dd752005","e5b98534-d375-4b9e-9632-a214bcb53314","5326673c-4785-4e47-96ea-849476e57474","5cf4a585-8baf-4050-bd8d-6beb2ca6bdfb","547450e9-ba8d-4a54-a4d2-68228c40f6ae","ccb6b139-2bb3-42a5-97fe-3de822f9c33e","74287fbf-1e25-41b7-ba76-51b76b2faea3","c6750f09-efc9-4661-9397-2ba9ce893557","7cc9d446-ea0c-4b88-8d2f-e10413578939","bb2200c1-8949-4149-8dfb-89b3040e572b","03bbc2e7-36e9-4a06-8100-2c73fe81e9e1","0a6595a8-bab4-4304-b28c-9bb0fb2810dc","04887fe2-dd11-404c-a692-25fd4552a510","148cd15e-46b4-4867-a75e-1e44251d7d29","39740ba2-dafc-4ee0-8806-569eeb0a20a4","579894c6-c8dd-441e-84ee-9c13856296ac","d616e3c1-df7b-4b44-b9f7-74063c5b6e1e","2eaaf901-9381-40d4-9028-83dc1702f2ad","6bfb9672-f3b1-4130-90ce-ed5784ed070a","8fc68e10-8d95-4a36-8e79-d058ddd413ec","1fe4da40-2338-45fd-aac8-1214852155ce","802a649d-4851-4b60-818d-e1b26b30c080","87b03db8-2496-440d-a758-b5c163dee32d","a9bdc95a-cc37-4d92-8f5e-0bef8e0c9622","7e25ba84-6db9-46f5-81b9-f45153fde82a","fffcecd2-ca50-486d-a35e-f19ddb01c7d5","67cccd18-5374-4a69-8747-c54d141ca7b4","b392bbf2-7313-4133-a363-101435c0ce68","4c5f4160-1248-471f-8124-2e6c7123f637","43adc171-7f05-4ace-8f4a-629fd3128977","37c62fd9-8369-4f36-b8f1-054bce5dae96","05027e48-43b4-444e-8c55-81ead81282a3","b7a15a7c-b0af-4e98-a417-723e8df14812","5c1ca4ca-aebc-4dd4-b1f2-d809829c26f6","3dad5fe1-02af-42d5-be9c-120acf204273","0d337f1c-bf8d-4f16-a4cc-459de6080a2e","0729d336-966a-491a-991b-2b911d2ebfa7","6200cd3e-881b-4be4-a54b-e092ad205ecb","19b25f25-209d-4f44-bd52-a77afee8a626","60ed0dcd-d780-4043-b52b-3edf57fa7603","adfcdcd9-8def-4f8f-8336-27dd6a43771a","64c7869b-c895-4937-a01d-8b9ca0ee24db","f436edb2-898d-411b-afbc-b27e4add13cf","67969c4c-3baa-4be2-9f3f-40c666f148f4","1cbc9f7f-d128-4990-9321-c59fa969074c","8f60ca13-3178-454f-901d-0532acc00dff","c9151a59-a460-4bf5-9d64-8deb3b2dd545","5c705b67-9423-4c0c-ab63-fc4d37995363","ebf70980-8bca-46b0-b58a-2223452f5251","757e3399-1b18-4318-8a2d-a6fecb314825","55bf1693-8294-46da-ab0a-276be520a253","02eef218-27e9-490b-9842-96f734e323c1","bc97a7c8-baca-415f-a044-7b7f59342bde","a4b85fe6-291d-48f9-a005-06f931de192b","08ee444d-63a2-449e-9dfd-4dcfca30fdd7","ac998a31-5ea0-4093-b991-429b439cb531","f2574083-f1d7-4821-9742-b7c8b2545160","f87f4121-ee90-469b-9fe2-6d1c18b3635c","9f75dba8-b8e7-4807-bcf2-65747ec73733","034eacb0-5711-4cbb-9a77-527a924f30b1","7ab42aec-b33e-4adf-a652-1d9132746e2e","624ca864-beb5-4ed9-b1a0-b83d74ce82d1","3ebff142-a65a-4eb6-ac94-d433a5deef8a","fbec24ec-00f0-4776-85a4-d35e1093be49","6a36a24d-d450-40a3-ace6-2252668982a9","983adeab-7744-4981-b482-3820ffc9cb43","baa68462-a9eb-4c6d-9707-7eb3c6c9c5b8","abfb6492-048c-49aa-8fa6-41df79da2186","02208c60-e263-4ca2-a2fb-1b938bc41949","a8b90f10-77d6-4c4f-a612-215afeb584e1","12d36554-89da-4125-a38f-180aba00f437","95b03404-aa40-4916-9612-2abd1d28ff0e","f0deb33f-4bf4-4b85-874a-1dc99c4b3d64","609c14ee-8f2f-43f1-98e8-447a343f5958","ecc09427-2b22-4023-a84a-2dbb683ebea9","a00f696e-5c81-4bd7-863a-ab7ffa74f53b","65039fa4-22a5-4c75-893e-a7a8600523a4","ec2acd84-de4d-4019-b3d5-de34b60e2789","23efff84-d0a9-4928-9d6f-35bacdec4525","cb326d28-17d8-4c0e-897b-077f38e0789a","96988ecb-686a-4b56-b6d2-262c97263198","38d0862a-0d40-4ac6-b376-72288b3adce6","2e4d7d56-eb32-479c-8db8-18110340499d","b19b9852-45c3-4cca-9730-03c0f4dbf30d","8114c440-ff2e-4fa5-b511-cf7158b03c87","474bd724-1171-4824-be15-9dcd785e50b3","a9c45285-85ab-4239-8f32-e7549b9a1dd5","2d147d4f-c8e3-4eea-9381-2c322e5ac567","fa002d00-fe72-404e-8f1b-8b3fb98114f3","4e7264cf-d38b-4e96-bb22-1ff65a8991d6","f6bb1c26-1ee3-4d4e-a1c6-375534cc52c4","vQwXgxJxwnw","wTiHheA40nI","gXY1kx7zlkk","w2BqPnVKVo4","b5p40OuTTW4","-yrLEKjMyrM","NyP-euljCHM","e59hzyoKQCs","5nCbHsCG334","y2NeAef6d30","DBlOJpT9Y1Y","F8cXD5hTt3c","pw7po593hJM","yEb2DX0TzKM","FCvDLjZ6ePM","JGFhHGPxWdk","TEJYev9AvtI","s3TMR9LNs2s","_KtoLPraVA8","tEB1Tccy7lk","Zr6r2GYCr5c","3ZrZAHAaOD4","fBFbEC0IczA","bZvpTAE7NYI","Q3On66u6vAE","zHyvVajsqMw","qa0i8klpl00","ByBVsOcXATE","Wj60irE4rkA","2vtVxIysp38","pm3jRj3cp5c","07r-HDZWRRU","wNcRZxl3B5g","95PyihUy5K4","3iY0P7DhZRs","nVfDfse13es","P7vIRAFSXmk","dXGLftcRHAE","RdunfbobxaY","Aq0JSbuIppQ","F9NekS6PCM0","KuurCxYog5k","AkObfvN3ArI","ZjwrXqjr59A","h_ZpvRjB9JI","PhbVnUBmygA","S2yTcZLOx10","fOXrNuiC-Ps","tJTFw45yddw","eHR2wzsu2Z0","MURXciUA2Do","n2RNRH9zX4c","hkYOwrEhxV4","AJjfEL773Fg","e1yeg1a9b-U","yoEn3bWxHmw","zYuw-8pwnp8","nMkQUlBtFlk","K838Qfp2FXM","Ha6TOLggCXg","8JQM2joOxUY","dzZDjJz77OA","1cAF2zkEv2o","br6ZeWBqCME","lRh2-d8e0vA","I06Cp3i_qI8","ntF_pPp0CZU","lMpTQ6CUMkc","J08Fl0Aq2MM","Xq-71-ag5Q4","Wrljtf3j7dI","UAS4weMb5As","UJoka5j_rUI","2y0sd446dJ0","3Frui3OA9nY","tjxXyAlJvvU","U66kKBK9Eg0","2zlZLPJLc0M","kgbBphp0Dd0","NcZ5lzb7T2w","Yc9TVVvL1ss","O_r6Ne79hMI","upIdZR08D3k","n_MVhE63ZQQ","VnPQ4mLRG-c","hp0PV5T26nE","wXcn7NL-_JI","2966qrVsjEQ","Z5Np1PNp_E4","RECLTp_YxSU","RAHsF4A8GLM","40BEATXkYp8","xrNwmw54SV8","p0tvK8smhrc","7qV7I5DW7uM","IdHkq0N7wJo","w7E_B9aAjnE","Re8mQqbWKGg","jAYnk0JPbSo","UXHDkQQ1ICY","7lUEU18Mq78","wZCUX1PLVwo","0bRmtmaM5C8","HXuj7wAt7u8","ecRk3pd6OAU","WWm9Cp38aQ0","HJTjG6SnX1c","C1_GS0mtxMQ","vhtoOh88VTc","l4kDNUxyS58","0DJcXYs5dtE","T-Xru_225mA","8qkZAWH9Jto","RyEjCcWTh9g","ZALtLBpSeic","x0O96sjbTZs","XJo6jhtSq78","MPGqRL_ochA","0epkO-3wQEw","K9ygSnBSxeM","06mUI1gRMJo","qRcWRXHrg-0","tAefRzPF7XY","NKxAOyQYYcw","iT8W6kaD-RA","SOo4yNoaAoc","hMzfGZnaPN8","fD-rKkoApDc","qDjQUF1K2pQ","ljiQ6H52oKQ","ZSM1w4_DS0E","lBqLz5hvSHA","MubnfJrcKd4","-IPcQvkMJIc","DWsUM2f6GrA","E0JufCTVCMc","DyWMsaXlSjs","fd6QaEJOjvI","bhpd4NeTbCI","5893JBg7r9k","qfeMas1zU6Q"]} \ No newline at end of file diff --git a/history/skip-list.json b/history/skip-list.json new file mode 100644 index 0000000..3b71424 --- /dev/null +++ b/history/skip-list.json @@ -0,0 +1 @@ +{"videoIds":["KX6q6lvoYtM","s7-l7gzm_PE","WovyQkSdONI","KKNGEr7Mc38","bzzFBvzONBo","ENW3PL50yPw","WTQwpuroPjQ","wwX0IgJYejc","RA2cvfdwy0I","dFknx-mRmKE","fenXCK0NO_w","BBKVBFrlnfw","B9udzeRK-vM","i61PKpgE3Ag","rAbJC-Qaw7Q","NEkUNahduWY","CnaegIpkenA","-ahp5X0VchM","n1E9IZfvGMA","pnn_rknhmcg","b7d71665-c736-4bc4-8072-93030cb13995","Zph8_udOKJ0","mMUNkgjwlio","mGohMkkxVj0","f2OyRTu8x3A","5mtuEf3zxTE","s0uiUWsichE","B5dZgGeXA2o","Nq3qLlcbFK0","U1oHRqUkI1E","q-sClVMYY4w","jA8ZQfq_Hzs","Gnl833wXRz0","wPy063-vd1Y","OZDFAvRq7Gc","9ZM9sCfmAGc","3hptKYix4X8","_Q4XT82yd-Q","sEXe-T-5Gn0","iDNlOGn1bTw","5kkIJNUGFho","_Fs5E5pQkLQ","X7ua58iwcd4","1aa14fcc-dd7f-45f6-bcd5-1a956b6383bb","BFt82dw0ci8","pWx_Kp6kliA","CQq3Ocm98sY","POASm17QnRk","9GzlbLIU5dU","8aUBS6z2dSI","5V-q3Sc0UIg","PSDXLvaswTI","2SNyah7nbE8","8JedAJA5AbQ","g81zFbnCZfc","NjdKMaeRBoU","m6kbpZ6JilI","mI30_ueZ7CU","jZfUANjHMF8","ie3wxnhEmYg","EVND2wqKBFE","0D8FwiFj7NM","eAKNfYJB8_c","ZZclhh9Keq8","l1qvUpHzKII","saGaeaMORA4","iCBpYwTxNiw","cf7T0TrgUUU","RUmJxQ3Hi8I","u-vMNzHgSHI","mBE_9vGJBUM","zjcYlEiwnKI","Hom5OMMzOQ0","uhpECa_XaBA","S1rQngjpUdI","9G2MRFs4vac","bdasraPo1Ak","6Uzi0OvFixw","kzWbCF_IkHY","7UeojKTzeHE","Ew0-Lg_Evj0","SaWSPZoPX34","PJh0ygZpQt8","3CZXzp1t9KE","489ca7d9-9a93-4ea4-9c0d-9ee82366f385","VPi_eWiaqdg","JsICN9ZiSjA","cru_4P6qVYQ","PF4dSKK_kww","boJRkecvyCM","xlzThNBFbk8","OnZv124nZqY","idb2PIVLLMs","4e58baFX6Go","XTnYVh7K6xQ","7RHwE_M68BY","rPaWW0IDurI","gaQwwT8Gjx0","vFTEUwYha0A","k8ZpHslhM_c","msygul3QpfU","HiVej9_fvl8","iuPQmw4Ax00","v5T1Q_5C_1w","hTY0ffRlmBQ","el6ObB60Fb4","frhd5xHQ_5Y","AVEZBy1uAk8","dnAMN9Kn8zI","ZJEnQOsMtsU","2wdsNwPUCgQ","6ctOnY1WmBw","MIKej1HCRW0","R8YC8OCnDxM","Httl6Xtf1eQ","G8Tp-3gKvu8","lxiXJKzbcp8","hPPq7NBAOvQ","yAHfG6jU2qA","zy8tpiJCEwk","3KsjuNcxTYA","u4VTFb4awrQ","elhGYEiZ7fw","gzwRflcLPAA","j95uk2BMkug","StQktHtUDbE","3bJHVYa4yMM","DMv1WLvLmQc","kC1NtDZPHuk","9y7TTU1jIvk","RAEW2KlyTy4","3ZVqcW6Wwmg","zA6gyFnlFWc","LioKxZatex0","QPkfVhYlxhE","YG7yFsXctv0","5klhxOKZ_ag","yJUk_pVN9m8","blBlD-mrIoE","L5dPkdmquNk","37LFbhjVNy0","Qbza16Y7owk","e357d703-6660-4bbb-ba40-bb7c401db429","jN6PmHUwrF0","EhEUtqEyM-8","UweigmKvoLs","vqa9qgqhT7E","LCLzgK03CQ0","wsISKLApBbk","6-mEiwe2NhE","c4tvVKDhpiY","vn_kFxqM_gw","rQ21FHpcOnY","0VSOoMuStvg","okEujapROIw","F6i7P-ZP6CY","9FEwl31hGKk","keinLNWVQXM","hnzrPKvRBD8","bHKyg77Cbs4","rjQ1L7gjCxE","lh1ij0ScKfA","dhhVs05qidI","Wh9318EAriE","9cMci6FRdMo","SSya123u9Yk","n2Mf3OotGrQ","2LRzttI1kbI","Y60lUXB8Wd8","4Gmd5UTF4rk","f7481641-a904-4d73-830a-40571b815f7d","IMAxsLAgTSQ","dcTdmQgGLDk","Bf2FIxtiWV8","77CdVSpnUX4","nxEhzsopyxY","cUngseNueP8","xZ4I2aE8zQA","GTI2ObvXMpo"]} \ No newline at end of file diff --git a/history/subscriptions.json b/history/subscriptions.json new file mode 100644 index 0000000..4d40fda --- /dev/null +++ b/history/subscriptions.json @@ -0,0 +1,127 @@ +{ + "subscriptions": [ + { + "id": "sub-1771016441117", + "url": "https://www.youtube.com/@TFTC/streams", + "name": "TFTC", + "createdAt": "2026-02-06T00:00:00.000Z", + "lastChecked": "2026-04-09T19:03:16.671Z", + "paused": false, + "channelId": "UCtdbWsnfA08KhSUO4amVLaQ" + }, + { + "id": "sub-1771016769660", + "url": "https://www.youtube.com/@MartyBentTFTC/videos", + "name": "Marty Bent", + "createdAt": "2026-02-08T00:00:00.000Z", + "lastChecked": "2026-04-09T19:03:25.378Z", + "paused": false, + "channelId": "UCUQcW3jxfQfEUS8kqR5pJtQ" + }, + { + "id": "sub-1771017860588", + "url": "https://www.youtube.com/@thejackmallersshow/streams", + "name": "THE JACK MALLERS SHOW", + "createdAt": "2026-02-01T00:00:00.000Z", + "lastChecked": "2026-04-09T19:03:26.591Z", + "paused": false, + "channelId": "UC3ol9RQbQHqle_Uly6w9LfA" + }, + { + "id": "sub-1771020687575", + "url": "https://www.youtube.com/@Bg2Pod/videos", + "name": "@Bg2Pod", + "createdAt": "2025-10-01T00:00:00.000Z", + "lastChecked": "2026-04-09T19:03:27.833Z", + "paused": false, + "channelId": "UC-yRDvpR99LUc5l7i7jLzew" + }, + { + "id": "sub-1771020804519", + "url": "https://www.youtube.com/@PrestonPysh/videos", + "name": "@PrestonPysh", + "createdAt": "2025-10-01T00:00:00.000Z", + "lastChecked": "2026-04-09T19:04:25.611Z", + "paused": false, + "channelId": "UCLTdCY-fNXc1GqzIuflK-OQ" + }, + { + "id": "sub-1771028164809", + "url": "https://www.youtube.com/@hubermanlab/videos", + "name": "Andrew Huberman", + "channelId": "UC2D2CMWXMOVWx7giW1n3LIg", + "createdAt": "2026-02-01T00:00:00.000Z", + "lastChecked": "2026-04-09T19:04:26.755Z", + "paused": false + }, + { + "id": "sub-1771028433890", + "url": "https://www.youtube.com/@FindingMastery/videos", + "name": "Finding Mastery", + "channelId": "UCSZrR-KiOLjUPbhPoPYCxNQ", + "createdAt": "2026-02-14T00:20:33.890Z", + "lastChecked": "2026-04-09T19:04:35.806Z", + "paused": false + }, + { + "id": "sub-1771030240503", + "url": "https://www.youtube.com/@tetragrammaton_now/videos", + "name": "Tetragrammaton with Rick Rubin", + "type": "youtube", + "channelId": "UC5Gat6FdyiG5ydUUHqPTAEQ", + "createdAt": "2026-02-10T00:00:00.000Z", + "lastChecked": "2026-04-09T19:04:42.980Z", + "paused": false + }, + { + "id": "sub-1771030543882", + "url": "https://serve.podhome.fm/rss/c90e609a-df1e-596a-bd5e-57bcc8aad6cc", + "name": "Citadel Dispatch", + "type": "podcast", + "channelId": null, + "createdAt": "2026-02-08T00:00:00.000Z", + "lastChecked": "2026-04-09T19:04:43.388Z", + "paused": false + }, + { + "id": "sub-1771045539000", + "url": "https://www.youtube.com/@allin/videos", + "name": "All-In Podcast", + "type": "youtube", + "channelId": "UCESLZhusAkFfsNsApnjF_Cg", + "createdAt": "2026-02-13T00:00:00.000Z", + "lastChecked": "2026-04-09T19:04:44.606Z", + "paused": false + }, + { + "id": "sub-1772423650145", + "url": "https://www.youtube.com/@macrovoices7508/videos", + "name": "Macro Voices", + "type": "youtube", + "channelId": "UCICRehoZjq3ZtAWgRJX118A", + "createdAt": "2026-02-02T00:00:00.000Z", + "lastChecked": "2026-04-09T19:04:46.151Z", + "paused": false + }, + { + "id": "sub-1772462897521", + "url": "https://www.youtube.com/@20VC/videos", + "name": "20VC with Harry Stebbings", + "type": "youtube", + "channelId": "UCf0PBRjhf0rF8fWBIxTuoWA", + "createdAt": "2026-02-20T00:00:00.000Z", + "lastChecked": "2026-04-09T19:04:47.083Z", + "paused": false + }, + { + "id": "sub-1773418202833", + "url": "https://www.youtube.com/@ForwardGuidanceBW/videos", + "name": "Forward Guidance", + "type": "youtube", + "channelId": "UCkrwgzhIBKccuDsi_SvZtnQ", + "createdAt": "2026-03-06T00:00:00.000Z", + "lastChecked": "2026-04-09T19:04:48.067Z", + "paused": false + } + ] +} \ No newline at end of file diff --git a/icon.png b/icon.png new file mode 100644 index 0000000..d326778 Binary files /dev/null and b/icon.png differ diff --git a/package.json b/package.json new file mode 100644 index 0000000..0b65712 --- /dev/null +++ b/package.json @@ -0,0 +1,24 @@ +{ + "name": "youtube-summarizer-startos", + "private": true, + "scripts": { + "build": "rm -rf ./javascript && ncc build startos/index.ts -o ./javascript", + "prettier": "prettier --write startos", + "check": "tsc --noEmit" + }, + "dependencies": { + "@start9labs/start-sdk": "1.0.0" + }, + "devDependencies": { + "@types/node": "^22.19.0", + "@vercel/ncc": "^0.38.4", + "prettier": "^3.6.2", + "typescript": "^5.9.3" + }, + "prettier": { + "trailingComma": "all", + "tabWidth": 2, + "semi": false, + "singleQuote": true + } +} diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..392c90f --- /dev/null +++ b/public/index.html @@ -0,0 +1,3680 @@ + + + + + + YouTube Transcript Summarizer + + + + +
+
+ + + + + + + + diff --git a/s9pk.mk b/s9pk.mk new file mode 100644 index 0000000..ee8a215 --- /dev/null +++ b/s9pk.mk @@ -0,0 +1,104 @@ +# ** Plumbing. DO NOT EDIT **. +# This file is imported by ./Makefile. Make edits there + +PACKAGE_ID := $(shell awk -F"'" '/id:/ {print $$2}' startos/manifest/index.ts) +INGREDIENTS := $(shell start-cli s9pk list-ingredients 2>/dev/null) +ARCHES ?= x86 arm +TARGETS ?= arches + +ifdef VARIANT +BASE_NAME := $(PACKAGE_ID)_$(VARIANT) +else +BASE_NAME := $(PACKAGE_ID) +endif + +.PHONY: all arches aarch64 x86_64 riscv64 arm arm64 x86 riscv arch/* clean install check-deps check-init package ingredients +.DELETE_ON_ERROR: +.SECONDARY: + +define SUMMARY + @manifest=$$(start-cli s9pk inspect $(1) manifest); \ + size=$$(du -h $(1) | awk '{print $$1}'); \ + title=$$(printf '%s' "$$manifest" | jq -r .title); \ + version=$$(printf '%s' "$$manifest" | jq -r .version); \ + arches=$$(printf '%s' "$$manifest" | jq -r '[.images[].arch // []] | flatten | unique | join(", ")'); \ + sdkv=$$(printf '%s' "$$manifest" | jq -r .sdkVersion); \ + gitHash=$$(printf '%s' "$$manifest" | jq -r .gitHash | sed -E 's/(.*-modified)$$/\x1b[0;31m\1\x1b[0m/'); \ + printf "\n"; \ + printf "\033[1;32m✅ Build Complete!\033[0m\n"; \ + printf "\n"; \ + printf "\033[1;37m📦 $$title\033[0m \033[36mv$$version\033[0m\n"; \ + printf "───────────────────────────────\n"; \ + printf " \033[1;36mFilename:\033[0m %s\n" "$(1)"; \ + printf " \033[1;36mSize:\033[0m %s\n" "$$size"; \ + printf " \033[1;36mArch:\033[0m %s\n" "$$arches"; \ + printf " \033[1;36mSDK:\033[0m %s\n" "$$sdkv"; \ + printf " \033[1;36mGit:\033[0m %s\n" "$$gitHash"; \ + echo "" +endef + +all: $(TARGETS) + +arches: $(ARCHES) + +universal: $(BASE_NAME).s9pk + $(call SUMMARY,$<) + +arch/%: $(BASE_NAME)_%.s9pk + $(call SUMMARY,$<) + +x86 x86_64: arch/x86_64 +arm arm64 aarch64: arch/aarch64 +riscv riscv64: arch/riscv64 + +$(BASE_NAME).s9pk: $(INGREDIENTS) .git/HEAD .git/index + @$(MAKE) --no-print-directory ingredients + @echo " Packing '$@'..." + start-cli s9pk pack -o $@ + +$(BASE_NAME)_%.s9pk: $(INGREDIENTS) .git/HEAD .git/index + @$(MAKE) --no-print-directory ingredients + @echo " Packing '$@'..." + start-cli s9pk pack --arch=$* -o $@ + +ingredients: $(INGREDIENTS) + @echo " Re-evaluating ingredients..." + +install: | check-deps check-init + @HOST=$$(awk -F'/' '/^host:/ {print $$3}' ~/.startos/config.yaml); \ + if [ -z "$$HOST" ]; then \ + echo "Error: You must define \"host: http://server-name.local\" in ~/.startos/config.yaml"; \ + exit 1; \ + fi; \ + S9PK=$$(ls -t *.s9pk 2>/dev/null | head -1); \ + if [ -z "$$S9PK" ]; then \ + echo "Error: No .s9pk file found. Run 'make' first."; \ + exit 1; \ + fi; \ + printf "\n🚀 Installing %s to %s ...\n" "$$S9PK" "$$HOST"; \ + start-cli package install -s "$$S9PK" + +check-deps: + @command -v start-cli >/dev/null || \ + (echo "Error: start-cli not found. Please see https://docs.start9.com/packaging/0.4.0.x/environment-setup.html" && exit 1) + @command -v npm >/dev/null || \ + (echo "Error: npm not found. Please install Node.js and npm." && exit 1) + +check-init: + @if [ ! -f ~/.startos/developer.key.pem ]; then \ + echo "Initializing StartOS developer environment..."; \ + start-cli init-key; \ + fi + +javascript/index.js: $(shell find startos -type f) tsconfig.json node_modules + npm run build + +node_modules: package-lock.json + npm ci + +package-lock.json: package.json + npm i + +clean: + @echo "Cleaning up build artifacts..." + @rm -rf $(PACKAGE_ID).s9pk $(PACKAGE_ID)_x86_64.s9pk $(PACKAGE_ID)_aarch64.s9pk $(PACKAGE_ID)_riscv64.s9pk javascript node_modules diff --git a/server/index.js b/server/index.js new file mode 100644 index 0000000..ae76c4c --- /dev/null +++ b/server/index.js @@ -0,0 +1,2621 @@ +import express from "express"; +import cors from "cors"; +import { execFile } from "child_process"; +import { promisify } from "util"; +import fs from "fs/promises"; +import { createWriteStream } from "fs"; +import path from "path"; +import os from "os"; +import https from "https"; +import http from "http"; +import { GoogleGenAI } from "@google/genai"; + +const execFileAsync = promisify(execFile); +const app = express(); +const PORT = process.env.PORT || 3001; + +// ── Data directory (configurable for StartOS or local dev) ──────────────── +// On StartOS: DATA_DIR=/data (persistent volume) +// On local dev: defaults to project root (parent of server/) +const __dirname = path.dirname(new URL(import.meta.url).pathname); +const DATA_DIR = process.env.DATA_DIR || path.join(__dirname, ".."); +const historyDir = path.join(DATA_DIR, "history"); +const configDir = path.join(DATA_DIR, "config"); +await fs.mkdir(historyDir, { recursive: true }).catch(() => {}); +await fs.mkdir(configDir, { recursive: true }).catch(() => {}); + +// ── Server-side API key (shared across all clients) ─────────────────────── +// Priority: GEMINI_API_KEY env var → StartOS config → .env file +let serverApiKey = process.env.GEMINI_API_KEY || ""; +const envPath = path.join(DATA_DIR, ".env"); +if (!serverApiKey) { + // Try StartOS config file + try { + const configContent = await fs.readFile(path.join(configDir, "startos-config.json"), "utf-8").catch(() => "{}"); + const config = JSON.parse(configContent); + if (config.gemini_api_key) serverApiKey = config.gemini_api_key; + } catch {} +} +if (!serverApiKey) { + // Fall back to .env file + try { + const envContent = await fs.readFile(envPath, "utf-8").catch(() => ""); + const match = envContent.match(/^GEMINI_API_KEY=(.+)$/m); + if (match) serverApiKey = match[1].trim().replace(/^["']|["']$/g, ""); + } catch {} +} + +// ── YouTube cookies (bypass bot detection) ────────────────────────────── +// Priority: 1) cookies.txt file 2) --cookies-from-browser (local dev only) 3) no cookies +// On StartOS: cookies.txt lives in DATA_DIR +// On local dev: cookies.txt in project root, or --cookies-from-browser via YT_COOKIES_FROM +let ytCookiesBrowser = ""; +const ytCookiesFilePath = path.join(DATA_DIR, "cookies.txt"); +let ytCookiesFileExists = false; +try { + const envContent2 = await fs.readFile(envPath, "utf-8").catch(() => ""); + const cm = envContent2.match(/^YT_COOKIES_FROM=(.+)$/m); + if (cm) ytCookiesBrowser = cm[1].trim().replace(/^["']|["']$/g, "").toLowerCase(); +} catch {} +try { + await fs.access(ytCookiesFilePath); + ytCookiesFileExists = true; + console.log(" 🍪 Found cookies.txt — will use for YouTube authentication"); +} catch { + ytCookiesFileExists = false; +} + +function ytCookieArgs() { + // Prefer cookies.txt file (stable, doesn't depend on browser session) + if (ytCookiesFileExists) return ["--cookies", ytCookiesFilePath]; + // Fall back to live browser cookies (local dev only, not available on StartOS) + if (ytCookiesBrowser) return ["--cookies-from-browser", ytCookiesBrowser]; + return []; +} + +// Extra yt-dlp args for robustness (browser impersonation, rate limiting) +function ytExtraArgs() { + const args = []; + // Browser impersonation helps avoid TLS fingerprint detection on servers + args.push("--impersonate", "chrome"); + // Sleep between requests to avoid rate limiting during batch operations + args.push("--sleep-interval", "1", "--max-sleep-interval", "3"); + return args; +} + +function ytCookieMethod() { + if (ytCookiesFileExists) return "cookies.txt"; + if (ytCookiesBrowser) return ytCookiesBrowser; + return "none"; +} + +function resolveApiKey(clientKey) { + // Client can send "USE_SERVER_KEY" or empty to use the server's stored key + if (!clientKey || clientKey === "USE_SERVER_KEY") return serverApiKey; + return clientKey; +} + +app.use(cors()); +app.use(express.json({ limit: "100mb" })); + +// ── History storage ─────────────────────────────────────────────────────── + +async function saveToHistory(videoId, url, title, chunks, entries, logs, uploadDate, type) { + // For podcast episodes, videoId might be a long GUID/URL — use a short hash for the filename + const idSuffix = type === "podcast" ? Buffer.from(videoId).toString("base64url").slice(0, 16) : videoId; + const id = `${Date.now()}-${idSuffix}`; + const record = { + id, + videoId, + url, + title: title || "Untitled", + type: type || "youtube", // "youtube" or "podcast" + topicCount: chunks.length, + segmentCount: entries.length, + createdAt: new Date().toISOString(), + uploadDate: uploadDate || "", + chunks, + entries, + logs, + }; + await fs.writeFile(path.join(historyDir, `${id}.json`), JSON.stringify(record)); + return id; +} + +// Serve the frontend from ../public +app.use(express.static(path.join(__dirname, "..", "public"))); +app.use("/assets", express.static(path.join(__dirname, "..", "assets"))); + +// ── yt-dlp auto-update ───────────────────────────────────────────────────── + +let ytdlpVersion = null; +let ytdlpLastCheck = 0; +const UPDATE_CHECK_INTERVAL = 24 * 60 * 60 * 1000; // 24 hours + +async function checkYtdlp() { + const info = { installed: false, version: null, updateAvailable: false, latestVersion: null }; + try { + const { stdout } = await execFileAsync("yt-dlp", ["--version"]); + info.installed = true; + info.version = stdout.trim(); + ytdlpVersion = info.version; + } catch { + return info; + } + + // Check for updates at most once per 24h + const now = Date.now(); + if (now - ytdlpLastCheck > UPDATE_CHECK_INTERVAL) { + ytdlpLastCheck = now; + try { + const resp = await fetch("https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest", { + headers: { "Accept": "application/vnd.github.v3+json" }, + signal: AbortSignal.timeout(5000), + }); + if (resp.ok) { + const data = await resp.json(); + info.latestVersion = data.tag_name?.replace(/^v/, "") || null; + if (info.latestVersion && info.version !== info.latestVersion) { + info.updateAvailable = true; + } + } + } catch {} // Network errors are fine, just skip the check + } + return info; +} + +async function autoUpdateYtdlp() { + console.log(" ↻ Updating yt-dlp..."); + + // Strategy 1: yt-dlp's built-in self-update + try { + const { stdout } = await execFileAsync("yt-dlp", ["-U"], { timeout: 60000 }); + console.log(` ${stdout.trim()}`); + return { success: true, message: stdout.trim() }; + } catch (e1) { + console.log(" … Self-update failed, trying pip..."); + } + + // Strategy 2: pip3 / pip (works in containers and on macOS) + for (const pip of ["pip3", "pip"]) { + try { + await execFileAsync(pip, ["install", "-U", "yt-dlp"], { timeout: 120000 }); + console.log(` ✓ Updated via ${pip}`); + return { success: true, message: `Updated via ${pip}` }; + } catch {} + } + + // Strategy 3: Homebrew (macOS local dev only) + try { + await execFileAsync("brew", ["upgrade", "yt-dlp"], { timeout: 120000 }); + console.log(" ✓ Updated via Homebrew"); + return { success: true, message: "Updated via Homebrew" }; + } catch {} + + // Strategy 4: Direct binary download to persistent storage (StartOS fallback) + try { + const binDir = path.join(DATA_DIR, "bin"); + await fs.mkdir(binDir, { recursive: true }); + const binPath = path.join(binDir, "yt-dlp"); + console.log(" … Trying direct binary download..."); + const { stdout } = await execFileAsync("sh", ["-c", + `curl -L -o "${binPath}" "https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp" && chmod +x "${binPath}" && "${binPath}" --version` + ], { timeout: 120000 }); + console.log(` ✓ Downloaded yt-dlp binary: ${stdout.trim()}`); + return { success: true, message: `Downloaded binary: ${stdout.trim()}` }; + } catch (e4) { + console.log(" ✗ All update strategies failed"); + return { success: false, message: "Auto-update failed. Try updating manually from the StartOS Actions menu." }; + } +} + +// ── Pricing (per 1M tokens) ─────────────────────────────────────────────── + +const PRICING = { + "gemini-3-flash-preview": { input: 0.50, output: 3.00, thinking: 3.00 }, + "gemini-3-pro-preview": { input: 2.00, output: 12.00, thinking: 12.00 }, + "gemini-3.1-pro-preview": { input: 2.00, output: 12.00, thinking: 12.00 }, + "gemini-2.5-flash": { input: 0.15, output: 0.60, thinking: 0.60 }, + // Fallback for unknown models + "default": { input: 1.00, output: 5.00, thinking: 5.00 }, +}; + +function calcCost(modelName, usage) { + const rates = PRICING[modelName] || PRICING["default"]; + const inputTokens = usage.promptTokenCount || 0; + const outputTokens = usage.candidatesTokenCount || 0; + const thinkingTokens = usage.thoughtsTokenCount || 0; + + const inputCost = (inputTokens / 1_000_000) * rates.input; + const outputCost = (outputTokens / 1_000_000) * rates.output; + const thinkingCost = (thinkingTokens / 1_000_000) * rates.thinking; + const totalCost = inputCost + outputCost + thinkingCost; + + return { + inputTokens, + outputTokens, + thinkingTokens, + totalTokens: usage.totalTokenCount || (inputTokens + outputTokens + thinkingTokens), + inputCost: inputCost.toFixed(6), + outputCost: outputCost.toFixed(6), + thinkingCost: thinkingCost.toFixed(6), + totalCost: totalCost.toFixed(6), + totalCostDisplay: totalCost < 0.01 ? `$${(totalCost * 100).toFixed(3)}¢` : `$${totalCost.toFixed(4)}`, + }; +} + +// ── Safe text extraction from Gemini responses ────────────────────────── + +function safeText(result) { + // The Gemini SDK .text getter can throw or return undefined + try { + if (result.text) return result.text; + } catch {} + // Fallback: dig into candidates manually + try { + const parts = result?.candidates?.[0]?.content?.parts; + if (parts) return parts.map(p => p.text || "").join(""); + } catch {} + return ""; +} + +// ── Retry helper for transient Gemini API errors ────────────────────────── + +async function retryGemini(fn, { retries = 3, delayMs = 3000, label = "Gemini call", log: logFn } = {}) { + for (let attempt = 1; attempt <= retries; attempt++) { + try { + return await fn(); + } catch (err) { + const msg = err?.message || String(err); + const status = err?.status || err?.httpStatusCode || 0; + const isRetryable = status === 503 || status === 429 || /overloaded|unavailable|capacity|high demand|rate limit|fetch failed|ECONNRESET|ETIMEDOUT|socket hang up|network/i.test(msg); + if (isRetryable && attempt < retries) { + const waitSec = (delayMs * attempt / 1000).toFixed(0); + if (logFn) logFn(`⚠ ${label} failed (${status || "error"}), retrying in ${waitSec}s... (attempt ${attempt}/${retries})`); + await new Promise(r => setTimeout(r, delayMs * attempt)); + } else { + throw err; + } + } + } +} + +// ── Health check ─────────────────────────────────────────────────────────── + +app.get("/api/health", async (req, res) => { + const info = await checkYtdlp(); + // Check cookies.txt freshness + let cookieInfo = { method: ytCookieMethod() }; + if (ytCookiesFileExists) { + try { + const stat = await fs.stat(ytCookiesFilePath); + const ageMs = Date.now() - stat.mtimeMs; + const ageDays = Math.floor(ageMs / (1000 * 60 * 60 * 24)); + cookieInfo.fileAgeDays = ageDays; + cookieInfo.fileExpiring = ageDays > 12; // cookies typically expire after ~14 days + } catch {} + } + res.json({ ok: true, ytdlp: info.installed, hasServerKey: !!serverApiKey, cookies: cookieInfo, ...info }); +}); + +// ── Status endpoints ─────────────────────────────────────────────────────── + +app.post("/api/heartbeat", (req, res) => { + res.json({ ok: true, sleeping: false }); +}); + +app.get("/api/status", (req, res) => { + res.json({ ok: true, sleeping: false, uptime: process.uptime() }); +}); + +// Shutdown: used by the macOS .app launcher to stop the server cleanly. +// On StartOS this endpoint is unused (StartOS manages the container lifecycle). +app.post("/api/shutdown", (req, res) => { + res.json({ ok: true, message: "Server shutting down..." }); + console.log("\n Server shutdown requested from browser. Goodbye!\n"); + setTimeout(() => process.exit(0), 300); +}); + +// ── Manual update endpoint ───────────────────────────────────────────────── + +app.post("/api/update-ytdlp", async (req, res) => { + const result = await autoUpdateYtdlp(); + const info = await checkYtdlp(); + res.json({ ...result, ...info }); +}); + +// ── Cookie management endpoints ─────────────────────────────────────────── + +// Upload cookies.txt content +app.post("/api/cookies/upload", express.text({ type: "*/*", limit: "2mb" }), async (req, res) => { + try { + const content = req.body; + if (!content || typeof content !== "string" || content.length < 20) { + return res.status(400).json({ error: "Invalid cookie file content" }); + } + // Basic validation: should look like a Netscape cookie file + const firstLine = content.split("\n")[0].trim(); + const looksValid = /^#.*cookie|^#.*http|^\./i.test(firstLine) || content.includes("\tTRUE\t") || content.includes("\tFALSE\t"); + if (!looksValid) { + return res.status(400).json({ error: "File doesn't look like a valid Netscape cookies.txt file. The first line should start with '# Netscape HTTP Cookie File' or '# HTTP Cookie File'." }); + } + await fs.writeFile(ytCookiesFilePath, content, "utf-8"); + ytCookiesFileExists = true; + console.log(" 🍪 cookies.txt uploaded via web UI"); + res.json({ ok: true, message: "Cookies saved successfully" }); + } catch (err) { + res.status(500).json({ error: err.message }); + } +}); + +// Delete cookies.txt +app.post("/api/cookies/delete", async (req, res) => { + try { + await fs.unlink(ytCookiesFilePath).catch(() => {}); + ytCookiesFileExists = false; + console.log(" 🍪 cookies.txt deleted via web UI"); + res.json({ ok: true }); + } catch (err) { + res.status(500).json({ error: err.message }); + } +}); + +// Test if cookies work by trying a lightweight yt-dlp operation +app.post("/api/cookies/test", async (req, res) => { + try { + const cookieArgs = ytCookieArgs(); + if (cookieArgs.length === 0) { + return res.json({ ok: false, error: "No cookies configured" }); + } + // Try to fetch title of a known video — lightweight, no download + const { stdout } = await execFileAsync("yt-dlp", [ + "--print", "%(title)s", + "--no-download", + ...cookieArgs, + "https://www.youtube.com/watch?v=dQw4w9WgXcQ", // well-known test video + ], { timeout: 20000 }); + const title = stdout.trim(); + if (title && title.length > 0) { + res.json({ ok: true, message: `Cookies working! Fetched: "${title}"` }); + } else { + res.json({ ok: false, error: "yt-dlp returned empty response" }); + } + } catch (err) { + const msg = (err.stderr || "") + " " + (err.message || ""); + const isAuth = /Sign in|bot|403/i.test(msg); + res.json({ ok: false, error: isAuth ? "Cookies are expired or invalid — YouTube still requires sign-in" : msg.slice(0, 300) }); + } +}); + +// Get cookie status +app.get("/api/cookies/status", async (req, res) => { + const info = { method: ytCookieMethod() }; + if (ytCookiesFileExists) { + try { + const stat = await fs.stat(ytCookiesFilePath); + info.fileAgeDays = Math.floor((Date.now() - stat.mtimeMs) / (1000 * 60 * 60 * 24)); + info.fileExpiring = info.fileAgeDays > 12; + info.fileSize = stat.size; + } catch {} + } + res.json(info); +}); + +// ── OAuth2 YouTube authentication (headless / StartOS) ──────────────────── +// Uses yt-dlp's built-in OAuth2 device flow: user enters a code on any browser, +// token is cached in yt-dlp's cache dir (persisted on /data volume). + +let oauthInProgress = false; +let oauthDeviceCode = null; +let oauthVerifyUrl = null; + +// Check if OAuth token already exists in yt-dlp cache +app.get("/api/auth/oauth/status", async (req, res) => { + // yt-dlp stores OAuth tokens in its cache dir + const cacheDir = process.env.XDG_CACHE_HOME || path.join(DATA_DIR, "ytdlp-cache"); + let hasToken = false; + try { + const files = await fs.readdir(path.join(cacheDir, "yt-dlp"), { recursive: true }).catch(() => []); + hasToken = files.some(f => f.includes("oauth") || f.includes("token")); + } catch {} + + res.json({ + hasToken, + hasCookies: ytCookiesFileExists, + cookieMethod: ytCookieMethod(), + inProgress: oauthInProgress, + deviceCode: oauthInProgress ? oauthDeviceCode : null, + verifyUrl: oauthInProgress ? oauthVerifyUrl : null, + }); +}); + +// Initiate OAuth2 device code flow +app.post("/api/auth/oauth/start", async (req, res) => { + if (oauthInProgress) { + return res.json({ ok: true, message: "OAuth flow already in progress", deviceCode: oauthDeviceCode, verifyUrl: oauthVerifyUrl }); + } + + oauthInProgress = true; + oauthDeviceCode = null; + oauthVerifyUrl = null; + + res.json({ ok: true, message: "OAuth flow started. Check /api/auth/oauth/status for the device code." }); + + // Run yt-dlp in background — it will output the device code to stderr + (async () => { + try { + const cacheDir = path.join(DATA_DIR, "ytdlp-cache"); + await fs.mkdir(cacheDir, { recursive: true }); + + const proc = execFile("yt-dlp", [ + "--username", "oauth", + "--password", "", + "--cache-dir", path.join(cacheDir, "yt-dlp"), + "--print", "%(title)s", + "--no-download", + "https://www.youtube.com/watch?v=dQw4w9WgXcQ", + ], { timeout: 300000, env: { ...process.env, XDG_CACHE_HOME: cacheDir } }); + + let stderrBuf = ""; + proc.stderr?.on("data", (chunk) => { + stderrBuf += chunk.toString(); + // Look for the device code pattern in yt-dlp output + const codeMatch = stderrBuf.match(/go to\s+(https?:\/\/\S+)\s+.*?enter.*?code[:\s]+([A-Z0-9-]+)/i); + if (codeMatch) { + oauthVerifyUrl = codeMatch[1]; + oauthDeviceCode = codeMatch[2]; + console.log(` 🔑 OAuth device code: ${oauthDeviceCode} — verify at ${oauthVerifyUrl}`); + } + }); + + await new Promise((resolve, reject) => { + proc.on("close", (code) => { + if (code === 0) resolve(); + else reject(new Error(`yt-dlp exited with code ${code}: ${stderrBuf.slice(-300)}`)); + }); + proc.on("error", reject); + }); + + console.log(" ✓ OAuth token cached successfully"); + } catch (err) { + console.error(" ⚠ OAuth flow failed:", err.message); + } finally { + oauthInProgress = false; + } + })(); +}); + +// ── History endpoints ───────────────────────────────────────────────────── + +const metaPath = path.join(historyDir, "_meta.json"); + +// meta.json structure: { folders: [ { id, name, order, items: [sessionId, ...] } ], uncategorized: [sessionId, ...] } +async function loadMeta() { + try { + return JSON.parse(await fs.readFile(metaPath, "utf-8")); + } catch { + return { folders: [], uncategorized: [] }; + } +} +async function saveMeta(meta) { + await fs.writeFile(metaPath, JSON.stringify(meta, null, 2)); +} + +// Get all history: sessions + folder structure +app.get("/api/history", async (req, res) => { + try { + const files = await fs.readdir(historyDir); + const sessionsMap = {}; + for (const file of files.filter(f => f.endsWith(".json") && !f.startsWith("_") && f !== "subscriptions.json" && f !== "skip-list.json" && f !== "seen-list.json" && f !== "auto-queue.json")) { + try { + const raw = await fs.readFile(path.join(historyDir, file), "utf-8"); + const data = JSON.parse(raw); + sessionsMap[data.id] = { + id: data.id, videoId: data.videoId, url: data.url, + title: data.title, topicCount: data.topicCount, + type: data.type || "youtube", + segmentCount: data.segmentCount, createdAt: data.createdAt, + uploadDate: data.uploadDate || "", + }; + } catch {} + } + + const meta = await loadMeta(); + + // Clean up: remove references to deleted sessions + for (const folder of meta.folders) { + folder.items = folder.items.filter(id => sessionsMap[id]); + } + meta.uncategorized = meta.uncategorized.filter(id => sessionsMap[id]); + + // Add any sessions not in meta (newly created) + const allReferenced = new Set([ + ...meta.uncategorized, + ...meta.folders.flatMap(f => f.items), + ]); + const allIds = Object.keys(sessionsMap); + const orphans = allIds.filter(id => !allReferenced.has(id)) + .sort((a, b) => new Date(sessionsMap[b].createdAt) - new Date(sessionsMap[a].createdAt)); + meta.uncategorized = [...orphans, ...meta.uncategorized]; + + await saveMeta(meta); + res.json({ sessions: sessionsMap, meta }); + } catch (err) { + res.json({ sessions: {}, meta: { folders: [], uncategorized: [] } }); + } +}); + +// Get a single session (full data) +app.get("/api/history/:id", async (req, res) => { + try { + const raw = await fs.readFile(path.join(historyDir, `${req.params.id}.json`), "utf-8"); + res.json(JSON.parse(raw)); + } catch { + res.status(404).json({ error: "Session not found" }); + } +}); + +// Rename a session title +app.put("/api/history/:id/title", async (req, res) => { + try { + const filePath = path.join(historyDir, `${req.params.id}.json`); + const raw = await fs.readFile(filePath, "utf-8"); + const data = JSON.parse(raw); + data.title = req.body.title || data.title; + await fs.writeFile(filePath, JSON.stringify(data)); + res.json({ ok: true, title: data.title }); + } catch { + res.status(404).json({ error: "Session not found" }); + } +}); + +// Delete a session +app.delete("/api/history/:id", async (req, res) => { + try { + // Read the file first to get the videoId for the skip list + const filePath = path.join(historyDir, `${req.params.id}.json`); + let videoId = null; + try { + const raw = await fs.readFile(filePath, "utf-8"); + videoId = JSON.parse(raw).videoId; + } catch {} + + await fs.unlink(filePath); + + // Add to skip list so subscriptions don't re-queue it + if (videoId) { + await addToSkipList(videoId); + } + + // Remove from meta + const meta = await loadMeta(); + meta.uncategorized = meta.uncategorized.filter(id => id !== req.params.id); + for (const folder of meta.folders) { + folder.items = folder.items.filter(id => id !== req.params.id); + } + await saveMeta(meta); + res.json({ ok: true }); + } catch { + res.status(404).json({ error: "Session not found" }); + } +}); + +// Update meta (folders, ordering) — the frontend sends the full structure +app.put("/api/history/meta", async (req, res) => { + try { + const meta = req.body; + await saveMeta(meta); + res.json({ ok: true }); + } catch (err) { + res.status(500).json({ error: err.message }); + } +}); + +// Create a folder +app.post("/api/history/folders", async (req, res) => { + try { + const meta = await loadMeta(); + const folder = { id: `folder-${Date.now()}`, name: req.body.name || "New Folder", items: [] }; + meta.folders.push(folder); + await saveMeta(meta); + res.json(folder); + } catch (err) { + res.status(500).json({ error: err.message }); + } +}); + +// Rename a folder +app.put("/api/history/folders/:id", async (req, res) => { + try { + const meta = await loadMeta(); + const folder = meta.folders.find(f => f.id === req.params.id); + if (!folder) return res.status(404).json({ error: "Folder not found" }); + folder.name = req.body.name || folder.name; + await saveMeta(meta); + res.json(folder); + } catch (err) { + res.status(500).json({ error: err.message }); + } +}); + +// Delete a folder (items move to uncategorized) +app.delete("/api/history/folders/:id", async (req, res) => { + try { + const meta = await loadMeta(); + const idx = meta.folders.findIndex(f => f.id === req.params.id); + if (idx === -1) return res.status(404).json({ error: "Folder not found" }); + const [folder] = meta.folders.splice(idx, 1); + meta.uncategorized = [...folder.items, ...meta.uncategorized]; + await saveMeta(meta); + res.json({ ok: true }); + } catch (err) { + res.status(500).json({ error: err.message }); + } +}); + +// Move a session to a folder (or uncategorized if folderId is null) +app.put("/api/history/move", async (req, res) => { + try { + const { sessionId, folderId, index } = req.body; + const meta = await loadMeta(); + + // Remove from current location + meta.uncategorized = meta.uncategorized.filter(id => id !== sessionId); + for (const folder of meta.folders) { + folder.items = folder.items.filter(id => id !== sessionId); + } + + // Add to new location + if (folderId) { + const folder = meta.folders.find(f => f.id === folderId); + if (folder) { + const i = typeof index === "number" ? index : folder.items.length; + folder.items.splice(i, 0, sessionId); + } + } else { + const i = typeof index === "number" ? index : 0; + meta.uncategorized.splice(i, 0, sessionId); + } + + await saveMeta(meta); + res.json({ ok: true }); + } catch (err) { + res.status(500).json({ error: err.message }); + } +}); + +// ── Subscriptions ───────────────────────────────────────────────────────── + +const subsPath = path.join(historyDir, "subscriptions.json"); + +async function loadSubscriptions() { + try { + return JSON.parse(await fs.readFile(subsPath, "utf-8")).subscriptions || []; + } catch { + return []; + } +} +async function saveSubscriptions(subs) { + await fs.writeFile(subsPath, JSON.stringify({ subscriptions: subs }, null, 2)); +} + +// List recent videos from a channel/playlist via yt-dlp (no download) +// Uses --flat-playlist for speed; returns id + title (no upload_date in flat mode) +async function listChannelVideosFast(url, limit = 15) { + const { stdout } = await execFileAsync("yt-dlp", [ + "--print", "%(id)s|%(title)s", + "--no-download", + "--playlist-end", String(limit), + "--flat-playlist", + ...ytCookieArgs(), + ...ytExtraArgs(), + url, + ], { timeout: 60000 }); + return stdout.trim().split("\n").filter(Boolean).map(line => { + const idx = line.indexOf("|"); + return { id: line.slice(0, idx), title: line.slice(idx + 1) }; + }); +} + +// Fetch upload_date for a batch of video IDs (processes in batches of 3) +// Bails after 2 consecutive failures to avoid grinding through blocked requests +async function fetchUploadDates(videoIds) { + if (videoIds.length === 0) return {}; + const dateMap = {}; + const batchSize = 50; + let consecutiveFails = 0; + for (let i = 0; i < videoIds.length; i += batchSize) { + const batch = videoIds.slice(i, i + batchSize); + const urls = batch.map(id => `https://www.youtube.com/watch?v=${id}`); + try { + const { stdout } = await execFileAsync("yt-dlp", [ + "--print", "%(id)s|%(upload_date)s", + "--no-download", + ...ytCookieArgs(), + ...urls, + ], { timeout: 45000 }); + for (const line of stdout.trim().split("\n").filter(Boolean)) { + const [id, date] = line.split("|"); + if (id && date && date !== "NA") dateMap[id] = date; + } + consecutiveFails = 0; + subLog(` Batch ${Math.floor(i/batchSize)+1}: got dates for ${batch.length} video(s)`); + } catch (err) { + consecutiveFails++; + subLog(` ⚠ Batch ${Math.floor(i/batchSize)+1} failed: ${err.message.slice(0, 80)}`); + if (consecutiveFails >= 2) { + subLog(` ⚠ 2 consecutive failures — aborting yt-dlp date fetch (bot detection likely)`); + break; + } + } + } + return dateMap; +} + +// ── RSS-based date fetching (bypasses bot detection) ───────────────────── + +// Fetch a URL and return the response body as a string +function fetchUrl(url) { + return new Promise((resolve, reject) => { + https.get(url, (res) => { + if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) { + return fetchUrl(res.headers.location).then(resolve, reject); + } + let data = ""; + res.on("data", (chunk) => (data += chunk)); + res.on("end", () => resolve(data)); + res.on("error", reject); + }).on("error", reject); + }); +} + +// Get channel_id from a YouTube channel/playlist URL using yt-dlp +async function getChannelId(url) { + // Method 1: flat-playlist channel_id (fast, may return NA) + try { + const { stdout } = await execFileAsync("yt-dlp", [ + "--print", "%(channel_id)s", + "--no-download", + "--playlist-items", "1", + "--flat-playlist", + ...ytCookieArgs(), + url, + ], { timeout: 15000 }); + const id = stdout.trim().split("\n")[0]; + if (id && id !== "NA" && id.length > 5) return id; + } catch {} + // Method 2: non-flat single video (slower but gets full metadata) + try { + const { stdout } = await execFileAsync("yt-dlp", [ + "--print", "%(channel_id)s", + "--no-download", + "--playlist-items", "1", + ...ytCookieArgs(), + url, + ], { timeout: 30000 }); + const id = stdout.trim().split("\n")[0]; + if (id && id !== "NA" && id.length > 5) return id; + } catch {} + return null; +} + +// Fetch video dates from YouTube RSS feed (no auth, no bot detection) +// Returns { videoId: "YYYYMMDD", ... } for up to 15 most recent videos +async function fetchDatesFromRSS(channelId) { + const dateMap = {}; + if (!channelId) return dateMap; + try { + const rssUrl = `https://www.youtube.com/feeds/videos.xml?channel_id=${channelId}`; + const xml = await fetchUrl(rssUrl); + const entryRegex = /[\s\S]*?([^<]+)<\/yt:videoId>[\s\S]*?([^<]+)<\/published>[\s\S]*?<\/entry>/g; + let match; + while ((match = entryRegex.exec(xml)) !== null) { + const videoId = match[1]; + const published = match[2]; // e.g. "2025-12-01T18:00:00+00:00" + const date = published.slice(0, 10).replace(/-/g, ""); // "20251201" + dateMap[videoId] = date; + } + } catch (err) { + subLog(` ⚠ RSS feed fetch failed: ${err.message}`); + } + return dateMap; +} + +// ── Podcast RSS feed parsing ──────────────────────────────────────────────── + +// Detect if a URL looks like a podcast RSS feed +function isPodcastFeedUrl(url) { + if (!url) return false; + const u = url.trim().toLowerCase(); + // Common podcast RSS feed patterns + if (u.includes("/feed") || u.includes("/rss") || u.includes("feeds.") || u.includes(".xml")) return true; + if (u.includes("anchor.fm") || u.includes("feeds.buzzsprout") || u.includes("feeds.simplecast")) return true; + if (u.includes("feeds.megaphone") || u.includes("feeds.transistor") || u.includes("feeds.libsyn")) return true; + if (u.includes("feeds.podcastmirror") || u.includes("feeds.acast") || u.includes("feeds.fireside")) return true; + if (u.includes("rss.art19") || u.includes("podbean.com/feed")) return true; + return false; +} + +// Fetch and parse a podcast RSS feed → returns { title, episodes: [{ id, title, date, audioUrl, duration }] } +async function parsePodcastRSS(feedUrl, limit = 200) { + const xml = await fetchUrl(feedUrl); + + // Extract podcast title + const titleMatch = xml.match(/[\s\S]*?(?:<!\[CDATA\[)?(.*?)(?:\]\]>)?<\/title>/); + const podcastTitle = titleMatch ? titleMatch[1].trim() : "Unknown Podcast"; + + // Extract episodes from <item> elements + const episodes = []; + const itemRegex = /<item>([\s\S]*?)<\/item>/g; + let match; + while ((match = itemRegex.exec(xml)) !== null && episodes.length < limit) { + const item = match[1]; + + // GUID (unique episode identifier) + const guidMatch = item.match(/<guid[^>]*>(?:<!\[CDATA\[)?(.*?)(?:\]\]>)?<\/guid>/); + const guid = guidMatch ? guidMatch[1].trim() : null; + + // Title + const epTitleMatch = item.match(/<title>(?:<!\[CDATA\[)?(.*?)(?:\]\]>)?<\/title>/); + const epTitle = epTitleMatch ? epTitleMatch[1].trim() : "Untitled Episode"; + + // Publish date + const pubDateMatch = item.match(/<pubDate>([^<]+)<\/pubDate>/); + const pubDate = pubDateMatch ? pubDateMatch[1].trim() : null; + let dateStr = ""; // YYYYMMDD + if (pubDate) { + try { + const d = new Date(pubDate); + if (!isNaN(d.getTime())) { + dateStr = d.toISOString().slice(0, 10).replace(/-/g, ""); + } + } catch {} + } + + // Audio enclosure URL + const enclosureMatch = item.match(/<enclosure[^>]+url=["']([^"']+)["']/); + const audioUrl = enclosureMatch ? enclosureMatch[1].trim() : null; + + // Duration (itunes:duration) + const durMatch = item.match(/<itunes:duration>([^<]+)<\/itunes:duration>/); + const duration = durMatch ? durMatch[1].trim() : ""; + + if (!audioUrl) continue; // Skip episodes without audio + + // Use guid, or fall back to audioUrl as unique ID + const id = guid || audioUrl; + + episodes.push({ id, title: epTitle, date: dateStr, audioUrl, duration }); + } + + return { title: podcastTitle, episodes }; +} + +// Download a podcast episode audio file via HTTP(S) to a local path +function downloadPodcastAudio(audioUrl, destPath) { + return new Promise((resolve, reject) => { + const doFetch = (url) => { + const getter = url.startsWith("https") ? https : http; + getter.get(url, (res) => { + if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) { + return doFetch(res.headers.location); + } + if (res.statusCode !== 200) { + return reject(new Error(`HTTP ${res.statusCode} downloading podcast audio`)); + } + const fileStream = createWriteStream(destPath); + res.pipe(fileStream); + fileStream.on("finish", () => fileStream.close(resolve)); + fileStream.on("error", reject); + }).on("error", reject); + }; + doFetch(audioUrl); + }); +} + +// Get channel name from URL +async function fetchChannelName(url) { + // Try fast flat-playlist approach first + try { + const { stdout } = await execFileAsync("yt-dlp", [ + "--print", "%(channel)s", + "--no-download", + "--playlist-end", "1", + "--flat-playlist", + ...ytCookieArgs(), + url, + ], { timeout: 15000 }); + const name = stdout.trim().split("\n")[0]; + if (name && name !== "NA") return name; + } catch {} + // Fallback: fetch without flat-playlist (slower but gets channel from video metadata) + try { + const { stdout } = await execFileAsync("yt-dlp", [ + "--print", "%(channel)s", + "--no-download", + "--playlist-end", "1", + ...ytCookieArgs(), + url, + ], { timeout: 30000 }); + const name = stdout.trim().split("\n")[0]; + if (name && name !== "NA") return name; + } catch {} + // Last resort: extract handle from URL + try { + const u = new URL(url); + const handleMatch = u.pathname.match(/\/@([^/]+)/); + if (handleMatch) return "@" + handleMatch[1]; + } catch {} + return "Unknown Channel"; +} + +// Skip list — videos deleted from history that subscriptions should not re-add +const skipPath = path.join(historyDir, "skip-list.json"); + +async function loadSkipList() { + try { + return new Set(JSON.parse(await fs.readFile(skipPath, "utf-8")).videoIds || []); + } catch { + return new Set(); + } +} + +async function addToSkipList(videoId) { + const skipIds = await loadSkipList(); + skipIds.add(videoId); + await fs.writeFile(skipPath, JSON.stringify({ videoIds: [...skipIds] })); +} + +// Seen list — videos already offered for approval (persists across restarts) +const seenPath = path.join(historyDir, "seen-list.json"); + +async function loadSeenList() { + try { + return new Set(JSON.parse(await fs.readFile(seenPath, "utf-8")).videoIds || []); + } catch { + return new Set(); + } +} + +async function addToSeenList(videoIds) { + const seen = await loadSeenList(); + for (const id of videoIds) seen.add(id); + await fs.writeFile(seenPath, JSON.stringify({ videoIds: [...seen] })); +} + +// Get all videoIds already processed in history +async function getProcessedVideoIds() { + const ids = new Set(); + try { + const files = await fs.readdir(historyDir); + for (const file of files.filter(f => f.endsWith(".json") && f !== "_meta.json" && f !== "subscriptions.json" && f !== "skip-list.json" && f !== "seen-list.json" && f !== "auto-queue.json")) { + try { + const raw = await fs.readFile(path.join(historyDir, file), "utf-8"); + const data = JSON.parse(raw); + if (data.videoId) ids.add(data.videoId); + } catch {} + } + } catch {} + return ids; +} + +// Server-side auto-queue for subscription-discovered videos (persisted to disk) +const autoQueuePath = path.join(historyDir, "auto-queue.json"); +let autoQueue = []; + +async function loadAutoQueue() { + try { + const data = JSON.parse(await fs.readFile(autoQueuePath, "utf-8")); + return data.items || []; + } catch { return []; } +} +async function saveAutoQueue() { + await fs.writeFile(autoQueuePath, JSON.stringify({ items: autoQueue }, null, 2)); +} + +// Load persisted queue on startup, filtering out already-processed items +autoQueue = await loadAutoQueue(); +{ + const processed = await getProcessedVideoIds(); + const before = autoQueue.length; + autoQueue = autoQueue.filter(q => !processed.has(q.videoId)); + if (autoQueue.length < before) { + console.log(` Auto-queue: removed ${before - autoQueue.length} already-processed item(s)`); + await saveAutoQueue(); + } +} + +// ── Background processing queue ────────────────────────────────────────── +// Processes "approved" auto-queue items sequentially with configurable delay +// between items to avoid hammering YouTube with rapid-fire downloads. +const processingConfigPath = path.join(configDir, "processing-config.json"); +let processingConfig = { + delaySeconds: 300, // Default delay between processing queue items (5 minutes) + enabled: true, // Whether background processing is active +}; +let processingState = { + running: false, // Is the processor loop currently active? + currentItem: null, // The item currently being processed (or null) + lastCompleted: null, // Timestamp of last completed item + rush: false, // If true, skip delay before next item + log: [], // Recent processing log entries +}; + +function procLog(msg) { + console.log(` [processor] ${msg}`); + processingState.log.push({ t: new Date().toISOString(), msg }); + if (processingState.log.length > 100) processingState.log.shift(); +} + +async function loadProcessingConfig() { + try { + const data = JSON.parse(await fs.readFile(processingConfigPath, "utf-8")); + if (typeof data.delaySeconds === "number") processingConfig.delaySeconds = data.delaySeconds; + if (typeof data.enabled === "boolean") processingConfig.enabled = data.enabled; + } catch {} +} +async function saveProcessingConfig() { + await fs.writeFile(processingConfigPath, JSON.stringify(processingConfig, null, 2)); +} +await loadProcessingConfig(); + +// The background processor: picks "approved" items, processes via internal HTTP, +// waits the configured delay, then picks the next one. Runs continuously. +async function backgroundProcessor() { + if (processingState.running) return; // Already running + processingState.running = true; + procLog("Background processor started"); + + while (true) { + // Find next approved item + const item = autoQueue.find(q => q.status === "approved"); + if (!item) { + procLog("No approved items in queue — processor sleeping"); + processingState.running = false; + processingState.currentItem = null; + return; + } + + if (!processingConfig.enabled) { + procLog("Processing is paused — processor sleeping"); + processingState.running = false; + processingState.currentItem = null; + return; + } + + // Wait the configured delay (unless rush mode or first item) + if (processingState.lastCompleted && !processingState.rush) { + const delaySec = processingConfig.delaySeconds; + procLog(`Waiting ${delaySec}s before next item...`); + await new Promise(r => setTimeout(r, delaySec * 1000)); + } + processingState.rush = false; + + // Re-check the item hasn't been removed/changed while we waited + const freshItem = autoQueue.find(q => q.id === item.id); + if (!freshItem || freshItem.status !== "approved") { + procLog(`Item ${item.id} was removed or status changed — skipping`); + continue; + } + + // Mark as processing + freshItem.status = "processing"; + processingState.currentItem = freshItem; + await saveAutoQueue(); + procLog(`Processing: ${freshItem.title} (${freshItem.url})`); + + try { + // Call the existing /api/process endpoint via internal HTTP request + const result = await processItemInternally(freshItem); + freshItem.status = "completed"; + freshItem.completedAt = new Date().toISOString(); + freshItem.historyId = result.historyId || null; + processingState.lastCompleted = new Date().toISOString(); + procLog(`✓ Completed: ${freshItem.title}`); + } catch (err) { + freshItem.status = "failed"; + freshItem.error = err.message || String(err); + freshItem.failedAt = new Date().toISOString(); + procLog(`✗ Failed: ${freshItem.title} — ${freshItem.error.slice(0, 200)}`); + } + + processingState.currentItem = null; + await saveAutoQueue(); + } +} + +// Internal HTTP request to /api/process — consumes the SSE stream and +// waits for the "result" or "error" event. This reuses the entire existing +// pipeline without any code duplication. +function processItemInternally(item) { + return new Promise((resolve, reject) => { + const apiKey = resolveApiKey(null); // Use server's stored key + if (!apiKey) { + return reject(new Error("No API key configured. Set your Gemini API key in Settings.")); + } + + const body = JSON.stringify({ + url: item.url, + apiKey: "USE_SERVER_KEY", + type: item.type || undefined, + title: item.title || undefined, + uploadDate: item.uploadDate || undefined, + episodeId: item.videoId || undefined, + }); + + const req = http.request({ + hostname: "127.0.0.1", + port: PORT, + path: "/api/process", + method: "POST", + headers: { "Content-Type": "application/json", "Content-Length": Buffer.byteLength(body) }, + timeout: 1800000, // 30 minutes max for very long videos + }, (res) => { + let buffer = ""; + let lastResult = null; + let lastError = null; + + res.on("data", (chunk) => { + buffer += chunk.toString(); + + // Parse SSE events from the buffer + const lines = buffer.split("\n"); + buffer = lines.pop() || ""; // Keep incomplete line in buffer + + let currentEvent = null; + for (const line of lines) { + if (line.startsWith("event: ")) { + currentEvent = line.slice(7).trim(); + } else if (line.startsWith("data: ") && currentEvent) { + try { + const data = JSON.parse(line.slice(6)); + if (currentEvent === "result") lastResult = data; + if (currentEvent === "error") lastError = data; + if (currentEvent === "log") { + procLog(` [${data.elapsed || "?"}s] ${data.message}`); + } + } catch {} + currentEvent = null; + } else if (line === "") { + currentEvent = null; + } + } + }); + + res.on("end", () => { + if (lastError) { + reject(new Error(lastError.message || "Processing failed")); + } else if (lastResult) { + resolve(lastResult); + } else { + reject(new Error("Processing ended without result")); + } + }); + + res.on("error", reject); + }); + + req.on("error", reject); + req.on("timeout", () => { + req.destroy(); + reject(new Error("Processing timed out after 30 minutes")); + }); + + req.write(body); + req.end(); + }); +} + +// Wake up the processor whenever there are approved items +function kickProcessor() { + if (!processingState.running && processingConfig.enabled) { + const hasApproved = autoQueue.some(q => q.status === "approved"); + if (hasApproved) { + backgroundProcessor().catch(err => procLog(`Processor error: ${err.message}`)); + } + } +} + +let subCheckRunning = false; +let subCheckPromise = null; +let subCheckLog = []; // Stores recent check logs for debug endpoint +function subLog(msg) { console.log(msg); subCheckLog.push({ t: new Date().toISOString(), msg }); if (subCheckLog.length > 200) subCheckLog.shift(); } + +async function checkSubscriptions() { + if (subCheckRunning) { + // Wait for current check to finish, then run again + if (subCheckPromise) await subCheckPromise; + return checkSubscriptions(); + } + subCheckRunning = true; + subCheckPromise = _checkSubscriptionsInner().finally(() => { + subCheckRunning = false; + subCheckPromise = null; + }); + return subCheckPromise; +} + +async function _checkSubscriptionsInner() { + subCheckLog = []; // Clear logs for fresh check + const subs = await loadSubscriptions(); + if (subs.length === 0) { subLog("No subscriptions found"); return; } + + const processedIds = await getProcessedVideoIds(); + const skippedIds = await loadSkipList(); + const seenIds = await loadSeenList(); + const queuedIds = new Set(autoQueue.map(q => { + // For YouTube: extract video ID from URL; for podcasts: use stored videoId (GUID) + if (q.videoId) return q.videoId; + const m = q.url.match(/[?&]v=([a-zA-Z0-9_-]{11})/); + return m ? m[1] : null; + }).filter(Boolean)); + + subLog(`${processedIds.size} in library, ${skippedIds.size} skipped, ${seenIds.size} seen, ${queuedIds.size} in queue`); + + let changed = false; + + for (const sub of subs) { + if (sub.paused) { subLog(`⏸ ${sub.name} — paused, skipping`); continue; } + + try { + const icon = sub.type === "podcast" ? "🎙" : "📡"; + subLog(`${icon} Checking: ${sub.name} (${sub.url})`); + + const cutoffDate = sub.createdAt.replace(/[-T:\.Z]/g, "").slice(0, 8); + + if (sub.type === "podcast") { + // ── Podcast subscription: discover episodes from RSS feed ── + const { episodes } = await parsePodcastRSS(sub.url, 200); + subLog(` Found ${episodes.length} episode(s) in RSS feed`); + + if (episodes.length === 0) { + sub.lastChecked = new Date().toISOString(); + changed = true; + continue; + } + + // Filter out already-known episodes + const unknowns = episodes.filter(ep => { + if (processedIds.has(ep.id)) return false; + if (queuedIds.has(ep.id)) return false; + if (skippedIds.has(ep.id)) return false; + if (seenIds.has(ep.id)) return false; + return true; + }); + const filtered = episodes.length - unknowns.length; + subLog(` ${unknowns.length} to check, ${filtered} already known`); + + if (unknowns.length === 0) { + sub.lastChecked = new Date().toISOString(); + changed = true; + continue; + } + + subLog(` Cutoff date: ${cutoffDate}`); + + let newCount = 0; + const seenNow = []; + for (const ep of unknowns) { + if (!ep.date || ep.date.length !== 8) continue; // skip undated + if (ep.date < cutoffDate) { + seenNow.push(ep.id); + continue; // before cutoff + } + subLog(` ✅ ${ep.date} — ${ep.title.slice(0, 60)}`); + + const itemStatus = sub.autoDownload ? "approved" : "pending"; + autoQueue.push({ + id: `auto-${Date.now()}-${Buffer.from(ep.id).toString("base64url").slice(0, 16)}`, + videoId: ep.id, // episode GUID + url: ep.audioUrl, + title: ep.title, + uploadDate: ep.date, + subscriptionId: sub.id, + subscriptionName: sub.name, + status: itemStatus, + type: "podcast", + duration: ep.duration || "", + }); + queuedIds.add(ep.id); + newCount++; + } + + if (seenNow.length > 0) await addToSeenList(seenNow); + + sub.lastChecked = new Date().toISOString(); + subLog(` → ${newCount} episode(s) queued for approval from ${sub.name}`); + changed = true; + + } else { + // ── YouTube subscription: discover videos via yt-dlp + RSS dates ── + + // Scale fetch limit based on how far back the subscription date goes + const daysSinceSub = Math.max(1, Math.ceil((Date.now() - new Date(sub.createdAt).getTime()) / 86400000)); + const estimatedVideos = Math.ceil(daysSinceSub / 7) * 4; + const fetchLimit = Math.min(Math.max(estimatedVideos, 15), 200); + subLog(` Subscription age: ${daysSinceSub}d → fetching up to ${fetchLimit} videos`); + + const candidates = await listChannelVideosFast(sub.url, fetchLimit); + subLog(` Found ${candidates.length} recent video(s)`); + + if (candidates.length === 0) { + subLog(` ⚠ No videos returned from yt-dlp for this channel`); + sub.lastChecked = new Date().toISOString(); + changed = true; + continue; + } + + const unknowns = candidates.filter(v => { + if (processedIds.has(v.id)) return false; + if (queuedIds.has(v.id)) return false; + if (skippedIds.has(v.id)) return false; + if (seenIds.has(v.id)) return false; + return true; + }); + const filtered = candidates.length - unknowns.length; + subLog(` ${unknowns.length} to check, ${filtered} already known`); + + if (unknowns.length === 0) { + sub.lastChecked = new Date().toISOString(); + changed = true; + continue; + } + + subLog(` Cutoff date: ${cutoffDate} — fetching upload dates...`); + + // Step 1: Get channel ID (cached on subscription, or fetch once) + if (!sub.channelId) { + subLog(` Resolving channel ID...`); + sub.channelId = await getChannelId(sub.url); + if (sub.channelId) { + subLog(` Resolved channel ID: ${sub.channelId}`); + changed = true; + } else { + subLog(` ⚠ Could not resolve channel ID — RSS will be skipped`); + } + } + + // Step 2: RSS feed — fast, no bot detection, covers ~15 most recent + const dateMap = sub.channelId ? await fetchDatesFromRSS(sub.channelId) : {}; + const rssCount = Object.keys(dateMap).length; + if (sub.channelId) subLog(` RSS feed: got dates for ${rssCount} videos`); + + // Step 3: Smart early termination + const needDates = unknowns.filter(v => !dateMap[v.id]); + let earlyTermination = false; + if (needDates.length > 0 && rssCount > 0) { + const rssDates = Object.values(dateMap).sort(); + const oldestRssDate = rssDates[0]; + if (oldestRssDate < cutoffDate) { + earlyTermination = true; + subLog(` Oldest RSS video (${oldestRssDate}) is before cutoff — ${needDates.length} older video(s) are definitely too old, skipping yt-dlp`); + } else { + subLog(` ${needDates.length} video(s) not in RSS — trying yt-dlp for dates...`); + const ytDates = await fetchUploadDates(needDates.map(v => v.id)); + Object.assign(dateMap, ytDates); + const ytCount = Object.keys(ytDates).length; + if (ytCount > 0) subLog(` yt-dlp added dates for ${ytCount} more video(s)`); + } + } else if (needDates.length > 0 && rssCount === 0) { + subLog(` ${needDates.length} video(s) need dates — trying yt-dlp...`); + const ytDates = await fetchUploadDates(needDates.map(v => v.id)); + Object.assign(dateMap, ytDates); + const ytCount = Object.keys(ytDates).length; + if (ytCount > 0) subLog(` yt-dlp added dates for ${ytCount} more video(s)`); + } + + const gotDates = Object.keys(dateMap).length; + if (gotDates > 0 || needDates.length === 0) { + subLog(` Total dates: ${gotDates} of ${unknowns.length} videos`); + } else { + subLog(` ⚠ No dates available — skipping. Try setting YT_COOKIES_FROM in .env`); + sub.lastChecked = new Date().toISOString(); + changed = true; + continue; + } + + let newCount = 0; + for (const video of unknowns) { + const uploadDate = dateMap[video.id]; + if (!uploadDate || uploadDate.length !== 8) { + continue; + } + if (uploadDate < cutoffDate) { + subLog(` ⏭ ${video.id} (${uploadDate}) — before cutoff`); + continue; + } + subLog(` ✅ ${video.id}${uploadDate ? ` (${uploadDate})` : ""} — ${video.title.slice(0,50)}`); + + const ytItemStatus = sub.autoDownload ? "approved" : "pending"; + autoQueue.push({ + id: `auto-${Date.now()}-${video.id}`, + videoId: video.id, + url: `https://www.youtube.com/watch?v=${video.id}`, + title: video.title, + uploadDate: uploadDate || null, + subscriptionId: sub.id, + subscriptionName: sub.name, + status: ytItemStatus, + }); + queuedIds.add(video.id); + newCount++; + } + + // Only add to seen list when we can PROVE a video is too old + const seenNow = unknowns.filter(v => { + if (queuedIds.has(v.id)) return false; + const d = dateMap[v.id]; + if (d && d.length === 8 && d < cutoffDate) return true; + if (d && d.length === 8 && d >= cutoffDate) return false; + return earlyTermination; + }).map(v => v.id); + if (seenNow.length > 0) await addToSeenList(seenNow); + + sub.lastChecked = new Date().toISOString(); + subLog(` → ${newCount} video(s) queued for approval from ${sub.name}`); + changed = true; + } + } catch (err) { + subLog(` ⚠ FAILED for ${sub.name}: ${err.message}`); + } + } + + const pendingCount = autoQueue.filter(q => q.status === "pending").length; + const approvedCount = autoQueue.filter(q => q.status === "approved").length; + subLog(`Done. ${pendingCount} pending, ${approvedCount} approved in auto-queue.`); + if (changed) await saveSubscriptions(subs); + await saveAutoQueue(); + + // Wake up the background processor if there are approved items + if (approvedCount > 0) { + subLog(`Kicking background processor for ${approvedCount} approved item(s)...`); + kickProcessor(); + } +} + +// CRUD endpoints +app.get("/api/subscriptions", async (req, res) => { + const subs = await loadSubscriptions(); + res.json({ subscriptions: subs }); +}); + +// Extract a normalized channel key from a YouTube URL for dedup +function channelKeyFromUrl(url) { + try { + const u = new URL(url); + const path = u.pathname.toLowerCase().replace(/\/+$/, ""); + // /@handle/videos → @handle, /@handle/streams → @handle + const handleMatch = path.match(/\/(@[^/]+)/); + if (handleMatch) return handleMatch[1]; + // /channel/UCxxx → channel/UCxxx + const channelMatch = path.match(/\/(channel\/[^/]+)/); + if (channelMatch) return channelMatch[1]; + // /c/name or /user/name + const cMatch = path.match(/\/(c|user)\/([^/]+)/); + if (cMatch) return cMatch[0]; + // /playlist?list=PLxxx + const list = u.searchParams.get("list"); + if (list) return `playlist/${list}`; + return path; // fallback + } catch { + return url.toLowerCase().replace(/\/+$/, ""); + } +} + +app.post("/api/subscriptions", async (req, res) => { + const { url, since, type } = req.body; + if (!url) return res.status(400).json({ error: "Missing url" }); + + const isPodcast = type === "podcast" || isPodcastFeedUrl(url); + + const subs = await loadSubscriptions(); + + // Prevent duplicates + if (isPodcast) { + const normalizedUrl = url.trim().toLowerCase().replace(/\/+$/, ""); + if (subs.find(s => s.url.trim().toLowerCase().replace(/\/+$/, "") === normalizedUrl)) { + return res.status(409).json({ error: "Already subscribed to this podcast" }); + } + } else { + const newKey = channelKeyFromUrl(url); + if (subs.find(s => channelKeyFromUrl(s.url) === newKey)) { + return res.status(409).json({ error: "Already subscribed to this channel" }); + } + } + + // Use provided cutoff date, or default to right now + const cutoff = since ? new Date(since).toISOString() : new Date().toISOString(); + const sub = { + id: `sub-${Date.now()}`, + url, + name: "Loading...", + type: isPodcast ? "podcast" : "youtube", + channelId: null, + createdAt: cutoff, + lastChecked: null, + paused: false, + }; + subs.push(sub); + await saveSubscriptions(subs); + + // Respond immediately so the UI isn't blocked + res.json(sub); + + // Background: resolve name and check for new content + (async () => { + try { + if (isPodcast) { + // Fetch podcast title from RSS feed + const { title } = await parsePodcastRSS(url, 1); + const freshSubs = await loadSubscriptions(); + const s = freshSubs.find(x => x.id === sub.id); + if (s) { + s.name = title || url; + await saveSubscriptions(freshSubs); + } + console.log(` 🎙 New podcast subscription: ${title} — checking for episodes...`); + } else { + const [name, channelId] = await Promise.all([ + fetchChannelName(url), + getChannelId(url), + ]); + const freshSubs = await loadSubscriptions(); + const s = freshSubs.find(x => x.id === sub.id); + if (s) { + s.name = name; + if (channelId) s.channelId = channelId; + await saveSubscriptions(freshSubs); + } + console.log(` 📡 New subscription: ${name} — checking for recent videos...`); + } + await checkSubscriptions(); + } catch (err) { + console.error(" ⚠ Background subscription setup error:", err.message); + } + })(); +}); + +app.delete("/api/subscriptions/:id", async (req, res) => { + let subs = await loadSubscriptions(); + subs = subs.filter(s => s.id !== req.params.id); + await saveSubscriptions(subs); + // Also remove any pending auto-queue items from this subscription + autoQueue = autoQueue.filter(q => q.subscriptionId !== req.params.id); + await saveAutoQueue(); + res.json({ ok: true }); +}); + +app.put("/api/subscriptions/:id/pause", async (req, res) => { + const subs = await loadSubscriptions(); + const sub = subs.find(s => s.id === req.params.id); + if (!sub) return res.status(404).json({ error: "Subscription not found" }); + sub.paused = !sub.paused; + await saveSubscriptions(subs); + res.json(sub); +}); + +app.put("/api/subscriptions/:id/since", async (req, res) => { + const { since } = req.body; + if (!since) return res.status(400).json({ error: "Missing 'since' date" }); + const subs = await loadSubscriptions(); + const sub = subs.find(s => s.id === req.params.id); + if (!sub) return res.status(404).json({ error: "Subscription not found" }); + sub.createdAt = new Date(since).toISOString(); + await saveSubscriptions(subs); + res.json(sub); +}); + +// Debug: subscription check logs (viewable in-app) +app.get("/api/sub-check-log", (req, res) => { + res.json({ log: subCheckLog, autoQueueCount: autoQueue.length, autoQueue: autoQueue.map(q => ({ id: q.id, videoId: q.videoId, title: q.title, status: q.status, sub: q.subscriptionName })) }); +}); + +// Auto-queue endpoints (frontend polls these) +app.get("/api/auto-queue", (req, res) => { + // Return all items grouped by status for the frontend + const showAll = req.query.all === "true"; + const items = showAll + ? autoQueue + : autoQueue.filter(q => ["pending", "approved", "processing"].includes(q.status)); + res.json({ + items, + checkRunning: subCheckRunning, + counts: { + pending: autoQueue.filter(q => q.status === "pending").length, + approved: autoQueue.filter(q => q.status === "approved").length, + processing: autoQueue.filter(q => q.status === "processing").length, + completed: autoQueue.filter(q => q.status === "completed").length, + failed: autoQueue.filter(q => q.status === "failed").length, + }, + }); +}); + +app.delete("/api/auto-queue/:id", async (req, res) => { + autoQueue = autoQueue.filter(q => q.id !== req.params.id); + await saveAutoQueue(); + res.json({ ok: true }); +}); + +app.post("/api/auto-queue/:id/skip", async (req, res) => { + const item = autoQueue.find(q => q.id === req.params.id); + if (item && item.videoId) { + await addToSkipList(item.videoId); + } + autoQueue = autoQueue.filter(q => q.id !== req.params.id); + await saveAutoQueue(); + res.json({ ok: true }); +}); + +// Approve a single auto-queue item for background processing +app.post("/api/auto-queue/:id/approve", async (req, res) => { + const item = autoQueue.find(q => q.id === req.params.id); + if (!item) return res.status(404).json({ error: "Item not found" }); + if (item.status !== "pending") return res.status(400).json({ error: `Cannot approve item with status '${item.status}'` }); + item.status = "approved"; + await saveAutoQueue(); + kickProcessor(); + res.json({ ok: true, item }); +}); + +// Approve all pending items at once +app.post("/api/auto-queue/approve-all", async (req, res) => { + let count = 0; + for (const item of autoQueue) { + if (item.status === "pending") { + item.status = "approved"; + count++; + } + } + if (count > 0) { + await saveAutoQueue(); + kickProcessor(); + } + res.json({ ok: true, approved: count }); +}); + +// Retry a failed item +app.post("/api/auto-queue/:id/retry", async (req, res) => { + const item = autoQueue.find(q => q.id === req.params.id); + if (!item) return res.status(404).json({ error: "Item not found" }); + if (item.status !== "failed") return res.status(400).json({ error: `Cannot retry item with status '${item.status}'` }); + item.status = "approved"; + item.error = undefined; + item.failedAt = undefined; + await saveAutoQueue(); + kickProcessor(); + res.json({ ok: true, item }); +}); + +// Clear completed and failed items from the queue +app.post("/api/auto-queue/clear-finished", async (req, res) => { + const before = autoQueue.length; + autoQueue = autoQueue.filter(q => !["completed", "failed"].includes(q.status)); + const removed = before - autoQueue.length; + if (removed > 0) await saveAutoQueue(); + res.json({ ok: true, removed }); +}); + +app.post("/api/subscriptions/check-now", async (req, res) => { + if (subCheckRunning) return res.json({ ok: true, message: "Already checking" }); + checkSubscriptions().catch(err => console.error(" ⚠ Manual subscription check error:", err.message)); + res.json({ ok: true, message: "Check started" }); +}); + +// ── Auto-download toggle per subscription ────────────────────────────────── +app.put("/api/subscriptions/:id/auto-download", async (req, res) => { + const subs = await loadSubscriptions(); + const sub = subs.find(s => s.id === req.params.id); + if (!sub) return res.status(404).json({ error: "Subscription not found" }); + sub.autoDownload = req.body.enabled === true; + await saveSubscriptions(subs); + res.json({ ok: true, subscription: sub }); +}); + +// ── Background processing status & configuration ─────────────────────────── + +// Get current processing status (what's running, queue depth, config) +app.get("/api/processing/status", (req, res) => { + res.json({ + running: processingState.running, + currentItem: processingState.currentItem + ? { id: processingState.currentItem.id, title: processingState.currentItem.title, url: processingState.currentItem.url } + : null, + lastCompleted: processingState.lastCompleted, + config: processingConfig, + counts: { + approved: autoQueue.filter(q => q.status === "approved").length, + processing: autoQueue.filter(q => q.status === "processing").length, + pending: autoQueue.filter(q => q.status === "pending").length, + }, + log: processingState.log.slice(-20), + }); +}); + +// Update processing configuration (delay between items, enable/disable) +app.put("/api/processing/config", async (req, res) => { + if (typeof req.body.delaySeconds === "number" && req.body.delaySeconds >= 0) { + processingConfig.delaySeconds = Math.max(0, Math.min(3600, req.body.delaySeconds)); + } + if (typeof req.body.enabled === "boolean") { + processingConfig.enabled = req.body.enabled; + // If enabling and there are approved items, kick the processor + if (req.body.enabled) kickProcessor(); + } + await saveProcessingConfig(); + res.json({ ok: true, config: processingConfig }); +}); + +// Rush: skip the delay before the next item in the queue +app.post("/api/processing/rush", (req, res) => { + processingState.rush = true; + // If not currently running but there are approved items, start processing + kickProcessor(); + res.json({ ok: true, message: "Rush mode enabled — next item will process immediately" }); +}); + +// Processing log (for debug/monitoring) +app.get("/api/processing/log", (req, res) => { + res.json({ log: processingState.log }); +}); + +// ── Full pipeline: URL → audio → transcript → topic analysis ────────────── + +app.post("/api/process", async (req, res) => { + const { url, apiKey: clientKey, model, type: itemType, title: itemTitle, uploadDate: itemUploadDate, episodeId } = req.body; + const apiKey = resolveApiKey(clientKey); + + if (!url) { + return res.status(400).json({ error: "Missing url" }); + } + if (!apiKey) { + return res.status(400).json({ error: "No API key provided. Set GEMINI_API_KEY in .env or enter one in Settings." }); + } + + // Determine if this is a podcast episode or YouTube video + const isPodcast = itemType === "podcast" || /\.(mp3|m4a|ogg|opus|wav|aac)(\?|$)/i.test(url); + const videoId = isPodcast ? (episodeId || url) : extractVideoId(url); + + if (!isPodcast && !videoId) { + return res.status(400).json({ error: "Invalid YouTube URL" }); + } + + const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "yts-")); + const audioExt = isPodcast ? (url.match(/\.(mp3|m4a|ogg|opus|wav|aac)/i)?.[1] || "mp3") : "mp3"; + const audioPath = path.join(tmpDir, `audio.${audioExt}`); + const mimeType = { mp3: "audio/mp3", m4a: "audio/mp4", ogg: "audio/ogg", opus: "audio/opus", wav: "audio/wav", aac: "audio/aac" }[audioExt] || "audio/mp3"; + + try { + const pipelineStart = Date.now(); + + // Set up SSE + res.writeHead(200, { + "Content-Type": "text/event-stream", + "Cache-Control": "no-cache", + Connection: "keep-alive", + }); + + // Helper to send log entries with elapsed time + const logHistory = []; + function log(step, message, detail) { + const elapsed = ((Date.now() - pipelineStart) / 1000).toFixed(1); + const logMsg = `[${elapsed}s] ${message}`; + console.log(` ${logMsg}`); + logHistory.push({ elapsed, message, detail: detail || null }); + sendEvent(res, "status", { step, message }); + sendEvent(res, "log", { elapsed, message, detail: detail || null }); + } + + // ── Step 1: Download audio ── + const dlStart = Date.now(); + let videoTitle = itemTitle || "Untitled"; + let videoUploadDate = itemUploadDate || ""; + + if (isPodcast) { + log(1, "Downloading podcast episode..."); + await downloadPodcastAudio(url, audioPath); + + const stats = await fs.stat(audioPath); + const sizeMB = (stats.size / (1024 * 1024)).toFixed(1); + const dlTime = ((Date.now() - dlStart) / 1000).toFixed(1); + log(1, `Episode downloaded (${sizeMB} MB) in ${dlTime}s`, `File size: ${sizeMB} MB`); + log(1, `Episode: ${videoTitle}`); + + } else { + log(1, "Downloading audio from YouTube..."); + + const dlBaseArgs = [ + "-x", + "--audio-format", "mp3", + "--audio-quality", "5", + "-o", audioPath, + "--no-playlist", + "--print", "%(title)s|||%(upload_date)s", + "--no-simulate", + ]; + const dlUrl = `https://www.youtube.com/watch?v=${videoId}`; + const cookieArgs = ytCookieArgs(); + const hasCookies = cookieArgs.length > 0; + let usedCookies = false; + let dlStdout = ""; + + // Helper: attempt a single yt-dlp download + async function attemptDownload(args, label) { + const result = await execFileAsync("yt-dlp", args, { timeout: 600000 }); + return result.stdout || ""; + } + + // Helper: check if error is a bot detection / rate limit block + function isBotBlock(errText) { + return /Sign in|confirm you're not a bot|bot detection|JsChallengeProvider|js.*challenge|HTTP Error 403|Too Many Requests|429/i.test(errText); + } + + // ── Smart download with retry ── + // Strategy: cookies → no-cookies → wait & retry (up to 3 attempts with increasing delays) + const MAX_RETRIES = 3; + const RETRY_DELAYS = [30, 60, 120]; // seconds — escalating backoff + let downloaded = false; + let lastError = ""; + + for (let attempt = 0; attempt <= MAX_RETRIES && !downloaded; attempt++) { + // On retry attempts, wait before trying again + if (attempt > 0) { + const waitSec = RETRY_DELAYS[Math.min(attempt - 1, RETRY_DELAYS.length - 1)]; + log(1, `⏳ YouTube is rate-limiting. Waiting ${waitSec}s before retry ${attempt}/${MAX_RETRIES}...`); + sendEvent(res, "status", { step: 1, message: `Rate limited — retrying in ${waitSec}s (attempt ${attempt}/${MAX_RETRIES})` }); + await new Promise(r => setTimeout(r, waitSec * 1000)); + log(1, `Retrying download (attempt ${attempt}/${MAX_RETRIES})...`); + // Clean up any partial file from previous attempt + await fs.unlink(audioPath).catch(() => {}); + } + + // Try with cookies first + if (hasCookies && !usedCookies) { + try { + log(1, attempt === 0 ? "Trying download with browser cookies (ad-free)..." : "Retrying with cookies..."); + dlStdout = await attemptDownload([...dlBaseArgs, ...cookieArgs, dlUrl], "cookies"); + usedCookies = true; + downloaded = true; + break; + } catch (cookieErr) { + const cookieMsg = (cookieErr.stderr || "") + " " + (cookieErr.message || ""); + if (attempt === 0) log(1, `⚠ Cookie download failed: ${cookieMsg.trim().slice(0, 200)}`); + log(1, "Retrying without cookies..."); + await fs.unlink(audioPath).catch(() => {}); + } + } + + // Try without cookies + if (!downloaded) { + try { + dlStdout = await attemptDownload([...dlBaseArgs, dlUrl], "no-cookies"); + downloaded = true; + break; + } catch (dlErr) { + lastError = (dlErr.stderr || "") + " " + (dlErr.stdout || "") + " " + (dlErr.message || ""); + const blocked = isBotBlock(lastError); + + if (blocked && attempt < MAX_RETRIES) { + log(1, `⚠ YouTube bot detection triggered`); + // Will loop back and wait + continue; + } + + if (blocked && attempt === MAX_RETRIES) { + // Last resort: try yt-dlp auto-update in case there's a newer version that handles this + log(1, "All retries exhausted — attempting yt-dlp auto-update as last resort..."); + const updateResult = await autoUpdateYtdlp(); + if (updateResult.success) { + log(1, "yt-dlp updated! Final retry..."); + try { + const retryResult = await attemptDownload([...dlBaseArgs, dlUrl], "post-update"); + dlStdout = retryResult; + downloaded = true; + break; + } catch { /* fall through to error */ } + } + } + + // Non-bot error or exhausted retries + if (!downloaded) { + log(1, `⚠ yt-dlp error: ${lastError.trim().slice(0, 300)}`); + } + } + } + } + + if (!downloaded) { + const blocked = isBotBlock(lastError); + let hint = ""; + if (blocked) { + hint = "\n\nYouTube is temporarily blocking downloads from your IP address. " + + "This is usually caused by:\n" + + "• Recent VPN use (YouTube flags VPN IPs)\n" + + "• Too many downloads in a short period\n" + + "• YouTube's general anti-bot measures\n\n" + + "What to try:\n" + + "• Wait 10-30 minutes and try again\n" + + "• Disconnect any VPN/proxy\n" + + "• Upload fresh cookies.txt via Settings\n" + + "• Try a different network (mobile hotspot, etc.)"; + } + throw new Error(`Download failed after ${MAX_RETRIES} retries.${hint}\n\nLast error: ${lastError.trim().slice(0, 300)}`); + } + + if (!usedCookies && hasCookies) { + log(1, "⚠ Downloaded without cookies — audio may contain ads"); + } + + const stats = await fs.stat(audioPath); + const sizeMB = (stats.size / (1024 * 1024)).toFixed(1); + const dlTime = ((Date.now() - dlStart) / 1000).toFixed(1); + log(1, `Audio downloaded (${sizeMB} MB) in ${dlTime}s`, `File size: ${sizeMB} MB`); + + // Extract title from the --print output of the download command + const fallbackTitle = videoTitle !== "Untitled" ? videoTitle : null; + let gotTitle = false; + + // First try: parse title from the download stdout (most reliable — same call that succeeded) + if (dlStdout) { + const printLines = dlStdout.split("\n").map(l => l.trim()).filter(Boolean); + for (const line of printLines) { + if (line.includes("|||")) { + const sep = line.indexOf("|||"); + const t = line.slice(0, sep).trim(); + const d = line.slice(sep + 3).trim(); + if (t && t !== "NA") { + videoTitle = t; + if (d && d !== "NA") videoUploadDate = d; + gotTitle = true; + log(1, `Video title: ${videoTitle}`); + break; + } + } + } + } + + // Second try: separate yt-dlp call (no cookies needed for public metadata) + if (!gotTitle) { + try { + const { stdout } = await execFileAsync("yt-dlp", [ + "--print", "%(title)s|||%(upload_date)s", + "--no-download", + `https://www.youtube.com/watch?v=${videoId}`, + ], { timeout: 15000 }); + const raw = stdout.trim(); + const sep = raw.indexOf("|||"); + if (sep > 0) { + videoTitle = raw.slice(0, sep).trim() || fallbackTitle || "Untitled"; + const d = raw.slice(sep + 3).trim(); + if (d && d !== "NA") videoUploadDate = d || videoUploadDate; + } else { + videoTitle = raw || fallbackTitle || "Untitled"; + } + gotTitle = videoTitle !== "Untitled"; + if (gotTitle) log(1, `Video title: ${videoTitle}`); + } catch { + // Title fetch failed + } + } + + // Third try: use the queue-provided title + if (!gotTitle && fallbackTitle) { + videoTitle = fallbackTitle; + log(1, `Using queue title: ${fallbackTitle}`); + gotTitle = true; + } + + if (!gotTitle) { + log(1, "⚠ Could not fetch video title"); + } + } + + // ── Step 2: Transcribe audio ── + // Detect audio duration to choose strategy + const audioDuration = await getAudioDuration(audioPath); + const audioDurMin = audioDuration ? (audioDuration / 60).toFixed(1) : "unknown"; + log(2, `Audio duration: ${audioDuration ? formatTime(Math.floor(audioDuration)) : "unknown"} (${audioDurMin} min)`); + + // Strategy: + // < 60 min AND < 30 MB → Flash on full file (fast, cheap, reliable) + // ≥ 60 min OR ≥ 30 MB → go straight to chunked transcription with Flash (45-min chunks) + // If full-file transcription is truncated or empty → fall back to chunks + const CHUNK_TIME_THRESHOLD = 60 * 60; // 60 minutes + const CHUNK_SIZE_THRESHOLD = 30 * 1024 * 1024; // 30 MB + let audioFileSize = 0; + try { audioFileSize = (await fs.stat(audioPath)).size; } catch {} + const audioSizeMB = (audioFileSize / (1024 * 1024)).toFixed(1); + const needsChunking = (audioDuration && audioDuration >= CHUNK_TIME_THRESHOLD) || (audioFileSize >= CHUNK_SIZE_THRESHOLD); + const transcriptionModel = "gemini-3-flash-preview"; // Flash handles transcription best + const analysisModel = model || "gemini-3.1-pro-preview"; + + if (needsChunking) { + const reason = audioDuration >= CHUNK_TIME_THRESHOLD ? `${audioDurMin} min` : `${audioSizeMB} MB`; + log(2, `Large audio (${reason}) — will use chunked transcription with ${transcriptionModel}`); + } + + const ai = new GoogleGenAI({ apiKey, httpOptions: { timeout: 900_000, headersTimeout: 900_000 } }); + + const transcriptionPrompt = (titleHint) => `${titleHint ? `Video title: "${titleHint}"\n\n` : ""}Transcribe this audio completely and verbatim. Include timestamps at regular intervals (every 15-30 seconds or at natural pauses). + +Format each line as: +[MM:SS] The spoken text here... + +Rules: +- Transcribe EVERY word spoken, do not skip or summarize anything. +- Use [MM:SS] or [H:MM:SS] timestamp format at the start of each line. +- Start a new timestamped line every 15-30 seconds or at natural speech pauses. +- Include filler words (um, uh, you know) for accuracy. +- If multiple speakers are distinguishable, identify them by name when possible (from introductions, context clues, or how they address each other). Format as: [MM:SS] Name: text. If you cannot determine a name, use descriptive labels like "Host" and "Guest" rather than "Speaker 1" and "Speaker 2". + +Return ONLY the timestamped transcript, nothing else.`; + + // Helper: upload a single audio file and transcribe it + async function transcribeSingleFile(filePath, mType, titleHint, modelName, offsetSeconds = 0) { + const upStart = Date.now(); + log(2, `Uploading audio${offsetSeconds > 0 ? ` (offset ${formatTime(offsetSeconds)})` : ""} to Gemini File API...`); + const uploaded = await ai.files.upload({ file: filePath, config: { mimeType: mType } }); + const upTime = ((Date.now() - upStart) / 1000).toFixed(1); + log(2, `Audio uploaded in ${upTime}s`, `File ref: ${uploaded.name}`); + + // Wait for processing + let f = uploaded; + const pStart = Date.now(); + while (f.state === "PROCESSING") { + const ws = ((Date.now() - pStart) / 1000).toFixed(0); + log(2, `Waiting for Gemini to process audio... (${ws}s)`); + await new Promise(r => setTimeout(r, 3000)); + f = await ai.files.get({ name: f.name }); + } + if (f.state === "FAILED") throw new Error("Gemini failed to process audio file."); + + const pTime = ((Date.now() - pStart) / 1000).toFixed(1); + log(2, `Audio processed in ${pTime}s. Transcribing with ${modelName}...`); + + const prompt = transcriptionPrompt(titleHint); + + // Only use thinkingConfig for Flash models — Pro doesn't support "minimal" + const txConfig = modelName.includes("flash") + ? { thinkingConfig: { thinkingLevel: "minimal" } } + : {}; + + // Retry logic that handles both API errors (via retryGemini) AND empty responses + const EMPTY_RETRIES = 3; + let result; + for (let emptyAttempt = 0; emptyAttempt < EMPTY_RETRIES; emptyAttempt++) { + result = await retryGemini( + () => ai.models.generateContent({ + model: modelName, + config: { + ...txConfig, + // Disable safety filters to prevent content blocking + safetySettings: [ + { category: "HARM_CATEGORY_HARASSMENT", threshold: "BLOCK_NONE" }, + { category: "HARM_CATEGORY_HATE_SPEECH", threshold: "BLOCK_NONE" }, + { category: "HARM_CATEGORY_SEXUALLY_EXPLICIT", threshold: "BLOCK_NONE" }, + { category: "HARM_CATEGORY_DANGEROUS_CONTENT", threshold: "BLOCK_NONE" }, + ], + }, + contents: [{ + role: "user", + parts: [ + { fileData: { fileUri: f.uri, mimeType: mType } }, + { text: prompt }, + ], + }], + }), + { retries: 3, delayMs: 5000, label: `Transcription${offsetSeconds > 0 ? ` (chunk@${formatTime(offsetSeconds)})` : ""}`, log: (msg) => log(2, msg) } + ); + + const responseText = safeText(result); + if (responseText) break; // Got actual content, done + + // Log why it's empty + const candidate = result?.candidates?.[0]; + const finishReason = candidate?.finishReason || "UNKNOWN"; + const blockReason = result?.promptFeedback?.blockReason || "none"; + log(2, `⚠ Empty response (attempt ${emptyAttempt + 1}/${EMPTY_RETRIES}) — finishReason: ${finishReason}, blockReason: ${blockReason}`); + + if (emptyAttempt < EMPTY_RETRIES - 1) { + const waitSec = 10 * (emptyAttempt + 1); + log(2, `Waiting ${waitSec}s before retry...`); + await new Promise(r => setTimeout(r, waitSec * 1000)); + } + } + + // Clean up uploaded file + try { await ai.files.delete({ name: f.name }); } catch {} + + return result; + } + + // ── Helper: chunked transcription for long audio ── + async function transcribeChunked(srcPath, srcMime, title, modelName, logFn) { + const chunkDir = path.join(os.tmpdir(), `yt-chunks-${Date.now()}`); + await fs.mkdir(chunkDir, { recursive: true }); + + try { + const audioChunks = await splitAudioFile(srcPath, chunkDir, 2700); // 45 min chunks + if (!audioChunks || audioChunks.length <= 1) return null; // splitting not needed + + logFn(`Split audio into ${audioChunks.length} chunks for transcription`); + const allEntries = []; + let totalIn = 0, totalOut = 0; + + for (const chunk of audioChunks) { + logFn(`Transcribing chunk ${chunk.index + 1}/${audioChunks.length} (starts at ${formatTime(chunk.startOffset)})...`); + const chunkResult = await transcribeSingleFile( + chunk.path, "audio/mpeg", title, + modelName, + chunk.startOffset + ); + + const chunkUsage = chunkResult.usageMetadata || {}; + const chunkCost = calcCost(modelName, chunkUsage); + totalIn += chunkCost.inputTokens; + totalOut += chunkCost.outputTokens; + + const chunkText = safeText(chunkResult); + if (!chunkText) { + logFn(`⚠ Chunk ${chunk.index + 1} returned empty response — skipping`); + continue; + } + const chunkEntries = parseTimestampedTranscript(chunkText); + + // Programmatically adjust timestamps: the model transcribes from 0:00 relative + // to the chunk, so add the chunk's startOffset to get real video timestamps + if (chunk.startOffset > 0) { + // Check if the model already adjusted (first entry near the startOffset) + const firstOffset = chunkEntries.length > 0 ? chunkEntries[0].offset : 0; + const alreadyAdjusted = firstOffset >= chunk.startOffset * 0.8; + if (!alreadyAdjusted) { + for (const e of chunkEntries) { + e.offset += chunk.startOffset; + } + logFn(`Adjusted chunk ${chunk.index + 1} timestamps by +${formatTime(chunk.startOffset)}`); + } + } + + logFn(`Chunk ${chunk.index + 1}: ${chunkEntries.length} segments, last timestamp ${chunkEntries.length > 0 ? formatTime(chunkEntries[chunkEntries.length - 1].offset) : "N/A"}`); + + // Merge: skip entries that overlap with already-transcribed content + const lastExistingTime = allEntries.length > 0 ? allEntries[allEntries.length - 1].offset : -1; + for (const e of chunkEntries) { + if (e.offset > lastExistingTime) allEntries.push(e); + } + } + + // Recalculate durations + for (let i = 0; i < allEntries.length - 1; i++) { + allEntries[i].duration = allEntries[i + 1].offset - allEntries[i].offset; + } + if (allEntries.length > 0) allEntries[allEntries.length - 1].duration = 15; + + // Calculate total cost for chunked transcription + const rates = PRICING[modelName] || PRICING["default"]; + const totalCostNum = (totalIn / 1e6) * rates.input + (totalOut / 1e6) * rates.output; + const costDisplay = totalCostNum < 0.01 ? `$${(totalCostNum * 100).toFixed(3)}¢` : `$${totalCostNum.toFixed(4)}`; + + logFn(`Chunked transcription complete: ${allEntries.length} total segments`); + logFn(`Total cost: ${totalIn.toLocaleString()} in / ${totalOut.toLocaleString()} out — cost: ${costDisplay}`); + return { + entries: allEntries, + cost: { + inputTokens: totalIn, outputTokens: totalOut, thinkingTokens: 0, + totalTokens: totalIn + totalOut, + totalCost: String(totalCostNum), totalCostDisplay: costDisplay, + }, + }; + } finally { + try { await fs.rm(chunkDir, { recursive: true, force: true }); } catch {} + } + } + + let entries; + let transcriptText = ""; + let txCost = { inputTokens: 0, outputTokens: 0, thinkingTokens: 0, totalTokens: 0, totalCost: "0", totalCostDisplay: "$0.00" }; + const txStart = Date.now(); + + if (needsChunking) { + // ── Very long audio: go straight to chunked transcription ── + log(2, `Skipping full-file attempt — using chunked transcription for ${audioDurMin} min audio`); + const chunkedResult = await transcribeChunked(audioPath, mimeType, videoTitle, transcriptionModel, (msg) => log(2, msg)); + if (chunkedResult && chunkedResult.entries.length > 0) { + entries = chunkedResult.entries; + txCost = chunkedResult.cost; + } else { + log(2, `⚠ Chunked transcription returned no entries, trying full file as last resort...`); + entries = null; // fall through to full-file attempt below + } + } + + if (!entries) { + // ── Normal: transcribe full file ── + const transcriptResult = await transcribeSingleFile(audioPath, mimeType, videoTitle, transcriptionModel); + + transcriptText = safeText(transcriptResult); + if (!transcriptText) { + log(2, `⚠ Full-file transcription returned empty — falling back to chunked transcription...`); + const chunkedResult = await transcribeChunked(audioPath, mimeType, videoTitle, transcriptionModel, (msg) => log(2, msg)); + if (chunkedResult && chunkedResult.entries.length > 0) { + entries = chunkedResult.entries; + txCost = chunkedResult.cost; + } else { + throw new Error("Gemini returned empty transcription for both full file and chunked attempts. Try again or use a shorter video."); + } + } else { + const txUsage = transcriptResult.usageMetadata || {}; + txCost = calcCost(transcriptionModel, txUsage); + const txTime = ((Date.now() - txStart) / 1000).toFixed(1); + log(2, `Transcription complete in ${txTime}s`, `${transcriptText.length} chars received`); + log(2, `Transcription tokens: ${txCost.inputTokens.toLocaleString()} in / ${txCost.outputTokens.toLocaleString()} out${txCost.thinkingTokens ? ` / ${txCost.thinkingTokens.toLocaleString()} thinking` : ""} — cost: ${txCost.totalCostDisplay}`); + + entries = parseTimestampedTranscript(transcriptText); + log(2, `Parsed ${entries.length} transcript segments`); + } + + // ── Truncation detection → fall back to chunks ── + if (audioDuration && entries.length > 0) { + const lastEntryTime = entries[entries.length - 1].offset; + const coverageRatio = lastEntryTime / audioDuration; + const missingSeconds = audioDuration - lastEntryTime; + + if (coverageRatio < 0.90 && missingSeconds > 120) { + log(2, `⚠ Transcript truncated — covers ${formatTime(lastEntryTime)} of ${formatTime(Math.floor(audioDuration))} (${(coverageRatio * 100).toFixed(0)}%)`); + log(2, `Falling back to chunked transcription...`); + const chunkedResult = await transcribeChunked(audioPath, mimeType, videoTitle, transcriptionModel, (msg) => log(2, msg)); + if (chunkedResult && chunkedResult.entries.length > 0) { + entries = chunkedResult.entries; + txCost = chunkedResult.cost; + const finalCoverage = entries[entries.length - 1].offset; + log(2, `Coverage after chunking: ${formatTime(finalCoverage)} of ${formatTime(Math.floor(audioDuration))}`); + } + } else { + log(2, `Transcript coverage: ${formatTime(lastEntryTime)} of ${formatTime(Math.floor(audioDuration))} (${(coverageRatio * 100).toFixed(0)}%) — OK`); + } + } + } + + const txTotalTime = ((Date.now() - txStart) / 1000).toFixed(1); + log(2, `Total transcription time: ${txTotalTime}s — ${entries.length} segments`); + + if (!entries || entries.length === 0) { + const preview = (transcriptText || "").slice(0, 500).replace(/\n/g, " ↵ "); + log(2, `⚠ Transcript parse failed. Preview: ${preview}`); + sendEvent(res, "error", { message: "Failed to parse transcript." }); + sendEvent(res, "result", { videoId, entries: [], chunks: [], rawTranscript: transcriptText }); + res.end(); + return; + } + + // ── Step 3: Topic analysis with model fallback ── + const analysisFallbacks = [ + analysisModel, + ...[ + "gemini-3.1-pro-preview", + "gemini-3-pro-preview", + "gemini-3-flash-preview", + "gemini-2.5-flash", + ].filter(m => m !== analysisModel), + ]; + + const analysisPrompt = buildAnalysisPrompt(entries); + let analysisResult = null; + let usedAnalysisModel = analysisModel; + const anaStart = Date.now(); + + for (const tryModel of analysisFallbacks) { + try { + log(3, `Analyzing topics across ${entries.length} segments with ${tryModel}...`); + analysisResult = await retryGemini( + () => ai.models.generateContent({ + model: tryModel, + contents: [ + { + role: "user", + parts: [{ text: analysisPrompt }], + }, + ], + }), + { retries: 2, delayMs: 5000, label: "Analysis", log: (msg) => log(3, msg) } + ); + usedAnalysisModel = tryModel; + break; + } catch (fallbackErr) { + const msg = fallbackErr?.message || String(fallbackErr); + log(3, `⚠ ${tryModel} failed: ${msg.slice(0, 150)}`); + if (tryModel !== analysisFallbacks[analysisFallbacks.length - 1]) { + log(3, `Falling back to next model...`); + } + } + } + + if (!analysisResult) { + throw new Error("All analysis models failed. Please try again later."); + } + + const analysisText = safeText(analysisResult); + if (!analysisText) { + throw new Error("Gemini returned an empty analysis. The transcript may be too long for the model. Try again."); + } + const anaTime = ((Date.now() - anaStart) / 1000).toFixed(1); + const anaUsage = analysisResult.usageMetadata || {}; + const anaCost = calcCost(usedAnalysisModel, anaUsage); + + // Parse the analysis JSON + let analysisJson; + try { + let jsonStr = analysisText.trim(); + const codeBlockMatch = jsonStr.match(/```(?:json)?\s*([\s\S]*?)```/); + if (codeBlockMatch) jsonStr = codeBlockMatch[1].trim(); + analysisJson = JSON.parse(jsonStr); + } catch (e) { + console.error("Failed to parse analysis JSON:", e.message); + sendEvent(res, "error", { message: "Topic analysis returned invalid JSON. Returning raw transcript." }); + sendEvent(res, "result", { videoId, entries, chunks: [], rawTranscript: transcriptText }); + res.end(); + return; + } + + // Build final chunks + const chunks = analysisJson.sections.map((section) => { + const start = Math.max(0, section.startIndex); + const end = Math.min(entries.length - 1, section.endIndex); + const sectionEntries = entries.slice(start, end + 1); + return { + title: section.title, + summary: section.summary, + entries: sectionEntries, + startTime: sectionEntries[0]?.offset || 0, + }; + }).filter((c) => c.entries.length > 0); + + const totalTime = ((Date.now() - pipelineStart) / 1000).toFixed(1); + log(3, `Topic analysis complete in ${anaTime}s — found ${chunks.length} topics`); + log(3, `Analysis tokens: ${anaCost.inputTokens.toLocaleString()} in / ${anaCost.outputTokens.toLocaleString()} out${anaCost.thinkingTokens ? ` / ${anaCost.thinkingTokens.toLocaleString()} thinking` : ""} — cost: ${anaCost.totalCostDisplay}`); + + // Total cost summary + const totalCostNum = parseFloat(txCost.totalCost) + parseFloat(anaCost.totalCost); + const totalCostDisplay = totalCostNum < 0.01 ? `$${(totalCostNum * 100).toFixed(3)}¢` : `$${totalCostNum.toFixed(4)}`; + const totalTokens = (txCost.totalTokens + anaCost.totalTokens).toLocaleString(); + log(3, `Pipeline finished in ${totalTime}s — total cost: ${totalCostDisplay} (${totalTokens} tokens)`); + + // Save to history + const contentType = isPodcast ? "podcast" : "youtube"; + const historyId = await saveToHistory(videoId, url, videoTitle, chunks, entries, logHistory, videoUploadDate, contentType).catch(() => null); + + sendEvent(res, "result", { videoId, videoTitle, entries, chunks, historyId, type: contentType }); + res.end(); + + } catch (err) { + console.error("Pipeline error:", err); + if (!res.headersSent) { + res.status(500).json({ error: err.message }); + } else { + sendEvent(res, "error", { message: err.message }); + res.end(); + } + } finally { + // Clean up temp files + try { + await fs.rm(tmpDir, { recursive: true, force: true }); + } catch {} + } +}); + +// ── Helpers ──────────────────────────────────────────────────────────────── + +// ── Audio duration helper (ffprobe) ───────────────────────────────────── +async function getAudioDuration(filePath) { + try { + const { stdout } = await execFileAsync("ffprobe", [ + "-v", "error", + "-show_entries", "format=duration", + "-of", "default=noprint_wrappers=1:nokey=1", + filePath, + ], { timeout: 15000 }); + const dur = parseFloat(stdout.trim()); + return isNaN(dur) ? null : dur; + } catch { + return null; + } +} + +// ── Split audio into chunks with ffmpeg ───────────────────────────────── +async function splitAudioFile(inputPath, outputDir, chunkSeconds = 2700) { + const duration = await getAudioDuration(inputPath); + if (!duration || duration <= chunkSeconds) return null; // no split needed + + const chunks = []; + let startSec = 0; + let i = 0; + while (startSec < duration) { + const chunkPath = path.join(outputDir, `chunk_${i}.mp3`); + const segLen = Math.min(chunkSeconds, duration - startSec); + await execFileAsync("ffmpeg", [ + "-y", "-i", inputPath, + "-ss", String(startSec), + "-t", String(segLen), + "-acodec", "copy", + chunkPath, + ], { timeout: 120000 }); + chunks.push({ path: chunkPath, startOffset: startSec, index: i }); + startSec += chunkSeconds; + i++; + } + return chunks; +} + +function sendEvent(res, event, data) { + res.write(`event: ${event}\ndata: ${JSON.stringify(data)}\n\n`); +} + +function extractVideoId(url) { + if (!url) return null; + const patterns = [ + /(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/|youtube\.com\/v\/)([a-zA-Z0-9_-]{11})/, + /^([a-zA-Z0-9_-]{11})$/, + ]; + for (const p of patterns) { + const m = url.match(p); + if (m) return m[1]; + } + return null; +} + +function formatTime(seconds) { + const s = Math.floor(seconds); + const h = Math.floor(s / 3600); + const m = Math.floor((s % 3600) / 60); + const sec = s % 60; + if (h > 0) return `${h}:${String(m).padStart(2, "0")}:${String(sec).padStart(2, "0")}`; + return `${m}:${String(sec).padStart(2, "0")}`; +} + +function parseTimestampedTranscript(text) { + const lines = text.trim().split("\n").filter(Boolean); + const entries = []; + // Match timestamps in various formats: + // [0:00], [00:00], [0:00:00], (0:00), 0:00 -, **0:00**, etc. + // Optionally preceded by speaker labels, markdown bold, etc. + const tsRegex = /^(?:[*_]*)?(?:\[?\(?)(\d{1,2}):(\d{2})(?::(\d{2}))?[\])]?(?:[*_]*)?\s*[-–—:]?\s*(.*)/; + // Also match lines like "Speaker 1 [0:00]: text" or "**[0:00]** text" + const altRegex = /^(?:.*?)[\[(\s](\d{1,2}):(\d{2})(?::(\d{2}))?[\])]\s*[-–—:]?\s*(.*)/; + + for (const line of lines) { + const trimmed = line.trim(); + let m = trimmed.match(tsRegex); + if (!m) m = trimmed.match(altRegex); + if (m) { + const hours = m[3] !== undefined ? parseInt(m[1]) : 0; + const mins = m[3] !== undefined ? parseInt(m[2]) : parseInt(m[1]); + const secs = m[3] !== undefined ? parseInt(m[3]) : parseInt(m[2]); + const offset = hours * 3600 + mins * 60 + secs; + // Strip any leftover markdown or speaker prefix from the text + const lineText = m[4].replace(/^\*\*\s*/, "").replace(/\s*\*\*$/, "").trim(); + if (lineText) entries.push({ text: lineText, offset, duration: 0 }); + } + } + + // Calculate durations from gaps between entries + for (let i = 0; i < entries.length - 1; i++) { + entries[i].duration = entries[i + 1].offset - entries[i].offset; + } + if (entries.length > 0) { + entries[entries.length - 1].duration = 15; // default last segment + } + + return entries; +} + +function buildAnalysisPrompt(entries) { + const numbered = entries + .map((e, i) => `[${i}] (${formatTime(e.offset)}) ${e.text}`) + .join("\n"); + + return `You are analyzing a video transcript. Your job is to identify natural topic boundaries and group the transcript into discussion-based sections. + +TRANSCRIPT (each line is numbered with a timestamp): +${numbered} + +INSTRUCTIONS: +1. Read the entire transcript carefully. +2. Identify where the discussion naturally shifts from one topic to another. +3. Group consecutive transcript segments by topic. Some sections may be short (a quick aside) and some may be long (an extended deep-dive). Let the content dictate the length. +4. For each section, write: + - A short, specific topic title (3-8 words) + - A 1-3 sentence summary of what's discussed + - The start and end segment indices (inclusive) + +IMPORTANT: +- Sections must be chronological and non-overlapping. +- Every segment index from 0 to ${entries.length - 1} must belong to exactly one section. +- startIndex of section N+1 must equal endIndex of section N plus 1. +- Create as many or as few sections as the content naturally requires. +- Titles should be descriptive and specific, not generic like "Introduction" unless it truly is one. + +Respond with ONLY valid JSON in this exact format, no other text: +{ + "sections": [ + { + "title": "Brief Topic Title", + "summary": "1-3 sentence summary of this discussion section.", + "startIndex": 0, + "endIndex": 15 + } + ] +}`; +} + +// ── Network mode ────────────────────────────────────────────────────────── +// On StartOS (DATA_DIR=/data): always bind to 0.0.0.0 (container networking) +// On local Mac dev: default to localhost (safe on public Wi-Fi) +// - Your .app launcher sets LAN_MODE=true (Home) or false (Traveling) +// - Running "npm start" directly defaults to localhost +const isStartOS = process.env.DATA_DIR && process.env.DATA_DIR !== path.join(__dirname, ".."); +const lanMode = isStartOS ? true : process.env.LAN_MODE === "true"; +const BIND_HOST = lanMode ? "0.0.0.0" : "127.0.0.1"; + +app.get("/api/network-mode", (req, res) => { + res.json({ lan: lanMode }); +}); + +// ── Start server ─────────────────────────────────────────────────────────── + +app.listen(PORT, BIND_HOST, async () => { + console.log(`\n YouTube Summarizer API running on http://${BIND_HOST}:${PORT}`); + console.log(` Data directory: ${DATA_DIR}`); + console.log(` Checking yt-dlp...`); + + const info = await checkYtdlp(); + if (!info.installed) { + console.log(` ⚠ yt-dlp not found. Install it: pip install yt-dlp\n`); + } else if (info.updateAvailable) { + console.log(` ✓ yt-dlp ${info.version} found`); + console.log(` ↑ Update available: ${info.latestVersion}`); + console.log(` Auto-updating...`); + const result = await autoUpdateYtdlp(); + if (result.success) { + const refreshed = await checkYtdlp(); + console.log(` ✓ yt-dlp updated to ${refreshed.version}\n`); + } else { + console.log(` ⚠ Auto-update failed. Run manually: yt-dlp -U\n`); + } + } else { + console.log(` ✓ yt-dlp ${info.version} (up to date)\n`); + } + + // Check subscriptions on startup + const subs = await loadSubscriptions(); + if (subs.length > 0) { + console.log(` 📡 Checking ${subs.length} subscription(s) for new videos...`); + await checkSubscriptions().catch(err => console.error(" ⚠ Subscription check error:", err.message)); + const pending = autoQueue.filter(q => q.status === "pending").length; + const approved = autoQueue.filter(q => q.status === "approved").length; + if (pending > 0) console.log(` ✚ ${pending} new video(s) queued from subscriptions`); + if (approved > 0) console.log(` ⏳ ${approved} approved video(s) ready for processing`); + if (pending === 0 && approved === 0) console.log(` ✓ No new videos from subscriptions`); + } + + // Resume processing any approved items from a previous session + const resumeApproved = autoQueue.filter(q => q.status === "approved").length; + // Also recover any items stuck in "processing" state from a crash + for (const item of autoQueue) { + if (item.status === "processing") { + console.log(` ⚠ Recovering stuck item: ${item.title}`); + item.status = "approved"; // Re-queue for processing + } + } + if (autoQueue.some(q => q.status === "approved")) { + await saveAutoQueue(); + console.log(` 🔄 Starting background processor...`); + // Delay slightly so the server is fully ready before internal HTTP calls + setTimeout(() => kickProcessor(), 2000); + } + + console.log(` ⚙ Processing config: ${processingConfig.delaySeconds}s delay, ${processingConfig.enabled ? "enabled" : "paused"}`); + + // Check subscriptions every hour (runs continuously on StartOS) + setInterval(() => { + checkSubscriptions().catch(err => console.error(" ⚠ Subscription check error:", err.message)); + }, 60 * 60 * 1000); +}); diff --git a/server/node_modules/.bin/glob b/server/node_modules/.bin/glob new file mode 120000 index 0000000..85c9c1d --- /dev/null +++ b/server/node_modules/.bin/glob @@ -0,0 +1 @@ +../glob/dist/esm/bin.mjs \ No newline at end of file diff --git a/server/node_modules/.bin/mime b/server/node_modules/.bin/mime new file mode 120000 index 0000000..fbb7ee0 --- /dev/null +++ b/server/node_modules/.bin/mime @@ -0,0 +1 @@ +../mime/cli.js \ No newline at end of file diff --git a/server/node_modules/.bin/node-which b/server/node_modules/.bin/node-which new file mode 120000 index 0000000..6f8415e --- /dev/null +++ b/server/node_modules/.bin/node-which @@ -0,0 +1 @@ +../which/bin/node-which \ No newline at end of file diff --git a/server/node_modules/.bin/rimraf b/server/node_modules/.bin/rimraf new file mode 120000 index 0000000..7e2fc27 --- /dev/null +++ b/server/node_modules/.bin/rimraf @@ -0,0 +1 @@ +../rimraf/dist/esm/bin.mjs \ No newline at end of file diff --git a/server/node_modules/.package-lock.json b/server/node_modules/.package-lock.json new file mode 100644 index 0000000..df5979c --- /dev/null +++ b/server/node_modules/.package-lock.json @@ -0,0 +1,1799 @@ +{ + "name": "youtube-summarizer-server", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "node_modules/@google/genai": { + "version": "1.41.0", + "resolved": "https://registry.npmjs.org/@google/genai/-/genai-1.41.0.tgz", + "integrity": "sha512-S4WGil+PG0NBQRAx+0yrQuM/TWOLn2gGEy5wn4IsoOI6ouHad0P61p3OWdhJ3aqr9kfj8o904i/jevfaGoGuIQ==", + "license": "Apache-2.0", + "dependencies": { + "google-auth-library": "^10.3.0", + "p-retry": "^7.1.1", + "protobufjs": "^7.5.4", + "ws": "^8.18.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@modelcontextprotocol/sdk": "^1.25.2" + }, + "peerDependenciesMeta": { + "@modelcontextprotocol/sdk": { + "optional": true + } + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "license": "BSD-3-Clause" + }, + "node_modules/@types/node": { + "version": "25.2.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.2.3.tgz", + "integrity": "sha512-m0jEgYlYz+mDJZ2+F4v8D1AyQb+QzsNqRuI7xg1VQX/KlKS0qT9r1Mo16yo5F/MtifXFgaofIFsdFMox2SxIbQ==", + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/bignumber.js": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz", + "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/body-parser": { + "version": "1.20.4", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", + "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.14.0", + "raw-body": "~2.5.3", + "type-is": "~1.6.18", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "license": "BSD-3-Clause" + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", + "license": "MIT" + }, + "node_modules/cors": { + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", + "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT" + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", + "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "~1.20.3", + "content-disposition": "~0.5.4", + "content-type": "~1.0.4", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "~0.1.12", + "proxy-addr": "~2.0.7", + "qs": "~6.14.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "~0.19.0", + "serve-static": "~1.16.2", + "setprototypeof": "1.2.0", + "statuses": "~2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, + "node_modules/finalhandler": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "statuses": "~2.0.2", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "license": "MIT", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gaxios": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.3.tgz", + "integrity": "sha512-YGGyuEdVIjqxkxVH1pUTMY/XtmmsApXrCVv5EU25iX6inEPbV+VakJfLealkBtJN69AQmh1eGOdCl9Sm1UP6XQ==", + "license": "Apache-2.0", + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "node-fetch": "^3.3.2", + "rimraf": "^5.0.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/gcp-metadata": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-8.1.2.tgz", + "integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==", + "license": "Apache-2.0", + "dependencies": { + "gaxios": "^7.0.0", + "google-logging-utils": "^1.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/google-auth-library": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.5.0.tgz", + "integrity": "sha512-7ABviyMOlX5hIVD60YOfHw4/CxOfBhyduaYB+wbFWCWoni4N7SLcV46hrVRktuBbZjFC9ONyqamZITN7q3n32w==", + "license": "Apache-2.0", + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^7.0.0", + "gcp-metadata": "^8.0.0", + "google-logging-utils": "^1.0.0", + "gtoken": "^8.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/google-logging-utils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz", + "integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gtoken": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-8.0.0.tgz", + "integrity": "sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw==", + "license": "MIT", + "dependencies": { + "gaxios": "^7.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/https-proxy-agent/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-network-error": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.3.0.tgz", + "integrity": "sha512-6oIwpsgRfnDiyEDLMay/GqCl3HoAtH5+RUKW29gYkL0QA+ipzpDLA16yQs7/RHCSu+BwgbJaOUqa4A99qNVQVw==", + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "license": "MIT", + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, + "node_modules/jwa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", + "license": "MIT", + "dependencies": { + "jwa": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "license": "Apache-2.0" + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "deprecated": "Use your platform's native DOMException instead", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/p-retry": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-7.1.1.tgz", + "integrity": "sha512-J5ApzjyRkkf601HpEeykoiCvzHQjWxPAHhyjFcEUP2SWq0+35NKh8TLhpLw+Dkq5TZBFvUM6UigdE9hIVYTl5w==", + "license": "MIT", + "dependencies": { + "is-network-error": "^1.1.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0" + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "license": "MIT" + }, + "node_modules/protobufjs": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz", + "integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/qs": { + "version": "6.14.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", + "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/rimraf": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", + "license": "ISC", + "dependencies": { + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/send": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.4.1", + "range-parser": "~1.2.1", + "statuses": "~2.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/serve-static": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "~0.19.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "license": "MIT" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ws": { + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", + "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + } + } +} diff --git a/server/node_modules/@google/genai/LICENSE b/server/node_modules/@google/genai/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/server/node_modules/@google/genai/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/server/node_modules/@google/genai/README.md b/server/node_modules/@google/genai/README.md new file mode 100644 index 0000000..7c679bd --- /dev/null +++ b/server/node_modules/@google/genai/README.md @@ -0,0 +1,609 @@ +# Google Gen AI SDK for TypeScript and JavaScript + +[![NPM Downloads](https://img.shields.io/npm/dw/%40google%2Fgenai)](https://www.npmjs.com/package/@google/genai) +[![Node Current](https://img.shields.io/node/v/%40google%2Fgenai)](https://www.npmjs.com/package/@google/genai) + +---------------------- +**Documentation:** https://googleapis.github.io/js-genai/ + +---------------------- + +The Google Gen AI JavaScript SDK is designed for +TypeScript and JavaScript developers to build applications powered by Gemini. The SDK +supports both the [Gemini Developer API](https://ai.google.dev/gemini-api/docs) +and [Vertex AI](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/overview). + +The Google Gen AI SDK is designed to work with Gemini 2.0+ features. + +> [!CAUTION] +> **API Key Security:** Avoid exposing API keys in client-side code. +> Use server-side implementations in production environments. + +## Code Generation + +Generative models are often unaware of recent API and SDK updates and may suggest outdated or legacy code. + +We recommend using our Code Generation instructions [`codegen_instructions.md`](https://raw.githubusercontent.com/googleapis/js-genai/refs/heads/main/codegen_instructions.md) when generating Google Gen AI SDK code to guide your model towards using the more recent SDK features. Copy and paste the instructions into your development environment to provide the model with the necessary context. + +## Prerequisites + +1. Node.js version 20 or later + +### The following are required for Vertex AI users (excluding Vertex AI Studio) +1. [Select](https://console.cloud.google.com/project) or [create](https://cloud.google.com/resource-manager/docs/creating-managing-projects#creating_a_project) a Google Cloud project. +1. [Enable billing for your project](https://cloud.google.com/billing/docs/how-to/modify-project). +1. [Enable the Vertex AI API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com). +1. [Configure authentication](https://cloud.google.com/docs/authentication) for your project. + * [Install the gcloud CLI](https://cloud.google.com/sdk/docs/install). + * [Initialize the gcloud CLI](https://cloud.google.com/sdk/docs/initializing). + * Create local authentication credentials for your user account: + + ```sh + gcloud auth application-default login + ``` +A list of accepted authentication options are listed in [GoogleAuthOptions](https://github.com/googleapis/google-auth-library-nodejs/blob/3ae120d0a45c95e36c59c9ac8286483938781f30/src/auth/googleauth.ts#L87) interface of google-auth-library-node.js GitHub repo. + +## Installation + +To install the SDK, run the following command: + +```shell +npm install @google/genai +``` + +## Quickstart + +The simplest way to get started is to use an API key from +[Google AI Studio](https://aistudio.google.com/apikey): + +```typescript +import {GoogleGenAI} from '@google/genai'; +const GEMINI_API_KEY = process.env.GEMINI_API_KEY; + +const ai = new GoogleGenAI({apiKey: GEMINI_API_KEY}); + +async function main() { + const response = await ai.models.generateContent({ + model: 'gemini-2.5-flash', + contents: 'Why is the sky blue?', + }); + console.log(response.text); +} + +main(); +``` + +## Initialization + +The Google Gen AI SDK provides support for both the +[Google AI Studio](https://ai.google.dev/gemini-api/docs) and +[Vertex AI](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/overview) + implementations of the Gemini API. + +### Gemini Developer API + +For server-side applications, initialize using an API key, which can +be acquired from [Google AI Studio](https://aistudio.google.com/apikey): + +```typescript +import { GoogleGenAI } from '@google/genai'; +const ai = new GoogleGenAI({apiKey: 'GEMINI_API_KEY'}); +``` + +#### Browser + +> [!CAUTION] +> **API Key Security:** Avoid exposing API keys in client-side code. +> Use server-side implementations in production environments. + +In the browser the initialization code is identical: + + +```typescript +import { GoogleGenAI } from '@google/genai'; +const ai = new GoogleGenAI({apiKey: 'GEMINI_API_KEY'}); +``` + +### Vertex AI + +Sample code for VertexAI initialization: + +```typescript +import { GoogleGenAI } from '@google/genai'; + +const ai = new GoogleGenAI({ + vertexai: true, + project: 'your_project', + location: 'your_location', +}); +``` + +### (Optional) (NodeJS only) Using environment variables: + +For NodeJS environments, you can create a client by configuring the necessary +environment variables. Configuration setup instructions depends on whether +you're using the Gemini Developer API or the Gemini API in Vertex AI. + +**Gemini Developer API:** Set `GOOGLE_API_KEY` as shown below: + +```bash +export GOOGLE_API_KEY='your-api-key' +``` + +**Gemini API on Vertex AI:** Set `GOOGLE_GENAI_USE_VERTEXAI`, +`GOOGLE_CLOUD_PROJECT` and `GOOGLE_CLOUD_LOCATION`, as shown below: + +```bash +export GOOGLE_GENAI_USE_VERTEXAI=true +export GOOGLE_CLOUD_PROJECT='your-project-id' +export GOOGLE_CLOUD_LOCATION='us-central1' +``` + +```typescript +import {GoogleGenAI} from '@google/genai'; + +const ai = new GoogleGenAI(); +``` + +## API Selection + +By default, the SDK uses the beta API endpoints provided by Google to support +preview features in the APIs. The stable API endpoints can be selected by +setting the API version to `v1`. + +To set the API version use `apiVersion`. For example, to set the API version to +`v1` for Vertex AI: + +```typescript +const ai = new GoogleGenAI({ + vertexai: true, + project: 'your_project', + location: 'your_location', + apiVersion: 'v1' +}); +``` + +To set the API version to `v1alpha` for the Gemini Developer API: + +```typescript +const ai = new GoogleGenAI({ + apiKey: 'GEMINI_API_KEY', + apiVersion: 'v1alpha' +}); +``` + +## GoogleGenAI overview + +All API features are accessed through an instance of the `GoogleGenAI` classes. +The submodules bundle together related API methods: + +- [`ai.models`](https://googleapis.github.io/js-genai/release_docs/classes/models.Models.html): + Use `models` to query models (`generateContent`, `generateImages`, ...), or + examine their metadata. +- [`ai.caches`](https://googleapis.github.io/js-genai/release_docs/classes/caches.Caches.html): + Create and manage `caches` to reduce costs when repeatedly using the same + large prompt prefix. +- [`ai.chats`](https://googleapis.github.io/js-genai/release_docs/classes/chats.Chats.html): + Create local stateful `chat` objects to simplify multi turn interactions. +- [`ai.files`](https://googleapis.github.io/js-genai/release_docs/classes/files.Files.html): + Upload `files` to the API and reference them in your prompts. + This reduces bandwidth if you use a file many times, and handles files too + large to fit inline with your prompt. +- [`ai.live`](https://googleapis.github.io/js-genai/release_docs/classes/live.Live.html): + Start a `live` session for real time interaction, allows text + audio + video + input, and text or audio output. + +## Samples + +More samples can be found in the +[github samples directory](https://github.com/googleapis/js-genai/tree/main/sdk-samples). + +### Streaming + +For quicker, more responsive API interactions use the `generateContentStream` +method which yields chunks as they're generated: + +```typescript +import {GoogleGenAI} from '@google/genai'; +const GEMINI_API_KEY = process.env.GEMINI_API_KEY; + +const ai = new GoogleGenAI({apiKey: GEMINI_API_KEY}); + +async function main() { + const response = await ai.models.generateContentStream({ + model: 'gemini-2.5-flash', + contents: 'Write a 100-word poem.', + }); + for await (const chunk of response) { + console.log(chunk.text); + } +} + +main(); +``` + +### Function Calling + +To let Gemini to interact with external systems, you can provide +`functionDeclaration` objects as `tools`. To use these tools it's a 4 step + +1. **Declare the function name, description, and parametersJsonSchema** +2. **Call `generateContent` with function calling enabled** +3. **Use the returned `FunctionCall` parameters to call your actual function** +3. **Send the result back to the model (with history, easier in `ai.chat`) + as a `FunctionResponse`** + +```typescript +import {GoogleGenAI, FunctionCallingConfigMode, FunctionDeclaration, Type} from '@google/genai'; +const GEMINI_API_KEY = process.env.GEMINI_API_KEY; + +async function main() { + const controlLightDeclaration: FunctionDeclaration = { + name: 'controlLight', + parametersJsonSchema: { + type: 'object', + properties:{ + brightness: { + type:'number', + }, + colorTemperature: { + type:'string', + }, + }, + required: ['brightness', 'colorTemperature'], + }, + }; + + const ai = new GoogleGenAI({apiKey: GEMINI_API_KEY}); + const response = await ai.models.generateContent({ + model: 'gemini-2.5-flash', + contents: 'Dim the lights so the room feels cozy and warm.', + config: { + toolConfig: { + functionCallingConfig: { + // Force it to call any function + mode: FunctionCallingConfigMode.ANY, + allowedFunctionNames: ['controlLight'], + } + }, + tools: [{functionDeclarations: [controlLightDeclaration]}] + } + }); + + console.log(response.functionCalls); +} + +main(); +``` + +#### Model Context Protocol (MCP) support (experimental) + +Built-in [MCP](https://modelcontextprotocol.io/introduction) support is an +experimental feature. You can pass a local MCP server as a tool directly. + +```javascript +import { GoogleGenAI, FunctionCallingConfigMode , mcpToTool} from '@google/genai'; +import { Client } from "@modelcontextprotocol/sdk/client/index.js"; +import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js"; + +// Create server parameters for stdio connection +const serverParams = new StdioClientTransport({ + command: "npx", // Executable + args: ["-y", "@philschmid/weather-mcp"] // MCP Server +}); + +const client = new Client( + { + name: "example-client", + version: "1.0.0" + } +); + +// Configure the client +const ai = new GoogleGenAI({}); + +// Initialize the connection between client and server +await client.connect(serverParams); + +// Send request to the model with MCP tools +const response = await ai.models.generateContent({ + model: "gemini-2.5-flash", + contents: `What is the weather in London in ${new Date().toLocaleDateString()}?`, + config: { + tools: [mcpToTool(client)], // uses the session, will automatically call the tool using automatic function calling + }, +}); +console.log(response.text); + +// Close the connection +await client.close(); +``` + +### Generate Content + +#### How to structure `contents` argument for `generateContent` + +The SDK allows you to specify the following types in the `contents` parameter: + +#### Content + +- `Content`: The SDK will wrap the singular `Content` instance in an array which +contains only the given content instance +- `Content[]`: No transformation happens + +#### Part + +Parts will be aggregated on a singular Content, with role 'user'. + +- `Part | string`: The SDK will wrap the `string` or `Part` in a `Content` +instance with role 'user'. +- `Part[] | string[]`: The SDK will wrap the full provided list into a single +`Content` with role 'user'. + +**_NOTE:_** This doesn't apply to `FunctionCall` and `FunctionResponse` parts, +if you are specifying those, you need to explicitly provide the full +`Content[]` structure making it explicit which Parts are 'spoken' by the model, +or the user. The SDK will throw an exception if you try this. + +## Error Handling + +To handle errors raised by the API, the SDK provides this [ApiError](https://github.com/googleapis/js-genai/blob/main/src/errors.ts) class. + +```typescript +import {GoogleGenAI} from '@google/genai'; +const GEMINI_API_KEY = process.env.GEMINI_API_KEY; + +const ai = new GoogleGenAI({apiKey: GEMINI_API_KEY}); + +async function main() { + await ai.models.generateContent({ + model: 'non-existent-model', + contents: 'Write a 100-word poem.', + }).catch((e) => { + console.error('error name: ', e.name); + console.error('error message: ', e.message); + console.error('error status: ', e.status); + }); +} + +main(); +``` + +## Interactions (Preview) + +> **Warning:** The Interactions API is in **Beta**. This is a preview of an +experimental feature. Features and schemas are subject to **breaking changes**. + +The Interactions API is a unified interface for interacting with Gemini models +and agents. It simplifies state management, tool orchestration, and long-running +tasks. + +See the [documentation site](https://ai.google.dev/gemini-api/docs/interactions) +for more details. + +### Basic Interaction + +```typescript +const interaction = await ai.interactions.create({ + model: 'gemini-2.5-flash', + input: 'Hello, how are you?', +}); +console.debug(interaction); + +``` + +### Stateful Conversation + +The Interactions API supports server-side state management. You can continue a +conversation by referencing the `previous_interaction_id`. + +```typescript +// 1. First turn +const interaction1 = await ai.interactions.create({ + model: 'gemini-2.5-flash', + input: 'Hi, my name is Amir.', +}); +console.debug(interaction1); + +// 2. Second turn (passing previous_interaction_id) +const interaction2 = await ai.interactions.create({ + model: 'gemini-2.5-flash', + input: 'What is my name?', + previous_interaction_id: interaction1.id, +}); +console.debug(interaction2); + +``` + +### Agents (Deep Research) + +You can use specialized agents like `deep-research-pro-preview-12-2025` for +complex tasks. + +```typescript +function sleep(ms: number): Promise<void> { + return new Promise(resolve => setTimeout(resolve, ms)); +} + +// 1. Start the Deep Research Agent +const initialInteraction = await ai.interactions.create({ + input: + 'Research the history of the Google TPUs with a focus on 2025 and 2026.', + agent: 'deep-research-pro-preview-12-2025', + background: true, +}); + +console.log(`Research started. Interaction ID: ${initialInteraction.id}`); + +// 2. Poll for results +while (true) { + const interaction = await ai.interactions.get(initialInteraction.id); + console.log(`Status: ${interaction.status}`); + + if (interaction.status === 'completed') { + console.debug('\nFinal Report:\n', interaction.outputs); + break; + } else if (['failed', 'cancelled'].includes(interaction.status)) { + console.log(`Failed with status: ${interaction.status}`); + break; + } + + await sleep(10000); // Sleep for 10 seconds +} + +``` + +### Multimodal Input + +You can provide multimodal data (text, images, audio, etc.) in the input list. + +```typescript +import base64 + +// Assuming you have a base64 string +// const base64Image = ...; + +const interaction = await ai.interactions.create({ + model: 'gemini-2.5-flash', + input: [ + { type: 'text', text: 'Describe the image.' }, + { type: 'image', data: base64Image, mime_type: 'image/png' }, + ], +}); + +console.debug(interaction); + +``` + +### Function Calling + +You can define custom functions for the model to use. The Interactions API +handles the tool selection, and you provide the execution result back to the +model. + +```typescript +// 1. Define the tool +const getWeather = (location: string) => { + /* Gets the weather for a given location. */ + return `The weather in ${location} is sunny.`; +}; + +// 2. Send the request with tools +let interaction = await ai.interactions.create({ + model: 'gemini-2.5-flash', + input: 'What is the weather in Mountain View, CA?', + tools: [ + { + type: 'function', + name: 'get_weather', + description: 'Gets the weather for a given location.', + parameters: { + type: 'object', + properties: { + location: { + type: 'string', + description: 'The city and state, e.g. San Francisco, CA', + }, + }, + required: ['location'], + }, + }, + ], +}); + +// 3. Handle the tool call +for (const output of interaction.outputs!) { + if (output.type === 'function_call') { + console.log( + `Tool Call: ${output.name}(${JSON.stringify(output.arguments)})`); + + // Execute your actual function here + // Note: ensure arguments match your function signature + const result = getWeather(JSON.stringify(output.arguments.location)); + + // Send result back to the model + interaction = await ai.interactions.create({ + model: 'gemini-2.5-flash', + previous_interaction_id: interaction.id, + input: [ + { + type: 'function_result', + name: output.name, + call_id: output.id, + result: result, + }, + ], + }); + + console.debug(`Response: ${JSON.stringify(interaction)}`); + } +} + +``` + +### Built-in Tools +You can also use Google's built-in tools, such as **Google Search** or **Code +Execution**. + +#### Grounding with Google Search + +```typescript +const interaction = await ai.interactions.create({ + model: 'gemini-2.5-flash', + input: 'Who won the last Super Bowl', + tools: [{ type: 'google_search' }], +}); + +console.debug(interaction); + +``` + +#### Code Execution + +```typescript +const interaction = await ai.interactions.create({ + model: 'gemini-2.5-flash', + input: 'Calculate the 50th Fibonacci number.', + tools: [{ type: 'code_execution' }], +}); + +console.debug(interaction); + +``` + +### Multimodal Output + +The Interactions API can generate multimodal outputs, such as images. You must +specify the `response_modalities`. + +```typescript +import * as fs from 'fs'; + +const interaction = await ai.interactions.create({ + model: 'gemini-3-pro-image-preview', + input: 'Generate an image of a futuristic city.', + response_modalities: ['image'], +}); + +for (const output of interaction.outputs!) { + if (output.type === 'image') { + console.log(`Generated image with mime_type: ${output.mime_type}`); + // Save the image + fs.writeFileSync( + 'generated_city.png', Buffer.from(output.data!, 'base64')); + } +} + +``` + +## How is this different from the other Google AI SDKs +This SDK (`@google/genai`) is Google Deepmind’s "vanilla" SDK for its generative +AI offerings, and is where Google Deepmind adds new AI features. + +Models hosted either on the [Vertex AI platform](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/overview) or the [Gemini Developer platform](https://ai.google.dev/gemini-api/docs) are accessible through this SDK. + +Other SDKs may be offering additional AI frameworks on top of this SDK, or may +be targeting specific project environments (like Firebase). + +The `@google/generative_language` and `@google-cloud/vertexai` SDKs are previous +iterations of this SDK and are no longer receiving new Gemini 2.0+ features. diff --git a/server/node_modules/@google/genai/dist/genai.d.ts b/server/node_modules/@google/genai/dist/genai.d.ts new file mode 100644 index 0000000..fb62660 --- /dev/null +++ b/server/node_modules/@google/genai/dist/genai.d.ts @@ -0,0 +1,11244 @@ +/// <reference types="node" /> + +import type { Client } from '@modelcontextprotocol/sdk/client/index.js'; +import { GoogleAuthOptions } from 'google-auth-library'; +import { ReadableStream as ReadableStream_2 } from 'stream/web'; + +/** Marks the end of user activity. + + This can only be sent if automatic (i.e. server-side) activity detection is + disabled. */ +export declare interface ActivityEnd { +} + +/** The different ways of handling user activity. */ +export declare enum ActivityHandling { + /** + * If unspecified, the default behavior is `START_OF_ACTIVITY_INTERRUPTS`. + */ + ACTIVITY_HANDLING_UNSPECIFIED = "ACTIVITY_HANDLING_UNSPECIFIED", + /** + * If true, start of activity will interrupt the model's response (also called "barge in"). The model's current response will be cut-off in the moment of the interruption. This is the default behavior. + */ + START_OF_ACTIVITY_INTERRUPTS = "START_OF_ACTIVITY_INTERRUPTS", + /** + * The model's response will not be interrupted. + */ + NO_INTERRUPTION = "NO_INTERRUPTION" +} + +/** Marks the start of user activity. + + This can only be sent if automatic (i.e. server-side) activity detection is + disabled. */ +export declare interface ActivityStart { +} + +/** Adapter size for tuning. This enum is not supported in Gemini API. */ +export declare enum AdapterSize { + /** + * Adapter size is unspecified. + */ + ADAPTER_SIZE_UNSPECIFIED = "ADAPTER_SIZE_UNSPECIFIED", + /** + * Adapter size 1. + */ + ADAPTER_SIZE_ONE = "ADAPTER_SIZE_ONE", + /** + * Adapter size 2. + */ + ADAPTER_SIZE_TWO = "ADAPTER_SIZE_TWO", + /** + * Adapter size 4. + */ + ADAPTER_SIZE_FOUR = "ADAPTER_SIZE_FOUR", + /** + * Adapter size 8. + */ + ADAPTER_SIZE_EIGHT = "ADAPTER_SIZE_EIGHT", + /** + * Adapter size 16. + */ + ADAPTER_SIZE_SIXTEEN = "ADAPTER_SIZE_SIXTEEN", + /** + * Adapter size 32. + */ + ADAPTER_SIZE_THIRTY_TWO = "ADAPTER_SIZE_THIRTY_TWO" +} + +/** + * The configuration for allowed tools. + */ +declare interface AllowedTools { + /** + * The mode of the tool choice. + */ + mode?: ToolChoiceType; + /** + * The names of the allowed tools. + */ + tools?: Array<string>; +} + +/** + * Citation information for model-generated content. + */ +declare interface Annotation { + /** + * End of the attributed segment, exclusive. + */ + end_index?: number; + /** + * Source attributed for a portion of the text. Could be a URL, title, or + * other identifier. + */ + source?: string; + /** + * Start of segment of the response that is attributed to this source. + * + * Index indicates the start of the segment, measured in bytes. + */ + start_index?: number; +} + +/** The generic reusable api auth config. Deprecated. Please use AuthConfig (google/cloud/aiplatform/master/auth.proto) instead. This data type is not supported in Gemini API. */ +export declare interface ApiAuth { + /** The API secret. */ + apiKeyConfig?: ApiAuthApiKeyConfig; +} + +/** The API secret. This data type is not supported in Gemini API. */ +export declare interface ApiAuthApiKeyConfig { + /** Required. The SecretManager secret version resource name storing API key. e.g. projects/{project}/secrets/{secret}/versions/{version} */ + apiKeySecretVersion?: string; + /** The API key string. Either this or `api_key_secret_version` must be set. */ + apiKeyString?: string; +} + +/** + * The ApiClient class is used to send requests to the Gemini API or Vertex AI + * endpoints. + */ +declare class ApiClient implements GeminiNextGenAPIClientAdapter { + readonly clientOptions: ApiClientInitOptions; + private readonly customBaseUrl?; + constructor(opts: ApiClientInitOptions); + isVertexAI(): boolean; + getProject(): string | undefined; + getLocation(): string | undefined; + getCustomBaseUrl(): string | undefined; + getAuthHeaders(): Promise<Headers>; + getApiVersion(): string; + getBaseUrl(): string; + getRequestUrl(): string; + getHeaders(): Record<string, string>; + private getRequestUrlInternal; + getBaseResourcePath(): string; + getApiKey(): string | undefined; + getWebsocketBaseUrl(): string; + setBaseUrl(url: string): void; + private constructUrl; + private shouldPrependVertexProjectPath; + request(request: HttpRequest): Promise<types.HttpResponse>; + private patchHttpOptions; + requestStream(request: HttpRequest): Promise<AsyncGenerator<types.HttpResponse>>; + private includeExtraHttpOptionsToRequestInit; + private unaryApiCall; + private streamApiCall; + processStreamResponse(response: Response): AsyncGenerator<types.HttpResponse>; + private apiCall; + getDefaultHeaders(): Record<string, string>; + private getHeadersInternal; + private getFileName; + /** + * Uploads a file asynchronously using Gemini API only, this is not supported + * in Vertex AI. + * + * @param file The string path to the file to be uploaded or a Blob object. + * @param config Optional parameters specified in the `UploadFileConfig` + * interface. @see {@link types.UploadFileConfig} + * @return A promise that resolves to a `File` object. + * @throws An error if called on a Vertex AI client. + * @throws An error if the `mimeType` is not provided and can not be inferred, + */ + uploadFile(file: string | Blob, config?: types.UploadFileConfig): Promise<types.File>; + /** + * Uploads a file to a given file search store asynchronously using Gemini API only, this is not supported + * in Vertex AI. + * + * @param fileSearchStoreName The name of the file search store to upload the file to. + * @param file The string path to the file to be uploaded or a Blob object. + * @param config Optional parameters specified in the `UploadFileConfig` + * interface. @see {@link UploadFileConfig} + * @return A promise that resolves to a `File` object. + * @throws An error if called on a Vertex AI client. + * @throws An error if the `mimeType` is not provided and can not be inferred, + */ + uploadFileToFileSearchStore(fileSearchStoreName: string, file: string | Blob, config?: types.UploadToFileSearchStoreConfig): Promise<types.UploadToFileSearchStoreOperation>; + /** + * Downloads a file asynchronously to the specified path. + * + * @params params - The parameters for the download request, see {@link + * types.DownloadFileParameters} + */ + downloadFile(params: types.DownloadFileParameters): Promise<void>; + private fetchUploadUrl; +} + +/** + * Options for initializing the ApiClient. The ApiClient uses the parameters + * for authentication purposes as well as to infer if SDK should send the + * request to Vertex AI or Gemini API. + */ +declare interface ApiClientInitOptions { + /** + * The object used for adding authentication headers to API requests. + */ + auth: Auth; + /** + * The uploader to use for uploading files. This field is required for + * creating a client, will be set through the Node_client or Web_client. + */ + uploader: Uploader; + /** + * Optional. The downloader to use for downloading files. This field is + * required for creating a client, will be set through the Node_client or + * Web_client. + */ + downloader: Downloader; + /** + * Optional. The Google Cloud project ID for Vertex AI users. + * It is not the numeric project name. + * If not provided, SDK will try to resolve it from runtime environment. + */ + project?: string; + /** + * Optional. The Google Cloud project location for Vertex AI users. + * If not provided, SDK will try to resolve it from runtime environment. + */ + location?: string; + /** + * The API Key. This is required for Gemini API users. + */ + apiKey?: string; + /** + * Optional. Set to true if you intend to call Vertex AI endpoints. + * If unset, default SDK behavior is to call Gemini API. + */ + vertexai?: boolean; + /** + * Optional. The API version for the endpoint. + * If unset, SDK will choose a default api version. + */ + apiVersion?: string; + /** + * Optional. A set of customizable configuration for HTTP requests. + */ + httpOptions?: types.HttpOptions; + /** + * Optional. An extra string to append at the end of the User-Agent header. + * + * This can be used to e.g specify the runtime and its version. + */ + userAgentExtra?: string; +} + +declare class APIConnectionError extends APIError<undefined, undefined, undefined> { + constructor({ message, cause }: { + message?: string | undefined; + cause?: Error | undefined; + }); +} + +declare class APIConnectionTimeoutError extends APIConnectionError { + constructor({ message }?: { + message?: string; + }); +} + +declare class APIError<TStatus extends number | undefined = number | undefined, THeaders extends Headers | undefined = Headers | undefined, TError extends Object | undefined = Object | undefined> extends GeminiNextGenAPIClientError { + /** HTTP status for the response that caused the error */ + readonly status: TStatus; + /** HTTP headers for the response that caused the error */ + readonly headers: THeaders; + /** JSON body of the response that caused the error */ + readonly error: TError; + constructor(status: TStatus, error: TError, message: string | undefined, headers: THeaders); + private static makeMessage; + static generate(status: number | undefined, errorResponse: Object | undefined, message: string | undefined, headers: Headers | undefined): APIError; +} + +/** + * API errors raised by the GenAI API. + */ +export declare class ApiError extends Error { + /** HTTP status code */ + status: number; + constructor(options: ApiErrorInfo); +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Details for errors from calling the API. + */ +export declare interface ApiErrorInfo { + /** The error message. */ + message: string; + /** The HTTP status code. */ + status: number; +} + +/** Config for authentication with API key. This data type is not supported in Gemini API. */ +export declare interface ApiKeyConfig { + /** Optional. The name of the SecretManager secret version resource storing the API key. Format: `projects/{project}/secrets/{secrete}/versions/{version}` - If both `api_key_secret` and `api_key_string` are specified, this field takes precedence over `api_key_string`. - If specified, the `secretmanager.versions.access` permission should be granted to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents) on the specified resource. */ + apiKeySecret?: string; + /** Optional. The API key to be used in the request directly. */ + apiKeyString?: string; + /** Optional. The location of the API key. */ + httpElementLocation?: HttpElementLocation; + /** Optional. The parameter name of the API key. E.g. If the API request is "https://example.com/act?api_key=", "api_key" would be the parameter name. */ + name?: string; +} + +/** + * A subclass of `Promise` providing additional helper methods + * for interacting with the SDK. + */ +declare class APIPromise<T> extends Promise<T> { + private responsePromise; + private parseResponse; + private parsedPromise; + private client; + constructor(client: BaseGeminiNextGenAPIClient, responsePromise: Promise<APIResponseProps>, parseResponse?: (client: BaseGeminiNextGenAPIClient, props: APIResponseProps) => PromiseOrValue<T>); + _thenUnwrap<U>(transform: (data: T, props: APIResponseProps) => U): APIPromise<U>; + /** + * Gets the raw `Response` instance instead of parsing the response + * data. + * + * If you want to parse the response body but still get the `Response` + * instance, you can use {@link withResponse()}. + * + * 👋 Getting the wrong TypeScript type for `Response`? + * Try setting `"moduleResolution": "NodeNext"` or add `"lib": ["DOM"]` + * to your `tsconfig.json`. + */ + asResponse(): Promise<Response>; + /** + * Gets the parsed response data and the raw `Response` instance. + * + * If you just want to get the raw `Response` instance without parsing it, + * you can use {@link asResponse()}. + * + * 👋 Getting the wrong TypeScript type for `Response`? + * Try setting `"moduleResolution": "NodeNext"` or add `"lib": ["DOM"]` + * to your `tsconfig.json`. + */ + withResponse(): Promise<{ + data: T; + response: Response; + }>; + private parse; + then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>; + catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): Promise<T | TResult>; + finally(onfinally?: (() => void) | undefined | null): Promise<T>; +} + +declare abstract class APIResource { + /** + * The key path from the client. For example, a resource accessible as `client.resource.subresource` would + * have a property `static override readonly _key = Object.freeze(['resource', 'subresource'] as const);`. + */ + static readonly _key: readonly string[]; + protected _client: BaseGeminiNextGenAPIClient; + constructor(client: BaseGeminiNextGenAPIClient); +} + +declare type APIResponseProps = { + response: Response; + options: FinalRequestOptions; + controller: AbortController; + requestLogID: string; + retryOfRequestLogID: string | undefined; + startTime: number; +}; + +/** The API spec that the external API implements. This enum is not supported in Gemini API. */ +export declare enum ApiSpec { + /** + * Unspecified API spec. This value should not be used. + */ + API_SPEC_UNSPECIFIED = "API_SPEC_UNSPECIFIED", + /** + * Simple search API spec. + */ + SIMPLE_SEARCH = "SIMPLE_SEARCH", + /** + * Elastic search API spec. + */ + ELASTIC_SEARCH = "ELASTIC_SEARCH" +} + +declare class APIUserAbortError extends APIError<undefined, undefined, undefined> { + constructor({ message }?: { + message?: string; + }); +} + +/** Representation of an audio chunk. */ +export declare interface AudioChunk { + /** Raw bytes of audio data. + * @remarks Encoded as base64 string. */ + data?: string; + /** MIME type of the audio chunk. */ + mimeType?: string; + /** Prompts and config used for generating this audio chunk. */ + sourceMetadata?: LiveMusicSourceMetadata; +} + +/** + * An audio content block. + */ +declare interface AudioContent { + type: 'audio'; + /** + * The audio content. + */ + data?: string; + /** + * The mime type of the audio. + */ + mime_type?: AudioMimeType; + /** + * The URI of the audio. + */ + uri?: string; +} + +/** + * The mime type of the audio. + */ +declare type AudioMimeType = 'audio/wav' | 'audio/mp3' | 'audio/aiff' | 'audio/aac' | 'audio/ogg' | 'audio/flac' | (string & {}); + +/** The audio transcription configuration in Setup. */ +export declare interface AudioTranscriptionConfig { +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * The Auth interface is used to authenticate with the API service. + */ +declare interface Auth { + /** + * Sets the headers needed to authenticate with the API service. + * + * @param headers - The Headers object that will be updated with the authentication headers. + * @param url - The URL of the request. + */ + addAuthHeaders(headers: Headers, url?: string): Promise<void>; +} + +/** Auth configuration to run the extension. This data type is not supported in Gemini API. */ +export declare interface AuthConfig { + /** Config for API key auth. */ + apiKeyConfig?: ApiKeyConfig; + /** Type of auth scheme. */ + authType?: AuthType; + /** Config for Google Service Account auth. */ + googleServiceAccountConfig?: AuthConfigGoogleServiceAccountConfig; + /** Config for HTTP Basic auth. */ + httpBasicAuthConfig?: AuthConfigHttpBasicAuthConfig; + /** Config for user oauth. */ + oauthConfig?: AuthConfigOauthConfig; + /** Config for user OIDC auth. */ + oidcConfig?: AuthConfigOidcConfig; +} + +/** Config for Google Service Account Authentication. This data type is not supported in Gemini API. */ +export declare interface AuthConfigGoogleServiceAccountConfig { + /** Optional. The service account that the extension execution service runs as. - If the service account is specified, the `iam.serviceAccounts.getAccessToken` permission should be granted to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents) on the specified service account. - If not specified, the Vertex AI Extension Service Agent will be used to execute the Extension. */ + serviceAccount?: string; +} + +/** Config for HTTP Basic Authentication. This data type is not supported in Gemini API. */ +export declare interface AuthConfigHttpBasicAuthConfig { + /** Required. The name of the SecretManager secret version resource storing the base64 encoded credentials. Format: `projects/{project}/secrets/{secrete}/versions/{version}` - If specified, the `secretmanager.versions.access` permission should be granted to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents) on the specified resource. */ + credentialSecret?: string; +} + +/** Config for user oauth. This data type is not supported in Gemini API. */ +export declare interface AuthConfigOauthConfig { + /** Access token for extension endpoint. Only used to propagate token from [[ExecuteExtensionRequest.runtime_auth_config]] at request time. */ + accessToken?: string; + /** The service account used to generate access tokens for executing the Extension. - If the service account is specified, the `iam.serviceAccounts.getAccessToken` permission should be granted to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents) on the provided service account. */ + serviceAccount?: string; +} + +/** Config for user OIDC auth. This data type is not supported in Gemini API. */ +export declare interface AuthConfigOidcConfig { + /** OpenID Connect formatted ID token for extension endpoint. Only used to propagate token from [[ExecuteExtensionRequest.runtime_auth_config]] at request time. */ + idToken?: string; + /** The service account used to generate an OpenID Connect (OIDC)-compatible JWT token signed by the Google OIDC Provider (accounts.google.com) for extension endpoint (https://cloud.google.com/iam/docs/create-short-lived-credentials-direct#sa-credentials-oidc). - The audience for the token will be set to the URL in the server url defined in the OpenApi spec. - If the service account is provided, the service account should grant `iam.serviceAccounts.getOpenIdToken` permission to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents). */ + serviceAccount?: string; +} + +declare class AuthenticationError extends APIError<401, Headers> { +} + +/** Config for auth_tokens.create parameters. */ +export declare interface AuthToken { + /** The name of the auth token. */ + name?: string; +} + +/** Type of auth scheme. This enum is not supported in Gemini API. */ +export declare enum AuthType { + AUTH_TYPE_UNSPECIFIED = "AUTH_TYPE_UNSPECIFIED", + /** + * No Auth. + */ + NO_AUTH = "NO_AUTH", + /** + * API Key Auth. + */ + API_KEY_AUTH = "API_KEY_AUTH", + /** + * HTTP Basic Auth. + */ + HTTP_BASIC_AUTH = "HTTP_BASIC_AUTH", + /** + * Google Service Account Auth. + */ + GOOGLE_SERVICE_ACCOUNT_AUTH = "GOOGLE_SERVICE_ACCOUNT_AUTH", + /** + * OAuth auth. + */ + OAUTH = "OAUTH", + /** + * OpenID Connect (OIDC) Auth. + */ + OIDC_AUTH = "OIDC_AUTH" +} + +/** Configures automatic detection of activity. */ +export declare interface AutomaticActivityDetection { + /** If enabled, detected voice and text input count as activity. If disabled, the client must send activity signals. */ + disabled?: boolean; + /** Determines how likely speech is to be detected. */ + startOfSpeechSensitivity?: StartSensitivity; + /** Determines how likely detected speech is ended. */ + endOfSpeechSensitivity?: EndSensitivity; + /** The required duration of detected speech before start-of-speech is committed. The lower this value the more sensitive the start-of-speech detection is and the shorter speech can be recognized. However, this also increases the probability of false positives. */ + prefixPaddingMs?: number; + /** The required duration of detected non-speech (e.g. silence) before end-of-speech is committed. The larger this value, the longer speech gaps can be without interrupting the user's activity but this will increase the model's latency. */ + silenceDurationMs?: number; +} + +/** The configuration for automatic function calling. */ +export declare interface AutomaticFunctionCallingConfig { + /** Whether to disable automatic function calling. + If not set or set to False, will enable automatic function calling. + If set to True, will disable automatic function calling. + */ + disable?: boolean; + /** If automatic function calling is enabled, + maximum number of remote calls for automatic function calling. + This number should be a positive integer. + If not set, SDK will set maximum number of remote calls to 10. + */ + maximumRemoteCalls?: number; + /** If automatic function calling is enabled, + whether to ignore call history to the response. + If not set, SDK will set ignore_call_history to false, + and will append the call history to + GenerateContentResponse.automatic_function_calling_history. + */ + ignoreCallHistory?: boolean; +} + +declare class BadRequestError extends APIError<400, Headers> { +} + +declare interface BaseCreateAgentInteractionParams { + /** + * Path param: Which version of the API to use. + */ + api_version?: string; + /** + * Body param: The name of the `Agent` used for generating the interaction. + */ + agent: (string & {}) | 'deep-research-pro-preview-12-2025'; + /** + * Body param: The inputs for the interaction. + */ + input: string | Array<Content_2> | Array<Turn> | TextContent | ImageContent | AudioContent | DocumentContent | VideoContent | ThoughtContent | FunctionCallContent | FunctionResultContent | CodeExecutionCallContent | CodeExecutionResultContent | URLContextCallContent | URLContextResultContent | GoogleSearchCallContent | GoogleSearchResultContent | MCPServerToolCallContent | MCPServerToolResultContent | FileSearchCallContent | FileSearchResultContent; + /** + * Body param: Configuration for the agent. + */ + agent_config?: DynamicAgentConfig | DeepResearchAgentConfig; + /** + * Body param: Input only. Whether to run the model interaction in the background. + */ + background?: boolean; + /** + * Body param: The ID of the previous interaction, if any. + */ + previous_interaction_id?: string; + /** + * Body param: Enforces that the generated response is a JSON object that complies with + * the JSON schema specified in this field. + */ + response_format?: unknown; + /** + * Body param: The mime type of the response. This is required if response_format is set. + */ + response_mime_type?: string; + /** + * Body param: The requested modalities of the response (TEXT, IMAGE, AUDIO). + */ + response_modalities?: Array<'text' | 'image' | 'audio'>; + /** + * Body param: Input only. Whether to store the response and request for later retrieval. + */ + store?: boolean; + /** + * Body param: Input only. Whether the interaction will be streamed. + */ + stream?: boolean; + /** + * Body param: System instruction for the interaction. + */ + system_instruction?: string; + /** + * Body param: A list of tool declarations the model may call during interaction. + */ + tools?: Array<Tool_2>; +} + +declare interface BaseCreateModelInteractionParams { + /** + * Path param: Which version of the API to use. + */ + api_version?: string; + /** + * Body param: The inputs for the interaction. + */ + input: string | Array<Content_2> | Array<Turn> | TextContent | ImageContent | AudioContent | DocumentContent | VideoContent | ThoughtContent | FunctionCallContent | FunctionResultContent | CodeExecutionCallContent | CodeExecutionResultContent | URLContextCallContent | URLContextResultContent | GoogleSearchCallContent | GoogleSearchResultContent | MCPServerToolCallContent | MCPServerToolResultContent | FileSearchCallContent | FileSearchResultContent; + /** + * Body param: The name of the `Model` used for generating the interaction. + */ + model: Model_2; + /** + * Body param: Input only. Whether to run the model interaction in the background. + */ + background?: boolean; + /** + * Body param: Input only. Configuration parameters for the model interaction. + */ + generation_config?: GenerationConfig_2; + /** + * Body param: The ID of the previous interaction, if any. + */ + previous_interaction_id?: string; + /** + * Body param: Enforces that the generated response is a JSON object that complies with + * the JSON schema specified in this field. + */ + response_format?: unknown; + /** + * Body param: The mime type of the response. This is required if response_format is set. + */ + response_mime_type?: string; + /** + * Body param: The requested modalities of the response (TEXT, IMAGE, AUDIO). + */ + response_modalities?: Array<'text' | 'image' | 'audio'>; + /** + * Body param: Input only. Whether to store the response and request for later retrieval. + */ + store?: boolean; + /** + * Body param: Input only. Whether the interaction will be streamed. + */ + stream?: boolean; + /** + * Body param: System instruction for the interaction. + */ + system_instruction?: string; + /** + * Body param: A list of tool declarations the model may call during interaction. + */ + tools?: Array<Tool_2>; +} + +/** + * Base class for Gemini Next Gen API API clients. + */ +declare class BaseGeminiNextGenAPIClient { + apiKey: string | null; + apiVersion: string; + baseURL: string; + maxRetries: number; + timeout: number; + logger: Logger; + logLevel: LogLevel | undefined; + fetchOptions: MergedRequestInit | undefined; + private fetch; + private encoder; + protected idempotencyHeader?: string; + private _options; + private clientAdapter; + /** + * API Client for interfacing with the Gemini Next Gen API API. + * + * @param {string | null | undefined} [opts.apiKey=process.env['GEMINI_API_KEY'] ?? null] + * @param {string | undefined} [opts.apiVersion=v1beta] + * @param {string} [opts.baseURL=process.env['GEMINI_NEXT_GEN_API_BASE_URL'] ?? https://generativelanguage.googleapis.com] - Override the default base URL for the API. + * @param {number} [opts.timeout=1 minute] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out. + * @param {MergedRequestInit} [opts.fetchOptions] - Additional `RequestInit` options to be passed to `fetch` calls. + * @param {Fetch} [opts.fetch] - Specify a custom `fetch` function implementation. + * @param {number} [opts.maxRetries=2] - The maximum number of times the client will retry a request. + * @param {HeadersLike} opts.defaultHeaders - Default headers to include with every request to the API. + * @param {Record<string, string | undefined>} opts.defaultQuery - Default query parameters to include with every request to the API. + */ + constructor({ baseURL, apiKey, apiVersion, ...opts }: ClientOptions); + /** + * Create a new client instance re-using the same options given to the current client with optional overriding. + */ + withOptions(options: Partial<ClientOptions>): this; + /** + * Check whether the base URL is set to its default. + */ + private baseURLOverridden; + protected defaultQuery(): Record<string, string | undefined> | undefined; + protected validateHeaders({ values, nulls }: NullableHeaders): void; + protected authHeaders(opts: FinalRequestOptions): Promise<NullableHeaders | undefined>; + /** + * Basic re-implementation of `qs.stringify` for primitive types. + */ + protected stringifyQuery(query: Record<string, unknown>): string; + private getUserAgent; + protected defaultIdempotencyKey(): string; + protected makeStatusError(status: number, error: Object, message: string | undefined, headers: Headers): Errors.APIError; + buildURL(path: string, query: Record<string, unknown> | null | undefined, defaultBaseURL?: string | undefined): string; + /** + * Used as a callback for mutating the given `FinalRequestOptions` object. + + */ + protected prepareOptions(options: FinalRequestOptions): Promise<void>; + /** + * Used as a callback for mutating the given `RequestInit` object. + * + * This is useful for cases where you want to add certain headers based off of + * the request properties, e.g. `method` or `url`. + */ + protected prepareRequest(request: _RequestInit, { url, options }: { + url: string; + options: FinalRequestOptions; + }): Promise<void>; + get<Rsp>(path: string, opts?: PromiseOrValue<RequestOptions>): APIPromise<Rsp>; + post<Rsp>(path: string, opts?: PromiseOrValue<RequestOptions>): APIPromise<Rsp>; + patch<Rsp>(path: string, opts?: PromiseOrValue<RequestOptions>): APIPromise<Rsp>; + put<Rsp>(path: string, opts?: PromiseOrValue<RequestOptions>): APIPromise<Rsp>; + delete<Rsp>(path: string, opts?: PromiseOrValue<RequestOptions>): APIPromise<Rsp>; + private methodRequest; + request<Rsp>(options: PromiseOrValue<FinalRequestOptions>, remainingRetries?: number | null): APIPromise<Rsp>; + private makeRequest; + fetchWithTimeout(url: _RequestInfo, init: _RequestInit | undefined, ms: number, controller: AbortController): Promise<Response>; + private shouldRetry; + private retryRequest; + private calculateDefaultRetryTimeoutMillis; + buildRequest(inputOptions: FinalRequestOptions, { retryCount }?: { + retryCount?: number; + }): Promise<{ + req: FinalizedRequestInit; + url: string; + timeout: number; + }>; + private buildHeaders; + private _makeAbort; + private buildBody; + static DEFAULT_TIMEOUT: number; +} + +declare class BaseInteractions extends APIResource { + static readonly _key: readonly ['interactions']; + /** + * Creates a new interaction. + * + * @example + * ```ts + * const interaction = await client.interactions.create({ + * api_version: 'api_version', + * input: 'string', + * model: 'gemini-2.5-flash', + * }); + * ``` + */ + create(params: CreateModelInteractionParamsNonStreaming, options?: RequestOptions): APIPromise<Interaction>; + create(params: CreateModelInteractionParamsStreaming, options?: RequestOptions): APIPromise<Stream<InteractionSSEEvent>>; + create(params: CreateAgentInteractionParamsNonStreaming, options?: RequestOptions): APIPromise<Interaction>; + create(params: CreateAgentInteractionParamsStreaming, options?: RequestOptions): APIPromise<Stream<InteractionSSEEvent>>; + create(params: BaseCreateModelInteractionParams | BaseCreateAgentInteractionParams, options?: RequestOptions): APIPromise<Stream<InteractionSSEEvent> | Interaction>; + /** + * Deletes the interaction by id. + * + * @example + * ```ts + * const interaction = await client.interactions.delete('id', { + * api_version: 'api_version', + * }); + * ``` + */ + delete(id: string, params?: InteractionDeleteParams | null | undefined, options?: RequestOptions): APIPromise<unknown>; + /** + * Cancels an interaction by id. This only applies to background interactions that are still running. + * + * @example + * ```ts + * const interaction = await client.interactions.cancel('id', { + * api_version: 'api_version', + * }); + * ``` + */ + cancel(id: string, params?: InteractionCancelParams | null | undefined, options?: RequestOptions): APIPromise<Interaction>; + /** + * Retrieves the full details of a single interaction based on its `Interaction.id`. + * + * @example + * ```ts + * const interaction = await client.interactions.get('id', { + * api_version: 'api_version', + * }); + * ``` + */ + get(id: string, params?: InteractionGetParamsNonStreaming, options?: RequestOptions): APIPromise<Interaction>; + get(id: string, params: InteractionGetParamsStreaming, options?: RequestOptions): APIPromise<Stream<InteractionSSEEvent>>; + get(id: string, params?: InteractionGetParamsBase | undefined, options?: RequestOptions): APIPromise<Stream<InteractionSSEEvent> | Interaction>; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +declare class BaseModule { +} + +/** + * Parameters for setting the base URLs for the Gemini API and Vertex AI API. + */ +export declare interface BaseUrlParameters { + geminiUrl?: string; + vertexUrl?: string; +} + +export declare class Batches extends BaseModule { + private readonly apiClient; + constructor(apiClient: ApiClient); + /** + * Lists batch jobs. + * + * @param params - The parameters for the list request. + * @return - A pager of batch jobs. + * + * @example + * ```ts + * const batchJobs = await ai.batches.list({config: {'pageSize': 2}}); + * for await (const batchJob of batchJobs) { + * console.log(batchJob); + * } + * ``` + */ + list: (params?: types.ListBatchJobsParameters) => Promise<Pager<types.BatchJob>>; + /** + * Create batch job. + * + * @param params - The parameters for create batch job request. + * @return The created batch job. + * + * @example + * ```ts + * const response = await ai.batches.create({ + * model: 'gemini-2.0-flash', + * src: {gcsUri: 'gs://bucket/path/to/file.jsonl', format: 'jsonl'}, + * config: { + * dest: {gcsUri: 'gs://bucket/path/output/directory', format: 'jsonl'}, + * } + * }); + * console.log(response); + * ``` + */ + create: (params: types.CreateBatchJobParameters) => Promise<types.BatchJob>; + /** + * **Experimental** Creates an embedding batch job. + * + * @param params - The parameters for create embedding batch job request. + * @return The created batch job. + * + * @example + * ```ts + * const response = await ai.batches.createEmbeddings({ + * model: 'text-embedding-004', + * src: {fileName: 'files/my_embedding_input'}, + * }); + * console.log(response); + * ``` + */ + createEmbeddings: (params: types.CreateEmbeddingsBatchJobParameters) => Promise<types.BatchJob>; + private createInlinedGenerateContentRequest; + private getGcsUri; + private getBigqueryUri; + private formatDestination; + /** + * Internal method to create batch job. + * + * @param params - The parameters for create batch job request. + * @return The created batch job. + * + */ + private createInternal; + /** + * Internal method to create batch job. + * + * @param params - The parameters for create batch job request. + * @return The created batch job. + * + */ + private createEmbeddingsInternal; + /** + * Gets batch job configurations. + * + * @param params - The parameters for the get request. + * @return The batch job. + * + * @example + * ```ts + * await ai.batches.get({name: '...'}); // The server-generated resource name. + * ``` + */ + get(params: types.GetBatchJobParameters): Promise<types.BatchJob>; + /** + * Cancels a batch job. + * + * @param params - The parameters for the cancel request. + * @return The empty response returned by the API. + * + * @example + * ```ts + * await ai.batches.cancel({name: '...'}); // The server-generated resource name. + * ``` + */ + cancel(params: types.CancelBatchJobParameters): Promise<void>; + private listInternal; + /** + * Deletes a batch job. + * + * @param params - The parameters for the delete request. + * @return The empty response returned by the API. + * + * @example + * ```ts + * await ai.batches.delete({name: '...'}); // The server-generated resource name. + * ``` + */ + delete(params: types.DeleteBatchJobParameters): Promise<types.DeleteResourceJob>; +} + +/** Config for batches.create return value. */ +export declare interface BatchJob { + /** The resource name of the BatchJob. Output only.". + */ + name?: string; + /** The display name of the BatchJob. + */ + displayName?: string; + /** The state of the BatchJob. + */ + state?: JobState; + /** Output only. Only populated when the job's state is JOB_STATE_FAILED or JOB_STATE_CANCELLED. */ + error?: JobError; + /** The time when the BatchJob was created. + */ + createTime?: string; + /** Output only. Time when the Job for the first time entered the `JOB_STATE_RUNNING` state. */ + startTime?: string; + /** The time when the BatchJob was completed. This field is for Vertex AI only. + */ + endTime?: string; + /** The time when the BatchJob was last updated. + */ + updateTime?: string; + /** The name of the model that produces the predictions via the BatchJob. + */ + model?: string; + /** Configuration for the input data. This field is for Vertex AI only. + */ + src?: BatchJobSource; + /** Configuration for the output data. + */ + dest?: BatchJobDestination; + /** Statistics on completed and failed prediction instances. This field is for Vertex AI only. + */ + completionStats?: CompletionStats; +} + +/** Config for `des` parameter. */ +export declare interface BatchJobDestination { + /** Storage format of the output files. Must be one of: + 'jsonl', 'bigquery'. + */ + format?: string; + /** The Google Cloud Storage URI to the output file. + */ + gcsUri?: string; + /** The BigQuery URI to the output table. + */ + bigqueryUri?: string; + /** The Gemini Developer API's file resource name of the output data + (e.g. "files/12345"). The file will be a JSONL file with a single response + per line. The responses will be GenerateContentResponse messages formatted + as JSON. The responses will be written in the same order as the input + requests. + */ + fileName?: string; + /** The responses to the requests in the batch. Returned when the batch was + built using inlined requests. The responses will be in the same order as + the input requests. + */ + inlinedResponses?: InlinedResponse[]; + /** The responses to the requests in the batch. Returned when the batch was + built using inlined requests. The responses will be in the same order as + the input requests. + */ + inlinedEmbedContentResponses?: InlinedEmbedContentResponse[]; +} + +export declare type BatchJobDestinationUnion = BatchJobDestination | string; + +/** Config for `src` parameter. */ +export declare interface BatchJobSource { + /** Storage format of the input files. Must be one of: + 'jsonl', 'bigquery'. + */ + format?: string; + /** The Google Cloud Storage URIs to input files. + */ + gcsUri?: string[]; + /** The BigQuery URI to input table. + */ + bigqueryUri?: string; + /** The Gemini Developer API's file resource name of the input data + (e.g. "files/12345"). + */ + fileName?: string; + /** The Gemini Developer API's inlined input data to run batch job. + */ + inlinedRequests?: InlinedRequest[]; +} + +export declare type BatchJobSourceUnion = BatchJobSource | InlinedRequest[] | string; + +/** Specifies the function Behavior. Currently only supported by the BidiGenerateContent method. This enum is not supported in Vertex AI. */ +export declare enum Behavior { + /** + * This value is unused. + */ + UNSPECIFIED = "UNSPECIFIED", + /** + * If set, the system will wait to receive the function response before continuing the conversation. + */ + BLOCKING = "BLOCKING", + /** + * If set, the system will not wait to receive the function response. Instead, it will attempt to handle function responses as they become available while maintaining the conversation between the user and the model. + */ + NON_BLOCKING = "NON_BLOCKING" +} + +/** Content blob. */ +declare interface Blob_2 { + /** Required. Raw bytes. + * @remarks Encoded as base64 string. */ + data?: string; + /** Optional. Display name of the blob. Used to provide a label or filename to distinguish blobs. This field is only returned in PromptMessage for prompt management. It is currently used in the Gemini GenerateContent calls only when server side tools (code_execution, google_search, and url_context) are enabled. This field is not supported in Gemini API. */ + displayName?: string; + /** Required. The IANA standard MIME type of the source data. */ + mimeType?: string; +} +export { Blob_2 as Blob } + +export declare type BlobImageUnion = Blob_2; + +/** Output only. The reason why the prompt was blocked. */ +export declare enum BlockedReason { + /** + * The blocked reason is unspecified. + */ + BLOCKED_REASON_UNSPECIFIED = "BLOCKED_REASON_UNSPECIFIED", + /** + * The prompt was blocked for safety reasons. + */ + SAFETY = "SAFETY", + /** + * The prompt was blocked for other reasons. For example, it may be due to the prompt's language, or because it contains other harmful content. + */ + OTHER = "OTHER", + /** + * The prompt was blocked because it contains a term from the terminology blocklist. + */ + BLOCKLIST = "BLOCKLIST", + /** + * The prompt was blocked because it contains prohibited content. + */ + PROHIBITED_CONTENT = "PROHIBITED_CONTENT", + /** + * The prompt was blocked because it contains content that is unsafe for image generation. + */ + IMAGE_SAFETY = "IMAGE_SAFETY", + /** + * The prompt was blocked by Model Armor. This enum value is not supported in Gemini API. + */ + MODEL_ARMOR = "MODEL_ARMOR", + /** + * The prompt was blocked as a jailbreak attempt. This enum value is not supported in Gemini API. + */ + JAILBREAK = "JAILBREAK" +} + +declare const brand_privateNullableHeaders: unique symbol; + +/** @ts-ignore For users with \@types/bun */ +declare type BunRequestInit = globalThis.FetchRequestInit; + +/** A resource used in LLM queries for users to explicitly specify what to cache. */ +export declare interface CachedContent { + /** The server-generated resource name of the cached content. */ + name?: string; + /** The user-generated meaningful display name of the cached content. */ + displayName?: string; + /** The name of the publisher model to use for cached content. */ + model?: string; + /** Creation time of the cache entry. */ + createTime?: string; + /** When the cache entry was last updated in UTC time. */ + updateTime?: string; + /** Expiration time of the cached content. */ + expireTime?: string; + /** Metadata on the usage of the cached content. */ + usageMetadata?: CachedContentUsageMetadata; +} + +/** Metadata on the usage of the cached content. */ +export declare interface CachedContentUsageMetadata { + /** Duration of audio in seconds. This field is not supported in Gemini API. */ + audioDurationSeconds?: number; + /** Number of images. This field is not supported in Gemini API. */ + imageCount?: number; + /** Number of text characters. This field is not supported in Gemini API. */ + textCount?: number; + /** Total number of tokens that the cached content consumes. */ + totalTokenCount?: number; + /** Duration of video in seconds. This field is not supported in Gemini API. */ + videoDurationSeconds?: number; +} + +export declare class Caches extends BaseModule { + private readonly apiClient; + constructor(apiClient: ApiClient); + /** + * Lists cached contents. + * + * @param params - The parameters for the list request. + * @return - A pager of cached contents. + * + * @example + * ```ts + * const cachedContents = await ai.caches.list({config: {'pageSize': 2}}); + * for await (const cachedContent of cachedContents) { + * console.log(cachedContent); + * } + * ``` + */ + list: (params?: types.ListCachedContentsParameters) => Promise<Pager<types.CachedContent>>; + /** + * Creates a cached contents resource. + * + * @remarks + * Context caching is only supported for specific models. See [Gemini + * Developer API reference](https://ai.google.dev/gemini-api/docs/caching?lang=node/context-cac) + * and [Vertex AI reference](https://cloud.google.com/vertex-ai/generative-ai/docs/context-cache/context-cache-overview#supported_models) + * for more information. + * + * @param params - The parameters for the create request. + * @return The created cached content. + * + * @example + * ```ts + * const contents = ...; // Initialize the content to cache. + * const response = await ai.caches.create({ + * model: 'gemini-2.0-flash-001', + * config: { + * 'contents': contents, + * 'displayName': 'test cache', + * 'systemInstruction': 'What is the sum of the two pdfs?', + * 'ttl': '86400s', + * } + * }); + * ``` + */ + create(params: types.CreateCachedContentParameters): Promise<types.CachedContent>; + /** + * Gets cached content configurations. + * + * @param params - The parameters for the get request. + * @return The cached content. + * + * @example + * ```ts + * await ai.caches.get({name: '...'}); // The server-generated resource name. + * ``` + */ + get(params: types.GetCachedContentParameters): Promise<types.CachedContent>; + /** + * Deletes cached content. + * + * @param params - The parameters for the delete request. + * @return The empty response returned by the API. + * + * @example + * ```ts + * await ai.caches.delete({name: '...'}); // The server-generated resource name. + * ``` + */ + delete(params: types.DeleteCachedContentParameters): Promise<types.DeleteCachedContentResponse>; + /** + * Updates cached content configurations. + * + * @param params - The parameters for the update request. + * @return The updated cached content. + * + * @example + * ```ts + * const response = await ai.caches.update({ + * name: '...', // The server-generated resource name. + * config: {'ttl': '7600s'} + * }); + * ``` + */ + update(params: types.UpdateCachedContentParameters): Promise<types.CachedContent>; + private listInternal; +} + +/** + * CallableTool is an invokable tool that can be executed with external + * application (e.g., via Model Context Protocol) or local functions with + * function calling. + */ +export declare interface CallableTool { + /** + * Returns tool that can be called by Gemini. + */ + tool(): Promise<Tool>; + /** + * Executes the callable tool with the given function call arguments and + * returns the response parts from the tool execution. + */ + callTool(functionCalls: FunctionCall[]): Promise<Part[]>; +} + +/** + * CallableToolConfig is the configuration for a callable tool. + */ +export declare interface CallableToolConfig { + /** + * Specifies the model's behavior after invoking this tool. + */ + behavior?: Behavior; + /** + * Timeout for remote calls in milliseconds. Note this timeout applies only to + * tool remote calls, and not making HTTP requests to the API. */ + timeout?: number; +} + +/** Optional parameters. */ +export declare interface CancelBatchJobConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Config for batches.cancel parameters. */ +export declare interface CancelBatchJobParameters { + /** A fully-qualified BatchJob resource name or ID. + Example: "projects/.../locations/.../batchPredictionJobs/456" + or "456" when project and location are initialized in the client. + */ + name: string; + /** Optional parameters for the request. */ + config?: CancelBatchJobConfig; +} + +/** Optional parameters for tunings.cancel method. */ +export declare interface CancelTuningJobConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Parameters for the cancel method. */ +export declare interface CancelTuningJobParameters { + /** The resource name of the tuning job. */ + name: string; + /** Optional parameters for the request. */ + config?: CancelTuningJobConfig; +} + +/** Empty response for tunings.cancel method. */ +export declare class CancelTuningJobResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; +} + +/** A response candidate generated from the model. */ +export declare interface Candidate { + /** Contains the multi-part content of the response. + */ + content?: Content; + /** Source attribution of the generated content. + */ + citationMetadata?: CitationMetadata; + /** Describes the reason the model stopped generating tokens. + */ + finishMessage?: string; + /** Number of tokens for this candidate. + */ + tokenCount?: number; + /** The reason why the model stopped generating tokens. + If empty, the model has not stopped generating the tokens. + */ + finishReason?: FinishReason; + /** Output only. Average log probability score of the candidate. */ + avgLogprobs?: number; + /** Output only. Metadata specifies sources used to ground generated content. */ + groundingMetadata?: GroundingMetadata; + /** Output only. Index of the candidate. */ + index?: number; + /** Output only. Log-likelihood scores for the response tokens and top tokens */ + logprobsResult?: LogprobsResult; + /** Output only. List of ratings for the safety of a response candidate. There is at most one rating per category. */ + safetyRatings?: SafetyRating[]; + /** Output only. Metadata related to url context retrieval tool. */ + urlContextMetadata?: UrlContextMetadata; +} + +/** + * Chat session that enables sending messages to the model with previous + * conversation context. + * + * @remarks + * The session maintains all the turns between user and model. + */ +export declare class Chat { + private readonly apiClient; + private readonly modelsModule; + private readonly model; + private readonly config; + private history; + private sendPromise; + constructor(apiClient: ApiClient, modelsModule: Models, model: string, config?: types.GenerateContentConfig, history?: types.Content[]); + /** + * Sends a message to the model and returns the response. + * + * @remarks + * This method will wait for the previous message to be processed before + * sending the next message. + * + * @see {@link Chat#sendMessageStream} for streaming method. + * @param params - parameters for sending messages within a chat session. + * @returns The model's response. + * + * @example + * ```ts + * const chat = ai.chats.create({model: 'gemini-2.0-flash'}); + * const response = await chat.sendMessage({ + * message: 'Why is the sky blue?' + * }); + * console.log(response.text); + * ``` + */ + sendMessage(params: types.SendMessageParameters): Promise<types.GenerateContentResponse>; + /** + * Sends a message to the model and returns the response in chunks. + * + * @remarks + * This method will wait for the previous message to be processed before + * sending the next message. + * + * @see {@link Chat#sendMessage} for non-streaming method. + * @param params - parameters for sending the message. + * @return The model's response. + * + * @example + * ```ts + * const chat = ai.chats.create({model: 'gemini-2.0-flash'}); + * const response = await chat.sendMessageStream({ + * message: 'Why is the sky blue?' + * }); + * for await (const chunk of response) { + * console.log(chunk.text); + * } + * ``` + */ + sendMessageStream(params: types.SendMessageParameters): Promise<AsyncGenerator<types.GenerateContentResponse>>; + /** + * Returns the chat history. + * + * @remarks + * The history is a list of contents alternating between user and model. + * + * There are two types of history: + * - The `curated history` contains only the valid turns between user and + * model, which will be included in the subsequent requests sent to the model. + * - The `comprehensive history` contains all turns, including invalid or + * empty model outputs, providing a complete record of the history. + * + * The history is updated after receiving the response from the model, + * for streaming response, it means receiving the last chunk of the response. + * + * The `comprehensive history` is returned by default. To get the `curated + * history`, set the `curated` parameter to `true`. + * + * @param curated - whether to return the curated history or the comprehensive + * history. + * @return History contents alternating between user and model for the entire + * chat session. + */ + getHistory(curated?: boolean): types.Content[]; + private processStreamResponse; + private recordHistory; +} + +/** + * A utility class to create a chat session. + */ +export declare class Chats { + private readonly modelsModule; + private readonly apiClient; + constructor(modelsModule: Models, apiClient: ApiClient); + /** + * Creates a new chat session. + * + * @remarks + * The config in the params will be used for all requests within the chat + * session unless overridden by a per-request `config` in + * @see {@link types.SendMessageParameters#config}. + * + * @param params - Parameters for creating a chat session. + * @returns A new chat session. + * + * @example + * ```ts + * const chat = ai.chats.create({ + * model: 'gemini-2.0-flash' + * config: { + * temperature: 0.5, + * maxOutputTokens: 1024, + * } + * }); + * ``` + */ + create(params: types.CreateChatParameters): Chat; +} + +/** Describes the machine learning model version checkpoint. */ +export declare interface Checkpoint { + /** The ID of the checkpoint. + */ + checkpointId?: string; + /** The epoch of the checkpoint. + */ + epoch?: string; + /** The step of the checkpoint. + */ + step?: string; +} + +/** Config for telling the service how to chunk the file. */ +export declare interface ChunkingConfig { + /** White space chunking configuration. */ + whiteSpaceConfig?: WhiteSpaceConfig; +} + +/** Source attributions for content. This data type is not supported in Gemini API. */ +export declare interface Citation { + /** Output only. End index into the content. */ + endIndex?: number; + /** Output only. License of the attribution. */ + license?: string; + /** Output only. Publication date of the attribution. */ + publicationDate?: GoogleTypeDate; + /** Output only. Start index into the content. */ + startIndex?: number; + /** Output only. Title of the attribution. */ + title?: string; + /** Output only. Url reference of the attribution. */ + uri?: string; +} + +/** Citation information when the model quotes another source. */ +export declare interface CitationMetadata { + /** Contains citation information when the model directly quotes, at + length, from another source. Can include traditional websites and code + repositories. + */ + citations?: Citation[]; +} + +declare interface ClientOptions { + /** + * Defaults to process.env['GEMINI_API_KEY']. + */ + apiKey?: string | null | undefined; + apiVersion?: string | undefined; + /** + * Override the default base URL for the API, e.g., "https://api.example.com/v2/" + * + * Defaults to process.env['GEMINI_NEXT_GEN_API_BASE_URL']. + */ + baseURL?: string | null | undefined; + /** + * The maximum amount of time (in milliseconds) that the client should wait for a response + * from the server before timing out a single request. + * + * Note that request timeouts are retried by default, so in a worst-case scenario you may wait + * much longer than this timeout before the promise succeeds or fails. + * + * @unit milliseconds + */ + timeout?: number | undefined; + /** + * Additional `RequestInit` options to be passed to `fetch` calls. + * Properties will be overridden by per-request `fetchOptions`. + */ + fetchOptions?: MergedRequestInit | undefined; + /** + * Specify a custom `fetch` function implementation. + * + * If not provided, we expect that `fetch` is defined globally. + */ + fetch?: Fetch | undefined; + /** + * The maximum number of times that the client will retry a request in case of a + * temporary failure, like a network error or a 5XX error from the server. + * + * @default 2 + */ + maxRetries?: number | undefined; + /** + * Default headers to include with every request to the API. + * + * These can be removed in individual requests by explicitly setting the + * header to `null` in request options. + */ + defaultHeaders?: HeadersLike | undefined; + /** + * Default query parameters to include with every request to the API. + * + * These can be removed in individual requests by explicitly setting the + * param to `undefined` in request options. + */ + defaultQuery?: Record<string, string | undefined> | undefined; + /** + * Set the log level. + * + * Defaults to process.env['GEMINI_NEXT_GEN_API_LOG'] or 'warn' if it isn't set. + */ + logLevel?: LogLevel | undefined; + /** + * Set the logger. + * + * Defaults to globalThis.console. + */ + logger?: Logger | undefined; + /** + * The adapter to the parent API client instance (for accessing auth, project, location) + */ + clientAdapter: GeminiNextGenAPIClientAdapter; +} + +/** + * The arguments to pass to the code execution. + */ +declare interface CodeExecutionCallArguments { + /** + * The code to be executed. + */ + code?: string; + /** + * Programming language of the `code`. + */ + language?: 'python'; +} + +/** + * Code execution content. + */ +declare interface CodeExecutionCallContent { + type: 'code_execution_call'; + /** + * A unique ID for this specific tool call. + */ + id?: string; + /** + * The arguments to pass to the code execution. + */ + arguments?: CodeExecutionCallArguments; +} + +/** Result of executing the [ExecutableCode]. Only generated when using the [CodeExecution] tool, and always follows a `part` containing the [ExecutableCode]. */ +export declare interface CodeExecutionResult { + /** Required. Outcome of the code execution. */ + outcome?: Outcome; + /** Optional. Contains stdout when code execution is successful, stderr or other description otherwise. */ + output?: string; +} + +/** + * Code execution result content. + */ +declare interface CodeExecutionResultContent { + type: 'code_execution_result'; + /** + * ID to match the ID from the code execution call block. + */ + call_id?: string; + /** + * Whether the code execution resulted in an error. + */ + is_error?: boolean; + /** + * The output of the code execution. + */ + result?: string; + /** + * A signature hash for backend validation. + */ + signature?: string; +} + +/** Success and error statistics of processing multiple entities (for example, DataItems or structured data rows) in batch. This data type is not supported in Gemini API. */ +export declare interface CompletionStats { + /** Output only. The number of entities for which any error was encountered. */ + failedCount?: string; + /** Output only. In cases when enough errors are encountered a job, pipeline, or operation may be failed as a whole. Below is the number of entities for which the processing had not been finished (either in successful or failed state). Set to -1 if the number is unknown (for example, the operation failed before the total entity number could be collected). */ + incompleteCount?: string; + /** Output only. The number of entities that had been processed successfully. */ + successfulCount?: string; + /** Output only. The number of the successful forecast points that are generated by the forecasting model. This is ONLY used by the forecasting batch prediction. */ + successfulForecastPointCount?: string; +} + +/** Tool to support computer use. */ +export declare interface ComputerUse { + /** Required. The environment being operated. */ + environment?: Environment; + /** By default, predefined functions are included in the final model call. + Some of them can be explicitly excluded from being automatically included. + This can serve two purposes: + 1. Using a more restricted / different action space. + 2. Improving the definitions / instructions of predefined functions. */ + excludedPredefinedFunctions?: string[]; +} + +/** Optional parameters for computing tokens. */ +export declare interface ComputeTokensConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Parameters for computing tokens. */ +export declare interface ComputeTokensParameters { + /** ID of the model to use. For a list of models, see `Google models + <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */ + model: string; + /** Input content. */ + contents: ContentListUnion; + /** Optional parameters for the request. + */ + config?: ComputeTokensConfig; +} + +/** Response for computing tokens. */ +export declare class ComputeTokensResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** Lists of tokens info from the input. A ComputeTokensRequest could have multiple instances with a prompt in each instance. We also need to return lists of tokens info for the request with multiple instances. */ + tokensInfo?: TokensInfo[]; +} + +/** Local tokenizer compute tokens result. */ +export declare interface ComputeTokensResult { + /** Lists of tokens info from the input. */ + tokensInfo?: TokensInfo[]; +} + +declare type _ConditionalNodeReadableStream<R = any> = typeof globalThis extends { + ReadableStream: any; +} ? never : _NodeReadableStream<R>; + +declare class ConflictError extends APIError<409, Headers> { +} + +/** Contains the multi-part content of a message. */ +export declare interface Content { + /** List of parts that constitute a single message. Each part may have + a different IANA MIME type. */ + parts?: Part[]; + /** Optional. The producer of the content. Must be either 'user' or 'model'. Useful to set for multi-turn conversations, otherwise can be left blank or unset. */ + role?: string; +} + +/** + * The content of the response. + */ +declare type Content_2 = TextContent | ImageContent | AudioContent | DocumentContent | VideoContent | ThoughtContent | FunctionCallContent | FunctionResultContent | CodeExecutionCallContent | CodeExecutionResultContent | URLContextCallContent | URLContextResultContent | GoogleSearchCallContent | GoogleSearchResultContent | MCPServerToolCallContent | MCPServerToolResultContent | FileSearchCallContent | FileSearchResultContent; + +declare interface ContentDelta { + delta?: ContentDelta.TextDelta | ContentDelta.ImageDelta | ContentDelta.AudioDelta | ContentDelta.DocumentDelta | ContentDelta.VideoDelta | ContentDelta.ThoughtSummaryDelta | ContentDelta.ThoughtSignatureDelta | ContentDelta.FunctionCallDelta | ContentDelta.FunctionResultDelta | ContentDelta.CodeExecutionCallDelta | ContentDelta.CodeExecutionResultDelta | ContentDelta.URLContextCallDelta | ContentDelta.URLContextResultDelta | ContentDelta.GoogleSearchCallDelta | ContentDelta.GoogleSearchResultDelta | ContentDelta.MCPServerToolCallDelta | ContentDelta.MCPServerToolResultDelta | ContentDelta.FileSearchCallDelta | ContentDelta.FileSearchResultDelta; + /** + * The event_id token to be used to resume the interaction stream, from this event. + */ + event_id?: string; + event_type?: 'content.delta'; + index?: number; +} + +declare namespace ContentDelta { + interface TextDelta { + type: 'text'; + /** + * Citation information for model-generated content. + */ + annotations?: Array<InteractionsAPI.Annotation>; + text?: string; + } + interface ImageDelta { + type: 'image'; + data?: string; + /** + * The mime type of the image. + */ + mime_type?: InteractionsAPI.ImageMimeType; + /** + * The resolution of the media. + */ + resolution?: 'low' | 'medium' | 'high' | 'ultra_high'; + uri?: string; + } + interface AudioDelta { + type: 'audio'; + data?: string; + /** + * The mime type of the audio. + */ + mime_type?: InteractionsAPI.AudioMimeType; + uri?: string; + } + interface DocumentDelta { + type: 'document'; + data?: string; + /** + * The mime type of the document. + */ + mime_type?: InteractionsAPI.DocumentMimeType; + uri?: string; + } + interface VideoDelta { + type: 'video'; + data?: string; + /** + * The mime type of the video. + */ + mime_type?: InteractionsAPI.VideoMimeType; + /** + * The resolution of the media. + */ + resolution?: 'low' | 'medium' | 'high' | 'ultra_high'; + uri?: string; + } + interface ThoughtSummaryDelta { + type: 'thought_summary'; + /** + * A text content block. + */ + content?: InteractionsAPI.TextContent | InteractionsAPI.ImageContent; + } + interface ThoughtSignatureDelta { + type: 'thought_signature'; + /** + * Signature to match the backend source to be part of the generation. + */ + signature?: string; + } + interface FunctionCallDelta { + type: 'function_call'; + /** + * A unique ID for this specific tool call. + */ + id?: string; + arguments?: { + [key: string]: unknown; + }; + name?: string; + } + interface FunctionResultDelta { + type: 'function_result'; + /** + * ID to match the ID from the function call block. + */ + call_id?: string; + is_error?: boolean; + name?: string; + /** + * Tool call result delta. + */ + result?: FunctionResultDelta.Items | unknown | string; + } + namespace FunctionResultDelta { + interface Items { + items?: Array<InteractionsAPI.TextContent | InteractionsAPI.ImageContent>; + } + } + interface CodeExecutionCallDelta { + type: 'code_execution_call'; + /** + * A unique ID for this specific tool call. + */ + id?: string; + /** + * The arguments to pass to the code execution. + */ + arguments?: InteractionsAPI.CodeExecutionCallArguments; + } + interface CodeExecutionResultDelta { + type: 'code_execution_result'; + /** + * ID to match the ID from the function call block. + */ + call_id?: string; + is_error?: boolean; + result?: string; + signature?: string; + } + interface URLContextCallDelta { + type: 'url_context_call'; + /** + * A unique ID for this specific tool call. + */ + id?: string; + /** + * The arguments to pass to the URL context. + */ + arguments?: InteractionsAPI.URLContextCallArguments; + } + interface URLContextResultDelta { + type: 'url_context_result'; + /** + * ID to match the ID from the function call block. + */ + call_id?: string; + is_error?: boolean; + result?: Array<InteractionsAPI.URLContextResult>; + signature?: string; + } + interface GoogleSearchCallDelta { + type: 'google_search_call'; + /** + * A unique ID for this specific tool call. + */ + id?: string; + /** + * The arguments to pass to Google Search. + */ + arguments?: InteractionsAPI.GoogleSearchCallArguments; + } + interface GoogleSearchResultDelta { + type: 'google_search_result'; + /** + * ID to match the ID from the function call block. + */ + call_id?: string; + is_error?: boolean; + result?: Array<InteractionsAPI.GoogleSearchResult>; + signature?: string; + } + interface MCPServerToolCallDelta { + type: 'mcp_server_tool_call'; + /** + * A unique ID for this specific tool call. + */ + id?: string; + arguments?: { + [key: string]: unknown; + }; + name?: string; + server_name?: string; + } + interface MCPServerToolResultDelta { + type: 'mcp_server_tool_result'; + /** + * ID to match the ID from the function call block. + */ + call_id?: string; + name?: string; + /** + * Tool call result delta. + */ + result?: MCPServerToolResultDelta.Items | unknown | string; + server_name?: string; + } + namespace MCPServerToolResultDelta { + interface Items { + items?: Array<InteractionsAPI.TextContent | InteractionsAPI.ImageContent>; + } + } + interface FileSearchCallDelta { + type: 'file_search_call'; + /** + * A unique ID for this specific tool call. + */ + id?: string; + } + interface FileSearchResultDelta { + type: 'file_search_result'; + result?: Array<FileSearchResultDelta.Result>; + } + namespace FileSearchResultDelta { + /** + * The result of the File Search. + */ + interface Result { + /** + * The name of the file search store. + */ + file_search_store?: string; + /** + * The text of the search result. + */ + text?: string; + /** + * The title of the search result. + */ + title?: string; + } + } +} + +/** The embedding generated from an input content. */ +export declare interface ContentEmbedding { + /** A list of floats representing an embedding. + */ + values?: number[]; + /** Vertex API only. Statistics of the input text associated with this + embedding. + */ + statistics?: ContentEmbeddingStatistics; +} + +/** Statistics of the input text associated with the result of content embedding. */ +export declare interface ContentEmbeddingStatistics { + /** Vertex API only. If the input text was truncated due to having + a length longer than the allowed maximum input. + */ + truncated?: boolean; + /** Vertex API only. Number of tokens of the input text. + */ + tokenCount?: number; +} + +export declare type ContentListUnion = Content | Content[] | PartUnion | PartUnion[]; + +/** A content reference image. + + A content reference image represents a subject to reference (ex. person, + product, animal) provided by the user. It can optionally be provided in + addition to a style reference image (ex. background, style reference). */ +export declare class ContentReferenceImage { + /** The reference image for the editing operation. */ + referenceImage?: Image_2; + /** The id of the reference image. */ + referenceId?: number; + /** The type of the reference image. Only set by the SDK. */ + referenceType?: string; + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI(): ReferenceImageAPIInternal; +} + +declare interface ContentStart { + /** + * The content of the response. + */ + content?: Content_2; + /** + * The event_id token to be used to resume the interaction stream, from this event. + */ + event_id?: string; + event_type?: 'content.start'; + index?: number; +} + +declare interface ContentStop { + /** + * The event_id token to be used to resume the interaction stream, from this event. + */ + event_id?: string; + event_type?: 'content.stop'; + index?: number; +} + +export declare type ContentUnion = Content | PartUnion[] | PartUnion; + +/** Enables context window compression -- mechanism managing model context window so it does not exceed given length. */ +export declare interface ContextWindowCompressionConfig { + /** Number of tokens (before running turn) that triggers context window compression mechanism. */ + triggerTokens?: string; + /** Sliding window compression mechanism. */ + slidingWindow?: SlidingWindow; +} + +/** Configuration for a Control reference image. */ +export declare interface ControlReferenceConfig { + /** The type of control reference image to use. */ + controlType?: ControlReferenceType; + /** Defaults to False. When set to True, the control image will be + computed by the model based on the control type. When set to False, + the control image must be provided by the user. */ + enableControlImageComputation?: boolean; +} + +/** A control reference image. + + The image of the control reference image is either a control image provided + by the user, or a regular image which the backend will use to generate a + control image of. In the case of the latter, the + enable_control_image_computation field in the config should be set to True. + + A control image is an image that represents a sketch image of areas for the + model to fill in based on the prompt. */ +export declare class ControlReferenceImage { + /** The reference image for the editing operation. */ + referenceImage?: Image_2; + /** The id of the reference image. */ + referenceId?: number; + /** The type of the reference image. Only set by the SDK. */ + referenceType?: string; + /** Configuration for the control reference image. */ + config?: ControlReferenceConfig; + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI(): ReferenceImageAPIInternal; +} + +/** Enum representing the control type of a control reference image. */ +export declare enum ControlReferenceType { + CONTROL_TYPE_DEFAULT = "CONTROL_TYPE_DEFAULT", + CONTROL_TYPE_CANNY = "CONTROL_TYPE_CANNY", + CONTROL_TYPE_SCRIBBLE = "CONTROL_TYPE_SCRIBBLE", + CONTROL_TYPE_FACE_MESH = "CONTROL_TYPE_FACE_MESH" +} + +/** Config for the count_tokens method. */ +export declare interface CountTokensConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** Instructions for the model to steer it toward better performance. + */ + systemInstruction?: ContentUnion; + /** Code that enables the system to interact with external systems to + perform an action outside of the knowledge and scope of the model. + */ + tools?: Tool[]; + /** Configuration that the model uses to generate the response. Not + supported by the Gemini Developer API. + */ + generationConfig?: GenerationConfig; +} + +/** Parameters for counting tokens. */ +export declare interface CountTokensParameters { + /** ID of the model to use. For a list of models, see `Google models + <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */ + model: string; + /** Input content. */ + contents: ContentListUnion; + /** Configuration for counting tokens. */ + config?: CountTokensConfig; +} + +/** Response for counting tokens. */ +export declare class CountTokensResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** Total number of tokens. */ + totalTokens?: number; + /** Number of tokens in the cached part of the prompt (the cached content). */ + cachedContentTokenCount?: number; +} + +/** Local tokenizer count tokens result. */ +export declare interface CountTokensResult { + /** The total number of tokens. */ + totalTokens?: number; +} + +declare interface CreateAgentInteractionParamsNonStreaming extends BaseCreateAgentInteractionParams { + /** + * Body param: Input only. Whether the interaction will be streamed. + */ + stream?: false; +} + +declare interface CreateAgentInteractionParamsStreaming extends BaseCreateAgentInteractionParams { + /** + * Body param: Input only. Whether the interaction will be streamed. + */ + stream: true; +} + +/** Optional parameters. */ +export declare interface CreateAuthTokenConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** An optional time after which, when using the resulting token, + messages in Live API sessions will be rejected. (Gemini may + preemptively close the session after this time.) + + If not set then this defaults to 30 minutes in the future. If set, this + value must be less than 20 hours in the future. */ + expireTime?: string; + /** The time after which new Live API sessions using the token + resulting from this request will be rejected. + + If not set this defaults to 60 seconds in the future. If set, this value + must be less than 20 hours in the future. */ + newSessionExpireTime?: string; + /** The number of times the token can be used. If this value is zero + then no limit is applied. Default is 1. Resuming a Live API session does + not count as a use. */ + uses?: number; + /** Configuration specific to Live API connections created using this token. */ + liveConnectConstraints?: LiveConnectConstraints; + /** Additional fields to lock in the effective LiveConnectParameters. */ + lockAdditionalFields?: string[]; +} + +/** Config for auth_tokens.create parameters. */ +export declare interface CreateAuthTokenParameters { + /** Optional parameters for the request. */ + config?: CreateAuthTokenConfig; +} + +/** Config for optional parameters. */ +export declare interface CreateBatchJobConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** The user-defined name of this BatchJob. + */ + displayName?: string; + /** GCS or BigQuery URI prefix for the output predictions. Example: + "gs://path/to/output/data" or "bq://projectId.bqDatasetId.bqTableId". + */ + dest?: BatchJobDestinationUnion; +} + +/** Config for batches.create parameters. */ +export declare interface CreateBatchJobParameters { + /** The name of the model to produces the predictions via the BatchJob. + */ + model?: string; + /** GCS URI(-s) or BigQuery URI to your input data to run batch job. + Example: "gs://path/to/input/data" or "bq://projectId.bqDatasetId.bqTableId". + */ + src: BatchJobSourceUnion; + /** Optional parameters for creating a BatchJob. + */ + config?: CreateBatchJobConfig; +} + +/** Optional configuration for cached content creation. */ +export declare interface CreateCachedContentConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** The TTL for this resource. The expiration time is computed: now + TTL. It is a duration string, with up to nine fractional digits, terminated by 's'. Example: "3.5s". */ + ttl?: string; + /** Timestamp of when this resource is considered expired. Uses RFC 3339 format, Example: 2014-10-02T15:01:23Z. */ + expireTime?: string; + /** The user-generated meaningful display name of the cached content. + */ + displayName?: string; + /** The content to cache. + */ + contents?: ContentListUnion; + /** Developer set system instruction. + */ + systemInstruction?: ContentUnion; + /** A list of `Tools` the model may use to generate the next response. + */ + tools?: Tool[]; + /** Configuration for the tools to use. This config is shared for all tools. + */ + toolConfig?: ToolConfig; + /** The Cloud KMS resource identifier of the customer managed + encryption key used to protect a resource. + The key needs to be in the same region as where the compute resource is + created. See + https://cloud.google.com/vertex-ai/docs/general/cmek for more + details. If this is set, then all created CachedContent objects + will be encrypted with the provided encryption key. + Allowed formats: projects/{project}/locations/{location}/keyRings/{key_ring}/cryptoKeys/{crypto_key} + */ + kmsKeyName?: string; +} + +/** Parameters for caches.create method. */ +export declare interface CreateCachedContentParameters { + /** ID of the model to use. Example: gemini-2.0-flash */ + model: string; + /** Configuration that contains optional parameters. + */ + config?: CreateCachedContentConfig; +} + +/** Parameters for initializing a new chat session. + + These parameters are used when creating a chat session with the + `chats.create()` method. */ +export declare interface CreateChatParameters { + /** The name of the model to use for the chat session. + + For example: 'gemini-2.0-flash', 'gemini-2.0-flash-lite', etc. See Gemini API + docs to find the available models. + */ + model: string; + /** Config for the entire chat session. + + This config applies to all requests within the session + unless overridden by a per-request `config` in `SendMessageParameters`. + */ + config?: GenerateContentConfig; + /** The initial conversation history for the chat session. + + This allows you to start the chat with a pre-existing history. The history + must be a list of `Content` alternating between 'user' and 'model' roles. + It should start with a 'user' message. + */ + history?: Content[]; +} + +/** Config for optional parameters. */ +export declare interface CreateEmbeddingsBatchJobConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** The user-defined name of this BatchJob. + */ + displayName?: string; +} + +/** Config for batches.create parameters. */ +export declare interface CreateEmbeddingsBatchJobParameters { + /** The name of the model to produces the predictions via the BatchJob. + */ + model?: string; + /** input data to run batch job". + */ + src: EmbeddingsBatchJobSource; + /** Optional parameters for creating a BatchJob. + */ + config?: CreateEmbeddingsBatchJobConfig; +} + +/** Used to override the default configuration. */ +export declare interface CreateFileConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Generates the parameters for the private _create method. */ +export declare interface CreateFileParameters { + /** The file to be uploaded. + mime_type: (Required) The MIME type of the file. Must be provided. + name: (Optional) The name of the file in the destination (e.g. + 'files/sample-image'). + display_name: (Optional) The display name of the file. + */ + file: File_2; + /** Used to override the default configuration. */ + config?: CreateFileConfig; +} + +/** Response for the create file method. */ +export declare class CreateFileResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; +} + +/** Optional parameters for creating a file search store. */ +export declare interface CreateFileSearchStoreConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** The human-readable display name for the file search store. + */ + displayName?: string; +} + +/** Config for file_search_stores.create parameters. */ +export declare interface CreateFileSearchStoreParameters { + /** Optional parameters for creating a file search store. + */ + config?: CreateFileSearchStoreConfig; +} + +/** + * Creates a `FunctionResponsePart` object from a `base64` encoded `string`. + */ +export declare function createFunctionResponsePartFromBase64(data: string, mimeType: string): FunctionResponsePart; + +/** + * Creates a `FunctionResponsePart` object from a `URI` string. + */ +export declare function createFunctionResponsePartFromUri(uri: string, mimeType: string): FunctionResponsePart; + +/** + * Creates a `Content` object with a model role from a `PartListUnion` object or `string`. + */ +export declare function createModelContent(partOrString: PartListUnion | string): Content; + +declare interface CreateModelInteractionParamsNonStreaming extends BaseCreateModelInteractionParams { + /** + * Body param: Input only. Whether the interaction will be streamed. + */ + stream?: false; +} + +declare interface CreateModelInteractionParamsStreaming extends BaseCreateModelInteractionParams { + /** + * Body param: Input only. Whether the interaction will be streamed. + */ + stream: true; +} + +/** + * Creates a `Part` object from a `base64` encoded `string`. + */ +export declare function createPartFromBase64(data: string, mimeType: string, mediaResolution?: PartMediaResolutionLevel): Part; + +/** + * Creates a `Part` object from the `outcome` and `output` of a `CodeExecutionResult` object. + */ +export declare function createPartFromCodeExecutionResult(outcome: Outcome, output: string): Part; + +/** + * Creates a `Part` object from the `code` and `language` of an `ExecutableCode` object. + */ +export declare function createPartFromExecutableCode(code: string, language: Language): Part; + +/** + * Creates a `Part` object from a `FunctionCall` object. + */ +export declare function createPartFromFunctionCall(name: string, args: Record<string, unknown>): Part; + +/** + * Creates a `Part` object from a `FunctionResponse` object. + */ +export declare function createPartFromFunctionResponse(id: string, name: string, response: Record<string, unknown>, parts?: FunctionResponsePart[]): Part; + +/** + * Creates a `Part` object from a `text` string. + */ +export declare function createPartFromText(text: string): Part; + +/** + * Creates a `Part` object from a `URI` string. + */ +export declare function createPartFromUri(uri: string, mimeType: string, mediaResolution?: PartMediaResolutionLevel): Part; + +/** Fine-tuning job creation request - optional fields. */ +export declare interface CreateTuningJobConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** The method to use for tuning (SUPERVISED_FINE_TUNING or PREFERENCE_TUNING or DISTILLATION). If not set, the default method (SFT) will be used. */ + method?: TuningMethod; + /** Validation dataset for tuning. The dataset must be formatted as a JSONL file. */ + validationDataset?: TuningValidationDataset; + /** The display name of the tuned Model. The name can be up to 128 characters long and can consist of any UTF-8 characters. */ + tunedModelDisplayName?: string; + /** The description of the TuningJob */ + description?: string; + /** Number of complete passes the model makes over the entire training dataset during training. */ + epochCount?: number; + /** Multiplier for adjusting the default learning rate. 1P models only. Mutually exclusive with learning_rate. */ + learningRateMultiplier?: number; + /** If set to true, disable intermediate checkpoints and only the last checkpoint will be exported. Otherwise, enable intermediate checkpoints. */ + exportLastCheckpointOnly?: boolean; + /** The optional checkpoint id of the pre-tuned model to use for tuning, if applicable. */ + preTunedModelCheckpointId?: string; + /** Adapter size for tuning. */ + adapterSize?: AdapterSize; + /** Tuning mode for SFT tuning. */ + tuningMode?: TuningMode; + /** Custom base model for tuning. This is only supported for OSS models in Vertex. */ + customBaseModel?: string; + /** The batch size hyperparameter for tuning. This is only supported for OSS models in Vertex. */ + batchSize?: number; + /** The learning rate for tuning. OSS models only. Mutually exclusive with learning_rate_multiplier. */ + learningRate?: number; + /** Optional. The labels with user-defined metadata to organize TuningJob and generated resources such as Model and Endpoint. Label keys and values can be no longer than 64 characters (Unicode codepoints), can only contain lowercase letters, numeric characters, underscores and dashes. International characters are allowed. See https://goo.gl/xmQnxf for more information and examples of labels. */ + labels?: Record<string, string>; + /** Weight for KL Divergence regularization, Preference Optimization tuning only. */ + beta?: number; + /** The base teacher model that is being distilled. Distillation only. */ + baseTeacherModel?: string; + /** The resource name of the Tuned teacher model. Distillation only. */ + tunedTeacherModelSource?: string; + /** Multiplier for adjusting the weight of the SFT loss. Distillation only. */ + sftLossWeightMultiplier?: number; + /** The Google Cloud Storage location where the tuning job outputs are written. */ + outputUri?: string; + /** The encryption spec of the tuning job. Customer-managed encryption key options for a TuningJob. If this is set, then all resources created by the TuningJob will be encrypted with provided encryption key. */ + encryptionSpec?: EncryptionSpec; +} + +/** Fine-tuning job creation parameters - optional fields. */ +export declare interface CreateTuningJobParameters { + /** The base model that is being tuned, e.g., "gemini-2.5-flash". */ + baseModel: string; + /** Cloud Storage path to file containing training dataset for tuning. The dataset must be formatted as a JSONL file. */ + trainingDataset: TuningDataset; + /** Configuration for the tuning job. */ + config?: CreateTuningJobConfig; +} + +/** Fine-tuning job creation parameters - optional fields. */ +export declare interface CreateTuningJobParametersPrivate { + /** The base model that is being tuned, e.g., "gemini-2.5-flash". */ + baseModel?: string; + /** The PreTunedModel that is being tuned. */ + preTunedModel?: PreTunedModel; + /** Cloud Storage path to file containing training dataset for tuning. The dataset must be formatted as a JSONL file. */ + trainingDataset: TuningDataset; + /** Configuration for the tuning job. */ + config?: CreateTuningJobConfig; +} + +/** + * Creates a `Content` object with a user role from a `PartListUnion` object or `string`. + */ +export declare function createUserContent(partOrString: PartListUnion | string): Content; + +/** User provided metadata stored as key-value pairs. This data type is not supported in Vertex AI. */ +export declare interface CustomMetadata { + /** Required. The key of the metadata to store. */ + key?: string; + /** The numeric value of the metadata to store. */ + numericValue?: number; + /** The StringList value of the metadata to store. */ + stringListValue?: StringList; + /** The string value of the metadata to store. */ + stringValue?: string; +} + +/** Distribution computed over a tuning dataset. This data type is not supported in Gemini API. */ +export declare interface DatasetDistribution { + /** Output only. Defines the histogram bucket. */ + buckets?: DatasetDistributionDistributionBucket[]; + /** Output only. The maximum of the population values. */ + max?: number; + /** Output only. The arithmetic mean of the values in the population. */ + mean?: number; + /** Output only. The median of the values in the population. */ + median?: number; + /** Output only. The minimum of the population values. */ + min?: number; + /** Output only. The 5th percentile of the values in the population. */ + p5?: number; + /** Output only. The 95th percentile of the values in the population. */ + p95?: number; + /** Output only. Sum of a given population of values. */ + sum?: number; +} + +/** Dataset bucket used to create a histogram for the distribution given a population of values. This data type is not supported in Gemini API. */ +export declare interface DatasetDistributionDistributionBucket { + /** Output only. Number of values in the bucket. */ + count?: string; + /** Output only. Left bound of the bucket. */ + left?: number; + /** Output only. Right bound of the bucket. */ + right?: number; +} + +/** Statistics computed over a tuning dataset. This data type is not supported in Gemini API. */ +export declare interface DatasetStats { + /** Output only. Number of billable characters in the tuning dataset. */ + totalBillableCharacterCount?: string; + /** Output only. Number of tuning characters in the tuning dataset. */ + totalTuningCharacterCount?: string; + /** Output only. Number of examples in the tuning dataset. */ + tuningDatasetExampleCount?: string; + /** Output only. Number of tuning steps for this Tuning Job. */ + tuningStepCount?: string; + /** Output only. Sample user messages in the training dataset uri. */ + userDatasetExamples?: Content[]; + /** Output only. Dataset distributions for the user input tokens. */ + userInputTokenDistribution?: DatasetDistribution; + /** Output only. Dataset distributions for the messages per example. */ + userMessagePerExampleDistribution?: DatasetDistribution; + /** Output only. Dataset distributions for the user output tokens. */ + userOutputTokenDistribution?: DatasetDistribution; +} + +/** + * Configuration for the Deep Research agent. + */ +declare interface DeepResearchAgentConfig { + /** + * Whether to include thought summaries in the response. + */ + thinking_summaries?: 'auto' | 'none'; + type?: 'deep-research'; +} + +/** Optional parameters for models.get method. */ +export declare interface DeleteBatchJobConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Config for batches.delete parameters. */ +export declare interface DeleteBatchJobParameters { + /** A fully-qualified BatchJob resource name or ID. + Example: "projects/.../locations/.../batchPredictionJobs/456" + or "456" when project and location are initialized in the client. + */ + name: string; + /** Optional parameters for the request. */ + config?: DeleteBatchJobConfig; +} + +/** Optional parameters for caches.delete method. */ +export declare interface DeleteCachedContentConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Parameters for caches.delete method. */ +export declare interface DeleteCachedContentParameters { + /** The server-generated resource name of the cached content. + */ + name: string; + /** Optional parameters for the request. + */ + config?: DeleteCachedContentConfig; +} + +/** Empty response for caches.delete method. */ +export declare class DeleteCachedContentResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; +} + +/** Config for optional parameters. */ +export declare interface DeleteDocumentConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** If set to true, any `Chunk`s and objects related to this `Document` will + also be deleted. + */ + force?: boolean; +} + +/** Config for documents.delete parameters. */ +export declare interface DeleteDocumentParameters { + /** The resource name of the Document. + Example: fileSearchStores/file-search-store-foo/documents/documents-bar */ + name: string; + /** Optional parameters for the request. */ + config?: DeleteDocumentConfig; +} + +/** Used to override the default configuration. */ +export declare interface DeleteFileConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Generates the parameters for the get method. */ +export declare interface DeleteFileParameters { + /** The name identifier for the file to be deleted. */ + name: string; + /** Used to override the default configuration. */ + config?: DeleteFileConfig; +} + +/** Response for the delete file method. */ +export declare class DeleteFileResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; +} + +/** Optional parameters for deleting a FileSearchStore. */ +export declare interface DeleteFileSearchStoreConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** If set to true, any Documents and objects related to this FileSearchStore will also be deleted. + If false (the default), a FAILED_PRECONDITION error will be returned if + the FileSearchStore contains any Documents. + */ + force?: boolean; +} + +/** Config for file_search_stores.delete parameters. */ +export declare interface DeleteFileSearchStoreParameters { + /** The resource name of the FileSearchStore. Example: `fileSearchStores/my-file-search-store-123` */ + name: string; + /** Optional parameters for the request. */ + config?: DeleteFileSearchStoreConfig; +} + +/** Configuration for deleting a tuned model. */ +export declare interface DeleteModelConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Parameters for deleting a tuned model. */ +export declare interface DeleteModelParameters { + model: string; + /** Optional parameters for the request. */ + config?: DeleteModelConfig; +} + +export declare class DeleteModelResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; +} + +/** The return value of delete operation. */ +export declare interface DeleteResourceJob { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + name?: string; + done?: boolean; + error?: JobError; +} + +/** Statistics computed for datasets used for distillation. This data type is not supported in Gemini API. */ +export declare interface DistillationDataStats { + /** Output only. Statistics computed for the training dataset. */ + trainingDatasetStats?: DatasetStats; +} + +/** Hyperparameters for Distillation. This data type is not supported in Gemini API. */ +export declare interface DistillationHyperParameters { + /** Optional. Adapter size for distillation. */ + adapterSize?: AdapterSize; + /** Optional. Number of complete passes the model makes over the entire training dataset during training. */ + epochCount?: string; + /** Optional. Multiplier for adjusting the default learning rate. */ + learningRateMultiplier?: number; +} + +/** Distillation tuning spec for tuning. */ +export declare interface DistillationSpec { + /** The GCS URI of the prompt dataset to use during distillation. */ + promptDatasetUri?: string; + /** The base teacher model that is being distilled. See [Supported models](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/tuning#supported_models). */ + baseTeacherModel?: string; + /** Optional. Hyperparameters for Distillation. */ + hyperParameters?: DistillationHyperParameters; + /** Deprecated. A path in a Cloud Storage bucket, which will be treated as the root output directory of the distillation pipeline. It is used by the system to generate the paths of output artifacts. */ + pipelineRootDirectory?: string; + /** The student model that is being tuned, e.g., "google/gemma-2b-1.1-it". Deprecated. Use base_model instead. */ + studentModel?: string; + /** Deprecated. Cloud Storage path to file containing training dataset for tuning. The dataset must be formatted as a JSONL file. */ + trainingDatasetUri?: string; + /** The resource name of the Tuned teacher model. Format: `projects/{project}/locations/{location}/models/{model}`. */ + tunedTeacherModelSource?: string; + /** Optional. Cloud Storage path to file containing validation dataset for tuning. The dataset must be formatted as a JSONL file. */ + validationDatasetUri?: string; +} + +/** A Document is a collection of Chunks. */ +declare interface Document_2 { + /** The resource name of the Document. + Example: fileSearchStores/file-search-store-foo/documents/documents-bar */ + name?: string; + /** The human-readable display name for the Document. */ + displayName?: string; + /** The current state of the Document. */ + state?: DocumentState; + /** The size of the Document in bytes. */ + sizeBytes?: string; + /** The MIME type of the Document. */ + mimeType?: string; + /** Output only. The Timestamp of when the `Document` was created. */ + createTime?: string; + /** Optional. User provided custom metadata stored as key-value pairs used for querying. A `Document` can have a maximum of 20 `CustomMetadata`. */ + customMetadata?: CustomMetadata[]; + /** Output only. The Timestamp of when the `Document` was last updated. */ + updateTime?: string; +} +export { Document_2 as Document } + +/** + * A document content block. + */ +declare interface DocumentContent { + type: 'document'; + /** + * The document content. + */ + data?: string; + /** + * The mime type of the document. + */ + mime_type?: DocumentMimeType; + /** + * The URI of the document. + */ + uri?: string; +} + +/** + * The mime type of the document. + */ +declare type DocumentMimeType = (string & {}) | 'application/pdf'; + +declare class Documents extends BaseModule { + private readonly apiClient; + constructor(apiClient: ApiClient); + /** + * Lists documents. + * + * @param params - The parameters for the list request. + * @return - A pager of documents. + * + * @example + * ```ts + * const documents = await ai.documents.list({parent:'rag_store_name', config: {'pageSize': 2}}); + * for await (const document of documents) { + * console.log(document); + * } + * ``` + */ + list: (params: types.ListDocumentsParameters) => Promise<Pager<types.Document>>; + /** + * Gets a Document. + * + * @param params - The parameters for getting a document. + * @return Document. + */ + get(params: types.GetDocumentParameters): Promise<types.Document>; + /** + * Deletes a Document. + * + * @param params - The parameters for deleting a document. + */ + delete(params: types.DeleteDocumentParameters): Promise<void>; + private listInternal; +} + +/** State for the lifecycle of a Document. */ +export declare enum DocumentState { + STATE_UNSPECIFIED = "STATE_UNSPECIFIED", + STATE_PENDING = "STATE_PENDING", + STATE_ACTIVE = "STATE_ACTIVE", + STATE_FAILED = "STATE_FAILED" +} + +/** @ts-ignore */ +declare type _DOMReadableStream<R = any> = globalThis.ReadableStream<R>; + +export declare type DownloadableFileUnion = string | File_2 | GeneratedVideo | Video; + +declare interface Downloader { + /** + * Downloads a file to the given location. + * + * @param params The parameters for downloading the file. + * @param apiClient The ApiClient to use for uploading. + * @return A Promises that resolves when the download is complete. + */ + download(params: DownloadFileParameters, apiClient: ApiClient): Promise<void>; +} + +/** Used to override the default configuration. */ +export declare interface DownloadFileConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Parameters used to download a file. */ +export declare interface DownloadFileParameters { + /** The file to download. It can be a file name, a file object or a generated video. */ + file: DownloadableFileUnion; + /** Location where the file should be downloaded to. */ + downloadPath: string; + /** Configuration to for the download operation. */ + config?: DownloadFileConfig; +} + +/** + * Configuration for dynamic agents. + */ +declare interface DynamicAgentConfig { + type?: 'dynamic'; + [k: string]: unknown; +} + +/** Describes the options to customize dynamic retrieval. */ +export declare interface DynamicRetrievalConfig { + /** Optional. The threshold to be used in dynamic retrieval. If not set, a system default value is used. */ + dynamicThreshold?: number; + /** The mode of the predictor to be used in dynamic retrieval. */ + mode?: DynamicRetrievalConfigMode; +} + +/** The mode of the predictor to be used in dynamic retrieval. */ +export declare enum DynamicRetrievalConfigMode { + /** + * Always trigger retrieval. + */ + MODE_UNSPECIFIED = "MODE_UNSPECIFIED", + /** + * Run retrieval only when system decides it is necessary. + */ + MODE_DYNAMIC = "MODE_DYNAMIC" +} + +/** Configuration for editing an image. */ +export declare interface EditImageConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** Cloud Storage URI used to store the generated images. */ + outputGcsUri?: string; + /** Description of what to discourage in the generated images. */ + negativePrompt?: string; + /** Number of images to generate. */ + numberOfImages?: number; + /** Aspect ratio of the generated images. Supported values are + "1:1", "3:4", "4:3", "9:16", and "16:9". */ + aspectRatio?: string; + /** Controls how much the model adheres to the text prompt. Large + values increase output and prompt alignment, but may compromise image + quality. */ + guidanceScale?: number; + /** Random seed for image generation. This is not available when + ``add_watermark`` is set to true. */ + seed?: number; + /** Filter level for safety filtering. */ + safetyFilterLevel?: SafetyFilterLevel; + /** Allows generation of people by the model. */ + personGeneration?: PersonGeneration; + /** Whether to report the safety scores of each generated image and + the positive prompt in the response. */ + includeSafetyAttributes?: boolean; + /** Whether to include the Responsible AI filter reason if the image + is filtered out of the response. */ + includeRaiReason?: boolean; + /** Language of the text in the prompt. */ + language?: ImagePromptLanguage; + /** MIME type of the generated image. */ + outputMimeType?: string; + /** Compression quality of the generated image (for ``image/jpeg`` + only). */ + outputCompressionQuality?: number; + /** Whether to add a watermark to the generated images. */ + addWatermark?: boolean; + /** User specified labels to track billing usage. */ + labels?: Record<string, string>; + /** Describes the editing mode for the request. */ + editMode?: EditMode; + /** The number of sampling steps. A higher value has better image + quality, while a lower value has better latency. */ + baseSteps?: number; +} + +/** Parameters for the request to edit an image. */ +export declare interface EditImageParameters { + /** The model to use. */ + model: string; + /** A text description of the edit to apply to the image. */ + prompt: string; + /** The reference images for Imagen 3 editing. */ + referenceImages: ReferenceImage[]; + /** Configuration for editing. */ + config?: EditImageConfig; +} + +/** Response for the request to edit an image. */ +export declare class EditImageResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** Generated images. */ + generatedImages?: GeneratedImage[]; +} + +/** Enum representing the editing mode. */ +export declare enum EditMode { + EDIT_MODE_DEFAULT = "EDIT_MODE_DEFAULT", + EDIT_MODE_INPAINT_REMOVAL = "EDIT_MODE_INPAINT_REMOVAL", + EDIT_MODE_INPAINT_INSERTION = "EDIT_MODE_INPAINT_INSERTION", + EDIT_MODE_OUTPAINT = "EDIT_MODE_OUTPAINT", + EDIT_MODE_CONTROLLED_EDITING = "EDIT_MODE_CONTROLLED_EDITING", + EDIT_MODE_STYLE = "EDIT_MODE_STYLE", + EDIT_MODE_BGSWAP = "EDIT_MODE_BGSWAP", + EDIT_MODE_PRODUCT_IMAGE = "EDIT_MODE_PRODUCT_IMAGE" +} + +/** Parameters for the embed_content method. */ +export declare interface EmbedContentBatch { + /** The content to embed. Only the `parts.text` fields will be counted. + */ + contents?: ContentListUnion; + /** Configuration that contains optional parameters. + */ + config?: EmbedContentConfig; +} + +/** Optional parameters for the embed_content method. */ +export declare interface EmbedContentConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** Type of task for which the embedding will be used. + */ + taskType?: string; + /** Title for the text. Only applicable when TaskType is + `RETRIEVAL_DOCUMENT`. + */ + title?: string; + /** Reduced dimension for the output embedding. If set, + excessive values in the output embedding are truncated from the end. + Supported by newer models since 2024 only. You cannot set this value if + using the earlier model (`models/embedding-001`). + */ + outputDimensionality?: number; + /** Vertex API only. The MIME type of the input. + */ + mimeType?: string; + /** Vertex API only. Whether to silently truncate inputs longer than + the max sequence length. If this option is set to false, oversized inputs + will lead to an INVALID_ARGUMENT error, similar to other text APIs. + */ + autoTruncate?: boolean; +} + +/** Request-level metadata for the Vertex Embed Content API. */ +export declare interface EmbedContentMetadata { + /** Vertex API only. The total number of billable characters included + in the request. + */ + billableCharacterCount?: number; +} + +/** Parameters for the embed_content method. */ +export declare interface EmbedContentParameters { + /** ID of the model to use. For a list of models, see `Google models + <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */ + model: string; + /** The content to embed. Only the `parts.text` fields will be counted. + */ + contents: ContentListUnion; + /** Configuration that contains optional parameters. + */ + config?: EmbedContentConfig; +} + +/** Response for the embed_content method. */ +export declare class EmbedContentResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** The embeddings for each request, in the same order as provided in + the batch request. + */ + embeddings?: ContentEmbedding[]; + /** Vertex API only. Metadata about the request. + */ + metadata?: EmbedContentMetadata; +} + +export declare interface EmbeddingsBatchJobSource { + /** The Gemini Developer API's file resource name of the input data + (e.g. "files/12345"). + */ + fileName?: string; + /** The Gemini Developer API's inlined input data to run batch job. + */ + inlinedRequests?: EmbedContentBatch; +} + +/** Represents a customer-managed encryption key spec that can be applied to a top-level resource. This data type is not supported in Gemini API. */ +export declare interface EncryptionSpec { + /** Required. The Cloud KMS resource identifier of the customer managed encryption key used to protect a resource. Has the form: `projects/my-project/locations/my-region/keyRings/my-kr/cryptoKeys/my-key`. The key needs to be in the same region as where the compute resource is created. */ + kmsKeyName?: string; +} + +/** An endpoint where you deploy models. */ +export declare interface Endpoint { + /** Resource name of the endpoint. */ + name?: string; + /** ID of the model that's deployed to the endpoint. */ + deployedModelId?: string; +} + +/** End of speech sensitivity. */ +export declare enum EndSensitivity { + /** + * The default is END_SENSITIVITY_LOW. + */ + END_SENSITIVITY_UNSPECIFIED = "END_SENSITIVITY_UNSPECIFIED", + /** + * Automatic detection ends speech more often. + */ + END_SENSITIVITY_HIGH = "END_SENSITIVITY_HIGH", + /** + * Automatic detection ends speech less often. + */ + END_SENSITIVITY_LOW = "END_SENSITIVITY_LOW" +} + +/** Tool to search public web data, powered by Vertex AI Search and Sec4 compliance. This data type is not supported in Gemini API. */ +export declare interface EnterpriseWebSearch { + /** Optional. List of domains to be excluded from the search results. The default limit is 2000 domains. */ + excludeDomains?: string[]; + /** Optional. Sites with confidence level chosen & above this value will be blocked from the search results. */ + blockingConfidence?: PhishBlockThreshold; +} + +/** An entity representing the segmented area. */ +export declare interface EntityLabel { + /** The label of the segmented entity. */ + label?: string; + /** The confidence score of the detected label. */ + score?: number; +} + +/** The environment being operated. */ +export declare enum Environment { + /** + * Defaults to browser. + */ + ENVIRONMENT_UNSPECIFIED = "ENVIRONMENT_UNSPECIFIED", + /** + * Operates in a web browser. + */ + ENVIRONMENT_BROWSER = "ENVIRONMENT_BROWSER" +} + +declare interface ErrorEvent_2 { + /** + * Error message from an interaction. + */ + error?: ErrorEvent_2.Error; + /** + * The event_id token to be used to resume the interaction stream, from this event. + */ + event_id?: string; + event_type?: 'error'; +} + +declare namespace ErrorEvent_2 { + /** + * Error message from an interaction. + */ + interface Error { + /** + * A URI that identifies the error type. + */ + code?: string; + /** + * A human-readable error message. + */ + message?: string; + } +} + +declare namespace Errors { + export { + GeminiNextGenAPIClientError, + APIError, + APIUserAbortError, + APIConnectionError, + APIConnectionTimeoutError, + BadRequestError, + AuthenticationError, + PermissionDeniedError, + NotFoundError, + ConflictError, + UnprocessableEntityError, + RateLimitError, + InternalServerError + } +} + +/** Code generated by the model that is meant to be executed, and the result returned to the model. Generated when using the [CodeExecution] tool, in which the code will be automatically executed, and a corresponding [CodeExecutionResult] will also be generated. */ +export declare interface ExecutableCode { + /** Required. The code to be executed. */ + code?: string; + /** Required. Programming language of the `code`. */ + language?: Language; +} + +/** Retrieve from data source powered by external API for grounding. The external API is not owned by Google, but need to follow the pre-defined API spec. This data type is not supported in Gemini API. */ +export declare interface ExternalApi { + /** The authentication config to access the API. Deprecated. Please use auth_config instead. */ + apiAuth?: ApiAuth; + /** The API spec that the external API implements. */ + apiSpec?: ApiSpec; + /** The authentication config to access the API. */ + authConfig?: AuthConfig; + /** Parameters for the elastic search API. */ + elasticSearchParams?: ExternalApiElasticSearchParams; + /** The endpoint of the external API. The system will call the API at this endpoint to retrieve the data for grounding. Example: https://acme.com:443/search */ + endpoint?: string; + /** Parameters for the simple search API. */ + simpleSearchParams?: ExternalApiSimpleSearchParams; +} + +/** The search parameters to use for the ELASTIC_SEARCH spec. This data type is not supported in Gemini API. */ +export declare interface ExternalApiElasticSearchParams { + /** The ElasticSearch index to use. */ + index?: string; + /** Optional. Number of hits (chunks) to request. When specified, it is passed to Elasticsearch as the `num_hits` param. */ + numHits?: number; + /** The ElasticSearch search template to use. */ + searchTemplate?: string; +} + +/** The search parameters to use for SIMPLE_SEARCH spec. This data type is not supported in Gemini API. */ +export declare interface ExternalApiSimpleSearchParams { +} + +/** Options for feature selection preference. */ +export declare enum FeatureSelectionPreference { + FEATURE_SELECTION_PREFERENCE_UNSPECIFIED = "FEATURE_SELECTION_PREFERENCE_UNSPECIFIED", + PRIORITIZE_QUALITY = "PRIORITIZE_QUALITY", + BALANCED = "BALANCED", + PRIORITIZE_COST = "PRIORITIZE_COST" +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +declare type Fetch = (input: string | URL | Request, init?: RequestInit) => Promise<Response>; + +export declare interface FetchPredictOperationConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Parameters for the fetchPredictOperation method. */ +export declare interface FetchPredictOperationParameters { + /** The server-assigned name for the operation. */ + operationName: string; + resourceName: string; + /** Used to override the default configuration. */ + config?: FetchPredictOperationConfig; +} + +/** @ts-ignore For users who use Deno */ +declare type FetchRequestInit = NonNullable<OverloadedParameters<typeof fetch>[1]>; + +/** A file uploaded to the API. */ +declare interface File_2 { + /** The `File` resource name. The ID (name excluding the "files/" prefix) can contain up to 40 characters that are lowercase alphanumeric or dashes (-). The ID cannot start or end with a dash. If the name is empty on create, a unique name will be generated. Example: `files/123-456` */ + name?: string; + /** Optional. The human-readable display name for the `File`. The display name must be no more than 512 characters in length, including spaces. Example: 'Welcome Image' */ + displayName?: string; + /** Output only. MIME type of the file. */ + mimeType?: string; + /** Output only. Size of the file in bytes. */ + sizeBytes?: string; + /** Output only. The timestamp of when the `File` was created. */ + createTime?: string; + /** Output only. The timestamp of when the `File` will be deleted. Only set if the `File` is scheduled to expire. */ + expirationTime?: string; + /** Output only. The timestamp of when the `File` was last updated. */ + updateTime?: string; + /** Output only. SHA-256 hash of the uploaded bytes. The hash value is encoded in base64 format. */ + sha256Hash?: string; + /** Output only. The URI of the `File`. */ + uri?: string; + /** Output only. The URI of the `File`, only set for downloadable (generated) files. */ + downloadUri?: string; + /** Output only. Processing state of the File. */ + state?: FileState; + /** Output only. The source of the `File`. */ + source?: FileSource; + /** Output only. Metadata for a video. */ + videoMetadata?: Record<string, unknown>; + /** Output only. Error status if File processing failed. */ + error?: FileStatus; +} +export { File_2 as File } + +/** URI based data. */ +export declare interface FileData { + /** Optional. Display name of the file data. Used to provide a label or filename to distinguish file datas. This field is only returned in PromptMessage for prompt management. It is currently used in the Gemini GenerateContent calls only when server side tools (code_execution, google_search, and url_context) are enabled. This field is not supported in Gemini API. */ + displayName?: string; + /** Required. URI. */ + fileUri?: string; + /** Required. The IANA standard MIME type of the source data. */ + mimeType?: string; +} + +export declare class Files extends BaseModule { + private readonly apiClient; + constructor(apiClient: ApiClient); + /** + * Lists files. + * + * @param params - The parameters for the list request. + * @return - A pager of files. + * + * @example + * ```ts + * const files = await ai.files.list({config: {'pageSize': 2}}); + * for await (const file of files) { + * console.log(file); + * } + * ``` + */ + list: (params?: types.ListFilesParameters) => Promise<Pager<types.File>>; + /** + * Uploads a file asynchronously to the Gemini API. + * This method is not available in Vertex AI. + * Supported upload sources: + * - Node.js: File path (string) or Blob object. + * - Browser: Blob object (e.g., File). + * + * @remarks + * The `mimeType` can be specified in the `config` parameter. If omitted: + * - For file path (string) inputs, the `mimeType` will be inferred from the + * file extension. + * - For Blob object inputs, the `mimeType` will be set to the Blob's `type` + * property. + * Somex eamples for file extension to mimeType mapping: + * .txt -> text/plain + * .json -> application/json + * .jpg -> image/jpeg + * .png -> image/png + * .mp3 -> audio/mpeg + * .mp4 -> video/mp4 + * + * This section can contain multiple paragraphs and code examples. + * + * @param params - Optional parameters specified in the + * `types.UploadFileParameters` interface. + * @see {@link types.UploadFileParameters#config} for the optional + * config in the parameters. + * @return A promise that resolves to a `types.File` object. + * @throws An error if called on a Vertex AI client. + * @throws An error if the `mimeType` is not provided and can not be inferred, + * the `mimeType` can be provided in the `params.config` parameter. + * @throws An error occurs if a suitable upload location cannot be established. + * + * @example + * The following code uploads a file to Gemini API. + * + * ```ts + * const file = await ai.files.upload({file: 'file.txt', config: { + * mimeType: 'text/plain', + * }}); + * console.log(file.name); + * ``` + */ + upload(params: types.UploadFileParameters): Promise<types.File>; + /** + * Downloads a remotely stored file asynchronously to a location specified in + * the `params` object. This method only works on Node environment, to + * download files in the browser, use a browser compliant method like an <a> + * tag. + * + * @param params - The parameters for the download request. + * + * @example + * The following code downloads an example file named "files/mehozpxf877d" as + * "file.txt". + * + * ```ts + * await ai.files.download({file: file.name, downloadPath: 'file.txt'}); + * ``` + */ + download(params: types.DownloadFileParameters): Promise<void>; + /** + * Registers Google Cloud Storage files for use with the API. + * This method is only available in Node.js environments. + */ + registerFiles(params: types.RegisterFilesParameters): Promise<types.RegisterFilesResponse>; + protected _registerFiles(params: types.InternalRegisterFilesParameters): Promise<types.RegisterFilesResponse>; + private listInternal; + private createInternal; + /** + * Retrieves the file information from the service. + * + * @param params - The parameters for the get request + * @return The Promise that resolves to the types.File object requested. + * + * @example + * ```ts + * const config: GetFileParameters = { + * name: fileName, + * }; + * file = await ai.files.get(config); + * console.log(file.name); + * ``` + */ + get(params: types.GetFileParameters): Promise<types.File>; + /** + * Deletes a remotely stored file. + * + * @param params - The parameters for the delete request. + * @return The DeleteFileResponse, the response for the delete method. + * + * @example + * The following code deletes an example file named "files/mehozpxf877d". + * + * ```ts + * await ai.files.delete({name: file.name}); + * ``` + */ + delete(params: types.DeleteFileParameters): Promise<types.DeleteFileResponse>; + private registerFilesInternal; +} + +/** Tool to retrieve knowledge from the File Search Stores. */ +export declare interface FileSearch { + /** The names of the file_search_stores to retrieve from. + Example: `fileSearchStores/my-file-search-store-123` */ + fileSearchStoreNames?: string[]; + /** The number of file search retrieval chunks to retrieve. */ + topK?: number; + /** Metadata filter to apply to the file search retrieval documents. See https://google.aip.dev/160 for the syntax of the filter expression. */ + metadataFilter?: string; +} + +/** + * File Search content. + */ +declare interface FileSearchCallContent { + type: 'file_search_call'; + /** + * A unique ID for this specific tool call. + */ + id?: string; +} + +/** + * File Search result content. + */ +declare interface FileSearchResultContent { + type: 'file_search_result'; + /** + * The results of the File Search. + */ + result?: Array<FileSearchResultContent.Result>; +} + +declare namespace FileSearchResultContent { + /** + * The result of the File Search. + */ + interface Result { + /** + * The name of the file search store. + */ + file_search_store?: string; + /** + * The text of the search result. + */ + text?: string; + /** + * The title of the search result. + */ + title?: string; + } +} + +/** A collection of Documents. */ +export declare interface FileSearchStore { + /** The resource name of the FileSearchStore. Example: `fileSearchStores/my-file-search-store-123` */ + name?: string; + /** The human-readable display name for the FileSearchStore. */ + displayName?: string; + /** The Timestamp of when the FileSearchStore was created. */ + createTime?: string; + /** The Timestamp of when the FileSearchStore was last updated. */ + updateTime?: string; + /** The number of documents in the FileSearchStore that are active and ready for retrieval. */ + activeDocumentsCount?: string; + /** The number of documents in the FileSearchStore that are being processed. */ + pendingDocumentsCount?: string; + /** The number of documents in the FileSearchStore that have failed processing. */ + failedDocumentsCount?: string; + /** The size of raw bytes ingested into the FileSearchStore. This is the + total size of all the documents in the FileSearchStore. */ + sizeBytes?: string; +} + +declare class FileSearchStores extends BaseModule { + private readonly apiClient; + readonly documents: Documents; + constructor(apiClient: ApiClient, documents?: Documents); + /** + * Lists file search stores. + * + * @param params - The parameters for the list request. + * @return - A pager of file search stores. + * + * @example + * ```ts + * const fileSearchStores = await ai.fileSearchStores.list({config: {'pageSize': 2}}); + * for await (const fileSearchStore of fileSearchStores) { + * console.log(fileSearchStore); + * } + * ``` + */ + list: (params?: types.ListFileSearchStoresParameters) => Promise<Pager<types.FileSearchStore>>; + /** + * Uploads a file asynchronously to a given File Search Store. + * This method is not available in Vertex AI. + * Supported upload sources: + * - Node.js: File path (string) or Blob object. + * - Browser: Blob object (e.g., File). + * + * @remarks + * The `mimeType` can be specified in the `config` parameter. If omitted: + * - For file path (string) inputs, the `mimeType` will be inferred from the + * file extension. + * - For Blob object inputs, the `mimeType` will be set to the Blob's `type` + * property. + * + * This section can contain multiple paragraphs and code examples. + * + * @param params - Optional parameters specified in the + * `types.UploadToFileSearchStoreParameters` interface. + * @see {@link types.UploadToFileSearchStoreParameters#config} for the optional + * config in the parameters. + * @return A promise that resolves to a long running operation. + * @throws An error if called on a Vertex AI client. + * @throws An error if the `mimeType` is not provided and can not be inferred, + * the `mimeType` can be provided in the `params.config` parameter. + * @throws An error occurs if a suitable upload location cannot be established. + * + * @example + * The following code uploads a file to a given file search store. + * + * ```ts + * const operation = await ai.fileSearchStores.upload({fileSearchStoreName: 'fileSearchStores/foo-bar', file: 'file.txt', config: { + * mimeType: 'text/plain', + * }}); + * console.log(operation.name); + * ``` + */ + uploadToFileSearchStore(params: types.UploadToFileSearchStoreParameters): Promise<types.UploadToFileSearchStoreOperation>; + /** + * Creates a File Search Store. + * + * @param params - The parameters for creating a File Search Store. + * @return FileSearchStore. + */ + create(params: types.CreateFileSearchStoreParameters): Promise<types.FileSearchStore>; + /** + * Gets a File Search Store. + * + * @param params - The parameters for getting a File Search Store. + * @return FileSearchStore. + */ + get(params: types.GetFileSearchStoreParameters): Promise<types.FileSearchStore>; + /** + * Deletes a File Search Store. + * + * @param params - The parameters for deleting a File Search Store. + */ + delete(params: types.DeleteFileSearchStoreParameters): Promise<void>; + private listInternal; + private uploadToFileSearchStoreInternal; + /** + * Imports a File from File Service to a FileSearchStore. + * + * This is a long-running operation, see aip.dev/151 + * + * @param params - The parameters for importing a file to a file search store. + * @return ImportFileOperation. + */ + importFile(params: types.ImportFileParameters): Promise<types.ImportFileOperation>; +} + +/** Source of the File. */ +export declare enum FileSource { + SOURCE_UNSPECIFIED = "SOURCE_UNSPECIFIED", + UPLOADED = "UPLOADED", + GENERATED = "GENERATED", + REGISTERED = "REGISTERED" +} + +/** + * Represents the size and mimeType of a file. The information is used to + * request the upload URL from the https://generativelanguage.googleapis.com/upload/v1beta/files endpoint. + * This interface defines the structure for constructing and executing HTTP + * requests. + */ +declare interface FileStat { + /** + * The size of the file in bytes. + */ + size: number; + /** + * The MIME type of the file. + */ + type: string | undefined; +} + +/** State for the lifecycle of a File. */ +export declare enum FileState { + STATE_UNSPECIFIED = "STATE_UNSPECIFIED", + PROCESSING = "PROCESSING", + ACTIVE = "ACTIVE", + FAILED = "FAILED" +} + +/** Status of a File that uses a common error model. */ +export declare interface FileStatus { + /** A list of messages that carry the error details. There is a common set of message types for APIs to use. */ + details?: Record<string, unknown>[]; + /** A list of messages that carry the error details. There is a common set of message types for APIs to use. */ + message?: string; + /** The status code. 0 for OK, 1 for CANCELLED */ + code?: number; +} + +declare type FinalizedRequestInit = RequestInit & { + headers: Headers; +}; + +declare type FinalRequestOptions = RequestOptions & { + method: HTTPMethod; + path: string; +}; + +/** Output only. The reason why the model stopped generating tokens. + + If empty, the model has not stopped generating the tokens. */ +export declare enum FinishReason { + /** + * The finish reason is unspecified. + */ + FINISH_REASON_UNSPECIFIED = "FINISH_REASON_UNSPECIFIED", + /** + * Token generation reached a natural stopping point or a configured stop sequence. + */ + STOP = "STOP", + /** + * Token generation reached the configured maximum output tokens. + */ + MAX_TOKENS = "MAX_TOKENS", + /** + * Token generation stopped because the content potentially contains safety violations. NOTE: When streaming, [content][] is empty if content filters blocks the output. + */ + SAFETY = "SAFETY", + /** + * The token generation stopped because of potential recitation. + */ + RECITATION = "RECITATION", + /** + * The token generation stopped because of using an unsupported language. + */ + LANGUAGE = "LANGUAGE", + /** + * All other reasons that stopped the token generation. + */ + OTHER = "OTHER", + /** + * Token generation stopped because the content contains forbidden terms. + */ + BLOCKLIST = "BLOCKLIST", + /** + * Token generation stopped for potentially containing prohibited content. + */ + PROHIBITED_CONTENT = "PROHIBITED_CONTENT", + /** + * Token generation stopped because the content potentially contains Sensitive Personally Identifiable Information (SPII). + */ + SPII = "SPII", + /** + * The function call generated by the model is invalid. + */ + MALFORMED_FUNCTION_CALL = "MALFORMED_FUNCTION_CALL", + /** + * Token generation stopped because generated images have safety violations. + */ + IMAGE_SAFETY = "IMAGE_SAFETY", + /** + * The tool call generated by the model is invalid. + */ + UNEXPECTED_TOOL_CALL = "UNEXPECTED_TOOL_CALL", + /** + * Image generation stopped because the generated images have prohibited content. + */ + IMAGE_PROHIBITED_CONTENT = "IMAGE_PROHIBITED_CONTENT", + /** + * The model was expected to generate an image, but none was generated. + */ + NO_IMAGE = "NO_IMAGE", + /** + * Image generation stopped because the generated image may be a recitation from a source. + */ + IMAGE_RECITATION = "IMAGE_RECITATION", + /** + * Image generation stopped for a reason not otherwise specified. + */ + IMAGE_OTHER = "IMAGE_OTHER" +} + +/** + * A tool that can be used by the model. + */ +declare interface Function_2 { + type: 'function'; + /** + * A description of the function. + */ + description?: string; + /** + * The name of the function. + */ + name?: string; + /** + * The JSON Schema for the function's parameters. + */ + parameters?: unknown; +} + +/** A function call. */ +export declare interface FunctionCall { + /** The unique id of the function call. If populated, the client to execute the + `function_call` and return the response with the matching `id`. */ + id?: string; + /** Optional. The function parameters and values in JSON object format. See [FunctionDeclaration.parameters] for parameter details. */ + args?: Record<string, unknown>; + /** Optional. The name of the function to call. Matches [FunctionDeclaration.name]. */ + name?: string; + /** Optional. The partial argument value of the function call. If provided, represents the arguments/fields that are streamed incrementally. This field is not supported in Gemini API. */ + partialArgs?: PartialArg[]; + /** Optional. Whether this is the last part of the FunctionCall. If true, another partial message for the current FunctionCall is expected to follow. This field is not supported in Gemini API. */ + willContinue?: boolean; +} + +/** + * A function tool call content block. + */ +declare interface FunctionCallContent { + /** + * A unique ID for this specific tool call. + */ + id: string; + /** + * The arguments to pass to the function. + */ + arguments: { + [key: string]: unknown; + }; + /** + * The name of the tool to call. + */ + name: string; + type: 'function_call'; +} + +/** Function calling config. */ +export declare interface FunctionCallingConfig { + /** Optional. Function names to call. Only set when the Mode is ANY. Function names should match [FunctionDeclaration.name]. With mode set to ANY, model will predict a function call from the set of function names provided. */ + allowedFunctionNames?: string[]; + /** Optional. Function calling mode. */ + mode?: FunctionCallingConfigMode; + /** Optional. When set to true, arguments of a single function call will be streamed out in multiple parts/contents/responses. Partial parameter results will be returned in the [FunctionCall.partial_args] field. This field is not supported in Gemini API. */ + streamFunctionCallArguments?: boolean; +} + +/** Function calling mode. */ +export declare enum FunctionCallingConfigMode { + /** + * Unspecified function calling mode. This value should not be used. + */ + MODE_UNSPECIFIED = "MODE_UNSPECIFIED", + /** + * Default model behavior, model decides to predict either function calls or natural language response. + */ + AUTO = "AUTO", + /** + * Model is constrained to always predicting function calls only. If "allowed_function_names" are set, the predicted function calls will be limited to any one of "allowed_function_names", else the predicted function calls will be any one of the provided "function_declarations". + */ + ANY = "ANY", + /** + * Model will not predict any function calls. Model behavior is same as when not passing any function declarations. + */ + NONE = "NONE", + /** + * Model is constrained to predict either function calls or natural language response. If "allowed_function_names" are set, the predicted function calls will be limited to any one of "allowed_function_names", else the predicted function calls will be any one of the provided "function_declarations". + */ + VALIDATED = "VALIDATED" +} + +/** Structured representation of a function declaration as defined by the [OpenAPI 3.0 specification](https://spec.openapis.org/oas/v3.0.3). Included in this declaration are the function name, description, parameters and response type. This FunctionDeclaration is a representation of a block of code that can be used as a `Tool` by the model and executed by the client. */ +export declare interface FunctionDeclaration { + /** Optional. Description and purpose of the function. Model uses it to decide how and whether to call the function. */ + description?: string; + /** Required. The name of the function to call. Must start with a letter or an underscore. Must be a-z, A-Z, 0-9, or contain underscores, dots and dashes, with a maximum length of 64. */ + name?: string; + /** Optional. Describes the parameters to this function in JSON Schema Object format. Reflects the Open API 3.03 Parameter Object. string Key: the name of the parameter. Parameter names are case sensitive. Schema Value: the Schema defining the type used for the parameter. For function with no parameters, this can be left unset. Parameter names must start with a letter or an underscore and must only contain chars a-z, A-Z, 0-9, or underscores with a maximum length of 64. Example with 1 required and 1 optional parameter: type: OBJECT properties: param1: type: STRING param2: type: INTEGER required: - param1 */ + parameters?: Schema; + /** Optional. Describes the parameters to the function in JSON Schema format. The schema must describe an object where the properties are the parameters to the function. For example: ``` { "type": "object", "properties": { "name": { "type": "string" }, "age": { "type": "integer" } }, "additionalProperties": false, "required": ["name", "age"], "propertyOrdering": ["name", "age"] } ``` This field is mutually exclusive with `parameters`. */ + parametersJsonSchema?: unknown; + /** Optional. Describes the output from this function in JSON Schema format. Reflects the Open API 3.03 Response Object. The Schema defines the type used for the response value of the function. */ + response?: Schema; + /** Optional. Describes the output from this function in JSON Schema format. The value specified by the schema is the response value of the function. This field is mutually exclusive with `response`. */ + responseJsonSchema?: unknown; + /** Optional. Specifies the function Behavior. Currently only supported by the BidiGenerateContent method. This field is not supported in Vertex AI. */ + behavior?: Behavior; +} + +/** A function response. */ +export declare class FunctionResponse { + /** Signals that function call continues, and more responses will be returned, turning the function call into a generator. Is only applicable to NON_BLOCKING function calls (see FunctionDeclaration.behavior for details), ignored otherwise. If false, the default, future responses will not be considered. Is only applicable to NON_BLOCKING function calls, is ignored otherwise. If set to false, future responses will not be considered. It is allowed to return empty `response` with `will_continue=False` to signal that the function call is finished. */ + willContinue?: boolean; + /** Specifies how the response should be scheduled in the conversation. Only applicable to NON_BLOCKING function calls, is ignored otherwise. Defaults to WHEN_IDLE. */ + scheduling?: FunctionResponseScheduling; + /** List of parts that constitute a function response. Each part may + have a different IANA MIME type. */ + parts?: FunctionResponsePart[]; + /** Optional. The id of the function call this response is for. Populated by the client to match the corresponding function call `id`. */ + id?: string; + /** Required. The name of the function to call. Matches [FunctionDeclaration.name] and [FunctionCall.name]. */ + name?: string; + /** Required. The function response in JSON object format. Use "output" key to specify function output and "error" key to specify error details (if any). If "output" and "error" keys are not specified, then whole "response" is treated as function output. */ + response?: Record<string, unknown>; +} + +/** Raw media bytes for function response. + + Text should not be sent as raw bytes, use the FunctionResponse.response + field. */ +export declare class FunctionResponseBlob { + /** Required. The IANA standard MIME type of the source data. */ + mimeType?: string; + /** Required. Inline media bytes. + * @remarks Encoded as base64 string. */ + data?: string; + /** Optional. Display name of the blob. + Used to provide a label or filename to distinguish blobs. */ + displayName?: string; +} + +/** URI based data for function response. */ +export declare class FunctionResponseFileData { + /** Required. URI. */ + fileUri?: string; + /** Required. The IANA standard MIME type of the source data. */ + mimeType?: string; + /** Optional. Display name of the file. + Used to provide a label or filename to distinguish files. */ + displayName?: string; +} + +/** A datatype containing media that is part of a `FunctionResponse` message. + + A `FunctionResponsePart` consists of data which has an associated datatype. A + `FunctionResponsePart` can only contain one of the accepted types in + `FunctionResponsePart.data`. + + A `FunctionResponsePart` must have a fixed IANA MIME type identifying the + type and subtype of the media if the `inline_data` field is filled with raw + bytes. */ +export declare class FunctionResponsePart { + /** Optional. Inline media bytes. */ + inlineData?: FunctionResponseBlob; + /** Optional. URI based data. */ + fileData?: FunctionResponseFileData; +} + +/** Specifies how the response should be scheduled in the conversation. */ +export declare enum FunctionResponseScheduling { + /** + * This value is unused. + */ + SCHEDULING_UNSPECIFIED = "SCHEDULING_UNSPECIFIED", + /** + * Only add the result to the conversation context, do not interrupt or trigger generation. + */ + SILENT = "SILENT", + /** + * Add the result to the conversation context, and prompt to generate output without interrupting ongoing generation. + */ + WHEN_IDLE = "WHEN_IDLE", + /** + * Add the result to the conversation context, interrupt ongoing generation and prompt to generate output. + */ + INTERRUPT = "INTERRUPT" +} + +/** + * A function tool result content block. + */ +declare interface FunctionResultContent { + /** + * ID to match the ID from the function call block. + */ + call_id: string; + /** + * The result of the tool call. + */ + result: FunctionResultContent.Items | unknown | string; + type: 'function_result'; + /** + * Whether the tool call resulted in an error. + */ + is_error?: boolean; + /** + * The name of the tool that was called. + */ + name?: string; +} + +declare namespace FunctionResultContent { + interface Items { + items?: Array<InteractionsAPI.TextContent | InteractionsAPI.ImageContent>; + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +declare interface GeminiNextGenAPIClientAdapter { + isVertexAI: () => boolean; + getProject: () => string | undefined; + getLocation: () => string | undefined; + getAuthHeaders: () => Headers | Promise<Headers>; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +declare class GeminiNextGenAPIClientError extends Error { +} + +/** Input example for preference optimization. This data type is not supported in Gemini API. */ +export declare interface GeminiPreferenceExample { + /** List of completions for a given prompt. */ + completions?: GeminiPreferenceExampleCompletion[]; + /** Multi-turn contents that represents the Prompt. */ + contents?: Content[]; +} + +/** Completion and its preference score. This data type is not supported in Gemini API. */ +export declare interface GeminiPreferenceExampleCompletion { + /** Single turn completion for the given prompt. */ + completion?: Content; + /** The score for the given completion. */ + score?: number; +} + +/** Optional model configuration parameters. + + For more information, see `Content generation parameters + <https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/content-generation-parameters>`_. */ +export declare interface GenerateContentConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** Instructions for the model to steer it toward better performance. + For example, "Answer as concisely as possible" or "Don't use technical + terms in your response". + */ + systemInstruction?: ContentUnion; + /** Value that controls the degree of randomness in token selection. + Lower temperatures are good for prompts that require a less open-ended or + creative response, while higher temperatures can lead to more diverse or + creative results. + */ + temperature?: number; + /** Tokens are selected from the most to least probable until the sum + of their probabilities equals this value. Use a lower value for less + random responses and a higher value for more random responses. + */ + topP?: number; + /** For each token selection step, the ``top_k`` tokens with the + highest probabilities are sampled. Then tokens are further filtered based + on ``top_p`` with the final token selected using temperature sampling. Use + a lower number for less random responses and a higher number for more + random responses. + */ + topK?: number; + /** Number of response variations to return. + */ + candidateCount?: number; + /** Maximum number of tokens that can be generated in the response. + */ + maxOutputTokens?: number; + /** List of strings that tells the model to stop generating text if one + of the strings is encountered in the response. + */ + stopSequences?: string[]; + /** Whether to return the log probabilities of the tokens that were + chosen by the model at each step. + */ + responseLogprobs?: boolean; + /** Number of top candidate tokens to return the log probabilities for + at each generation step. + */ + logprobs?: number; + /** Positive values penalize tokens that already appear in the + generated text, increasing the probability of generating more diverse + content. + */ + presencePenalty?: number; + /** Positive values penalize tokens that repeatedly appear in the + generated text, increasing the probability of generating more diverse + content. + */ + frequencyPenalty?: number; + /** When ``seed`` is fixed to a specific number, the model makes a best + effort to provide the same response for repeated requests. By default, a + random number is used. + */ + seed?: number; + /** Output response mimetype of the generated candidate text. + Supported mimetype: + - `text/plain`: (default) Text output. + - `application/json`: JSON response in the candidates. + The model needs to be prompted to output the appropriate response type, + otherwise the behavior is undefined. + This is a preview feature. + */ + responseMimeType?: string; + /** The `Schema` object allows the definition of input and output data types. + These types can be objects, but also primitives and arrays. + Represents a select subset of an [OpenAPI 3.0 schema + object](https://spec.openapis.org/oas/v3.0.3#schema). + If set, a compatible response_mime_type must also be set. + Compatible mimetypes: `application/json`: Schema for JSON response. + + If `response_schema` doesn't process your schema correctly, try using + `response_json_schema` instead. + */ + responseSchema?: SchemaUnion; + /** Optional. Output schema of the generated response. + This is an alternative to `response_schema` that accepts [JSON + Schema](https://json-schema.org/). If set, `response_schema` must be + omitted, but `response_mime_type` is required. While the full JSON Schema + may be sent, not all features are supported. Specifically, only the + following properties are supported: - `$id` - `$defs` - `$ref` - `$anchor` + - `type` - `format` - `title` - `description` - `enum` (for strings and + numbers) - `items` - `prefixItems` - `minItems` - `maxItems` - `minimum` - + `maximum` - `anyOf` - `oneOf` (interpreted the same as `anyOf`) - + `properties` - `additionalProperties` - `required` The non-standard + `propertyOrdering` property may also be set. Cyclic references are + unrolled to a limited degree and, as such, may only be used within + non-required properties. (Nullable properties are not sufficient.) If + `$ref` is set on a sub-schema, no other properties, except for than those + starting as a `$`, may be set. */ + responseJsonSchema?: unknown; + /** Configuration for model router requests. + */ + routingConfig?: GenerationConfigRoutingConfig; + /** Configuration for model selection. + */ + modelSelectionConfig?: ModelSelectionConfig; + /** Safety settings in the request to block unsafe content in the + response. + */ + safetySettings?: SafetySetting[]; + /** Code that enables the system to interact with external systems to + perform an action outside of the knowledge and scope of the model. + */ + tools?: ToolListUnion; + /** Associates model output to a specific function call. + */ + toolConfig?: ToolConfig; + /** Labels with user-defined metadata to break down billed charges. */ + labels?: Record<string, string>; + /** Resource name of a context cache that can be used in subsequent + requests. + */ + cachedContent?: string; + /** The requested modalities of the response. Represents the set of + modalities that the model can return. + */ + responseModalities?: string[]; + /** If specified, the media resolution specified will be used. + */ + mediaResolution?: MediaResolution; + /** The speech generation configuration. + */ + speechConfig?: SpeechConfigUnion; + /** If enabled, audio timestamp will be included in the request to the + model. + */ + audioTimestamp?: boolean; + /** The configuration for automatic function calling. + */ + automaticFunctionCalling?: AutomaticFunctionCallingConfig; + /** The thinking features configuration. + */ + thinkingConfig?: ThinkingConfig; + /** The image generation configuration. + */ + imageConfig?: ImageConfig; + /** Enables enhanced civic answers. It may not be available for all + models. This field is not supported in Vertex AI. + */ + enableEnhancedCivicAnswers?: boolean; + /** Settings for prompt and response sanitization using the Model Armor + service. If supplied, safety_settings must not be supplied. + */ + modelArmorConfig?: ModelArmorConfig; +} + +/** Config for models.generate_content parameters. */ +export declare interface GenerateContentParameters { + /** ID of the model to use. For a list of models, see `Google models + <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */ + model: string; + /** Content of the request. + */ + contents: ContentListUnion; + /** Configuration that contains optional model parameters. + */ + config?: GenerateContentConfig; +} + +/** Response message for PredictionService.GenerateContent. */ +export declare class GenerateContentResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** Response variations returned by the model. + */ + candidates?: Candidate[]; + /** Timestamp when the request is made to the server. + */ + createTime?: string; + /** The history of automatic function calling. + */ + automaticFunctionCallingHistory?: Content[]; + /** Output only. The model version used to generate the response. */ + modelVersion?: string; + /** Output only. Content filter results for a prompt sent in the request. Note: Sent only in the first stream chunk. Only happens when no candidates were generated due to content violations. */ + promptFeedback?: GenerateContentResponsePromptFeedback; + /** Output only. response_id is used to identify each response. It is the encoding of the event_id. */ + responseId?: string; + /** Usage metadata about the response(s). */ + usageMetadata?: GenerateContentResponseUsageMetadata; + /** + * Returns the concatenation of all text parts from the first candidate in the response. + * + * @remarks + * If there are multiple candidates in the response, the text from the first + * one will be returned. + * If there are non-text parts in the response, the concatenation of all text + * parts will be returned, and a warning will be logged. + * If there are thought parts in the response, the concatenation of all text + * parts excluding the thought parts will be returned. + * + * @example + * ```ts + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: + * 'Why is the sky blue?', + * }); + * + * console.debug(response.text); + * ``` + */ + get text(): string | undefined; + /** + * Returns the concatenation of all inline data parts from the first candidate + * in the response. + * + * @remarks + * If there are multiple candidates in the response, the inline data from the + * first one will be returned. If there are non-inline data parts in the + * response, the concatenation of all inline data parts will be returned, and + * a warning will be logged. + */ + get data(): string | undefined; + /** + * Returns the function calls from the first candidate in the response. + * + * @remarks + * If there are multiple candidates in the response, the function calls from + * the first one will be returned. + * If there are no function calls in the response, undefined will be returned. + * + * @example + * ```ts + * const controlLightFunctionDeclaration: FunctionDeclaration = { + * name: 'controlLight', + * parameters: { + * type: Type.OBJECT, + * description: 'Set the brightness and color temperature of a room light.', + * properties: { + * brightness: { + * type: Type.NUMBER, + * description: + * 'Light level from 0 to 100. Zero is off and 100 is full brightness.', + * }, + * colorTemperature: { + * type: Type.STRING, + * description: + * 'Color temperature of the light fixture which can be `daylight`, `cool` or `warm`.', + * }, + * }, + * required: ['brightness', 'colorTemperature'], + * }; + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: 'Dim the lights so the room feels cozy and warm.', + * config: { + * tools: [{functionDeclarations: [controlLightFunctionDeclaration]}], + * toolConfig: { + * functionCallingConfig: { + * mode: FunctionCallingConfigMode.ANY, + * allowedFunctionNames: ['controlLight'], + * }, + * }, + * }, + * }); + * console.debug(JSON.stringify(response.functionCalls)); + * ``` + */ + get functionCalls(): FunctionCall[] | undefined; + /** + * Returns the first executable code from the first candidate in the response. + * + * @remarks + * If there are multiple candidates in the response, the executable code from + * the first one will be returned. + * If there are no executable code in the response, undefined will be + * returned. + * + * @example + * ```ts + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: + * 'What is the sum of the first 50 prime numbers? Generate and run code for the calculation, and make sure you get all 50.' + * config: { + * tools: [{codeExecution: {}}], + * }, + * }); + * + * console.debug(response.executableCode); + * ``` + */ + get executableCode(): string | undefined; + /** + * Returns the first code execution result from the first candidate in the response. + * + * @remarks + * If there are multiple candidates in the response, the code execution result from + * the first one will be returned. + * If there are no code execution result in the response, undefined will be returned. + * + * @example + * ```ts + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: + * 'What is the sum of the first 50 prime numbers? Generate and run code for the calculation, and make sure you get all 50.' + * config: { + * tools: [{codeExecution: {}}], + * }, + * }); + * + * console.debug(response.codeExecutionResult); + * ``` + */ + get codeExecutionResult(): string | undefined; +} + +/** Content filter results for a prompt sent in the request. Note: This is sent only in the first stream chunk and only if no candidates were generated due to content violations. */ +export declare class GenerateContentResponsePromptFeedback { + /** Output only. The reason why the prompt was blocked. */ + blockReason?: BlockedReason; + /** Output only. A readable message that explains the reason why the prompt was blocked. This field is not supported in Gemini API. */ + blockReasonMessage?: string; + /** Output only. A list of safety ratings for the prompt. There is one rating per category. */ + safetyRatings?: SafetyRating[]; +} + +/** Usage metadata about the content generation request and response. This message provides a detailed breakdown of token usage and other relevant metrics. This data type is not supported in Gemini API. */ +export declare class GenerateContentResponseUsageMetadata { + /** Output only. A detailed breakdown of the token count for each modality in the cached content. */ + cacheTokensDetails?: ModalityTokenCount[]; + /** Output only. The number of tokens in the cached content that was used for this request. */ + cachedContentTokenCount?: number; + /** The total number of tokens in the generated candidates. */ + candidatesTokenCount?: number; + /** Output only. A detailed breakdown of the token count for each modality in the generated candidates. */ + candidatesTokensDetails?: ModalityTokenCount[]; + /** The total number of tokens in the prompt. This includes any text, images, or other media provided in the request. When `cached_content` is set, this also includes the number of tokens in the cached content. */ + promptTokenCount?: number; + /** Output only. A detailed breakdown of the token count for each modality in the prompt. */ + promptTokensDetails?: ModalityTokenCount[]; + /** Output only. The number of tokens that were part of the model's generated "thoughts" output, if applicable. */ + thoughtsTokenCount?: number; + /** Output only. The number of tokens in the results from tool executions, which are provided back to the model as input, if applicable. */ + toolUsePromptTokenCount?: number; + /** Output only. A detailed breakdown by modality of the token counts from the results of tool executions, which are provided back to the model as input. */ + toolUsePromptTokensDetails?: ModalityTokenCount[]; + /** The total number of tokens for the entire request. This is the sum of `prompt_token_count`, `candidates_token_count`, `tool_use_prompt_token_count`, and `thoughts_token_count`. */ + totalTokenCount?: number; + /** Output only. The traffic type for this request. */ + trafficType?: TrafficType; +} + +/** An output image. */ +export declare interface GeneratedImage { + /** The output image data. */ + image?: Image_2; + /** Responsible AI filter reason if the image is filtered out of the + response. */ + raiFilteredReason?: string; + /** Safety attributes of the image. Lists of RAI categories and their + scores of each content. */ + safetyAttributes?: SafetyAttributes; + /** The rewritten prompt used for the image generation if the prompt + enhancer is enabled. */ + enhancedPrompt?: string; +} + +/** A generated image mask. */ +export declare interface GeneratedImageMask { + /** The generated image mask. */ + mask?: Image_2; + /** The detected entities on the segmented area. */ + labels?: EntityLabel[]; +} + +/** A generated video. */ +export declare interface GeneratedVideo { + /** The output video */ + video?: Video; +} + +/** The config for generating an images. */ +export declare interface GenerateImagesConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** Cloud Storage URI used to store the generated images. */ + outputGcsUri?: string; + /** Description of what to discourage in the generated images. */ + negativePrompt?: string; + /** Number of images to generate. */ + numberOfImages?: number; + /** Aspect ratio of the generated images. Supported values are + "1:1", "3:4", "4:3", "9:16", and "16:9". */ + aspectRatio?: string; + /** Controls how much the model adheres to the text prompt. Large + values increase output and prompt alignment, but may compromise image + quality. */ + guidanceScale?: number; + /** Random seed for image generation. This is not available when + ``add_watermark`` is set to true. */ + seed?: number; + /** Filter level for safety filtering. */ + safetyFilterLevel?: SafetyFilterLevel; + /** Allows generation of people by the model. */ + personGeneration?: PersonGeneration; + /** Whether to report the safety scores of each generated image and + the positive prompt in the response. */ + includeSafetyAttributes?: boolean; + /** Whether to include the Responsible AI filter reason if the image + is filtered out of the response. */ + includeRaiReason?: boolean; + /** Language of the text in the prompt. */ + language?: ImagePromptLanguage; + /** MIME type of the generated image. */ + outputMimeType?: string; + /** Compression quality of the generated image (for ``image/jpeg`` + only). */ + outputCompressionQuality?: number; + /** Whether to add a watermark to the generated images. */ + addWatermark?: boolean; + /** User specified labels to track billing usage. */ + labels?: Record<string, string>; + /** The size of the largest dimension of the generated image. + Supported sizes are 1K and 2K (not supported for Imagen 3 models). */ + imageSize?: string; + /** Whether to use the prompt rewriting logic. */ + enhancePrompt?: boolean; +} + +/** The parameters for generating images. */ +export declare interface GenerateImagesParameters { + /** ID of the model to use. For a list of models, see `Google models + <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */ + model: string; + /** Text prompt that typically describes the images to output. + */ + prompt: string; + /** Configuration for generating images. + */ + config?: GenerateImagesConfig; +} + +/** The output images response. */ +export declare class GenerateImagesResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** List of generated images. */ + generatedImages?: GeneratedImage[]; + /** Safety attributes of the positive prompt. Only populated if + ``include_safety_attributes`` is set to True. */ + positivePromptSafetyAttributes?: SafetyAttributes; +} + +/** Configuration for generating videos. */ +export declare interface GenerateVideosConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** Number of output videos. */ + numberOfVideos?: number; + /** The gcs bucket where to save the generated videos. */ + outputGcsUri?: string; + /** Frames per second for video generation. */ + fps?: number; + /** Duration of the clip for video generation in seconds. */ + durationSeconds?: number; + /** The RNG seed. If RNG seed is exactly same for each request with + unchanged inputs, the prediction results will be consistent. Otherwise, + a random RNG seed will be used each time to produce a different + result. */ + seed?: number; + /** The aspect ratio for the generated video. 16:9 (landscape) and + 9:16 (portrait) are supported. */ + aspectRatio?: string; + /** The resolution for the generated video. 720p and 1080p are + supported. */ + resolution?: string; + /** Whether allow to generate person videos, and restrict to specific + ages. Supported values are: dont_allow, allow_adult. */ + personGeneration?: string; + /** The pubsub topic where to publish the video generation + progress. */ + pubsubTopic?: string; + /** Explicitly state what should not be included in the generated + videos. */ + negativePrompt?: string; + /** Whether to use the prompt rewriting logic. */ + enhancePrompt?: boolean; + /** Whether to generate audio along with the video. */ + generateAudio?: boolean; + /** Image to use as the last frame of generated videos. + Only supported for image to video use cases. */ + lastFrame?: Image_2; + /** The images to use as the references to generate the videos. + If this field is provided, the text prompt field must also be provided. + The image, video, or last_frame field are not supported. Each image must + be associated with a type. Veo 2 supports up to 3 asset images *or* 1 + style image. */ + referenceImages?: VideoGenerationReferenceImage[]; + /** The mask to use for generating videos. */ + mask?: VideoGenerationMask; + /** Compression quality of the generated videos. */ + compressionQuality?: VideoCompressionQuality; +} + +/** A video generation operation. */ +export declare class GenerateVideosOperation implements Operation<GenerateVideosResponse> { + /** The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`. */ + name?: string; + /** Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata. Any method that returns a long-running operation should document the metadata type, if any. */ + metadata?: Record<string, unknown>; + /** If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available. */ + done?: boolean; + /** The error result of the operation in case of failure or cancellation. */ + error?: Record<string, unknown>; + /** The generated videos. */ + response?: GenerateVideosResponse; + /** + * Instantiates an Operation of the same type as the one being called with the fields set from the API response. + * @internal + */ + _fromAPIResponse({ apiResponse, _isVertexAI, }: OperationFromAPIResponseParameters): Operation<GenerateVideosResponse>; + /** The full HTTP response. */ + sdkHttpResponse?: HttpResponse; +} + +/** Class that represents the parameters for generating videos. */ +export declare interface GenerateVideosParameters { + /** ID of the model to use. For a list of models, see `Google models + <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */ + model: string; + /** The text prompt for generating the videos. + Optional if image or video is provided. */ + prompt?: string; + /** The input image for generating the videos. + Optional if prompt is provided. Not allowed if video is provided. */ + image?: Image_2; + /** The input video for video extension use cases. + Optional if prompt is provided. Not allowed if image is provided. */ + video?: Video; + /** A set of source input(s) for video generation. */ + source?: GenerateVideosSource; + /** Configuration for generating videos. */ + config?: GenerateVideosConfig; +} + +/** Response with generated videos. */ +export declare class GenerateVideosResponse { + /** List of the generated videos */ + generatedVideos?: GeneratedVideo[]; + /** Returns if any videos were filtered due to RAI policies. */ + raiMediaFilteredCount?: number; + /** Returns rai failure reasons if any. */ + raiMediaFilteredReasons?: string[]; +} + +/** A set of source input(s) for video generation. */ +export declare interface GenerateVideosSource { + /** The text prompt for generating the videos. + Optional if image or video is provided. */ + prompt?: string; + /** The input image for generating the videos. + Optional if prompt is provided. Not allowed if video is provided. */ + image?: Image_2; + /** The input video for video extension use cases. + Optional if prompt is provided. Not allowed if image is provided. */ + video?: Video; +} + +/** Generation config. */ +export declare interface GenerationConfig { + /** Optional. Config for model selection. */ + modelSelectionConfig?: ModelSelectionConfig; + /** Output schema of the generated response. This is an alternative to + `response_schema` that accepts [JSON Schema](https://json-schema.org/). + */ + responseJsonSchema?: unknown; + /** Optional. If enabled, audio timestamp will be included in the request to the model. This field is not supported in Gemini API. */ + audioTimestamp?: boolean; + /** Optional. Number of candidates to generate. */ + candidateCount?: number; + /** Optional. If enabled, the model will detect emotions and adapt its responses accordingly. This field is not supported in Gemini API. */ + enableAffectiveDialog?: boolean; + /** Optional. Frequency penalties. */ + frequencyPenalty?: number; + /** Optional. Logit probabilities. */ + logprobs?: number; + /** Optional. The maximum number of output tokens to generate per message. */ + maxOutputTokens?: number; + /** Optional. If specified, the media resolution specified will be used. */ + mediaResolution?: MediaResolution; + /** Optional. Positive penalties. */ + presencePenalty?: number; + /** Optional. If true, export the logprobs results in response. */ + responseLogprobs?: boolean; + /** Optional. Output response mimetype of the generated candidate text. Supported mimetype: - `text/plain`: (default) Text output. - `application/json`: JSON response in the candidates. The model needs to be prompted to output the appropriate response type, otherwise the behavior is undefined. This is a preview feature. */ + responseMimeType?: string; + /** Optional. The modalities of the response. */ + responseModalities?: Modality[]; + /** Optional. The `Schema` object allows the definition of input and output data types. These types can be objects, but also primitives and arrays. Represents a select subset of an [OpenAPI 3.0 schema object](https://spec.openapis.org/oas/v3.0.3#schema). If set, a compatible response_mime_type must also be set. Compatible mimetypes: `application/json`: Schema for JSON response. */ + responseSchema?: Schema; + /** Optional. Routing configuration. This field is not supported in Gemini API. */ + routingConfig?: GenerationConfigRoutingConfig; + /** Optional. Seed. */ + seed?: number; + /** Optional. The speech generation config. */ + speechConfig?: SpeechConfig; + /** Optional. Stop sequences. */ + stopSequences?: string[]; + /** Optional. Controls the randomness of predictions. */ + temperature?: number; + /** Optional. Config for thinking features. An error will be returned if this field is set for models that don't support thinking. */ + thinkingConfig?: ThinkingConfig; + /** Optional. If specified, top-k sampling will be used. */ + topK?: number; + /** Optional. If specified, nucleus sampling will be used. */ + topP?: number; + /** Optional. Enables enhanced civic answers. It may not be available for all models. This field is not supported in Vertex AI. */ + enableEnhancedCivicAnswers?: boolean; +} + +/** + * Configuration parameters for model interactions. + */ +declare interface GenerationConfig_2 { + /** + * Configuration for image interaction. + */ + image_config?: ImageConfig_2; + /** + * The maximum number of tokens to include in the response. + */ + max_output_tokens?: number; + /** + * Seed used in decoding for reproducibility. + */ + seed?: number; + /** + * Configuration for speech interaction. + */ + speech_config?: Array<SpeechConfig_2>; + /** + * A list of character sequences that will stop output interaction. + */ + stop_sequences?: Array<string>; + /** + * Controls the randomness of the output. + */ + temperature?: number; + /** + * The level of thought tokens that the model should generate. + */ + thinking_level?: ThinkingLevel_2; + /** + * Whether to include thought summaries in the response. + */ + thinking_summaries?: 'auto' | 'none'; + /** + * The tool choice for the interaction. + */ + tool_choice?: ToolChoice; + /** + * The maximum cumulative probability of tokens to consider when sampling. + */ + top_p?: number; +} + +/** The configuration for routing the request to a specific model. This data type is not supported in Gemini API. */ +export declare interface GenerationConfigRoutingConfig { + /** Automated routing. */ + autoMode?: GenerationConfigRoutingConfigAutoRoutingMode; + /** Manual routing. */ + manualMode?: GenerationConfigRoutingConfigManualRoutingMode; +} + +/** When automated routing is specified, the routing will be determined by the pretrained routing model and customer provided model routing preference. This data type is not supported in Gemini API. */ +export declare interface GenerationConfigRoutingConfigAutoRoutingMode { + /** The model routing preference. */ + modelRoutingPreference?: 'UNKNOWN' | 'PRIORITIZE_QUALITY' | 'BALANCED' | 'PRIORITIZE_COST'; +} + +/** When manual routing is set, the specified model will be used directly. This data type is not supported in Gemini API. */ +export declare interface GenerationConfigRoutingConfigManualRoutingMode { + /** The model name to use. Only the public LLM models are accepted. See [Supported models](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference#supported-models). */ + modelName?: string; +} + +/** + * Config for thinking feature. + * + * @deprecated This interface will be deprecated. Please use `ThinkingConfig` instead. + */ +export declare interface GenerationConfigThinkingConfig extends ThinkingConfig { +} + +/** Optional parameters. */ +export declare interface GetBatchJobConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Config for batches.get parameters. */ +export declare interface GetBatchJobParameters { + /** A fully-qualified BatchJob resource name or ID. + Example: "projects/.../locations/.../batchPredictionJobs/456" + or "456" when project and location are initialized in the client. + */ + name: string; + /** Optional parameters for the request. */ + config?: GetBatchJobConfig; +} + +/** Optional parameters for caches.get method. */ +export declare interface GetCachedContentConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Parameters for caches.get method. */ +export declare interface GetCachedContentParameters { + /** The server-generated resource name of the cached content. + */ + name: string; + /** Optional parameters for the request. + */ + config?: GetCachedContentConfig; +} + +/** Optional Config. */ +export declare interface GetDocumentConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Parameters for documents.get. */ +export declare interface GetDocumentParameters { + /** The resource name of the Document. + Example: fileSearchStores/file-search-store-foo/documents/documents-bar */ + name: string; + /** Optional parameters for the request. */ + config?: GetDocumentConfig; +} + +/** Used to override the default configuration. */ +export declare interface GetFileConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Generates the parameters for the get method. */ +export declare interface GetFileParameters { + /** The name identifier for the file to retrieve. */ + name: string; + /** Used to override the default configuration. */ + config?: GetFileConfig; +} + +/** Optional parameters for getting a FileSearchStore. */ +export declare interface GetFileSearchStoreConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Config for file_search_stores.get parameters. */ +export declare interface GetFileSearchStoreParameters { + /** The resource name of the FileSearchStore. Example: `fileSearchStores/my-file-search-store-123` */ + name: string; + /** Optional parameters for the request. */ + config?: GetFileSearchStoreConfig; +} + +/** Optional parameters for models.get method. */ +export declare interface GetModelConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +export declare interface GetModelParameters { + model: string; + /** Optional parameters for the request. */ + config?: GetModelConfig; +} + +export declare interface GetOperationConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Parameters for the GET method. */ +export declare interface GetOperationParameters { + /** The server-assigned name for the operation. */ + operationName: string; + /** Used to override the default configuration. */ + config?: GetOperationConfig; +} + +/** Optional parameters for tunings.get method. */ +export declare interface GetTuningJobConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Parameters for the get method. */ +export declare interface GetTuningJobParameters { + name: string; + /** Optional parameters for the request. */ + config?: GetTuningJobConfig; +} + +/** + * The Google GenAI SDK. + * + * @remarks + * Provides access to the GenAI features through either the {@link https://cloud.google.com/vertex-ai/docs/reference/rest | Gemini API} + * or the {@link https://cloud.google.com/vertex-ai/docs/reference/rest | Vertex AI API}. + * + * The {@link GoogleGenAIOptions.vertexai} value determines which of the API services to use. + * + * When using the Gemini API, a {@link GoogleGenAIOptions.apiKey} must also be set, + * when using Vertex AI {@link GoogleGenAIOptions.project} and {@link GoogleGenAIOptions.location} must also be set. + * + * @example + * Initializing the SDK for using the Gemini API: + * ```ts + * import {GoogleGenAI} from '@google/genai'; + * const ai = new GoogleGenAI({apiKey: 'GEMINI_API_KEY'}); + * ``` + * + * @example + * Initializing the SDK for using the Vertex AI API: + * ```ts + * import {GoogleGenAI} from '@google/genai'; + * const ai = new GoogleGenAI({ + * vertexai: true, + * project: 'PROJECT_ID', + * location: 'PROJECT_LOCATION' + * }); + * ``` + * + */ +export declare class GoogleGenAI { + protected readonly apiClient: ApiClient; + private readonly apiKey?; + readonly vertexai: boolean; + private readonly apiVersion?; + private readonly httpOptions?; + readonly models: Models; + readonly live: Live; + readonly batches: Batches; + readonly chats: Chats; + readonly caches: Caches; + readonly files: Files; + readonly operations: Operations; + readonly authTokens: Tokens; + readonly tunings: Tunings; + readonly fileSearchStores: FileSearchStores; + private _interactions; + get interactions(): Interactions; + constructor(options: GoogleGenAIOptions); +} + +/** + * Google Gen AI SDK's configuration options. + * + * See {@link GoogleGenAI} for usage samples. + */ +export declare interface GoogleGenAIOptions { + /** + * Optional. Determines whether to use the Vertex AI or the Gemini API. + * + * @remarks + * When true, the {@link https://cloud.google.com/vertex-ai/docs/reference/rest | Vertex AI API} will used. + * When false, the {@link https://ai.google.dev/api | Gemini API} will be used. + * + * If unset, default SDK behavior is to use the Gemini API service. + */ + vertexai?: boolean; + /** + * Optional. The Google Cloud project ID for Vertex AI clients. + * + * Find your project ID: https://cloud.google.com/resource-manager/docs/creating-managing-projects#identifying_projects + * + * @remarks + * Only supported on Node runtimes, ignored on browser runtimes. + */ + project?: string; + /** + * Optional. The Google Cloud project {@link https://cloud.google.com/vertex-ai/generative-ai/docs/learn/locations | location} for Vertex AI clients. + * + * @remarks + * Only supported on Node runtimes, ignored on browser runtimes. + * + */ + location?: string; + /** + * The API Key, required for Gemini API clients. + * + * @remarks + * Required on browser runtimes. + */ + apiKey?: string; + /** + * Optional. The API version to use. + * + * @remarks + * If unset, the default API version will be used. + */ + apiVersion?: string; + /** + * Optional. Authentication options defined by the by google-auth-library for Vertex AI clients. + * + * @remarks + * @see {@link https://github.com/googleapis/google-auth-library-nodejs/blob/v9.15.0/src/auth/googleauth.ts | GoogleAuthOptions interface in google-auth-library-nodejs}. + * + * Only supported on Node runtimes, ignored on browser runtimes. + * + */ + googleAuthOptions?: GoogleAuthOptions; + /** + * Optional. A set of customizable configuration for HTTP requests. + */ + httpOptions?: HttpOptions; +} + +/** Tool to retrieve public maps data for grounding, powered by Google. */ +export declare interface GoogleMaps { + /** The authentication config to access the API. Only API key is supported. This field is not supported in Gemini API. */ + authConfig?: AuthConfig; + /** Optional. If true, include the widget context token in the response. */ + enableWidget?: boolean; +} + +/** The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors). This data type is not supported in Gemini API. */ +export declare interface GoogleRpcStatus { + /** The status code, which should be an enum value of google.rpc.Code. */ + code?: number; + /** A list of messages that carry the error details. There is a common set of message types for APIs to use. */ + details?: Record<string, unknown>[]; + /** A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the google.rpc.Status.details field, or localized by the client. */ + message?: string; +} + +/** GoogleSearch tool type. Tool to support Google Search in Model. Powered by Google. */ +export declare interface GoogleSearch { + /** Optional. List of domains to be excluded from the search results. The default limit is 2000 domains. Example: ["amazon.com", "facebook.com"]. This field is not supported in Gemini API. */ + excludeDomains?: string[]; + /** Optional. Sites with confidence level chosen & above this value will be blocked from the search results. This field is not supported in Gemini API. */ + blockingConfidence?: PhishBlockThreshold; + /** Optional. Filter search results to a specific time range. If customers set a start time, they must set an end time (and vice versa). This field is not supported in Vertex AI. */ + timeRangeFilter?: Interval; +} + +/** + * The arguments to pass to Google Search. + */ +declare interface GoogleSearchCallArguments { + /** + * Web search queries for the following-up web search. + */ + queries?: Array<string>; +} + +/** + * Google Search content. + */ +declare interface GoogleSearchCallContent { + type: 'google_search_call'; + /** + * A unique ID for this specific tool call. + */ + id?: string; + /** + * The arguments to pass to Google Search. + */ + arguments?: GoogleSearchCallArguments; +} + +/** + * The result of the Google Search. + */ +declare interface GoogleSearchResult { + /** + * Web content snippet that can be embedded in a web page or an app webview. + */ + rendered_content?: string; + /** + * Title of the search result. + */ + title?: string; + /** + * URI reference of the search result. + */ + url?: string; +} + +/** + * Google Search result content. + */ +declare interface GoogleSearchResultContent { + type: 'google_search_result'; + /** + * ID to match the ID from the google search call block. + */ + call_id?: string; + /** + * Whether the Google Search resulted in an error. + */ + is_error?: boolean; + /** + * The results of the Google Search. + */ + result?: Array<GoogleSearchResult>; + /** + * The signature of the Google Search result. + */ + signature?: string; +} + +/** Tool to retrieve public web data for grounding, powered by Google. */ +export declare interface GoogleSearchRetrieval { + /** Specifies the dynamic retrieval configuration for the given source. */ + dynamicRetrievalConfig?: DynamicRetrievalConfig; +} + +/** Represents a whole or partial calendar date, such as a birthday. The time of day and time zone are either specified elsewhere or are insignificant. The date is relative to the Gregorian Calendar. This can represent one of the following: * A full date, with non-zero year, month, and day values. * A month and day, with a zero year (for example, an anniversary). * A year on its own, with a zero month and a zero day. * A year and month, with a zero day (for example, a credit card expiration date). Related types: * google.type.TimeOfDay * google.type.DateTime * google.protobuf.Timestamp. This data type is not supported in Gemini API. */ +export declare interface GoogleTypeDate { + /** Day of a month. Must be from 1 to 31 and valid for the year and month, or 0 to specify a year by itself or a year and month where the day isn't significant. */ + day?: number; + /** Month of a year. Must be from 1 to 12, or 0 to specify a year without a month and day. */ + month?: number; + /** Year of the date. Must be from 1 to 9999, or 0 to specify a date without a year. */ + year?: number; +} + +/** Grounding chunk. */ +export declare interface GroundingChunk { + /** Grounding chunk from Google Maps. This field is not supported in Gemini API. */ + maps?: GroundingChunkMaps; + /** Grounding chunk from context retrieved by the retrieval tools. This field is not supported in Gemini API. */ + retrievedContext?: GroundingChunkRetrievedContext; + /** Grounding chunk from the web. */ + web?: GroundingChunkWeb; +} + +/** Chunk from Google Maps. This data type is not supported in Gemini API. */ +export declare interface GroundingChunkMaps { + /** Sources used to generate the place answer. This includes review snippets and photos that were used to generate the answer, as well as uris to flag content. */ + placeAnswerSources?: GroundingChunkMapsPlaceAnswerSources; + /** This Place's resource name, in `places/{place_id}` format. Can be used to look up the Place. */ + placeId?: string; + /** Text of the place answer. */ + text?: string; + /** Title of the place. */ + title?: string; + /** URI reference of the place. */ + uri?: string; +} + +/** Sources used to generate the place answer. This data type is not supported in Gemini API. */ +export declare interface GroundingChunkMapsPlaceAnswerSources { + /** A link where users can flag a problem with the generated answer. */ + flagContentUri?: string; + /** Snippets of reviews that are used to generate the answer. */ + reviewSnippets?: GroundingChunkMapsPlaceAnswerSourcesReviewSnippet[]; +} + +/** Author attribution for a photo or review. This data type is not supported in Gemini API. */ +export declare interface GroundingChunkMapsPlaceAnswerSourcesAuthorAttribution { + /** Name of the author of the Photo or Review. */ + displayName?: string; + /** Profile photo URI of the author of the Photo or Review. */ + photoUri?: string; + /** URI of the author of the Photo or Review. */ + uri?: string; +} + +/** Encapsulates a review snippet. This data type is not supported in Gemini API. */ +export declare interface GroundingChunkMapsPlaceAnswerSourcesReviewSnippet { + /** This review's author. */ + authorAttribution?: GroundingChunkMapsPlaceAnswerSourcesAuthorAttribution; + /** A link where users can flag a problem with the review. */ + flagContentUri?: string; + /** A link to show the review on Google Maps. */ + googleMapsUri?: string; + /** A string of formatted recent time, expressing the review time relative to the current time in a form appropriate for the language and country. */ + relativePublishTimeDescription?: string; + /** A reference representing this place review which may be used to look up this place review again. */ + review?: string; + /** Id of the review referencing the place. */ + reviewId?: string; + /** Title of the review. */ + title?: string; +} + +/** Chunk from context retrieved by the retrieval tools. This data type is not supported in Gemini API. */ +export declare interface GroundingChunkRetrievedContext { + /** Output only. The full document name for the referenced Vertex AI Search document. */ + documentName?: string; + /** Additional context for the RAG retrieval result. This is only populated when using the RAG retrieval tool. */ + ragChunk?: RagChunk; + /** Text of the attribution. */ + text?: string; + /** Title of the attribution. */ + title?: string; + /** URI reference of the attribution. */ + uri?: string; +} + +/** Chunk from the web. */ +export declare interface GroundingChunkWeb { + /** Domain of the (original) URI. This field is not supported in Gemini API. */ + domain?: string; + /** Title of the chunk. */ + title?: string; + /** URI reference of the chunk. */ + uri?: string; +} + +/** Metadata returned to client when grounding is enabled. */ +export declare interface GroundingMetadata { + /** Optional. Output only. Resource name of the Google Maps widget context token to be used with the PlacesContextElement widget to render contextual data. This is populated only for Google Maps grounding. This field is not supported in Gemini API. */ + googleMapsWidgetContextToken?: string; + /** List of supporting references retrieved from specified grounding source. */ + groundingChunks?: GroundingChunk[]; + /** Optional. List of grounding support. */ + groundingSupports?: GroundingSupport[]; + /** Optional. Output only. Retrieval metadata. */ + retrievalMetadata?: RetrievalMetadata; + /** Optional. Queries executed by the retrieval tools. This field is not supported in Gemini API. */ + retrievalQueries?: string[]; + /** Optional. Google search entry for the following-up web searches. */ + searchEntryPoint?: SearchEntryPoint; + /** Optional. Output only. List of source flagging uris. This is currently populated only for Google Maps grounding. This field is not supported in Gemini API. */ + sourceFlaggingUris?: GroundingMetadataSourceFlaggingUri[]; + /** Optional. Web search queries for the following-up web search. */ + webSearchQueries?: string[]; +} + +/** Source content flagging uri for a place or review. This is currently populated only for Google Maps grounding. This data type is not supported in Gemini API. */ +export declare interface GroundingMetadataSourceFlaggingUri { + /** A link where users can flag a problem with the source (place or review). */ + flagContentUri?: string; + /** Id of the place or review. */ + sourceId?: string; +} + +/** Grounding support. */ +export declare interface GroundingSupport { + /** Confidence score of the support references. Ranges from 0 to 1. 1 is the most confident. For Gemini 2.0 and before, this list must have the same size as the grounding_chunk_indices. For Gemini 2.5 and after, this list will be empty and should be ignored. */ + confidenceScores?: number[]; + /** A list of indices (into 'grounding_chunk') specifying the citations associated with the claim. For instance [1,3,4] means that grounding_chunk[1], grounding_chunk[3], grounding_chunk[4] are the retrieved content attributed to the claim. */ + groundingChunkIndices?: number[]; + /** Segment of the content this support belongs to. */ + segment?: Segment; +} + +/** Specify if the threshold is used for probability or severity score. If not specified, the threshold is used for probability score. This enum is not supported in Gemini API. */ +export declare enum HarmBlockMethod { + /** + * The harm block method is unspecified. + */ + HARM_BLOCK_METHOD_UNSPECIFIED = "HARM_BLOCK_METHOD_UNSPECIFIED", + /** + * The harm block method uses both probability and severity scores. + */ + SEVERITY = "SEVERITY", + /** + * The harm block method uses the probability score. + */ + PROBABILITY = "PROBABILITY" +} + +/** The harm block threshold. */ +export declare enum HarmBlockThreshold { + /** + * Unspecified harm block threshold. + */ + HARM_BLOCK_THRESHOLD_UNSPECIFIED = "HARM_BLOCK_THRESHOLD_UNSPECIFIED", + /** + * Block low threshold and above (i.e. block more). + */ + BLOCK_LOW_AND_ABOVE = "BLOCK_LOW_AND_ABOVE", + /** + * Block medium threshold and above. + */ + BLOCK_MEDIUM_AND_ABOVE = "BLOCK_MEDIUM_AND_ABOVE", + /** + * Block only high threshold (i.e. block less). + */ + BLOCK_ONLY_HIGH = "BLOCK_ONLY_HIGH", + /** + * Block none. + */ + BLOCK_NONE = "BLOCK_NONE", + /** + * Turn off the safety filter. + */ + OFF = "OFF" +} + +/** Harm category. */ +export declare enum HarmCategory { + /** + * The harm category is unspecified. + */ + HARM_CATEGORY_UNSPECIFIED = "HARM_CATEGORY_UNSPECIFIED", + /** + * The harm category is harassment. + */ + HARM_CATEGORY_HARASSMENT = "HARM_CATEGORY_HARASSMENT", + /** + * The harm category is hate speech. + */ + HARM_CATEGORY_HATE_SPEECH = "HARM_CATEGORY_HATE_SPEECH", + /** + * The harm category is sexually explicit content. + */ + HARM_CATEGORY_SEXUALLY_EXPLICIT = "HARM_CATEGORY_SEXUALLY_EXPLICIT", + /** + * The harm category is dangerous content. + */ + HARM_CATEGORY_DANGEROUS_CONTENT = "HARM_CATEGORY_DANGEROUS_CONTENT", + /** + * Deprecated: Election filter is not longer supported. The harm category is civic integrity. + */ + HARM_CATEGORY_CIVIC_INTEGRITY = "HARM_CATEGORY_CIVIC_INTEGRITY", + /** + * The harm category is image hate. This enum value is not supported in Gemini API. + */ + HARM_CATEGORY_IMAGE_HATE = "HARM_CATEGORY_IMAGE_HATE", + /** + * The harm category is image dangerous content. This enum value is not supported in Gemini API. + */ + HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT = "HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT", + /** + * The harm category is image harassment. This enum value is not supported in Gemini API. + */ + HARM_CATEGORY_IMAGE_HARASSMENT = "HARM_CATEGORY_IMAGE_HARASSMENT", + /** + * The harm category is image sexually explicit content. This enum value is not supported in Gemini API. + */ + HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT = "HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT", + /** + * The harm category is for jailbreak prompts. This enum value is not supported in Gemini API. + */ + HARM_CATEGORY_JAILBREAK = "HARM_CATEGORY_JAILBREAK" +} + +/** Output only. Harm probability levels in the content. */ +export declare enum HarmProbability { + /** + * Harm probability unspecified. + */ + HARM_PROBABILITY_UNSPECIFIED = "HARM_PROBABILITY_UNSPECIFIED", + /** + * Negligible level of harm. + */ + NEGLIGIBLE = "NEGLIGIBLE", + /** + * Low level of harm. + */ + LOW = "LOW", + /** + * Medium level of harm. + */ + MEDIUM = "MEDIUM", + /** + * High level of harm. + */ + HIGH = "HIGH" +} + +/** Output only. Harm severity levels in the content. This enum is not supported in Gemini API. */ +export declare enum HarmSeverity { + /** + * Harm severity unspecified. + */ + HARM_SEVERITY_UNSPECIFIED = "HARM_SEVERITY_UNSPECIFIED", + /** + * Negligible level of harm severity. + */ + HARM_SEVERITY_NEGLIGIBLE = "HARM_SEVERITY_NEGLIGIBLE", + /** + * Low level of harm severity. + */ + HARM_SEVERITY_LOW = "HARM_SEVERITY_LOW", + /** + * Medium level of harm severity. + */ + HARM_SEVERITY_MEDIUM = "HARM_SEVERITY_MEDIUM", + /** + * High level of harm severity. + */ + HARM_SEVERITY_HIGH = "HARM_SEVERITY_HIGH" +} + +declare type HeadersLike = Headers | readonly HeaderValue[][] | Record<string, HeaderValue | readonly HeaderValue[]> | undefined | null | NullableHeaders; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +declare type HeaderValue = string | undefined | null; + +/** The location of the API key. This enum is not supported in Gemini API. */ +export declare enum HttpElementLocation { + HTTP_IN_UNSPECIFIED = "HTTP_IN_UNSPECIFIED", + /** + * Element is in the HTTP request query. + */ + HTTP_IN_QUERY = "HTTP_IN_QUERY", + /** + * Element is in the HTTP request header. + */ + HTTP_IN_HEADER = "HTTP_IN_HEADER", + /** + * Element is in the HTTP request path. + */ + HTTP_IN_PATH = "HTTP_IN_PATH", + /** + * Element is in the HTTP request body. + */ + HTTP_IN_BODY = "HTTP_IN_BODY", + /** + * Element is in the HTTP request cookie. + */ + HTTP_IN_COOKIE = "HTTP_IN_COOKIE" +} + +declare type HTTPMethod = 'get' | 'post' | 'put' | 'patch' | 'delete'; + +/** HTTP options to be used in each of the requests. */ +export declare interface HttpOptions { + /** The base URL for the AI platform service endpoint. */ + baseUrl?: string; + /** The resource scope used to constructing the resource name when base_url is set */ + baseUrlResourceScope?: ResourceScope; + /** Specifies the version of the API to use. */ + apiVersion?: string; + /** Additional HTTP headers to be sent with the request. */ + headers?: Record<string, string>; + /** Timeout for the request in milliseconds. */ + timeout?: number; + /** Extra parameters to add to the request body. + The structure must match the backend API's request structure. + - VertexAI backend API docs: https://cloud.google.com/vertex-ai/docs/reference/rest + - GeminiAPI backend API docs: https://ai.google.dev/api/rest */ + extraBody?: Record<string, unknown>; + /** HTTP retry options for the request. */ + retryOptions?: HttpRetryOptions; +} + +/** + * Represents the necessary information to send a request to an API endpoint. + * This interface defines the structure for constructing and executing HTTP + * requests. + */ +declare interface HttpRequest { + /** + * URL path from the modules, this path is appended to the base API URL to + * form the complete request URL. + * + * If you wish to set full URL, use httpOptions.baseUrl instead. Example to + * set full URL in the request: + * + * const request: HttpRequest = { + * path: '', + * httpOptions: { + * baseUrl: 'https://<custom-full-url>', + * apiVersion: '', + * }, + * httpMethod: 'GET', + * }; + * + * The result URL will be: https://<custom-full-url> + * + */ + path: string; + /** + * Optional query parameters to be appended to the request URL. + */ + queryParams?: Record<string, string>; + /** + * Optional request body in json string or Blob format, GET request doesn't + * need a request body. + */ + body?: string | Blob; + /** + * The HTTP method to be used for the request. + */ + httpMethod: 'GET' | 'POST' | 'PATCH' | 'DELETE'; + /** + * Optional set of customizable configuration for HTTP requests. + */ + httpOptions?: types.HttpOptions; + /** + * Optional abort signal which can be used to cancel the request. + */ + abortSignal?: AbortSignal; +} + +/** A wrapper class for the http response. */ +export declare class HttpResponse { + /** Used to retain the processed HTTP headers in the response. */ + headers?: Record<string, string>; + /** + * The original http response. + */ + responseInternal: Response; + constructor(response: Response); + json(): Promise<unknown>; +} + +/** HTTP retry options to be used in each of the requests. */ +export declare interface HttpRetryOptions { + /** Maximum number of attempts, including the original request. + If 0 or 1, it means no retries. If not specified, default to 5. */ + attempts?: number; +} + +/** An image. */ +declare interface Image_2 { + /** The Cloud Storage URI of the image. ``Image`` can contain a value + for this field or the ``image_bytes`` field but not both. */ + gcsUri?: string; + /** The image bytes data. ``Image`` can contain a value for this field + or the ``gcs_uri`` field but not both. + * @remarks Encoded as base64 string. */ + imageBytes?: string; + /** The MIME type of the image. */ + mimeType?: string; +} +export { Image_2 as Image } + +/** The image generation configuration to be used in GenerateContentConfig. */ +export declare interface ImageConfig { + /** Aspect ratio of the generated images. Supported values are + "1:1", "2:3", "3:2", "3:4", "4:3", "9:16", "16:9", and "21:9". */ + aspectRatio?: string; + /** Optional. Specifies the size of generated images. Supported + values are `1K`, `2K`, `4K`. If not specified, the model will use default + value `1K`. */ + imageSize?: string; + /** Controls the generation of people. Supported values are: + ALLOW_ALL, ALLOW_ADULT, ALLOW_NONE. */ + personGeneration?: string; + /** MIME type of the generated image. This field is not + supported in Gemini API. */ + outputMimeType?: string; + /** Compression quality of the generated image (for + ``image/jpeg`` only). This field is not supported in Gemini API. */ + outputCompressionQuality?: number; +} + +/** + * The configuration for image interaction. + */ +declare interface ImageConfig_2 { + aspect_ratio?: '1:1' | '2:3' | '3:2' | '3:4' | '4:3' | '4:5' | '5:4' | '9:16' | '16:9' | '21:9'; + image_size?: '1K' | '2K' | '4K'; +} + +/** + * An image content block. + */ +declare interface ImageContent { + type: 'image'; + /** + * The image content. + */ + data?: string; + /** + * The mime type of the image. + */ + mime_type?: ImageMimeType; + /** + * The resolution of the media. + */ + resolution?: 'low' | 'medium' | 'high' | 'ultra_high'; + /** + * The URI of the image. + */ + uri?: string; +} + +/** + * The mime type of the image. + */ +declare type ImageMimeType = 'image/png' | 'image/jpeg' | 'image/webp' | 'image/heic' | 'image/heif' | (string & {}); + +/** Enum that specifies the language of the text in the prompt. */ +export declare enum ImagePromptLanguage { + /** + * Auto-detect the language. + */ + auto = "auto", + /** + * English + */ + en = "en", + /** + * Japanese + */ + ja = "ja", + /** + * Korean + */ + ko = "ko", + /** + * Hindi + */ + hi = "hi", + /** + * Chinese + */ + zh = "zh", + /** + * Portuguese + */ + pt = "pt", + /** + * Spanish + */ + es = "es" +} + +/** Optional parameters for importing a file. */ +export declare interface ImportFileConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** User provided custom metadata stored as key-value pairs used for querying. */ + customMetadata?: CustomMetadata[]; + /** Config for telling the service how to chunk the file. */ + chunkingConfig?: ChunkingConfig; +} + +/** Long-running operation for importing a file to a FileSearchStore. */ +export declare class ImportFileOperation implements Operation<ImportFileResponse> { + /** The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`. */ + name?: string; + /** Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata. Any method that returns a long-running operation should document the metadata type, if any. */ + metadata?: Record<string, unknown>; + /** If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available. */ + done?: boolean; + /** The error result of the operation in case of failure or cancellation. */ + error?: Record<string, unknown>; + /** The result of the ImportFile operation, available when the operation is done. */ + response?: ImportFileResponse; + /** + * Instantiates an Operation of the same type as the one being called with the fields set from the API response. + * @internal + */ + _fromAPIResponse({ apiResponse, _isVertexAI, }: OperationFromAPIResponseParameters): Operation<ImportFileResponse>; + /** The full HTTP response. */ + sdkHttpResponse?: HttpResponse; +} + +/** Config for file_search_stores.import_file parameters. */ +export declare interface ImportFileParameters { + /** The resource name of the FileSearchStore. Example: `fileSearchStores/my-file-search-store-123` */ + fileSearchStoreName: string; + /** The name of the File API File to import. Example: `files/abc-123` */ + fileName: string; + /** Optional parameters for the request. */ + config?: ImportFileConfig; +} + +/** Response for ImportFile to import a File API file with a file search store. */ +export declare class ImportFileResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** The name of the FileSearchStore containing Documents. */ + parent?: string; + /** The identifier for the Document imported. */ + documentName?: string; +} + +/** Config for `inlined_embedding_responses` parameter. */ +export declare class InlinedEmbedContentResponse { + /** The response to the request. + */ + response?: SingleEmbedContentResponse; + /** The error encountered while processing the request. + */ + error?: JobError; +} + +/** Config for inlined request. */ +export declare interface InlinedRequest { + /** ID of the model to use. For a list of models, see `Google models + <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */ + model?: string; + /** Content of the request. + */ + contents?: ContentListUnion; + /** The metadata to be associated with the request. */ + metadata?: Record<string, string>; + /** Configuration that contains optional model parameters. + */ + config?: GenerateContentConfig; +} + +/** Config for `inlined_responses` parameter. */ +export declare class InlinedResponse { + /** The response to the request. + */ + response?: GenerateContentResponse; + /** The metadata to be associated with the request. */ + metadata?: Record<string, string>; + /** The error encountered while processing the request. + */ + error?: JobError; +} + +/** + * The Interaction resource. + */ +declare interface Interaction { + /** + * Output only. A unique identifier for the interaction completion. + */ + id: string; + /** + * Output only. The status of the interaction. + */ + status: 'in_progress' | 'requires_action' | 'completed' | 'failed' | 'cancelled' | 'incomplete'; + /** + * The name of the `Agent` used for generating the interaction. + */ + agent?: (string & {}) | 'deep-research-pro-preview-12-2025'; + /** + * Output only. The time at which the response was created in ISO 8601 format + * (YYYY-MM-DDThh:mm:ssZ). + */ + created?: string; + /** + * The name of the `Model` used for generating the interaction. + */ + model?: Model_2; + /** + * Output only. Responses from the model. + */ + outputs?: Array<Content_2>; + /** + * The ID of the previous interaction, if any. + */ + previous_interaction_id?: string; + /** + * Output only. The role of the interaction. + */ + role?: string; + /** + * Output only. The time at which the response was last updated in ISO 8601 format + * (YYYY-MM-DDThh:mm:ssZ). + */ + updated?: string; + /** + * Output only. Statistics on the interaction request's token usage. + */ + usage?: Usage; +} + +declare interface InteractionCancelParams { + /** + * Which version of the API to use. + */ + api_version?: string; +} + +declare interface InteractionCompleteEvent { + /** + * The event_id token to be used to resume the interaction stream, from this event. + */ + event_id?: string; + event_type?: 'interaction.complete'; + /** + * The Interaction resource. + */ + interaction?: Interaction; +} + +declare type InteractionCreateParams = CreateModelInteractionParamsNonStreaming | CreateModelInteractionParamsStreaming | CreateAgentInteractionParamsNonStreaming | CreateAgentInteractionParamsStreaming; + +declare interface InteractionDeleteParams { + /** + * Which version of the API to use. + */ + api_version?: string; +} + +declare type InteractionDeleteResponse = unknown; + +declare type InteractionGetParams = InteractionGetParamsNonStreaming | InteractionGetParamsStreaming; + +declare namespace InteractionGetParams { + type InteractionGetParamsNonStreaming = InteractionsAPI.InteractionGetParamsNonStreaming; + type InteractionGetParamsStreaming = InteractionsAPI.InteractionGetParamsStreaming; +} + +declare interface InteractionGetParamsBase { + /** + * Path param: Which version of the API to use. + */ + api_version?: string; + /** + * Query param: If set to true, includes the input in the response. + */ + include_input?: boolean; + /** + * Query param: Optional. If set, resumes the interaction stream from the next chunk after the event marked by the event id. Can only be used if `stream` is true. + */ + last_event_id?: string; + /** + * Query param: If set to true, the generated content will be streamed incrementally. + */ + stream?: boolean; +} + +declare interface InteractionGetParamsNonStreaming extends InteractionGetParamsBase { + /** + * Query param: If set to true, the generated content will be streamed incrementally. + */ + stream?: false; +} + +declare interface InteractionGetParamsStreaming extends InteractionGetParamsBase { + /** + * Query param: If set to true, the generated content will be streamed incrementally. + */ + stream: true; +} + +export declare class Interactions extends BaseInteractions { +} + +export declare namespace Interactions { + export { type AllowedTools as AllowedTools, type Annotation as Annotation, type AudioContent as AudioContent, type AudioMimeType as AudioMimeType, type CodeExecutionCallArguments as CodeExecutionCallArguments, type CodeExecutionCallContent as CodeExecutionCallContent, type CodeExecutionResultContent as CodeExecutionResultContent, type Content_2 as Content, type ContentDelta as ContentDelta, type ContentStart as ContentStart, type ContentStop as ContentStop, type DeepResearchAgentConfig as DeepResearchAgentConfig, type DocumentContent as DocumentContent, type DocumentMimeType as DocumentMimeType, type DynamicAgentConfig as DynamicAgentConfig, type ErrorEvent_2 as ErrorEvent, type FileSearchCallContent as FileSearchCallContent, type FileSearchResultContent as FileSearchResultContent, type Function_2 as Function, type FunctionCallContent as FunctionCallContent, type FunctionResultContent as FunctionResultContent, type GenerationConfig_2 as GenerationConfig, type GoogleSearchCallArguments as GoogleSearchCallArguments, type GoogleSearchCallContent as GoogleSearchCallContent, type GoogleSearchResult as GoogleSearchResult, type GoogleSearchResultContent as GoogleSearchResultContent, type ImageConfig_2 as ImageConfig, type ImageContent as ImageContent, type ImageMimeType as ImageMimeType, type Interaction as Interaction, type InteractionCompleteEvent as InteractionCompleteEvent, type InteractionSSEEvent as InteractionSSEEvent, type InteractionStartEvent as InteractionStartEvent, type InteractionStatusUpdate as InteractionStatusUpdate, type MCPServerToolCallContent as MCPServerToolCallContent, type MCPServerToolResultContent as MCPServerToolResultContent, type Model_2 as Model, type SpeechConfig_2 as SpeechConfig, type TextContent as TextContent, type ThinkingLevel_2 as ThinkingLevel, type ThoughtContent as ThoughtContent, type Tool_2 as Tool, type ToolChoice as ToolChoice, type ToolChoiceConfig as ToolChoiceConfig, type ToolChoiceType as ToolChoiceType, type Turn as Turn, type URLContextCallArguments as URLContextCallArguments, type URLContextCallContent as URLContextCallContent, type URLContextResult as URLContextResult, type URLContextResultContent as URLContextResultContent, type Usage as Usage, type VideoContent as VideoContent, type VideoMimeType as VideoMimeType, type InteractionDeleteResponse as InteractionDeleteResponse, type InteractionCreateParams as InteractionCreateParams, type CreateModelInteractionParamsNonStreaming as CreateModelInteractionParamsNonStreaming, type CreateModelInteractionParamsStreaming as CreateModelInteractionParamsStreaming, type CreateAgentInteractionParamsNonStreaming as CreateAgentInteractionParamsNonStreaming, type CreateAgentInteractionParamsStreaming as CreateAgentInteractionParamsStreaming, type InteractionDeleteParams as InteractionDeleteParams, type InteractionCancelParams as InteractionCancelParams, type InteractionGetParams as InteractionGetParams, type InteractionGetParamsNonStreaming as InteractionGetParamsNonStreaming, type InteractionGetParamsStreaming as InteractionGetParamsStreaming, }; +} + +declare namespace InteractionsAPI { + export { + BaseInteractions, + Interactions, + AllowedTools, + Annotation, + AudioContent, + AudioMimeType, + CodeExecutionCallArguments, + CodeExecutionCallContent, + CodeExecutionResultContent, + Content_2 as Content, + ContentDelta, + ContentStart, + ContentStop, + DeepResearchAgentConfig, + DocumentContent, + DocumentMimeType, + DynamicAgentConfig, + ErrorEvent_2 as ErrorEvent, + FileSearchCallContent, + FileSearchResultContent, + Function_2 as Function, + FunctionCallContent, + FunctionResultContent, + GenerationConfig_2 as GenerationConfig, + GoogleSearchCallArguments, + GoogleSearchCallContent, + GoogleSearchResult, + GoogleSearchResultContent, + ImageConfig_2 as ImageConfig, + ImageContent, + ImageMimeType, + Interaction, + InteractionCompleteEvent, + InteractionSSEEvent, + InteractionStartEvent, + InteractionStatusUpdate, + MCPServerToolCallContent, + MCPServerToolResultContent, + Model_2 as Model, + SpeechConfig_2 as SpeechConfig, + TextContent, + ThinkingLevel_2 as ThinkingLevel, + ThoughtContent, + Tool_2 as Tool, + ToolChoice, + ToolChoiceConfig, + ToolChoiceType, + Turn, + URLContextCallArguments, + URLContextCallContent, + URLContextResult, + URLContextResultContent, + Usage, + VideoContent, + VideoMimeType, + InteractionDeleteResponse, + InteractionCreateParams, + BaseCreateModelInteractionParams, + BaseCreateAgentInteractionParams, + CreateModelInteractionParamsNonStreaming, + CreateModelInteractionParamsStreaming, + CreateAgentInteractionParamsNonStreaming, + CreateAgentInteractionParamsStreaming, + InteractionDeleteParams, + InteractionCancelParams, + InteractionGetParams, + InteractionGetParamsBase, + InteractionGetParamsNonStreaming, + InteractionGetParamsStreaming + } +} + +declare type InteractionSSEEvent = InteractionStartEvent | InteractionCompleteEvent | InteractionStatusUpdate | ContentStart | ContentDelta | ContentStop | ErrorEvent_2; + +declare interface InteractionStartEvent { + /** + * The event_id token to be used to resume the interaction stream, from this event. + */ + event_id?: string; + event_type?: 'interaction.start'; + /** + * The Interaction resource. + */ + interaction?: Interaction; +} + +declare interface InteractionStatusUpdate { + /** + * The event_id token to be used to resume the interaction stream, from this event. + */ + event_id?: string; + event_type?: 'interaction.status_update'; + interaction_id?: string; + status?: 'in_progress' | 'requires_action' | 'completed' | 'failed' | 'cancelled' | 'incomplete'; +} + +/** Parameters for the private _Register method. */ +export declare interface InternalRegisterFilesParameters { + /** The Google Cloud Storage URIs to register. Example: `gs://bucket/object`. */ + uris: string[]; + /** Used to override the default configuration. */ + config?: RegisterFilesConfig; +} + +declare class InternalServerError extends APIError<number, Headers> { +} + +/** Represents a time interval, encoded as a Timestamp start (inclusive) and a Timestamp end (exclusive). The start must be less than or equal to the end. When the start equals the end, the interval is empty (matches no time). When both start and end are unspecified, the interval matches any time. */ +export declare interface Interval { + /** Optional. Exclusive end of the interval. If specified, a Timestamp matching this interval will have to be before the end. */ + endTime?: string; + /** Optional. Inclusive start of the interval. If specified, a Timestamp matching this interval will have to be the same or after the start. */ + startTime?: string; +} + +/** Job error. */ +export declare interface JobError { + /** A list of messages that carry the error details. There is a common set of message types for APIs to use. */ + details?: string[]; + /** The status code. */ + code?: number; + /** A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the `details` field. */ + message?: string; +} + +/** Job state. */ +export declare enum JobState { + /** + * The job state is unspecified. + */ + JOB_STATE_UNSPECIFIED = "JOB_STATE_UNSPECIFIED", + /** + * The job has been just created or resumed and processing has not yet begun. + */ + JOB_STATE_QUEUED = "JOB_STATE_QUEUED", + /** + * The service is preparing to run the job. + */ + JOB_STATE_PENDING = "JOB_STATE_PENDING", + /** + * The job is in progress. + */ + JOB_STATE_RUNNING = "JOB_STATE_RUNNING", + /** + * The job completed successfully. + */ + JOB_STATE_SUCCEEDED = "JOB_STATE_SUCCEEDED", + /** + * The job failed. + */ + JOB_STATE_FAILED = "JOB_STATE_FAILED", + /** + * The job is being cancelled. From this state the job may only go to either `JOB_STATE_SUCCEEDED`, `JOB_STATE_FAILED` or `JOB_STATE_CANCELLED`. + */ + JOB_STATE_CANCELLING = "JOB_STATE_CANCELLING", + /** + * The job has been cancelled. + */ + JOB_STATE_CANCELLED = "JOB_STATE_CANCELLED", + /** + * The job has been stopped, and can be resumed. + */ + JOB_STATE_PAUSED = "JOB_STATE_PAUSED", + /** + * The job has expired. + */ + JOB_STATE_EXPIRED = "JOB_STATE_EXPIRED", + /** + * The job is being updated. Only jobs in the `JOB_STATE_RUNNING` state can be updated. After updating, the job goes back to the `JOB_STATE_RUNNING` state. + */ + JOB_STATE_UPDATING = "JOB_STATE_UPDATING", + /** + * The job is partially succeeded, some results may be missing due to errors. + */ + JOB_STATE_PARTIALLY_SUCCEEDED = "JOB_STATE_PARTIALLY_SUCCEEDED" +} + +/** Programming language of the `code`. */ +export declare enum Language { + /** + * Unspecified language. This value should not be used. + */ + LANGUAGE_UNSPECIFIED = "LANGUAGE_UNSPECIFIED", + /** + * Python >= 3.10, with numpy and simpy available. + */ + PYTHON = "PYTHON" +} + +/** An object that represents a latitude/longitude pair. + + This is expressed as a pair of doubles to represent degrees latitude and + degrees longitude. Unless specified otherwise, this object must conform to the + <a href="https://en.wikipedia.org/wiki/World_Geodetic_System#1984_version"> + WGS84 standard</a>. Values must be within normalized ranges. */ +export declare interface LatLng { + /** The latitude in degrees. It must be in the range [-90.0, +90.0]. */ + latitude?: number; + /** The longitude in degrees. It must be in the range [-180.0, +180.0] */ + longitude?: number; +} + +/** Config for optional parameters. */ +export declare interface ListBatchJobsConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + pageSize?: number; + pageToken?: string; + filter?: string; +} + +/** Config for batches.list parameters. */ +export declare interface ListBatchJobsParameters { + config?: ListBatchJobsConfig; +} + +/** Config for batches.list return value. */ +export declare class ListBatchJobsResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + nextPageToken?: string; + batchJobs?: BatchJob[]; +} + +/** Config for caches.list method. */ +export declare interface ListCachedContentsConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + pageSize?: number; + pageToken?: string; +} + +/** Parameters for caches.list method. */ +export declare interface ListCachedContentsParameters { + /** Configuration that contains optional parameters. + */ + config?: ListCachedContentsConfig; +} + +export declare class ListCachedContentsResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + nextPageToken?: string; + /** List of cached contents. + */ + cachedContents?: CachedContent[]; +} + +/** Config for optional parameters. */ +export declare interface ListDocumentsConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + pageSize?: number; + pageToken?: string; +} + +/** Config for documents.list parameters. */ +export declare interface ListDocumentsParameters { + /** The resource name of the FileSearchStores. Example: `fileSearchStore/file-search-store-foo` */ + parent: string; + config?: ListDocumentsConfig; +} + +/** Config for documents.list return value. */ +export declare class ListDocumentsResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** A token, which can be sent as `page_token` to retrieve the next page. If this field is omitted, there are no more pages. */ + nextPageToken?: string; + /** The returned `Document`s. */ + documents?: Document_2[]; +} + +export declare interface ListFilesConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + pageSize?: number; + pageToken?: string; +} + +/** Optional parameters for listing FileSearchStore. */ +export declare interface ListFileSearchStoresConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + pageSize?: number; + pageToken?: string; +} + +/** Config for file_search_stores.list parameters. */ +export declare interface ListFileSearchStoresParameters { + /** Optional parameters for the list request. */ + config?: ListFileSearchStoresConfig; +} + +/** Config for file_search_stores.list return value. */ +export declare class ListFileSearchStoresResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + nextPageToken?: string; + /** The returned file search stores. */ + fileSearchStores?: FileSearchStore[]; +} + +/** Generates the parameters for the list method. */ +export declare interface ListFilesParameters { + /** Used to override the default configuration. */ + config?: ListFilesConfig; +} + +/** Response for the list files method. */ +export declare class ListFilesResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** A token that can be sent as a `page_token` into a subsequent `ListFiles` call. */ + nextPageToken?: string; + /** The list of `File`s. */ + files?: File_2[]; +} + +export declare interface ListModelsConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + pageSize?: number; + pageToken?: string; + filter?: string; + /** Set true to list base models, false to list tuned models. */ + queryBase?: boolean; +} + +export declare interface ListModelsParameters { + config?: ListModelsConfig; +} + +export declare class ListModelsResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + nextPageToken?: string; + models?: Model[]; +} + +/** Configuration for the list tuning jobs method. */ +export declare interface ListTuningJobsConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + pageSize?: number; + pageToken?: string; + filter?: string; +} + +/** Parameters for the list tuning jobs method. */ +export declare interface ListTuningJobsParameters { + config?: ListTuningJobsConfig; +} + +/** Response for the list tuning jobs method. */ +export declare class ListTuningJobsResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** A token to retrieve the next page of results. Pass to ListTuningJobsRequest.page_token to obtain that page. */ + nextPageToken?: string; + /** List of TuningJobs in the requested page. */ + tuningJobs?: TuningJob[]; +} + +/** + Live class encapsulates the configuration for live interaction with the + Generative Language API. It embeds ApiClient for general API settings. + + @experimental + */ +export declare class Live { + private readonly apiClient; + private readonly auth; + private readonly webSocketFactory; + readonly music: LiveMusic; + constructor(apiClient: ApiClient, auth: Auth, webSocketFactory: WebSocketFactory); + /** + Establishes a connection to the specified model with the given + configuration and returns a Session object representing that connection. + + @experimental Built-in MCP support is an experimental feature, may change in + future versions. + + @remarks + + @param params - The parameters for establishing a connection to the model. + @return A live session. + + @example + ```ts + let model: string; + if (GOOGLE_GENAI_USE_VERTEXAI) { + model = 'gemini-2.0-flash-live-preview-04-09'; + } else { + model = 'gemini-live-2.5-flash-preview'; + } + const session = await ai.live.connect({ + model: model, + config: { + responseModalities: [Modality.AUDIO], + }, + callbacks: { + onopen: () => { + console.log('Connected to the socket.'); + }, + onmessage: (e: MessageEvent) => { + console.log('Received message from the server: %s\n', debug(e.data)); + }, + onerror: (e: ErrorEvent) => { + console.log('Error occurred: %s\n', debug(e.error)); + }, + onclose: (e: CloseEvent) => { + console.log('Connection closed.'); + }, + }, + }); + ``` + */ + connect(params: types.LiveConnectParameters): Promise<Session>; + private isCallableTool; +} + +/** Callbacks for the live API. */ +export declare interface LiveCallbacks { + /** + * Called when the websocket connection is established. + */ + onopen?: (() => void) | null; + /** + * Called when a message is received from the server. + */ + onmessage: (e: LiveServerMessage) => void; + /** + * Called when an error occurs. + */ + onerror?: ((e: ErrorEvent) => void) | null; + /** + * Called when the websocket connection is closed. + */ + onclose?: ((e: CloseEvent) => void) | null; +} + +/** Incremental update of the current conversation delivered from the client. + + All the content here will unconditionally be appended to the conversation + history and used as part of the prompt to the model to generate content. + + A message here will interrupt any current model generation. */ +export declare interface LiveClientContent { + /** The content appended to the current conversation with the model. + + For single-turn queries, this is a single instance. For multi-turn + queries, this is a repeated field that contains conversation history and + latest request. + */ + turns?: Content[]; + /** If true, indicates that the server content generation should start with + the currently accumulated prompt. Otherwise, the server will await + additional messages before starting generation. */ + turnComplete?: boolean; +} + +/** Messages sent by the client in the API call. */ +export declare interface LiveClientMessage { + /** Message to be sent by the system when connecting to the API. SDK users should not send this message. */ + setup?: LiveClientSetup; + /** Incremental update of the current conversation delivered from the client. */ + clientContent?: LiveClientContent; + /** User input that is sent in real time. */ + realtimeInput?: LiveClientRealtimeInput; + /** Response to a `ToolCallMessage` received from the server. */ + toolResponse?: LiveClientToolResponse; +} + +/** User input that is sent in real time. + + This is different from `LiveClientContent` in a few ways: + + - Can be sent continuously without interruption to model generation. + - If there is a need to mix data interleaved across the + `LiveClientContent` and the `LiveClientRealtimeInput`, server attempts to + optimize for best response, but there are no guarantees. + - End of turn is not explicitly specified, but is rather derived from user + activity (for example, end of speech). + - Even before the end of turn, the data is processed incrementally + to optimize for a fast start of the response from the model. + - Is always assumed to be the user's input (cannot be used to populate + conversation history). */ +export declare interface LiveClientRealtimeInput { + /** Inlined bytes data for media input. */ + mediaChunks?: Blob_2[]; + /** The realtime audio input stream. */ + audio?: Blob_2; + /** + Indicates that the audio stream has ended, e.g. because the microphone was + turned off. + + This should only be sent when automatic activity detection is enabled + (which is the default). + + The client can reopen the stream by sending an audio message. + */ + audioStreamEnd?: boolean; + /** The realtime video input stream. */ + video?: Blob_2; + /** The realtime text input stream. */ + text?: string; + /** Marks the start of user activity. */ + activityStart?: ActivityStart; + /** Marks the end of user activity. */ + activityEnd?: ActivityEnd; +} + +/** Message contains configuration that will apply for the duration of the streaming session. */ +export declare interface LiveClientSetup { + /** + The fully qualified name of the publisher model or tuned model endpoint to + use. + */ + model?: string; + /** The generation configuration for the session. + Note: only a subset of fields are supported. + */ + generationConfig?: GenerationConfig; + /** The user provided system instructions for the model. + Note: only text should be used in parts and content in each part will be + in a separate paragraph. */ + systemInstruction?: ContentUnion; + /** A list of `Tools` the model may use to generate the next response. + + A `Tool` is a piece of code that enables the system to interact with + external systems to perform an action, or set of actions, outside of + knowledge and scope of the model. */ + tools?: ToolListUnion; + /** Configures the realtime input behavior in BidiGenerateContent. */ + realtimeInputConfig?: RealtimeInputConfig; + /** Configures session resumption mechanism. + + If included server will send SessionResumptionUpdate messages. */ + sessionResumption?: SessionResumptionConfig; + /** Configures context window compression mechanism. + + If included, server will compress context window to fit into given length. */ + contextWindowCompression?: ContextWindowCompressionConfig; + /** The transcription of the input aligns with the input audio language. + */ + inputAudioTranscription?: AudioTranscriptionConfig; + /** The transcription of the output aligns with the language code + specified for the output audio. + */ + outputAudioTranscription?: AudioTranscriptionConfig; + /** Configures the proactivity of the model. This allows the model to respond proactively to + the input and to ignore irrelevant input. */ + proactivity?: ProactivityConfig; + /** Configures the explicit VAD signal. If enabled, the client will send + vad_signal to indicate the start and end of speech. This allows the server + to process the audio more efficiently. */ + explicitVadSignal?: boolean; +} + +/** Client generated response to a `ToolCall` received from the server. + + Individual `FunctionResponse` objects are matched to the respective + `FunctionCall` objects by the `id` field. + + Note that in the unary and server-streaming GenerateContent APIs function + calling happens by exchanging the `Content` parts, while in the bidi + GenerateContent APIs function calling happens over this dedicated set of + messages. */ +export declare class LiveClientToolResponse { + /** The response to the function calls. */ + functionResponses?: FunctionResponse[]; +} + +/** Session config for the API connection. */ +export declare interface LiveConnectConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** The generation configuration for the session. */ + generationConfig?: GenerationConfig; + /** The requested modalities of the response. Represents the set of + modalities that the model can return. Defaults to AUDIO if not specified. + */ + responseModalities?: Modality[]; + /** Value that controls the degree of randomness in token selection. + Lower temperatures are good for prompts that require a less open-ended or + creative response, while higher temperatures can lead to more diverse or + creative results. + */ + temperature?: number; + /** Tokens are selected from the most to least probable until the sum + of their probabilities equals this value. Use a lower value for less + random responses and a higher value for more random responses. + */ + topP?: number; + /** For each token selection step, the ``top_k`` tokens with the + highest probabilities are sampled. Then tokens are further filtered based + on ``top_p`` with the final token selected using temperature sampling. Use + a lower number for less random responses and a higher number for more + random responses. + */ + topK?: number; + /** Maximum number of tokens that can be generated in the response. + */ + maxOutputTokens?: number; + /** If specified, the media resolution specified will be used. + */ + mediaResolution?: MediaResolution; + /** When ``seed`` is fixed to a specific number, the model makes a best + effort to provide the same response for repeated requests. By default, a + random number is used. + */ + seed?: number; + /** The speech generation configuration. + */ + speechConfig?: SpeechConfig; + /** Config for thinking features. + An error will be returned if this field is set for models that don't + support thinking. + */ + thinkingConfig?: ThinkingConfig; + /** If enabled, the model will detect emotions and adapt its responses accordingly. */ + enableAffectiveDialog?: boolean; + /** The user provided system instructions for the model. + Note: only text should be used in parts and content in each part will be + in a separate paragraph. */ + systemInstruction?: ContentUnion; + /** A list of `Tools` the model may use to generate the next response. + + A `Tool` is a piece of code that enables the system to interact with + external systems to perform an action, or set of actions, outside of + knowledge and scope of the model. */ + tools?: ToolListUnion; + /** Configures session resumption mechanism. + + If included the server will send SessionResumptionUpdate messages. */ + sessionResumption?: SessionResumptionConfig; + /** The transcription of the input aligns with the input audio language. + */ + inputAudioTranscription?: AudioTranscriptionConfig; + /** The transcription of the output aligns with the language code + specified for the output audio. + */ + outputAudioTranscription?: AudioTranscriptionConfig; + /** Configures the realtime input behavior in BidiGenerateContent. */ + realtimeInputConfig?: RealtimeInputConfig; + /** Configures context window compression mechanism. + + If included, server will compress context window to fit into given length. */ + contextWindowCompression?: ContextWindowCompressionConfig; + /** Configures the proactivity of the model. This allows the model to respond proactively to + the input and to ignore irrelevant input. */ + proactivity?: ProactivityConfig; + /** Configures the explicit VAD signal. If enabled, the client will send + vad_signal to indicate the start and end of speech. This allows the server + to process the audio more efficiently. */ + explicitVadSignal?: boolean; +} + +/** Config for LiveConnectConstraints for Auth Token creation. */ +export declare interface LiveConnectConstraints { + /** ID of the model to configure in the ephemeral token for Live API. + For a list of models, see `Gemini models + <https://ai.google.dev/gemini-api/docs/models>`. */ + model?: string; + /** Configuration specific to Live API connections created using this token. */ + config?: LiveConnectConfig; +} + +/** Parameters for connecting to the live API. */ +export declare interface LiveConnectParameters { + /** ID of the model to use. For a list of models, see `Google models + <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */ + model: string; + /** callbacks */ + callbacks: LiveCallbacks; + /** Optional configuration parameters for the request. + */ + config?: LiveConnectConfig; +} + +/** + LiveMusic class encapsulates the configuration for live music + generation via Lyria Live models. + + @experimental + */ +declare class LiveMusic { + private readonly apiClient; + private readonly auth; + private readonly webSocketFactory; + constructor(apiClient: ApiClient, auth: Auth, webSocketFactory: WebSocketFactory); + /** + Establishes a connection to the specified model and returns a + LiveMusicSession object representing that connection. + + @experimental + + @remarks + + @param params - The parameters for establishing a connection to the model. + @return A live session. + + @example + ```ts + let model = 'models/lyria-realtime-exp'; + const session = await ai.live.music.connect({ + model: model, + callbacks: { + onmessage: (e: MessageEvent) => { + console.log('Received message from the server: %s\n', debug(e.data)); + }, + onerror: (e: ErrorEvent) => { + console.log('Error occurred: %s\n', debug(e.error)); + }, + onclose: (e: CloseEvent) => { + console.log('Connection closed.'); + }, + }, + }); + ``` + */ + connect(params: types.LiveMusicConnectParameters): Promise<LiveMusicSession>; +} + +/** Callbacks for the realtime music API. */ +export declare interface LiveMusicCallbacks { + /** + * Called when a message is received from the server. + */ + onmessage: (e: LiveMusicServerMessage) => void; + /** + * Called when an error occurs. + */ + onerror?: ((e: ErrorEvent) => void) | null; + /** + * Called when the websocket connection is closed. + */ + onclose?: ((e: CloseEvent) => void) | null; +} + +/** User input to start or steer the music. */ +export declare interface LiveMusicClientContent { + /** Weighted prompts as the model input. */ + weightedPrompts?: WeightedPrompt[]; +} + +/** Messages sent by the client in the LiveMusicClientMessage call. */ +export declare interface LiveMusicClientMessage { + /** Message to be sent in the first (and only in the first) `LiveMusicClientMessage`. + Clients should wait for a `LiveMusicSetupComplete` message before + sending any additional messages. */ + setup?: LiveMusicClientSetup; + /** User input to influence music generation. */ + clientContent?: LiveMusicClientContent; + /** Configuration for music generation. */ + musicGenerationConfig?: LiveMusicGenerationConfig; + /** Playback control signal for the music generation. */ + playbackControl?: LiveMusicPlaybackControl; +} + +/** Message to be sent by the system when connecting to the API. */ +export declare interface LiveMusicClientSetup { + /** The model's resource name. Format: `models/{model}`. */ + model?: string; +} + +/** Parameters for connecting to the live API. */ +export declare interface LiveMusicConnectParameters { + /** The model's resource name. */ + model: string; + /** Callbacks invoked on server events. */ + callbacks: LiveMusicCallbacks; +} + +/** A prompt that was filtered with the reason. */ +export declare interface LiveMusicFilteredPrompt { + /** The text prompt that was filtered. */ + text?: string; + /** The reason the prompt was filtered. */ + filteredReason?: string; +} + +/** Configuration for music generation. */ +export declare interface LiveMusicGenerationConfig { + /** Controls the variance in audio generation. Higher values produce + higher variance. Range is [0.0, 3.0]. */ + temperature?: number; + /** Controls how the model selects tokens for output. Samples the topK + tokens with the highest probabilities. Range is [1, 1000]. */ + topK?: number; + /** Seeds audio generation. If not set, the request uses a randomly + generated seed. */ + seed?: number; + /** Controls how closely the model follows prompts. + Higher guidance follows more closely, but will make transitions more + abrupt. Range is [0.0, 6.0]. */ + guidance?: number; + /** Beats per minute. Range is [60, 200]. */ + bpm?: number; + /** Density of sounds. Range is [0.0, 1.0]. */ + density?: number; + /** Brightness of the music. Range is [0.0, 1.0]. */ + brightness?: number; + /** Scale of the generated music. */ + scale?: Scale; + /** Whether the audio output should contain bass. */ + muteBass?: boolean; + /** Whether the audio output should contain drums. */ + muteDrums?: boolean; + /** Whether the audio output should contain only bass and drums. */ + onlyBassAndDrums?: boolean; + /** The mode of music generation. Default mode is QUALITY. */ + musicGenerationMode?: MusicGenerationMode; +} + +/** The playback control signal to apply to the music generation. */ +export declare enum LiveMusicPlaybackControl { + /** + * This value is unused. + */ + PLAYBACK_CONTROL_UNSPECIFIED = "PLAYBACK_CONTROL_UNSPECIFIED", + /** + * Start generating the music. + */ + PLAY = "PLAY", + /** + * Hold the music generation. Use PLAY to resume from the current position. + */ + PAUSE = "PAUSE", + /** + * Stop the music generation and reset the context (prompts retained). + Use PLAY to restart the music generation. + */ + STOP = "STOP", + /** + * Reset the context of the music generation without stopping it. + Retains the current prompts and config. + */ + RESET_CONTEXT = "RESET_CONTEXT" +} + +/** Server update generated by the model in response to client messages. + + Content is generated as quickly as possible, and not in real time. + Clients may choose to buffer and play it out in real time. */ +export declare interface LiveMusicServerContent { + /** The audio chunks that the model has generated. */ + audioChunks?: AudioChunk[]; +} + +/** Response message for the LiveMusicClientMessage call. */ +export declare class LiveMusicServerMessage { + /** Message sent in response to a `LiveMusicClientSetup` message from the client. + Clients should wait for this message before sending any additional messages. */ + setupComplete?: LiveMusicServerSetupComplete; + /** Content generated by the model in response to client messages. */ + serverContent?: LiveMusicServerContent; + /** A prompt that was filtered with the reason. */ + filteredPrompt?: LiveMusicFilteredPrompt; + /** + * Returns the first audio chunk from the server content, if present. + * + * @remarks + * If there are no audio chunks in the response, undefined will be returned. + */ + get audioChunk(): AudioChunk | undefined; +} + +/** Sent in response to a `LiveMusicClientSetup` message from the client. */ +export declare interface LiveMusicServerSetupComplete { +} + +/** + Represents a connection to the API. + + @experimental + */ +export declare class LiveMusicSession { + readonly conn: WebSocket_2; + private readonly apiClient; + constructor(conn: WebSocket_2, apiClient: ApiClient); + /** + Sets inputs to steer music generation. Updates the session's current + weighted prompts. + + @param params - Contains one property, `weightedPrompts`. + + - `weightedPrompts` to send to the model; weights are normalized to + sum to 1.0. + + @experimental + */ + setWeightedPrompts(params: types.LiveMusicSetWeightedPromptsParameters): Promise<void>; + /** + Sets a configuration to the model. Updates the session's current + music generation config. + + @param params - Contains one property, `musicGenerationConfig`. + + - `musicGenerationConfig` to set in the model. Passing an empty or + undefined config to the model will reset the config to defaults. + + @experimental + */ + setMusicGenerationConfig(params: types.LiveMusicSetConfigParameters): Promise<void>; + private sendPlaybackControl; + /** + * Start the music stream. + * + * @experimental + */ + play(): void; + /** + * Temporarily halt the music stream. Use `play` to resume from the current + * position. + * + * @experimental + */ + pause(): void; + /** + * Stop the music stream and reset the state. Retains the current prompts + * and config. + * + * @experimental + */ + stop(): void; + /** + * Resets the context of the music generation without stopping it. + * Retains the current prompts and config. + * + * @experimental + */ + resetContext(): void; + /** + Terminates the WebSocket connection. + + @experimental + */ + close(): void; +} + +/** Parameters for setting config for the live music API. */ +export declare interface LiveMusicSetConfigParameters { + /** Configuration for music generation. */ + musicGenerationConfig: LiveMusicGenerationConfig; +} + +/** Parameters for setting weighted prompts for the live music API. */ +export declare interface LiveMusicSetWeightedPromptsParameters { + /** A map of text prompts to weights to use for the generation request. */ + weightedPrompts: WeightedPrompt[]; +} + +/** Prompts and config used for generating this audio chunk. */ +export declare interface LiveMusicSourceMetadata { + /** Weighted prompts for generating this audio chunk. */ + clientContent?: LiveMusicClientContent; + /** Music generation config for generating this audio chunk. */ + musicGenerationConfig?: LiveMusicGenerationConfig; +} + +/** Parameters for sending client content to the live API. */ +export declare interface LiveSendClientContentParameters { + /** Client content to send to the session. */ + turns?: ContentListUnion; + /** If true, indicates that the server content generation should start with + the currently accumulated prompt. Otherwise, the server will await + additional messages before starting generation. */ + turnComplete?: boolean; +} + +/** Parameters for sending realtime input to the live API. */ +export declare interface LiveSendRealtimeInputParameters { + /** Realtime input to send to the session. */ + media?: BlobImageUnion; + /** The realtime audio input stream. */ + audio?: Blob_2; + /** + Indicates that the audio stream has ended, e.g. because the microphone was + turned off. + + This should only be sent when automatic activity detection is enabled + (which is the default). + + The client can reopen the stream by sending an audio message. + */ + audioStreamEnd?: boolean; + /** The realtime video input stream. */ + video?: BlobImageUnion; + /** The realtime text input stream. */ + text?: string; + /** Marks the start of user activity. */ + activityStart?: ActivityStart; + /** Marks the end of user activity. */ + activityEnd?: ActivityEnd; +} + +/** Parameters for sending tool responses to the live API. */ +export declare class LiveSendToolResponseParameters { + /** Tool responses to send to the session. */ + functionResponses: FunctionResponse[] | FunctionResponse; +} + +/** Incremental server update generated by the model in response to client messages. + + Content is generated as quickly as possible, and not in real time. Clients + may choose to buffer and play it out in real time. */ +export declare interface LiveServerContent { + /** The content that the model has generated as part of the current conversation with the user. */ + modelTurn?: Content; + /** If true, indicates that the model is done generating. Generation will only start in response to additional client messages. Can be set alongside `content`, indicating that the `content` is the last in the turn. */ + turnComplete?: boolean; + /** If true, indicates that a client message has interrupted current model generation. If the client is playing out the content in realtime, this is a good signal to stop and empty the current queue. */ + interrupted?: boolean; + /** Metadata returned to client when grounding is enabled. */ + groundingMetadata?: GroundingMetadata; + /** If true, indicates that the model is done generating. When model is + interrupted while generating there will be no generation_complete message + in interrupted turn, it will go through interrupted > turn_complete. + When model assumes realtime playback there will be delay between + generation_complete and turn_complete that is caused by model + waiting for playback to finish. If true, indicates that the model + has finished generating all content. This is a signal to the client + that it can stop sending messages. */ + generationComplete?: boolean; + /** Input transcription. The transcription is independent to the model + turn which means it doesn’t imply any ordering between transcription and + model turn. */ + inputTranscription?: Transcription; + /** Output transcription. The transcription is independent to the model + turn which means it doesn’t imply any ordering between transcription and + model turn. + */ + outputTranscription?: Transcription; + /** Metadata related to url context retrieval tool. */ + urlContextMetadata?: UrlContextMetadata; + /** Reason for the turn is complete. */ + turnCompleteReason?: TurnCompleteReason; + /** If true, indicates that the model is not generating content because + it is waiting for more input from the user, e.g. because it expects the + user to continue talking. */ + waitingForInput?: boolean; +} + +/** Server will not be able to service client soon. */ +export declare interface LiveServerGoAway { + /** The remaining time before the connection will be terminated as ABORTED. The minimal time returned here is specified differently together with the rate limits for a given model. */ + timeLeft?: string; +} + +/** Response message for API call. */ +export declare class LiveServerMessage { + /** Sent in response to a `LiveClientSetup` message from the client. */ + setupComplete?: LiveServerSetupComplete; + /** Content generated by the model in response to client messages. */ + serverContent?: LiveServerContent; + /** Request for the client to execute the `function_calls` and return the responses with the matching `id`s. */ + toolCall?: LiveServerToolCall; + /** Notification for the client that a previously issued `ToolCallMessage` with the specified `id`s should have been not executed and should be cancelled. */ + toolCallCancellation?: LiveServerToolCallCancellation; + /** Usage metadata about model response(s). */ + usageMetadata?: UsageMetadata; + /** Server will disconnect soon. */ + goAway?: LiveServerGoAway; + /** Update of the session resumption state. */ + sessionResumptionUpdate?: LiveServerSessionResumptionUpdate; + /** Voice activity detection signal. Allowlisted only. */ + voiceActivityDetectionSignal?: VoiceActivityDetectionSignal; + /** Voice activity signal. */ + voiceActivity?: VoiceActivity; + /** + * Returns the concatenation of all text parts from the server content if present. + * + * @remarks + * If there are non-text parts in the response, the concatenation of all text + * parts will be returned, and a warning will be logged. + */ + get text(): string | undefined; + /** + * Returns the concatenation of all inline data parts from the server content if present. + * + * @remarks + * If there are non-inline data parts in the + * response, the concatenation of all inline data parts will be returned, and + * a warning will be logged. + */ + get data(): string | undefined; +} + +/** Update of the session resumption state. + + Only sent if `session_resumption` was set in the connection config. */ +export declare interface LiveServerSessionResumptionUpdate { + /** New handle that represents state that can be resumed. Empty if `resumable`=false. */ + newHandle?: string; + /** True if session can be resumed at this point. It might be not possible to resume session at some points. In that case we send update empty new_handle and resumable=false. Example of such case could be model executing function calls or just generating. Resuming session (using previous session token) in such state will result in some data loss. */ + resumable?: boolean; + /** Index of last message sent by client that is included in state represented by this SessionResumptionToken. Only sent when `SessionResumptionConfig.transparent` is set. + + Presence of this index allows users to transparently reconnect and avoid issue of losing some part of realtime audio input/video. If client wishes to temporarily disconnect (for example as result of receiving GoAway) they can do it without losing state by buffering messages sent since last `SessionResmumptionTokenUpdate`. This field will enable them to limit buffering (avoid keeping all requests in RAM). + + Note: This should not be used for when resuming a session at some time later -- in those cases partial audio and video frames arelikely not needed. */ + lastConsumedClientMessageIndex?: string; +} + +/** Sent in response to a `LiveGenerateContentSetup` message from the client. */ +export declare interface LiveServerSetupComplete { + /** The session id of the live session. */ + sessionId?: string; +} + +/** Request for the client to execute the `function_calls` and return the responses with the matching `id`s. */ +export declare interface LiveServerToolCall { + /** The function call to be executed. */ + functionCalls?: FunctionCall[]; +} + +/** Notification for the client that a previously issued `ToolCallMessage` with the specified `id`s should have been not executed and should be cancelled. + + If there were side-effects to those tool calls, clients may attempt to undo + the tool calls. This message occurs only in cases where the clients interrupt + server turns. */ +export declare interface LiveServerToolCallCancellation { + /** The ids of the tool calls to be cancelled. */ + ids?: string[]; +} + +declare type LogFn = (message: string, ...rest: unknown[]) => void; + +declare type Logger = { + error: LogFn; + warn: LogFn; + info: LogFn; + debug: LogFn; +}; + +declare type LogLevel = 'off' | 'error' | 'warn' | 'info' | 'debug'; + +/** Logprobs Result */ +export declare interface LogprobsResult { + /** Length = total number of decoding steps. The chosen candidates may or may not be in top_candidates. */ + chosenCandidates?: LogprobsResultCandidate[]; + /** Length = total number of decoding steps. */ + topCandidates?: LogprobsResultTopCandidates[]; +} + +/** Candidate for the logprobs token and score. */ +export declare interface LogprobsResultCandidate { + /** The candidate's log probability. */ + logProbability?: number; + /** The candidate's token string value. */ + token?: string; + /** The candidate's token id value. */ + tokenId?: number; +} + +/** Candidates with top log probabilities at each decoding step. */ +export declare interface LogprobsResultTopCandidates { + /** Sorted by log probability in descending order. */ + candidates?: LogprobsResultCandidate[]; +} + +/** Configuration for a Mask reference image. */ +export declare interface MaskReferenceConfig { + /** Prompts the model to generate a mask instead of you needing to + provide one (unless MASK_MODE_USER_PROVIDED is used). */ + maskMode?: MaskReferenceMode; + /** A list of up to 5 class ids to use for semantic segmentation. + Automatically creates an image mask based on specific objects. */ + segmentationClasses?: number[]; + /** Dilation percentage of the mask provided. + Float between 0 and 1. */ + maskDilation?: number; +} + +/** A mask reference image. + + This encapsulates either a mask image provided by the user and configs for + the user provided mask, or only config parameters for the model to generate + a mask. + + A mask image is an image whose non-zero values indicate where to edit the base + image. If the user provides a mask image, the mask must be in the same + dimensions as the raw image. */ +export declare class MaskReferenceImage { + /** The reference image for the editing operation. */ + referenceImage?: Image_2; + /** The id of the reference image. */ + referenceId?: number; + /** The type of the reference image. Only set by the SDK. */ + referenceType?: string; + /** Configuration for the mask reference image. */ + config?: MaskReferenceConfig; + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI(): ReferenceImageAPIInternal; +} + +/** Enum representing the mask mode of a mask reference image. */ +export declare enum MaskReferenceMode { + MASK_MODE_DEFAULT = "MASK_MODE_DEFAULT", + MASK_MODE_USER_PROVIDED = "MASK_MODE_USER_PROVIDED", + MASK_MODE_BACKGROUND = "MASK_MODE_BACKGROUND", + MASK_MODE_FOREGROUND = "MASK_MODE_FOREGROUND", + MASK_MODE_SEMANTIC = "MASK_MODE_SEMANTIC" +} + +/** + * MCPServer tool call content. + */ +declare interface MCPServerToolCallContent { + /** + * A unique ID for this specific tool call. + */ + id: string; + /** + * The JSON object of arguments for the function. + */ + arguments: { + [key: string]: unknown; + }; + /** + * The name of the tool which was called. + */ + name: string; + /** + * The name of the used MCP server. + */ + server_name: string; + type: 'mcp_server_tool_call'; +} + +/** + * MCPServer tool result content. + */ +declare interface MCPServerToolResultContent { + /** + * ID to match the ID from the MCP server tool call block. + */ + call_id: string; + /** + * The result of the tool call. + */ + result: MCPServerToolResultContent.Items | unknown | string; + type: 'mcp_server_tool_result'; + /** + * Name of the tool which is called for this specific tool call. + */ + name?: string; + /** + * The name of the used MCP server. + */ + server_name?: string; +} + +declare namespace MCPServerToolResultContent { + interface Items { + items?: Array<InteractionsAPI.TextContent | InteractionsAPI.ImageContent>; + } +} + +/** + * Creates a McpCallableTool from MCP clients and an optional config. + * + * The callable tool can invoke the MCP clients with given function call + * arguments. (often for automatic function calling). + * Use the config to modify tool parameters such as behavior. + * + * @experimental Built-in MCP support is an experimental feature, may change in future + * versions. + */ +export declare function mcpToTool(...args: [...Client[], CallableToolConfig | Client]): CallableTool; + +/** Server content modalities. */ +export declare enum MediaModality { + /** + * The modality is unspecified. + */ + MODALITY_UNSPECIFIED = "MODALITY_UNSPECIFIED", + /** + * Plain text. + */ + TEXT = "TEXT", + /** + * Images. + */ + IMAGE = "IMAGE", + /** + * Video. + */ + VIDEO = "VIDEO", + /** + * Audio. + */ + AUDIO = "AUDIO", + /** + * Document, e.g. PDF. + */ + DOCUMENT = "DOCUMENT" +} + +/** The media resolution to use. */ +export declare enum MediaResolution { + /** + * Media resolution has not been set + */ + MEDIA_RESOLUTION_UNSPECIFIED = "MEDIA_RESOLUTION_UNSPECIFIED", + /** + * Media resolution set to low (64 tokens). + */ + MEDIA_RESOLUTION_LOW = "MEDIA_RESOLUTION_LOW", + /** + * Media resolution set to medium (256 tokens). + */ + MEDIA_RESOLUTION_MEDIUM = "MEDIA_RESOLUTION_MEDIUM", + /** + * Media resolution set to high (zoomed reframing with 256 tokens). + */ + MEDIA_RESOLUTION_HIGH = "MEDIA_RESOLUTION_HIGH" +} + +/** + * This type contains `RequestInit` options that may be available on the current runtime, + * including per-platform extensions like `dispatcher`, `agent`, `client`, etc. + */ +declare type MergedRequestInit = RequestInits & +/** We don't include these in the types as they'll be overridden for every request. */ +Partial<Record<'body' | 'headers' | 'method' | 'signal', never>>; + +/** Server content modalities. */ +export declare enum Modality { + /** + * The modality is unspecified. + */ + MODALITY_UNSPECIFIED = "MODALITY_UNSPECIFIED", + /** + * Indicates the model should return text + */ + TEXT = "TEXT", + /** + * Indicates the model should return images. + */ + IMAGE = "IMAGE", + /** + * Indicates the model should return audio. + */ + AUDIO = "AUDIO" +} + +/** Represents token counting info for a single modality. */ +export declare interface ModalityTokenCount { + /** The modality associated with this token count. */ + modality?: MediaModality; + /** Number of tokens. */ + tokenCount?: number; +} + +/** A trained machine learning model. */ +export declare interface Model { + /** Resource name of the model. */ + name?: string; + /** Display name of the model. */ + displayName?: string; + /** Description of the model. */ + description?: string; + /** Version ID of the model. A new version is committed when a new + model version is uploaded or trained under an existing model ID. The + version ID is an auto-incrementing decimal number in string + representation. */ + version?: string; + /** List of deployed models created from this base model. Note that a + model could have been deployed to endpoints in different locations. */ + endpoints?: Endpoint[]; + /** Labels with user-defined metadata to organize your models. */ + labels?: Record<string, string>; + /** Information about the tuned model from the base model. */ + tunedModelInfo?: TunedModelInfo; + /** The maximum number of input tokens that the model can handle. */ + inputTokenLimit?: number; + /** The maximum number of output tokens that the model can generate. */ + outputTokenLimit?: number; + /** List of actions that are supported by the model. */ + supportedActions?: string[]; + /** The default checkpoint id of a model version. + */ + defaultCheckpointId?: string; + /** The checkpoints of the model. */ + checkpoints?: Checkpoint[]; + /** Temperature value used for sampling set when the dataset was saved. + This value is used to tune the degree of randomness. */ + temperature?: number; + /** The maximum temperature value used for sampling set when the + dataset was saved. This value is used to tune the degree of randomness. */ + maxTemperature?: number; + /** Optional. Specifies the nucleus sampling threshold. The model + considers only the smallest set of tokens whose cumulative probability is + at least `top_p`. This helps generate more diverse and less repetitive + responses. For example, a `top_p` of 0.9 means the model considers tokens + until the cumulative probability of the tokens to select from reaches 0.9. + It's recommended to adjust either temperature or `top_p`, but not both. */ + topP?: number; + /** Optional. Specifies the top-k sampling threshold. The model + considers only the top k most probable tokens for the next token. This can + be useful for generating more coherent and less random text. For example, + a `top_k` of 40 means the model will choose the next word from the 40 most + likely words. */ + topK?: number; + /** Whether the model supports thinking features. If true, thoughts are + returned only if the model supports thought and thoughts are available. */ + thinking?: boolean; +} + +/** + * The model that will complete your prompt.\n\nSee [models](https://ai.google.dev/gemini-api/docs/models) for additional details. + */ +declare type Model_2 = 'gemini-2.5-flash' | 'gemini-2.5-flash-image' | 'gemini-2.5-flash-lite' | 'gemini-2.5-flash-lite-preview-09-2025' | 'gemini-2.5-flash-native-audio-preview-12-2025' | 'gemini-2.5-flash-preview-09-2025' | 'gemini-2.5-flash-preview-tts' | 'gemini-2.5-pro' | 'gemini-2.5-pro-preview-tts' | 'gemini-3-flash-preview' | 'gemini-3-pro-image-preview' | 'gemini-3-pro-preview' | (string & {}); + +/** Configuration for Model Armor integrations of prompt and responses. This data type is not supported in Gemini API. */ +export declare interface ModelArmorConfig { + /** Optional. The name of the Model Armor template to use for prompt sanitization. */ + promptTemplateName?: string; + /** Optional. The name of the Model Armor template to use for response sanitization. */ + responseTemplateName?: string; +} + +export declare class Models extends BaseModule { + private readonly apiClient; + constructor(apiClient: ApiClient); + /** + * Makes an API request to generate content with a given model. + * + * For the `model` parameter, supported formats for Vertex AI API include: + * - The Gemini model ID, for example: 'gemini-2.0-flash' + * - The full resource name starts with 'projects/', for example: + * 'projects/my-project-id/locations/us-central1/publishers/google/models/gemini-2.0-flash' + * - The partial resource name with 'publishers/', for example: + * 'publishers/google/models/gemini-2.0-flash' or + * 'publishers/meta/models/llama-3.1-405b-instruct-maas' + * - `/` separated publisher and model name, for example: + * 'google/gemini-2.0-flash' or 'meta/llama-3.1-405b-instruct-maas' + * + * For the `model` parameter, supported formats for Gemini API include: + * - The Gemini model ID, for example: 'gemini-2.0-flash' + * - The model name starts with 'models/', for example: + * 'models/gemini-2.0-flash' + * - For tuned models, the model name starts with 'tunedModels/', + * for example: + * 'tunedModels/1234567890123456789' + * + * Some models support multimodal input and output. + * + * @param params - The parameters for generating content. + * @return The response from generating content. + * + * @example + * ```ts + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: 'why is the sky blue?', + * config: { + * candidateCount: 2, + * } + * }); + * console.log(response); + * ``` + */ + generateContent: (params: types.GenerateContentParameters) => Promise<types.GenerateContentResponse>; + /** + * This logic is needed for GenerateContentConfig only. + * Previously we made GenerateContentConfig.responseSchema field to accept + * unknown. Since v1.9.0, we switch to use backend JSON schema support. + * To maintain backward compatibility, we move the data that was treated as + * JSON schema from the responseSchema field to the responseJsonSchema field. + */ + private maybeMoveToResponseJsonSchem; + /** + * Makes an API request to generate content with a given model and yields the + * response in chunks. + * + * For the `model` parameter, supported formats for Vertex AI API include: + * - The Gemini model ID, for example: 'gemini-2.0-flash' + * - The full resource name starts with 'projects/', for example: + * 'projects/my-project-id/locations/us-central1/publishers/google/models/gemini-2.0-flash' + * - The partial resource name with 'publishers/', for example: + * 'publishers/google/models/gemini-2.0-flash' or + * 'publishers/meta/models/llama-3.1-405b-instruct-maas' + * - `/` separated publisher and model name, for example: + * 'google/gemini-2.0-flash' or 'meta/llama-3.1-405b-instruct-maas' + * + * For the `model` parameter, supported formats for Gemini API include: + * - The Gemini model ID, for example: 'gemini-2.0-flash' + * - The model name starts with 'models/', for example: + * 'models/gemini-2.0-flash' + * - For tuned models, the model name starts with 'tunedModels/', + * for example: + * 'tunedModels/1234567890123456789' + * + * Some models support multimodal input and output. + * + * @param params - The parameters for generating content with streaming response. + * @return The response from generating content. + * + * @example + * ```ts + * const response = await ai.models.generateContentStream({ + * model: 'gemini-2.0-flash', + * contents: 'why is the sky blue?', + * config: { + * maxOutputTokens: 200, + * } + * }); + * for await (const chunk of response) { + * console.log(chunk); + * } + * ``` + */ + generateContentStream: (params: types.GenerateContentParameters) => Promise<AsyncGenerator<types.GenerateContentResponse>>; + /** + * Transforms the CallableTools in the parameters to be simply Tools, it + * copies the params into a new object and replaces the tools, it does not + * modify the original params. Also sets the MCP usage header if there are + * MCP tools in the parameters. + */ + private processParamsMaybeAddMcpUsage; + private initAfcToolsMap; + private processAfcStream; + /** + * Generates an image based on a text description and configuration. + * + * @param params - The parameters for generating images. + * @return The response from the API. + * + * @example + * ```ts + * const response = await client.models.generateImages({ + * model: 'imagen-4.0-generate-001', + * prompt: 'Robot holding a red skateboard', + * config: { + * numberOfImages: 1, + * includeRaiReason: true, + * }, + * }); + * console.log(response?.generatedImages?.[0]?.image?.imageBytes); + * ``` + */ + generateImages: (params: types.GenerateImagesParameters) => Promise<types.GenerateImagesResponse>; + list: (params?: types.ListModelsParameters) => Promise<Pager<types.Model>>; + /** + * Edits an image based on a prompt, list of reference images, and configuration. + * + * @param params - The parameters for editing an image. + * @return The response from the API. + * + * @example + * ```ts + * const response = await client.models.editImage({ + * model: 'imagen-3.0-capability-001', + * prompt: 'Generate an image containing a mug with the product logo [1] visible on the side of the mug.', + * referenceImages: [subjectReferenceImage] + * config: { + * numberOfImages: 1, + * includeRaiReason: true, + * }, + * }); + * console.log(response?.generatedImages?.[0]?.image?.imageBytes); + * ``` + */ + editImage: (params: types.EditImageParameters) => Promise<types.EditImageResponse>; + /** + * Upscales an image based on an image, upscale factor, and configuration. + * Only supported in Vertex AI currently. + * + * @param params - The parameters for upscaling an image. + * @return The response from the API. + * + * @example + * ```ts + * const response = await client.models.upscaleImage({ + * model: 'imagen-4.0-upscale-preview', + * image: image, + * upscaleFactor: 'x2', + * config: { + * includeRaiReason: true, + * }, + * }); + * console.log(response?.generatedImages?.[0]?.image?.imageBytes); + * ``` + */ + upscaleImage: (params: types.UpscaleImageParameters) => Promise<types.UpscaleImageResponse>; + /** + * Generates videos based on a text description and configuration. + * + * @param params - The parameters for generating videos. + * @return A Promise<GenerateVideosOperation> which allows you to track the progress and eventually retrieve the generated videos using the operations.get method. + * + * @example + * ```ts + * const operation = await ai.models.generateVideos({ + * model: 'veo-2.0-generate-001', + * source: { + * prompt: 'A neon hologram of a cat driving at top speed', + * }, + * config: { + * numberOfVideos: 1 + * }); + * + * while (!operation.done) { + * await new Promise(resolve => setTimeout(resolve, 10000)); + * operation = await ai.operations.getVideosOperation({operation: operation}); + * } + * + * console.log(operation.response?.generatedVideos?.[0]?.video?.uri); + * ``` + */ + generateVideos: (params: types.GenerateVideosParameters) => Promise<types.GenerateVideosOperation>; + private generateContentInternal; + private generateContentStreamInternal; + /** + * Calculates embeddings for the given contents. Only text is supported. + * + * @param params - The parameters for embedding contents. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.embedContent({ + * model: 'text-embedding-004', + * contents: [ + * 'What is your name?', + * 'What is your favorite color?', + * ], + * config: { + * outputDimensionality: 64, + * }, + * }); + * console.log(response); + * ``` + */ + embedContent(params: types.EmbedContentParameters): Promise<types.EmbedContentResponse>; + /** + * Private method for generating images. + */ + private generateImagesInternal; + /** + * Private method for editing an image. + */ + private editImageInternal; + /** + * Private method for upscaling an image. + */ + private upscaleImageInternal; + /** + * Recontextualizes an image. + * + * There are two types of recontextualization currently supported: + * 1) Imagen Product Recontext - Generate images of products in new scenes + * and contexts. + * 2) Virtual Try-On: Generate images of persons modeling fashion products. + * + * @param params - The parameters for recontextualizing an image. + * @return The response from the API. + * + * @example + * ```ts + * const response1 = await ai.models.recontextImage({ + * model: 'imagen-product-recontext-preview-06-30', + * source: { + * prompt: 'In a modern kitchen setting.', + * productImages: [productImage], + * }, + * config: { + * numberOfImages: 1, + * }, + * }); + * console.log(response1?.generatedImages?.[0]?.image?.imageBytes); + * + * const response2 = await ai.models.recontextImage({ + * model: 'virtual-try-on-001', + * source: { + * personImage: personImage, + * productImages: [productImage], + * }, + * config: { + * numberOfImages: 1, + * }, + * }); + * console.log(response2?.generatedImages?.[0]?.image?.imageBytes); + * ``` + */ + recontextImage(params: types.RecontextImageParameters): Promise<types.RecontextImageResponse>; + /** + * Segments an image, creating a mask of a specified area. + * + * @param params - The parameters for segmenting an image. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.segmentImage({ + * model: 'image-segmentation-001', + * source: { + * image: image, + * }, + * config: { + * mode: 'foreground', + * }, + * }); + * console.log(response?.generatedMasks?.[0]?.mask?.imageBytes); + * ``` + */ + segmentImage(params: types.SegmentImageParameters): Promise<types.SegmentImageResponse>; + /** + * Fetches information about a model by name. + * + * @example + * ```ts + * const modelInfo = await ai.models.get({model: 'gemini-2.0-flash'}); + * ``` + */ + get(params: types.GetModelParameters): Promise<types.Model>; + private listInternal; + /** + * Updates a tuned model by its name. + * + * @param params - The parameters for updating the model. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.update({ + * model: 'tuned-model-name', + * config: { + * displayName: 'New display name', + * description: 'New description', + * }, + * }); + * ``` + */ + update(params: types.UpdateModelParameters): Promise<types.Model>; + /** + * Deletes a tuned model by its name. + * + * @param params - The parameters for deleting the model. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.delete({model: 'tuned-model-name'}); + * ``` + */ + delete(params: types.DeleteModelParameters): Promise<types.DeleteModelResponse>; + /** + * Counts the number of tokens in the given contents. Multimodal input is + * supported for Gemini models. + * + * @param params - The parameters for counting tokens. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.countTokens({ + * model: 'gemini-2.0-flash', + * contents: 'The quick brown fox jumps over the lazy dog.' + * }); + * console.log(response); + * ``` + */ + countTokens(params: types.CountTokensParameters): Promise<types.CountTokensResponse>; + /** + * Given a list of contents, returns a corresponding TokensInfo containing + * the list of tokens and list of token ids. + * + * This method is not supported by the Gemini Developer API. + * + * @param params - The parameters for computing tokens. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.computeTokens({ + * model: 'gemini-2.0-flash', + * contents: 'What is your name?' + * }); + * console.log(response); + * ``` + */ + computeTokens(params: types.ComputeTokensParameters): Promise<types.ComputeTokensResponse>; + /** + * Private method for generating videos. + */ + private generateVideosInternal; +} + +/** Config for model selection. */ +export declare interface ModelSelectionConfig { + /** Options for feature selection preference. */ + featureSelectionPreference?: FeatureSelectionPreference; +} + +/** Configuration for a multi-speaker text-to-speech request. */ +export declare interface MultiSpeakerVoiceConfig { + /** Required. A list of configurations for the voices of the speakers. Exactly two speaker voice configurations must be provided. */ + speakerVoiceConfigs?: SpeakerVoiceConfig[]; +} + +/** The mode of music generation. */ +export declare enum MusicGenerationMode { + /** + * Rely on the server default generation mode. + */ + MUSIC_GENERATION_MODE_UNSPECIFIED = "MUSIC_GENERATION_MODE_UNSPECIFIED", + /** + * Steer text prompts to regions of latent space with higher quality + music. + */ + QUALITY = "QUALITY", + /** + * Steer text prompts to regions of latent space with a larger + diversity of music. + */ + DIVERSITY = "DIVERSITY", + /** + * Steer text prompts to regions of latent space more likely to + generate music with vocals. + */ + VOCALIZATION = "VOCALIZATION" +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/// <reference types="node" /> +/** + * Shims for types that we can't always rely on being available globally. + * + * Note: these only exist at the type-level, there is no corresponding runtime + * version for any of these symbols. + */ +declare type NeverToAny<T> = T extends never ? any : T; + +/** @ts-ignore For users with node-fetch@2 */ +declare type NodeFetch2RequestInit = NotAny<import('../node_modules/@types/node-fetch/index.d.ts').RequestInit> | NotAny<import('../../node_modules/@types/node-fetch/index.d.ts').RequestInit> | NotAny<import('../../../node_modules/@types/node-fetch/index.d.ts').RequestInit> | NotAny<import('../../../../node_modules/@types/node-fetch/index.d.ts').RequestInit> | NotAny<import('../../../../../node_modules/@types/node-fetch/index.d.ts').RequestInit> | NotAny<import('../../../../../../node_modules/@types/node-fetch/index.d.ts').RequestInit> | NotAny<import('../../../../../../../node_modules/@types/node-fetch/index.d.ts').RequestInit> | NotAny<import('../../../../../../../../node_modules/@types/node-fetch/index.d.ts').RequestInit> | NotAny<import('../../../../../../../../../node_modules/@types/node-fetch/index.d.ts').RequestInit> | NotAny<import('../../../../../../../../../../node_modules/@types/node-fetch/index.d.ts').RequestInit>; + +/** @ts-ignore For users with node-fetch@3, doesn't need file extension because types are at ./@types/index.d.ts */ +declare type NodeFetch3RequestInit = NotAny<import('../node_modules/node-fetch').RequestInit> | NotAny<import('../../node_modules/node-fetch').RequestInit> | NotAny<import('../../../node_modules/node-fetch').RequestInit> | NotAny<import('../../../../node_modules/node-fetch').RequestInit> | NotAny<import('../../../../../node_modules/node-fetch').RequestInit> | NotAny<import('../../../../../../node_modules/node-fetch').RequestInit> | NotAny<import('../../../../../../../node_modules/node-fetch').RequestInit> | NotAny<import('../../../../../../../../node_modules/node-fetch').RequestInit> | NotAny<import('../../../../../../../../../node_modules/node-fetch').RequestInit> | NotAny<import('../../../../../../../../../../node_modules/node-fetch').RequestInit>; + +/** @ts-ignore */ +declare type _NodeReadableStream<R = any> = ReadableStream_2<R>; + +declare type NotAny<T> = [0] extends [1 & T] ? never : T; + +declare class NotFoundError extends APIError<404, Headers> { +} + +/** + * @internal + * Users can pass explicit nulls to unset default headers. When we parse them + * into a standard headers type we need to preserve that information. + */ +declare type NullableHeaders = { + /** Brand check, prevent users from creating a NullableHeaders. */ + [brand_privateNullableHeaders]: true; + /** Parsed headers. */ + values: Headers; + /** Set of lowercase header names explicitly set to null. */ + nulls: Set<string>; +}; + +/** A long-running operation. */ +export declare interface Operation<T> { + /** The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`. */ + name?: string; + /** Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata. Any method that returns a long-running operation should document the metadata type, if any. */ + metadata?: Record<string, unknown>; + /** If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available. */ + done?: boolean; + /** The error result of the operation in case of failure or cancellation. */ + error?: Record<string, unknown>; + /** The response if the operation is successful. */ + response?: T; + /** + * Instantiates an Operation of the same type as the one being called with the fields set from the API response. + * @internal + */ + _fromAPIResponse({ apiResponse, _isVertexAI, }: OperationFromAPIResponseParameters): Operation<T>; +} + +/** Parameters of the fromAPIResponse method of the Operation class. */ +export declare interface OperationFromAPIResponseParameters { + /** The API response to be converted to an Operation. */ + apiResponse: Record<string, unknown>; + /** Whether the API response is from Vertex AI. */ + _isVertexAI: boolean; +} + +/** Parameters for the get method of the operations module. */ +export declare interface OperationGetParameters<T, U extends Operation<T>> { + /** Used to override the default configuration. */ + config?: GetOperationConfig; + /** The operation to be retrieved. */ + operation: U; +} + +export declare class Operations extends BaseModule { + private readonly apiClient; + constructor(apiClient: ApiClient); + /** + * Gets the status of a long-running operation. + * + * @param parameters The parameters for the get operation request. + * @return The updated Operation object, with the latest status or result. + */ + getVideosOperation(parameters: types.OperationGetParameters<types.GenerateVideosResponse, types.GenerateVideosOperation>): Promise<types.GenerateVideosOperation>; + /** + * Gets the status of a long-running operation. + * + * @param parameters The parameters for the get operation request. + * @return The updated Operation object, with the latest status or result. + */ + get<T, U extends types.Operation<T>>(parameters: types.OperationGetParameters<T, U>): Promise<types.Operation<T>>; + private getVideosOperationInternal; + private fetchPredictVideosOperationInternal; +} + +/** Outcome of the code execution. */ +export declare enum Outcome { + /** + * Unspecified status. This value should not be used. + */ + OUTCOME_UNSPECIFIED = "OUTCOME_UNSPECIFIED", + /** + * Code execution completed successfully. + */ + OUTCOME_OK = "OUTCOME_OK", + /** + * Code execution finished but with a failure. `stderr` should contain the reason. + */ + OUTCOME_FAILED = "OUTCOME_FAILED", + /** + * Code execution ran for too long, and was cancelled. There may or may not be a partial output present. + */ + OUTCOME_DEADLINE_EXCEEDED = "OUTCOME_DEADLINE_EXCEEDED" +} + +/** + * Some environments overload the global fetch function, and Parameters<T> only gets the last signature. + */ +declare type OverloadedParameters<T> = T extends ({ + (...args: infer A): unknown; + (...args: infer B): unknown; + (...args: infer C): unknown; + (...args: infer D): unknown; +}) ? A | B | C | D : T extends ({ + (...args: infer A): unknown; + (...args: infer B): unknown; + (...args: infer C): unknown; +}) ? A | B | C : T extends ({ + (...args: infer A): unknown; + (...args: infer B): unknown; +}) ? A | B : T extends (...args: infer A) => unknown ? A : never; + +export declare enum PagedItem { + PAGED_ITEM_BATCH_JOBS = "batchJobs", + PAGED_ITEM_MODELS = "models", + PAGED_ITEM_TUNING_JOBS = "tuningJobs", + PAGED_ITEM_FILES = "files", + PAGED_ITEM_CACHED_CONTENTS = "cachedContents", + PAGED_ITEM_FILE_SEARCH_STORES = "fileSearchStores", + PAGED_ITEM_DOCUMENTS = "documents" +} + +declare interface PagedItemConfig { + parent?: string; + config?: { + pageToken?: string; + pageSize?: number; + }; +} + +declare interface PagedItemResponse<T> { + nextPageToken?: string; + sdkHttpResponse?: types.HttpResponse; + batchJobs?: T[]; + models?: T[]; + tuningJobs?: T[]; + files?: T[]; + cachedContents?: T[]; + fileSearchStores?: T[]; + documents?: T[]; +} + +/** + * Pager class for iterating through paginated results. + */ +export declare class Pager<T> implements AsyncIterable<T> { + private nameInternal; + private pageInternal; + private paramsInternal; + private pageInternalSize; + private sdkHttpResponseInternal?; + protected requestInternal: (params: PagedItemConfig) => Promise<PagedItemResponse<T>>; + protected idxInternal: number; + constructor(name: PagedItem, request: (params: PagedItemConfig) => Promise<PagedItemResponse<T>>, response: PagedItemResponse<T>, params: PagedItemConfig); + private init; + private initNextPage; + /** + * Returns the current page, which is a list of items. + * + * @remarks + * The first page is retrieved when the pager is created. The returned list of + * items could be a subset of the entire list. + */ + get page(): T[]; + /** + * Returns the type of paged item (for example, ``batch_jobs``). + */ + get name(): PagedItem; + /** + * Returns the length of the page fetched each time by this pager. + * + * @remarks + * The number of items in the page is less than or equal to the page length. + */ + get pageSize(): number; + /** + * Returns the headers of the API response. + */ + get sdkHttpResponse(): types.HttpResponse | undefined; + /** + * Returns the parameters when making the API request for the next page. + * + * @remarks + * Parameters contain a set of optional configs that can be + * used to customize the API request. For example, the `pageToken` parameter + * contains the token to request the next page. + */ + get params(): PagedItemConfig; + /** + * Returns the total number of items in the current page. + */ + get pageLength(): number; + /** + * Returns the item at the given index. + */ + getItem(index: number): T; + /** + * Returns an async iterator that support iterating through all items + * retrieved from the API. + * + * @remarks + * The iterator will automatically fetch the next page if there are more items + * to fetch from the API. + * + * @example + * + * ```ts + * const pager = await ai.files.list({config: {pageSize: 10}}); + * for await (const file of pager) { + * console.log(file.name); + * } + * ``` + */ + [Symbol.asyncIterator](): AsyncIterator<T>; + /** + * Fetches the next page of items. This makes a new API request. + * + * @throws {Error} If there are no more pages to fetch. + * + * @example + * + * ```ts + * const pager = await ai.files.list({config: {pageSize: 10}}); + * let page = pager.page; + * while (true) { + * for (const file of page) { + * console.log(file.name); + * } + * if (!pager.hasNextPage()) { + * break; + * } + * page = await pager.nextPage(); + * } + * ``` + */ + nextPage(): Promise<T[]>; + /** + * Returns true if there are more pages to fetch from the API. + */ + hasNextPage(): boolean; +} + +/** A datatype containing media content. + + Exactly one field within a Part should be set, representing the specific type + of content being conveyed. Using multiple fields within the same `Part` + instance is considered invalid. */ +export declare interface Part { + /** Media resolution for the input media. + */ + mediaResolution?: PartMediaResolution; + /** Optional. Result of executing the [ExecutableCode]. */ + codeExecutionResult?: CodeExecutionResult; + /** Optional. Code generated by the model that is meant to be executed. */ + executableCode?: ExecutableCode; + /** Optional. URI based data. */ + fileData?: FileData; + /** Optional. A predicted [FunctionCall] returned from the model that contains a string representing the [FunctionDeclaration.name] with the parameters and their values. */ + functionCall?: FunctionCall; + /** Optional. The result output of a [FunctionCall] that contains a string representing the [FunctionDeclaration.name] and a structured JSON object containing any output from the function call. It is used as context to the model. */ + functionResponse?: FunctionResponse; + /** Optional. Inlined bytes data. */ + inlineData?: Blob_2; + /** Optional. Text part (can be code). */ + text?: string; + /** Optional. Indicates if the part is thought from the model. */ + thought?: boolean; + /** Optional. An opaque signature for the thought so it can be reused in subsequent requests. + * @remarks Encoded as base64 string. */ + thoughtSignature?: string; + /** Optional. Video metadata. The metadata should only be specified while the video data is presented in inline_data or file_data. */ + videoMetadata?: VideoMetadata; +} + +/** Partial argument value of the function call. This data type is not supported in Gemini API. */ +export declare interface PartialArg { + /** Optional. Represents a null value. */ + nullValue?: 'NULL_VALUE'; + /** Optional. Represents a double value. */ + numberValue?: number; + /** Optional. Represents a string value. */ + stringValue?: string; + /** Optional. Represents a boolean value. */ + boolValue?: boolean; + /** Required. A JSON Path (RFC 9535) to the argument being streamed. https://datatracker.ietf.org/doc/html/rfc9535. e.g. "$.foo.bar[0].data". */ + jsonPath?: string; + /** Optional. Whether this is not the last part of the same json_path. If true, another PartialArg message for the current json_path is expected to follow. */ + willContinue?: boolean; +} + +export declare type PartListUnion = PartUnion[] | PartUnion; + +/** Media resolution for the input media. */ +export declare interface PartMediaResolution { + /** The tokenization quality used for given media. + */ + level?: PartMediaResolutionLevel; + /** Specifies the required sequence length for media tokenization. + */ + numTokens?: number; +} + +/** The tokenization quality used for given media. */ +export declare enum PartMediaResolutionLevel { + /** + * Media resolution has not been set. + */ + MEDIA_RESOLUTION_UNSPECIFIED = "MEDIA_RESOLUTION_UNSPECIFIED", + /** + * Media resolution set to low. + */ + MEDIA_RESOLUTION_LOW = "MEDIA_RESOLUTION_LOW", + /** + * Media resolution set to medium. + */ + MEDIA_RESOLUTION_MEDIUM = "MEDIA_RESOLUTION_MEDIUM", + /** + * Media resolution set to high. + */ + MEDIA_RESOLUTION_HIGH = "MEDIA_RESOLUTION_HIGH", + /** + * Media resolution set to ultra high. + */ + MEDIA_RESOLUTION_ULTRA_HIGH = "MEDIA_RESOLUTION_ULTRA_HIGH" +} + +/** Tuning spec for Partner models. This data type is not supported in Gemini API. */ +export declare interface PartnerModelTuningSpec { + /** Hyperparameters for tuning. The accepted hyper_parameters and their valid range of values will differ depending on the base model. */ + hyperParameters?: Record<string, unknown>; + /** Required. Cloud Storage path to file containing training dataset for tuning. The dataset must be formatted as a JSONL file. */ + trainingDatasetUri?: string; + /** Optional. Cloud Storage path to file containing validation dataset for tuning. The dataset must be formatted as a JSONL file. */ + validationDatasetUri?: string; +} + +export declare type PartUnion = Part | string; + +declare class PermissionDeniedError extends APIError<403, Headers> { +} + +/** Enum that controls the generation of people. */ +export declare enum PersonGeneration { + /** + * Block generation of images of people. + */ + DONT_ALLOW = "DONT_ALLOW", + /** + * Generate images of adults, but not children. + */ + ALLOW_ADULT = "ALLOW_ADULT", + /** + * Generate images that include adults and children. + */ + ALLOW_ALL = "ALLOW_ALL" +} + +/** Sites with confidence level chosen & above this value will be blocked from the search results. This enum is not supported in Gemini API. */ +export declare enum PhishBlockThreshold { + /** + * Defaults to unspecified. + */ + PHISH_BLOCK_THRESHOLD_UNSPECIFIED = "PHISH_BLOCK_THRESHOLD_UNSPECIFIED", + /** + * Blocks Low and above confidence URL that is risky. + */ + BLOCK_LOW_AND_ABOVE = "BLOCK_LOW_AND_ABOVE", + /** + * Blocks Medium and above confidence URL that is risky. + */ + BLOCK_MEDIUM_AND_ABOVE = "BLOCK_MEDIUM_AND_ABOVE", + /** + * Blocks High and above confidence URL that is risky. + */ + BLOCK_HIGH_AND_ABOVE = "BLOCK_HIGH_AND_ABOVE", + /** + * Blocks Higher and above confidence URL that is risky. + */ + BLOCK_HIGHER_AND_ABOVE = "BLOCK_HIGHER_AND_ABOVE", + /** + * Blocks Very high and above confidence URL that is risky. + */ + BLOCK_VERY_HIGH_AND_ABOVE = "BLOCK_VERY_HIGH_AND_ABOVE", + /** + * Blocks Extremely high confidence URL that is risky. + */ + BLOCK_ONLY_EXTREMELY_HIGH = "BLOCK_ONLY_EXTREMELY_HIGH" +} + +/** The configuration for the prebuilt speaker to use. */ +export declare interface PrebuiltVoiceConfig { + /** The name of the preset voice to use. */ + voiceName?: string; +} + +/** Statistics computed for datasets used for preference optimization. This data type is not supported in Gemini API. */ +export declare interface PreferenceOptimizationDataStats { + /** Output only. Dataset distributions for scores variance per example. */ + scoreVariancePerExampleDistribution?: DatasetDistribution; + /** Output only. Dataset distributions for scores. */ + scoresDistribution?: DatasetDistribution; + /** Output only. Number of billable tokens in the tuning dataset. */ + totalBillableTokenCount?: string; + /** Output only. Number of examples in the tuning dataset. */ + tuningDatasetExampleCount?: string; + /** Output only. Number of tuning steps for this Tuning Job. */ + tuningStepCount?: string; + /** Output only. Sample user examples in the training dataset. */ + userDatasetExamples?: GeminiPreferenceExample[]; + /** Output only. Dataset distributions for the user input tokens. */ + userInputTokenDistribution?: DatasetDistribution; + /** Output only. Dataset distributions for the user output tokens. */ + userOutputTokenDistribution?: DatasetDistribution; +} + +/** Hyperparameters for Preference Optimization. This data type is not supported in Gemini API. */ +export declare interface PreferenceOptimizationHyperParameters { + /** Optional. Adapter size for preference optimization. */ + adapterSize?: AdapterSize; + /** Optional. Weight for KL Divergence regularization. */ + beta?: number; + /** Optional. Number of complete passes the model makes over the entire training dataset during training. */ + epochCount?: string; + /** Optional. Multiplier for adjusting the default learning rate. */ + learningRateMultiplier?: number; +} + +/** Preference optimization tuning spec for tuning. */ +export declare interface PreferenceOptimizationSpec { + /** Optional. If set to true, disable intermediate checkpoints for Preference Optimization and only the last checkpoint will be exported. Otherwise, enable intermediate checkpoints for Preference Optimization. Default is false. */ + exportLastCheckpointOnly?: boolean; + /** Optional. Hyperparameters for Preference Optimization. */ + hyperParameters?: PreferenceOptimizationHyperParameters; + /** Required. Cloud Storage path to file containing training dataset for preference optimization tuning. The dataset must be formatted as a JSONL file. */ + trainingDatasetUri?: string; + /** Optional. Cloud Storage path to file containing validation dataset for preference optimization tuning. The dataset must be formatted as a JSONL file. */ + validationDatasetUri?: string; +} + +/** A pre-tuned model for continuous tuning. This data type is not supported in Gemini API. */ +export declare interface PreTunedModel { + /** Output only. The name of the base model this PreTunedModel was tuned from. */ + baseModel?: string; + /** Optional. The source checkpoint id. If not specified, the default checkpoint will be used. */ + checkpointId?: string; + /** The resource name of the Model. E.g., a model resource name with a specified version id or alias: `projects/{project}/locations/{location}/models/{model}@{version_id}` `projects/{project}/locations/{location}/models/{model}@{alias}` Or, omit the version id to use the default version: `projects/{project}/locations/{location}/models/{model}` */ + tunedModelName?: string; +} + +/** Config for proactivity features. */ +export declare interface ProactivityConfig { + /** If enabled, the model can reject responding to the last prompt. For + example, this allows the model to ignore out of context speech or to stay + silent if the user did not make a request, yet. */ + proactiveAudio?: boolean; +} + +/** An image of the product. */ +export declare interface ProductImage { + /** An image of the product to be recontextualized. */ + productImage?: Image_2; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +declare type PromiseOrValue<T> = T | Promise<T>; + +/** A RagChunk includes the content of a chunk of a RagFile, and associated metadata. This data type is not supported in Gemini API. */ +export declare interface RagChunk { + /** If populated, represents where the chunk starts and ends in the document. */ + pageSpan?: RagChunkPageSpan; + /** The content of the chunk. */ + text?: string; +} + +/** Represents where the chunk starts and ends in the document. This data type is not supported in Gemini API. */ +export declare interface RagChunkPageSpan { + /** Page where chunk starts in the document. Inclusive. 1-indexed. */ + firstPage?: number; + /** Page where chunk ends in the document. Inclusive. 1-indexed. */ + lastPage?: number; +} + +/** Specifies the context retrieval config. This data type is not supported in Gemini API. */ +export declare interface RagRetrievalConfig { + /** Optional. Config for filters. */ + filter?: RagRetrievalConfigFilter; + /** Optional. Config for Hybrid Search. */ + hybridSearch?: RagRetrievalConfigHybridSearch; + /** Optional. Config for ranking and reranking. */ + ranking?: RagRetrievalConfigRanking; + /** Optional. The number of contexts to retrieve. */ + topK?: number; +} + +/** Config for filters. This data type is not supported in Gemini API. */ +export declare interface RagRetrievalConfigFilter { + /** Optional. String for metadata filtering. */ + metadataFilter?: string; + /** Optional. Only returns contexts with vector distance smaller than the threshold. */ + vectorDistanceThreshold?: number; + /** Optional. Only returns contexts with vector similarity larger than the threshold. */ + vectorSimilarityThreshold?: number; +} + +/** Config for Hybrid Search. This data type is not supported in Gemini API. */ +export declare interface RagRetrievalConfigHybridSearch { + /** Optional. Alpha value controls the weight between dense and sparse vector search results. The range is [0, 1], while 0 means sparse vector search only and 1 means dense vector search only. The default value is 0.5 which balances sparse and dense vector search equally. */ + alpha?: number; +} + +/** Config for ranking and reranking. This data type is not supported in Gemini API. */ +export declare interface RagRetrievalConfigRanking { + /** Optional. Config for LlmRanker. */ + llmRanker?: RagRetrievalConfigRankingLlmRanker; + /** Optional. Config for Rank Service. */ + rankService?: RagRetrievalConfigRankingRankService; +} + +/** Config for LlmRanker. This data type is not supported in Gemini API. */ +export declare interface RagRetrievalConfigRankingLlmRanker { + /** Optional. The model name used for ranking. See [Supported models](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference#supported-models). */ + modelName?: string; +} + +/** Config for Rank Service. This data type is not supported in Gemini API. */ +export declare interface RagRetrievalConfigRankingRankService { + /** Optional. The model name of the rank service. Format: `semantic-ranker-512@latest` */ + modelName?: string; +} + +declare class RateLimitError extends APIError<429, Headers> { +} + +/** A raw reference image. + + A raw reference image represents the base image to edit, provided by the user. + It can optionally be provided in addition to a mask reference image or + a style reference image. */ +export declare class RawReferenceImage { + /** The reference image for the editing operation. */ + referenceImage?: Image_2; + /** The id of the reference image. */ + referenceId?: number; + /** The type of the reference image. Only set by the SDK. */ + referenceType?: string; + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI(): ReferenceImageAPIInternal; +} + +declare type _ReadableStream_2<R = any> = NeverToAny<([0] extends [1 & _DOMReadableStream<R>] ? never : _DOMReadableStream<R>) | ([0] extends [1 & _ConditionalNodeReadableStream<R>] ? never : _ConditionalNodeReadableStream<R>)>; + +/** Marks the end of user activity. + + This can only be sent if automatic (i.e. server-side) activity detection is + disabled. */ +export declare interface RealtimeInputConfig { + /** If not set, automatic activity detection is enabled by default. If automatic voice detection is disabled, the client must send activity signals. */ + automaticActivityDetection?: AutomaticActivityDetection; + /** Defines what effect activity has. */ + activityHandling?: ActivityHandling; + /** Defines which input is included in the user's turn. */ + turnCoverage?: TurnCoverage; +} + +/** Configuration for recontextualizing an image. */ +export declare interface RecontextImageConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** Number of images to generate. */ + numberOfImages?: number; + /** The number of sampling steps. A higher value has better image + quality, while a lower value has better latency. */ + baseSteps?: number; + /** Cloud Storage URI used to store the generated images. */ + outputGcsUri?: string; + /** Random seed for image generation. */ + seed?: number; + /** Filter level for safety filtering. */ + safetyFilterLevel?: SafetyFilterLevel; + /** Whether allow to generate person images, and restrict to specific + ages. */ + personGeneration?: PersonGeneration; + /** Whether to add a SynthID watermark to the generated images. */ + addWatermark?: boolean; + /** MIME type of the generated image. */ + outputMimeType?: string; + /** Compression quality of the generated image (for ``image/jpeg`` + only). */ + outputCompressionQuality?: number; + /** Whether to use the prompt rewriting logic. */ + enhancePrompt?: boolean; + /** User specified labels to track billing usage. */ + labels?: Record<string, string>; +} + +/** The parameters for recontextualizing an image. */ +export declare interface RecontextImageParameters { + /** ID of the model to use. For a list of models, see `Google models + <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */ + model: string; + /** A set of source input(s) for image recontextualization. */ + source: RecontextImageSource; + /** Configuration for image recontextualization. */ + config?: RecontextImageConfig; +} + +/** The output images response. */ +export declare class RecontextImageResponse { + /** List of generated images. */ + generatedImages?: GeneratedImage[]; +} + +/** A set of source input(s) for image recontextualization. */ +export declare interface RecontextImageSource { + /** A text prompt for guiding the model during image + recontextualization. Not supported for Virtual Try-On. */ + prompt?: string; + /** Image of the person or subject who will be wearing the + product(s). */ + personImage?: Image_2; + /** A list of product images. */ + productImages?: ProductImage[]; +} + +export declare type ReferenceImage = RawReferenceImage | MaskReferenceImage | ControlReferenceImage | StyleReferenceImage | SubjectReferenceImage | ContentReferenceImage; + +/** Private class that represents a Reference image that is sent to API. */ +declare interface ReferenceImageAPIInternal { + /** The reference image for the editing operation. */ + referenceImage?: types.Image; + /** The id of the reference image. */ + referenceId?: number; + /** The type of the reference image. Only set by the SDK. */ + referenceType?: string; + /** Configuration for the mask reference image. */ + maskImageConfig?: types.MaskReferenceConfig; + /** Configuration for the control reference image. */ + controlImageConfig?: types.ControlReferenceConfig; + /** Configuration for the style reference image. */ + styleImageConfig?: types.StyleReferenceConfig; + /** Configuration for the subject reference image. */ + subjectImageConfig?: types.SubjectReferenceConfig; +} + +/** Used to override the default configuration. */ +export declare interface RegisterFilesConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Generates the parameters for the private registerFiles method. */ +export declare interface RegisterFilesParameters { + /** + * The authentication object. + */ + auth?: any; + /** + * The Google Cloud Storage URIs to register. Example: `gs://bucket/object`. + */ + uris: string[]; + /** Used to override the default configuration. */ + config?: RegisterFilesConfig; +} + +/** Response for the _register file method. */ +export declare class RegisterFilesResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** The registered files. */ + files?: File_2[]; +} + +/** Represents a recorded session. */ +export declare interface ReplayFile { + replayId?: string; + interactions?: ReplayInteraction[]; +} + +/** Represents a single interaction, request and response in a replay. */ +export declare interface ReplayInteraction { + request?: ReplayRequest; + response?: ReplayResponse; +} + +/** Represents a single request in a replay. */ +export declare interface ReplayRequest { + method?: string; + url?: string; + headers?: Record<string, string>; + bodySegments?: Record<string, unknown>[]; +} + +/** Represents a single response in a replay. */ +export declare class ReplayResponse { + statusCode?: number; + headers?: Record<string, string>; + bodySegments?: Record<string, unknown>[]; + sdkResponseSegments?: Record<string, unknown>[]; +} + +/** ReplicatedVoiceConfig is used to configure replicated voice. */ +export declare interface ReplicatedVoiceConfig { + /** The mime type of the replicated voice. + */ + mimeType?: string; + /** The sample audio of the replicated voice. + + * @remarks Encoded as base64 string. */ + voiceSampleAudio?: string; +} + +/** + * The type for the first argument to `fetch`. + * + * https://developer.mozilla.org/docs/Web/API/Window/fetch#resource + */ +declare type _RequestInfo = Request | URL | string; + +/** + * An alias to the builtin `RequestInit` type so we can + * easily alias it in import statements if there are name clashes. + * + * https://developer.mozilla.org/docs/Web/API/RequestInit + */ +declare type _RequestInit = RequestInit; + +declare type RequestInits = NotAny<UndiciTypesRequestInit> | NotAny<UndiciRequestInit> | NotAny<BunRequestInit> | NotAny<NodeFetch2RequestInit> | NotAny<NodeFetch3RequestInit> | NotAny<RequestInit> | NotAny<FetchRequestInit>; + +declare type RequestOptions = { + /** + * The HTTP method for the request (e.g., 'get', 'post', 'put', 'delete'). + */ + method?: HTTPMethod; + /** + * The URL path for the request. + * + * @example "/v1/foo" + */ + path?: string; + /** + * Query parameters to include in the request URL. + */ + query?: object | undefined | null; + /** + * The request body. Can be a string, JSON object, FormData, or other supported types. + */ + body?: unknown; + /** + * HTTP headers to include with the request. Can be a Headers object, plain object, or array of tuples. + */ + headers?: HeadersLike; + /** + * The maximum number of times that the client will retry a request in case of a + * temporary failure, like a network error or a 5XX error from the server. + * + * @default 2 + */ + maxRetries?: number; + stream?: boolean | undefined; + /** + * The maximum amount of time (in milliseconds) that the client should wait for a response + * from the server before timing out a single request. + * + * @unit milliseconds + */ + timeout?: number; + /** + * Additional `RequestInit` options to be passed to the underlying `fetch` call. + * These options will be merged with the client's default fetch options. + */ + fetchOptions?: MergedRequestInit; + /** + * An AbortSignal that can be used to cancel the request. + */ + signal?: AbortSignal | undefined | null; + /** + * A unique key for this request to enable idempotency. + */ + idempotencyKey?: string; + /** + * Override the default base URL for this specific request. + */ + defaultBaseURL?: string | undefined; + __binaryResponse?: boolean | undefined; + __streamClass?: typeof Stream; +}; + +/** Resource scope. */ +export declare enum ResourceScope { + /** + * When setting base_url, this value configures resource scope to be the collection. + The resource name will not include api version, project, or location. + For example, if base_url is set to "https://aiplatform.googleapis.com", + then the resource name for a Model would be + "https://aiplatform.googleapis.com/publishers/google/models/gemini-3-pro-preview + */ + COLLECTION = "COLLECTION" +} + +/** Defines a retrieval tool that model can call to access external knowledge. This data type is not supported in Gemini API. */ +export declare interface Retrieval { + /** Optional. Deprecated. This option is no longer supported. */ + disableAttribution?: boolean; + /** Use data source powered by external API for grounding. */ + externalApi?: ExternalApi; + /** Set to use data source powered by Vertex AI Search. */ + vertexAiSearch?: VertexAISearch; + /** Set to use data source powered by Vertex RAG store. User data is uploaded via the VertexRagDataService. */ + vertexRagStore?: VertexRagStore; +} + +/** Retrieval config. + */ +export declare interface RetrievalConfig { + /** Optional. The location of the user. */ + latLng?: LatLng; + /** The language code of the user. */ + languageCode?: string; +} + +/** Metadata related to retrieval in the grounding flow. */ +export declare interface RetrievalMetadata { + /** Optional. Score indicating how likely information from Google Search could help answer the prompt. The score is in the range `[0, 1]`, where 0 is the least likely and 1 is the most likely. This score is only populated when Google Search grounding and dynamic retrieval is enabled. It will be compared to the threshold to determine whether to trigger Google Search. */ + googleSearchDynamicRetrievalScore?: number; +} + +/** Safety attributes of a GeneratedImage or the user-provided prompt. */ +export declare interface SafetyAttributes { + /** List of RAI categories. */ + categories?: string[]; + /** List of scores of each categories. */ + scores?: number[]; + /** Internal use only. */ + contentType?: string; +} + +/** Enum that controls the safety filter level for objectionable content. */ +export declare enum SafetyFilterLevel { + BLOCK_LOW_AND_ABOVE = "BLOCK_LOW_AND_ABOVE", + BLOCK_MEDIUM_AND_ABOVE = "BLOCK_MEDIUM_AND_ABOVE", + BLOCK_ONLY_HIGH = "BLOCK_ONLY_HIGH", + BLOCK_NONE = "BLOCK_NONE" +} + +/** Safety rating corresponding to the generated content. */ +export declare interface SafetyRating { + /** Output only. Indicates whether the content was filtered out because of this rating. */ + blocked?: boolean; + /** Output only. Harm category. */ + category?: HarmCategory; + /** Output only. The overwritten threshold for the safety category of Gemini 2.0 image out. If minors are detected in the output image, the threshold of each safety category will be overwritten if user sets a lower threshold. This field is not supported in Gemini API. */ + overwrittenThreshold?: HarmBlockThreshold; + /** Output only. Harm probability levels in the content. */ + probability?: HarmProbability; + /** Output only. Harm probability score. This field is not supported in Gemini API. */ + probabilityScore?: number; + /** Output only. Harm severity levels in the content. This field is not supported in Gemini API. */ + severity?: HarmSeverity; + /** Output only. Harm severity score. This field is not supported in Gemini API. */ + severityScore?: number; +} + +/** Safety settings. */ +export declare interface SafetySetting { + /** Required. Harm category. */ + category?: HarmCategory; + /** Optional. Specify if the threshold is used for probability or severity score. If not specified, the threshold is used for probability score. This field is not supported in Gemini API. */ + method?: HarmBlockMethod; + /** Required. The harm block threshold. */ + threshold?: HarmBlockThreshold; +} + +/** Scale of the generated music. */ +export declare enum Scale { + /** + * Default value. This value is unused. + */ + SCALE_UNSPECIFIED = "SCALE_UNSPECIFIED", + /** + * C major or A minor. + */ + C_MAJOR_A_MINOR = "C_MAJOR_A_MINOR", + /** + * Db major or Bb minor. + */ + D_FLAT_MAJOR_B_FLAT_MINOR = "D_FLAT_MAJOR_B_FLAT_MINOR", + /** + * D major or B minor. + */ + D_MAJOR_B_MINOR = "D_MAJOR_B_MINOR", + /** + * Eb major or C minor + */ + E_FLAT_MAJOR_C_MINOR = "E_FLAT_MAJOR_C_MINOR", + /** + * E major or Db minor. + */ + E_MAJOR_D_FLAT_MINOR = "E_MAJOR_D_FLAT_MINOR", + /** + * F major or D minor. + */ + F_MAJOR_D_MINOR = "F_MAJOR_D_MINOR", + /** + * Gb major or Eb minor. + */ + G_FLAT_MAJOR_E_FLAT_MINOR = "G_FLAT_MAJOR_E_FLAT_MINOR", + /** + * G major or E minor. + */ + G_MAJOR_E_MINOR = "G_MAJOR_E_MINOR", + /** + * Ab major or F minor. + */ + A_FLAT_MAJOR_F_MINOR = "A_FLAT_MAJOR_F_MINOR", + /** + * A major or Gb minor. + */ + A_MAJOR_G_FLAT_MINOR = "A_MAJOR_G_FLAT_MINOR", + /** + * Bb major or G minor. + */ + B_FLAT_MAJOR_G_MINOR = "B_FLAT_MAJOR_G_MINOR", + /** + * B major or Ab minor. + */ + B_MAJOR_A_FLAT_MINOR = "B_MAJOR_A_FLAT_MINOR" +} + +/** Schema is used to define the format of input/output data. + + Represents a select subset of an [OpenAPI 3.0 schema + object](https://spec.openapis.org/oas/v3.0.3#schema-object). More fields may + be added in the future as needed. */ +export declare interface Schema { + /** Optional. The value should be validated against any (one or more) of the subschemas in the list. */ + anyOf?: Schema[]; + /** Optional. Default value of the data. */ + default?: unknown; + /** Optional. The description of the data. */ + description?: string; + /** Optional. Possible values of the element of primitive type with enum format. Examples: 1. We can define direction as : {type:STRING, format:enum, enum:["EAST", NORTH", "SOUTH", "WEST"]} 2. We can define apartment number as : {type:INTEGER, format:enum, enum:["101", "201", "301"]} */ + enum?: string[]; + /** Optional. Example of the object. Will only populated when the object is the root. */ + example?: unknown; + /** Optional. The format of the data. Supported formats: for NUMBER type: "float", "double" for INTEGER type: "int32", "int64" for STRING type: "email", "byte", etc */ + format?: string; + /** Optional. SCHEMA FIELDS FOR TYPE ARRAY Schema of the elements of Type.ARRAY. */ + items?: Schema; + /** Optional. Maximum number of the elements for Type.ARRAY. */ + maxItems?: string; + /** Optional. Maximum length of the Type.STRING */ + maxLength?: string; + /** Optional. Maximum number of the properties for Type.OBJECT. */ + maxProperties?: string; + /** Optional. Maximum value of the Type.INTEGER and Type.NUMBER */ + maximum?: number; + /** Optional. Minimum number of the elements for Type.ARRAY. */ + minItems?: string; + /** Optional. SCHEMA FIELDS FOR TYPE STRING Minimum length of the Type.STRING */ + minLength?: string; + /** Optional. Minimum number of the properties for Type.OBJECT. */ + minProperties?: string; + /** Optional. SCHEMA FIELDS FOR TYPE INTEGER and NUMBER Minimum value of the Type.INTEGER and Type.NUMBER */ + minimum?: number; + /** Optional. Indicates if the value may be null. */ + nullable?: boolean; + /** Optional. Pattern of the Type.STRING to restrict a string to a regular expression. */ + pattern?: string; + /** Optional. SCHEMA FIELDS FOR TYPE OBJECT Properties of Type.OBJECT. */ + properties?: Record<string, Schema>; + /** Optional. The order of the properties. Not a standard field in open api spec. Only used to support the order of the properties. */ + propertyOrdering?: string[]; + /** Optional. Required properties of Type.OBJECT. */ + required?: string[]; + /** Optional. The title of the Schema. */ + title?: string; + /** Optional. The type of the data. */ + type?: Type; +} + +export declare type SchemaUnion = Schema | unknown; + +/** An image mask representing a brush scribble. */ +export declare interface ScribbleImage { + /** The brush scribble to guide segmentation. Valid for the interactive mode. */ + image?: Image_2; +} + +/** Google search entry point. */ +export declare interface SearchEntryPoint { + /** Optional. Web content snippet that can be embedded in a web page or an app webview. */ + renderedContent?: string; + /** Optional. Base64 encoded JSON representing array of tuple. + * @remarks Encoded as base64 string. */ + sdkBlob?: string; +} + +/** Segment of the content. */ +export declare interface Segment { + /** Output only. End index in the given Part, measured in bytes. Offset from the start of the Part, exclusive, starting at zero. */ + endIndex?: number; + /** Output only. The index of a Part object within its parent Content object. */ + partIndex?: number; + /** Output only. Start index in the given Part, measured in bytes. Offset from the start of the Part, inclusive, starting at zero. */ + startIndex?: number; + /** Output only. The text corresponding to the segment from the response. */ + text?: string; +} + +/** Configuration for segmenting an image. */ +export declare interface SegmentImageConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** The segmentation mode to use. */ + mode?: SegmentMode; + /** The maximum number of predictions to return up to, by top + confidence score. */ + maxPredictions?: number; + /** The confidence score threshold for the detections as a decimal + value. Only predictions with a confidence score higher than this + threshold will be returned. */ + confidenceThreshold?: number; + /** A decimal value representing how much dilation to apply to the + masks. 0 for no dilation. 1.0 means the masked area covers the whole + image. */ + maskDilation?: number; + /** The binary color threshold to apply to the masks. The threshold + can be set to a decimal value between 0 and 255 non-inclusive. + Set to -1 for no binary color thresholding. */ + binaryColorThreshold?: number; + /** User specified labels to track billing usage. */ + labels?: Record<string, string>; +} + +/** The parameters for segmenting an image. */ +export declare interface SegmentImageParameters { + /** ID of the model to use. For a list of models, see `Google models + <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */ + model: string; + /** A set of source input(s) for image segmentation. */ + source: SegmentImageSource; + /** Configuration for image segmentation. */ + config?: SegmentImageConfig; +} + +/** The output images response. */ +export declare class SegmentImageResponse { + /** List of generated image masks. + */ + generatedMasks?: GeneratedImageMask[]; +} + +/** A set of source input(s) for image segmentation. */ +export declare interface SegmentImageSource { + /** A text prompt for guiding the model during image segmentation. + Required for prompt mode and semantic mode, disallowed for other modes. */ + prompt?: string; + /** The image to be segmented. */ + image?: Image_2; + /** The brush scribble to guide segmentation. + Required for the interactive mode, disallowed for other modes. */ + scribbleImage?: ScribbleImage; +} + +/** Enum that represents the segmentation mode. */ +export declare enum SegmentMode { + FOREGROUND = "FOREGROUND", + BACKGROUND = "BACKGROUND", + PROMPT = "PROMPT", + SEMANTIC = "SEMANTIC", + INTERACTIVE = "INTERACTIVE" +} + +/** Parameters for sending a message within a chat session. + + These parameters are used with the `chat.sendMessage()` method. */ +export declare interface SendMessageParameters { + /** The message to send to the model. + + The SDK will combine all parts into a single 'user' content to send to + the model. + */ + message: PartListUnion; + /** Config for this specific request. + + Please note that the per-request config does not change the chat level + config, nor inherit from it. If you intend to use some values from the + chat's default config, you must explicitly copy them into this per-request + config. + */ + config?: GenerateContentConfig; +} + +/** + Represents a connection to the API. + + @experimental + */ +export declare class Session { + readonly conn: WebSocket_2; + private readonly apiClient; + constructor(conn: WebSocket_2, apiClient: ApiClient); + private tLiveClientContent; + private tLiveClienttToolResponse; + /** + Send a message over the established connection. + + @param params - Contains two **optional** properties, `turns` and + `turnComplete`. + + - `turns` will be converted to a `Content[]` + - `turnComplete: true` [default] indicates that you are done sending + content and expect a response. If `turnComplete: false`, the server + will wait for additional messages before starting generation. + + @experimental + + @remarks + There are two ways to send messages to the live API: + `sendClientContent` and `sendRealtimeInput`. + + `sendClientContent` messages are added to the model context **in order**. + Having a conversation using `sendClientContent` messages is roughly + equivalent to using the `Chat.sendMessageStream`, except that the state of + the `chat` history is stored on the API server instead of locally. + + Because of `sendClientContent`'s order guarantee, the model cannot respons + as quickly to `sendClientContent` messages as to `sendRealtimeInput` + messages. This makes the biggest difference when sending objects that have + significant preprocessing time (typically images). + + The `sendClientContent` message sends a `Content[]` + which has more options than the `Blob` sent by `sendRealtimeInput`. + + So the main use-cases for `sendClientContent` over `sendRealtimeInput` are: + + - Sending anything that can't be represented as a `Blob` (text, + `sendClientContent({turns="Hello?"}`)). + - Managing turns when not using audio input and voice activity detection. + (`sendClientContent({turnComplete:true})` or the short form + `sendClientContent()`) + - Prefilling a conversation context + ``` + sendClientContent({ + turns: [ + Content({role:user, parts:...}), + Content({role:user, parts:...}), + ... + ] + }) + ``` + @experimental + */ + sendClientContent(params: types.LiveSendClientContentParameters): void; + /** + Send a realtime message over the established connection. + + @param params - Contains one property, `media`. + + - `media` will be converted to a `Blob` + + @experimental + + @remarks + Use `sendRealtimeInput` for realtime audio chunks and video frames (images). + + With `sendRealtimeInput` the api will respond to audio automatically + based on voice activity detection (VAD). + + `sendRealtimeInput` is optimized for responsivness at the expense of + deterministic ordering guarantees. Audio and video tokens are to the + context when they become available. + + Note: The Call signature expects a `Blob` object, but only a subset + of audio and image mimetypes are allowed. + */ + sendRealtimeInput(params: types.LiveSendRealtimeInputParameters): void; + /** + Send a function response message over the established connection. + + @param params - Contains property `functionResponses`. + + - `functionResponses` will be converted to a `functionResponses[]` + + @remarks + Use `sendFunctionResponse` to reply to `LiveServerToolCall` from the server. + + Use {@link types.LiveConnectConfig#tools} to configure the callable functions. + + @experimental + */ + sendToolResponse(params: types.LiveSendToolResponseParameters): void; + /** + Terminates the WebSocket connection. + + @experimental + + @example + ```ts + let model: string; + if (GOOGLE_GENAI_USE_VERTEXAI) { + model = 'gemini-2.0-flash-live-preview-04-09'; + } else { + model = 'gemini-live-2.5-flash-preview'; + } + const session = await ai.live.connect({ + model: model, + config: { + responseModalities: [Modality.AUDIO], + } + }); + + session.close(); + ``` + */ + close(): void; +} + +/** Configuration of session resumption mechanism. + + Included in `LiveConnectConfig.session_resumption`. If included server + will send `LiveServerSessionResumptionUpdate` messages. */ +export declare interface SessionResumptionConfig { + /** Session resumption handle of previous session (session to restore). + + If not present new session will be started. */ + handle?: string; + /** If set the server will send `last_consumed_client_message_index` in the `session_resumption_update` messages to allow for transparent reconnections. */ + transparent?: boolean; +} + +/** + * Overrides the base URLs for the Gemini API and Vertex AI API. + * + * @remarks This function should be called before initializing the SDK. If the + * base URLs are set after initializing the SDK, the base URLs will not be + * updated. Base URLs provided in the HttpOptions will also take precedence over + * URLs set here. + * + * @example + * ```ts + * import {GoogleGenAI, setDefaultBaseUrls} from '@google/genai'; + * // Override the base URL for the Gemini API. + * setDefaultBaseUrls({geminiUrl:'https://gemini.google.com'}); + * + * // Override the base URL for the Vertex AI API. + * setDefaultBaseUrls({vertexUrl: 'https://vertexai.googleapis.com'}); + * + * const ai = new GoogleGenAI({apiKey: 'GEMINI_API_KEY'}); + * ``` + */ +export declare function setDefaultBaseUrls(baseUrlParams: BaseUrlParameters): void; + +/** Config for `response` parameter. */ +export declare class SingleEmbedContentResponse { + /** The response to the request. + */ + embedding?: ContentEmbedding; + /** The error encountered while processing the request. + */ + tokenCount?: string; +} + +/** Context window will be truncated by keeping only suffix of it. + + Context window will always be cut at start of USER role turn. System + instructions and `BidiGenerateContentSetup.prefix_turns` will not be + subject to the sliding window mechanism, they will always stay at the + beginning of context window. */ +export declare interface SlidingWindow { + /** Session reduction target -- how many tokens we should keep. Window shortening operation has some latency costs, so we should avoid running it on every turn. Should be < trigger_tokens. If not set, trigger_tokens/2 is assumed. */ + targetTokens?: string; +} + +/** Configuration for a single speaker in a multi speaker setup. */ +export declare interface SpeakerVoiceConfig { + /** Required. The name of the speaker. This should be the same as the speaker name used in the prompt. */ + speaker?: string; + /** Required. The configuration for the voice of this speaker. */ + voiceConfig?: VoiceConfig; +} + +export declare interface SpeechConfig { + /** Configuration for the voice of the response. */ + voiceConfig?: VoiceConfig; + /** Optional. Language code (ISO 639. e.g. en-US) for the speech synthesization. */ + languageCode?: string; + /** The configuration for a multi-speaker text-to-speech request. This field is mutually exclusive with `voice_config`. */ + multiSpeakerVoiceConfig?: MultiSpeakerVoiceConfig; +} + +/** + * The configuration for speech interaction. + */ +declare interface SpeechConfig_2 { + /** + * The language of the speech. + */ + language?: string; + /** + * The speaker's name, it should match the speaker name given in the prompt. + */ + speaker?: string; + /** + * The voice of the speaker. + */ + voice?: string; +} + +export declare type SpeechConfigUnion = SpeechConfig | string; + +/** Start of speech sensitivity. */ +export declare enum StartSensitivity { + /** + * The default is START_SENSITIVITY_LOW. + */ + START_SENSITIVITY_UNSPECIFIED = "START_SENSITIVITY_UNSPECIFIED", + /** + * Automatic detection will detect the start of speech more often. + */ + START_SENSITIVITY_HIGH = "START_SENSITIVITY_HIGH", + /** + * Automatic detection will detect the start of speech less often. + */ + START_SENSITIVITY_LOW = "START_SENSITIVITY_LOW" +} + +declare class Stream<Item> implements AsyncIterable<Item> { + private iterator; + controller: AbortController; + private client; + constructor(iterator: () => AsyncIterator<Item>, controller: AbortController, client?: BaseGeminiNextGenAPIClient); + static fromSSEResponse<Item>(response: Response, controller: AbortController, client?: BaseGeminiNextGenAPIClient): Stream<Item>; + /** + * Generates a Stream from a newline-separated ReadableStream + * where each item is a JSON value. + */ + static fromReadableStream<Item>(readableStream: _ReadableStream_2, controller: AbortController, client?: BaseGeminiNextGenAPIClient): Stream<Item>; + [Symbol.asyncIterator](): AsyncIterator<Item>; + /** + * Splits the stream into two streams which can be + * independently read from at different speeds. + */ + tee(): [Stream<Item>, Stream<Item>]; + /** + * Converts this stream to a newline-separated ReadableStream of + * JSON stringified values in the stream + * which can be turned back into a Stream with `Stream.fromReadableStream()`. + */ + toReadableStream(): _ReadableStream_2; +} + +/** User provided string values assigned to a single metadata key. This data type is not supported in Vertex AI. */ +export declare interface StringList { + /** The string values of the metadata to store. */ + values?: string[]; +} + +/** Configuration for a Style reference image. */ +export declare interface StyleReferenceConfig { + /** A text description of the style to use for the generated image. */ + styleDescription?: string; +} + +/** A style reference image. + + This encapsulates a style reference image provided by the user, and + additionally optional config parameters for the style reference image. + + A raw reference image can also be provided as a destination for the style to + be applied to. */ +export declare class StyleReferenceImage { + /** The reference image for the editing operation. */ + referenceImage?: Image_2; + /** The id of the reference image. */ + referenceId?: number; + /** The type of the reference image. Only set by the SDK. */ + referenceType?: string; + /** Configuration for the style reference image. */ + config?: StyleReferenceConfig; + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI(): ReferenceImageAPIInternal; +} + +/** Configuration for a Subject reference image. */ +export declare interface SubjectReferenceConfig { + /** The subject type of a subject reference image. */ + subjectType?: SubjectReferenceType; + /** Subject description for the image. */ + subjectDescription?: string; +} + +/** A subject reference image. + + This encapsulates a subject reference image provided by the user, and + additionally optional config parameters for the subject reference image. + + A raw reference image can also be provided as a destination for the subject to + be applied to. */ +export declare class SubjectReferenceImage { + /** The reference image for the editing operation. */ + referenceImage?: Image_2; + /** The id of the reference image. */ + referenceId?: number; + /** The type of the reference image. Only set by the SDK. */ + referenceType?: string; + /** Configuration for the subject reference image. */ + config?: SubjectReferenceConfig; + toReferenceImageAPI(): ReferenceImageAPIInternal; +} + +/** Enum representing the subject type of a subject reference image. */ +export declare enum SubjectReferenceType { + SUBJECT_TYPE_DEFAULT = "SUBJECT_TYPE_DEFAULT", + SUBJECT_TYPE_PERSON = "SUBJECT_TYPE_PERSON", + SUBJECT_TYPE_ANIMAL = "SUBJECT_TYPE_ANIMAL", + SUBJECT_TYPE_PRODUCT = "SUBJECT_TYPE_PRODUCT" +} + +/** Hyperparameters for SFT. This data type is not supported in Gemini API. */ +export declare interface SupervisedHyperParameters { + /** Optional. Adapter size for tuning. */ + adapterSize?: AdapterSize; + /** Optional. Batch size for tuning. This feature is only available for open source models. */ + batchSize?: string; + /** Optional. Number of complete passes the model makes over the entire training dataset during training. */ + epochCount?: string; + /** Optional. Learning rate for tuning. Mutually exclusive with `learning_rate_multiplier`. This feature is only available for open source models. */ + learningRate?: number; + /** Optional. Multiplier for adjusting the default learning rate. Mutually exclusive with `learning_rate`. This feature is only available for 1P models. */ + learningRateMultiplier?: number; +} + +/** Dataset distribution for Supervised Tuning. This data type is not supported in Gemini API. */ +export declare interface SupervisedTuningDatasetDistribution { + /** Output only. Sum of a given population of values that are billable. */ + billableSum?: string; + /** Output only. Defines the histogram bucket. */ + buckets?: SupervisedTuningDatasetDistributionDatasetBucket[]; + /** Output only. The maximum of the population values. */ + max?: number; + /** Output only. The arithmetic mean of the values in the population. */ + mean?: number; + /** Output only. The median of the values in the population. */ + median?: number; + /** Output only. The minimum of the population values. */ + min?: number; + /** Output only. The 5th percentile of the values in the population. */ + p5?: number; + /** Output only. The 95th percentile of the values in the population. */ + p95?: number; + /** Output only. Sum of a given population of values. */ + sum?: string; +} + +/** Dataset bucket used to create a histogram for the distribution given a population of values. This data type is not supported in Gemini API. */ +export declare interface SupervisedTuningDatasetDistributionDatasetBucket { + /** Output only. Number of values in the bucket. */ + count?: number; + /** Output only. Left bound of the bucket. */ + left?: number; + /** Output only. Right bound of the bucket. */ + right?: number; +} + +/** Tuning data statistics for Supervised Tuning. This data type is not supported in Gemini API. */ +export declare interface SupervisedTuningDataStats { + /** Output only. For each index in `truncated_example_indices`, the user-facing reason why the example was dropped. */ + droppedExampleReasons?: string[]; + /** Output only. Number of billable characters in the tuning dataset. */ + totalBillableCharacterCount?: string; + /** Output only. Number of billable tokens in the tuning dataset. */ + totalBillableTokenCount?: string; + /** Output only. The number of examples in the dataset that have been dropped. An example can be dropped for reasons including: too many tokens, contains an invalid image, contains too many images, etc. */ + totalTruncatedExampleCount?: string; + /** Output only. Number of tuning characters in the tuning dataset. */ + totalTuningCharacterCount?: string; + /** Output only. A partial sample of the indices (starting from 1) of the dropped examples. */ + truncatedExampleIndices?: string[]; + /** Output only. Number of examples in the tuning dataset. */ + tuningDatasetExampleCount?: string; + /** Output only. Number of tuning steps for this Tuning Job. */ + tuningStepCount?: string; + /** Output only. Sample user messages in the training dataset uri. */ + userDatasetExamples?: Content[]; + /** Output only. Dataset distributions for the user input tokens. */ + userInputTokenDistribution?: SupervisedTuningDatasetDistribution; + /** Output only. Dataset distributions for the messages per example. */ + userMessagePerExampleDistribution?: SupervisedTuningDatasetDistribution; + /** Output only. Dataset distributions for the user output tokens. */ + userOutputTokenDistribution?: SupervisedTuningDatasetDistribution; +} + +/** Supervised tuning spec for tuning. */ +export declare interface SupervisedTuningSpec { + /** Optional. If set to true, disable intermediate checkpoints for SFT and only the last checkpoint will be exported. Otherwise, enable intermediate checkpoints for SFT. Default is false. */ + exportLastCheckpointOnly?: boolean; + /** Optional. Hyperparameters for SFT. */ + hyperParameters?: SupervisedHyperParameters; + /** Required. Training dataset used for tuning. The dataset can be specified as either a Cloud Storage path to a JSONL file or as the resource name of a Vertex Multimodal Dataset. */ + trainingDatasetUri?: string; + /** Tuning mode. */ + tuningMode?: TuningMode; + /** Optional. Validation dataset used for tuning. The dataset can be specified as either a Cloud Storage path to a JSONL file or as the resource name of a Vertex Multimodal Dataset. */ + validationDatasetUri?: string; +} + +export declare interface TestTableFile { + comment?: string; + testMethod?: string; + parameterNames?: string[]; + testTable?: TestTableItem[]; +} + +export declare interface TestTableItem { + /** The name of the test. This is used to derive the replay id. */ + name?: string; + /** The parameters to the test. Use pydantic models. */ + parameters?: Record<string, unknown>; + /** Expects an exception for MLDev matching the string. */ + exceptionIfMldev?: string; + /** Expects an exception for Vertex matching the string. */ + exceptionIfVertex?: string; + /** Use if you don't want to use the default replay id which is derived from the test name. */ + overrideReplayId?: string; + /** True if the parameters contain an unsupported union type. This test will be skipped for languages that do not support the union type. */ + hasUnion?: boolean; + /** When set to a reason string, this test will be skipped in the API mode. Use this flag for tests that can not be reproduced with the real API. E.g. a test that deletes a resource. */ + skipInApiMode?: string; + /** Keys to ignore when comparing the request and response. This is useful for tests that are not deterministic. */ + ignoreKeys?: string[]; +} + +/** + * A text content block. + */ +declare interface TextContent { + type: 'text'; + /** + * Citation information for model-generated content. + */ + annotations?: Array<Annotation>; + /** + * The text content. + */ + text?: string; +} + +/** The thinking features configuration. */ +export declare interface ThinkingConfig { + /** Indicates whether to include thoughts in the response. If true, thoughts are returned only if the model supports thought and thoughts are available. + */ + includeThoughts?: boolean; + /** Indicates the thinking budget in tokens. 0 is DISABLED. -1 is AUTOMATIC. The default values and allowed ranges are model dependent. + */ + thinkingBudget?: number; + /** Optional. The number of thoughts tokens that the model should generate. */ + thinkingLevel?: ThinkingLevel; +} + +/** The number of thoughts tokens that the model should generate. */ +export declare enum ThinkingLevel { + /** + * Unspecified thinking level. + */ + THINKING_LEVEL_UNSPECIFIED = "THINKING_LEVEL_UNSPECIFIED", + /** + * Low thinking level. + */ + LOW = "LOW", + /** + * Medium thinking level. + */ + MEDIUM = "MEDIUM", + /** + * High thinking level. + */ + HIGH = "HIGH", + /** + * MINIMAL thinking level. + */ + MINIMAL = "MINIMAL" +} + +declare type ThinkingLevel_2 = 'minimal' | 'low' | 'medium' | 'high'; + +/** + * A thought content block. + */ +declare interface ThoughtContent { + type: 'thought'; + /** + * Signature to match the backend source to be part of the generation. + */ + signature?: string; + /** + * A summary of the thought. + */ + summary?: Array<TextContent | ImageContent>; +} + +export declare class Tokens extends BaseModule { + private readonly apiClient; + constructor(apiClient: ApiClient); + /** + * Creates an ephemeral auth token resource. + * + * @experimental + * + * @remarks + * Ephemeral auth tokens is only supported in the Gemini Developer API. + * It can be used for the session connection to the Live constrained API. + * Support in v1alpha only. + * + * @param params - The parameters for the create request. + * @return The created auth token. + * + * @example + * ```ts + * const ai = new GoogleGenAI({ + * apiKey: token.name, + * httpOptions: { apiVersion: 'v1alpha' } // Support in v1alpha only. + * }); + * + * // Case 1: If LiveEphemeralParameters is unset, unlock LiveConnectConfig + * // when using the token in Live API sessions. Each session connection can + * // use a different configuration. + * const config: CreateAuthTokenConfig = { + * uses: 3, + * expireTime: '2025-05-01T00:00:00Z', + * } + * const token = await ai.tokens.create(config); + * + * // Case 2: If LiveEphemeralParameters is set, lock all fields in + * // LiveConnectConfig when using the token in Live API sessions. For + * // example, changing `outputAudioTranscription` in the Live API + * // connection will be ignored by the API. + * const config: CreateAuthTokenConfig = + * uses: 3, + * expireTime: '2025-05-01T00:00:00Z', + * LiveEphemeralParameters: { + * model: 'gemini-2.0-flash-001', + * config: { + * 'responseModalities': ['AUDIO'], + * 'systemInstruction': 'Always answer in English.', + * } + * } + * } + * const token = await ai.tokens.create(config); + * + * // Case 3: If LiveEphemeralParameters is set and lockAdditionalFields is + * // set, lock LiveConnectConfig with set and additional fields (e.g. + * // responseModalities, systemInstruction, temperature in this example) when + * // using the token in Live API sessions. + * const config: CreateAuthTokenConfig = + * uses: 3, + * expireTime: '2025-05-01T00:00:00Z', + * LiveEphemeralParameters: { + * model: 'gemini-2.0-flash-001', + * config: { + * 'responseModalities': ['AUDIO'], + * 'systemInstruction': 'Always answer in English.', + * } + * }, + * lockAdditionalFields: ['temperature'], + * } + * const token = await ai.tokens.create(config); + * + * // Case 4: If LiveEphemeralParameters is set and lockAdditionalFields is + * // empty array, lock LiveConnectConfig with set fields (e.g. + * // responseModalities, systemInstruction in this example) when using the + * // token in Live API sessions. + * const config: CreateAuthTokenConfig = + * uses: 3, + * expireTime: '2025-05-01T00:00:00Z', + * LiveEphemeralParameters: { + * model: 'gemini-2.0-flash-001', + * config: { + * 'responseModalities': ['AUDIO'], + * 'systemInstruction': 'Always answer in English.', + * } + * }, + * lockAdditionalFields: [], + * } + * const token = await ai.tokens.create(config); + * ``` + */ + create(params: types.CreateAuthTokenParameters): Promise<types.AuthToken>; +} + +/** Tokens info with a list of tokens and the corresponding list of token ids. */ +export declare interface TokensInfo { + /** Optional fields for the role from the corresponding Content. */ + role?: string; + /** A list of token ids from the input. */ + tokenIds?: string[]; + /** A list of tokens from the input. + * @remarks Encoded as base64 string. */ + tokens?: string[]; +} + +/** Tool details of a tool that the model may use to generate a response. */ +export declare interface Tool { + /** Optional. Retrieval tool type. System will always execute the provided retrieval tool(s) to get external knowledge to answer the prompt. Retrieval results are presented to the model for generation. This field is not supported in Gemini API. */ + retrieval?: Retrieval; + /** Optional. Tool to support the model interacting directly with the + computer. If enabled, it automatically populates computer-use specific + Function Declarations. */ + computerUse?: ComputerUse; + /** Optional. Tool to retrieve knowledge from the File Search Stores. */ + fileSearch?: FileSearch; + /** Optional. CodeExecution tool type. Enables the model to execute code as part of generation. */ + codeExecution?: ToolCodeExecution; + /** Optional. Tool to support searching public web data, powered by Vertex AI Search and Sec4 compliance. This field is not supported in Gemini API. */ + enterpriseWebSearch?: EnterpriseWebSearch; + /** Optional. Function tool type. One or more function declarations to be passed to the model along with the current user query. Model may decide to call a subset of these functions by populating FunctionCall in the response. User should provide a FunctionResponse for each function call in the next turn. Based on the function responses, Model will generate the final response back to the user. Maximum 512 function declarations can be provided. */ + functionDeclarations?: FunctionDeclaration[]; + /** Optional. GoogleMaps tool type. Tool to support Google Maps in Model. */ + googleMaps?: GoogleMaps; + /** Optional. GoogleSearch tool type. Tool to support Google Search in Model. Powered by Google. */ + googleSearch?: GoogleSearch; + /** Optional. Specialized retrieval tool that is powered by Google Search. */ + googleSearchRetrieval?: GoogleSearchRetrieval; + /** Optional. Tool to support URL context retrieval. */ + urlContext?: UrlContext; +} + +/** + * A tool that can be used by the model. + */ +declare type Tool_2 = Function_2 | Tool_2.GoogleSearch | Tool_2.CodeExecution | Tool_2.URLContext | Tool_2.ComputerUse | Tool_2.MCPServer | Tool_2.FileSearch; + +declare namespace Tool_2 { + /** + * A tool that can be used by the model to search Google. + */ + interface GoogleSearch { + type: 'google_search'; + } + /** + * A tool that can be used by the model to execute code. + */ + interface CodeExecution { + type: 'code_execution'; + } + /** + * A tool that can be used by the model to fetch URL context. + */ + interface URLContext { + type: 'url_context'; + } + /** + * A tool that can be used by the model to interact with the computer. + */ + interface ComputerUse { + type: 'computer_use'; + /** + * The environment being operated. + */ + environment?: 'browser'; + /** + * The list of predefined functions that are excluded from the model call. + */ + excludedPredefinedFunctions?: Array<string>; + } + /** + * A MCPServer is a server that can be called by the model to perform actions. + */ + interface MCPServer { + type: 'mcp_server'; + /** + * The allowed tools. + */ + allowed_tools?: Array<InteractionsAPI.AllowedTools>; + /** + * Optional: Fields for authentication headers, timeouts, etc., if needed. + */ + headers?: { + [key: string]: string; + }; + /** + * The name of the MCPServer. + */ + name?: string; + /** + * The full URL for the MCPServer endpoint. + * Example: "https://api.example.com/mcp" + */ + url?: string; + } + /** + * A tool that can be used by the model to search files. + */ + interface FileSearch { + type: 'file_search'; + /** + * The file search store names to search. + */ + file_search_store_names?: Array<string>; + /** + * Metadata filter to apply to the semantic retrieval documents and chunks. + */ + metadata_filter?: string; + /** + * The number of semantic retrieval chunks to retrieve. + */ + top_k?: number; + } +} + +/** + * The configuration for tool choice. + */ +declare type ToolChoice = ToolChoiceType | ToolChoiceConfig; + +declare interface ToolChoiceConfig { + /** + * The configuration for allowed tools. + */ + allowed_tools?: AllowedTools; +} + +declare type ToolChoiceType = 'auto' | 'any' | 'none' | 'validated'; + +/** Tool that executes code generated by the model, and automatically returns the result to the model. See also [ExecutableCode]and [CodeExecutionResult] which are input and output to this tool. This data type is not supported in Gemini API. */ +export declare interface ToolCodeExecution { +} + +/** Tool config. + + This config is shared for all tools provided in the request. */ +export declare interface ToolConfig { + /** Optional. Retrieval config. */ + retrievalConfig?: RetrievalConfig; + /** Optional. Function calling config. */ + functionCallingConfig?: FunctionCallingConfig; +} + +export declare type ToolListUnion = ToolUnion[]; + +export declare type ToolUnion = Tool | CallableTool; + +/** Output only. The traffic type for this request. This enum is not supported in Gemini API. */ +export declare enum TrafficType { + /** + * Unspecified request traffic type. + */ + TRAFFIC_TYPE_UNSPECIFIED = "TRAFFIC_TYPE_UNSPECIFIED", + /** + * The request was processed using Pay-As-You-Go quota. + */ + ON_DEMAND = "ON_DEMAND", + /** + * Type for Provisioned Throughput traffic. + */ + PROVISIONED_THROUGHPUT = "PROVISIONED_THROUGHPUT" +} + +/** Audio transcription in Server Conent. */ +export declare interface Transcription { + /** Transcription text. + */ + text?: string; + /** The bool indicates the end of the transcription. + */ + finished?: boolean; +} + +/** TunedModel for the Tuned Model of a Tuning Job. */ +export declare interface TunedModel { + /** Output only. The resource name of the TunedModel. + Format: `projects/{project}/locations/{location}/models/{model}@{version_id}` + When tuning from a base model, the version_id will be 1. + For continuous tuning, the version id will be incremented by 1 from the + last version id in the parent model. E.g., `projects/{project}/locations/{location}/models/{model}@{last_version_id + 1}` + */ + model?: string; + /** Output only. A resource name of an Endpoint. + Format: `projects/{project}/locations/{location}/endpoints/{endpoint}`. + */ + endpoint?: string; + /** The checkpoints associated with this TunedModel. + This field is only populated for tuning jobs that enable intermediate + checkpoints. */ + checkpoints?: TunedModelCheckpoint[]; +} + +/** TunedModelCheckpoint for the Tuned Model of a Tuning Job. */ +export declare interface TunedModelCheckpoint { + /** The ID of the checkpoint. + */ + checkpointId?: string; + /** The epoch of the checkpoint. + */ + epoch?: string; + /** The step of the checkpoint. + */ + step?: string; + /** The Endpoint resource name that the checkpoint is deployed to. + Format: `projects/{project}/locations/{location}/endpoints/{endpoint}`. + */ + endpoint?: string; +} + +/** A tuned machine learning model. */ +export declare interface TunedModelInfo { + /** ID of the base model that you want to tune. */ + baseModel?: string; + /** Date and time when the base model was created. */ + createTime?: string; + /** Date and time when the base model was last updated. */ + updateTime?: string; +} + +/** Supervised fine-tuning training dataset. */ +export declare interface TuningDataset { + /** GCS URI of the file containing training dataset in JSONL format. */ + gcsUri?: string; + /** The resource name of the Vertex Multimodal Dataset that is used as training dataset. Example: 'projects/my-project-id-or-number/locations/my-location/datasets/my-dataset-id'. */ + vertexDatasetResource?: string; + /** Inline examples with simple input/output text. */ + examples?: TuningExample[]; +} + +/** The tuning data statistic values for TuningJob. This data type is not supported in Gemini API. */ +export declare interface TuningDataStats { + /** Output only. Statistics for distillation. */ + distillationDataStats?: DistillationDataStats; + /** Output only. Statistics for preference optimization. */ + preferenceOptimizationDataStats?: PreferenceOptimizationDataStats; + /** The SFT Tuning data stats. */ + supervisedTuningDataStats?: SupervisedTuningDataStats; +} + +/** A single example for tuning. This data type is not supported in Vertex AI. */ +export declare interface TuningExample { + /** Required. The expected model output. */ + output?: string; + /** Optional. Text model input. */ + textInput?: string; +} + +/** A tuning job. */ +export declare interface TuningJob { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** Output only. Identifier. Resource name of a TuningJob. Format: `projects/{project}/locations/{location}/tuningJobs/{tuning_job}` */ + name?: string; + /** Output only. The detailed state of the job. */ + state?: JobState; + /** Output only. Time when the TuningJob was created. */ + createTime?: string; + /** Output only. Time when the TuningJob for the first time entered the `JOB_STATE_RUNNING` state. */ + startTime?: string; + /** Output only. Time when the TuningJob entered any of the following JobStates: `JOB_STATE_SUCCEEDED`, `JOB_STATE_FAILED`, `JOB_STATE_CANCELLED`, `JOB_STATE_EXPIRED`. */ + endTime?: string; + /** Output only. Time when the TuningJob was most recently updated. */ + updateTime?: string; + /** Output only. Only populated when job's state is `JOB_STATE_FAILED` or `JOB_STATE_CANCELLED`. */ + error?: GoogleRpcStatus; + /** Optional. The description of the TuningJob. */ + description?: string; + /** The base model that is being tuned. See [Supported models](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/tuning#supported_models). */ + baseModel?: string; + /** Output only. The tuned model resources associated with this TuningJob. */ + tunedModel?: TunedModel; + /** The pre-tuned model for continuous tuning. */ + preTunedModel?: PreTunedModel; + /** Tuning Spec for Supervised Fine Tuning. */ + supervisedTuningSpec?: SupervisedTuningSpec; + /** Tuning Spec for Preference Optimization. */ + preferenceOptimizationSpec?: PreferenceOptimizationSpec; + /** Tuning Spec for Distillation. */ + distillationSpec?: DistillationSpec; + /** Output only. The tuning data statistics associated with this TuningJob. */ + tuningDataStats?: TuningDataStats; + /** Customer-managed encryption key options for a TuningJob. If this is set, then all resources created by the TuningJob will be encrypted with the provided encryption key. */ + encryptionSpec?: EncryptionSpec; + /** Tuning Spec for open sourced and third party Partner models. */ + partnerModelTuningSpec?: PartnerModelTuningSpec; + /** Optional. The user-provided path to custom model weights. Set this field to tune a custom model. The path must be a Cloud Storage directory that contains the model weights in .safetensors format along with associated model metadata files. If this field is set, the base_model field must still be set to indicate which base model the custom model is derived from. This feature is only available for open source models. */ + customBaseModel?: string; + /** Output only. The Experiment associated with this TuningJob. */ + experiment?: string; + /** Optional. The labels with user-defined metadata to organize TuningJob and generated resources such as Model and Endpoint. Label keys and values can be no longer than 64 characters (Unicode codepoints), can only contain lowercase letters, numeric characters, underscores and dashes. International characters are allowed. See https://goo.gl/xmQnxf for more information and examples of labels. */ + labels?: Record<string, string>; + /** Optional. Cloud Storage path to the directory where tuning job outputs are written to. This field is only available and required for open source models. */ + outputUri?: string; + /** Output only. The resource name of the PipelineJob associated with the TuningJob. Format: `projects/{project}/locations/{location}/pipelineJobs/{pipeline_job}`. */ + pipelineJob?: string; + /** The service account that the tuningJob workload runs as. If not specified, the Vertex AI Secure Fine-Tuned Service Agent in the project will be used. See https://cloud.google.com/iam/docs/service-agents#vertex-ai-secure-fine-tuning-service-agent Users starting the pipeline must have the `iam.serviceAccounts.actAs` permission on this service account. */ + serviceAccount?: string; + /** Optional. The display name of the TunedModel. The name can be up to 128 characters long and can consist of any UTF-8 characters. For continuous tuning, tuned_model_display_name will by default use the same display name as the pre-tuned model. If a new display name is provided, the tuning job will create a new model instead of a new version. */ + tunedModelDisplayName?: string; + /** Tuning Spec for Veo Tuning. */ + veoTuningSpec?: VeoTuningSpec; +} + +/** Enum representing the tuning method. */ +export declare enum TuningMethod { + /** + * Supervised fine tuning. + */ + SUPERVISED_FINE_TUNING = "SUPERVISED_FINE_TUNING", + /** + * Preference optimization tuning. + */ + PREFERENCE_TUNING = "PREFERENCE_TUNING", + /** + * Distillation tuning. + */ + DISTILLATION = "DISTILLATION" +} + +/** Tuning mode. This enum is not supported in Gemini API. */ +export declare enum TuningMode { + /** + * Tuning mode is unspecified. + */ + TUNING_MODE_UNSPECIFIED = "TUNING_MODE_UNSPECIFIED", + /** + * Full fine-tuning mode. + */ + TUNING_MODE_FULL = "TUNING_MODE_FULL", + /** + * PEFT adapter tuning mode. + */ + TUNING_MODE_PEFT_ADAPTER = "TUNING_MODE_PEFT_ADAPTER" +} + +/** A long-running operation. */ +export declare interface TuningOperation { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`. */ + name?: string; + /** Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata. Any method that returns a long-running operation should document the metadata type, if any. */ + metadata?: Record<string, unknown>; + /** If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available. */ + done?: boolean; + /** The error result of the operation in case of failure or cancellation. */ + error?: Record<string, unknown>; +} + +declare class Tunings extends BaseModule { + private readonly apiClient; + constructor(apiClient: ApiClient); + /** + * Lists tuning jobs. + * + * @param params - The parameters for the list request. + * @return - A pager of tuning jobs. + * + * @example + * ```ts + * const tuningJobs = await ai.tunings.list({config: {'pageSize': 2}}); + * for await (const tuningJob of tuningJobs) { + * console.log(tuningJob); + * } + * ``` + */ + list: (params?: types.ListTuningJobsParameters) => Promise<Pager<types.TuningJob>>; + /** + * Gets a TuningJob. + * + * @param name - The resource name of the tuning job. + * @return - A TuningJob object. + * + * @experimental - The SDK's tuning implementation is experimental, and may + * change in future versions. + */ + get: (params: types.GetTuningJobParameters) => Promise<types.TuningJob>; + /** + * Creates a supervised fine-tuning job. + * + * @param params - The parameters for the tuning job. + * @return - A TuningJob operation. + * + * @experimental - The SDK's tuning implementation is experimental, and may + * change in future versions. + */ + tune: (params: types.CreateTuningJobParameters) => Promise<types.TuningJob>; + private getInternal; + private listInternal; + /** + * Cancels a tuning job. + * + * @param params - The parameters for the cancel request. + * @return The empty response returned by the API. + * + * @example + * ```ts + * await ai.tunings.cancel({name: '...'}); // The server-generated resource name. + * ``` + */ + cancel(params: types.CancelTuningJobParameters): Promise<types.CancelTuningJobResponse>; + private tuneInternal; + private tuneMldevInternal; +} + +/** The tuning task. Either I2V or T2V. This enum is not supported in Gemini API. */ +export declare enum TuningTask { + /** + * Default value. This value is unused. + */ + TUNING_TASK_UNSPECIFIED = "TUNING_TASK_UNSPECIFIED", + /** + * Tuning task for image to video. + */ + TUNING_TASK_I2V = "TUNING_TASK_I2V", + /** + * Tuning task for text to video. + */ + TUNING_TASK_T2V = "TUNING_TASK_T2V", + /** + * Tuning task for reference to video. + */ + TUNING_TASK_R2V = "TUNING_TASK_R2V" +} + +export declare interface TuningValidationDataset { + /** GCS URI of the file containing validation dataset in JSONL format. */ + gcsUri?: string; + /** The resource name of the Vertex Multimodal Dataset that is used as validation dataset. Example: 'projects/my-project-id-or-number/locations/my-location/datasets/my-dataset-id'. */ + vertexDatasetResource?: string; +} + +declare interface Turn { + /** + * The content of the turn. + */ + content?: string | Array<Content_2>; + /** + * The originator of this turn. Must be user for input or model for + * model output. + */ + role?: string; +} + +/** The reason why the turn is complete. */ +export declare enum TurnCompleteReason { + /** + * Default value. Reason is unspecified. + */ + TURN_COMPLETE_REASON_UNSPECIFIED = "TURN_COMPLETE_REASON_UNSPECIFIED", + /** + * The function call generated by the model is invalid. + */ + MALFORMED_FUNCTION_CALL = "MALFORMED_FUNCTION_CALL", + /** + * The response is rejected by the model. + */ + RESPONSE_REJECTED = "RESPONSE_REJECTED", + /** + * Needs more input from the user. + */ + NEED_MORE_INPUT = "NEED_MORE_INPUT" +} + +/** Options about which input is included in the user's turn. */ +export declare enum TurnCoverage { + /** + * If unspecified, the default behavior is `TURN_INCLUDES_ONLY_ACTIVITY`. + */ + TURN_COVERAGE_UNSPECIFIED = "TURN_COVERAGE_UNSPECIFIED", + /** + * The users turn only includes activity since the last turn, excluding inactivity (e.g. silence on the audio stream). This is the default behavior. + */ + TURN_INCLUDES_ONLY_ACTIVITY = "TURN_INCLUDES_ONLY_ACTIVITY", + /** + * The users turn includes all realtime input since the last turn, including inactivity (e.g. silence on the audio stream). + */ + TURN_INCLUDES_ALL_INPUT = "TURN_INCLUDES_ALL_INPUT" +} + +/** The type of the data. */ +export declare enum Type { + /** + * Not specified, should not be used. + */ + TYPE_UNSPECIFIED = "TYPE_UNSPECIFIED", + /** + * OpenAPI string type + */ + STRING = "STRING", + /** + * OpenAPI number type + */ + NUMBER = "NUMBER", + /** + * OpenAPI integer type + */ + INTEGER = "INTEGER", + /** + * OpenAPI boolean type + */ + BOOLEAN = "BOOLEAN", + /** + * OpenAPI array type + */ + ARRAY = "ARRAY", + /** + * OpenAPI object type + */ + OBJECT = "OBJECT", + /** + * Null type + */ + NULL = "NULL" +} + +declare namespace types { + export { + createFunctionResponsePartFromBase64, + createFunctionResponsePartFromUri, + createPartFromUri, + createPartFromText, + createPartFromFunctionCall, + createPartFromFunctionResponse, + createPartFromBase64, + createPartFromCodeExecutionResult, + createPartFromExecutableCode, + createUserContent, + createModelContent, + Outcome, + Language, + FunctionResponseScheduling, + Type, + ApiSpec, + AuthType, + HttpElementLocation, + PhishBlockThreshold, + Behavior, + DynamicRetrievalConfigMode, + FunctionCallingConfigMode, + ThinkingLevel, + HarmCategory, + HarmBlockMethod, + HarmBlockThreshold, + FinishReason, + HarmProbability, + HarmSeverity, + UrlRetrievalStatus, + BlockedReason, + TrafficType, + Modality, + MediaResolution, + TuningMode, + AdapterSize, + JobState, + TuningTask, + PartMediaResolutionLevel, + ResourceScope, + FeatureSelectionPreference, + Environment, + SafetyFilterLevel, + PersonGeneration, + ImagePromptLanguage, + MaskReferenceMode, + ControlReferenceType, + SubjectReferenceType, + EditMode, + SegmentMode, + VideoGenerationReferenceType, + VideoGenerationMaskMode, + VideoCompressionQuality, + TuningMethod, + DocumentState, + FileState, + FileSource, + TurnCompleteReason, + MediaModality, + VadSignalType, + VoiceActivityType, + StartSensitivity, + EndSensitivity, + ActivityHandling, + TurnCoverage, + Scale, + MusicGenerationMode, + LiveMusicPlaybackControl, + PartMediaResolution, + CodeExecutionResult, + ExecutableCode, + FileData, + PartialArg, + FunctionCall, + FunctionResponseBlob, + FunctionResponseFileData, + FunctionResponsePart, + FunctionResponse, + Blob_2 as Blob, + VideoMetadata, + Part, + Content, + HttpRetryOptions, + HttpOptions, + Schema, + ModelSelectionConfig, + ComputerUse, + FileSearch, + ApiAuthApiKeyConfig, + ApiAuth, + ApiKeyConfig, + AuthConfigGoogleServiceAccountConfig, + AuthConfigHttpBasicAuthConfig, + AuthConfigOauthConfig, + AuthConfigOidcConfig, + AuthConfig, + ExternalApiElasticSearchParams, + ExternalApiSimpleSearchParams, + ExternalApi, + VertexAISearchDataStoreSpec, + VertexAISearch, + VertexRagStoreRagResource, + RagRetrievalConfigFilter, + RagRetrievalConfigHybridSearch, + RagRetrievalConfigRankingLlmRanker, + RagRetrievalConfigRankingRankService, + RagRetrievalConfigRanking, + RagRetrievalConfig, + VertexRagStore, + Retrieval, + ToolCodeExecution, + EnterpriseWebSearch, + FunctionDeclaration, + GoogleMaps, + Interval, + GoogleSearch, + DynamicRetrievalConfig, + GoogleSearchRetrieval, + UrlContext, + Tool, + LatLng, + RetrievalConfig, + FunctionCallingConfig, + ToolConfig, + ReplicatedVoiceConfig, + PrebuiltVoiceConfig, + VoiceConfig, + SpeakerVoiceConfig, + MultiSpeakerVoiceConfig, + SpeechConfig, + AutomaticFunctionCallingConfig, + ThinkingConfig, + ImageConfig, + GenerationConfigRoutingConfigAutoRoutingMode, + GenerationConfigRoutingConfigManualRoutingMode, + GenerationConfigRoutingConfig, + SafetySetting, + ModelArmorConfig, + GenerateContentConfig, + GenerateContentParameters, + HttpResponse, + LiveCallbacks, + GoogleTypeDate, + Citation, + CitationMetadata, + GroundingChunkMapsPlaceAnswerSourcesAuthorAttribution, + GroundingChunkMapsPlaceAnswerSourcesReviewSnippet, + GroundingChunkMapsPlaceAnswerSources, + GroundingChunkMaps, + RagChunkPageSpan, + RagChunk, + GroundingChunkRetrievedContext, + GroundingChunkWeb, + GroundingChunk, + Segment, + GroundingSupport, + RetrievalMetadata, + SearchEntryPoint, + GroundingMetadataSourceFlaggingUri, + GroundingMetadata, + LogprobsResultCandidate, + LogprobsResultTopCandidates, + LogprobsResult, + SafetyRating, + UrlMetadata, + UrlContextMetadata, + Candidate, + GenerateContentResponsePromptFeedback, + ModalityTokenCount, + GenerateContentResponseUsageMetadata, + GenerateContentResponse, + ReferenceImage, + EditImageParameters, + EmbedContentConfig, + EmbedContentParameters, + ContentEmbeddingStatistics, + ContentEmbedding, + EmbedContentMetadata, + EmbedContentResponse, + GenerateImagesConfig, + GenerateImagesParameters, + Image_2 as Image, + SafetyAttributes, + GeneratedImage, + GenerateImagesResponse, + MaskReferenceConfig, + ControlReferenceConfig, + StyleReferenceConfig, + SubjectReferenceConfig, + EditImageConfig, + EditImageResponse, + UpscaleImageResponse, + ProductImage, + RecontextImageSource, + RecontextImageConfig, + RecontextImageParameters, + RecontextImageResponse, + ScribbleImage, + SegmentImageSource, + SegmentImageConfig, + SegmentImageParameters, + EntityLabel, + GeneratedImageMask, + SegmentImageResponse, + GetModelConfig, + GetModelParameters, + Endpoint, + TunedModelInfo, + Checkpoint, + Model, + ListModelsConfig, + ListModelsParameters, + ListModelsResponse, + UpdateModelConfig, + UpdateModelParameters, + DeleteModelConfig, + DeleteModelParameters, + DeleteModelResponse, + GenerationConfig, + CountTokensConfig, + CountTokensParameters, + CountTokensResponse, + ComputeTokensConfig, + ComputeTokensParameters, + TokensInfo, + ComputeTokensResponse, + Video, + GenerateVideosSource, + VideoGenerationReferenceImage, + VideoGenerationMask, + GenerateVideosConfig, + GenerateVideosParameters, + GeneratedVideo, + GenerateVideosResponse, + Operation, + GenerateVideosOperation, + GetTuningJobConfig, + GetTuningJobParameters, + TunedModelCheckpoint, + TunedModel, + SupervisedHyperParameters, + SupervisedTuningSpec, + PreferenceOptimizationHyperParameters, + PreferenceOptimizationSpec, + DistillationHyperParameters, + DistillationSpec, + GoogleRpcStatus, + PreTunedModel, + DatasetDistributionDistributionBucket, + DatasetDistribution, + DatasetStats, + DistillationDataStats, + GeminiPreferenceExampleCompletion, + GeminiPreferenceExample, + PreferenceOptimizationDataStats, + SupervisedTuningDatasetDistributionDatasetBucket, + SupervisedTuningDatasetDistribution, + SupervisedTuningDataStats, + TuningDataStats, + EncryptionSpec, + PartnerModelTuningSpec, + VeoHyperParameters, + VeoTuningSpec, + TuningJob, + ListTuningJobsConfig, + ListTuningJobsParameters, + ListTuningJobsResponse, + CancelTuningJobConfig, + CancelTuningJobParameters, + CancelTuningJobResponse, + TuningExample, + TuningDataset, + TuningValidationDataset, + CreateTuningJobConfig, + CreateTuningJobParametersPrivate, + TuningOperation, + CreateCachedContentConfig, + CreateCachedContentParameters, + CachedContentUsageMetadata, + CachedContent, + GetCachedContentConfig, + GetCachedContentParameters, + DeleteCachedContentConfig, + DeleteCachedContentParameters, + DeleteCachedContentResponse, + UpdateCachedContentConfig, + UpdateCachedContentParameters, + ListCachedContentsConfig, + ListCachedContentsParameters, + ListCachedContentsResponse, + GetDocumentConfig, + GetDocumentParameters, + StringList, + CustomMetadata, + Document_2 as Document, + DeleteDocumentConfig, + DeleteDocumentParameters, + ListDocumentsConfig, + ListDocumentsParameters, + ListDocumentsResponse, + CreateFileSearchStoreConfig, + CreateFileSearchStoreParameters, + FileSearchStore, + GetFileSearchStoreConfig, + GetFileSearchStoreParameters, + DeleteFileSearchStoreConfig, + DeleteFileSearchStoreParameters, + ListFileSearchStoresConfig, + ListFileSearchStoresParameters, + ListFileSearchStoresResponse, + WhiteSpaceConfig, + ChunkingConfig, + UploadToFileSearchStoreConfig, + UploadToFileSearchStoreParameters, + UploadToFileSearchStoreResumableResponse, + ImportFileConfig, + ImportFileParameters, + ImportFileResponse, + ImportFileOperation, + ListFilesConfig, + ListFilesParameters, + FileStatus, + File_2 as File, + ListFilesResponse, + CreateFileConfig, + CreateFileParameters, + CreateFileResponse, + GetFileConfig, + GetFileParameters, + DeleteFileConfig, + DeleteFileParameters, + DeleteFileResponse, + RegisterFilesConfig, + InternalRegisterFilesParameters, + RegisterFilesResponse, + InlinedRequest, + BatchJobSource, + JobError, + InlinedResponse, + SingleEmbedContentResponse, + InlinedEmbedContentResponse, + BatchJobDestination, + CreateBatchJobConfig, + CreateBatchJobParameters, + CompletionStats, + BatchJob, + EmbedContentBatch, + EmbeddingsBatchJobSource, + CreateEmbeddingsBatchJobConfig, + CreateEmbeddingsBatchJobParameters, + GetBatchJobConfig, + GetBatchJobParameters, + CancelBatchJobConfig, + CancelBatchJobParameters, + ListBatchJobsConfig, + ListBatchJobsParameters, + ListBatchJobsResponse, + DeleteBatchJobConfig, + DeleteBatchJobParameters, + DeleteResourceJob, + GetOperationConfig, + GetOperationParameters, + FetchPredictOperationConfig, + FetchPredictOperationParameters, + TestTableItem, + TestTableFile, + ReplayRequest, + ReplayResponse, + ReplayInteraction, + ReplayFile, + UploadFileConfig, + DownloadFileConfig, + DownloadFileParameters, + UpscaleImageConfig, + UpscaleImageParameters, + RawReferenceImage, + MaskReferenceImage, + ControlReferenceImage, + StyleReferenceImage, + SubjectReferenceImage, + ContentReferenceImage, + LiveServerSetupComplete, + Transcription, + LiveServerContent, + LiveServerToolCall, + LiveServerToolCallCancellation, + UsageMetadata, + LiveServerGoAway, + LiveServerSessionResumptionUpdate, + VoiceActivityDetectionSignal, + VoiceActivity, + LiveServerMessage, + OperationFromAPIResponseParameters, + GenerationConfigThinkingConfig, + RegisterFilesParameters, + AutomaticActivityDetection, + RealtimeInputConfig, + SessionResumptionConfig, + SlidingWindow, + ContextWindowCompressionConfig, + AudioTranscriptionConfig, + ProactivityConfig, + LiveClientSetup, + LiveClientContent, + ActivityStart, + ActivityEnd, + LiveClientRealtimeInput, + LiveClientToolResponse, + LiveSendRealtimeInputParameters, + LiveClientMessage, + LiveConnectConfig, + LiveConnectParameters, + CreateChatParameters, + SendMessageParameters, + LiveSendClientContentParameters, + LiveSendToolResponseParameters, + LiveMusicClientSetup, + WeightedPrompt, + LiveMusicClientContent, + LiveMusicGenerationConfig, + LiveMusicClientMessage, + LiveMusicServerSetupComplete, + LiveMusicSourceMetadata, + AudioChunk, + LiveMusicServerContent, + LiveMusicFilteredPrompt, + LiveMusicServerMessage, + LiveMusicCallbacks, + UploadFileParameters, + CallableTool, + CallableToolConfig, + LiveMusicConnectParameters, + LiveMusicSetConfigParameters, + LiveMusicSetWeightedPromptsParameters, + AuthToken, + LiveConnectConstraints, + CreateAuthTokenConfig, + CreateAuthTokenParameters, + OperationGetParameters, + CountTokensResult, + ComputeTokensResult, + CreateTuningJobParameters, + UploadToFileSearchStoreResponse, + UploadToFileSearchStoreOperation, + BlobImageUnion, + PartUnion, + PartListUnion, + ContentUnion, + ContentListUnion, + SchemaUnion, + SpeechConfigUnion, + ToolUnion, + ToolListUnion, + DownloadableFileUnion, + BatchJobSourceUnion, + BatchJobDestinationUnion + } +} + +/** @ts-ignore For users with undici */ +declare type UndiciRequestInit = NotAny<import('../node_modules/undici/index.d.ts').RequestInit> | NotAny<import('../../node_modules/undici/index.d.ts').RequestInit> | NotAny<import('../../../node_modules/undici/index.d.ts').RequestInit> | NotAny<import('../../../../node_modules/undici/index.d.ts').RequestInit> | NotAny<import('../../../../../node_modules/undici/index.d.ts').RequestInit> | NotAny<import('../../../../../../node_modules/undici/index.d.ts').RequestInit> | NotAny<import('../../../../../../../node_modules/undici/index.d.ts').RequestInit> | NotAny<import('../../../../../../../../node_modules/undici/index.d.ts').RequestInit> | NotAny<import('../../../../../../../../../node_modules/undici/index.d.ts').RequestInit> | NotAny<import('../../../../../../../../../../node_modules/undici/index.d.ts').RequestInit>; + +/** + * These imports attempt to get types from a parent package's dependencies. + * Unresolved bare specifiers can trigger [automatic type acquisition][1] in some projects, which + * would cause typescript to show types not present at runtime. To avoid this, we import + * directly from parent node_modules folders. + * + * We need to check multiple levels because we don't know what directory structure we'll be in. + * For example, pnpm generates directories like this: + * ``` + * node_modules + * ├── .pnpm + * │ └── pkg@1.0.0 + * │ └── node_modules + * │ └── pkg + * │ └── internal + * │ └── types.d.ts + * ├── pkg -> .pnpm/pkg@1.0.0/node_modules/pkg + * └── undici + * ``` + * + * [1]: https://www.typescriptlang.org/tsconfig/#typeAcquisition + */ +/** @ts-ignore For users with \@types/node */ +declare type UndiciTypesRequestInit = NotAny<import('../node_modules/undici-types/index.d.ts').RequestInit> | NotAny<import('../../node_modules/undici-types/index.d.ts').RequestInit> | NotAny<import('../../../node_modules/undici-types/index.d.ts').RequestInit> | NotAny<import('../../../../node_modules/undici-types/index.d.ts').RequestInit> | NotAny<import('../../../../../node_modules/undici-types/index.d.ts').RequestInit> | NotAny<import('../../../../../../node_modules/undici-types/index.d.ts').RequestInit> | NotAny<import('../../../../../../../node_modules/undici-types/index.d.ts').RequestInit> | NotAny<import('../../../../../../../../node_modules/undici-types/index.d.ts').RequestInit> | NotAny<import('../../../../../../../../../node_modules/undici-types/index.d.ts').RequestInit> | NotAny<import('../../../../../../../../../../node_modules/undici-types/index.d.ts').RequestInit>; + +declare class UnprocessableEntityError extends APIError<422, Headers> { +} + +/** Optional parameters for caches.update method. */ +export declare interface UpdateCachedContentConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** The TTL for this resource. The expiration time is computed: now + TTL. It is a duration string, with up to nine fractional digits, terminated by 's'. Example: "3.5s". */ + ttl?: string; + /** Timestamp of when this resource is considered expired. Uses RFC 3339 format, Example: 2014-10-02T15:01:23Z. */ + expireTime?: string; +} + +export declare interface UpdateCachedContentParameters { + /** The server-generated resource name of the cached content. + */ + name: string; + /** Configuration that contains optional parameters. + */ + config?: UpdateCachedContentConfig; +} + +/** Configuration for updating a tuned model. */ +export declare interface UpdateModelConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + displayName?: string; + description?: string; + defaultCheckpointId?: string; +} + +/** Configuration for updating a tuned model. */ +export declare interface UpdateModelParameters { + model: string; + config?: UpdateModelConfig; +} + +declare interface Uploader { + /** + * Uploads a file to the given upload url. + * + * @param file The file to upload. file is in string type or a Blob. + * @param uploadUrl The upload URL as a string is where the file will be + * uploaded to. The uploadUrl must be a url that was returned by the + * https://generativelanguage.googleapis.com/upload/v1beta/files endpoint + * @param apiClient The ApiClient to use for uploading. + * @return A Promise that resolves to types.File. + */ + upload(file: string | Blob, uploadUrl: string, apiClient: ApiClient): Promise<File_2>; + /** + * Uploads a file to file search store via the given upload url. + * + * @param file The file to upload. file is in string type or a Blob. + * @param uploadUrl The upload URL as a string is where the file will be + * uploaded to. The uploadUrl must be a url that was returned by the + * https://generativelanguage.googleapis.com/upload/v1beta/{file_search_store_name}:uploadToFileSearchStore endpoint + * @param apiClient The ApiClient to use for uploading. + * @return A Promise that resolves to types.UploadToFileSearchStoreOperation. + */ + uploadToFileSearchStore(file: string | Blob, uploadUrl: string, apiClient: ApiClient): Promise<UploadToFileSearchStoreOperation>; + /** + * Returns the file's mimeType and the size of a given file. If the file is a + * string path, the file type is determined by the file extension. If the + * file's type cannot be determined, the type will be set to undefined. + * + * @param file The file to get the stat for. Can be a string path or a Blob. + * @return A Promise that resolves to the file stat of the given file. + */ + stat(file: string | Blob): Promise<FileStat>; +} + +/** Used to override the default configuration. */ +export declare interface UploadFileConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** The name of the file in the destination (e.g., 'files/sample-image'. If not provided one will be generated. */ + name?: string; + /** mime_type: The MIME type of the file. If not provided, it will be inferred from the file extension. */ + mimeType?: string; + /** Optional display name of the file. */ + displayName?: string; +} + +/** Parameters for the upload file method. */ +export declare interface UploadFileParameters { + /** The string path to the file to be uploaded or a Blob object. */ + file: string | globalThis.Blob; + /** Configuration that contains optional parameters. */ + config?: UploadFileConfig; +} + +/** Optional parameters for uploading a file to a FileSearchStore. */ +export declare interface UploadToFileSearchStoreConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** MIME type of the file to be uploaded. If not provided, it will be inferred from the file extension. */ + mimeType?: string; + /** Display name of the created document. */ + displayName?: string; + /** User provided custom metadata stored as key-value pairs used for querying. */ + customMetadata?: CustomMetadata[]; + /** Config for telling the service how to chunk the file. */ + chunkingConfig?: ChunkingConfig; +} + +/** Long-running operation for uploading a file to a FileSearchStore. */ +export declare class UploadToFileSearchStoreOperation implements Operation<UploadToFileSearchStoreResponse> { + /** The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`. */ + name?: string; + /** Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata. Any method that returns a long-running operation should document the metadata type, if any. */ + metadata?: Record<string, unknown>; + /** If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available. */ + done?: boolean; + /** The error result of the operation in case of failure or cancellation. */ + error?: Record<string, unknown>; + /** The result of the UploadToFileSearchStore operation, available when the operation is done. */ + response?: UploadToFileSearchStoreResponse; + /** + * Instantiates an Operation of the same type as the one being called with the fields set from the API response. + * @internal + */ + _fromAPIResponse({ apiResponse, _isVertexAI, }: OperationFromAPIResponseParameters): Operation<UploadToFileSearchStoreResponse>; + /** The full HTTP response. */ + sdkHttpResponse?: HttpResponse; +} + +/** Generates the parameters for the private _upload_to_file_search_store method. */ +export declare interface UploadToFileSearchStoreParameters { + /** The resource name of the FileSearchStore. Example: `fileSearchStores/my-file-search-store-123` */ + fileSearchStoreName: string; + /** Used to override the default configuration. */ + config?: UploadToFileSearchStoreConfig; +} + +/** Parameters for the upload file to file search store method. */ +export declare interface UploadToFileSearchStoreParameters { + /** The name of the file search store to upload. */ + fileSearchStoreName: string; + /** The string path to the file to be uploaded or a Blob object. */ + file: string | globalThis.Blob; + /** Configuration that contains optional parameters. */ + config?: UploadToFileSearchStoreConfig; +} + +/** The response when long-running operation for uploading a file to a FileSearchStore complete. */ +export declare class UploadToFileSearchStoreResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** The name of the FileSearchStore containing Documents. */ + parent?: string; + /** The identifier for the Document imported. */ + documentName?: string; +} + +/** Response for the resumable upload method. */ +export declare class UploadToFileSearchStoreResumableResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; +} + +/** Configuration for upscaling an image. + + For more information on this configuration, refer to + the `Imagen API reference documentation + <https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/imagen-api>`_. */ +export declare interface UpscaleImageConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** Cloud Storage URI used to store the generated images. */ + outputGcsUri?: string; + /** Filter level for safety filtering. */ + safetyFilterLevel?: SafetyFilterLevel; + /** Allows generation of people by the model. */ + personGeneration?: PersonGeneration; + /** Whether to include a reason for filtered-out images in the + response. */ + includeRaiReason?: boolean; + /** The image format that the output should be saved as. */ + outputMimeType?: string; + /** The level of compression. Only applicable if the + ``output_mime_type`` is ``image/jpeg``. */ + outputCompressionQuality?: number; + /** Whether to add an image enhancing step before upscaling. + It is expected to suppress the noise and JPEG compression artifacts + from the input image. */ + enhanceInputImage?: boolean; + /** With a higher image preservation factor, the original image + pixels are more respected. With a lower image preservation factor, the + output image will have be more different from the input image, but + with finer details and less noise. */ + imagePreservationFactor?: number; + /** User specified labels to track billing usage. */ + labels?: Record<string, string>; +} + +/** User-facing config UpscaleImageParameters. */ +export declare interface UpscaleImageParameters { + /** The model to use. */ + model: string; + /** The input image to upscale. */ + image: Image_2; + /** The factor to upscale the image (x2 or x4). */ + upscaleFactor: string; + /** Configuration for upscaling. */ + config?: UpscaleImageConfig; +} + +export declare class UpscaleImageResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** Generated images. */ + generatedImages?: GeneratedImage[]; +} + +/** Tool to support URL context. */ +export declare interface UrlContext { +} + +/** + * The arguments to pass to the URL context. + */ +declare interface URLContextCallArguments { + /** + * The URLs to fetch. + */ + urls?: Array<string>; +} + +/** + * URL context content. + */ +declare interface URLContextCallContent { + type: 'url_context_call'; + /** + * A unique ID for this specific tool call. + */ + id?: string; + /** + * The arguments to pass to the URL context. + */ + arguments?: URLContextCallArguments; +} + +/** Metadata related to url context retrieval tool. */ +export declare interface UrlContextMetadata { + /** Output only. List of url context. */ + urlMetadata?: UrlMetadata[]; +} + +/** + * The result of the URL context. + */ +declare interface URLContextResult { + /** + * The status of the URL retrieval. + */ + status?: 'success' | 'error' | 'paywall' | 'unsafe'; + /** + * The URL that was fetched. + */ + url?: string; +} + +/** + * URL context result content. + */ +declare interface URLContextResultContent { + type: 'url_context_result'; + /** + * ID to match the ID from the url context call block. + */ + call_id?: string; + /** + * Whether the URL context resulted in an error. + */ + is_error?: boolean; + /** + * The results of the URL context. + */ + result?: Array<URLContextResult>; + /** + * The signature of the URL context result. + */ + signature?: string; +} + +/** Context of the a single url retrieval. */ +export declare interface UrlMetadata { + /** Retrieved url by the tool. */ + retrievedUrl?: string; + /** Status of the url retrieval. */ + urlRetrievalStatus?: UrlRetrievalStatus; +} + +/** Status of the url retrieval. */ +export declare enum UrlRetrievalStatus { + /** + * Default value. This value is unused. + */ + URL_RETRIEVAL_STATUS_UNSPECIFIED = "URL_RETRIEVAL_STATUS_UNSPECIFIED", + /** + * Url retrieval is successful. + */ + URL_RETRIEVAL_STATUS_SUCCESS = "URL_RETRIEVAL_STATUS_SUCCESS", + /** + * Url retrieval is failed due to error. + */ + URL_RETRIEVAL_STATUS_ERROR = "URL_RETRIEVAL_STATUS_ERROR", + /** + * Url retrieval is failed because the content is behind paywall. This enum value is not supported in Vertex AI. + */ + URL_RETRIEVAL_STATUS_PAYWALL = "URL_RETRIEVAL_STATUS_PAYWALL", + /** + * Url retrieval is failed because the content is unsafe. This enum value is not supported in Vertex AI. + */ + URL_RETRIEVAL_STATUS_UNSAFE = "URL_RETRIEVAL_STATUS_UNSAFE" +} + +/** + * Statistics on the interaction request's token usage. + */ +declare interface Usage { + /** + * A breakdown of cached token usage by modality. + */ + cached_tokens_by_modality?: Array<Usage.CachedTokensByModality>; + /** + * A breakdown of input token usage by modality. + */ + input_tokens_by_modality?: Array<Usage.InputTokensByModality>; + /** + * A breakdown of output token usage by modality. + */ + output_tokens_by_modality?: Array<Usage.OutputTokensByModality>; + /** + * A breakdown of tool-use token usage by modality. + */ + tool_use_tokens_by_modality?: Array<Usage.ToolUseTokensByModality>; + /** + * Number of tokens in the cached part of the prompt (the cached content). + */ + total_cached_tokens?: number; + /** + * Number of tokens in the prompt (context). + */ + total_input_tokens?: number; + /** + * Total number of tokens across all the generated responses. + */ + total_output_tokens?: number; + /** + * Number of tokens of thoughts for thinking models. + */ + total_thought_tokens?: number; + /** + * Total token count for the interaction request (prompt + responses + other + * internal tokens). + */ + total_tokens?: number; + /** + * Number of tokens present in tool-use prompt(s). + */ + total_tool_use_tokens?: number; +} + +declare namespace Usage { + /** + * The token count for a single response modality. + */ + interface CachedTokensByModality { + /** + * The modality associated with the token count. + */ + modality?: 'text' | 'image' | 'audio'; + /** + * Number of tokens for the modality. + */ + tokens?: number; + } + /** + * The token count for a single response modality. + */ + interface InputTokensByModality { + /** + * The modality associated with the token count. + */ + modality?: 'text' | 'image' | 'audio'; + /** + * Number of tokens for the modality. + */ + tokens?: number; + } + /** + * The token count for a single response modality. + */ + interface OutputTokensByModality { + /** + * The modality associated with the token count. + */ + modality?: 'text' | 'image' | 'audio'; + /** + * Number of tokens for the modality. + */ + tokens?: number; + } + /** + * The token count for a single response modality. + */ + interface ToolUseTokensByModality { + /** + * The modality associated with the token count. + */ + modality?: 'text' | 'image' | 'audio'; + /** + * Number of tokens for the modality. + */ + tokens?: number; + } +} + +/** Usage metadata about response(s). */ +export declare interface UsageMetadata { + /** Number of tokens in the prompt. When `cached_content` is set, this is still the total effective prompt size meaning this includes the number of tokens in the cached content. */ + promptTokenCount?: number; + /** Number of tokens in the cached part of the prompt (the cached content). */ + cachedContentTokenCount?: number; + /** Total number of tokens across all the generated response candidates. */ + responseTokenCount?: number; + /** Number of tokens present in tool-use prompt(s). */ + toolUsePromptTokenCount?: number; + /** Number of tokens of thoughts for thinking models. */ + thoughtsTokenCount?: number; + /** Total token count for prompt, response candidates, and tool-use prompts(if present). */ + totalTokenCount?: number; + /** List of modalities that were processed in the request input. */ + promptTokensDetails?: ModalityTokenCount[]; + /** List of modalities that were processed in the cache input. */ + cacheTokensDetails?: ModalityTokenCount[]; + /** List of modalities that were returned in the response. */ + responseTokensDetails?: ModalityTokenCount[]; + /** List of modalities that were processed in the tool-use prompt. */ + toolUsePromptTokensDetails?: ModalityTokenCount[]; + /** Traffic type. This shows whether a request consumes Pay-As-You-Go + or Provisioned Throughput quota. */ + trafficType?: TrafficType; +} + +/** The type of the VAD signal. */ +export declare enum VadSignalType { + /** + * The default is VAD_SIGNAL_TYPE_UNSPECIFIED. + */ + VAD_SIGNAL_TYPE_UNSPECIFIED = "VAD_SIGNAL_TYPE_UNSPECIFIED", + /** + * Start of sentence signal. + */ + VAD_SIGNAL_TYPE_SOS = "VAD_SIGNAL_TYPE_SOS", + /** + * End of sentence signal. + */ + VAD_SIGNAL_TYPE_EOS = "VAD_SIGNAL_TYPE_EOS" +} + +/** Hyperparameters for Veo. This data type is not supported in Gemini API. */ +export declare interface VeoHyperParameters { + /** Optional. Number of complete passes the model makes over the entire training dataset during training. */ + epochCount?: string; + /** Optional. Multiplier for adjusting the default learning rate. */ + learningRateMultiplier?: number; + /** Optional. The tuning task. Either I2V or T2V. */ + tuningTask?: TuningTask; +} + +/** Tuning Spec for Veo Model Tuning. This data type is not supported in Gemini API. */ +export declare interface VeoTuningSpec { + /** Optional. Hyperparameters for Veo. */ + hyperParameters?: VeoHyperParameters; + /** Required. Training dataset used for tuning. The dataset can be specified as either a Cloud Storage path to a JSONL file or as the resource name of a Vertex Multimodal Dataset. */ + trainingDatasetUri?: string; + /** Optional. Validation dataset used for tuning. The dataset can be specified as either a Cloud Storage path to a JSONL file or as the resource name of a Vertex Multimodal Dataset. */ + validationDatasetUri?: string; +} + +/** Retrieve from Vertex AI Search datastore or engine for grounding. datastore and engine are mutually exclusive. See https://cloud.google.com/products/agent-builder. This data type is not supported in Gemini API. */ +export declare interface VertexAISearch { + /** Specifications that define the specific DataStores to be searched, along with configurations for those data stores. This is only considered for Engines with multiple data stores. It should only be set if engine is used. */ + dataStoreSpecs?: VertexAISearchDataStoreSpec[]; + /** Optional. Fully-qualified Vertex AI Search data store resource ID. Format: `projects/{project}/locations/{location}/collections/{collection}/dataStores/{dataStore}` */ + datastore?: string; + /** Optional. Fully-qualified Vertex AI Search engine resource ID. Format: `projects/{project}/locations/{location}/collections/{collection}/engines/{engine}` */ + engine?: string; + /** Optional. Filter strings to be passed to the search API. */ + filter?: string; + /** Optional. Number of search results to return per query. The default value is 10. The maximumm allowed value is 10. */ + maxResults?: number; +} + +/** Define data stores within engine to filter on in a search call and configurations for those data stores. For more information, see https://cloud.google.com/generative-ai-app-builder/docs/reference/rpc/google.cloud.discoveryengine.v1#datastorespec. This data type is not supported in Gemini API. */ +export declare interface VertexAISearchDataStoreSpec { + /** Full resource name of DataStore, such as Format: `projects/{project}/locations/{location}/collections/{collection}/dataStores/{dataStore}` */ + dataStore?: string; + /** Optional. Filter specification to filter documents in the data store specified by data_store field. For more information on filtering, see [Filtering](https://cloud.google.com/generative-ai-app-builder/docs/filter-search-metadata) */ + filter?: string; +} + +/** Retrieve from Vertex RAG Store for grounding. This data type is not supported in Gemini API. */ +export declare interface VertexRagStore { + /** Optional. Deprecated. Please use rag_resources instead. */ + ragCorpora?: string[]; + /** Optional. The representation of the rag source. It can be used to specify corpus only or ragfiles. Currently only support one corpus or multiple files from one corpus. In the future we may open up multiple corpora support. */ + ragResources?: VertexRagStoreRagResource[]; + /** Optional. The retrieval config for the Rag query. */ + ragRetrievalConfig?: RagRetrievalConfig; + /** Optional. Number of top k results to return from the selected corpora. */ + similarityTopK?: number; + /** Optional. Currently only supported for Gemini Multimodal Live API. In Gemini Multimodal Live API, if `store_context` bool is specified, Gemini will leverage it to automatically memorize the interactions between the client and Gemini, and retrieve context when needed to augment the response generation for users' ongoing and future interactions. */ + storeContext?: boolean; + /** Optional. Only return results with vector distance smaller than the threshold. */ + vectorDistanceThreshold?: number; +} + +/** The definition of the Rag resource. This data type is not supported in Gemini API. */ +export declare interface VertexRagStoreRagResource { + /** Optional. RagCorpora resource name. Format: `projects/{project}/locations/{location}/ragCorpora/{rag_corpus}` */ + ragCorpus?: string; + /** Optional. rag_file_id. The files should be in the same rag_corpus set in rag_corpus field. */ + ragFileIds?: string[]; +} + +/** A generated video. */ +export declare interface Video { + /** Path to another storage. */ + uri?: string; + /** Video bytes. + * @remarks Encoded as base64 string. */ + videoBytes?: string; + /** Video encoding, for example ``video/mp4``. */ + mimeType?: string; +} + +/** Enum that controls the compression quality of the generated videos. */ +export declare enum VideoCompressionQuality { + /** + * Optimized video compression quality. This will produce videos + with a compressed, smaller file size. + */ + OPTIMIZED = "OPTIMIZED", + /** + * Lossless video compression quality. This will produce videos + with a larger file size. + */ + LOSSLESS = "LOSSLESS" +} + +/** + * A video content block. + */ +declare interface VideoContent { + type: 'video'; + /** + * The video content. + */ + data?: string; + /** + * The mime type of the video. + */ + mime_type?: VideoMimeType; + /** + * The resolution of the media. + */ + resolution?: 'low' | 'medium' | 'high' | 'ultra_high'; + /** + * The URI of the video. + */ + uri?: string; +} + +/** A mask for video generation. */ +export declare interface VideoGenerationMask { + /** The image mask to use for generating videos. */ + image?: Image_2; + /** Describes how the mask will be used. Inpainting masks must + match the aspect ratio of the input video. Outpainting masks can be + either 9:16 or 16:9. */ + maskMode?: VideoGenerationMaskMode; +} + +/** Enum for the mask mode of a video generation mask. */ +export declare enum VideoGenerationMaskMode { + /** + * The image mask contains a masked rectangular region which is + applied on the first frame of the input video. The object described in + the prompt is inserted into this region and will appear in subsequent + frames. + */ + INSERT = "INSERT", + /** + * The image mask is used to determine an object in the + first video frame to track. This object is removed from the video. + */ + REMOVE = "REMOVE", + /** + * The image mask is used to determine a region in the + video. Objects in this region will be removed. + */ + REMOVE_STATIC = "REMOVE_STATIC", + /** + * The image mask contains a masked rectangular region where + the input video will go. The remaining area will be generated. Video + masks are not supported. + */ + OUTPAINT = "OUTPAINT" +} + +/** A reference image for video generation. */ +export declare interface VideoGenerationReferenceImage { + /** The reference image. */ + image?: Image_2; + /** The type of the reference image, which defines how the reference + image will be used to generate the video. */ + referenceType?: VideoGenerationReferenceType; +} + +/** Enum for the reference type of a video generation reference image. */ +export declare enum VideoGenerationReferenceType { + /** + * A reference image that provides assets to the generated video, + such as the scene, an object, a character, etc. + */ + ASSET = "ASSET", + /** + * A reference image that provides aesthetics including colors, + lighting, texture, etc., to be used as the style of the generated video, + such as 'anime', 'photography', 'origami', etc. + */ + STYLE = "STYLE" +} + +/** Metadata describes the input video content. */ +export declare interface VideoMetadata { + /** Optional. The end offset of the video. */ + endOffset?: string; + /** Optional. The frame rate of the video sent to the model. If not specified, the default value will be 1.0. The fps range is (0.0, 24.0]. */ + fps?: number; + /** Optional. The start offset of the video. */ + startOffset?: string; +} + +/** + * The mime type of the video. + */ +declare type VideoMimeType = 'video/mp4' | 'video/mpeg' | 'video/mov' | 'video/avi' | 'video/x-flv' | 'video/mpg' | 'video/webm' | 'video/wmv' | 'video/3gpp' | (string & {}); + +/** Voice activity signal. */ +export declare interface VoiceActivity { + /** The type of the voice activity signal. */ + voiceActivityType?: VoiceActivityType; +} + +export declare interface VoiceActivityDetectionSignal { + /** The type of the VAD signal. */ + vadSignalType?: VadSignalType; +} + +/** The type of the voice activity signal. */ +export declare enum VoiceActivityType { + /** + * The default is VOICE_ACTIVITY_TYPE_UNSPECIFIED. + */ + TYPE_UNSPECIFIED = "TYPE_UNSPECIFIED", + /** + * Start of sentence signal. + */ + ACTIVITY_START = "ACTIVITY_START", + /** + * End of sentence signal. + */ + ACTIVITY_END = "ACTIVITY_END" +} + +export declare interface VoiceConfig { + /** If true, the model will use a replicated voice for the response. */ + replicatedVoiceConfig?: ReplicatedVoiceConfig; + /** The configuration for the prebuilt voice to use. */ + prebuiltVoiceConfig?: PrebuiltVoiceConfig; +} + +declare interface WebSocket_2 { + /** + * Connects the socket to the server. + */ + connect(): void; + /** + * Sends a message to the server. + */ + send(message: string): void; + /** + * Closes the socket connection. + */ + close(): void; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +declare interface WebSocketCallbacks { + onopen: () => void; + onerror: (e: any) => void; + onmessage: (e: any) => void; + onclose: (e: any) => void; +} + +declare interface WebSocketFactory { + /** + * Returns a new WebSocket instance. + */ + create(url: string, headers: Record<string, string>, callbacks: WebSocketCallbacks): WebSocket_2; +} + +/** Maps a prompt to a relative weight to steer music generation. */ +export declare interface WeightedPrompt { + /** Text prompt. */ + text?: string; + /** Weight of the prompt. The weight is used to control the relative + importance of the prompt. Higher weights are more important than lower + weights. + + Weight must not be 0. Weights of all weighted_prompts in this + LiveMusicClientContent message will be normalized. */ + weight?: number; +} + +/** Configuration for a white space chunking algorithm. */ +export declare interface WhiteSpaceConfig { + /** Maximum number of tokens per chunk. */ + maxTokensPerChunk?: number; + /** Maximum number of overlapping tokens between two adjacent chunks. */ + maxOverlapTokens?: number; +} + +export { } diff --git a/server/node_modules/@google/genai/dist/index.cjs b/server/node_modules/@google/genai/dist/index.cjs new file mode 100644 index 0000000..7012bee --- /dev/null +++ b/server/node_modules/@google/genai/dist/index.cjs @@ -0,0 +1,19595 @@ +'use strict'; + +var pRetry = require('p-retry'); + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Overrides the base URLs for the Gemini API and Vertex AI API. + * + * @remarks This function should be called before initializing the SDK. If the + * base URLs are set after initializing the SDK, the base URLs will not be + * updated. Base URLs provided in the HttpOptions will also take precedence over + * URLs set here. + * + * @example + * ```ts + * import {GoogleGenAI, setDefaultBaseUrls} from '@google/genai'; + * // Override the base URL for the Gemini API. + * setDefaultBaseUrls({geminiUrl:'https://gemini.google.com'}); + * + * // Override the base URL for the Vertex AI API. + * setDefaultBaseUrls({vertexUrl: 'https://vertexai.googleapis.com'}); + * + * const ai = new GoogleGenAI({apiKey: 'GEMINI_API_KEY'}); + * ``` + */ +function setDefaultBaseUrls(baseUrlParams) { + baseUrlParams.geminiUrl; + baseUrlParams.vertexUrl; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class BaseModule { +} +function formatMap(templateString, valueMap) { + // Use a regular expression to find all placeholders in the template string + const regex = /\{([^}]+)\}/g; + // Replace each placeholder with its corresponding value from the valueMap + return templateString.replace(regex, (match, key) => { + if (Object.prototype.hasOwnProperty.call(valueMap, key)) { + const value = valueMap[key]; + // Convert the value to a string if it's not a string already + return value !== undefined && value !== null ? String(value) : ''; + } + else { + // Handle missing keys + throw new Error(`Key '${key}' not found in valueMap.`); + } + }); +} +function setValueByPath(data, keys, value) { + for (let i = 0; i < keys.length - 1; i++) { + const key = keys[i]; + if (key.endsWith('[]')) { + const keyName = key.slice(0, -2); + if (!(keyName in data)) { + if (Array.isArray(value)) { + data[keyName] = Array.from({ length: value.length }, () => ({})); + } + else { + throw new Error(`Value must be a list given an array path ${key}`); + } + } + if (Array.isArray(data[keyName])) { + const arrayData = data[keyName]; + if (Array.isArray(value)) { + for (let j = 0; j < arrayData.length; j++) { + const entry = arrayData[j]; + setValueByPath(entry, keys.slice(i + 1), value[j]); + } + } + else { + for (const d of arrayData) { + setValueByPath(d, keys.slice(i + 1), value); + } + } + } + return; + } + else if (key.endsWith('[0]')) { + const keyName = key.slice(0, -3); + if (!(keyName in data)) { + data[keyName] = [{}]; + } + const arrayData = data[keyName]; + setValueByPath(arrayData[0], keys.slice(i + 1), value); + return; + } + if (!data[key] || typeof data[key] !== 'object') { + data[key] = {}; + } + data = data[key]; + } + const keyToSet = keys[keys.length - 1]; + const existingData = data[keyToSet]; + if (existingData !== undefined) { + if (!value || + (typeof value === 'object' && Object.keys(value).length === 0)) { + return; + } + if (value === existingData) { + return; + } + if (typeof existingData === 'object' && + typeof value === 'object' && + existingData !== null && + value !== null) { + Object.assign(existingData, value); + } + else { + throw new Error(`Cannot set value for an existing key. Key: ${keyToSet}`); + } + } + else { + if (keyToSet === '_self' && + typeof value === 'object' && + value !== null && + !Array.isArray(value)) { + const valueAsRecord = value; + Object.assign(data, valueAsRecord); + } + else { + data[keyToSet] = value; + } + } +} +function getValueByPath(data, keys, defaultValue = undefined) { + try { + if (keys.length === 1 && keys[0] === '_self') { + return data; + } + for (let i = 0; i < keys.length; i++) { + if (typeof data !== 'object' || data === null) { + return defaultValue; + } + const key = keys[i]; + if (key.endsWith('[]')) { + const keyName = key.slice(0, -2); + if (keyName in data) { + const arrayData = data[keyName]; + if (!Array.isArray(arrayData)) { + return defaultValue; + } + return arrayData.map((d) => getValueByPath(d, keys.slice(i + 1), defaultValue)); + } + else { + return defaultValue; + } + } + else { + data = data[key]; + } + } + return data; + } + catch (error) { + if (error instanceof TypeError) { + return defaultValue; + } + throw error; + } +} +/** + * Moves values from source paths to destination paths. + * + * Examples: + * moveValueByPath( + * {'requests': [{'content': v1}, {'content': v2}]}, + * {'requests[].*': 'requests[].request.*'} + * ) + * -> {'requests': [{'request': {'content': v1}}, {'request': {'content': v2}}]} + */ +function moveValueByPath(data, paths) { + for (const [sourcePath, destPath] of Object.entries(paths)) { + const sourceKeys = sourcePath.split('.'); + const destKeys = destPath.split('.'); + // Determine keys to exclude from wildcard to avoid cyclic references + const excludeKeys = new Set(); + let wildcardIdx = -1; + for (let i = 0; i < sourceKeys.length; i++) { + if (sourceKeys[i] === '*') { + wildcardIdx = i; + break; + } + } + if (wildcardIdx !== -1 && destKeys.length > wildcardIdx) { + // Extract the intermediate key between source and dest paths + // Example: source=['requests[]', '*'], dest=['requests[]', 'request', '*'] + // We want to exclude 'request' + for (let i = wildcardIdx; i < destKeys.length; i++) { + const key = destKeys[i]; + if (key !== '*' && !key.endsWith('[]') && !key.endsWith('[0]')) { + excludeKeys.add(key); + } + } + } + _moveValueRecursive(data, sourceKeys, destKeys, 0, excludeKeys); + } +} +/** + * Recursively moves values from source path to destination path. + */ +function _moveValueRecursive(data, sourceKeys, destKeys, keyIdx, excludeKeys) { + if (keyIdx >= sourceKeys.length) { + return; + } + if (typeof data !== 'object' || data === null) { + return; + } + const key = sourceKeys[keyIdx]; + if (key.endsWith('[]')) { + const keyName = key.slice(0, -2); + const dataRecord = data; + if (keyName in dataRecord && Array.isArray(dataRecord[keyName])) { + for (const item of dataRecord[keyName]) { + _moveValueRecursive(item, sourceKeys, destKeys, keyIdx + 1, excludeKeys); + } + } + } + else if (key === '*') { + // wildcard - move all fields + if (typeof data === 'object' && data !== null && !Array.isArray(data)) { + const dataRecord = data; + const keysToMove = Object.keys(dataRecord).filter((k) => !k.startsWith('_') && !excludeKeys.has(k)); + const valuesToMove = {}; + for (const k of keysToMove) { + valuesToMove[k] = dataRecord[k]; + } + // Set values at destination + for (const [k, v] of Object.entries(valuesToMove)) { + const newDestKeys = []; + for (const dk of destKeys.slice(keyIdx)) { + if (dk === '*') { + newDestKeys.push(k); + } + else { + newDestKeys.push(dk); + } + } + setValueByPath(dataRecord, newDestKeys, v); + } + for (const k of keysToMove) { + delete dataRecord[k]; + } + } + } + else { + // Navigate to next level + const dataRecord = data; + if (key in dataRecord) { + _moveValueRecursive(dataRecord[key], sourceKeys, destKeys, keyIdx + 1, excludeKeys); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function tBytes$1(fromBytes) { + if (typeof fromBytes !== 'string') { + throw new Error('fromImageBytes must be a string'); + } + // TODO(b/389133914): Remove dummy bytes converter. + return fromBytes; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Code generated by the Google Gen AI SDK generator DO NOT EDIT. +function fetchPredictOperationParametersToVertex(fromObject) { + const toObject = {}; + const fromOperationName = getValueByPath(fromObject, [ + 'operationName', + ]); + if (fromOperationName != null) { + setValueByPath(toObject, ['operationName'], fromOperationName); + } + const fromResourceName = getValueByPath(fromObject, ['resourceName']); + if (fromResourceName != null) { + setValueByPath(toObject, ['_url', 'resourceName'], fromResourceName); + } + return toObject; +} +function generateVideosOperationFromMldev$1(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromResponse = getValueByPath(fromObject, [ + 'response', + 'generateVideoResponse', + ]); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], generateVideosResponseFromMldev$1(fromResponse)); + } + return toObject; +} +function generateVideosOperationFromVertex$1(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], generateVideosResponseFromVertex$1(fromResponse)); + } + return toObject; +} +function generateVideosResponseFromMldev$1(fromObject) { + const toObject = {}; + const fromGeneratedVideos = getValueByPath(fromObject, [ + 'generatedSamples', + ]); + if (fromGeneratedVideos != null) { + let transformedList = fromGeneratedVideos; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedVideoFromMldev$1(item); + }); + } + setValueByPath(toObject, ['generatedVideos'], transformedList); + } + const fromRaiMediaFilteredCount = getValueByPath(fromObject, [ + 'raiMediaFilteredCount', + ]); + if (fromRaiMediaFilteredCount != null) { + setValueByPath(toObject, ['raiMediaFilteredCount'], fromRaiMediaFilteredCount); + } + const fromRaiMediaFilteredReasons = getValueByPath(fromObject, [ + 'raiMediaFilteredReasons', + ]); + if (fromRaiMediaFilteredReasons != null) { + setValueByPath(toObject, ['raiMediaFilteredReasons'], fromRaiMediaFilteredReasons); + } + return toObject; +} +function generateVideosResponseFromVertex$1(fromObject) { + const toObject = {}; + const fromGeneratedVideos = getValueByPath(fromObject, ['videos']); + if (fromGeneratedVideos != null) { + let transformedList = fromGeneratedVideos; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedVideoFromVertex$1(item); + }); + } + setValueByPath(toObject, ['generatedVideos'], transformedList); + } + const fromRaiMediaFilteredCount = getValueByPath(fromObject, [ + 'raiMediaFilteredCount', + ]); + if (fromRaiMediaFilteredCount != null) { + setValueByPath(toObject, ['raiMediaFilteredCount'], fromRaiMediaFilteredCount); + } + const fromRaiMediaFilteredReasons = getValueByPath(fromObject, [ + 'raiMediaFilteredReasons', + ]); + if (fromRaiMediaFilteredReasons != null) { + setValueByPath(toObject, ['raiMediaFilteredReasons'], fromRaiMediaFilteredReasons); + } + return toObject; +} +function generatedVideoFromMldev$1(fromObject) { + const toObject = {}; + const fromVideo = getValueByPath(fromObject, ['video']); + if (fromVideo != null) { + setValueByPath(toObject, ['video'], videoFromMldev$1(fromVideo)); + } + return toObject; +} +function generatedVideoFromVertex$1(fromObject) { + const toObject = {}; + const fromVideo = getValueByPath(fromObject, ['_self']); + if (fromVideo != null) { + setValueByPath(toObject, ['video'], videoFromVertex$1(fromVideo)); + } + return toObject; +} +function getOperationParametersToMldev(fromObject) { + const toObject = {}; + const fromOperationName = getValueByPath(fromObject, [ + 'operationName', + ]); + if (fromOperationName != null) { + setValueByPath(toObject, ['_url', 'operationName'], fromOperationName); + } + return toObject; +} +function getOperationParametersToVertex(fromObject) { + const toObject = {}; + const fromOperationName = getValueByPath(fromObject, [ + 'operationName', + ]); + if (fromOperationName != null) { + setValueByPath(toObject, ['_url', 'operationName'], fromOperationName); + } + return toObject; +} +function importFileOperationFromMldev$1(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], importFileResponseFromMldev$1(fromResponse)); + } + return toObject; +} +function importFileResponseFromMldev$1(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromParent = getValueByPath(fromObject, ['parent']); + if (fromParent != null) { + setValueByPath(toObject, ['parent'], fromParent); + } + const fromDocumentName = getValueByPath(fromObject, ['documentName']); + if (fromDocumentName != null) { + setValueByPath(toObject, ['documentName'], fromDocumentName); + } + return toObject; +} +function uploadToFileSearchStoreOperationFromMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], uploadToFileSearchStoreResponseFromMldev(fromResponse)); + } + return toObject; +} +function uploadToFileSearchStoreResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromParent = getValueByPath(fromObject, ['parent']); + if (fromParent != null) { + setValueByPath(toObject, ['parent'], fromParent); + } + const fromDocumentName = getValueByPath(fromObject, ['documentName']); + if (fromDocumentName != null) { + setValueByPath(toObject, ['documentName'], fromDocumentName); + } + return toObject; +} +function videoFromMldev$1(fromObject) { + const toObject = {}; + const fromUri = getValueByPath(fromObject, ['uri']); + if (fromUri != null) { + setValueByPath(toObject, ['uri'], fromUri); + } + const fromVideoBytes = getValueByPath(fromObject, ['encodedVideo']); + if (fromVideoBytes != null) { + setValueByPath(toObject, ['videoBytes'], tBytes$1(fromVideoBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['encoding']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function videoFromVertex$1(fromObject) { + const toObject = {}; + const fromUri = getValueByPath(fromObject, ['gcsUri']); + if (fromUri != null) { + setValueByPath(toObject, ['uri'], fromUri); + } + const fromVideoBytes = getValueByPath(fromObject, [ + 'bytesBase64Encoded', + ]); + if (fromVideoBytes != null) { + setValueByPath(toObject, ['videoBytes'], tBytes$1(fromVideoBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** Outcome of the code execution. */ +exports.Outcome = void 0; +(function (Outcome) { + /** + * Unspecified status. This value should not be used. + */ + Outcome["OUTCOME_UNSPECIFIED"] = "OUTCOME_UNSPECIFIED"; + /** + * Code execution completed successfully. + */ + Outcome["OUTCOME_OK"] = "OUTCOME_OK"; + /** + * Code execution finished but with a failure. `stderr` should contain the reason. + */ + Outcome["OUTCOME_FAILED"] = "OUTCOME_FAILED"; + /** + * Code execution ran for too long, and was cancelled. There may or may not be a partial output present. + */ + Outcome["OUTCOME_DEADLINE_EXCEEDED"] = "OUTCOME_DEADLINE_EXCEEDED"; +})(exports.Outcome || (exports.Outcome = {})); +/** Programming language of the `code`. */ +exports.Language = void 0; +(function (Language) { + /** + * Unspecified language. This value should not be used. + */ + Language["LANGUAGE_UNSPECIFIED"] = "LANGUAGE_UNSPECIFIED"; + /** + * Python >= 3.10, with numpy and simpy available. + */ + Language["PYTHON"] = "PYTHON"; +})(exports.Language || (exports.Language = {})); +/** Specifies how the response should be scheduled in the conversation. */ +exports.FunctionResponseScheduling = void 0; +(function (FunctionResponseScheduling) { + /** + * This value is unused. + */ + FunctionResponseScheduling["SCHEDULING_UNSPECIFIED"] = "SCHEDULING_UNSPECIFIED"; + /** + * Only add the result to the conversation context, do not interrupt or trigger generation. + */ + FunctionResponseScheduling["SILENT"] = "SILENT"; + /** + * Add the result to the conversation context, and prompt to generate output without interrupting ongoing generation. + */ + FunctionResponseScheduling["WHEN_IDLE"] = "WHEN_IDLE"; + /** + * Add the result to the conversation context, interrupt ongoing generation and prompt to generate output. + */ + FunctionResponseScheduling["INTERRUPT"] = "INTERRUPT"; +})(exports.FunctionResponseScheduling || (exports.FunctionResponseScheduling = {})); +/** The type of the data. */ +exports.Type = void 0; +(function (Type) { + /** + * Not specified, should not be used. + */ + Type["TYPE_UNSPECIFIED"] = "TYPE_UNSPECIFIED"; + /** + * OpenAPI string type + */ + Type["STRING"] = "STRING"; + /** + * OpenAPI number type + */ + Type["NUMBER"] = "NUMBER"; + /** + * OpenAPI integer type + */ + Type["INTEGER"] = "INTEGER"; + /** + * OpenAPI boolean type + */ + Type["BOOLEAN"] = "BOOLEAN"; + /** + * OpenAPI array type + */ + Type["ARRAY"] = "ARRAY"; + /** + * OpenAPI object type + */ + Type["OBJECT"] = "OBJECT"; + /** + * Null type + */ + Type["NULL"] = "NULL"; +})(exports.Type || (exports.Type = {})); +/** The API spec that the external API implements. This enum is not supported in Gemini API. */ +exports.ApiSpec = void 0; +(function (ApiSpec) { + /** + * Unspecified API spec. This value should not be used. + */ + ApiSpec["API_SPEC_UNSPECIFIED"] = "API_SPEC_UNSPECIFIED"; + /** + * Simple search API spec. + */ + ApiSpec["SIMPLE_SEARCH"] = "SIMPLE_SEARCH"; + /** + * Elastic search API spec. + */ + ApiSpec["ELASTIC_SEARCH"] = "ELASTIC_SEARCH"; +})(exports.ApiSpec || (exports.ApiSpec = {})); +/** Type of auth scheme. This enum is not supported in Gemini API. */ +exports.AuthType = void 0; +(function (AuthType) { + AuthType["AUTH_TYPE_UNSPECIFIED"] = "AUTH_TYPE_UNSPECIFIED"; + /** + * No Auth. + */ + AuthType["NO_AUTH"] = "NO_AUTH"; + /** + * API Key Auth. + */ + AuthType["API_KEY_AUTH"] = "API_KEY_AUTH"; + /** + * HTTP Basic Auth. + */ + AuthType["HTTP_BASIC_AUTH"] = "HTTP_BASIC_AUTH"; + /** + * Google Service Account Auth. + */ + AuthType["GOOGLE_SERVICE_ACCOUNT_AUTH"] = "GOOGLE_SERVICE_ACCOUNT_AUTH"; + /** + * OAuth auth. + */ + AuthType["OAUTH"] = "OAUTH"; + /** + * OpenID Connect (OIDC) Auth. + */ + AuthType["OIDC_AUTH"] = "OIDC_AUTH"; +})(exports.AuthType || (exports.AuthType = {})); +/** The location of the API key. This enum is not supported in Gemini API. */ +exports.HttpElementLocation = void 0; +(function (HttpElementLocation) { + HttpElementLocation["HTTP_IN_UNSPECIFIED"] = "HTTP_IN_UNSPECIFIED"; + /** + * Element is in the HTTP request query. + */ + HttpElementLocation["HTTP_IN_QUERY"] = "HTTP_IN_QUERY"; + /** + * Element is in the HTTP request header. + */ + HttpElementLocation["HTTP_IN_HEADER"] = "HTTP_IN_HEADER"; + /** + * Element is in the HTTP request path. + */ + HttpElementLocation["HTTP_IN_PATH"] = "HTTP_IN_PATH"; + /** + * Element is in the HTTP request body. + */ + HttpElementLocation["HTTP_IN_BODY"] = "HTTP_IN_BODY"; + /** + * Element is in the HTTP request cookie. + */ + HttpElementLocation["HTTP_IN_COOKIE"] = "HTTP_IN_COOKIE"; +})(exports.HttpElementLocation || (exports.HttpElementLocation = {})); +/** Sites with confidence level chosen & above this value will be blocked from the search results. This enum is not supported in Gemini API. */ +exports.PhishBlockThreshold = void 0; +(function (PhishBlockThreshold) { + /** + * Defaults to unspecified. + */ + PhishBlockThreshold["PHISH_BLOCK_THRESHOLD_UNSPECIFIED"] = "PHISH_BLOCK_THRESHOLD_UNSPECIFIED"; + /** + * Blocks Low and above confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_LOW_AND_ABOVE"] = "BLOCK_LOW_AND_ABOVE"; + /** + * Blocks Medium and above confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_MEDIUM_AND_ABOVE"] = "BLOCK_MEDIUM_AND_ABOVE"; + /** + * Blocks High and above confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_HIGH_AND_ABOVE"] = "BLOCK_HIGH_AND_ABOVE"; + /** + * Blocks Higher and above confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_HIGHER_AND_ABOVE"] = "BLOCK_HIGHER_AND_ABOVE"; + /** + * Blocks Very high and above confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_VERY_HIGH_AND_ABOVE"] = "BLOCK_VERY_HIGH_AND_ABOVE"; + /** + * Blocks Extremely high confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_ONLY_EXTREMELY_HIGH"] = "BLOCK_ONLY_EXTREMELY_HIGH"; +})(exports.PhishBlockThreshold || (exports.PhishBlockThreshold = {})); +/** Specifies the function Behavior. Currently only supported by the BidiGenerateContent method. This enum is not supported in Vertex AI. */ +exports.Behavior = void 0; +(function (Behavior) { + /** + * This value is unused. + */ + Behavior["UNSPECIFIED"] = "UNSPECIFIED"; + /** + * If set, the system will wait to receive the function response before continuing the conversation. + */ + Behavior["BLOCKING"] = "BLOCKING"; + /** + * If set, the system will not wait to receive the function response. Instead, it will attempt to handle function responses as they become available while maintaining the conversation between the user and the model. + */ + Behavior["NON_BLOCKING"] = "NON_BLOCKING"; +})(exports.Behavior || (exports.Behavior = {})); +/** The mode of the predictor to be used in dynamic retrieval. */ +exports.DynamicRetrievalConfigMode = void 0; +(function (DynamicRetrievalConfigMode) { + /** + * Always trigger retrieval. + */ + DynamicRetrievalConfigMode["MODE_UNSPECIFIED"] = "MODE_UNSPECIFIED"; + /** + * Run retrieval only when system decides it is necessary. + */ + DynamicRetrievalConfigMode["MODE_DYNAMIC"] = "MODE_DYNAMIC"; +})(exports.DynamicRetrievalConfigMode || (exports.DynamicRetrievalConfigMode = {})); +/** Function calling mode. */ +exports.FunctionCallingConfigMode = void 0; +(function (FunctionCallingConfigMode) { + /** + * Unspecified function calling mode. This value should not be used. + */ + FunctionCallingConfigMode["MODE_UNSPECIFIED"] = "MODE_UNSPECIFIED"; + /** + * Default model behavior, model decides to predict either function calls or natural language response. + */ + FunctionCallingConfigMode["AUTO"] = "AUTO"; + /** + * Model is constrained to always predicting function calls only. If "allowed_function_names" are set, the predicted function calls will be limited to any one of "allowed_function_names", else the predicted function calls will be any one of the provided "function_declarations". + */ + FunctionCallingConfigMode["ANY"] = "ANY"; + /** + * Model will not predict any function calls. Model behavior is same as when not passing any function declarations. + */ + FunctionCallingConfigMode["NONE"] = "NONE"; + /** + * Model is constrained to predict either function calls or natural language response. If "allowed_function_names" are set, the predicted function calls will be limited to any one of "allowed_function_names", else the predicted function calls will be any one of the provided "function_declarations". + */ + FunctionCallingConfigMode["VALIDATED"] = "VALIDATED"; +})(exports.FunctionCallingConfigMode || (exports.FunctionCallingConfigMode = {})); +/** The number of thoughts tokens that the model should generate. */ +exports.ThinkingLevel = void 0; +(function (ThinkingLevel) { + /** + * Unspecified thinking level. + */ + ThinkingLevel["THINKING_LEVEL_UNSPECIFIED"] = "THINKING_LEVEL_UNSPECIFIED"; + /** + * Low thinking level. + */ + ThinkingLevel["LOW"] = "LOW"; + /** + * Medium thinking level. + */ + ThinkingLevel["MEDIUM"] = "MEDIUM"; + /** + * High thinking level. + */ + ThinkingLevel["HIGH"] = "HIGH"; + /** + * MINIMAL thinking level. + */ + ThinkingLevel["MINIMAL"] = "MINIMAL"; +})(exports.ThinkingLevel || (exports.ThinkingLevel = {})); +/** Harm category. */ +exports.HarmCategory = void 0; +(function (HarmCategory) { + /** + * The harm category is unspecified. + */ + HarmCategory["HARM_CATEGORY_UNSPECIFIED"] = "HARM_CATEGORY_UNSPECIFIED"; + /** + * The harm category is harassment. + */ + HarmCategory["HARM_CATEGORY_HARASSMENT"] = "HARM_CATEGORY_HARASSMENT"; + /** + * The harm category is hate speech. + */ + HarmCategory["HARM_CATEGORY_HATE_SPEECH"] = "HARM_CATEGORY_HATE_SPEECH"; + /** + * The harm category is sexually explicit content. + */ + HarmCategory["HARM_CATEGORY_SEXUALLY_EXPLICIT"] = "HARM_CATEGORY_SEXUALLY_EXPLICIT"; + /** + * The harm category is dangerous content. + */ + HarmCategory["HARM_CATEGORY_DANGEROUS_CONTENT"] = "HARM_CATEGORY_DANGEROUS_CONTENT"; + /** + * Deprecated: Election filter is not longer supported. The harm category is civic integrity. + */ + HarmCategory["HARM_CATEGORY_CIVIC_INTEGRITY"] = "HARM_CATEGORY_CIVIC_INTEGRITY"; + /** + * The harm category is image hate. This enum value is not supported in Gemini API. + */ + HarmCategory["HARM_CATEGORY_IMAGE_HATE"] = "HARM_CATEGORY_IMAGE_HATE"; + /** + * The harm category is image dangerous content. This enum value is not supported in Gemini API. + */ + HarmCategory["HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT"] = "HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT"; + /** + * The harm category is image harassment. This enum value is not supported in Gemini API. + */ + HarmCategory["HARM_CATEGORY_IMAGE_HARASSMENT"] = "HARM_CATEGORY_IMAGE_HARASSMENT"; + /** + * The harm category is image sexually explicit content. This enum value is not supported in Gemini API. + */ + HarmCategory["HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT"] = "HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT"; + /** + * The harm category is for jailbreak prompts. This enum value is not supported in Gemini API. + */ + HarmCategory["HARM_CATEGORY_JAILBREAK"] = "HARM_CATEGORY_JAILBREAK"; +})(exports.HarmCategory || (exports.HarmCategory = {})); +/** Specify if the threshold is used for probability or severity score. If not specified, the threshold is used for probability score. This enum is not supported in Gemini API. */ +exports.HarmBlockMethod = void 0; +(function (HarmBlockMethod) { + /** + * The harm block method is unspecified. + */ + HarmBlockMethod["HARM_BLOCK_METHOD_UNSPECIFIED"] = "HARM_BLOCK_METHOD_UNSPECIFIED"; + /** + * The harm block method uses both probability and severity scores. + */ + HarmBlockMethod["SEVERITY"] = "SEVERITY"; + /** + * The harm block method uses the probability score. + */ + HarmBlockMethod["PROBABILITY"] = "PROBABILITY"; +})(exports.HarmBlockMethod || (exports.HarmBlockMethod = {})); +/** The harm block threshold. */ +exports.HarmBlockThreshold = void 0; +(function (HarmBlockThreshold) { + /** + * Unspecified harm block threshold. + */ + HarmBlockThreshold["HARM_BLOCK_THRESHOLD_UNSPECIFIED"] = "HARM_BLOCK_THRESHOLD_UNSPECIFIED"; + /** + * Block low threshold and above (i.e. block more). + */ + HarmBlockThreshold["BLOCK_LOW_AND_ABOVE"] = "BLOCK_LOW_AND_ABOVE"; + /** + * Block medium threshold and above. + */ + HarmBlockThreshold["BLOCK_MEDIUM_AND_ABOVE"] = "BLOCK_MEDIUM_AND_ABOVE"; + /** + * Block only high threshold (i.e. block less). + */ + HarmBlockThreshold["BLOCK_ONLY_HIGH"] = "BLOCK_ONLY_HIGH"; + /** + * Block none. + */ + HarmBlockThreshold["BLOCK_NONE"] = "BLOCK_NONE"; + /** + * Turn off the safety filter. + */ + HarmBlockThreshold["OFF"] = "OFF"; +})(exports.HarmBlockThreshold || (exports.HarmBlockThreshold = {})); +/** Output only. The reason why the model stopped generating tokens. + +If empty, the model has not stopped generating the tokens. */ +exports.FinishReason = void 0; +(function (FinishReason) { + /** + * The finish reason is unspecified. + */ + FinishReason["FINISH_REASON_UNSPECIFIED"] = "FINISH_REASON_UNSPECIFIED"; + /** + * Token generation reached a natural stopping point or a configured stop sequence. + */ + FinishReason["STOP"] = "STOP"; + /** + * Token generation reached the configured maximum output tokens. + */ + FinishReason["MAX_TOKENS"] = "MAX_TOKENS"; + /** + * Token generation stopped because the content potentially contains safety violations. NOTE: When streaming, [content][] is empty if content filters blocks the output. + */ + FinishReason["SAFETY"] = "SAFETY"; + /** + * The token generation stopped because of potential recitation. + */ + FinishReason["RECITATION"] = "RECITATION"; + /** + * The token generation stopped because of using an unsupported language. + */ + FinishReason["LANGUAGE"] = "LANGUAGE"; + /** + * All other reasons that stopped the token generation. + */ + FinishReason["OTHER"] = "OTHER"; + /** + * Token generation stopped because the content contains forbidden terms. + */ + FinishReason["BLOCKLIST"] = "BLOCKLIST"; + /** + * Token generation stopped for potentially containing prohibited content. + */ + FinishReason["PROHIBITED_CONTENT"] = "PROHIBITED_CONTENT"; + /** + * Token generation stopped because the content potentially contains Sensitive Personally Identifiable Information (SPII). + */ + FinishReason["SPII"] = "SPII"; + /** + * The function call generated by the model is invalid. + */ + FinishReason["MALFORMED_FUNCTION_CALL"] = "MALFORMED_FUNCTION_CALL"; + /** + * Token generation stopped because generated images have safety violations. + */ + FinishReason["IMAGE_SAFETY"] = "IMAGE_SAFETY"; + /** + * The tool call generated by the model is invalid. + */ + FinishReason["UNEXPECTED_TOOL_CALL"] = "UNEXPECTED_TOOL_CALL"; + /** + * Image generation stopped because the generated images have prohibited content. + */ + FinishReason["IMAGE_PROHIBITED_CONTENT"] = "IMAGE_PROHIBITED_CONTENT"; + /** + * The model was expected to generate an image, but none was generated. + */ + FinishReason["NO_IMAGE"] = "NO_IMAGE"; + /** + * Image generation stopped because the generated image may be a recitation from a source. + */ + FinishReason["IMAGE_RECITATION"] = "IMAGE_RECITATION"; + /** + * Image generation stopped for a reason not otherwise specified. + */ + FinishReason["IMAGE_OTHER"] = "IMAGE_OTHER"; +})(exports.FinishReason || (exports.FinishReason = {})); +/** Output only. Harm probability levels in the content. */ +exports.HarmProbability = void 0; +(function (HarmProbability) { + /** + * Harm probability unspecified. + */ + HarmProbability["HARM_PROBABILITY_UNSPECIFIED"] = "HARM_PROBABILITY_UNSPECIFIED"; + /** + * Negligible level of harm. + */ + HarmProbability["NEGLIGIBLE"] = "NEGLIGIBLE"; + /** + * Low level of harm. + */ + HarmProbability["LOW"] = "LOW"; + /** + * Medium level of harm. + */ + HarmProbability["MEDIUM"] = "MEDIUM"; + /** + * High level of harm. + */ + HarmProbability["HIGH"] = "HIGH"; +})(exports.HarmProbability || (exports.HarmProbability = {})); +/** Output only. Harm severity levels in the content. This enum is not supported in Gemini API. */ +exports.HarmSeverity = void 0; +(function (HarmSeverity) { + /** + * Harm severity unspecified. + */ + HarmSeverity["HARM_SEVERITY_UNSPECIFIED"] = "HARM_SEVERITY_UNSPECIFIED"; + /** + * Negligible level of harm severity. + */ + HarmSeverity["HARM_SEVERITY_NEGLIGIBLE"] = "HARM_SEVERITY_NEGLIGIBLE"; + /** + * Low level of harm severity. + */ + HarmSeverity["HARM_SEVERITY_LOW"] = "HARM_SEVERITY_LOW"; + /** + * Medium level of harm severity. + */ + HarmSeverity["HARM_SEVERITY_MEDIUM"] = "HARM_SEVERITY_MEDIUM"; + /** + * High level of harm severity. + */ + HarmSeverity["HARM_SEVERITY_HIGH"] = "HARM_SEVERITY_HIGH"; +})(exports.HarmSeverity || (exports.HarmSeverity = {})); +/** Status of the url retrieval. */ +exports.UrlRetrievalStatus = void 0; +(function (UrlRetrievalStatus) { + /** + * Default value. This value is unused. + */ + UrlRetrievalStatus["URL_RETRIEVAL_STATUS_UNSPECIFIED"] = "URL_RETRIEVAL_STATUS_UNSPECIFIED"; + /** + * Url retrieval is successful. + */ + UrlRetrievalStatus["URL_RETRIEVAL_STATUS_SUCCESS"] = "URL_RETRIEVAL_STATUS_SUCCESS"; + /** + * Url retrieval is failed due to error. + */ + UrlRetrievalStatus["URL_RETRIEVAL_STATUS_ERROR"] = "URL_RETRIEVAL_STATUS_ERROR"; + /** + * Url retrieval is failed because the content is behind paywall. This enum value is not supported in Vertex AI. + */ + UrlRetrievalStatus["URL_RETRIEVAL_STATUS_PAYWALL"] = "URL_RETRIEVAL_STATUS_PAYWALL"; + /** + * Url retrieval is failed because the content is unsafe. This enum value is not supported in Vertex AI. + */ + UrlRetrievalStatus["URL_RETRIEVAL_STATUS_UNSAFE"] = "URL_RETRIEVAL_STATUS_UNSAFE"; +})(exports.UrlRetrievalStatus || (exports.UrlRetrievalStatus = {})); +/** Output only. The reason why the prompt was blocked. */ +exports.BlockedReason = void 0; +(function (BlockedReason) { + /** + * The blocked reason is unspecified. + */ + BlockedReason["BLOCKED_REASON_UNSPECIFIED"] = "BLOCKED_REASON_UNSPECIFIED"; + /** + * The prompt was blocked for safety reasons. + */ + BlockedReason["SAFETY"] = "SAFETY"; + /** + * The prompt was blocked for other reasons. For example, it may be due to the prompt's language, or because it contains other harmful content. + */ + BlockedReason["OTHER"] = "OTHER"; + /** + * The prompt was blocked because it contains a term from the terminology blocklist. + */ + BlockedReason["BLOCKLIST"] = "BLOCKLIST"; + /** + * The prompt was blocked because it contains prohibited content. + */ + BlockedReason["PROHIBITED_CONTENT"] = "PROHIBITED_CONTENT"; + /** + * The prompt was blocked because it contains content that is unsafe for image generation. + */ + BlockedReason["IMAGE_SAFETY"] = "IMAGE_SAFETY"; + /** + * The prompt was blocked by Model Armor. This enum value is not supported in Gemini API. + */ + BlockedReason["MODEL_ARMOR"] = "MODEL_ARMOR"; + /** + * The prompt was blocked as a jailbreak attempt. This enum value is not supported in Gemini API. + */ + BlockedReason["JAILBREAK"] = "JAILBREAK"; +})(exports.BlockedReason || (exports.BlockedReason = {})); +/** Output only. The traffic type for this request. This enum is not supported in Gemini API. */ +exports.TrafficType = void 0; +(function (TrafficType) { + /** + * Unspecified request traffic type. + */ + TrafficType["TRAFFIC_TYPE_UNSPECIFIED"] = "TRAFFIC_TYPE_UNSPECIFIED"; + /** + * The request was processed using Pay-As-You-Go quota. + */ + TrafficType["ON_DEMAND"] = "ON_DEMAND"; + /** + * Type for Provisioned Throughput traffic. + */ + TrafficType["PROVISIONED_THROUGHPUT"] = "PROVISIONED_THROUGHPUT"; +})(exports.TrafficType || (exports.TrafficType = {})); +/** Server content modalities. */ +exports.Modality = void 0; +(function (Modality) { + /** + * The modality is unspecified. + */ + Modality["MODALITY_UNSPECIFIED"] = "MODALITY_UNSPECIFIED"; + /** + * Indicates the model should return text + */ + Modality["TEXT"] = "TEXT"; + /** + * Indicates the model should return images. + */ + Modality["IMAGE"] = "IMAGE"; + /** + * Indicates the model should return audio. + */ + Modality["AUDIO"] = "AUDIO"; +})(exports.Modality || (exports.Modality = {})); +/** The media resolution to use. */ +exports.MediaResolution = void 0; +(function (MediaResolution) { + /** + * Media resolution has not been set + */ + MediaResolution["MEDIA_RESOLUTION_UNSPECIFIED"] = "MEDIA_RESOLUTION_UNSPECIFIED"; + /** + * Media resolution set to low (64 tokens). + */ + MediaResolution["MEDIA_RESOLUTION_LOW"] = "MEDIA_RESOLUTION_LOW"; + /** + * Media resolution set to medium (256 tokens). + */ + MediaResolution["MEDIA_RESOLUTION_MEDIUM"] = "MEDIA_RESOLUTION_MEDIUM"; + /** + * Media resolution set to high (zoomed reframing with 256 tokens). + */ + MediaResolution["MEDIA_RESOLUTION_HIGH"] = "MEDIA_RESOLUTION_HIGH"; +})(exports.MediaResolution || (exports.MediaResolution = {})); +/** Tuning mode. This enum is not supported in Gemini API. */ +exports.TuningMode = void 0; +(function (TuningMode) { + /** + * Tuning mode is unspecified. + */ + TuningMode["TUNING_MODE_UNSPECIFIED"] = "TUNING_MODE_UNSPECIFIED"; + /** + * Full fine-tuning mode. + */ + TuningMode["TUNING_MODE_FULL"] = "TUNING_MODE_FULL"; + /** + * PEFT adapter tuning mode. + */ + TuningMode["TUNING_MODE_PEFT_ADAPTER"] = "TUNING_MODE_PEFT_ADAPTER"; +})(exports.TuningMode || (exports.TuningMode = {})); +/** Adapter size for tuning. This enum is not supported in Gemini API. */ +exports.AdapterSize = void 0; +(function (AdapterSize) { + /** + * Adapter size is unspecified. + */ + AdapterSize["ADAPTER_SIZE_UNSPECIFIED"] = "ADAPTER_SIZE_UNSPECIFIED"; + /** + * Adapter size 1. + */ + AdapterSize["ADAPTER_SIZE_ONE"] = "ADAPTER_SIZE_ONE"; + /** + * Adapter size 2. + */ + AdapterSize["ADAPTER_SIZE_TWO"] = "ADAPTER_SIZE_TWO"; + /** + * Adapter size 4. + */ + AdapterSize["ADAPTER_SIZE_FOUR"] = "ADAPTER_SIZE_FOUR"; + /** + * Adapter size 8. + */ + AdapterSize["ADAPTER_SIZE_EIGHT"] = "ADAPTER_SIZE_EIGHT"; + /** + * Adapter size 16. + */ + AdapterSize["ADAPTER_SIZE_SIXTEEN"] = "ADAPTER_SIZE_SIXTEEN"; + /** + * Adapter size 32. + */ + AdapterSize["ADAPTER_SIZE_THIRTY_TWO"] = "ADAPTER_SIZE_THIRTY_TWO"; +})(exports.AdapterSize || (exports.AdapterSize = {})); +/** Job state. */ +exports.JobState = void 0; +(function (JobState) { + /** + * The job state is unspecified. + */ + JobState["JOB_STATE_UNSPECIFIED"] = "JOB_STATE_UNSPECIFIED"; + /** + * The job has been just created or resumed and processing has not yet begun. + */ + JobState["JOB_STATE_QUEUED"] = "JOB_STATE_QUEUED"; + /** + * The service is preparing to run the job. + */ + JobState["JOB_STATE_PENDING"] = "JOB_STATE_PENDING"; + /** + * The job is in progress. + */ + JobState["JOB_STATE_RUNNING"] = "JOB_STATE_RUNNING"; + /** + * The job completed successfully. + */ + JobState["JOB_STATE_SUCCEEDED"] = "JOB_STATE_SUCCEEDED"; + /** + * The job failed. + */ + JobState["JOB_STATE_FAILED"] = "JOB_STATE_FAILED"; + /** + * The job is being cancelled. From this state the job may only go to either `JOB_STATE_SUCCEEDED`, `JOB_STATE_FAILED` or `JOB_STATE_CANCELLED`. + */ + JobState["JOB_STATE_CANCELLING"] = "JOB_STATE_CANCELLING"; + /** + * The job has been cancelled. + */ + JobState["JOB_STATE_CANCELLED"] = "JOB_STATE_CANCELLED"; + /** + * The job has been stopped, and can be resumed. + */ + JobState["JOB_STATE_PAUSED"] = "JOB_STATE_PAUSED"; + /** + * The job has expired. + */ + JobState["JOB_STATE_EXPIRED"] = "JOB_STATE_EXPIRED"; + /** + * The job is being updated. Only jobs in the `JOB_STATE_RUNNING` state can be updated. After updating, the job goes back to the `JOB_STATE_RUNNING` state. + */ + JobState["JOB_STATE_UPDATING"] = "JOB_STATE_UPDATING"; + /** + * The job is partially succeeded, some results may be missing due to errors. + */ + JobState["JOB_STATE_PARTIALLY_SUCCEEDED"] = "JOB_STATE_PARTIALLY_SUCCEEDED"; +})(exports.JobState || (exports.JobState = {})); +/** The tuning task. Either I2V or T2V. This enum is not supported in Gemini API. */ +exports.TuningTask = void 0; +(function (TuningTask) { + /** + * Default value. This value is unused. + */ + TuningTask["TUNING_TASK_UNSPECIFIED"] = "TUNING_TASK_UNSPECIFIED"; + /** + * Tuning task for image to video. + */ + TuningTask["TUNING_TASK_I2V"] = "TUNING_TASK_I2V"; + /** + * Tuning task for text to video. + */ + TuningTask["TUNING_TASK_T2V"] = "TUNING_TASK_T2V"; + /** + * Tuning task for reference to video. + */ + TuningTask["TUNING_TASK_R2V"] = "TUNING_TASK_R2V"; +})(exports.TuningTask || (exports.TuningTask = {})); +/** The tokenization quality used for given media. */ +exports.PartMediaResolutionLevel = void 0; +(function (PartMediaResolutionLevel) { + /** + * Media resolution has not been set. + */ + PartMediaResolutionLevel["MEDIA_RESOLUTION_UNSPECIFIED"] = "MEDIA_RESOLUTION_UNSPECIFIED"; + /** + * Media resolution set to low. + */ + PartMediaResolutionLevel["MEDIA_RESOLUTION_LOW"] = "MEDIA_RESOLUTION_LOW"; + /** + * Media resolution set to medium. + */ + PartMediaResolutionLevel["MEDIA_RESOLUTION_MEDIUM"] = "MEDIA_RESOLUTION_MEDIUM"; + /** + * Media resolution set to high. + */ + PartMediaResolutionLevel["MEDIA_RESOLUTION_HIGH"] = "MEDIA_RESOLUTION_HIGH"; + /** + * Media resolution set to ultra high. + */ + PartMediaResolutionLevel["MEDIA_RESOLUTION_ULTRA_HIGH"] = "MEDIA_RESOLUTION_ULTRA_HIGH"; +})(exports.PartMediaResolutionLevel || (exports.PartMediaResolutionLevel = {})); +/** Resource scope. */ +exports.ResourceScope = void 0; +(function (ResourceScope) { + /** + * When setting base_url, this value configures resource scope to be the collection. + The resource name will not include api version, project, or location. + For example, if base_url is set to "https://aiplatform.googleapis.com", + then the resource name for a Model would be + "https://aiplatform.googleapis.com/publishers/google/models/gemini-3-pro-preview + */ + ResourceScope["COLLECTION"] = "COLLECTION"; +})(exports.ResourceScope || (exports.ResourceScope = {})); +/** Options for feature selection preference. */ +exports.FeatureSelectionPreference = void 0; +(function (FeatureSelectionPreference) { + FeatureSelectionPreference["FEATURE_SELECTION_PREFERENCE_UNSPECIFIED"] = "FEATURE_SELECTION_PREFERENCE_UNSPECIFIED"; + FeatureSelectionPreference["PRIORITIZE_QUALITY"] = "PRIORITIZE_QUALITY"; + FeatureSelectionPreference["BALANCED"] = "BALANCED"; + FeatureSelectionPreference["PRIORITIZE_COST"] = "PRIORITIZE_COST"; +})(exports.FeatureSelectionPreference || (exports.FeatureSelectionPreference = {})); +/** The environment being operated. */ +exports.Environment = void 0; +(function (Environment) { + /** + * Defaults to browser. + */ + Environment["ENVIRONMENT_UNSPECIFIED"] = "ENVIRONMENT_UNSPECIFIED"; + /** + * Operates in a web browser. + */ + Environment["ENVIRONMENT_BROWSER"] = "ENVIRONMENT_BROWSER"; +})(exports.Environment || (exports.Environment = {})); +/** Enum that controls the safety filter level for objectionable content. */ +exports.SafetyFilterLevel = void 0; +(function (SafetyFilterLevel) { + SafetyFilterLevel["BLOCK_LOW_AND_ABOVE"] = "BLOCK_LOW_AND_ABOVE"; + SafetyFilterLevel["BLOCK_MEDIUM_AND_ABOVE"] = "BLOCK_MEDIUM_AND_ABOVE"; + SafetyFilterLevel["BLOCK_ONLY_HIGH"] = "BLOCK_ONLY_HIGH"; + SafetyFilterLevel["BLOCK_NONE"] = "BLOCK_NONE"; +})(exports.SafetyFilterLevel || (exports.SafetyFilterLevel = {})); +/** Enum that controls the generation of people. */ +exports.PersonGeneration = void 0; +(function (PersonGeneration) { + /** + * Block generation of images of people. + */ + PersonGeneration["DONT_ALLOW"] = "DONT_ALLOW"; + /** + * Generate images of adults, but not children. + */ + PersonGeneration["ALLOW_ADULT"] = "ALLOW_ADULT"; + /** + * Generate images that include adults and children. + */ + PersonGeneration["ALLOW_ALL"] = "ALLOW_ALL"; +})(exports.PersonGeneration || (exports.PersonGeneration = {})); +/** Enum that specifies the language of the text in the prompt. */ +exports.ImagePromptLanguage = void 0; +(function (ImagePromptLanguage) { + /** + * Auto-detect the language. + */ + ImagePromptLanguage["auto"] = "auto"; + /** + * English + */ + ImagePromptLanguage["en"] = "en"; + /** + * Japanese + */ + ImagePromptLanguage["ja"] = "ja"; + /** + * Korean + */ + ImagePromptLanguage["ko"] = "ko"; + /** + * Hindi + */ + ImagePromptLanguage["hi"] = "hi"; + /** + * Chinese + */ + ImagePromptLanguage["zh"] = "zh"; + /** + * Portuguese + */ + ImagePromptLanguage["pt"] = "pt"; + /** + * Spanish + */ + ImagePromptLanguage["es"] = "es"; +})(exports.ImagePromptLanguage || (exports.ImagePromptLanguage = {})); +/** Enum representing the mask mode of a mask reference image. */ +exports.MaskReferenceMode = void 0; +(function (MaskReferenceMode) { + MaskReferenceMode["MASK_MODE_DEFAULT"] = "MASK_MODE_DEFAULT"; + MaskReferenceMode["MASK_MODE_USER_PROVIDED"] = "MASK_MODE_USER_PROVIDED"; + MaskReferenceMode["MASK_MODE_BACKGROUND"] = "MASK_MODE_BACKGROUND"; + MaskReferenceMode["MASK_MODE_FOREGROUND"] = "MASK_MODE_FOREGROUND"; + MaskReferenceMode["MASK_MODE_SEMANTIC"] = "MASK_MODE_SEMANTIC"; +})(exports.MaskReferenceMode || (exports.MaskReferenceMode = {})); +/** Enum representing the control type of a control reference image. */ +exports.ControlReferenceType = void 0; +(function (ControlReferenceType) { + ControlReferenceType["CONTROL_TYPE_DEFAULT"] = "CONTROL_TYPE_DEFAULT"; + ControlReferenceType["CONTROL_TYPE_CANNY"] = "CONTROL_TYPE_CANNY"; + ControlReferenceType["CONTROL_TYPE_SCRIBBLE"] = "CONTROL_TYPE_SCRIBBLE"; + ControlReferenceType["CONTROL_TYPE_FACE_MESH"] = "CONTROL_TYPE_FACE_MESH"; +})(exports.ControlReferenceType || (exports.ControlReferenceType = {})); +/** Enum representing the subject type of a subject reference image. */ +exports.SubjectReferenceType = void 0; +(function (SubjectReferenceType) { + SubjectReferenceType["SUBJECT_TYPE_DEFAULT"] = "SUBJECT_TYPE_DEFAULT"; + SubjectReferenceType["SUBJECT_TYPE_PERSON"] = "SUBJECT_TYPE_PERSON"; + SubjectReferenceType["SUBJECT_TYPE_ANIMAL"] = "SUBJECT_TYPE_ANIMAL"; + SubjectReferenceType["SUBJECT_TYPE_PRODUCT"] = "SUBJECT_TYPE_PRODUCT"; +})(exports.SubjectReferenceType || (exports.SubjectReferenceType = {})); +/** Enum representing the editing mode. */ +exports.EditMode = void 0; +(function (EditMode) { + EditMode["EDIT_MODE_DEFAULT"] = "EDIT_MODE_DEFAULT"; + EditMode["EDIT_MODE_INPAINT_REMOVAL"] = "EDIT_MODE_INPAINT_REMOVAL"; + EditMode["EDIT_MODE_INPAINT_INSERTION"] = "EDIT_MODE_INPAINT_INSERTION"; + EditMode["EDIT_MODE_OUTPAINT"] = "EDIT_MODE_OUTPAINT"; + EditMode["EDIT_MODE_CONTROLLED_EDITING"] = "EDIT_MODE_CONTROLLED_EDITING"; + EditMode["EDIT_MODE_STYLE"] = "EDIT_MODE_STYLE"; + EditMode["EDIT_MODE_BGSWAP"] = "EDIT_MODE_BGSWAP"; + EditMode["EDIT_MODE_PRODUCT_IMAGE"] = "EDIT_MODE_PRODUCT_IMAGE"; +})(exports.EditMode || (exports.EditMode = {})); +/** Enum that represents the segmentation mode. */ +exports.SegmentMode = void 0; +(function (SegmentMode) { + SegmentMode["FOREGROUND"] = "FOREGROUND"; + SegmentMode["BACKGROUND"] = "BACKGROUND"; + SegmentMode["PROMPT"] = "PROMPT"; + SegmentMode["SEMANTIC"] = "SEMANTIC"; + SegmentMode["INTERACTIVE"] = "INTERACTIVE"; +})(exports.SegmentMode || (exports.SegmentMode = {})); +/** Enum for the reference type of a video generation reference image. */ +exports.VideoGenerationReferenceType = void 0; +(function (VideoGenerationReferenceType) { + /** + * A reference image that provides assets to the generated video, + such as the scene, an object, a character, etc. + */ + VideoGenerationReferenceType["ASSET"] = "ASSET"; + /** + * A reference image that provides aesthetics including colors, + lighting, texture, etc., to be used as the style of the generated video, + such as 'anime', 'photography', 'origami', etc. + */ + VideoGenerationReferenceType["STYLE"] = "STYLE"; +})(exports.VideoGenerationReferenceType || (exports.VideoGenerationReferenceType = {})); +/** Enum for the mask mode of a video generation mask. */ +exports.VideoGenerationMaskMode = void 0; +(function (VideoGenerationMaskMode) { + /** + * The image mask contains a masked rectangular region which is + applied on the first frame of the input video. The object described in + the prompt is inserted into this region and will appear in subsequent + frames. + */ + VideoGenerationMaskMode["INSERT"] = "INSERT"; + /** + * The image mask is used to determine an object in the + first video frame to track. This object is removed from the video. + */ + VideoGenerationMaskMode["REMOVE"] = "REMOVE"; + /** + * The image mask is used to determine a region in the + video. Objects in this region will be removed. + */ + VideoGenerationMaskMode["REMOVE_STATIC"] = "REMOVE_STATIC"; + /** + * The image mask contains a masked rectangular region where + the input video will go. The remaining area will be generated. Video + masks are not supported. + */ + VideoGenerationMaskMode["OUTPAINT"] = "OUTPAINT"; +})(exports.VideoGenerationMaskMode || (exports.VideoGenerationMaskMode = {})); +/** Enum that controls the compression quality of the generated videos. */ +exports.VideoCompressionQuality = void 0; +(function (VideoCompressionQuality) { + /** + * Optimized video compression quality. This will produce videos + with a compressed, smaller file size. + */ + VideoCompressionQuality["OPTIMIZED"] = "OPTIMIZED"; + /** + * Lossless video compression quality. This will produce videos + with a larger file size. + */ + VideoCompressionQuality["LOSSLESS"] = "LOSSLESS"; +})(exports.VideoCompressionQuality || (exports.VideoCompressionQuality = {})); +/** Enum representing the tuning method. */ +exports.TuningMethod = void 0; +(function (TuningMethod) { + /** + * Supervised fine tuning. + */ + TuningMethod["SUPERVISED_FINE_TUNING"] = "SUPERVISED_FINE_TUNING"; + /** + * Preference optimization tuning. + */ + TuningMethod["PREFERENCE_TUNING"] = "PREFERENCE_TUNING"; + /** + * Distillation tuning. + */ + TuningMethod["DISTILLATION"] = "DISTILLATION"; +})(exports.TuningMethod || (exports.TuningMethod = {})); +/** State for the lifecycle of a Document. */ +exports.DocumentState = void 0; +(function (DocumentState) { + DocumentState["STATE_UNSPECIFIED"] = "STATE_UNSPECIFIED"; + DocumentState["STATE_PENDING"] = "STATE_PENDING"; + DocumentState["STATE_ACTIVE"] = "STATE_ACTIVE"; + DocumentState["STATE_FAILED"] = "STATE_FAILED"; +})(exports.DocumentState || (exports.DocumentState = {})); +/** State for the lifecycle of a File. */ +exports.FileState = void 0; +(function (FileState) { + FileState["STATE_UNSPECIFIED"] = "STATE_UNSPECIFIED"; + FileState["PROCESSING"] = "PROCESSING"; + FileState["ACTIVE"] = "ACTIVE"; + FileState["FAILED"] = "FAILED"; +})(exports.FileState || (exports.FileState = {})); +/** Source of the File. */ +exports.FileSource = void 0; +(function (FileSource) { + FileSource["SOURCE_UNSPECIFIED"] = "SOURCE_UNSPECIFIED"; + FileSource["UPLOADED"] = "UPLOADED"; + FileSource["GENERATED"] = "GENERATED"; + FileSource["REGISTERED"] = "REGISTERED"; +})(exports.FileSource || (exports.FileSource = {})); +/** The reason why the turn is complete. */ +exports.TurnCompleteReason = void 0; +(function (TurnCompleteReason) { + /** + * Default value. Reason is unspecified. + */ + TurnCompleteReason["TURN_COMPLETE_REASON_UNSPECIFIED"] = "TURN_COMPLETE_REASON_UNSPECIFIED"; + /** + * The function call generated by the model is invalid. + */ + TurnCompleteReason["MALFORMED_FUNCTION_CALL"] = "MALFORMED_FUNCTION_CALL"; + /** + * The response is rejected by the model. + */ + TurnCompleteReason["RESPONSE_REJECTED"] = "RESPONSE_REJECTED"; + /** + * Needs more input from the user. + */ + TurnCompleteReason["NEED_MORE_INPUT"] = "NEED_MORE_INPUT"; +})(exports.TurnCompleteReason || (exports.TurnCompleteReason = {})); +/** Server content modalities. */ +exports.MediaModality = void 0; +(function (MediaModality) { + /** + * The modality is unspecified. + */ + MediaModality["MODALITY_UNSPECIFIED"] = "MODALITY_UNSPECIFIED"; + /** + * Plain text. + */ + MediaModality["TEXT"] = "TEXT"; + /** + * Images. + */ + MediaModality["IMAGE"] = "IMAGE"; + /** + * Video. + */ + MediaModality["VIDEO"] = "VIDEO"; + /** + * Audio. + */ + MediaModality["AUDIO"] = "AUDIO"; + /** + * Document, e.g. PDF. + */ + MediaModality["DOCUMENT"] = "DOCUMENT"; +})(exports.MediaModality || (exports.MediaModality = {})); +/** The type of the VAD signal. */ +exports.VadSignalType = void 0; +(function (VadSignalType) { + /** + * The default is VAD_SIGNAL_TYPE_UNSPECIFIED. + */ + VadSignalType["VAD_SIGNAL_TYPE_UNSPECIFIED"] = "VAD_SIGNAL_TYPE_UNSPECIFIED"; + /** + * Start of sentence signal. + */ + VadSignalType["VAD_SIGNAL_TYPE_SOS"] = "VAD_SIGNAL_TYPE_SOS"; + /** + * End of sentence signal. + */ + VadSignalType["VAD_SIGNAL_TYPE_EOS"] = "VAD_SIGNAL_TYPE_EOS"; +})(exports.VadSignalType || (exports.VadSignalType = {})); +/** The type of the voice activity signal. */ +exports.VoiceActivityType = void 0; +(function (VoiceActivityType) { + /** + * The default is VOICE_ACTIVITY_TYPE_UNSPECIFIED. + */ + VoiceActivityType["TYPE_UNSPECIFIED"] = "TYPE_UNSPECIFIED"; + /** + * Start of sentence signal. + */ + VoiceActivityType["ACTIVITY_START"] = "ACTIVITY_START"; + /** + * End of sentence signal. + */ + VoiceActivityType["ACTIVITY_END"] = "ACTIVITY_END"; +})(exports.VoiceActivityType || (exports.VoiceActivityType = {})); +/** Start of speech sensitivity. */ +exports.StartSensitivity = void 0; +(function (StartSensitivity) { + /** + * The default is START_SENSITIVITY_LOW. + */ + StartSensitivity["START_SENSITIVITY_UNSPECIFIED"] = "START_SENSITIVITY_UNSPECIFIED"; + /** + * Automatic detection will detect the start of speech more often. + */ + StartSensitivity["START_SENSITIVITY_HIGH"] = "START_SENSITIVITY_HIGH"; + /** + * Automatic detection will detect the start of speech less often. + */ + StartSensitivity["START_SENSITIVITY_LOW"] = "START_SENSITIVITY_LOW"; +})(exports.StartSensitivity || (exports.StartSensitivity = {})); +/** End of speech sensitivity. */ +exports.EndSensitivity = void 0; +(function (EndSensitivity) { + /** + * The default is END_SENSITIVITY_LOW. + */ + EndSensitivity["END_SENSITIVITY_UNSPECIFIED"] = "END_SENSITIVITY_UNSPECIFIED"; + /** + * Automatic detection ends speech more often. + */ + EndSensitivity["END_SENSITIVITY_HIGH"] = "END_SENSITIVITY_HIGH"; + /** + * Automatic detection ends speech less often. + */ + EndSensitivity["END_SENSITIVITY_LOW"] = "END_SENSITIVITY_LOW"; +})(exports.EndSensitivity || (exports.EndSensitivity = {})); +/** The different ways of handling user activity. */ +exports.ActivityHandling = void 0; +(function (ActivityHandling) { + /** + * If unspecified, the default behavior is `START_OF_ACTIVITY_INTERRUPTS`. + */ + ActivityHandling["ACTIVITY_HANDLING_UNSPECIFIED"] = "ACTIVITY_HANDLING_UNSPECIFIED"; + /** + * If true, start of activity will interrupt the model's response (also called "barge in"). The model's current response will be cut-off in the moment of the interruption. This is the default behavior. + */ + ActivityHandling["START_OF_ACTIVITY_INTERRUPTS"] = "START_OF_ACTIVITY_INTERRUPTS"; + /** + * The model's response will not be interrupted. + */ + ActivityHandling["NO_INTERRUPTION"] = "NO_INTERRUPTION"; +})(exports.ActivityHandling || (exports.ActivityHandling = {})); +/** Options about which input is included in the user's turn. */ +exports.TurnCoverage = void 0; +(function (TurnCoverage) { + /** + * If unspecified, the default behavior is `TURN_INCLUDES_ONLY_ACTIVITY`. + */ + TurnCoverage["TURN_COVERAGE_UNSPECIFIED"] = "TURN_COVERAGE_UNSPECIFIED"; + /** + * The users turn only includes activity since the last turn, excluding inactivity (e.g. silence on the audio stream). This is the default behavior. + */ + TurnCoverage["TURN_INCLUDES_ONLY_ACTIVITY"] = "TURN_INCLUDES_ONLY_ACTIVITY"; + /** + * The users turn includes all realtime input since the last turn, including inactivity (e.g. silence on the audio stream). + */ + TurnCoverage["TURN_INCLUDES_ALL_INPUT"] = "TURN_INCLUDES_ALL_INPUT"; +})(exports.TurnCoverage || (exports.TurnCoverage = {})); +/** Scale of the generated music. */ +exports.Scale = void 0; +(function (Scale) { + /** + * Default value. This value is unused. + */ + Scale["SCALE_UNSPECIFIED"] = "SCALE_UNSPECIFIED"; + /** + * C major or A minor. + */ + Scale["C_MAJOR_A_MINOR"] = "C_MAJOR_A_MINOR"; + /** + * Db major or Bb minor. + */ + Scale["D_FLAT_MAJOR_B_FLAT_MINOR"] = "D_FLAT_MAJOR_B_FLAT_MINOR"; + /** + * D major or B minor. + */ + Scale["D_MAJOR_B_MINOR"] = "D_MAJOR_B_MINOR"; + /** + * Eb major or C minor + */ + Scale["E_FLAT_MAJOR_C_MINOR"] = "E_FLAT_MAJOR_C_MINOR"; + /** + * E major or Db minor. + */ + Scale["E_MAJOR_D_FLAT_MINOR"] = "E_MAJOR_D_FLAT_MINOR"; + /** + * F major or D minor. + */ + Scale["F_MAJOR_D_MINOR"] = "F_MAJOR_D_MINOR"; + /** + * Gb major or Eb minor. + */ + Scale["G_FLAT_MAJOR_E_FLAT_MINOR"] = "G_FLAT_MAJOR_E_FLAT_MINOR"; + /** + * G major or E minor. + */ + Scale["G_MAJOR_E_MINOR"] = "G_MAJOR_E_MINOR"; + /** + * Ab major or F minor. + */ + Scale["A_FLAT_MAJOR_F_MINOR"] = "A_FLAT_MAJOR_F_MINOR"; + /** + * A major or Gb minor. + */ + Scale["A_MAJOR_G_FLAT_MINOR"] = "A_MAJOR_G_FLAT_MINOR"; + /** + * Bb major or G minor. + */ + Scale["B_FLAT_MAJOR_G_MINOR"] = "B_FLAT_MAJOR_G_MINOR"; + /** + * B major or Ab minor. + */ + Scale["B_MAJOR_A_FLAT_MINOR"] = "B_MAJOR_A_FLAT_MINOR"; +})(exports.Scale || (exports.Scale = {})); +/** The mode of music generation. */ +exports.MusicGenerationMode = void 0; +(function (MusicGenerationMode) { + /** + * Rely on the server default generation mode. + */ + MusicGenerationMode["MUSIC_GENERATION_MODE_UNSPECIFIED"] = "MUSIC_GENERATION_MODE_UNSPECIFIED"; + /** + * Steer text prompts to regions of latent space with higher quality + music. + */ + MusicGenerationMode["QUALITY"] = "QUALITY"; + /** + * Steer text prompts to regions of latent space with a larger + diversity of music. + */ + MusicGenerationMode["DIVERSITY"] = "DIVERSITY"; + /** + * Steer text prompts to regions of latent space more likely to + generate music with vocals. + */ + MusicGenerationMode["VOCALIZATION"] = "VOCALIZATION"; +})(exports.MusicGenerationMode || (exports.MusicGenerationMode = {})); +/** The playback control signal to apply to the music generation. */ +exports.LiveMusicPlaybackControl = void 0; +(function (LiveMusicPlaybackControl) { + /** + * This value is unused. + */ + LiveMusicPlaybackControl["PLAYBACK_CONTROL_UNSPECIFIED"] = "PLAYBACK_CONTROL_UNSPECIFIED"; + /** + * Start generating the music. + */ + LiveMusicPlaybackControl["PLAY"] = "PLAY"; + /** + * Hold the music generation. Use PLAY to resume from the current position. + */ + LiveMusicPlaybackControl["PAUSE"] = "PAUSE"; + /** + * Stop the music generation and reset the context (prompts retained). + Use PLAY to restart the music generation. + */ + LiveMusicPlaybackControl["STOP"] = "STOP"; + /** + * Reset the context of the music generation without stopping it. + Retains the current prompts and config. + */ + LiveMusicPlaybackControl["RESET_CONTEXT"] = "RESET_CONTEXT"; +})(exports.LiveMusicPlaybackControl || (exports.LiveMusicPlaybackControl = {})); +/** Raw media bytes for function response. + +Text should not be sent as raw bytes, use the FunctionResponse.response +field. */ +class FunctionResponseBlob { +} +/** URI based data for function response. */ +class FunctionResponseFileData { +} +/** A datatype containing media that is part of a `FunctionResponse` message. + +A `FunctionResponsePart` consists of data which has an associated datatype. A +`FunctionResponsePart` can only contain one of the accepted types in +`FunctionResponsePart.data`. + +A `FunctionResponsePart` must have a fixed IANA MIME type identifying the +type and subtype of the media if the `inline_data` field is filled with raw +bytes. */ +class FunctionResponsePart { +} +/** + * Creates a `FunctionResponsePart` object from a `base64` encoded `string`. + */ +function createFunctionResponsePartFromBase64(data, mimeType) { + return { + inlineData: { + data: data, + mimeType: mimeType, + }, + }; +} +/** + * Creates a `FunctionResponsePart` object from a `URI` string. + */ +function createFunctionResponsePartFromUri(uri, mimeType) { + return { + fileData: { + fileUri: uri, + mimeType: mimeType, + }, + }; +} +/** A function response. */ +class FunctionResponse { +} +/** + * Creates a `Part` object from a `URI` string. + */ +function createPartFromUri(uri, mimeType, mediaResolution) { + return Object.assign({ fileData: { + fileUri: uri, + mimeType: mimeType, + } }, (mediaResolution && { mediaResolution: { level: mediaResolution } })); +} +/** + * Creates a `Part` object from a `text` string. + */ +function createPartFromText(text) { + return { + text: text, + }; +} +/** + * Creates a `Part` object from a `FunctionCall` object. + */ +function createPartFromFunctionCall(name, args) { + return { + functionCall: { + name: name, + args: args, + }, + }; +} +/** + * Creates a `Part` object from a `FunctionResponse` object. + */ +function createPartFromFunctionResponse(id, name, response, parts = []) { + return { + functionResponse: Object.assign({ id: id, name: name, response: response }, (parts.length > 0 && { parts })), + }; +} +/** + * Creates a `Part` object from a `base64` encoded `string`. + */ +function createPartFromBase64(data, mimeType, mediaResolution) { + return Object.assign({ inlineData: { + data: data, + mimeType: mimeType, + } }, (mediaResolution && { mediaResolution: { level: mediaResolution } })); +} +/** + * Creates a `Part` object from the `outcome` and `output` of a `CodeExecutionResult` object. + */ +function createPartFromCodeExecutionResult(outcome, output) { + return { + codeExecutionResult: { + outcome: outcome, + output: output, + }, + }; +} +/** + * Creates a `Part` object from the `code` and `language` of an `ExecutableCode` object. + */ +function createPartFromExecutableCode(code, language) { + return { + executableCode: { + code: code, + language: language, + }, + }; +} +function _isPart(obj) { + if (typeof obj === 'object' && obj !== null) { + return ('fileData' in obj || + 'text' in obj || + 'functionCall' in obj || + 'functionResponse' in obj || + 'inlineData' in obj || + 'videoMetadata' in obj || + 'codeExecutionResult' in obj || + 'executableCode' in obj); + } + return false; +} +function _toParts(partOrString) { + const parts = []; + if (typeof partOrString === 'string') { + parts.push(createPartFromText(partOrString)); + } + else if (_isPart(partOrString)) { + parts.push(partOrString); + } + else if (Array.isArray(partOrString)) { + if (partOrString.length === 0) { + throw new Error('partOrString cannot be an empty array'); + } + for (const part of partOrString) { + if (typeof part === 'string') { + parts.push(createPartFromText(part)); + } + else if (_isPart(part)) { + parts.push(part); + } + else { + throw new Error('element in PartUnion must be a Part object or string'); + } + } + } + else { + throw new Error('partOrString must be a Part object, string, or array'); + } + return parts; +} +/** + * Creates a `Content` object with a user role from a `PartListUnion` object or `string`. + */ +function createUserContent(partOrString) { + return { + role: 'user', + parts: _toParts(partOrString), + }; +} +/** + * Creates a `Content` object with a model role from a `PartListUnion` object or `string`. + */ +function createModelContent(partOrString) { + return { + role: 'model', + parts: _toParts(partOrString), + }; +} +/** A wrapper class for the http response. */ +class HttpResponse { + constructor(response) { + // Process the headers. + const headers = {}; + for (const pair of response.headers.entries()) { + headers[pair[0]] = pair[1]; + } + this.headers = headers; + // Keep the original response. + this.responseInternal = response; + } + json() { + return this.responseInternal.json(); + } +} +/** Content filter results for a prompt sent in the request. Note: This is sent only in the first stream chunk and only if no candidates were generated due to content violations. */ +class GenerateContentResponsePromptFeedback { +} +/** Usage metadata about the content generation request and response. This message provides a detailed breakdown of token usage and other relevant metrics. This data type is not supported in Gemini API. */ +class GenerateContentResponseUsageMetadata { +} +/** Response message for PredictionService.GenerateContent. */ +class GenerateContentResponse { + /** + * Returns the concatenation of all text parts from the first candidate in the response. + * + * @remarks + * If there are multiple candidates in the response, the text from the first + * one will be returned. + * If there are non-text parts in the response, the concatenation of all text + * parts will be returned, and a warning will be logged. + * If there are thought parts in the response, the concatenation of all text + * parts excluding the thought parts will be returned. + * + * @example + * ```ts + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: + * 'Why is the sky blue?', + * }); + * + * console.debug(response.text); + * ``` + */ + get text() { + var _a, _b, _c, _d, _e, _f, _g, _h; + if (((_d = (_c = (_b = (_a = this.candidates) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.parts) === null || _d === void 0 ? void 0 : _d.length) === 0) { + return undefined; + } + if (this.candidates && this.candidates.length > 1) { + console.warn('there are multiple candidates in the response, returning text from the first one.'); + } + let text = ''; + let anyTextPartText = false; + const nonTextParts = []; + for (const part of (_h = (_g = (_f = (_e = this.candidates) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.content) === null || _g === void 0 ? void 0 : _g.parts) !== null && _h !== void 0 ? _h : []) { + for (const [fieldName, fieldValue] of Object.entries(part)) { + if (fieldName !== 'text' && + fieldName !== 'thought' && + fieldName !== 'thoughtSignature' && + (fieldValue !== null || fieldValue !== undefined)) { + nonTextParts.push(fieldName); + } + } + if (typeof part.text === 'string') { + if (typeof part.thought === 'boolean' && part.thought) { + continue; + } + anyTextPartText = true; + text += part.text; + } + } + if (nonTextParts.length > 0) { + console.warn(`there are non-text parts ${nonTextParts} in the response, returning concatenation of all text parts. Please refer to the non text parts for a full response from model.`); + } + // part.text === '' is different from part.text is null + return anyTextPartText ? text : undefined; + } + /** + * Returns the concatenation of all inline data parts from the first candidate + * in the response. + * + * @remarks + * If there are multiple candidates in the response, the inline data from the + * first one will be returned. If there are non-inline data parts in the + * response, the concatenation of all inline data parts will be returned, and + * a warning will be logged. + */ + get data() { + var _a, _b, _c, _d, _e, _f, _g, _h; + if (((_d = (_c = (_b = (_a = this.candidates) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.parts) === null || _d === void 0 ? void 0 : _d.length) === 0) { + return undefined; + } + if (this.candidates && this.candidates.length > 1) { + console.warn('there are multiple candidates in the response, returning data from the first one.'); + } + let data = ''; + const nonDataParts = []; + for (const part of (_h = (_g = (_f = (_e = this.candidates) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.content) === null || _g === void 0 ? void 0 : _g.parts) !== null && _h !== void 0 ? _h : []) { + for (const [fieldName, fieldValue] of Object.entries(part)) { + if (fieldName !== 'inlineData' && + (fieldValue !== null || fieldValue !== undefined)) { + nonDataParts.push(fieldName); + } + } + if (part.inlineData && typeof part.inlineData.data === 'string') { + data += atob(part.inlineData.data); + } + } + if (nonDataParts.length > 0) { + console.warn(`there are non-data parts ${nonDataParts} in the response, returning concatenation of all data parts. Please refer to the non data parts for a full response from model.`); + } + return data.length > 0 ? btoa(data) : undefined; + } + /** + * Returns the function calls from the first candidate in the response. + * + * @remarks + * If there are multiple candidates in the response, the function calls from + * the first one will be returned. + * If there are no function calls in the response, undefined will be returned. + * + * @example + * ```ts + * const controlLightFunctionDeclaration: FunctionDeclaration = { + * name: 'controlLight', + * parameters: { + * type: Type.OBJECT, + * description: 'Set the brightness and color temperature of a room light.', + * properties: { + * brightness: { + * type: Type.NUMBER, + * description: + * 'Light level from 0 to 100. Zero is off and 100 is full brightness.', + * }, + * colorTemperature: { + * type: Type.STRING, + * description: + * 'Color temperature of the light fixture which can be `daylight`, `cool` or `warm`.', + * }, + * }, + * required: ['brightness', 'colorTemperature'], + * }; + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: 'Dim the lights so the room feels cozy and warm.', + * config: { + * tools: [{functionDeclarations: [controlLightFunctionDeclaration]}], + * toolConfig: { + * functionCallingConfig: { + * mode: FunctionCallingConfigMode.ANY, + * allowedFunctionNames: ['controlLight'], + * }, + * }, + * }, + * }); + * console.debug(JSON.stringify(response.functionCalls)); + * ``` + */ + get functionCalls() { + var _a, _b, _c, _d, _e, _f, _g, _h; + if (((_d = (_c = (_b = (_a = this.candidates) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.parts) === null || _d === void 0 ? void 0 : _d.length) === 0) { + return undefined; + } + if (this.candidates && this.candidates.length > 1) { + console.warn('there are multiple candidates in the response, returning function calls from the first one.'); + } + const functionCalls = (_h = (_g = (_f = (_e = this.candidates) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.content) === null || _g === void 0 ? void 0 : _g.parts) === null || _h === void 0 ? void 0 : _h.filter((part) => part.functionCall).map((part) => part.functionCall).filter((functionCall) => functionCall !== undefined); + if ((functionCalls === null || functionCalls === void 0 ? void 0 : functionCalls.length) === 0) { + return undefined; + } + return functionCalls; + } + /** + * Returns the first executable code from the first candidate in the response. + * + * @remarks + * If there are multiple candidates in the response, the executable code from + * the first one will be returned. + * If there are no executable code in the response, undefined will be + * returned. + * + * @example + * ```ts + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: + * 'What is the sum of the first 50 prime numbers? Generate and run code for the calculation, and make sure you get all 50.' + * config: { + * tools: [{codeExecution: {}}], + * }, + * }); + * + * console.debug(response.executableCode); + * ``` + */ + get executableCode() { + var _a, _b, _c, _d, _e, _f, _g, _h, _j; + if (((_d = (_c = (_b = (_a = this.candidates) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.parts) === null || _d === void 0 ? void 0 : _d.length) === 0) { + return undefined; + } + if (this.candidates && this.candidates.length > 1) { + console.warn('there are multiple candidates in the response, returning executable code from the first one.'); + } + const executableCode = (_h = (_g = (_f = (_e = this.candidates) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.content) === null || _g === void 0 ? void 0 : _g.parts) === null || _h === void 0 ? void 0 : _h.filter((part) => part.executableCode).map((part) => part.executableCode).filter((executableCode) => executableCode !== undefined); + if ((executableCode === null || executableCode === void 0 ? void 0 : executableCode.length) === 0) { + return undefined; + } + return (_j = executableCode === null || executableCode === void 0 ? void 0 : executableCode[0]) === null || _j === void 0 ? void 0 : _j.code; + } + /** + * Returns the first code execution result from the first candidate in the response. + * + * @remarks + * If there are multiple candidates in the response, the code execution result from + * the first one will be returned. + * If there are no code execution result in the response, undefined will be returned. + * + * @example + * ```ts + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: + * 'What is the sum of the first 50 prime numbers? Generate and run code for the calculation, and make sure you get all 50.' + * config: { + * tools: [{codeExecution: {}}], + * }, + * }); + * + * console.debug(response.codeExecutionResult); + * ``` + */ + get codeExecutionResult() { + var _a, _b, _c, _d, _e, _f, _g, _h, _j; + if (((_d = (_c = (_b = (_a = this.candidates) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.parts) === null || _d === void 0 ? void 0 : _d.length) === 0) { + return undefined; + } + if (this.candidates && this.candidates.length > 1) { + console.warn('there are multiple candidates in the response, returning code execution result from the first one.'); + } + const codeExecutionResult = (_h = (_g = (_f = (_e = this.candidates) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.content) === null || _g === void 0 ? void 0 : _g.parts) === null || _h === void 0 ? void 0 : _h.filter((part) => part.codeExecutionResult).map((part) => part.codeExecutionResult).filter((codeExecutionResult) => codeExecutionResult !== undefined); + if ((codeExecutionResult === null || codeExecutionResult === void 0 ? void 0 : codeExecutionResult.length) === 0) { + return undefined; + } + return (_j = codeExecutionResult === null || codeExecutionResult === void 0 ? void 0 : codeExecutionResult[0]) === null || _j === void 0 ? void 0 : _j.output; + } +} +/** Response for the embed_content method. */ +class EmbedContentResponse { +} +/** The output images response. */ +class GenerateImagesResponse { +} +/** Response for the request to edit an image. */ +class EditImageResponse { +} +class UpscaleImageResponse { +} +/** The output images response. */ +class RecontextImageResponse { +} +/** The output images response. */ +class SegmentImageResponse { +} +class ListModelsResponse { +} +class DeleteModelResponse { +} +/** Response for counting tokens. */ +class CountTokensResponse { +} +/** Response for computing tokens. */ +class ComputeTokensResponse { +} +/** Response with generated videos. */ +class GenerateVideosResponse { +} +/** A video generation operation. */ +class GenerateVideosOperation { + /** + * Instantiates an Operation of the same type as the one being called with the fields set from the API response. + * @internal + */ + _fromAPIResponse({ apiResponse, _isVertexAI, }) { + const operation = new GenerateVideosOperation(); + let response; + const op = apiResponse; + if (_isVertexAI) { + response = generateVideosOperationFromVertex$1(op); + } + else { + response = generateVideosOperationFromMldev$1(op); + } + Object.assign(operation, response); + return operation; + } +} +/** Response for the list tuning jobs method. */ +class ListTuningJobsResponse { +} +/** Empty response for tunings.cancel method. */ +class CancelTuningJobResponse { +} +/** Empty response for caches.delete method. */ +class DeleteCachedContentResponse { +} +class ListCachedContentsResponse { +} +/** Config for documents.list return value. */ +class ListDocumentsResponse { +} +/** Config for file_search_stores.list return value. */ +class ListFileSearchStoresResponse { +} +/** Response for the resumable upload method. */ +class UploadToFileSearchStoreResumableResponse { +} +/** Response for ImportFile to import a File API file with a file search store. */ +class ImportFileResponse { +} +/** Long-running operation for importing a file to a FileSearchStore. */ +class ImportFileOperation { + /** + * Instantiates an Operation of the same type as the one being called with the fields set from the API response. + * @internal + */ + _fromAPIResponse({ apiResponse, _isVertexAI, }) { + const operation = new ImportFileOperation(); + const op = apiResponse; + const response = importFileOperationFromMldev$1(op); + Object.assign(operation, response); + return operation; + } +} +/** Response for the list files method. */ +class ListFilesResponse { +} +/** Response for the create file method. */ +class CreateFileResponse { +} +/** Response for the delete file method. */ +class DeleteFileResponse { +} +/** Response for the _register file method. */ +class RegisterFilesResponse { +} +/** Config for `inlined_responses` parameter. */ +class InlinedResponse { +} +/** Config for `response` parameter. */ +class SingleEmbedContentResponse { +} +/** Config for `inlined_embedding_responses` parameter. */ +class InlinedEmbedContentResponse { +} +/** Config for batches.list return value. */ +class ListBatchJobsResponse { +} +/** Represents a single response in a replay. */ +class ReplayResponse { +} +/** A raw reference image. + +A raw reference image represents the base image to edit, provided by the user. +It can optionally be provided in addition to a mask reference image or +a style reference image. */ +class RawReferenceImage { + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI() { + const referenceImageAPI = { + referenceType: 'REFERENCE_TYPE_RAW', + referenceImage: this.referenceImage, + referenceId: this.referenceId, + }; + return referenceImageAPI; + } +} +/** A mask reference image. + +This encapsulates either a mask image provided by the user and configs for +the user provided mask, or only config parameters for the model to generate +a mask. + +A mask image is an image whose non-zero values indicate where to edit the base +image. If the user provides a mask image, the mask must be in the same +dimensions as the raw image. */ +class MaskReferenceImage { + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI() { + const referenceImageAPI = { + referenceType: 'REFERENCE_TYPE_MASK', + referenceImage: this.referenceImage, + referenceId: this.referenceId, + maskImageConfig: this.config, + }; + return referenceImageAPI; + } +} +/** A control reference image. + +The image of the control reference image is either a control image provided +by the user, or a regular image which the backend will use to generate a +control image of. In the case of the latter, the +enable_control_image_computation field in the config should be set to True. + +A control image is an image that represents a sketch image of areas for the +model to fill in based on the prompt. */ +class ControlReferenceImage { + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI() { + const referenceImageAPI = { + referenceType: 'REFERENCE_TYPE_CONTROL', + referenceImage: this.referenceImage, + referenceId: this.referenceId, + controlImageConfig: this.config, + }; + return referenceImageAPI; + } +} +/** A style reference image. + +This encapsulates a style reference image provided by the user, and +additionally optional config parameters for the style reference image. + +A raw reference image can also be provided as a destination for the style to +be applied to. */ +class StyleReferenceImage { + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI() { + const referenceImageAPI = { + referenceType: 'REFERENCE_TYPE_STYLE', + referenceImage: this.referenceImage, + referenceId: this.referenceId, + styleImageConfig: this.config, + }; + return referenceImageAPI; + } +} +/** A subject reference image. + +This encapsulates a subject reference image provided by the user, and +additionally optional config parameters for the subject reference image. + +A raw reference image can also be provided as a destination for the subject to +be applied to. */ +class SubjectReferenceImage { + /* Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI() { + const referenceImageAPI = { + referenceType: 'REFERENCE_TYPE_SUBJECT', + referenceImage: this.referenceImage, + referenceId: this.referenceId, + subjectImageConfig: this.config, + }; + return referenceImageAPI; + } +} +/** A content reference image. + +A content reference image represents a subject to reference (ex. person, +product, animal) provided by the user. It can optionally be provided in +addition to a style reference image (ex. background, style reference). */ +class ContentReferenceImage { + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI() { + const referenceImageAPI = { + referenceType: 'REFERENCE_TYPE_CONTENT', + referenceImage: this.referenceImage, + referenceId: this.referenceId, + }; + return referenceImageAPI; + } +} +/** Response message for API call. */ +class LiveServerMessage { + /** + * Returns the concatenation of all text parts from the server content if present. + * + * @remarks + * If there are non-text parts in the response, the concatenation of all text + * parts will be returned, and a warning will be logged. + */ + get text() { + var _a, _b, _c; + let text = ''; + let anyTextPartFound = false; + const nonTextParts = []; + for (const part of (_c = (_b = (_a = this.serverContent) === null || _a === void 0 ? void 0 : _a.modelTurn) === null || _b === void 0 ? void 0 : _b.parts) !== null && _c !== void 0 ? _c : []) { + for (const [fieldName, fieldValue] of Object.entries(part)) { + if (fieldName !== 'text' && + fieldName !== 'thought' && + fieldValue !== null) { + nonTextParts.push(fieldName); + } + } + if (typeof part.text === 'string') { + if (typeof part.thought === 'boolean' && part.thought) { + continue; + } + anyTextPartFound = true; + text += part.text; + } + } + if (nonTextParts.length > 0) { + console.warn(`there are non-text parts ${nonTextParts} in the response, returning concatenation of all text parts. Please refer to the non text parts for a full response from model.`); + } + // part.text === '' is different from part.text is null + return anyTextPartFound ? text : undefined; + } + /** + * Returns the concatenation of all inline data parts from the server content if present. + * + * @remarks + * If there are non-inline data parts in the + * response, the concatenation of all inline data parts will be returned, and + * a warning will be logged. + */ + get data() { + var _a, _b, _c; + let data = ''; + const nonDataParts = []; + for (const part of (_c = (_b = (_a = this.serverContent) === null || _a === void 0 ? void 0 : _a.modelTurn) === null || _b === void 0 ? void 0 : _b.parts) !== null && _c !== void 0 ? _c : []) { + for (const [fieldName, fieldValue] of Object.entries(part)) { + if (fieldName !== 'inlineData' && fieldValue !== null) { + nonDataParts.push(fieldName); + } + } + if (part.inlineData && typeof part.inlineData.data === 'string') { + data += atob(part.inlineData.data); + } + } + if (nonDataParts.length > 0) { + console.warn(`there are non-data parts ${nonDataParts} in the response, returning concatenation of all data parts. Please refer to the non data parts for a full response from model.`); + } + return data.length > 0 ? btoa(data) : undefined; + } +} +/** Client generated response to a `ToolCall` received from the server. + +Individual `FunctionResponse` objects are matched to the respective +`FunctionCall` objects by the `id` field. + +Note that in the unary and server-streaming GenerateContent APIs function +calling happens by exchanging the `Content` parts, while in the bidi +GenerateContent APIs function calling happens over this dedicated set of +messages. */ +class LiveClientToolResponse { +} +/** Parameters for sending tool responses to the live API. */ +class LiveSendToolResponseParameters { + constructor() { + /** Tool responses to send to the session. */ + this.functionResponses = []; + } +} +/** Response message for the LiveMusicClientMessage call. */ +class LiveMusicServerMessage { + /** + * Returns the first audio chunk from the server content, if present. + * + * @remarks + * If there are no audio chunks in the response, undefined will be returned. + */ + get audioChunk() { + if (this.serverContent && + this.serverContent.audioChunks && + this.serverContent.audioChunks.length > 0) { + return this.serverContent.audioChunks[0]; + } + return undefined; + } +} +/** The response when long-running operation for uploading a file to a FileSearchStore complete. */ +class UploadToFileSearchStoreResponse { +} +/** Long-running operation for uploading a file to a FileSearchStore. */ +class UploadToFileSearchStoreOperation { + /** + * Instantiates an Operation of the same type as the one being called with the fields set from the API response. + * @internal + */ + _fromAPIResponse({ apiResponse, _isVertexAI, }) { + const operation = new UploadToFileSearchStoreOperation(); + const op = apiResponse; + const response = uploadToFileSearchStoreOperationFromMldev(op); + Object.assign(operation, response); + return operation; + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function tModel(apiClient, model) { + if (!model || typeof model !== 'string') { + throw new Error('model is required and must be a string'); + } + if (model.includes('..') || model.includes('?') || model.includes('&')) { + throw new Error('invalid model parameter'); + } + if (apiClient.isVertexAI()) { + if (model.startsWith('publishers/') || + model.startsWith('projects/') || + model.startsWith('models/')) { + return model; + } + else if (model.indexOf('/') >= 0) { + const parts = model.split('/', 2); + return `publishers/${parts[0]}/models/${parts[1]}`; + } + else { + return `publishers/google/models/${model}`; + } + } + else { + if (model.startsWith('models/') || model.startsWith('tunedModels/')) { + return model; + } + else { + return `models/${model}`; + } + } +} +function tCachesModel(apiClient, model) { + const transformedModel = tModel(apiClient, model); + if (!transformedModel) { + return ''; + } + if (transformedModel.startsWith('publishers/') && apiClient.isVertexAI()) { + // vertex caches only support model name start with projects. + return `projects/${apiClient.getProject()}/locations/${apiClient.getLocation()}/${transformedModel}`; + } + else if (transformedModel.startsWith('models/') && apiClient.isVertexAI()) { + return `projects/${apiClient.getProject()}/locations/${apiClient.getLocation()}/publishers/google/${transformedModel}`; + } + else { + return transformedModel; + } +} +function tBlobs(blobs) { + if (Array.isArray(blobs)) { + return blobs.map((blob) => tBlob(blob)); + } + else { + return [tBlob(blobs)]; + } +} +function tBlob(blob) { + if (typeof blob === 'object' && blob !== null) { + return blob; + } + throw new Error(`Could not parse input as Blob. Unsupported blob type: ${typeof blob}`); +} +function tImageBlob(blob) { + const transformedBlob = tBlob(blob); + if (transformedBlob.mimeType && + transformedBlob.mimeType.startsWith('image/')) { + return transformedBlob; + } + throw new Error(`Unsupported mime type: ${transformedBlob.mimeType}`); +} +function tAudioBlob(blob) { + const transformedBlob = tBlob(blob); + if (transformedBlob.mimeType && + transformedBlob.mimeType.startsWith('audio/')) { + return transformedBlob; + } + throw new Error(`Unsupported mime type: ${transformedBlob.mimeType}`); +} +function tPart(origin) { + if (origin === null || origin === undefined) { + throw new Error('PartUnion is required'); + } + if (typeof origin === 'object') { + return origin; + } + if (typeof origin === 'string') { + return { text: origin }; + } + throw new Error(`Unsupported part type: ${typeof origin}`); +} +function tParts(origin) { + if (origin === null || + origin === undefined || + (Array.isArray(origin) && origin.length === 0)) { + throw new Error('PartListUnion is required'); + } + if (Array.isArray(origin)) { + return origin.map((item) => tPart(item)); + } + return [tPart(origin)]; +} +function _isContent(origin) { + return (origin !== null && + origin !== undefined && + typeof origin === 'object' && + 'parts' in origin && + Array.isArray(origin.parts)); +} +function _isFunctionCallPart(origin) { + return (origin !== null && + origin !== undefined && + typeof origin === 'object' && + 'functionCall' in origin); +} +function _isFunctionResponsePart(origin) { + return (origin !== null && + origin !== undefined && + typeof origin === 'object' && + 'functionResponse' in origin); +} +function tContent(origin) { + if (origin === null || origin === undefined) { + throw new Error('ContentUnion is required'); + } + if (_isContent(origin)) { + // _isContent is a utility function that checks if the + // origin is a Content. + return origin; + } + return { + role: 'user', + parts: tParts(origin), + }; +} +function tContentsForEmbed(apiClient, origin) { + if (!origin) { + return []; + } + if (apiClient.isVertexAI() && Array.isArray(origin)) { + return origin.flatMap((item) => { + const content = tContent(item); + if (content.parts && + content.parts.length > 0 && + content.parts[0].text !== undefined) { + return [content.parts[0].text]; + } + return []; + }); + } + else if (apiClient.isVertexAI()) { + const content = tContent(origin); + if (content.parts && + content.parts.length > 0 && + content.parts[0].text !== undefined) { + return [content.parts[0].text]; + } + return []; + } + if (Array.isArray(origin)) { + return origin.map((item) => tContent(item)); + } + return [tContent(origin)]; +} +function tContents(origin) { + if (origin === null || + origin === undefined || + (Array.isArray(origin) && origin.length === 0)) { + throw new Error('contents are required'); + } + if (!Array.isArray(origin)) { + // If it's not an array, it's a single content or a single PartUnion. + if (_isFunctionCallPart(origin) || _isFunctionResponsePart(origin)) { + throw new Error('To specify functionCall or functionResponse parts, please wrap them in a Content object, specifying the role for them'); + } + return [tContent(origin)]; + } + const result = []; + const accumulatedParts = []; + const isContentArray = _isContent(origin[0]); + for (const item of origin) { + const isContent = _isContent(item); + if (isContent != isContentArray) { + throw new Error('Mixing Content and Parts is not supported, please group the parts into a the appropriate Content objects and specify the roles for them'); + } + if (isContent) { + // `isContent` contains the result of _isContent, which is a utility + // function that checks if the item is a Content. + result.push(item); + } + else if (_isFunctionCallPart(item) || _isFunctionResponsePart(item)) { + throw new Error('To specify functionCall or functionResponse parts, please wrap them, and any other parts, in Content objects as appropriate, specifying the role for them'); + } + else { + accumulatedParts.push(item); + } + } + if (!isContentArray) { + result.push({ role: 'user', parts: tParts(accumulatedParts) }); + } + return result; +} +/* +Transform the type field from an array of types to an array of anyOf fields. +Example: + {type: ['STRING', 'NUMBER']} +will be transformed to + {anyOf: [{type: 'STRING'}, {type: 'NUMBER'}]} +*/ +function flattenTypeArrayToAnyOf(typeList, resultingSchema) { + if (typeList.includes('null')) { + resultingSchema['nullable'] = true; + } + const listWithoutNull = typeList.filter((type) => type !== 'null'); + if (listWithoutNull.length === 1) { + resultingSchema['type'] = Object.values(exports.Type).includes(listWithoutNull[0].toUpperCase()) + ? listWithoutNull[0].toUpperCase() + : exports.Type.TYPE_UNSPECIFIED; + } + else { + resultingSchema['anyOf'] = []; + for (const i of listWithoutNull) { + resultingSchema['anyOf'].push({ + 'type': Object.values(exports.Type).includes(i.toUpperCase()) + ? i.toUpperCase() + : exports.Type.TYPE_UNSPECIFIED, + }); + } + } +} +function processJsonSchema(_jsonSchema) { + const genAISchema = {}; + const schemaFieldNames = ['items']; + const listSchemaFieldNames = ['anyOf']; + const dictSchemaFieldNames = ['properties']; + if (_jsonSchema['type'] && _jsonSchema['anyOf']) { + throw new Error('type and anyOf cannot be both populated.'); + } + /* + This is to handle the nullable array or object. The _jsonSchema will + be in the format of {anyOf: [{type: 'null'}, {type: 'object'}]}. The + logic is to check if anyOf has 2 elements and one of the element is null, + if so, the anyOf field is unnecessary, so we need to get rid of the anyOf + field and make the schema nullable. Then use the other element as the new + _jsonSchema for processing. This is because the backend doesn't have a null + type. + This has to be checked before we process any other fields. + For example: + const objectNullable = z.object({ + nullableArray: z.array(z.string()).nullable(), + }); + Will have the raw _jsonSchema as: + { + type: 'OBJECT', + properties: { + nullableArray: { + anyOf: [ + {type: 'null'}, + { + type: 'array', + items: {type: 'string'}, + }, + ], + } + }, + required: [ 'nullableArray' ], + } + Will result in following schema compatible with Gemini API: + { + type: 'OBJECT', + properties: { + nullableArray: { + nullable: true, + type: 'ARRAY', + items: {type: 'string'}, + } + }, + required: [ 'nullableArray' ], + } + */ + const incomingAnyOf = _jsonSchema['anyOf']; + if (incomingAnyOf != null && incomingAnyOf.length == 2) { + if (incomingAnyOf[0]['type'] === 'null') { + genAISchema['nullable'] = true; + _jsonSchema = incomingAnyOf[1]; + } + else if (incomingAnyOf[1]['type'] === 'null') { + genAISchema['nullable'] = true; + _jsonSchema = incomingAnyOf[0]; + } + } + if (_jsonSchema['type'] instanceof Array) { + flattenTypeArrayToAnyOf(_jsonSchema['type'], genAISchema); + } + for (const [fieldName, fieldValue] of Object.entries(_jsonSchema)) { + // Skip if the fieldvalue is undefined or null. + if (fieldValue == null) { + continue; + } + if (fieldName == 'type') { + if (fieldValue === 'null') { + throw new Error('type: null can not be the only possible type for the field.'); + } + if (fieldValue instanceof Array) { + // we have already handled the type field with array of types in the + // beginning of this function. + continue; + } + genAISchema['type'] = Object.values(exports.Type).includes(fieldValue.toUpperCase()) + ? fieldValue.toUpperCase() + : exports.Type.TYPE_UNSPECIFIED; + } + else if (schemaFieldNames.includes(fieldName)) { + genAISchema[fieldName] = + processJsonSchema(fieldValue); + } + else if (listSchemaFieldNames.includes(fieldName)) { + const listSchemaFieldValue = []; + for (const item of fieldValue) { + if (item['type'] == 'null') { + genAISchema['nullable'] = true; + continue; + } + listSchemaFieldValue.push(processJsonSchema(item)); + } + genAISchema[fieldName] = + listSchemaFieldValue; + } + else if (dictSchemaFieldNames.includes(fieldName)) { + const dictSchemaFieldValue = {}; + for (const [key, value] of Object.entries(fieldValue)) { + dictSchemaFieldValue[key] = processJsonSchema(value); + } + genAISchema[fieldName] = + dictSchemaFieldValue; + } + else { + // additionalProperties is not included in JSONSchema, skipping it. + if (fieldName === 'additionalProperties') { + continue; + } + genAISchema[fieldName] = fieldValue; + } + } + return genAISchema; +} +// we take the unknown in the schema field because we want enable user to pass +// the output of major schema declaration tools without casting. Tools such as +// zodToJsonSchema, typebox, zodToJsonSchema function can return JsonSchema7Type +// or object, see details in +// https://github.com/StefanTerdell/zod-to-json-schema/blob/70525efe555cd226691e093d171370a3b10921d1/src/zodToJsonSchema.ts#L7 +// typebox can return unknown, see details in +// https://github.com/sinclairzx81/typebox/blob/5a5431439f7d5ca6b494d0d18fbfd7b1a356d67c/src/type/create/type.ts#L35 +// Note: proper json schemas with the $schema field set never arrive to this +// transformer. Schemas with $schema are routed to the equivalent API json +// schema field. +function tSchema(schema) { + return processJsonSchema(schema); +} +function tSpeechConfig(speechConfig) { + if (typeof speechConfig === 'object') { + return speechConfig; + } + else if (typeof speechConfig === 'string') { + return { + voiceConfig: { + prebuiltVoiceConfig: { + voiceName: speechConfig, + }, + }, + }; + } + else { + throw new Error(`Unsupported speechConfig type: ${typeof speechConfig}`); + } +} +function tLiveSpeechConfig(speechConfig) { + if ('multiSpeakerVoiceConfig' in speechConfig) { + throw new Error('multiSpeakerVoiceConfig is not supported in the live API.'); + } + return speechConfig; +} +function tTool(tool) { + if (tool.functionDeclarations) { + for (const functionDeclaration of tool.functionDeclarations) { + if (functionDeclaration.parameters) { + if (!Object.keys(functionDeclaration.parameters).includes('$schema')) { + functionDeclaration.parameters = processJsonSchema(functionDeclaration.parameters); + } + else { + if (!functionDeclaration.parametersJsonSchema) { + functionDeclaration.parametersJsonSchema = + functionDeclaration.parameters; + delete functionDeclaration.parameters; + } + } + } + if (functionDeclaration.response) { + if (!Object.keys(functionDeclaration.response).includes('$schema')) { + functionDeclaration.response = processJsonSchema(functionDeclaration.response); + } + else { + if (!functionDeclaration.responseJsonSchema) { + functionDeclaration.responseJsonSchema = + functionDeclaration.response; + delete functionDeclaration.response; + } + } + } + } + } + return tool; +} +function tTools(tools) { + // Check if the incoming type is defined. + if (tools === undefined || tools === null) { + throw new Error('tools is required'); + } + if (!Array.isArray(tools)) { + throw new Error('tools is required and must be an array of Tools'); + } + const result = []; + for (const tool of tools) { + result.push(tool); + } + return result; +} +/** + * Prepends resource name with project, location, resource_prefix if needed. + * + * @param client The API client. + * @param resourceName The resource name. + * @param resourcePrefix The resource prefix. + * @param splitsAfterPrefix The number of splits after the prefix. + * @returns The completed resource name. + * + * Examples: + * + * ``` + * resource_name = '123' + * resource_prefix = 'cachedContents' + * splits_after_prefix = 1 + * client.vertexai = True + * client.project = 'bar' + * client.location = 'us-west1' + * _resource_name(client, resource_name, resource_prefix, splits_after_prefix) + * returns: 'projects/bar/locations/us-west1/cachedContents/123' + * ``` + * + * ``` + * resource_name = 'projects/foo/locations/us-central1/cachedContents/123' + * resource_prefix = 'cachedContents' + * splits_after_prefix = 1 + * client.vertexai = True + * client.project = 'bar' + * client.location = 'us-west1' + * _resource_name(client, resource_name, resource_prefix, splits_after_prefix) + * returns: 'projects/foo/locations/us-central1/cachedContents/123' + * ``` + * + * ``` + * resource_name = '123' + * resource_prefix = 'cachedContents' + * splits_after_prefix = 1 + * client.vertexai = False + * _resource_name(client, resource_name, resource_prefix, splits_after_prefix) + * returns 'cachedContents/123' + * ``` + * + * ``` + * resource_name = 'some/wrong/cachedContents/resource/name/123' + * resource_prefix = 'cachedContents' + * splits_after_prefix = 1 + * client.vertexai = False + * # client.vertexai = True + * _resource_name(client, resource_name, resource_prefix, splits_after_prefix) + * -> 'some/wrong/resource/name/123' + * ``` + */ +function resourceName(client, resourceName, resourcePrefix, splitsAfterPrefix = 1) { + const shouldAppendPrefix = !resourceName.startsWith(`${resourcePrefix}/`) && + resourceName.split('/').length === splitsAfterPrefix; + if (client.isVertexAI()) { + if (resourceName.startsWith('projects/')) { + return resourceName; + } + else if (resourceName.startsWith('locations/')) { + return `projects/${client.getProject()}/${resourceName}`; + } + else if (resourceName.startsWith(`${resourcePrefix}/`)) { + return `projects/${client.getProject()}/locations/${client.getLocation()}/${resourceName}`; + } + else if (shouldAppendPrefix) { + return `projects/${client.getProject()}/locations/${client.getLocation()}/${resourcePrefix}/${resourceName}`; + } + else { + return resourceName; + } + } + if (shouldAppendPrefix) { + return `${resourcePrefix}/${resourceName}`; + } + return resourceName; +} +function tCachedContentName(apiClient, name) { + if (typeof name !== 'string') { + throw new Error('name must be a string'); + } + return resourceName(apiClient, name, 'cachedContents'); +} +function tTuningJobStatus(status) { + switch (status) { + case 'STATE_UNSPECIFIED': + return 'JOB_STATE_UNSPECIFIED'; + case 'CREATING': + return 'JOB_STATE_RUNNING'; + case 'ACTIVE': + return 'JOB_STATE_SUCCEEDED'; + case 'FAILED': + return 'JOB_STATE_FAILED'; + default: + return status; + } +} +function tBytes(fromImageBytes) { + return tBytes$1(fromImageBytes); +} +function _isFile(origin) { + return (origin !== null && + origin !== undefined && + typeof origin === 'object' && + 'name' in origin); +} +function isGeneratedVideo(origin) { + return (origin !== null && + origin !== undefined && + typeof origin === 'object' && + 'video' in origin); +} +function isVideo(origin) { + return (origin !== null && + origin !== undefined && + typeof origin === 'object' && + 'uri' in origin); +} +function tFileName(fromName) { + var _a; + let name; + if (_isFile(fromName)) { + name = fromName.name; + } + if (isVideo(fromName)) { + name = fromName.uri; + if (name === undefined) { + return undefined; + } + } + if (isGeneratedVideo(fromName)) { + name = (_a = fromName.video) === null || _a === void 0 ? void 0 : _a.uri; + if (name === undefined) { + return undefined; + } + } + if (typeof fromName === 'string') { + name = fromName; + } + if (name === undefined) { + throw new Error('Could not extract file name from the provided input.'); + } + if (name.startsWith('https://')) { + const suffix = name.split('files/')[1]; + const match = suffix.match(/[a-z0-9]+/); + if (match === null) { + throw new Error(`Could not extract file name from URI ${name}`); + } + name = match[0]; + } + else if (name.startsWith('files/')) { + name = name.split('files/')[1]; + } + return name; +} +function tModelsUrl(apiClient, baseModels) { + let res; + if (apiClient.isVertexAI()) { + res = baseModels ? 'publishers/google/models' : 'models'; + } + else { + res = baseModels ? 'models' : 'tunedModels'; + } + return res; +} +function tExtractModels(response) { + for (const key of ['models', 'tunedModels', 'publisherModels']) { + if (hasField(response, key)) { + return response[key]; + } + } + return []; +} +function hasField(data, fieldName) { + return data !== null && typeof data === 'object' && fieldName in data; +} +function mcpToGeminiTool(mcpTool, config = {}) { + const mcpToolSchema = mcpTool; + const functionDeclaration = { + name: mcpToolSchema['name'], + description: mcpToolSchema['description'], + parametersJsonSchema: mcpToolSchema['inputSchema'], + }; + if (mcpToolSchema['outputSchema']) { + functionDeclaration['responseJsonSchema'] = mcpToolSchema['outputSchema']; + } + if (config.behavior) { + functionDeclaration['behavior'] = config.behavior; + } + const geminiTool = { + functionDeclarations: [ + functionDeclaration, + ], + }; + return geminiTool; +} +/** + * Converts a list of MCP tools to a single Gemini tool with a list of function + * declarations. + */ +function mcpToolsToGeminiTool(mcpTools, config = {}) { + const functionDeclarations = []; + const toolNames = new Set(); + for (const mcpTool of mcpTools) { + const mcpToolName = mcpTool.name; + if (toolNames.has(mcpToolName)) { + throw new Error(`Duplicate function name ${mcpToolName} found in MCP tools. Please ensure function names are unique.`); + } + toolNames.add(mcpToolName); + const geminiTool = mcpToGeminiTool(mcpTool, config); + if (geminiTool.functionDeclarations) { + functionDeclarations.push(...geminiTool.functionDeclarations); + } + } + return { functionDeclarations: functionDeclarations }; +} +// Transforms a source input into a BatchJobSource object with validation. +function tBatchJobSource(client, src) { + let sourceObj; + if (typeof src === 'string') { + if (client.isVertexAI()) { + if (src.startsWith('gs://')) { + sourceObj = { format: 'jsonl', gcsUri: [src] }; + } + else if (src.startsWith('bq://')) { + sourceObj = { format: 'bigquery', bigqueryUri: src }; + } + else { + throw new Error(`Unsupported string source for Vertex AI: ${src}`); + } + } + else { + // MLDEV + if (src.startsWith('files/')) { + sourceObj = { fileName: src }; // Default to fileName for string input + } + else { + throw new Error(`Unsupported string source for Gemini API: ${src}`); + } + } + } + else if (Array.isArray(src)) { + if (client.isVertexAI()) { + throw new Error('InlinedRequest[] is not supported in Vertex AI.'); + } + sourceObj = { inlinedRequests: src }; + } + else { + // It's already a BatchJobSource object + sourceObj = src; + } + // Validation logic + const vertexSourcesCount = [sourceObj.gcsUri, sourceObj.bigqueryUri].filter(Boolean).length; + const mldevSourcesCount = [ + sourceObj.inlinedRequests, + sourceObj.fileName, + ].filter(Boolean).length; + if (client.isVertexAI()) { + if (mldevSourcesCount > 0 || vertexSourcesCount !== 1) { + throw new Error('Exactly one of `gcsUri` or `bigqueryUri` must be set for Vertex AI.'); + } + } + else { + // MLDEV + if (vertexSourcesCount > 0 || mldevSourcesCount !== 1) { + throw new Error('Exactly one of `inlinedRequests`, `fileName`, ' + + 'must be set for Gemini API.'); + } + } + return sourceObj; +} +function tBatchJobDestination(dest) { + if (typeof dest !== 'string') { + return dest; + } + const destString = dest; + if (destString.startsWith('gs://')) { + return { + format: 'jsonl', + gcsUri: destString, + }; + } + else if (destString.startsWith('bq://')) { + return { + format: 'bigquery', + bigqueryUri: destString, + }; + } + else { + throw new Error(`Unsupported destination: ${destString}`); + } +} +function tRecvBatchJobDestination(dest) { + // Ensure dest is a non-null object before proceeding. + if (typeof dest !== 'object' || dest === null) { + // If the input is not an object, it cannot be a valid BatchJobDestination + // based on the operations performed. Return it cast, or handle as an error. + // Casting an empty object might be a safe default. + return {}; + } + // Cast to Record<string, unknown> to allow string property access. + const obj = dest; + // Safely access nested properties. + const inlineResponsesVal = obj['inlinedResponses']; + if (typeof inlineResponsesVal !== 'object' || inlineResponsesVal === null) { + return dest; + } + const inlineResponsesObj = inlineResponsesVal; + const responsesArray = inlineResponsesObj['inlinedResponses']; + if (!Array.isArray(responsesArray) || responsesArray.length === 0) { + return dest; + } + // Check if any response has the 'embedding' property. + let hasEmbedding = false; + for (const responseItem of responsesArray) { + if (typeof responseItem !== 'object' || responseItem === null) { + continue; + } + const responseItemObj = responseItem; + const responseVal = responseItemObj['response']; + if (typeof responseVal !== 'object' || responseVal === null) { + continue; + } + const responseObj = responseVal; + // Check for the existence of the 'embedding' key. + if (responseObj['embedding'] !== undefined) { + hasEmbedding = true; + break; + } + } + // Perform the transformation if an embedding was found. + if (hasEmbedding) { + obj['inlinedEmbedContentResponses'] = obj['inlinedResponses']; + delete obj['inlinedResponses']; + } + // Cast the (potentially) modified object to the target type. + return dest; +} +function tBatchJobName(apiClient, name) { + const nameString = name; + if (!apiClient.isVertexAI()) { + const mldevPattern = /batches\/[^/]+$/; + if (mldevPattern.test(nameString)) { + return nameString.split('/').pop(); + } + else { + throw new Error(`Invalid batch job name: ${nameString}.`); + } + } + const vertexPattern = /^projects\/[^/]+\/locations\/[^/]+\/batchPredictionJobs\/[^/]+$/; + if (vertexPattern.test(nameString)) { + return nameString.split('/').pop(); + } + else if (/^\d+$/.test(nameString)) { + return nameString; + } + else { + throw new Error(`Invalid batch job name: ${nameString}.`); + } +} +function tJobState(state) { + const stateString = state; + if (stateString === 'BATCH_STATE_UNSPECIFIED') { + return 'JOB_STATE_UNSPECIFIED'; + } + else if (stateString === 'BATCH_STATE_PENDING') { + return 'JOB_STATE_PENDING'; + } + else if (stateString === 'BATCH_STATE_RUNNING') { + return 'JOB_STATE_RUNNING'; + } + else if (stateString === 'BATCH_STATE_SUCCEEDED') { + return 'JOB_STATE_SUCCEEDED'; + } + else if (stateString === 'BATCH_STATE_FAILED') { + return 'JOB_STATE_FAILED'; + } + else if (stateString === 'BATCH_STATE_CANCELLED') { + return 'JOB_STATE_CANCELLED'; + } + else if (stateString === 'BATCH_STATE_EXPIRED') { + return 'JOB_STATE_EXPIRED'; + } + else { + return stateString; + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function batchJobDestinationFromMldev(fromObject) { + const toObject = {}; + const fromFileName = getValueByPath(fromObject, ['responsesFile']); + if (fromFileName != null) { + setValueByPath(toObject, ['fileName'], fromFileName); + } + const fromInlinedResponses = getValueByPath(fromObject, [ + 'inlinedResponses', + 'inlinedResponses', + ]); + if (fromInlinedResponses != null) { + let transformedList = fromInlinedResponses; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return inlinedResponseFromMldev(item); + }); + } + setValueByPath(toObject, ['inlinedResponses'], transformedList); + } + const fromInlinedEmbedContentResponses = getValueByPath(fromObject, [ + 'inlinedEmbedContentResponses', + 'inlinedResponses', + ]); + if (fromInlinedEmbedContentResponses != null) { + let transformedList = fromInlinedEmbedContentResponses; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['inlinedEmbedContentResponses'], transformedList); + } + return toObject; +} +function batchJobDestinationFromVertex(fromObject) { + const toObject = {}; + const fromFormat = getValueByPath(fromObject, ['predictionsFormat']); + if (fromFormat != null) { + setValueByPath(toObject, ['format'], fromFormat); + } + const fromGcsUri = getValueByPath(fromObject, [ + 'gcsDestination', + 'outputUriPrefix', + ]); + if (fromGcsUri != null) { + setValueByPath(toObject, ['gcsUri'], fromGcsUri); + } + const fromBigqueryUri = getValueByPath(fromObject, [ + 'bigqueryDestination', + 'outputUri', + ]); + if (fromBigqueryUri != null) { + setValueByPath(toObject, ['bigqueryUri'], fromBigqueryUri); + } + return toObject; +} +function batchJobDestinationToVertex(fromObject) { + const toObject = {}; + const fromFormat = getValueByPath(fromObject, ['format']); + if (fromFormat != null) { + setValueByPath(toObject, ['predictionsFormat'], fromFormat); + } + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (fromGcsUri != null) { + setValueByPath(toObject, ['gcsDestination', 'outputUriPrefix'], fromGcsUri); + } + const fromBigqueryUri = getValueByPath(fromObject, ['bigqueryUri']); + if (fromBigqueryUri != null) { + setValueByPath(toObject, ['bigqueryDestination', 'outputUri'], fromBigqueryUri); + } + if (getValueByPath(fromObject, ['fileName']) !== undefined) { + throw new Error('fileName parameter is not supported in Vertex AI.'); + } + if (getValueByPath(fromObject, ['inlinedResponses']) !== undefined) { + throw new Error('inlinedResponses parameter is not supported in Vertex AI.'); + } + if (getValueByPath(fromObject, ['inlinedEmbedContentResponses']) !== + undefined) { + throw new Error('inlinedEmbedContentResponses parameter is not supported in Vertex AI.'); + } + return toObject; +} +function batchJobFromMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromDisplayName = getValueByPath(fromObject, [ + 'metadata', + 'displayName', + ]); + if (fromDisplayName != null) { + setValueByPath(toObject, ['displayName'], fromDisplayName); + } + const fromState = getValueByPath(fromObject, ['metadata', 'state']); + if (fromState != null) { + setValueByPath(toObject, ['state'], tJobState(fromState)); + } + const fromCreateTime = getValueByPath(fromObject, [ + 'metadata', + 'createTime', + ]); + if (fromCreateTime != null) { + setValueByPath(toObject, ['createTime'], fromCreateTime); + } + const fromEndTime = getValueByPath(fromObject, [ + 'metadata', + 'endTime', + ]); + if (fromEndTime != null) { + setValueByPath(toObject, ['endTime'], fromEndTime); + } + const fromUpdateTime = getValueByPath(fromObject, [ + 'metadata', + 'updateTime', + ]); + if (fromUpdateTime != null) { + setValueByPath(toObject, ['updateTime'], fromUpdateTime); + } + const fromModel = getValueByPath(fromObject, ['metadata', 'model']); + if (fromModel != null) { + setValueByPath(toObject, ['model'], fromModel); + } + const fromDest = getValueByPath(fromObject, ['metadata', 'output']); + if (fromDest != null) { + setValueByPath(toObject, ['dest'], batchJobDestinationFromMldev(tRecvBatchJobDestination(fromDest))); + } + return toObject; +} +function batchJobFromVertex(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (fromDisplayName != null) { + setValueByPath(toObject, ['displayName'], fromDisplayName); + } + const fromState = getValueByPath(fromObject, ['state']); + if (fromState != null) { + setValueByPath(toObject, ['state'], tJobState(fromState)); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromCreateTime = getValueByPath(fromObject, ['createTime']); + if (fromCreateTime != null) { + setValueByPath(toObject, ['createTime'], fromCreateTime); + } + const fromStartTime = getValueByPath(fromObject, ['startTime']); + if (fromStartTime != null) { + setValueByPath(toObject, ['startTime'], fromStartTime); + } + const fromEndTime = getValueByPath(fromObject, ['endTime']); + if (fromEndTime != null) { + setValueByPath(toObject, ['endTime'], fromEndTime); + } + const fromUpdateTime = getValueByPath(fromObject, ['updateTime']); + if (fromUpdateTime != null) { + setValueByPath(toObject, ['updateTime'], fromUpdateTime); + } + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['model'], fromModel); + } + const fromSrc = getValueByPath(fromObject, ['inputConfig']); + if (fromSrc != null) { + setValueByPath(toObject, ['src'], batchJobSourceFromVertex(fromSrc)); + } + const fromDest = getValueByPath(fromObject, ['outputConfig']); + if (fromDest != null) { + setValueByPath(toObject, ['dest'], batchJobDestinationFromVertex(tRecvBatchJobDestination(fromDest))); + } + const fromCompletionStats = getValueByPath(fromObject, [ + 'completionStats', + ]); + if (fromCompletionStats != null) { + setValueByPath(toObject, ['completionStats'], fromCompletionStats); + } + return toObject; +} +function batchJobSourceFromVertex(fromObject) { + const toObject = {}; + const fromFormat = getValueByPath(fromObject, ['instancesFormat']); + if (fromFormat != null) { + setValueByPath(toObject, ['format'], fromFormat); + } + const fromGcsUri = getValueByPath(fromObject, ['gcsSource', 'uris']); + if (fromGcsUri != null) { + setValueByPath(toObject, ['gcsUri'], fromGcsUri); + } + const fromBigqueryUri = getValueByPath(fromObject, [ + 'bigquerySource', + 'inputUri', + ]); + if (fromBigqueryUri != null) { + setValueByPath(toObject, ['bigqueryUri'], fromBigqueryUri); + } + return toObject; +} +function batchJobSourceToMldev(apiClient, fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['format']) !== undefined) { + throw new Error('format parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['gcsUri']) !== undefined) { + throw new Error('gcsUri parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['bigqueryUri']) !== undefined) { + throw new Error('bigqueryUri parameter is not supported in Gemini API.'); + } + const fromFileName = getValueByPath(fromObject, ['fileName']); + if (fromFileName != null) { + setValueByPath(toObject, ['fileName'], fromFileName); + } + const fromInlinedRequests = getValueByPath(fromObject, [ + 'inlinedRequests', + ]); + if (fromInlinedRequests != null) { + let transformedList = fromInlinedRequests; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return inlinedRequestToMldev(apiClient, item); + }); + } + setValueByPath(toObject, ['requests', 'requests'], transformedList); + } + return toObject; +} +function batchJobSourceToVertex(fromObject) { + const toObject = {}; + const fromFormat = getValueByPath(fromObject, ['format']); + if (fromFormat != null) { + setValueByPath(toObject, ['instancesFormat'], fromFormat); + } + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (fromGcsUri != null) { + setValueByPath(toObject, ['gcsSource', 'uris'], fromGcsUri); + } + const fromBigqueryUri = getValueByPath(fromObject, ['bigqueryUri']); + if (fromBigqueryUri != null) { + setValueByPath(toObject, ['bigquerySource', 'inputUri'], fromBigqueryUri); + } + if (getValueByPath(fromObject, ['fileName']) !== undefined) { + throw new Error('fileName parameter is not supported in Vertex AI.'); + } + if (getValueByPath(fromObject, ['inlinedRequests']) !== undefined) { + throw new Error('inlinedRequests parameter is not supported in Vertex AI.'); + } + return toObject; +} +function blobToMldev$4(fromObject) { + const toObject = {}; + const fromData = getValueByPath(fromObject, ['data']); + if (fromData != null) { + setValueByPath(toObject, ['data'], fromData); + } + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function cancelBatchJobParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tBatchJobName(apiClient, fromName)); + } + return toObject; +} +function cancelBatchJobParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tBatchJobName(apiClient, fromName)); + } + return toObject; +} +function candidateFromMldev$1(fromObject) { + const toObject = {}; + const fromContent = getValueByPath(fromObject, ['content']); + if (fromContent != null) { + setValueByPath(toObject, ['content'], fromContent); + } + const fromCitationMetadata = getValueByPath(fromObject, [ + 'citationMetadata', + ]); + if (fromCitationMetadata != null) { + setValueByPath(toObject, ['citationMetadata'], citationMetadataFromMldev$1(fromCitationMetadata)); + } + const fromTokenCount = getValueByPath(fromObject, ['tokenCount']); + if (fromTokenCount != null) { + setValueByPath(toObject, ['tokenCount'], fromTokenCount); + } + const fromFinishReason = getValueByPath(fromObject, ['finishReason']); + if (fromFinishReason != null) { + setValueByPath(toObject, ['finishReason'], fromFinishReason); + } + const fromAvgLogprobs = getValueByPath(fromObject, ['avgLogprobs']); + if (fromAvgLogprobs != null) { + setValueByPath(toObject, ['avgLogprobs'], fromAvgLogprobs); + } + const fromGroundingMetadata = getValueByPath(fromObject, [ + 'groundingMetadata', + ]); + if (fromGroundingMetadata != null) { + setValueByPath(toObject, ['groundingMetadata'], fromGroundingMetadata); + } + const fromIndex = getValueByPath(fromObject, ['index']); + if (fromIndex != null) { + setValueByPath(toObject, ['index'], fromIndex); + } + const fromLogprobsResult = getValueByPath(fromObject, [ + 'logprobsResult', + ]); + if (fromLogprobsResult != null) { + setValueByPath(toObject, ['logprobsResult'], fromLogprobsResult); + } + const fromSafetyRatings = getValueByPath(fromObject, [ + 'safetyRatings', + ]); + if (fromSafetyRatings != null) { + let transformedList = fromSafetyRatings; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['safetyRatings'], transformedList); + } + const fromUrlContextMetadata = getValueByPath(fromObject, [ + 'urlContextMetadata', + ]); + if (fromUrlContextMetadata != null) { + setValueByPath(toObject, ['urlContextMetadata'], fromUrlContextMetadata); + } + return toObject; +} +function citationMetadataFromMldev$1(fromObject) { + const toObject = {}; + const fromCitations = getValueByPath(fromObject, ['citationSources']); + if (fromCitations != null) { + let transformedList = fromCitations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['citations'], transformedList); + } + return toObject; +} +function contentToMldev$4(fromObject) { + const toObject = {}; + const fromParts = getValueByPath(fromObject, ['parts']); + if (fromParts != null) { + let transformedList = fromParts; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return partToMldev$4(item); + }); + } + setValueByPath(toObject, ['parts'], transformedList); + } + const fromRole = getValueByPath(fromObject, ['role']); + if (fromRole != null) { + setValueByPath(toObject, ['role'], fromRole); + } + return toObject; +} +function createBatchJobConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['batch', 'displayName'], fromDisplayName); + } + if (getValueByPath(fromObject, ['dest']) !== undefined) { + throw new Error('dest parameter is not supported in Gemini API.'); + } + return toObject; +} +function createBatchJobConfigToVertex(fromObject, parentObject) { + const toObject = {}; + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromDisplayName); + } + const fromDest = getValueByPath(fromObject, ['dest']); + if (parentObject !== undefined && fromDest != null) { + setValueByPath(parentObject, ['outputConfig'], batchJobDestinationToVertex(tBatchJobDestination(fromDest))); + } + return toObject; +} +function createBatchJobParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromSrc = getValueByPath(fromObject, ['src']); + if (fromSrc != null) { + setValueByPath(toObject, ['batch', 'inputConfig'], batchJobSourceToMldev(apiClient, tBatchJobSource(apiClient, fromSrc))); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createBatchJobConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function createBatchJobParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['model'], tModel(apiClient, fromModel)); + } + const fromSrc = getValueByPath(fromObject, ['src']); + if (fromSrc != null) { + setValueByPath(toObject, ['inputConfig'], batchJobSourceToVertex(tBatchJobSource(apiClient, fromSrc))); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createBatchJobConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function createEmbeddingsBatchJobConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['batch', 'displayName'], fromDisplayName); + } + return toObject; +} +function createEmbeddingsBatchJobParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromSrc = getValueByPath(fromObject, ['src']); + if (fromSrc != null) { + setValueByPath(toObject, ['batch', 'inputConfig'], embeddingsBatchJobSourceToMldev(apiClient, fromSrc)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createEmbeddingsBatchJobConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function deleteBatchJobParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tBatchJobName(apiClient, fromName)); + } + return toObject; +} +function deleteBatchJobParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tBatchJobName(apiClient, fromName)); + } + return toObject; +} +function deleteResourceJobFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + return toObject; +} +function deleteResourceJobFromVertex(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + return toObject; +} +function embedContentBatchToMldev(apiClient, fromObject) { + const toObject = {}; + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContentsForEmbed(apiClient, fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['requests[]', 'request', 'content'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['_self'], embedContentConfigToMldev$1(fromConfig, toObject)); + moveValueByPath(toObject, { 'requests[].*': 'requests[].request.*' }); + } + return toObject; +} +function embedContentConfigToMldev$1(fromObject, parentObject) { + const toObject = {}; + const fromTaskType = getValueByPath(fromObject, ['taskType']); + if (parentObject !== undefined && fromTaskType != null) { + setValueByPath(parentObject, ['requests[]', 'taskType'], fromTaskType); + } + const fromTitle = getValueByPath(fromObject, ['title']); + if (parentObject !== undefined && fromTitle != null) { + setValueByPath(parentObject, ['requests[]', 'title'], fromTitle); + } + const fromOutputDimensionality = getValueByPath(fromObject, [ + 'outputDimensionality', + ]); + if (parentObject !== undefined && fromOutputDimensionality != null) { + setValueByPath(parentObject, ['requests[]', 'outputDimensionality'], fromOutputDimensionality); + } + if (getValueByPath(fromObject, ['mimeType']) !== undefined) { + throw new Error('mimeType parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['autoTruncate']) !== undefined) { + throw new Error('autoTruncate parameter is not supported in Gemini API.'); + } + return toObject; +} +function embeddingsBatchJobSourceToMldev(apiClient, fromObject) { + const toObject = {}; + const fromFileName = getValueByPath(fromObject, ['fileName']); + if (fromFileName != null) { + setValueByPath(toObject, ['file_name'], fromFileName); + } + const fromInlinedRequests = getValueByPath(fromObject, [ + 'inlinedRequests', + ]); + if (fromInlinedRequests != null) { + setValueByPath(toObject, ['requests'], embedContentBatchToMldev(apiClient, fromInlinedRequests)); + } + return toObject; +} +function fileDataToMldev$4(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromFileUri = getValueByPath(fromObject, ['fileUri']); + if (fromFileUri != null) { + setValueByPath(toObject, ['fileUri'], fromFileUri); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function functionCallToMldev$4(fromObject) { + const toObject = {}; + const fromId = getValueByPath(fromObject, ['id']); + if (fromId != null) { + setValueByPath(toObject, ['id'], fromId); + } + const fromArgs = getValueByPath(fromObject, ['args']); + if (fromArgs != null) { + setValueByPath(toObject, ['args'], fromArgs); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + if (getValueByPath(fromObject, ['partialArgs']) !== undefined) { + throw new Error('partialArgs parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['willContinue']) !== undefined) { + throw new Error('willContinue parameter is not supported in Gemini API.'); + } + return toObject; +} +function functionCallingConfigToMldev$2(fromObject) { + const toObject = {}; + const fromAllowedFunctionNames = getValueByPath(fromObject, [ + 'allowedFunctionNames', + ]); + if (fromAllowedFunctionNames != null) { + setValueByPath(toObject, ['allowedFunctionNames'], fromAllowedFunctionNames); + } + const fromMode = getValueByPath(fromObject, ['mode']); + if (fromMode != null) { + setValueByPath(toObject, ['mode'], fromMode); + } + if (getValueByPath(fromObject, ['streamFunctionCallArguments']) !== + undefined) { + throw new Error('streamFunctionCallArguments parameter is not supported in Gemini API.'); + } + return toObject; +} +function generateContentConfigToMldev$1(apiClient, fromObject, parentObject) { + const toObject = {}; + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['systemInstruction'], contentToMldev$4(tContent(fromSystemInstruction))); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (fromTemperature != null) { + setValueByPath(toObject, ['temperature'], fromTemperature); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (fromTopP != null) { + setValueByPath(toObject, ['topP'], fromTopP); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (fromTopK != null) { + setValueByPath(toObject, ['topK'], fromTopK); + } + const fromCandidateCount = getValueByPath(fromObject, [ + 'candidateCount', + ]); + if (fromCandidateCount != null) { + setValueByPath(toObject, ['candidateCount'], fromCandidateCount); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (fromMaxOutputTokens != null) { + setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens); + } + const fromStopSequences = getValueByPath(fromObject, [ + 'stopSequences', + ]); + if (fromStopSequences != null) { + setValueByPath(toObject, ['stopSequences'], fromStopSequences); + } + const fromResponseLogprobs = getValueByPath(fromObject, [ + 'responseLogprobs', + ]); + if (fromResponseLogprobs != null) { + setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs); + } + const fromLogprobs = getValueByPath(fromObject, ['logprobs']); + if (fromLogprobs != null) { + setValueByPath(toObject, ['logprobs'], fromLogprobs); + } + const fromPresencePenalty = getValueByPath(fromObject, [ + 'presencePenalty', + ]); + if (fromPresencePenalty != null) { + setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty); + } + const fromFrequencyPenalty = getValueByPath(fromObject, [ + 'frequencyPenalty', + ]); + if (fromFrequencyPenalty != null) { + setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (fromSeed != null) { + setValueByPath(toObject, ['seed'], fromSeed); + } + const fromResponseMimeType = getValueByPath(fromObject, [ + 'responseMimeType', + ]); + if (fromResponseMimeType != null) { + setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType); + } + const fromResponseSchema = getValueByPath(fromObject, [ + 'responseSchema', + ]); + if (fromResponseSchema != null) { + setValueByPath(toObject, ['responseSchema'], tSchema(fromResponseSchema)); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + if (getValueByPath(fromObject, ['routingConfig']) !== undefined) { + throw new Error('routingConfig parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['modelSelectionConfig']) !== undefined) { + throw new Error('modelSelectionConfig parameter is not supported in Gemini API.'); + } + const fromSafetySettings = getValueByPath(fromObject, [ + 'safetySettings', + ]); + if (parentObject !== undefined && fromSafetySettings != null) { + let transformedList = fromSafetySettings; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return safetySettingToMldev$1(item); + }); + } + setValueByPath(parentObject, ['safetySettings'], transformedList); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = tTools(fromTools); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToMldev$4(tTool(item)); + }); + } + setValueByPath(parentObject, ['tools'], transformedList); + } + const fromToolConfig = getValueByPath(fromObject, ['toolConfig']); + if (parentObject !== undefined && fromToolConfig != null) { + setValueByPath(parentObject, ['toolConfig'], toolConfigToMldev$2(fromToolConfig)); + } + if (getValueByPath(fromObject, ['labels']) !== undefined) { + throw new Error('labels parameter is not supported in Gemini API.'); + } + const fromCachedContent = getValueByPath(fromObject, [ + 'cachedContent', + ]); + if (parentObject !== undefined && fromCachedContent != null) { + setValueByPath(parentObject, ['cachedContent'], tCachedContentName(apiClient, fromCachedContent)); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (fromResponseModalities != null) { + setValueByPath(toObject, ['responseModalities'], fromResponseModalities); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (fromSpeechConfig != null) { + setValueByPath(toObject, ['speechConfig'], tSpeechConfig(fromSpeechConfig)); + } + if (getValueByPath(fromObject, ['audioTimestamp']) !== undefined) { + throw new Error('audioTimestamp parameter is not supported in Gemini API.'); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (fromThinkingConfig != null) { + setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig); + } + const fromImageConfig = getValueByPath(fromObject, ['imageConfig']); + if (fromImageConfig != null) { + setValueByPath(toObject, ['imageConfig'], imageConfigToMldev$1(fromImageConfig)); + } + const fromEnableEnhancedCivicAnswers = getValueByPath(fromObject, [ + 'enableEnhancedCivicAnswers', + ]); + if (fromEnableEnhancedCivicAnswers != null) { + setValueByPath(toObject, ['enableEnhancedCivicAnswers'], fromEnableEnhancedCivicAnswers); + } + if (getValueByPath(fromObject, ['modelArmorConfig']) !== undefined) { + throw new Error('modelArmorConfig parameter is not supported in Gemini API.'); + } + return toObject; +} +function generateContentResponseFromMldev$1(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromCandidates = getValueByPath(fromObject, ['candidates']); + if (fromCandidates != null) { + let transformedList = fromCandidates; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return candidateFromMldev$1(item); + }); + } + setValueByPath(toObject, ['candidates'], transformedList); + } + const fromModelVersion = getValueByPath(fromObject, ['modelVersion']); + if (fromModelVersion != null) { + setValueByPath(toObject, ['modelVersion'], fromModelVersion); + } + const fromPromptFeedback = getValueByPath(fromObject, [ + 'promptFeedback', + ]); + if (fromPromptFeedback != null) { + setValueByPath(toObject, ['promptFeedback'], fromPromptFeedback); + } + const fromResponseId = getValueByPath(fromObject, ['responseId']); + if (fromResponseId != null) { + setValueByPath(toObject, ['responseId'], fromResponseId); + } + const fromUsageMetadata = getValueByPath(fromObject, [ + 'usageMetadata', + ]); + if (fromUsageMetadata != null) { + setValueByPath(toObject, ['usageMetadata'], fromUsageMetadata); + } + return toObject; +} +function getBatchJobParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tBatchJobName(apiClient, fromName)); + } + return toObject; +} +function getBatchJobParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tBatchJobName(apiClient, fromName)); + } + return toObject; +} +function googleMapsToMldev$4(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['authConfig']) !== undefined) { + throw new Error('authConfig parameter is not supported in Gemini API.'); + } + const fromEnableWidget = getValueByPath(fromObject, ['enableWidget']); + if (fromEnableWidget != null) { + setValueByPath(toObject, ['enableWidget'], fromEnableWidget); + } + return toObject; +} +function googleSearchToMldev$4(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['excludeDomains']) !== undefined) { + throw new Error('excludeDomains parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['blockingConfidence']) !== undefined) { + throw new Error('blockingConfidence parameter is not supported in Gemini API.'); + } + const fromTimeRangeFilter = getValueByPath(fromObject, [ + 'timeRangeFilter', + ]); + if (fromTimeRangeFilter != null) { + setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter); + } + return toObject; +} +function imageConfigToMldev$1(fromObject) { + const toObject = {}; + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (fromAspectRatio != null) { + setValueByPath(toObject, ['aspectRatio'], fromAspectRatio); + } + const fromImageSize = getValueByPath(fromObject, ['imageSize']); + if (fromImageSize != null) { + setValueByPath(toObject, ['imageSize'], fromImageSize); + } + if (getValueByPath(fromObject, ['personGeneration']) !== undefined) { + throw new Error('personGeneration parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['outputMimeType']) !== undefined) { + throw new Error('outputMimeType parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['outputCompressionQuality']) !== + undefined) { + throw new Error('outputCompressionQuality parameter is not supported in Gemini API.'); + } + return toObject; +} +function inlinedRequestToMldev(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['request', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return contentToMldev$4(item); + }); + } + setValueByPath(toObject, ['request', 'contents'], transformedList); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['request', 'generationConfig'], generateContentConfigToMldev$1(apiClient, fromConfig, getValueByPath(toObject, ['request'], {}))); + } + return toObject; +} +function inlinedResponseFromMldev(fromObject) { + const toObject = {}; + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], generateContentResponseFromMldev$1(fromResponse)); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + return toObject; +} +function listBatchJobsConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + if (getValueByPath(fromObject, ['filter']) !== undefined) { + throw new Error('filter parameter is not supported in Gemini API.'); + } + return toObject; +} +function listBatchJobsConfigToVertex(fromObject, parentObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + const fromFilter = getValueByPath(fromObject, ['filter']); + if (parentObject !== undefined && fromFilter != null) { + setValueByPath(parentObject, ['_query', 'filter'], fromFilter); + } + return toObject; +} +function listBatchJobsParametersToMldev(fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listBatchJobsConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function listBatchJobsParametersToVertex(fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listBatchJobsConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function listBatchJobsResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromBatchJobs = getValueByPath(fromObject, ['operations']); + if (fromBatchJobs != null) { + let transformedList = fromBatchJobs; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return batchJobFromMldev(item); + }); + } + setValueByPath(toObject, ['batchJobs'], transformedList); + } + return toObject; +} +function listBatchJobsResponseFromVertex(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromBatchJobs = getValueByPath(fromObject, [ + 'batchPredictionJobs', + ]); + if (fromBatchJobs != null) { + let transformedList = fromBatchJobs; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return batchJobFromVertex(item); + }); + } + setValueByPath(toObject, ['batchJobs'], transformedList); + } + return toObject; +} +function partToMldev$4(fromObject) { + const toObject = {}; + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromCodeExecutionResult = getValueByPath(fromObject, [ + 'codeExecutionResult', + ]); + if (fromCodeExecutionResult != null) { + setValueByPath(toObject, ['codeExecutionResult'], fromCodeExecutionResult); + } + const fromExecutableCode = getValueByPath(fromObject, [ + 'executableCode', + ]); + if (fromExecutableCode != null) { + setValueByPath(toObject, ['executableCode'], fromExecutableCode); + } + const fromFileData = getValueByPath(fromObject, ['fileData']); + if (fromFileData != null) { + setValueByPath(toObject, ['fileData'], fileDataToMldev$4(fromFileData)); + } + const fromFunctionCall = getValueByPath(fromObject, ['functionCall']); + if (fromFunctionCall != null) { + setValueByPath(toObject, ['functionCall'], functionCallToMldev$4(fromFunctionCall)); + } + const fromFunctionResponse = getValueByPath(fromObject, [ + 'functionResponse', + ]); + if (fromFunctionResponse != null) { + setValueByPath(toObject, ['functionResponse'], fromFunctionResponse); + } + const fromInlineData = getValueByPath(fromObject, ['inlineData']); + if (fromInlineData != null) { + setValueByPath(toObject, ['inlineData'], blobToMldev$4(fromInlineData)); + } + const fromText = getValueByPath(fromObject, ['text']); + if (fromText != null) { + setValueByPath(toObject, ['text'], fromText); + } + const fromThought = getValueByPath(fromObject, ['thought']); + if (fromThought != null) { + setValueByPath(toObject, ['thought'], fromThought); + } + const fromThoughtSignature = getValueByPath(fromObject, [ + 'thoughtSignature', + ]); + if (fromThoughtSignature != null) { + setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature); + } + const fromVideoMetadata = getValueByPath(fromObject, [ + 'videoMetadata', + ]); + if (fromVideoMetadata != null) { + setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata); + } + return toObject; +} +function safetySettingToMldev$1(fromObject) { + const toObject = {}; + const fromCategory = getValueByPath(fromObject, ['category']); + if (fromCategory != null) { + setValueByPath(toObject, ['category'], fromCategory); + } + if (getValueByPath(fromObject, ['method']) !== undefined) { + throw new Error('method parameter is not supported in Gemini API.'); + } + const fromThreshold = getValueByPath(fromObject, ['threshold']); + if (fromThreshold != null) { + setValueByPath(toObject, ['threshold'], fromThreshold); + } + return toObject; +} +function toolConfigToMldev$2(fromObject) { + const toObject = {}; + const fromRetrievalConfig = getValueByPath(fromObject, [ + 'retrievalConfig', + ]); + if (fromRetrievalConfig != null) { + setValueByPath(toObject, ['retrievalConfig'], fromRetrievalConfig); + } + const fromFunctionCallingConfig = getValueByPath(fromObject, [ + 'functionCallingConfig', + ]); + if (fromFunctionCallingConfig != null) { + setValueByPath(toObject, ['functionCallingConfig'], functionCallingConfigToMldev$2(fromFunctionCallingConfig)); + } + return toObject; +} +function toolToMldev$4(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['retrieval']) !== undefined) { + throw new Error('retrieval parameter is not supported in Gemini API.'); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + const fromFileSearch = getValueByPath(fromObject, ['fileSearch']); + if (fromFileSearch != null) { + setValueByPath(toObject, ['fileSearch'], fromFileSearch); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + if (getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined) { + throw new Error('enterpriseWebSearch parameter is not supported in Gemini API.'); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], googleMapsToMldev$4(fromGoogleMaps)); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], googleSearchToMldev$4(fromGoogleSearch)); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +exports.PagedItem = void 0; +(function (PagedItem) { + PagedItem["PAGED_ITEM_BATCH_JOBS"] = "batchJobs"; + PagedItem["PAGED_ITEM_MODELS"] = "models"; + PagedItem["PAGED_ITEM_TUNING_JOBS"] = "tuningJobs"; + PagedItem["PAGED_ITEM_FILES"] = "files"; + PagedItem["PAGED_ITEM_CACHED_CONTENTS"] = "cachedContents"; + PagedItem["PAGED_ITEM_FILE_SEARCH_STORES"] = "fileSearchStores"; + PagedItem["PAGED_ITEM_DOCUMENTS"] = "documents"; +})(exports.PagedItem || (exports.PagedItem = {})); +/** + * Pager class for iterating through paginated results. + */ +class Pager { + constructor(name, request, response, params) { + this.pageInternal = []; + this.paramsInternal = {}; + this.requestInternal = request; + this.init(name, response, params); + } + init(name, response, params) { + var _a, _b; + this.nameInternal = name; + this.pageInternal = response[this.nameInternal] || []; + this.sdkHttpResponseInternal = response === null || response === void 0 ? void 0 : response.sdkHttpResponse; + this.idxInternal = 0; + let requestParams = { config: {} }; + if (!params || Object.keys(params).length === 0) { + requestParams = { config: {} }; + } + else if (typeof params === 'object') { + requestParams = Object.assign({}, params); + } + else { + requestParams = params; + } + if (requestParams['config']) { + requestParams['config']['pageToken'] = response['nextPageToken']; + } + this.paramsInternal = requestParams; + this.pageInternalSize = + (_b = (_a = requestParams['config']) === null || _a === void 0 ? void 0 : _a['pageSize']) !== null && _b !== void 0 ? _b : this.pageInternal.length; + } + initNextPage(response) { + this.init(this.nameInternal, response, this.paramsInternal); + } + /** + * Returns the current page, which is a list of items. + * + * @remarks + * The first page is retrieved when the pager is created. The returned list of + * items could be a subset of the entire list. + */ + get page() { + return this.pageInternal; + } + /** + * Returns the type of paged item (for example, ``batch_jobs``). + */ + get name() { + return this.nameInternal; + } + /** + * Returns the length of the page fetched each time by this pager. + * + * @remarks + * The number of items in the page is less than or equal to the page length. + */ + get pageSize() { + return this.pageInternalSize; + } + /** + * Returns the headers of the API response. + */ + get sdkHttpResponse() { + return this.sdkHttpResponseInternal; + } + /** + * Returns the parameters when making the API request for the next page. + * + * @remarks + * Parameters contain a set of optional configs that can be + * used to customize the API request. For example, the `pageToken` parameter + * contains the token to request the next page. + */ + get params() { + return this.paramsInternal; + } + /** + * Returns the total number of items in the current page. + */ + get pageLength() { + return this.pageInternal.length; + } + /** + * Returns the item at the given index. + */ + getItem(index) { + return this.pageInternal[index]; + } + /** + * Returns an async iterator that support iterating through all items + * retrieved from the API. + * + * @remarks + * The iterator will automatically fetch the next page if there are more items + * to fetch from the API. + * + * @example + * + * ```ts + * const pager = await ai.files.list({config: {pageSize: 10}}); + * for await (const file of pager) { + * console.log(file.name); + * } + * ``` + */ + [Symbol.asyncIterator]() { + return { + next: async () => { + if (this.idxInternal >= this.pageLength) { + if (this.hasNextPage()) { + await this.nextPage(); + } + else { + return { value: undefined, done: true }; + } + } + const item = this.getItem(this.idxInternal); + this.idxInternal += 1; + return { value: item, done: false }; + }, + return: async () => { + return { value: undefined, done: true }; + }, + }; + } + /** + * Fetches the next page of items. This makes a new API request. + * + * @throws {Error} If there are no more pages to fetch. + * + * @example + * + * ```ts + * const pager = await ai.files.list({config: {pageSize: 10}}); + * let page = pager.page; + * while (true) { + * for (const file of page) { + * console.log(file.name); + * } + * if (!pager.hasNextPage()) { + * break; + * } + * page = await pager.nextPage(); + * } + * ``` + */ + async nextPage() { + if (!this.hasNextPage()) { + throw new Error('No more pages to fetch.'); + } + const response = await this.requestInternal(this.params); + this.initNextPage(response); + return this.page; + } + /** + * Returns true if there are more pages to fetch from the API. + */ + hasNextPage() { + var _a; + if (((_a = this.params['config']) === null || _a === void 0 ? void 0 : _a['pageToken']) !== undefined) { + return true; + } + return false; + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Batches extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + /** + * Lists batch jobs. + * + * @param params - The parameters for the list request. + * @return - A pager of batch jobs. + * + * @example + * ```ts + * const batchJobs = await ai.batches.list({config: {'pageSize': 2}}); + * for await (const batchJob of batchJobs) { + * console.log(batchJob); + * } + * ``` + */ + this.list = async (params = {}) => { + return new Pager(exports.PagedItem.PAGED_ITEM_BATCH_JOBS, (x) => this.listInternal(x), await this.listInternal(params), params); + }; + /** + * Create batch job. + * + * @param params - The parameters for create batch job request. + * @return The created batch job. + * + * @example + * ```ts + * const response = await ai.batches.create({ + * model: 'gemini-2.0-flash', + * src: {gcsUri: 'gs://bucket/path/to/file.jsonl', format: 'jsonl'}, + * config: { + * dest: {gcsUri: 'gs://bucket/path/output/directory', format: 'jsonl'}, + * } + * }); + * console.log(response); + * ``` + */ + this.create = async (params) => { + if (this.apiClient.isVertexAI()) { + // Format destination if not provided + // Cast params.src as Vertex AI path does not handle InlinedRequest[] + params.config = this.formatDestination(params.src, params.config); + } + return this.createInternal(params); + }; + /** + * **Experimental** Creates an embedding batch job. + * + * @param params - The parameters for create embedding batch job request. + * @return The created batch job. + * + * @example + * ```ts + * const response = await ai.batches.createEmbeddings({ + * model: 'text-embedding-004', + * src: {fileName: 'files/my_embedding_input'}, + * }); + * console.log(response); + * ``` + */ + this.createEmbeddings = async (params) => { + console.warn('batches.createEmbeddings() is experimental and may change without notice.'); + if (this.apiClient.isVertexAI()) { + throw new Error('Vertex AI does not support batches.createEmbeddings.'); + } + return this.createEmbeddingsInternal(params); + }; + } + // Helper function to handle inlined generate content requests + createInlinedGenerateContentRequest(params) { + const body = createBatchJobParametersToMldev(this.apiClient, // Use instance apiClient + params); + const urlParams = body['_url']; + const path = formatMap('{model}:batchGenerateContent', urlParams); + const batch = body['batch']; + const inputConfig = batch['inputConfig']; + const requestsWrapper = inputConfig['requests']; + const requests = requestsWrapper['requests']; + const newRequests = []; + for (const request of requests) { + const requestDict = Object.assign({}, request); // Clone + if (requestDict['systemInstruction']) { + const systemInstructionValue = requestDict['systemInstruction']; + delete requestDict['systemInstruction']; + const requestContent = requestDict['request']; + requestContent['systemInstruction'] = systemInstructionValue; + requestDict['request'] = requestContent; + } + newRequests.push(requestDict); + } + requestsWrapper['requests'] = newRequests; + delete body['config']; + delete body['_url']; + delete body['_query']; + return { path, body }; + } + // Helper function to get the first GCS URI + getGcsUri(src) { + if (typeof src === 'string') { + return src.startsWith('gs://') ? src : undefined; + } + if (!Array.isArray(src) && src.gcsUri && src.gcsUri.length > 0) { + return src.gcsUri[0]; + } + return undefined; + } + // Helper function to get the BigQuery URI + getBigqueryUri(src) { + if (typeof src === 'string') { + return src.startsWith('bq://') ? src : undefined; + } + if (!Array.isArray(src)) { + return src.bigqueryUri; + } + return undefined; + } + // Function to format the destination configuration for Vertex AI + formatDestination(src, config) { + const newConfig = config ? Object.assign({}, config) : {}; + const timestampStr = Date.now().toString(); + if (!newConfig.displayName) { + newConfig.displayName = `genaiBatchJob_${timestampStr}`; + } + if (newConfig.dest === undefined) { + const gcsUri = this.getGcsUri(src); + const bigqueryUri = this.getBigqueryUri(src); + if (gcsUri) { + if (gcsUri.endsWith('.jsonl')) { + // For .jsonl files, remove suffix and add /dest + newConfig.dest = `${gcsUri.slice(0, -6)}/dest`; + } + else { + // Fallback for other GCS URIs + newConfig.dest = `${gcsUri}_dest_${timestampStr}`; + } + } + else if (bigqueryUri) { + newConfig.dest = `${bigqueryUri}_dest_${timestampStr}`; + } + else { + throw new Error('Unsupported source for Vertex AI: No GCS or BigQuery URI found.'); + } + } + return newConfig; + } + /** + * Internal method to create batch job. + * + * @param params - The parameters for create batch job request. + * @return The created batch job. + * + */ + async createInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = createBatchJobParametersToVertex(this.apiClient, params); + path = formatMap('batchPredictionJobs', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = batchJobFromVertex(apiResponse); + return resp; + }); + } + else { + const body = createBatchJobParametersToMldev(this.apiClient, params); + path = formatMap('{model}:batchGenerateContent', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = batchJobFromMldev(apiResponse); + return resp; + }); + } + } + /** + * Internal method to create batch job. + * + * @param params - The parameters for create batch job request. + * @return The created batch job. + * + */ + async createEmbeddingsInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = createEmbeddingsBatchJobParametersToMldev(this.apiClient, params); + path = formatMap('{model}:asyncBatchEmbedContent', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = batchJobFromMldev(apiResponse); + return resp; + }); + } + } + /** + * Gets batch job configurations. + * + * @param params - The parameters for the get request. + * @return The batch job. + * + * @example + * ```ts + * await ai.batches.get({name: '...'}); // The server-generated resource name. + * ``` + */ + async get(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = getBatchJobParametersToVertex(this.apiClient, params); + path = formatMap('batchPredictionJobs/{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = batchJobFromVertex(apiResponse); + return resp; + }); + } + else { + const body = getBatchJobParametersToMldev(this.apiClient, params); + path = formatMap('batches/{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = batchJobFromMldev(apiResponse); + return resp; + }); + } + } + /** + * Cancels a batch job. + * + * @param params - The parameters for the cancel request. + * @return The empty response returned by the API. + * + * @example + * ```ts + * await ai.batches.cancel({name: '...'}); // The server-generated resource name. + * ``` + */ + async cancel(params) { + var _a, _b, _c, _d; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = cancelBatchJobParametersToVertex(this.apiClient, params); + path = formatMap('batchPredictionJobs/{name}:cancel', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + await this.apiClient.request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }); + } + else { + const body = cancelBatchJobParametersToMldev(this.apiClient, params); + path = formatMap('batches/{name}:cancel', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + await this.apiClient.request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }); + } + } + async listInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = listBatchJobsParametersToVertex(params); + path = formatMap('batchPredictionJobs', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listBatchJobsResponseFromVertex(apiResponse); + const typedResp = new ListBatchJobsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = listBatchJobsParametersToMldev(params); + path = formatMap('batches', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listBatchJobsResponseFromMldev(apiResponse); + const typedResp = new ListBatchJobsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Deletes a batch job. + * + * @param params - The parameters for the delete request. + * @return The empty response returned by the API. + * + * @example + * ```ts + * await ai.batches.delete({name: '...'}); // The server-generated resource name. + * ``` + */ + async delete(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = deleteBatchJobParametersToVertex(this.apiClient, params); + path = formatMap('batchPredictionJobs/{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = deleteResourceJobFromVertex(apiResponse); + return resp; + }); + } + else { + const body = deleteBatchJobParametersToMldev(this.apiClient, params); + path = formatMap('batches/{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = deleteResourceJobFromMldev(apiResponse); + return resp; + }); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function blobToMldev$3(fromObject) { + const toObject = {}; + const fromData = getValueByPath(fromObject, ['data']); + if (fromData != null) { + setValueByPath(toObject, ['data'], fromData); + } + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function contentToMldev$3(fromObject) { + const toObject = {}; + const fromParts = getValueByPath(fromObject, ['parts']); + if (fromParts != null) { + let transformedList = fromParts; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return partToMldev$3(item); + }); + } + setValueByPath(toObject, ['parts'], transformedList); + } + const fromRole = getValueByPath(fromObject, ['role']); + if (fromRole != null) { + setValueByPath(toObject, ['role'], fromRole); + } + return toObject; +} +function createCachedContentConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromTtl = getValueByPath(fromObject, ['ttl']); + if (parentObject !== undefined && fromTtl != null) { + setValueByPath(parentObject, ['ttl'], fromTtl); + } + const fromExpireTime = getValueByPath(fromObject, ['expireTime']); + if (parentObject !== undefined && fromExpireTime != null) { + setValueByPath(parentObject, ['expireTime'], fromExpireTime); + } + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromDisplayName); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (parentObject !== undefined && fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return contentToMldev$3(item); + }); + } + setValueByPath(parentObject, ['contents'], transformedList); + } + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['systemInstruction'], contentToMldev$3(tContent(fromSystemInstruction))); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = fromTools; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToMldev$3(item); + }); + } + setValueByPath(parentObject, ['tools'], transformedList); + } + const fromToolConfig = getValueByPath(fromObject, ['toolConfig']); + if (parentObject !== undefined && fromToolConfig != null) { + setValueByPath(parentObject, ['toolConfig'], toolConfigToMldev$1(fromToolConfig)); + } + if (getValueByPath(fromObject, ['kmsKeyName']) !== undefined) { + throw new Error('kmsKeyName parameter is not supported in Gemini API.'); + } + return toObject; +} +function createCachedContentConfigToVertex(fromObject, parentObject) { + const toObject = {}; + const fromTtl = getValueByPath(fromObject, ['ttl']); + if (parentObject !== undefined && fromTtl != null) { + setValueByPath(parentObject, ['ttl'], fromTtl); + } + const fromExpireTime = getValueByPath(fromObject, ['expireTime']); + if (parentObject !== undefined && fromExpireTime != null) { + setValueByPath(parentObject, ['expireTime'], fromExpireTime); + } + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromDisplayName); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (parentObject !== undefined && fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(parentObject, ['contents'], transformedList); + } + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['systemInstruction'], tContent(fromSystemInstruction)); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = fromTools; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToVertex$2(item); + }); + } + setValueByPath(parentObject, ['tools'], transformedList); + } + const fromToolConfig = getValueByPath(fromObject, ['toolConfig']); + if (parentObject !== undefined && fromToolConfig != null) { + setValueByPath(parentObject, ['toolConfig'], fromToolConfig); + } + const fromKmsKeyName = getValueByPath(fromObject, ['kmsKeyName']); + if (parentObject !== undefined && fromKmsKeyName != null) { + setValueByPath(parentObject, ['encryption_spec', 'kmsKeyName'], fromKmsKeyName); + } + return toObject; +} +function createCachedContentParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['model'], tCachesModel(apiClient, fromModel)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createCachedContentConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function createCachedContentParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['model'], tCachesModel(apiClient, fromModel)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createCachedContentConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function deleteCachedContentParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tCachedContentName(apiClient, fromName)); + } + return toObject; +} +function deleteCachedContentParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tCachedContentName(apiClient, fromName)); + } + return toObject; +} +function deleteCachedContentResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function deleteCachedContentResponseFromVertex(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function fileDataToMldev$3(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromFileUri = getValueByPath(fromObject, ['fileUri']); + if (fromFileUri != null) { + setValueByPath(toObject, ['fileUri'], fromFileUri); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function functionCallToMldev$3(fromObject) { + const toObject = {}; + const fromId = getValueByPath(fromObject, ['id']); + if (fromId != null) { + setValueByPath(toObject, ['id'], fromId); + } + const fromArgs = getValueByPath(fromObject, ['args']); + if (fromArgs != null) { + setValueByPath(toObject, ['args'], fromArgs); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + if (getValueByPath(fromObject, ['partialArgs']) !== undefined) { + throw new Error('partialArgs parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['willContinue']) !== undefined) { + throw new Error('willContinue parameter is not supported in Gemini API.'); + } + return toObject; +} +function functionCallingConfigToMldev$1(fromObject) { + const toObject = {}; + const fromAllowedFunctionNames = getValueByPath(fromObject, [ + 'allowedFunctionNames', + ]); + if (fromAllowedFunctionNames != null) { + setValueByPath(toObject, ['allowedFunctionNames'], fromAllowedFunctionNames); + } + const fromMode = getValueByPath(fromObject, ['mode']); + if (fromMode != null) { + setValueByPath(toObject, ['mode'], fromMode); + } + if (getValueByPath(fromObject, ['streamFunctionCallArguments']) !== + undefined) { + throw new Error('streamFunctionCallArguments parameter is not supported in Gemini API.'); + } + return toObject; +} +function functionDeclarationToVertex$2(fromObject) { + const toObject = {}; + const fromDescription = getValueByPath(fromObject, ['description']); + if (fromDescription != null) { + setValueByPath(toObject, ['description'], fromDescription); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromParameters = getValueByPath(fromObject, ['parameters']); + if (fromParameters != null) { + setValueByPath(toObject, ['parameters'], fromParameters); + } + const fromParametersJsonSchema = getValueByPath(fromObject, [ + 'parametersJsonSchema', + ]); + if (fromParametersJsonSchema != null) { + setValueByPath(toObject, ['parametersJsonSchema'], fromParametersJsonSchema); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], fromResponse); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + if (getValueByPath(fromObject, ['behavior']) !== undefined) { + throw new Error('behavior parameter is not supported in Vertex AI.'); + } + return toObject; +} +function getCachedContentParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tCachedContentName(apiClient, fromName)); + } + return toObject; +} +function getCachedContentParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tCachedContentName(apiClient, fromName)); + } + return toObject; +} +function googleMapsToMldev$3(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['authConfig']) !== undefined) { + throw new Error('authConfig parameter is not supported in Gemini API.'); + } + const fromEnableWidget = getValueByPath(fromObject, ['enableWidget']); + if (fromEnableWidget != null) { + setValueByPath(toObject, ['enableWidget'], fromEnableWidget); + } + return toObject; +} +function googleSearchToMldev$3(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['excludeDomains']) !== undefined) { + throw new Error('excludeDomains parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['blockingConfidence']) !== undefined) { + throw new Error('blockingConfidence parameter is not supported in Gemini API.'); + } + const fromTimeRangeFilter = getValueByPath(fromObject, [ + 'timeRangeFilter', + ]); + if (fromTimeRangeFilter != null) { + setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter); + } + return toObject; +} +function listCachedContentsConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + return toObject; +} +function listCachedContentsConfigToVertex(fromObject, parentObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + return toObject; +} +function listCachedContentsParametersToMldev(fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listCachedContentsConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function listCachedContentsParametersToVertex(fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listCachedContentsConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function listCachedContentsResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromCachedContents = getValueByPath(fromObject, [ + 'cachedContents', + ]); + if (fromCachedContents != null) { + let transformedList = fromCachedContents; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['cachedContents'], transformedList); + } + return toObject; +} +function listCachedContentsResponseFromVertex(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromCachedContents = getValueByPath(fromObject, [ + 'cachedContents', + ]); + if (fromCachedContents != null) { + let transformedList = fromCachedContents; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['cachedContents'], transformedList); + } + return toObject; +} +function partToMldev$3(fromObject) { + const toObject = {}; + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromCodeExecutionResult = getValueByPath(fromObject, [ + 'codeExecutionResult', + ]); + if (fromCodeExecutionResult != null) { + setValueByPath(toObject, ['codeExecutionResult'], fromCodeExecutionResult); + } + const fromExecutableCode = getValueByPath(fromObject, [ + 'executableCode', + ]); + if (fromExecutableCode != null) { + setValueByPath(toObject, ['executableCode'], fromExecutableCode); + } + const fromFileData = getValueByPath(fromObject, ['fileData']); + if (fromFileData != null) { + setValueByPath(toObject, ['fileData'], fileDataToMldev$3(fromFileData)); + } + const fromFunctionCall = getValueByPath(fromObject, ['functionCall']); + if (fromFunctionCall != null) { + setValueByPath(toObject, ['functionCall'], functionCallToMldev$3(fromFunctionCall)); + } + const fromFunctionResponse = getValueByPath(fromObject, [ + 'functionResponse', + ]); + if (fromFunctionResponse != null) { + setValueByPath(toObject, ['functionResponse'], fromFunctionResponse); + } + const fromInlineData = getValueByPath(fromObject, ['inlineData']); + if (fromInlineData != null) { + setValueByPath(toObject, ['inlineData'], blobToMldev$3(fromInlineData)); + } + const fromText = getValueByPath(fromObject, ['text']); + if (fromText != null) { + setValueByPath(toObject, ['text'], fromText); + } + const fromThought = getValueByPath(fromObject, ['thought']); + if (fromThought != null) { + setValueByPath(toObject, ['thought'], fromThought); + } + const fromThoughtSignature = getValueByPath(fromObject, [ + 'thoughtSignature', + ]); + if (fromThoughtSignature != null) { + setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature); + } + const fromVideoMetadata = getValueByPath(fromObject, [ + 'videoMetadata', + ]); + if (fromVideoMetadata != null) { + setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata); + } + return toObject; +} +function toolConfigToMldev$1(fromObject) { + const toObject = {}; + const fromRetrievalConfig = getValueByPath(fromObject, [ + 'retrievalConfig', + ]); + if (fromRetrievalConfig != null) { + setValueByPath(toObject, ['retrievalConfig'], fromRetrievalConfig); + } + const fromFunctionCallingConfig = getValueByPath(fromObject, [ + 'functionCallingConfig', + ]); + if (fromFunctionCallingConfig != null) { + setValueByPath(toObject, ['functionCallingConfig'], functionCallingConfigToMldev$1(fromFunctionCallingConfig)); + } + return toObject; +} +function toolToMldev$3(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['retrieval']) !== undefined) { + throw new Error('retrieval parameter is not supported in Gemini API.'); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + const fromFileSearch = getValueByPath(fromObject, ['fileSearch']); + if (fromFileSearch != null) { + setValueByPath(toObject, ['fileSearch'], fromFileSearch); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + if (getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined) { + throw new Error('enterpriseWebSearch parameter is not supported in Gemini API.'); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], googleMapsToMldev$3(fromGoogleMaps)); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], googleSearchToMldev$3(fromGoogleSearch)); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} +function toolToVertex$2(fromObject) { + const toObject = {}; + const fromRetrieval = getValueByPath(fromObject, ['retrieval']); + if (fromRetrieval != null) { + setValueByPath(toObject, ['retrieval'], fromRetrieval); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + if (getValueByPath(fromObject, ['fileSearch']) !== undefined) { + throw new Error('fileSearch parameter is not supported in Vertex AI.'); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + const fromEnterpriseWebSearch = getValueByPath(fromObject, [ + 'enterpriseWebSearch', + ]); + if (fromEnterpriseWebSearch != null) { + setValueByPath(toObject, ['enterpriseWebSearch'], fromEnterpriseWebSearch); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return functionDeclarationToVertex$2(item); + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], fromGoogleMaps); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], fromGoogleSearch); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} +function updateCachedContentConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromTtl = getValueByPath(fromObject, ['ttl']); + if (parentObject !== undefined && fromTtl != null) { + setValueByPath(parentObject, ['ttl'], fromTtl); + } + const fromExpireTime = getValueByPath(fromObject, ['expireTime']); + if (parentObject !== undefined && fromExpireTime != null) { + setValueByPath(parentObject, ['expireTime'], fromExpireTime); + } + return toObject; +} +function updateCachedContentConfigToVertex(fromObject, parentObject) { + const toObject = {}; + const fromTtl = getValueByPath(fromObject, ['ttl']); + if (parentObject !== undefined && fromTtl != null) { + setValueByPath(parentObject, ['ttl'], fromTtl); + } + const fromExpireTime = getValueByPath(fromObject, ['expireTime']); + if (parentObject !== undefined && fromExpireTime != null) { + setValueByPath(parentObject, ['expireTime'], fromExpireTime); + } + return toObject; +} +function updateCachedContentParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tCachedContentName(apiClient, fromName)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + updateCachedContentConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function updateCachedContentParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tCachedContentName(apiClient, fromName)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + updateCachedContentConfigToVertex(fromConfig, toObject); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Caches extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + /** + * Lists cached contents. + * + * @param params - The parameters for the list request. + * @return - A pager of cached contents. + * + * @example + * ```ts + * const cachedContents = await ai.caches.list({config: {'pageSize': 2}}); + * for await (const cachedContent of cachedContents) { + * console.log(cachedContent); + * } + * ``` + */ + this.list = async (params = {}) => { + return new Pager(exports.PagedItem.PAGED_ITEM_CACHED_CONTENTS, (x) => this.listInternal(x), await this.listInternal(params), params); + }; + } + /** + * Creates a cached contents resource. + * + * @remarks + * Context caching is only supported for specific models. See [Gemini + * Developer API reference](https://ai.google.dev/gemini-api/docs/caching?lang=node/context-cac) + * and [Vertex AI reference](https://cloud.google.com/vertex-ai/generative-ai/docs/context-cache/context-cache-overview#supported_models) + * for more information. + * + * @param params - The parameters for the create request. + * @return The created cached content. + * + * @example + * ```ts + * const contents = ...; // Initialize the content to cache. + * const response = await ai.caches.create({ + * model: 'gemini-2.0-flash-001', + * config: { + * 'contents': contents, + * 'displayName': 'test cache', + * 'systemInstruction': 'What is the sum of the two pdfs?', + * 'ttl': '86400s', + * } + * }); + * ``` + */ + async create(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = createCachedContentParametersToVertex(this.apiClient, params); + path = formatMap('cachedContents', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + else { + const body = createCachedContentParametersToMldev(this.apiClient, params); + path = formatMap('cachedContents', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } + /** + * Gets cached content configurations. + * + * @param params - The parameters for the get request. + * @return The cached content. + * + * @example + * ```ts + * await ai.caches.get({name: '...'}); // The server-generated resource name. + * ``` + */ + async get(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = getCachedContentParametersToVertex(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + else { + const body = getCachedContentParametersToMldev(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } + /** + * Deletes cached content. + * + * @param params - The parameters for the delete request. + * @return The empty response returned by the API. + * + * @example + * ```ts + * await ai.caches.delete({name: '...'}); // The server-generated resource name. + * ``` + */ + async delete(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = deleteCachedContentParametersToVertex(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = deleteCachedContentResponseFromVertex(apiResponse); + const typedResp = new DeleteCachedContentResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = deleteCachedContentParametersToMldev(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = deleteCachedContentResponseFromMldev(apiResponse); + const typedResp = new DeleteCachedContentResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Updates cached content configurations. + * + * @param params - The parameters for the update request. + * @return The updated cached content. + * + * @example + * ```ts + * const response = await ai.caches.update({ + * name: '...', // The server-generated resource name. + * config: {'ttl': '7600s'} + * }); + * ``` + */ + async update(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = updateCachedContentParametersToVertex(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'PATCH', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + else { + const body = updateCachedContentParametersToMldev(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'PATCH', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } + async listInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = listCachedContentsParametersToVertex(params); + path = formatMap('cachedContents', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listCachedContentsResponseFromVertex(apiResponse); + const typedResp = new ListCachedContentsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = listCachedContentsParametersToMldev(params); + path = formatMap('cachedContents', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listCachedContentsResponseFromMldev(apiResponse); + const typedResp = new ListCachedContentsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } +} + +/****************************************************************************** +Copyright (c) Microsoft Corporation. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +***************************************************************************** */ +/* global Reflect, Promise, SuppressedError, Symbol, Iterator */ + + +function __rest(s, e) { + var t = {}; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) + t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === "function") + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { + if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) + t[p[i]] = s[p[i]]; + } + return t; +} + +function __values(o) { + var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; + if (m) return m.call(o); + if (o && typeof o.length === "number") return { + next: function () { + if (o && i >= o.length) o = void 0; + return { value: o && o[i++], done: !o }; + } + }; + throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); +} + +function __await(v) { + return this instanceof __await ? (this.v = v, this) : new __await(v); +} + +function __asyncGenerator(thisArg, _arguments, generator) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var g = generator.apply(thisArg, _arguments || []), i, q = []; + return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i; + function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; } + function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } } + function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function fulfill(value) { resume("next", value); } + function reject(value) { resume("throw", value); } + function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } +} + +function __asyncValues(o) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var m = o[Symbol.asyncIterator], i; + return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); + function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } + function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } +} + +typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { + var e = new Error(message); + return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Returns true if the response is valid, false otherwise. + */ +function isValidResponse(response) { + var _a; + if (response.candidates == undefined || response.candidates.length === 0) { + return false; + } + const content = (_a = response.candidates[0]) === null || _a === void 0 ? void 0 : _a.content; + if (content === undefined) { + return false; + } + return isValidContent(content); +} +function isValidContent(content) { + if (content.parts === undefined || content.parts.length === 0) { + return false; + } + for (const part of content.parts) { + if (part === undefined || Object.keys(part).length === 0) { + return false; + } + } + return true; +} +/** + * Validates the history contains the correct roles. + * + * @throws Error if the history does not start with a user turn. + * @throws Error if the history contains an invalid role. + */ +function validateHistory(history) { + // Empty history is valid. + if (history.length === 0) { + return; + } + for (const content of history) { + if (content.role !== 'user' && content.role !== 'model') { + throw new Error(`Role must be user or model, but got ${content.role}.`); + } + } +} +/** + * Extracts the curated (valid) history from a comprehensive history. + * + * @remarks + * The model may sometimes generate invalid or empty contents(e.g., due to safty + * filters or recitation). Extracting valid turns from the history + * ensures that subsequent requests could be accpeted by the model. + */ +function extractCuratedHistory(comprehensiveHistory) { + if (comprehensiveHistory === undefined || comprehensiveHistory.length === 0) { + return []; + } + const curatedHistory = []; + const length = comprehensiveHistory.length; + let i = 0; + while (i < length) { + if (comprehensiveHistory[i].role === 'user') { + curatedHistory.push(comprehensiveHistory[i]); + i++; + } + else { + const modelOutput = []; + let isValid = true; + while (i < length && comprehensiveHistory[i].role === 'model') { + modelOutput.push(comprehensiveHistory[i]); + if (isValid && !isValidContent(comprehensiveHistory[i])) { + isValid = false; + } + i++; + } + if (isValid) { + curatedHistory.push(...modelOutput); + } + else { + // Remove the last user input when model content is invalid. + curatedHistory.pop(); + } + } + } + return curatedHistory; +} +/** + * A utility class to create a chat session. + */ +class Chats { + constructor(modelsModule, apiClient) { + this.modelsModule = modelsModule; + this.apiClient = apiClient; + } + /** + * Creates a new chat session. + * + * @remarks + * The config in the params will be used for all requests within the chat + * session unless overridden by a per-request `config` in + * @see {@link types.SendMessageParameters#config}. + * + * @param params - Parameters for creating a chat session. + * @returns A new chat session. + * + * @example + * ```ts + * const chat = ai.chats.create({ + * model: 'gemini-2.0-flash' + * config: { + * temperature: 0.5, + * maxOutputTokens: 1024, + * } + * }); + * ``` + */ + create(params) { + return new Chat(this.apiClient, this.modelsModule, params.model, params.config, + // Deep copy the history to avoid mutating the history outside of the + // chat session. + structuredClone(params.history)); + } +} +/** + * Chat session that enables sending messages to the model with previous + * conversation context. + * + * @remarks + * The session maintains all the turns between user and model. + */ +class Chat { + constructor(apiClient, modelsModule, model, config = {}, history = []) { + this.apiClient = apiClient; + this.modelsModule = modelsModule; + this.model = model; + this.config = config; + this.history = history; + // A promise to represent the current state of the message being sent to the + // model. + this.sendPromise = Promise.resolve(); + validateHistory(history); + } + /** + * Sends a message to the model and returns the response. + * + * @remarks + * This method will wait for the previous message to be processed before + * sending the next message. + * + * @see {@link Chat#sendMessageStream} for streaming method. + * @param params - parameters for sending messages within a chat session. + * @returns The model's response. + * + * @example + * ```ts + * const chat = ai.chats.create({model: 'gemini-2.0-flash'}); + * const response = await chat.sendMessage({ + * message: 'Why is the sky blue?' + * }); + * console.log(response.text); + * ``` + */ + async sendMessage(params) { + var _a; + await this.sendPromise; + const inputContent = tContent(params.message); + const responsePromise = this.modelsModule.generateContent({ + model: this.model, + contents: this.getHistory(true).concat(inputContent), + config: (_a = params.config) !== null && _a !== void 0 ? _a : this.config, + }); + this.sendPromise = (async () => { + var _a, _b, _c; + const response = await responsePromise; + const outputContent = (_b = (_a = response.candidates) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.content; + // Because the AFC input contains the entire curated chat history in + // addition to the new user input, we need to truncate the AFC history + // to deduplicate the existing chat history. + const fullAutomaticFunctionCallingHistory = response.automaticFunctionCallingHistory; + const index = this.getHistory(true).length; + let automaticFunctionCallingHistory = []; + if (fullAutomaticFunctionCallingHistory != null) { + automaticFunctionCallingHistory = + (_c = fullAutomaticFunctionCallingHistory.slice(index)) !== null && _c !== void 0 ? _c : []; + } + const modelOutput = outputContent ? [outputContent] : []; + this.recordHistory(inputContent, modelOutput, automaticFunctionCallingHistory); + return; + })(); + await this.sendPromise.catch(() => { + // Resets sendPromise to avoid subsequent calls failing + this.sendPromise = Promise.resolve(); + }); + return responsePromise; + } + /** + * Sends a message to the model and returns the response in chunks. + * + * @remarks + * This method will wait for the previous message to be processed before + * sending the next message. + * + * @see {@link Chat#sendMessage} for non-streaming method. + * @param params - parameters for sending the message. + * @return The model's response. + * + * @example + * ```ts + * const chat = ai.chats.create({model: 'gemini-2.0-flash'}); + * const response = await chat.sendMessageStream({ + * message: 'Why is the sky blue?' + * }); + * for await (const chunk of response) { + * console.log(chunk.text); + * } + * ``` + */ + async sendMessageStream(params) { + var _a; + await this.sendPromise; + const inputContent = tContent(params.message); + const streamResponse = this.modelsModule.generateContentStream({ + model: this.model, + contents: this.getHistory(true).concat(inputContent), + config: (_a = params.config) !== null && _a !== void 0 ? _a : this.config, + }); + // Resolve the internal tracking of send completion promise - `sendPromise` + // for both success and failure response. The actual failure is still + // propagated by the `await streamResponse`. + this.sendPromise = streamResponse + .then(() => undefined) + .catch(() => undefined); + const response = await streamResponse; + const result = this.processStreamResponse(response, inputContent); + return result; + } + /** + * Returns the chat history. + * + * @remarks + * The history is a list of contents alternating between user and model. + * + * There are two types of history: + * - The `curated history` contains only the valid turns between user and + * model, which will be included in the subsequent requests sent to the model. + * - The `comprehensive history` contains all turns, including invalid or + * empty model outputs, providing a complete record of the history. + * + * The history is updated after receiving the response from the model, + * for streaming response, it means receiving the last chunk of the response. + * + * The `comprehensive history` is returned by default. To get the `curated + * history`, set the `curated` parameter to `true`. + * + * @param curated - whether to return the curated history or the comprehensive + * history. + * @return History contents alternating between user and model for the entire + * chat session. + */ + getHistory(curated = false) { + const history = curated + ? extractCuratedHistory(this.history) + : this.history; + // Deep copy the history to avoid mutating the history outside of the + // chat session. + return structuredClone(history); + } + processStreamResponse(streamResponse, inputContent) { + return __asyncGenerator(this, arguments, function* processStreamResponse_1() { + var _a, e_1, _b, _c; + var _d, _e; + const outputContent = []; + try { + for (var _f = true, streamResponse_1 = __asyncValues(streamResponse), streamResponse_1_1; streamResponse_1_1 = yield __await(streamResponse_1.next()), _a = streamResponse_1_1.done, !_a; _f = true) { + _c = streamResponse_1_1.value; + _f = false; + const chunk = _c; + if (isValidResponse(chunk)) { + const content = (_e = (_d = chunk.candidates) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.content; + if (content !== undefined) { + outputContent.push(content); + } + } + yield yield __await(chunk); + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (!_f && !_a && (_b = streamResponse_1.return)) yield __await(_b.call(streamResponse_1)); + } + finally { if (e_1) throw e_1.error; } + } + this.recordHistory(inputContent, outputContent); + }); + } + recordHistory(userInput, modelOutput, automaticFunctionCallingHistory) { + let outputContents = []; + if (modelOutput.length > 0 && + modelOutput.every((content) => content.role !== undefined)) { + outputContents = modelOutput; + } + else { + // Appends an empty content when model returns empty response, so that the + // history is always alternating between user and model. + outputContents.push({ + role: 'model', + parts: [], + }); + } + if (automaticFunctionCallingHistory && + automaticFunctionCallingHistory.length > 0) { + this.history.push(...extractCuratedHistory(automaticFunctionCallingHistory)); + } + else { + this.history.push(userInput); + } + this.history.push(...outputContents); + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Code generated by the Google Gen AI SDK generator DO NOT EDIT. +function createFileSearchStoreConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromDisplayName); + } + return toObject; +} +function createFileSearchStoreParametersToMldev(fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createFileSearchStoreConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function deleteFileSearchStoreConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromForce = getValueByPath(fromObject, ['force']); + if (parentObject !== undefined && fromForce != null) { + setValueByPath(parentObject, ['_query', 'force'], fromForce); + } + return toObject; +} +function deleteFileSearchStoreParametersToMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + deleteFileSearchStoreConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function getFileSearchStoreParametersToMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + return toObject; +} +function importFileConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromCustomMetadata = getValueByPath(fromObject, [ + 'customMetadata', + ]); + if (parentObject !== undefined && fromCustomMetadata != null) { + let transformedList = fromCustomMetadata; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(parentObject, ['customMetadata'], transformedList); + } + const fromChunkingConfig = getValueByPath(fromObject, [ + 'chunkingConfig', + ]); + if (parentObject !== undefined && fromChunkingConfig != null) { + setValueByPath(parentObject, ['chunkingConfig'], fromChunkingConfig); + } + return toObject; +} +function importFileOperationFromMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], importFileResponseFromMldev(fromResponse)); + } + return toObject; +} +function importFileParametersToMldev(fromObject) { + const toObject = {}; + const fromFileSearchStoreName = getValueByPath(fromObject, [ + 'fileSearchStoreName', + ]); + if (fromFileSearchStoreName != null) { + setValueByPath(toObject, ['_url', 'file_search_store_name'], fromFileSearchStoreName); + } + const fromFileName = getValueByPath(fromObject, ['fileName']); + if (fromFileName != null) { + setValueByPath(toObject, ['fileName'], fromFileName); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + importFileConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function importFileResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromParent = getValueByPath(fromObject, ['parent']); + if (fromParent != null) { + setValueByPath(toObject, ['parent'], fromParent); + } + const fromDocumentName = getValueByPath(fromObject, ['documentName']); + if (fromDocumentName != null) { + setValueByPath(toObject, ['documentName'], fromDocumentName); + } + return toObject; +} +function listFileSearchStoresConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + return toObject; +} +function listFileSearchStoresParametersToMldev(fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listFileSearchStoresConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function listFileSearchStoresResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromFileSearchStores = getValueByPath(fromObject, [ + 'fileSearchStores', + ]); + if (fromFileSearchStores != null) { + let transformedList = fromFileSearchStores; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['fileSearchStores'], transformedList); + } + return toObject; +} +function uploadToFileSearchStoreConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (parentObject !== undefined && fromMimeType != null) { + setValueByPath(parentObject, ['mimeType'], fromMimeType); + } + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromDisplayName); + } + const fromCustomMetadata = getValueByPath(fromObject, [ + 'customMetadata', + ]); + if (parentObject !== undefined && fromCustomMetadata != null) { + let transformedList = fromCustomMetadata; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(parentObject, ['customMetadata'], transformedList); + } + const fromChunkingConfig = getValueByPath(fromObject, [ + 'chunkingConfig', + ]); + if (parentObject !== undefined && fromChunkingConfig != null) { + setValueByPath(parentObject, ['chunkingConfig'], fromChunkingConfig); + } + return toObject; +} +function uploadToFileSearchStoreParametersToMldev(fromObject) { + const toObject = {}; + const fromFileSearchStoreName = getValueByPath(fromObject, [ + 'fileSearchStoreName', + ]); + if (fromFileSearchStoreName != null) { + setValueByPath(toObject, ['_url', 'file_search_store_name'], fromFileSearchStoreName); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + uploadToFileSearchStoreConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function uploadToFileSearchStoreResumableResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * API errors raised by the GenAI API. + */ +class ApiError extends Error { + constructor(options) { + super(options.message); + this.name = 'ApiError'; + this.status = options.status; + Object.setPrototypeOf(this, ApiError.prototype); + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const CONTENT_TYPE_HEADER = 'Content-Type'; +const SERVER_TIMEOUT_HEADER = 'X-Server-Timeout'; +const USER_AGENT_HEADER = 'User-Agent'; +const GOOGLE_API_CLIENT_HEADER = 'x-goog-api-client'; +const SDK_VERSION = '1.41.0'; // x-release-please-version +const LIBRARY_LABEL = `google-genai-sdk/${SDK_VERSION}`; +const VERTEX_AI_API_DEFAULT_VERSION = 'v1beta1'; +const GOOGLE_AI_API_DEFAULT_VERSION = 'v1beta'; +// Default retry options. +// The config is based on https://cloud.google.com/storage/docs/retry-strategy. +const DEFAULT_RETRY_ATTEMPTS = 5; // Including the initial call +// LINT.IfChange +const DEFAULT_RETRY_HTTP_STATUS_CODES = [ + 408, // Request timeout + 429, // Too many requests + 500, // Internal server error + 502, // Bad gateway + 503, // Service unavailable + 504, // Gateway timeout +]; +/** + * The ApiClient class is used to send requests to the Gemini API or Vertex AI + * endpoints. + */ +class ApiClient { + constructor(opts) { + var _a, _b, _c; + this.clientOptions = Object.assign({}, opts); + this.customBaseUrl = (_a = opts.httpOptions) === null || _a === void 0 ? void 0 : _a.baseUrl; + if (this.clientOptions.vertexai) { + if (this.clientOptions.project && this.clientOptions.location) { + this.clientOptions.apiKey = undefined; + } + else if (this.clientOptions.apiKey) { + this.clientOptions.project = undefined; + this.clientOptions.location = undefined; + } + } + const initHttpOptions = {}; + if (this.clientOptions.vertexai) { + if (!this.clientOptions.location && + !this.clientOptions.apiKey && + !this.customBaseUrl) { + this.clientOptions.location = 'global'; + } + const hasSufficientAuth = (this.clientOptions.project && this.clientOptions.location) || + this.clientOptions.apiKey; + if (!hasSufficientAuth && !this.customBaseUrl) { + throw new Error('Authentication is not set up. Please provide either a project and location, or an API key, or a custom base URL.'); + } + const hasConstructorAuth = (opts.project && opts.location) || !!opts.apiKey; + if (this.customBaseUrl && !hasConstructorAuth) { + initHttpOptions.baseUrl = this.customBaseUrl; + this.clientOptions.project = undefined; + this.clientOptions.location = undefined; + } + else if (this.clientOptions.apiKey || + this.clientOptions.location === 'global') { + // Vertex Express or global endpoint case. + initHttpOptions.baseUrl = 'https://aiplatform.googleapis.com/'; + } + else if (this.clientOptions.project && this.clientOptions.location) { + initHttpOptions.baseUrl = `https://${this.clientOptions.location}-aiplatform.googleapis.com/`; + } + initHttpOptions.apiVersion = + (_b = this.clientOptions.apiVersion) !== null && _b !== void 0 ? _b : VERTEX_AI_API_DEFAULT_VERSION; + } + else { + // Gemini API + if (!this.clientOptions.apiKey) { + throw new ApiError({ + message: 'API key must be set when using the Gemini API.', + status: 403, + }); + } + initHttpOptions.apiVersion = + (_c = this.clientOptions.apiVersion) !== null && _c !== void 0 ? _c : GOOGLE_AI_API_DEFAULT_VERSION; + initHttpOptions.baseUrl = `https://generativelanguage.googleapis.com/`; + } + initHttpOptions.headers = this.getDefaultHeaders(); + this.clientOptions.httpOptions = initHttpOptions; + if (opts.httpOptions) { + this.clientOptions.httpOptions = this.patchHttpOptions(initHttpOptions, opts.httpOptions); + } + } + isVertexAI() { + var _a; + return (_a = this.clientOptions.vertexai) !== null && _a !== void 0 ? _a : false; + } + getProject() { + return this.clientOptions.project; + } + getLocation() { + return this.clientOptions.location; + } + getCustomBaseUrl() { + return this.customBaseUrl; + } + async getAuthHeaders() { + const headers = new Headers(); + await this.clientOptions.auth.addAuthHeaders(headers); + return headers; + } + getApiVersion() { + if (this.clientOptions.httpOptions && + this.clientOptions.httpOptions.apiVersion !== undefined) { + return this.clientOptions.httpOptions.apiVersion; + } + throw new Error('API version is not set.'); + } + getBaseUrl() { + if (this.clientOptions.httpOptions && + this.clientOptions.httpOptions.baseUrl !== undefined) { + return this.clientOptions.httpOptions.baseUrl; + } + throw new Error('Base URL is not set.'); + } + getRequestUrl() { + return this.getRequestUrlInternal(this.clientOptions.httpOptions); + } + getHeaders() { + if (this.clientOptions.httpOptions && + this.clientOptions.httpOptions.headers !== undefined) { + return this.clientOptions.httpOptions.headers; + } + else { + throw new Error('Headers are not set.'); + } + } + getRequestUrlInternal(httpOptions) { + if (!httpOptions || + httpOptions.baseUrl === undefined || + httpOptions.apiVersion === undefined) { + throw new Error('HTTP options are not correctly set.'); + } + const baseUrl = httpOptions.baseUrl.endsWith('/') + ? httpOptions.baseUrl.slice(0, -1) + : httpOptions.baseUrl; + const urlElement = [baseUrl]; + if (httpOptions.apiVersion && httpOptions.apiVersion !== '') { + urlElement.push(httpOptions.apiVersion); + } + return urlElement.join('/'); + } + getBaseResourcePath() { + return `projects/${this.clientOptions.project}/locations/${this.clientOptions.location}`; + } + getApiKey() { + return this.clientOptions.apiKey; + } + getWebsocketBaseUrl() { + const baseUrl = this.getBaseUrl(); + const urlParts = new URL(baseUrl); + urlParts.protocol = urlParts.protocol == 'http:' ? 'ws' : 'wss'; + return urlParts.toString(); + } + setBaseUrl(url) { + if (this.clientOptions.httpOptions) { + this.clientOptions.httpOptions.baseUrl = url; + } + else { + throw new Error('HTTP options are not correctly set.'); + } + } + constructUrl(path, httpOptions, prependProjectLocation) { + const urlElement = [this.getRequestUrlInternal(httpOptions)]; + if (prependProjectLocation) { + urlElement.push(this.getBaseResourcePath()); + } + if (path !== '') { + urlElement.push(path); + } + const url = new URL(`${urlElement.join('/')}`); + return url; + } + shouldPrependVertexProjectPath(request, httpOptions) { + if (httpOptions.baseUrl && + httpOptions.baseUrlResourceScope === exports.ResourceScope.COLLECTION) { + return false; + } + if (this.clientOptions.apiKey) { + return false; + } + if (!this.clientOptions.vertexai) { + return false; + } + if (request.path.startsWith('projects/')) { + // Assume the path already starts with + // `projects/<project>/location/<location>`. + return false; + } + if (request.httpMethod === 'GET' && + request.path.startsWith('publishers/google/models')) { + // These paths are used by Vertex's models.get and models.list + // calls. For base models Vertex does not accept a project/location + // prefix (for tuned model the prefix is required). + return false; + } + return true; + } + async request(request) { + let patchedHttpOptions = this.clientOptions.httpOptions; + if (request.httpOptions) { + patchedHttpOptions = this.patchHttpOptions(this.clientOptions.httpOptions, request.httpOptions); + } + const prependProjectLocation = this.shouldPrependVertexProjectPath(request, patchedHttpOptions); + const url = this.constructUrl(request.path, patchedHttpOptions, prependProjectLocation); + if (request.queryParams) { + for (const [key, value] of Object.entries(request.queryParams)) { + url.searchParams.append(key, String(value)); + } + } + let requestInit = {}; + if (request.httpMethod === 'GET') { + if (request.body && request.body !== '{}') { + throw new Error('Request body should be empty for GET request, but got non empty request body'); + } + } + else { + requestInit.body = request.body; + } + requestInit = await this.includeExtraHttpOptionsToRequestInit(requestInit, patchedHttpOptions, url.toString(), request.abortSignal); + return this.unaryApiCall(url, requestInit, request.httpMethod); + } + patchHttpOptions(baseHttpOptions, requestHttpOptions) { + const patchedHttpOptions = JSON.parse(JSON.stringify(baseHttpOptions)); + for (const [key, value] of Object.entries(requestHttpOptions)) { + // Records compile to objects. + if (typeof value === 'object') { + // @ts-expect-error TS2345TS7053: Element implicitly has an 'any' type + // because expression of type 'string' can't be used to index type + // 'HttpOptions'. + patchedHttpOptions[key] = Object.assign(Object.assign({}, patchedHttpOptions[key]), value); + } + else if (value !== undefined) { + // @ts-expect-error TS2345TS7053: Element implicitly has an 'any' type + // because expression of type 'string' can't be used to index type + // 'HttpOptions'. + patchedHttpOptions[key] = value; + } + } + return patchedHttpOptions; + } + async requestStream(request) { + let patchedHttpOptions = this.clientOptions.httpOptions; + if (request.httpOptions) { + patchedHttpOptions = this.patchHttpOptions(this.clientOptions.httpOptions, request.httpOptions); + } + const prependProjectLocation = this.shouldPrependVertexProjectPath(request, patchedHttpOptions); + const url = this.constructUrl(request.path, patchedHttpOptions, prependProjectLocation); + if (!url.searchParams.has('alt') || url.searchParams.get('alt') !== 'sse') { + url.searchParams.set('alt', 'sse'); + } + let requestInit = {}; + requestInit.body = request.body; + requestInit = await this.includeExtraHttpOptionsToRequestInit(requestInit, patchedHttpOptions, url.toString(), request.abortSignal); + return this.streamApiCall(url, requestInit, request.httpMethod); + } + async includeExtraHttpOptionsToRequestInit(requestInit, httpOptions, url, abortSignal) { + if ((httpOptions && httpOptions.timeout) || abortSignal) { + const abortController = new AbortController(); + const signal = abortController.signal; + if (httpOptions.timeout && (httpOptions === null || httpOptions === void 0 ? void 0 : httpOptions.timeout) > 0) { + const timeoutHandle = setTimeout(() => abortController.abort(), httpOptions.timeout); + if (timeoutHandle && + typeof timeoutHandle.unref === + 'function') { + // call unref to prevent nodejs process from hanging, see + // https://nodejs.org/api/timers.html#timeoutunref + timeoutHandle.unref(); + } + } + if (abortSignal) { + abortSignal.addEventListener('abort', () => { + abortController.abort(); + }); + } + requestInit.signal = signal; + } + if (httpOptions && httpOptions.extraBody !== null) { + includeExtraBodyToRequestInit(requestInit, httpOptions.extraBody); + } + requestInit.headers = await this.getHeadersInternal(httpOptions, url); + return requestInit; + } + async unaryApiCall(url, requestInit, httpMethod) { + return this.apiCall(url.toString(), Object.assign(Object.assign({}, requestInit), { method: httpMethod })) + .then(async (response) => { + await throwErrorIfNotOK(response); + return new HttpResponse(response); + }) + .catch((e) => { + if (e instanceof Error) { + throw e; + } + else { + throw new Error(JSON.stringify(e)); + } + }); + } + async streamApiCall(url, requestInit, httpMethod) { + return this.apiCall(url.toString(), Object.assign(Object.assign({}, requestInit), { method: httpMethod })) + .then(async (response) => { + await throwErrorIfNotOK(response); + return this.processStreamResponse(response); + }) + .catch((e) => { + if (e instanceof Error) { + throw e; + } + else { + throw new Error(JSON.stringify(e)); + } + }); + } + processStreamResponse(response) { + return __asyncGenerator(this, arguments, function* processStreamResponse_1() { + var _a; + const reader = (_a = response === null || response === void 0 ? void 0 : response.body) === null || _a === void 0 ? void 0 : _a.getReader(); + const decoder = new TextDecoder('utf-8'); + if (!reader) { + throw new Error('Response body is empty'); + } + try { + let buffer = ''; + const dataPrefix = 'data:'; + const delimiters = ['\n\n', '\r\r', '\r\n\r\n']; + while (true) { + const { done, value } = yield __await(reader.read()); + if (done) { + if (buffer.trim().length > 0) { + throw new Error('Incomplete JSON segment at the end'); + } + break; + } + const chunkString = decoder.decode(value, { stream: true }); + // Parse and throw an error if the chunk contains an error. + try { + const chunkJson = JSON.parse(chunkString); + if ('error' in chunkJson) { + const errorJson = JSON.parse(JSON.stringify(chunkJson['error'])); + const status = errorJson['status']; + const code = errorJson['code']; + const errorMessage = `got status: ${status}. ${JSON.stringify(chunkJson)}`; + if (code >= 400 && code < 600) { + const apiError = new ApiError({ + message: errorMessage, + status: code, + }); + throw apiError; + } + } + } + catch (e) { + const error = e; + if (error.name === 'ApiError') { + throw e; + } + } + buffer += chunkString; + let delimiterIndex = -1; + let delimiterLength = 0; + while (true) { + delimiterIndex = -1; + delimiterLength = 0; + for (const delimiter of delimiters) { + const index = buffer.indexOf(delimiter); + if (index !== -1 && + (delimiterIndex === -1 || index < delimiterIndex)) { + delimiterIndex = index; + delimiterLength = delimiter.length; + } + } + if (delimiterIndex === -1) { + break; // No complete event in buffer + } + const eventString = buffer.substring(0, delimiterIndex); + buffer = buffer.substring(delimiterIndex + delimiterLength); + const trimmedEvent = eventString.trim(); + if (trimmedEvent.startsWith(dataPrefix)) { + const processedChunkString = trimmedEvent + .substring(dataPrefix.length) + .trim(); + try { + const partialResponse = new Response(processedChunkString, { + headers: response === null || response === void 0 ? void 0 : response.headers, + status: response === null || response === void 0 ? void 0 : response.status, + statusText: response === null || response === void 0 ? void 0 : response.statusText, + }); + yield yield __await(new HttpResponse(partialResponse)); + } + catch (e) { + throw new Error(`exception parsing stream chunk ${processedChunkString}. ${e}`); + } + } + } + } + } + finally { + reader.releaseLock(); + } + }); + } + async apiCall(url, requestInit) { + var _a; + if (!this.clientOptions.httpOptions || + !this.clientOptions.httpOptions.retryOptions) { + return fetch(url, requestInit); + } + const retryOptions = this.clientOptions.httpOptions.retryOptions; + const runFetch = async () => { + const response = await fetch(url, requestInit); + if (response.ok) { + return response; + } + if (DEFAULT_RETRY_HTTP_STATUS_CODES.includes(response.status)) { + throw new Error(`Retryable HTTP Error: ${response.statusText}`); + } + throw new pRetry.AbortError(`Non-retryable exception ${response.statusText} sending request`); + }; + return pRetry(runFetch, { + // Retry attempts is one less than the number of total attempts. + retries: ((_a = retryOptions.attempts) !== null && _a !== void 0 ? _a : DEFAULT_RETRY_ATTEMPTS) - 1, + }); + } + getDefaultHeaders() { + const headers = {}; + const versionHeaderValue = LIBRARY_LABEL + ' ' + this.clientOptions.userAgentExtra; + headers[USER_AGENT_HEADER] = versionHeaderValue; + headers[GOOGLE_API_CLIENT_HEADER] = versionHeaderValue; + headers[CONTENT_TYPE_HEADER] = 'application/json'; + return headers; + } + async getHeadersInternal(httpOptions, url) { + const headers = new Headers(); + if (httpOptions && httpOptions.headers) { + for (const [key, value] of Object.entries(httpOptions.headers)) { + headers.append(key, value); + } + // Append a timeout header if it is set, note that the timeout option is + // in milliseconds but the header is in seconds. + if (httpOptions.timeout && httpOptions.timeout > 0) { + headers.append(SERVER_TIMEOUT_HEADER, String(Math.ceil(httpOptions.timeout / 1000))); + } + } + await this.clientOptions.auth.addAuthHeaders(headers, url); + return headers; + } + getFileName(file) { + var _a; + let fileName = ''; + if (typeof file === 'string') { + fileName = file.replace(/[/\\]+$/, ''); + fileName = (_a = fileName.split(/[/\\]/).pop()) !== null && _a !== void 0 ? _a : ''; + } + return fileName; + } + /** + * Uploads a file asynchronously using Gemini API only, this is not supported + * in Vertex AI. + * + * @param file The string path to the file to be uploaded or a Blob object. + * @param config Optional parameters specified in the `UploadFileConfig` + * interface. @see {@link types.UploadFileConfig} + * @return A promise that resolves to a `File` object. + * @throws An error if called on a Vertex AI client. + * @throws An error if the `mimeType` is not provided and can not be inferred, + */ + async uploadFile(file, config) { + var _a; + const fileToUpload = {}; + if (config != null) { + fileToUpload.mimeType = config.mimeType; + fileToUpload.name = config.name; + fileToUpload.displayName = config.displayName; + } + if (fileToUpload.name && !fileToUpload.name.startsWith('files/')) { + fileToUpload.name = `files/${fileToUpload.name}`; + } + const uploader = this.clientOptions.uploader; + const fileStat = await uploader.stat(file); + fileToUpload.sizeBytes = String(fileStat.size); + const mimeType = (_a = config === null || config === void 0 ? void 0 : config.mimeType) !== null && _a !== void 0 ? _a : fileStat.type; + if (mimeType === undefined || mimeType === '') { + throw new Error('Can not determine mimeType. Please provide mimeType in the config.'); + } + fileToUpload.mimeType = mimeType; + const body = { + file: fileToUpload, + }; + const fileName = this.getFileName(file); + const path = formatMap('upload/v1beta/files', body['_url']); + const uploadUrl = await this.fetchUploadUrl(path, fileToUpload.sizeBytes, fileToUpload.mimeType, fileName, body, config === null || config === void 0 ? void 0 : config.httpOptions); + return uploader.upload(file, uploadUrl, this); + } + /** + * Uploads a file to a given file search store asynchronously using Gemini API only, this is not supported + * in Vertex AI. + * + * @param fileSearchStoreName The name of the file search store to upload the file to. + * @param file The string path to the file to be uploaded or a Blob object. + * @param config Optional parameters specified in the `UploadFileConfig` + * interface. @see {@link UploadFileConfig} + * @return A promise that resolves to a `File` object. + * @throws An error if called on a Vertex AI client. + * @throws An error if the `mimeType` is not provided and can not be inferred, + */ + async uploadFileToFileSearchStore(fileSearchStoreName, file, config) { + var _a; + const uploader = this.clientOptions.uploader; + const fileStat = await uploader.stat(file); + const sizeBytes = String(fileStat.size); + const mimeType = (_a = config === null || config === void 0 ? void 0 : config.mimeType) !== null && _a !== void 0 ? _a : fileStat.type; + if (mimeType === undefined || mimeType === '') { + throw new Error('Can not determine mimeType. Please provide mimeType in the config.'); + } + const path = `upload/v1beta/${fileSearchStoreName}:uploadToFileSearchStore`; + const fileName = this.getFileName(file); + const body = {}; + if (config != null) { + uploadToFileSearchStoreConfigToMldev(config, body); + } + const uploadUrl = await this.fetchUploadUrl(path, sizeBytes, mimeType, fileName, body, config === null || config === void 0 ? void 0 : config.httpOptions); + return uploader.uploadToFileSearchStore(file, uploadUrl, this); + } + /** + * Downloads a file asynchronously to the specified path. + * + * @params params - The parameters for the download request, see {@link + * types.DownloadFileParameters} + */ + async downloadFile(params) { + const downloader = this.clientOptions.downloader; + await downloader.download(params, this); + } + async fetchUploadUrl(path, sizeBytes, mimeType, fileName, body, configHttpOptions) { + var _a; + let httpOptions = {}; + if (configHttpOptions) { + httpOptions = configHttpOptions; + } + else { + httpOptions = { + apiVersion: '', // api-version is set in the path. + headers: Object.assign({ 'Content-Type': 'application/json', 'X-Goog-Upload-Protocol': 'resumable', 'X-Goog-Upload-Command': 'start', 'X-Goog-Upload-Header-Content-Length': `${sizeBytes}`, 'X-Goog-Upload-Header-Content-Type': `${mimeType}` }, (fileName ? { 'X-Goog-Upload-File-Name': fileName } : {})), + }; + } + const httpResponse = await this.request({ + path, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions, + }); + if (!httpResponse || !(httpResponse === null || httpResponse === void 0 ? void 0 : httpResponse.headers)) { + throw new Error('Server did not return an HttpResponse or the returned HttpResponse did not have headers.'); + } + const uploadUrl = (_a = httpResponse === null || httpResponse === void 0 ? void 0 : httpResponse.headers) === null || _a === void 0 ? void 0 : _a['x-goog-upload-url']; + if (uploadUrl === undefined) { + throw new Error('Failed to get upload url. Server did not return the x-google-upload-url in the headers'); + } + return uploadUrl; + } +} +async function throwErrorIfNotOK(response) { + var _a; + if (response === undefined) { + throw new Error('response is undefined'); + } + if (!response.ok) { + const status = response.status; + let errorBody; + if ((_a = response.headers.get('content-type')) === null || _a === void 0 ? void 0 : _a.includes('application/json')) { + errorBody = await response.json(); + } + else { + errorBody = { + error: { + message: await response.text(), + code: response.status, + status: response.statusText, + }, + }; + } + const errorMessage = JSON.stringify(errorBody); + if (status >= 400 && status < 600) { + const apiError = new ApiError({ + message: errorMessage, + status: status, + }); + throw apiError; + } + throw new Error(errorMessage); + } +} +/** + * Recursively updates the `requestInit.body` with values from an `extraBody` object. + * + * If `requestInit.body` is a string, it's assumed to be JSON and will be parsed. + * The `extraBody` is then deeply merged into this parsed object. + * If `requestInit.body` is a Blob, `extraBody` will be ignored, and a warning logged, + * as merging structured data into an opaque Blob is not supported. + * + * The function does not enforce that updated values from `extraBody` have the + * same type as existing values in `requestInit.body`. Type mismatches during + * the merge will result in a warning, but the value from `extraBody` will overwrite + * the original. `extraBody` users are responsible for ensuring `extraBody` has the correct structure. + * + * @param requestInit The RequestInit object whose body will be updated. + * @param extraBody The object containing updates to be merged into `requestInit.body`. + */ +function includeExtraBodyToRequestInit(requestInit, extraBody) { + if (!extraBody || Object.keys(extraBody).length === 0) { + return; + } + if (requestInit.body instanceof Blob) { + console.warn('includeExtraBodyToRequestInit: extraBody provided but current request body is a Blob. extraBody will be ignored as merging is not supported for Blob bodies.'); + return; + } + let currentBodyObject = {}; + // If adding new type to HttpRequest.body, please check the code below to + // see if we need to update the logic. + if (typeof requestInit.body === 'string' && requestInit.body.length > 0) { + try { + const parsedBody = JSON.parse(requestInit.body); + if (typeof parsedBody === 'object' && + parsedBody !== null && + !Array.isArray(parsedBody)) { + currentBodyObject = parsedBody; + } + else { + console.warn('includeExtraBodyToRequestInit: Original request body is valid JSON but not a non-array object. Skip applying extraBody to the request body.'); + return; + } + /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ + } + catch (e) { + console.warn('includeExtraBodyToRequestInit: Original request body is not valid JSON. Skip applying extraBody to the request body.'); + return; + } + } + function deepMerge(target, source) { + const output = Object.assign({}, target); + for (const key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + const sourceValue = source[key]; + const targetValue = output[key]; + if (sourceValue && + typeof sourceValue === 'object' && + !Array.isArray(sourceValue) && + targetValue && + typeof targetValue === 'object' && + !Array.isArray(targetValue)) { + output[key] = deepMerge(targetValue, sourceValue); + } + else { + if (targetValue && + sourceValue && + typeof targetValue !== typeof sourceValue) { + console.warn(`includeExtraBodyToRequestInit:deepMerge: Type mismatch for key "${key}". Original type: ${typeof targetValue}, New type: ${typeof sourceValue}. Overwriting.`); + } + output[key] = sourceValue; + } + } + } + return output; + } + const mergedBody = deepMerge(currentBodyObject, extraBody); + requestInit.body = JSON.stringify(mergedBody); +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function crossError() { + // TODO(b/399934880): this message needs a link to a help page explaining how to enable conditional exports + return new Error(`This feature requires the web or Node specific @google/genai implementation, you can fix this by either: + +*Enabling conditional exports for your project [recommended]* + +*Using a platform specific import* - Make sure your code imports either '@google/genai/web' or '@google/genai/node' instead of '@google/genai'. +`); +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class CrossDownloader { + async download(_params, _apiClient) { + throw crossError(); + } +} + +const MAX_CHUNK_SIZE = 1024 * 1024 * 8; // bytes +const MAX_RETRY_COUNT = 3; +const INITIAL_RETRY_DELAY_MS = 1000; +const DELAY_MULTIPLIER = 2; +const X_GOOG_UPLOAD_STATUS_HEADER_FIELD = 'x-goog-upload-status'; +class CrossUploader { + async upload(file, uploadUrl, apiClient) { + if (typeof file === 'string') { + throw crossError(); + } + else { + return uploadBlob(file, uploadUrl, apiClient); + } + } + async uploadToFileSearchStore(file, uploadUrl, apiClient) { + if (typeof file === 'string') { + throw crossError(); + } + else { + return uploadBlobToFileSearchStore(file, uploadUrl, apiClient); + } + } + async stat(file) { + if (typeof file === 'string') { + throw crossError(); + } + else { + return getBlobStat(file); + } + } +} +async function uploadBlob(file, uploadUrl, apiClient) { + var _a; + const response = await uploadBlobInternal(file, uploadUrl, apiClient); + const responseJson = (await (response === null || response === void 0 ? void 0 : response.json())); + if (((_a = response === null || response === void 0 ? void 0 : response.headers) === null || _a === void 0 ? void 0 : _a[X_GOOG_UPLOAD_STATUS_HEADER_FIELD]) !== 'final') { + throw new Error('Failed to upload file: Upload status is not finalized.'); + } + return responseJson['file']; +} +async function uploadBlobToFileSearchStore(file, uploadUrl, apiClient) { + var _a; + const response = await uploadBlobInternal(file, uploadUrl, apiClient); + const responseJson = (await (response === null || response === void 0 ? void 0 : response.json())); + if (((_a = response === null || response === void 0 ? void 0 : response.headers) === null || _a === void 0 ? void 0 : _a[X_GOOG_UPLOAD_STATUS_HEADER_FIELD]) !== 'final') { + throw new Error('Failed to upload file: Upload status is not finalized.'); + } + const resp = uploadToFileSearchStoreOperationFromMldev(responseJson); + const typedResp = new UploadToFileSearchStoreOperation(); + Object.assign(typedResp, resp); + return typedResp; +} +async function uploadBlobInternal(file, uploadUrl, apiClient) { + var _a, _b; + let fileSize = 0; + let offset = 0; + let response = new HttpResponse(new Response()); + let uploadCommand = 'upload'; + fileSize = file.size; + while (offset < fileSize) { + const chunkSize = Math.min(MAX_CHUNK_SIZE, fileSize - offset); + const chunk = file.slice(offset, offset + chunkSize); + if (offset + chunkSize >= fileSize) { + uploadCommand += ', finalize'; + } + let retryCount = 0; + let currentDelayMs = INITIAL_RETRY_DELAY_MS; + while (retryCount < MAX_RETRY_COUNT) { + response = await apiClient.request({ + path: '', + body: chunk, + httpMethod: 'POST', + httpOptions: { + apiVersion: '', + baseUrl: uploadUrl, + headers: { + 'X-Goog-Upload-Command': uploadCommand, + 'X-Goog-Upload-Offset': String(offset), + 'Content-Length': String(chunkSize), + }, + }, + }); + if ((_a = response === null || response === void 0 ? void 0 : response.headers) === null || _a === void 0 ? void 0 : _a[X_GOOG_UPLOAD_STATUS_HEADER_FIELD]) { + break; + } + retryCount++; + await sleep$1(currentDelayMs); + currentDelayMs = currentDelayMs * DELAY_MULTIPLIER; + } + offset += chunkSize; + // The `x-goog-upload-status` header field can be `active`, `final` and + //`cancelled` in resposne. + if (((_b = response === null || response === void 0 ? void 0 : response.headers) === null || _b === void 0 ? void 0 : _b[X_GOOG_UPLOAD_STATUS_HEADER_FIELD]) !== 'active') { + break; + } + // TODO(b/401391430) Investigate why the upload status is not finalized + // even though all content has been uploaded. + if (fileSize <= offset) { + throw new Error('All content has been uploaded, but the upload status is not finalized.'); + } + } + return response; +} +async function getBlobStat(file) { + const fileStat = { size: file.size, type: file.type }; + return fileStat; +} +function sleep$1(ms) { + return new Promise((resolvePromise) => setTimeout(resolvePromise, ms)); +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class CrossWebSocketFactory { + create(_url, _headers, _callbacks) { + throw crossError(); + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Code generated by the Google Gen AI SDK generator DO NOT EDIT. +function createFileParametersToMldev(fromObject) { + const toObject = {}; + const fromFile = getValueByPath(fromObject, ['file']); + if (fromFile != null) { + setValueByPath(toObject, ['file'], fromFile); + } + return toObject; +} +function createFileResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function deleteFileParametersToMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'file'], tFileName(fromName)); + } + return toObject; +} +function deleteFileResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function getFileParametersToMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'file'], tFileName(fromName)); + } + return toObject; +} +function internalRegisterFilesParametersToMldev(fromObject) { + const toObject = {}; + const fromUris = getValueByPath(fromObject, ['uris']); + if (fromUris != null) { + setValueByPath(toObject, ['uris'], fromUris); + } + return toObject; +} +function listFilesConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + return toObject; +} +function listFilesParametersToMldev(fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listFilesConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function listFilesResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromFiles = getValueByPath(fromObject, ['files']); + if (fromFiles != null) { + let transformedList = fromFiles; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['files'], transformedList); + } + return toObject; +} +function registerFilesResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromFiles = getValueByPath(fromObject, ['files']); + if (fromFiles != null) { + let transformedList = fromFiles; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['files'], transformedList); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Files extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + /** + * Lists files. + * + * @param params - The parameters for the list request. + * @return - A pager of files. + * + * @example + * ```ts + * const files = await ai.files.list({config: {'pageSize': 2}}); + * for await (const file of files) { + * console.log(file); + * } + * ``` + */ + this.list = async (params = {}) => { + return new Pager(exports.PagedItem.PAGED_ITEM_FILES, (x) => this.listInternal(x), await this.listInternal(params), params); + }; + } + /** + * Uploads a file asynchronously to the Gemini API. + * This method is not available in Vertex AI. + * Supported upload sources: + * - Node.js: File path (string) or Blob object. + * - Browser: Blob object (e.g., File). + * + * @remarks + * The `mimeType` can be specified in the `config` parameter. If omitted: + * - For file path (string) inputs, the `mimeType` will be inferred from the + * file extension. + * - For Blob object inputs, the `mimeType` will be set to the Blob's `type` + * property. + * Somex eamples for file extension to mimeType mapping: + * .txt -> text/plain + * .json -> application/json + * .jpg -> image/jpeg + * .png -> image/png + * .mp3 -> audio/mpeg + * .mp4 -> video/mp4 + * + * This section can contain multiple paragraphs and code examples. + * + * @param params - Optional parameters specified in the + * `types.UploadFileParameters` interface. + * @see {@link types.UploadFileParameters#config} for the optional + * config in the parameters. + * @return A promise that resolves to a `types.File` object. + * @throws An error if called on a Vertex AI client. + * @throws An error if the `mimeType` is not provided and can not be inferred, + * the `mimeType` can be provided in the `params.config` parameter. + * @throws An error occurs if a suitable upload location cannot be established. + * + * @example + * The following code uploads a file to Gemini API. + * + * ```ts + * const file = await ai.files.upload({file: 'file.txt', config: { + * mimeType: 'text/plain', + * }}); + * console.log(file.name); + * ``` + */ + async upload(params) { + if (this.apiClient.isVertexAI()) { + throw new Error('Vertex AI does not support uploading files. You can share files through a GCS bucket.'); + } + return this.apiClient + .uploadFile(params.file, params.config) + .then((resp) => { + return resp; + }); + } + /** + * Downloads a remotely stored file asynchronously to a location specified in + * the `params` object. This method only works on Node environment, to + * download files in the browser, use a browser compliant method like an <a> + * tag. + * + * @param params - The parameters for the download request. + * + * @example + * The following code downloads an example file named "files/mehozpxf877d" as + * "file.txt". + * + * ```ts + * await ai.files.download({file: file.name, downloadPath: 'file.txt'}); + * ``` + */ + async download(params) { + await this.apiClient.downloadFile(params); + } + /** + * Registers Google Cloud Storage files for use with the API. + * This method is only available in Node.js environments. + */ + async registerFiles(params) { + throw new Error('registerFiles is only supported in Node.js environments.'); + } + async _registerFiles(params) { + return this.registerFilesInternal(params); + } + async listInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = listFilesParametersToMldev(params); + path = formatMap('files', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listFilesResponseFromMldev(apiResponse); + const typedResp = new ListFilesResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + async createInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = createFileParametersToMldev(params); + path = formatMap('upload/v1beta/files', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = createFileResponseFromMldev(apiResponse); + const typedResp = new CreateFileResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Retrieves the file information from the service. + * + * @param params - The parameters for the get request + * @return The Promise that resolves to the types.File object requested. + * + * @example + * ```ts + * const config: GetFileParameters = { + * name: fileName, + * }; + * file = await ai.files.get(config); + * console.log(file.name); + * ``` + */ + async get(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = getFileParametersToMldev(params); + path = formatMap('files/{file}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } + /** + * Deletes a remotely stored file. + * + * @param params - The parameters for the delete request. + * @return The DeleteFileResponse, the response for the delete method. + * + * @example + * The following code deletes an example file named "files/mehozpxf877d". + * + * ```ts + * await ai.files.delete({name: file.name}); + * ``` + */ + async delete(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = deleteFileParametersToMldev(params); + path = formatMap('files/{file}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = deleteFileResponseFromMldev(apiResponse); + const typedResp = new DeleteFileResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + async registerFilesInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = internalRegisterFilesParametersToMldev(params); + path = formatMap('files:register', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = registerFilesResponseFromMldev(apiResponse); + const typedResp = new RegisterFilesResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Code generated by the Google Gen AI SDK generator DO NOT EDIT. +function deleteDocumentConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromForce = getValueByPath(fromObject, ['force']); + if (parentObject !== undefined && fromForce != null) { + setValueByPath(parentObject, ['_query', 'force'], fromForce); + } + return toObject; +} +function deleteDocumentParametersToMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + deleteDocumentConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function getDocumentParametersToMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + return toObject; +} +function listDocumentsConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + return toObject; +} +function listDocumentsParametersToMldev(fromObject) { + const toObject = {}; + const fromParent = getValueByPath(fromObject, ['parent']); + if (fromParent != null) { + setValueByPath(toObject, ['_url', 'parent'], fromParent); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listDocumentsConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function listDocumentsResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromDocuments = getValueByPath(fromObject, ['documents']); + if (fromDocuments != null) { + let transformedList = fromDocuments; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['documents'], transformedList); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Documents extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + /** + * Lists documents. + * + * @param params - The parameters for the list request. + * @return - A pager of documents. + * + * @example + * ```ts + * const documents = await ai.documents.list({parent:'rag_store_name', config: {'pageSize': 2}}); + * for await (const document of documents) { + * console.log(document); + * } + * ``` + */ + this.list = async (params) => { + return new Pager(exports.PagedItem.PAGED_ITEM_DOCUMENTS, (x) => this.listInternal({ parent: params.parent, config: x.config }), await this.listInternal(params), params); + }; + } + /** + * Gets a Document. + * + * @param params - The parameters for getting a document. + * @return Document. + */ + async get(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = getDocumentParametersToMldev(params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } + /** + * Deletes a Document. + * + * @param params - The parameters for deleting a document. + */ + async delete(params) { + var _a, _b; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = deleteDocumentParametersToMldev(params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + await this.apiClient.request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }); + } + } + async listInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = listDocumentsParametersToMldev(params); + path = formatMap('{parent}/documents', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = listDocumentsResponseFromMldev(apiResponse); + const typedResp = new ListDocumentsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class FileSearchStores extends BaseModule { + constructor(apiClient, documents = new Documents(apiClient)) { + super(); + this.apiClient = apiClient; + this.documents = documents; + /** + * Lists file search stores. + * + * @param params - The parameters for the list request. + * @return - A pager of file search stores. + * + * @example + * ```ts + * const fileSearchStores = await ai.fileSearchStores.list({config: {'pageSize': 2}}); + * for await (const fileSearchStore of fileSearchStores) { + * console.log(fileSearchStore); + * } + * ``` + */ + this.list = async (params = {}) => { + return new Pager(exports.PagedItem.PAGED_ITEM_FILE_SEARCH_STORES, (x) => this.listInternal(x), await this.listInternal(params), params); + }; + } + /** + * Uploads a file asynchronously to a given File Search Store. + * This method is not available in Vertex AI. + * Supported upload sources: + * - Node.js: File path (string) or Blob object. + * - Browser: Blob object (e.g., File). + * + * @remarks + * The `mimeType` can be specified in the `config` parameter. If omitted: + * - For file path (string) inputs, the `mimeType` will be inferred from the + * file extension. + * - For Blob object inputs, the `mimeType` will be set to the Blob's `type` + * property. + * + * This section can contain multiple paragraphs and code examples. + * + * @param params - Optional parameters specified in the + * `types.UploadToFileSearchStoreParameters` interface. + * @see {@link types.UploadToFileSearchStoreParameters#config} for the optional + * config in the parameters. + * @return A promise that resolves to a long running operation. + * @throws An error if called on a Vertex AI client. + * @throws An error if the `mimeType` is not provided and can not be inferred, + * the `mimeType` can be provided in the `params.config` parameter. + * @throws An error occurs if a suitable upload location cannot be established. + * + * @example + * The following code uploads a file to a given file search store. + * + * ```ts + * const operation = await ai.fileSearchStores.upload({fileSearchStoreName: 'fileSearchStores/foo-bar', file: 'file.txt', config: { + * mimeType: 'text/plain', + * }}); + * console.log(operation.name); + * ``` + */ + async uploadToFileSearchStore(params) { + if (this.apiClient.isVertexAI()) { + throw new Error('Vertex AI does not support uploading files to a file search store.'); + } + return this.apiClient.uploadFileToFileSearchStore(params.fileSearchStoreName, params.file, params.config); + } + /** + * Creates a File Search Store. + * + * @param params - The parameters for creating a File Search Store. + * @return FileSearchStore. + */ + async create(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = createFileSearchStoreParametersToMldev(params); + path = formatMap('fileSearchStores', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } + /** + * Gets a File Search Store. + * + * @param params - The parameters for getting a File Search Store. + * @return FileSearchStore. + */ + async get(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = getFileSearchStoreParametersToMldev(params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } + /** + * Deletes a File Search Store. + * + * @param params - The parameters for deleting a File Search Store. + */ + async delete(params) { + var _a, _b; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = deleteFileSearchStoreParametersToMldev(params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + await this.apiClient.request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }); + } + } + async listInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = listFileSearchStoresParametersToMldev(params); + path = formatMap('fileSearchStores', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = listFileSearchStoresResponseFromMldev(apiResponse); + const typedResp = new ListFileSearchStoresResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + async uploadToFileSearchStoreInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = uploadToFileSearchStoreParametersToMldev(params); + path = formatMap('upload/v1beta/{file_search_store_name}:uploadToFileSearchStore', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = uploadToFileSearchStoreResumableResponseFromMldev(apiResponse); + const typedResp = new UploadToFileSearchStoreResumableResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Imports a File from File Service to a FileSearchStore. + * + * This is a long-running operation, see aip.dev/151 + * + * @param params - The parameters for importing a file to a file search store. + * @return ImportFileOperation. + */ + async importFile(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = importFileParametersToMldev(params); + path = formatMap('{file_search_store_name}:importFile', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = importFileOperationFromMldev(apiResponse); + const typedResp = new ImportFileOperation(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +/** + * https://stackoverflow.com/a/2117523 + */ +let uuid4Internal = function () { + const { crypto } = globalThis; + if (crypto === null || crypto === void 0 ? void 0 : crypto.randomUUID) { + uuid4Internal = crypto.randomUUID.bind(crypto); + return crypto.randomUUID(); + } + const u8 = new Uint8Array(1); + const randomByte = crypto ? () => crypto.getRandomValues(u8)[0] : () => (Math.random() * 0xff) & 0xff; + return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, (c) => (+c ^ (randomByte() & (15 >> (+c / 4)))).toString(16)); +}; +const uuid4 = () => uuid4Internal(); + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +function isAbortError(err) { + return (typeof err === 'object' && + err !== null && + // Spec-compliant fetch implementations + (('name' in err && err.name === 'AbortError') || + // Expo fetch + ('message' in err && String(err.message).includes('FetchRequestCanceledException')))); +} +const castToError = (err) => { + if (err instanceof Error) + return err; + if (typeof err === 'object' && err !== null) { + try { + if (Object.prototype.toString.call(err) === '[object Error]') { + // @ts-ignore - not all envs have native support for cause yet + const error = new Error(err.message, err.cause ? { cause: err.cause } : {}); + if (err.stack) + error.stack = err.stack; + // @ts-ignore - not all envs have native support for cause yet + if (err.cause && !error.cause) + error.cause = err.cause; + if (err.name) + error.name = err.name; + return error; + } + } + catch (_a) { } + try { + return new Error(JSON.stringify(err)); + } + catch (_b) { } + } + return new Error(err); +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +class GeminiNextGenAPIClientError extends Error { +} +class APIError extends GeminiNextGenAPIClientError { + constructor(status, error, message, headers) { + super(`${APIError.makeMessage(status, error, message)}`); + this.status = status; + this.headers = headers; + this.error = error; + } + static makeMessage(status, error, message) { + const msg = (error === null || error === void 0 ? void 0 : error.message) ? + typeof error.message === 'string' ? + error.message + : JSON.stringify(error.message) + : error ? JSON.stringify(error) + : message; + if (status && msg) { + return `${status} ${msg}`; + } + if (status) { + return `${status} status code (no body)`; + } + if (msg) { + return msg; + } + return '(no status code or body)'; + } + static generate(status, errorResponse, message, headers) { + if (!status || !headers) { + return new APIConnectionError({ message, cause: castToError(errorResponse) }); + } + const error = errorResponse; + if (status === 400) { + return new BadRequestError(status, error, message, headers); + } + if (status === 401) { + return new AuthenticationError(status, error, message, headers); + } + if (status === 403) { + return new PermissionDeniedError(status, error, message, headers); + } + if (status === 404) { + return new NotFoundError(status, error, message, headers); + } + if (status === 409) { + return new ConflictError(status, error, message, headers); + } + if (status === 422) { + return new UnprocessableEntityError(status, error, message, headers); + } + if (status === 429) { + return new RateLimitError(status, error, message, headers); + } + if (status >= 500) { + return new InternalServerError(status, error, message, headers); + } + return new APIError(status, error, message, headers); + } +} +class APIUserAbortError extends APIError { + constructor({ message } = {}) { + super(undefined, undefined, message || 'Request was aborted.', undefined); + } +} +class APIConnectionError extends APIError { + constructor({ message, cause }) { + super(undefined, undefined, message || 'Connection error.', undefined); + // in some environments the 'cause' property is already declared + // @ts-ignore + if (cause) + this.cause = cause; + } +} +class APIConnectionTimeoutError extends APIConnectionError { + constructor({ message } = {}) { + super({ message: message !== null && message !== void 0 ? message : 'Request timed out.' }); + } +} +class BadRequestError extends APIError { +} +class AuthenticationError extends APIError { +} +class PermissionDeniedError extends APIError { +} +class NotFoundError extends APIError { +} +class ConflictError extends APIError { +} +class UnprocessableEntityError extends APIError { +} +class RateLimitError extends APIError { +} +class InternalServerError extends APIError { +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +// https://url.spec.whatwg.org/#url-scheme-string +const startsWithSchemeRegexp = /^[a-z][a-z0-9+.-]*:/i; +const isAbsoluteURL = (url) => { + return startsWithSchemeRegexp.test(url); +}; +let isArrayInternal = (val) => ((isArrayInternal = Array.isArray), isArrayInternal(val)); +const isArray = isArrayInternal; +let isReadonlyArrayInternal = isArray; +const isReadonlyArray = isReadonlyArrayInternal; +// https://stackoverflow.com/a/34491287 +function isEmptyObj(obj) { + if (!obj) + return true; + for (const _k in obj) + return false; + return true; +} +// https://eslint.org/docs/latest/rules/no-prototype-builtins +function hasOwn(obj, key) { + return Object.prototype.hasOwnProperty.call(obj, key); +} +const validatePositiveInteger = (name, n) => { + if (typeof n !== 'number' || !Number.isInteger(n)) { + throw new GeminiNextGenAPIClientError(`${name} must be an integer`); + } + if (n < 0) { + throw new GeminiNextGenAPIClientError(`${name} must be a positive integer`); + } + return n; +}; +const safeJSON = (text) => { + try { + return JSON.parse(text); + } + catch (err) { + return undefined; + } +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const VERSION = '0.0.1'; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +/** + * Note this does not detect 'browser'; for that, use getBrowserInfo(). + */ +function getDetectedPlatform() { + if (typeof Deno !== 'undefined' && Deno.build != null) { + return 'deno'; + } + if (typeof EdgeRuntime !== 'undefined') { + return 'edge'; + } + if (Object.prototype.toString.call(typeof globalThis.process !== 'undefined' ? globalThis.process : 0) === '[object process]') { + return 'node'; + } + return 'unknown'; +} +const getPlatformProperties = () => { + var _a, _b, _c, _d, _e; + const detectedPlatform = getDetectedPlatform(); + if (detectedPlatform === 'deno') { + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': VERSION, + 'X-Stainless-OS': normalizePlatform(Deno.build.os), + 'X-Stainless-Arch': normalizeArch(Deno.build.arch), + 'X-Stainless-Runtime': 'deno', + 'X-Stainless-Runtime-Version': typeof Deno.version === 'string' ? Deno.version : (_b = (_a = Deno.version) === null || _a === void 0 ? void 0 : _a.deno) !== null && _b !== void 0 ? _b : 'unknown', + }; + } + if (typeof EdgeRuntime !== 'undefined') { + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': VERSION, + 'X-Stainless-OS': 'Unknown', + 'X-Stainless-Arch': `other:${EdgeRuntime}`, + 'X-Stainless-Runtime': 'edge', + 'X-Stainless-Runtime-Version': globalThis.process.version, + }; + } + // Check if Node.js + if (detectedPlatform === 'node') { + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': VERSION, + 'X-Stainless-OS': normalizePlatform((_c = globalThis.process.platform) !== null && _c !== void 0 ? _c : 'unknown'), + 'X-Stainless-Arch': normalizeArch((_d = globalThis.process.arch) !== null && _d !== void 0 ? _d : 'unknown'), + 'X-Stainless-Runtime': 'node', + 'X-Stainless-Runtime-Version': (_e = globalThis.process.version) !== null && _e !== void 0 ? _e : 'unknown', + }; + } + const browserInfo = getBrowserInfo(); + if (browserInfo) { + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': VERSION, + 'X-Stainless-OS': 'Unknown', + 'X-Stainless-Arch': 'unknown', + 'X-Stainless-Runtime': `browser:${browserInfo.browser}`, + 'X-Stainless-Runtime-Version': browserInfo.version, + }; + } + // TODO add support for Cloudflare workers, etc. + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': VERSION, + 'X-Stainless-OS': 'Unknown', + 'X-Stainless-Arch': 'unknown', + 'X-Stainless-Runtime': 'unknown', + 'X-Stainless-Runtime-Version': 'unknown', + }; +}; +// Note: modified from https://github.com/JS-DevTools/host-environment/blob/b1ab79ecde37db5d6e163c050e54fe7d287d7c92/src/isomorphic.browser.ts +function getBrowserInfo() { + if (typeof navigator === 'undefined' || !navigator) { + return null; + } + // NOTE: The order matters here! + const browserPatterns = [ + { key: 'edge', pattern: /Edge(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'ie', pattern: /MSIE(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'ie', pattern: /Trident(?:.*rv\:(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'chrome', pattern: /Chrome(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'firefox', pattern: /Firefox(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'safari', pattern: /(?:Version\W+(\d+)\.(\d+)(?:\.(\d+))?)?(?:\W+Mobile\S*)?\W+Safari/ }, + ]; + // Find the FIRST matching browser + for (const { key, pattern } of browserPatterns) { + const match = pattern.exec(navigator.userAgent); + if (match) { + const major = match[1] || 0; + const minor = match[2] || 0; + const patch = match[3] || 0; + return { browser: key, version: `${major}.${minor}.${patch}` }; + } + } + return null; +} +const normalizeArch = (arch) => { + // Node docs: + // - https://nodejs.org/api/process.html#processarch + // Deno docs: + // - https://doc.deno.land/deno/stable/~/Deno.build + if (arch === 'x32') + return 'x32'; + if (arch === 'x86_64' || arch === 'x64') + return 'x64'; + if (arch === 'arm') + return 'arm'; + if (arch === 'aarch64' || arch === 'arm64') + return 'arm64'; + if (arch) + return `other:${arch}`; + return 'unknown'; +}; +const normalizePlatform = (platform) => { + // Node platforms: + // - https://nodejs.org/api/process.html#processplatform + // Deno platforms: + // - https://doc.deno.land/deno/stable/~/Deno.build + // - https://github.com/denoland/deno/issues/14799 + platform = platform.toLowerCase(); + // NOTE: this iOS check is untested and may not work + // Node does not work natively on IOS, there is a fork at + // https://github.com/nodejs-mobile/nodejs-mobile + // however it is unknown at the time of writing how to detect if it is running + if (platform.includes('ios')) + return 'iOS'; + if (platform === 'android') + return 'Android'; + if (platform === 'darwin') + return 'MacOS'; + if (platform === 'win32') + return 'Windows'; + if (platform === 'freebsd') + return 'FreeBSD'; + if (platform === 'openbsd') + return 'OpenBSD'; + if (platform === 'linux') + return 'Linux'; + if (platform) + return `Other:${platform}`; + return 'Unknown'; +}; +let _platformHeaders; +const getPlatformHeaders = () => { + return (_platformHeaders !== null && _platformHeaders !== void 0 ? _platformHeaders : (_platformHeaders = getPlatformProperties())); +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function getDefaultFetch() { + if (typeof fetch !== 'undefined') { + return fetch; + } + throw new Error('`fetch` is not defined as a global; Either pass `fetch` to the client, `new GeminiNextGenAPIClient({ fetch })` or polyfill the global, `globalThis.fetch = fetch`'); +} +function makeReadableStream(...args) { + const ReadableStream = globalThis.ReadableStream; + if (typeof ReadableStream === 'undefined') { + // Note: All of the platforms / runtimes we officially support already define + // `ReadableStream` as a global, so this should only ever be hit on unsupported runtimes. + throw new Error('`ReadableStream` is not defined as a global; You will need to polyfill it, `globalThis.ReadableStream = ReadableStream`'); + } + return new ReadableStream(...args); +} +function ReadableStreamFrom(iterable) { + let iter = Symbol.asyncIterator in iterable ? iterable[Symbol.asyncIterator]() : iterable[Symbol.iterator](); + return makeReadableStream({ + start() { }, + async pull(controller) { + const { done, value } = await iter.next(); + if (done) { + controller.close(); + } + else { + controller.enqueue(value); + } + }, + async cancel() { + var _a; + await ((_a = iter.return) === null || _a === void 0 ? void 0 : _a.call(iter)); + }, + }); +} +/** + * Most browsers don't yet have async iterable support for ReadableStream, + * and Node has a very different way of reading bytes from its "ReadableStream". + * + * This polyfill was pulled from https://github.com/MattiasBuelens/web-streams-polyfill/pull/122#issuecomment-1627354490 + */ +function ReadableStreamToAsyncIterable(stream) { + if (stream[Symbol.asyncIterator]) + return stream; + const reader = stream.getReader(); + return { + async next() { + try { + const result = await reader.read(); + if (result === null || result === void 0 ? void 0 : result.done) + reader.releaseLock(); // release lock when stream becomes closed + return result; + } + catch (e) { + reader.releaseLock(); // release lock when stream becomes errored + throw e; + } + }, + async return() { + const cancelPromise = reader.cancel(); + reader.releaseLock(); + await cancelPromise; + return { done: true, value: undefined }; + }, + [Symbol.asyncIterator]() { + return this; + }, + }; +} +/** + * Cancels a ReadableStream we don't need to consume. + * See https://undici.nodejs.org/#/?id=garbage-collection + */ +async function CancelReadableStream(stream) { + var _a, _b; + if (stream === null || typeof stream !== 'object') + return; + if (stream[Symbol.asyncIterator]) { + await ((_b = (_a = stream[Symbol.asyncIterator]()).return) === null || _b === void 0 ? void 0 : _b.call(_a)); + return; + } + const reader = stream.getReader(); + const cancelPromise = reader.cancel(); + reader.releaseLock(); + await cancelPromise; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const FallbackEncoder = ({ headers, body }) => { + return { + bodyHeaders: { + 'content-type': 'application/json', + }, + body: JSON.stringify(body), + }; +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const checkFileSupport = () => { + var _a; + if (typeof File === 'undefined') { + const { process } = globalThis; + const isOldNode = typeof ((_a = process === null || process === void 0 ? void 0 : process.versions) === null || _a === void 0 ? void 0 : _a.node) === 'string' && parseInt(process.versions.node.split('.')) < 20; + throw new Error('`File` is not defined as a global, which is required for file uploads.' + + (isOldNode ? + " Update to Node 20 LTS or newer, or set `globalThis.File` to `import('node:buffer').File`." + : '')); + } +}; +/** + * Construct a `File` instance. This is used to ensure a helpful error is thrown + * for environments that don't define a global `File` yet. + */ +function makeFile(fileBits, fileName, options) { + checkFileSupport(); + return new File(fileBits, fileName !== null && fileName !== void 0 ? fileName : 'unknown_file', options); +} +function getName(value) { + return (((typeof value === 'object' && + value !== null && + (('name' in value && value.name && String(value.name)) || + ('url' in value && value.url && String(value.url)) || + ('filename' in value && value.filename && String(value.filename)) || + ('path' in value && value.path && String(value.path)))) || + '') + .split(/[\\/]/) + .pop() || undefined); +} +const isAsyncIterable = (value) => value != null && typeof value === 'object' && typeof value[Symbol.asyncIterator] === 'function'; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * This check adds the arrayBuffer() method type because it is available and used at runtime + */ +const isBlobLike = (value) => value != null && + typeof value === 'object' && + typeof value.size === 'number' && + typeof value.type === 'string' && + typeof value.text === 'function' && + typeof value.slice === 'function' && + typeof value.arrayBuffer === 'function'; +/** + * This check adds the arrayBuffer() method type because it is available and used at runtime + */ +const isFileLike = (value) => value != null && + typeof value === 'object' && + typeof value.name === 'string' && + typeof value.lastModified === 'number' && + isBlobLike(value); +const isResponseLike = (value) => value != null && + typeof value === 'object' && + typeof value.url === 'string' && + typeof value.blob === 'function'; +/** + * Helper for creating a {@link File} to pass to an SDK upload method from a variety of different data formats + * @param value the raw content of the file. Can be an {@link Uploadable}, BlobLikePart, or AsyncIterable of BlobLikeParts + * @param {string=} name the name of the file. If omitted, toFile will try to determine a file name from bits if possible + * @param {Object=} options additional properties + * @param {string=} options.type the MIME type of the content + * @param {number=} options.lastModified the last modified timestamp + * @returns a {@link File} with the given properties + */ +async function toFile(value, name, options) { + checkFileSupport(); + // If it's a promise, resolve it. + value = await value; + // If we've been given a `File` we don't need to do anything + if (isFileLike(value)) { + if (value instanceof File) { + return value; + } + return makeFile([await value.arrayBuffer()], value.name); + } + if (isResponseLike(value)) { + const blob = await value.blob(); + name || (name = new URL(value.url).pathname.split(/[\\/]/).pop()); + return makeFile(await getBytes(blob), name, options); + } + const parts = await getBytes(value); + name || (name = getName(value)); + if (!(options === null || options === void 0 ? void 0 : options.type)) { + const type = parts.find((part) => typeof part === 'object' && 'type' in part && part.type); + if (typeof type === 'string') { + options = Object.assign(Object.assign({}, options), { type }); + } + } + return makeFile(parts, name, options); +} +async function getBytes(value) { + var _a, e_1, _b, _c; + var _d; + let parts = []; + if (typeof value === 'string' || + ArrayBuffer.isView(value) || // includes Uint8Array, Buffer, etc. + value instanceof ArrayBuffer) { + parts.push(value); + } + else if (isBlobLike(value)) { + parts.push(value instanceof Blob ? value : await value.arrayBuffer()); + } + else if (isAsyncIterable(value) // includes Readable, ReadableStream, etc. + ) { + try { + for (var _e = true, value_1 = __asyncValues(value), value_1_1; value_1_1 = await value_1.next(), _a = value_1_1.done, !_a; _e = true) { + _c = value_1_1.value; + _e = false; + const chunk = _c; + parts.push(...(await getBytes(chunk))); // TODO, consider validating? + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (!_e && !_a && (_b = value_1.return)) await _b.call(value_1); + } + finally { if (e_1) throw e_1.error; } + } + } + else { + const constructor = (_d = value === null || value === void 0 ? void 0 : value.constructor) === null || _d === void 0 ? void 0 : _d.name; + throw new Error(`Unexpected data type: ${typeof value}${constructor ? `; constructor: ${constructor}` : ''}${propsForError(value)}`); + } + return parts; +} +function propsForError(value) { + if (typeof value !== 'object' || value === null) + return ''; + const props = Object.getOwnPropertyNames(value); + return `; props: [${props.map((p) => `"${p}"`).join(', ')}]`; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class APIResource { + constructor(client) { + this._client = client; + } +} +/** + * The key path from the client. For example, a resource accessible as `client.resource.subresource` would + * have a property `static override readonly _key = Object.freeze(['resource', 'subresource'] as const);`. + */ +APIResource._key = []; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Percent-encode everything that isn't safe to have in a path without encoding safe chars. + * + * Taken from https://datatracker.ietf.org/doc/html/rfc3986#section-3.3: + * > unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + * > sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" + * > pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + */ +function encodeURIPath(str) { + return str.replace(/[^A-Za-z0-9\-._~!$&'()*+,;=:@]+/g, encodeURIComponent); +} +const EMPTY = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.create(null)); +const createPathTagFunction = (pathEncoder = encodeURIPath) => (function path(statics, ...params) { + // If there are no params, no processing is needed. + if (statics.length === 1) + return statics[0]; + let postPath = false; + const invalidSegments = []; + const path = statics.reduce((previousValue, currentValue, index) => { + var _a, _b, _c; + if (/[?#]/.test(currentValue)) { + postPath = true; + } + const value = params[index]; + let encoded = (postPath ? encodeURIComponent : pathEncoder)('' + value); + if (index !== params.length && + (value == null || + (typeof value === 'object' && + // handle values from other realms + value.toString === + ((_c = Object.getPrototypeOf((_b = Object.getPrototypeOf((_a = value.hasOwnProperty) !== null && _a !== void 0 ? _a : EMPTY)) !== null && _b !== void 0 ? _b : EMPTY)) === null || _c === void 0 ? void 0 : _c.toString)))) { + encoded = value + ''; + invalidSegments.push({ + start: previousValue.length + currentValue.length, + length: encoded.length, + error: `Value of type ${Object.prototype.toString + .call(value) + .slice(8, -1)} is not a valid path parameter`, + }); + } + return previousValue + currentValue + (index === params.length ? '' : encoded); + }, ''); + const pathOnly = path.split(/[?#]/, 1)[0]; + const invalidSegmentPattern = /(?<=^|\/)(?:\.|%2e){1,2}(?=\/|$)/gi; + let match; + // Find all invalid segments + while ((match = invalidSegmentPattern.exec(pathOnly)) !== null) { + invalidSegments.push({ + start: match.index, + length: match[0].length, + error: `Value "${match[0]}" can\'t be safely passed as a path parameter`, + }); + } + invalidSegments.sort((a, b) => a.start - b.start); + if (invalidSegments.length > 0) { + let lastEnd = 0; + const underline = invalidSegments.reduce((acc, segment) => { + const spaces = ' '.repeat(segment.start - lastEnd); + const arrows = '^'.repeat(segment.length); + lastEnd = segment.start + segment.length; + return acc + spaces + arrows; + }, ''); + throw new GeminiNextGenAPIClientError(`Path parameters result in path with invalid segments:\n${invalidSegments + .map((e) => e.error) + .join('\n')}\n${path}\n${underline}`); + } + return path; +}); +/** + * URI-encodes path params and ensures no unsafe /./ or /../ path segments are introduced. + */ +const path = /* @__PURE__ */ createPathTagFunction(encodeURIPath); + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class BaseInteractions extends APIResource { + create(params, options) { + var _a; + const { api_version = this._client.apiVersion } = params, body = __rest(params, ["api_version"]); + if ('model' in body && 'agent_config' in body) { + throw new GeminiNextGenAPIClientError(`Invalid request: specified \`model\` and \`agent_config\`. If specifying \`model\`, use \`generation_config\`.`); + } + if ('agent' in body && 'generation_config' in body) { + throw new GeminiNextGenAPIClientError(`Invalid request: specified \`agent\` and \`generation_config\`. If specifying \`agent\`, use \`agent_config\`.`); + } + return this._client.post(path `/${api_version}/interactions`, Object.assign(Object.assign({ body }, options), { stream: (_a = params.stream) !== null && _a !== void 0 ? _a : false })); + } + /** + * Deletes the interaction by id. + * + * @example + * ```ts + * const interaction = await client.interactions.delete('id', { + * api_version: 'api_version', + * }); + * ``` + */ + delete(id, params = {}, options) { + const { api_version = this._client.apiVersion } = params !== null && params !== void 0 ? params : {}; + return this._client.delete(path `/${api_version}/interactions/${id}`, options); + } + /** + * Cancels an interaction by id. This only applies to background interactions that are still running. + * + * @example + * ```ts + * const interaction = await client.interactions.cancel('id', { + * api_version: 'api_version', + * }); + * ``` + */ + cancel(id, params = {}, options) { + const { api_version = this._client.apiVersion } = params !== null && params !== void 0 ? params : {}; + return this._client.post(path `/${api_version}/interactions/${id}/cancel`, options); + } + get(id, params = {}, options) { + var _a; + const _b = params !== null && params !== void 0 ? params : {}, { api_version = this._client.apiVersion } = _b, query = __rest(_b, ["api_version"]); + return this._client.get(path `/${api_version}/interactions/${id}`, Object.assign(Object.assign({ query }, options), { stream: (_a = params === null || params === void 0 ? void 0 : params.stream) !== null && _a !== void 0 ? _a : false })); + } +} +BaseInteractions._key = Object.freeze(['interactions']); +class Interactions extends BaseInteractions { +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function concatBytes(buffers) { + let length = 0; + for (const buffer of buffers) { + length += buffer.length; + } + const output = new Uint8Array(length); + let index = 0; + for (const buffer of buffers) { + output.set(buffer, index); + index += buffer.length; + } + return output; +} +let encodeUTF8_; +function encodeUTF8(str) { + let encoder; + return (encodeUTF8_ !== null && encodeUTF8_ !== void 0 ? encodeUTF8_ : ((encoder = new globalThis.TextEncoder()), (encodeUTF8_ = encoder.encode.bind(encoder))))(str); +} +let decodeUTF8_; +function decodeUTF8(bytes) { + let decoder; + return (decodeUTF8_ !== null && decodeUTF8_ !== void 0 ? decodeUTF8_ : ((decoder = new globalThis.TextDecoder()), (decodeUTF8_ = decoder.decode.bind(decoder))))(bytes); +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * A re-implementation of httpx's `LineDecoder` in Python that handles incrementally + * reading lines from text. + * + * https://github.com/encode/httpx/blob/920333ea98118e9cf617f246905d7b202510941c/httpx/_decoders.py#L258 + */ +class LineDecoder { + constructor() { + this.buffer = new Uint8Array(); + this.carriageReturnIndex = null; + } + decode(chunk) { + if (chunk == null) { + return []; + } + const binaryChunk = chunk instanceof ArrayBuffer ? new Uint8Array(chunk) + : typeof chunk === 'string' ? encodeUTF8(chunk) + : chunk; + this.buffer = concatBytes([this.buffer, binaryChunk]); + const lines = []; + let patternIndex; + while ((patternIndex = findNewlineIndex(this.buffer, this.carriageReturnIndex)) != null) { + if (patternIndex.carriage && this.carriageReturnIndex == null) { + // skip until we either get a corresponding `\n`, a new `\r` or nothing + this.carriageReturnIndex = patternIndex.index; + continue; + } + // we got double \r or \rtext\n + if (this.carriageReturnIndex != null && + (patternIndex.index !== this.carriageReturnIndex + 1 || patternIndex.carriage)) { + lines.push(decodeUTF8(this.buffer.subarray(0, this.carriageReturnIndex - 1))); + this.buffer = this.buffer.subarray(this.carriageReturnIndex); + this.carriageReturnIndex = null; + continue; + } + const endIndex = this.carriageReturnIndex !== null ? patternIndex.preceding - 1 : patternIndex.preceding; + const line = decodeUTF8(this.buffer.subarray(0, endIndex)); + lines.push(line); + this.buffer = this.buffer.subarray(patternIndex.index); + this.carriageReturnIndex = null; + } + return lines; + } + flush() { + if (!this.buffer.length) { + return []; + } + return this.decode('\n'); + } +} +// prettier-ignore +LineDecoder.NEWLINE_CHARS = new Set(['\n', '\r']); +LineDecoder.NEWLINE_REGEXP = /\r\n|[\n\r]/g; +/** + * This function searches the buffer for the end patterns, (\r or \n) + * and returns an object with the index preceding the matched newline and the + * index after the newline char. `null` is returned if no new line is found. + * + * ```ts + * findNewLineIndex('abc\ndef') -> { preceding: 2, index: 3 } + * ``` + */ +function findNewlineIndex(buffer, startIndex) { + const newline = 0x0a; // \n + const carriage = 0x0d; // \r + for (let i = startIndex !== null && startIndex !== void 0 ? startIndex : 0; i < buffer.length; i++) { + if (buffer[i] === newline) { + return { preceding: i, index: i + 1, carriage: false }; + } + if (buffer[i] === carriage) { + return { preceding: i, index: i + 1, carriage: true }; + } + } + return null; +} +function findDoubleNewlineIndex(buffer) { + // This function searches the buffer for the end patterns (\r\r, \n\n, \r\n\r\n) + // and returns the index right after the first occurrence of any pattern, + // or -1 if none of the patterns are found. + const newline = 0x0a; // \n + const carriage = 0x0d; // \r + for (let i = 0; i < buffer.length - 1; i++) { + if (buffer[i] === newline && buffer[i + 1] === newline) { + // \n\n + return i + 2; + } + if (buffer[i] === carriage && buffer[i + 1] === carriage) { + // \r\r + return i + 2; + } + if (buffer[i] === carriage && + buffer[i + 1] === newline && + i + 3 < buffer.length && + buffer[i + 2] === carriage && + buffer[i + 3] === newline) { + // \r\n\r\n + return i + 4; + } + } + return -1; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +const levelNumbers = { + off: 0, + error: 200, + warn: 300, + info: 400, + debug: 500, +}; +const parseLogLevel = (maybeLevel, sourceName, client) => { + if (!maybeLevel) { + return undefined; + } + if (hasOwn(levelNumbers, maybeLevel)) { + return maybeLevel; + } + loggerFor(client).warn(`${sourceName} was set to ${JSON.stringify(maybeLevel)}, expected one of ${JSON.stringify(Object.keys(levelNumbers))}`); + return undefined; +}; +function noop() { } +function makeLogFn(fnLevel, logger, logLevel) { + if (!logger || levelNumbers[fnLevel] > levelNumbers[logLevel]) { + return noop; + } + else { + // Don't wrap logger functions, we want the stacktrace intact! + return logger[fnLevel].bind(logger); + } +} +const noopLogger = { + error: noop, + warn: noop, + info: noop, + debug: noop, +}; +let cachedLoggers = /* @__PURE__ */ new WeakMap(); +function loggerFor(client) { + var _a; + const logger = client.logger; + const logLevel = (_a = client.logLevel) !== null && _a !== void 0 ? _a : 'off'; + if (!logger) { + return noopLogger; + } + const cachedLogger = cachedLoggers.get(logger); + if (cachedLogger && cachedLogger[0] === logLevel) { + return cachedLogger[1]; + } + const levelLogger = { + error: makeLogFn('error', logger, logLevel), + warn: makeLogFn('warn', logger, logLevel), + info: makeLogFn('info', logger, logLevel), + debug: makeLogFn('debug', logger, logLevel), + }; + cachedLoggers.set(logger, [logLevel, levelLogger]); + return levelLogger; +} +const formatRequestDetails = (details) => { + if (details.options) { + details.options = Object.assign({}, details.options); + delete details.options['headers']; // redundant + leaks internals + } + if (details.headers) { + details.headers = Object.fromEntries((details.headers instanceof Headers ? [...details.headers] : Object.entries(details.headers)).map(([name, value]) => [ + name, + (name.toLowerCase() === 'x-goog-api-key' || + name.toLowerCase() === 'authorization' || + name.toLowerCase() === 'cookie' || + name.toLowerCase() === 'set-cookie') ? + '***' + : value, + ])); + } + if ('retryOfRequestLogID' in details) { + if (details.retryOfRequestLogID) { + details.retryOf = details.retryOfRequestLogID; + } + delete details.retryOfRequestLogID; + } + return details; +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Stream { + constructor(iterator, controller, client) { + this.iterator = iterator; + this.controller = controller; + this.client = client; + } + static fromSSEResponse(response, controller, client) { + let consumed = false; + const logger = client ? loggerFor(client) : console; + function iterator() { + return __asyncGenerator(this, arguments, function* iterator_1() { + var _a, e_1, _b, _c; + if (consumed) { + throw new GeminiNextGenAPIClientError('Cannot iterate over a consumed stream, use `.tee()` to split the stream.'); + } + consumed = true; + let done = false; + try { + try { + for (var _d = true, _e = __asyncValues(_iterSSEMessages(response, controller)), _f; _f = yield __await(_e.next()), _a = _f.done, !_a; _d = true) { + _c = _f.value; + _d = false; + const sse = _c; + if (done) + continue; + if (sse.data.startsWith('[DONE]')) { + done = true; + continue; + } + else { + try { + // @ts-ignore + yield yield __await(JSON.parse(sse.data)); + } + catch (e) { + logger.error(`Could not parse message into JSON:`, sse.data); + logger.error(`From chunk:`, sse.raw); + throw e; + } + } + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (!_d && !_a && (_b = _e.return)) yield __await(_b.call(_e)); + } + finally { if (e_1) throw e_1.error; } + } + done = true; + } + catch (e) { + // If the user calls `stream.controller.abort()`, we should exit without throwing. + if (isAbortError(e)) + return yield __await(void 0); + throw e; + } + finally { + // If the user `break`s, abort the ongoing request. + if (!done) + controller.abort(); + } + }); + } + return new Stream(iterator, controller, client); + } + /** + * Generates a Stream from a newline-separated ReadableStream + * where each item is a JSON value. + */ + static fromReadableStream(readableStream, controller, client) { + let consumed = false; + function iterLines() { + return __asyncGenerator(this, arguments, function* iterLines_1() { + var _a, e_2, _b, _c; + const lineDecoder = new LineDecoder(); + const iter = ReadableStreamToAsyncIterable(readableStream); + try { + for (var _d = true, iter_1 = __asyncValues(iter), iter_1_1; iter_1_1 = yield __await(iter_1.next()), _a = iter_1_1.done, !_a; _d = true) { + _c = iter_1_1.value; + _d = false; + const chunk = _c; + for (const line of lineDecoder.decode(chunk)) { + yield yield __await(line); + } + } + } + catch (e_2_1) { e_2 = { error: e_2_1 }; } + finally { + try { + if (!_d && !_a && (_b = iter_1.return)) yield __await(_b.call(iter_1)); + } + finally { if (e_2) throw e_2.error; } + } + for (const line of lineDecoder.flush()) { + yield yield __await(line); + } + }); + } + function iterator() { + return __asyncGenerator(this, arguments, function* iterator_2() { + var _a, e_3, _b, _c; + if (consumed) { + throw new GeminiNextGenAPIClientError('Cannot iterate over a consumed stream, use `.tee()` to split the stream.'); + } + consumed = true; + let done = false; + try { + try { + for (var _d = true, _e = __asyncValues(iterLines()), _f; _f = yield __await(_e.next()), _a = _f.done, !_a; _d = true) { + _c = _f.value; + _d = false; + const line = _c; + if (done) + continue; + // @ts-ignore + if (line) + yield yield __await(JSON.parse(line)); + } + } + catch (e_3_1) { e_3 = { error: e_3_1 }; } + finally { + try { + if (!_d && !_a && (_b = _e.return)) yield __await(_b.call(_e)); + } + finally { if (e_3) throw e_3.error; } + } + done = true; + } + catch (e) { + // If the user calls `stream.controller.abort()`, we should exit without throwing. + if (isAbortError(e)) + return yield __await(void 0); + throw e; + } + finally { + // If the user `break`s, abort the ongoing request. + if (!done) + controller.abort(); + } + }); + } + return new Stream(iterator, controller, client); + } + [Symbol.asyncIterator]() { + return this.iterator(); + } + /** + * Splits the stream into two streams which can be + * independently read from at different speeds. + */ + tee() { + const left = []; + const right = []; + const iterator = this.iterator(); + const teeIterator = (queue) => { + return { + next: () => { + if (queue.length === 0) { + const result = iterator.next(); + left.push(result); + right.push(result); + } + return queue.shift(); + }, + }; + }; + return [ + new Stream(() => teeIterator(left), this.controller, this.client), + new Stream(() => teeIterator(right), this.controller, this.client), + ]; + } + /** + * Converts this stream to a newline-separated ReadableStream of + * JSON stringified values in the stream + * which can be turned back into a Stream with `Stream.fromReadableStream()`. + */ + toReadableStream() { + const self = this; + let iter; + return makeReadableStream({ + async start() { + iter = self[Symbol.asyncIterator](); + }, + async pull(ctrl) { + try { + const { value, done } = await iter.next(); + if (done) + return ctrl.close(); + const bytes = encodeUTF8(JSON.stringify(value) + '\n'); + ctrl.enqueue(bytes); + } + catch (err) { + ctrl.error(err); + } + }, + async cancel() { + var _a; + await ((_a = iter.return) === null || _a === void 0 ? void 0 : _a.call(iter)); + }, + }); + } +} +function _iterSSEMessages(response, controller) { + return __asyncGenerator(this, arguments, function* _iterSSEMessages_1() { + var _a, e_4, _b, _c; + if (!response.body) { + controller.abort(); + if (typeof globalThis.navigator !== 'undefined' && + globalThis.navigator.product === 'ReactNative') { + throw new GeminiNextGenAPIClientError(`The default react-native fetch implementation does not support streaming. Please use expo/fetch: https://docs.expo.dev/versions/latest/sdk/expo/#expofetch-api`); + } + throw new GeminiNextGenAPIClientError(`Attempted to iterate over a response with no body`); + } + const sseDecoder = new SSEDecoder(); + const lineDecoder = new LineDecoder(); + const iter = ReadableStreamToAsyncIterable(response.body); + try { + for (var _d = true, _e = __asyncValues(iterSSEChunks(iter)), _f; _f = yield __await(_e.next()), _a = _f.done, !_a; _d = true) { + _c = _f.value; + _d = false; + const sseChunk = _c; + for (const line of lineDecoder.decode(sseChunk)) { + const sse = sseDecoder.decode(line); + if (sse) + yield yield __await(sse); + } + } + } + catch (e_4_1) { e_4 = { error: e_4_1 }; } + finally { + try { + if (!_d && !_a && (_b = _e.return)) yield __await(_b.call(_e)); + } + finally { if (e_4) throw e_4.error; } + } + for (const line of lineDecoder.flush()) { + const sse = sseDecoder.decode(line); + if (sse) + yield yield __await(sse); + } + }); +} +/** + * Given an async iterable iterator, iterates over it and yields full + * SSE chunks, i.e. yields when a double new-line is encountered. + */ +function iterSSEChunks(iterator) { + return __asyncGenerator(this, arguments, function* iterSSEChunks_1() { + var _a, e_5, _b, _c; + let data = new Uint8Array(); + try { + for (var _d = true, iterator_3 = __asyncValues(iterator), iterator_3_1; iterator_3_1 = yield __await(iterator_3.next()), _a = iterator_3_1.done, !_a; _d = true) { + _c = iterator_3_1.value; + _d = false; + const chunk = _c; + if (chunk == null) { + continue; + } + const binaryChunk = chunk instanceof ArrayBuffer ? new Uint8Array(chunk) + : typeof chunk === 'string' ? encodeUTF8(chunk) + : chunk; + let newData = new Uint8Array(data.length + binaryChunk.length); + newData.set(data); + newData.set(binaryChunk, data.length); + data = newData; + let patternIndex; + while ((patternIndex = findDoubleNewlineIndex(data)) !== -1) { + yield yield __await(data.slice(0, patternIndex)); + data = data.slice(patternIndex); + } + } + } + catch (e_5_1) { e_5 = { error: e_5_1 }; } + finally { + try { + if (!_d && !_a && (_b = iterator_3.return)) yield __await(_b.call(iterator_3)); + } + finally { if (e_5) throw e_5.error; } + } + if (data.length > 0) { + yield yield __await(data); + } + }); +} +class SSEDecoder { + constructor() { + this.event = null; + this.data = []; + this.chunks = []; + } + decode(line) { + if (line.endsWith('\r')) { + line = line.substring(0, line.length - 1); + } + if (!line) { + // empty line and we didn't previously encounter any messages + if (!this.event && !this.data.length) + return null; + const sse = { + event: this.event, + data: this.data.join('\n'), + raw: this.chunks, + }; + this.event = null; + this.data = []; + this.chunks = []; + return sse; + } + this.chunks.push(line); + if (line.startsWith(':')) { + return null; + } + let [fieldname, _, value] = partition(line, ':'); + if (value.startsWith(' ')) { + value = value.substring(1); + } + if (fieldname === 'event') { + this.event = value; + } + else if (fieldname === 'data') { + this.data.push(value); + } + return null; + } +} +function partition(str, delimiter) { + const index = str.indexOf(delimiter); + if (index !== -1) { + return [str.substring(0, index), delimiter, str.substring(index + delimiter.length)]; + } + return [str, '', '']; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +async function defaultParseResponse(client, props) { + const { response, requestLogID, retryOfRequestLogID, startTime } = props; + const body = await (async () => { + var _a; + if (props.options.stream) { + loggerFor(client).debug('response', response.status, response.url, response.headers, response.body); + // Note: there is an invariant here that isn't represented in the type system + // that if you set `stream: true` the response type must also be `Stream<T>` + if (props.options.__streamClass) { + return props.options.__streamClass.fromSSEResponse(response, props.controller, client); + } + return Stream.fromSSEResponse(response, props.controller, client); + } + // fetch refuses to read the body when the status code is 204. + if (response.status === 204) { + return null; + } + if (props.options.__binaryResponse) { + return response; + } + const contentType = response.headers.get('content-type'); + const mediaType = (_a = contentType === null || contentType === void 0 ? void 0 : contentType.split(';')[0]) === null || _a === void 0 ? void 0 : _a.trim(); + const isJSON = (mediaType === null || mediaType === void 0 ? void 0 : mediaType.includes('application/json')) || (mediaType === null || mediaType === void 0 ? void 0 : mediaType.endsWith('+json')); + if (isJSON) { + const contentLength = response.headers.get('content-length'); + if (contentLength === '0') { + // if there is no content we can't do anything + return undefined; + } + const json = await response.json(); + return json; + } + const text = await response.text(); + return text; + })(); + loggerFor(client).debug(`[${requestLogID}] response parsed`, formatRequestDetails({ + retryOfRequestLogID, + url: response.url, + status: response.status, + body, + durationMs: Date.now() - startTime, + })); + return body; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * A subclass of `Promise` providing additional helper methods + * for interacting with the SDK. + */ +class APIPromise extends Promise { + constructor(client, responsePromise, parseResponse = defaultParseResponse) { + super((resolve) => { + // this is maybe a bit weird but this has to be a no-op to not implicitly + // parse the response body; instead .then, .catch, .finally are overridden + // to parse the response + resolve(null); + }); + this.responsePromise = responsePromise; + this.parseResponse = parseResponse; + this.client = client; + } + _thenUnwrap(transform) { + return new APIPromise(this.client, this.responsePromise, async (client, props) => transform(await this.parseResponse(client, props), props)); + } + /** + * Gets the raw `Response` instance instead of parsing the response + * data. + * + * If you want to parse the response body but still get the `Response` + * instance, you can use {@link withResponse()}. + * + * 👋 Getting the wrong TypeScript type for `Response`? + * Try setting `"moduleResolution": "NodeNext"` or add `"lib": ["DOM"]` + * to your `tsconfig.json`. + */ + asResponse() { + return this.responsePromise.then((p) => p.response); + } + /** + * Gets the parsed response data and the raw `Response` instance. + * + * If you just want to get the raw `Response` instance without parsing it, + * you can use {@link asResponse()}. + * + * 👋 Getting the wrong TypeScript type for `Response`? + * Try setting `"moduleResolution": "NodeNext"` or add `"lib": ["DOM"]` + * to your `tsconfig.json`. + */ + async withResponse() { + const [data, response] = await Promise.all([this.parse(), this.asResponse()]); + return { data, response }; + } + parse() { + if (!this.parsedPromise) { + this.parsedPromise = this.responsePromise.then((data) => this.parseResponse(this.client, data)); + } + return this.parsedPromise; + } + then(onfulfilled, onrejected) { + return this.parse().then(onfulfilled, onrejected); + } + catch(onrejected) { + return this.parse().catch(onrejected); + } + finally(onfinally) { + return this.parse().finally(onfinally); + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +const brand_privateNullableHeaders = /* @__PURE__ */ Symbol('brand.privateNullableHeaders'); +function* iterateHeaders(headers) { + if (!headers) + return; + if (brand_privateNullableHeaders in headers) { + const { values, nulls } = headers; + yield* values.entries(); + for (const name of nulls) { + yield [name, null]; + } + return; + } + let shouldClear = false; + let iter; + if (headers instanceof Headers) { + iter = headers.entries(); + } + else if (isReadonlyArray(headers)) { + iter = headers; + } + else { + shouldClear = true; + iter = Object.entries(headers !== null && headers !== void 0 ? headers : {}); + } + for (let row of iter) { + const name = row[0]; + if (typeof name !== 'string') + throw new TypeError('expected header name to be a string'); + const values = isReadonlyArray(row[1]) ? row[1] : [row[1]]; + let didClear = false; + for (const value of values) { + if (value === undefined) + continue; + // Objects keys always overwrite older headers, they never append. + // Yield a null to clear the header before adding the new values. + if (shouldClear && !didClear) { + didClear = true; + yield [name, null]; + } + yield [name, value]; + } + } +} +const buildHeaders = (newHeaders) => { + const targetHeaders = new Headers(); + const nullHeaders = new Set(); + for (const headers of newHeaders) { + const seenHeaders = new Set(); + for (const [name, value] of iterateHeaders(headers)) { + const lowerName = name.toLowerCase(); + if (!seenHeaders.has(lowerName)) { + targetHeaders.delete(name); + seenHeaders.add(lowerName); + } + if (value === null) { + targetHeaders.delete(name); + nullHeaders.add(lowerName); + } + else { + targetHeaders.append(name, value); + nullHeaders.delete(lowerName); + } + } + } + return { [brand_privateNullableHeaders]: true, values: targetHeaders, nulls: nullHeaders }; +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +/** + * Read an environment variable. + * + * Trims beginning and trailing whitespace. + * + * Will return undefined if the environment variable doesn't exist or cannot be accessed. + */ +const readEnv = (env) => { + var _a, _b, _c, _d, _e, _f; + if (typeof globalThis.process !== 'undefined') { + return (_c = (_b = (_a = globalThis.process.env) === null || _a === void 0 ? void 0 : _a[env]) === null || _b === void 0 ? void 0 : _b.trim()) !== null && _c !== void 0 ? _c : undefined; + } + if (typeof globalThis.Deno !== 'undefined') { + return (_f = (_e = (_d = globalThis.Deno.env) === null || _d === void 0 ? void 0 : _d.get) === null || _e === void 0 ? void 0 : _e.call(_d, env)) === null || _f === void 0 ? void 0 : _f.trim(); + } + return undefined; +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +var _a; +/** + * Base class for Gemini Next Gen API API clients. + */ +class BaseGeminiNextGenAPIClient { + /** + * API Client for interfacing with the Gemini Next Gen API API. + * + * @param {string | null | undefined} [opts.apiKey=process.env['GEMINI_API_KEY'] ?? null] + * @param {string | undefined} [opts.apiVersion=v1beta] + * @param {string} [opts.baseURL=process.env['GEMINI_NEXT_GEN_API_BASE_URL'] ?? https://generativelanguage.googleapis.com] - Override the default base URL for the API. + * @param {number} [opts.timeout=1 minute] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out. + * @param {MergedRequestInit} [opts.fetchOptions] - Additional `RequestInit` options to be passed to `fetch` calls. + * @param {Fetch} [opts.fetch] - Specify a custom `fetch` function implementation. + * @param {number} [opts.maxRetries=2] - The maximum number of times the client will retry a request. + * @param {HeadersLike} opts.defaultHeaders - Default headers to include with every request to the API. + * @param {Record<string, string | undefined>} opts.defaultQuery - Default query parameters to include with every request to the API. + */ + constructor(_b) { + var _c, _d, _e, _f, _g, _h, _j; + var { baseURL = readEnv('GEMINI_NEXT_GEN_API_BASE_URL'), apiKey = (_c = readEnv('GEMINI_API_KEY')) !== null && _c !== void 0 ? _c : null, apiVersion = 'v1beta' } = _b, opts = __rest(_b, ["baseURL", "apiKey", "apiVersion"]); + const options = Object.assign(Object.assign({ apiKey, + apiVersion }, opts), { baseURL: baseURL || `https://generativelanguage.googleapis.com` }); + this.baseURL = options.baseURL; + this.timeout = (_d = options.timeout) !== null && _d !== void 0 ? _d : BaseGeminiNextGenAPIClient.DEFAULT_TIMEOUT /* 1 minute */; + this.logger = (_e = options.logger) !== null && _e !== void 0 ? _e : console; + const defaultLogLevel = 'warn'; + // Set default logLevel early so that we can log a warning in parseLogLevel. + this.logLevel = defaultLogLevel; + this.logLevel = + (_g = (_f = parseLogLevel(options.logLevel, 'ClientOptions.logLevel', this)) !== null && _f !== void 0 ? _f : parseLogLevel(readEnv('GEMINI_NEXT_GEN_API_LOG'), "process.env['GEMINI_NEXT_GEN_API_LOG']", this)) !== null && _g !== void 0 ? _g : defaultLogLevel; + this.fetchOptions = options.fetchOptions; + this.maxRetries = (_h = options.maxRetries) !== null && _h !== void 0 ? _h : 2; + this.fetch = (_j = options.fetch) !== null && _j !== void 0 ? _j : getDefaultFetch(); + this.encoder = FallbackEncoder; + this._options = options; + this.apiKey = apiKey; + this.apiVersion = apiVersion; + this.clientAdapter = options.clientAdapter; + } + /** + * Create a new client instance re-using the same options given to the current client with optional overriding. + */ + withOptions(options) { + const client = new this.constructor(Object.assign(Object.assign(Object.assign({}, this._options), { baseURL: this.baseURL, maxRetries: this.maxRetries, timeout: this.timeout, logger: this.logger, logLevel: this.logLevel, fetch: this.fetch, fetchOptions: this.fetchOptions, apiKey: this.apiKey, apiVersion: this.apiVersion }), options)); + return client; + } + /** + * Check whether the base URL is set to its default. + */ + baseURLOverridden() { + return this.baseURL !== 'https://generativelanguage.googleapis.com'; + } + defaultQuery() { + return this._options.defaultQuery; + } + validateHeaders({ values, nulls }) { + // The headers object handles case insensitivity. + if (values.has('authorization') || values.has('x-goog-api-key')) { + return; + } + if (this.apiKey && values.get('x-goog-api-key')) { + return; + } + if (nulls.has('x-goog-api-key')) { + return; + } + throw new Error('Could not resolve authentication method. Expected the apiKey to be set. Or for the "x-goog-api-key" headers to be explicitly omitted'); + } + async authHeaders(opts) { + const existingHeaders = buildHeaders([opts.headers]); + if (existingHeaders.values.has('authorization') || existingHeaders.values.has('x-goog-api-key')) { + return undefined; + } + if (this.apiKey) { + return buildHeaders([{ 'x-goog-api-key': this.apiKey }]); + } + if (this.clientAdapter.isVertexAI()) { + return buildHeaders([await this.clientAdapter.getAuthHeaders()]); + } + return undefined; + } + /** + * Basic re-implementation of `qs.stringify` for primitive types. + */ + stringifyQuery(query) { + return Object.entries(query) + .filter(([_, value]) => typeof value !== 'undefined') + .map(([key, value]) => { + if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { + return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`; + } + if (value === null) { + return `${encodeURIComponent(key)}=`; + } + throw new GeminiNextGenAPIClientError(`Cannot stringify type ${typeof value}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`); + }) + .join('&'); + } + getUserAgent() { + return `${this.constructor.name}/JS ${VERSION}`; + } + defaultIdempotencyKey() { + return `stainless-node-retry-${uuid4()}`; + } + makeStatusError(status, error, message, headers) { + return APIError.generate(status, error, message, headers); + } + buildURL(path, query, defaultBaseURL) { + const baseURL = (!this.baseURLOverridden() && defaultBaseURL) || this.baseURL; + const url = isAbsoluteURL(path) ? + new URL(path) + : new URL(baseURL + (baseURL.endsWith('/') && path.startsWith('/') ? path.slice(1) : path)); + const defaultQuery = this.defaultQuery(); + if (!isEmptyObj(defaultQuery)) { + query = Object.assign(Object.assign({}, defaultQuery), query); + } + if (typeof query === 'object' && query && !Array.isArray(query)) { + url.search = this.stringifyQuery(query); + } + return url.toString(); + } + /** + * Used as a callback for mutating the given `FinalRequestOptions` object. + + */ + async prepareOptions(options) { + if (this.clientAdapter && + this.clientAdapter.isVertexAI() && + !options.path.startsWith(`/${this.apiVersion}/projects/`)) { + const oldPath = options.path.slice(this.apiVersion.length + 1); + options.path = `/${this.apiVersion}/projects/${this.clientAdapter.getProject()}/locations/${this.clientAdapter.getLocation()}${oldPath}`; + } + } + /** + * Used as a callback for mutating the given `RequestInit` object. + * + * This is useful for cases where you want to add certain headers based off of + * the request properties, e.g. `method` or `url`. + */ + async prepareRequest(request, { url, options }) { } + get(path, opts) { + return this.methodRequest('get', path, opts); + } + post(path, opts) { + return this.methodRequest('post', path, opts); + } + patch(path, opts) { + return this.methodRequest('patch', path, opts); + } + put(path, opts) { + return this.methodRequest('put', path, opts); + } + delete(path, opts) { + return this.methodRequest('delete', path, opts); + } + methodRequest(method, path, opts) { + return this.request(Promise.resolve(opts).then((opts) => { + return Object.assign({ method, path }, opts); + })); + } + request(options, remainingRetries = null) { + return new APIPromise(this, this.makeRequest(options, remainingRetries, undefined)); + } + async makeRequest(optionsInput, retriesRemaining, retryOfRequestLogID) { + var _b, _c, _d; + const options = await optionsInput; + const maxRetries = (_b = options.maxRetries) !== null && _b !== void 0 ? _b : this.maxRetries; + if (retriesRemaining == null) { + retriesRemaining = maxRetries; + } + await this.prepareOptions(options); + const { req, url, timeout } = await this.buildRequest(options, { + retryCount: maxRetries - retriesRemaining, + }); + await this.prepareRequest(req, { url, options }); + /** Not an API request ID, just for correlating local log entries. */ + const requestLogID = 'log_' + ((Math.random() * (1 << 24)) | 0).toString(16).padStart(6, '0'); + const retryLogStr = retryOfRequestLogID === undefined ? '' : `, retryOf: ${retryOfRequestLogID}`; + const startTime = Date.now(); + loggerFor(this).debug(`[${requestLogID}] sending request`, formatRequestDetails({ + retryOfRequestLogID, + method: options.method, + url, + options, + headers: req.headers, + })); + if ((_c = options.signal) === null || _c === void 0 ? void 0 : _c.aborted) { + throw new APIUserAbortError(); + } + const controller = new AbortController(); + const response = await this.fetchWithTimeout(url, req, timeout, controller).catch(castToError); + const headersTime = Date.now(); + if (response instanceof globalThis.Error) { + const retryMessage = `retrying, ${retriesRemaining} attempts remaining`; + if ((_d = options.signal) === null || _d === void 0 ? void 0 : _d.aborted) { + throw new APIUserAbortError(); + } + // detect native connection timeout errors + // deno throws "TypeError: error sending request for url (https://example/): client error (Connect): tcp connect error: Operation timed out (os error 60): Operation timed out (os error 60)" + // undici throws "TypeError: fetch failed" with cause "ConnectTimeoutError: Connect Timeout Error (attempted address: example:443, timeout: 1ms)" + // others do not provide enough information to distinguish timeouts from other connection errors + const isTimeout = isAbortError(response) || + /timed? ?out/i.test(String(response) + ('cause' in response ? String(response.cause) : '')); + if (retriesRemaining) { + loggerFor(this).info(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - ${retryMessage}`); + loggerFor(this).debug(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (${retryMessage})`, formatRequestDetails({ + retryOfRequestLogID, + url, + durationMs: headersTime - startTime, + message: response.message, + })); + return this.retryRequest(options, retriesRemaining, retryOfRequestLogID !== null && retryOfRequestLogID !== void 0 ? retryOfRequestLogID : requestLogID); + } + loggerFor(this).info(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - error; no more retries left`); + loggerFor(this).debug(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (error; no more retries left)`, formatRequestDetails({ + retryOfRequestLogID, + url, + durationMs: headersTime - startTime, + message: response.message, + })); + if (isTimeout) { + throw new APIConnectionTimeoutError(); + } + throw new APIConnectionError({ cause: response }); + } + const responseInfo = `[${requestLogID}${retryLogStr}] ${req.method} ${url} ${response.ok ? 'succeeded' : 'failed'} with status ${response.status} in ${headersTime - startTime}ms`; + if (!response.ok) { + const shouldRetry = await this.shouldRetry(response); + if (retriesRemaining && shouldRetry) { + const retryMessage = `retrying, ${retriesRemaining} attempts remaining`; + // We don't need the body of this response. + await CancelReadableStream(response.body); + loggerFor(this).info(`${responseInfo} - ${retryMessage}`); + loggerFor(this).debug(`[${requestLogID}] response error (${retryMessage})`, formatRequestDetails({ + retryOfRequestLogID, + url: response.url, + status: response.status, + headers: response.headers, + durationMs: headersTime - startTime, + })); + return this.retryRequest(options, retriesRemaining, retryOfRequestLogID !== null && retryOfRequestLogID !== void 0 ? retryOfRequestLogID : requestLogID, response.headers); + } + const retryMessage = shouldRetry ? `error; no more retries left` : `error; not retryable`; + loggerFor(this).info(`${responseInfo} - ${retryMessage}`); + const errText = await response.text().catch((err) => castToError(err).message); + const errJSON = safeJSON(errText); + const errMessage = errJSON ? undefined : errText; + loggerFor(this).debug(`[${requestLogID}] response error (${retryMessage})`, formatRequestDetails({ + retryOfRequestLogID, + url: response.url, + status: response.status, + headers: response.headers, + message: errMessage, + durationMs: Date.now() - startTime, + })); + // @ts-ignore + const err = this.makeStatusError(response.status, errJSON, errMessage, response.headers); + throw err; + } + loggerFor(this).info(responseInfo); + loggerFor(this).debug(`[${requestLogID}] response start`, formatRequestDetails({ + retryOfRequestLogID, + url: response.url, + status: response.status, + headers: response.headers, + durationMs: headersTime - startTime, + })); + return { response, options, controller, requestLogID, retryOfRequestLogID, startTime }; + } + async fetchWithTimeout(url, init, ms, controller) { + const _b = init || {}, { signal, method } = _b, options = __rest(_b, ["signal", "method"]); + const abort = this._makeAbort(controller); + if (signal) + signal.addEventListener('abort', abort, { once: true }); + const timeout = setTimeout(abort, ms); + const isReadableBody = (globalThis.ReadableStream && options.body instanceof globalThis.ReadableStream) || + (typeof options.body === 'object' && options.body !== null && Symbol.asyncIterator in options.body); + const fetchOptions = Object.assign(Object.assign(Object.assign({ signal: controller.signal }, (isReadableBody ? { duplex: 'half' } : {})), { method: 'GET' }), options); + if (method) { + // Custom methods like 'patch' need to be uppercased + // See https://github.com/nodejs/undici/issues/2294 + fetchOptions.method = method.toUpperCase(); + } + try { + // use undefined this binding; fetch errors if bound to something else in browser/cloudflare + return await this.fetch.call(undefined, url, fetchOptions); + } + finally { + clearTimeout(timeout); + } + } + async shouldRetry(response) { + // Note this is not a standard header. + const shouldRetryHeader = response.headers.get('x-should-retry'); + // If the server explicitly says whether or not to retry, obey. + if (shouldRetryHeader === 'true') + return true; + if (shouldRetryHeader === 'false') + return false; + // Retry on request timeouts. + if (response.status === 408) + return true; + // Retry on lock timeouts. + if (response.status === 409) + return true; + // Retry on rate limits. + if (response.status === 429) + return true; + // Retry internal errors. + if (response.status >= 500) + return true; + return false; + } + async retryRequest(options, retriesRemaining, requestLogID, responseHeaders) { + var _b; + let timeoutMillis; + // Note the `retry-after-ms` header may not be standard, but is a good idea and we'd like proactive support for it. + const retryAfterMillisHeader = responseHeaders === null || responseHeaders === void 0 ? void 0 : responseHeaders.get('retry-after-ms'); + if (retryAfterMillisHeader) { + const timeoutMs = parseFloat(retryAfterMillisHeader); + if (!Number.isNaN(timeoutMs)) { + timeoutMillis = timeoutMs; + } + } + // About the Retry-After header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After + const retryAfterHeader = responseHeaders === null || responseHeaders === void 0 ? void 0 : responseHeaders.get('retry-after'); + if (retryAfterHeader && !timeoutMillis) { + const timeoutSeconds = parseFloat(retryAfterHeader); + if (!Number.isNaN(timeoutSeconds)) { + timeoutMillis = timeoutSeconds * 1000; + } + else { + timeoutMillis = Date.parse(retryAfterHeader) - Date.now(); + } + } + // If the API asks us to wait a certain amount of time (and it's a reasonable amount), + // just do what it says, but otherwise calculate a default + if (!(timeoutMillis && 0 <= timeoutMillis && timeoutMillis < 60 * 1000)) { + const maxRetries = (_b = options.maxRetries) !== null && _b !== void 0 ? _b : this.maxRetries; + timeoutMillis = this.calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries); + } + await sleep(timeoutMillis); + return this.makeRequest(options, retriesRemaining - 1, requestLogID); + } + calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries) { + const initialRetryDelay = 0.5; + const maxRetryDelay = 8.0; + const numRetries = maxRetries - retriesRemaining; + // Apply exponential backoff, but not more than the max. + const sleepSeconds = Math.min(initialRetryDelay * Math.pow(2, numRetries), maxRetryDelay); + // Apply some jitter, take up to at most 25 percent of the retry time. + const jitter = 1 - Math.random() * 0.25; + return sleepSeconds * jitter * 1000; + } + async buildRequest(inputOptions, { retryCount = 0 } = {}) { + var _b, _c, _d; + const options = Object.assign({}, inputOptions); + const { method, path, query, defaultBaseURL } = options; + const url = this.buildURL(path, query, defaultBaseURL); + if ('timeout' in options) + validatePositiveInteger('timeout', options.timeout); + options.timeout = (_b = options.timeout) !== null && _b !== void 0 ? _b : this.timeout; + const { bodyHeaders, body } = this.buildBody({ options }); + const reqHeaders = await this.buildHeaders({ options: inputOptions, method, bodyHeaders, retryCount }); + const req = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ method, headers: reqHeaders }, (options.signal && { signal: options.signal })), (globalThis.ReadableStream && + body instanceof globalThis.ReadableStream && { duplex: 'half' })), (body && { body })), ((_c = this.fetchOptions) !== null && _c !== void 0 ? _c : {})), ((_d = options.fetchOptions) !== null && _d !== void 0 ? _d : {})); + return { req, url, timeout: options.timeout }; + } + async buildHeaders({ options, method, bodyHeaders, retryCount, }) { + let idempotencyHeaders = {}; + if (this.idempotencyHeader && method !== 'get') { + if (!options.idempotencyKey) + options.idempotencyKey = this.defaultIdempotencyKey(); + idempotencyHeaders[this.idempotencyHeader] = options.idempotencyKey; + } + const authHeaders = await this.authHeaders(options); + let headers = buildHeaders([ + idempotencyHeaders, + Object.assign(Object.assign({ Accept: 'application/json', 'User-Agent': this.getUserAgent(), 'X-Stainless-Retry-Count': String(retryCount) }, (options.timeout ? { 'X-Stainless-Timeout': String(Math.trunc(options.timeout / 1000)) } : {})), getPlatformHeaders()), + this._options.defaultHeaders, + bodyHeaders, + options.headers, + authHeaders, + ]); + this.validateHeaders(headers); + return headers.values; + } + _makeAbort(controller) { + // note: we can't just inline this method inside `fetchWithTimeout()` because then the closure + // would capture all request options, and cause a memory leak. + return () => controller.abort(); + } + buildBody({ options: { body, headers: rawHeaders } }) { + if (!body) { + return { bodyHeaders: undefined, body: undefined }; + } + const headers = buildHeaders([rawHeaders]); + if ( + // Pass raw type verbatim + ArrayBuffer.isView(body) || + body instanceof ArrayBuffer || + body instanceof DataView || + (typeof body === 'string' && + // Preserve legacy string encoding behavior for now + headers.values.has('content-type')) || + // `Blob` is superset of `File` + (globalThis.Blob && body instanceof globalThis.Blob) || + // `FormData` -> `multipart/form-data` + body instanceof FormData || + // `URLSearchParams` -> `application/x-www-form-urlencoded` + body instanceof URLSearchParams || + // Send chunked stream (each chunk has own `length`) + (globalThis.ReadableStream && body instanceof globalThis.ReadableStream)) { + return { bodyHeaders: undefined, body: body }; + } + else if (typeof body === 'object' && + (Symbol.asyncIterator in body || + (Symbol.iterator in body && 'next' in body && typeof body.next === 'function'))) { + return { bodyHeaders: undefined, body: ReadableStreamFrom(body) }; + } + else { + return this.encoder({ body, headers }); + } + } +} +BaseGeminiNextGenAPIClient.DEFAULT_TIMEOUT = 60000; // 1 minute +/** + * API Client for interfacing with the Gemini Next Gen API API. + */ +class GeminiNextGenAPIClient extends BaseGeminiNextGenAPIClient { + constructor() { + super(...arguments); + this.interactions = new Interactions(this); + } +} +_a = GeminiNextGenAPIClient; +GeminiNextGenAPIClient.GeminiNextGenAPIClient = _a; +GeminiNextGenAPIClient.GeminiNextGenAPIClientError = GeminiNextGenAPIClientError; +GeminiNextGenAPIClient.APIError = APIError; +GeminiNextGenAPIClient.APIConnectionError = APIConnectionError; +GeminiNextGenAPIClient.APIConnectionTimeoutError = APIConnectionTimeoutError; +GeminiNextGenAPIClient.APIUserAbortError = APIUserAbortError; +GeminiNextGenAPIClient.NotFoundError = NotFoundError; +GeminiNextGenAPIClient.ConflictError = ConflictError; +GeminiNextGenAPIClient.RateLimitError = RateLimitError; +GeminiNextGenAPIClient.BadRequestError = BadRequestError; +GeminiNextGenAPIClient.AuthenticationError = AuthenticationError; +GeminiNextGenAPIClient.InternalServerError = InternalServerError; +GeminiNextGenAPIClient.PermissionDeniedError = PermissionDeniedError; +GeminiNextGenAPIClient.UnprocessableEntityError = UnprocessableEntityError; +GeminiNextGenAPIClient.toFile = toFile; +GeminiNextGenAPIClient.Interactions = Interactions; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function blobToMldev$2(fromObject) { + const toObject = {}; + const fromData = getValueByPath(fromObject, ['data']); + if (fromData != null) { + setValueByPath(toObject, ['data'], fromData); + } + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function contentToMldev$2(fromObject) { + const toObject = {}; + const fromParts = getValueByPath(fromObject, ['parts']); + if (fromParts != null) { + let transformedList = fromParts; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return partToMldev$2(item); + }); + } + setValueByPath(toObject, ['parts'], transformedList); + } + const fromRole = getValueByPath(fromObject, ['role']); + if (fromRole != null) { + setValueByPath(toObject, ['role'], fromRole); + } + return toObject; +} +function fileDataToMldev$2(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromFileUri = getValueByPath(fromObject, ['fileUri']); + if (fromFileUri != null) { + setValueByPath(toObject, ['fileUri'], fromFileUri); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function functionCallToMldev$2(fromObject) { + const toObject = {}; + const fromId = getValueByPath(fromObject, ['id']); + if (fromId != null) { + setValueByPath(toObject, ['id'], fromId); + } + const fromArgs = getValueByPath(fromObject, ['args']); + if (fromArgs != null) { + setValueByPath(toObject, ['args'], fromArgs); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + if (getValueByPath(fromObject, ['partialArgs']) !== undefined) { + throw new Error('partialArgs parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['willContinue']) !== undefined) { + throw new Error('willContinue parameter is not supported in Gemini API.'); + } + return toObject; +} +function functionDeclarationToVertex$1(fromObject) { + const toObject = {}; + const fromDescription = getValueByPath(fromObject, ['description']); + if (fromDescription != null) { + setValueByPath(toObject, ['description'], fromDescription); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromParameters = getValueByPath(fromObject, ['parameters']); + if (fromParameters != null) { + setValueByPath(toObject, ['parameters'], fromParameters); + } + const fromParametersJsonSchema = getValueByPath(fromObject, [ + 'parametersJsonSchema', + ]); + if (fromParametersJsonSchema != null) { + setValueByPath(toObject, ['parametersJsonSchema'], fromParametersJsonSchema); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], fromResponse); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + if (getValueByPath(fromObject, ['behavior']) !== undefined) { + throw new Error('behavior parameter is not supported in Vertex AI.'); + } + return toObject; +} +function generationConfigToVertex$1(fromObject) { + const toObject = {}; + const fromModelSelectionConfig = getValueByPath(fromObject, [ + 'modelSelectionConfig', + ]); + if (fromModelSelectionConfig != null) { + setValueByPath(toObject, ['modelConfig'], fromModelSelectionConfig); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + const fromAudioTimestamp = getValueByPath(fromObject, [ + 'audioTimestamp', + ]); + if (fromAudioTimestamp != null) { + setValueByPath(toObject, ['audioTimestamp'], fromAudioTimestamp); + } + const fromCandidateCount = getValueByPath(fromObject, [ + 'candidateCount', + ]); + if (fromCandidateCount != null) { + setValueByPath(toObject, ['candidateCount'], fromCandidateCount); + } + const fromEnableAffectiveDialog = getValueByPath(fromObject, [ + 'enableAffectiveDialog', + ]); + if (fromEnableAffectiveDialog != null) { + setValueByPath(toObject, ['enableAffectiveDialog'], fromEnableAffectiveDialog); + } + const fromFrequencyPenalty = getValueByPath(fromObject, [ + 'frequencyPenalty', + ]); + if (fromFrequencyPenalty != null) { + setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty); + } + const fromLogprobs = getValueByPath(fromObject, ['logprobs']); + if (fromLogprobs != null) { + setValueByPath(toObject, ['logprobs'], fromLogprobs); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (fromMaxOutputTokens != null) { + setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromPresencePenalty = getValueByPath(fromObject, [ + 'presencePenalty', + ]); + if (fromPresencePenalty != null) { + setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty); + } + const fromResponseLogprobs = getValueByPath(fromObject, [ + 'responseLogprobs', + ]); + if (fromResponseLogprobs != null) { + setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs); + } + const fromResponseMimeType = getValueByPath(fromObject, [ + 'responseMimeType', + ]); + if (fromResponseMimeType != null) { + setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (fromResponseModalities != null) { + setValueByPath(toObject, ['responseModalities'], fromResponseModalities); + } + const fromResponseSchema = getValueByPath(fromObject, [ + 'responseSchema', + ]); + if (fromResponseSchema != null) { + setValueByPath(toObject, ['responseSchema'], fromResponseSchema); + } + const fromRoutingConfig = getValueByPath(fromObject, [ + 'routingConfig', + ]); + if (fromRoutingConfig != null) { + setValueByPath(toObject, ['routingConfig'], fromRoutingConfig); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (fromSeed != null) { + setValueByPath(toObject, ['seed'], fromSeed); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (fromSpeechConfig != null) { + setValueByPath(toObject, ['speechConfig'], fromSpeechConfig); + } + const fromStopSequences = getValueByPath(fromObject, [ + 'stopSequences', + ]); + if (fromStopSequences != null) { + setValueByPath(toObject, ['stopSequences'], fromStopSequences); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (fromTemperature != null) { + setValueByPath(toObject, ['temperature'], fromTemperature); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (fromThinkingConfig != null) { + setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (fromTopK != null) { + setValueByPath(toObject, ['topK'], fromTopK); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (fromTopP != null) { + setValueByPath(toObject, ['topP'], fromTopP); + } + if (getValueByPath(fromObject, ['enableEnhancedCivicAnswers']) !== + undefined) { + throw new Error('enableEnhancedCivicAnswers parameter is not supported in Vertex AI.'); + } + return toObject; +} +function googleMapsToMldev$2(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['authConfig']) !== undefined) { + throw new Error('authConfig parameter is not supported in Gemini API.'); + } + const fromEnableWidget = getValueByPath(fromObject, ['enableWidget']); + if (fromEnableWidget != null) { + setValueByPath(toObject, ['enableWidget'], fromEnableWidget); + } + return toObject; +} +function googleSearchToMldev$2(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['excludeDomains']) !== undefined) { + throw new Error('excludeDomains parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['blockingConfidence']) !== undefined) { + throw new Error('blockingConfidence parameter is not supported in Gemini API.'); + } + const fromTimeRangeFilter = getValueByPath(fromObject, [ + 'timeRangeFilter', + ]); + if (fromTimeRangeFilter != null) { + setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter); + } + return toObject; +} +function liveConnectConfigToMldev$1(fromObject, parentObject) { + const toObject = {}; + const fromGenerationConfig = getValueByPath(fromObject, [ + 'generationConfig', + ]); + if (parentObject !== undefined && fromGenerationConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig'], fromGenerationConfig); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (parentObject !== undefined && fromResponseModalities != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'responseModalities'], fromResponseModalities); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (parentObject !== undefined && fromTemperature != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'temperature'], fromTemperature); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (parentObject !== undefined && fromTopP != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'topP'], fromTopP); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (parentObject !== undefined && fromTopK != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'topK'], fromTopK); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (parentObject !== undefined && fromMaxOutputTokens != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'maxOutputTokens'], fromMaxOutputTokens); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (parentObject !== undefined && fromMediaResolution != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'mediaResolution'], fromMediaResolution); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (parentObject !== undefined && fromSeed != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'seed'], fromSeed); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (parentObject !== undefined && fromSpeechConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'speechConfig'], tLiveSpeechConfig(fromSpeechConfig)); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (parentObject !== undefined && fromThinkingConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'thinkingConfig'], fromThinkingConfig); + } + const fromEnableAffectiveDialog = getValueByPath(fromObject, [ + 'enableAffectiveDialog', + ]); + if (parentObject !== undefined && fromEnableAffectiveDialog != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'enableAffectiveDialog'], fromEnableAffectiveDialog); + } + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['setup', 'systemInstruction'], contentToMldev$2(tContent(fromSystemInstruction))); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = tTools(fromTools); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToMldev$2(tTool(item)); + }); + } + setValueByPath(parentObject, ['setup', 'tools'], transformedList); + } + const fromSessionResumption = getValueByPath(fromObject, [ + 'sessionResumption', + ]); + if (parentObject !== undefined && fromSessionResumption != null) { + setValueByPath(parentObject, ['setup', 'sessionResumption'], sessionResumptionConfigToMldev$1(fromSessionResumption)); + } + const fromInputAudioTranscription = getValueByPath(fromObject, [ + 'inputAudioTranscription', + ]); + if (parentObject !== undefined && fromInputAudioTranscription != null) { + setValueByPath(parentObject, ['setup', 'inputAudioTranscription'], fromInputAudioTranscription); + } + const fromOutputAudioTranscription = getValueByPath(fromObject, [ + 'outputAudioTranscription', + ]); + if (parentObject !== undefined && fromOutputAudioTranscription != null) { + setValueByPath(parentObject, ['setup', 'outputAudioTranscription'], fromOutputAudioTranscription); + } + const fromRealtimeInputConfig = getValueByPath(fromObject, [ + 'realtimeInputConfig', + ]); + if (parentObject !== undefined && fromRealtimeInputConfig != null) { + setValueByPath(parentObject, ['setup', 'realtimeInputConfig'], fromRealtimeInputConfig); + } + const fromContextWindowCompression = getValueByPath(fromObject, [ + 'contextWindowCompression', + ]); + if (parentObject !== undefined && fromContextWindowCompression != null) { + setValueByPath(parentObject, ['setup', 'contextWindowCompression'], fromContextWindowCompression); + } + const fromProactivity = getValueByPath(fromObject, ['proactivity']); + if (parentObject !== undefined && fromProactivity != null) { + setValueByPath(parentObject, ['setup', 'proactivity'], fromProactivity); + } + if (getValueByPath(fromObject, ['explicitVadSignal']) !== undefined) { + throw new Error('explicitVadSignal parameter is not supported in Gemini API.'); + } + return toObject; +} +function liveConnectConfigToVertex(fromObject, parentObject) { + const toObject = {}; + const fromGenerationConfig = getValueByPath(fromObject, [ + 'generationConfig', + ]); + if (parentObject !== undefined && fromGenerationConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig'], generationConfigToVertex$1(fromGenerationConfig)); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (parentObject !== undefined && fromResponseModalities != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'responseModalities'], fromResponseModalities); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (parentObject !== undefined && fromTemperature != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'temperature'], fromTemperature); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (parentObject !== undefined && fromTopP != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'topP'], fromTopP); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (parentObject !== undefined && fromTopK != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'topK'], fromTopK); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (parentObject !== undefined && fromMaxOutputTokens != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'maxOutputTokens'], fromMaxOutputTokens); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (parentObject !== undefined && fromMediaResolution != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'mediaResolution'], fromMediaResolution); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (parentObject !== undefined && fromSeed != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'seed'], fromSeed); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (parentObject !== undefined && fromSpeechConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'speechConfig'], tLiveSpeechConfig(fromSpeechConfig)); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (parentObject !== undefined && fromThinkingConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'thinkingConfig'], fromThinkingConfig); + } + const fromEnableAffectiveDialog = getValueByPath(fromObject, [ + 'enableAffectiveDialog', + ]); + if (parentObject !== undefined && fromEnableAffectiveDialog != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'enableAffectiveDialog'], fromEnableAffectiveDialog); + } + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['setup', 'systemInstruction'], tContent(fromSystemInstruction)); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = tTools(fromTools); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToVertex$1(tTool(item)); + }); + } + setValueByPath(parentObject, ['setup', 'tools'], transformedList); + } + const fromSessionResumption = getValueByPath(fromObject, [ + 'sessionResumption', + ]); + if (parentObject !== undefined && fromSessionResumption != null) { + setValueByPath(parentObject, ['setup', 'sessionResumption'], fromSessionResumption); + } + const fromInputAudioTranscription = getValueByPath(fromObject, [ + 'inputAudioTranscription', + ]); + if (parentObject !== undefined && fromInputAudioTranscription != null) { + setValueByPath(parentObject, ['setup', 'inputAudioTranscription'], fromInputAudioTranscription); + } + const fromOutputAudioTranscription = getValueByPath(fromObject, [ + 'outputAudioTranscription', + ]); + if (parentObject !== undefined && fromOutputAudioTranscription != null) { + setValueByPath(parentObject, ['setup', 'outputAudioTranscription'], fromOutputAudioTranscription); + } + const fromRealtimeInputConfig = getValueByPath(fromObject, [ + 'realtimeInputConfig', + ]); + if (parentObject !== undefined && fromRealtimeInputConfig != null) { + setValueByPath(parentObject, ['setup', 'realtimeInputConfig'], fromRealtimeInputConfig); + } + const fromContextWindowCompression = getValueByPath(fromObject, [ + 'contextWindowCompression', + ]); + if (parentObject !== undefined && fromContextWindowCompression != null) { + setValueByPath(parentObject, ['setup', 'contextWindowCompression'], fromContextWindowCompression); + } + const fromProactivity = getValueByPath(fromObject, ['proactivity']); + if (parentObject !== undefined && fromProactivity != null) { + setValueByPath(parentObject, ['setup', 'proactivity'], fromProactivity); + } + const fromExplicitVadSignal = getValueByPath(fromObject, [ + 'explicitVadSignal', + ]); + if (parentObject !== undefined && fromExplicitVadSignal != null) { + setValueByPath(parentObject, ['setup', 'explicitVadSignal'], fromExplicitVadSignal); + } + return toObject; +} +function liveConnectParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['setup', 'model'], tModel(apiClient, fromModel)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['config'], liveConnectConfigToMldev$1(fromConfig, toObject)); + } + return toObject; +} +function liveConnectParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['setup', 'model'], tModel(apiClient, fromModel)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['config'], liveConnectConfigToVertex(fromConfig, toObject)); + } + return toObject; +} +function liveMusicSetConfigParametersToMldev(fromObject) { + const toObject = {}; + const fromMusicGenerationConfig = getValueByPath(fromObject, [ + 'musicGenerationConfig', + ]); + if (fromMusicGenerationConfig != null) { + setValueByPath(toObject, ['musicGenerationConfig'], fromMusicGenerationConfig); + } + return toObject; +} +function liveMusicSetWeightedPromptsParametersToMldev(fromObject) { + const toObject = {}; + const fromWeightedPrompts = getValueByPath(fromObject, [ + 'weightedPrompts', + ]); + if (fromWeightedPrompts != null) { + let transformedList = fromWeightedPrompts; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['weightedPrompts'], transformedList); + } + return toObject; +} +function liveSendRealtimeInputParametersToMldev(fromObject) { + const toObject = {}; + const fromMedia = getValueByPath(fromObject, ['media']); + if (fromMedia != null) { + let transformedList = tBlobs(fromMedia); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return blobToMldev$2(item); + }); + } + setValueByPath(toObject, ['mediaChunks'], transformedList); + } + const fromAudio = getValueByPath(fromObject, ['audio']); + if (fromAudio != null) { + setValueByPath(toObject, ['audio'], blobToMldev$2(tAudioBlob(fromAudio))); + } + const fromAudioStreamEnd = getValueByPath(fromObject, [ + 'audioStreamEnd', + ]); + if (fromAudioStreamEnd != null) { + setValueByPath(toObject, ['audioStreamEnd'], fromAudioStreamEnd); + } + const fromVideo = getValueByPath(fromObject, ['video']); + if (fromVideo != null) { + setValueByPath(toObject, ['video'], blobToMldev$2(tImageBlob(fromVideo))); + } + const fromText = getValueByPath(fromObject, ['text']); + if (fromText != null) { + setValueByPath(toObject, ['text'], fromText); + } + const fromActivityStart = getValueByPath(fromObject, [ + 'activityStart', + ]); + if (fromActivityStart != null) { + setValueByPath(toObject, ['activityStart'], fromActivityStart); + } + const fromActivityEnd = getValueByPath(fromObject, ['activityEnd']); + if (fromActivityEnd != null) { + setValueByPath(toObject, ['activityEnd'], fromActivityEnd); + } + return toObject; +} +function liveSendRealtimeInputParametersToVertex(fromObject) { + const toObject = {}; + const fromMedia = getValueByPath(fromObject, ['media']); + if (fromMedia != null) { + let transformedList = tBlobs(fromMedia); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['mediaChunks'], transformedList); + } + const fromAudio = getValueByPath(fromObject, ['audio']); + if (fromAudio != null) { + setValueByPath(toObject, ['audio'], tAudioBlob(fromAudio)); + } + const fromAudioStreamEnd = getValueByPath(fromObject, [ + 'audioStreamEnd', + ]); + if (fromAudioStreamEnd != null) { + setValueByPath(toObject, ['audioStreamEnd'], fromAudioStreamEnd); + } + const fromVideo = getValueByPath(fromObject, ['video']); + if (fromVideo != null) { + setValueByPath(toObject, ['video'], tImageBlob(fromVideo)); + } + const fromText = getValueByPath(fromObject, ['text']); + if (fromText != null) { + setValueByPath(toObject, ['text'], fromText); + } + const fromActivityStart = getValueByPath(fromObject, [ + 'activityStart', + ]); + if (fromActivityStart != null) { + setValueByPath(toObject, ['activityStart'], fromActivityStart); + } + const fromActivityEnd = getValueByPath(fromObject, ['activityEnd']); + if (fromActivityEnd != null) { + setValueByPath(toObject, ['activityEnd'], fromActivityEnd); + } + return toObject; +} +function liveServerMessageFromVertex(fromObject) { + const toObject = {}; + const fromSetupComplete = getValueByPath(fromObject, [ + 'setupComplete', + ]); + if (fromSetupComplete != null) { + setValueByPath(toObject, ['setupComplete'], fromSetupComplete); + } + const fromServerContent = getValueByPath(fromObject, [ + 'serverContent', + ]); + if (fromServerContent != null) { + setValueByPath(toObject, ['serverContent'], fromServerContent); + } + const fromToolCall = getValueByPath(fromObject, ['toolCall']); + if (fromToolCall != null) { + setValueByPath(toObject, ['toolCall'], fromToolCall); + } + const fromToolCallCancellation = getValueByPath(fromObject, [ + 'toolCallCancellation', + ]); + if (fromToolCallCancellation != null) { + setValueByPath(toObject, ['toolCallCancellation'], fromToolCallCancellation); + } + const fromUsageMetadata = getValueByPath(fromObject, [ + 'usageMetadata', + ]); + if (fromUsageMetadata != null) { + setValueByPath(toObject, ['usageMetadata'], usageMetadataFromVertex(fromUsageMetadata)); + } + const fromGoAway = getValueByPath(fromObject, ['goAway']); + if (fromGoAway != null) { + setValueByPath(toObject, ['goAway'], fromGoAway); + } + const fromSessionResumptionUpdate = getValueByPath(fromObject, [ + 'sessionResumptionUpdate', + ]); + if (fromSessionResumptionUpdate != null) { + setValueByPath(toObject, ['sessionResumptionUpdate'], fromSessionResumptionUpdate); + } + const fromVoiceActivityDetectionSignal = getValueByPath(fromObject, [ + 'voiceActivityDetectionSignal', + ]); + if (fromVoiceActivityDetectionSignal != null) { + setValueByPath(toObject, ['voiceActivityDetectionSignal'], fromVoiceActivityDetectionSignal); + } + const fromVoiceActivity = getValueByPath(fromObject, [ + 'voiceActivity', + ]); + if (fromVoiceActivity != null) { + setValueByPath(toObject, ['voiceActivity'], voiceActivityFromVertex(fromVoiceActivity)); + } + return toObject; +} +function partToMldev$2(fromObject) { + const toObject = {}; + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromCodeExecutionResult = getValueByPath(fromObject, [ + 'codeExecutionResult', + ]); + if (fromCodeExecutionResult != null) { + setValueByPath(toObject, ['codeExecutionResult'], fromCodeExecutionResult); + } + const fromExecutableCode = getValueByPath(fromObject, [ + 'executableCode', + ]); + if (fromExecutableCode != null) { + setValueByPath(toObject, ['executableCode'], fromExecutableCode); + } + const fromFileData = getValueByPath(fromObject, ['fileData']); + if (fromFileData != null) { + setValueByPath(toObject, ['fileData'], fileDataToMldev$2(fromFileData)); + } + const fromFunctionCall = getValueByPath(fromObject, ['functionCall']); + if (fromFunctionCall != null) { + setValueByPath(toObject, ['functionCall'], functionCallToMldev$2(fromFunctionCall)); + } + const fromFunctionResponse = getValueByPath(fromObject, [ + 'functionResponse', + ]); + if (fromFunctionResponse != null) { + setValueByPath(toObject, ['functionResponse'], fromFunctionResponse); + } + const fromInlineData = getValueByPath(fromObject, ['inlineData']); + if (fromInlineData != null) { + setValueByPath(toObject, ['inlineData'], blobToMldev$2(fromInlineData)); + } + const fromText = getValueByPath(fromObject, ['text']); + if (fromText != null) { + setValueByPath(toObject, ['text'], fromText); + } + const fromThought = getValueByPath(fromObject, ['thought']); + if (fromThought != null) { + setValueByPath(toObject, ['thought'], fromThought); + } + const fromThoughtSignature = getValueByPath(fromObject, [ + 'thoughtSignature', + ]); + if (fromThoughtSignature != null) { + setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature); + } + const fromVideoMetadata = getValueByPath(fromObject, [ + 'videoMetadata', + ]); + if (fromVideoMetadata != null) { + setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata); + } + return toObject; +} +function sessionResumptionConfigToMldev$1(fromObject) { + const toObject = {}; + const fromHandle = getValueByPath(fromObject, ['handle']); + if (fromHandle != null) { + setValueByPath(toObject, ['handle'], fromHandle); + } + if (getValueByPath(fromObject, ['transparent']) !== undefined) { + throw new Error('transparent parameter is not supported in Gemini API.'); + } + return toObject; +} +function toolToMldev$2(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['retrieval']) !== undefined) { + throw new Error('retrieval parameter is not supported in Gemini API.'); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + const fromFileSearch = getValueByPath(fromObject, ['fileSearch']); + if (fromFileSearch != null) { + setValueByPath(toObject, ['fileSearch'], fromFileSearch); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + if (getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined) { + throw new Error('enterpriseWebSearch parameter is not supported in Gemini API.'); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], googleMapsToMldev$2(fromGoogleMaps)); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], googleSearchToMldev$2(fromGoogleSearch)); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} +function toolToVertex$1(fromObject) { + const toObject = {}; + const fromRetrieval = getValueByPath(fromObject, ['retrieval']); + if (fromRetrieval != null) { + setValueByPath(toObject, ['retrieval'], fromRetrieval); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + if (getValueByPath(fromObject, ['fileSearch']) !== undefined) { + throw new Error('fileSearch parameter is not supported in Vertex AI.'); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + const fromEnterpriseWebSearch = getValueByPath(fromObject, [ + 'enterpriseWebSearch', + ]); + if (fromEnterpriseWebSearch != null) { + setValueByPath(toObject, ['enterpriseWebSearch'], fromEnterpriseWebSearch); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return functionDeclarationToVertex$1(item); + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], fromGoogleMaps); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], fromGoogleSearch); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} +function usageMetadataFromVertex(fromObject) { + const toObject = {}; + const fromPromptTokenCount = getValueByPath(fromObject, [ + 'promptTokenCount', + ]); + if (fromPromptTokenCount != null) { + setValueByPath(toObject, ['promptTokenCount'], fromPromptTokenCount); + } + const fromCachedContentTokenCount = getValueByPath(fromObject, [ + 'cachedContentTokenCount', + ]); + if (fromCachedContentTokenCount != null) { + setValueByPath(toObject, ['cachedContentTokenCount'], fromCachedContentTokenCount); + } + const fromResponseTokenCount = getValueByPath(fromObject, [ + 'candidatesTokenCount', + ]); + if (fromResponseTokenCount != null) { + setValueByPath(toObject, ['responseTokenCount'], fromResponseTokenCount); + } + const fromToolUsePromptTokenCount = getValueByPath(fromObject, [ + 'toolUsePromptTokenCount', + ]); + if (fromToolUsePromptTokenCount != null) { + setValueByPath(toObject, ['toolUsePromptTokenCount'], fromToolUsePromptTokenCount); + } + const fromThoughtsTokenCount = getValueByPath(fromObject, [ + 'thoughtsTokenCount', + ]); + if (fromThoughtsTokenCount != null) { + setValueByPath(toObject, ['thoughtsTokenCount'], fromThoughtsTokenCount); + } + const fromTotalTokenCount = getValueByPath(fromObject, [ + 'totalTokenCount', + ]); + if (fromTotalTokenCount != null) { + setValueByPath(toObject, ['totalTokenCount'], fromTotalTokenCount); + } + const fromPromptTokensDetails = getValueByPath(fromObject, [ + 'promptTokensDetails', + ]); + if (fromPromptTokensDetails != null) { + let transformedList = fromPromptTokensDetails; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['promptTokensDetails'], transformedList); + } + const fromCacheTokensDetails = getValueByPath(fromObject, [ + 'cacheTokensDetails', + ]); + if (fromCacheTokensDetails != null) { + let transformedList = fromCacheTokensDetails; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['cacheTokensDetails'], transformedList); + } + const fromResponseTokensDetails = getValueByPath(fromObject, [ + 'candidatesTokensDetails', + ]); + if (fromResponseTokensDetails != null) { + let transformedList = fromResponseTokensDetails; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['responseTokensDetails'], transformedList); + } + const fromToolUsePromptTokensDetails = getValueByPath(fromObject, [ + 'toolUsePromptTokensDetails', + ]); + if (fromToolUsePromptTokensDetails != null) { + let transformedList = fromToolUsePromptTokensDetails; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['toolUsePromptTokensDetails'], transformedList); + } + const fromTrafficType = getValueByPath(fromObject, ['trafficType']); + if (fromTrafficType != null) { + setValueByPath(toObject, ['trafficType'], fromTrafficType); + } + return toObject; +} +function voiceActivityFromVertex(fromObject) { + const toObject = {}; + const fromVoiceActivityType = getValueByPath(fromObject, ['type']); + if (fromVoiceActivityType != null) { + setValueByPath(toObject, ['voiceActivityType'], fromVoiceActivityType); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function blobToMldev$1(fromObject, _rootObject) { + const toObject = {}; + const fromData = getValueByPath(fromObject, ['data']); + if (fromData != null) { + setValueByPath(toObject, ['data'], fromData); + } + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function candidateFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromContent = getValueByPath(fromObject, ['content']); + if (fromContent != null) { + setValueByPath(toObject, ['content'], fromContent); + } + const fromCitationMetadata = getValueByPath(fromObject, [ + 'citationMetadata', + ]); + if (fromCitationMetadata != null) { + setValueByPath(toObject, ['citationMetadata'], citationMetadataFromMldev(fromCitationMetadata)); + } + const fromTokenCount = getValueByPath(fromObject, ['tokenCount']); + if (fromTokenCount != null) { + setValueByPath(toObject, ['tokenCount'], fromTokenCount); + } + const fromFinishReason = getValueByPath(fromObject, ['finishReason']); + if (fromFinishReason != null) { + setValueByPath(toObject, ['finishReason'], fromFinishReason); + } + const fromAvgLogprobs = getValueByPath(fromObject, ['avgLogprobs']); + if (fromAvgLogprobs != null) { + setValueByPath(toObject, ['avgLogprobs'], fromAvgLogprobs); + } + const fromGroundingMetadata = getValueByPath(fromObject, [ + 'groundingMetadata', + ]); + if (fromGroundingMetadata != null) { + setValueByPath(toObject, ['groundingMetadata'], fromGroundingMetadata); + } + const fromIndex = getValueByPath(fromObject, ['index']); + if (fromIndex != null) { + setValueByPath(toObject, ['index'], fromIndex); + } + const fromLogprobsResult = getValueByPath(fromObject, [ + 'logprobsResult', + ]); + if (fromLogprobsResult != null) { + setValueByPath(toObject, ['logprobsResult'], fromLogprobsResult); + } + const fromSafetyRatings = getValueByPath(fromObject, [ + 'safetyRatings', + ]); + if (fromSafetyRatings != null) { + let transformedList = fromSafetyRatings; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['safetyRatings'], transformedList); + } + const fromUrlContextMetadata = getValueByPath(fromObject, [ + 'urlContextMetadata', + ]); + if (fromUrlContextMetadata != null) { + setValueByPath(toObject, ['urlContextMetadata'], fromUrlContextMetadata); + } + return toObject; +} +function citationMetadataFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromCitations = getValueByPath(fromObject, ['citationSources']); + if (fromCitations != null) { + let transformedList = fromCitations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['citations'], transformedList); + } + return toObject; +} +function computeTokensParametersToVertex(apiClient, fromObject, _rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['contents'], transformedList); + } + return toObject; +} +function computeTokensResponseFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromTokensInfo = getValueByPath(fromObject, ['tokensInfo']); + if (fromTokensInfo != null) { + let transformedList = fromTokensInfo; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['tokensInfo'], transformedList); + } + return toObject; +} +function contentEmbeddingFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromValues = getValueByPath(fromObject, ['values']); + if (fromValues != null) { + setValueByPath(toObject, ['values'], fromValues); + } + const fromStatistics = getValueByPath(fromObject, ['statistics']); + if (fromStatistics != null) { + setValueByPath(toObject, ['statistics'], contentEmbeddingStatisticsFromVertex(fromStatistics)); + } + return toObject; +} +function contentEmbeddingStatisticsFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromTruncated = getValueByPath(fromObject, ['truncated']); + if (fromTruncated != null) { + setValueByPath(toObject, ['truncated'], fromTruncated); + } + const fromTokenCount = getValueByPath(fromObject, ['token_count']); + if (fromTokenCount != null) { + setValueByPath(toObject, ['tokenCount'], fromTokenCount); + } + return toObject; +} +function contentToMldev$1(fromObject, rootObject) { + const toObject = {}; + const fromParts = getValueByPath(fromObject, ['parts']); + if (fromParts != null) { + let transformedList = fromParts; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return partToMldev$1(item); + }); + } + setValueByPath(toObject, ['parts'], transformedList); + } + const fromRole = getValueByPath(fromObject, ['role']); + if (fromRole != null) { + setValueByPath(toObject, ['role'], fromRole); + } + return toObject; +} +function controlReferenceConfigToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromControlType = getValueByPath(fromObject, ['controlType']); + if (fromControlType != null) { + setValueByPath(toObject, ['controlType'], fromControlType); + } + const fromEnableControlImageComputation = getValueByPath(fromObject, [ + 'enableControlImageComputation', + ]); + if (fromEnableControlImageComputation != null) { + setValueByPath(toObject, ['computeControl'], fromEnableControlImageComputation); + } + return toObject; +} +function countTokensConfigToMldev(fromObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['systemInstruction']) !== undefined) { + throw new Error('systemInstruction parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['tools']) !== undefined) { + throw new Error('tools parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['generationConfig']) !== undefined) { + throw new Error('generationConfig parameter is not supported in Gemini API.'); + } + return toObject; +} +function countTokensConfigToVertex(fromObject, parentObject, rootObject) { + const toObject = {}; + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['systemInstruction'], tContent(fromSystemInstruction)); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = fromTools; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToVertex(item); + }); + } + setValueByPath(parentObject, ['tools'], transformedList); + } + const fromGenerationConfig = getValueByPath(fromObject, [ + 'generationConfig', + ]); + if (parentObject !== undefined && fromGenerationConfig != null) { + setValueByPath(parentObject, ['generationConfig'], generationConfigToVertex(fromGenerationConfig)); + } + return toObject; +} +function countTokensParametersToMldev(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return contentToMldev$1(item); + }); + } + setValueByPath(toObject, ['contents'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + countTokensConfigToMldev(fromConfig); + } + return toObject; +} +function countTokensParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['contents'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + countTokensConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function countTokensResponseFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromTotalTokens = getValueByPath(fromObject, ['totalTokens']); + if (fromTotalTokens != null) { + setValueByPath(toObject, ['totalTokens'], fromTotalTokens); + } + const fromCachedContentTokenCount = getValueByPath(fromObject, [ + 'cachedContentTokenCount', + ]); + if (fromCachedContentTokenCount != null) { + setValueByPath(toObject, ['cachedContentTokenCount'], fromCachedContentTokenCount); + } + return toObject; +} +function countTokensResponseFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromTotalTokens = getValueByPath(fromObject, ['totalTokens']); + if (fromTotalTokens != null) { + setValueByPath(toObject, ['totalTokens'], fromTotalTokens); + } + return toObject; +} +function deleteModelParametersToMldev(apiClient, fromObject, _rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'name'], tModel(apiClient, fromModel)); + } + return toObject; +} +function deleteModelParametersToVertex(apiClient, fromObject, _rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'name'], tModel(apiClient, fromModel)); + } + return toObject; +} +function deleteModelResponseFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function deleteModelResponseFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function editImageConfigToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromOutputGcsUri = getValueByPath(fromObject, ['outputGcsUri']); + if (parentObject !== undefined && fromOutputGcsUri != null) { + setValueByPath(parentObject, ['parameters', 'storageUri'], fromOutputGcsUri); + } + const fromNegativePrompt = getValueByPath(fromObject, [ + 'negativePrompt', + ]); + if (parentObject !== undefined && fromNegativePrompt != null) { + setValueByPath(parentObject, ['parameters', 'negativePrompt'], fromNegativePrompt); + } + const fromNumberOfImages = getValueByPath(fromObject, [ + 'numberOfImages', + ]); + if (parentObject !== undefined && fromNumberOfImages != null) { + setValueByPath(parentObject, ['parameters', 'sampleCount'], fromNumberOfImages); + } + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (parentObject !== undefined && fromAspectRatio != null) { + setValueByPath(parentObject, ['parameters', 'aspectRatio'], fromAspectRatio); + } + const fromGuidanceScale = getValueByPath(fromObject, [ + 'guidanceScale', + ]); + if (parentObject !== undefined && fromGuidanceScale != null) { + setValueByPath(parentObject, ['parameters', 'guidanceScale'], fromGuidanceScale); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (parentObject !== undefined && fromSeed != null) { + setValueByPath(parentObject, ['parameters', 'seed'], fromSeed); + } + const fromSafetyFilterLevel = getValueByPath(fromObject, [ + 'safetyFilterLevel', + ]); + if (parentObject !== undefined && fromSafetyFilterLevel != null) { + setValueByPath(parentObject, ['parameters', 'safetySetting'], fromSafetyFilterLevel); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (parentObject !== undefined && fromPersonGeneration != null) { + setValueByPath(parentObject, ['parameters', 'personGeneration'], fromPersonGeneration); + } + const fromIncludeSafetyAttributes = getValueByPath(fromObject, [ + 'includeSafetyAttributes', + ]); + if (parentObject !== undefined && fromIncludeSafetyAttributes != null) { + setValueByPath(parentObject, ['parameters', 'includeSafetyAttributes'], fromIncludeSafetyAttributes); + } + const fromIncludeRaiReason = getValueByPath(fromObject, [ + 'includeRaiReason', + ]); + if (parentObject !== undefined && fromIncludeRaiReason != null) { + setValueByPath(parentObject, ['parameters', 'includeRaiReason'], fromIncludeRaiReason); + } + const fromLanguage = getValueByPath(fromObject, ['language']); + if (parentObject !== undefined && fromLanguage != null) { + setValueByPath(parentObject, ['parameters', 'language'], fromLanguage); + } + const fromOutputMimeType = getValueByPath(fromObject, [ + 'outputMimeType', + ]); + if (parentObject !== undefined && fromOutputMimeType != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'mimeType'], fromOutputMimeType); + } + const fromOutputCompressionQuality = getValueByPath(fromObject, [ + 'outputCompressionQuality', + ]); + if (parentObject !== undefined && fromOutputCompressionQuality != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'compressionQuality'], fromOutputCompressionQuality); + } + const fromAddWatermark = getValueByPath(fromObject, ['addWatermark']); + if (parentObject !== undefined && fromAddWatermark != null) { + setValueByPath(parentObject, ['parameters', 'addWatermark'], fromAddWatermark); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (parentObject !== undefined && fromLabels != null) { + setValueByPath(parentObject, ['labels'], fromLabels); + } + const fromEditMode = getValueByPath(fromObject, ['editMode']); + if (parentObject !== undefined && fromEditMode != null) { + setValueByPath(parentObject, ['parameters', 'editMode'], fromEditMode); + } + const fromBaseSteps = getValueByPath(fromObject, ['baseSteps']); + if (parentObject !== undefined && fromBaseSteps != null) { + setValueByPath(parentObject, ['parameters', 'editConfig', 'baseSteps'], fromBaseSteps); + } + return toObject; +} +function editImageParametersInternalToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (fromPrompt != null) { + setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromReferenceImages = getValueByPath(fromObject, [ + 'referenceImages', + ]); + if (fromReferenceImages != null) { + let transformedList = fromReferenceImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return referenceImageAPIInternalToVertex(item); + }); + } + setValueByPath(toObject, ['instances[0]', 'referenceImages'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + editImageConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function editImageResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromGeneratedImages = getValueByPath(fromObject, [ + 'predictions', + ]); + if (fromGeneratedImages != null) { + let transformedList = fromGeneratedImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedImageFromVertex(item); + }); + } + setValueByPath(toObject, ['generatedImages'], transformedList); + } + return toObject; +} +function embedContentConfigToMldev(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromTaskType = getValueByPath(fromObject, ['taskType']); + if (parentObject !== undefined && fromTaskType != null) { + setValueByPath(parentObject, ['requests[]', 'taskType'], fromTaskType); + } + const fromTitle = getValueByPath(fromObject, ['title']); + if (parentObject !== undefined && fromTitle != null) { + setValueByPath(parentObject, ['requests[]', 'title'], fromTitle); + } + const fromOutputDimensionality = getValueByPath(fromObject, [ + 'outputDimensionality', + ]); + if (parentObject !== undefined && fromOutputDimensionality != null) { + setValueByPath(parentObject, ['requests[]', 'outputDimensionality'], fromOutputDimensionality); + } + if (getValueByPath(fromObject, ['mimeType']) !== undefined) { + throw new Error('mimeType parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['autoTruncate']) !== undefined) { + throw new Error('autoTruncate parameter is not supported in Gemini API.'); + } + return toObject; +} +function embedContentConfigToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromTaskType = getValueByPath(fromObject, ['taskType']); + if (parentObject !== undefined && fromTaskType != null) { + setValueByPath(parentObject, ['instances[]', 'task_type'], fromTaskType); + } + const fromTitle = getValueByPath(fromObject, ['title']); + if (parentObject !== undefined && fromTitle != null) { + setValueByPath(parentObject, ['instances[]', 'title'], fromTitle); + } + const fromOutputDimensionality = getValueByPath(fromObject, [ + 'outputDimensionality', + ]); + if (parentObject !== undefined && fromOutputDimensionality != null) { + setValueByPath(parentObject, ['parameters', 'outputDimensionality'], fromOutputDimensionality); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (parentObject !== undefined && fromMimeType != null) { + setValueByPath(parentObject, ['instances[]', 'mimeType'], fromMimeType); + } + const fromAutoTruncate = getValueByPath(fromObject, ['autoTruncate']); + if (parentObject !== undefined && fromAutoTruncate != null) { + setValueByPath(parentObject, ['parameters', 'autoTruncate'], fromAutoTruncate); + } + return toObject; +} +function embedContentParametersToMldev(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContentsForEmbed(apiClient, fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['requests[]', 'content'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + embedContentConfigToMldev(fromConfig, toObject); + } + const fromModelForEmbedContent = getValueByPath(fromObject, ['model']); + if (fromModelForEmbedContent !== undefined) { + setValueByPath(toObject, ['requests[]', 'model'], tModel(apiClient, fromModelForEmbedContent)); + } + return toObject; +} +function embedContentParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContentsForEmbed(apiClient, fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['instances[]', 'content'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + embedContentConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function embedContentResponseFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromEmbeddings = getValueByPath(fromObject, ['embeddings']); + if (fromEmbeddings != null) { + let transformedList = fromEmbeddings; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['embeddings'], transformedList); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + return toObject; +} +function embedContentResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromEmbeddings = getValueByPath(fromObject, [ + 'predictions[]', + 'embeddings', + ]); + if (fromEmbeddings != null) { + let transformedList = fromEmbeddings; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return contentEmbeddingFromVertex(item); + }); + } + setValueByPath(toObject, ['embeddings'], transformedList); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + return toObject; +} +function endpointFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['endpoint']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromDeployedModelId = getValueByPath(fromObject, [ + 'deployedModelId', + ]); + if (fromDeployedModelId != null) { + setValueByPath(toObject, ['deployedModelId'], fromDeployedModelId); + } + return toObject; +} +function fileDataToMldev$1(fromObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromFileUri = getValueByPath(fromObject, ['fileUri']); + if (fromFileUri != null) { + setValueByPath(toObject, ['fileUri'], fromFileUri); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function functionCallToMldev$1(fromObject, _rootObject) { + const toObject = {}; + const fromId = getValueByPath(fromObject, ['id']); + if (fromId != null) { + setValueByPath(toObject, ['id'], fromId); + } + const fromArgs = getValueByPath(fromObject, ['args']); + if (fromArgs != null) { + setValueByPath(toObject, ['args'], fromArgs); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + if (getValueByPath(fromObject, ['partialArgs']) !== undefined) { + throw new Error('partialArgs parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['willContinue']) !== undefined) { + throw new Error('willContinue parameter is not supported in Gemini API.'); + } + return toObject; +} +function functionCallingConfigToMldev(fromObject, _rootObject) { + const toObject = {}; + const fromAllowedFunctionNames = getValueByPath(fromObject, [ + 'allowedFunctionNames', + ]); + if (fromAllowedFunctionNames != null) { + setValueByPath(toObject, ['allowedFunctionNames'], fromAllowedFunctionNames); + } + const fromMode = getValueByPath(fromObject, ['mode']); + if (fromMode != null) { + setValueByPath(toObject, ['mode'], fromMode); + } + if (getValueByPath(fromObject, ['streamFunctionCallArguments']) !== + undefined) { + throw new Error('streamFunctionCallArguments parameter is not supported in Gemini API.'); + } + return toObject; +} +function functionDeclarationToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromDescription = getValueByPath(fromObject, ['description']); + if (fromDescription != null) { + setValueByPath(toObject, ['description'], fromDescription); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromParameters = getValueByPath(fromObject, ['parameters']); + if (fromParameters != null) { + setValueByPath(toObject, ['parameters'], fromParameters); + } + const fromParametersJsonSchema = getValueByPath(fromObject, [ + 'parametersJsonSchema', + ]); + if (fromParametersJsonSchema != null) { + setValueByPath(toObject, ['parametersJsonSchema'], fromParametersJsonSchema); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], fromResponse); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + if (getValueByPath(fromObject, ['behavior']) !== undefined) { + throw new Error('behavior parameter is not supported in Vertex AI.'); + } + return toObject; +} +function generateContentConfigToMldev(apiClient, fromObject, parentObject, rootObject) { + const toObject = {}; + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['systemInstruction'], contentToMldev$1(tContent(fromSystemInstruction))); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (fromTemperature != null) { + setValueByPath(toObject, ['temperature'], fromTemperature); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (fromTopP != null) { + setValueByPath(toObject, ['topP'], fromTopP); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (fromTopK != null) { + setValueByPath(toObject, ['topK'], fromTopK); + } + const fromCandidateCount = getValueByPath(fromObject, [ + 'candidateCount', + ]); + if (fromCandidateCount != null) { + setValueByPath(toObject, ['candidateCount'], fromCandidateCount); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (fromMaxOutputTokens != null) { + setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens); + } + const fromStopSequences = getValueByPath(fromObject, [ + 'stopSequences', + ]); + if (fromStopSequences != null) { + setValueByPath(toObject, ['stopSequences'], fromStopSequences); + } + const fromResponseLogprobs = getValueByPath(fromObject, [ + 'responseLogprobs', + ]); + if (fromResponseLogprobs != null) { + setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs); + } + const fromLogprobs = getValueByPath(fromObject, ['logprobs']); + if (fromLogprobs != null) { + setValueByPath(toObject, ['logprobs'], fromLogprobs); + } + const fromPresencePenalty = getValueByPath(fromObject, [ + 'presencePenalty', + ]); + if (fromPresencePenalty != null) { + setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty); + } + const fromFrequencyPenalty = getValueByPath(fromObject, [ + 'frequencyPenalty', + ]); + if (fromFrequencyPenalty != null) { + setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (fromSeed != null) { + setValueByPath(toObject, ['seed'], fromSeed); + } + const fromResponseMimeType = getValueByPath(fromObject, [ + 'responseMimeType', + ]); + if (fromResponseMimeType != null) { + setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType); + } + const fromResponseSchema = getValueByPath(fromObject, [ + 'responseSchema', + ]); + if (fromResponseSchema != null) { + setValueByPath(toObject, ['responseSchema'], tSchema(fromResponseSchema)); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + if (getValueByPath(fromObject, ['routingConfig']) !== undefined) { + throw new Error('routingConfig parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['modelSelectionConfig']) !== undefined) { + throw new Error('modelSelectionConfig parameter is not supported in Gemini API.'); + } + const fromSafetySettings = getValueByPath(fromObject, [ + 'safetySettings', + ]); + if (parentObject !== undefined && fromSafetySettings != null) { + let transformedList = fromSafetySettings; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return safetySettingToMldev(item); + }); + } + setValueByPath(parentObject, ['safetySettings'], transformedList); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = tTools(fromTools); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToMldev$1(tTool(item)); + }); + } + setValueByPath(parentObject, ['tools'], transformedList); + } + const fromToolConfig = getValueByPath(fromObject, ['toolConfig']); + if (parentObject !== undefined && fromToolConfig != null) { + setValueByPath(parentObject, ['toolConfig'], toolConfigToMldev(fromToolConfig)); + } + if (getValueByPath(fromObject, ['labels']) !== undefined) { + throw new Error('labels parameter is not supported in Gemini API.'); + } + const fromCachedContent = getValueByPath(fromObject, [ + 'cachedContent', + ]); + if (parentObject !== undefined && fromCachedContent != null) { + setValueByPath(parentObject, ['cachedContent'], tCachedContentName(apiClient, fromCachedContent)); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (fromResponseModalities != null) { + setValueByPath(toObject, ['responseModalities'], fromResponseModalities); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (fromSpeechConfig != null) { + setValueByPath(toObject, ['speechConfig'], tSpeechConfig(fromSpeechConfig)); + } + if (getValueByPath(fromObject, ['audioTimestamp']) !== undefined) { + throw new Error('audioTimestamp parameter is not supported in Gemini API.'); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (fromThinkingConfig != null) { + setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig); + } + const fromImageConfig = getValueByPath(fromObject, ['imageConfig']); + if (fromImageConfig != null) { + setValueByPath(toObject, ['imageConfig'], imageConfigToMldev(fromImageConfig)); + } + const fromEnableEnhancedCivicAnswers = getValueByPath(fromObject, [ + 'enableEnhancedCivicAnswers', + ]); + if (fromEnableEnhancedCivicAnswers != null) { + setValueByPath(toObject, ['enableEnhancedCivicAnswers'], fromEnableEnhancedCivicAnswers); + } + if (getValueByPath(fromObject, ['modelArmorConfig']) !== undefined) { + throw new Error('modelArmorConfig parameter is not supported in Gemini API.'); + } + return toObject; +} +function generateContentConfigToVertex(apiClient, fromObject, parentObject, rootObject) { + const toObject = {}; + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['systemInstruction'], tContent(fromSystemInstruction)); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (fromTemperature != null) { + setValueByPath(toObject, ['temperature'], fromTemperature); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (fromTopP != null) { + setValueByPath(toObject, ['topP'], fromTopP); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (fromTopK != null) { + setValueByPath(toObject, ['topK'], fromTopK); + } + const fromCandidateCount = getValueByPath(fromObject, [ + 'candidateCount', + ]); + if (fromCandidateCount != null) { + setValueByPath(toObject, ['candidateCount'], fromCandidateCount); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (fromMaxOutputTokens != null) { + setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens); + } + const fromStopSequences = getValueByPath(fromObject, [ + 'stopSequences', + ]); + if (fromStopSequences != null) { + setValueByPath(toObject, ['stopSequences'], fromStopSequences); + } + const fromResponseLogprobs = getValueByPath(fromObject, [ + 'responseLogprobs', + ]); + if (fromResponseLogprobs != null) { + setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs); + } + const fromLogprobs = getValueByPath(fromObject, ['logprobs']); + if (fromLogprobs != null) { + setValueByPath(toObject, ['logprobs'], fromLogprobs); + } + const fromPresencePenalty = getValueByPath(fromObject, [ + 'presencePenalty', + ]); + if (fromPresencePenalty != null) { + setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty); + } + const fromFrequencyPenalty = getValueByPath(fromObject, [ + 'frequencyPenalty', + ]); + if (fromFrequencyPenalty != null) { + setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (fromSeed != null) { + setValueByPath(toObject, ['seed'], fromSeed); + } + const fromResponseMimeType = getValueByPath(fromObject, [ + 'responseMimeType', + ]); + if (fromResponseMimeType != null) { + setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType); + } + const fromResponseSchema = getValueByPath(fromObject, [ + 'responseSchema', + ]); + if (fromResponseSchema != null) { + setValueByPath(toObject, ['responseSchema'], tSchema(fromResponseSchema)); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + const fromRoutingConfig = getValueByPath(fromObject, [ + 'routingConfig', + ]); + if (fromRoutingConfig != null) { + setValueByPath(toObject, ['routingConfig'], fromRoutingConfig); + } + const fromModelSelectionConfig = getValueByPath(fromObject, [ + 'modelSelectionConfig', + ]); + if (fromModelSelectionConfig != null) { + setValueByPath(toObject, ['modelConfig'], fromModelSelectionConfig); + } + const fromSafetySettings = getValueByPath(fromObject, [ + 'safetySettings', + ]); + if (parentObject !== undefined && fromSafetySettings != null) { + let transformedList = fromSafetySettings; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(parentObject, ['safetySettings'], transformedList); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = tTools(fromTools); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToVertex(tTool(item)); + }); + } + setValueByPath(parentObject, ['tools'], transformedList); + } + const fromToolConfig = getValueByPath(fromObject, ['toolConfig']); + if (parentObject !== undefined && fromToolConfig != null) { + setValueByPath(parentObject, ['toolConfig'], fromToolConfig); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (parentObject !== undefined && fromLabels != null) { + setValueByPath(parentObject, ['labels'], fromLabels); + } + const fromCachedContent = getValueByPath(fromObject, [ + 'cachedContent', + ]); + if (parentObject !== undefined && fromCachedContent != null) { + setValueByPath(parentObject, ['cachedContent'], tCachedContentName(apiClient, fromCachedContent)); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (fromResponseModalities != null) { + setValueByPath(toObject, ['responseModalities'], fromResponseModalities); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (fromSpeechConfig != null) { + setValueByPath(toObject, ['speechConfig'], tSpeechConfig(fromSpeechConfig)); + } + const fromAudioTimestamp = getValueByPath(fromObject, [ + 'audioTimestamp', + ]); + if (fromAudioTimestamp != null) { + setValueByPath(toObject, ['audioTimestamp'], fromAudioTimestamp); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (fromThinkingConfig != null) { + setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig); + } + const fromImageConfig = getValueByPath(fromObject, ['imageConfig']); + if (fromImageConfig != null) { + setValueByPath(toObject, ['imageConfig'], imageConfigToVertex(fromImageConfig)); + } + if (getValueByPath(fromObject, ['enableEnhancedCivicAnswers']) !== + undefined) { + throw new Error('enableEnhancedCivicAnswers parameter is not supported in Vertex AI.'); + } + const fromModelArmorConfig = getValueByPath(fromObject, [ + 'modelArmorConfig', + ]); + if (parentObject !== undefined && fromModelArmorConfig != null) { + setValueByPath(parentObject, ['modelArmorConfig'], fromModelArmorConfig); + } + return toObject; +} +function generateContentParametersToMldev(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return contentToMldev$1(item); + }); + } + setValueByPath(toObject, ['contents'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['generationConfig'], generateContentConfigToMldev(apiClient, fromConfig, toObject)); + } + return toObject; +} +function generateContentParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['contents'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['generationConfig'], generateContentConfigToVertex(apiClient, fromConfig, toObject)); + } + return toObject; +} +function generateContentResponseFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromCandidates = getValueByPath(fromObject, ['candidates']); + if (fromCandidates != null) { + let transformedList = fromCandidates; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return candidateFromMldev(item); + }); + } + setValueByPath(toObject, ['candidates'], transformedList); + } + const fromModelVersion = getValueByPath(fromObject, ['modelVersion']); + if (fromModelVersion != null) { + setValueByPath(toObject, ['modelVersion'], fromModelVersion); + } + const fromPromptFeedback = getValueByPath(fromObject, [ + 'promptFeedback', + ]); + if (fromPromptFeedback != null) { + setValueByPath(toObject, ['promptFeedback'], fromPromptFeedback); + } + const fromResponseId = getValueByPath(fromObject, ['responseId']); + if (fromResponseId != null) { + setValueByPath(toObject, ['responseId'], fromResponseId); + } + const fromUsageMetadata = getValueByPath(fromObject, [ + 'usageMetadata', + ]); + if (fromUsageMetadata != null) { + setValueByPath(toObject, ['usageMetadata'], fromUsageMetadata); + } + return toObject; +} +function generateContentResponseFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromCandidates = getValueByPath(fromObject, ['candidates']); + if (fromCandidates != null) { + let transformedList = fromCandidates; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['candidates'], transformedList); + } + const fromCreateTime = getValueByPath(fromObject, ['createTime']); + if (fromCreateTime != null) { + setValueByPath(toObject, ['createTime'], fromCreateTime); + } + const fromModelVersion = getValueByPath(fromObject, ['modelVersion']); + if (fromModelVersion != null) { + setValueByPath(toObject, ['modelVersion'], fromModelVersion); + } + const fromPromptFeedback = getValueByPath(fromObject, [ + 'promptFeedback', + ]); + if (fromPromptFeedback != null) { + setValueByPath(toObject, ['promptFeedback'], fromPromptFeedback); + } + const fromResponseId = getValueByPath(fromObject, ['responseId']); + if (fromResponseId != null) { + setValueByPath(toObject, ['responseId'], fromResponseId); + } + const fromUsageMetadata = getValueByPath(fromObject, [ + 'usageMetadata', + ]); + if (fromUsageMetadata != null) { + setValueByPath(toObject, ['usageMetadata'], fromUsageMetadata); + } + return toObject; +} +function generateImagesConfigToMldev(fromObject, parentObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['outputGcsUri']) !== undefined) { + throw new Error('outputGcsUri parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['negativePrompt']) !== undefined) { + throw new Error('negativePrompt parameter is not supported in Gemini API.'); + } + const fromNumberOfImages = getValueByPath(fromObject, [ + 'numberOfImages', + ]); + if (parentObject !== undefined && fromNumberOfImages != null) { + setValueByPath(parentObject, ['parameters', 'sampleCount'], fromNumberOfImages); + } + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (parentObject !== undefined && fromAspectRatio != null) { + setValueByPath(parentObject, ['parameters', 'aspectRatio'], fromAspectRatio); + } + const fromGuidanceScale = getValueByPath(fromObject, [ + 'guidanceScale', + ]); + if (parentObject !== undefined && fromGuidanceScale != null) { + setValueByPath(parentObject, ['parameters', 'guidanceScale'], fromGuidanceScale); + } + if (getValueByPath(fromObject, ['seed']) !== undefined) { + throw new Error('seed parameter is not supported in Gemini API.'); + } + const fromSafetyFilterLevel = getValueByPath(fromObject, [ + 'safetyFilterLevel', + ]); + if (parentObject !== undefined && fromSafetyFilterLevel != null) { + setValueByPath(parentObject, ['parameters', 'safetySetting'], fromSafetyFilterLevel); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (parentObject !== undefined && fromPersonGeneration != null) { + setValueByPath(parentObject, ['parameters', 'personGeneration'], fromPersonGeneration); + } + const fromIncludeSafetyAttributes = getValueByPath(fromObject, [ + 'includeSafetyAttributes', + ]); + if (parentObject !== undefined && fromIncludeSafetyAttributes != null) { + setValueByPath(parentObject, ['parameters', 'includeSafetyAttributes'], fromIncludeSafetyAttributes); + } + const fromIncludeRaiReason = getValueByPath(fromObject, [ + 'includeRaiReason', + ]); + if (parentObject !== undefined && fromIncludeRaiReason != null) { + setValueByPath(parentObject, ['parameters', 'includeRaiReason'], fromIncludeRaiReason); + } + const fromLanguage = getValueByPath(fromObject, ['language']); + if (parentObject !== undefined && fromLanguage != null) { + setValueByPath(parentObject, ['parameters', 'language'], fromLanguage); + } + const fromOutputMimeType = getValueByPath(fromObject, [ + 'outputMimeType', + ]); + if (parentObject !== undefined && fromOutputMimeType != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'mimeType'], fromOutputMimeType); + } + const fromOutputCompressionQuality = getValueByPath(fromObject, [ + 'outputCompressionQuality', + ]); + if (parentObject !== undefined && fromOutputCompressionQuality != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'compressionQuality'], fromOutputCompressionQuality); + } + if (getValueByPath(fromObject, ['addWatermark']) !== undefined) { + throw new Error('addWatermark parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['labels']) !== undefined) { + throw new Error('labels parameter is not supported in Gemini API.'); + } + const fromImageSize = getValueByPath(fromObject, ['imageSize']); + if (parentObject !== undefined && fromImageSize != null) { + setValueByPath(parentObject, ['parameters', 'sampleImageSize'], fromImageSize); + } + if (getValueByPath(fromObject, ['enhancePrompt']) !== undefined) { + throw new Error('enhancePrompt parameter is not supported in Gemini API.'); + } + return toObject; +} +function generateImagesConfigToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromOutputGcsUri = getValueByPath(fromObject, ['outputGcsUri']); + if (parentObject !== undefined && fromOutputGcsUri != null) { + setValueByPath(parentObject, ['parameters', 'storageUri'], fromOutputGcsUri); + } + const fromNegativePrompt = getValueByPath(fromObject, [ + 'negativePrompt', + ]); + if (parentObject !== undefined && fromNegativePrompt != null) { + setValueByPath(parentObject, ['parameters', 'negativePrompt'], fromNegativePrompt); + } + const fromNumberOfImages = getValueByPath(fromObject, [ + 'numberOfImages', + ]); + if (parentObject !== undefined && fromNumberOfImages != null) { + setValueByPath(parentObject, ['parameters', 'sampleCount'], fromNumberOfImages); + } + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (parentObject !== undefined && fromAspectRatio != null) { + setValueByPath(parentObject, ['parameters', 'aspectRatio'], fromAspectRatio); + } + const fromGuidanceScale = getValueByPath(fromObject, [ + 'guidanceScale', + ]); + if (parentObject !== undefined && fromGuidanceScale != null) { + setValueByPath(parentObject, ['parameters', 'guidanceScale'], fromGuidanceScale); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (parentObject !== undefined && fromSeed != null) { + setValueByPath(parentObject, ['parameters', 'seed'], fromSeed); + } + const fromSafetyFilterLevel = getValueByPath(fromObject, [ + 'safetyFilterLevel', + ]); + if (parentObject !== undefined && fromSafetyFilterLevel != null) { + setValueByPath(parentObject, ['parameters', 'safetySetting'], fromSafetyFilterLevel); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (parentObject !== undefined && fromPersonGeneration != null) { + setValueByPath(parentObject, ['parameters', 'personGeneration'], fromPersonGeneration); + } + const fromIncludeSafetyAttributes = getValueByPath(fromObject, [ + 'includeSafetyAttributes', + ]); + if (parentObject !== undefined && fromIncludeSafetyAttributes != null) { + setValueByPath(parentObject, ['parameters', 'includeSafetyAttributes'], fromIncludeSafetyAttributes); + } + const fromIncludeRaiReason = getValueByPath(fromObject, [ + 'includeRaiReason', + ]); + if (parentObject !== undefined && fromIncludeRaiReason != null) { + setValueByPath(parentObject, ['parameters', 'includeRaiReason'], fromIncludeRaiReason); + } + const fromLanguage = getValueByPath(fromObject, ['language']); + if (parentObject !== undefined && fromLanguage != null) { + setValueByPath(parentObject, ['parameters', 'language'], fromLanguage); + } + const fromOutputMimeType = getValueByPath(fromObject, [ + 'outputMimeType', + ]); + if (parentObject !== undefined && fromOutputMimeType != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'mimeType'], fromOutputMimeType); + } + const fromOutputCompressionQuality = getValueByPath(fromObject, [ + 'outputCompressionQuality', + ]); + if (parentObject !== undefined && fromOutputCompressionQuality != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'compressionQuality'], fromOutputCompressionQuality); + } + const fromAddWatermark = getValueByPath(fromObject, ['addWatermark']); + if (parentObject !== undefined && fromAddWatermark != null) { + setValueByPath(parentObject, ['parameters', 'addWatermark'], fromAddWatermark); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (parentObject !== undefined && fromLabels != null) { + setValueByPath(parentObject, ['labels'], fromLabels); + } + const fromImageSize = getValueByPath(fromObject, ['imageSize']); + if (parentObject !== undefined && fromImageSize != null) { + setValueByPath(parentObject, ['parameters', 'sampleImageSize'], fromImageSize); + } + const fromEnhancePrompt = getValueByPath(fromObject, [ + 'enhancePrompt', + ]); + if (parentObject !== undefined && fromEnhancePrompt != null) { + setValueByPath(parentObject, ['parameters', 'enhancePrompt'], fromEnhancePrompt); + } + return toObject; +} +function generateImagesParametersToMldev(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (fromPrompt != null) { + setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + generateImagesConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function generateImagesParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (fromPrompt != null) { + setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + generateImagesConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function generateImagesResponseFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromGeneratedImages = getValueByPath(fromObject, [ + 'predictions', + ]); + if (fromGeneratedImages != null) { + let transformedList = fromGeneratedImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedImageFromMldev(item); + }); + } + setValueByPath(toObject, ['generatedImages'], transformedList); + } + const fromPositivePromptSafetyAttributes = getValueByPath(fromObject, [ + 'positivePromptSafetyAttributes', + ]); + if (fromPositivePromptSafetyAttributes != null) { + setValueByPath(toObject, ['positivePromptSafetyAttributes'], safetyAttributesFromMldev(fromPositivePromptSafetyAttributes)); + } + return toObject; +} +function generateImagesResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromGeneratedImages = getValueByPath(fromObject, [ + 'predictions', + ]); + if (fromGeneratedImages != null) { + let transformedList = fromGeneratedImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedImageFromVertex(item); + }); + } + setValueByPath(toObject, ['generatedImages'], transformedList); + } + const fromPositivePromptSafetyAttributes = getValueByPath(fromObject, [ + 'positivePromptSafetyAttributes', + ]); + if (fromPositivePromptSafetyAttributes != null) { + setValueByPath(toObject, ['positivePromptSafetyAttributes'], safetyAttributesFromVertex(fromPositivePromptSafetyAttributes)); + } + return toObject; +} +function generateVideosConfigToMldev(fromObject, parentObject, rootObject) { + const toObject = {}; + const fromNumberOfVideos = getValueByPath(fromObject, [ + 'numberOfVideos', + ]); + if (parentObject !== undefined && fromNumberOfVideos != null) { + setValueByPath(parentObject, ['parameters', 'sampleCount'], fromNumberOfVideos); + } + if (getValueByPath(fromObject, ['outputGcsUri']) !== undefined) { + throw new Error('outputGcsUri parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['fps']) !== undefined) { + throw new Error('fps parameter is not supported in Gemini API.'); + } + const fromDurationSeconds = getValueByPath(fromObject, [ + 'durationSeconds', + ]); + if (parentObject !== undefined && fromDurationSeconds != null) { + setValueByPath(parentObject, ['parameters', 'durationSeconds'], fromDurationSeconds); + } + if (getValueByPath(fromObject, ['seed']) !== undefined) { + throw new Error('seed parameter is not supported in Gemini API.'); + } + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (parentObject !== undefined && fromAspectRatio != null) { + setValueByPath(parentObject, ['parameters', 'aspectRatio'], fromAspectRatio); + } + const fromResolution = getValueByPath(fromObject, ['resolution']); + if (parentObject !== undefined && fromResolution != null) { + setValueByPath(parentObject, ['parameters', 'resolution'], fromResolution); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (parentObject !== undefined && fromPersonGeneration != null) { + setValueByPath(parentObject, ['parameters', 'personGeneration'], fromPersonGeneration); + } + if (getValueByPath(fromObject, ['pubsubTopic']) !== undefined) { + throw new Error('pubsubTopic parameter is not supported in Gemini API.'); + } + const fromNegativePrompt = getValueByPath(fromObject, [ + 'negativePrompt', + ]); + if (parentObject !== undefined && fromNegativePrompt != null) { + setValueByPath(parentObject, ['parameters', 'negativePrompt'], fromNegativePrompt); + } + const fromEnhancePrompt = getValueByPath(fromObject, [ + 'enhancePrompt', + ]); + if (parentObject !== undefined && fromEnhancePrompt != null) { + setValueByPath(parentObject, ['parameters', 'enhancePrompt'], fromEnhancePrompt); + } + if (getValueByPath(fromObject, ['generateAudio']) !== undefined) { + throw new Error('generateAudio parameter is not supported in Gemini API.'); + } + const fromLastFrame = getValueByPath(fromObject, ['lastFrame']); + if (parentObject !== undefined && fromLastFrame != null) { + setValueByPath(parentObject, ['instances[0]', 'lastFrame'], imageToMldev(fromLastFrame)); + } + const fromReferenceImages = getValueByPath(fromObject, [ + 'referenceImages', + ]); + if (parentObject !== undefined && fromReferenceImages != null) { + let transformedList = fromReferenceImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return videoGenerationReferenceImageToMldev(item); + }); + } + setValueByPath(parentObject, ['instances[0]', 'referenceImages'], transformedList); + } + if (getValueByPath(fromObject, ['mask']) !== undefined) { + throw new Error('mask parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['compressionQuality']) !== undefined) { + throw new Error('compressionQuality parameter is not supported in Gemini API.'); + } + return toObject; +} +function generateVideosConfigToVertex(fromObject, parentObject, rootObject) { + const toObject = {}; + const fromNumberOfVideos = getValueByPath(fromObject, [ + 'numberOfVideos', + ]); + if (parentObject !== undefined && fromNumberOfVideos != null) { + setValueByPath(parentObject, ['parameters', 'sampleCount'], fromNumberOfVideos); + } + const fromOutputGcsUri = getValueByPath(fromObject, ['outputGcsUri']); + if (parentObject !== undefined && fromOutputGcsUri != null) { + setValueByPath(parentObject, ['parameters', 'storageUri'], fromOutputGcsUri); + } + const fromFps = getValueByPath(fromObject, ['fps']); + if (parentObject !== undefined && fromFps != null) { + setValueByPath(parentObject, ['parameters', 'fps'], fromFps); + } + const fromDurationSeconds = getValueByPath(fromObject, [ + 'durationSeconds', + ]); + if (parentObject !== undefined && fromDurationSeconds != null) { + setValueByPath(parentObject, ['parameters', 'durationSeconds'], fromDurationSeconds); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (parentObject !== undefined && fromSeed != null) { + setValueByPath(parentObject, ['parameters', 'seed'], fromSeed); + } + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (parentObject !== undefined && fromAspectRatio != null) { + setValueByPath(parentObject, ['parameters', 'aspectRatio'], fromAspectRatio); + } + const fromResolution = getValueByPath(fromObject, ['resolution']); + if (parentObject !== undefined && fromResolution != null) { + setValueByPath(parentObject, ['parameters', 'resolution'], fromResolution); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (parentObject !== undefined && fromPersonGeneration != null) { + setValueByPath(parentObject, ['parameters', 'personGeneration'], fromPersonGeneration); + } + const fromPubsubTopic = getValueByPath(fromObject, ['pubsubTopic']); + if (parentObject !== undefined && fromPubsubTopic != null) { + setValueByPath(parentObject, ['parameters', 'pubsubTopic'], fromPubsubTopic); + } + const fromNegativePrompt = getValueByPath(fromObject, [ + 'negativePrompt', + ]); + if (parentObject !== undefined && fromNegativePrompt != null) { + setValueByPath(parentObject, ['parameters', 'negativePrompt'], fromNegativePrompt); + } + const fromEnhancePrompt = getValueByPath(fromObject, [ + 'enhancePrompt', + ]); + if (parentObject !== undefined && fromEnhancePrompt != null) { + setValueByPath(parentObject, ['parameters', 'enhancePrompt'], fromEnhancePrompt); + } + const fromGenerateAudio = getValueByPath(fromObject, [ + 'generateAudio', + ]); + if (parentObject !== undefined && fromGenerateAudio != null) { + setValueByPath(parentObject, ['parameters', 'generateAudio'], fromGenerateAudio); + } + const fromLastFrame = getValueByPath(fromObject, ['lastFrame']); + if (parentObject !== undefined && fromLastFrame != null) { + setValueByPath(parentObject, ['instances[0]', 'lastFrame'], imageToVertex(fromLastFrame)); + } + const fromReferenceImages = getValueByPath(fromObject, [ + 'referenceImages', + ]); + if (parentObject !== undefined && fromReferenceImages != null) { + let transformedList = fromReferenceImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return videoGenerationReferenceImageToVertex(item); + }); + } + setValueByPath(parentObject, ['instances[0]', 'referenceImages'], transformedList); + } + const fromMask = getValueByPath(fromObject, ['mask']); + if (parentObject !== undefined && fromMask != null) { + setValueByPath(parentObject, ['instances[0]', 'mask'], videoGenerationMaskToVertex(fromMask)); + } + const fromCompressionQuality = getValueByPath(fromObject, [ + 'compressionQuality', + ]); + if (parentObject !== undefined && fromCompressionQuality != null) { + setValueByPath(parentObject, ['parameters', 'compressionQuality'], fromCompressionQuality); + } + return toObject; +} +function generateVideosOperationFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromResponse = getValueByPath(fromObject, [ + 'response', + 'generateVideoResponse', + ]); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], generateVideosResponseFromMldev(fromResponse)); + } + return toObject; +} +function generateVideosOperationFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], generateVideosResponseFromVertex(fromResponse)); + } + return toObject; +} +function generateVideosParametersToMldev(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (fromPrompt != null) { + setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromImage = getValueByPath(fromObject, ['image']); + if (fromImage != null) { + setValueByPath(toObject, ['instances[0]', 'image'], imageToMldev(fromImage)); + } + const fromVideo = getValueByPath(fromObject, ['video']); + if (fromVideo != null) { + setValueByPath(toObject, ['instances[0]', 'video'], videoToMldev(fromVideo)); + } + const fromSource = getValueByPath(fromObject, ['source']); + if (fromSource != null) { + generateVideosSourceToMldev(fromSource, toObject); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + generateVideosConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function generateVideosParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (fromPrompt != null) { + setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromImage = getValueByPath(fromObject, ['image']); + if (fromImage != null) { + setValueByPath(toObject, ['instances[0]', 'image'], imageToVertex(fromImage)); + } + const fromVideo = getValueByPath(fromObject, ['video']); + if (fromVideo != null) { + setValueByPath(toObject, ['instances[0]', 'video'], videoToVertex(fromVideo)); + } + const fromSource = getValueByPath(fromObject, ['source']); + if (fromSource != null) { + generateVideosSourceToVertex(fromSource, toObject); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + generateVideosConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function generateVideosResponseFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromGeneratedVideos = getValueByPath(fromObject, [ + 'generatedSamples', + ]); + if (fromGeneratedVideos != null) { + let transformedList = fromGeneratedVideos; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedVideoFromMldev(item); + }); + } + setValueByPath(toObject, ['generatedVideos'], transformedList); + } + const fromRaiMediaFilteredCount = getValueByPath(fromObject, [ + 'raiMediaFilteredCount', + ]); + if (fromRaiMediaFilteredCount != null) { + setValueByPath(toObject, ['raiMediaFilteredCount'], fromRaiMediaFilteredCount); + } + const fromRaiMediaFilteredReasons = getValueByPath(fromObject, [ + 'raiMediaFilteredReasons', + ]); + if (fromRaiMediaFilteredReasons != null) { + setValueByPath(toObject, ['raiMediaFilteredReasons'], fromRaiMediaFilteredReasons); + } + return toObject; +} +function generateVideosResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromGeneratedVideos = getValueByPath(fromObject, ['videos']); + if (fromGeneratedVideos != null) { + let transformedList = fromGeneratedVideos; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedVideoFromVertex(item); + }); + } + setValueByPath(toObject, ['generatedVideos'], transformedList); + } + const fromRaiMediaFilteredCount = getValueByPath(fromObject, [ + 'raiMediaFilteredCount', + ]); + if (fromRaiMediaFilteredCount != null) { + setValueByPath(toObject, ['raiMediaFilteredCount'], fromRaiMediaFilteredCount); + } + const fromRaiMediaFilteredReasons = getValueByPath(fromObject, [ + 'raiMediaFilteredReasons', + ]); + if (fromRaiMediaFilteredReasons != null) { + setValueByPath(toObject, ['raiMediaFilteredReasons'], fromRaiMediaFilteredReasons); + } + return toObject; +} +function generateVideosSourceToMldev(fromObject, parentObject, rootObject) { + const toObject = {}; + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (parentObject !== undefined && fromPrompt != null) { + setValueByPath(parentObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromImage = getValueByPath(fromObject, ['image']); + if (parentObject !== undefined && fromImage != null) { + setValueByPath(parentObject, ['instances[0]', 'image'], imageToMldev(fromImage)); + } + const fromVideo = getValueByPath(fromObject, ['video']); + if (parentObject !== undefined && fromVideo != null) { + setValueByPath(parentObject, ['instances[0]', 'video'], videoToMldev(fromVideo)); + } + return toObject; +} +function generateVideosSourceToVertex(fromObject, parentObject, rootObject) { + const toObject = {}; + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (parentObject !== undefined && fromPrompt != null) { + setValueByPath(parentObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromImage = getValueByPath(fromObject, ['image']); + if (parentObject !== undefined && fromImage != null) { + setValueByPath(parentObject, ['instances[0]', 'image'], imageToVertex(fromImage)); + } + const fromVideo = getValueByPath(fromObject, ['video']); + if (parentObject !== undefined && fromVideo != null) { + setValueByPath(parentObject, ['instances[0]', 'video'], videoToVertex(fromVideo)); + } + return toObject; +} +function generatedImageFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromImage = getValueByPath(fromObject, ['_self']); + if (fromImage != null) { + setValueByPath(toObject, ['image'], imageFromMldev(fromImage)); + } + const fromRaiFilteredReason = getValueByPath(fromObject, [ + 'raiFilteredReason', + ]); + if (fromRaiFilteredReason != null) { + setValueByPath(toObject, ['raiFilteredReason'], fromRaiFilteredReason); + } + const fromSafetyAttributes = getValueByPath(fromObject, ['_self']); + if (fromSafetyAttributes != null) { + setValueByPath(toObject, ['safetyAttributes'], safetyAttributesFromMldev(fromSafetyAttributes)); + } + return toObject; +} +function generatedImageFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromImage = getValueByPath(fromObject, ['_self']); + if (fromImage != null) { + setValueByPath(toObject, ['image'], imageFromVertex(fromImage)); + } + const fromRaiFilteredReason = getValueByPath(fromObject, [ + 'raiFilteredReason', + ]); + if (fromRaiFilteredReason != null) { + setValueByPath(toObject, ['raiFilteredReason'], fromRaiFilteredReason); + } + const fromSafetyAttributes = getValueByPath(fromObject, ['_self']); + if (fromSafetyAttributes != null) { + setValueByPath(toObject, ['safetyAttributes'], safetyAttributesFromVertex(fromSafetyAttributes)); + } + const fromEnhancedPrompt = getValueByPath(fromObject, ['prompt']); + if (fromEnhancedPrompt != null) { + setValueByPath(toObject, ['enhancedPrompt'], fromEnhancedPrompt); + } + return toObject; +} +function generatedImageMaskFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromMask = getValueByPath(fromObject, ['_self']); + if (fromMask != null) { + setValueByPath(toObject, ['mask'], imageFromVertex(fromMask)); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (fromLabels != null) { + let transformedList = fromLabels; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['labels'], transformedList); + } + return toObject; +} +function generatedVideoFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromVideo = getValueByPath(fromObject, ['video']); + if (fromVideo != null) { + setValueByPath(toObject, ['video'], videoFromMldev(fromVideo)); + } + return toObject; +} +function generatedVideoFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromVideo = getValueByPath(fromObject, ['_self']); + if (fromVideo != null) { + setValueByPath(toObject, ['video'], videoFromVertex(fromVideo)); + } + return toObject; +} +function generationConfigToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromModelSelectionConfig = getValueByPath(fromObject, [ + 'modelSelectionConfig', + ]); + if (fromModelSelectionConfig != null) { + setValueByPath(toObject, ['modelConfig'], fromModelSelectionConfig); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + const fromAudioTimestamp = getValueByPath(fromObject, [ + 'audioTimestamp', + ]); + if (fromAudioTimestamp != null) { + setValueByPath(toObject, ['audioTimestamp'], fromAudioTimestamp); + } + const fromCandidateCount = getValueByPath(fromObject, [ + 'candidateCount', + ]); + if (fromCandidateCount != null) { + setValueByPath(toObject, ['candidateCount'], fromCandidateCount); + } + const fromEnableAffectiveDialog = getValueByPath(fromObject, [ + 'enableAffectiveDialog', + ]); + if (fromEnableAffectiveDialog != null) { + setValueByPath(toObject, ['enableAffectiveDialog'], fromEnableAffectiveDialog); + } + const fromFrequencyPenalty = getValueByPath(fromObject, [ + 'frequencyPenalty', + ]); + if (fromFrequencyPenalty != null) { + setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty); + } + const fromLogprobs = getValueByPath(fromObject, ['logprobs']); + if (fromLogprobs != null) { + setValueByPath(toObject, ['logprobs'], fromLogprobs); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (fromMaxOutputTokens != null) { + setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromPresencePenalty = getValueByPath(fromObject, [ + 'presencePenalty', + ]); + if (fromPresencePenalty != null) { + setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty); + } + const fromResponseLogprobs = getValueByPath(fromObject, [ + 'responseLogprobs', + ]); + if (fromResponseLogprobs != null) { + setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs); + } + const fromResponseMimeType = getValueByPath(fromObject, [ + 'responseMimeType', + ]); + if (fromResponseMimeType != null) { + setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (fromResponseModalities != null) { + setValueByPath(toObject, ['responseModalities'], fromResponseModalities); + } + const fromResponseSchema = getValueByPath(fromObject, [ + 'responseSchema', + ]); + if (fromResponseSchema != null) { + setValueByPath(toObject, ['responseSchema'], fromResponseSchema); + } + const fromRoutingConfig = getValueByPath(fromObject, [ + 'routingConfig', + ]); + if (fromRoutingConfig != null) { + setValueByPath(toObject, ['routingConfig'], fromRoutingConfig); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (fromSeed != null) { + setValueByPath(toObject, ['seed'], fromSeed); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (fromSpeechConfig != null) { + setValueByPath(toObject, ['speechConfig'], fromSpeechConfig); + } + const fromStopSequences = getValueByPath(fromObject, [ + 'stopSequences', + ]); + if (fromStopSequences != null) { + setValueByPath(toObject, ['stopSequences'], fromStopSequences); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (fromTemperature != null) { + setValueByPath(toObject, ['temperature'], fromTemperature); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (fromThinkingConfig != null) { + setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (fromTopK != null) { + setValueByPath(toObject, ['topK'], fromTopK); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (fromTopP != null) { + setValueByPath(toObject, ['topP'], fromTopP); + } + if (getValueByPath(fromObject, ['enableEnhancedCivicAnswers']) !== + undefined) { + throw new Error('enableEnhancedCivicAnswers parameter is not supported in Vertex AI.'); + } + return toObject; +} +function getModelParametersToMldev(apiClient, fromObject, _rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'name'], tModel(apiClient, fromModel)); + } + return toObject; +} +function getModelParametersToVertex(apiClient, fromObject, _rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'name'], tModel(apiClient, fromModel)); + } + return toObject; +} +function googleMapsToMldev$1(fromObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['authConfig']) !== undefined) { + throw new Error('authConfig parameter is not supported in Gemini API.'); + } + const fromEnableWidget = getValueByPath(fromObject, ['enableWidget']); + if (fromEnableWidget != null) { + setValueByPath(toObject, ['enableWidget'], fromEnableWidget); + } + return toObject; +} +function googleSearchToMldev$1(fromObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['excludeDomains']) !== undefined) { + throw new Error('excludeDomains parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['blockingConfidence']) !== undefined) { + throw new Error('blockingConfidence parameter is not supported in Gemini API.'); + } + const fromTimeRangeFilter = getValueByPath(fromObject, [ + 'timeRangeFilter', + ]); + if (fromTimeRangeFilter != null) { + setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter); + } + return toObject; +} +function imageConfigToMldev(fromObject, _rootObject) { + const toObject = {}; + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (fromAspectRatio != null) { + setValueByPath(toObject, ['aspectRatio'], fromAspectRatio); + } + const fromImageSize = getValueByPath(fromObject, ['imageSize']); + if (fromImageSize != null) { + setValueByPath(toObject, ['imageSize'], fromImageSize); + } + if (getValueByPath(fromObject, ['personGeneration']) !== undefined) { + throw new Error('personGeneration parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['outputMimeType']) !== undefined) { + throw new Error('outputMimeType parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['outputCompressionQuality']) !== + undefined) { + throw new Error('outputCompressionQuality parameter is not supported in Gemini API.'); + } + return toObject; +} +function imageConfigToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (fromAspectRatio != null) { + setValueByPath(toObject, ['aspectRatio'], fromAspectRatio); + } + const fromImageSize = getValueByPath(fromObject, ['imageSize']); + if (fromImageSize != null) { + setValueByPath(toObject, ['imageSize'], fromImageSize); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (fromPersonGeneration != null) { + setValueByPath(toObject, ['personGeneration'], fromPersonGeneration); + } + const fromOutputMimeType = getValueByPath(fromObject, [ + 'outputMimeType', + ]); + if (fromOutputMimeType != null) { + setValueByPath(toObject, ['imageOutputOptions', 'mimeType'], fromOutputMimeType); + } + const fromOutputCompressionQuality = getValueByPath(fromObject, [ + 'outputCompressionQuality', + ]); + if (fromOutputCompressionQuality != null) { + setValueByPath(toObject, ['imageOutputOptions', 'compressionQuality'], fromOutputCompressionQuality); + } + return toObject; +} +function imageFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromImageBytes = getValueByPath(fromObject, [ + 'bytesBase64Encoded', + ]); + if (fromImageBytes != null) { + setValueByPath(toObject, ['imageBytes'], tBytes(fromImageBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function imageFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (fromGcsUri != null) { + setValueByPath(toObject, ['gcsUri'], fromGcsUri); + } + const fromImageBytes = getValueByPath(fromObject, [ + 'bytesBase64Encoded', + ]); + if (fromImageBytes != null) { + setValueByPath(toObject, ['imageBytes'], tBytes(fromImageBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function imageToMldev(fromObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['gcsUri']) !== undefined) { + throw new Error('gcsUri parameter is not supported in Gemini API.'); + } + const fromImageBytes = getValueByPath(fromObject, ['imageBytes']); + if (fromImageBytes != null) { + setValueByPath(toObject, ['bytesBase64Encoded'], tBytes(fromImageBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function imageToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (fromGcsUri != null) { + setValueByPath(toObject, ['gcsUri'], fromGcsUri); + } + const fromImageBytes = getValueByPath(fromObject, ['imageBytes']); + if (fromImageBytes != null) { + setValueByPath(toObject, ['bytesBase64Encoded'], tBytes(fromImageBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function listModelsConfigToMldev(apiClient, fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + const fromFilter = getValueByPath(fromObject, ['filter']); + if (parentObject !== undefined && fromFilter != null) { + setValueByPath(parentObject, ['_query', 'filter'], fromFilter); + } + const fromQueryBase = getValueByPath(fromObject, ['queryBase']); + if (parentObject !== undefined && fromQueryBase != null) { + setValueByPath(parentObject, ['_url', 'models_url'], tModelsUrl(apiClient, fromQueryBase)); + } + return toObject; +} +function listModelsConfigToVertex(apiClient, fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + const fromFilter = getValueByPath(fromObject, ['filter']); + if (parentObject !== undefined && fromFilter != null) { + setValueByPath(parentObject, ['_query', 'filter'], fromFilter); + } + const fromQueryBase = getValueByPath(fromObject, ['queryBase']); + if (parentObject !== undefined && fromQueryBase != null) { + setValueByPath(parentObject, ['_url', 'models_url'], tModelsUrl(apiClient, fromQueryBase)); + } + return toObject; +} +function listModelsParametersToMldev(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listModelsConfigToMldev(apiClient, fromConfig, toObject); + } + return toObject; +} +function listModelsParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listModelsConfigToVertex(apiClient, fromConfig, toObject); + } + return toObject; +} +function listModelsResponseFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromModels = getValueByPath(fromObject, ['_self']); + if (fromModels != null) { + let transformedList = tExtractModels(fromModels); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return modelFromMldev(item); + }); + } + setValueByPath(toObject, ['models'], transformedList); + } + return toObject; +} +function listModelsResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromModels = getValueByPath(fromObject, ['_self']); + if (fromModels != null) { + let transformedList = tExtractModels(fromModels); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return modelFromVertex(item); + }); + } + setValueByPath(toObject, ['models'], transformedList); + } + return toObject; +} +function maskReferenceConfigToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromMaskMode = getValueByPath(fromObject, ['maskMode']); + if (fromMaskMode != null) { + setValueByPath(toObject, ['maskMode'], fromMaskMode); + } + const fromSegmentationClasses = getValueByPath(fromObject, [ + 'segmentationClasses', + ]); + if (fromSegmentationClasses != null) { + setValueByPath(toObject, ['maskClasses'], fromSegmentationClasses); + } + const fromMaskDilation = getValueByPath(fromObject, ['maskDilation']); + if (fromMaskDilation != null) { + setValueByPath(toObject, ['dilation'], fromMaskDilation); + } + return toObject; +} +function modelFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (fromDisplayName != null) { + setValueByPath(toObject, ['displayName'], fromDisplayName); + } + const fromDescription = getValueByPath(fromObject, ['description']); + if (fromDescription != null) { + setValueByPath(toObject, ['description'], fromDescription); + } + const fromVersion = getValueByPath(fromObject, ['version']); + if (fromVersion != null) { + setValueByPath(toObject, ['version'], fromVersion); + } + const fromTunedModelInfo = getValueByPath(fromObject, ['_self']); + if (fromTunedModelInfo != null) { + setValueByPath(toObject, ['tunedModelInfo'], tunedModelInfoFromMldev(fromTunedModelInfo)); + } + const fromInputTokenLimit = getValueByPath(fromObject, [ + 'inputTokenLimit', + ]); + if (fromInputTokenLimit != null) { + setValueByPath(toObject, ['inputTokenLimit'], fromInputTokenLimit); + } + const fromOutputTokenLimit = getValueByPath(fromObject, [ + 'outputTokenLimit', + ]); + if (fromOutputTokenLimit != null) { + setValueByPath(toObject, ['outputTokenLimit'], fromOutputTokenLimit); + } + const fromSupportedActions = getValueByPath(fromObject, [ + 'supportedGenerationMethods', + ]); + if (fromSupportedActions != null) { + setValueByPath(toObject, ['supportedActions'], fromSupportedActions); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (fromTemperature != null) { + setValueByPath(toObject, ['temperature'], fromTemperature); + } + const fromMaxTemperature = getValueByPath(fromObject, [ + 'maxTemperature', + ]); + if (fromMaxTemperature != null) { + setValueByPath(toObject, ['maxTemperature'], fromMaxTemperature); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (fromTopP != null) { + setValueByPath(toObject, ['topP'], fromTopP); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (fromTopK != null) { + setValueByPath(toObject, ['topK'], fromTopK); + } + const fromThinking = getValueByPath(fromObject, ['thinking']); + if (fromThinking != null) { + setValueByPath(toObject, ['thinking'], fromThinking); + } + return toObject; +} +function modelFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (fromDisplayName != null) { + setValueByPath(toObject, ['displayName'], fromDisplayName); + } + const fromDescription = getValueByPath(fromObject, ['description']); + if (fromDescription != null) { + setValueByPath(toObject, ['description'], fromDescription); + } + const fromVersion = getValueByPath(fromObject, ['versionId']); + if (fromVersion != null) { + setValueByPath(toObject, ['version'], fromVersion); + } + const fromEndpoints = getValueByPath(fromObject, ['deployedModels']); + if (fromEndpoints != null) { + let transformedList = fromEndpoints; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return endpointFromVertex(item); + }); + } + setValueByPath(toObject, ['endpoints'], transformedList); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (fromLabels != null) { + setValueByPath(toObject, ['labels'], fromLabels); + } + const fromTunedModelInfo = getValueByPath(fromObject, ['_self']); + if (fromTunedModelInfo != null) { + setValueByPath(toObject, ['tunedModelInfo'], tunedModelInfoFromVertex(fromTunedModelInfo)); + } + const fromDefaultCheckpointId = getValueByPath(fromObject, [ + 'defaultCheckpointId', + ]); + if (fromDefaultCheckpointId != null) { + setValueByPath(toObject, ['defaultCheckpointId'], fromDefaultCheckpointId); + } + const fromCheckpoints = getValueByPath(fromObject, ['checkpoints']); + if (fromCheckpoints != null) { + let transformedList = fromCheckpoints; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['checkpoints'], transformedList); + } + return toObject; +} +function partToMldev$1(fromObject, rootObject) { + const toObject = {}; + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromCodeExecutionResult = getValueByPath(fromObject, [ + 'codeExecutionResult', + ]); + if (fromCodeExecutionResult != null) { + setValueByPath(toObject, ['codeExecutionResult'], fromCodeExecutionResult); + } + const fromExecutableCode = getValueByPath(fromObject, [ + 'executableCode', + ]); + if (fromExecutableCode != null) { + setValueByPath(toObject, ['executableCode'], fromExecutableCode); + } + const fromFileData = getValueByPath(fromObject, ['fileData']); + if (fromFileData != null) { + setValueByPath(toObject, ['fileData'], fileDataToMldev$1(fromFileData)); + } + const fromFunctionCall = getValueByPath(fromObject, ['functionCall']); + if (fromFunctionCall != null) { + setValueByPath(toObject, ['functionCall'], functionCallToMldev$1(fromFunctionCall)); + } + const fromFunctionResponse = getValueByPath(fromObject, [ + 'functionResponse', + ]); + if (fromFunctionResponse != null) { + setValueByPath(toObject, ['functionResponse'], fromFunctionResponse); + } + const fromInlineData = getValueByPath(fromObject, ['inlineData']); + if (fromInlineData != null) { + setValueByPath(toObject, ['inlineData'], blobToMldev$1(fromInlineData)); + } + const fromText = getValueByPath(fromObject, ['text']); + if (fromText != null) { + setValueByPath(toObject, ['text'], fromText); + } + const fromThought = getValueByPath(fromObject, ['thought']); + if (fromThought != null) { + setValueByPath(toObject, ['thought'], fromThought); + } + const fromThoughtSignature = getValueByPath(fromObject, [ + 'thoughtSignature', + ]); + if (fromThoughtSignature != null) { + setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature); + } + const fromVideoMetadata = getValueByPath(fromObject, [ + 'videoMetadata', + ]); + if (fromVideoMetadata != null) { + setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata); + } + return toObject; +} +function productImageToVertex(fromObject, rootObject) { + const toObject = {}; + const fromProductImage = getValueByPath(fromObject, ['productImage']); + if (fromProductImage != null) { + setValueByPath(toObject, ['image'], imageToVertex(fromProductImage)); + } + return toObject; +} +function recontextImageConfigToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromNumberOfImages = getValueByPath(fromObject, [ + 'numberOfImages', + ]); + if (parentObject !== undefined && fromNumberOfImages != null) { + setValueByPath(parentObject, ['parameters', 'sampleCount'], fromNumberOfImages); + } + const fromBaseSteps = getValueByPath(fromObject, ['baseSteps']); + if (parentObject !== undefined && fromBaseSteps != null) { + setValueByPath(parentObject, ['parameters', 'baseSteps'], fromBaseSteps); + } + const fromOutputGcsUri = getValueByPath(fromObject, ['outputGcsUri']); + if (parentObject !== undefined && fromOutputGcsUri != null) { + setValueByPath(parentObject, ['parameters', 'storageUri'], fromOutputGcsUri); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (parentObject !== undefined && fromSeed != null) { + setValueByPath(parentObject, ['parameters', 'seed'], fromSeed); + } + const fromSafetyFilterLevel = getValueByPath(fromObject, [ + 'safetyFilterLevel', + ]); + if (parentObject !== undefined && fromSafetyFilterLevel != null) { + setValueByPath(parentObject, ['parameters', 'safetySetting'], fromSafetyFilterLevel); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (parentObject !== undefined && fromPersonGeneration != null) { + setValueByPath(parentObject, ['parameters', 'personGeneration'], fromPersonGeneration); + } + const fromAddWatermark = getValueByPath(fromObject, ['addWatermark']); + if (parentObject !== undefined && fromAddWatermark != null) { + setValueByPath(parentObject, ['parameters', 'addWatermark'], fromAddWatermark); + } + const fromOutputMimeType = getValueByPath(fromObject, [ + 'outputMimeType', + ]); + if (parentObject !== undefined && fromOutputMimeType != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'mimeType'], fromOutputMimeType); + } + const fromOutputCompressionQuality = getValueByPath(fromObject, [ + 'outputCompressionQuality', + ]); + if (parentObject !== undefined && fromOutputCompressionQuality != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'compressionQuality'], fromOutputCompressionQuality); + } + const fromEnhancePrompt = getValueByPath(fromObject, [ + 'enhancePrompt', + ]); + if (parentObject !== undefined && fromEnhancePrompt != null) { + setValueByPath(parentObject, ['parameters', 'enhancePrompt'], fromEnhancePrompt); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (parentObject !== undefined && fromLabels != null) { + setValueByPath(parentObject, ['labels'], fromLabels); + } + return toObject; +} +function recontextImageParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromSource = getValueByPath(fromObject, ['source']); + if (fromSource != null) { + recontextImageSourceToVertex(fromSource, toObject); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + recontextImageConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function recontextImageResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromGeneratedImages = getValueByPath(fromObject, [ + 'predictions', + ]); + if (fromGeneratedImages != null) { + let transformedList = fromGeneratedImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedImageFromVertex(item); + }); + } + setValueByPath(toObject, ['generatedImages'], transformedList); + } + return toObject; +} +function recontextImageSourceToVertex(fromObject, parentObject, rootObject) { + const toObject = {}; + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (parentObject !== undefined && fromPrompt != null) { + setValueByPath(parentObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromPersonImage = getValueByPath(fromObject, ['personImage']); + if (parentObject !== undefined && fromPersonImage != null) { + setValueByPath(parentObject, ['instances[0]', 'personImage', 'image'], imageToVertex(fromPersonImage)); + } + const fromProductImages = getValueByPath(fromObject, [ + 'productImages', + ]); + if (parentObject !== undefined && fromProductImages != null) { + let transformedList = fromProductImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return productImageToVertex(item); + }); + } + setValueByPath(parentObject, ['instances[0]', 'productImages'], transformedList); + } + return toObject; +} +function referenceImageAPIInternalToVertex(fromObject, rootObject) { + const toObject = {}; + const fromReferenceImage = getValueByPath(fromObject, [ + 'referenceImage', + ]); + if (fromReferenceImage != null) { + setValueByPath(toObject, ['referenceImage'], imageToVertex(fromReferenceImage)); + } + const fromReferenceId = getValueByPath(fromObject, ['referenceId']); + if (fromReferenceId != null) { + setValueByPath(toObject, ['referenceId'], fromReferenceId); + } + const fromReferenceType = getValueByPath(fromObject, [ + 'referenceType', + ]); + if (fromReferenceType != null) { + setValueByPath(toObject, ['referenceType'], fromReferenceType); + } + const fromMaskImageConfig = getValueByPath(fromObject, [ + 'maskImageConfig', + ]); + if (fromMaskImageConfig != null) { + setValueByPath(toObject, ['maskImageConfig'], maskReferenceConfigToVertex(fromMaskImageConfig)); + } + const fromControlImageConfig = getValueByPath(fromObject, [ + 'controlImageConfig', + ]); + if (fromControlImageConfig != null) { + setValueByPath(toObject, ['controlImageConfig'], controlReferenceConfigToVertex(fromControlImageConfig)); + } + const fromStyleImageConfig = getValueByPath(fromObject, [ + 'styleImageConfig', + ]); + if (fromStyleImageConfig != null) { + setValueByPath(toObject, ['styleImageConfig'], fromStyleImageConfig); + } + const fromSubjectImageConfig = getValueByPath(fromObject, [ + 'subjectImageConfig', + ]); + if (fromSubjectImageConfig != null) { + setValueByPath(toObject, ['subjectImageConfig'], fromSubjectImageConfig); + } + return toObject; +} +function safetyAttributesFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromCategories = getValueByPath(fromObject, [ + 'safetyAttributes', + 'categories', + ]); + if (fromCategories != null) { + setValueByPath(toObject, ['categories'], fromCategories); + } + const fromScores = getValueByPath(fromObject, [ + 'safetyAttributes', + 'scores', + ]); + if (fromScores != null) { + setValueByPath(toObject, ['scores'], fromScores); + } + const fromContentType = getValueByPath(fromObject, ['contentType']); + if (fromContentType != null) { + setValueByPath(toObject, ['contentType'], fromContentType); + } + return toObject; +} +function safetyAttributesFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromCategories = getValueByPath(fromObject, [ + 'safetyAttributes', + 'categories', + ]); + if (fromCategories != null) { + setValueByPath(toObject, ['categories'], fromCategories); + } + const fromScores = getValueByPath(fromObject, [ + 'safetyAttributes', + 'scores', + ]); + if (fromScores != null) { + setValueByPath(toObject, ['scores'], fromScores); + } + const fromContentType = getValueByPath(fromObject, ['contentType']); + if (fromContentType != null) { + setValueByPath(toObject, ['contentType'], fromContentType); + } + return toObject; +} +function safetySettingToMldev(fromObject, _rootObject) { + const toObject = {}; + const fromCategory = getValueByPath(fromObject, ['category']); + if (fromCategory != null) { + setValueByPath(toObject, ['category'], fromCategory); + } + if (getValueByPath(fromObject, ['method']) !== undefined) { + throw new Error('method parameter is not supported in Gemini API.'); + } + const fromThreshold = getValueByPath(fromObject, ['threshold']); + if (fromThreshold != null) { + setValueByPath(toObject, ['threshold'], fromThreshold); + } + return toObject; +} +function scribbleImageToVertex(fromObject, rootObject) { + const toObject = {}; + const fromImage = getValueByPath(fromObject, ['image']); + if (fromImage != null) { + setValueByPath(toObject, ['image'], imageToVertex(fromImage)); + } + return toObject; +} +function segmentImageConfigToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromMode = getValueByPath(fromObject, ['mode']); + if (parentObject !== undefined && fromMode != null) { + setValueByPath(parentObject, ['parameters', 'mode'], fromMode); + } + const fromMaxPredictions = getValueByPath(fromObject, [ + 'maxPredictions', + ]); + if (parentObject !== undefined && fromMaxPredictions != null) { + setValueByPath(parentObject, ['parameters', 'maxPredictions'], fromMaxPredictions); + } + const fromConfidenceThreshold = getValueByPath(fromObject, [ + 'confidenceThreshold', + ]); + if (parentObject !== undefined && fromConfidenceThreshold != null) { + setValueByPath(parentObject, ['parameters', 'confidenceThreshold'], fromConfidenceThreshold); + } + const fromMaskDilation = getValueByPath(fromObject, ['maskDilation']); + if (parentObject !== undefined && fromMaskDilation != null) { + setValueByPath(parentObject, ['parameters', 'maskDilation'], fromMaskDilation); + } + const fromBinaryColorThreshold = getValueByPath(fromObject, [ + 'binaryColorThreshold', + ]); + if (parentObject !== undefined && fromBinaryColorThreshold != null) { + setValueByPath(parentObject, ['parameters', 'binaryColorThreshold'], fromBinaryColorThreshold); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (parentObject !== undefined && fromLabels != null) { + setValueByPath(parentObject, ['labels'], fromLabels); + } + return toObject; +} +function segmentImageParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromSource = getValueByPath(fromObject, ['source']); + if (fromSource != null) { + segmentImageSourceToVertex(fromSource, toObject); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + segmentImageConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function segmentImageResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromGeneratedMasks = getValueByPath(fromObject, ['predictions']); + if (fromGeneratedMasks != null) { + let transformedList = fromGeneratedMasks; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedImageMaskFromVertex(item); + }); + } + setValueByPath(toObject, ['generatedMasks'], transformedList); + } + return toObject; +} +function segmentImageSourceToVertex(fromObject, parentObject, rootObject) { + const toObject = {}; + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (parentObject !== undefined && fromPrompt != null) { + setValueByPath(parentObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromImage = getValueByPath(fromObject, ['image']); + if (parentObject !== undefined && fromImage != null) { + setValueByPath(parentObject, ['instances[0]', 'image'], imageToVertex(fromImage)); + } + const fromScribbleImage = getValueByPath(fromObject, [ + 'scribbleImage', + ]); + if (parentObject !== undefined && fromScribbleImage != null) { + setValueByPath(parentObject, ['instances[0]', 'scribble'], scribbleImageToVertex(fromScribbleImage)); + } + return toObject; +} +function toolConfigToMldev(fromObject, rootObject) { + const toObject = {}; + const fromRetrievalConfig = getValueByPath(fromObject, [ + 'retrievalConfig', + ]); + if (fromRetrievalConfig != null) { + setValueByPath(toObject, ['retrievalConfig'], fromRetrievalConfig); + } + const fromFunctionCallingConfig = getValueByPath(fromObject, [ + 'functionCallingConfig', + ]); + if (fromFunctionCallingConfig != null) { + setValueByPath(toObject, ['functionCallingConfig'], functionCallingConfigToMldev(fromFunctionCallingConfig)); + } + return toObject; +} +function toolToMldev$1(fromObject, rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['retrieval']) !== undefined) { + throw new Error('retrieval parameter is not supported in Gemini API.'); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + const fromFileSearch = getValueByPath(fromObject, ['fileSearch']); + if (fromFileSearch != null) { + setValueByPath(toObject, ['fileSearch'], fromFileSearch); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + if (getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined) { + throw new Error('enterpriseWebSearch parameter is not supported in Gemini API.'); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], googleMapsToMldev$1(fromGoogleMaps)); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], googleSearchToMldev$1(fromGoogleSearch)); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} +function toolToVertex(fromObject, rootObject) { + const toObject = {}; + const fromRetrieval = getValueByPath(fromObject, ['retrieval']); + if (fromRetrieval != null) { + setValueByPath(toObject, ['retrieval'], fromRetrieval); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + if (getValueByPath(fromObject, ['fileSearch']) !== undefined) { + throw new Error('fileSearch parameter is not supported in Vertex AI.'); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + const fromEnterpriseWebSearch = getValueByPath(fromObject, [ + 'enterpriseWebSearch', + ]); + if (fromEnterpriseWebSearch != null) { + setValueByPath(toObject, ['enterpriseWebSearch'], fromEnterpriseWebSearch); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return functionDeclarationToVertex(item); + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], fromGoogleMaps); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], fromGoogleSearch); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} +function tunedModelInfoFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromBaseModel = getValueByPath(fromObject, ['baseModel']); + if (fromBaseModel != null) { + setValueByPath(toObject, ['baseModel'], fromBaseModel); + } + const fromCreateTime = getValueByPath(fromObject, ['createTime']); + if (fromCreateTime != null) { + setValueByPath(toObject, ['createTime'], fromCreateTime); + } + const fromUpdateTime = getValueByPath(fromObject, ['updateTime']); + if (fromUpdateTime != null) { + setValueByPath(toObject, ['updateTime'], fromUpdateTime); + } + return toObject; +} +function tunedModelInfoFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromBaseModel = getValueByPath(fromObject, [ + 'labels', + 'google-vertex-llm-tuning-base-model-id', + ]); + if (fromBaseModel != null) { + setValueByPath(toObject, ['baseModel'], fromBaseModel); + } + const fromCreateTime = getValueByPath(fromObject, ['createTime']); + if (fromCreateTime != null) { + setValueByPath(toObject, ['createTime'], fromCreateTime); + } + const fromUpdateTime = getValueByPath(fromObject, ['updateTime']); + if (fromUpdateTime != null) { + setValueByPath(toObject, ['updateTime'], fromUpdateTime); + } + return toObject; +} +function updateModelConfigToMldev(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromDisplayName); + } + const fromDescription = getValueByPath(fromObject, ['description']); + if (parentObject !== undefined && fromDescription != null) { + setValueByPath(parentObject, ['description'], fromDescription); + } + const fromDefaultCheckpointId = getValueByPath(fromObject, [ + 'defaultCheckpointId', + ]); + if (parentObject !== undefined && fromDefaultCheckpointId != null) { + setValueByPath(parentObject, ['defaultCheckpointId'], fromDefaultCheckpointId); + } + return toObject; +} +function updateModelConfigToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromDisplayName); + } + const fromDescription = getValueByPath(fromObject, ['description']); + if (parentObject !== undefined && fromDescription != null) { + setValueByPath(parentObject, ['description'], fromDescription); + } + const fromDefaultCheckpointId = getValueByPath(fromObject, [ + 'defaultCheckpointId', + ]); + if (parentObject !== undefined && fromDefaultCheckpointId != null) { + setValueByPath(parentObject, ['defaultCheckpointId'], fromDefaultCheckpointId); + } + return toObject; +} +function updateModelParametersToMldev(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'name'], tModel(apiClient, fromModel)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + updateModelConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function updateModelParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + updateModelConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function upscaleImageAPIConfigInternalToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromOutputGcsUri = getValueByPath(fromObject, ['outputGcsUri']); + if (parentObject !== undefined && fromOutputGcsUri != null) { + setValueByPath(parentObject, ['parameters', 'storageUri'], fromOutputGcsUri); + } + const fromSafetyFilterLevel = getValueByPath(fromObject, [ + 'safetyFilterLevel', + ]); + if (parentObject !== undefined && fromSafetyFilterLevel != null) { + setValueByPath(parentObject, ['parameters', 'safetySetting'], fromSafetyFilterLevel); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (parentObject !== undefined && fromPersonGeneration != null) { + setValueByPath(parentObject, ['parameters', 'personGeneration'], fromPersonGeneration); + } + const fromIncludeRaiReason = getValueByPath(fromObject, [ + 'includeRaiReason', + ]); + if (parentObject !== undefined && fromIncludeRaiReason != null) { + setValueByPath(parentObject, ['parameters', 'includeRaiReason'], fromIncludeRaiReason); + } + const fromOutputMimeType = getValueByPath(fromObject, [ + 'outputMimeType', + ]); + if (parentObject !== undefined && fromOutputMimeType != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'mimeType'], fromOutputMimeType); + } + const fromOutputCompressionQuality = getValueByPath(fromObject, [ + 'outputCompressionQuality', + ]); + if (parentObject !== undefined && fromOutputCompressionQuality != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'compressionQuality'], fromOutputCompressionQuality); + } + const fromEnhanceInputImage = getValueByPath(fromObject, [ + 'enhanceInputImage', + ]); + if (parentObject !== undefined && fromEnhanceInputImage != null) { + setValueByPath(parentObject, ['parameters', 'upscaleConfig', 'enhanceInputImage'], fromEnhanceInputImage); + } + const fromImagePreservationFactor = getValueByPath(fromObject, [ + 'imagePreservationFactor', + ]); + if (parentObject !== undefined && fromImagePreservationFactor != null) { + setValueByPath(parentObject, ['parameters', 'upscaleConfig', 'imagePreservationFactor'], fromImagePreservationFactor); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (parentObject !== undefined && fromLabels != null) { + setValueByPath(parentObject, ['labels'], fromLabels); + } + const fromNumberOfImages = getValueByPath(fromObject, [ + 'numberOfImages', + ]); + if (parentObject !== undefined && fromNumberOfImages != null) { + setValueByPath(parentObject, ['parameters', 'sampleCount'], fromNumberOfImages); + } + const fromMode = getValueByPath(fromObject, ['mode']); + if (parentObject !== undefined && fromMode != null) { + setValueByPath(parentObject, ['parameters', 'mode'], fromMode); + } + return toObject; +} +function upscaleImageAPIParametersInternalToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromImage = getValueByPath(fromObject, ['image']); + if (fromImage != null) { + setValueByPath(toObject, ['instances[0]', 'image'], imageToVertex(fromImage)); + } + const fromUpscaleFactor = getValueByPath(fromObject, [ + 'upscaleFactor', + ]); + if (fromUpscaleFactor != null) { + setValueByPath(toObject, ['parameters', 'upscaleConfig', 'upscaleFactor'], fromUpscaleFactor); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + upscaleImageAPIConfigInternalToVertex(fromConfig, toObject); + } + return toObject; +} +function upscaleImageResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromGeneratedImages = getValueByPath(fromObject, [ + 'predictions', + ]); + if (fromGeneratedImages != null) { + let transformedList = fromGeneratedImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedImageFromVertex(item); + }); + } + setValueByPath(toObject, ['generatedImages'], transformedList); + } + return toObject; +} +function videoFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromUri = getValueByPath(fromObject, ['uri']); + if (fromUri != null) { + setValueByPath(toObject, ['uri'], fromUri); + } + const fromVideoBytes = getValueByPath(fromObject, ['encodedVideo']); + if (fromVideoBytes != null) { + setValueByPath(toObject, ['videoBytes'], tBytes(fromVideoBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['encoding']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function videoFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromUri = getValueByPath(fromObject, ['gcsUri']); + if (fromUri != null) { + setValueByPath(toObject, ['uri'], fromUri); + } + const fromVideoBytes = getValueByPath(fromObject, [ + 'bytesBase64Encoded', + ]); + if (fromVideoBytes != null) { + setValueByPath(toObject, ['videoBytes'], tBytes(fromVideoBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function videoGenerationMaskToVertex(fromObject, rootObject) { + const toObject = {}; + const fromImage = getValueByPath(fromObject, ['image']); + if (fromImage != null) { + setValueByPath(toObject, ['_self'], imageToVertex(fromImage)); + } + const fromMaskMode = getValueByPath(fromObject, ['maskMode']); + if (fromMaskMode != null) { + setValueByPath(toObject, ['maskMode'], fromMaskMode); + } + return toObject; +} +function videoGenerationReferenceImageToMldev(fromObject, rootObject) { + const toObject = {}; + const fromImage = getValueByPath(fromObject, ['image']); + if (fromImage != null) { + setValueByPath(toObject, ['image'], imageToMldev(fromImage)); + } + const fromReferenceType = getValueByPath(fromObject, [ + 'referenceType', + ]); + if (fromReferenceType != null) { + setValueByPath(toObject, ['referenceType'], fromReferenceType); + } + return toObject; +} +function videoGenerationReferenceImageToVertex(fromObject, rootObject) { + const toObject = {}; + const fromImage = getValueByPath(fromObject, ['image']); + if (fromImage != null) { + setValueByPath(toObject, ['image'], imageToVertex(fromImage)); + } + const fromReferenceType = getValueByPath(fromObject, [ + 'referenceType', + ]); + if (fromReferenceType != null) { + setValueByPath(toObject, ['referenceType'], fromReferenceType); + } + return toObject; +} +function videoToMldev(fromObject, _rootObject) { + const toObject = {}; + const fromUri = getValueByPath(fromObject, ['uri']); + if (fromUri != null) { + setValueByPath(toObject, ['uri'], fromUri); + } + const fromVideoBytes = getValueByPath(fromObject, ['videoBytes']); + if (fromVideoBytes != null) { + setValueByPath(toObject, ['encodedVideo'], tBytes(fromVideoBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['encoding'], fromMimeType); + } + return toObject; +} +function videoToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromUri = getValueByPath(fromObject, ['uri']); + if (fromUri != null) { + setValueByPath(toObject, ['gcsUri'], fromUri); + } + const fromVideoBytes = getValueByPath(fromObject, ['videoBytes']); + if (fromVideoBytes != null) { + setValueByPath(toObject, ['bytesBase64Encoded'], tBytes(fromVideoBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// TODO: b/416041229 - Determine how to retrieve the MCP package version. +const MCP_LABEL = 'mcp_used/unknown'; +// Whether MCP tool usage is detected from mcpToTool. This is used for +// telemetry. +let hasMcpToolUsageFromMcpToTool = false; +// Checks whether the list of tools contains any MCP tools. +function hasMcpToolUsage(tools) { + for (const tool of tools) { + if (isMcpCallableTool(tool)) { + return true; + } + if (typeof tool === 'object' && 'inputSchema' in tool) { + return true; + } + } + return hasMcpToolUsageFromMcpToTool; +} +// Sets the MCP version label in the Google API client header. +function setMcpUsageHeader(headers) { + var _a; + const existingHeader = (_a = headers[GOOGLE_API_CLIENT_HEADER]) !== null && _a !== void 0 ? _a : ''; + headers[GOOGLE_API_CLIENT_HEADER] = (existingHeader + ` ${MCP_LABEL}`).trimStart(); +} +// Returns true if the object is a MCP CallableTool, otherwise false. +function isMcpCallableTool(object) { + return (object !== null && + typeof object === 'object' && + object instanceof McpCallableTool); +} +// List all tools from the MCP client. +function listAllTools(mcpClient_1) { + return __asyncGenerator(this, arguments, function* listAllTools_1(mcpClient, maxTools = 100) { + let cursor = undefined; + let numTools = 0; + while (numTools < maxTools) { + const t = yield __await(mcpClient.listTools({ cursor })); + for (const tool of t.tools) { + yield yield __await(tool); + numTools++; + } + if (!t.nextCursor) { + break; + } + cursor = t.nextCursor; + } + }); +} +/** + * McpCallableTool can be used for model inference and invoking MCP clients with + * given function call arguments. + * + * @experimental Built-in MCP support is an experimental feature, may change in future + * versions. + */ +class McpCallableTool { + constructor(mcpClients = [], config) { + this.mcpTools = []; + this.functionNameToMcpClient = {}; + this.mcpClients = mcpClients; + this.config = config; + } + /** + * Creates a McpCallableTool. + */ + static create(mcpClients, config) { + return new McpCallableTool(mcpClients, config); + } + /** + * Validates the function names are not duplicate and initialize the function + * name to MCP client mapping. + * + * @throws {Error} if the MCP tools from the MCP clients have duplicate tool + * names. + */ + async initialize() { + var _a, e_1, _b, _c; + if (this.mcpTools.length > 0) { + return; + } + const functionMap = {}; + const mcpTools = []; + for (const mcpClient of this.mcpClients) { + try { + for (var _d = true, _e = (e_1 = void 0, __asyncValues(listAllTools(mcpClient))), _f; _f = await _e.next(), _a = _f.done, !_a; _d = true) { + _c = _f.value; + _d = false; + const mcpTool = _c; + mcpTools.push(mcpTool); + const mcpToolName = mcpTool.name; + if (functionMap[mcpToolName]) { + throw new Error(`Duplicate function name ${mcpToolName} found in MCP tools. Please ensure function names are unique.`); + } + functionMap[mcpToolName] = mcpClient; + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (!_d && !_a && (_b = _e.return)) await _b.call(_e); + } + finally { if (e_1) throw e_1.error; } + } + } + this.mcpTools = mcpTools; + this.functionNameToMcpClient = functionMap; + } + async tool() { + await this.initialize(); + return mcpToolsToGeminiTool(this.mcpTools, this.config); + } + async callTool(functionCalls) { + await this.initialize(); + const functionCallResponseParts = []; + for (const functionCall of functionCalls) { + if (functionCall.name in this.functionNameToMcpClient) { + const mcpClient = this.functionNameToMcpClient[functionCall.name]; + let requestOptions = undefined; + // TODO: b/424238654 - Add support for finer grained timeout control. + if (this.config.timeout) { + requestOptions = { + timeout: this.config.timeout, + }; + } + const callToolResponse = await mcpClient.callTool({ + name: functionCall.name, + arguments: functionCall.args, + }, + // Set the result schema to undefined to allow MCP to rely on the + // default schema. + undefined, requestOptions); + functionCallResponseParts.push({ + functionResponse: { + name: functionCall.name, + response: callToolResponse.isError + ? { error: callToolResponse } + : callToolResponse, + }, + }); + } + } + return functionCallResponseParts; + } +} +function isMcpClient(client) { + return (client !== null && + typeof client === 'object' && + 'listTools' in client && + typeof client.listTools === 'function'); +} +/** + * Creates a McpCallableTool from MCP clients and an optional config. + * + * The callable tool can invoke the MCP clients with given function call + * arguments. (often for automatic function calling). + * Use the config to modify tool parameters such as behavior. + * + * @experimental Built-in MCP support is an experimental feature, may change in future + * versions. + */ +function mcpToTool(...args) { + // Set MCP usage for telemetry. + hasMcpToolUsageFromMcpToTool = true; + if (args.length === 0) { + throw new Error('No MCP clients provided'); + } + const maybeConfig = args[args.length - 1]; + if (isMcpClient(maybeConfig)) { + return McpCallableTool.create(args, {}); + } + return McpCallableTool.create(args.slice(0, args.length - 1), maybeConfig); +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Handles incoming messages from the WebSocket. + * + * @remarks + * This function is responsible for parsing incoming messages, transforming them + * into LiveMusicServerMessage, and then calling the onmessage callback. + * Note that the first message which is received from the server is a + * setupComplete message. + * + * @param apiClient The ApiClient instance. + * @param onmessage The user-provided onmessage callback (if any). + * @param event The MessageEvent from the WebSocket. + */ +async function handleWebSocketMessage$1(apiClient, onmessage, event) { + const serverMessage = new LiveMusicServerMessage(); + let data; + if (event.data instanceof Blob) { + data = JSON.parse(await event.data.text()); + } + else { + data = JSON.parse(event.data); + } + Object.assign(serverMessage, data); + onmessage(serverMessage); +} +/** + LiveMusic class encapsulates the configuration for live music + generation via Lyria Live models. + + @experimental + */ +class LiveMusic { + constructor(apiClient, auth, webSocketFactory) { + this.apiClient = apiClient; + this.auth = auth; + this.webSocketFactory = webSocketFactory; + } + /** + Establishes a connection to the specified model and returns a + LiveMusicSession object representing that connection. + + @experimental + + @remarks + + @param params - The parameters for establishing a connection to the model. + @return A live session. + + @example + ```ts + let model = 'models/lyria-realtime-exp'; + const session = await ai.live.music.connect({ + model: model, + callbacks: { + onmessage: (e: MessageEvent) => { + console.log('Received message from the server: %s\n', debug(e.data)); + }, + onerror: (e: ErrorEvent) => { + console.log('Error occurred: %s\n', debug(e.error)); + }, + onclose: (e: CloseEvent) => { + console.log('Connection closed.'); + }, + }, + }); + ``` + */ + async connect(params) { + var _a, _b; + if (this.apiClient.isVertexAI()) { + throw new Error('Live music is not supported for Vertex AI.'); + } + console.warn('Live music generation is experimental and may change in future versions.'); + const websocketBaseUrl = this.apiClient.getWebsocketBaseUrl(); + const apiVersion = this.apiClient.getApiVersion(); + const headers = mapToHeaders$1(this.apiClient.getDefaultHeaders()); + const apiKey = this.apiClient.getApiKey(); + const url = `${websocketBaseUrl}/ws/google.ai.generativelanguage.${apiVersion}.GenerativeService.BidiGenerateMusic?key=${apiKey}`; + let onopenResolve = () => { }; + const onopenPromise = new Promise((resolve) => { + onopenResolve = resolve; + }); + const callbacks = params.callbacks; + const onopenAwaitedCallback = function () { + onopenResolve({}); + }; + const apiClient = this.apiClient; + const websocketCallbacks = { + onopen: onopenAwaitedCallback, + onmessage: (event) => { + void handleWebSocketMessage$1(apiClient, callbacks.onmessage, event); + }, + onerror: (_a = callbacks === null || callbacks === void 0 ? void 0 : callbacks.onerror) !== null && _a !== void 0 ? _a : function (e) { + }, + onclose: (_b = callbacks === null || callbacks === void 0 ? void 0 : callbacks.onclose) !== null && _b !== void 0 ? _b : function (e) { + }, + }; + const conn = this.webSocketFactory.create(url, headersToMap$1(headers), websocketCallbacks); + conn.connect(); + // Wait for the websocket to open before sending requests. + await onopenPromise; + const model = tModel(this.apiClient, params.model); + const setup = { model }; + const clientMessage = { setup }; + conn.send(JSON.stringify(clientMessage)); + return new LiveMusicSession(conn, this.apiClient); + } +} +/** + Represents a connection to the API. + + @experimental + */ +class LiveMusicSession { + constructor(conn, apiClient) { + this.conn = conn; + this.apiClient = apiClient; + } + /** + Sets inputs to steer music generation. Updates the session's current + weighted prompts. + + @param params - Contains one property, `weightedPrompts`. + + - `weightedPrompts` to send to the model; weights are normalized to + sum to 1.0. + + @experimental + */ + async setWeightedPrompts(params) { + if (!params.weightedPrompts || + Object.keys(params.weightedPrompts).length === 0) { + throw new Error('Weighted prompts must be set and contain at least one entry.'); + } + const clientContent = liveMusicSetWeightedPromptsParametersToMldev(params); + this.conn.send(JSON.stringify({ clientContent })); + } + /** + Sets a configuration to the model. Updates the session's current + music generation config. + + @param params - Contains one property, `musicGenerationConfig`. + + - `musicGenerationConfig` to set in the model. Passing an empty or + undefined config to the model will reset the config to defaults. + + @experimental + */ + async setMusicGenerationConfig(params) { + if (!params.musicGenerationConfig) { + params.musicGenerationConfig = {}; + } + const setConfigParameters = liveMusicSetConfigParametersToMldev(params); + this.conn.send(JSON.stringify(setConfigParameters)); + } + sendPlaybackControl(playbackControl) { + const clientMessage = { playbackControl }; + this.conn.send(JSON.stringify(clientMessage)); + } + /** + * Start the music stream. + * + * @experimental + */ + play() { + this.sendPlaybackControl(exports.LiveMusicPlaybackControl.PLAY); + } + /** + * Temporarily halt the music stream. Use `play` to resume from the current + * position. + * + * @experimental + */ + pause() { + this.sendPlaybackControl(exports.LiveMusicPlaybackControl.PAUSE); + } + /** + * Stop the music stream and reset the state. Retains the current prompts + * and config. + * + * @experimental + */ + stop() { + this.sendPlaybackControl(exports.LiveMusicPlaybackControl.STOP); + } + /** + * Resets the context of the music generation without stopping it. + * Retains the current prompts and config. + * + * @experimental + */ + resetContext() { + this.sendPlaybackControl(exports.LiveMusicPlaybackControl.RESET_CONTEXT); + } + /** + Terminates the WebSocket connection. + + @experimental + */ + close() { + this.conn.close(); + } +} +// Converts an headers object to a "map" object as expected by the WebSocket +// constructor. We use this as the Auth interface works with Headers objects +// while the WebSocket constructor takes a map. +function headersToMap$1(headers) { + const headerMap = {}; + headers.forEach((value, key) => { + headerMap[key] = value; + }); + return headerMap; +} +// Converts a "map" object to a headers object. We use this as the Auth +// interface works with Headers objects while the API client default headers +// returns a map. +function mapToHeaders$1(map) { + const headers = new Headers(); + for (const [key, value] of Object.entries(map)) { + headers.append(key, value); + } + return headers; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const FUNCTION_RESPONSE_REQUIRES_ID = 'FunctionResponse request must have an `id` field from the response of a ToolCall.FunctionalCalls in Google AI.'; +/** + * Handles incoming messages from the WebSocket. + * + * @remarks + * This function is responsible for parsing incoming messages, transforming them + * into LiveServerMessages, and then calling the onmessage callback. Note that + * the first message which is received from the server is a setupComplete + * message. + * + * @param apiClient The ApiClient instance. + * @param onmessage The user-provided onmessage callback (if any). + * @param event The MessageEvent from the WebSocket. + */ +async function handleWebSocketMessage(apiClient, onmessage, event) { + const serverMessage = new LiveServerMessage(); + let jsonData; + if (event.data instanceof Blob) { + jsonData = await event.data.text(); + } + else if (event.data instanceof ArrayBuffer) { + jsonData = new TextDecoder().decode(event.data); + } + else { + jsonData = event.data; + } + const data = JSON.parse(jsonData); + if (apiClient.isVertexAI()) { + const resp = liveServerMessageFromVertex(data); + Object.assign(serverMessage, resp); + } + else { + const resp = data; + Object.assign(serverMessage, resp); + } + onmessage(serverMessage); +} +/** + Live class encapsulates the configuration for live interaction with the + Generative Language API. It embeds ApiClient for general API settings. + + @experimental + */ +class Live { + constructor(apiClient, auth, webSocketFactory) { + this.apiClient = apiClient; + this.auth = auth; + this.webSocketFactory = webSocketFactory; + this.music = new LiveMusic(this.apiClient, this.auth, this.webSocketFactory); + } + /** + Establishes a connection to the specified model with the given + configuration and returns a Session object representing that connection. + + @experimental Built-in MCP support is an experimental feature, may change in + future versions. + + @remarks + + @param params - The parameters for establishing a connection to the model. + @return A live session. + + @example + ```ts + let model: string; + if (GOOGLE_GENAI_USE_VERTEXAI) { + model = 'gemini-2.0-flash-live-preview-04-09'; + } else { + model = 'gemini-live-2.5-flash-preview'; + } + const session = await ai.live.connect({ + model: model, + config: { + responseModalities: [Modality.AUDIO], + }, + callbacks: { + onopen: () => { + console.log('Connected to the socket.'); + }, + onmessage: (e: MessageEvent) => { + console.log('Received message from the server: %s\n', debug(e.data)); + }, + onerror: (e: ErrorEvent) => { + console.log('Error occurred: %s\n', debug(e.error)); + }, + onclose: (e: CloseEvent) => { + console.log('Connection closed.'); + }, + }, + }); + ``` + */ + async connect(params) { + var _a, _b, _c, _d, _e, _f; + // TODO: b/404946746 - Support per request HTTP options. + if (params.config && params.config.httpOptions) { + throw new Error('The Live module does not support httpOptions at request-level in' + + ' LiveConnectConfig yet. Please use the client-level httpOptions' + + ' configuration instead.'); + } + const websocketBaseUrl = this.apiClient.getWebsocketBaseUrl(); + const apiVersion = this.apiClient.getApiVersion(); + let url; + const clientHeaders = this.apiClient.getHeaders(); + if (params.config && + params.config.tools && + hasMcpToolUsage(params.config.tools)) { + setMcpUsageHeader(clientHeaders); + } + const headers = mapToHeaders(clientHeaders); + if (this.apiClient.isVertexAI()) { + const project = this.apiClient.getProject(); + const location = this.apiClient.getLocation(); + const apiKey = this.apiClient.getApiKey(); + const hasStandardAuth = (!!project && !!location) || !!apiKey; + if (this.apiClient.getCustomBaseUrl() && !hasStandardAuth) { + // Custom base URL without standard auth (e.g., proxy). + url = websocketBaseUrl; + // Auth headers are assumed to be in `clientHeaders` from httpOptions. + } + else { + url = `${websocketBaseUrl}/ws/google.cloud.aiplatform.${apiVersion}.LlmBidiService/BidiGenerateContent`; + await this.auth.addAuthHeaders(headers, url); + } + } + else { + const apiKey = this.apiClient.getApiKey(); + let method = 'BidiGenerateContent'; + let keyName = 'key'; + if (apiKey === null || apiKey === void 0 ? void 0 : apiKey.startsWith('auth_tokens/')) { + console.warn('Warning: Ephemeral token support is experimental and may change in future versions.'); + if (apiVersion !== 'v1alpha') { + console.warn("Warning: The SDK's ephemeral token support is in v1alpha only. Please use const ai = new GoogleGenAI({apiKey: token.name, httpOptions: { apiVersion: 'v1alpha' }}); before session connection."); + } + method = 'BidiGenerateContentConstrained'; + keyName = 'access_token'; + } + url = `${websocketBaseUrl}/ws/google.ai.generativelanguage.${apiVersion}.GenerativeService.${method}?${keyName}=${apiKey}`; + } + let onopenResolve = () => { }; + const onopenPromise = new Promise((resolve) => { + onopenResolve = resolve; + }); + const callbacks = params.callbacks; + const onopenAwaitedCallback = function () { + var _a; + (_a = callbacks === null || callbacks === void 0 ? void 0 : callbacks.onopen) === null || _a === void 0 ? void 0 : _a.call(callbacks); + onopenResolve({}); + }; + const apiClient = this.apiClient; + const websocketCallbacks = { + onopen: onopenAwaitedCallback, + onmessage: (event) => { + void handleWebSocketMessage(apiClient, callbacks.onmessage, event); + }, + onerror: (_a = callbacks === null || callbacks === void 0 ? void 0 : callbacks.onerror) !== null && _a !== void 0 ? _a : function (e) { + }, + onclose: (_b = callbacks === null || callbacks === void 0 ? void 0 : callbacks.onclose) !== null && _b !== void 0 ? _b : function (e) { + }, + }; + const conn = this.webSocketFactory.create(url, headersToMap(headers), websocketCallbacks); + conn.connect(); + // Wait for the websocket to open before sending requests. + await onopenPromise; + let transformedModel = tModel(this.apiClient, params.model); + if (this.apiClient.isVertexAI() && + transformedModel.startsWith('publishers/')) { + const project = this.apiClient.getProject(); + const location = this.apiClient.getLocation(); + if (project && location) { + transformedModel = + `projects/${project}/locations/${location}/` + transformedModel; + } + } + let clientMessage = {}; + if (this.apiClient.isVertexAI() && + ((_c = params.config) === null || _c === void 0 ? void 0 : _c.responseModalities) === undefined) { + // Set default to AUDIO to align with MLDev API. + if (params.config === undefined) { + params.config = { responseModalities: [exports.Modality.AUDIO] }; + } + else { + params.config.responseModalities = [exports.Modality.AUDIO]; + } + } + if ((_d = params.config) === null || _d === void 0 ? void 0 : _d.generationConfig) { + // Raise deprecation warning for generationConfig. + console.warn('Setting `LiveConnectConfig.generation_config` is deprecated, please set the fields on `LiveConnectConfig` directly. This will become an error in a future version (not before Q3 2025).'); + } + const inputTools = (_f = (_e = params.config) === null || _e === void 0 ? void 0 : _e.tools) !== null && _f !== void 0 ? _f : []; + const convertedTools = []; + for (const tool of inputTools) { + if (this.isCallableTool(tool)) { + const callableTool = tool; + convertedTools.push(await callableTool.tool()); + } + else { + convertedTools.push(tool); + } + } + if (convertedTools.length > 0) { + params.config.tools = convertedTools; + } + const liveConnectParameters = { + model: transformedModel, + config: params.config, + callbacks: params.callbacks, + }; + if (this.apiClient.isVertexAI()) { + clientMessage = liveConnectParametersToVertex(this.apiClient, liveConnectParameters); + } + else { + clientMessage = liveConnectParametersToMldev(this.apiClient, liveConnectParameters); + } + delete clientMessage['config']; + conn.send(JSON.stringify(clientMessage)); + return new Session(conn, this.apiClient); + } + // TODO: b/416041229 - Abstract this method to a common place. + isCallableTool(tool) { + return 'callTool' in tool && typeof tool.callTool === 'function'; + } +} +const defaultLiveSendClientContentParamerters = { + turnComplete: true, +}; +/** + Represents a connection to the API. + + @experimental + */ +class Session { + constructor(conn, apiClient) { + this.conn = conn; + this.apiClient = apiClient; + } + tLiveClientContent(apiClient, params) { + if (params.turns !== null && params.turns !== undefined) { + let contents = []; + try { + contents = tContents(params.turns); + if (!apiClient.isVertexAI()) { + contents = contents.map((item) => contentToMldev$1(item)); + } + } + catch (_a) { + throw new Error(`Failed to parse client content "turns", type: '${typeof params.turns}'`); + } + return { + clientContent: { turns: contents, turnComplete: params.turnComplete }, + }; + } + return { + clientContent: { turnComplete: params.turnComplete }, + }; + } + tLiveClienttToolResponse(apiClient, params) { + let functionResponses = []; + if (params.functionResponses == null) { + throw new Error('functionResponses is required.'); + } + if (!Array.isArray(params.functionResponses)) { + functionResponses = [params.functionResponses]; + } + else { + functionResponses = params.functionResponses; + } + if (functionResponses.length === 0) { + throw new Error('functionResponses is required.'); + } + for (const functionResponse of functionResponses) { + if (typeof functionResponse !== 'object' || + functionResponse === null || + !('name' in functionResponse) || + !('response' in functionResponse)) { + throw new Error(`Could not parse function response, type '${typeof functionResponse}'.`); + } + if (!apiClient.isVertexAI() && !('id' in functionResponse)) { + throw new Error(FUNCTION_RESPONSE_REQUIRES_ID); + } + } + const clientMessage = { + toolResponse: { functionResponses: functionResponses }, + }; + return clientMessage; + } + /** + Send a message over the established connection. + + @param params - Contains two **optional** properties, `turns` and + `turnComplete`. + + - `turns` will be converted to a `Content[]` + - `turnComplete: true` [default] indicates that you are done sending + content and expect a response. If `turnComplete: false`, the server + will wait for additional messages before starting generation. + + @experimental + + @remarks + There are two ways to send messages to the live API: + `sendClientContent` and `sendRealtimeInput`. + + `sendClientContent` messages are added to the model context **in order**. + Having a conversation using `sendClientContent` messages is roughly + equivalent to using the `Chat.sendMessageStream`, except that the state of + the `chat` history is stored on the API server instead of locally. + + Because of `sendClientContent`'s order guarantee, the model cannot respons + as quickly to `sendClientContent` messages as to `sendRealtimeInput` + messages. This makes the biggest difference when sending objects that have + significant preprocessing time (typically images). + + The `sendClientContent` message sends a `Content[]` + which has more options than the `Blob` sent by `sendRealtimeInput`. + + So the main use-cases for `sendClientContent` over `sendRealtimeInput` are: + + - Sending anything that can't be represented as a `Blob` (text, + `sendClientContent({turns="Hello?"}`)). + - Managing turns when not using audio input and voice activity detection. + (`sendClientContent({turnComplete:true})` or the short form + `sendClientContent()`) + - Prefilling a conversation context + ``` + sendClientContent({ + turns: [ + Content({role:user, parts:...}), + Content({role:user, parts:...}), + ... + ] + }) + ``` + @experimental + */ + sendClientContent(params) { + params = Object.assign(Object.assign({}, defaultLiveSendClientContentParamerters), params); + const clientMessage = this.tLiveClientContent(this.apiClient, params); + this.conn.send(JSON.stringify(clientMessage)); + } + /** + Send a realtime message over the established connection. + + @param params - Contains one property, `media`. + + - `media` will be converted to a `Blob` + + @experimental + + @remarks + Use `sendRealtimeInput` for realtime audio chunks and video frames (images). + + With `sendRealtimeInput` the api will respond to audio automatically + based on voice activity detection (VAD). + + `sendRealtimeInput` is optimized for responsivness at the expense of + deterministic ordering guarantees. Audio and video tokens are to the + context when they become available. + + Note: The Call signature expects a `Blob` object, but only a subset + of audio and image mimetypes are allowed. + */ + sendRealtimeInput(params) { + let clientMessage = {}; + if (this.apiClient.isVertexAI()) { + clientMessage = { + 'realtimeInput': liveSendRealtimeInputParametersToVertex(params), + }; + } + else { + clientMessage = { + 'realtimeInput': liveSendRealtimeInputParametersToMldev(params), + }; + } + this.conn.send(JSON.stringify(clientMessage)); + } + /** + Send a function response message over the established connection. + + @param params - Contains property `functionResponses`. + + - `functionResponses` will be converted to a `functionResponses[]` + + @remarks + Use `sendFunctionResponse` to reply to `LiveServerToolCall` from the server. + + Use {@link types.LiveConnectConfig#tools} to configure the callable functions. + + @experimental + */ + sendToolResponse(params) { + if (params.functionResponses == null) { + throw new Error('Tool response parameters are required.'); + } + const clientMessage = this.tLiveClienttToolResponse(this.apiClient, params); + this.conn.send(JSON.stringify(clientMessage)); + } + /** + Terminates the WebSocket connection. + + @experimental + + @example + ```ts + let model: string; + if (GOOGLE_GENAI_USE_VERTEXAI) { + model = 'gemini-2.0-flash-live-preview-04-09'; + } else { + model = 'gemini-live-2.5-flash-preview'; + } + const session = await ai.live.connect({ + model: model, + config: { + responseModalities: [Modality.AUDIO], + } + }); + + session.close(); + ``` + */ + close() { + this.conn.close(); + } +} +// Converts an headers object to a "map" object as expected by the WebSocket +// constructor. We use this as the Auth interface works with Headers objects +// while the WebSocket constructor takes a map. +function headersToMap(headers) { + const headerMap = {}; + headers.forEach((value, key) => { + headerMap[key] = value; + }); + return headerMap; +} +// Converts a "map" object to a headers object. We use this as the Auth +// interface works with Headers objects while the API client default headers +// returns a map. +function mapToHeaders(map) { + const headers = new Headers(); + for (const [key, value] of Object.entries(map)) { + headers.append(key, value); + } + return headers; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const DEFAULT_MAX_REMOTE_CALLS = 10; +/** Returns whether automatic function calling is disabled. */ +function shouldDisableAfc(config) { + var _a, _b, _c; + if ((_a = config === null || config === void 0 ? void 0 : config.automaticFunctionCalling) === null || _a === void 0 ? void 0 : _a.disable) { + return true; + } + let callableToolsPresent = false; + for (const tool of (_b = config === null || config === void 0 ? void 0 : config.tools) !== null && _b !== void 0 ? _b : []) { + if (isCallableTool(tool)) { + callableToolsPresent = true; + break; + } + } + if (!callableToolsPresent) { + return true; + } + const maxCalls = (_c = config === null || config === void 0 ? void 0 : config.automaticFunctionCalling) === null || _c === void 0 ? void 0 : _c.maximumRemoteCalls; + if ((maxCalls && (maxCalls < 0 || !Number.isInteger(maxCalls))) || + maxCalls == 0) { + console.warn('Invalid maximumRemoteCalls value provided for automatic function calling. Disabled automatic function calling. Please provide a valid integer value greater than 0. maximumRemoteCalls provided:', maxCalls); + return true; + } + return false; +} +function isCallableTool(tool) { + return 'callTool' in tool && typeof tool.callTool === 'function'; +} +// Checks whether the list of tools contains any CallableTools. Will return true +// if there is at least one CallableTool. +function hasCallableTools(params) { + var _a, _b, _c; + return (_c = (_b = (_a = params.config) === null || _a === void 0 ? void 0 : _a.tools) === null || _b === void 0 ? void 0 : _b.some((tool) => isCallableTool(tool))) !== null && _c !== void 0 ? _c : false; +} +/** + * Returns the indexes of the tools that are not compatible with AFC. + */ +function findAfcIncompatibleToolIndexes(params) { + var _a; + // Use number[] for an array of numbers in TypeScript + const afcIncompatibleToolIndexes = []; + if (!((_a = params === null || params === void 0 ? void 0 : params.config) === null || _a === void 0 ? void 0 : _a.tools)) { + return afcIncompatibleToolIndexes; + } + params.config.tools.forEach((tool, index) => { + if (isCallableTool(tool)) { + return; + } + const geminiTool = tool; + if (geminiTool.functionDeclarations && + geminiTool.functionDeclarations.length > 0) { + afcIncompatibleToolIndexes.push(index); + } + }); + return afcIncompatibleToolIndexes; +} +/** + * Returns whether to append automatic function calling history to the + * response. + */ +function shouldAppendAfcHistory(config) { + var _a; + return !((_a = config === null || config === void 0 ? void 0 : config.automaticFunctionCalling) === null || _a === void 0 ? void 0 : _a.ignoreCallHistory); +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Models extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + /** + * Makes an API request to generate content with a given model. + * + * For the `model` parameter, supported formats for Vertex AI API include: + * - The Gemini model ID, for example: 'gemini-2.0-flash' + * - The full resource name starts with 'projects/', for example: + * 'projects/my-project-id/locations/us-central1/publishers/google/models/gemini-2.0-flash' + * - The partial resource name with 'publishers/', for example: + * 'publishers/google/models/gemini-2.0-flash' or + * 'publishers/meta/models/llama-3.1-405b-instruct-maas' + * - `/` separated publisher and model name, for example: + * 'google/gemini-2.0-flash' or 'meta/llama-3.1-405b-instruct-maas' + * + * For the `model` parameter, supported formats for Gemini API include: + * - The Gemini model ID, for example: 'gemini-2.0-flash' + * - The model name starts with 'models/', for example: + * 'models/gemini-2.0-flash' + * - For tuned models, the model name starts with 'tunedModels/', + * for example: + * 'tunedModels/1234567890123456789' + * + * Some models support multimodal input and output. + * + * @param params - The parameters for generating content. + * @return The response from generating content. + * + * @example + * ```ts + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: 'why is the sky blue?', + * config: { + * candidateCount: 2, + * } + * }); + * console.log(response); + * ``` + */ + this.generateContent = async (params) => { + var _a, _b, _c, _d, _e; + const transformedParams = await this.processParamsMaybeAddMcpUsage(params); + this.maybeMoveToResponseJsonSchem(params); + if (!hasCallableTools(params) || shouldDisableAfc(params.config)) { + return await this.generateContentInternal(transformedParams); + } + const incompatibleToolIndexes = findAfcIncompatibleToolIndexes(params); + if (incompatibleToolIndexes.length > 0) { + const formattedIndexes = incompatibleToolIndexes + .map((index) => `tools[${index}]`) + .join(', '); + throw new Error(`Automatic function calling with CallableTools (or MCP objects) and basic FunctionDeclarations is not yet supported. Incompatible tools found at ${formattedIndexes}.`); + } + let response; + let functionResponseContent; + const automaticFunctionCallingHistory = tContents(transformedParams.contents); + const maxRemoteCalls = (_c = (_b = (_a = transformedParams.config) === null || _a === void 0 ? void 0 : _a.automaticFunctionCalling) === null || _b === void 0 ? void 0 : _b.maximumRemoteCalls) !== null && _c !== void 0 ? _c : DEFAULT_MAX_REMOTE_CALLS; + let remoteCalls = 0; + while (remoteCalls < maxRemoteCalls) { + response = await this.generateContentInternal(transformedParams); + if (!response.functionCalls || response.functionCalls.length === 0) { + break; + } + const responseContent = response.candidates[0].content; + const functionResponseParts = []; + for (const tool of (_e = (_d = params.config) === null || _d === void 0 ? void 0 : _d.tools) !== null && _e !== void 0 ? _e : []) { + if (isCallableTool(tool)) { + const callableTool = tool; + const parts = await callableTool.callTool(response.functionCalls); + functionResponseParts.push(...parts); + } + } + remoteCalls++; + functionResponseContent = { + role: 'user', + parts: functionResponseParts, + }; + transformedParams.contents = tContents(transformedParams.contents); + transformedParams.contents.push(responseContent); + transformedParams.contents.push(functionResponseContent); + if (shouldAppendAfcHistory(transformedParams.config)) { + automaticFunctionCallingHistory.push(responseContent); + automaticFunctionCallingHistory.push(functionResponseContent); + } + } + if (shouldAppendAfcHistory(transformedParams.config)) { + response.automaticFunctionCallingHistory = + automaticFunctionCallingHistory; + } + return response; + }; + /** + * Makes an API request to generate content with a given model and yields the + * response in chunks. + * + * For the `model` parameter, supported formats for Vertex AI API include: + * - The Gemini model ID, for example: 'gemini-2.0-flash' + * - The full resource name starts with 'projects/', for example: + * 'projects/my-project-id/locations/us-central1/publishers/google/models/gemini-2.0-flash' + * - The partial resource name with 'publishers/', for example: + * 'publishers/google/models/gemini-2.0-flash' or + * 'publishers/meta/models/llama-3.1-405b-instruct-maas' + * - `/` separated publisher and model name, for example: + * 'google/gemini-2.0-flash' or 'meta/llama-3.1-405b-instruct-maas' + * + * For the `model` parameter, supported formats for Gemini API include: + * - The Gemini model ID, for example: 'gemini-2.0-flash' + * - The model name starts with 'models/', for example: + * 'models/gemini-2.0-flash' + * - For tuned models, the model name starts with 'tunedModels/', + * for example: + * 'tunedModels/1234567890123456789' + * + * Some models support multimodal input and output. + * + * @param params - The parameters for generating content with streaming response. + * @return The response from generating content. + * + * @example + * ```ts + * const response = await ai.models.generateContentStream({ + * model: 'gemini-2.0-flash', + * contents: 'why is the sky blue?', + * config: { + * maxOutputTokens: 200, + * } + * }); + * for await (const chunk of response) { + * console.log(chunk); + * } + * ``` + */ + this.generateContentStream = async (params) => { + var _a, _b, _c, _d, _e; + this.maybeMoveToResponseJsonSchem(params); + if (shouldDisableAfc(params.config)) { + const transformedParams = await this.processParamsMaybeAddMcpUsage(params); + return await this.generateContentStreamInternal(transformedParams); + } + const incompatibleToolIndexes = findAfcIncompatibleToolIndexes(params); + if (incompatibleToolIndexes.length > 0) { + const formattedIndexes = incompatibleToolIndexes + .map((index) => `tools[${index}]`) + .join(', '); + throw new Error(`Incompatible tools found at ${formattedIndexes}. Automatic function calling with CallableTools (or MCP objects) and basic FunctionDeclarations" is not yet supported.`); + } + // With tool compatibility confirmed, validate that the configuration are + // compatible with each other and raise an error if invalid. + const streamFunctionCall = (_c = (_b = (_a = params === null || params === void 0 ? void 0 : params.config) === null || _a === void 0 ? void 0 : _a.toolConfig) === null || _b === void 0 ? void 0 : _b.functionCallingConfig) === null || _c === void 0 ? void 0 : _c.streamFunctionCallArguments; + const disableAfc = (_e = (_d = params === null || params === void 0 ? void 0 : params.config) === null || _d === void 0 ? void 0 : _d.automaticFunctionCalling) === null || _e === void 0 ? void 0 : _e.disable; + if (streamFunctionCall && !disableAfc) { + throw new Error("Running in streaming mode with 'streamFunctionCallArguments' enabled, " + + 'this feature is not compatible with automatic function calling (AFC). ' + + "Please set 'config.automaticFunctionCalling.disable' to true to disable AFC " + + "or leave 'config.toolConfig.functionCallingConfig.streamFunctionCallArguments' " + + 'to be undefined or set to false to disable streaming function call arguments feature.'); + } + return await this.processAfcStream(params); + }; + /** + * Generates an image based on a text description and configuration. + * + * @param params - The parameters for generating images. + * @return The response from the API. + * + * @example + * ```ts + * const response = await client.models.generateImages({ + * model: 'imagen-4.0-generate-001', + * prompt: 'Robot holding a red skateboard', + * config: { + * numberOfImages: 1, + * includeRaiReason: true, + * }, + * }); + * console.log(response?.generatedImages?.[0]?.image?.imageBytes); + * ``` + */ + this.generateImages = async (params) => { + return await this.generateImagesInternal(params).then((apiResponse) => { + var _a; + let positivePromptSafetyAttributes; + const generatedImages = []; + if (apiResponse === null || apiResponse === void 0 ? void 0 : apiResponse.generatedImages) { + for (const generatedImage of apiResponse.generatedImages) { + if (generatedImage && + (generatedImage === null || generatedImage === void 0 ? void 0 : generatedImage.safetyAttributes) && + ((_a = generatedImage === null || generatedImage === void 0 ? void 0 : generatedImage.safetyAttributes) === null || _a === void 0 ? void 0 : _a.contentType) === 'Positive Prompt') { + positivePromptSafetyAttributes = generatedImage === null || generatedImage === void 0 ? void 0 : generatedImage.safetyAttributes; + } + else { + generatedImages.push(generatedImage); + } + } + } + let response; + if (positivePromptSafetyAttributes) { + response = { + generatedImages: generatedImages, + positivePromptSafetyAttributes: positivePromptSafetyAttributes, + sdkHttpResponse: apiResponse.sdkHttpResponse, + }; + } + else { + response = { + generatedImages: generatedImages, + sdkHttpResponse: apiResponse.sdkHttpResponse, + }; + } + return response; + }); + }; + this.list = async (params) => { + var _a; + const defaultConfig = { + queryBase: true, + }; + const actualConfig = Object.assign(Object.assign({}, defaultConfig), params === null || params === void 0 ? void 0 : params.config); + const actualParams = { + config: actualConfig, + }; + if (this.apiClient.isVertexAI()) { + if (!actualParams.config.queryBase) { + if ((_a = actualParams.config) === null || _a === void 0 ? void 0 : _a.filter) { + throw new Error('Filtering tuned models list for Vertex AI is not currently supported'); + } + else { + actualParams.config.filter = 'labels.tune-type:*'; + } + } + } + return new Pager(exports.PagedItem.PAGED_ITEM_MODELS, (x) => this.listInternal(x), await this.listInternal(actualParams), actualParams); + }; + /** + * Edits an image based on a prompt, list of reference images, and configuration. + * + * @param params - The parameters for editing an image. + * @return The response from the API. + * + * @example + * ```ts + * const response = await client.models.editImage({ + * model: 'imagen-3.0-capability-001', + * prompt: 'Generate an image containing a mug with the product logo [1] visible on the side of the mug.', + * referenceImages: [subjectReferenceImage] + * config: { + * numberOfImages: 1, + * includeRaiReason: true, + * }, + * }); + * console.log(response?.generatedImages?.[0]?.image?.imageBytes); + * ``` + */ + this.editImage = async (params) => { + const paramsInternal = { + model: params.model, + prompt: params.prompt, + referenceImages: [], + config: params.config, + }; + if (params.referenceImages) { + if (params.referenceImages) { + paramsInternal.referenceImages = params.referenceImages.map((img) => img.toReferenceImageAPI()); + } + } + return await this.editImageInternal(paramsInternal); + }; + /** + * Upscales an image based on an image, upscale factor, and configuration. + * Only supported in Vertex AI currently. + * + * @param params - The parameters for upscaling an image. + * @return The response from the API. + * + * @example + * ```ts + * const response = await client.models.upscaleImage({ + * model: 'imagen-4.0-upscale-preview', + * image: image, + * upscaleFactor: 'x2', + * config: { + * includeRaiReason: true, + * }, + * }); + * console.log(response?.generatedImages?.[0]?.image?.imageBytes); + * ``` + */ + this.upscaleImage = async (params) => { + let apiConfig = { + numberOfImages: 1, + mode: 'upscale', + }; + if (params.config) { + apiConfig = Object.assign(Object.assign({}, apiConfig), params.config); + } + const apiParams = { + model: params.model, + image: params.image, + upscaleFactor: params.upscaleFactor, + config: apiConfig, + }; + return await this.upscaleImageInternal(apiParams); + }; + /** + * Generates videos based on a text description and configuration. + * + * @param params - The parameters for generating videos. + * @return A Promise<GenerateVideosOperation> which allows you to track the progress and eventually retrieve the generated videos using the operations.get method. + * + * @example + * ```ts + * const operation = await ai.models.generateVideos({ + * model: 'veo-2.0-generate-001', + * source: { + * prompt: 'A neon hologram of a cat driving at top speed', + * }, + * config: { + * numberOfVideos: 1 + * }); + * + * while (!operation.done) { + * await new Promise(resolve => setTimeout(resolve, 10000)); + * operation = await ai.operations.getVideosOperation({operation: operation}); + * } + * + * console.log(operation.response?.generatedVideos?.[0]?.video?.uri); + * ``` + */ + this.generateVideos = async (params) => { + var _a, _b, _c, _d, _e, _f; + if ((params.prompt || params.image || params.video) && params.source) { + throw new Error('Source and prompt/image/video are mutually exclusive. Please only use source.'); + } + // Gemini API does not support video bytes. + if (!this.apiClient.isVertexAI()) { + if (((_a = params.video) === null || _a === void 0 ? void 0 : _a.uri) && ((_b = params.video) === null || _b === void 0 ? void 0 : _b.videoBytes)) { + params.video = { + uri: params.video.uri, + mimeType: params.video.mimeType, + }; + } + else if (((_d = (_c = params.source) === null || _c === void 0 ? void 0 : _c.video) === null || _d === void 0 ? void 0 : _d.uri) && + ((_f = (_e = params.source) === null || _e === void 0 ? void 0 : _e.video) === null || _f === void 0 ? void 0 : _f.videoBytes)) { + params.source.video = { + uri: params.source.video.uri, + mimeType: params.source.video.mimeType, + }; + } + } + return await this.generateVideosInternal(params); + }; + } + /** + * This logic is needed for GenerateContentConfig only. + * Previously we made GenerateContentConfig.responseSchema field to accept + * unknown. Since v1.9.0, we switch to use backend JSON schema support. + * To maintain backward compatibility, we move the data that was treated as + * JSON schema from the responseSchema field to the responseJsonSchema field. + */ + maybeMoveToResponseJsonSchem(params) { + if (params.config && params.config.responseSchema) { + if (!params.config.responseJsonSchema) { + if (Object.keys(params.config.responseSchema).includes('$schema')) { + params.config.responseJsonSchema = params.config.responseSchema; + delete params.config.responseSchema; + } + } + } + return; + } + /** + * Transforms the CallableTools in the parameters to be simply Tools, it + * copies the params into a new object and replaces the tools, it does not + * modify the original params. Also sets the MCP usage header if there are + * MCP tools in the parameters. + */ + async processParamsMaybeAddMcpUsage(params) { + var _a, _b, _c; + const tools = (_a = params.config) === null || _a === void 0 ? void 0 : _a.tools; + if (!tools) { + return params; + } + const transformedTools = await Promise.all(tools.map(async (tool) => { + if (isCallableTool(tool)) { + const callableTool = tool; + return await callableTool.tool(); + } + return tool; + })); + const newParams = { + model: params.model, + contents: params.contents, + config: Object.assign(Object.assign({}, params.config), { tools: transformedTools }), + }; + newParams.config.tools = transformedTools; + if (params.config && + params.config.tools && + hasMcpToolUsage(params.config.tools)) { + const headers = (_c = (_b = params.config.httpOptions) === null || _b === void 0 ? void 0 : _b.headers) !== null && _c !== void 0 ? _c : {}; + let newHeaders = Object.assign({}, headers); + if (Object.keys(newHeaders).length === 0) { + newHeaders = this.apiClient.getDefaultHeaders(); + } + setMcpUsageHeader(newHeaders); + newParams.config.httpOptions = Object.assign(Object.assign({}, params.config.httpOptions), { headers: newHeaders }); + } + return newParams; + } + async initAfcToolsMap(params) { + var _a, _b, _c; + const afcTools = new Map(); + for (const tool of (_b = (_a = params.config) === null || _a === void 0 ? void 0 : _a.tools) !== null && _b !== void 0 ? _b : []) { + if (isCallableTool(tool)) { + const callableTool = tool; + const toolDeclaration = await callableTool.tool(); + for (const declaration of (_c = toolDeclaration.functionDeclarations) !== null && _c !== void 0 ? _c : []) { + if (!declaration.name) { + throw new Error('Function declaration name is required.'); + } + if (afcTools.has(declaration.name)) { + throw new Error(`Duplicate tool declaration name: ${declaration.name}`); + } + afcTools.set(declaration.name, callableTool); + } + } + } + return afcTools; + } + async processAfcStream(params) { + var _a, _b, _c; + const maxRemoteCalls = (_c = (_b = (_a = params.config) === null || _a === void 0 ? void 0 : _a.automaticFunctionCalling) === null || _b === void 0 ? void 0 : _b.maximumRemoteCalls) !== null && _c !== void 0 ? _c : DEFAULT_MAX_REMOTE_CALLS; + let wereFunctionsCalled = false; + let remoteCallCount = 0; + const afcToolsMap = await this.initAfcToolsMap(params); + return (function (models, afcTools, params) { + return __asyncGenerator(this, arguments, function* () { + var _a, e_1, _b, _c; + var _d, _e; + while (remoteCallCount < maxRemoteCalls) { + if (wereFunctionsCalled) { + remoteCallCount++; + wereFunctionsCalled = false; + } + const transformedParams = yield __await(models.processParamsMaybeAddMcpUsage(params)); + const response = yield __await(models.generateContentStreamInternal(transformedParams)); + const functionResponses = []; + const responseContents = []; + try { + for (var _f = true, response_1 = (e_1 = void 0, __asyncValues(response)), response_1_1; response_1_1 = yield __await(response_1.next()), _a = response_1_1.done, !_a; _f = true) { + _c = response_1_1.value; + _f = false; + const chunk = _c; + yield yield __await(chunk); + if (chunk.candidates && ((_d = chunk.candidates[0]) === null || _d === void 0 ? void 0 : _d.content)) { + responseContents.push(chunk.candidates[0].content); + for (const part of (_e = chunk.candidates[0].content.parts) !== null && _e !== void 0 ? _e : []) { + if (remoteCallCount < maxRemoteCalls && part.functionCall) { + if (!part.functionCall.name) { + throw new Error('Function call name was not returned by the model.'); + } + if (!afcTools.has(part.functionCall.name)) { + throw new Error(`Automatic function calling was requested, but not all the tools the model used implement the CallableTool interface. Available tools: ${afcTools.keys()}, mising tool: ${part.functionCall.name}`); + } + else { + const responseParts = yield __await(afcTools + .get(part.functionCall.name) + .callTool([part.functionCall])); + functionResponses.push(...responseParts); + } + } + } + } + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (!_f && !_a && (_b = response_1.return)) yield __await(_b.call(response_1)); + } + finally { if (e_1) throw e_1.error; } + } + if (functionResponses.length > 0) { + wereFunctionsCalled = true; + const typedResponseChunk = new GenerateContentResponse(); + typedResponseChunk.candidates = [ + { + content: { + role: 'user', + parts: functionResponses, + }, + }, + ]; + yield yield __await(typedResponseChunk); + const newContents = []; + newContents.push(...responseContents); + newContents.push({ + role: 'user', + parts: functionResponses, + }); + const updatedContents = tContents(params.contents).concat(newContents); + params.contents = updatedContents; + } + else { + break; + } + } + }); + })(this, afcToolsMap, params); + } + async generateContentInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = generateContentParametersToVertex(this.apiClient, params); + path = formatMap('{model}:generateContent', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = generateContentResponseFromVertex(apiResponse); + const typedResp = new GenerateContentResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = generateContentParametersToMldev(this.apiClient, params); + path = formatMap('{model}:generateContent', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = generateContentResponseFromMldev(apiResponse); + const typedResp = new GenerateContentResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + async generateContentStreamInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = generateContentParametersToVertex(this.apiClient, params); + path = formatMap('{model}:streamGenerateContent?alt=sse', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + const apiClient = this.apiClient; + response = apiClient.requestStream({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }); + return response.then(function (apiResponse) { + return __asyncGenerator(this, arguments, function* () { + var _a, e_2, _b, _c; + try { + for (var _d = true, apiResponse_1 = __asyncValues(apiResponse), apiResponse_1_1; apiResponse_1_1 = yield __await(apiResponse_1.next()), _a = apiResponse_1_1.done, !_a; _d = true) { + _c = apiResponse_1_1.value; + _d = false; + const chunk = _c; + const resp = generateContentResponseFromVertex((yield __await(chunk.json())), params); + resp['sdkHttpResponse'] = { + headers: chunk.headers, + }; + const typedResp = new GenerateContentResponse(); + Object.assign(typedResp, resp); + yield yield __await(typedResp); + } + } + catch (e_2_1) { e_2 = { error: e_2_1 }; } + finally { + try { + if (!_d && !_a && (_b = apiResponse_1.return)) yield __await(_b.call(apiResponse_1)); + } + finally { if (e_2) throw e_2.error; } + } + }); + }); + } + else { + const body = generateContentParametersToMldev(this.apiClient, params); + path = formatMap('{model}:streamGenerateContent?alt=sse', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + const apiClient = this.apiClient; + response = apiClient.requestStream({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }); + return response.then(function (apiResponse) { + return __asyncGenerator(this, arguments, function* () { + var _a, e_3, _b, _c; + try { + for (var _d = true, apiResponse_2 = __asyncValues(apiResponse), apiResponse_2_1; apiResponse_2_1 = yield __await(apiResponse_2.next()), _a = apiResponse_2_1.done, !_a; _d = true) { + _c = apiResponse_2_1.value; + _d = false; + const chunk = _c; + const resp = generateContentResponseFromMldev((yield __await(chunk.json())), params); + resp['sdkHttpResponse'] = { + headers: chunk.headers, + }; + const typedResp = new GenerateContentResponse(); + Object.assign(typedResp, resp); + yield yield __await(typedResp); + } + } + catch (e_3_1) { e_3 = { error: e_3_1 }; } + finally { + try { + if (!_d && !_a && (_b = apiResponse_2.return)) yield __await(_b.call(apiResponse_2)); + } + finally { if (e_3) throw e_3.error; } + } + }); + }); + } + } + /** + * Calculates embeddings for the given contents. Only text is supported. + * + * @param params - The parameters for embedding contents. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.embedContent({ + * model: 'text-embedding-004', + * contents: [ + * 'What is your name?', + * 'What is your favorite color?', + * ], + * config: { + * outputDimensionality: 64, + * }, + * }); + * console.log(response); + * ``` + */ + async embedContent(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = embedContentParametersToVertex(this.apiClient, params); + path = formatMap('{model}:predict', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = embedContentResponseFromVertex(apiResponse); + const typedResp = new EmbedContentResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = embedContentParametersToMldev(this.apiClient, params); + path = formatMap('{model}:batchEmbedContents', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = embedContentResponseFromMldev(apiResponse); + const typedResp = new EmbedContentResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Private method for generating images. + */ + async generateImagesInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = generateImagesParametersToVertex(this.apiClient, params); + path = formatMap('{model}:predict', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = generateImagesResponseFromVertex(apiResponse); + const typedResp = new GenerateImagesResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = generateImagesParametersToMldev(this.apiClient, params); + path = formatMap('{model}:predict', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = generateImagesResponseFromMldev(apiResponse); + const typedResp = new GenerateImagesResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Private method for editing an image. + */ + async editImageInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = editImageParametersInternalToVertex(this.apiClient, params); + path = formatMap('{model}:predict', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = editImageResponseFromVertex(apiResponse); + const typedResp = new EditImageResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + throw new Error('This method is only supported by the Vertex AI.'); + } + } + /** + * Private method for upscaling an image. + */ + async upscaleImageInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = upscaleImageAPIParametersInternalToVertex(this.apiClient, params); + path = formatMap('{model}:predict', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = upscaleImageResponseFromVertex(apiResponse); + const typedResp = new UpscaleImageResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + throw new Error('This method is only supported by the Vertex AI.'); + } + } + /** + * Recontextualizes an image. + * + * There are two types of recontextualization currently supported: + * 1) Imagen Product Recontext - Generate images of products in new scenes + * and contexts. + * 2) Virtual Try-On: Generate images of persons modeling fashion products. + * + * @param params - The parameters for recontextualizing an image. + * @return The response from the API. + * + * @example + * ```ts + * const response1 = await ai.models.recontextImage({ + * model: 'imagen-product-recontext-preview-06-30', + * source: { + * prompt: 'In a modern kitchen setting.', + * productImages: [productImage], + * }, + * config: { + * numberOfImages: 1, + * }, + * }); + * console.log(response1?.generatedImages?.[0]?.image?.imageBytes); + * + * const response2 = await ai.models.recontextImage({ + * model: 'virtual-try-on-001', + * source: { + * personImage: personImage, + * productImages: [productImage], + * }, + * config: { + * numberOfImages: 1, + * }, + * }); + * console.log(response2?.generatedImages?.[0]?.image?.imageBytes); + * ``` + */ + async recontextImage(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = recontextImageParametersToVertex(this.apiClient, params); + path = formatMap('{model}:predict', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = recontextImageResponseFromVertex(apiResponse); + const typedResp = new RecontextImageResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + throw new Error('This method is only supported by the Vertex AI.'); + } + } + /** + * Segments an image, creating a mask of a specified area. + * + * @param params - The parameters for segmenting an image. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.segmentImage({ + * model: 'image-segmentation-001', + * source: { + * image: image, + * }, + * config: { + * mode: 'foreground', + * }, + * }); + * console.log(response?.generatedMasks?.[0]?.mask?.imageBytes); + * ``` + */ + async segmentImage(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = segmentImageParametersToVertex(this.apiClient, params); + path = formatMap('{model}:predict', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = segmentImageResponseFromVertex(apiResponse); + const typedResp = new SegmentImageResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + throw new Error('This method is only supported by the Vertex AI.'); + } + } + /** + * Fetches information about a model by name. + * + * @example + * ```ts + * const modelInfo = await ai.models.get({model: 'gemini-2.0-flash'}); + * ``` + */ + async get(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = getModelParametersToVertex(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = modelFromVertex(apiResponse); + return resp; + }); + } + else { + const body = getModelParametersToMldev(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = modelFromMldev(apiResponse); + return resp; + }); + } + } + async listInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = listModelsParametersToVertex(this.apiClient, params); + path = formatMap('{models_url}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listModelsResponseFromVertex(apiResponse); + const typedResp = new ListModelsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = listModelsParametersToMldev(this.apiClient, params); + path = formatMap('{models_url}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listModelsResponseFromMldev(apiResponse); + const typedResp = new ListModelsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Updates a tuned model by its name. + * + * @param params - The parameters for updating the model. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.update({ + * model: 'tuned-model-name', + * config: { + * displayName: 'New display name', + * description: 'New description', + * }, + * }); + * ``` + */ + async update(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = updateModelParametersToVertex(this.apiClient, params); + path = formatMap('{model}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'PATCH', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = modelFromVertex(apiResponse); + return resp; + }); + } + else { + const body = updateModelParametersToMldev(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'PATCH', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = modelFromMldev(apiResponse); + return resp; + }); + } + } + /** + * Deletes a tuned model by its name. + * + * @param params - The parameters for deleting the model. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.delete({model: 'tuned-model-name'}); + * ``` + */ + async delete(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = deleteModelParametersToVertex(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = deleteModelResponseFromVertex(apiResponse); + const typedResp = new DeleteModelResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = deleteModelParametersToMldev(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = deleteModelResponseFromMldev(apiResponse); + const typedResp = new DeleteModelResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Counts the number of tokens in the given contents. Multimodal input is + * supported for Gemini models. + * + * @param params - The parameters for counting tokens. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.countTokens({ + * model: 'gemini-2.0-flash', + * contents: 'The quick brown fox jumps over the lazy dog.' + * }); + * console.log(response); + * ``` + */ + async countTokens(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = countTokensParametersToVertex(this.apiClient, params); + path = formatMap('{model}:countTokens', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = countTokensResponseFromVertex(apiResponse); + const typedResp = new CountTokensResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = countTokensParametersToMldev(this.apiClient, params); + path = formatMap('{model}:countTokens', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = countTokensResponseFromMldev(apiResponse); + const typedResp = new CountTokensResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Given a list of contents, returns a corresponding TokensInfo containing + * the list of tokens and list of token ids. + * + * This method is not supported by the Gemini Developer API. + * + * @param params - The parameters for computing tokens. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.computeTokens({ + * model: 'gemini-2.0-flash', + * contents: 'What is your name?' + * }); + * console.log(response); + * ``` + */ + async computeTokens(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = computeTokensParametersToVertex(this.apiClient, params); + path = formatMap('{model}:computeTokens', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = computeTokensResponseFromVertex(apiResponse); + const typedResp = new ComputeTokensResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + throw new Error('This method is only supported by the Vertex AI.'); + } + } + /** + * Private method for generating videos. + */ + async generateVideosInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = generateVideosParametersToVertex(this.apiClient, params); + path = formatMap('{model}:predictLongRunning', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = generateVideosOperationFromVertex(apiResponse); + const typedResp = new GenerateVideosOperation(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = generateVideosParametersToMldev(this.apiClient, params); + path = formatMap('{model}:predictLongRunning', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = generateVideosOperationFromMldev(apiResponse); + const typedResp = new GenerateVideosOperation(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Operations extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + } + /** + * Gets the status of a long-running operation. + * + * @param parameters The parameters for the get operation request. + * @return The updated Operation object, with the latest status or result. + */ + async getVideosOperation(parameters) { + const operation = parameters.operation; + const config = parameters.config; + if (operation.name === undefined || operation.name === '') { + throw new Error('Operation name is required.'); + } + if (this.apiClient.isVertexAI()) { + const resourceName = operation.name.split('/operations/')[0]; + let httpOptions = undefined; + if (config && 'httpOptions' in config) { + httpOptions = config.httpOptions; + } + const rawOperation = await this.fetchPredictVideosOperationInternal({ + operationName: operation.name, + resourceName: resourceName, + config: { httpOptions: httpOptions }, + }); + return operation._fromAPIResponse({ + apiResponse: rawOperation, + _isVertexAI: true, + }); + } + else { + const rawOperation = await this.getVideosOperationInternal({ + operationName: operation.name, + config: config, + }); + return operation._fromAPIResponse({ + apiResponse: rawOperation, + _isVertexAI: false, + }); + } + } + /** + * Gets the status of a long-running operation. + * + * @param parameters The parameters for the get operation request. + * @return The updated Operation object, with the latest status or result. + */ + async get(parameters) { + const operation = parameters.operation; + const config = parameters.config; + if (operation.name === undefined || operation.name === '') { + throw new Error('Operation name is required.'); + } + if (this.apiClient.isVertexAI()) { + const resourceName = operation.name.split('/operations/')[0]; + let httpOptions = undefined; + if (config && 'httpOptions' in config) { + httpOptions = config.httpOptions; + } + const rawOperation = await this.fetchPredictVideosOperationInternal({ + operationName: operation.name, + resourceName: resourceName, + config: { httpOptions: httpOptions }, + }); + return operation._fromAPIResponse({ + apiResponse: rawOperation, + _isVertexAI: true, + }); + } + else { + const rawOperation = await this.getVideosOperationInternal({ + operationName: operation.name, + config: config, + }); + return operation._fromAPIResponse({ + apiResponse: rawOperation, + _isVertexAI: false, + }); + } + } + async getVideosOperationInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = getOperationParametersToVertex(params); + path = formatMap('{operationName}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response; + } + else { + const body = getOperationParametersToMldev(params); + path = formatMap('{operationName}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response; + } + } + async fetchPredictVideosOperationInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = fetchPredictOperationParametersToVertex(params); + path = formatMap('{resourceName}:fetchPredictOperation', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response; + } + else { + throw new Error('This method is only supported by the Vertex AI.'); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function blobToMldev(fromObject) { + const toObject = {}; + const fromData = getValueByPath(fromObject, ['data']); + if (fromData != null) { + setValueByPath(toObject, ['data'], fromData); + } + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function contentToMldev(fromObject) { + const toObject = {}; + const fromParts = getValueByPath(fromObject, ['parts']); + if (fromParts != null) { + let transformedList = fromParts; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return partToMldev(item); + }); + } + setValueByPath(toObject, ['parts'], transformedList); + } + const fromRole = getValueByPath(fromObject, ['role']); + if (fromRole != null) { + setValueByPath(toObject, ['role'], fromRole); + } + return toObject; +} +function createAuthTokenConfigToMldev(apiClient, fromObject, parentObject) { + const toObject = {}; + const fromExpireTime = getValueByPath(fromObject, ['expireTime']); + if (parentObject !== undefined && fromExpireTime != null) { + setValueByPath(parentObject, ['expireTime'], fromExpireTime); + } + const fromNewSessionExpireTime = getValueByPath(fromObject, [ + 'newSessionExpireTime', + ]); + if (parentObject !== undefined && fromNewSessionExpireTime != null) { + setValueByPath(parentObject, ['newSessionExpireTime'], fromNewSessionExpireTime); + } + const fromUses = getValueByPath(fromObject, ['uses']); + if (parentObject !== undefined && fromUses != null) { + setValueByPath(parentObject, ['uses'], fromUses); + } + const fromLiveConnectConstraints = getValueByPath(fromObject, [ + 'liveConnectConstraints', + ]); + if (parentObject !== undefined && fromLiveConnectConstraints != null) { + setValueByPath(parentObject, ['bidiGenerateContentSetup'], liveConnectConstraintsToMldev(apiClient, fromLiveConnectConstraints)); + } + const fromLockAdditionalFields = getValueByPath(fromObject, [ + 'lockAdditionalFields', + ]); + if (parentObject !== undefined && fromLockAdditionalFields != null) { + setValueByPath(parentObject, ['fieldMask'], fromLockAdditionalFields); + } + return toObject; +} +function createAuthTokenParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['config'], createAuthTokenConfigToMldev(apiClient, fromConfig, toObject)); + } + return toObject; +} +function fileDataToMldev(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromFileUri = getValueByPath(fromObject, ['fileUri']); + if (fromFileUri != null) { + setValueByPath(toObject, ['fileUri'], fromFileUri); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function functionCallToMldev(fromObject) { + const toObject = {}; + const fromId = getValueByPath(fromObject, ['id']); + if (fromId != null) { + setValueByPath(toObject, ['id'], fromId); + } + const fromArgs = getValueByPath(fromObject, ['args']); + if (fromArgs != null) { + setValueByPath(toObject, ['args'], fromArgs); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + if (getValueByPath(fromObject, ['partialArgs']) !== undefined) { + throw new Error('partialArgs parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['willContinue']) !== undefined) { + throw new Error('willContinue parameter is not supported in Gemini API.'); + } + return toObject; +} +function googleMapsToMldev(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['authConfig']) !== undefined) { + throw new Error('authConfig parameter is not supported in Gemini API.'); + } + const fromEnableWidget = getValueByPath(fromObject, ['enableWidget']); + if (fromEnableWidget != null) { + setValueByPath(toObject, ['enableWidget'], fromEnableWidget); + } + return toObject; +} +function googleSearchToMldev(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['excludeDomains']) !== undefined) { + throw new Error('excludeDomains parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['blockingConfidence']) !== undefined) { + throw new Error('blockingConfidence parameter is not supported in Gemini API.'); + } + const fromTimeRangeFilter = getValueByPath(fromObject, [ + 'timeRangeFilter', + ]); + if (fromTimeRangeFilter != null) { + setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter); + } + return toObject; +} +function liveConnectConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromGenerationConfig = getValueByPath(fromObject, [ + 'generationConfig', + ]); + if (parentObject !== undefined && fromGenerationConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig'], fromGenerationConfig); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (parentObject !== undefined && fromResponseModalities != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'responseModalities'], fromResponseModalities); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (parentObject !== undefined && fromTemperature != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'temperature'], fromTemperature); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (parentObject !== undefined && fromTopP != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'topP'], fromTopP); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (parentObject !== undefined && fromTopK != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'topK'], fromTopK); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (parentObject !== undefined && fromMaxOutputTokens != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'maxOutputTokens'], fromMaxOutputTokens); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (parentObject !== undefined && fromMediaResolution != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'mediaResolution'], fromMediaResolution); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (parentObject !== undefined && fromSeed != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'seed'], fromSeed); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (parentObject !== undefined && fromSpeechConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'speechConfig'], tLiveSpeechConfig(fromSpeechConfig)); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (parentObject !== undefined && fromThinkingConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'thinkingConfig'], fromThinkingConfig); + } + const fromEnableAffectiveDialog = getValueByPath(fromObject, [ + 'enableAffectiveDialog', + ]); + if (parentObject !== undefined && fromEnableAffectiveDialog != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'enableAffectiveDialog'], fromEnableAffectiveDialog); + } + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['setup', 'systemInstruction'], contentToMldev(tContent(fromSystemInstruction))); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = tTools(fromTools); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToMldev(tTool(item)); + }); + } + setValueByPath(parentObject, ['setup', 'tools'], transformedList); + } + const fromSessionResumption = getValueByPath(fromObject, [ + 'sessionResumption', + ]); + if (parentObject !== undefined && fromSessionResumption != null) { + setValueByPath(parentObject, ['setup', 'sessionResumption'], sessionResumptionConfigToMldev(fromSessionResumption)); + } + const fromInputAudioTranscription = getValueByPath(fromObject, [ + 'inputAudioTranscription', + ]); + if (parentObject !== undefined && fromInputAudioTranscription != null) { + setValueByPath(parentObject, ['setup', 'inputAudioTranscription'], fromInputAudioTranscription); + } + const fromOutputAudioTranscription = getValueByPath(fromObject, [ + 'outputAudioTranscription', + ]); + if (parentObject !== undefined && fromOutputAudioTranscription != null) { + setValueByPath(parentObject, ['setup', 'outputAudioTranscription'], fromOutputAudioTranscription); + } + const fromRealtimeInputConfig = getValueByPath(fromObject, [ + 'realtimeInputConfig', + ]); + if (parentObject !== undefined && fromRealtimeInputConfig != null) { + setValueByPath(parentObject, ['setup', 'realtimeInputConfig'], fromRealtimeInputConfig); + } + const fromContextWindowCompression = getValueByPath(fromObject, [ + 'contextWindowCompression', + ]); + if (parentObject !== undefined && fromContextWindowCompression != null) { + setValueByPath(parentObject, ['setup', 'contextWindowCompression'], fromContextWindowCompression); + } + const fromProactivity = getValueByPath(fromObject, ['proactivity']); + if (parentObject !== undefined && fromProactivity != null) { + setValueByPath(parentObject, ['setup', 'proactivity'], fromProactivity); + } + if (getValueByPath(fromObject, ['explicitVadSignal']) !== undefined) { + throw new Error('explicitVadSignal parameter is not supported in Gemini API.'); + } + return toObject; +} +function liveConnectConstraintsToMldev(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['setup', 'model'], tModel(apiClient, fromModel)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['config'], liveConnectConfigToMldev(fromConfig, toObject)); + } + return toObject; +} +function partToMldev(fromObject) { + const toObject = {}; + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromCodeExecutionResult = getValueByPath(fromObject, [ + 'codeExecutionResult', + ]); + if (fromCodeExecutionResult != null) { + setValueByPath(toObject, ['codeExecutionResult'], fromCodeExecutionResult); + } + const fromExecutableCode = getValueByPath(fromObject, [ + 'executableCode', + ]); + if (fromExecutableCode != null) { + setValueByPath(toObject, ['executableCode'], fromExecutableCode); + } + const fromFileData = getValueByPath(fromObject, ['fileData']); + if (fromFileData != null) { + setValueByPath(toObject, ['fileData'], fileDataToMldev(fromFileData)); + } + const fromFunctionCall = getValueByPath(fromObject, ['functionCall']); + if (fromFunctionCall != null) { + setValueByPath(toObject, ['functionCall'], functionCallToMldev(fromFunctionCall)); + } + const fromFunctionResponse = getValueByPath(fromObject, [ + 'functionResponse', + ]); + if (fromFunctionResponse != null) { + setValueByPath(toObject, ['functionResponse'], fromFunctionResponse); + } + const fromInlineData = getValueByPath(fromObject, ['inlineData']); + if (fromInlineData != null) { + setValueByPath(toObject, ['inlineData'], blobToMldev(fromInlineData)); + } + const fromText = getValueByPath(fromObject, ['text']); + if (fromText != null) { + setValueByPath(toObject, ['text'], fromText); + } + const fromThought = getValueByPath(fromObject, ['thought']); + if (fromThought != null) { + setValueByPath(toObject, ['thought'], fromThought); + } + const fromThoughtSignature = getValueByPath(fromObject, [ + 'thoughtSignature', + ]); + if (fromThoughtSignature != null) { + setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature); + } + const fromVideoMetadata = getValueByPath(fromObject, [ + 'videoMetadata', + ]); + if (fromVideoMetadata != null) { + setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata); + } + return toObject; +} +function sessionResumptionConfigToMldev(fromObject) { + const toObject = {}; + const fromHandle = getValueByPath(fromObject, ['handle']); + if (fromHandle != null) { + setValueByPath(toObject, ['handle'], fromHandle); + } + if (getValueByPath(fromObject, ['transparent']) !== undefined) { + throw new Error('transparent parameter is not supported in Gemini API.'); + } + return toObject; +} +function toolToMldev(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['retrieval']) !== undefined) { + throw new Error('retrieval parameter is not supported in Gemini API.'); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + const fromFileSearch = getValueByPath(fromObject, ['fileSearch']); + if (fromFileSearch != null) { + setValueByPath(toObject, ['fileSearch'], fromFileSearch); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + if (getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined) { + throw new Error('enterpriseWebSearch parameter is not supported in Gemini API.'); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], googleMapsToMldev(fromGoogleMaps)); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], googleSearchToMldev(fromGoogleSearch)); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Returns a comma-separated list of field masks from a given object. + * + * @param setup The object to extract field masks from. + * @return A comma-separated list of field masks. + */ +function getFieldMasks(setup) { + const fields = []; + for (const key in setup) { + if (Object.prototype.hasOwnProperty.call(setup, key)) { + const value = setup[key]; + // 2nd layer, recursively get field masks see TODO(b/418290100) + if (typeof value === 'object' && + value != null && + Object.keys(value).length > 0) { + const field = Object.keys(value).map((kk) => `${key}.${kk}`); + fields.push(...field); + } + else { + fields.push(key); // 1st layer + } + } + } + return fields.join(','); +} +/** + * Converts bidiGenerateContentSetup. + * @param requestDict - The request dictionary. + * @param config - The configuration object. + * @return - The modified request dictionary. + */ +function convertBidiSetupToTokenSetup(requestDict, config) { + // Convert bidiGenerateContentSetup from bidiGenerateContentSetup.setup. + let setupForMaskGeneration = null; + const bidiGenerateContentSetupValue = requestDict['bidiGenerateContentSetup']; + if (typeof bidiGenerateContentSetupValue === 'object' && + bidiGenerateContentSetupValue !== null && + 'setup' in bidiGenerateContentSetupValue) { + // Now we know bidiGenerateContentSetupValue is an object and has a 'setup' + // property. + const innerSetup = bidiGenerateContentSetupValue + .setup; + if (typeof innerSetup === 'object' && innerSetup !== null) { + // Valid inner setup found. + requestDict['bidiGenerateContentSetup'] = innerSetup; + setupForMaskGeneration = innerSetup; + } + else { + // `bidiGenerateContentSetupValue.setup` is not a valid object; treat as + // if bidiGenerateContentSetup is invalid. + delete requestDict['bidiGenerateContentSetup']; + } + } + else if (bidiGenerateContentSetupValue !== undefined) { + // `bidiGenerateContentSetup` exists but not in the expected + // shape {setup: {...}}; treat as invalid. + delete requestDict['bidiGenerateContentSetup']; + } + const preExistingFieldMask = requestDict['fieldMask']; + // Handle mask generation setup. + if (setupForMaskGeneration) { + const generatedMaskFromBidi = getFieldMasks(setupForMaskGeneration); + if (Array.isArray(config === null || config === void 0 ? void 0 : config.lockAdditionalFields) && + (config === null || config === void 0 ? void 0 : config.lockAdditionalFields.length) === 0) { + // Case 1: lockAdditionalFields is an empty array. Lock only fields from + // bidi setup. + if (generatedMaskFromBidi) { + // Only assign if mask is not empty + requestDict['fieldMask'] = generatedMaskFromBidi; + } + else { + delete requestDict['fieldMask']; // If mask is empty, effectively no + // specific fields locked by bidi + } + } + else if ((config === null || config === void 0 ? void 0 : config.lockAdditionalFields) && + config.lockAdditionalFields.length > 0 && + preExistingFieldMask !== null && + Array.isArray(preExistingFieldMask) && + preExistingFieldMask.length > 0) { + // Case 2: Lock fields from bidi setup + additional fields + // (preExistingFieldMask). + const generationConfigFields = [ + 'temperature', + 'topK', + 'topP', + 'maxOutputTokens', + 'responseModalities', + 'seed', + 'speechConfig', + ]; + let mappedFieldsFromPreExisting = []; + if (preExistingFieldMask.length > 0) { + mappedFieldsFromPreExisting = preExistingFieldMask.map((field) => { + if (generationConfigFields.includes(field)) { + return `generationConfig.${field}`; + } + return field; // Keep original field name if not in + // generationConfigFields + }); + } + const finalMaskParts = []; + if (generatedMaskFromBidi) { + finalMaskParts.push(generatedMaskFromBidi); + } + if (mappedFieldsFromPreExisting.length > 0) { + finalMaskParts.push(...mappedFieldsFromPreExisting); + } + if (finalMaskParts.length > 0) { + requestDict['fieldMask'] = finalMaskParts.join(','); + } + else { + // If no fields from bidi and no valid additional fields from + // pre-existing mask. + delete requestDict['fieldMask']; + } + } + else { + // Case 3: "Lock all fields" (meaning, don't send a field_mask, let server + // defaults apply or all are mutable). This is hit if: + // - `config.lockAdditionalFields` is undefined. + // - `config.lockAdditionalFields` is non-empty, BUT + // `preExistingFieldMask` is null, not a string, or an empty string. + delete requestDict['fieldMask']; + } + } + else { + // No valid `bidiGenerateContentSetup` was found or extracted. + // "Lock additional null fields if any". + if (preExistingFieldMask !== null && + Array.isArray(preExistingFieldMask) && + preExistingFieldMask.length > 0) { + // If there's a pre-existing field mask, it's a string, and it's not + // empty, then we should lock all fields. + requestDict['fieldMask'] = preExistingFieldMask.join(','); + } + else { + delete requestDict['fieldMask']; + } + } + return requestDict; +} +class Tokens extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + } + /** + * Creates an ephemeral auth token resource. + * + * @experimental + * + * @remarks + * Ephemeral auth tokens is only supported in the Gemini Developer API. + * It can be used for the session connection to the Live constrained API. + * Support in v1alpha only. + * + * @param params - The parameters for the create request. + * @return The created auth token. + * + * @example + * ```ts + * const ai = new GoogleGenAI({ + * apiKey: token.name, + * httpOptions: { apiVersion: 'v1alpha' } // Support in v1alpha only. + * }); + * + * // Case 1: If LiveEphemeralParameters is unset, unlock LiveConnectConfig + * // when using the token in Live API sessions. Each session connection can + * // use a different configuration. + * const config: CreateAuthTokenConfig = { + * uses: 3, + * expireTime: '2025-05-01T00:00:00Z', + * } + * const token = await ai.tokens.create(config); + * + * // Case 2: If LiveEphemeralParameters is set, lock all fields in + * // LiveConnectConfig when using the token in Live API sessions. For + * // example, changing `outputAudioTranscription` in the Live API + * // connection will be ignored by the API. + * const config: CreateAuthTokenConfig = + * uses: 3, + * expireTime: '2025-05-01T00:00:00Z', + * LiveEphemeralParameters: { + * model: 'gemini-2.0-flash-001', + * config: { + * 'responseModalities': ['AUDIO'], + * 'systemInstruction': 'Always answer in English.', + * } + * } + * } + * const token = await ai.tokens.create(config); + * + * // Case 3: If LiveEphemeralParameters is set and lockAdditionalFields is + * // set, lock LiveConnectConfig with set and additional fields (e.g. + * // responseModalities, systemInstruction, temperature in this example) when + * // using the token in Live API sessions. + * const config: CreateAuthTokenConfig = + * uses: 3, + * expireTime: '2025-05-01T00:00:00Z', + * LiveEphemeralParameters: { + * model: 'gemini-2.0-flash-001', + * config: { + * 'responseModalities': ['AUDIO'], + * 'systemInstruction': 'Always answer in English.', + * } + * }, + * lockAdditionalFields: ['temperature'], + * } + * const token = await ai.tokens.create(config); + * + * // Case 4: If LiveEphemeralParameters is set and lockAdditionalFields is + * // empty array, lock LiveConnectConfig with set fields (e.g. + * // responseModalities, systemInstruction in this example) when using the + * // token in Live API sessions. + * const config: CreateAuthTokenConfig = + * uses: 3, + * expireTime: '2025-05-01T00:00:00Z', + * LiveEphemeralParameters: { + * model: 'gemini-2.0-flash-001', + * config: { + * 'responseModalities': ['AUDIO'], + * 'systemInstruction': 'Always answer in English.', + * } + * }, + * lockAdditionalFields: [], + * } + * const token = await ai.tokens.create(config); + * ``` + */ + async create(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('The client.tokens.create method is only supported by the Gemini Developer API.'); + } + else { + const body = createAuthTokenParametersToMldev(this.apiClient, params); + path = formatMap('auth_tokens', body['_url']); + queryParams = body['_query']; + delete body['config']; + delete body['_url']; + delete body['_query']; + const transformedBody = convertBidiSetupToTokenSetup(body, params.config); + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(transformedBody), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Code generated by the Google Gen AI SDK generator DO NOT EDIT. +function cancelTuningJobParametersToMldev(fromObject, _rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + return toObject; +} +function cancelTuningJobParametersToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + return toObject; +} +function cancelTuningJobResponseFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function cancelTuningJobResponseFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function createTuningJobConfigToMldev(fromObject, parentObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['validationDataset']) !== undefined) { + throw new Error('validationDataset parameter is not supported in Gemini API.'); + } + const fromTunedModelDisplayName = getValueByPath(fromObject, [ + 'tunedModelDisplayName', + ]); + if (parentObject !== undefined && fromTunedModelDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromTunedModelDisplayName); + } + if (getValueByPath(fromObject, ['description']) !== undefined) { + throw new Error('description parameter is not supported in Gemini API.'); + } + const fromEpochCount = getValueByPath(fromObject, ['epochCount']); + if (parentObject !== undefined && fromEpochCount != null) { + setValueByPath(parentObject, ['tuningTask', 'hyperparameters', 'epochCount'], fromEpochCount); + } + const fromLearningRateMultiplier = getValueByPath(fromObject, [ + 'learningRateMultiplier', + ]); + if (fromLearningRateMultiplier != null) { + setValueByPath(toObject, ['tuningTask', 'hyperparameters', 'learningRateMultiplier'], fromLearningRateMultiplier); + } + if (getValueByPath(fromObject, ['exportLastCheckpointOnly']) !== + undefined) { + throw new Error('exportLastCheckpointOnly parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['preTunedModelCheckpointId']) !== + undefined) { + throw new Error('preTunedModelCheckpointId parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['adapterSize']) !== undefined) { + throw new Error('adapterSize parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['tuningMode']) !== undefined) { + throw new Error('tuningMode parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['customBaseModel']) !== undefined) { + throw new Error('customBaseModel parameter is not supported in Gemini API.'); + } + const fromBatchSize = getValueByPath(fromObject, ['batchSize']); + if (parentObject !== undefined && fromBatchSize != null) { + setValueByPath(parentObject, ['tuningTask', 'hyperparameters', 'batchSize'], fromBatchSize); + } + const fromLearningRate = getValueByPath(fromObject, ['learningRate']); + if (parentObject !== undefined && fromLearningRate != null) { + setValueByPath(parentObject, ['tuningTask', 'hyperparameters', 'learningRate'], fromLearningRate); + } + if (getValueByPath(fromObject, ['labels']) !== undefined) { + throw new Error('labels parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['beta']) !== undefined) { + throw new Error('beta parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['baseTeacherModel']) !== undefined) { + throw new Error('baseTeacherModel parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['tunedTeacherModelSource']) !== undefined) { + throw new Error('tunedTeacherModelSource parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['sftLossWeightMultiplier']) !== undefined) { + throw new Error('sftLossWeightMultiplier parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['outputUri']) !== undefined) { + throw new Error('outputUri parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['encryptionSpec']) !== undefined) { + throw new Error('encryptionSpec parameter is not supported in Gemini API.'); + } + return toObject; +} +function createTuningJobConfigToVertex(fromObject, parentObject, rootObject) { + const toObject = {}; + let discriminatorValidationDataset = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorValidationDataset === undefined) { + discriminatorValidationDataset = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorValidationDataset === 'SUPERVISED_FINE_TUNING') { + const fromValidationDataset = getValueByPath(fromObject, [ + 'validationDataset', + ]); + if (parentObject !== undefined && fromValidationDataset != null) { + setValueByPath(parentObject, ['supervisedTuningSpec'], tuningValidationDatasetToVertex(fromValidationDataset)); + } + } + else if (discriminatorValidationDataset === 'PREFERENCE_TUNING') { + const fromValidationDataset = getValueByPath(fromObject, [ + 'validationDataset', + ]); + if (parentObject !== undefined && fromValidationDataset != null) { + setValueByPath(parentObject, ['preferenceOptimizationSpec'], tuningValidationDatasetToVertex(fromValidationDataset)); + } + } + else if (discriminatorValidationDataset === 'DISTILLATION') { + const fromValidationDataset = getValueByPath(fromObject, [ + 'validationDataset', + ]); + if (parentObject !== undefined && fromValidationDataset != null) { + setValueByPath(parentObject, ['distillationSpec'], tuningValidationDatasetToVertex(fromValidationDataset)); + } + } + const fromTunedModelDisplayName = getValueByPath(fromObject, [ + 'tunedModelDisplayName', + ]); + if (parentObject !== undefined && fromTunedModelDisplayName != null) { + setValueByPath(parentObject, ['tunedModelDisplayName'], fromTunedModelDisplayName); + } + const fromDescription = getValueByPath(fromObject, ['description']); + if (parentObject !== undefined && fromDescription != null) { + setValueByPath(parentObject, ['description'], fromDescription); + } + let discriminatorEpochCount = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorEpochCount === undefined) { + discriminatorEpochCount = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorEpochCount === 'SUPERVISED_FINE_TUNING') { + const fromEpochCount = getValueByPath(fromObject, ['epochCount']); + if (parentObject !== undefined && fromEpochCount != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'hyperParameters', 'epochCount'], fromEpochCount); + } + } + else if (discriminatorEpochCount === 'PREFERENCE_TUNING') { + const fromEpochCount = getValueByPath(fromObject, ['epochCount']); + if (parentObject !== undefined && fromEpochCount != null) { + setValueByPath(parentObject, ['preferenceOptimizationSpec', 'hyperParameters', 'epochCount'], fromEpochCount); + } + } + else if (discriminatorEpochCount === 'DISTILLATION') { + const fromEpochCount = getValueByPath(fromObject, ['epochCount']); + if (parentObject !== undefined && fromEpochCount != null) { + setValueByPath(parentObject, ['distillationSpec', 'hyperParameters', 'epochCount'], fromEpochCount); + } + } + let discriminatorLearningRateMultiplier = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorLearningRateMultiplier === undefined) { + discriminatorLearningRateMultiplier = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorLearningRateMultiplier === 'SUPERVISED_FINE_TUNING') { + const fromLearningRateMultiplier = getValueByPath(fromObject, [ + 'learningRateMultiplier', + ]); + if (parentObject !== undefined && fromLearningRateMultiplier != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'hyperParameters', 'learningRateMultiplier'], fromLearningRateMultiplier); + } + } + else if (discriminatorLearningRateMultiplier === 'PREFERENCE_TUNING') { + const fromLearningRateMultiplier = getValueByPath(fromObject, [ + 'learningRateMultiplier', + ]); + if (parentObject !== undefined && fromLearningRateMultiplier != null) { + setValueByPath(parentObject, [ + 'preferenceOptimizationSpec', + 'hyperParameters', + 'learningRateMultiplier', + ], fromLearningRateMultiplier); + } + } + else if (discriminatorLearningRateMultiplier === 'DISTILLATION') { + const fromLearningRateMultiplier = getValueByPath(fromObject, [ + 'learningRateMultiplier', + ]); + if (parentObject !== undefined && fromLearningRateMultiplier != null) { + setValueByPath(parentObject, ['distillationSpec', 'hyperParameters', 'learningRateMultiplier'], fromLearningRateMultiplier); + } + } + let discriminatorExportLastCheckpointOnly = getValueByPath(rootObject, ['config', 'method']); + if (discriminatorExportLastCheckpointOnly === undefined) { + discriminatorExportLastCheckpointOnly = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorExportLastCheckpointOnly === 'SUPERVISED_FINE_TUNING') { + const fromExportLastCheckpointOnly = getValueByPath(fromObject, [ + 'exportLastCheckpointOnly', + ]); + if (parentObject !== undefined && fromExportLastCheckpointOnly != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'exportLastCheckpointOnly'], fromExportLastCheckpointOnly); + } + } + else if (discriminatorExportLastCheckpointOnly === 'PREFERENCE_TUNING') { + const fromExportLastCheckpointOnly = getValueByPath(fromObject, [ + 'exportLastCheckpointOnly', + ]); + if (parentObject !== undefined && fromExportLastCheckpointOnly != null) { + setValueByPath(parentObject, ['preferenceOptimizationSpec', 'exportLastCheckpointOnly'], fromExportLastCheckpointOnly); + } + } + else if (discriminatorExportLastCheckpointOnly === 'DISTILLATION') { + const fromExportLastCheckpointOnly = getValueByPath(fromObject, [ + 'exportLastCheckpointOnly', + ]); + if (parentObject !== undefined && fromExportLastCheckpointOnly != null) { + setValueByPath(parentObject, ['distillationSpec', 'exportLastCheckpointOnly'], fromExportLastCheckpointOnly); + } + } + let discriminatorAdapterSize = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorAdapterSize === undefined) { + discriminatorAdapterSize = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorAdapterSize === 'SUPERVISED_FINE_TUNING') { + const fromAdapterSize = getValueByPath(fromObject, ['adapterSize']); + if (parentObject !== undefined && fromAdapterSize != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'hyperParameters', 'adapterSize'], fromAdapterSize); + } + } + else if (discriminatorAdapterSize === 'PREFERENCE_TUNING') { + const fromAdapterSize = getValueByPath(fromObject, ['adapterSize']); + if (parentObject !== undefined && fromAdapterSize != null) { + setValueByPath(parentObject, ['preferenceOptimizationSpec', 'hyperParameters', 'adapterSize'], fromAdapterSize); + } + } + else if (discriminatorAdapterSize === 'DISTILLATION') { + const fromAdapterSize = getValueByPath(fromObject, ['adapterSize']); + if (parentObject !== undefined && fromAdapterSize != null) { + setValueByPath(parentObject, ['distillationSpec', 'hyperParameters', 'adapterSize'], fromAdapterSize); + } + } + let discriminatorTuningMode = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorTuningMode === undefined) { + discriminatorTuningMode = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorTuningMode === 'SUPERVISED_FINE_TUNING') { + const fromTuningMode = getValueByPath(fromObject, ['tuningMode']); + if (parentObject !== undefined && fromTuningMode != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'tuningMode'], fromTuningMode); + } + } + const fromCustomBaseModel = getValueByPath(fromObject, [ + 'customBaseModel', + ]); + if (parentObject !== undefined && fromCustomBaseModel != null) { + setValueByPath(parentObject, ['customBaseModel'], fromCustomBaseModel); + } + let discriminatorBatchSize = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorBatchSize === undefined) { + discriminatorBatchSize = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorBatchSize === 'SUPERVISED_FINE_TUNING') { + const fromBatchSize = getValueByPath(fromObject, ['batchSize']); + if (parentObject !== undefined && fromBatchSize != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'hyperParameters', 'batchSize'], fromBatchSize); + } + } + let discriminatorLearningRate = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorLearningRate === undefined) { + discriminatorLearningRate = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorLearningRate === 'SUPERVISED_FINE_TUNING') { + const fromLearningRate = getValueByPath(fromObject, [ + 'learningRate', + ]); + if (parentObject !== undefined && fromLearningRate != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'hyperParameters', 'learningRate'], fromLearningRate); + } + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (parentObject !== undefined && fromLabels != null) { + setValueByPath(parentObject, ['labels'], fromLabels); + } + const fromBeta = getValueByPath(fromObject, ['beta']); + if (parentObject !== undefined && fromBeta != null) { + setValueByPath(parentObject, ['preferenceOptimizationSpec', 'hyperParameters', 'beta'], fromBeta); + } + const fromBaseTeacherModel = getValueByPath(fromObject, [ + 'baseTeacherModel', + ]); + if (parentObject !== undefined && fromBaseTeacherModel != null) { + setValueByPath(parentObject, ['distillationSpec', 'baseTeacherModel'], fromBaseTeacherModel); + } + const fromTunedTeacherModelSource = getValueByPath(fromObject, [ + 'tunedTeacherModelSource', + ]); + if (parentObject !== undefined && fromTunedTeacherModelSource != null) { + setValueByPath(parentObject, ['distillationSpec', 'tunedTeacherModelSource'], fromTunedTeacherModelSource); + } + const fromSftLossWeightMultiplier = getValueByPath(fromObject, [ + 'sftLossWeightMultiplier', + ]); + if (parentObject !== undefined && fromSftLossWeightMultiplier != null) { + setValueByPath(parentObject, ['distillationSpec', 'hyperParameters', 'sftLossWeightMultiplier'], fromSftLossWeightMultiplier); + } + const fromOutputUri = getValueByPath(fromObject, ['outputUri']); + if (parentObject !== undefined && fromOutputUri != null) { + setValueByPath(parentObject, ['outputUri'], fromOutputUri); + } + const fromEncryptionSpec = getValueByPath(fromObject, [ + 'encryptionSpec', + ]); + if (parentObject !== undefined && fromEncryptionSpec != null) { + setValueByPath(parentObject, ['encryptionSpec'], fromEncryptionSpec); + } + return toObject; +} +function createTuningJobParametersPrivateToMldev(fromObject, rootObject) { + const toObject = {}; + const fromBaseModel = getValueByPath(fromObject, ['baseModel']); + if (fromBaseModel != null) { + setValueByPath(toObject, ['baseModel'], fromBaseModel); + } + const fromPreTunedModel = getValueByPath(fromObject, [ + 'preTunedModel', + ]); + if (fromPreTunedModel != null) { + setValueByPath(toObject, ['preTunedModel'], fromPreTunedModel); + } + const fromTrainingDataset = getValueByPath(fromObject, [ + 'trainingDataset', + ]); + if (fromTrainingDataset != null) { + tuningDatasetToMldev(fromTrainingDataset); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createTuningJobConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function createTuningJobParametersPrivateToVertex(fromObject, rootObject) { + const toObject = {}; + const fromBaseModel = getValueByPath(fromObject, ['baseModel']); + if (fromBaseModel != null) { + setValueByPath(toObject, ['baseModel'], fromBaseModel); + } + const fromPreTunedModel = getValueByPath(fromObject, [ + 'preTunedModel', + ]); + if (fromPreTunedModel != null) { + setValueByPath(toObject, ['preTunedModel'], fromPreTunedModel); + } + const fromTrainingDataset = getValueByPath(fromObject, [ + 'trainingDataset', + ]); + if (fromTrainingDataset != null) { + tuningDatasetToVertex(fromTrainingDataset, toObject, rootObject); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createTuningJobConfigToVertex(fromConfig, toObject, rootObject); + } + return toObject; +} +function getTuningJobParametersToMldev(fromObject, _rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + return toObject; +} +function getTuningJobParametersToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + return toObject; +} +function listTuningJobsConfigToMldev(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + const fromFilter = getValueByPath(fromObject, ['filter']); + if (parentObject !== undefined && fromFilter != null) { + setValueByPath(parentObject, ['_query', 'filter'], fromFilter); + } + return toObject; +} +function listTuningJobsConfigToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + const fromFilter = getValueByPath(fromObject, ['filter']); + if (parentObject !== undefined && fromFilter != null) { + setValueByPath(parentObject, ['_query', 'filter'], fromFilter); + } + return toObject; +} +function listTuningJobsParametersToMldev(fromObject, rootObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listTuningJobsConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function listTuningJobsParametersToVertex(fromObject, rootObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listTuningJobsConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function listTuningJobsResponseFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromTuningJobs = getValueByPath(fromObject, ['tunedModels']); + if (fromTuningJobs != null) { + let transformedList = fromTuningJobs; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return tuningJobFromMldev(item); + }); + } + setValueByPath(toObject, ['tuningJobs'], transformedList); + } + return toObject; +} +function listTuningJobsResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromTuningJobs = getValueByPath(fromObject, ['tuningJobs']); + if (fromTuningJobs != null) { + let transformedList = fromTuningJobs; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return tuningJobFromVertex(item); + }); + } + setValueByPath(toObject, ['tuningJobs'], transformedList); + } + return toObject; +} +function tunedModelFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['name']); + if (fromModel != null) { + setValueByPath(toObject, ['model'], fromModel); + } + const fromEndpoint = getValueByPath(fromObject, ['name']); + if (fromEndpoint != null) { + setValueByPath(toObject, ['endpoint'], fromEndpoint); + } + return toObject; +} +function tuningDatasetToMldev(fromObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['gcsUri']) !== undefined) { + throw new Error('gcsUri parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['vertexDatasetResource']) !== undefined) { + throw new Error('vertexDatasetResource parameter is not supported in Gemini API.'); + } + const fromExamples = getValueByPath(fromObject, ['examples']); + if (fromExamples != null) { + let transformedList = fromExamples; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['examples', 'examples'], transformedList); + } + return toObject; +} +function tuningDatasetToVertex(fromObject, parentObject, rootObject) { + const toObject = {}; + let discriminatorGcsUri = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorGcsUri === undefined) { + discriminatorGcsUri = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorGcsUri === 'SUPERVISED_FINE_TUNING') { + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (parentObject !== undefined && fromGcsUri != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'trainingDatasetUri'], fromGcsUri); + } + } + else if (discriminatorGcsUri === 'PREFERENCE_TUNING') { + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (parentObject !== undefined && fromGcsUri != null) { + setValueByPath(parentObject, ['preferenceOptimizationSpec', 'trainingDatasetUri'], fromGcsUri); + } + } + else if (discriminatorGcsUri === 'DISTILLATION') { + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (parentObject !== undefined && fromGcsUri != null) { + setValueByPath(parentObject, ['distillationSpec', 'promptDatasetUri'], fromGcsUri); + } + } + let discriminatorVertexDatasetResource = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorVertexDatasetResource === undefined) { + discriminatorVertexDatasetResource = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorVertexDatasetResource === 'SUPERVISED_FINE_TUNING') { + const fromVertexDatasetResource = getValueByPath(fromObject, [ + 'vertexDatasetResource', + ]); + if (parentObject !== undefined && fromVertexDatasetResource != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'trainingDatasetUri'], fromVertexDatasetResource); + } + } + else if (discriminatorVertexDatasetResource === 'PREFERENCE_TUNING') { + const fromVertexDatasetResource = getValueByPath(fromObject, [ + 'vertexDatasetResource', + ]); + if (parentObject !== undefined && fromVertexDatasetResource != null) { + setValueByPath(parentObject, ['preferenceOptimizationSpec', 'trainingDatasetUri'], fromVertexDatasetResource); + } + } + else if (discriminatorVertexDatasetResource === 'DISTILLATION') { + const fromVertexDatasetResource = getValueByPath(fromObject, [ + 'vertexDatasetResource', + ]); + if (parentObject !== undefined && fromVertexDatasetResource != null) { + setValueByPath(parentObject, ['distillationSpec', 'promptDatasetUri'], fromVertexDatasetResource); + } + } + if (getValueByPath(fromObject, ['examples']) !== undefined) { + throw new Error('examples parameter is not supported in Vertex AI.'); + } + return toObject; +} +function tuningJobFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromState = getValueByPath(fromObject, ['state']); + if (fromState != null) { + setValueByPath(toObject, ['state'], tTuningJobStatus(fromState)); + } + const fromCreateTime = getValueByPath(fromObject, ['createTime']); + if (fromCreateTime != null) { + setValueByPath(toObject, ['createTime'], fromCreateTime); + } + const fromStartTime = getValueByPath(fromObject, [ + 'tuningTask', + 'startTime', + ]); + if (fromStartTime != null) { + setValueByPath(toObject, ['startTime'], fromStartTime); + } + const fromEndTime = getValueByPath(fromObject, [ + 'tuningTask', + 'completeTime', + ]); + if (fromEndTime != null) { + setValueByPath(toObject, ['endTime'], fromEndTime); + } + const fromUpdateTime = getValueByPath(fromObject, ['updateTime']); + if (fromUpdateTime != null) { + setValueByPath(toObject, ['updateTime'], fromUpdateTime); + } + const fromDescription = getValueByPath(fromObject, ['description']); + if (fromDescription != null) { + setValueByPath(toObject, ['description'], fromDescription); + } + const fromBaseModel = getValueByPath(fromObject, ['baseModel']); + if (fromBaseModel != null) { + setValueByPath(toObject, ['baseModel'], fromBaseModel); + } + const fromTunedModel = getValueByPath(fromObject, ['_self']); + if (fromTunedModel != null) { + setValueByPath(toObject, ['tunedModel'], tunedModelFromMldev(fromTunedModel)); + } + return toObject; +} +function tuningJobFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromState = getValueByPath(fromObject, ['state']); + if (fromState != null) { + setValueByPath(toObject, ['state'], tTuningJobStatus(fromState)); + } + const fromCreateTime = getValueByPath(fromObject, ['createTime']); + if (fromCreateTime != null) { + setValueByPath(toObject, ['createTime'], fromCreateTime); + } + const fromStartTime = getValueByPath(fromObject, ['startTime']); + if (fromStartTime != null) { + setValueByPath(toObject, ['startTime'], fromStartTime); + } + const fromEndTime = getValueByPath(fromObject, ['endTime']); + if (fromEndTime != null) { + setValueByPath(toObject, ['endTime'], fromEndTime); + } + const fromUpdateTime = getValueByPath(fromObject, ['updateTime']); + if (fromUpdateTime != null) { + setValueByPath(toObject, ['updateTime'], fromUpdateTime); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromDescription = getValueByPath(fromObject, ['description']); + if (fromDescription != null) { + setValueByPath(toObject, ['description'], fromDescription); + } + const fromBaseModel = getValueByPath(fromObject, ['baseModel']); + if (fromBaseModel != null) { + setValueByPath(toObject, ['baseModel'], fromBaseModel); + } + const fromTunedModel = getValueByPath(fromObject, ['tunedModel']); + if (fromTunedModel != null) { + setValueByPath(toObject, ['tunedModel'], fromTunedModel); + } + const fromPreTunedModel = getValueByPath(fromObject, [ + 'preTunedModel', + ]); + if (fromPreTunedModel != null) { + setValueByPath(toObject, ['preTunedModel'], fromPreTunedModel); + } + const fromSupervisedTuningSpec = getValueByPath(fromObject, [ + 'supervisedTuningSpec', + ]); + if (fromSupervisedTuningSpec != null) { + setValueByPath(toObject, ['supervisedTuningSpec'], fromSupervisedTuningSpec); + } + const fromPreferenceOptimizationSpec = getValueByPath(fromObject, [ + 'preferenceOptimizationSpec', + ]); + if (fromPreferenceOptimizationSpec != null) { + setValueByPath(toObject, ['preferenceOptimizationSpec'], fromPreferenceOptimizationSpec); + } + const fromDistillationSpec = getValueByPath(fromObject, [ + 'distillationSpec', + ]); + if (fromDistillationSpec != null) { + setValueByPath(toObject, ['distillationSpec'], fromDistillationSpec); + } + const fromTuningDataStats = getValueByPath(fromObject, [ + 'tuningDataStats', + ]); + if (fromTuningDataStats != null) { + setValueByPath(toObject, ['tuningDataStats'], fromTuningDataStats); + } + const fromEncryptionSpec = getValueByPath(fromObject, [ + 'encryptionSpec', + ]); + if (fromEncryptionSpec != null) { + setValueByPath(toObject, ['encryptionSpec'], fromEncryptionSpec); + } + const fromPartnerModelTuningSpec = getValueByPath(fromObject, [ + 'partnerModelTuningSpec', + ]); + if (fromPartnerModelTuningSpec != null) { + setValueByPath(toObject, ['partnerModelTuningSpec'], fromPartnerModelTuningSpec); + } + const fromCustomBaseModel = getValueByPath(fromObject, [ + 'customBaseModel', + ]); + if (fromCustomBaseModel != null) { + setValueByPath(toObject, ['customBaseModel'], fromCustomBaseModel); + } + const fromExperiment = getValueByPath(fromObject, ['experiment']); + if (fromExperiment != null) { + setValueByPath(toObject, ['experiment'], fromExperiment); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (fromLabels != null) { + setValueByPath(toObject, ['labels'], fromLabels); + } + const fromOutputUri = getValueByPath(fromObject, ['outputUri']); + if (fromOutputUri != null) { + setValueByPath(toObject, ['outputUri'], fromOutputUri); + } + const fromPipelineJob = getValueByPath(fromObject, ['pipelineJob']); + if (fromPipelineJob != null) { + setValueByPath(toObject, ['pipelineJob'], fromPipelineJob); + } + const fromServiceAccount = getValueByPath(fromObject, [ + 'serviceAccount', + ]); + if (fromServiceAccount != null) { + setValueByPath(toObject, ['serviceAccount'], fromServiceAccount); + } + const fromTunedModelDisplayName = getValueByPath(fromObject, [ + 'tunedModelDisplayName', + ]); + if (fromTunedModelDisplayName != null) { + setValueByPath(toObject, ['tunedModelDisplayName'], fromTunedModelDisplayName); + } + const fromVeoTuningSpec = getValueByPath(fromObject, [ + 'veoTuningSpec', + ]); + if (fromVeoTuningSpec != null) { + setValueByPath(toObject, ['veoTuningSpec'], fromVeoTuningSpec); + } + return toObject; +} +function tuningOperationFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + return toObject; +} +function tuningValidationDatasetToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (fromGcsUri != null) { + setValueByPath(toObject, ['validationDatasetUri'], fromGcsUri); + } + const fromVertexDatasetResource = getValueByPath(fromObject, [ + 'vertexDatasetResource', + ]); + if (fromVertexDatasetResource != null) { + setValueByPath(toObject, ['validationDatasetUri'], fromVertexDatasetResource); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Tunings extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + /** + * Lists tuning jobs. + * + * @param params - The parameters for the list request. + * @return - A pager of tuning jobs. + * + * @example + * ```ts + * const tuningJobs = await ai.tunings.list({config: {'pageSize': 2}}); + * for await (const tuningJob of tuningJobs) { + * console.log(tuningJob); + * } + * ``` + */ + this.list = async (params = {}) => { + return new Pager(exports.PagedItem.PAGED_ITEM_TUNING_JOBS, (x) => this.listInternal(x), await this.listInternal(params), params); + }; + /** + * Gets a TuningJob. + * + * @param name - The resource name of the tuning job. + * @return - A TuningJob object. + * + * @experimental - The SDK's tuning implementation is experimental, and may + * change in future versions. + */ + this.get = async (params) => { + return await this.getInternal(params); + }; + /** + * Creates a supervised fine-tuning job. + * + * @param params - The parameters for the tuning job. + * @return - A TuningJob operation. + * + * @experimental - The SDK's tuning implementation is experimental, and may + * change in future versions. + */ + this.tune = async (params) => { + var _a; + if (this.apiClient.isVertexAI()) { + if (params.baseModel.startsWith('projects/')) { + const preTunedModel = { + tunedModelName: params.baseModel, + }; + if ((_a = params.config) === null || _a === void 0 ? void 0 : _a.preTunedModelCheckpointId) { + preTunedModel.checkpointId = params.config.preTunedModelCheckpointId; + } + const paramsPrivate = Object.assign(Object.assign({}, params), { preTunedModel: preTunedModel }); + paramsPrivate.baseModel = undefined; + return await this.tuneInternal(paramsPrivate); + } + else { + const paramsPrivate = Object.assign({}, params); + return await this.tuneInternal(paramsPrivate); + } + } + else { + const paramsPrivate = Object.assign({}, params); + const operation = await this.tuneMldevInternal(paramsPrivate); + let tunedModelName = ''; + if (operation['metadata'] !== undefined && + operation['metadata']['tunedModel'] !== undefined) { + tunedModelName = operation['metadata']['tunedModel']; + } + else if (operation['name'] !== undefined && + operation['name'].includes('/operations/')) { + tunedModelName = operation['name'].split('/operations/')[0]; + } + const tuningJob = { + name: tunedModelName, + state: exports.JobState.JOB_STATE_QUEUED, + }; + return tuningJob; + } + }; + } + async getInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = getTuningJobParametersToVertex(params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = tuningJobFromVertex(apiResponse); + return resp; + }); + } + else { + const body = getTuningJobParametersToMldev(params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = tuningJobFromMldev(apiResponse); + return resp; + }); + } + } + async listInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = listTuningJobsParametersToVertex(params); + path = formatMap('tuningJobs', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listTuningJobsResponseFromVertex(apiResponse); + const typedResp = new ListTuningJobsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = listTuningJobsParametersToMldev(params); + path = formatMap('tunedModels', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listTuningJobsResponseFromMldev(apiResponse); + const typedResp = new ListTuningJobsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Cancels a tuning job. + * + * @param params - The parameters for the cancel request. + * @return The empty response returned by the API. + * + * @example + * ```ts + * await ai.tunings.cancel({name: '...'}); // The server-generated resource name. + * ``` + */ + async cancel(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = cancelTuningJobParametersToVertex(params); + path = formatMap('{name}:cancel', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = cancelTuningJobResponseFromVertex(apiResponse); + const typedResp = new CancelTuningJobResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = cancelTuningJobParametersToMldev(params); + path = formatMap('{name}:cancel', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = cancelTuningJobResponseFromMldev(apiResponse); + const typedResp = new CancelTuningJobResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + async tuneInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = createTuningJobParametersPrivateToVertex(params, params); + path = formatMap('tuningJobs', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = tuningJobFromVertex(apiResponse); + return resp; + }); + } + else { + throw new Error('This method is only supported by the Vertex AI.'); + } + } + async tuneMldevInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = createTuningJobParametersPrivateToMldev(params); + path = formatMap('tunedModels', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = tuningOperationFromMldev(apiResponse); + return resp; + }); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const GOOGLE_API_KEY_HEADER = 'x-goog-api-key'; +// TODO(b/395122533): We need a secure client side authentication mechanism. +class WebAuth { + constructor(apiKey) { + this.apiKey = apiKey; + } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async addAuthHeaders(headers, url) { + if (headers.get(GOOGLE_API_KEY_HEADER) !== null) { + return; + } + if (this.apiKey.startsWith('auth_tokens/')) { + throw new Error('Ephemeral tokens are only supported by the live API.'); + } + // Check if API key is empty or null + if (!this.apiKey) { + throw new Error('API key is missing. Please provide a valid API key.'); + } + headers.append(GOOGLE_API_KEY_HEADER, this.apiKey); + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const LANGUAGE_LABEL_PREFIX = 'gl-node/'; +/** + * The Google GenAI SDK. + * + * @remarks + * Provides access to the GenAI features through either the {@link https://cloud.google.com/vertex-ai/docs/reference/rest | Gemini API} + * or the {@link https://cloud.google.com/vertex-ai/docs/reference/rest | Vertex AI API}. + * + * The {@link GoogleGenAIOptions.vertexai} value determines which of the API services to use. + * + * When using the Gemini API, a {@link GoogleGenAIOptions.apiKey} must also be set, + * when using Vertex AI {@link GoogleGenAIOptions.project} and {@link GoogleGenAIOptions.location} must also be set. + * + * @example + * Initializing the SDK for using the Gemini API: + * ```ts + * import {GoogleGenAI} from '@google/genai'; + * const ai = new GoogleGenAI({apiKey: 'GEMINI_API_KEY'}); + * ``` + * + * @example + * Initializing the SDK for using the Vertex AI API: + * ```ts + * import {GoogleGenAI} from '@google/genai'; + * const ai = new GoogleGenAI({ + * vertexai: true, + * project: 'PROJECT_ID', + * location: 'PROJECT_LOCATION' + * }); + * ``` + * + */ +class GoogleGenAI { + get interactions() { + var _a; + if (this._interactions !== undefined) { + return this._interactions; + } + console.warn('GoogleGenAI.interactions: Interactions usage is experimental and may change in future versions.'); + if (this.vertexai) { + throw new Error('This version of the GenAI SDK does not support Vertex AI API for interactions.'); + } + const httpOpts = this.httpOptions; + // Unsupported Options Warnings + if (httpOpts === null || httpOpts === void 0 ? void 0 : httpOpts.extraBody) { + console.warn('GoogleGenAI.interactions: Client level httpOptions.extraBody is not supported by the interactions client and will be ignored.'); + } + const nextGenClient = new GeminiNextGenAPIClient({ + baseURL: this.apiClient.getBaseUrl(), + apiKey: this.apiKey, + apiVersion: this.apiClient.getApiVersion(), + clientAdapter: this.apiClient, + defaultHeaders: this.apiClient.getDefaultHeaders(), + timeout: httpOpts === null || httpOpts === void 0 ? void 0 : httpOpts.timeout, + maxRetries: (_a = httpOpts === null || httpOpts === void 0 ? void 0 : httpOpts.retryOptions) === null || _a === void 0 ? void 0 : _a.attempts, + }); + this._interactions = nextGenClient.interactions; + return this._interactions; + } + constructor(options) { + var _a; + if (options.apiKey == null) { + throw new Error(`An API Key must be set when running in an unspecified environment.\n + ${crossError().message}`); + } + this.vertexai = (_a = options.vertexai) !== null && _a !== void 0 ? _a : false; + this.apiKey = options.apiKey; + this.apiVersion = options.apiVersion; + this.httpOptions = options.httpOptions; + const auth = new WebAuth(this.apiKey); + this.apiClient = new ApiClient({ + auth: auth, + apiVersion: this.apiVersion, + apiKey: this.apiKey, + vertexai: this.vertexai, + httpOptions: this.httpOptions, + userAgentExtra: LANGUAGE_LABEL_PREFIX + 'cross', + uploader: new CrossUploader(), + downloader: new CrossDownloader(), + }); + this.models = new Models(this.apiClient); + this.live = new Live(this.apiClient, auth, new CrossWebSocketFactory()); + this.chats = new Chats(this.models, this.apiClient); + this.batches = new Batches(this.apiClient); + this.caches = new Caches(this.apiClient); + this.files = new Files(this.apiClient); + this.operations = new Operations(this.apiClient); + this.authTokens = new Tokens(this.apiClient); + this.tunings = new Tunings(this.apiClient); + this.fileSearchStores = new FileSearchStores(this.apiClient); + } +} + +exports.ApiError = ApiError; +exports.Batches = Batches; +exports.Caches = Caches; +exports.CancelTuningJobResponse = CancelTuningJobResponse; +exports.Chat = Chat; +exports.Chats = Chats; +exports.ComputeTokensResponse = ComputeTokensResponse; +exports.ContentReferenceImage = ContentReferenceImage; +exports.ControlReferenceImage = ControlReferenceImage; +exports.CountTokensResponse = CountTokensResponse; +exports.CreateFileResponse = CreateFileResponse; +exports.DeleteCachedContentResponse = DeleteCachedContentResponse; +exports.DeleteFileResponse = DeleteFileResponse; +exports.DeleteModelResponse = DeleteModelResponse; +exports.EditImageResponse = EditImageResponse; +exports.EmbedContentResponse = EmbedContentResponse; +exports.Files = Files; +exports.FunctionResponse = FunctionResponse; +exports.FunctionResponseBlob = FunctionResponseBlob; +exports.FunctionResponseFileData = FunctionResponseFileData; +exports.FunctionResponsePart = FunctionResponsePart; +exports.GenerateContentResponse = GenerateContentResponse; +exports.GenerateContentResponsePromptFeedback = GenerateContentResponsePromptFeedback; +exports.GenerateContentResponseUsageMetadata = GenerateContentResponseUsageMetadata; +exports.GenerateImagesResponse = GenerateImagesResponse; +exports.GenerateVideosOperation = GenerateVideosOperation; +exports.GenerateVideosResponse = GenerateVideosResponse; +exports.GoogleGenAI = GoogleGenAI; +exports.HttpResponse = HttpResponse; +exports.ImportFileOperation = ImportFileOperation; +exports.ImportFileResponse = ImportFileResponse; +exports.InlinedEmbedContentResponse = InlinedEmbedContentResponse; +exports.InlinedResponse = InlinedResponse; +exports.ListBatchJobsResponse = ListBatchJobsResponse; +exports.ListCachedContentsResponse = ListCachedContentsResponse; +exports.ListDocumentsResponse = ListDocumentsResponse; +exports.ListFileSearchStoresResponse = ListFileSearchStoresResponse; +exports.ListFilesResponse = ListFilesResponse; +exports.ListModelsResponse = ListModelsResponse; +exports.ListTuningJobsResponse = ListTuningJobsResponse; +exports.Live = Live; +exports.LiveClientToolResponse = LiveClientToolResponse; +exports.LiveMusicServerMessage = LiveMusicServerMessage; +exports.LiveSendToolResponseParameters = LiveSendToolResponseParameters; +exports.LiveServerMessage = LiveServerMessage; +exports.MaskReferenceImage = MaskReferenceImage; +exports.Models = Models; +exports.Operations = Operations; +exports.Pager = Pager; +exports.RawReferenceImage = RawReferenceImage; +exports.RecontextImageResponse = RecontextImageResponse; +exports.RegisterFilesResponse = RegisterFilesResponse; +exports.ReplayResponse = ReplayResponse; +exports.SegmentImageResponse = SegmentImageResponse; +exports.Session = Session; +exports.SingleEmbedContentResponse = SingleEmbedContentResponse; +exports.StyleReferenceImage = StyleReferenceImage; +exports.SubjectReferenceImage = SubjectReferenceImage; +exports.Tokens = Tokens; +exports.UploadToFileSearchStoreOperation = UploadToFileSearchStoreOperation; +exports.UploadToFileSearchStoreResponse = UploadToFileSearchStoreResponse; +exports.UploadToFileSearchStoreResumableResponse = UploadToFileSearchStoreResumableResponse; +exports.UpscaleImageResponse = UpscaleImageResponse; +exports.createFunctionResponsePartFromBase64 = createFunctionResponsePartFromBase64; +exports.createFunctionResponsePartFromUri = createFunctionResponsePartFromUri; +exports.createModelContent = createModelContent; +exports.createPartFromBase64 = createPartFromBase64; +exports.createPartFromCodeExecutionResult = createPartFromCodeExecutionResult; +exports.createPartFromExecutableCode = createPartFromExecutableCode; +exports.createPartFromFunctionCall = createPartFromFunctionCall; +exports.createPartFromFunctionResponse = createPartFromFunctionResponse; +exports.createPartFromText = createPartFromText; +exports.createPartFromUri = createPartFromUri; +exports.createUserContent = createUserContent; +exports.mcpToTool = mcpToTool; +exports.setDefaultBaseUrls = setDefaultBaseUrls; +//# sourceMappingURL=index.cjs.map diff --git a/server/node_modules/@google/genai/dist/index.mjs b/server/node_modules/@google/genai/dist/index.mjs new file mode 100644 index 0000000..7e1fc07 --- /dev/null +++ b/server/node_modules/@google/genai/dist/index.mjs @@ -0,0 +1,19518 @@ +import pRetry, { AbortError } from 'p-retry'; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Overrides the base URLs for the Gemini API and Vertex AI API. + * + * @remarks This function should be called before initializing the SDK. If the + * base URLs are set after initializing the SDK, the base URLs will not be + * updated. Base URLs provided in the HttpOptions will also take precedence over + * URLs set here. + * + * @example + * ```ts + * import {GoogleGenAI, setDefaultBaseUrls} from '@google/genai'; + * // Override the base URL for the Gemini API. + * setDefaultBaseUrls({geminiUrl:'https://gemini.google.com'}); + * + * // Override the base URL for the Vertex AI API. + * setDefaultBaseUrls({vertexUrl: 'https://vertexai.googleapis.com'}); + * + * const ai = new GoogleGenAI({apiKey: 'GEMINI_API_KEY'}); + * ``` + */ +function setDefaultBaseUrls(baseUrlParams) { + baseUrlParams.geminiUrl; + baseUrlParams.vertexUrl; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class BaseModule { +} +function formatMap(templateString, valueMap) { + // Use a regular expression to find all placeholders in the template string + const regex = /\{([^}]+)\}/g; + // Replace each placeholder with its corresponding value from the valueMap + return templateString.replace(regex, (match, key) => { + if (Object.prototype.hasOwnProperty.call(valueMap, key)) { + const value = valueMap[key]; + // Convert the value to a string if it's not a string already + return value !== undefined && value !== null ? String(value) : ''; + } + else { + // Handle missing keys + throw new Error(`Key '${key}' not found in valueMap.`); + } + }); +} +function setValueByPath(data, keys, value) { + for (let i = 0; i < keys.length - 1; i++) { + const key = keys[i]; + if (key.endsWith('[]')) { + const keyName = key.slice(0, -2); + if (!(keyName in data)) { + if (Array.isArray(value)) { + data[keyName] = Array.from({ length: value.length }, () => ({})); + } + else { + throw new Error(`Value must be a list given an array path ${key}`); + } + } + if (Array.isArray(data[keyName])) { + const arrayData = data[keyName]; + if (Array.isArray(value)) { + for (let j = 0; j < arrayData.length; j++) { + const entry = arrayData[j]; + setValueByPath(entry, keys.slice(i + 1), value[j]); + } + } + else { + for (const d of arrayData) { + setValueByPath(d, keys.slice(i + 1), value); + } + } + } + return; + } + else if (key.endsWith('[0]')) { + const keyName = key.slice(0, -3); + if (!(keyName in data)) { + data[keyName] = [{}]; + } + const arrayData = data[keyName]; + setValueByPath(arrayData[0], keys.slice(i + 1), value); + return; + } + if (!data[key] || typeof data[key] !== 'object') { + data[key] = {}; + } + data = data[key]; + } + const keyToSet = keys[keys.length - 1]; + const existingData = data[keyToSet]; + if (existingData !== undefined) { + if (!value || + (typeof value === 'object' && Object.keys(value).length === 0)) { + return; + } + if (value === existingData) { + return; + } + if (typeof existingData === 'object' && + typeof value === 'object' && + existingData !== null && + value !== null) { + Object.assign(existingData, value); + } + else { + throw new Error(`Cannot set value for an existing key. Key: ${keyToSet}`); + } + } + else { + if (keyToSet === '_self' && + typeof value === 'object' && + value !== null && + !Array.isArray(value)) { + const valueAsRecord = value; + Object.assign(data, valueAsRecord); + } + else { + data[keyToSet] = value; + } + } +} +function getValueByPath(data, keys, defaultValue = undefined) { + try { + if (keys.length === 1 && keys[0] === '_self') { + return data; + } + for (let i = 0; i < keys.length; i++) { + if (typeof data !== 'object' || data === null) { + return defaultValue; + } + const key = keys[i]; + if (key.endsWith('[]')) { + const keyName = key.slice(0, -2); + if (keyName in data) { + const arrayData = data[keyName]; + if (!Array.isArray(arrayData)) { + return defaultValue; + } + return arrayData.map((d) => getValueByPath(d, keys.slice(i + 1), defaultValue)); + } + else { + return defaultValue; + } + } + else { + data = data[key]; + } + } + return data; + } + catch (error) { + if (error instanceof TypeError) { + return defaultValue; + } + throw error; + } +} +/** + * Moves values from source paths to destination paths. + * + * Examples: + * moveValueByPath( + * {'requests': [{'content': v1}, {'content': v2}]}, + * {'requests[].*': 'requests[].request.*'} + * ) + * -> {'requests': [{'request': {'content': v1}}, {'request': {'content': v2}}]} + */ +function moveValueByPath(data, paths) { + for (const [sourcePath, destPath] of Object.entries(paths)) { + const sourceKeys = sourcePath.split('.'); + const destKeys = destPath.split('.'); + // Determine keys to exclude from wildcard to avoid cyclic references + const excludeKeys = new Set(); + let wildcardIdx = -1; + for (let i = 0; i < sourceKeys.length; i++) { + if (sourceKeys[i] === '*') { + wildcardIdx = i; + break; + } + } + if (wildcardIdx !== -1 && destKeys.length > wildcardIdx) { + // Extract the intermediate key between source and dest paths + // Example: source=['requests[]', '*'], dest=['requests[]', 'request', '*'] + // We want to exclude 'request' + for (let i = wildcardIdx; i < destKeys.length; i++) { + const key = destKeys[i]; + if (key !== '*' && !key.endsWith('[]') && !key.endsWith('[0]')) { + excludeKeys.add(key); + } + } + } + _moveValueRecursive(data, sourceKeys, destKeys, 0, excludeKeys); + } +} +/** + * Recursively moves values from source path to destination path. + */ +function _moveValueRecursive(data, sourceKeys, destKeys, keyIdx, excludeKeys) { + if (keyIdx >= sourceKeys.length) { + return; + } + if (typeof data !== 'object' || data === null) { + return; + } + const key = sourceKeys[keyIdx]; + if (key.endsWith('[]')) { + const keyName = key.slice(0, -2); + const dataRecord = data; + if (keyName in dataRecord && Array.isArray(dataRecord[keyName])) { + for (const item of dataRecord[keyName]) { + _moveValueRecursive(item, sourceKeys, destKeys, keyIdx + 1, excludeKeys); + } + } + } + else if (key === '*') { + // wildcard - move all fields + if (typeof data === 'object' && data !== null && !Array.isArray(data)) { + const dataRecord = data; + const keysToMove = Object.keys(dataRecord).filter((k) => !k.startsWith('_') && !excludeKeys.has(k)); + const valuesToMove = {}; + for (const k of keysToMove) { + valuesToMove[k] = dataRecord[k]; + } + // Set values at destination + for (const [k, v] of Object.entries(valuesToMove)) { + const newDestKeys = []; + for (const dk of destKeys.slice(keyIdx)) { + if (dk === '*') { + newDestKeys.push(k); + } + else { + newDestKeys.push(dk); + } + } + setValueByPath(dataRecord, newDestKeys, v); + } + for (const k of keysToMove) { + delete dataRecord[k]; + } + } + } + else { + // Navigate to next level + const dataRecord = data; + if (key in dataRecord) { + _moveValueRecursive(dataRecord[key], sourceKeys, destKeys, keyIdx + 1, excludeKeys); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function tBytes$1(fromBytes) { + if (typeof fromBytes !== 'string') { + throw new Error('fromImageBytes must be a string'); + } + // TODO(b/389133914): Remove dummy bytes converter. + return fromBytes; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Code generated by the Google Gen AI SDK generator DO NOT EDIT. +function fetchPredictOperationParametersToVertex(fromObject) { + const toObject = {}; + const fromOperationName = getValueByPath(fromObject, [ + 'operationName', + ]); + if (fromOperationName != null) { + setValueByPath(toObject, ['operationName'], fromOperationName); + } + const fromResourceName = getValueByPath(fromObject, ['resourceName']); + if (fromResourceName != null) { + setValueByPath(toObject, ['_url', 'resourceName'], fromResourceName); + } + return toObject; +} +function generateVideosOperationFromMldev$1(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromResponse = getValueByPath(fromObject, [ + 'response', + 'generateVideoResponse', + ]); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], generateVideosResponseFromMldev$1(fromResponse)); + } + return toObject; +} +function generateVideosOperationFromVertex$1(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], generateVideosResponseFromVertex$1(fromResponse)); + } + return toObject; +} +function generateVideosResponseFromMldev$1(fromObject) { + const toObject = {}; + const fromGeneratedVideos = getValueByPath(fromObject, [ + 'generatedSamples', + ]); + if (fromGeneratedVideos != null) { + let transformedList = fromGeneratedVideos; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedVideoFromMldev$1(item); + }); + } + setValueByPath(toObject, ['generatedVideos'], transformedList); + } + const fromRaiMediaFilteredCount = getValueByPath(fromObject, [ + 'raiMediaFilteredCount', + ]); + if (fromRaiMediaFilteredCount != null) { + setValueByPath(toObject, ['raiMediaFilteredCount'], fromRaiMediaFilteredCount); + } + const fromRaiMediaFilteredReasons = getValueByPath(fromObject, [ + 'raiMediaFilteredReasons', + ]); + if (fromRaiMediaFilteredReasons != null) { + setValueByPath(toObject, ['raiMediaFilteredReasons'], fromRaiMediaFilteredReasons); + } + return toObject; +} +function generateVideosResponseFromVertex$1(fromObject) { + const toObject = {}; + const fromGeneratedVideos = getValueByPath(fromObject, ['videos']); + if (fromGeneratedVideos != null) { + let transformedList = fromGeneratedVideos; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedVideoFromVertex$1(item); + }); + } + setValueByPath(toObject, ['generatedVideos'], transformedList); + } + const fromRaiMediaFilteredCount = getValueByPath(fromObject, [ + 'raiMediaFilteredCount', + ]); + if (fromRaiMediaFilteredCount != null) { + setValueByPath(toObject, ['raiMediaFilteredCount'], fromRaiMediaFilteredCount); + } + const fromRaiMediaFilteredReasons = getValueByPath(fromObject, [ + 'raiMediaFilteredReasons', + ]); + if (fromRaiMediaFilteredReasons != null) { + setValueByPath(toObject, ['raiMediaFilteredReasons'], fromRaiMediaFilteredReasons); + } + return toObject; +} +function generatedVideoFromMldev$1(fromObject) { + const toObject = {}; + const fromVideo = getValueByPath(fromObject, ['video']); + if (fromVideo != null) { + setValueByPath(toObject, ['video'], videoFromMldev$1(fromVideo)); + } + return toObject; +} +function generatedVideoFromVertex$1(fromObject) { + const toObject = {}; + const fromVideo = getValueByPath(fromObject, ['_self']); + if (fromVideo != null) { + setValueByPath(toObject, ['video'], videoFromVertex$1(fromVideo)); + } + return toObject; +} +function getOperationParametersToMldev(fromObject) { + const toObject = {}; + const fromOperationName = getValueByPath(fromObject, [ + 'operationName', + ]); + if (fromOperationName != null) { + setValueByPath(toObject, ['_url', 'operationName'], fromOperationName); + } + return toObject; +} +function getOperationParametersToVertex(fromObject) { + const toObject = {}; + const fromOperationName = getValueByPath(fromObject, [ + 'operationName', + ]); + if (fromOperationName != null) { + setValueByPath(toObject, ['_url', 'operationName'], fromOperationName); + } + return toObject; +} +function importFileOperationFromMldev$1(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], importFileResponseFromMldev$1(fromResponse)); + } + return toObject; +} +function importFileResponseFromMldev$1(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromParent = getValueByPath(fromObject, ['parent']); + if (fromParent != null) { + setValueByPath(toObject, ['parent'], fromParent); + } + const fromDocumentName = getValueByPath(fromObject, ['documentName']); + if (fromDocumentName != null) { + setValueByPath(toObject, ['documentName'], fromDocumentName); + } + return toObject; +} +function uploadToFileSearchStoreOperationFromMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], uploadToFileSearchStoreResponseFromMldev(fromResponse)); + } + return toObject; +} +function uploadToFileSearchStoreResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromParent = getValueByPath(fromObject, ['parent']); + if (fromParent != null) { + setValueByPath(toObject, ['parent'], fromParent); + } + const fromDocumentName = getValueByPath(fromObject, ['documentName']); + if (fromDocumentName != null) { + setValueByPath(toObject, ['documentName'], fromDocumentName); + } + return toObject; +} +function videoFromMldev$1(fromObject) { + const toObject = {}; + const fromUri = getValueByPath(fromObject, ['uri']); + if (fromUri != null) { + setValueByPath(toObject, ['uri'], fromUri); + } + const fromVideoBytes = getValueByPath(fromObject, ['encodedVideo']); + if (fromVideoBytes != null) { + setValueByPath(toObject, ['videoBytes'], tBytes$1(fromVideoBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['encoding']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function videoFromVertex$1(fromObject) { + const toObject = {}; + const fromUri = getValueByPath(fromObject, ['gcsUri']); + if (fromUri != null) { + setValueByPath(toObject, ['uri'], fromUri); + } + const fromVideoBytes = getValueByPath(fromObject, [ + 'bytesBase64Encoded', + ]); + if (fromVideoBytes != null) { + setValueByPath(toObject, ['videoBytes'], tBytes$1(fromVideoBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** Outcome of the code execution. */ +var Outcome; +(function (Outcome) { + /** + * Unspecified status. This value should not be used. + */ + Outcome["OUTCOME_UNSPECIFIED"] = "OUTCOME_UNSPECIFIED"; + /** + * Code execution completed successfully. + */ + Outcome["OUTCOME_OK"] = "OUTCOME_OK"; + /** + * Code execution finished but with a failure. `stderr` should contain the reason. + */ + Outcome["OUTCOME_FAILED"] = "OUTCOME_FAILED"; + /** + * Code execution ran for too long, and was cancelled. There may or may not be a partial output present. + */ + Outcome["OUTCOME_DEADLINE_EXCEEDED"] = "OUTCOME_DEADLINE_EXCEEDED"; +})(Outcome || (Outcome = {})); +/** Programming language of the `code`. */ +var Language; +(function (Language) { + /** + * Unspecified language. This value should not be used. + */ + Language["LANGUAGE_UNSPECIFIED"] = "LANGUAGE_UNSPECIFIED"; + /** + * Python >= 3.10, with numpy and simpy available. + */ + Language["PYTHON"] = "PYTHON"; +})(Language || (Language = {})); +/** Specifies how the response should be scheduled in the conversation. */ +var FunctionResponseScheduling; +(function (FunctionResponseScheduling) { + /** + * This value is unused. + */ + FunctionResponseScheduling["SCHEDULING_UNSPECIFIED"] = "SCHEDULING_UNSPECIFIED"; + /** + * Only add the result to the conversation context, do not interrupt or trigger generation. + */ + FunctionResponseScheduling["SILENT"] = "SILENT"; + /** + * Add the result to the conversation context, and prompt to generate output without interrupting ongoing generation. + */ + FunctionResponseScheduling["WHEN_IDLE"] = "WHEN_IDLE"; + /** + * Add the result to the conversation context, interrupt ongoing generation and prompt to generate output. + */ + FunctionResponseScheduling["INTERRUPT"] = "INTERRUPT"; +})(FunctionResponseScheduling || (FunctionResponseScheduling = {})); +/** The type of the data. */ +var Type; +(function (Type) { + /** + * Not specified, should not be used. + */ + Type["TYPE_UNSPECIFIED"] = "TYPE_UNSPECIFIED"; + /** + * OpenAPI string type + */ + Type["STRING"] = "STRING"; + /** + * OpenAPI number type + */ + Type["NUMBER"] = "NUMBER"; + /** + * OpenAPI integer type + */ + Type["INTEGER"] = "INTEGER"; + /** + * OpenAPI boolean type + */ + Type["BOOLEAN"] = "BOOLEAN"; + /** + * OpenAPI array type + */ + Type["ARRAY"] = "ARRAY"; + /** + * OpenAPI object type + */ + Type["OBJECT"] = "OBJECT"; + /** + * Null type + */ + Type["NULL"] = "NULL"; +})(Type || (Type = {})); +/** The API spec that the external API implements. This enum is not supported in Gemini API. */ +var ApiSpec; +(function (ApiSpec) { + /** + * Unspecified API spec. This value should not be used. + */ + ApiSpec["API_SPEC_UNSPECIFIED"] = "API_SPEC_UNSPECIFIED"; + /** + * Simple search API spec. + */ + ApiSpec["SIMPLE_SEARCH"] = "SIMPLE_SEARCH"; + /** + * Elastic search API spec. + */ + ApiSpec["ELASTIC_SEARCH"] = "ELASTIC_SEARCH"; +})(ApiSpec || (ApiSpec = {})); +/** Type of auth scheme. This enum is not supported in Gemini API. */ +var AuthType; +(function (AuthType) { + AuthType["AUTH_TYPE_UNSPECIFIED"] = "AUTH_TYPE_UNSPECIFIED"; + /** + * No Auth. + */ + AuthType["NO_AUTH"] = "NO_AUTH"; + /** + * API Key Auth. + */ + AuthType["API_KEY_AUTH"] = "API_KEY_AUTH"; + /** + * HTTP Basic Auth. + */ + AuthType["HTTP_BASIC_AUTH"] = "HTTP_BASIC_AUTH"; + /** + * Google Service Account Auth. + */ + AuthType["GOOGLE_SERVICE_ACCOUNT_AUTH"] = "GOOGLE_SERVICE_ACCOUNT_AUTH"; + /** + * OAuth auth. + */ + AuthType["OAUTH"] = "OAUTH"; + /** + * OpenID Connect (OIDC) Auth. + */ + AuthType["OIDC_AUTH"] = "OIDC_AUTH"; +})(AuthType || (AuthType = {})); +/** The location of the API key. This enum is not supported in Gemini API. */ +var HttpElementLocation; +(function (HttpElementLocation) { + HttpElementLocation["HTTP_IN_UNSPECIFIED"] = "HTTP_IN_UNSPECIFIED"; + /** + * Element is in the HTTP request query. + */ + HttpElementLocation["HTTP_IN_QUERY"] = "HTTP_IN_QUERY"; + /** + * Element is in the HTTP request header. + */ + HttpElementLocation["HTTP_IN_HEADER"] = "HTTP_IN_HEADER"; + /** + * Element is in the HTTP request path. + */ + HttpElementLocation["HTTP_IN_PATH"] = "HTTP_IN_PATH"; + /** + * Element is in the HTTP request body. + */ + HttpElementLocation["HTTP_IN_BODY"] = "HTTP_IN_BODY"; + /** + * Element is in the HTTP request cookie. + */ + HttpElementLocation["HTTP_IN_COOKIE"] = "HTTP_IN_COOKIE"; +})(HttpElementLocation || (HttpElementLocation = {})); +/** Sites with confidence level chosen & above this value will be blocked from the search results. This enum is not supported in Gemini API. */ +var PhishBlockThreshold; +(function (PhishBlockThreshold) { + /** + * Defaults to unspecified. + */ + PhishBlockThreshold["PHISH_BLOCK_THRESHOLD_UNSPECIFIED"] = "PHISH_BLOCK_THRESHOLD_UNSPECIFIED"; + /** + * Blocks Low and above confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_LOW_AND_ABOVE"] = "BLOCK_LOW_AND_ABOVE"; + /** + * Blocks Medium and above confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_MEDIUM_AND_ABOVE"] = "BLOCK_MEDIUM_AND_ABOVE"; + /** + * Blocks High and above confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_HIGH_AND_ABOVE"] = "BLOCK_HIGH_AND_ABOVE"; + /** + * Blocks Higher and above confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_HIGHER_AND_ABOVE"] = "BLOCK_HIGHER_AND_ABOVE"; + /** + * Blocks Very high and above confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_VERY_HIGH_AND_ABOVE"] = "BLOCK_VERY_HIGH_AND_ABOVE"; + /** + * Blocks Extremely high confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_ONLY_EXTREMELY_HIGH"] = "BLOCK_ONLY_EXTREMELY_HIGH"; +})(PhishBlockThreshold || (PhishBlockThreshold = {})); +/** Specifies the function Behavior. Currently only supported by the BidiGenerateContent method. This enum is not supported in Vertex AI. */ +var Behavior; +(function (Behavior) { + /** + * This value is unused. + */ + Behavior["UNSPECIFIED"] = "UNSPECIFIED"; + /** + * If set, the system will wait to receive the function response before continuing the conversation. + */ + Behavior["BLOCKING"] = "BLOCKING"; + /** + * If set, the system will not wait to receive the function response. Instead, it will attempt to handle function responses as they become available while maintaining the conversation between the user and the model. + */ + Behavior["NON_BLOCKING"] = "NON_BLOCKING"; +})(Behavior || (Behavior = {})); +/** The mode of the predictor to be used in dynamic retrieval. */ +var DynamicRetrievalConfigMode; +(function (DynamicRetrievalConfigMode) { + /** + * Always trigger retrieval. + */ + DynamicRetrievalConfigMode["MODE_UNSPECIFIED"] = "MODE_UNSPECIFIED"; + /** + * Run retrieval only when system decides it is necessary. + */ + DynamicRetrievalConfigMode["MODE_DYNAMIC"] = "MODE_DYNAMIC"; +})(DynamicRetrievalConfigMode || (DynamicRetrievalConfigMode = {})); +/** Function calling mode. */ +var FunctionCallingConfigMode; +(function (FunctionCallingConfigMode) { + /** + * Unspecified function calling mode. This value should not be used. + */ + FunctionCallingConfigMode["MODE_UNSPECIFIED"] = "MODE_UNSPECIFIED"; + /** + * Default model behavior, model decides to predict either function calls or natural language response. + */ + FunctionCallingConfigMode["AUTO"] = "AUTO"; + /** + * Model is constrained to always predicting function calls only. If "allowed_function_names" are set, the predicted function calls will be limited to any one of "allowed_function_names", else the predicted function calls will be any one of the provided "function_declarations". + */ + FunctionCallingConfigMode["ANY"] = "ANY"; + /** + * Model will not predict any function calls. Model behavior is same as when not passing any function declarations. + */ + FunctionCallingConfigMode["NONE"] = "NONE"; + /** + * Model is constrained to predict either function calls or natural language response. If "allowed_function_names" are set, the predicted function calls will be limited to any one of "allowed_function_names", else the predicted function calls will be any one of the provided "function_declarations". + */ + FunctionCallingConfigMode["VALIDATED"] = "VALIDATED"; +})(FunctionCallingConfigMode || (FunctionCallingConfigMode = {})); +/** The number of thoughts tokens that the model should generate. */ +var ThinkingLevel; +(function (ThinkingLevel) { + /** + * Unspecified thinking level. + */ + ThinkingLevel["THINKING_LEVEL_UNSPECIFIED"] = "THINKING_LEVEL_UNSPECIFIED"; + /** + * Low thinking level. + */ + ThinkingLevel["LOW"] = "LOW"; + /** + * Medium thinking level. + */ + ThinkingLevel["MEDIUM"] = "MEDIUM"; + /** + * High thinking level. + */ + ThinkingLevel["HIGH"] = "HIGH"; + /** + * MINIMAL thinking level. + */ + ThinkingLevel["MINIMAL"] = "MINIMAL"; +})(ThinkingLevel || (ThinkingLevel = {})); +/** Harm category. */ +var HarmCategory; +(function (HarmCategory) { + /** + * The harm category is unspecified. + */ + HarmCategory["HARM_CATEGORY_UNSPECIFIED"] = "HARM_CATEGORY_UNSPECIFIED"; + /** + * The harm category is harassment. + */ + HarmCategory["HARM_CATEGORY_HARASSMENT"] = "HARM_CATEGORY_HARASSMENT"; + /** + * The harm category is hate speech. + */ + HarmCategory["HARM_CATEGORY_HATE_SPEECH"] = "HARM_CATEGORY_HATE_SPEECH"; + /** + * The harm category is sexually explicit content. + */ + HarmCategory["HARM_CATEGORY_SEXUALLY_EXPLICIT"] = "HARM_CATEGORY_SEXUALLY_EXPLICIT"; + /** + * The harm category is dangerous content. + */ + HarmCategory["HARM_CATEGORY_DANGEROUS_CONTENT"] = "HARM_CATEGORY_DANGEROUS_CONTENT"; + /** + * Deprecated: Election filter is not longer supported. The harm category is civic integrity. + */ + HarmCategory["HARM_CATEGORY_CIVIC_INTEGRITY"] = "HARM_CATEGORY_CIVIC_INTEGRITY"; + /** + * The harm category is image hate. This enum value is not supported in Gemini API. + */ + HarmCategory["HARM_CATEGORY_IMAGE_HATE"] = "HARM_CATEGORY_IMAGE_HATE"; + /** + * The harm category is image dangerous content. This enum value is not supported in Gemini API. + */ + HarmCategory["HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT"] = "HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT"; + /** + * The harm category is image harassment. This enum value is not supported in Gemini API. + */ + HarmCategory["HARM_CATEGORY_IMAGE_HARASSMENT"] = "HARM_CATEGORY_IMAGE_HARASSMENT"; + /** + * The harm category is image sexually explicit content. This enum value is not supported in Gemini API. + */ + HarmCategory["HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT"] = "HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT"; + /** + * The harm category is for jailbreak prompts. This enum value is not supported in Gemini API. + */ + HarmCategory["HARM_CATEGORY_JAILBREAK"] = "HARM_CATEGORY_JAILBREAK"; +})(HarmCategory || (HarmCategory = {})); +/** Specify if the threshold is used for probability or severity score. If not specified, the threshold is used for probability score. This enum is not supported in Gemini API. */ +var HarmBlockMethod; +(function (HarmBlockMethod) { + /** + * The harm block method is unspecified. + */ + HarmBlockMethod["HARM_BLOCK_METHOD_UNSPECIFIED"] = "HARM_BLOCK_METHOD_UNSPECIFIED"; + /** + * The harm block method uses both probability and severity scores. + */ + HarmBlockMethod["SEVERITY"] = "SEVERITY"; + /** + * The harm block method uses the probability score. + */ + HarmBlockMethod["PROBABILITY"] = "PROBABILITY"; +})(HarmBlockMethod || (HarmBlockMethod = {})); +/** The harm block threshold. */ +var HarmBlockThreshold; +(function (HarmBlockThreshold) { + /** + * Unspecified harm block threshold. + */ + HarmBlockThreshold["HARM_BLOCK_THRESHOLD_UNSPECIFIED"] = "HARM_BLOCK_THRESHOLD_UNSPECIFIED"; + /** + * Block low threshold and above (i.e. block more). + */ + HarmBlockThreshold["BLOCK_LOW_AND_ABOVE"] = "BLOCK_LOW_AND_ABOVE"; + /** + * Block medium threshold and above. + */ + HarmBlockThreshold["BLOCK_MEDIUM_AND_ABOVE"] = "BLOCK_MEDIUM_AND_ABOVE"; + /** + * Block only high threshold (i.e. block less). + */ + HarmBlockThreshold["BLOCK_ONLY_HIGH"] = "BLOCK_ONLY_HIGH"; + /** + * Block none. + */ + HarmBlockThreshold["BLOCK_NONE"] = "BLOCK_NONE"; + /** + * Turn off the safety filter. + */ + HarmBlockThreshold["OFF"] = "OFF"; +})(HarmBlockThreshold || (HarmBlockThreshold = {})); +/** Output only. The reason why the model stopped generating tokens. + +If empty, the model has not stopped generating the tokens. */ +var FinishReason; +(function (FinishReason) { + /** + * The finish reason is unspecified. + */ + FinishReason["FINISH_REASON_UNSPECIFIED"] = "FINISH_REASON_UNSPECIFIED"; + /** + * Token generation reached a natural stopping point or a configured stop sequence. + */ + FinishReason["STOP"] = "STOP"; + /** + * Token generation reached the configured maximum output tokens. + */ + FinishReason["MAX_TOKENS"] = "MAX_TOKENS"; + /** + * Token generation stopped because the content potentially contains safety violations. NOTE: When streaming, [content][] is empty if content filters blocks the output. + */ + FinishReason["SAFETY"] = "SAFETY"; + /** + * The token generation stopped because of potential recitation. + */ + FinishReason["RECITATION"] = "RECITATION"; + /** + * The token generation stopped because of using an unsupported language. + */ + FinishReason["LANGUAGE"] = "LANGUAGE"; + /** + * All other reasons that stopped the token generation. + */ + FinishReason["OTHER"] = "OTHER"; + /** + * Token generation stopped because the content contains forbidden terms. + */ + FinishReason["BLOCKLIST"] = "BLOCKLIST"; + /** + * Token generation stopped for potentially containing prohibited content. + */ + FinishReason["PROHIBITED_CONTENT"] = "PROHIBITED_CONTENT"; + /** + * Token generation stopped because the content potentially contains Sensitive Personally Identifiable Information (SPII). + */ + FinishReason["SPII"] = "SPII"; + /** + * The function call generated by the model is invalid. + */ + FinishReason["MALFORMED_FUNCTION_CALL"] = "MALFORMED_FUNCTION_CALL"; + /** + * Token generation stopped because generated images have safety violations. + */ + FinishReason["IMAGE_SAFETY"] = "IMAGE_SAFETY"; + /** + * The tool call generated by the model is invalid. + */ + FinishReason["UNEXPECTED_TOOL_CALL"] = "UNEXPECTED_TOOL_CALL"; + /** + * Image generation stopped because the generated images have prohibited content. + */ + FinishReason["IMAGE_PROHIBITED_CONTENT"] = "IMAGE_PROHIBITED_CONTENT"; + /** + * The model was expected to generate an image, but none was generated. + */ + FinishReason["NO_IMAGE"] = "NO_IMAGE"; + /** + * Image generation stopped because the generated image may be a recitation from a source. + */ + FinishReason["IMAGE_RECITATION"] = "IMAGE_RECITATION"; + /** + * Image generation stopped for a reason not otherwise specified. + */ + FinishReason["IMAGE_OTHER"] = "IMAGE_OTHER"; +})(FinishReason || (FinishReason = {})); +/** Output only. Harm probability levels in the content. */ +var HarmProbability; +(function (HarmProbability) { + /** + * Harm probability unspecified. + */ + HarmProbability["HARM_PROBABILITY_UNSPECIFIED"] = "HARM_PROBABILITY_UNSPECIFIED"; + /** + * Negligible level of harm. + */ + HarmProbability["NEGLIGIBLE"] = "NEGLIGIBLE"; + /** + * Low level of harm. + */ + HarmProbability["LOW"] = "LOW"; + /** + * Medium level of harm. + */ + HarmProbability["MEDIUM"] = "MEDIUM"; + /** + * High level of harm. + */ + HarmProbability["HIGH"] = "HIGH"; +})(HarmProbability || (HarmProbability = {})); +/** Output only. Harm severity levels in the content. This enum is not supported in Gemini API. */ +var HarmSeverity; +(function (HarmSeverity) { + /** + * Harm severity unspecified. + */ + HarmSeverity["HARM_SEVERITY_UNSPECIFIED"] = "HARM_SEVERITY_UNSPECIFIED"; + /** + * Negligible level of harm severity. + */ + HarmSeverity["HARM_SEVERITY_NEGLIGIBLE"] = "HARM_SEVERITY_NEGLIGIBLE"; + /** + * Low level of harm severity. + */ + HarmSeverity["HARM_SEVERITY_LOW"] = "HARM_SEVERITY_LOW"; + /** + * Medium level of harm severity. + */ + HarmSeverity["HARM_SEVERITY_MEDIUM"] = "HARM_SEVERITY_MEDIUM"; + /** + * High level of harm severity. + */ + HarmSeverity["HARM_SEVERITY_HIGH"] = "HARM_SEVERITY_HIGH"; +})(HarmSeverity || (HarmSeverity = {})); +/** Status of the url retrieval. */ +var UrlRetrievalStatus; +(function (UrlRetrievalStatus) { + /** + * Default value. This value is unused. + */ + UrlRetrievalStatus["URL_RETRIEVAL_STATUS_UNSPECIFIED"] = "URL_RETRIEVAL_STATUS_UNSPECIFIED"; + /** + * Url retrieval is successful. + */ + UrlRetrievalStatus["URL_RETRIEVAL_STATUS_SUCCESS"] = "URL_RETRIEVAL_STATUS_SUCCESS"; + /** + * Url retrieval is failed due to error. + */ + UrlRetrievalStatus["URL_RETRIEVAL_STATUS_ERROR"] = "URL_RETRIEVAL_STATUS_ERROR"; + /** + * Url retrieval is failed because the content is behind paywall. This enum value is not supported in Vertex AI. + */ + UrlRetrievalStatus["URL_RETRIEVAL_STATUS_PAYWALL"] = "URL_RETRIEVAL_STATUS_PAYWALL"; + /** + * Url retrieval is failed because the content is unsafe. This enum value is not supported in Vertex AI. + */ + UrlRetrievalStatus["URL_RETRIEVAL_STATUS_UNSAFE"] = "URL_RETRIEVAL_STATUS_UNSAFE"; +})(UrlRetrievalStatus || (UrlRetrievalStatus = {})); +/** Output only. The reason why the prompt was blocked. */ +var BlockedReason; +(function (BlockedReason) { + /** + * The blocked reason is unspecified. + */ + BlockedReason["BLOCKED_REASON_UNSPECIFIED"] = "BLOCKED_REASON_UNSPECIFIED"; + /** + * The prompt was blocked for safety reasons. + */ + BlockedReason["SAFETY"] = "SAFETY"; + /** + * The prompt was blocked for other reasons. For example, it may be due to the prompt's language, or because it contains other harmful content. + */ + BlockedReason["OTHER"] = "OTHER"; + /** + * The prompt was blocked because it contains a term from the terminology blocklist. + */ + BlockedReason["BLOCKLIST"] = "BLOCKLIST"; + /** + * The prompt was blocked because it contains prohibited content. + */ + BlockedReason["PROHIBITED_CONTENT"] = "PROHIBITED_CONTENT"; + /** + * The prompt was blocked because it contains content that is unsafe for image generation. + */ + BlockedReason["IMAGE_SAFETY"] = "IMAGE_SAFETY"; + /** + * The prompt was blocked by Model Armor. This enum value is not supported in Gemini API. + */ + BlockedReason["MODEL_ARMOR"] = "MODEL_ARMOR"; + /** + * The prompt was blocked as a jailbreak attempt. This enum value is not supported in Gemini API. + */ + BlockedReason["JAILBREAK"] = "JAILBREAK"; +})(BlockedReason || (BlockedReason = {})); +/** Output only. The traffic type for this request. This enum is not supported in Gemini API. */ +var TrafficType; +(function (TrafficType) { + /** + * Unspecified request traffic type. + */ + TrafficType["TRAFFIC_TYPE_UNSPECIFIED"] = "TRAFFIC_TYPE_UNSPECIFIED"; + /** + * The request was processed using Pay-As-You-Go quota. + */ + TrafficType["ON_DEMAND"] = "ON_DEMAND"; + /** + * Type for Provisioned Throughput traffic. + */ + TrafficType["PROVISIONED_THROUGHPUT"] = "PROVISIONED_THROUGHPUT"; +})(TrafficType || (TrafficType = {})); +/** Server content modalities. */ +var Modality; +(function (Modality) { + /** + * The modality is unspecified. + */ + Modality["MODALITY_UNSPECIFIED"] = "MODALITY_UNSPECIFIED"; + /** + * Indicates the model should return text + */ + Modality["TEXT"] = "TEXT"; + /** + * Indicates the model should return images. + */ + Modality["IMAGE"] = "IMAGE"; + /** + * Indicates the model should return audio. + */ + Modality["AUDIO"] = "AUDIO"; +})(Modality || (Modality = {})); +/** The media resolution to use. */ +var MediaResolution; +(function (MediaResolution) { + /** + * Media resolution has not been set + */ + MediaResolution["MEDIA_RESOLUTION_UNSPECIFIED"] = "MEDIA_RESOLUTION_UNSPECIFIED"; + /** + * Media resolution set to low (64 tokens). + */ + MediaResolution["MEDIA_RESOLUTION_LOW"] = "MEDIA_RESOLUTION_LOW"; + /** + * Media resolution set to medium (256 tokens). + */ + MediaResolution["MEDIA_RESOLUTION_MEDIUM"] = "MEDIA_RESOLUTION_MEDIUM"; + /** + * Media resolution set to high (zoomed reframing with 256 tokens). + */ + MediaResolution["MEDIA_RESOLUTION_HIGH"] = "MEDIA_RESOLUTION_HIGH"; +})(MediaResolution || (MediaResolution = {})); +/** Tuning mode. This enum is not supported in Gemini API. */ +var TuningMode; +(function (TuningMode) { + /** + * Tuning mode is unspecified. + */ + TuningMode["TUNING_MODE_UNSPECIFIED"] = "TUNING_MODE_UNSPECIFIED"; + /** + * Full fine-tuning mode. + */ + TuningMode["TUNING_MODE_FULL"] = "TUNING_MODE_FULL"; + /** + * PEFT adapter tuning mode. + */ + TuningMode["TUNING_MODE_PEFT_ADAPTER"] = "TUNING_MODE_PEFT_ADAPTER"; +})(TuningMode || (TuningMode = {})); +/** Adapter size for tuning. This enum is not supported in Gemini API. */ +var AdapterSize; +(function (AdapterSize) { + /** + * Adapter size is unspecified. + */ + AdapterSize["ADAPTER_SIZE_UNSPECIFIED"] = "ADAPTER_SIZE_UNSPECIFIED"; + /** + * Adapter size 1. + */ + AdapterSize["ADAPTER_SIZE_ONE"] = "ADAPTER_SIZE_ONE"; + /** + * Adapter size 2. + */ + AdapterSize["ADAPTER_SIZE_TWO"] = "ADAPTER_SIZE_TWO"; + /** + * Adapter size 4. + */ + AdapterSize["ADAPTER_SIZE_FOUR"] = "ADAPTER_SIZE_FOUR"; + /** + * Adapter size 8. + */ + AdapterSize["ADAPTER_SIZE_EIGHT"] = "ADAPTER_SIZE_EIGHT"; + /** + * Adapter size 16. + */ + AdapterSize["ADAPTER_SIZE_SIXTEEN"] = "ADAPTER_SIZE_SIXTEEN"; + /** + * Adapter size 32. + */ + AdapterSize["ADAPTER_SIZE_THIRTY_TWO"] = "ADAPTER_SIZE_THIRTY_TWO"; +})(AdapterSize || (AdapterSize = {})); +/** Job state. */ +var JobState; +(function (JobState) { + /** + * The job state is unspecified. + */ + JobState["JOB_STATE_UNSPECIFIED"] = "JOB_STATE_UNSPECIFIED"; + /** + * The job has been just created or resumed and processing has not yet begun. + */ + JobState["JOB_STATE_QUEUED"] = "JOB_STATE_QUEUED"; + /** + * The service is preparing to run the job. + */ + JobState["JOB_STATE_PENDING"] = "JOB_STATE_PENDING"; + /** + * The job is in progress. + */ + JobState["JOB_STATE_RUNNING"] = "JOB_STATE_RUNNING"; + /** + * The job completed successfully. + */ + JobState["JOB_STATE_SUCCEEDED"] = "JOB_STATE_SUCCEEDED"; + /** + * The job failed. + */ + JobState["JOB_STATE_FAILED"] = "JOB_STATE_FAILED"; + /** + * The job is being cancelled. From this state the job may only go to either `JOB_STATE_SUCCEEDED`, `JOB_STATE_FAILED` or `JOB_STATE_CANCELLED`. + */ + JobState["JOB_STATE_CANCELLING"] = "JOB_STATE_CANCELLING"; + /** + * The job has been cancelled. + */ + JobState["JOB_STATE_CANCELLED"] = "JOB_STATE_CANCELLED"; + /** + * The job has been stopped, and can be resumed. + */ + JobState["JOB_STATE_PAUSED"] = "JOB_STATE_PAUSED"; + /** + * The job has expired. + */ + JobState["JOB_STATE_EXPIRED"] = "JOB_STATE_EXPIRED"; + /** + * The job is being updated. Only jobs in the `JOB_STATE_RUNNING` state can be updated. After updating, the job goes back to the `JOB_STATE_RUNNING` state. + */ + JobState["JOB_STATE_UPDATING"] = "JOB_STATE_UPDATING"; + /** + * The job is partially succeeded, some results may be missing due to errors. + */ + JobState["JOB_STATE_PARTIALLY_SUCCEEDED"] = "JOB_STATE_PARTIALLY_SUCCEEDED"; +})(JobState || (JobState = {})); +/** The tuning task. Either I2V or T2V. This enum is not supported in Gemini API. */ +var TuningTask; +(function (TuningTask) { + /** + * Default value. This value is unused. + */ + TuningTask["TUNING_TASK_UNSPECIFIED"] = "TUNING_TASK_UNSPECIFIED"; + /** + * Tuning task for image to video. + */ + TuningTask["TUNING_TASK_I2V"] = "TUNING_TASK_I2V"; + /** + * Tuning task for text to video. + */ + TuningTask["TUNING_TASK_T2V"] = "TUNING_TASK_T2V"; + /** + * Tuning task for reference to video. + */ + TuningTask["TUNING_TASK_R2V"] = "TUNING_TASK_R2V"; +})(TuningTask || (TuningTask = {})); +/** The tokenization quality used for given media. */ +var PartMediaResolutionLevel; +(function (PartMediaResolutionLevel) { + /** + * Media resolution has not been set. + */ + PartMediaResolutionLevel["MEDIA_RESOLUTION_UNSPECIFIED"] = "MEDIA_RESOLUTION_UNSPECIFIED"; + /** + * Media resolution set to low. + */ + PartMediaResolutionLevel["MEDIA_RESOLUTION_LOW"] = "MEDIA_RESOLUTION_LOW"; + /** + * Media resolution set to medium. + */ + PartMediaResolutionLevel["MEDIA_RESOLUTION_MEDIUM"] = "MEDIA_RESOLUTION_MEDIUM"; + /** + * Media resolution set to high. + */ + PartMediaResolutionLevel["MEDIA_RESOLUTION_HIGH"] = "MEDIA_RESOLUTION_HIGH"; + /** + * Media resolution set to ultra high. + */ + PartMediaResolutionLevel["MEDIA_RESOLUTION_ULTRA_HIGH"] = "MEDIA_RESOLUTION_ULTRA_HIGH"; +})(PartMediaResolutionLevel || (PartMediaResolutionLevel = {})); +/** Resource scope. */ +var ResourceScope; +(function (ResourceScope) { + /** + * When setting base_url, this value configures resource scope to be the collection. + The resource name will not include api version, project, or location. + For example, if base_url is set to "https://aiplatform.googleapis.com", + then the resource name for a Model would be + "https://aiplatform.googleapis.com/publishers/google/models/gemini-3-pro-preview + */ + ResourceScope["COLLECTION"] = "COLLECTION"; +})(ResourceScope || (ResourceScope = {})); +/** Options for feature selection preference. */ +var FeatureSelectionPreference; +(function (FeatureSelectionPreference) { + FeatureSelectionPreference["FEATURE_SELECTION_PREFERENCE_UNSPECIFIED"] = "FEATURE_SELECTION_PREFERENCE_UNSPECIFIED"; + FeatureSelectionPreference["PRIORITIZE_QUALITY"] = "PRIORITIZE_QUALITY"; + FeatureSelectionPreference["BALANCED"] = "BALANCED"; + FeatureSelectionPreference["PRIORITIZE_COST"] = "PRIORITIZE_COST"; +})(FeatureSelectionPreference || (FeatureSelectionPreference = {})); +/** The environment being operated. */ +var Environment; +(function (Environment) { + /** + * Defaults to browser. + */ + Environment["ENVIRONMENT_UNSPECIFIED"] = "ENVIRONMENT_UNSPECIFIED"; + /** + * Operates in a web browser. + */ + Environment["ENVIRONMENT_BROWSER"] = "ENVIRONMENT_BROWSER"; +})(Environment || (Environment = {})); +/** Enum that controls the safety filter level for objectionable content. */ +var SafetyFilterLevel; +(function (SafetyFilterLevel) { + SafetyFilterLevel["BLOCK_LOW_AND_ABOVE"] = "BLOCK_LOW_AND_ABOVE"; + SafetyFilterLevel["BLOCK_MEDIUM_AND_ABOVE"] = "BLOCK_MEDIUM_AND_ABOVE"; + SafetyFilterLevel["BLOCK_ONLY_HIGH"] = "BLOCK_ONLY_HIGH"; + SafetyFilterLevel["BLOCK_NONE"] = "BLOCK_NONE"; +})(SafetyFilterLevel || (SafetyFilterLevel = {})); +/** Enum that controls the generation of people. */ +var PersonGeneration; +(function (PersonGeneration) { + /** + * Block generation of images of people. + */ + PersonGeneration["DONT_ALLOW"] = "DONT_ALLOW"; + /** + * Generate images of adults, but not children. + */ + PersonGeneration["ALLOW_ADULT"] = "ALLOW_ADULT"; + /** + * Generate images that include adults and children. + */ + PersonGeneration["ALLOW_ALL"] = "ALLOW_ALL"; +})(PersonGeneration || (PersonGeneration = {})); +/** Enum that specifies the language of the text in the prompt. */ +var ImagePromptLanguage; +(function (ImagePromptLanguage) { + /** + * Auto-detect the language. + */ + ImagePromptLanguage["auto"] = "auto"; + /** + * English + */ + ImagePromptLanguage["en"] = "en"; + /** + * Japanese + */ + ImagePromptLanguage["ja"] = "ja"; + /** + * Korean + */ + ImagePromptLanguage["ko"] = "ko"; + /** + * Hindi + */ + ImagePromptLanguage["hi"] = "hi"; + /** + * Chinese + */ + ImagePromptLanguage["zh"] = "zh"; + /** + * Portuguese + */ + ImagePromptLanguage["pt"] = "pt"; + /** + * Spanish + */ + ImagePromptLanguage["es"] = "es"; +})(ImagePromptLanguage || (ImagePromptLanguage = {})); +/** Enum representing the mask mode of a mask reference image. */ +var MaskReferenceMode; +(function (MaskReferenceMode) { + MaskReferenceMode["MASK_MODE_DEFAULT"] = "MASK_MODE_DEFAULT"; + MaskReferenceMode["MASK_MODE_USER_PROVIDED"] = "MASK_MODE_USER_PROVIDED"; + MaskReferenceMode["MASK_MODE_BACKGROUND"] = "MASK_MODE_BACKGROUND"; + MaskReferenceMode["MASK_MODE_FOREGROUND"] = "MASK_MODE_FOREGROUND"; + MaskReferenceMode["MASK_MODE_SEMANTIC"] = "MASK_MODE_SEMANTIC"; +})(MaskReferenceMode || (MaskReferenceMode = {})); +/** Enum representing the control type of a control reference image. */ +var ControlReferenceType; +(function (ControlReferenceType) { + ControlReferenceType["CONTROL_TYPE_DEFAULT"] = "CONTROL_TYPE_DEFAULT"; + ControlReferenceType["CONTROL_TYPE_CANNY"] = "CONTROL_TYPE_CANNY"; + ControlReferenceType["CONTROL_TYPE_SCRIBBLE"] = "CONTROL_TYPE_SCRIBBLE"; + ControlReferenceType["CONTROL_TYPE_FACE_MESH"] = "CONTROL_TYPE_FACE_MESH"; +})(ControlReferenceType || (ControlReferenceType = {})); +/** Enum representing the subject type of a subject reference image. */ +var SubjectReferenceType; +(function (SubjectReferenceType) { + SubjectReferenceType["SUBJECT_TYPE_DEFAULT"] = "SUBJECT_TYPE_DEFAULT"; + SubjectReferenceType["SUBJECT_TYPE_PERSON"] = "SUBJECT_TYPE_PERSON"; + SubjectReferenceType["SUBJECT_TYPE_ANIMAL"] = "SUBJECT_TYPE_ANIMAL"; + SubjectReferenceType["SUBJECT_TYPE_PRODUCT"] = "SUBJECT_TYPE_PRODUCT"; +})(SubjectReferenceType || (SubjectReferenceType = {})); +/** Enum representing the editing mode. */ +var EditMode; +(function (EditMode) { + EditMode["EDIT_MODE_DEFAULT"] = "EDIT_MODE_DEFAULT"; + EditMode["EDIT_MODE_INPAINT_REMOVAL"] = "EDIT_MODE_INPAINT_REMOVAL"; + EditMode["EDIT_MODE_INPAINT_INSERTION"] = "EDIT_MODE_INPAINT_INSERTION"; + EditMode["EDIT_MODE_OUTPAINT"] = "EDIT_MODE_OUTPAINT"; + EditMode["EDIT_MODE_CONTROLLED_EDITING"] = "EDIT_MODE_CONTROLLED_EDITING"; + EditMode["EDIT_MODE_STYLE"] = "EDIT_MODE_STYLE"; + EditMode["EDIT_MODE_BGSWAP"] = "EDIT_MODE_BGSWAP"; + EditMode["EDIT_MODE_PRODUCT_IMAGE"] = "EDIT_MODE_PRODUCT_IMAGE"; +})(EditMode || (EditMode = {})); +/** Enum that represents the segmentation mode. */ +var SegmentMode; +(function (SegmentMode) { + SegmentMode["FOREGROUND"] = "FOREGROUND"; + SegmentMode["BACKGROUND"] = "BACKGROUND"; + SegmentMode["PROMPT"] = "PROMPT"; + SegmentMode["SEMANTIC"] = "SEMANTIC"; + SegmentMode["INTERACTIVE"] = "INTERACTIVE"; +})(SegmentMode || (SegmentMode = {})); +/** Enum for the reference type of a video generation reference image. */ +var VideoGenerationReferenceType; +(function (VideoGenerationReferenceType) { + /** + * A reference image that provides assets to the generated video, + such as the scene, an object, a character, etc. + */ + VideoGenerationReferenceType["ASSET"] = "ASSET"; + /** + * A reference image that provides aesthetics including colors, + lighting, texture, etc., to be used as the style of the generated video, + such as 'anime', 'photography', 'origami', etc. + */ + VideoGenerationReferenceType["STYLE"] = "STYLE"; +})(VideoGenerationReferenceType || (VideoGenerationReferenceType = {})); +/** Enum for the mask mode of a video generation mask. */ +var VideoGenerationMaskMode; +(function (VideoGenerationMaskMode) { + /** + * The image mask contains a masked rectangular region which is + applied on the first frame of the input video. The object described in + the prompt is inserted into this region and will appear in subsequent + frames. + */ + VideoGenerationMaskMode["INSERT"] = "INSERT"; + /** + * The image mask is used to determine an object in the + first video frame to track. This object is removed from the video. + */ + VideoGenerationMaskMode["REMOVE"] = "REMOVE"; + /** + * The image mask is used to determine a region in the + video. Objects in this region will be removed. + */ + VideoGenerationMaskMode["REMOVE_STATIC"] = "REMOVE_STATIC"; + /** + * The image mask contains a masked rectangular region where + the input video will go. The remaining area will be generated. Video + masks are not supported. + */ + VideoGenerationMaskMode["OUTPAINT"] = "OUTPAINT"; +})(VideoGenerationMaskMode || (VideoGenerationMaskMode = {})); +/** Enum that controls the compression quality of the generated videos. */ +var VideoCompressionQuality; +(function (VideoCompressionQuality) { + /** + * Optimized video compression quality. This will produce videos + with a compressed, smaller file size. + */ + VideoCompressionQuality["OPTIMIZED"] = "OPTIMIZED"; + /** + * Lossless video compression quality. This will produce videos + with a larger file size. + */ + VideoCompressionQuality["LOSSLESS"] = "LOSSLESS"; +})(VideoCompressionQuality || (VideoCompressionQuality = {})); +/** Enum representing the tuning method. */ +var TuningMethod; +(function (TuningMethod) { + /** + * Supervised fine tuning. + */ + TuningMethod["SUPERVISED_FINE_TUNING"] = "SUPERVISED_FINE_TUNING"; + /** + * Preference optimization tuning. + */ + TuningMethod["PREFERENCE_TUNING"] = "PREFERENCE_TUNING"; + /** + * Distillation tuning. + */ + TuningMethod["DISTILLATION"] = "DISTILLATION"; +})(TuningMethod || (TuningMethod = {})); +/** State for the lifecycle of a Document. */ +var DocumentState; +(function (DocumentState) { + DocumentState["STATE_UNSPECIFIED"] = "STATE_UNSPECIFIED"; + DocumentState["STATE_PENDING"] = "STATE_PENDING"; + DocumentState["STATE_ACTIVE"] = "STATE_ACTIVE"; + DocumentState["STATE_FAILED"] = "STATE_FAILED"; +})(DocumentState || (DocumentState = {})); +/** State for the lifecycle of a File. */ +var FileState; +(function (FileState) { + FileState["STATE_UNSPECIFIED"] = "STATE_UNSPECIFIED"; + FileState["PROCESSING"] = "PROCESSING"; + FileState["ACTIVE"] = "ACTIVE"; + FileState["FAILED"] = "FAILED"; +})(FileState || (FileState = {})); +/** Source of the File. */ +var FileSource; +(function (FileSource) { + FileSource["SOURCE_UNSPECIFIED"] = "SOURCE_UNSPECIFIED"; + FileSource["UPLOADED"] = "UPLOADED"; + FileSource["GENERATED"] = "GENERATED"; + FileSource["REGISTERED"] = "REGISTERED"; +})(FileSource || (FileSource = {})); +/** The reason why the turn is complete. */ +var TurnCompleteReason; +(function (TurnCompleteReason) { + /** + * Default value. Reason is unspecified. + */ + TurnCompleteReason["TURN_COMPLETE_REASON_UNSPECIFIED"] = "TURN_COMPLETE_REASON_UNSPECIFIED"; + /** + * The function call generated by the model is invalid. + */ + TurnCompleteReason["MALFORMED_FUNCTION_CALL"] = "MALFORMED_FUNCTION_CALL"; + /** + * The response is rejected by the model. + */ + TurnCompleteReason["RESPONSE_REJECTED"] = "RESPONSE_REJECTED"; + /** + * Needs more input from the user. + */ + TurnCompleteReason["NEED_MORE_INPUT"] = "NEED_MORE_INPUT"; +})(TurnCompleteReason || (TurnCompleteReason = {})); +/** Server content modalities. */ +var MediaModality; +(function (MediaModality) { + /** + * The modality is unspecified. + */ + MediaModality["MODALITY_UNSPECIFIED"] = "MODALITY_UNSPECIFIED"; + /** + * Plain text. + */ + MediaModality["TEXT"] = "TEXT"; + /** + * Images. + */ + MediaModality["IMAGE"] = "IMAGE"; + /** + * Video. + */ + MediaModality["VIDEO"] = "VIDEO"; + /** + * Audio. + */ + MediaModality["AUDIO"] = "AUDIO"; + /** + * Document, e.g. PDF. + */ + MediaModality["DOCUMENT"] = "DOCUMENT"; +})(MediaModality || (MediaModality = {})); +/** The type of the VAD signal. */ +var VadSignalType; +(function (VadSignalType) { + /** + * The default is VAD_SIGNAL_TYPE_UNSPECIFIED. + */ + VadSignalType["VAD_SIGNAL_TYPE_UNSPECIFIED"] = "VAD_SIGNAL_TYPE_UNSPECIFIED"; + /** + * Start of sentence signal. + */ + VadSignalType["VAD_SIGNAL_TYPE_SOS"] = "VAD_SIGNAL_TYPE_SOS"; + /** + * End of sentence signal. + */ + VadSignalType["VAD_SIGNAL_TYPE_EOS"] = "VAD_SIGNAL_TYPE_EOS"; +})(VadSignalType || (VadSignalType = {})); +/** The type of the voice activity signal. */ +var VoiceActivityType; +(function (VoiceActivityType) { + /** + * The default is VOICE_ACTIVITY_TYPE_UNSPECIFIED. + */ + VoiceActivityType["TYPE_UNSPECIFIED"] = "TYPE_UNSPECIFIED"; + /** + * Start of sentence signal. + */ + VoiceActivityType["ACTIVITY_START"] = "ACTIVITY_START"; + /** + * End of sentence signal. + */ + VoiceActivityType["ACTIVITY_END"] = "ACTIVITY_END"; +})(VoiceActivityType || (VoiceActivityType = {})); +/** Start of speech sensitivity. */ +var StartSensitivity; +(function (StartSensitivity) { + /** + * The default is START_SENSITIVITY_LOW. + */ + StartSensitivity["START_SENSITIVITY_UNSPECIFIED"] = "START_SENSITIVITY_UNSPECIFIED"; + /** + * Automatic detection will detect the start of speech more often. + */ + StartSensitivity["START_SENSITIVITY_HIGH"] = "START_SENSITIVITY_HIGH"; + /** + * Automatic detection will detect the start of speech less often. + */ + StartSensitivity["START_SENSITIVITY_LOW"] = "START_SENSITIVITY_LOW"; +})(StartSensitivity || (StartSensitivity = {})); +/** End of speech sensitivity. */ +var EndSensitivity; +(function (EndSensitivity) { + /** + * The default is END_SENSITIVITY_LOW. + */ + EndSensitivity["END_SENSITIVITY_UNSPECIFIED"] = "END_SENSITIVITY_UNSPECIFIED"; + /** + * Automatic detection ends speech more often. + */ + EndSensitivity["END_SENSITIVITY_HIGH"] = "END_SENSITIVITY_HIGH"; + /** + * Automatic detection ends speech less often. + */ + EndSensitivity["END_SENSITIVITY_LOW"] = "END_SENSITIVITY_LOW"; +})(EndSensitivity || (EndSensitivity = {})); +/** The different ways of handling user activity. */ +var ActivityHandling; +(function (ActivityHandling) { + /** + * If unspecified, the default behavior is `START_OF_ACTIVITY_INTERRUPTS`. + */ + ActivityHandling["ACTIVITY_HANDLING_UNSPECIFIED"] = "ACTIVITY_HANDLING_UNSPECIFIED"; + /** + * If true, start of activity will interrupt the model's response (also called "barge in"). The model's current response will be cut-off in the moment of the interruption. This is the default behavior. + */ + ActivityHandling["START_OF_ACTIVITY_INTERRUPTS"] = "START_OF_ACTIVITY_INTERRUPTS"; + /** + * The model's response will not be interrupted. + */ + ActivityHandling["NO_INTERRUPTION"] = "NO_INTERRUPTION"; +})(ActivityHandling || (ActivityHandling = {})); +/** Options about which input is included in the user's turn. */ +var TurnCoverage; +(function (TurnCoverage) { + /** + * If unspecified, the default behavior is `TURN_INCLUDES_ONLY_ACTIVITY`. + */ + TurnCoverage["TURN_COVERAGE_UNSPECIFIED"] = "TURN_COVERAGE_UNSPECIFIED"; + /** + * The users turn only includes activity since the last turn, excluding inactivity (e.g. silence on the audio stream). This is the default behavior. + */ + TurnCoverage["TURN_INCLUDES_ONLY_ACTIVITY"] = "TURN_INCLUDES_ONLY_ACTIVITY"; + /** + * The users turn includes all realtime input since the last turn, including inactivity (e.g. silence on the audio stream). + */ + TurnCoverage["TURN_INCLUDES_ALL_INPUT"] = "TURN_INCLUDES_ALL_INPUT"; +})(TurnCoverage || (TurnCoverage = {})); +/** Scale of the generated music. */ +var Scale; +(function (Scale) { + /** + * Default value. This value is unused. + */ + Scale["SCALE_UNSPECIFIED"] = "SCALE_UNSPECIFIED"; + /** + * C major or A minor. + */ + Scale["C_MAJOR_A_MINOR"] = "C_MAJOR_A_MINOR"; + /** + * Db major or Bb minor. + */ + Scale["D_FLAT_MAJOR_B_FLAT_MINOR"] = "D_FLAT_MAJOR_B_FLAT_MINOR"; + /** + * D major or B minor. + */ + Scale["D_MAJOR_B_MINOR"] = "D_MAJOR_B_MINOR"; + /** + * Eb major or C minor + */ + Scale["E_FLAT_MAJOR_C_MINOR"] = "E_FLAT_MAJOR_C_MINOR"; + /** + * E major or Db minor. + */ + Scale["E_MAJOR_D_FLAT_MINOR"] = "E_MAJOR_D_FLAT_MINOR"; + /** + * F major or D minor. + */ + Scale["F_MAJOR_D_MINOR"] = "F_MAJOR_D_MINOR"; + /** + * Gb major or Eb minor. + */ + Scale["G_FLAT_MAJOR_E_FLAT_MINOR"] = "G_FLAT_MAJOR_E_FLAT_MINOR"; + /** + * G major or E minor. + */ + Scale["G_MAJOR_E_MINOR"] = "G_MAJOR_E_MINOR"; + /** + * Ab major or F minor. + */ + Scale["A_FLAT_MAJOR_F_MINOR"] = "A_FLAT_MAJOR_F_MINOR"; + /** + * A major or Gb minor. + */ + Scale["A_MAJOR_G_FLAT_MINOR"] = "A_MAJOR_G_FLAT_MINOR"; + /** + * Bb major or G minor. + */ + Scale["B_FLAT_MAJOR_G_MINOR"] = "B_FLAT_MAJOR_G_MINOR"; + /** + * B major or Ab minor. + */ + Scale["B_MAJOR_A_FLAT_MINOR"] = "B_MAJOR_A_FLAT_MINOR"; +})(Scale || (Scale = {})); +/** The mode of music generation. */ +var MusicGenerationMode; +(function (MusicGenerationMode) { + /** + * Rely on the server default generation mode. + */ + MusicGenerationMode["MUSIC_GENERATION_MODE_UNSPECIFIED"] = "MUSIC_GENERATION_MODE_UNSPECIFIED"; + /** + * Steer text prompts to regions of latent space with higher quality + music. + */ + MusicGenerationMode["QUALITY"] = "QUALITY"; + /** + * Steer text prompts to regions of latent space with a larger + diversity of music. + */ + MusicGenerationMode["DIVERSITY"] = "DIVERSITY"; + /** + * Steer text prompts to regions of latent space more likely to + generate music with vocals. + */ + MusicGenerationMode["VOCALIZATION"] = "VOCALIZATION"; +})(MusicGenerationMode || (MusicGenerationMode = {})); +/** The playback control signal to apply to the music generation. */ +var LiveMusicPlaybackControl; +(function (LiveMusicPlaybackControl) { + /** + * This value is unused. + */ + LiveMusicPlaybackControl["PLAYBACK_CONTROL_UNSPECIFIED"] = "PLAYBACK_CONTROL_UNSPECIFIED"; + /** + * Start generating the music. + */ + LiveMusicPlaybackControl["PLAY"] = "PLAY"; + /** + * Hold the music generation. Use PLAY to resume from the current position. + */ + LiveMusicPlaybackControl["PAUSE"] = "PAUSE"; + /** + * Stop the music generation and reset the context (prompts retained). + Use PLAY to restart the music generation. + */ + LiveMusicPlaybackControl["STOP"] = "STOP"; + /** + * Reset the context of the music generation without stopping it. + Retains the current prompts and config. + */ + LiveMusicPlaybackControl["RESET_CONTEXT"] = "RESET_CONTEXT"; +})(LiveMusicPlaybackControl || (LiveMusicPlaybackControl = {})); +/** Raw media bytes for function response. + +Text should not be sent as raw bytes, use the FunctionResponse.response +field. */ +class FunctionResponseBlob { +} +/** URI based data for function response. */ +class FunctionResponseFileData { +} +/** A datatype containing media that is part of a `FunctionResponse` message. + +A `FunctionResponsePart` consists of data which has an associated datatype. A +`FunctionResponsePart` can only contain one of the accepted types in +`FunctionResponsePart.data`. + +A `FunctionResponsePart` must have a fixed IANA MIME type identifying the +type and subtype of the media if the `inline_data` field is filled with raw +bytes. */ +class FunctionResponsePart { +} +/** + * Creates a `FunctionResponsePart` object from a `base64` encoded `string`. + */ +function createFunctionResponsePartFromBase64(data, mimeType) { + return { + inlineData: { + data: data, + mimeType: mimeType, + }, + }; +} +/** + * Creates a `FunctionResponsePart` object from a `URI` string. + */ +function createFunctionResponsePartFromUri(uri, mimeType) { + return { + fileData: { + fileUri: uri, + mimeType: mimeType, + }, + }; +} +/** A function response. */ +class FunctionResponse { +} +/** + * Creates a `Part` object from a `URI` string. + */ +function createPartFromUri(uri, mimeType, mediaResolution) { + return Object.assign({ fileData: { + fileUri: uri, + mimeType: mimeType, + } }, (mediaResolution && { mediaResolution: { level: mediaResolution } })); +} +/** + * Creates a `Part` object from a `text` string. + */ +function createPartFromText(text) { + return { + text: text, + }; +} +/** + * Creates a `Part` object from a `FunctionCall` object. + */ +function createPartFromFunctionCall(name, args) { + return { + functionCall: { + name: name, + args: args, + }, + }; +} +/** + * Creates a `Part` object from a `FunctionResponse` object. + */ +function createPartFromFunctionResponse(id, name, response, parts = []) { + return { + functionResponse: Object.assign({ id: id, name: name, response: response }, (parts.length > 0 && { parts })), + }; +} +/** + * Creates a `Part` object from a `base64` encoded `string`. + */ +function createPartFromBase64(data, mimeType, mediaResolution) { + return Object.assign({ inlineData: { + data: data, + mimeType: mimeType, + } }, (mediaResolution && { mediaResolution: { level: mediaResolution } })); +} +/** + * Creates a `Part` object from the `outcome` and `output` of a `CodeExecutionResult` object. + */ +function createPartFromCodeExecutionResult(outcome, output) { + return { + codeExecutionResult: { + outcome: outcome, + output: output, + }, + }; +} +/** + * Creates a `Part` object from the `code` and `language` of an `ExecutableCode` object. + */ +function createPartFromExecutableCode(code, language) { + return { + executableCode: { + code: code, + language: language, + }, + }; +} +function _isPart(obj) { + if (typeof obj === 'object' && obj !== null) { + return ('fileData' in obj || + 'text' in obj || + 'functionCall' in obj || + 'functionResponse' in obj || + 'inlineData' in obj || + 'videoMetadata' in obj || + 'codeExecutionResult' in obj || + 'executableCode' in obj); + } + return false; +} +function _toParts(partOrString) { + const parts = []; + if (typeof partOrString === 'string') { + parts.push(createPartFromText(partOrString)); + } + else if (_isPart(partOrString)) { + parts.push(partOrString); + } + else if (Array.isArray(partOrString)) { + if (partOrString.length === 0) { + throw new Error('partOrString cannot be an empty array'); + } + for (const part of partOrString) { + if (typeof part === 'string') { + parts.push(createPartFromText(part)); + } + else if (_isPart(part)) { + parts.push(part); + } + else { + throw new Error('element in PartUnion must be a Part object or string'); + } + } + } + else { + throw new Error('partOrString must be a Part object, string, or array'); + } + return parts; +} +/** + * Creates a `Content` object with a user role from a `PartListUnion` object or `string`. + */ +function createUserContent(partOrString) { + return { + role: 'user', + parts: _toParts(partOrString), + }; +} +/** + * Creates a `Content` object with a model role from a `PartListUnion` object or `string`. + */ +function createModelContent(partOrString) { + return { + role: 'model', + parts: _toParts(partOrString), + }; +} +/** A wrapper class for the http response. */ +class HttpResponse { + constructor(response) { + // Process the headers. + const headers = {}; + for (const pair of response.headers.entries()) { + headers[pair[0]] = pair[1]; + } + this.headers = headers; + // Keep the original response. + this.responseInternal = response; + } + json() { + return this.responseInternal.json(); + } +} +/** Content filter results for a prompt sent in the request. Note: This is sent only in the first stream chunk and only if no candidates were generated due to content violations. */ +class GenerateContentResponsePromptFeedback { +} +/** Usage metadata about the content generation request and response. This message provides a detailed breakdown of token usage and other relevant metrics. This data type is not supported in Gemini API. */ +class GenerateContentResponseUsageMetadata { +} +/** Response message for PredictionService.GenerateContent. */ +class GenerateContentResponse { + /** + * Returns the concatenation of all text parts from the first candidate in the response. + * + * @remarks + * If there are multiple candidates in the response, the text from the first + * one will be returned. + * If there are non-text parts in the response, the concatenation of all text + * parts will be returned, and a warning will be logged. + * If there are thought parts in the response, the concatenation of all text + * parts excluding the thought parts will be returned. + * + * @example + * ```ts + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: + * 'Why is the sky blue?', + * }); + * + * console.debug(response.text); + * ``` + */ + get text() { + var _a, _b, _c, _d, _e, _f, _g, _h; + if (((_d = (_c = (_b = (_a = this.candidates) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.parts) === null || _d === void 0 ? void 0 : _d.length) === 0) { + return undefined; + } + if (this.candidates && this.candidates.length > 1) { + console.warn('there are multiple candidates in the response, returning text from the first one.'); + } + let text = ''; + let anyTextPartText = false; + const nonTextParts = []; + for (const part of (_h = (_g = (_f = (_e = this.candidates) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.content) === null || _g === void 0 ? void 0 : _g.parts) !== null && _h !== void 0 ? _h : []) { + for (const [fieldName, fieldValue] of Object.entries(part)) { + if (fieldName !== 'text' && + fieldName !== 'thought' && + fieldName !== 'thoughtSignature' && + (fieldValue !== null || fieldValue !== undefined)) { + nonTextParts.push(fieldName); + } + } + if (typeof part.text === 'string') { + if (typeof part.thought === 'boolean' && part.thought) { + continue; + } + anyTextPartText = true; + text += part.text; + } + } + if (nonTextParts.length > 0) { + console.warn(`there are non-text parts ${nonTextParts} in the response, returning concatenation of all text parts. Please refer to the non text parts for a full response from model.`); + } + // part.text === '' is different from part.text is null + return anyTextPartText ? text : undefined; + } + /** + * Returns the concatenation of all inline data parts from the first candidate + * in the response. + * + * @remarks + * If there are multiple candidates in the response, the inline data from the + * first one will be returned. If there are non-inline data parts in the + * response, the concatenation of all inline data parts will be returned, and + * a warning will be logged. + */ + get data() { + var _a, _b, _c, _d, _e, _f, _g, _h; + if (((_d = (_c = (_b = (_a = this.candidates) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.parts) === null || _d === void 0 ? void 0 : _d.length) === 0) { + return undefined; + } + if (this.candidates && this.candidates.length > 1) { + console.warn('there are multiple candidates in the response, returning data from the first one.'); + } + let data = ''; + const nonDataParts = []; + for (const part of (_h = (_g = (_f = (_e = this.candidates) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.content) === null || _g === void 0 ? void 0 : _g.parts) !== null && _h !== void 0 ? _h : []) { + for (const [fieldName, fieldValue] of Object.entries(part)) { + if (fieldName !== 'inlineData' && + (fieldValue !== null || fieldValue !== undefined)) { + nonDataParts.push(fieldName); + } + } + if (part.inlineData && typeof part.inlineData.data === 'string') { + data += atob(part.inlineData.data); + } + } + if (nonDataParts.length > 0) { + console.warn(`there are non-data parts ${nonDataParts} in the response, returning concatenation of all data parts. Please refer to the non data parts for a full response from model.`); + } + return data.length > 0 ? btoa(data) : undefined; + } + /** + * Returns the function calls from the first candidate in the response. + * + * @remarks + * If there are multiple candidates in the response, the function calls from + * the first one will be returned. + * If there are no function calls in the response, undefined will be returned. + * + * @example + * ```ts + * const controlLightFunctionDeclaration: FunctionDeclaration = { + * name: 'controlLight', + * parameters: { + * type: Type.OBJECT, + * description: 'Set the brightness and color temperature of a room light.', + * properties: { + * brightness: { + * type: Type.NUMBER, + * description: + * 'Light level from 0 to 100. Zero is off and 100 is full brightness.', + * }, + * colorTemperature: { + * type: Type.STRING, + * description: + * 'Color temperature of the light fixture which can be `daylight`, `cool` or `warm`.', + * }, + * }, + * required: ['brightness', 'colorTemperature'], + * }; + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: 'Dim the lights so the room feels cozy and warm.', + * config: { + * tools: [{functionDeclarations: [controlLightFunctionDeclaration]}], + * toolConfig: { + * functionCallingConfig: { + * mode: FunctionCallingConfigMode.ANY, + * allowedFunctionNames: ['controlLight'], + * }, + * }, + * }, + * }); + * console.debug(JSON.stringify(response.functionCalls)); + * ``` + */ + get functionCalls() { + var _a, _b, _c, _d, _e, _f, _g, _h; + if (((_d = (_c = (_b = (_a = this.candidates) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.parts) === null || _d === void 0 ? void 0 : _d.length) === 0) { + return undefined; + } + if (this.candidates && this.candidates.length > 1) { + console.warn('there are multiple candidates in the response, returning function calls from the first one.'); + } + const functionCalls = (_h = (_g = (_f = (_e = this.candidates) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.content) === null || _g === void 0 ? void 0 : _g.parts) === null || _h === void 0 ? void 0 : _h.filter((part) => part.functionCall).map((part) => part.functionCall).filter((functionCall) => functionCall !== undefined); + if ((functionCalls === null || functionCalls === void 0 ? void 0 : functionCalls.length) === 0) { + return undefined; + } + return functionCalls; + } + /** + * Returns the first executable code from the first candidate in the response. + * + * @remarks + * If there are multiple candidates in the response, the executable code from + * the first one will be returned. + * If there are no executable code in the response, undefined will be + * returned. + * + * @example + * ```ts + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: + * 'What is the sum of the first 50 prime numbers? Generate and run code for the calculation, and make sure you get all 50.' + * config: { + * tools: [{codeExecution: {}}], + * }, + * }); + * + * console.debug(response.executableCode); + * ``` + */ + get executableCode() { + var _a, _b, _c, _d, _e, _f, _g, _h, _j; + if (((_d = (_c = (_b = (_a = this.candidates) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.parts) === null || _d === void 0 ? void 0 : _d.length) === 0) { + return undefined; + } + if (this.candidates && this.candidates.length > 1) { + console.warn('there are multiple candidates in the response, returning executable code from the first one.'); + } + const executableCode = (_h = (_g = (_f = (_e = this.candidates) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.content) === null || _g === void 0 ? void 0 : _g.parts) === null || _h === void 0 ? void 0 : _h.filter((part) => part.executableCode).map((part) => part.executableCode).filter((executableCode) => executableCode !== undefined); + if ((executableCode === null || executableCode === void 0 ? void 0 : executableCode.length) === 0) { + return undefined; + } + return (_j = executableCode === null || executableCode === void 0 ? void 0 : executableCode[0]) === null || _j === void 0 ? void 0 : _j.code; + } + /** + * Returns the first code execution result from the first candidate in the response. + * + * @remarks + * If there are multiple candidates in the response, the code execution result from + * the first one will be returned. + * If there are no code execution result in the response, undefined will be returned. + * + * @example + * ```ts + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: + * 'What is the sum of the first 50 prime numbers? Generate and run code for the calculation, and make sure you get all 50.' + * config: { + * tools: [{codeExecution: {}}], + * }, + * }); + * + * console.debug(response.codeExecutionResult); + * ``` + */ + get codeExecutionResult() { + var _a, _b, _c, _d, _e, _f, _g, _h, _j; + if (((_d = (_c = (_b = (_a = this.candidates) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.parts) === null || _d === void 0 ? void 0 : _d.length) === 0) { + return undefined; + } + if (this.candidates && this.candidates.length > 1) { + console.warn('there are multiple candidates in the response, returning code execution result from the first one.'); + } + const codeExecutionResult = (_h = (_g = (_f = (_e = this.candidates) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.content) === null || _g === void 0 ? void 0 : _g.parts) === null || _h === void 0 ? void 0 : _h.filter((part) => part.codeExecutionResult).map((part) => part.codeExecutionResult).filter((codeExecutionResult) => codeExecutionResult !== undefined); + if ((codeExecutionResult === null || codeExecutionResult === void 0 ? void 0 : codeExecutionResult.length) === 0) { + return undefined; + } + return (_j = codeExecutionResult === null || codeExecutionResult === void 0 ? void 0 : codeExecutionResult[0]) === null || _j === void 0 ? void 0 : _j.output; + } +} +/** Response for the embed_content method. */ +class EmbedContentResponse { +} +/** The output images response. */ +class GenerateImagesResponse { +} +/** Response for the request to edit an image. */ +class EditImageResponse { +} +class UpscaleImageResponse { +} +/** The output images response. */ +class RecontextImageResponse { +} +/** The output images response. */ +class SegmentImageResponse { +} +class ListModelsResponse { +} +class DeleteModelResponse { +} +/** Response for counting tokens. */ +class CountTokensResponse { +} +/** Response for computing tokens. */ +class ComputeTokensResponse { +} +/** Response with generated videos. */ +class GenerateVideosResponse { +} +/** A video generation operation. */ +class GenerateVideosOperation { + /** + * Instantiates an Operation of the same type as the one being called with the fields set from the API response. + * @internal + */ + _fromAPIResponse({ apiResponse, _isVertexAI, }) { + const operation = new GenerateVideosOperation(); + let response; + const op = apiResponse; + if (_isVertexAI) { + response = generateVideosOperationFromVertex$1(op); + } + else { + response = generateVideosOperationFromMldev$1(op); + } + Object.assign(operation, response); + return operation; + } +} +/** Response for the list tuning jobs method. */ +class ListTuningJobsResponse { +} +/** Empty response for tunings.cancel method. */ +class CancelTuningJobResponse { +} +/** Empty response for caches.delete method. */ +class DeleteCachedContentResponse { +} +class ListCachedContentsResponse { +} +/** Config for documents.list return value. */ +class ListDocumentsResponse { +} +/** Config for file_search_stores.list return value. */ +class ListFileSearchStoresResponse { +} +/** Response for the resumable upload method. */ +class UploadToFileSearchStoreResumableResponse { +} +/** Response for ImportFile to import a File API file with a file search store. */ +class ImportFileResponse { +} +/** Long-running operation for importing a file to a FileSearchStore. */ +class ImportFileOperation { + /** + * Instantiates an Operation of the same type as the one being called with the fields set from the API response. + * @internal + */ + _fromAPIResponse({ apiResponse, _isVertexAI, }) { + const operation = new ImportFileOperation(); + const op = apiResponse; + const response = importFileOperationFromMldev$1(op); + Object.assign(operation, response); + return operation; + } +} +/** Response for the list files method. */ +class ListFilesResponse { +} +/** Response for the create file method. */ +class CreateFileResponse { +} +/** Response for the delete file method. */ +class DeleteFileResponse { +} +/** Response for the _register file method. */ +class RegisterFilesResponse { +} +/** Config for `inlined_responses` parameter. */ +class InlinedResponse { +} +/** Config for `response` parameter. */ +class SingleEmbedContentResponse { +} +/** Config for `inlined_embedding_responses` parameter. */ +class InlinedEmbedContentResponse { +} +/** Config for batches.list return value. */ +class ListBatchJobsResponse { +} +/** Represents a single response in a replay. */ +class ReplayResponse { +} +/** A raw reference image. + +A raw reference image represents the base image to edit, provided by the user. +It can optionally be provided in addition to a mask reference image or +a style reference image. */ +class RawReferenceImage { + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI() { + const referenceImageAPI = { + referenceType: 'REFERENCE_TYPE_RAW', + referenceImage: this.referenceImage, + referenceId: this.referenceId, + }; + return referenceImageAPI; + } +} +/** A mask reference image. + +This encapsulates either a mask image provided by the user and configs for +the user provided mask, or only config parameters for the model to generate +a mask. + +A mask image is an image whose non-zero values indicate where to edit the base +image. If the user provides a mask image, the mask must be in the same +dimensions as the raw image. */ +class MaskReferenceImage { + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI() { + const referenceImageAPI = { + referenceType: 'REFERENCE_TYPE_MASK', + referenceImage: this.referenceImage, + referenceId: this.referenceId, + maskImageConfig: this.config, + }; + return referenceImageAPI; + } +} +/** A control reference image. + +The image of the control reference image is either a control image provided +by the user, or a regular image which the backend will use to generate a +control image of. In the case of the latter, the +enable_control_image_computation field in the config should be set to True. + +A control image is an image that represents a sketch image of areas for the +model to fill in based on the prompt. */ +class ControlReferenceImage { + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI() { + const referenceImageAPI = { + referenceType: 'REFERENCE_TYPE_CONTROL', + referenceImage: this.referenceImage, + referenceId: this.referenceId, + controlImageConfig: this.config, + }; + return referenceImageAPI; + } +} +/** A style reference image. + +This encapsulates a style reference image provided by the user, and +additionally optional config parameters for the style reference image. + +A raw reference image can also be provided as a destination for the style to +be applied to. */ +class StyleReferenceImage { + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI() { + const referenceImageAPI = { + referenceType: 'REFERENCE_TYPE_STYLE', + referenceImage: this.referenceImage, + referenceId: this.referenceId, + styleImageConfig: this.config, + }; + return referenceImageAPI; + } +} +/** A subject reference image. + +This encapsulates a subject reference image provided by the user, and +additionally optional config parameters for the subject reference image. + +A raw reference image can also be provided as a destination for the subject to +be applied to. */ +class SubjectReferenceImage { + /* Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI() { + const referenceImageAPI = { + referenceType: 'REFERENCE_TYPE_SUBJECT', + referenceImage: this.referenceImage, + referenceId: this.referenceId, + subjectImageConfig: this.config, + }; + return referenceImageAPI; + } +} +/** A content reference image. + +A content reference image represents a subject to reference (ex. person, +product, animal) provided by the user. It can optionally be provided in +addition to a style reference image (ex. background, style reference). */ +class ContentReferenceImage { + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI() { + const referenceImageAPI = { + referenceType: 'REFERENCE_TYPE_CONTENT', + referenceImage: this.referenceImage, + referenceId: this.referenceId, + }; + return referenceImageAPI; + } +} +/** Response message for API call. */ +class LiveServerMessage { + /** + * Returns the concatenation of all text parts from the server content if present. + * + * @remarks + * If there are non-text parts in the response, the concatenation of all text + * parts will be returned, and a warning will be logged. + */ + get text() { + var _a, _b, _c; + let text = ''; + let anyTextPartFound = false; + const nonTextParts = []; + for (const part of (_c = (_b = (_a = this.serverContent) === null || _a === void 0 ? void 0 : _a.modelTurn) === null || _b === void 0 ? void 0 : _b.parts) !== null && _c !== void 0 ? _c : []) { + for (const [fieldName, fieldValue] of Object.entries(part)) { + if (fieldName !== 'text' && + fieldName !== 'thought' && + fieldValue !== null) { + nonTextParts.push(fieldName); + } + } + if (typeof part.text === 'string') { + if (typeof part.thought === 'boolean' && part.thought) { + continue; + } + anyTextPartFound = true; + text += part.text; + } + } + if (nonTextParts.length > 0) { + console.warn(`there are non-text parts ${nonTextParts} in the response, returning concatenation of all text parts. Please refer to the non text parts for a full response from model.`); + } + // part.text === '' is different from part.text is null + return anyTextPartFound ? text : undefined; + } + /** + * Returns the concatenation of all inline data parts from the server content if present. + * + * @remarks + * If there are non-inline data parts in the + * response, the concatenation of all inline data parts will be returned, and + * a warning will be logged. + */ + get data() { + var _a, _b, _c; + let data = ''; + const nonDataParts = []; + for (const part of (_c = (_b = (_a = this.serverContent) === null || _a === void 0 ? void 0 : _a.modelTurn) === null || _b === void 0 ? void 0 : _b.parts) !== null && _c !== void 0 ? _c : []) { + for (const [fieldName, fieldValue] of Object.entries(part)) { + if (fieldName !== 'inlineData' && fieldValue !== null) { + nonDataParts.push(fieldName); + } + } + if (part.inlineData && typeof part.inlineData.data === 'string') { + data += atob(part.inlineData.data); + } + } + if (nonDataParts.length > 0) { + console.warn(`there are non-data parts ${nonDataParts} in the response, returning concatenation of all data parts. Please refer to the non data parts for a full response from model.`); + } + return data.length > 0 ? btoa(data) : undefined; + } +} +/** Client generated response to a `ToolCall` received from the server. + +Individual `FunctionResponse` objects are matched to the respective +`FunctionCall` objects by the `id` field. + +Note that in the unary and server-streaming GenerateContent APIs function +calling happens by exchanging the `Content` parts, while in the bidi +GenerateContent APIs function calling happens over this dedicated set of +messages. */ +class LiveClientToolResponse { +} +/** Parameters for sending tool responses to the live API. */ +class LiveSendToolResponseParameters { + constructor() { + /** Tool responses to send to the session. */ + this.functionResponses = []; + } +} +/** Response message for the LiveMusicClientMessage call. */ +class LiveMusicServerMessage { + /** + * Returns the first audio chunk from the server content, if present. + * + * @remarks + * If there are no audio chunks in the response, undefined will be returned. + */ + get audioChunk() { + if (this.serverContent && + this.serverContent.audioChunks && + this.serverContent.audioChunks.length > 0) { + return this.serverContent.audioChunks[0]; + } + return undefined; + } +} +/** The response when long-running operation for uploading a file to a FileSearchStore complete. */ +class UploadToFileSearchStoreResponse { +} +/** Long-running operation for uploading a file to a FileSearchStore. */ +class UploadToFileSearchStoreOperation { + /** + * Instantiates an Operation of the same type as the one being called with the fields set from the API response. + * @internal + */ + _fromAPIResponse({ apiResponse, _isVertexAI, }) { + const operation = new UploadToFileSearchStoreOperation(); + const op = apiResponse; + const response = uploadToFileSearchStoreOperationFromMldev(op); + Object.assign(operation, response); + return operation; + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function tModel(apiClient, model) { + if (!model || typeof model !== 'string') { + throw new Error('model is required and must be a string'); + } + if (model.includes('..') || model.includes('?') || model.includes('&')) { + throw new Error('invalid model parameter'); + } + if (apiClient.isVertexAI()) { + if (model.startsWith('publishers/') || + model.startsWith('projects/') || + model.startsWith('models/')) { + return model; + } + else if (model.indexOf('/') >= 0) { + const parts = model.split('/', 2); + return `publishers/${parts[0]}/models/${parts[1]}`; + } + else { + return `publishers/google/models/${model}`; + } + } + else { + if (model.startsWith('models/') || model.startsWith('tunedModels/')) { + return model; + } + else { + return `models/${model}`; + } + } +} +function tCachesModel(apiClient, model) { + const transformedModel = tModel(apiClient, model); + if (!transformedModel) { + return ''; + } + if (transformedModel.startsWith('publishers/') && apiClient.isVertexAI()) { + // vertex caches only support model name start with projects. + return `projects/${apiClient.getProject()}/locations/${apiClient.getLocation()}/${transformedModel}`; + } + else if (transformedModel.startsWith('models/') && apiClient.isVertexAI()) { + return `projects/${apiClient.getProject()}/locations/${apiClient.getLocation()}/publishers/google/${transformedModel}`; + } + else { + return transformedModel; + } +} +function tBlobs(blobs) { + if (Array.isArray(blobs)) { + return blobs.map((blob) => tBlob(blob)); + } + else { + return [tBlob(blobs)]; + } +} +function tBlob(blob) { + if (typeof blob === 'object' && blob !== null) { + return blob; + } + throw new Error(`Could not parse input as Blob. Unsupported blob type: ${typeof blob}`); +} +function tImageBlob(blob) { + const transformedBlob = tBlob(blob); + if (transformedBlob.mimeType && + transformedBlob.mimeType.startsWith('image/')) { + return transformedBlob; + } + throw new Error(`Unsupported mime type: ${transformedBlob.mimeType}`); +} +function tAudioBlob(blob) { + const transformedBlob = tBlob(blob); + if (transformedBlob.mimeType && + transformedBlob.mimeType.startsWith('audio/')) { + return transformedBlob; + } + throw new Error(`Unsupported mime type: ${transformedBlob.mimeType}`); +} +function tPart(origin) { + if (origin === null || origin === undefined) { + throw new Error('PartUnion is required'); + } + if (typeof origin === 'object') { + return origin; + } + if (typeof origin === 'string') { + return { text: origin }; + } + throw new Error(`Unsupported part type: ${typeof origin}`); +} +function tParts(origin) { + if (origin === null || + origin === undefined || + (Array.isArray(origin) && origin.length === 0)) { + throw new Error('PartListUnion is required'); + } + if (Array.isArray(origin)) { + return origin.map((item) => tPart(item)); + } + return [tPart(origin)]; +} +function _isContent(origin) { + return (origin !== null && + origin !== undefined && + typeof origin === 'object' && + 'parts' in origin && + Array.isArray(origin.parts)); +} +function _isFunctionCallPart(origin) { + return (origin !== null && + origin !== undefined && + typeof origin === 'object' && + 'functionCall' in origin); +} +function _isFunctionResponsePart(origin) { + return (origin !== null && + origin !== undefined && + typeof origin === 'object' && + 'functionResponse' in origin); +} +function tContent(origin) { + if (origin === null || origin === undefined) { + throw new Error('ContentUnion is required'); + } + if (_isContent(origin)) { + // _isContent is a utility function that checks if the + // origin is a Content. + return origin; + } + return { + role: 'user', + parts: tParts(origin), + }; +} +function tContentsForEmbed(apiClient, origin) { + if (!origin) { + return []; + } + if (apiClient.isVertexAI() && Array.isArray(origin)) { + return origin.flatMap((item) => { + const content = tContent(item); + if (content.parts && + content.parts.length > 0 && + content.parts[0].text !== undefined) { + return [content.parts[0].text]; + } + return []; + }); + } + else if (apiClient.isVertexAI()) { + const content = tContent(origin); + if (content.parts && + content.parts.length > 0 && + content.parts[0].text !== undefined) { + return [content.parts[0].text]; + } + return []; + } + if (Array.isArray(origin)) { + return origin.map((item) => tContent(item)); + } + return [tContent(origin)]; +} +function tContents(origin) { + if (origin === null || + origin === undefined || + (Array.isArray(origin) && origin.length === 0)) { + throw new Error('contents are required'); + } + if (!Array.isArray(origin)) { + // If it's not an array, it's a single content or a single PartUnion. + if (_isFunctionCallPart(origin) || _isFunctionResponsePart(origin)) { + throw new Error('To specify functionCall or functionResponse parts, please wrap them in a Content object, specifying the role for them'); + } + return [tContent(origin)]; + } + const result = []; + const accumulatedParts = []; + const isContentArray = _isContent(origin[0]); + for (const item of origin) { + const isContent = _isContent(item); + if (isContent != isContentArray) { + throw new Error('Mixing Content and Parts is not supported, please group the parts into a the appropriate Content objects and specify the roles for them'); + } + if (isContent) { + // `isContent` contains the result of _isContent, which is a utility + // function that checks if the item is a Content. + result.push(item); + } + else if (_isFunctionCallPart(item) || _isFunctionResponsePart(item)) { + throw new Error('To specify functionCall or functionResponse parts, please wrap them, and any other parts, in Content objects as appropriate, specifying the role for them'); + } + else { + accumulatedParts.push(item); + } + } + if (!isContentArray) { + result.push({ role: 'user', parts: tParts(accumulatedParts) }); + } + return result; +} +/* +Transform the type field from an array of types to an array of anyOf fields. +Example: + {type: ['STRING', 'NUMBER']} +will be transformed to + {anyOf: [{type: 'STRING'}, {type: 'NUMBER'}]} +*/ +function flattenTypeArrayToAnyOf(typeList, resultingSchema) { + if (typeList.includes('null')) { + resultingSchema['nullable'] = true; + } + const listWithoutNull = typeList.filter((type) => type !== 'null'); + if (listWithoutNull.length === 1) { + resultingSchema['type'] = Object.values(Type).includes(listWithoutNull[0].toUpperCase()) + ? listWithoutNull[0].toUpperCase() + : Type.TYPE_UNSPECIFIED; + } + else { + resultingSchema['anyOf'] = []; + for (const i of listWithoutNull) { + resultingSchema['anyOf'].push({ + 'type': Object.values(Type).includes(i.toUpperCase()) + ? i.toUpperCase() + : Type.TYPE_UNSPECIFIED, + }); + } + } +} +function processJsonSchema(_jsonSchema) { + const genAISchema = {}; + const schemaFieldNames = ['items']; + const listSchemaFieldNames = ['anyOf']; + const dictSchemaFieldNames = ['properties']; + if (_jsonSchema['type'] && _jsonSchema['anyOf']) { + throw new Error('type and anyOf cannot be both populated.'); + } + /* + This is to handle the nullable array or object. The _jsonSchema will + be in the format of {anyOf: [{type: 'null'}, {type: 'object'}]}. The + logic is to check if anyOf has 2 elements and one of the element is null, + if so, the anyOf field is unnecessary, so we need to get rid of the anyOf + field and make the schema nullable. Then use the other element as the new + _jsonSchema for processing. This is because the backend doesn't have a null + type. + This has to be checked before we process any other fields. + For example: + const objectNullable = z.object({ + nullableArray: z.array(z.string()).nullable(), + }); + Will have the raw _jsonSchema as: + { + type: 'OBJECT', + properties: { + nullableArray: { + anyOf: [ + {type: 'null'}, + { + type: 'array', + items: {type: 'string'}, + }, + ], + } + }, + required: [ 'nullableArray' ], + } + Will result in following schema compatible with Gemini API: + { + type: 'OBJECT', + properties: { + nullableArray: { + nullable: true, + type: 'ARRAY', + items: {type: 'string'}, + } + }, + required: [ 'nullableArray' ], + } + */ + const incomingAnyOf = _jsonSchema['anyOf']; + if (incomingAnyOf != null && incomingAnyOf.length == 2) { + if (incomingAnyOf[0]['type'] === 'null') { + genAISchema['nullable'] = true; + _jsonSchema = incomingAnyOf[1]; + } + else if (incomingAnyOf[1]['type'] === 'null') { + genAISchema['nullable'] = true; + _jsonSchema = incomingAnyOf[0]; + } + } + if (_jsonSchema['type'] instanceof Array) { + flattenTypeArrayToAnyOf(_jsonSchema['type'], genAISchema); + } + for (const [fieldName, fieldValue] of Object.entries(_jsonSchema)) { + // Skip if the fieldvalue is undefined or null. + if (fieldValue == null) { + continue; + } + if (fieldName == 'type') { + if (fieldValue === 'null') { + throw new Error('type: null can not be the only possible type for the field.'); + } + if (fieldValue instanceof Array) { + // we have already handled the type field with array of types in the + // beginning of this function. + continue; + } + genAISchema['type'] = Object.values(Type).includes(fieldValue.toUpperCase()) + ? fieldValue.toUpperCase() + : Type.TYPE_UNSPECIFIED; + } + else if (schemaFieldNames.includes(fieldName)) { + genAISchema[fieldName] = + processJsonSchema(fieldValue); + } + else if (listSchemaFieldNames.includes(fieldName)) { + const listSchemaFieldValue = []; + for (const item of fieldValue) { + if (item['type'] == 'null') { + genAISchema['nullable'] = true; + continue; + } + listSchemaFieldValue.push(processJsonSchema(item)); + } + genAISchema[fieldName] = + listSchemaFieldValue; + } + else if (dictSchemaFieldNames.includes(fieldName)) { + const dictSchemaFieldValue = {}; + for (const [key, value] of Object.entries(fieldValue)) { + dictSchemaFieldValue[key] = processJsonSchema(value); + } + genAISchema[fieldName] = + dictSchemaFieldValue; + } + else { + // additionalProperties is not included in JSONSchema, skipping it. + if (fieldName === 'additionalProperties') { + continue; + } + genAISchema[fieldName] = fieldValue; + } + } + return genAISchema; +} +// we take the unknown in the schema field because we want enable user to pass +// the output of major schema declaration tools without casting. Tools such as +// zodToJsonSchema, typebox, zodToJsonSchema function can return JsonSchema7Type +// or object, see details in +// https://github.com/StefanTerdell/zod-to-json-schema/blob/70525efe555cd226691e093d171370a3b10921d1/src/zodToJsonSchema.ts#L7 +// typebox can return unknown, see details in +// https://github.com/sinclairzx81/typebox/blob/5a5431439f7d5ca6b494d0d18fbfd7b1a356d67c/src/type/create/type.ts#L35 +// Note: proper json schemas with the $schema field set never arrive to this +// transformer. Schemas with $schema are routed to the equivalent API json +// schema field. +function tSchema(schema) { + return processJsonSchema(schema); +} +function tSpeechConfig(speechConfig) { + if (typeof speechConfig === 'object') { + return speechConfig; + } + else if (typeof speechConfig === 'string') { + return { + voiceConfig: { + prebuiltVoiceConfig: { + voiceName: speechConfig, + }, + }, + }; + } + else { + throw new Error(`Unsupported speechConfig type: ${typeof speechConfig}`); + } +} +function tLiveSpeechConfig(speechConfig) { + if ('multiSpeakerVoiceConfig' in speechConfig) { + throw new Error('multiSpeakerVoiceConfig is not supported in the live API.'); + } + return speechConfig; +} +function tTool(tool) { + if (tool.functionDeclarations) { + for (const functionDeclaration of tool.functionDeclarations) { + if (functionDeclaration.parameters) { + if (!Object.keys(functionDeclaration.parameters).includes('$schema')) { + functionDeclaration.parameters = processJsonSchema(functionDeclaration.parameters); + } + else { + if (!functionDeclaration.parametersJsonSchema) { + functionDeclaration.parametersJsonSchema = + functionDeclaration.parameters; + delete functionDeclaration.parameters; + } + } + } + if (functionDeclaration.response) { + if (!Object.keys(functionDeclaration.response).includes('$schema')) { + functionDeclaration.response = processJsonSchema(functionDeclaration.response); + } + else { + if (!functionDeclaration.responseJsonSchema) { + functionDeclaration.responseJsonSchema = + functionDeclaration.response; + delete functionDeclaration.response; + } + } + } + } + } + return tool; +} +function tTools(tools) { + // Check if the incoming type is defined. + if (tools === undefined || tools === null) { + throw new Error('tools is required'); + } + if (!Array.isArray(tools)) { + throw new Error('tools is required and must be an array of Tools'); + } + const result = []; + for (const tool of tools) { + result.push(tool); + } + return result; +} +/** + * Prepends resource name with project, location, resource_prefix if needed. + * + * @param client The API client. + * @param resourceName The resource name. + * @param resourcePrefix The resource prefix. + * @param splitsAfterPrefix The number of splits after the prefix. + * @returns The completed resource name. + * + * Examples: + * + * ``` + * resource_name = '123' + * resource_prefix = 'cachedContents' + * splits_after_prefix = 1 + * client.vertexai = True + * client.project = 'bar' + * client.location = 'us-west1' + * _resource_name(client, resource_name, resource_prefix, splits_after_prefix) + * returns: 'projects/bar/locations/us-west1/cachedContents/123' + * ``` + * + * ``` + * resource_name = 'projects/foo/locations/us-central1/cachedContents/123' + * resource_prefix = 'cachedContents' + * splits_after_prefix = 1 + * client.vertexai = True + * client.project = 'bar' + * client.location = 'us-west1' + * _resource_name(client, resource_name, resource_prefix, splits_after_prefix) + * returns: 'projects/foo/locations/us-central1/cachedContents/123' + * ``` + * + * ``` + * resource_name = '123' + * resource_prefix = 'cachedContents' + * splits_after_prefix = 1 + * client.vertexai = False + * _resource_name(client, resource_name, resource_prefix, splits_after_prefix) + * returns 'cachedContents/123' + * ``` + * + * ``` + * resource_name = 'some/wrong/cachedContents/resource/name/123' + * resource_prefix = 'cachedContents' + * splits_after_prefix = 1 + * client.vertexai = False + * # client.vertexai = True + * _resource_name(client, resource_name, resource_prefix, splits_after_prefix) + * -> 'some/wrong/resource/name/123' + * ``` + */ +function resourceName(client, resourceName, resourcePrefix, splitsAfterPrefix = 1) { + const shouldAppendPrefix = !resourceName.startsWith(`${resourcePrefix}/`) && + resourceName.split('/').length === splitsAfterPrefix; + if (client.isVertexAI()) { + if (resourceName.startsWith('projects/')) { + return resourceName; + } + else if (resourceName.startsWith('locations/')) { + return `projects/${client.getProject()}/${resourceName}`; + } + else if (resourceName.startsWith(`${resourcePrefix}/`)) { + return `projects/${client.getProject()}/locations/${client.getLocation()}/${resourceName}`; + } + else if (shouldAppendPrefix) { + return `projects/${client.getProject()}/locations/${client.getLocation()}/${resourcePrefix}/${resourceName}`; + } + else { + return resourceName; + } + } + if (shouldAppendPrefix) { + return `${resourcePrefix}/${resourceName}`; + } + return resourceName; +} +function tCachedContentName(apiClient, name) { + if (typeof name !== 'string') { + throw new Error('name must be a string'); + } + return resourceName(apiClient, name, 'cachedContents'); +} +function tTuningJobStatus(status) { + switch (status) { + case 'STATE_UNSPECIFIED': + return 'JOB_STATE_UNSPECIFIED'; + case 'CREATING': + return 'JOB_STATE_RUNNING'; + case 'ACTIVE': + return 'JOB_STATE_SUCCEEDED'; + case 'FAILED': + return 'JOB_STATE_FAILED'; + default: + return status; + } +} +function tBytes(fromImageBytes) { + return tBytes$1(fromImageBytes); +} +function _isFile(origin) { + return (origin !== null && + origin !== undefined && + typeof origin === 'object' && + 'name' in origin); +} +function isGeneratedVideo(origin) { + return (origin !== null && + origin !== undefined && + typeof origin === 'object' && + 'video' in origin); +} +function isVideo(origin) { + return (origin !== null && + origin !== undefined && + typeof origin === 'object' && + 'uri' in origin); +} +function tFileName(fromName) { + var _a; + let name; + if (_isFile(fromName)) { + name = fromName.name; + } + if (isVideo(fromName)) { + name = fromName.uri; + if (name === undefined) { + return undefined; + } + } + if (isGeneratedVideo(fromName)) { + name = (_a = fromName.video) === null || _a === void 0 ? void 0 : _a.uri; + if (name === undefined) { + return undefined; + } + } + if (typeof fromName === 'string') { + name = fromName; + } + if (name === undefined) { + throw new Error('Could not extract file name from the provided input.'); + } + if (name.startsWith('https://')) { + const suffix = name.split('files/')[1]; + const match = suffix.match(/[a-z0-9]+/); + if (match === null) { + throw new Error(`Could not extract file name from URI ${name}`); + } + name = match[0]; + } + else if (name.startsWith('files/')) { + name = name.split('files/')[1]; + } + return name; +} +function tModelsUrl(apiClient, baseModels) { + let res; + if (apiClient.isVertexAI()) { + res = baseModels ? 'publishers/google/models' : 'models'; + } + else { + res = baseModels ? 'models' : 'tunedModels'; + } + return res; +} +function tExtractModels(response) { + for (const key of ['models', 'tunedModels', 'publisherModels']) { + if (hasField(response, key)) { + return response[key]; + } + } + return []; +} +function hasField(data, fieldName) { + return data !== null && typeof data === 'object' && fieldName in data; +} +function mcpToGeminiTool(mcpTool, config = {}) { + const mcpToolSchema = mcpTool; + const functionDeclaration = { + name: mcpToolSchema['name'], + description: mcpToolSchema['description'], + parametersJsonSchema: mcpToolSchema['inputSchema'], + }; + if (mcpToolSchema['outputSchema']) { + functionDeclaration['responseJsonSchema'] = mcpToolSchema['outputSchema']; + } + if (config.behavior) { + functionDeclaration['behavior'] = config.behavior; + } + const geminiTool = { + functionDeclarations: [ + functionDeclaration, + ], + }; + return geminiTool; +} +/** + * Converts a list of MCP tools to a single Gemini tool with a list of function + * declarations. + */ +function mcpToolsToGeminiTool(mcpTools, config = {}) { + const functionDeclarations = []; + const toolNames = new Set(); + for (const mcpTool of mcpTools) { + const mcpToolName = mcpTool.name; + if (toolNames.has(mcpToolName)) { + throw new Error(`Duplicate function name ${mcpToolName} found in MCP tools. Please ensure function names are unique.`); + } + toolNames.add(mcpToolName); + const geminiTool = mcpToGeminiTool(mcpTool, config); + if (geminiTool.functionDeclarations) { + functionDeclarations.push(...geminiTool.functionDeclarations); + } + } + return { functionDeclarations: functionDeclarations }; +} +// Transforms a source input into a BatchJobSource object with validation. +function tBatchJobSource(client, src) { + let sourceObj; + if (typeof src === 'string') { + if (client.isVertexAI()) { + if (src.startsWith('gs://')) { + sourceObj = { format: 'jsonl', gcsUri: [src] }; + } + else if (src.startsWith('bq://')) { + sourceObj = { format: 'bigquery', bigqueryUri: src }; + } + else { + throw new Error(`Unsupported string source for Vertex AI: ${src}`); + } + } + else { + // MLDEV + if (src.startsWith('files/')) { + sourceObj = { fileName: src }; // Default to fileName for string input + } + else { + throw new Error(`Unsupported string source for Gemini API: ${src}`); + } + } + } + else if (Array.isArray(src)) { + if (client.isVertexAI()) { + throw new Error('InlinedRequest[] is not supported in Vertex AI.'); + } + sourceObj = { inlinedRequests: src }; + } + else { + // It's already a BatchJobSource object + sourceObj = src; + } + // Validation logic + const vertexSourcesCount = [sourceObj.gcsUri, sourceObj.bigqueryUri].filter(Boolean).length; + const mldevSourcesCount = [ + sourceObj.inlinedRequests, + sourceObj.fileName, + ].filter(Boolean).length; + if (client.isVertexAI()) { + if (mldevSourcesCount > 0 || vertexSourcesCount !== 1) { + throw new Error('Exactly one of `gcsUri` or `bigqueryUri` must be set for Vertex AI.'); + } + } + else { + // MLDEV + if (vertexSourcesCount > 0 || mldevSourcesCount !== 1) { + throw new Error('Exactly one of `inlinedRequests`, `fileName`, ' + + 'must be set for Gemini API.'); + } + } + return sourceObj; +} +function tBatchJobDestination(dest) { + if (typeof dest !== 'string') { + return dest; + } + const destString = dest; + if (destString.startsWith('gs://')) { + return { + format: 'jsonl', + gcsUri: destString, + }; + } + else if (destString.startsWith('bq://')) { + return { + format: 'bigquery', + bigqueryUri: destString, + }; + } + else { + throw new Error(`Unsupported destination: ${destString}`); + } +} +function tRecvBatchJobDestination(dest) { + // Ensure dest is a non-null object before proceeding. + if (typeof dest !== 'object' || dest === null) { + // If the input is not an object, it cannot be a valid BatchJobDestination + // based on the operations performed. Return it cast, or handle as an error. + // Casting an empty object might be a safe default. + return {}; + } + // Cast to Record<string, unknown> to allow string property access. + const obj = dest; + // Safely access nested properties. + const inlineResponsesVal = obj['inlinedResponses']; + if (typeof inlineResponsesVal !== 'object' || inlineResponsesVal === null) { + return dest; + } + const inlineResponsesObj = inlineResponsesVal; + const responsesArray = inlineResponsesObj['inlinedResponses']; + if (!Array.isArray(responsesArray) || responsesArray.length === 0) { + return dest; + } + // Check if any response has the 'embedding' property. + let hasEmbedding = false; + for (const responseItem of responsesArray) { + if (typeof responseItem !== 'object' || responseItem === null) { + continue; + } + const responseItemObj = responseItem; + const responseVal = responseItemObj['response']; + if (typeof responseVal !== 'object' || responseVal === null) { + continue; + } + const responseObj = responseVal; + // Check for the existence of the 'embedding' key. + if (responseObj['embedding'] !== undefined) { + hasEmbedding = true; + break; + } + } + // Perform the transformation if an embedding was found. + if (hasEmbedding) { + obj['inlinedEmbedContentResponses'] = obj['inlinedResponses']; + delete obj['inlinedResponses']; + } + // Cast the (potentially) modified object to the target type. + return dest; +} +function tBatchJobName(apiClient, name) { + const nameString = name; + if (!apiClient.isVertexAI()) { + const mldevPattern = /batches\/[^/]+$/; + if (mldevPattern.test(nameString)) { + return nameString.split('/').pop(); + } + else { + throw new Error(`Invalid batch job name: ${nameString}.`); + } + } + const vertexPattern = /^projects\/[^/]+\/locations\/[^/]+\/batchPredictionJobs\/[^/]+$/; + if (vertexPattern.test(nameString)) { + return nameString.split('/').pop(); + } + else if (/^\d+$/.test(nameString)) { + return nameString; + } + else { + throw new Error(`Invalid batch job name: ${nameString}.`); + } +} +function tJobState(state) { + const stateString = state; + if (stateString === 'BATCH_STATE_UNSPECIFIED') { + return 'JOB_STATE_UNSPECIFIED'; + } + else if (stateString === 'BATCH_STATE_PENDING') { + return 'JOB_STATE_PENDING'; + } + else if (stateString === 'BATCH_STATE_RUNNING') { + return 'JOB_STATE_RUNNING'; + } + else if (stateString === 'BATCH_STATE_SUCCEEDED') { + return 'JOB_STATE_SUCCEEDED'; + } + else if (stateString === 'BATCH_STATE_FAILED') { + return 'JOB_STATE_FAILED'; + } + else if (stateString === 'BATCH_STATE_CANCELLED') { + return 'JOB_STATE_CANCELLED'; + } + else if (stateString === 'BATCH_STATE_EXPIRED') { + return 'JOB_STATE_EXPIRED'; + } + else { + return stateString; + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function batchJobDestinationFromMldev(fromObject) { + const toObject = {}; + const fromFileName = getValueByPath(fromObject, ['responsesFile']); + if (fromFileName != null) { + setValueByPath(toObject, ['fileName'], fromFileName); + } + const fromInlinedResponses = getValueByPath(fromObject, [ + 'inlinedResponses', + 'inlinedResponses', + ]); + if (fromInlinedResponses != null) { + let transformedList = fromInlinedResponses; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return inlinedResponseFromMldev(item); + }); + } + setValueByPath(toObject, ['inlinedResponses'], transformedList); + } + const fromInlinedEmbedContentResponses = getValueByPath(fromObject, [ + 'inlinedEmbedContentResponses', + 'inlinedResponses', + ]); + if (fromInlinedEmbedContentResponses != null) { + let transformedList = fromInlinedEmbedContentResponses; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['inlinedEmbedContentResponses'], transformedList); + } + return toObject; +} +function batchJobDestinationFromVertex(fromObject) { + const toObject = {}; + const fromFormat = getValueByPath(fromObject, ['predictionsFormat']); + if (fromFormat != null) { + setValueByPath(toObject, ['format'], fromFormat); + } + const fromGcsUri = getValueByPath(fromObject, [ + 'gcsDestination', + 'outputUriPrefix', + ]); + if (fromGcsUri != null) { + setValueByPath(toObject, ['gcsUri'], fromGcsUri); + } + const fromBigqueryUri = getValueByPath(fromObject, [ + 'bigqueryDestination', + 'outputUri', + ]); + if (fromBigqueryUri != null) { + setValueByPath(toObject, ['bigqueryUri'], fromBigqueryUri); + } + return toObject; +} +function batchJobDestinationToVertex(fromObject) { + const toObject = {}; + const fromFormat = getValueByPath(fromObject, ['format']); + if (fromFormat != null) { + setValueByPath(toObject, ['predictionsFormat'], fromFormat); + } + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (fromGcsUri != null) { + setValueByPath(toObject, ['gcsDestination', 'outputUriPrefix'], fromGcsUri); + } + const fromBigqueryUri = getValueByPath(fromObject, ['bigqueryUri']); + if (fromBigqueryUri != null) { + setValueByPath(toObject, ['bigqueryDestination', 'outputUri'], fromBigqueryUri); + } + if (getValueByPath(fromObject, ['fileName']) !== undefined) { + throw new Error('fileName parameter is not supported in Vertex AI.'); + } + if (getValueByPath(fromObject, ['inlinedResponses']) !== undefined) { + throw new Error('inlinedResponses parameter is not supported in Vertex AI.'); + } + if (getValueByPath(fromObject, ['inlinedEmbedContentResponses']) !== + undefined) { + throw new Error('inlinedEmbedContentResponses parameter is not supported in Vertex AI.'); + } + return toObject; +} +function batchJobFromMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromDisplayName = getValueByPath(fromObject, [ + 'metadata', + 'displayName', + ]); + if (fromDisplayName != null) { + setValueByPath(toObject, ['displayName'], fromDisplayName); + } + const fromState = getValueByPath(fromObject, ['metadata', 'state']); + if (fromState != null) { + setValueByPath(toObject, ['state'], tJobState(fromState)); + } + const fromCreateTime = getValueByPath(fromObject, [ + 'metadata', + 'createTime', + ]); + if (fromCreateTime != null) { + setValueByPath(toObject, ['createTime'], fromCreateTime); + } + const fromEndTime = getValueByPath(fromObject, [ + 'metadata', + 'endTime', + ]); + if (fromEndTime != null) { + setValueByPath(toObject, ['endTime'], fromEndTime); + } + const fromUpdateTime = getValueByPath(fromObject, [ + 'metadata', + 'updateTime', + ]); + if (fromUpdateTime != null) { + setValueByPath(toObject, ['updateTime'], fromUpdateTime); + } + const fromModel = getValueByPath(fromObject, ['metadata', 'model']); + if (fromModel != null) { + setValueByPath(toObject, ['model'], fromModel); + } + const fromDest = getValueByPath(fromObject, ['metadata', 'output']); + if (fromDest != null) { + setValueByPath(toObject, ['dest'], batchJobDestinationFromMldev(tRecvBatchJobDestination(fromDest))); + } + return toObject; +} +function batchJobFromVertex(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (fromDisplayName != null) { + setValueByPath(toObject, ['displayName'], fromDisplayName); + } + const fromState = getValueByPath(fromObject, ['state']); + if (fromState != null) { + setValueByPath(toObject, ['state'], tJobState(fromState)); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromCreateTime = getValueByPath(fromObject, ['createTime']); + if (fromCreateTime != null) { + setValueByPath(toObject, ['createTime'], fromCreateTime); + } + const fromStartTime = getValueByPath(fromObject, ['startTime']); + if (fromStartTime != null) { + setValueByPath(toObject, ['startTime'], fromStartTime); + } + const fromEndTime = getValueByPath(fromObject, ['endTime']); + if (fromEndTime != null) { + setValueByPath(toObject, ['endTime'], fromEndTime); + } + const fromUpdateTime = getValueByPath(fromObject, ['updateTime']); + if (fromUpdateTime != null) { + setValueByPath(toObject, ['updateTime'], fromUpdateTime); + } + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['model'], fromModel); + } + const fromSrc = getValueByPath(fromObject, ['inputConfig']); + if (fromSrc != null) { + setValueByPath(toObject, ['src'], batchJobSourceFromVertex(fromSrc)); + } + const fromDest = getValueByPath(fromObject, ['outputConfig']); + if (fromDest != null) { + setValueByPath(toObject, ['dest'], batchJobDestinationFromVertex(tRecvBatchJobDestination(fromDest))); + } + const fromCompletionStats = getValueByPath(fromObject, [ + 'completionStats', + ]); + if (fromCompletionStats != null) { + setValueByPath(toObject, ['completionStats'], fromCompletionStats); + } + return toObject; +} +function batchJobSourceFromVertex(fromObject) { + const toObject = {}; + const fromFormat = getValueByPath(fromObject, ['instancesFormat']); + if (fromFormat != null) { + setValueByPath(toObject, ['format'], fromFormat); + } + const fromGcsUri = getValueByPath(fromObject, ['gcsSource', 'uris']); + if (fromGcsUri != null) { + setValueByPath(toObject, ['gcsUri'], fromGcsUri); + } + const fromBigqueryUri = getValueByPath(fromObject, [ + 'bigquerySource', + 'inputUri', + ]); + if (fromBigqueryUri != null) { + setValueByPath(toObject, ['bigqueryUri'], fromBigqueryUri); + } + return toObject; +} +function batchJobSourceToMldev(apiClient, fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['format']) !== undefined) { + throw new Error('format parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['gcsUri']) !== undefined) { + throw new Error('gcsUri parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['bigqueryUri']) !== undefined) { + throw new Error('bigqueryUri parameter is not supported in Gemini API.'); + } + const fromFileName = getValueByPath(fromObject, ['fileName']); + if (fromFileName != null) { + setValueByPath(toObject, ['fileName'], fromFileName); + } + const fromInlinedRequests = getValueByPath(fromObject, [ + 'inlinedRequests', + ]); + if (fromInlinedRequests != null) { + let transformedList = fromInlinedRequests; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return inlinedRequestToMldev(apiClient, item); + }); + } + setValueByPath(toObject, ['requests', 'requests'], transformedList); + } + return toObject; +} +function batchJobSourceToVertex(fromObject) { + const toObject = {}; + const fromFormat = getValueByPath(fromObject, ['format']); + if (fromFormat != null) { + setValueByPath(toObject, ['instancesFormat'], fromFormat); + } + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (fromGcsUri != null) { + setValueByPath(toObject, ['gcsSource', 'uris'], fromGcsUri); + } + const fromBigqueryUri = getValueByPath(fromObject, ['bigqueryUri']); + if (fromBigqueryUri != null) { + setValueByPath(toObject, ['bigquerySource', 'inputUri'], fromBigqueryUri); + } + if (getValueByPath(fromObject, ['fileName']) !== undefined) { + throw new Error('fileName parameter is not supported in Vertex AI.'); + } + if (getValueByPath(fromObject, ['inlinedRequests']) !== undefined) { + throw new Error('inlinedRequests parameter is not supported in Vertex AI.'); + } + return toObject; +} +function blobToMldev$4(fromObject) { + const toObject = {}; + const fromData = getValueByPath(fromObject, ['data']); + if (fromData != null) { + setValueByPath(toObject, ['data'], fromData); + } + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function cancelBatchJobParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tBatchJobName(apiClient, fromName)); + } + return toObject; +} +function cancelBatchJobParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tBatchJobName(apiClient, fromName)); + } + return toObject; +} +function candidateFromMldev$1(fromObject) { + const toObject = {}; + const fromContent = getValueByPath(fromObject, ['content']); + if (fromContent != null) { + setValueByPath(toObject, ['content'], fromContent); + } + const fromCitationMetadata = getValueByPath(fromObject, [ + 'citationMetadata', + ]); + if (fromCitationMetadata != null) { + setValueByPath(toObject, ['citationMetadata'], citationMetadataFromMldev$1(fromCitationMetadata)); + } + const fromTokenCount = getValueByPath(fromObject, ['tokenCount']); + if (fromTokenCount != null) { + setValueByPath(toObject, ['tokenCount'], fromTokenCount); + } + const fromFinishReason = getValueByPath(fromObject, ['finishReason']); + if (fromFinishReason != null) { + setValueByPath(toObject, ['finishReason'], fromFinishReason); + } + const fromAvgLogprobs = getValueByPath(fromObject, ['avgLogprobs']); + if (fromAvgLogprobs != null) { + setValueByPath(toObject, ['avgLogprobs'], fromAvgLogprobs); + } + const fromGroundingMetadata = getValueByPath(fromObject, [ + 'groundingMetadata', + ]); + if (fromGroundingMetadata != null) { + setValueByPath(toObject, ['groundingMetadata'], fromGroundingMetadata); + } + const fromIndex = getValueByPath(fromObject, ['index']); + if (fromIndex != null) { + setValueByPath(toObject, ['index'], fromIndex); + } + const fromLogprobsResult = getValueByPath(fromObject, [ + 'logprobsResult', + ]); + if (fromLogprobsResult != null) { + setValueByPath(toObject, ['logprobsResult'], fromLogprobsResult); + } + const fromSafetyRatings = getValueByPath(fromObject, [ + 'safetyRatings', + ]); + if (fromSafetyRatings != null) { + let transformedList = fromSafetyRatings; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['safetyRatings'], transformedList); + } + const fromUrlContextMetadata = getValueByPath(fromObject, [ + 'urlContextMetadata', + ]); + if (fromUrlContextMetadata != null) { + setValueByPath(toObject, ['urlContextMetadata'], fromUrlContextMetadata); + } + return toObject; +} +function citationMetadataFromMldev$1(fromObject) { + const toObject = {}; + const fromCitations = getValueByPath(fromObject, ['citationSources']); + if (fromCitations != null) { + let transformedList = fromCitations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['citations'], transformedList); + } + return toObject; +} +function contentToMldev$4(fromObject) { + const toObject = {}; + const fromParts = getValueByPath(fromObject, ['parts']); + if (fromParts != null) { + let transformedList = fromParts; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return partToMldev$4(item); + }); + } + setValueByPath(toObject, ['parts'], transformedList); + } + const fromRole = getValueByPath(fromObject, ['role']); + if (fromRole != null) { + setValueByPath(toObject, ['role'], fromRole); + } + return toObject; +} +function createBatchJobConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['batch', 'displayName'], fromDisplayName); + } + if (getValueByPath(fromObject, ['dest']) !== undefined) { + throw new Error('dest parameter is not supported in Gemini API.'); + } + return toObject; +} +function createBatchJobConfigToVertex(fromObject, parentObject) { + const toObject = {}; + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromDisplayName); + } + const fromDest = getValueByPath(fromObject, ['dest']); + if (parentObject !== undefined && fromDest != null) { + setValueByPath(parentObject, ['outputConfig'], batchJobDestinationToVertex(tBatchJobDestination(fromDest))); + } + return toObject; +} +function createBatchJobParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromSrc = getValueByPath(fromObject, ['src']); + if (fromSrc != null) { + setValueByPath(toObject, ['batch', 'inputConfig'], batchJobSourceToMldev(apiClient, tBatchJobSource(apiClient, fromSrc))); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createBatchJobConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function createBatchJobParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['model'], tModel(apiClient, fromModel)); + } + const fromSrc = getValueByPath(fromObject, ['src']); + if (fromSrc != null) { + setValueByPath(toObject, ['inputConfig'], batchJobSourceToVertex(tBatchJobSource(apiClient, fromSrc))); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createBatchJobConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function createEmbeddingsBatchJobConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['batch', 'displayName'], fromDisplayName); + } + return toObject; +} +function createEmbeddingsBatchJobParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromSrc = getValueByPath(fromObject, ['src']); + if (fromSrc != null) { + setValueByPath(toObject, ['batch', 'inputConfig'], embeddingsBatchJobSourceToMldev(apiClient, fromSrc)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createEmbeddingsBatchJobConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function deleteBatchJobParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tBatchJobName(apiClient, fromName)); + } + return toObject; +} +function deleteBatchJobParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tBatchJobName(apiClient, fromName)); + } + return toObject; +} +function deleteResourceJobFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + return toObject; +} +function deleteResourceJobFromVertex(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + return toObject; +} +function embedContentBatchToMldev(apiClient, fromObject) { + const toObject = {}; + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContentsForEmbed(apiClient, fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['requests[]', 'request', 'content'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['_self'], embedContentConfigToMldev$1(fromConfig, toObject)); + moveValueByPath(toObject, { 'requests[].*': 'requests[].request.*' }); + } + return toObject; +} +function embedContentConfigToMldev$1(fromObject, parentObject) { + const toObject = {}; + const fromTaskType = getValueByPath(fromObject, ['taskType']); + if (parentObject !== undefined && fromTaskType != null) { + setValueByPath(parentObject, ['requests[]', 'taskType'], fromTaskType); + } + const fromTitle = getValueByPath(fromObject, ['title']); + if (parentObject !== undefined && fromTitle != null) { + setValueByPath(parentObject, ['requests[]', 'title'], fromTitle); + } + const fromOutputDimensionality = getValueByPath(fromObject, [ + 'outputDimensionality', + ]); + if (parentObject !== undefined && fromOutputDimensionality != null) { + setValueByPath(parentObject, ['requests[]', 'outputDimensionality'], fromOutputDimensionality); + } + if (getValueByPath(fromObject, ['mimeType']) !== undefined) { + throw new Error('mimeType parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['autoTruncate']) !== undefined) { + throw new Error('autoTruncate parameter is not supported in Gemini API.'); + } + return toObject; +} +function embeddingsBatchJobSourceToMldev(apiClient, fromObject) { + const toObject = {}; + const fromFileName = getValueByPath(fromObject, ['fileName']); + if (fromFileName != null) { + setValueByPath(toObject, ['file_name'], fromFileName); + } + const fromInlinedRequests = getValueByPath(fromObject, [ + 'inlinedRequests', + ]); + if (fromInlinedRequests != null) { + setValueByPath(toObject, ['requests'], embedContentBatchToMldev(apiClient, fromInlinedRequests)); + } + return toObject; +} +function fileDataToMldev$4(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromFileUri = getValueByPath(fromObject, ['fileUri']); + if (fromFileUri != null) { + setValueByPath(toObject, ['fileUri'], fromFileUri); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function functionCallToMldev$4(fromObject) { + const toObject = {}; + const fromId = getValueByPath(fromObject, ['id']); + if (fromId != null) { + setValueByPath(toObject, ['id'], fromId); + } + const fromArgs = getValueByPath(fromObject, ['args']); + if (fromArgs != null) { + setValueByPath(toObject, ['args'], fromArgs); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + if (getValueByPath(fromObject, ['partialArgs']) !== undefined) { + throw new Error('partialArgs parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['willContinue']) !== undefined) { + throw new Error('willContinue parameter is not supported in Gemini API.'); + } + return toObject; +} +function functionCallingConfigToMldev$2(fromObject) { + const toObject = {}; + const fromAllowedFunctionNames = getValueByPath(fromObject, [ + 'allowedFunctionNames', + ]); + if (fromAllowedFunctionNames != null) { + setValueByPath(toObject, ['allowedFunctionNames'], fromAllowedFunctionNames); + } + const fromMode = getValueByPath(fromObject, ['mode']); + if (fromMode != null) { + setValueByPath(toObject, ['mode'], fromMode); + } + if (getValueByPath(fromObject, ['streamFunctionCallArguments']) !== + undefined) { + throw new Error('streamFunctionCallArguments parameter is not supported in Gemini API.'); + } + return toObject; +} +function generateContentConfigToMldev$1(apiClient, fromObject, parentObject) { + const toObject = {}; + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['systemInstruction'], contentToMldev$4(tContent(fromSystemInstruction))); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (fromTemperature != null) { + setValueByPath(toObject, ['temperature'], fromTemperature); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (fromTopP != null) { + setValueByPath(toObject, ['topP'], fromTopP); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (fromTopK != null) { + setValueByPath(toObject, ['topK'], fromTopK); + } + const fromCandidateCount = getValueByPath(fromObject, [ + 'candidateCount', + ]); + if (fromCandidateCount != null) { + setValueByPath(toObject, ['candidateCount'], fromCandidateCount); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (fromMaxOutputTokens != null) { + setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens); + } + const fromStopSequences = getValueByPath(fromObject, [ + 'stopSequences', + ]); + if (fromStopSequences != null) { + setValueByPath(toObject, ['stopSequences'], fromStopSequences); + } + const fromResponseLogprobs = getValueByPath(fromObject, [ + 'responseLogprobs', + ]); + if (fromResponseLogprobs != null) { + setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs); + } + const fromLogprobs = getValueByPath(fromObject, ['logprobs']); + if (fromLogprobs != null) { + setValueByPath(toObject, ['logprobs'], fromLogprobs); + } + const fromPresencePenalty = getValueByPath(fromObject, [ + 'presencePenalty', + ]); + if (fromPresencePenalty != null) { + setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty); + } + const fromFrequencyPenalty = getValueByPath(fromObject, [ + 'frequencyPenalty', + ]); + if (fromFrequencyPenalty != null) { + setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (fromSeed != null) { + setValueByPath(toObject, ['seed'], fromSeed); + } + const fromResponseMimeType = getValueByPath(fromObject, [ + 'responseMimeType', + ]); + if (fromResponseMimeType != null) { + setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType); + } + const fromResponseSchema = getValueByPath(fromObject, [ + 'responseSchema', + ]); + if (fromResponseSchema != null) { + setValueByPath(toObject, ['responseSchema'], tSchema(fromResponseSchema)); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + if (getValueByPath(fromObject, ['routingConfig']) !== undefined) { + throw new Error('routingConfig parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['modelSelectionConfig']) !== undefined) { + throw new Error('modelSelectionConfig parameter is not supported in Gemini API.'); + } + const fromSafetySettings = getValueByPath(fromObject, [ + 'safetySettings', + ]); + if (parentObject !== undefined && fromSafetySettings != null) { + let transformedList = fromSafetySettings; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return safetySettingToMldev$1(item); + }); + } + setValueByPath(parentObject, ['safetySettings'], transformedList); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = tTools(fromTools); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToMldev$4(tTool(item)); + }); + } + setValueByPath(parentObject, ['tools'], transformedList); + } + const fromToolConfig = getValueByPath(fromObject, ['toolConfig']); + if (parentObject !== undefined && fromToolConfig != null) { + setValueByPath(parentObject, ['toolConfig'], toolConfigToMldev$2(fromToolConfig)); + } + if (getValueByPath(fromObject, ['labels']) !== undefined) { + throw new Error('labels parameter is not supported in Gemini API.'); + } + const fromCachedContent = getValueByPath(fromObject, [ + 'cachedContent', + ]); + if (parentObject !== undefined && fromCachedContent != null) { + setValueByPath(parentObject, ['cachedContent'], tCachedContentName(apiClient, fromCachedContent)); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (fromResponseModalities != null) { + setValueByPath(toObject, ['responseModalities'], fromResponseModalities); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (fromSpeechConfig != null) { + setValueByPath(toObject, ['speechConfig'], tSpeechConfig(fromSpeechConfig)); + } + if (getValueByPath(fromObject, ['audioTimestamp']) !== undefined) { + throw new Error('audioTimestamp parameter is not supported in Gemini API.'); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (fromThinkingConfig != null) { + setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig); + } + const fromImageConfig = getValueByPath(fromObject, ['imageConfig']); + if (fromImageConfig != null) { + setValueByPath(toObject, ['imageConfig'], imageConfigToMldev$1(fromImageConfig)); + } + const fromEnableEnhancedCivicAnswers = getValueByPath(fromObject, [ + 'enableEnhancedCivicAnswers', + ]); + if (fromEnableEnhancedCivicAnswers != null) { + setValueByPath(toObject, ['enableEnhancedCivicAnswers'], fromEnableEnhancedCivicAnswers); + } + if (getValueByPath(fromObject, ['modelArmorConfig']) !== undefined) { + throw new Error('modelArmorConfig parameter is not supported in Gemini API.'); + } + return toObject; +} +function generateContentResponseFromMldev$1(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromCandidates = getValueByPath(fromObject, ['candidates']); + if (fromCandidates != null) { + let transformedList = fromCandidates; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return candidateFromMldev$1(item); + }); + } + setValueByPath(toObject, ['candidates'], transformedList); + } + const fromModelVersion = getValueByPath(fromObject, ['modelVersion']); + if (fromModelVersion != null) { + setValueByPath(toObject, ['modelVersion'], fromModelVersion); + } + const fromPromptFeedback = getValueByPath(fromObject, [ + 'promptFeedback', + ]); + if (fromPromptFeedback != null) { + setValueByPath(toObject, ['promptFeedback'], fromPromptFeedback); + } + const fromResponseId = getValueByPath(fromObject, ['responseId']); + if (fromResponseId != null) { + setValueByPath(toObject, ['responseId'], fromResponseId); + } + const fromUsageMetadata = getValueByPath(fromObject, [ + 'usageMetadata', + ]); + if (fromUsageMetadata != null) { + setValueByPath(toObject, ['usageMetadata'], fromUsageMetadata); + } + return toObject; +} +function getBatchJobParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tBatchJobName(apiClient, fromName)); + } + return toObject; +} +function getBatchJobParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tBatchJobName(apiClient, fromName)); + } + return toObject; +} +function googleMapsToMldev$4(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['authConfig']) !== undefined) { + throw new Error('authConfig parameter is not supported in Gemini API.'); + } + const fromEnableWidget = getValueByPath(fromObject, ['enableWidget']); + if (fromEnableWidget != null) { + setValueByPath(toObject, ['enableWidget'], fromEnableWidget); + } + return toObject; +} +function googleSearchToMldev$4(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['excludeDomains']) !== undefined) { + throw new Error('excludeDomains parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['blockingConfidence']) !== undefined) { + throw new Error('blockingConfidence parameter is not supported in Gemini API.'); + } + const fromTimeRangeFilter = getValueByPath(fromObject, [ + 'timeRangeFilter', + ]); + if (fromTimeRangeFilter != null) { + setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter); + } + return toObject; +} +function imageConfigToMldev$1(fromObject) { + const toObject = {}; + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (fromAspectRatio != null) { + setValueByPath(toObject, ['aspectRatio'], fromAspectRatio); + } + const fromImageSize = getValueByPath(fromObject, ['imageSize']); + if (fromImageSize != null) { + setValueByPath(toObject, ['imageSize'], fromImageSize); + } + if (getValueByPath(fromObject, ['personGeneration']) !== undefined) { + throw new Error('personGeneration parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['outputMimeType']) !== undefined) { + throw new Error('outputMimeType parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['outputCompressionQuality']) !== + undefined) { + throw new Error('outputCompressionQuality parameter is not supported in Gemini API.'); + } + return toObject; +} +function inlinedRequestToMldev(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['request', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return contentToMldev$4(item); + }); + } + setValueByPath(toObject, ['request', 'contents'], transformedList); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['request', 'generationConfig'], generateContentConfigToMldev$1(apiClient, fromConfig, getValueByPath(toObject, ['request'], {}))); + } + return toObject; +} +function inlinedResponseFromMldev(fromObject) { + const toObject = {}; + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], generateContentResponseFromMldev$1(fromResponse)); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + return toObject; +} +function listBatchJobsConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + if (getValueByPath(fromObject, ['filter']) !== undefined) { + throw new Error('filter parameter is not supported in Gemini API.'); + } + return toObject; +} +function listBatchJobsConfigToVertex(fromObject, parentObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + const fromFilter = getValueByPath(fromObject, ['filter']); + if (parentObject !== undefined && fromFilter != null) { + setValueByPath(parentObject, ['_query', 'filter'], fromFilter); + } + return toObject; +} +function listBatchJobsParametersToMldev(fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listBatchJobsConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function listBatchJobsParametersToVertex(fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listBatchJobsConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function listBatchJobsResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromBatchJobs = getValueByPath(fromObject, ['operations']); + if (fromBatchJobs != null) { + let transformedList = fromBatchJobs; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return batchJobFromMldev(item); + }); + } + setValueByPath(toObject, ['batchJobs'], transformedList); + } + return toObject; +} +function listBatchJobsResponseFromVertex(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromBatchJobs = getValueByPath(fromObject, [ + 'batchPredictionJobs', + ]); + if (fromBatchJobs != null) { + let transformedList = fromBatchJobs; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return batchJobFromVertex(item); + }); + } + setValueByPath(toObject, ['batchJobs'], transformedList); + } + return toObject; +} +function partToMldev$4(fromObject) { + const toObject = {}; + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromCodeExecutionResult = getValueByPath(fromObject, [ + 'codeExecutionResult', + ]); + if (fromCodeExecutionResult != null) { + setValueByPath(toObject, ['codeExecutionResult'], fromCodeExecutionResult); + } + const fromExecutableCode = getValueByPath(fromObject, [ + 'executableCode', + ]); + if (fromExecutableCode != null) { + setValueByPath(toObject, ['executableCode'], fromExecutableCode); + } + const fromFileData = getValueByPath(fromObject, ['fileData']); + if (fromFileData != null) { + setValueByPath(toObject, ['fileData'], fileDataToMldev$4(fromFileData)); + } + const fromFunctionCall = getValueByPath(fromObject, ['functionCall']); + if (fromFunctionCall != null) { + setValueByPath(toObject, ['functionCall'], functionCallToMldev$4(fromFunctionCall)); + } + const fromFunctionResponse = getValueByPath(fromObject, [ + 'functionResponse', + ]); + if (fromFunctionResponse != null) { + setValueByPath(toObject, ['functionResponse'], fromFunctionResponse); + } + const fromInlineData = getValueByPath(fromObject, ['inlineData']); + if (fromInlineData != null) { + setValueByPath(toObject, ['inlineData'], blobToMldev$4(fromInlineData)); + } + const fromText = getValueByPath(fromObject, ['text']); + if (fromText != null) { + setValueByPath(toObject, ['text'], fromText); + } + const fromThought = getValueByPath(fromObject, ['thought']); + if (fromThought != null) { + setValueByPath(toObject, ['thought'], fromThought); + } + const fromThoughtSignature = getValueByPath(fromObject, [ + 'thoughtSignature', + ]); + if (fromThoughtSignature != null) { + setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature); + } + const fromVideoMetadata = getValueByPath(fromObject, [ + 'videoMetadata', + ]); + if (fromVideoMetadata != null) { + setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata); + } + return toObject; +} +function safetySettingToMldev$1(fromObject) { + const toObject = {}; + const fromCategory = getValueByPath(fromObject, ['category']); + if (fromCategory != null) { + setValueByPath(toObject, ['category'], fromCategory); + } + if (getValueByPath(fromObject, ['method']) !== undefined) { + throw new Error('method parameter is not supported in Gemini API.'); + } + const fromThreshold = getValueByPath(fromObject, ['threshold']); + if (fromThreshold != null) { + setValueByPath(toObject, ['threshold'], fromThreshold); + } + return toObject; +} +function toolConfigToMldev$2(fromObject) { + const toObject = {}; + const fromRetrievalConfig = getValueByPath(fromObject, [ + 'retrievalConfig', + ]); + if (fromRetrievalConfig != null) { + setValueByPath(toObject, ['retrievalConfig'], fromRetrievalConfig); + } + const fromFunctionCallingConfig = getValueByPath(fromObject, [ + 'functionCallingConfig', + ]); + if (fromFunctionCallingConfig != null) { + setValueByPath(toObject, ['functionCallingConfig'], functionCallingConfigToMldev$2(fromFunctionCallingConfig)); + } + return toObject; +} +function toolToMldev$4(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['retrieval']) !== undefined) { + throw new Error('retrieval parameter is not supported in Gemini API.'); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + const fromFileSearch = getValueByPath(fromObject, ['fileSearch']); + if (fromFileSearch != null) { + setValueByPath(toObject, ['fileSearch'], fromFileSearch); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + if (getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined) { + throw new Error('enterpriseWebSearch parameter is not supported in Gemini API.'); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], googleMapsToMldev$4(fromGoogleMaps)); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], googleSearchToMldev$4(fromGoogleSearch)); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +var PagedItem; +(function (PagedItem) { + PagedItem["PAGED_ITEM_BATCH_JOBS"] = "batchJobs"; + PagedItem["PAGED_ITEM_MODELS"] = "models"; + PagedItem["PAGED_ITEM_TUNING_JOBS"] = "tuningJobs"; + PagedItem["PAGED_ITEM_FILES"] = "files"; + PagedItem["PAGED_ITEM_CACHED_CONTENTS"] = "cachedContents"; + PagedItem["PAGED_ITEM_FILE_SEARCH_STORES"] = "fileSearchStores"; + PagedItem["PAGED_ITEM_DOCUMENTS"] = "documents"; +})(PagedItem || (PagedItem = {})); +/** + * Pager class for iterating through paginated results. + */ +class Pager { + constructor(name, request, response, params) { + this.pageInternal = []; + this.paramsInternal = {}; + this.requestInternal = request; + this.init(name, response, params); + } + init(name, response, params) { + var _a, _b; + this.nameInternal = name; + this.pageInternal = response[this.nameInternal] || []; + this.sdkHttpResponseInternal = response === null || response === void 0 ? void 0 : response.sdkHttpResponse; + this.idxInternal = 0; + let requestParams = { config: {} }; + if (!params || Object.keys(params).length === 0) { + requestParams = { config: {} }; + } + else if (typeof params === 'object') { + requestParams = Object.assign({}, params); + } + else { + requestParams = params; + } + if (requestParams['config']) { + requestParams['config']['pageToken'] = response['nextPageToken']; + } + this.paramsInternal = requestParams; + this.pageInternalSize = + (_b = (_a = requestParams['config']) === null || _a === void 0 ? void 0 : _a['pageSize']) !== null && _b !== void 0 ? _b : this.pageInternal.length; + } + initNextPage(response) { + this.init(this.nameInternal, response, this.paramsInternal); + } + /** + * Returns the current page, which is a list of items. + * + * @remarks + * The first page is retrieved when the pager is created. The returned list of + * items could be a subset of the entire list. + */ + get page() { + return this.pageInternal; + } + /** + * Returns the type of paged item (for example, ``batch_jobs``). + */ + get name() { + return this.nameInternal; + } + /** + * Returns the length of the page fetched each time by this pager. + * + * @remarks + * The number of items in the page is less than or equal to the page length. + */ + get pageSize() { + return this.pageInternalSize; + } + /** + * Returns the headers of the API response. + */ + get sdkHttpResponse() { + return this.sdkHttpResponseInternal; + } + /** + * Returns the parameters when making the API request for the next page. + * + * @remarks + * Parameters contain a set of optional configs that can be + * used to customize the API request. For example, the `pageToken` parameter + * contains the token to request the next page. + */ + get params() { + return this.paramsInternal; + } + /** + * Returns the total number of items in the current page. + */ + get pageLength() { + return this.pageInternal.length; + } + /** + * Returns the item at the given index. + */ + getItem(index) { + return this.pageInternal[index]; + } + /** + * Returns an async iterator that support iterating through all items + * retrieved from the API. + * + * @remarks + * The iterator will automatically fetch the next page if there are more items + * to fetch from the API. + * + * @example + * + * ```ts + * const pager = await ai.files.list({config: {pageSize: 10}}); + * for await (const file of pager) { + * console.log(file.name); + * } + * ``` + */ + [Symbol.asyncIterator]() { + return { + next: async () => { + if (this.idxInternal >= this.pageLength) { + if (this.hasNextPage()) { + await this.nextPage(); + } + else { + return { value: undefined, done: true }; + } + } + const item = this.getItem(this.idxInternal); + this.idxInternal += 1; + return { value: item, done: false }; + }, + return: async () => { + return { value: undefined, done: true }; + }, + }; + } + /** + * Fetches the next page of items. This makes a new API request. + * + * @throws {Error} If there are no more pages to fetch. + * + * @example + * + * ```ts + * const pager = await ai.files.list({config: {pageSize: 10}}); + * let page = pager.page; + * while (true) { + * for (const file of page) { + * console.log(file.name); + * } + * if (!pager.hasNextPage()) { + * break; + * } + * page = await pager.nextPage(); + * } + * ``` + */ + async nextPage() { + if (!this.hasNextPage()) { + throw new Error('No more pages to fetch.'); + } + const response = await this.requestInternal(this.params); + this.initNextPage(response); + return this.page; + } + /** + * Returns true if there are more pages to fetch from the API. + */ + hasNextPage() { + var _a; + if (((_a = this.params['config']) === null || _a === void 0 ? void 0 : _a['pageToken']) !== undefined) { + return true; + } + return false; + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Batches extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + /** + * Lists batch jobs. + * + * @param params - The parameters for the list request. + * @return - A pager of batch jobs. + * + * @example + * ```ts + * const batchJobs = await ai.batches.list({config: {'pageSize': 2}}); + * for await (const batchJob of batchJobs) { + * console.log(batchJob); + * } + * ``` + */ + this.list = async (params = {}) => { + return new Pager(PagedItem.PAGED_ITEM_BATCH_JOBS, (x) => this.listInternal(x), await this.listInternal(params), params); + }; + /** + * Create batch job. + * + * @param params - The parameters for create batch job request. + * @return The created batch job. + * + * @example + * ```ts + * const response = await ai.batches.create({ + * model: 'gemini-2.0-flash', + * src: {gcsUri: 'gs://bucket/path/to/file.jsonl', format: 'jsonl'}, + * config: { + * dest: {gcsUri: 'gs://bucket/path/output/directory', format: 'jsonl'}, + * } + * }); + * console.log(response); + * ``` + */ + this.create = async (params) => { + if (this.apiClient.isVertexAI()) { + // Format destination if not provided + // Cast params.src as Vertex AI path does not handle InlinedRequest[] + params.config = this.formatDestination(params.src, params.config); + } + return this.createInternal(params); + }; + /** + * **Experimental** Creates an embedding batch job. + * + * @param params - The parameters for create embedding batch job request. + * @return The created batch job. + * + * @example + * ```ts + * const response = await ai.batches.createEmbeddings({ + * model: 'text-embedding-004', + * src: {fileName: 'files/my_embedding_input'}, + * }); + * console.log(response); + * ``` + */ + this.createEmbeddings = async (params) => { + console.warn('batches.createEmbeddings() is experimental and may change without notice.'); + if (this.apiClient.isVertexAI()) { + throw new Error('Vertex AI does not support batches.createEmbeddings.'); + } + return this.createEmbeddingsInternal(params); + }; + } + // Helper function to handle inlined generate content requests + createInlinedGenerateContentRequest(params) { + const body = createBatchJobParametersToMldev(this.apiClient, // Use instance apiClient + params); + const urlParams = body['_url']; + const path = formatMap('{model}:batchGenerateContent', urlParams); + const batch = body['batch']; + const inputConfig = batch['inputConfig']; + const requestsWrapper = inputConfig['requests']; + const requests = requestsWrapper['requests']; + const newRequests = []; + for (const request of requests) { + const requestDict = Object.assign({}, request); // Clone + if (requestDict['systemInstruction']) { + const systemInstructionValue = requestDict['systemInstruction']; + delete requestDict['systemInstruction']; + const requestContent = requestDict['request']; + requestContent['systemInstruction'] = systemInstructionValue; + requestDict['request'] = requestContent; + } + newRequests.push(requestDict); + } + requestsWrapper['requests'] = newRequests; + delete body['config']; + delete body['_url']; + delete body['_query']; + return { path, body }; + } + // Helper function to get the first GCS URI + getGcsUri(src) { + if (typeof src === 'string') { + return src.startsWith('gs://') ? src : undefined; + } + if (!Array.isArray(src) && src.gcsUri && src.gcsUri.length > 0) { + return src.gcsUri[0]; + } + return undefined; + } + // Helper function to get the BigQuery URI + getBigqueryUri(src) { + if (typeof src === 'string') { + return src.startsWith('bq://') ? src : undefined; + } + if (!Array.isArray(src)) { + return src.bigqueryUri; + } + return undefined; + } + // Function to format the destination configuration for Vertex AI + formatDestination(src, config) { + const newConfig = config ? Object.assign({}, config) : {}; + const timestampStr = Date.now().toString(); + if (!newConfig.displayName) { + newConfig.displayName = `genaiBatchJob_${timestampStr}`; + } + if (newConfig.dest === undefined) { + const gcsUri = this.getGcsUri(src); + const bigqueryUri = this.getBigqueryUri(src); + if (gcsUri) { + if (gcsUri.endsWith('.jsonl')) { + // For .jsonl files, remove suffix and add /dest + newConfig.dest = `${gcsUri.slice(0, -6)}/dest`; + } + else { + // Fallback for other GCS URIs + newConfig.dest = `${gcsUri}_dest_${timestampStr}`; + } + } + else if (bigqueryUri) { + newConfig.dest = `${bigqueryUri}_dest_${timestampStr}`; + } + else { + throw new Error('Unsupported source for Vertex AI: No GCS or BigQuery URI found.'); + } + } + return newConfig; + } + /** + * Internal method to create batch job. + * + * @param params - The parameters for create batch job request. + * @return The created batch job. + * + */ + async createInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = createBatchJobParametersToVertex(this.apiClient, params); + path = formatMap('batchPredictionJobs', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = batchJobFromVertex(apiResponse); + return resp; + }); + } + else { + const body = createBatchJobParametersToMldev(this.apiClient, params); + path = formatMap('{model}:batchGenerateContent', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = batchJobFromMldev(apiResponse); + return resp; + }); + } + } + /** + * Internal method to create batch job. + * + * @param params - The parameters for create batch job request. + * @return The created batch job. + * + */ + async createEmbeddingsInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = createEmbeddingsBatchJobParametersToMldev(this.apiClient, params); + path = formatMap('{model}:asyncBatchEmbedContent', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = batchJobFromMldev(apiResponse); + return resp; + }); + } + } + /** + * Gets batch job configurations. + * + * @param params - The parameters for the get request. + * @return The batch job. + * + * @example + * ```ts + * await ai.batches.get({name: '...'}); // The server-generated resource name. + * ``` + */ + async get(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = getBatchJobParametersToVertex(this.apiClient, params); + path = formatMap('batchPredictionJobs/{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = batchJobFromVertex(apiResponse); + return resp; + }); + } + else { + const body = getBatchJobParametersToMldev(this.apiClient, params); + path = formatMap('batches/{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = batchJobFromMldev(apiResponse); + return resp; + }); + } + } + /** + * Cancels a batch job. + * + * @param params - The parameters for the cancel request. + * @return The empty response returned by the API. + * + * @example + * ```ts + * await ai.batches.cancel({name: '...'}); // The server-generated resource name. + * ``` + */ + async cancel(params) { + var _a, _b, _c, _d; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = cancelBatchJobParametersToVertex(this.apiClient, params); + path = formatMap('batchPredictionJobs/{name}:cancel', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + await this.apiClient.request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }); + } + else { + const body = cancelBatchJobParametersToMldev(this.apiClient, params); + path = formatMap('batches/{name}:cancel', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + await this.apiClient.request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }); + } + } + async listInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = listBatchJobsParametersToVertex(params); + path = formatMap('batchPredictionJobs', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listBatchJobsResponseFromVertex(apiResponse); + const typedResp = new ListBatchJobsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = listBatchJobsParametersToMldev(params); + path = formatMap('batches', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listBatchJobsResponseFromMldev(apiResponse); + const typedResp = new ListBatchJobsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Deletes a batch job. + * + * @param params - The parameters for the delete request. + * @return The empty response returned by the API. + * + * @example + * ```ts + * await ai.batches.delete({name: '...'}); // The server-generated resource name. + * ``` + */ + async delete(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = deleteBatchJobParametersToVertex(this.apiClient, params); + path = formatMap('batchPredictionJobs/{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = deleteResourceJobFromVertex(apiResponse); + return resp; + }); + } + else { + const body = deleteBatchJobParametersToMldev(this.apiClient, params); + path = formatMap('batches/{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = deleteResourceJobFromMldev(apiResponse); + return resp; + }); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function blobToMldev$3(fromObject) { + const toObject = {}; + const fromData = getValueByPath(fromObject, ['data']); + if (fromData != null) { + setValueByPath(toObject, ['data'], fromData); + } + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function contentToMldev$3(fromObject) { + const toObject = {}; + const fromParts = getValueByPath(fromObject, ['parts']); + if (fromParts != null) { + let transformedList = fromParts; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return partToMldev$3(item); + }); + } + setValueByPath(toObject, ['parts'], transformedList); + } + const fromRole = getValueByPath(fromObject, ['role']); + if (fromRole != null) { + setValueByPath(toObject, ['role'], fromRole); + } + return toObject; +} +function createCachedContentConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromTtl = getValueByPath(fromObject, ['ttl']); + if (parentObject !== undefined && fromTtl != null) { + setValueByPath(parentObject, ['ttl'], fromTtl); + } + const fromExpireTime = getValueByPath(fromObject, ['expireTime']); + if (parentObject !== undefined && fromExpireTime != null) { + setValueByPath(parentObject, ['expireTime'], fromExpireTime); + } + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromDisplayName); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (parentObject !== undefined && fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return contentToMldev$3(item); + }); + } + setValueByPath(parentObject, ['contents'], transformedList); + } + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['systemInstruction'], contentToMldev$3(tContent(fromSystemInstruction))); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = fromTools; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToMldev$3(item); + }); + } + setValueByPath(parentObject, ['tools'], transformedList); + } + const fromToolConfig = getValueByPath(fromObject, ['toolConfig']); + if (parentObject !== undefined && fromToolConfig != null) { + setValueByPath(parentObject, ['toolConfig'], toolConfigToMldev$1(fromToolConfig)); + } + if (getValueByPath(fromObject, ['kmsKeyName']) !== undefined) { + throw new Error('kmsKeyName parameter is not supported in Gemini API.'); + } + return toObject; +} +function createCachedContentConfigToVertex(fromObject, parentObject) { + const toObject = {}; + const fromTtl = getValueByPath(fromObject, ['ttl']); + if (parentObject !== undefined && fromTtl != null) { + setValueByPath(parentObject, ['ttl'], fromTtl); + } + const fromExpireTime = getValueByPath(fromObject, ['expireTime']); + if (parentObject !== undefined && fromExpireTime != null) { + setValueByPath(parentObject, ['expireTime'], fromExpireTime); + } + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromDisplayName); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (parentObject !== undefined && fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(parentObject, ['contents'], transformedList); + } + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['systemInstruction'], tContent(fromSystemInstruction)); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = fromTools; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToVertex$2(item); + }); + } + setValueByPath(parentObject, ['tools'], transformedList); + } + const fromToolConfig = getValueByPath(fromObject, ['toolConfig']); + if (parentObject !== undefined && fromToolConfig != null) { + setValueByPath(parentObject, ['toolConfig'], fromToolConfig); + } + const fromKmsKeyName = getValueByPath(fromObject, ['kmsKeyName']); + if (parentObject !== undefined && fromKmsKeyName != null) { + setValueByPath(parentObject, ['encryption_spec', 'kmsKeyName'], fromKmsKeyName); + } + return toObject; +} +function createCachedContentParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['model'], tCachesModel(apiClient, fromModel)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createCachedContentConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function createCachedContentParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['model'], tCachesModel(apiClient, fromModel)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createCachedContentConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function deleteCachedContentParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tCachedContentName(apiClient, fromName)); + } + return toObject; +} +function deleteCachedContentParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tCachedContentName(apiClient, fromName)); + } + return toObject; +} +function deleteCachedContentResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function deleteCachedContentResponseFromVertex(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function fileDataToMldev$3(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromFileUri = getValueByPath(fromObject, ['fileUri']); + if (fromFileUri != null) { + setValueByPath(toObject, ['fileUri'], fromFileUri); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function functionCallToMldev$3(fromObject) { + const toObject = {}; + const fromId = getValueByPath(fromObject, ['id']); + if (fromId != null) { + setValueByPath(toObject, ['id'], fromId); + } + const fromArgs = getValueByPath(fromObject, ['args']); + if (fromArgs != null) { + setValueByPath(toObject, ['args'], fromArgs); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + if (getValueByPath(fromObject, ['partialArgs']) !== undefined) { + throw new Error('partialArgs parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['willContinue']) !== undefined) { + throw new Error('willContinue parameter is not supported in Gemini API.'); + } + return toObject; +} +function functionCallingConfigToMldev$1(fromObject) { + const toObject = {}; + const fromAllowedFunctionNames = getValueByPath(fromObject, [ + 'allowedFunctionNames', + ]); + if (fromAllowedFunctionNames != null) { + setValueByPath(toObject, ['allowedFunctionNames'], fromAllowedFunctionNames); + } + const fromMode = getValueByPath(fromObject, ['mode']); + if (fromMode != null) { + setValueByPath(toObject, ['mode'], fromMode); + } + if (getValueByPath(fromObject, ['streamFunctionCallArguments']) !== + undefined) { + throw new Error('streamFunctionCallArguments parameter is not supported in Gemini API.'); + } + return toObject; +} +function functionDeclarationToVertex$2(fromObject) { + const toObject = {}; + const fromDescription = getValueByPath(fromObject, ['description']); + if (fromDescription != null) { + setValueByPath(toObject, ['description'], fromDescription); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromParameters = getValueByPath(fromObject, ['parameters']); + if (fromParameters != null) { + setValueByPath(toObject, ['parameters'], fromParameters); + } + const fromParametersJsonSchema = getValueByPath(fromObject, [ + 'parametersJsonSchema', + ]); + if (fromParametersJsonSchema != null) { + setValueByPath(toObject, ['parametersJsonSchema'], fromParametersJsonSchema); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], fromResponse); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + if (getValueByPath(fromObject, ['behavior']) !== undefined) { + throw new Error('behavior parameter is not supported in Vertex AI.'); + } + return toObject; +} +function getCachedContentParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tCachedContentName(apiClient, fromName)); + } + return toObject; +} +function getCachedContentParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tCachedContentName(apiClient, fromName)); + } + return toObject; +} +function googleMapsToMldev$3(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['authConfig']) !== undefined) { + throw new Error('authConfig parameter is not supported in Gemini API.'); + } + const fromEnableWidget = getValueByPath(fromObject, ['enableWidget']); + if (fromEnableWidget != null) { + setValueByPath(toObject, ['enableWidget'], fromEnableWidget); + } + return toObject; +} +function googleSearchToMldev$3(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['excludeDomains']) !== undefined) { + throw new Error('excludeDomains parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['blockingConfidence']) !== undefined) { + throw new Error('blockingConfidence parameter is not supported in Gemini API.'); + } + const fromTimeRangeFilter = getValueByPath(fromObject, [ + 'timeRangeFilter', + ]); + if (fromTimeRangeFilter != null) { + setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter); + } + return toObject; +} +function listCachedContentsConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + return toObject; +} +function listCachedContentsConfigToVertex(fromObject, parentObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + return toObject; +} +function listCachedContentsParametersToMldev(fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listCachedContentsConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function listCachedContentsParametersToVertex(fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listCachedContentsConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function listCachedContentsResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromCachedContents = getValueByPath(fromObject, [ + 'cachedContents', + ]); + if (fromCachedContents != null) { + let transformedList = fromCachedContents; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['cachedContents'], transformedList); + } + return toObject; +} +function listCachedContentsResponseFromVertex(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromCachedContents = getValueByPath(fromObject, [ + 'cachedContents', + ]); + if (fromCachedContents != null) { + let transformedList = fromCachedContents; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['cachedContents'], transformedList); + } + return toObject; +} +function partToMldev$3(fromObject) { + const toObject = {}; + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromCodeExecutionResult = getValueByPath(fromObject, [ + 'codeExecutionResult', + ]); + if (fromCodeExecutionResult != null) { + setValueByPath(toObject, ['codeExecutionResult'], fromCodeExecutionResult); + } + const fromExecutableCode = getValueByPath(fromObject, [ + 'executableCode', + ]); + if (fromExecutableCode != null) { + setValueByPath(toObject, ['executableCode'], fromExecutableCode); + } + const fromFileData = getValueByPath(fromObject, ['fileData']); + if (fromFileData != null) { + setValueByPath(toObject, ['fileData'], fileDataToMldev$3(fromFileData)); + } + const fromFunctionCall = getValueByPath(fromObject, ['functionCall']); + if (fromFunctionCall != null) { + setValueByPath(toObject, ['functionCall'], functionCallToMldev$3(fromFunctionCall)); + } + const fromFunctionResponse = getValueByPath(fromObject, [ + 'functionResponse', + ]); + if (fromFunctionResponse != null) { + setValueByPath(toObject, ['functionResponse'], fromFunctionResponse); + } + const fromInlineData = getValueByPath(fromObject, ['inlineData']); + if (fromInlineData != null) { + setValueByPath(toObject, ['inlineData'], blobToMldev$3(fromInlineData)); + } + const fromText = getValueByPath(fromObject, ['text']); + if (fromText != null) { + setValueByPath(toObject, ['text'], fromText); + } + const fromThought = getValueByPath(fromObject, ['thought']); + if (fromThought != null) { + setValueByPath(toObject, ['thought'], fromThought); + } + const fromThoughtSignature = getValueByPath(fromObject, [ + 'thoughtSignature', + ]); + if (fromThoughtSignature != null) { + setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature); + } + const fromVideoMetadata = getValueByPath(fromObject, [ + 'videoMetadata', + ]); + if (fromVideoMetadata != null) { + setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata); + } + return toObject; +} +function toolConfigToMldev$1(fromObject) { + const toObject = {}; + const fromRetrievalConfig = getValueByPath(fromObject, [ + 'retrievalConfig', + ]); + if (fromRetrievalConfig != null) { + setValueByPath(toObject, ['retrievalConfig'], fromRetrievalConfig); + } + const fromFunctionCallingConfig = getValueByPath(fromObject, [ + 'functionCallingConfig', + ]); + if (fromFunctionCallingConfig != null) { + setValueByPath(toObject, ['functionCallingConfig'], functionCallingConfigToMldev$1(fromFunctionCallingConfig)); + } + return toObject; +} +function toolToMldev$3(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['retrieval']) !== undefined) { + throw new Error('retrieval parameter is not supported in Gemini API.'); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + const fromFileSearch = getValueByPath(fromObject, ['fileSearch']); + if (fromFileSearch != null) { + setValueByPath(toObject, ['fileSearch'], fromFileSearch); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + if (getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined) { + throw new Error('enterpriseWebSearch parameter is not supported in Gemini API.'); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], googleMapsToMldev$3(fromGoogleMaps)); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], googleSearchToMldev$3(fromGoogleSearch)); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} +function toolToVertex$2(fromObject) { + const toObject = {}; + const fromRetrieval = getValueByPath(fromObject, ['retrieval']); + if (fromRetrieval != null) { + setValueByPath(toObject, ['retrieval'], fromRetrieval); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + if (getValueByPath(fromObject, ['fileSearch']) !== undefined) { + throw new Error('fileSearch parameter is not supported in Vertex AI.'); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + const fromEnterpriseWebSearch = getValueByPath(fromObject, [ + 'enterpriseWebSearch', + ]); + if (fromEnterpriseWebSearch != null) { + setValueByPath(toObject, ['enterpriseWebSearch'], fromEnterpriseWebSearch); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return functionDeclarationToVertex$2(item); + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], fromGoogleMaps); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], fromGoogleSearch); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} +function updateCachedContentConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromTtl = getValueByPath(fromObject, ['ttl']); + if (parentObject !== undefined && fromTtl != null) { + setValueByPath(parentObject, ['ttl'], fromTtl); + } + const fromExpireTime = getValueByPath(fromObject, ['expireTime']); + if (parentObject !== undefined && fromExpireTime != null) { + setValueByPath(parentObject, ['expireTime'], fromExpireTime); + } + return toObject; +} +function updateCachedContentConfigToVertex(fromObject, parentObject) { + const toObject = {}; + const fromTtl = getValueByPath(fromObject, ['ttl']); + if (parentObject !== undefined && fromTtl != null) { + setValueByPath(parentObject, ['ttl'], fromTtl); + } + const fromExpireTime = getValueByPath(fromObject, ['expireTime']); + if (parentObject !== undefined && fromExpireTime != null) { + setValueByPath(parentObject, ['expireTime'], fromExpireTime); + } + return toObject; +} +function updateCachedContentParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tCachedContentName(apiClient, fromName)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + updateCachedContentConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function updateCachedContentParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tCachedContentName(apiClient, fromName)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + updateCachedContentConfigToVertex(fromConfig, toObject); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Caches extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + /** + * Lists cached contents. + * + * @param params - The parameters for the list request. + * @return - A pager of cached contents. + * + * @example + * ```ts + * const cachedContents = await ai.caches.list({config: {'pageSize': 2}}); + * for await (const cachedContent of cachedContents) { + * console.log(cachedContent); + * } + * ``` + */ + this.list = async (params = {}) => { + return new Pager(PagedItem.PAGED_ITEM_CACHED_CONTENTS, (x) => this.listInternal(x), await this.listInternal(params), params); + }; + } + /** + * Creates a cached contents resource. + * + * @remarks + * Context caching is only supported for specific models. See [Gemini + * Developer API reference](https://ai.google.dev/gemini-api/docs/caching?lang=node/context-cac) + * and [Vertex AI reference](https://cloud.google.com/vertex-ai/generative-ai/docs/context-cache/context-cache-overview#supported_models) + * for more information. + * + * @param params - The parameters for the create request. + * @return The created cached content. + * + * @example + * ```ts + * const contents = ...; // Initialize the content to cache. + * const response = await ai.caches.create({ + * model: 'gemini-2.0-flash-001', + * config: { + * 'contents': contents, + * 'displayName': 'test cache', + * 'systemInstruction': 'What is the sum of the two pdfs?', + * 'ttl': '86400s', + * } + * }); + * ``` + */ + async create(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = createCachedContentParametersToVertex(this.apiClient, params); + path = formatMap('cachedContents', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + else { + const body = createCachedContentParametersToMldev(this.apiClient, params); + path = formatMap('cachedContents', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } + /** + * Gets cached content configurations. + * + * @param params - The parameters for the get request. + * @return The cached content. + * + * @example + * ```ts + * await ai.caches.get({name: '...'}); // The server-generated resource name. + * ``` + */ + async get(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = getCachedContentParametersToVertex(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + else { + const body = getCachedContentParametersToMldev(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } + /** + * Deletes cached content. + * + * @param params - The parameters for the delete request. + * @return The empty response returned by the API. + * + * @example + * ```ts + * await ai.caches.delete({name: '...'}); // The server-generated resource name. + * ``` + */ + async delete(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = deleteCachedContentParametersToVertex(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = deleteCachedContentResponseFromVertex(apiResponse); + const typedResp = new DeleteCachedContentResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = deleteCachedContentParametersToMldev(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = deleteCachedContentResponseFromMldev(apiResponse); + const typedResp = new DeleteCachedContentResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Updates cached content configurations. + * + * @param params - The parameters for the update request. + * @return The updated cached content. + * + * @example + * ```ts + * const response = await ai.caches.update({ + * name: '...', // The server-generated resource name. + * config: {'ttl': '7600s'} + * }); + * ``` + */ + async update(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = updateCachedContentParametersToVertex(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'PATCH', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + else { + const body = updateCachedContentParametersToMldev(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'PATCH', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } + async listInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = listCachedContentsParametersToVertex(params); + path = formatMap('cachedContents', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listCachedContentsResponseFromVertex(apiResponse); + const typedResp = new ListCachedContentsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = listCachedContentsParametersToMldev(params); + path = formatMap('cachedContents', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listCachedContentsResponseFromMldev(apiResponse); + const typedResp = new ListCachedContentsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } +} + +/****************************************************************************** +Copyright (c) Microsoft Corporation. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +***************************************************************************** */ +/* global Reflect, Promise, SuppressedError, Symbol, Iterator */ + + +function __rest(s, e) { + var t = {}; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) + t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === "function") + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { + if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) + t[p[i]] = s[p[i]]; + } + return t; +} + +function __values(o) { + var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; + if (m) return m.call(o); + if (o && typeof o.length === "number") return { + next: function () { + if (o && i >= o.length) o = void 0; + return { value: o && o[i++], done: !o }; + } + }; + throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); +} + +function __await(v) { + return this instanceof __await ? (this.v = v, this) : new __await(v); +} + +function __asyncGenerator(thisArg, _arguments, generator) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var g = generator.apply(thisArg, _arguments || []), i, q = []; + return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i; + function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; } + function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } } + function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function fulfill(value) { resume("next", value); } + function reject(value) { resume("throw", value); } + function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } +} + +function __asyncValues(o) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var m = o[Symbol.asyncIterator], i; + return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); + function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } + function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } +} + +typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { + var e = new Error(message); + return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Returns true if the response is valid, false otherwise. + */ +function isValidResponse(response) { + var _a; + if (response.candidates == undefined || response.candidates.length === 0) { + return false; + } + const content = (_a = response.candidates[0]) === null || _a === void 0 ? void 0 : _a.content; + if (content === undefined) { + return false; + } + return isValidContent(content); +} +function isValidContent(content) { + if (content.parts === undefined || content.parts.length === 0) { + return false; + } + for (const part of content.parts) { + if (part === undefined || Object.keys(part).length === 0) { + return false; + } + } + return true; +} +/** + * Validates the history contains the correct roles. + * + * @throws Error if the history does not start with a user turn. + * @throws Error if the history contains an invalid role. + */ +function validateHistory(history) { + // Empty history is valid. + if (history.length === 0) { + return; + } + for (const content of history) { + if (content.role !== 'user' && content.role !== 'model') { + throw new Error(`Role must be user or model, but got ${content.role}.`); + } + } +} +/** + * Extracts the curated (valid) history from a comprehensive history. + * + * @remarks + * The model may sometimes generate invalid or empty contents(e.g., due to safty + * filters or recitation). Extracting valid turns from the history + * ensures that subsequent requests could be accpeted by the model. + */ +function extractCuratedHistory(comprehensiveHistory) { + if (comprehensiveHistory === undefined || comprehensiveHistory.length === 0) { + return []; + } + const curatedHistory = []; + const length = comprehensiveHistory.length; + let i = 0; + while (i < length) { + if (comprehensiveHistory[i].role === 'user') { + curatedHistory.push(comprehensiveHistory[i]); + i++; + } + else { + const modelOutput = []; + let isValid = true; + while (i < length && comprehensiveHistory[i].role === 'model') { + modelOutput.push(comprehensiveHistory[i]); + if (isValid && !isValidContent(comprehensiveHistory[i])) { + isValid = false; + } + i++; + } + if (isValid) { + curatedHistory.push(...modelOutput); + } + else { + // Remove the last user input when model content is invalid. + curatedHistory.pop(); + } + } + } + return curatedHistory; +} +/** + * A utility class to create a chat session. + */ +class Chats { + constructor(modelsModule, apiClient) { + this.modelsModule = modelsModule; + this.apiClient = apiClient; + } + /** + * Creates a new chat session. + * + * @remarks + * The config in the params will be used for all requests within the chat + * session unless overridden by a per-request `config` in + * @see {@link types.SendMessageParameters#config}. + * + * @param params - Parameters for creating a chat session. + * @returns A new chat session. + * + * @example + * ```ts + * const chat = ai.chats.create({ + * model: 'gemini-2.0-flash' + * config: { + * temperature: 0.5, + * maxOutputTokens: 1024, + * } + * }); + * ``` + */ + create(params) { + return new Chat(this.apiClient, this.modelsModule, params.model, params.config, + // Deep copy the history to avoid mutating the history outside of the + // chat session. + structuredClone(params.history)); + } +} +/** + * Chat session that enables sending messages to the model with previous + * conversation context. + * + * @remarks + * The session maintains all the turns between user and model. + */ +class Chat { + constructor(apiClient, modelsModule, model, config = {}, history = []) { + this.apiClient = apiClient; + this.modelsModule = modelsModule; + this.model = model; + this.config = config; + this.history = history; + // A promise to represent the current state of the message being sent to the + // model. + this.sendPromise = Promise.resolve(); + validateHistory(history); + } + /** + * Sends a message to the model and returns the response. + * + * @remarks + * This method will wait for the previous message to be processed before + * sending the next message. + * + * @see {@link Chat#sendMessageStream} for streaming method. + * @param params - parameters for sending messages within a chat session. + * @returns The model's response. + * + * @example + * ```ts + * const chat = ai.chats.create({model: 'gemini-2.0-flash'}); + * const response = await chat.sendMessage({ + * message: 'Why is the sky blue?' + * }); + * console.log(response.text); + * ``` + */ + async sendMessage(params) { + var _a; + await this.sendPromise; + const inputContent = tContent(params.message); + const responsePromise = this.modelsModule.generateContent({ + model: this.model, + contents: this.getHistory(true).concat(inputContent), + config: (_a = params.config) !== null && _a !== void 0 ? _a : this.config, + }); + this.sendPromise = (async () => { + var _a, _b, _c; + const response = await responsePromise; + const outputContent = (_b = (_a = response.candidates) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.content; + // Because the AFC input contains the entire curated chat history in + // addition to the new user input, we need to truncate the AFC history + // to deduplicate the existing chat history. + const fullAutomaticFunctionCallingHistory = response.automaticFunctionCallingHistory; + const index = this.getHistory(true).length; + let automaticFunctionCallingHistory = []; + if (fullAutomaticFunctionCallingHistory != null) { + automaticFunctionCallingHistory = + (_c = fullAutomaticFunctionCallingHistory.slice(index)) !== null && _c !== void 0 ? _c : []; + } + const modelOutput = outputContent ? [outputContent] : []; + this.recordHistory(inputContent, modelOutput, automaticFunctionCallingHistory); + return; + })(); + await this.sendPromise.catch(() => { + // Resets sendPromise to avoid subsequent calls failing + this.sendPromise = Promise.resolve(); + }); + return responsePromise; + } + /** + * Sends a message to the model and returns the response in chunks. + * + * @remarks + * This method will wait for the previous message to be processed before + * sending the next message. + * + * @see {@link Chat#sendMessage} for non-streaming method. + * @param params - parameters for sending the message. + * @return The model's response. + * + * @example + * ```ts + * const chat = ai.chats.create({model: 'gemini-2.0-flash'}); + * const response = await chat.sendMessageStream({ + * message: 'Why is the sky blue?' + * }); + * for await (const chunk of response) { + * console.log(chunk.text); + * } + * ``` + */ + async sendMessageStream(params) { + var _a; + await this.sendPromise; + const inputContent = tContent(params.message); + const streamResponse = this.modelsModule.generateContentStream({ + model: this.model, + contents: this.getHistory(true).concat(inputContent), + config: (_a = params.config) !== null && _a !== void 0 ? _a : this.config, + }); + // Resolve the internal tracking of send completion promise - `sendPromise` + // for both success and failure response. The actual failure is still + // propagated by the `await streamResponse`. + this.sendPromise = streamResponse + .then(() => undefined) + .catch(() => undefined); + const response = await streamResponse; + const result = this.processStreamResponse(response, inputContent); + return result; + } + /** + * Returns the chat history. + * + * @remarks + * The history is a list of contents alternating between user and model. + * + * There are two types of history: + * - The `curated history` contains only the valid turns between user and + * model, which will be included in the subsequent requests sent to the model. + * - The `comprehensive history` contains all turns, including invalid or + * empty model outputs, providing a complete record of the history. + * + * The history is updated after receiving the response from the model, + * for streaming response, it means receiving the last chunk of the response. + * + * The `comprehensive history` is returned by default. To get the `curated + * history`, set the `curated` parameter to `true`. + * + * @param curated - whether to return the curated history or the comprehensive + * history. + * @return History contents alternating between user and model for the entire + * chat session. + */ + getHistory(curated = false) { + const history = curated + ? extractCuratedHistory(this.history) + : this.history; + // Deep copy the history to avoid mutating the history outside of the + // chat session. + return structuredClone(history); + } + processStreamResponse(streamResponse, inputContent) { + return __asyncGenerator(this, arguments, function* processStreamResponse_1() { + var _a, e_1, _b, _c; + var _d, _e; + const outputContent = []; + try { + for (var _f = true, streamResponse_1 = __asyncValues(streamResponse), streamResponse_1_1; streamResponse_1_1 = yield __await(streamResponse_1.next()), _a = streamResponse_1_1.done, !_a; _f = true) { + _c = streamResponse_1_1.value; + _f = false; + const chunk = _c; + if (isValidResponse(chunk)) { + const content = (_e = (_d = chunk.candidates) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.content; + if (content !== undefined) { + outputContent.push(content); + } + } + yield yield __await(chunk); + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (!_f && !_a && (_b = streamResponse_1.return)) yield __await(_b.call(streamResponse_1)); + } + finally { if (e_1) throw e_1.error; } + } + this.recordHistory(inputContent, outputContent); + }); + } + recordHistory(userInput, modelOutput, automaticFunctionCallingHistory) { + let outputContents = []; + if (modelOutput.length > 0 && + modelOutput.every((content) => content.role !== undefined)) { + outputContents = modelOutput; + } + else { + // Appends an empty content when model returns empty response, so that the + // history is always alternating between user and model. + outputContents.push({ + role: 'model', + parts: [], + }); + } + if (automaticFunctionCallingHistory && + automaticFunctionCallingHistory.length > 0) { + this.history.push(...extractCuratedHistory(automaticFunctionCallingHistory)); + } + else { + this.history.push(userInput); + } + this.history.push(...outputContents); + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Code generated by the Google Gen AI SDK generator DO NOT EDIT. +function createFileSearchStoreConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromDisplayName); + } + return toObject; +} +function createFileSearchStoreParametersToMldev(fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createFileSearchStoreConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function deleteFileSearchStoreConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromForce = getValueByPath(fromObject, ['force']); + if (parentObject !== undefined && fromForce != null) { + setValueByPath(parentObject, ['_query', 'force'], fromForce); + } + return toObject; +} +function deleteFileSearchStoreParametersToMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + deleteFileSearchStoreConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function getFileSearchStoreParametersToMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + return toObject; +} +function importFileConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromCustomMetadata = getValueByPath(fromObject, [ + 'customMetadata', + ]); + if (parentObject !== undefined && fromCustomMetadata != null) { + let transformedList = fromCustomMetadata; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(parentObject, ['customMetadata'], transformedList); + } + const fromChunkingConfig = getValueByPath(fromObject, [ + 'chunkingConfig', + ]); + if (parentObject !== undefined && fromChunkingConfig != null) { + setValueByPath(parentObject, ['chunkingConfig'], fromChunkingConfig); + } + return toObject; +} +function importFileOperationFromMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], importFileResponseFromMldev(fromResponse)); + } + return toObject; +} +function importFileParametersToMldev(fromObject) { + const toObject = {}; + const fromFileSearchStoreName = getValueByPath(fromObject, [ + 'fileSearchStoreName', + ]); + if (fromFileSearchStoreName != null) { + setValueByPath(toObject, ['_url', 'file_search_store_name'], fromFileSearchStoreName); + } + const fromFileName = getValueByPath(fromObject, ['fileName']); + if (fromFileName != null) { + setValueByPath(toObject, ['fileName'], fromFileName); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + importFileConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function importFileResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromParent = getValueByPath(fromObject, ['parent']); + if (fromParent != null) { + setValueByPath(toObject, ['parent'], fromParent); + } + const fromDocumentName = getValueByPath(fromObject, ['documentName']); + if (fromDocumentName != null) { + setValueByPath(toObject, ['documentName'], fromDocumentName); + } + return toObject; +} +function listFileSearchStoresConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + return toObject; +} +function listFileSearchStoresParametersToMldev(fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listFileSearchStoresConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function listFileSearchStoresResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromFileSearchStores = getValueByPath(fromObject, [ + 'fileSearchStores', + ]); + if (fromFileSearchStores != null) { + let transformedList = fromFileSearchStores; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['fileSearchStores'], transformedList); + } + return toObject; +} +function uploadToFileSearchStoreConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (parentObject !== undefined && fromMimeType != null) { + setValueByPath(parentObject, ['mimeType'], fromMimeType); + } + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromDisplayName); + } + const fromCustomMetadata = getValueByPath(fromObject, [ + 'customMetadata', + ]); + if (parentObject !== undefined && fromCustomMetadata != null) { + let transformedList = fromCustomMetadata; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(parentObject, ['customMetadata'], transformedList); + } + const fromChunkingConfig = getValueByPath(fromObject, [ + 'chunkingConfig', + ]); + if (parentObject !== undefined && fromChunkingConfig != null) { + setValueByPath(parentObject, ['chunkingConfig'], fromChunkingConfig); + } + return toObject; +} +function uploadToFileSearchStoreParametersToMldev(fromObject) { + const toObject = {}; + const fromFileSearchStoreName = getValueByPath(fromObject, [ + 'fileSearchStoreName', + ]); + if (fromFileSearchStoreName != null) { + setValueByPath(toObject, ['_url', 'file_search_store_name'], fromFileSearchStoreName); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + uploadToFileSearchStoreConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function uploadToFileSearchStoreResumableResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * API errors raised by the GenAI API. + */ +class ApiError extends Error { + constructor(options) { + super(options.message); + this.name = 'ApiError'; + this.status = options.status; + Object.setPrototypeOf(this, ApiError.prototype); + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const CONTENT_TYPE_HEADER = 'Content-Type'; +const SERVER_TIMEOUT_HEADER = 'X-Server-Timeout'; +const USER_AGENT_HEADER = 'User-Agent'; +const GOOGLE_API_CLIENT_HEADER = 'x-goog-api-client'; +const SDK_VERSION = '1.41.0'; // x-release-please-version +const LIBRARY_LABEL = `google-genai-sdk/${SDK_VERSION}`; +const VERTEX_AI_API_DEFAULT_VERSION = 'v1beta1'; +const GOOGLE_AI_API_DEFAULT_VERSION = 'v1beta'; +// Default retry options. +// The config is based on https://cloud.google.com/storage/docs/retry-strategy. +const DEFAULT_RETRY_ATTEMPTS = 5; // Including the initial call +// LINT.IfChange +const DEFAULT_RETRY_HTTP_STATUS_CODES = [ + 408, // Request timeout + 429, // Too many requests + 500, // Internal server error + 502, // Bad gateway + 503, // Service unavailable + 504, // Gateway timeout +]; +/** + * The ApiClient class is used to send requests to the Gemini API or Vertex AI + * endpoints. + */ +class ApiClient { + constructor(opts) { + var _a, _b, _c; + this.clientOptions = Object.assign({}, opts); + this.customBaseUrl = (_a = opts.httpOptions) === null || _a === void 0 ? void 0 : _a.baseUrl; + if (this.clientOptions.vertexai) { + if (this.clientOptions.project && this.clientOptions.location) { + this.clientOptions.apiKey = undefined; + } + else if (this.clientOptions.apiKey) { + this.clientOptions.project = undefined; + this.clientOptions.location = undefined; + } + } + const initHttpOptions = {}; + if (this.clientOptions.vertexai) { + if (!this.clientOptions.location && + !this.clientOptions.apiKey && + !this.customBaseUrl) { + this.clientOptions.location = 'global'; + } + const hasSufficientAuth = (this.clientOptions.project && this.clientOptions.location) || + this.clientOptions.apiKey; + if (!hasSufficientAuth && !this.customBaseUrl) { + throw new Error('Authentication is not set up. Please provide either a project and location, or an API key, or a custom base URL.'); + } + const hasConstructorAuth = (opts.project && opts.location) || !!opts.apiKey; + if (this.customBaseUrl && !hasConstructorAuth) { + initHttpOptions.baseUrl = this.customBaseUrl; + this.clientOptions.project = undefined; + this.clientOptions.location = undefined; + } + else if (this.clientOptions.apiKey || + this.clientOptions.location === 'global') { + // Vertex Express or global endpoint case. + initHttpOptions.baseUrl = 'https://aiplatform.googleapis.com/'; + } + else if (this.clientOptions.project && this.clientOptions.location) { + initHttpOptions.baseUrl = `https://${this.clientOptions.location}-aiplatform.googleapis.com/`; + } + initHttpOptions.apiVersion = + (_b = this.clientOptions.apiVersion) !== null && _b !== void 0 ? _b : VERTEX_AI_API_DEFAULT_VERSION; + } + else { + // Gemini API + if (!this.clientOptions.apiKey) { + throw new ApiError({ + message: 'API key must be set when using the Gemini API.', + status: 403, + }); + } + initHttpOptions.apiVersion = + (_c = this.clientOptions.apiVersion) !== null && _c !== void 0 ? _c : GOOGLE_AI_API_DEFAULT_VERSION; + initHttpOptions.baseUrl = `https://generativelanguage.googleapis.com/`; + } + initHttpOptions.headers = this.getDefaultHeaders(); + this.clientOptions.httpOptions = initHttpOptions; + if (opts.httpOptions) { + this.clientOptions.httpOptions = this.patchHttpOptions(initHttpOptions, opts.httpOptions); + } + } + isVertexAI() { + var _a; + return (_a = this.clientOptions.vertexai) !== null && _a !== void 0 ? _a : false; + } + getProject() { + return this.clientOptions.project; + } + getLocation() { + return this.clientOptions.location; + } + getCustomBaseUrl() { + return this.customBaseUrl; + } + async getAuthHeaders() { + const headers = new Headers(); + await this.clientOptions.auth.addAuthHeaders(headers); + return headers; + } + getApiVersion() { + if (this.clientOptions.httpOptions && + this.clientOptions.httpOptions.apiVersion !== undefined) { + return this.clientOptions.httpOptions.apiVersion; + } + throw new Error('API version is not set.'); + } + getBaseUrl() { + if (this.clientOptions.httpOptions && + this.clientOptions.httpOptions.baseUrl !== undefined) { + return this.clientOptions.httpOptions.baseUrl; + } + throw new Error('Base URL is not set.'); + } + getRequestUrl() { + return this.getRequestUrlInternal(this.clientOptions.httpOptions); + } + getHeaders() { + if (this.clientOptions.httpOptions && + this.clientOptions.httpOptions.headers !== undefined) { + return this.clientOptions.httpOptions.headers; + } + else { + throw new Error('Headers are not set.'); + } + } + getRequestUrlInternal(httpOptions) { + if (!httpOptions || + httpOptions.baseUrl === undefined || + httpOptions.apiVersion === undefined) { + throw new Error('HTTP options are not correctly set.'); + } + const baseUrl = httpOptions.baseUrl.endsWith('/') + ? httpOptions.baseUrl.slice(0, -1) + : httpOptions.baseUrl; + const urlElement = [baseUrl]; + if (httpOptions.apiVersion && httpOptions.apiVersion !== '') { + urlElement.push(httpOptions.apiVersion); + } + return urlElement.join('/'); + } + getBaseResourcePath() { + return `projects/${this.clientOptions.project}/locations/${this.clientOptions.location}`; + } + getApiKey() { + return this.clientOptions.apiKey; + } + getWebsocketBaseUrl() { + const baseUrl = this.getBaseUrl(); + const urlParts = new URL(baseUrl); + urlParts.protocol = urlParts.protocol == 'http:' ? 'ws' : 'wss'; + return urlParts.toString(); + } + setBaseUrl(url) { + if (this.clientOptions.httpOptions) { + this.clientOptions.httpOptions.baseUrl = url; + } + else { + throw new Error('HTTP options are not correctly set.'); + } + } + constructUrl(path, httpOptions, prependProjectLocation) { + const urlElement = [this.getRequestUrlInternal(httpOptions)]; + if (prependProjectLocation) { + urlElement.push(this.getBaseResourcePath()); + } + if (path !== '') { + urlElement.push(path); + } + const url = new URL(`${urlElement.join('/')}`); + return url; + } + shouldPrependVertexProjectPath(request, httpOptions) { + if (httpOptions.baseUrl && + httpOptions.baseUrlResourceScope === ResourceScope.COLLECTION) { + return false; + } + if (this.clientOptions.apiKey) { + return false; + } + if (!this.clientOptions.vertexai) { + return false; + } + if (request.path.startsWith('projects/')) { + // Assume the path already starts with + // `projects/<project>/location/<location>`. + return false; + } + if (request.httpMethod === 'GET' && + request.path.startsWith('publishers/google/models')) { + // These paths are used by Vertex's models.get and models.list + // calls. For base models Vertex does not accept a project/location + // prefix (for tuned model the prefix is required). + return false; + } + return true; + } + async request(request) { + let patchedHttpOptions = this.clientOptions.httpOptions; + if (request.httpOptions) { + patchedHttpOptions = this.patchHttpOptions(this.clientOptions.httpOptions, request.httpOptions); + } + const prependProjectLocation = this.shouldPrependVertexProjectPath(request, patchedHttpOptions); + const url = this.constructUrl(request.path, patchedHttpOptions, prependProjectLocation); + if (request.queryParams) { + for (const [key, value] of Object.entries(request.queryParams)) { + url.searchParams.append(key, String(value)); + } + } + let requestInit = {}; + if (request.httpMethod === 'GET') { + if (request.body && request.body !== '{}') { + throw new Error('Request body should be empty for GET request, but got non empty request body'); + } + } + else { + requestInit.body = request.body; + } + requestInit = await this.includeExtraHttpOptionsToRequestInit(requestInit, patchedHttpOptions, url.toString(), request.abortSignal); + return this.unaryApiCall(url, requestInit, request.httpMethod); + } + patchHttpOptions(baseHttpOptions, requestHttpOptions) { + const patchedHttpOptions = JSON.parse(JSON.stringify(baseHttpOptions)); + for (const [key, value] of Object.entries(requestHttpOptions)) { + // Records compile to objects. + if (typeof value === 'object') { + // @ts-expect-error TS2345TS7053: Element implicitly has an 'any' type + // because expression of type 'string' can't be used to index type + // 'HttpOptions'. + patchedHttpOptions[key] = Object.assign(Object.assign({}, patchedHttpOptions[key]), value); + } + else if (value !== undefined) { + // @ts-expect-error TS2345TS7053: Element implicitly has an 'any' type + // because expression of type 'string' can't be used to index type + // 'HttpOptions'. + patchedHttpOptions[key] = value; + } + } + return patchedHttpOptions; + } + async requestStream(request) { + let patchedHttpOptions = this.clientOptions.httpOptions; + if (request.httpOptions) { + patchedHttpOptions = this.patchHttpOptions(this.clientOptions.httpOptions, request.httpOptions); + } + const prependProjectLocation = this.shouldPrependVertexProjectPath(request, patchedHttpOptions); + const url = this.constructUrl(request.path, patchedHttpOptions, prependProjectLocation); + if (!url.searchParams.has('alt') || url.searchParams.get('alt') !== 'sse') { + url.searchParams.set('alt', 'sse'); + } + let requestInit = {}; + requestInit.body = request.body; + requestInit = await this.includeExtraHttpOptionsToRequestInit(requestInit, patchedHttpOptions, url.toString(), request.abortSignal); + return this.streamApiCall(url, requestInit, request.httpMethod); + } + async includeExtraHttpOptionsToRequestInit(requestInit, httpOptions, url, abortSignal) { + if ((httpOptions && httpOptions.timeout) || abortSignal) { + const abortController = new AbortController(); + const signal = abortController.signal; + if (httpOptions.timeout && (httpOptions === null || httpOptions === void 0 ? void 0 : httpOptions.timeout) > 0) { + const timeoutHandle = setTimeout(() => abortController.abort(), httpOptions.timeout); + if (timeoutHandle && + typeof timeoutHandle.unref === + 'function') { + // call unref to prevent nodejs process from hanging, see + // https://nodejs.org/api/timers.html#timeoutunref + timeoutHandle.unref(); + } + } + if (abortSignal) { + abortSignal.addEventListener('abort', () => { + abortController.abort(); + }); + } + requestInit.signal = signal; + } + if (httpOptions && httpOptions.extraBody !== null) { + includeExtraBodyToRequestInit(requestInit, httpOptions.extraBody); + } + requestInit.headers = await this.getHeadersInternal(httpOptions, url); + return requestInit; + } + async unaryApiCall(url, requestInit, httpMethod) { + return this.apiCall(url.toString(), Object.assign(Object.assign({}, requestInit), { method: httpMethod })) + .then(async (response) => { + await throwErrorIfNotOK(response); + return new HttpResponse(response); + }) + .catch((e) => { + if (e instanceof Error) { + throw e; + } + else { + throw new Error(JSON.stringify(e)); + } + }); + } + async streamApiCall(url, requestInit, httpMethod) { + return this.apiCall(url.toString(), Object.assign(Object.assign({}, requestInit), { method: httpMethod })) + .then(async (response) => { + await throwErrorIfNotOK(response); + return this.processStreamResponse(response); + }) + .catch((e) => { + if (e instanceof Error) { + throw e; + } + else { + throw new Error(JSON.stringify(e)); + } + }); + } + processStreamResponse(response) { + return __asyncGenerator(this, arguments, function* processStreamResponse_1() { + var _a; + const reader = (_a = response === null || response === void 0 ? void 0 : response.body) === null || _a === void 0 ? void 0 : _a.getReader(); + const decoder = new TextDecoder('utf-8'); + if (!reader) { + throw new Error('Response body is empty'); + } + try { + let buffer = ''; + const dataPrefix = 'data:'; + const delimiters = ['\n\n', '\r\r', '\r\n\r\n']; + while (true) { + const { done, value } = yield __await(reader.read()); + if (done) { + if (buffer.trim().length > 0) { + throw new Error('Incomplete JSON segment at the end'); + } + break; + } + const chunkString = decoder.decode(value, { stream: true }); + // Parse and throw an error if the chunk contains an error. + try { + const chunkJson = JSON.parse(chunkString); + if ('error' in chunkJson) { + const errorJson = JSON.parse(JSON.stringify(chunkJson['error'])); + const status = errorJson['status']; + const code = errorJson['code']; + const errorMessage = `got status: ${status}. ${JSON.stringify(chunkJson)}`; + if (code >= 400 && code < 600) { + const apiError = new ApiError({ + message: errorMessage, + status: code, + }); + throw apiError; + } + } + } + catch (e) { + const error = e; + if (error.name === 'ApiError') { + throw e; + } + } + buffer += chunkString; + let delimiterIndex = -1; + let delimiterLength = 0; + while (true) { + delimiterIndex = -1; + delimiterLength = 0; + for (const delimiter of delimiters) { + const index = buffer.indexOf(delimiter); + if (index !== -1 && + (delimiterIndex === -1 || index < delimiterIndex)) { + delimiterIndex = index; + delimiterLength = delimiter.length; + } + } + if (delimiterIndex === -1) { + break; // No complete event in buffer + } + const eventString = buffer.substring(0, delimiterIndex); + buffer = buffer.substring(delimiterIndex + delimiterLength); + const trimmedEvent = eventString.trim(); + if (trimmedEvent.startsWith(dataPrefix)) { + const processedChunkString = trimmedEvent + .substring(dataPrefix.length) + .trim(); + try { + const partialResponse = new Response(processedChunkString, { + headers: response === null || response === void 0 ? void 0 : response.headers, + status: response === null || response === void 0 ? void 0 : response.status, + statusText: response === null || response === void 0 ? void 0 : response.statusText, + }); + yield yield __await(new HttpResponse(partialResponse)); + } + catch (e) { + throw new Error(`exception parsing stream chunk ${processedChunkString}. ${e}`); + } + } + } + } + } + finally { + reader.releaseLock(); + } + }); + } + async apiCall(url, requestInit) { + var _a; + if (!this.clientOptions.httpOptions || + !this.clientOptions.httpOptions.retryOptions) { + return fetch(url, requestInit); + } + const retryOptions = this.clientOptions.httpOptions.retryOptions; + const runFetch = async () => { + const response = await fetch(url, requestInit); + if (response.ok) { + return response; + } + if (DEFAULT_RETRY_HTTP_STATUS_CODES.includes(response.status)) { + throw new Error(`Retryable HTTP Error: ${response.statusText}`); + } + throw new AbortError(`Non-retryable exception ${response.statusText} sending request`); + }; + return pRetry(runFetch, { + // Retry attempts is one less than the number of total attempts. + retries: ((_a = retryOptions.attempts) !== null && _a !== void 0 ? _a : DEFAULT_RETRY_ATTEMPTS) - 1, + }); + } + getDefaultHeaders() { + const headers = {}; + const versionHeaderValue = LIBRARY_LABEL + ' ' + this.clientOptions.userAgentExtra; + headers[USER_AGENT_HEADER] = versionHeaderValue; + headers[GOOGLE_API_CLIENT_HEADER] = versionHeaderValue; + headers[CONTENT_TYPE_HEADER] = 'application/json'; + return headers; + } + async getHeadersInternal(httpOptions, url) { + const headers = new Headers(); + if (httpOptions && httpOptions.headers) { + for (const [key, value] of Object.entries(httpOptions.headers)) { + headers.append(key, value); + } + // Append a timeout header if it is set, note that the timeout option is + // in milliseconds but the header is in seconds. + if (httpOptions.timeout && httpOptions.timeout > 0) { + headers.append(SERVER_TIMEOUT_HEADER, String(Math.ceil(httpOptions.timeout / 1000))); + } + } + await this.clientOptions.auth.addAuthHeaders(headers, url); + return headers; + } + getFileName(file) { + var _a; + let fileName = ''; + if (typeof file === 'string') { + fileName = file.replace(/[/\\]+$/, ''); + fileName = (_a = fileName.split(/[/\\]/).pop()) !== null && _a !== void 0 ? _a : ''; + } + return fileName; + } + /** + * Uploads a file asynchronously using Gemini API only, this is not supported + * in Vertex AI. + * + * @param file The string path to the file to be uploaded or a Blob object. + * @param config Optional parameters specified in the `UploadFileConfig` + * interface. @see {@link types.UploadFileConfig} + * @return A promise that resolves to a `File` object. + * @throws An error if called on a Vertex AI client. + * @throws An error if the `mimeType` is not provided and can not be inferred, + */ + async uploadFile(file, config) { + var _a; + const fileToUpload = {}; + if (config != null) { + fileToUpload.mimeType = config.mimeType; + fileToUpload.name = config.name; + fileToUpload.displayName = config.displayName; + } + if (fileToUpload.name && !fileToUpload.name.startsWith('files/')) { + fileToUpload.name = `files/${fileToUpload.name}`; + } + const uploader = this.clientOptions.uploader; + const fileStat = await uploader.stat(file); + fileToUpload.sizeBytes = String(fileStat.size); + const mimeType = (_a = config === null || config === void 0 ? void 0 : config.mimeType) !== null && _a !== void 0 ? _a : fileStat.type; + if (mimeType === undefined || mimeType === '') { + throw new Error('Can not determine mimeType. Please provide mimeType in the config.'); + } + fileToUpload.mimeType = mimeType; + const body = { + file: fileToUpload, + }; + const fileName = this.getFileName(file); + const path = formatMap('upload/v1beta/files', body['_url']); + const uploadUrl = await this.fetchUploadUrl(path, fileToUpload.sizeBytes, fileToUpload.mimeType, fileName, body, config === null || config === void 0 ? void 0 : config.httpOptions); + return uploader.upload(file, uploadUrl, this); + } + /** + * Uploads a file to a given file search store asynchronously using Gemini API only, this is not supported + * in Vertex AI. + * + * @param fileSearchStoreName The name of the file search store to upload the file to. + * @param file The string path to the file to be uploaded or a Blob object. + * @param config Optional parameters specified in the `UploadFileConfig` + * interface. @see {@link UploadFileConfig} + * @return A promise that resolves to a `File` object. + * @throws An error if called on a Vertex AI client. + * @throws An error if the `mimeType` is not provided and can not be inferred, + */ + async uploadFileToFileSearchStore(fileSearchStoreName, file, config) { + var _a; + const uploader = this.clientOptions.uploader; + const fileStat = await uploader.stat(file); + const sizeBytes = String(fileStat.size); + const mimeType = (_a = config === null || config === void 0 ? void 0 : config.mimeType) !== null && _a !== void 0 ? _a : fileStat.type; + if (mimeType === undefined || mimeType === '') { + throw new Error('Can not determine mimeType. Please provide mimeType in the config.'); + } + const path = `upload/v1beta/${fileSearchStoreName}:uploadToFileSearchStore`; + const fileName = this.getFileName(file); + const body = {}; + if (config != null) { + uploadToFileSearchStoreConfigToMldev(config, body); + } + const uploadUrl = await this.fetchUploadUrl(path, sizeBytes, mimeType, fileName, body, config === null || config === void 0 ? void 0 : config.httpOptions); + return uploader.uploadToFileSearchStore(file, uploadUrl, this); + } + /** + * Downloads a file asynchronously to the specified path. + * + * @params params - The parameters for the download request, see {@link + * types.DownloadFileParameters} + */ + async downloadFile(params) { + const downloader = this.clientOptions.downloader; + await downloader.download(params, this); + } + async fetchUploadUrl(path, sizeBytes, mimeType, fileName, body, configHttpOptions) { + var _a; + let httpOptions = {}; + if (configHttpOptions) { + httpOptions = configHttpOptions; + } + else { + httpOptions = { + apiVersion: '', // api-version is set in the path. + headers: Object.assign({ 'Content-Type': 'application/json', 'X-Goog-Upload-Protocol': 'resumable', 'X-Goog-Upload-Command': 'start', 'X-Goog-Upload-Header-Content-Length': `${sizeBytes}`, 'X-Goog-Upload-Header-Content-Type': `${mimeType}` }, (fileName ? { 'X-Goog-Upload-File-Name': fileName } : {})), + }; + } + const httpResponse = await this.request({ + path, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions, + }); + if (!httpResponse || !(httpResponse === null || httpResponse === void 0 ? void 0 : httpResponse.headers)) { + throw new Error('Server did not return an HttpResponse or the returned HttpResponse did not have headers.'); + } + const uploadUrl = (_a = httpResponse === null || httpResponse === void 0 ? void 0 : httpResponse.headers) === null || _a === void 0 ? void 0 : _a['x-goog-upload-url']; + if (uploadUrl === undefined) { + throw new Error('Failed to get upload url. Server did not return the x-google-upload-url in the headers'); + } + return uploadUrl; + } +} +async function throwErrorIfNotOK(response) { + var _a; + if (response === undefined) { + throw new Error('response is undefined'); + } + if (!response.ok) { + const status = response.status; + let errorBody; + if ((_a = response.headers.get('content-type')) === null || _a === void 0 ? void 0 : _a.includes('application/json')) { + errorBody = await response.json(); + } + else { + errorBody = { + error: { + message: await response.text(), + code: response.status, + status: response.statusText, + }, + }; + } + const errorMessage = JSON.stringify(errorBody); + if (status >= 400 && status < 600) { + const apiError = new ApiError({ + message: errorMessage, + status: status, + }); + throw apiError; + } + throw new Error(errorMessage); + } +} +/** + * Recursively updates the `requestInit.body` with values from an `extraBody` object. + * + * If `requestInit.body` is a string, it's assumed to be JSON and will be parsed. + * The `extraBody` is then deeply merged into this parsed object. + * If `requestInit.body` is a Blob, `extraBody` will be ignored, and a warning logged, + * as merging structured data into an opaque Blob is not supported. + * + * The function does not enforce that updated values from `extraBody` have the + * same type as existing values in `requestInit.body`. Type mismatches during + * the merge will result in a warning, but the value from `extraBody` will overwrite + * the original. `extraBody` users are responsible for ensuring `extraBody` has the correct structure. + * + * @param requestInit The RequestInit object whose body will be updated. + * @param extraBody The object containing updates to be merged into `requestInit.body`. + */ +function includeExtraBodyToRequestInit(requestInit, extraBody) { + if (!extraBody || Object.keys(extraBody).length === 0) { + return; + } + if (requestInit.body instanceof Blob) { + console.warn('includeExtraBodyToRequestInit: extraBody provided but current request body is a Blob. extraBody will be ignored as merging is not supported for Blob bodies.'); + return; + } + let currentBodyObject = {}; + // If adding new type to HttpRequest.body, please check the code below to + // see if we need to update the logic. + if (typeof requestInit.body === 'string' && requestInit.body.length > 0) { + try { + const parsedBody = JSON.parse(requestInit.body); + if (typeof parsedBody === 'object' && + parsedBody !== null && + !Array.isArray(parsedBody)) { + currentBodyObject = parsedBody; + } + else { + console.warn('includeExtraBodyToRequestInit: Original request body is valid JSON but not a non-array object. Skip applying extraBody to the request body.'); + return; + } + /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ + } + catch (e) { + console.warn('includeExtraBodyToRequestInit: Original request body is not valid JSON. Skip applying extraBody to the request body.'); + return; + } + } + function deepMerge(target, source) { + const output = Object.assign({}, target); + for (const key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + const sourceValue = source[key]; + const targetValue = output[key]; + if (sourceValue && + typeof sourceValue === 'object' && + !Array.isArray(sourceValue) && + targetValue && + typeof targetValue === 'object' && + !Array.isArray(targetValue)) { + output[key] = deepMerge(targetValue, sourceValue); + } + else { + if (targetValue && + sourceValue && + typeof targetValue !== typeof sourceValue) { + console.warn(`includeExtraBodyToRequestInit:deepMerge: Type mismatch for key "${key}". Original type: ${typeof targetValue}, New type: ${typeof sourceValue}. Overwriting.`); + } + output[key] = sourceValue; + } + } + } + return output; + } + const mergedBody = deepMerge(currentBodyObject, extraBody); + requestInit.body = JSON.stringify(mergedBody); +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function crossError() { + // TODO(b/399934880): this message needs a link to a help page explaining how to enable conditional exports + return new Error(`This feature requires the web or Node specific @google/genai implementation, you can fix this by either: + +*Enabling conditional exports for your project [recommended]* + +*Using a platform specific import* - Make sure your code imports either '@google/genai/web' or '@google/genai/node' instead of '@google/genai'. +`); +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class CrossDownloader { + async download(_params, _apiClient) { + throw crossError(); + } +} + +const MAX_CHUNK_SIZE = 1024 * 1024 * 8; // bytes +const MAX_RETRY_COUNT = 3; +const INITIAL_RETRY_DELAY_MS = 1000; +const DELAY_MULTIPLIER = 2; +const X_GOOG_UPLOAD_STATUS_HEADER_FIELD = 'x-goog-upload-status'; +class CrossUploader { + async upload(file, uploadUrl, apiClient) { + if (typeof file === 'string') { + throw crossError(); + } + else { + return uploadBlob(file, uploadUrl, apiClient); + } + } + async uploadToFileSearchStore(file, uploadUrl, apiClient) { + if (typeof file === 'string') { + throw crossError(); + } + else { + return uploadBlobToFileSearchStore(file, uploadUrl, apiClient); + } + } + async stat(file) { + if (typeof file === 'string') { + throw crossError(); + } + else { + return getBlobStat(file); + } + } +} +async function uploadBlob(file, uploadUrl, apiClient) { + var _a; + const response = await uploadBlobInternal(file, uploadUrl, apiClient); + const responseJson = (await (response === null || response === void 0 ? void 0 : response.json())); + if (((_a = response === null || response === void 0 ? void 0 : response.headers) === null || _a === void 0 ? void 0 : _a[X_GOOG_UPLOAD_STATUS_HEADER_FIELD]) !== 'final') { + throw new Error('Failed to upload file: Upload status is not finalized.'); + } + return responseJson['file']; +} +async function uploadBlobToFileSearchStore(file, uploadUrl, apiClient) { + var _a; + const response = await uploadBlobInternal(file, uploadUrl, apiClient); + const responseJson = (await (response === null || response === void 0 ? void 0 : response.json())); + if (((_a = response === null || response === void 0 ? void 0 : response.headers) === null || _a === void 0 ? void 0 : _a[X_GOOG_UPLOAD_STATUS_HEADER_FIELD]) !== 'final') { + throw new Error('Failed to upload file: Upload status is not finalized.'); + } + const resp = uploadToFileSearchStoreOperationFromMldev(responseJson); + const typedResp = new UploadToFileSearchStoreOperation(); + Object.assign(typedResp, resp); + return typedResp; +} +async function uploadBlobInternal(file, uploadUrl, apiClient) { + var _a, _b; + let fileSize = 0; + let offset = 0; + let response = new HttpResponse(new Response()); + let uploadCommand = 'upload'; + fileSize = file.size; + while (offset < fileSize) { + const chunkSize = Math.min(MAX_CHUNK_SIZE, fileSize - offset); + const chunk = file.slice(offset, offset + chunkSize); + if (offset + chunkSize >= fileSize) { + uploadCommand += ', finalize'; + } + let retryCount = 0; + let currentDelayMs = INITIAL_RETRY_DELAY_MS; + while (retryCount < MAX_RETRY_COUNT) { + response = await apiClient.request({ + path: '', + body: chunk, + httpMethod: 'POST', + httpOptions: { + apiVersion: '', + baseUrl: uploadUrl, + headers: { + 'X-Goog-Upload-Command': uploadCommand, + 'X-Goog-Upload-Offset': String(offset), + 'Content-Length': String(chunkSize), + }, + }, + }); + if ((_a = response === null || response === void 0 ? void 0 : response.headers) === null || _a === void 0 ? void 0 : _a[X_GOOG_UPLOAD_STATUS_HEADER_FIELD]) { + break; + } + retryCount++; + await sleep$1(currentDelayMs); + currentDelayMs = currentDelayMs * DELAY_MULTIPLIER; + } + offset += chunkSize; + // The `x-goog-upload-status` header field can be `active`, `final` and + //`cancelled` in resposne. + if (((_b = response === null || response === void 0 ? void 0 : response.headers) === null || _b === void 0 ? void 0 : _b[X_GOOG_UPLOAD_STATUS_HEADER_FIELD]) !== 'active') { + break; + } + // TODO(b/401391430) Investigate why the upload status is not finalized + // even though all content has been uploaded. + if (fileSize <= offset) { + throw new Error('All content has been uploaded, but the upload status is not finalized.'); + } + } + return response; +} +async function getBlobStat(file) { + const fileStat = { size: file.size, type: file.type }; + return fileStat; +} +function sleep$1(ms) { + return new Promise((resolvePromise) => setTimeout(resolvePromise, ms)); +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class CrossWebSocketFactory { + create(_url, _headers, _callbacks) { + throw crossError(); + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Code generated by the Google Gen AI SDK generator DO NOT EDIT. +function createFileParametersToMldev(fromObject) { + const toObject = {}; + const fromFile = getValueByPath(fromObject, ['file']); + if (fromFile != null) { + setValueByPath(toObject, ['file'], fromFile); + } + return toObject; +} +function createFileResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function deleteFileParametersToMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'file'], tFileName(fromName)); + } + return toObject; +} +function deleteFileResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function getFileParametersToMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'file'], tFileName(fromName)); + } + return toObject; +} +function internalRegisterFilesParametersToMldev(fromObject) { + const toObject = {}; + const fromUris = getValueByPath(fromObject, ['uris']); + if (fromUris != null) { + setValueByPath(toObject, ['uris'], fromUris); + } + return toObject; +} +function listFilesConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + return toObject; +} +function listFilesParametersToMldev(fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listFilesConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function listFilesResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromFiles = getValueByPath(fromObject, ['files']); + if (fromFiles != null) { + let transformedList = fromFiles; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['files'], transformedList); + } + return toObject; +} +function registerFilesResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromFiles = getValueByPath(fromObject, ['files']); + if (fromFiles != null) { + let transformedList = fromFiles; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['files'], transformedList); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Files extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + /** + * Lists files. + * + * @param params - The parameters for the list request. + * @return - A pager of files. + * + * @example + * ```ts + * const files = await ai.files.list({config: {'pageSize': 2}}); + * for await (const file of files) { + * console.log(file); + * } + * ``` + */ + this.list = async (params = {}) => { + return new Pager(PagedItem.PAGED_ITEM_FILES, (x) => this.listInternal(x), await this.listInternal(params), params); + }; + } + /** + * Uploads a file asynchronously to the Gemini API. + * This method is not available in Vertex AI. + * Supported upload sources: + * - Node.js: File path (string) or Blob object. + * - Browser: Blob object (e.g., File). + * + * @remarks + * The `mimeType` can be specified in the `config` parameter. If omitted: + * - For file path (string) inputs, the `mimeType` will be inferred from the + * file extension. + * - For Blob object inputs, the `mimeType` will be set to the Blob's `type` + * property. + * Somex eamples for file extension to mimeType mapping: + * .txt -> text/plain + * .json -> application/json + * .jpg -> image/jpeg + * .png -> image/png + * .mp3 -> audio/mpeg + * .mp4 -> video/mp4 + * + * This section can contain multiple paragraphs and code examples. + * + * @param params - Optional parameters specified in the + * `types.UploadFileParameters` interface. + * @see {@link types.UploadFileParameters#config} for the optional + * config in the parameters. + * @return A promise that resolves to a `types.File` object. + * @throws An error if called on a Vertex AI client. + * @throws An error if the `mimeType` is not provided and can not be inferred, + * the `mimeType` can be provided in the `params.config` parameter. + * @throws An error occurs if a suitable upload location cannot be established. + * + * @example + * The following code uploads a file to Gemini API. + * + * ```ts + * const file = await ai.files.upload({file: 'file.txt', config: { + * mimeType: 'text/plain', + * }}); + * console.log(file.name); + * ``` + */ + async upload(params) { + if (this.apiClient.isVertexAI()) { + throw new Error('Vertex AI does not support uploading files. You can share files through a GCS bucket.'); + } + return this.apiClient + .uploadFile(params.file, params.config) + .then((resp) => { + return resp; + }); + } + /** + * Downloads a remotely stored file asynchronously to a location specified in + * the `params` object. This method only works on Node environment, to + * download files in the browser, use a browser compliant method like an <a> + * tag. + * + * @param params - The parameters for the download request. + * + * @example + * The following code downloads an example file named "files/mehozpxf877d" as + * "file.txt". + * + * ```ts + * await ai.files.download({file: file.name, downloadPath: 'file.txt'}); + * ``` + */ + async download(params) { + await this.apiClient.downloadFile(params); + } + /** + * Registers Google Cloud Storage files for use with the API. + * This method is only available in Node.js environments. + */ + async registerFiles(params) { + throw new Error('registerFiles is only supported in Node.js environments.'); + } + async _registerFiles(params) { + return this.registerFilesInternal(params); + } + async listInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = listFilesParametersToMldev(params); + path = formatMap('files', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listFilesResponseFromMldev(apiResponse); + const typedResp = new ListFilesResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + async createInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = createFileParametersToMldev(params); + path = formatMap('upload/v1beta/files', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = createFileResponseFromMldev(apiResponse); + const typedResp = new CreateFileResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Retrieves the file information from the service. + * + * @param params - The parameters for the get request + * @return The Promise that resolves to the types.File object requested. + * + * @example + * ```ts + * const config: GetFileParameters = { + * name: fileName, + * }; + * file = await ai.files.get(config); + * console.log(file.name); + * ``` + */ + async get(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = getFileParametersToMldev(params); + path = formatMap('files/{file}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } + /** + * Deletes a remotely stored file. + * + * @param params - The parameters for the delete request. + * @return The DeleteFileResponse, the response for the delete method. + * + * @example + * The following code deletes an example file named "files/mehozpxf877d". + * + * ```ts + * await ai.files.delete({name: file.name}); + * ``` + */ + async delete(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = deleteFileParametersToMldev(params); + path = formatMap('files/{file}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = deleteFileResponseFromMldev(apiResponse); + const typedResp = new DeleteFileResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + async registerFilesInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = internalRegisterFilesParametersToMldev(params); + path = formatMap('files:register', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = registerFilesResponseFromMldev(apiResponse); + const typedResp = new RegisterFilesResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Code generated by the Google Gen AI SDK generator DO NOT EDIT. +function deleteDocumentConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromForce = getValueByPath(fromObject, ['force']); + if (parentObject !== undefined && fromForce != null) { + setValueByPath(parentObject, ['_query', 'force'], fromForce); + } + return toObject; +} +function deleteDocumentParametersToMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + deleteDocumentConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function getDocumentParametersToMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + return toObject; +} +function listDocumentsConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + return toObject; +} +function listDocumentsParametersToMldev(fromObject) { + const toObject = {}; + const fromParent = getValueByPath(fromObject, ['parent']); + if (fromParent != null) { + setValueByPath(toObject, ['_url', 'parent'], fromParent); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listDocumentsConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function listDocumentsResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromDocuments = getValueByPath(fromObject, ['documents']); + if (fromDocuments != null) { + let transformedList = fromDocuments; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['documents'], transformedList); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Documents extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + /** + * Lists documents. + * + * @param params - The parameters for the list request. + * @return - A pager of documents. + * + * @example + * ```ts + * const documents = await ai.documents.list({parent:'rag_store_name', config: {'pageSize': 2}}); + * for await (const document of documents) { + * console.log(document); + * } + * ``` + */ + this.list = async (params) => { + return new Pager(PagedItem.PAGED_ITEM_DOCUMENTS, (x) => this.listInternal({ parent: params.parent, config: x.config }), await this.listInternal(params), params); + }; + } + /** + * Gets a Document. + * + * @param params - The parameters for getting a document. + * @return Document. + */ + async get(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = getDocumentParametersToMldev(params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } + /** + * Deletes a Document. + * + * @param params - The parameters for deleting a document. + */ + async delete(params) { + var _a, _b; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = deleteDocumentParametersToMldev(params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + await this.apiClient.request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }); + } + } + async listInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = listDocumentsParametersToMldev(params); + path = formatMap('{parent}/documents', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = listDocumentsResponseFromMldev(apiResponse); + const typedResp = new ListDocumentsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class FileSearchStores extends BaseModule { + constructor(apiClient, documents = new Documents(apiClient)) { + super(); + this.apiClient = apiClient; + this.documents = documents; + /** + * Lists file search stores. + * + * @param params - The parameters for the list request. + * @return - A pager of file search stores. + * + * @example + * ```ts + * const fileSearchStores = await ai.fileSearchStores.list({config: {'pageSize': 2}}); + * for await (const fileSearchStore of fileSearchStores) { + * console.log(fileSearchStore); + * } + * ``` + */ + this.list = async (params = {}) => { + return new Pager(PagedItem.PAGED_ITEM_FILE_SEARCH_STORES, (x) => this.listInternal(x), await this.listInternal(params), params); + }; + } + /** + * Uploads a file asynchronously to a given File Search Store. + * This method is not available in Vertex AI. + * Supported upload sources: + * - Node.js: File path (string) or Blob object. + * - Browser: Blob object (e.g., File). + * + * @remarks + * The `mimeType` can be specified in the `config` parameter. If omitted: + * - For file path (string) inputs, the `mimeType` will be inferred from the + * file extension. + * - For Blob object inputs, the `mimeType` will be set to the Blob's `type` + * property. + * + * This section can contain multiple paragraphs and code examples. + * + * @param params - Optional parameters specified in the + * `types.UploadToFileSearchStoreParameters` interface. + * @see {@link types.UploadToFileSearchStoreParameters#config} for the optional + * config in the parameters. + * @return A promise that resolves to a long running operation. + * @throws An error if called on a Vertex AI client. + * @throws An error if the `mimeType` is not provided and can not be inferred, + * the `mimeType` can be provided in the `params.config` parameter. + * @throws An error occurs if a suitable upload location cannot be established. + * + * @example + * The following code uploads a file to a given file search store. + * + * ```ts + * const operation = await ai.fileSearchStores.upload({fileSearchStoreName: 'fileSearchStores/foo-bar', file: 'file.txt', config: { + * mimeType: 'text/plain', + * }}); + * console.log(operation.name); + * ``` + */ + async uploadToFileSearchStore(params) { + if (this.apiClient.isVertexAI()) { + throw new Error('Vertex AI does not support uploading files to a file search store.'); + } + return this.apiClient.uploadFileToFileSearchStore(params.fileSearchStoreName, params.file, params.config); + } + /** + * Creates a File Search Store. + * + * @param params - The parameters for creating a File Search Store. + * @return FileSearchStore. + */ + async create(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = createFileSearchStoreParametersToMldev(params); + path = formatMap('fileSearchStores', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } + /** + * Gets a File Search Store. + * + * @param params - The parameters for getting a File Search Store. + * @return FileSearchStore. + */ + async get(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = getFileSearchStoreParametersToMldev(params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } + /** + * Deletes a File Search Store. + * + * @param params - The parameters for deleting a File Search Store. + */ + async delete(params) { + var _a, _b; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = deleteFileSearchStoreParametersToMldev(params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + await this.apiClient.request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }); + } + } + async listInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = listFileSearchStoresParametersToMldev(params); + path = formatMap('fileSearchStores', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = listFileSearchStoresResponseFromMldev(apiResponse); + const typedResp = new ListFileSearchStoresResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + async uploadToFileSearchStoreInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = uploadToFileSearchStoreParametersToMldev(params); + path = formatMap('upload/v1beta/{file_search_store_name}:uploadToFileSearchStore', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = uploadToFileSearchStoreResumableResponseFromMldev(apiResponse); + const typedResp = new UploadToFileSearchStoreResumableResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Imports a File from File Service to a FileSearchStore. + * + * This is a long-running operation, see aip.dev/151 + * + * @param params - The parameters for importing a file to a file search store. + * @return ImportFileOperation. + */ + async importFile(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = importFileParametersToMldev(params); + path = formatMap('{file_search_store_name}:importFile', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = importFileOperationFromMldev(apiResponse); + const typedResp = new ImportFileOperation(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +/** + * https://stackoverflow.com/a/2117523 + */ +let uuid4Internal = function () { + const { crypto } = globalThis; + if (crypto === null || crypto === void 0 ? void 0 : crypto.randomUUID) { + uuid4Internal = crypto.randomUUID.bind(crypto); + return crypto.randomUUID(); + } + const u8 = new Uint8Array(1); + const randomByte = crypto ? () => crypto.getRandomValues(u8)[0] : () => (Math.random() * 0xff) & 0xff; + return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, (c) => (+c ^ (randomByte() & (15 >> (+c / 4)))).toString(16)); +}; +const uuid4 = () => uuid4Internal(); + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +function isAbortError(err) { + return (typeof err === 'object' && + err !== null && + // Spec-compliant fetch implementations + (('name' in err && err.name === 'AbortError') || + // Expo fetch + ('message' in err && String(err.message).includes('FetchRequestCanceledException')))); +} +const castToError = (err) => { + if (err instanceof Error) + return err; + if (typeof err === 'object' && err !== null) { + try { + if (Object.prototype.toString.call(err) === '[object Error]') { + // @ts-ignore - not all envs have native support for cause yet + const error = new Error(err.message, err.cause ? { cause: err.cause } : {}); + if (err.stack) + error.stack = err.stack; + // @ts-ignore - not all envs have native support for cause yet + if (err.cause && !error.cause) + error.cause = err.cause; + if (err.name) + error.name = err.name; + return error; + } + } + catch (_a) { } + try { + return new Error(JSON.stringify(err)); + } + catch (_b) { } + } + return new Error(err); +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +class GeminiNextGenAPIClientError extends Error { +} +class APIError extends GeminiNextGenAPIClientError { + constructor(status, error, message, headers) { + super(`${APIError.makeMessage(status, error, message)}`); + this.status = status; + this.headers = headers; + this.error = error; + } + static makeMessage(status, error, message) { + const msg = (error === null || error === void 0 ? void 0 : error.message) ? + typeof error.message === 'string' ? + error.message + : JSON.stringify(error.message) + : error ? JSON.stringify(error) + : message; + if (status && msg) { + return `${status} ${msg}`; + } + if (status) { + return `${status} status code (no body)`; + } + if (msg) { + return msg; + } + return '(no status code or body)'; + } + static generate(status, errorResponse, message, headers) { + if (!status || !headers) { + return new APIConnectionError({ message, cause: castToError(errorResponse) }); + } + const error = errorResponse; + if (status === 400) { + return new BadRequestError(status, error, message, headers); + } + if (status === 401) { + return new AuthenticationError(status, error, message, headers); + } + if (status === 403) { + return new PermissionDeniedError(status, error, message, headers); + } + if (status === 404) { + return new NotFoundError(status, error, message, headers); + } + if (status === 409) { + return new ConflictError(status, error, message, headers); + } + if (status === 422) { + return new UnprocessableEntityError(status, error, message, headers); + } + if (status === 429) { + return new RateLimitError(status, error, message, headers); + } + if (status >= 500) { + return new InternalServerError(status, error, message, headers); + } + return new APIError(status, error, message, headers); + } +} +class APIUserAbortError extends APIError { + constructor({ message } = {}) { + super(undefined, undefined, message || 'Request was aborted.', undefined); + } +} +class APIConnectionError extends APIError { + constructor({ message, cause }) { + super(undefined, undefined, message || 'Connection error.', undefined); + // in some environments the 'cause' property is already declared + // @ts-ignore + if (cause) + this.cause = cause; + } +} +class APIConnectionTimeoutError extends APIConnectionError { + constructor({ message } = {}) { + super({ message: message !== null && message !== void 0 ? message : 'Request timed out.' }); + } +} +class BadRequestError extends APIError { +} +class AuthenticationError extends APIError { +} +class PermissionDeniedError extends APIError { +} +class NotFoundError extends APIError { +} +class ConflictError extends APIError { +} +class UnprocessableEntityError extends APIError { +} +class RateLimitError extends APIError { +} +class InternalServerError extends APIError { +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +// https://url.spec.whatwg.org/#url-scheme-string +const startsWithSchemeRegexp = /^[a-z][a-z0-9+.-]*:/i; +const isAbsoluteURL = (url) => { + return startsWithSchemeRegexp.test(url); +}; +let isArrayInternal = (val) => ((isArrayInternal = Array.isArray), isArrayInternal(val)); +const isArray = isArrayInternal; +let isReadonlyArrayInternal = isArray; +const isReadonlyArray = isReadonlyArrayInternal; +// https://stackoverflow.com/a/34491287 +function isEmptyObj(obj) { + if (!obj) + return true; + for (const _k in obj) + return false; + return true; +} +// https://eslint.org/docs/latest/rules/no-prototype-builtins +function hasOwn(obj, key) { + return Object.prototype.hasOwnProperty.call(obj, key); +} +const validatePositiveInteger = (name, n) => { + if (typeof n !== 'number' || !Number.isInteger(n)) { + throw new GeminiNextGenAPIClientError(`${name} must be an integer`); + } + if (n < 0) { + throw new GeminiNextGenAPIClientError(`${name} must be a positive integer`); + } + return n; +}; +const safeJSON = (text) => { + try { + return JSON.parse(text); + } + catch (err) { + return undefined; + } +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const VERSION = '0.0.1'; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +/** + * Note this does not detect 'browser'; for that, use getBrowserInfo(). + */ +function getDetectedPlatform() { + if (typeof Deno !== 'undefined' && Deno.build != null) { + return 'deno'; + } + if (typeof EdgeRuntime !== 'undefined') { + return 'edge'; + } + if (Object.prototype.toString.call(typeof globalThis.process !== 'undefined' ? globalThis.process : 0) === '[object process]') { + return 'node'; + } + return 'unknown'; +} +const getPlatformProperties = () => { + var _a, _b, _c, _d, _e; + const detectedPlatform = getDetectedPlatform(); + if (detectedPlatform === 'deno') { + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': VERSION, + 'X-Stainless-OS': normalizePlatform(Deno.build.os), + 'X-Stainless-Arch': normalizeArch(Deno.build.arch), + 'X-Stainless-Runtime': 'deno', + 'X-Stainless-Runtime-Version': typeof Deno.version === 'string' ? Deno.version : (_b = (_a = Deno.version) === null || _a === void 0 ? void 0 : _a.deno) !== null && _b !== void 0 ? _b : 'unknown', + }; + } + if (typeof EdgeRuntime !== 'undefined') { + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': VERSION, + 'X-Stainless-OS': 'Unknown', + 'X-Stainless-Arch': `other:${EdgeRuntime}`, + 'X-Stainless-Runtime': 'edge', + 'X-Stainless-Runtime-Version': globalThis.process.version, + }; + } + // Check if Node.js + if (detectedPlatform === 'node') { + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': VERSION, + 'X-Stainless-OS': normalizePlatform((_c = globalThis.process.platform) !== null && _c !== void 0 ? _c : 'unknown'), + 'X-Stainless-Arch': normalizeArch((_d = globalThis.process.arch) !== null && _d !== void 0 ? _d : 'unknown'), + 'X-Stainless-Runtime': 'node', + 'X-Stainless-Runtime-Version': (_e = globalThis.process.version) !== null && _e !== void 0 ? _e : 'unknown', + }; + } + const browserInfo = getBrowserInfo(); + if (browserInfo) { + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': VERSION, + 'X-Stainless-OS': 'Unknown', + 'X-Stainless-Arch': 'unknown', + 'X-Stainless-Runtime': `browser:${browserInfo.browser}`, + 'X-Stainless-Runtime-Version': browserInfo.version, + }; + } + // TODO add support for Cloudflare workers, etc. + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': VERSION, + 'X-Stainless-OS': 'Unknown', + 'X-Stainless-Arch': 'unknown', + 'X-Stainless-Runtime': 'unknown', + 'X-Stainless-Runtime-Version': 'unknown', + }; +}; +// Note: modified from https://github.com/JS-DevTools/host-environment/blob/b1ab79ecde37db5d6e163c050e54fe7d287d7c92/src/isomorphic.browser.ts +function getBrowserInfo() { + if (typeof navigator === 'undefined' || !navigator) { + return null; + } + // NOTE: The order matters here! + const browserPatterns = [ + { key: 'edge', pattern: /Edge(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'ie', pattern: /MSIE(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'ie', pattern: /Trident(?:.*rv\:(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'chrome', pattern: /Chrome(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'firefox', pattern: /Firefox(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'safari', pattern: /(?:Version\W+(\d+)\.(\d+)(?:\.(\d+))?)?(?:\W+Mobile\S*)?\W+Safari/ }, + ]; + // Find the FIRST matching browser + for (const { key, pattern } of browserPatterns) { + const match = pattern.exec(navigator.userAgent); + if (match) { + const major = match[1] || 0; + const minor = match[2] || 0; + const patch = match[3] || 0; + return { browser: key, version: `${major}.${minor}.${patch}` }; + } + } + return null; +} +const normalizeArch = (arch) => { + // Node docs: + // - https://nodejs.org/api/process.html#processarch + // Deno docs: + // - https://doc.deno.land/deno/stable/~/Deno.build + if (arch === 'x32') + return 'x32'; + if (arch === 'x86_64' || arch === 'x64') + return 'x64'; + if (arch === 'arm') + return 'arm'; + if (arch === 'aarch64' || arch === 'arm64') + return 'arm64'; + if (arch) + return `other:${arch}`; + return 'unknown'; +}; +const normalizePlatform = (platform) => { + // Node platforms: + // - https://nodejs.org/api/process.html#processplatform + // Deno platforms: + // - https://doc.deno.land/deno/stable/~/Deno.build + // - https://github.com/denoland/deno/issues/14799 + platform = platform.toLowerCase(); + // NOTE: this iOS check is untested and may not work + // Node does not work natively on IOS, there is a fork at + // https://github.com/nodejs-mobile/nodejs-mobile + // however it is unknown at the time of writing how to detect if it is running + if (platform.includes('ios')) + return 'iOS'; + if (platform === 'android') + return 'Android'; + if (platform === 'darwin') + return 'MacOS'; + if (platform === 'win32') + return 'Windows'; + if (platform === 'freebsd') + return 'FreeBSD'; + if (platform === 'openbsd') + return 'OpenBSD'; + if (platform === 'linux') + return 'Linux'; + if (platform) + return `Other:${platform}`; + return 'Unknown'; +}; +let _platformHeaders; +const getPlatformHeaders = () => { + return (_platformHeaders !== null && _platformHeaders !== void 0 ? _platformHeaders : (_platformHeaders = getPlatformProperties())); +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function getDefaultFetch() { + if (typeof fetch !== 'undefined') { + return fetch; + } + throw new Error('`fetch` is not defined as a global; Either pass `fetch` to the client, `new GeminiNextGenAPIClient({ fetch })` or polyfill the global, `globalThis.fetch = fetch`'); +} +function makeReadableStream(...args) { + const ReadableStream = globalThis.ReadableStream; + if (typeof ReadableStream === 'undefined') { + // Note: All of the platforms / runtimes we officially support already define + // `ReadableStream` as a global, so this should only ever be hit on unsupported runtimes. + throw new Error('`ReadableStream` is not defined as a global; You will need to polyfill it, `globalThis.ReadableStream = ReadableStream`'); + } + return new ReadableStream(...args); +} +function ReadableStreamFrom(iterable) { + let iter = Symbol.asyncIterator in iterable ? iterable[Symbol.asyncIterator]() : iterable[Symbol.iterator](); + return makeReadableStream({ + start() { }, + async pull(controller) { + const { done, value } = await iter.next(); + if (done) { + controller.close(); + } + else { + controller.enqueue(value); + } + }, + async cancel() { + var _a; + await ((_a = iter.return) === null || _a === void 0 ? void 0 : _a.call(iter)); + }, + }); +} +/** + * Most browsers don't yet have async iterable support for ReadableStream, + * and Node has a very different way of reading bytes from its "ReadableStream". + * + * This polyfill was pulled from https://github.com/MattiasBuelens/web-streams-polyfill/pull/122#issuecomment-1627354490 + */ +function ReadableStreamToAsyncIterable(stream) { + if (stream[Symbol.asyncIterator]) + return stream; + const reader = stream.getReader(); + return { + async next() { + try { + const result = await reader.read(); + if (result === null || result === void 0 ? void 0 : result.done) + reader.releaseLock(); // release lock when stream becomes closed + return result; + } + catch (e) { + reader.releaseLock(); // release lock when stream becomes errored + throw e; + } + }, + async return() { + const cancelPromise = reader.cancel(); + reader.releaseLock(); + await cancelPromise; + return { done: true, value: undefined }; + }, + [Symbol.asyncIterator]() { + return this; + }, + }; +} +/** + * Cancels a ReadableStream we don't need to consume. + * See https://undici.nodejs.org/#/?id=garbage-collection + */ +async function CancelReadableStream(stream) { + var _a, _b; + if (stream === null || typeof stream !== 'object') + return; + if (stream[Symbol.asyncIterator]) { + await ((_b = (_a = stream[Symbol.asyncIterator]()).return) === null || _b === void 0 ? void 0 : _b.call(_a)); + return; + } + const reader = stream.getReader(); + const cancelPromise = reader.cancel(); + reader.releaseLock(); + await cancelPromise; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const FallbackEncoder = ({ headers, body }) => { + return { + bodyHeaders: { + 'content-type': 'application/json', + }, + body: JSON.stringify(body), + }; +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const checkFileSupport = () => { + var _a; + if (typeof File === 'undefined') { + const { process } = globalThis; + const isOldNode = typeof ((_a = process === null || process === void 0 ? void 0 : process.versions) === null || _a === void 0 ? void 0 : _a.node) === 'string' && parseInt(process.versions.node.split('.')) < 20; + throw new Error('`File` is not defined as a global, which is required for file uploads.' + + (isOldNode ? + " Update to Node 20 LTS or newer, or set `globalThis.File` to `import('node:buffer').File`." + : '')); + } +}; +/** + * Construct a `File` instance. This is used to ensure a helpful error is thrown + * for environments that don't define a global `File` yet. + */ +function makeFile(fileBits, fileName, options) { + checkFileSupport(); + return new File(fileBits, fileName !== null && fileName !== void 0 ? fileName : 'unknown_file', options); +} +function getName(value) { + return (((typeof value === 'object' && + value !== null && + (('name' in value && value.name && String(value.name)) || + ('url' in value && value.url && String(value.url)) || + ('filename' in value && value.filename && String(value.filename)) || + ('path' in value && value.path && String(value.path)))) || + '') + .split(/[\\/]/) + .pop() || undefined); +} +const isAsyncIterable = (value) => value != null && typeof value === 'object' && typeof value[Symbol.asyncIterator] === 'function'; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * This check adds the arrayBuffer() method type because it is available and used at runtime + */ +const isBlobLike = (value) => value != null && + typeof value === 'object' && + typeof value.size === 'number' && + typeof value.type === 'string' && + typeof value.text === 'function' && + typeof value.slice === 'function' && + typeof value.arrayBuffer === 'function'; +/** + * This check adds the arrayBuffer() method type because it is available and used at runtime + */ +const isFileLike = (value) => value != null && + typeof value === 'object' && + typeof value.name === 'string' && + typeof value.lastModified === 'number' && + isBlobLike(value); +const isResponseLike = (value) => value != null && + typeof value === 'object' && + typeof value.url === 'string' && + typeof value.blob === 'function'; +/** + * Helper for creating a {@link File} to pass to an SDK upload method from a variety of different data formats + * @param value the raw content of the file. Can be an {@link Uploadable}, BlobLikePart, or AsyncIterable of BlobLikeParts + * @param {string=} name the name of the file. If omitted, toFile will try to determine a file name from bits if possible + * @param {Object=} options additional properties + * @param {string=} options.type the MIME type of the content + * @param {number=} options.lastModified the last modified timestamp + * @returns a {@link File} with the given properties + */ +async function toFile(value, name, options) { + checkFileSupport(); + // If it's a promise, resolve it. + value = await value; + // If we've been given a `File` we don't need to do anything + if (isFileLike(value)) { + if (value instanceof File) { + return value; + } + return makeFile([await value.arrayBuffer()], value.name); + } + if (isResponseLike(value)) { + const blob = await value.blob(); + name || (name = new URL(value.url).pathname.split(/[\\/]/).pop()); + return makeFile(await getBytes(blob), name, options); + } + const parts = await getBytes(value); + name || (name = getName(value)); + if (!(options === null || options === void 0 ? void 0 : options.type)) { + const type = parts.find((part) => typeof part === 'object' && 'type' in part && part.type); + if (typeof type === 'string') { + options = Object.assign(Object.assign({}, options), { type }); + } + } + return makeFile(parts, name, options); +} +async function getBytes(value) { + var _a, e_1, _b, _c; + var _d; + let parts = []; + if (typeof value === 'string' || + ArrayBuffer.isView(value) || // includes Uint8Array, Buffer, etc. + value instanceof ArrayBuffer) { + parts.push(value); + } + else if (isBlobLike(value)) { + parts.push(value instanceof Blob ? value : await value.arrayBuffer()); + } + else if (isAsyncIterable(value) // includes Readable, ReadableStream, etc. + ) { + try { + for (var _e = true, value_1 = __asyncValues(value), value_1_1; value_1_1 = await value_1.next(), _a = value_1_1.done, !_a; _e = true) { + _c = value_1_1.value; + _e = false; + const chunk = _c; + parts.push(...(await getBytes(chunk))); // TODO, consider validating? + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (!_e && !_a && (_b = value_1.return)) await _b.call(value_1); + } + finally { if (e_1) throw e_1.error; } + } + } + else { + const constructor = (_d = value === null || value === void 0 ? void 0 : value.constructor) === null || _d === void 0 ? void 0 : _d.name; + throw new Error(`Unexpected data type: ${typeof value}${constructor ? `; constructor: ${constructor}` : ''}${propsForError(value)}`); + } + return parts; +} +function propsForError(value) { + if (typeof value !== 'object' || value === null) + return ''; + const props = Object.getOwnPropertyNames(value); + return `; props: [${props.map((p) => `"${p}"`).join(', ')}]`; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class APIResource { + constructor(client) { + this._client = client; + } +} +/** + * The key path from the client. For example, a resource accessible as `client.resource.subresource` would + * have a property `static override readonly _key = Object.freeze(['resource', 'subresource'] as const);`. + */ +APIResource._key = []; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Percent-encode everything that isn't safe to have in a path without encoding safe chars. + * + * Taken from https://datatracker.ietf.org/doc/html/rfc3986#section-3.3: + * > unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + * > sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" + * > pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + */ +function encodeURIPath(str) { + return str.replace(/[^A-Za-z0-9\-._~!$&'()*+,;=:@]+/g, encodeURIComponent); +} +const EMPTY = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.create(null)); +const createPathTagFunction = (pathEncoder = encodeURIPath) => (function path(statics, ...params) { + // If there are no params, no processing is needed. + if (statics.length === 1) + return statics[0]; + let postPath = false; + const invalidSegments = []; + const path = statics.reduce((previousValue, currentValue, index) => { + var _a, _b, _c; + if (/[?#]/.test(currentValue)) { + postPath = true; + } + const value = params[index]; + let encoded = (postPath ? encodeURIComponent : pathEncoder)('' + value); + if (index !== params.length && + (value == null || + (typeof value === 'object' && + // handle values from other realms + value.toString === + ((_c = Object.getPrototypeOf((_b = Object.getPrototypeOf((_a = value.hasOwnProperty) !== null && _a !== void 0 ? _a : EMPTY)) !== null && _b !== void 0 ? _b : EMPTY)) === null || _c === void 0 ? void 0 : _c.toString)))) { + encoded = value + ''; + invalidSegments.push({ + start: previousValue.length + currentValue.length, + length: encoded.length, + error: `Value of type ${Object.prototype.toString + .call(value) + .slice(8, -1)} is not a valid path parameter`, + }); + } + return previousValue + currentValue + (index === params.length ? '' : encoded); + }, ''); + const pathOnly = path.split(/[?#]/, 1)[0]; + const invalidSegmentPattern = /(?<=^|\/)(?:\.|%2e){1,2}(?=\/|$)/gi; + let match; + // Find all invalid segments + while ((match = invalidSegmentPattern.exec(pathOnly)) !== null) { + invalidSegments.push({ + start: match.index, + length: match[0].length, + error: `Value "${match[0]}" can\'t be safely passed as a path parameter`, + }); + } + invalidSegments.sort((a, b) => a.start - b.start); + if (invalidSegments.length > 0) { + let lastEnd = 0; + const underline = invalidSegments.reduce((acc, segment) => { + const spaces = ' '.repeat(segment.start - lastEnd); + const arrows = '^'.repeat(segment.length); + lastEnd = segment.start + segment.length; + return acc + spaces + arrows; + }, ''); + throw new GeminiNextGenAPIClientError(`Path parameters result in path with invalid segments:\n${invalidSegments + .map((e) => e.error) + .join('\n')}\n${path}\n${underline}`); + } + return path; +}); +/** + * URI-encodes path params and ensures no unsafe /./ or /../ path segments are introduced. + */ +const path = /* @__PURE__ */ createPathTagFunction(encodeURIPath); + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class BaseInteractions extends APIResource { + create(params, options) { + var _a; + const { api_version = this._client.apiVersion } = params, body = __rest(params, ["api_version"]); + if ('model' in body && 'agent_config' in body) { + throw new GeminiNextGenAPIClientError(`Invalid request: specified \`model\` and \`agent_config\`. If specifying \`model\`, use \`generation_config\`.`); + } + if ('agent' in body && 'generation_config' in body) { + throw new GeminiNextGenAPIClientError(`Invalid request: specified \`agent\` and \`generation_config\`. If specifying \`agent\`, use \`agent_config\`.`); + } + return this._client.post(path `/${api_version}/interactions`, Object.assign(Object.assign({ body }, options), { stream: (_a = params.stream) !== null && _a !== void 0 ? _a : false })); + } + /** + * Deletes the interaction by id. + * + * @example + * ```ts + * const interaction = await client.interactions.delete('id', { + * api_version: 'api_version', + * }); + * ``` + */ + delete(id, params = {}, options) { + const { api_version = this._client.apiVersion } = params !== null && params !== void 0 ? params : {}; + return this._client.delete(path `/${api_version}/interactions/${id}`, options); + } + /** + * Cancels an interaction by id. This only applies to background interactions that are still running. + * + * @example + * ```ts + * const interaction = await client.interactions.cancel('id', { + * api_version: 'api_version', + * }); + * ``` + */ + cancel(id, params = {}, options) { + const { api_version = this._client.apiVersion } = params !== null && params !== void 0 ? params : {}; + return this._client.post(path `/${api_version}/interactions/${id}/cancel`, options); + } + get(id, params = {}, options) { + var _a; + const _b = params !== null && params !== void 0 ? params : {}, { api_version = this._client.apiVersion } = _b, query = __rest(_b, ["api_version"]); + return this._client.get(path `/${api_version}/interactions/${id}`, Object.assign(Object.assign({ query }, options), { stream: (_a = params === null || params === void 0 ? void 0 : params.stream) !== null && _a !== void 0 ? _a : false })); + } +} +BaseInteractions._key = Object.freeze(['interactions']); +class Interactions extends BaseInteractions { +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function concatBytes(buffers) { + let length = 0; + for (const buffer of buffers) { + length += buffer.length; + } + const output = new Uint8Array(length); + let index = 0; + for (const buffer of buffers) { + output.set(buffer, index); + index += buffer.length; + } + return output; +} +let encodeUTF8_; +function encodeUTF8(str) { + let encoder; + return (encodeUTF8_ !== null && encodeUTF8_ !== void 0 ? encodeUTF8_ : ((encoder = new globalThis.TextEncoder()), (encodeUTF8_ = encoder.encode.bind(encoder))))(str); +} +let decodeUTF8_; +function decodeUTF8(bytes) { + let decoder; + return (decodeUTF8_ !== null && decodeUTF8_ !== void 0 ? decodeUTF8_ : ((decoder = new globalThis.TextDecoder()), (decodeUTF8_ = decoder.decode.bind(decoder))))(bytes); +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * A re-implementation of httpx's `LineDecoder` in Python that handles incrementally + * reading lines from text. + * + * https://github.com/encode/httpx/blob/920333ea98118e9cf617f246905d7b202510941c/httpx/_decoders.py#L258 + */ +class LineDecoder { + constructor() { + this.buffer = new Uint8Array(); + this.carriageReturnIndex = null; + } + decode(chunk) { + if (chunk == null) { + return []; + } + const binaryChunk = chunk instanceof ArrayBuffer ? new Uint8Array(chunk) + : typeof chunk === 'string' ? encodeUTF8(chunk) + : chunk; + this.buffer = concatBytes([this.buffer, binaryChunk]); + const lines = []; + let patternIndex; + while ((patternIndex = findNewlineIndex(this.buffer, this.carriageReturnIndex)) != null) { + if (patternIndex.carriage && this.carriageReturnIndex == null) { + // skip until we either get a corresponding `\n`, a new `\r` or nothing + this.carriageReturnIndex = patternIndex.index; + continue; + } + // we got double \r or \rtext\n + if (this.carriageReturnIndex != null && + (patternIndex.index !== this.carriageReturnIndex + 1 || patternIndex.carriage)) { + lines.push(decodeUTF8(this.buffer.subarray(0, this.carriageReturnIndex - 1))); + this.buffer = this.buffer.subarray(this.carriageReturnIndex); + this.carriageReturnIndex = null; + continue; + } + const endIndex = this.carriageReturnIndex !== null ? patternIndex.preceding - 1 : patternIndex.preceding; + const line = decodeUTF8(this.buffer.subarray(0, endIndex)); + lines.push(line); + this.buffer = this.buffer.subarray(patternIndex.index); + this.carriageReturnIndex = null; + } + return lines; + } + flush() { + if (!this.buffer.length) { + return []; + } + return this.decode('\n'); + } +} +// prettier-ignore +LineDecoder.NEWLINE_CHARS = new Set(['\n', '\r']); +LineDecoder.NEWLINE_REGEXP = /\r\n|[\n\r]/g; +/** + * This function searches the buffer for the end patterns, (\r or \n) + * and returns an object with the index preceding the matched newline and the + * index after the newline char. `null` is returned if no new line is found. + * + * ```ts + * findNewLineIndex('abc\ndef') -> { preceding: 2, index: 3 } + * ``` + */ +function findNewlineIndex(buffer, startIndex) { + const newline = 0x0a; // \n + const carriage = 0x0d; // \r + for (let i = startIndex !== null && startIndex !== void 0 ? startIndex : 0; i < buffer.length; i++) { + if (buffer[i] === newline) { + return { preceding: i, index: i + 1, carriage: false }; + } + if (buffer[i] === carriage) { + return { preceding: i, index: i + 1, carriage: true }; + } + } + return null; +} +function findDoubleNewlineIndex(buffer) { + // This function searches the buffer for the end patterns (\r\r, \n\n, \r\n\r\n) + // and returns the index right after the first occurrence of any pattern, + // or -1 if none of the patterns are found. + const newline = 0x0a; // \n + const carriage = 0x0d; // \r + for (let i = 0; i < buffer.length - 1; i++) { + if (buffer[i] === newline && buffer[i + 1] === newline) { + // \n\n + return i + 2; + } + if (buffer[i] === carriage && buffer[i + 1] === carriage) { + // \r\r + return i + 2; + } + if (buffer[i] === carriage && + buffer[i + 1] === newline && + i + 3 < buffer.length && + buffer[i + 2] === carriage && + buffer[i + 3] === newline) { + // \r\n\r\n + return i + 4; + } + } + return -1; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +const levelNumbers = { + off: 0, + error: 200, + warn: 300, + info: 400, + debug: 500, +}; +const parseLogLevel = (maybeLevel, sourceName, client) => { + if (!maybeLevel) { + return undefined; + } + if (hasOwn(levelNumbers, maybeLevel)) { + return maybeLevel; + } + loggerFor(client).warn(`${sourceName} was set to ${JSON.stringify(maybeLevel)}, expected one of ${JSON.stringify(Object.keys(levelNumbers))}`); + return undefined; +}; +function noop() { } +function makeLogFn(fnLevel, logger, logLevel) { + if (!logger || levelNumbers[fnLevel] > levelNumbers[logLevel]) { + return noop; + } + else { + // Don't wrap logger functions, we want the stacktrace intact! + return logger[fnLevel].bind(logger); + } +} +const noopLogger = { + error: noop, + warn: noop, + info: noop, + debug: noop, +}; +let cachedLoggers = /* @__PURE__ */ new WeakMap(); +function loggerFor(client) { + var _a; + const logger = client.logger; + const logLevel = (_a = client.logLevel) !== null && _a !== void 0 ? _a : 'off'; + if (!logger) { + return noopLogger; + } + const cachedLogger = cachedLoggers.get(logger); + if (cachedLogger && cachedLogger[0] === logLevel) { + return cachedLogger[1]; + } + const levelLogger = { + error: makeLogFn('error', logger, logLevel), + warn: makeLogFn('warn', logger, logLevel), + info: makeLogFn('info', logger, logLevel), + debug: makeLogFn('debug', logger, logLevel), + }; + cachedLoggers.set(logger, [logLevel, levelLogger]); + return levelLogger; +} +const formatRequestDetails = (details) => { + if (details.options) { + details.options = Object.assign({}, details.options); + delete details.options['headers']; // redundant + leaks internals + } + if (details.headers) { + details.headers = Object.fromEntries((details.headers instanceof Headers ? [...details.headers] : Object.entries(details.headers)).map(([name, value]) => [ + name, + (name.toLowerCase() === 'x-goog-api-key' || + name.toLowerCase() === 'authorization' || + name.toLowerCase() === 'cookie' || + name.toLowerCase() === 'set-cookie') ? + '***' + : value, + ])); + } + if ('retryOfRequestLogID' in details) { + if (details.retryOfRequestLogID) { + details.retryOf = details.retryOfRequestLogID; + } + delete details.retryOfRequestLogID; + } + return details; +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Stream { + constructor(iterator, controller, client) { + this.iterator = iterator; + this.controller = controller; + this.client = client; + } + static fromSSEResponse(response, controller, client) { + let consumed = false; + const logger = client ? loggerFor(client) : console; + function iterator() { + return __asyncGenerator(this, arguments, function* iterator_1() { + var _a, e_1, _b, _c; + if (consumed) { + throw new GeminiNextGenAPIClientError('Cannot iterate over a consumed stream, use `.tee()` to split the stream.'); + } + consumed = true; + let done = false; + try { + try { + for (var _d = true, _e = __asyncValues(_iterSSEMessages(response, controller)), _f; _f = yield __await(_e.next()), _a = _f.done, !_a; _d = true) { + _c = _f.value; + _d = false; + const sse = _c; + if (done) + continue; + if (sse.data.startsWith('[DONE]')) { + done = true; + continue; + } + else { + try { + // @ts-ignore + yield yield __await(JSON.parse(sse.data)); + } + catch (e) { + logger.error(`Could not parse message into JSON:`, sse.data); + logger.error(`From chunk:`, sse.raw); + throw e; + } + } + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (!_d && !_a && (_b = _e.return)) yield __await(_b.call(_e)); + } + finally { if (e_1) throw e_1.error; } + } + done = true; + } + catch (e) { + // If the user calls `stream.controller.abort()`, we should exit without throwing. + if (isAbortError(e)) + return yield __await(void 0); + throw e; + } + finally { + // If the user `break`s, abort the ongoing request. + if (!done) + controller.abort(); + } + }); + } + return new Stream(iterator, controller, client); + } + /** + * Generates a Stream from a newline-separated ReadableStream + * where each item is a JSON value. + */ + static fromReadableStream(readableStream, controller, client) { + let consumed = false; + function iterLines() { + return __asyncGenerator(this, arguments, function* iterLines_1() { + var _a, e_2, _b, _c; + const lineDecoder = new LineDecoder(); + const iter = ReadableStreamToAsyncIterable(readableStream); + try { + for (var _d = true, iter_1 = __asyncValues(iter), iter_1_1; iter_1_1 = yield __await(iter_1.next()), _a = iter_1_1.done, !_a; _d = true) { + _c = iter_1_1.value; + _d = false; + const chunk = _c; + for (const line of lineDecoder.decode(chunk)) { + yield yield __await(line); + } + } + } + catch (e_2_1) { e_2 = { error: e_2_1 }; } + finally { + try { + if (!_d && !_a && (_b = iter_1.return)) yield __await(_b.call(iter_1)); + } + finally { if (e_2) throw e_2.error; } + } + for (const line of lineDecoder.flush()) { + yield yield __await(line); + } + }); + } + function iterator() { + return __asyncGenerator(this, arguments, function* iterator_2() { + var _a, e_3, _b, _c; + if (consumed) { + throw new GeminiNextGenAPIClientError('Cannot iterate over a consumed stream, use `.tee()` to split the stream.'); + } + consumed = true; + let done = false; + try { + try { + for (var _d = true, _e = __asyncValues(iterLines()), _f; _f = yield __await(_e.next()), _a = _f.done, !_a; _d = true) { + _c = _f.value; + _d = false; + const line = _c; + if (done) + continue; + // @ts-ignore + if (line) + yield yield __await(JSON.parse(line)); + } + } + catch (e_3_1) { e_3 = { error: e_3_1 }; } + finally { + try { + if (!_d && !_a && (_b = _e.return)) yield __await(_b.call(_e)); + } + finally { if (e_3) throw e_3.error; } + } + done = true; + } + catch (e) { + // If the user calls `stream.controller.abort()`, we should exit without throwing. + if (isAbortError(e)) + return yield __await(void 0); + throw e; + } + finally { + // If the user `break`s, abort the ongoing request. + if (!done) + controller.abort(); + } + }); + } + return new Stream(iterator, controller, client); + } + [Symbol.asyncIterator]() { + return this.iterator(); + } + /** + * Splits the stream into two streams which can be + * independently read from at different speeds. + */ + tee() { + const left = []; + const right = []; + const iterator = this.iterator(); + const teeIterator = (queue) => { + return { + next: () => { + if (queue.length === 0) { + const result = iterator.next(); + left.push(result); + right.push(result); + } + return queue.shift(); + }, + }; + }; + return [ + new Stream(() => teeIterator(left), this.controller, this.client), + new Stream(() => teeIterator(right), this.controller, this.client), + ]; + } + /** + * Converts this stream to a newline-separated ReadableStream of + * JSON stringified values in the stream + * which can be turned back into a Stream with `Stream.fromReadableStream()`. + */ + toReadableStream() { + const self = this; + let iter; + return makeReadableStream({ + async start() { + iter = self[Symbol.asyncIterator](); + }, + async pull(ctrl) { + try { + const { value, done } = await iter.next(); + if (done) + return ctrl.close(); + const bytes = encodeUTF8(JSON.stringify(value) + '\n'); + ctrl.enqueue(bytes); + } + catch (err) { + ctrl.error(err); + } + }, + async cancel() { + var _a; + await ((_a = iter.return) === null || _a === void 0 ? void 0 : _a.call(iter)); + }, + }); + } +} +function _iterSSEMessages(response, controller) { + return __asyncGenerator(this, arguments, function* _iterSSEMessages_1() { + var _a, e_4, _b, _c; + if (!response.body) { + controller.abort(); + if (typeof globalThis.navigator !== 'undefined' && + globalThis.navigator.product === 'ReactNative') { + throw new GeminiNextGenAPIClientError(`The default react-native fetch implementation does not support streaming. Please use expo/fetch: https://docs.expo.dev/versions/latest/sdk/expo/#expofetch-api`); + } + throw new GeminiNextGenAPIClientError(`Attempted to iterate over a response with no body`); + } + const sseDecoder = new SSEDecoder(); + const lineDecoder = new LineDecoder(); + const iter = ReadableStreamToAsyncIterable(response.body); + try { + for (var _d = true, _e = __asyncValues(iterSSEChunks(iter)), _f; _f = yield __await(_e.next()), _a = _f.done, !_a; _d = true) { + _c = _f.value; + _d = false; + const sseChunk = _c; + for (const line of lineDecoder.decode(sseChunk)) { + const sse = sseDecoder.decode(line); + if (sse) + yield yield __await(sse); + } + } + } + catch (e_4_1) { e_4 = { error: e_4_1 }; } + finally { + try { + if (!_d && !_a && (_b = _e.return)) yield __await(_b.call(_e)); + } + finally { if (e_4) throw e_4.error; } + } + for (const line of lineDecoder.flush()) { + const sse = sseDecoder.decode(line); + if (sse) + yield yield __await(sse); + } + }); +} +/** + * Given an async iterable iterator, iterates over it and yields full + * SSE chunks, i.e. yields when a double new-line is encountered. + */ +function iterSSEChunks(iterator) { + return __asyncGenerator(this, arguments, function* iterSSEChunks_1() { + var _a, e_5, _b, _c; + let data = new Uint8Array(); + try { + for (var _d = true, iterator_3 = __asyncValues(iterator), iterator_3_1; iterator_3_1 = yield __await(iterator_3.next()), _a = iterator_3_1.done, !_a; _d = true) { + _c = iterator_3_1.value; + _d = false; + const chunk = _c; + if (chunk == null) { + continue; + } + const binaryChunk = chunk instanceof ArrayBuffer ? new Uint8Array(chunk) + : typeof chunk === 'string' ? encodeUTF8(chunk) + : chunk; + let newData = new Uint8Array(data.length + binaryChunk.length); + newData.set(data); + newData.set(binaryChunk, data.length); + data = newData; + let patternIndex; + while ((patternIndex = findDoubleNewlineIndex(data)) !== -1) { + yield yield __await(data.slice(0, patternIndex)); + data = data.slice(patternIndex); + } + } + } + catch (e_5_1) { e_5 = { error: e_5_1 }; } + finally { + try { + if (!_d && !_a && (_b = iterator_3.return)) yield __await(_b.call(iterator_3)); + } + finally { if (e_5) throw e_5.error; } + } + if (data.length > 0) { + yield yield __await(data); + } + }); +} +class SSEDecoder { + constructor() { + this.event = null; + this.data = []; + this.chunks = []; + } + decode(line) { + if (line.endsWith('\r')) { + line = line.substring(0, line.length - 1); + } + if (!line) { + // empty line and we didn't previously encounter any messages + if (!this.event && !this.data.length) + return null; + const sse = { + event: this.event, + data: this.data.join('\n'), + raw: this.chunks, + }; + this.event = null; + this.data = []; + this.chunks = []; + return sse; + } + this.chunks.push(line); + if (line.startsWith(':')) { + return null; + } + let [fieldname, _, value] = partition(line, ':'); + if (value.startsWith(' ')) { + value = value.substring(1); + } + if (fieldname === 'event') { + this.event = value; + } + else if (fieldname === 'data') { + this.data.push(value); + } + return null; + } +} +function partition(str, delimiter) { + const index = str.indexOf(delimiter); + if (index !== -1) { + return [str.substring(0, index), delimiter, str.substring(index + delimiter.length)]; + } + return [str, '', '']; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +async function defaultParseResponse(client, props) { + const { response, requestLogID, retryOfRequestLogID, startTime } = props; + const body = await (async () => { + var _a; + if (props.options.stream) { + loggerFor(client).debug('response', response.status, response.url, response.headers, response.body); + // Note: there is an invariant here that isn't represented in the type system + // that if you set `stream: true` the response type must also be `Stream<T>` + if (props.options.__streamClass) { + return props.options.__streamClass.fromSSEResponse(response, props.controller, client); + } + return Stream.fromSSEResponse(response, props.controller, client); + } + // fetch refuses to read the body when the status code is 204. + if (response.status === 204) { + return null; + } + if (props.options.__binaryResponse) { + return response; + } + const contentType = response.headers.get('content-type'); + const mediaType = (_a = contentType === null || contentType === void 0 ? void 0 : contentType.split(';')[0]) === null || _a === void 0 ? void 0 : _a.trim(); + const isJSON = (mediaType === null || mediaType === void 0 ? void 0 : mediaType.includes('application/json')) || (mediaType === null || mediaType === void 0 ? void 0 : mediaType.endsWith('+json')); + if (isJSON) { + const contentLength = response.headers.get('content-length'); + if (contentLength === '0') { + // if there is no content we can't do anything + return undefined; + } + const json = await response.json(); + return json; + } + const text = await response.text(); + return text; + })(); + loggerFor(client).debug(`[${requestLogID}] response parsed`, formatRequestDetails({ + retryOfRequestLogID, + url: response.url, + status: response.status, + body, + durationMs: Date.now() - startTime, + })); + return body; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * A subclass of `Promise` providing additional helper methods + * for interacting with the SDK. + */ +class APIPromise extends Promise { + constructor(client, responsePromise, parseResponse = defaultParseResponse) { + super((resolve) => { + // this is maybe a bit weird but this has to be a no-op to not implicitly + // parse the response body; instead .then, .catch, .finally are overridden + // to parse the response + resolve(null); + }); + this.responsePromise = responsePromise; + this.parseResponse = parseResponse; + this.client = client; + } + _thenUnwrap(transform) { + return new APIPromise(this.client, this.responsePromise, async (client, props) => transform(await this.parseResponse(client, props), props)); + } + /** + * Gets the raw `Response` instance instead of parsing the response + * data. + * + * If you want to parse the response body but still get the `Response` + * instance, you can use {@link withResponse()}. + * + * 👋 Getting the wrong TypeScript type for `Response`? + * Try setting `"moduleResolution": "NodeNext"` or add `"lib": ["DOM"]` + * to your `tsconfig.json`. + */ + asResponse() { + return this.responsePromise.then((p) => p.response); + } + /** + * Gets the parsed response data and the raw `Response` instance. + * + * If you just want to get the raw `Response` instance without parsing it, + * you can use {@link asResponse()}. + * + * 👋 Getting the wrong TypeScript type for `Response`? + * Try setting `"moduleResolution": "NodeNext"` or add `"lib": ["DOM"]` + * to your `tsconfig.json`. + */ + async withResponse() { + const [data, response] = await Promise.all([this.parse(), this.asResponse()]); + return { data, response }; + } + parse() { + if (!this.parsedPromise) { + this.parsedPromise = this.responsePromise.then((data) => this.parseResponse(this.client, data)); + } + return this.parsedPromise; + } + then(onfulfilled, onrejected) { + return this.parse().then(onfulfilled, onrejected); + } + catch(onrejected) { + return this.parse().catch(onrejected); + } + finally(onfinally) { + return this.parse().finally(onfinally); + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +const brand_privateNullableHeaders = /* @__PURE__ */ Symbol('brand.privateNullableHeaders'); +function* iterateHeaders(headers) { + if (!headers) + return; + if (brand_privateNullableHeaders in headers) { + const { values, nulls } = headers; + yield* values.entries(); + for (const name of nulls) { + yield [name, null]; + } + return; + } + let shouldClear = false; + let iter; + if (headers instanceof Headers) { + iter = headers.entries(); + } + else if (isReadonlyArray(headers)) { + iter = headers; + } + else { + shouldClear = true; + iter = Object.entries(headers !== null && headers !== void 0 ? headers : {}); + } + for (let row of iter) { + const name = row[0]; + if (typeof name !== 'string') + throw new TypeError('expected header name to be a string'); + const values = isReadonlyArray(row[1]) ? row[1] : [row[1]]; + let didClear = false; + for (const value of values) { + if (value === undefined) + continue; + // Objects keys always overwrite older headers, they never append. + // Yield a null to clear the header before adding the new values. + if (shouldClear && !didClear) { + didClear = true; + yield [name, null]; + } + yield [name, value]; + } + } +} +const buildHeaders = (newHeaders) => { + const targetHeaders = new Headers(); + const nullHeaders = new Set(); + for (const headers of newHeaders) { + const seenHeaders = new Set(); + for (const [name, value] of iterateHeaders(headers)) { + const lowerName = name.toLowerCase(); + if (!seenHeaders.has(lowerName)) { + targetHeaders.delete(name); + seenHeaders.add(lowerName); + } + if (value === null) { + targetHeaders.delete(name); + nullHeaders.add(lowerName); + } + else { + targetHeaders.append(name, value); + nullHeaders.delete(lowerName); + } + } + } + return { [brand_privateNullableHeaders]: true, values: targetHeaders, nulls: nullHeaders }; +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +/** + * Read an environment variable. + * + * Trims beginning and trailing whitespace. + * + * Will return undefined if the environment variable doesn't exist or cannot be accessed. + */ +const readEnv = (env) => { + var _a, _b, _c, _d, _e, _f; + if (typeof globalThis.process !== 'undefined') { + return (_c = (_b = (_a = globalThis.process.env) === null || _a === void 0 ? void 0 : _a[env]) === null || _b === void 0 ? void 0 : _b.trim()) !== null && _c !== void 0 ? _c : undefined; + } + if (typeof globalThis.Deno !== 'undefined') { + return (_f = (_e = (_d = globalThis.Deno.env) === null || _d === void 0 ? void 0 : _d.get) === null || _e === void 0 ? void 0 : _e.call(_d, env)) === null || _f === void 0 ? void 0 : _f.trim(); + } + return undefined; +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +var _a; +/** + * Base class for Gemini Next Gen API API clients. + */ +class BaseGeminiNextGenAPIClient { + /** + * API Client for interfacing with the Gemini Next Gen API API. + * + * @param {string | null | undefined} [opts.apiKey=process.env['GEMINI_API_KEY'] ?? null] + * @param {string | undefined} [opts.apiVersion=v1beta] + * @param {string} [opts.baseURL=process.env['GEMINI_NEXT_GEN_API_BASE_URL'] ?? https://generativelanguage.googleapis.com] - Override the default base URL for the API. + * @param {number} [opts.timeout=1 minute] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out. + * @param {MergedRequestInit} [opts.fetchOptions] - Additional `RequestInit` options to be passed to `fetch` calls. + * @param {Fetch} [opts.fetch] - Specify a custom `fetch` function implementation. + * @param {number} [opts.maxRetries=2] - The maximum number of times the client will retry a request. + * @param {HeadersLike} opts.defaultHeaders - Default headers to include with every request to the API. + * @param {Record<string, string | undefined>} opts.defaultQuery - Default query parameters to include with every request to the API. + */ + constructor(_b) { + var _c, _d, _e, _f, _g, _h, _j; + var { baseURL = readEnv('GEMINI_NEXT_GEN_API_BASE_URL'), apiKey = (_c = readEnv('GEMINI_API_KEY')) !== null && _c !== void 0 ? _c : null, apiVersion = 'v1beta' } = _b, opts = __rest(_b, ["baseURL", "apiKey", "apiVersion"]); + const options = Object.assign(Object.assign({ apiKey, + apiVersion }, opts), { baseURL: baseURL || `https://generativelanguage.googleapis.com` }); + this.baseURL = options.baseURL; + this.timeout = (_d = options.timeout) !== null && _d !== void 0 ? _d : BaseGeminiNextGenAPIClient.DEFAULT_TIMEOUT /* 1 minute */; + this.logger = (_e = options.logger) !== null && _e !== void 0 ? _e : console; + const defaultLogLevel = 'warn'; + // Set default logLevel early so that we can log a warning in parseLogLevel. + this.logLevel = defaultLogLevel; + this.logLevel = + (_g = (_f = parseLogLevel(options.logLevel, 'ClientOptions.logLevel', this)) !== null && _f !== void 0 ? _f : parseLogLevel(readEnv('GEMINI_NEXT_GEN_API_LOG'), "process.env['GEMINI_NEXT_GEN_API_LOG']", this)) !== null && _g !== void 0 ? _g : defaultLogLevel; + this.fetchOptions = options.fetchOptions; + this.maxRetries = (_h = options.maxRetries) !== null && _h !== void 0 ? _h : 2; + this.fetch = (_j = options.fetch) !== null && _j !== void 0 ? _j : getDefaultFetch(); + this.encoder = FallbackEncoder; + this._options = options; + this.apiKey = apiKey; + this.apiVersion = apiVersion; + this.clientAdapter = options.clientAdapter; + } + /** + * Create a new client instance re-using the same options given to the current client with optional overriding. + */ + withOptions(options) { + const client = new this.constructor(Object.assign(Object.assign(Object.assign({}, this._options), { baseURL: this.baseURL, maxRetries: this.maxRetries, timeout: this.timeout, logger: this.logger, logLevel: this.logLevel, fetch: this.fetch, fetchOptions: this.fetchOptions, apiKey: this.apiKey, apiVersion: this.apiVersion }), options)); + return client; + } + /** + * Check whether the base URL is set to its default. + */ + baseURLOverridden() { + return this.baseURL !== 'https://generativelanguage.googleapis.com'; + } + defaultQuery() { + return this._options.defaultQuery; + } + validateHeaders({ values, nulls }) { + // The headers object handles case insensitivity. + if (values.has('authorization') || values.has('x-goog-api-key')) { + return; + } + if (this.apiKey && values.get('x-goog-api-key')) { + return; + } + if (nulls.has('x-goog-api-key')) { + return; + } + throw new Error('Could not resolve authentication method. Expected the apiKey to be set. Or for the "x-goog-api-key" headers to be explicitly omitted'); + } + async authHeaders(opts) { + const existingHeaders = buildHeaders([opts.headers]); + if (existingHeaders.values.has('authorization') || existingHeaders.values.has('x-goog-api-key')) { + return undefined; + } + if (this.apiKey) { + return buildHeaders([{ 'x-goog-api-key': this.apiKey }]); + } + if (this.clientAdapter.isVertexAI()) { + return buildHeaders([await this.clientAdapter.getAuthHeaders()]); + } + return undefined; + } + /** + * Basic re-implementation of `qs.stringify` for primitive types. + */ + stringifyQuery(query) { + return Object.entries(query) + .filter(([_, value]) => typeof value !== 'undefined') + .map(([key, value]) => { + if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { + return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`; + } + if (value === null) { + return `${encodeURIComponent(key)}=`; + } + throw new GeminiNextGenAPIClientError(`Cannot stringify type ${typeof value}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`); + }) + .join('&'); + } + getUserAgent() { + return `${this.constructor.name}/JS ${VERSION}`; + } + defaultIdempotencyKey() { + return `stainless-node-retry-${uuid4()}`; + } + makeStatusError(status, error, message, headers) { + return APIError.generate(status, error, message, headers); + } + buildURL(path, query, defaultBaseURL) { + const baseURL = (!this.baseURLOverridden() && defaultBaseURL) || this.baseURL; + const url = isAbsoluteURL(path) ? + new URL(path) + : new URL(baseURL + (baseURL.endsWith('/') && path.startsWith('/') ? path.slice(1) : path)); + const defaultQuery = this.defaultQuery(); + if (!isEmptyObj(defaultQuery)) { + query = Object.assign(Object.assign({}, defaultQuery), query); + } + if (typeof query === 'object' && query && !Array.isArray(query)) { + url.search = this.stringifyQuery(query); + } + return url.toString(); + } + /** + * Used as a callback for mutating the given `FinalRequestOptions` object. + + */ + async prepareOptions(options) { + if (this.clientAdapter && + this.clientAdapter.isVertexAI() && + !options.path.startsWith(`/${this.apiVersion}/projects/`)) { + const oldPath = options.path.slice(this.apiVersion.length + 1); + options.path = `/${this.apiVersion}/projects/${this.clientAdapter.getProject()}/locations/${this.clientAdapter.getLocation()}${oldPath}`; + } + } + /** + * Used as a callback for mutating the given `RequestInit` object. + * + * This is useful for cases where you want to add certain headers based off of + * the request properties, e.g. `method` or `url`. + */ + async prepareRequest(request, { url, options }) { } + get(path, opts) { + return this.methodRequest('get', path, opts); + } + post(path, opts) { + return this.methodRequest('post', path, opts); + } + patch(path, opts) { + return this.methodRequest('patch', path, opts); + } + put(path, opts) { + return this.methodRequest('put', path, opts); + } + delete(path, opts) { + return this.methodRequest('delete', path, opts); + } + methodRequest(method, path, opts) { + return this.request(Promise.resolve(opts).then((opts) => { + return Object.assign({ method, path }, opts); + })); + } + request(options, remainingRetries = null) { + return new APIPromise(this, this.makeRequest(options, remainingRetries, undefined)); + } + async makeRequest(optionsInput, retriesRemaining, retryOfRequestLogID) { + var _b, _c, _d; + const options = await optionsInput; + const maxRetries = (_b = options.maxRetries) !== null && _b !== void 0 ? _b : this.maxRetries; + if (retriesRemaining == null) { + retriesRemaining = maxRetries; + } + await this.prepareOptions(options); + const { req, url, timeout } = await this.buildRequest(options, { + retryCount: maxRetries - retriesRemaining, + }); + await this.prepareRequest(req, { url, options }); + /** Not an API request ID, just for correlating local log entries. */ + const requestLogID = 'log_' + ((Math.random() * (1 << 24)) | 0).toString(16).padStart(6, '0'); + const retryLogStr = retryOfRequestLogID === undefined ? '' : `, retryOf: ${retryOfRequestLogID}`; + const startTime = Date.now(); + loggerFor(this).debug(`[${requestLogID}] sending request`, formatRequestDetails({ + retryOfRequestLogID, + method: options.method, + url, + options, + headers: req.headers, + })); + if ((_c = options.signal) === null || _c === void 0 ? void 0 : _c.aborted) { + throw new APIUserAbortError(); + } + const controller = new AbortController(); + const response = await this.fetchWithTimeout(url, req, timeout, controller).catch(castToError); + const headersTime = Date.now(); + if (response instanceof globalThis.Error) { + const retryMessage = `retrying, ${retriesRemaining} attempts remaining`; + if ((_d = options.signal) === null || _d === void 0 ? void 0 : _d.aborted) { + throw new APIUserAbortError(); + } + // detect native connection timeout errors + // deno throws "TypeError: error sending request for url (https://example/): client error (Connect): tcp connect error: Operation timed out (os error 60): Operation timed out (os error 60)" + // undici throws "TypeError: fetch failed" with cause "ConnectTimeoutError: Connect Timeout Error (attempted address: example:443, timeout: 1ms)" + // others do not provide enough information to distinguish timeouts from other connection errors + const isTimeout = isAbortError(response) || + /timed? ?out/i.test(String(response) + ('cause' in response ? String(response.cause) : '')); + if (retriesRemaining) { + loggerFor(this).info(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - ${retryMessage}`); + loggerFor(this).debug(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (${retryMessage})`, formatRequestDetails({ + retryOfRequestLogID, + url, + durationMs: headersTime - startTime, + message: response.message, + })); + return this.retryRequest(options, retriesRemaining, retryOfRequestLogID !== null && retryOfRequestLogID !== void 0 ? retryOfRequestLogID : requestLogID); + } + loggerFor(this).info(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - error; no more retries left`); + loggerFor(this).debug(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (error; no more retries left)`, formatRequestDetails({ + retryOfRequestLogID, + url, + durationMs: headersTime - startTime, + message: response.message, + })); + if (isTimeout) { + throw new APIConnectionTimeoutError(); + } + throw new APIConnectionError({ cause: response }); + } + const responseInfo = `[${requestLogID}${retryLogStr}] ${req.method} ${url} ${response.ok ? 'succeeded' : 'failed'} with status ${response.status} in ${headersTime - startTime}ms`; + if (!response.ok) { + const shouldRetry = await this.shouldRetry(response); + if (retriesRemaining && shouldRetry) { + const retryMessage = `retrying, ${retriesRemaining} attempts remaining`; + // We don't need the body of this response. + await CancelReadableStream(response.body); + loggerFor(this).info(`${responseInfo} - ${retryMessage}`); + loggerFor(this).debug(`[${requestLogID}] response error (${retryMessage})`, formatRequestDetails({ + retryOfRequestLogID, + url: response.url, + status: response.status, + headers: response.headers, + durationMs: headersTime - startTime, + })); + return this.retryRequest(options, retriesRemaining, retryOfRequestLogID !== null && retryOfRequestLogID !== void 0 ? retryOfRequestLogID : requestLogID, response.headers); + } + const retryMessage = shouldRetry ? `error; no more retries left` : `error; not retryable`; + loggerFor(this).info(`${responseInfo} - ${retryMessage}`); + const errText = await response.text().catch((err) => castToError(err).message); + const errJSON = safeJSON(errText); + const errMessage = errJSON ? undefined : errText; + loggerFor(this).debug(`[${requestLogID}] response error (${retryMessage})`, formatRequestDetails({ + retryOfRequestLogID, + url: response.url, + status: response.status, + headers: response.headers, + message: errMessage, + durationMs: Date.now() - startTime, + })); + // @ts-ignore + const err = this.makeStatusError(response.status, errJSON, errMessage, response.headers); + throw err; + } + loggerFor(this).info(responseInfo); + loggerFor(this).debug(`[${requestLogID}] response start`, formatRequestDetails({ + retryOfRequestLogID, + url: response.url, + status: response.status, + headers: response.headers, + durationMs: headersTime - startTime, + })); + return { response, options, controller, requestLogID, retryOfRequestLogID, startTime }; + } + async fetchWithTimeout(url, init, ms, controller) { + const _b = init || {}, { signal, method } = _b, options = __rest(_b, ["signal", "method"]); + const abort = this._makeAbort(controller); + if (signal) + signal.addEventListener('abort', abort, { once: true }); + const timeout = setTimeout(abort, ms); + const isReadableBody = (globalThis.ReadableStream && options.body instanceof globalThis.ReadableStream) || + (typeof options.body === 'object' && options.body !== null && Symbol.asyncIterator in options.body); + const fetchOptions = Object.assign(Object.assign(Object.assign({ signal: controller.signal }, (isReadableBody ? { duplex: 'half' } : {})), { method: 'GET' }), options); + if (method) { + // Custom methods like 'patch' need to be uppercased + // See https://github.com/nodejs/undici/issues/2294 + fetchOptions.method = method.toUpperCase(); + } + try { + // use undefined this binding; fetch errors if bound to something else in browser/cloudflare + return await this.fetch.call(undefined, url, fetchOptions); + } + finally { + clearTimeout(timeout); + } + } + async shouldRetry(response) { + // Note this is not a standard header. + const shouldRetryHeader = response.headers.get('x-should-retry'); + // If the server explicitly says whether or not to retry, obey. + if (shouldRetryHeader === 'true') + return true; + if (shouldRetryHeader === 'false') + return false; + // Retry on request timeouts. + if (response.status === 408) + return true; + // Retry on lock timeouts. + if (response.status === 409) + return true; + // Retry on rate limits. + if (response.status === 429) + return true; + // Retry internal errors. + if (response.status >= 500) + return true; + return false; + } + async retryRequest(options, retriesRemaining, requestLogID, responseHeaders) { + var _b; + let timeoutMillis; + // Note the `retry-after-ms` header may not be standard, but is a good idea and we'd like proactive support for it. + const retryAfterMillisHeader = responseHeaders === null || responseHeaders === void 0 ? void 0 : responseHeaders.get('retry-after-ms'); + if (retryAfterMillisHeader) { + const timeoutMs = parseFloat(retryAfterMillisHeader); + if (!Number.isNaN(timeoutMs)) { + timeoutMillis = timeoutMs; + } + } + // About the Retry-After header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After + const retryAfterHeader = responseHeaders === null || responseHeaders === void 0 ? void 0 : responseHeaders.get('retry-after'); + if (retryAfterHeader && !timeoutMillis) { + const timeoutSeconds = parseFloat(retryAfterHeader); + if (!Number.isNaN(timeoutSeconds)) { + timeoutMillis = timeoutSeconds * 1000; + } + else { + timeoutMillis = Date.parse(retryAfterHeader) - Date.now(); + } + } + // If the API asks us to wait a certain amount of time (and it's a reasonable amount), + // just do what it says, but otherwise calculate a default + if (!(timeoutMillis && 0 <= timeoutMillis && timeoutMillis < 60 * 1000)) { + const maxRetries = (_b = options.maxRetries) !== null && _b !== void 0 ? _b : this.maxRetries; + timeoutMillis = this.calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries); + } + await sleep(timeoutMillis); + return this.makeRequest(options, retriesRemaining - 1, requestLogID); + } + calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries) { + const initialRetryDelay = 0.5; + const maxRetryDelay = 8.0; + const numRetries = maxRetries - retriesRemaining; + // Apply exponential backoff, but not more than the max. + const sleepSeconds = Math.min(initialRetryDelay * Math.pow(2, numRetries), maxRetryDelay); + // Apply some jitter, take up to at most 25 percent of the retry time. + const jitter = 1 - Math.random() * 0.25; + return sleepSeconds * jitter * 1000; + } + async buildRequest(inputOptions, { retryCount = 0 } = {}) { + var _b, _c, _d; + const options = Object.assign({}, inputOptions); + const { method, path, query, defaultBaseURL } = options; + const url = this.buildURL(path, query, defaultBaseURL); + if ('timeout' in options) + validatePositiveInteger('timeout', options.timeout); + options.timeout = (_b = options.timeout) !== null && _b !== void 0 ? _b : this.timeout; + const { bodyHeaders, body } = this.buildBody({ options }); + const reqHeaders = await this.buildHeaders({ options: inputOptions, method, bodyHeaders, retryCount }); + const req = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ method, headers: reqHeaders }, (options.signal && { signal: options.signal })), (globalThis.ReadableStream && + body instanceof globalThis.ReadableStream && { duplex: 'half' })), (body && { body })), ((_c = this.fetchOptions) !== null && _c !== void 0 ? _c : {})), ((_d = options.fetchOptions) !== null && _d !== void 0 ? _d : {})); + return { req, url, timeout: options.timeout }; + } + async buildHeaders({ options, method, bodyHeaders, retryCount, }) { + let idempotencyHeaders = {}; + if (this.idempotencyHeader && method !== 'get') { + if (!options.idempotencyKey) + options.idempotencyKey = this.defaultIdempotencyKey(); + idempotencyHeaders[this.idempotencyHeader] = options.idempotencyKey; + } + const authHeaders = await this.authHeaders(options); + let headers = buildHeaders([ + idempotencyHeaders, + Object.assign(Object.assign({ Accept: 'application/json', 'User-Agent': this.getUserAgent(), 'X-Stainless-Retry-Count': String(retryCount) }, (options.timeout ? { 'X-Stainless-Timeout': String(Math.trunc(options.timeout / 1000)) } : {})), getPlatformHeaders()), + this._options.defaultHeaders, + bodyHeaders, + options.headers, + authHeaders, + ]); + this.validateHeaders(headers); + return headers.values; + } + _makeAbort(controller) { + // note: we can't just inline this method inside `fetchWithTimeout()` because then the closure + // would capture all request options, and cause a memory leak. + return () => controller.abort(); + } + buildBody({ options: { body, headers: rawHeaders } }) { + if (!body) { + return { bodyHeaders: undefined, body: undefined }; + } + const headers = buildHeaders([rawHeaders]); + if ( + // Pass raw type verbatim + ArrayBuffer.isView(body) || + body instanceof ArrayBuffer || + body instanceof DataView || + (typeof body === 'string' && + // Preserve legacy string encoding behavior for now + headers.values.has('content-type')) || + // `Blob` is superset of `File` + (globalThis.Blob && body instanceof globalThis.Blob) || + // `FormData` -> `multipart/form-data` + body instanceof FormData || + // `URLSearchParams` -> `application/x-www-form-urlencoded` + body instanceof URLSearchParams || + // Send chunked stream (each chunk has own `length`) + (globalThis.ReadableStream && body instanceof globalThis.ReadableStream)) { + return { bodyHeaders: undefined, body: body }; + } + else if (typeof body === 'object' && + (Symbol.asyncIterator in body || + (Symbol.iterator in body && 'next' in body && typeof body.next === 'function'))) { + return { bodyHeaders: undefined, body: ReadableStreamFrom(body) }; + } + else { + return this.encoder({ body, headers }); + } + } +} +BaseGeminiNextGenAPIClient.DEFAULT_TIMEOUT = 60000; // 1 minute +/** + * API Client for interfacing with the Gemini Next Gen API API. + */ +class GeminiNextGenAPIClient extends BaseGeminiNextGenAPIClient { + constructor() { + super(...arguments); + this.interactions = new Interactions(this); + } +} +_a = GeminiNextGenAPIClient; +GeminiNextGenAPIClient.GeminiNextGenAPIClient = _a; +GeminiNextGenAPIClient.GeminiNextGenAPIClientError = GeminiNextGenAPIClientError; +GeminiNextGenAPIClient.APIError = APIError; +GeminiNextGenAPIClient.APIConnectionError = APIConnectionError; +GeminiNextGenAPIClient.APIConnectionTimeoutError = APIConnectionTimeoutError; +GeminiNextGenAPIClient.APIUserAbortError = APIUserAbortError; +GeminiNextGenAPIClient.NotFoundError = NotFoundError; +GeminiNextGenAPIClient.ConflictError = ConflictError; +GeminiNextGenAPIClient.RateLimitError = RateLimitError; +GeminiNextGenAPIClient.BadRequestError = BadRequestError; +GeminiNextGenAPIClient.AuthenticationError = AuthenticationError; +GeminiNextGenAPIClient.InternalServerError = InternalServerError; +GeminiNextGenAPIClient.PermissionDeniedError = PermissionDeniedError; +GeminiNextGenAPIClient.UnprocessableEntityError = UnprocessableEntityError; +GeminiNextGenAPIClient.toFile = toFile; +GeminiNextGenAPIClient.Interactions = Interactions; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function blobToMldev$2(fromObject) { + const toObject = {}; + const fromData = getValueByPath(fromObject, ['data']); + if (fromData != null) { + setValueByPath(toObject, ['data'], fromData); + } + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function contentToMldev$2(fromObject) { + const toObject = {}; + const fromParts = getValueByPath(fromObject, ['parts']); + if (fromParts != null) { + let transformedList = fromParts; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return partToMldev$2(item); + }); + } + setValueByPath(toObject, ['parts'], transformedList); + } + const fromRole = getValueByPath(fromObject, ['role']); + if (fromRole != null) { + setValueByPath(toObject, ['role'], fromRole); + } + return toObject; +} +function fileDataToMldev$2(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromFileUri = getValueByPath(fromObject, ['fileUri']); + if (fromFileUri != null) { + setValueByPath(toObject, ['fileUri'], fromFileUri); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function functionCallToMldev$2(fromObject) { + const toObject = {}; + const fromId = getValueByPath(fromObject, ['id']); + if (fromId != null) { + setValueByPath(toObject, ['id'], fromId); + } + const fromArgs = getValueByPath(fromObject, ['args']); + if (fromArgs != null) { + setValueByPath(toObject, ['args'], fromArgs); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + if (getValueByPath(fromObject, ['partialArgs']) !== undefined) { + throw new Error('partialArgs parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['willContinue']) !== undefined) { + throw new Error('willContinue parameter is not supported in Gemini API.'); + } + return toObject; +} +function functionDeclarationToVertex$1(fromObject) { + const toObject = {}; + const fromDescription = getValueByPath(fromObject, ['description']); + if (fromDescription != null) { + setValueByPath(toObject, ['description'], fromDescription); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromParameters = getValueByPath(fromObject, ['parameters']); + if (fromParameters != null) { + setValueByPath(toObject, ['parameters'], fromParameters); + } + const fromParametersJsonSchema = getValueByPath(fromObject, [ + 'parametersJsonSchema', + ]); + if (fromParametersJsonSchema != null) { + setValueByPath(toObject, ['parametersJsonSchema'], fromParametersJsonSchema); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], fromResponse); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + if (getValueByPath(fromObject, ['behavior']) !== undefined) { + throw new Error('behavior parameter is not supported in Vertex AI.'); + } + return toObject; +} +function generationConfigToVertex$1(fromObject) { + const toObject = {}; + const fromModelSelectionConfig = getValueByPath(fromObject, [ + 'modelSelectionConfig', + ]); + if (fromModelSelectionConfig != null) { + setValueByPath(toObject, ['modelConfig'], fromModelSelectionConfig); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + const fromAudioTimestamp = getValueByPath(fromObject, [ + 'audioTimestamp', + ]); + if (fromAudioTimestamp != null) { + setValueByPath(toObject, ['audioTimestamp'], fromAudioTimestamp); + } + const fromCandidateCount = getValueByPath(fromObject, [ + 'candidateCount', + ]); + if (fromCandidateCount != null) { + setValueByPath(toObject, ['candidateCount'], fromCandidateCount); + } + const fromEnableAffectiveDialog = getValueByPath(fromObject, [ + 'enableAffectiveDialog', + ]); + if (fromEnableAffectiveDialog != null) { + setValueByPath(toObject, ['enableAffectiveDialog'], fromEnableAffectiveDialog); + } + const fromFrequencyPenalty = getValueByPath(fromObject, [ + 'frequencyPenalty', + ]); + if (fromFrequencyPenalty != null) { + setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty); + } + const fromLogprobs = getValueByPath(fromObject, ['logprobs']); + if (fromLogprobs != null) { + setValueByPath(toObject, ['logprobs'], fromLogprobs); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (fromMaxOutputTokens != null) { + setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromPresencePenalty = getValueByPath(fromObject, [ + 'presencePenalty', + ]); + if (fromPresencePenalty != null) { + setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty); + } + const fromResponseLogprobs = getValueByPath(fromObject, [ + 'responseLogprobs', + ]); + if (fromResponseLogprobs != null) { + setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs); + } + const fromResponseMimeType = getValueByPath(fromObject, [ + 'responseMimeType', + ]); + if (fromResponseMimeType != null) { + setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (fromResponseModalities != null) { + setValueByPath(toObject, ['responseModalities'], fromResponseModalities); + } + const fromResponseSchema = getValueByPath(fromObject, [ + 'responseSchema', + ]); + if (fromResponseSchema != null) { + setValueByPath(toObject, ['responseSchema'], fromResponseSchema); + } + const fromRoutingConfig = getValueByPath(fromObject, [ + 'routingConfig', + ]); + if (fromRoutingConfig != null) { + setValueByPath(toObject, ['routingConfig'], fromRoutingConfig); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (fromSeed != null) { + setValueByPath(toObject, ['seed'], fromSeed); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (fromSpeechConfig != null) { + setValueByPath(toObject, ['speechConfig'], fromSpeechConfig); + } + const fromStopSequences = getValueByPath(fromObject, [ + 'stopSequences', + ]); + if (fromStopSequences != null) { + setValueByPath(toObject, ['stopSequences'], fromStopSequences); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (fromTemperature != null) { + setValueByPath(toObject, ['temperature'], fromTemperature); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (fromThinkingConfig != null) { + setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (fromTopK != null) { + setValueByPath(toObject, ['topK'], fromTopK); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (fromTopP != null) { + setValueByPath(toObject, ['topP'], fromTopP); + } + if (getValueByPath(fromObject, ['enableEnhancedCivicAnswers']) !== + undefined) { + throw new Error('enableEnhancedCivicAnswers parameter is not supported in Vertex AI.'); + } + return toObject; +} +function googleMapsToMldev$2(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['authConfig']) !== undefined) { + throw new Error('authConfig parameter is not supported in Gemini API.'); + } + const fromEnableWidget = getValueByPath(fromObject, ['enableWidget']); + if (fromEnableWidget != null) { + setValueByPath(toObject, ['enableWidget'], fromEnableWidget); + } + return toObject; +} +function googleSearchToMldev$2(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['excludeDomains']) !== undefined) { + throw new Error('excludeDomains parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['blockingConfidence']) !== undefined) { + throw new Error('blockingConfidence parameter is not supported in Gemini API.'); + } + const fromTimeRangeFilter = getValueByPath(fromObject, [ + 'timeRangeFilter', + ]); + if (fromTimeRangeFilter != null) { + setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter); + } + return toObject; +} +function liveConnectConfigToMldev$1(fromObject, parentObject) { + const toObject = {}; + const fromGenerationConfig = getValueByPath(fromObject, [ + 'generationConfig', + ]); + if (parentObject !== undefined && fromGenerationConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig'], fromGenerationConfig); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (parentObject !== undefined && fromResponseModalities != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'responseModalities'], fromResponseModalities); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (parentObject !== undefined && fromTemperature != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'temperature'], fromTemperature); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (parentObject !== undefined && fromTopP != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'topP'], fromTopP); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (parentObject !== undefined && fromTopK != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'topK'], fromTopK); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (parentObject !== undefined && fromMaxOutputTokens != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'maxOutputTokens'], fromMaxOutputTokens); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (parentObject !== undefined && fromMediaResolution != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'mediaResolution'], fromMediaResolution); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (parentObject !== undefined && fromSeed != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'seed'], fromSeed); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (parentObject !== undefined && fromSpeechConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'speechConfig'], tLiveSpeechConfig(fromSpeechConfig)); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (parentObject !== undefined && fromThinkingConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'thinkingConfig'], fromThinkingConfig); + } + const fromEnableAffectiveDialog = getValueByPath(fromObject, [ + 'enableAffectiveDialog', + ]); + if (parentObject !== undefined && fromEnableAffectiveDialog != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'enableAffectiveDialog'], fromEnableAffectiveDialog); + } + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['setup', 'systemInstruction'], contentToMldev$2(tContent(fromSystemInstruction))); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = tTools(fromTools); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToMldev$2(tTool(item)); + }); + } + setValueByPath(parentObject, ['setup', 'tools'], transformedList); + } + const fromSessionResumption = getValueByPath(fromObject, [ + 'sessionResumption', + ]); + if (parentObject !== undefined && fromSessionResumption != null) { + setValueByPath(parentObject, ['setup', 'sessionResumption'], sessionResumptionConfigToMldev$1(fromSessionResumption)); + } + const fromInputAudioTranscription = getValueByPath(fromObject, [ + 'inputAudioTranscription', + ]); + if (parentObject !== undefined && fromInputAudioTranscription != null) { + setValueByPath(parentObject, ['setup', 'inputAudioTranscription'], fromInputAudioTranscription); + } + const fromOutputAudioTranscription = getValueByPath(fromObject, [ + 'outputAudioTranscription', + ]); + if (parentObject !== undefined && fromOutputAudioTranscription != null) { + setValueByPath(parentObject, ['setup', 'outputAudioTranscription'], fromOutputAudioTranscription); + } + const fromRealtimeInputConfig = getValueByPath(fromObject, [ + 'realtimeInputConfig', + ]); + if (parentObject !== undefined && fromRealtimeInputConfig != null) { + setValueByPath(parentObject, ['setup', 'realtimeInputConfig'], fromRealtimeInputConfig); + } + const fromContextWindowCompression = getValueByPath(fromObject, [ + 'contextWindowCompression', + ]); + if (parentObject !== undefined && fromContextWindowCompression != null) { + setValueByPath(parentObject, ['setup', 'contextWindowCompression'], fromContextWindowCompression); + } + const fromProactivity = getValueByPath(fromObject, ['proactivity']); + if (parentObject !== undefined && fromProactivity != null) { + setValueByPath(parentObject, ['setup', 'proactivity'], fromProactivity); + } + if (getValueByPath(fromObject, ['explicitVadSignal']) !== undefined) { + throw new Error('explicitVadSignal parameter is not supported in Gemini API.'); + } + return toObject; +} +function liveConnectConfigToVertex(fromObject, parentObject) { + const toObject = {}; + const fromGenerationConfig = getValueByPath(fromObject, [ + 'generationConfig', + ]); + if (parentObject !== undefined && fromGenerationConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig'], generationConfigToVertex$1(fromGenerationConfig)); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (parentObject !== undefined && fromResponseModalities != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'responseModalities'], fromResponseModalities); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (parentObject !== undefined && fromTemperature != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'temperature'], fromTemperature); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (parentObject !== undefined && fromTopP != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'topP'], fromTopP); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (parentObject !== undefined && fromTopK != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'topK'], fromTopK); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (parentObject !== undefined && fromMaxOutputTokens != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'maxOutputTokens'], fromMaxOutputTokens); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (parentObject !== undefined && fromMediaResolution != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'mediaResolution'], fromMediaResolution); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (parentObject !== undefined && fromSeed != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'seed'], fromSeed); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (parentObject !== undefined && fromSpeechConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'speechConfig'], tLiveSpeechConfig(fromSpeechConfig)); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (parentObject !== undefined && fromThinkingConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'thinkingConfig'], fromThinkingConfig); + } + const fromEnableAffectiveDialog = getValueByPath(fromObject, [ + 'enableAffectiveDialog', + ]); + if (parentObject !== undefined && fromEnableAffectiveDialog != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'enableAffectiveDialog'], fromEnableAffectiveDialog); + } + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['setup', 'systemInstruction'], tContent(fromSystemInstruction)); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = tTools(fromTools); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToVertex$1(tTool(item)); + }); + } + setValueByPath(parentObject, ['setup', 'tools'], transformedList); + } + const fromSessionResumption = getValueByPath(fromObject, [ + 'sessionResumption', + ]); + if (parentObject !== undefined && fromSessionResumption != null) { + setValueByPath(parentObject, ['setup', 'sessionResumption'], fromSessionResumption); + } + const fromInputAudioTranscription = getValueByPath(fromObject, [ + 'inputAudioTranscription', + ]); + if (parentObject !== undefined && fromInputAudioTranscription != null) { + setValueByPath(parentObject, ['setup', 'inputAudioTranscription'], fromInputAudioTranscription); + } + const fromOutputAudioTranscription = getValueByPath(fromObject, [ + 'outputAudioTranscription', + ]); + if (parentObject !== undefined && fromOutputAudioTranscription != null) { + setValueByPath(parentObject, ['setup', 'outputAudioTranscription'], fromOutputAudioTranscription); + } + const fromRealtimeInputConfig = getValueByPath(fromObject, [ + 'realtimeInputConfig', + ]); + if (parentObject !== undefined && fromRealtimeInputConfig != null) { + setValueByPath(parentObject, ['setup', 'realtimeInputConfig'], fromRealtimeInputConfig); + } + const fromContextWindowCompression = getValueByPath(fromObject, [ + 'contextWindowCompression', + ]); + if (parentObject !== undefined && fromContextWindowCompression != null) { + setValueByPath(parentObject, ['setup', 'contextWindowCompression'], fromContextWindowCompression); + } + const fromProactivity = getValueByPath(fromObject, ['proactivity']); + if (parentObject !== undefined && fromProactivity != null) { + setValueByPath(parentObject, ['setup', 'proactivity'], fromProactivity); + } + const fromExplicitVadSignal = getValueByPath(fromObject, [ + 'explicitVadSignal', + ]); + if (parentObject !== undefined && fromExplicitVadSignal != null) { + setValueByPath(parentObject, ['setup', 'explicitVadSignal'], fromExplicitVadSignal); + } + return toObject; +} +function liveConnectParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['setup', 'model'], tModel(apiClient, fromModel)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['config'], liveConnectConfigToMldev$1(fromConfig, toObject)); + } + return toObject; +} +function liveConnectParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['setup', 'model'], tModel(apiClient, fromModel)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['config'], liveConnectConfigToVertex(fromConfig, toObject)); + } + return toObject; +} +function liveMusicSetConfigParametersToMldev(fromObject) { + const toObject = {}; + const fromMusicGenerationConfig = getValueByPath(fromObject, [ + 'musicGenerationConfig', + ]); + if (fromMusicGenerationConfig != null) { + setValueByPath(toObject, ['musicGenerationConfig'], fromMusicGenerationConfig); + } + return toObject; +} +function liveMusicSetWeightedPromptsParametersToMldev(fromObject) { + const toObject = {}; + const fromWeightedPrompts = getValueByPath(fromObject, [ + 'weightedPrompts', + ]); + if (fromWeightedPrompts != null) { + let transformedList = fromWeightedPrompts; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['weightedPrompts'], transformedList); + } + return toObject; +} +function liveSendRealtimeInputParametersToMldev(fromObject) { + const toObject = {}; + const fromMedia = getValueByPath(fromObject, ['media']); + if (fromMedia != null) { + let transformedList = tBlobs(fromMedia); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return blobToMldev$2(item); + }); + } + setValueByPath(toObject, ['mediaChunks'], transformedList); + } + const fromAudio = getValueByPath(fromObject, ['audio']); + if (fromAudio != null) { + setValueByPath(toObject, ['audio'], blobToMldev$2(tAudioBlob(fromAudio))); + } + const fromAudioStreamEnd = getValueByPath(fromObject, [ + 'audioStreamEnd', + ]); + if (fromAudioStreamEnd != null) { + setValueByPath(toObject, ['audioStreamEnd'], fromAudioStreamEnd); + } + const fromVideo = getValueByPath(fromObject, ['video']); + if (fromVideo != null) { + setValueByPath(toObject, ['video'], blobToMldev$2(tImageBlob(fromVideo))); + } + const fromText = getValueByPath(fromObject, ['text']); + if (fromText != null) { + setValueByPath(toObject, ['text'], fromText); + } + const fromActivityStart = getValueByPath(fromObject, [ + 'activityStart', + ]); + if (fromActivityStart != null) { + setValueByPath(toObject, ['activityStart'], fromActivityStart); + } + const fromActivityEnd = getValueByPath(fromObject, ['activityEnd']); + if (fromActivityEnd != null) { + setValueByPath(toObject, ['activityEnd'], fromActivityEnd); + } + return toObject; +} +function liveSendRealtimeInputParametersToVertex(fromObject) { + const toObject = {}; + const fromMedia = getValueByPath(fromObject, ['media']); + if (fromMedia != null) { + let transformedList = tBlobs(fromMedia); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['mediaChunks'], transformedList); + } + const fromAudio = getValueByPath(fromObject, ['audio']); + if (fromAudio != null) { + setValueByPath(toObject, ['audio'], tAudioBlob(fromAudio)); + } + const fromAudioStreamEnd = getValueByPath(fromObject, [ + 'audioStreamEnd', + ]); + if (fromAudioStreamEnd != null) { + setValueByPath(toObject, ['audioStreamEnd'], fromAudioStreamEnd); + } + const fromVideo = getValueByPath(fromObject, ['video']); + if (fromVideo != null) { + setValueByPath(toObject, ['video'], tImageBlob(fromVideo)); + } + const fromText = getValueByPath(fromObject, ['text']); + if (fromText != null) { + setValueByPath(toObject, ['text'], fromText); + } + const fromActivityStart = getValueByPath(fromObject, [ + 'activityStart', + ]); + if (fromActivityStart != null) { + setValueByPath(toObject, ['activityStart'], fromActivityStart); + } + const fromActivityEnd = getValueByPath(fromObject, ['activityEnd']); + if (fromActivityEnd != null) { + setValueByPath(toObject, ['activityEnd'], fromActivityEnd); + } + return toObject; +} +function liveServerMessageFromVertex(fromObject) { + const toObject = {}; + const fromSetupComplete = getValueByPath(fromObject, [ + 'setupComplete', + ]); + if (fromSetupComplete != null) { + setValueByPath(toObject, ['setupComplete'], fromSetupComplete); + } + const fromServerContent = getValueByPath(fromObject, [ + 'serverContent', + ]); + if (fromServerContent != null) { + setValueByPath(toObject, ['serverContent'], fromServerContent); + } + const fromToolCall = getValueByPath(fromObject, ['toolCall']); + if (fromToolCall != null) { + setValueByPath(toObject, ['toolCall'], fromToolCall); + } + const fromToolCallCancellation = getValueByPath(fromObject, [ + 'toolCallCancellation', + ]); + if (fromToolCallCancellation != null) { + setValueByPath(toObject, ['toolCallCancellation'], fromToolCallCancellation); + } + const fromUsageMetadata = getValueByPath(fromObject, [ + 'usageMetadata', + ]); + if (fromUsageMetadata != null) { + setValueByPath(toObject, ['usageMetadata'], usageMetadataFromVertex(fromUsageMetadata)); + } + const fromGoAway = getValueByPath(fromObject, ['goAway']); + if (fromGoAway != null) { + setValueByPath(toObject, ['goAway'], fromGoAway); + } + const fromSessionResumptionUpdate = getValueByPath(fromObject, [ + 'sessionResumptionUpdate', + ]); + if (fromSessionResumptionUpdate != null) { + setValueByPath(toObject, ['sessionResumptionUpdate'], fromSessionResumptionUpdate); + } + const fromVoiceActivityDetectionSignal = getValueByPath(fromObject, [ + 'voiceActivityDetectionSignal', + ]); + if (fromVoiceActivityDetectionSignal != null) { + setValueByPath(toObject, ['voiceActivityDetectionSignal'], fromVoiceActivityDetectionSignal); + } + const fromVoiceActivity = getValueByPath(fromObject, [ + 'voiceActivity', + ]); + if (fromVoiceActivity != null) { + setValueByPath(toObject, ['voiceActivity'], voiceActivityFromVertex(fromVoiceActivity)); + } + return toObject; +} +function partToMldev$2(fromObject) { + const toObject = {}; + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromCodeExecutionResult = getValueByPath(fromObject, [ + 'codeExecutionResult', + ]); + if (fromCodeExecutionResult != null) { + setValueByPath(toObject, ['codeExecutionResult'], fromCodeExecutionResult); + } + const fromExecutableCode = getValueByPath(fromObject, [ + 'executableCode', + ]); + if (fromExecutableCode != null) { + setValueByPath(toObject, ['executableCode'], fromExecutableCode); + } + const fromFileData = getValueByPath(fromObject, ['fileData']); + if (fromFileData != null) { + setValueByPath(toObject, ['fileData'], fileDataToMldev$2(fromFileData)); + } + const fromFunctionCall = getValueByPath(fromObject, ['functionCall']); + if (fromFunctionCall != null) { + setValueByPath(toObject, ['functionCall'], functionCallToMldev$2(fromFunctionCall)); + } + const fromFunctionResponse = getValueByPath(fromObject, [ + 'functionResponse', + ]); + if (fromFunctionResponse != null) { + setValueByPath(toObject, ['functionResponse'], fromFunctionResponse); + } + const fromInlineData = getValueByPath(fromObject, ['inlineData']); + if (fromInlineData != null) { + setValueByPath(toObject, ['inlineData'], blobToMldev$2(fromInlineData)); + } + const fromText = getValueByPath(fromObject, ['text']); + if (fromText != null) { + setValueByPath(toObject, ['text'], fromText); + } + const fromThought = getValueByPath(fromObject, ['thought']); + if (fromThought != null) { + setValueByPath(toObject, ['thought'], fromThought); + } + const fromThoughtSignature = getValueByPath(fromObject, [ + 'thoughtSignature', + ]); + if (fromThoughtSignature != null) { + setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature); + } + const fromVideoMetadata = getValueByPath(fromObject, [ + 'videoMetadata', + ]); + if (fromVideoMetadata != null) { + setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata); + } + return toObject; +} +function sessionResumptionConfigToMldev$1(fromObject) { + const toObject = {}; + const fromHandle = getValueByPath(fromObject, ['handle']); + if (fromHandle != null) { + setValueByPath(toObject, ['handle'], fromHandle); + } + if (getValueByPath(fromObject, ['transparent']) !== undefined) { + throw new Error('transparent parameter is not supported in Gemini API.'); + } + return toObject; +} +function toolToMldev$2(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['retrieval']) !== undefined) { + throw new Error('retrieval parameter is not supported in Gemini API.'); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + const fromFileSearch = getValueByPath(fromObject, ['fileSearch']); + if (fromFileSearch != null) { + setValueByPath(toObject, ['fileSearch'], fromFileSearch); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + if (getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined) { + throw new Error('enterpriseWebSearch parameter is not supported in Gemini API.'); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], googleMapsToMldev$2(fromGoogleMaps)); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], googleSearchToMldev$2(fromGoogleSearch)); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} +function toolToVertex$1(fromObject) { + const toObject = {}; + const fromRetrieval = getValueByPath(fromObject, ['retrieval']); + if (fromRetrieval != null) { + setValueByPath(toObject, ['retrieval'], fromRetrieval); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + if (getValueByPath(fromObject, ['fileSearch']) !== undefined) { + throw new Error('fileSearch parameter is not supported in Vertex AI.'); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + const fromEnterpriseWebSearch = getValueByPath(fromObject, [ + 'enterpriseWebSearch', + ]); + if (fromEnterpriseWebSearch != null) { + setValueByPath(toObject, ['enterpriseWebSearch'], fromEnterpriseWebSearch); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return functionDeclarationToVertex$1(item); + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], fromGoogleMaps); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], fromGoogleSearch); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} +function usageMetadataFromVertex(fromObject) { + const toObject = {}; + const fromPromptTokenCount = getValueByPath(fromObject, [ + 'promptTokenCount', + ]); + if (fromPromptTokenCount != null) { + setValueByPath(toObject, ['promptTokenCount'], fromPromptTokenCount); + } + const fromCachedContentTokenCount = getValueByPath(fromObject, [ + 'cachedContentTokenCount', + ]); + if (fromCachedContentTokenCount != null) { + setValueByPath(toObject, ['cachedContentTokenCount'], fromCachedContentTokenCount); + } + const fromResponseTokenCount = getValueByPath(fromObject, [ + 'candidatesTokenCount', + ]); + if (fromResponseTokenCount != null) { + setValueByPath(toObject, ['responseTokenCount'], fromResponseTokenCount); + } + const fromToolUsePromptTokenCount = getValueByPath(fromObject, [ + 'toolUsePromptTokenCount', + ]); + if (fromToolUsePromptTokenCount != null) { + setValueByPath(toObject, ['toolUsePromptTokenCount'], fromToolUsePromptTokenCount); + } + const fromThoughtsTokenCount = getValueByPath(fromObject, [ + 'thoughtsTokenCount', + ]); + if (fromThoughtsTokenCount != null) { + setValueByPath(toObject, ['thoughtsTokenCount'], fromThoughtsTokenCount); + } + const fromTotalTokenCount = getValueByPath(fromObject, [ + 'totalTokenCount', + ]); + if (fromTotalTokenCount != null) { + setValueByPath(toObject, ['totalTokenCount'], fromTotalTokenCount); + } + const fromPromptTokensDetails = getValueByPath(fromObject, [ + 'promptTokensDetails', + ]); + if (fromPromptTokensDetails != null) { + let transformedList = fromPromptTokensDetails; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['promptTokensDetails'], transformedList); + } + const fromCacheTokensDetails = getValueByPath(fromObject, [ + 'cacheTokensDetails', + ]); + if (fromCacheTokensDetails != null) { + let transformedList = fromCacheTokensDetails; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['cacheTokensDetails'], transformedList); + } + const fromResponseTokensDetails = getValueByPath(fromObject, [ + 'candidatesTokensDetails', + ]); + if (fromResponseTokensDetails != null) { + let transformedList = fromResponseTokensDetails; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['responseTokensDetails'], transformedList); + } + const fromToolUsePromptTokensDetails = getValueByPath(fromObject, [ + 'toolUsePromptTokensDetails', + ]); + if (fromToolUsePromptTokensDetails != null) { + let transformedList = fromToolUsePromptTokensDetails; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['toolUsePromptTokensDetails'], transformedList); + } + const fromTrafficType = getValueByPath(fromObject, ['trafficType']); + if (fromTrafficType != null) { + setValueByPath(toObject, ['trafficType'], fromTrafficType); + } + return toObject; +} +function voiceActivityFromVertex(fromObject) { + const toObject = {}; + const fromVoiceActivityType = getValueByPath(fromObject, ['type']); + if (fromVoiceActivityType != null) { + setValueByPath(toObject, ['voiceActivityType'], fromVoiceActivityType); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function blobToMldev$1(fromObject, _rootObject) { + const toObject = {}; + const fromData = getValueByPath(fromObject, ['data']); + if (fromData != null) { + setValueByPath(toObject, ['data'], fromData); + } + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function candidateFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromContent = getValueByPath(fromObject, ['content']); + if (fromContent != null) { + setValueByPath(toObject, ['content'], fromContent); + } + const fromCitationMetadata = getValueByPath(fromObject, [ + 'citationMetadata', + ]); + if (fromCitationMetadata != null) { + setValueByPath(toObject, ['citationMetadata'], citationMetadataFromMldev(fromCitationMetadata)); + } + const fromTokenCount = getValueByPath(fromObject, ['tokenCount']); + if (fromTokenCount != null) { + setValueByPath(toObject, ['tokenCount'], fromTokenCount); + } + const fromFinishReason = getValueByPath(fromObject, ['finishReason']); + if (fromFinishReason != null) { + setValueByPath(toObject, ['finishReason'], fromFinishReason); + } + const fromAvgLogprobs = getValueByPath(fromObject, ['avgLogprobs']); + if (fromAvgLogprobs != null) { + setValueByPath(toObject, ['avgLogprobs'], fromAvgLogprobs); + } + const fromGroundingMetadata = getValueByPath(fromObject, [ + 'groundingMetadata', + ]); + if (fromGroundingMetadata != null) { + setValueByPath(toObject, ['groundingMetadata'], fromGroundingMetadata); + } + const fromIndex = getValueByPath(fromObject, ['index']); + if (fromIndex != null) { + setValueByPath(toObject, ['index'], fromIndex); + } + const fromLogprobsResult = getValueByPath(fromObject, [ + 'logprobsResult', + ]); + if (fromLogprobsResult != null) { + setValueByPath(toObject, ['logprobsResult'], fromLogprobsResult); + } + const fromSafetyRatings = getValueByPath(fromObject, [ + 'safetyRatings', + ]); + if (fromSafetyRatings != null) { + let transformedList = fromSafetyRatings; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['safetyRatings'], transformedList); + } + const fromUrlContextMetadata = getValueByPath(fromObject, [ + 'urlContextMetadata', + ]); + if (fromUrlContextMetadata != null) { + setValueByPath(toObject, ['urlContextMetadata'], fromUrlContextMetadata); + } + return toObject; +} +function citationMetadataFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromCitations = getValueByPath(fromObject, ['citationSources']); + if (fromCitations != null) { + let transformedList = fromCitations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['citations'], transformedList); + } + return toObject; +} +function computeTokensParametersToVertex(apiClient, fromObject, _rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['contents'], transformedList); + } + return toObject; +} +function computeTokensResponseFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromTokensInfo = getValueByPath(fromObject, ['tokensInfo']); + if (fromTokensInfo != null) { + let transformedList = fromTokensInfo; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['tokensInfo'], transformedList); + } + return toObject; +} +function contentEmbeddingFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromValues = getValueByPath(fromObject, ['values']); + if (fromValues != null) { + setValueByPath(toObject, ['values'], fromValues); + } + const fromStatistics = getValueByPath(fromObject, ['statistics']); + if (fromStatistics != null) { + setValueByPath(toObject, ['statistics'], contentEmbeddingStatisticsFromVertex(fromStatistics)); + } + return toObject; +} +function contentEmbeddingStatisticsFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromTruncated = getValueByPath(fromObject, ['truncated']); + if (fromTruncated != null) { + setValueByPath(toObject, ['truncated'], fromTruncated); + } + const fromTokenCount = getValueByPath(fromObject, ['token_count']); + if (fromTokenCount != null) { + setValueByPath(toObject, ['tokenCount'], fromTokenCount); + } + return toObject; +} +function contentToMldev$1(fromObject, rootObject) { + const toObject = {}; + const fromParts = getValueByPath(fromObject, ['parts']); + if (fromParts != null) { + let transformedList = fromParts; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return partToMldev$1(item); + }); + } + setValueByPath(toObject, ['parts'], transformedList); + } + const fromRole = getValueByPath(fromObject, ['role']); + if (fromRole != null) { + setValueByPath(toObject, ['role'], fromRole); + } + return toObject; +} +function controlReferenceConfigToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromControlType = getValueByPath(fromObject, ['controlType']); + if (fromControlType != null) { + setValueByPath(toObject, ['controlType'], fromControlType); + } + const fromEnableControlImageComputation = getValueByPath(fromObject, [ + 'enableControlImageComputation', + ]); + if (fromEnableControlImageComputation != null) { + setValueByPath(toObject, ['computeControl'], fromEnableControlImageComputation); + } + return toObject; +} +function countTokensConfigToMldev(fromObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['systemInstruction']) !== undefined) { + throw new Error('systemInstruction parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['tools']) !== undefined) { + throw new Error('tools parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['generationConfig']) !== undefined) { + throw new Error('generationConfig parameter is not supported in Gemini API.'); + } + return toObject; +} +function countTokensConfigToVertex(fromObject, parentObject, rootObject) { + const toObject = {}; + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['systemInstruction'], tContent(fromSystemInstruction)); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = fromTools; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToVertex(item); + }); + } + setValueByPath(parentObject, ['tools'], transformedList); + } + const fromGenerationConfig = getValueByPath(fromObject, [ + 'generationConfig', + ]); + if (parentObject !== undefined && fromGenerationConfig != null) { + setValueByPath(parentObject, ['generationConfig'], generationConfigToVertex(fromGenerationConfig)); + } + return toObject; +} +function countTokensParametersToMldev(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return contentToMldev$1(item); + }); + } + setValueByPath(toObject, ['contents'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + countTokensConfigToMldev(fromConfig); + } + return toObject; +} +function countTokensParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['contents'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + countTokensConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function countTokensResponseFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromTotalTokens = getValueByPath(fromObject, ['totalTokens']); + if (fromTotalTokens != null) { + setValueByPath(toObject, ['totalTokens'], fromTotalTokens); + } + const fromCachedContentTokenCount = getValueByPath(fromObject, [ + 'cachedContentTokenCount', + ]); + if (fromCachedContentTokenCount != null) { + setValueByPath(toObject, ['cachedContentTokenCount'], fromCachedContentTokenCount); + } + return toObject; +} +function countTokensResponseFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromTotalTokens = getValueByPath(fromObject, ['totalTokens']); + if (fromTotalTokens != null) { + setValueByPath(toObject, ['totalTokens'], fromTotalTokens); + } + return toObject; +} +function deleteModelParametersToMldev(apiClient, fromObject, _rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'name'], tModel(apiClient, fromModel)); + } + return toObject; +} +function deleteModelParametersToVertex(apiClient, fromObject, _rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'name'], tModel(apiClient, fromModel)); + } + return toObject; +} +function deleteModelResponseFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function deleteModelResponseFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function editImageConfigToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromOutputGcsUri = getValueByPath(fromObject, ['outputGcsUri']); + if (parentObject !== undefined && fromOutputGcsUri != null) { + setValueByPath(parentObject, ['parameters', 'storageUri'], fromOutputGcsUri); + } + const fromNegativePrompt = getValueByPath(fromObject, [ + 'negativePrompt', + ]); + if (parentObject !== undefined && fromNegativePrompt != null) { + setValueByPath(parentObject, ['parameters', 'negativePrompt'], fromNegativePrompt); + } + const fromNumberOfImages = getValueByPath(fromObject, [ + 'numberOfImages', + ]); + if (parentObject !== undefined && fromNumberOfImages != null) { + setValueByPath(parentObject, ['parameters', 'sampleCount'], fromNumberOfImages); + } + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (parentObject !== undefined && fromAspectRatio != null) { + setValueByPath(parentObject, ['parameters', 'aspectRatio'], fromAspectRatio); + } + const fromGuidanceScale = getValueByPath(fromObject, [ + 'guidanceScale', + ]); + if (parentObject !== undefined && fromGuidanceScale != null) { + setValueByPath(parentObject, ['parameters', 'guidanceScale'], fromGuidanceScale); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (parentObject !== undefined && fromSeed != null) { + setValueByPath(parentObject, ['parameters', 'seed'], fromSeed); + } + const fromSafetyFilterLevel = getValueByPath(fromObject, [ + 'safetyFilterLevel', + ]); + if (parentObject !== undefined && fromSafetyFilterLevel != null) { + setValueByPath(parentObject, ['parameters', 'safetySetting'], fromSafetyFilterLevel); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (parentObject !== undefined && fromPersonGeneration != null) { + setValueByPath(parentObject, ['parameters', 'personGeneration'], fromPersonGeneration); + } + const fromIncludeSafetyAttributes = getValueByPath(fromObject, [ + 'includeSafetyAttributes', + ]); + if (parentObject !== undefined && fromIncludeSafetyAttributes != null) { + setValueByPath(parentObject, ['parameters', 'includeSafetyAttributes'], fromIncludeSafetyAttributes); + } + const fromIncludeRaiReason = getValueByPath(fromObject, [ + 'includeRaiReason', + ]); + if (parentObject !== undefined && fromIncludeRaiReason != null) { + setValueByPath(parentObject, ['parameters', 'includeRaiReason'], fromIncludeRaiReason); + } + const fromLanguage = getValueByPath(fromObject, ['language']); + if (parentObject !== undefined && fromLanguage != null) { + setValueByPath(parentObject, ['parameters', 'language'], fromLanguage); + } + const fromOutputMimeType = getValueByPath(fromObject, [ + 'outputMimeType', + ]); + if (parentObject !== undefined && fromOutputMimeType != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'mimeType'], fromOutputMimeType); + } + const fromOutputCompressionQuality = getValueByPath(fromObject, [ + 'outputCompressionQuality', + ]); + if (parentObject !== undefined && fromOutputCompressionQuality != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'compressionQuality'], fromOutputCompressionQuality); + } + const fromAddWatermark = getValueByPath(fromObject, ['addWatermark']); + if (parentObject !== undefined && fromAddWatermark != null) { + setValueByPath(parentObject, ['parameters', 'addWatermark'], fromAddWatermark); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (parentObject !== undefined && fromLabels != null) { + setValueByPath(parentObject, ['labels'], fromLabels); + } + const fromEditMode = getValueByPath(fromObject, ['editMode']); + if (parentObject !== undefined && fromEditMode != null) { + setValueByPath(parentObject, ['parameters', 'editMode'], fromEditMode); + } + const fromBaseSteps = getValueByPath(fromObject, ['baseSteps']); + if (parentObject !== undefined && fromBaseSteps != null) { + setValueByPath(parentObject, ['parameters', 'editConfig', 'baseSteps'], fromBaseSteps); + } + return toObject; +} +function editImageParametersInternalToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (fromPrompt != null) { + setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromReferenceImages = getValueByPath(fromObject, [ + 'referenceImages', + ]); + if (fromReferenceImages != null) { + let transformedList = fromReferenceImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return referenceImageAPIInternalToVertex(item); + }); + } + setValueByPath(toObject, ['instances[0]', 'referenceImages'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + editImageConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function editImageResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromGeneratedImages = getValueByPath(fromObject, [ + 'predictions', + ]); + if (fromGeneratedImages != null) { + let transformedList = fromGeneratedImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedImageFromVertex(item); + }); + } + setValueByPath(toObject, ['generatedImages'], transformedList); + } + return toObject; +} +function embedContentConfigToMldev(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromTaskType = getValueByPath(fromObject, ['taskType']); + if (parentObject !== undefined && fromTaskType != null) { + setValueByPath(parentObject, ['requests[]', 'taskType'], fromTaskType); + } + const fromTitle = getValueByPath(fromObject, ['title']); + if (parentObject !== undefined && fromTitle != null) { + setValueByPath(parentObject, ['requests[]', 'title'], fromTitle); + } + const fromOutputDimensionality = getValueByPath(fromObject, [ + 'outputDimensionality', + ]); + if (parentObject !== undefined && fromOutputDimensionality != null) { + setValueByPath(parentObject, ['requests[]', 'outputDimensionality'], fromOutputDimensionality); + } + if (getValueByPath(fromObject, ['mimeType']) !== undefined) { + throw new Error('mimeType parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['autoTruncate']) !== undefined) { + throw new Error('autoTruncate parameter is not supported in Gemini API.'); + } + return toObject; +} +function embedContentConfigToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromTaskType = getValueByPath(fromObject, ['taskType']); + if (parentObject !== undefined && fromTaskType != null) { + setValueByPath(parentObject, ['instances[]', 'task_type'], fromTaskType); + } + const fromTitle = getValueByPath(fromObject, ['title']); + if (parentObject !== undefined && fromTitle != null) { + setValueByPath(parentObject, ['instances[]', 'title'], fromTitle); + } + const fromOutputDimensionality = getValueByPath(fromObject, [ + 'outputDimensionality', + ]); + if (parentObject !== undefined && fromOutputDimensionality != null) { + setValueByPath(parentObject, ['parameters', 'outputDimensionality'], fromOutputDimensionality); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (parentObject !== undefined && fromMimeType != null) { + setValueByPath(parentObject, ['instances[]', 'mimeType'], fromMimeType); + } + const fromAutoTruncate = getValueByPath(fromObject, ['autoTruncate']); + if (parentObject !== undefined && fromAutoTruncate != null) { + setValueByPath(parentObject, ['parameters', 'autoTruncate'], fromAutoTruncate); + } + return toObject; +} +function embedContentParametersToMldev(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContentsForEmbed(apiClient, fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['requests[]', 'content'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + embedContentConfigToMldev(fromConfig, toObject); + } + const fromModelForEmbedContent = getValueByPath(fromObject, ['model']); + if (fromModelForEmbedContent !== undefined) { + setValueByPath(toObject, ['requests[]', 'model'], tModel(apiClient, fromModelForEmbedContent)); + } + return toObject; +} +function embedContentParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContentsForEmbed(apiClient, fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['instances[]', 'content'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + embedContentConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function embedContentResponseFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromEmbeddings = getValueByPath(fromObject, ['embeddings']); + if (fromEmbeddings != null) { + let transformedList = fromEmbeddings; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['embeddings'], transformedList); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + return toObject; +} +function embedContentResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromEmbeddings = getValueByPath(fromObject, [ + 'predictions[]', + 'embeddings', + ]); + if (fromEmbeddings != null) { + let transformedList = fromEmbeddings; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return contentEmbeddingFromVertex(item); + }); + } + setValueByPath(toObject, ['embeddings'], transformedList); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + return toObject; +} +function endpointFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['endpoint']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromDeployedModelId = getValueByPath(fromObject, [ + 'deployedModelId', + ]); + if (fromDeployedModelId != null) { + setValueByPath(toObject, ['deployedModelId'], fromDeployedModelId); + } + return toObject; +} +function fileDataToMldev$1(fromObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromFileUri = getValueByPath(fromObject, ['fileUri']); + if (fromFileUri != null) { + setValueByPath(toObject, ['fileUri'], fromFileUri); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function functionCallToMldev$1(fromObject, _rootObject) { + const toObject = {}; + const fromId = getValueByPath(fromObject, ['id']); + if (fromId != null) { + setValueByPath(toObject, ['id'], fromId); + } + const fromArgs = getValueByPath(fromObject, ['args']); + if (fromArgs != null) { + setValueByPath(toObject, ['args'], fromArgs); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + if (getValueByPath(fromObject, ['partialArgs']) !== undefined) { + throw new Error('partialArgs parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['willContinue']) !== undefined) { + throw new Error('willContinue parameter is not supported in Gemini API.'); + } + return toObject; +} +function functionCallingConfigToMldev(fromObject, _rootObject) { + const toObject = {}; + const fromAllowedFunctionNames = getValueByPath(fromObject, [ + 'allowedFunctionNames', + ]); + if (fromAllowedFunctionNames != null) { + setValueByPath(toObject, ['allowedFunctionNames'], fromAllowedFunctionNames); + } + const fromMode = getValueByPath(fromObject, ['mode']); + if (fromMode != null) { + setValueByPath(toObject, ['mode'], fromMode); + } + if (getValueByPath(fromObject, ['streamFunctionCallArguments']) !== + undefined) { + throw new Error('streamFunctionCallArguments parameter is not supported in Gemini API.'); + } + return toObject; +} +function functionDeclarationToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromDescription = getValueByPath(fromObject, ['description']); + if (fromDescription != null) { + setValueByPath(toObject, ['description'], fromDescription); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromParameters = getValueByPath(fromObject, ['parameters']); + if (fromParameters != null) { + setValueByPath(toObject, ['parameters'], fromParameters); + } + const fromParametersJsonSchema = getValueByPath(fromObject, [ + 'parametersJsonSchema', + ]); + if (fromParametersJsonSchema != null) { + setValueByPath(toObject, ['parametersJsonSchema'], fromParametersJsonSchema); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], fromResponse); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + if (getValueByPath(fromObject, ['behavior']) !== undefined) { + throw new Error('behavior parameter is not supported in Vertex AI.'); + } + return toObject; +} +function generateContentConfigToMldev(apiClient, fromObject, parentObject, rootObject) { + const toObject = {}; + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['systemInstruction'], contentToMldev$1(tContent(fromSystemInstruction))); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (fromTemperature != null) { + setValueByPath(toObject, ['temperature'], fromTemperature); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (fromTopP != null) { + setValueByPath(toObject, ['topP'], fromTopP); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (fromTopK != null) { + setValueByPath(toObject, ['topK'], fromTopK); + } + const fromCandidateCount = getValueByPath(fromObject, [ + 'candidateCount', + ]); + if (fromCandidateCount != null) { + setValueByPath(toObject, ['candidateCount'], fromCandidateCount); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (fromMaxOutputTokens != null) { + setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens); + } + const fromStopSequences = getValueByPath(fromObject, [ + 'stopSequences', + ]); + if (fromStopSequences != null) { + setValueByPath(toObject, ['stopSequences'], fromStopSequences); + } + const fromResponseLogprobs = getValueByPath(fromObject, [ + 'responseLogprobs', + ]); + if (fromResponseLogprobs != null) { + setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs); + } + const fromLogprobs = getValueByPath(fromObject, ['logprobs']); + if (fromLogprobs != null) { + setValueByPath(toObject, ['logprobs'], fromLogprobs); + } + const fromPresencePenalty = getValueByPath(fromObject, [ + 'presencePenalty', + ]); + if (fromPresencePenalty != null) { + setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty); + } + const fromFrequencyPenalty = getValueByPath(fromObject, [ + 'frequencyPenalty', + ]); + if (fromFrequencyPenalty != null) { + setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (fromSeed != null) { + setValueByPath(toObject, ['seed'], fromSeed); + } + const fromResponseMimeType = getValueByPath(fromObject, [ + 'responseMimeType', + ]); + if (fromResponseMimeType != null) { + setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType); + } + const fromResponseSchema = getValueByPath(fromObject, [ + 'responseSchema', + ]); + if (fromResponseSchema != null) { + setValueByPath(toObject, ['responseSchema'], tSchema(fromResponseSchema)); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + if (getValueByPath(fromObject, ['routingConfig']) !== undefined) { + throw new Error('routingConfig parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['modelSelectionConfig']) !== undefined) { + throw new Error('modelSelectionConfig parameter is not supported in Gemini API.'); + } + const fromSafetySettings = getValueByPath(fromObject, [ + 'safetySettings', + ]); + if (parentObject !== undefined && fromSafetySettings != null) { + let transformedList = fromSafetySettings; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return safetySettingToMldev(item); + }); + } + setValueByPath(parentObject, ['safetySettings'], transformedList); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = tTools(fromTools); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToMldev$1(tTool(item)); + }); + } + setValueByPath(parentObject, ['tools'], transformedList); + } + const fromToolConfig = getValueByPath(fromObject, ['toolConfig']); + if (parentObject !== undefined && fromToolConfig != null) { + setValueByPath(parentObject, ['toolConfig'], toolConfigToMldev(fromToolConfig)); + } + if (getValueByPath(fromObject, ['labels']) !== undefined) { + throw new Error('labels parameter is not supported in Gemini API.'); + } + const fromCachedContent = getValueByPath(fromObject, [ + 'cachedContent', + ]); + if (parentObject !== undefined && fromCachedContent != null) { + setValueByPath(parentObject, ['cachedContent'], tCachedContentName(apiClient, fromCachedContent)); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (fromResponseModalities != null) { + setValueByPath(toObject, ['responseModalities'], fromResponseModalities); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (fromSpeechConfig != null) { + setValueByPath(toObject, ['speechConfig'], tSpeechConfig(fromSpeechConfig)); + } + if (getValueByPath(fromObject, ['audioTimestamp']) !== undefined) { + throw new Error('audioTimestamp parameter is not supported in Gemini API.'); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (fromThinkingConfig != null) { + setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig); + } + const fromImageConfig = getValueByPath(fromObject, ['imageConfig']); + if (fromImageConfig != null) { + setValueByPath(toObject, ['imageConfig'], imageConfigToMldev(fromImageConfig)); + } + const fromEnableEnhancedCivicAnswers = getValueByPath(fromObject, [ + 'enableEnhancedCivicAnswers', + ]); + if (fromEnableEnhancedCivicAnswers != null) { + setValueByPath(toObject, ['enableEnhancedCivicAnswers'], fromEnableEnhancedCivicAnswers); + } + if (getValueByPath(fromObject, ['modelArmorConfig']) !== undefined) { + throw new Error('modelArmorConfig parameter is not supported in Gemini API.'); + } + return toObject; +} +function generateContentConfigToVertex(apiClient, fromObject, parentObject, rootObject) { + const toObject = {}; + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['systemInstruction'], tContent(fromSystemInstruction)); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (fromTemperature != null) { + setValueByPath(toObject, ['temperature'], fromTemperature); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (fromTopP != null) { + setValueByPath(toObject, ['topP'], fromTopP); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (fromTopK != null) { + setValueByPath(toObject, ['topK'], fromTopK); + } + const fromCandidateCount = getValueByPath(fromObject, [ + 'candidateCount', + ]); + if (fromCandidateCount != null) { + setValueByPath(toObject, ['candidateCount'], fromCandidateCount); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (fromMaxOutputTokens != null) { + setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens); + } + const fromStopSequences = getValueByPath(fromObject, [ + 'stopSequences', + ]); + if (fromStopSequences != null) { + setValueByPath(toObject, ['stopSequences'], fromStopSequences); + } + const fromResponseLogprobs = getValueByPath(fromObject, [ + 'responseLogprobs', + ]); + if (fromResponseLogprobs != null) { + setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs); + } + const fromLogprobs = getValueByPath(fromObject, ['logprobs']); + if (fromLogprobs != null) { + setValueByPath(toObject, ['logprobs'], fromLogprobs); + } + const fromPresencePenalty = getValueByPath(fromObject, [ + 'presencePenalty', + ]); + if (fromPresencePenalty != null) { + setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty); + } + const fromFrequencyPenalty = getValueByPath(fromObject, [ + 'frequencyPenalty', + ]); + if (fromFrequencyPenalty != null) { + setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (fromSeed != null) { + setValueByPath(toObject, ['seed'], fromSeed); + } + const fromResponseMimeType = getValueByPath(fromObject, [ + 'responseMimeType', + ]); + if (fromResponseMimeType != null) { + setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType); + } + const fromResponseSchema = getValueByPath(fromObject, [ + 'responseSchema', + ]); + if (fromResponseSchema != null) { + setValueByPath(toObject, ['responseSchema'], tSchema(fromResponseSchema)); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + const fromRoutingConfig = getValueByPath(fromObject, [ + 'routingConfig', + ]); + if (fromRoutingConfig != null) { + setValueByPath(toObject, ['routingConfig'], fromRoutingConfig); + } + const fromModelSelectionConfig = getValueByPath(fromObject, [ + 'modelSelectionConfig', + ]); + if (fromModelSelectionConfig != null) { + setValueByPath(toObject, ['modelConfig'], fromModelSelectionConfig); + } + const fromSafetySettings = getValueByPath(fromObject, [ + 'safetySettings', + ]); + if (parentObject !== undefined && fromSafetySettings != null) { + let transformedList = fromSafetySettings; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(parentObject, ['safetySettings'], transformedList); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = tTools(fromTools); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToVertex(tTool(item)); + }); + } + setValueByPath(parentObject, ['tools'], transformedList); + } + const fromToolConfig = getValueByPath(fromObject, ['toolConfig']); + if (parentObject !== undefined && fromToolConfig != null) { + setValueByPath(parentObject, ['toolConfig'], fromToolConfig); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (parentObject !== undefined && fromLabels != null) { + setValueByPath(parentObject, ['labels'], fromLabels); + } + const fromCachedContent = getValueByPath(fromObject, [ + 'cachedContent', + ]); + if (parentObject !== undefined && fromCachedContent != null) { + setValueByPath(parentObject, ['cachedContent'], tCachedContentName(apiClient, fromCachedContent)); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (fromResponseModalities != null) { + setValueByPath(toObject, ['responseModalities'], fromResponseModalities); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (fromSpeechConfig != null) { + setValueByPath(toObject, ['speechConfig'], tSpeechConfig(fromSpeechConfig)); + } + const fromAudioTimestamp = getValueByPath(fromObject, [ + 'audioTimestamp', + ]); + if (fromAudioTimestamp != null) { + setValueByPath(toObject, ['audioTimestamp'], fromAudioTimestamp); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (fromThinkingConfig != null) { + setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig); + } + const fromImageConfig = getValueByPath(fromObject, ['imageConfig']); + if (fromImageConfig != null) { + setValueByPath(toObject, ['imageConfig'], imageConfigToVertex(fromImageConfig)); + } + if (getValueByPath(fromObject, ['enableEnhancedCivicAnswers']) !== + undefined) { + throw new Error('enableEnhancedCivicAnswers parameter is not supported in Vertex AI.'); + } + const fromModelArmorConfig = getValueByPath(fromObject, [ + 'modelArmorConfig', + ]); + if (parentObject !== undefined && fromModelArmorConfig != null) { + setValueByPath(parentObject, ['modelArmorConfig'], fromModelArmorConfig); + } + return toObject; +} +function generateContentParametersToMldev(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return contentToMldev$1(item); + }); + } + setValueByPath(toObject, ['contents'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['generationConfig'], generateContentConfigToMldev(apiClient, fromConfig, toObject)); + } + return toObject; +} +function generateContentParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['contents'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['generationConfig'], generateContentConfigToVertex(apiClient, fromConfig, toObject)); + } + return toObject; +} +function generateContentResponseFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromCandidates = getValueByPath(fromObject, ['candidates']); + if (fromCandidates != null) { + let transformedList = fromCandidates; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return candidateFromMldev(item); + }); + } + setValueByPath(toObject, ['candidates'], transformedList); + } + const fromModelVersion = getValueByPath(fromObject, ['modelVersion']); + if (fromModelVersion != null) { + setValueByPath(toObject, ['modelVersion'], fromModelVersion); + } + const fromPromptFeedback = getValueByPath(fromObject, [ + 'promptFeedback', + ]); + if (fromPromptFeedback != null) { + setValueByPath(toObject, ['promptFeedback'], fromPromptFeedback); + } + const fromResponseId = getValueByPath(fromObject, ['responseId']); + if (fromResponseId != null) { + setValueByPath(toObject, ['responseId'], fromResponseId); + } + const fromUsageMetadata = getValueByPath(fromObject, [ + 'usageMetadata', + ]); + if (fromUsageMetadata != null) { + setValueByPath(toObject, ['usageMetadata'], fromUsageMetadata); + } + return toObject; +} +function generateContentResponseFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromCandidates = getValueByPath(fromObject, ['candidates']); + if (fromCandidates != null) { + let transformedList = fromCandidates; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['candidates'], transformedList); + } + const fromCreateTime = getValueByPath(fromObject, ['createTime']); + if (fromCreateTime != null) { + setValueByPath(toObject, ['createTime'], fromCreateTime); + } + const fromModelVersion = getValueByPath(fromObject, ['modelVersion']); + if (fromModelVersion != null) { + setValueByPath(toObject, ['modelVersion'], fromModelVersion); + } + const fromPromptFeedback = getValueByPath(fromObject, [ + 'promptFeedback', + ]); + if (fromPromptFeedback != null) { + setValueByPath(toObject, ['promptFeedback'], fromPromptFeedback); + } + const fromResponseId = getValueByPath(fromObject, ['responseId']); + if (fromResponseId != null) { + setValueByPath(toObject, ['responseId'], fromResponseId); + } + const fromUsageMetadata = getValueByPath(fromObject, [ + 'usageMetadata', + ]); + if (fromUsageMetadata != null) { + setValueByPath(toObject, ['usageMetadata'], fromUsageMetadata); + } + return toObject; +} +function generateImagesConfigToMldev(fromObject, parentObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['outputGcsUri']) !== undefined) { + throw new Error('outputGcsUri parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['negativePrompt']) !== undefined) { + throw new Error('negativePrompt parameter is not supported in Gemini API.'); + } + const fromNumberOfImages = getValueByPath(fromObject, [ + 'numberOfImages', + ]); + if (parentObject !== undefined && fromNumberOfImages != null) { + setValueByPath(parentObject, ['parameters', 'sampleCount'], fromNumberOfImages); + } + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (parentObject !== undefined && fromAspectRatio != null) { + setValueByPath(parentObject, ['parameters', 'aspectRatio'], fromAspectRatio); + } + const fromGuidanceScale = getValueByPath(fromObject, [ + 'guidanceScale', + ]); + if (parentObject !== undefined && fromGuidanceScale != null) { + setValueByPath(parentObject, ['parameters', 'guidanceScale'], fromGuidanceScale); + } + if (getValueByPath(fromObject, ['seed']) !== undefined) { + throw new Error('seed parameter is not supported in Gemini API.'); + } + const fromSafetyFilterLevel = getValueByPath(fromObject, [ + 'safetyFilterLevel', + ]); + if (parentObject !== undefined && fromSafetyFilterLevel != null) { + setValueByPath(parentObject, ['parameters', 'safetySetting'], fromSafetyFilterLevel); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (parentObject !== undefined && fromPersonGeneration != null) { + setValueByPath(parentObject, ['parameters', 'personGeneration'], fromPersonGeneration); + } + const fromIncludeSafetyAttributes = getValueByPath(fromObject, [ + 'includeSafetyAttributes', + ]); + if (parentObject !== undefined && fromIncludeSafetyAttributes != null) { + setValueByPath(parentObject, ['parameters', 'includeSafetyAttributes'], fromIncludeSafetyAttributes); + } + const fromIncludeRaiReason = getValueByPath(fromObject, [ + 'includeRaiReason', + ]); + if (parentObject !== undefined && fromIncludeRaiReason != null) { + setValueByPath(parentObject, ['parameters', 'includeRaiReason'], fromIncludeRaiReason); + } + const fromLanguage = getValueByPath(fromObject, ['language']); + if (parentObject !== undefined && fromLanguage != null) { + setValueByPath(parentObject, ['parameters', 'language'], fromLanguage); + } + const fromOutputMimeType = getValueByPath(fromObject, [ + 'outputMimeType', + ]); + if (parentObject !== undefined && fromOutputMimeType != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'mimeType'], fromOutputMimeType); + } + const fromOutputCompressionQuality = getValueByPath(fromObject, [ + 'outputCompressionQuality', + ]); + if (parentObject !== undefined && fromOutputCompressionQuality != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'compressionQuality'], fromOutputCompressionQuality); + } + if (getValueByPath(fromObject, ['addWatermark']) !== undefined) { + throw new Error('addWatermark parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['labels']) !== undefined) { + throw new Error('labels parameter is not supported in Gemini API.'); + } + const fromImageSize = getValueByPath(fromObject, ['imageSize']); + if (parentObject !== undefined && fromImageSize != null) { + setValueByPath(parentObject, ['parameters', 'sampleImageSize'], fromImageSize); + } + if (getValueByPath(fromObject, ['enhancePrompt']) !== undefined) { + throw new Error('enhancePrompt parameter is not supported in Gemini API.'); + } + return toObject; +} +function generateImagesConfigToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromOutputGcsUri = getValueByPath(fromObject, ['outputGcsUri']); + if (parentObject !== undefined && fromOutputGcsUri != null) { + setValueByPath(parentObject, ['parameters', 'storageUri'], fromOutputGcsUri); + } + const fromNegativePrompt = getValueByPath(fromObject, [ + 'negativePrompt', + ]); + if (parentObject !== undefined && fromNegativePrompt != null) { + setValueByPath(parentObject, ['parameters', 'negativePrompt'], fromNegativePrompt); + } + const fromNumberOfImages = getValueByPath(fromObject, [ + 'numberOfImages', + ]); + if (parentObject !== undefined && fromNumberOfImages != null) { + setValueByPath(parentObject, ['parameters', 'sampleCount'], fromNumberOfImages); + } + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (parentObject !== undefined && fromAspectRatio != null) { + setValueByPath(parentObject, ['parameters', 'aspectRatio'], fromAspectRatio); + } + const fromGuidanceScale = getValueByPath(fromObject, [ + 'guidanceScale', + ]); + if (parentObject !== undefined && fromGuidanceScale != null) { + setValueByPath(parentObject, ['parameters', 'guidanceScale'], fromGuidanceScale); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (parentObject !== undefined && fromSeed != null) { + setValueByPath(parentObject, ['parameters', 'seed'], fromSeed); + } + const fromSafetyFilterLevel = getValueByPath(fromObject, [ + 'safetyFilterLevel', + ]); + if (parentObject !== undefined && fromSafetyFilterLevel != null) { + setValueByPath(parentObject, ['parameters', 'safetySetting'], fromSafetyFilterLevel); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (parentObject !== undefined && fromPersonGeneration != null) { + setValueByPath(parentObject, ['parameters', 'personGeneration'], fromPersonGeneration); + } + const fromIncludeSafetyAttributes = getValueByPath(fromObject, [ + 'includeSafetyAttributes', + ]); + if (parentObject !== undefined && fromIncludeSafetyAttributes != null) { + setValueByPath(parentObject, ['parameters', 'includeSafetyAttributes'], fromIncludeSafetyAttributes); + } + const fromIncludeRaiReason = getValueByPath(fromObject, [ + 'includeRaiReason', + ]); + if (parentObject !== undefined && fromIncludeRaiReason != null) { + setValueByPath(parentObject, ['parameters', 'includeRaiReason'], fromIncludeRaiReason); + } + const fromLanguage = getValueByPath(fromObject, ['language']); + if (parentObject !== undefined && fromLanguage != null) { + setValueByPath(parentObject, ['parameters', 'language'], fromLanguage); + } + const fromOutputMimeType = getValueByPath(fromObject, [ + 'outputMimeType', + ]); + if (parentObject !== undefined && fromOutputMimeType != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'mimeType'], fromOutputMimeType); + } + const fromOutputCompressionQuality = getValueByPath(fromObject, [ + 'outputCompressionQuality', + ]); + if (parentObject !== undefined && fromOutputCompressionQuality != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'compressionQuality'], fromOutputCompressionQuality); + } + const fromAddWatermark = getValueByPath(fromObject, ['addWatermark']); + if (parentObject !== undefined && fromAddWatermark != null) { + setValueByPath(parentObject, ['parameters', 'addWatermark'], fromAddWatermark); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (parentObject !== undefined && fromLabels != null) { + setValueByPath(parentObject, ['labels'], fromLabels); + } + const fromImageSize = getValueByPath(fromObject, ['imageSize']); + if (parentObject !== undefined && fromImageSize != null) { + setValueByPath(parentObject, ['parameters', 'sampleImageSize'], fromImageSize); + } + const fromEnhancePrompt = getValueByPath(fromObject, [ + 'enhancePrompt', + ]); + if (parentObject !== undefined && fromEnhancePrompt != null) { + setValueByPath(parentObject, ['parameters', 'enhancePrompt'], fromEnhancePrompt); + } + return toObject; +} +function generateImagesParametersToMldev(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (fromPrompt != null) { + setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + generateImagesConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function generateImagesParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (fromPrompt != null) { + setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + generateImagesConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function generateImagesResponseFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromGeneratedImages = getValueByPath(fromObject, [ + 'predictions', + ]); + if (fromGeneratedImages != null) { + let transformedList = fromGeneratedImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedImageFromMldev(item); + }); + } + setValueByPath(toObject, ['generatedImages'], transformedList); + } + const fromPositivePromptSafetyAttributes = getValueByPath(fromObject, [ + 'positivePromptSafetyAttributes', + ]); + if (fromPositivePromptSafetyAttributes != null) { + setValueByPath(toObject, ['positivePromptSafetyAttributes'], safetyAttributesFromMldev(fromPositivePromptSafetyAttributes)); + } + return toObject; +} +function generateImagesResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromGeneratedImages = getValueByPath(fromObject, [ + 'predictions', + ]); + if (fromGeneratedImages != null) { + let transformedList = fromGeneratedImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedImageFromVertex(item); + }); + } + setValueByPath(toObject, ['generatedImages'], transformedList); + } + const fromPositivePromptSafetyAttributes = getValueByPath(fromObject, [ + 'positivePromptSafetyAttributes', + ]); + if (fromPositivePromptSafetyAttributes != null) { + setValueByPath(toObject, ['positivePromptSafetyAttributes'], safetyAttributesFromVertex(fromPositivePromptSafetyAttributes)); + } + return toObject; +} +function generateVideosConfigToMldev(fromObject, parentObject, rootObject) { + const toObject = {}; + const fromNumberOfVideos = getValueByPath(fromObject, [ + 'numberOfVideos', + ]); + if (parentObject !== undefined && fromNumberOfVideos != null) { + setValueByPath(parentObject, ['parameters', 'sampleCount'], fromNumberOfVideos); + } + if (getValueByPath(fromObject, ['outputGcsUri']) !== undefined) { + throw new Error('outputGcsUri parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['fps']) !== undefined) { + throw new Error('fps parameter is not supported in Gemini API.'); + } + const fromDurationSeconds = getValueByPath(fromObject, [ + 'durationSeconds', + ]); + if (parentObject !== undefined && fromDurationSeconds != null) { + setValueByPath(parentObject, ['parameters', 'durationSeconds'], fromDurationSeconds); + } + if (getValueByPath(fromObject, ['seed']) !== undefined) { + throw new Error('seed parameter is not supported in Gemini API.'); + } + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (parentObject !== undefined && fromAspectRatio != null) { + setValueByPath(parentObject, ['parameters', 'aspectRatio'], fromAspectRatio); + } + const fromResolution = getValueByPath(fromObject, ['resolution']); + if (parentObject !== undefined && fromResolution != null) { + setValueByPath(parentObject, ['parameters', 'resolution'], fromResolution); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (parentObject !== undefined && fromPersonGeneration != null) { + setValueByPath(parentObject, ['parameters', 'personGeneration'], fromPersonGeneration); + } + if (getValueByPath(fromObject, ['pubsubTopic']) !== undefined) { + throw new Error('pubsubTopic parameter is not supported in Gemini API.'); + } + const fromNegativePrompt = getValueByPath(fromObject, [ + 'negativePrompt', + ]); + if (parentObject !== undefined && fromNegativePrompt != null) { + setValueByPath(parentObject, ['parameters', 'negativePrompt'], fromNegativePrompt); + } + const fromEnhancePrompt = getValueByPath(fromObject, [ + 'enhancePrompt', + ]); + if (parentObject !== undefined && fromEnhancePrompt != null) { + setValueByPath(parentObject, ['parameters', 'enhancePrompt'], fromEnhancePrompt); + } + if (getValueByPath(fromObject, ['generateAudio']) !== undefined) { + throw new Error('generateAudio parameter is not supported in Gemini API.'); + } + const fromLastFrame = getValueByPath(fromObject, ['lastFrame']); + if (parentObject !== undefined && fromLastFrame != null) { + setValueByPath(parentObject, ['instances[0]', 'lastFrame'], imageToMldev(fromLastFrame)); + } + const fromReferenceImages = getValueByPath(fromObject, [ + 'referenceImages', + ]); + if (parentObject !== undefined && fromReferenceImages != null) { + let transformedList = fromReferenceImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return videoGenerationReferenceImageToMldev(item); + }); + } + setValueByPath(parentObject, ['instances[0]', 'referenceImages'], transformedList); + } + if (getValueByPath(fromObject, ['mask']) !== undefined) { + throw new Error('mask parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['compressionQuality']) !== undefined) { + throw new Error('compressionQuality parameter is not supported in Gemini API.'); + } + return toObject; +} +function generateVideosConfigToVertex(fromObject, parentObject, rootObject) { + const toObject = {}; + const fromNumberOfVideos = getValueByPath(fromObject, [ + 'numberOfVideos', + ]); + if (parentObject !== undefined && fromNumberOfVideos != null) { + setValueByPath(parentObject, ['parameters', 'sampleCount'], fromNumberOfVideos); + } + const fromOutputGcsUri = getValueByPath(fromObject, ['outputGcsUri']); + if (parentObject !== undefined && fromOutputGcsUri != null) { + setValueByPath(parentObject, ['parameters', 'storageUri'], fromOutputGcsUri); + } + const fromFps = getValueByPath(fromObject, ['fps']); + if (parentObject !== undefined && fromFps != null) { + setValueByPath(parentObject, ['parameters', 'fps'], fromFps); + } + const fromDurationSeconds = getValueByPath(fromObject, [ + 'durationSeconds', + ]); + if (parentObject !== undefined && fromDurationSeconds != null) { + setValueByPath(parentObject, ['parameters', 'durationSeconds'], fromDurationSeconds); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (parentObject !== undefined && fromSeed != null) { + setValueByPath(parentObject, ['parameters', 'seed'], fromSeed); + } + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (parentObject !== undefined && fromAspectRatio != null) { + setValueByPath(parentObject, ['parameters', 'aspectRatio'], fromAspectRatio); + } + const fromResolution = getValueByPath(fromObject, ['resolution']); + if (parentObject !== undefined && fromResolution != null) { + setValueByPath(parentObject, ['parameters', 'resolution'], fromResolution); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (parentObject !== undefined && fromPersonGeneration != null) { + setValueByPath(parentObject, ['parameters', 'personGeneration'], fromPersonGeneration); + } + const fromPubsubTopic = getValueByPath(fromObject, ['pubsubTopic']); + if (parentObject !== undefined && fromPubsubTopic != null) { + setValueByPath(parentObject, ['parameters', 'pubsubTopic'], fromPubsubTopic); + } + const fromNegativePrompt = getValueByPath(fromObject, [ + 'negativePrompt', + ]); + if (parentObject !== undefined && fromNegativePrompt != null) { + setValueByPath(parentObject, ['parameters', 'negativePrompt'], fromNegativePrompt); + } + const fromEnhancePrompt = getValueByPath(fromObject, [ + 'enhancePrompt', + ]); + if (parentObject !== undefined && fromEnhancePrompt != null) { + setValueByPath(parentObject, ['parameters', 'enhancePrompt'], fromEnhancePrompt); + } + const fromGenerateAudio = getValueByPath(fromObject, [ + 'generateAudio', + ]); + if (parentObject !== undefined && fromGenerateAudio != null) { + setValueByPath(parentObject, ['parameters', 'generateAudio'], fromGenerateAudio); + } + const fromLastFrame = getValueByPath(fromObject, ['lastFrame']); + if (parentObject !== undefined && fromLastFrame != null) { + setValueByPath(parentObject, ['instances[0]', 'lastFrame'], imageToVertex(fromLastFrame)); + } + const fromReferenceImages = getValueByPath(fromObject, [ + 'referenceImages', + ]); + if (parentObject !== undefined && fromReferenceImages != null) { + let transformedList = fromReferenceImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return videoGenerationReferenceImageToVertex(item); + }); + } + setValueByPath(parentObject, ['instances[0]', 'referenceImages'], transformedList); + } + const fromMask = getValueByPath(fromObject, ['mask']); + if (parentObject !== undefined && fromMask != null) { + setValueByPath(parentObject, ['instances[0]', 'mask'], videoGenerationMaskToVertex(fromMask)); + } + const fromCompressionQuality = getValueByPath(fromObject, [ + 'compressionQuality', + ]); + if (parentObject !== undefined && fromCompressionQuality != null) { + setValueByPath(parentObject, ['parameters', 'compressionQuality'], fromCompressionQuality); + } + return toObject; +} +function generateVideosOperationFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromResponse = getValueByPath(fromObject, [ + 'response', + 'generateVideoResponse', + ]); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], generateVideosResponseFromMldev(fromResponse)); + } + return toObject; +} +function generateVideosOperationFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], generateVideosResponseFromVertex(fromResponse)); + } + return toObject; +} +function generateVideosParametersToMldev(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (fromPrompt != null) { + setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromImage = getValueByPath(fromObject, ['image']); + if (fromImage != null) { + setValueByPath(toObject, ['instances[0]', 'image'], imageToMldev(fromImage)); + } + const fromVideo = getValueByPath(fromObject, ['video']); + if (fromVideo != null) { + setValueByPath(toObject, ['instances[0]', 'video'], videoToMldev(fromVideo)); + } + const fromSource = getValueByPath(fromObject, ['source']); + if (fromSource != null) { + generateVideosSourceToMldev(fromSource, toObject); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + generateVideosConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function generateVideosParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (fromPrompt != null) { + setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromImage = getValueByPath(fromObject, ['image']); + if (fromImage != null) { + setValueByPath(toObject, ['instances[0]', 'image'], imageToVertex(fromImage)); + } + const fromVideo = getValueByPath(fromObject, ['video']); + if (fromVideo != null) { + setValueByPath(toObject, ['instances[0]', 'video'], videoToVertex(fromVideo)); + } + const fromSource = getValueByPath(fromObject, ['source']); + if (fromSource != null) { + generateVideosSourceToVertex(fromSource, toObject); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + generateVideosConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function generateVideosResponseFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromGeneratedVideos = getValueByPath(fromObject, [ + 'generatedSamples', + ]); + if (fromGeneratedVideos != null) { + let transformedList = fromGeneratedVideos; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedVideoFromMldev(item); + }); + } + setValueByPath(toObject, ['generatedVideos'], transformedList); + } + const fromRaiMediaFilteredCount = getValueByPath(fromObject, [ + 'raiMediaFilteredCount', + ]); + if (fromRaiMediaFilteredCount != null) { + setValueByPath(toObject, ['raiMediaFilteredCount'], fromRaiMediaFilteredCount); + } + const fromRaiMediaFilteredReasons = getValueByPath(fromObject, [ + 'raiMediaFilteredReasons', + ]); + if (fromRaiMediaFilteredReasons != null) { + setValueByPath(toObject, ['raiMediaFilteredReasons'], fromRaiMediaFilteredReasons); + } + return toObject; +} +function generateVideosResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromGeneratedVideos = getValueByPath(fromObject, ['videos']); + if (fromGeneratedVideos != null) { + let transformedList = fromGeneratedVideos; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedVideoFromVertex(item); + }); + } + setValueByPath(toObject, ['generatedVideos'], transformedList); + } + const fromRaiMediaFilteredCount = getValueByPath(fromObject, [ + 'raiMediaFilteredCount', + ]); + if (fromRaiMediaFilteredCount != null) { + setValueByPath(toObject, ['raiMediaFilteredCount'], fromRaiMediaFilteredCount); + } + const fromRaiMediaFilteredReasons = getValueByPath(fromObject, [ + 'raiMediaFilteredReasons', + ]); + if (fromRaiMediaFilteredReasons != null) { + setValueByPath(toObject, ['raiMediaFilteredReasons'], fromRaiMediaFilteredReasons); + } + return toObject; +} +function generateVideosSourceToMldev(fromObject, parentObject, rootObject) { + const toObject = {}; + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (parentObject !== undefined && fromPrompt != null) { + setValueByPath(parentObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromImage = getValueByPath(fromObject, ['image']); + if (parentObject !== undefined && fromImage != null) { + setValueByPath(parentObject, ['instances[0]', 'image'], imageToMldev(fromImage)); + } + const fromVideo = getValueByPath(fromObject, ['video']); + if (parentObject !== undefined && fromVideo != null) { + setValueByPath(parentObject, ['instances[0]', 'video'], videoToMldev(fromVideo)); + } + return toObject; +} +function generateVideosSourceToVertex(fromObject, parentObject, rootObject) { + const toObject = {}; + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (parentObject !== undefined && fromPrompt != null) { + setValueByPath(parentObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromImage = getValueByPath(fromObject, ['image']); + if (parentObject !== undefined && fromImage != null) { + setValueByPath(parentObject, ['instances[0]', 'image'], imageToVertex(fromImage)); + } + const fromVideo = getValueByPath(fromObject, ['video']); + if (parentObject !== undefined && fromVideo != null) { + setValueByPath(parentObject, ['instances[0]', 'video'], videoToVertex(fromVideo)); + } + return toObject; +} +function generatedImageFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromImage = getValueByPath(fromObject, ['_self']); + if (fromImage != null) { + setValueByPath(toObject, ['image'], imageFromMldev(fromImage)); + } + const fromRaiFilteredReason = getValueByPath(fromObject, [ + 'raiFilteredReason', + ]); + if (fromRaiFilteredReason != null) { + setValueByPath(toObject, ['raiFilteredReason'], fromRaiFilteredReason); + } + const fromSafetyAttributes = getValueByPath(fromObject, ['_self']); + if (fromSafetyAttributes != null) { + setValueByPath(toObject, ['safetyAttributes'], safetyAttributesFromMldev(fromSafetyAttributes)); + } + return toObject; +} +function generatedImageFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromImage = getValueByPath(fromObject, ['_self']); + if (fromImage != null) { + setValueByPath(toObject, ['image'], imageFromVertex(fromImage)); + } + const fromRaiFilteredReason = getValueByPath(fromObject, [ + 'raiFilteredReason', + ]); + if (fromRaiFilteredReason != null) { + setValueByPath(toObject, ['raiFilteredReason'], fromRaiFilteredReason); + } + const fromSafetyAttributes = getValueByPath(fromObject, ['_self']); + if (fromSafetyAttributes != null) { + setValueByPath(toObject, ['safetyAttributes'], safetyAttributesFromVertex(fromSafetyAttributes)); + } + const fromEnhancedPrompt = getValueByPath(fromObject, ['prompt']); + if (fromEnhancedPrompt != null) { + setValueByPath(toObject, ['enhancedPrompt'], fromEnhancedPrompt); + } + return toObject; +} +function generatedImageMaskFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromMask = getValueByPath(fromObject, ['_self']); + if (fromMask != null) { + setValueByPath(toObject, ['mask'], imageFromVertex(fromMask)); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (fromLabels != null) { + let transformedList = fromLabels; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['labels'], transformedList); + } + return toObject; +} +function generatedVideoFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromVideo = getValueByPath(fromObject, ['video']); + if (fromVideo != null) { + setValueByPath(toObject, ['video'], videoFromMldev(fromVideo)); + } + return toObject; +} +function generatedVideoFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromVideo = getValueByPath(fromObject, ['_self']); + if (fromVideo != null) { + setValueByPath(toObject, ['video'], videoFromVertex(fromVideo)); + } + return toObject; +} +function generationConfigToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromModelSelectionConfig = getValueByPath(fromObject, [ + 'modelSelectionConfig', + ]); + if (fromModelSelectionConfig != null) { + setValueByPath(toObject, ['modelConfig'], fromModelSelectionConfig); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + const fromAudioTimestamp = getValueByPath(fromObject, [ + 'audioTimestamp', + ]); + if (fromAudioTimestamp != null) { + setValueByPath(toObject, ['audioTimestamp'], fromAudioTimestamp); + } + const fromCandidateCount = getValueByPath(fromObject, [ + 'candidateCount', + ]); + if (fromCandidateCount != null) { + setValueByPath(toObject, ['candidateCount'], fromCandidateCount); + } + const fromEnableAffectiveDialog = getValueByPath(fromObject, [ + 'enableAffectiveDialog', + ]); + if (fromEnableAffectiveDialog != null) { + setValueByPath(toObject, ['enableAffectiveDialog'], fromEnableAffectiveDialog); + } + const fromFrequencyPenalty = getValueByPath(fromObject, [ + 'frequencyPenalty', + ]); + if (fromFrequencyPenalty != null) { + setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty); + } + const fromLogprobs = getValueByPath(fromObject, ['logprobs']); + if (fromLogprobs != null) { + setValueByPath(toObject, ['logprobs'], fromLogprobs); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (fromMaxOutputTokens != null) { + setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromPresencePenalty = getValueByPath(fromObject, [ + 'presencePenalty', + ]); + if (fromPresencePenalty != null) { + setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty); + } + const fromResponseLogprobs = getValueByPath(fromObject, [ + 'responseLogprobs', + ]); + if (fromResponseLogprobs != null) { + setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs); + } + const fromResponseMimeType = getValueByPath(fromObject, [ + 'responseMimeType', + ]); + if (fromResponseMimeType != null) { + setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (fromResponseModalities != null) { + setValueByPath(toObject, ['responseModalities'], fromResponseModalities); + } + const fromResponseSchema = getValueByPath(fromObject, [ + 'responseSchema', + ]); + if (fromResponseSchema != null) { + setValueByPath(toObject, ['responseSchema'], fromResponseSchema); + } + const fromRoutingConfig = getValueByPath(fromObject, [ + 'routingConfig', + ]); + if (fromRoutingConfig != null) { + setValueByPath(toObject, ['routingConfig'], fromRoutingConfig); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (fromSeed != null) { + setValueByPath(toObject, ['seed'], fromSeed); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (fromSpeechConfig != null) { + setValueByPath(toObject, ['speechConfig'], fromSpeechConfig); + } + const fromStopSequences = getValueByPath(fromObject, [ + 'stopSequences', + ]); + if (fromStopSequences != null) { + setValueByPath(toObject, ['stopSequences'], fromStopSequences); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (fromTemperature != null) { + setValueByPath(toObject, ['temperature'], fromTemperature); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (fromThinkingConfig != null) { + setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (fromTopK != null) { + setValueByPath(toObject, ['topK'], fromTopK); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (fromTopP != null) { + setValueByPath(toObject, ['topP'], fromTopP); + } + if (getValueByPath(fromObject, ['enableEnhancedCivicAnswers']) !== + undefined) { + throw new Error('enableEnhancedCivicAnswers parameter is not supported in Vertex AI.'); + } + return toObject; +} +function getModelParametersToMldev(apiClient, fromObject, _rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'name'], tModel(apiClient, fromModel)); + } + return toObject; +} +function getModelParametersToVertex(apiClient, fromObject, _rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'name'], tModel(apiClient, fromModel)); + } + return toObject; +} +function googleMapsToMldev$1(fromObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['authConfig']) !== undefined) { + throw new Error('authConfig parameter is not supported in Gemini API.'); + } + const fromEnableWidget = getValueByPath(fromObject, ['enableWidget']); + if (fromEnableWidget != null) { + setValueByPath(toObject, ['enableWidget'], fromEnableWidget); + } + return toObject; +} +function googleSearchToMldev$1(fromObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['excludeDomains']) !== undefined) { + throw new Error('excludeDomains parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['blockingConfidence']) !== undefined) { + throw new Error('blockingConfidence parameter is not supported in Gemini API.'); + } + const fromTimeRangeFilter = getValueByPath(fromObject, [ + 'timeRangeFilter', + ]); + if (fromTimeRangeFilter != null) { + setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter); + } + return toObject; +} +function imageConfigToMldev(fromObject, _rootObject) { + const toObject = {}; + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (fromAspectRatio != null) { + setValueByPath(toObject, ['aspectRatio'], fromAspectRatio); + } + const fromImageSize = getValueByPath(fromObject, ['imageSize']); + if (fromImageSize != null) { + setValueByPath(toObject, ['imageSize'], fromImageSize); + } + if (getValueByPath(fromObject, ['personGeneration']) !== undefined) { + throw new Error('personGeneration parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['outputMimeType']) !== undefined) { + throw new Error('outputMimeType parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['outputCompressionQuality']) !== + undefined) { + throw new Error('outputCompressionQuality parameter is not supported in Gemini API.'); + } + return toObject; +} +function imageConfigToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (fromAspectRatio != null) { + setValueByPath(toObject, ['aspectRatio'], fromAspectRatio); + } + const fromImageSize = getValueByPath(fromObject, ['imageSize']); + if (fromImageSize != null) { + setValueByPath(toObject, ['imageSize'], fromImageSize); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (fromPersonGeneration != null) { + setValueByPath(toObject, ['personGeneration'], fromPersonGeneration); + } + const fromOutputMimeType = getValueByPath(fromObject, [ + 'outputMimeType', + ]); + if (fromOutputMimeType != null) { + setValueByPath(toObject, ['imageOutputOptions', 'mimeType'], fromOutputMimeType); + } + const fromOutputCompressionQuality = getValueByPath(fromObject, [ + 'outputCompressionQuality', + ]); + if (fromOutputCompressionQuality != null) { + setValueByPath(toObject, ['imageOutputOptions', 'compressionQuality'], fromOutputCompressionQuality); + } + return toObject; +} +function imageFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromImageBytes = getValueByPath(fromObject, [ + 'bytesBase64Encoded', + ]); + if (fromImageBytes != null) { + setValueByPath(toObject, ['imageBytes'], tBytes(fromImageBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function imageFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (fromGcsUri != null) { + setValueByPath(toObject, ['gcsUri'], fromGcsUri); + } + const fromImageBytes = getValueByPath(fromObject, [ + 'bytesBase64Encoded', + ]); + if (fromImageBytes != null) { + setValueByPath(toObject, ['imageBytes'], tBytes(fromImageBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function imageToMldev(fromObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['gcsUri']) !== undefined) { + throw new Error('gcsUri parameter is not supported in Gemini API.'); + } + const fromImageBytes = getValueByPath(fromObject, ['imageBytes']); + if (fromImageBytes != null) { + setValueByPath(toObject, ['bytesBase64Encoded'], tBytes(fromImageBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function imageToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (fromGcsUri != null) { + setValueByPath(toObject, ['gcsUri'], fromGcsUri); + } + const fromImageBytes = getValueByPath(fromObject, ['imageBytes']); + if (fromImageBytes != null) { + setValueByPath(toObject, ['bytesBase64Encoded'], tBytes(fromImageBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function listModelsConfigToMldev(apiClient, fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + const fromFilter = getValueByPath(fromObject, ['filter']); + if (parentObject !== undefined && fromFilter != null) { + setValueByPath(parentObject, ['_query', 'filter'], fromFilter); + } + const fromQueryBase = getValueByPath(fromObject, ['queryBase']); + if (parentObject !== undefined && fromQueryBase != null) { + setValueByPath(parentObject, ['_url', 'models_url'], tModelsUrl(apiClient, fromQueryBase)); + } + return toObject; +} +function listModelsConfigToVertex(apiClient, fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + const fromFilter = getValueByPath(fromObject, ['filter']); + if (parentObject !== undefined && fromFilter != null) { + setValueByPath(parentObject, ['_query', 'filter'], fromFilter); + } + const fromQueryBase = getValueByPath(fromObject, ['queryBase']); + if (parentObject !== undefined && fromQueryBase != null) { + setValueByPath(parentObject, ['_url', 'models_url'], tModelsUrl(apiClient, fromQueryBase)); + } + return toObject; +} +function listModelsParametersToMldev(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listModelsConfigToMldev(apiClient, fromConfig, toObject); + } + return toObject; +} +function listModelsParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listModelsConfigToVertex(apiClient, fromConfig, toObject); + } + return toObject; +} +function listModelsResponseFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromModels = getValueByPath(fromObject, ['_self']); + if (fromModels != null) { + let transformedList = tExtractModels(fromModels); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return modelFromMldev(item); + }); + } + setValueByPath(toObject, ['models'], transformedList); + } + return toObject; +} +function listModelsResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromModels = getValueByPath(fromObject, ['_self']); + if (fromModels != null) { + let transformedList = tExtractModels(fromModels); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return modelFromVertex(item); + }); + } + setValueByPath(toObject, ['models'], transformedList); + } + return toObject; +} +function maskReferenceConfigToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromMaskMode = getValueByPath(fromObject, ['maskMode']); + if (fromMaskMode != null) { + setValueByPath(toObject, ['maskMode'], fromMaskMode); + } + const fromSegmentationClasses = getValueByPath(fromObject, [ + 'segmentationClasses', + ]); + if (fromSegmentationClasses != null) { + setValueByPath(toObject, ['maskClasses'], fromSegmentationClasses); + } + const fromMaskDilation = getValueByPath(fromObject, ['maskDilation']); + if (fromMaskDilation != null) { + setValueByPath(toObject, ['dilation'], fromMaskDilation); + } + return toObject; +} +function modelFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (fromDisplayName != null) { + setValueByPath(toObject, ['displayName'], fromDisplayName); + } + const fromDescription = getValueByPath(fromObject, ['description']); + if (fromDescription != null) { + setValueByPath(toObject, ['description'], fromDescription); + } + const fromVersion = getValueByPath(fromObject, ['version']); + if (fromVersion != null) { + setValueByPath(toObject, ['version'], fromVersion); + } + const fromTunedModelInfo = getValueByPath(fromObject, ['_self']); + if (fromTunedModelInfo != null) { + setValueByPath(toObject, ['tunedModelInfo'], tunedModelInfoFromMldev(fromTunedModelInfo)); + } + const fromInputTokenLimit = getValueByPath(fromObject, [ + 'inputTokenLimit', + ]); + if (fromInputTokenLimit != null) { + setValueByPath(toObject, ['inputTokenLimit'], fromInputTokenLimit); + } + const fromOutputTokenLimit = getValueByPath(fromObject, [ + 'outputTokenLimit', + ]); + if (fromOutputTokenLimit != null) { + setValueByPath(toObject, ['outputTokenLimit'], fromOutputTokenLimit); + } + const fromSupportedActions = getValueByPath(fromObject, [ + 'supportedGenerationMethods', + ]); + if (fromSupportedActions != null) { + setValueByPath(toObject, ['supportedActions'], fromSupportedActions); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (fromTemperature != null) { + setValueByPath(toObject, ['temperature'], fromTemperature); + } + const fromMaxTemperature = getValueByPath(fromObject, [ + 'maxTemperature', + ]); + if (fromMaxTemperature != null) { + setValueByPath(toObject, ['maxTemperature'], fromMaxTemperature); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (fromTopP != null) { + setValueByPath(toObject, ['topP'], fromTopP); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (fromTopK != null) { + setValueByPath(toObject, ['topK'], fromTopK); + } + const fromThinking = getValueByPath(fromObject, ['thinking']); + if (fromThinking != null) { + setValueByPath(toObject, ['thinking'], fromThinking); + } + return toObject; +} +function modelFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (fromDisplayName != null) { + setValueByPath(toObject, ['displayName'], fromDisplayName); + } + const fromDescription = getValueByPath(fromObject, ['description']); + if (fromDescription != null) { + setValueByPath(toObject, ['description'], fromDescription); + } + const fromVersion = getValueByPath(fromObject, ['versionId']); + if (fromVersion != null) { + setValueByPath(toObject, ['version'], fromVersion); + } + const fromEndpoints = getValueByPath(fromObject, ['deployedModels']); + if (fromEndpoints != null) { + let transformedList = fromEndpoints; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return endpointFromVertex(item); + }); + } + setValueByPath(toObject, ['endpoints'], transformedList); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (fromLabels != null) { + setValueByPath(toObject, ['labels'], fromLabels); + } + const fromTunedModelInfo = getValueByPath(fromObject, ['_self']); + if (fromTunedModelInfo != null) { + setValueByPath(toObject, ['tunedModelInfo'], tunedModelInfoFromVertex(fromTunedModelInfo)); + } + const fromDefaultCheckpointId = getValueByPath(fromObject, [ + 'defaultCheckpointId', + ]); + if (fromDefaultCheckpointId != null) { + setValueByPath(toObject, ['defaultCheckpointId'], fromDefaultCheckpointId); + } + const fromCheckpoints = getValueByPath(fromObject, ['checkpoints']); + if (fromCheckpoints != null) { + let transformedList = fromCheckpoints; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['checkpoints'], transformedList); + } + return toObject; +} +function partToMldev$1(fromObject, rootObject) { + const toObject = {}; + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromCodeExecutionResult = getValueByPath(fromObject, [ + 'codeExecutionResult', + ]); + if (fromCodeExecutionResult != null) { + setValueByPath(toObject, ['codeExecutionResult'], fromCodeExecutionResult); + } + const fromExecutableCode = getValueByPath(fromObject, [ + 'executableCode', + ]); + if (fromExecutableCode != null) { + setValueByPath(toObject, ['executableCode'], fromExecutableCode); + } + const fromFileData = getValueByPath(fromObject, ['fileData']); + if (fromFileData != null) { + setValueByPath(toObject, ['fileData'], fileDataToMldev$1(fromFileData)); + } + const fromFunctionCall = getValueByPath(fromObject, ['functionCall']); + if (fromFunctionCall != null) { + setValueByPath(toObject, ['functionCall'], functionCallToMldev$1(fromFunctionCall)); + } + const fromFunctionResponse = getValueByPath(fromObject, [ + 'functionResponse', + ]); + if (fromFunctionResponse != null) { + setValueByPath(toObject, ['functionResponse'], fromFunctionResponse); + } + const fromInlineData = getValueByPath(fromObject, ['inlineData']); + if (fromInlineData != null) { + setValueByPath(toObject, ['inlineData'], blobToMldev$1(fromInlineData)); + } + const fromText = getValueByPath(fromObject, ['text']); + if (fromText != null) { + setValueByPath(toObject, ['text'], fromText); + } + const fromThought = getValueByPath(fromObject, ['thought']); + if (fromThought != null) { + setValueByPath(toObject, ['thought'], fromThought); + } + const fromThoughtSignature = getValueByPath(fromObject, [ + 'thoughtSignature', + ]); + if (fromThoughtSignature != null) { + setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature); + } + const fromVideoMetadata = getValueByPath(fromObject, [ + 'videoMetadata', + ]); + if (fromVideoMetadata != null) { + setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata); + } + return toObject; +} +function productImageToVertex(fromObject, rootObject) { + const toObject = {}; + const fromProductImage = getValueByPath(fromObject, ['productImage']); + if (fromProductImage != null) { + setValueByPath(toObject, ['image'], imageToVertex(fromProductImage)); + } + return toObject; +} +function recontextImageConfigToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromNumberOfImages = getValueByPath(fromObject, [ + 'numberOfImages', + ]); + if (parentObject !== undefined && fromNumberOfImages != null) { + setValueByPath(parentObject, ['parameters', 'sampleCount'], fromNumberOfImages); + } + const fromBaseSteps = getValueByPath(fromObject, ['baseSteps']); + if (parentObject !== undefined && fromBaseSteps != null) { + setValueByPath(parentObject, ['parameters', 'baseSteps'], fromBaseSteps); + } + const fromOutputGcsUri = getValueByPath(fromObject, ['outputGcsUri']); + if (parentObject !== undefined && fromOutputGcsUri != null) { + setValueByPath(parentObject, ['parameters', 'storageUri'], fromOutputGcsUri); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (parentObject !== undefined && fromSeed != null) { + setValueByPath(parentObject, ['parameters', 'seed'], fromSeed); + } + const fromSafetyFilterLevel = getValueByPath(fromObject, [ + 'safetyFilterLevel', + ]); + if (parentObject !== undefined && fromSafetyFilterLevel != null) { + setValueByPath(parentObject, ['parameters', 'safetySetting'], fromSafetyFilterLevel); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (parentObject !== undefined && fromPersonGeneration != null) { + setValueByPath(parentObject, ['parameters', 'personGeneration'], fromPersonGeneration); + } + const fromAddWatermark = getValueByPath(fromObject, ['addWatermark']); + if (parentObject !== undefined && fromAddWatermark != null) { + setValueByPath(parentObject, ['parameters', 'addWatermark'], fromAddWatermark); + } + const fromOutputMimeType = getValueByPath(fromObject, [ + 'outputMimeType', + ]); + if (parentObject !== undefined && fromOutputMimeType != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'mimeType'], fromOutputMimeType); + } + const fromOutputCompressionQuality = getValueByPath(fromObject, [ + 'outputCompressionQuality', + ]); + if (parentObject !== undefined && fromOutputCompressionQuality != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'compressionQuality'], fromOutputCompressionQuality); + } + const fromEnhancePrompt = getValueByPath(fromObject, [ + 'enhancePrompt', + ]); + if (parentObject !== undefined && fromEnhancePrompt != null) { + setValueByPath(parentObject, ['parameters', 'enhancePrompt'], fromEnhancePrompt); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (parentObject !== undefined && fromLabels != null) { + setValueByPath(parentObject, ['labels'], fromLabels); + } + return toObject; +} +function recontextImageParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromSource = getValueByPath(fromObject, ['source']); + if (fromSource != null) { + recontextImageSourceToVertex(fromSource, toObject); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + recontextImageConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function recontextImageResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromGeneratedImages = getValueByPath(fromObject, [ + 'predictions', + ]); + if (fromGeneratedImages != null) { + let transformedList = fromGeneratedImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedImageFromVertex(item); + }); + } + setValueByPath(toObject, ['generatedImages'], transformedList); + } + return toObject; +} +function recontextImageSourceToVertex(fromObject, parentObject, rootObject) { + const toObject = {}; + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (parentObject !== undefined && fromPrompt != null) { + setValueByPath(parentObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromPersonImage = getValueByPath(fromObject, ['personImage']); + if (parentObject !== undefined && fromPersonImage != null) { + setValueByPath(parentObject, ['instances[0]', 'personImage', 'image'], imageToVertex(fromPersonImage)); + } + const fromProductImages = getValueByPath(fromObject, [ + 'productImages', + ]); + if (parentObject !== undefined && fromProductImages != null) { + let transformedList = fromProductImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return productImageToVertex(item); + }); + } + setValueByPath(parentObject, ['instances[0]', 'productImages'], transformedList); + } + return toObject; +} +function referenceImageAPIInternalToVertex(fromObject, rootObject) { + const toObject = {}; + const fromReferenceImage = getValueByPath(fromObject, [ + 'referenceImage', + ]); + if (fromReferenceImage != null) { + setValueByPath(toObject, ['referenceImage'], imageToVertex(fromReferenceImage)); + } + const fromReferenceId = getValueByPath(fromObject, ['referenceId']); + if (fromReferenceId != null) { + setValueByPath(toObject, ['referenceId'], fromReferenceId); + } + const fromReferenceType = getValueByPath(fromObject, [ + 'referenceType', + ]); + if (fromReferenceType != null) { + setValueByPath(toObject, ['referenceType'], fromReferenceType); + } + const fromMaskImageConfig = getValueByPath(fromObject, [ + 'maskImageConfig', + ]); + if (fromMaskImageConfig != null) { + setValueByPath(toObject, ['maskImageConfig'], maskReferenceConfigToVertex(fromMaskImageConfig)); + } + const fromControlImageConfig = getValueByPath(fromObject, [ + 'controlImageConfig', + ]); + if (fromControlImageConfig != null) { + setValueByPath(toObject, ['controlImageConfig'], controlReferenceConfigToVertex(fromControlImageConfig)); + } + const fromStyleImageConfig = getValueByPath(fromObject, [ + 'styleImageConfig', + ]); + if (fromStyleImageConfig != null) { + setValueByPath(toObject, ['styleImageConfig'], fromStyleImageConfig); + } + const fromSubjectImageConfig = getValueByPath(fromObject, [ + 'subjectImageConfig', + ]); + if (fromSubjectImageConfig != null) { + setValueByPath(toObject, ['subjectImageConfig'], fromSubjectImageConfig); + } + return toObject; +} +function safetyAttributesFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromCategories = getValueByPath(fromObject, [ + 'safetyAttributes', + 'categories', + ]); + if (fromCategories != null) { + setValueByPath(toObject, ['categories'], fromCategories); + } + const fromScores = getValueByPath(fromObject, [ + 'safetyAttributes', + 'scores', + ]); + if (fromScores != null) { + setValueByPath(toObject, ['scores'], fromScores); + } + const fromContentType = getValueByPath(fromObject, ['contentType']); + if (fromContentType != null) { + setValueByPath(toObject, ['contentType'], fromContentType); + } + return toObject; +} +function safetyAttributesFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromCategories = getValueByPath(fromObject, [ + 'safetyAttributes', + 'categories', + ]); + if (fromCategories != null) { + setValueByPath(toObject, ['categories'], fromCategories); + } + const fromScores = getValueByPath(fromObject, [ + 'safetyAttributes', + 'scores', + ]); + if (fromScores != null) { + setValueByPath(toObject, ['scores'], fromScores); + } + const fromContentType = getValueByPath(fromObject, ['contentType']); + if (fromContentType != null) { + setValueByPath(toObject, ['contentType'], fromContentType); + } + return toObject; +} +function safetySettingToMldev(fromObject, _rootObject) { + const toObject = {}; + const fromCategory = getValueByPath(fromObject, ['category']); + if (fromCategory != null) { + setValueByPath(toObject, ['category'], fromCategory); + } + if (getValueByPath(fromObject, ['method']) !== undefined) { + throw new Error('method parameter is not supported in Gemini API.'); + } + const fromThreshold = getValueByPath(fromObject, ['threshold']); + if (fromThreshold != null) { + setValueByPath(toObject, ['threshold'], fromThreshold); + } + return toObject; +} +function scribbleImageToVertex(fromObject, rootObject) { + const toObject = {}; + const fromImage = getValueByPath(fromObject, ['image']); + if (fromImage != null) { + setValueByPath(toObject, ['image'], imageToVertex(fromImage)); + } + return toObject; +} +function segmentImageConfigToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromMode = getValueByPath(fromObject, ['mode']); + if (parentObject !== undefined && fromMode != null) { + setValueByPath(parentObject, ['parameters', 'mode'], fromMode); + } + const fromMaxPredictions = getValueByPath(fromObject, [ + 'maxPredictions', + ]); + if (parentObject !== undefined && fromMaxPredictions != null) { + setValueByPath(parentObject, ['parameters', 'maxPredictions'], fromMaxPredictions); + } + const fromConfidenceThreshold = getValueByPath(fromObject, [ + 'confidenceThreshold', + ]); + if (parentObject !== undefined && fromConfidenceThreshold != null) { + setValueByPath(parentObject, ['parameters', 'confidenceThreshold'], fromConfidenceThreshold); + } + const fromMaskDilation = getValueByPath(fromObject, ['maskDilation']); + if (parentObject !== undefined && fromMaskDilation != null) { + setValueByPath(parentObject, ['parameters', 'maskDilation'], fromMaskDilation); + } + const fromBinaryColorThreshold = getValueByPath(fromObject, [ + 'binaryColorThreshold', + ]); + if (parentObject !== undefined && fromBinaryColorThreshold != null) { + setValueByPath(parentObject, ['parameters', 'binaryColorThreshold'], fromBinaryColorThreshold); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (parentObject !== undefined && fromLabels != null) { + setValueByPath(parentObject, ['labels'], fromLabels); + } + return toObject; +} +function segmentImageParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromSource = getValueByPath(fromObject, ['source']); + if (fromSource != null) { + segmentImageSourceToVertex(fromSource, toObject); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + segmentImageConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function segmentImageResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromGeneratedMasks = getValueByPath(fromObject, ['predictions']); + if (fromGeneratedMasks != null) { + let transformedList = fromGeneratedMasks; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedImageMaskFromVertex(item); + }); + } + setValueByPath(toObject, ['generatedMasks'], transformedList); + } + return toObject; +} +function segmentImageSourceToVertex(fromObject, parentObject, rootObject) { + const toObject = {}; + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (parentObject !== undefined && fromPrompt != null) { + setValueByPath(parentObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromImage = getValueByPath(fromObject, ['image']); + if (parentObject !== undefined && fromImage != null) { + setValueByPath(parentObject, ['instances[0]', 'image'], imageToVertex(fromImage)); + } + const fromScribbleImage = getValueByPath(fromObject, [ + 'scribbleImage', + ]); + if (parentObject !== undefined && fromScribbleImage != null) { + setValueByPath(parentObject, ['instances[0]', 'scribble'], scribbleImageToVertex(fromScribbleImage)); + } + return toObject; +} +function toolConfigToMldev(fromObject, rootObject) { + const toObject = {}; + const fromRetrievalConfig = getValueByPath(fromObject, [ + 'retrievalConfig', + ]); + if (fromRetrievalConfig != null) { + setValueByPath(toObject, ['retrievalConfig'], fromRetrievalConfig); + } + const fromFunctionCallingConfig = getValueByPath(fromObject, [ + 'functionCallingConfig', + ]); + if (fromFunctionCallingConfig != null) { + setValueByPath(toObject, ['functionCallingConfig'], functionCallingConfigToMldev(fromFunctionCallingConfig)); + } + return toObject; +} +function toolToMldev$1(fromObject, rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['retrieval']) !== undefined) { + throw new Error('retrieval parameter is not supported in Gemini API.'); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + const fromFileSearch = getValueByPath(fromObject, ['fileSearch']); + if (fromFileSearch != null) { + setValueByPath(toObject, ['fileSearch'], fromFileSearch); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + if (getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined) { + throw new Error('enterpriseWebSearch parameter is not supported in Gemini API.'); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], googleMapsToMldev$1(fromGoogleMaps)); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], googleSearchToMldev$1(fromGoogleSearch)); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} +function toolToVertex(fromObject, rootObject) { + const toObject = {}; + const fromRetrieval = getValueByPath(fromObject, ['retrieval']); + if (fromRetrieval != null) { + setValueByPath(toObject, ['retrieval'], fromRetrieval); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + if (getValueByPath(fromObject, ['fileSearch']) !== undefined) { + throw new Error('fileSearch parameter is not supported in Vertex AI.'); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + const fromEnterpriseWebSearch = getValueByPath(fromObject, [ + 'enterpriseWebSearch', + ]); + if (fromEnterpriseWebSearch != null) { + setValueByPath(toObject, ['enterpriseWebSearch'], fromEnterpriseWebSearch); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return functionDeclarationToVertex(item); + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], fromGoogleMaps); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], fromGoogleSearch); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} +function tunedModelInfoFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromBaseModel = getValueByPath(fromObject, ['baseModel']); + if (fromBaseModel != null) { + setValueByPath(toObject, ['baseModel'], fromBaseModel); + } + const fromCreateTime = getValueByPath(fromObject, ['createTime']); + if (fromCreateTime != null) { + setValueByPath(toObject, ['createTime'], fromCreateTime); + } + const fromUpdateTime = getValueByPath(fromObject, ['updateTime']); + if (fromUpdateTime != null) { + setValueByPath(toObject, ['updateTime'], fromUpdateTime); + } + return toObject; +} +function tunedModelInfoFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromBaseModel = getValueByPath(fromObject, [ + 'labels', + 'google-vertex-llm-tuning-base-model-id', + ]); + if (fromBaseModel != null) { + setValueByPath(toObject, ['baseModel'], fromBaseModel); + } + const fromCreateTime = getValueByPath(fromObject, ['createTime']); + if (fromCreateTime != null) { + setValueByPath(toObject, ['createTime'], fromCreateTime); + } + const fromUpdateTime = getValueByPath(fromObject, ['updateTime']); + if (fromUpdateTime != null) { + setValueByPath(toObject, ['updateTime'], fromUpdateTime); + } + return toObject; +} +function updateModelConfigToMldev(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromDisplayName); + } + const fromDescription = getValueByPath(fromObject, ['description']); + if (parentObject !== undefined && fromDescription != null) { + setValueByPath(parentObject, ['description'], fromDescription); + } + const fromDefaultCheckpointId = getValueByPath(fromObject, [ + 'defaultCheckpointId', + ]); + if (parentObject !== undefined && fromDefaultCheckpointId != null) { + setValueByPath(parentObject, ['defaultCheckpointId'], fromDefaultCheckpointId); + } + return toObject; +} +function updateModelConfigToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromDisplayName); + } + const fromDescription = getValueByPath(fromObject, ['description']); + if (parentObject !== undefined && fromDescription != null) { + setValueByPath(parentObject, ['description'], fromDescription); + } + const fromDefaultCheckpointId = getValueByPath(fromObject, [ + 'defaultCheckpointId', + ]); + if (parentObject !== undefined && fromDefaultCheckpointId != null) { + setValueByPath(parentObject, ['defaultCheckpointId'], fromDefaultCheckpointId); + } + return toObject; +} +function updateModelParametersToMldev(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'name'], tModel(apiClient, fromModel)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + updateModelConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function updateModelParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + updateModelConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function upscaleImageAPIConfigInternalToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromOutputGcsUri = getValueByPath(fromObject, ['outputGcsUri']); + if (parentObject !== undefined && fromOutputGcsUri != null) { + setValueByPath(parentObject, ['parameters', 'storageUri'], fromOutputGcsUri); + } + const fromSafetyFilterLevel = getValueByPath(fromObject, [ + 'safetyFilterLevel', + ]); + if (parentObject !== undefined && fromSafetyFilterLevel != null) { + setValueByPath(parentObject, ['parameters', 'safetySetting'], fromSafetyFilterLevel); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (parentObject !== undefined && fromPersonGeneration != null) { + setValueByPath(parentObject, ['parameters', 'personGeneration'], fromPersonGeneration); + } + const fromIncludeRaiReason = getValueByPath(fromObject, [ + 'includeRaiReason', + ]); + if (parentObject !== undefined && fromIncludeRaiReason != null) { + setValueByPath(parentObject, ['parameters', 'includeRaiReason'], fromIncludeRaiReason); + } + const fromOutputMimeType = getValueByPath(fromObject, [ + 'outputMimeType', + ]); + if (parentObject !== undefined && fromOutputMimeType != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'mimeType'], fromOutputMimeType); + } + const fromOutputCompressionQuality = getValueByPath(fromObject, [ + 'outputCompressionQuality', + ]); + if (parentObject !== undefined && fromOutputCompressionQuality != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'compressionQuality'], fromOutputCompressionQuality); + } + const fromEnhanceInputImage = getValueByPath(fromObject, [ + 'enhanceInputImage', + ]); + if (parentObject !== undefined && fromEnhanceInputImage != null) { + setValueByPath(parentObject, ['parameters', 'upscaleConfig', 'enhanceInputImage'], fromEnhanceInputImage); + } + const fromImagePreservationFactor = getValueByPath(fromObject, [ + 'imagePreservationFactor', + ]); + if (parentObject !== undefined && fromImagePreservationFactor != null) { + setValueByPath(parentObject, ['parameters', 'upscaleConfig', 'imagePreservationFactor'], fromImagePreservationFactor); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (parentObject !== undefined && fromLabels != null) { + setValueByPath(parentObject, ['labels'], fromLabels); + } + const fromNumberOfImages = getValueByPath(fromObject, [ + 'numberOfImages', + ]); + if (parentObject !== undefined && fromNumberOfImages != null) { + setValueByPath(parentObject, ['parameters', 'sampleCount'], fromNumberOfImages); + } + const fromMode = getValueByPath(fromObject, ['mode']); + if (parentObject !== undefined && fromMode != null) { + setValueByPath(parentObject, ['parameters', 'mode'], fromMode); + } + return toObject; +} +function upscaleImageAPIParametersInternalToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromImage = getValueByPath(fromObject, ['image']); + if (fromImage != null) { + setValueByPath(toObject, ['instances[0]', 'image'], imageToVertex(fromImage)); + } + const fromUpscaleFactor = getValueByPath(fromObject, [ + 'upscaleFactor', + ]); + if (fromUpscaleFactor != null) { + setValueByPath(toObject, ['parameters', 'upscaleConfig', 'upscaleFactor'], fromUpscaleFactor); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + upscaleImageAPIConfigInternalToVertex(fromConfig, toObject); + } + return toObject; +} +function upscaleImageResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromGeneratedImages = getValueByPath(fromObject, [ + 'predictions', + ]); + if (fromGeneratedImages != null) { + let transformedList = fromGeneratedImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedImageFromVertex(item); + }); + } + setValueByPath(toObject, ['generatedImages'], transformedList); + } + return toObject; +} +function videoFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromUri = getValueByPath(fromObject, ['uri']); + if (fromUri != null) { + setValueByPath(toObject, ['uri'], fromUri); + } + const fromVideoBytes = getValueByPath(fromObject, ['encodedVideo']); + if (fromVideoBytes != null) { + setValueByPath(toObject, ['videoBytes'], tBytes(fromVideoBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['encoding']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function videoFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromUri = getValueByPath(fromObject, ['gcsUri']); + if (fromUri != null) { + setValueByPath(toObject, ['uri'], fromUri); + } + const fromVideoBytes = getValueByPath(fromObject, [ + 'bytesBase64Encoded', + ]); + if (fromVideoBytes != null) { + setValueByPath(toObject, ['videoBytes'], tBytes(fromVideoBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function videoGenerationMaskToVertex(fromObject, rootObject) { + const toObject = {}; + const fromImage = getValueByPath(fromObject, ['image']); + if (fromImage != null) { + setValueByPath(toObject, ['_self'], imageToVertex(fromImage)); + } + const fromMaskMode = getValueByPath(fromObject, ['maskMode']); + if (fromMaskMode != null) { + setValueByPath(toObject, ['maskMode'], fromMaskMode); + } + return toObject; +} +function videoGenerationReferenceImageToMldev(fromObject, rootObject) { + const toObject = {}; + const fromImage = getValueByPath(fromObject, ['image']); + if (fromImage != null) { + setValueByPath(toObject, ['image'], imageToMldev(fromImage)); + } + const fromReferenceType = getValueByPath(fromObject, [ + 'referenceType', + ]); + if (fromReferenceType != null) { + setValueByPath(toObject, ['referenceType'], fromReferenceType); + } + return toObject; +} +function videoGenerationReferenceImageToVertex(fromObject, rootObject) { + const toObject = {}; + const fromImage = getValueByPath(fromObject, ['image']); + if (fromImage != null) { + setValueByPath(toObject, ['image'], imageToVertex(fromImage)); + } + const fromReferenceType = getValueByPath(fromObject, [ + 'referenceType', + ]); + if (fromReferenceType != null) { + setValueByPath(toObject, ['referenceType'], fromReferenceType); + } + return toObject; +} +function videoToMldev(fromObject, _rootObject) { + const toObject = {}; + const fromUri = getValueByPath(fromObject, ['uri']); + if (fromUri != null) { + setValueByPath(toObject, ['uri'], fromUri); + } + const fromVideoBytes = getValueByPath(fromObject, ['videoBytes']); + if (fromVideoBytes != null) { + setValueByPath(toObject, ['encodedVideo'], tBytes(fromVideoBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['encoding'], fromMimeType); + } + return toObject; +} +function videoToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromUri = getValueByPath(fromObject, ['uri']); + if (fromUri != null) { + setValueByPath(toObject, ['gcsUri'], fromUri); + } + const fromVideoBytes = getValueByPath(fromObject, ['videoBytes']); + if (fromVideoBytes != null) { + setValueByPath(toObject, ['bytesBase64Encoded'], tBytes(fromVideoBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// TODO: b/416041229 - Determine how to retrieve the MCP package version. +const MCP_LABEL = 'mcp_used/unknown'; +// Whether MCP tool usage is detected from mcpToTool. This is used for +// telemetry. +let hasMcpToolUsageFromMcpToTool = false; +// Checks whether the list of tools contains any MCP tools. +function hasMcpToolUsage(tools) { + for (const tool of tools) { + if (isMcpCallableTool(tool)) { + return true; + } + if (typeof tool === 'object' && 'inputSchema' in tool) { + return true; + } + } + return hasMcpToolUsageFromMcpToTool; +} +// Sets the MCP version label in the Google API client header. +function setMcpUsageHeader(headers) { + var _a; + const existingHeader = (_a = headers[GOOGLE_API_CLIENT_HEADER]) !== null && _a !== void 0 ? _a : ''; + headers[GOOGLE_API_CLIENT_HEADER] = (existingHeader + ` ${MCP_LABEL}`).trimStart(); +} +// Returns true if the object is a MCP CallableTool, otherwise false. +function isMcpCallableTool(object) { + return (object !== null && + typeof object === 'object' && + object instanceof McpCallableTool); +} +// List all tools from the MCP client. +function listAllTools(mcpClient_1) { + return __asyncGenerator(this, arguments, function* listAllTools_1(mcpClient, maxTools = 100) { + let cursor = undefined; + let numTools = 0; + while (numTools < maxTools) { + const t = yield __await(mcpClient.listTools({ cursor })); + for (const tool of t.tools) { + yield yield __await(tool); + numTools++; + } + if (!t.nextCursor) { + break; + } + cursor = t.nextCursor; + } + }); +} +/** + * McpCallableTool can be used for model inference and invoking MCP clients with + * given function call arguments. + * + * @experimental Built-in MCP support is an experimental feature, may change in future + * versions. + */ +class McpCallableTool { + constructor(mcpClients = [], config) { + this.mcpTools = []; + this.functionNameToMcpClient = {}; + this.mcpClients = mcpClients; + this.config = config; + } + /** + * Creates a McpCallableTool. + */ + static create(mcpClients, config) { + return new McpCallableTool(mcpClients, config); + } + /** + * Validates the function names are not duplicate and initialize the function + * name to MCP client mapping. + * + * @throws {Error} if the MCP tools from the MCP clients have duplicate tool + * names. + */ + async initialize() { + var _a, e_1, _b, _c; + if (this.mcpTools.length > 0) { + return; + } + const functionMap = {}; + const mcpTools = []; + for (const mcpClient of this.mcpClients) { + try { + for (var _d = true, _e = (e_1 = void 0, __asyncValues(listAllTools(mcpClient))), _f; _f = await _e.next(), _a = _f.done, !_a; _d = true) { + _c = _f.value; + _d = false; + const mcpTool = _c; + mcpTools.push(mcpTool); + const mcpToolName = mcpTool.name; + if (functionMap[mcpToolName]) { + throw new Error(`Duplicate function name ${mcpToolName} found in MCP tools. Please ensure function names are unique.`); + } + functionMap[mcpToolName] = mcpClient; + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (!_d && !_a && (_b = _e.return)) await _b.call(_e); + } + finally { if (e_1) throw e_1.error; } + } + } + this.mcpTools = mcpTools; + this.functionNameToMcpClient = functionMap; + } + async tool() { + await this.initialize(); + return mcpToolsToGeminiTool(this.mcpTools, this.config); + } + async callTool(functionCalls) { + await this.initialize(); + const functionCallResponseParts = []; + for (const functionCall of functionCalls) { + if (functionCall.name in this.functionNameToMcpClient) { + const mcpClient = this.functionNameToMcpClient[functionCall.name]; + let requestOptions = undefined; + // TODO: b/424238654 - Add support for finer grained timeout control. + if (this.config.timeout) { + requestOptions = { + timeout: this.config.timeout, + }; + } + const callToolResponse = await mcpClient.callTool({ + name: functionCall.name, + arguments: functionCall.args, + }, + // Set the result schema to undefined to allow MCP to rely on the + // default schema. + undefined, requestOptions); + functionCallResponseParts.push({ + functionResponse: { + name: functionCall.name, + response: callToolResponse.isError + ? { error: callToolResponse } + : callToolResponse, + }, + }); + } + } + return functionCallResponseParts; + } +} +function isMcpClient(client) { + return (client !== null && + typeof client === 'object' && + 'listTools' in client && + typeof client.listTools === 'function'); +} +/** + * Creates a McpCallableTool from MCP clients and an optional config. + * + * The callable tool can invoke the MCP clients with given function call + * arguments. (often for automatic function calling). + * Use the config to modify tool parameters such as behavior. + * + * @experimental Built-in MCP support is an experimental feature, may change in future + * versions. + */ +function mcpToTool(...args) { + // Set MCP usage for telemetry. + hasMcpToolUsageFromMcpToTool = true; + if (args.length === 0) { + throw new Error('No MCP clients provided'); + } + const maybeConfig = args[args.length - 1]; + if (isMcpClient(maybeConfig)) { + return McpCallableTool.create(args, {}); + } + return McpCallableTool.create(args.slice(0, args.length - 1), maybeConfig); +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Handles incoming messages from the WebSocket. + * + * @remarks + * This function is responsible for parsing incoming messages, transforming them + * into LiveMusicServerMessage, and then calling the onmessage callback. + * Note that the first message which is received from the server is a + * setupComplete message. + * + * @param apiClient The ApiClient instance. + * @param onmessage The user-provided onmessage callback (if any). + * @param event The MessageEvent from the WebSocket. + */ +async function handleWebSocketMessage$1(apiClient, onmessage, event) { + const serverMessage = new LiveMusicServerMessage(); + let data; + if (event.data instanceof Blob) { + data = JSON.parse(await event.data.text()); + } + else { + data = JSON.parse(event.data); + } + Object.assign(serverMessage, data); + onmessage(serverMessage); +} +/** + LiveMusic class encapsulates the configuration for live music + generation via Lyria Live models. + + @experimental + */ +class LiveMusic { + constructor(apiClient, auth, webSocketFactory) { + this.apiClient = apiClient; + this.auth = auth; + this.webSocketFactory = webSocketFactory; + } + /** + Establishes a connection to the specified model and returns a + LiveMusicSession object representing that connection. + + @experimental + + @remarks + + @param params - The parameters for establishing a connection to the model. + @return A live session. + + @example + ```ts + let model = 'models/lyria-realtime-exp'; + const session = await ai.live.music.connect({ + model: model, + callbacks: { + onmessage: (e: MessageEvent) => { + console.log('Received message from the server: %s\n', debug(e.data)); + }, + onerror: (e: ErrorEvent) => { + console.log('Error occurred: %s\n', debug(e.error)); + }, + onclose: (e: CloseEvent) => { + console.log('Connection closed.'); + }, + }, + }); + ``` + */ + async connect(params) { + var _a, _b; + if (this.apiClient.isVertexAI()) { + throw new Error('Live music is not supported for Vertex AI.'); + } + console.warn('Live music generation is experimental and may change in future versions.'); + const websocketBaseUrl = this.apiClient.getWebsocketBaseUrl(); + const apiVersion = this.apiClient.getApiVersion(); + const headers = mapToHeaders$1(this.apiClient.getDefaultHeaders()); + const apiKey = this.apiClient.getApiKey(); + const url = `${websocketBaseUrl}/ws/google.ai.generativelanguage.${apiVersion}.GenerativeService.BidiGenerateMusic?key=${apiKey}`; + let onopenResolve = () => { }; + const onopenPromise = new Promise((resolve) => { + onopenResolve = resolve; + }); + const callbacks = params.callbacks; + const onopenAwaitedCallback = function () { + onopenResolve({}); + }; + const apiClient = this.apiClient; + const websocketCallbacks = { + onopen: onopenAwaitedCallback, + onmessage: (event) => { + void handleWebSocketMessage$1(apiClient, callbacks.onmessage, event); + }, + onerror: (_a = callbacks === null || callbacks === void 0 ? void 0 : callbacks.onerror) !== null && _a !== void 0 ? _a : function (e) { + }, + onclose: (_b = callbacks === null || callbacks === void 0 ? void 0 : callbacks.onclose) !== null && _b !== void 0 ? _b : function (e) { + }, + }; + const conn = this.webSocketFactory.create(url, headersToMap$1(headers), websocketCallbacks); + conn.connect(); + // Wait for the websocket to open before sending requests. + await onopenPromise; + const model = tModel(this.apiClient, params.model); + const setup = { model }; + const clientMessage = { setup }; + conn.send(JSON.stringify(clientMessage)); + return new LiveMusicSession(conn, this.apiClient); + } +} +/** + Represents a connection to the API. + + @experimental + */ +class LiveMusicSession { + constructor(conn, apiClient) { + this.conn = conn; + this.apiClient = apiClient; + } + /** + Sets inputs to steer music generation. Updates the session's current + weighted prompts. + + @param params - Contains one property, `weightedPrompts`. + + - `weightedPrompts` to send to the model; weights are normalized to + sum to 1.0. + + @experimental + */ + async setWeightedPrompts(params) { + if (!params.weightedPrompts || + Object.keys(params.weightedPrompts).length === 0) { + throw new Error('Weighted prompts must be set and contain at least one entry.'); + } + const clientContent = liveMusicSetWeightedPromptsParametersToMldev(params); + this.conn.send(JSON.stringify({ clientContent })); + } + /** + Sets a configuration to the model. Updates the session's current + music generation config. + + @param params - Contains one property, `musicGenerationConfig`. + + - `musicGenerationConfig` to set in the model. Passing an empty or + undefined config to the model will reset the config to defaults. + + @experimental + */ + async setMusicGenerationConfig(params) { + if (!params.musicGenerationConfig) { + params.musicGenerationConfig = {}; + } + const setConfigParameters = liveMusicSetConfigParametersToMldev(params); + this.conn.send(JSON.stringify(setConfigParameters)); + } + sendPlaybackControl(playbackControl) { + const clientMessage = { playbackControl }; + this.conn.send(JSON.stringify(clientMessage)); + } + /** + * Start the music stream. + * + * @experimental + */ + play() { + this.sendPlaybackControl(LiveMusicPlaybackControl.PLAY); + } + /** + * Temporarily halt the music stream. Use `play` to resume from the current + * position. + * + * @experimental + */ + pause() { + this.sendPlaybackControl(LiveMusicPlaybackControl.PAUSE); + } + /** + * Stop the music stream and reset the state. Retains the current prompts + * and config. + * + * @experimental + */ + stop() { + this.sendPlaybackControl(LiveMusicPlaybackControl.STOP); + } + /** + * Resets the context of the music generation without stopping it. + * Retains the current prompts and config. + * + * @experimental + */ + resetContext() { + this.sendPlaybackControl(LiveMusicPlaybackControl.RESET_CONTEXT); + } + /** + Terminates the WebSocket connection. + + @experimental + */ + close() { + this.conn.close(); + } +} +// Converts an headers object to a "map" object as expected by the WebSocket +// constructor. We use this as the Auth interface works with Headers objects +// while the WebSocket constructor takes a map. +function headersToMap$1(headers) { + const headerMap = {}; + headers.forEach((value, key) => { + headerMap[key] = value; + }); + return headerMap; +} +// Converts a "map" object to a headers object. We use this as the Auth +// interface works with Headers objects while the API client default headers +// returns a map. +function mapToHeaders$1(map) { + const headers = new Headers(); + for (const [key, value] of Object.entries(map)) { + headers.append(key, value); + } + return headers; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const FUNCTION_RESPONSE_REQUIRES_ID = 'FunctionResponse request must have an `id` field from the response of a ToolCall.FunctionalCalls in Google AI.'; +/** + * Handles incoming messages from the WebSocket. + * + * @remarks + * This function is responsible for parsing incoming messages, transforming them + * into LiveServerMessages, and then calling the onmessage callback. Note that + * the first message which is received from the server is a setupComplete + * message. + * + * @param apiClient The ApiClient instance. + * @param onmessage The user-provided onmessage callback (if any). + * @param event The MessageEvent from the WebSocket. + */ +async function handleWebSocketMessage(apiClient, onmessage, event) { + const serverMessage = new LiveServerMessage(); + let jsonData; + if (event.data instanceof Blob) { + jsonData = await event.data.text(); + } + else if (event.data instanceof ArrayBuffer) { + jsonData = new TextDecoder().decode(event.data); + } + else { + jsonData = event.data; + } + const data = JSON.parse(jsonData); + if (apiClient.isVertexAI()) { + const resp = liveServerMessageFromVertex(data); + Object.assign(serverMessage, resp); + } + else { + const resp = data; + Object.assign(serverMessage, resp); + } + onmessage(serverMessage); +} +/** + Live class encapsulates the configuration for live interaction with the + Generative Language API. It embeds ApiClient for general API settings. + + @experimental + */ +class Live { + constructor(apiClient, auth, webSocketFactory) { + this.apiClient = apiClient; + this.auth = auth; + this.webSocketFactory = webSocketFactory; + this.music = new LiveMusic(this.apiClient, this.auth, this.webSocketFactory); + } + /** + Establishes a connection to the specified model with the given + configuration and returns a Session object representing that connection. + + @experimental Built-in MCP support is an experimental feature, may change in + future versions. + + @remarks + + @param params - The parameters for establishing a connection to the model. + @return A live session. + + @example + ```ts + let model: string; + if (GOOGLE_GENAI_USE_VERTEXAI) { + model = 'gemini-2.0-flash-live-preview-04-09'; + } else { + model = 'gemini-live-2.5-flash-preview'; + } + const session = await ai.live.connect({ + model: model, + config: { + responseModalities: [Modality.AUDIO], + }, + callbacks: { + onopen: () => { + console.log('Connected to the socket.'); + }, + onmessage: (e: MessageEvent) => { + console.log('Received message from the server: %s\n', debug(e.data)); + }, + onerror: (e: ErrorEvent) => { + console.log('Error occurred: %s\n', debug(e.error)); + }, + onclose: (e: CloseEvent) => { + console.log('Connection closed.'); + }, + }, + }); + ``` + */ + async connect(params) { + var _a, _b, _c, _d, _e, _f; + // TODO: b/404946746 - Support per request HTTP options. + if (params.config && params.config.httpOptions) { + throw new Error('The Live module does not support httpOptions at request-level in' + + ' LiveConnectConfig yet. Please use the client-level httpOptions' + + ' configuration instead.'); + } + const websocketBaseUrl = this.apiClient.getWebsocketBaseUrl(); + const apiVersion = this.apiClient.getApiVersion(); + let url; + const clientHeaders = this.apiClient.getHeaders(); + if (params.config && + params.config.tools && + hasMcpToolUsage(params.config.tools)) { + setMcpUsageHeader(clientHeaders); + } + const headers = mapToHeaders(clientHeaders); + if (this.apiClient.isVertexAI()) { + const project = this.apiClient.getProject(); + const location = this.apiClient.getLocation(); + const apiKey = this.apiClient.getApiKey(); + const hasStandardAuth = (!!project && !!location) || !!apiKey; + if (this.apiClient.getCustomBaseUrl() && !hasStandardAuth) { + // Custom base URL without standard auth (e.g., proxy). + url = websocketBaseUrl; + // Auth headers are assumed to be in `clientHeaders` from httpOptions. + } + else { + url = `${websocketBaseUrl}/ws/google.cloud.aiplatform.${apiVersion}.LlmBidiService/BidiGenerateContent`; + await this.auth.addAuthHeaders(headers, url); + } + } + else { + const apiKey = this.apiClient.getApiKey(); + let method = 'BidiGenerateContent'; + let keyName = 'key'; + if (apiKey === null || apiKey === void 0 ? void 0 : apiKey.startsWith('auth_tokens/')) { + console.warn('Warning: Ephemeral token support is experimental and may change in future versions.'); + if (apiVersion !== 'v1alpha') { + console.warn("Warning: The SDK's ephemeral token support is in v1alpha only. Please use const ai = new GoogleGenAI({apiKey: token.name, httpOptions: { apiVersion: 'v1alpha' }}); before session connection."); + } + method = 'BidiGenerateContentConstrained'; + keyName = 'access_token'; + } + url = `${websocketBaseUrl}/ws/google.ai.generativelanguage.${apiVersion}.GenerativeService.${method}?${keyName}=${apiKey}`; + } + let onopenResolve = () => { }; + const onopenPromise = new Promise((resolve) => { + onopenResolve = resolve; + }); + const callbacks = params.callbacks; + const onopenAwaitedCallback = function () { + var _a; + (_a = callbacks === null || callbacks === void 0 ? void 0 : callbacks.onopen) === null || _a === void 0 ? void 0 : _a.call(callbacks); + onopenResolve({}); + }; + const apiClient = this.apiClient; + const websocketCallbacks = { + onopen: onopenAwaitedCallback, + onmessage: (event) => { + void handleWebSocketMessage(apiClient, callbacks.onmessage, event); + }, + onerror: (_a = callbacks === null || callbacks === void 0 ? void 0 : callbacks.onerror) !== null && _a !== void 0 ? _a : function (e) { + }, + onclose: (_b = callbacks === null || callbacks === void 0 ? void 0 : callbacks.onclose) !== null && _b !== void 0 ? _b : function (e) { + }, + }; + const conn = this.webSocketFactory.create(url, headersToMap(headers), websocketCallbacks); + conn.connect(); + // Wait for the websocket to open before sending requests. + await onopenPromise; + let transformedModel = tModel(this.apiClient, params.model); + if (this.apiClient.isVertexAI() && + transformedModel.startsWith('publishers/')) { + const project = this.apiClient.getProject(); + const location = this.apiClient.getLocation(); + if (project && location) { + transformedModel = + `projects/${project}/locations/${location}/` + transformedModel; + } + } + let clientMessage = {}; + if (this.apiClient.isVertexAI() && + ((_c = params.config) === null || _c === void 0 ? void 0 : _c.responseModalities) === undefined) { + // Set default to AUDIO to align with MLDev API. + if (params.config === undefined) { + params.config = { responseModalities: [Modality.AUDIO] }; + } + else { + params.config.responseModalities = [Modality.AUDIO]; + } + } + if ((_d = params.config) === null || _d === void 0 ? void 0 : _d.generationConfig) { + // Raise deprecation warning for generationConfig. + console.warn('Setting `LiveConnectConfig.generation_config` is deprecated, please set the fields on `LiveConnectConfig` directly. This will become an error in a future version (not before Q3 2025).'); + } + const inputTools = (_f = (_e = params.config) === null || _e === void 0 ? void 0 : _e.tools) !== null && _f !== void 0 ? _f : []; + const convertedTools = []; + for (const tool of inputTools) { + if (this.isCallableTool(tool)) { + const callableTool = tool; + convertedTools.push(await callableTool.tool()); + } + else { + convertedTools.push(tool); + } + } + if (convertedTools.length > 0) { + params.config.tools = convertedTools; + } + const liveConnectParameters = { + model: transformedModel, + config: params.config, + callbacks: params.callbacks, + }; + if (this.apiClient.isVertexAI()) { + clientMessage = liveConnectParametersToVertex(this.apiClient, liveConnectParameters); + } + else { + clientMessage = liveConnectParametersToMldev(this.apiClient, liveConnectParameters); + } + delete clientMessage['config']; + conn.send(JSON.stringify(clientMessage)); + return new Session(conn, this.apiClient); + } + // TODO: b/416041229 - Abstract this method to a common place. + isCallableTool(tool) { + return 'callTool' in tool && typeof tool.callTool === 'function'; + } +} +const defaultLiveSendClientContentParamerters = { + turnComplete: true, +}; +/** + Represents a connection to the API. + + @experimental + */ +class Session { + constructor(conn, apiClient) { + this.conn = conn; + this.apiClient = apiClient; + } + tLiveClientContent(apiClient, params) { + if (params.turns !== null && params.turns !== undefined) { + let contents = []; + try { + contents = tContents(params.turns); + if (!apiClient.isVertexAI()) { + contents = contents.map((item) => contentToMldev$1(item)); + } + } + catch (_a) { + throw new Error(`Failed to parse client content "turns", type: '${typeof params.turns}'`); + } + return { + clientContent: { turns: contents, turnComplete: params.turnComplete }, + }; + } + return { + clientContent: { turnComplete: params.turnComplete }, + }; + } + tLiveClienttToolResponse(apiClient, params) { + let functionResponses = []; + if (params.functionResponses == null) { + throw new Error('functionResponses is required.'); + } + if (!Array.isArray(params.functionResponses)) { + functionResponses = [params.functionResponses]; + } + else { + functionResponses = params.functionResponses; + } + if (functionResponses.length === 0) { + throw new Error('functionResponses is required.'); + } + for (const functionResponse of functionResponses) { + if (typeof functionResponse !== 'object' || + functionResponse === null || + !('name' in functionResponse) || + !('response' in functionResponse)) { + throw new Error(`Could not parse function response, type '${typeof functionResponse}'.`); + } + if (!apiClient.isVertexAI() && !('id' in functionResponse)) { + throw new Error(FUNCTION_RESPONSE_REQUIRES_ID); + } + } + const clientMessage = { + toolResponse: { functionResponses: functionResponses }, + }; + return clientMessage; + } + /** + Send a message over the established connection. + + @param params - Contains two **optional** properties, `turns` and + `turnComplete`. + + - `turns` will be converted to a `Content[]` + - `turnComplete: true` [default] indicates that you are done sending + content and expect a response. If `turnComplete: false`, the server + will wait for additional messages before starting generation. + + @experimental + + @remarks + There are two ways to send messages to the live API: + `sendClientContent` and `sendRealtimeInput`. + + `sendClientContent` messages are added to the model context **in order**. + Having a conversation using `sendClientContent` messages is roughly + equivalent to using the `Chat.sendMessageStream`, except that the state of + the `chat` history is stored on the API server instead of locally. + + Because of `sendClientContent`'s order guarantee, the model cannot respons + as quickly to `sendClientContent` messages as to `sendRealtimeInput` + messages. This makes the biggest difference when sending objects that have + significant preprocessing time (typically images). + + The `sendClientContent` message sends a `Content[]` + which has more options than the `Blob` sent by `sendRealtimeInput`. + + So the main use-cases for `sendClientContent` over `sendRealtimeInput` are: + + - Sending anything that can't be represented as a `Blob` (text, + `sendClientContent({turns="Hello?"}`)). + - Managing turns when not using audio input and voice activity detection. + (`sendClientContent({turnComplete:true})` or the short form + `sendClientContent()`) + - Prefilling a conversation context + ``` + sendClientContent({ + turns: [ + Content({role:user, parts:...}), + Content({role:user, parts:...}), + ... + ] + }) + ``` + @experimental + */ + sendClientContent(params) { + params = Object.assign(Object.assign({}, defaultLiveSendClientContentParamerters), params); + const clientMessage = this.tLiveClientContent(this.apiClient, params); + this.conn.send(JSON.stringify(clientMessage)); + } + /** + Send a realtime message over the established connection. + + @param params - Contains one property, `media`. + + - `media` will be converted to a `Blob` + + @experimental + + @remarks + Use `sendRealtimeInput` for realtime audio chunks and video frames (images). + + With `sendRealtimeInput` the api will respond to audio automatically + based on voice activity detection (VAD). + + `sendRealtimeInput` is optimized for responsivness at the expense of + deterministic ordering guarantees. Audio and video tokens are to the + context when they become available. + + Note: The Call signature expects a `Blob` object, but only a subset + of audio and image mimetypes are allowed. + */ + sendRealtimeInput(params) { + let clientMessage = {}; + if (this.apiClient.isVertexAI()) { + clientMessage = { + 'realtimeInput': liveSendRealtimeInputParametersToVertex(params), + }; + } + else { + clientMessage = { + 'realtimeInput': liveSendRealtimeInputParametersToMldev(params), + }; + } + this.conn.send(JSON.stringify(clientMessage)); + } + /** + Send a function response message over the established connection. + + @param params - Contains property `functionResponses`. + + - `functionResponses` will be converted to a `functionResponses[]` + + @remarks + Use `sendFunctionResponse` to reply to `LiveServerToolCall` from the server. + + Use {@link types.LiveConnectConfig#tools} to configure the callable functions. + + @experimental + */ + sendToolResponse(params) { + if (params.functionResponses == null) { + throw new Error('Tool response parameters are required.'); + } + const clientMessage = this.tLiveClienttToolResponse(this.apiClient, params); + this.conn.send(JSON.stringify(clientMessage)); + } + /** + Terminates the WebSocket connection. + + @experimental + + @example + ```ts + let model: string; + if (GOOGLE_GENAI_USE_VERTEXAI) { + model = 'gemini-2.0-flash-live-preview-04-09'; + } else { + model = 'gemini-live-2.5-flash-preview'; + } + const session = await ai.live.connect({ + model: model, + config: { + responseModalities: [Modality.AUDIO], + } + }); + + session.close(); + ``` + */ + close() { + this.conn.close(); + } +} +// Converts an headers object to a "map" object as expected by the WebSocket +// constructor. We use this as the Auth interface works with Headers objects +// while the WebSocket constructor takes a map. +function headersToMap(headers) { + const headerMap = {}; + headers.forEach((value, key) => { + headerMap[key] = value; + }); + return headerMap; +} +// Converts a "map" object to a headers object. We use this as the Auth +// interface works with Headers objects while the API client default headers +// returns a map. +function mapToHeaders(map) { + const headers = new Headers(); + for (const [key, value] of Object.entries(map)) { + headers.append(key, value); + } + return headers; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const DEFAULT_MAX_REMOTE_CALLS = 10; +/** Returns whether automatic function calling is disabled. */ +function shouldDisableAfc(config) { + var _a, _b, _c; + if ((_a = config === null || config === void 0 ? void 0 : config.automaticFunctionCalling) === null || _a === void 0 ? void 0 : _a.disable) { + return true; + } + let callableToolsPresent = false; + for (const tool of (_b = config === null || config === void 0 ? void 0 : config.tools) !== null && _b !== void 0 ? _b : []) { + if (isCallableTool(tool)) { + callableToolsPresent = true; + break; + } + } + if (!callableToolsPresent) { + return true; + } + const maxCalls = (_c = config === null || config === void 0 ? void 0 : config.automaticFunctionCalling) === null || _c === void 0 ? void 0 : _c.maximumRemoteCalls; + if ((maxCalls && (maxCalls < 0 || !Number.isInteger(maxCalls))) || + maxCalls == 0) { + console.warn('Invalid maximumRemoteCalls value provided for automatic function calling. Disabled automatic function calling. Please provide a valid integer value greater than 0. maximumRemoteCalls provided:', maxCalls); + return true; + } + return false; +} +function isCallableTool(tool) { + return 'callTool' in tool && typeof tool.callTool === 'function'; +} +// Checks whether the list of tools contains any CallableTools. Will return true +// if there is at least one CallableTool. +function hasCallableTools(params) { + var _a, _b, _c; + return (_c = (_b = (_a = params.config) === null || _a === void 0 ? void 0 : _a.tools) === null || _b === void 0 ? void 0 : _b.some((tool) => isCallableTool(tool))) !== null && _c !== void 0 ? _c : false; +} +/** + * Returns the indexes of the tools that are not compatible with AFC. + */ +function findAfcIncompatibleToolIndexes(params) { + var _a; + // Use number[] for an array of numbers in TypeScript + const afcIncompatibleToolIndexes = []; + if (!((_a = params === null || params === void 0 ? void 0 : params.config) === null || _a === void 0 ? void 0 : _a.tools)) { + return afcIncompatibleToolIndexes; + } + params.config.tools.forEach((tool, index) => { + if (isCallableTool(tool)) { + return; + } + const geminiTool = tool; + if (geminiTool.functionDeclarations && + geminiTool.functionDeclarations.length > 0) { + afcIncompatibleToolIndexes.push(index); + } + }); + return afcIncompatibleToolIndexes; +} +/** + * Returns whether to append automatic function calling history to the + * response. + */ +function shouldAppendAfcHistory(config) { + var _a; + return !((_a = config === null || config === void 0 ? void 0 : config.automaticFunctionCalling) === null || _a === void 0 ? void 0 : _a.ignoreCallHistory); +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Models extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + /** + * Makes an API request to generate content with a given model. + * + * For the `model` parameter, supported formats for Vertex AI API include: + * - The Gemini model ID, for example: 'gemini-2.0-flash' + * - The full resource name starts with 'projects/', for example: + * 'projects/my-project-id/locations/us-central1/publishers/google/models/gemini-2.0-flash' + * - The partial resource name with 'publishers/', for example: + * 'publishers/google/models/gemini-2.0-flash' or + * 'publishers/meta/models/llama-3.1-405b-instruct-maas' + * - `/` separated publisher and model name, for example: + * 'google/gemini-2.0-flash' or 'meta/llama-3.1-405b-instruct-maas' + * + * For the `model` parameter, supported formats for Gemini API include: + * - The Gemini model ID, for example: 'gemini-2.0-flash' + * - The model name starts with 'models/', for example: + * 'models/gemini-2.0-flash' + * - For tuned models, the model name starts with 'tunedModels/', + * for example: + * 'tunedModels/1234567890123456789' + * + * Some models support multimodal input and output. + * + * @param params - The parameters for generating content. + * @return The response from generating content. + * + * @example + * ```ts + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: 'why is the sky blue?', + * config: { + * candidateCount: 2, + * } + * }); + * console.log(response); + * ``` + */ + this.generateContent = async (params) => { + var _a, _b, _c, _d, _e; + const transformedParams = await this.processParamsMaybeAddMcpUsage(params); + this.maybeMoveToResponseJsonSchem(params); + if (!hasCallableTools(params) || shouldDisableAfc(params.config)) { + return await this.generateContentInternal(transformedParams); + } + const incompatibleToolIndexes = findAfcIncompatibleToolIndexes(params); + if (incompatibleToolIndexes.length > 0) { + const formattedIndexes = incompatibleToolIndexes + .map((index) => `tools[${index}]`) + .join(', '); + throw new Error(`Automatic function calling with CallableTools (or MCP objects) and basic FunctionDeclarations is not yet supported. Incompatible tools found at ${formattedIndexes}.`); + } + let response; + let functionResponseContent; + const automaticFunctionCallingHistory = tContents(transformedParams.contents); + const maxRemoteCalls = (_c = (_b = (_a = transformedParams.config) === null || _a === void 0 ? void 0 : _a.automaticFunctionCalling) === null || _b === void 0 ? void 0 : _b.maximumRemoteCalls) !== null && _c !== void 0 ? _c : DEFAULT_MAX_REMOTE_CALLS; + let remoteCalls = 0; + while (remoteCalls < maxRemoteCalls) { + response = await this.generateContentInternal(transformedParams); + if (!response.functionCalls || response.functionCalls.length === 0) { + break; + } + const responseContent = response.candidates[0].content; + const functionResponseParts = []; + for (const tool of (_e = (_d = params.config) === null || _d === void 0 ? void 0 : _d.tools) !== null && _e !== void 0 ? _e : []) { + if (isCallableTool(tool)) { + const callableTool = tool; + const parts = await callableTool.callTool(response.functionCalls); + functionResponseParts.push(...parts); + } + } + remoteCalls++; + functionResponseContent = { + role: 'user', + parts: functionResponseParts, + }; + transformedParams.contents = tContents(transformedParams.contents); + transformedParams.contents.push(responseContent); + transformedParams.contents.push(functionResponseContent); + if (shouldAppendAfcHistory(transformedParams.config)) { + automaticFunctionCallingHistory.push(responseContent); + automaticFunctionCallingHistory.push(functionResponseContent); + } + } + if (shouldAppendAfcHistory(transformedParams.config)) { + response.automaticFunctionCallingHistory = + automaticFunctionCallingHistory; + } + return response; + }; + /** + * Makes an API request to generate content with a given model and yields the + * response in chunks. + * + * For the `model` parameter, supported formats for Vertex AI API include: + * - The Gemini model ID, for example: 'gemini-2.0-flash' + * - The full resource name starts with 'projects/', for example: + * 'projects/my-project-id/locations/us-central1/publishers/google/models/gemini-2.0-flash' + * - The partial resource name with 'publishers/', for example: + * 'publishers/google/models/gemini-2.0-flash' or + * 'publishers/meta/models/llama-3.1-405b-instruct-maas' + * - `/` separated publisher and model name, for example: + * 'google/gemini-2.0-flash' or 'meta/llama-3.1-405b-instruct-maas' + * + * For the `model` parameter, supported formats for Gemini API include: + * - The Gemini model ID, for example: 'gemini-2.0-flash' + * - The model name starts with 'models/', for example: + * 'models/gemini-2.0-flash' + * - For tuned models, the model name starts with 'tunedModels/', + * for example: + * 'tunedModels/1234567890123456789' + * + * Some models support multimodal input and output. + * + * @param params - The parameters for generating content with streaming response. + * @return The response from generating content. + * + * @example + * ```ts + * const response = await ai.models.generateContentStream({ + * model: 'gemini-2.0-flash', + * contents: 'why is the sky blue?', + * config: { + * maxOutputTokens: 200, + * } + * }); + * for await (const chunk of response) { + * console.log(chunk); + * } + * ``` + */ + this.generateContentStream = async (params) => { + var _a, _b, _c, _d, _e; + this.maybeMoveToResponseJsonSchem(params); + if (shouldDisableAfc(params.config)) { + const transformedParams = await this.processParamsMaybeAddMcpUsage(params); + return await this.generateContentStreamInternal(transformedParams); + } + const incompatibleToolIndexes = findAfcIncompatibleToolIndexes(params); + if (incompatibleToolIndexes.length > 0) { + const formattedIndexes = incompatibleToolIndexes + .map((index) => `tools[${index}]`) + .join(', '); + throw new Error(`Incompatible tools found at ${formattedIndexes}. Automatic function calling with CallableTools (or MCP objects) and basic FunctionDeclarations" is not yet supported.`); + } + // With tool compatibility confirmed, validate that the configuration are + // compatible with each other and raise an error if invalid. + const streamFunctionCall = (_c = (_b = (_a = params === null || params === void 0 ? void 0 : params.config) === null || _a === void 0 ? void 0 : _a.toolConfig) === null || _b === void 0 ? void 0 : _b.functionCallingConfig) === null || _c === void 0 ? void 0 : _c.streamFunctionCallArguments; + const disableAfc = (_e = (_d = params === null || params === void 0 ? void 0 : params.config) === null || _d === void 0 ? void 0 : _d.automaticFunctionCalling) === null || _e === void 0 ? void 0 : _e.disable; + if (streamFunctionCall && !disableAfc) { + throw new Error("Running in streaming mode with 'streamFunctionCallArguments' enabled, " + + 'this feature is not compatible with automatic function calling (AFC). ' + + "Please set 'config.automaticFunctionCalling.disable' to true to disable AFC " + + "or leave 'config.toolConfig.functionCallingConfig.streamFunctionCallArguments' " + + 'to be undefined or set to false to disable streaming function call arguments feature.'); + } + return await this.processAfcStream(params); + }; + /** + * Generates an image based on a text description and configuration. + * + * @param params - The parameters for generating images. + * @return The response from the API. + * + * @example + * ```ts + * const response = await client.models.generateImages({ + * model: 'imagen-4.0-generate-001', + * prompt: 'Robot holding a red skateboard', + * config: { + * numberOfImages: 1, + * includeRaiReason: true, + * }, + * }); + * console.log(response?.generatedImages?.[0]?.image?.imageBytes); + * ``` + */ + this.generateImages = async (params) => { + return await this.generateImagesInternal(params).then((apiResponse) => { + var _a; + let positivePromptSafetyAttributes; + const generatedImages = []; + if (apiResponse === null || apiResponse === void 0 ? void 0 : apiResponse.generatedImages) { + for (const generatedImage of apiResponse.generatedImages) { + if (generatedImage && + (generatedImage === null || generatedImage === void 0 ? void 0 : generatedImage.safetyAttributes) && + ((_a = generatedImage === null || generatedImage === void 0 ? void 0 : generatedImage.safetyAttributes) === null || _a === void 0 ? void 0 : _a.contentType) === 'Positive Prompt') { + positivePromptSafetyAttributes = generatedImage === null || generatedImage === void 0 ? void 0 : generatedImage.safetyAttributes; + } + else { + generatedImages.push(generatedImage); + } + } + } + let response; + if (positivePromptSafetyAttributes) { + response = { + generatedImages: generatedImages, + positivePromptSafetyAttributes: positivePromptSafetyAttributes, + sdkHttpResponse: apiResponse.sdkHttpResponse, + }; + } + else { + response = { + generatedImages: generatedImages, + sdkHttpResponse: apiResponse.sdkHttpResponse, + }; + } + return response; + }); + }; + this.list = async (params) => { + var _a; + const defaultConfig = { + queryBase: true, + }; + const actualConfig = Object.assign(Object.assign({}, defaultConfig), params === null || params === void 0 ? void 0 : params.config); + const actualParams = { + config: actualConfig, + }; + if (this.apiClient.isVertexAI()) { + if (!actualParams.config.queryBase) { + if ((_a = actualParams.config) === null || _a === void 0 ? void 0 : _a.filter) { + throw new Error('Filtering tuned models list for Vertex AI is not currently supported'); + } + else { + actualParams.config.filter = 'labels.tune-type:*'; + } + } + } + return new Pager(PagedItem.PAGED_ITEM_MODELS, (x) => this.listInternal(x), await this.listInternal(actualParams), actualParams); + }; + /** + * Edits an image based on a prompt, list of reference images, and configuration. + * + * @param params - The parameters for editing an image. + * @return The response from the API. + * + * @example + * ```ts + * const response = await client.models.editImage({ + * model: 'imagen-3.0-capability-001', + * prompt: 'Generate an image containing a mug with the product logo [1] visible on the side of the mug.', + * referenceImages: [subjectReferenceImage] + * config: { + * numberOfImages: 1, + * includeRaiReason: true, + * }, + * }); + * console.log(response?.generatedImages?.[0]?.image?.imageBytes); + * ``` + */ + this.editImage = async (params) => { + const paramsInternal = { + model: params.model, + prompt: params.prompt, + referenceImages: [], + config: params.config, + }; + if (params.referenceImages) { + if (params.referenceImages) { + paramsInternal.referenceImages = params.referenceImages.map((img) => img.toReferenceImageAPI()); + } + } + return await this.editImageInternal(paramsInternal); + }; + /** + * Upscales an image based on an image, upscale factor, and configuration. + * Only supported in Vertex AI currently. + * + * @param params - The parameters for upscaling an image. + * @return The response from the API. + * + * @example + * ```ts + * const response = await client.models.upscaleImage({ + * model: 'imagen-4.0-upscale-preview', + * image: image, + * upscaleFactor: 'x2', + * config: { + * includeRaiReason: true, + * }, + * }); + * console.log(response?.generatedImages?.[0]?.image?.imageBytes); + * ``` + */ + this.upscaleImage = async (params) => { + let apiConfig = { + numberOfImages: 1, + mode: 'upscale', + }; + if (params.config) { + apiConfig = Object.assign(Object.assign({}, apiConfig), params.config); + } + const apiParams = { + model: params.model, + image: params.image, + upscaleFactor: params.upscaleFactor, + config: apiConfig, + }; + return await this.upscaleImageInternal(apiParams); + }; + /** + * Generates videos based on a text description and configuration. + * + * @param params - The parameters for generating videos. + * @return A Promise<GenerateVideosOperation> which allows you to track the progress and eventually retrieve the generated videos using the operations.get method. + * + * @example + * ```ts + * const operation = await ai.models.generateVideos({ + * model: 'veo-2.0-generate-001', + * source: { + * prompt: 'A neon hologram of a cat driving at top speed', + * }, + * config: { + * numberOfVideos: 1 + * }); + * + * while (!operation.done) { + * await new Promise(resolve => setTimeout(resolve, 10000)); + * operation = await ai.operations.getVideosOperation({operation: operation}); + * } + * + * console.log(operation.response?.generatedVideos?.[0]?.video?.uri); + * ``` + */ + this.generateVideos = async (params) => { + var _a, _b, _c, _d, _e, _f; + if ((params.prompt || params.image || params.video) && params.source) { + throw new Error('Source and prompt/image/video are mutually exclusive. Please only use source.'); + } + // Gemini API does not support video bytes. + if (!this.apiClient.isVertexAI()) { + if (((_a = params.video) === null || _a === void 0 ? void 0 : _a.uri) && ((_b = params.video) === null || _b === void 0 ? void 0 : _b.videoBytes)) { + params.video = { + uri: params.video.uri, + mimeType: params.video.mimeType, + }; + } + else if (((_d = (_c = params.source) === null || _c === void 0 ? void 0 : _c.video) === null || _d === void 0 ? void 0 : _d.uri) && + ((_f = (_e = params.source) === null || _e === void 0 ? void 0 : _e.video) === null || _f === void 0 ? void 0 : _f.videoBytes)) { + params.source.video = { + uri: params.source.video.uri, + mimeType: params.source.video.mimeType, + }; + } + } + return await this.generateVideosInternal(params); + }; + } + /** + * This logic is needed for GenerateContentConfig only. + * Previously we made GenerateContentConfig.responseSchema field to accept + * unknown. Since v1.9.0, we switch to use backend JSON schema support. + * To maintain backward compatibility, we move the data that was treated as + * JSON schema from the responseSchema field to the responseJsonSchema field. + */ + maybeMoveToResponseJsonSchem(params) { + if (params.config && params.config.responseSchema) { + if (!params.config.responseJsonSchema) { + if (Object.keys(params.config.responseSchema).includes('$schema')) { + params.config.responseJsonSchema = params.config.responseSchema; + delete params.config.responseSchema; + } + } + } + return; + } + /** + * Transforms the CallableTools in the parameters to be simply Tools, it + * copies the params into a new object and replaces the tools, it does not + * modify the original params. Also sets the MCP usage header if there are + * MCP tools in the parameters. + */ + async processParamsMaybeAddMcpUsage(params) { + var _a, _b, _c; + const tools = (_a = params.config) === null || _a === void 0 ? void 0 : _a.tools; + if (!tools) { + return params; + } + const transformedTools = await Promise.all(tools.map(async (tool) => { + if (isCallableTool(tool)) { + const callableTool = tool; + return await callableTool.tool(); + } + return tool; + })); + const newParams = { + model: params.model, + contents: params.contents, + config: Object.assign(Object.assign({}, params.config), { tools: transformedTools }), + }; + newParams.config.tools = transformedTools; + if (params.config && + params.config.tools && + hasMcpToolUsage(params.config.tools)) { + const headers = (_c = (_b = params.config.httpOptions) === null || _b === void 0 ? void 0 : _b.headers) !== null && _c !== void 0 ? _c : {}; + let newHeaders = Object.assign({}, headers); + if (Object.keys(newHeaders).length === 0) { + newHeaders = this.apiClient.getDefaultHeaders(); + } + setMcpUsageHeader(newHeaders); + newParams.config.httpOptions = Object.assign(Object.assign({}, params.config.httpOptions), { headers: newHeaders }); + } + return newParams; + } + async initAfcToolsMap(params) { + var _a, _b, _c; + const afcTools = new Map(); + for (const tool of (_b = (_a = params.config) === null || _a === void 0 ? void 0 : _a.tools) !== null && _b !== void 0 ? _b : []) { + if (isCallableTool(tool)) { + const callableTool = tool; + const toolDeclaration = await callableTool.tool(); + for (const declaration of (_c = toolDeclaration.functionDeclarations) !== null && _c !== void 0 ? _c : []) { + if (!declaration.name) { + throw new Error('Function declaration name is required.'); + } + if (afcTools.has(declaration.name)) { + throw new Error(`Duplicate tool declaration name: ${declaration.name}`); + } + afcTools.set(declaration.name, callableTool); + } + } + } + return afcTools; + } + async processAfcStream(params) { + var _a, _b, _c; + const maxRemoteCalls = (_c = (_b = (_a = params.config) === null || _a === void 0 ? void 0 : _a.automaticFunctionCalling) === null || _b === void 0 ? void 0 : _b.maximumRemoteCalls) !== null && _c !== void 0 ? _c : DEFAULT_MAX_REMOTE_CALLS; + let wereFunctionsCalled = false; + let remoteCallCount = 0; + const afcToolsMap = await this.initAfcToolsMap(params); + return (function (models, afcTools, params) { + return __asyncGenerator(this, arguments, function* () { + var _a, e_1, _b, _c; + var _d, _e; + while (remoteCallCount < maxRemoteCalls) { + if (wereFunctionsCalled) { + remoteCallCount++; + wereFunctionsCalled = false; + } + const transformedParams = yield __await(models.processParamsMaybeAddMcpUsage(params)); + const response = yield __await(models.generateContentStreamInternal(transformedParams)); + const functionResponses = []; + const responseContents = []; + try { + for (var _f = true, response_1 = (e_1 = void 0, __asyncValues(response)), response_1_1; response_1_1 = yield __await(response_1.next()), _a = response_1_1.done, !_a; _f = true) { + _c = response_1_1.value; + _f = false; + const chunk = _c; + yield yield __await(chunk); + if (chunk.candidates && ((_d = chunk.candidates[0]) === null || _d === void 0 ? void 0 : _d.content)) { + responseContents.push(chunk.candidates[0].content); + for (const part of (_e = chunk.candidates[0].content.parts) !== null && _e !== void 0 ? _e : []) { + if (remoteCallCount < maxRemoteCalls && part.functionCall) { + if (!part.functionCall.name) { + throw new Error('Function call name was not returned by the model.'); + } + if (!afcTools.has(part.functionCall.name)) { + throw new Error(`Automatic function calling was requested, but not all the tools the model used implement the CallableTool interface. Available tools: ${afcTools.keys()}, mising tool: ${part.functionCall.name}`); + } + else { + const responseParts = yield __await(afcTools + .get(part.functionCall.name) + .callTool([part.functionCall])); + functionResponses.push(...responseParts); + } + } + } + } + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (!_f && !_a && (_b = response_1.return)) yield __await(_b.call(response_1)); + } + finally { if (e_1) throw e_1.error; } + } + if (functionResponses.length > 0) { + wereFunctionsCalled = true; + const typedResponseChunk = new GenerateContentResponse(); + typedResponseChunk.candidates = [ + { + content: { + role: 'user', + parts: functionResponses, + }, + }, + ]; + yield yield __await(typedResponseChunk); + const newContents = []; + newContents.push(...responseContents); + newContents.push({ + role: 'user', + parts: functionResponses, + }); + const updatedContents = tContents(params.contents).concat(newContents); + params.contents = updatedContents; + } + else { + break; + } + } + }); + })(this, afcToolsMap, params); + } + async generateContentInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = generateContentParametersToVertex(this.apiClient, params); + path = formatMap('{model}:generateContent', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = generateContentResponseFromVertex(apiResponse); + const typedResp = new GenerateContentResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = generateContentParametersToMldev(this.apiClient, params); + path = formatMap('{model}:generateContent', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = generateContentResponseFromMldev(apiResponse); + const typedResp = new GenerateContentResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + async generateContentStreamInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = generateContentParametersToVertex(this.apiClient, params); + path = formatMap('{model}:streamGenerateContent?alt=sse', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + const apiClient = this.apiClient; + response = apiClient.requestStream({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }); + return response.then(function (apiResponse) { + return __asyncGenerator(this, arguments, function* () { + var _a, e_2, _b, _c; + try { + for (var _d = true, apiResponse_1 = __asyncValues(apiResponse), apiResponse_1_1; apiResponse_1_1 = yield __await(apiResponse_1.next()), _a = apiResponse_1_1.done, !_a; _d = true) { + _c = apiResponse_1_1.value; + _d = false; + const chunk = _c; + const resp = generateContentResponseFromVertex((yield __await(chunk.json())), params); + resp['sdkHttpResponse'] = { + headers: chunk.headers, + }; + const typedResp = new GenerateContentResponse(); + Object.assign(typedResp, resp); + yield yield __await(typedResp); + } + } + catch (e_2_1) { e_2 = { error: e_2_1 }; } + finally { + try { + if (!_d && !_a && (_b = apiResponse_1.return)) yield __await(_b.call(apiResponse_1)); + } + finally { if (e_2) throw e_2.error; } + } + }); + }); + } + else { + const body = generateContentParametersToMldev(this.apiClient, params); + path = formatMap('{model}:streamGenerateContent?alt=sse', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + const apiClient = this.apiClient; + response = apiClient.requestStream({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }); + return response.then(function (apiResponse) { + return __asyncGenerator(this, arguments, function* () { + var _a, e_3, _b, _c; + try { + for (var _d = true, apiResponse_2 = __asyncValues(apiResponse), apiResponse_2_1; apiResponse_2_1 = yield __await(apiResponse_2.next()), _a = apiResponse_2_1.done, !_a; _d = true) { + _c = apiResponse_2_1.value; + _d = false; + const chunk = _c; + const resp = generateContentResponseFromMldev((yield __await(chunk.json())), params); + resp['sdkHttpResponse'] = { + headers: chunk.headers, + }; + const typedResp = new GenerateContentResponse(); + Object.assign(typedResp, resp); + yield yield __await(typedResp); + } + } + catch (e_3_1) { e_3 = { error: e_3_1 }; } + finally { + try { + if (!_d && !_a && (_b = apiResponse_2.return)) yield __await(_b.call(apiResponse_2)); + } + finally { if (e_3) throw e_3.error; } + } + }); + }); + } + } + /** + * Calculates embeddings for the given contents. Only text is supported. + * + * @param params - The parameters for embedding contents. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.embedContent({ + * model: 'text-embedding-004', + * contents: [ + * 'What is your name?', + * 'What is your favorite color?', + * ], + * config: { + * outputDimensionality: 64, + * }, + * }); + * console.log(response); + * ``` + */ + async embedContent(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = embedContentParametersToVertex(this.apiClient, params); + path = formatMap('{model}:predict', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = embedContentResponseFromVertex(apiResponse); + const typedResp = new EmbedContentResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = embedContentParametersToMldev(this.apiClient, params); + path = formatMap('{model}:batchEmbedContents', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = embedContentResponseFromMldev(apiResponse); + const typedResp = new EmbedContentResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Private method for generating images. + */ + async generateImagesInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = generateImagesParametersToVertex(this.apiClient, params); + path = formatMap('{model}:predict', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = generateImagesResponseFromVertex(apiResponse); + const typedResp = new GenerateImagesResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = generateImagesParametersToMldev(this.apiClient, params); + path = formatMap('{model}:predict', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = generateImagesResponseFromMldev(apiResponse); + const typedResp = new GenerateImagesResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Private method for editing an image. + */ + async editImageInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = editImageParametersInternalToVertex(this.apiClient, params); + path = formatMap('{model}:predict', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = editImageResponseFromVertex(apiResponse); + const typedResp = new EditImageResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + throw new Error('This method is only supported by the Vertex AI.'); + } + } + /** + * Private method for upscaling an image. + */ + async upscaleImageInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = upscaleImageAPIParametersInternalToVertex(this.apiClient, params); + path = formatMap('{model}:predict', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = upscaleImageResponseFromVertex(apiResponse); + const typedResp = new UpscaleImageResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + throw new Error('This method is only supported by the Vertex AI.'); + } + } + /** + * Recontextualizes an image. + * + * There are two types of recontextualization currently supported: + * 1) Imagen Product Recontext - Generate images of products in new scenes + * and contexts. + * 2) Virtual Try-On: Generate images of persons modeling fashion products. + * + * @param params - The parameters for recontextualizing an image. + * @return The response from the API. + * + * @example + * ```ts + * const response1 = await ai.models.recontextImage({ + * model: 'imagen-product-recontext-preview-06-30', + * source: { + * prompt: 'In a modern kitchen setting.', + * productImages: [productImage], + * }, + * config: { + * numberOfImages: 1, + * }, + * }); + * console.log(response1?.generatedImages?.[0]?.image?.imageBytes); + * + * const response2 = await ai.models.recontextImage({ + * model: 'virtual-try-on-001', + * source: { + * personImage: personImage, + * productImages: [productImage], + * }, + * config: { + * numberOfImages: 1, + * }, + * }); + * console.log(response2?.generatedImages?.[0]?.image?.imageBytes); + * ``` + */ + async recontextImage(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = recontextImageParametersToVertex(this.apiClient, params); + path = formatMap('{model}:predict', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = recontextImageResponseFromVertex(apiResponse); + const typedResp = new RecontextImageResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + throw new Error('This method is only supported by the Vertex AI.'); + } + } + /** + * Segments an image, creating a mask of a specified area. + * + * @param params - The parameters for segmenting an image. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.segmentImage({ + * model: 'image-segmentation-001', + * source: { + * image: image, + * }, + * config: { + * mode: 'foreground', + * }, + * }); + * console.log(response?.generatedMasks?.[0]?.mask?.imageBytes); + * ``` + */ + async segmentImage(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = segmentImageParametersToVertex(this.apiClient, params); + path = formatMap('{model}:predict', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = segmentImageResponseFromVertex(apiResponse); + const typedResp = new SegmentImageResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + throw new Error('This method is only supported by the Vertex AI.'); + } + } + /** + * Fetches information about a model by name. + * + * @example + * ```ts + * const modelInfo = await ai.models.get({model: 'gemini-2.0-flash'}); + * ``` + */ + async get(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = getModelParametersToVertex(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = modelFromVertex(apiResponse); + return resp; + }); + } + else { + const body = getModelParametersToMldev(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = modelFromMldev(apiResponse); + return resp; + }); + } + } + async listInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = listModelsParametersToVertex(this.apiClient, params); + path = formatMap('{models_url}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listModelsResponseFromVertex(apiResponse); + const typedResp = new ListModelsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = listModelsParametersToMldev(this.apiClient, params); + path = formatMap('{models_url}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listModelsResponseFromMldev(apiResponse); + const typedResp = new ListModelsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Updates a tuned model by its name. + * + * @param params - The parameters for updating the model. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.update({ + * model: 'tuned-model-name', + * config: { + * displayName: 'New display name', + * description: 'New description', + * }, + * }); + * ``` + */ + async update(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = updateModelParametersToVertex(this.apiClient, params); + path = formatMap('{model}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'PATCH', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = modelFromVertex(apiResponse); + return resp; + }); + } + else { + const body = updateModelParametersToMldev(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'PATCH', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = modelFromMldev(apiResponse); + return resp; + }); + } + } + /** + * Deletes a tuned model by its name. + * + * @param params - The parameters for deleting the model. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.delete({model: 'tuned-model-name'}); + * ``` + */ + async delete(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = deleteModelParametersToVertex(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = deleteModelResponseFromVertex(apiResponse); + const typedResp = new DeleteModelResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = deleteModelParametersToMldev(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = deleteModelResponseFromMldev(apiResponse); + const typedResp = new DeleteModelResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Counts the number of tokens in the given contents. Multimodal input is + * supported for Gemini models. + * + * @param params - The parameters for counting tokens. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.countTokens({ + * model: 'gemini-2.0-flash', + * contents: 'The quick brown fox jumps over the lazy dog.' + * }); + * console.log(response); + * ``` + */ + async countTokens(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = countTokensParametersToVertex(this.apiClient, params); + path = formatMap('{model}:countTokens', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = countTokensResponseFromVertex(apiResponse); + const typedResp = new CountTokensResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = countTokensParametersToMldev(this.apiClient, params); + path = formatMap('{model}:countTokens', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = countTokensResponseFromMldev(apiResponse); + const typedResp = new CountTokensResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Given a list of contents, returns a corresponding TokensInfo containing + * the list of tokens and list of token ids. + * + * This method is not supported by the Gemini Developer API. + * + * @param params - The parameters for computing tokens. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.computeTokens({ + * model: 'gemini-2.0-flash', + * contents: 'What is your name?' + * }); + * console.log(response); + * ``` + */ + async computeTokens(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = computeTokensParametersToVertex(this.apiClient, params); + path = formatMap('{model}:computeTokens', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = computeTokensResponseFromVertex(apiResponse); + const typedResp = new ComputeTokensResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + throw new Error('This method is only supported by the Vertex AI.'); + } + } + /** + * Private method for generating videos. + */ + async generateVideosInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = generateVideosParametersToVertex(this.apiClient, params); + path = formatMap('{model}:predictLongRunning', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = generateVideosOperationFromVertex(apiResponse); + const typedResp = new GenerateVideosOperation(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = generateVideosParametersToMldev(this.apiClient, params); + path = formatMap('{model}:predictLongRunning', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = generateVideosOperationFromMldev(apiResponse); + const typedResp = new GenerateVideosOperation(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Operations extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + } + /** + * Gets the status of a long-running operation. + * + * @param parameters The parameters for the get operation request. + * @return The updated Operation object, with the latest status or result. + */ + async getVideosOperation(parameters) { + const operation = parameters.operation; + const config = parameters.config; + if (operation.name === undefined || operation.name === '') { + throw new Error('Operation name is required.'); + } + if (this.apiClient.isVertexAI()) { + const resourceName = operation.name.split('/operations/')[0]; + let httpOptions = undefined; + if (config && 'httpOptions' in config) { + httpOptions = config.httpOptions; + } + const rawOperation = await this.fetchPredictVideosOperationInternal({ + operationName: operation.name, + resourceName: resourceName, + config: { httpOptions: httpOptions }, + }); + return operation._fromAPIResponse({ + apiResponse: rawOperation, + _isVertexAI: true, + }); + } + else { + const rawOperation = await this.getVideosOperationInternal({ + operationName: operation.name, + config: config, + }); + return operation._fromAPIResponse({ + apiResponse: rawOperation, + _isVertexAI: false, + }); + } + } + /** + * Gets the status of a long-running operation. + * + * @param parameters The parameters for the get operation request. + * @return The updated Operation object, with the latest status or result. + */ + async get(parameters) { + const operation = parameters.operation; + const config = parameters.config; + if (operation.name === undefined || operation.name === '') { + throw new Error('Operation name is required.'); + } + if (this.apiClient.isVertexAI()) { + const resourceName = operation.name.split('/operations/')[0]; + let httpOptions = undefined; + if (config && 'httpOptions' in config) { + httpOptions = config.httpOptions; + } + const rawOperation = await this.fetchPredictVideosOperationInternal({ + operationName: operation.name, + resourceName: resourceName, + config: { httpOptions: httpOptions }, + }); + return operation._fromAPIResponse({ + apiResponse: rawOperation, + _isVertexAI: true, + }); + } + else { + const rawOperation = await this.getVideosOperationInternal({ + operationName: operation.name, + config: config, + }); + return operation._fromAPIResponse({ + apiResponse: rawOperation, + _isVertexAI: false, + }); + } + } + async getVideosOperationInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = getOperationParametersToVertex(params); + path = formatMap('{operationName}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response; + } + else { + const body = getOperationParametersToMldev(params); + path = formatMap('{operationName}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response; + } + } + async fetchPredictVideosOperationInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = fetchPredictOperationParametersToVertex(params); + path = formatMap('{resourceName}:fetchPredictOperation', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response; + } + else { + throw new Error('This method is only supported by the Vertex AI.'); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function blobToMldev(fromObject) { + const toObject = {}; + const fromData = getValueByPath(fromObject, ['data']); + if (fromData != null) { + setValueByPath(toObject, ['data'], fromData); + } + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function contentToMldev(fromObject) { + const toObject = {}; + const fromParts = getValueByPath(fromObject, ['parts']); + if (fromParts != null) { + let transformedList = fromParts; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return partToMldev(item); + }); + } + setValueByPath(toObject, ['parts'], transformedList); + } + const fromRole = getValueByPath(fromObject, ['role']); + if (fromRole != null) { + setValueByPath(toObject, ['role'], fromRole); + } + return toObject; +} +function createAuthTokenConfigToMldev(apiClient, fromObject, parentObject) { + const toObject = {}; + const fromExpireTime = getValueByPath(fromObject, ['expireTime']); + if (parentObject !== undefined && fromExpireTime != null) { + setValueByPath(parentObject, ['expireTime'], fromExpireTime); + } + const fromNewSessionExpireTime = getValueByPath(fromObject, [ + 'newSessionExpireTime', + ]); + if (parentObject !== undefined && fromNewSessionExpireTime != null) { + setValueByPath(parentObject, ['newSessionExpireTime'], fromNewSessionExpireTime); + } + const fromUses = getValueByPath(fromObject, ['uses']); + if (parentObject !== undefined && fromUses != null) { + setValueByPath(parentObject, ['uses'], fromUses); + } + const fromLiveConnectConstraints = getValueByPath(fromObject, [ + 'liveConnectConstraints', + ]); + if (parentObject !== undefined && fromLiveConnectConstraints != null) { + setValueByPath(parentObject, ['bidiGenerateContentSetup'], liveConnectConstraintsToMldev(apiClient, fromLiveConnectConstraints)); + } + const fromLockAdditionalFields = getValueByPath(fromObject, [ + 'lockAdditionalFields', + ]); + if (parentObject !== undefined && fromLockAdditionalFields != null) { + setValueByPath(parentObject, ['fieldMask'], fromLockAdditionalFields); + } + return toObject; +} +function createAuthTokenParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['config'], createAuthTokenConfigToMldev(apiClient, fromConfig, toObject)); + } + return toObject; +} +function fileDataToMldev(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromFileUri = getValueByPath(fromObject, ['fileUri']); + if (fromFileUri != null) { + setValueByPath(toObject, ['fileUri'], fromFileUri); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function functionCallToMldev(fromObject) { + const toObject = {}; + const fromId = getValueByPath(fromObject, ['id']); + if (fromId != null) { + setValueByPath(toObject, ['id'], fromId); + } + const fromArgs = getValueByPath(fromObject, ['args']); + if (fromArgs != null) { + setValueByPath(toObject, ['args'], fromArgs); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + if (getValueByPath(fromObject, ['partialArgs']) !== undefined) { + throw new Error('partialArgs parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['willContinue']) !== undefined) { + throw new Error('willContinue parameter is not supported in Gemini API.'); + } + return toObject; +} +function googleMapsToMldev(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['authConfig']) !== undefined) { + throw new Error('authConfig parameter is not supported in Gemini API.'); + } + const fromEnableWidget = getValueByPath(fromObject, ['enableWidget']); + if (fromEnableWidget != null) { + setValueByPath(toObject, ['enableWidget'], fromEnableWidget); + } + return toObject; +} +function googleSearchToMldev(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['excludeDomains']) !== undefined) { + throw new Error('excludeDomains parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['blockingConfidence']) !== undefined) { + throw new Error('blockingConfidence parameter is not supported in Gemini API.'); + } + const fromTimeRangeFilter = getValueByPath(fromObject, [ + 'timeRangeFilter', + ]); + if (fromTimeRangeFilter != null) { + setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter); + } + return toObject; +} +function liveConnectConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromGenerationConfig = getValueByPath(fromObject, [ + 'generationConfig', + ]); + if (parentObject !== undefined && fromGenerationConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig'], fromGenerationConfig); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (parentObject !== undefined && fromResponseModalities != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'responseModalities'], fromResponseModalities); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (parentObject !== undefined && fromTemperature != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'temperature'], fromTemperature); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (parentObject !== undefined && fromTopP != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'topP'], fromTopP); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (parentObject !== undefined && fromTopK != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'topK'], fromTopK); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (parentObject !== undefined && fromMaxOutputTokens != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'maxOutputTokens'], fromMaxOutputTokens); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (parentObject !== undefined && fromMediaResolution != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'mediaResolution'], fromMediaResolution); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (parentObject !== undefined && fromSeed != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'seed'], fromSeed); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (parentObject !== undefined && fromSpeechConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'speechConfig'], tLiveSpeechConfig(fromSpeechConfig)); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (parentObject !== undefined && fromThinkingConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'thinkingConfig'], fromThinkingConfig); + } + const fromEnableAffectiveDialog = getValueByPath(fromObject, [ + 'enableAffectiveDialog', + ]); + if (parentObject !== undefined && fromEnableAffectiveDialog != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'enableAffectiveDialog'], fromEnableAffectiveDialog); + } + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['setup', 'systemInstruction'], contentToMldev(tContent(fromSystemInstruction))); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = tTools(fromTools); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToMldev(tTool(item)); + }); + } + setValueByPath(parentObject, ['setup', 'tools'], transformedList); + } + const fromSessionResumption = getValueByPath(fromObject, [ + 'sessionResumption', + ]); + if (parentObject !== undefined && fromSessionResumption != null) { + setValueByPath(parentObject, ['setup', 'sessionResumption'], sessionResumptionConfigToMldev(fromSessionResumption)); + } + const fromInputAudioTranscription = getValueByPath(fromObject, [ + 'inputAudioTranscription', + ]); + if (parentObject !== undefined && fromInputAudioTranscription != null) { + setValueByPath(parentObject, ['setup', 'inputAudioTranscription'], fromInputAudioTranscription); + } + const fromOutputAudioTranscription = getValueByPath(fromObject, [ + 'outputAudioTranscription', + ]); + if (parentObject !== undefined && fromOutputAudioTranscription != null) { + setValueByPath(parentObject, ['setup', 'outputAudioTranscription'], fromOutputAudioTranscription); + } + const fromRealtimeInputConfig = getValueByPath(fromObject, [ + 'realtimeInputConfig', + ]); + if (parentObject !== undefined && fromRealtimeInputConfig != null) { + setValueByPath(parentObject, ['setup', 'realtimeInputConfig'], fromRealtimeInputConfig); + } + const fromContextWindowCompression = getValueByPath(fromObject, [ + 'contextWindowCompression', + ]); + if (parentObject !== undefined && fromContextWindowCompression != null) { + setValueByPath(parentObject, ['setup', 'contextWindowCompression'], fromContextWindowCompression); + } + const fromProactivity = getValueByPath(fromObject, ['proactivity']); + if (parentObject !== undefined && fromProactivity != null) { + setValueByPath(parentObject, ['setup', 'proactivity'], fromProactivity); + } + if (getValueByPath(fromObject, ['explicitVadSignal']) !== undefined) { + throw new Error('explicitVadSignal parameter is not supported in Gemini API.'); + } + return toObject; +} +function liveConnectConstraintsToMldev(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['setup', 'model'], tModel(apiClient, fromModel)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['config'], liveConnectConfigToMldev(fromConfig, toObject)); + } + return toObject; +} +function partToMldev(fromObject) { + const toObject = {}; + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromCodeExecutionResult = getValueByPath(fromObject, [ + 'codeExecutionResult', + ]); + if (fromCodeExecutionResult != null) { + setValueByPath(toObject, ['codeExecutionResult'], fromCodeExecutionResult); + } + const fromExecutableCode = getValueByPath(fromObject, [ + 'executableCode', + ]); + if (fromExecutableCode != null) { + setValueByPath(toObject, ['executableCode'], fromExecutableCode); + } + const fromFileData = getValueByPath(fromObject, ['fileData']); + if (fromFileData != null) { + setValueByPath(toObject, ['fileData'], fileDataToMldev(fromFileData)); + } + const fromFunctionCall = getValueByPath(fromObject, ['functionCall']); + if (fromFunctionCall != null) { + setValueByPath(toObject, ['functionCall'], functionCallToMldev(fromFunctionCall)); + } + const fromFunctionResponse = getValueByPath(fromObject, [ + 'functionResponse', + ]); + if (fromFunctionResponse != null) { + setValueByPath(toObject, ['functionResponse'], fromFunctionResponse); + } + const fromInlineData = getValueByPath(fromObject, ['inlineData']); + if (fromInlineData != null) { + setValueByPath(toObject, ['inlineData'], blobToMldev(fromInlineData)); + } + const fromText = getValueByPath(fromObject, ['text']); + if (fromText != null) { + setValueByPath(toObject, ['text'], fromText); + } + const fromThought = getValueByPath(fromObject, ['thought']); + if (fromThought != null) { + setValueByPath(toObject, ['thought'], fromThought); + } + const fromThoughtSignature = getValueByPath(fromObject, [ + 'thoughtSignature', + ]); + if (fromThoughtSignature != null) { + setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature); + } + const fromVideoMetadata = getValueByPath(fromObject, [ + 'videoMetadata', + ]); + if (fromVideoMetadata != null) { + setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata); + } + return toObject; +} +function sessionResumptionConfigToMldev(fromObject) { + const toObject = {}; + const fromHandle = getValueByPath(fromObject, ['handle']); + if (fromHandle != null) { + setValueByPath(toObject, ['handle'], fromHandle); + } + if (getValueByPath(fromObject, ['transparent']) !== undefined) { + throw new Error('transparent parameter is not supported in Gemini API.'); + } + return toObject; +} +function toolToMldev(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['retrieval']) !== undefined) { + throw new Error('retrieval parameter is not supported in Gemini API.'); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + const fromFileSearch = getValueByPath(fromObject, ['fileSearch']); + if (fromFileSearch != null) { + setValueByPath(toObject, ['fileSearch'], fromFileSearch); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + if (getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined) { + throw new Error('enterpriseWebSearch parameter is not supported in Gemini API.'); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], googleMapsToMldev(fromGoogleMaps)); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], googleSearchToMldev(fromGoogleSearch)); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Returns a comma-separated list of field masks from a given object. + * + * @param setup The object to extract field masks from. + * @return A comma-separated list of field masks. + */ +function getFieldMasks(setup) { + const fields = []; + for (const key in setup) { + if (Object.prototype.hasOwnProperty.call(setup, key)) { + const value = setup[key]; + // 2nd layer, recursively get field masks see TODO(b/418290100) + if (typeof value === 'object' && + value != null && + Object.keys(value).length > 0) { + const field = Object.keys(value).map((kk) => `${key}.${kk}`); + fields.push(...field); + } + else { + fields.push(key); // 1st layer + } + } + } + return fields.join(','); +} +/** + * Converts bidiGenerateContentSetup. + * @param requestDict - The request dictionary. + * @param config - The configuration object. + * @return - The modified request dictionary. + */ +function convertBidiSetupToTokenSetup(requestDict, config) { + // Convert bidiGenerateContentSetup from bidiGenerateContentSetup.setup. + let setupForMaskGeneration = null; + const bidiGenerateContentSetupValue = requestDict['bidiGenerateContentSetup']; + if (typeof bidiGenerateContentSetupValue === 'object' && + bidiGenerateContentSetupValue !== null && + 'setup' in bidiGenerateContentSetupValue) { + // Now we know bidiGenerateContentSetupValue is an object and has a 'setup' + // property. + const innerSetup = bidiGenerateContentSetupValue + .setup; + if (typeof innerSetup === 'object' && innerSetup !== null) { + // Valid inner setup found. + requestDict['bidiGenerateContentSetup'] = innerSetup; + setupForMaskGeneration = innerSetup; + } + else { + // `bidiGenerateContentSetupValue.setup` is not a valid object; treat as + // if bidiGenerateContentSetup is invalid. + delete requestDict['bidiGenerateContentSetup']; + } + } + else if (bidiGenerateContentSetupValue !== undefined) { + // `bidiGenerateContentSetup` exists but not in the expected + // shape {setup: {...}}; treat as invalid. + delete requestDict['bidiGenerateContentSetup']; + } + const preExistingFieldMask = requestDict['fieldMask']; + // Handle mask generation setup. + if (setupForMaskGeneration) { + const generatedMaskFromBidi = getFieldMasks(setupForMaskGeneration); + if (Array.isArray(config === null || config === void 0 ? void 0 : config.lockAdditionalFields) && + (config === null || config === void 0 ? void 0 : config.lockAdditionalFields.length) === 0) { + // Case 1: lockAdditionalFields is an empty array. Lock only fields from + // bidi setup. + if (generatedMaskFromBidi) { + // Only assign if mask is not empty + requestDict['fieldMask'] = generatedMaskFromBidi; + } + else { + delete requestDict['fieldMask']; // If mask is empty, effectively no + // specific fields locked by bidi + } + } + else if ((config === null || config === void 0 ? void 0 : config.lockAdditionalFields) && + config.lockAdditionalFields.length > 0 && + preExistingFieldMask !== null && + Array.isArray(preExistingFieldMask) && + preExistingFieldMask.length > 0) { + // Case 2: Lock fields from bidi setup + additional fields + // (preExistingFieldMask). + const generationConfigFields = [ + 'temperature', + 'topK', + 'topP', + 'maxOutputTokens', + 'responseModalities', + 'seed', + 'speechConfig', + ]; + let mappedFieldsFromPreExisting = []; + if (preExistingFieldMask.length > 0) { + mappedFieldsFromPreExisting = preExistingFieldMask.map((field) => { + if (generationConfigFields.includes(field)) { + return `generationConfig.${field}`; + } + return field; // Keep original field name if not in + // generationConfigFields + }); + } + const finalMaskParts = []; + if (generatedMaskFromBidi) { + finalMaskParts.push(generatedMaskFromBidi); + } + if (mappedFieldsFromPreExisting.length > 0) { + finalMaskParts.push(...mappedFieldsFromPreExisting); + } + if (finalMaskParts.length > 0) { + requestDict['fieldMask'] = finalMaskParts.join(','); + } + else { + // If no fields from bidi and no valid additional fields from + // pre-existing mask. + delete requestDict['fieldMask']; + } + } + else { + // Case 3: "Lock all fields" (meaning, don't send a field_mask, let server + // defaults apply or all are mutable). This is hit if: + // - `config.lockAdditionalFields` is undefined. + // - `config.lockAdditionalFields` is non-empty, BUT + // `preExistingFieldMask` is null, not a string, or an empty string. + delete requestDict['fieldMask']; + } + } + else { + // No valid `bidiGenerateContentSetup` was found or extracted. + // "Lock additional null fields if any". + if (preExistingFieldMask !== null && + Array.isArray(preExistingFieldMask) && + preExistingFieldMask.length > 0) { + // If there's a pre-existing field mask, it's a string, and it's not + // empty, then we should lock all fields. + requestDict['fieldMask'] = preExistingFieldMask.join(','); + } + else { + delete requestDict['fieldMask']; + } + } + return requestDict; +} +class Tokens extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + } + /** + * Creates an ephemeral auth token resource. + * + * @experimental + * + * @remarks + * Ephemeral auth tokens is only supported in the Gemini Developer API. + * It can be used for the session connection to the Live constrained API. + * Support in v1alpha only. + * + * @param params - The parameters for the create request. + * @return The created auth token. + * + * @example + * ```ts + * const ai = new GoogleGenAI({ + * apiKey: token.name, + * httpOptions: { apiVersion: 'v1alpha' } // Support in v1alpha only. + * }); + * + * // Case 1: If LiveEphemeralParameters is unset, unlock LiveConnectConfig + * // when using the token in Live API sessions. Each session connection can + * // use a different configuration. + * const config: CreateAuthTokenConfig = { + * uses: 3, + * expireTime: '2025-05-01T00:00:00Z', + * } + * const token = await ai.tokens.create(config); + * + * // Case 2: If LiveEphemeralParameters is set, lock all fields in + * // LiveConnectConfig when using the token in Live API sessions. For + * // example, changing `outputAudioTranscription` in the Live API + * // connection will be ignored by the API. + * const config: CreateAuthTokenConfig = + * uses: 3, + * expireTime: '2025-05-01T00:00:00Z', + * LiveEphemeralParameters: { + * model: 'gemini-2.0-flash-001', + * config: { + * 'responseModalities': ['AUDIO'], + * 'systemInstruction': 'Always answer in English.', + * } + * } + * } + * const token = await ai.tokens.create(config); + * + * // Case 3: If LiveEphemeralParameters is set and lockAdditionalFields is + * // set, lock LiveConnectConfig with set and additional fields (e.g. + * // responseModalities, systemInstruction, temperature in this example) when + * // using the token in Live API sessions. + * const config: CreateAuthTokenConfig = + * uses: 3, + * expireTime: '2025-05-01T00:00:00Z', + * LiveEphemeralParameters: { + * model: 'gemini-2.0-flash-001', + * config: { + * 'responseModalities': ['AUDIO'], + * 'systemInstruction': 'Always answer in English.', + * } + * }, + * lockAdditionalFields: ['temperature'], + * } + * const token = await ai.tokens.create(config); + * + * // Case 4: If LiveEphemeralParameters is set and lockAdditionalFields is + * // empty array, lock LiveConnectConfig with set fields (e.g. + * // responseModalities, systemInstruction in this example) when using the + * // token in Live API sessions. + * const config: CreateAuthTokenConfig = + * uses: 3, + * expireTime: '2025-05-01T00:00:00Z', + * LiveEphemeralParameters: { + * model: 'gemini-2.0-flash-001', + * config: { + * 'responseModalities': ['AUDIO'], + * 'systemInstruction': 'Always answer in English.', + * } + * }, + * lockAdditionalFields: [], + * } + * const token = await ai.tokens.create(config); + * ``` + */ + async create(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('The client.tokens.create method is only supported by the Gemini Developer API.'); + } + else { + const body = createAuthTokenParametersToMldev(this.apiClient, params); + path = formatMap('auth_tokens', body['_url']); + queryParams = body['_query']; + delete body['config']; + delete body['_url']; + delete body['_query']; + const transformedBody = convertBidiSetupToTokenSetup(body, params.config); + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(transformedBody), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Code generated by the Google Gen AI SDK generator DO NOT EDIT. +function cancelTuningJobParametersToMldev(fromObject, _rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + return toObject; +} +function cancelTuningJobParametersToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + return toObject; +} +function cancelTuningJobResponseFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function cancelTuningJobResponseFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function createTuningJobConfigToMldev(fromObject, parentObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['validationDataset']) !== undefined) { + throw new Error('validationDataset parameter is not supported in Gemini API.'); + } + const fromTunedModelDisplayName = getValueByPath(fromObject, [ + 'tunedModelDisplayName', + ]); + if (parentObject !== undefined && fromTunedModelDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromTunedModelDisplayName); + } + if (getValueByPath(fromObject, ['description']) !== undefined) { + throw new Error('description parameter is not supported in Gemini API.'); + } + const fromEpochCount = getValueByPath(fromObject, ['epochCount']); + if (parentObject !== undefined && fromEpochCount != null) { + setValueByPath(parentObject, ['tuningTask', 'hyperparameters', 'epochCount'], fromEpochCount); + } + const fromLearningRateMultiplier = getValueByPath(fromObject, [ + 'learningRateMultiplier', + ]); + if (fromLearningRateMultiplier != null) { + setValueByPath(toObject, ['tuningTask', 'hyperparameters', 'learningRateMultiplier'], fromLearningRateMultiplier); + } + if (getValueByPath(fromObject, ['exportLastCheckpointOnly']) !== + undefined) { + throw new Error('exportLastCheckpointOnly parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['preTunedModelCheckpointId']) !== + undefined) { + throw new Error('preTunedModelCheckpointId parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['adapterSize']) !== undefined) { + throw new Error('adapterSize parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['tuningMode']) !== undefined) { + throw new Error('tuningMode parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['customBaseModel']) !== undefined) { + throw new Error('customBaseModel parameter is not supported in Gemini API.'); + } + const fromBatchSize = getValueByPath(fromObject, ['batchSize']); + if (parentObject !== undefined && fromBatchSize != null) { + setValueByPath(parentObject, ['tuningTask', 'hyperparameters', 'batchSize'], fromBatchSize); + } + const fromLearningRate = getValueByPath(fromObject, ['learningRate']); + if (parentObject !== undefined && fromLearningRate != null) { + setValueByPath(parentObject, ['tuningTask', 'hyperparameters', 'learningRate'], fromLearningRate); + } + if (getValueByPath(fromObject, ['labels']) !== undefined) { + throw new Error('labels parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['beta']) !== undefined) { + throw new Error('beta parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['baseTeacherModel']) !== undefined) { + throw new Error('baseTeacherModel parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['tunedTeacherModelSource']) !== undefined) { + throw new Error('tunedTeacherModelSource parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['sftLossWeightMultiplier']) !== undefined) { + throw new Error('sftLossWeightMultiplier parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['outputUri']) !== undefined) { + throw new Error('outputUri parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['encryptionSpec']) !== undefined) { + throw new Error('encryptionSpec parameter is not supported in Gemini API.'); + } + return toObject; +} +function createTuningJobConfigToVertex(fromObject, parentObject, rootObject) { + const toObject = {}; + let discriminatorValidationDataset = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorValidationDataset === undefined) { + discriminatorValidationDataset = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorValidationDataset === 'SUPERVISED_FINE_TUNING') { + const fromValidationDataset = getValueByPath(fromObject, [ + 'validationDataset', + ]); + if (parentObject !== undefined && fromValidationDataset != null) { + setValueByPath(parentObject, ['supervisedTuningSpec'], tuningValidationDatasetToVertex(fromValidationDataset)); + } + } + else if (discriminatorValidationDataset === 'PREFERENCE_TUNING') { + const fromValidationDataset = getValueByPath(fromObject, [ + 'validationDataset', + ]); + if (parentObject !== undefined && fromValidationDataset != null) { + setValueByPath(parentObject, ['preferenceOptimizationSpec'], tuningValidationDatasetToVertex(fromValidationDataset)); + } + } + else if (discriminatorValidationDataset === 'DISTILLATION') { + const fromValidationDataset = getValueByPath(fromObject, [ + 'validationDataset', + ]); + if (parentObject !== undefined && fromValidationDataset != null) { + setValueByPath(parentObject, ['distillationSpec'], tuningValidationDatasetToVertex(fromValidationDataset)); + } + } + const fromTunedModelDisplayName = getValueByPath(fromObject, [ + 'tunedModelDisplayName', + ]); + if (parentObject !== undefined && fromTunedModelDisplayName != null) { + setValueByPath(parentObject, ['tunedModelDisplayName'], fromTunedModelDisplayName); + } + const fromDescription = getValueByPath(fromObject, ['description']); + if (parentObject !== undefined && fromDescription != null) { + setValueByPath(parentObject, ['description'], fromDescription); + } + let discriminatorEpochCount = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorEpochCount === undefined) { + discriminatorEpochCount = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorEpochCount === 'SUPERVISED_FINE_TUNING') { + const fromEpochCount = getValueByPath(fromObject, ['epochCount']); + if (parentObject !== undefined && fromEpochCount != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'hyperParameters', 'epochCount'], fromEpochCount); + } + } + else if (discriminatorEpochCount === 'PREFERENCE_TUNING') { + const fromEpochCount = getValueByPath(fromObject, ['epochCount']); + if (parentObject !== undefined && fromEpochCount != null) { + setValueByPath(parentObject, ['preferenceOptimizationSpec', 'hyperParameters', 'epochCount'], fromEpochCount); + } + } + else if (discriminatorEpochCount === 'DISTILLATION') { + const fromEpochCount = getValueByPath(fromObject, ['epochCount']); + if (parentObject !== undefined && fromEpochCount != null) { + setValueByPath(parentObject, ['distillationSpec', 'hyperParameters', 'epochCount'], fromEpochCount); + } + } + let discriminatorLearningRateMultiplier = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorLearningRateMultiplier === undefined) { + discriminatorLearningRateMultiplier = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorLearningRateMultiplier === 'SUPERVISED_FINE_TUNING') { + const fromLearningRateMultiplier = getValueByPath(fromObject, [ + 'learningRateMultiplier', + ]); + if (parentObject !== undefined && fromLearningRateMultiplier != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'hyperParameters', 'learningRateMultiplier'], fromLearningRateMultiplier); + } + } + else if (discriminatorLearningRateMultiplier === 'PREFERENCE_TUNING') { + const fromLearningRateMultiplier = getValueByPath(fromObject, [ + 'learningRateMultiplier', + ]); + if (parentObject !== undefined && fromLearningRateMultiplier != null) { + setValueByPath(parentObject, [ + 'preferenceOptimizationSpec', + 'hyperParameters', + 'learningRateMultiplier', + ], fromLearningRateMultiplier); + } + } + else if (discriminatorLearningRateMultiplier === 'DISTILLATION') { + const fromLearningRateMultiplier = getValueByPath(fromObject, [ + 'learningRateMultiplier', + ]); + if (parentObject !== undefined && fromLearningRateMultiplier != null) { + setValueByPath(parentObject, ['distillationSpec', 'hyperParameters', 'learningRateMultiplier'], fromLearningRateMultiplier); + } + } + let discriminatorExportLastCheckpointOnly = getValueByPath(rootObject, ['config', 'method']); + if (discriminatorExportLastCheckpointOnly === undefined) { + discriminatorExportLastCheckpointOnly = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorExportLastCheckpointOnly === 'SUPERVISED_FINE_TUNING') { + const fromExportLastCheckpointOnly = getValueByPath(fromObject, [ + 'exportLastCheckpointOnly', + ]); + if (parentObject !== undefined && fromExportLastCheckpointOnly != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'exportLastCheckpointOnly'], fromExportLastCheckpointOnly); + } + } + else if (discriminatorExportLastCheckpointOnly === 'PREFERENCE_TUNING') { + const fromExportLastCheckpointOnly = getValueByPath(fromObject, [ + 'exportLastCheckpointOnly', + ]); + if (parentObject !== undefined && fromExportLastCheckpointOnly != null) { + setValueByPath(parentObject, ['preferenceOptimizationSpec', 'exportLastCheckpointOnly'], fromExportLastCheckpointOnly); + } + } + else if (discriminatorExportLastCheckpointOnly === 'DISTILLATION') { + const fromExportLastCheckpointOnly = getValueByPath(fromObject, [ + 'exportLastCheckpointOnly', + ]); + if (parentObject !== undefined && fromExportLastCheckpointOnly != null) { + setValueByPath(parentObject, ['distillationSpec', 'exportLastCheckpointOnly'], fromExportLastCheckpointOnly); + } + } + let discriminatorAdapterSize = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorAdapterSize === undefined) { + discriminatorAdapterSize = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorAdapterSize === 'SUPERVISED_FINE_TUNING') { + const fromAdapterSize = getValueByPath(fromObject, ['adapterSize']); + if (parentObject !== undefined && fromAdapterSize != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'hyperParameters', 'adapterSize'], fromAdapterSize); + } + } + else if (discriminatorAdapterSize === 'PREFERENCE_TUNING') { + const fromAdapterSize = getValueByPath(fromObject, ['adapterSize']); + if (parentObject !== undefined && fromAdapterSize != null) { + setValueByPath(parentObject, ['preferenceOptimizationSpec', 'hyperParameters', 'adapterSize'], fromAdapterSize); + } + } + else if (discriminatorAdapterSize === 'DISTILLATION') { + const fromAdapterSize = getValueByPath(fromObject, ['adapterSize']); + if (parentObject !== undefined && fromAdapterSize != null) { + setValueByPath(parentObject, ['distillationSpec', 'hyperParameters', 'adapterSize'], fromAdapterSize); + } + } + let discriminatorTuningMode = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorTuningMode === undefined) { + discriminatorTuningMode = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorTuningMode === 'SUPERVISED_FINE_TUNING') { + const fromTuningMode = getValueByPath(fromObject, ['tuningMode']); + if (parentObject !== undefined && fromTuningMode != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'tuningMode'], fromTuningMode); + } + } + const fromCustomBaseModel = getValueByPath(fromObject, [ + 'customBaseModel', + ]); + if (parentObject !== undefined && fromCustomBaseModel != null) { + setValueByPath(parentObject, ['customBaseModel'], fromCustomBaseModel); + } + let discriminatorBatchSize = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorBatchSize === undefined) { + discriminatorBatchSize = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorBatchSize === 'SUPERVISED_FINE_TUNING') { + const fromBatchSize = getValueByPath(fromObject, ['batchSize']); + if (parentObject !== undefined && fromBatchSize != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'hyperParameters', 'batchSize'], fromBatchSize); + } + } + let discriminatorLearningRate = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorLearningRate === undefined) { + discriminatorLearningRate = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorLearningRate === 'SUPERVISED_FINE_TUNING') { + const fromLearningRate = getValueByPath(fromObject, [ + 'learningRate', + ]); + if (parentObject !== undefined && fromLearningRate != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'hyperParameters', 'learningRate'], fromLearningRate); + } + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (parentObject !== undefined && fromLabels != null) { + setValueByPath(parentObject, ['labels'], fromLabels); + } + const fromBeta = getValueByPath(fromObject, ['beta']); + if (parentObject !== undefined && fromBeta != null) { + setValueByPath(parentObject, ['preferenceOptimizationSpec', 'hyperParameters', 'beta'], fromBeta); + } + const fromBaseTeacherModel = getValueByPath(fromObject, [ + 'baseTeacherModel', + ]); + if (parentObject !== undefined && fromBaseTeacherModel != null) { + setValueByPath(parentObject, ['distillationSpec', 'baseTeacherModel'], fromBaseTeacherModel); + } + const fromTunedTeacherModelSource = getValueByPath(fromObject, [ + 'tunedTeacherModelSource', + ]); + if (parentObject !== undefined && fromTunedTeacherModelSource != null) { + setValueByPath(parentObject, ['distillationSpec', 'tunedTeacherModelSource'], fromTunedTeacherModelSource); + } + const fromSftLossWeightMultiplier = getValueByPath(fromObject, [ + 'sftLossWeightMultiplier', + ]); + if (parentObject !== undefined && fromSftLossWeightMultiplier != null) { + setValueByPath(parentObject, ['distillationSpec', 'hyperParameters', 'sftLossWeightMultiplier'], fromSftLossWeightMultiplier); + } + const fromOutputUri = getValueByPath(fromObject, ['outputUri']); + if (parentObject !== undefined && fromOutputUri != null) { + setValueByPath(parentObject, ['outputUri'], fromOutputUri); + } + const fromEncryptionSpec = getValueByPath(fromObject, [ + 'encryptionSpec', + ]); + if (parentObject !== undefined && fromEncryptionSpec != null) { + setValueByPath(parentObject, ['encryptionSpec'], fromEncryptionSpec); + } + return toObject; +} +function createTuningJobParametersPrivateToMldev(fromObject, rootObject) { + const toObject = {}; + const fromBaseModel = getValueByPath(fromObject, ['baseModel']); + if (fromBaseModel != null) { + setValueByPath(toObject, ['baseModel'], fromBaseModel); + } + const fromPreTunedModel = getValueByPath(fromObject, [ + 'preTunedModel', + ]); + if (fromPreTunedModel != null) { + setValueByPath(toObject, ['preTunedModel'], fromPreTunedModel); + } + const fromTrainingDataset = getValueByPath(fromObject, [ + 'trainingDataset', + ]); + if (fromTrainingDataset != null) { + tuningDatasetToMldev(fromTrainingDataset); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createTuningJobConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function createTuningJobParametersPrivateToVertex(fromObject, rootObject) { + const toObject = {}; + const fromBaseModel = getValueByPath(fromObject, ['baseModel']); + if (fromBaseModel != null) { + setValueByPath(toObject, ['baseModel'], fromBaseModel); + } + const fromPreTunedModel = getValueByPath(fromObject, [ + 'preTunedModel', + ]); + if (fromPreTunedModel != null) { + setValueByPath(toObject, ['preTunedModel'], fromPreTunedModel); + } + const fromTrainingDataset = getValueByPath(fromObject, [ + 'trainingDataset', + ]); + if (fromTrainingDataset != null) { + tuningDatasetToVertex(fromTrainingDataset, toObject, rootObject); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createTuningJobConfigToVertex(fromConfig, toObject, rootObject); + } + return toObject; +} +function getTuningJobParametersToMldev(fromObject, _rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + return toObject; +} +function getTuningJobParametersToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + return toObject; +} +function listTuningJobsConfigToMldev(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + const fromFilter = getValueByPath(fromObject, ['filter']); + if (parentObject !== undefined && fromFilter != null) { + setValueByPath(parentObject, ['_query', 'filter'], fromFilter); + } + return toObject; +} +function listTuningJobsConfigToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + const fromFilter = getValueByPath(fromObject, ['filter']); + if (parentObject !== undefined && fromFilter != null) { + setValueByPath(parentObject, ['_query', 'filter'], fromFilter); + } + return toObject; +} +function listTuningJobsParametersToMldev(fromObject, rootObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listTuningJobsConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function listTuningJobsParametersToVertex(fromObject, rootObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listTuningJobsConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function listTuningJobsResponseFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromTuningJobs = getValueByPath(fromObject, ['tunedModels']); + if (fromTuningJobs != null) { + let transformedList = fromTuningJobs; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return tuningJobFromMldev(item); + }); + } + setValueByPath(toObject, ['tuningJobs'], transformedList); + } + return toObject; +} +function listTuningJobsResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromTuningJobs = getValueByPath(fromObject, ['tuningJobs']); + if (fromTuningJobs != null) { + let transformedList = fromTuningJobs; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return tuningJobFromVertex(item); + }); + } + setValueByPath(toObject, ['tuningJobs'], transformedList); + } + return toObject; +} +function tunedModelFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['name']); + if (fromModel != null) { + setValueByPath(toObject, ['model'], fromModel); + } + const fromEndpoint = getValueByPath(fromObject, ['name']); + if (fromEndpoint != null) { + setValueByPath(toObject, ['endpoint'], fromEndpoint); + } + return toObject; +} +function tuningDatasetToMldev(fromObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['gcsUri']) !== undefined) { + throw new Error('gcsUri parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['vertexDatasetResource']) !== undefined) { + throw new Error('vertexDatasetResource parameter is not supported in Gemini API.'); + } + const fromExamples = getValueByPath(fromObject, ['examples']); + if (fromExamples != null) { + let transformedList = fromExamples; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['examples', 'examples'], transformedList); + } + return toObject; +} +function tuningDatasetToVertex(fromObject, parentObject, rootObject) { + const toObject = {}; + let discriminatorGcsUri = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorGcsUri === undefined) { + discriminatorGcsUri = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorGcsUri === 'SUPERVISED_FINE_TUNING') { + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (parentObject !== undefined && fromGcsUri != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'trainingDatasetUri'], fromGcsUri); + } + } + else if (discriminatorGcsUri === 'PREFERENCE_TUNING') { + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (parentObject !== undefined && fromGcsUri != null) { + setValueByPath(parentObject, ['preferenceOptimizationSpec', 'trainingDatasetUri'], fromGcsUri); + } + } + else if (discriminatorGcsUri === 'DISTILLATION') { + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (parentObject !== undefined && fromGcsUri != null) { + setValueByPath(parentObject, ['distillationSpec', 'promptDatasetUri'], fromGcsUri); + } + } + let discriminatorVertexDatasetResource = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorVertexDatasetResource === undefined) { + discriminatorVertexDatasetResource = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorVertexDatasetResource === 'SUPERVISED_FINE_TUNING') { + const fromVertexDatasetResource = getValueByPath(fromObject, [ + 'vertexDatasetResource', + ]); + if (parentObject !== undefined && fromVertexDatasetResource != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'trainingDatasetUri'], fromVertexDatasetResource); + } + } + else if (discriminatorVertexDatasetResource === 'PREFERENCE_TUNING') { + const fromVertexDatasetResource = getValueByPath(fromObject, [ + 'vertexDatasetResource', + ]); + if (parentObject !== undefined && fromVertexDatasetResource != null) { + setValueByPath(parentObject, ['preferenceOptimizationSpec', 'trainingDatasetUri'], fromVertexDatasetResource); + } + } + else if (discriminatorVertexDatasetResource === 'DISTILLATION') { + const fromVertexDatasetResource = getValueByPath(fromObject, [ + 'vertexDatasetResource', + ]); + if (parentObject !== undefined && fromVertexDatasetResource != null) { + setValueByPath(parentObject, ['distillationSpec', 'promptDatasetUri'], fromVertexDatasetResource); + } + } + if (getValueByPath(fromObject, ['examples']) !== undefined) { + throw new Error('examples parameter is not supported in Vertex AI.'); + } + return toObject; +} +function tuningJobFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromState = getValueByPath(fromObject, ['state']); + if (fromState != null) { + setValueByPath(toObject, ['state'], tTuningJobStatus(fromState)); + } + const fromCreateTime = getValueByPath(fromObject, ['createTime']); + if (fromCreateTime != null) { + setValueByPath(toObject, ['createTime'], fromCreateTime); + } + const fromStartTime = getValueByPath(fromObject, [ + 'tuningTask', + 'startTime', + ]); + if (fromStartTime != null) { + setValueByPath(toObject, ['startTime'], fromStartTime); + } + const fromEndTime = getValueByPath(fromObject, [ + 'tuningTask', + 'completeTime', + ]); + if (fromEndTime != null) { + setValueByPath(toObject, ['endTime'], fromEndTime); + } + const fromUpdateTime = getValueByPath(fromObject, ['updateTime']); + if (fromUpdateTime != null) { + setValueByPath(toObject, ['updateTime'], fromUpdateTime); + } + const fromDescription = getValueByPath(fromObject, ['description']); + if (fromDescription != null) { + setValueByPath(toObject, ['description'], fromDescription); + } + const fromBaseModel = getValueByPath(fromObject, ['baseModel']); + if (fromBaseModel != null) { + setValueByPath(toObject, ['baseModel'], fromBaseModel); + } + const fromTunedModel = getValueByPath(fromObject, ['_self']); + if (fromTunedModel != null) { + setValueByPath(toObject, ['tunedModel'], tunedModelFromMldev(fromTunedModel)); + } + return toObject; +} +function tuningJobFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromState = getValueByPath(fromObject, ['state']); + if (fromState != null) { + setValueByPath(toObject, ['state'], tTuningJobStatus(fromState)); + } + const fromCreateTime = getValueByPath(fromObject, ['createTime']); + if (fromCreateTime != null) { + setValueByPath(toObject, ['createTime'], fromCreateTime); + } + const fromStartTime = getValueByPath(fromObject, ['startTime']); + if (fromStartTime != null) { + setValueByPath(toObject, ['startTime'], fromStartTime); + } + const fromEndTime = getValueByPath(fromObject, ['endTime']); + if (fromEndTime != null) { + setValueByPath(toObject, ['endTime'], fromEndTime); + } + const fromUpdateTime = getValueByPath(fromObject, ['updateTime']); + if (fromUpdateTime != null) { + setValueByPath(toObject, ['updateTime'], fromUpdateTime); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromDescription = getValueByPath(fromObject, ['description']); + if (fromDescription != null) { + setValueByPath(toObject, ['description'], fromDescription); + } + const fromBaseModel = getValueByPath(fromObject, ['baseModel']); + if (fromBaseModel != null) { + setValueByPath(toObject, ['baseModel'], fromBaseModel); + } + const fromTunedModel = getValueByPath(fromObject, ['tunedModel']); + if (fromTunedModel != null) { + setValueByPath(toObject, ['tunedModel'], fromTunedModel); + } + const fromPreTunedModel = getValueByPath(fromObject, [ + 'preTunedModel', + ]); + if (fromPreTunedModel != null) { + setValueByPath(toObject, ['preTunedModel'], fromPreTunedModel); + } + const fromSupervisedTuningSpec = getValueByPath(fromObject, [ + 'supervisedTuningSpec', + ]); + if (fromSupervisedTuningSpec != null) { + setValueByPath(toObject, ['supervisedTuningSpec'], fromSupervisedTuningSpec); + } + const fromPreferenceOptimizationSpec = getValueByPath(fromObject, [ + 'preferenceOptimizationSpec', + ]); + if (fromPreferenceOptimizationSpec != null) { + setValueByPath(toObject, ['preferenceOptimizationSpec'], fromPreferenceOptimizationSpec); + } + const fromDistillationSpec = getValueByPath(fromObject, [ + 'distillationSpec', + ]); + if (fromDistillationSpec != null) { + setValueByPath(toObject, ['distillationSpec'], fromDistillationSpec); + } + const fromTuningDataStats = getValueByPath(fromObject, [ + 'tuningDataStats', + ]); + if (fromTuningDataStats != null) { + setValueByPath(toObject, ['tuningDataStats'], fromTuningDataStats); + } + const fromEncryptionSpec = getValueByPath(fromObject, [ + 'encryptionSpec', + ]); + if (fromEncryptionSpec != null) { + setValueByPath(toObject, ['encryptionSpec'], fromEncryptionSpec); + } + const fromPartnerModelTuningSpec = getValueByPath(fromObject, [ + 'partnerModelTuningSpec', + ]); + if (fromPartnerModelTuningSpec != null) { + setValueByPath(toObject, ['partnerModelTuningSpec'], fromPartnerModelTuningSpec); + } + const fromCustomBaseModel = getValueByPath(fromObject, [ + 'customBaseModel', + ]); + if (fromCustomBaseModel != null) { + setValueByPath(toObject, ['customBaseModel'], fromCustomBaseModel); + } + const fromExperiment = getValueByPath(fromObject, ['experiment']); + if (fromExperiment != null) { + setValueByPath(toObject, ['experiment'], fromExperiment); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (fromLabels != null) { + setValueByPath(toObject, ['labels'], fromLabels); + } + const fromOutputUri = getValueByPath(fromObject, ['outputUri']); + if (fromOutputUri != null) { + setValueByPath(toObject, ['outputUri'], fromOutputUri); + } + const fromPipelineJob = getValueByPath(fromObject, ['pipelineJob']); + if (fromPipelineJob != null) { + setValueByPath(toObject, ['pipelineJob'], fromPipelineJob); + } + const fromServiceAccount = getValueByPath(fromObject, [ + 'serviceAccount', + ]); + if (fromServiceAccount != null) { + setValueByPath(toObject, ['serviceAccount'], fromServiceAccount); + } + const fromTunedModelDisplayName = getValueByPath(fromObject, [ + 'tunedModelDisplayName', + ]); + if (fromTunedModelDisplayName != null) { + setValueByPath(toObject, ['tunedModelDisplayName'], fromTunedModelDisplayName); + } + const fromVeoTuningSpec = getValueByPath(fromObject, [ + 'veoTuningSpec', + ]); + if (fromVeoTuningSpec != null) { + setValueByPath(toObject, ['veoTuningSpec'], fromVeoTuningSpec); + } + return toObject; +} +function tuningOperationFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + return toObject; +} +function tuningValidationDatasetToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (fromGcsUri != null) { + setValueByPath(toObject, ['validationDatasetUri'], fromGcsUri); + } + const fromVertexDatasetResource = getValueByPath(fromObject, [ + 'vertexDatasetResource', + ]); + if (fromVertexDatasetResource != null) { + setValueByPath(toObject, ['validationDatasetUri'], fromVertexDatasetResource); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Tunings extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + /** + * Lists tuning jobs. + * + * @param params - The parameters for the list request. + * @return - A pager of tuning jobs. + * + * @example + * ```ts + * const tuningJobs = await ai.tunings.list({config: {'pageSize': 2}}); + * for await (const tuningJob of tuningJobs) { + * console.log(tuningJob); + * } + * ``` + */ + this.list = async (params = {}) => { + return new Pager(PagedItem.PAGED_ITEM_TUNING_JOBS, (x) => this.listInternal(x), await this.listInternal(params), params); + }; + /** + * Gets a TuningJob. + * + * @param name - The resource name of the tuning job. + * @return - A TuningJob object. + * + * @experimental - The SDK's tuning implementation is experimental, and may + * change in future versions. + */ + this.get = async (params) => { + return await this.getInternal(params); + }; + /** + * Creates a supervised fine-tuning job. + * + * @param params - The parameters for the tuning job. + * @return - A TuningJob operation. + * + * @experimental - The SDK's tuning implementation is experimental, and may + * change in future versions. + */ + this.tune = async (params) => { + var _a; + if (this.apiClient.isVertexAI()) { + if (params.baseModel.startsWith('projects/')) { + const preTunedModel = { + tunedModelName: params.baseModel, + }; + if ((_a = params.config) === null || _a === void 0 ? void 0 : _a.preTunedModelCheckpointId) { + preTunedModel.checkpointId = params.config.preTunedModelCheckpointId; + } + const paramsPrivate = Object.assign(Object.assign({}, params), { preTunedModel: preTunedModel }); + paramsPrivate.baseModel = undefined; + return await this.tuneInternal(paramsPrivate); + } + else { + const paramsPrivate = Object.assign({}, params); + return await this.tuneInternal(paramsPrivate); + } + } + else { + const paramsPrivate = Object.assign({}, params); + const operation = await this.tuneMldevInternal(paramsPrivate); + let tunedModelName = ''; + if (operation['metadata'] !== undefined && + operation['metadata']['tunedModel'] !== undefined) { + tunedModelName = operation['metadata']['tunedModel']; + } + else if (operation['name'] !== undefined && + operation['name'].includes('/operations/')) { + tunedModelName = operation['name'].split('/operations/')[0]; + } + const tuningJob = { + name: tunedModelName, + state: JobState.JOB_STATE_QUEUED, + }; + return tuningJob; + } + }; + } + async getInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = getTuningJobParametersToVertex(params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = tuningJobFromVertex(apiResponse); + return resp; + }); + } + else { + const body = getTuningJobParametersToMldev(params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = tuningJobFromMldev(apiResponse); + return resp; + }); + } + } + async listInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = listTuningJobsParametersToVertex(params); + path = formatMap('tuningJobs', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listTuningJobsResponseFromVertex(apiResponse); + const typedResp = new ListTuningJobsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = listTuningJobsParametersToMldev(params); + path = formatMap('tunedModels', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listTuningJobsResponseFromMldev(apiResponse); + const typedResp = new ListTuningJobsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Cancels a tuning job. + * + * @param params - The parameters for the cancel request. + * @return The empty response returned by the API. + * + * @example + * ```ts + * await ai.tunings.cancel({name: '...'}); // The server-generated resource name. + * ``` + */ + async cancel(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = cancelTuningJobParametersToVertex(params); + path = formatMap('{name}:cancel', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = cancelTuningJobResponseFromVertex(apiResponse); + const typedResp = new CancelTuningJobResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = cancelTuningJobParametersToMldev(params); + path = formatMap('{name}:cancel', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = cancelTuningJobResponseFromMldev(apiResponse); + const typedResp = new CancelTuningJobResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + async tuneInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = createTuningJobParametersPrivateToVertex(params, params); + path = formatMap('tuningJobs', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = tuningJobFromVertex(apiResponse); + return resp; + }); + } + else { + throw new Error('This method is only supported by the Vertex AI.'); + } + } + async tuneMldevInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = createTuningJobParametersPrivateToMldev(params); + path = formatMap('tunedModels', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = tuningOperationFromMldev(apiResponse); + return resp; + }); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const GOOGLE_API_KEY_HEADER = 'x-goog-api-key'; +// TODO(b/395122533): We need a secure client side authentication mechanism. +class WebAuth { + constructor(apiKey) { + this.apiKey = apiKey; + } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async addAuthHeaders(headers, url) { + if (headers.get(GOOGLE_API_KEY_HEADER) !== null) { + return; + } + if (this.apiKey.startsWith('auth_tokens/')) { + throw new Error('Ephemeral tokens are only supported by the live API.'); + } + // Check if API key is empty or null + if (!this.apiKey) { + throw new Error('API key is missing. Please provide a valid API key.'); + } + headers.append(GOOGLE_API_KEY_HEADER, this.apiKey); + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const LANGUAGE_LABEL_PREFIX = 'gl-node/'; +/** + * The Google GenAI SDK. + * + * @remarks + * Provides access to the GenAI features through either the {@link https://cloud.google.com/vertex-ai/docs/reference/rest | Gemini API} + * or the {@link https://cloud.google.com/vertex-ai/docs/reference/rest | Vertex AI API}. + * + * The {@link GoogleGenAIOptions.vertexai} value determines which of the API services to use. + * + * When using the Gemini API, a {@link GoogleGenAIOptions.apiKey} must also be set, + * when using Vertex AI {@link GoogleGenAIOptions.project} and {@link GoogleGenAIOptions.location} must also be set. + * + * @example + * Initializing the SDK for using the Gemini API: + * ```ts + * import {GoogleGenAI} from '@google/genai'; + * const ai = new GoogleGenAI({apiKey: 'GEMINI_API_KEY'}); + * ``` + * + * @example + * Initializing the SDK for using the Vertex AI API: + * ```ts + * import {GoogleGenAI} from '@google/genai'; + * const ai = new GoogleGenAI({ + * vertexai: true, + * project: 'PROJECT_ID', + * location: 'PROJECT_LOCATION' + * }); + * ``` + * + */ +class GoogleGenAI { + get interactions() { + var _a; + if (this._interactions !== undefined) { + return this._interactions; + } + console.warn('GoogleGenAI.interactions: Interactions usage is experimental and may change in future versions.'); + if (this.vertexai) { + throw new Error('This version of the GenAI SDK does not support Vertex AI API for interactions.'); + } + const httpOpts = this.httpOptions; + // Unsupported Options Warnings + if (httpOpts === null || httpOpts === void 0 ? void 0 : httpOpts.extraBody) { + console.warn('GoogleGenAI.interactions: Client level httpOptions.extraBody is not supported by the interactions client and will be ignored.'); + } + const nextGenClient = new GeminiNextGenAPIClient({ + baseURL: this.apiClient.getBaseUrl(), + apiKey: this.apiKey, + apiVersion: this.apiClient.getApiVersion(), + clientAdapter: this.apiClient, + defaultHeaders: this.apiClient.getDefaultHeaders(), + timeout: httpOpts === null || httpOpts === void 0 ? void 0 : httpOpts.timeout, + maxRetries: (_a = httpOpts === null || httpOpts === void 0 ? void 0 : httpOpts.retryOptions) === null || _a === void 0 ? void 0 : _a.attempts, + }); + this._interactions = nextGenClient.interactions; + return this._interactions; + } + constructor(options) { + var _a; + if (options.apiKey == null) { + throw new Error(`An API Key must be set when running in an unspecified environment.\n + ${crossError().message}`); + } + this.vertexai = (_a = options.vertexai) !== null && _a !== void 0 ? _a : false; + this.apiKey = options.apiKey; + this.apiVersion = options.apiVersion; + this.httpOptions = options.httpOptions; + const auth = new WebAuth(this.apiKey); + this.apiClient = new ApiClient({ + auth: auth, + apiVersion: this.apiVersion, + apiKey: this.apiKey, + vertexai: this.vertexai, + httpOptions: this.httpOptions, + userAgentExtra: LANGUAGE_LABEL_PREFIX + 'cross', + uploader: new CrossUploader(), + downloader: new CrossDownloader(), + }); + this.models = new Models(this.apiClient); + this.live = new Live(this.apiClient, auth, new CrossWebSocketFactory()); + this.chats = new Chats(this.models, this.apiClient); + this.batches = new Batches(this.apiClient); + this.caches = new Caches(this.apiClient); + this.files = new Files(this.apiClient); + this.operations = new Operations(this.apiClient); + this.authTokens = new Tokens(this.apiClient); + this.tunings = new Tunings(this.apiClient); + this.fileSearchStores = new FileSearchStores(this.apiClient); + } +} + +export { ActivityHandling, AdapterSize, ApiError, ApiSpec, AuthType, Batches, Behavior, BlockedReason, Caches, CancelTuningJobResponse, Chat, Chats, ComputeTokensResponse, ContentReferenceImage, ControlReferenceImage, ControlReferenceType, CountTokensResponse, CreateFileResponse, DeleteCachedContentResponse, DeleteFileResponse, DeleteModelResponse, DocumentState, DynamicRetrievalConfigMode, EditImageResponse, EditMode, EmbedContentResponse, EndSensitivity, Environment, FeatureSelectionPreference, FileSource, FileState, Files, FinishReason, FunctionCallingConfigMode, FunctionResponse, FunctionResponseBlob, FunctionResponseFileData, FunctionResponsePart, FunctionResponseScheduling, GenerateContentResponse, GenerateContentResponsePromptFeedback, GenerateContentResponseUsageMetadata, GenerateImagesResponse, GenerateVideosOperation, GenerateVideosResponse, GoogleGenAI, HarmBlockMethod, HarmBlockThreshold, HarmCategory, HarmProbability, HarmSeverity, HttpElementLocation, HttpResponse, ImagePromptLanguage, ImportFileOperation, ImportFileResponse, InlinedEmbedContentResponse, InlinedResponse, JobState, Language, ListBatchJobsResponse, ListCachedContentsResponse, ListDocumentsResponse, ListFileSearchStoresResponse, ListFilesResponse, ListModelsResponse, ListTuningJobsResponse, Live, LiveClientToolResponse, LiveMusicPlaybackControl, LiveMusicServerMessage, LiveSendToolResponseParameters, LiveServerMessage, MaskReferenceImage, MaskReferenceMode, MediaModality, MediaResolution, Modality, Models, MusicGenerationMode, Operations, Outcome, PagedItem, Pager, PartMediaResolutionLevel, PersonGeneration, PhishBlockThreshold, RawReferenceImage, RecontextImageResponse, RegisterFilesResponse, ReplayResponse, ResourceScope, SafetyFilterLevel, Scale, SegmentImageResponse, SegmentMode, Session, SingleEmbedContentResponse, StartSensitivity, StyleReferenceImage, SubjectReferenceImage, SubjectReferenceType, ThinkingLevel, Tokens, TrafficType, TuningMethod, TuningMode, TuningTask, TurnCompleteReason, TurnCoverage, Type, UploadToFileSearchStoreOperation, UploadToFileSearchStoreResponse, UploadToFileSearchStoreResumableResponse, UpscaleImageResponse, UrlRetrievalStatus, VadSignalType, VideoCompressionQuality, VideoGenerationMaskMode, VideoGenerationReferenceType, VoiceActivityType, createFunctionResponsePartFromBase64, createFunctionResponsePartFromUri, createModelContent, createPartFromBase64, createPartFromCodeExecutionResult, createPartFromExecutableCode, createPartFromFunctionCall, createPartFromFunctionResponse, createPartFromText, createPartFromUri, createUserContent, mcpToTool, setDefaultBaseUrls }; +//# sourceMappingURL=index.mjs.map diff --git a/server/node_modules/@google/genai/dist/index.mjs.map b/server/node_modules/@google/genai/dist/index.mjs.map new file mode 100644 index 0000000..18f95b9 --- /dev/null +++ b/server/node_modules/@google/genai/dist/index.mjs.map @@ -0,0 +1 @@ +{"version":3,"file":"index.mjs","sources":["../src/_base_url.ts","../src/_common.ts","../src/_base_transformers.ts","../src/converters/_operations_converters.ts","../src/types.ts","../src/_transformers.ts","../src/converters/_batches_converters.ts","../src/pagers.ts","../src/batches.ts","../src/converters/_caches_converters.ts","../src/caches.ts","../src/chats.ts","../src/converters/_filesearchstores_converters.ts","../src/errors.ts","../src/_api_client.ts","../src/cross/_cross_error.ts","../src/cross/_cross_downloader.ts","../src/cross/_cross_uploader.ts","../src/cross/_cross_websocket.ts","../src/converters/_files_converters.ts","../src/files.ts","../src/converters/_documents_converters.ts","../src/documents.ts","../src/filesearchstores.ts","../src/interactions/internal/utils/uuid.ts","../src/interactions/internal/errors.ts","../src/interactions/core/error.ts","../src/interactions/internal/utils/values.ts","../src/interactions/internal/utils/sleep.ts","../src/interactions/version.ts","../src/interactions/internal/detect-platform.ts","../src/interactions/internal/shims.ts","../src/interactions/internal/request-options.ts","../src/interactions/internal/uploads.ts","../src/interactions/internal/to-file.ts","../src/interactions/core/resource.ts","../src/interactions/internal/utils/path.ts","../src/interactions/resources/interactions.ts","../src/interactions/internal/utils/bytes.ts","../src/interactions/internal/decoders/line.ts","../src/interactions/internal/utils/log.ts","../src/interactions/core/streaming.ts","../src/interactions/internal/parse.ts","../src/interactions/core/api-promise.ts","../src/interactions/internal/headers.ts","../src/interactions/internal/utils/env.ts","../src/interactions/client.ts","../src/converters/_live_converters.ts","../src/converters/_models_converters.ts","../src/mcp/_mcp.ts","../src/music.ts","../src/live.ts","../src/_afc.ts","../src/models.ts","../src/operations.ts","../src/converters/_tokens_converters.ts","../src/tokens.ts","../src/converters/_tunings_converters.ts","../src/tunings.ts","../src/web/_web_auth.ts","../src/client.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {HttpOptions} from './types.js';\n\nlet _defaultBaseGeminiUrl: string | undefined = undefined;\nlet _defaultBaseVertexUrl: string | undefined = undefined;\n\n/**\n * Parameters for setting the base URLs for the Gemini API and Vertex AI API.\n */\nexport interface BaseUrlParameters {\n geminiUrl?: string;\n vertexUrl?: string;\n}\n\n/**\n * Overrides the base URLs for the Gemini API and Vertex AI API.\n *\n * @remarks This function should be called before initializing the SDK. If the\n * base URLs are set after initializing the SDK, the base URLs will not be\n * updated. Base URLs provided in the HttpOptions will also take precedence over\n * URLs set here.\n *\n * @example\n * ```ts\n * import {GoogleGenAI, setDefaultBaseUrls} from '@google/genai';\n * // Override the base URL for the Gemini API.\n * setDefaultBaseUrls({geminiUrl:'https://gemini.google.com'});\n *\n * // Override the base URL for the Vertex AI API.\n * setDefaultBaseUrls({vertexUrl: 'https://vertexai.googleapis.com'});\n *\n * const ai = new GoogleGenAI({apiKey: 'GEMINI_API_KEY'});\n * ```\n */\nexport function setDefaultBaseUrls(baseUrlParams: BaseUrlParameters) {\n _defaultBaseGeminiUrl = baseUrlParams.geminiUrl;\n _defaultBaseVertexUrl = baseUrlParams.vertexUrl;\n}\n\n/**\n * Returns the default base URLs for the Gemini API and Vertex AI API.\n */\nexport function getDefaultBaseUrls(): BaseUrlParameters {\n return {\n geminiUrl: _defaultBaseGeminiUrl,\n vertexUrl: _defaultBaseVertexUrl,\n };\n}\n\n/**\n * Returns the default base URL based on the following priority:\n * 1. Base URLs set via HttpOptions.\n * 2. Base URLs set via the latest call to setDefaultBaseUrls.\n * 3. Base URLs set via environment variables.\n */\nexport function getBaseUrl(\n httpOptions: HttpOptions | undefined,\n vertexai: boolean | undefined,\n vertexBaseUrlFromEnv: string | undefined,\n geminiBaseUrlFromEnv: string | undefined,\n): string | undefined {\n if (!httpOptions?.baseUrl) {\n const defaultBaseUrls = getDefaultBaseUrls();\n if (vertexai) {\n return defaultBaseUrls.vertexUrl ?? vertexBaseUrlFromEnv;\n } else {\n return defaultBaseUrls.geminiUrl ?? geminiBaseUrlFromEnv;\n }\n }\n\n return httpOptions.baseUrl;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nexport class BaseModule {}\n\nexport function formatMap(\n templateString: string,\n valueMap: Record<string, unknown>,\n): string {\n // Use a regular expression to find all placeholders in the template string\n const regex = /\\{([^}]+)\\}/g;\n\n // Replace each placeholder with its corresponding value from the valueMap\n return templateString.replace(regex, (match, key) => {\n if (Object.prototype.hasOwnProperty.call(valueMap, key)) {\n const value = valueMap[key];\n // Convert the value to a string if it's not a string already\n return value !== undefined && value !== null ? String(value) : '';\n } else {\n // Handle missing keys\n throw new Error(`Key '${key}' not found in valueMap.`);\n }\n });\n}\n\nexport function setValueByPath(\n data: Record<string, unknown>,\n keys: string[],\n value: unknown,\n): void {\n for (let i = 0; i < keys.length - 1; i++) {\n const key = keys[i];\n\n if (key.endsWith('[]')) {\n const keyName = key.slice(0, -2);\n if (!(keyName in data)) {\n if (Array.isArray(value)) {\n data[keyName] = Array.from({length: value.length}, () => ({}));\n } else {\n throw new Error(`Value must be a list given an array path ${key}`);\n }\n }\n\n if (Array.isArray(data[keyName])) {\n const arrayData = data[keyName] as Array<unknown>;\n\n if (Array.isArray(value)) {\n for (let j = 0; j < arrayData.length; j++) {\n const entry = arrayData[j] as Record<string, unknown>;\n setValueByPath(entry, keys.slice(i + 1), value[j]);\n }\n } else {\n for (const d of arrayData) {\n setValueByPath(\n d as Record<string, unknown>,\n keys.slice(i + 1),\n value,\n );\n }\n }\n }\n return;\n } else if (key.endsWith('[0]')) {\n const keyName = key.slice(0, -3);\n if (!(keyName in data)) {\n data[keyName] = [{}];\n }\n const arrayData = (data as Record<string, unknown>)[keyName];\n setValueByPath(\n (arrayData as Array<Record<string, unknown>>)[0],\n keys.slice(i + 1),\n value,\n );\n return;\n }\n\n if (!data[key] || typeof data[key] !== 'object') {\n data[key] = {};\n }\n\n data = data[key] as Record<string, unknown>;\n }\n\n const keyToSet = keys[keys.length - 1];\n const existingData = data[keyToSet];\n\n if (existingData !== undefined) {\n if (\n !value ||\n (typeof value === 'object' && Object.keys(value).length === 0)\n ) {\n return;\n }\n\n if (value === existingData) {\n return;\n }\n\n if (\n typeof existingData === 'object' &&\n typeof value === 'object' &&\n existingData !== null &&\n value !== null\n ) {\n Object.assign(existingData, value);\n } else {\n throw new Error(`Cannot set value for an existing key. Key: ${keyToSet}`);\n }\n } else {\n if (\n keyToSet === '_self' &&\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(value)\n ) {\n const valueAsRecord = value as Record<string, unknown>;\n\n Object.assign(data, valueAsRecord);\n } else {\n data[keyToSet] = value;\n }\n }\n}\n\nexport function getValueByPath(\n data: unknown,\n keys: string[],\n defaultValue: unknown = undefined,\n): unknown {\n try {\n if (keys.length === 1 && keys[0] === '_self') {\n return data;\n }\n\n for (let i = 0; i < keys.length; i++) {\n if (typeof data !== 'object' || data === null) {\n return defaultValue;\n }\n\n const key = keys[i];\n if (key.endsWith('[]')) {\n const keyName = key.slice(0, -2);\n if (keyName in data) {\n const arrayData = (data as Record<string, unknown>)[keyName];\n if (!Array.isArray(arrayData)) {\n return defaultValue;\n }\n return arrayData.map((d) =>\n getValueByPath(d, keys.slice(i + 1), defaultValue),\n );\n } else {\n return defaultValue;\n }\n } else {\n data = (data as Record<string, unknown>)[key];\n }\n }\n\n return data;\n } catch (error) {\n if (error instanceof TypeError) {\n return defaultValue;\n }\n throw error;\n }\n}\n\n/**\n * Moves values from source paths to destination paths.\n *\n * Examples:\n * moveValueByPath(\n * {'requests': [{'content': v1}, {'content': v2}]},\n * {'requests[].*': 'requests[].request.*'}\n * )\n * -> {'requests': [{'request': {'content': v1}}, {'request': {'content': v2}}]}\n */\nexport function moveValueByPath(\n data: unknown,\n paths: Record<string, string>,\n): void {\n for (const [sourcePath, destPath] of Object.entries(paths)) {\n const sourceKeys = sourcePath.split('.');\n const destKeys = destPath.split('.');\n\n // Determine keys to exclude from wildcard to avoid cyclic references\n const excludeKeys = new Set<string>();\n let wildcardIdx = -1;\n for (let i = 0; i < sourceKeys.length; i++) {\n if (sourceKeys[i] === '*') {\n wildcardIdx = i;\n break;\n }\n }\n\n if (wildcardIdx !== -1 && destKeys.length > wildcardIdx) {\n // Extract the intermediate key between source and dest paths\n // Example: source=['requests[]', '*'], dest=['requests[]', 'request', '*']\n // We want to exclude 'request'\n for (let i = wildcardIdx; i < destKeys.length; i++) {\n const key = destKeys[i];\n if (key !== '*' && !key.endsWith('[]') && !key.endsWith('[0]')) {\n excludeKeys.add(key);\n }\n }\n }\n\n _moveValueRecursive(data, sourceKeys, destKeys, 0, excludeKeys);\n }\n}\n\n/**\n * Recursively moves values from source path to destination path.\n */\nfunction _moveValueRecursive(\n data: unknown,\n sourceKeys: string[],\n destKeys: string[],\n keyIdx: number,\n excludeKeys: Set<string>,\n): void {\n if (keyIdx >= sourceKeys.length) {\n return;\n }\n\n if (typeof data !== 'object' || data === null) {\n return;\n }\n\n const key = sourceKeys[keyIdx];\n\n if (key.endsWith('[]')) {\n const keyName = key.slice(0, -2);\n const dataRecord = data as Record<string, unknown>;\n if (keyName in dataRecord && Array.isArray(dataRecord[keyName])) {\n for (const item of dataRecord[keyName] as Array<unknown>) {\n _moveValueRecursive(\n item,\n sourceKeys,\n destKeys,\n keyIdx + 1,\n excludeKeys,\n );\n }\n }\n } else if (key === '*') {\n // wildcard - move all fields\n if (typeof data === 'object' && data !== null && !Array.isArray(data)) {\n const dataRecord = data as Record<string, unknown>;\n const keysToMove = Object.keys(dataRecord).filter(\n (k) => !k.startsWith('_') && !excludeKeys.has(k),\n );\n\n const valuesToMove: Record<string, unknown> = {};\n for (const k of keysToMove) {\n valuesToMove[k] = dataRecord[k];\n }\n\n // Set values at destination\n for (const [k, v] of Object.entries(valuesToMove)) {\n const newDestKeys: string[] = [];\n for (const dk of destKeys.slice(keyIdx)) {\n if (dk === '*') {\n newDestKeys.push(k);\n } else {\n newDestKeys.push(dk);\n }\n }\n setValueByPath(dataRecord, newDestKeys, v);\n }\n\n for (const k of keysToMove) {\n delete dataRecord[k];\n }\n }\n } else {\n // Navigate to next level\n const dataRecord = data as Record<string, unknown>;\n if (key in dataRecord) {\n _moveValueRecursive(\n dataRecord[key],\n sourceKeys,\n destKeys,\n keyIdx + 1,\n excludeKeys,\n );\n }\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nexport function tBytes(fromBytes: string | unknown): string {\n if (typeof fromBytes !== 'string') {\n throw new Error('fromImageBytes must be a string');\n }\n // TODO(b/389133914): Remove dummy bytes converter.\n return fromBytes;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport * as t from '../_base_transformers.js';\nimport * as common from '../_common.js';\nimport type * as types from '../types.js';\n\nexport function fetchPredictOperationParametersToMldev(\n fromObject: types.FetchPredictOperationParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['operationName']) !== undefined) {\n throw new Error('operationName parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['resourceName']) !== undefined) {\n throw new Error('resourceName parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['config']) !== undefined) {\n throw new Error('config parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function fetchPredictOperationParametersToVertex(\n fromObject: types.FetchPredictOperationParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromOperationName = common.getValueByPath(fromObject, [\n 'operationName',\n ]);\n if (fromOperationName != null) {\n common.setValueByPath(toObject, ['operationName'], fromOperationName);\n }\n\n const fromResourceName = common.getValueByPath(fromObject, ['resourceName']);\n if (fromResourceName != null) {\n common.setValueByPath(toObject, ['_url', 'resourceName'], fromResourceName);\n }\n\n return toObject;\n}\n\nexport function generateVideosOperationFromMldev(\n fromObject: types.GenerateVideosOperation,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromMetadata = common.getValueByPath(fromObject, ['metadata']);\n if (fromMetadata != null) {\n common.setValueByPath(toObject, ['metadata'], fromMetadata);\n }\n\n const fromDone = common.getValueByPath(fromObject, ['done']);\n if (fromDone != null) {\n common.setValueByPath(toObject, ['done'], fromDone);\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n const fromResponse = common.getValueByPath(fromObject, [\n 'response',\n 'generateVideoResponse',\n ]);\n if (fromResponse != null) {\n common.setValueByPath(\n toObject,\n ['response'],\n generateVideosResponseFromMldev(fromResponse),\n );\n }\n\n return toObject;\n}\n\nexport function generateVideosOperationFromVertex(\n fromObject: types.GenerateVideosOperation,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromMetadata = common.getValueByPath(fromObject, ['metadata']);\n if (fromMetadata != null) {\n common.setValueByPath(toObject, ['metadata'], fromMetadata);\n }\n\n const fromDone = common.getValueByPath(fromObject, ['done']);\n if (fromDone != null) {\n common.setValueByPath(toObject, ['done'], fromDone);\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n const fromResponse = common.getValueByPath(fromObject, ['response']);\n if (fromResponse != null) {\n common.setValueByPath(\n toObject,\n ['response'],\n generateVideosResponseFromVertex(fromResponse),\n );\n }\n\n return toObject;\n}\n\nexport function generateVideosResponseFromMldev(\n fromObject: types.GenerateVideosResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromGeneratedVideos = common.getValueByPath(fromObject, [\n 'generatedSamples',\n ]);\n if (fromGeneratedVideos != null) {\n let transformedList = fromGeneratedVideos;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return generatedVideoFromMldev(item);\n });\n }\n common.setValueByPath(toObject, ['generatedVideos'], transformedList);\n }\n\n const fromRaiMediaFilteredCount = common.getValueByPath(fromObject, [\n 'raiMediaFilteredCount',\n ]);\n if (fromRaiMediaFilteredCount != null) {\n common.setValueByPath(\n toObject,\n ['raiMediaFilteredCount'],\n fromRaiMediaFilteredCount,\n );\n }\n\n const fromRaiMediaFilteredReasons = common.getValueByPath(fromObject, [\n 'raiMediaFilteredReasons',\n ]);\n if (fromRaiMediaFilteredReasons != null) {\n common.setValueByPath(\n toObject,\n ['raiMediaFilteredReasons'],\n fromRaiMediaFilteredReasons,\n );\n }\n\n return toObject;\n}\n\nexport function generateVideosResponseFromVertex(\n fromObject: types.GenerateVideosResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromGeneratedVideos = common.getValueByPath(fromObject, ['videos']);\n if (fromGeneratedVideos != null) {\n let transformedList = fromGeneratedVideos;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return generatedVideoFromVertex(item);\n });\n }\n common.setValueByPath(toObject, ['generatedVideos'], transformedList);\n }\n\n const fromRaiMediaFilteredCount = common.getValueByPath(fromObject, [\n 'raiMediaFilteredCount',\n ]);\n if (fromRaiMediaFilteredCount != null) {\n common.setValueByPath(\n toObject,\n ['raiMediaFilteredCount'],\n fromRaiMediaFilteredCount,\n );\n }\n\n const fromRaiMediaFilteredReasons = common.getValueByPath(fromObject, [\n 'raiMediaFilteredReasons',\n ]);\n if (fromRaiMediaFilteredReasons != null) {\n common.setValueByPath(\n toObject,\n ['raiMediaFilteredReasons'],\n fromRaiMediaFilteredReasons,\n );\n }\n\n return toObject;\n}\n\nexport function generatedVideoFromMldev(\n fromObject: types.GeneratedVideo,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromVideo = common.getValueByPath(fromObject, ['video']);\n if (fromVideo != null) {\n common.setValueByPath(toObject, ['video'], videoFromMldev(fromVideo));\n }\n\n return toObject;\n}\n\nexport function generatedVideoFromVertex(\n fromObject: types.GeneratedVideo,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromVideo = common.getValueByPath(fromObject, ['_self']);\n if (fromVideo != null) {\n common.setValueByPath(toObject, ['video'], videoFromVertex(fromVideo));\n }\n\n return toObject;\n}\n\nexport function getOperationParametersToMldev(\n fromObject: types.GetOperationParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromOperationName = common.getValueByPath(fromObject, [\n 'operationName',\n ]);\n if (fromOperationName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'operationName'],\n fromOperationName,\n );\n }\n\n return toObject;\n}\n\nexport function getOperationParametersToVertex(\n fromObject: types.GetOperationParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromOperationName = common.getValueByPath(fromObject, [\n 'operationName',\n ]);\n if (fromOperationName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'operationName'],\n fromOperationName,\n );\n }\n\n return toObject;\n}\n\nexport function importFileOperationFromMldev(\n fromObject: types.ImportFileOperation,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromMetadata = common.getValueByPath(fromObject, ['metadata']);\n if (fromMetadata != null) {\n common.setValueByPath(toObject, ['metadata'], fromMetadata);\n }\n\n const fromDone = common.getValueByPath(fromObject, ['done']);\n if (fromDone != null) {\n common.setValueByPath(toObject, ['done'], fromDone);\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n const fromResponse = common.getValueByPath(fromObject, ['response']);\n if (fromResponse != null) {\n common.setValueByPath(\n toObject,\n ['response'],\n importFileResponseFromMldev(fromResponse),\n );\n }\n\n return toObject;\n}\n\nexport function importFileResponseFromMldev(\n fromObject: types.ImportFileResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromParent = common.getValueByPath(fromObject, ['parent']);\n if (fromParent != null) {\n common.setValueByPath(toObject, ['parent'], fromParent);\n }\n\n const fromDocumentName = common.getValueByPath(fromObject, ['documentName']);\n if (fromDocumentName != null) {\n common.setValueByPath(toObject, ['documentName'], fromDocumentName);\n }\n\n return toObject;\n}\n\nexport function uploadToFileSearchStoreOperationFromMldev(\n fromObject: types.UploadToFileSearchStoreOperation,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromMetadata = common.getValueByPath(fromObject, ['metadata']);\n if (fromMetadata != null) {\n common.setValueByPath(toObject, ['metadata'], fromMetadata);\n }\n\n const fromDone = common.getValueByPath(fromObject, ['done']);\n if (fromDone != null) {\n common.setValueByPath(toObject, ['done'], fromDone);\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n const fromResponse = common.getValueByPath(fromObject, ['response']);\n if (fromResponse != null) {\n common.setValueByPath(\n toObject,\n ['response'],\n uploadToFileSearchStoreResponseFromMldev(fromResponse),\n );\n }\n\n return toObject;\n}\n\nexport function uploadToFileSearchStoreResponseFromMldev(\n fromObject: types.UploadToFileSearchStoreResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromParent = common.getValueByPath(fromObject, ['parent']);\n if (fromParent != null) {\n common.setValueByPath(toObject, ['parent'], fromParent);\n }\n\n const fromDocumentName = common.getValueByPath(fromObject, ['documentName']);\n if (fromDocumentName != null) {\n common.setValueByPath(toObject, ['documentName'], fromDocumentName);\n }\n\n return toObject;\n}\n\nexport function videoFromMldev(\n fromObject: types.Video,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromUri = common.getValueByPath(fromObject, ['uri']);\n if (fromUri != null) {\n common.setValueByPath(toObject, ['uri'], fromUri);\n }\n\n const fromVideoBytes = common.getValueByPath(fromObject, ['encodedVideo']);\n if (fromVideoBytes != null) {\n common.setValueByPath(toObject, ['videoBytes'], t.tBytes(fromVideoBytes));\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['encoding']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function videoFromVertex(\n fromObject: types.Video,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromUri = common.getValueByPath(fromObject, ['gcsUri']);\n if (fromUri != null) {\n common.setValueByPath(toObject, ['uri'], fromUri);\n }\n\n const fromVideoBytes = common.getValueByPath(fromObject, [\n 'bytesBase64Encoded',\n ]);\n if (fromVideoBytes != null) {\n common.setValueByPath(toObject, ['videoBytes'], t.tBytes(fromVideoBytes));\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport type {ReferenceImageAPIInternal} from './_internal_types.js';\nimport {\n generateVideosOperationFromMldev,\n generateVideosOperationFromVertex,\n importFileOperationFromMldev,\n uploadToFileSearchStoreOperationFromMldev,\n} from './converters/_operations_converters.js';\n\n/** Outcome of the code execution. */\nexport enum Outcome {\n /**\n * Unspecified status. This value should not be used.\n */\n OUTCOME_UNSPECIFIED = 'OUTCOME_UNSPECIFIED',\n /**\n * Code execution completed successfully.\n */\n OUTCOME_OK = 'OUTCOME_OK',\n /**\n * Code execution finished but with a failure. `stderr` should contain the reason.\n */\n OUTCOME_FAILED = 'OUTCOME_FAILED',\n /**\n * Code execution ran for too long, and was cancelled. There may or may not be a partial output present.\n */\n OUTCOME_DEADLINE_EXCEEDED = 'OUTCOME_DEADLINE_EXCEEDED',\n}\n\n/** Programming language of the `code`. */\nexport enum Language {\n /**\n * Unspecified language. This value should not be used.\n */\n LANGUAGE_UNSPECIFIED = 'LANGUAGE_UNSPECIFIED',\n /**\n * Python >= 3.10, with numpy and simpy available.\n */\n PYTHON = 'PYTHON',\n}\n\n/** Specifies how the response should be scheduled in the conversation. */\nexport enum FunctionResponseScheduling {\n /**\n * This value is unused.\n */\n SCHEDULING_UNSPECIFIED = 'SCHEDULING_UNSPECIFIED',\n /**\n * Only add the result to the conversation context, do not interrupt or trigger generation.\n */\n SILENT = 'SILENT',\n /**\n * Add the result to the conversation context, and prompt to generate output without interrupting ongoing generation.\n */\n WHEN_IDLE = 'WHEN_IDLE',\n /**\n * Add the result to the conversation context, interrupt ongoing generation and prompt to generate output.\n */\n INTERRUPT = 'INTERRUPT',\n}\n\n/** The type of the data. */\nexport enum Type {\n /**\n * Not specified, should not be used.\n */\n TYPE_UNSPECIFIED = 'TYPE_UNSPECIFIED',\n /**\n * OpenAPI string type\n */\n STRING = 'STRING',\n /**\n * OpenAPI number type\n */\n NUMBER = 'NUMBER',\n /**\n * OpenAPI integer type\n */\n INTEGER = 'INTEGER',\n /**\n * OpenAPI boolean type\n */\n BOOLEAN = 'BOOLEAN',\n /**\n * OpenAPI array type\n */\n ARRAY = 'ARRAY',\n /**\n * OpenAPI object type\n */\n OBJECT = 'OBJECT',\n /**\n * Null type\n */\n NULL = 'NULL',\n}\n\n/** The API spec that the external API implements. This enum is not supported in Gemini API. */\nexport enum ApiSpec {\n /**\n * Unspecified API spec. This value should not be used.\n */\n API_SPEC_UNSPECIFIED = 'API_SPEC_UNSPECIFIED',\n /**\n * Simple search API spec.\n */\n SIMPLE_SEARCH = 'SIMPLE_SEARCH',\n /**\n * Elastic search API spec.\n */\n ELASTIC_SEARCH = 'ELASTIC_SEARCH',\n}\n\n/** Type of auth scheme. This enum is not supported in Gemini API. */\nexport enum AuthType {\n AUTH_TYPE_UNSPECIFIED = 'AUTH_TYPE_UNSPECIFIED',\n /**\n * No Auth.\n */\n NO_AUTH = 'NO_AUTH',\n /**\n * API Key Auth.\n */\n API_KEY_AUTH = 'API_KEY_AUTH',\n /**\n * HTTP Basic Auth.\n */\n HTTP_BASIC_AUTH = 'HTTP_BASIC_AUTH',\n /**\n * Google Service Account Auth.\n */\n GOOGLE_SERVICE_ACCOUNT_AUTH = 'GOOGLE_SERVICE_ACCOUNT_AUTH',\n /**\n * OAuth auth.\n */\n OAUTH = 'OAUTH',\n /**\n * OpenID Connect (OIDC) Auth.\n */\n OIDC_AUTH = 'OIDC_AUTH',\n}\n\n/** The location of the API key. This enum is not supported in Gemini API. */\nexport enum HttpElementLocation {\n HTTP_IN_UNSPECIFIED = 'HTTP_IN_UNSPECIFIED',\n /**\n * Element is in the HTTP request query.\n */\n HTTP_IN_QUERY = 'HTTP_IN_QUERY',\n /**\n * Element is in the HTTP request header.\n */\n HTTP_IN_HEADER = 'HTTP_IN_HEADER',\n /**\n * Element is in the HTTP request path.\n */\n HTTP_IN_PATH = 'HTTP_IN_PATH',\n /**\n * Element is in the HTTP request body.\n */\n HTTP_IN_BODY = 'HTTP_IN_BODY',\n /**\n * Element is in the HTTP request cookie.\n */\n HTTP_IN_COOKIE = 'HTTP_IN_COOKIE',\n}\n\n/** Sites with confidence level chosen & above this value will be blocked from the search results. This enum is not supported in Gemini API. */\nexport enum PhishBlockThreshold {\n /**\n * Defaults to unspecified.\n */\n PHISH_BLOCK_THRESHOLD_UNSPECIFIED = 'PHISH_BLOCK_THRESHOLD_UNSPECIFIED',\n /**\n * Blocks Low and above confidence URL that is risky.\n */\n BLOCK_LOW_AND_ABOVE = 'BLOCK_LOW_AND_ABOVE',\n /**\n * Blocks Medium and above confidence URL that is risky.\n */\n BLOCK_MEDIUM_AND_ABOVE = 'BLOCK_MEDIUM_AND_ABOVE',\n /**\n * Blocks High and above confidence URL that is risky.\n */\n BLOCK_HIGH_AND_ABOVE = 'BLOCK_HIGH_AND_ABOVE',\n /**\n * Blocks Higher and above confidence URL that is risky.\n */\n BLOCK_HIGHER_AND_ABOVE = 'BLOCK_HIGHER_AND_ABOVE',\n /**\n * Blocks Very high and above confidence URL that is risky.\n */\n BLOCK_VERY_HIGH_AND_ABOVE = 'BLOCK_VERY_HIGH_AND_ABOVE',\n /**\n * Blocks Extremely high confidence URL that is risky.\n */\n BLOCK_ONLY_EXTREMELY_HIGH = 'BLOCK_ONLY_EXTREMELY_HIGH',\n}\n\n/** Specifies the function Behavior. Currently only supported by the BidiGenerateContent method. This enum is not supported in Vertex AI. */\nexport enum Behavior {\n /**\n * This value is unused.\n */\n UNSPECIFIED = 'UNSPECIFIED',\n /**\n * If set, the system will wait to receive the function response before continuing the conversation.\n */\n BLOCKING = 'BLOCKING',\n /**\n * If set, the system will not wait to receive the function response. Instead, it will attempt to handle function responses as they become available while maintaining the conversation between the user and the model.\n */\n NON_BLOCKING = 'NON_BLOCKING',\n}\n\n/** The mode of the predictor to be used in dynamic retrieval. */\nexport enum DynamicRetrievalConfigMode {\n /**\n * Always trigger retrieval.\n */\n MODE_UNSPECIFIED = 'MODE_UNSPECIFIED',\n /**\n * Run retrieval only when system decides it is necessary.\n */\n MODE_DYNAMIC = 'MODE_DYNAMIC',\n}\n\n/** Function calling mode. */\nexport enum FunctionCallingConfigMode {\n /**\n * Unspecified function calling mode. This value should not be used.\n */\n MODE_UNSPECIFIED = 'MODE_UNSPECIFIED',\n /**\n * Default model behavior, model decides to predict either function calls or natural language response.\n */\n AUTO = 'AUTO',\n /**\n * Model is constrained to always predicting function calls only. If \"allowed_function_names\" are set, the predicted function calls will be limited to any one of \"allowed_function_names\", else the predicted function calls will be any one of the provided \"function_declarations\".\n */\n ANY = 'ANY',\n /**\n * Model will not predict any function calls. Model behavior is same as when not passing any function declarations.\n */\n NONE = 'NONE',\n /**\n * Model is constrained to predict either function calls or natural language response. If \"allowed_function_names\" are set, the predicted function calls will be limited to any one of \"allowed_function_names\", else the predicted function calls will be any one of the provided \"function_declarations\".\n */\n VALIDATED = 'VALIDATED',\n}\n\n/** The number of thoughts tokens that the model should generate. */\nexport enum ThinkingLevel {\n /**\n * Unspecified thinking level.\n */\n THINKING_LEVEL_UNSPECIFIED = 'THINKING_LEVEL_UNSPECIFIED',\n /**\n * Low thinking level.\n */\n LOW = 'LOW',\n /**\n * Medium thinking level.\n */\n MEDIUM = 'MEDIUM',\n /**\n * High thinking level.\n */\n HIGH = 'HIGH',\n /**\n * MINIMAL thinking level.\n */\n MINIMAL = 'MINIMAL',\n}\n\n/** Harm category. */\nexport enum HarmCategory {\n /**\n * The harm category is unspecified.\n */\n HARM_CATEGORY_UNSPECIFIED = 'HARM_CATEGORY_UNSPECIFIED',\n /**\n * The harm category is harassment.\n */\n HARM_CATEGORY_HARASSMENT = 'HARM_CATEGORY_HARASSMENT',\n /**\n * The harm category is hate speech.\n */\n HARM_CATEGORY_HATE_SPEECH = 'HARM_CATEGORY_HATE_SPEECH',\n /**\n * The harm category is sexually explicit content.\n */\n HARM_CATEGORY_SEXUALLY_EXPLICIT = 'HARM_CATEGORY_SEXUALLY_EXPLICIT',\n /**\n * The harm category is dangerous content.\n */\n HARM_CATEGORY_DANGEROUS_CONTENT = 'HARM_CATEGORY_DANGEROUS_CONTENT',\n /**\n * Deprecated: Election filter is not longer supported. The harm category is civic integrity.\n */\n HARM_CATEGORY_CIVIC_INTEGRITY = 'HARM_CATEGORY_CIVIC_INTEGRITY',\n /**\n * The harm category is image hate. This enum value is not supported in Gemini API.\n */\n HARM_CATEGORY_IMAGE_HATE = 'HARM_CATEGORY_IMAGE_HATE',\n /**\n * The harm category is image dangerous content. This enum value is not supported in Gemini API.\n */\n HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT = 'HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT',\n /**\n * The harm category is image harassment. This enum value is not supported in Gemini API.\n */\n HARM_CATEGORY_IMAGE_HARASSMENT = 'HARM_CATEGORY_IMAGE_HARASSMENT',\n /**\n * The harm category is image sexually explicit content. This enum value is not supported in Gemini API.\n */\n HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT = 'HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT',\n /**\n * The harm category is for jailbreak prompts. This enum value is not supported in Gemini API.\n */\n HARM_CATEGORY_JAILBREAK = 'HARM_CATEGORY_JAILBREAK',\n}\n\n/** Specify if the threshold is used for probability or severity score. If not specified, the threshold is used for probability score. This enum is not supported in Gemini API. */\nexport enum HarmBlockMethod {\n /**\n * The harm block method is unspecified.\n */\n HARM_BLOCK_METHOD_UNSPECIFIED = 'HARM_BLOCK_METHOD_UNSPECIFIED',\n /**\n * The harm block method uses both probability and severity scores.\n */\n SEVERITY = 'SEVERITY',\n /**\n * The harm block method uses the probability score.\n */\n PROBABILITY = 'PROBABILITY',\n}\n\n/** The harm block threshold. */\nexport enum HarmBlockThreshold {\n /**\n * Unspecified harm block threshold.\n */\n HARM_BLOCK_THRESHOLD_UNSPECIFIED = 'HARM_BLOCK_THRESHOLD_UNSPECIFIED',\n /**\n * Block low threshold and above (i.e. block more).\n */\n BLOCK_LOW_AND_ABOVE = 'BLOCK_LOW_AND_ABOVE',\n /**\n * Block medium threshold and above.\n */\n BLOCK_MEDIUM_AND_ABOVE = 'BLOCK_MEDIUM_AND_ABOVE',\n /**\n * Block only high threshold (i.e. block less).\n */\n BLOCK_ONLY_HIGH = 'BLOCK_ONLY_HIGH',\n /**\n * Block none.\n */\n BLOCK_NONE = 'BLOCK_NONE',\n /**\n * Turn off the safety filter.\n */\n OFF = 'OFF',\n}\n\n/** Output only. The reason why the model stopped generating tokens.\n\nIf empty, the model has not stopped generating the tokens. */\nexport enum FinishReason {\n /**\n * The finish reason is unspecified.\n */\n FINISH_REASON_UNSPECIFIED = 'FINISH_REASON_UNSPECIFIED',\n /**\n * Token generation reached a natural stopping point or a configured stop sequence.\n */\n STOP = 'STOP',\n /**\n * Token generation reached the configured maximum output tokens.\n */\n MAX_TOKENS = 'MAX_TOKENS',\n /**\n * Token generation stopped because the content potentially contains safety violations. NOTE: When streaming, [content][] is empty if content filters blocks the output.\n */\n SAFETY = 'SAFETY',\n /**\n * The token generation stopped because of potential recitation.\n */\n RECITATION = 'RECITATION',\n /**\n * The token generation stopped because of using an unsupported language.\n */\n LANGUAGE = 'LANGUAGE',\n /**\n * All other reasons that stopped the token generation.\n */\n OTHER = 'OTHER',\n /**\n * Token generation stopped because the content contains forbidden terms.\n */\n BLOCKLIST = 'BLOCKLIST',\n /**\n * Token generation stopped for potentially containing prohibited content.\n */\n PROHIBITED_CONTENT = 'PROHIBITED_CONTENT',\n /**\n * Token generation stopped because the content potentially contains Sensitive Personally Identifiable Information (SPII).\n */\n SPII = 'SPII',\n /**\n * The function call generated by the model is invalid.\n */\n MALFORMED_FUNCTION_CALL = 'MALFORMED_FUNCTION_CALL',\n /**\n * Token generation stopped because generated images have safety violations.\n */\n IMAGE_SAFETY = 'IMAGE_SAFETY',\n /**\n * The tool call generated by the model is invalid.\n */\n UNEXPECTED_TOOL_CALL = 'UNEXPECTED_TOOL_CALL',\n /**\n * Image generation stopped because the generated images have prohibited content.\n */\n IMAGE_PROHIBITED_CONTENT = 'IMAGE_PROHIBITED_CONTENT',\n /**\n * The model was expected to generate an image, but none was generated.\n */\n NO_IMAGE = 'NO_IMAGE',\n /**\n * Image generation stopped because the generated image may be a recitation from a source.\n */\n IMAGE_RECITATION = 'IMAGE_RECITATION',\n /**\n * Image generation stopped for a reason not otherwise specified.\n */\n IMAGE_OTHER = 'IMAGE_OTHER',\n}\n\n/** Output only. Harm probability levels in the content. */\nexport enum HarmProbability {\n /**\n * Harm probability unspecified.\n */\n HARM_PROBABILITY_UNSPECIFIED = 'HARM_PROBABILITY_UNSPECIFIED',\n /**\n * Negligible level of harm.\n */\n NEGLIGIBLE = 'NEGLIGIBLE',\n /**\n * Low level of harm.\n */\n LOW = 'LOW',\n /**\n * Medium level of harm.\n */\n MEDIUM = 'MEDIUM',\n /**\n * High level of harm.\n */\n HIGH = 'HIGH',\n}\n\n/** Output only. Harm severity levels in the content. This enum is not supported in Gemini API. */\nexport enum HarmSeverity {\n /**\n * Harm severity unspecified.\n */\n HARM_SEVERITY_UNSPECIFIED = 'HARM_SEVERITY_UNSPECIFIED',\n /**\n * Negligible level of harm severity.\n */\n HARM_SEVERITY_NEGLIGIBLE = 'HARM_SEVERITY_NEGLIGIBLE',\n /**\n * Low level of harm severity.\n */\n HARM_SEVERITY_LOW = 'HARM_SEVERITY_LOW',\n /**\n * Medium level of harm severity.\n */\n HARM_SEVERITY_MEDIUM = 'HARM_SEVERITY_MEDIUM',\n /**\n * High level of harm severity.\n */\n HARM_SEVERITY_HIGH = 'HARM_SEVERITY_HIGH',\n}\n\n/** Status of the url retrieval. */\nexport enum UrlRetrievalStatus {\n /**\n * Default value. This value is unused.\n */\n URL_RETRIEVAL_STATUS_UNSPECIFIED = 'URL_RETRIEVAL_STATUS_UNSPECIFIED',\n /**\n * Url retrieval is successful.\n */\n URL_RETRIEVAL_STATUS_SUCCESS = 'URL_RETRIEVAL_STATUS_SUCCESS',\n /**\n * Url retrieval is failed due to error.\n */\n URL_RETRIEVAL_STATUS_ERROR = 'URL_RETRIEVAL_STATUS_ERROR',\n /**\n * Url retrieval is failed because the content is behind paywall. This enum value is not supported in Vertex AI.\n */\n URL_RETRIEVAL_STATUS_PAYWALL = 'URL_RETRIEVAL_STATUS_PAYWALL',\n /**\n * Url retrieval is failed because the content is unsafe. This enum value is not supported in Vertex AI.\n */\n URL_RETRIEVAL_STATUS_UNSAFE = 'URL_RETRIEVAL_STATUS_UNSAFE',\n}\n\n/** Output only. The reason why the prompt was blocked. */\nexport enum BlockedReason {\n /**\n * The blocked reason is unspecified.\n */\n BLOCKED_REASON_UNSPECIFIED = 'BLOCKED_REASON_UNSPECIFIED',\n /**\n * The prompt was blocked for safety reasons.\n */\n SAFETY = 'SAFETY',\n /**\n * The prompt was blocked for other reasons. For example, it may be due to the prompt's language, or because it contains other harmful content.\n */\n OTHER = 'OTHER',\n /**\n * The prompt was blocked because it contains a term from the terminology blocklist.\n */\n BLOCKLIST = 'BLOCKLIST',\n /**\n * The prompt was blocked because it contains prohibited content.\n */\n PROHIBITED_CONTENT = 'PROHIBITED_CONTENT',\n /**\n * The prompt was blocked because it contains content that is unsafe for image generation.\n */\n IMAGE_SAFETY = 'IMAGE_SAFETY',\n /**\n * The prompt was blocked by Model Armor. This enum value is not supported in Gemini API.\n */\n MODEL_ARMOR = 'MODEL_ARMOR',\n /**\n * The prompt was blocked as a jailbreak attempt. This enum value is not supported in Gemini API.\n */\n JAILBREAK = 'JAILBREAK',\n}\n\n/** Output only. The traffic type for this request. This enum is not supported in Gemini API. */\nexport enum TrafficType {\n /**\n * Unspecified request traffic type.\n */\n TRAFFIC_TYPE_UNSPECIFIED = 'TRAFFIC_TYPE_UNSPECIFIED',\n /**\n * The request was processed using Pay-As-You-Go quota.\n */\n ON_DEMAND = 'ON_DEMAND',\n /**\n * Type for Provisioned Throughput traffic.\n */\n PROVISIONED_THROUGHPUT = 'PROVISIONED_THROUGHPUT',\n}\n\n/** Server content modalities. */\nexport enum Modality {\n /**\n * The modality is unspecified.\n */\n MODALITY_UNSPECIFIED = 'MODALITY_UNSPECIFIED',\n /**\n * Indicates the model should return text\n */\n TEXT = 'TEXT',\n /**\n * Indicates the model should return images.\n */\n IMAGE = 'IMAGE',\n /**\n * Indicates the model should return audio.\n */\n AUDIO = 'AUDIO',\n}\n\n/** The media resolution to use. */\nexport enum MediaResolution {\n /**\n * Media resolution has not been set\n */\n MEDIA_RESOLUTION_UNSPECIFIED = 'MEDIA_RESOLUTION_UNSPECIFIED',\n /**\n * Media resolution set to low (64 tokens).\n */\n MEDIA_RESOLUTION_LOW = 'MEDIA_RESOLUTION_LOW',\n /**\n * Media resolution set to medium (256 tokens).\n */\n MEDIA_RESOLUTION_MEDIUM = 'MEDIA_RESOLUTION_MEDIUM',\n /**\n * Media resolution set to high (zoomed reframing with 256 tokens).\n */\n MEDIA_RESOLUTION_HIGH = 'MEDIA_RESOLUTION_HIGH',\n}\n\n/** Tuning mode. This enum is not supported in Gemini API. */\nexport enum TuningMode {\n /**\n * Tuning mode is unspecified.\n */\n TUNING_MODE_UNSPECIFIED = 'TUNING_MODE_UNSPECIFIED',\n /**\n * Full fine-tuning mode.\n */\n TUNING_MODE_FULL = 'TUNING_MODE_FULL',\n /**\n * PEFT adapter tuning mode.\n */\n TUNING_MODE_PEFT_ADAPTER = 'TUNING_MODE_PEFT_ADAPTER',\n}\n\n/** Adapter size for tuning. This enum is not supported in Gemini API. */\nexport enum AdapterSize {\n /**\n * Adapter size is unspecified.\n */\n ADAPTER_SIZE_UNSPECIFIED = 'ADAPTER_SIZE_UNSPECIFIED',\n /**\n * Adapter size 1.\n */\n ADAPTER_SIZE_ONE = 'ADAPTER_SIZE_ONE',\n /**\n * Adapter size 2.\n */\n ADAPTER_SIZE_TWO = 'ADAPTER_SIZE_TWO',\n /**\n * Adapter size 4.\n */\n ADAPTER_SIZE_FOUR = 'ADAPTER_SIZE_FOUR',\n /**\n * Adapter size 8.\n */\n ADAPTER_SIZE_EIGHT = 'ADAPTER_SIZE_EIGHT',\n /**\n * Adapter size 16.\n */\n ADAPTER_SIZE_SIXTEEN = 'ADAPTER_SIZE_SIXTEEN',\n /**\n * Adapter size 32.\n */\n ADAPTER_SIZE_THIRTY_TWO = 'ADAPTER_SIZE_THIRTY_TWO',\n}\n\n/** Job state. */\nexport enum JobState {\n /**\n * The job state is unspecified.\n */\n JOB_STATE_UNSPECIFIED = 'JOB_STATE_UNSPECIFIED',\n /**\n * The job has been just created or resumed and processing has not yet begun.\n */\n JOB_STATE_QUEUED = 'JOB_STATE_QUEUED',\n /**\n * The service is preparing to run the job.\n */\n JOB_STATE_PENDING = 'JOB_STATE_PENDING',\n /**\n * The job is in progress.\n */\n JOB_STATE_RUNNING = 'JOB_STATE_RUNNING',\n /**\n * The job completed successfully.\n */\n JOB_STATE_SUCCEEDED = 'JOB_STATE_SUCCEEDED',\n /**\n * The job failed.\n */\n JOB_STATE_FAILED = 'JOB_STATE_FAILED',\n /**\n * The job is being cancelled. From this state the job may only go to either `JOB_STATE_SUCCEEDED`, `JOB_STATE_FAILED` or `JOB_STATE_CANCELLED`.\n */\n JOB_STATE_CANCELLING = 'JOB_STATE_CANCELLING',\n /**\n * The job has been cancelled.\n */\n JOB_STATE_CANCELLED = 'JOB_STATE_CANCELLED',\n /**\n * The job has been stopped, and can be resumed.\n */\n JOB_STATE_PAUSED = 'JOB_STATE_PAUSED',\n /**\n * The job has expired.\n */\n JOB_STATE_EXPIRED = 'JOB_STATE_EXPIRED',\n /**\n * The job is being updated. Only jobs in the `JOB_STATE_RUNNING` state can be updated. After updating, the job goes back to the `JOB_STATE_RUNNING` state.\n */\n JOB_STATE_UPDATING = 'JOB_STATE_UPDATING',\n /**\n * The job is partially succeeded, some results may be missing due to errors.\n */\n JOB_STATE_PARTIALLY_SUCCEEDED = 'JOB_STATE_PARTIALLY_SUCCEEDED',\n}\n\n/** The tuning task. Either I2V or T2V. This enum is not supported in Gemini API. */\nexport enum TuningTask {\n /**\n * Default value. This value is unused.\n */\n TUNING_TASK_UNSPECIFIED = 'TUNING_TASK_UNSPECIFIED',\n /**\n * Tuning task for image to video.\n */\n TUNING_TASK_I2V = 'TUNING_TASK_I2V',\n /**\n * Tuning task for text to video.\n */\n TUNING_TASK_T2V = 'TUNING_TASK_T2V',\n /**\n * Tuning task for reference to video.\n */\n TUNING_TASK_R2V = 'TUNING_TASK_R2V',\n}\n\n/** The tokenization quality used for given media. */\nexport enum PartMediaResolutionLevel {\n /**\n * Media resolution has not been set.\n */\n MEDIA_RESOLUTION_UNSPECIFIED = 'MEDIA_RESOLUTION_UNSPECIFIED',\n /**\n * Media resolution set to low.\n */\n MEDIA_RESOLUTION_LOW = 'MEDIA_RESOLUTION_LOW',\n /**\n * Media resolution set to medium.\n */\n MEDIA_RESOLUTION_MEDIUM = 'MEDIA_RESOLUTION_MEDIUM',\n /**\n * Media resolution set to high.\n */\n MEDIA_RESOLUTION_HIGH = 'MEDIA_RESOLUTION_HIGH',\n /**\n * Media resolution set to ultra high.\n */\n MEDIA_RESOLUTION_ULTRA_HIGH = 'MEDIA_RESOLUTION_ULTRA_HIGH',\n}\n\n/** Resource scope. */\nexport enum ResourceScope {\n /**\n * When setting base_url, this value configures resource scope to be the collection.\n The resource name will not include api version, project, or location.\n For example, if base_url is set to \"https://aiplatform.googleapis.com\",\n then the resource name for a Model would be\n \"https://aiplatform.googleapis.com/publishers/google/models/gemini-3-pro-preview\n */\n COLLECTION = 'COLLECTION',\n}\n\n/** Options for feature selection preference. */\nexport enum FeatureSelectionPreference {\n FEATURE_SELECTION_PREFERENCE_UNSPECIFIED = 'FEATURE_SELECTION_PREFERENCE_UNSPECIFIED',\n PRIORITIZE_QUALITY = 'PRIORITIZE_QUALITY',\n BALANCED = 'BALANCED',\n PRIORITIZE_COST = 'PRIORITIZE_COST',\n}\n\n/** The environment being operated. */\nexport enum Environment {\n /**\n * Defaults to browser.\n */\n ENVIRONMENT_UNSPECIFIED = 'ENVIRONMENT_UNSPECIFIED',\n /**\n * Operates in a web browser.\n */\n ENVIRONMENT_BROWSER = 'ENVIRONMENT_BROWSER',\n}\n\n/** Enum that controls the safety filter level for objectionable content. */\nexport enum SafetyFilterLevel {\n BLOCK_LOW_AND_ABOVE = 'BLOCK_LOW_AND_ABOVE',\n BLOCK_MEDIUM_AND_ABOVE = 'BLOCK_MEDIUM_AND_ABOVE',\n BLOCK_ONLY_HIGH = 'BLOCK_ONLY_HIGH',\n BLOCK_NONE = 'BLOCK_NONE',\n}\n\n/** Enum that controls the generation of people. */\nexport enum PersonGeneration {\n /**\n * Block generation of images of people.\n */\n DONT_ALLOW = 'DONT_ALLOW',\n /**\n * Generate images of adults, but not children.\n */\n ALLOW_ADULT = 'ALLOW_ADULT',\n /**\n * Generate images that include adults and children.\n */\n ALLOW_ALL = 'ALLOW_ALL',\n}\n\n/** Enum that specifies the language of the text in the prompt. */\nexport enum ImagePromptLanguage {\n /**\n * Auto-detect the language.\n */\n auto = 'auto',\n /**\n * English\n */\n en = 'en',\n /**\n * Japanese\n */\n ja = 'ja',\n /**\n * Korean\n */\n ko = 'ko',\n /**\n * Hindi\n */\n hi = 'hi',\n /**\n * Chinese\n */\n zh = 'zh',\n /**\n * Portuguese\n */\n pt = 'pt',\n /**\n * Spanish\n */\n es = 'es',\n}\n\n/** Enum representing the mask mode of a mask reference image. */\nexport enum MaskReferenceMode {\n MASK_MODE_DEFAULT = 'MASK_MODE_DEFAULT',\n MASK_MODE_USER_PROVIDED = 'MASK_MODE_USER_PROVIDED',\n MASK_MODE_BACKGROUND = 'MASK_MODE_BACKGROUND',\n MASK_MODE_FOREGROUND = 'MASK_MODE_FOREGROUND',\n MASK_MODE_SEMANTIC = 'MASK_MODE_SEMANTIC',\n}\n\n/** Enum representing the control type of a control reference image. */\nexport enum ControlReferenceType {\n CONTROL_TYPE_DEFAULT = 'CONTROL_TYPE_DEFAULT',\n CONTROL_TYPE_CANNY = 'CONTROL_TYPE_CANNY',\n CONTROL_TYPE_SCRIBBLE = 'CONTROL_TYPE_SCRIBBLE',\n CONTROL_TYPE_FACE_MESH = 'CONTROL_TYPE_FACE_MESH',\n}\n\n/** Enum representing the subject type of a subject reference image. */\nexport enum SubjectReferenceType {\n SUBJECT_TYPE_DEFAULT = 'SUBJECT_TYPE_DEFAULT',\n SUBJECT_TYPE_PERSON = 'SUBJECT_TYPE_PERSON',\n SUBJECT_TYPE_ANIMAL = 'SUBJECT_TYPE_ANIMAL',\n SUBJECT_TYPE_PRODUCT = 'SUBJECT_TYPE_PRODUCT',\n}\n\n/** Enum representing the editing mode. */\nexport enum EditMode {\n EDIT_MODE_DEFAULT = 'EDIT_MODE_DEFAULT',\n EDIT_MODE_INPAINT_REMOVAL = 'EDIT_MODE_INPAINT_REMOVAL',\n EDIT_MODE_INPAINT_INSERTION = 'EDIT_MODE_INPAINT_INSERTION',\n EDIT_MODE_OUTPAINT = 'EDIT_MODE_OUTPAINT',\n EDIT_MODE_CONTROLLED_EDITING = 'EDIT_MODE_CONTROLLED_EDITING',\n EDIT_MODE_STYLE = 'EDIT_MODE_STYLE',\n EDIT_MODE_BGSWAP = 'EDIT_MODE_BGSWAP',\n EDIT_MODE_PRODUCT_IMAGE = 'EDIT_MODE_PRODUCT_IMAGE',\n}\n\n/** Enum that represents the segmentation mode. */\nexport enum SegmentMode {\n FOREGROUND = 'FOREGROUND',\n BACKGROUND = 'BACKGROUND',\n PROMPT = 'PROMPT',\n SEMANTIC = 'SEMANTIC',\n INTERACTIVE = 'INTERACTIVE',\n}\n\n/** Enum for the reference type of a video generation reference image. */\nexport enum VideoGenerationReferenceType {\n /**\n * A reference image that provides assets to the generated video,\n such as the scene, an object, a character, etc.\n */\n ASSET = 'ASSET',\n /**\n * A reference image that provides aesthetics including colors,\n lighting, texture, etc., to be used as the style of the generated video,\n such as 'anime', 'photography', 'origami', etc.\n */\n STYLE = 'STYLE',\n}\n\n/** Enum for the mask mode of a video generation mask. */\nexport enum VideoGenerationMaskMode {\n /**\n * The image mask contains a masked rectangular region which is\n applied on the first frame of the input video. The object described in\n the prompt is inserted into this region and will appear in subsequent\n frames.\n */\n INSERT = 'INSERT',\n /**\n * The image mask is used to determine an object in the\n first video frame to track. This object is removed from the video.\n */\n REMOVE = 'REMOVE',\n /**\n * The image mask is used to determine a region in the\n video. Objects in this region will be removed.\n */\n REMOVE_STATIC = 'REMOVE_STATIC',\n /**\n * The image mask contains a masked rectangular region where\n the input video will go. The remaining area will be generated. Video\n masks are not supported.\n */\n OUTPAINT = 'OUTPAINT',\n}\n\n/** Enum that controls the compression quality of the generated videos. */\nexport enum VideoCompressionQuality {\n /**\n * Optimized video compression quality. This will produce videos\n with a compressed, smaller file size.\n */\n OPTIMIZED = 'OPTIMIZED',\n /**\n * Lossless video compression quality. This will produce videos\n with a larger file size.\n */\n LOSSLESS = 'LOSSLESS',\n}\n\n/** Enum representing the tuning method. */\nexport enum TuningMethod {\n /**\n * Supervised fine tuning.\n */\n SUPERVISED_FINE_TUNING = 'SUPERVISED_FINE_TUNING',\n /**\n * Preference optimization tuning.\n */\n PREFERENCE_TUNING = 'PREFERENCE_TUNING',\n /**\n * Distillation tuning.\n */\n DISTILLATION = 'DISTILLATION',\n}\n\n/** State for the lifecycle of a Document. */\nexport enum DocumentState {\n STATE_UNSPECIFIED = 'STATE_UNSPECIFIED',\n STATE_PENDING = 'STATE_PENDING',\n STATE_ACTIVE = 'STATE_ACTIVE',\n STATE_FAILED = 'STATE_FAILED',\n}\n\n/** State for the lifecycle of a File. */\nexport enum FileState {\n STATE_UNSPECIFIED = 'STATE_UNSPECIFIED',\n PROCESSING = 'PROCESSING',\n ACTIVE = 'ACTIVE',\n FAILED = 'FAILED',\n}\n\n/** Source of the File. */\nexport enum FileSource {\n SOURCE_UNSPECIFIED = 'SOURCE_UNSPECIFIED',\n UPLOADED = 'UPLOADED',\n GENERATED = 'GENERATED',\n REGISTERED = 'REGISTERED',\n}\n\n/** The reason why the turn is complete. */\nexport enum TurnCompleteReason {\n /**\n * Default value. Reason is unspecified.\n */\n TURN_COMPLETE_REASON_UNSPECIFIED = 'TURN_COMPLETE_REASON_UNSPECIFIED',\n /**\n * The function call generated by the model is invalid.\n */\n MALFORMED_FUNCTION_CALL = 'MALFORMED_FUNCTION_CALL',\n /**\n * The response is rejected by the model.\n */\n RESPONSE_REJECTED = 'RESPONSE_REJECTED',\n /**\n * Needs more input from the user.\n */\n NEED_MORE_INPUT = 'NEED_MORE_INPUT',\n}\n\n/** Server content modalities. */\nexport enum MediaModality {\n /**\n * The modality is unspecified.\n */\n MODALITY_UNSPECIFIED = 'MODALITY_UNSPECIFIED',\n /**\n * Plain text.\n */\n TEXT = 'TEXT',\n /**\n * Images.\n */\n IMAGE = 'IMAGE',\n /**\n * Video.\n */\n VIDEO = 'VIDEO',\n /**\n * Audio.\n */\n AUDIO = 'AUDIO',\n /**\n * Document, e.g. PDF.\n */\n DOCUMENT = 'DOCUMENT',\n}\n\n/** The type of the VAD signal. */\nexport enum VadSignalType {\n /**\n * The default is VAD_SIGNAL_TYPE_UNSPECIFIED.\n */\n VAD_SIGNAL_TYPE_UNSPECIFIED = 'VAD_SIGNAL_TYPE_UNSPECIFIED',\n /**\n * Start of sentence signal.\n */\n VAD_SIGNAL_TYPE_SOS = 'VAD_SIGNAL_TYPE_SOS',\n /**\n * End of sentence signal.\n */\n VAD_SIGNAL_TYPE_EOS = 'VAD_SIGNAL_TYPE_EOS',\n}\n\n/** The type of the voice activity signal. */\nexport enum VoiceActivityType {\n /**\n * The default is VOICE_ACTIVITY_TYPE_UNSPECIFIED.\n */\n TYPE_UNSPECIFIED = 'TYPE_UNSPECIFIED',\n /**\n * Start of sentence signal.\n */\n ACTIVITY_START = 'ACTIVITY_START',\n /**\n * End of sentence signal.\n */\n ACTIVITY_END = 'ACTIVITY_END',\n}\n\n/** Start of speech sensitivity. */\nexport enum StartSensitivity {\n /**\n * The default is START_SENSITIVITY_LOW.\n */\n START_SENSITIVITY_UNSPECIFIED = 'START_SENSITIVITY_UNSPECIFIED',\n /**\n * Automatic detection will detect the start of speech more often.\n */\n START_SENSITIVITY_HIGH = 'START_SENSITIVITY_HIGH',\n /**\n * Automatic detection will detect the start of speech less often.\n */\n START_SENSITIVITY_LOW = 'START_SENSITIVITY_LOW',\n}\n\n/** End of speech sensitivity. */\nexport enum EndSensitivity {\n /**\n * The default is END_SENSITIVITY_LOW.\n */\n END_SENSITIVITY_UNSPECIFIED = 'END_SENSITIVITY_UNSPECIFIED',\n /**\n * Automatic detection ends speech more often.\n */\n END_SENSITIVITY_HIGH = 'END_SENSITIVITY_HIGH',\n /**\n * Automatic detection ends speech less often.\n */\n END_SENSITIVITY_LOW = 'END_SENSITIVITY_LOW',\n}\n\n/** The different ways of handling user activity. */\nexport enum ActivityHandling {\n /**\n * If unspecified, the default behavior is `START_OF_ACTIVITY_INTERRUPTS`.\n */\n ACTIVITY_HANDLING_UNSPECIFIED = 'ACTIVITY_HANDLING_UNSPECIFIED',\n /**\n * If true, start of activity will interrupt the model's response (also called \"barge in\"). The model's current response will be cut-off in the moment of the interruption. This is the default behavior.\n */\n START_OF_ACTIVITY_INTERRUPTS = 'START_OF_ACTIVITY_INTERRUPTS',\n /**\n * The model's response will not be interrupted.\n */\n NO_INTERRUPTION = 'NO_INTERRUPTION',\n}\n\n/** Options about which input is included in the user's turn. */\nexport enum TurnCoverage {\n /**\n * If unspecified, the default behavior is `TURN_INCLUDES_ONLY_ACTIVITY`.\n */\n TURN_COVERAGE_UNSPECIFIED = 'TURN_COVERAGE_UNSPECIFIED',\n /**\n * The users turn only includes activity since the last turn, excluding inactivity (e.g. silence on the audio stream). This is the default behavior.\n */\n TURN_INCLUDES_ONLY_ACTIVITY = 'TURN_INCLUDES_ONLY_ACTIVITY',\n /**\n * The users turn includes all realtime input since the last turn, including inactivity (e.g. silence on the audio stream).\n */\n TURN_INCLUDES_ALL_INPUT = 'TURN_INCLUDES_ALL_INPUT',\n}\n\n/** Scale of the generated music. */\nexport enum Scale {\n /**\n * Default value. This value is unused.\n */\n SCALE_UNSPECIFIED = 'SCALE_UNSPECIFIED',\n /**\n * C major or A minor.\n */\n C_MAJOR_A_MINOR = 'C_MAJOR_A_MINOR',\n /**\n * Db major or Bb minor.\n */\n D_FLAT_MAJOR_B_FLAT_MINOR = 'D_FLAT_MAJOR_B_FLAT_MINOR',\n /**\n * D major or B minor.\n */\n D_MAJOR_B_MINOR = 'D_MAJOR_B_MINOR',\n /**\n * Eb major or C minor\n */\n E_FLAT_MAJOR_C_MINOR = 'E_FLAT_MAJOR_C_MINOR',\n /**\n * E major or Db minor.\n */\n E_MAJOR_D_FLAT_MINOR = 'E_MAJOR_D_FLAT_MINOR',\n /**\n * F major or D minor.\n */\n F_MAJOR_D_MINOR = 'F_MAJOR_D_MINOR',\n /**\n * Gb major or Eb minor.\n */\n G_FLAT_MAJOR_E_FLAT_MINOR = 'G_FLAT_MAJOR_E_FLAT_MINOR',\n /**\n * G major or E minor.\n */\n G_MAJOR_E_MINOR = 'G_MAJOR_E_MINOR',\n /**\n * Ab major or F minor.\n */\n A_FLAT_MAJOR_F_MINOR = 'A_FLAT_MAJOR_F_MINOR',\n /**\n * A major or Gb minor.\n */\n A_MAJOR_G_FLAT_MINOR = 'A_MAJOR_G_FLAT_MINOR',\n /**\n * Bb major or G minor.\n */\n B_FLAT_MAJOR_G_MINOR = 'B_FLAT_MAJOR_G_MINOR',\n /**\n * B major or Ab minor.\n */\n B_MAJOR_A_FLAT_MINOR = 'B_MAJOR_A_FLAT_MINOR',\n}\n\n/** The mode of music generation. */\nexport enum MusicGenerationMode {\n /**\n * Rely on the server default generation mode.\n */\n MUSIC_GENERATION_MODE_UNSPECIFIED = 'MUSIC_GENERATION_MODE_UNSPECIFIED',\n /**\n * Steer text prompts to regions of latent space with higher quality\n music.\n */\n QUALITY = 'QUALITY',\n /**\n * Steer text prompts to regions of latent space with a larger\n diversity of music.\n */\n DIVERSITY = 'DIVERSITY',\n /**\n * Steer text prompts to regions of latent space more likely to\n generate music with vocals.\n */\n VOCALIZATION = 'VOCALIZATION',\n}\n\n/** The playback control signal to apply to the music generation. */\nexport enum LiveMusicPlaybackControl {\n /**\n * This value is unused.\n */\n PLAYBACK_CONTROL_UNSPECIFIED = 'PLAYBACK_CONTROL_UNSPECIFIED',\n /**\n * Start generating the music.\n */\n PLAY = 'PLAY',\n /**\n * Hold the music generation. Use PLAY to resume from the current position.\n */\n PAUSE = 'PAUSE',\n /**\n * Stop the music generation and reset the context (prompts retained).\n Use PLAY to restart the music generation.\n */\n STOP = 'STOP',\n /**\n * Reset the context of the music generation without stopping it.\n Retains the current prompts and config.\n */\n RESET_CONTEXT = 'RESET_CONTEXT',\n}\n\n/** Media resolution for the input media. */\nexport declare interface PartMediaResolution {\n /** The tokenization quality used for given media.\n */\n level?: PartMediaResolutionLevel;\n /** Specifies the required sequence length for media tokenization.\n */\n numTokens?: number;\n}\n\n/** Result of executing the [ExecutableCode]. Only generated when using the [CodeExecution] tool, and always follows a `part` containing the [ExecutableCode]. */\nexport declare interface CodeExecutionResult {\n /** Required. Outcome of the code execution. */\n outcome?: Outcome;\n /** Optional. Contains stdout when code execution is successful, stderr or other description otherwise. */\n output?: string;\n}\n\n/** Code generated by the model that is meant to be executed, and the result returned to the model. Generated when using the [CodeExecution] tool, in which the code will be automatically executed, and a corresponding [CodeExecutionResult] will also be generated. */\nexport declare interface ExecutableCode {\n /** Required. The code to be executed. */\n code?: string;\n /** Required. Programming language of the `code`. */\n language?: Language;\n}\n\n/** URI based data. */\nexport declare interface FileData {\n /** Optional. Display name of the file data. Used to provide a label or filename to distinguish file datas. This field is only returned in PromptMessage for prompt management. It is currently used in the Gemini GenerateContent calls only when server side tools (code_execution, google_search, and url_context) are enabled. This field is not supported in Gemini API. */\n displayName?: string;\n /** Required. URI. */\n fileUri?: string;\n /** Required. The IANA standard MIME type of the source data. */\n mimeType?: string;\n}\n\n/** Partial argument value of the function call. This data type is not supported in Gemini API. */\nexport declare interface PartialArg {\n /** Optional. Represents a null value. */\n nullValue?: 'NULL_VALUE';\n /** Optional. Represents a double value. */\n numberValue?: number;\n /** Optional. Represents a string value. */\n stringValue?: string;\n /** Optional. Represents a boolean value. */\n boolValue?: boolean;\n /** Required. A JSON Path (RFC 9535) to the argument being streamed. https://datatracker.ietf.org/doc/html/rfc9535. e.g. \"$.foo.bar[0].data\". */\n jsonPath?: string;\n /** Optional. Whether this is not the last part of the same json_path. If true, another PartialArg message for the current json_path is expected to follow. */\n willContinue?: boolean;\n}\n\n/** A function call. */\nexport declare interface FunctionCall {\n /** The unique id of the function call. If populated, the client to execute the\n `function_call` and return the response with the matching `id`. */\n id?: string;\n /** Optional. The function parameters and values in JSON object format. See [FunctionDeclaration.parameters] for parameter details. */\n args?: Record<string, unknown>;\n /** Optional. The name of the function to call. Matches [FunctionDeclaration.name]. */\n name?: string;\n /** Optional. The partial argument value of the function call. If provided, represents the arguments/fields that are streamed incrementally. This field is not supported in Gemini API. */\n partialArgs?: PartialArg[];\n /** Optional. Whether this is the last part of the FunctionCall. If true, another partial message for the current FunctionCall is expected to follow. This field is not supported in Gemini API. */\n willContinue?: boolean;\n}\n\n/** Raw media bytes for function response.\n\nText should not be sent as raw bytes, use the FunctionResponse.response\nfield. */\nexport class FunctionResponseBlob {\n /** Required. The IANA standard MIME type of the source data. */\n mimeType?: string;\n /** Required. Inline media bytes.\n * @remarks Encoded as base64 string. */\n data?: string;\n /** Optional. Display name of the blob.\n Used to provide a label or filename to distinguish blobs. */\n displayName?: string;\n}\n\n/** URI based data for function response. */\nexport class FunctionResponseFileData {\n /** Required. URI. */\n fileUri?: string;\n /** Required. The IANA standard MIME type of the source data. */\n mimeType?: string;\n /** Optional. Display name of the file.\n Used to provide a label or filename to distinguish files. */\n displayName?: string;\n}\n\n/** A datatype containing media that is part of a `FunctionResponse` message.\n\nA `FunctionResponsePart` consists of data which has an associated datatype. A\n`FunctionResponsePart` can only contain one of the accepted types in\n`FunctionResponsePart.data`.\n\nA `FunctionResponsePart` must have a fixed IANA MIME type identifying the\ntype and subtype of the media if the `inline_data` field is filled with raw\nbytes. */\nexport class FunctionResponsePart {\n /** Optional. Inline media bytes. */\n inlineData?: FunctionResponseBlob;\n /** Optional. URI based data. */\n fileData?: FunctionResponseFileData;\n}\n/**\n * Creates a `FunctionResponsePart` object from a `base64` encoded `string`.\n */\nexport function createFunctionResponsePartFromBase64(\n data: string,\n mimeType: string,\n): FunctionResponsePart {\n return {\n inlineData: {\n data: data,\n mimeType: mimeType,\n },\n };\n}\n/**\n * Creates a `FunctionResponsePart` object from a `URI` string.\n */\nexport function createFunctionResponsePartFromUri(\n uri: string,\n mimeType: string,\n): FunctionResponsePart {\n return {\n fileData: {\n fileUri: uri,\n mimeType: mimeType,\n },\n };\n}\n\n/** A function response. */\nexport class FunctionResponse {\n /** Signals that function call continues, and more responses will be returned, turning the function call into a generator. Is only applicable to NON_BLOCKING function calls (see FunctionDeclaration.behavior for details), ignored otherwise. If false, the default, future responses will not be considered. Is only applicable to NON_BLOCKING function calls, is ignored otherwise. If set to false, future responses will not be considered. It is allowed to return empty `response` with `will_continue=False` to signal that the function call is finished. */\n willContinue?: boolean;\n /** Specifies how the response should be scheduled in the conversation. Only applicable to NON_BLOCKING function calls, is ignored otherwise. Defaults to WHEN_IDLE. */\n scheduling?: FunctionResponseScheduling;\n /** List of parts that constitute a function response. Each part may\n have a different IANA MIME type. */\n parts?: FunctionResponsePart[];\n /** Optional. The id of the function call this response is for. Populated by the client to match the corresponding function call `id`. */\n id?: string;\n /** Required. The name of the function to call. Matches [FunctionDeclaration.name] and [FunctionCall.name]. */\n name?: string;\n /** Required. The function response in JSON object format. Use \"output\" key to specify function output and \"error\" key to specify error details (if any). If \"output\" and \"error\" keys are not specified, then whole \"response\" is treated as function output. */\n response?: Record<string, unknown>;\n}\n\n/** Content blob. */\nexport declare interface Blob {\n /** Required. Raw bytes.\n * @remarks Encoded as base64 string. */\n data?: string;\n /** Optional. Display name of the blob. Used to provide a label or filename to distinguish blobs. This field is only returned in PromptMessage for prompt management. It is currently used in the Gemini GenerateContent calls only when server side tools (code_execution, google_search, and url_context) are enabled. This field is not supported in Gemini API. */\n displayName?: string;\n /** Required. The IANA standard MIME type of the source data. */\n mimeType?: string;\n}\n\n/** Metadata describes the input video content. */\nexport declare interface VideoMetadata {\n /** Optional. The end offset of the video. */\n endOffset?: string;\n /** Optional. The frame rate of the video sent to the model. If not specified, the default value will be 1.0. The fps range is (0.0, 24.0]. */\n fps?: number;\n /** Optional. The start offset of the video. */\n startOffset?: string;\n}\n\n/** A datatype containing media content.\n\nExactly one field within a Part should be set, representing the specific type\nof content being conveyed. Using multiple fields within the same `Part`\ninstance is considered invalid. */\nexport declare interface Part {\n /** Media resolution for the input media.\n */\n mediaResolution?: PartMediaResolution;\n /** Optional. Result of executing the [ExecutableCode]. */\n codeExecutionResult?: CodeExecutionResult;\n /** Optional. Code generated by the model that is meant to be executed. */\n executableCode?: ExecutableCode;\n /** Optional. URI based data. */\n fileData?: FileData;\n /** Optional. A predicted [FunctionCall] returned from the model that contains a string representing the [FunctionDeclaration.name] with the parameters and their values. */\n functionCall?: FunctionCall;\n /** Optional. The result output of a [FunctionCall] that contains a string representing the [FunctionDeclaration.name] and a structured JSON object containing any output from the function call. It is used as context to the model. */\n functionResponse?: FunctionResponse;\n /** Optional. Inlined bytes data. */\n inlineData?: Blob;\n /** Optional. Text part (can be code). */\n text?: string;\n /** Optional. Indicates if the part is thought from the model. */\n thought?: boolean;\n /** Optional. An opaque signature for the thought so it can be reused in subsequent requests.\n * @remarks Encoded as base64 string. */\n thoughtSignature?: string;\n /** Optional. Video metadata. The metadata should only be specified while the video data is presented in inline_data or file_data. */\n videoMetadata?: VideoMetadata;\n}\n/**\n * Creates a `Part` object from a `URI` string.\n */\nexport function createPartFromUri(\n uri: string,\n mimeType: string,\n mediaResolution?: PartMediaResolutionLevel,\n): Part {\n return {\n fileData: {\n fileUri: uri,\n mimeType: mimeType,\n },\n ...(mediaResolution && {mediaResolution: {level: mediaResolution}}),\n };\n}\n/**\n * Creates a `Part` object from a `text` string.\n */\nexport function createPartFromText(text: string): Part {\n return {\n text: text,\n };\n}\n/**\n * Creates a `Part` object from a `FunctionCall` object.\n */\nexport function createPartFromFunctionCall(\n name: string,\n args: Record<string, unknown>,\n): Part {\n return {\n functionCall: {\n name: name,\n args: args,\n },\n };\n}\n/**\n * Creates a `Part` object from a `FunctionResponse` object.\n */\nexport function createPartFromFunctionResponse(\n id: string,\n name: string,\n response: Record<string, unknown>,\n parts: FunctionResponsePart[] = [],\n): Part {\n return {\n functionResponse: {\n id: id,\n name: name,\n response: response,\n ...(parts.length > 0 && {parts}),\n },\n };\n}\n/**\n * Creates a `Part` object from a `base64` encoded `string`.\n */\nexport function createPartFromBase64(\n data: string,\n mimeType: string,\n mediaResolution?: PartMediaResolutionLevel,\n): Part {\n return {\n inlineData: {\n data: data,\n mimeType: mimeType,\n },\n ...(mediaResolution && {mediaResolution: {level: mediaResolution}}),\n };\n}\n/**\n * Creates a `Part` object from the `outcome` and `output` of a `CodeExecutionResult` object.\n */\nexport function createPartFromCodeExecutionResult(\n outcome: Outcome,\n output: string,\n): Part {\n return {\n codeExecutionResult: {\n outcome: outcome,\n output: output,\n },\n };\n}\n/**\n * Creates a `Part` object from the `code` and `language` of an `ExecutableCode` object.\n */\nexport function createPartFromExecutableCode(\n code: string,\n language: Language,\n): Part {\n return {\n executableCode: {\n code: code,\n language: language,\n },\n };\n}\n\n/** Contains the multi-part content of a message. */\nexport declare interface Content {\n /** List of parts that constitute a single message. Each part may have\n a different IANA MIME type. */\n parts?: Part[];\n /** Optional. The producer of the content. Must be either 'user' or 'model'. Useful to set for multi-turn conversations, otherwise can be left blank or unset. */\n role?: string;\n}\nfunction _isPart(obj: unknown): obj is Part {\n if (typeof obj === 'object' && obj !== null) {\n return (\n 'fileData' in obj ||\n 'text' in obj ||\n 'functionCall' in obj ||\n 'functionResponse' in obj ||\n 'inlineData' in obj ||\n 'videoMetadata' in obj ||\n 'codeExecutionResult' in obj ||\n 'executableCode' in obj\n );\n }\n return false;\n}\nfunction _toParts(partOrString: PartListUnion | string): Part[] {\n const parts: Part[] = [];\n if (typeof partOrString === 'string') {\n parts.push(createPartFromText(partOrString));\n } else if (_isPart(partOrString)) {\n parts.push(partOrString);\n } else if (Array.isArray(partOrString)) {\n if (partOrString.length === 0) {\n throw new Error('partOrString cannot be an empty array');\n }\n for (const part of partOrString) {\n if (typeof part === 'string') {\n parts.push(createPartFromText(part));\n } else if (_isPart(part)) {\n parts.push(part);\n } else {\n throw new Error('element in PartUnion must be a Part object or string');\n }\n }\n } else {\n throw new Error('partOrString must be a Part object, string, or array');\n }\n return parts;\n}\n/**\n * Creates a `Content` object with a user role from a `PartListUnion` object or `string`.\n */\nexport function createUserContent(\n partOrString: PartListUnion | string,\n): Content {\n return {\n role: 'user',\n parts: _toParts(partOrString),\n };\n}\n\n/**\n * Creates a `Content` object with a model role from a `PartListUnion` object or `string`.\n */\nexport function createModelContent(\n partOrString: PartListUnion | string,\n): Content {\n return {\n role: 'model',\n parts: _toParts(partOrString),\n };\n}\n/** HTTP retry options to be used in each of the requests. */\nexport declare interface HttpRetryOptions {\n /** Maximum number of attempts, including the original request.\n If 0 or 1, it means no retries. If not specified, default to 5. */\n attempts?: number;\n}\n\n/** HTTP options to be used in each of the requests. */\nexport declare interface HttpOptions {\n /** The base URL for the AI platform service endpoint. */\n baseUrl?: string;\n /** The resource scope used to constructing the resource name when base_url is set */\n baseUrlResourceScope?: ResourceScope;\n /** Specifies the version of the API to use. */\n apiVersion?: string;\n /** Additional HTTP headers to be sent with the request. */\n headers?: Record<string, string>;\n /** Timeout for the request in milliseconds. */\n timeout?: number;\n /** Extra parameters to add to the request body.\n The structure must match the backend API's request structure.\n - VertexAI backend API docs: https://cloud.google.com/vertex-ai/docs/reference/rest\n - GeminiAPI backend API docs: https://ai.google.dev/api/rest */\n extraBody?: Record<string, unknown>;\n /** HTTP retry options for the request. */\n retryOptions?: HttpRetryOptions;\n}\n\n/** Schema is used to define the format of input/output data.\n\nRepresents a select subset of an [OpenAPI 3.0 schema\nobject](https://spec.openapis.org/oas/v3.0.3#schema-object). More fields may\nbe added in the future as needed. */\nexport declare interface Schema {\n /** Optional. The value should be validated against any (one or more) of the subschemas in the list. */\n anyOf?: Schema[];\n /** Optional. Default value of the data. */\n default?: unknown;\n /** Optional. The description of the data. */\n description?: string;\n /** Optional. Possible values of the element of primitive type with enum format. Examples: 1. We can define direction as : {type:STRING, format:enum, enum:[\"EAST\", NORTH\", \"SOUTH\", \"WEST\"]} 2. We can define apartment number as : {type:INTEGER, format:enum, enum:[\"101\", \"201\", \"301\"]} */\n enum?: string[];\n /** Optional. Example of the object. Will only populated when the object is the root. */\n example?: unknown;\n /** Optional. The format of the data. Supported formats: for NUMBER type: \"float\", \"double\" for INTEGER type: \"int32\", \"int64\" for STRING type: \"email\", \"byte\", etc */\n format?: string;\n /** Optional. SCHEMA FIELDS FOR TYPE ARRAY Schema of the elements of Type.ARRAY. */\n items?: Schema;\n /** Optional. Maximum number of the elements for Type.ARRAY. */\n maxItems?: string;\n /** Optional. Maximum length of the Type.STRING */\n maxLength?: string;\n /** Optional. Maximum number of the properties for Type.OBJECT. */\n maxProperties?: string;\n /** Optional. Maximum value of the Type.INTEGER and Type.NUMBER */\n maximum?: number;\n /** Optional. Minimum number of the elements for Type.ARRAY. */\n minItems?: string;\n /** Optional. SCHEMA FIELDS FOR TYPE STRING Minimum length of the Type.STRING */\n minLength?: string;\n /** Optional. Minimum number of the properties for Type.OBJECT. */\n minProperties?: string;\n /** Optional. SCHEMA FIELDS FOR TYPE INTEGER and NUMBER Minimum value of the Type.INTEGER and Type.NUMBER */\n minimum?: number;\n /** Optional. Indicates if the value may be null. */\n nullable?: boolean;\n /** Optional. Pattern of the Type.STRING to restrict a string to a regular expression. */\n pattern?: string;\n /** Optional. SCHEMA FIELDS FOR TYPE OBJECT Properties of Type.OBJECT. */\n properties?: Record<string, Schema>;\n /** Optional. The order of the properties. Not a standard field in open api spec. Only used to support the order of the properties. */\n propertyOrdering?: string[];\n /** Optional. Required properties of Type.OBJECT. */\n required?: string[];\n /** Optional. The title of the Schema. */\n title?: string;\n /** Optional. The type of the data. */\n type?: Type;\n}\n\n/** Config for model selection. */\nexport declare interface ModelSelectionConfig {\n /** Options for feature selection preference. */\n featureSelectionPreference?: FeatureSelectionPreference;\n}\n\n/** Tool to support computer use. */\nexport declare interface ComputerUse {\n /** Required. The environment being operated. */\n environment?: Environment;\n /** By default, predefined functions are included in the final model call.\n Some of them can be explicitly excluded from being automatically included.\n This can serve two purposes:\n 1. Using a more restricted / different action space.\n 2. Improving the definitions / instructions of predefined functions. */\n excludedPredefinedFunctions?: string[];\n}\n\n/** Tool to retrieve knowledge from the File Search Stores. */\nexport declare interface FileSearch {\n /** The names of the file_search_stores to retrieve from.\n Example: `fileSearchStores/my-file-search-store-123` */\n fileSearchStoreNames?: string[];\n /** The number of file search retrieval chunks to retrieve. */\n topK?: number;\n /** Metadata filter to apply to the file search retrieval documents. See https://google.aip.dev/160 for the syntax of the filter expression. */\n metadataFilter?: string;\n}\n\n/** The API secret. This data type is not supported in Gemini API. */\nexport declare interface ApiAuthApiKeyConfig {\n /** Required. The SecretManager secret version resource name storing API key. e.g. projects/{project}/secrets/{secret}/versions/{version} */\n apiKeySecretVersion?: string;\n /** The API key string. Either this or `api_key_secret_version` must be set. */\n apiKeyString?: string;\n}\n\n/** The generic reusable api auth config. Deprecated. Please use AuthConfig (google/cloud/aiplatform/master/auth.proto) instead. This data type is not supported in Gemini API. */\nexport declare interface ApiAuth {\n /** The API secret. */\n apiKeyConfig?: ApiAuthApiKeyConfig;\n}\n\n/** Config for authentication with API key. This data type is not supported in Gemini API. */\nexport declare interface ApiKeyConfig {\n /** Optional. The name of the SecretManager secret version resource storing the API key. Format: `projects/{project}/secrets/{secrete}/versions/{version}` - If both `api_key_secret` and `api_key_string` are specified, this field takes precedence over `api_key_string`. - If specified, the `secretmanager.versions.access` permission should be granted to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents) on the specified resource. */\n apiKeySecret?: string;\n /** Optional. The API key to be used in the request directly. */\n apiKeyString?: string;\n /** Optional. The location of the API key. */\n httpElementLocation?: HttpElementLocation;\n /** Optional. The parameter name of the API key. E.g. If the API request is \"https://example.com/act?api_key=\", \"api_key\" would be the parameter name. */\n name?: string;\n}\n\n/** Config for Google Service Account Authentication. This data type is not supported in Gemini API. */\nexport declare interface AuthConfigGoogleServiceAccountConfig {\n /** Optional. The service account that the extension execution service runs as. - If the service account is specified, the `iam.serviceAccounts.getAccessToken` permission should be granted to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents) on the specified service account. - If not specified, the Vertex AI Extension Service Agent will be used to execute the Extension. */\n serviceAccount?: string;\n}\n\n/** Config for HTTP Basic Authentication. This data type is not supported in Gemini API. */\nexport declare interface AuthConfigHttpBasicAuthConfig {\n /** Required. The name of the SecretManager secret version resource storing the base64 encoded credentials. Format: `projects/{project}/secrets/{secrete}/versions/{version}` - If specified, the `secretmanager.versions.access` permission should be granted to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents) on the specified resource. */\n credentialSecret?: string;\n}\n\n/** Config for user oauth. This data type is not supported in Gemini API. */\nexport declare interface AuthConfigOauthConfig {\n /** Access token for extension endpoint. Only used to propagate token from [[ExecuteExtensionRequest.runtime_auth_config]] at request time. */\n accessToken?: string;\n /** The service account used to generate access tokens for executing the Extension. - If the service account is specified, the `iam.serviceAccounts.getAccessToken` permission should be granted to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents) on the provided service account. */\n serviceAccount?: string;\n}\n\n/** Config for user OIDC auth. This data type is not supported in Gemini API. */\nexport declare interface AuthConfigOidcConfig {\n /** OpenID Connect formatted ID token for extension endpoint. Only used to propagate token from [[ExecuteExtensionRequest.runtime_auth_config]] at request time. */\n idToken?: string;\n /** The service account used to generate an OpenID Connect (OIDC)-compatible JWT token signed by the Google OIDC Provider (accounts.google.com) for extension endpoint (https://cloud.google.com/iam/docs/create-short-lived-credentials-direct#sa-credentials-oidc). - The audience for the token will be set to the URL in the server url defined in the OpenApi spec. - If the service account is provided, the service account should grant `iam.serviceAccounts.getOpenIdToken` permission to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents). */\n serviceAccount?: string;\n}\n\n/** Auth configuration to run the extension. This data type is not supported in Gemini API. */\nexport declare interface AuthConfig {\n /** Config for API key auth. */\n apiKeyConfig?: ApiKeyConfig;\n /** Type of auth scheme. */\n authType?: AuthType;\n /** Config for Google Service Account auth. */\n googleServiceAccountConfig?: AuthConfigGoogleServiceAccountConfig;\n /** Config for HTTP Basic auth. */\n httpBasicAuthConfig?: AuthConfigHttpBasicAuthConfig;\n /** Config for user oauth. */\n oauthConfig?: AuthConfigOauthConfig;\n /** Config for user OIDC auth. */\n oidcConfig?: AuthConfigOidcConfig;\n}\n\n/** The search parameters to use for the ELASTIC_SEARCH spec. This data type is not supported in Gemini API. */\nexport declare interface ExternalApiElasticSearchParams {\n /** The ElasticSearch index to use. */\n index?: string;\n /** Optional. Number of hits (chunks) to request. When specified, it is passed to Elasticsearch as the `num_hits` param. */\n numHits?: number;\n /** The ElasticSearch search template to use. */\n searchTemplate?: string;\n}\n\n/** The search parameters to use for SIMPLE_SEARCH spec. This data type is not supported in Gemini API. */\nexport declare interface ExternalApiSimpleSearchParams {}\n\n/** Retrieve from data source powered by external API for grounding. The external API is not owned by Google, but need to follow the pre-defined API spec. This data type is not supported in Gemini API. */\nexport declare interface ExternalApi {\n /** The authentication config to access the API. Deprecated. Please use auth_config instead. */\n apiAuth?: ApiAuth;\n /** The API spec that the external API implements. */\n apiSpec?: ApiSpec;\n /** The authentication config to access the API. */\n authConfig?: AuthConfig;\n /** Parameters for the elastic search API. */\n elasticSearchParams?: ExternalApiElasticSearchParams;\n /** The endpoint of the external API. The system will call the API at this endpoint to retrieve the data for grounding. Example: https://acme.com:443/search */\n endpoint?: string;\n /** Parameters for the simple search API. */\n simpleSearchParams?: ExternalApiSimpleSearchParams;\n}\n\n/** Define data stores within engine to filter on in a search call and configurations for those data stores. For more information, see https://cloud.google.com/generative-ai-app-builder/docs/reference/rpc/google.cloud.discoveryengine.v1#datastorespec. This data type is not supported in Gemini API. */\nexport declare interface VertexAISearchDataStoreSpec {\n /** Full resource name of DataStore, such as Format: `projects/{project}/locations/{location}/collections/{collection}/dataStores/{dataStore}` */\n dataStore?: string;\n /** Optional. Filter specification to filter documents in the data store specified by data_store field. For more information on filtering, see [Filtering](https://cloud.google.com/generative-ai-app-builder/docs/filter-search-metadata) */\n filter?: string;\n}\n\n/** Retrieve from Vertex AI Search datastore or engine for grounding. datastore and engine are mutually exclusive. See https://cloud.google.com/products/agent-builder. This data type is not supported in Gemini API. */\nexport declare interface VertexAISearch {\n /** Specifications that define the specific DataStores to be searched, along with configurations for those data stores. This is only considered for Engines with multiple data stores. It should only be set if engine is used. */\n dataStoreSpecs?: VertexAISearchDataStoreSpec[];\n /** Optional. Fully-qualified Vertex AI Search data store resource ID. Format: `projects/{project}/locations/{location}/collections/{collection}/dataStores/{dataStore}` */\n datastore?: string;\n /** Optional. Fully-qualified Vertex AI Search engine resource ID. Format: `projects/{project}/locations/{location}/collections/{collection}/engines/{engine}` */\n engine?: string;\n /** Optional. Filter strings to be passed to the search API. */\n filter?: string;\n /** Optional. Number of search results to return per query. The default value is 10. The maximumm allowed value is 10. */\n maxResults?: number;\n}\n\n/** The definition of the Rag resource. This data type is not supported in Gemini API. */\nexport declare interface VertexRagStoreRagResource {\n /** Optional. RagCorpora resource name. Format: `projects/{project}/locations/{location}/ragCorpora/{rag_corpus}` */\n ragCorpus?: string;\n /** Optional. rag_file_id. The files should be in the same rag_corpus set in rag_corpus field. */\n ragFileIds?: string[];\n}\n\n/** Config for filters. This data type is not supported in Gemini API. */\nexport declare interface RagRetrievalConfigFilter {\n /** Optional. String for metadata filtering. */\n metadataFilter?: string;\n /** Optional. Only returns contexts with vector distance smaller than the threshold. */\n vectorDistanceThreshold?: number;\n /** Optional. Only returns contexts with vector similarity larger than the threshold. */\n vectorSimilarityThreshold?: number;\n}\n\n/** Config for Hybrid Search. This data type is not supported in Gemini API. */\nexport declare interface RagRetrievalConfigHybridSearch {\n /** Optional. Alpha value controls the weight between dense and sparse vector search results. The range is [0, 1], while 0 means sparse vector search only and 1 means dense vector search only. The default value is 0.5 which balances sparse and dense vector search equally. */\n alpha?: number;\n}\n\n/** Config for LlmRanker. This data type is not supported in Gemini API. */\nexport declare interface RagRetrievalConfigRankingLlmRanker {\n /** Optional. The model name used for ranking. See [Supported models](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference#supported-models). */\n modelName?: string;\n}\n\n/** Config for Rank Service. This data type is not supported in Gemini API. */\nexport declare interface RagRetrievalConfigRankingRankService {\n /** Optional. The model name of the rank service. Format: `semantic-ranker-512@latest` */\n modelName?: string;\n}\n\n/** Config for ranking and reranking. This data type is not supported in Gemini API. */\nexport declare interface RagRetrievalConfigRanking {\n /** Optional. Config for LlmRanker. */\n llmRanker?: RagRetrievalConfigRankingLlmRanker;\n /** Optional. Config for Rank Service. */\n rankService?: RagRetrievalConfigRankingRankService;\n}\n\n/** Specifies the context retrieval config. This data type is not supported in Gemini API. */\nexport declare interface RagRetrievalConfig {\n /** Optional. Config for filters. */\n filter?: RagRetrievalConfigFilter;\n /** Optional. Config for Hybrid Search. */\n hybridSearch?: RagRetrievalConfigHybridSearch;\n /** Optional. Config for ranking and reranking. */\n ranking?: RagRetrievalConfigRanking;\n /** Optional. The number of contexts to retrieve. */\n topK?: number;\n}\n\n/** Retrieve from Vertex RAG Store for grounding. This data type is not supported in Gemini API. */\nexport declare interface VertexRagStore {\n /** Optional. Deprecated. Please use rag_resources instead. */\n ragCorpora?: string[];\n /** Optional. The representation of the rag source. It can be used to specify corpus only or ragfiles. Currently only support one corpus or multiple files from one corpus. In the future we may open up multiple corpora support. */\n ragResources?: VertexRagStoreRagResource[];\n /** Optional. The retrieval config for the Rag query. */\n ragRetrievalConfig?: RagRetrievalConfig;\n /** Optional. Number of top k results to return from the selected corpora. */\n similarityTopK?: number;\n /** Optional. Currently only supported for Gemini Multimodal Live API. In Gemini Multimodal Live API, if `store_context` bool is specified, Gemini will leverage it to automatically memorize the interactions between the client and Gemini, and retrieve context when needed to augment the response generation for users' ongoing and future interactions. */\n storeContext?: boolean;\n /** Optional. Only return results with vector distance smaller than the threshold. */\n vectorDistanceThreshold?: number;\n}\n\n/** Defines a retrieval tool that model can call to access external knowledge. This data type is not supported in Gemini API. */\nexport declare interface Retrieval {\n /** Optional. Deprecated. This option is no longer supported. */\n disableAttribution?: boolean;\n /** Use data source powered by external API for grounding. */\n externalApi?: ExternalApi;\n /** Set to use data source powered by Vertex AI Search. */\n vertexAiSearch?: VertexAISearch;\n /** Set to use data source powered by Vertex RAG store. User data is uploaded via the VertexRagDataService. */\n vertexRagStore?: VertexRagStore;\n}\n\n/** Tool that executes code generated by the model, and automatically returns the result to the model. See also [ExecutableCode]and [CodeExecutionResult] which are input and output to this tool. This data type is not supported in Gemini API. */\nexport declare interface ToolCodeExecution {}\n\n/** Tool to search public web data, powered by Vertex AI Search and Sec4 compliance. This data type is not supported in Gemini API. */\nexport declare interface EnterpriseWebSearch {\n /** Optional. List of domains to be excluded from the search results. The default limit is 2000 domains. */\n excludeDomains?: string[];\n /** Optional. Sites with confidence level chosen & above this value will be blocked from the search results. */\n blockingConfidence?: PhishBlockThreshold;\n}\n\n/** Structured representation of a function declaration as defined by the [OpenAPI 3.0 specification](https://spec.openapis.org/oas/v3.0.3). Included in this declaration are the function name, description, parameters and response type. This FunctionDeclaration is a representation of a block of code that can be used as a `Tool` by the model and executed by the client. */\nexport declare interface FunctionDeclaration {\n /** Optional. Description and purpose of the function. Model uses it to decide how and whether to call the function. */\n description?: string;\n /** Required. The name of the function to call. Must start with a letter or an underscore. Must be a-z, A-Z, 0-9, or contain underscores, dots and dashes, with a maximum length of 64. */\n name?: string;\n /** Optional. Describes the parameters to this function in JSON Schema Object format. Reflects the Open API 3.03 Parameter Object. string Key: the name of the parameter. Parameter names are case sensitive. Schema Value: the Schema defining the type used for the parameter. For function with no parameters, this can be left unset. Parameter names must start with a letter or an underscore and must only contain chars a-z, A-Z, 0-9, or underscores with a maximum length of 64. Example with 1 required and 1 optional parameter: type: OBJECT properties: param1: type: STRING param2: type: INTEGER required: - param1 */\n parameters?: Schema;\n /** Optional. Describes the parameters to the function in JSON Schema format. The schema must describe an object where the properties are the parameters to the function. For example: ``` { \"type\": \"object\", \"properties\": { \"name\": { \"type\": \"string\" }, \"age\": { \"type\": \"integer\" } }, \"additionalProperties\": false, \"required\": [\"name\", \"age\"], \"propertyOrdering\": [\"name\", \"age\"] } ``` This field is mutually exclusive with `parameters`. */\n parametersJsonSchema?: unknown;\n /** Optional. Describes the output from this function in JSON Schema format. Reflects the Open API 3.03 Response Object. The Schema defines the type used for the response value of the function. */\n response?: Schema;\n /** Optional. Describes the output from this function in JSON Schema format. The value specified by the schema is the response value of the function. This field is mutually exclusive with `response`. */\n responseJsonSchema?: unknown;\n /** Optional. Specifies the function Behavior. Currently only supported by the BidiGenerateContent method. This field is not supported in Vertex AI. */\n behavior?: Behavior;\n}\n\n/** Tool to retrieve public maps data for grounding, powered by Google. */\nexport declare interface GoogleMaps {\n /** The authentication config to access the API. Only API key is supported. This field is not supported in Gemini API. */\n authConfig?: AuthConfig;\n /** Optional. If true, include the widget context token in the response. */\n enableWidget?: boolean;\n}\n\n/** Represents a time interval, encoded as a Timestamp start (inclusive) and a Timestamp end (exclusive). The start must be less than or equal to the end. When the start equals the end, the interval is empty (matches no time). When both start and end are unspecified, the interval matches any time. */\nexport declare interface Interval {\n /** Optional. Exclusive end of the interval. If specified, a Timestamp matching this interval will have to be before the end. */\n endTime?: string;\n /** Optional. Inclusive start of the interval. If specified, a Timestamp matching this interval will have to be the same or after the start. */\n startTime?: string;\n}\n\n/** GoogleSearch tool type. Tool to support Google Search in Model. Powered by Google. */\nexport declare interface GoogleSearch {\n /** Optional. List of domains to be excluded from the search results. The default limit is 2000 domains. Example: [\"amazon.com\", \"facebook.com\"]. This field is not supported in Gemini API. */\n excludeDomains?: string[];\n /** Optional. Sites with confidence level chosen & above this value will be blocked from the search results. This field is not supported in Gemini API. */\n blockingConfidence?: PhishBlockThreshold;\n /** Optional. Filter search results to a specific time range. If customers set a start time, they must set an end time (and vice versa). This field is not supported in Vertex AI. */\n timeRangeFilter?: Interval;\n}\n\n/** Describes the options to customize dynamic retrieval. */\nexport declare interface DynamicRetrievalConfig {\n /** Optional. The threshold to be used in dynamic retrieval. If not set, a system default value is used. */\n dynamicThreshold?: number;\n /** The mode of the predictor to be used in dynamic retrieval. */\n mode?: DynamicRetrievalConfigMode;\n}\n\n/** Tool to retrieve public web data for grounding, powered by Google. */\nexport declare interface GoogleSearchRetrieval {\n /** Specifies the dynamic retrieval configuration for the given source. */\n dynamicRetrievalConfig?: DynamicRetrievalConfig;\n}\n\n/** Tool to support URL context. */\nexport declare interface UrlContext {}\n\n/** Tool details of a tool that the model may use to generate a response. */\nexport declare interface Tool {\n /** Optional. Retrieval tool type. System will always execute the provided retrieval tool(s) to get external knowledge to answer the prompt. Retrieval results are presented to the model for generation. This field is not supported in Gemini API. */\n retrieval?: Retrieval;\n /** Optional. Tool to support the model interacting directly with the\n computer. If enabled, it automatically populates computer-use specific\n Function Declarations. */\n computerUse?: ComputerUse;\n /** Optional. Tool to retrieve knowledge from the File Search Stores. */\n fileSearch?: FileSearch;\n /** Optional. CodeExecution tool type. Enables the model to execute code as part of generation. */\n codeExecution?: ToolCodeExecution;\n /** Optional. Tool to support searching public web data, powered by Vertex AI Search and Sec4 compliance. This field is not supported in Gemini API. */\n enterpriseWebSearch?: EnterpriseWebSearch;\n /** Optional. Function tool type. One or more function declarations to be passed to the model along with the current user query. Model may decide to call a subset of these functions by populating FunctionCall in the response. User should provide a FunctionResponse for each function call in the next turn. Based on the function responses, Model will generate the final response back to the user. Maximum 512 function declarations can be provided. */\n functionDeclarations?: FunctionDeclaration[];\n /** Optional. GoogleMaps tool type. Tool to support Google Maps in Model. */\n googleMaps?: GoogleMaps;\n /** Optional. GoogleSearch tool type. Tool to support Google Search in Model. Powered by Google. */\n googleSearch?: GoogleSearch;\n /** Optional. Specialized retrieval tool that is powered by Google Search. */\n googleSearchRetrieval?: GoogleSearchRetrieval;\n /** Optional. Tool to support URL context retrieval. */\n urlContext?: UrlContext;\n}\n\n/** An object that represents a latitude/longitude pair.\n\nThis is expressed as a pair of doubles to represent degrees latitude and\ndegrees longitude. Unless specified otherwise, this object must conform to the\n<a href=\"https://en.wikipedia.org/wiki/World_Geodetic_System#1984_version\">\nWGS84 standard</a>. Values must be within normalized ranges. */\nexport declare interface LatLng {\n /** The latitude in degrees. It must be in the range [-90.0, +90.0]. */\n latitude?: number;\n /** The longitude in degrees. It must be in the range [-180.0, +180.0] */\n longitude?: number;\n}\n\n/** Retrieval config.\n */\nexport declare interface RetrievalConfig {\n /** Optional. The location of the user. */\n latLng?: LatLng;\n /** The language code of the user. */\n languageCode?: string;\n}\n\n/** Function calling config. */\nexport declare interface FunctionCallingConfig {\n /** Optional. Function names to call. Only set when the Mode is ANY. Function names should match [FunctionDeclaration.name]. With mode set to ANY, model will predict a function call from the set of function names provided. */\n allowedFunctionNames?: string[];\n /** Optional. Function calling mode. */\n mode?: FunctionCallingConfigMode;\n /** Optional. When set to true, arguments of a single function call will be streamed out in multiple parts/contents/responses. Partial parameter results will be returned in the [FunctionCall.partial_args] field. This field is not supported in Gemini API. */\n streamFunctionCallArguments?: boolean;\n}\n\n/** Tool config.\n\nThis config is shared for all tools provided in the request. */\nexport declare interface ToolConfig {\n /** Optional. Retrieval config. */\n retrievalConfig?: RetrievalConfig;\n /** Optional. Function calling config. */\n functionCallingConfig?: FunctionCallingConfig;\n}\n\n/** ReplicatedVoiceConfig is used to configure replicated voice. */\nexport declare interface ReplicatedVoiceConfig {\n /** The mime type of the replicated voice.\n */\n mimeType?: string;\n /** The sample audio of the replicated voice.\n \n * @remarks Encoded as base64 string. */\n voiceSampleAudio?: string;\n}\n\n/** The configuration for the prebuilt speaker to use. */\nexport declare interface PrebuiltVoiceConfig {\n /** The name of the preset voice to use. */\n voiceName?: string;\n}\n\nexport declare interface VoiceConfig {\n /** If true, the model will use a replicated voice for the response. */\n replicatedVoiceConfig?: ReplicatedVoiceConfig;\n /** The configuration for the prebuilt voice to use. */\n prebuiltVoiceConfig?: PrebuiltVoiceConfig;\n}\n\n/** Configuration for a single speaker in a multi speaker setup. */\nexport declare interface SpeakerVoiceConfig {\n /** Required. The name of the speaker. This should be the same as the speaker name used in the prompt. */\n speaker?: string;\n /** Required. The configuration for the voice of this speaker. */\n voiceConfig?: VoiceConfig;\n}\n\n/** Configuration for a multi-speaker text-to-speech request. */\nexport declare interface MultiSpeakerVoiceConfig {\n /** Required. A list of configurations for the voices of the speakers. Exactly two speaker voice configurations must be provided. */\n speakerVoiceConfigs?: SpeakerVoiceConfig[];\n}\n\nexport declare interface SpeechConfig {\n /** Configuration for the voice of the response. */\n voiceConfig?: VoiceConfig;\n /** Optional. Language code (ISO 639. e.g. en-US) for the speech synthesization. */\n languageCode?: string;\n /** The configuration for a multi-speaker text-to-speech request. This field is mutually exclusive with `voice_config`. */\n multiSpeakerVoiceConfig?: MultiSpeakerVoiceConfig;\n}\n\n/** The configuration for automatic function calling. */\nexport declare interface AutomaticFunctionCallingConfig {\n /** Whether to disable automatic function calling.\n If not set or set to False, will enable automatic function calling.\n If set to True, will disable automatic function calling.\n */\n disable?: boolean;\n /** If automatic function calling is enabled,\n maximum number of remote calls for automatic function calling.\n This number should be a positive integer.\n If not set, SDK will set maximum number of remote calls to 10.\n */\n maximumRemoteCalls?: number;\n /** If automatic function calling is enabled,\n whether to ignore call history to the response.\n If not set, SDK will set ignore_call_history to false,\n and will append the call history to\n GenerateContentResponse.automatic_function_calling_history.\n */\n ignoreCallHistory?: boolean;\n}\n\n/** The thinking features configuration. */\nexport declare interface ThinkingConfig {\n /** Indicates whether to include thoughts in the response. If true, thoughts are returned only if the model supports thought and thoughts are available.\n */\n includeThoughts?: boolean;\n /** Indicates the thinking budget in tokens. 0 is DISABLED. -1 is AUTOMATIC. The default values and allowed ranges are model dependent.\n */\n thinkingBudget?: number;\n /** Optional. The number of thoughts tokens that the model should generate. */\n thinkingLevel?: ThinkingLevel;\n}\n\n/** The image generation configuration to be used in GenerateContentConfig. */\nexport declare interface ImageConfig {\n /** Aspect ratio of the generated images. Supported values are\n \"1:1\", \"2:3\", \"3:2\", \"3:4\", \"4:3\", \"9:16\", \"16:9\", and \"21:9\". */\n aspectRatio?: string;\n /** Optional. Specifies the size of generated images. Supported\n values are `1K`, `2K`, `4K`. If not specified, the model will use default\n value `1K`. */\n imageSize?: string;\n /** Controls the generation of people. Supported values are:\n ALLOW_ALL, ALLOW_ADULT, ALLOW_NONE. */\n personGeneration?: string;\n /** MIME type of the generated image. This field is not\n supported in Gemini API. */\n outputMimeType?: string;\n /** Compression quality of the generated image (for\n ``image/jpeg`` only). This field is not supported in Gemini API. */\n outputCompressionQuality?: number;\n}\n\n/** When automated routing is specified, the routing will be determined by the pretrained routing model and customer provided model routing preference. This data type is not supported in Gemini API. */\nexport declare interface GenerationConfigRoutingConfigAutoRoutingMode {\n /** The model routing preference. */\n modelRoutingPreference?:\n | 'UNKNOWN'\n | 'PRIORITIZE_QUALITY'\n | 'BALANCED'\n | 'PRIORITIZE_COST';\n}\n\n/** When manual routing is set, the specified model will be used directly. This data type is not supported in Gemini API. */\nexport declare interface GenerationConfigRoutingConfigManualRoutingMode {\n /** The model name to use. Only the public LLM models are accepted. See [Supported models](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference#supported-models). */\n modelName?: string;\n}\n\n/** The configuration for routing the request to a specific model. This data type is not supported in Gemini API. */\nexport declare interface GenerationConfigRoutingConfig {\n /** Automated routing. */\n autoMode?: GenerationConfigRoutingConfigAutoRoutingMode;\n /** Manual routing. */\n manualMode?: GenerationConfigRoutingConfigManualRoutingMode;\n}\n\n/** Safety settings. */\nexport declare interface SafetySetting {\n /** Required. Harm category. */\n category?: HarmCategory;\n /** Optional. Specify if the threshold is used for probability or severity score. If not specified, the threshold is used for probability score. This field is not supported in Gemini API. */\n method?: HarmBlockMethod;\n /** Required. The harm block threshold. */\n threshold?: HarmBlockThreshold;\n}\n\n/** Configuration for Model Armor integrations of prompt and responses. This data type is not supported in Gemini API. */\nexport declare interface ModelArmorConfig {\n /** Optional. The name of the Model Armor template to use for prompt sanitization. */\n promptTemplateName?: string;\n /** Optional. The name of the Model Armor template to use for response sanitization. */\n responseTemplateName?: string;\n}\n\n/** Optional model configuration parameters.\n\nFor more information, see `Content generation parameters\n<https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/content-generation-parameters>`_. */\nexport declare interface GenerateContentConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** Instructions for the model to steer it toward better performance.\n For example, \"Answer as concisely as possible\" or \"Don't use technical\n terms in your response\".\n */\n systemInstruction?: ContentUnion;\n /** Value that controls the degree of randomness in token selection.\n Lower temperatures are good for prompts that require a less open-ended or\n creative response, while higher temperatures can lead to more diverse or\n creative results.\n */\n temperature?: number;\n /** Tokens are selected from the most to least probable until the sum\n of their probabilities equals this value. Use a lower value for less\n random responses and a higher value for more random responses.\n */\n topP?: number;\n /** For each token selection step, the ``top_k`` tokens with the\n highest probabilities are sampled. Then tokens are further filtered based\n on ``top_p`` with the final token selected using temperature sampling. Use\n a lower number for less random responses and a higher number for more\n random responses.\n */\n topK?: number;\n /** Number of response variations to return.\n */\n candidateCount?: number;\n /** Maximum number of tokens that can be generated in the response.\n */\n maxOutputTokens?: number;\n /** List of strings that tells the model to stop generating text if one\n of the strings is encountered in the response.\n */\n stopSequences?: string[];\n /** Whether to return the log probabilities of the tokens that were\n chosen by the model at each step.\n */\n responseLogprobs?: boolean;\n /** Number of top candidate tokens to return the log probabilities for\n at each generation step.\n */\n logprobs?: number;\n /** Positive values penalize tokens that already appear in the\n generated text, increasing the probability of generating more diverse\n content.\n */\n presencePenalty?: number;\n /** Positive values penalize tokens that repeatedly appear in the\n generated text, increasing the probability of generating more diverse\n content.\n */\n frequencyPenalty?: number;\n /** When ``seed`` is fixed to a specific number, the model makes a best\n effort to provide the same response for repeated requests. By default, a\n random number is used.\n */\n seed?: number;\n /** Output response mimetype of the generated candidate text.\n Supported mimetype:\n - `text/plain`: (default) Text output.\n - `application/json`: JSON response in the candidates.\n The model needs to be prompted to output the appropriate response type,\n otherwise the behavior is undefined.\n This is a preview feature.\n */\n responseMimeType?: string;\n /** The `Schema` object allows the definition of input and output data types.\n These types can be objects, but also primitives and arrays.\n Represents a select subset of an [OpenAPI 3.0 schema\n object](https://spec.openapis.org/oas/v3.0.3#schema).\n If set, a compatible response_mime_type must also be set.\n Compatible mimetypes: `application/json`: Schema for JSON response.\n\n If `response_schema` doesn't process your schema correctly, try using\n `response_json_schema` instead.\n */\n responseSchema?: SchemaUnion;\n /** Optional. Output schema of the generated response.\n This is an alternative to `response_schema` that accepts [JSON\n Schema](https://json-schema.org/). If set, `response_schema` must be\n omitted, but `response_mime_type` is required. While the full JSON Schema\n may be sent, not all features are supported. Specifically, only the\n following properties are supported: - `$id` - `$defs` - `$ref` - `$anchor`\n - `type` - `format` - `title` - `description` - `enum` (for strings and\n numbers) - `items` - `prefixItems` - `minItems` - `maxItems` - `minimum` -\n `maximum` - `anyOf` - `oneOf` (interpreted the same as `anyOf`) -\n `properties` - `additionalProperties` - `required` The non-standard\n `propertyOrdering` property may also be set. Cyclic references are\n unrolled to a limited degree and, as such, may only be used within\n non-required properties. (Nullable properties are not sufficient.) If\n `$ref` is set on a sub-schema, no other properties, except for than those\n starting as a `$`, may be set. */\n responseJsonSchema?: unknown;\n /** Configuration for model router requests.\n */\n routingConfig?: GenerationConfigRoutingConfig;\n /** Configuration for model selection.\n */\n modelSelectionConfig?: ModelSelectionConfig;\n /** Safety settings in the request to block unsafe content in the\n response.\n */\n safetySettings?: SafetySetting[];\n /** Code that enables the system to interact with external systems to\n perform an action outside of the knowledge and scope of the model.\n */\n tools?: ToolListUnion;\n /** Associates model output to a specific function call.\n */\n toolConfig?: ToolConfig;\n /** Labels with user-defined metadata to break down billed charges. */\n labels?: Record<string, string>;\n /** Resource name of a context cache that can be used in subsequent\n requests.\n */\n cachedContent?: string;\n /** The requested modalities of the response. Represents the set of\n modalities that the model can return.\n */\n responseModalities?: string[];\n /** If specified, the media resolution specified will be used.\n */\n mediaResolution?: MediaResolution;\n /** The speech generation configuration.\n */\n speechConfig?: SpeechConfigUnion;\n /** If enabled, audio timestamp will be included in the request to the\n model.\n */\n audioTimestamp?: boolean;\n /** The configuration for automatic function calling.\n */\n automaticFunctionCalling?: AutomaticFunctionCallingConfig;\n /** The thinking features configuration.\n */\n thinkingConfig?: ThinkingConfig;\n /** The image generation configuration.\n */\n imageConfig?: ImageConfig;\n /** Enables enhanced civic answers. It may not be available for all\n models. This field is not supported in Vertex AI.\n */\n enableEnhancedCivicAnswers?: boolean;\n /** Settings for prompt and response sanitization using the Model Armor\n service. If supplied, safety_settings must not be supplied.\n */\n modelArmorConfig?: ModelArmorConfig;\n}\n\n/** Config for models.generate_content parameters. */\nexport declare interface GenerateContentParameters {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model: string;\n /** Content of the request.\n */\n contents: ContentListUnion;\n /** Configuration that contains optional model parameters.\n */\n config?: GenerateContentConfig;\n}\n\n/** A wrapper class for the http response. */\nexport class HttpResponse {\n /** Used to retain the processed HTTP headers in the response. */\n headers?: Record<string, string>;\n /**\n * The original http response.\n */\n responseInternal: Response;\n\n constructor(response: Response) {\n // Process the headers.\n const headers: Record<string, string> = {};\n for (const pair of response.headers.entries()) {\n headers[pair[0]] = pair[1];\n }\n this.headers = headers;\n\n // Keep the original response.\n this.responseInternal = response;\n }\n\n json(): Promise<unknown> {\n return this.responseInternal.json();\n }\n}\n\n/** Callbacks for the live API. */\nexport interface LiveCallbacks {\n /**\n * Called when the websocket connection is established.\n */\n onopen?: (() => void) | null;\n /**\n * Called when a message is received from the server.\n */\n onmessage: (e: LiveServerMessage) => void;\n /**\n * Called when an error occurs.\n */\n onerror?: ((e: ErrorEvent) => void) | null;\n /**\n * Called when the websocket connection is closed.\n */\n onclose?: ((e: CloseEvent) => void) | null;\n}\n\n/** Represents a whole or partial calendar date, such as a birthday. The time of day and time zone are either specified elsewhere or are insignificant. The date is relative to the Gregorian Calendar. This can represent one of the following: * A full date, with non-zero year, month, and day values. * A month and day, with a zero year (for example, an anniversary). * A year on its own, with a zero month and a zero day. * A year and month, with a zero day (for example, a credit card expiration date). Related types: * google.type.TimeOfDay * google.type.DateTime * google.protobuf.Timestamp. This data type is not supported in Gemini API. */\nexport declare interface GoogleTypeDate {\n /** Day of a month. Must be from 1 to 31 and valid for the year and month, or 0 to specify a year by itself or a year and month where the day isn't significant. */\n day?: number;\n /** Month of a year. Must be from 1 to 12, or 0 to specify a year without a month and day. */\n month?: number;\n /** Year of the date. Must be from 1 to 9999, or 0 to specify a date without a year. */\n year?: number;\n}\n\n/** Source attributions for content. This data type is not supported in Gemini API. */\nexport declare interface Citation {\n /** Output only. End index into the content. */\n endIndex?: number;\n /** Output only. License of the attribution. */\n license?: string;\n /** Output only. Publication date of the attribution. */\n publicationDate?: GoogleTypeDate;\n /** Output only. Start index into the content. */\n startIndex?: number;\n /** Output only. Title of the attribution. */\n title?: string;\n /** Output only. Url reference of the attribution. */\n uri?: string;\n}\n\n/** Citation information when the model quotes another source. */\nexport declare interface CitationMetadata {\n /** Contains citation information when the model directly quotes, at\n length, from another source. Can include traditional websites and code\n repositories.\n */\n citations?: Citation[];\n}\n\n/** Author attribution for a photo or review. This data type is not supported in Gemini API. */\nexport declare interface GroundingChunkMapsPlaceAnswerSourcesAuthorAttribution {\n /** Name of the author of the Photo or Review. */\n displayName?: string;\n /** Profile photo URI of the author of the Photo or Review. */\n photoUri?: string;\n /** URI of the author of the Photo or Review. */\n uri?: string;\n}\n\n/** Encapsulates a review snippet. This data type is not supported in Gemini API. */\nexport declare interface GroundingChunkMapsPlaceAnswerSourcesReviewSnippet {\n /** This review's author. */\n authorAttribution?: GroundingChunkMapsPlaceAnswerSourcesAuthorAttribution;\n /** A link where users can flag a problem with the review. */\n flagContentUri?: string;\n /** A link to show the review on Google Maps. */\n googleMapsUri?: string;\n /** A string of formatted recent time, expressing the review time relative to the current time in a form appropriate for the language and country. */\n relativePublishTimeDescription?: string;\n /** A reference representing this place review which may be used to look up this place review again. */\n review?: string;\n /** Id of the review referencing the place. */\n reviewId?: string;\n /** Title of the review. */\n title?: string;\n}\n\n/** Sources used to generate the place answer. This data type is not supported in Gemini API. */\nexport declare interface GroundingChunkMapsPlaceAnswerSources {\n /** A link where users can flag a problem with the generated answer. */\n flagContentUri?: string;\n /** Snippets of reviews that are used to generate the answer. */\n reviewSnippets?: GroundingChunkMapsPlaceAnswerSourcesReviewSnippet[];\n}\n\n/** Chunk from Google Maps. This data type is not supported in Gemini API. */\nexport declare interface GroundingChunkMaps {\n /** Sources used to generate the place answer. This includes review snippets and photos that were used to generate the answer, as well as uris to flag content. */\n placeAnswerSources?: GroundingChunkMapsPlaceAnswerSources;\n /** This Place's resource name, in `places/{place_id}` format. Can be used to look up the Place. */\n placeId?: string;\n /** Text of the place answer. */\n text?: string;\n /** Title of the place. */\n title?: string;\n /** URI reference of the place. */\n uri?: string;\n}\n\n/** Represents where the chunk starts and ends in the document. This data type is not supported in Gemini API. */\nexport declare interface RagChunkPageSpan {\n /** Page where chunk starts in the document. Inclusive. 1-indexed. */\n firstPage?: number;\n /** Page where chunk ends in the document. Inclusive. 1-indexed. */\n lastPage?: number;\n}\n\n/** A RagChunk includes the content of a chunk of a RagFile, and associated metadata. This data type is not supported in Gemini API. */\nexport declare interface RagChunk {\n /** If populated, represents where the chunk starts and ends in the document. */\n pageSpan?: RagChunkPageSpan;\n /** The content of the chunk. */\n text?: string;\n}\n\n/** Chunk from context retrieved by the retrieval tools. This data type is not supported in Gemini API. */\nexport declare interface GroundingChunkRetrievedContext {\n /** Output only. The full document name for the referenced Vertex AI Search document. */\n documentName?: string;\n /** Additional context for the RAG retrieval result. This is only populated when using the RAG retrieval tool. */\n ragChunk?: RagChunk;\n /** Text of the attribution. */\n text?: string;\n /** Title of the attribution. */\n title?: string;\n /** URI reference of the attribution. */\n uri?: string;\n}\n\n/** Chunk from the web. */\nexport declare interface GroundingChunkWeb {\n /** Domain of the (original) URI. This field is not supported in Gemini API. */\n domain?: string;\n /** Title of the chunk. */\n title?: string;\n /** URI reference of the chunk. */\n uri?: string;\n}\n\n/** Grounding chunk. */\nexport declare interface GroundingChunk {\n /** Grounding chunk from Google Maps. This field is not supported in Gemini API. */\n maps?: GroundingChunkMaps;\n /** Grounding chunk from context retrieved by the retrieval tools. This field is not supported in Gemini API. */\n retrievedContext?: GroundingChunkRetrievedContext;\n /** Grounding chunk from the web. */\n web?: GroundingChunkWeb;\n}\n\n/** Segment of the content. */\nexport declare interface Segment {\n /** Output only. End index in the given Part, measured in bytes. Offset from the start of the Part, exclusive, starting at zero. */\n endIndex?: number;\n /** Output only. The index of a Part object within its parent Content object. */\n partIndex?: number;\n /** Output only. Start index in the given Part, measured in bytes. Offset from the start of the Part, inclusive, starting at zero. */\n startIndex?: number;\n /** Output only. The text corresponding to the segment from the response. */\n text?: string;\n}\n\n/** Grounding support. */\nexport declare interface GroundingSupport {\n /** Confidence score of the support references. Ranges from 0 to 1. 1 is the most confident. For Gemini 2.0 and before, this list must have the same size as the grounding_chunk_indices. For Gemini 2.5 and after, this list will be empty and should be ignored. */\n confidenceScores?: number[];\n /** A list of indices (into 'grounding_chunk') specifying the citations associated with the claim. For instance [1,3,4] means that grounding_chunk[1], grounding_chunk[3], grounding_chunk[4] are the retrieved content attributed to the claim. */\n groundingChunkIndices?: number[];\n /** Segment of the content this support belongs to. */\n segment?: Segment;\n}\n\n/** Metadata related to retrieval in the grounding flow. */\nexport declare interface RetrievalMetadata {\n /** Optional. Score indicating how likely information from Google Search could help answer the prompt. The score is in the range `[0, 1]`, where 0 is the least likely and 1 is the most likely. This score is only populated when Google Search grounding and dynamic retrieval is enabled. It will be compared to the threshold to determine whether to trigger Google Search. */\n googleSearchDynamicRetrievalScore?: number;\n}\n\n/** Google search entry point. */\nexport declare interface SearchEntryPoint {\n /** Optional. Web content snippet that can be embedded in a web page or an app webview. */\n renderedContent?: string;\n /** Optional. Base64 encoded JSON representing array of tuple.\n * @remarks Encoded as base64 string. */\n sdkBlob?: string;\n}\n\n/** Source content flagging uri for a place or review. This is currently populated only for Google Maps grounding. This data type is not supported in Gemini API. */\nexport declare interface GroundingMetadataSourceFlaggingUri {\n /** A link where users can flag a problem with the source (place or review). */\n flagContentUri?: string;\n /** Id of the place or review. */\n sourceId?: string;\n}\n\n/** Metadata returned to client when grounding is enabled. */\nexport declare interface GroundingMetadata {\n /** Optional. Output only. Resource name of the Google Maps widget context token to be used with the PlacesContextElement widget to render contextual data. This is populated only for Google Maps grounding. This field is not supported in Gemini API. */\n googleMapsWidgetContextToken?: string;\n /** List of supporting references retrieved from specified grounding source. */\n groundingChunks?: GroundingChunk[];\n /** Optional. List of grounding support. */\n groundingSupports?: GroundingSupport[];\n /** Optional. Output only. Retrieval metadata. */\n retrievalMetadata?: RetrievalMetadata;\n /** Optional. Queries executed by the retrieval tools. This field is not supported in Gemini API. */\n retrievalQueries?: string[];\n /** Optional. Google search entry for the following-up web searches. */\n searchEntryPoint?: SearchEntryPoint;\n /** Optional. Output only. List of source flagging uris. This is currently populated only for Google Maps grounding. This field is not supported in Gemini API. */\n sourceFlaggingUris?: GroundingMetadataSourceFlaggingUri[];\n /** Optional. Web search queries for the following-up web search. */\n webSearchQueries?: string[];\n}\n\n/** Candidate for the logprobs token and score. */\nexport declare interface LogprobsResultCandidate {\n /** The candidate's log probability. */\n logProbability?: number;\n /** The candidate's token string value. */\n token?: string;\n /** The candidate's token id value. */\n tokenId?: number;\n}\n\n/** Candidates with top log probabilities at each decoding step. */\nexport declare interface LogprobsResultTopCandidates {\n /** Sorted by log probability in descending order. */\n candidates?: LogprobsResultCandidate[];\n}\n\n/** Logprobs Result */\nexport declare interface LogprobsResult {\n /** Length = total number of decoding steps. The chosen candidates may or may not be in top_candidates. */\n chosenCandidates?: LogprobsResultCandidate[];\n /** Length = total number of decoding steps. */\n topCandidates?: LogprobsResultTopCandidates[];\n}\n\n/** Safety rating corresponding to the generated content. */\nexport declare interface SafetyRating {\n /** Output only. Indicates whether the content was filtered out because of this rating. */\n blocked?: boolean;\n /** Output only. Harm category. */\n category?: HarmCategory;\n /** Output only. The overwritten threshold for the safety category of Gemini 2.0 image out. If minors are detected in the output image, the threshold of each safety category will be overwritten if user sets a lower threshold. This field is not supported in Gemini API. */\n overwrittenThreshold?: HarmBlockThreshold;\n /** Output only. Harm probability levels in the content. */\n probability?: HarmProbability;\n /** Output only. Harm probability score. This field is not supported in Gemini API. */\n probabilityScore?: number;\n /** Output only. Harm severity levels in the content. This field is not supported in Gemini API. */\n severity?: HarmSeverity;\n /** Output only. Harm severity score. This field is not supported in Gemini API. */\n severityScore?: number;\n}\n\n/** Context of the a single url retrieval. */\nexport declare interface UrlMetadata {\n /** Retrieved url by the tool. */\n retrievedUrl?: string;\n /** Status of the url retrieval. */\n urlRetrievalStatus?: UrlRetrievalStatus;\n}\n\n/** Metadata related to url context retrieval tool. */\nexport declare interface UrlContextMetadata {\n /** Output only. List of url context. */\n urlMetadata?: UrlMetadata[];\n}\n\n/** A response candidate generated from the model. */\nexport declare interface Candidate {\n /** Contains the multi-part content of the response.\n */\n content?: Content;\n /** Source attribution of the generated content.\n */\n citationMetadata?: CitationMetadata;\n /** Describes the reason the model stopped generating tokens.\n */\n finishMessage?: string;\n /** Number of tokens for this candidate.\n */\n tokenCount?: number;\n /** The reason why the model stopped generating tokens.\n If empty, the model has not stopped generating the tokens.\n */\n finishReason?: FinishReason;\n /** Output only. Average log probability score of the candidate. */\n avgLogprobs?: number;\n /** Output only. Metadata specifies sources used to ground generated content. */\n groundingMetadata?: GroundingMetadata;\n /** Output only. Index of the candidate. */\n index?: number;\n /** Output only. Log-likelihood scores for the response tokens and top tokens */\n logprobsResult?: LogprobsResult;\n /** Output only. List of ratings for the safety of a response candidate. There is at most one rating per category. */\n safetyRatings?: SafetyRating[];\n /** Output only. Metadata related to url context retrieval tool. */\n urlContextMetadata?: UrlContextMetadata;\n}\n\n/** Content filter results for a prompt sent in the request. Note: This is sent only in the first stream chunk and only if no candidates were generated due to content violations. */\nexport class GenerateContentResponsePromptFeedback {\n /** Output only. The reason why the prompt was blocked. */\n blockReason?: BlockedReason;\n /** Output only. A readable message that explains the reason why the prompt was blocked. This field is not supported in Gemini API. */\n blockReasonMessage?: string;\n /** Output only. A list of safety ratings for the prompt. There is one rating per category. */\n safetyRatings?: SafetyRating[];\n}\n\n/** Represents token counting info for a single modality. */\nexport declare interface ModalityTokenCount {\n /** The modality associated with this token count. */\n modality?: MediaModality;\n /** Number of tokens. */\n tokenCount?: number;\n}\n\n/** Usage metadata about the content generation request and response. This message provides a detailed breakdown of token usage and other relevant metrics. This data type is not supported in Gemini API. */\nexport class GenerateContentResponseUsageMetadata {\n /** Output only. A detailed breakdown of the token count for each modality in the cached content. */\n cacheTokensDetails?: ModalityTokenCount[];\n /** Output only. The number of tokens in the cached content that was used for this request. */\n cachedContentTokenCount?: number;\n /** The total number of tokens in the generated candidates. */\n candidatesTokenCount?: number;\n /** Output only. A detailed breakdown of the token count for each modality in the generated candidates. */\n candidatesTokensDetails?: ModalityTokenCount[];\n /** The total number of tokens in the prompt. This includes any text, images, or other media provided in the request. When `cached_content` is set, this also includes the number of tokens in the cached content. */\n promptTokenCount?: number;\n /** Output only. A detailed breakdown of the token count for each modality in the prompt. */\n promptTokensDetails?: ModalityTokenCount[];\n /** Output only. The number of tokens that were part of the model's generated \"thoughts\" output, if applicable. */\n thoughtsTokenCount?: number;\n /** Output only. The number of tokens in the results from tool executions, which are provided back to the model as input, if applicable. */\n toolUsePromptTokenCount?: number;\n /** Output only. A detailed breakdown by modality of the token counts from the results of tool executions, which are provided back to the model as input. */\n toolUsePromptTokensDetails?: ModalityTokenCount[];\n /** The total number of tokens for the entire request. This is the sum of `prompt_token_count`, `candidates_token_count`, `tool_use_prompt_token_count`, and `thoughts_token_count`. */\n totalTokenCount?: number;\n /** Output only. The traffic type for this request. */\n trafficType?: TrafficType;\n}\n\n/** Response message for PredictionService.GenerateContent. */\nexport class GenerateContentResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** Response variations returned by the model.\n */\n candidates?: Candidate[];\n /** Timestamp when the request is made to the server.\n */\n createTime?: string;\n /** The history of automatic function calling.\n */\n automaticFunctionCallingHistory?: Content[];\n /** Output only. The model version used to generate the response. */\n modelVersion?: string;\n /** Output only. Content filter results for a prompt sent in the request. Note: Sent only in the first stream chunk. Only happens when no candidates were generated due to content violations. */\n promptFeedback?: GenerateContentResponsePromptFeedback;\n /** Output only. response_id is used to identify each response. It is the encoding of the event_id. */\n responseId?: string;\n /** Usage metadata about the response(s). */\n usageMetadata?: GenerateContentResponseUsageMetadata;\n /**\n * Returns the concatenation of all text parts from the first candidate in the response.\n *\n * @remarks\n * If there are multiple candidates in the response, the text from the first\n * one will be returned.\n * If there are non-text parts in the response, the concatenation of all text\n * parts will be returned, and a warning will be logged.\n * If there are thought parts in the response, the concatenation of all text\n * parts excluding the thought parts will be returned.\n *\n * @example\n * ```ts\n * const response = await ai.models.generateContent({\n * model: 'gemini-2.0-flash',\n * contents:\n * 'Why is the sky blue?',\n * });\n *\n * console.debug(response.text);\n * ```\n */\n get text(): string | undefined {\n if (this.candidates?.[0]?.content?.parts?.length === 0) {\n return undefined;\n }\n if (this.candidates && this.candidates.length > 1) {\n console.warn(\n 'there are multiple candidates in the response, returning text from the first one.',\n );\n }\n let text = '';\n let anyTextPartText = false;\n const nonTextParts = [];\n for (const part of this.candidates?.[0]?.content?.parts ?? []) {\n for (const [fieldName, fieldValue] of Object.entries(part)) {\n if (\n fieldName !== 'text' &&\n fieldName !== 'thought' &&\n fieldName !== 'thoughtSignature' &&\n (fieldValue !== null || fieldValue !== undefined)\n ) {\n nonTextParts.push(fieldName);\n }\n }\n if (typeof part.text === 'string') {\n if (typeof part.thought === 'boolean' && part.thought) {\n continue;\n }\n anyTextPartText = true;\n text += part.text;\n }\n }\n if (nonTextParts.length > 0) {\n console.warn(\n `there are non-text parts ${nonTextParts} in the response, returning concatenation of all text parts. Please refer to the non text parts for a full response from model.`,\n );\n }\n // part.text === '' is different from part.text is null\n return anyTextPartText ? text : undefined;\n }\n\n /**\n * Returns the concatenation of all inline data parts from the first candidate\n * in the response.\n *\n * @remarks\n * If there are multiple candidates in the response, the inline data from the\n * first one will be returned. If there are non-inline data parts in the\n * response, the concatenation of all inline data parts will be returned, and\n * a warning will be logged.\n */\n get data(): string | undefined {\n if (this.candidates?.[0]?.content?.parts?.length === 0) {\n return undefined;\n }\n if (this.candidates && this.candidates.length > 1) {\n console.warn(\n 'there are multiple candidates in the response, returning data from the first one.',\n );\n }\n let data = '';\n const nonDataParts = [];\n for (const part of this.candidates?.[0]?.content?.parts ?? []) {\n for (const [fieldName, fieldValue] of Object.entries(part)) {\n if (\n fieldName !== 'inlineData' &&\n (fieldValue !== null || fieldValue !== undefined)\n ) {\n nonDataParts.push(fieldName);\n }\n }\n if (part.inlineData && typeof part.inlineData.data === 'string') {\n data += atob(part.inlineData.data);\n }\n }\n if (nonDataParts.length > 0) {\n console.warn(\n `there are non-data parts ${nonDataParts} in the response, returning concatenation of all data parts. Please refer to the non data parts for a full response from model.`,\n );\n }\n return data.length > 0 ? btoa(data) : undefined;\n }\n\n /**\n * Returns the function calls from the first candidate in the response.\n *\n * @remarks\n * If there are multiple candidates in the response, the function calls from\n * the first one will be returned.\n * If there are no function calls in the response, undefined will be returned.\n *\n * @example\n * ```ts\n * const controlLightFunctionDeclaration: FunctionDeclaration = {\n * name: 'controlLight',\n * parameters: {\n * type: Type.OBJECT,\n * description: 'Set the brightness and color temperature of a room light.',\n * properties: {\n * brightness: {\n * type: Type.NUMBER,\n * description:\n * 'Light level from 0 to 100. Zero is off and 100 is full brightness.',\n * },\n * colorTemperature: {\n * type: Type.STRING,\n * description:\n * 'Color temperature of the light fixture which can be `daylight`, `cool` or `warm`.',\n * },\n * },\n * required: ['brightness', 'colorTemperature'],\n * };\n * const response = await ai.models.generateContent({\n * model: 'gemini-2.0-flash',\n * contents: 'Dim the lights so the room feels cozy and warm.',\n * config: {\n * tools: [{functionDeclarations: [controlLightFunctionDeclaration]}],\n * toolConfig: {\n * functionCallingConfig: {\n * mode: FunctionCallingConfigMode.ANY,\n * allowedFunctionNames: ['controlLight'],\n * },\n * },\n * },\n * });\n * console.debug(JSON.stringify(response.functionCalls));\n * ```\n */\n get functionCalls(): FunctionCall[] | undefined {\n if (this.candidates?.[0]?.content?.parts?.length === 0) {\n return undefined;\n }\n if (this.candidates && this.candidates.length > 1) {\n console.warn(\n 'there are multiple candidates in the response, returning function calls from the first one.',\n );\n }\n const functionCalls = this.candidates?.[0]?.content?.parts\n ?.filter((part) => part.functionCall)\n .map((part) => part.functionCall)\n .filter(\n (functionCall): functionCall is FunctionCall =>\n functionCall !== undefined,\n );\n if (functionCalls?.length === 0) {\n return undefined;\n }\n return functionCalls;\n }\n /**\n * Returns the first executable code from the first candidate in the response.\n *\n * @remarks\n * If there are multiple candidates in the response, the executable code from\n * the first one will be returned.\n * If there are no executable code in the response, undefined will be\n * returned.\n *\n * @example\n * ```ts\n * const response = await ai.models.generateContent({\n * model: 'gemini-2.0-flash',\n * contents:\n * 'What is the sum of the first 50 prime numbers? Generate and run code for the calculation, and make sure you get all 50.'\n * config: {\n * tools: [{codeExecution: {}}],\n * },\n * });\n *\n * console.debug(response.executableCode);\n * ```\n */\n get executableCode(): string | undefined {\n if (this.candidates?.[0]?.content?.parts?.length === 0) {\n return undefined;\n }\n if (this.candidates && this.candidates.length > 1) {\n console.warn(\n 'there are multiple candidates in the response, returning executable code from the first one.',\n );\n }\n const executableCode = this.candidates?.[0]?.content?.parts\n ?.filter((part) => part.executableCode)\n .map((part) => part.executableCode)\n .filter(\n (executableCode): executableCode is ExecutableCode =>\n executableCode !== undefined,\n );\n if (executableCode?.length === 0) {\n return undefined;\n }\n\n return executableCode?.[0]?.code;\n }\n /**\n * Returns the first code execution result from the first candidate in the response.\n *\n * @remarks\n * If there are multiple candidates in the response, the code execution result from\n * the first one will be returned.\n * If there are no code execution result in the response, undefined will be returned.\n *\n * @example\n * ```ts\n * const response = await ai.models.generateContent({\n * model: 'gemini-2.0-flash',\n * contents:\n * 'What is the sum of the first 50 prime numbers? Generate and run code for the calculation, and make sure you get all 50.'\n * config: {\n * tools: [{codeExecution: {}}],\n * },\n * });\n *\n * console.debug(response.codeExecutionResult);\n * ```\n */\n get codeExecutionResult(): string | undefined {\n if (this.candidates?.[0]?.content?.parts?.length === 0) {\n return undefined;\n }\n if (this.candidates && this.candidates.length > 1) {\n console.warn(\n 'there are multiple candidates in the response, returning code execution result from the first one.',\n );\n }\n const codeExecutionResult = this.candidates?.[0]?.content?.parts\n ?.filter((part) => part.codeExecutionResult)\n .map((part) => part.codeExecutionResult)\n .filter(\n (codeExecutionResult): codeExecutionResult is CodeExecutionResult =>\n codeExecutionResult !== undefined,\n );\n if (codeExecutionResult?.length === 0) {\n return undefined;\n }\n return codeExecutionResult?.[0]?.output;\n }\n}\n\nexport type ReferenceImage =\n | RawReferenceImage\n | MaskReferenceImage\n | ControlReferenceImage\n | StyleReferenceImage\n | SubjectReferenceImage\n | ContentReferenceImage;\n\n/** Parameters for the request to edit an image. */\nexport declare interface EditImageParameters {\n /** The model to use. */\n model: string;\n /** A text description of the edit to apply to the image. */\n prompt: string;\n /** The reference images for Imagen 3 editing. */\n referenceImages: ReferenceImage[];\n /** Configuration for editing. */\n config?: EditImageConfig;\n}\n\n/** Optional parameters for the embed_content method. */\nexport declare interface EmbedContentConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** Type of task for which the embedding will be used.\n */\n taskType?: string;\n /** Title for the text. Only applicable when TaskType is\n `RETRIEVAL_DOCUMENT`.\n */\n title?: string;\n /** Reduced dimension for the output embedding. If set,\n excessive values in the output embedding are truncated from the end.\n Supported by newer models since 2024 only. You cannot set this value if\n using the earlier model (`models/embedding-001`).\n */\n outputDimensionality?: number;\n /** Vertex API only. The MIME type of the input.\n */\n mimeType?: string;\n /** Vertex API only. Whether to silently truncate inputs longer than\n the max sequence length. If this option is set to false, oversized inputs\n will lead to an INVALID_ARGUMENT error, similar to other text APIs.\n */\n autoTruncate?: boolean;\n}\n\n/** Parameters for the embed_content method. */\nexport declare interface EmbedContentParameters {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model: string;\n /** The content to embed. Only the `parts.text` fields will be counted.\n */\n contents: ContentListUnion;\n /** Configuration that contains optional parameters.\n */\n config?: EmbedContentConfig;\n}\n\n/** Statistics of the input text associated with the result of content embedding. */\nexport declare interface ContentEmbeddingStatistics {\n /** Vertex API only. If the input text was truncated due to having\n a length longer than the allowed maximum input.\n */\n truncated?: boolean;\n /** Vertex API only. Number of tokens of the input text.\n */\n tokenCount?: number;\n}\n\n/** The embedding generated from an input content. */\nexport declare interface ContentEmbedding {\n /** A list of floats representing an embedding.\n */\n values?: number[];\n /** Vertex API only. Statistics of the input text associated with this\n embedding.\n */\n statistics?: ContentEmbeddingStatistics;\n}\n\n/** Request-level metadata for the Vertex Embed Content API. */\nexport declare interface EmbedContentMetadata {\n /** Vertex API only. The total number of billable characters included\n in the request.\n */\n billableCharacterCount?: number;\n}\n\n/** Response for the embed_content method. */\nexport class EmbedContentResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** The embeddings for each request, in the same order as provided in\n the batch request.\n */\n embeddings?: ContentEmbedding[];\n /** Vertex API only. Metadata about the request.\n */\n metadata?: EmbedContentMetadata;\n}\n\n/** The config for generating an images. */\nexport declare interface GenerateImagesConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** Cloud Storage URI used to store the generated images. */\n outputGcsUri?: string;\n /** Description of what to discourage in the generated images. */\n negativePrompt?: string;\n /** Number of images to generate. */\n numberOfImages?: number;\n /** Aspect ratio of the generated images. Supported values are\n \"1:1\", \"3:4\", \"4:3\", \"9:16\", and \"16:9\". */\n aspectRatio?: string;\n /** Controls how much the model adheres to the text prompt. Large\n values increase output and prompt alignment, but may compromise image\n quality. */\n guidanceScale?: number;\n /** Random seed for image generation. This is not available when\n ``add_watermark`` is set to true. */\n seed?: number;\n /** Filter level for safety filtering. */\n safetyFilterLevel?: SafetyFilterLevel;\n /** Allows generation of people by the model. */\n personGeneration?: PersonGeneration;\n /** Whether to report the safety scores of each generated image and\n the positive prompt in the response. */\n includeSafetyAttributes?: boolean;\n /** Whether to include the Responsible AI filter reason if the image\n is filtered out of the response. */\n includeRaiReason?: boolean;\n /** Language of the text in the prompt. */\n language?: ImagePromptLanguage;\n /** MIME type of the generated image. */\n outputMimeType?: string;\n /** Compression quality of the generated image (for ``image/jpeg``\n only). */\n outputCompressionQuality?: number;\n /** Whether to add a watermark to the generated images. */\n addWatermark?: boolean;\n /** User specified labels to track billing usage. */\n labels?: Record<string, string>;\n /** The size of the largest dimension of the generated image.\n Supported sizes are 1K and 2K (not supported for Imagen 3 models). */\n imageSize?: string;\n /** Whether to use the prompt rewriting logic. */\n enhancePrompt?: boolean;\n}\n\n/** The parameters for generating images. */\nexport declare interface GenerateImagesParameters {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model: string;\n /** Text prompt that typically describes the images to output.\n */\n prompt: string;\n /** Configuration for generating images.\n */\n config?: GenerateImagesConfig;\n}\n\n/** An image. */\nexport declare interface Image {\n /** The Cloud Storage URI of the image. ``Image`` can contain a value\n for this field or the ``image_bytes`` field but not both. */\n gcsUri?: string;\n /** The image bytes data. ``Image`` can contain a value for this field\n or the ``gcs_uri`` field but not both.\n * @remarks Encoded as base64 string. */\n imageBytes?: string;\n /** The MIME type of the image. */\n mimeType?: string;\n}\n\n/** Safety attributes of a GeneratedImage or the user-provided prompt. */\nexport declare interface SafetyAttributes {\n /** List of RAI categories. */\n categories?: string[];\n /** List of scores of each categories. */\n scores?: number[];\n /** Internal use only. */\n contentType?: string;\n}\n\n/** An output image. */\nexport declare interface GeneratedImage {\n /** The output image data. */\n image?: Image;\n /** Responsible AI filter reason if the image is filtered out of the\n response. */\n raiFilteredReason?: string;\n /** Safety attributes of the image. Lists of RAI categories and their\n scores of each content. */\n safetyAttributes?: SafetyAttributes;\n /** The rewritten prompt used for the image generation if the prompt\n enhancer is enabled. */\n enhancedPrompt?: string;\n}\n\n/** The output images response. */\nexport class GenerateImagesResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** List of generated images. */\n generatedImages?: GeneratedImage[];\n /** Safety attributes of the positive prompt. Only populated if\n ``include_safety_attributes`` is set to True. */\n positivePromptSafetyAttributes?: SafetyAttributes;\n}\n\n/** Configuration for a Mask reference image. */\nexport declare interface MaskReferenceConfig {\n /** Prompts the model to generate a mask instead of you needing to\n provide one (unless MASK_MODE_USER_PROVIDED is used). */\n maskMode?: MaskReferenceMode;\n /** A list of up to 5 class ids to use for semantic segmentation.\n Automatically creates an image mask based on specific objects. */\n segmentationClasses?: number[];\n /** Dilation percentage of the mask provided.\n Float between 0 and 1. */\n maskDilation?: number;\n}\n\n/** Configuration for a Control reference image. */\nexport declare interface ControlReferenceConfig {\n /** The type of control reference image to use. */\n controlType?: ControlReferenceType;\n /** Defaults to False. When set to True, the control image will be\n computed by the model based on the control type. When set to False,\n the control image must be provided by the user. */\n enableControlImageComputation?: boolean;\n}\n\n/** Configuration for a Style reference image. */\nexport declare interface StyleReferenceConfig {\n /** A text description of the style to use for the generated image. */\n styleDescription?: string;\n}\n\n/** Configuration for a Subject reference image. */\nexport declare interface SubjectReferenceConfig {\n /** The subject type of a subject reference image. */\n subjectType?: SubjectReferenceType;\n /** Subject description for the image. */\n subjectDescription?: string;\n}\n\n/** Configuration for editing an image. */\nexport declare interface EditImageConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** Cloud Storage URI used to store the generated images. */\n outputGcsUri?: string;\n /** Description of what to discourage in the generated images. */\n negativePrompt?: string;\n /** Number of images to generate. */\n numberOfImages?: number;\n /** Aspect ratio of the generated images. Supported values are\n \"1:1\", \"3:4\", \"4:3\", \"9:16\", and \"16:9\". */\n aspectRatio?: string;\n /** Controls how much the model adheres to the text prompt. Large\n values increase output and prompt alignment, but may compromise image\n quality. */\n guidanceScale?: number;\n /** Random seed for image generation. This is not available when\n ``add_watermark`` is set to true. */\n seed?: number;\n /** Filter level for safety filtering. */\n safetyFilterLevel?: SafetyFilterLevel;\n /** Allows generation of people by the model. */\n personGeneration?: PersonGeneration;\n /** Whether to report the safety scores of each generated image and\n the positive prompt in the response. */\n includeSafetyAttributes?: boolean;\n /** Whether to include the Responsible AI filter reason if the image\n is filtered out of the response. */\n includeRaiReason?: boolean;\n /** Language of the text in the prompt. */\n language?: ImagePromptLanguage;\n /** MIME type of the generated image. */\n outputMimeType?: string;\n /** Compression quality of the generated image (for ``image/jpeg``\n only). */\n outputCompressionQuality?: number;\n /** Whether to add a watermark to the generated images. */\n addWatermark?: boolean;\n /** User specified labels to track billing usage. */\n labels?: Record<string, string>;\n /** Describes the editing mode for the request. */\n editMode?: EditMode;\n /** The number of sampling steps. A higher value has better image\n quality, while a lower value has better latency. */\n baseSteps?: number;\n}\n\n/** Response for the request to edit an image. */\nexport class EditImageResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** Generated images. */\n generatedImages?: GeneratedImage[];\n}\n\nexport class UpscaleImageResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** Generated images. */\n generatedImages?: GeneratedImage[];\n}\n\n/** An image of the product. */\nexport declare interface ProductImage {\n /** An image of the product to be recontextualized. */\n productImage?: Image;\n}\n\n/** A set of source input(s) for image recontextualization. */\nexport declare interface RecontextImageSource {\n /** A text prompt for guiding the model during image\n recontextualization. Not supported for Virtual Try-On. */\n prompt?: string;\n /** Image of the person or subject who will be wearing the\n product(s). */\n personImage?: Image;\n /** A list of product images. */\n productImages?: ProductImage[];\n}\n\n/** Configuration for recontextualizing an image. */\nexport declare interface RecontextImageConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** Number of images to generate. */\n numberOfImages?: number;\n /** The number of sampling steps. A higher value has better image\n quality, while a lower value has better latency. */\n baseSteps?: number;\n /** Cloud Storage URI used to store the generated images. */\n outputGcsUri?: string;\n /** Random seed for image generation. */\n seed?: number;\n /** Filter level for safety filtering. */\n safetyFilterLevel?: SafetyFilterLevel;\n /** Whether allow to generate person images, and restrict to specific\n ages. */\n personGeneration?: PersonGeneration;\n /** Whether to add a SynthID watermark to the generated images. */\n addWatermark?: boolean;\n /** MIME type of the generated image. */\n outputMimeType?: string;\n /** Compression quality of the generated image (for ``image/jpeg``\n only). */\n outputCompressionQuality?: number;\n /** Whether to use the prompt rewriting logic. */\n enhancePrompt?: boolean;\n /** User specified labels to track billing usage. */\n labels?: Record<string, string>;\n}\n\n/** The parameters for recontextualizing an image. */\nexport declare interface RecontextImageParameters {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model: string;\n /** A set of source input(s) for image recontextualization. */\n source: RecontextImageSource;\n /** Configuration for image recontextualization. */\n config?: RecontextImageConfig;\n}\n\n/** The output images response. */\nexport class RecontextImageResponse {\n /** List of generated images. */\n generatedImages?: GeneratedImage[];\n}\n\n/** An image mask representing a brush scribble. */\nexport declare interface ScribbleImage {\n /** The brush scribble to guide segmentation. Valid for the interactive mode. */\n image?: Image;\n}\n\n/** A set of source input(s) for image segmentation. */\nexport declare interface SegmentImageSource {\n /** A text prompt for guiding the model during image segmentation.\n Required for prompt mode and semantic mode, disallowed for other modes. */\n prompt?: string;\n /** The image to be segmented. */\n image?: Image;\n /** The brush scribble to guide segmentation.\n Required for the interactive mode, disallowed for other modes. */\n scribbleImage?: ScribbleImage;\n}\n\n/** Configuration for segmenting an image. */\nexport declare interface SegmentImageConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** The segmentation mode to use. */\n mode?: SegmentMode;\n /** The maximum number of predictions to return up to, by top\n confidence score. */\n maxPredictions?: number;\n /** The confidence score threshold for the detections as a decimal\n value. Only predictions with a confidence score higher than this\n threshold will be returned. */\n confidenceThreshold?: number;\n /** A decimal value representing how much dilation to apply to the\n masks. 0 for no dilation. 1.0 means the masked area covers the whole\n image. */\n maskDilation?: number;\n /** The binary color threshold to apply to the masks. The threshold\n can be set to a decimal value between 0 and 255 non-inclusive.\n Set to -1 for no binary color thresholding. */\n binaryColorThreshold?: number;\n /** User specified labels to track billing usage. */\n labels?: Record<string, string>;\n}\n\n/** The parameters for segmenting an image. */\nexport declare interface SegmentImageParameters {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model: string;\n /** A set of source input(s) for image segmentation. */\n source: SegmentImageSource;\n /** Configuration for image segmentation. */\n config?: SegmentImageConfig;\n}\n\n/** An entity representing the segmented area. */\nexport declare interface EntityLabel {\n /** The label of the segmented entity. */\n label?: string;\n /** The confidence score of the detected label. */\n score?: number;\n}\n\n/** A generated image mask. */\nexport declare interface GeneratedImageMask {\n /** The generated image mask. */\n mask?: Image;\n /** The detected entities on the segmented area. */\n labels?: EntityLabel[];\n}\n\n/** The output images response. */\nexport class SegmentImageResponse {\n /** List of generated image masks.\n */\n generatedMasks?: GeneratedImageMask[];\n}\n\n/** Optional parameters for models.get method. */\nexport declare interface GetModelConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\nexport declare interface GetModelParameters {\n model: string;\n /** Optional parameters for the request. */\n config?: GetModelConfig;\n}\n\n/** An endpoint where you deploy models. */\nexport declare interface Endpoint {\n /** Resource name of the endpoint. */\n name?: string;\n /** ID of the model that's deployed to the endpoint. */\n deployedModelId?: string;\n}\n\n/** A tuned machine learning model. */\nexport declare interface TunedModelInfo {\n /** ID of the base model that you want to tune. */\n baseModel?: string;\n /** Date and time when the base model was created. */\n createTime?: string;\n /** Date and time when the base model was last updated. */\n updateTime?: string;\n}\n\n/** Describes the machine learning model version checkpoint. */\nexport declare interface Checkpoint {\n /** The ID of the checkpoint.\n */\n checkpointId?: string;\n /** The epoch of the checkpoint.\n */\n epoch?: string;\n /** The step of the checkpoint.\n */\n step?: string;\n}\n\n/** A trained machine learning model. */\nexport declare interface Model {\n /** Resource name of the model. */\n name?: string;\n /** Display name of the model. */\n displayName?: string;\n /** Description of the model. */\n description?: string;\n /** Version ID of the model. A new version is committed when a new\n model version is uploaded or trained under an existing model ID. The\n version ID is an auto-incrementing decimal number in string\n representation. */\n version?: string;\n /** List of deployed models created from this base model. Note that a\n model could have been deployed to endpoints in different locations. */\n endpoints?: Endpoint[];\n /** Labels with user-defined metadata to organize your models. */\n labels?: Record<string, string>;\n /** Information about the tuned model from the base model. */\n tunedModelInfo?: TunedModelInfo;\n /** The maximum number of input tokens that the model can handle. */\n inputTokenLimit?: number;\n /** The maximum number of output tokens that the model can generate. */\n outputTokenLimit?: number;\n /** List of actions that are supported by the model. */\n supportedActions?: string[];\n /** The default checkpoint id of a model version.\n */\n defaultCheckpointId?: string;\n /** The checkpoints of the model. */\n checkpoints?: Checkpoint[];\n /** Temperature value used for sampling set when the dataset was saved.\n This value is used to tune the degree of randomness. */\n temperature?: number;\n /** The maximum temperature value used for sampling set when the\n dataset was saved. This value is used to tune the degree of randomness. */\n maxTemperature?: number;\n /** Optional. Specifies the nucleus sampling threshold. The model\n considers only the smallest set of tokens whose cumulative probability is\n at least `top_p`. This helps generate more diverse and less repetitive\n responses. For example, a `top_p` of 0.9 means the model considers tokens\n until the cumulative probability of the tokens to select from reaches 0.9.\n It's recommended to adjust either temperature or `top_p`, but not both. */\n topP?: number;\n /** Optional. Specifies the top-k sampling threshold. The model\n considers only the top k most probable tokens for the next token. This can\n be useful for generating more coherent and less random text. For example,\n a `top_k` of 40 means the model will choose the next word from the 40 most\n likely words. */\n topK?: number;\n /** Whether the model supports thinking features. If true, thoughts are\n returned only if the model supports thought and thoughts are available. */\n thinking?: boolean;\n}\n\nexport declare interface ListModelsConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n pageSize?: number;\n pageToken?: string;\n filter?: string;\n /** Set true to list base models, false to list tuned models. */\n queryBase?: boolean;\n}\n\nexport declare interface ListModelsParameters {\n config?: ListModelsConfig;\n}\n\nexport class ListModelsResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n nextPageToken?: string;\n models?: Model[];\n}\n\n/** Configuration for updating a tuned model. */\nexport declare interface UpdateModelConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n displayName?: string;\n description?: string;\n defaultCheckpointId?: string;\n}\n\n/** Configuration for updating a tuned model. */\nexport declare interface UpdateModelParameters {\n model: string;\n config?: UpdateModelConfig;\n}\n\n/** Configuration for deleting a tuned model. */\nexport declare interface DeleteModelConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for deleting a tuned model. */\nexport declare interface DeleteModelParameters {\n model: string;\n /** Optional parameters for the request. */\n config?: DeleteModelConfig;\n}\n\nexport class DeleteModelResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n}\n\n/** Generation config. */\nexport declare interface GenerationConfig {\n /** Optional. Config for model selection. */\n modelSelectionConfig?: ModelSelectionConfig;\n /** Output schema of the generated response. This is an alternative to\n `response_schema` that accepts [JSON Schema](https://json-schema.org/).\n */\n responseJsonSchema?: unknown;\n /** Optional. If enabled, audio timestamp will be included in the request to the model. This field is not supported in Gemini API. */\n audioTimestamp?: boolean;\n /** Optional. Number of candidates to generate. */\n candidateCount?: number;\n /** Optional. If enabled, the model will detect emotions and adapt its responses accordingly. This field is not supported in Gemini API. */\n enableAffectiveDialog?: boolean;\n /** Optional. Frequency penalties. */\n frequencyPenalty?: number;\n /** Optional. Logit probabilities. */\n logprobs?: number;\n /** Optional. The maximum number of output tokens to generate per message. */\n maxOutputTokens?: number;\n /** Optional. If specified, the media resolution specified will be used. */\n mediaResolution?: MediaResolution;\n /** Optional. Positive penalties. */\n presencePenalty?: number;\n /** Optional. If true, export the logprobs results in response. */\n responseLogprobs?: boolean;\n /** Optional. Output response mimetype of the generated candidate text. Supported mimetype: - `text/plain`: (default) Text output. - `application/json`: JSON response in the candidates. The model needs to be prompted to output the appropriate response type, otherwise the behavior is undefined. This is a preview feature. */\n responseMimeType?: string;\n /** Optional. The modalities of the response. */\n responseModalities?: Modality[];\n /** Optional. The `Schema` object allows the definition of input and output data types. These types can be objects, but also primitives and arrays. Represents a select subset of an [OpenAPI 3.0 schema object](https://spec.openapis.org/oas/v3.0.3#schema). If set, a compatible response_mime_type must also be set. Compatible mimetypes: `application/json`: Schema for JSON response. */\n responseSchema?: Schema;\n /** Optional. Routing configuration. This field is not supported in Gemini API. */\n routingConfig?: GenerationConfigRoutingConfig;\n /** Optional. Seed. */\n seed?: number;\n /** Optional. The speech generation config. */\n speechConfig?: SpeechConfig;\n /** Optional. Stop sequences. */\n stopSequences?: string[];\n /** Optional. Controls the randomness of predictions. */\n temperature?: number;\n /** Optional. Config for thinking features. An error will be returned if this field is set for models that don't support thinking. */\n thinkingConfig?: ThinkingConfig;\n /** Optional. If specified, top-k sampling will be used. */\n topK?: number;\n /** Optional. If specified, nucleus sampling will be used. */\n topP?: number;\n /** Optional. Enables enhanced civic answers. It may not be available for all models. This field is not supported in Vertex AI. */\n enableEnhancedCivicAnswers?: boolean;\n}\n\n/** Config for the count_tokens method. */\nexport declare interface CountTokensConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** Instructions for the model to steer it toward better performance.\n */\n systemInstruction?: ContentUnion;\n /** Code that enables the system to interact with external systems to\n perform an action outside of the knowledge and scope of the model.\n */\n tools?: Tool[];\n /** Configuration that the model uses to generate the response. Not\n supported by the Gemini Developer API.\n */\n generationConfig?: GenerationConfig;\n}\n\n/** Parameters for counting tokens. */\nexport declare interface CountTokensParameters {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model: string;\n /** Input content. */\n contents: ContentListUnion;\n /** Configuration for counting tokens. */\n config?: CountTokensConfig;\n}\n\n/** Response for counting tokens. */\nexport class CountTokensResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** Total number of tokens. */\n totalTokens?: number;\n /** Number of tokens in the cached part of the prompt (the cached content). */\n cachedContentTokenCount?: number;\n}\n\n/** Optional parameters for computing tokens. */\nexport declare interface ComputeTokensConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for computing tokens. */\nexport declare interface ComputeTokensParameters {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model: string;\n /** Input content. */\n contents: ContentListUnion;\n /** Optional parameters for the request.\n */\n config?: ComputeTokensConfig;\n}\n\n/** Tokens info with a list of tokens and the corresponding list of token ids. */\nexport declare interface TokensInfo {\n /** Optional fields for the role from the corresponding Content. */\n role?: string;\n /** A list of token ids from the input. */\n tokenIds?: string[];\n /** A list of tokens from the input.\n * @remarks Encoded as base64 string. */\n tokens?: string[];\n}\n\n/** Response for computing tokens. */\nexport class ComputeTokensResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** Lists of tokens info from the input. A ComputeTokensRequest could have multiple instances with a prompt in each instance. We also need to return lists of tokens info for the request with multiple instances. */\n tokensInfo?: TokensInfo[];\n}\n\n/** A generated video. */\nexport declare interface Video {\n /** Path to another storage. */\n uri?: string;\n /** Video bytes.\n * @remarks Encoded as base64 string. */\n videoBytes?: string;\n /** Video encoding, for example ``video/mp4``. */\n mimeType?: string;\n}\n\n/** A set of source input(s) for video generation. */\nexport declare interface GenerateVideosSource {\n /** The text prompt for generating the videos.\n Optional if image or video is provided. */\n prompt?: string;\n /** The input image for generating the videos.\n Optional if prompt is provided. Not allowed if video is provided. */\n image?: Image;\n /** The input video for video extension use cases.\n Optional if prompt is provided. Not allowed if image is provided. */\n video?: Video;\n}\n\n/** A reference image for video generation. */\nexport declare interface VideoGenerationReferenceImage {\n /** The reference image. */\n image?: Image;\n /** The type of the reference image, which defines how the reference\n image will be used to generate the video. */\n referenceType?: VideoGenerationReferenceType;\n}\n\n/** A mask for video generation. */\nexport declare interface VideoGenerationMask {\n /** The image mask to use for generating videos. */\n image?: Image;\n /** Describes how the mask will be used. Inpainting masks must\n match the aspect ratio of the input video. Outpainting masks can be\n either 9:16 or 16:9. */\n maskMode?: VideoGenerationMaskMode;\n}\n\n/** Configuration for generating videos. */\nexport declare interface GenerateVideosConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** Number of output videos. */\n numberOfVideos?: number;\n /** The gcs bucket where to save the generated videos. */\n outputGcsUri?: string;\n /** Frames per second for video generation. */\n fps?: number;\n /** Duration of the clip for video generation in seconds. */\n durationSeconds?: number;\n /** The RNG seed. If RNG seed is exactly same for each request with\n unchanged inputs, the prediction results will be consistent. Otherwise,\n a random RNG seed will be used each time to produce a different\n result. */\n seed?: number;\n /** The aspect ratio for the generated video. 16:9 (landscape) and\n 9:16 (portrait) are supported. */\n aspectRatio?: string;\n /** The resolution for the generated video. 720p and 1080p are\n supported. */\n resolution?: string;\n /** Whether allow to generate person videos, and restrict to specific\n ages. Supported values are: dont_allow, allow_adult. */\n personGeneration?: string;\n /** The pubsub topic where to publish the video generation\n progress. */\n pubsubTopic?: string;\n /** Explicitly state what should not be included in the generated\n videos. */\n negativePrompt?: string;\n /** Whether to use the prompt rewriting logic. */\n enhancePrompt?: boolean;\n /** Whether to generate audio along with the video. */\n generateAudio?: boolean;\n /** Image to use as the last frame of generated videos.\n Only supported for image to video use cases. */\n lastFrame?: Image;\n /** The images to use as the references to generate the videos.\n If this field is provided, the text prompt field must also be provided.\n The image, video, or last_frame field are not supported. Each image must\n be associated with a type. Veo 2 supports up to 3 asset images *or* 1\n style image. */\n referenceImages?: VideoGenerationReferenceImage[];\n /** The mask to use for generating videos. */\n mask?: VideoGenerationMask;\n /** Compression quality of the generated videos. */\n compressionQuality?: VideoCompressionQuality;\n}\n\n/** Class that represents the parameters for generating videos. */\nexport declare interface GenerateVideosParameters {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model: string;\n /** The text prompt for generating the videos.\n Optional if image or video is provided. */\n prompt?: string;\n /** The input image for generating the videos.\n Optional if prompt is provided. Not allowed if video is provided. */\n image?: Image;\n /** The input video for video extension use cases.\n Optional if prompt is provided. Not allowed if image is provided. */\n video?: Video;\n /** A set of source input(s) for video generation. */\n source?: GenerateVideosSource;\n /** Configuration for generating videos. */\n config?: GenerateVideosConfig;\n}\n\n/** A generated video. */\nexport declare interface GeneratedVideo {\n /** The output video */\n video?: Video;\n}\n\n/** Response with generated videos. */\nexport class GenerateVideosResponse {\n /** List of the generated videos */\n generatedVideos?: GeneratedVideo[];\n /** Returns if any videos were filtered due to RAI policies. */\n raiMediaFilteredCount?: number;\n /** Returns rai failure reasons if any. */\n raiMediaFilteredReasons?: string[];\n}\n\n/** A long-running operation. */\nexport declare interface Operation<T> {\n /** The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`. */\n name?: string;\n /** Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata. Any method that returns a long-running operation should document the metadata type, if any. */\n metadata?: Record<string, unknown>;\n /** If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available. */\n done?: boolean;\n /** The error result of the operation in case of failure or cancellation. */\n error?: Record<string, unknown>;\n /** The response if the operation is successful. */\n response?: T;\n /**\n * Instantiates an Operation of the same type as the one being called with the fields set from the API response.\n * @internal\n */\n _fromAPIResponse({\n apiResponse,\n _isVertexAI,\n }: OperationFromAPIResponseParameters): Operation<T>;\n}\n\n/** A video generation operation. */\nexport class GenerateVideosOperation\n implements Operation<GenerateVideosResponse>\n{\n /** The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`. */\n name?: string;\n /** Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata. Any method that returns a long-running operation should document the metadata type, if any. */\n metadata?: Record<string, unknown>;\n /** If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available. */\n done?: boolean;\n /** The error result of the operation in case of failure or cancellation. */\n error?: Record<string, unknown>;\n /** The generated videos. */\n response?: GenerateVideosResponse;\n\n /**\n * Instantiates an Operation of the same type as the one being called with the fields set from the API response.\n * @internal\n */\n _fromAPIResponse({\n apiResponse,\n _isVertexAI,\n }: OperationFromAPIResponseParameters): Operation<GenerateVideosResponse> {\n const operation = new GenerateVideosOperation();\n let response;\n const op = apiResponse as unknown as GenerateVideosOperation;\n\n if (_isVertexAI) {\n response = generateVideosOperationFromVertex(op);\n } else {\n response = generateVideosOperationFromMldev(op);\n }\n Object.assign(operation, response);\n return operation;\n }\n /** The full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n}\n\n/** Optional parameters for tunings.get method. */\nexport declare interface GetTuningJobConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for the get method. */\nexport declare interface GetTuningJobParameters {\n name: string;\n /** Optional parameters for the request. */\n config?: GetTuningJobConfig;\n}\n\n/** TunedModelCheckpoint for the Tuned Model of a Tuning Job. */\nexport declare interface TunedModelCheckpoint {\n /** The ID of the checkpoint.\n */\n checkpointId?: string;\n /** The epoch of the checkpoint.\n */\n epoch?: string;\n /** The step of the checkpoint.\n */\n step?: string;\n /** The Endpoint resource name that the checkpoint is deployed to.\n Format: `projects/{project}/locations/{location}/endpoints/{endpoint}`.\n */\n endpoint?: string;\n}\n\n/** TunedModel for the Tuned Model of a Tuning Job. */\nexport declare interface TunedModel {\n /** Output only. The resource name of the TunedModel.\n Format: `projects/{project}/locations/{location}/models/{model}@{version_id}`\n When tuning from a base model, the version_id will be 1.\n For continuous tuning, the version id will be incremented by 1 from the\n last version id in the parent model. E.g., `projects/{project}/locations/{location}/models/{model}@{last_version_id + 1}`\n */\n model?: string;\n /** Output only. A resource name of an Endpoint.\n Format: `projects/{project}/locations/{location}/endpoints/{endpoint}`.\n */\n endpoint?: string;\n /** The checkpoints associated with this TunedModel.\n This field is only populated for tuning jobs that enable intermediate\n checkpoints. */\n checkpoints?: TunedModelCheckpoint[];\n}\n\n/** Hyperparameters for SFT. This data type is not supported in Gemini API. */\nexport declare interface SupervisedHyperParameters {\n /** Optional. Adapter size for tuning. */\n adapterSize?: AdapterSize;\n /** Optional. Batch size for tuning. This feature is only available for open source models. */\n batchSize?: string;\n /** Optional. Number of complete passes the model makes over the entire training dataset during training. */\n epochCount?: string;\n /** Optional. Learning rate for tuning. Mutually exclusive with `learning_rate_multiplier`. This feature is only available for open source models. */\n learningRate?: number;\n /** Optional. Multiplier for adjusting the default learning rate. Mutually exclusive with `learning_rate`. This feature is only available for 1P models. */\n learningRateMultiplier?: number;\n}\n\n/** Supervised tuning spec for tuning. */\nexport declare interface SupervisedTuningSpec {\n /** Optional. If set to true, disable intermediate checkpoints for SFT and only the last checkpoint will be exported. Otherwise, enable intermediate checkpoints for SFT. Default is false. */\n exportLastCheckpointOnly?: boolean;\n /** Optional. Hyperparameters for SFT. */\n hyperParameters?: SupervisedHyperParameters;\n /** Required. Training dataset used for tuning. The dataset can be specified as either a Cloud Storage path to a JSONL file or as the resource name of a Vertex Multimodal Dataset. */\n trainingDatasetUri?: string;\n /** Tuning mode. */\n tuningMode?: TuningMode;\n /** Optional. Validation dataset used for tuning. The dataset can be specified as either a Cloud Storage path to a JSONL file or as the resource name of a Vertex Multimodal Dataset. */\n validationDatasetUri?: string;\n}\n\n/** Hyperparameters for Preference Optimization. This data type is not supported in Gemini API. */\nexport declare interface PreferenceOptimizationHyperParameters {\n /** Optional. Adapter size for preference optimization. */\n adapterSize?: AdapterSize;\n /** Optional. Weight for KL Divergence regularization. */\n beta?: number;\n /** Optional. Number of complete passes the model makes over the entire training dataset during training. */\n epochCount?: string;\n /** Optional. Multiplier for adjusting the default learning rate. */\n learningRateMultiplier?: number;\n}\n\n/** Preference optimization tuning spec for tuning. */\nexport declare interface PreferenceOptimizationSpec {\n /** Optional. If set to true, disable intermediate checkpoints for Preference Optimization and only the last checkpoint will be exported. Otherwise, enable intermediate checkpoints for Preference Optimization. Default is false. */\n exportLastCheckpointOnly?: boolean;\n /** Optional. Hyperparameters for Preference Optimization. */\n hyperParameters?: PreferenceOptimizationHyperParameters;\n /** Required. Cloud Storage path to file containing training dataset for preference optimization tuning. The dataset must be formatted as a JSONL file. */\n trainingDatasetUri?: string;\n /** Optional. Cloud Storage path to file containing validation dataset for preference optimization tuning. The dataset must be formatted as a JSONL file. */\n validationDatasetUri?: string;\n}\n\n/** Hyperparameters for Distillation. This data type is not supported in Gemini API. */\nexport declare interface DistillationHyperParameters {\n /** Optional. Adapter size for distillation. */\n adapterSize?: AdapterSize;\n /** Optional. Number of complete passes the model makes over the entire training dataset during training. */\n epochCount?: string;\n /** Optional. Multiplier for adjusting the default learning rate. */\n learningRateMultiplier?: number;\n}\n\n/** Distillation tuning spec for tuning. */\nexport declare interface DistillationSpec {\n /** The GCS URI of the prompt dataset to use during distillation. */\n promptDatasetUri?: string;\n /** The base teacher model that is being distilled. See [Supported models](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/tuning#supported_models). */\n baseTeacherModel?: string;\n /** Optional. Hyperparameters for Distillation. */\n hyperParameters?: DistillationHyperParameters;\n /** Deprecated. A path in a Cloud Storage bucket, which will be treated as the root output directory of the distillation pipeline. It is used by the system to generate the paths of output artifacts. */\n pipelineRootDirectory?: string;\n /** The student model that is being tuned, e.g., \"google/gemma-2b-1.1-it\". Deprecated. Use base_model instead. */\n studentModel?: string;\n /** Deprecated. Cloud Storage path to file containing training dataset for tuning. The dataset must be formatted as a JSONL file. */\n trainingDatasetUri?: string;\n /** The resource name of the Tuned teacher model. Format: `projects/{project}/locations/{location}/models/{model}`. */\n tunedTeacherModelSource?: string;\n /** Optional. Cloud Storage path to file containing validation dataset for tuning. The dataset must be formatted as a JSONL file. */\n validationDatasetUri?: string;\n}\n\n/** The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors). This data type is not supported in Gemini API. */\nexport declare interface GoogleRpcStatus {\n /** The status code, which should be an enum value of google.rpc.Code. */\n code?: number;\n /** A list of messages that carry the error details. There is a common set of message types for APIs to use. */\n details?: Record<string, unknown>[];\n /** A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the google.rpc.Status.details field, or localized by the client. */\n message?: string;\n}\n\n/** A pre-tuned model for continuous tuning. This data type is not supported in Gemini API. */\nexport declare interface PreTunedModel {\n /** Output only. The name of the base model this PreTunedModel was tuned from. */\n baseModel?: string;\n /** Optional. The source checkpoint id. If not specified, the default checkpoint will be used. */\n checkpointId?: string;\n /** The resource name of the Model. E.g., a model resource name with a specified version id or alias: `projects/{project}/locations/{location}/models/{model}@{version_id}` `projects/{project}/locations/{location}/models/{model}@{alias}` Or, omit the version id to use the default version: `projects/{project}/locations/{location}/models/{model}` */\n tunedModelName?: string;\n}\n\n/** Dataset bucket used to create a histogram for the distribution given a population of values. This data type is not supported in Gemini API. */\nexport declare interface DatasetDistributionDistributionBucket {\n /** Output only. Number of values in the bucket. */\n count?: string;\n /** Output only. Left bound of the bucket. */\n left?: number;\n /** Output only. Right bound of the bucket. */\n right?: number;\n}\n\n/** Distribution computed over a tuning dataset. This data type is not supported in Gemini API. */\nexport declare interface DatasetDistribution {\n /** Output only. Defines the histogram bucket. */\n buckets?: DatasetDistributionDistributionBucket[];\n /** Output only. The maximum of the population values. */\n max?: number;\n /** Output only. The arithmetic mean of the values in the population. */\n mean?: number;\n /** Output only. The median of the values in the population. */\n median?: number;\n /** Output only. The minimum of the population values. */\n min?: number;\n /** Output only. The 5th percentile of the values in the population. */\n p5?: number;\n /** Output only. The 95th percentile of the values in the population. */\n p95?: number;\n /** Output only. Sum of a given population of values. */\n sum?: number;\n}\n\n/** Statistics computed over a tuning dataset. This data type is not supported in Gemini API. */\nexport declare interface DatasetStats {\n /** Output only. Number of billable characters in the tuning dataset. */\n totalBillableCharacterCount?: string;\n /** Output only. Number of tuning characters in the tuning dataset. */\n totalTuningCharacterCount?: string;\n /** Output only. Number of examples in the tuning dataset. */\n tuningDatasetExampleCount?: string;\n /** Output only. Number of tuning steps for this Tuning Job. */\n tuningStepCount?: string;\n /** Output only. Sample user messages in the training dataset uri. */\n userDatasetExamples?: Content[];\n /** Output only. Dataset distributions for the user input tokens. */\n userInputTokenDistribution?: DatasetDistribution;\n /** Output only. Dataset distributions for the messages per example. */\n userMessagePerExampleDistribution?: DatasetDistribution;\n /** Output only. Dataset distributions for the user output tokens. */\n userOutputTokenDistribution?: DatasetDistribution;\n}\n\n/** Statistics computed for datasets used for distillation. This data type is not supported in Gemini API. */\nexport declare interface DistillationDataStats {\n /** Output only. Statistics computed for the training dataset. */\n trainingDatasetStats?: DatasetStats;\n}\n\n/** Completion and its preference score. This data type is not supported in Gemini API. */\nexport declare interface GeminiPreferenceExampleCompletion {\n /** Single turn completion for the given prompt. */\n completion?: Content;\n /** The score for the given completion. */\n score?: number;\n}\n\n/** Input example for preference optimization. This data type is not supported in Gemini API. */\nexport declare interface GeminiPreferenceExample {\n /** List of completions for a given prompt. */\n completions?: GeminiPreferenceExampleCompletion[];\n /** Multi-turn contents that represents the Prompt. */\n contents?: Content[];\n}\n\n/** Statistics computed for datasets used for preference optimization. This data type is not supported in Gemini API. */\nexport declare interface PreferenceOptimizationDataStats {\n /** Output only. Dataset distributions for scores variance per example. */\n scoreVariancePerExampleDistribution?: DatasetDistribution;\n /** Output only. Dataset distributions for scores. */\n scoresDistribution?: DatasetDistribution;\n /** Output only. Number of billable tokens in the tuning dataset. */\n totalBillableTokenCount?: string;\n /** Output only. Number of examples in the tuning dataset. */\n tuningDatasetExampleCount?: string;\n /** Output only. Number of tuning steps for this Tuning Job. */\n tuningStepCount?: string;\n /** Output only. Sample user examples in the training dataset. */\n userDatasetExamples?: GeminiPreferenceExample[];\n /** Output only. Dataset distributions for the user input tokens. */\n userInputTokenDistribution?: DatasetDistribution;\n /** Output only. Dataset distributions for the user output tokens. */\n userOutputTokenDistribution?: DatasetDistribution;\n}\n\n/** Dataset bucket used to create a histogram for the distribution given a population of values. This data type is not supported in Gemini API. */\nexport declare interface SupervisedTuningDatasetDistributionDatasetBucket {\n /** Output only. Number of values in the bucket. */\n count?: number;\n /** Output only. Left bound of the bucket. */\n left?: number;\n /** Output only. Right bound of the bucket. */\n right?: number;\n}\n\n/** Dataset distribution for Supervised Tuning. This data type is not supported in Gemini API. */\nexport declare interface SupervisedTuningDatasetDistribution {\n /** Output only. Sum of a given population of values that are billable. */\n billableSum?: string;\n /** Output only. Defines the histogram bucket. */\n buckets?: SupervisedTuningDatasetDistributionDatasetBucket[];\n /** Output only. The maximum of the population values. */\n max?: number;\n /** Output only. The arithmetic mean of the values in the population. */\n mean?: number;\n /** Output only. The median of the values in the population. */\n median?: number;\n /** Output only. The minimum of the population values. */\n min?: number;\n /** Output only. The 5th percentile of the values in the population. */\n p5?: number;\n /** Output only. The 95th percentile of the values in the population. */\n p95?: number;\n /** Output only. Sum of a given population of values. */\n sum?: string;\n}\n\n/** Tuning data statistics for Supervised Tuning. This data type is not supported in Gemini API. */\nexport declare interface SupervisedTuningDataStats {\n /** Output only. For each index in `truncated_example_indices`, the user-facing reason why the example was dropped. */\n droppedExampleReasons?: string[];\n /** Output only. Number of billable characters in the tuning dataset. */\n totalBillableCharacterCount?: string;\n /** Output only. Number of billable tokens in the tuning dataset. */\n totalBillableTokenCount?: string;\n /** Output only. The number of examples in the dataset that have been dropped. An example can be dropped for reasons including: too many tokens, contains an invalid image, contains too many images, etc. */\n totalTruncatedExampleCount?: string;\n /** Output only. Number of tuning characters in the tuning dataset. */\n totalTuningCharacterCount?: string;\n /** Output only. A partial sample of the indices (starting from 1) of the dropped examples. */\n truncatedExampleIndices?: string[];\n /** Output only. Number of examples in the tuning dataset. */\n tuningDatasetExampleCount?: string;\n /** Output only. Number of tuning steps for this Tuning Job. */\n tuningStepCount?: string;\n /** Output only. Sample user messages in the training dataset uri. */\n userDatasetExamples?: Content[];\n /** Output only. Dataset distributions for the user input tokens. */\n userInputTokenDistribution?: SupervisedTuningDatasetDistribution;\n /** Output only. Dataset distributions for the messages per example. */\n userMessagePerExampleDistribution?: SupervisedTuningDatasetDistribution;\n /** Output only. Dataset distributions for the user output tokens. */\n userOutputTokenDistribution?: SupervisedTuningDatasetDistribution;\n}\n\n/** The tuning data statistic values for TuningJob. This data type is not supported in Gemini API. */\nexport declare interface TuningDataStats {\n /** Output only. Statistics for distillation. */\n distillationDataStats?: DistillationDataStats;\n /** Output only. Statistics for preference optimization. */\n preferenceOptimizationDataStats?: PreferenceOptimizationDataStats;\n /** The SFT Tuning data stats. */\n supervisedTuningDataStats?: SupervisedTuningDataStats;\n}\n\n/** Represents a customer-managed encryption key spec that can be applied to a top-level resource. This data type is not supported in Gemini API. */\nexport declare interface EncryptionSpec {\n /** Required. The Cloud KMS resource identifier of the customer managed encryption key used to protect a resource. Has the form: `projects/my-project/locations/my-region/keyRings/my-kr/cryptoKeys/my-key`. The key needs to be in the same region as where the compute resource is created. */\n kmsKeyName?: string;\n}\n\n/** Tuning spec for Partner models. This data type is not supported in Gemini API. */\nexport declare interface PartnerModelTuningSpec {\n /** Hyperparameters for tuning. The accepted hyper_parameters and their valid range of values will differ depending on the base model. */\n hyperParameters?: Record<string, unknown>;\n /** Required. Cloud Storage path to file containing training dataset for tuning. The dataset must be formatted as a JSONL file. */\n trainingDatasetUri?: string;\n /** Optional. Cloud Storage path to file containing validation dataset for tuning. The dataset must be formatted as a JSONL file. */\n validationDatasetUri?: string;\n}\n\n/** Hyperparameters for Veo. This data type is not supported in Gemini API. */\nexport declare interface VeoHyperParameters {\n /** Optional. Number of complete passes the model makes over the entire training dataset during training. */\n epochCount?: string;\n /** Optional. Multiplier for adjusting the default learning rate. */\n learningRateMultiplier?: number;\n /** Optional. The tuning task. Either I2V or T2V. */\n tuningTask?: TuningTask;\n}\n\n/** Tuning Spec for Veo Model Tuning. This data type is not supported in Gemini API. */\nexport declare interface VeoTuningSpec {\n /** Optional. Hyperparameters for Veo. */\n hyperParameters?: VeoHyperParameters;\n /** Required. Training dataset used for tuning. The dataset can be specified as either a Cloud Storage path to a JSONL file or as the resource name of a Vertex Multimodal Dataset. */\n trainingDatasetUri?: string;\n /** Optional. Validation dataset used for tuning. The dataset can be specified as either a Cloud Storage path to a JSONL file or as the resource name of a Vertex Multimodal Dataset. */\n validationDatasetUri?: string;\n}\n\n/** A tuning job. */\nexport declare interface TuningJob {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** Output only. Identifier. Resource name of a TuningJob. Format: `projects/{project}/locations/{location}/tuningJobs/{tuning_job}` */\n name?: string;\n /** Output only. The detailed state of the job. */\n state?: JobState;\n /** Output only. Time when the TuningJob was created. */\n createTime?: string;\n /** Output only. Time when the TuningJob for the first time entered the `JOB_STATE_RUNNING` state. */\n startTime?: string;\n /** Output only. Time when the TuningJob entered any of the following JobStates: `JOB_STATE_SUCCEEDED`, `JOB_STATE_FAILED`, `JOB_STATE_CANCELLED`, `JOB_STATE_EXPIRED`. */\n endTime?: string;\n /** Output only. Time when the TuningJob was most recently updated. */\n updateTime?: string;\n /** Output only. Only populated when job's state is `JOB_STATE_FAILED` or `JOB_STATE_CANCELLED`. */\n error?: GoogleRpcStatus;\n /** Optional. The description of the TuningJob. */\n description?: string;\n /** The base model that is being tuned. See [Supported models](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/tuning#supported_models). */\n baseModel?: string;\n /** Output only. The tuned model resources associated with this TuningJob. */\n tunedModel?: TunedModel;\n /** The pre-tuned model for continuous tuning. */\n preTunedModel?: PreTunedModel;\n /** Tuning Spec for Supervised Fine Tuning. */\n supervisedTuningSpec?: SupervisedTuningSpec;\n /** Tuning Spec for Preference Optimization. */\n preferenceOptimizationSpec?: PreferenceOptimizationSpec;\n /** Tuning Spec for Distillation. */\n distillationSpec?: DistillationSpec;\n /** Output only. The tuning data statistics associated with this TuningJob. */\n tuningDataStats?: TuningDataStats;\n /** Customer-managed encryption key options for a TuningJob. If this is set, then all resources created by the TuningJob will be encrypted with the provided encryption key. */\n encryptionSpec?: EncryptionSpec;\n /** Tuning Spec for open sourced and third party Partner models. */\n partnerModelTuningSpec?: PartnerModelTuningSpec;\n /** Optional. The user-provided path to custom model weights. Set this field to tune a custom model. The path must be a Cloud Storage directory that contains the model weights in .safetensors format along with associated model metadata files. If this field is set, the base_model field must still be set to indicate which base model the custom model is derived from. This feature is only available for open source models. */\n customBaseModel?: string;\n /** Output only. The Experiment associated with this TuningJob. */\n experiment?: string;\n /** Optional. The labels with user-defined metadata to organize TuningJob and generated resources such as Model and Endpoint. Label keys and values can be no longer than 64 characters (Unicode codepoints), can only contain lowercase letters, numeric characters, underscores and dashes. International characters are allowed. See https://goo.gl/xmQnxf for more information and examples of labels. */\n labels?: Record<string, string>;\n /** Optional. Cloud Storage path to the directory where tuning job outputs are written to. This field is only available and required for open source models. */\n outputUri?: string;\n /** Output only. The resource name of the PipelineJob associated with the TuningJob. Format: `projects/{project}/locations/{location}/pipelineJobs/{pipeline_job}`. */\n pipelineJob?: string;\n /** The service account that the tuningJob workload runs as. If not specified, the Vertex AI Secure Fine-Tuned Service Agent in the project will be used. See https://cloud.google.com/iam/docs/service-agents#vertex-ai-secure-fine-tuning-service-agent Users starting the pipeline must have the `iam.serviceAccounts.actAs` permission on this service account. */\n serviceAccount?: string;\n /** Optional. The display name of the TunedModel. The name can be up to 128 characters long and can consist of any UTF-8 characters. For continuous tuning, tuned_model_display_name will by default use the same display name as the pre-tuned model. If a new display name is provided, the tuning job will create a new model instead of a new version. */\n tunedModelDisplayName?: string;\n /** Tuning Spec for Veo Tuning. */\n veoTuningSpec?: VeoTuningSpec;\n}\n\n/** Configuration for the list tuning jobs method. */\nexport declare interface ListTuningJobsConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n pageSize?: number;\n pageToken?: string;\n filter?: string;\n}\n\n/** Parameters for the list tuning jobs method. */\nexport declare interface ListTuningJobsParameters {\n config?: ListTuningJobsConfig;\n}\n\n/** Response for the list tuning jobs method. */\nexport class ListTuningJobsResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** A token to retrieve the next page of results. Pass to ListTuningJobsRequest.page_token to obtain that page. */\n nextPageToken?: string;\n /** List of TuningJobs in the requested page. */\n tuningJobs?: TuningJob[];\n}\n\n/** Optional parameters for tunings.cancel method. */\nexport declare interface CancelTuningJobConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for the cancel method. */\nexport declare interface CancelTuningJobParameters {\n /** The resource name of the tuning job. */\n name: string;\n /** Optional parameters for the request. */\n config?: CancelTuningJobConfig;\n}\n\n/** Empty response for tunings.cancel method. */\nexport class CancelTuningJobResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n}\n\n/** A single example for tuning. This data type is not supported in Vertex AI. */\nexport declare interface TuningExample {\n /** Required. The expected model output. */\n output?: string;\n /** Optional. Text model input. */\n textInput?: string;\n}\n\n/** Supervised fine-tuning training dataset. */\nexport declare interface TuningDataset {\n /** GCS URI of the file containing training dataset in JSONL format. */\n gcsUri?: string;\n /** The resource name of the Vertex Multimodal Dataset that is used as training dataset. Example: 'projects/my-project-id-or-number/locations/my-location/datasets/my-dataset-id'. */\n vertexDatasetResource?: string;\n /** Inline examples with simple input/output text. */\n examples?: TuningExample[];\n}\n\nexport declare interface TuningValidationDataset {\n /** GCS URI of the file containing validation dataset in JSONL format. */\n gcsUri?: string;\n /** The resource name of the Vertex Multimodal Dataset that is used as validation dataset. Example: 'projects/my-project-id-or-number/locations/my-location/datasets/my-dataset-id'. */\n vertexDatasetResource?: string;\n}\n\n/** Fine-tuning job creation request - optional fields. */\nexport declare interface CreateTuningJobConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** The method to use for tuning (SUPERVISED_FINE_TUNING or PREFERENCE_TUNING or DISTILLATION). If not set, the default method (SFT) will be used. */\n method?: TuningMethod;\n /** Validation dataset for tuning. The dataset must be formatted as a JSONL file. */\n validationDataset?: TuningValidationDataset;\n /** The display name of the tuned Model. The name can be up to 128 characters long and can consist of any UTF-8 characters. */\n tunedModelDisplayName?: string;\n /** The description of the TuningJob */\n description?: string;\n /** Number of complete passes the model makes over the entire training dataset during training. */\n epochCount?: number;\n /** Multiplier for adjusting the default learning rate. 1P models only. Mutually exclusive with learning_rate. */\n learningRateMultiplier?: number;\n /** If set to true, disable intermediate checkpoints and only the last checkpoint will be exported. Otherwise, enable intermediate checkpoints. */\n exportLastCheckpointOnly?: boolean;\n /** The optional checkpoint id of the pre-tuned model to use for tuning, if applicable. */\n preTunedModelCheckpointId?: string;\n /** Adapter size for tuning. */\n adapterSize?: AdapterSize;\n /** Tuning mode for SFT tuning. */\n tuningMode?: TuningMode;\n /** Custom base model for tuning. This is only supported for OSS models in Vertex. */\n customBaseModel?: string;\n /** The batch size hyperparameter for tuning. This is only supported for OSS models in Vertex. */\n batchSize?: number;\n /** The learning rate for tuning. OSS models only. Mutually exclusive with learning_rate_multiplier. */\n learningRate?: number;\n /** Optional. The labels with user-defined metadata to organize TuningJob and generated resources such as Model and Endpoint. Label keys and values can be no longer than 64 characters (Unicode codepoints), can only contain lowercase letters, numeric characters, underscores and dashes. International characters are allowed. See https://goo.gl/xmQnxf for more information and examples of labels. */\n labels?: Record<string, string>;\n /** Weight for KL Divergence regularization, Preference Optimization tuning only. */\n beta?: number;\n /** The base teacher model that is being distilled. Distillation only. */\n baseTeacherModel?: string;\n /** The resource name of the Tuned teacher model. Distillation only. */\n tunedTeacherModelSource?: string;\n /** Multiplier for adjusting the weight of the SFT loss. Distillation only. */\n sftLossWeightMultiplier?: number;\n /** The Google Cloud Storage location where the tuning job outputs are written. */\n outputUri?: string;\n /** The encryption spec of the tuning job. Customer-managed encryption key options for a TuningJob. If this is set, then all resources created by the TuningJob will be encrypted with provided encryption key. */\n encryptionSpec?: EncryptionSpec;\n}\n\n/** Fine-tuning job creation parameters - optional fields. */\nexport declare interface CreateTuningJobParametersPrivate {\n /** The base model that is being tuned, e.g., \"gemini-2.5-flash\". */\n baseModel?: string;\n /** The PreTunedModel that is being tuned. */\n preTunedModel?: PreTunedModel;\n /** Cloud Storage path to file containing training dataset for tuning. The dataset must be formatted as a JSONL file. */\n trainingDataset: TuningDataset;\n /** Configuration for the tuning job. */\n config?: CreateTuningJobConfig;\n}\n\n/** A long-running operation. */\nexport declare interface TuningOperation {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`. */\n name?: string;\n /** Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata. Any method that returns a long-running operation should document the metadata type, if any. */\n metadata?: Record<string, unknown>;\n /** If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available. */\n done?: boolean;\n /** The error result of the operation in case of failure or cancellation. */\n error?: Record<string, unknown>;\n}\n\n/** Optional configuration for cached content creation. */\nexport declare interface CreateCachedContentConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** The TTL for this resource. The expiration time is computed: now + TTL. It is a duration string, with up to nine fractional digits, terminated by 's'. Example: \"3.5s\". */\n ttl?: string;\n /** Timestamp of when this resource is considered expired. Uses RFC 3339 format, Example: 2014-10-02T15:01:23Z. */\n expireTime?: string;\n /** The user-generated meaningful display name of the cached content.\n */\n displayName?: string;\n /** The content to cache.\n */\n contents?: ContentListUnion;\n /** Developer set system instruction.\n */\n systemInstruction?: ContentUnion;\n /** A list of `Tools` the model may use to generate the next response.\n */\n tools?: Tool[];\n /** Configuration for the tools to use. This config is shared for all tools.\n */\n toolConfig?: ToolConfig;\n /** The Cloud KMS resource identifier of the customer managed\n encryption key used to protect a resource.\n The key needs to be in the same region as where the compute resource is\n created. See\n https://cloud.google.com/vertex-ai/docs/general/cmek for more\n details. If this is set, then all created CachedContent objects\n will be encrypted with the provided encryption key.\n Allowed formats: projects/{project}/locations/{location}/keyRings/{key_ring}/cryptoKeys/{crypto_key}\n */\n kmsKeyName?: string;\n}\n\n/** Parameters for caches.create method. */\nexport declare interface CreateCachedContentParameters {\n /** ID of the model to use. Example: gemini-2.0-flash */\n model: string;\n /** Configuration that contains optional parameters.\n */\n config?: CreateCachedContentConfig;\n}\n\n/** Metadata on the usage of the cached content. */\nexport declare interface CachedContentUsageMetadata {\n /** Duration of audio in seconds. This field is not supported in Gemini API. */\n audioDurationSeconds?: number;\n /** Number of images. This field is not supported in Gemini API. */\n imageCount?: number;\n /** Number of text characters. This field is not supported in Gemini API. */\n textCount?: number;\n /** Total number of tokens that the cached content consumes. */\n totalTokenCount?: number;\n /** Duration of video in seconds. This field is not supported in Gemini API. */\n videoDurationSeconds?: number;\n}\n\n/** A resource used in LLM queries for users to explicitly specify what to cache. */\nexport declare interface CachedContent {\n /** The server-generated resource name of the cached content. */\n name?: string;\n /** The user-generated meaningful display name of the cached content. */\n displayName?: string;\n /** The name of the publisher model to use for cached content. */\n model?: string;\n /** Creation time of the cache entry. */\n createTime?: string;\n /** When the cache entry was last updated in UTC time. */\n updateTime?: string;\n /** Expiration time of the cached content. */\n expireTime?: string;\n /** Metadata on the usage of the cached content. */\n usageMetadata?: CachedContentUsageMetadata;\n}\n\n/** Optional parameters for caches.get method. */\nexport declare interface GetCachedContentConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for caches.get method. */\nexport declare interface GetCachedContentParameters {\n /** The server-generated resource name of the cached content.\n */\n name: string;\n /** Optional parameters for the request.\n */\n config?: GetCachedContentConfig;\n}\n\n/** Optional parameters for caches.delete method. */\nexport declare interface DeleteCachedContentConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for caches.delete method. */\nexport declare interface DeleteCachedContentParameters {\n /** The server-generated resource name of the cached content.\n */\n name: string;\n /** Optional parameters for the request.\n */\n config?: DeleteCachedContentConfig;\n}\n\n/** Empty response for caches.delete method. */\nexport class DeleteCachedContentResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n}\n\n/** Optional parameters for caches.update method. */\nexport declare interface UpdateCachedContentConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** The TTL for this resource. The expiration time is computed: now + TTL. It is a duration string, with up to nine fractional digits, terminated by 's'. Example: \"3.5s\". */\n ttl?: string;\n /** Timestamp of when this resource is considered expired. Uses RFC 3339 format, Example: 2014-10-02T15:01:23Z. */\n expireTime?: string;\n}\n\nexport declare interface UpdateCachedContentParameters {\n /** The server-generated resource name of the cached content.\n */\n name: string;\n /** Configuration that contains optional parameters.\n */\n config?: UpdateCachedContentConfig;\n}\n\n/** Config for caches.list method. */\nexport declare interface ListCachedContentsConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n pageSize?: number;\n pageToken?: string;\n}\n\n/** Parameters for caches.list method. */\nexport declare interface ListCachedContentsParameters {\n /** Configuration that contains optional parameters.\n */\n config?: ListCachedContentsConfig;\n}\n\nexport class ListCachedContentsResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n nextPageToken?: string;\n /** List of cached contents.\n */\n cachedContents?: CachedContent[];\n}\n\n/** Optional Config. */\nexport declare interface GetDocumentConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for documents.get. */\nexport declare interface GetDocumentParameters {\n /** The resource name of the Document.\n Example: fileSearchStores/file-search-store-foo/documents/documents-bar */\n name: string;\n /** Optional parameters for the request. */\n config?: GetDocumentConfig;\n}\n\n/** User provided string values assigned to a single metadata key. This data type is not supported in Vertex AI. */\nexport declare interface StringList {\n /** The string values of the metadata to store. */\n values?: string[];\n}\n\n/** User provided metadata stored as key-value pairs. This data type is not supported in Vertex AI. */\nexport declare interface CustomMetadata {\n /** Required. The key of the metadata to store. */\n key?: string;\n /** The numeric value of the metadata to store. */\n numericValue?: number;\n /** The StringList value of the metadata to store. */\n stringListValue?: StringList;\n /** The string value of the metadata to store. */\n stringValue?: string;\n}\n\n/** A Document is a collection of Chunks. */\nexport declare interface Document {\n /** The resource name of the Document.\n Example: fileSearchStores/file-search-store-foo/documents/documents-bar */\n name?: string;\n /** The human-readable display name for the Document. */\n displayName?: string;\n /** The current state of the Document. */\n state?: DocumentState;\n /** The size of the Document in bytes. */\n sizeBytes?: string;\n /** The MIME type of the Document. */\n mimeType?: string;\n /** Output only. The Timestamp of when the `Document` was created. */\n createTime?: string;\n /** Optional. User provided custom metadata stored as key-value pairs used for querying. A `Document` can have a maximum of 20 `CustomMetadata`. */\n customMetadata?: CustomMetadata[];\n /** Output only. The Timestamp of when the `Document` was last updated. */\n updateTime?: string;\n}\n\n/** Config for optional parameters. */\nexport declare interface DeleteDocumentConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** If set to true, any `Chunk`s and objects related to this `Document` will\n also be deleted.\n */\n force?: boolean;\n}\n\n/** Config for documents.delete parameters. */\nexport declare interface DeleteDocumentParameters {\n /** The resource name of the Document.\n Example: fileSearchStores/file-search-store-foo/documents/documents-bar */\n name: string;\n /** Optional parameters for the request. */\n config?: DeleteDocumentConfig;\n}\n\n/** Config for optional parameters. */\nexport declare interface ListDocumentsConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n pageSize?: number;\n pageToken?: string;\n}\n\n/** Config for documents.list parameters. */\nexport declare interface ListDocumentsParameters {\n /** The resource name of the FileSearchStores. Example: `fileSearchStore/file-search-store-foo` */\n parent: string;\n config?: ListDocumentsConfig;\n}\n\n/** Config for documents.list return value. */\nexport class ListDocumentsResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** A token, which can be sent as `page_token` to retrieve the next page. If this field is omitted, there are no more pages. */\n nextPageToken?: string;\n /** The returned `Document`s. */\n documents?: Document[];\n}\n\n/** Optional parameters for creating a file search store. */\nexport declare interface CreateFileSearchStoreConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** The human-readable display name for the file search store.\n */\n displayName?: string;\n}\n\n/** Config for file_search_stores.create parameters. */\nexport declare interface CreateFileSearchStoreParameters {\n /** Optional parameters for creating a file search store.\n */\n config?: CreateFileSearchStoreConfig;\n}\n\n/** A collection of Documents. */\nexport declare interface FileSearchStore {\n /** The resource name of the FileSearchStore. Example: `fileSearchStores/my-file-search-store-123` */\n name?: string;\n /** The human-readable display name for the FileSearchStore. */\n displayName?: string;\n /** The Timestamp of when the FileSearchStore was created. */\n createTime?: string;\n /** The Timestamp of when the FileSearchStore was last updated. */\n updateTime?: string;\n /** The number of documents in the FileSearchStore that are active and ready for retrieval. */\n activeDocumentsCount?: string;\n /** The number of documents in the FileSearchStore that are being processed. */\n pendingDocumentsCount?: string;\n /** The number of documents in the FileSearchStore that have failed processing. */\n failedDocumentsCount?: string;\n /** The size of raw bytes ingested into the FileSearchStore. This is the\n total size of all the documents in the FileSearchStore. */\n sizeBytes?: string;\n}\n\n/** Optional parameters for getting a FileSearchStore. */\nexport declare interface GetFileSearchStoreConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Config for file_search_stores.get parameters. */\nexport declare interface GetFileSearchStoreParameters {\n /** The resource name of the FileSearchStore. Example: `fileSearchStores/my-file-search-store-123` */\n name: string;\n /** Optional parameters for the request. */\n config?: GetFileSearchStoreConfig;\n}\n\n/** Optional parameters for deleting a FileSearchStore. */\nexport declare interface DeleteFileSearchStoreConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** If set to true, any Documents and objects related to this FileSearchStore will also be deleted.\n If false (the default), a FAILED_PRECONDITION error will be returned if\n the FileSearchStore contains any Documents.\n */\n force?: boolean;\n}\n\n/** Config for file_search_stores.delete parameters. */\nexport declare interface DeleteFileSearchStoreParameters {\n /** The resource name of the FileSearchStore. Example: `fileSearchStores/my-file-search-store-123` */\n name: string;\n /** Optional parameters for the request. */\n config?: DeleteFileSearchStoreConfig;\n}\n\n/** Optional parameters for listing FileSearchStore. */\nexport declare interface ListFileSearchStoresConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n pageSize?: number;\n pageToken?: string;\n}\n\n/** Config for file_search_stores.list parameters. */\nexport declare interface ListFileSearchStoresParameters {\n /** Optional parameters for the list request. */\n config?: ListFileSearchStoresConfig;\n}\n\n/** Config for file_search_stores.list return value. */\nexport class ListFileSearchStoresResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n nextPageToken?: string;\n /** The returned file search stores. */\n fileSearchStores?: FileSearchStore[];\n}\n\n/** Configuration for a white space chunking algorithm. */\nexport declare interface WhiteSpaceConfig {\n /** Maximum number of tokens per chunk. */\n maxTokensPerChunk?: number;\n /** Maximum number of overlapping tokens between two adjacent chunks. */\n maxOverlapTokens?: number;\n}\n\n/** Config for telling the service how to chunk the file. */\nexport declare interface ChunkingConfig {\n /** White space chunking configuration. */\n whiteSpaceConfig?: WhiteSpaceConfig;\n}\n\n/** Optional parameters for uploading a file to a FileSearchStore. */\nexport declare interface UploadToFileSearchStoreConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** MIME type of the file to be uploaded. If not provided, it will be inferred from the file extension. */\n mimeType?: string;\n /** Display name of the created document. */\n displayName?: string;\n /** User provided custom metadata stored as key-value pairs used for querying. */\n customMetadata?: CustomMetadata[];\n /** Config for telling the service how to chunk the file. */\n chunkingConfig?: ChunkingConfig;\n}\n\n/** Generates the parameters for the private _upload_to_file_search_store method. */\nexport declare interface UploadToFileSearchStoreParameters {\n /** The resource name of the FileSearchStore. Example: `fileSearchStores/my-file-search-store-123` */\n fileSearchStoreName: string;\n /** Used to override the default configuration. */\n config?: UploadToFileSearchStoreConfig;\n}\n\n/** Response for the resumable upload method. */\nexport class UploadToFileSearchStoreResumableResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n}\n\n/** Optional parameters for importing a file. */\nexport declare interface ImportFileConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** User provided custom metadata stored as key-value pairs used for querying. */\n customMetadata?: CustomMetadata[];\n /** Config for telling the service how to chunk the file. */\n chunkingConfig?: ChunkingConfig;\n}\n\n/** Config for file_search_stores.import_file parameters. */\nexport declare interface ImportFileParameters {\n /** The resource name of the FileSearchStore. Example: `fileSearchStores/my-file-search-store-123` */\n fileSearchStoreName: string;\n /** The name of the File API File to import. Example: `files/abc-123` */\n fileName: string;\n /** Optional parameters for the request. */\n config?: ImportFileConfig;\n}\n\n/** Response for ImportFile to import a File API file with a file search store. */\nexport class ImportFileResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** The name of the FileSearchStore containing Documents. */\n parent?: string;\n /** The identifier for the Document imported. */\n documentName?: string;\n}\n\n/** Long-running operation for importing a file to a FileSearchStore. */\nexport class ImportFileOperation implements Operation<ImportFileResponse> {\n /** The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`. */\n name?: string;\n /** Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata. Any method that returns a long-running operation should document the metadata type, if any. */\n metadata?: Record<string, unknown>;\n /** If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available. */\n done?: boolean;\n /** The error result of the operation in case of failure or cancellation. */\n error?: Record<string, unknown>;\n /** The result of the ImportFile operation, available when the operation is done. */\n response?: ImportFileResponse;\n\n /**\n * Instantiates an Operation of the same type as the one being called with the fields set from the API response.\n * @internal\n */\n _fromAPIResponse({\n apiResponse,\n _isVertexAI,\n }: OperationFromAPIResponseParameters): Operation<ImportFileResponse> {\n const operation = new ImportFileOperation();\n\n const op = apiResponse as unknown as ImportFileOperation;\n const response = importFileOperationFromMldev(op);\n Object.assign(operation, response);\n return operation;\n }\n /** The full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n}\n\nexport /** Used to override the default configuration. */\ndeclare interface ListFilesConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n pageSize?: number;\n pageToken?: string;\n}\n\n/** Generates the parameters for the list method. */\nexport declare interface ListFilesParameters {\n /** Used to override the default configuration. */\n config?: ListFilesConfig;\n}\n\n/** Status of a File that uses a common error model. */\nexport declare interface FileStatus {\n /** A list of messages that carry the error details. There is a common set of message types for APIs to use. */\n details?: Record<string, unknown>[];\n /** A list of messages that carry the error details. There is a common set of message types for APIs to use. */\n message?: string;\n /** The status code. 0 for OK, 1 for CANCELLED */\n code?: number;\n}\n\n/** A file uploaded to the API. */\nexport declare interface File {\n /** The `File` resource name. The ID (name excluding the \"files/\" prefix) can contain up to 40 characters that are lowercase alphanumeric or dashes (-). The ID cannot start or end with a dash. If the name is empty on create, a unique name will be generated. Example: `files/123-456` */\n name?: string;\n /** Optional. The human-readable display name for the `File`. The display name must be no more than 512 characters in length, including spaces. Example: 'Welcome Image' */\n displayName?: string;\n /** Output only. MIME type of the file. */\n mimeType?: string;\n /** Output only. Size of the file in bytes. */\n sizeBytes?: string;\n /** Output only. The timestamp of when the `File` was created. */\n createTime?: string;\n /** Output only. The timestamp of when the `File` will be deleted. Only set if the `File` is scheduled to expire. */\n expirationTime?: string;\n /** Output only. The timestamp of when the `File` was last updated. */\n updateTime?: string;\n /** Output only. SHA-256 hash of the uploaded bytes. The hash value is encoded in base64 format. */\n sha256Hash?: string;\n /** Output only. The URI of the `File`. */\n uri?: string;\n /** Output only. The URI of the `File`, only set for downloadable (generated) files. */\n downloadUri?: string;\n /** Output only. Processing state of the File. */\n state?: FileState;\n /** Output only. The source of the `File`. */\n source?: FileSource;\n /** Output only. Metadata for a video. */\n videoMetadata?: Record<string, unknown>;\n /** Output only. Error status if File processing failed. */\n error?: FileStatus;\n}\n\n/** Response for the list files method. */\nexport class ListFilesResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** A token that can be sent as a `page_token` into a subsequent `ListFiles` call. */\n nextPageToken?: string;\n /** The list of `File`s. */\n files?: File[];\n}\n\n/** Used to override the default configuration. */\nexport declare interface CreateFileConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Generates the parameters for the private _create method. */\nexport declare interface CreateFileParameters {\n /** The file to be uploaded.\n mime_type: (Required) The MIME type of the file. Must be provided.\n name: (Optional) The name of the file in the destination (e.g.\n 'files/sample-image').\n display_name: (Optional) The display name of the file.\n */\n file: File;\n /** Used to override the default configuration. */\n config?: CreateFileConfig;\n}\n\n/** Response for the create file method. */\nexport class CreateFileResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n}\n\n/** Used to override the default configuration. */\nexport declare interface GetFileConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Generates the parameters for the get method. */\nexport declare interface GetFileParameters {\n /** The name identifier for the file to retrieve. */\n name: string;\n /** Used to override the default configuration. */\n config?: GetFileConfig;\n}\n\n/** Used to override the default configuration. */\nexport declare interface DeleteFileConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Generates the parameters for the get method. */\nexport declare interface DeleteFileParameters {\n /** The name identifier for the file to be deleted. */\n name: string;\n /** Used to override the default configuration. */\n config?: DeleteFileConfig;\n}\n\n/** Response for the delete file method. */\nexport class DeleteFileResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n}\n\n/** Used to override the default configuration. */\nexport declare interface RegisterFilesConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for the private _Register method. */\nexport declare interface InternalRegisterFilesParameters {\n /** The Google Cloud Storage URIs to register. Example: `gs://bucket/object`. */\n uris: string[];\n /** Used to override the default configuration. */\n config?: RegisterFilesConfig;\n}\n\n/** Response for the _register file method. */\nexport class RegisterFilesResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** The registered files. */\n files?: File[];\n}\n\n/** Config for inlined request. */\nexport declare interface InlinedRequest {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model?: string;\n /** Content of the request.\n */\n contents?: ContentListUnion;\n /** The metadata to be associated with the request. */\n metadata?: Record<string, string>;\n /** Configuration that contains optional model parameters.\n */\n config?: GenerateContentConfig;\n}\n\n/** Config for `src` parameter. */\nexport declare interface BatchJobSource {\n /** Storage format of the input files. Must be one of:\n 'jsonl', 'bigquery'.\n */\n format?: string;\n /** The Google Cloud Storage URIs to input files.\n */\n gcsUri?: string[];\n /** The BigQuery URI to input table.\n */\n bigqueryUri?: string;\n /** The Gemini Developer API's file resource name of the input data\n (e.g. \"files/12345\").\n */\n fileName?: string;\n /** The Gemini Developer API's inlined input data to run batch job.\n */\n inlinedRequests?: InlinedRequest[];\n}\n\n/** Job error. */\nexport declare interface JobError {\n /** A list of messages that carry the error details. There is a common set of message types for APIs to use. */\n details?: string[];\n /** The status code. */\n code?: number;\n /** A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the `details` field. */\n message?: string;\n}\n\n/** Config for `inlined_responses` parameter. */\nexport class InlinedResponse {\n /** The response to the request.\n */\n response?: GenerateContentResponse;\n /** The metadata to be associated with the request. */\n metadata?: Record<string, string>;\n /** The error encountered while processing the request.\n */\n error?: JobError;\n}\n\n/** Config for `response` parameter. */\nexport class SingleEmbedContentResponse {\n /** The response to the request.\n */\n embedding?: ContentEmbedding;\n /** The error encountered while processing the request.\n */\n tokenCount?: string;\n}\n\n/** Config for `inlined_embedding_responses` parameter. */\nexport class InlinedEmbedContentResponse {\n /** The response to the request.\n */\n response?: SingleEmbedContentResponse;\n /** The error encountered while processing the request.\n */\n error?: JobError;\n}\n\n/** Config for `des` parameter. */\nexport declare interface BatchJobDestination {\n /** Storage format of the output files. Must be one of:\n 'jsonl', 'bigquery'.\n */\n format?: string;\n /** The Google Cloud Storage URI to the output file.\n */\n gcsUri?: string;\n /** The BigQuery URI to the output table.\n */\n bigqueryUri?: string;\n /** The Gemini Developer API's file resource name of the output data\n (e.g. \"files/12345\"). The file will be a JSONL file with a single response\n per line. The responses will be GenerateContentResponse messages formatted\n as JSON. The responses will be written in the same order as the input\n requests.\n */\n fileName?: string;\n /** The responses to the requests in the batch. Returned when the batch was\n built using inlined requests. The responses will be in the same order as\n the input requests.\n */\n inlinedResponses?: InlinedResponse[];\n /** The responses to the requests in the batch. Returned when the batch was\n built using inlined requests. The responses will be in the same order as\n the input requests.\n */\n inlinedEmbedContentResponses?: InlinedEmbedContentResponse[];\n}\n\n/** Config for optional parameters. */\nexport declare interface CreateBatchJobConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** The user-defined name of this BatchJob.\n */\n displayName?: string;\n /** GCS or BigQuery URI prefix for the output predictions. Example:\n \"gs://path/to/output/data\" or \"bq://projectId.bqDatasetId.bqTableId\".\n */\n dest?: BatchJobDestinationUnion;\n}\n\n/** Config for batches.create parameters. */\nexport declare interface CreateBatchJobParameters {\n /** The name of the model to produces the predictions via the BatchJob.\n */\n model?: string;\n /** GCS URI(-s) or BigQuery URI to your input data to run batch job.\n Example: \"gs://path/to/input/data\" or \"bq://projectId.bqDatasetId.bqTableId\".\n */\n src: BatchJobSourceUnion;\n /** Optional parameters for creating a BatchJob.\n */\n config?: CreateBatchJobConfig;\n}\n\n/** Success and error statistics of processing multiple entities (for example, DataItems or structured data rows) in batch. This data type is not supported in Gemini API. */\nexport declare interface CompletionStats {\n /** Output only. The number of entities for which any error was encountered. */\n failedCount?: string;\n /** Output only. In cases when enough errors are encountered a job, pipeline, or operation may be failed as a whole. Below is the number of entities for which the processing had not been finished (either in successful or failed state). Set to -1 if the number is unknown (for example, the operation failed before the total entity number could be collected). */\n incompleteCount?: string;\n /** Output only. The number of entities that had been processed successfully. */\n successfulCount?: string;\n /** Output only. The number of the successful forecast points that are generated by the forecasting model. This is ONLY used by the forecasting batch prediction. */\n successfulForecastPointCount?: string;\n}\n\n/** Config for batches.create return value. */\nexport declare interface BatchJob {\n /** The resource name of the BatchJob. Output only.\".\n */\n name?: string;\n /** The display name of the BatchJob.\n */\n displayName?: string;\n /** The state of the BatchJob.\n */\n state?: JobState;\n /** Output only. Only populated when the job's state is JOB_STATE_FAILED or JOB_STATE_CANCELLED. */\n error?: JobError;\n /** The time when the BatchJob was created.\n */\n createTime?: string;\n /** Output only. Time when the Job for the first time entered the `JOB_STATE_RUNNING` state. */\n startTime?: string;\n /** The time when the BatchJob was completed. This field is for Vertex AI only.\n */\n endTime?: string;\n /** The time when the BatchJob was last updated.\n */\n updateTime?: string;\n /** The name of the model that produces the predictions via the BatchJob.\n */\n model?: string;\n /** Configuration for the input data. This field is for Vertex AI only.\n */\n src?: BatchJobSource;\n /** Configuration for the output data.\n */\n dest?: BatchJobDestination;\n /** Statistics on completed and failed prediction instances. This field is for Vertex AI only.\n */\n completionStats?: CompletionStats;\n}\n\n/** Parameters for the embed_content method. */\nexport declare interface EmbedContentBatch {\n /** The content to embed. Only the `parts.text` fields will be counted.\n */\n contents?: ContentListUnion;\n /** Configuration that contains optional parameters.\n */\n config?: EmbedContentConfig;\n}\n\nexport declare interface EmbeddingsBatchJobSource {\n /** The Gemini Developer API's file resource name of the input data\n (e.g. \"files/12345\").\n */\n fileName?: string;\n /** The Gemini Developer API's inlined input data to run batch job.\n */\n inlinedRequests?: EmbedContentBatch;\n}\n\n/** Config for optional parameters. */\nexport declare interface CreateEmbeddingsBatchJobConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** The user-defined name of this BatchJob.\n */\n displayName?: string;\n}\n\n/** Config for batches.create parameters. */\nexport declare interface CreateEmbeddingsBatchJobParameters {\n /** The name of the model to produces the predictions via the BatchJob.\n */\n model?: string;\n /** input data to run batch job\".\n */\n src: EmbeddingsBatchJobSource;\n /** Optional parameters for creating a BatchJob.\n */\n config?: CreateEmbeddingsBatchJobConfig;\n}\n\n/** Optional parameters. */\nexport declare interface GetBatchJobConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Config for batches.get parameters. */\nexport declare interface GetBatchJobParameters {\n /** A fully-qualified BatchJob resource name or ID.\n Example: \"projects/.../locations/.../batchPredictionJobs/456\"\n or \"456\" when project and location are initialized in the client.\n */\n name: string;\n /** Optional parameters for the request. */\n config?: GetBatchJobConfig;\n}\n\n/** Optional parameters. */\nexport declare interface CancelBatchJobConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Config for batches.cancel parameters. */\nexport declare interface CancelBatchJobParameters {\n /** A fully-qualified BatchJob resource name or ID.\n Example: \"projects/.../locations/.../batchPredictionJobs/456\"\n or \"456\" when project and location are initialized in the client.\n */\n name: string;\n /** Optional parameters for the request. */\n config?: CancelBatchJobConfig;\n}\n\n/** Config for optional parameters. */\nexport declare interface ListBatchJobsConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n pageSize?: number;\n pageToken?: string;\n filter?: string;\n}\n\n/** Config for batches.list parameters. */\nexport declare interface ListBatchJobsParameters {\n config?: ListBatchJobsConfig;\n}\n\n/** Config for batches.list return value. */\nexport class ListBatchJobsResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n nextPageToken?: string;\n batchJobs?: BatchJob[];\n}\n\n/** Optional parameters for models.get method. */\nexport declare interface DeleteBatchJobConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Config for batches.delete parameters. */\nexport declare interface DeleteBatchJobParameters {\n /** A fully-qualified BatchJob resource name or ID.\n Example: \"projects/.../locations/.../batchPredictionJobs/456\"\n or \"456\" when project and location are initialized in the client.\n */\n name: string;\n /** Optional parameters for the request. */\n config?: DeleteBatchJobConfig;\n}\n\n/** The return value of delete operation. */\nexport declare interface DeleteResourceJob {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n name?: string;\n done?: boolean;\n error?: JobError;\n}\n\nexport declare interface GetOperationConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for the GET method. */\nexport declare interface GetOperationParameters {\n /** The server-assigned name for the operation. */\n operationName: string;\n /** Used to override the default configuration. */\n config?: GetOperationConfig;\n}\n\nexport declare interface FetchPredictOperationConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for the fetchPredictOperation method. */\nexport declare interface FetchPredictOperationParameters {\n /** The server-assigned name for the operation. */\n operationName: string;\n resourceName: string;\n /** Used to override the default configuration. */\n config?: FetchPredictOperationConfig;\n}\n\nexport declare interface TestTableItem {\n /** The name of the test. This is used to derive the replay id. */\n name?: string;\n /** The parameters to the test. Use pydantic models. */\n parameters?: Record<string, unknown>;\n /** Expects an exception for MLDev matching the string. */\n exceptionIfMldev?: string;\n /** Expects an exception for Vertex matching the string. */\n exceptionIfVertex?: string;\n /** Use if you don't want to use the default replay id which is derived from the test name. */\n overrideReplayId?: string;\n /** True if the parameters contain an unsupported union type. This test will be skipped for languages that do not support the union type. */\n hasUnion?: boolean;\n /** When set to a reason string, this test will be skipped in the API mode. Use this flag for tests that can not be reproduced with the real API. E.g. a test that deletes a resource. */\n skipInApiMode?: string;\n /** Keys to ignore when comparing the request and response. This is useful for tests that are not deterministic. */\n ignoreKeys?: string[];\n}\n\nexport declare interface TestTableFile {\n comment?: string;\n testMethod?: string;\n parameterNames?: string[];\n testTable?: TestTableItem[];\n}\n\n/** Represents a single request in a replay. */\nexport declare interface ReplayRequest {\n method?: string;\n url?: string;\n headers?: Record<string, string>;\n bodySegments?: Record<string, unknown>[];\n}\n\n/** Represents a single response in a replay. */\nexport class ReplayResponse {\n statusCode?: number;\n headers?: Record<string, string>;\n bodySegments?: Record<string, unknown>[];\n sdkResponseSegments?: Record<string, unknown>[];\n}\n\n/** Represents a single interaction, request and response in a replay. */\nexport declare interface ReplayInteraction {\n request?: ReplayRequest;\n response?: ReplayResponse;\n}\n\n/** Represents a recorded session. */\nexport declare interface ReplayFile {\n replayId?: string;\n interactions?: ReplayInteraction[];\n}\n\n/** Used to override the default configuration. */\nexport declare interface UploadFileConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** The name of the file in the destination (e.g., 'files/sample-image'. If not provided one will be generated. */\n name?: string;\n /** mime_type: The MIME type of the file. If not provided, it will be inferred from the file extension. */\n mimeType?: string;\n /** Optional display name of the file. */\n displayName?: string;\n}\n\n/** Used to override the default configuration. */\nexport declare interface DownloadFileConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters used to download a file. */\nexport declare interface DownloadFileParameters {\n /** The file to download. It can be a file name, a file object or a generated video. */\n file: DownloadableFileUnion;\n /** Location where the file should be downloaded to. */\n downloadPath: string;\n /** Configuration to for the download operation. */\n config?: DownloadFileConfig;\n}\n\n/** Configuration for upscaling an image.\n\nFor more information on this configuration, refer to\nthe `Imagen API reference documentation\n<https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/imagen-api>`_. */\nexport declare interface UpscaleImageConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** Cloud Storage URI used to store the generated images. */\n outputGcsUri?: string;\n /** Filter level for safety filtering. */\n safetyFilterLevel?: SafetyFilterLevel;\n /** Allows generation of people by the model. */\n personGeneration?: PersonGeneration;\n /** Whether to include a reason for filtered-out images in the\n response. */\n includeRaiReason?: boolean;\n /** The image format that the output should be saved as. */\n outputMimeType?: string;\n /** The level of compression. Only applicable if the\n ``output_mime_type`` is ``image/jpeg``. */\n outputCompressionQuality?: number;\n /** Whether to add an image enhancing step before upscaling.\n It is expected to suppress the noise and JPEG compression artifacts\n from the input image. */\n enhanceInputImage?: boolean;\n /** With a higher image preservation factor, the original image\n pixels are more respected. With a lower image preservation factor, the\n output image will have be more different from the input image, but\n with finer details and less noise. */\n imagePreservationFactor?: number;\n /** User specified labels to track billing usage. */\n labels?: Record<string, string>;\n}\n\n/** User-facing config UpscaleImageParameters. */\nexport declare interface UpscaleImageParameters {\n /** The model to use. */\n model: string;\n /** The input image to upscale. */\n image: Image;\n /** The factor to upscale the image (x2 or x4). */\n upscaleFactor: string;\n /** Configuration for upscaling. */\n config?: UpscaleImageConfig;\n}\n\n/** A raw reference image.\n\nA raw reference image represents the base image to edit, provided by the user.\nIt can optionally be provided in addition to a mask reference image or\na style reference image. */\nexport class RawReferenceImage {\n /** The reference image for the editing operation. */\n referenceImage?: Image;\n /** The id of the reference image. */\n referenceId?: number;\n /** The type of the reference image. Only set by the SDK. */\n referenceType?: string;\n /** Internal method to convert to ReferenceImageAPIInternal. */\n toReferenceImageAPI(): ReferenceImageAPIInternal {\n const referenceImageAPI = {\n referenceType: 'REFERENCE_TYPE_RAW',\n referenceImage: this.referenceImage,\n referenceId: this.referenceId,\n };\n return referenceImageAPI;\n }\n}\n\n/** A mask reference image.\n\nThis encapsulates either a mask image provided by the user and configs for\nthe user provided mask, or only config parameters for the model to generate\na mask.\n\nA mask image is an image whose non-zero values indicate where to edit the base\nimage. If the user provides a mask image, the mask must be in the same\ndimensions as the raw image. */\nexport class MaskReferenceImage {\n /** The reference image for the editing operation. */\n referenceImage?: Image;\n /** The id of the reference image. */\n referenceId?: number;\n /** The type of the reference image. Only set by the SDK. */\n referenceType?: string;\n /** Configuration for the mask reference image. */\n config?: MaskReferenceConfig;\n /** Internal method to convert to ReferenceImageAPIInternal. */\n toReferenceImageAPI(): ReferenceImageAPIInternal {\n const referenceImageAPI = {\n referenceType: 'REFERENCE_TYPE_MASK',\n referenceImage: this.referenceImage,\n referenceId: this.referenceId,\n maskImageConfig: this.config,\n };\n return referenceImageAPI;\n }\n}\n\n/** A control reference image.\n\nThe image of the control reference image is either a control image provided\nby the user, or a regular image which the backend will use to generate a\ncontrol image of. In the case of the latter, the\nenable_control_image_computation field in the config should be set to True.\n\nA control image is an image that represents a sketch image of areas for the\nmodel to fill in based on the prompt. */\nexport class ControlReferenceImage {\n /** The reference image for the editing operation. */\n referenceImage?: Image;\n /** The id of the reference image. */\n referenceId?: number;\n /** The type of the reference image. Only set by the SDK. */\n referenceType?: string;\n /** Configuration for the control reference image. */\n config?: ControlReferenceConfig;\n /** Internal method to convert to ReferenceImageAPIInternal. */\n toReferenceImageAPI(): ReferenceImageAPIInternal {\n const referenceImageAPI = {\n referenceType: 'REFERENCE_TYPE_CONTROL',\n referenceImage: this.referenceImage,\n referenceId: this.referenceId,\n controlImageConfig: this.config,\n };\n return referenceImageAPI;\n }\n}\n\n/** A style reference image.\n\nThis encapsulates a style reference image provided by the user, and\nadditionally optional config parameters for the style reference image.\n\nA raw reference image can also be provided as a destination for the style to\nbe applied to. */\nexport class StyleReferenceImage {\n /** The reference image for the editing operation. */\n referenceImage?: Image;\n /** The id of the reference image. */\n referenceId?: number;\n /** The type of the reference image. Only set by the SDK. */\n referenceType?: string;\n /** Configuration for the style reference image. */\n config?: StyleReferenceConfig;\n /** Internal method to convert to ReferenceImageAPIInternal. */\n toReferenceImageAPI(): ReferenceImageAPIInternal {\n const referenceImageAPI = {\n referenceType: 'REFERENCE_TYPE_STYLE',\n referenceImage: this.referenceImage,\n referenceId: this.referenceId,\n styleImageConfig: this.config,\n };\n return referenceImageAPI;\n }\n}\n\n/** A subject reference image.\n\nThis encapsulates a subject reference image provided by the user, and\nadditionally optional config parameters for the subject reference image.\n\nA raw reference image can also be provided as a destination for the subject to\nbe applied to. */\nexport class SubjectReferenceImage {\n /** The reference image for the editing operation. */\n referenceImage?: Image;\n /** The id of the reference image. */\n referenceId?: number;\n /** The type of the reference image. Only set by the SDK. */\n referenceType?: string;\n /** Configuration for the subject reference image. */\n config?: SubjectReferenceConfig;\n /* Internal method to convert to ReferenceImageAPIInternal. */\n toReferenceImageAPI(): ReferenceImageAPIInternal {\n const referenceImageAPI = {\n referenceType: 'REFERENCE_TYPE_SUBJECT',\n referenceImage: this.referenceImage,\n referenceId: this.referenceId,\n subjectImageConfig: this.config,\n };\n return referenceImageAPI;\n }\n}\n\n/** A content reference image.\n\nA content reference image represents a subject to reference (ex. person,\nproduct, animal) provided by the user. It can optionally be provided in\naddition to a style reference image (ex. background, style reference). */\nexport class ContentReferenceImage {\n /** The reference image for the editing operation. */\n referenceImage?: Image;\n /** The id of the reference image. */\n referenceId?: number;\n /** The type of the reference image. Only set by the SDK. */\n referenceType?: string;\n /** Internal method to convert to ReferenceImageAPIInternal. */\n toReferenceImageAPI(): ReferenceImageAPIInternal {\n const referenceImageAPI = {\n referenceType: 'REFERENCE_TYPE_CONTENT',\n referenceImage: this.referenceImage,\n referenceId: this.referenceId,\n };\n return referenceImageAPI;\n }\n}\n\n/** Sent in response to a `LiveGenerateContentSetup` message from the client. */\nexport declare interface LiveServerSetupComplete {\n /** The session id of the live session. */\n sessionId?: string;\n}\n\n/** Audio transcription in Server Conent. */\nexport declare interface Transcription {\n /** Transcription text.\n */\n text?: string;\n /** The bool indicates the end of the transcription.\n */\n finished?: boolean;\n}\n\n/** Incremental server update generated by the model in response to client messages.\n\nContent is generated as quickly as possible, and not in real time. Clients\nmay choose to buffer and play it out in real time. */\nexport declare interface LiveServerContent {\n /** The content that the model has generated as part of the current conversation with the user. */\n modelTurn?: Content;\n /** If true, indicates that the model is done generating. Generation will only start in response to additional client messages. Can be set alongside `content`, indicating that the `content` is the last in the turn. */\n turnComplete?: boolean;\n /** If true, indicates that a client message has interrupted current model generation. If the client is playing out the content in realtime, this is a good signal to stop and empty the current queue. */\n interrupted?: boolean;\n /** Metadata returned to client when grounding is enabled. */\n groundingMetadata?: GroundingMetadata;\n /** If true, indicates that the model is done generating. When model is\n interrupted while generating there will be no generation_complete message\n in interrupted turn, it will go through interrupted > turn_complete.\n When model assumes realtime playback there will be delay between\n generation_complete and turn_complete that is caused by model\n waiting for playback to finish. If true, indicates that the model\n has finished generating all content. This is a signal to the client\n that it can stop sending messages. */\n generationComplete?: boolean;\n /** Input transcription. The transcription is independent to the model\n turn which means it doesn’t imply any ordering between transcription and\n model turn. */\n inputTranscription?: Transcription;\n /** Output transcription. The transcription is independent to the model\n turn which means it doesn’t imply any ordering between transcription and\n model turn.\n */\n outputTranscription?: Transcription;\n /** Metadata related to url context retrieval tool. */\n urlContextMetadata?: UrlContextMetadata;\n /** Reason for the turn is complete. */\n turnCompleteReason?: TurnCompleteReason;\n /** If true, indicates that the model is not generating content because\n it is waiting for more input from the user, e.g. because it expects the\n user to continue talking. */\n waitingForInput?: boolean;\n}\n\n/** Request for the client to execute the `function_calls` and return the responses with the matching `id`s. */\nexport declare interface LiveServerToolCall {\n /** The function call to be executed. */\n functionCalls?: FunctionCall[];\n}\n\n/** Notification for the client that a previously issued `ToolCallMessage` with the specified `id`s should have been not executed and should be cancelled.\n\nIf there were side-effects to those tool calls, clients may attempt to undo\nthe tool calls. This message occurs only in cases where the clients interrupt\nserver turns. */\nexport declare interface LiveServerToolCallCancellation {\n /** The ids of the tool calls to be cancelled. */\n ids?: string[];\n}\n\n/** Usage metadata about response(s). */\nexport declare interface UsageMetadata {\n /** Number of tokens in the prompt. When `cached_content` is set, this is still the total effective prompt size meaning this includes the number of tokens in the cached content. */\n promptTokenCount?: number;\n /** Number of tokens in the cached part of the prompt (the cached content). */\n cachedContentTokenCount?: number;\n /** Total number of tokens across all the generated response candidates. */\n responseTokenCount?: number;\n /** Number of tokens present in tool-use prompt(s). */\n toolUsePromptTokenCount?: number;\n /** Number of tokens of thoughts for thinking models. */\n thoughtsTokenCount?: number;\n /** Total token count for prompt, response candidates, and tool-use prompts(if present). */\n totalTokenCount?: number;\n /** List of modalities that were processed in the request input. */\n promptTokensDetails?: ModalityTokenCount[];\n /** List of modalities that were processed in the cache input. */\n cacheTokensDetails?: ModalityTokenCount[];\n /** List of modalities that were returned in the response. */\n responseTokensDetails?: ModalityTokenCount[];\n /** List of modalities that were processed in the tool-use prompt. */\n toolUsePromptTokensDetails?: ModalityTokenCount[];\n /** Traffic type. This shows whether a request consumes Pay-As-You-Go\n or Provisioned Throughput quota. */\n trafficType?: TrafficType;\n}\n\n/** Server will not be able to service client soon. */\nexport declare interface LiveServerGoAway {\n /** The remaining time before the connection will be terminated as ABORTED. The minimal time returned here is specified differently together with the rate limits for a given model. */\n timeLeft?: string;\n}\n\n/** Update of the session resumption state.\n\nOnly sent if `session_resumption` was set in the connection config. */\nexport declare interface LiveServerSessionResumptionUpdate {\n /** New handle that represents state that can be resumed. Empty if `resumable`=false. */\n newHandle?: string;\n /** True if session can be resumed at this point. It might be not possible to resume session at some points. In that case we send update empty new_handle and resumable=false. Example of such case could be model executing function calls or just generating. Resuming session (using previous session token) in such state will result in some data loss. */\n resumable?: boolean;\n /** Index of last message sent by client that is included in state represented by this SessionResumptionToken. Only sent when `SessionResumptionConfig.transparent` is set.\n\nPresence of this index allows users to transparently reconnect and avoid issue of losing some part of realtime audio input/video. If client wishes to temporarily disconnect (for example as result of receiving GoAway) they can do it without losing state by buffering messages sent since last `SessionResmumptionTokenUpdate`. This field will enable them to limit buffering (avoid keeping all requests in RAM).\n\nNote: This should not be used for when resuming a session at some time later -- in those cases partial audio and video frames arelikely not needed. */\n lastConsumedClientMessageIndex?: string;\n}\n\nexport declare interface VoiceActivityDetectionSignal {\n /** The type of the VAD signal. */\n vadSignalType?: VadSignalType;\n}\n\n/** Voice activity signal. */\nexport declare interface VoiceActivity {\n /** The type of the voice activity signal. */\n voiceActivityType?: VoiceActivityType;\n}\n\n/** Response message for API call. */\nexport class LiveServerMessage {\n /** Sent in response to a `LiveClientSetup` message from the client. */\n setupComplete?: LiveServerSetupComplete;\n /** Content generated by the model in response to client messages. */\n serverContent?: LiveServerContent;\n /** Request for the client to execute the `function_calls` and return the responses with the matching `id`s. */\n toolCall?: LiveServerToolCall;\n /** Notification for the client that a previously issued `ToolCallMessage` with the specified `id`s should have been not executed and should be cancelled. */\n toolCallCancellation?: LiveServerToolCallCancellation;\n /** Usage metadata about model response(s). */\n usageMetadata?: UsageMetadata;\n /** Server will disconnect soon. */\n goAway?: LiveServerGoAway;\n /** Update of the session resumption state. */\n sessionResumptionUpdate?: LiveServerSessionResumptionUpdate;\n /** Voice activity detection signal. Allowlisted only. */\n voiceActivityDetectionSignal?: VoiceActivityDetectionSignal;\n /** Voice activity signal. */\n voiceActivity?: VoiceActivity;\n /**\n * Returns the concatenation of all text parts from the server content if present.\n *\n * @remarks\n * If there are non-text parts in the response, the concatenation of all text\n * parts will be returned, and a warning will be logged.\n */\n get text(): string | undefined {\n let text = '';\n let anyTextPartFound = false;\n const nonTextParts = [];\n for (const part of this.serverContent?.modelTurn?.parts ?? []) {\n for (const [fieldName, fieldValue] of Object.entries(part)) {\n if (\n fieldName !== 'text' &&\n fieldName !== 'thought' &&\n fieldValue !== null\n ) {\n nonTextParts.push(fieldName);\n }\n }\n if (typeof part.text === 'string') {\n if (typeof part.thought === 'boolean' && part.thought) {\n continue;\n }\n anyTextPartFound = true;\n text += part.text;\n }\n }\n if (nonTextParts.length > 0) {\n console.warn(\n `there are non-text parts ${nonTextParts} in the response, returning concatenation of all text parts. Please refer to the non text parts for a full response from model.`,\n );\n }\n // part.text === '' is different from part.text is null\n return anyTextPartFound ? text : undefined;\n }\n\n /**\n * Returns the concatenation of all inline data parts from the server content if present.\n *\n * @remarks\n * If there are non-inline data parts in the\n * response, the concatenation of all inline data parts will be returned, and\n * a warning will be logged.\n */\n get data(): string | undefined {\n let data = '';\n const nonDataParts = [];\n for (const part of this.serverContent?.modelTurn?.parts ?? []) {\n for (const [fieldName, fieldValue] of Object.entries(part)) {\n if (fieldName !== 'inlineData' && fieldValue !== null) {\n nonDataParts.push(fieldName);\n }\n }\n if (part.inlineData && typeof part.inlineData.data === 'string') {\n data += atob(part.inlineData.data);\n }\n }\n if (nonDataParts.length > 0) {\n console.warn(\n `there are non-data parts ${nonDataParts} in the response, returning concatenation of all data parts. Please refer to the non data parts for a full response from model.`,\n );\n }\n return data.length > 0 ? btoa(data) : undefined;\n }\n}\n\n/** Parameters of the fromAPIResponse method of the Operation class. */\nexport declare interface OperationFromAPIResponseParameters {\n /** The API response to be converted to an Operation. */\n apiResponse: Record<string, unknown>;\n /** Whether the API response is from Vertex AI. */\n _isVertexAI: boolean;\n}\n\n/**\n * Config for thinking feature.\n *\n * @deprecated This interface will be deprecated. Please use `ThinkingConfig` instead.\n */\nexport declare interface GenerationConfigThinkingConfig\n extends ThinkingConfig {}\n\n/** Generates the parameters for the private registerFiles method. */\nexport declare interface RegisterFilesParameters {\n /**\n * The authentication object.\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n auth?: any;\n /**\n * The Google Cloud Storage URIs to register. Example: `gs://bucket/object`.\n */\n uris: string[];\n /** Used to override the default configuration. */\n config?: RegisterFilesConfig;\n}\n\n/** Configures automatic detection of activity. */\nexport declare interface AutomaticActivityDetection {\n /** If enabled, detected voice and text input count as activity. If disabled, the client must send activity signals. */\n disabled?: boolean;\n /** Determines how likely speech is to be detected. */\n startOfSpeechSensitivity?: StartSensitivity;\n /** Determines how likely detected speech is ended. */\n endOfSpeechSensitivity?: EndSensitivity;\n /** The required duration of detected speech before start-of-speech is committed. The lower this value the more sensitive the start-of-speech detection is and the shorter speech can be recognized. However, this also increases the probability of false positives. */\n prefixPaddingMs?: number;\n /** The required duration of detected non-speech (e.g. silence) before end-of-speech is committed. The larger this value, the longer speech gaps can be without interrupting the user's activity but this will increase the model's latency. */\n silenceDurationMs?: number;\n}\n\n/** Marks the end of user activity.\n\nThis can only be sent if automatic (i.e. server-side) activity detection is\ndisabled. */\nexport declare interface RealtimeInputConfig {\n /** If not set, automatic activity detection is enabled by default. If automatic voice detection is disabled, the client must send activity signals. */\n automaticActivityDetection?: AutomaticActivityDetection;\n /** Defines what effect activity has. */\n activityHandling?: ActivityHandling;\n /** Defines which input is included in the user's turn. */\n turnCoverage?: TurnCoverage;\n}\n\n/** Configuration of session resumption mechanism.\n\nIncluded in `LiveConnectConfig.session_resumption`. If included server\nwill send `LiveServerSessionResumptionUpdate` messages. */\nexport declare interface SessionResumptionConfig {\n /** Session resumption handle of previous session (session to restore).\n\nIf not present new session will be started. */\n handle?: string;\n /** If set the server will send `last_consumed_client_message_index` in the `session_resumption_update` messages to allow for transparent reconnections. */\n transparent?: boolean;\n}\n\n/** Context window will be truncated by keeping only suffix of it.\n\nContext window will always be cut at start of USER role turn. System\ninstructions and `BidiGenerateContentSetup.prefix_turns` will not be\nsubject to the sliding window mechanism, they will always stay at the\nbeginning of context window. */\nexport declare interface SlidingWindow {\n /** Session reduction target -- how many tokens we should keep. Window shortening operation has some latency costs, so we should avoid running it on every turn. Should be < trigger_tokens. If not set, trigger_tokens/2 is assumed. */\n targetTokens?: string;\n}\n\n/** Enables context window compression -- mechanism managing model context window so it does not exceed given length. */\nexport declare interface ContextWindowCompressionConfig {\n /** Number of tokens (before running turn) that triggers context window compression mechanism. */\n triggerTokens?: string;\n /** Sliding window compression mechanism. */\n slidingWindow?: SlidingWindow;\n}\n\n/** The audio transcription configuration in Setup. */\nexport declare interface AudioTranscriptionConfig {}\n\n/** Config for proactivity features. */\nexport declare interface ProactivityConfig {\n /** If enabled, the model can reject responding to the last prompt. For\n example, this allows the model to ignore out of context speech or to stay\n silent if the user did not make a request, yet. */\n proactiveAudio?: boolean;\n}\n\n/** Message contains configuration that will apply for the duration of the streaming session. */\nexport declare interface LiveClientSetup {\n /** \n The fully qualified name of the publisher model or tuned model endpoint to\n use.\n */\n model?: string;\n /** The generation configuration for the session.\n Note: only a subset of fields are supported.\n */\n generationConfig?: GenerationConfig;\n /** The user provided system instructions for the model.\n Note: only text should be used in parts and content in each part will be\n in a separate paragraph. */\n systemInstruction?: ContentUnion;\n /** A list of `Tools` the model may use to generate the next response.\n\n A `Tool` is a piece of code that enables the system to interact with\n external systems to perform an action, or set of actions, outside of\n knowledge and scope of the model. */\n tools?: ToolListUnion;\n /** Configures the realtime input behavior in BidiGenerateContent. */\n realtimeInputConfig?: RealtimeInputConfig;\n /** Configures session resumption mechanism.\n\n If included server will send SessionResumptionUpdate messages. */\n sessionResumption?: SessionResumptionConfig;\n /** Configures context window compression mechanism.\n\n If included, server will compress context window to fit into given length. */\n contextWindowCompression?: ContextWindowCompressionConfig;\n /** The transcription of the input aligns with the input audio language.\n */\n inputAudioTranscription?: AudioTranscriptionConfig;\n /** The transcription of the output aligns with the language code\n specified for the output audio.\n */\n outputAudioTranscription?: AudioTranscriptionConfig;\n /** Configures the proactivity of the model. This allows the model to respond proactively to\n the input and to ignore irrelevant input. */\n proactivity?: ProactivityConfig;\n /** Configures the explicit VAD signal. If enabled, the client will send\n vad_signal to indicate the start and end of speech. This allows the server\n to process the audio more efficiently. */\n explicitVadSignal?: boolean;\n}\n\n/** Incremental update of the current conversation delivered from the client.\n\nAll the content here will unconditionally be appended to the conversation\nhistory and used as part of the prompt to the model to generate content.\n\nA message here will interrupt any current model generation. */\nexport declare interface LiveClientContent {\n /** The content appended to the current conversation with the model.\n\n For single-turn queries, this is a single instance. For multi-turn\n queries, this is a repeated field that contains conversation history and\n latest request.\n */\n turns?: Content[];\n /** If true, indicates that the server content generation should start with\n the currently accumulated prompt. Otherwise, the server will await\n additional messages before starting generation. */\n turnComplete?: boolean;\n}\n\n/** Marks the start of user activity.\n\nThis can only be sent if automatic (i.e. server-side) activity detection is\ndisabled. */\nexport declare interface ActivityStart {}\n\n/** Marks the end of user activity.\n\nThis can only be sent if automatic (i.e. server-side) activity detection is\ndisabled. */\nexport declare interface ActivityEnd {}\n\n/** User input that is sent in real time.\n\nThis is different from `LiveClientContent` in a few ways:\n\n - Can be sent continuously without interruption to model generation.\n - If there is a need to mix data interleaved across the\n `LiveClientContent` and the `LiveClientRealtimeInput`, server attempts to\n optimize for best response, but there are no guarantees.\n - End of turn is not explicitly specified, but is rather derived from user\n activity (for example, end of speech).\n - Even before the end of turn, the data is processed incrementally\n to optimize for a fast start of the response from the model.\n - Is always assumed to be the user's input (cannot be used to populate\n conversation history). */\nexport declare interface LiveClientRealtimeInput {\n /** Inlined bytes data for media input. */\n mediaChunks?: Blob[];\n /** The realtime audio input stream. */\n audio?: Blob;\n /** \nIndicates that the audio stream has ended, e.g. because the microphone was\nturned off.\n\nThis should only be sent when automatic activity detection is enabled\n(which is the default).\n\nThe client can reopen the stream by sending an audio message.\n */\n audioStreamEnd?: boolean;\n /** The realtime video input stream. */\n video?: Blob;\n /** The realtime text input stream. */\n text?: string;\n /** Marks the start of user activity. */\n activityStart?: ActivityStart;\n /** Marks the end of user activity. */\n activityEnd?: ActivityEnd;\n}\n\n/** Client generated response to a `ToolCall` received from the server.\n\nIndividual `FunctionResponse` objects are matched to the respective\n`FunctionCall` objects by the `id` field.\n\nNote that in the unary and server-streaming GenerateContent APIs function\ncalling happens by exchanging the `Content` parts, while in the bidi\nGenerateContent APIs function calling happens over this dedicated set of\nmessages. */\nexport class LiveClientToolResponse {\n /** The response to the function calls. */\n functionResponses?: FunctionResponse[];\n}\n\n/** Parameters for sending realtime input to the live API. */\nexport declare interface LiveSendRealtimeInputParameters {\n /** Realtime input to send to the session. */\n media?: BlobImageUnion;\n /** The realtime audio input stream. */\n audio?: Blob;\n /** \nIndicates that the audio stream has ended, e.g. because the microphone was\nturned off.\n\nThis should only be sent when automatic activity detection is enabled\n(which is the default).\n\nThe client can reopen the stream by sending an audio message.\n */\n audioStreamEnd?: boolean;\n /** The realtime video input stream. */\n video?: BlobImageUnion;\n /** The realtime text input stream. */\n text?: string;\n /** Marks the start of user activity. */\n activityStart?: ActivityStart;\n /** Marks the end of user activity. */\n activityEnd?: ActivityEnd;\n}\n\n/** Messages sent by the client in the API call. */\nexport declare interface LiveClientMessage {\n /** Message to be sent by the system when connecting to the API. SDK users should not send this message. */\n setup?: LiveClientSetup;\n /** Incremental update of the current conversation delivered from the client. */\n clientContent?: LiveClientContent;\n /** User input that is sent in real time. */\n realtimeInput?: LiveClientRealtimeInput;\n /** Response to a `ToolCallMessage` received from the server. */\n toolResponse?: LiveClientToolResponse;\n}\n\n/** Session config for the API connection. */\nexport declare interface LiveConnectConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** The generation configuration for the session. */\n generationConfig?: GenerationConfig;\n /** The requested modalities of the response. Represents the set of\n modalities that the model can return. Defaults to AUDIO if not specified.\n */\n responseModalities?: Modality[];\n /** Value that controls the degree of randomness in token selection.\n Lower temperatures are good for prompts that require a less open-ended or\n creative response, while higher temperatures can lead to more diverse or\n creative results.\n */\n temperature?: number;\n /** Tokens are selected from the most to least probable until the sum\n of their probabilities equals this value. Use a lower value for less\n random responses and a higher value for more random responses.\n */\n topP?: number;\n /** For each token selection step, the ``top_k`` tokens with the\n highest probabilities are sampled. Then tokens are further filtered based\n on ``top_p`` with the final token selected using temperature sampling. Use\n a lower number for less random responses and a higher number for more\n random responses.\n */\n topK?: number;\n /** Maximum number of tokens that can be generated in the response.\n */\n maxOutputTokens?: number;\n /** If specified, the media resolution specified will be used.\n */\n mediaResolution?: MediaResolution;\n /** When ``seed`` is fixed to a specific number, the model makes a best\n effort to provide the same response for repeated requests. By default, a\n random number is used.\n */\n seed?: number;\n /** The speech generation configuration.\n */\n speechConfig?: SpeechConfig;\n /** Config for thinking features.\n An error will be returned if this field is set for models that don't\n support thinking.\n */\n thinkingConfig?: ThinkingConfig;\n /** If enabled, the model will detect emotions and adapt its responses accordingly. */\n enableAffectiveDialog?: boolean;\n /** The user provided system instructions for the model.\n Note: only text should be used in parts and content in each part will be\n in a separate paragraph. */\n systemInstruction?: ContentUnion;\n /** A list of `Tools` the model may use to generate the next response.\n\n A `Tool` is a piece of code that enables the system to interact with\n external systems to perform an action, or set of actions, outside of\n knowledge and scope of the model. */\n tools?: ToolListUnion;\n /** Configures session resumption mechanism.\n\nIf included the server will send SessionResumptionUpdate messages. */\n sessionResumption?: SessionResumptionConfig;\n /** The transcription of the input aligns with the input audio language.\n */\n inputAudioTranscription?: AudioTranscriptionConfig;\n /** The transcription of the output aligns with the language code\n specified for the output audio.\n */\n outputAudioTranscription?: AudioTranscriptionConfig;\n /** Configures the realtime input behavior in BidiGenerateContent. */\n realtimeInputConfig?: RealtimeInputConfig;\n /** Configures context window compression mechanism.\n\n If included, server will compress context window to fit into given length. */\n contextWindowCompression?: ContextWindowCompressionConfig;\n /** Configures the proactivity of the model. This allows the model to respond proactively to\n the input and to ignore irrelevant input. */\n proactivity?: ProactivityConfig;\n /** Configures the explicit VAD signal. If enabled, the client will send\n vad_signal to indicate the start and end of speech. This allows the server\n to process the audio more efficiently. */\n explicitVadSignal?: boolean;\n}\n\n/** Parameters for connecting to the live API. */\nexport declare interface LiveConnectParameters {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model: string;\n /** callbacks */\n callbacks: LiveCallbacks;\n /** Optional configuration parameters for the request.\n */\n config?: LiveConnectConfig;\n}\n\n/** Parameters for initializing a new chat session.\n\nThese parameters are used when creating a chat session with the\n`chats.create()` method. */\nexport declare interface CreateChatParameters {\n /** The name of the model to use for the chat session.\n\n For example: 'gemini-2.0-flash', 'gemini-2.0-flash-lite', etc. See Gemini API\n docs to find the available models.\n */\n model: string;\n /** Config for the entire chat session.\n\n This config applies to all requests within the session\n unless overridden by a per-request `config` in `SendMessageParameters`.\n */\n config?: GenerateContentConfig;\n /** The initial conversation history for the chat session.\n\n This allows you to start the chat with a pre-existing history. The history\n must be a list of `Content` alternating between 'user' and 'model' roles.\n It should start with a 'user' message.\n */\n history?: Content[];\n}\n\n/** Parameters for sending a message within a chat session.\n\nThese parameters are used with the `chat.sendMessage()` method. */\nexport declare interface SendMessageParameters {\n /** The message to send to the model.\n\n The SDK will combine all parts into a single 'user' content to send to\n the model.\n */\n message: PartListUnion;\n /** Config for this specific request.\n\n Please note that the per-request config does not change the chat level\n config, nor inherit from it. If you intend to use some values from the\n chat's default config, you must explicitly copy them into this per-request\n config.\n */\n config?: GenerateContentConfig;\n}\n\n/** Parameters for sending client content to the live API. */\nexport declare interface LiveSendClientContentParameters {\n /** Client content to send to the session. */\n turns?: ContentListUnion;\n /** If true, indicates that the server content generation should start with\n the currently accumulated prompt. Otherwise, the server will await\n additional messages before starting generation. */\n turnComplete?: boolean;\n}\n\n/** Parameters for sending tool responses to the live API. */\nexport class LiveSendToolResponseParameters {\n /** Tool responses to send to the session. */\n functionResponses: FunctionResponse[] | FunctionResponse = [];\n}\n\n/** Message to be sent by the system when connecting to the API. */\nexport declare interface LiveMusicClientSetup {\n /** The model's resource name. Format: `models/{model}`. */\n model?: string;\n}\n\n/** Maps a prompt to a relative weight to steer music generation. */\nexport declare interface WeightedPrompt {\n /** Text prompt. */\n text?: string;\n /** Weight of the prompt. The weight is used to control the relative\n importance of the prompt. Higher weights are more important than lower\n weights.\n\n Weight must not be 0. Weights of all weighted_prompts in this\n LiveMusicClientContent message will be normalized. */\n weight?: number;\n}\n\n/** User input to start or steer the music. */\nexport declare interface LiveMusicClientContent {\n /** Weighted prompts as the model input. */\n weightedPrompts?: WeightedPrompt[];\n}\n\n/** Configuration for music generation. */\nexport declare interface LiveMusicGenerationConfig {\n /** Controls the variance in audio generation. Higher values produce\n higher variance. Range is [0.0, 3.0]. */\n temperature?: number;\n /** Controls how the model selects tokens for output. Samples the topK\n tokens with the highest probabilities. Range is [1, 1000]. */\n topK?: number;\n /** Seeds audio generation. If not set, the request uses a randomly\n generated seed. */\n seed?: number;\n /** Controls how closely the model follows prompts.\n Higher guidance follows more closely, but will make transitions more\n abrupt. Range is [0.0, 6.0]. */\n guidance?: number;\n /** Beats per minute. Range is [60, 200]. */\n bpm?: number;\n /** Density of sounds. Range is [0.0, 1.0]. */\n density?: number;\n /** Brightness of the music. Range is [0.0, 1.0]. */\n brightness?: number;\n /** Scale of the generated music. */\n scale?: Scale;\n /** Whether the audio output should contain bass. */\n muteBass?: boolean;\n /** Whether the audio output should contain drums. */\n muteDrums?: boolean;\n /** Whether the audio output should contain only bass and drums. */\n onlyBassAndDrums?: boolean;\n /** The mode of music generation. Default mode is QUALITY. */\n musicGenerationMode?: MusicGenerationMode;\n}\n\n/** Messages sent by the client in the LiveMusicClientMessage call. */\nexport declare interface LiveMusicClientMessage {\n /** Message to be sent in the first (and only in the first) `LiveMusicClientMessage`.\n Clients should wait for a `LiveMusicSetupComplete` message before\n sending any additional messages. */\n setup?: LiveMusicClientSetup;\n /** User input to influence music generation. */\n clientContent?: LiveMusicClientContent;\n /** Configuration for music generation. */\n musicGenerationConfig?: LiveMusicGenerationConfig;\n /** Playback control signal for the music generation. */\n playbackControl?: LiveMusicPlaybackControl;\n}\n\n/** Sent in response to a `LiveMusicClientSetup` message from the client. */\nexport declare interface LiveMusicServerSetupComplete {}\n\n/** Prompts and config used for generating this audio chunk. */\nexport declare interface LiveMusicSourceMetadata {\n /** Weighted prompts for generating this audio chunk. */\n clientContent?: LiveMusicClientContent;\n /** Music generation config for generating this audio chunk. */\n musicGenerationConfig?: LiveMusicGenerationConfig;\n}\n\n/** Representation of an audio chunk. */\nexport declare interface AudioChunk {\n /** Raw bytes of audio data.\n * @remarks Encoded as base64 string. */\n data?: string;\n /** MIME type of the audio chunk. */\n mimeType?: string;\n /** Prompts and config used for generating this audio chunk. */\n sourceMetadata?: LiveMusicSourceMetadata;\n}\n\n/** Server update generated by the model in response to client messages.\n\nContent is generated as quickly as possible, and not in real time.\nClients may choose to buffer and play it out in real time. */\nexport declare interface LiveMusicServerContent {\n /** The audio chunks that the model has generated. */\n audioChunks?: AudioChunk[];\n}\n\n/** A prompt that was filtered with the reason. */\nexport declare interface LiveMusicFilteredPrompt {\n /** The text prompt that was filtered. */\n text?: string;\n /** The reason the prompt was filtered. */\n filteredReason?: string;\n}\n\n/** Response message for the LiveMusicClientMessage call. */\nexport class LiveMusicServerMessage {\n /** Message sent in response to a `LiveMusicClientSetup` message from the client.\n Clients should wait for this message before sending any additional messages. */\n setupComplete?: LiveMusicServerSetupComplete;\n /** Content generated by the model in response to client messages. */\n serverContent?: LiveMusicServerContent;\n /** A prompt that was filtered with the reason. */\n filteredPrompt?: LiveMusicFilteredPrompt;\n /**\n * Returns the first audio chunk from the server content, if present.\n *\n * @remarks\n * If there are no audio chunks in the response, undefined will be returned.\n */\n get audioChunk(): AudioChunk | undefined {\n if (\n this.serverContent &&\n this.serverContent.audioChunks &&\n this.serverContent.audioChunks.length > 0\n ) {\n return this.serverContent.audioChunks[0];\n }\n return undefined;\n }\n}\n\n/** Callbacks for the realtime music API. */\nexport interface LiveMusicCallbacks {\n /**\n * Called when a message is received from the server.\n */\n onmessage: (e: LiveMusicServerMessage) => void;\n /**\n * Called when an error occurs.\n */\n onerror?: ((e: ErrorEvent) => void) | null;\n /**\n * Called when the websocket connection is closed.\n */\n onclose?: ((e: CloseEvent) => void) | null;\n}\n\n/** Parameters for the upload file method. */\nexport interface UploadFileParameters {\n /** The string path to the file to be uploaded or a Blob object. */\n file: string | globalThis.Blob;\n /** Configuration that contains optional parameters. */\n config?: UploadFileConfig;\n}\n\n/** Parameters for the upload file to file search store method. */\nexport interface UploadToFileSearchStoreParameters {\n /** The name of the file search store to upload. */\n fileSearchStoreName: string;\n /** The string path to the file to be uploaded or a Blob object. */\n file: string | globalThis.Blob;\n /** Configuration that contains optional parameters. */\n config?: UploadToFileSearchStoreConfig;\n}\n\n/**\n * CallableTool is an invokable tool that can be executed with external\n * application (e.g., via Model Context Protocol) or local functions with\n * function calling.\n */\nexport interface CallableTool {\n /**\n * Returns tool that can be called by Gemini.\n */\n tool(): Promise<Tool>;\n /**\n * Executes the callable tool with the given function call arguments and\n * returns the response parts from the tool execution.\n */\n callTool(functionCalls: FunctionCall[]): Promise<Part[]>;\n}\n\n/**\n * CallableToolConfig is the configuration for a callable tool.\n */\nexport interface CallableToolConfig {\n /**\n * Specifies the model's behavior after invoking this tool.\n */\n behavior?: Behavior;\n /**\n * Timeout for remote calls in milliseconds. Note this timeout applies only to\n * tool remote calls, and not making HTTP requests to the API. */\n timeout?: number;\n}\n\n/** Parameters for connecting to the live API. */\nexport declare interface LiveMusicConnectParameters {\n /** The model's resource name. */\n model: string;\n /** Callbacks invoked on server events. */\n callbacks: LiveMusicCallbacks;\n}\n\n/** Parameters for setting config for the live music API. */\nexport declare interface LiveMusicSetConfigParameters {\n /** Configuration for music generation. */\n musicGenerationConfig: LiveMusicGenerationConfig;\n}\n\n/** Parameters for setting weighted prompts for the live music API. */\nexport declare interface LiveMusicSetWeightedPromptsParameters {\n /** A map of text prompts to weights to use for the generation request. */\n weightedPrompts: WeightedPrompt[];\n}\n\n/** Config for auth_tokens.create parameters. */\nexport declare interface AuthToken {\n /** The name of the auth token. */\n name?: string;\n}\n\n/** Config for LiveConnectConstraints for Auth Token creation. */\nexport declare interface LiveConnectConstraints {\n /** ID of the model to configure in the ephemeral token for Live API.\n For a list of models, see `Gemini models\n <https://ai.google.dev/gemini-api/docs/models>`. */\n model?: string;\n /** Configuration specific to Live API connections created using this token. */\n config?: LiveConnectConfig;\n}\n\n/** Optional parameters. */\nexport declare interface CreateAuthTokenConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** An optional time after which, when using the resulting token,\n messages in Live API sessions will be rejected. (Gemini may\n preemptively close the session after this time.)\n\n If not set then this defaults to 30 minutes in the future. If set, this\n value must be less than 20 hours in the future. */\n expireTime?: string;\n /** The time after which new Live API sessions using the token\n resulting from this request will be rejected.\n\n If not set this defaults to 60 seconds in the future. If set, this value\n must be less than 20 hours in the future. */\n newSessionExpireTime?: string;\n /** The number of times the token can be used. If this value is zero\n then no limit is applied. Default is 1. Resuming a Live API session does\n not count as a use. */\n uses?: number;\n /** Configuration specific to Live API connections created using this token. */\n liveConnectConstraints?: LiveConnectConstraints;\n /** Additional fields to lock in the effective LiveConnectParameters. */\n lockAdditionalFields?: string[];\n}\n\n/** Config for auth_tokens.create parameters. */\nexport declare interface CreateAuthTokenParameters {\n /** Optional parameters for the request. */\n config?: CreateAuthTokenConfig;\n}\n\n/** Parameters for the get method of the operations module. */\nexport declare interface OperationGetParameters<T, U extends Operation<T>> {\n /** Used to override the default configuration. */\n config?: GetOperationConfig;\n /** The operation to be retrieved. */\n operation: U;\n}\n\n/** Local tokenizer count tokens result. */\nexport declare interface CountTokensResult {\n /** The total number of tokens. */\n totalTokens?: number;\n}\n\n/** Local tokenizer compute tokens result. */\nexport declare interface ComputeTokensResult {\n /** Lists of tokens info from the input. */\n tokensInfo?: TokensInfo[];\n}\n\n/** Fine-tuning job creation parameters - optional fields. */\nexport declare interface CreateTuningJobParameters {\n /** The base model that is being tuned, e.g., \"gemini-2.5-flash\". */\n baseModel: string;\n /** Cloud Storage path to file containing training dataset for tuning. The dataset must be formatted as a JSONL file. */\n trainingDataset: TuningDataset;\n /** Configuration for the tuning job. */\n config?: CreateTuningJobConfig;\n}\n\n/** The response when long-running operation for uploading a file to a FileSearchStore complete. */\nexport class UploadToFileSearchStoreResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** The name of the FileSearchStore containing Documents. */\n parent?: string;\n /** The identifier for the Document imported. */\n documentName?: string;\n}\n\n/** Long-running operation for uploading a file to a FileSearchStore. */\nexport class UploadToFileSearchStoreOperation\n implements Operation<UploadToFileSearchStoreResponse>\n{\n /** The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`. */\n name?: string;\n /** Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata. Any method that returns a long-running operation should document the metadata type, if any. */\n metadata?: Record<string, unknown>;\n /** If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available. */\n done?: boolean;\n /** The error result of the operation in case of failure or cancellation. */\n error?: Record<string, unknown>;\n /** The result of the UploadToFileSearchStore operation, available when the operation is done. */\n response?: UploadToFileSearchStoreResponse;\n\n /**\n * Instantiates an Operation of the same type as the one being called with the fields set from the API response.\n * @internal\n */\n _fromAPIResponse({\n apiResponse,\n _isVertexAI,\n }: OperationFromAPIResponseParameters): Operation<UploadToFileSearchStoreResponse> {\n const operation = new UploadToFileSearchStoreOperation();\n\n const op = apiResponse as unknown as UploadToFileSearchStoreOperation;\n const response = uploadToFileSearchStoreOperationFromMldev(op);\n Object.assign(operation, response);\n return operation;\n }\n /** The full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n}\n\nexport type BlobImageUnion = Blob;\n\nexport type PartUnion = Part | string;\n\nexport type PartListUnion = PartUnion[] | PartUnion;\n\nexport type ContentUnion = Content | PartUnion[] | PartUnion;\n\nexport type ContentListUnion = Content | Content[] | PartUnion | PartUnion[];\n\nexport type SchemaUnion = Schema | unknown;\n\nexport type SpeechConfigUnion = SpeechConfig | string;\n\nexport type ToolUnion = Tool | CallableTool;\n\nexport type ToolListUnion = ToolUnion[];\n\nexport type DownloadableFileUnion = string | File | GeneratedVideo | Video;\n\nexport type BatchJobSourceUnion = BatchJobSource | InlinedRequest[] | string;\n\nexport type BatchJobDestinationUnion = BatchJobDestination | string;\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type {Tool as McpTool} from '@modelcontextprotocol/sdk/types';\n\nimport {ApiClient} from './_api_client.js';\nimport * as baseTransformers from './_base_transformers.js';\nimport * as types from './types.js';\n\nexport function tModel(apiClient: ApiClient, model: string | unknown): string {\n if (!model || typeof model !== 'string') {\n throw new Error('model is required and must be a string');\n }\n if (model.includes('..') || model.includes('?') || model.includes('&')) {\n throw new Error('invalid model parameter');\n }\n\n if (apiClient.isVertexAI()) {\n if (\n model.startsWith('publishers/') ||\n model.startsWith('projects/') ||\n model.startsWith('models/')\n ) {\n return model;\n } else if (model.indexOf('/') >= 0) {\n const parts = model.split('/', 2);\n return `publishers/${parts[0]}/models/${parts[1]}`;\n } else {\n return `publishers/google/models/${model}`;\n }\n } else {\n if (model.startsWith('models/') || model.startsWith('tunedModels/')) {\n return model;\n } else {\n return `models/${model}`;\n }\n }\n}\n\nexport function tCachesModel(\n apiClient: ApiClient,\n model: string | unknown,\n): string {\n const transformedModel = tModel(apiClient, model as string);\n if (!transformedModel) {\n return '';\n }\n\n if (transformedModel.startsWith('publishers/') && apiClient.isVertexAI()) {\n // vertex caches only support model name start with projects.\n return `projects/${apiClient.getProject()}/locations/${apiClient.getLocation()}/${transformedModel}`;\n } else if (transformedModel.startsWith('models/') && apiClient.isVertexAI()) {\n return `projects/${apiClient.getProject()}/locations/${apiClient.getLocation()}/publishers/google/${transformedModel}`;\n } else {\n return transformedModel;\n }\n}\n\nexport function tBlobs(\n blobs: types.BlobImageUnion | types.BlobImageUnion[],\n): types.Blob[] {\n if (Array.isArray(blobs)) {\n return blobs.map((blob) => tBlob(blob));\n } else {\n return [tBlob(blobs)];\n }\n}\n\nexport function tBlob(blob: types.BlobImageUnion): types.Blob {\n if (typeof blob === 'object' && blob !== null) {\n return blob;\n }\n\n throw new Error(\n `Could not parse input as Blob. Unsupported blob type: ${typeof blob}`,\n );\n}\n\nexport function tImageBlob(blob: types.BlobImageUnion): types.Blob {\n const transformedBlob = tBlob(blob);\n if (\n transformedBlob.mimeType &&\n transformedBlob.mimeType.startsWith('image/')\n ) {\n return transformedBlob;\n }\n throw new Error(`Unsupported mime type: ${transformedBlob.mimeType!}`);\n}\n\nexport function tAudioBlob(blob: types.Blob): types.Blob {\n const transformedBlob = tBlob(blob);\n if (\n transformedBlob.mimeType &&\n transformedBlob.mimeType.startsWith('audio/')\n ) {\n return transformedBlob;\n }\n throw new Error(`Unsupported mime type: ${transformedBlob.mimeType!}`);\n}\n\nexport function tPart(origin?: types.PartUnion | null): types.Part {\n if (origin === null || origin === undefined) {\n throw new Error('PartUnion is required');\n }\n if (typeof origin === 'object') {\n return origin;\n }\n if (typeof origin === 'string') {\n return {text: origin};\n }\n throw new Error(`Unsupported part type: ${typeof origin}`);\n}\n\nexport function tParts(origin?: types.PartListUnion | null): types.Part[] {\n if (\n origin === null ||\n origin === undefined ||\n (Array.isArray(origin) && origin.length === 0)\n ) {\n throw new Error('PartListUnion is required');\n }\n if (Array.isArray(origin)) {\n return origin.map((item) => tPart(item as types.PartUnion)!);\n }\n return [tPart(origin)!];\n}\n\nfunction _isContent(origin: unknown): boolean {\n return (\n origin !== null &&\n origin !== undefined &&\n typeof origin === 'object' &&\n 'parts' in origin &&\n Array.isArray(origin.parts)\n );\n}\n\nfunction _isFunctionCallPart(origin: unknown): boolean {\n return (\n origin !== null &&\n origin !== undefined &&\n typeof origin === 'object' &&\n 'functionCall' in origin\n );\n}\n\nfunction _isFunctionResponsePart(origin: unknown): boolean {\n return (\n origin !== null &&\n origin !== undefined &&\n typeof origin === 'object' &&\n 'functionResponse' in origin\n );\n}\n\nexport function tContent(origin?: types.ContentUnion): types.Content {\n if (origin === null || origin === undefined) {\n throw new Error('ContentUnion is required');\n }\n if (_isContent(origin)) {\n // _isContent is a utility function that checks if the\n // origin is a Content.\n return origin as types.Content;\n }\n\n return {\n role: 'user',\n parts: tParts(origin as types.PartListUnion)!,\n };\n}\n\nexport function tContentsForEmbed(\n apiClient: ApiClient,\n origin: types.ContentListUnion,\n): types.ContentUnion[] {\n if (!origin) {\n return [];\n }\n if (apiClient.isVertexAI() && Array.isArray(origin)) {\n return origin.flatMap((item) => {\n const content = tContent(item as types.ContentUnion);\n if (\n content.parts &&\n content.parts.length > 0 &&\n content.parts[0].text !== undefined\n ) {\n return [content.parts[0].text];\n }\n return [];\n });\n } else if (apiClient.isVertexAI()) {\n const content = tContent(origin as types.ContentUnion);\n if (\n content.parts &&\n content.parts.length > 0 &&\n content.parts[0].text !== undefined\n ) {\n return [content.parts[0].text];\n }\n return [];\n }\n if (Array.isArray(origin)) {\n return origin.map((item) => tContent(item as types.ContentUnion)!);\n }\n return [tContent(origin as types.ContentUnion)!];\n}\n\nexport function tContents(origin?: types.ContentListUnion): types.Content[] {\n if (\n origin === null ||\n origin === undefined ||\n (Array.isArray(origin) && origin.length === 0)\n ) {\n throw new Error('contents are required');\n }\n if (!Array.isArray(origin)) {\n // If it's not an array, it's a single content or a single PartUnion.\n if (_isFunctionCallPart(origin) || _isFunctionResponsePart(origin)) {\n throw new Error(\n 'To specify functionCall or functionResponse parts, please wrap them in a Content object, specifying the role for them',\n );\n }\n return [tContent(origin as types.ContentUnion)];\n }\n\n const result: types.Content[] = [];\n const accumulatedParts: types.PartUnion[] = [];\n const isContentArray = _isContent(origin[0]);\n\n for (const item of origin) {\n const isContent = _isContent(item);\n\n if (isContent != isContentArray) {\n throw new Error(\n 'Mixing Content and Parts is not supported, please group the parts into a the appropriate Content objects and specify the roles for them',\n );\n }\n\n if (isContent) {\n // `isContent` contains the result of _isContent, which is a utility\n // function that checks if the item is a Content.\n result.push(item as types.Content);\n } else if (_isFunctionCallPart(item) || _isFunctionResponsePart(item)) {\n throw new Error(\n 'To specify functionCall or functionResponse parts, please wrap them, and any other parts, in Content objects as appropriate, specifying the role for them',\n );\n } else {\n accumulatedParts.push(item as types.PartUnion);\n }\n }\n\n if (!isContentArray) {\n result.push({role: 'user', parts: tParts(accumulatedParts)});\n }\n return result;\n}\n\n/*\nTransform the type field from an array of types to an array of anyOf fields.\nExample:\n {type: ['STRING', 'NUMBER']}\nwill be transformed to\n {anyOf: [{type: 'STRING'}, {type: 'NUMBER'}]}\n*/\nfunction flattenTypeArrayToAnyOf(\n typeList: string[],\n resultingSchema: types.Schema,\n) {\n if (typeList.includes('null')) {\n resultingSchema['nullable'] = true;\n }\n const listWithoutNull = typeList.filter((type) => type !== 'null');\n\n if (listWithoutNull.length === 1) {\n resultingSchema['type'] = Object.values(types.Type).includes(\n listWithoutNull[0].toUpperCase() as types.Type,\n )\n ? (listWithoutNull[0].toUpperCase() as types.Type)\n : types.Type.TYPE_UNSPECIFIED;\n } else {\n resultingSchema['anyOf'] = [];\n for (const i of listWithoutNull) {\n resultingSchema['anyOf'].push({\n 'type': Object.values(types.Type).includes(\n i.toUpperCase() as types.Type,\n )\n ? (i.toUpperCase() as types.Type)\n : types.Type.TYPE_UNSPECIFIED,\n });\n }\n }\n}\n\nexport function processJsonSchema(\n _jsonSchema: types.Schema | Record<string, unknown>,\n): types.Schema {\n const genAISchema: types.Schema = {};\n const schemaFieldNames = ['items'];\n const listSchemaFieldNames = ['anyOf'];\n const dictSchemaFieldNames = ['properties'];\n\n if (_jsonSchema['type'] && _jsonSchema['anyOf']) {\n throw new Error('type and anyOf cannot be both populated.');\n }\n\n /*\n This is to handle the nullable array or object. The _jsonSchema will\n be in the format of {anyOf: [{type: 'null'}, {type: 'object'}]}. The\n logic is to check if anyOf has 2 elements and one of the element is null,\n if so, the anyOf field is unnecessary, so we need to get rid of the anyOf\n field and make the schema nullable. Then use the other element as the new\n _jsonSchema for processing. This is because the backend doesn't have a null\n type.\n This has to be checked before we process any other fields.\n For example:\n const objectNullable = z.object({\n nullableArray: z.array(z.string()).nullable(),\n });\n Will have the raw _jsonSchema as:\n {\n type: 'OBJECT',\n properties: {\n nullableArray: {\n anyOf: [\n {type: 'null'},\n {\n type: 'array',\n items: {type: 'string'},\n },\n ],\n }\n },\n required: [ 'nullableArray' ],\n }\n Will result in following schema compatible with Gemini API:\n {\n type: 'OBJECT',\n properties: {\n nullableArray: {\n nullable: true,\n type: 'ARRAY',\n items: {type: 'string'},\n }\n },\n required: [ 'nullableArray' ],\n }\n */\n const incomingAnyOf = _jsonSchema['anyOf'] as Record<string, unknown>[];\n if (incomingAnyOf != null && incomingAnyOf.length == 2) {\n if (incomingAnyOf[0]!['type'] === 'null') {\n genAISchema['nullable'] = true;\n _jsonSchema = incomingAnyOf![1];\n } else if (incomingAnyOf[1]!['type'] === 'null') {\n genAISchema['nullable'] = true;\n _jsonSchema = incomingAnyOf![0];\n }\n }\n\n if (_jsonSchema['type'] instanceof Array) {\n flattenTypeArrayToAnyOf(_jsonSchema['type'], genAISchema);\n }\n\n for (const [fieldName, fieldValue] of Object.entries(_jsonSchema)) {\n // Skip if the fieldvalue is undefined or null.\n if (fieldValue == null) {\n continue;\n }\n\n if (fieldName == 'type') {\n if (fieldValue === 'null') {\n throw new Error(\n 'type: null can not be the only possible type for the field.',\n );\n }\n if (fieldValue instanceof Array) {\n // we have already handled the type field with array of types in the\n // beginning of this function.\n continue;\n }\n genAISchema['type'] = Object.values(types.Type).includes(\n fieldValue.toUpperCase() as types.Type,\n )\n ? fieldValue.toUpperCase()\n : types.Type.TYPE_UNSPECIFIED;\n } else if (schemaFieldNames.includes(fieldName)) {\n (genAISchema as Record<string, unknown>)[fieldName] =\n processJsonSchema(fieldValue);\n } else if (listSchemaFieldNames.includes(fieldName)) {\n const listSchemaFieldValue: Array<types.Schema> = [];\n for (const item of fieldValue) {\n if (item['type'] == 'null') {\n genAISchema['nullable'] = true;\n continue;\n }\n listSchemaFieldValue.push(\n processJsonSchema(item as Record<string, unknown>),\n );\n }\n (genAISchema as Record<string, unknown>)[fieldName] =\n listSchemaFieldValue;\n } else if (dictSchemaFieldNames.includes(fieldName)) {\n const dictSchemaFieldValue: Record<string, types.Schema> = {};\n for (const [key, value] of Object.entries(\n fieldValue as Record<string, unknown>,\n )) {\n dictSchemaFieldValue[key] = processJsonSchema(\n value as Record<string, unknown>,\n );\n }\n (genAISchema as Record<string, unknown>)[fieldName] =\n dictSchemaFieldValue;\n } else {\n // additionalProperties is not included in JSONSchema, skipping it.\n if (fieldName === 'additionalProperties') {\n continue;\n }\n (genAISchema as Record<string, unknown>)[fieldName] = fieldValue;\n }\n }\n return genAISchema;\n}\n\n// we take the unknown in the schema field because we want enable user to pass\n// the output of major schema declaration tools without casting. Tools such as\n// zodToJsonSchema, typebox, zodToJsonSchema function can return JsonSchema7Type\n// or object, see details in\n// https://github.com/StefanTerdell/zod-to-json-schema/blob/70525efe555cd226691e093d171370a3b10921d1/src/zodToJsonSchema.ts#L7\n// typebox can return unknown, see details in\n// https://github.com/sinclairzx81/typebox/blob/5a5431439f7d5ca6b494d0d18fbfd7b1a356d67c/src/type/create/type.ts#L35\n// Note: proper json schemas with the $schema field set never arrive to this\n// transformer. Schemas with $schema are routed to the equivalent API json\n// schema field.\nexport function tSchema(schema: types.Schema | unknown): types.Schema {\n return processJsonSchema(schema as types.Schema);\n}\n\nexport function tSpeechConfig(\n speechConfig: types.SpeechConfigUnion,\n): types.SpeechConfig {\n if (typeof speechConfig === 'object') {\n return speechConfig;\n } else if (typeof speechConfig === 'string') {\n return {\n voiceConfig: {\n prebuiltVoiceConfig: {\n voiceName: speechConfig,\n },\n },\n };\n } else {\n throw new Error(`Unsupported speechConfig type: ${typeof speechConfig}`);\n }\n}\n\nexport function tLiveSpeechConfig(\n speechConfig: types.SpeechConfig | object,\n): types.SpeechConfig {\n if ('multiSpeakerVoiceConfig' in speechConfig) {\n throw new Error(\n 'multiSpeakerVoiceConfig is not supported in the live API.',\n );\n }\n return speechConfig;\n}\n\nexport function tTool(tool: types.Tool): types.Tool {\n if (tool.functionDeclarations) {\n for (const functionDeclaration of tool.functionDeclarations) {\n if (functionDeclaration.parameters) {\n if (!Object.keys(functionDeclaration.parameters).includes('$schema')) {\n functionDeclaration.parameters = processJsonSchema(\n functionDeclaration.parameters,\n );\n } else {\n if (!functionDeclaration.parametersJsonSchema) {\n functionDeclaration.parametersJsonSchema =\n functionDeclaration.parameters;\n delete functionDeclaration.parameters;\n }\n }\n }\n if (functionDeclaration.response) {\n if (!Object.keys(functionDeclaration.response).includes('$schema')) {\n functionDeclaration.response = processJsonSchema(\n functionDeclaration.response,\n );\n } else {\n if (!functionDeclaration.responseJsonSchema) {\n functionDeclaration.responseJsonSchema =\n functionDeclaration.response;\n delete functionDeclaration.response;\n }\n }\n }\n }\n }\n return tool;\n}\n\nexport function tTools(tools: types.ToolListUnion | unknown): types.Tool[] {\n // Check if the incoming type is defined.\n if (tools === undefined || tools === null) {\n throw new Error('tools is required');\n }\n if (!Array.isArray(tools)) {\n throw new Error('tools is required and must be an array of Tools');\n }\n const result: types.Tool[] = [];\n for (const tool of tools) {\n result.push(tool as types.Tool);\n }\n return result;\n}\n\n/**\n * Prepends resource name with project, location, resource_prefix if needed.\n *\n * @param client The API client.\n * @param resourceName The resource name.\n * @param resourcePrefix The resource prefix.\n * @param splitsAfterPrefix The number of splits after the prefix.\n * @returns The completed resource name.\n *\n * Examples:\n *\n * ```\n * resource_name = '123'\n * resource_prefix = 'cachedContents'\n * splits_after_prefix = 1\n * client.vertexai = True\n * client.project = 'bar'\n * client.location = 'us-west1'\n * _resource_name(client, resource_name, resource_prefix, splits_after_prefix)\n * returns: 'projects/bar/locations/us-west1/cachedContents/123'\n * ```\n *\n * ```\n * resource_name = 'projects/foo/locations/us-central1/cachedContents/123'\n * resource_prefix = 'cachedContents'\n * splits_after_prefix = 1\n * client.vertexai = True\n * client.project = 'bar'\n * client.location = 'us-west1'\n * _resource_name(client, resource_name, resource_prefix, splits_after_prefix)\n * returns: 'projects/foo/locations/us-central1/cachedContents/123'\n * ```\n *\n * ```\n * resource_name = '123'\n * resource_prefix = 'cachedContents'\n * splits_after_prefix = 1\n * client.vertexai = False\n * _resource_name(client, resource_name, resource_prefix, splits_after_prefix)\n * returns 'cachedContents/123'\n * ```\n *\n * ```\n * resource_name = 'some/wrong/cachedContents/resource/name/123'\n * resource_prefix = 'cachedContents'\n * splits_after_prefix = 1\n * client.vertexai = False\n * # client.vertexai = True\n * _resource_name(client, resource_name, resource_prefix, splits_after_prefix)\n * -> 'some/wrong/resource/name/123'\n * ```\n */\nfunction resourceName(\n client: ApiClient,\n resourceName: string,\n resourcePrefix: string,\n splitsAfterPrefix: number = 1,\n): string {\n const shouldAppendPrefix =\n !resourceName.startsWith(`${resourcePrefix}/`) &&\n resourceName.split('/').length === splitsAfterPrefix;\n if (client.isVertexAI()) {\n if (resourceName.startsWith('projects/')) {\n return resourceName;\n } else if (resourceName.startsWith('locations/')) {\n return `projects/${client.getProject()}/${resourceName}`;\n } else if (resourceName.startsWith(`${resourcePrefix}/`)) {\n return `projects/${client.getProject()}/locations/${client.getLocation()}/${resourceName}`;\n } else if (shouldAppendPrefix) {\n return `projects/${client.getProject()}/locations/${client.getLocation()}/${resourcePrefix}/${resourceName}`;\n } else {\n return resourceName;\n }\n }\n if (shouldAppendPrefix) {\n return `${resourcePrefix}/${resourceName}`;\n }\n return resourceName;\n}\n\nexport function tCachedContentName(\n apiClient: ApiClient,\n name: string | unknown,\n): string {\n if (typeof name !== 'string') {\n throw new Error('name must be a string');\n }\n return resourceName(apiClient, name, 'cachedContents');\n}\n\nexport function tTuningJobStatus(status: string | unknown): string {\n switch (status) {\n case 'STATE_UNSPECIFIED':\n return 'JOB_STATE_UNSPECIFIED';\n case 'CREATING':\n return 'JOB_STATE_RUNNING';\n case 'ACTIVE':\n return 'JOB_STATE_SUCCEEDED';\n case 'FAILED':\n return 'JOB_STATE_FAILED';\n default:\n return status as string;\n }\n}\n\nexport function tBytes(fromImageBytes: string | unknown): string {\n return baseTransformers.tBytes(fromImageBytes);\n}\n\nfunction _isFile(origin: unknown): boolean {\n return (\n origin !== null &&\n origin !== undefined &&\n typeof origin === 'object' &&\n 'name' in origin\n );\n}\n\nexport function isGeneratedVideo(origin: unknown): boolean {\n return (\n origin !== null &&\n origin !== undefined &&\n typeof origin === 'object' &&\n 'video' in origin\n );\n}\n\nexport function isVideo(origin: unknown): boolean {\n return (\n origin !== null &&\n origin !== undefined &&\n typeof origin === 'object' &&\n 'uri' in origin\n );\n}\n\nexport function tFileName(\n fromName: string | types.File | types.GeneratedVideo | types.Video,\n): string | undefined {\n let name: string | undefined;\n\n if (_isFile(fromName)) {\n name = (fromName as types.File).name;\n }\n if (isVideo(fromName)) {\n name = (fromName as types.Video).uri;\n if (name === undefined) {\n return undefined;\n }\n }\n if (isGeneratedVideo(fromName)) {\n name = (fromName as types.GeneratedVideo).video?.uri;\n if (name === undefined) {\n return undefined;\n }\n }\n if (typeof fromName === 'string') {\n name = fromName;\n }\n\n if (name === undefined) {\n throw new Error('Could not extract file name from the provided input.');\n }\n\n if (name.startsWith('https://')) {\n const suffix = name.split('files/')[1];\n const match = suffix.match(/[a-z0-9]+/);\n if (match === null) {\n throw new Error(`Could not extract file name from URI ${name}`);\n }\n name = match[0];\n } else if (name.startsWith('files/')) {\n name = name.split('files/')[1];\n }\n return name;\n}\n\nexport function tModelsUrl(\n apiClient: ApiClient,\n baseModels: boolean | unknown,\n): string {\n let res: string;\n if (apiClient.isVertexAI()) {\n res = baseModels ? 'publishers/google/models' : 'models';\n } else {\n res = baseModels ? 'models' : 'tunedModels';\n }\n return res;\n}\n\nexport function tExtractModels(response: unknown): Record<string, unknown>[] {\n for (const key of ['models', 'tunedModels', 'publisherModels']) {\n if (hasField(response, key)) {\n return (response as Record<string, unknown>)[key] as Record<\n string,\n unknown\n >[];\n }\n }\n return [];\n}\n\nfunction hasField(data: unknown, fieldName: string): boolean {\n return data !== null && typeof data === 'object' && fieldName in data;\n}\n\nexport function mcpToGeminiTool(\n mcpTool: McpTool,\n config: types.CallableToolConfig = {},\n): types.Tool {\n const mcpToolSchema = mcpTool as Record<string, unknown>;\n const functionDeclaration: Record<string, unknown> = {\n name: mcpToolSchema['name'],\n description: mcpToolSchema['description'],\n parametersJsonSchema: mcpToolSchema['inputSchema'],\n };\n if (mcpToolSchema['outputSchema']) {\n functionDeclaration['responseJsonSchema'] = mcpToolSchema['outputSchema'];\n }\n if (config.behavior) {\n functionDeclaration['behavior'] = config.behavior;\n }\n\n const geminiTool = {\n functionDeclarations: [\n functionDeclaration as unknown as types.FunctionDeclaration,\n ],\n };\n\n return geminiTool;\n}\n\n/**\n * Converts a list of MCP tools to a single Gemini tool with a list of function\n * declarations.\n */\nexport function mcpToolsToGeminiTool(\n mcpTools: McpTool[],\n config: types.CallableToolConfig = {},\n): types.Tool {\n const functionDeclarations: types.FunctionDeclaration[] = [];\n const toolNames = new Set<string>();\n for (const mcpTool of mcpTools) {\n const mcpToolName = mcpTool.name as string;\n if (toolNames.has(mcpToolName)) {\n throw new Error(\n `Duplicate function name ${\n mcpToolName\n } found in MCP tools. Please ensure function names are unique.`,\n );\n }\n toolNames.add(mcpToolName);\n const geminiTool = mcpToGeminiTool(mcpTool, config);\n if (geminiTool.functionDeclarations) {\n functionDeclarations.push(...geminiTool.functionDeclarations);\n }\n }\n\n return {functionDeclarations: functionDeclarations};\n}\n\n// Transforms a source input into a BatchJobSource object with validation.\nexport function tBatchJobSource(\n client: ApiClient,\n src: string | types.InlinedRequest[] | types.BatchJobSource,\n): types.BatchJobSource {\n let sourceObj: types.BatchJobSource;\n\n if (typeof src === 'string') {\n if (client.isVertexAI()) {\n if (src.startsWith('gs://')) {\n sourceObj = {format: 'jsonl', gcsUri: [src]};\n } else if (src.startsWith('bq://')) {\n sourceObj = {format: 'bigquery', bigqueryUri: src};\n } else {\n throw new Error(`Unsupported string source for Vertex AI: ${src}`);\n }\n } else {\n // MLDEV\n if (src.startsWith('files/')) {\n sourceObj = {fileName: src}; // Default to fileName for string input\n } else {\n throw new Error(`Unsupported string source for Gemini API: ${src}`);\n }\n }\n } else if (Array.isArray(src)) {\n if (client.isVertexAI()) {\n throw new Error('InlinedRequest[] is not supported in Vertex AI.');\n }\n sourceObj = {inlinedRequests: src};\n } else {\n // It's already a BatchJobSource object\n sourceObj = src;\n }\n\n // Validation logic\n const vertexSourcesCount = [sourceObj.gcsUri, sourceObj.bigqueryUri].filter(\n Boolean,\n ).length;\n\n const mldevSourcesCount = [\n sourceObj.inlinedRequests,\n sourceObj.fileName,\n ].filter(Boolean).length;\n\n if (client.isVertexAI()) {\n if (mldevSourcesCount > 0 || vertexSourcesCount !== 1) {\n throw new Error(\n 'Exactly one of `gcsUri` or `bigqueryUri` must be set for Vertex AI.',\n );\n }\n } else {\n // MLDEV\n if (vertexSourcesCount > 0 || mldevSourcesCount !== 1) {\n throw new Error(\n 'Exactly one of `inlinedRequests`, `fileName`, ' +\n 'must be set for Gemini API.',\n );\n }\n }\n\n return sourceObj;\n}\n\nexport function tEmbeddingBatchJobSource(\n client: ApiClient,\n src: types.EmbeddingsBatchJobSource,\n): types.EmbeddingsBatchJobSource {\n if (client.isVertexAI()) {\n throw new Error('Embedding batch jobs are not supported in Vertex AI.');\n }\n\n const sourceObj: types.EmbeddingsBatchJobSource = {...src};\n\n const mldevSources =\n Number(!!sourceObj.inlinedRequests) + Number(!!sourceObj.fileName);\n\n if (mldevSources !== 1) {\n throw new Error(\n 'Exactly one of `inlinedRequests` or `fileName` must be set for Embedding Batch Jobs in the Gemini API.',\n );\n }\n return sourceObj;\n}\n\nexport function tBatchJobDestination(\n dest: string | types.BatchJobDestination,\n): types.BatchJobDestination {\n if (typeof dest !== 'string') {\n return dest as types.BatchJobDestination;\n }\n const destString = dest as string;\n if (destString.startsWith('gs://')) {\n return {\n format: 'jsonl',\n gcsUri: destString,\n };\n } else if (destString.startsWith('bq://')) {\n return {\n format: 'bigquery',\n bigqueryUri: destString,\n };\n } else {\n throw new Error(`Unsupported destination: ${destString}`);\n }\n}\n\nexport function tRecvBatchJobDestination(\n dest: unknown,\n): types.BatchJobDestination {\n // Ensure dest is a non-null object before proceeding.\n if (typeof dest !== 'object' || dest === null) {\n // If the input is not an object, it cannot be a valid BatchJobDestination\n // based on the operations performed. Return it cast, or handle as an error.\n // Casting an empty object might be a safe default.\n return {} as types.BatchJobDestination;\n }\n\n // Cast to Record<string, unknown> to allow string property access.\n const obj = dest as Record<string, unknown>;\n\n // Safely access nested properties.\n const inlineResponsesVal = obj['inlinedResponses'];\n if (typeof inlineResponsesVal !== 'object' || inlineResponsesVal === null) {\n return dest as types.BatchJobDestination;\n }\n const inlineResponsesObj = inlineResponsesVal as Record<string, unknown>;\n\n const responsesArray = inlineResponsesObj['inlinedResponses'];\n if (!Array.isArray(responsesArray) || responsesArray.length === 0) {\n return dest as types.BatchJobDestination;\n }\n\n // Check if any response has the 'embedding' property.\n let hasEmbedding = false;\n for (const responseItem of responsesArray) {\n if (typeof responseItem !== 'object' || responseItem === null) {\n continue;\n }\n const responseItemObj = responseItem as Record<string, unknown>;\n\n const responseVal = responseItemObj['response'];\n if (typeof responseVal !== 'object' || responseVal === null) {\n continue;\n }\n const responseObj = responseVal as Record<string, unknown>;\n\n // Check for the existence of the 'embedding' key.\n if (responseObj['embedding'] !== undefined) {\n hasEmbedding = true;\n break;\n }\n }\n\n // Perform the transformation if an embedding was found.\n if (hasEmbedding) {\n obj['inlinedEmbedContentResponses'] = obj['inlinedResponses'];\n delete obj['inlinedResponses'];\n }\n\n // Cast the (potentially) modified object to the target type.\n return dest as types.BatchJobDestination;\n}\n\nexport function tBatchJobName(apiClient: ApiClient, name: unknown): string {\n const nameString = name as string;\n if (!apiClient.isVertexAI()) {\n const mldevPattern = /batches\\/[^/]+$/;\n\n if (mldevPattern.test(nameString)) {\n return nameString.split('/').pop() as string;\n } else {\n throw new Error(`Invalid batch job name: ${nameString}.`);\n }\n }\n\n const vertexPattern =\n /^projects\\/[^/]+\\/locations\\/[^/]+\\/batchPredictionJobs\\/[^/]+$/;\n\n if (vertexPattern.test(nameString)) {\n return nameString.split('/').pop() as string;\n } else if (/^\\d+$/.test(nameString)) {\n return nameString;\n } else {\n throw new Error(`Invalid batch job name: ${nameString}.`);\n }\n}\n\nexport function tJobState(state: unknown): string {\n const stateString = state as string;\n if (stateString === 'BATCH_STATE_UNSPECIFIED') {\n return 'JOB_STATE_UNSPECIFIED';\n } else if (stateString === 'BATCH_STATE_PENDING') {\n return 'JOB_STATE_PENDING';\n } else if (stateString === 'BATCH_STATE_RUNNING') {\n return 'JOB_STATE_RUNNING';\n } else if (stateString === 'BATCH_STATE_SUCCEEDED') {\n return 'JOB_STATE_SUCCEEDED';\n } else if (stateString === 'BATCH_STATE_FAILED') {\n return 'JOB_STATE_FAILED';\n } else if (stateString === 'BATCH_STATE_CANCELLED') {\n return 'JOB_STATE_CANCELLED';\n } else if (stateString === 'BATCH_STATE_EXPIRED') {\n return 'JOB_STATE_EXPIRED';\n } else {\n return stateString;\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport {ApiClient} from '../_api_client.js';\nimport * as common from '../_common.js';\nimport * as t from '../_transformers.js';\nimport type * as types from '../types.js';\n\nexport function batchJobDestinationFromMldev(\n fromObject: types.BatchJobDestination,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromFileName = common.getValueByPath(fromObject, ['responsesFile']);\n if (fromFileName != null) {\n common.setValueByPath(toObject, ['fileName'], fromFileName);\n }\n\n const fromInlinedResponses = common.getValueByPath(fromObject, [\n 'inlinedResponses',\n 'inlinedResponses',\n ]);\n if (fromInlinedResponses != null) {\n let transformedList = fromInlinedResponses;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return inlinedResponseFromMldev(item);\n });\n }\n common.setValueByPath(toObject, ['inlinedResponses'], transformedList);\n }\n\n const fromInlinedEmbedContentResponses = common.getValueByPath(fromObject, [\n 'inlinedEmbedContentResponses',\n 'inlinedResponses',\n ]);\n if (fromInlinedEmbedContentResponses != null) {\n let transformedList = fromInlinedEmbedContentResponses;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(\n toObject,\n ['inlinedEmbedContentResponses'],\n transformedList,\n );\n }\n\n return toObject;\n}\n\nexport function batchJobDestinationFromVertex(\n fromObject: types.BatchJobDestination,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromFormat = common.getValueByPath(fromObject, ['predictionsFormat']);\n if (fromFormat != null) {\n common.setValueByPath(toObject, ['format'], fromFormat);\n }\n\n const fromGcsUri = common.getValueByPath(fromObject, [\n 'gcsDestination',\n 'outputUriPrefix',\n ]);\n if (fromGcsUri != null) {\n common.setValueByPath(toObject, ['gcsUri'], fromGcsUri);\n }\n\n const fromBigqueryUri = common.getValueByPath(fromObject, [\n 'bigqueryDestination',\n 'outputUri',\n ]);\n if (fromBigqueryUri != null) {\n common.setValueByPath(toObject, ['bigqueryUri'], fromBigqueryUri);\n }\n\n return toObject;\n}\n\nexport function batchJobDestinationToVertex(\n fromObject: types.BatchJobDestination,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromFormat = common.getValueByPath(fromObject, ['format']);\n if (fromFormat != null) {\n common.setValueByPath(toObject, ['predictionsFormat'], fromFormat);\n }\n\n const fromGcsUri = common.getValueByPath(fromObject, ['gcsUri']);\n if (fromGcsUri != null) {\n common.setValueByPath(\n toObject,\n ['gcsDestination', 'outputUriPrefix'],\n fromGcsUri,\n );\n }\n\n const fromBigqueryUri = common.getValueByPath(fromObject, ['bigqueryUri']);\n if (fromBigqueryUri != null) {\n common.setValueByPath(\n toObject,\n ['bigqueryDestination', 'outputUri'],\n fromBigqueryUri,\n );\n }\n\n if (common.getValueByPath(fromObject, ['fileName']) !== undefined) {\n throw new Error('fileName parameter is not supported in Vertex AI.');\n }\n\n if (common.getValueByPath(fromObject, ['inlinedResponses']) !== undefined) {\n throw new Error(\n 'inlinedResponses parameter is not supported in Vertex AI.',\n );\n }\n\n if (\n common.getValueByPath(fromObject, ['inlinedEmbedContentResponses']) !==\n undefined\n ) {\n throw new Error(\n 'inlinedEmbedContentResponses parameter is not supported in Vertex AI.',\n );\n }\n\n return toObject;\n}\n\nexport function batchJobFromMldev(\n fromObject: types.BatchJob,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromDisplayName = common.getValueByPath(fromObject, [\n 'metadata',\n 'displayName',\n ]);\n if (fromDisplayName != null) {\n common.setValueByPath(toObject, ['displayName'], fromDisplayName);\n }\n\n const fromState = common.getValueByPath(fromObject, ['metadata', 'state']);\n if (fromState != null) {\n common.setValueByPath(toObject, ['state'], t.tJobState(fromState));\n }\n\n const fromCreateTime = common.getValueByPath(fromObject, [\n 'metadata',\n 'createTime',\n ]);\n if (fromCreateTime != null) {\n common.setValueByPath(toObject, ['createTime'], fromCreateTime);\n }\n\n const fromEndTime = common.getValueByPath(fromObject, [\n 'metadata',\n 'endTime',\n ]);\n if (fromEndTime != null) {\n common.setValueByPath(toObject, ['endTime'], fromEndTime);\n }\n\n const fromUpdateTime = common.getValueByPath(fromObject, [\n 'metadata',\n 'updateTime',\n ]);\n if (fromUpdateTime != null) {\n common.setValueByPath(toObject, ['updateTime'], fromUpdateTime);\n }\n\n const fromModel = common.getValueByPath(fromObject, ['metadata', 'model']);\n if (fromModel != null) {\n common.setValueByPath(toObject, ['model'], fromModel);\n }\n\n const fromDest = common.getValueByPath(fromObject, ['metadata', 'output']);\n if (fromDest != null) {\n common.setValueByPath(\n toObject,\n ['dest'],\n batchJobDestinationFromMldev(t.tRecvBatchJobDestination(fromDest)),\n );\n }\n\n return toObject;\n}\n\nexport function batchJobFromVertex(\n fromObject: types.BatchJob,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromDisplayName = common.getValueByPath(fromObject, ['displayName']);\n if (fromDisplayName != null) {\n common.setValueByPath(toObject, ['displayName'], fromDisplayName);\n }\n\n const fromState = common.getValueByPath(fromObject, ['state']);\n if (fromState != null) {\n common.setValueByPath(toObject, ['state'], t.tJobState(fromState));\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n const fromCreateTime = common.getValueByPath(fromObject, ['createTime']);\n if (fromCreateTime != null) {\n common.setValueByPath(toObject, ['createTime'], fromCreateTime);\n }\n\n const fromStartTime = common.getValueByPath(fromObject, ['startTime']);\n if (fromStartTime != null) {\n common.setValueByPath(toObject, ['startTime'], fromStartTime);\n }\n\n const fromEndTime = common.getValueByPath(fromObject, ['endTime']);\n if (fromEndTime != null) {\n common.setValueByPath(toObject, ['endTime'], fromEndTime);\n }\n\n const fromUpdateTime = common.getValueByPath(fromObject, ['updateTime']);\n if (fromUpdateTime != null) {\n common.setValueByPath(toObject, ['updateTime'], fromUpdateTime);\n }\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(toObject, ['model'], fromModel);\n }\n\n const fromSrc = common.getValueByPath(fromObject, ['inputConfig']);\n if (fromSrc != null) {\n common.setValueByPath(toObject, ['src'], batchJobSourceFromVertex(fromSrc));\n }\n\n const fromDest = common.getValueByPath(fromObject, ['outputConfig']);\n if (fromDest != null) {\n common.setValueByPath(\n toObject,\n ['dest'],\n batchJobDestinationFromVertex(t.tRecvBatchJobDestination(fromDest)),\n );\n }\n\n const fromCompletionStats = common.getValueByPath(fromObject, [\n 'completionStats',\n ]);\n if (fromCompletionStats != null) {\n common.setValueByPath(toObject, ['completionStats'], fromCompletionStats);\n }\n\n return toObject;\n}\n\nexport function batchJobSourceFromVertex(\n fromObject: types.BatchJobSource,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromFormat = common.getValueByPath(fromObject, ['instancesFormat']);\n if (fromFormat != null) {\n common.setValueByPath(toObject, ['format'], fromFormat);\n }\n\n const fromGcsUri = common.getValueByPath(fromObject, ['gcsSource', 'uris']);\n if (fromGcsUri != null) {\n common.setValueByPath(toObject, ['gcsUri'], fromGcsUri);\n }\n\n const fromBigqueryUri = common.getValueByPath(fromObject, [\n 'bigquerySource',\n 'inputUri',\n ]);\n if (fromBigqueryUri != null) {\n common.setValueByPath(toObject, ['bigqueryUri'], fromBigqueryUri);\n }\n\n return toObject;\n}\n\nexport function batchJobSourceToMldev(\n apiClient: ApiClient,\n fromObject: types.BatchJobSource,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['format']) !== undefined) {\n throw new Error('format parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['gcsUri']) !== undefined) {\n throw new Error('gcsUri parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['bigqueryUri']) !== undefined) {\n throw new Error('bigqueryUri parameter is not supported in Gemini API.');\n }\n\n const fromFileName = common.getValueByPath(fromObject, ['fileName']);\n if (fromFileName != null) {\n common.setValueByPath(toObject, ['fileName'], fromFileName);\n }\n\n const fromInlinedRequests = common.getValueByPath(fromObject, [\n 'inlinedRequests',\n ]);\n if (fromInlinedRequests != null) {\n let transformedList = fromInlinedRequests;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return inlinedRequestToMldev(apiClient, item);\n });\n }\n common.setValueByPath(toObject, ['requests', 'requests'], transformedList);\n }\n\n return toObject;\n}\n\nexport function batchJobSourceToVertex(\n fromObject: types.BatchJobSource,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromFormat = common.getValueByPath(fromObject, ['format']);\n if (fromFormat != null) {\n common.setValueByPath(toObject, ['instancesFormat'], fromFormat);\n }\n\n const fromGcsUri = common.getValueByPath(fromObject, ['gcsUri']);\n if (fromGcsUri != null) {\n common.setValueByPath(toObject, ['gcsSource', 'uris'], fromGcsUri);\n }\n\n const fromBigqueryUri = common.getValueByPath(fromObject, ['bigqueryUri']);\n if (fromBigqueryUri != null) {\n common.setValueByPath(\n toObject,\n ['bigquerySource', 'inputUri'],\n fromBigqueryUri,\n );\n }\n\n if (common.getValueByPath(fromObject, ['fileName']) !== undefined) {\n throw new Error('fileName parameter is not supported in Vertex AI.');\n }\n\n if (common.getValueByPath(fromObject, ['inlinedRequests']) !== undefined) {\n throw new Error('inlinedRequests parameter is not supported in Vertex AI.');\n }\n\n return toObject;\n}\n\nexport function blobToMldev(fromObject: types.Blob): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromData = common.getValueByPath(fromObject, ['data']);\n if (fromData != null) {\n common.setValueByPath(toObject, ['data'], fromData);\n }\n\n if (common.getValueByPath(fromObject, ['displayName']) !== undefined) {\n throw new Error('displayName parameter is not supported in Gemini API.');\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function cancelBatchJobParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.CancelBatchJobParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tBatchJobName(apiClient, fromName),\n );\n }\n\n return toObject;\n}\n\nexport function cancelBatchJobParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.CancelBatchJobParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tBatchJobName(apiClient, fromName),\n );\n }\n\n return toObject;\n}\n\nexport function candidateFromMldev(\n fromObject: types.Candidate,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromContent = common.getValueByPath(fromObject, ['content']);\n if (fromContent != null) {\n common.setValueByPath(toObject, ['content'], fromContent);\n }\n\n const fromCitationMetadata = common.getValueByPath(fromObject, [\n 'citationMetadata',\n ]);\n if (fromCitationMetadata != null) {\n common.setValueByPath(\n toObject,\n ['citationMetadata'],\n citationMetadataFromMldev(fromCitationMetadata),\n );\n }\n\n const fromTokenCount = common.getValueByPath(fromObject, ['tokenCount']);\n if (fromTokenCount != null) {\n common.setValueByPath(toObject, ['tokenCount'], fromTokenCount);\n }\n\n const fromFinishReason = common.getValueByPath(fromObject, ['finishReason']);\n if (fromFinishReason != null) {\n common.setValueByPath(toObject, ['finishReason'], fromFinishReason);\n }\n\n const fromAvgLogprobs = common.getValueByPath(fromObject, ['avgLogprobs']);\n if (fromAvgLogprobs != null) {\n common.setValueByPath(toObject, ['avgLogprobs'], fromAvgLogprobs);\n }\n\n const fromGroundingMetadata = common.getValueByPath(fromObject, [\n 'groundingMetadata',\n ]);\n if (fromGroundingMetadata != null) {\n common.setValueByPath(\n toObject,\n ['groundingMetadata'],\n fromGroundingMetadata,\n );\n }\n\n const fromIndex = common.getValueByPath(fromObject, ['index']);\n if (fromIndex != null) {\n common.setValueByPath(toObject, ['index'], fromIndex);\n }\n\n const fromLogprobsResult = common.getValueByPath(fromObject, [\n 'logprobsResult',\n ]);\n if (fromLogprobsResult != null) {\n common.setValueByPath(toObject, ['logprobsResult'], fromLogprobsResult);\n }\n\n const fromSafetyRatings = common.getValueByPath(fromObject, [\n 'safetyRatings',\n ]);\n if (fromSafetyRatings != null) {\n let transformedList = fromSafetyRatings;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['safetyRatings'], transformedList);\n }\n\n const fromUrlContextMetadata = common.getValueByPath(fromObject, [\n 'urlContextMetadata',\n ]);\n if (fromUrlContextMetadata != null) {\n common.setValueByPath(\n toObject,\n ['urlContextMetadata'],\n fromUrlContextMetadata,\n );\n }\n\n return toObject;\n}\n\nexport function citationMetadataFromMldev(\n fromObject: types.CitationMetadata,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromCitations = common.getValueByPath(fromObject, ['citationSources']);\n if (fromCitations != null) {\n let transformedList = fromCitations;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['citations'], transformedList);\n }\n\n return toObject;\n}\n\nexport function contentToMldev(\n fromObject: types.Content,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromParts = common.getValueByPath(fromObject, ['parts']);\n if (fromParts != null) {\n let transformedList = fromParts;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return partToMldev(item);\n });\n }\n common.setValueByPath(toObject, ['parts'], transformedList);\n }\n\n const fromRole = common.getValueByPath(fromObject, ['role']);\n if (fromRole != null) {\n common.setValueByPath(toObject, ['role'], fromRole);\n }\n\n return toObject;\n}\n\nexport function createBatchJobConfigToMldev(\n fromObject: types.CreateBatchJobConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromDisplayName = common.getValueByPath(fromObject, ['displayName']);\n if (parentObject !== undefined && fromDisplayName != null) {\n common.setValueByPath(\n parentObject,\n ['batch', 'displayName'],\n fromDisplayName,\n );\n }\n\n if (common.getValueByPath(fromObject, ['dest']) !== undefined) {\n throw new Error('dest parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function createBatchJobConfigToVertex(\n fromObject: types.CreateBatchJobConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromDisplayName = common.getValueByPath(fromObject, ['displayName']);\n if (parentObject !== undefined && fromDisplayName != null) {\n common.setValueByPath(parentObject, ['displayName'], fromDisplayName);\n }\n\n const fromDest = common.getValueByPath(fromObject, ['dest']);\n if (parentObject !== undefined && fromDest != null) {\n common.setValueByPath(\n parentObject,\n ['outputConfig'],\n batchJobDestinationToVertex(t.tBatchJobDestination(fromDest)),\n );\n }\n\n return toObject;\n}\n\nexport function createBatchJobParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.CreateBatchJobParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromSrc = common.getValueByPath(fromObject, ['src']);\n if (fromSrc != null) {\n common.setValueByPath(\n toObject,\n ['batch', 'inputConfig'],\n batchJobSourceToMldev(apiClient, t.tBatchJobSource(apiClient, fromSrc)),\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n createBatchJobConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function createBatchJobParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.CreateBatchJobParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(toObject, ['model'], t.tModel(apiClient, fromModel));\n }\n\n const fromSrc = common.getValueByPath(fromObject, ['src']);\n if (fromSrc != null) {\n common.setValueByPath(\n toObject,\n ['inputConfig'],\n batchJobSourceToVertex(t.tBatchJobSource(apiClient, fromSrc)),\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n createBatchJobConfigToVertex(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function createEmbeddingsBatchJobConfigToMldev(\n fromObject: types.CreateEmbeddingsBatchJobConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromDisplayName = common.getValueByPath(fromObject, ['displayName']);\n if (parentObject !== undefined && fromDisplayName != null) {\n common.setValueByPath(\n parentObject,\n ['batch', 'displayName'],\n fromDisplayName,\n );\n }\n\n return toObject;\n}\n\nexport function createEmbeddingsBatchJobParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.CreateEmbeddingsBatchJobParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromSrc = common.getValueByPath(fromObject, ['src']);\n if (fromSrc != null) {\n common.setValueByPath(\n toObject,\n ['batch', 'inputConfig'],\n embeddingsBatchJobSourceToMldev(apiClient, fromSrc),\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n createEmbeddingsBatchJobConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function deleteBatchJobParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.DeleteBatchJobParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tBatchJobName(apiClient, fromName),\n );\n }\n\n return toObject;\n}\n\nexport function deleteBatchJobParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.DeleteBatchJobParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tBatchJobName(apiClient, fromName),\n );\n }\n\n return toObject;\n}\n\nexport function deleteResourceJobFromMldev(\n fromObject: types.DeleteResourceJob,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromDone = common.getValueByPath(fromObject, ['done']);\n if (fromDone != null) {\n common.setValueByPath(toObject, ['done'], fromDone);\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n return toObject;\n}\n\nexport function deleteResourceJobFromVertex(\n fromObject: types.DeleteResourceJob,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromDone = common.getValueByPath(fromObject, ['done']);\n if (fromDone != null) {\n common.setValueByPath(toObject, ['done'], fromDone);\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n return toObject;\n}\n\nexport function embedContentBatchToMldev(\n apiClient: ApiClient,\n fromObject: types.EmbedContentBatch,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromContents = common.getValueByPath(fromObject, ['contents']);\n if (fromContents != null) {\n let transformedList = t.tContentsForEmbed(apiClient, fromContents);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(\n toObject,\n ['requests[]', 'request', 'content'],\n transformedList,\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n common.setValueByPath(\n toObject,\n ['_self'],\n embedContentConfigToMldev(fromConfig, toObject),\n );\n common.moveValueByPath(toObject, {'requests[].*': 'requests[].request.*'});\n }\n\n return toObject;\n}\n\nexport function embedContentConfigToMldev(\n fromObject: types.EmbedContentConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromTaskType = common.getValueByPath(fromObject, ['taskType']);\n if (parentObject !== undefined && fromTaskType != null) {\n common.setValueByPath(\n parentObject,\n ['requests[]', 'taskType'],\n fromTaskType,\n );\n }\n\n const fromTitle = common.getValueByPath(fromObject, ['title']);\n if (parentObject !== undefined && fromTitle != null) {\n common.setValueByPath(parentObject, ['requests[]', 'title'], fromTitle);\n }\n\n const fromOutputDimensionality = common.getValueByPath(fromObject, [\n 'outputDimensionality',\n ]);\n if (parentObject !== undefined && fromOutputDimensionality != null) {\n common.setValueByPath(\n parentObject,\n ['requests[]', 'outputDimensionality'],\n fromOutputDimensionality,\n );\n }\n\n if (common.getValueByPath(fromObject, ['mimeType']) !== undefined) {\n throw new Error('mimeType parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['autoTruncate']) !== undefined) {\n throw new Error('autoTruncate parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function embeddingsBatchJobSourceToMldev(\n apiClient: ApiClient,\n fromObject: types.EmbeddingsBatchJobSource,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromFileName = common.getValueByPath(fromObject, ['fileName']);\n if (fromFileName != null) {\n common.setValueByPath(toObject, ['file_name'], fromFileName);\n }\n\n const fromInlinedRequests = common.getValueByPath(fromObject, [\n 'inlinedRequests',\n ]);\n if (fromInlinedRequests != null) {\n common.setValueByPath(\n toObject,\n ['requests'],\n embedContentBatchToMldev(apiClient, fromInlinedRequests),\n );\n }\n\n return toObject;\n}\n\nexport function fileDataToMldev(\n fromObject: types.FileData,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['displayName']) !== undefined) {\n throw new Error('displayName parameter is not supported in Gemini API.');\n }\n\n const fromFileUri = common.getValueByPath(fromObject, ['fileUri']);\n if (fromFileUri != null) {\n common.setValueByPath(toObject, ['fileUri'], fromFileUri);\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function functionCallToMldev(\n fromObject: types.FunctionCall,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromId = common.getValueByPath(fromObject, ['id']);\n if (fromId != null) {\n common.setValueByPath(toObject, ['id'], fromId);\n }\n\n const fromArgs = common.getValueByPath(fromObject, ['args']);\n if (fromArgs != null) {\n common.setValueByPath(toObject, ['args'], fromArgs);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n if (common.getValueByPath(fromObject, ['partialArgs']) !== undefined) {\n throw new Error('partialArgs parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['willContinue']) !== undefined) {\n throw new Error('willContinue parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function functionCallingConfigToMldev(\n fromObject: types.FunctionCallingConfig,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromAllowedFunctionNames = common.getValueByPath(fromObject, [\n 'allowedFunctionNames',\n ]);\n if (fromAllowedFunctionNames != null) {\n common.setValueByPath(\n toObject,\n ['allowedFunctionNames'],\n fromAllowedFunctionNames,\n );\n }\n\n const fromMode = common.getValueByPath(fromObject, ['mode']);\n if (fromMode != null) {\n common.setValueByPath(toObject, ['mode'], fromMode);\n }\n\n if (\n common.getValueByPath(fromObject, ['streamFunctionCallArguments']) !==\n undefined\n ) {\n throw new Error(\n 'streamFunctionCallArguments parameter is not supported in Gemini API.',\n );\n }\n\n return toObject;\n}\n\nexport function generateContentConfigToMldev(\n apiClient: ApiClient,\n fromObject: types.GenerateContentConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSystemInstruction = common.getValueByPath(fromObject, [\n 'systemInstruction',\n ]);\n if (parentObject !== undefined && fromSystemInstruction != null) {\n common.setValueByPath(\n parentObject,\n ['systemInstruction'],\n contentToMldev(t.tContent(fromSystemInstruction)),\n );\n }\n\n const fromTemperature = common.getValueByPath(fromObject, ['temperature']);\n if (fromTemperature != null) {\n common.setValueByPath(toObject, ['temperature'], fromTemperature);\n }\n\n const fromTopP = common.getValueByPath(fromObject, ['topP']);\n if (fromTopP != null) {\n common.setValueByPath(toObject, ['topP'], fromTopP);\n }\n\n const fromTopK = common.getValueByPath(fromObject, ['topK']);\n if (fromTopK != null) {\n common.setValueByPath(toObject, ['topK'], fromTopK);\n }\n\n const fromCandidateCount = common.getValueByPath(fromObject, [\n 'candidateCount',\n ]);\n if (fromCandidateCount != null) {\n common.setValueByPath(toObject, ['candidateCount'], fromCandidateCount);\n }\n\n const fromMaxOutputTokens = common.getValueByPath(fromObject, [\n 'maxOutputTokens',\n ]);\n if (fromMaxOutputTokens != null) {\n common.setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens);\n }\n\n const fromStopSequences = common.getValueByPath(fromObject, [\n 'stopSequences',\n ]);\n if (fromStopSequences != null) {\n common.setValueByPath(toObject, ['stopSequences'], fromStopSequences);\n }\n\n const fromResponseLogprobs = common.getValueByPath(fromObject, [\n 'responseLogprobs',\n ]);\n if (fromResponseLogprobs != null) {\n common.setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs);\n }\n\n const fromLogprobs = common.getValueByPath(fromObject, ['logprobs']);\n if (fromLogprobs != null) {\n common.setValueByPath(toObject, ['logprobs'], fromLogprobs);\n }\n\n const fromPresencePenalty = common.getValueByPath(fromObject, [\n 'presencePenalty',\n ]);\n if (fromPresencePenalty != null) {\n common.setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty);\n }\n\n const fromFrequencyPenalty = common.getValueByPath(fromObject, [\n 'frequencyPenalty',\n ]);\n if (fromFrequencyPenalty != null) {\n common.setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty);\n }\n\n const fromSeed = common.getValueByPath(fromObject, ['seed']);\n if (fromSeed != null) {\n common.setValueByPath(toObject, ['seed'], fromSeed);\n }\n\n const fromResponseMimeType = common.getValueByPath(fromObject, [\n 'responseMimeType',\n ]);\n if (fromResponseMimeType != null) {\n common.setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType);\n }\n\n const fromResponseSchema = common.getValueByPath(fromObject, [\n 'responseSchema',\n ]);\n if (fromResponseSchema != null) {\n common.setValueByPath(\n toObject,\n ['responseSchema'],\n t.tSchema(fromResponseSchema),\n );\n }\n\n const fromResponseJsonSchema = common.getValueByPath(fromObject, [\n 'responseJsonSchema',\n ]);\n if (fromResponseJsonSchema != null) {\n common.setValueByPath(\n toObject,\n ['responseJsonSchema'],\n fromResponseJsonSchema,\n );\n }\n\n if (common.getValueByPath(fromObject, ['routingConfig']) !== undefined) {\n throw new Error('routingConfig parameter is not supported in Gemini API.');\n }\n\n if (\n common.getValueByPath(fromObject, ['modelSelectionConfig']) !== undefined\n ) {\n throw new Error(\n 'modelSelectionConfig parameter is not supported in Gemini API.',\n );\n }\n\n const fromSafetySettings = common.getValueByPath(fromObject, [\n 'safetySettings',\n ]);\n if (parentObject !== undefined && fromSafetySettings != null) {\n let transformedList = fromSafetySettings;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return safetySettingToMldev(item);\n });\n }\n common.setValueByPath(parentObject, ['safetySettings'], transformedList);\n }\n\n const fromTools = common.getValueByPath(fromObject, ['tools']);\n if (parentObject !== undefined && fromTools != null) {\n let transformedList = t.tTools(fromTools);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return toolToMldev(t.tTool(item));\n });\n }\n common.setValueByPath(parentObject, ['tools'], transformedList);\n }\n\n const fromToolConfig = common.getValueByPath(fromObject, ['toolConfig']);\n if (parentObject !== undefined && fromToolConfig != null) {\n common.setValueByPath(\n parentObject,\n ['toolConfig'],\n toolConfigToMldev(fromToolConfig),\n );\n }\n\n if (common.getValueByPath(fromObject, ['labels']) !== undefined) {\n throw new Error('labels parameter is not supported in Gemini API.');\n }\n\n const fromCachedContent = common.getValueByPath(fromObject, [\n 'cachedContent',\n ]);\n if (parentObject !== undefined && fromCachedContent != null) {\n common.setValueByPath(\n parentObject,\n ['cachedContent'],\n t.tCachedContentName(apiClient, fromCachedContent),\n );\n }\n\n const fromResponseModalities = common.getValueByPath(fromObject, [\n 'responseModalities',\n ]);\n if (fromResponseModalities != null) {\n common.setValueByPath(\n toObject,\n ['responseModalities'],\n fromResponseModalities,\n );\n }\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (fromMediaResolution != null) {\n common.setValueByPath(toObject, ['mediaResolution'], fromMediaResolution);\n }\n\n const fromSpeechConfig = common.getValueByPath(fromObject, ['speechConfig']);\n if (fromSpeechConfig != null) {\n common.setValueByPath(\n toObject,\n ['speechConfig'],\n t.tSpeechConfig(fromSpeechConfig),\n );\n }\n\n if (common.getValueByPath(fromObject, ['audioTimestamp']) !== undefined) {\n throw new Error('audioTimestamp parameter is not supported in Gemini API.');\n }\n\n const fromThinkingConfig = common.getValueByPath(fromObject, [\n 'thinkingConfig',\n ]);\n if (fromThinkingConfig != null) {\n common.setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig);\n }\n\n const fromImageConfig = common.getValueByPath(fromObject, ['imageConfig']);\n if (fromImageConfig != null) {\n common.setValueByPath(\n toObject,\n ['imageConfig'],\n imageConfigToMldev(fromImageConfig),\n );\n }\n\n const fromEnableEnhancedCivicAnswers = common.getValueByPath(fromObject, [\n 'enableEnhancedCivicAnswers',\n ]);\n if (fromEnableEnhancedCivicAnswers != null) {\n common.setValueByPath(\n toObject,\n ['enableEnhancedCivicAnswers'],\n fromEnableEnhancedCivicAnswers,\n );\n }\n\n if (common.getValueByPath(fromObject, ['modelArmorConfig']) !== undefined) {\n throw new Error(\n 'modelArmorConfig parameter is not supported in Gemini API.',\n );\n }\n\n return toObject;\n}\n\nexport function generateContentResponseFromMldev(\n fromObject: types.GenerateContentResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromCandidates = common.getValueByPath(fromObject, ['candidates']);\n if (fromCandidates != null) {\n let transformedList = fromCandidates;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return candidateFromMldev(item);\n });\n }\n common.setValueByPath(toObject, ['candidates'], transformedList);\n }\n\n const fromModelVersion = common.getValueByPath(fromObject, ['modelVersion']);\n if (fromModelVersion != null) {\n common.setValueByPath(toObject, ['modelVersion'], fromModelVersion);\n }\n\n const fromPromptFeedback = common.getValueByPath(fromObject, [\n 'promptFeedback',\n ]);\n if (fromPromptFeedback != null) {\n common.setValueByPath(toObject, ['promptFeedback'], fromPromptFeedback);\n }\n\n const fromResponseId = common.getValueByPath(fromObject, ['responseId']);\n if (fromResponseId != null) {\n common.setValueByPath(toObject, ['responseId'], fromResponseId);\n }\n\n const fromUsageMetadata = common.getValueByPath(fromObject, [\n 'usageMetadata',\n ]);\n if (fromUsageMetadata != null) {\n common.setValueByPath(toObject, ['usageMetadata'], fromUsageMetadata);\n }\n\n return toObject;\n}\n\nexport function getBatchJobParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.GetBatchJobParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tBatchJobName(apiClient, fromName),\n );\n }\n\n return toObject;\n}\n\nexport function getBatchJobParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.GetBatchJobParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tBatchJobName(apiClient, fromName),\n );\n }\n\n return toObject;\n}\n\nexport function googleMapsToMldev(\n fromObject: types.GoogleMaps,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['authConfig']) !== undefined) {\n throw new Error('authConfig parameter is not supported in Gemini API.');\n }\n\n const fromEnableWidget = common.getValueByPath(fromObject, ['enableWidget']);\n if (fromEnableWidget != null) {\n common.setValueByPath(toObject, ['enableWidget'], fromEnableWidget);\n }\n\n return toObject;\n}\n\nexport function googleSearchToMldev(\n fromObject: types.GoogleSearch,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['excludeDomains']) !== undefined) {\n throw new Error('excludeDomains parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['blockingConfidence']) !== undefined) {\n throw new Error(\n 'blockingConfidence parameter is not supported in Gemini API.',\n );\n }\n\n const fromTimeRangeFilter = common.getValueByPath(fromObject, [\n 'timeRangeFilter',\n ]);\n if (fromTimeRangeFilter != null) {\n common.setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter);\n }\n\n return toObject;\n}\n\nexport function imageConfigToMldev(\n fromObject: types.ImageConfig,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromAspectRatio = common.getValueByPath(fromObject, ['aspectRatio']);\n if (fromAspectRatio != null) {\n common.setValueByPath(toObject, ['aspectRatio'], fromAspectRatio);\n }\n\n const fromImageSize = common.getValueByPath(fromObject, ['imageSize']);\n if (fromImageSize != null) {\n common.setValueByPath(toObject, ['imageSize'], fromImageSize);\n }\n\n if (common.getValueByPath(fromObject, ['personGeneration']) !== undefined) {\n throw new Error(\n 'personGeneration parameter is not supported in Gemini API.',\n );\n }\n\n if (common.getValueByPath(fromObject, ['outputMimeType']) !== undefined) {\n throw new Error('outputMimeType parameter is not supported in Gemini API.');\n }\n\n if (\n common.getValueByPath(fromObject, ['outputCompressionQuality']) !==\n undefined\n ) {\n throw new Error(\n 'outputCompressionQuality parameter is not supported in Gemini API.',\n );\n }\n\n return toObject;\n}\n\nexport function inlinedRequestToMldev(\n apiClient: ApiClient,\n fromObject: types.InlinedRequest,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['request', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromContents = common.getValueByPath(fromObject, ['contents']);\n if (fromContents != null) {\n let transformedList = t.tContents(fromContents);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return contentToMldev(item);\n });\n }\n common.setValueByPath(toObject, ['request', 'contents'], transformedList);\n }\n\n const fromMetadata = common.getValueByPath(fromObject, ['metadata']);\n if (fromMetadata != null) {\n common.setValueByPath(toObject, ['metadata'], fromMetadata);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n common.setValueByPath(\n toObject,\n ['request', 'generationConfig'],\n generateContentConfigToMldev(\n apiClient,\n fromConfig,\n common.getValueByPath(toObject, ['request'], {}) as Record<\n string,\n unknown\n >,\n ),\n );\n }\n\n return toObject;\n}\n\nexport function inlinedResponseFromMldev(\n fromObject: types.InlinedResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromResponse = common.getValueByPath(fromObject, ['response']);\n if (fromResponse != null) {\n common.setValueByPath(\n toObject,\n ['response'],\n generateContentResponseFromMldev(\n fromResponse as types.GenerateContentResponse,\n ),\n );\n }\n\n const fromMetadata = common.getValueByPath(fromObject, ['metadata']);\n if (fromMetadata != null) {\n common.setValueByPath(toObject, ['metadata'], fromMetadata);\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n return toObject;\n}\n\nexport function listBatchJobsConfigToMldev(\n fromObject: types.ListBatchJobsConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPageSize = common.getValueByPath(fromObject, ['pageSize']);\n if (parentObject !== undefined && fromPageSize != null) {\n common.setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize);\n }\n\n const fromPageToken = common.getValueByPath(fromObject, ['pageToken']);\n if (parentObject !== undefined && fromPageToken != null) {\n common.setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken);\n }\n\n if (common.getValueByPath(fromObject, ['filter']) !== undefined) {\n throw new Error('filter parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function listBatchJobsConfigToVertex(\n fromObject: types.ListBatchJobsConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPageSize = common.getValueByPath(fromObject, ['pageSize']);\n if (parentObject !== undefined && fromPageSize != null) {\n common.setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize);\n }\n\n const fromPageToken = common.getValueByPath(fromObject, ['pageToken']);\n if (parentObject !== undefined && fromPageToken != null) {\n common.setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken);\n }\n\n const fromFilter = common.getValueByPath(fromObject, ['filter']);\n if (parentObject !== undefined && fromFilter != null) {\n common.setValueByPath(parentObject, ['_query', 'filter'], fromFilter);\n }\n\n return toObject;\n}\n\nexport function listBatchJobsParametersToMldev(\n fromObject: types.ListBatchJobsParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n listBatchJobsConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function listBatchJobsParametersToVertex(\n fromObject: types.ListBatchJobsParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n listBatchJobsConfigToVertex(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function listBatchJobsResponseFromMldev(\n fromObject: types.ListBatchJobsResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromNextPageToken = common.getValueByPath(fromObject, [\n 'nextPageToken',\n ]);\n if (fromNextPageToken != null) {\n common.setValueByPath(toObject, ['nextPageToken'], fromNextPageToken);\n }\n\n const fromBatchJobs = common.getValueByPath(fromObject, ['operations']);\n if (fromBatchJobs != null) {\n let transformedList = fromBatchJobs;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return batchJobFromMldev(item);\n });\n }\n common.setValueByPath(toObject, ['batchJobs'], transformedList);\n }\n\n return toObject;\n}\n\nexport function listBatchJobsResponseFromVertex(\n fromObject: types.ListBatchJobsResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromNextPageToken = common.getValueByPath(fromObject, [\n 'nextPageToken',\n ]);\n if (fromNextPageToken != null) {\n common.setValueByPath(toObject, ['nextPageToken'], fromNextPageToken);\n }\n\n const fromBatchJobs = common.getValueByPath(fromObject, [\n 'batchPredictionJobs',\n ]);\n if (fromBatchJobs != null) {\n let transformedList = fromBatchJobs;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return batchJobFromVertex(item);\n });\n }\n common.setValueByPath(toObject, ['batchJobs'], transformedList);\n }\n\n return toObject;\n}\n\nexport function partToMldev(fromObject: types.Part): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (fromMediaResolution != null) {\n common.setValueByPath(toObject, ['mediaResolution'], fromMediaResolution);\n }\n\n const fromCodeExecutionResult = common.getValueByPath(fromObject, [\n 'codeExecutionResult',\n ]);\n if (fromCodeExecutionResult != null) {\n common.setValueByPath(\n toObject,\n ['codeExecutionResult'],\n fromCodeExecutionResult,\n );\n }\n\n const fromExecutableCode = common.getValueByPath(fromObject, [\n 'executableCode',\n ]);\n if (fromExecutableCode != null) {\n common.setValueByPath(toObject, ['executableCode'], fromExecutableCode);\n }\n\n const fromFileData = common.getValueByPath(fromObject, ['fileData']);\n if (fromFileData != null) {\n common.setValueByPath(\n toObject,\n ['fileData'],\n fileDataToMldev(fromFileData),\n );\n }\n\n const fromFunctionCall = common.getValueByPath(fromObject, ['functionCall']);\n if (fromFunctionCall != null) {\n common.setValueByPath(\n toObject,\n ['functionCall'],\n functionCallToMldev(fromFunctionCall),\n );\n }\n\n const fromFunctionResponse = common.getValueByPath(fromObject, [\n 'functionResponse',\n ]);\n if (fromFunctionResponse != null) {\n common.setValueByPath(toObject, ['functionResponse'], fromFunctionResponse);\n }\n\n const fromInlineData = common.getValueByPath(fromObject, ['inlineData']);\n if (fromInlineData != null) {\n common.setValueByPath(\n toObject,\n ['inlineData'],\n blobToMldev(fromInlineData),\n );\n }\n\n const fromText = common.getValueByPath(fromObject, ['text']);\n if (fromText != null) {\n common.setValueByPath(toObject, ['text'], fromText);\n }\n\n const fromThought = common.getValueByPath(fromObject, ['thought']);\n if (fromThought != null) {\n common.setValueByPath(toObject, ['thought'], fromThought);\n }\n\n const fromThoughtSignature = common.getValueByPath(fromObject, [\n 'thoughtSignature',\n ]);\n if (fromThoughtSignature != null) {\n common.setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature);\n }\n\n const fromVideoMetadata = common.getValueByPath(fromObject, [\n 'videoMetadata',\n ]);\n if (fromVideoMetadata != null) {\n common.setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata);\n }\n\n return toObject;\n}\n\nexport function safetySettingToMldev(\n fromObject: types.SafetySetting,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromCategory = common.getValueByPath(fromObject, ['category']);\n if (fromCategory != null) {\n common.setValueByPath(toObject, ['category'], fromCategory);\n }\n\n if (common.getValueByPath(fromObject, ['method']) !== undefined) {\n throw new Error('method parameter is not supported in Gemini API.');\n }\n\n const fromThreshold = common.getValueByPath(fromObject, ['threshold']);\n if (fromThreshold != null) {\n common.setValueByPath(toObject, ['threshold'], fromThreshold);\n }\n\n return toObject;\n}\n\nexport function toolConfigToMldev(\n fromObject: types.ToolConfig,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromRetrievalConfig = common.getValueByPath(fromObject, [\n 'retrievalConfig',\n ]);\n if (fromRetrievalConfig != null) {\n common.setValueByPath(toObject, ['retrievalConfig'], fromRetrievalConfig);\n }\n\n const fromFunctionCallingConfig = common.getValueByPath(fromObject, [\n 'functionCallingConfig',\n ]);\n if (fromFunctionCallingConfig != null) {\n common.setValueByPath(\n toObject,\n ['functionCallingConfig'],\n functionCallingConfigToMldev(fromFunctionCallingConfig),\n );\n }\n\n return toObject;\n}\n\nexport function toolToMldev(fromObject: types.Tool): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['retrieval']) !== undefined) {\n throw new Error('retrieval parameter is not supported in Gemini API.');\n }\n\n const fromComputerUse = common.getValueByPath(fromObject, ['computerUse']);\n if (fromComputerUse != null) {\n common.setValueByPath(toObject, ['computerUse'], fromComputerUse);\n }\n\n const fromFileSearch = common.getValueByPath(fromObject, ['fileSearch']);\n if (fromFileSearch != null) {\n common.setValueByPath(toObject, ['fileSearch'], fromFileSearch);\n }\n\n const fromCodeExecution = common.getValueByPath(fromObject, [\n 'codeExecution',\n ]);\n if (fromCodeExecution != null) {\n common.setValueByPath(toObject, ['codeExecution'], fromCodeExecution);\n }\n\n if (\n common.getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined\n ) {\n throw new Error(\n 'enterpriseWebSearch parameter is not supported in Gemini API.',\n );\n }\n\n const fromFunctionDeclarations = common.getValueByPath(fromObject, [\n 'functionDeclarations',\n ]);\n if (fromFunctionDeclarations != null) {\n let transformedList = fromFunctionDeclarations;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['functionDeclarations'], transformedList);\n }\n\n const fromGoogleMaps = common.getValueByPath(fromObject, ['googleMaps']);\n if (fromGoogleMaps != null) {\n common.setValueByPath(\n toObject,\n ['googleMaps'],\n googleMapsToMldev(fromGoogleMaps),\n );\n }\n\n const fromGoogleSearch = common.getValueByPath(fromObject, ['googleSearch']);\n if (fromGoogleSearch != null) {\n common.setValueByPath(\n toObject,\n ['googleSearch'],\n googleSearchToMldev(fromGoogleSearch),\n );\n }\n\n const fromGoogleSearchRetrieval = common.getValueByPath(fromObject, [\n 'googleSearchRetrieval',\n ]);\n if (fromGoogleSearchRetrieval != null) {\n common.setValueByPath(\n toObject,\n ['googleSearchRetrieval'],\n fromGoogleSearchRetrieval,\n );\n }\n\n const fromUrlContext = common.getValueByPath(fromObject, ['urlContext']);\n if (fromUrlContext != null) {\n common.setValueByPath(toObject, ['urlContext'], fromUrlContext);\n }\n\n return toObject;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Pagers for the GenAI List APIs.\n */\n\nimport * as types from '../src/types';\n\nexport enum PagedItem {\n PAGED_ITEM_BATCH_JOBS = 'batchJobs',\n PAGED_ITEM_MODELS = 'models',\n PAGED_ITEM_TUNING_JOBS = 'tuningJobs',\n PAGED_ITEM_FILES = 'files',\n PAGED_ITEM_CACHED_CONTENTS = 'cachedContents',\n PAGED_ITEM_FILE_SEARCH_STORES = 'fileSearchStores',\n PAGED_ITEM_DOCUMENTS = 'documents',\n}\n\nexport interface PagedItemConfig {\n parent?: string;\n config?: {\n pageToken?: string;\n pageSize?: number;\n };\n}\n\ninterface PagedItemResponse<T> {\n nextPageToken?: string;\n sdkHttpResponse?: types.HttpResponse;\n batchJobs?: T[];\n models?: T[];\n tuningJobs?: T[];\n files?: T[];\n cachedContents?: T[];\n fileSearchStores?: T[];\n documents?: T[];\n}\n\n/**\n * Pager class for iterating through paginated results.\n */\nexport class Pager<T> implements AsyncIterable<T> {\n private nameInternal!: PagedItem;\n private pageInternal: T[] = [];\n private paramsInternal: PagedItemConfig = {};\n private pageInternalSize!: number;\n private sdkHttpResponseInternal?: types.HttpResponse;\n protected requestInternal!: (\n params: PagedItemConfig,\n ) => Promise<PagedItemResponse<T>>;\n protected idxInternal!: number;\n\n constructor(\n name: PagedItem,\n request: (params: PagedItemConfig) => Promise<PagedItemResponse<T>>,\n response: PagedItemResponse<T>,\n params: PagedItemConfig,\n ) {\n this.requestInternal = request;\n this.init(name, response, params);\n }\n\n private init(\n name: PagedItem,\n response: PagedItemResponse<T>,\n params: PagedItemConfig,\n ) {\n this.nameInternal = name;\n this.pageInternal = response[this.nameInternal] || [];\n\n this.sdkHttpResponseInternal = response?.sdkHttpResponse;\n this.idxInternal = 0;\n let requestParams: PagedItemConfig = {config: {}};\n if (!params || Object.keys(params).length === 0) {\n requestParams = {config: {}};\n } else if (typeof params === 'object') {\n requestParams = {...params};\n } else {\n requestParams = params;\n }\n if (requestParams['config']) {\n requestParams['config']['pageToken'] = response['nextPageToken'];\n }\n this.paramsInternal = requestParams;\n this.pageInternalSize =\n requestParams['config']?.['pageSize'] ?? this.pageInternal.length;\n }\n\n private initNextPage(response: PagedItemResponse<T>): void {\n this.init(this.nameInternal, response, this.paramsInternal);\n }\n\n /**\n * Returns the current page, which is a list of items.\n *\n * @remarks\n * The first page is retrieved when the pager is created. The returned list of\n * items could be a subset of the entire list.\n */\n get page(): T[] {\n return this.pageInternal;\n }\n\n /**\n * Returns the type of paged item (for example, ``batch_jobs``).\n */\n get name(): PagedItem {\n return this.nameInternal;\n }\n\n /**\n * Returns the length of the page fetched each time by this pager.\n *\n * @remarks\n * The number of items in the page is less than or equal to the page length.\n */\n get pageSize(): number {\n return this.pageInternalSize;\n }\n\n /**\n * Returns the headers of the API response.\n */\n get sdkHttpResponse(): types.HttpResponse | undefined {\n return this.sdkHttpResponseInternal;\n }\n\n /**\n * Returns the parameters when making the API request for the next page.\n *\n * @remarks\n * Parameters contain a set of optional configs that can be\n * used to customize the API request. For example, the `pageToken` parameter\n * contains the token to request the next page.\n */\n get params(): PagedItemConfig {\n return this.paramsInternal;\n }\n\n /**\n * Returns the total number of items in the current page.\n */\n get pageLength(): number {\n return this.pageInternal.length;\n }\n\n /**\n * Returns the item at the given index.\n */\n getItem(index: number): T {\n return this.pageInternal[index];\n }\n\n /**\n * Returns an async iterator that support iterating through all items\n * retrieved from the API.\n *\n * @remarks\n * The iterator will automatically fetch the next page if there are more items\n * to fetch from the API.\n *\n * @example\n *\n * ```ts\n * const pager = await ai.files.list({config: {pageSize: 10}});\n * for await (const file of pager) {\n * console.log(file.name);\n * }\n * ```\n */\n [Symbol.asyncIterator](): AsyncIterator<T> {\n return {\n next: async () => {\n if (this.idxInternal >= this.pageLength) {\n if (this.hasNextPage()) {\n await this.nextPage();\n } else {\n return {value: undefined, done: true};\n }\n }\n const item = this.getItem(this.idxInternal);\n this.idxInternal += 1;\n return {value: item, done: false};\n },\n return: async () => {\n return {value: undefined, done: true};\n },\n };\n }\n\n /**\n * Fetches the next page of items. This makes a new API request.\n *\n * @throws {Error} If there are no more pages to fetch.\n *\n * @example\n *\n * ```ts\n * const pager = await ai.files.list({config: {pageSize: 10}});\n * let page = pager.page;\n * while (true) {\n * for (const file of page) {\n * console.log(file.name);\n * }\n * if (!pager.hasNextPage()) {\n * break;\n * }\n * page = await pager.nextPage();\n * }\n * ```\n */\n async nextPage(): Promise<T[]> {\n if (!this.hasNextPage()) {\n throw new Error('No more pages to fetch.');\n }\n const response = await this.requestInternal(this.params);\n this.initNextPage(response);\n return this.page;\n }\n\n /**\n * Returns true if there are more pages to fetch from the API.\n */\n hasNextPage(): boolean {\n if (this.params['config']?.['pageToken'] !== undefined) {\n return true;\n }\n return false;\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport {ApiClient} from './_api_client.js';\nimport * as common from './_common.js';\nimport {BaseModule} from './_common.js';\nimport * as converters from './converters/_batches_converters.js';\nimport {PagedItem, Pager} from './pagers.js';\nimport * as types from './types.js';\n\nexport class Batches extends BaseModule {\n constructor(private readonly apiClient: ApiClient) {\n super();\n }\n\n /**\n * Lists batch jobs.\n *\n * @param params - The parameters for the list request.\n * @return - A pager of batch jobs.\n *\n * @example\n * ```ts\n * const batchJobs = await ai.batches.list({config: {'pageSize': 2}});\n * for await (const batchJob of batchJobs) {\n * console.log(batchJob);\n * }\n * ```\n */\n list = async (\n params: types.ListBatchJobsParameters = {},\n ): Promise<Pager<types.BatchJob>> => {\n return new Pager<types.BatchJob>(\n PagedItem.PAGED_ITEM_BATCH_JOBS,\n (x: types.ListBatchJobsParameters) => this.listInternal(x),\n await this.listInternal(params),\n params,\n );\n };\n\n /**\n * Create batch job.\n *\n * @param params - The parameters for create batch job request.\n * @return The created batch job.\n *\n * @example\n * ```ts\n * const response = await ai.batches.create({\n * model: 'gemini-2.0-flash',\n * src: {gcsUri: 'gs://bucket/path/to/file.jsonl', format: 'jsonl'},\n * config: {\n * dest: {gcsUri: 'gs://bucket/path/output/directory', format: 'jsonl'},\n * }\n * });\n * console.log(response);\n * ```\n */\n create = async (\n params: types.CreateBatchJobParameters,\n ): Promise<types.BatchJob> => {\n if (this.apiClient.isVertexAI()) {\n // Format destination if not provided\n // Cast params.src as Vertex AI path does not handle InlinedRequest[]\n params.config = this.formatDestination(\n params.src as string | types.BatchJobSource,\n params.config,\n );\n }\n return this.createInternal(params);\n };\n\n /**\n * **Experimental** Creates an embedding batch job.\n *\n * @param params - The parameters for create embedding batch job request.\n * @return The created batch job.\n *\n * @example\n * ```ts\n * const response = await ai.batches.createEmbeddings({\n * model: 'text-embedding-004',\n * src: {fileName: 'files/my_embedding_input'},\n * });\n * console.log(response);\n * ```\n */\n createEmbeddings = async (\n params: types.CreateEmbeddingsBatchJobParameters,\n ): Promise<types.BatchJob> => {\n console.warn(\n 'batches.createEmbeddings() is experimental and may change without notice.',\n );\n\n if (this.apiClient.isVertexAI()) {\n throw new Error('Vertex AI does not support batches.createEmbeddings.');\n }\n\n return this.createEmbeddingsInternal(params);\n };\n\n // Helper function to handle inlined generate content requests\n private createInlinedGenerateContentRequest(\n params: types.CreateBatchJobParameters,\n ): {path: string; body: Record<string, unknown>} {\n const body = converters.createBatchJobParametersToMldev(\n this.apiClient, // Use instance apiClient\n params,\n );\n\n const urlParams = body['_url'] as Record<string, unknown>;\n const path = common.formatMap('{model}:batchGenerateContent', urlParams);\n\n const batch = body['batch'] as {[key: string]: unknown};\n const inputConfig = batch['inputConfig'] as {[key: string]: unknown};\n const requestsWrapper = inputConfig['requests'] as {\n [key: string]: unknown;\n };\n const requests = requestsWrapper['requests'] as Array<{\n [key: string]: unknown;\n }>;\n const newRequests = [];\n\n for (const request of requests) {\n const requestDict = {...request}; // Clone\n if (requestDict['systemInstruction']) {\n const systemInstructionValue = requestDict['systemInstruction'];\n delete requestDict['systemInstruction'];\n const requestContent = requestDict['request'] as {\n [key: string]: unknown;\n };\n requestContent['systemInstruction'] = systemInstructionValue;\n requestDict['request'] = requestContent;\n }\n newRequests.push(requestDict);\n }\n requestsWrapper['requests'] = newRequests;\n\n delete body['config'];\n delete body['_url'];\n delete body['_query'];\n\n return {path, body};\n }\n\n // Helper function to get the first GCS URI\n private getGcsUri(src: string | types.BatchJobSource): string | undefined {\n if (typeof src === 'string') {\n return src.startsWith('gs://') ? src : undefined;\n }\n if (!Array.isArray(src) && src.gcsUri && src.gcsUri.length > 0) {\n return src.gcsUri[0];\n }\n return undefined;\n }\n\n // Helper function to get the BigQuery URI\n private getBigqueryUri(\n src: string | types.BatchJobSource,\n ): string | undefined {\n if (typeof src === 'string') {\n return src.startsWith('bq://') ? src : undefined;\n }\n if (!Array.isArray(src)) {\n return src.bigqueryUri;\n }\n return undefined;\n }\n\n // Function to format the destination configuration for Vertex AI\n private formatDestination(\n src: string | types.BatchJobSource,\n config?: types.CreateBatchJobConfig,\n ): types.CreateBatchJobConfig {\n const newConfig = config ? {...config} : {};\n\n const timestampStr = Date.now().toString();\n\n if (!newConfig.displayName) {\n newConfig.displayName = `genaiBatchJob_${timestampStr}`;\n }\n\n if (newConfig.dest === undefined) {\n const gcsUri = this.getGcsUri(src);\n const bigqueryUri = this.getBigqueryUri(src);\n\n if (gcsUri) {\n if (gcsUri.endsWith('.jsonl')) {\n // For .jsonl files, remove suffix and add /dest\n newConfig.dest = `${gcsUri.slice(0, -6)}/dest`;\n } else {\n // Fallback for other GCS URIs\n newConfig.dest = `${gcsUri}_dest_${timestampStr}`;\n }\n } else if (bigqueryUri) {\n newConfig.dest = `${bigqueryUri}_dest_${timestampStr}`;\n } else {\n throw new Error(\n 'Unsupported source for Vertex AI: No GCS or BigQuery URI found.',\n );\n }\n }\n return newConfig;\n }\n\n /**\n * Internal method to create batch job.\n *\n * @param params - The parameters for create batch job request.\n * @return The created batch job.\n *\n */\n private async createInternal(\n params: types.CreateBatchJobParameters,\n ): Promise<types.BatchJob> {\n let response: Promise<types.BatchJob>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.createBatchJobParametersToVertex(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n 'batchPredictionJobs',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.BatchJob>;\n\n return response.then((apiResponse) => {\n const resp = converters.batchJobFromVertex(apiResponse);\n\n return resp as types.BatchJob;\n });\n } else {\n const body = converters.createBatchJobParametersToMldev(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n '{model}:batchGenerateContent',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.BatchJob>;\n\n return response.then((apiResponse) => {\n const resp = converters.batchJobFromMldev(apiResponse);\n\n return resp as types.BatchJob;\n });\n }\n }\n\n /**\n * Internal method to create batch job.\n *\n * @param params - The parameters for create batch job request.\n * @return The created batch job.\n *\n */\n private async createEmbeddingsInternal(\n params: types.CreateEmbeddingsBatchJobParameters,\n ): Promise<types.BatchJob> {\n let response: Promise<types.BatchJob>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.createEmbeddingsBatchJobParametersToMldev(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n '{model}:asyncBatchEmbedContent',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.BatchJob>;\n\n return response.then((apiResponse) => {\n const resp = converters.batchJobFromMldev(apiResponse);\n\n return resp as types.BatchJob;\n });\n }\n }\n\n /**\n * Gets batch job configurations.\n *\n * @param params - The parameters for the get request.\n * @return The batch job.\n *\n * @example\n * ```ts\n * await ai.batches.get({name: '...'}); // The server-generated resource name.\n * ```\n */\n async get(params: types.GetBatchJobParameters): Promise<types.BatchJob> {\n let response: Promise<types.BatchJob>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.getBatchJobParametersToVertex(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n 'batchPredictionJobs/{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.BatchJob>;\n\n return response.then((apiResponse) => {\n const resp = converters.batchJobFromVertex(apiResponse);\n\n return resp as types.BatchJob;\n });\n } else {\n const body = converters.getBatchJobParametersToMldev(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n 'batches/{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.BatchJob>;\n\n return response.then((apiResponse) => {\n const resp = converters.batchJobFromMldev(apiResponse);\n\n return resp as types.BatchJob;\n });\n }\n }\n\n /**\n * Cancels a batch job.\n *\n * @param params - The parameters for the cancel request.\n * @return The empty response returned by the API.\n *\n * @example\n * ```ts\n * await ai.batches.cancel({name: '...'}); // The server-generated resource name.\n * ```\n */\n async cancel(params: types.CancelBatchJobParameters): Promise<void> {\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.cancelBatchJobParametersToVertex(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n 'batchPredictionJobs/{name}:cancel',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n await this.apiClient.request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n });\n } else {\n const body = converters.cancelBatchJobParametersToMldev(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n 'batches/{name}:cancel',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n await this.apiClient.request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n });\n }\n }\n\n private async listInternal(\n params: types.ListBatchJobsParameters,\n ): Promise<types.ListBatchJobsResponse> {\n let response: Promise<types.ListBatchJobsResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.listBatchJobsParametersToVertex(params);\n path = common.formatMap(\n 'batchPredictionJobs',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.ListBatchJobsResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.ListBatchJobsResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.listBatchJobsResponseFromVertex(apiResponse);\n const typedResp = new types.ListBatchJobsResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n const body = converters.listBatchJobsParametersToMldev(params);\n path = common.formatMap(\n 'batches',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.ListBatchJobsResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.ListBatchJobsResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.listBatchJobsResponseFromMldev(apiResponse);\n const typedResp = new types.ListBatchJobsResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n /**\n * Deletes a batch job.\n *\n * @param params - The parameters for the delete request.\n * @return The empty response returned by the API.\n *\n * @example\n * ```ts\n * await ai.batches.delete({name: '...'}); // The server-generated resource name.\n * ```\n */\n async delete(\n params: types.DeleteBatchJobParameters,\n ): Promise<types.DeleteResourceJob> {\n let response: Promise<types.DeleteResourceJob>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.deleteBatchJobParametersToVertex(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n 'batchPredictionJobs/{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'DELETE',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.DeleteResourceJob;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.DeleteResourceJob>;\n\n return response.then((apiResponse) => {\n const resp = converters.deleteResourceJobFromVertex(apiResponse);\n\n return resp as types.DeleteResourceJob;\n });\n } else {\n const body = converters.deleteBatchJobParametersToMldev(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n 'batches/{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'DELETE',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.DeleteResourceJob;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.DeleteResourceJob>;\n\n return response.then((apiResponse) => {\n const resp = converters.deleteResourceJobFromMldev(apiResponse);\n\n return resp as types.DeleteResourceJob;\n });\n }\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport {ApiClient} from '../_api_client.js';\nimport * as common from '../_common.js';\nimport * as t from '../_transformers.js';\nimport type * as types from '../types.js';\n\nexport function blobToMldev(fromObject: types.Blob): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromData = common.getValueByPath(fromObject, ['data']);\n if (fromData != null) {\n common.setValueByPath(toObject, ['data'], fromData);\n }\n\n if (common.getValueByPath(fromObject, ['displayName']) !== undefined) {\n throw new Error('displayName parameter is not supported in Gemini API.');\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function contentToMldev(\n fromObject: types.Content,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromParts = common.getValueByPath(fromObject, ['parts']);\n if (fromParts != null) {\n let transformedList = fromParts;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return partToMldev(item);\n });\n }\n common.setValueByPath(toObject, ['parts'], transformedList);\n }\n\n const fromRole = common.getValueByPath(fromObject, ['role']);\n if (fromRole != null) {\n common.setValueByPath(toObject, ['role'], fromRole);\n }\n\n return toObject;\n}\n\nexport function createCachedContentConfigToMldev(\n fromObject: types.CreateCachedContentConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromTtl = common.getValueByPath(fromObject, ['ttl']);\n if (parentObject !== undefined && fromTtl != null) {\n common.setValueByPath(parentObject, ['ttl'], fromTtl);\n }\n\n const fromExpireTime = common.getValueByPath(fromObject, ['expireTime']);\n if (parentObject !== undefined && fromExpireTime != null) {\n common.setValueByPath(parentObject, ['expireTime'], fromExpireTime);\n }\n\n const fromDisplayName = common.getValueByPath(fromObject, ['displayName']);\n if (parentObject !== undefined && fromDisplayName != null) {\n common.setValueByPath(parentObject, ['displayName'], fromDisplayName);\n }\n\n const fromContents = common.getValueByPath(fromObject, ['contents']);\n if (parentObject !== undefined && fromContents != null) {\n let transformedList = t.tContents(fromContents);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return contentToMldev(item);\n });\n }\n common.setValueByPath(parentObject, ['contents'], transformedList);\n }\n\n const fromSystemInstruction = common.getValueByPath(fromObject, [\n 'systemInstruction',\n ]);\n if (parentObject !== undefined && fromSystemInstruction != null) {\n common.setValueByPath(\n parentObject,\n ['systemInstruction'],\n contentToMldev(t.tContent(fromSystemInstruction)),\n );\n }\n\n const fromTools = common.getValueByPath(fromObject, ['tools']);\n if (parentObject !== undefined && fromTools != null) {\n let transformedList = fromTools;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return toolToMldev(item);\n });\n }\n common.setValueByPath(parentObject, ['tools'], transformedList);\n }\n\n const fromToolConfig = common.getValueByPath(fromObject, ['toolConfig']);\n if (parentObject !== undefined && fromToolConfig != null) {\n common.setValueByPath(\n parentObject,\n ['toolConfig'],\n toolConfigToMldev(fromToolConfig),\n );\n }\n\n if (common.getValueByPath(fromObject, ['kmsKeyName']) !== undefined) {\n throw new Error('kmsKeyName parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function createCachedContentConfigToVertex(\n fromObject: types.CreateCachedContentConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromTtl = common.getValueByPath(fromObject, ['ttl']);\n if (parentObject !== undefined && fromTtl != null) {\n common.setValueByPath(parentObject, ['ttl'], fromTtl);\n }\n\n const fromExpireTime = common.getValueByPath(fromObject, ['expireTime']);\n if (parentObject !== undefined && fromExpireTime != null) {\n common.setValueByPath(parentObject, ['expireTime'], fromExpireTime);\n }\n\n const fromDisplayName = common.getValueByPath(fromObject, ['displayName']);\n if (parentObject !== undefined && fromDisplayName != null) {\n common.setValueByPath(parentObject, ['displayName'], fromDisplayName);\n }\n\n const fromContents = common.getValueByPath(fromObject, ['contents']);\n if (parentObject !== undefined && fromContents != null) {\n let transformedList = t.tContents(fromContents);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(parentObject, ['contents'], transformedList);\n }\n\n const fromSystemInstruction = common.getValueByPath(fromObject, [\n 'systemInstruction',\n ]);\n if (parentObject !== undefined && fromSystemInstruction != null) {\n common.setValueByPath(\n parentObject,\n ['systemInstruction'],\n t.tContent(fromSystemInstruction),\n );\n }\n\n const fromTools = common.getValueByPath(fromObject, ['tools']);\n if (parentObject !== undefined && fromTools != null) {\n let transformedList = fromTools;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return toolToVertex(item);\n });\n }\n common.setValueByPath(parentObject, ['tools'], transformedList);\n }\n\n const fromToolConfig = common.getValueByPath(fromObject, ['toolConfig']);\n if (parentObject !== undefined && fromToolConfig != null) {\n common.setValueByPath(parentObject, ['toolConfig'], fromToolConfig);\n }\n\n const fromKmsKeyName = common.getValueByPath(fromObject, ['kmsKeyName']);\n if (parentObject !== undefined && fromKmsKeyName != null) {\n common.setValueByPath(\n parentObject,\n ['encryption_spec', 'kmsKeyName'],\n fromKmsKeyName,\n );\n }\n\n return toObject;\n}\n\nexport function createCachedContentParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.CreateCachedContentParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['model'],\n t.tCachesModel(apiClient, fromModel),\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n createCachedContentConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function createCachedContentParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.CreateCachedContentParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['model'],\n t.tCachesModel(apiClient, fromModel),\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n createCachedContentConfigToVertex(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function deleteCachedContentParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.DeleteCachedContentParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tCachedContentName(apiClient, fromName),\n );\n }\n\n return toObject;\n}\n\nexport function deleteCachedContentParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.DeleteCachedContentParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tCachedContentName(apiClient, fromName),\n );\n }\n\n return toObject;\n}\n\nexport function deleteCachedContentResponseFromMldev(\n fromObject: types.DeleteCachedContentResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n return toObject;\n}\n\nexport function deleteCachedContentResponseFromVertex(\n fromObject: types.DeleteCachedContentResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n return toObject;\n}\n\nexport function fileDataToMldev(\n fromObject: types.FileData,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['displayName']) !== undefined) {\n throw new Error('displayName parameter is not supported in Gemini API.');\n }\n\n const fromFileUri = common.getValueByPath(fromObject, ['fileUri']);\n if (fromFileUri != null) {\n common.setValueByPath(toObject, ['fileUri'], fromFileUri);\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function functionCallToMldev(\n fromObject: types.FunctionCall,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromId = common.getValueByPath(fromObject, ['id']);\n if (fromId != null) {\n common.setValueByPath(toObject, ['id'], fromId);\n }\n\n const fromArgs = common.getValueByPath(fromObject, ['args']);\n if (fromArgs != null) {\n common.setValueByPath(toObject, ['args'], fromArgs);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n if (common.getValueByPath(fromObject, ['partialArgs']) !== undefined) {\n throw new Error('partialArgs parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['willContinue']) !== undefined) {\n throw new Error('willContinue parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function functionCallingConfigToMldev(\n fromObject: types.FunctionCallingConfig,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromAllowedFunctionNames = common.getValueByPath(fromObject, [\n 'allowedFunctionNames',\n ]);\n if (fromAllowedFunctionNames != null) {\n common.setValueByPath(\n toObject,\n ['allowedFunctionNames'],\n fromAllowedFunctionNames,\n );\n }\n\n const fromMode = common.getValueByPath(fromObject, ['mode']);\n if (fromMode != null) {\n common.setValueByPath(toObject, ['mode'], fromMode);\n }\n\n if (\n common.getValueByPath(fromObject, ['streamFunctionCallArguments']) !==\n undefined\n ) {\n throw new Error(\n 'streamFunctionCallArguments parameter is not supported in Gemini API.',\n );\n }\n\n return toObject;\n}\n\nexport function functionDeclarationToVertex(\n fromObject: types.FunctionDeclaration,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromDescription = common.getValueByPath(fromObject, ['description']);\n if (fromDescription != null) {\n common.setValueByPath(toObject, ['description'], fromDescription);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromParameters = common.getValueByPath(fromObject, ['parameters']);\n if (fromParameters != null) {\n common.setValueByPath(toObject, ['parameters'], fromParameters);\n }\n\n const fromParametersJsonSchema = common.getValueByPath(fromObject, [\n 'parametersJsonSchema',\n ]);\n if (fromParametersJsonSchema != null) {\n common.setValueByPath(\n toObject,\n ['parametersJsonSchema'],\n fromParametersJsonSchema,\n );\n }\n\n const fromResponse = common.getValueByPath(fromObject, ['response']);\n if (fromResponse != null) {\n common.setValueByPath(toObject, ['response'], fromResponse);\n }\n\n const fromResponseJsonSchema = common.getValueByPath(fromObject, [\n 'responseJsonSchema',\n ]);\n if (fromResponseJsonSchema != null) {\n common.setValueByPath(\n toObject,\n ['responseJsonSchema'],\n fromResponseJsonSchema,\n );\n }\n\n if (common.getValueByPath(fromObject, ['behavior']) !== undefined) {\n throw new Error('behavior parameter is not supported in Vertex AI.');\n }\n\n return toObject;\n}\n\nexport function getCachedContentParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.GetCachedContentParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tCachedContentName(apiClient, fromName),\n );\n }\n\n return toObject;\n}\n\nexport function getCachedContentParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.GetCachedContentParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tCachedContentName(apiClient, fromName),\n );\n }\n\n return toObject;\n}\n\nexport function googleMapsToMldev(\n fromObject: types.GoogleMaps,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['authConfig']) !== undefined) {\n throw new Error('authConfig parameter is not supported in Gemini API.');\n }\n\n const fromEnableWidget = common.getValueByPath(fromObject, ['enableWidget']);\n if (fromEnableWidget != null) {\n common.setValueByPath(toObject, ['enableWidget'], fromEnableWidget);\n }\n\n return toObject;\n}\n\nexport function googleSearchToMldev(\n fromObject: types.GoogleSearch,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['excludeDomains']) !== undefined) {\n throw new Error('excludeDomains parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['blockingConfidence']) !== undefined) {\n throw new Error(\n 'blockingConfidence parameter is not supported in Gemini API.',\n );\n }\n\n const fromTimeRangeFilter = common.getValueByPath(fromObject, [\n 'timeRangeFilter',\n ]);\n if (fromTimeRangeFilter != null) {\n common.setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter);\n }\n\n return toObject;\n}\n\nexport function listCachedContentsConfigToMldev(\n fromObject: types.ListCachedContentsConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPageSize = common.getValueByPath(fromObject, ['pageSize']);\n if (parentObject !== undefined && fromPageSize != null) {\n common.setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize);\n }\n\n const fromPageToken = common.getValueByPath(fromObject, ['pageToken']);\n if (parentObject !== undefined && fromPageToken != null) {\n common.setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken);\n }\n\n return toObject;\n}\n\nexport function listCachedContentsConfigToVertex(\n fromObject: types.ListCachedContentsConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPageSize = common.getValueByPath(fromObject, ['pageSize']);\n if (parentObject !== undefined && fromPageSize != null) {\n common.setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize);\n }\n\n const fromPageToken = common.getValueByPath(fromObject, ['pageToken']);\n if (parentObject !== undefined && fromPageToken != null) {\n common.setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken);\n }\n\n return toObject;\n}\n\nexport function listCachedContentsParametersToMldev(\n fromObject: types.ListCachedContentsParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n listCachedContentsConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function listCachedContentsParametersToVertex(\n fromObject: types.ListCachedContentsParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n listCachedContentsConfigToVertex(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function listCachedContentsResponseFromMldev(\n fromObject: types.ListCachedContentsResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromNextPageToken = common.getValueByPath(fromObject, [\n 'nextPageToken',\n ]);\n if (fromNextPageToken != null) {\n common.setValueByPath(toObject, ['nextPageToken'], fromNextPageToken);\n }\n\n const fromCachedContents = common.getValueByPath(fromObject, [\n 'cachedContents',\n ]);\n if (fromCachedContents != null) {\n let transformedList = fromCachedContents;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['cachedContents'], transformedList);\n }\n\n return toObject;\n}\n\nexport function listCachedContentsResponseFromVertex(\n fromObject: types.ListCachedContentsResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromNextPageToken = common.getValueByPath(fromObject, [\n 'nextPageToken',\n ]);\n if (fromNextPageToken != null) {\n common.setValueByPath(toObject, ['nextPageToken'], fromNextPageToken);\n }\n\n const fromCachedContents = common.getValueByPath(fromObject, [\n 'cachedContents',\n ]);\n if (fromCachedContents != null) {\n let transformedList = fromCachedContents;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['cachedContents'], transformedList);\n }\n\n return toObject;\n}\n\nexport function partToMldev(fromObject: types.Part): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (fromMediaResolution != null) {\n common.setValueByPath(toObject, ['mediaResolution'], fromMediaResolution);\n }\n\n const fromCodeExecutionResult = common.getValueByPath(fromObject, [\n 'codeExecutionResult',\n ]);\n if (fromCodeExecutionResult != null) {\n common.setValueByPath(\n toObject,\n ['codeExecutionResult'],\n fromCodeExecutionResult,\n );\n }\n\n const fromExecutableCode = common.getValueByPath(fromObject, [\n 'executableCode',\n ]);\n if (fromExecutableCode != null) {\n common.setValueByPath(toObject, ['executableCode'], fromExecutableCode);\n }\n\n const fromFileData = common.getValueByPath(fromObject, ['fileData']);\n if (fromFileData != null) {\n common.setValueByPath(\n toObject,\n ['fileData'],\n fileDataToMldev(fromFileData),\n );\n }\n\n const fromFunctionCall = common.getValueByPath(fromObject, ['functionCall']);\n if (fromFunctionCall != null) {\n common.setValueByPath(\n toObject,\n ['functionCall'],\n functionCallToMldev(fromFunctionCall),\n );\n }\n\n const fromFunctionResponse = common.getValueByPath(fromObject, [\n 'functionResponse',\n ]);\n if (fromFunctionResponse != null) {\n common.setValueByPath(toObject, ['functionResponse'], fromFunctionResponse);\n }\n\n const fromInlineData = common.getValueByPath(fromObject, ['inlineData']);\n if (fromInlineData != null) {\n common.setValueByPath(\n toObject,\n ['inlineData'],\n blobToMldev(fromInlineData),\n );\n }\n\n const fromText = common.getValueByPath(fromObject, ['text']);\n if (fromText != null) {\n common.setValueByPath(toObject, ['text'], fromText);\n }\n\n const fromThought = common.getValueByPath(fromObject, ['thought']);\n if (fromThought != null) {\n common.setValueByPath(toObject, ['thought'], fromThought);\n }\n\n const fromThoughtSignature = common.getValueByPath(fromObject, [\n 'thoughtSignature',\n ]);\n if (fromThoughtSignature != null) {\n common.setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature);\n }\n\n const fromVideoMetadata = common.getValueByPath(fromObject, [\n 'videoMetadata',\n ]);\n if (fromVideoMetadata != null) {\n common.setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata);\n }\n\n return toObject;\n}\n\nexport function toolConfigToMldev(\n fromObject: types.ToolConfig,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromRetrievalConfig = common.getValueByPath(fromObject, [\n 'retrievalConfig',\n ]);\n if (fromRetrievalConfig != null) {\n common.setValueByPath(toObject, ['retrievalConfig'], fromRetrievalConfig);\n }\n\n const fromFunctionCallingConfig = common.getValueByPath(fromObject, [\n 'functionCallingConfig',\n ]);\n if (fromFunctionCallingConfig != null) {\n common.setValueByPath(\n toObject,\n ['functionCallingConfig'],\n functionCallingConfigToMldev(fromFunctionCallingConfig),\n );\n }\n\n return toObject;\n}\n\nexport function toolToMldev(fromObject: types.Tool): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['retrieval']) !== undefined) {\n throw new Error('retrieval parameter is not supported in Gemini API.');\n }\n\n const fromComputerUse = common.getValueByPath(fromObject, ['computerUse']);\n if (fromComputerUse != null) {\n common.setValueByPath(toObject, ['computerUse'], fromComputerUse);\n }\n\n const fromFileSearch = common.getValueByPath(fromObject, ['fileSearch']);\n if (fromFileSearch != null) {\n common.setValueByPath(toObject, ['fileSearch'], fromFileSearch);\n }\n\n const fromCodeExecution = common.getValueByPath(fromObject, [\n 'codeExecution',\n ]);\n if (fromCodeExecution != null) {\n common.setValueByPath(toObject, ['codeExecution'], fromCodeExecution);\n }\n\n if (\n common.getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined\n ) {\n throw new Error(\n 'enterpriseWebSearch parameter is not supported in Gemini API.',\n );\n }\n\n const fromFunctionDeclarations = common.getValueByPath(fromObject, [\n 'functionDeclarations',\n ]);\n if (fromFunctionDeclarations != null) {\n let transformedList = fromFunctionDeclarations;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['functionDeclarations'], transformedList);\n }\n\n const fromGoogleMaps = common.getValueByPath(fromObject, ['googleMaps']);\n if (fromGoogleMaps != null) {\n common.setValueByPath(\n toObject,\n ['googleMaps'],\n googleMapsToMldev(fromGoogleMaps),\n );\n }\n\n const fromGoogleSearch = common.getValueByPath(fromObject, ['googleSearch']);\n if (fromGoogleSearch != null) {\n common.setValueByPath(\n toObject,\n ['googleSearch'],\n googleSearchToMldev(fromGoogleSearch),\n );\n }\n\n const fromGoogleSearchRetrieval = common.getValueByPath(fromObject, [\n 'googleSearchRetrieval',\n ]);\n if (fromGoogleSearchRetrieval != null) {\n common.setValueByPath(\n toObject,\n ['googleSearchRetrieval'],\n fromGoogleSearchRetrieval,\n );\n }\n\n const fromUrlContext = common.getValueByPath(fromObject, ['urlContext']);\n if (fromUrlContext != null) {\n common.setValueByPath(toObject, ['urlContext'], fromUrlContext);\n }\n\n return toObject;\n}\n\nexport function toolToVertex(fromObject: types.Tool): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromRetrieval = common.getValueByPath(fromObject, ['retrieval']);\n if (fromRetrieval != null) {\n common.setValueByPath(toObject, ['retrieval'], fromRetrieval);\n }\n\n const fromComputerUse = common.getValueByPath(fromObject, ['computerUse']);\n if (fromComputerUse != null) {\n common.setValueByPath(toObject, ['computerUse'], fromComputerUse);\n }\n\n if (common.getValueByPath(fromObject, ['fileSearch']) !== undefined) {\n throw new Error('fileSearch parameter is not supported in Vertex AI.');\n }\n\n const fromCodeExecution = common.getValueByPath(fromObject, [\n 'codeExecution',\n ]);\n if (fromCodeExecution != null) {\n common.setValueByPath(toObject, ['codeExecution'], fromCodeExecution);\n }\n\n const fromEnterpriseWebSearch = common.getValueByPath(fromObject, [\n 'enterpriseWebSearch',\n ]);\n if (fromEnterpriseWebSearch != null) {\n common.setValueByPath(\n toObject,\n ['enterpriseWebSearch'],\n fromEnterpriseWebSearch,\n );\n }\n\n const fromFunctionDeclarations = common.getValueByPath(fromObject, [\n 'functionDeclarations',\n ]);\n if (fromFunctionDeclarations != null) {\n let transformedList = fromFunctionDeclarations;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return functionDeclarationToVertex(item);\n });\n }\n common.setValueByPath(toObject, ['functionDeclarations'], transformedList);\n }\n\n const fromGoogleMaps = common.getValueByPath(fromObject, ['googleMaps']);\n if (fromGoogleMaps != null) {\n common.setValueByPath(toObject, ['googleMaps'], fromGoogleMaps);\n }\n\n const fromGoogleSearch = common.getValueByPath(fromObject, ['googleSearch']);\n if (fromGoogleSearch != null) {\n common.setValueByPath(toObject, ['googleSearch'], fromGoogleSearch);\n }\n\n const fromGoogleSearchRetrieval = common.getValueByPath(fromObject, [\n 'googleSearchRetrieval',\n ]);\n if (fromGoogleSearchRetrieval != null) {\n common.setValueByPath(\n toObject,\n ['googleSearchRetrieval'],\n fromGoogleSearchRetrieval,\n );\n }\n\n const fromUrlContext = common.getValueByPath(fromObject, ['urlContext']);\n if (fromUrlContext != null) {\n common.setValueByPath(toObject, ['urlContext'], fromUrlContext);\n }\n\n return toObject;\n}\n\nexport function updateCachedContentConfigToMldev(\n fromObject: types.UpdateCachedContentConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromTtl = common.getValueByPath(fromObject, ['ttl']);\n if (parentObject !== undefined && fromTtl != null) {\n common.setValueByPath(parentObject, ['ttl'], fromTtl);\n }\n\n const fromExpireTime = common.getValueByPath(fromObject, ['expireTime']);\n if (parentObject !== undefined && fromExpireTime != null) {\n common.setValueByPath(parentObject, ['expireTime'], fromExpireTime);\n }\n\n return toObject;\n}\n\nexport function updateCachedContentConfigToVertex(\n fromObject: types.UpdateCachedContentConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromTtl = common.getValueByPath(fromObject, ['ttl']);\n if (parentObject !== undefined && fromTtl != null) {\n common.setValueByPath(parentObject, ['ttl'], fromTtl);\n }\n\n const fromExpireTime = common.getValueByPath(fromObject, ['expireTime']);\n if (parentObject !== undefined && fromExpireTime != null) {\n common.setValueByPath(parentObject, ['expireTime'], fromExpireTime);\n }\n\n return toObject;\n}\n\nexport function updateCachedContentParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.UpdateCachedContentParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tCachedContentName(apiClient, fromName),\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n updateCachedContentConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function updateCachedContentParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.UpdateCachedContentParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tCachedContentName(apiClient, fromName),\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n updateCachedContentConfigToVertex(fromConfig, toObject);\n }\n\n return toObject;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport {ApiClient} from './_api_client.js';\nimport * as common from './_common.js';\nimport {BaseModule} from './_common.js';\nimport * as converters from './converters/_caches_converters.js';\nimport {PagedItem, Pager} from './pagers.js';\nimport * as types from './types.js';\n\nexport class Caches extends BaseModule {\n constructor(private readonly apiClient: ApiClient) {\n super();\n }\n\n /**\n * Lists cached contents.\n *\n * @param params - The parameters for the list request.\n * @return - A pager of cached contents.\n *\n * @example\n * ```ts\n * const cachedContents = await ai.caches.list({config: {'pageSize': 2}});\n * for await (const cachedContent of cachedContents) {\n * console.log(cachedContent);\n * }\n * ```\n */\n list = async (\n params: types.ListCachedContentsParameters = {},\n ): Promise<Pager<types.CachedContent>> => {\n return new Pager<types.CachedContent>(\n PagedItem.PAGED_ITEM_CACHED_CONTENTS,\n (x: types.ListCachedContentsParameters) => this.listInternal(x),\n await this.listInternal(params),\n params,\n );\n };\n\n /**\n * Creates a cached contents resource.\n *\n * @remarks\n * Context caching is only supported for specific models. See [Gemini\n * Developer API reference](https://ai.google.dev/gemini-api/docs/caching?lang=node/context-cac)\n * and [Vertex AI reference](https://cloud.google.com/vertex-ai/generative-ai/docs/context-cache/context-cache-overview#supported_models)\n * for more information.\n *\n * @param params - The parameters for the create request.\n * @return The created cached content.\n *\n * @example\n * ```ts\n * const contents = ...; // Initialize the content to cache.\n * const response = await ai.caches.create({\n * model: 'gemini-2.0-flash-001',\n * config: {\n * 'contents': contents,\n * 'displayName': 'test cache',\n * 'systemInstruction': 'What is the sum of the two pdfs?',\n * 'ttl': '86400s',\n * }\n * });\n * ```\n */\n async create(\n params: types.CreateCachedContentParameters,\n ): Promise<types.CachedContent> {\n let response: Promise<types.CachedContent>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.createCachedContentParametersToVertex(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n 'cachedContents',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.CachedContent>;\n\n return response.then((resp) => {\n return resp as types.CachedContent;\n });\n } else {\n const body = converters.createCachedContentParametersToMldev(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n 'cachedContents',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.CachedContent>;\n\n return response.then((resp) => {\n return resp as types.CachedContent;\n });\n }\n }\n\n /**\n * Gets cached content configurations.\n *\n * @param params - The parameters for the get request.\n * @return The cached content.\n *\n * @example\n * ```ts\n * await ai.caches.get({name: '...'}); // The server-generated resource name.\n * ```\n */\n async get(\n params: types.GetCachedContentParameters,\n ): Promise<types.CachedContent> {\n let response: Promise<types.CachedContent>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.getCachedContentParametersToVertex(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.CachedContent>;\n\n return response.then((resp) => {\n return resp as types.CachedContent;\n });\n } else {\n const body = converters.getCachedContentParametersToMldev(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.CachedContent>;\n\n return response.then((resp) => {\n return resp as types.CachedContent;\n });\n }\n }\n\n /**\n * Deletes cached content.\n *\n * @param params - The parameters for the delete request.\n * @return The empty response returned by the API.\n *\n * @example\n * ```ts\n * await ai.caches.delete({name: '...'}); // The server-generated resource name.\n * ```\n */\n async delete(\n params: types.DeleteCachedContentParameters,\n ): Promise<types.DeleteCachedContentResponse> {\n let response: Promise<types.DeleteCachedContentResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.deleteCachedContentParametersToVertex(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'DELETE',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.DeleteCachedContentResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.DeleteCachedContentResponse>;\n\n return response.then((apiResponse) => {\n const resp =\n converters.deleteCachedContentResponseFromVertex(apiResponse);\n const typedResp = new types.DeleteCachedContentResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n const body = converters.deleteCachedContentParametersToMldev(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'DELETE',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.DeleteCachedContentResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.DeleteCachedContentResponse>;\n\n return response.then((apiResponse) => {\n const resp =\n converters.deleteCachedContentResponseFromMldev(apiResponse);\n const typedResp = new types.DeleteCachedContentResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n /**\n * Updates cached content configurations.\n *\n * @param params - The parameters for the update request.\n * @return The updated cached content.\n *\n * @example\n * ```ts\n * const response = await ai.caches.update({\n * name: '...', // The server-generated resource name.\n * config: {'ttl': '7600s'}\n * });\n * ```\n */\n async update(\n params: types.UpdateCachedContentParameters,\n ): Promise<types.CachedContent> {\n let response: Promise<types.CachedContent>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.updateCachedContentParametersToVertex(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'PATCH',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.CachedContent>;\n\n return response.then((resp) => {\n return resp as types.CachedContent;\n });\n } else {\n const body = converters.updateCachedContentParametersToMldev(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'PATCH',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.CachedContent>;\n\n return response.then((resp) => {\n return resp as types.CachedContent;\n });\n }\n }\n\n private async listInternal(\n params: types.ListCachedContentsParameters,\n ): Promise<types.ListCachedContentsResponse> {\n let response: Promise<types.ListCachedContentsResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.listCachedContentsParametersToVertex(params);\n path = common.formatMap(\n 'cachedContents',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.ListCachedContentsResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.ListCachedContentsResponse>;\n\n return response.then((apiResponse) => {\n const resp =\n converters.listCachedContentsResponseFromVertex(apiResponse);\n const typedResp = new types.ListCachedContentsResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n const body = converters.listCachedContentsParametersToMldev(params);\n path = common.formatMap(\n 'cachedContents',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.ListCachedContentsResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.ListCachedContentsResponse>;\n\n return response.then((apiResponse) => {\n const resp =\n converters.listCachedContentsResponseFromMldev(apiResponse);\n const typedResp = new types.ListCachedContentsResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {ApiClient} from './_api_client.js';\nimport * as t from './_transformers.js';\nimport {Models} from './models.js';\nimport * as types from './types.js';\n\n/**\n * Returns true if the response is valid, false otherwise.\n */\nfunction isValidResponse(response: types.GenerateContentResponse): boolean {\n if (response.candidates == undefined || response.candidates.length === 0) {\n return false;\n }\n const content = response.candidates[0]?.content;\n if (content === undefined) {\n return false;\n }\n return isValidContent(content);\n}\n\nfunction isValidContent(content: types.Content): boolean {\n if (content.parts === undefined || content.parts.length === 0) {\n return false;\n }\n for (const part of content.parts) {\n if (part === undefined || Object.keys(part).length === 0) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * Validates the history contains the correct roles.\n *\n * @throws Error if the history does not start with a user turn.\n * @throws Error if the history contains an invalid role.\n */\nfunction validateHistory(history: types.Content[]) {\n // Empty history is valid.\n if (history.length === 0) {\n return;\n }\n for (const content of history) {\n if (content.role !== 'user' && content.role !== 'model') {\n throw new Error(`Role must be user or model, but got ${content.role}.`);\n }\n }\n}\n\n/**\n * Extracts the curated (valid) history from a comprehensive history.\n *\n * @remarks\n * The model may sometimes generate invalid or empty contents(e.g., due to safty\n * filters or recitation). Extracting valid turns from the history\n * ensures that subsequent requests could be accpeted by the model.\n */\nfunction extractCuratedHistory(\n comprehensiveHistory: types.Content[],\n): types.Content[] {\n if (comprehensiveHistory === undefined || comprehensiveHistory.length === 0) {\n return [];\n }\n const curatedHistory: types.Content[] = [];\n const length = comprehensiveHistory.length;\n let i = 0;\n while (i < length) {\n if (comprehensiveHistory[i].role === 'user') {\n curatedHistory.push(comprehensiveHistory[i]);\n i++;\n } else {\n const modelOutput: types.Content[] = [];\n let isValid = true;\n while (i < length && comprehensiveHistory[i].role === 'model') {\n modelOutput.push(comprehensiveHistory[i]);\n if (isValid && !isValidContent(comprehensiveHistory[i])) {\n isValid = false;\n }\n i++;\n }\n if (isValid) {\n curatedHistory.push(...modelOutput);\n } else {\n // Remove the last user input when model content is invalid.\n curatedHistory.pop();\n }\n }\n }\n return curatedHistory;\n}\n\n/**\n * A utility class to create a chat session.\n */\nexport class Chats {\n private readonly modelsModule: Models;\n private readonly apiClient: ApiClient;\n\n constructor(modelsModule: Models, apiClient: ApiClient) {\n this.modelsModule = modelsModule;\n this.apiClient = apiClient;\n }\n\n /**\n * Creates a new chat session.\n *\n * @remarks\n * The config in the params will be used for all requests within the chat\n * session unless overridden by a per-request `config` in\n * @see {@link types.SendMessageParameters#config}.\n *\n * @param params - Parameters for creating a chat session.\n * @returns A new chat session.\n *\n * @example\n * ```ts\n * const chat = ai.chats.create({\n * model: 'gemini-2.0-flash'\n * config: {\n * temperature: 0.5,\n * maxOutputTokens: 1024,\n * }\n * });\n * ```\n */\n create(params: types.CreateChatParameters) {\n return new Chat(\n this.apiClient,\n this.modelsModule,\n params.model,\n params.config,\n // Deep copy the history to avoid mutating the history outside of the\n // chat session.\n structuredClone(params.history),\n );\n }\n}\n\n/**\n * Chat session that enables sending messages to the model with previous\n * conversation context.\n *\n * @remarks\n * The session maintains all the turns between user and model.\n */\nexport class Chat {\n // A promise to represent the current state of the message being sent to the\n // model.\n private sendPromise: Promise<void> = Promise.resolve();\n\n constructor(\n private readonly apiClient: ApiClient,\n private readonly modelsModule: Models,\n private readonly model: string,\n private readonly config: types.GenerateContentConfig = {},\n private history: types.Content[] = [],\n ) {\n validateHistory(history);\n }\n\n /**\n * Sends a message to the model and returns the response.\n *\n * @remarks\n * This method will wait for the previous message to be processed before\n * sending the next message.\n *\n * @see {@link Chat#sendMessageStream} for streaming method.\n * @param params - parameters for sending messages within a chat session.\n * @returns The model's response.\n *\n * @example\n * ```ts\n * const chat = ai.chats.create({model: 'gemini-2.0-flash'});\n * const response = await chat.sendMessage({\n * message: 'Why is the sky blue?'\n * });\n * console.log(response.text);\n * ```\n */\n async sendMessage(\n params: types.SendMessageParameters,\n ): Promise<types.GenerateContentResponse> {\n await this.sendPromise;\n const inputContent = t.tContent(params.message);\n const responsePromise = this.modelsModule.generateContent({\n model: this.model,\n contents: this.getHistory(true).concat(inputContent),\n config: params.config ?? this.config,\n });\n this.sendPromise = (async () => {\n const response = await responsePromise;\n const outputContent = response.candidates?.[0]?.content;\n\n // Because the AFC input contains the entire curated chat history in\n // addition to the new user input, we need to truncate the AFC history\n // to deduplicate the existing chat history.\n const fullAutomaticFunctionCallingHistory =\n response.automaticFunctionCallingHistory;\n const index = this.getHistory(true).length;\n\n let automaticFunctionCallingHistory: types.Content[] = [];\n if (fullAutomaticFunctionCallingHistory != null) {\n automaticFunctionCallingHistory =\n fullAutomaticFunctionCallingHistory.slice(index) ?? [];\n }\n\n const modelOutput = outputContent ? [outputContent] : [];\n this.recordHistory(\n inputContent,\n modelOutput,\n automaticFunctionCallingHistory,\n );\n return;\n })();\n await this.sendPromise.catch(() => {\n // Resets sendPromise to avoid subsequent calls failing\n this.sendPromise = Promise.resolve();\n });\n return responsePromise;\n }\n\n /**\n * Sends a message to the model and returns the response in chunks.\n *\n * @remarks\n * This method will wait for the previous message to be processed before\n * sending the next message.\n *\n * @see {@link Chat#sendMessage} for non-streaming method.\n * @param params - parameters for sending the message.\n * @return The model's response.\n *\n * @example\n * ```ts\n * const chat = ai.chats.create({model: 'gemini-2.0-flash'});\n * const response = await chat.sendMessageStream({\n * message: 'Why is the sky blue?'\n * });\n * for await (const chunk of response) {\n * console.log(chunk.text);\n * }\n * ```\n */\n async sendMessageStream(\n params: types.SendMessageParameters,\n ): Promise<AsyncGenerator<types.GenerateContentResponse>> {\n await this.sendPromise;\n const inputContent = t.tContent(params.message);\n const streamResponse = this.modelsModule.generateContentStream({\n model: this.model,\n contents: this.getHistory(true).concat(inputContent),\n config: params.config ?? this.config,\n });\n // Resolve the internal tracking of send completion promise - `sendPromise`\n // for both success and failure response. The actual failure is still\n // propagated by the `await streamResponse`.\n this.sendPromise = streamResponse\n .then(() => undefined)\n .catch(() => undefined);\n const response = await streamResponse;\n const result = this.processStreamResponse(response, inputContent);\n return result;\n }\n\n /**\n * Returns the chat history.\n *\n * @remarks\n * The history is a list of contents alternating between user and model.\n *\n * There are two types of history:\n * - The `curated history` contains only the valid turns between user and\n * model, which will be included in the subsequent requests sent to the model.\n * - The `comprehensive history` contains all turns, including invalid or\n * empty model outputs, providing a complete record of the history.\n *\n * The history is updated after receiving the response from the model,\n * for streaming response, it means receiving the last chunk of the response.\n *\n * The `comprehensive history` is returned by default. To get the `curated\n * history`, set the `curated` parameter to `true`.\n *\n * @param curated - whether to return the curated history or the comprehensive\n * history.\n * @return History contents alternating between user and model for the entire\n * chat session.\n */\n getHistory(curated: boolean = false): types.Content[] {\n const history = curated\n ? extractCuratedHistory(this.history)\n : this.history;\n // Deep copy the history to avoid mutating the history outside of the\n // chat session.\n return structuredClone(history);\n }\n\n private async *processStreamResponse(\n streamResponse: AsyncGenerator<types.GenerateContentResponse>,\n inputContent: types.Content,\n ) {\n const outputContent: types.Content[] = [];\n for await (const chunk of streamResponse) {\n if (isValidResponse(chunk)) {\n const content = chunk.candidates?.[0]?.content;\n if (content !== undefined) {\n outputContent.push(content);\n }\n }\n yield chunk;\n }\n this.recordHistory(inputContent, outputContent);\n }\n\n private recordHistory(\n userInput: types.Content,\n modelOutput: types.Content[],\n automaticFunctionCallingHistory?: types.Content[],\n ) {\n let outputContents: types.Content[] = [];\n if (\n modelOutput.length > 0 &&\n modelOutput.every((content) => content.role !== undefined)\n ) {\n outputContents = modelOutput;\n } else {\n // Appends an empty content when model returns empty response, so that the\n // history is always alternating between user and model.\n outputContents.push({\n role: 'model',\n parts: [],\n } as types.Content);\n }\n if (\n automaticFunctionCallingHistory &&\n automaticFunctionCallingHistory.length > 0\n ) {\n this.history.push(\n ...extractCuratedHistory(automaticFunctionCallingHistory!),\n );\n } else {\n this.history.push(userInput);\n }\n this.history.push(...outputContents);\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport * as common from '../_common.js';\nimport type * as types from '../types.js';\n\nexport function createFileSearchStoreConfigToMldev(\n fromObject: types.CreateFileSearchStoreConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromDisplayName = common.getValueByPath(fromObject, ['displayName']);\n if (parentObject !== undefined && fromDisplayName != null) {\n common.setValueByPath(parentObject, ['displayName'], fromDisplayName);\n }\n\n return toObject;\n}\n\nexport function createFileSearchStoreParametersToMldev(\n fromObject: types.CreateFileSearchStoreParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n createFileSearchStoreConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function deleteFileSearchStoreConfigToMldev(\n fromObject: types.DeleteFileSearchStoreConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromForce = common.getValueByPath(fromObject, ['force']);\n if (parentObject !== undefined && fromForce != null) {\n common.setValueByPath(parentObject, ['_query', 'force'], fromForce);\n }\n\n return toObject;\n}\n\nexport function deleteFileSearchStoreParametersToMldev(\n fromObject: types.DeleteFileSearchStoreParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['_url', 'name'], fromName);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n deleteFileSearchStoreConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function getFileSearchStoreParametersToMldev(\n fromObject: types.GetFileSearchStoreParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['_url', 'name'], fromName);\n }\n\n return toObject;\n}\n\nexport function importFileConfigToMldev(\n fromObject: types.ImportFileConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromCustomMetadata = common.getValueByPath(fromObject, [\n 'customMetadata',\n ]);\n if (parentObject !== undefined && fromCustomMetadata != null) {\n let transformedList = fromCustomMetadata;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(parentObject, ['customMetadata'], transformedList);\n }\n\n const fromChunkingConfig = common.getValueByPath(fromObject, [\n 'chunkingConfig',\n ]);\n if (parentObject !== undefined && fromChunkingConfig != null) {\n common.setValueByPath(parentObject, ['chunkingConfig'], fromChunkingConfig);\n }\n\n return toObject;\n}\n\nexport function importFileOperationFromMldev(\n fromObject: types.ImportFileOperation,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromMetadata = common.getValueByPath(fromObject, ['metadata']);\n if (fromMetadata != null) {\n common.setValueByPath(toObject, ['metadata'], fromMetadata);\n }\n\n const fromDone = common.getValueByPath(fromObject, ['done']);\n if (fromDone != null) {\n common.setValueByPath(toObject, ['done'], fromDone);\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n const fromResponse = common.getValueByPath(fromObject, ['response']);\n if (fromResponse != null) {\n common.setValueByPath(\n toObject,\n ['response'],\n importFileResponseFromMldev(fromResponse),\n );\n }\n\n return toObject;\n}\n\nexport function importFileParametersToMldev(\n fromObject: types.ImportFileParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromFileSearchStoreName = common.getValueByPath(fromObject, [\n 'fileSearchStoreName',\n ]);\n if (fromFileSearchStoreName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'file_search_store_name'],\n fromFileSearchStoreName,\n );\n }\n\n const fromFileName = common.getValueByPath(fromObject, ['fileName']);\n if (fromFileName != null) {\n common.setValueByPath(toObject, ['fileName'], fromFileName);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n importFileConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function importFileResponseFromMldev(\n fromObject: types.ImportFileResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromParent = common.getValueByPath(fromObject, ['parent']);\n if (fromParent != null) {\n common.setValueByPath(toObject, ['parent'], fromParent);\n }\n\n const fromDocumentName = common.getValueByPath(fromObject, ['documentName']);\n if (fromDocumentName != null) {\n common.setValueByPath(toObject, ['documentName'], fromDocumentName);\n }\n\n return toObject;\n}\n\nexport function listFileSearchStoresConfigToMldev(\n fromObject: types.ListFileSearchStoresConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPageSize = common.getValueByPath(fromObject, ['pageSize']);\n if (parentObject !== undefined && fromPageSize != null) {\n common.setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize);\n }\n\n const fromPageToken = common.getValueByPath(fromObject, ['pageToken']);\n if (parentObject !== undefined && fromPageToken != null) {\n common.setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken);\n }\n\n return toObject;\n}\n\nexport function listFileSearchStoresParametersToMldev(\n fromObject: types.ListFileSearchStoresParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n listFileSearchStoresConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function listFileSearchStoresResponseFromMldev(\n fromObject: types.ListFileSearchStoresResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromNextPageToken = common.getValueByPath(fromObject, [\n 'nextPageToken',\n ]);\n if (fromNextPageToken != null) {\n common.setValueByPath(toObject, ['nextPageToken'], fromNextPageToken);\n }\n\n const fromFileSearchStores = common.getValueByPath(fromObject, [\n 'fileSearchStores',\n ]);\n if (fromFileSearchStores != null) {\n let transformedList = fromFileSearchStores;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['fileSearchStores'], transformedList);\n }\n\n return toObject;\n}\n\nexport function uploadToFileSearchStoreConfigToMldev(\n fromObject: types.UploadToFileSearchStoreConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (parentObject !== undefined && fromMimeType != null) {\n common.setValueByPath(parentObject, ['mimeType'], fromMimeType);\n }\n\n const fromDisplayName = common.getValueByPath(fromObject, ['displayName']);\n if (parentObject !== undefined && fromDisplayName != null) {\n common.setValueByPath(parentObject, ['displayName'], fromDisplayName);\n }\n\n const fromCustomMetadata = common.getValueByPath(fromObject, [\n 'customMetadata',\n ]);\n if (parentObject !== undefined && fromCustomMetadata != null) {\n let transformedList = fromCustomMetadata;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(parentObject, ['customMetadata'], transformedList);\n }\n\n const fromChunkingConfig = common.getValueByPath(fromObject, [\n 'chunkingConfig',\n ]);\n if (parentObject !== undefined && fromChunkingConfig != null) {\n common.setValueByPath(parentObject, ['chunkingConfig'], fromChunkingConfig);\n }\n\n return toObject;\n}\n\nexport function uploadToFileSearchStoreParametersToMldev(\n fromObject: types.UploadToFileSearchStoreParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromFileSearchStoreName = common.getValueByPath(fromObject, [\n 'fileSearchStoreName',\n ]);\n if (fromFileSearchStoreName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'file_search_store_name'],\n fromFileSearchStoreName,\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n uploadToFileSearchStoreConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function uploadToFileSearchStoreResumableResponseFromMldev(\n fromObject: types.UploadToFileSearchStoreResumableResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n return toObject;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Details for errors from calling the API.\n */\nexport interface ApiErrorInfo {\n /** The error message. */\n message: string;\n /** The HTTP status code. */\n status: number;\n}\n\n/**\n * API errors raised by the GenAI API.\n */\nexport class ApiError extends Error {\n /** HTTP status code */\n status: number;\n\n constructor(options: ApiErrorInfo) {\n super(options.message);\n this.name = 'ApiError';\n this.status = options.status;\n Object.setPrototypeOf(this, ApiError.prototype);\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport pRetry, {AbortError} from 'p-retry';\nimport {Auth} from './_auth.js';\nimport * as common from './_common.js';\nimport {Downloader} from './_downloader.js';\nimport {Uploader} from './_uploader.js';\nimport {uploadToFileSearchStoreConfigToMldev} from './converters/_filesearchstores_converters.js';\nimport {ApiError} from './errors.js';\nimport {GeminiNextGenAPIClientAdapter} from './interactions/client-adapter.js';\nimport * as types from './types.js';\n\nconst CONTENT_TYPE_HEADER = 'Content-Type';\nconst SERVER_TIMEOUT_HEADER = 'X-Server-Timeout';\nconst USER_AGENT_HEADER = 'User-Agent';\nexport const GOOGLE_API_CLIENT_HEADER = 'x-goog-api-client';\nexport const SDK_VERSION = '1.41.0'; // x-release-please-version\nconst LIBRARY_LABEL = `google-genai-sdk/${SDK_VERSION}`;\nconst VERTEX_AI_API_DEFAULT_VERSION = 'v1beta1';\nconst GOOGLE_AI_API_DEFAULT_VERSION = 'v1beta';\n\n// Default retry options.\n// The config is based on https://cloud.google.com/storage/docs/retry-strategy.\nconst DEFAULT_RETRY_ATTEMPTS = 5; // Including the initial call\n// LINT.IfChange\nconst DEFAULT_RETRY_HTTP_STATUS_CODES = [\n 408, // Request timeout\n 429, // Too many requests\n 500, // Internal server error\n 502, // Bad gateway\n 503, // Service unavailable\n 504, // Gateway timeout\n];\n// LINT.ThenChange(//depot/google3/third_party/py/google/genai/_api_client.py)\n\n/**\n * Options for initializing the ApiClient. The ApiClient uses the parameters\n * for authentication purposes as well as to infer if SDK should send the\n * request to Vertex AI or Gemini API.\n */\nexport interface ApiClientInitOptions {\n /**\n * The object used for adding authentication headers to API requests.\n */\n auth: Auth;\n /**\n * The uploader to use for uploading files. This field is required for\n * creating a client, will be set through the Node_client or Web_client.\n */\n uploader: Uploader;\n /**\n * Optional. The downloader to use for downloading files. This field is\n * required for creating a client, will be set through the Node_client or\n * Web_client.\n */\n downloader: Downloader;\n /**\n * Optional. The Google Cloud project ID for Vertex AI users.\n * It is not the numeric project name.\n * If not provided, SDK will try to resolve it from runtime environment.\n */\n project?: string;\n /**\n * Optional. The Google Cloud project location for Vertex AI users.\n * If not provided, SDK will try to resolve it from runtime environment.\n */\n location?: string;\n /**\n * The API Key. This is required for Gemini API users.\n */\n apiKey?: string;\n /**\n * Optional. Set to true if you intend to call Vertex AI endpoints.\n * If unset, default SDK behavior is to call Gemini API.\n */\n vertexai?: boolean;\n /**\n * Optional. The API version for the endpoint.\n * If unset, SDK will choose a default api version.\n */\n apiVersion?: string;\n /**\n * Optional. A set of customizable configuration for HTTP requests.\n */\n httpOptions?: types.HttpOptions;\n /**\n * Optional. An extra string to append at the end of the User-Agent header.\n *\n * This can be used to e.g specify the runtime and its version.\n */\n userAgentExtra?: string;\n}\n\n/**\n * Represents the necessary information to send a request to an API endpoint.\n * This interface defines the structure for constructing and executing HTTP\n * requests.\n */\nexport interface HttpRequest {\n /**\n * URL path from the modules, this path is appended to the base API URL to\n * form the complete request URL.\n *\n * If you wish to set full URL, use httpOptions.baseUrl instead. Example to\n * set full URL in the request:\n *\n * const request: HttpRequest = {\n * path: '',\n * httpOptions: {\n * baseUrl: 'https://<custom-full-url>',\n * apiVersion: '',\n * },\n * httpMethod: 'GET',\n * };\n *\n * The result URL will be: https://<custom-full-url>\n *\n */\n path: string;\n /**\n * Optional query parameters to be appended to the request URL.\n */\n queryParams?: Record<string, string>;\n /**\n * Optional request body in json string or Blob format, GET request doesn't\n * need a request body.\n */\n body?: string | Blob;\n /**\n * The HTTP method to be used for the request.\n */\n httpMethod: 'GET' | 'POST' | 'PATCH' | 'DELETE';\n /**\n * Optional set of customizable configuration for HTTP requests.\n */\n httpOptions?: types.HttpOptions;\n /**\n * Optional abort signal which can be used to cancel the request.\n */\n abortSignal?: AbortSignal;\n}\n\n/**\n * The ApiClient class is used to send requests to the Gemini API or Vertex AI\n * endpoints.\n */\nexport class ApiClient implements GeminiNextGenAPIClientAdapter {\n readonly clientOptions: ApiClientInitOptions;\n private readonly customBaseUrl?: string;\n constructor(opts: ApiClientInitOptions) {\n this.clientOptions = {\n ...opts,\n };\n\n this.customBaseUrl = opts.httpOptions?.baseUrl;\n\n if (this.clientOptions.vertexai) {\n if (this.clientOptions.project && this.clientOptions.location) {\n this.clientOptions.apiKey = undefined;\n } else if (this.clientOptions.apiKey) {\n this.clientOptions.project = undefined;\n this.clientOptions.location = undefined;\n }\n }\n\n const initHttpOptions: types.HttpOptions = {};\n\n if (this.clientOptions.vertexai) {\n if (\n !this.clientOptions.location &&\n !this.clientOptions.apiKey &&\n !this.customBaseUrl\n ) {\n this.clientOptions.location = 'global';\n }\n\n const hasSufficientAuth =\n (this.clientOptions.project && this.clientOptions.location) ||\n this.clientOptions.apiKey;\n\n if (!hasSufficientAuth && !this.customBaseUrl) {\n throw new Error(\n 'Authentication is not set up. Please provide either a project and location, or an API key, or a custom base URL.',\n );\n }\n\n const hasConstructorAuth =\n (opts.project && opts.location) || !!opts.apiKey;\n\n if (this.customBaseUrl && !hasConstructorAuth) {\n initHttpOptions.baseUrl = this.customBaseUrl;\n this.clientOptions.project = undefined;\n this.clientOptions.location = undefined;\n } else if (\n this.clientOptions.apiKey ||\n this.clientOptions.location === 'global'\n ) {\n // Vertex Express or global endpoint case.\n initHttpOptions.baseUrl = 'https://aiplatform.googleapis.com/';\n } else if (this.clientOptions.project && this.clientOptions.location) {\n initHttpOptions.baseUrl = `https://${this.clientOptions.location}-aiplatform.googleapis.com/`;\n }\n\n initHttpOptions.apiVersion =\n this.clientOptions.apiVersion ?? VERTEX_AI_API_DEFAULT_VERSION;\n } else {\n // Gemini API\n if (!this.clientOptions.apiKey) {\n throw new ApiError({\n message: 'API key must be set when using the Gemini API.',\n status: 403,\n });\n }\n initHttpOptions.apiVersion =\n this.clientOptions.apiVersion ?? GOOGLE_AI_API_DEFAULT_VERSION;\n initHttpOptions.baseUrl = `https://generativelanguage.googleapis.com/`;\n }\n\n initHttpOptions.headers = this.getDefaultHeaders();\n\n this.clientOptions.httpOptions = initHttpOptions;\n\n if (opts.httpOptions) {\n this.clientOptions.httpOptions = this.patchHttpOptions(\n initHttpOptions,\n opts.httpOptions,\n );\n }\n }\n\n isVertexAI(): boolean {\n return this.clientOptions.vertexai ?? false;\n }\n\n getProject() {\n return this.clientOptions.project;\n }\n\n getLocation() {\n return this.clientOptions.location;\n }\n\n getCustomBaseUrl(): string | undefined {\n return this.customBaseUrl;\n }\n\n async getAuthHeaders(): Promise<Headers> {\n const headers = new Headers();\n await this.clientOptions.auth.addAuthHeaders(headers);\n return headers;\n }\n\n getApiVersion() {\n if (\n this.clientOptions.httpOptions &&\n this.clientOptions.httpOptions.apiVersion !== undefined\n ) {\n return this.clientOptions.httpOptions.apiVersion;\n }\n throw new Error('API version is not set.');\n }\n\n getBaseUrl() {\n if (\n this.clientOptions.httpOptions &&\n this.clientOptions.httpOptions.baseUrl !== undefined\n ) {\n return this.clientOptions.httpOptions.baseUrl;\n }\n throw new Error('Base URL is not set.');\n }\n\n getRequestUrl() {\n return this.getRequestUrlInternal(this.clientOptions.httpOptions);\n }\n\n getHeaders() {\n if (\n this.clientOptions.httpOptions &&\n this.clientOptions.httpOptions.headers !== undefined\n ) {\n return this.clientOptions.httpOptions.headers;\n } else {\n throw new Error('Headers are not set.');\n }\n }\n\n private getRequestUrlInternal(httpOptions?: types.HttpOptions) {\n if (\n !httpOptions ||\n httpOptions.baseUrl === undefined ||\n httpOptions.apiVersion === undefined\n ) {\n throw new Error('HTTP options are not correctly set.');\n }\n const baseUrl = httpOptions.baseUrl.endsWith('/')\n ? httpOptions.baseUrl.slice(0, -1)\n : httpOptions.baseUrl;\n const urlElement: Array<string> = [baseUrl];\n if (httpOptions.apiVersion && httpOptions.apiVersion !== '') {\n urlElement.push(httpOptions.apiVersion);\n }\n return urlElement.join('/');\n }\n\n getBaseResourcePath() {\n return `projects/${this.clientOptions.project}/locations/${\n this.clientOptions.location\n }`;\n }\n\n getApiKey() {\n return this.clientOptions.apiKey;\n }\n\n getWebsocketBaseUrl() {\n const baseUrl = this.getBaseUrl();\n const urlParts = new URL(baseUrl);\n urlParts.protocol = urlParts.protocol == 'http:' ? 'ws' : 'wss';\n return urlParts.toString();\n }\n\n setBaseUrl(url: string) {\n if (this.clientOptions.httpOptions) {\n this.clientOptions.httpOptions.baseUrl = url;\n } else {\n throw new Error('HTTP options are not correctly set.');\n }\n }\n\n private constructUrl(\n path: string,\n httpOptions: types.HttpOptions,\n prependProjectLocation: boolean,\n ): URL {\n const urlElement: Array<string> = [this.getRequestUrlInternal(httpOptions)];\n if (prependProjectLocation) {\n urlElement.push(this.getBaseResourcePath());\n }\n if (path !== '') {\n urlElement.push(path);\n }\n const url = new URL(`${urlElement.join('/')}`);\n\n return url;\n }\n\n private shouldPrependVertexProjectPath(\n request: HttpRequest,\n httpOptions: types.HttpOptions,\n ): boolean {\n if (\n httpOptions.baseUrl &&\n httpOptions.baseUrlResourceScope === types.ResourceScope.COLLECTION\n ) {\n return false;\n }\n if (this.clientOptions.apiKey) {\n return false;\n }\n if (!this.clientOptions.vertexai) {\n return false;\n }\n if (request.path.startsWith('projects/')) {\n // Assume the path already starts with\n // `projects/<project>/location/<location>`.\n return false;\n }\n if (\n request.httpMethod === 'GET' &&\n request.path.startsWith('publishers/google/models')\n ) {\n // These paths are used by Vertex's models.get and models.list\n // calls. For base models Vertex does not accept a project/location\n // prefix (for tuned model the prefix is required).\n return false;\n }\n return true;\n }\n\n async request(request: HttpRequest): Promise<types.HttpResponse> {\n let patchedHttpOptions = this.clientOptions.httpOptions!;\n if (request.httpOptions) {\n patchedHttpOptions = this.patchHttpOptions(\n this.clientOptions.httpOptions!,\n request.httpOptions,\n );\n }\n\n const prependProjectLocation = this.shouldPrependVertexProjectPath(\n request,\n patchedHttpOptions,\n );\n const url = this.constructUrl(\n request.path,\n patchedHttpOptions,\n prependProjectLocation,\n );\n if (request.queryParams) {\n for (const [key, value] of Object.entries(request.queryParams)) {\n url.searchParams.append(key, String(value));\n }\n }\n let requestInit: RequestInit = {};\n if (request.httpMethod === 'GET') {\n if (request.body && request.body !== '{}') {\n throw new Error(\n 'Request body should be empty for GET request, but got non empty request body',\n );\n }\n } else {\n requestInit.body = request.body;\n }\n requestInit = await this.includeExtraHttpOptionsToRequestInit(\n requestInit,\n patchedHttpOptions,\n url.toString(),\n request.abortSignal,\n );\n return this.unaryApiCall(url, requestInit, request.httpMethod);\n }\n\n private patchHttpOptions(\n baseHttpOptions: types.HttpOptions,\n requestHttpOptions: types.HttpOptions,\n ): types.HttpOptions {\n const patchedHttpOptions = JSON.parse(\n JSON.stringify(baseHttpOptions),\n ) as types.HttpOptions;\n\n for (const [key, value] of Object.entries(requestHttpOptions)) {\n // Records compile to objects.\n if (typeof value === 'object') {\n // @ts-expect-error TS2345TS7053: Element implicitly has an 'any' type\n // because expression of type 'string' can't be used to index type\n // 'HttpOptions'.\n patchedHttpOptions[key] = {...patchedHttpOptions[key], ...value};\n } else if (value !== undefined) {\n // @ts-expect-error TS2345TS7053: Element implicitly has an 'any' type\n // because expression of type 'string' can't be used to index type\n // 'HttpOptions'.\n patchedHttpOptions[key] = value;\n }\n }\n return patchedHttpOptions;\n }\n\n async requestStream(\n request: HttpRequest,\n ): Promise<AsyncGenerator<types.HttpResponse>> {\n let patchedHttpOptions = this.clientOptions.httpOptions!;\n if (request.httpOptions) {\n patchedHttpOptions = this.patchHttpOptions(\n this.clientOptions.httpOptions!,\n request.httpOptions,\n );\n }\n\n const prependProjectLocation = this.shouldPrependVertexProjectPath(\n request,\n patchedHttpOptions,\n );\n const url = this.constructUrl(\n request.path,\n patchedHttpOptions,\n prependProjectLocation,\n );\n if (!url.searchParams.has('alt') || url.searchParams.get('alt') !== 'sse') {\n url.searchParams.set('alt', 'sse');\n }\n let requestInit: RequestInit = {};\n requestInit.body = request.body;\n requestInit = await this.includeExtraHttpOptionsToRequestInit(\n requestInit,\n patchedHttpOptions,\n url.toString(),\n request.abortSignal,\n );\n return this.streamApiCall(url, requestInit, request.httpMethod);\n }\n\n private async includeExtraHttpOptionsToRequestInit(\n requestInit: RequestInit,\n httpOptions: types.HttpOptions,\n url: string,\n abortSignal?: AbortSignal,\n ): Promise<RequestInit> {\n if ((httpOptions && httpOptions.timeout) || abortSignal) {\n const abortController = new AbortController();\n const signal = abortController.signal;\n if (httpOptions.timeout && httpOptions?.timeout > 0) {\n const timeoutHandle = setTimeout(\n () => abortController.abort(),\n httpOptions.timeout,\n );\n if (\n timeoutHandle &&\n typeof (timeoutHandle as unknown as NodeJS.Timeout).unref ===\n 'function'\n ) {\n // call unref to prevent nodejs process from hanging, see\n // https://nodejs.org/api/timers.html#timeoutunref\n timeoutHandle.unref();\n }\n }\n if (abortSignal) {\n abortSignal.addEventListener('abort', () => {\n abortController.abort();\n });\n }\n requestInit.signal = signal;\n }\n if (httpOptions && httpOptions.extraBody !== null) {\n includeExtraBodyToRequestInit(\n requestInit,\n httpOptions.extraBody as Record<string, unknown>,\n );\n }\n requestInit.headers = await this.getHeadersInternal(httpOptions, url);\n return requestInit;\n }\n\n private async unaryApiCall(\n url: URL,\n requestInit: RequestInit,\n httpMethod: 'GET' | 'POST' | 'PATCH' | 'DELETE',\n ): Promise<types.HttpResponse> {\n return this.apiCall(url.toString(), {\n ...requestInit,\n method: httpMethod,\n })\n .then(async (response) => {\n await throwErrorIfNotOK(response);\n return new types.HttpResponse(response);\n })\n .catch((e) => {\n if (e instanceof Error) {\n throw e;\n } else {\n throw new Error(JSON.stringify(e));\n }\n });\n }\n\n private async streamApiCall(\n url: URL,\n requestInit: RequestInit,\n httpMethod: 'GET' | 'POST' | 'PATCH' | 'DELETE',\n ): Promise<AsyncGenerator<types.HttpResponse>> {\n return this.apiCall(url.toString(), {\n ...requestInit,\n method: httpMethod,\n })\n .then(async (response) => {\n await throwErrorIfNotOK(response);\n return this.processStreamResponse(response);\n })\n .catch((e) => {\n if (e instanceof Error) {\n throw e;\n } else {\n throw new Error(JSON.stringify(e));\n }\n });\n }\n\n async *processStreamResponse(\n response: Response,\n ): AsyncGenerator<types.HttpResponse> {\n const reader = response?.body?.getReader();\n const decoder = new TextDecoder('utf-8');\n if (!reader) {\n throw new Error('Response body is empty');\n }\n\n try {\n let buffer = '';\n const dataPrefix = 'data:';\n const delimiters = ['\\n\\n', '\\r\\r', '\\r\\n\\r\\n'];\n\n while (true) {\n const {done, value} = await reader.read();\n if (done) {\n if (buffer.trim().length > 0) {\n throw new Error('Incomplete JSON segment at the end');\n }\n break;\n }\n const chunkString = decoder.decode(value, {stream: true});\n\n // Parse and throw an error if the chunk contains an error.\n try {\n const chunkJson = JSON.parse(chunkString) as Record<string, unknown>;\n if ('error' in chunkJson) {\n const errorJson = JSON.parse(\n JSON.stringify(chunkJson['error']),\n ) as Record<string, unknown>;\n const status = errorJson['status'] as string;\n const code = errorJson['code'] as number;\n const errorMessage = `got status: ${status}. ${JSON.stringify(\n chunkJson,\n )}`;\n if (code >= 400 && code < 600) {\n const apiError = new ApiError({\n message: errorMessage,\n status: code,\n });\n throw apiError;\n }\n }\n } catch (e: unknown) {\n const error = e as Error;\n if (error.name === 'ApiError') {\n throw e;\n }\n }\n buffer += chunkString;\n\n let delimiterIndex = -1;\n let delimiterLength = 0;\n\n while (true) {\n delimiterIndex = -1;\n delimiterLength = 0;\n\n for (const delimiter of delimiters) {\n const index = buffer.indexOf(delimiter);\n if (\n index !== -1 &&\n (delimiterIndex === -1 || index < delimiterIndex)\n ) {\n delimiterIndex = index;\n delimiterLength = delimiter.length;\n }\n }\n\n if (delimiterIndex === -1) {\n break; // No complete event in buffer\n }\n\n const eventString = buffer.substring(0, delimiterIndex);\n buffer = buffer.substring(delimiterIndex + delimiterLength);\n\n const trimmedEvent = eventString.trim();\n\n if (trimmedEvent.startsWith(dataPrefix)) {\n const processedChunkString = trimmedEvent\n .substring(dataPrefix.length)\n .trim();\n try {\n const partialResponse = new Response(processedChunkString, {\n headers: response?.headers,\n status: response?.status,\n statusText: response?.statusText,\n });\n yield new types.HttpResponse(partialResponse);\n } catch (e) {\n throw new Error(\n `exception parsing stream chunk ${processedChunkString}. ${e}`,\n );\n }\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n }\n private async apiCall(\n url: string,\n requestInit: RequestInit,\n ): Promise<Response> {\n if (\n !this.clientOptions.httpOptions ||\n !this.clientOptions.httpOptions.retryOptions\n ) {\n return fetch(url, requestInit);\n }\n\n const retryOptions = this.clientOptions.httpOptions.retryOptions;\n const runFetch = async () => {\n const response = await fetch(url, requestInit);\n\n if (response.ok) {\n return response;\n }\n\n if (DEFAULT_RETRY_HTTP_STATUS_CODES.includes(response.status)) {\n throw new Error(`Retryable HTTP Error: ${response.statusText}`);\n }\n\n throw new AbortError(\n `Non-retryable exception ${response.statusText} sending request`,\n );\n };\n\n return pRetry(runFetch, {\n // Retry attempts is one less than the number of total attempts.\n retries: (retryOptions.attempts ?? DEFAULT_RETRY_ATTEMPTS) - 1,\n });\n }\n\n getDefaultHeaders(): Record<string, string> {\n const headers: Record<string, string> = {};\n\n const versionHeaderValue =\n LIBRARY_LABEL + ' ' + this.clientOptions.userAgentExtra;\n\n headers[USER_AGENT_HEADER] = versionHeaderValue;\n headers[GOOGLE_API_CLIENT_HEADER] = versionHeaderValue;\n headers[CONTENT_TYPE_HEADER] = 'application/json';\n\n return headers;\n }\n\n private async getHeadersInternal(\n httpOptions: types.HttpOptions | undefined,\n url: string,\n ): Promise<Headers> {\n const headers = new Headers();\n if (httpOptions && httpOptions.headers) {\n for (const [key, value] of Object.entries(httpOptions.headers)) {\n headers.append(key, value);\n }\n // Append a timeout header if it is set, note that the timeout option is\n // in milliseconds but the header is in seconds.\n if (httpOptions.timeout && httpOptions.timeout > 0) {\n headers.append(\n SERVER_TIMEOUT_HEADER,\n String(Math.ceil(httpOptions.timeout / 1000)),\n );\n }\n }\n await this.clientOptions.auth.addAuthHeaders(headers, url);\n return headers;\n }\n\n private getFileName(file: string | Blob): string {\n let fileName: string = '';\n if (typeof file === 'string') {\n fileName = file.replace(/[/\\\\]+$/, '');\n fileName = fileName.split(/[/\\\\]/).pop() ?? '';\n }\n return fileName;\n }\n\n /**\n * Uploads a file asynchronously using Gemini API only, this is not supported\n * in Vertex AI.\n *\n * @param file The string path to the file to be uploaded or a Blob object.\n * @param config Optional parameters specified in the `UploadFileConfig`\n * interface. @see {@link types.UploadFileConfig}\n * @return A promise that resolves to a `File` object.\n * @throws An error if called on a Vertex AI client.\n * @throws An error if the `mimeType` is not provided and can not be inferred,\n */\n async uploadFile(\n file: string | Blob,\n config?: types.UploadFileConfig,\n ): Promise<types.File> {\n const fileToUpload: types.File = {};\n if (config != null) {\n fileToUpload.mimeType = config.mimeType;\n fileToUpload.name = config.name;\n fileToUpload.displayName = config.displayName;\n }\n\n if (fileToUpload.name && !fileToUpload.name.startsWith('files/')) {\n fileToUpload.name = `files/${fileToUpload.name}`;\n }\n\n const uploader = this.clientOptions.uploader;\n const fileStat = await uploader.stat(file);\n fileToUpload.sizeBytes = String(fileStat.size);\n const mimeType = config?.mimeType ?? fileStat.type;\n if (mimeType === undefined || mimeType === '') {\n throw new Error(\n 'Can not determine mimeType. Please provide mimeType in the config.',\n );\n }\n fileToUpload.mimeType = mimeType;\n const body: Record<string, unknown> = {\n file: fileToUpload,\n };\n const fileName = this.getFileName(file);\n const path = common.formatMap(\n 'upload/v1beta/files',\n body['_url'] as Record<string, unknown>,\n );\n const uploadUrl = await this.fetchUploadUrl(\n path,\n fileToUpload.sizeBytes,\n fileToUpload.mimeType,\n fileName,\n body,\n config?.httpOptions,\n );\n return uploader.upload(file, uploadUrl, this);\n }\n\n /**\n * Uploads a file to a given file search store asynchronously using Gemini API only, this is not supported\n * in Vertex AI.\n *\n * @param fileSearchStoreName The name of the file search store to upload the file to.\n * @param file The string path to the file to be uploaded or a Blob object.\n * @param config Optional parameters specified in the `UploadFileConfig`\n * interface. @see {@link UploadFileConfig}\n * @return A promise that resolves to a `File` object.\n * @throws An error if called on a Vertex AI client.\n * @throws An error if the `mimeType` is not provided and can not be inferred,\n */\n async uploadFileToFileSearchStore(\n fileSearchStoreName: string,\n file: string | Blob,\n config?: types.UploadToFileSearchStoreConfig,\n ): Promise<types.UploadToFileSearchStoreOperation> {\n const uploader = this.clientOptions.uploader;\n const fileStat = await uploader.stat(file);\n const sizeBytes = String(fileStat.size);\n const mimeType = config?.mimeType ?? fileStat.type;\n if (mimeType === undefined || mimeType === '') {\n throw new Error(\n 'Can not determine mimeType. Please provide mimeType in the config.',\n );\n }\n const path = `upload/v1beta/${fileSearchStoreName}:uploadToFileSearchStore`;\n const fileName = this.getFileName(file);\n const body: Record<string, unknown> = {};\n if (config != null) {\n uploadToFileSearchStoreConfigToMldev(config, body);\n }\n const uploadUrl = await this.fetchUploadUrl(\n path,\n sizeBytes,\n mimeType,\n fileName,\n body,\n config?.httpOptions,\n );\n return uploader.uploadToFileSearchStore(file, uploadUrl, this);\n }\n\n /**\n * Downloads a file asynchronously to the specified path.\n *\n * @params params - The parameters for the download request, see {@link\n * types.DownloadFileParameters}\n */\n async downloadFile(params: types.DownloadFileParameters): Promise<void> {\n const downloader = this.clientOptions.downloader;\n await downloader.download(params, this);\n }\n\n private async fetchUploadUrl(\n path: string,\n sizeBytes: string,\n mimeType: string,\n fileName: string,\n body: Record<string, unknown>,\n configHttpOptions?: types.HttpOptions,\n ): Promise<string> {\n let httpOptions: types.HttpOptions = {};\n if (configHttpOptions) {\n httpOptions = configHttpOptions;\n } else {\n httpOptions = {\n apiVersion: '', // api-version is set in the path.\n headers: {\n 'Content-Type': 'application/json',\n 'X-Goog-Upload-Protocol': 'resumable',\n 'X-Goog-Upload-Command': 'start',\n 'X-Goog-Upload-Header-Content-Length': `${sizeBytes}`,\n 'X-Goog-Upload-Header-Content-Type': `${mimeType}`,\n ...(fileName ? {'X-Goog-Upload-File-Name': fileName} : {}),\n },\n };\n }\n\n const httpResponse = await this.request({\n path,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions,\n });\n\n if (!httpResponse || !httpResponse?.headers) {\n throw new Error(\n 'Server did not return an HttpResponse or the returned HttpResponse did not have headers.',\n );\n }\n\n const uploadUrl: string | undefined =\n httpResponse?.headers?.['x-goog-upload-url'];\n if (uploadUrl === undefined) {\n throw new Error(\n 'Failed to get upload url. Server did not return the x-google-upload-url in the headers',\n );\n }\n return uploadUrl;\n }\n}\n\nasync function throwErrorIfNotOK(response: Response | undefined) {\n if (response === undefined) {\n throw new Error('response is undefined');\n }\n if (!response.ok) {\n const status: number = response.status;\n let errorBody: Record<string, unknown>;\n if (response.headers.get('content-type')?.includes('application/json')) {\n errorBody = await response.json();\n } else {\n errorBody = {\n error: {\n message: await response.text(),\n code: response.status,\n status: response.statusText,\n },\n };\n }\n const errorMessage = JSON.stringify(errorBody);\n if (status >= 400 && status < 600) {\n const apiError = new ApiError({\n message: errorMessage,\n status: status,\n });\n throw apiError;\n }\n throw new Error(errorMessage);\n }\n}\n\n/**\n * Recursively updates the `requestInit.body` with values from an `extraBody` object.\n *\n * If `requestInit.body` is a string, it's assumed to be JSON and will be parsed.\n * The `extraBody` is then deeply merged into this parsed object.\n * If `requestInit.body` is a Blob, `extraBody` will be ignored, and a warning logged,\n * as merging structured data into an opaque Blob is not supported.\n *\n * The function does not enforce that updated values from `extraBody` have the\n * same type as existing values in `requestInit.body`. Type mismatches during\n * the merge will result in a warning, but the value from `extraBody` will overwrite\n * the original. `extraBody` users are responsible for ensuring `extraBody` has the correct structure.\n *\n * @param requestInit The RequestInit object whose body will be updated.\n * @param extraBody The object containing updates to be merged into `requestInit.body`.\n */\nexport function includeExtraBodyToRequestInit(\n requestInit: RequestInit,\n extraBody: Record<string, unknown>,\n) {\n if (!extraBody || Object.keys(extraBody).length === 0) {\n return;\n }\n\n if (requestInit.body instanceof Blob) {\n console.warn(\n 'includeExtraBodyToRequestInit: extraBody provided but current request body is a Blob. extraBody will be ignored as merging is not supported for Blob bodies.',\n );\n return;\n }\n\n let currentBodyObject: Record<string, unknown> = {};\n\n // If adding new type to HttpRequest.body, please check the code below to\n // see if we need to update the logic.\n if (typeof requestInit.body === 'string' && requestInit.body.length > 0) {\n try {\n const parsedBody = JSON.parse(requestInit.body);\n if (\n typeof parsedBody === 'object' &&\n parsedBody !== null &&\n !Array.isArray(parsedBody)\n ) {\n currentBodyObject = parsedBody as Record<string, unknown>;\n } else {\n console.warn(\n 'includeExtraBodyToRequestInit: Original request body is valid JSON but not a non-array object. Skip applying extraBody to the request body.',\n );\n return;\n }\n /* eslint-disable-next-line @typescript-eslint/no-unused-vars */\n } catch (e) {\n console.warn(\n 'includeExtraBodyToRequestInit: Original request body is not valid JSON. Skip applying extraBody to the request body.',\n );\n return;\n }\n }\n\n function deepMerge(\n target: Record<string, unknown>,\n source: Record<string, unknown>,\n ): Record<string, unknown> {\n const output = {...target};\n for (const key in source) {\n if (Object.prototype.hasOwnProperty.call(source, key)) {\n const sourceValue = source[key];\n const targetValue = output[key];\n if (\n sourceValue &&\n typeof sourceValue === 'object' &&\n !Array.isArray(sourceValue) &&\n targetValue &&\n typeof targetValue === 'object' &&\n !Array.isArray(targetValue)\n ) {\n output[key] = deepMerge(\n targetValue as Record<string, unknown>,\n sourceValue as Record<string, unknown>,\n );\n } else {\n if (\n targetValue &&\n sourceValue &&\n typeof targetValue !== typeof sourceValue\n ) {\n console.warn(\n `includeExtraBodyToRequestInit:deepMerge: Type mismatch for key \"${key}\". Original type: ${typeof targetValue}, New type: ${typeof sourceValue}. Overwriting.`,\n );\n }\n output[key] = sourceValue;\n }\n }\n }\n return output;\n }\n\n const mergedBody = deepMerge(currentBodyObject, extraBody);\n requestInit.body = JSON.stringify(mergedBody);\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nexport function crossError(): Error {\n // TODO(b/399934880): this message needs a link to a help page explaining how to enable conditional exports\n return new Error(`This feature requires the web or Node specific @google/genai implementation, you can fix this by either:\n\n*Enabling conditional exports for your project [recommended]*\n\n*Using a platform specific import* - Make sure your code imports either '@google/genai/web' or '@google/genai/node' instead of '@google/genai'.\n`);\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {ApiClient} from '../_api_client.js';\nimport {Downloader} from '../_downloader.js';\nimport {DownloadFileParameters} from '../types.js';\n\nimport {crossError} from './_cross_error.js';\n\nexport class CrossDownloader implements Downloader {\n async download(\n _params: DownloadFileParameters,\n _apiClient: ApiClient,\n ): Promise<void> {\n throw crossError();\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {ApiClient} from '../_api_client.js';\nimport {FileStat, Uploader} from '../_uploader.js';\nimport * as _converters from '../converters/_operations_converters.js';\nimport {\n File,\n HttpResponse,\n UploadToFileSearchStoreOperation,\n} from '../types.js';\nimport {crossError} from './_cross_error.js';\n\nexport const MAX_CHUNK_SIZE = 1024 * 1024 * 8; // bytes\nexport const MAX_RETRY_COUNT = 3;\nexport const INITIAL_RETRY_DELAY_MS = 1000;\nexport const DELAY_MULTIPLIER = 2;\nexport const X_GOOG_UPLOAD_STATUS_HEADER_FIELD = 'x-goog-upload-status';\n\nexport class CrossUploader implements Uploader {\n async upload(\n file: string | Blob,\n uploadUrl: string,\n apiClient: ApiClient,\n ): Promise<File> {\n if (typeof file === 'string') {\n throw crossError();\n } else {\n return uploadBlob(file, uploadUrl, apiClient);\n }\n }\n\n async uploadToFileSearchStore(\n file: string | Blob,\n uploadUrl: string,\n apiClient: ApiClient,\n ): Promise<UploadToFileSearchStoreOperation> {\n if (typeof file === 'string') {\n throw crossError();\n } else {\n return uploadBlobToFileSearchStore(file, uploadUrl, apiClient);\n }\n }\n\n async stat(file: string | Blob): Promise<FileStat> {\n if (typeof file === 'string') {\n throw crossError();\n } else {\n return getBlobStat(file);\n }\n }\n}\n\nexport async function uploadBlob(\n file: Blob,\n uploadUrl: string,\n apiClient: ApiClient,\n): Promise<File> {\n const response = await uploadBlobInternal(file, uploadUrl, apiClient);\n const responseJson = (await response?.json()) as Record<\n string,\n File | unknown\n >;\n if (response?.headers?.[X_GOOG_UPLOAD_STATUS_HEADER_FIELD] !== 'final') {\n throw new Error('Failed to upload file: Upload status is not finalized.');\n }\n return responseJson['file'] as File;\n}\n\nexport async function uploadBlobToFileSearchStore(\n file: Blob,\n uploadUrl: string,\n apiClient: ApiClient,\n): Promise<UploadToFileSearchStoreOperation> {\n const response = await uploadBlobInternal(file, uploadUrl, apiClient);\n const responseJson =\n (await response?.json()) as UploadToFileSearchStoreOperation;\n if (response?.headers?.[X_GOOG_UPLOAD_STATUS_HEADER_FIELD] !== 'final') {\n throw new Error('Failed to upload file: Upload status is not finalized.');\n }\n const resp =\n _converters.uploadToFileSearchStoreOperationFromMldev(responseJson);\n const typedResp = new UploadToFileSearchStoreOperation();\n Object.assign(typedResp, resp);\n return typedResp;\n}\n\nasync function uploadBlobInternal(\n file: Blob,\n uploadUrl: string,\n apiClient: ApiClient,\n): Promise<HttpResponse> {\n let fileSize = 0;\n let offset = 0;\n let response: HttpResponse = new HttpResponse(new Response());\n let uploadCommand = 'upload';\n fileSize = file.size;\n while (offset < fileSize) {\n const chunkSize = Math.min(MAX_CHUNK_SIZE, fileSize - offset);\n const chunk = file.slice(offset, offset + chunkSize);\n if (offset + chunkSize >= fileSize) {\n uploadCommand += ', finalize';\n }\n let retryCount = 0;\n let currentDelayMs = INITIAL_RETRY_DELAY_MS;\n while (retryCount < MAX_RETRY_COUNT) {\n response = await apiClient.request({\n path: '',\n body: chunk,\n httpMethod: 'POST',\n httpOptions: {\n apiVersion: '',\n baseUrl: uploadUrl,\n headers: {\n 'X-Goog-Upload-Command': uploadCommand,\n 'X-Goog-Upload-Offset': String(offset),\n 'Content-Length': String(chunkSize),\n },\n },\n });\n if (response?.headers?.[X_GOOG_UPLOAD_STATUS_HEADER_FIELD]) {\n break;\n }\n retryCount++;\n await sleep(currentDelayMs);\n currentDelayMs = currentDelayMs * DELAY_MULTIPLIER;\n }\n offset += chunkSize;\n // The `x-goog-upload-status` header field can be `active`, `final` and\n //`cancelled` in resposne.\n if (response?.headers?.[X_GOOG_UPLOAD_STATUS_HEADER_FIELD] !== 'active') {\n break;\n }\n // TODO(b/401391430) Investigate why the upload status is not finalized\n // even though all content has been uploaded.\n if (fileSize <= offset) {\n throw new Error(\n 'All content has been uploaded, but the upload status is not finalized.',\n );\n }\n }\n\n return response;\n}\n\nexport async function getBlobStat(file: Blob): Promise<FileStat> {\n const fileStat: FileStat = {size: file.size, type: file.type};\n return fileStat;\n}\n\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolvePromise) => setTimeout(resolvePromise, ms));\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {\n WebSocketCallbacks,\n WebSocketFactory,\n WebSocket as Ws,\n} from '../_websocket.js';\nimport {crossError} from './_cross_error.js';\n\nexport class CrossWebSocketFactory implements WebSocketFactory {\n create(\n _url: string,\n _headers: Record<string, string>,\n _callbacks: WebSocketCallbacks,\n ): Ws {\n throw crossError();\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport * as common from '../_common.js';\nimport * as t from '../_transformers.js';\nimport type * as types from '../types.js';\n\nexport function createFileParametersToMldev(\n fromObject: types.CreateFileParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromFile = common.getValueByPath(fromObject, ['file']);\n if (fromFile != null) {\n common.setValueByPath(toObject, ['file'], fromFile);\n }\n\n return toObject;\n}\n\nexport function createFileResponseFromMldev(\n fromObject: types.CreateFileResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n return toObject;\n}\n\nexport function deleteFileParametersToMldev(\n fromObject: types.DeleteFileParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['_url', 'file'], t.tFileName(fromName));\n }\n\n return toObject;\n}\n\nexport function deleteFileResponseFromMldev(\n fromObject: types.DeleteFileResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n return toObject;\n}\n\nexport function getFileParametersToMldev(\n fromObject: types.GetFileParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['_url', 'file'], t.tFileName(fromName));\n }\n\n return toObject;\n}\n\nexport function internalRegisterFilesParametersToMldev(\n fromObject: types.InternalRegisterFilesParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromUris = common.getValueByPath(fromObject, ['uris']);\n if (fromUris != null) {\n common.setValueByPath(toObject, ['uris'], fromUris);\n }\n\n return toObject;\n}\n\nexport function listFilesConfigToMldev(\n fromObject: types.ListFilesConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPageSize = common.getValueByPath(fromObject, ['pageSize']);\n if (parentObject !== undefined && fromPageSize != null) {\n common.setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize);\n }\n\n const fromPageToken = common.getValueByPath(fromObject, ['pageToken']);\n if (parentObject !== undefined && fromPageToken != null) {\n common.setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken);\n }\n\n return toObject;\n}\n\nexport function listFilesParametersToMldev(\n fromObject: types.ListFilesParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n listFilesConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function listFilesResponseFromMldev(\n fromObject: types.ListFilesResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromNextPageToken = common.getValueByPath(fromObject, [\n 'nextPageToken',\n ]);\n if (fromNextPageToken != null) {\n common.setValueByPath(toObject, ['nextPageToken'], fromNextPageToken);\n }\n\n const fromFiles = common.getValueByPath(fromObject, ['files']);\n if (fromFiles != null) {\n let transformedList = fromFiles;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['files'], transformedList);\n }\n\n return toObject;\n}\n\nexport function registerFilesResponseFromMldev(\n fromObject: types.RegisterFilesResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromFiles = common.getValueByPath(fromObject, ['files']);\n if (fromFiles != null) {\n let transformedList = fromFiles;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['files'], transformedList);\n }\n\n return toObject;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport {ApiClient} from './_api_client.js';\nimport * as common from './_common.js';\nimport {BaseModule} from './_common.js';\nimport * as converters from './converters/_files_converters.js';\nimport {PagedItem, Pager} from './pagers.js';\nimport * as types from './types.js';\n\nexport class Files extends BaseModule {\n constructor(private readonly apiClient: ApiClient) {\n super();\n }\n\n /**\n * Lists files.\n *\n * @param params - The parameters for the list request.\n * @return - A pager of files.\n *\n * @example\n * ```ts\n * const files = await ai.files.list({config: {'pageSize': 2}});\n * for await (const file of files) {\n * console.log(file);\n * }\n * ```\n */\n list = async (\n params: types.ListFilesParameters = {},\n ): Promise<Pager<types.File>> => {\n return new Pager<types.File>(\n PagedItem.PAGED_ITEM_FILES,\n (x: types.ListFilesParameters) => this.listInternal(x),\n await this.listInternal(params),\n params,\n );\n };\n\n /**\n * Uploads a file asynchronously to the Gemini API.\n * This method is not available in Vertex AI.\n * Supported upload sources:\n * - Node.js: File path (string) or Blob object.\n * - Browser: Blob object (e.g., File).\n *\n * @remarks\n * The `mimeType` can be specified in the `config` parameter. If omitted:\n * - For file path (string) inputs, the `mimeType` will be inferred from the\n * file extension.\n * - For Blob object inputs, the `mimeType` will be set to the Blob's `type`\n * property.\n * Somex eamples for file extension to mimeType mapping:\n * .txt -> text/plain\n * .json -> application/json\n * .jpg -> image/jpeg\n * .png -> image/png\n * .mp3 -> audio/mpeg\n * .mp4 -> video/mp4\n *\n * This section can contain multiple paragraphs and code examples.\n *\n * @param params - Optional parameters specified in the\n * `types.UploadFileParameters` interface.\n * @see {@link types.UploadFileParameters#config} for the optional\n * config in the parameters.\n * @return A promise that resolves to a `types.File` object.\n * @throws An error if called on a Vertex AI client.\n * @throws An error if the `mimeType` is not provided and can not be inferred,\n * the `mimeType` can be provided in the `params.config` parameter.\n * @throws An error occurs if a suitable upload location cannot be established.\n *\n * @example\n * The following code uploads a file to Gemini API.\n *\n * ```ts\n * const file = await ai.files.upload({file: 'file.txt', config: {\n * mimeType: 'text/plain',\n * }});\n * console.log(file.name);\n * ```\n */\n async upload(params: types.UploadFileParameters): Promise<types.File> {\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'Vertex AI does not support uploading files. You can share files through a GCS bucket.',\n );\n }\n\n return this.apiClient\n .uploadFile(params.file, params.config)\n .then((resp) => {\n return resp as types.File;\n });\n }\n\n /**\n * Downloads a remotely stored file asynchronously to a location specified in\n * the `params` object. This method only works on Node environment, to\n * download files in the browser, use a browser compliant method like an <a>\n * tag.\n *\n * @param params - The parameters for the download request.\n *\n * @example\n * The following code downloads an example file named \"files/mehozpxf877d\" as\n * \"file.txt\".\n *\n * ```ts\n * await ai.files.download({file: file.name, downloadPath: 'file.txt'});\n * ```\n */\n\n async download(params: types.DownloadFileParameters): Promise<void> {\n await this.apiClient.downloadFile(params);\n }\n\n /**\n * Registers Google Cloud Storage files for use with the API.\n * This method is only available in Node.js environments.\n */\n async registerFiles(\n params: types.RegisterFilesParameters,\n ): Promise<types.RegisterFilesResponse> {\n void params;\n throw new Error('registerFiles is only supported in Node.js environments.');\n }\n\n protected async _registerFiles(\n params: types.InternalRegisterFilesParameters,\n ): Promise<types.RegisterFilesResponse> {\n return this.registerFilesInternal(params);\n }\n\n private async listInternal(\n params: types.ListFilesParameters,\n ): Promise<types.ListFilesResponse> {\n let response: Promise<types.ListFilesResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.listFilesParametersToMldev(params);\n path = common.formatMap('files', body['_url'] as Record<string, unknown>);\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.ListFilesResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.ListFilesResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.listFilesResponseFromMldev(apiResponse);\n const typedResp = new types.ListFilesResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n private async createInternal(\n params: types.CreateFileParameters,\n ): Promise<types.CreateFileResponse> {\n let response: Promise<types.CreateFileResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.createFileParametersToMldev(params);\n path = common.formatMap(\n 'upload/v1beta/files',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.CreateFileResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.createFileResponseFromMldev(apiResponse);\n const typedResp = new types.CreateFileResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n /**\n * Retrieves the file information from the service.\n *\n * @param params - The parameters for the get request\n * @return The Promise that resolves to the types.File object requested.\n *\n * @example\n * ```ts\n * const config: GetFileParameters = {\n * name: fileName,\n * };\n * file = await ai.files.get(config);\n * console.log(file.name);\n * ```\n */\n async get(params: types.GetFileParameters): Promise<types.File> {\n let response: Promise<types.File>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.getFileParametersToMldev(params);\n path = common.formatMap(\n 'files/{file}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.File>;\n\n return response.then((resp) => {\n return resp as types.File;\n });\n }\n }\n\n /**\n * Deletes a remotely stored file.\n *\n * @param params - The parameters for the delete request.\n * @return The DeleteFileResponse, the response for the delete method.\n *\n * @example\n * The following code deletes an example file named \"files/mehozpxf877d\".\n *\n * ```ts\n * await ai.files.delete({name: file.name});\n * ```\n */\n async delete(\n params: types.DeleteFileParameters,\n ): Promise<types.DeleteFileResponse> {\n let response: Promise<types.DeleteFileResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.deleteFileParametersToMldev(params);\n path = common.formatMap(\n 'files/{file}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'DELETE',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.DeleteFileResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.DeleteFileResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.deleteFileResponseFromMldev(apiResponse);\n const typedResp = new types.DeleteFileResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n private async registerFilesInternal(\n params: types.InternalRegisterFilesParameters,\n ): Promise<types.RegisterFilesResponse> {\n let response: Promise<types.RegisterFilesResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.internalRegisterFilesParametersToMldev(params);\n path = common.formatMap(\n 'files:register',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.RegisterFilesResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.registerFilesResponseFromMldev(apiResponse);\n const typedResp = new types.RegisterFilesResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport * as common from '../_common.js';\nimport type * as types from '../types.js';\n\nexport function deleteDocumentConfigToMldev(\n fromObject: types.DeleteDocumentConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromForce = common.getValueByPath(fromObject, ['force']);\n if (parentObject !== undefined && fromForce != null) {\n common.setValueByPath(parentObject, ['_query', 'force'], fromForce);\n }\n\n return toObject;\n}\n\nexport function deleteDocumentParametersToMldev(\n fromObject: types.DeleteDocumentParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['_url', 'name'], fromName);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n deleteDocumentConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function getDocumentParametersToMldev(\n fromObject: types.GetDocumentParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['_url', 'name'], fromName);\n }\n\n return toObject;\n}\n\nexport function listDocumentsConfigToMldev(\n fromObject: types.ListDocumentsConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPageSize = common.getValueByPath(fromObject, ['pageSize']);\n if (parentObject !== undefined && fromPageSize != null) {\n common.setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize);\n }\n\n const fromPageToken = common.getValueByPath(fromObject, ['pageToken']);\n if (parentObject !== undefined && fromPageToken != null) {\n common.setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken);\n }\n\n return toObject;\n}\n\nexport function listDocumentsParametersToMldev(\n fromObject: types.ListDocumentsParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromParent = common.getValueByPath(fromObject, ['parent']);\n if (fromParent != null) {\n common.setValueByPath(toObject, ['_url', 'parent'], fromParent);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n listDocumentsConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function listDocumentsResponseFromMldev(\n fromObject: types.ListDocumentsResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromNextPageToken = common.getValueByPath(fromObject, [\n 'nextPageToken',\n ]);\n if (fromNextPageToken != null) {\n common.setValueByPath(toObject, ['nextPageToken'], fromNextPageToken);\n }\n\n const fromDocuments = common.getValueByPath(fromObject, ['documents']);\n if (fromDocuments != null) {\n let transformedList = fromDocuments;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['documents'], transformedList);\n }\n\n return toObject;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport {ApiClient} from './_api_client.js';\nimport * as common from './_common.js';\nimport {BaseModule} from './_common.js';\nimport * as converters from './converters/_documents_converters.js';\nimport {PagedItem, PagedItemConfig, Pager} from './pagers.js';\nimport * as types from './types.js';\n\nexport class Documents extends BaseModule {\n constructor(private readonly apiClient: ApiClient) {\n super();\n }\n\n /**\n * Lists documents.\n *\n * @param params - The parameters for the list request.\n * @return - A pager of documents.\n *\n * @example\n * ```ts\n * const documents = await ai.documents.list({parent:'rag_store_name', config: {'pageSize': 2}});\n * for await (const document of documents) {\n * console.log(document);\n * }\n * ```\n */\n\n list = async (\n params: types.ListDocumentsParameters,\n ): Promise<Pager<types.Document>> => {\n return new Pager<types.Document>(\n PagedItem.PAGED_ITEM_DOCUMENTS,\n (x: PagedItemConfig) =>\n this.listInternal({parent: params.parent, config: x.config}),\n await this.listInternal(params),\n params,\n );\n };\n\n /**\n * Gets a Document.\n *\n * @param params - The parameters for getting a document.\n * @return Document.\n */\n\n async get(params: types.GetDocumentParameters): Promise<types.Document> {\n let response: Promise<types.Document>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.getDocumentParametersToMldev(params);\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.Document>;\n\n return response.then((resp) => {\n return resp as types.Document;\n });\n }\n }\n\n /**\n * Deletes a Document.\n *\n * @param params - The parameters for deleting a document.\n */\n\n async delete(params: types.DeleteDocumentParameters): Promise<void> {\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.deleteDocumentParametersToMldev(params);\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n await this.apiClient.request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'DELETE',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n });\n }\n }\n\n private async listInternal(\n params: types.ListDocumentsParameters,\n ): Promise<types.ListDocumentsResponse> {\n let response: Promise<types.ListDocumentsResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.listDocumentsParametersToMldev(params);\n path = common.formatMap(\n '{parent}/documents',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.ListDocumentsResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.listDocumentsResponseFromMldev(apiResponse);\n const typedResp = new types.ListDocumentsResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport {ApiClient} from './_api_client.js';\nimport * as common from './_common.js';\nimport {BaseModule} from './_common.js';\nimport * as converters from './converters/_filesearchstores_converters.js';\nimport {Documents} from './documents.js';\nimport {PagedItem, Pager} from './pagers.js';\nimport * as types from './types.js';\n\nexport class FileSearchStores extends BaseModule {\n constructor(\n private readonly apiClient: ApiClient,\n public readonly documents: Documents = new Documents(apiClient),\n ) {\n super();\n }\n\n /**\n * Lists file search stores.\n *\n * @param params - The parameters for the list request.\n * @return - A pager of file search stores.\n *\n * @example\n * ```ts\n * const fileSearchStores = await ai.fileSearchStores.list({config: {'pageSize': 2}});\n * for await (const fileSearchStore of fileSearchStores) {\n * console.log(fileSearchStore);\n * }\n * ```\n */\n\n list = async (\n params: types.ListFileSearchStoresParameters = {},\n ): Promise<Pager<types.FileSearchStore>> => {\n return new Pager<types.FileSearchStore>(\n PagedItem.PAGED_ITEM_FILE_SEARCH_STORES,\n (x: types.ListFileSearchStoresParameters) => this.listInternal(x),\n await this.listInternal(params),\n params,\n );\n };\n\n /**\n * Uploads a file asynchronously to a given File Search Store.\n * This method is not available in Vertex AI.\n * Supported upload sources:\n * - Node.js: File path (string) or Blob object.\n * - Browser: Blob object (e.g., File).\n *\n * @remarks\n * The `mimeType` can be specified in the `config` parameter. If omitted:\n * - For file path (string) inputs, the `mimeType` will be inferred from the\n * file extension.\n * - For Blob object inputs, the `mimeType` will be set to the Blob's `type`\n * property.\n *\n * This section can contain multiple paragraphs and code examples.\n *\n * @param params - Optional parameters specified in the\n * `types.UploadToFileSearchStoreParameters` interface.\n * @see {@link types.UploadToFileSearchStoreParameters#config} for the optional\n * config in the parameters.\n * @return A promise that resolves to a long running operation.\n * @throws An error if called on a Vertex AI client.\n * @throws An error if the `mimeType` is not provided and can not be inferred,\n * the `mimeType` can be provided in the `params.config` parameter.\n * @throws An error occurs if a suitable upload location cannot be established.\n *\n * @example\n * The following code uploads a file to a given file search store.\n *\n * ```ts\n * const operation = await ai.fileSearchStores.upload({fileSearchStoreName: 'fileSearchStores/foo-bar', file: 'file.txt', config: {\n * mimeType: 'text/plain',\n * }});\n * console.log(operation.name);\n * ```\n */\n async uploadToFileSearchStore(\n params: types.UploadToFileSearchStoreParameters,\n ): Promise<types.UploadToFileSearchStoreOperation> {\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'Vertex AI does not support uploading files to a file search store.',\n );\n }\n\n return this.apiClient.uploadFileToFileSearchStore(\n params.fileSearchStoreName,\n params.file,\n params.config,\n );\n }\n\n /**\n * Creates a File Search Store.\n *\n * @param params - The parameters for creating a File Search Store.\n * @return FileSearchStore.\n */\n\n async create(\n params: types.CreateFileSearchStoreParameters,\n ): Promise<types.FileSearchStore> {\n let response: Promise<types.FileSearchStore>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.createFileSearchStoreParametersToMldev(params);\n path = common.formatMap(\n 'fileSearchStores',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.FileSearchStore>;\n\n return response.then((resp) => {\n return resp as types.FileSearchStore;\n });\n }\n }\n\n /**\n * Gets a File Search Store.\n *\n * @param params - The parameters for getting a File Search Store.\n * @return FileSearchStore.\n */\n\n async get(\n params: types.GetFileSearchStoreParameters,\n ): Promise<types.FileSearchStore> {\n let response: Promise<types.FileSearchStore>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.getFileSearchStoreParametersToMldev(params);\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.FileSearchStore>;\n\n return response.then((resp) => {\n return resp as types.FileSearchStore;\n });\n }\n }\n\n /**\n * Deletes a File Search Store.\n *\n * @param params - The parameters for deleting a File Search Store.\n */\n\n async delete(params: types.DeleteFileSearchStoreParameters): Promise<void> {\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.deleteFileSearchStoreParametersToMldev(params);\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n await this.apiClient.request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'DELETE',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n });\n }\n }\n\n private async listInternal(\n params: types.ListFileSearchStoresParameters,\n ): Promise<types.ListFileSearchStoresResponse> {\n let response: Promise<types.ListFileSearchStoresResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.listFileSearchStoresParametersToMldev(params);\n path = common.formatMap(\n 'fileSearchStores',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.ListFileSearchStoresResponse>;\n\n return response.then((apiResponse) => {\n const resp =\n converters.listFileSearchStoresResponseFromMldev(apiResponse);\n const typedResp = new types.ListFileSearchStoresResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n private async uploadToFileSearchStoreInternal(\n params: types.UploadToFileSearchStoreParameters,\n ): Promise<types.UploadToFileSearchStoreResumableResponse> {\n let response: Promise<types.UploadToFileSearchStoreResumableResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.uploadToFileSearchStoreParametersToMldev(params);\n path = common.formatMap(\n 'upload/v1beta/{file_search_store_name}:uploadToFileSearchStore',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.UploadToFileSearchStoreResumableResponse>;\n\n return response.then((apiResponse) => {\n const resp =\n converters.uploadToFileSearchStoreResumableResponseFromMldev(\n apiResponse,\n );\n const typedResp = new types.UploadToFileSearchStoreResumableResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n /**\n * Imports a File from File Service to a FileSearchStore.\n *\n * This is a long-running operation, see aip.dev/151\n *\n * @param params - The parameters for importing a file to a file search store.\n * @return ImportFileOperation.\n */\n\n async importFile(\n params: types.ImportFileParameters,\n ): Promise<types.ImportFileOperation> {\n let response: Promise<types.ImportFileOperation>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.importFileParametersToMldev(params);\n path = common.formatMap(\n '{file_search_store_name}:importFile',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.ImportFileOperation>;\n\n return response.then((apiResponse) => {\n const resp = converters.importFileOperationFromMldev(apiResponse);\n const typedResp = new types.ImportFileOperation();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\n/**\n * https://stackoverflow.com/a/2117523\n */\nlet uuid4Internal = function (): string {\n const { crypto } = globalThis as any;\n if (crypto?.randomUUID) {\n uuid4Internal = crypto.randomUUID.bind(crypto);\n return crypto.randomUUID();\n }\n const u8 = new Uint8Array(1);\n const randomByte = crypto ? () => crypto.getRandomValues(u8)[0]! : () => (Math.random() * 0xff) & 0xff;\n return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, (c) =>\n (+c ^ (randomByte() & (15 >> (+c / 4)))).toString(16),\n );\n};\n\nexport const uuid4 = (): string => uuid4Internal();\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nexport function isAbortError(err: unknown) {\n return (\n typeof err === 'object' &&\n err !== null &&\n // Spec-compliant fetch implementations\n (('name' in err && (err as any).name === 'AbortError') ||\n // Expo fetch\n ('message' in err && String((err as any).message).includes('FetchRequestCanceledException')))\n );\n}\n\nexport const castToError = (err: any): Error => {\n if (err instanceof Error) return err;\n if (typeof err === 'object' && err !== null) {\n try {\n if (Object.prototype.toString.call(err) === '[object Error]') {\n // @ts-ignore - not all envs have native support for cause yet\n const error = new Error(err.message, err.cause ? { cause: err.cause } : {});\n if (err.stack) error.stack = err.stack;\n // @ts-ignore - not all envs have native support for cause yet\n if (err.cause && !error.cause) error.cause = err.cause;\n if (err.name) error.name = err.name;\n return error;\n }\n } catch {}\n try {\n return new Error(JSON.stringify(err));\n } catch {}\n }\n return new Error(err);\n};\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nimport { castToError } from '../internal/errors.js';\n\nexport class GeminiNextGenAPIClientError extends Error {}\n\nexport class APIError<\n TStatus extends number | undefined = number | undefined,\n THeaders extends Headers | undefined = Headers | undefined,\n TError extends Object | undefined = Object | undefined,\n> extends GeminiNextGenAPIClientError {\n /** HTTP status for the response that caused the error */\n readonly status: TStatus;\n /** HTTP headers for the response that caused the error */\n readonly headers: THeaders;\n /** JSON body of the response that caused the error */\n readonly error: TError;\n\n constructor(status: TStatus, error: TError, message: string | undefined, headers: THeaders) {\n super(`${APIError.makeMessage(status, error, message)}`);\n this.status = status;\n this.headers = headers;\n this.error = error;\n }\n\n private static makeMessage(status: number | undefined, error: any, message: string | undefined) {\n const msg =\n error?.message ?\n typeof error.message === 'string' ?\n error.message\n : JSON.stringify(error.message)\n : error ? JSON.stringify(error)\n : message;\n\n if (status && msg) {\n return `${status} ${msg}`;\n }\n if (status) {\n return `${status} status code (no body)`;\n }\n if (msg) {\n return msg;\n }\n return '(no status code or body)';\n }\n\n static generate(\n status: number | undefined,\n errorResponse: Object | undefined,\n message: string | undefined,\n headers: Headers | undefined,\n ): APIError {\n if (!status || !headers) {\n return new APIConnectionError({ message, cause: castToError(errorResponse) });\n }\n\n const error = errorResponse as Record<string, any>;\n\n if (status === 400) {\n return new BadRequestError(status, error, message, headers);\n }\n\n if (status === 401) {\n return new AuthenticationError(status, error, message, headers);\n }\n\n if (status === 403) {\n return new PermissionDeniedError(status, error, message, headers);\n }\n\n if (status === 404) {\n return new NotFoundError(status, error, message, headers);\n }\n\n if (status === 409) {\n return new ConflictError(status, error, message, headers);\n }\n\n if (status === 422) {\n return new UnprocessableEntityError(status, error, message, headers);\n }\n\n if (status === 429) {\n return new RateLimitError(status, error, message, headers);\n }\n\n if (status >= 500) {\n return new InternalServerError(status, error, message, headers);\n }\n\n return new APIError(status, error, message, headers);\n }\n}\n\nexport class APIUserAbortError extends APIError<undefined, undefined, undefined> {\n constructor({ message }: { message?: string } = {}) {\n super(undefined, undefined, message || 'Request was aborted.', undefined);\n }\n}\n\nexport class APIConnectionError extends APIError<undefined, undefined, undefined> {\n constructor({ message, cause }: { message?: string | undefined; cause?: Error | undefined }) {\n super(undefined, undefined, message || 'Connection error.', undefined);\n // in some environments the 'cause' property is already declared\n // @ts-ignore\n if (cause) this.cause = cause;\n }\n}\n\nexport class APIConnectionTimeoutError extends APIConnectionError {\n constructor({ message }: { message?: string } = {}) {\n super({ message: message ?? 'Request timed out.' });\n }\n}\n\nexport class BadRequestError extends APIError<400, Headers> {}\n\nexport class AuthenticationError extends APIError<401, Headers> {}\n\nexport class PermissionDeniedError extends APIError<403, Headers> {}\n\nexport class NotFoundError extends APIError<404, Headers> {}\n\nexport class ConflictError extends APIError<409, Headers> {}\n\nexport class UnprocessableEntityError extends APIError<422, Headers> {}\n\nexport class RateLimitError extends APIError<429, Headers> {}\n\nexport class InternalServerError extends APIError<number, Headers> {}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nimport { GeminiNextGenAPIClientError } from '../../core/error.js';\n\n// https://url.spec.whatwg.org/#url-scheme-string\nconst startsWithSchemeRegexp = /^[a-z][a-z0-9+.-]*:/i;\n\nexport const isAbsoluteURL = (url: string): boolean => {\n return startsWithSchemeRegexp.test(url);\n};\n\nlet isArrayInternal = (val: unknown): val is unknown[] => (\n (isArrayInternal = Array.isArray), isArrayInternal(val)\n);\nexport const isArray = isArrayInternal;\nlet isReadonlyArrayInternal = isArray as (val: unknown) => val is readonly unknown[];\nexport const isReadonlyArray = isReadonlyArrayInternal;\n\n/** Returns an object if the given value isn't an object, otherwise returns as-is */\nexport function maybeObj(x: unknown): object {\n if (typeof x !== 'object') {\n return {};\n }\n\n return x ?? {};\n}\n\n// https://stackoverflow.com/a/34491287\nexport function isEmptyObj(obj: Object | null | undefined): boolean {\n if (!obj) return true;\n for (const _k in obj) return false;\n return true;\n}\n\n// https://eslint.org/docs/latest/rules/no-prototype-builtins\nexport function hasOwn<T extends object = object>(obj: T, key: PropertyKey): key is keyof T {\n return Object.prototype.hasOwnProperty.call(obj, key);\n}\n\nexport function isObj(obj: unknown): obj is Record<string, unknown> {\n return obj != null && typeof obj === 'object' && !Array.isArray(obj);\n}\n\nexport const ensurePresent = <T>(value: T | null | undefined): T => {\n if (value == null) {\n throw new GeminiNextGenAPIClientError(`Expected a value to be given but received ${value} instead.`);\n }\n\n return value;\n};\n\nexport const validatePositiveInteger = (name: string, n: unknown): number => {\n if (typeof n !== 'number' || !Number.isInteger(n)) {\n throw new GeminiNextGenAPIClientError(`${name} must be an integer`);\n }\n if (n < 0) {\n throw new GeminiNextGenAPIClientError(`${name} must be a positive integer`);\n }\n return n;\n};\n\nexport const coerceInteger = (value: unknown): number => {\n if (typeof value === 'number') return Math.round(value);\n if (typeof value === 'string') return parseInt(value, 10);\n\n throw new GeminiNextGenAPIClientError(`Could not coerce ${value} (type: ${typeof value}) into a number`);\n};\n\nexport const coerceFloat = (value: unknown): number => {\n if (typeof value === 'number') return value;\n if (typeof value === 'string') return parseFloat(value);\n\n throw new GeminiNextGenAPIClientError(`Could not coerce ${value} (type: ${typeof value}) into a number`);\n};\n\nexport const coerceBoolean = (value: unknown): boolean => {\n if (typeof value === 'boolean') return value;\n if (typeof value === 'string') return value === 'true';\n return Boolean(value);\n};\n\nexport const maybeCoerceInteger = (value: unknown): number | undefined => {\n if (value == null) {\n return undefined;\n }\n return coerceInteger(value);\n};\n\nexport const maybeCoerceFloat = (value: unknown): number | undefined => {\n if (value == null) {\n return undefined;\n }\n return coerceFloat(value);\n};\n\nexport const maybeCoerceBoolean = (value: unknown): boolean | undefined => {\n if (value == null) {\n return undefined;\n }\n return coerceBoolean(value);\n};\n\nexport const safeJSON = (text: string) => {\n try {\n return JSON.parse(text);\n } catch (err) {\n return undefined;\n }\n};\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nexport const sleep = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms));\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nexport const VERSION = '0.0.1';\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nimport { VERSION } from '../version.js';\n\nexport const isRunningInBrowser = () => {\n return (\n // @ts-ignore\n (typeof window !== 'undefined' &&\n // @ts-ignore\n typeof window.document !== 'undefined' && typeof navigator !== 'undefined')\n );\n};\n\ntype DetectedPlatform = 'deno' | 'node' | 'edge' | 'unknown';\n\n/**\n * Note this does not detect 'browser'; for that, use getBrowserInfo().\n */\nfunction getDetectedPlatform(): DetectedPlatform {\n if (typeof Deno !== 'undefined' && Deno.build != null) {\n return 'deno';\n }\n if (typeof EdgeRuntime !== 'undefined') {\n return 'edge';\n }\n if (\n Object.prototype.toString.call(\n typeof (globalThis as any).process !== 'undefined' ? (globalThis as any).process : 0,\n ) === '[object process]'\n ) {\n return 'node';\n }\n return 'unknown';\n}\n\ndeclare const Deno: any;\ndeclare const EdgeRuntime: any;\ntype Arch = 'x32' | 'x64' | 'arm' | 'arm64' | `other:${string}` | 'unknown';\ntype PlatformName =\n | 'MacOS'\n | 'Linux'\n | 'Windows'\n | 'FreeBSD'\n | 'OpenBSD'\n | 'iOS'\n | 'Android'\n | `Other:${string}`\n | 'Unknown';\ntype Browser = 'ie' | 'edge' | 'chrome' | 'firefox' | 'safari';\ntype PlatformProperties = {\n 'X-Stainless-Lang': 'js';\n 'X-Stainless-Package-Version': string;\n 'X-Stainless-OS': PlatformName;\n 'X-Stainless-Arch': Arch;\n 'X-Stainless-Runtime': 'node' | 'deno' | 'edge' | `browser:${Browser}` | 'unknown';\n 'X-Stainless-Runtime-Version': string;\n};\nconst getPlatformProperties = (): PlatformProperties => {\n const detectedPlatform = getDetectedPlatform();\n if (detectedPlatform === 'deno') {\n return {\n 'X-Stainless-Lang': 'js',\n 'X-Stainless-Package-Version': VERSION,\n 'X-Stainless-OS': normalizePlatform(Deno.build.os),\n 'X-Stainless-Arch': normalizeArch(Deno.build.arch),\n 'X-Stainless-Runtime': 'deno',\n 'X-Stainless-Runtime-Version':\n typeof Deno.version === 'string' ? Deno.version : Deno.version?.deno ?? 'unknown',\n };\n }\n if (typeof EdgeRuntime !== 'undefined') {\n return {\n 'X-Stainless-Lang': 'js',\n 'X-Stainless-Package-Version': VERSION,\n 'X-Stainless-OS': 'Unknown',\n 'X-Stainless-Arch': `other:${EdgeRuntime}`,\n 'X-Stainless-Runtime': 'edge',\n 'X-Stainless-Runtime-Version': (globalThis as any).process.version,\n };\n }\n // Check if Node.js\n if (detectedPlatform === 'node') {\n return {\n 'X-Stainless-Lang': 'js',\n 'X-Stainless-Package-Version': VERSION,\n 'X-Stainless-OS': normalizePlatform((globalThis as any).process.platform ?? 'unknown'),\n 'X-Stainless-Arch': normalizeArch((globalThis as any).process.arch ?? 'unknown'),\n 'X-Stainless-Runtime': 'node',\n 'X-Stainless-Runtime-Version': (globalThis as any).process.version ?? 'unknown',\n };\n }\n\n const browserInfo = getBrowserInfo();\n if (browserInfo) {\n return {\n 'X-Stainless-Lang': 'js',\n 'X-Stainless-Package-Version': VERSION,\n 'X-Stainless-OS': 'Unknown',\n 'X-Stainless-Arch': 'unknown',\n 'X-Stainless-Runtime': `browser:${browserInfo.browser}`,\n 'X-Stainless-Runtime-Version': browserInfo.version,\n };\n }\n\n // TODO add support for Cloudflare workers, etc.\n return {\n 'X-Stainless-Lang': 'js',\n 'X-Stainless-Package-Version': VERSION,\n 'X-Stainless-OS': 'Unknown',\n 'X-Stainless-Arch': 'unknown',\n 'X-Stainless-Runtime': 'unknown',\n 'X-Stainless-Runtime-Version': 'unknown',\n };\n};\n\ntype BrowserInfo = {\n browser: Browser;\n version: string;\n};\n\ndeclare const navigator: { userAgent: string } | undefined;\n\n// Note: modified from https://github.com/JS-DevTools/host-environment/blob/b1ab79ecde37db5d6e163c050e54fe7d287d7c92/src/isomorphic.browser.ts\nfunction getBrowserInfo(): BrowserInfo | null {\n if (typeof navigator === 'undefined' || !navigator) {\n return null;\n }\n\n // NOTE: The order matters here!\n const browserPatterns = [\n { key: 'edge' as const, pattern: /Edge(?:\\W+(\\d+)\\.(\\d+)(?:\\.(\\d+))?)?/ },\n { key: 'ie' as const, pattern: /MSIE(?:\\W+(\\d+)\\.(\\d+)(?:\\.(\\d+))?)?/ },\n { key: 'ie' as const, pattern: /Trident(?:.*rv\\:(\\d+)\\.(\\d+)(?:\\.(\\d+))?)?/ },\n { key: 'chrome' as const, pattern: /Chrome(?:\\W+(\\d+)\\.(\\d+)(?:\\.(\\d+))?)?/ },\n { key: 'firefox' as const, pattern: /Firefox(?:\\W+(\\d+)\\.(\\d+)(?:\\.(\\d+))?)?/ },\n { key: 'safari' as const, pattern: /(?:Version\\W+(\\d+)\\.(\\d+)(?:\\.(\\d+))?)?(?:\\W+Mobile\\S*)?\\W+Safari/ },\n ];\n\n // Find the FIRST matching browser\n for (const { key, pattern } of browserPatterns) {\n const match = pattern.exec(navigator.userAgent);\n if (match) {\n const major = match[1] || 0;\n const minor = match[2] || 0;\n const patch = match[3] || 0;\n\n return { browser: key, version: `${major}.${minor}.${patch}` };\n }\n }\n\n return null;\n}\n\nconst normalizeArch = (arch: string): Arch => {\n // Node docs:\n // - https://nodejs.org/api/process.html#processarch\n // Deno docs:\n // - https://doc.deno.land/deno/stable/~/Deno.build\n if (arch === 'x32') return 'x32';\n if (arch === 'x86_64' || arch === 'x64') return 'x64';\n if (arch === 'arm') return 'arm';\n if (arch === 'aarch64' || arch === 'arm64') return 'arm64';\n if (arch) return `other:${arch}`;\n return 'unknown';\n};\n\nconst normalizePlatform = (platform: string): PlatformName => {\n // Node platforms:\n // - https://nodejs.org/api/process.html#processplatform\n // Deno platforms:\n // - https://doc.deno.land/deno/stable/~/Deno.build\n // - https://github.com/denoland/deno/issues/14799\n\n platform = platform.toLowerCase();\n\n // NOTE: this iOS check is untested and may not work\n // Node does not work natively on IOS, there is a fork at\n // https://github.com/nodejs-mobile/nodejs-mobile\n // however it is unknown at the time of writing how to detect if it is running\n if (platform.includes('ios')) return 'iOS';\n if (platform === 'android') return 'Android';\n if (platform === 'darwin') return 'MacOS';\n if (platform === 'win32') return 'Windows';\n if (platform === 'freebsd') return 'FreeBSD';\n if (platform === 'openbsd') return 'OpenBSD';\n if (platform === 'linux') return 'Linux';\n if (platform) return `Other:${platform}`;\n return 'Unknown';\n};\n\nlet _platformHeaders: PlatformProperties;\nexport const getPlatformHeaders = () => {\n return (_platformHeaders ??= getPlatformProperties());\n};\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\n/**\n * This module provides internal shims and utility functions for environments where certain Node.js or global types may not be available.\n *\n * These are used to ensure we can provide a consistent behaviour between different JavaScript environments and good error\n * messages in cases where an environment isn't fully supported.\n */\n\nimport type { Fetch } from './builtin-types.js';\nimport type { ReadableStream } from './shim-types.js';\n\nexport function getDefaultFetch(): Fetch {\n if (typeof fetch !== 'undefined') {\n return fetch as any;\n }\n\n throw new Error(\n '`fetch` is not defined as a global; Either pass `fetch` to the client, `new GeminiNextGenAPIClient({ fetch })` or polyfill the global, `globalThis.fetch = fetch`',\n );\n}\n\ntype ReadableStreamArgs = ConstructorParameters<typeof ReadableStream>;\n\nexport function makeReadableStream(...args: ReadableStreamArgs): ReadableStream {\n const ReadableStream = (globalThis as any).ReadableStream;\n if (typeof ReadableStream === 'undefined') {\n // Note: All of the platforms / runtimes we officially support already define\n // `ReadableStream` as a global, so this should only ever be hit on unsupported runtimes.\n throw new Error(\n '`ReadableStream` is not defined as a global; You will need to polyfill it, `globalThis.ReadableStream = ReadableStream`',\n );\n }\n\n return new ReadableStream(...args);\n}\n\nexport function ReadableStreamFrom<T>(iterable: Iterable<T> | AsyncIterable<T>): ReadableStream<T> {\n let iter: AsyncIterator<T> | Iterator<T> =\n Symbol.asyncIterator in iterable ? iterable[Symbol.asyncIterator]() : iterable[Symbol.iterator]();\n\n return makeReadableStream({\n start() {},\n async pull(controller: any) {\n const { done, value } = await iter.next();\n if (done) {\n controller.close();\n } else {\n controller.enqueue(value);\n }\n },\n async cancel() {\n await iter.return?.();\n },\n });\n}\n\n/**\n * Most browsers don't yet have async iterable support for ReadableStream,\n * and Node has a very different way of reading bytes from its \"ReadableStream\".\n *\n * This polyfill was pulled from https://github.com/MattiasBuelens/web-streams-polyfill/pull/122#issuecomment-1627354490\n */\nexport function ReadableStreamToAsyncIterable<T>(stream: any): AsyncIterableIterator<T> {\n if (stream[Symbol.asyncIterator]) return stream;\n\n const reader = stream.getReader();\n return {\n async next() {\n try {\n const result = await reader.read();\n if (result?.done) reader.releaseLock(); // release lock when stream becomes closed\n return result;\n } catch (e) {\n reader.releaseLock(); // release lock when stream becomes errored\n throw e;\n }\n },\n async return() {\n const cancelPromise = reader.cancel();\n reader.releaseLock();\n await cancelPromise;\n return { done: true, value: undefined };\n },\n [Symbol.asyncIterator]() {\n return this;\n },\n };\n}\n\n/**\n * Cancels a ReadableStream we don't need to consume.\n * See https://undici.nodejs.org/#/?id=garbage-collection\n */\nexport async function CancelReadableStream(stream: any): Promise<void> {\n if (stream === null || typeof stream !== 'object') return;\n\n if (stream[Symbol.asyncIterator]) {\n await stream[Symbol.asyncIterator]().return?.();\n return;\n }\n\n const reader = stream.getReader();\n const cancelPromise = reader.cancel();\n reader.releaseLock();\n await cancelPromise;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nimport { NullableHeaders } from './headers.js';\n\nimport type { BodyInit } from './builtin-types.js';\nimport { Stream } from '../core/streaming.js';\nimport type { HTTPMethod, MergedRequestInit } from './types.js';\nimport { type HeadersLike } from './headers.js';\n\nexport type FinalRequestOptions = RequestOptions & { method: HTTPMethod; path: string };\n\nexport type RequestOptions = {\n /**\n * The HTTP method for the request (e.g., 'get', 'post', 'put', 'delete').\n */\n method?: HTTPMethod;\n\n /**\n * The URL path for the request.\n *\n * @example \"/v1/foo\"\n */\n path?: string;\n\n /**\n * Query parameters to include in the request URL.\n */\n query?: object | undefined | null;\n\n /**\n * The request body. Can be a string, JSON object, FormData, or other supported types.\n */\n body?: unknown;\n\n /**\n * HTTP headers to include with the request. Can be a Headers object, plain object, or array of tuples.\n */\n headers?: HeadersLike;\n\n /**\n * The maximum number of times that the client will retry a request in case of a\n * temporary failure, like a network error or a 5XX error from the server.\n *\n * @default 2\n */\n maxRetries?: number;\n\n stream?: boolean | undefined;\n\n /**\n * The maximum amount of time (in milliseconds) that the client should wait for a response\n * from the server before timing out a single request.\n *\n * @unit milliseconds\n */\n timeout?: number;\n\n /**\n * Additional `RequestInit` options to be passed to the underlying `fetch` call.\n * These options will be merged with the client's default fetch options.\n */\n fetchOptions?: MergedRequestInit;\n\n /**\n * An AbortSignal that can be used to cancel the request.\n */\n signal?: AbortSignal | undefined | null;\n\n /**\n * A unique key for this request to enable idempotency.\n */\n idempotencyKey?: string;\n\n /**\n * Override the default base URL for this specific request.\n */\n defaultBaseURL?: string | undefined;\n\n __binaryResponse?: boolean | undefined;\n __streamClass?: typeof Stream;\n};\n\nexport type EncodedContent = { bodyHeaders: HeadersLike; body: BodyInit };\nexport type RequestEncoder = (request: { headers: NullableHeaders; body: unknown }) => EncodedContent;\n\nexport const FallbackEncoder: RequestEncoder = ({ headers, body }) => {\n return {\n bodyHeaders: {\n 'content-type': 'application/json',\n },\n body: JSON.stringify(body),\n };\n};\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { type RequestOptions } from './request-options.js';\nimport type { FilePropertyBag, Fetch } from './builtin-types.js';\nimport type { BaseGeminiNextGenAPIClient } from '../client.js';\nimport { ReadableStreamFrom } from './shims.js';\n\nexport type BlobPart = string | ArrayBuffer | ArrayBufferView | Blob | DataView;\ntype FsReadStream = AsyncIterable<Uint8Array> & { path: string | { toString(): string } };\n\n// https://github.com/oven-sh/bun/issues/5980\ninterface BunFile extends Blob {\n readonly name?: string | undefined;\n}\n\nexport const checkFileSupport = () => {\n if (typeof File === 'undefined') {\n const { process } = globalThis as any;\n const isOldNode =\n typeof process?.versions?.node === 'string' && parseInt(process.versions.node.split('.')) < 20;\n throw new Error(\n '`File` is not defined as a global, which is required for file uploads.' +\n (isOldNode ?\n \" Update to Node 20 LTS or newer, or set `globalThis.File` to `import('node:buffer').File`.\"\n : ''),\n );\n }\n};\n\n/**\n * Typically, this is a native \"File\" class.\n *\n * We provide the {@link toFile} utility to convert a variety of objects\n * into the File class.\n *\n * For convenience, you can also pass a fetch Response, or in Node,\n * the result of fs.createReadStream().\n */\nexport type Uploadable = File | Response | FsReadStream | BunFile;\n\n/**\n * Construct a `File` instance. This is used to ensure a helpful error is thrown\n * for environments that don't define a global `File` yet.\n */\nexport function makeFile(\n fileBits: BlobPart[],\n fileName: string | undefined,\n options?: FilePropertyBag,\n): File {\n checkFileSupport();\n return new File(fileBits as any, fileName ?? 'unknown_file', options);\n}\n\nexport function getName(value: any): string | undefined {\n return ((\n (typeof value === 'object' &&\n value !== null &&\n (('name' in value && value.name && String(value.name)) ||\n ('url' in value && value.url && String(value.url)) ||\n ('filename' in value && value.filename && String(value.filename)) ||\n ('path' in value && value.path && String(value.path)))) ||\n ''\n )\n .split(/[\\\\/]/)\n .pop() || undefined);\n}\n\nexport const isAsyncIterable = (value: any): value is AsyncIterable<any> =>\n value != null && typeof value === 'object' && typeof value[Symbol.asyncIterator] === 'function';\n\n/**\n * Returns a multipart/form-data request if any part of the given request body contains a File / Blob value.\n * Otherwise returns the request as is.\n */\nexport const maybeMultipartFormRequestOptions = async (\n opts: RequestOptions,\n fetch: BaseGeminiNextGenAPIClient | Fetch,\n): Promise<RequestOptions> => {\n if (!hasUploadableValue(opts.body)) return opts;\n\n return { ...opts, body: await createForm(opts.body, fetch) };\n};\n\ntype MultipartFormRequestOptions = Omit<RequestOptions, 'body'> & { body: unknown };\n\nexport const multipartFormRequestOptions = async (\n opts: MultipartFormRequestOptions,\n fetch: BaseGeminiNextGenAPIClient | Fetch,\n): Promise<RequestOptions> => {\n return { ...opts, body: await createForm(opts.body, fetch) };\n};\n\nconst supportsFormDataMap = /* @__PURE__ */ new WeakMap<Fetch, Promise<boolean>>();\n\n/**\n * node-fetch doesn't support the global FormData object in recent node versions. Instead of sending\n * properly-encoded form data, it just stringifies the object, resulting in a request body of \"[object FormData]\".\n * This function detects if the fetch function provided supports the global FormData object to avoid\n * confusing error messages later on.\n */\nfunction supportsFormData(fetchObject: BaseGeminiNextGenAPIClient | Fetch): Promise<boolean> {\n const fetch: Fetch = typeof fetchObject === 'function' ? fetchObject : (fetchObject as any).fetch;\n const cached = supportsFormDataMap.get(fetch);\n if (cached) return cached;\n const promise = (async () => {\n try {\n const FetchResponse = (\n 'Response' in fetch ?\n fetch.Response\n : (await fetch('data:,')).constructor) as typeof Response;\n const data = new FormData();\n if (data.toString() === (await new FetchResponse(data).text())) {\n return false;\n }\n return true;\n } catch {\n // avoid false negatives\n return true;\n }\n })();\n supportsFormDataMap.set(fetch, promise);\n return promise;\n}\n\nexport const createForm = async <T = Record<string, unknown>>(\n body: T | undefined,\n fetch: BaseGeminiNextGenAPIClient | Fetch,\n): Promise<FormData> => {\n if (!(await supportsFormData(fetch))) {\n throw new TypeError(\n 'The provided fetch function does not support file uploads with the current global FormData class.',\n );\n }\n const form = new FormData();\n await Promise.all(Object.entries(body || {}).map(([key, value]) => addFormValue(form, key, value)));\n return form;\n};\n\n// We check for Blob not File because Bun.File doesn't inherit from File,\n// but they both inherit from Blob and have a `name` property at runtime.\nconst isNamedBlob = (value: unknown): value is Blob => value instanceof Blob && 'name' in value;\n\nconst isUploadable = (value: unknown) =>\n typeof value === 'object' &&\n value !== null &&\n (value instanceof Response || isAsyncIterable(value) || isNamedBlob(value));\n\nconst hasUploadableValue = (value: unknown): boolean => {\n if (isUploadable(value)) return true;\n if (Array.isArray(value)) return value.some(hasUploadableValue);\n if (value && typeof value === 'object') {\n for (const k in value) {\n if (hasUploadableValue((value as any)[k])) return true;\n }\n }\n return false;\n};\n\nconst addFormValue = async (form: FormData, key: string, value: unknown): Promise<void> => {\n if (value === undefined) return;\n if (value == null) {\n throw new TypeError(\n `Received null for \"${key}\"; to pass null in FormData, you must use the string 'null'`,\n );\n }\n\n // TODO: make nested formats configurable\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {\n form.append(key, String(value));\n } else if (value instanceof Response) {\n form.append(key, makeFile([await value.blob()], getName(value)));\n } else if (isAsyncIterable(value)) {\n form.append(key, makeFile([await new Response(ReadableStreamFrom(value)).blob()], getName(value)));\n } else if (isNamedBlob(value)) {\n form.append(key, value, getName(value));\n } else if (Array.isArray(value)) {\n await Promise.all(value.map((entry) => addFormValue(form, key + '[]', entry)));\n } else if (typeof value === 'object') {\n await Promise.all(\n Object.entries(value).map(([name, prop]) => addFormValue(form, `${key}[${name}]`, prop)),\n );\n } else {\n throw new TypeError(\n `Invalid value given to form, expected a string, number, boolean, object, Array, File or Blob but got ${value} instead`,\n );\n }\n};\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { BlobPart, getName, makeFile, isAsyncIterable } from './uploads.js';\nimport type { FilePropertyBag } from './builtin-types.js';\nimport { checkFileSupport } from './uploads.js';\n\nexport type BlobLikePart = string | ArrayBuffer | ArrayBufferView | BlobLike | DataView;\n\n/**\n * Intended to match DOM Blob, node-fetch Blob, node:buffer Blob, etc.\n * Don't add arrayBuffer here, node-fetch doesn't have it\n */\nexport interface BlobLike {\n /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/size) */\n readonly size: number;\n /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/type) */\n readonly type: string;\n /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/text) */\n text(): Promise<string>;\n /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/slice) */\n slice(start?: number, end?: number): BlobLike;\n}\n\n/**\n * This check adds the arrayBuffer() method type because it is available and used at runtime\n */\nconst isBlobLike = (value: any): value is BlobLike & { arrayBuffer(): Promise<ArrayBuffer> } =>\n value != null &&\n typeof value === 'object' &&\n typeof value.size === 'number' &&\n typeof value.type === 'string' &&\n typeof value.text === 'function' &&\n typeof value.slice === 'function' &&\n typeof value.arrayBuffer === 'function';\n\n/**\n * Intended to match DOM File, node:buffer File, undici File, etc.\n */\ninterface FileLike extends BlobLike {\n /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/File/lastModified) */\n readonly lastModified: number;\n /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/File/name) */\n readonly name?: string | undefined;\n}\n\n/**\n * This check adds the arrayBuffer() method type because it is available and used at runtime\n */\nconst isFileLike = (value: any): value is FileLike & { arrayBuffer(): Promise<ArrayBuffer> } =>\n value != null &&\n typeof value === 'object' &&\n typeof value.name === 'string' &&\n typeof value.lastModified === 'number' &&\n isBlobLike(value);\n\n/**\n * Intended to match DOM Response, node-fetch Response, undici Response, etc.\n */\nexport interface ResponseLike {\n url: string;\n blob(): Promise<BlobLike>;\n}\n\nconst isResponseLike = (value: any): value is ResponseLike =>\n value != null &&\n typeof value === 'object' &&\n typeof value.url === 'string' &&\n typeof value.blob === 'function';\n\nexport type ToFileInput =\n | FileLike\n | ResponseLike\n | Exclude<BlobLikePart, string>\n | AsyncIterable<BlobLikePart>;\n\n/**\n * Helper for creating a {@link File} to pass to an SDK upload method from a variety of different data formats\n * @param value the raw content of the file. Can be an {@link Uploadable}, BlobLikePart, or AsyncIterable of BlobLikeParts\n * @param {string=} name the name of the file. If omitted, toFile will try to determine a file name from bits if possible\n * @param {Object=} options additional properties\n * @param {string=} options.type the MIME type of the content\n * @param {number=} options.lastModified the last modified timestamp\n * @returns a {@link File} with the given properties\n */\nexport async function toFile(\n value: ToFileInput | PromiseLike<ToFileInput>,\n name?: string | null | undefined,\n options?: FilePropertyBag | undefined,\n): Promise<File> {\n checkFileSupport();\n\n // If it's a promise, resolve it.\n value = await value;\n\n // If we've been given a `File` we don't need to do anything\n if (isFileLike(value)) {\n if (value instanceof File) {\n return value;\n }\n return makeFile([await value.arrayBuffer()], value.name);\n }\n\n if (isResponseLike(value)) {\n const blob = await value.blob();\n name ||= new URL(value.url).pathname.split(/[\\\\/]/).pop();\n\n return makeFile(await getBytes(blob), name, options);\n }\n\n const parts = await getBytes(value);\n\n name ||= getName(value);\n\n if (!options?.type) {\n const type = parts.find((part) => typeof part === 'object' && 'type' in part && part.type);\n if (typeof type === 'string') {\n options = { ...options, type };\n }\n }\n\n return makeFile(parts, name, options);\n}\n\nasync function getBytes(value: BlobLikePart | AsyncIterable<BlobLikePart>): Promise<Array<BlobPart>> {\n let parts: Array<BlobPart> = [];\n if (\n typeof value === 'string' ||\n ArrayBuffer.isView(value) || // includes Uint8Array, Buffer, etc.\n value instanceof ArrayBuffer\n ) {\n parts.push(value);\n } else if (isBlobLike(value)) {\n parts.push(value instanceof Blob ? value : await value.arrayBuffer());\n } else if (\n isAsyncIterable(value) // includes Readable, ReadableStream, etc.\n ) {\n for await (const chunk of value) {\n parts.push(...(await getBytes(chunk as BlobLikePart))); // TODO, consider validating?\n }\n } else {\n const constructor = value?.constructor?.name;\n throw new Error(\n `Unexpected data type: ${typeof value}${\n constructor ? `; constructor: ${constructor}` : ''\n }${propsForError(value)}`,\n );\n }\n\n return parts;\n}\n\nfunction propsForError(value: unknown): string {\n if (typeof value !== 'object' || value === null) return '';\n const props = Object.getOwnPropertyNames(value);\n return `; props: [${props.map((p) => `\"${p}\"`).join(', ')}]`;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nimport { BaseGeminiNextGenAPIClient } from '../client.js';\n\nexport abstract class APIResource {\n /**\n * The key path from the client. For example, a resource accessible as `client.resource.subresource` would\n * have a property `static override readonly _key = Object.freeze(['resource', 'subresource'] as const);`.\n */\n static readonly _key: readonly string[] = [];\n protected _client: BaseGeminiNextGenAPIClient;\n\n constructor(client: BaseGeminiNextGenAPIClient) {\n this._client = client;\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { GeminiNextGenAPIClientError } from '../../core/error.js';\n\n/**\n * Percent-encode everything that isn't safe to have in a path without encoding safe chars.\n *\n * Taken from https://datatracker.ietf.org/doc/html/rfc3986#section-3.3:\n * > unreserved = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n * > sub-delims = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\" / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n * > pchar = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n */\nexport function encodeURIPath(str: string) {\n return str.replace(/[^A-Za-z0-9\\-._~!$&'()*+,;=:@]+/g, encodeURIComponent);\n}\n\nconst EMPTY = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.create(null));\n\nexport const createPathTagFunction = (pathEncoder = encodeURIPath) =>\n (function path(statics: readonly string[], ...params: readonly unknown[]): string {\n // If there are no params, no processing is needed.\n if (statics.length === 1) return statics[0]!;\n\n let postPath = false;\n const invalidSegments = [];\n const path = statics.reduce((previousValue, currentValue, index) => {\n if (/[?#]/.test(currentValue)) {\n postPath = true;\n }\n const value = params[index];\n let encoded = (postPath ? encodeURIComponent : pathEncoder)('' + value);\n if (\n index !== params.length &&\n (value == null ||\n (typeof value === 'object' &&\n // handle values from other realms\n value.toString ===\n Object.getPrototypeOf(Object.getPrototypeOf((value as any).hasOwnProperty ?? EMPTY) ?? EMPTY)\n ?.toString))\n ) {\n encoded = value + '';\n invalidSegments.push({\n start: previousValue.length + currentValue.length,\n length: encoded.length,\n error: `Value of type ${Object.prototype.toString\n .call(value)\n .slice(8, -1)} is not a valid path parameter`,\n });\n }\n return previousValue + currentValue + (index === params.length ? '' : encoded);\n }, '');\n\n const pathOnly = path.split(/[?#]/, 1)[0]!;\n const invalidSegmentPattern = /(?<=^|\\/)(?:\\.|%2e){1,2}(?=\\/|$)/gi;\n let match;\n\n // Find all invalid segments\n while ((match = invalidSegmentPattern.exec(pathOnly)) !== null) {\n invalidSegments.push({\n start: match.index,\n length: match[0].length,\n error: `Value \"${match[0]}\" can\\'t be safely passed as a path parameter`,\n });\n }\n\n invalidSegments.sort((a, b) => a.start - b.start);\n\n if (invalidSegments.length > 0) {\n let lastEnd = 0;\n const underline = invalidSegments.reduce((acc, segment) => {\n const spaces = ' '.repeat(segment.start - lastEnd);\n const arrows = '^'.repeat(segment.length);\n lastEnd = segment.start + segment.length;\n return acc + spaces + arrows;\n }, '');\n\n throw new GeminiNextGenAPIClientError(\n `Path parameters result in path with invalid segments:\\n${invalidSegments\n .map((e) => e.error)\n .join('\\n')}\\n${path}\\n${underline}`,\n );\n }\n\n return path;\n });\n\n/**\n * URI-encodes path params and ensures no unsafe /./ or /../ path segments are introduced.\n */\nexport const path = /* @__PURE__ */ createPathTagFunction(encodeURIPath);\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nimport { APIResource } from '../core/resource.js';\nimport * as Errors from '../core/error.js';\nimport * as InteractionsAPI from './interactions.js';\nimport { APIPromise } from '../core/api-promise.js';\nimport { Stream } from '../core/streaming.js';\nimport { RequestOptions } from '../internal/request-options.js';\nimport { path } from '../internal/utils/path.js';\n\nexport class BaseInteractions extends APIResource {\n static override readonly _key: readonly ['interactions'] = Object.freeze(['interactions'] as const);\n\n /**\n * Creates a new interaction.\n *\n * @example\n * ```ts\n * const interaction = await client.interactions.create({\n * api_version: 'api_version',\n * input: 'string',\n * model: 'gemini-2.5-flash',\n * });\n * ```\n */\n create(params: CreateModelInteractionParamsNonStreaming, options?: RequestOptions): APIPromise<Interaction>;\n create(\n params: CreateModelInteractionParamsStreaming,\n options?: RequestOptions,\n ): APIPromise<Stream<InteractionSSEEvent>>;\n create(params: CreateAgentInteractionParamsNonStreaming, options?: RequestOptions): APIPromise<Interaction>;\n create(\n params: CreateAgentInteractionParamsStreaming,\n options?: RequestOptions,\n ): APIPromise<Stream<InteractionSSEEvent>>;\n create(\n params: BaseCreateModelInteractionParams | BaseCreateAgentInteractionParams,\n options?: RequestOptions,\n ): APIPromise<Stream<InteractionSSEEvent> | Interaction>;\n create(\n params: InteractionCreateParams,\n options?: RequestOptions,\n ): APIPromise<Interaction> | APIPromise<Stream<InteractionSSEEvent>> {\n const { api_version = this._client.apiVersion, ...body } = params;\n if ('model' in body && 'agent_config' in body) {\n throw new Errors.GeminiNextGenAPIClientError(\n `Invalid request: specified \\`model\\` and \\`agent_config\\`. If specifying \\`model\\`, use \\`generation_config\\`.`,\n );\n }\n if ('agent' in body && 'generation_config' in body) {\n throw new Errors.GeminiNextGenAPIClientError(\n `Invalid request: specified \\`agent\\` and \\`generation_config\\`. If specifying \\`agent\\`, use \\`agent_config\\`.`,\n );\n }\n return this._client.post(path`/${api_version}/interactions`, {\n body,\n ...options,\n stream: params.stream ?? false,\n }) as APIPromise<Interaction> | APIPromise<Stream<InteractionSSEEvent>>;\n }\n\n /**\n * Deletes the interaction by id.\n *\n * @example\n * ```ts\n * const interaction = await client.interactions.delete('id', {\n * api_version: 'api_version',\n * });\n * ```\n */\n delete(\n id: string,\n params: InteractionDeleteParams | null | undefined = {},\n options?: RequestOptions,\n ): APIPromise<unknown> {\n const { api_version = this._client.apiVersion } = params ?? {};\n return this._client.delete(path`/${api_version}/interactions/${id}`, options);\n }\n\n /**\n * Cancels an interaction by id. This only applies to background interactions that are still running.\n *\n * @example\n * ```ts\n * const interaction = await client.interactions.cancel('id', {\n * api_version: 'api_version',\n * });\n * ```\n */\n cancel(\n id: string,\n params: InteractionCancelParams | null | undefined = {},\n options?: RequestOptions,\n ): APIPromise<Interaction> {\n const { api_version = this._client.apiVersion } = params ?? {};\n return this._client.post(path`/${api_version}/interactions/${id}/cancel`, options);\n }\n\n /**\n * Retrieves the full details of a single interaction based on its `Interaction.id`.\n *\n * @example\n * ```ts\n * const interaction = await client.interactions.get('id', {\n * api_version: 'api_version',\n * });\n * ```\n */\n get(\n id: string,\n params?: InteractionGetParamsNonStreaming,\n options?: RequestOptions,\n ): APIPromise<Interaction>;\n get(\n id: string,\n params: InteractionGetParamsStreaming,\n options?: RequestOptions,\n ): APIPromise<Stream<InteractionSSEEvent>>;\n get(\n id: string,\n params?: InteractionGetParamsBase | undefined,\n options?: RequestOptions,\n ): APIPromise<Stream<InteractionSSEEvent> | Interaction>;\n get(\n id: string,\n params: InteractionGetParams | undefined = {},\n options?: RequestOptions,\n ): APIPromise<Interaction> | APIPromise<Stream<InteractionSSEEvent>> {\n const { api_version = this._client.apiVersion, ...query } = params ?? {};\n return this._client.get(path`/${api_version}/interactions/${id}`, {\n query,\n ...options,\n stream: params?.stream ?? false,\n }) as APIPromise<Interaction> | APIPromise<Stream<InteractionSSEEvent>>;\n }\n}\nexport class Interactions extends BaseInteractions {}\n\n/**\n * The configuration for allowed tools.\n */\nexport interface AllowedTools {\n /**\n * The mode of the tool choice.\n */\n mode?: ToolChoiceType;\n\n /**\n * The names of the allowed tools.\n */\n tools?: Array<string>;\n}\n\n/**\n * Citation information for model-generated content.\n */\nexport interface Annotation {\n /**\n * End of the attributed segment, exclusive.\n */\n end_index?: number;\n\n /**\n * Source attributed for a portion of the text. Could be a URL, title, or\n * other identifier.\n */\n source?: string;\n\n /**\n * Start of segment of the response that is attributed to this source.\n *\n * Index indicates the start of the segment, measured in bytes.\n */\n start_index?: number;\n}\n\n/**\n * An audio content block.\n */\nexport interface AudioContent {\n type: 'audio';\n\n /**\n * The audio content.\n */\n data?: string;\n\n /**\n * The mime type of the audio.\n */\n mime_type?: AudioMimeType;\n\n /**\n * The URI of the audio.\n */\n uri?: string;\n}\n\n/**\n * The mime type of the audio.\n */\nexport type AudioMimeType =\n | 'audio/wav'\n | 'audio/mp3'\n | 'audio/aiff'\n | 'audio/aac'\n | 'audio/ogg'\n | 'audio/flac'\n | (string & {});\n\n/**\n * The arguments to pass to the code execution.\n */\nexport interface CodeExecutionCallArguments {\n /**\n * The code to be executed.\n */\n code?: string;\n\n /**\n * Programming language of the `code`.\n */\n language?: 'python';\n}\n\n/**\n * Code execution content.\n */\nexport interface CodeExecutionCallContent {\n type: 'code_execution_call';\n\n /**\n * A unique ID for this specific tool call.\n */\n id?: string;\n\n /**\n * The arguments to pass to the code execution.\n */\n arguments?: CodeExecutionCallArguments;\n}\n\n/**\n * Code execution result content.\n */\nexport interface CodeExecutionResultContent {\n type: 'code_execution_result';\n\n /**\n * ID to match the ID from the code execution call block.\n */\n call_id?: string;\n\n /**\n * Whether the code execution resulted in an error.\n */\n is_error?: boolean;\n\n /**\n * The output of the code execution.\n */\n result?: string;\n\n /**\n * A signature hash for backend validation.\n */\n signature?: string;\n}\n\n/**\n * The content of the response.\n */\nexport type Content =\n | TextContent\n | ImageContent\n | AudioContent\n | DocumentContent\n | VideoContent\n | ThoughtContent\n | FunctionCallContent\n | FunctionResultContent\n | CodeExecutionCallContent\n | CodeExecutionResultContent\n | URLContextCallContent\n | URLContextResultContent\n | GoogleSearchCallContent\n | GoogleSearchResultContent\n | MCPServerToolCallContent\n | MCPServerToolResultContent\n | FileSearchCallContent\n | FileSearchResultContent;\n\nexport interface ContentDelta {\n delta?:\n | ContentDelta.TextDelta\n | ContentDelta.ImageDelta\n | ContentDelta.AudioDelta\n | ContentDelta.DocumentDelta\n | ContentDelta.VideoDelta\n | ContentDelta.ThoughtSummaryDelta\n | ContentDelta.ThoughtSignatureDelta\n | ContentDelta.FunctionCallDelta\n | ContentDelta.FunctionResultDelta\n | ContentDelta.CodeExecutionCallDelta\n | ContentDelta.CodeExecutionResultDelta\n | ContentDelta.URLContextCallDelta\n | ContentDelta.URLContextResultDelta\n | ContentDelta.GoogleSearchCallDelta\n | ContentDelta.GoogleSearchResultDelta\n | ContentDelta.MCPServerToolCallDelta\n | ContentDelta.MCPServerToolResultDelta\n | ContentDelta.FileSearchCallDelta\n | ContentDelta.FileSearchResultDelta;\n\n /**\n * The event_id token to be used to resume the interaction stream, from this event.\n */\n event_id?: string;\n\n event_type?: 'content.delta';\n\n index?: number;\n}\n\nexport namespace ContentDelta {\n export interface TextDelta {\n type: 'text';\n\n /**\n * Citation information for model-generated content.\n */\n annotations?: Array<InteractionsAPI.Annotation>;\n\n text?: string;\n }\n\n export interface ImageDelta {\n type: 'image';\n\n data?: string;\n\n /**\n * The mime type of the image.\n */\n mime_type?: InteractionsAPI.ImageMimeType;\n\n /**\n * The resolution of the media.\n */\n resolution?: 'low' | 'medium' | 'high' | 'ultra_high';\n\n uri?: string;\n }\n\n export interface AudioDelta {\n type: 'audio';\n\n data?: string;\n\n /**\n * The mime type of the audio.\n */\n mime_type?: InteractionsAPI.AudioMimeType;\n\n uri?: string;\n }\n\n export interface DocumentDelta {\n type: 'document';\n\n data?: string;\n\n /**\n * The mime type of the document.\n */\n mime_type?: InteractionsAPI.DocumentMimeType;\n\n uri?: string;\n }\n\n export interface VideoDelta {\n type: 'video';\n\n data?: string;\n\n /**\n * The mime type of the video.\n */\n mime_type?: InteractionsAPI.VideoMimeType;\n\n /**\n * The resolution of the media.\n */\n resolution?: 'low' | 'medium' | 'high' | 'ultra_high';\n\n uri?: string;\n }\n\n export interface ThoughtSummaryDelta {\n type: 'thought_summary';\n\n /**\n * A text content block.\n */\n content?: InteractionsAPI.TextContent | InteractionsAPI.ImageContent;\n }\n\n export interface ThoughtSignatureDelta {\n type: 'thought_signature';\n\n /**\n * Signature to match the backend source to be part of the generation.\n */\n signature?: string;\n }\n\n export interface FunctionCallDelta {\n type: 'function_call';\n\n /**\n * A unique ID for this specific tool call.\n */\n id?: string;\n\n arguments?: { [key: string]: unknown };\n\n name?: string;\n }\n\n export interface FunctionResultDelta {\n type: 'function_result';\n\n /**\n * ID to match the ID from the function call block.\n */\n call_id?: string;\n\n is_error?: boolean;\n\n name?: string;\n\n /**\n * Tool call result delta.\n */\n result?: FunctionResultDelta.Items | unknown | string;\n }\n\n export namespace FunctionResultDelta {\n export interface Items {\n items?: Array<InteractionsAPI.TextContent | InteractionsAPI.ImageContent>;\n }\n }\n\n export interface CodeExecutionCallDelta {\n type: 'code_execution_call';\n\n /**\n * A unique ID for this specific tool call.\n */\n id?: string;\n\n /**\n * The arguments to pass to the code execution.\n */\n arguments?: InteractionsAPI.CodeExecutionCallArguments;\n }\n\n export interface CodeExecutionResultDelta {\n type: 'code_execution_result';\n\n /**\n * ID to match the ID from the function call block.\n */\n call_id?: string;\n\n is_error?: boolean;\n\n result?: string;\n\n signature?: string;\n }\n\n export interface URLContextCallDelta {\n type: 'url_context_call';\n\n /**\n * A unique ID for this specific tool call.\n */\n id?: string;\n\n /**\n * The arguments to pass to the URL context.\n */\n arguments?: InteractionsAPI.URLContextCallArguments;\n }\n\n export interface URLContextResultDelta {\n type: 'url_context_result';\n\n /**\n * ID to match the ID from the function call block.\n */\n call_id?: string;\n\n is_error?: boolean;\n\n result?: Array<InteractionsAPI.URLContextResult>;\n\n signature?: string;\n }\n\n export interface GoogleSearchCallDelta {\n type: 'google_search_call';\n\n /**\n * A unique ID for this specific tool call.\n */\n id?: string;\n\n /**\n * The arguments to pass to Google Search.\n */\n arguments?: InteractionsAPI.GoogleSearchCallArguments;\n }\n\n export interface GoogleSearchResultDelta {\n type: 'google_search_result';\n\n /**\n * ID to match the ID from the function call block.\n */\n call_id?: string;\n\n is_error?: boolean;\n\n result?: Array<InteractionsAPI.GoogleSearchResult>;\n\n signature?: string;\n }\n\n export interface MCPServerToolCallDelta {\n type: 'mcp_server_tool_call';\n\n /**\n * A unique ID for this specific tool call.\n */\n id?: string;\n\n arguments?: { [key: string]: unknown };\n\n name?: string;\n\n server_name?: string;\n }\n\n export interface MCPServerToolResultDelta {\n type: 'mcp_server_tool_result';\n\n /**\n * ID to match the ID from the function call block.\n */\n call_id?: string;\n\n name?: string;\n\n /**\n * Tool call result delta.\n */\n result?: MCPServerToolResultDelta.Items | unknown | string;\n\n server_name?: string;\n }\n\n export namespace MCPServerToolResultDelta {\n export interface Items {\n items?: Array<InteractionsAPI.TextContent | InteractionsAPI.ImageContent>;\n }\n }\n\n export interface FileSearchCallDelta {\n type: 'file_search_call';\n\n /**\n * A unique ID for this specific tool call.\n */\n id?: string;\n }\n\n export interface FileSearchResultDelta {\n type: 'file_search_result';\n\n result?: Array<FileSearchResultDelta.Result>;\n }\n\n export namespace FileSearchResultDelta {\n /**\n * The result of the File Search.\n */\n export interface Result {\n /**\n * The name of the file search store.\n */\n file_search_store?: string;\n\n /**\n * The text of the search result.\n */\n text?: string;\n\n /**\n * The title of the search result.\n */\n title?: string;\n }\n }\n}\n\nexport interface ContentStart {\n /**\n * The content of the response.\n */\n content?: Content;\n\n /**\n * The event_id token to be used to resume the interaction stream, from this event.\n */\n event_id?: string;\n\n event_type?: 'content.start';\n\n index?: number;\n}\n\nexport interface ContentStop {\n /**\n * The event_id token to be used to resume the interaction stream, from this event.\n */\n event_id?: string;\n\n event_type?: 'content.stop';\n\n index?: number;\n}\n\n/**\n * Configuration for the Deep Research agent.\n */\nexport interface DeepResearchAgentConfig {\n /**\n * Whether to include thought summaries in the response.\n */\n thinking_summaries?: 'auto' | 'none';\n\n type?: 'deep-research';\n}\n\n/**\n * A document content block.\n */\nexport interface DocumentContent {\n type: 'document';\n\n /**\n * The document content.\n */\n data?: string;\n\n /**\n * The mime type of the document.\n */\n mime_type?: DocumentMimeType;\n\n /**\n * The URI of the document.\n */\n uri?: string;\n}\n\n/**\n * The mime type of the document.\n */\nexport type DocumentMimeType = (string & {}) | 'application/pdf';\n\n/**\n * Configuration for dynamic agents.\n */\nexport interface DynamicAgentConfig {\n type?: 'dynamic';\n\n [k: string]: unknown;\n}\n\nexport interface ErrorEvent {\n /**\n * Error message from an interaction.\n */\n error?: ErrorEvent.Error;\n\n /**\n * The event_id token to be used to resume the interaction stream, from this event.\n */\n event_id?: string;\n\n event_type?: 'error';\n}\n\nexport namespace ErrorEvent {\n /**\n * Error message from an interaction.\n */\n export interface Error {\n /**\n * A URI that identifies the error type.\n */\n code?: string;\n\n /**\n * A human-readable error message.\n */\n message?: string;\n }\n}\n\n/**\n * File Search content.\n */\nexport interface FileSearchCallContent {\n type: 'file_search_call';\n\n /**\n * A unique ID for this specific tool call.\n */\n id?: string;\n}\n\n/**\n * File Search result content.\n */\nexport interface FileSearchResultContent {\n type: 'file_search_result';\n\n /**\n * The results of the File Search.\n */\n result?: Array<FileSearchResultContent.Result>;\n}\n\nexport namespace FileSearchResultContent {\n /**\n * The result of the File Search.\n */\n export interface Result {\n /**\n * The name of the file search store.\n */\n file_search_store?: string;\n\n /**\n * The text of the search result.\n */\n text?: string;\n\n /**\n * The title of the search result.\n */\n title?: string;\n }\n}\n\n/**\n * A tool that can be used by the model.\n */\nexport interface Function {\n type: 'function';\n\n /**\n * A description of the function.\n */\n description?: string;\n\n /**\n * The name of the function.\n */\n name?: string;\n\n /**\n * The JSON Schema for the function's parameters.\n */\n parameters?: unknown;\n}\n\n/**\n * A function tool call content block.\n */\nexport interface FunctionCallContent {\n /**\n * A unique ID for this specific tool call.\n */\n id: string;\n\n /**\n * The arguments to pass to the function.\n */\n arguments: { [key: string]: unknown };\n\n /**\n * The name of the tool to call.\n */\n name: string;\n\n type: 'function_call';\n}\n\n/**\n * A function tool result content block.\n */\nexport interface FunctionResultContent {\n /**\n * ID to match the ID from the function call block.\n */\n call_id: string;\n\n /**\n * The result of the tool call.\n */\n result: FunctionResultContent.Items | unknown | string;\n\n type: 'function_result';\n\n /**\n * Whether the tool call resulted in an error.\n */\n is_error?: boolean;\n\n /**\n * The name of the tool that was called.\n */\n name?: string;\n}\n\nexport namespace FunctionResultContent {\n export interface Items {\n items?: Array<InteractionsAPI.TextContent | InteractionsAPI.ImageContent>;\n }\n}\n\n/**\n * Configuration parameters for model interactions.\n */\nexport interface GenerationConfig {\n /**\n * Configuration for image interaction.\n */\n image_config?: ImageConfig;\n\n /**\n * The maximum number of tokens to include in the response.\n */\n max_output_tokens?: number;\n\n /**\n * Seed used in decoding for reproducibility.\n */\n seed?: number;\n\n /**\n * Configuration for speech interaction.\n */\n speech_config?: Array<SpeechConfig>;\n\n /**\n * A list of character sequences that will stop output interaction.\n */\n stop_sequences?: Array<string>;\n\n /**\n * Controls the randomness of the output.\n */\n temperature?: number;\n\n /**\n * The level of thought tokens that the model should generate.\n */\n thinking_level?: ThinkingLevel;\n\n /**\n * Whether to include thought summaries in the response.\n */\n thinking_summaries?: 'auto' | 'none';\n\n /**\n * The tool choice for the interaction.\n */\n tool_choice?: ToolChoice;\n\n /**\n * The maximum cumulative probability of tokens to consider when sampling.\n */\n top_p?: number;\n}\n\n/**\n * The arguments to pass to Google Search.\n */\nexport interface GoogleSearchCallArguments {\n /**\n * Web search queries for the following-up web search.\n */\n queries?: Array<string>;\n}\n\n/**\n * Google Search content.\n */\nexport interface GoogleSearchCallContent {\n type: 'google_search_call';\n\n /**\n * A unique ID for this specific tool call.\n */\n id?: string;\n\n /**\n * The arguments to pass to Google Search.\n */\n arguments?: GoogleSearchCallArguments;\n}\n\n/**\n * The result of the Google Search.\n */\nexport interface GoogleSearchResult {\n /**\n * Web content snippet that can be embedded in a web page or an app webview.\n */\n rendered_content?: string;\n\n /**\n * Title of the search result.\n */\n title?: string;\n\n /**\n * URI reference of the search result.\n */\n url?: string;\n}\n\n/**\n * Google Search result content.\n */\nexport interface GoogleSearchResultContent {\n type: 'google_search_result';\n\n /**\n * ID to match the ID from the google search call block.\n */\n call_id?: string;\n\n /**\n * Whether the Google Search resulted in an error.\n */\n is_error?: boolean;\n\n /**\n * The results of the Google Search.\n */\n result?: Array<GoogleSearchResult>;\n\n /**\n * The signature of the Google Search result.\n */\n signature?: string;\n}\n\n/**\n * The configuration for image interaction.\n */\nexport interface ImageConfig {\n aspect_ratio?: '1:1' | '2:3' | '3:2' | '3:4' | '4:3' | '4:5' | '5:4' | '9:16' | '16:9' | '21:9';\n\n image_size?: '1K' | '2K' | '4K';\n}\n\n/**\n * An image content block.\n */\nexport interface ImageContent {\n type: 'image';\n\n /**\n * The image content.\n */\n data?: string;\n\n /**\n * The mime type of the image.\n */\n mime_type?: ImageMimeType;\n\n /**\n * The resolution of the media.\n */\n resolution?: 'low' | 'medium' | 'high' | 'ultra_high';\n\n /**\n * The URI of the image.\n */\n uri?: string;\n}\n\n/**\n * The mime type of the image.\n */\nexport type ImageMimeType =\n | 'image/png'\n | 'image/jpeg'\n | 'image/webp'\n | 'image/heic'\n | 'image/heif'\n | (string & {});\n\n/**\n * The Interaction resource.\n */\nexport interface Interaction {\n /**\n * Output only. A unique identifier for the interaction completion.\n */\n id: string;\n\n /**\n * Output only. The status of the interaction.\n */\n status: 'in_progress' | 'requires_action' | 'completed' | 'failed' | 'cancelled' | 'incomplete';\n\n /**\n * The name of the `Agent` used for generating the interaction.\n */\n agent?: (string & {}) | 'deep-research-pro-preview-12-2025';\n\n /**\n * Output only. The time at which the response was created in ISO 8601 format\n * (YYYY-MM-DDThh:mm:ssZ).\n */\n created?: string;\n\n /**\n * The name of the `Model` used for generating the interaction.\n */\n model?: Model;\n\n /**\n * Output only. Responses from the model.\n */\n outputs?: Array<Content>;\n\n /**\n * The ID of the previous interaction, if any.\n */\n previous_interaction_id?: string;\n\n /**\n * Output only. The role of the interaction.\n */\n role?: string;\n\n /**\n * Output only. The time at which the response was last updated in ISO 8601 format\n * (YYYY-MM-DDThh:mm:ssZ).\n */\n updated?: string;\n\n /**\n * Output only. Statistics on the interaction request's token usage.\n */\n usage?: Usage;\n}\n\nexport interface InteractionCompleteEvent {\n /**\n * The event_id token to be used to resume the interaction stream, from this event.\n */\n event_id?: string;\n\n event_type?: 'interaction.complete';\n\n /**\n * The Interaction resource.\n */\n interaction?: Interaction;\n}\n\nexport type InteractionSSEEvent =\n | InteractionStartEvent\n | InteractionCompleteEvent\n | InteractionStatusUpdate\n | ContentStart\n | ContentDelta\n | ContentStop\n | ErrorEvent;\n\nexport interface InteractionStartEvent {\n /**\n * The event_id token to be used to resume the interaction stream, from this event.\n */\n event_id?: string;\n\n event_type?: 'interaction.start';\n\n /**\n * The Interaction resource.\n */\n interaction?: Interaction;\n}\n\nexport interface InteractionStatusUpdate {\n /**\n * The event_id token to be used to resume the interaction stream, from this event.\n */\n event_id?: string;\n\n event_type?: 'interaction.status_update';\n\n interaction_id?: string;\n\n status?: 'in_progress' | 'requires_action' | 'completed' | 'failed' | 'cancelled' | 'incomplete';\n}\n\n/**\n * MCPServer tool call content.\n */\nexport interface MCPServerToolCallContent {\n /**\n * A unique ID for this specific tool call.\n */\n id: string;\n\n /**\n * The JSON object of arguments for the function.\n */\n arguments: { [key: string]: unknown };\n\n /**\n * The name of the tool which was called.\n */\n name: string;\n\n /**\n * The name of the used MCP server.\n */\n server_name: string;\n\n type: 'mcp_server_tool_call';\n}\n\n/**\n * MCPServer tool result content.\n */\nexport interface MCPServerToolResultContent {\n /**\n * ID to match the ID from the MCP server tool call block.\n */\n call_id: string;\n\n /**\n * The result of the tool call.\n */\n result: MCPServerToolResultContent.Items | unknown | string;\n\n type: 'mcp_server_tool_result';\n\n /**\n * Name of the tool which is called for this specific tool call.\n */\n name?: string;\n\n /**\n * The name of the used MCP server.\n */\n server_name?: string;\n}\n\nexport namespace MCPServerToolResultContent {\n export interface Items {\n items?: Array<InteractionsAPI.TextContent | InteractionsAPI.ImageContent>;\n }\n}\n\n/**\n * The model that will complete your prompt.\\n\\nSee [models](https://ai.google.dev/gemini-api/docs/models) for additional details.\n */\nexport type Model =\n | 'gemini-2.5-flash'\n | 'gemini-2.5-flash-image'\n | 'gemini-2.5-flash-lite'\n | 'gemini-2.5-flash-lite-preview-09-2025'\n | 'gemini-2.5-flash-native-audio-preview-12-2025'\n | 'gemini-2.5-flash-preview-09-2025'\n | 'gemini-2.5-flash-preview-tts'\n | 'gemini-2.5-pro'\n | 'gemini-2.5-pro-preview-tts'\n | 'gemini-3-flash-preview'\n | 'gemini-3-pro-image-preview'\n | 'gemini-3-pro-preview'\n | (string & {});\n\n/**\n * The configuration for speech interaction.\n */\nexport interface SpeechConfig {\n /**\n * The language of the speech.\n */\n language?: string;\n\n /**\n * The speaker's name, it should match the speaker name given in the prompt.\n */\n speaker?: string;\n\n /**\n * The voice of the speaker.\n */\n voice?: string;\n}\n\n/**\n * A text content block.\n */\nexport interface TextContent {\n type: 'text';\n\n /**\n * Citation information for model-generated content.\n */\n annotations?: Array<Annotation>;\n\n /**\n * The text content.\n */\n text?: string;\n}\n\nexport type ThinkingLevel = 'minimal' | 'low' | 'medium' | 'high';\n\n/**\n * A thought content block.\n */\nexport interface ThoughtContent {\n type: 'thought';\n\n /**\n * Signature to match the backend source to be part of the generation.\n */\n signature?: string;\n\n /**\n * A summary of the thought.\n */\n summary?: Array<TextContent | ImageContent>;\n}\n\n/**\n * A tool that can be used by the model.\n */\nexport type Tool =\n | Function\n | Tool.GoogleSearch\n | Tool.CodeExecution\n | Tool.URLContext\n | Tool.ComputerUse\n | Tool.MCPServer\n | Tool.FileSearch;\n\nexport namespace Tool {\n /**\n * A tool that can be used by the model to search Google.\n */\n export interface GoogleSearch {\n type: 'google_search';\n }\n\n /**\n * A tool that can be used by the model to execute code.\n */\n export interface CodeExecution {\n type: 'code_execution';\n }\n\n /**\n * A tool that can be used by the model to fetch URL context.\n */\n export interface URLContext {\n type: 'url_context';\n }\n\n /**\n * A tool that can be used by the model to interact with the computer.\n */\n export interface ComputerUse {\n type: 'computer_use';\n\n /**\n * The environment being operated.\n */\n environment?: 'browser';\n\n /**\n * The list of predefined functions that are excluded from the model call.\n */\n excludedPredefinedFunctions?: Array<string>;\n }\n\n /**\n * A MCPServer is a server that can be called by the model to perform actions.\n */\n export interface MCPServer {\n type: 'mcp_server';\n\n /**\n * The allowed tools.\n */\n allowed_tools?: Array<InteractionsAPI.AllowedTools>;\n\n /**\n * Optional: Fields for authentication headers, timeouts, etc., if needed.\n */\n headers?: { [key: string]: string };\n\n /**\n * The name of the MCPServer.\n */\n name?: string;\n\n /**\n * The full URL for the MCPServer endpoint.\n * Example: \"https://api.example.com/mcp\"\n */\n url?: string;\n }\n\n /**\n * A tool that can be used by the model to search files.\n */\n export interface FileSearch {\n type: 'file_search';\n\n /**\n * The file search store names to search.\n */\n file_search_store_names?: Array<string>;\n\n /**\n * Metadata filter to apply to the semantic retrieval documents and chunks.\n */\n metadata_filter?: string;\n\n /**\n * The number of semantic retrieval chunks to retrieve.\n */\n top_k?: number;\n }\n}\n\n/**\n * The configuration for tool choice.\n */\nexport type ToolChoice = ToolChoiceType | ToolChoiceConfig;\n\nexport interface ToolChoiceConfig {\n /**\n * The configuration for allowed tools.\n */\n allowed_tools?: AllowedTools;\n}\n\nexport type ToolChoiceType = 'auto' | 'any' | 'none' | 'validated';\n\nexport interface Turn {\n /**\n * The content of the turn.\n */\n content?: string | Array<Content>;\n\n /**\n * The originator of this turn. Must be user for input or model for\n * model output.\n */\n role?: string;\n}\n\n/**\n * The arguments to pass to the URL context.\n */\nexport interface URLContextCallArguments {\n /**\n * The URLs to fetch.\n */\n urls?: Array<string>;\n}\n\n/**\n * URL context content.\n */\nexport interface URLContextCallContent {\n type: 'url_context_call';\n\n /**\n * A unique ID for this specific tool call.\n */\n id?: string;\n\n /**\n * The arguments to pass to the URL context.\n */\n arguments?: URLContextCallArguments;\n}\n\n/**\n * The result of the URL context.\n */\nexport interface URLContextResult {\n /**\n * The status of the URL retrieval.\n */\n status?: 'success' | 'error' | 'paywall' | 'unsafe';\n\n /**\n * The URL that was fetched.\n */\n url?: string;\n}\n\n/**\n * URL context result content.\n */\nexport interface URLContextResultContent {\n type: 'url_context_result';\n\n /**\n * ID to match the ID from the url context call block.\n */\n call_id?: string;\n\n /**\n * Whether the URL context resulted in an error.\n */\n is_error?: boolean;\n\n /**\n * The results of the URL context.\n */\n result?: Array<URLContextResult>;\n\n /**\n * The signature of the URL context result.\n */\n signature?: string;\n}\n\n/**\n * Statistics on the interaction request's token usage.\n */\nexport interface Usage {\n /**\n * A breakdown of cached token usage by modality.\n */\n cached_tokens_by_modality?: Array<Usage.CachedTokensByModality>;\n\n /**\n * A breakdown of input token usage by modality.\n */\n input_tokens_by_modality?: Array<Usage.InputTokensByModality>;\n\n /**\n * A breakdown of output token usage by modality.\n */\n output_tokens_by_modality?: Array<Usage.OutputTokensByModality>;\n\n /**\n * A breakdown of tool-use token usage by modality.\n */\n tool_use_tokens_by_modality?: Array<Usage.ToolUseTokensByModality>;\n\n /**\n * Number of tokens in the cached part of the prompt (the cached content).\n */\n total_cached_tokens?: number;\n\n /**\n * Number of tokens in the prompt (context).\n */\n total_input_tokens?: number;\n\n /**\n * Total number of tokens across all the generated responses.\n */\n total_output_tokens?: number;\n\n /**\n * Number of tokens of thoughts for thinking models.\n */\n total_thought_tokens?: number;\n\n /**\n * Total token count for the interaction request (prompt + responses + other\n * internal tokens).\n */\n total_tokens?: number;\n\n /**\n * Number of tokens present in tool-use prompt(s).\n */\n total_tool_use_tokens?: number;\n}\n\nexport namespace Usage {\n /**\n * The token count for a single response modality.\n */\n export interface CachedTokensByModality {\n /**\n * The modality associated with the token count.\n */\n modality?: 'text' | 'image' | 'audio';\n\n /**\n * Number of tokens for the modality.\n */\n tokens?: number;\n }\n\n /**\n * The token count for a single response modality.\n */\n export interface InputTokensByModality {\n /**\n * The modality associated with the token count.\n */\n modality?: 'text' | 'image' | 'audio';\n\n /**\n * Number of tokens for the modality.\n */\n tokens?: number;\n }\n\n /**\n * The token count for a single response modality.\n */\n export interface OutputTokensByModality {\n /**\n * The modality associated with the token count.\n */\n modality?: 'text' | 'image' | 'audio';\n\n /**\n * Number of tokens for the modality.\n */\n tokens?: number;\n }\n\n /**\n * The token count for a single response modality.\n */\n export interface ToolUseTokensByModality {\n /**\n * The modality associated with the token count.\n */\n modality?: 'text' | 'image' | 'audio';\n\n /**\n * Number of tokens for the modality.\n */\n tokens?: number;\n }\n}\n\n/**\n * A video content block.\n */\nexport interface VideoContent {\n type: 'video';\n\n /**\n * The video content.\n */\n data?: string;\n\n /**\n * The mime type of the video.\n */\n mime_type?: VideoMimeType;\n\n /**\n * The resolution of the media.\n */\n resolution?: 'low' | 'medium' | 'high' | 'ultra_high';\n\n /**\n * The URI of the video.\n */\n uri?: string;\n}\n\n/**\n * The mime type of the video.\n */\nexport type VideoMimeType =\n | 'video/mp4'\n | 'video/mpeg'\n | 'video/mov'\n | 'video/avi'\n | 'video/x-flv'\n | 'video/mpg'\n | 'video/webm'\n | 'video/wmv'\n | 'video/3gpp'\n | (string & {});\n\nexport type InteractionDeleteResponse = unknown;\n\nexport type InteractionCreateParams =\n | CreateModelInteractionParamsNonStreaming\n | CreateModelInteractionParamsStreaming\n | CreateAgentInteractionParamsNonStreaming\n | CreateAgentInteractionParamsStreaming;\n\nexport interface BaseCreateModelInteractionParams {\n /**\n * Path param: Which version of the API to use.\n */\n api_version?: string;\n\n /**\n * Body param: The inputs for the interaction.\n */\n input:\n | string\n | Array<Content>\n | Array<Turn>\n | TextContent\n | ImageContent\n | AudioContent\n | DocumentContent\n | VideoContent\n | ThoughtContent\n | FunctionCallContent\n | FunctionResultContent\n | CodeExecutionCallContent\n | CodeExecutionResultContent\n | URLContextCallContent\n | URLContextResultContent\n | GoogleSearchCallContent\n | GoogleSearchResultContent\n | MCPServerToolCallContent\n | MCPServerToolResultContent\n | FileSearchCallContent\n | FileSearchResultContent;\n\n /**\n * Body param: The name of the `Model` used for generating the interaction.\n */\n model: Model;\n\n /**\n * Body param: Input only. Whether to run the model interaction in the background.\n */\n background?: boolean;\n\n /**\n * Body param: Input only. Configuration parameters for the model interaction.\n */\n generation_config?: GenerationConfig;\n\n /**\n * Body param: The ID of the previous interaction, if any.\n */\n previous_interaction_id?: string;\n\n /**\n * Body param: Enforces that the generated response is a JSON object that complies with\n * the JSON schema specified in this field.\n */\n response_format?: unknown;\n\n /**\n * Body param: The mime type of the response. This is required if response_format is set.\n */\n response_mime_type?: string;\n\n /**\n * Body param: The requested modalities of the response (TEXT, IMAGE, AUDIO).\n */\n response_modalities?: Array<'text' | 'image' | 'audio'>;\n\n /**\n * Body param: Input only. Whether to store the response and request for later retrieval.\n */\n store?: boolean;\n\n /**\n * Body param: Input only. Whether the interaction will be streamed.\n */\n stream?: boolean;\n\n /**\n * Body param: System instruction for the interaction.\n */\n system_instruction?: string;\n\n /**\n * Body param: A list of tool declarations the model may call during interaction.\n */\n tools?: Array<Tool>;\n}\n\nexport interface BaseCreateAgentInteractionParams {\n /**\n * Path param: Which version of the API to use.\n */\n api_version?: string;\n\n /**\n * Body param: The name of the `Agent` used for generating the interaction.\n */\n agent: (string & {}) | 'deep-research-pro-preview-12-2025';\n\n /**\n * Body param: The inputs for the interaction.\n */\n input:\n | string\n | Array<Content>\n | Array<Turn>\n | TextContent\n | ImageContent\n | AudioContent\n | DocumentContent\n | VideoContent\n | ThoughtContent\n | FunctionCallContent\n | FunctionResultContent\n | CodeExecutionCallContent\n | CodeExecutionResultContent\n | URLContextCallContent\n | URLContextResultContent\n | GoogleSearchCallContent\n | GoogleSearchResultContent\n | MCPServerToolCallContent\n | MCPServerToolResultContent\n | FileSearchCallContent\n | FileSearchResultContent;\n\n /**\n * Body param: Configuration for the agent.\n */\n agent_config?: DynamicAgentConfig | DeepResearchAgentConfig;\n\n /**\n * Body param: Input only. Whether to run the model interaction in the background.\n */\n background?: boolean;\n\n /**\n * Body param: The ID of the previous interaction, if any.\n */\n previous_interaction_id?: string;\n\n /**\n * Body param: Enforces that the generated response is a JSON object that complies with\n * the JSON schema specified in this field.\n */\n response_format?: unknown;\n\n /**\n * Body param: The mime type of the response. This is required if response_format is set.\n */\n response_mime_type?: string;\n\n /**\n * Body param: The requested modalities of the response (TEXT, IMAGE, AUDIO).\n */\n response_modalities?: Array<'text' | 'image' | 'audio'>;\n\n /**\n * Body param: Input only. Whether to store the response and request for later retrieval.\n */\n store?: boolean;\n\n /**\n * Body param: Input only. Whether the interaction will be streamed.\n */\n stream?: boolean;\n\n /**\n * Body param: System instruction for the interaction.\n */\n system_instruction?: string;\n\n /**\n * Body param: A list of tool declarations the model may call during interaction.\n */\n tools?: Array<Tool>;\n}\n\nexport interface CreateModelInteractionParamsNonStreaming extends BaseCreateModelInteractionParams {\n /**\n * Body param: Input only. Whether the interaction will be streamed.\n */\n stream?: false;\n}\n\nexport interface CreateModelInteractionParamsStreaming extends BaseCreateModelInteractionParams {\n /**\n * Body param: Input only. Whether the interaction will be streamed.\n */\n stream: true;\n}\n\nexport interface CreateAgentInteractionParamsNonStreaming extends BaseCreateAgentInteractionParams {\n /**\n * Body param: Input only. Whether the interaction will be streamed.\n */\n stream?: false;\n}\n\nexport interface CreateAgentInteractionParamsStreaming extends BaseCreateAgentInteractionParams {\n /**\n * Body param: Input only. Whether the interaction will be streamed.\n */\n stream: true;\n}\n\nexport interface InteractionDeleteParams {\n /**\n * Which version of the API to use.\n */\n api_version?: string;\n}\n\nexport interface InteractionCancelParams {\n /**\n * Which version of the API to use.\n */\n api_version?: string;\n}\n\nexport type InteractionGetParams = InteractionGetParamsNonStreaming | InteractionGetParamsStreaming;\n\nexport interface InteractionGetParamsBase {\n /**\n * Path param: Which version of the API to use.\n */\n api_version?: string;\n\n /**\n * Query param: If set to true, includes the input in the response.\n */\n include_input?: boolean;\n\n /**\n * Query param: Optional. If set, resumes the interaction stream from the next chunk after the event marked by the event id. Can only be used if `stream` is true.\n */\n last_event_id?: string;\n\n /**\n * Query param: If set to true, the generated content will be streamed incrementally.\n */\n stream?: boolean;\n}\n\nexport namespace InteractionGetParams {\n export type InteractionGetParamsNonStreaming = InteractionsAPI.InteractionGetParamsNonStreaming;\n export type InteractionGetParamsStreaming = InteractionsAPI.InteractionGetParamsStreaming;\n}\n\nexport interface InteractionGetParamsNonStreaming extends InteractionGetParamsBase {\n /**\n * Query param: If set to true, the generated content will be streamed incrementally.\n */\n stream?: false;\n}\n\nexport interface InteractionGetParamsStreaming extends InteractionGetParamsBase {\n /**\n * Query param: If set to true, the generated content will be streamed incrementally.\n */\n stream: true;\n}\n\nexport declare namespace Interactions {\n export {\n type AllowedTools as AllowedTools,\n type Annotation as Annotation,\n type AudioContent as AudioContent,\n type AudioMimeType as AudioMimeType,\n type CodeExecutionCallArguments as CodeExecutionCallArguments,\n type CodeExecutionCallContent as CodeExecutionCallContent,\n type CodeExecutionResultContent as CodeExecutionResultContent,\n type Content as Content,\n type ContentDelta as ContentDelta,\n type ContentStart as ContentStart,\n type ContentStop as ContentStop,\n type DeepResearchAgentConfig as DeepResearchAgentConfig,\n type DocumentContent as DocumentContent,\n type DocumentMimeType as DocumentMimeType,\n type DynamicAgentConfig as DynamicAgentConfig,\n type ErrorEvent as ErrorEvent,\n type FileSearchCallContent as FileSearchCallContent,\n type FileSearchResultContent as FileSearchResultContent,\n type Function as Function,\n type FunctionCallContent as FunctionCallContent,\n type FunctionResultContent as FunctionResultContent,\n type GenerationConfig as GenerationConfig,\n type GoogleSearchCallArguments as GoogleSearchCallArguments,\n type GoogleSearchCallContent as GoogleSearchCallContent,\n type GoogleSearchResult as GoogleSearchResult,\n type GoogleSearchResultContent as GoogleSearchResultContent,\n type ImageConfig as ImageConfig,\n type ImageContent as ImageContent,\n type ImageMimeType as ImageMimeType,\n type Interaction as Interaction,\n type InteractionCompleteEvent as InteractionCompleteEvent,\n type InteractionSSEEvent as InteractionSSEEvent,\n type InteractionStartEvent as InteractionStartEvent,\n type InteractionStatusUpdate as InteractionStatusUpdate,\n type MCPServerToolCallContent as MCPServerToolCallContent,\n type MCPServerToolResultContent as MCPServerToolResultContent,\n type Model as Model,\n type SpeechConfig as SpeechConfig,\n type TextContent as TextContent,\n type ThinkingLevel as ThinkingLevel,\n type ThoughtContent as ThoughtContent,\n type Tool as Tool,\n type ToolChoice as ToolChoice,\n type ToolChoiceConfig as ToolChoiceConfig,\n type ToolChoiceType as ToolChoiceType,\n type Turn as Turn,\n type URLContextCallArguments as URLContextCallArguments,\n type URLContextCallContent as URLContextCallContent,\n type URLContextResult as URLContextResult,\n type URLContextResultContent as URLContextResultContent,\n type Usage as Usage,\n type VideoContent as VideoContent,\n type VideoMimeType as VideoMimeType,\n type InteractionDeleteResponse as InteractionDeleteResponse,\n type InteractionCreateParams as InteractionCreateParams,\n type CreateModelInteractionParamsNonStreaming as CreateModelInteractionParamsNonStreaming,\n type CreateModelInteractionParamsStreaming as CreateModelInteractionParamsStreaming,\n type CreateAgentInteractionParamsNonStreaming as CreateAgentInteractionParamsNonStreaming,\n type CreateAgentInteractionParamsStreaming as CreateAgentInteractionParamsStreaming,\n type InteractionDeleteParams as InteractionDeleteParams,\n type InteractionCancelParams as InteractionCancelParams,\n type InteractionGetParams as InteractionGetParams,\n type InteractionGetParamsNonStreaming as InteractionGetParamsNonStreaming,\n type InteractionGetParamsStreaming as InteractionGetParamsStreaming,\n };\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nexport function concatBytes(buffers: Uint8Array[]): Uint8Array {\n let length = 0;\n for (const buffer of buffers) {\n length += buffer.length;\n }\n const output = new Uint8Array(length);\n let index = 0;\n for (const buffer of buffers) {\n output.set(buffer, index);\n index += buffer.length;\n }\n\n return output;\n}\n\nlet encodeUTF8_: (str: string) => Uint8Array;\nexport function encodeUTF8(str: string) {\n let encoder;\n return (\n encodeUTF8_ ??\n ((encoder = new (globalThis as any).TextEncoder()), (encodeUTF8_ = encoder.encode.bind(encoder)))\n )(str);\n}\n\nlet decodeUTF8_: (bytes: Uint8Array) => string;\nexport function decodeUTF8(bytes: Uint8Array) {\n let decoder;\n return (\n decodeUTF8_ ??\n ((decoder = new (globalThis as any).TextDecoder()), (decodeUTF8_ = decoder.decode.bind(decoder)))\n )(bytes);\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { concatBytes, decodeUTF8, encodeUTF8 } from '../utils/bytes.js';\n\nexport type Bytes = string | ArrayBuffer | Uint8Array | null | undefined;\n\n/**\n * A re-implementation of httpx's `LineDecoder` in Python that handles incrementally\n * reading lines from text.\n *\n * https://github.com/encode/httpx/blob/920333ea98118e9cf617f246905d7b202510941c/httpx/_decoders.py#L258\n */\nexport class LineDecoder {\n // prettier-ignore\n static NEWLINE_CHARS = new Set(['\\n', '\\r']);\n static NEWLINE_REGEXP = /\\r\\n|[\\n\\r]/g;\n\n private buffer: Uint8Array;\n private carriageReturnIndex: number | null;\n\n constructor() {\n this.buffer = new Uint8Array();\n this.carriageReturnIndex = null;\n }\n\n decode(chunk: Bytes): string[] {\n if (chunk == null) {\n return [];\n }\n\n const binaryChunk =\n chunk instanceof ArrayBuffer ? new Uint8Array(chunk)\n : typeof chunk === 'string' ? encodeUTF8(chunk)\n : chunk;\n\n this.buffer = concatBytes([this.buffer, binaryChunk]);\n\n const lines: string[] = [];\n let patternIndex;\n while ((patternIndex = findNewlineIndex(this.buffer, this.carriageReturnIndex)) != null) {\n if (patternIndex.carriage && this.carriageReturnIndex == null) {\n // skip until we either get a corresponding `\\n`, a new `\\r` or nothing\n this.carriageReturnIndex = patternIndex.index;\n continue;\n }\n\n // we got double \\r or \\rtext\\n\n if (\n this.carriageReturnIndex != null &&\n (patternIndex.index !== this.carriageReturnIndex + 1 || patternIndex.carriage)\n ) {\n lines.push(decodeUTF8(this.buffer.subarray(0, this.carriageReturnIndex - 1)));\n this.buffer = this.buffer.subarray(this.carriageReturnIndex);\n this.carriageReturnIndex = null;\n continue;\n }\n\n const endIndex =\n this.carriageReturnIndex !== null ? patternIndex.preceding - 1 : patternIndex.preceding;\n\n const line = decodeUTF8(this.buffer.subarray(0, endIndex));\n lines.push(line);\n\n this.buffer = this.buffer.subarray(patternIndex.index);\n this.carriageReturnIndex = null;\n }\n\n return lines;\n }\n\n flush(): string[] {\n if (!this.buffer.length) {\n return [];\n }\n return this.decode('\\n');\n }\n}\n\n/**\n * This function searches the buffer for the end patterns, (\\r or \\n)\n * and returns an object with the index preceding the matched newline and the\n * index after the newline char. `null` is returned if no new line is found.\n *\n * ```ts\n * findNewLineIndex('abc\\ndef') -> { preceding: 2, index: 3 }\n * ```\n */\nfunction findNewlineIndex(\n buffer: Uint8Array,\n startIndex: number | null,\n): { preceding: number; index: number; carriage: boolean } | null {\n const newline = 0x0a; // \\n\n const carriage = 0x0d; // \\r\n\n for (let i = startIndex ?? 0; i < buffer.length; i++) {\n if (buffer[i] === newline) {\n return { preceding: i, index: i + 1, carriage: false };\n }\n\n if (buffer[i] === carriage) {\n return { preceding: i, index: i + 1, carriage: true };\n }\n }\n\n return null;\n}\n\nexport function findDoubleNewlineIndex(buffer: Uint8Array): number {\n // This function searches the buffer for the end patterns (\\r\\r, \\n\\n, \\r\\n\\r\\n)\n // and returns the index right after the first occurrence of any pattern,\n // or -1 if none of the patterns are found.\n const newline = 0x0a; // \\n\n const carriage = 0x0d; // \\r\n\n for (let i = 0; i < buffer.length - 1; i++) {\n if (buffer[i] === newline && buffer[i + 1] === newline) {\n // \\n\\n\n return i + 2;\n }\n if (buffer[i] === carriage && buffer[i + 1] === carriage) {\n // \\r\\r\n return i + 2;\n }\n if (\n buffer[i] === carriage &&\n buffer[i + 1] === newline &&\n i + 3 < buffer.length &&\n buffer[i + 2] === carriage &&\n buffer[i + 3] === newline\n ) {\n // \\r\\n\\r\\n\n return i + 4;\n }\n }\n\n return -1;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nimport { hasOwn } from './values.js';\nimport { type BaseGeminiNextGenAPIClient } from '../../client.js';\nimport { RequestOptions } from '../request-options.js';\n\ntype LogFn = (message: string, ...rest: unknown[]) => void;\nexport type Logger = {\n error: LogFn;\n warn: LogFn;\n info: LogFn;\n debug: LogFn;\n};\nexport type LogLevel = 'off' | 'error' | 'warn' | 'info' | 'debug';\n\nconst levelNumbers = {\n off: 0,\n error: 200,\n warn: 300,\n info: 400,\n debug: 500,\n};\n\nexport const parseLogLevel = (\n maybeLevel: string | undefined,\n sourceName: string,\n client: BaseGeminiNextGenAPIClient,\n): LogLevel | undefined => {\n if (!maybeLevel) {\n return undefined;\n }\n if (hasOwn(levelNumbers, maybeLevel)) {\n return maybeLevel;\n }\n loggerFor(client).warn(\n `${sourceName} was set to ${JSON.stringify(maybeLevel)}, expected one of ${JSON.stringify(\n Object.keys(levelNumbers),\n )}`,\n );\n return undefined;\n};\n\nfunction noop() {}\n\nfunction makeLogFn(fnLevel: keyof Logger, logger: Logger | undefined, logLevel: LogLevel) {\n if (!logger || levelNumbers[fnLevel] > levelNumbers[logLevel]) {\n return noop;\n } else {\n // Don't wrap logger functions, we want the stacktrace intact!\n return logger[fnLevel].bind(logger);\n }\n}\n\nconst noopLogger = {\n error: noop,\n warn: noop,\n info: noop,\n debug: noop,\n};\n\nlet cachedLoggers = /* @__PURE__ */ new WeakMap<Logger, [LogLevel, Logger]>();\n\nexport function loggerFor(client: BaseGeminiNextGenAPIClient): Logger {\n const logger = client.logger;\n const logLevel = client.logLevel ?? 'off';\n if (!logger) {\n return noopLogger;\n }\n\n const cachedLogger = cachedLoggers.get(logger);\n if (cachedLogger && cachedLogger[0] === logLevel) {\n return cachedLogger[1];\n }\n\n const levelLogger = {\n error: makeLogFn('error', logger, logLevel),\n warn: makeLogFn('warn', logger, logLevel),\n info: makeLogFn('info', logger, logLevel),\n debug: makeLogFn('debug', logger, logLevel),\n };\n\n cachedLoggers.set(logger, [logLevel, levelLogger]);\n\n return levelLogger;\n}\n\nexport const formatRequestDetails = (details: {\n options?: RequestOptions | undefined;\n headers?: Headers | Record<string, string> | undefined;\n retryOfRequestLogID?: string | undefined;\n retryOf?: string | undefined;\n url?: string | undefined;\n status?: number | undefined;\n method?: string | undefined;\n durationMs?: number | undefined;\n message?: unknown;\n body?: unknown;\n}) => {\n if (details.options) {\n details.options = { ...details.options };\n delete details.options['headers']; // redundant + leaks internals\n }\n if (details.headers) {\n details.headers = Object.fromEntries(\n (details.headers instanceof Headers ? [...details.headers] : Object.entries(details.headers)).map(\n ([name, value]) => [\n name,\n (\n name.toLowerCase() === 'x-goog-api-key' ||\n name.toLowerCase() === 'authorization' ||\n name.toLowerCase() === 'cookie' ||\n name.toLowerCase() === 'set-cookie'\n ) ?\n '***'\n : value,\n ],\n ),\n );\n }\n if ('retryOfRequestLogID' in details) {\n if (details.retryOfRequestLogID) {\n details.retryOf = details.retryOfRequestLogID;\n }\n delete details.retryOfRequestLogID;\n }\n return details;\n};\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { GeminiNextGenAPIClientError } from './error.js';\nimport { type ReadableStream } from '../internal/shim-types.js';\nimport { makeReadableStream } from '../internal/shims.js';\nimport { findDoubleNewlineIndex, LineDecoder } from '../internal/decoders/line.js';\nimport { ReadableStreamToAsyncIterable } from '../internal/shims.js';\nimport { isAbortError } from '../internal/errors.js';\nimport { encodeUTF8 } from '../internal/utils/bytes.js';\nimport { loggerFor } from '../internal/utils/log.js';\nimport type { BaseGeminiNextGenAPIClient } from '../client.js';\n\ntype Bytes = string | ArrayBuffer | Uint8Array | null | undefined;\n\nexport type ServerSentEvent = {\n event: string | null;\n data: string;\n raw: string[];\n};\n\nexport class Stream<Item> implements AsyncIterable<Item> {\n controller: AbortController;\n private client: BaseGeminiNextGenAPIClient | undefined;\n\n constructor(\n private iterator: () => AsyncIterator<Item>,\n controller: AbortController,\n client?: BaseGeminiNextGenAPIClient,\n ) {\n this.controller = controller;\n this.client = client;\n }\n\n static fromSSEResponse<Item>(\n response: Response,\n controller: AbortController,\n client?: BaseGeminiNextGenAPIClient,\n ): Stream<Item> {\n let consumed = false;\n const logger = client ? loggerFor(client) : console;\n\n async function* iterator(): AsyncIterator<Item, any, undefined> {\n if (consumed) {\n throw new GeminiNextGenAPIClientError(\n 'Cannot iterate over a consumed stream, use `.tee()` to split the stream.',\n );\n }\n consumed = true;\n let done = false;\n try {\n for await (const sse of _iterSSEMessages(response, controller)) {\n if (done) continue;\n\n if (sse.data.startsWith('[DONE]')) {\n done = true;\n continue;\n } else {\n try {\n // @ts-ignore\n yield JSON.parse(sse.data);\n } catch (e) {\n logger.error(`Could not parse message into JSON:`, sse.data);\n logger.error(`From chunk:`, sse.raw);\n throw e;\n }\n }\n }\n done = true;\n } catch (e) {\n // If the user calls `stream.controller.abort()`, we should exit without throwing.\n if (isAbortError(e)) return;\n throw e;\n } finally {\n // If the user `break`s, abort the ongoing request.\n if (!done) controller.abort();\n }\n }\n\n return new Stream(iterator, controller, client);\n }\n\n /**\n * Generates a Stream from a newline-separated ReadableStream\n * where each item is a JSON value.\n */\n static fromReadableStream<Item>(\n readableStream: ReadableStream,\n controller: AbortController,\n client?: BaseGeminiNextGenAPIClient,\n ): Stream<Item> {\n let consumed = false;\n\n async function* iterLines(): AsyncGenerator<string, void, unknown> {\n const lineDecoder = new LineDecoder();\n\n const iter = ReadableStreamToAsyncIterable<Bytes>(readableStream);\n for await (const chunk of iter) {\n for (const line of lineDecoder.decode(chunk)) {\n yield line;\n }\n }\n\n for (const line of lineDecoder.flush()) {\n yield line;\n }\n }\n\n async function* iterator(): AsyncIterator<Item, any, undefined> {\n if (consumed) {\n throw new GeminiNextGenAPIClientError(\n 'Cannot iterate over a consumed stream, use `.tee()` to split the stream.',\n );\n }\n consumed = true;\n let done = false;\n try {\n for await (const line of iterLines()) {\n if (done) continue;\n // @ts-ignore\n if (line) yield JSON.parse(line);\n }\n done = true;\n } catch (e) {\n // If the user calls `stream.controller.abort()`, we should exit without throwing.\n if (isAbortError(e)) return;\n throw e;\n } finally {\n // If the user `break`s, abort the ongoing request.\n if (!done) controller.abort();\n }\n }\n\n return new Stream(iterator, controller, client);\n }\n\n [Symbol.asyncIterator](): AsyncIterator<Item> {\n return this.iterator();\n }\n\n /**\n * Splits the stream into two streams which can be\n * independently read from at different speeds.\n */\n tee(): [Stream<Item>, Stream<Item>] {\n const left: Array<Promise<IteratorResult<Item>>> = [];\n const right: Array<Promise<IteratorResult<Item>>> = [];\n const iterator = this.iterator();\n\n const teeIterator = (queue: Array<Promise<IteratorResult<Item>>>): AsyncIterator<Item> => {\n return {\n next: () => {\n if (queue.length === 0) {\n const result = iterator.next();\n left.push(result);\n right.push(result);\n }\n return queue.shift()!;\n },\n };\n };\n\n return [\n new Stream(() => teeIterator(left), this.controller, this.client),\n new Stream(() => teeIterator(right), this.controller, this.client),\n ];\n }\n\n /**\n * Converts this stream to a newline-separated ReadableStream of\n * JSON stringified values in the stream\n * which can be turned back into a Stream with `Stream.fromReadableStream()`.\n */\n toReadableStream(): ReadableStream {\n const self = this;\n let iter: AsyncIterator<Item>;\n\n return makeReadableStream({\n async start() {\n iter = self[Symbol.asyncIterator]();\n },\n async pull(ctrl: any) {\n try {\n const { value, done } = await iter.next();\n if (done) return ctrl.close();\n\n const bytes = encodeUTF8(JSON.stringify(value) + '\\n');\n\n ctrl.enqueue(bytes);\n } catch (err) {\n ctrl.error(err);\n }\n },\n async cancel() {\n await iter.return?.();\n },\n });\n }\n}\n\nexport async function* _iterSSEMessages(\n response: Response,\n controller: AbortController,\n): AsyncGenerator<ServerSentEvent, void, unknown> {\n if (!response.body) {\n controller.abort();\n if (\n typeof (globalThis as any).navigator !== 'undefined' &&\n (globalThis as any).navigator.product === 'ReactNative'\n ) {\n throw new GeminiNextGenAPIClientError(\n `The default react-native fetch implementation does not support streaming. Please use expo/fetch: https://docs.expo.dev/versions/latest/sdk/expo/#expofetch-api`,\n );\n }\n throw new GeminiNextGenAPIClientError(`Attempted to iterate over a response with no body`);\n }\n\n const sseDecoder = new SSEDecoder();\n const lineDecoder = new LineDecoder();\n\n const iter = ReadableStreamToAsyncIterable<Bytes>(response.body);\n for await (const sseChunk of iterSSEChunks(iter)) {\n for (const line of lineDecoder.decode(sseChunk)) {\n const sse = sseDecoder.decode(line);\n if (sse) yield sse;\n }\n }\n\n for (const line of lineDecoder.flush()) {\n const sse = sseDecoder.decode(line);\n if (sse) yield sse;\n }\n}\n\n/**\n * Given an async iterable iterator, iterates over it and yields full\n * SSE chunks, i.e. yields when a double new-line is encountered.\n */\nasync function* iterSSEChunks(iterator: AsyncIterableIterator<Bytes>): AsyncGenerator<Uint8Array> {\n let data = new Uint8Array();\n\n for await (const chunk of iterator) {\n if (chunk == null) {\n continue;\n }\n\n const binaryChunk =\n chunk instanceof ArrayBuffer ? new Uint8Array(chunk)\n : typeof chunk === 'string' ? encodeUTF8(chunk)\n : chunk;\n\n let newData = new Uint8Array(data.length + binaryChunk.length);\n newData.set(data);\n newData.set(binaryChunk, data.length);\n data = newData;\n\n let patternIndex;\n while ((patternIndex = findDoubleNewlineIndex(data)) !== -1) {\n yield data.slice(0, patternIndex);\n data = data.slice(patternIndex);\n }\n }\n\n if (data.length > 0) {\n yield data;\n }\n}\n\nclass SSEDecoder {\n private data: string[];\n private event: string | null;\n private chunks: string[];\n\n constructor() {\n this.event = null;\n this.data = [];\n this.chunks = [];\n }\n\n decode(line: string) {\n if (line.endsWith('\\r')) {\n line = line.substring(0, line.length - 1);\n }\n\n if (!line) {\n // empty line and we didn't previously encounter any messages\n if (!this.event && !this.data.length) return null;\n\n const sse: ServerSentEvent = {\n event: this.event,\n data: this.data.join('\\n'),\n raw: this.chunks,\n };\n\n this.event = null;\n this.data = [];\n this.chunks = [];\n\n return sse;\n }\n\n this.chunks.push(line);\n\n if (line.startsWith(':')) {\n return null;\n }\n\n let [fieldname, _, value] = partition(line, ':');\n\n if (value.startsWith(' ')) {\n value = value.substring(1);\n }\n\n if (fieldname === 'event') {\n this.event = value;\n } else if (fieldname === 'data') {\n this.data.push(value);\n }\n\n return null;\n }\n}\n\nfunction partition(str: string, delimiter: string): [string, string, string] {\n const index = str.indexOf(delimiter);\n if (index !== -1) {\n return [str.substring(0, index), delimiter, str.substring(index + delimiter.length)];\n }\n\n return [str, '', ''];\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nimport type { FinalRequestOptions } from './request-options.js';\nimport { Stream } from '../core/streaming.js';\nimport { type BaseGeminiNextGenAPIClient } from '../client.js';\nimport { formatRequestDetails, loggerFor } from './utils/log.js';\n\nexport type APIResponseProps = {\n response: Response;\n options: FinalRequestOptions;\n controller: AbortController;\n requestLogID: string;\n retryOfRequestLogID: string | undefined;\n startTime: number;\n};\n\nexport async function defaultParseResponse<T>(\n client: BaseGeminiNextGenAPIClient,\n props: APIResponseProps,\n): Promise<T> {\n const { response, requestLogID, retryOfRequestLogID, startTime } = props;\n const body = await (async () => {\n if (props.options.stream) {\n loggerFor(client).debug('response', response.status, response.url, response.headers, response.body);\n\n // Note: there is an invariant here that isn't represented in the type system\n // that if you set `stream: true` the response type must also be `Stream<T>`\n\n if (props.options.__streamClass) {\n return props.options.__streamClass.fromSSEResponse(response, props.controller, client) as any;\n }\n\n return Stream.fromSSEResponse(response, props.controller, client) as any;\n }\n\n // fetch refuses to read the body when the status code is 204.\n if (response.status === 204) {\n return null as T;\n }\n\n if (props.options.__binaryResponse) {\n return response as unknown as T;\n }\n\n const contentType = response.headers.get('content-type');\n const mediaType = contentType?.split(';')[0]?.trim();\n const isJSON = mediaType?.includes('application/json') || mediaType?.endsWith('+json');\n if (isJSON) {\n const contentLength = response.headers.get('content-length');\n if (contentLength === '0') {\n // if there is no content we can't do anything\n return undefined as T;\n }\n\n const json = await response.json();\n return json as T;\n }\n\n const text = await response.text();\n return text as unknown as T;\n })();\n loggerFor(client).debug(\n `[${requestLogID}] response parsed`,\n formatRequestDetails({\n retryOfRequestLogID,\n url: response.url,\n status: response.status,\n body,\n durationMs: Date.now() - startTime,\n }),\n );\n return body;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nimport { type BaseGeminiNextGenAPIClient } from '../client.js';\n\nimport { type PromiseOrValue } from '../internal/types.js';\nimport { APIResponseProps, defaultParseResponse } from '../internal/parse.js';\n\n/**\n * A subclass of `Promise` providing additional helper methods\n * for interacting with the SDK.\n */\nexport class APIPromise<T> extends Promise<T> {\n private parsedPromise: Promise<T> | undefined;\n private client: BaseGeminiNextGenAPIClient;\n\n constructor(\n client: BaseGeminiNextGenAPIClient,\n private responsePromise: Promise<APIResponseProps>,\n private parseResponse: (\n client: BaseGeminiNextGenAPIClient,\n props: APIResponseProps,\n ) => PromiseOrValue<T> = defaultParseResponse,\n ) {\n super((resolve) => {\n // this is maybe a bit weird but this has to be a no-op to not implicitly\n // parse the response body; instead .then, .catch, .finally are overridden\n // to parse the response\n resolve(null as any);\n });\n this.client = client;\n }\n\n _thenUnwrap<U>(transform: (data: T, props: APIResponseProps) => U): APIPromise<U> {\n return new APIPromise(this.client, this.responsePromise, async (client, props) =>\n transform(await this.parseResponse(client, props), props),\n );\n }\n\n /**\n * Gets the raw `Response` instance instead of parsing the response\n * data.\n *\n * If you want to parse the response body but still get the `Response`\n * instance, you can use {@link withResponse()}.\n *\n * 👋 Getting the wrong TypeScript type for `Response`?\n * Try setting `\"moduleResolution\": \"NodeNext\"` or add `\"lib\": [\"DOM\"]`\n * to your `tsconfig.json`.\n */\n asResponse(): Promise<Response> {\n return this.responsePromise.then((p) => p.response);\n }\n\n /**\n * Gets the parsed response data and the raw `Response` instance.\n *\n * If you just want to get the raw `Response` instance without parsing it,\n * you can use {@link asResponse()}.\n *\n * 👋 Getting the wrong TypeScript type for `Response`?\n * Try setting `\"moduleResolution\": \"NodeNext\"` or add `\"lib\": [\"DOM\"]`\n * to your `tsconfig.json`.\n */\n async withResponse(): Promise<{ data: T; response: Response }> {\n const [data, response] = await Promise.all([this.parse(), this.asResponse()]);\n return { data, response };\n }\n\n private parse(): Promise<T> {\n if (!this.parsedPromise) {\n this.parsedPromise = this.responsePromise.then((data) => this.parseResponse(this.client, data));\n }\n return this.parsedPromise;\n }\n\n override then<TResult1 = T, TResult2 = never>(\n onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null,\n onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null,\n ): Promise<TResult1 | TResult2> {\n return this.parse().then(onfulfilled, onrejected);\n }\n\n override catch<TResult = never>(\n onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null,\n ): Promise<T | TResult> {\n return this.parse().catch(onrejected);\n }\n\n override finally(onfinally?: (() => void) | undefined | null): Promise<T> {\n return this.parse().finally(onfinally);\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nimport { isReadonlyArray } from './utils/values.js';\n\ntype HeaderValue = string | undefined | null;\nexport type HeadersLike =\n | Headers\n | readonly HeaderValue[][]\n | Record<string, HeaderValue | readonly HeaderValue[]>\n | undefined\n | null\n | NullableHeaders;\n\nconst brand_privateNullableHeaders = /* @__PURE__ */ Symbol('brand.privateNullableHeaders');\n\n/**\n * @internal\n * Users can pass explicit nulls to unset default headers. When we parse them\n * into a standard headers type we need to preserve that information.\n */\nexport type NullableHeaders = {\n /** Brand check, prevent users from creating a NullableHeaders. */\n [brand_privateNullableHeaders]: true;\n /** Parsed headers. */\n values: Headers;\n /** Set of lowercase header names explicitly set to null. */\n nulls: Set<string>;\n};\n\nfunction* iterateHeaders(headers: HeadersLike): IterableIterator<readonly [string, string | null]> {\n if (!headers) return;\n\n if (brand_privateNullableHeaders in headers) {\n const { values, nulls } = headers;\n yield* values.entries();\n for (const name of nulls) {\n yield [name, null];\n }\n return;\n }\n\n let shouldClear = false;\n let iter: Iterable<readonly (HeaderValue | readonly HeaderValue[])[]>;\n if (headers instanceof Headers) {\n iter = headers.entries();\n } else if (isReadonlyArray(headers)) {\n iter = headers;\n } else {\n shouldClear = true;\n iter = Object.entries(headers ?? {});\n }\n for (let row of iter) {\n const name = row[0];\n if (typeof name !== 'string') throw new TypeError('expected header name to be a string');\n const values = isReadonlyArray(row[1]) ? row[1] : [row[1]];\n let didClear = false;\n for (const value of values) {\n if (value === undefined) continue;\n\n // Objects keys always overwrite older headers, they never append.\n // Yield a null to clear the header before adding the new values.\n if (shouldClear && !didClear) {\n didClear = true;\n yield [name, null];\n }\n yield [name, value];\n }\n }\n}\n\nexport const buildHeaders = (newHeaders: HeadersLike[]): NullableHeaders => {\n const targetHeaders = new Headers();\n const nullHeaders = new Set<string>();\n for (const headers of newHeaders) {\n const seenHeaders = new Set<string>();\n for (const [name, value] of iterateHeaders(headers)) {\n const lowerName = name.toLowerCase();\n if (!seenHeaders.has(lowerName)) {\n targetHeaders.delete(name);\n seenHeaders.add(lowerName);\n }\n if (value === null) {\n targetHeaders.delete(name);\n nullHeaders.add(lowerName);\n } else {\n targetHeaders.append(name, value);\n nullHeaders.delete(lowerName);\n }\n }\n }\n return { [brand_privateNullableHeaders]: true, values: targetHeaders, nulls: nullHeaders };\n};\n\nexport const isEmptyHeaders = (headers: HeadersLike) => {\n for (const _ of iterateHeaders(headers)) return false;\n return true;\n};\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\n/**\n * Read an environment variable.\n *\n * Trims beginning and trailing whitespace.\n *\n * Will return undefined if the environment variable doesn't exist or cannot be accessed.\n */\nexport const readEnv = (env: string): string | undefined => {\n if (typeof (globalThis as any).process !== 'undefined') {\n return (globalThis as any).process.env?.[env]?.trim() ?? undefined;\n }\n if (typeof (globalThis as any).Deno !== 'undefined') {\n return (globalThis as any).Deno.env?.get?.(env)?.trim();\n }\n return undefined;\n};\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nimport type { RequestInit, RequestInfo, BodyInit } from './internal/builtin-types.js';\nimport type { HTTPMethod, PromiseOrValue, MergedRequestInit, FinalizedRequestInit } from './internal/types.js';\nimport { uuid4 } from './internal/utils/uuid.js';\nimport { validatePositiveInteger, isAbsoluteURL, safeJSON } from './internal/utils/values.js';\nimport { sleep } from './internal/utils/sleep.js';\nexport type { Logger, LogLevel } from './internal/utils/log.js';\nimport { castToError, isAbortError } from './internal/errors.js';\nimport type { APIResponseProps } from './internal/parse.js';\nimport { getPlatformHeaders } from './internal/detect-platform.js';\nimport * as Shims from './internal/shims.js';\nimport * as Opts from './internal/request-options.js';\nimport { VERSION } from './version.js';\nimport * as Errors from './core/error.js';\nimport * as Uploads from './core/uploads.js';\nimport * as API from './resources/index.js';\nimport { APIPromise } from './core/api-promise.js';\nimport {\n AllowedTools,\n Annotation,\n AudioContent,\n AudioMimeType,\n CodeExecutionCallArguments,\n CodeExecutionCallContent,\n CodeExecutionResultContent,\n Content,\n ContentDelta,\n ContentStart,\n ContentStop,\n CreateAgentInteractionParamsNonStreaming,\n CreateAgentInteractionParamsStreaming,\n CreateModelInteractionParamsNonStreaming,\n CreateModelInteractionParamsStreaming,\n DeepResearchAgentConfig,\n DocumentContent,\n DocumentMimeType,\n DynamicAgentConfig,\n ErrorEvent,\n FileSearchCallContent,\n FileSearchResultContent,\n Function,\n FunctionCallContent,\n FunctionResultContent,\n GenerationConfig,\n GoogleSearchCallArguments,\n GoogleSearchCallContent,\n GoogleSearchResult,\n GoogleSearchResultContent,\n ImageConfig,\n ImageContent,\n ImageMimeType,\n Interaction,\n InteractionCancelParams,\n InteractionCompleteEvent,\n InteractionCreateParams,\n InteractionDeleteParams,\n InteractionDeleteResponse,\n InteractionGetParams,\n InteractionGetParamsNonStreaming,\n InteractionGetParamsStreaming,\n InteractionSSEEvent,\n InteractionStartEvent,\n InteractionStatusUpdate,\n Interactions,\n MCPServerToolCallContent,\n MCPServerToolResultContent,\n Model,\n SpeechConfig,\n TextContent,\n ThinkingLevel,\n ThoughtContent,\n Tool,\n ToolChoice,\n ToolChoiceConfig,\n ToolChoiceType,\n Turn,\n URLContextCallArguments,\n URLContextCallContent,\n URLContextResult,\n URLContextResultContent,\n Usage,\n VideoContent,\n VideoMimeType,\n} from './resources/interactions.js';\nimport { type Fetch } from './internal/builtin-types.js';\nimport { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers.js';\nimport { FinalRequestOptions, RequestOptions } from './internal/request-options.js';\nimport { readEnv } from './internal/utils/env.js';\nimport {\n type LogLevel,\n type Logger,\n formatRequestDetails,\n loggerFor,\n parseLogLevel,\n} from './internal/utils/log.js';\nimport { isEmptyObj } from './internal/utils/values.js';\nimport { GeminiNextGenAPIClientAdapter } from './client-adapter.js';\n\nexport interface ClientOptions {\n /**\n * Defaults to process.env['GEMINI_API_KEY'].\n */\n apiKey?: string | null | undefined;\n\n apiVersion?: string | undefined;\n\n /**\n * Override the default base URL for the API, e.g., \"https://api.example.com/v2/\"\n *\n * Defaults to process.env['GEMINI_NEXT_GEN_API_BASE_URL'].\n */\n baseURL?: string | null | undefined;\n\n /**\n * The maximum amount of time (in milliseconds) that the client should wait for a response\n * from the server before timing out a single request.\n *\n * Note that request timeouts are retried by default, so in a worst-case scenario you may wait\n * much longer than this timeout before the promise succeeds or fails.\n *\n * @unit milliseconds\n */\n timeout?: number | undefined;\n /**\n * Additional `RequestInit` options to be passed to `fetch` calls.\n * Properties will be overridden by per-request `fetchOptions`.\n */\n fetchOptions?: MergedRequestInit | undefined;\n\n /**\n * Specify a custom `fetch` function implementation.\n *\n * If not provided, we expect that `fetch` is defined globally.\n */\n fetch?: Fetch | undefined;\n\n /**\n * The maximum number of times that the client will retry a request in case of a\n * temporary failure, like a network error or a 5XX error from the server.\n *\n * @default 2\n */\n maxRetries?: number | undefined;\n\n /**\n * Default headers to include with every request to the API.\n *\n * These can be removed in individual requests by explicitly setting the\n * header to `null` in request options.\n */\n defaultHeaders?: HeadersLike | undefined;\n\n /**\n * Default query parameters to include with every request to the API.\n *\n * These can be removed in individual requests by explicitly setting the\n * param to `undefined` in request options.\n */\n defaultQuery?: Record<string, string | undefined> | undefined;\n\n /**\n * Set the log level.\n *\n * Defaults to process.env['GEMINI_NEXT_GEN_API_LOG'] or 'warn' if it isn't set.\n */\n logLevel?: LogLevel | undefined;\n\n /**\n * Set the logger.\n *\n * Defaults to globalThis.console.\n */\n logger?: Logger | undefined;\n\n /**\n * The adapter to the parent API client instance (for accessing auth, project, location)\n */\n clientAdapter: GeminiNextGenAPIClientAdapter;\n}\n\n/**\n * Base class for Gemini Next Gen API API clients.\n */\nexport class BaseGeminiNextGenAPIClient {\n apiKey: string | null;\n apiVersion: string;\n\n baseURL: string;\n maxRetries: number;\n timeout: number;\n logger: Logger;\n logLevel: LogLevel | undefined;\n fetchOptions: MergedRequestInit | undefined;\n\n private fetch: Fetch;\n private encoder: Opts.RequestEncoder;\n protected idempotencyHeader?: string;\n private _options: ClientOptions;\n private clientAdapter: GeminiNextGenAPIClientAdapter;\n\n /**\n * API Client for interfacing with the Gemini Next Gen API API.\n *\n * @param {string | null | undefined} [opts.apiKey=process.env['GEMINI_API_KEY'] ?? null]\n * @param {string | undefined} [opts.apiVersion=v1beta]\n * @param {string} [opts.baseURL=process.env['GEMINI_NEXT_GEN_API_BASE_URL'] ?? https://generativelanguage.googleapis.com] - Override the default base URL for the API.\n * @param {number} [opts.timeout=1 minute] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out.\n * @param {MergedRequestInit} [opts.fetchOptions] - Additional `RequestInit` options to be passed to `fetch` calls.\n * @param {Fetch} [opts.fetch] - Specify a custom `fetch` function implementation.\n * @param {number} [opts.maxRetries=2] - The maximum number of times the client will retry a request.\n * @param {HeadersLike} opts.defaultHeaders - Default headers to include with every request to the API.\n * @param {Record<string, string | undefined>} opts.defaultQuery - Default query parameters to include with every request to the API.\n */\n constructor({\n baseURL = readEnv('GEMINI_NEXT_GEN_API_BASE_URL'),\n apiKey = readEnv('GEMINI_API_KEY') ?? null,\n apiVersion = 'v1beta',\n ...opts\n }: ClientOptions) {\n const options: ClientOptions = {\n apiKey,\n apiVersion,\n ...opts,\n baseURL: baseURL || `https://generativelanguage.googleapis.com`,\n };\n\n this.baseURL = options.baseURL!;\n this.timeout = options.timeout ?? BaseGeminiNextGenAPIClient.DEFAULT_TIMEOUT /* 1 minute */;\n this.logger = options.logger ?? console;\n const defaultLogLevel = 'warn';\n // Set default logLevel early so that we can log a warning in parseLogLevel.\n this.logLevel = defaultLogLevel;\n this.logLevel =\n parseLogLevel(options.logLevel, 'ClientOptions.logLevel', this) ??\n parseLogLevel(readEnv('GEMINI_NEXT_GEN_API_LOG'), \"process.env['GEMINI_NEXT_GEN_API_LOG']\", this) ??\n defaultLogLevel;\n this.fetchOptions = options.fetchOptions;\n this.maxRetries = options.maxRetries ?? 2;\n this.fetch = options.fetch ?? Shims.getDefaultFetch();\n this.encoder = Opts.FallbackEncoder;\n\n this._options = options;\n\n this.apiKey = apiKey;\n this.apiVersion = apiVersion;\n this.clientAdapter = options.clientAdapter;\n }\n\n /**\n * Create a new client instance re-using the same options given to the current client with optional overriding.\n */\n withOptions(options: Partial<ClientOptions>): this {\n const client = new (this.constructor as any as new (props: ClientOptions) => typeof this)({\n ...this._options,\n baseURL: this.baseURL,\n maxRetries: this.maxRetries,\n timeout: this.timeout,\n logger: this.logger,\n logLevel: this.logLevel,\n fetch: this.fetch,\n fetchOptions: this.fetchOptions,\n apiKey: this.apiKey,\n apiVersion: this.apiVersion,\n ...options,\n });\n return client;\n }\n\n /**\n * Check whether the base URL is set to its default.\n */\n private baseURLOverridden() {\n return this.baseURL !== 'https://generativelanguage.googleapis.com';\n }\n\n protected defaultQuery(): Record<string, string | undefined> | undefined {\n return this._options.defaultQuery;\n }\n\n protected validateHeaders({ values, nulls }: NullableHeaders) {\n // The headers object handles case insensitivity.\n if (values.has('authorization') || values.has('x-goog-api-key')) {\n return;\n }\n if (this.apiKey && values.get('x-goog-api-key')) {\n return;\n }\n if (nulls.has('x-goog-api-key')) {\n return;\n }\n\n throw new Error(\n 'Could not resolve authentication method. Expected the apiKey to be set. Or for the \"x-goog-api-key\" headers to be explicitly omitted',\n );\n }\n\n protected async authHeaders(opts: FinalRequestOptions): Promise<NullableHeaders | undefined> {\n const existingHeaders = buildHeaders([opts.headers]);\n\n if (existingHeaders.values.has('authorization') || existingHeaders.values.has('x-goog-api-key')) {\n return undefined;\n }\n\n if (this.apiKey) {\n return buildHeaders([{ 'x-goog-api-key': this.apiKey }]);\n }\n\n if (this.clientAdapter.isVertexAI()) {\n return buildHeaders([await this.clientAdapter.getAuthHeaders()]);\n }\n\n return undefined;\n }\n\n /**\n * Basic re-implementation of `qs.stringify` for primitive types.\n */\n protected stringifyQuery(query: Record<string, unknown>): string {\n return Object.entries(query)\n .filter(([_, value]) => typeof value !== 'undefined')\n .map(([key, value]) => {\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {\n return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;\n }\n if (value === null) {\n return `${encodeURIComponent(key)}=`;\n }\n throw new Errors.GeminiNextGenAPIClientError(\n `Cannot stringify type ${typeof value}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`,\n );\n })\n .join('&');\n }\n\n private getUserAgent(): string {\n return `${this.constructor.name}/JS ${VERSION}`;\n }\n\n protected defaultIdempotencyKey(): string {\n return `stainless-node-retry-${uuid4()}`;\n }\n\n protected makeStatusError(\n status: number,\n error: Object,\n message: string | undefined,\n headers: Headers,\n ): Errors.APIError {\n return Errors.APIError.generate(status, error, message, headers);\n }\n\n buildURL(\n path: string,\n query: Record<string, unknown> | null | undefined,\n defaultBaseURL?: string | undefined,\n ): string {\n const baseURL = (!this.baseURLOverridden() && defaultBaseURL) || this.baseURL;\n const url =\n isAbsoluteURL(path) ?\n new URL(path)\n : new URL(baseURL + (baseURL.endsWith('/') && path.startsWith('/') ? path.slice(1) : path));\n\n const defaultQuery = this.defaultQuery();\n if (!isEmptyObj(defaultQuery)) {\n query = { ...defaultQuery, ...query };\n }\n\n if (typeof query === 'object' && query && !Array.isArray(query)) {\n url.search = this.stringifyQuery(query as Record<string, unknown>);\n }\n\n return url.toString();\n }\n\n /**\n * Used as a callback for mutating the given `FinalRequestOptions` object.\n\n */\n protected async prepareOptions(options: FinalRequestOptions): Promise<void> {\n if (\n this.clientAdapter &&\n this.clientAdapter.isVertexAI() &&\n !options.path.startsWith(`/${this.apiVersion}/projects/`)\n ) {\n const oldPath = options.path.slice(this.apiVersion.length + 1);\n options.path = `/${\n this.apiVersion\n }/projects/${this.clientAdapter.getProject()}/locations/${this.clientAdapter.getLocation()}${oldPath}`;\n }\n }\n\n /**\n * Used as a callback for mutating the given `RequestInit` object.\n *\n * This is useful for cases where you want to add certain headers based off of\n * the request properties, e.g. `method` or `url`.\n */\n protected async prepareRequest(\n request: RequestInit,\n { url, options }: { url: string; options: FinalRequestOptions },\n ): Promise<void> {}\n\n get<Rsp>(path: string, opts?: PromiseOrValue<RequestOptions>): APIPromise<Rsp> {\n return this.methodRequest('get', path, opts);\n }\n\n post<Rsp>(path: string, opts?: PromiseOrValue<RequestOptions>): APIPromise<Rsp> {\n return this.methodRequest('post', path, opts);\n }\n\n patch<Rsp>(path: string, opts?: PromiseOrValue<RequestOptions>): APIPromise<Rsp> {\n return this.methodRequest('patch', path, opts);\n }\n\n put<Rsp>(path: string, opts?: PromiseOrValue<RequestOptions>): APIPromise<Rsp> {\n return this.methodRequest('put', path, opts);\n }\n\n delete<Rsp>(path: string, opts?: PromiseOrValue<RequestOptions>): APIPromise<Rsp> {\n return this.methodRequest('delete', path, opts);\n }\n\n private methodRequest<Rsp>(\n method: HTTPMethod,\n path: string,\n opts?: PromiseOrValue<RequestOptions>,\n ): APIPromise<Rsp> {\n return this.request(\n Promise.resolve(opts).then((opts) => {\n return { method, path, ...opts };\n }),\n );\n }\n\n request<Rsp>(\n options: PromiseOrValue<FinalRequestOptions>,\n remainingRetries: number | null = null,\n ): APIPromise<Rsp> {\n return new APIPromise(this, this.makeRequest(options, remainingRetries, undefined));\n }\n\n private async makeRequest(\n optionsInput: PromiseOrValue<FinalRequestOptions>,\n retriesRemaining: number | null,\n retryOfRequestLogID: string | undefined,\n ): Promise<APIResponseProps> {\n const options = await optionsInput;\n const maxRetries = options.maxRetries ?? this.maxRetries;\n if (retriesRemaining == null) {\n retriesRemaining = maxRetries;\n }\n\n await this.prepareOptions(options);\n\n const { req, url, timeout } = await this.buildRequest(options, {\n retryCount: maxRetries - retriesRemaining,\n });\n\n await this.prepareRequest(req, { url, options });\n\n /** Not an API request ID, just for correlating local log entries. */\n const requestLogID = 'log_' + ((Math.random() * (1 << 24)) | 0).toString(16).padStart(6, '0');\n const retryLogStr = retryOfRequestLogID === undefined ? '' : `, retryOf: ${retryOfRequestLogID}`;\n const startTime = Date.now();\n\n loggerFor(this).debug(\n `[${requestLogID}] sending request`,\n formatRequestDetails({\n retryOfRequestLogID,\n method: options.method,\n url,\n options,\n headers: req.headers,\n }),\n );\n\n if (options.signal?.aborted) {\n throw new Errors.APIUserAbortError();\n }\n\n const controller = new AbortController();\n const response = await this.fetchWithTimeout(url, req, timeout, controller).catch(castToError);\n const headersTime = Date.now();\n\n if (response instanceof globalThis.Error) {\n const retryMessage = `retrying, ${retriesRemaining} attempts remaining`;\n if (options.signal?.aborted) {\n throw new Errors.APIUserAbortError();\n }\n // detect native connection timeout errors\n // deno throws \"TypeError: error sending request for url (https://example/): client error (Connect): tcp connect error: Operation timed out (os error 60): Operation timed out (os error 60)\"\n // undici throws \"TypeError: fetch failed\" with cause \"ConnectTimeoutError: Connect Timeout Error (attempted address: example:443, timeout: 1ms)\"\n // others do not provide enough information to distinguish timeouts from other connection errors\n const isTimeout =\n isAbortError(response) ||\n /timed? ?out/i.test(String(response) + ('cause' in response ? String(response.cause) : ''));\n if (retriesRemaining) {\n loggerFor(this).info(\n `[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - ${retryMessage}`,\n );\n loggerFor(this).debug(\n `[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (${retryMessage})`,\n formatRequestDetails({\n retryOfRequestLogID,\n url,\n durationMs: headersTime - startTime,\n message: response.message,\n }),\n );\n return this.retryRequest(options, retriesRemaining, retryOfRequestLogID ?? requestLogID);\n }\n loggerFor(this).info(\n `[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - error; no more retries left`,\n );\n loggerFor(this).debug(\n `[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (error; no more retries left)`,\n formatRequestDetails({\n retryOfRequestLogID,\n url,\n durationMs: headersTime - startTime,\n message: response.message,\n }),\n );\n if (isTimeout) {\n throw new Errors.APIConnectionTimeoutError();\n }\n throw new Errors.APIConnectionError({ cause: response });\n }\n\n const responseInfo = `[${requestLogID}${retryLogStr}] ${req.method} ${url} ${\n response.ok ? 'succeeded' : 'failed'\n } with status ${response.status} in ${headersTime - startTime}ms`;\n\n if (!response.ok) {\n const shouldRetry = await this.shouldRetry(response);\n if (retriesRemaining && shouldRetry) {\n const retryMessage = `retrying, ${retriesRemaining} attempts remaining`;\n\n // We don't need the body of this response.\n await Shims.CancelReadableStream(response.body);\n loggerFor(this).info(`${responseInfo} - ${retryMessage}`);\n loggerFor(this).debug(\n `[${requestLogID}] response error (${retryMessage})`,\n formatRequestDetails({\n retryOfRequestLogID,\n url: response.url,\n status: response.status,\n headers: response.headers,\n durationMs: headersTime - startTime,\n }),\n );\n return this.retryRequest(\n options,\n retriesRemaining,\n retryOfRequestLogID ?? requestLogID,\n response.headers,\n );\n }\n\n const retryMessage = shouldRetry ? `error; no more retries left` : `error; not retryable`;\n\n loggerFor(this).info(`${responseInfo} - ${retryMessage}`);\n\n const errText = await response.text().catch((err: any) => castToError(err).message);\n const errJSON = safeJSON(errText);\n const errMessage = errJSON ? undefined : errText;\n\n loggerFor(this).debug(\n `[${requestLogID}] response error (${retryMessage})`,\n formatRequestDetails({\n retryOfRequestLogID,\n url: response.url,\n status: response.status,\n headers: response.headers,\n message: errMessage,\n durationMs: Date.now() - startTime,\n }),\n );\n // @ts-ignore\n const err = this.makeStatusError(response.status, errJSON, errMessage, response.headers);\n throw err;\n }\n\n loggerFor(this).info(responseInfo);\n loggerFor(this).debug(\n `[${requestLogID}] response start`,\n formatRequestDetails({\n retryOfRequestLogID,\n url: response.url,\n status: response.status,\n headers: response.headers,\n durationMs: headersTime - startTime,\n }),\n );\n\n return { response, options, controller, requestLogID, retryOfRequestLogID, startTime };\n }\n\n async fetchWithTimeout(\n url: RequestInfo,\n init: RequestInit | undefined,\n ms: number,\n controller: AbortController,\n ): Promise<Response> {\n const { signal, method, ...options } = init || {};\n const abort = this._makeAbort(controller);\n if (signal) signal.addEventListener('abort', abort, { once: true });\n\n const timeout = setTimeout(abort, ms);\n\n const isReadableBody =\n ((globalThis as any).ReadableStream && options.body instanceof (globalThis as any).ReadableStream) ||\n (typeof options.body === 'object' && options.body !== null && Symbol.asyncIterator in options.body);\n\n const fetchOptions: RequestInit = {\n signal: controller.signal as any,\n ...(isReadableBody ? { duplex: 'half' } : {}),\n method: 'GET',\n ...options,\n };\n if (method) {\n // Custom methods like 'patch' need to be uppercased\n // See https://github.com/nodejs/undici/issues/2294\n fetchOptions.method = method.toUpperCase();\n }\n\n try {\n // use undefined this binding; fetch errors if bound to something else in browser/cloudflare\n return await this.fetch.call(undefined, url, fetchOptions);\n } finally {\n clearTimeout(timeout);\n }\n }\n\n private async shouldRetry(response: Response): Promise<boolean> {\n // Note this is not a standard header.\n const shouldRetryHeader = response.headers.get('x-should-retry');\n\n // If the server explicitly says whether or not to retry, obey.\n if (shouldRetryHeader === 'true') return true;\n if (shouldRetryHeader === 'false') return false;\n\n // Retry on request timeouts.\n if (response.status === 408) return true;\n\n // Retry on lock timeouts.\n if (response.status === 409) return true;\n\n // Retry on rate limits.\n if (response.status === 429) return true;\n\n // Retry internal errors.\n if (response.status >= 500) return true;\n\n return false;\n }\n\n private async retryRequest(\n options: FinalRequestOptions,\n retriesRemaining: number,\n requestLogID: string,\n responseHeaders?: Headers | undefined,\n ): Promise<APIResponseProps> {\n let timeoutMillis: number | undefined;\n\n // Note the `retry-after-ms` header may not be standard, but is a good idea and we'd like proactive support for it.\n const retryAfterMillisHeader = responseHeaders?.get('retry-after-ms');\n if (retryAfterMillisHeader) {\n const timeoutMs = parseFloat(retryAfterMillisHeader);\n if (!Number.isNaN(timeoutMs)) {\n timeoutMillis = timeoutMs;\n }\n }\n\n // About the Retry-After header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After\n const retryAfterHeader = responseHeaders?.get('retry-after');\n if (retryAfterHeader && !timeoutMillis) {\n const timeoutSeconds = parseFloat(retryAfterHeader);\n if (!Number.isNaN(timeoutSeconds)) {\n timeoutMillis = timeoutSeconds * 1000;\n } else {\n timeoutMillis = Date.parse(retryAfterHeader) - Date.now();\n }\n }\n\n // If the API asks us to wait a certain amount of time (and it's a reasonable amount),\n // just do what it says, but otherwise calculate a default\n if (!(timeoutMillis && 0 <= timeoutMillis && timeoutMillis < 60 * 1000)) {\n const maxRetries = options.maxRetries ?? this.maxRetries;\n timeoutMillis = this.calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries);\n }\n await sleep(timeoutMillis);\n\n return this.makeRequest(options, retriesRemaining - 1, requestLogID);\n }\n\n private calculateDefaultRetryTimeoutMillis(retriesRemaining: number, maxRetries: number): number {\n const initialRetryDelay = 0.5;\n const maxRetryDelay = 8.0;\n\n const numRetries = maxRetries - retriesRemaining;\n\n // Apply exponential backoff, but not more than the max.\n const sleepSeconds = Math.min(initialRetryDelay * Math.pow(2, numRetries), maxRetryDelay);\n\n // Apply some jitter, take up to at most 25 percent of the retry time.\n const jitter = 1 - Math.random() * 0.25;\n\n return sleepSeconds * jitter * 1000;\n }\n\n async buildRequest(\n inputOptions: FinalRequestOptions,\n { retryCount = 0 }: { retryCount?: number } = {},\n ): Promise<{ req: FinalizedRequestInit; url: string; timeout: number }> {\n const options = { ...inputOptions };\n const { method, path, query, defaultBaseURL } = options;\n\n const url = this.buildURL(path!, query as Record<string, unknown>, defaultBaseURL);\n if ('timeout' in options) validatePositiveInteger('timeout', options.timeout);\n options.timeout = options.timeout ?? this.timeout;\n const { bodyHeaders, body } = this.buildBody({ options });\n const reqHeaders = await this.buildHeaders({ options: inputOptions, method, bodyHeaders, retryCount });\n\n const req: FinalizedRequestInit = {\n method,\n headers: reqHeaders,\n ...(options.signal && { signal: options.signal }),\n ...((globalThis as any).ReadableStream &&\n body instanceof (globalThis as any).ReadableStream && { duplex: 'half' }),\n ...(body && { body }),\n ...((this.fetchOptions as any) ?? {}),\n ...((options.fetchOptions as any) ?? {}),\n };\n\n return { req, url, timeout: options.timeout };\n }\n\n private async buildHeaders({\n options,\n method,\n bodyHeaders,\n retryCount,\n }: {\n options: FinalRequestOptions;\n method: HTTPMethod;\n bodyHeaders: HeadersLike;\n retryCount: number;\n }): Promise<Headers> {\n let idempotencyHeaders: HeadersLike = {};\n if (this.idempotencyHeader && method !== 'get') {\n if (!options.idempotencyKey) options.idempotencyKey = this.defaultIdempotencyKey();\n idempotencyHeaders[this.idempotencyHeader] = options.idempotencyKey;\n }\n\n const authHeaders = await this.authHeaders(options);\n\n let headers = buildHeaders([\n idempotencyHeaders,\n {\n Accept: 'application/json',\n 'User-Agent': this.getUserAgent(),\n 'X-Stainless-Retry-Count': String(retryCount),\n ...(options.timeout ? { 'X-Stainless-Timeout': String(Math.trunc(options.timeout / 1000)) } : {}),\n ...getPlatformHeaders(),\n },\n this._options.defaultHeaders,\n bodyHeaders,\n options.headers,\n authHeaders,\n ]);\n\n this.validateHeaders(headers);\n\n return headers.values;\n }\n\n private _makeAbort(controller: AbortController) {\n // note: we can't just inline this method inside `fetchWithTimeout()` because then the closure\n // would capture all request options, and cause a memory leak.\n return () => controller.abort();\n }\n\n private buildBody({ options: { body, headers: rawHeaders } }: { options: FinalRequestOptions }): {\n bodyHeaders: HeadersLike;\n body: BodyInit | undefined;\n } {\n if (!body) {\n return { bodyHeaders: undefined, body: undefined };\n }\n const headers = buildHeaders([rawHeaders]);\n if (\n // Pass raw type verbatim\n ArrayBuffer.isView(body) ||\n body instanceof ArrayBuffer ||\n body instanceof DataView ||\n (typeof body === 'string' &&\n // Preserve legacy string encoding behavior for now\n headers.values.has('content-type')) ||\n // `Blob` is superset of `File`\n ((globalThis as any).Blob && body instanceof (globalThis as any).Blob) ||\n // `FormData` -> `multipart/form-data`\n body instanceof FormData ||\n // `URLSearchParams` -> `application/x-www-form-urlencoded`\n body instanceof URLSearchParams ||\n // Send chunked stream (each chunk has own `length`)\n ((globalThis as any).ReadableStream && body instanceof (globalThis as any).ReadableStream)\n ) {\n return { bodyHeaders: undefined, body: body as BodyInit };\n } else if (\n typeof body === 'object' &&\n (Symbol.asyncIterator in body ||\n (Symbol.iterator in body && 'next' in body && typeof body.next === 'function'))\n ) {\n return { bodyHeaders: undefined, body: Shims.ReadableStreamFrom(body as AsyncIterable<Uint8Array>) };\n } else {\n return this.encoder({ body, headers });\n }\n }\n\n static DEFAULT_TIMEOUT = 60000; // 1 minute\n}\n\n/**\n * API Client for interfacing with the Gemini Next Gen API API.\n */\nexport class GeminiNextGenAPIClient extends BaseGeminiNextGenAPIClient {\n static GeminiNextGenAPIClient = this;\n\n static GeminiNextGenAPIClientError = Errors.GeminiNextGenAPIClientError;\n static APIError = Errors.APIError;\n static APIConnectionError = Errors.APIConnectionError;\n static APIConnectionTimeoutError = Errors.APIConnectionTimeoutError;\n static APIUserAbortError = Errors.APIUserAbortError;\n static NotFoundError = Errors.NotFoundError;\n static ConflictError = Errors.ConflictError;\n static RateLimitError = Errors.RateLimitError;\n static BadRequestError = Errors.BadRequestError;\n static AuthenticationError = Errors.AuthenticationError;\n static InternalServerError = Errors.InternalServerError;\n static PermissionDeniedError = Errors.PermissionDeniedError;\n static UnprocessableEntityError = Errors.UnprocessableEntityError;\n\n static toFile = Uploads.toFile;\n\n interactions: API.Interactions = new API.Interactions(this);\n}\n\nGeminiNextGenAPIClient.Interactions = Interactions;\n\nexport declare namespace GeminiNextGenAPIClient {\n export type RequestOptions = Opts.RequestOptions;\n\n export {\n Interactions as Interactions,\n type AllowedTools as AllowedTools,\n type Annotation as Annotation,\n type AudioContent as AudioContent,\n type AudioMimeType as AudioMimeType,\n type CodeExecutionCallArguments as CodeExecutionCallArguments,\n type CodeExecutionCallContent as CodeExecutionCallContent,\n type CodeExecutionResultContent as CodeExecutionResultContent,\n type Content as Content,\n type ContentDelta as ContentDelta,\n type ContentStart as ContentStart,\n type ContentStop as ContentStop,\n type DeepResearchAgentConfig as DeepResearchAgentConfig,\n type DocumentContent as DocumentContent,\n type DocumentMimeType as DocumentMimeType,\n type DynamicAgentConfig as DynamicAgentConfig,\n type ErrorEvent as ErrorEvent,\n type FileSearchCallContent as FileSearchCallContent,\n type FileSearchResultContent as FileSearchResultContent,\n type Function as Function,\n type FunctionCallContent as FunctionCallContent,\n type FunctionResultContent as FunctionResultContent,\n type GenerationConfig as GenerationConfig,\n type GoogleSearchCallArguments as GoogleSearchCallArguments,\n type GoogleSearchCallContent as GoogleSearchCallContent,\n type GoogleSearchResult as GoogleSearchResult,\n type GoogleSearchResultContent as GoogleSearchResultContent,\n type ImageConfig as ImageConfig,\n type ImageContent as ImageContent,\n type ImageMimeType as ImageMimeType,\n type Interaction as Interaction,\n type InteractionCompleteEvent as InteractionCompleteEvent,\n type InteractionSSEEvent as InteractionSSEEvent,\n type InteractionStartEvent as InteractionStartEvent,\n type InteractionStatusUpdate as InteractionStatusUpdate,\n type MCPServerToolCallContent as MCPServerToolCallContent,\n type MCPServerToolResultContent as MCPServerToolResultContent,\n type Model as Model,\n type SpeechConfig as SpeechConfig,\n type TextContent as TextContent,\n type ThinkingLevel as ThinkingLevel,\n type ThoughtContent as ThoughtContent,\n type Tool as Tool,\n type ToolChoice as ToolChoice,\n type ToolChoiceConfig as ToolChoiceConfig,\n type ToolChoiceType as ToolChoiceType,\n type Turn as Turn,\n type URLContextCallArguments as URLContextCallArguments,\n type URLContextCallContent as URLContextCallContent,\n type URLContextResult as URLContextResult,\n type URLContextResultContent as URLContextResultContent,\n type Usage as Usage,\n type VideoContent as VideoContent,\n type VideoMimeType as VideoMimeType,\n type InteractionDeleteResponse as InteractionDeleteResponse,\n type InteractionCreateParams as InteractionCreateParams,\n type CreateModelInteractionParamsNonStreaming as CreateModelInteractionParamsNonStreaming,\n type CreateModelInteractionParamsStreaming as CreateModelInteractionParamsStreaming,\n type CreateAgentInteractionParamsNonStreaming as CreateAgentInteractionParamsNonStreaming,\n type CreateAgentInteractionParamsStreaming as CreateAgentInteractionParamsStreaming,\n type InteractionDeleteParams as InteractionDeleteParams,\n type InteractionCancelParams as InteractionCancelParams,\n type InteractionGetParams as InteractionGetParams,\n type InteractionGetParamsNonStreaming as InteractionGetParamsNonStreaming,\n type InteractionGetParamsStreaming as InteractionGetParamsStreaming,\n };\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport {ApiClient} from '../_api_client.js';\nimport * as common from '../_common.js';\nimport * as t from '../_transformers.js';\nimport type * as types from '../types.js';\n\nexport function blobToMldev(fromObject: types.Blob): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromData = common.getValueByPath(fromObject, ['data']);\n if (fromData != null) {\n common.setValueByPath(toObject, ['data'], fromData);\n }\n\n if (common.getValueByPath(fromObject, ['displayName']) !== undefined) {\n throw new Error('displayName parameter is not supported in Gemini API.');\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function contentToMldev(\n fromObject: types.Content,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromParts = common.getValueByPath(fromObject, ['parts']);\n if (fromParts != null) {\n let transformedList = fromParts;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return partToMldev(item);\n });\n }\n common.setValueByPath(toObject, ['parts'], transformedList);\n }\n\n const fromRole = common.getValueByPath(fromObject, ['role']);\n if (fromRole != null) {\n common.setValueByPath(toObject, ['role'], fromRole);\n }\n\n return toObject;\n}\n\nexport function fileDataToMldev(\n fromObject: types.FileData,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['displayName']) !== undefined) {\n throw new Error('displayName parameter is not supported in Gemini API.');\n }\n\n const fromFileUri = common.getValueByPath(fromObject, ['fileUri']);\n if (fromFileUri != null) {\n common.setValueByPath(toObject, ['fileUri'], fromFileUri);\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function functionCallToMldev(\n fromObject: types.FunctionCall,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromId = common.getValueByPath(fromObject, ['id']);\n if (fromId != null) {\n common.setValueByPath(toObject, ['id'], fromId);\n }\n\n const fromArgs = common.getValueByPath(fromObject, ['args']);\n if (fromArgs != null) {\n common.setValueByPath(toObject, ['args'], fromArgs);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n if (common.getValueByPath(fromObject, ['partialArgs']) !== undefined) {\n throw new Error('partialArgs parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['willContinue']) !== undefined) {\n throw new Error('willContinue parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function functionDeclarationToVertex(\n fromObject: types.FunctionDeclaration,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromDescription = common.getValueByPath(fromObject, ['description']);\n if (fromDescription != null) {\n common.setValueByPath(toObject, ['description'], fromDescription);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromParameters = common.getValueByPath(fromObject, ['parameters']);\n if (fromParameters != null) {\n common.setValueByPath(toObject, ['parameters'], fromParameters);\n }\n\n const fromParametersJsonSchema = common.getValueByPath(fromObject, [\n 'parametersJsonSchema',\n ]);\n if (fromParametersJsonSchema != null) {\n common.setValueByPath(\n toObject,\n ['parametersJsonSchema'],\n fromParametersJsonSchema,\n );\n }\n\n const fromResponse = common.getValueByPath(fromObject, ['response']);\n if (fromResponse != null) {\n common.setValueByPath(toObject, ['response'], fromResponse);\n }\n\n const fromResponseJsonSchema = common.getValueByPath(fromObject, [\n 'responseJsonSchema',\n ]);\n if (fromResponseJsonSchema != null) {\n common.setValueByPath(\n toObject,\n ['responseJsonSchema'],\n fromResponseJsonSchema,\n );\n }\n\n if (common.getValueByPath(fromObject, ['behavior']) !== undefined) {\n throw new Error('behavior parameter is not supported in Vertex AI.');\n }\n\n return toObject;\n}\n\nexport function generationConfigToVertex(\n fromObject: types.GenerationConfig,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModelSelectionConfig = common.getValueByPath(fromObject, [\n 'modelSelectionConfig',\n ]);\n if (fromModelSelectionConfig != null) {\n common.setValueByPath(toObject, ['modelConfig'], fromModelSelectionConfig);\n }\n\n const fromResponseJsonSchema = common.getValueByPath(fromObject, [\n 'responseJsonSchema',\n ]);\n if (fromResponseJsonSchema != null) {\n common.setValueByPath(\n toObject,\n ['responseJsonSchema'],\n fromResponseJsonSchema,\n );\n }\n\n const fromAudioTimestamp = common.getValueByPath(fromObject, [\n 'audioTimestamp',\n ]);\n if (fromAudioTimestamp != null) {\n common.setValueByPath(toObject, ['audioTimestamp'], fromAudioTimestamp);\n }\n\n const fromCandidateCount = common.getValueByPath(fromObject, [\n 'candidateCount',\n ]);\n if (fromCandidateCount != null) {\n common.setValueByPath(toObject, ['candidateCount'], fromCandidateCount);\n }\n\n const fromEnableAffectiveDialog = common.getValueByPath(fromObject, [\n 'enableAffectiveDialog',\n ]);\n if (fromEnableAffectiveDialog != null) {\n common.setValueByPath(\n toObject,\n ['enableAffectiveDialog'],\n fromEnableAffectiveDialog,\n );\n }\n\n const fromFrequencyPenalty = common.getValueByPath(fromObject, [\n 'frequencyPenalty',\n ]);\n if (fromFrequencyPenalty != null) {\n common.setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty);\n }\n\n const fromLogprobs = common.getValueByPath(fromObject, ['logprobs']);\n if (fromLogprobs != null) {\n common.setValueByPath(toObject, ['logprobs'], fromLogprobs);\n }\n\n const fromMaxOutputTokens = common.getValueByPath(fromObject, [\n 'maxOutputTokens',\n ]);\n if (fromMaxOutputTokens != null) {\n common.setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens);\n }\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (fromMediaResolution != null) {\n common.setValueByPath(toObject, ['mediaResolution'], fromMediaResolution);\n }\n\n const fromPresencePenalty = common.getValueByPath(fromObject, [\n 'presencePenalty',\n ]);\n if (fromPresencePenalty != null) {\n common.setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty);\n }\n\n const fromResponseLogprobs = common.getValueByPath(fromObject, [\n 'responseLogprobs',\n ]);\n if (fromResponseLogprobs != null) {\n common.setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs);\n }\n\n const fromResponseMimeType = common.getValueByPath(fromObject, [\n 'responseMimeType',\n ]);\n if (fromResponseMimeType != null) {\n common.setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType);\n }\n\n const fromResponseModalities = common.getValueByPath(fromObject, [\n 'responseModalities',\n ]);\n if (fromResponseModalities != null) {\n common.setValueByPath(\n toObject,\n ['responseModalities'],\n fromResponseModalities,\n );\n }\n\n const fromResponseSchema = common.getValueByPath(fromObject, [\n 'responseSchema',\n ]);\n if (fromResponseSchema != null) {\n common.setValueByPath(toObject, ['responseSchema'], fromResponseSchema);\n }\n\n const fromRoutingConfig = common.getValueByPath(fromObject, [\n 'routingConfig',\n ]);\n if (fromRoutingConfig != null) {\n common.setValueByPath(toObject, ['routingConfig'], fromRoutingConfig);\n }\n\n const fromSeed = common.getValueByPath(fromObject, ['seed']);\n if (fromSeed != null) {\n common.setValueByPath(toObject, ['seed'], fromSeed);\n }\n\n const fromSpeechConfig = common.getValueByPath(fromObject, ['speechConfig']);\n if (fromSpeechConfig != null) {\n common.setValueByPath(toObject, ['speechConfig'], fromSpeechConfig);\n }\n\n const fromStopSequences = common.getValueByPath(fromObject, [\n 'stopSequences',\n ]);\n if (fromStopSequences != null) {\n common.setValueByPath(toObject, ['stopSequences'], fromStopSequences);\n }\n\n const fromTemperature = common.getValueByPath(fromObject, ['temperature']);\n if (fromTemperature != null) {\n common.setValueByPath(toObject, ['temperature'], fromTemperature);\n }\n\n const fromThinkingConfig = common.getValueByPath(fromObject, [\n 'thinkingConfig',\n ]);\n if (fromThinkingConfig != null) {\n common.setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig);\n }\n\n const fromTopK = common.getValueByPath(fromObject, ['topK']);\n if (fromTopK != null) {\n common.setValueByPath(toObject, ['topK'], fromTopK);\n }\n\n const fromTopP = common.getValueByPath(fromObject, ['topP']);\n if (fromTopP != null) {\n common.setValueByPath(toObject, ['topP'], fromTopP);\n }\n\n if (\n common.getValueByPath(fromObject, ['enableEnhancedCivicAnswers']) !==\n undefined\n ) {\n throw new Error(\n 'enableEnhancedCivicAnswers parameter is not supported in Vertex AI.',\n );\n }\n\n return toObject;\n}\n\nexport function googleMapsToMldev(\n fromObject: types.GoogleMaps,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['authConfig']) !== undefined) {\n throw new Error('authConfig parameter is not supported in Gemini API.');\n }\n\n const fromEnableWidget = common.getValueByPath(fromObject, ['enableWidget']);\n if (fromEnableWidget != null) {\n common.setValueByPath(toObject, ['enableWidget'], fromEnableWidget);\n }\n\n return toObject;\n}\n\nexport function googleSearchToMldev(\n fromObject: types.GoogleSearch,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['excludeDomains']) !== undefined) {\n throw new Error('excludeDomains parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['blockingConfidence']) !== undefined) {\n throw new Error(\n 'blockingConfidence parameter is not supported in Gemini API.',\n );\n }\n\n const fromTimeRangeFilter = common.getValueByPath(fromObject, [\n 'timeRangeFilter',\n ]);\n if (fromTimeRangeFilter != null) {\n common.setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter);\n }\n\n return toObject;\n}\n\nexport function liveClientContentToMldev(\n fromObject: types.LiveClientContent,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromTurns = common.getValueByPath(fromObject, ['turns']);\n if (fromTurns != null) {\n let transformedList = fromTurns;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return contentToMldev(item);\n });\n }\n common.setValueByPath(toObject, ['turns'], transformedList);\n }\n\n const fromTurnComplete = common.getValueByPath(fromObject, ['turnComplete']);\n if (fromTurnComplete != null) {\n common.setValueByPath(toObject, ['turnComplete'], fromTurnComplete);\n }\n\n return toObject;\n}\n\nexport function liveClientMessageToMldev(\n fromObject: types.LiveClientMessage,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSetup = common.getValueByPath(fromObject, ['setup']);\n if (fromSetup != null) {\n common.setValueByPath(\n toObject,\n ['setup'],\n liveClientSetupToMldev(fromSetup),\n );\n }\n\n const fromClientContent = common.getValueByPath(fromObject, [\n 'clientContent',\n ]);\n if (fromClientContent != null) {\n common.setValueByPath(\n toObject,\n ['clientContent'],\n liveClientContentToMldev(fromClientContent),\n );\n }\n\n const fromRealtimeInput = common.getValueByPath(fromObject, [\n 'realtimeInput',\n ]);\n if (fromRealtimeInput != null) {\n common.setValueByPath(\n toObject,\n ['realtimeInput'],\n liveClientRealtimeInputToMldev(fromRealtimeInput),\n );\n }\n\n const fromToolResponse = common.getValueByPath(fromObject, ['toolResponse']);\n if (fromToolResponse != null) {\n common.setValueByPath(toObject, ['toolResponse'], fromToolResponse);\n }\n\n return toObject;\n}\n\nexport function liveClientMessageToVertex(\n fromObject: types.LiveClientMessage,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSetup = common.getValueByPath(fromObject, ['setup']);\n if (fromSetup != null) {\n common.setValueByPath(\n toObject,\n ['setup'],\n liveClientSetupToVertex(fromSetup),\n );\n }\n\n const fromClientContent = common.getValueByPath(fromObject, [\n 'clientContent',\n ]);\n if (fromClientContent != null) {\n common.setValueByPath(toObject, ['clientContent'], fromClientContent);\n }\n\n const fromRealtimeInput = common.getValueByPath(fromObject, [\n 'realtimeInput',\n ]);\n if (fromRealtimeInput != null) {\n common.setValueByPath(\n toObject,\n ['realtimeInput'],\n liveClientRealtimeInputToVertex(fromRealtimeInput),\n );\n }\n\n const fromToolResponse = common.getValueByPath(fromObject, ['toolResponse']);\n if (fromToolResponse != null) {\n common.setValueByPath(toObject, ['toolResponse'], fromToolResponse);\n }\n\n return toObject;\n}\n\nexport function liveClientRealtimeInputToMldev(\n fromObject: types.LiveClientRealtimeInput,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMediaChunks = common.getValueByPath(fromObject, ['mediaChunks']);\n if (fromMediaChunks != null) {\n let transformedList = fromMediaChunks;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return blobToMldev(item);\n });\n }\n common.setValueByPath(toObject, ['mediaChunks'], transformedList);\n }\n\n const fromAudio = common.getValueByPath(fromObject, ['audio']);\n if (fromAudio != null) {\n common.setValueByPath(toObject, ['audio'], blobToMldev(fromAudio));\n }\n\n const fromAudioStreamEnd = common.getValueByPath(fromObject, [\n 'audioStreamEnd',\n ]);\n if (fromAudioStreamEnd != null) {\n common.setValueByPath(toObject, ['audioStreamEnd'], fromAudioStreamEnd);\n }\n\n const fromVideo = common.getValueByPath(fromObject, ['video']);\n if (fromVideo != null) {\n common.setValueByPath(toObject, ['video'], blobToMldev(fromVideo));\n }\n\n const fromText = common.getValueByPath(fromObject, ['text']);\n if (fromText != null) {\n common.setValueByPath(toObject, ['text'], fromText);\n }\n\n const fromActivityStart = common.getValueByPath(fromObject, [\n 'activityStart',\n ]);\n if (fromActivityStart != null) {\n common.setValueByPath(toObject, ['activityStart'], fromActivityStart);\n }\n\n const fromActivityEnd = common.getValueByPath(fromObject, ['activityEnd']);\n if (fromActivityEnd != null) {\n common.setValueByPath(toObject, ['activityEnd'], fromActivityEnd);\n }\n\n return toObject;\n}\n\nexport function liveClientRealtimeInputToVertex(\n fromObject: types.LiveClientRealtimeInput,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMediaChunks = common.getValueByPath(fromObject, ['mediaChunks']);\n if (fromMediaChunks != null) {\n let transformedList = fromMediaChunks;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['mediaChunks'], transformedList);\n }\n\n const fromAudio = common.getValueByPath(fromObject, ['audio']);\n if (fromAudio != null) {\n common.setValueByPath(toObject, ['audio'], fromAudio);\n }\n\n if (common.getValueByPath(fromObject, ['audioStreamEnd']) !== undefined) {\n throw new Error('audioStreamEnd parameter is not supported in Vertex AI.');\n }\n\n const fromVideo = common.getValueByPath(fromObject, ['video']);\n if (fromVideo != null) {\n common.setValueByPath(toObject, ['video'], fromVideo);\n }\n\n const fromText = common.getValueByPath(fromObject, ['text']);\n if (fromText != null) {\n common.setValueByPath(toObject, ['text'], fromText);\n }\n\n const fromActivityStart = common.getValueByPath(fromObject, [\n 'activityStart',\n ]);\n if (fromActivityStart != null) {\n common.setValueByPath(toObject, ['activityStart'], fromActivityStart);\n }\n\n const fromActivityEnd = common.getValueByPath(fromObject, ['activityEnd']);\n if (fromActivityEnd != null) {\n common.setValueByPath(toObject, ['activityEnd'], fromActivityEnd);\n }\n\n return toObject;\n}\n\nexport function liveClientSetupToMldev(\n fromObject: types.LiveClientSetup,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(toObject, ['model'], fromModel);\n }\n\n const fromGenerationConfig = common.getValueByPath(fromObject, [\n 'generationConfig',\n ]);\n if (fromGenerationConfig != null) {\n common.setValueByPath(toObject, ['generationConfig'], fromGenerationConfig);\n }\n\n const fromSystemInstruction = common.getValueByPath(fromObject, [\n 'systemInstruction',\n ]);\n if (fromSystemInstruction != null) {\n common.setValueByPath(\n toObject,\n ['systemInstruction'],\n contentToMldev(t.tContent(fromSystemInstruction)),\n );\n }\n\n const fromTools = common.getValueByPath(fromObject, ['tools']);\n if (fromTools != null) {\n let transformedList = t.tTools(fromTools);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return toolToMldev(t.tTool(item));\n });\n }\n common.setValueByPath(toObject, ['tools'], transformedList);\n }\n\n const fromRealtimeInputConfig = common.getValueByPath(fromObject, [\n 'realtimeInputConfig',\n ]);\n if (fromRealtimeInputConfig != null) {\n common.setValueByPath(\n toObject,\n ['realtimeInputConfig'],\n fromRealtimeInputConfig,\n );\n }\n\n const fromSessionResumption = common.getValueByPath(fromObject, [\n 'sessionResumption',\n ]);\n if (fromSessionResumption != null) {\n common.setValueByPath(\n toObject,\n ['sessionResumption'],\n sessionResumptionConfigToMldev(fromSessionResumption),\n );\n }\n\n const fromContextWindowCompression = common.getValueByPath(fromObject, [\n 'contextWindowCompression',\n ]);\n if (fromContextWindowCompression != null) {\n common.setValueByPath(\n toObject,\n ['contextWindowCompression'],\n fromContextWindowCompression,\n );\n }\n\n const fromInputAudioTranscription = common.getValueByPath(fromObject, [\n 'inputAudioTranscription',\n ]);\n if (fromInputAudioTranscription != null) {\n common.setValueByPath(\n toObject,\n ['inputAudioTranscription'],\n fromInputAudioTranscription,\n );\n }\n\n const fromOutputAudioTranscription = common.getValueByPath(fromObject, [\n 'outputAudioTranscription',\n ]);\n if (fromOutputAudioTranscription != null) {\n common.setValueByPath(\n toObject,\n ['outputAudioTranscription'],\n fromOutputAudioTranscription,\n );\n }\n\n const fromProactivity = common.getValueByPath(fromObject, ['proactivity']);\n if (fromProactivity != null) {\n common.setValueByPath(toObject, ['proactivity'], fromProactivity);\n }\n\n if (common.getValueByPath(fromObject, ['explicitVadSignal']) !== undefined) {\n throw new Error(\n 'explicitVadSignal parameter is not supported in Gemini API.',\n );\n }\n\n return toObject;\n}\n\nexport function liveClientSetupToVertex(\n fromObject: types.LiveClientSetup,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(toObject, ['model'], fromModel);\n }\n\n const fromGenerationConfig = common.getValueByPath(fromObject, [\n 'generationConfig',\n ]);\n if (fromGenerationConfig != null) {\n common.setValueByPath(\n toObject,\n ['generationConfig'],\n generationConfigToVertex(fromGenerationConfig),\n );\n }\n\n const fromSystemInstruction = common.getValueByPath(fromObject, [\n 'systemInstruction',\n ]);\n if (fromSystemInstruction != null) {\n common.setValueByPath(\n toObject,\n ['systemInstruction'],\n t.tContent(fromSystemInstruction),\n );\n }\n\n const fromTools = common.getValueByPath(fromObject, ['tools']);\n if (fromTools != null) {\n let transformedList = t.tTools(fromTools);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return toolToVertex(t.tTool(item));\n });\n }\n common.setValueByPath(toObject, ['tools'], transformedList);\n }\n\n const fromRealtimeInputConfig = common.getValueByPath(fromObject, [\n 'realtimeInputConfig',\n ]);\n if (fromRealtimeInputConfig != null) {\n common.setValueByPath(\n toObject,\n ['realtimeInputConfig'],\n fromRealtimeInputConfig,\n );\n }\n\n const fromSessionResumption = common.getValueByPath(fromObject, [\n 'sessionResumption',\n ]);\n if (fromSessionResumption != null) {\n common.setValueByPath(\n toObject,\n ['sessionResumption'],\n fromSessionResumption,\n );\n }\n\n const fromContextWindowCompression = common.getValueByPath(fromObject, [\n 'contextWindowCompression',\n ]);\n if (fromContextWindowCompression != null) {\n common.setValueByPath(\n toObject,\n ['contextWindowCompression'],\n fromContextWindowCompression,\n );\n }\n\n const fromInputAudioTranscription = common.getValueByPath(fromObject, [\n 'inputAudioTranscription',\n ]);\n if (fromInputAudioTranscription != null) {\n common.setValueByPath(\n toObject,\n ['inputAudioTranscription'],\n fromInputAudioTranscription,\n );\n }\n\n const fromOutputAudioTranscription = common.getValueByPath(fromObject, [\n 'outputAudioTranscription',\n ]);\n if (fromOutputAudioTranscription != null) {\n common.setValueByPath(\n toObject,\n ['outputAudioTranscription'],\n fromOutputAudioTranscription,\n );\n }\n\n const fromProactivity = common.getValueByPath(fromObject, ['proactivity']);\n if (fromProactivity != null) {\n common.setValueByPath(toObject, ['proactivity'], fromProactivity);\n }\n\n const fromExplicitVadSignal = common.getValueByPath(fromObject, [\n 'explicitVadSignal',\n ]);\n if (fromExplicitVadSignal != null) {\n common.setValueByPath(\n toObject,\n ['explicitVadSignal'],\n fromExplicitVadSignal,\n );\n }\n\n return toObject;\n}\n\nexport function liveConnectConfigToMldev(\n fromObject: types.LiveConnectConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromGenerationConfig = common.getValueByPath(fromObject, [\n 'generationConfig',\n ]);\n if (parentObject !== undefined && fromGenerationConfig != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig'],\n fromGenerationConfig,\n );\n }\n\n const fromResponseModalities = common.getValueByPath(fromObject, [\n 'responseModalities',\n ]);\n if (parentObject !== undefined && fromResponseModalities != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'responseModalities'],\n fromResponseModalities,\n );\n }\n\n const fromTemperature = common.getValueByPath(fromObject, ['temperature']);\n if (parentObject !== undefined && fromTemperature != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'temperature'],\n fromTemperature,\n );\n }\n\n const fromTopP = common.getValueByPath(fromObject, ['topP']);\n if (parentObject !== undefined && fromTopP != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'topP'],\n fromTopP,\n );\n }\n\n const fromTopK = common.getValueByPath(fromObject, ['topK']);\n if (parentObject !== undefined && fromTopK != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'topK'],\n fromTopK,\n );\n }\n\n const fromMaxOutputTokens = common.getValueByPath(fromObject, [\n 'maxOutputTokens',\n ]);\n if (parentObject !== undefined && fromMaxOutputTokens != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'maxOutputTokens'],\n fromMaxOutputTokens,\n );\n }\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (parentObject !== undefined && fromMediaResolution != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'mediaResolution'],\n fromMediaResolution,\n );\n }\n\n const fromSeed = common.getValueByPath(fromObject, ['seed']);\n if (parentObject !== undefined && fromSeed != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'seed'],\n fromSeed,\n );\n }\n\n const fromSpeechConfig = common.getValueByPath(fromObject, ['speechConfig']);\n if (parentObject !== undefined && fromSpeechConfig != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'speechConfig'],\n t.tLiveSpeechConfig(fromSpeechConfig),\n );\n }\n\n const fromThinkingConfig = common.getValueByPath(fromObject, [\n 'thinkingConfig',\n ]);\n if (parentObject !== undefined && fromThinkingConfig != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'thinkingConfig'],\n fromThinkingConfig,\n );\n }\n\n const fromEnableAffectiveDialog = common.getValueByPath(fromObject, [\n 'enableAffectiveDialog',\n ]);\n if (parentObject !== undefined && fromEnableAffectiveDialog != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'enableAffectiveDialog'],\n fromEnableAffectiveDialog,\n );\n }\n\n const fromSystemInstruction = common.getValueByPath(fromObject, [\n 'systemInstruction',\n ]);\n if (parentObject !== undefined && fromSystemInstruction != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'systemInstruction'],\n contentToMldev(t.tContent(fromSystemInstruction)),\n );\n }\n\n const fromTools = common.getValueByPath(fromObject, ['tools']);\n if (parentObject !== undefined && fromTools != null) {\n let transformedList = t.tTools(fromTools);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return toolToMldev(t.tTool(item));\n });\n }\n common.setValueByPath(parentObject, ['setup', 'tools'], transformedList);\n }\n\n const fromSessionResumption = common.getValueByPath(fromObject, [\n 'sessionResumption',\n ]);\n if (parentObject !== undefined && fromSessionResumption != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'sessionResumption'],\n sessionResumptionConfigToMldev(fromSessionResumption),\n );\n }\n\n const fromInputAudioTranscription = common.getValueByPath(fromObject, [\n 'inputAudioTranscription',\n ]);\n if (parentObject !== undefined && fromInputAudioTranscription != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'inputAudioTranscription'],\n fromInputAudioTranscription,\n );\n }\n\n const fromOutputAudioTranscription = common.getValueByPath(fromObject, [\n 'outputAudioTranscription',\n ]);\n if (parentObject !== undefined && fromOutputAudioTranscription != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'outputAudioTranscription'],\n fromOutputAudioTranscription,\n );\n }\n\n const fromRealtimeInputConfig = common.getValueByPath(fromObject, [\n 'realtimeInputConfig',\n ]);\n if (parentObject !== undefined && fromRealtimeInputConfig != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'realtimeInputConfig'],\n fromRealtimeInputConfig,\n );\n }\n\n const fromContextWindowCompression = common.getValueByPath(fromObject, [\n 'contextWindowCompression',\n ]);\n if (parentObject !== undefined && fromContextWindowCompression != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'contextWindowCompression'],\n fromContextWindowCompression,\n );\n }\n\n const fromProactivity = common.getValueByPath(fromObject, ['proactivity']);\n if (parentObject !== undefined && fromProactivity != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'proactivity'],\n fromProactivity,\n );\n }\n\n if (common.getValueByPath(fromObject, ['explicitVadSignal']) !== undefined) {\n throw new Error(\n 'explicitVadSignal parameter is not supported in Gemini API.',\n );\n }\n\n return toObject;\n}\n\nexport function liveConnectConfigToVertex(\n fromObject: types.LiveConnectConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromGenerationConfig = common.getValueByPath(fromObject, [\n 'generationConfig',\n ]);\n if (parentObject !== undefined && fromGenerationConfig != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig'],\n generationConfigToVertex(fromGenerationConfig),\n );\n }\n\n const fromResponseModalities = common.getValueByPath(fromObject, [\n 'responseModalities',\n ]);\n if (parentObject !== undefined && fromResponseModalities != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'responseModalities'],\n fromResponseModalities,\n );\n }\n\n const fromTemperature = common.getValueByPath(fromObject, ['temperature']);\n if (parentObject !== undefined && fromTemperature != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'temperature'],\n fromTemperature,\n );\n }\n\n const fromTopP = common.getValueByPath(fromObject, ['topP']);\n if (parentObject !== undefined && fromTopP != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'topP'],\n fromTopP,\n );\n }\n\n const fromTopK = common.getValueByPath(fromObject, ['topK']);\n if (parentObject !== undefined && fromTopK != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'topK'],\n fromTopK,\n );\n }\n\n const fromMaxOutputTokens = common.getValueByPath(fromObject, [\n 'maxOutputTokens',\n ]);\n if (parentObject !== undefined && fromMaxOutputTokens != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'maxOutputTokens'],\n fromMaxOutputTokens,\n );\n }\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (parentObject !== undefined && fromMediaResolution != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'mediaResolution'],\n fromMediaResolution,\n );\n }\n\n const fromSeed = common.getValueByPath(fromObject, ['seed']);\n if (parentObject !== undefined && fromSeed != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'seed'],\n fromSeed,\n );\n }\n\n const fromSpeechConfig = common.getValueByPath(fromObject, ['speechConfig']);\n if (parentObject !== undefined && fromSpeechConfig != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'speechConfig'],\n t.tLiveSpeechConfig(fromSpeechConfig),\n );\n }\n\n const fromThinkingConfig = common.getValueByPath(fromObject, [\n 'thinkingConfig',\n ]);\n if (parentObject !== undefined && fromThinkingConfig != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'thinkingConfig'],\n fromThinkingConfig,\n );\n }\n\n const fromEnableAffectiveDialog = common.getValueByPath(fromObject, [\n 'enableAffectiveDialog',\n ]);\n if (parentObject !== undefined && fromEnableAffectiveDialog != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'enableAffectiveDialog'],\n fromEnableAffectiveDialog,\n );\n }\n\n const fromSystemInstruction = common.getValueByPath(fromObject, [\n 'systemInstruction',\n ]);\n if (parentObject !== undefined && fromSystemInstruction != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'systemInstruction'],\n t.tContent(fromSystemInstruction),\n );\n }\n\n const fromTools = common.getValueByPath(fromObject, ['tools']);\n if (parentObject !== undefined && fromTools != null) {\n let transformedList = t.tTools(fromTools);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return toolToVertex(t.tTool(item));\n });\n }\n common.setValueByPath(parentObject, ['setup', 'tools'], transformedList);\n }\n\n const fromSessionResumption = common.getValueByPath(fromObject, [\n 'sessionResumption',\n ]);\n if (parentObject !== undefined && fromSessionResumption != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'sessionResumption'],\n fromSessionResumption,\n );\n }\n\n const fromInputAudioTranscription = common.getValueByPath(fromObject, [\n 'inputAudioTranscription',\n ]);\n if (parentObject !== undefined && fromInputAudioTranscription != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'inputAudioTranscription'],\n fromInputAudioTranscription,\n );\n }\n\n const fromOutputAudioTranscription = common.getValueByPath(fromObject, [\n 'outputAudioTranscription',\n ]);\n if (parentObject !== undefined && fromOutputAudioTranscription != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'outputAudioTranscription'],\n fromOutputAudioTranscription,\n );\n }\n\n const fromRealtimeInputConfig = common.getValueByPath(fromObject, [\n 'realtimeInputConfig',\n ]);\n if (parentObject !== undefined && fromRealtimeInputConfig != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'realtimeInputConfig'],\n fromRealtimeInputConfig,\n );\n }\n\n const fromContextWindowCompression = common.getValueByPath(fromObject, [\n 'contextWindowCompression',\n ]);\n if (parentObject !== undefined && fromContextWindowCompression != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'contextWindowCompression'],\n fromContextWindowCompression,\n );\n }\n\n const fromProactivity = common.getValueByPath(fromObject, ['proactivity']);\n if (parentObject !== undefined && fromProactivity != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'proactivity'],\n fromProactivity,\n );\n }\n\n const fromExplicitVadSignal = common.getValueByPath(fromObject, [\n 'explicitVadSignal',\n ]);\n if (parentObject !== undefined && fromExplicitVadSignal != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'explicitVadSignal'],\n fromExplicitVadSignal,\n );\n }\n\n return toObject;\n}\n\nexport function liveConnectParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.LiveConnectParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['setup', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n common.setValueByPath(\n toObject,\n ['config'],\n liveConnectConfigToMldev(fromConfig, toObject),\n );\n }\n\n return toObject;\n}\n\nexport function liveConnectParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.LiveConnectParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['setup', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n common.setValueByPath(\n toObject,\n ['config'],\n liveConnectConfigToVertex(fromConfig, toObject),\n );\n }\n\n return toObject;\n}\n\nexport function liveMusicClientMessageToVertex(\n fromObject: types.LiveMusicClientMessage,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['setup']) !== undefined) {\n throw new Error('setup parameter is not supported in Vertex AI.');\n }\n\n if (common.getValueByPath(fromObject, ['clientContent']) !== undefined) {\n throw new Error('clientContent parameter is not supported in Vertex AI.');\n }\n\n if (\n common.getValueByPath(fromObject, ['musicGenerationConfig']) !== undefined\n ) {\n throw new Error(\n 'musicGenerationConfig parameter is not supported in Vertex AI.',\n );\n }\n\n if (common.getValueByPath(fromObject, ['playbackControl']) !== undefined) {\n throw new Error('playbackControl parameter is not supported in Vertex AI.');\n }\n\n return toObject;\n}\n\nexport function liveMusicConnectParametersToMldev(\n fromObject: types.LiveMusicConnectParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(toObject, ['setup', 'model'], fromModel);\n }\n\n const fromCallbacks = common.getValueByPath(fromObject, ['callbacks']);\n if (fromCallbacks != null) {\n common.setValueByPath(toObject, ['callbacks'], fromCallbacks);\n }\n\n return toObject;\n}\n\nexport function liveMusicConnectParametersToVertex(\n fromObject: types.LiveMusicConnectParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['model']) !== undefined) {\n throw new Error('model parameter is not supported in Vertex AI.');\n }\n\n if (common.getValueByPath(fromObject, ['callbacks']) !== undefined) {\n throw new Error('callbacks parameter is not supported in Vertex AI.');\n }\n\n return toObject;\n}\n\nexport function liveMusicSetConfigParametersToMldev(\n fromObject: types.LiveMusicSetConfigParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMusicGenerationConfig = common.getValueByPath(fromObject, [\n 'musicGenerationConfig',\n ]);\n if (fromMusicGenerationConfig != null) {\n common.setValueByPath(\n toObject,\n ['musicGenerationConfig'],\n fromMusicGenerationConfig,\n );\n }\n\n return toObject;\n}\n\nexport function liveMusicSetConfigParametersToVertex(\n fromObject: types.LiveMusicSetConfigParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (\n common.getValueByPath(fromObject, ['musicGenerationConfig']) !== undefined\n ) {\n throw new Error(\n 'musicGenerationConfig parameter is not supported in Vertex AI.',\n );\n }\n\n return toObject;\n}\n\nexport function liveMusicSetWeightedPromptsParametersToMldev(\n fromObject: types.LiveMusicSetWeightedPromptsParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromWeightedPrompts = common.getValueByPath(fromObject, [\n 'weightedPrompts',\n ]);\n if (fromWeightedPrompts != null) {\n let transformedList = fromWeightedPrompts;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['weightedPrompts'], transformedList);\n }\n\n return toObject;\n}\n\nexport function liveMusicSetWeightedPromptsParametersToVertex(\n fromObject: types.LiveMusicSetWeightedPromptsParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['weightedPrompts']) !== undefined) {\n throw new Error('weightedPrompts parameter is not supported in Vertex AI.');\n }\n\n return toObject;\n}\n\nexport function liveSendRealtimeInputParametersToMldev(\n fromObject: types.LiveSendRealtimeInputParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMedia = common.getValueByPath(fromObject, ['media']);\n if (fromMedia != null) {\n let transformedList = t.tBlobs(fromMedia);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return blobToMldev(item);\n });\n }\n common.setValueByPath(toObject, ['mediaChunks'], transformedList);\n }\n\n const fromAudio = common.getValueByPath(fromObject, ['audio']);\n if (fromAudio != null) {\n common.setValueByPath(\n toObject,\n ['audio'],\n blobToMldev(t.tAudioBlob(fromAudio)),\n );\n }\n\n const fromAudioStreamEnd = common.getValueByPath(fromObject, [\n 'audioStreamEnd',\n ]);\n if (fromAudioStreamEnd != null) {\n common.setValueByPath(toObject, ['audioStreamEnd'], fromAudioStreamEnd);\n }\n\n const fromVideo = common.getValueByPath(fromObject, ['video']);\n if (fromVideo != null) {\n common.setValueByPath(\n toObject,\n ['video'],\n blobToMldev(t.tImageBlob(fromVideo)),\n );\n }\n\n const fromText = common.getValueByPath(fromObject, ['text']);\n if (fromText != null) {\n common.setValueByPath(toObject, ['text'], fromText);\n }\n\n const fromActivityStart = common.getValueByPath(fromObject, [\n 'activityStart',\n ]);\n if (fromActivityStart != null) {\n common.setValueByPath(toObject, ['activityStart'], fromActivityStart);\n }\n\n const fromActivityEnd = common.getValueByPath(fromObject, ['activityEnd']);\n if (fromActivityEnd != null) {\n common.setValueByPath(toObject, ['activityEnd'], fromActivityEnd);\n }\n\n return toObject;\n}\n\nexport function liveSendRealtimeInputParametersToVertex(\n fromObject: types.LiveSendRealtimeInputParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMedia = common.getValueByPath(fromObject, ['media']);\n if (fromMedia != null) {\n let transformedList = t.tBlobs(fromMedia);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['mediaChunks'], transformedList);\n }\n\n const fromAudio = common.getValueByPath(fromObject, ['audio']);\n if (fromAudio != null) {\n common.setValueByPath(toObject, ['audio'], t.tAudioBlob(fromAudio));\n }\n\n const fromAudioStreamEnd = common.getValueByPath(fromObject, [\n 'audioStreamEnd',\n ]);\n if (fromAudioStreamEnd != null) {\n common.setValueByPath(toObject, ['audioStreamEnd'], fromAudioStreamEnd);\n }\n\n const fromVideo = common.getValueByPath(fromObject, ['video']);\n if (fromVideo != null) {\n common.setValueByPath(toObject, ['video'], t.tImageBlob(fromVideo));\n }\n\n const fromText = common.getValueByPath(fromObject, ['text']);\n if (fromText != null) {\n common.setValueByPath(toObject, ['text'], fromText);\n }\n\n const fromActivityStart = common.getValueByPath(fromObject, [\n 'activityStart',\n ]);\n if (fromActivityStart != null) {\n common.setValueByPath(toObject, ['activityStart'], fromActivityStart);\n }\n\n const fromActivityEnd = common.getValueByPath(fromObject, ['activityEnd']);\n if (fromActivityEnd != null) {\n common.setValueByPath(toObject, ['activityEnd'], fromActivityEnd);\n }\n\n return toObject;\n}\n\nexport function liveServerMessageFromMldev(\n fromObject: types.LiveServerMessage,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSetupComplete = common.getValueByPath(fromObject, [\n 'setupComplete',\n ]);\n if (fromSetupComplete != null) {\n common.setValueByPath(toObject, ['setupComplete'], fromSetupComplete);\n }\n\n const fromServerContent = common.getValueByPath(fromObject, [\n 'serverContent',\n ]);\n if (fromServerContent != null) {\n common.setValueByPath(toObject, ['serverContent'], fromServerContent);\n }\n\n const fromToolCall = common.getValueByPath(fromObject, ['toolCall']);\n if (fromToolCall != null) {\n common.setValueByPath(toObject, ['toolCall'], fromToolCall);\n }\n\n const fromToolCallCancellation = common.getValueByPath(fromObject, [\n 'toolCallCancellation',\n ]);\n if (fromToolCallCancellation != null) {\n common.setValueByPath(\n toObject,\n ['toolCallCancellation'],\n fromToolCallCancellation,\n );\n }\n\n const fromUsageMetadata = common.getValueByPath(fromObject, [\n 'usageMetadata',\n ]);\n if (fromUsageMetadata != null) {\n common.setValueByPath(toObject, ['usageMetadata'], fromUsageMetadata);\n }\n\n const fromGoAway = common.getValueByPath(fromObject, ['goAway']);\n if (fromGoAway != null) {\n common.setValueByPath(toObject, ['goAway'], fromGoAway);\n }\n\n const fromSessionResumptionUpdate = common.getValueByPath(fromObject, [\n 'sessionResumptionUpdate',\n ]);\n if (fromSessionResumptionUpdate != null) {\n common.setValueByPath(\n toObject,\n ['sessionResumptionUpdate'],\n fromSessionResumptionUpdate,\n );\n }\n\n const fromVoiceActivityDetectionSignal = common.getValueByPath(fromObject, [\n 'voiceActivityDetectionSignal',\n ]);\n if (fromVoiceActivityDetectionSignal != null) {\n common.setValueByPath(\n toObject,\n ['voiceActivityDetectionSignal'],\n fromVoiceActivityDetectionSignal,\n );\n }\n\n const fromVoiceActivity = common.getValueByPath(fromObject, [\n 'voiceActivity',\n ]);\n if (fromVoiceActivity != null) {\n common.setValueByPath(\n toObject,\n ['voiceActivity'],\n voiceActivityFromMldev(fromVoiceActivity),\n );\n }\n\n return toObject;\n}\n\nexport function liveServerMessageFromVertex(\n fromObject: types.LiveServerMessage,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSetupComplete = common.getValueByPath(fromObject, [\n 'setupComplete',\n ]);\n if (fromSetupComplete != null) {\n common.setValueByPath(toObject, ['setupComplete'], fromSetupComplete);\n }\n\n const fromServerContent = common.getValueByPath(fromObject, [\n 'serverContent',\n ]);\n if (fromServerContent != null) {\n common.setValueByPath(toObject, ['serverContent'], fromServerContent);\n }\n\n const fromToolCall = common.getValueByPath(fromObject, ['toolCall']);\n if (fromToolCall != null) {\n common.setValueByPath(toObject, ['toolCall'], fromToolCall);\n }\n\n const fromToolCallCancellation = common.getValueByPath(fromObject, [\n 'toolCallCancellation',\n ]);\n if (fromToolCallCancellation != null) {\n common.setValueByPath(\n toObject,\n ['toolCallCancellation'],\n fromToolCallCancellation,\n );\n }\n\n const fromUsageMetadata = common.getValueByPath(fromObject, [\n 'usageMetadata',\n ]);\n if (fromUsageMetadata != null) {\n common.setValueByPath(\n toObject,\n ['usageMetadata'],\n usageMetadataFromVertex(fromUsageMetadata),\n );\n }\n\n const fromGoAway = common.getValueByPath(fromObject, ['goAway']);\n if (fromGoAway != null) {\n common.setValueByPath(toObject, ['goAway'], fromGoAway);\n }\n\n const fromSessionResumptionUpdate = common.getValueByPath(fromObject, [\n 'sessionResumptionUpdate',\n ]);\n if (fromSessionResumptionUpdate != null) {\n common.setValueByPath(\n toObject,\n ['sessionResumptionUpdate'],\n fromSessionResumptionUpdate,\n );\n }\n\n const fromVoiceActivityDetectionSignal = common.getValueByPath(fromObject, [\n 'voiceActivityDetectionSignal',\n ]);\n if (fromVoiceActivityDetectionSignal != null) {\n common.setValueByPath(\n toObject,\n ['voiceActivityDetectionSignal'],\n fromVoiceActivityDetectionSignal,\n );\n }\n\n const fromVoiceActivity = common.getValueByPath(fromObject, [\n 'voiceActivity',\n ]);\n if (fromVoiceActivity != null) {\n common.setValueByPath(\n toObject,\n ['voiceActivity'],\n voiceActivityFromVertex(fromVoiceActivity),\n );\n }\n\n return toObject;\n}\n\nexport function partToMldev(fromObject: types.Part): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (fromMediaResolution != null) {\n common.setValueByPath(toObject, ['mediaResolution'], fromMediaResolution);\n }\n\n const fromCodeExecutionResult = common.getValueByPath(fromObject, [\n 'codeExecutionResult',\n ]);\n if (fromCodeExecutionResult != null) {\n common.setValueByPath(\n toObject,\n ['codeExecutionResult'],\n fromCodeExecutionResult,\n );\n }\n\n const fromExecutableCode = common.getValueByPath(fromObject, [\n 'executableCode',\n ]);\n if (fromExecutableCode != null) {\n common.setValueByPath(toObject, ['executableCode'], fromExecutableCode);\n }\n\n const fromFileData = common.getValueByPath(fromObject, ['fileData']);\n if (fromFileData != null) {\n common.setValueByPath(\n toObject,\n ['fileData'],\n fileDataToMldev(fromFileData),\n );\n }\n\n const fromFunctionCall = common.getValueByPath(fromObject, ['functionCall']);\n if (fromFunctionCall != null) {\n common.setValueByPath(\n toObject,\n ['functionCall'],\n functionCallToMldev(fromFunctionCall),\n );\n }\n\n const fromFunctionResponse = common.getValueByPath(fromObject, [\n 'functionResponse',\n ]);\n if (fromFunctionResponse != null) {\n common.setValueByPath(toObject, ['functionResponse'], fromFunctionResponse);\n }\n\n const fromInlineData = common.getValueByPath(fromObject, ['inlineData']);\n if (fromInlineData != null) {\n common.setValueByPath(\n toObject,\n ['inlineData'],\n blobToMldev(fromInlineData),\n );\n }\n\n const fromText = common.getValueByPath(fromObject, ['text']);\n if (fromText != null) {\n common.setValueByPath(toObject, ['text'], fromText);\n }\n\n const fromThought = common.getValueByPath(fromObject, ['thought']);\n if (fromThought != null) {\n common.setValueByPath(toObject, ['thought'], fromThought);\n }\n\n const fromThoughtSignature = common.getValueByPath(fromObject, [\n 'thoughtSignature',\n ]);\n if (fromThoughtSignature != null) {\n common.setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature);\n }\n\n const fromVideoMetadata = common.getValueByPath(fromObject, [\n 'videoMetadata',\n ]);\n if (fromVideoMetadata != null) {\n common.setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata);\n }\n\n return toObject;\n}\n\nexport function sessionResumptionConfigToMldev(\n fromObject: types.SessionResumptionConfig,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromHandle = common.getValueByPath(fromObject, ['handle']);\n if (fromHandle != null) {\n common.setValueByPath(toObject, ['handle'], fromHandle);\n }\n\n if (common.getValueByPath(fromObject, ['transparent']) !== undefined) {\n throw new Error('transparent parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function toolToMldev(fromObject: types.Tool): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['retrieval']) !== undefined) {\n throw new Error('retrieval parameter is not supported in Gemini API.');\n }\n\n const fromComputerUse = common.getValueByPath(fromObject, ['computerUse']);\n if (fromComputerUse != null) {\n common.setValueByPath(toObject, ['computerUse'], fromComputerUse);\n }\n\n const fromFileSearch = common.getValueByPath(fromObject, ['fileSearch']);\n if (fromFileSearch != null) {\n common.setValueByPath(toObject, ['fileSearch'], fromFileSearch);\n }\n\n const fromCodeExecution = common.getValueByPath(fromObject, [\n 'codeExecution',\n ]);\n if (fromCodeExecution != null) {\n common.setValueByPath(toObject, ['codeExecution'], fromCodeExecution);\n }\n\n if (\n common.getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined\n ) {\n throw new Error(\n 'enterpriseWebSearch parameter is not supported in Gemini API.',\n );\n }\n\n const fromFunctionDeclarations = common.getValueByPath(fromObject, [\n 'functionDeclarations',\n ]);\n if (fromFunctionDeclarations != null) {\n let transformedList = fromFunctionDeclarations;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['functionDeclarations'], transformedList);\n }\n\n const fromGoogleMaps = common.getValueByPath(fromObject, ['googleMaps']);\n if (fromGoogleMaps != null) {\n common.setValueByPath(\n toObject,\n ['googleMaps'],\n googleMapsToMldev(fromGoogleMaps),\n );\n }\n\n const fromGoogleSearch = common.getValueByPath(fromObject, ['googleSearch']);\n if (fromGoogleSearch != null) {\n common.setValueByPath(\n toObject,\n ['googleSearch'],\n googleSearchToMldev(fromGoogleSearch),\n );\n }\n\n const fromGoogleSearchRetrieval = common.getValueByPath(fromObject, [\n 'googleSearchRetrieval',\n ]);\n if (fromGoogleSearchRetrieval != null) {\n common.setValueByPath(\n toObject,\n ['googleSearchRetrieval'],\n fromGoogleSearchRetrieval,\n );\n }\n\n const fromUrlContext = common.getValueByPath(fromObject, ['urlContext']);\n if (fromUrlContext != null) {\n common.setValueByPath(toObject, ['urlContext'], fromUrlContext);\n }\n\n return toObject;\n}\n\nexport function toolToVertex(fromObject: types.Tool): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromRetrieval = common.getValueByPath(fromObject, ['retrieval']);\n if (fromRetrieval != null) {\n common.setValueByPath(toObject, ['retrieval'], fromRetrieval);\n }\n\n const fromComputerUse = common.getValueByPath(fromObject, ['computerUse']);\n if (fromComputerUse != null) {\n common.setValueByPath(toObject, ['computerUse'], fromComputerUse);\n }\n\n if (common.getValueByPath(fromObject, ['fileSearch']) !== undefined) {\n throw new Error('fileSearch parameter is not supported in Vertex AI.');\n }\n\n const fromCodeExecution = common.getValueByPath(fromObject, [\n 'codeExecution',\n ]);\n if (fromCodeExecution != null) {\n common.setValueByPath(toObject, ['codeExecution'], fromCodeExecution);\n }\n\n const fromEnterpriseWebSearch = common.getValueByPath(fromObject, [\n 'enterpriseWebSearch',\n ]);\n if (fromEnterpriseWebSearch != null) {\n common.setValueByPath(\n toObject,\n ['enterpriseWebSearch'],\n fromEnterpriseWebSearch,\n );\n }\n\n const fromFunctionDeclarations = common.getValueByPath(fromObject, [\n 'functionDeclarations',\n ]);\n if (fromFunctionDeclarations != null) {\n let transformedList = fromFunctionDeclarations;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return functionDeclarationToVertex(item);\n });\n }\n common.setValueByPath(toObject, ['functionDeclarations'], transformedList);\n }\n\n const fromGoogleMaps = common.getValueByPath(fromObject, ['googleMaps']);\n if (fromGoogleMaps != null) {\n common.setValueByPath(toObject, ['googleMaps'], fromGoogleMaps);\n }\n\n const fromGoogleSearch = common.getValueByPath(fromObject, ['googleSearch']);\n if (fromGoogleSearch != null) {\n common.setValueByPath(toObject, ['googleSearch'], fromGoogleSearch);\n }\n\n const fromGoogleSearchRetrieval = common.getValueByPath(fromObject, [\n 'googleSearchRetrieval',\n ]);\n if (fromGoogleSearchRetrieval != null) {\n common.setValueByPath(\n toObject,\n ['googleSearchRetrieval'],\n fromGoogleSearchRetrieval,\n );\n }\n\n const fromUrlContext = common.getValueByPath(fromObject, ['urlContext']);\n if (fromUrlContext != null) {\n common.setValueByPath(toObject, ['urlContext'], fromUrlContext);\n }\n\n return toObject;\n}\n\nexport function usageMetadataFromVertex(\n fromObject: types.UsageMetadata,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPromptTokenCount = common.getValueByPath(fromObject, [\n 'promptTokenCount',\n ]);\n if (fromPromptTokenCount != null) {\n common.setValueByPath(toObject, ['promptTokenCount'], fromPromptTokenCount);\n }\n\n const fromCachedContentTokenCount = common.getValueByPath(fromObject, [\n 'cachedContentTokenCount',\n ]);\n if (fromCachedContentTokenCount != null) {\n common.setValueByPath(\n toObject,\n ['cachedContentTokenCount'],\n fromCachedContentTokenCount,\n );\n }\n\n const fromResponseTokenCount = common.getValueByPath(fromObject, [\n 'candidatesTokenCount',\n ]);\n if (fromResponseTokenCount != null) {\n common.setValueByPath(\n toObject,\n ['responseTokenCount'],\n fromResponseTokenCount,\n );\n }\n\n const fromToolUsePromptTokenCount = common.getValueByPath(fromObject, [\n 'toolUsePromptTokenCount',\n ]);\n if (fromToolUsePromptTokenCount != null) {\n common.setValueByPath(\n toObject,\n ['toolUsePromptTokenCount'],\n fromToolUsePromptTokenCount,\n );\n }\n\n const fromThoughtsTokenCount = common.getValueByPath(fromObject, [\n 'thoughtsTokenCount',\n ]);\n if (fromThoughtsTokenCount != null) {\n common.setValueByPath(\n toObject,\n ['thoughtsTokenCount'],\n fromThoughtsTokenCount,\n );\n }\n\n const fromTotalTokenCount = common.getValueByPath(fromObject, [\n 'totalTokenCount',\n ]);\n if (fromTotalTokenCount != null) {\n common.setValueByPath(toObject, ['totalTokenCount'], fromTotalTokenCount);\n }\n\n const fromPromptTokensDetails = common.getValueByPath(fromObject, [\n 'promptTokensDetails',\n ]);\n if (fromPromptTokensDetails != null) {\n let transformedList = fromPromptTokensDetails;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['promptTokensDetails'], transformedList);\n }\n\n const fromCacheTokensDetails = common.getValueByPath(fromObject, [\n 'cacheTokensDetails',\n ]);\n if (fromCacheTokensDetails != null) {\n let transformedList = fromCacheTokensDetails;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['cacheTokensDetails'], transformedList);\n }\n\n const fromResponseTokensDetails = common.getValueByPath(fromObject, [\n 'candidatesTokensDetails',\n ]);\n if (fromResponseTokensDetails != null) {\n let transformedList = fromResponseTokensDetails;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['responseTokensDetails'], transformedList);\n }\n\n const fromToolUsePromptTokensDetails = common.getValueByPath(fromObject, [\n 'toolUsePromptTokensDetails',\n ]);\n if (fromToolUsePromptTokensDetails != null) {\n let transformedList = fromToolUsePromptTokensDetails;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(\n toObject,\n ['toolUsePromptTokensDetails'],\n transformedList,\n );\n }\n\n const fromTrafficType = common.getValueByPath(fromObject, ['trafficType']);\n if (fromTrafficType != null) {\n common.setValueByPath(toObject, ['trafficType'], fromTrafficType);\n }\n\n return toObject;\n}\n\nexport function voiceActivityFromMldev(\n fromObject: types.VoiceActivity,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromVoiceActivityType = common.getValueByPath(fromObject, ['type']);\n if (fromVoiceActivityType != null) {\n common.setValueByPath(\n toObject,\n ['voiceActivityType'],\n fromVoiceActivityType,\n );\n }\n\n return toObject;\n}\n\nexport function voiceActivityFromVertex(\n fromObject: types.VoiceActivity,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromVoiceActivityType = common.getValueByPath(fromObject, ['type']);\n if (fromVoiceActivityType != null) {\n common.setValueByPath(\n toObject,\n ['voiceActivityType'],\n fromVoiceActivityType,\n );\n }\n\n return toObject;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport {ApiClient} from '../_api_client.js';\nimport * as common from '../_common.js';\nimport type * as _internal_types from '../_internal_types.js';\nimport * as t from '../_transformers.js';\nimport type * as types from '../types.js';\n\nexport function blobToMldev(\n fromObject: types.Blob,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromData = common.getValueByPath(fromObject, ['data']);\n if (fromData != null) {\n common.setValueByPath(toObject, ['data'], fromData);\n }\n\n if (common.getValueByPath(fromObject, ['displayName']) !== undefined) {\n throw new Error('displayName parameter is not supported in Gemini API.');\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function candidateFromMldev(\n fromObject: types.Candidate,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromContent = common.getValueByPath(fromObject, ['content']);\n if (fromContent != null) {\n common.setValueByPath(toObject, ['content'], fromContent);\n }\n\n const fromCitationMetadata = common.getValueByPath(fromObject, [\n 'citationMetadata',\n ]);\n if (fromCitationMetadata != null) {\n common.setValueByPath(\n toObject,\n ['citationMetadata'],\n citationMetadataFromMldev(fromCitationMetadata, rootObject),\n );\n }\n\n const fromTokenCount = common.getValueByPath(fromObject, ['tokenCount']);\n if (fromTokenCount != null) {\n common.setValueByPath(toObject, ['tokenCount'], fromTokenCount);\n }\n\n const fromFinishReason = common.getValueByPath(fromObject, ['finishReason']);\n if (fromFinishReason != null) {\n common.setValueByPath(toObject, ['finishReason'], fromFinishReason);\n }\n\n const fromAvgLogprobs = common.getValueByPath(fromObject, ['avgLogprobs']);\n if (fromAvgLogprobs != null) {\n common.setValueByPath(toObject, ['avgLogprobs'], fromAvgLogprobs);\n }\n\n const fromGroundingMetadata = common.getValueByPath(fromObject, [\n 'groundingMetadata',\n ]);\n if (fromGroundingMetadata != null) {\n common.setValueByPath(\n toObject,\n ['groundingMetadata'],\n fromGroundingMetadata,\n );\n }\n\n const fromIndex = common.getValueByPath(fromObject, ['index']);\n if (fromIndex != null) {\n common.setValueByPath(toObject, ['index'], fromIndex);\n }\n\n const fromLogprobsResult = common.getValueByPath(fromObject, [\n 'logprobsResult',\n ]);\n if (fromLogprobsResult != null) {\n common.setValueByPath(toObject, ['logprobsResult'], fromLogprobsResult);\n }\n\n const fromSafetyRatings = common.getValueByPath(fromObject, [\n 'safetyRatings',\n ]);\n if (fromSafetyRatings != null) {\n let transformedList = fromSafetyRatings;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['safetyRatings'], transformedList);\n }\n\n const fromUrlContextMetadata = common.getValueByPath(fromObject, [\n 'urlContextMetadata',\n ]);\n if (fromUrlContextMetadata != null) {\n common.setValueByPath(\n toObject,\n ['urlContextMetadata'],\n fromUrlContextMetadata,\n );\n }\n\n return toObject;\n}\n\nexport function citationMetadataFromMldev(\n fromObject: types.CitationMetadata,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromCitations = common.getValueByPath(fromObject, ['citationSources']);\n if (fromCitations != null) {\n let transformedList = fromCitations;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['citations'], transformedList);\n }\n\n return toObject;\n}\n\nexport function computeTokensParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.ComputeTokensParameters,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromContents = common.getValueByPath(fromObject, ['contents']);\n if (fromContents != null) {\n let transformedList = t.tContents(fromContents);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['contents'], transformedList);\n }\n\n return toObject;\n}\n\nexport function computeTokensResponseFromVertex(\n fromObject: types.ComputeTokensResponse,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromTokensInfo = common.getValueByPath(fromObject, ['tokensInfo']);\n if (fromTokensInfo != null) {\n let transformedList = fromTokensInfo;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['tokensInfo'], transformedList);\n }\n\n return toObject;\n}\n\nexport function contentEmbeddingFromVertex(\n fromObject: types.ContentEmbedding,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromValues = common.getValueByPath(fromObject, ['values']);\n if (fromValues != null) {\n common.setValueByPath(toObject, ['values'], fromValues);\n }\n\n const fromStatistics = common.getValueByPath(fromObject, ['statistics']);\n if (fromStatistics != null) {\n common.setValueByPath(\n toObject,\n ['statistics'],\n contentEmbeddingStatisticsFromVertex(fromStatistics, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function contentEmbeddingStatisticsFromVertex(\n fromObject: types.ContentEmbeddingStatistics,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromTruncated = common.getValueByPath(fromObject, ['truncated']);\n if (fromTruncated != null) {\n common.setValueByPath(toObject, ['truncated'], fromTruncated);\n }\n\n const fromTokenCount = common.getValueByPath(fromObject, ['token_count']);\n if (fromTokenCount != null) {\n common.setValueByPath(toObject, ['tokenCount'], fromTokenCount);\n }\n\n return toObject;\n}\n\nexport function contentToMldev(\n fromObject: types.Content,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromParts = common.getValueByPath(fromObject, ['parts']);\n if (fromParts != null) {\n let transformedList = fromParts;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return partToMldev(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['parts'], transformedList);\n }\n\n const fromRole = common.getValueByPath(fromObject, ['role']);\n if (fromRole != null) {\n common.setValueByPath(toObject, ['role'], fromRole);\n }\n\n return toObject;\n}\n\nexport function controlReferenceConfigToVertex(\n fromObject: types.ControlReferenceConfig,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromControlType = common.getValueByPath(fromObject, ['controlType']);\n if (fromControlType != null) {\n common.setValueByPath(toObject, ['controlType'], fromControlType);\n }\n\n const fromEnableControlImageComputation = common.getValueByPath(fromObject, [\n 'enableControlImageComputation',\n ]);\n if (fromEnableControlImageComputation != null) {\n common.setValueByPath(\n toObject,\n ['computeControl'],\n fromEnableControlImageComputation,\n );\n }\n\n return toObject;\n}\n\nexport function countTokensConfigToMldev(\n fromObject: types.CountTokensConfig,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['systemInstruction']) !== undefined) {\n throw new Error(\n 'systemInstruction parameter is not supported in Gemini API.',\n );\n }\n\n if (common.getValueByPath(fromObject, ['tools']) !== undefined) {\n throw new Error('tools parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['generationConfig']) !== undefined) {\n throw new Error(\n 'generationConfig parameter is not supported in Gemini API.',\n );\n }\n\n return toObject;\n}\n\nexport function countTokensConfigToVertex(\n fromObject: types.CountTokensConfig,\n parentObject: Record<string, unknown>,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSystemInstruction = common.getValueByPath(fromObject, [\n 'systemInstruction',\n ]);\n if (parentObject !== undefined && fromSystemInstruction != null) {\n common.setValueByPath(\n parentObject,\n ['systemInstruction'],\n t.tContent(fromSystemInstruction),\n );\n }\n\n const fromTools = common.getValueByPath(fromObject, ['tools']);\n if (parentObject !== undefined && fromTools != null) {\n let transformedList = fromTools;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return toolToVertex(item, rootObject);\n });\n }\n common.setValueByPath(parentObject, ['tools'], transformedList);\n }\n\n const fromGenerationConfig = common.getValueByPath(fromObject, [\n 'generationConfig',\n ]);\n if (parentObject !== undefined && fromGenerationConfig != null) {\n common.setValueByPath(\n parentObject,\n ['generationConfig'],\n generationConfigToVertex(fromGenerationConfig, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function countTokensParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.CountTokensParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromContents = common.getValueByPath(fromObject, ['contents']);\n if (fromContents != null) {\n let transformedList = t.tContents(fromContents);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return contentToMldev(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['contents'], transformedList);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n countTokensConfigToMldev(fromConfig, rootObject);\n }\n\n return toObject;\n}\n\nexport function countTokensParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.CountTokensParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromContents = common.getValueByPath(fromObject, ['contents']);\n if (fromContents != null) {\n let transformedList = t.tContents(fromContents);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['contents'], transformedList);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n countTokensConfigToVertex(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function countTokensResponseFromMldev(\n fromObject: types.CountTokensResponse,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromTotalTokens = common.getValueByPath(fromObject, ['totalTokens']);\n if (fromTotalTokens != null) {\n common.setValueByPath(toObject, ['totalTokens'], fromTotalTokens);\n }\n\n const fromCachedContentTokenCount = common.getValueByPath(fromObject, [\n 'cachedContentTokenCount',\n ]);\n if (fromCachedContentTokenCount != null) {\n common.setValueByPath(\n toObject,\n ['cachedContentTokenCount'],\n fromCachedContentTokenCount,\n );\n }\n\n return toObject;\n}\n\nexport function countTokensResponseFromVertex(\n fromObject: types.CountTokensResponse,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromTotalTokens = common.getValueByPath(fromObject, ['totalTokens']);\n if (fromTotalTokens != null) {\n common.setValueByPath(toObject, ['totalTokens'], fromTotalTokens);\n }\n\n return toObject;\n}\n\nexport function deleteModelParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.DeleteModelParameters,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n return toObject;\n}\n\nexport function deleteModelParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.DeleteModelParameters,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n return toObject;\n}\n\nexport function deleteModelResponseFromMldev(\n fromObject: types.DeleteModelResponse,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n return toObject;\n}\n\nexport function deleteModelResponseFromVertex(\n fromObject: types.DeleteModelResponse,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n return toObject;\n}\n\nexport function editImageConfigToVertex(\n fromObject: types.EditImageConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromOutputGcsUri = common.getValueByPath(fromObject, ['outputGcsUri']);\n if (parentObject !== undefined && fromOutputGcsUri != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'storageUri'],\n fromOutputGcsUri,\n );\n }\n\n const fromNegativePrompt = common.getValueByPath(fromObject, [\n 'negativePrompt',\n ]);\n if (parentObject !== undefined && fromNegativePrompt != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'negativePrompt'],\n fromNegativePrompt,\n );\n }\n\n const fromNumberOfImages = common.getValueByPath(fromObject, [\n 'numberOfImages',\n ]);\n if (parentObject !== undefined && fromNumberOfImages != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'sampleCount'],\n fromNumberOfImages,\n );\n }\n\n const fromAspectRatio = common.getValueByPath(fromObject, ['aspectRatio']);\n if (parentObject !== undefined && fromAspectRatio != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'aspectRatio'],\n fromAspectRatio,\n );\n }\n\n const fromGuidanceScale = common.getValueByPath(fromObject, [\n 'guidanceScale',\n ]);\n if (parentObject !== undefined && fromGuidanceScale != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'guidanceScale'],\n fromGuidanceScale,\n );\n }\n\n const fromSeed = common.getValueByPath(fromObject, ['seed']);\n if (parentObject !== undefined && fromSeed != null) {\n common.setValueByPath(parentObject, ['parameters', 'seed'], fromSeed);\n }\n\n const fromSafetyFilterLevel = common.getValueByPath(fromObject, [\n 'safetyFilterLevel',\n ]);\n if (parentObject !== undefined && fromSafetyFilterLevel != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'safetySetting'],\n fromSafetyFilterLevel,\n );\n }\n\n const fromPersonGeneration = common.getValueByPath(fromObject, [\n 'personGeneration',\n ]);\n if (parentObject !== undefined && fromPersonGeneration != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'personGeneration'],\n fromPersonGeneration,\n );\n }\n\n const fromIncludeSafetyAttributes = common.getValueByPath(fromObject, [\n 'includeSafetyAttributes',\n ]);\n if (parentObject !== undefined && fromIncludeSafetyAttributes != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'includeSafetyAttributes'],\n fromIncludeSafetyAttributes,\n );\n }\n\n const fromIncludeRaiReason = common.getValueByPath(fromObject, [\n 'includeRaiReason',\n ]);\n if (parentObject !== undefined && fromIncludeRaiReason != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'includeRaiReason'],\n fromIncludeRaiReason,\n );\n }\n\n const fromLanguage = common.getValueByPath(fromObject, ['language']);\n if (parentObject !== undefined && fromLanguage != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'language'],\n fromLanguage,\n );\n }\n\n const fromOutputMimeType = common.getValueByPath(fromObject, [\n 'outputMimeType',\n ]);\n if (parentObject !== undefined && fromOutputMimeType != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'outputOptions', 'mimeType'],\n fromOutputMimeType,\n );\n }\n\n const fromOutputCompressionQuality = common.getValueByPath(fromObject, [\n 'outputCompressionQuality',\n ]);\n if (parentObject !== undefined && fromOutputCompressionQuality != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'outputOptions', 'compressionQuality'],\n fromOutputCompressionQuality,\n );\n }\n\n const fromAddWatermark = common.getValueByPath(fromObject, ['addWatermark']);\n if (parentObject !== undefined && fromAddWatermark != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'addWatermark'],\n fromAddWatermark,\n );\n }\n\n const fromLabels = common.getValueByPath(fromObject, ['labels']);\n if (parentObject !== undefined && fromLabels != null) {\n common.setValueByPath(parentObject, ['labels'], fromLabels);\n }\n\n const fromEditMode = common.getValueByPath(fromObject, ['editMode']);\n if (parentObject !== undefined && fromEditMode != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'editMode'],\n fromEditMode,\n );\n }\n\n const fromBaseSteps = common.getValueByPath(fromObject, ['baseSteps']);\n if (parentObject !== undefined && fromBaseSteps != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'editConfig', 'baseSteps'],\n fromBaseSteps,\n );\n }\n\n return toObject;\n}\n\nexport function editImageParametersInternalToVertex(\n apiClient: ApiClient,\n fromObject: _internal_types.EditImageParametersInternal,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromPrompt = common.getValueByPath(fromObject, ['prompt']);\n if (fromPrompt != null) {\n common.setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt);\n }\n\n const fromReferenceImages = common.getValueByPath(fromObject, [\n 'referenceImages',\n ]);\n if (fromReferenceImages != null) {\n let transformedList = fromReferenceImages;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return referenceImageAPIInternalToVertex(item, rootObject);\n });\n }\n common.setValueByPath(\n toObject,\n ['instances[0]', 'referenceImages'],\n transformedList,\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n editImageConfigToVertex(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function editImageResponseFromVertex(\n fromObject: types.EditImageResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromGeneratedImages = common.getValueByPath(fromObject, [\n 'predictions',\n ]);\n if (fromGeneratedImages != null) {\n let transformedList = fromGeneratedImages;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return generatedImageFromVertex(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['generatedImages'], transformedList);\n }\n\n return toObject;\n}\n\nexport function embedContentConfigToMldev(\n fromObject: types.EmbedContentConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromTaskType = common.getValueByPath(fromObject, ['taskType']);\n if (parentObject !== undefined && fromTaskType != null) {\n common.setValueByPath(\n parentObject,\n ['requests[]', 'taskType'],\n fromTaskType,\n );\n }\n\n const fromTitle = common.getValueByPath(fromObject, ['title']);\n if (parentObject !== undefined && fromTitle != null) {\n common.setValueByPath(parentObject, ['requests[]', 'title'], fromTitle);\n }\n\n const fromOutputDimensionality = common.getValueByPath(fromObject, [\n 'outputDimensionality',\n ]);\n if (parentObject !== undefined && fromOutputDimensionality != null) {\n common.setValueByPath(\n parentObject,\n ['requests[]', 'outputDimensionality'],\n fromOutputDimensionality,\n );\n }\n\n if (common.getValueByPath(fromObject, ['mimeType']) !== undefined) {\n throw new Error('mimeType parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['autoTruncate']) !== undefined) {\n throw new Error('autoTruncate parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function embedContentConfigToVertex(\n fromObject: types.EmbedContentConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromTaskType = common.getValueByPath(fromObject, ['taskType']);\n if (parentObject !== undefined && fromTaskType != null) {\n common.setValueByPath(\n parentObject,\n ['instances[]', 'task_type'],\n fromTaskType,\n );\n }\n\n const fromTitle = common.getValueByPath(fromObject, ['title']);\n if (parentObject !== undefined && fromTitle != null) {\n common.setValueByPath(parentObject, ['instances[]', 'title'], fromTitle);\n }\n\n const fromOutputDimensionality = common.getValueByPath(fromObject, [\n 'outputDimensionality',\n ]);\n if (parentObject !== undefined && fromOutputDimensionality != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'outputDimensionality'],\n fromOutputDimensionality,\n );\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (parentObject !== undefined && fromMimeType != null) {\n common.setValueByPath(\n parentObject,\n ['instances[]', 'mimeType'],\n fromMimeType,\n );\n }\n\n const fromAutoTruncate = common.getValueByPath(fromObject, ['autoTruncate']);\n if (parentObject !== undefined && fromAutoTruncate != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'autoTruncate'],\n fromAutoTruncate,\n );\n }\n\n return toObject;\n}\n\nexport function embedContentParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.EmbedContentParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromContents = common.getValueByPath(fromObject, ['contents']);\n if (fromContents != null) {\n let transformedList = t.tContentsForEmbed(apiClient, fromContents);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['requests[]', 'content'], transformedList);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n embedContentConfigToMldev(fromConfig, toObject, rootObject);\n }\n\n const fromModelForEmbedContent = common.getValueByPath(fromObject, ['model']);\n if (fromModelForEmbedContent !== undefined) {\n common.setValueByPath(\n toObject,\n ['requests[]', 'model'],\n t.tModel(apiClient, fromModelForEmbedContent),\n );\n }\n\n return toObject;\n}\n\nexport function embedContentParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.EmbedContentParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromContents = common.getValueByPath(fromObject, ['contents']);\n if (fromContents != null) {\n let transformedList = t.tContentsForEmbed(apiClient, fromContents);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(\n toObject,\n ['instances[]', 'content'],\n transformedList,\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n embedContentConfigToVertex(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function embedContentResponseFromMldev(\n fromObject: types.EmbedContentResponse,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromEmbeddings = common.getValueByPath(fromObject, ['embeddings']);\n if (fromEmbeddings != null) {\n let transformedList = fromEmbeddings;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['embeddings'], transformedList);\n }\n\n const fromMetadata = common.getValueByPath(fromObject, ['metadata']);\n if (fromMetadata != null) {\n common.setValueByPath(toObject, ['metadata'], fromMetadata);\n }\n\n return toObject;\n}\n\nexport function embedContentResponseFromVertex(\n fromObject: types.EmbedContentResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromEmbeddings = common.getValueByPath(fromObject, [\n 'predictions[]',\n 'embeddings',\n ]);\n if (fromEmbeddings != null) {\n let transformedList = fromEmbeddings;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return contentEmbeddingFromVertex(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['embeddings'], transformedList);\n }\n\n const fromMetadata = common.getValueByPath(fromObject, ['metadata']);\n if (fromMetadata != null) {\n common.setValueByPath(toObject, ['metadata'], fromMetadata);\n }\n\n return toObject;\n}\n\nexport function endpointFromVertex(\n fromObject: types.Endpoint,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['endpoint']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromDeployedModelId = common.getValueByPath(fromObject, [\n 'deployedModelId',\n ]);\n if (fromDeployedModelId != null) {\n common.setValueByPath(toObject, ['deployedModelId'], fromDeployedModelId);\n }\n\n return toObject;\n}\n\nexport function fileDataToMldev(\n fromObject: types.FileData,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['displayName']) !== undefined) {\n throw new Error('displayName parameter is not supported in Gemini API.');\n }\n\n const fromFileUri = common.getValueByPath(fromObject, ['fileUri']);\n if (fromFileUri != null) {\n common.setValueByPath(toObject, ['fileUri'], fromFileUri);\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function functionCallToMldev(\n fromObject: types.FunctionCall,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromId = common.getValueByPath(fromObject, ['id']);\n if (fromId != null) {\n common.setValueByPath(toObject, ['id'], fromId);\n }\n\n const fromArgs = common.getValueByPath(fromObject, ['args']);\n if (fromArgs != null) {\n common.setValueByPath(toObject, ['args'], fromArgs);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n if (common.getValueByPath(fromObject, ['partialArgs']) !== undefined) {\n throw new Error('partialArgs parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['willContinue']) !== undefined) {\n throw new Error('willContinue parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function functionCallingConfigToMldev(\n fromObject: types.FunctionCallingConfig,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromAllowedFunctionNames = common.getValueByPath(fromObject, [\n 'allowedFunctionNames',\n ]);\n if (fromAllowedFunctionNames != null) {\n common.setValueByPath(\n toObject,\n ['allowedFunctionNames'],\n fromAllowedFunctionNames,\n );\n }\n\n const fromMode = common.getValueByPath(fromObject, ['mode']);\n if (fromMode != null) {\n common.setValueByPath(toObject, ['mode'], fromMode);\n }\n\n if (\n common.getValueByPath(fromObject, ['streamFunctionCallArguments']) !==\n undefined\n ) {\n throw new Error(\n 'streamFunctionCallArguments parameter is not supported in Gemini API.',\n );\n }\n\n return toObject;\n}\n\nexport function functionDeclarationToVertex(\n fromObject: types.FunctionDeclaration,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromDescription = common.getValueByPath(fromObject, ['description']);\n if (fromDescription != null) {\n common.setValueByPath(toObject, ['description'], fromDescription);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromParameters = common.getValueByPath(fromObject, ['parameters']);\n if (fromParameters != null) {\n common.setValueByPath(toObject, ['parameters'], fromParameters);\n }\n\n const fromParametersJsonSchema = common.getValueByPath(fromObject, [\n 'parametersJsonSchema',\n ]);\n if (fromParametersJsonSchema != null) {\n common.setValueByPath(\n toObject,\n ['parametersJsonSchema'],\n fromParametersJsonSchema,\n );\n }\n\n const fromResponse = common.getValueByPath(fromObject, ['response']);\n if (fromResponse != null) {\n common.setValueByPath(toObject, ['response'], fromResponse);\n }\n\n const fromResponseJsonSchema = common.getValueByPath(fromObject, [\n 'responseJsonSchema',\n ]);\n if (fromResponseJsonSchema != null) {\n common.setValueByPath(\n toObject,\n ['responseJsonSchema'],\n fromResponseJsonSchema,\n );\n }\n\n if (common.getValueByPath(fromObject, ['behavior']) !== undefined) {\n throw new Error('behavior parameter is not supported in Vertex AI.');\n }\n\n return toObject;\n}\n\nexport function generateContentConfigToMldev(\n apiClient: ApiClient,\n fromObject: types.GenerateContentConfig,\n parentObject: Record<string, unknown>,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSystemInstruction = common.getValueByPath(fromObject, [\n 'systemInstruction',\n ]);\n if (parentObject !== undefined && fromSystemInstruction != null) {\n common.setValueByPath(\n parentObject,\n ['systemInstruction'],\n contentToMldev(t.tContent(fromSystemInstruction), rootObject),\n );\n }\n\n const fromTemperature = common.getValueByPath(fromObject, ['temperature']);\n if (fromTemperature != null) {\n common.setValueByPath(toObject, ['temperature'], fromTemperature);\n }\n\n const fromTopP = common.getValueByPath(fromObject, ['topP']);\n if (fromTopP != null) {\n common.setValueByPath(toObject, ['topP'], fromTopP);\n }\n\n const fromTopK = common.getValueByPath(fromObject, ['topK']);\n if (fromTopK != null) {\n common.setValueByPath(toObject, ['topK'], fromTopK);\n }\n\n const fromCandidateCount = common.getValueByPath(fromObject, [\n 'candidateCount',\n ]);\n if (fromCandidateCount != null) {\n common.setValueByPath(toObject, ['candidateCount'], fromCandidateCount);\n }\n\n const fromMaxOutputTokens = common.getValueByPath(fromObject, [\n 'maxOutputTokens',\n ]);\n if (fromMaxOutputTokens != null) {\n common.setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens);\n }\n\n const fromStopSequences = common.getValueByPath(fromObject, [\n 'stopSequences',\n ]);\n if (fromStopSequences != null) {\n common.setValueByPath(toObject, ['stopSequences'], fromStopSequences);\n }\n\n const fromResponseLogprobs = common.getValueByPath(fromObject, [\n 'responseLogprobs',\n ]);\n if (fromResponseLogprobs != null) {\n common.setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs);\n }\n\n const fromLogprobs = common.getValueByPath(fromObject, ['logprobs']);\n if (fromLogprobs != null) {\n common.setValueByPath(toObject, ['logprobs'], fromLogprobs);\n }\n\n const fromPresencePenalty = common.getValueByPath(fromObject, [\n 'presencePenalty',\n ]);\n if (fromPresencePenalty != null) {\n common.setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty);\n }\n\n const fromFrequencyPenalty = common.getValueByPath(fromObject, [\n 'frequencyPenalty',\n ]);\n if (fromFrequencyPenalty != null) {\n common.setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty);\n }\n\n const fromSeed = common.getValueByPath(fromObject, ['seed']);\n if (fromSeed != null) {\n common.setValueByPath(toObject, ['seed'], fromSeed);\n }\n\n const fromResponseMimeType = common.getValueByPath(fromObject, [\n 'responseMimeType',\n ]);\n if (fromResponseMimeType != null) {\n common.setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType);\n }\n\n const fromResponseSchema = common.getValueByPath(fromObject, [\n 'responseSchema',\n ]);\n if (fromResponseSchema != null) {\n common.setValueByPath(\n toObject,\n ['responseSchema'],\n t.tSchema(fromResponseSchema),\n );\n }\n\n const fromResponseJsonSchema = common.getValueByPath(fromObject, [\n 'responseJsonSchema',\n ]);\n if (fromResponseJsonSchema != null) {\n common.setValueByPath(\n toObject,\n ['responseJsonSchema'],\n fromResponseJsonSchema,\n );\n }\n\n if (common.getValueByPath(fromObject, ['routingConfig']) !== undefined) {\n throw new Error('routingConfig parameter is not supported in Gemini API.');\n }\n\n if (\n common.getValueByPath(fromObject, ['modelSelectionConfig']) !== undefined\n ) {\n throw new Error(\n 'modelSelectionConfig parameter is not supported in Gemini API.',\n );\n }\n\n const fromSafetySettings = common.getValueByPath(fromObject, [\n 'safetySettings',\n ]);\n if (parentObject !== undefined && fromSafetySettings != null) {\n let transformedList = fromSafetySettings;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return safetySettingToMldev(item, rootObject);\n });\n }\n common.setValueByPath(parentObject, ['safetySettings'], transformedList);\n }\n\n const fromTools = common.getValueByPath(fromObject, ['tools']);\n if (parentObject !== undefined && fromTools != null) {\n let transformedList = t.tTools(fromTools);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return toolToMldev(t.tTool(item), rootObject);\n });\n }\n common.setValueByPath(parentObject, ['tools'], transformedList);\n }\n\n const fromToolConfig = common.getValueByPath(fromObject, ['toolConfig']);\n if (parentObject !== undefined && fromToolConfig != null) {\n common.setValueByPath(\n parentObject,\n ['toolConfig'],\n toolConfigToMldev(fromToolConfig, rootObject),\n );\n }\n\n if (common.getValueByPath(fromObject, ['labels']) !== undefined) {\n throw new Error('labels parameter is not supported in Gemini API.');\n }\n\n const fromCachedContent = common.getValueByPath(fromObject, [\n 'cachedContent',\n ]);\n if (parentObject !== undefined && fromCachedContent != null) {\n common.setValueByPath(\n parentObject,\n ['cachedContent'],\n t.tCachedContentName(apiClient, fromCachedContent),\n );\n }\n\n const fromResponseModalities = common.getValueByPath(fromObject, [\n 'responseModalities',\n ]);\n if (fromResponseModalities != null) {\n common.setValueByPath(\n toObject,\n ['responseModalities'],\n fromResponseModalities,\n );\n }\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (fromMediaResolution != null) {\n common.setValueByPath(toObject, ['mediaResolution'], fromMediaResolution);\n }\n\n const fromSpeechConfig = common.getValueByPath(fromObject, ['speechConfig']);\n if (fromSpeechConfig != null) {\n common.setValueByPath(\n toObject,\n ['speechConfig'],\n t.tSpeechConfig(fromSpeechConfig),\n );\n }\n\n if (common.getValueByPath(fromObject, ['audioTimestamp']) !== undefined) {\n throw new Error('audioTimestamp parameter is not supported in Gemini API.');\n }\n\n const fromThinkingConfig = common.getValueByPath(fromObject, [\n 'thinkingConfig',\n ]);\n if (fromThinkingConfig != null) {\n common.setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig);\n }\n\n const fromImageConfig = common.getValueByPath(fromObject, ['imageConfig']);\n if (fromImageConfig != null) {\n common.setValueByPath(\n toObject,\n ['imageConfig'],\n imageConfigToMldev(fromImageConfig, rootObject),\n );\n }\n\n const fromEnableEnhancedCivicAnswers = common.getValueByPath(fromObject, [\n 'enableEnhancedCivicAnswers',\n ]);\n if (fromEnableEnhancedCivicAnswers != null) {\n common.setValueByPath(\n toObject,\n ['enableEnhancedCivicAnswers'],\n fromEnableEnhancedCivicAnswers,\n );\n }\n\n if (common.getValueByPath(fromObject, ['modelArmorConfig']) !== undefined) {\n throw new Error(\n 'modelArmorConfig parameter is not supported in Gemini API.',\n );\n }\n\n return toObject;\n}\n\nexport function generateContentConfigToVertex(\n apiClient: ApiClient,\n fromObject: types.GenerateContentConfig,\n parentObject: Record<string, unknown>,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSystemInstruction = common.getValueByPath(fromObject, [\n 'systemInstruction',\n ]);\n if (parentObject !== undefined && fromSystemInstruction != null) {\n common.setValueByPath(\n parentObject,\n ['systemInstruction'],\n t.tContent(fromSystemInstruction),\n );\n }\n\n const fromTemperature = common.getValueByPath(fromObject, ['temperature']);\n if (fromTemperature != null) {\n common.setValueByPath(toObject, ['temperature'], fromTemperature);\n }\n\n const fromTopP = common.getValueByPath(fromObject, ['topP']);\n if (fromTopP != null) {\n common.setValueByPath(toObject, ['topP'], fromTopP);\n }\n\n const fromTopK = common.getValueByPath(fromObject, ['topK']);\n if (fromTopK != null) {\n common.setValueByPath(toObject, ['topK'], fromTopK);\n }\n\n const fromCandidateCount = common.getValueByPath(fromObject, [\n 'candidateCount',\n ]);\n if (fromCandidateCount != null) {\n common.setValueByPath(toObject, ['candidateCount'], fromCandidateCount);\n }\n\n const fromMaxOutputTokens = common.getValueByPath(fromObject, [\n 'maxOutputTokens',\n ]);\n if (fromMaxOutputTokens != null) {\n common.setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens);\n }\n\n const fromStopSequences = common.getValueByPath(fromObject, [\n 'stopSequences',\n ]);\n if (fromStopSequences != null) {\n common.setValueByPath(toObject, ['stopSequences'], fromStopSequences);\n }\n\n const fromResponseLogprobs = common.getValueByPath(fromObject, [\n 'responseLogprobs',\n ]);\n if (fromResponseLogprobs != null) {\n common.setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs);\n }\n\n const fromLogprobs = common.getValueByPath(fromObject, ['logprobs']);\n if (fromLogprobs != null) {\n common.setValueByPath(toObject, ['logprobs'], fromLogprobs);\n }\n\n const fromPresencePenalty = common.getValueByPath(fromObject, [\n 'presencePenalty',\n ]);\n if (fromPresencePenalty != null) {\n common.setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty);\n }\n\n const fromFrequencyPenalty = common.getValueByPath(fromObject, [\n 'frequencyPenalty',\n ]);\n if (fromFrequencyPenalty != null) {\n common.setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty);\n }\n\n const fromSeed = common.getValueByPath(fromObject, ['seed']);\n if (fromSeed != null) {\n common.setValueByPath(toObject, ['seed'], fromSeed);\n }\n\n const fromResponseMimeType = common.getValueByPath(fromObject, [\n 'responseMimeType',\n ]);\n if (fromResponseMimeType != null) {\n common.setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType);\n }\n\n const fromResponseSchema = common.getValueByPath(fromObject, [\n 'responseSchema',\n ]);\n if (fromResponseSchema != null) {\n common.setValueByPath(\n toObject,\n ['responseSchema'],\n t.tSchema(fromResponseSchema),\n );\n }\n\n const fromResponseJsonSchema = common.getValueByPath(fromObject, [\n 'responseJsonSchema',\n ]);\n if (fromResponseJsonSchema != null) {\n common.setValueByPath(\n toObject,\n ['responseJsonSchema'],\n fromResponseJsonSchema,\n );\n }\n\n const fromRoutingConfig = common.getValueByPath(fromObject, [\n 'routingConfig',\n ]);\n if (fromRoutingConfig != null) {\n common.setValueByPath(toObject, ['routingConfig'], fromRoutingConfig);\n }\n\n const fromModelSelectionConfig = common.getValueByPath(fromObject, [\n 'modelSelectionConfig',\n ]);\n if (fromModelSelectionConfig != null) {\n common.setValueByPath(toObject, ['modelConfig'], fromModelSelectionConfig);\n }\n\n const fromSafetySettings = common.getValueByPath(fromObject, [\n 'safetySettings',\n ]);\n if (parentObject !== undefined && fromSafetySettings != null) {\n let transformedList = fromSafetySettings;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(parentObject, ['safetySettings'], transformedList);\n }\n\n const fromTools = common.getValueByPath(fromObject, ['tools']);\n if (parentObject !== undefined && fromTools != null) {\n let transformedList = t.tTools(fromTools);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return toolToVertex(t.tTool(item), rootObject);\n });\n }\n common.setValueByPath(parentObject, ['tools'], transformedList);\n }\n\n const fromToolConfig = common.getValueByPath(fromObject, ['toolConfig']);\n if (parentObject !== undefined && fromToolConfig != null) {\n common.setValueByPath(parentObject, ['toolConfig'], fromToolConfig);\n }\n\n const fromLabels = common.getValueByPath(fromObject, ['labels']);\n if (parentObject !== undefined && fromLabels != null) {\n common.setValueByPath(parentObject, ['labels'], fromLabels);\n }\n\n const fromCachedContent = common.getValueByPath(fromObject, [\n 'cachedContent',\n ]);\n if (parentObject !== undefined && fromCachedContent != null) {\n common.setValueByPath(\n parentObject,\n ['cachedContent'],\n t.tCachedContentName(apiClient, fromCachedContent),\n );\n }\n\n const fromResponseModalities = common.getValueByPath(fromObject, [\n 'responseModalities',\n ]);\n if (fromResponseModalities != null) {\n common.setValueByPath(\n toObject,\n ['responseModalities'],\n fromResponseModalities,\n );\n }\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (fromMediaResolution != null) {\n common.setValueByPath(toObject, ['mediaResolution'], fromMediaResolution);\n }\n\n const fromSpeechConfig = common.getValueByPath(fromObject, ['speechConfig']);\n if (fromSpeechConfig != null) {\n common.setValueByPath(\n toObject,\n ['speechConfig'],\n t.tSpeechConfig(fromSpeechConfig),\n );\n }\n\n const fromAudioTimestamp = common.getValueByPath(fromObject, [\n 'audioTimestamp',\n ]);\n if (fromAudioTimestamp != null) {\n common.setValueByPath(toObject, ['audioTimestamp'], fromAudioTimestamp);\n }\n\n const fromThinkingConfig = common.getValueByPath(fromObject, [\n 'thinkingConfig',\n ]);\n if (fromThinkingConfig != null) {\n common.setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig);\n }\n\n const fromImageConfig = common.getValueByPath(fromObject, ['imageConfig']);\n if (fromImageConfig != null) {\n common.setValueByPath(\n toObject,\n ['imageConfig'],\n imageConfigToVertex(fromImageConfig, rootObject),\n );\n }\n\n if (\n common.getValueByPath(fromObject, ['enableEnhancedCivicAnswers']) !==\n undefined\n ) {\n throw new Error(\n 'enableEnhancedCivicAnswers parameter is not supported in Vertex AI.',\n );\n }\n\n const fromModelArmorConfig = common.getValueByPath(fromObject, [\n 'modelArmorConfig',\n ]);\n if (parentObject !== undefined && fromModelArmorConfig != null) {\n common.setValueByPath(\n parentObject,\n ['modelArmorConfig'],\n fromModelArmorConfig,\n );\n }\n\n return toObject;\n}\n\nexport function generateContentParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.GenerateContentParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromContents = common.getValueByPath(fromObject, ['contents']);\n if (fromContents != null) {\n let transformedList = t.tContents(fromContents);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return contentToMldev(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['contents'], transformedList);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n common.setValueByPath(\n toObject,\n ['generationConfig'],\n generateContentConfigToMldev(apiClient, fromConfig, toObject, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function generateContentParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.GenerateContentParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromContents = common.getValueByPath(fromObject, ['contents']);\n if (fromContents != null) {\n let transformedList = t.tContents(fromContents);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['contents'], transformedList);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n common.setValueByPath(\n toObject,\n ['generationConfig'],\n generateContentConfigToVertex(\n apiClient,\n fromConfig,\n toObject,\n rootObject,\n ),\n );\n }\n\n return toObject;\n}\n\nexport function generateContentResponseFromMldev(\n fromObject: types.GenerateContentResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromCandidates = common.getValueByPath(fromObject, ['candidates']);\n if (fromCandidates != null) {\n let transformedList = fromCandidates;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return candidateFromMldev(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['candidates'], transformedList);\n }\n\n const fromModelVersion = common.getValueByPath(fromObject, ['modelVersion']);\n if (fromModelVersion != null) {\n common.setValueByPath(toObject, ['modelVersion'], fromModelVersion);\n }\n\n const fromPromptFeedback = common.getValueByPath(fromObject, [\n 'promptFeedback',\n ]);\n if (fromPromptFeedback != null) {\n common.setValueByPath(toObject, ['promptFeedback'], fromPromptFeedback);\n }\n\n const fromResponseId = common.getValueByPath(fromObject, ['responseId']);\n if (fromResponseId != null) {\n common.setValueByPath(toObject, ['responseId'], fromResponseId);\n }\n\n const fromUsageMetadata = common.getValueByPath(fromObject, [\n 'usageMetadata',\n ]);\n if (fromUsageMetadata != null) {\n common.setValueByPath(toObject, ['usageMetadata'], fromUsageMetadata);\n }\n\n return toObject;\n}\n\nexport function generateContentResponseFromVertex(\n fromObject: types.GenerateContentResponse,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromCandidates = common.getValueByPath(fromObject, ['candidates']);\n if (fromCandidates != null) {\n let transformedList = fromCandidates;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['candidates'], transformedList);\n }\n\n const fromCreateTime = common.getValueByPath(fromObject, ['createTime']);\n if (fromCreateTime != null) {\n common.setValueByPath(toObject, ['createTime'], fromCreateTime);\n }\n\n const fromModelVersion = common.getValueByPath(fromObject, ['modelVersion']);\n if (fromModelVersion != null) {\n common.setValueByPath(toObject, ['modelVersion'], fromModelVersion);\n }\n\n const fromPromptFeedback = common.getValueByPath(fromObject, [\n 'promptFeedback',\n ]);\n if (fromPromptFeedback != null) {\n common.setValueByPath(toObject, ['promptFeedback'], fromPromptFeedback);\n }\n\n const fromResponseId = common.getValueByPath(fromObject, ['responseId']);\n if (fromResponseId != null) {\n common.setValueByPath(toObject, ['responseId'], fromResponseId);\n }\n\n const fromUsageMetadata = common.getValueByPath(fromObject, [\n 'usageMetadata',\n ]);\n if (fromUsageMetadata != null) {\n common.setValueByPath(toObject, ['usageMetadata'], fromUsageMetadata);\n }\n\n return toObject;\n}\n\nexport function generateImagesConfigToMldev(\n fromObject: types.GenerateImagesConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['outputGcsUri']) !== undefined) {\n throw new Error('outputGcsUri parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['negativePrompt']) !== undefined) {\n throw new Error('negativePrompt parameter is not supported in Gemini API.');\n }\n\n const fromNumberOfImages = common.getValueByPath(fromObject, [\n 'numberOfImages',\n ]);\n if (parentObject !== undefined && fromNumberOfImages != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'sampleCount'],\n fromNumberOfImages,\n );\n }\n\n const fromAspectRatio = common.getValueByPath(fromObject, ['aspectRatio']);\n if (parentObject !== undefined && fromAspectRatio != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'aspectRatio'],\n fromAspectRatio,\n );\n }\n\n const fromGuidanceScale = common.getValueByPath(fromObject, [\n 'guidanceScale',\n ]);\n if (parentObject !== undefined && fromGuidanceScale != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'guidanceScale'],\n fromGuidanceScale,\n );\n }\n\n if (common.getValueByPath(fromObject, ['seed']) !== undefined) {\n throw new Error('seed parameter is not supported in Gemini API.');\n }\n\n const fromSafetyFilterLevel = common.getValueByPath(fromObject, [\n 'safetyFilterLevel',\n ]);\n if (parentObject !== undefined && fromSafetyFilterLevel != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'safetySetting'],\n fromSafetyFilterLevel,\n );\n }\n\n const fromPersonGeneration = common.getValueByPath(fromObject, [\n 'personGeneration',\n ]);\n if (parentObject !== undefined && fromPersonGeneration != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'personGeneration'],\n fromPersonGeneration,\n );\n }\n\n const fromIncludeSafetyAttributes = common.getValueByPath(fromObject, [\n 'includeSafetyAttributes',\n ]);\n if (parentObject !== undefined && fromIncludeSafetyAttributes != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'includeSafetyAttributes'],\n fromIncludeSafetyAttributes,\n );\n }\n\n const fromIncludeRaiReason = common.getValueByPath(fromObject, [\n 'includeRaiReason',\n ]);\n if (parentObject !== undefined && fromIncludeRaiReason != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'includeRaiReason'],\n fromIncludeRaiReason,\n );\n }\n\n const fromLanguage = common.getValueByPath(fromObject, ['language']);\n if (parentObject !== undefined && fromLanguage != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'language'],\n fromLanguage,\n );\n }\n\n const fromOutputMimeType = common.getValueByPath(fromObject, [\n 'outputMimeType',\n ]);\n if (parentObject !== undefined && fromOutputMimeType != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'outputOptions', 'mimeType'],\n fromOutputMimeType,\n );\n }\n\n const fromOutputCompressionQuality = common.getValueByPath(fromObject, [\n 'outputCompressionQuality',\n ]);\n if (parentObject !== undefined && fromOutputCompressionQuality != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'outputOptions', 'compressionQuality'],\n fromOutputCompressionQuality,\n );\n }\n\n if (common.getValueByPath(fromObject, ['addWatermark']) !== undefined) {\n throw new Error('addWatermark parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['labels']) !== undefined) {\n throw new Error('labels parameter is not supported in Gemini API.');\n }\n\n const fromImageSize = common.getValueByPath(fromObject, ['imageSize']);\n if (parentObject !== undefined && fromImageSize != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'sampleImageSize'],\n fromImageSize,\n );\n }\n\n if (common.getValueByPath(fromObject, ['enhancePrompt']) !== undefined) {\n throw new Error('enhancePrompt parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function generateImagesConfigToVertex(\n fromObject: types.GenerateImagesConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromOutputGcsUri = common.getValueByPath(fromObject, ['outputGcsUri']);\n if (parentObject !== undefined && fromOutputGcsUri != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'storageUri'],\n fromOutputGcsUri,\n );\n }\n\n const fromNegativePrompt = common.getValueByPath(fromObject, [\n 'negativePrompt',\n ]);\n if (parentObject !== undefined && fromNegativePrompt != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'negativePrompt'],\n fromNegativePrompt,\n );\n }\n\n const fromNumberOfImages = common.getValueByPath(fromObject, [\n 'numberOfImages',\n ]);\n if (parentObject !== undefined && fromNumberOfImages != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'sampleCount'],\n fromNumberOfImages,\n );\n }\n\n const fromAspectRatio = common.getValueByPath(fromObject, ['aspectRatio']);\n if (parentObject !== undefined && fromAspectRatio != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'aspectRatio'],\n fromAspectRatio,\n );\n }\n\n const fromGuidanceScale = common.getValueByPath(fromObject, [\n 'guidanceScale',\n ]);\n if (parentObject !== undefined && fromGuidanceScale != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'guidanceScale'],\n fromGuidanceScale,\n );\n }\n\n const fromSeed = common.getValueByPath(fromObject, ['seed']);\n if (parentObject !== undefined && fromSeed != null) {\n common.setValueByPath(parentObject, ['parameters', 'seed'], fromSeed);\n }\n\n const fromSafetyFilterLevel = common.getValueByPath(fromObject, [\n 'safetyFilterLevel',\n ]);\n if (parentObject !== undefined && fromSafetyFilterLevel != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'safetySetting'],\n fromSafetyFilterLevel,\n );\n }\n\n const fromPersonGeneration = common.getValueByPath(fromObject, [\n 'personGeneration',\n ]);\n if (parentObject !== undefined && fromPersonGeneration != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'personGeneration'],\n fromPersonGeneration,\n );\n }\n\n const fromIncludeSafetyAttributes = common.getValueByPath(fromObject, [\n 'includeSafetyAttributes',\n ]);\n if (parentObject !== undefined && fromIncludeSafetyAttributes != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'includeSafetyAttributes'],\n fromIncludeSafetyAttributes,\n );\n }\n\n const fromIncludeRaiReason = common.getValueByPath(fromObject, [\n 'includeRaiReason',\n ]);\n if (parentObject !== undefined && fromIncludeRaiReason != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'includeRaiReason'],\n fromIncludeRaiReason,\n );\n }\n\n const fromLanguage = common.getValueByPath(fromObject, ['language']);\n if (parentObject !== undefined && fromLanguage != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'language'],\n fromLanguage,\n );\n }\n\n const fromOutputMimeType = common.getValueByPath(fromObject, [\n 'outputMimeType',\n ]);\n if (parentObject !== undefined && fromOutputMimeType != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'outputOptions', 'mimeType'],\n fromOutputMimeType,\n );\n }\n\n const fromOutputCompressionQuality = common.getValueByPath(fromObject, [\n 'outputCompressionQuality',\n ]);\n if (parentObject !== undefined && fromOutputCompressionQuality != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'outputOptions', 'compressionQuality'],\n fromOutputCompressionQuality,\n );\n }\n\n const fromAddWatermark = common.getValueByPath(fromObject, ['addWatermark']);\n if (parentObject !== undefined && fromAddWatermark != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'addWatermark'],\n fromAddWatermark,\n );\n }\n\n const fromLabels = common.getValueByPath(fromObject, ['labels']);\n if (parentObject !== undefined && fromLabels != null) {\n common.setValueByPath(parentObject, ['labels'], fromLabels);\n }\n\n const fromImageSize = common.getValueByPath(fromObject, ['imageSize']);\n if (parentObject !== undefined && fromImageSize != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'sampleImageSize'],\n fromImageSize,\n );\n }\n\n const fromEnhancePrompt = common.getValueByPath(fromObject, [\n 'enhancePrompt',\n ]);\n if (parentObject !== undefined && fromEnhancePrompt != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'enhancePrompt'],\n fromEnhancePrompt,\n );\n }\n\n return toObject;\n}\n\nexport function generateImagesParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.GenerateImagesParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromPrompt = common.getValueByPath(fromObject, ['prompt']);\n if (fromPrompt != null) {\n common.setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n generateImagesConfigToMldev(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function generateImagesParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.GenerateImagesParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromPrompt = common.getValueByPath(fromObject, ['prompt']);\n if (fromPrompt != null) {\n common.setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n generateImagesConfigToVertex(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function generateImagesResponseFromMldev(\n fromObject: types.GenerateImagesResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromGeneratedImages = common.getValueByPath(fromObject, [\n 'predictions',\n ]);\n if (fromGeneratedImages != null) {\n let transformedList = fromGeneratedImages;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return generatedImageFromMldev(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['generatedImages'], transformedList);\n }\n\n const fromPositivePromptSafetyAttributes = common.getValueByPath(fromObject, [\n 'positivePromptSafetyAttributes',\n ]);\n if (fromPositivePromptSafetyAttributes != null) {\n common.setValueByPath(\n toObject,\n ['positivePromptSafetyAttributes'],\n safetyAttributesFromMldev(fromPositivePromptSafetyAttributes, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function generateImagesResponseFromVertex(\n fromObject: types.GenerateImagesResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromGeneratedImages = common.getValueByPath(fromObject, [\n 'predictions',\n ]);\n if (fromGeneratedImages != null) {\n let transformedList = fromGeneratedImages;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return generatedImageFromVertex(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['generatedImages'], transformedList);\n }\n\n const fromPositivePromptSafetyAttributes = common.getValueByPath(fromObject, [\n 'positivePromptSafetyAttributes',\n ]);\n if (fromPositivePromptSafetyAttributes != null) {\n common.setValueByPath(\n toObject,\n ['positivePromptSafetyAttributes'],\n safetyAttributesFromVertex(\n fromPositivePromptSafetyAttributes,\n rootObject,\n ),\n );\n }\n\n return toObject;\n}\n\nexport function generateVideosConfigToMldev(\n fromObject: types.GenerateVideosConfig,\n parentObject: Record<string, unknown>,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromNumberOfVideos = common.getValueByPath(fromObject, [\n 'numberOfVideos',\n ]);\n if (parentObject !== undefined && fromNumberOfVideos != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'sampleCount'],\n fromNumberOfVideos,\n );\n }\n\n if (common.getValueByPath(fromObject, ['outputGcsUri']) !== undefined) {\n throw new Error('outputGcsUri parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['fps']) !== undefined) {\n throw new Error('fps parameter is not supported in Gemini API.');\n }\n\n const fromDurationSeconds = common.getValueByPath(fromObject, [\n 'durationSeconds',\n ]);\n if (parentObject !== undefined && fromDurationSeconds != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'durationSeconds'],\n fromDurationSeconds,\n );\n }\n\n if (common.getValueByPath(fromObject, ['seed']) !== undefined) {\n throw new Error('seed parameter is not supported in Gemini API.');\n }\n\n const fromAspectRatio = common.getValueByPath(fromObject, ['aspectRatio']);\n if (parentObject !== undefined && fromAspectRatio != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'aspectRatio'],\n fromAspectRatio,\n );\n }\n\n const fromResolution = common.getValueByPath(fromObject, ['resolution']);\n if (parentObject !== undefined && fromResolution != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'resolution'],\n fromResolution,\n );\n }\n\n const fromPersonGeneration = common.getValueByPath(fromObject, [\n 'personGeneration',\n ]);\n if (parentObject !== undefined && fromPersonGeneration != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'personGeneration'],\n fromPersonGeneration,\n );\n }\n\n if (common.getValueByPath(fromObject, ['pubsubTopic']) !== undefined) {\n throw new Error('pubsubTopic parameter is not supported in Gemini API.');\n }\n\n const fromNegativePrompt = common.getValueByPath(fromObject, [\n 'negativePrompt',\n ]);\n if (parentObject !== undefined && fromNegativePrompt != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'negativePrompt'],\n fromNegativePrompt,\n );\n }\n\n const fromEnhancePrompt = common.getValueByPath(fromObject, [\n 'enhancePrompt',\n ]);\n if (parentObject !== undefined && fromEnhancePrompt != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'enhancePrompt'],\n fromEnhancePrompt,\n );\n }\n\n if (common.getValueByPath(fromObject, ['generateAudio']) !== undefined) {\n throw new Error('generateAudio parameter is not supported in Gemini API.');\n }\n\n const fromLastFrame = common.getValueByPath(fromObject, ['lastFrame']);\n if (parentObject !== undefined && fromLastFrame != null) {\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'lastFrame'],\n imageToMldev(fromLastFrame, rootObject),\n );\n }\n\n const fromReferenceImages = common.getValueByPath(fromObject, [\n 'referenceImages',\n ]);\n if (parentObject !== undefined && fromReferenceImages != null) {\n let transformedList = fromReferenceImages;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return videoGenerationReferenceImageToMldev(item, rootObject);\n });\n }\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'referenceImages'],\n transformedList,\n );\n }\n\n if (common.getValueByPath(fromObject, ['mask']) !== undefined) {\n throw new Error('mask parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['compressionQuality']) !== undefined) {\n throw new Error(\n 'compressionQuality parameter is not supported in Gemini API.',\n );\n }\n\n return toObject;\n}\n\nexport function generateVideosConfigToVertex(\n fromObject: types.GenerateVideosConfig,\n parentObject: Record<string, unknown>,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromNumberOfVideos = common.getValueByPath(fromObject, [\n 'numberOfVideos',\n ]);\n if (parentObject !== undefined && fromNumberOfVideos != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'sampleCount'],\n fromNumberOfVideos,\n );\n }\n\n const fromOutputGcsUri = common.getValueByPath(fromObject, ['outputGcsUri']);\n if (parentObject !== undefined && fromOutputGcsUri != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'storageUri'],\n fromOutputGcsUri,\n );\n }\n\n const fromFps = common.getValueByPath(fromObject, ['fps']);\n if (parentObject !== undefined && fromFps != null) {\n common.setValueByPath(parentObject, ['parameters', 'fps'], fromFps);\n }\n\n const fromDurationSeconds = common.getValueByPath(fromObject, [\n 'durationSeconds',\n ]);\n if (parentObject !== undefined && fromDurationSeconds != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'durationSeconds'],\n fromDurationSeconds,\n );\n }\n\n const fromSeed = common.getValueByPath(fromObject, ['seed']);\n if (parentObject !== undefined && fromSeed != null) {\n common.setValueByPath(parentObject, ['parameters', 'seed'], fromSeed);\n }\n\n const fromAspectRatio = common.getValueByPath(fromObject, ['aspectRatio']);\n if (parentObject !== undefined && fromAspectRatio != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'aspectRatio'],\n fromAspectRatio,\n );\n }\n\n const fromResolution = common.getValueByPath(fromObject, ['resolution']);\n if (parentObject !== undefined && fromResolution != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'resolution'],\n fromResolution,\n );\n }\n\n const fromPersonGeneration = common.getValueByPath(fromObject, [\n 'personGeneration',\n ]);\n if (parentObject !== undefined && fromPersonGeneration != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'personGeneration'],\n fromPersonGeneration,\n );\n }\n\n const fromPubsubTopic = common.getValueByPath(fromObject, ['pubsubTopic']);\n if (parentObject !== undefined && fromPubsubTopic != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'pubsubTopic'],\n fromPubsubTopic,\n );\n }\n\n const fromNegativePrompt = common.getValueByPath(fromObject, [\n 'negativePrompt',\n ]);\n if (parentObject !== undefined && fromNegativePrompt != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'negativePrompt'],\n fromNegativePrompt,\n );\n }\n\n const fromEnhancePrompt = common.getValueByPath(fromObject, [\n 'enhancePrompt',\n ]);\n if (parentObject !== undefined && fromEnhancePrompt != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'enhancePrompt'],\n fromEnhancePrompt,\n );\n }\n\n const fromGenerateAudio = common.getValueByPath(fromObject, [\n 'generateAudio',\n ]);\n if (parentObject !== undefined && fromGenerateAudio != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'generateAudio'],\n fromGenerateAudio,\n );\n }\n\n const fromLastFrame = common.getValueByPath(fromObject, ['lastFrame']);\n if (parentObject !== undefined && fromLastFrame != null) {\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'lastFrame'],\n imageToVertex(fromLastFrame, rootObject),\n );\n }\n\n const fromReferenceImages = common.getValueByPath(fromObject, [\n 'referenceImages',\n ]);\n if (parentObject !== undefined && fromReferenceImages != null) {\n let transformedList = fromReferenceImages;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return videoGenerationReferenceImageToVertex(item, rootObject);\n });\n }\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'referenceImages'],\n transformedList,\n );\n }\n\n const fromMask = common.getValueByPath(fromObject, ['mask']);\n if (parentObject !== undefined && fromMask != null) {\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'mask'],\n videoGenerationMaskToVertex(fromMask, rootObject),\n );\n }\n\n const fromCompressionQuality = common.getValueByPath(fromObject, [\n 'compressionQuality',\n ]);\n if (parentObject !== undefined && fromCompressionQuality != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'compressionQuality'],\n fromCompressionQuality,\n );\n }\n\n return toObject;\n}\n\nexport function generateVideosOperationFromMldev(\n fromObject: types.GenerateVideosOperation,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromMetadata = common.getValueByPath(fromObject, ['metadata']);\n if (fromMetadata != null) {\n common.setValueByPath(toObject, ['metadata'], fromMetadata);\n }\n\n const fromDone = common.getValueByPath(fromObject, ['done']);\n if (fromDone != null) {\n common.setValueByPath(toObject, ['done'], fromDone);\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n const fromResponse = common.getValueByPath(fromObject, [\n 'response',\n 'generateVideoResponse',\n ]);\n if (fromResponse != null) {\n common.setValueByPath(\n toObject,\n ['response'],\n generateVideosResponseFromMldev(fromResponse, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function generateVideosOperationFromVertex(\n fromObject: types.GenerateVideosOperation,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromMetadata = common.getValueByPath(fromObject, ['metadata']);\n if (fromMetadata != null) {\n common.setValueByPath(toObject, ['metadata'], fromMetadata);\n }\n\n const fromDone = common.getValueByPath(fromObject, ['done']);\n if (fromDone != null) {\n common.setValueByPath(toObject, ['done'], fromDone);\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n const fromResponse = common.getValueByPath(fromObject, ['response']);\n if (fromResponse != null) {\n common.setValueByPath(\n toObject,\n ['response'],\n generateVideosResponseFromVertex(fromResponse, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function generateVideosParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.GenerateVideosParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromPrompt = common.getValueByPath(fromObject, ['prompt']);\n if (fromPrompt != null) {\n common.setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt);\n }\n\n const fromImage = common.getValueByPath(fromObject, ['image']);\n if (fromImage != null) {\n common.setValueByPath(\n toObject,\n ['instances[0]', 'image'],\n imageToMldev(fromImage, rootObject),\n );\n }\n\n const fromVideo = common.getValueByPath(fromObject, ['video']);\n if (fromVideo != null) {\n common.setValueByPath(\n toObject,\n ['instances[0]', 'video'],\n videoToMldev(fromVideo, rootObject),\n );\n }\n\n const fromSource = common.getValueByPath(fromObject, ['source']);\n if (fromSource != null) {\n generateVideosSourceToMldev(fromSource, toObject, rootObject);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n generateVideosConfigToMldev(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function generateVideosParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.GenerateVideosParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromPrompt = common.getValueByPath(fromObject, ['prompt']);\n if (fromPrompt != null) {\n common.setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt);\n }\n\n const fromImage = common.getValueByPath(fromObject, ['image']);\n if (fromImage != null) {\n common.setValueByPath(\n toObject,\n ['instances[0]', 'image'],\n imageToVertex(fromImage, rootObject),\n );\n }\n\n const fromVideo = common.getValueByPath(fromObject, ['video']);\n if (fromVideo != null) {\n common.setValueByPath(\n toObject,\n ['instances[0]', 'video'],\n videoToVertex(fromVideo, rootObject),\n );\n }\n\n const fromSource = common.getValueByPath(fromObject, ['source']);\n if (fromSource != null) {\n generateVideosSourceToVertex(fromSource, toObject, rootObject);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n generateVideosConfigToVertex(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function generateVideosResponseFromMldev(\n fromObject: types.GenerateVideosResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromGeneratedVideos = common.getValueByPath(fromObject, [\n 'generatedSamples',\n ]);\n if (fromGeneratedVideos != null) {\n let transformedList = fromGeneratedVideos;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return generatedVideoFromMldev(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['generatedVideos'], transformedList);\n }\n\n const fromRaiMediaFilteredCount = common.getValueByPath(fromObject, [\n 'raiMediaFilteredCount',\n ]);\n if (fromRaiMediaFilteredCount != null) {\n common.setValueByPath(\n toObject,\n ['raiMediaFilteredCount'],\n fromRaiMediaFilteredCount,\n );\n }\n\n const fromRaiMediaFilteredReasons = common.getValueByPath(fromObject, [\n 'raiMediaFilteredReasons',\n ]);\n if (fromRaiMediaFilteredReasons != null) {\n common.setValueByPath(\n toObject,\n ['raiMediaFilteredReasons'],\n fromRaiMediaFilteredReasons,\n );\n }\n\n return toObject;\n}\n\nexport function generateVideosResponseFromVertex(\n fromObject: types.GenerateVideosResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromGeneratedVideos = common.getValueByPath(fromObject, ['videos']);\n if (fromGeneratedVideos != null) {\n let transformedList = fromGeneratedVideos;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return generatedVideoFromVertex(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['generatedVideos'], transformedList);\n }\n\n const fromRaiMediaFilteredCount = common.getValueByPath(fromObject, [\n 'raiMediaFilteredCount',\n ]);\n if (fromRaiMediaFilteredCount != null) {\n common.setValueByPath(\n toObject,\n ['raiMediaFilteredCount'],\n fromRaiMediaFilteredCount,\n );\n }\n\n const fromRaiMediaFilteredReasons = common.getValueByPath(fromObject, [\n 'raiMediaFilteredReasons',\n ]);\n if (fromRaiMediaFilteredReasons != null) {\n common.setValueByPath(\n toObject,\n ['raiMediaFilteredReasons'],\n fromRaiMediaFilteredReasons,\n );\n }\n\n return toObject;\n}\n\nexport function generateVideosSourceToMldev(\n fromObject: types.GenerateVideosSource,\n parentObject: Record<string, unknown>,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPrompt = common.getValueByPath(fromObject, ['prompt']);\n if (parentObject !== undefined && fromPrompt != null) {\n common.setValueByPath(parentObject, ['instances[0]', 'prompt'], fromPrompt);\n }\n\n const fromImage = common.getValueByPath(fromObject, ['image']);\n if (parentObject !== undefined && fromImage != null) {\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'image'],\n imageToMldev(fromImage, rootObject),\n );\n }\n\n const fromVideo = common.getValueByPath(fromObject, ['video']);\n if (parentObject !== undefined && fromVideo != null) {\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'video'],\n videoToMldev(fromVideo, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function generateVideosSourceToVertex(\n fromObject: types.GenerateVideosSource,\n parentObject: Record<string, unknown>,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPrompt = common.getValueByPath(fromObject, ['prompt']);\n if (parentObject !== undefined && fromPrompt != null) {\n common.setValueByPath(parentObject, ['instances[0]', 'prompt'], fromPrompt);\n }\n\n const fromImage = common.getValueByPath(fromObject, ['image']);\n if (parentObject !== undefined && fromImage != null) {\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'image'],\n imageToVertex(fromImage, rootObject),\n );\n }\n\n const fromVideo = common.getValueByPath(fromObject, ['video']);\n if (parentObject !== undefined && fromVideo != null) {\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'video'],\n videoToVertex(fromVideo, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function generatedImageFromMldev(\n fromObject: types.GeneratedImage,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromImage = common.getValueByPath(fromObject, ['_self']);\n if (fromImage != null) {\n common.setValueByPath(\n toObject,\n ['image'],\n imageFromMldev(fromImage, rootObject),\n );\n }\n\n const fromRaiFilteredReason = common.getValueByPath(fromObject, [\n 'raiFilteredReason',\n ]);\n if (fromRaiFilteredReason != null) {\n common.setValueByPath(\n toObject,\n ['raiFilteredReason'],\n fromRaiFilteredReason,\n );\n }\n\n const fromSafetyAttributes = common.getValueByPath(fromObject, ['_self']);\n if (fromSafetyAttributes != null) {\n common.setValueByPath(\n toObject,\n ['safetyAttributes'],\n safetyAttributesFromMldev(fromSafetyAttributes, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function generatedImageFromVertex(\n fromObject: types.GeneratedImage,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromImage = common.getValueByPath(fromObject, ['_self']);\n if (fromImage != null) {\n common.setValueByPath(\n toObject,\n ['image'],\n imageFromVertex(fromImage, rootObject),\n );\n }\n\n const fromRaiFilteredReason = common.getValueByPath(fromObject, [\n 'raiFilteredReason',\n ]);\n if (fromRaiFilteredReason != null) {\n common.setValueByPath(\n toObject,\n ['raiFilteredReason'],\n fromRaiFilteredReason,\n );\n }\n\n const fromSafetyAttributes = common.getValueByPath(fromObject, ['_self']);\n if (fromSafetyAttributes != null) {\n common.setValueByPath(\n toObject,\n ['safetyAttributes'],\n safetyAttributesFromVertex(fromSafetyAttributes, rootObject),\n );\n }\n\n const fromEnhancedPrompt = common.getValueByPath(fromObject, ['prompt']);\n if (fromEnhancedPrompt != null) {\n common.setValueByPath(toObject, ['enhancedPrompt'], fromEnhancedPrompt);\n }\n\n return toObject;\n}\n\nexport function generatedImageMaskFromVertex(\n fromObject: types.GeneratedImageMask,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMask = common.getValueByPath(fromObject, ['_self']);\n if (fromMask != null) {\n common.setValueByPath(\n toObject,\n ['mask'],\n imageFromVertex(fromMask, rootObject),\n );\n }\n\n const fromLabels = common.getValueByPath(fromObject, ['labels']);\n if (fromLabels != null) {\n let transformedList = fromLabels;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['labels'], transformedList);\n }\n\n return toObject;\n}\n\nexport function generatedVideoFromMldev(\n fromObject: types.GeneratedVideo,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromVideo = common.getValueByPath(fromObject, ['video']);\n if (fromVideo != null) {\n common.setValueByPath(\n toObject,\n ['video'],\n videoFromMldev(fromVideo, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function generatedVideoFromVertex(\n fromObject: types.GeneratedVideo,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromVideo = common.getValueByPath(fromObject, ['_self']);\n if (fromVideo != null) {\n common.setValueByPath(\n toObject,\n ['video'],\n videoFromVertex(fromVideo, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function generationConfigToVertex(\n fromObject: types.GenerationConfig,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModelSelectionConfig = common.getValueByPath(fromObject, [\n 'modelSelectionConfig',\n ]);\n if (fromModelSelectionConfig != null) {\n common.setValueByPath(toObject, ['modelConfig'], fromModelSelectionConfig);\n }\n\n const fromResponseJsonSchema = common.getValueByPath(fromObject, [\n 'responseJsonSchema',\n ]);\n if (fromResponseJsonSchema != null) {\n common.setValueByPath(\n toObject,\n ['responseJsonSchema'],\n fromResponseJsonSchema,\n );\n }\n\n const fromAudioTimestamp = common.getValueByPath(fromObject, [\n 'audioTimestamp',\n ]);\n if (fromAudioTimestamp != null) {\n common.setValueByPath(toObject, ['audioTimestamp'], fromAudioTimestamp);\n }\n\n const fromCandidateCount = common.getValueByPath(fromObject, [\n 'candidateCount',\n ]);\n if (fromCandidateCount != null) {\n common.setValueByPath(toObject, ['candidateCount'], fromCandidateCount);\n }\n\n const fromEnableAffectiveDialog = common.getValueByPath(fromObject, [\n 'enableAffectiveDialog',\n ]);\n if (fromEnableAffectiveDialog != null) {\n common.setValueByPath(\n toObject,\n ['enableAffectiveDialog'],\n fromEnableAffectiveDialog,\n );\n }\n\n const fromFrequencyPenalty = common.getValueByPath(fromObject, [\n 'frequencyPenalty',\n ]);\n if (fromFrequencyPenalty != null) {\n common.setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty);\n }\n\n const fromLogprobs = common.getValueByPath(fromObject, ['logprobs']);\n if (fromLogprobs != null) {\n common.setValueByPath(toObject, ['logprobs'], fromLogprobs);\n }\n\n const fromMaxOutputTokens = common.getValueByPath(fromObject, [\n 'maxOutputTokens',\n ]);\n if (fromMaxOutputTokens != null) {\n common.setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens);\n }\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (fromMediaResolution != null) {\n common.setValueByPath(toObject, ['mediaResolution'], fromMediaResolution);\n }\n\n const fromPresencePenalty = common.getValueByPath(fromObject, [\n 'presencePenalty',\n ]);\n if (fromPresencePenalty != null) {\n common.setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty);\n }\n\n const fromResponseLogprobs = common.getValueByPath(fromObject, [\n 'responseLogprobs',\n ]);\n if (fromResponseLogprobs != null) {\n common.setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs);\n }\n\n const fromResponseMimeType = common.getValueByPath(fromObject, [\n 'responseMimeType',\n ]);\n if (fromResponseMimeType != null) {\n common.setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType);\n }\n\n const fromResponseModalities = common.getValueByPath(fromObject, [\n 'responseModalities',\n ]);\n if (fromResponseModalities != null) {\n common.setValueByPath(\n toObject,\n ['responseModalities'],\n fromResponseModalities,\n );\n }\n\n const fromResponseSchema = common.getValueByPath(fromObject, [\n 'responseSchema',\n ]);\n if (fromResponseSchema != null) {\n common.setValueByPath(toObject, ['responseSchema'], fromResponseSchema);\n }\n\n const fromRoutingConfig = common.getValueByPath(fromObject, [\n 'routingConfig',\n ]);\n if (fromRoutingConfig != null) {\n common.setValueByPath(toObject, ['routingConfig'], fromRoutingConfig);\n }\n\n const fromSeed = common.getValueByPath(fromObject, ['seed']);\n if (fromSeed != null) {\n common.setValueByPath(toObject, ['seed'], fromSeed);\n }\n\n const fromSpeechConfig = common.getValueByPath(fromObject, ['speechConfig']);\n if (fromSpeechConfig != null) {\n common.setValueByPath(toObject, ['speechConfig'], fromSpeechConfig);\n }\n\n const fromStopSequences = common.getValueByPath(fromObject, [\n 'stopSequences',\n ]);\n if (fromStopSequences != null) {\n common.setValueByPath(toObject, ['stopSequences'], fromStopSequences);\n }\n\n const fromTemperature = common.getValueByPath(fromObject, ['temperature']);\n if (fromTemperature != null) {\n common.setValueByPath(toObject, ['temperature'], fromTemperature);\n }\n\n const fromThinkingConfig = common.getValueByPath(fromObject, [\n 'thinkingConfig',\n ]);\n if (fromThinkingConfig != null) {\n common.setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig);\n }\n\n const fromTopK = common.getValueByPath(fromObject, ['topK']);\n if (fromTopK != null) {\n common.setValueByPath(toObject, ['topK'], fromTopK);\n }\n\n const fromTopP = common.getValueByPath(fromObject, ['topP']);\n if (fromTopP != null) {\n common.setValueByPath(toObject, ['topP'], fromTopP);\n }\n\n if (\n common.getValueByPath(fromObject, ['enableEnhancedCivicAnswers']) !==\n undefined\n ) {\n throw new Error(\n 'enableEnhancedCivicAnswers parameter is not supported in Vertex AI.',\n );\n }\n\n return toObject;\n}\n\nexport function getModelParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.GetModelParameters,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n return toObject;\n}\n\nexport function getModelParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.GetModelParameters,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n return toObject;\n}\n\nexport function googleMapsToMldev(\n fromObject: types.GoogleMaps,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['authConfig']) !== undefined) {\n throw new Error('authConfig parameter is not supported in Gemini API.');\n }\n\n const fromEnableWidget = common.getValueByPath(fromObject, ['enableWidget']);\n if (fromEnableWidget != null) {\n common.setValueByPath(toObject, ['enableWidget'], fromEnableWidget);\n }\n\n return toObject;\n}\n\nexport function googleSearchToMldev(\n fromObject: types.GoogleSearch,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['excludeDomains']) !== undefined) {\n throw new Error('excludeDomains parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['blockingConfidence']) !== undefined) {\n throw new Error(\n 'blockingConfidence parameter is not supported in Gemini API.',\n );\n }\n\n const fromTimeRangeFilter = common.getValueByPath(fromObject, [\n 'timeRangeFilter',\n ]);\n if (fromTimeRangeFilter != null) {\n common.setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter);\n }\n\n return toObject;\n}\n\nexport function imageConfigToMldev(\n fromObject: types.ImageConfig,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromAspectRatio = common.getValueByPath(fromObject, ['aspectRatio']);\n if (fromAspectRatio != null) {\n common.setValueByPath(toObject, ['aspectRatio'], fromAspectRatio);\n }\n\n const fromImageSize = common.getValueByPath(fromObject, ['imageSize']);\n if (fromImageSize != null) {\n common.setValueByPath(toObject, ['imageSize'], fromImageSize);\n }\n\n if (common.getValueByPath(fromObject, ['personGeneration']) !== undefined) {\n throw new Error(\n 'personGeneration parameter is not supported in Gemini API.',\n );\n }\n\n if (common.getValueByPath(fromObject, ['outputMimeType']) !== undefined) {\n throw new Error('outputMimeType parameter is not supported in Gemini API.');\n }\n\n if (\n common.getValueByPath(fromObject, ['outputCompressionQuality']) !==\n undefined\n ) {\n throw new Error(\n 'outputCompressionQuality parameter is not supported in Gemini API.',\n );\n }\n\n return toObject;\n}\n\nexport function imageConfigToVertex(\n fromObject: types.ImageConfig,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromAspectRatio = common.getValueByPath(fromObject, ['aspectRatio']);\n if (fromAspectRatio != null) {\n common.setValueByPath(toObject, ['aspectRatio'], fromAspectRatio);\n }\n\n const fromImageSize = common.getValueByPath(fromObject, ['imageSize']);\n if (fromImageSize != null) {\n common.setValueByPath(toObject, ['imageSize'], fromImageSize);\n }\n\n const fromPersonGeneration = common.getValueByPath(fromObject, [\n 'personGeneration',\n ]);\n if (fromPersonGeneration != null) {\n common.setValueByPath(toObject, ['personGeneration'], fromPersonGeneration);\n }\n\n const fromOutputMimeType = common.getValueByPath(fromObject, [\n 'outputMimeType',\n ]);\n if (fromOutputMimeType != null) {\n common.setValueByPath(\n toObject,\n ['imageOutputOptions', 'mimeType'],\n fromOutputMimeType,\n );\n }\n\n const fromOutputCompressionQuality = common.getValueByPath(fromObject, [\n 'outputCompressionQuality',\n ]);\n if (fromOutputCompressionQuality != null) {\n common.setValueByPath(\n toObject,\n ['imageOutputOptions', 'compressionQuality'],\n fromOutputCompressionQuality,\n );\n }\n\n return toObject;\n}\n\nexport function imageFromMldev(\n fromObject: types.Image,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromImageBytes = common.getValueByPath(fromObject, [\n 'bytesBase64Encoded',\n ]);\n if (fromImageBytes != null) {\n common.setValueByPath(toObject, ['imageBytes'], t.tBytes(fromImageBytes));\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function imageFromVertex(\n fromObject: types.Image,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromGcsUri = common.getValueByPath(fromObject, ['gcsUri']);\n if (fromGcsUri != null) {\n common.setValueByPath(toObject, ['gcsUri'], fromGcsUri);\n }\n\n const fromImageBytes = common.getValueByPath(fromObject, [\n 'bytesBase64Encoded',\n ]);\n if (fromImageBytes != null) {\n common.setValueByPath(toObject, ['imageBytes'], t.tBytes(fromImageBytes));\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function imageToMldev(\n fromObject: types.Image,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['gcsUri']) !== undefined) {\n throw new Error('gcsUri parameter is not supported in Gemini API.');\n }\n\n const fromImageBytes = common.getValueByPath(fromObject, ['imageBytes']);\n if (fromImageBytes != null) {\n common.setValueByPath(\n toObject,\n ['bytesBase64Encoded'],\n t.tBytes(fromImageBytes),\n );\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function imageToVertex(\n fromObject: types.Image,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromGcsUri = common.getValueByPath(fromObject, ['gcsUri']);\n if (fromGcsUri != null) {\n common.setValueByPath(toObject, ['gcsUri'], fromGcsUri);\n }\n\n const fromImageBytes = common.getValueByPath(fromObject, ['imageBytes']);\n if (fromImageBytes != null) {\n common.setValueByPath(\n toObject,\n ['bytesBase64Encoded'],\n t.tBytes(fromImageBytes),\n );\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function listModelsConfigToMldev(\n apiClient: ApiClient,\n fromObject: types.ListModelsConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPageSize = common.getValueByPath(fromObject, ['pageSize']);\n if (parentObject !== undefined && fromPageSize != null) {\n common.setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize);\n }\n\n const fromPageToken = common.getValueByPath(fromObject, ['pageToken']);\n if (parentObject !== undefined && fromPageToken != null) {\n common.setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken);\n }\n\n const fromFilter = common.getValueByPath(fromObject, ['filter']);\n if (parentObject !== undefined && fromFilter != null) {\n common.setValueByPath(parentObject, ['_query', 'filter'], fromFilter);\n }\n\n const fromQueryBase = common.getValueByPath(fromObject, ['queryBase']);\n if (parentObject !== undefined && fromQueryBase != null) {\n common.setValueByPath(\n parentObject,\n ['_url', 'models_url'],\n t.tModelsUrl(apiClient, fromQueryBase),\n );\n }\n\n return toObject;\n}\n\nexport function listModelsConfigToVertex(\n apiClient: ApiClient,\n fromObject: types.ListModelsConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPageSize = common.getValueByPath(fromObject, ['pageSize']);\n if (parentObject !== undefined && fromPageSize != null) {\n common.setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize);\n }\n\n const fromPageToken = common.getValueByPath(fromObject, ['pageToken']);\n if (parentObject !== undefined && fromPageToken != null) {\n common.setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken);\n }\n\n const fromFilter = common.getValueByPath(fromObject, ['filter']);\n if (parentObject !== undefined && fromFilter != null) {\n common.setValueByPath(parentObject, ['_query', 'filter'], fromFilter);\n }\n\n const fromQueryBase = common.getValueByPath(fromObject, ['queryBase']);\n if (parentObject !== undefined && fromQueryBase != null) {\n common.setValueByPath(\n parentObject,\n ['_url', 'models_url'],\n t.tModelsUrl(apiClient, fromQueryBase),\n );\n }\n\n return toObject;\n}\n\nexport function listModelsParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.ListModelsParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n listModelsConfigToMldev(apiClient, fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function listModelsParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.ListModelsParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n listModelsConfigToVertex(apiClient, fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function listModelsResponseFromMldev(\n fromObject: types.ListModelsResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromNextPageToken = common.getValueByPath(fromObject, [\n 'nextPageToken',\n ]);\n if (fromNextPageToken != null) {\n common.setValueByPath(toObject, ['nextPageToken'], fromNextPageToken);\n }\n\n const fromModels = common.getValueByPath(fromObject, ['_self']);\n if (fromModels != null) {\n let transformedList = t.tExtractModels(fromModels);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return modelFromMldev(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['models'], transformedList);\n }\n\n return toObject;\n}\n\nexport function listModelsResponseFromVertex(\n fromObject: types.ListModelsResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromNextPageToken = common.getValueByPath(fromObject, [\n 'nextPageToken',\n ]);\n if (fromNextPageToken != null) {\n common.setValueByPath(toObject, ['nextPageToken'], fromNextPageToken);\n }\n\n const fromModels = common.getValueByPath(fromObject, ['_self']);\n if (fromModels != null) {\n let transformedList = t.tExtractModels(fromModels);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return modelFromVertex(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['models'], transformedList);\n }\n\n return toObject;\n}\n\nexport function maskReferenceConfigToVertex(\n fromObject: types.MaskReferenceConfig,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMaskMode = common.getValueByPath(fromObject, ['maskMode']);\n if (fromMaskMode != null) {\n common.setValueByPath(toObject, ['maskMode'], fromMaskMode);\n }\n\n const fromSegmentationClasses = common.getValueByPath(fromObject, [\n 'segmentationClasses',\n ]);\n if (fromSegmentationClasses != null) {\n common.setValueByPath(toObject, ['maskClasses'], fromSegmentationClasses);\n }\n\n const fromMaskDilation = common.getValueByPath(fromObject, ['maskDilation']);\n if (fromMaskDilation != null) {\n common.setValueByPath(toObject, ['dilation'], fromMaskDilation);\n }\n\n return toObject;\n}\n\nexport function modelFromMldev(\n fromObject: types.Model,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromDisplayName = common.getValueByPath(fromObject, ['displayName']);\n if (fromDisplayName != null) {\n common.setValueByPath(toObject, ['displayName'], fromDisplayName);\n }\n\n const fromDescription = common.getValueByPath(fromObject, ['description']);\n if (fromDescription != null) {\n common.setValueByPath(toObject, ['description'], fromDescription);\n }\n\n const fromVersion = common.getValueByPath(fromObject, ['version']);\n if (fromVersion != null) {\n common.setValueByPath(toObject, ['version'], fromVersion);\n }\n\n const fromTunedModelInfo = common.getValueByPath(fromObject, ['_self']);\n if (fromTunedModelInfo != null) {\n common.setValueByPath(\n toObject,\n ['tunedModelInfo'],\n tunedModelInfoFromMldev(fromTunedModelInfo, rootObject),\n );\n }\n\n const fromInputTokenLimit = common.getValueByPath(fromObject, [\n 'inputTokenLimit',\n ]);\n if (fromInputTokenLimit != null) {\n common.setValueByPath(toObject, ['inputTokenLimit'], fromInputTokenLimit);\n }\n\n const fromOutputTokenLimit = common.getValueByPath(fromObject, [\n 'outputTokenLimit',\n ]);\n if (fromOutputTokenLimit != null) {\n common.setValueByPath(toObject, ['outputTokenLimit'], fromOutputTokenLimit);\n }\n\n const fromSupportedActions = common.getValueByPath(fromObject, [\n 'supportedGenerationMethods',\n ]);\n if (fromSupportedActions != null) {\n common.setValueByPath(toObject, ['supportedActions'], fromSupportedActions);\n }\n\n const fromTemperature = common.getValueByPath(fromObject, ['temperature']);\n if (fromTemperature != null) {\n common.setValueByPath(toObject, ['temperature'], fromTemperature);\n }\n\n const fromMaxTemperature = common.getValueByPath(fromObject, [\n 'maxTemperature',\n ]);\n if (fromMaxTemperature != null) {\n common.setValueByPath(toObject, ['maxTemperature'], fromMaxTemperature);\n }\n\n const fromTopP = common.getValueByPath(fromObject, ['topP']);\n if (fromTopP != null) {\n common.setValueByPath(toObject, ['topP'], fromTopP);\n }\n\n const fromTopK = common.getValueByPath(fromObject, ['topK']);\n if (fromTopK != null) {\n common.setValueByPath(toObject, ['topK'], fromTopK);\n }\n\n const fromThinking = common.getValueByPath(fromObject, ['thinking']);\n if (fromThinking != null) {\n common.setValueByPath(toObject, ['thinking'], fromThinking);\n }\n\n return toObject;\n}\n\nexport function modelFromVertex(\n fromObject: types.Model,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromDisplayName = common.getValueByPath(fromObject, ['displayName']);\n if (fromDisplayName != null) {\n common.setValueByPath(toObject, ['displayName'], fromDisplayName);\n }\n\n const fromDescription = common.getValueByPath(fromObject, ['description']);\n if (fromDescription != null) {\n common.setValueByPath(toObject, ['description'], fromDescription);\n }\n\n const fromVersion = common.getValueByPath(fromObject, ['versionId']);\n if (fromVersion != null) {\n common.setValueByPath(toObject, ['version'], fromVersion);\n }\n\n const fromEndpoints = common.getValueByPath(fromObject, ['deployedModels']);\n if (fromEndpoints != null) {\n let transformedList = fromEndpoints;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return endpointFromVertex(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['endpoints'], transformedList);\n }\n\n const fromLabels = common.getValueByPath(fromObject, ['labels']);\n if (fromLabels != null) {\n common.setValueByPath(toObject, ['labels'], fromLabels);\n }\n\n const fromTunedModelInfo = common.getValueByPath(fromObject, ['_self']);\n if (fromTunedModelInfo != null) {\n common.setValueByPath(\n toObject,\n ['tunedModelInfo'],\n tunedModelInfoFromVertex(fromTunedModelInfo, rootObject),\n );\n }\n\n const fromDefaultCheckpointId = common.getValueByPath(fromObject, [\n 'defaultCheckpointId',\n ]);\n if (fromDefaultCheckpointId != null) {\n common.setValueByPath(\n toObject,\n ['defaultCheckpointId'],\n fromDefaultCheckpointId,\n );\n }\n\n const fromCheckpoints = common.getValueByPath(fromObject, ['checkpoints']);\n if (fromCheckpoints != null) {\n let transformedList = fromCheckpoints;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['checkpoints'], transformedList);\n }\n\n return toObject;\n}\n\nexport function partToMldev(\n fromObject: types.Part,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (fromMediaResolution != null) {\n common.setValueByPath(toObject, ['mediaResolution'], fromMediaResolution);\n }\n\n const fromCodeExecutionResult = common.getValueByPath(fromObject, [\n 'codeExecutionResult',\n ]);\n if (fromCodeExecutionResult != null) {\n common.setValueByPath(\n toObject,\n ['codeExecutionResult'],\n fromCodeExecutionResult,\n );\n }\n\n const fromExecutableCode = common.getValueByPath(fromObject, [\n 'executableCode',\n ]);\n if (fromExecutableCode != null) {\n common.setValueByPath(toObject, ['executableCode'], fromExecutableCode);\n }\n\n const fromFileData = common.getValueByPath(fromObject, ['fileData']);\n if (fromFileData != null) {\n common.setValueByPath(\n toObject,\n ['fileData'],\n fileDataToMldev(fromFileData, rootObject),\n );\n }\n\n const fromFunctionCall = common.getValueByPath(fromObject, ['functionCall']);\n if (fromFunctionCall != null) {\n common.setValueByPath(\n toObject,\n ['functionCall'],\n functionCallToMldev(fromFunctionCall, rootObject),\n );\n }\n\n const fromFunctionResponse = common.getValueByPath(fromObject, [\n 'functionResponse',\n ]);\n if (fromFunctionResponse != null) {\n common.setValueByPath(toObject, ['functionResponse'], fromFunctionResponse);\n }\n\n const fromInlineData = common.getValueByPath(fromObject, ['inlineData']);\n if (fromInlineData != null) {\n common.setValueByPath(\n toObject,\n ['inlineData'],\n blobToMldev(fromInlineData, rootObject),\n );\n }\n\n const fromText = common.getValueByPath(fromObject, ['text']);\n if (fromText != null) {\n common.setValueByPath(toObject, ['text'], fromText);\n }\n\n const fromThought = common.getValueByPath(fromObject, ['thought']);\n if (fromThought != null) {\n common.setValueByPath(toObject, ['thought'], fromThought);\n }\n\n const fromThoughtSignature = common.getValueByPath(fromObject, [\n 'thoughtSignature',\n ]);\n if (fromThoughtSignature != null) {\n common.setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature);\n }\n\n const fromVideoMetadata = common.getValueByPath(fromObject, [\n 'videoMetadata',\n ]);\n if (fromVideoMetadata != null) {\n common.setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata);\n }\n\n return toObject;\n}\n\nexport function productImageToVertex(\n fromObject: types.ProductImage,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromProductImage = common.getValueByPath(fromObject, ['productImage']);\n if (fromProductImage != null) {\n common.setValueByPath(\n toObject,\n ['image'],\n imageToVertex(fromProductImage, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function recontextImageConfigToVertex(\n fromObject: types.RecontextImageConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromNumberOfImages = common.getValueByPath(fromObject, [\n 'numberOfImages',\n ]);\n if (parentObject !== undefined && fromNumberOfImages != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'sampleCount'],\n fromNumberOfImages,\n );\n }\n\n const fromBaseSteps = common.getValueByPath(fromObject, ['baseSteps']);\n if (parentObject !== undefined && fromBaseSteps != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'baseSteps'],\n fromBaseSteps,\n );\n }\n\n const fromOutputGcsUri = common.getValueByPath(fromObject, ['outputGcsUri']);\n if (parentObject !== undefined && fromOutputGcsUri != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'storageUri'],\n fromOutputGcsUri,\n );\n }\n\n const fromSeed = common.getValueByPath(fromObject, ['seed']);\n if (parentObject !== undefined && fromSeed != null) {\n common.setValueByPath(parentObject, ['parameters', 'seed'], fromSeed);\n }\n\n const fromSafetyFilterLevel = common.getValueByPath(fromObject, [\n 'safetyFilterLevel',\n ]);\n if (parentObject !== undefined && fromSafetyFilterLevel != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'safetySetting'],\n fromSafetyFilterLevel,\n );\n }\n\n const fromPersonGeneration = common.getValueByPath(fromObject, [\n 'personGeneration',\n ]);\n if (parentObject !== undefined && fromPersonGeneration != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'personGeneration'],\n fromPersonGeneration,\n );\n }\n\n const fromAddWatermark = common.getValueByPath(fromObject, ['addWatermark']);\n if (parentObject !== undefined && fromAddWatermark != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'addWatermark'],\n fromAddWatermark,\n );\n }\n\n const fromOutputMimeType = common.getValueByPath(fromObject, [\n 'outputMimeType',\n ]);\n if (parentObject !== undefined && fromOutputMimeType != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'outputOptions', 'mimeType'],\n fromOutputMimeType,\n );\n }\n\n const fromOutputCompressionQuality = common.getValueByPath(fromObject, [\n 'outputCompressionQuality',\n ]);\n if (parentObject !== undefined && fromOutputCompressionQuality != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'outputOptions', 'compressionQuality'],\n fromOutputCompressionQuality,\n );\n }\n\n const fromEnhancePrompt = common.getValueByPath(fromObject, [\n 'enhancePrompt',\n ]);\n if (parentObject !== undefined && fromEnhancePrompt != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'enhancePrompt'],\n fromEnhancePrompt,\n );\n }\n\n const fromLabels = common.getValueByPath(fromObject, ['labels']);\n if (parentObject !== undefined && fromLabels != null) {\n common.setValueByPath(parentObject, ['labels'], fromLabels);\n }\n\n return toObject;\n}\n\nexport function recontextImageParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.RecontextImageParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromSource = common.getValueByPath(fromObject, ['source']);\n if (fromSource != null) {\n recontextImageSourceToVertex(fromSource, toObject, rootObject);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n recontextImageConfigToVertex(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function recontextImageResponseFromVertex(\n fromObject: types.RecontextImageResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromGeneratedImages = common.getValueByPath(fromObject, [\n 'predictions',\n ]);\n if (fromGeneratedImages != null) {\n let transformedList = fromGeneratedImages;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return generatedImageFromVertex(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['generatedImages'], transformedList);\n }\n\n return toObject;\n}\n\nexport function recontextImageSourceToVertex(\n fromObject: types.RecontextImageSource,\n parentObject: Record<string, unknown>,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPrompt = common.getValueByPath(fromObject, ['prompt']);\n if (parentObject !== undefined && fromPrompt != null) {\n common.setValueByPath(parentObject, ['instances[0]', 'prompt'], fromPrompt);\n }\n\n const fromPersonImage = common.getValueByPath(fromObject, ['personImage']);\n if (parentObject !== undefined && fromPersonImage != null) {\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'personImage', 'image'],\n imageToVertex(fromPersonImage, rootObject),\n );\n }\n\n const fromProductImages = common.getValueByPath(fromObject, [\n 'productImages',\n ]);\n if (parentObject !== undefined && fromProductImages != null) {\n let transformedList = fromProductImages;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return productImageToVertex(item, rootObject);\n });\n }\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'productImages'],\n transformedList,\n );\n }\n\n return toObject;\n}\n\nexport function referenceImageAPIInternalToVertex(\n fromObject: _internal_types.ReferenceImageAPIInternal,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromReferenceImage = common.getValueByPath(fromObject, [\n 'referenceImage',\n ]);\n if (fromReferenceImage != null) {\n common.setValueByPath(\n toObject,\n ['referenceImage'],\n imageToVertex(fromReferenceImage, rootObject),\n );\n }\n\n const fromReferenceId = common.getValueByPath(fromObject, ['referenceId']);\n if (fromReferenceId != null) {\n common.setValueByPath(toObject, ['referenceId'], fromReferenceId);\n }\n\n const fromReferenceType = common.getValueByPath(fromObject, [\n 'referenceType',\n ]);\n if (fromReferenceType != null) {\n common.setValueByPath(toObject, ['referenceType'], fromReferenceType);\n }\n\n const fromMaskImageConfig = common.getValueByPath(fromObject, [\n 'maskImageConfig',\n ]);\n if (fromMaskImageConfig != null) {\n common.setValueByPath(\n toObject,\n ['maskImageConfig'],\n maskReferenceConfigToVertex(fromMaskImageConfig, rootObject),\n );\n }\n\n const fromControlImageConfig = common.getValueByPath(fromObject, [\n 'controlImageConfig',\n ]);\n if (fromControlImageConfig != null) {\n common.setValueByPath(\n toObject,\n ['controlImageConfig'],\n controlReferenceConfigToVertex(fromControlImageConfig, rootObject),\n );\n }\n\n const fromStyleImageConfig = common.getValueByPath(fromObject, [\n 'styleImageConfig',\n ]);\n if (fromStyleImageConfig != null) {\n common.setValueByPath(toObject, ['styleImageConfig'], fromStyleImageConfig);\n }\n\n const fromSubjectImageConfig = common.getValueByPath(fromObject, [\n 'subjectImageConfig',\n ]);\n if (fromSubjectImageConfig != null) {\n common.setValueByPath(\n toObject,\n ['subjectImageConfig'],\n fromSubjectImageConfig,\n );\n }\n\n return toObject;\n}\n\nexport function safetyAttributesFromMldev(\n fromObject: types.SafetyAttributes,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromCategories = common.getValueByPath(fromObject, [\n 'safetyAttributes',\n 'categories',\n ]);\n if (fromCategories != null) {\n common.setValueByPath(toObject, ['categories'], fromCategories);\n }\n\n const fromScores = common.getValueByPath(fromObject, [\n 'safetyAttributes',\n 'scores',\n ]);\n if (fromScores != null) {\n common.setValueByPath(toObject, ['scores'], fromScores);\n }\n\n const fromContentType = common.getValueByPath(fromObject, ['contentType']);\n if (fromContentType != null) {\n common.setValueByPath(toObject, ['contentType'], fromContentType);\n }\n\n return toObject;\n}\n\nexport function safetyAttributesFromVertex(\n fromObject: types.SafetyAttributes,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromCategories = common.getValueByPath(fromObject, [\n 'safetyAttributes',\n 'categories',\n ]);\n if (fromCategories != null) {\n common.setValueByPath(toObject, ['categories'], fromCategories);\n }\n\n const fromScores = common.getValueByPath(fromObject, [\n 'safetyAttributes',\n 'scores',\n ]);\n if (fromScores != null) {\n common.setValueByPath(toObject, ['scores'], fromScores);\n }\n\n const fromContentType = common.getValueByPath(fromObject, ['contentType']);\n if (fromContentType != null) {\n common.setValueByPath(toObject, ['contentType'], fromContentType);\n }\n\n return toObject;\n}\n\nexport function safetySettingToMldev(\n fromObject: types.SafetySetting,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromCategory = common.getValueByPath(fromObject, ['category']);\n if (fromCategory != null) {\n common.setValueByPath(toObject, ['category'], fromCategory);\n }\n\n if (common.getValueByPath(fromObject, ['method']) !== undefined) {\n throw new Error('method parameter is not supported in Gemini API.');\n }\n\n const fromThreshold = common.getValueByPath(fromObject, ['threshold']);\n if (fromThreshold != null) {\n common.setValueByPath(toObject, ['threshold'], fromThreshold);\n }\n\n return toObject;\n}\n\nexport function scribbleImageToVertex(\n fromObject: types.ScribbleImage,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromImage = common.getValueByPath(fromObject, ['image']);\n if (fromImage != null) {\n common.setValueByPath(\n toObject,\n ['image'],\n imageToVertex(fromImage, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function segmentImageConfigToVertex(\n fromObject: types.SegmentImageConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMode = common.getValueByPath(fromObject, ['mode']);\n if (parentObject !== undefined && fromMode != null) {\n common.setValueByPath(parentObject, ['parameters', 'mode'], fromMode);\n }\n\n const fromMaxPredictions = common.getValueByPath(fromObject, [\n 'maxPredictions',\n ]);\n if (parentObject !== undefined && fromMaxPredictions != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'maxPredictions'],\n fromMaxPredictions,\n );\n }\n\n const fromConfidenceThreshold = common.getValueByPath(fromObject, [\n 'confidenceThreshold',\n ]);\n if (parentObject !== undefined && fromConfidenceThreshold != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'confidenceThreshold'],\n fromConfidenceThreshold,\n );\n }\n\n const fromMaskDilation = common.getValueByPath(fromObject, ['maskDilation']);\n if (parentObject !== undefined && fromMaskDilation != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'maskDilation'],\n fromMaskDilation,\n );\n }\n\n const fromBinaryColorThreshold = common.getValueByPath(fromObject, [\n 'binaryColorThreshold',\n ]);\n if (parentObject !== undefined && fromBinaryColorThreshold != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'binaryColorThreshold'],\n fromBinaryColorThreshold,\n );\n }\n\n const fromLabels = common.getValueByPath(fromObject, ['labels']);\n if (parentObject !== undefined && fromLabels != null) {\n common.setValueByPath(parentObject, ['labels'], fromLabels);\n }\n\n return toObject;\n}\n\nexport function segmentImageParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.SegmentImageParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromSource = common.getValueByPath(fromObject, ['source']);\n if (fromSource != null) {\n segmentImageSourceToVertex(fromSource, toObject, rootObject);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n segmentImageConfigToVertex(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function segmentImageResponseFromVertex(\n fromObject: types.SegmentImageResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromGeneratedMasks = common.getValueByPath(fromObject, ['predictions']);\n if (fromGeneratedMasks != null) {\n let transformedList = fromGeneratedMasks;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return generatedImageMaskFromVertex(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['generatedMasks'], transformedList);\n }\n\n return toObject;\n}\n\nexport function segmentImageSourceToVertex(\n fromObject: types.SegmentImageSource,\n parentObject: Record<string, unknown>,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPrompt = common.getValueByPath(fromObject, ['prompt']);\n if (parentObject !== undefined && fromPrompt != null) {\n common.setValueByPath(parentObject, ['instances[0]', 'prompt'], fromPrompt);\n }\n\n const fromImage = common.getValueByPath(fromObject, ['image']);\n if (parentObject !== undefined && fromImage != null) {\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'image'],\n imageToVertex(fromImage, rootObject),\n );\n }\n\n const fromScribbleImage = common.getValueByPath(fromObject, [\n 'scribbleImage',\n ]);\n if (parentObject !== undefined && fromScribbleImage != null) {\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'scribble'],\n scribbleImageToVertex(fromScribbleImage, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function toolConfigToMldev(\n fromObject: types.ToolConfig,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromRetrievalConfig = common.getValueByPath(fromObject, [\n 'retrievalConfig',\n ]);\n if (fromRetrievalConfig != null) {\n common.setValueByPath(toObject, ['retrievalConfig'], fromRetrievalConfig);\n }\n\n const fromFunctionCallingConfig = common.getValueByPath(fromObject, [\n 'functionCallingConfig',\n ]);\n if (fromFunctionCallingConfig != null) {\n common.setValueByPath(\n toObject,\n ['functionCallingConfig'],\n functionCallingConfigToMldev(fromFunctionCallingConfig, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function toolToMldev(\n fromObject: types.Tool,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['retrieval']) !== undefined) {\n throw new Error('retrieval parameter is not supported in Gemini API.');\n }\n\n const fromComputerUse = common.getValueByPath(fromObject, ['computerUse']);\n if (fromComputerUse != null) {\n common.setValueByPath(toObject, ['computerUse'], fromComputerUse);\n }\n\n const fromFileSearch = common.getValueByPath(fromObject, ['fileSearch']);\n if (fromFileSearch != null) {\n common.setValueByPath(toObject, ['fileSearch'], fromFileSearch);\n }\n\n const fromCodeExecution = common.getValueByPath(fromObject, [\n 'codeExecution',\n ]);\n if (fromCodeExecution != null) {\n common.setValueByPath(toObject, ['codeExecution'], fromCodeExecution);\n }\n\n if (\n common.getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined\n ) {\n throw new Error(\n 'enterpriseWebSearch parameter is not supported in Gemini API.',\n );\n }\n\n const fromFunctionDeclarations = common.getValueByPath(fromObject, [\n 'functionDeclarations',\n ]);\n if (fromFunctionDeclarations != null) {\n let transformedList = fromFunctionDeclarations;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['functionDeclarations'], transformedList);\n }\n\n const fromGoogleMaps = common.getValueByPath(fromObject, ['googleMaps']);\n if (fromGoogleMaps != null) {\n common.setValueByPath(\n toObject,\n ['googleMaps'],\n googleMapsToMldev(fromGoogleMaps, rootObject),\n );\n }\n\n const fromGoogleSearch = common.getValueByPath(fromObject, ['googleSearch']);\n if (fromGoogleSearch != null) {\n common.setValueByPath(\n toObject,\n ['googleSearch'],\n googleSearchToMldev(fromGoogleSearch, rootObject),\n );\n }\n\n const fromGoogleSearchRetrieval = common.getValueByPath(fromObject, [\n 'googleSearchRetrieval',\n ]);\n if (fromGoogleSearchRetrieval != null) {\n common.setValueByPath(\n toObject,\n ['googleSearchRetrieval'],\n fromGoogleSearchRetrieval,\n );\n }\n\n const fromUrlContext = common.getValueByPath(fromObject, ['urlContext']);\n if (fromUrlContext != null) {\n common.setValueByPath(toObject, ['urlContext'], fromUrlContext);\n }\n\n return toObject;\n}\n\nexport function toolToVertex(\n fromObject: types.Tool,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromRetrieval = common.getValueByPath(fromObject, ['retrieval']);\n if (fromRetrieval != null) {\n common.setValueByPath(toObject, ['retrieval'], fromRetrieval);\n }\n\n const fromComputerUse = common.getValueByPath(fromObject, ['computerUse']);\n if (fromComputerUse != null) {\n common.setValueByPath(toObject, ['computerUse'], fromComputerUse);\n }\n\n if (common.getValueByPath(fromObject, ['fileSearch']) !== undefined) {\n throw new Error('fileSearch parameter is not supported in Vertex AI.');\n }\n\n const fromCodeExecution = common.getValueByPath(fromObject, [\n 'codeExecution',\n ]);\n if (fromCodeExecution != null) {\n common.setValueByPath(toObject, ['codeExecution'], fromCodeExecution);\n }\n\n const fromEnterpriseWebSearch = common.getValueByPath(fromObject, [\n 'enterpriseWebSearch',\n ]);\n if (fromEnterpriseWebSearch != null) {\n common.setValueByPath(\n toObject,\n ['enterpriseWebSearch'],\n fromEnterpriseWebSearch,\n );\n }\n\n const fromFunctionDeclarations = common.getValueByPath(fromObject, [\n 'functionDeclarations',\n ]);\n if (fromFunctionDeclarations != null) {\n let transformedList = fromFunctionDeclarations;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return functionDeclarationToVertex(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['functionDeclarations'], transformedList);\n }\n\n const fromGoogleMaps = common.getValueByPath(fromObject, ['googleMaps']);\n if (fromGoogleMaps != null) {\n common.setValueByPath(toObject, ['googleMaps'], fromGoogleMaps);\n }\n\n const fromGoogleSearch = common.getValueByPath(fromObject, ['googleSearch']);\n if (fromGoogleSearch != null) {\n common.setValueByPath(toObject, ['googleSearch'], fromGoogleSearch);\n }\n\n const fromGoogleSearchRetrieval = common.getValueByPath(fromObject, [\n 'googleSearchRetrieval',\n ]);\n if (fromGoogleSearchRetrieval != null) {\n common.setValueByPath(\n toObject,\n ['googleSearchRetrieval'],\n fromGoogleSearchRetrieval,\n );\n }\n\n const fromUrlContext = common.getValueByPath(fromObject, ['urlContext']);\n if (fromUrlContext != null) {\n common.setValueByPath(toObject, ['urlContext'], fromUrlContext);\n }\n\n return toObject;\n}\n\nexport function tunedModelInfoFromMldev(\n fromObject: types.TunedModelInfo,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromBaseModel = common.getValueByPath(fromObject, ['baseModel']);\n if (fromBaseModel != null) {\n common.setValueByPath(toObject, ['baseModel'], fromBaseModel);\n }\n\n const fromCreateTime = common.getValueByPath(fromObject, ['createTime']);\n if (fromCreateTime != null) {\n common.setValueByPath(toObject, ['createTime'], fromCreateTime);\n }\n\n const fromUpdateTime = common.getValueByPath(fromObject, ['updateTime']);\n if (fromUpdateTime != null) {\n common.setValueByPath(toObject, ['updateTime'], fromUpdateTime);\n }\n\n return toObject;\n}\n\nexport function tunedModelInfoFromVertex(\n fromObject: types.TunedModelInfo,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromBaseModel = common.getValueByPath(fromObject, [\n 'labels',\n 'google-vertex-llm-tuning-base-model-id',\n ]);\n if (fromBaseModel != null) {\n common.setValueByPath(toObject, ['baseModel'], fromBaseModel);\n }\n\n const fromCreateTime = common.getValueByPath(fromObject, ['createTime']);\n if (fromCreateTime != null) {\n common.setValueByPath(toObject, ['createTime'], fromCreateTime);\n }\n\n const fromUpdateTime = common.getValueByPath(fromObject, ['updateTime']);\n if (fromUpdateTime != null) {\n common.setValueByPath(toObject, ['updateTime'], fromUpdateTime);\n }\n\n return toObject;\n}\n\nexport function updateModelConfigToMldev(\n fromObject: types.UpdateModelConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromDisplayName = common.getValueByPath(fromObject, ['displayName']);\n if (parentObject !== undefined && fromDisplayName != null) {\n common.setValueByPath(parentObject, ['displayName'], fromDisplayName);\n }\n\n const fromDescription = common.getValueByPath(fromObject, ['description']);\n if (parentObject !== undefined && fromDescription != null) {\n common.setValueByPath(parentObject, ['description'], fromDescription);\n }\n\n const fromDefaultCheckpointId = common.getValueByPath(fromObject, [\n 'defaultCheckpointId',\n ]);\n if (parentObject !== undefined && fromDefaultCheckpointId != null) {\n common.setValueByPath(\n parentObject,\n ['defaultCheckpointId'],\n fromDefaultCheckpointId,\n );\n }\n\n return toObject;\n}\n\nexport function updateModelConfigToVertex(\n fromObject: types.UpdateModelConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromDisplayName = common.getValueByPath(fromObject, ['displayName']);\n if (parentObject !== undefined && fromDisplayName != null) {\n common.setValueByPath(parentObject, ['displayName'], fromDisplayName);\n }\n\n const fromDescription = common.getValueByPath(fromObject, ['description']);\n if (parentObject !== undefined && fromDescription != null) {\n common.setValueByPath(parentObject, ['description'], fromDescription);\n }\n\n const fromDefaultCheckpointId = common.getValueByPath(fromObject, [\n 'defaultCheckpointId',\n ]);\n if (parentObject !== undefined && fromDefaultCheckpointId != null) {\n common.setValueByPath(\n parentObject,\n ['defaultCheckpointId'],\n fromDefaultCheckpointId,\n );\n }\n\n return toObject;\n}\n\nexport function updateModelParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.UpdateModelParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n updateModelConfigToMldev(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function updateModelParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.UpdateModelParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n updateModelConfigToVertex(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function upscaleImageAPIConfigInternalToVertex(\n fromObject: _internal_types.UpscaleImageAPIConfigInternal,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromOutputGcsUri = common.getValueByPath(fromObject, ['outputGcsUri']);\n if (parentObject !== undefined && fromOutputGcsUri != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'storageUri'],\n fromOutputGcsUri,\n );\n }\n\n const fromSafetyFilterLevel = common.getValueByPath(fromObject, [\n 'safetyFilterLevel',\n ]);\n if (parentObject !== undefined && fromSafetyFilterLevel != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'safetySetting'],\n fromSafetyFilterLevel,\n );\n }\n\n const fromPersonGeneration = common.getValueByPath(fromObject, [\n 'personGeneration',\n ]);\n if (parentObject !== undefined && fromPersonGeneration != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'personGeneration'],\n fromPersonGeneration,\n );\n }\n\n const fromIncludeRaiReason = common.getValueByPath(fromObject, [\n 'includeRaiReason',\n ]);\n if (parentObject !== undefined && fromIncludeRaiReason != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'includeRaiReason'],\n fromIncludeRaiReason,\n );\n }\n\n const fromOutputMimeType = common.getValueByPath(fromObject, [\n 'outputMimeType',\n ]);\n if (parentObject !== undefined && fromOutputMimeType != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'outputOptions', 'mimeType'],\n fromOutputMimeType,\n );\n }\n\n const fromOutputCompressionQuality = common.getValueByPath(fromObject, [\n 'outputCompressionQuality',\n ]);\n if (parentObject !== undefined && fromOutputCompressionQuality != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'outputOptions', 'compressionQuality'],\n fromOutputCompressionQuality,\n );\n }\n\n const fromEnhanceInputImage = common.getValueByPath(fromObject, [\n 'enhanceInputImage',\n ]);\n if (parentObject !== undefined && fromEnhanceInputImage != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'upscaleConfig', 'enhanceInputImage'],\n fromEnhanceInputImage,\n );\n }\n\n const fromImagePreservationFactor = common.getValueByPath(fromObject, [\n 'imagePreservationFactor',\n ]);\n if (parentObject !== undefined && fromImagePreservationFactor != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'upscaleConfig', 'imagePreservationFactor'],\n fromImagePreservationFactor,\n );\n }\n\n const fromLabels = common.getValueByPath(fromObject, ['labels']);\n if (parentObject !== undefined && fromLabels != null) {\n common.setValueByPath(parentObject, ['labels'], fromLabels);\n }\n\n const fromNumberOfImages = common.getValueByPath(fromObject, [\n 'numberOfImages',\n ]);\n if (parentObject !== undefined && fromNumberOfImages != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'sampleCount'],\n fromNumberOfImages,\n );\n }\n\n const fromMode = common.getValueByPath(fromObject, ['mode']);\n if (parentObject !== undefined && fromMode != null) {\n common.setValueByPath(parentObject, ['parameters', 'mode'], fromMode);\n }\n\n return toObject;\n}\n\nexport function upscaleImageAPIParametersInternalToVertex(\n apiClient: ApiClient,\n fromObject: _internal_types.UpscaleImageAPIParametersInternal,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromImage = common.getValueByPath(fromObject, ['image']);\n if (fromImage != null) {\n common.setValueByPath(\n toObject,\n ['instances[0]', 'image'],\n imageToVertex(fromImage, rootObject),\n );\n }\n\n const fromUpscaleFactor = common.getValueByPath(fromObject, [\n 'upscaleFactor',\n ]);\n if (fromUpscaleFactor != null) {\n common.setValueByPath(\n toObject,\n ['parameters', 'upscaleConfig', 'upscaleFactor'],\n fromUpscaleFactor,\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n upscaleImageAPIConfigInternalToVertex(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function upscaleImageResponseFromVertex(\n fromObject: types.UpscaleImageResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromGeneratedImages = common.getValueByPath(fromObject, [\n 'predictions',\n ]);\n if (fromGeneratedImages != null) {\n let transformedList = fromGeneratedImages;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return generatedImageFromVertex(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['generatedImages'], transformedList);\n }\n\n return toObject;\n}\n\nexport function videoFromMldev(\n fromObject: types.Video,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromUri = common.getValueByPath(fromObject, ['uri']);\n if (fromUri != null) {\n common.setValueByPath(toObject, ['uri'], fromUri);\n }\n\n const fromVideoBytes = common.getValueByPath(fromObject, ['encodedVideo']);\n if (fromVideoBytes != null) {\n common.setValueByPath(toObject, ['videoBytes'], t.tBytes(fromVideoBytes));\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['encoding']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function videoFromVertex(\n fromObject: types.Video,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromUri = common.getValueByPath(fromObject, ['gcsUri']);\n if (fromUri != null) {\n common.setValueByPath(toObject, ['uri'], fromUri);\n }\n\n const fromVideoBytes = common.getValueByPath(fromObject, [\n 'bytesBase64Encoded',\n ]);\n if (fromVideoBytes != null) {\n common.setValueByPath(toObject, ['videoBytes'], t.tBytes(fromVideoBytes));\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function videoGenerationMaskToVertex(\n fromObject: types.VideoGenerationMask,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromImage = common.getValueByPath(fromObject, ['image']);\n if (fromImage != null) {\n common.setValueByPath(\n toObject,\n ['_self'],\n imageToVertex(fromImage, rootObject),\n );\n }\n\n const fromMaskMode = common.getValueByPath(fromObject, ['maskMode']);\n if (fromMaskMode != null) {\n common.setValueByPath(toObject, ['maskMode'], fromMaskMode);\n }\n\n return toObject;\n}\n\nexport function videoGenerationReferenceImageToMldev(\n fromObject: types.VideoGenerationReferenceImage,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromImage = common.getValueByPath(fromObject, ['image']);\n if (fromImage != null) {\n common.setValueByPath(\n toObject,\n ['image'],\n imageToMldev(fromImage, rootObject),\n );\n }\n\n const fromReferenceType = common.getValueByPath(fromObject, [\n 'referenceType',\n ]);\n if (fromReferenceType != null) {\n common.setValueByPath(toObject, ['referenceType'], fromReferenceType);\n }\n\n return toObject;\n}\n\nexport function videoGenerationReferenceImageToVertex(\n fromObject: types.VideoGenerationReferenceImage,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromImage = common.getValueByPath(fromObject, ['image']);\n if (fromImage != null) {\n common.setValueByPath(\n toObject,\n ['image'],\n imageToVertex(fromImage, rootObject),\n );\n }\n\n const fromReferenceType = common.getValueByPath(fromObject, [\n 'referenceType',\n ]);\n if (fromReferenceType != null) {\n common.setValueByPath(toObject, ['referenceType'], fromReferenceType);\n }\n\n return toObject;\n}\n\nexport function videoToMldev(\n fromObject: types.Video,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromUri = common.getValueByPath(fromObject, ['uri']);\n if (fromUri != null) {\n common.setValueByPath(toObject, ['uri'], fromUri);\n }\n\n const fromVideoBytes = common.getValueByPath(fromObject, ['videoBytes']);\n if (fromVideoBytes != null) {\n common.setValueByPath(toObject, ['encodedVideo'], t.tBytes(fromVideoBytes));\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['encoding'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function videoToVertex(\n fromObject: types.Video,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromUri = common.getValueByPath(fromObject, ['uri']);\n if (fromUri != null) {\n common.setValueByPath(toObject, ['gcsUri'], fromUri);\n }\n\n const fromVideoBytes = common.getValueByPath(fromObject, ['videoBytes']);\n if (fromVideoBytes != null) {\n common.setValueByPath(\n toObject,\n ['bytesBase64Encoded'],\n t.tBytes(fromVideoBytes),\n );\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type {Client as McpClient} from '@modelcontextprotocol/sdk/client/index.js';\nimport type {Tool as McpTool} from '@modelcontextprotocol/sdk/types.js';\n\nimport {GOOGLE_API_CLIENT_HEADER} from '../_api_client.js';\nimport {mcpToolsToGeminiTool} from '../_transformers.js';\nimport {\n CallableTool,\n CallableToolConfig,\n FunctionCall,\n Part,\n Tool,\n ToolListUnion,\n} from '../types.js';\n\n// TODO: b/416041229 - Determine how to retrieve the MCP package version.\nexport const MCP_LABEL = 'mcp_used/unknown';\n\n// Whether MCP tool usage is detected from mcpToTool. This is used for\n// telemetry.\nlet hasMcpToolUsageFromMcpToTool = false;\n\n// Checks whether the list of tools contains any MCP tools.\nexport function hasMcpToolUsage(tools: ToolListUnion): boolean {\n for (const tool of tools) {\n if (isMcpCallableTool(tool)) {\n return true;\n }\n if (typeof tool === 'object' && 'inputSchema' in tool) {\n return true;\n }\n }\n\n return hasMcpToolUsageFromMcpToTool;\n}\n\n// Sets the MCP version label in the Google API client header.\nexport function setMcpUsageHeader(headers: Record<string, string>) {\n const existingHeader = headers[GOOGLE_API_CLIENT_HEADER] ?? '';\n headers[GOOGLE_API_CLIENT_HEADER] = (\n existingHeader + ` ${MCP_LABEL}`\n ).trimStart();\n}\n\n// Returns true if the object is a MCP CallableTool, otherwise false.\nfunction isMcpCallableTool(object: unknown): boolean {\n return (\n object !== null &&\n typeof object === 'object' &&\n object instanceof McpCallableTool\n );\n}\n\n// List all tools from the MCP client.\nasync function* listAllTools(\n mcpClient: McpClient,\n maxTools: number = 100,\n): AsyncGenerator<McpTool> {\n let cursor: string | undefined = undefined;\n let numTools = 0;\n while (numTools < maxTools) {\n const t = await mcpClient.listTools({cursor});\n for (const tool of t.tools) {\n yield tool;\n numTools++;\n }\n if (!t.nextCursor) {\n break;\n }\n cursor = t.nextCursor;\n }\n}\n\n/**\n * McpCallableTool can be used for model inference and invoking MCP clients with\n * given function call arguments.\n *\n * @experimental Built-in MCP support is an experimental feature, may change in future\n * versions.\n */\nexport class McpCallableTool implements CallableTool {\n private readonly mcpClients;\n private mcpTools: McpTool[] = [];\n private functionNameToMcpClient: Record<string, McpClient> = {};\n private readonly config: CallableToolConfig;\n\n private constructor(\n mcpClients: McpClient[] = [],\n config: CallableToolConfig,\n ) {\n this.mcpClients = mcpClients;\n this.config = config;\n }\n\n /**\n * Creates a McpCallableTool.\n */\n public static create(\n mcpClients: McpClient[],\n config: CallableToolConfig,\n ): McpCallableTool {\n return new McpCallableTool(mcpClients, config);\n }\n\n /**\n * Validates the function names are not duplicate and initialize the function\n * name to MCP client mapping.\n *\n * @throws {Error} if the MCP tools from the MCP clients have duplicate tool\n * names.\n */\n async initialize() {\n if (this.mcpTools.length > 0) {\n return;\n }\n\n const functionMap: Record<string, McpClient> = {};\n const mcpTools: McpTool[] = [];\n for (const mcpClient of this.mcpClients) {\n for await (const mcpTool of listAllTools(mcpClient)) {\n mcpTools.push(mcpTool);\n const mcpToolName = mcpTool.name as string;\n if (functionMap[mcpToolName]) {\n throw new Error(\n `Duplicate function name ${\n mcpToolName\n } found in MCP tools. Please ensure function names are unique.`,\n );\n }\n functionMap[mcpToolName] = mcpClient;\n }\n }\n this.mcpTools = mcpTools;\n this.functionNameToMcpClient = functionMap;\n }\n\n public async tool(): Promise<Tool> {\n await this.initialize();\n return mcpToolsToGeminiTool(this.mcpTools, this.config);\n }\n\n public async callTool(functionCalls: FunctionCall[]): Promise<Part[]> {\n await this.initialize();\n const functionCallResponseParts: Part[] = [];\n for (const functionCall of functionCalls) {\n if (functionCall.name! in this.functionNameToMcpClient) {\n const mcpClient = this.functionNameToMcpClient[functionCall.name!];\n let requestOptions = undefined;\n // TODO: b/424238654 - Add support for finer grained timeout control.\n if (this.config.timeout) {\n requestOptions = {\n timeout: this.config.timeout,\n };\n }\n const callToolResponse = await mcpClient.callTool(\n {\n name: functionCall.name!,\n arguments: functionCall.args,\n },\n // Set the result schema to undefined to allow MCP to rely on the\n // default schema.\n undefined,\n requestOptions,\n );\n functionCallResponseParts.push({\n functionResponse: {\n name: functionCall.name,\n response: callToolResponse.isError\n ? {error: callToolResponse}\n : (callToolResponse as Record<string, unknown>),\n },\n });\n }\n }\n return functionCallResponseParts;\n }\n}\n\nfunction isMcpClient(client: unknown): client is McpClient {\n return (\n client !== null &&\n typeof client === 'object' &&\n 'listTools' in client &&\n typeof client.listTools === 'function'\n );\n}\n\n/**\n * Creates a McpCallableTool from MCP clients and an optional config.\n *\n * The callable tool can invoke the MCP clients with given function call\n * arguments. (often for automatic function calling).\n * Use the config to modify tool parameters such as behavior.\n *\n * @experimental Built-in MCP support is an experimental feature, may change in future\n * versions.\n */\nexport function mcpToTool(\n ...args: [...McpClient[], CallableToolConfig | McpClient]\n): CallableTool {\n // Set MCP usage for telemetry.\n hasMcpToolUsageFromMcpToTool = true;\n if (args.length === 0) {\n throw new Error('No MCP clients provided');\n }\n const maybeConfig = args[args.length - 1];\n if (isMcpClient(maybeConfig)) {\n return McpCallableTool.create(args as McpClient[], {});\n }\n return McpCallableTool.create(\n args.slice(0, args.length - 1) as McpClient[],\n maybeConfig,\n );\n}\n\n/**\n * Sets the MCP tool usage flag from calling mcpToTool. This is used for\n * telemetry.\n */\nexport function setMcpToolUsageFromMcpToTool(mcpToolUsage: boolean) {\n hasMcpToolUsageFromMcpToTool = mcpToolUsage;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Live music client.\n *\n * @experimental\n */\n\nimport {ApiClient} from './_api_client.js';\nimport {Auth} from './_auth.js';\nimport * as t from './_transformers.js';\nimport {WebSocket, WebSocketCallbacks, WebSocketFactory} from './_websocket.js';\nimport * as converters from './converters/_live_converters.js';\nimport * as types from './types.js';\n\n/**\n * Handles incoming messages from the WebSocket.\n *\n * @remarks\n * This function is responsible for parsing incoming messages, transforming them\n * into LiveMusicServerMessage, and then calling the onmessage callback.\n * Note that the first message which is received from the server is a\n * setupComplete message.\n *\n * @param apiClient The ApiClient instance.\n * @param onmessage The user-provided onmessage callback (if any).\n * @param event The MessageEvent from the WebSocket.\n */\nasync function handleWebSocketMessage(\n apiClient: ApiClient,\n onmessage: (msg: types.LiveMusicServerMessage) => void,\n event: MessageEvent,\n): Promise<void> {\n const serverMessage: types.LiveMusicServerMessage =\n new types.LiveMusicServerMessage();\n let data: types.LiveMusicServerMessage;\n if (event.data instanceof Blob) {\n data = JSON.parse(await event.data.text()) as types.LiveMusicServerMessage;\n } else {\n data = JSON.parse(event.data) as types.LiveMusicServerMessage;\n }\n Object.assign(serverMessage, data);\n onmessage(serverMessage);\n}\n\n/**\n LiveMusic class encapsulates the configuration for live music\n generation via Lyria Live models.\n\n @experimental\n */\nexport class LiveMusic {\n constructor(\n private readonly apiClient: ApiClient,\n private readonly auth: Auth,\n private readonly webSocketFactory: WebSocketFactory,\n ) {}\n\n /**\n Establishes a connection to the specified model and returns a\n LiveMusicSession object representing that connection.\n\n @experimental\n\n @remarks\n\n @param params - The parameters for establishing a connection to the model.\n @return A live session.\n\n @example\n ```ts\n let model = 'models/lyria-realtime-exp';\n const session = await ai.live.music.connect({\n model: model,\n callbacks: {\n onmessage: (e: MessageEvent) => {\n console.log('Received message from the server: %s\\n', debug(e.data));\n },\n onerror: (e: ErrorEvent) => {\n console.log('Error occurred: %s\\n', debug(e.error));\n },\n onclose: (e: CloseEvent) => {\n console.log('Connection closed.');\n },\n },\n });\n ```\n */\n async connect(\n params: types.LiveMusicConnectParameters,\n ): Promise<LiveMusicSession> {\n if (this.apiClient.isVertexAI()) {\n throw new Error('Live music is not supported for Vertex AI.');\n }\n console.warn(\n 'Live music generation is experimental and may change in future versions.',\n );\n\n const websocketBaseUrl = this.apiClient.getWebsocketBaseUrl();\n const apiVersion = this.apiClient.getApiVersion();\n const headers = mapToHeaders(this.apiClient.getDefaultHeaders());\n const apiKey = this.apiClient.getApiKey();\n const url = `${websocketBaseUrl}/ws/google.ai.generativelanguage.${\n apiVersion\n }.GenerativeService.BidiGenerateMusic?key=${apiKey}`;\n\n let onopenResolve: (value: unknown) => void = () => {};\n const onopenPromise = new Promise((resolve: (value: unknown) => void) => {\n onopenResolve = resolve;\n });\n\n const callbacks: types.LiveMusicCallbacks = params.callbacks;\n\n const onopenAwaitedCallback = function () {\n onopenResolve({});\n };\n\n const apiClient = this.apiClient;\n const websocketCallbacks: WebSocketCallbacks = {\n onopen: onopenAwaitedCallback,\n onmessage: (event: MessageEvent) => {\n void handleWebSocketMessage(apiClient, callbacks.onmessage, event);\n },\n onerror:\n callbacks?.onerror ??\n function (e: ErrorEvent) {\n void e;\n },\n onclose:\n callbacks?.onclose ??\n function (e: CloseEvent) {\n void e;\n },\n };\n\n const conn = this.webSocketFactory.create(\n url,\n headersToMap(headers),\n websocketCallbacks,\n );\n conn.connect();\n // Wait for the websocket to open before sending requests.\n await onopenPromise;\n\n const model = t.tModel(this.apiClient, params.model);\n const setup = {model};\n const clientMessage = {setup};\n conn.send(JSON.stringify(clientMessage));\n\n return new LiveMusicSession(conn, this.apiClient);\n }\n}\n\n/**\n Represents a connection to the API.\n\n @experimental\n */\nexport class LiveMusicSession {\n constructor(\n readonly conn: WebSocket,\n private readonly apiClient: ApiClient,\n ) {}\n\n /**\n Sets inputs to steer music generation. Updates the session's current\n weighted prompts.\n\n @param params - Contains one property, `weightedPrompts`.\n\n - `weightedPrompts` to send to the model; weights are normalized to\n sum to 1.0.\n\n @experimental\n */\n async setWeightedPrompts(\n params: types.LiveMusicSetWeightedPromptsParameters,\n ) {\n if (\n !params.weightedPrompts ||\n Object.keys(params.weightedPrompts).length === 0\n ) {\n throw new Error(\n 'Weighted prompts must be set and contain at least one entry.',\n );\n }\n const clientContent =\n converters.liveMusicSetWeightedPromptsParametersToMldev(params);\n this.conn.send(JSON.stringify({clientContent}));\n }\n\n /**\n Sets a configuration to the model. Updates the session's current\n music generation config.\n\n @param params - Contains one property, `musicGenerationConfig`.\n\n - `musicGenerationConfig` to set in the model. Passing an empty or\n undefined config to the model will reset the config to defaults.\n\n @experimental\n */\n async setMusicGenerationConfig(params: types.LiveMusicSetConfigParameters) {\n if (!params.musicGenerationConfig) {\n params.musicGenerationConfig = {};\n }\n const setConfigParameters =\n converters.liveMusicSetConfigParametersToMldev(params);\n this.conn.send(JSON.stringify(setConfigParameters));\n }\n\n private sendPlaybackControl(playbackControl: types.LiveMusicPlaybackControl) {\n const clientMessage = {playbackControl};\n this.conn.send(JSON.stringify(clientMessage));\n }\n\n /**\n * Start the music stream.\n *\n * @experimental\n */\n play() {\n this.sendPlaybackControl(types.LiveMusicPlaybackControl.PLAY);\n }\n\n /**\n * Temporarily halt the music stream. Use `play` to resume from the current\n * position.\n *\n * @experimental\n */\n pause() {\n this.sendPlaybackControl(types.LiveMusicPlaybackControl.PAUSE);\n }\n\n /**\n * Stop the music stream and reset the state. Retains the current prompts\n * and config.\n *\n * @experimental\n */\n stop() {\n this.sendPlaybackControl(types.LiveMusicPlaybackControl.STOP);\n }\n\n /**\n * Resets the context of the music generation without stopping it.\n * Retains the current prompts and config.\n *\n * @experimental\n */\n resetContext() {\n this.sendPlaybackControl(types.LiveMusicPlaybackControl.RESET_CONTEXT);\n }\n\n /**\n Terminates the WebSocket connection.\n\n @experimental\n */\n close() {\n this.conn.close();\n }\n}\n\n// Converts an headers object to a \"map\" object as expected by the WebSocket\n// constructor. We use this as the Auth interface works with Headers objects\n// while the WebSocket constructor takes a map.\nfunction headersToMap(headers: Headers): Record<string, string> {\n const headerMap: Record<string, string> = {};\n headers.forEach((value, key) => {\n headerMap[key] = value;\n });\n return headerMap;\n}\n\n// Converts a \"map\" object to a headers object. We use this as the Auth\n// interface works with Headers objects while the API client default headers\n// returns a map.\nfunction mapToHeaders(map: Record<string, string>): Headers {\n const headers = new Headers();\n for (const [key, value] of Object.entries(map)) {\n headers.append(key, value);\n }\n return headers;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Live client.\n *\n * @experimental\n */\n\nimport {ApiClient} from './_api_client.js';\nimport {Auth} from './_auth.js';\nimport * as t from './_transformers.js';\nimport {WebSocket, WebSocketCallbacks, WebSocketFactory} from './_websocket.js';\nimport * as converters from './converters/_live_converters.js';\nimport {contentToMldev} from './converters/_models_converters.js';\nimport {hasMcpToolUsage, setMcpUsageHeader} from './mcp/_mcp.js';\nimport {LiveMusic} from './music.js';\nimport * as types from './types.js';\n\nconst FUNCTION_RESPONSE_REQUIRES_ID =\n 'FunctionResponse request must have an `id` field from the response of a ToolCall.FunctionalCalls in Google AI.';\n\n/**\n * Handles incoming messages from the WebSocket.\n *\n * @remarks\n * This function is responsible for parsing incoming messages, transforming them\n * into LiveServerMessages, and then calling the onmessage callback. Note that\n * the first message which is received from the server is a setupComplete\n * message.\n *\n * @param apiClient The ApiClient instance.\n * @param onmessage The user-provided onmessage callback (if any).\n * @param event The MessageEvent from the WebSocket.\n */\nasync function handleWebSocketMessage(\n apiClient: ApiClient,\n onmessage: (msg: types.LiveServerMessage) => void,\n event: MessageEvent,\n): Promise<void> {\n const serverMessage: types.LiveServerMessage = new types.LiveServerMessage();\n let jsonData: string;\n if (event.data instanceof Blob) {\n jsonData = await event.data.text();\n } else if (event.data instanceof ArrayBuffer) {\n jsonData = new TextDecoder().decode(event.data);\n } else {\n jsonData = event.data;\n }\n\n const data = JSON.parse(jsonData) as types.LiveServerMessage;\n\n if (apiClient.isVertexAI()) {\n const resp = converters.liveServerMessageFromVertex(data);\n Object.assign(serverMessage, resp);\n } else {\n const resp = data;\n Object.assign(serverMessage, resp);\n }\n\n onmessage(serverMessage);\n}\n\n/**\n Live class encapsulates the configuration for live interaction with the\n Generative Language API. It embeds ApiClient for general API settings.\n\n @experimental\n */\nexport class Live {\n public readonly music: LiveMusic;\n\n constructor(\n private readonly apiClient: ApiClient,\n private readonly auth: Auth,\n private readonly webSocketFactory: WebSocketFactory,\n ) {\n this.music = new LiveMusic(\n this.apiClient,\n this.auth,\n this.webSocketFactory,\n );\n }\n\n /**\n Establishes a connection to the specified model with the given\n configuration and returns a Session object representing that connection.\n\n @experimental Built-in MCP support is an experimental feature, may change in\n future versions.\n\n @remarks\n\n @param params - The parameters for establishing a connection to the model.\n @return A live session.\n\n @example\n ```ts\n let model: string;\n if (GOOGLE_GENAI_USE_VERTEXAI) {\n model = 'gemini-2.0-flash-live-preview-04-09';\n } else {\n model = 'gemini-live-2.5-flash-preview';\n }\n const session = await ai.live.connect({\n model: model,\n config: {\n responseModalities: [Modality.AUDIO],\n },\n callbacks: {\n onopen: () => {\n console.log('Connected to the socket.');\n },\n onmessage: (e: MessageEvent) => {\n console.log('Received message from the server: %s\\n', debug(e.data));\n },\n onerror: (e: ErrorEvent) => {\n console.log('Error occurred: %s\\n', debug(e.error));\n },\n onclose: (e: CloseEvent) => {\n console.log('Connection closed.');\n },\n },\n });\n ```\n */\n async connect(params: types.LiveConnectParameters): Promise<Session> {\n // TODO: b/404946746 - Support per request HTTP options.\n if (params.config && params.config.httpOptions) {\n throw new Error(\n 'The Live module does not support httpOptions at request-level in' +\n ' LiveConnectConfig yet. Please use the client-level httpOptions' +\n ' configuration instead.',\n );\n }\n const websocketBaseUrl = this.apiClient.getWebsocketBaseUrl();\n const apiVersion = this.apiClient.getApiVersion();\n let url: string;\n const clientHeaders = this.apiClient.getHeaders();\n if (\n params.config &&\n params.config.tools &&\n hasMcpToolUsage(params.config.tools)\n ) {\n setMcpUsageHeader(clientHeaders);\n }\n const headers = mapToHeaders(clientHeaders);\n if (this.apiClient.isVertexAI()) {\n const project = this.apiClient.getProject();\n const location = this.apiClient.getLocation();\n const apiKey = this.apiClient.getApiKey();\n const hasStandardAuth = (!!project && !!location) || !!apiKey;\n\n if (this.apiClient.getCustomBaseUrl() && !hasStandardAuth) {\n // Custom base URL without standard auth (e.g., proxy).\n url = websocketBaseUrl;\n // Auth headers are assumed to be in `clientHeaders` from httpOptions.\n } else {\n url = `${websocketBaseUrl}/ws/google.cloud.aiplatform.${apiVersion}.LlmBidiService/BidiGenerateContent`;\n await this.auth.addAuthHeaders(headers, url);\n }\n } else {\n const apiKey = this.apiClient.getApiKey();\n\n let method = 'BidiGenerateContent';\n let keyName = 'key';\n if (apiKey?.startsWith('auth_tokens/')) {\n console.warn(\n 'Warning: Ephemeral token support is experimental and may change in future versions.',\n );\n if (apiVersion !== 'v1alpha') {\n console.warn(\n \"Warning: The SDK's ephemeral token support is in v1alpha only. Please use const ai = new GoogleGenAI({apiKey: token.name, httpOptions: { apiVersion: 'v1alpha' }}); before session connection.\",\n );\n }\n method = 'BidiGenerateContentConstrained';\n keyName = 'access_token';\n }\n\n url = `${websocketBaseUrl}/ws/google.ai.generativelanguage.${\n apiVersion\n }.GenerativeService.${method}?${keyName}=${apiKey}`;\n }\n\n let onopenResolve: (value: unknown) => void = () => {};\n const onopenPromise = new Promise((resolve: (value: unknown) => void) => {\n onopenResolve = resolve;\n });\n\n const callbacks: types.LiveCallbacks = params.callbacks;\n\n const onopenAwaitedCallback = function () {\n callbacks?.onopen?.();\n onopenResolve({});\n };\n\n const apiClient = this.apiClient;\n\n const websocketCallbacks: WebSocketCallbacks = {\n onopen: onopenAwaitedCallback,\n onmessage: (event: MessageEvent) => {\n void handleWebSocketMessage(apiClient, callbacks.onmessage, event);\n },\n onerror:\n callbacks?.onerror ??\n function (e: ErrorEvent) {\n void e;\n },\n onclose:\n callbacks?.onclose ??\n function (e: CloseEvent) {\n void e;\n },\n };\n\n const conn = this.webSocketFactory.create(\n url,\n headersToMap(headers),\n websocketCallbacks,\n );\n conn.connect();\n // Wait for the websocket to open before sending requests.\n await onopenPromise;\n\n let transformedModel = t.tModel(this.apiClient, params.model);\n if (\n this.apiClient.isVertexAI() &&\n transformedModel.startsWith('publishers/')\n ) {\n const project = this.apiClient.getProject();\n const location = this.apiClient.getLocation();\n if (project && location) {\n transformedModel =\n `projects/${project}/locations/${location}/` + transformedModel;\n }\n }\n\n let clientMessage: Record<string, unknown> = {};\n\n if (\n this.apiClient.isVertexAI() &&\n params.config?.responseModalities === undefined\n ) {\n // Set default to AUDIO to align with MLDev API.\n if (params.config === undefined) {\n params.config = {responseModalities: [types.Modality.AUDIO]};\n } else {\n params.config.responseModalities = [types.Modality.AUDIO];\n }\n }\n if (params.config?.generationConfig) {\n // Raise deprecation warning for generationConfig.\n console.warn(\n 'Setting `LiveConnectConfig.generation_config` is deprecated, please set the fields on `LiveConnectConfig` directly. This will become an error in a future version (not before Q3 2025).',\n );\n }\n const inputTools = params.config?.tools ?? [];\n const convertedTools: types.Tool[] = [];\n for (const tool of inputTools) {\n if (this.isCallableTool(tool)) {\n const callableTool = tool as types.CallableTool;\n convertedTools.push(await callableTool.tool());\n } else {\n convertedTools.push(tool as types.Tool);\n }\n }\n if (convertedTools.length > 0) {\n params.config!.tools = convertedTools;\n }\n const liveConnectParameters: types.LiveConnectParameters = {\n model: transformedModel,\n config: params.config,\n callbacks: params.callbacks,\n };\n if (this.apiClient.isVertexAI()) {\n clientMessage = converters.liveConnectParametersToVertex(\n this.apiClient,\n liveConnectParameters,\n );\n } else {\n clientMessage = converters.liveConnectParametersToMldev(\n this.apiClient,\n liveConnectParameters,\n );\n }\n delete clientMessage['config'];\n conn.send(JSON.stringify(clientMessage));\n return new Session(conn, this.apiClient);\n }\n\n // TODO: b/416041229 - Abstract this method to a common place.\n private isCallableTool(tool: types.ToolUnion): boolean {\n return 'callTool' in tool && typeof tool.callTool === 'function';\n }\n}\n\nconst defaultLiveSendClientContentParamerters: types.LiveSendClientContentParameters =\n {\n turnComplete: true,\n };\n\n/**\n Represents a connection to the API.\n\n @experimental\n */\nexport class Session {\n constructor(\n readonly conn: WebSocket,\n private readonly apiClient: ApiClient,\n ) {}\n\n private tLiveClientContent(\n apiClient: ApiClient,\n params: types.LiveSendClientContentParameters,\n ): types.LiveClientMessage {\n if (params.turns !== null && params.turns !== undefined) {\n let contents: types.Content[] = [];\n try {\n contents = t.tContents(params.turns as types.ContentListUnion);\n if (!apiClient.isVertexAI()) {\n contents = contents.map((item) => contentToMldev(item));\n }\n } catch {\n throw new Error(\n `Failed to parse client content \"turns\", type: '${typeof params.turns}'`,\n );\n }\n return {\n clientContent: {turns: contents, turnComplete: params.turnComplete},\n };\n }\n\n return {\n clientContent: {turnComplete: params.turnComplete},\n };\n }\n\n private tLiveClienttToolResponse(\n apiClient: ApiClient,\n params: types.LiveSendToolResponseParameters,\n ): types.LiveClientMessage {\n let functionResponses: types.FunctionResponse[] = [];\n\n if (params.functionResponses == null) {\n throw new Error('functionResponses is required.');\n }\n\n if (!Array.isArray(params.functionResponses)) {\n functionResponses = [params.functionResponses];\n } else {\n functionResponses = params.functionResponses;\n }\n\n if (functionResponses.length === 0) {\n throw new Error('functionResponses is required.');\n }\n\n for (const functionResponse of functionResponses) {\n if (\n typeof functionResponse !== 'object' ||\n functionResponse === null ||\n !('name' in functionResponse) ||\n !('response' in functionResponse)\n ) {\n throw new Error(\n `Could not parse function response, type '${typeof functionResponse}'.`,\n );\n }\n if (!apiClient.isVertexAI() && !('id' in functionResponse)) {\n throw new Error(FUNCTION_RESPONSE_REQUIRES_ID);\n }\n }\n\n const clientMessage: types.LiveClientMessage = {\n toolResponse: {functionResponses: functionResponses},\n };\n return clientMessage;\n }\n\n /**\n Send a message over the established connection.\n\n @param params - Contains two **optional** properties, `turns` and\n `turnComplete`.\n\n - `turns` will be converted to a `Content[]`\n - `turnComplete: true` [default] indicates that you are done sending\n content and expect a response. If `turnComplete: false`, the server\n will wait for additional messages before starting generation.\n\n @experimental\n\n @remarks\n There are two ways to send messages to the live API:\n `sendClientContent` and `sendRealtimeInput`.\n\n `sendClientContent` messages are added to the model context **in order**.\n Having a conversation using `sendClientContent` messages is roughly\n equivalent to using the `Chat.sendMessageStream`, except that the state of\n the `chat` history is stored on the API server instead of locally.\n\n Because of `sendClientContent`'s order guarantee, the model cannot respons\n as quickly to `sendClientContent` messages as to `sendRealtimeInput`\n messages. This makes the biggest difference when sending objects that have\n significant preprocessing time (typically images).\n\n The `sendClientContent` message sends a `Content[]`\n which has more options than the `Blob` sent by `sendRealtimeInput`.\n\n So the main use-cases for `sendClientContent` over `sendRealtimeInput` are:\n\n - Sending anything that can't be represented as a `Blob` (text,\n `sendClientContent({turns=\"Hello?\"}`)).\n - Managing turns when not using audio input and voice activity detection.\n (`sendClientContent({turnComplete:true})` or the short form\n `sendClientContent()`)\n - Prefilling a conversation context\n ```\n sendClientContent({\n turns: [\n Content({role:user, parts:...}),\n Content({role:user, parts:...}),\n ...\n ]\n })\n ```\n @experimental\n */\n sendClientContent(params: types.LiveSendClientContentParameters) {\n params = {\n ...defaultLiveSendClientContentParamerters,\n ...params,\n };\n\n const clientMessage: types.LiveClientMessage = this.tLiveClientContent(\n this.apiClient,\n params,\n );\n this.conn.send(JSON.stringify(clientMessage));\n }\n\n /**\n Send a realtime message over the established connection.\n\n @param params - Contains one property, `media`.\n\n - `media` will be converted to a `Blob`\n\n @experimental\n\n @remarks\n Use `sendRealtimeInput` for realtime audio chunks and video frames (images).\n\n With `sendRealtimeInput` the api will respond to audio automatically\n based on voice activity detection (VAD).\n\n `sendRealtimeInput` is optimized for responsivness at the expense of\n deterministic ordering guarantees. Audio and video tokens are to the\n context when they become available.\n\n Note: The Call signature expects a `Blob` object, but only a subset\n of audio and image mimetypes are allowed.\n */\n sendRealtimeInput(params: types.LiveSendRealtimeInputParameters) {\n let clientMessage: types.LiveClientMessage = {};\n\n if (this.apiClient.isVertexAI()) {\n clientMessage = {\n 'realtimeInput':\n converters.liveSendRealtimeInputParametersToVertex(params),\n };\n } else {\n clientMessage = {\n 'realtimeInput':\n converters.liveSendRealtimeInputParametersToMldev(params),\n };\n }\n this.conn.send(JSON.stringify(clientMessage));\n }\n\n /**\n Send a function response message over the established connection.\n\n @param params - Contains property `functionResponses`.\n\n - `functionResponses` will be converted to a `functionResponses[]`\n\n @remarks\n Use `sendFunctionResponse` to reply to `LiveServerToolCall` from the server.\n\n Use {@link types.LiveConnectConfig#tools} to configure the callable functions.\n\n @experimental\n */\n sendToolResponse(params: types.LiveSendToolResponseParameters) {\n if (params.functionResponses == null) {\n throw new Error('Tool response parameters are required.');\n }\n\n const clientMessage: types.LiveClientMessage =\n this.tLiveClienttToolResponse(this.apiClient, params);\n this.conn.send(JSON.stringify(clientMessage));\n }\n\n /**\n Terminates the WebSocket connection.\n\n @experimental\n\n @example\n ```ts\n let model: string;\n if (GOOGLE_GENAI_USE_VERTEXAI) {\n model = 'gemini-2.0-flash-live-preview-04-09';\n } else {\n model = 'gemini-live-2.5-flash-preview';\n }\n const session = await ai.live.connect({\n model: model,\n config: {\n responseModalities: [Modality.AUDIO],\n }\n });\n\n session.close();\n ```\n */\n close() {\n this.conn.close();\n }\n}\n\n// Converts an headers object to a \"map\" object as expected by the WebSocket\n// constructor. We use this as the Auth interface works with Headers objects\n// while the WebSocket constructor takes a map.\nfunction headersToMap(headers: Headers): Record<string, string> {\n const headerMap: Record<string, string> = {};\n headers.forEach((value, key) => {\n headerMap[key] = value;\n });\n return headerMap;\n}\n\n// Converts a \"map\" object to a headers object. We use this as the Auth\n// interface works with Headers objects while the API client default headers\n// returns a map.\nfunction mapToHeaders(map: Record<string, string>): Headers {\n const headers = new Headers();\n for (const [key, value] of Object.entries(map)) {\n headers.append(key, value);\n }\n return headers;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport * as types from './types.js';\n\nexport const DEFAULT_MAX_REMOTE_CALLS = 10;\n\n/** Returns whether automatic function calling is disabled. */\nexport function shouldDisableAfc(\n config: types.GenerateContentConfig | undefined,\n): boolean {\n if (config?.automaticFunctionCalling?.disable) {\n return true;\n }\n\n let callableToolsPresent = false;\n for (const tool of config?.tools ?? []) {\n if (isCallableTool(tool)) {\n callableToolsPresent = true;\n break;\n }\n }\n if (!callableToolsPresent) {\n return true;\n }\n\n const maxCalls = config?.automaticFunctionCalling?.maximumRemoteCalls;\n if (\n (maxCalls && (maxCalls < 0 || !Number.isInteger(maxCalls))) ||\n maxCalls == 0\n ) {\n console.warn(\n 'Invalid maximumRemoteCalls value provided for automatic function calling. Disabled automatic function calling. Please provide a valid integer value greater than 0. maximumRemoteCalls provided:',\n maxCalls,\n );\n return true;\n }\n return false;\n}\n\nexport function isCallableTool(tool: types.ToolUnion): boolean {\n return 'callTool' in tool && typeof tool.callTool === 'function';\n}\n\n// Checks whether the list of tools contains any CallableTools. Will return true\n// if there is at least one CallableTool.\nexport function hasCallableTools(\n params: types.GenerateContentParameters,\n): boolean {\n return params.config?.tools?.some((tool) => isCallableTool(tool)) ?? false;\n}\n\n/**\n * Returns the indexes of the tools that are not compatible with AFC.\n */\nexport function findAfcIncompatibleToolIndexes(\n params?: types.GenerateContentParameters,\n): number[] {\n // Use number[] for an array of numbers in TypeScript\n const afcIncompatibleToolIndexes: number[] = [];\n if (!params?.config?.tools) {\n return afcIncompatibleToolIndexes;\n }\n params.config.tools.forEach((tool, index) => {\n if (isCallableTool(tool)) {\n return;\n }\n const geminiTool = tool as types.Tool;\n if (\n geminiTool.functionDeclarations &&\n geminiTool.functionDeclarations.length > 0\n ) {\n afcIncompatibleToolIndexes.push(index);\n }\n });\n\n return afcIncompatibleToolIndexes;\n}\n\n/**\n * Returns whether to append automatic function calling history to the\n * response.\n */\nexport function shouldAppendAfcHistory(\n config: types.GenerateContentConfig | undefined,\n): boolean {\n return !config?.automaticFunctionCalling?.ignoreCallHistory;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport * as afc from './_afc.js';\nimport {ApiClient} from './_api_client.js';\nimport * as common from './_common.js';\nimport {BaseModule} from './_common.js';\nimport * as _internal_types from './_internal_types.js';\nimport {tContents} from './_transformers.js';\nimport * as converters from './converters/_models_converters.js';\nimport * as mcp from './mcp/_mcp.js';\nimport {PagedItem, Pager} from './pagers.js';\nimport * as types from './types.js';\n\nexport class Models extends BaseModule {\n constructor(private readonly apiClient: ApiClient) {\n super();\n }\n\n /**\n * Makes an API request to generate content with a given model.\n *\n * For the `model` parameter, supported formats for Vertex AI API include:\n * - The Gemini model ID, for example: 'gemini-2.0-flash'\n * - The full resource name starts with 'projects/', for example:\n * 'projects/my-project-id/locations/us-central1/publishers/google/models/gemini-2.0-flash'\n * - The partial resource name with 'publishers/', for example:\n * 'publishers/google/models/gemini-2.0-flash' or\n * 'publishers/meta/models/llama-3.1-405b-instruct-maas'\n * - `/` separated publisher and model name, for example:\n * 'google/gemini-2.0-flash' or 'meta/llama-3.1-405b-instruct-maas'\n *\n * For the `model` parameter, supported formats for Gemini API include:\n * - The Gemini model ID, for example: 'gemini-2.0-flash'\n * - The model name starts with 'models/', for example:\n * 'models/gemini-2.0-flash'\n * - For tuned models, the model name starts with 'tunedModels/',\n * for example:\n * 'tunedModels/1234567890123456789'\n *\n * Some models support multimodal input and output.\n *\n * @param params - The parameters for generating content.\n * @return The response from generating content.\n *\n * @example\n * ```ts\n * const response = await ai.models.generateContent({\n * model: 'gemini-2.0-flash',\n * contents: 'why is the sky blue?',\n * config: {\n * candidateCount: 2,\n * }\n * });\n * console.log(response);\n * ```\n */\n generateContent = async (\n params: types.GenerateContentParameters,\n ): Promise<types.GenerateContentResponse> => {\n const transformedParams = await this.processParamsMaybeAddMcpUsage(params);\n this.maybeMoveToResponseJsonSchem(params);\n if (!afc.hasCallableTools(params) || afc.shouldDisableAfc(params.config)) {\n return await this.generateContentInternal(transformedParams);\n }\n\n const incompatibleToolIndexes = afc.findAfcIncompatibleToolIndexes(params);\n if (incompatibleToolIndexes.length > 0) {\n const formattedIndexes = incompatibleToolIndexes\n .map((index: number) => `tools[${index}]`)\n .join(', ');\n throw new Error(\n `Automatic function calling with CallableTools (or MCP objects) and basic FunctionDeclarations is not yet supported. Incompatible tools found at ${formattedIndexes}.`,\n );\n }\n\n let response: types.GenerateContentResponse;\n let functionResponseContent: types.Content;\n const automaticFunctionCallingHistory: types.Content[] = tContents(\n transformedParams.contents,\n );\n const maxRemoteCalls =\n transformedParams.config?.automaticFunctionCalling?.maximumRemoteCalls ??\n afc.DEFAULT_MAX_REMOTE_CALLS;\n let remoteCalls = 0;\n while (remoteCalls < maxRemoteCalls) {\n response = await this.generateContentInternal(transformedParams);\n if (!response.functionCalls || response.functionCalls!.length === 0) {\n break;\n }\n\n const responseContent: types.Content = response.candidates![0].content!;\n const functionResponseParts: types.Part[] = [];\n for (const tool of params.config?.tools ?? []) {\n if (afc.isCallableTool(tool)) {\n const callableTool = tool as types.CallableTool;\n const parts = await callableTool.callTool(response.functionCalls!);\n functionResponseParts.push(...parts);\n }\n }\n\n remoteCalls++;\n\n functionResponseContent = {\n role: 'user',\n parts: functionResponseParts,\n };\n\n transformedParams.contents = tContents(transformedParams.contents);\n (transformedParams.contents as types.Content[]).push(responseContent);\n (transformedParams.contents as types.Content[]).push(\n functionResponseContent,\n );\n\n if (afc.shouldAppendAfcHistory(transformedParams.config)) {\n automaticFunctionCallingHistory.push(responseContent);\n automaticFunctionCallingHistory.push(functionResponseContent);\n }\n }\n if (afc.shouldAppendAfcHistory(transformedParams.config)) {\n response!.automaticFunctionCallingHistory =\n automaticFunctionCallingHistory;\n }\n return response!;\n };\n\n /**\n * This logic is needed for GenerateContentConfig only.\n * Previously we made GenerateContentConfig.responseSchema field to accept\n * unknown. Since v1.9.0, we switch to use backend JSON schema support.\n * To maintain backward compatibility, we move the data that was treated as\n * JSON schema from the responseSchema field to the responseJsonSchema field.\n */\n private maybeMoveToResponseJsonSchem(\n params: types.GenerateContentParameters,\n ): void {\n if (params.config && params.config.responseSchema) {\n if (!params.config.responseJsonSchema) {\n if (Object.keys(params.config.responseSchema).includes('$schema')) {\n params.config.responseJsonSchema = params.config.responseSchema;\n delete params.config.responseSchema;\n }\n }\n }\n return;\n }\n\n /**\n * Makes an API request to generate content with a given model and yields the\n * response in chunks.\n *\n * For the `model` parameter, supported formats for Vertex AI API include:\n * - The Gemini model ID, for example: 'gemini-2.0-flash'\n * - The full resource name starts with 'projects/', for example:\n * 'projects/my-project-id/locations/us-central1/publishers/google/models/gemini-2.0-flash'\n * - The partial resource name with 'publishers/', for example:\n * 'publishers/google/models/gemini-2.0-flash' or\n * 'publishers/meta/models/llama-3.1-405b-instruct-maas'\n * - `/` separated publisher and model name, for example:\n * 'google/gemini-2.0-flash' or 'meta/llama-3.1-405b-instruct-maas'\n *\n * For the `model` parameter, supported formats for Gemini API include:\n * - The Gemini model ID, for example: 'gemini-2.0-flash'\n * - The model name starts with 'models/', for example:\n * 'models/gemini-2.0-flash'\n * - For tuned models, the model name starts with 'tunedModels/',\n * for example:\n * 'tunedModels/1234567890123456789'\n *\n * Some models support multimodal input and output.\n *\n * @param params - The parameters for generating content with streaming response.\n * @return The response from generating content.\n *\n * @example\n * ```ts\n * const response = await ai.models.generateContentStream({\n * model: 'gemini-2.0-flash',\n * contents: 'why is the sky blue?',\n * config: {\n * maxOutputTokens: 200,\n * }\n * });\n * for await (const chunk of response) {\n * console.log(chunk);\n * }\n * ```\n */\n generateContentStream = async (\n params: types.GenerateContentParameters,\n ): Promise<AsyncGenerator<types.GenerateContentResponse>> => {\n this.maybeMoveToResponseJsonSchem(params);\n if (afc.shouldDisableAfc(params.config)) {\n const transformedParams =\n await this.processParamsMaybeAddMcpUsage(params);\n return await this.generateContentStreamInternal(transformedParams);\n }\n const incompatibleToolIndexes = afc.findAfcIncompatibleToolIndexes(params);\n if (incompatibleToolIndexes.length > 0) {\n const formattedIndexes = incompatibleToolIndexes\n .map((index: number) => `tools[${index}]`)\n .join(', ');\n throw new Error(\n `Incompatible tools found at ${formattedIndexes}. Automatic function calling with CallableTools (or MCP objects) and basic FunctionDeclarations\" is not yet supported.`,\n );\n }\n\n // With tool compatibility confirmed, validate that the configuration are\n // compatible with each other and raise an error if invalid.\n const streamFunctionCall =\n params?.config?.toolConfig?.functionCallingConfig\n ?.streamFunctionCallArguments;\n const disableAfc = params?.config?.automaticFunctionCalling?.disable;\n\n if (streamFunctionCall && !disableAfc) {\n throw new Error(\n \"Running in streaming mode with 'streamFunctionCallArguments' enabled, \" +\n 'this feature is not compatible with automatic function calling (AFC). ' +\n \"Please set 'config.automaticFunctionCalling.disable' to true to disable AFC \" +\n \"or leave 'config.toolConfig.functionCallingConfig.streamFunctionCallArguments' \" +\n 'to be undefined or set to false to disable streaming function call arguments feature.',\n );\n }\n\n return await this.processAfcStream(params);\n };\n\n /**\n * Transforms the CallableTools in the parameters to be simply Tools, it\n * copies the params into a new object and replaces the tools, it does not\n * modify the original params. Also sets the MCP usage header if there are\n * MCP tools in the parameters.\n */\n private async processParamsMaybeAddMcpUsage(\n params: types.GenerateContentParameters,\n ): Promise<types.GenerateContentParameters> {\n const tools = params.config?.tools;\n if (!tools) {\n return params;\n }\n const transformedTools = await Promise.all(\n tools.map(async (tool) => {\n if (afc.isCallableTool(tool)) {\n const callableTool = tool as types.CallableTool;\n return await callableTool.tool();\n }\n return tool;\n }),\n );\n const newParams: types.GenerateContentParameters = {\n model: params.model,\n contents: params.contents,\n config: {\n ...params.config,\n tools: transformedTools,\n },\n };\n newParams.config!.tools = transformedTools;\n\n if (\n params.config &&\n params.config.tools &&\n mcp.hasMcpToolUsage(params.config.tools)\n ) {\n const headers = params.config.httpOptions?.headers ?? {};\n let newHeaders = {...headers};\n if (Object.keys(newHeaders).length === 0) {\n newHeaders = this.apiClient.getDefaultHeaders();\n }\n mcp.setMcpUsageHeader(newHeaders);\n newParams.config!.httpOptions = {\n ...params.config.httpOptions,\n headers: newHeaders,\n };\n }\n return newParams;\n }\n\n private async initAfcToolsMap(\n params: types.GenerateContentParameters,\n ): Promise<Map<string, types.CallableTool>> {\n const afcTools: Map<string, types.CallableTool> = new Map();\n for (const tool of params.config?.tools ?? []) {\n if (afc.isCallableTool(tool)) {\n const callableTool = tool as types.CallableTool;\n const toolDeclaration = await callableTool.tool();\n for (const declaration of toolDeclaration.functionDeclarations ?? []) {\n if (!declaration.name) {\n throw new Error('Function declaration name is required.');\n }\n if (afcTools.has(declaration.name)) {\n throw new Error(\n `Duplicate tool declaration name: ${declaration.name}`,\n );\n }\n afcTools.set(declaration.name, callableTool);\n }\n }\n }\n return afcTools;\n }\n\n private async processAfcStream(\n params: types.GenerateContentParameters,\n ): Promise<AsyncGenerator<types.GenerateContentResponse>> {\n const maxRemoteCalls =\n params.config?.automaticFunctionCalling?.maximumRemoteCalls ??\n afc.DEFAULT_MAX_REMOTE_CALLS;\n let wereFunctionsCalled = false;\n let remoteCallCount = 0;\n const afcToolsMap = await this.initAfcToolsMap(params);\n return (async function* (\n models: Models,\n afcTools: Map<string, types.CallableTool>,\n params: types.GenerateContentParameters,\n ) {\n while (remoteCallCount < maxRemoteCalls) {\n if (wereFunctionsCalled) {\n remoteCallCount++;\n wereFunctionsCalled = false;\n }\n const transformedParams =\n await models.processParamsMaybeAddMcpUsage(params);\n const response =\n await models.generateContentStreamInternal(transformedParams);\n\n const functionResponses: types.Part[] = [];\n const responseContents: types.Content[] = [];\n\n for await (const chunk of response) {\n yield chunk;\n if (chunk.candidates && chunk.candidates[0]?.content) {\n responseContents.push(chunk.candidates[0].content);\n for (const part of chunk.candidates[0].content.parts ?? []) {\n if (remoteCallCount < maxRemoteCalls && part.functionCall) {\n if (!part.functionCall.name) {\n throw new Error(\n 'Function call name was not returned by the model.',\n );\n }\n if (!afcTools.has(part.functionCall.name)) {\n throw new Error(\n `Automatic function calling was requested, but not all the tools the model used implement the CallableTool interface. Available tools: ${afcTools.keys()}, mising tool: ${\n part.functionCall.name\n }`,\n );\n } else {\n const responseParts = await afcTools\n .get(part.functionCall.name)!\n .callTool([part.functionCall]);\n functionResponses.push(...responseParts);\n }\n }\n }\n }\n }\n\n if (functionResponses.length > 0) {\n wereFunctionsCalled = true;\n const typedResponseChunk = new types.GenerateContentResponse();\n typedResponseChunk.candidates = [\n {\n content: {\n role: 'user',\n parts: functionResponses,\n },\n },\n ];\n\n yield typedResponseChunk;\n\n const newContents: types.Content[] = [];\n newContents.push(...responseContents);\n newContents.push({\n role: 'user',\n parts: functionResponses,\n });\n const updatedContents = tContents(params.contents).concat(\n newContents,\n );\n\n params.contents = updatedContents;\n } else {\n break;\n }\n }\n })(this, afcToolsMap, params);\n }\n\n /**\n * Generates an image based on a text description and configuration.\n *\n * @param params - The parameters for generating images.\n * @return The response from the API.\n *\n * @example\n * ```ts\n * const response = await client.models.generateImages({\n * model: 'imagen-4.0-generate-001',\n * prompt: 'Robot holding a red skateboard',\n * config: {\n * numberOfImages: 1,\n * includeRaiReason: true,\n * },\n * });\n * console.log(response?.generatedImages?.[0]?.image?.imageBytes);\n * ```\n */\n generateImages = async (\n params: types.GenerateImagesParameters,\n ): Promise<types.GenerateImagesResponse> => {\n return await this.generateImagesInternal(params).then((apiResponse) => {\n let positivePromptSafetyAttributes;\n const generatedImages = [];\n\n if (apiResponse?.generatedImages) {\n for (const generatedImage of apiResponse.generatedImages) {\n if (\n generatedImage &&\n generatedImage?.safetyAttributes &&\n generatedImage?.safetyAttributes?.contentType === 'Positive Prompt'\n ) {\n positivePromptSafetyAttributes = generatedImage?.safetyAttributes;\n } else {\n generatedImages.push(generatedImage);\n }\n }\n }\n let response: types.GenerateImagesResponse;\n\n if (positivePromptSafetyAttributes) {\n response = {\n generatedImages: generatedImages,\n positivePromptSafetyAttributes: positivePromptSafetyAttributes,\n sdkHttpResponse: apiResponse.sdkHttpResponse,\n };\n } else {\n response = {\n generatedImages: generatedImages,\n sdkHttpResponse: apiResponse.sdkHttpResponse,\n };\n }\n return response;\n });\n };\n\n list = async (\n params?: types.ListModelsParameters,\n ): Promise<Pager<types.Model>> => {\n const defaultConfig: types.ListModelsConfig = {\n queryBase: true,\n };\n const actualConfig: types.ListModelsConfig = {\n ...defaultConfig,\n ...params?.config,\n };\n const actualParams: types.ListModelsParameters = {\n config: actualConfig,\n };\n\n if (this.apiClient.isVertexAI()) {\n if (!actualParams.config!.queryBase) {\n if (actualParams.config?.filter) {\n throw new Error(\n 'Filtering tuned models list for Vertex AI is not currently supported',\n );\n } else {\n actualParams.config!.filter = 'labels.tune-type:*';\n }\n }\n }\n\n return new Pager<types.Model>(\n PagedItem.PAGED_ITEM_MODELS,\n (x: types.ListModelsParameters) => this.listInternal(x),\n await this.listInternal(actualParams),\n actualParams,\n );\n };\n\n /**\n * Edits an image based on a prompt, list of reference images, and configuration.\n *\n * @param params - The parameters for editing an image.\n * @return The response from the API.\n *\n * @example\n * ```ts\n * const response = await client.models.editImage({\n * model: 'imagen-3.0-capability-001',\n * prompt: 'Generate an image containing a mug with the product logo [1] visible on the side of the mug.',\n * referenceImages: [subjectReferenceImage]\n * config: {\n * numberOfImages: 1,\n * includeRaiReason: true,\n * },\n * });\n * console.log(response?.generatedImages?.[0]?.image?.imageBytes);\n * ```\n */\n editImage = async (\n params: types.EditImageParameters,\n ): Promise<types.EditImageResponse> => {\n const paramsInternal: _internal_types.EditImageParametersInternal = {\n model: params.model,\n prompt: params.prompt,\n referenceImages: [],\n config: params.config,\n };\n if (params.referenceImages) {\n if (params.referenceImages) {\n paramsInternal.referenceImages = params.referenceImages.map((img) =>\n img.toReferenceImageAPI(),\n );\n }\n }\n return await this.editImageInternal(paramsInternal);\n };\n\n /**\n * Upscales an image based on an image, upscale factor, and configuration.\n * Only supported in Vertex AI currently.\n *\n * @param params - The parameters for upscaling an image.\n * @return The response from the API.\n *\n * @example\n * ```ts\n * const response = await client.models.upscaleImage({\n * model: 'imagen-4.0-upscale-preview',\n * image: image,\n * upscaleFactor: 'x2',\n * config: {\n * includeRaiReason: true,\n * },\n * });\n * console.log(response?.generatedImages?.[0]?.image?.imageBytes);\n * ```\n */\n upscaleImage = async (\n params: types.UpscaleImageParameters,\n ): Promise<types.UpscaleImageResponse> => {\n let apiConfig: _internal_types.UpscaleImageAPIConfigInternal = {\n numberOfImages: 1,\n mode: 'upscale',\n };\n\n if (params.config) {\n apiConfig = {...apiConfig, ...params.config};\n }\n\n const apiParams: _internal_types.UpscaleImageAPIParametersInternal = {\n model: params.model,\n image: params.image,\n upscaleFactor: params.upscaleFactor,\n config: apiConfig,\n };\n return await this.upscaleImageInternal(apiParams);\n };\n\n /**\n * Generates videos based on a text description and configuration.\n *\n * @param params - The parameters for generating videos.\n * @return A Promise<GenerateVideosOperation> which allows you to track the progress and eventually retrieve the generated videos using the operations.get method.\n *\n * @example\n * ```ts\n * const operation = await ai.models.generateVideos({\n * model: 'veo-2.0-generate-001',\n * source: {\n * prompt: 'A neon hologram of a cat driving at top speed',\n * },\n * config: {\n * numberOfVideos: 1\n * });\n *\n * while (!operation.done) {\n * await new Promise(resolve => setTimeout(resolve, 10000));\n * operation = await ai.operations.getVideosOperation({operation: operation});\n * }\n *\n * console.log(operation.response?.generatedVideos?.[0]?.video?.uri);\n * ```\n */\n\n generateVideos = async (\n params: types.GenerateVideosParameters,\n ): Promise<types.GenerateVideosOperation> => {\n if ((params.prompt || params.image || params.video) && params.source) {\n throw new Error(\n 'Source and prompt/image/video are mutually exclusive. Please only use source.',\n );\n }\n // Gemini API does not support video bytes.\n if (!this.apiClient.isVertexAI()) {\n if (params.video?.uri && params.video?.videoBytes) {\n params.video = {\n uri: params.video.uri,\n mimeType: params.video.mimeType,\n };\n } else if (\n params.source?.video?.uri &&\n params.source?.video?.videoBytes\n ) {\n params.source.video = {\n uri: params.source.video.uri,\n mimeType: params.source.video.mimeType,\n };\n }\n }\n return await this.generateVideosInternal(params);\n };\n\n private async generateContentInternal(\n params: types.GenerateContentParameters,\n ): Promise<types.GenerateContentResponse> {\n let response: Promise<types.GenerateContentResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.generateContentParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:generateContent',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.GenerateContentResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.GenerateContentResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.generateContentResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.GenerateContentResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n const body = converters.generateContentParametersToMldev(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:generateContent',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.GenerateContentResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.GenerateContentResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.generateContentResponseFromMldev(\n apiResponse,\n params,\n );\n const typedResp = new types.GenerateContentResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n private async generateContentStreamInternal(\n params: types.GenerateContentParameters,\n ): Promise<AsyncGenerator<types.GenerateContentResponse>> {\n let response: Promise<AsyncGenerator<types.HttpResponse>>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.generateContentParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:streamGenerateContent?alt=sse',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n const apiClient = this.apiClient;\n response = apiClient.requestStream({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n }) as Promise<AsyncGenerator<types.HttpResponse>>;\n\n return response.then(async function* (\n apiResponse: AsyncGenerator<types.HttpResponse>,\n ) {\n for await (const chunk of apiResponse) {\n const resp = converters.generateContentResponseFromVertex(\n (await chunk.json()) as types.GenerateContentResponse,\n params,\n );\n\n resp['sdkHttpResponse'] = {\n headers: chunk.headers,\n } as types.HttpResponse;\n\n const typedResp = new types.GenerateContentResponse();\n Object.assign(typedResp, resp);\n yield typedResp;\n }\n });\n } else {\n const body = converters.generateContentParametersToMldev(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:streamGenerateContent?alt=sse',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n const apiClient = this.apiClient;\n response = apiClient.requestStream({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n }) as Promise<AsyncGenerator<types.HttpResponse>>;\n\n return response.then(async function* (\n apiResponse: AsyncGenerator<types.HttpResponse>,\n ) {\n for await (const chunk of apiResponse) {\n const resp = converters.generateContentResponseFromMldev(\n (await chunk.json()) as types.GenerateContentResponse,\n params,\n );\n\n resp['sdkHttpResponse'] = {\n headers: chunk.headers,\n } as types.HttpResponse;\n\n const typedResp = new types.GenerateContentResponse();\n Object.assign(typedResp, resp);\n yield typedResp;\n }\n });\n }\n }\n\n /**\n * Calculates embeddings for the given contents. Only text is supported.\n *\n * @param params - The parameters for embedding contents.\n * @return The response from the API.\n *\n * @example\n * ```ts\n * const response = await ai.models.embedContent({\n * model: 'text-embedding-004',\n * contents: [\n * 'What is your name?',\n * 'What is your favorite color?',\n * ],\n * config: {\n * outputDimensionality: 64,\n * },\n * });\n * console.log(response);\n * ```\n */\n async embedContent(\n params: types.EmbedContentParameters,\n ): Promise<types.EmbedContentResponse> {\n let response: Promise<types.EmbedContentResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.embedContentParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:predict',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.EmbedContentResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.EmbedContentResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.embedContentResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.EmbedContentResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n const body = converters.embedContentParametersToMldev(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:batchEmbedContents',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.EmbedContentResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.EmbedContentResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.embedContentResponseFromMldev(\n apiResponse,\n params,\n );\n const typedResp = new types.EmbedContentResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n /**\n * Private method for generating images.\n */\n private async generateImagesInternal(\n params: types.GenerateImagesParameters,\n ): Promise<types.GenerateImagesResponse> {\n let response: Promise<types.GenerateImagesResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.generateImagesParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:predict',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.GenerateImagesResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.GenerateImagesResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.generateImagesResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.GenerateImagesResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n const body = converters.generateImagesParametersToMldev(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:predict',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.GenerateImagesResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.GenerateImagesResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.generateImagesResponseFromMldev(\n apiResponse,\n params,\n );\n const typedResp = new types.GenerateImagesResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n /**\n * Private method for editing an image.\n */\n private async editImageInternal(\n params: _internal_types.EditImageParametersInternal,\n ): Promise<types.EditImageResponse> {\n let response: Promise<types.EditImageResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.editImageParametersInternalToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:predict',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.EditImageResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.EditImageResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.editImageResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.EditImageResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n throw new Error('This method is only supported by the Vertex AI.');\n }\n }\n\n /**\n * Private method for upscaling an image.\n */\n private async upscaleImageInternal(\n params: _internal_types.UpscaleImageAPIParametersInternal,\n ): Promise<types.UpscaleImageResponse> {\n let response: Promise<types.UpscaleImageResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.upscaleImageAPIParametersInternalToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:predict',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.UpscaleImageResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.UpscaleImageResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.upscaleImageResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.UpscaleImageResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n throw new Error('This method is only supported by the Vertex AI.');\n }\n }\n\n /**\n * Recontextualizes an image.\n *\n * There are two types of recontextualization currently supported:\n * 1) Imagen Product Recontext - Generate images of products in new scenes\n * and contexts.\n * 2) Virtual Try-On: Generate images of persons modeling fashion products.\n *\n * @param params - The parameters for recontextualizing an image.\n * @return The response from the API.\n *\n * @example\n * ```ts\n * const response1 = await ai.models.recontextImage({\n * model: 'imagen-product-recontext-preview-06-30',\n * source: {\n * prompt: 'In a modern kitchen setting.',\n * productImages: [productImage],\n * },\n * config: {\n * numberOfImages: 1,\n * },\n * });\n * console.log(response1?.generatedImages?.[0]?.image?.imageBytes);\n *\n * const response2 = await ai.models.recontextImage({\n * model: 'virtual-try-on-001',\n * source: {\n * personImage: personImage,\n * productImages: [productImage],\n * },\n * config: {\n * numberOfImages: 1,\n * },\n * });\n * console.log(response2?.generatedImages?.[0]?.image?.imageBytes);\n * ```\n */\n async recontextImage(\n params: types.RecontextImageParameters,\n ): Promise<types.RecontextImageResponse> {\n let response: Promise<types.RecontextImageResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.recontextImageParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:predict',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.RecontextImageResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.recontextImageResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.RecontextImageResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n throw new Error('This method is only supported by the Vertex AI.');\n }\n }\n\n /**\n * Segments an image, creating a mask of a specified area.\n *\n * @param params - The parameters for segmenting an image.\n * @return The response from the API.\n *\n * @example\n * ```ts\n * const response = await ai.models.segmentImage({\n * model: 'image-segmentation-001',\n * source: {\n * image: image,\n * },\n * config: {\n * mode: 'foreground',\n * },\n * });\n * console.log(response?.generatedMasks?.[0]?.mask?.imageBytes);\n * ```\n */\n async segmentImage(\n params: types.SegmentImageParameters,\n ): Promise<types.SegmentImageResponse> {\n let response: Promise<types.SegmentImageResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.segmentImageParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:predict',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.SegmentImageResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.segmentImageResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.SegmentImageResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n throw new Error('This method is only supported by the Vertex AI.');\n }\n }\n\n /**\n * Fetches information about a model by name.\n *\n * @example\n * ```ts\n * const modelInfo = await ai.models.get({model: 'gemini-2.0-flash'});\n * ```\n */\n async get(params: types.GetModelParameters): Promise<types.Model> {\n let response: Promise<types.Model>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.getModelParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.Model>;\n\n return response.then((apiResponse) => {\n const resp = converters.modelFromVertex(apiResponse, params);\n\n return resp as types.Model;\n });\n } else {\n const body = converters.getModelParametersToMldev(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.Model>;\n\n return response.then((apiResponse) => {\n const resp = converters.modelFromMldev(apiResponse, params);\n\n return resp as types.Model;\n });\n }\n }\n\n private async listInternal(\n params: types.ListModelsParameters,\n ): Promise<types.ListModelsResponse> {\n let response: Promise<types.ListModelsResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.listModelsParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{models_url}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.ListModelsResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.ListModelsResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.listModelsResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.ListModelsResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n const body = converters.listModelsParametersToMldev(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{models_url}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.ListModelsResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.ListModelsResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.listModelsResponseFromMldev(\n apiResponse,\n params,\n );\n const typedResp = new types.ListModelsResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n /**\n * Updates a tuned model by its name.\n *\n * @param params - The parameters for updating the model.\n * @return The response from the API.\n *\n * @example\n * ```ts\n * const response = await ai.models.update({\n * model: 'tuned-model-name',\n * config: {\n * displayName: 'New display name',\n * description: 'New description',\n * },\n * });\n * ```\n */\n async update(params: types.UpdateModelParameters): Promise<types.Model> {\n let response: Promise<types.Model>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.updateModelParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'PATCH',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.Model>;\n\n return response.then((apiResponse) => {\n const resp = converters.modelFromVertex(apiResponse, params);\n\n return resp as types.Model;\n });\n } else {\n const body = converters.updateModelParametersToMldev(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'PATCH',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.Model>;\n\n return response.then((apiResponse) => {\n const resp = converters.modelFromMldev(apiResponse, params);\n\n return resp as types.Model;\n });\n }\n }\n\n /**\n * Deletes a tuned model by its name.\n *\n * @param params - The parameters for deleting the model.\n * @return The response from the API.\n *\n * @example\n * ```ts\n * const response = await ai.models.delete({model: 'tuned-model-name'});\n * ```\n */\n async delete(\n params: types.DeleteModelParameters,\n ): Promise<types.DeleteModelResponse> {\n let response: Promise<types.DeleteModelResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.deleteModelParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'DELETE',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.DeleteModelResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.DeleteModelResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.deleteModelResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.DeleteModelResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n const body = converters.deleteModelParametersToMldev(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'DELETE',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.DeleteModelResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.DeleteModelResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.deleteModelResponseFromMldev(\n apiResponse,\n params,\n );\n const typedResp = new types.DeleteModelResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n /**\n * Counts the number of tokens in the given contents. Multimodal input is\n * supported for Gemini models.\n *\n * @param params - The parameters for counting tokens.\n * @return The response from the API.\n *\n * @example\n * ```ts\n * const response = await ai.models.countTokens({\n * model: 'gemini-2.0-flash',\n * contents: 'The quick brown fox jumps over the lazy dog.'\n * });\n * console.log(response);\n * ```\n */\n async countTokens(\n params: types.CountTokensParameters,\n ): Promise<types.CountTokensResponse> {\n let response: Promise<types.CountTokensResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.countTokensParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:countTokens',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.CountTokensResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.CountTokensResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.countTokensResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.CountTokensResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n const body = converters.countTokensParametersToMldev(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:countTokens',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.CountTokensResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.CountTokensResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.countTokensResponseFromMldev(\n apiResponse,\n params,\n );\n const typedResp = new types.CountTokensResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n /**\n * Given a list of contents, returns a corresponding TokensInfo containing\n * the list of tokens and list of token ids.\n *\n * This method is not supported by the Gemini Developer API.\n *\n * @param params - The parameters for computing tokens.\n * @return The response from the API.\n *\n * @example\n * ```ts\n * const response = await ai.models.computeTokens({\n * model: 'gemini-2.0-flash',\n * contents: 'What is your name?'\n * });\n * console.log(response);\n * ```\n */\n async computeTokens(\n params: types.ComputeTokensParameters,\n ): Promise<types.ComputeTokensResponse> {\n let response: Promise<types.ComputeTokensResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.computeTokensParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:computeTokens',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.ComputeTokensResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.ComputeTokensResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.computeTokensResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.ComputeTokensResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n throw new Error('This method is only supported by the Vertex AI.');\n }\n }\n\n /**\n * Private method for generating videos.\n */\n private async generateVideosInternal(\n params: types.GenerateVideosParameters,\n ): Promise<types.GenerateVideosOperation> {\n let response: Promise<types.GenerateVideosOperation>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.generateVideosParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:predictLongRunning',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.GenerateVideosOperation>;\n\n return response.then((apiResponse) => {\n const resp = converters.generateVideosOperationFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.GenerateVideosOperation();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n const body = converters.generateVideosParametersToMldev(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:predictLongRunning',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.GenerateVideosOperation>;\n\n return response.then((apiResponse) => {\n const resp = converters.generateVideosOperationFromMldev(\n apiResponse,\n params,\n );\n const typedResp = new types.GenerateVideosOperation();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport {ApiClient} from './_api_client.js';\nimport * as common from './_common.js';\nimport {BaseModule} from './_common.js';\nimport * as converters from './converters/_operations_converters.js';\nimport * as types from './types.js';\n\nexport class Operations extends BaseModule {\n constructor(private readonly apiClient: ApiClient) {\n super();\n }\n\n /**\n * Gets the status of a long-running operation.\n *\n * @param parameters The parameters for the get operation request.\n * @return The updated Operation object, with the latest status or result.\n */\n async getVideosOperation(\n parameters: types.OperationGetParameters<\n types.GenerateVideosResponse,\n types.GenerateVideosOperation\n >,\n ): Promise<types.GenerateVideosOperation> {\n const operation = parameters.operation;\n const config = parameters.config;\n\n if (operation.name === undefined || operation.name === '') {\n throw new Error('Operation name is required.');\n }\n\n if (this.apiClient.isVertexAI()) {\n const resourceName = operation.name.split('/operations/')[0];\n let httpOptions: types.HttpOptions | undefined = undefined;\n\n if (config && 'httpOptions' in config) {\n httpOptions = config.httpOptions;\n }\n\n const rawOperation = await this.fetchPredictVideosOperationInternal({\n operationName: operation.name,\n resourceName: resourceName,\n config: {httpOptions: httpOptions},\n });\n\n return operation._fromAPIResponse({\n apiResponse: rawOperation,\n _isVertexAI: true,\n });\n } else {\n const rawOperation = await this.getVideosOperationInternal({\n operationName: operation.name,\n config: config,\n });\n return operation._fromAPIResponse({\n apiResponse: rawOperation,\n _isVertexAI: false,\n });\n }\n }\n\n /**\n * Gets the status of a long-running operation.\n *\n * @param parameters The parameters for the get operation request.\n * @return The updated Operation object, with the latest status or result.\n */\n async get<T, U extends types.Operation<T>>(\n parameters: types.OperationGetParameters<T, U>,\n ): Promise<types.Operation<T>> {\n const operation = parameters.operation;\n const config = parameters.config;\n\n if (operation.name === undefined || operation.name === '') {\n throw new Error('Operation name is required.');\n }\n\n if (this.apiClient.isVertexAI()) {\n const resourceName = operation.name.split('/operations/')[0];\n let httpOptions: types.HttpOptions | undefined = undefined;\n\n if (config && 'httpOptions' in config) {\n httpOptions = config.httpOptions;\n }\n\n const rawOperation = await this.fetchPredictVideosOperationInternal({\n operationName: operation.name,\n resourceName: resourceName,\n config: {httpOptions: httpOptions},\n });\n\n return operation._fromAPIResponse({\n apiResponse: rawOperation,\n _isVertexAI: true,\n });\n } else {\n const rawOperation = await this.getVideosOperationInternal({\n operationName: operation.name,\n config: config,\n });\n return operation._fromAPIResponse({\n apiResponse: rawOperation,\n _isVertexAI: false,\n });\n }\n }\n\n private async getVideosOperationInternal(\n params: types.GetOperationParameters,\n ): Promise<Record<string, unknown>> {\n let response: Promise<Record<string, unknown>>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.getOperationParametersToVertex(params);\n path = common.formatMap(\n '{operationName}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<Record<string, unknown>>;\n\n return response;\n } else {\n const body = converters.getOperationParametersToMldev(params);\n path = common.formatMap(\n '{operationName}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<Record<string, unknown>>;\n\n return response;\n }\n }\n\n private async fetchPredictVideosOperationInternal(\n params: types.FetchPredictOperationParameters,\n ): Promise<Record<string, unknown>> {\n let response: Promise<Record<string, unknown>>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.fetchPredictOperationParametersToVertex(params);\n path = common.formatMap(\n '{resourceName}:fetchPredictOperation',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<Record<string, unknown>>;\n\n return response;\n } else {\n throw new Error('This method is only supported by the Vertex AI.');\n }\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport {ApiClient} from '../_api_client.js';\nimport * as common from '../_common.js';\nimport * as t from '../_transformers.js';\nimport type * as types from '../types.js';\n\nexport function blobToMldev(fromObject: types.Blob): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromData = common.getValueByPath(fromObject, ['data']);\n if (fromData != null) {\n common.setValueByPath(toObject, ['data'], fromData);\n }\n\n if (common.getValueByPath(fromObject, ['displayName']) !== undefined) {\n throw new Error('displayName parameter is not supported in Gemini API.');\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function contentToMldev(\n fromObject: types.Content,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromParts = common.getValueByPath(fromObject, ['parts']);\n if (fromParts != null) {\n let transformedList = fromParts;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return partToMldev(item);\n });\n }\n common.setValueByPath(toObject, ['parts'], transformedList);\n }\n\n const fromRole = common.getValueByPath(fromObject, ['role']);\n if (fromRole != null) {\n common.setValueByPath(toObject, ['role'], fromRole);\n }\n\n return toObject;\n}\n\nexport function createAuthTokenConfigToMldev(\n apiClient: ApiClient,\n fromObject: types.CreateAuthTokenConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromExpireTime = common.getValueByPath(fromObject, ['expireTime']);\n if (parentObject !== undefined && fromExpireTime != null) {\n common.setValueByPath(parentObject, ['expireTime'], fromExpireTime);\n }\n\n const fromNewSessionExpireTime = common.getValueByPath(fromObject, [\n 'newSessionExpireTime',\n ]);\n if (parentObject !== undefined && fromNewSessionExpireTime != null) {\n common.setValueByPath(\n parentObject,\n ['newSessionExpireTime'],\n fromNewSessionExpireTime,\n );\n }\n\n const fromUses = common.getValueByPath(fromObject, ['uses']);\n if (parentObject !== undefined && fromUses != null) {\n common.setValueByPath(parentObject, ['uses'], fromUses);\n }\n\n const fromLiveConnectConstraints = common.getValueByPath(fromObject, [\n 'liveConnectConstraints',\n ]);\n if (parentObject !== undefined && fromLiveConnectConstraints != null) {\n common.setValueByPath(\n parentObject,\n ['bidiGenerateContentSetup'],\n liveConnectConstraintsToMldev(apiClient, fromLiveConnectConstraints),\n );\n }\n\n const fromLockAdditionalFields = common.getValueByPath(fromObject, [\n 'lockAdditionalFields',\n ]);\n if (parentObject !== undefined && fromLockAdditionalFields != null) {\n common.setValueByPath(\n parentObject,\n ['fieldMask'],\n fromLockAdditionalFields,\n );\n }\n\n return toObject;\n}\n\nexport function createAuthTokenParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.CreateAuthTokenParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n common.setValueByPath(\n toObject,\n ['config'],\n createAuthTokenConfigToMldev(apiClient, fromConfig, toObject),\n );\n }\n\n return toObject;\n}\n\nexport function createAuthTokenParametersToVertex(\n fromObject: types.CreateAuthTokenParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['config']) !== undefined) {\n throw new Error('config parameter is not supported in Vertex AI.');\n }\n\n return toObject;\n}\n\nexport function fileDataToMldev(\n fromObject: types.FileData,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['displayName']) !== undefined) {\n throw new Error('displayName parameter is not supported in Gemini API.');\n }\n\n const fromFileUri = common.getValueByPath(fromObject, ['fileUri']);\n if (fromFileUri != null) {\n common.setValueByPath(toObject, ['fileUri'], fromFileUri);\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function functionCallToMldev(\n fromObject: types.FunctionCall,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromId = common.getValueByPath(fromObject, ['id']);\n if (fromId != null) {\n common.setValueByPath(toObject, ['id'], fromId);\n }\n\n const fromArgs = common.getValueByPath(fromObject, ['args']);\n if (fromArgs != null) {\n common.setValueByPath(toObject, ['args'], fromArgs);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n if (common.getValueByPath(fromObject, ['partialArgs']) !== undefined) {\n throw new Error('partialArgs parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['willContinue']) !== undefined) {\n throw new Error('willContinue parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function googleMapsToMldev(\n fromObject: types.GoogleMaps,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['authConfig']) !== undefined) {\n throw new Error('authConfig parameter is not supported in Gemini API.');\n }\n\n const fromEnableWidget = common.getValueByPath(fromObject, ['enableWidget']);\n if (fromEnableWidget != null) {\n common.setValueByPath(toObject, ['enableWidget'], fromEnableWidget);\n }\n\n return toObject;\n}\n\nexport function googleSearchToMldev(\n fromObject: types.GoogleSearch,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['excludeDomains']) !== undefined) {\n throw new Error('excludeDomains parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['blockingConfidence']) !== undefined) {\n throw new Error(\n 'blockingConfidence parameter is not supported in Gemini API.',\n );\n }\n\n const fromTimeRangeFilter = common.getValueByPath(fromObject, [\n 'timeRangeFilter',\n ]);\n if (fromTimeRangeFilter != null) {\n common.setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter);\n }\n\n return toObject;\n}\n\nexport function liveConnectConfigToMldev(\n fromObject: types.LiveConnectConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromGenerationConfig = common.getValueByPath(fromObject, [\n 'generationConfig',\n ]);\n if (parentObject !== undefined && fromGenerationConfig != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig'],\n fromGenerationConfig,\n );\n }\n\n const fromResponseModalities = common.getValueByPath(fromObject, [\n 'responseModalities',\n ]);\n if (parentObject !== undefined && fromResponseModalities != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'responseModalities'],\n fromResponseModalities,\n );\n }\n\n const fromTemperature = common.getValueByPath(fromObject, ['temperature']);\n if (parentObject !== undefined && fromTemperature != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'temperature'],\n fromTemperature,\n );\n }\n\n const fromTopP = common.getValueByPath(fromObject, ['topP']);\n if (parentObject !== undefined && fromTopP != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'topP'],\n fromTopP,\n );\n }\n\n const fromTopK = common.getValueByPath(fromObject, ['topK']);\n if (parentObject !== undefined && fromTopK != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'topK'],\n fromTopK,\n );\n }\n\n const fromMaxOutputTokens = common.getValueByPath(fromObject, [\n 'maxOutputTokens',\n ]);\n if (parentObject !== undefined && fromMaxOutputTokens != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'maxOutputTokens'],\n fromMaxOutputTokens,\n );\n }\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (parentObject !== undefined && fromMediaResolution != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'mediaResolution'],\n fromMediaResolution,\n );\n }\n\n const fromSeed = common.getValueByPath(fromObject, ['seed']);\n if (parentObject !== undefined && fromSeed != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'seed'],\n fromSeed,\n );\n }\n\n const fromSpeechConfig = common.getValueByPath(fromObject, ['speechConfig']);\n if (parentObject !== undefined && fromSpeechConfig != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'speechConfig'],\n t.tLiveSpeechConfig(fromSpeechConfig),\n );\n }\n\n const fromThinkingConfig = common.getValueByPath(fromObject, [\n 'thinkingConfig',\n ]);\n if (parentObject !== undefined && fromThinkingConfig != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'thinkingConfig'],\n fromThinkingConfig,\n );\n }\n\n const fromEnableAffectiveDialog = common.getValueByPath(fromObject, [\n 'enableAffectiveDialog',\n ]);\n if (parentObject !== undefined && fromEnableAffectiveDialog != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'enableAffectiveDialog'],\n fromEnableAffectiveDialog,\n );\n }\n\n const fromSystemInstruction = common.getValueByPath(fromObject, [\n 'systemInstruction',\n ]);\n if (parentObject !== undefined && fromSystemInstruction != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'systemInstruction'],\n contentToMldev(t.tContent(fromSystemInstruction)),\n );\n }\n\n const fromTools = common.getValueByPath(fromObject, ['tools']);\n if (parentObject !== undefined && fromTools != null) {\n let transformedList = t.tTools(fromTools);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return toolToMldev(t.tTool(item));\n });\n }\n common.setValueByPath(parentObject, ['setup', 'tools'], transformedList);\n }\n\n const fromSessionResumption = common.getValueByPath(fromObject, [\n 'sessionResumption',\n ]);\n if (parentObject !== undefined && fromSessionResumption != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'sessionResumption'],\n sessionResumptionConfigToMldev(fromSessionResumption),\n );\n }\n\n const fromInputAudioTranscription = common.getValueByPath(fromObject, [\n 'inputAudioTranscription',\n ]);\n if (parentObject !== undefined && fromInputAudioTranscription != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'inputAudioTranscription'],\n fromInputAudioTranscription,\n );\n }\n\n const fromOutputAudioTranscription = common.getValueByPath(fromObject, [\n 'outputAudioTranscription',\n ]);\n if (parentObject !== undefined && fromOutputAudioTranscription != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'outputAudioTranscription'],\n fromOutputAudioTranscription,\n );\n }\n\n const fromRealtimeInputConfig = common.getValueByPath(fromObject, [\n 'realtimeInputConfig',\n ]);\n if (parentObject !== undefined && fromRealtimeInputConfig != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'realtimeInputConfig'],\n fromRealtimeInputConfig,\n );\n }\n\n const fromContextWindowCompression = common.getValueByPath(fromObject, [\n 'contextWindowCompression',\n ]);\n if (parentObject !== undefined && fromContextWindowCompression != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'contextWindowCompression'],\n fromContextWindowCompression,\n );\n }\n\n const fromProactivity = common.getValueByPath(fromObject, ['proactivity']);\n if (parentObject !== undefined && fromProactivity != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'proactivity'],\n fromProactivity,\n );\n }\n\n if (common.getValueByPath(fromObject, ['explicitVadSignal']) !== undefined) {\n throw new Error(\n 'explicitVadSignal parameter is not supported in Gemini API.',\n );\n }\n\n return toObject;\n}\n\nexport function liveConnectConstraintsToMldev(\n apiClient: ApiClient,\n fromObject: types.LiveConnectConstraints,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['setup', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n common.setValueByPath(\n toObject,\n ['config'],\n liveConnectConfigToMldev(fromConfig, toObject),\n );\n }\n\n return toObject;\n}\n\nexport function partToMldev(fromObject: types.Part): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (fromMediaResolution != null) {\n common.setValueByPath(toObject, ['mediaResolution'], fromMediaResolution);\n }\n\n const fromCodeExecutionResult = common.getValueByPath(fromObject, [\n 'codeExecutionResult',\n ]);\n if (fromCodeExecutionResult != null) {\n common.setValueByPath(\n toObject,\n ['codeExecutionResult'],\n fromCodeExecutionResult,\n );\n }\n\n const fromExecutableCode = common.getValueByPath(fromObject, [\n 'executableCode',\n ]);\n if (fromExecutableCode != null) {\n common.setValueByPath(toObject, ['executableCode'], fromExecutableCode);\n }\n\n const fromFileData = common.getValueByPath(fromObject, ['fileData']);\n if (fromFileData != null) {\n common.setValueByPath(\n toObject,\n ['fileData'],\n fileDataToMldev(fromFileData),\n );\n }\n\n const fromFunctionCall = common.getValueByPath(fromObject, ['functionCall']);\n if (fromFunctionCall != null) {\n common.setValueByPath(\n toObject,\n ['functionCall'],\n functionCallToMldev(fromFunctionCall),\n );\n }\n\n const fromFunctionResponse = common.getValueByPath(fromObject, [\n 'functionResponse',\n ]);\n if (fromFunctionResponse != null) {\n common.setValueByPath(toObject, ['functionResponse'], fromFunctionResponse);\n }\n\n const fromInlineData = common.getValueByPath(fromObject, ['inlineData']);\n if (fromInlineData != null) {\n common.setValueByPath(\n toObject,\n ['inlineData'],\n blobToMldev(fromInlineData),\n );\n }\n\n const fromText = common.getValueByPath(fromObject, ['text']);\n if (fromText != null) {\n common.setValueByPath(toObject, ['text'], fromText);\n }\n\n const fromThought = common.getValueByPath(fromObject, ['thought']);\n if (fromThought != null) {\n common.setValueByPath(toObject, ['thought'], fromThought);\n }\n\n const fromThoughtSignature = common.getValueByPath(fromObject, [\n 'thoughtSignature',\n ]);\n if (fromThoughtSignature != null) {\n common.setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature);\n }\n\n const fromVideoMetadata = common.getValueByPath(fromObject, [\n 'videoMetadata',\n ]);\n if (fromVideoMetadata != null) {\n common.setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata);\n }\n\n return toObject;\n}\n\nexport function sessionResumptionConfigToMldev(\n fromObject: types.SessionResumptionConfig,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromHandle = common.getValueByPath(fromObject, ['handle']);\n if (fromHandle != null) {\n common.setValueByPath(toObject, ['handle'], fromHandle);\n }\n\n if (common.getValueByPath(fromObject, ['transparent']) !== undefined) {\n throw new Error('transparent parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function toolToMldev(fromObject: types.Tool): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['retrieval']) !== undefined) {\n throw new Error('retrieval parameter is not supported in Gemini API.');\n }\n\n const fromComputerUse = common.getValueByPath(fromObject, ['computerUse']);\n if (fromComputerUse != null) {\n common.setValueByPath(toObject, ['computerUse'], fromComputerUse);\n }\n\n const fromFileSearch = common.getValueByPath(fromObject, ['fileSearch']);\n if (fromFileSearch != null) {\n common.setValueByPath(toObject, ['fileSearch'], fromFileSearch);\n }\n\n const fromCodeExecution = common.getValueByPath(fromObject, [\n 'codeExecution',\n ]);\n if (fromCodeExecution != null) {\n common.setValueByPath(toObject, ['codeExecution'], fromCodeExecution);\n }\n\n if (\n common.getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined\n ) {\n throw new Error(\n 'enterpriseWebSearch parameter is not supported in Gemini API.',\n );\n }\n\n const fromFunctionDeclarations = common.getValueByPath(fromObject, [\n 'functionDeclarations',\n ]);\n if (fromFunctionDeclarations != null) {\n let transformedList = fromFunctionDeclarations;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['functionDeclarations'], transformedList);\n }\n\n const fromGoogleMaps = common.getValueByPath(fromObject, ['googleMaps']);\n if (fromGoogleMaps != null) {\n common.setValueByPath(\n toObject,\n ['googleMaps'],\n googleMapsToMldev(fromGoogleMaps),\n );\n }\n\n const fromGoogleSearch = common.getValueByPath(fromObject, ['googleSearch']);\n if (fromGoogleSearch != null) {\n common.setValueByPath(\n toObject,\n ['googleSearch'],\n googleSearchToMldev(fromGoogleSearch),\n );\n }\n\n const fromGoogleSearchRetrieval = common.getValueByPath(fromObject, [\n 'googleSearchRetrieval',\n ]);\n if (fromGoogleSearchRetrieval != null) {\n common.setValueByPath(\n toObject,\n ['googleSearchRetrieval'],\n fromGoogleSearchRetrieval,\n );\n }\n\n const fromUrlContext = common.getValueByPath(fromObject, ['urlContext']);\n if (fromUrlContext != null) {\n common.setValueByPath(toObject, ['urlContext'], fromUrlContext);\n }\n\n return toObject;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {ApiClient} from './_api_client.js';\nimport * as common from './_common.js';\nimport {BaseModule} from './_common.js';\nimport * as converters from './converters/_tokens_converters.js';\nimport * as types from './types.js';\n\n/**\n * Returns a comma-separated list of field masks from a given object.\n *\n * @param setup The object to extract field masks from.\n * @return A comma-separated list of field masks.\n */\nfunction getFieldMasks(setup: Record<string, unknown>): string {\n const fields: string[] = [];\n\n for (const key in setup) {\n if (Object.prototype.hasOwnProperty.call(setup, key)) {\n const value = setup[key];\n // 2nd layer, recursively get field masks see TODO(b/418290100)\n if (\n typeof value === 'object' &&\n value != null &&\n Object.keys(value).length > 0\n ) {\n const field = Object.keys(value).map((kk) => `${key}.${kk}`);\n fields.push(...field);\n } else {\n fields.push(key); // 1st layer\n }\n }\n }\n\n return fields.join(',');\n}\n\n/**\n * Converts bidiGenerateContentSetup.\n * @param requestDict - The request dictionary.\n * @param config - The configuration object.\n * @return - The modified request dictionary.\n */\nfunction convertBidiSetupToTokenSetup(\n requestDict: Record<string, unknown>,\n config?: {lockAdditionalFields?: string[]},\n): Record<string, unknown> {\n // Convert bidiGenerateContentSetup from bidiGenerateContentSetup.setup.\n let setupForMaskGeneration: Record<string, unknown> | null = null;\n const bidiGenerateContentSetupValue = requestDict['bidiGenerateContentSetup'];\n if (\n typeof bidiGenerateContentSetupValue === 'object' &&\n bidiGenerateContentSetupValue !== null &&\n 'setup' in bidiGenerateContentSetupValue\n ) {\n // Now we know bidiGenerateContentSetupValue is an object and has a 'setup'\n // property.\n const innerSetup = (bidiGenerateContentSetupValue as {setup: unknown})\n .setup;\n\n if (typeof innerSetup === 'object' && innerSetup !== null) {\n // Valid inner setup found.\n requestDict['bidiGenerateContentSetup'] = innerSetup;\n setupForMaskGeneration = innerSetup as Record<string, unknown>;\n } else {\n // `bidiGenerateContentSetupValue.setup` is not a valid object; treat as\n // if bidiGenerateContentSetup is invalid.\n delete requestDict['bidiGenerateContentSetup'];\n }\n } else if (bidiGenerateContentSetupValue !== undefined) {\n // `bidiGenerateContentSetup` exists but not in the expected\n // shape {setup: {...}}; treat as invalid.\n delete requestDict['bidiGenerateContentSetup'];\n }\n\n const preExistingFieldMask = requestDict['fieldMask'];\n // Handle mask generation setup.\n if (setupForMaskGeneration) {\n const generatedMaskFromBidi = getFieldMasks(setupForMaskGeneration);\n\n if (\n Array.isArray(config?.lockAdditionalFields) &&\n config?.lockAdditionalFields.length === 0\n ) {\n // Case 1: lockAdditionalFields is an empty array. Lock only fields from\n // bidi setup.\n if (generatedMaskFromBidi) {\n // Only assign if mask is not empty\n requestDict['fieldMask'] = generatedMaskFromBidi;\n } else {\n delete requestDict['fieldMask']; // If mask is empty, effectively no\n // specific fields locked by bidi\n }\n } else if (\n config?.lockAdditionalFields &&\n config.lockAdditionalFields.length > 0 &&\n preExistingFieldMask !== null &&\n Array.isArray(preExistingFieldMask) &&\n preExistingFieldMask.length > 0\n ) {\n // Case 2: Lock fields from bidi setup + additional fields\n // (preExistingFieldMask).\n\n const generationConfigFields = [\n 'temperature',\n 'topK',\n 'topP',\n 'maxOutputTokens',\n 'responseModalities',\n 'seed',\n 'speechConfig',\n ];\n\n let mappedFieldsFromPreExisting: string[] = [];\n if (preExistingFieldMask.length > 0) {\n mappedFieldsFromPreExisting = preExistingFieldMask.map((field) => {\n if (generationConfigFields.includes(field)) {\n return `generationConfig.${field}`;\n }\n return field; // Keep original field name if not in\n // generationConfigFields\n });\n }\n\n const finalMaskParts: string[] = [];\n if (generatedMaskFromBidi) {\n finalMaskParts.push(generatedMaskFromBidi);\n }\n if (mappedFieldsFromPreExisting.length > 0) {\n finalMaskParts.push(...mappedFieldsFromPreExisting);\n }\n\n if (finalMaskParts.length > 0) {\n requestDict['fieldMask'] = finalMaskParts.join(',');\n } else {\n // If no fields from bidi and no valid additional fields from\n // pre-existing mask.\n delete requestDict['fieldMask'];\n }\n } else {\n // Case 3: \"Lock all fields\" (meaning, don't send a field_mask, let server\n // defaults apply or all are mutable). This is hit if:\n // - `config.lockAdditionalFields` is undefined.\n // - `config.lockAdditionalFields` is non-empty, BUT\n // `preExistingFieldMask` is null, not a string, or an empty string.\n delete requestDict['fieldMask'];\n }\n } else {\n // No valid `bidiGenerateContentSetup` was found or extracted.\n // \"Lock additional null fields if any\".\n if (\n preExistingFieldMask !== null &&\n Array.isArray(preExistingFieldMask) &&\n preExistingFieldMask.length > 0\n ) {\n // If there's a pre-existing field mask, it's a string, and it's not\n // empty, then we should lock all fields.\n requestDict['fieldMask'] = preExistingFieldMask.join(',');\n } else {\n delete requestDict['fieldMask'];\n }\n }\n\n return requestDict;\n}\n\nexport class Tokens extends BaseModule {\n constructor(private readonly apiClient: ApiClient) {\n super();\n }\n /**\n * Creates an ephemeral auth token resource.\n *\n * @experimental\n *\n * @remarks\n * Ephemeral auth tokens is only supported in the Gemini Developer API.\n * It can be used for the session connection to the Live constrained API.\n * Support in v1alpha only.\n *\n * @param params - The parameters for the create request.\n * @return The created auth token.\n *\n * @example\n * ```ts\n * const ai = new GoogleGenAI({\n * apiKey: token.name,\n * httpOptions: { apiVersion: 'v1alpha' } // Support in v1alpha only.\n * });\n *\n * // Case 1: If LiveEphemeralParameters is unset, unlock LiveConnectConfig\n * // when using the token in Live API sessions. Each session connection can\n * // use a different configuration.\n * const config: CreateAuthTokenConfig = {\n * uses: 3,\n * expireTime: '2025-05-01T00:00:00Z',\n * }\n * const token = await ai.tokens.create(config);\n *\n * // Case 2: If LiveEphemeralParameters is set, lock all fields in\n * // LiveConnectConfig when using the token in Live API sessions. For\n * // example, changing `outputAudioTranscription` in the Live API\n * // connection will be ignored by the API.\n * const config: CreateAuthTokenConfig =\n * uses: 3,\n * expireTime: '2025-05-01T00:00:00Z',\n * LiveEphemeralParameters: {\n * model: 'gemini-2.0-flash-001',\n * config: {\n * 'responseModalities': ['AUDIO'],\n * 'systemInstruction': 'Always answer in English.',\n * }\n * }\n * }\n * const token = await ai.tokens.create(config);\n *\n * // Case 3: If LiveEphemeralParameters is set and lockAdditionalFields is\n * // set, lock LiveConnectConfig with set and additional fields (e.g.\n * // responseModalities, systemInstruction, temperature in this example) when\n * // using the token in Live API sessions.\n * const config: CreateAuthTokenConfig =\n * uses: 3,\n * expireTime: '2025-05-01T00:00:00Z',\n * LiveEphemeralParameters: {\n * model: 'gemini-2.0-flash-001',\n * config: {\n * 'responseModalities': ['AUDIO'],\n * 'systemInstruction': 'Always answer in English.',\n * }\n * },\n * lockAdditionalFields: ['temperature'],\n * }\n * const token = await ai.tokens.create(config);\n *\n * // Case 4: If LiveEphemeralParameters is set and lockAdditionalFields is\n * // empty array, lock LiveConnectConfig with set fields (e.g.\n * // responseModalities, systemInstruction in this example) when using the\n * // token in Live API sessions.\n * const config: CreateAuthTokenConfig =\n * uses: 3,\n * expireTime: '2025-05-01T00:00:00Z',\n * LiveEphemeralParameters: {\n * model: 'gemini-2.0-flash-001',\n * config: {\n * 'responseModalities': ['AUDIO'],\n * 'systemInstruction': 'Always answer in English.',\n * }\n * },\n * lockAdditionalFields: [],\n * }\n * const token = await ai.tokens.create(config);\n * ```\n */\n\n async create(\n params: types.CreateAuthTokenParameters,\n ): Promise<types.AuthToken> {\n let response: Promise<types.AuthToken>;\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'The client.tokens.create method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.createAuthTokenParametersToMldev(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n 'auth_tokens',\n body['_url'] as Record<string, unknown>,\n );\n\n queryParams = body['_query'] as Record<string, string>;\n delete body['config'];\n delete body['_url'];\n delete body['_query'];\n\n const transformedBody = convertBidiSetupToTokenSetup(body, params.config);\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(transformedBody),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.AuthToken>;\n\n return response.then((resp) => {\n return resp as types.AuthToken;\n });\n }\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport * as common from '../_common.js';\nimport * as t from '../_transformers.js';\nimport type * as types from '../types.js';\n\nexport function cancelTuningJobParametersToMldev(\n fromObject: types.CancelTuningJobParameters,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['_url', 'name'], fromName);\n }\n\n return toObject;\n}\n\nexport function cancelTuningJobParametersToVertex(\n fromObject: types.CancelTuningJobParameters,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['_url', 'name'], fromName);\n }\n\n return toObject;\n}\n\nexport function cancelTuningJobResponseFromMldev(\n fromObject: types.CancelTuningJobResponse,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n return toObject;\n}\n\nexport function cancelTuningJobResponseFromVertex(\n fromObject: types.CancelTuningJobResponse,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n return toObject;\n}\n\nexport function createTuningJobConfigToMldev(\n fromObject: types.CreateTuningJobConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['validationDataset']) !== undefined) {\n throw new Error(\n 'validationDataset parameter is not supported in Gemini API.',\n );\n }\n\n const fromTunedModelDisplayName = common.getValueByPath(fromObject, [\n 'tunedModelDisplayName',\n ]);\n if (parentObject !== undefined && fromTunedModelDisplayName != null) {\n common.setValueByPath(\n parentObject,\n ['displayName'],\n fromTunedModelDisplayName,\n );\n }\n\n if (common.getValueByPath(fromObject, ['description']) !== undefined) {\n throw new Error('description parameter is not supported in Gemini API.');\n }\n\n const fromEpochCount = common.getValueByPath(fromObject, ['epochCount']);\n if (parentObject !== undefined && fromEpochCount != null) {\n common.setValueByPath(\n parentObject,\n ['tuningTask', 'hyperparameters', 'epochCount'],\n fromEpochCount,\n );\n }\n\n const fromLearningRateMultiplier = common.getValueByPath(fromObject, [\n 'learningRateMultiplier',\n ]);\n if (fromLearningRateMultiplier != null) {\n common.setValueByPath(\n toObject,\n ['tuningTask', 'hyperparameters', 'learningRateMultiplier'],\n fromLearningRateMultiplier,\n );\n }\n\n if (\n common.getValueByPath(fromObject, ['exportLastCheckpointOnly']) !==\n undefined\n ) {\n throw new Error(\n 'exportLastCheckpointOnly parameter is not supported in Gemini API.',\n );\n }\n\n if (\n common.getValueByPath(fromObject, ['preTunedModelCheckpointId']) !==\n undefined\n ) {\n throw new Error(\n 'preTunedModelCheckpointId parameter is not supported in Gemini API.',\n );\n }\n\n if (common.getValueByPath(fromObject, ['adapterSize']) !== undefined) {\n throw new Error('adapterSize parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['tuningMode']) !== undefined) {\n throw new Error('tuningMode parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['customBaseModel']) !== undefined) {\n throw new Error(\n 'customBaseModel parameter is not supported in Gemini API.',\n );\n }\n\n const fromBatchSize = common.getValueByPath(fromObject, ['batchSize']);\n if (parentObject !== undefined && fromBatchSize != null) {\n common.setValueByPath(\n parentObject,\n ['tuningTask', 'hyperparameters', 'batchSize'],\n fromBatchSize,\n );\n }\n\n const fromLearningRate = common.getValueByPath(fromObject, ['learningRate']);\n if (parentObject !== undefined && fromLearningRate != null) {\n common.setValueByPath(\n parentObject,\n ['tuningTask', 'hyperparameters', 'learningRate'],\n fromLearningRate,\n );\n }\n\n if (common.getValueByPath(fromObject, ['labels']) !== undefined) {\n throw new Error('labels parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['beta']) !== undefined) {\n throw new Error('beta parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['baseTeacherModel']) !== undefined) {\n throw new Error(\n 'baseTeacherModel parameter is not supported in Gemini API.',\n );\n }\n\n if (\n common.getValueByPath(fromObject, ['tunedTeacherModelSource']) !== undefined\n ) {\n throw new Error(\n 'tunedTeacherModelSource parameter is not supported in Gemini API.',\n );\n }\n\n if (\n common.getValueByPath(fromObject, ['sftLossWeightMultiplier']) !== undefined\n ) {\n throw new Error(\n 'sftLossWeightMultiplier parameter is not supported in Gemini API.',\n );\n }\n\n if (common.getValueByPath(fromObject, ['outputUri']) !== undefined) {\n throw new Error('outputUri parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['encryptionSpec']) !== undefined) {\n throw new Error('encryptionSpec parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function createTuningJobConfigToVertex(\n fromObject: types.CreateTuningJobConfig,\n parentObject: Record<string, unknown>,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n let discriminatorValidationDataset = common.getValueByPath(rootObject, [\n 'config',\n 'method',\n ]);\n if (discriminatorValidationDataset === undefined) {\n discriminatorValidationDataset = 'SUPERVISED_FINE_TUNING';\n }\n if (discriminatorValidationDataset === 'SUPERVISED_FINE_TUNING') {\n const fromValidationDataset = common.getValueByPath(fromObject, [\n 'validationDataset',\n ]);\n if (parentObject !== undefined && fromValidationDataset != null) {\n common.setValueByPath(\n parentObject,\n ['supervisedTuningSpec'],\n tuningValidationDatasetToVertex(fromValidationDataset, rootObject),\n );\n }\n } else if (discriminatorValidationDataset === 'PREFERENCE_TUNING') {\n const fromValidationDataset = common.getValueByPath(fromObject, [\n 'validationDataset',\n ]);\n if (parentObject !== undefined && fromValidationDataset != null) {\n common.setValueByPath(\n parentObject,\n ['preferenceOptimizationSpec'],\n tuningValidationDatasetToVertex(fromValidationDataset, rootObject),\n );\n }\n } else if (discriminatorValidationDataset === 'DISTILLATION') {\n const fromValidationDataset = common.getValueByPath(fromObject, [\n 'validationDataset',\n ]);\n if (parentObject !== undefined && fromValidationDataset != null) {\n common.setValueByPath(\n parentObject,\n ['distillationSpec'],\n tuningValidationDatasetToVertex(fromValidationDataset, rootObject),\n );\n }\n }\n\n const fromTunedModelDisplayName = common.getValueByPath(fromObject, [\n 'tunedModelDisplayName',\n ]);\n if (parentObject !== undefined && fromTunedModelDisplayName != null) {\n common.setValueByPath(\n parentObject,\n ['tunedModelDisplayName'],\n fromTunedModelDisplayName,\n );\n }\n\n const fromDescription = common.getValueByPath(fromObject, ['description']);\n if (parentObject !== undefined && fromDescription != null) {\n common.setValueByPath(parentObject, ['description'], fromDescription);\n }\n\n let discriminatorEpochCount = common.getValueByPath(rootObject, [\n 'config',\n 'method',\n ]);\n if (discriminatorEpochCount === undefined) {\n discriminatorEpochCount = 'SUPERVISED_FINE_TUNING';\n }\n if (discriminatorEpochCount === 'SUPERVISED_FINE_TUNING') {\n const fromEpochCount = common.getValueByPath(fromObject, ['epochCount']);\n if (parentObject !== undefined && fromEpochCount != null) {\n common.setValueByPath(\n parentObject,\n ['supervisedTuningSpec', 'hyperParameters', 'epochCount'],\n fromEpochCount,\n );\n }\n } else if (discriminatorEpochCount === 'PREFERENCE_TUNING') {\n const fromEpochCount = common.getValueByPath(fromObject, ['epochCount']);\n if (parentObject !== undefined && fromEpochCount != null) {\n common.setValueByPath(\n parentObject,\n ['preferenceOptimizationSpec', 'hyperParameters', 'epochCount'],\n fromEpochCount,\n );\n }\n } else if (discriminatorEpochCount === 'DISTILLATION') {\n const fromEpochCount = common.getValueByPath(fromObject, ['epochCount']);\n if (parentObject !== undefined && fromEpochCount != null) {\n common.setValueByPath(\n parentObject,\n ['distillationSpec', 'hyperParameters', 'epochCount'],\n fromEpochCount,\n );\n }\n }\n\n let discriminatorLearningRateMultiplier = common.getValueByPath(rootObject, [\n 'config',\n 'method',\n ]);\n if (discriminatorLearningRateMultiplier === undefined) {\n discriminatorLearningRateMultiplier = 'SUPERVISED_FINE_TUNING';\n }\n if (discriminatorLearningRateMultiplier === 'SUPERVISED_FINE_TUNING') {\n const fromLearningRateMultiplier = common.getValueByPath(fromObject, [\n 'learningRateMultiplier',\n ]);\n if (parentObject !== undefined && fromLearningRateMultiplier != null) {\n common.setValueByPath(\n parentObject,\n ['supervisedTuningSpec', 'hyperParameters', 'learningRateMultiplier'],\n fromLearningRateMultiplier,\n );\n }\n } else if (discriminatorLearningRateMultiplier === 'PREFERENCE_TUNING') {\n const fromLearningRateMultiplier = common.getValueByPath(fromObject, [\n 'learningRateMultiplier',\n ]);\n if (parentObject !== undefined && fromLearningRateMultiplier != null) {\n common.setValueByPath(\n parentObject,\n [\n 'preferenceOptimizationSpec',\n 'hyperParameters',\n 'learningRateMultiplier',\n ],\n fromLearningRateMultiplier,\n );\n }\n } else if (discriminatorLearningRateMultiplier === 'DISTILLATION') {\n const fromLearningRateMultiplier = common.getValueByPath(fromObject, [\n 'learningRateMultiplier',\n ]);\n if (parentObject !== undefined && fromLearningRateMultiplier != null) {\n common.setValueByPath(\n parentObject,\n ['distillationSpec', 'hyperParameters', 'learningRateMultiplier'],\n fromLearningRateMultiplier,\n );\n }\n }\n\n let discriminatorExportLastCheckpointOnly = common.getValueByPath(\n rootObject,\n ['config', 'method'],\n );\n if (discriminatorExportLastCheckpointOnly === undefined) {\n discriminatorExportLastCheckpointOnly = 'SUPERVISED_FINE_TUNING';\n }\n if (discriminatorExportLastCheckpointOnly === 'SUPERVISED_FINE_TUNING') {\n const fromExportLastCheckpointOnly = common.getValueByPath(fromObject, [\n 'exportLastCheckpointOnly',\n ]);\n if (parentObject !== undefined && fromExportLastCheckpointOnly != null) {\n common.setValueByPath(\n parentObject,\n ['supervisedTuningSpec', 'exportLastCheckpointOnly'],\n fromExportLastCheckpointOnly,\n );\n }\n } else if (discriminatorExportLastCheckpointOnly === 'PREFERENCE_TUNING') {\n const fromExportLastCheckpointOnly = common.getValueByPath(fromObject, [\n 'exportLastCheckpointOnly',\n ]);\n if (parentObject !== undefined && fromExportLastCheckpointOnly != null) {\n common.setValueByPath(\n parentObject,\n ['preferenceOptimizationSpec', 'exportLastCheckpointOnly'],\n fromExportLastCheckpointOnly,\n );\n }\n } else if (discriminatorExportLastCheckpointOnly === 'DISTILLATION') {\n const fromExportLastCheckpointOnly = common.getValueByPath(fromObject, [\n 'exportLastCheckpointOnly',\n ]);\n if (parentObject !== undefined && fromExportLastCheckpointOnly != null) {\n common.setValueByPath(\n parentObject,\n ['distillationSpec', 'exportLastCheckpointOnly'],\n fromExportLastCheckpointOnly,\n );\n }\n }\n\n let discriminatorAdapterSize = common.getValueByPath(rootObject, [\n 'config',\n 'method',\n ]);\n if (discriminatorAdapterSize === undefined) {\n discriminatorAdapterSize = 'SUPERVISED_FINE_TUNING';\n }\n if (discriminatorAdapterSize === 'SUPERVISED_FINE_TUNING') {\n const fromAdapterSize = common.getValueByPath(fromObject, ['adapterSize']);\n if (parentObject !== undefined && fromAdapterSize != null) {\n common.setValueByPath(\n parentObject,\n ['supervisedTuningSpec', 'hyperParameters', 'adapterSize'],\n fromAdapterSize,\n );\n }\n } else if (discriminatorAdapterSize === 'PREFERENCE_TUNING') {\n const fromAdapterSize = common.getValueByPath(fromObject, ['adapterSize']);\n if (parentObject !== undefined && fromAdapterSize != null) {\n common.setValueByPath(\n parentObject,\n ['preferenceOptimizationSpec', 'hyperParameters', 'adapterSize'],\n fromAdapterSize,\n );\n }\n } else if (discriminatorAdapterSize === 'DISTILLATION') {\n const fromAdapterSize = common.getValueByPath(fromObject, ['adapterSize']);\n if (parentObject !== undefined && fromAdapterSize != null) {\n common.setValueByPath(\n parentObject,\n ['distillationSpec', 'hyperParameters', 'adapterSize'],\n fromAdapterSize,\n );\n }\n }\n\n let discriminatorTuningMode = common.getValueByPath(rootObject, [\n 'config',\n 'method',\n ]);\n if (discriminatorTuningMode === undefined) {\n discriminatorTuningMode = 'SUPERVISED_FINE_TUNING';\n }\n if (discriminatorTuningMode === 'SUPERVISED_FINE_TUNING') {\n const fromTuningMode = common.getValueByPath(fromObject, ['tuningMode']);\n if (parentObject !== undefined && fromTuningMode != null) {\n common.setValueByPath(\n parentObject,\n ['supervisedTuningSpec', 'tuningMode'],\n fromTuningMode,\n );\n }\n }\n\n const fromCustomBaseModel = common.getValueByPath(fromObject, [\n 'customBaseModel',\n ]);\n if (parentObject !== undefined && fromCustomBaseModel != null) {\n common.setValueByPath(\n parentObject,\n ['customBaseModel'],\n fromCustomBaseModel,\n );\n }\n\n let discriminatorBatchSize = common.getValueByPath(rootObject, [\n 'config',\n 'method',\n ]);\n if (discriminatorBatchSize === undefined) {\n discriminatorBatchSize = 'SUPERVISED_FINE_TUNING';\n }\n if (discriminatorBatchSize === 'SUPERVISED_FINE_TUNING') {\n const fromBatchSize = common.getValueByPath(fromObject, ['batchSize']);\n if (parentObject !== undefined && fromBatchSize != null) {\n common.setValueByPath(\n parentObject,\n ['supervisedTuningSpec', 'hyperParameters', 'batchSize'],\n fromBatchSize,\n );\n }\n }\n\n let discriminatorLearningRate = common.getValueByPath(rootObject, [\n 'config',\n 'method',\n ]);\n if (discriminatorLearningRate === undefined) {\n discriminatorLearningRate = 'SUPERVISED_FINE_TUNING';\n }\n if (discriminatorLearningRate === 'SUPERVISED_FINE_TUNING') {\n const fromLearningRate = common.getValueByPath(fromObject, [\n 'learningRate',\n ]);\n if (parentObject !== undefined && fromLearningRate != null) {\n common.setValueByPath(\n parentObject,\n ['supervisedTuningSpec', 'hyperParameters', 'learningRate'],\n fromLearningRate,\n );\n }\n }\n\n const fromLabels = common.getValueByPath(fromObject, ['labels']);\n if (parentObject !== undefined && fromLabels != null) {\n common.setValueByPath(parentObject, ['labels'], fromLabels);\n }\n\n const fromBeta = common.getValueByPath(fromObject, ['beta']);\n if (parentObject !== undefined && fromBeta != null) {\n common.setValueByPath(\n parentObject,\n ['preferenceOptimizationSpec', 'hyperParameters', 'beta'],\n fromBeta,\n );\n }\n\n const fromBaseTeacherModel = common.getValueByPath(fromObject, [\n 'baseTeacherModel',\n ]);\n if (parentObject !== undefined && fromBaseTeacherModel != null) {\n common.setValueByPath(\n parentObject,\n ['distillationSpec', 'baseTeacherModel'],\n fromBaseTeacherModel,\n );\n }\n\n const fromTunedTeacherModelSource = common.getValueByPath(fromObject, [\n 'tunedTeacherModelSource',\n ]);\n if (parentObject !== undefined && fromTunedTeacherModelSource != null) {\n common.setValueByPath(\n parentObject,\n ['distillationSpec', 'tunedTeacherModelSource'],\n fromTunedTeacherModelSource,\n );\n }\n\n const fromSftLossWeightMultiplier = common.getValueByPath(fromObject, [\n 'sftLossWeightMultiplier',\n ]);\n if (parentObject !== undefined && fromSftLossWeightMultiplier != null) {\n common.setValueByPath(\n parentObject,\n ['distillationSpec', 'hyperParameters', 'sftLossWeightMultiplier'],\n fromSftLossWeightMultiplier,\n );\n }\n\n const fromOutputUri = common.getValueByPath(fromObject, ['outputUri']);\n if (parentObject !== undefined && fromOutputUri != null) {\n common.setValueByPath(parentObject, ['outputUri'], fromOutputUri);\n }\n\n const fromEncryptionSpec = common.getValueByPath(fromObject, [\n 'encryptionSpec',\n ]);\n if (parentObject !== undefined && fromEncryptionSpec != null) {\n common.setValueByPath(parentObject, ['encryptionSpec'], fromEncryptionSpec);\n }\n\n return toObject;\n}\n\nexport function createTuningJobParametersPrivateToMldev(\n fromObject: types.CreateTuningJobParametersPrivate,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromBaseModel = common.getValueByPath(fromObject, ['baseModel']);\n if (fromBaseModel != null) {\n common.setValueByPath(toObject, ['baseModel'], fromBaseModel);\n }\n\n const fromPreTunedModel = common.getValueByPath(fromObject, [\n 'preTunedModel',\n ]);\n if (fromPreTunedModel != null) {\n common.setValueByPath(toObject, ['preTunedModel'], fromPreTunedModel);\n }\n\n const fromTrainingDataset = common.getValueByPath(fromObject, [\n 'trainingDataset',\n ]);\n if (fromTrainingDataset != null) {\n tuningDatasetToMldev(fromTrainingDataset, rootObject);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n createTuningJobConfigToMldev(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function createTuningJobParametersPrivateToVertex(\n fromObject: types.CreateTuningJobParametersPrivate,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromBaseModel = common.getValueByPath(fromObject, ['baseModel']);\n if (fromBaseModel != null) {\n common.setValueByPath(toObject, ['baseModel'], fromBaseModel);\n }\n\n const fromPreTunedModel = common.getValueByPath(fromObject, [\n 'preTunedModel',\n ]);\n if (fromPreTunedModel != null) {\n common.setValueByPath(toObject, ['preTunedModel'], fromPreTunedModel);\n }\n\n const fromTrainingDataset = common.getValueByPath(fromObject, [\n 'trainingDataset',\n ]);\n if (fromTrainingDataset != null) {\n tuningDatasetToVertex(fromTrainingDataset, toObject, rootObject);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n createTuningJobConfigToVertex(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function getTuningJobParametersToMldev(\n fromObject: types.GetTuningJobParameters,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['_url', 'name'], fromName);\n }\n\n return toObject;\n}\n\nexport function getTuningJobParametersToVertex(\n fromObject: types.GetTuningJobParameters,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['_url', 'name'], fromName);\n }\n\n return toObject;\n}\n\nexport function listTuningJobsConfigToMldev(\n fromObject: types.ListTuningJobsConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPageSize = common.getValueByPath(fromObject, ['pageSize']);\n if (parentObject !== undefined && fromPageSize != null) {\n common.setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize);\n }\n\n const fromPageToken = common.getValueByPath(fromObject, ['pageToken']);\n if (parentObject !== undefined && fromPageToken != null) {\n common.setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken);\n }\n\n const fromFilter = common.getValueByPath(fromObject, ['filter']);\n if (parentObject !== undefined && fromFilter != null) {\n common.setValueByPath(parentObject, ['_query', 'filter'], fromFilter);\n }\n\n return toObject;\n}\n\nexport function listTuningJobsConfigToVertex(\n fromObject: types.ListTuningJobsConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPageSize = common.getValueByPath(fromObject, ['pageSize']);\n if (parentObject !== undefined && fromPageSize != null) {\n common.setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize);\n }\n\n const fromPageToken = common.getValueByPath(fromObject, ['pageToken']);\n if (parentObject !== undefined && fromPageToken != null) {\n common.setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken);\n }\n\n const fromFilter = common.getValueByPath(fromObject, ['filter']);\n if (parentObject !== undefined && fromFilter != null) {\n common.setValueByPath(parentObject, ['_query', 'filter'], fromFilter);\n }\n\n return toObject;\n}\n\nexport function listTuningJobsParametersToMldev(\n fromObject: types.ListTuningJobsParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n listTuningJobsConfigToMldev(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function listTuningJobsParametersToVertex(\n fromObject: types.ListTuningJobsParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n listTuningJobsConfigToVertex(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function listTuningJobsResponseFromMldev(\n fromObject: types.ListTuningJobsResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromNextPageToken = common.getValueByPath(fromObject, [\n 'nextPageToken',\n ]);\n if (fromNextPageToken != null) {\n common.setValueByPath(toObject, ['nextPageToken'], fromNextPageToken);\n }\n\n const fromTuningJobs = common.getValueByPath(fromObject, ['tunedModels']);\n if (fromTuningJobs != null) {\n let transformedList = fromTuningJobs;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return tuningJobFromMldev(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['tuningJobs'], transformedList);\n }\n\n return toObject;\n}\n\nexport function listTuningJobsResponseFromVertex(\n fromObject: types.ListTuningJobsResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromNextPageToken = common.getValueByPath(fromObject, [\n 'nextPageToken',\n ]);\n if (fromNextPageToken != null) {\n common.setValueByPath(toObject, ['nextPageToken'], fromNextPageToken);\n }\n\n const fromTuningJobs = common.getValueByPath(fromObject, ['tuningJobs']);\n if (fromTuningJobs != null) {\n let transformedList = fromTuningJobs;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return tuningJobFromVertex(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['tuningJobs'], transformedList);\n }\n\n return toObject;\n}\n\nexport function tunedModelFromMldev(\n fromObject: types.TunedModel,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['name']);\n if (fromModel != null) {\n common.setValueByPath(toObject, ['model'], fromModel);\n }\n\n const fromEndpoint = common.getValueByPath(fromObject, ['name']);\n if (fromEndpoint != null) {\n common.setValueByPath(toObject, ['endpoint'], fromEndpoint);\n }\n\n return toObject;\n}\n\nexport function tuningDatasetToMldev(\n fromObject: types.TuningDataset,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['gcsUri']) !== undefined) {\n throw new Error('gcsUri parameter is not supported in Gemini API.');\n }\n\n if (\n common.getValueByPath(fromObject, ['vertexDatasetResource']) !== undefined\n ) {\n throw new Error(\n 'vertexDatasetResource parameter is not supported in Gemini API.',\n );\n }\n\n const fromExamples = common.getValueByPath(fromObject, ['examples']);\n if (fromExamples != null) {\n let transformedList = fromExamples;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['examples', 'examples'], transformedList);\n }\n\n return toObject;\n}\n\nexport function tuningDatasetToVertex(\n fromObject: types.TuningDataset,\n parentObject: Record<string, unknown>,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n let discriminatorGcsUri = common.getValueByPath(rootObject, [\n 'config',\n 'method',\n ]);\n if (discriminatorGcsUri === undefined) {\n discriminatorGcsUri = 'SUPERVISED_FINE_TUNING';\n }\n if (discriminatorGcsUri === 'SUPERVISED_FINE_TUNING') {\n const fromGcsUri = common.getValueByPath(fromObject, ['gcsUri']);\n if (parentObject !== undefined && fromGcsUri != null) {\n common.setValueByPath(\n parentObject,\n ['supervisedTuningSpec', 'trainingDatasetUri'],\n fromGcsUri,\n );\n }\n } else if (discriminatorGcsUri === 'PREFERENCE_TUNING') {\n const fromGcsUri = common.getValueByPath(fromObject, ['gcsUri']);\n if (parentObject !== undefined && fromGcsUri != null) {\n common.setValueByPath(\n parentObject,\n ['preferenceOptimizationSpec', 'trainingDatasetUri'],\n fromGcsUri,\n );\n }\n } else if (discriminatorGcsUri === 'DISTILLATION') {\n const fromGcsUri = common.getValueByPath(fromObject, ['gcsUri']);\n if (parentObject !== undefined && fromGcsUri != null) {\n common.setValueByPath(\n parentObject,\n ['distillationSpec', 'promptDatasetUri'],\n fromGcsUri,\n );\n }\n }\n\n let discriminatorVertexDatasetResource = common.getValueByPath(rootObject, [\n 'config',\n 'method',\n ]);\n if (discriminatorVertexDatasetResource === undefined) {\n discriminatorVertexDatasetResource = 'SUPERVISED_FINE_TUNING';\n }\n if (discriminatorVertexDatasetResource === 'SUPERVISED_FINE_TUNING') {\n const fromVertexDatasetResource = common.getValueByPath(fromObject, [\n 'vertexDatasetResource',\n ]);\n if (parentObject !== undefined && fromVertexDatasetResource != null) {\n common.setValueByPath(\n parentObject,\n ['supervisedTuningSpec', 'trainingDatasetUri'],\n fromVertexDatasetResource,\n );\n }\n } else if (discriminatorVertexDatasetResource === 'PREFERENCE_TUNING') {\n const fromVertexDatasetResource = common.getValueByPath(fromObject, [\n 'vertexDatasetResource',\n ]);\n if (parentObject !== undefined && fromVertexDatasetResource != null) {\n common.setValueByPath(\n parentObject,\n ['preferenceOptimizationSpec', 'trainingDatasetUri'],\n fromVertexDatasetResource,\n );\n }\n } else if (discriminatorVertexDatasetResource === 'DISTILLATION') {\n const fromVertexDatasetResource = common.getValueByPath(fromObject, [\n 'vertexDatasetResource',\n ]);\n if (parentObject !== undefined && fromVertexDatasetResource != null) {\n common.setValueByPath(\n parentObject,\n ['distillationSpec', 'promptDatasetUri'],\n fromVertexDatasetResource,\n );\n }\n }\n if (common.getValueByPath(fromObject, ['examples']) !== undefined) {\n throw new Error('examples parameter is not supported in Vertex AI.');\n }\n\n return toObject;\n}\n\nexport function tuningJobFromMldev(\n fromObject: types.TuningJob,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromState = common.getValueByPath(fromObject, ['state']);\n if (fromState != null) {\n common.setValueByPath(toObject, ['state'], t.tTuningJobStatus(fromState));\n }\n\n const fromCreateTime = common.getValueByPath(fromObject, ['createTime']);\n if (fromCreateTime != null) {\n common.setValueByPath(toObject, ['createTime'], fromCreateTime);\n }\n\n const fromStartTime = common.getValueByPath(fromObject, [\n 'tuningTask',\n 'startTime',\n ]);\n if (fromStartTime != null) {\n common.setValueByPath(toObject, ['startTime'], fromStartTime);\n }\n\n const fromEndTime = common.getValueByPath(fromObject, [\n 'tuningTask',\n 'completeTime',\n ]);\n if (fromEndTime != null) {\n common.setValueByPath(toObject, ['endTime'], fromEndTime);\n }\n\n const fromUpdateTime = common.getValueByPath(fromObject, ['updateTime']);\n if (fromUpdateTime != null) {\n common.setValueByPath(toObject, ['updateTime'], fromUpdateTime);\n }\n\n const fromDescription = common.getValueByPath(fromObject, ['description']);\n if (fromDescription != null) {\n common.setValueByPath(toObject, ['description'], fromDescription);\n }\n\n const fromBaseModel = common.getValueByPath(fromObject, ['baseModel']);\n if (fromBaseModel != null) {\n common.setValueByPath(toObject, ['baseModel'], fromBaseModel);\n }\n\n const fromTunedModel = common.getValueByPath(fromObject, ['_self']);\n if (fromTunedModel != null) {\n common.setValueByPath(\n toObject,\n ['tunedModel'],\n tunedModelFromMldev(fromTunedModel, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function tuningJobFromVertex(\n fromObject: types.TuningJob,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromState = common.getValueByPath(fromObject, ['state']);\n if (fromState != null) {\n common.setValueByPath(toObject, ['state'], t.tTuningJobStatus(fromState));\n }\n\n const fromCreateTime = common.getValueByPath(fromObject, ['createTime']);\n if (fromCreateTime != null) {\n common.setValueByPath(toObject, ['createTime'], fromCreateTime);\n }\n\n const fromStartTime = common.getValueByPath(fromObject, ['startTime']);\n if (fromStartTime != null) {\n common.setValueByPath(toObject, ['startTime'], fromStartTime);\n }\n\n const fromEndTime = common.getValueByPath(fromObject, ['endTime']);\n if (fromEndTime != null) {\n common.setValueByPath(toObject, ['endTime'], fromEndTime);\n }\n\n const fromUpdateTime = common.getValueByPath(fromObject, ['updateTime']);\n if (fromUpdateTime != null) {\n common.setValueByPath(toObject, ['updateTime'], fromUpdateTime);\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n const fromDescription = common.getValueByPath(fromObject, ['description']);\n if (fromDescription != null) {\n common.setValueByPath(toObject, ['description'], fromDescription);\n }\n\n const fromBaseModel = common.getValueByPath(fromObject, ['baseModel']);\n if (fromBaseModel != null) {\n common.setValueByPath(toObject, ['baseModel'], fromBaseModel);\n }\n\n const fromTunedModel = common.getValueByPath(fromObject, ['tunedModel']);\n if (fromTunedModel != null) {\n common.setValueByPath(toObject, ['tunedModel'], fromTunedModel);\n }\n\n const fromPreTunedModel = common.getValueByPath(fromObject, [\n 'preTunedModel',\n ]);\n if (fromPreTunedModel != null) {\n common.setValueByPath(toObject, ['preTunedModel'], fromPreTunedModel);\n }\n\n const fromSupervisedTuningSpec = common.getValueByPath(fromObject, [\n 'supervisedTuningSpec',\n ]);\n if (fromSupervisedTuningSpec != null) {\n common.setValueByPath(\n toObject,\n ['supervisedTuningSpec'],\n fromSupervisedTuningSpec,\n );\n }\n\n const fromPreferenceOptimizationSpec = common.getValueByPath(fromObject, [\n 'preferenceOptimizationSpec',\n ]);\n if (fromPreferenceOptimizationSpec != null) {\n common.setValueByPath(\n toObject,\n ['preferenceOptimizationSpec'],\n fromPreferenceOptimizationSpec,\n );\n }\n\n const fromDistillationSpec = common.getValueByPath(fromObject, [\n 'distillationSpec',\n ]);\n if (fromDistillationSpec != null) {\n common.setValueByPath(toObject, ['distillationSpec'], fromDistillationSpec);\n }\n\n const fromTuningDataStats = common.getValueByPath(fromObject, [\n 'tuningDataStats',\n ]);\n if (fromTuningDataStats != null) {\n common.setValueByPath(toObject, ['tuningDataStats'], fromTuningDataStats);\n }\n\n const fromEncryptionSpec = common.getValueByPath(fromObject, [\n 'encryptionSpec',\n ]);\n if (fromEncryptionSpec != null) {\n common.setValueByPath(toObject, ['encryptionSpec'], fromEncryptionSpec);\n }\n\n const fromPartnerModelTuningSpec = common.getValueByPath(fromObject, [\n 'partnerModelTuningSpec',\n ]);\n if (fromPartnerModelTuningSpec != null) {\n common.setValueByPath(\n toObject,\n ['partnerModelTuningSpec'],\n fromPartnerModelTuningSpec,\n );\n }\n\n const fromCustomBaseModel = common.getValueByPath(fromObject, [\n 'customBaseModel',\n ]);\n if (fromCustomBaseModel != null) {\n common.setValueByPath(toObject, ['customBaseModel'], fromCustomBaseModel);\n }\n\n const fromExperiment = common.getValueByPath(fromObject, ['experiment']);\n if (fromExperiment != null) {\n common.setValueByPath(toObject, ['experiment'], fromExperiment);\n }\n\n const fromLabels = common.getValueByPath(fromObject, ['labels']);\n if (fromLabels != null) {\n common.setValueByPath(toObject, ['labels'], fromLabels);\n }\n\n const fromOutputUri = common.getValueByPath(fromObject, ['outputUri']);\n if (fromOutputUri != null) {\n common.setValueByPath(toObject, ['outputUri'], fromOutputUri);\n }\n\n const fromPipelineJob = common.getValueByPath(fromObject, ['pipelineJob']);\n if (fromPipelineJob != null) {\n common.setValueByPath(toObject, ['pipelineJob'], fromPipelineJob);\n }\n\n const fromServiceAccount = common.getValueByPath(fromObject, [\n 'serviceAccount',\n ]);\n if (fromServiceAccount != null) {\n common.setValueByPath(toObject, ['serviceAccount'], fromServiceAccount);\n }\n\n const fromTunedModelDisplayName = common.getValueByPath(fromObject, [\n 'tunedModelDisplayName',\n ]);\n if (fromTunedModelDisplayName != null) {\n common.setValueByPath(\n toObject,\n ['tunedModelDisplayName'],\n fromTunedModelDisplayName,\n );\n }\n\n const fromVeoTuningSpec = common.getValueByPath(fromObject, [\n 'veoTuningSpec',\n ]);\n if (fromVeoTuningSpec != null) {\n common.setValueByPath(toObject, ['veoTuningSpec'], fromVeoTuningSpec);\n }\n\n return toObject;\n}\n\nexport function tuningOperationFromMldev(\n fromObject: types.TuningOperation,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromMetadata = common.getValueByPath(fromObject, ['metadata']);\n if (fromMetadata != null) {\n common.setValueByPath(toObject, ['metadata'], fromMetadata);\n }\n\n const fromDone = common.getValueByPath(fromObject, ['done']);\n if (fromDone != null) {\n common.setValueByPath(toObject, ['done'], fromDone);\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n return toObject;\n}\n\nexport function tuningValidationDatasetToVertex(\n fromObject: types.TuningValidationDataset,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromGcsUri = common.getValueByPath(fromObject, ['gcsUri']);\n if (fromGcsUri != null) {\n common.setValueByPath(toObject, ['validationDatasetUri'], fromGcsUri);\n }\n\n const fromVertexDatasetResource = common.getValueByPath(fromObject, [\n 'vertexDatasetResource',\n ]);\n if (fromVertexDatasetResource != null) {\n common.setValueByPath(\n toObject,\n ['validationDatasetUri'],\n fromVertexDatasetResource,\n );\n }\n\n return toObject;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport {ApiClient} from './_api_client.js';\nimport * as common from './_common.js';\nimport {BaseModule} from './_common.js';\nimport * as converters from './converters/_tunings_converters.js';\nimport {PagedItem, Pager} from './pagers.js';\nimport * as types from './types.js';\n\nexport class Tunings extends BaseModule {\n constructor(private readonly apiClient: ApiClient) {\n super();\n }\n\n /**\n * Lists tuning jobs.\n *\n * @param params - The parameters for the list request.\n * @return - A pager of tuning jobs.\n *\n * @example\n * ```ts\n * const tuningJobs = await ai.tunings.list({config: {'pageSize': 2}});\n * for await (const tuningJob of tuningJobs) {\n * console.log(tuningJob);\n * }\n * ```\n */\n list = async (\n params: types.ListTuningJobsParameters = {},\n ): Promise<Pager<types.TuningJob>> => {\n return new Pager<types.TuningJob>(\n PagedItem.PAGED_ITEM_TUNING_JOBS,\n (x: types.ListTuningJobsParameters) => this.listInternal(x),\n await this.listInternal(params),\n params,\n );\n };\n\n /**\n * Gets a TuningJob.\n *\n * @param name - The resource name of the tuning job.\n * @return - A TuningJob object.\n *\n * @experimental - The SDK's tuning implementation is experimental, and may\n * change in future versions.\n */\n get = async (\n params: types.GetTuningJobParameters,\n ): Promise<types.TuningJob> => {\n return await this.getInternal(params);\n };\n\n /**\n * Creates a supervised fine-tuning job.\n *\n * @param params - The parameters for the tuning job.\n * @return - A TuningJob operation.\n *\n * @experimental - The SDK's tuning implementation is experimental, and may\n * change in future versions.\n */\n tune = async (\n params: types.CreateTuningJobParameters,\n ): Promise<types.TuningJob> => {\n if (this.apiClient.isVertexAI()) {\n if (params.baseModel.startsWith('projects/')) {\n const preTunedModel: types.PreTunedModel = {\n tunedModelName: params.baseModel,\n };\n if (params.config?.preTunedModelCheckpointId) {\n preTunedModel.checkpointId = params.config.preTunedModelCheckpointId;\n }\n const paramsPrivate: types.CreateTuningJobParametersPrivate = {\n ...params,\n preTunedModel: preTunedModel,\n };\n paramsPrivate.baseModel = undefined;\n return await this.tuneInternal(paramsPrivate);\n } else {\n const paramsPrivate: types.CreateTuningJobParametersPrivate = {\n ...params,\n };\n return await this.tuneInternal(paramsPrivate);\n }\n } else {\n const paramsPrivate: types.CreateTuningJobParametersPrivate = {\n ...params,\n };\n const operation = await this.tuneMldevInternal(paramsPrivate);\n let tunedModelName = '';\n if (\n operation['metadata'] !== undefined &&\n operation['metadata']['tunedModel'] !== undefined\n ) {\n tunedModelName = operation['metadata']['tunedModel'] as string;\n } else if (\n operation['name'] !== undefined &&\n operation['name'].includes('/operations/')\n ) {\n tunedModelName = operation['name'].split('/operations/')[0];\n }\n const tuningJob: types.TuningJob = {\n name: tunedModelName,\n state: types.JobState.JOB_STATE_QUEUED,\n };\n\n return tuningJob;\n }\n };\n\n private async getInternal(\n params: types.GetTuningJobParameters,\n ): Promise<types.TuningJob> {\n let response: Promise<types.TuningJob>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.getTuningJobParametersToVertex(params, params);\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.TuningJob;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.TuningJob>;\n\n return response.then((apiResponse) => {\n const resp = converters.tuningJobFromVertex(apiResponse, params);\n\n return resp as types.TuningJob;\n });\n } else {\n const body = converters.getTuningJobParametersToMldev(params, params);\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.TuningJob;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.TuningJob>;\n\n return response.then((apiResponse) => {\n const resp = converters.tuningJobFromMldev(apiResponse, params);\n\n return resp as types.TuningJob;\n });\n }\n }\n\n private async listInternal(\n params: types.ListTuningJobsParameters,\n ): Promise<types.ListTuningJobsResponse> {\n let response: Promise<types.ListTuningJobsResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.listTuningJobsParametersToVertex(params, params);\n path = common.formatMap(\n 'tuningJobs',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.ListTuningJobsResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.ListTuningJobsResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.listTuningJobsResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.ListTuningJobsResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n const body = converters.listTuningJobsParametersToMldev(params, params);\n path = common.formatMap(\n 'tunedModels',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.ListTuningJobsResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.ListTuningJobsResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.listTuningJobsResponseFromMldev(\n apiResponse,\n params,\n );\n const typedResp = new types.ListTuningJobsResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n /**\n * Cancels a tuning job.\n *\n * @param params - The parameters for the cancel request.\n * @return The empty response returned by the API.\n *\n * @example\n * ```ts\n * await ai.tunings.cancel({name: '...'}); // The server-generated resource name.\n * ```\n */\n async cancel(\n params: types.CancelTuningJobParameters,\n ): Promise<types.CancelTuningJobResponse> {\n let response: Promise<types.CancelTuningJobResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.cancelTuningJobParametersToVertex(params, params);\n path = common.formatMap(\n '{name}:cancel',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.CancelTuningJobResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.CancelTuningJobResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.cancelTuningJobResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.CancelTuningJobResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n const body = converters.cancelTuningJobParametersToMldev(params, params);\n path = common.formatMap(\n '{name}:cancel',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.CancelTuningJobResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.CancelTuningJobResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.cancelTuningJobResponseFromMldev(\n apiResponse,\n params,\n );\n const typedResp = new types.CancelTuningJobResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n private async tuneInternal(\n params: types.CreateTuningJobParametersPrivate,\n ): Promise<types.TuningJob> {\n let response: Promise<types.TuningJob>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.createTuningJobParametersPrivateToVertex(\n params,\n params,\n );\n path = common.formatMap(\n 'tuningJobs',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.TuningJob;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.TuningJob>;\n\n return response.then((apiResponse) => {\n const resp = converters.tuningJobFromVertex(apiResponse, params);\n\n return resp as types.TuningJob;\n });\n } else {\n throw new Error('This method is only supported by the Vertex AI.');\n }\n }\n\n private async tuneMldevInternal(\n params: types.CreateTuningJobParametersPrivate,\n ): Promise<types.TuningOperation> {\n let response: Promise<types.TuningOperation>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.createTuningJobParametersPrivateToMldev(\n params,\n params,\n );\n path = common.formatMap(\n 'tunedModels',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.TuningOperation;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.TuningOperation>;\n\n return response.then((apiResponse) => {\n const resp = converters.tuningOperationFromMldev(apiResponse, params);\n\n return resp as types.TuningOperation;\n });\n }\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {Auth} from '../_auth.js';\n\nexport const GOOGLE_API_KEY_HEADER = 'x-goog-api-key';\n// TODO(b/395122533): We need a secure client side authentication mechanism.\nexport class WebAuth implements Auth {\n constructor(private readonly apiKey: string) {}\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n async addAuthHeaders(headers: Headers, url?: string): Promise<void> {\n if (headers.get(GOOGLE_API_KEY_HEADER) !== null) {\n return;\n }\n\n if (this.apiKey.startsWith('auth_tokens/')) {\n throw new Error('Ephemeral tokens are only supported by the live API.');\n }\n\n // Check if API key is empty or null\n if (!this.apiKey) {\n throw new Error('API key is missing. Please provide a valid API key.');\n }\n headers.append(GOOGLE_API_KEY_HEADER, this.apiKey);\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {GoogleAuthOptions} from 'google-auth-library';\n\nimport {ApiClient} from './_api_client.js';\nimport {Batches} from './batches.js';\nimport {Caches} from './caches.js';\nimport {Chats} from './chats.js';\nimport {CrossDownloader} from './cross/_cross_downloader.js';\nimport {crossError} from './cross/_cross_error.js';\nimport {CrossUploader} from './cross/_cross_uploader.js';\nimport {CrossWebSocketFactory} from './cross/_cross_websocket.js';\nimport {Files} from './files.js';\nimport {FileSearchStores} from './filesearchstores.js';\nimport GeminiNextGenAPI from './interactions/index.js';\nimport {Interactions as GeminiNextGenInteractions} from './interactions/resources/interactions.js';\nimport {Live} from './live.js';\nimport {Models} from './models.js';\nimport {Operations} from './operations.js';\nimport {Tokens} from './tokens.js';\nimport {Tunings} from './tunings.js';\nimport {HttpOptions} from './types.js';\nimport {WebAuth} from './web/_web_auth.js';\n\nconst LANGUAGE_LABEL_PREFIX = 'gl-node/';\n\n/**\n * Google Gen AI SDK's configuration options.\n *\n * See {@link GoogleGenAI} for usage samples.\n */\nexport interface GoogleGenAIOptions {\n /**\n * Optional. Determines whether to use the Vertex AI or the Gemini API.\n *\n * @remarks\n * When true, the {@link https://cloud.google.com/vertex-ai/docs/reference/rest | Vertex AI API} will used.\n * When false, the {@link https://ai.google.dev/api | Gemini API} will be used.\n *\n * If unset, default SDK behavior is to use the Gemini API service.\n */\n vertexai?: boolean;\n /**\n * Optional. The Google Cloud project ID for Vertex AI clients.\n *\n * Find your project ID: https://cloud.google.com/resource-manager/docs/creating-managing-projects#identifying_projects\n *\n * @remarks\n * Only supported on Node runtimes, ignored on browser runtimes.\n */\n project?: string;\n /**\n * Optional. The Google Cloud project {@link https://cloud.google.com/vertex-ai/generative-ai/docs/learn/locations | location} for Vertex AI clients.\n *\n * @remarks\n * Only supported on Node runtimes, ignored on browser runtimes.\n *\n */\n location?: string;\n /**\n * The API Key, required for Gemini API clients.\n *\n * @remarks\n * Required on browser runtimes.\n */\n apiKey?: string;\n /**\n * Optional. The API version to use.\n *\n * @remarks\n * If unset, the default API version will be used.\n */\n apiVersion?: string;\n /**\n * Optional. Authentication options defined by the by google-auth-library for Vertex AI clients.\n *\n * @remarks\n * @see {@link https://github.com/googleapis/google-auth-library-nodejs/blob/v9.15.0/src/auth/googleauth.ts | GoogleAuthOptions interface in google-auth-library-nodejs}.\n *\n * Only supported on Node runtimes, ignored on browser runtimes.\n *\n */\n googleAuthOptions?: GoogleAuthOptions;\n /**\n * Optional. A set of customizable configuration for HTTP requests.\n */\n httpOptions?: HttpOptions;\n}\n\n/**\n * The Google GenAI SDK.\n *\n * @remarks\n * Provides access to the GenAI features through either the {@link https://cloud.google.com/vertex-ai/docs/reference/rest | Gemini API}\n * or the {@link https://cloud.google.com/vertex-ai/docs/reference/rest | Vertex AI API}.\n *\n * The {@link GoogleGenAIOptions.vertexai} value determines which of the API services to use.\n *\n * When using the Gemini API, a {@link GoogleGenAIOptions.apiKey} must also be set,\n * when using Vertex AI {@link GoogleGenAIOptions.project} and {@link GoogleGenAIOptions.location} must also be set.\n *\n * @example\n * Initializing the SDK for using the Gemini API:\n * ```ts\n * import {GoogleGenAI} from '@google/genai';\n * const ai = new GoogleGenAI({apiKey: 'GEMINI_API_KEY'});\n * ```\n *\n * @example\n * Initializing the SDK for using the Vertex AI API:\n * ```ts\n * import {GoogleGenAI} from '@google/genai';\n * const ai = new GoogleGenAI({\n * vertexai: true,\n * project: 'PROJECT_ID',\n * location: 'PROJECT_LOCATION'\n * });\n * ```\n *\n */\nexport class GoogleGenAI {\n protected readonly apiClient: ApiClient;\n private readonly apiKey?: string;\n public readonly vertexai: boolean;\n private readonly apiVersion?: string;\n private readonly httpOptions?: HttpOptions;\n readonly models: Models;\n readonly live: Live;\n readonly batches: Batches;\n readonly chats: Chats;\n readonly caches: Caches;\n readonly files: Files;\n readonly operations: Operations;\n readonly authTokens: Tokens;\n readonly tunings: Tunings;\n readonly fileSearchStores: FileSearchStores;\n private _interactions: GeminiNextGenInteractions | undefined;\n\n get interactions(): GeminiNextGenInteractions {\n if (this._interactions !== undefined) {\n return this._interactions;\n }\n\n console.warn(\n 'GoogleGenAI.interactions: Interactions usage is experimental and may change in future versions.',\n );\n\n if (this.vertexai) {\n throw new Error(\n 'This version of the GenAI SDK does not support Vertex AI API for interactions.',\n );\n }\n\n const httpOpts = this.httpOptions;\n\n // Unsupported Options Warnings\n if (httpOpts?.extraBody) {\n console.warn(\n 'GoogleGenAI.interactions: Client level httpOptions.extraBody is not supported by the interactions client and will be ignored.',\n );\n }\n\n const nextGenClient = new GeminiNextGenAPI({\n baseURL: this.apiClient.getBaseUrl(),\n apiKey: this.apiKey,\n apiVersion: this.apiClient.getApiVersion(),\n clientAdapter: this.apiClient,\n defaultHeaders: this.apiClient.getDefaultHeaders(),\n timeout: httpOpts?.timeout,\n maxRetries: httpOpts?.retryOptions?.attempts,\n });\n this._interactions = nextGenClient.interactions;\n\n return this._interactions;\n }\n\n constructor(options: GoogleGenAIOptions) {\n if (options.apiKey == null) {\n throw new Error(\n `An API Key must be set when running in an unspecified environment.\\n + ${crossError().message}`,\n );\n }\n this.vertexai = options.vertexai ?? false;\n this.apiKey = options.apiKey;\n this.apiVersion = options.apiVersion;\n this.httpOptions = options.httpOptions;\n const auth = new WebAuth(this.apiKey);\n this.apiClient = new ApiClient({\n auth: auth,\n apiVersion: this.apiVersion,\n apiKey: this.apiKey,\n vertexai: this.vertexai,\n httpOptions: this.httpOptions,\n userAgentExtra: LANGUAGE_LABEL_PREFIX + 'cross',\n uploader: new CrossUploader(),\n downloader: new CrossDownloader(),\n });\n this.models = new Models(this.apiClient);\n this.live = new Live(this.apiClient, auth, new CrossWebSocketFactory());\n this.chats = new Chats(this.models, this.apiClient);\n this.batches = new Batches(this.apiClient);\n this.caches = new Caches(this.apiClient);\n this.files = new Files(this.apiClient);\n this.operations = new Operations(this.apiClient);\n this.authTokens = new Tokens(this.apiClient);\n this.tunings = new Tunings(this.apiClient);\n this.fileSearchStores = new FileSearchStores(this.apiClient);\n }\n}\n"],"names":["tBytes","common.getValueByPath","common.setValueByPath","generateVideosOperationFromMldev","generateVideosResponseFromMldev","generateVideosOperationFromVertex","generateVideosResponseFromVertex","generatedVideoFromMldev","generatedVideoFromVertex","videoFromMldev","videoFromVertex","importFileOperationFromMldev","importFileResponseFromMldev","t.tBytes","types.Type","baseTransformers.tBytes","t.tJobState","t.tRecvBatchJobDestination","blobToMldev","t.tBatchJobName","candidateFromMldev","citationMetadataFromMldev","contentToMldev","partToMldev","t.tBatchJobDestination","t.tModel","t.tBatchJobSource","t.tContentsForEmbed","embedContentConfigToMldev","common.moveValueByPath","fileDataToMldev","functionCallToMldev","functionCallingConfigToMldev","generateContentConfigToMldev","t.tContent","t.tSchema","safetySettingToMldev","t.tTools","toolToMldev","t.tTool","toolConfigToMldev","t.tCachedContentName","t.tSpeechConfig","imageConfigToMldev","generateContentResponseFromMldev","googleMapsToMldev","googleSearchToMldev","t.tContents","converters.createBatchJobParametersToMldev","common.formatMap","converters.createBatchJobParametersToVertex","converters.batchJobFromVertex","converters.batchJobFromMldev","converters.createEmbeddingsBatchJobParametersToMldev","converters.getBatchJobParametersToVertex","converters.getBatchJobParametersToMldev","converters.cancelBatchJobParametersToVertex","converters.cancelBatchJobParametersToMldev","converters.listBatchJobsParametersToVertex","converters.listBatchJobsResponseFromVertex","types.ListBatchJobsResponse","converters.listBatchJobsParametersToMldev","converters.listBatchJobsResponseFromMldev","converters.deleteBatchJobParametersToVertex","converters.deleteResourceJobFromVertex","converters.deleteBatchJobParametersToMldev","converters.deleteResourceJobFromMldev","toolToVertex","t.tCachesModel","functionDeclarationToVertex","converters.createCachedContentParametersToVertex","converters.createCachedContentParametersToMldev","converters.getCachedContentParametersToVertex","converters.getCachedContentParametersToMldev","converters.deleteCachedContentParametersToVertex","converters.deleteCachedContentResponseFromVertex","types.DeleteCachedContentResponse","converters.deleteCachedContentParametersToMldev","converters.deleteCachedContentResponseFromMldev","converters.updateCachedContentParametersToVertex","converters.updateCachedContentParametersToMldev","converters.listCachedContentsParametersToVertex","converters.listCachedContentsResponseFromVertex","types.ListCachedContentsResponse","converters.listCachedContentsParametersToMldev","converters.listCachedContentsResponseFromMldev","types.ResourceScope","types.HttpResponse","_converters.uploadToFileSearchStoreOperationFromMldev","sleep","t.tFileName","converters.listFilesParametersToMldev","converters.listFilesResponseFromMldev","types.ListFilesResponse","converters.createFileParametersToMldev","converters.createFileResponseFromMldev","types.CreateFileResponse","converters.getFileParametersToMldev","converters.deleteFileParametersToMldev","converters.deleteFileResponseFromMldev","types.DeleteFileResponse","converters.internalRegisterFilesParametersToMldev","converters.registerFilesResponseFromMldev","types.RegisterFilesResponse","converters.getDocumentParametersToMldev","converters.deleteDocumentParametersToMldev","converters.listDocumentsParametersToMldev","converters.listDocumentsResponseFromMldev","types.ListDocumentsResponse","converters.createFileSearchStoreParametersToMldev","converters.getFileSearchStoreParametersToMldev","converters.deleteFileSearchStoreParametersToMldev","converters.listFileSearchStoresParametersToMldev","converters.listFileSearchStoresResponseFromMldev","types.ListFileSearchStoresResponse","converters.uploadToFileSearchStoreParametersToMldev","converters.uploadToFileSearchStoreResumableResponseFromMldev","types.UploadToFileSearchStoreResumableResponse","converters.importFileParametersToMldev","converters.importFileOperationFromMldev","types.ImportFileOperation","Errors.GeminiNextGenAPIClientError","Shims.getDefaultFetch","Opts.FallbackEncoder","Errors.APIError","Errors.APIUserAbortError","Errors.APIConnectionTimeoutError","Errors.APIConnectionError","Shims.CancelReadableStream","Shims.ReadableStreamFrom","API.Interactions","Errors.NotFoundError","Errors.ConflictError","Errors.RateLimitError","Errors.BadRequestError","Errors.AuthenticationError","Errors.InternalServerError","Errors.PermissionDeniedError","Errors.UnprocessableEntityError","Uploads.toFile","generationConfigToVertex","liveConnectConfigToMldev","t.tLiveSpeechConfig","sessionResumptionConfigToMldev","t.tBlobs","t.tAudioBlob","t.tImageBlob","t.tModelsUrl","t.tExtractModels","handleWebSocketMessage","types.LiveMusicServerMessage","mapToHeaders","headersToMap","converters.liveMusicSetWeightedPromptsParametersToMldev","converters.liveMusicSetConfigParametersToMldev","types.LiveMusicPlaybackControl","types.LiveServerMessage","converters.liveServerMessageFromVertex","types.Modality","converters.liveConnectParametersToVertex","converters.liveConnectParametersToMldev","converters.liveSendRealtimeInputParametersToVertex","converters.liveSendRealtimeInputParametersToMldev","afc.hasCallableTools","afc.shouldDisableAfc","afc.findAfcIncompatibleToolIndexes","afc.DEFAULT_MAX_REMOTE_CALLS","afc.isCallableTool","afc.shouldAppendAfcHistory","mcp.hasMcpToolUsage","mcp.setMcpUsageHeader","types.GenerateContentResponse","converters.generateContentParametersToVertex","converters.generateContentResponseFromVertex","converters.generateContentParametersToMldev","converters.generateContentResponseFromMldev","converters.embedContentParametersToVertex","converters.embedContentResponseFromVertex","types.EmbedContentResponse","converters.embedContentParametersToMldev","converters.embedContentResponseFromMldev","converters.generateImagesParametersToVertex","converters.generateImagesResponseFromVertex","types.GenerateImagesResponse","converters.generateImagesParametersToMldev","converters.generateImagesResponseFromMldev","converters.editImageParametersInternalToVertex","converters.editImageResponseFromVertex","types.EditImageResponse","converters.upscaleImageAPIParametersInternalToVertex","converters.upscaleImageResponseFromVertex","types.UpscaleImageResponse","converters.recontextImageParametersToVertex","converters.recontextImageResponseFromVertex","types.RecontextImageResponse","converters.segmentImageParametersToVertex","converters.segmentImageResponseFromVertex","types.SegmentImageResponse","converters.getModelParametersToVertex","converters.modelFromVertex","converters.getModelParametersToMldev","converters.modelFromMldev","converters.listModelsParametersToVertex","converters.listModelsResponseFromVertex","types.ListModelsResponse","converters.listModelsParametersToMldev","converters.listModelsResponseFromMldev","converters.updateModelParametersToVertex","converters.updateModelParametersToMldev","converters.deleteModelParametersToVertex","converters.deleteModelResponseFromVertex","types.DeleteModelResponse","converters.deleteModelParametersToMldev","converters.deleteModelResponseFromMldev","converters.countTokensParametersToVertex","converters.countTokensResponseFromVertex","types.CountTokensResponse","converters.countTokensParametersToMldev","converters.countTokensResponseFromMldev","converters.computeTokensParametersToVertex","converters.computeTokensResponseFromVertex","types.ComputeTokensResponse","converters.generateVideosParametersToVertex","converters.generateVideosOperationFromVertex","types.GenerateVideosOperation","converters.generateVideosParametersToMldev","converters.generateVideosOperationFromMldev","converters.getOperationParametersToVertex","converters.getOperationParametersToMldev","converters.fetchPredictOperationParametersToVertex","converters.createAuthTokenParametersToMldev","t.tTuningJobStatus","types.JobState","converters.getTuningJobParametersToVertex","converters.tuningJobFromVertex","converters.getTuningJobParametersToMldev","converters.tuningJobFromMldev","converters.listTuningJobsParametersToVertex","converters.listTuningJobsResponseFromVertex","types.ListTuningJobsResponse","converters.listTuningJobsParametersToMldev","converters.listTuningJobsResponseFromMldev","converters.cancelTuningJobParametersToVertex","converters.cancelTuningJobResponseFromVertex","types.CancelTuningJobResponse","converters.cancelTuningJobParametersToMldev","converters.cancelTuningJobResponseFromMldev","converters.createTuningJobParametersPrivateToVertex","converters.createTuningJobParametersPrivateToMldev","converters.tuningOperationFromMldev","GeminiNextGenAPI"],"mappings":"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"} \ No newline at end of file diff --git a/server/node_modules/@google/genai/dist/node/index.cjs b/server/node_modules/@google/genai/dist/node/index.cjs new file mode 100644 index 0000000..7555182 --- /dev/null +++ b/server/node_modules/@google/genai/dist/node/index.cjs @@ -0,0 +1,20083 @@ +'use strict'; + +var pRetry = require('p-retry'); +var googleAuthLibrary = require('google-auth-library'); +var fs = require('fs'); +var fs$1 = require('fs/promises'); +var node_stream = require('node:stream'); +var promises = require('node:stream/promises'); +var NodeWs = require('ws'); +var path$1 = require('path'); + +function _interopNamespaceDefault(e) { + var n = Object.create(null); + if (e) { + Object.keys(e).forEach(function (k) { + if (k !== 'default') { + var d = Object.getOwnPropertyDescriptor(e, k); + Object.defineProperty(n, k, d.get ? d : { + enumerable: true, + get: function () { return e[k]; } + }); + } + }); + } + n.default = e; + return Object.freeze(n); +} + +var fs__namespace = /*#__PURE__*/_interopNamespaceDefault(fs$1); +var NodeWs__namespace = /*#__PURE__*/_interopNamespaceDefault(NodeWs); +var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path$1); + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +let _defaultBaseGeminiUrl = undefined; +let _defaultBaseVertexUrl = undefined; +/** + * Overrides the base URLs for the Gemini API and Vertex AI API. + * + * @remarks This function should be called before initializing the SDK. If the + * base URLs are set after initializing the SDK, the base URLs will not be + * updated. Base URLs provided in the HttpOptions will also take precedence over + * URLs set here. + * + * @example + * ```ts + * import {GoogleGenAI, setDefaultBaseUrls} from '@google/genai'; + * // Override the base URL for the Gemini API. + * setDefaultBaseUrls({geminiUrl:'https://gemini.google.com'}); + * + * // Override the base URL for the Vertex AI API. + * setDefaultBaseUrls({vertexUrl: 'https://vertexai.googleapis.com'}); + * + * const ai = new GoogleGenAI({apiKey: 'GEMINI_API_KEY'}); + * ``` + */ +function setDefaultBaseUrls(baseUrlParams) { + _defaultBaseGeminiUrl = baseUrlParams.geminiUrl; + _defaultBaseVertexUrl = baseUrlParams.vertexUrl; +} +/** + * Returns the default base URLs for the Gemini API and Vertex AI API. + */ +function getDefaultBaseUrls() { + return { + geminiUrl: _defaultBaseGeminiUrl, + vertexUrl: _defaultBaseVertexUrl, + }; +} +/** + * Returns the default base URL based on the following priority: + * 1. Base URLs set via HttpOptions. + * 2. Base URLs set via the latest call to setDefaultBaseUrls. + * 3. Base URLs set via environment variables. + */ +function getBaseUrl(httpOptions, vertexai, vertexBaseUrlFromEnv, geminiBaseUrlFromEnv) { + var _a, _b; + if (!(httpOptions === null || httpOptions === void 0 ? void 0 : httpOptions.baseUrl)) { + const defaultBaseUrls = getDefaultBaseUrls(); + if (vertexai) { + return (_a = defaultBaseUrls.vertexUrl) !== null && _a !== void 0 ? _a : vertexBaseUrlFromEnv; + } + else { + return (_b = defaultBaseUrls.geminiUrl) !== null && _b !== void 0 ? _b : geminiBaseUrlFromEnv; + } + } + return httpOptions.baseUrl; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class BaseModule { +} +function formatMap(templateString, valueMap) { + // Use a regular expression to find all placeholders in the template string + const regex = /\{([^}]+)\}/g; + // Replace each placeholder with its corresponding value from the valueMap + return templateString.replace(regex, (match, key) => { + if (Object.prototype.hasOwnProperty.call(valueMap, key)) { + const value = valueMap[key]; + // Convert the value to a string if it's not a string already + return value !== undefined && value !== null ? String(value) : ''; + } + else { + // Handle missing keys + throw new Error(`Key '${key}' not found in valueMap.`); + } + }); +} +function setValueByPath(data, keys, value) { + for (let i = 0; i < keys.length - 1; i++) { + const key = keys[i]; + if (key.endsWith('[]')) { + const keyName = key.slice(0, -2); + if (!(keyName in data)) { + if (Array.isArray(value)) { + data[keyName] = Array.from({ length: value.length }, () => ({})); + } + else { + throw new Error(`Value must be a list given an array path ${key}`); + } + } + if (Array.isArray(data[keyName])) { + const arrayData = data[keyName]; + if (Array.isArray(value)) { + for (let j = 0; j < arrayData.length; j++) { + const entry = arrayData[j]; + setValueByPath(entry, keys.slice(i + 1), value[j]); + } + } + else { + for (const d of arrayData) { + setValueByPath(d, keys.slice(i + 1), value); + } + } + } + return; + } + else if (key.endsWith('[0]')) { + const keyName = key.slice(0, -3); + if (!(keyName in data)) { + data[keyName] = [{}]; + } + const arrayData = data[keyName]; + setValueByPath(arrayData[0], keys.slice(i + 1), value); + return; + } + if (!data[key] || typeof data[key] !== 'object') { + data[key] = {}; + } + data = data[key]; + } + const keyToSet = keys[keys.length - 1]; + const existingData = data[keyToSet]; + if (existingData !== undefined) { + if (!value || + (typeof value === 'object' && Object.keys(value).length === 0)) { + return; + } + if (value === existingData) { + return; + } + if (typeof existingData === 'object' && + typeof value === 'object' && + existingData !== null && + value !== null) { + Object.assign(existingData, value); + } + else { + throw new Error(`Cannot set value for an existing key. Key: ${keyToSet}`); + } + } + else { + if (keyToSet === '_self' && + typeof value === 'object' && + value !== null && + !Array.isArray(value)) { + const valueAsRecord = value; + Object.assign(data, valueAsRecord); + } + else { + data[keyToSet] = value; + } + } +} +function getValueByPath(data, keys, defaultValue = undefined) { + try { + if (keys.length === 1 && keys[0] === '_self') { + return data; + } + for (let i = 0; i < keys.length; i++) { + if (typeof data !== 'object' || data === null) { + return defaultValue; + } + const key = keys[i]; + if (key.endsWith('[]')) { + const keyName = key.slice(0, -2); + if (keyName in data) { + const arrayData = data[keyName]; + if (!Array.isArray(arrayData)) { + return defaultValue; + } + return arrayData.map((d) => getValueByPath(d, keys.slice(i + 1), defaultValue)); + } + else { + return defaultValue; + } + } + else { + data = data[key]; + } + } + return data; + } + catch (error) { + if (error instanceof TypeError) { + return defaultValue; + } + throw error; + } +} +/** + * Moves values from source paths to destination paths. + * + * Examples: + * moveValueByPath( + * {'requests': [{'content': v1}, {'content': v2}]}, + * {'requests[].*': 'requests[].request.*'} + * ) + * -> {'requests': [{'request': {'content': v1}}, {'request': {'content': v2}}]} + */ +function moveValueByPath(data, paths) { + for (const [sourcePath, destPath] of Object.entries(paths)) { + const sourceKeys = sourcePath.split('.'); + const destKeys = destPath.split('.'); + // Determine keys to exclude from wildcard to avoid cyclic references + const excludeKeys = new Set(); + let wildcardIdx = -1; + for (let i = 0; i < sourceKeys.length; i++) { + if (sourceKeys[i] === '*') { + wildcardIdx = i; + break; + } + } + if (wildcardIdx !== -1 && destKeys.length > wildcardIdx) { + // Extract the intermediate key between source and dest paths + // Example: source=['requests[]', '*'], dest=['requests[]', 'request', '*'] + // We want to exclude 'request' + for (let i = wildcardIdx; i < destKeys.length; i++) { + const key = destKeys[i]; + if (key !== '*' && !key.endsWith('[]') && !key.endsWith('[0]')) { + excludeKeys.add(key); + } + } + } + _moveValueRecursive(data, sourceKeys, destKeys, 0, excludeKeys); + } +} +/** + * Recursively moves values from source path to destination path. + */ +function _moveValueRecursive(data, sourceKeys, destKeys, keyIdx, excludeKeys) { + if (keyIdx >= sourceKeys.length) { + return; + } + if (typeof data !== 'object' || data === null) { + return; + } + const key = sourceKeys[keyIdx]; + if (key.endsWith('[]')) { + const keyName = key.slice(0, -2); + const dataRecord = data; + if (keyName in dataRecord && Array.isArray(dataRecord[keyName])) { + for (const item of dataRecord[keyName]) { + _moveValueRecursive(item, sourceKeys, destKeys, keyIdx + 1, excludeKeys); + } + } + } + else if (key === '*') { + // wildcard - move all fields + if (typeof data === 'object' && data !== null && !Array.isArray(data)) { + const dataRecord = data; + const keysToMove = Object.keys(dataRecord).filter((k) => !k.startsWith('_') && !excludeKeys.has(k)); + const valuesToMove = {}; + for (const k of keysToMove) { + valuesToMove[k] = dataRecord[k]; + } + // Set values at destination + for (const [k, v] of Object.entries(valuesToMove)) { + const newDestKeys = []; + for (const dk of destKeys.slice(keyIdx)) { + if (dk === '*') { + newDestKeys.push(k); + } + else { + newDestKeys.push(dk); + } + } + setValueByPath(dataRecord, newDestKeys, v); + } + for (const k of keysToMove) { + delete dataRecord[k]; + } + } + } + else { + // Navigate to next level + const dataRecord = data; + if (key in dataRecord) { + _moveValueRecursive(dataRecord[key], sourceKeys, destKeys, keyIdx + 1, excludeKeys); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function tBytes$1(fromBytes) { + if (typeof fromBytes !== 'string') { + throw new Error('fromImageBytes must be a string'); + } + // TODO(b/389133914): Remove dummy bytes converter. + return fromBytes; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Code generated by the Google Gen AI SDK generator DO NOT EDIT. +function fetchPredictOperationParametersToVertex(fromObject) { + const toObject = {}; + const fromOperationName = getValueByPath(fromObject, [ + 'operationName', + ]); + if (fromOperationName != null) { + setValueByPath(toObject, ['operationName'], fromOperationName); + } + const fromResourceName = getValueByPath(fromObject, ['resourceName']); + if (fromResourceName != null) { + setValueByPath(toObject, ['_url', 'resourceName'], fromResourceName); + } + return toObject; +} +function generateVideosOperationFromMldev$1(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromResponse = getValueByPath(fromObject, [ + 'response', + 'generateVideoResponse', + ]); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], generateVideosResponseFromMldev$1(fromResponse)); + } + return toObject; +} +function generateVideosOperationFromVertex$1(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], generateVideosResponseFromVertex$1(fromResponse)); + } + return toObject; +} +function generateVideosResponseFromMldev$1(fromObject) { + const toObject = {}; + const fromGeneratedVideos = getValueByPath(fromObject, [ + 'generatedSamples', + ]); + if (fromGeneratedVideos != null) { + let transformedList = fromGeneratedVideos; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedVideoFromMldev$1(item); + }); + } + setValueByPath(toObject, ['generatedVideos'], transformedList); + } + const fromRaiMediaFilteredCount = getValueByPath(fromObject, [ + 'raiMediaFilteredCount', + ]); + if (fromRaiMediaFilteredCount != null) { + setValueByPath(toObject, ['raiMediaFilteredCount'], fromRaiMediaFilteredCount); + } + const fromRaiMediaFilteredReasons = getValueByPath(fromObject, [ + 'raiMediaFilteredReasons', + ]); + if (fromRaiMediaFilteredReasons != null) { + setValueByPath(toObject, ['raiMediaFilteredReasons'], fromRaiMediaFilteredReasons); + } + return toObject; +} +function generateVideosResponseFromVertex$1(fromObject) { + const toObject = {}; + const fromGeneratedVideos = getValueByPath(fromObject, ['videos']); + if (fromGeneratedVideos != null) { + let transformedList = fromGeneratedVideos; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedVideoFromVertex$1(item); + }); + } + setValueByPath(toObject, ['generatedVideos'], transformedList); + } + const fromRaiMediaFilteredCount = getValueByPath(fromObject, [ + 'raiMediaFilteredCount', + ]); + if (fromRaiMediaFilteredCount != null) { + setValueByPath(toObject, ['raiMediaFilteredCount'], fromRaiMediaFilteredCount); + } + const fromRaiMediaFilteredReasons = getValueByPath(fromObject, [ + 'raiMediaFilteredReasons', + ]); + if (fromRaiMediaFilteredReasons != null) { + setValueByPath(toObject, ['raiMediaFilteredReasons'], fromRaiMediaFilteredReasons); + } + return toObject; +} +function generatedVideoFromMldev$1(fromObject) { + const toObject = {}; + const fromVideo = getValueByPath(fromObject, ['video']); + if (fromVideo != null) { + setValueByPath(toObject, ['video'], videoFromMldev$1(fromVideo)); + } + return toObject; +} +function generatedVideoFromVertex$1(fromObject) { + const toObject = {}; + const fromVideo = getValueByPath(fromObject, ['_self']); + if (fromVideo != null) { + setValueByPath(toObject, ['video'], videoFromVertex$1(fromVideo)); + } + return toObject; +} +function getOperationParametersToMldev(fromObject) { + const toObject = {}; + const fromOperationName = getValueByPath(fromObject, [ + 'operationName', + ]); + if (fromOperationName != null) { + setValueByPath(toObject, ['_url', 'operationName'], fromOperationName); + } + return toObject; +} +function getOperationParametersToVertex(fromObject) { + const toObject = {}; + const fromOperationName = getValueByPath(fromObject, [ + 'operationName', + ]); + if (fromOperationName != null) { + setValueByPath(toObject, ['_url', 'operationName'], fromOperationName); + } + return toObject; +} +function importFileOperationFromMldev$1(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], importFileResponseFromMldev$1(fromResponse)); + } + return toObject; +} +function importFileResponseFromMldev$1(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromParent = getValueByPath(fromObject, ['parent']); + if (fromParent != null) { + setValueByPath(toObject, ['parent'], fromParent); + } + const fromDocumentName = getValueByPath(fromObject, ['documentName']); + if (fromDocumentName != null) { + setValueByPath(toObject, ['documentName'], fromDocumentName); + } + return toObject; +} +function uploadToFileSearchStoreOperationFromMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], uploadToFileSearchStoreResponseFromMldev(fromResponse)); + } + return toObject; +} +function uploadToFileSearchStoreResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromParent = getValueByPath(fromObject, ['parent']); + if (fromParent != null) { + setValueByPath(toObject, ['parent'], fromParent); + } + const fromDocumentName = getValueByPath(fromObject, ['documentName']); + if (fromDocumentName != null) { + setValueByPath(toObject, ['documentName'], fromDocumentName); + } + return toObject; +} +function videoFromMldev$1(fromObject) { + const toObject = {}; + const fromUri = getValueByPath(fromObject, ['uri']); + if (fromUri != null) { + setValueByPath(toObject, ['uri'], fromUri); + } + const fromVideoBytes = getValueByPath(fromObject, ['encodedVideo']); + if (fromVideoBytes != null) { + setValueByPath(toObject, ['videoBytes'], tBytes$1(fromVideoBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['encoding']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function videoFromVertex$1(fromObject) { + const toObject = {}; + const fromUri = getValueByPath(fromObject, ['gcsUri']); + if (fromUri != null) { + setValueByPath(toObject, ['uri'], fromUri); + } + const fromVideoBytes = getValueByPath(fromObject, [ + 'bytesBase64Encoded', + ]); + if (fromVideoBytes != null) { + setValueByPath(toObject, ['videoBytes'], tBytes$1(fromVideoBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** Outcome of the code execution. */ +exports.Outcome = void 0; +(function (Outcome) { + /** + * Unspecified status. This value should not be used. + */ + Outcome["OUTCOME_UNSPECIFIED"] = "OUTCOME_UNSPECIFIED"; + /** + * Code execution completed successfully. + */ + Outcome["OUTCOME_OK"] = "OUTCOME_OK"; + /** + * Code execution finished but with a failure. `stderr` should contain the reason. + */ + Outcome["OUTCOME_FAILED"] = "OUTCOME_FAILED"; + /** + * Code execution ran for too long, and was cancelled. There may or may not be a partial output present. + */ + Outcome["OUTCOME_DEADLINE_EXCEEDED"] = "OUTCOME_DEADLINE_EXCEEDED"; +})(exports.Outcome || (exports.Outcome = {})); +/** Programming language of the `code`. */ +exports.Language = void 0; +(function (Language) { + /** + * Unspecified language. This value should not be used. + */ + Language["LANGUAGE_UNSPECIFIED"] = "LANGUAGE_UNSPECIFIED"; + /** + * Python >= 3.10, with numpy and simpy available. + */ + Language["PYTHON"] = "PYTHON"; +})(exports.Language || (exports.Language = {})); +/** Specifies how the response should be scheduled in the conversation. */ +exports.FunctionResponseScheduling = void 0; +(function (FunctionResponseScheduling) { + /** + * This value is unused. + */ + FunctionResponseScheduling["SCHEDULING_UNSPECIFIED"] = "SCHEDULING_UNSPECIFIED"; + /** + * Only add the result to the conversation context, do not interrupt or trigger generation. + */ + FunctionResponseScheduling["SILENT"] = "SILENT"; + /** + * Add the result to the conversation context, and prompt to generate output without interrupting ongoing generation. + */ + FunctionResponseScheduling["WHEN_IDLE"] = "WHEN_IDLE"; + /** + * Add the result to the conversation context, interrupt ongoing generation and prompt to generate output. + */ + FunctionResponseScheduling["INTERRUPT"] = "INTERRUPT"; +})(exports.FunctionResponseScheduling || (exports.FunctionResponseScheduling = {})); +/** The type of the data. */ +exports.Type = void 0; +(function (Type) { + /** + * Not specified, should not be used. + */ + Type["TYPE_UNSPECIFIED"] = "TYPE_UNSPECIFIED"; + /** + * OpenAPI string type + */ + Type["STRING"] = "STRING"; + /** + * OpenAPI number type + */ + Type["NUMBER"] = "NUMBER"; + /** + * OpenAPI integer type + */ + Type["INTEGER"] = "INTEGER"; + /** + * OpenAPI boolean type + */ + Type["BOOLEAN"] = "BOOLEAN"; + /** + * OpenAPI array type + */ + Type["ARRAY"] = "ARRAY"; + /** + * OpenAPI object type + */ + Type["OBJECT"] = "OBJECT"; + /** + * Null type + */ + Type["NULL"] = "NULL"; +})(exports.Type || (exports.Type = {})); +/** The API spec that the external API implements. This enum is not supported in Gemini API. */ +exports.ApiSpec = void 0; +(function (ApiSpec) { + /** + * Unspecified API spec. This value should not be used. + */ + ApiSpec["API_SPEC_UNSPECIFIED"] = "API_SPEC_UNSPECIFIED"; + /** + * Simple search API spec. + */ + ApiSpec["SIMPLE_SEARCH"] = "SIMPLE_SEARCH"; + /** + * Elastic search API spec. + */ + ApiSpec["ELASTIC_SEARCH"] = "ELASTIC_SEARCH"; +})(exports.ApiSpec || (exports.ApiSpec = {})); +/** Type of auth scheme. This enum is not supported in Gemini API. */ +exports.AuthType = void 0; +(function (AuthType) { + AuthType["AUTH_TYPE_UNSPECIFIED"] = "AUTH_TYPE_UNSPECIFIED"; + /** + * No Auth. + */ + AuthType["NO_AUTH"] = "NO_AUTH"; + /** + * API Key Auth. + */ + AuthType["API_KEY_AUTH"] = "API_KEY_AUTH"; + /** + * HTTP Basic Auth. + */ + AuthType["HTTP_BASIC_AUTH"] = "HTTP_BASIC_AUTH"; + /** + * Google Service Account Auth. + */ + AuthType["GOOGLE_SERVICE_ACCOUNT_AUTH"] = "GOOGLE_SERVICE_ACCOUNT_AUTH"; + /** + * OAuth auth. + */ + AuthType["OAUTH"] = "OAUTH"; + /** + * OpenID Connect (OIDC) Auth. + */ + AuthType["OIDC_AUTH"] = "OIDC_AUTH"; +})(exports.AuthType || (exports.AuthType = {})); +/** The location of the API key. This enum is not supported in Gemini API. */ +exports.HttpElementLocation = void 0; +(function (HttpElementLocation) { + HttpElementLocation["HTTP_IN_UNSPECIFIED"] = "HTTP_IN_UNSPECIFIED"; + /** + * Element is in the HTTP request query. + */ + HttpElementLocation["HTTP_IN_QUERY"] = "HTTP_IN_QUERY"; + /** + * Element is in the HTTP request header. + */ + HttpElementLocation["HTTP_IN_HEADER"] = "HTTP_IN_HEADER"; + /** + * Element is in the HTTP request path. + */ + HttpElementLocation["HTTP_IN_PATH"] = "HTTP_IN_PATH"; + /** + * Element is in the HTTP request body. + */ + HttpElementLocation["HTTP_IN_BODY"] = "HTTP_IN_BODY"; + /** + * Element is in the HTTP request cookie. + */ + HttpElementLocation["HTTP_IN_COOKIE"] = "HTTP_IN_COOKIE"; +})(exports.HttpElementLocation || (exports.HttpElementLocation = {})); +/** Sites with confidence level chosen & above this value will be blocked from the search results. This enum is not supported in Gemini API. */ +exports.PhishBlockThreshold = void 0; +(function (PhishBlockThreshold) { + /** + * Defaults to unspecified. + */ + PhishBlockThreshold["PHISH_BLOCK_THRESHOLD_UNSPECIFIED"] = "PHISH_BLOCK_THRESHOLD_UNSPECIFIED"; + /** + * Blocks Low and above confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_LOW_AND_ABOVE"] = "BLOCK_LOW_AND_ABOVE"; + /** + * Blocks Medium and above confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_MEDIUM_AND_ABOVE"] = "BLOCK_MEDIUM_AND_ABOVE"; + /** + * Blocks High and above confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_HIGH_AND_ABOVE"] = "BLOCK_HIGH_AND_ABOVE"; + /** + * Blocks Higher and above confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_HIGHER_AND_ABOVE"] = "BLOCK_HIGHER_AND_ABOVE"; + /** + * Blocks Very high and above confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_VERY_HIGH_AND_ABOVE"] = "BLOCK_VERY_HIGH_AND_ABOVE"; + /** + * Blocks Extremely high confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_ONLY_EXTREMELY_HIGH"] = "BLOCK_ONLY_EXTREMELY_HIGH"; +})(exports.PhishBlockThreshold || (exports.PhishBlockThreshold = {})); +/** Specifies the function Behavior. Currently only supported by the BidiGenerateContent method. This enum is not supported in Vertex AI. */ +exports.Behavior = void 0; +(function (Behavior) { + /** + * This value is unused. + */ + Behavior["UNSPECIFIED"] = "UNSPECIFIED"; + /** + * If set, the system will wait to receive the function response before continuing the conversation. + */ + Behavior["BLOCKING"] = "BLOCKING"; + /** + * If set, the system will not wait to receive the function response. Instead, it will attempt to handle function responses as they become available while maintaining the conversation between the user and the model. + */ + Behavior["NON_BLOCKING"] = "NON_BLOCKING"; +})(exports.Behavior || (exports.Behavior = {})); +/** The mode of the predictor to be used in dynamic retrieval. */ +exports.DynamicRetrievalConfigMode = void 0; +(function (DynamicRetrievalConfigMode) { + /** + * Always trigger retrieval. + */ + DynamicRetrievalConfigMode["MODE_UNSPECIFIED"] = "MODE_UNSPECIFIED"; + /** + * Run retrieval only when system decides it is necessary. + */ + DynamicRetrievalConfigMode["MODE_DYNAMIC"] = "MODE_DYNAMIC"; +})(exports.DynamicRetrievalConfigMode || (exports.DynamicRetrievalConfigMode = {})); +/** Function calling mode. */ +exports.FunctionCallingConfigMode = void 0; +(function (FunctionCallingConfigMode) { + /** + * Unspecified function calling mode. This value should not be used. + */ + FunctionCallingConfigMode["MODE_UNSPECIFIED"] = "MODE_UNSPECIFIED"; + /** + * Default model behavior, model decides to predict either function calls or natural language response. + */ + FunctionCallingConfigMode["AUTO"] = "AUTO"; + /** + * Model is constrained to always predicting function calls only. If "allowed_function_names" are set, the predicted function calls will be limited to any one of "allowed_function_names", else the predicted function calls will be any one of the provided "function_declarations". + */ + FunctionCallingConfigMode["ANY"] = "ANY"; + /** + * Model will not predict any function calls. Model behavior is same as when not passing any function declarations. + */ + FunctionCallingConfigMode["NONE"] = "NONE"; + /** + * Model is constrained to predict either function calls or natural language response. If "allowed_function_names" are set, the predicted function calls will be limited to any one of "allowed_function_names", else the predicted function calls will be any one of the provided "function_declarations". + */ + FunctionCallingConfigMode["VALIDATED"] = "VALIDATED"; +})(exports.FunctionCallingConfigMode || (exports.FunctionCallingConfigMode = {})); +/** The number of thoughts tokens that the model should generate. */ +exports.ThinkingLevel = void 0; +(function (ThinkingLevel) { + /** + * Unspecified thinking level. + */ + ThinkingLevel["THINKING_LEVEL_UNSPECIFIED"] = "THINKING_LEVEL_UNSPECIFIED"; + /** + * Low thinking level. + */ + ThinkingLevel["LOW"] = "LOW"; + /** + * Medium thinking level. + */ + ThinkingLevel["MEDIUM"] = "MEDIUM"; + /** + * High thinking level. + */ + ThinkingLevel["HIGH"] = "HIGH"; + /** + * MINIMAL thinking level. + */ + ThinkingLevel["MINIMAL"] = "MINIMAL"; +})(exports.ThinkingLevel || (exports.ThinkingLevel = {})); +/** Harm category. */ +exports.HarmCategory = void 0; +(function (HarmCategory) { + /** + * The harm category is unspecified. + */ + HarmCategory["HARM_CATEGORY_UNSPECIFIED"] = "HARM_CATEGORY_UNSPECIFIED"; + /** + * The harm category is harassment. + */ + HarmCategory["HARM_CATEGORY_HARASSMENT"] = "HARM_CATEGORY_HARASSMENT"; + /** + * The harm category is hate speech. + */ + HarmCategory["HARM_CATEGORY_HATE_SPEECH"] = "HARM_CATEGORY_HATE_SPEECH"; + /** + * The harm category is sexually explicit content. + */ + HarmCategory["HARM_CATEGORY_SEXUALLY_EXPLICIT"] = "HARM_CATEGORY_SEXUALLY_EXPLICIT"; + /** + * The harm category is dangerous content. + */ + HarmCategory["HARM_CATEGORY_DANGEROUS_CONTENT"] = "HARM_CATEGORY_DANGEROUS_CONTENT"; + /** + * Deprecated: Election filter is not longer supported. The harm category is civic integrity. + */ + HarmCategory["HARM_CATEGORY_CIVIC_INTEGRITY"] = "HARM_CATEGORY_CIVIC_INTEGRITY"; + /** + * The harm category is image hate. This enum value is not supported in Gemini API. + */ + HarmCategory["HARM_CATEGORY_IMAGE_HATE"] = "HARM_CATEGORY_IMAGE_HATE"; + /** + * The harm category is image dangerous content. This enum value is not supported in Gemini API. + */ + HarmCategory["HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT"] = "HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT"; + /** + * The harm category is image harassment. This enum value is not supported in Gemini API. + */ + HarmCategory["HARM_CATEGORY_IMAGE_HARASSMENT"] = "HARM_CATEGORY_IMAGE_HARASSMENT"; + /** + * The harm category is image sexually explicit content. This enum value is not supported in Gemini API. + */ + HarmCategory["HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT"] = "HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT"; + /** + * The harm category is for jailbreak prompts. This enum value is not supported in Gemini API. + */ + HarmCategory["HARM_CATEGORY_JAILBREAK"] = "HARM_CATEGORY_JAILBREAK"; +})(exports.HarmCategory || (exports.HarmCategory = {})); +/** Specify if the threshold is used for probability or severity score. If not specified, the threshold is used for probability score. This enum is not supported in Gemini API. */ +exports.HarmBlockMethod = void 0; +(function (HarmBlockMethod) { + /** + * The harm block method is unspecified. + */ + HarmBlockMethod["HARM_BLOCK_METHOD_UNSPECIFIED"] = "HARM_BLOCK_METHOD_UNSPECIFIED"; + /** + * The harm block method uses both probability and severity scores. + */ + HarmBlockMethod["SEVERITY"] = "SEVERITY"; + /** + * The harm block method uses the probability score. + */ + HarmBlockMethod["PROBABILITY"] = "PROBABILITY"; +})(exports.HarmBlockMethod || (exports.HarmBlockMethod = {})); +/** The harm block threshold. */ +exports.HarmBlockThreshold = void 0; +(function (HarmBlockThreshold) { + /** + * Unspecified harm block threshold. + */ + HarmBlockThreshold["HARM_BLOCK_THRESHOLD_UNSPECIFIED"] = "HARM_BLOCK_THRESHOLD_UNSPECIFIED"; + /** + * Block low threshold and above (i.e. block more). + */ + HarmBlockThreshold["BLOCK_LOW_AND_ABOVE"] = "BLOCK_LOW_AND_ABOVE"; + /** + * Block medium threshold and above. + */ + HarmBlockThreshold["BLOCK_MEDIUM_AND_ABOVE"] = "BLOCK_MEDIUM_AND_ABOVE"; + /** + * Block only high threshold (i.e. block less). + */ + HarmBlockThreshold["BLOCK_ONLY_HIGH"] = "BLOCK_ONLY_HIGH"; + /** + * Block none. + */ + HarmBlockThreshold["BLOCK_NONE"] = "BLOCK_NONE"; + /** + * Turn off the safety filter. + */ + HarmBlockThreshold["OFF"] = "OFF"; +})(exports.HarmBlockThreshold || (exports.HarmBlockThreshold = {})); +/** Output only. The reason why the model stopped generating tokens. + +If empty, the model has not stopped generating the tokens. */ +exports.FinishReason = void 0; +(function (FinishReason) { + /** + * The finish reason is unspecified. + */ + FinishReason["FINISH_REASON_UNSPECIFIED"] = "FINISH_REASON_UNSPECIFIED"; + /** + * Token generation reached a natural stopping point or a configured stop sequence. + */ + FinishReason["STOP"] = "STOP"; + /** + * Token generation reached the configured maximum output tokens. + */ + FinishReason["MAX_TOKENS"] = "MAX_TOKENS"; + /** + * Token generation stopped because the content potentially contains safety violations. NOTE: When streaming, [content][] is empty if content filters blocks the output. + */ + FinishReason["SAFETY"] = "SAFETY"; + /** + * The token generation stopped because of potential recitation. + */ + FinishReason["RECITATION"] = "RECITATION"; + /** + * The token generation stopped because of using an unsupported language. + */ + FinishReason["LANGUAGE"] = "LANGUAGE"; + /** + * All other reasons that stopped the token generation. + */ + FinishReason["OTHER"] = "OTHER"; + /** + * Token generation stopped because the content contains forbidden terms. + */ + FinishReason["BLOCKLIST"] = "BLOCKLIST"; + /** + * Token generation stopped for potentially containing prohibited content. + */ + FinishReason["PROHIBITED_CONTENT"] = "PROHIBITED_CONTENT"; + /** + * Token generation stopped because the content potentially contains Sensitive Personally Identifiable Information (SPII). + */ + FinishReason["SPII"] = "SPII"; + /** + * The function call generated by the model is invalid. + */ + FinishReason["MALFORMED_FUNCTION_CALL"] = "MALFORMED_FUNCTION_CALL"; + /** + * Token generation stopped because generated images have safety violations. + */ + FinishReason["IMAGE_SAFETY"] = "IMAGE_SAFETY"; + /** + * The tool call generated by the model is invalid. + */ + FinishReason["UNEXPECTED_TOOL_CALL"] = "UNEXPECTED_TOOL_CALL"; + /** + * Image generation stopped because the generated images have prohibited content. + */ + FinishReason["IMAGE_PROHIBITED_CONTENT"] = "IMAGE_PROHIBITED_CONTENT"; + /** + * The model was expected to generate an image, but none was generated. + */ + FinishReason["NO_IMAGE"] = "NO_IMAGE"; + /** + * Image generation stopped because the generated image may be a recitation from a source. + */ + FinishReason["IMAGE_RECITATION"] = "IMAGE_RECITATION"; + /** + * Image generation stopped for a reason not otherwise specified. + */ + FinishReason["IMAGE_OTHER"] = "IMAGE_OTHER"; +})(exports.FinishReason || (exports.FinishReason = {})); +/** Output only. Harm probability levels in the content. */ +exports.HarmProbability = void 0; +(function (HarmProbability) { + /** + * Harm probability unspecified. + */ + HarmProbability["HARM_PROBABILITY_UNSPECIFIED"] = "HARM_PROBABILITY_UNSPECIFIED"; + /** + * Negligible level of harm. + */ + HarmProbability["NEGLIGIBLE"] = "NEGLIGIBLE"; + /** + * Low level of harm. + */ + HarmProbability["LOW"] = "LOW"; + /** + * Medium level of harm. + */ + HarmProbability["MEDIUM"] = "MEDIUM"; + /** + * High level of harm. + */ + HarmProbability["HIGH"] = "HIGH"; +})(exports.HarmProbability || (exports.HarmProbability = {})); +/** Output only. Harm severity levels in the content. This enum is not supported in Gemini API. */ +exports.HarmSeverity = void 0; +(function (HarmSeverity) { + /** + * Harm severity unspecified. + */ + HarmSeverity["HARM_SEVERITY_UNSPECIFIED"] = "HARM_SEVERITY_UNSPECIFIED"; + /** + * Negligible level of harm severity. + */ + HarmSeverity["HARM_SEVERITY_NEGLIGIBLE"] = "HARM_SEVERITY_NEGLIGIBLE"; + /** + * Low level of harm severity. + */ + HarmSeverity["HARM_SEVERITY_LOW"] = "HARM_SEVERITY_LOW"; + /** + * Medium level of harm severity. + */ + HarmSeverity["HARM_SEVERITY_MEDIUM"] = "HARM_SEVERITY_MEDIUM"; + /** + * High level of harm severity. + */ + HarmSeverity["HARM_SEVERITY_HIGH"] = "HARM_SEVERITY_HIGH"; +})(exports.HarmSeverity || (exports.HarmSeverity = {})); +/** Status of the url retrieval. */ +exports.UrlRetrievalStatus = void 0; +(function (UrlRetrievalStatus) { + /** + * Default value. This value is unused. + */ + UrlRetrievalStatus["URL_RETRIEVAL_STATUS_UNSPECIFIED"] = "URL_RETRIEVAL_STATUS_UNSPECIFIED"; + /** + * Url retrieval is successful. + */ + UrlRetrievalStatus["URL_RETRIEVAL_STATUS_SUCCESS"] = "URL_RETRIEVAL_STATUS_SUCCESS"; + /** + * Url retrieval is failed due to error. + */ + UrlRetrievalStatus["URL_RETRIEVAL_STATUS_ERROR"] = "URL_RETRIEVAL_STATUS_ERROR"; + /** + * Url retrieval is failed because the content is behind paywall. This enum value is not supported in Vertex AI. + */ + UrlRetrievalStatus["URL_RETRIEVAL_STATUS_PAYWALL"] = "URL_RETRIEVAL_STATUS_PAYWALL"; + /** + * Url retrieval is failed because the content is unsafe. This enum value is not supported in Vertex AI. + */ + UrlRetrievalStatus["URL_RETRIEVAL_STATUS_UNSAFE"] = "URL_RETRIEVAL_STATUS_UNSAFE"; +})(exports.UrlRetrievalStatus || (exports.UrlRetrievalStatus = {})); +/** Output only. The reason why the prompt was blocked. */ +exports.BlockedReason = void 0; +(function (BlockedReason) { + /** + * The blocked reason is unspecified. + */ + BlockedReason["BLOCKED_REASON_UNSPECIFIED"] = "BLOCKED_REASON_UNSPECIFIED"; + /** + * The prompt was blocked for safety reasons. + */ + BlockedReason["SAFETY"] = "SAFETY"; + /** + * The prompt was blocked for other reasons. For example, it may be due to the prompt's language, or because it contains other harmful content. + */ + BlockedReason["OTHER"] = "OTHER"; + /** + * The prompt was blocked because it contains a term from the terminology blocklist. + */ + BlockedReason["BLOCKLIST"] = "BLOCKLIST"; + /** + * The prompt was blocked because it contains prohibited content. + */ + BlockedReason["PROHIBITED_CONTENT"] = "PROHIBITED_CONTENT"; + /** + * The prompt was blocked because it contains content that is unsafe for image generation. + */ + BlockedReason["IMAGE_SAFETY"] = "IMAGE_SAFETY"; + /** + * The prompt was blocked by Model Armor. This enum value is not supported in Gemini API. + */ + BlockedReason["MODEL_ARMOR"] = "MODEL_ARMOR"; + /** + * The prompt was blocked as a jailbreak attempt. This enum value is not supported in Gemini API. + */ + BlockedReason["JAILBREAK"] = "JAILBREAK"; +})(exports.BlockedReason || (exports.BlockedReason = {})); +/** Output only. The traffic type for this request. This enum is not supported in Gemini API. */ +exports.TrafficType = void 0; +(function (TrafficType) { + /** + * Unspecified request traffic type. + */ + TrafficType["TRAFFIC_TYPE_UNSPECIFIED"] = "TRAFFIC_TYPE_UNSPECIFIED"; + /** + * The request was processed using Pay-As-You-Go quota. + */ + TrafficType["ON_DEMAND"] = "ON_DEMAND"; + /** + * Type for Provisioned Throughput traffic. + */ + TrafficType["PROVISIONED_THROUGHPUT"] = "PROVISIONED_THROUGHPUT"; +})(exports.TrafficType || (exports.TrafficType = {})); +/** Server content modalities. */ +exports.Modality = void 0; +(function (Modality) { + /** + * The modality is unspecified. + */ + Modality["MODALITY_UNSPECIFIED"] = "MODALITY_UNSPECIFIED"; + /** + * Indicates the model should return text + */ + Modality["TEXT"] = "TEXT"; + /** + * Indicates the model should return images. + */ + Modality["IMAGE"] = "IMAGE"; + /** + * Indicates the model should return audio. + */ + Modality["AUDIO"] = "AUDIO"; +})(exports.Modality || (exports.Modality = {})); +/** The media resolution to use. */ +exports.MediaResolution = void 0; +(function (MediaResolution) { + /** + * Media resolution has not been set + */ + MediaResolution["MEDIA_RESOLUTION_UNSPECIFIED"] = "MEDIA_RESOLUTION_UNSPECIFIED"; + /** + * Media resolution set to low (64 tokens). + */ + MediaResolution["MEDIA_RESOLUTION_LOW"] = "MEDIA_RESOLUTION_LOW"; + /** + * Media resolution set to medium (256 tokens). + */ + MediaResolution["MEDIA_RESOLUTION_MEDIUM"] = "MEDIA_RESOLUTION_MEDIUM"; + /** + * Media resolution set to high (zoomed reframing with 256 tokens). + */ + MediaResolution["MEDIA_RESOLUTION_HIGH"] = "MEDIA_RESOLUTION_HIGH"; +})(exports.MediaResolution || (exports.MediaResolution = {})); +/** Tuning mode. This enum is not supported in Gemini API. */ +exports.TuningMode = void 0; +(function (TuningMode) { + /** + * Tuning mode is unspecified. + */ + TuningMode["TUNING_MODE_UNSPECIFIED"] = "TUNING_MODE_UNSPECIFIED"; + /** + * Full fine-tuning mode. + */ + TuningMode["TUNING_MODE_FULL"] = "TUNING_MODE_FULL"; + /** + * PEFT adapter tuning mode. + */ + TuningMode["TUNING_MODE_PEFT_ADAPTER"] = "TUNING_MODE_PEFT_ADAPTER"; +})(exports.TuningMode || (exports.TuningMode = {})); +/** Adapter size for tuning. This enum is not supported in Gemini API. */ +exports.AdapterSize = void 0; +(function (AdapterSize) { + /** + * Adapter size is unspecified. + */ + AdapterSize["ADAPTER_SIZE_UNSPECIFIED"] = "ADAPTER_SIZE_UNSPECIFIED"; + /** + * Adapter size 1. + */ + AdapterSize["ADAPTER_SIZE_ONE"] = "ADAPTER_SIZE_ONE"; + /** + * Adapter size 2. + */ + AdapterSize["ADAPTER_SIZE_TWO"] = "ADAPTER_SIZE_TWO"; + /** + * Adapter size 4. + */ + AdapterSize["ADAPTER_SIZE_FOUR"] = "ADAPTER_SIZE_FOUR"; + /** + * Adapter size 8. + */ + AdapterSize["ADAPTER_SIZE_EIGHT"] = "ADAPTER_SIZE_EIGHT"; + /** + * Adapter size 16. + */ + AdapterSize["ADAPTER_SIZE_SIXTEEN"] = "ADAPTER_SIZE_SIXTEEN"; + /** + * Adapter size 32. + */ + AdapterSize["ADAPTER_SIZE_THIRTY_TWO"] = "ADAPTER_SIZE_THIRTY_TWO"; +})(exports.AdapterSize || (exports.AdapterSize = {})); +/** Job state. */ +exports.JobState = void 0; +(function (JobState) { + /** + * The job state is unspecified. + */ + JobState["JOB_STATE_UNSPECIFIED"] = "JOB_STATE_UNSPECIFIED"; + /** + * The job has been just created or resumed and processing has not yet begun. + */ + JobState["JOB_STATE_QUEUED"] = "JOB_STATE_QUEUED"; + /** + * The service is preparing to run the job. + */ + JobState["JOB_STATE_PENDING"] = "JOB_STATE_PENDING"; + /** + * The job is in progress. + */ + JobState["JOB_STATE_RUNNING"] = "JOB_STATE_RUNNING"; + /** + * The job completed successfully. + */ + JobState["JOB_STATE_SUCCEEDED"] = "JOB_STATE_SUCCEEDED"; + /** + * The job failed. + */ + JobState["JOB_STATE_FAILED"] = "JOB_STATE_FAILED"; + /** + * The job is being cancelled. From this state the job may only go to either `JOB_STATE_SUCCEEDED`, `JOB_STATE_FAILED` or `JOB_STATE_CANCELLED`. + */ + JobState["JOB_STATE_CANCELLING"] = "JOB_STATE_CANCELLING"; + /** + * The job has been cancelled. + */ + JobState["JOB_STATE_CANCELLED"] = "JOB_STATE_CANCELLED"; + /** + * The job has been stopped, and can be resumed. + */ + JobState["JOB_STATE_PAUSED"] = "JOB_STATE_PAUSED"; + /** + * The job has expired. + */ + JobState["JOB_STATE_EXPIRED"] = "JOB_STATE_EXPIRED"; + /** + * The job is being updated. Only jobs in the `JOB_STATE_RUNNING` state can be updated. After updating, the job goes back to the `JOB_STATE_RUNNING` state. + */ + JobState["JOB_STATE_UPDATING"] = "JOB_STATE_UPDATING"; + /** + * The job is partially succeeded, some results may be missing due to errors. + */ + JobState["JOB_STATE_PARTIALLY_SUCCEEDED"] = "JOB_STATE_PARTIALLY_SUCCEEDED"; +})(exports.JobState || (exports.JobState = {})); +/** The tuning task. Either I2V or T2V. This enum is not supported in Gemini API. */ +exports.TuningTask = void 0; +(function (TuningTask) { + /** + * Default value. This value is unused. + */ + TuningTask["TUNING_TASK_UNSPECIFIED"] = "TUNING_TASK_UNSPECIFIED"; + /** + * Tuning task for image to video. + */ + TuningTask["TUNING_TASK_I2V"] = "TUNING_TASK_I2V"; + /** + * Tuning task for text to video. + */ + TuningTask["TUNING_TASK_T2V"] = "TUNING_TASK_T2V"; + /** + * Tuning task for reference to video. + */ + TuningTask["TUNING_TASK_R2V"] = "TUNING_TASK_R2V"; +})(exports.TuningTask || (exports.TuningTask = {})); +/** The tokenization quality used for given media. */ +exports.PartMediaResolutionLevel = void 0; +(function (PartMediaResolutionLevel) { + /** + * Media resolution has not been set. + */ + PartMediaResolutionLevel["MEDIA_RESOLUTION_UNSPECIFIED"] = "MEDIA_RESOLUTION_UNSPECIFIED"; + /** + * Media resolution set to low. + */ + PartMediaResolutionLevel["MEDIA_RESOLUTION_LOW"] = "MEDIA_RESOLUTION_LOW"; + /** + * Media resolution set to medium. + */ + PartMediaResolutionLevel["MEDIA_RESOLUTION_MEDIUM"] = "MEDIA_RESOLUTION_MEDIUM"; + /** + * Media resolution set to high. + */ + PartMediaResolutionLevel["MEDIA_RESOLUTION_HIGH"] = "MEDIA_RESOLUTION_HIGH"; + /** + * Media resolution set to ultra high. + */ + PartMediaResolutionLevel["MEDIA_RESOLUTION_ULTRA_HIGH"] = "MEDIA_RESOLUTION_ULTRA_HIGH"; +})(exports.PartMediaResolutionLevel || (exports.PartMediaResolutionLevel = {})); +/** Resource scope. */ +exports.ResourceScope = void 0; +(function (ResourceScope) { + /** + * When setting base_url, this value configures resource scope to be the collection. + The resource name will not include api version, project, or location. + For example, if base_url is set to "https://aiplatform.googleapis.com", + then the resource name for a Model would be + "https://aiplatform.googleapis.com/publishers/google/models/gemini-3-pro-preview + */ + ResourceScope["COLLECTION"] = "COLLECTION"; +})(exports.ResourceScope || (exports.ResourceScope = {})); +/** Options for feature selection preference. */ +exports.FeatureSelectionPreference = void 0; +(function (FeatureSelectionPreference) { + FeatureSelectionPreference["FEATURE_SELECTION_PREFERENCE_UNSPECIFIED"] = "FEATURE_SELECTION_PREFERENCE_UNSPECIFIED"; + FeatureSelectionPreference["PRIORITIZE_QUALITY"] = "PRIORITIZE_QUALITY"; + FeatureSelectionPreference["BALANCED"] = "BALANCED"; + FeatureSelectionPreference["PRIORITIZE_COST"] = "PRIORITIZE_COST"; +})(exports.FeatureSelectionPreference || (exports.FeatureSelectionPreference = {})); +/** The environment being operated. */ +exports.Environment = void 0; +(function (Environment) { + /** + * Defaults to browser. + */ + Environment["ENVIRONMENT_UNSPECIFIED"] = "ENVIRONMENT_UNSPECIFIED"; + /** + * Operates in a web browser. + */ + Environment["ENVIRONMENT_BROWSER"] = "ENVIRONMENT_BROWSER"; +})(exports.Environment || (exports.Environment = {})); +/** Enum that controls the safety filter level for objectionable content. */ +exports.SafetyFilterLevel = void 0; +(function (SafetyFilterLevel) { + SafetyFilterLevel["BLOCK_LOW_AND_ABOVE"] = "BLOCK_LOW_AND_ABOVE"; + SafetyFilterLevel["BLOCK_MEDIUM_AND_ABOVE"] = "BLOCK_MEDIUM_AND_ABOVE"; + SafetyFilterLevel["BLOCK_ONLY_HIGH"] = "BLOCK_ONLY_HIGH"; + SafetyFilterLevel["BLOCK_NONE"] = "BLOCK_NONE"; +})(exports.SafetyFilterLevel || (exports.SafetyFilterLevel = {})); +/** Enum that controls the generation of people. */ +exports.PersonGeneration = void 0; +(function (PersonGeneration) { + /** + * Block generation of images of people. + */ + PersonGeneration["DONT_ALLOW"] = "DONT_ALLOW"; + /** + * Generate images of adults, but not children. + */ + PersonGeneration["ALLOW_ADULT"] = "ALLOW_ADULT"; + /** + * Generate images that include adults and children. + */ + PersonGeneration["ALLOW_ALL"] = "ALLOW_ALL"; +})(exports.PersonGeneration || (exports.PersonGeneration = {})); +/** Enum that specifies the language of the text in the prompt. */ +exports.ImagePromptLanguage = void 0; +(function (ImagePromptLanguage) { + /** + * Auto-detect the language. + */ + ImagePromptLanguage["auto"] = "auto"; + /** + * English + */ + ImagePromptLanguage["en"] = "en"; + /** + * Japanese + */ + ImagePromptLanguage["ja"] = "ja"; + /** + * Korean + */ + ImagePromptLanguage["ko"] = "ko"; + /** + * Hindi + */ + ImagePromptLanguage["hi"] = "hi"; + /** + * Chinese + */ + ImagePromptLanguage["zh"] = "zh"; + /** + * Portuguese + */ + ImagePromptLanguage["pt"] = "pt"; + /** + * Spanish + */ + ImagePromptLanguage["es"] = "es"; +})(exports.ImagePromptLanguage || (exports.ImagePromptLanguage = {})); +/** Enum representing the mask mode of a mask reference image. */ +exports.MaskReferenceMode = void 0; +(function (MaskReferenceMode) { + MaskReferenceMode["MASK_MODE_DEFAULT"] = "MASK_MODE_DEFAULT"; + MaskReferenceMode["MASK_MODE_USER_PROVIDED"] = "MASK_MODE_USER_PROVIDED"; + MaskReferenceMode["MASK_MODE_BACKGROUND"] = "MASK_MODE_BACKGROUND"; + MaskReferenceMode["MASK_MODE_FOREGROUND"] = "MASK_MODE_FOREGROUND"; + MaskReferenceMode["MASK_MODE_SEMANTIC"] = "MASK_MODE_SEMANTIC"; +})(exports.MaskReferenceMode || (exports.MaskReferenceMode = {})); +/** Enum representing the control type of a control reference image. */ +exports.ControlReferenceType = void 0; +(function (ControlReferenceType) { + ControlReferenceType["CONTROL_TYPE_DEFAULT"] = "CONTROL_TYPE_DEFAULT"; + ControlReferenceType["CONTROL_TYPE_CANNY"] = "CONTROL_TYPE_CANNY"; + ControlReferenceType["CONTROL_TYPE_SCRIBBLE"] = "CONTROL_TYPE_SCRIBBLE"; + ControlReferenceType["CONTROL_TYPE_FACE_MESH"] = "CONTROL_TYPE_FACE_MESH"; +})(exports.ControlReferenceType || (exports.ControlReferenceType = {})); +/** Enum representing the subject type of a subject reference image. */ +exports.SubjectReferenceType = void 0; +(function (SubjectReferenceType) { + SubjectReferenceType["SUBJECT_TYPE_DEFAULT"] = "SUBJECT_TYPE_DEFAULT"; + SubjectReferenceType["SUBJECT_TYPE_PERSON"] = "SUBJECT_TYPE_PERSON"; + SubjectReferenceType["SUBJECT_TYPE_ANIMAL"] = "SUBJECT_TYPE_ANIMAL"; + SubjectReferenceType["SUBJECT_TYPE_PRODUCT"] = "SUBJECT_TYPE_PRODUCT"; +})(exports.SubjectReferenceType || (exports.SubjectReferenceType = {})); +/** Enum representing the editing mode. */ +exports.EditMode = void 0; +(function (EditMode) { + EditMode["EDIT_MODE_DEFAULT"] = "EDIT_MODE_DEFAULT"; + EditMode["EDIT_MODE_INPAINT_REMOVAL"] = "EDIT_MODE_INPAINT_REMOVAL"; + EditMode["EDIT_MODE_INPAINT_INSERTION"] = "EDIT_MODE_INPAINT_INSERTION"; + EditMode["EDIT_MODE_OUTPAINT"] = "EDIT_MODE_OUTPAINT"; + EditMode["EDIT_MODE_CONTROLLED_EDITING"] = "EDIT_MODE_CONTROLLED_EDITING"; + EditMode["EDIT_MODE_STYLE"] = "EDIT_MODE_STYLE"; + EditMode["EDIT_MODE_BGSWAP"] = "EDIT_MODE_BGSWAP"; + EditMode["EDIT_MODE_PRODUCT_IMAGE"] = "EDIT_MODE_PRODUCT_IMAGE"; +})(exports.EditMode || (exports.EditMode = {})); +/** Enum that represents the segmentation mode. */ +exports.SegmentMode = void 0; +(function (SegmentMode) { + SegmentMode["FOREGROUND"] = "FOREGROUND"; + SegmentMode["BACKGROUND"] = "BACKGROUND"; + SegmentMode["PROMPT"] = "PROMPT"; + SegmentMode["SEMANTIC"] = "SEMANTIC"; + SegmentMode["INTERACTIVE"] = "INTERACTIVE"; +})(exports.SegmentMode || (exports.SegmentMode = {})); +/** Enum for the reference type of a video generation reference image. */ +exports.VideoGenerationReferenceType = void 0; +(function (VideoGenerationReferenceType) { + /** + * A reference image that provides assets to the generated video, + such as the scene, an object, a character, etc. + */ + VideoGenerationReferenceType["ASSET"] = "ASSET"; + /** + * A reference image that provides aesthetics including colors, + lighting, texture, etc., to be used as the style of the generated video, + such as 'anime', 'photography', 'origami', etc. + */ + VideoGenerationReferenceType["STYLE"] = "STYLE"; +})(exports.VideoGenerationReferenceType || (exports.VideoGenerationReferenceType = {})); +/** Enum for the mask mode of a video generation mask. */ +exports.VideoGenerationMaskMode = void 0; +(function (VideoGenerationMaskMode) { + /** + * The image mask contains a masked rectangular region which is + applied on the first frame of the input video. The object described in + the prompt is inserted into this region and will appear in subsequent + frames. + */ + VideoGenerationMaskMode["INSERT"] = "INSERT"; + /** + * The image mask is used to determine an object in the + first video frame to track. This object is removed from the video. + */ + VideoGenerationMaskMode["REMOVE"] = "REMOVE"; + /** + * The image mask is used to determine a region in the + video. Objects in this region will be removed. + */ + VideoGenerationMaskMode["REMOVE_STATIC"] = "REMOVE_STATIC"; + /** + * The image mask contains a masked rectangular region where + the input video will go. The remaining area will be generated. Video + masks are not supported. + */ + VideoGenerationMaskMode["OUTPAINT"] = "OUTPAINT"; +})(exports.VideoGenerationMaskMode || (exports.VideoGenerationMaskMode = {})); +/** Enum that controls the compression quality of the generated videos. */ +exports.VideoCompressionQuality = void 0; +(function (VideoCompressionQuality) { + /** + * Optimized video compression quality. This will produce videos + with a compressed, smaller file size. + */ + VideoCompressionQuality["OPTIMIZED"] = "OPTIMIZED"; + /** + * Lossless video compression quality. This will produce videos + with a larger file size. + */ + VideoCompressionQuality["LOSSLESS"] = "LOSSLESS"; +})(exports.VideoCompressionQuality || (exports.VideoCompressionQuality = {})); +/** Enum representing the tuning method. */ +exports.TuningMethod = void 0; +(function (TuningMethod) { + /** + * Supervised fine tuning. + */ + TuningMethod["SUPERVISED_FINE_TUNING"] = "SUPERVISED_FINE_TUNING"; + /** + * Preference optimization tuning. + */ + TuningMethod["PREFERENCE_TUNING"] = "PREFERENCE_TUNING"; + /** + * Distillation tuning. + */ + TuningMethod["DISTILLATION"] = "DISTILLATION"; +})(exports.TuningMethod || (exports.TuningMethod = {})); +/** State for the lifecycle of a Document. */ +exports.DocumentState = void 0; +(function (DocumentState) { + DocumentState["STATE_UNSPECIFIED"] = "STATE_UNSPECIFIED"; + DocumentState["STATE_PENDING"] = "STATE_PENDING"; + DocumentState["STATE_ACTIVE"] = "STATE_ACTIVE"; + DocumentState["STATE_FAILED"] = "STATE_FAILED"; +})(exports.DocumentState || (exports.DocumentState = {})); +/** State for the lifecycle of a File. */ +exports.FileState = void 0; +(function (FileState) { + FileState["STATE_UNSPECIFIED"] = "STATE_UNSPECIFIED"; + FileState["PROCESSING"] = "PROCESSING"; + FileState["ACTIVE"] = "ACTIVE"; + FileState["FAILED"] = "FAILED"; +})(exports.FileState || (exports.FileState = {})); +/** Source of the File. */ +exports.FileSource = void 0; +(function (FileSource) { + FileSource["SOURCE_UNSPECIFIED"] = "SOURCE_UNSPECIFIED"; + FileSource["UPLOADED"] = "UPLOADED"; + FileSource["GENERATED"] = "GENERATED"; + FileSource["REGISTERED"] = "REGISTERED"; +})(exports.FileSource || (exports.FileSource = {})); +/** The reason why the turn is complete. */ +exports.TurnCompleteReason = void 0; +(function (TurnCompleteReason) { + /** + * Default value. Reason is unspecified. + */ + TurnCompleteReason["TURN_COMPLETE_REASON_UNSPECIFIED"] = "TURN_COMPLETE_REASON_UNSPECIFIED"; + /** + * The function call generated by the model is invalid. + */ + TurnCompleteReason["MALFORMED_FUNCTION_CALL"] = "MALFORMED_FUNCTION_CALL"; + /** + * The response is rejected by the model. + */ + TurnCompleteReason["RESPONSE_REJECTED"] = "RESPONSE_REJECTED"; + /** + * Needs more input from the user. + */ + TurnCompleteReason["NEED_MORE_INPUT"] = "NEED_MORE_INPUT"; +})(exports.TurnCompleteReason || (exports.TurnCompleteReason = {})); +/** Server content modalities. */ +exports.MediaModality = void 0; +(function (MediaModality) { + /** + * The modality is unspecified. + */ + MediaModality["MODALITY_UNSPECIFIED"] = "MODALITY_UNSPECIFIED"; + /** + * Plain text. + */ + MediaModality["TEXT"] = "TEXT"; + /** + * Images. + */ + MediaModality["IMAGE"] = "IMAGE"; + /** + * Video. + */ + MediaModality["VIDEO"] = "VIDEO"; + /** + * Audio. + */ + MediaModality["AUDIO"] = "AUDIO"; + /** + * Document, e.g. PDF. + */ + MediaModality["DOCUMENT"] = "DOCUMENT"; +})(exports.MediaModality || (exports.MediaModality = {})); +/** The type of the VAD signal. */ +exports.VadSignalType = void 0; +(function (VadSignalType) { + /** + * The default is VAD_SIGNAL_TYPE_UNSPECIFIED. + */ + VadSignalType["VAD_SIGNAL_TYPE_UNSPECIFIED"] = "VAD_SIGNAL_TYPE_UNSPECIFIED"; + /** + * Start of sentence signal. + */ + VadSignalType["VAD_SIGNAL_TYPE_SOS"] = "VAD_SIGNAL_TYPE_SOS"; + /** + * End of sentence signal. + */ + VadSignalType["VAD_SIGNAL_TYPE_EOS"] = "VAD_SIGNAL_TYPE_EOS"; +})(exports.VadSignalType || (exports.VadSignalType = {})); +/** The type of the voice activity signal. */ +exports.VoiceActivityType = void 0; +(function (VoiceActivityType) { + /** + * The default is VOICE_ACTIVITY_TYPE_UNSPECIFIED. + */ + VoiceActivityType["TYPE_UNSPECIFIED"] = "TYPE_UNSPECIFIED"; + /** + * Start of sentence signal. + */ + VoiceActivityType["ACTIVITY_START"] = "ACTIVITY_START"; + /** + * End of sentence signal. + */ + VoiceActivityType["ACTIVITY_END"] = "ACTIVITY_END"; +})(exports.VoiceActivityType || (exports.VoiceActivityType = {})); +/** Start of speech sensitivity. */ +exports.StartSensitivity = void 0; +(function (StartSensitivity) { + /** + * The default is START_SENSITIVITY_LOW. + */ + StartSensitivity["START_SENSITIVITY_UNSPECIFIED"] = "START_SENSITIVITY_UNSPECIFIED"; + /** + * Automatic detection will detect the start of speech more often. + */ + StartSensitivity["START_SENSITIVITY_HIGH"] = "START_SENSITIVITY_HIGH"; + /** + * Automatic detection will detect the start of speech less often. + */ + StartSensitivity["START_SENSITIVITY_LOW"] = "START_SENSITIVITY_LOW"; +})(exports.StartSensitivity || (exports.StartSensitivity = {})); +/** End of speech sensitivity. */ +exports.EndSensitivity = void 0; +(function (EndSensitivity) { + /** + * The default is END_SENSITIVITY_LOW. + */ + EndSensitivity["END_SENSITIVITY_UNSPECIFIED"] = "END_SENSITIVITY_UNSPECIFIED"; + /** + * Automatic detection ends speech more often. + */ + EndSensitivity["END_SENSITIVITY_HIGH"] = "END_SENSITIVITY_HIGH"; + /** + * Automatic detection ends speech less often. + */ + EndSensitivity["END_SENSITIVITY_LOW"] = "END_SENSITIVITY_LOW"; +})(exports.EndSensitivity || (exports.EndSensitivity = {})); +/** The different ways of handling user activity. */ +exports.ActivityHandling = void 0; +(function (ActivityHandling) { + /** + * If unspecified, the default behavior is `START_OF_ACTIVITY_INTERRUPTS`. + */ + ActivityHandling["ACTIVITY_HANDLING_UNSPECIFIED"] = "ACTIVITY_HANDLING_UNSPECIFIED"; + /** + * If true, start of activity will interrupt the model's response (also called "barge in"). The model's current response will be cut-off in the moment of the interruption. This is the default behavior. + */ + ActivityHandling["START_OF_ACTIVITY_INTERRUPTS"] = "START_OF_ACTIVITY_INTERRUPTS"; + /** + * The model's response will not be interrupted. + */ + ActivityHandling["NO_INTERRUPTION"] = "NO_INTERRUPTION"; +})(exports.ActivityHandling || (exports.ActivityHandling = {})); +/** Options about which input is included in the user's turn. */ +exports.TurnCoverage = void 0; +(function (TurnCoverage) { + /** + * If unspecified, the default behavior is `TURN_INCLUDES_ONLY_ACTIVITY`. + */ + TurnCoverage["TURN_COVERAGE_UNSPECIFIED"] = "TURN_COVERAGE_UNSPECIFIED"; + /** + * The users turn only includes activity since the last turn, excluding inactivity (e.g. silence on the audio stream). This is the default behavior. + */ + TurnCoverage["TURN_INCLUDES_ONLY_ACTIVITY"] = "TURN_INCLUDES_ONLY_ACTIVITY"; + /** + * The users turn includes all realtime input since the last turn, including inactivity (e.g. silence on the audio stream). + */ + TurnCoverage["TURN_INCLUDES_ALL_INPUT"] = "TURN_INCLUDES_ALL_INPUT"; +})(exports.TurnCoverage || (exports.TurnCoverage = {})); +/** Scale of the generated music. */ +exports.Scale = void 0; +(function (Scale) { + /** + * Default value. This value is unused. + */ + Scale["SCALE_UNSPECIFIED"] = "SCALE_UNSPECIFIED"; + /** + * C major or A minor. + */ + Scale["C_MAJOR_A_MINOR"] = "C_MAJOR_A_MINOR"; + /** + * Db major or Bb minor. + */ + Scale["D_FLAT_MAJOR_B_FLAT_MINOR"] = "D_FLAT_MAJOR_B_FLAT_MINOR"; + /** + * D major or B minor. + */ + Scale["D_MAJOR_B_MINOR"] = "D_MAJOR_B_MINOR"; + /** + * Eb major or C minor + */ + Scale["E_FLAT_MAJOR_C_MINOR"] = "E_FLAT_MAJOR_C_MINOR"; + /** + * E major or Db minor. + */ + Scale["E_MAJOR_D_FLAT_MINOR"] = "E_MAJOR_D_FLAT_MINOR"; + /** + * F major or D minor. + */ + Scale["F_MAJOR_D_MINOR"] = "F_MAJOR_D_MINOR"; + /** + * Gb major or Eb minor. + */ + Scale["G_FLAT_MAJOR_E_FLAT_MINOR"] = "G_FLAT_MAJOR_E_FLAT_MINOR"; + /** + * G major or E minor. + */ + Scale["G_MAJOR_E_MINOR"] = "G_MAJOR_E_MINOR"; + /** + * Ab major or F minor. + */ + Scale["A_FLAT_MAJOR_F_MINOR"] = "A_FLAT_MAJOR_F_MINOR"; + /** + * A major or Gb minor. + */ + Scale["A_MAJOR_G_FLAT_MINOR"] = "A_MAJOR_G_FLAT_MINOR"; + /** + * Bb major or G minor. + */ + Scale["B_FLAT_MAJOR_G_MINOR"] = "B_FLAT_MAJOR_G_MINOR"; + /** + * B major or Ab minor. + */ + Scale["B_MAJOR_A_FLAT_MINOR"] = "B_MAJOR_A_FLAT_MINOR"; +})(exports.Scale || (exports.Scale = {})); +/** The mode of music generation. */ +exports.MusicGenerationMode = void 0; +(function (MusicGenerationMode) { + /** + * Rely on the server default generation mode. + */ + MusicGenerationMode["MUSIC_GENERATION_MODE_UNSPECIFIED"] = "MUSIC_GENERATION_MODE_UNSPECIFIED"; + /** + * Steer text prompts to regions of latent space with higher quality + music. + */ + MusicGenerationMode["QUALITY"] = "QUALITY"; + /** + * Steer text prompts to regions of latent space with a larger + diversity of music. + */ + MusicGenerationMode["DIVERSITY"] = "DIVERSITY"; + /** + * Steer text prompts to regions of latent space more likely to + generate music with vocals. + */ + MusicGenerationMode["VOCALIZATION"] = "VOCALIZATION"; +})(exports.MusicGenerationMode || (exports.MusicGenerationMode = {})); +/** The playback control signal to apply to the music generation. */ +exports.LiveMusicPlaybackControl = void 0; +(function (LiveMusicPlaybackControl) { + /** + * This value is unused. + */ + LiveMusicPlaybackControl["PLAYBACK_CONTROL_UNSPECIFIED"] = "PLAYBACK_CONTROL_UNSPECIFIED"; + /** + * Start generating the music. + */ + LiveMusicPlaybackControl["PLAY"] = "PLAY"; + /** + * Hold the music generation. Use PLAY to resume from the current position. + */ + LiveMusicPlaybackControl["PAUSE"] = "PAUSE"; + /** + * Stop the music generation and reset the context (prompts retained). + Use PLAY to restart the music generation. + */ + LiveMusicPlaybackControl["STOP"] = "STOP"; + /** + * Reset the context of the music generation without stopping it. + Retains the current prompts and config. + */ + LiveMusicPlaybackControl["RESET_CONTEXT"] = "RESET_CONTEXT"; +})(exports.LiveMusicPlaybackControl || (exports.LiveMusicPlaybackControl = {})); +/** Raw media bytes for function response. + +Text should not be sent as raw bytes, use the FunctionResponse.response +field. */ +class FunctionResponseBlob { +} +/** URI based data for function response. */ +class FunctionResponseFileData { +} +/** A datatype containing media that is part of a `FunctionResponse` message. + +A `FunctionResponsePart` consists of data which has an associated datatype. A +`FunctionResponsePart` can only contain one of the accepted types in +`FunctionResponsePart.data`. + +A `FunctionResponsePart` must have a fixed IANA MIME type identifying the +type and subtype of the media if the `inline_data` field is filled with raw +bytes. */ +class FunctionResponsePart { +} +/** + * Creates a `FunctionResponsePart` object from a `base64` encoded `string`. + */ +function createFunctionResponsePartFromBase64(data, mimeType) { + return { + inlineData: { + data: data, + mimeType: mimeType, + }, + }; +} +/** + * Creates a `FunctionResponsePart` object from a `URI` string. + */ +function createFunctionResponsePartFromUri(uri, mimeType) { + return { + fileData: { + fileUri: uri, + mimeType: mimeType, + }, + }; +} +/** A function response. */ +class FunctionResponse { +} +/** + * Creates a `Part` object from a `URI` string. + */ +function createPartFromUri(uri, mimeType, mediaResolution) { + return Object.assign({ fileData: { + fileUri: uri, + mimeType: mimeType, + } }, (mediaResolution && { mediaResolution: { level: mediaResolution } })); +} +/** + * Creates a `Part` object from a `text` string. + */ +function createPartFromText(text) { + return { + text: text, + }; +} +/** + * Creates a `Part` object from a `FunctionCall` object. + */ +function createPartFromFunctionCall(name, args) { + return { + functionCall: { + name: name, + args: args, + }, + }; +} +/** + * Creates a `Part` object from a `FunctionResponse` object. + */ +function createPartFromFunctionResponse(id, name, response, parts = []) { + return { + functionResponse: Object.assign({ id: id, name: name, response: response }, (parts.length > 0 && { parts })), + }; +} +/** + * Creates a `Part` object from a `base64` encoded `string`. + */ +function createPartFromBase64(data, mimeType, mediaResolution) { + return Object.assign({ inlineData: { + data: data, + mimeType: mimeType, + } }, (mediaResolution && { mediaResolution: { level: mediaResolution } })); +} +/** + * Creates a `Part` object from the `outcome` and `output` of a `CodeExecutionResult` object. + */ +function createPartFromCodeExecutionResult(outcome, output) { + return { + codeExecutionResult: { + outcome: outcome, + output: output, + }, + }; +} +/** + * Creates a `Part` object from the `code` and `language` of an `ExecutableCode` object. + */ +function createPartFromExecutableCode(code, language) { + return { + executableCode: { + code: code, + language: language, + }, + }; +} +function _isPart(obj) { + if (typeof obj === 'object' && obj !== null) { + return ('fileData' in obj || + 'text' in obj || + 'functionCall' in obj || + 'functionResponse' in obj || + 'inlineData' in obj || + 'videoMetadata' in obj || + 'codeExecutionResult' in obj || + 'executableCode' in obj); + } + return false; +} +function _toParts(partOrString) { + const parts = []; + if (typeof partOrString === 'string') { + parts.push(createPartFromText(partOrString)); + } + else if (_isPart(partOrString)) { + parts.push(partOrString); + } + else if (Array.isArray(partOrString)) { + if (partOrString.length === 0) { + throw new Error('partOrString cannot be an empty array'); + } + for (const part of partOrString) { + if (typeof part === 'string') { + parts.push(createPartFromText(part)); + } + else if (_isPart(part)) { + parts.push(part); + } + else { + throw new Error('element in PartUnion must be a Part object or string'); + } + } + } + else { + throw new Error('partOrString must be a Part object, string, or array'); + } + return parts; +} +/** + * Creates a `Content` object with a user role from a `PartListUnion` object or `string`. + */ +function createUserContent(partOrString) { + return { + role: 'user', + parts: _toParts(partOrString), + }; +} +/** + * Creates a `Content` object with a model role from a `PartListUnion` object or `string`. + */ +function createModelContent(partOrString) { + return { + role: 'model', + parts: _toParts(partOrString), + }; +} +/** A wrapper class for the http response. */ +class HttpResponse { + constructor(response) { + // Process the headers. + const headers = {}; + for (const pair of response.headers.entries()) { + headers[pair[0]] = pair[1]; + } + this.headers = headers; + // Keep the original response. + this.responseInternal = response; + } + json() { + return this.responseInternal.json(); + } +} +/** Content filter results for a prompt sent in the request. Note: This is sent only in the first stream chunk and only if no candidates were generated due to content violations. */ +class GenerateContentResponsePromptFeedback { +} +/** Usage metadata about the content generation request and response. This message provides a detailed breakdown of token usage and other relevant metrics. This data type is not supported in Gemini API. */ +class GenerateContentResponseUsageMetadata { +} +/** Response message for PredictionService.GenerateContent. */ +class GenerateContentResponse { + /** + * Returns the concatenation of all text parts from the first candidate in the response. + * + * @remarks + * If there are multiple candidates in the response, the text from the first + * one will be returned. + * If there are non-text parts in the response, the concatenation of all text + * parts will be returned, and a warning will be logged. + * If there are thought parts in the response, the concatenation of all text + * parts excluding the thought parts will be returned. + * + * @example + * ```ts + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: + * 'Why is the sky blue?', + * }); + * + * console.debug(response.text); + * ``` + */ + get text() { + var _a, _b, _c, _d, _e, _f, _g, _h; + if (((_d = (_c = (_b = (_a = this.candidates) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.parts) === null || _d === void 0 ? void 0 : _d.length) === 0) { + return undefined; + } + if (this.candidates && this.candidates.length > 1) { + console.warn('there are multiple candidates in the response, returning text from the first one.'); + } + let text = ''; + let anyTextPartText = false; + const nonTextParts = []; + for (const part of (_h = (_g = (_f = (_e = this.candidates) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.content) === null || _g === void 0 ? void 0 : _g.parts) !== null && _h !== void 0 ? _h : []) { + for (const [fieldName, fieldValue] of Object.entries(part)) { + if (fieldName !== 'text' && + fieldName !== 'thought' && + fieldName !== 'thoughtSignature' && + (fieldValue !== null || fieldValue !== undefined)) { + nonTextParts.push(fieldName); + } + } + if (typeof part.text === 'string') { + if (typeof part.thought === 'boolean' && part.thought) { + continue; + } + anyTextPartText = true; + text += part.text; + } + } + if (nonTextParts.length > 0) { + console.warn(`there are non-text parts ${nonTextParts} in the response, returning concatenation of all text parts. Please refer to the non text parts for a full response from model.`); + } + // part.text === '' is different from part.text is null + return anyTextPartText ? text : undefined; + } + /** + * Returns the concatenation of all inline data parts from the first candidate + * in the response. + * + * @remarks + * If there are multiple candidates in the response, the inline data from the + * first one will be returned. If there are non-inline data parts in the + * response, the concatenation of all inline data parts will be returned, and + * a warning will be logged. + */ + get data() { + var _a, _b, _c, _d, _e, _f, _g, _h; + if (((_d = (_c = (_b = (_a = this.candidates) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.parts) === null || _d === void 0 ? void 0 : _d.length) === 0) { + return undefined; + } + if (this.candidates && this.candidates.length > 1) { + console.warn('there are multiple candidates in the response, returning data from the first one.'); + } + let data = ''; + const nonDataParts = []; + for (const part of (_h = (_g = (_f = (_e = this.candidates) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.content) === null || _g === void 0 ? void 0 : _g.parts) !== null && _h !== void 0 ? _h : []) { + for (const [fieldName, fieldValue] of Object.entries(part)) { + if (fieldName !== 'inlineData' && + (fieldValue !== null || fieldValue !== undefined)) { + nonDataParts.push(fieldName); + } + } + if (part.inlineData && typeof part.inlineData.data === 'string') { + data += atob(part.inlineData.data); + } + } + if (nonDataParts.length > 0) { + console.warn(`there are non-data parts ${nonDataParts} in the response, returning concatenation of all data parts. Please refer to the non data parts for a full response from model.`); + } + return data.length > 0 ? btoa(data) : undefined; + } + /** + * Returns the function calls from the first candidate in the response. + * + * @remarks + * If there are multiple candidates in the response, the function calls from + * the first one will be returned. + * If there are no function calls in the response, undefined will be returned. + * + * @example + * ```ts + * const controlLightFunctionDeclaration: FunctionDeclaration = { + * name: 'controlLight', + * parameters: { + * type: Type.OBJECT, + * description: 'Set the brightness and color temperature of a room light.', + * properties: { + * brightness: { + * type: Type.NUMBER, + * description: + * 'Light level from 0 to 100. Zero is off and 100 is full brightness.', + * }, + * colorTemperature: { + * type: Type.STRING, + * description: + * 'Color temperature of the light fixture which can be `daylight`, `cool` or `warm`.', + * }, + * }, + * required: ['brightness', 'colorTemperature'], + * }; + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: 'Dim the lights so the room feels cozy and warm.', + * config: { + * tools: [{functionDeclarations: [controlLightFunctionDeclaration]}], + * toolConfig: { + * functionCallingConfig: { + * mode: FunctionCallingConfigMode.ANY, + * allowedFunctionNames: ['controlLight'], + * }, + * }, + * }, + * }); + * console.debug(JSON.stringify(response.functionCalls)); + * ``` + */ + get functionCalls() { + var _a, _b, _c, _d, _e, _f, _g, _h; + if (((_d = (_c = (_b = (_a = this.candidates) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.parts) === null || _d === void 0 ? void 0 : _d.length) === 0) { + return undefined; + } + if (this.candidates && this.candidates.length > 1) { + console.warn('there are multiple candidates in the response, returning function calls from the first one.'); + } + const functionCalls = (_h = (_g = (_f = (_e = this.candidates) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.content) === null || _g === void 0 ? void 0 : _g.parts) === null || _h === void 0 ? void 0 : _h.filter((part) => part.functionCall).map((part) => part.functionCall).filter((functionCall) => functionCall !== undefined); + if ((functionCalls === null || functionCalls === void 0 ? void 0 : functionCalls.length) === 0) { + return undefined; + } + return functionCalls; + } + /** + * Returns the first executable code from the first candidate in the response. + * + * @remarks + * If there are multiple candidates in the response, the executable code from + * the first one will be returned. + * If there are no executable code in the response, undefined will be + * returned. + * + * @example + * ```ts + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: + * 'What is the sum of the first 50 prime numbers? Generate and run code for the calculation, and make sure you get all 50.' + * config: { + * tools: [{codeExecution: {}}], + * }, + * }); + * + * console.debug(response.executableCode); + * ``` + */ + get executableCode() { + var _a, _b, _c, _d, _e, _f, _g, _h, _j; + if (((_d = (_c = (_b = (_a = this.candidates) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.parts) === null || _d === void 0 ? void 0 : _d.length) === 0) { + return undefined; + } + if (this.candidates && this.candidates.length > 1) { + console.warn('there are multiple candidates in the response, returning executable code from the first one.'); + } + const executableCode = (_h = (_g = (_f = (_e = this.candidates) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.content) === null || _g === void 0 ? void 0 : _g.parts) === null || _h === void 0 ? void 0 : _h.filter((part) => part.executableCode).map((part) => part.executableCode).filter((executableCode) => executableCode !== undefined); + if ((executableCode === null || executableCode === void 0 ? void 0 : executableCode.length) === 0) { + return undefined; + } + return (_j = executableCode === null || executableCode === void 0 ? void 0 : executableCode[0]) === null || _j === void 0 ? void 0 : _j.code; + } + /** + * Returns the first code execution result from the first candidate in the response. + * + * @remarks + * If there are multiple candidates in the response, the code execution result from + * the first one will be returned. + * If there are no code execution result in the response, undefined will be returned. + * + * @example + * ```ts + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: + * 'What is the sum of the first 50 prime numbers? Generate and run code for the calculation, and make sure you get all 50.' + * config: { + * tools: [{codeExecution: {}}], + * }, + * }); + * + * console.debug(response.codeExecutionResult); + * ``` + */ + get codeExecutionResult() { + var _a, _b, _c, _d, _e, _f, _g, _h, _j; + if (((_d = (_c = (_b = (_a = this.candidates) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.parts) === null || _d === void 0 ? void 0 : _d.length) === 0) { + return undefined; + } + if (this.candidates && this.candidates.length > 1) { + console.warn('there are multiple candidates in the response, returning code execution result from the first one.'); + } + const codeExecutionResult = (_h = (_g = (_f = (_e = this.candidates) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.content) === null || _g === void 0 ? void 0 : _g.parts) === null || _h === void 0 ? void 0 : _h.filter((part) => part.codeExecutionResult).map((part) => part.codeExecutionResult).filter((codeExecutionResult) => codeExecutionResult !== undefined); + if ((codeExecutionResult === null || codeExecutionResult === void 0 ? void 0 : codeExecutionResult.length) === 0) { + return undefined; + } + return (_j = codeExecutionResult === null || codeExecutionResult === void 0 ? void 0 : codeExecutionResult[0]) === null || _j === void 0 ? void 0 : _j.output; + } +} +/** Response for the embed_content method. */ +class EmbedContentResponse { +} +/** The output images response. */ +class GenerateImagesResponse { +} +/** Response for the request to edit an image. */ +class EditImageResponse { +} +class UpscaleImageResponse { +} +/** The output images response. */ +class RecontextImageResponse { +} +/** The output images response. */ +class SegmentImageResponse { +} +class ListModelsResponse { +} +class DeleteModelResponse { +} +/** Response for counting tokens. */ +class CountTokensResponse { +} +/** Response for computing tokens. */ +class ComputeTokensResponse { +} +/** Response with generated videos. */ +class GenerateVideosResponse { +} +/** A video generation operation. */ +class GenerateVideosOperation { + /** + * Instantiates an Operation of the same type as the one being called with the fields set from the API response. + * @internal + */ + _fromAPIResponse({ apiResponse, _isVertexAI, }) { + const operation = new GenerateVideosOperation(); + let response; + const op = apiResponse; + if (_isVertexAI) { + response = generateVideosOperationFromVertex$1(op); + } + else { + response = generateVideosOperationFromMldev$1(op); + } + Object.assign(operation, response); + return operation; + } +} +/** Response for the list tuning jobs method. */ +class ListTuningJobsResponse { +} +/** Empty response for tunings.cancel method. */ +class CancelTuningJobResponse { +} +/** Empty response for caches.delete method. */ +class DeleteCachedContentResponse { +} +class ListCachedContentsResponse { +} +/** Config for documents.list return value. */ +class ListDocumentsResponse { +} +/** Config for file_search_stores.list return value. */ +class ListFileSearchStoresResponse { +} +/** Response for the resumable upload method. */ +class UploadToFileSearchStoreResumableResponse { +} +/** Response for ImportFile to import a File API file with a file search store. */ +class ImportFileResponse { +} +/** Long-running operation for importing a file to a FileSearchStore. */ +class ImportFileOperation { + /** + * Instantiates an Operation of the same type as the one being called with the fields set from the API response. + * @internal + */ + _fromAPIResponse({ apiResponse, _isVertexAI, }) { + const operation = new ImportFileOperation(); + const op = apiResponse; + const response = importFileOperationFromMldev$1(op); + Object.assign(operation, response); + return operation; + } +} +/** Response for the list files method. */ +class ListFilesResponse { +} +/** Response for the create file method. */ +class CreateFileResponse { +} +/** Response for the delete file method. */ +class DeleteFileResponse { +} +/** Response for the _register file method. */ +class RegisterFilesResponse { +} +/** Config for `inlined_responses` parameter. */ +class InlinedResponse { +} +/** Config for `response` parameter. */ +class SingleEmbedContentResponse { +} +/** Config for `inlined_embedding_responses` parameter. */ +class InlinedEmbedContentResponse { +} +/** Config for batches.list return value. */ +class ListBatchJobsResponse { +} +/** Represents a single response in a replay. */ +class ReplayResponse { +} +/** A raw reference image. + +A raw reference image represents the base image to edit, provided by the user. +It can optionally be provided in addition to a mask reference image or +a style reference image. */ +class RawReferenceImage { + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI() { + const referenceImageAPI = { + referenceType: 'REFERENCE_TYPE_RAW', + referenceImage: this.referenceImage, + referenceId: this.referenceId, + }; + return referenceImageAPI; + } +} +/** A mask reference image. + +This encapsulates either a mask image provided by the user and configs for +the user provided mask, or only config parameters for the model to generate +a mask. + +A mask image is an image whose non-zero values indicate where to edit the base +image. If the user provides a mask image, the mask must be in the same +dimensions as the raw image. */ +class MaskReferenceImage { + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI() { + const referenceImageAPI = { + referenceType: 'REFERENCE_TYPE_MASK', + referenceImage: this.referenceImage, + referenceId: this.referenceId, + maskImageConfig: this.config, + }; + return referenceImageAPI; + } +} +/** A control reference image. + +The image of the control reference image is either a control image provided +by the user, or a regular image which the backend will use to generate a +control image of. In the case of the latter, the +enable_control_image_computation field in the config should be set to True. + +A control image is an image that represents a sketch image of areas for the +model to fill in based on the prompt. */ +class ControlReferenceImage { + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI() { + const referenceImageAPI = { + referenceType: 'REFERENCE_TYPE_CONTROL', + referenceImage: this.referenceImage, + referenceId: this.referenceId, + controlImageConfig: this.config, + }; + return referenceImageAPI; + } +} +/** A style reference image. + +This encapsulates a style reference image provided by the user, and +additionally optional config parameters for the style reference image. + +A raw reference image can also be provided as a destination for the style to +be applied to. */ +class StyleReferenceImage { + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI() { + const referenceImageAPI = { + referenceType: 'REFERENCE_TYPE_STYLE', + referenceImage: this.referenceImage, + referenceId: this.referenceId, + styleImageConfig: this.config, + }; + return referenceImageAPI; + } +} +/** A subject reference image. + +This encapsulates a subject reference image provided by the user, and +additionally optional config parameters for the subject reference image. + +A raw reference image can also be provided as a destination for the subject to +be applied to. */ +class SubjectReferenceImage { + /* Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI() { + const referenceImageAPI = { + referenceType: 'REFERENCE_TYPE_SUBJECT', + referenceImage: this.referenceImage, + referenceId: this.referenceId, + subjectImageConfig: this.config, + }; + return referenceImageAPI; + } +} +/** A content reference image. + +A content reference image represents a subject to reference (ex. person, +product, animal) provided by the user. It can optionally be provided in +addition to a style reference image (ex. background, style reference). */ +class ContentReferenceImage { + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI() { + const referenceImageAPI = { + referenceType: 'REFERENCE_TYPE_CONTENT', + referenceImage: this.referenceImage, + referenceId: this.referenceId, + }; + return referenceImageAPI; + } +} +/** Response message for API call. */ +class LiveServerMessage { + /** + * Returns the concatenation of all text parts from the server content if present. + * + * @remarks + * If there are non-text parts in the response, the concatenation of all text + * parts will be returned, and a warning will be logged. + */ + get text() { + var _a, _b, _c; + let text = ''; + let anyTextPartFound = false; + const nonTextParts = []; + for (const part of (_c = (_b = (_a = this.serverContent) === null || _a === void 0 ? void 0 : _a.modelTurn) === null || _b === void 0 ? void 0 : _b.parts) !== null && _c !== void 0 ? _c : []) { + for (const [fieldName, fieldValue] of Object.entries(part)) { + if (fieldName !== 'text' && + fieldName !== 'thought' && + fieldValue !== null) { + nonTextParts.push(fieldName); + } + } + if (typeof part.text === 'string') { + if (typeof part.thought === 'boolean' && part.thought) { + continue; + } + anyTextPartFound = true; + text += part.text; + } + } + if (nonTextParts.length > 0) { + console.warn(`there are non-text parts ${nonTextParts} in the response, returning concatenation of all text parts. Please refer to the non text parts for a full response from model.`); + } + // part.text === '' is different from part.text is null + return anyTextPartFound ? text : undefined; + } + /** + * Returns the concatenation of all inline data parts from the server content if present. + * + * @remarks + * If there are non-inline data parts in the + * response, the concatenation of all inline data parts will be returned, and + * a warning will be logged. + */ + get data() { + var _a, _b, _c; + let data = ''; + const nonDataParts = []; + for (const part of (_c = (_b = (_a = this.serverContent) === null || _a === void 0 ? void 0 : _a.modelTurn) === null || _b === void 0 ? void 0 : _b.parts) !== null && _c !== void 0 ? _c : []) { + for (const [fieldName, fieldValue] of Object.entries(part)) { + if (fieldName !== 'inlineData' && fieldValue !== null) { + nonDataParts.push(fieldName); + } + } + if (part.inlineData && typeof part.inlineData.data === 'string') { + data += atob(part.inlineData.data); + } + } + if (nonDataParts.length > 0) { + console.warn(`there are non-data parts ${nonDataParts} in the response, returning concatenation of all data parts. Please refer to the non data parts for a full response from model.`); + } + return data.length > 0 ? btoa(data) : undefined; + } +} +/** Client generated response to a `ToolCall` received from the server. + +Individual `FunctionResponse` objects are matched to the respective +`FunctionCall` objects by the `id` field. + +Note that in the unary and server-streaming GenerateContent APIs function +calling happens by exchanging the `Content` parts, while in the bidi +GenerateContent APIs function calling happens over this dedicated set of +messages. */ +class LiveClientToolResponse { +} +/** Parameters for sending tool responses to the live API. */ +class LiveSendToolResponseParameters { + constructor() { + /** Tool responses to send to the session. */ + this.functionResponses = []; + } +} +/** Response message for the LiveMusicClientMessage call. */ +class LiveMusicServerMessage { + /** + * Returns the first audio chunk from the server content, if present. + * + * @remarks + * If there are no audio chunks in the response, undefined will be returned. + */ + get audioChunk() { + if (this.serverContent && + this.serverContent.audioChunks && + this.serverContent.audioChunks.length > 0) { + return this.serverContent.audioChunks[0]; + } + return undefined; + } +} +/** The response when long-running operation for uploading a file to a FileSearchStore complete. */ +class UploadToFileSearchStoreResponse { +} +/** Long-running operation for uploading a file to a FileSearchStore. */ +class UploadToFileSearchStoreOperation { + /** + * Instantiates an Operation of the same type as the one being called with the fields set from the API response. + * @internal + */ + _fromAPIResponse({ apiResponse, _isVertexAI, }) { + const operation = new UploadToFileSearchStoreOperation(); + const op = apiResponse; + const response = uploadToFileSearchStoreOperationFromMldev(op); + Object.assign(operation, response); + return operation; + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function tModel(apiClient, model) { + if (!model || typeof model !== 'string') { + throw new Error('model is required and must be a string'); + } + if (model.includes('..') || model.includes('?') || model.includes('&')) { + throw new Error('invalid model parameter'); + } + if (apiClient.isVertexAI()) { + if (model.startsWith('publishers/') || + model.startsWith('projects/') || + model.startsWith('models/')) { + return model; + } + else if (model.indexOf('/') >= 0) { + const parts = model.split('/', 2); + return `publishers/${parts[0]}/models/${parts[1]}`; + } + else { + return `publishers/google/models/${model}`; + } + } + else { + if (model.startsWith('models/') || model.startsWith('tunedModels/')) { + return model; + } + else { + return `models/${model}`; + } + } +} +function tCachesModel(apiClient, model) { + const transformedModel = tModel(apiClient, model); + if (!transformedModel) { + return ''; + } + if (transformedModel.startsWith('publishers/') && apiClient.isVertexAI()) { + // vertex caches only support model name start with projects. + return `projects/${apiClient.getProject()}/locations/${apiClient.getLocation()}/${transformedModel}`; + } + else if (transformedModel.startsWith('models/') && apiClient.isVertexAI()) { + return `projects/${apiClient.getProject()}/locations/${apiClient.getLocation()}/publishers/google/${transformedModel}`; + } + else { + return transformedModel; + } +} +function tBlobs(blobs) { + if (Array.isArray(blobs)) { + return blobs.map((blob) => tBlob(blob)); + } + else { + return [tBlob(blobs)]; + } +} +function tBlob(blob) { + if (typeof blob === 'object' && blob !== null) { + return blob; + } + throw new Error(`Could not parse input as Blob. Unsupported blob type: ${typeof blob}`); +} +function tImageBlob(blob) { + const transformedBlob = tBlob(blob); + if (transformedBlob.mimeType && + transformedBlob.mimeType.startsWith('image/')) { + return transformedBlob; + } + throw new Error(`Unsupported mime type: ${transformedBlob.mimeType}`); +} +function tAudioBlob(blob) { + const transformedBlob = tBlob(blob); + if (transformedBlob.mimeType && + transformedBlob.mimeType.startsWith('audio/')) { + return transformedBlob; + } + throw new Error(`Unsupported mime type: ${transformedBlob.mimeType}`); +} +function tPart(origin) { + if (origin === null || origin === undefined) { + throw new Error('PartUnion is required'); + } + if (typeof origin === 'object') { + return origin; + } + if (typeof origin === 'string') { + return { text: origin }; + } + throw new Error(`Unsupported part type: ${typeof origin}`); +} +function tParts(origin) { + if (origin === null || + origin === undefined || + (Array.isArray(origin) && origin.length === 0)) { + throw new Error('PartListUnion is required'); + } + if (Array.isArray(origin)) { + return origin.map((item) => tPart(item)); + } + return [tPart(origin)]; +} +function _isContent(origin) { + return (origin !== null && + origin !== undefined && + typeof origin === 'object' && + 'parts' in origin && + Array.isArray(origin.parts)); +} +function _isFunctionCallPart(origin) { + return (origin !== null && + origin !== undefined && + typeof origin === 'object' && + 'functionCall' in origin); +} +function _isFunctionResponsePart(origin) { + return (origin !== null && + origin !== undefined && + typeof origin === 'object' && + 'functionResponse' in origin); +} +function tContent(origin) { + if (origin === null || origin === undefined) { + throw new Error('ContentUnion is required'); + } + if (_isContent(origin)) { + // _isContent is a utility function that checks if the + // origin is a Content. + return origin; + } + return { + role: 'user', + parts: tParts(origin), + }; +} +function tContentsForEmbed(apiClient, origin) { + if (!origin) { + return []; + } + if (apiClient.isVertexAI() && Array.isArray(origin)) { + return origin.flatMap((item) => { + const content = tContent(item); + if (content.parts && + content.parts.length > 0 && + content.parts[0].text !== undefined) { + return [content.parts[0].text]; + } + return []; + }); + } + else if (apiClient.isVertexAI()) { + const content = tContent(origin); + if (content.parts && + content.parts.length > 0 && + content.parts[0].text !== undefined) { + return [content.parts[0].text]; + } + return []; + } + if (Array.isArray(origin)) { + return origin.map((item) => tContent(item)); + } + return [tContent(origin)]; +} +function tContents(origin) { + if (origin === null || + origin === undefined || + (Array.isArray(origin) && origin.length === 0)) { + throw new Error('contents are required'); + } + if (!Array.isArray(origin)) { + // If it's not an array, it's a single content or a single PartUnion. + if (_isFunctionCallPart(origin) || _isFunctionResponsePart(origin)) { + throw new Error('To specify functionCall or functionResponse parts, please wrap them in a Content object, specifying the role for them'); + } + return [tContent(origin)]; + } + const result = []; + const accumulatedParts = []; + const isContentArray = _isContent(origin[0]); + for (const item of origin) { + const isContent = _isContent(item); + if (isContent != isContentArray) { + throw new Error('Mixing Content and Parts is not supported, please group the parts into a the appropriate Content objects and specify the roles for them'); + } + if (isContent) { + // `isContent` contains the result of _isContent, which is a utility + // function that checks if the item is a Content. + result.push(item); + } + else if (_isFunctionCallPart(item) || _isFunctionResponsePart(item)) { + throw new Error('To specify functionCall or functionResponse parts, please wrap them, and any other parts, in Content objects as appropriate, specifying the role for them'); + } + else { + accumulatedParts.push(item); + } + } + if (!isContentArray) { + result.push({ role: 'user', parts: tParts(accumulatedParts) }); + } + return result; +} +/* +Transform the type field from an array of types to an array of anyOf fields. +Example: + {type: ['STRING', 'NUMBER']} +will be transformed to + {anyOf: [{type: 'STRING'}, {type: 'NUMBER'}]} +*/ +function flattenTypeArrayToAnyOf(typeList, resultingSchema) { + if (typeList.includes('null')) { + resultingSchema['nullable'] = true; + } + const listWithoutNull = typeList.filter((type) => type !== 'null'); + if (listWithoutNull.length === 1) { + resultingSchema['type'] = Object.values(exports.Type).includes(listWithoutNull[0].toUpperCase()) + ? listWithoutNull[0].toUpperCase() + : exports.Type.TYPE_UNSPECIFIED; + } + else { + resultingSchema['anyOf'] = []; + for (const i of listWithoutNull) { + resultingSchema['anyOf'].push({ + 'type': Object.values(exports.Type).includes(i.toUpperCase()) + ? i.toUpperCase() + : exports.Type.TYPE_UNSPECIFIED, + }); + } + } +} +function processJsonSchema(_jsonSchema) { + const genAISchema = {}; + const schemaFieldNames = ['items']; + const listSchemaFieldNames = ['anyOf']; + const dictSchemaFieldNames = ['properties']; + if (_jsonSchema['type'] && _jsonSchema['anyOf']) { + throw new Error('type and anyOf cannot be both populated.'); + } + /* + This is to handle the nullable array or object. The _jsonSchema will + be in the format of {anyOf: [{type: 'null'}, {type: 'object'}]}. The + logic is to check if anyOf has 2 elements and one of the element is null, + if so, the anyOf field is unnecessary, so we need to get rid of the anyOf + field and make the schema nullable. Then use the other element as the new + _jsonSchema for processing. This is because the backend doesn't have a null + type. + This has to be checked before we process any other fields. + For example: + const objectNullable = z.object({ + nullableArray: z.array(z.string()).nullable(), + }); + Will have the raw _jsonSchema as: + { + type: 'OBJECT', + properties: { + nullableArray: { + anyOf: [ + {type: 'null'}, + { + type: 'array', + items: {type: 'string'}, + }, + ], + } + }, + required: [ 'nullableArray' ], + } + Will result in following schema compatible with Gemini API: + { + type: 'OBJECT', + properties: { + nullableArray: { + nullable: true, + type: 'ARRAY', + items: {type: 'string'}, + } + }, + required: [ 'nullableArray' ], + } + */ + const incomingAnyOf = _jsonSchema['anyOf']; + if (incomingAnyOf != null && incomingAnyOf.length == 2) { + if (incomingAnyOf[0]['type'] === 'null') { + genAISchema['nullable'] = true; + _jsonSchema = incomingAnyOf[1]; + } + else if (incomingAnyOf[1]['type'] === 'null') { + genAISchema['nullable'] = true; + _jsonSchema = incomingAnyOf[0]; + } + } + if (_jsonSchema['type'] instanceof Array) { + flattenTypeArrayToAnyOf(_jsonSchema['type'], genAISchema); + } + for (const [fieldName, fieldValue] of Object.entries(_jsonSchema)) { + // Skip if the fieldvalue is undefined or null. + if (fieldValue == null) { + continue; + } + if (fieldName == 'type') { + if (fieldValue === 'null') { + throw new Error('type: null can not be the only possible type for the field.'); + } + if (fieldValue instanceof Array) { + // we have already handled the type field with array of types in the + // beginning of this function. + continue; + } + genAISchema['type'] = Object.values(exports.Type).includes(fieldValue.toUpperCase()) + ? fieldValue.toUpperCase() + : exports.Type.TYPE_UNSPECIFIED; + } + else if (schemaFieldNames.includes(fieldName)) { + genAISchema[fieldName] = + processJsonSchema(fieldValue); + } + else if (listSchemaFieldNames.includes(fieldName)) { + const listSchemaFieldValue = []; + for (const item of fieldValue) { + if (item['type'] == 'null') { + genAISchema['nullable'] = true; + continue; + } + listSchemaFieldValue.push(processJsonSchema(item)); + } + genAISchema[fieldName] = + listSchemaFieldValue; + } + else if (dictSchemaFieldNames.includes(fieldName)) { + const dictSchemaFieldValue = {}; + for (const [key, value] of Object.entries(fieldValue)) { + dictSchemaFieldValue[key] = processJsonSchema(value); + } + genAISchema[fieldName] = + dictSchemaFieldValue; + } + else { + // additionalProperties is not included in JSONSchema, skipping it. + if (fieldName === 'additionalProperties') { + continue; + } + genAISchema[fieldName] = fieldValue; + } + } + return genAISchema; +} +// we take the unknown in the schema field because we want enable user to pass +// the output of major schema declaration tools without casting. Tools such as +// zodToJsonSchema, typebox, zodToJsonSchema function can return JsonSchema7Type +// or object, see details in +// https://github.com/StefanTerdell/zod-to-json-schema/blob/70525efe555cd226691e093d171370a3b10921d1/src/zodToJsonSchema.ts#L7 +// typebox can return unknown, see details in +// https://github.com/sinclairzx81/typebox/blob/5a5431439f7d5ca6b494d0d18fbfd7b1a356d67c/src/type/create/type.ts#L35 +// Note: proper json schemas with the $schema field set never arrive to this +// transformer. Schemas with $schema are routed to the equivalent API json +// schema field. +function tSchema(schema) { + return processJsonSchema(schema); +} +function tSpeechConfig(speechConfig) { + if (typeof speechConfig === 'object') { + return speechConfig; + } + else if (typeof speechConfig === 'string') { + return { + voiceConfig: { + prebuiltVoiceConfig: { + voiceName: speechConfig, + }, + }, + }; + } + else { + throw new Error(`Unsupported speechConfig type: ${typeof speechConfig}`); + } +} +function tLiveSpeechConfig(speechConfig) { + if ('multiSpeakerVoiceConfig' in speechConfig) { + throw new Error('multiSpeakerVoiceConfig is not supported in the live API.'); + } + return speechConfig; +} +function tTool(tool) { + if (tool.functionDeclarations) { + for (const functionDeclaration of tool.functionDeclarations) { + if (functionDeclaration.parameters) { + if (!Object.keys(functionDeclaration.parameters).includes('$schema')) { + functionDeclaration.parameters = processJsonSchema(functionDeclaration.parameters); + } + else { + if (!functionDeclaration.parametersJsonSchema) { + functionDeclaration.parametersJsonSchema = + functionDeclaration.parameters; + delete functionDeclaration.parameters; + } + } + } + if (functionDeclaration.response) { + if (!Object.keys(functionDeclaration.response).includes('$schema')) { + functionDeclaration.response = processJsonSchema(functionDeclaration.response); + } + else { + if (!functionDeclaration.responseJsonSchema) { + functionDeclaration.responseJsonSchema = + functionDeclaration.response; + delete functionDeclaration.response; + } + } + } + } + } + return tool; +} +function tTools(tools) { + // Check if the incoming type is defined. + if (tools === undefined || tools === null) { + throw new Error('tools is required'); + } + if (!Array.isArray(tools)) { + throw new Error('tools is required and must be an array of Tools'); + } + const result = []; + for (const tool of tools) { + result.push(tool); + } + return result; +} +/** + * Prepends resource name with project, location, resource_prefix if needed. + * + * @param client The API client. + * @param resourceName The resource name. + * @param resourcePrefix The resource prefix. + * @param splitsAfterPrefix The number of splits after the prefix. + * @returns The completed resource name. + * + * Examples: + * + * ``` + * resource_name = '123' + * resource_prefix = 'cachedContents' + * splits_after_prefix = 1 + * client.vertexai = True + * client.project = 'bar' + * client.location = 'us-west1' + * _resource_name(client, resource_name, resource_prefix, splits_after_prefix) + * returns: 'projects/bar/locations/us-west1/cachedContents/123' + * ``` + * + * ``` + * resource_name = 'projects/foo/locations/us-central1/cachedContents/123' + * resource_prefix = 'cachedContents' + * splits_after_prefix = 1 + * client.vertexai = True + * client.project = 'bar' + * client.location = 'us-west1' + * _resource_name(client, resource_name, resource_prefix, splits_after_prefix) + * returns: 'projects/foo/locations/us-central1/cachedContents/123' + * ``` + * + * ``` + * resource_name = '123' + * resource_prefix = 'cachedContents' + * splits_after_prefix = 1 + * client.vertexai = False + * _resource_name(client, resource_name, resource_prefix, splits_after_prefix) + * returns 'cachedContents/123' + * ``` + * + * ``` + * resource_name = 'some/wrong/cachedContents/resource/name/123' + * resource_prefix = 'cachedContents' + * splits_after_prefix = 1 + * client.vertexai = False + * # client.vertexai = True + * _resource_name(client, resource_name, resource_prefix, splits_after_prefix) + * -> 'some/wrong/resource/name/123' + * ``` + */ +function resourceName(client, resourceName, resourcePrefix, splitsAfterPrefix = 1) { + const shouldAppendPrefix = !resourceName.startsWith(`${resourcePrefix}/`) && + resourceName.split('/').length === splitsAfterPrefix; + if (client.isVertexAI()) { + if (resourceName.startsWith('projects/')) { + return resourceName; + } + else if (resourceName.startsWith('locations/')) { + return `projects/${client.getProject()}/${resourceName}`; + } + else if (resourceName.startsWith(`${resourcePrefix}/`)) { + return `projects/${client.getProject()}/locations/${client.getLocation()}/${resourceName}`; + } + else if (shouldAppendPrefix) { + return `projects/${client.getProject()}/locations/${client.getLocation()}/${resourcePrefix}/${resourceName}`; + } + else { + return resourceName; + } + } + if (shouldAppendPrefix) { + return `${resourcePrefix}/${resourceName}`; + } + return resourceName; +} +function tCachedContentName(apiClient, name) { + if (typeof name !== 'string') { + throw new Error('name must be a string'); + } + return resourceName(apiClient, name, 'cachedContents'); +} +function tTuningJobStatus(status) { + switch (status) { + case 'STATE_UNSPECIFIED': + return 'JOB_STATE_UNSPECIFIED'; + case 'CREATING': + return 'JOB_STATE_RUNNING'; + case 'ACTIVE': + return 'JOB_STATE_SUCCEEDED'; + case 'FAILED': + return 'JOB_STATE_FAILED'; + default: + return status; + } +} +function tBytes(fromImageBytes) { + return tBytes$1(fromImageBytes); +} +function _isFile(origin) { + return (origin !== null && + origin !== undefined && + typeof origin === 'object' && + 'name' in origin); +} +function isGeneratedVideo(origin) { + return (origin !== null && + origin !== undefined && + typeof origin === 'object' && + 'video' in origin); +} +function isVideo(origin) { + return (origin !== null && + origin !== undefined && + typeof origin === 'object' && + 'uri' in origin); +} +function tFileName(fromName) { + var _a; + let name; + if (_isFile(fromName)) { + name = fromName.name; + } + if (isVideo(fromName)) { + name = fromName.uri; + if (name === undefined) { + return undefined; + } + } + if (isGeneratedVideo(fromName)) { + name = (_a = fromName.video) === null || _a === void 0 ? void 0 : _a.uri; + if (name === undefined) { + return undefined; + } + } + if (typeof fromName === 'string') { + name = fromName; + } + if (name === undefined) { + throw new Error('Could not extract file name from the provided input.'); + } + if (name.startsWith('https://')) { + const suffix = name.split('files/')[1]; + const match = suffix.match(/[a-z0-9]+/); + if (match === null) { + throw new Error(`Could not extract file name from URI ${name}`); + } + name = match[0]; + } + else if (name.startsWith('files/')) { + name = name.split('files/')[1]; + } + return name; +} +function tModelsUrl(apiClient, baseModels) { + let res; + if (apiClient.isVertexAI()) { + res = baseModels ? 'publishers/google/models' : 'models'; + } + else { + res = baseModels ? 'models' : 'tunedModels'; + } + return res; +} +function tExtractModels(response) { + for (const key of ['models', 'tunedModels', 'publisherModels']) { + if (hasField(response, key)) { + return response[key]; + } + } + return []; +} +function hasField(data, fieldName) { + return data !== null && typeof data === 'object' && fieldName in data; +} +function mcpToGeminiTool(mcpTool, config = {}) { + const mcpToolSchema = mcpTool; + const functionDeclaration = { + name: mcpToolSchema['name'], + description: mcpToolSchema['description'], + parametersJsonSchema: mcpToolSchema['inputSchema'], + }; + if (mcpToolSchema['outputSchema']) { + functionDeclaration['responseJsonSchema'] = mcpToolSchema['outputSchema']; + } + if (config.behavior) { + functionDeclaration['behavior'] = config.behavior; + } + const geminiTool = { + functionDeclarations: [ + functionDeclaration, + ], + }; + return geminiTool; +} +/** + * Converts a list of MCP tools to a single Gemini tool with a list of function + * declarations. + */ +function mcpToolsToGeminiTool(mcpTools, config = {}) { + const functionDeclarations = []; + const toolNames = new Set(); + for (const mcpTool of mcpTools) { + const mcpToolName = mcpTool.name; + if (toolNames.has(mcpToolName)) { + throw new Error(`Duplicate function name ${mcpToolName} found in MCP tools. Please ensure function names are unique.`); + } + toolNames.add(mcpToolName); + const geminiTool = mcpToGeminiTool(mcpTool, config); + if (geminiTool.functionDeclarations) { + functionDeclarations.push(...geminiTool.functionDeclarations); + } + } + return { functionDeclarations: functionDeclarations }; +} +// Transforms a source input into a BatchJobSource object with validation. +function tBatchJobSource(client, src) { + let sourceObj; + if (typeof src === 'string') { + if (client.isVertexAI()) { + if (src.startsWith('gs://')) { + sourceObj = { format: 'jsonl', gcsUri: [src] }; + } + else if (src.startsWith('bq://')) { + sourceObj = { format: 'bigquery', bigqueryUri: src }; + } + else { + throw new Error(`Unsupported string source for Vertex AI: ${src}`); + } + } + else { + // MLDEV + if (src.startsWith('files/')) { + sourceObj = { fileName: src }; // Default to fileName for string input + } + else { + throw new Error(`Unsupported string source for Gemini API: ${src}`); + } + } + } + else if (Array.isArray(src)) { + if (client.isVertexAI()) { + throw new Error('InlinedRequest[] is not supported in Vertex AI.'); + } + sourceObj = { inlinedRequests: src }; + } + else { + // It's already a BatchJobSource object + sourceObj = src; + } + // Validation logic + const vertexSourcesCount = [sourceObj.gcsUri, sourceObj.bigqueryUri].filter(Boolean).length; + const mldevSourcesCount = [ + sourceObj.inlinedRequests, + sourceObj.fileName, + ].filter(Boolean).length; + if (client.isVertexAI()) { + if (mldevSourcesCount > 0 || vertexSourcesCount !== 1) { + throw new Error('Exactly one of `gcsUri` or `bigqueryUri` must be set for Vertex AI.'); + } + } + else { + // MLDEV + if (vertexSourcesCount > 0 || mldevSourcesCount !== 1) { + throw new Error('Exactly one of `inlinedRequests`, `fileName`, ' + + 'must be set for Gemini API.'); + } + } + return sourceObj; +} +function tBatchJobDestination(dest) { + if (typeof dest !== 'string') { + return dest; + } + const destString = dest; + if (destString.startsWith('gs://')) { + return { + format: 'jsonl', + gcsUri: destString, + }; + } + else if (destString.startsWith('bq://')) { + return { + format: 'bigquery', + bigqueryUri: destString, + }; + } + else { + throw new Error(`Unsupported destination: ${destString}`); + } +} +function tRecvBatchJobDestination(dest) { + // Ensure dest is a non-null object before proceeding. + if (typeof dest !== 'object' || dest === null) { + // If the input is not an object, it cannot be a valid BatchJobDestination + // based on the operations performed. Return it cast, or handle as an error. + // Casting an empty object might be a safe default. + return {}; + } + // Cast to Record<string, unknown> to allow string property access. + const obj = dest; + // Safely access nested properties. + const inlineResponsesVal = obj['inlinedResponses']; + if (typeof inlineResponsesVal !== 'object' || inlineResponsesVal === null) { + return dest; + } + const inlineResponsesObj = inlineResponsesVal; + const responsesArray = inlineResponsesObj['inlinedResponses']; + if (!Array.isArray(responsesArray) || responsesArray.length === 0) { + return dest; + } + // Check if any response has the 'embedding' property. + let hasEmbedding = false; + for (const responseItem of responsesArray) { + if (typeof responseItem !== 'object' || responseItem === null) { + continue; + } + const responseItemObj = responseItem; + const responseVal = responseItemObj['response']; + if (typeof responseVal !== 'object' || responseVal === null) { + continue; + } + const responseObj = responseVal; + // Check for the existence of the 'embedding' key. + if (responseObj['embedding'] !== undefined) { + hasEmbedding = true; + break; + } + } + // Perform the transformation if an embedding was found. + if (hasEmbedding) { + obj['inlinedEmbedContentResponses'] = obj['inlinedResponses']; + delete obj['inlinedResponses']; + } + // Cast the (potentially) modified object to the target type. + return dest; +} +function tBatchJobName(apiClient, name) { + const nameString = name; + if (!apiClient.isVertexAI()) { + const mldevPattern = /batches\/[^/]+$/; + if (mldevPattern.test(nameString)) { + return nameString.split('/').pop(); + } + else { + throw new Error(`Invalid batch job name: ${nameString}.`); + } + } + const vertexPattern = /^projects\/[^/]+\/locations\/[^/]+\/batchPredictionJobs\/[^/]+$/; + if (vertexPattern.test(nameString)) { + return nameString.split('/').pop(); + } + else if (/^\d+$/.test(nameString)) { + return nameString; + } + else { + throw new Error(`Invalid batch job name: ${nameString}.`); + } +} +function tJobState(state) { + const stateString = state; + if (stateString === 'BATCH_STATE_UNSPECIFIED') { + return 'JOB_STATE_UNSPECIFIED'; + } + else if (stateString === 'BATCH_STATE_PENDING') { + return 'JOB_STATE_PENDING'; + } + else if (stateString === 'BATCH_STATE_RUNNING') { + return 'JOB_STATE_RUNNING'; + } + else if (stateString === 'BATCH_STATE_SUCCEEDED') { + return 'JOB_STATE_SUCCEEDED'; + } + else if (stateString === 'BATCH_STATE_FAILED') { + return 'JOB_STATE_FAILED'; + } + else if (stateString === 'BATCH_STATE_CANCELLED') { + return 'JOB_STATE_CANCELLED'; + } + else if (stateString === 'BATCH_STATE_EXPIRED') { + return 'JOB_STATE_EXPIRED'; + } + else { + return stateString; + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function batchJobDestinationFromMldev(fromObject) { + const toObject = {}; + const fromFileName = getValueByPath(fromObject, ['responsesFile']); + if (fromFileName != null) { + setValueByPath(toObject, ['fileName'], fromFileName); + } + const fromInlinedResponses = getValueByPath(fromObject, [ + 'inlinedResponses', + 'inlinedResponses', + ]); + if (fromInlinedResponses != null) { + let transformedList = fromInlinedResponses; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return inlinedResponseFromMldev(item); + }); + } + setValueByPath(toObject, ['inlinedResponses'], transformedList); + } + const fromInlinedEmbedContentResponses = getValueByPath(fromObject, [ + 'inlinedEmbedContentResponses', + 'inlinedResponses', + ]); + if (fromInlinedEmbedContentResponses != null) { + let transformedList = fromInlinedEmbedContentResponses; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['inlinedEmbedContentResponses'], transformedList); + } + return toObject; +} +function batchJobDestinationFromVertex(fromObject) { + const toObject = {}; + const fromFormat = getValueByPath(fromObject, ['predictionsFormat']); + if (fromFormat != null) { + setValueByPath(toObject, ['format'], fromFormat); + } + const fromGcsUri = getValueByPath(fromObject, [ + 'gcsDestination', + 'outputUriPrefix', + ]); + if (fromGcsUri != null) { + setValueByPath(toObject, ['gcsUri'], fromGcsUri); + } + const fromBigqueryUri = getValueByPath(fromObject, [ + 'bigqueryDestination', + 'outputUri', + ]); + if (fromBigqueryUri != null) { + setValueByPath(toObject, ['bigqueryUri'], fromBigqueryUri); + } + return toObject; +} +function batchJobDestinationToVertex(fromObject) { + const toObject = {}; + const fromFormat = getValueByPath(fromObject, ['format']); + if (fromFormat != null) { + setValueByPath(toObject, ['predictionsFormat'], fromFormat); + } + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (fromGcsUri != null) { + setValueByPath(toObject, ['gcsDestination', 'outputUriPrefix'], fromGcsUri); + } + const fromBigqueryUri = getValueByPath(fromObject, ['bigqueryUri']); + if (fromBigqueryUri != null) { + setValueByPath(toObject, ['bigqueryDestination', 'outputUri'], fromBigqueryUri); + } + if (getValueByPath(fromObject, ['fileName']) !== undefined) { + throw new Error('fileName parameter is not supported in Vertex AI.'); + } + if (getValueByPath(fromObject, ['inlinedResponses']) !== undefined) { + throw new Error('inlinedResponses parameter is not supported in Vertex AI.'); + } + if (getValueByPath(fromObject, ['inlinedEmbedContentResponses']) !== + undefined) { + throw new Error('inlinedEmbedContentResponses parameter is not supported in Vertex AI.'); + } + return toObject; +} +function batchJobFromMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromDisplayName = getValueByPath(fromObject, [ + 'metadata', + 'displayName', + ]); + if (fromDisplayName != null) { + setValueByPath(toObject, ['displayName'], fromDisplayName); + } + const fromState = getValueByPath(fromObject, ['metadata', 'state']); + if (fromState != null) { + setValueByPath(toObject, ['state'], tJobState(fromState)); + } + const fromCreateTime = getValueByPath(fromObject, [ + 'metadata', + 'createTime', + ]); + if (fromCreateTime != null) { + setValueByPath(toObject, ['createTime'], fromCreateTime); + } + const fromEndTime = getValueByPath(fromObject, [ + 'metadata', + 'endTime', + ]); + if (fromEndTime != null) { + setValueByPath(toObject, ['endTime'], fromEndTime); + } + const fromUpdateTime = getValueByPath(fromObject, [ + 'metadata', + 'updateTime', + ]); + if (fromUpdateTime != null) { + setValueByPath(toObject, ['updateTime'], fromUpdateTime); + } + const fromModel = getValueByPath(fromObject, ['metadata', 'model']); + if (fromModel != null) { + setValueByPath(toObject, ['model'], fromModel); + } + const fromDest = getValueByPath(fromObject, ['metadata', 'output']); + if (fromDest != null) { + setValueByPath(toObject, ['dest'], batchJobDestinationFromMldev(tRecvBatchJobDestination(fromDest))); + } + return toObject; +} +function batchJobFromVertex(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (fromDisplayName != null) { + setValueByPath(toObject, ['displayName'], fromDisplayName); + } + const fromState = getValueByPath(fromObject, ['state']); + if (fromState != null) { + setValueByPath(toObject, ['state'], tJobState(fromState)); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromCreateTime = getValueByPath(fromObject, ['createTime']); + if (fromCreateTime != null) { + setValueByPath(toObject, ['createTime'], fromCreateTime); + } + const fromStartTime = getValueByPath(fromObject, ['startTime']); + if (fromStartTime != null) { + setValueByPath(toObject, ['startTime'], fromStartTime); + } + const fromEndTime = getValueByPath(fromObject, ['endTime']); + if (fromEndTime != null) { + setValueByPath(toObject, ['endTime'], fromEndTime); + } + const fromUpdateTime = getValueByPath(fromObject, ['updateTime']); + if (fromUpdateTime != null) { + setValueByPath(toObject, ['updateTime'], fromUpdateTime); + } + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['model'], fromModel); + } + const fromSrc = getValueByPath(fromObject, ['inputConfig']); + if (fromSrc != null) { + setValueByPath(toObject, ['src'], batchJobSourceFromVertex(fromSrc)); + } + const fromDest = getValueByPath(fromObject, ['outputConfig']); + if (fromDest != null) { + setValueByPath(toObject, ['dest'], batchJobDestinationFromVertex(tRecvBatchJobDestination(fromDest))); + } + const fromCompletionStats = getValueByPath(fromObject, [ + 'completionStats', + ]); + if (fromCompletionStats != null) { + setValueByPath(toObject, ['completionStats'], fromCompletionStats); + } + return toObject; +} +function batchJobSourceFromVertex(fromObject) { + const toObject = {}; + const fromFormat = getValueByPath(fromObject, ['instancesFormat']); + if (fromFormat != null) { + setValueByPath(toObject, ['format'], fromFormat); + } + const fromGcsUri = getValueByPath(fromObject, ['gcsSource', 'uris']); + if (fromGcsUri != null) { + setValueByPath(toObject, ['gcsUri'], fromGcsUri); + } + const fromBigqueryUri = getValueByPath(fromObject, [ + 'bigquerySource', + 'inputUri', + ]); + if (fromBigqueryUri != null) { + setValueByPath(toObject, ['bigqueryUri'], fromBigqueryUri); + } + return toObject; +} +function batchJobSourceToMldev(apiClient, fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['format']) !== undefined) { + throw new Error('format parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['gcsUri']) !== undefined) { + throw new Error('gcsUri parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['bigqueryUri']) !== undefined) { + throw new Error('bigqueryUri parameter is not supported in Gemini API.'); + } + const fromFileName = getValueByPath(fromObject, ['fileName']); + if (fromFileName != null) { + setValueByPath(toObject, ['fileName'], fromFileName); + } + const fromInlinedRequests = getValueByPath(fromObject, [ + 'inlinedRequests', + ]); + if (fromInlinedRequests != null) { + let transformedList = fromInlinedRequests; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return inlinedRequestToMldev(apiClient, item); + }); + } + setValueByPath(toObject, ['requests', 'requests'], transformedList); + } + return toObject; +} +function batchJobSourceToVertex(fromObject) { + const toObject = {}; + const fromFormat = getValueByPath(fromObject, ['format']); + if (fromFormat != null) { + setValueByPath(toObject, ['instancesFormat'], fromFormat); + } + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (fromGcsUri != null) { + setValueByPath(toObject, ['gcsSource', 'uris'], fromGcsUri); + } + const fromBigqueryUri = getValueByPath(fromObject, ['bigqueryUri']); + if (fromBigqueryUri != null) { + setValueByPath(toObject, ['bigquerySource', 'inputUri'], fromBigqueryUri); + } + if (getValueByPath(fromObject, ['fileName']) !== undefined) { + throw new Error('fileName parameter is not supported in Vertex AI.'); + } + if (getValueByPath(fromObject, ['inlinedRequests']) !== undefined) { + throw new Error('inlinedRequests parameter is not supported in Vertex AI.'); + } + return toObject; +} +function blobToMldev$4(fromObject) { + const toObject = {}; + const fromData = getValueByPath(fromObject, ['data']); + if (fromData != null) { + setValueByPath(toObject, ['data'], fromData); + } + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function cancelBatchJobParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tBatchJobName(apiClient, fromName)); + } + return toObject; +} +function cancelBatchJobParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tBatchJobName(apiClient, fromName)); + } + return toObject; +} +function candidateFromMldev$1(fromObject) { + const toObject = {}; + const fromContent = getValueByPath(fromObject, ['content']); + if (fromContent != null) { + setValueByPath(toObject, ['content'], fromContent); + } + const fromCitationMetadata = getValueByPath(fromObject, [ + 'citationMetadata', + ]); + if (fromCitationMetadata != null) { + setValueByPath(toObject, ['citationMetadata'], citationMetadataFromMldev$1(fromCitationMetadata)); + } + const fromTokenCount = getValueByPath(fromObject, ['tokenCount']); + if (fromTokenCount != null) { + setValueByPath(toObject, ['tokenCount'], fromTokenCount); + } + const fromFinishReason = getValueByPath(fromObject, ['finishReason']); + if (fromFinishReason != null) { + setValueByPath(toObject, ['finishReason'], fromFinishReason); + } + const fromAvgLogprobs = getValueByPath(fromObject, ['avgLogprobs']); + if (fromAvgLogprobs != null) { + setValueByPath(toObject, ['avgLogprobs'], fromAvgLogprobs); + } + const fromGroundingMetadata = getValueByPath(fromObject, [ + 'groundingMetadata', + ]); + if (fromGroundingMetadata != null) { + setValueByPath(toObject, ['groundingMetadata'], fromGroundingMetadata); + } + const fromIndex = getValueByPath(fromObject, ['index']); + if (fromIndex != null) { + setValueByPath(toObject, ['index'], fromIndex); + } + const fromLogprobsResult = getValueByPath(fromObject, [ + 'logprobsResult', + ]); + if (fromLogprobsResult != null) { + setValueByPath(toObject, ['logprobsResult'], fromLogprobsResult); + } + const fromSafetyRatings = getValueByPath(fromObject, [ + 'safetyRatings', + ]); + if (fromSafetyRatings != null) { + let transformedList = fromSafetyRatings; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['safetyRatings'], transformedList); + } + const fromUrlContextMetadata = getValueByPath(fromObject, [ + 'urlContextMetadata', + ]); + if (fromUrlContextMetadata != null) { + setValueByPath(toObject, ['urlContextMetadata'], fromUrlContextMetadata); + } + return toObject; +} +function citationMetadataFromMldev$1(fromObject) { + const toObject = {}; + const fromCitations = getValueByPath(fromObject, ['citationSources']); + if (fromCitations != null) { + let transformedList = fromCitations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['citations'], transformedList); + } + return toObject; +} +function contentToMldev$4(fromObject) { + const toObject = {}; + const fromParts = getValueByPath(fromObject, ['parts']); + if (fromParts != null) { + let transformedList = fromParts; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return partToMldev$4(item); + }); + } + setValueByPath(toObject, ['parts'], transformedList); + } + const fromRole = getValueByPath(fromObject, ['role']); + if (fromRole != null) { + setValueByPath(toObject, ['role'], fromRole); + } + return toObject; +} +function createBatchJobConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['batch', 'displayName'], fromDisplayName); + } + if (getValueByPath(fromObject, ['dest']) !== undefined) { + throw new Error('dest parameter is not supported in Gemini API.'); + } + return toObject; +} +function createBatchJobConfigToVertex(fromObject, parentObject) { + const toObject = {}; + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromDisplayName); + } + const fromDest = getValueByPath(fromObject, ['dest']); + if (parentObject !== undefined && fromDest != null) { + setValueByPath(parentObject, ['outputConfig'], batchJobDestinationToVertex(tBatchJobDestination(fromDest))); + } + return toObject; +} +function createBatchJobParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromSrc = getValueByPath(fromObject, ['src']); + if (fromSrc != null) { + setValueByPath(toObject, ['batch', 'inputConfig'], batchJobSourceToMldev(apiClient, tBatchJobSource(apiClient, fromSrc))); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createBatchJobConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function createBatchJobParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['model'], tModel(apiClient, fromModel)); + } + const fromSrc = getValueByPath(fromObject, ['src']); + if (fromSrc != null) { + setValueByPath(toObject, ['inputConfig'], batchJobSourceToVertex(tBatchJobSource(apiClient, fromSrc))); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createBatchJobConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function createEmbeddingsBatchJobConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['batch', 'displayName'], fromDisplayName); + } + return toObject; +} +function createEmbeddingsBatchJobParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromSrc = getValueByPath(fromObject, ['src']); + if (fromSrc != null) { + setValueByPath(toObject, ['batch', 'inputConfig'], embeddingsBatchJobSourceToMldev(apiClient, fromSrc)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createEmbeddingsBatchJobConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function deleteBatchJobParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tBatchJobName(apiClient, fromName)); + } + return toObject; +} +function deleteBatchJobParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tBatchJobName(apiClient, fromName)); + } + return toObject; +} +function deleteResourceJobFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + return toObject; +} +function deleteResourceJobFromVertex(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + return toObject; +} +function embedContentBatchToMldev(apiClient, fromObject) { + const toObject = {}; + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContentsForEmbed(apiClient, fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['requests[]', 'request', 'content'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['_self'], embedContentConfigToMldev$1(fromConfig, toObject)); + moveValueByPath(toObject, { 'requests[].*': 'requests[].request.*' }); + } + return toObject; +} +function embedContentConfigToMldev$1(fromObject, parentObject) { + const toObject = {}; + const fromTaskType = getValueByPath(fromObject, ['taskType']); + if (parentObject !== undefined && fromTaskType != null) { + setValueByPath(parentObject, ['requests[]', 'taskType'], fromTaskType); + } + const fromTitle = getValueByPath(fromObject, ['title']); + if (parentObject !== undefined && fromTitle != null) { + setValueByPath(parentObject, ['requests[]', 'title'], fromTitle); + } + const fromOutputDimensionality = getValueByPath(fromObject, [ + 'outputDimensionality', + ]); + if (parentObject !== undefined && fromOutputDimensionality != null) { + setValueByPath(parentObject, ['requests[]', 'outputDimensionality'], fromOutputDimensionality); + } + if (getValueByPath(fromObject, ['mimeType']) !== undefined) { + throw new Error('mimeType parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['autoTruncate']) !== undefined) { + throw new Error('autoTruncate parameter is not supported in Gemini API.'); + } + return toObject; +} +function embeddingsBatchJobSourceToMldev(apiClient, fromObject) { + const toObject = {}; + const fromFileName = getValueByPath(fromObject, ['fileName']); + if (fromFileName != null) { + setValueByPath(toObject, ['file_name'], fromFileName); + } + const fromInlinedRequests = getValueByPath(fromObject, [ + 'inlinedRequests', + ]); + if (fromInlinedRequests != null) { + setValueByPath(toObject, ['requests'], embedContentBatchToMldev(apiClient, fromInlinedRequests)); + } + return toObject; +} +function fileDataToMldev$4(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromFileUri = getValueByPath(fromObject, ['fileUri']); + if (fromFileUri != null) { + setValueByPath(toObject, ['fileUri'], fromFileUri); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function functionCallToMldev$4(fromObject) { + const toObject = {}; + const fromId = getValueByPath(fromObject, ['id']); + if (fromId != null) { + setValueByPath(toObject, ['id'], fromId); + } + const fromArgs = getValueByPath(fromObject, ['args']); + if (fromArgs != null) { + setValueByPath(toObject, ['args'], fromArgs); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + if (getValueByPath(fromObject, ['partialArgs']) !== undefined) { + throw new Error('partialArgs parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['willContinue']) !== undefined) { + throw new Error('willContinue parameter is not supported in Gemini API.'); + } + return toObject; +} +function functionCallingConfigToMldev$2(fromObject) { + const toObject = {}; + const fromAllowedFunctionNames = getValueByPath(fromObject, [ + 'allowedFunctionNames', + ]); + if (fromAllowedFunctionNames != null) { + setValueByPath(toObject, ['allowedFunctionNames'], fromAllowedFunctionNames); + } + const fromMode = getValueByPath(fromObject, ['mode']); + if (fromMode != null) { + setValueByPath(toObject, ['mode'], fromMode); + } + if (getValueByPath(fromObject, ['streamFunctionCallArguments']) !== + undefined) { + throw new Error('streamFunctionCallArguments parameter is not supported in Gemini API.'); + } + return toObject; +} +function generateContentConfigToMldev$1(apiClient, fromObject, parentObject) { + const toObject = {}; + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['systemInstruction'], contentToMldev$4(tContent(fromSystemInstruction))); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (fromTemperature != null) { + setValueByPath(toObject, ['temperature'], fromTemperature); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (fromTopP != null) { + setValueByPath(toObject, ['topP'], fromTopP); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (fromTopK != null) { + setValueByPath(toObject, ['topK'], fromTopK); + } + const fromCandidateCount = getValueByPath(fromObject, [ + 'candidateCount', + ]); + if (fromCandidateCount != null) { + setValueByPath(toObject, ['candidateCount'], fromCandidateCount); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (fromMaxOutputTokens != null) { + setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens); + } + const fromStopSequences = getValueByPath(fromObject, [ + 'stopSequences', + ]); + if (fromStopSequences != null) { + setValueByPath(toObject, ['stopSequences'], fromStopSequences); + } + const fromResponseLogprobs = getValueByPath(fromObject, [ + 'responseLogprobs', + ]); + if (fromResponseLogprobs != null) { + setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs); + } + const fromLogprobs = getValueByPath(fromObject, ['logprobs']); + if (fromLogprobs != null) { + setValueByPath(toObject, ['logprobs'], fromLogprobs); + } + const fromPresencePenalty = getValueByPath(fromObject, [ + 'presencePenalty', + ]); + if (fromPresencePenalty != null) { + setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty); + } + const fromFrequencyPenalty = getValueByPath(fromObject, [ + 'frequencyPenalty', + ]); + if (fromFrequencyPenalty != null) { + setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (fromSeed != null) { + setValueByPath(toObject, ['seed'], fromSeed); + } + const fromResponseMimeType = getValueByPath(fromObject, [ + 'responseMimeType', + ]); + if (fromResponseMimeType != null) { + setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType); + } + const fromResponseSchema = getValueByPath(fromObject, [ + 'responseSchema', + ]); + if (fromResponseSchema != null) { + setValueByPath(toObject, ['responseSchema'], tSchema(fromResponseSchema)); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + if (getValueByPath(fromObject, ['routingConfig']) !== undefined) { + throw new Error('routingConfig parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['modelSelectionConfig']) !== undefined) { + throw new Error('modelSelectionConfig parameter is not supported in Gemini API.'); + } + const fromSafetySettings = getValueByPath(fromObject, [ + 'safetySettings', + ]); + if (parentObject !== undefined && fromSafetySettings != null) { + let transformedList = fromSafetySettings; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return safetySettingToMldev$1(item); + }); + } + setValueByPath(parentObject, ['safetySettings'], transformedList); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = tTools(fromTools); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToMldev$4(tTool(item)); + }); + } + setValueByPath(parentObject, ['tools'], transformedList); + } + const fromToolConfig = getValueByPath(fromObject, ['toolConfig']); + if (parentObject !== undefined && fromToolConfig != null) { + setValueByPath(parentObject, ['toolConfig'], toolConfigToMldev$2(fromToolConfig)); + } + if (getValueByPath(fromObject, ['labels']) !== undefined) { + throw new Error('labels parameter is not supported in Gemini API.'); + } + const fromCachedContent = getValueByPath(fromObject, [ + 'cachedContent', + ]); + if (parentObject !== undefined && fromCachedContent != null) { + setValueByPath(parentObject, ['cachedContent'], tCachedContentName(apiClient, fromCachedContent)); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (fromResponseModalities != null) { + setValueByPath(toObject, ['responseModalities'], fromResponseModalities); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (fromSpeechConfig != null) { + setValueByPath(toObject, ['speechConfig'], tSpeechConfig(fromSpeechConfig)); + } + if (getValueByPath(fromObject, ['audioTimestamp']) !== undefined) { + throw new Error('audioTimestamp parameter is not supported in Gemini API.'); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (fromThinkingConfig != null) { + setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig); + } + const fromImageConfig = getValueByPath(fromObject, ['imageConfig']); + if (fromImageConfig != null) { + setValueByPath(toObject, ['imageConfig'], imageConfigToMldev$1(fromImageConfig)); + } + const fromEnableEnhancedCivicAnswers = getValueByPath(fromObject, [ + 'enableEnhancedCivicAnswers', + ]); + if (fromEnableEnhancedCivicAnswers != null) { + setValueByPath(toObject, ['enableEnhancedCivicAnswers'], fromEnableEnhancedCivicAnswers); + } + if (getValueByPath(fromObject, ['modelArmorConfig']) !== undefined) { + throw new Error('modelArmorConfig parameter is not supported in Gemini API.'); + } + return toObject; +} +function generateContentResponseFromMldev$1(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromCandidates = getValueByPath(fromObject, ['candidates']); + if (fromCandidates != null) { + let transformedList = fromCandidates; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return candidateFromMldev$1(item); + }); + } + setValueByPath(toObject, ['candidates'], transformedList); + } + const fromModelVersion = getValueByPath(fromObject, ['modelVersion']); + if (fromModelVersion != null) { + setValueByPath(toObject, ['modelVersion'], fromModelVersion); + } + const fromPromptFeedback = getValueByPath(fromObject, [ + 'promptFeedback', + ]); + if (fromPromptFeedback != null) { + setValueByPath(toObject, ['promptFeedback'], fromPromptFeedback); + } + const fromResponseId = getValueByPath(fromObject, ['responseId']); + if (fromResponseId != null) { + setValueByPath(toObject, ['responseId'], fromResponseId); + } + const fromUsageMetadata = getValueByPath(fromObject, [ + 'usageMetadata', + ]); + if (fromUsageMetadata != null) { + setValueByPath(toObject, ['usageMetadata'], fromUsageMetadata); + } + return toObject; +} +function getBatchJobParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tBatchJobName(apiClient, fromName)); + } + return toObject; +} +function getBatchJobParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tBatchJobName(apiClient, fromName)); + } + return toObject; +} +function googleMapsToMldev$4(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['authConfig']) !== undefined) { + throw new Error('authConfig parameter is not supported in Gemini API.'); + } + const fromEnableWidget = getValueByPath(fromObject, ['enableWidget']); + if (fromEnableWidget != null) { + setValueByPath(toObject, ['enableWidget'], fromEnableWidget); + } + return toObject; +} +function googleSearchToMldev$4(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['excludeDomains']) !== undefined) { + throw new Error('excludeDomains parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['blockingConfidence']) !== undefined) { + throw new Error('blockingConfidence parameter is not supported in Gemini API.'); + } + const fromTimeRangeFilter = getValueByPath(fromObject, [ + 'timeRangeFilter', + ]); + if (fromTimeRangeFilter != null) { + setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter); + } + return toObject; +} +function imageConfigToMldev$1(fromObject) { + const toObject = {}; + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (fromAspectRatio != null) { + setValueByPath(toObject, ['aspectRatio'], fromAspectRatio); + } + const fromImageSize = getValueByPath(fromObject, ['imageSize']); + if (fromImageSize != null) { + setValueByPath(toObject, ['imageSize'], fromImageSize); + } + if (getValueByPath(fromObject, ['personGeneration']) !== undefined) { + throw new Error('personGeneration parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['outputMimeType']) !== undefined) { + throw new Error('outputMimeType parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['outputCompressionQuality']) !== + undefined) { + throw new Error('outputCompressionQuality parameter is not supported in Gemini API.'); + } + return toObject; +} +function inlinedRequestToMldev(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['request', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return contentToMldev$4(item); + }); + } + setValueByPath(toObject, ['request', 'contents'], transformedList); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['request', 'generationConfig'], generateContentConfigToMldev$1(apiClient, fromConfig, getValueByPath(toObject, ['request'], {}))); + } + return toObject; +} +function inlinedResponseFromMldev(fromObject) { + const toObject = {}; + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], generateContentResponseFromMldev$1(fromResponse)); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + return toObject; +} +function listBatchJobsConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + if (getValueByPath(fromObject, ['filter']) !== undefined) { + throw new Error('filter parameter is not supported in Gemini API.'); + } + return toObject; +} +function listBatchJobsConfigToVertex(fromObject, parentObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + const fromFilter = getValueByPath(fromObject, ['filter']); + if (parentObject !== undefined && fromFilter != null) { + setValueByPath(parentObject, ['_query', 'filter'], fromFilter); + } + return toObject; +} +function listBatchJobsParametersToMldev(fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listBatchJobsConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function listBatchJobsParametersToVertex(fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listBatchJobsConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function listBatchJobsResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromBatchJobs = getValueByPath(fromObject, ['operations']); + if (fromBatchJobs != null) { + let transformedList = fromBatchJobs; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return batchJobFromMldev(item); + }); + } + setValueByPath(toObject, ['batchJobs'], transformedList); + } + return toObject; +} +function listBatchJobsResponseFromVertex(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromBatchJobs = getValueByPath(fromObject, [ + 'batchPredictionJobs', + ]); + if (fromBatchJobs != null) { + let transformedList = fromBatchJobs; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return batchJobFromVertex(item); + }); + } + setValueByPath(toObject, ['batchJobs'], transformedList); + } + return toObject; +} +function partToMldev$4(fromObject) { + const toObject = {}; + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromCodeExecutionResult = getValueByPath(fromObject, [ + 'codeExecutionResult', + ]); + if (fromCodeExecutionResult != null) { + setValueByPath(toObject, ['codeExecutionResult'], fromCodeExecutionResult); + } + const fromExecutableCode = getValueByPath(fromObject, [ + 'executableCode', + ]); + if (fromExecutableCode != null) { + setValueByPath(toObject, ['executableCode'], fromExecutableCode); + } + const fromFileData = getValueByPath(fromObject, ['fileData']); + if (fromFileData != null) { + setValueByPath(toObject, ['fileData'], fileDataToMldev$4(fromFileData)); + } + const fromFunctionCall = getValueByPath(fromObject, ['functionCall']); + if (fromFunctionCall != null) { + setValueByPath(toObject, ['functionCall'], functionCallToMldev$4(fromFunctionCall)); + } + const fromFunctionResponse = getValueByPath(fromObject, [ + 'functionResponse', + ]); + if (fromFunctionResponse != null) { + setValueByPath(toObject, ['functionResponse'], fromFunctionResponse); + } + const fromInlineData = getValueByPath(fromObject, ['inlineData']); + if (fromInlineData != null) { + setValueByPath(toObject, ['inlineData'], blobToMldev$4(fromInlineData)); + } + const fromText = getValueByPath(fromObject, ['text']); + if (fromText != null) { + setValueByPath(toObject, ['text'], fromText); + } + const fromThought = getValueByPath(fromObject, ['thought']); + if (fromThought != null) { + setValueByPath(toObject, ['thought'], fromThought); + } + const fromThoughtSignature = getValueByPath(fromObject, [ + 'thoughtSignature', + ]); + if (fromThoughtSignature != null) { + setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature); + } + const fromVideoMetadata = getValueByPath(fromObject, [ + 'videoMetadata', + ]); + if (fromVideoMetadata != null) { + setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata); + } + return toObject; +} +function safetySettingToMldev$1(fromObject) { + const toObject = {}; + const fromCategory = getValueByPath(fromObject, ['category']); + if (fromCategory != null) { + setValueByPath(toObject, ['category'], fromCategory); + } + if (getValueByPath(fromObject, ['method']) !== undefined) { + throw new Error('method parameter is not supported in Gemini API.'); + } + const fromThreshold = getValueByPath(fromObject, ['threshold']); + if (fromThreshold != null) { + setValueByPath(toObject, ['threshold'], fromThreshold); + } + return toObject; +} +function toolConfigToMldev$2(fromObject) { + const toObject = {}; + const fromRetrievalConfig = getValueByPath(fromObject, [ + 'retrievalConfig', + ]); + if (fromRetrievalConfig != null) { + setValueByPath(toObject, ['retrievalConfig'], fromRetrievalConfig); + } + const fromFunctionCallingConfig = getValueByPath(fromObject, [ + 'functionCallingConfig', + ]); + if (fromFunctionCallingConfig != null) { + setValueByPath(toObject, ['functionCallingConfig'], functionCallingConfigToMldev$2(fromFunctionCallingConfig)); + } + return toObject; +} +function toolToMldev$4(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['retrieval']) !== undefined) { + throw new Error('retrieval parameter is not supported in Gemini API.'); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + const fromFileSearch = getValueByPath(fromObject, ['fileSearch']); + if (fromFileSearch != null) { + setValueByPath(toObject, ['fileSearch'], fromFileSearch); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + if (getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined) { + throw new Error('enterpriseWebSearch parameter is not supported in Gemini API.'); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], googleMapsToMldev$4(fromGoogleMaps)); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], googleSearchToMldev$4(fromGoogleSearch)); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +exports.PagedItem = void 0; +(function (PagedItem) { + PagedItem["PAGED_ITEM_BATCH_JOBS"] = "batchJobs"; + PagedItem["PAGED_ITEM_MODELS"] = "models"; + PagedItem["PAGED_ITEM_TUNING_JOBS"] = "tuningJobs"; + PagedItem["PAGED_ITEM_FILES"] = "files"; + PagedItem["PAGED_ITEM_CACHED_CONTENTS"] = "cachedContents"; + PagedItem["PAGED_ITEM_FILE_SEARCH_STORES"] = "fileSearchStores"; + PagedItem["PAGED_ITEM_DOCUMENTS"] = "documents"; +})(exports.PagedItem || (exports.PagedItem = {})); +/** + * Pager class for iterating through paginated results. + */ +class Pager { + constructor(name, request, response, params) { + this.pageInternal = []; + this.paramsInternal = {}; + this.requestInternal = request; + this.init(name, response, params); + } + init(name, response, params) { + var _a, _b; + this.nameInternal = name; + this.pageInternal = response[this.nameInternal] || []; + this.sdkHttpResponseInternal = response === null || response === void 0 ? void 0 : response.sdkHttpResponse; + this.idxInternal = 0; + let requestParams = { config: {} }; + if (!params || Object.keys(params).length === 0) { + requestParams = { config: {} }; + } + else if (typeof params === 'object') { + requestParams = Object.assign({}, params); + } + else { + requestParams = params; + } + if (requestParams['config']) { + requestParams['config']['pageToken'] = response['nextPageToken']; + } + this.paramsInternal = requestParams; + this.pageInternalSize = + (_b = (_a = requestParams['config']) === null || _a === void 0 ? void 0 : _a['pageSize']) !== null && _b !== void 0 ? _b : this.pageInternal.length; + } + initNextPage(response) { + this.init(this.nameInternal, response, this.paramsInternal); + } + /** + * Returns the current page, which is a list of items. + * + * @remarks + * The first page is retrieved when the pager is created. The returned list of + * items could be a subset of the entire list. + */ + get page() { + return this.pageInternal; + } + /** + * Returns the type of paged item (for example, ``batch_jobs``). + */ + get name() { + return this.nameInternal; + } + /** + * Returns the length of the page fetched each time by this pager. + * + * @remarks + * The number of items in the page is less than or equal to the page length. + */ + get pageSize() { + return this.pageInternalSize; + } + /** + * Returns the headers of the API response. + */ + get sdkHttpResponse() { + return this.sdkHttpResponseInternal; + } + /** + * Returns the parameters when making the API request for the next page. + * + * @remarks + * Parameters contain a set of optional configs that can be + * used to customize the API request. For example, the `pageToken` parameter + * contains the token to request the next page. + */ + get params() { + return this.paramsInternal; + } + /** + * Returns the total number of items in the current page. + */ + get pageLength() { + return this.pageInternal.length; + } + /** + * Returns the item at the given index. + */ + getItem(index) { + return this.pageInternal[index]; + } + /** + * Returns an async iterator that support iterating through all items + * retrieved from the API. + * + * @remarks + * The iterator will automatically fetch the next page if there are more items + * to fetch from the API. + * + * @example + * + * ```ts + * const pager = await ai.files.list({config: {pageSize: 10}}); + * for await (const file of pager) { + * console.log(file.name); + * } + * ``` + */ + [Symbol.asyncIterator]() { + return { + next: async () => { + if (this.idxInternal >= this.pageLength) { + if (this.hasNextPage()) { + await this.nextPage(); + } + else { + return { value: undefined, done: true }; + } + } + const item = this.getItem(this.idxInternal); + this.idxInternal += 1; + return { value: item, done: false }; + }, + return: async () => { + return { value: undefined, done: true }; + }, + }; + } + /** + * Fetches the next page of items. This makes a new API request. + * + * @throws {Error} If there are no more pages to fetch. + * + * @example + * + * ```ts + * const pager = await ai.files.list({config: {pageSize: 10}}); + * let page = pager.page; + * while (true) { + * for (const file of page) { + * console.log(file.name); + * } + * if (!pager.hasNextPage()) { + * break; + * } + * page = await pager.nextPage(); + * } + * ``` + */ + async nextPage() { + if (!this.hasNextPage()) { + throw new Error('No more pages to fetch.'); + } + const response = await this.requestInternal(this.params); + this.initNextPage(response); + return this.page; + } + /** + * Returns true if there are more pages to fetch from the API. + */ + hasNextPage() { + var _a; + if (((_a = this.params['config']) === null || _a === void 0 ? void 0 : _a['pageToken']) !== undefined) { + return true; + } + return false; + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Batches extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + /** + * Lists batch jobs. + * + * @param params - The parameters for the list request. + * @return - A pager of batch jobs. + * + * @example + * ```ts + * const batchJobs = await ai.batches.list({config: {'pageSize': 2}}); + * for await (const batchJob of batchJobs) { + * console.log(batchJob); + * } + * ``` + */ + this.list = async (params = {}) => { + return new Pager(exports.PagedItem.PAGED_ITEM_BATCH_JOBS, (x) => this.listInternal(x), await this.listInternal(params), params); + }; + /** + * Create batch job. + * + * @param params - The parameters for create batch job request. + * @return The created batch job. + * + * @example + * ```ts + * const response = await ai.batches.create({ + * model: 'gemini-2.0-flash', + * src: {gcsUri: 'gs://bucket/path/to/file.jsonl', format: 'jsonl'}, + * config: { + * dest: {gcsUri: 'gs://bucket/path/output/directory', format: 'jsonl'}, + * } + * }); + * console.log(response); + * ``` + */ + this.create = async (params) => { + if (this.apiClient.isVertexAI()) { + // Format destination if not provided + // Cast params.src as Vertex AI path does not handle InlinedRequest[] + params.config = this.formatDestination(params.src, params.config); + } + return this.createInternal(params); + }; + /** + * **Experimental** Creates an embedding batch job. + * + * @param params - The parameters for create embedding batch job request. + * @return The created batch job. + * + * @example + * ```ts + * const response = await ai.batches.createEmbeddings({ + * model: 'text-embedding-004', + * src: {fileName: 'files/my_embedding_input'}, + * }); + * console.log(response); + * ``` + */ + this.createEmbeddings = async (params) => { + console.warn('batches.createEmbeddings() is experimental and may change without notice.'); + if (this.apiClient.isVertexAI()) { + throw new Error('Vertex AI does not support batches.createEmbeddings.'); + } + return this.createEmbeddingsInternal(params); + }; + } + // Helper function to handle inlined generate content requests + createInlinedGenerateContentRequest(params) { + const body = createBatchJobParametersToMldev(this.apiClient, // Use instance apiClient + params); + const urlParams = body['_url']; + const path = formatMap('{model}:batchGenerateContent', urlParams); + const batch = body['batch']; + const inputConfig = batch['inputConfig']; + const requestsWrapper = inputConfig['requests']; + const requests = requestsWrapper['requests']; + const newRequests = []; + for (const request of requests) { + const requestDict = Object.assign({}, request); // Clone + if (requestDict['systemInstruction']) { + const systemInstructionValue = requestDict['systemInstruction']; + delete requestDict['systemInstruction']; + const requestContent = requestDict['request']; + requestContent['systemInstruction'] = systemInstructionValue; + requestDict['request'] = requestContent; + } + newRequests.push(requestDict); + } + requestsWrapper['requests'] = newRequests; + delete body['config']; + delete body['_url']; + delete body['_query']; + return { path, body }; + } + // Helper function to get the first GCS URI + getGcsUri(src) { + if (typeof src === 'string') { + return src.startsWith('gs://') ? src : undefined; + } + if (!Array.isArray(src) && src.gcsUri && src.gcsUri.length > 0) { + return src.gcsUri[0]; + } + return undefined; + } + // Helper function to get the BigQuery URI + getBigqueryUri(src) { + if (typeof src === 'string') { + return src.startsWith('bq://') ? src : undefined; + } + if (!Array.isArray(src)) { + return src.bigqueryUri; + } + return undefined; + } + // Function to format the destination configuration for Vertex AI + formatDestination(src, config) { + const newConfig = config ? Object.assign({}, config) : {}; + const timestampStr = Date.now().toString(); + if (!newConfig.displayName) { + newConfig.displayName = `genaiBatchJob_${timestampStr}`; + } + if (newConfig.dest === undefined) { + const gcsUri = this.getGcsUri(src); + const bigqueryUri = this.getBigqueryUri(src); + if (gcsUri) { + if (gcsUri.endsWith('.jsonl')) { + // For .jsonl files, remove suffix and add /dest + newConfig.dest = `${gcsUri.slice(0, -6)}/dest`; + } + else { + // Fallback for other GCS URIs + newConfig.dest = `${gcsUri}_dest_${timestampStr}`; + } + } + else if (bigqueryUri) { + newConfig.dest = `${bigqueryUri}_dest_${timestampStr}`; + } + else { + throw new Error('Unsupported source for Vertex AI: No GCS or BigQuery URI found.'); + } + } + return newConfig; + } + /** + * Internal method to create batch job. + * + * @param params - The parameters for create batch job request. + * @return The created batch job. + * + */ + async createInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = createBatchJobParametersToVertex(this.apiClient, params); + path = formatMap('batchPredictionJobs', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = batchJobFromVertex(apiResponse); + return resp; + }); + } + else { + const body = createBatchJobParametersToMldev(this.apiClient, params); + path = formatMap('{model}:batchGenerateContent', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = batchJobFromMldev(apiResponse); + return resp; + }); + } + } + /** + * Internal method to create batch job. + * + * @param params - The parameters for create batch job request. + * @return The created batch job. + * + */ + async createEmbeddingsInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = createEmbeddingsBatchJobParametersToMldev(this.apiClient, params); + path = formatMap('{model}:asyncBatchEmbedContent', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = batchJobFromMldev(apiResponse); + return resp; + }); + } + } + /** + * Gets batch job configurations. + * + * @param params - The parameters for the get request. + * @return The batch job. + * + * @example + * ```ts + * await ai.batches.get({name: '...'}); // The server-generated resource name. + * ``` + */ + async get(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = getBatchJobParametersToVertex(this.apiClient, params); + path = formatMap('batchPredictionJobs/{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = batchJobFromVertex(apiResponse); + return resp; + }); + } + else { + const body = getBatchJobParametersToMldev(this.apiClient, params); + path = formatMap('batches/{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = batchJobFromMldev(apiResponse); + return resp; + }); + } + } + /** + * Cancels a batch job. + * + * @param params - The parameters for the cancel request. + * @return The empty response returned by the API. + * + * @example + * ```ts + * await ai.batches.cancel({name: '...'}); // The server-generated resource name. + * ``` + */ + async cancel(params) { + var _a, _b, _c, _d; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = cancelBatchJobParametersToVertex(this.apiClient, params); + path = formatMap('batchPredictionJobs/{name}:cancel', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + await this.apiClient.request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }); + } + else { + const body = cancelBatchJobParametersToMldev(this.apiClient, params); + path = formatMap('batches/{name}:cancel', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + await this.apiClient.request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }); + } + } + async listInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = listBatchJobsParametersToVertex(params); + path = formatMap('batchPredictionJobs', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listBatchJobsResponseFromVertex(apiResponse); + const typedResp = new ListBatchJobsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = listBatchJobsParametersToMldev(params); + path = formatMap('batches', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listBatchJobsResponseFromMldev(apiResponse); + const typedResp = new ListBatchJobsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Deletes a batch job. + * + * @param params - The parameters for the delete request. + * @return The empty response returned by the API. + * + * @example + * ```ts + * await ai.batches.delete({name: '...'}); // The server-generated resource name. + * ``` + */ + async delete(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = deleteBatchJobParametersToVertex(this.apiClient, params); + path = formatMap('batchPredictionJobs/{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = deleteResourceJobFromVertex(apiResponse); + return resp; + }); + } + else { + const body = deleteBatchJobParametersToMldev(this.apiClient, params); + path = formatMap('batches/{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = deleteResourceJobFromMldev(apiResponse); + return resp; + }); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function blobToMldev$3(fromObject) { + const toObject = {}; + const fromData = getValueByPath(fromObject, ['data']); + if (fromData != null) { + setValueByPath(toObject, ['data'], fromData); + } + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function contentToMldev$3(fromObject) { + const toObject = {}; + const fromParts = getValueByPath(fromObject, ['parts']); + if (fromParts != null) { + let transformedList = fromParts; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return partToMldev$3(item); + }); + } + setValueByPath(toObject, ['parts'], transformedList); + } + const fromRole = getValueByPath(fromObject, ['role']); + if (fromRole != null) { + setValueByPath(toObject, ['role'], fromRole); + } + return toObject; +} +function createCachedContentConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromTtl = getValueByPath(fromObject, ['ttl']); + if (parentObject !== undefined && fromTtl != null) { + setValueByPath(parentObject, ['ttl'], fromTtl); + } + const fromExpireTime = getValueByPath(fromObject, ['expireTime']); + if (parentObject !== undefined && fromExpireTime != null) { + setValueByPath(parentObject, ['expireTime'], fromExpireTime); + } + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromDisplayName); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (parentObject !== undefined && fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return contentToMldev$3(item); + }); + } + setValueByPath(parentObject, ['contents'], transformedList); + } + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['systemInstruction'], contentToMldev$3(tContent(fromSystemInstruction))); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = fromTools; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToMldev$3(item); + }); + } + setValueByPath(parentObject, ['tools'], transformedList); + } + const fromToolConfig = getValueByPath(fromObject, ['toolConfig']); + if (parentObject !== undefined && fromToolConfig != null) { + setValueByPath(parentObject, ['toolConfig'], toolConfigToMldev$1(fromToolConfig)); + } + if (getValueByPath(fromObject, ['kmsKeyName']) !== undefined) { + throw new Error('kmsKeyName parameter is not supported in Gemini API.'); + } + return toObject; +} +function createCachedContentConfigToVertex(fromObject, parentObject) { + const toObject = {}; + const fromTtl = getValueByPath(fromObject, ['ttl']); + if (parentObject !== undefined && fromTtl != null) { + setValueByPath(parentObject, ['ttl'], fromTtl); + } + const fromExpireTime = getValueByPath(fromObject, ['expireTime']); + if (parentObject !== undefined && fromExpireTime != null) { + setValueByPath(parentObject, ['expireTime'], fromExpireTime); + } + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromDisplayName); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (parentObject !== undefined && fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(parentObject, ['contents'], transformedList); + } + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['systemInstruction'], tContent(fromSystemInstruction)); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = fromTools; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToVertex$2(item); + }); + } + setValueByPath(parentObject, ['tools'], transformedList); + } + const fromToolConfig = getValueByPath(fromObject, ['toolConfig']); + if (parentObject !== undefined && fromToolConfig != null) { + setValueByPath(parentObject, ['toolConfig'], fromToolConfig); + } + const fromKmsKeyName = getValueByPath(fromObject, ['kmsKeyName']); + if (parentObject !== undefined && fromKmsKeyName != null) { + setValueByPath(parentObject, ['encryption_spec', 'kmsKeyName'], fromKmsKeyName); + } + return toObject; +} +function createCachedContentParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['model'], tCachesModel(apiClient, fromModel)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createCachedContentConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function createCachedContentParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['model'], tCachesModel(apiClient, fromModel)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createCachedContentConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function deleteCachedContentParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tCachedContentName(apiClient, fromName)); + } + return toObject; +} +function deleteCachedContentParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tCachedContentName(apiClient, fromName)); + } + return toObject; +} +function deleteCachedContentResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function deleteCachedContentResponseFromVertex(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function fileDataToMldev$3(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromFileUri = getValueByPath(fromObject, ['fileUri']); + if (fromFileUri != null) { + setValueByPath(toObject, ['fileUri'], fromFileUri); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function functionCallToMldev$3(fromObject) { + const toObject = {}; + const fromId = getValueByPath(fromObject, ['id']); + if (fromId != null) { + setValueByPath(toObject, ['id'], fromId); + } + const fromArgs = getValueByPath(fromObject, ['args']); + if (fromArgs != null) { + setValueByPath(toObject, ['args'], fromArgs); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + if (getValueByPath(fromObject, ['partialArgs']) !== undefined) { + throw new Error('partialArgs parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['willContinue']) !== undefined) { + throw new Error('willContinue parameter is not supported in Gemini API.'); + } + return toObject; +} +function functionCallingConfigToMldev$1(fromObject) { + const toObject = {}; + const fromAllowedFunctionNames = getValueByPath(fromObject, [ + 'allowedFunctionNames', + ]); + if (fromAllowedFunctionNames != null) { + setValueByPath(toObject, ['allowedFunctionNames'], fromAllowedFunctionNames); + } + const fromMode = getValueByPath(fromObject, ['mode']); + if (fromMode != null) { + setValueByPath(toObject, ['mode'], fromMode); + } + if (getValueByPath(fromObject, ['streamFunctionCallArguments']) !== + undefined) { + throw new Error('streamFunctionCallArguments parameter is not supported in Gemini API.'); + } + return toObject; +} +function functionDeclarationToVertex$2(fromObject) { + const toObject = {}; + const fromDescription = getValueByPath(fromObject, ['description']); + if (fromDescription != null) { + setValueByPath(toObject, ['description'], fromDescription); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromParameters = getValueByPath(fromObject, ['parameters']); + if (fromParameters != null) { + setValueByPath(toObject, ['parameters'], fromParameters); + } + const fromParametersJsonSchema = getValueByPath(fromObject, [ + 'parametersJsonSchema', + ]); + if (fromParametersJsonSchema != null) { + setValueByPath(toObject, ['parametersJsonSchema'], fromParametersJsonSchema); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], fromResponse); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + if (getValueByPath(fromObject, ['behavior']) !== undefined) { + throw new Error('behavior parameter is not supported in Vertex AI.'); + } + return toObject; +} +function getCachedContentParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tCachedContentName(apiClient, fromName)); + } + return toObject; +} +function getCachedContentParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tCachedContentName(apiClient, fromName)); + } + return toObject; +} +function googleMapsToMldev$3(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['authConfig']) !== undefined) { + throw new Error('authConfig parameter is not supported in Gemini API.'); + } + const fromEnableWidget = getValueByPath(fromObject, ['enableWidget']); + if (fromEnableWidget != null) { + setValueByPath(toObject, ['enableWidget'], fromEnableWidget); + } + return toObject; +} +function googleSearchToMldev$3(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['excludeDomains']) !== undefined) { + throw new Error('excludeDomains parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['blockingConfidence']) !== undefined) { + throw new Error('blockingConfidence parameter is not supported in Gemini API.'); + } + const fromTimeRangeFilter = getValueByPath(fromObject, [ + 'timeRangeFilter', + ]); + if (fromTimeRangeFilter != null) { + setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter); + } + return toObject; +} +function listCachedContentsConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + return toObject; +} +function listCachedContentsConfigToVertex(fromObject, parentObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + return toObject; +} +function listCachedContentsParametersToMldev(fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listCachedContentsConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function listCachedContentsParametersToVertex(fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listCachedContentsConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function listCachedContentsResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromCachedContents = getValueByPath(fromObject, [ + 'cachedContents', + ]); + if (fromCachedContents != null) { + let transformedList = fromCachedContents; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['cachedContents'], transformedList); + } + return toObject; +} +function listCachedContentsResponseFromVertex(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromCachedContents = getValueByPath(fromObject, [ + 'cachedContents', + ]); + if (fromCachedContents != null) { + let transformedList = fromCachedContents; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['cachedContents'], transformedList); + } + return toObject; +} +function partToMldev$3(fromObject) { + const toObject = {}; + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromCodeExecutionResult = getValueByPath(fromObject, [ + 'codeExecutionResult', + ]); + if (fromCodeExecutionResult != null) { + setValueByPath(toObject, ['codeExecutionResult'], fromCodeExecutionResult); + } + const fromExecutableCode = getValueByPath(fromObject, [ + 'executableCode', + ]); + if (fromExecutableCode != null) { + setValueByPath(toObject, ['executableCode'], fromExecutableCode); + } + const fromFileData = getValueByPath(fromObject, ['fileData']); + if (fromFileData != null) { + setValueByPath(toObject, ['fileData'], fileDataToMldev$3(fromFileData)); + } + const fromFunctionCall = getValueByPath(fromObject, ['functionCall']); + if (fromFunctionCall != null) { + setValueByPath(toObject, ['functionCall'], functionCallToMldev$3(fromFunctionCall)); + } + const fromFunctionResponse = getValueByPath(fromObject, [ + 'functionResponse', + ]); + if (fromFunctionResponse != null) { + setValueByPath(toObject, ['functionResponse'], fromFunctionResponse); + } + const fromInlineData = getValueByPath(fromObject, ['inlineData']); + if (fromInlineData != null) { + setValueByPath(toObject, ['inlineData'], blobToMldev$3(fromInlineData)); + } + const fromText = getValueByPath(fromObject, ['text']); + if (fromText != null) { + setValueByPath(toObject, ['text'], fromText); + } + const fromThought = getValueByPath(fromObject, ['thought']); + if (fromThought != null) { + setValueByPath(toObject, ['thought'], fromThought); + } + const fromThoughtSignature = getValueByPath(fromObject, [ + 'thoughtSignature', + ]); + if (fromThoughtSignature != null) { + setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature); + } + const fromVideoMetadata = getValueByPath(fromObject, [ + 'videoMetadata', + ]); + if (fromVideoMetadata != null) { + setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata); + } + return toObject; +} +function toolConfigToMldev$1(fromObject) { + const toObject = {}; + const fromRetrievalConfig = getValueByPath(fromObject, [ + 'retrievalConfig', + ]); + if (fromRetrievalConfig != null) { + setValueByPath(toObject, ['retrievalConfig'], fromRetrievalConfig); + } + const fromFunctionCallingConfig = getValueByPath(fromObject, [ + 'functionCallingConfig', + ]); + if (fromFunctionCallingConfig != null) { + setValueByPath(toObject, ['functionCallingConfig'], functionCallingConfigToMldev$1(fromFunctionCallingConfig)); + } + return toObject; +} +function toolToMldev$3(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['retrieval']) !== undefined) { + throw new Error('retrieval parameter is not supported in Gemini API.'); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + const fromFileSearch = getValueByPath(fromObject, ['fileSearch']); + if (fromFileSearch != null) { + setValueByPath(toObject, ['fileSearch'], fromFileSearch); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + if (getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined) { + throw new Error('enterpriseWebSearch parameter is not supported in Gemini API.'); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], googleMapsToMldev$3(fromGoogleMaps)); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], googleSearchToMldev$3(fromGoogleSearch)); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} +function toolToVertex$2(fromObject) { + const toObject = {}; + const fromRetrieval = getValueByPath(fromObject, ['retrieval']); + if (fromRetrieval != null) { + setValueByPath(toObject, ['retrieval'], fromRetrieval); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + if (getValueByPath(fromObject, ['fileSearch']) !== undefined) { + throw new Error('fileSearch parameter is not supported in Vertex AI.'); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + const fromEnterpriseWebSearch = getValueByPath(fromObject, [ + 'enterpriseWebSearch', + ]); + if (fromEnterpriseWebSearch != null) { + setValueByPath(toObject, ['enterpriseWebSearch'], fromEnterpriseWebSearch); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return functionDeclarationToVertex$2(item); + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], fromGoogleMaps); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], fromGoogleSearch); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} +function updateCachedContentConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromTtl = getValueByPath(fromObject, ['ttl']); + if (parentObject !== undefined && fromTtl != null) { + setValueByPath(parentObject, ['ttl'], fromTtl); + } + const fromExpireTime = getValueByPath(fromObject, ['expireTime']); + if (parentObject !== undefined && fromExpireTime != null) { + setValueByPath(parentObject, ['expireTime'], fromExpireTime); + } + return toObject; +} +function updateCachedContentConfigToVertex(fromObject, parentObject) { + const toObject = {}; + const fromTtl = getValueByPath(fromObject, ['ttl']); + if (parentObject !== undefined && fromTtl != null) { + setValueByPath(parentObject, ['ttl'], fromTtl); + } + const fromExpireTime = getValueByPath(fromObject, ['expireTime']); + if (parentObject !== undefined && fromExpireTime != null) { + setValueByPath(parentObject, ['expireTime'], fromExpireTime); + } + return toObject; +} +function updateCachedContentParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tCachedContentName(apiClient, fromName)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + updateCachedContentConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function updateCachedContentParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tCachedContentName(apiClient, fromName)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + updateCachedContentConfigToVertex(fromConfig, toObject); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Caches extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + /** + * Lists cached contents. + * + * @param params - The parameters for the list request. + * @return - A pager of cached contents. + * + * @example + * ```ts + * const cachedContents = await ai.caches.list({config: {'pageSize': 2}}); + * for await (const cachedContent of cachedContents) { + * console.log(cachedContent); + * } + * ``` + */ + this.list = async (params = {}) => { + return new Pager(exports.PagedItem.PAGED_ITEM_CACHED_CONTENTS, (x) => this.listInternal(x), await this.listInternal(params), params); + }; + } + /** + * Creates a cached contents resource. + * + * @remarks + * Context caching is only supported for specific models. See [Gemini + * Developer API reference](https://ai.google.dev/gemini-api/docs/caching?lang=node/context-cac) + * and [Vertex AI reference](https://cloud.google.com/vertex-ai/generative-ai/docs/context-cache/context-cache-overview#supported_models) + * for more information. + * + * @param params - The parameters for the create request. + * @return The created cached content. + * + * @example + * ```ts + * const contents = ...; // Initialize the content to cache. + * const response = await ai.caches.create({ + * model: 'gemini-2.0-flash-001', + * config: { + * 'contents': contents, + * 'displayName': 'test cache', + * 'systemInstruction': 'What is the sum of the two pdfs?', + * 'ttl': '86400s', + * } + * }); + * ``` + */ + async create(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = createCachedContentParametersToVertex(this.apiClient, params); + path = formatMap('cachedContents', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + else { + const body = createCachedContentParametersToMldev(this.apiClient, params); + path = formatMap('cachedContents', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } + /** + * Gets cached content configurations. + * + * @param params - The parameters for the get request. + * @return The cached content. + * + * @example + * ```ts + * await ai.caches.get({name: '...'}); // The server-generated resource name. + * ``` + */ + async get(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = getCachedContentParametersToVertex(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + else { + const body = getCachedContentParametersToMldev(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } + /** + * Deletes cached content. + * + * @param params - The parameters for the delete request. + * @return The empty response returned by the API. + * + * @example + * ```ts + * await ai.caches.delete({name: '...'}); // The server-generated resource name. + * ``` + */ + async delete(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = deleteCachedContentParametersToVertex(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = deleteCachedContentResponseFromVertex(apiResponse); + const typedResp = new DeleteCachedContentResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = deleteCachedContentParametersToMldev(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = deleteCachedContentResponseFromMldev(apiResponse); + const typedResp = new DeleteCachedContentResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Updates cached content configurations. + * + * @param params - The parameters for the update request. + * @return The updated cached content. + * + * @example + * ```ts + * const response = await ai.caches.update({ + * name: '...', // The server-generated resource name. + * config: {'ttl': '7600s'} + * }); + * ``` + */ + async update(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = updateCachedContentParametersToVertex(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'PATCH', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + else { + const body = updateCachedContentParametersToMldev(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'PATCH', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } + async listInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = listCachedContentsParametersToVertex(params); + path = formatMap('cachedContents', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listCachedContentsResponseFromVertex(apiResponse); + const typedResp = new ListCachedContentsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = listCachedContentsParametersToMldev(params); + path = formatMap('cachedContents', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listCachedContentsResponseFromMldev(apiResponse); + const typedResp = new ListCachedContentsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } +} + +/****************************************************************************** +Copyright (c) Microsoft Corporation. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +***************************************************************************** */ +/* global Reflect, Promise, SuppressedError, Symbol, Iterator */ + + +function __rest(s, e) { + var t = {}; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) + t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === "function") + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { + if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) + t[p[i]] = s[p[i]]; + } + return t; +} + +function __values(o) { + var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; + if (m) return m.call(o); + if (o && typeof o.length === "number") return { + next: function () { + if (o && i >= o.length) o = void 0; + return { value: o && o[i++], done: !o }; + } + }; + throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); +} + +function __await(v) { + return this instanceof __await ? (this.v = v, this) : new __await(v); +} + +function __asyncGenerator(thisArg, _arguments, generator) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var g = generator.apply(thisArg, _arguments || []), i, q = []; + return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i; + function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; } + function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } } + function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function fulfill(value) { resume("next", value); } + function reject(value) { resume("throw", value); } + function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } +} + +function __asyncValues(o) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var m = o[Symbol.asyncIterator], i; + return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); + function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } + function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } +} + +typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { + var e = new Error(message); + return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Returns true if the response is valid, false otherwise. + */ +function isValidResponse(response) { + var _a; + if (response.candidates == undefined || response.candidates.length === 0) { + return false; + } + const content = (_a = response.candidates[0]) === null || _a === void 0 ? void 0 : _a.content; + if (content === undefined) { + return false; + } + return isValidContent(content); +} +function isValidContent(content) { + if (content.parts === undefined || content.parts.length === 0) { + return false; + } + for (const part of content.parts) { + if (part === undefined || Object.keys(part).length === 0) { + return false; + } + } + return true; +} +/** + * Validates the history contains the correct roles. + * + * @throws Error if the history does not start with a user turn. + * @throws Error if the history contains an invalid role. + */ +function validateHistory(history) { + // Empty history is valid. + if (history.length === 0) { + return; + } + for (const content of history) { + if (content.role !== 'user' && content.role !== 'model') { + throw new Error(`Role must be user or model, but got ${content.role}.`); + } + } +} +/** + * Extracts the curated (valid) history from a comprehensive history. + * + * @remarks + * The model may sometimes generate invalid or empty contents(e.g., due to safty + * filters or recitation). Extracting valid turns from the history + * ensures that subsequent requests could be accpeted by the model. + */ +function extractCuratedHistory(comprehensiveHistory) { + if (comprehensiveHistory === undefined || comprehensiveHistory.length === 0) { + return []; + } + const curatedHistory = []; + const length = comprehensiveHistory.length; + let i = 0; + while (i < length) { + if (comprehensiveHistory[i].role === 'user') { + curatedHistory.push(comprehensiveHistory[i]); + i++; + } + else { + const modelOutput = []; + let isValid = true; + while (i < length && comprehensiveHistory[i].role === 'model') { + modelOutput.push(comprehensiveHistory[i]); + if (isValid && !isValidContent(comprehensiveHistory[i])) { + isValid = false; + } + i++; + } + if (isValid) { + curatedHistory.push(...modelOutput); + } + else { + // Remove the last user input when model content is invalid. + curatedHistory.pop(); + } + } + } + return curatedHistory; +} +/** + * A utility class to create a chat session. + */ +class Chats { + constructor(modelsModule, apiClient) { + this.modelsModule = modelsModule; + this.apiClient = apiClient; + } + /** + * Creates a new chat session. + * + * @remarks + * The config in the params will be used for all requests within the chat + * session unless overridden by a per-request `config` in + * @see {@link types.SendMessageParameters#config}. + * + * @param params - Parameters for creating a chat session. + * @returns A new chat session. + * + * @example + * ```ts + * const chat = ai.chats.create({ + * model: 'gemini-2.0-flash' + * config: { + * temperature: 0.5, + * maxOutputTokens: 1024, + * } + * }); + * ``` + */ + create(params) { + return new Chat(this.apiClient, this.modelsModule, params.model, params.config, + // Deep copy the history to avoid mutating the history outside of the + // chat session. + structuredClone(params.history)); + } +} +/** + * Chat session that enables sending messages to the model with previous + * conversation context. + * + * @remarks + * The session maintains all the turns between user and model. + */ +class Chat { + constructor(apiClient, modelsModule, model, config = {}, history = []) { + this.apiClient = apiClient; + this.modelsModule = modelsModule; + this.model = model; + this.config = config; + this.history = history; + // A promise to represent the current state of the message being sent to the + // model. + this.sendPromise = Promise.resolve(); + validateHistory(history); + } + /** + * Sends a message to the model and returns the response. + * + * @remarks + * This method will wait for the previous message to be processed before + * sending the next message. + * + * @see {@link Chat#sendMessageStream} for streaming method. + * @param params - parameters for sending messages within a chat session. + * @returns The model's response. + * + * @example + * ```ts + * const chat = ai.chats.create({model: 'gemini-2.0-flash'}); + * const response = await chat.sendMessage({ + * message: 'Why is the sky blue?' + * }); + * console.log(response.text); + * ``` + */ + async sendMessage(params) { + var _a; + await this.sendPromise; + const inputContent = tContent(params.message); + const responsePromise = this.modelsModule.generateContent({ + model: this.model, + contents: this.getHistory(true).concat(inputContent), + config: (_a = params.config) !== null && _a !== void 0 ? _a : this.config, + }); + this.sendPromise = (async () => { + var _a, _b, _c; + const response = await responsePromise; + const outputContent = (_b = (_a = response.candidates) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.content; + // Because the AFC input contains the entire curated chat history in + // addition to the new user input, we need to truncate the AFC history + // to deduplicate the existing chat history. + const fullAutomaticFunctionCallingHistory = response.automaticFunctionCallingHistory; + const index = this.getHistory(true).length; + let automaticFunctionCallingHistory = []; + if (fullAutomaticFunctionCallingHistory != null) { + automaticFunctionCallingHistory = + (_c = fullAutomaticFunctionCallingHistory.slice(index)) !== null && _c !== void 0 ? _c : []; + } + const modelOutput = outputContent ? [outputContent] : []; + this.recordHistory(inputContent, modelOutput, automaticFunctionCallingHistory); + return; + })(); + await this.sendPromise.catch(() => { + // Resets sendPromise to avoid subsequent calls failing + this.sendPromise = Promise.resolve(); + }); + return responsePromise; + } + /** + * Sends a message to the model and returns the response in chunks. + * + * @remarks + * This method will wait for the previous message to be processed before + * sending the next message. + * + * @see {@link Chat#sendMessage} for non-streaming method. + * @param params - parameters for sending the message. + * @return The model's response. + * + * @example + * ```ts + * const chat = ai.chats.create({model: 'gemini-2.0-flash'}); + * const response = await chat.sendMessageStream({ + * message: 'Why is the sky blue?' + * }); + * for await (const chunk of response) { + * console.log(chunk.text); + * } + * ``` + */ + async sendMessageStream(params) { + var _a; + await this.sendPromise; + const inputContent = tContent(params.message); + const streamResponse = this.modelsModule.generateContentStream({ + model: this.model, + contents: this.getHistory(true).concat(inputContent), + config: (_a = params.config) !== null && _a !== void 0 ? _a : this.config, + }); + // Resolve the internal tracking of send completion promise - `sendPromise` + // for both success and failure response. The actual failure is still + // propagated by the `await streamResponse`. + this.sendPromise = streamResponse + .then(() => undefined) + .catch(() => undefined); + const response = await streamResponse; + const result = this.processStreamResponse(response, inputContent); + return result; + } + /** + * Returns the chat history. + * + * @remarks + * The history is a list of contents alternating between user and model. + * + * There are two types of history: + * - The `curated history` contains only the valid turns between user and + * model, which will be included in the subsequent requests sent to the model. + * - The `comprehensive history` contains all turns, including invalid or + * empty model outputs, providing a complete record of the history. + * + * The history is updated after receiving the response from the model, + * for streaming response, it means receiving the last chunk of the response. + * + * The `comprehensive history` is returned by default. To get the `curated + * history`, set the `curated` parameter to `true`. + * + * @param curated - whether to return the curated history or the comprehensive + * history. + * @return History contents alternating between user and model for the entire + * chat session. + */ + getHistory(curated = false) { + const history = curated + ? extractCuratedHistory(this.history) + : this.history; + // Deep copy the history to avoid mutating the history outside of the + // chat session. + return structuredClone(history); + } + processStreamResponse(streamResponse, inputContent) { + return __asyncGenerator(this, arguments, function* processStreamResponse_1() { + var _a, e_1, _b, _c; + var _d, _e; + const outputContent = []; + try { + for (var _f = true, streamResponse_1 = __asyncValues(streamResponse), streamResponse_1_1; streamResponse_1_1 = yield __await(streamResponse_1.next()), _a = streamResponse_1_1.done, !_a; _f = true) { + _c = streamResponse_1_1.value; + _f = false; + const chunk = _c; + if (isValidResponse(chunk)) { + const content = (_e = (_d = chunk.candidates) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.content; + if (content !== undefined) { + outputContent.push(content); + } + } + yield yield __await(chunk); + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (!_f && !_a && (_b = streamResponse_1.return)) yield __await(_b.call(streamResponse_1)); + } + finally { if (e_1) throw e_1.error; } + } + this.recordHistory(inputContent, outputContent); + }); + } + recordHistory(userInput, modelOutput, automaticFunctionCallingHistory) { + let outputContents = []; + if (modelOutput.length > 0 && + modelOutput.every((content) => content.role !== undefined)) { + outputContents = modelOutput; + } + else { + // Appends an empty content when model returns empty response, so that the + // history is always alternating between user and model. + outputContents.push({ + role: 'model', + parts: [], + }); + } + if (automaticFunctionCallingHistory && + automaticFunctionCallingHistory.length > 0) { + this.history.push(...extractCuratedHistory(automaticFunctionCallingHistory)); + } + else { + this.history.push(userInput); + } + this.history.push(...outputContents); + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * API errors raised by the GenAI API. + */ +class ApiError extends Error { + constructor(options) { + super(options.message); + this.name = 'ApiError'; + this.status = options.status; + Object.setPrototypeOf(this, ApiError.prototype); + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Code generated by the Google Gen AI SDK generator DO NOT EDIT. +function createFileParametersToMldev(fromObject) { + const toObject = {}; + const fromFile = getValueByPath(fromObject, ['file']); + if (fromFile != null) { + setValueByPath(toObject, ['file'], fromFile); + } + return toObject; +} +function createFileResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function deleteFileParametersToMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'file'], tFileName(fromName)); + } + return toObject; +} +function deleteFileResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function getFileParametersToMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'file'], tFileName(fromName)); + } + return toObject; +} +function internalRegisterFilesParametersToMldev(fromObject) { + const toObject = {}; + const fromUris = getValueByPath(fromObject, ['uris']); + if (fromUris != null) { + setValueByPath(toObject, ['uris'], fromUris); + } + return toObject; +} +function listFilesConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + return toObject; +} +function listFilesParametersToMldev(fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listFilesConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function listFilesResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromFiles = getValueByPath(fromObject, ['files']); + if (fromFiles != null) { + let transformedList = fromFiles; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['files'], transformedList); + } + return toObject; +} +function registerFilesResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromFiles = getValueByPath(fromObject, ['files']); + if (fromFiles != null) { + let transformedList = fromFiles; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['files'], transformedList); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Files extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + /** + * Lists files. + * + * @param params - The parameters for the list request. + * @return - A pager of files. + * + * @example + * ```ts + * const files = await ai.files.list({config: {'pageSize': 2}}); + * for await (const file of files) { + * console.log(file); + * } + * ``` + */ + this.list = async (params = {}) => { + return new Pager(exports.PagedItem.PAGED_ITEM_FILES, (x) => this.listInternal(x), await this.listInternal(params), params); + }; + } + /** + * Uploads a file asynchronously to the Gemini API. + * This method is not available in Vertex AI. + * Supported upload sources: + * - Node.js: File path (string) or Blob object. + * - Browser: Blob object (e.g., File). + * + * @remarks + * The `mimeType` can be specified in the `config` parameter. If omitted: + * - For file path (string) inputs, the `mimeType` will be inferred from the + * file extension. + * - For Blob object inputs, the `mimeType` will be set to the Blob's `type` + * property. + * Somex eamples for file extension to mimeType mapping: + * .txt -> text/plain + * .json -> application/json + * .jpg -> image/jpeg + * .png -> image/png + * .mp3 -> audio/mpeg + * .mp4 -> video/mp4 + * + * This section can contain multiple paragraphs and code examples. + * + * @param params - Optional parameters specified in the + * `types.UploadFileParameters` interface. + * @see {@link types.UploadFileParameters#config} for the optional + * config in the parameters. + * @return A promise that resolves to a `types.File` object. + * @throws An error if called on a Vertex AI client. + * @throws An error if the `mimeType` is not provided and can not be inferred, + * the `mimeType` can be provided in the `params.config` parameter. + * @throws An error occurs if a suitable upload location cannot be established. + * + * @example + * The following code uploads a file to Gemini API. + * + * ```ts + * const file = await ai.files.upload({file: 'file.txt', config: { + * mimeType: 'text/plain', + * }}); + * console.log(file.name); + * ``` + */ + async upload(params) { + if (this.apiClient.isVertexAI()) { + throw new Error('Vertex AI does not support uploading files. You can share files through a GCS bucket.'); + } + return this.apiClient + .uploadFile(params.file, params.config) + .then((resp) => { + return resp; + }); + } + /** + * Downloads a remotely stored file asynchronously to a location specified in + * the `params` object. This method only works on Node environment, to + * download files in the browser, use a browser compliant method like an <a> + * tag. + * + * @param params - The parameters for the download request. + * + * @example + * The following code downloads an example file named "files/mehozpxf877d" as + * "file.txt". + * + * ```ts + * await ai.files.download({file: file.name, downloadPath: 'file.txt'}); + * ``` + */ + async download(params) { + await this.apiClient.downloadFile(params); + } + /** + * Registers Google Cloud Storage files for use with the API. + * This method is only available in Node.js environments. + */ + async registerFiles(params) { + throw new Error('registerFiles is only supported in Node.js environments.'); + } + async _registerFiles(params) { + return this.registerFilesInternal(params); + } + async listInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = listFilesParametersToMldev(params); + path = formatMap('files', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listFilesResponseFromMldev(apiResponse); + const typedResp = new ListFilesResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + async createInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = createFileParametersToMldev(params); + path = formatMap('upload/v1beta/files', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = createFileResponseFromMldev(apiResponse); + const typedResp = new CreateFileResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Retrieves the file information from the service. + * + * @param params - The parameters for the get request + * @return The Promise that resolves to the types.File object requested. + * + * @example + * ```ts + * const config: GetFileParameters = { + * name: fileName, + * }; + * file = await ai.files.get(config); + * console.log(file.name); + * ``` + */ + async get(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = getFileParametersToMldev(params); + path = formatMap('files/{file}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } + /** + * Deletes a remotely stored file. + * + * @param params - The parameters for the delete request. + * @return The DeleteFileResponse, the response for the delete method. + * + * @example + * The following code deletes an example file named "files/mehozpxf877d". + * + * ```ts + * await ai.files.delete({name: file.name}); + * ``` + */ + async delete(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = deleteFileParametersToMldev(params); + path = formatMap('files/{file}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = deleteFileResponseFromMldev(apiResponse); + const typedResp = new DeleteFileResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + async registerFilesInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = internalRegisterFilesParametersToMldev(params); + path = formatMap('files:register', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = registerFilesResponseFromMldev(apiResponse); + const typedResp = new RegisterFilesResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function blobToMldev$2(fromObject) { + const toObject = {}; + const fromData = getValueByPath(fromObject, ['data']); + if (fromData != null) { + setValueByPath(toObject, ['data'], fromData); + } + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function contentToMldev$2(fromObject) { + const toObject = {}; + const fromParts = getValueByPath(fromObject, ['parts']); + if (fromParts != null) { + let transformedList = fromParts; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return partToMldev$2(item); + }); + } + setValueByPath(toObject, ['parts'], transformedList); + } + const fromRole = getValueByPath(fromObject, ['role']); + if (fromRole != null) { + setValueByPath(toObject, ['role'], fromRole); + } + return toObject; +} +function fileDataToMldev$2(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromFileUri = getValueByPath(fromObject, ['fileUri']); + if (fromFileUri != null) { + setValueByPath(toObject, ['fileUri'], fromFileUri); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function functionCallToMldev$2(fromObject) { + const toObject = {}; + const fromId = getValueByPath(fromObject, ['id']); + if (fromId != null) { + setValueByPath(toObject, ['id'], fromId); + } + const fromArgs = getValueByPath(fromObject, ['args']); + if (fromArgs != null) { + setValueByPath(toObject, ['args'], fromArgs); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + if (getValueByPath(fromObject, ['partialArgs']) !== undefined) { + throw new Error('partialArgs parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['willContinue']) !== undefined) { + throw new Error('willContinue parameter is not supported in Gemini API.'); + } + return toObject; +} +function functionDeclarationToVertex$1(fromObject) { + const toObject = {}; + const fromDescription = getValueByPath(fromObject, ['description']); + if (fromDescription != null) { + setValueByPath(toObject, ['description'], fromDescription); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromParameters = getValueByPath(fromObject, ['parameters']); + if (fromParameters != null) { + setValueByPath(toObject, ['parameters'], fromParameters); + } + const fromParametersJsonSchema = getValueByPath(fromObject, [ + 'parametersJsonSchema', + ]); + if (fromParametersJsonSchema != null) { + setValueByPath(toObject, ['parametersJsonSchema'], fromParametersJsonSchema); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], fromResponse); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + if (getValueByPath(fromObject, ['behavior']) !== undefined) { + throw new Error('behavior parameter is not supported in Vertex AI.'); + } + return toObject; +} +function generationConfigToVertex$1(fromObject) { + const toObject = {}; + const fromModelSelectionConfig = getValueByPath(fromObject, [ + 'modelSelectionConfig', + ]); + if (fromModelSelectionConfig != null) { + setValueByPath(toObject, ['modelConfig'], fromModelSelectionConfig); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + const fromAudioTimestamp = getValueByPath(fromObject, [ + 'audioTimestamp', + ]); + if (fromAudioTimestamp != null) { + setValueByPath(toObject, ['audioTimestamp'], fromAudioTimestamp); + } + const fromCandidateCount = getValueByPath(fromObject, [ + 'candidateCount', + ]); + if (fromCandidateCount != null) { + setValueByPath(toObject, ['candidateCount'], fromCandidateCount); + } + const fromEnableAffectiveDialog = getValueByPath(fromObject, [ + 'enableAffectiveDialog', + ]); + if (fromEnableAffectiveDialog != null) { + setValueByPath(toObject, ['enableAffectiveDialog'], fromEnableAffectiveDialog); + } + const fromFrequencyPenalty = getValueByPath(fromObject, [ + 'frequencyPenalty', + ]); + if (fromFrequencyPenalty != null) { + setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty); + } + const fromLogprobs = getValueByPath(fromObject, ['logprobs']); + if (fromLogprobs != null) { + setValueByPath(toObject, ['logprobs'], fromLogprobs); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (fromMaxOutputTokens != null) { + setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromPresencePenalty = getValueByPath(fromObject, [ + 'presencePenalty', + ]); + if (fromPresencePenalty != null) { + setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty); + } + const fromResponseLogprobs = getValueByPath(fromObject, [ + 'responseLogprobs', + ]); + if (fromResponseLogprobs != null) { + setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs); + } + const fromResponseMimeType = getValueByPath(fromObject, [ + 'responseMimeType', + ]); + if (fromResponseMimeType != null) { + setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (fromResponseModalities != null) { + setValueByPath(toObject, ['responseModalities'], fromResponseModalities); + } + const fromResponseSchema = getValueByPath(fromObject, [ + 'responseSchema', + ]); + if (fromResponseSchema != null) { + setValueByPath(toObject, ['responseSchema'], fromResponseSchema); + } + const fromRoutingConfig = getValueByPath(fromObject, [ + 'routingConfig', + ]); + if (fromRoutingConfig != null) { + setValueByPath(toObject, ['routingConfig'], fromRoutingConfig); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (fromSeed != null) { + setValueByPath(toObject, ['seed'], fromSeed); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (fromSpeechConfig != null) { + setValueByPath(toObject, ['speechConfig'], fromSpeechConfig); + } + const fromStopSequences = getValueByPath(fromObject, [ + 'stopSequences', + ]); + if (fromStopSequences != null) { + setValueByPath(toObject, ['stopSequences'], fromStopSequences); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (fromTemperature != null) { + setValueByPath(toObject, ['temperature'], fromTemperature); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (fromThinkingConfig != null) { + setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (fromTopK != null) { + setValueByPath(toObject, ['topK'], fromTopK); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (fromTopP != null) { + setValueByPath(toObject, ['topP'], fromTopP); + } + if (getValueByPath(fromObject, ['enableEnhancedCivicAnswers']) !== + undefined) { + throw new Error('enableEnhancedCivicAnswers parameter is not supported in Vertex AI.'); + } + return toObject; +} +function googleMapsToMldev$2(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['authConfig']) !== undefined) { + throw new Error('authConfig parameter is not supported in Gemini API.'); + } + const fromEnableWidget = getValueByPath(fromObject, ['enableWidget']); + if (fromEnableWidget != null) { + setValueByPath(toObject, ['enableWidget'], fromEnableWidget); + } + return toObject; +} +function googleSearchToMldev$2(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['excludeDomains']) !== undefined) { + throw new Error('excludeDomains parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['blockingConfidence']) !== undefined) { + throw new Error('blockingConfidence parameter is not supported in Gemini API.'); + } + const fromTimeRangeFilter = getValueByPath(fromObject, [ + 'timeRangeFilter', + ]); + if (fromTimeRangeFilter != null) { + setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter); + } + return toObject; +} +function liveConnectConfigToMldev$1(fromObject, parentObject) { + const toObject = {}; + const fromGenerationConfig = getValueByPath(fromObject, [ + 'generationConfig', + ]); + if (parentObject !== undefined && fromGenerationConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig'], fromGenerationConfig); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (parentObject !== undefined && fromResponseModalities != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'responseModalities'], fromResponseModalities); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (parentObject !== undefined && fromTemperature != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'temperature'], fromTemperature); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (parentObject !== undefined && fromTopP != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'topP'], fromTopP); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (parentObject !== undefined && fromTopK != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'topK'], fromTopK); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (parentObject !== undefined && fromMaxOutputTokens != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'maxOutputTokens'], fromMaxOutputTokens); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (parentObject !== undefined && fromMediaResolution != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'mediaResolution'], fromMediaResolution); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (parentObject !== undefined && fromSeed != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'seed'], fromSeed); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (parentObject !== undefined && fromSpeechConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'speechConfig'], tLiveSpeechConfig(fromSpeechConfig)); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (parentObject !== undefined && fromThinkingConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'thinkingConfig'], fromThinkingConfig); + } + const fromEnableAffectiveDialog = getValueByPath(fromObject, [ + 'enableAffectiveDialog', + ]); + if (parentObject !== undefined && fromEnableAffectiveDialog != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'enableAffectiveDialog'], fromEnableAffectiveDialog); + } + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['setup', 'systemInstruction'], contentToMldev$2(tContent(fromSystemInstruction))); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = tTools(fromTools); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToMldev$2(tTool(item)); + }); + } + setValueByPath(parentObject, ['setup', 'tools'], transformedList); + } + const fromSessionResumption = getValueByPath(fromObject, [ + 'sessionResumption', + ]); + if (parentObject !== undefined && fromSessionResumption != null) { + setValueByPath(parentObject, ['setup', 'sessionResumption'], sessionResumptionConfigToMldev$1(fromSessionResumption)); + } + const fromInputAudioTranscription = getValueByPath(fromObject, [ + 'inputAudioTranscription', + ]); + if (parentObject !== undefined && fromInputAudioTranscription != null) { + setValueByPath(parentObject, ['setup', 'inputAudioTranscription'], fromInputAudioTranscription); + } + const fromOutputAudioTranscription = getValueByPath(fromObject, [ + 'outputAudioTranscription', + ]); + if (parentObject !== undefined && fromOutputAudioTranscription != null) { + setValueByPath(parentObject, ['setup', 'outputAudioTranscription'], fromOutputAudioTranscription); + } + const fromRealtimeInputConfig = getValueByPath(fromObject, [ + 'realtimeInputConfig', + ]); + if (parentObject !== undefined && fromRealtimeInputConfig != null) { + setValueByPath(parentObject, ['setup', 'realtimeInputConfig'], fromRealtimeInputConfig); + } + const fromContextWindowCompression = getValueByPath(fromObject, [ + 'contextWindowCompression', + ]); + if (parentObject !== undefined && fromContextWindowCompression != null) { + setValueByPath(parentObject, ['setup', 'contextWindowCompression'], fromContextWindowCompression); + } + const fromProactivity = getValueByPath(fromObject, ['proactivity']); + if (parentObject !== undefined && fromProactivity != null) { + setValueByPath(parentObject, ['setup', 'proactivity'], fromProactivity); + } + if (getValueByPath(fromObject, ['explicitVadSignal']) !== undefined) { + throw new Error('explicitVadSignal parameter is not supported in Gemini API.'); + } + return toObject; +} +function liveConnectConfigToVertex(fromObject, parentObject) { + const toObject = {}; + const fromGenerationConfig = getValueByPath(fromObject, [ + 'generationConfig', + ]); + if (parentObject !== undefined && fromGenerationConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig'], generationConfigToVertex$1(fromGenerationConfig)); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (parentObject !== undefined && fromResponseModalities != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'responseModalities'], fromResponseModalities); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (parentObject !== undefined && fromTemperature != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'temperature'], fromTemperature); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (parentObject !== undefined && fromTopP != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'topP'], fromTopP); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (parentObject !== undefined && fromTopK != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'topK'], fromTopK); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (parentObject !== undefined && fromMaxOutputTokens != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'maxOutputTokens'], fromMaxOutputTokens); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (parentObject !== undefined && fromMediaResolution != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'mediaResolution'], fromMediaResolution); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (parentObject !== undefined && fromSeed != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'seed'], fromSeed); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (parentObject !== undefined && fromSpeechConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'speechConfig'], tLiveSpeechConfig(fromSpeechConfig)); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (parentObject !== undefined && fromThinkingConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'thinkingConfig'], fromThinkingConfig); + } + const fromEnableAffectiveDialog = getValueByPath(fromObject, [ + 'enableAffectiveDialog', + ]); + if (parentObject !== undefined && fromEnableAffectiveDialog != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'enableAffectiveDialog'], fromEnableAffectiveDialog); + } + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['setup', 'systemInstruction'], tContent(fromSystemInstruction)); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = tTools(fromTools); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToVertex$1(tTool(item)); + }); + } + setValueByPath(parentObject, ['setup', 'tools'], transformedList); + } + const fromSessionResumption = getValueByPath(fromObject, [ + 'sessionResumption', + ]); + if (parentObject !== undefined && fromSessionResumption != null) { + setValueByPath(parentObject, ['setup', 'sessionResumption'], fromSessionResumption); + } + const fromInputAudioTranscription = getValueByPath(fromObject, [ + 'inputAudioTranscription', + ]); + if (parentObject !== undefined && fromInputAudioTranscription != null) { + setValueByPath(parentObject, ['setup', 'inputAudioTranscription'], fromInputAudioTranscription); + } + const fromOutputAudioTranscription = getValueByPath(fromObject, [ + 'outputAudioTranscription', + ]); + if (parentObject !== undefined && fromOutputAudioTranscription != null) { + setValueByPath(parentObject, ['setup', 'outputAudioTranscription'], fromOutputAudioTranscription); + } + const fromRealtimeInputConfig = getValueByPath(fromObject, [ + 'realtimeInputConfig', + ]); + if (parentObject !== undefined && fromRealtimeInputConfig != null) { + setValueByPath(parentObject, ['setup', 'realtimeInputConfig'], fromRealtimeInputConfig); + } + const fromContextWindowCompression = getValueByPath(fromObject, [ + 'contextWindowCompression', + ]); + if (parentObject !== undefined && fromContextWindowCompression != null) { + setValueByPath(parentObject, ['setup', 'contextWindowCompression'], fromContextWindowCompression); + } + const fromProactivity = getValueByPath(fromObject, ['proactivity']); + if (parentObject !== undefined && fromProactivity != null) { + setValueByPath(parentObject, ['setup', 'proactivity'], fromProactivity); + } + const fromExplicitVadSignal = getValueByPath(fromObject, [ + 'explicitVadSignal', + ]); + if (parentObject !== undefined && fromExplicitVadSignal != null) { + setValueByPath(parentObject, ['setup', 'explicitVadSignal'], fromExplicitVadSignal); + } + return toObject; +} +function liveConnectParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['setup', 'model'], tModel(apiClient, fromModel)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['config'], liveConnectConfigToMldev$1(fromConfig, toObject)); + } + return toObject; +} +function liveConnectParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['setup', 'model'], tModel(apiClient, fromModel)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['config'], liveConnectConfigToVertex(fromConfig, toObject)); + } + return toObject; +} +function liveMusicSetConfigParametersToMldev(fromObject) { + const toObject = {}; + const fromMusicGenerationConfig = getValueByPath(fromObject, [ + 'musicGenerationConfig', + ]); + if (fromMusicGenerationConfig != null) { + setValueByPath(toObject, ['musicGenerationConfig'], fromMusicGenerationConfig); + } + return toObject; +} +function liveMusicSetWeightedPromptsParametersToMldev(fromObject) { + const toObject = {}; + const fromWeightedPrompts = getValueByPath(fromObject, [ + 'weightedPrompts', + ]); + if (fromWeightedPrompts != null) { + let transformedList = fromWeightedPrompts; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['weightedPrompts'], transformedList); + } + return toObject; +} +function liveSendRealtimeInputParametersToMldev(fromObject) { + const toObject = {}; + const fromMedia = getValueByPath(fromObject, ['media']); + if (fromMedia != null) { + let transformedList = tBlobs(fromMedia); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return blobToMldev$2(item); + }); + } + setValueByPath(toObject, ['mediaChunks'], transformedList); + } + const fromAudio = getValueByPath(fromObject, ['audio']); + if (fromAudio != null) { + setValueByPath(toObject, ['audio'], blobToMldev$2(tAudioBlob(fromAudio))); + } + const fromAudioStreamEnd = getValueByPath(fromObject, [ + 'audioStreamEnd', + ]); + if (fromAudioStreamEnd != null) { + setValueByPath(toObject, ['audioStreamEnd'], fromAudioStreamEnd); + } + const fromVideo = getValueByPath(fromObject, ['video']); + if (fromVideo != null) { + setValueByPath(toObject, ['video'], blobToMldev$2(tImageBlob(fromVideo))); + } + const fromText = getValueByPath(fromObject, ['text']); + if (fromText != null) { + setValueByPath(toObject, ['text'], fromText); + } + const fromActivityStart = getValueByPath(fromObject, [ + 'activityStart', + ]); + if (fromActivityStart != null) { + setValueByPath(toObject, ['activityStart'], fromActivityStart); + } + const fromActivityEnd = getValueByPath(fromObject, ['activityEnd']); + if (fromActivityEnd != null) { + setValueByPath(toObject, ['activityEnd'], fromActivityEnd); + } + return toObject; +} +function liveSendRealtimeInputParametersToVertex(fromObject) { + const toObject = {}; + const fromMedia = getValueByPath(fromObject, ['media']); + if (fromMedia != null) { + let transformedList = tBlobs(fromMedia); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['mediaChunks'], transformedList); + } + const fromAudio = getValueByPath(fromObject, ['audio']); + if (fromAudio != null) { + setValueByPath(toObject, ['audio'], tAudioBlob(fromAudio)); + } + const fromAudioStreamEnd = getValueByPath(fromObject, [ + 'audioStreamEnd', + ]); + if (fromAudioStreamEnd != null) { + setValueByPath(toObject, ['audioStreamEnd'], fromAudioStreamEnd); + } + const fromVideo = getValueByPath(fromObject, ['video']); + if (fromVideo != null) { + setValueByPath(toObject, ['video'], tImageBlob(fromVideo)); + } + const fromText = getValueByPath(fromObject, ['text']); + if (fromText != null) { + setValueByPath(toObject, ['text'], fromText); + } + const fromActivityStart = getValueByPath(fromObject, [ + 'activityStart', + ]); + if (fromActivityStart != null) { + setValueByPath(toObject, ['activityStart'], fromActivityStart); + } + const fromActivityEnd = getValueByPath(fromObject, ['activityEnd']); + if (fromActivityEnd != null) { + setValueByPath(toObject, ['activityEnd'], fromActivityEnd); + } + return toObject; +} +function liveServerMessageFromVertex(fromObject) { + const toObject = {}; + const fromSetupComplete = getValueByPath(fromObject, [ + 'setupComplete', + ]); + if (fromSetupComplete != null) { + setValueByPath(toObject, ['setupComplete'], fromSetupComplete); + } + const fromServerContent = getValueByPath(fromObject, [ + 'serverContent', + ]); + if (fromServerContent != null) { + setValueByPath(toObject, ['serverContent'], fromServerContent); + } + const fromToolCall = getValueByPath(fromObject, ['toolCall']); + if (fromToolCall != null) { + setValueByPath(toObject, ['toolCall'], fromToolCall); + } + const fromToolCallCancellation = getValueByPath(fromObject, [ + 'toolCallCancellation', + ]); + if (fromToolCallCancellation != null) { + setValueByPath(toObject, ['toolCallCancellation'], fromToolCallCancellation); + } + const fromUsageMetadata = getValueByPath(fromObject, [ + 'usageMetadata', + ]); + if (fromUsageMetadata != null) { + setValueByPath(toObject, ['usageMetadata'], usageMetadataFromVertex(fromUsageMetadata)); + } + const fromGoAway = getValueByPath(fromObject, ['goAway']); + if (fromGoAway != null) { + setValueByPath(toObject, ['goAway'], fromGoAway); + } + const fromSessionResumptionUpdate = getValueByPath(fromObject, [ + 'sessionResumptionUpdate', + ]); + if (fromSessionResumptionUpdate != null) { + setValueByPath(toObject, ['sessionResumptionUpdate'], fromSessionResumptionUpdate); + } + const fromVoiceActivityDetectionSignal = getValueByPath(fromObject, [ + 'voiceActivityDetectionSignal', + ]); + if (fromVoiceActivityDetectionSignal != null) { + setValueByPath(toObject, ['voiceActivityDetectionSignal'], fromVoiceActivityDetectionSignal); + } + const fromVoiceActivity = getValueByPath(fromObject, [ + 'voiceActivity', + ]); + if (fromVoiceActivity != null) { + setValueByPath(toObject, ['voiceActivity'], voiceActivityFromVertex(fromVoiceActivity)); + } + return toObject; +} +function partToMldev$2(fromObject) { + const toObject = {}; + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromCodeExecutionResult = getValueByPath(fromObject, [ + 'codeExecutionResult', + ]); + if (fromCodeExecutionResult != null) { + setValueByPath(toObject, ['codeExecutionResult'], fromCodeExecutionResult); + } + const fromExecutableCode = getValueByPath(fromObject, [ + 'executableCode', + ]); + if (fromExecutableCode != null) { + setValueByPath(toObject, ['executableCode'], fromExecutableCode); + } + const fromFileData = getValueByPath(fromObject, ['fileData']); + if (fromFileData != null) { + setValueByPath(toObject, ['fileData'], fileDataToMldev$2(fromFileData)); + } + const fromFunctionCall = getValueByPath(fromObject, ['functionCall']); + if (fromFunctionCall != null) { + setValueByPath(toObject, ['functionCall'], functionCallToMldev$2(fromFunctionCall)); + } + const fromFunctionResponse = getValueByPath(fromObject, [ + 'functionResponse', + ]); + if (fromFunctionResponse != null) { + setValueByPath(toObject, ['functionResponse'], fromFunctionResponse); + } + const fromInlineData = getValueByPath(fromObject, ['inlineData']); + if (fromInlineData != null) { + setValueByPath(toObject, ['inlineData'], blobToMldev$2(fromInlineData)); + } + const fromText = getValueByPath(fromObject, ['text']); + if (fromText != null) { + setValueByPath(toObject, ['text'], fromText); + } + const fromThought = getValueByPath(fromObject, ['thought']); + if (fromThought != null) { + setValueByPath(toObject, ['thought'], fromThought); + } + const fromThoughtSignature = getValueByPath(fromObject, [ + 'thoughtSignature', + ]); + if (fromThoughtSignature != null) { + setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature); + } + const fromVideoMetadata = getValueByPath(fromObject, [ + 'videoMetadata', + ]); + if (fromVideoMetadata != null) { + setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata); + } + return toObject; +} +function sessionResumptionConfigToMldev$1(fromObject) { + const toObject = {}; + const fromHandle = getValueByPath(fromObject, ['handle']); + if (fromHandle != null) { + setValueByPath(toObject, ['handle'], fromHandle); + } + if (getValueByPath(fromObject, ['transparent']) !== undefined) { + throw new Error('transparent parameter is not supported in Gemini API.'); + } + return toObject; +} +function toolToMldev$2(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['retrieval']) !== undefined) { + throw new Error('retrieval parameter is not supported in Gemini API.'); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + const fromFileSearch = getValueByPath(fromObject, ['fileSearch']); + if (fromFileSearch != null) { + setValueByPath(toObject, ['fileSearch'], fromFileSearch); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + if (getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined) { + throw new Error('enterpriseWebSearch parameter is not supported in Gemini API.'); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], googleMapsToMldev$2(fromGoogleMaps)); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], googleSearchToMldev$2(fromGoogleSearch)); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} +function toolToVertex$1(fromObject) { + const toObject = {}; + const fromRetrieval = getValueByPath(fromObject, ['retrieval']); + if (fromRetrieval != null) { + setValueByPath(toObject, ['retrieval'], fromRetrieval); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + if (getValueByPath(fromObject, ['fileSearch']) !== undefined) { + throw new Error('fileSearch parameter is not supported in Vertex AI.'); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + const fromEnterpriseWebSearch = getValueByPath(fromObject, [ + 'enterpriseWebSearch', + ]); + if (fromEnterpriseWebSearch != null) { + setValueByPath(toObject, ['enterpriseWebSearch'], fromEnterpriseWebSearch); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return functionDeclarationToVertex$1(item); + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], fromGoogleMaps); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], fromGoogleSearch); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} +function usageMetadataFromVertex(fromObject) { + const toObject = {}; + const fromPromptTokenCount = getValueByPath(fromObject, [ + 'promptTokenCount', + ]); + if (fromPromptTokenCount != null) { + setValueByPath(toObject, ['promptTokenCount'], fromPromptTokenCount); + } + const fromCachedContentTokenCount = getValueByPath(fromObject, [ + 'cachedContentTokenCount', + ]); + if (fromCachedContentTokenCount != null) { + setValueByPath(toObject, ['cachedContentTokenCount'], fromCachedContentTokenCount); + } + const fromResponseTokenCount = getValueByPath(fromObject, [ + 'candidatesTokenCount', + ]); + if (fromResponseTokenCount != null) { + setValueByPath(toObject, ['responseTokenCount'], fromResponseTokenCount); + } + const fromToolUsePromptTokenCount = getValueByPath(fromObject, [ + 'toolUsePromptTokenCount', + ]); + if (fromToolUsePromptTokenCount != null) { + setValueByPath(toObject, ['toolUsePromptTokenCount'], fromToolUsePromptTokenCount); + } + const fromThoughtsTokenCount = getValueByPath(fromObject, [ + 'thoughtsTokenCount', + ]); + if (fromThoughtsTokenCount != null) { + setValueByPath(toObject, ['thoughtsTokenCount'], fromThoughtsTokenCount); + } + const fromTotalTokenCount = getValueByPath(fromObject, [ + 'totalTokenCount', + ]); + if (fromTotalTokenCount != null) { + setValueByPath(toObject, ['totalTokenCount'], fromTotalTokenCount); + } + const fromPromptTokensDetails = getValueByPath(fromObject, [ + 'promptTokensDetails', + ]); + if (fromPromptTokensDetails != null) { + let transformedList = fromPromptTokensDetails; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['promptTokensDetails'], transformedList); + } + const fromCacheTokensDetails = getValueByPath(fromObject, [ + 'cacheTokensDetails', + ]); + if (fromCacheTokensDetails != null) { + let transformedList = fromCacheTokensDetails; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['cacheTokensDetails'], transformedList); + } + const fromResponseTokensDetails = getValueByPath(fromObject, [ + 'candidatesTokensDetails', + ]); + if (fromResponseTokensDetails != null) { + let transformedList = fromResponseTokensDetails; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['responseTokensDetails'], transformedList); + } + const fromToolUsePromptTokensDetails = getValueByPath(fromObject, [ + 'toolUsePromptTokensDetails', + ]); + if (fromToolUsePromptTokensDetails != null) { + let transformedList = fromToolUsePromptTokensDetails; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['toolUsePromptTokensDetails'], transformedList); + } + const fromTrafficType = getValueByPath(fromObject, ['trafficType']); + if (fromTrafficType != null) { + setValueByPath(toObject, ['trafficType'], fromTrafficType); + } + return toObject; +} +function voiceActivityFromVertex(fromObject) { + const toObject = {}; + const fromVoiceActivityType = getValueByPath(fromObject, ['type']); + if (fromVoiceActivityType != null) { + setValueByPath(toObject, ['voiceActivityType'], fromVoiceActivityType); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function blobToMldev$1(fromObject, _rootObject) { + const toObject = {}; + const fromData = getValueByPath(fromObject, ['data']); + if (fromData != null) { + setValueByPath(toObject, ['data'], fromData); + } + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function candidateFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromContent = getValueByPath(fromObject, ['content']); + if (fromContent != null) { + setValueByPath(toObject, ['content'], fromContent); + } + const fromCitationMetadata = getValueByPath(fromObject, [ + 'citationMetadata', + ]); + if (fromCitationMetadata != null) { + setValueByPath(toObject, ['citationMetadata'], citationMetadataFromMldev(fromCitationMetadata)); + } + const fromTokenCount = getValueByPath(fromObject, ['tokenCount']); + if (fromTokenCount != null) { + setValueByPath(toObject, ['tokenCount'], fromTokenCount); + } + const fromFinishReason = getValueByPath(fromObject, ['finishReason']); + if (fromFinishReason != null) { + setValueByPath(toObject, ['finishReason'], fromFinishReason); + } + const fromAvgLogprobs = getValueByPath(fromObject, ['avgLogprobs']); + if (fromAvgLogprobs != null) { + setValueByPath(toObject, ['avgLogprobs'], fromAvgLogprobs); + } + const fromGroundingMetadata = getValueByPath(fromObject, [ + 'groundingMetadata', + ]); + if (fromGroundingMetadata != null) { + setValueByPath(toObject, ['groundingMetadata'], fromGroundingMetadata); + } + const fromIndex = getValueByPath(fromObject, ['index']); + if (fromIndex != null) { + setValueByPath(toObject, ['index'], fromIndex); + } + const fromLogprobsResult = getValueByPath(fromObject, [ + 'logprobsResult', + ]); + if (fromLogprobsResult != null) { + setValueByPath(toObject, ['logprobsResult'], fromLogprobsResult); + } + const fromSafetyRatings = getValueByPath(fromObject, [ + 'safetyRatings', + ]); + if (fromSafetyRatings != null) { + let transformedList = fromSafetyRatings; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['safetyRatings'], transformedList); + } + const fromUrlContextMetadata = getValueByPath(fromObject, [ + 'urlContextMetadata', + ]); + if (fromUrlContextMetadata != null) { + setValueByPath(toObject, ['urlContextMetadata'], fromUrlContextMetadata); + } + return toObject; +} +function citationMetadataFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromCitations = getValueByPath(fromObject, ['citationSources']); + if (fromCitations != null) { + let transformedList = fromCitations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['citations'], transformedList); + } + return toObject; +} +function computeTokensParametersToVertex(apiClient, fromObject, _rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['contents'], transformedList); + } + return toObject; +} +function computeTokensResponseFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromTokensInfo = getValueByPath(fromObject, ['tokensInfo']); + if (fromTokensInfo != null) { + let transformedList = fromTokensInfo; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['tokensInfo'], transformedList); + } + return toObject; +} +function contentEmbeddingFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromValues = getValueByPath(fromObject, ['values']); + if (fromValues != null) { + setValueByPath(toObject, ['values'], fromValues); + } + const fromStatistics = getValueByPath(fromObject, ['statistics']); + if (fromStatistics != null) { + setValueByPath(toObject, ['statistics'], contentEmbeddingStatisticsFromVertex(fromStatistics)); + } + return toObject; +} +function contentEmbeddingStatisticsFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromTruncated = getValueByPath(fromObject, ['truncated']); + if (fromTruncated != null) { + setValueByPath(toObject, ['truncated'], fromTruncated); + } + const fromTokenCount = getValueByPath(fromObject, ['token_count']); + if (fromTokenCount != null) { + setValueByPath(toObject, ['tokenCount'], fromTokenCount); + } + return toObject; +} +function contentToMldev$1(fromObject, rootObject) { + const toObject = {}; + const fromParts = getValueByPath(fromObject, ['parts']); + if (fromParts != null) { + let transformedList = fromParts; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return partToMldev$1(item); + }); + } + setValueByPath(toObject, ['parts'], transformedList); + } + const fromRole = getValueByPath(fromObject, ['role']); + if (fromRole != null) { + setValueByPath(toObject, ['role'], fromRole); + } + return toObject; +} +function controlReferenceConfigToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromControlType = getValueByPath(fromObject, ['controlType']); + if (fromControlType != null) { + setValueByPath(toObject, ['controlType'], fromControlType); + } + const fromEnableControlImageComputation = getValueByPath(fromObject, [ + 'enableControlImageComputation', + ]); + if (fromEnableControlImageComputation != null) { + setValueByPath(toObject, ['computeControl'], fromEnableControlImageComputation); + } + return toObject; +} +function countTokensConfigToMldev(fromObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['systemInstruction']) !== undefined) { + throw new Error('systemInstruction parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['tools']) !== undefined) { + throw new Error('tools parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['generationConfig']) !== undefined) { + throw new Error('generationConfig parameter is not supported in Gemini API.'); + } + return toObject; +} +function countTokensConfigToVertex(fromObject, parentObject, rootObject) { + const toObject = {}; + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['systemInstruction'], tContent(fromSystemInstruction)); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = fromTools; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToVertex(item); + }); + } + setValueByPath(parentObject, ['tools'], transformedList); + } + const fromGenerationConfig = getValueByPath(fromObject, [ + 'generationConfig', + ]); + if (parentObject !== undefined && fromGenerationConfig != null) { + setValueByPath(parentObject, ['generationConfig'], generationConfigToVertex(fromGenerationConfig)); + } + return toObject; +} +function countTokensParametersToMldev(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return contentToMldev$1(item); + }); + } + setValueByPath(toObject, ['contents'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + countTokensConfigToMldev(fromConfig); + } + return toObject; +} +function countTokensParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['contents'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + countTokensConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function countTokensResponseFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromTotalTokens = getValueByPath(fromObject, ['totalTokens']); + if (fromTotalTokens != null) { + setValueByPath(toObject, ['totalTokens'], fromTotalTokens); + } + const fromCachedContentTokenCount = getValueByPath(fromObject, [ + 'cachedContentTokenCount', + ]); + if (fromCachedContentTokenCount != null) { + setValueByPath(toObject, ['cachedContentTokenCount'], fromCachedContentTokenCount); + } + return toObject; +} +function countTokensResponseFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromTotalTokens = getValueByPath(fromObject, ['totalTokens']); + if (fromTotalTokens != null) { + setValueByPath(toObject, ['totalTokens'], fromTotalTokens); + } + return toObject; +} +function deleteModelParametersToMldev(apiClient, fromObject, _rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'name'], tModel(apiClient, fromModel)); + } + return toObject; +} +function deleteModelParametersToVertex(apiClient, fromObject, _rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'name'], tModel(apiClient, fromModel)); + } + return toObject; +} +function deleteModelResponseFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function deleteModelResponseFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function editImageConfigToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromOutputGcsUri = getValueByPath(fromObject, ['outputGcsUri']); + if (parentObject !== undefined && fromOutputGcsUri != null) { + setValueByPath(parentObject, ['parameters', 'storageUri'], fromOutputGcsUri); + } + const fromNegativePrompt = getValueByPath(fromObject, [ + 'negativePrompt', + ]); + if (parentObject !== undefined && fromNegativePrompt != null) { + setValueByPath(parentObject, ['parameters', 'negativePrompt'], fromNegativePrompt); + } + const fromNumberOfImages = getValueByPath(fromObject, [ + 'numberOfImages', + ]); + if (parentObject !== undefined && fromNumberOfImages != null) { + setValueByPath(parentObject, ['parameters', 'sampleCount'], fromNumberOfImages); + } + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (parentObject !== undefined && fromAspectRatio != null) { + setValueByPath(parentObject, ['parameters', 'aspectRatio'], fromAspectRatio); + } + const fromGuidanceScale = getValueByPath(fromObject, [ + 'guidanceScale', + ]); + if (parentObject !== undefined && fromGuidanceScale != null) { + setValueByPath(parentObject, ['parameters', 'guidanceScale'], fromGuidanceScale); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (parentObject !== undefined && fromSeed != null) { + setValueByPath(parentObject, ['parameters', 'seed'], fromSeed); + } + const fromSafetyFilterLevel = getValueByPath(fromObject, [ + 'safetyFilterLevel', + ]); + if (parentObject !== undefined && fromSafetyFilterLevel != null) { + setValueByPath(parentObject, ['parameters', 'safetySetting'], fromSafetyFilterLevel); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (parentObject !== undefined && fromPersonGeneration != null) { + setValueByPath(parentObject, ['parameters', 'personGeneration'], fromPersonGeneration); + } + const fromIncludeSafetyAttributes = getValueByPath(fromObject, [ + 'includeSafetyAttributes', + ]); + if (parentObject !== undefined && fromIncludeSafetyAttributes != null) { + setValueByPath(parentObject, ['parameters', 'includeSafetyAttributes'], fromIncludeSafetyAttributes); + } + const fromIncludeRaiReason = getValueByPath(fromObject, [ + 'includeRaiReason', + ]); + if (parentObject !== undefined && fromIncludeRaiReason != null) { + setValueByPath(parentObject, ['parameters', 'includeRaiReason'], fromIncludeRaiReason); + } + const fromLanguage = getValueByPath(fromObject, ['language']); + if (parentObject !== undefined && fromLanguage != null) { + setValueByPath(parentObject, ['parameters', 'language'], fromLanguage); + } + const fromOutputMimeType = getValueByPath(fromObject, [ + 'outputMimeType', + ]); + if (parentObject !== undefined && fromOutputMimeType != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'mimeType'], fromOutputMimeType); + } + const fromOutputCompressionQuality = getValueByPath(fromObject, [ + 'outputCompressionQuality', + ]); + if (parentObject !== undefined && fromOutputCompressionQuality != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'compressionQuality'], fromOutputCompressionQuality); + } + const fromAddWatermark = getValueByPath(fromObject, ['addWatermark']); + if (parentObject !== undefined && fromAddWatermark != null) { + setValueByPath(parentObject, ['parameters', 'addWatermark'], fromAddWatermark); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (parentObject !== undefined && fromLabels != null) { + setValueByPath(parentObject, ['labels'], fromLabels); + } + const fromEditMode = getValueByPath(fromObject, ['editMode']); + if (parentObject !== undefined && fromEditMode != null) { + setValueByPath(parentObject, ['parameters', 'editMode'], fromEditMode); + } + const fromBaseSteps = getValueByPath(fromObject, ['baseSteps']); + if (parentObject !== undefined && fromBaseSteps != null) { + setValueByPath(parentObject, ['parameters', 'editConfig', 'baseSteps'], fromBaseSteps); + } + return toObject; +} +function editImageParametersInternalToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (fromPrompt != null) { + setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromReferenceImages = getValueByPath(fromObject, [ + 'referenceImages', + ]); + if (fromReferenceImages != null) { + let transformedList = fromReferenceImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return referenceImageAPIInternalToVertex(item); + }); + } + setValueByPath(toObject, ['instances[0]', 'referenceImages'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + editImageConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function editImageResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromGeneratedImages = getValueByPath(fromObject, [ + 'predictions', + ]); + if (fromGeneratedImages != null) { + let transformedList = fromGeneratedImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedImageFromVertex(item); + }); + } + setValueByPath(toObject, ['generatedImages'], transformedList); + } + return toObject; +} +function embedContentConfigToMldev(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromTaskType = getValueByPath(fromObject, ['taskType']); + if (parentObject !== undefined && fromTaskType != null) { + setValueByPath(parentObject, ['requests[]', 'taskType'], fromTaskType); + } + const fromTitle = getValueByPath(fromObject, ['title']); + if (parentObject !== undefined && fromTitle != null) { + setValueByPath(parentObject, ['requests[]', 'title'], fromTitle); + } + const fromOutputDimensionality = getValueByPath(fromObject, [ + 'outputDimensionality', + ]); + if (parentObject !== undefined && fromOutputDimensionality != null) { + setValueByPath(parentObject, ['requests[]', 'outputDimensionality'], fromOutputDimensionality); + } + if (getValueByPath(fromObject, ['mimeType']) !== undefined) { + throw new Error('mimeType parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['autoTruncate']) !== undefined) { + throw new Error('autoTruncate parameter is not supported in Gemini API.'); + } + return toObject; +} +function embedContentConfigToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromTaskType = getValueByPath(fromObject, ['taskType']); + if (parentObject !== undefined && fromTaskType != null) { + setValueByPath(parentObject, ['instances[]', 'task_type'], fromTaskType); + } + const fromTitle = getValueByPath(fromObject, ['title']); + if (parentObject !== undefined && fromTitle != null) { + setValueByPath(parentObject, ['instances[]', 'title'], fromTitle); + } + const fromOutputDimensionality = getValueByPath(fromObject, [ + 'outputDimensionality', + ]); + if (parentObject !== undefined && fromOutputDimensionality != null) { + setValueByPath(parentObject, ['parameters', 'outputDimensionality'], fromOutputDimensionality); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (parentObject !== undefined && fromMimeType != null) { + setValueByPath(parentObject, ['instances[]', 'mimeType'], fromMimeType); + } + const fromAutoTruncate = getValueByPath(fromObject, ['autoTruncate']); + if (parentObject !== undefined && fromAutoTruncate != null) { + setValueByPath(parentObject, ['parameters', 'autoTruncate'], fromAutoTruncate); + } + return toObject; +} +function embedContentParametersToMldev(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContentsForEmbed(apiClient, fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['requests[]', 'content'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + embedContentConfigToMldev(fromConfig, toObject); + } + const fromModelForEmbedContent = getValueByPath(fromObject, ['model']); + if (fromModelForEmbedContent !== undefined) { + setValueByPath(toObject, ['requests[]', 'model'], tModel(apiClient, fromModelForEmbedContent)); + } + return toObject; +} +function embedContentParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContentsForEmbed(apiClient, fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['instances[]', 'content'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + embedContentConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function embedContentResponseFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromEmbeddings = getValueByPath(fromObject, ['embeddings']); + if (fromEmbeddings != null) { + let transformedList = fromEmbeddings; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['embeddings'], transformedList); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + return toObject; +} +function embedContentResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromEmbeddings = getValueByPath(fromObject, [ + 'predictions[]', + 'embeddings', + ]); + if (fromEmbeddings != null) { + let transformedList = fromEmbeddings; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return contentEmbeddingFromVertex(item); + }); + } + setValueByPath(toObject, ['embeddings'], transformedList); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + return toObject; +} +function endpointFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['endpoint']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromDeployedModelId = getValueByPath(fromObject, [ + 'deployedModelId', + ]); + if (fromDeployedModelId != null) { + setValueByPath(toObject, ['deployedModelId'], fromDeployedModelId); + } + return toObject; +} +function fileDataToMldev$1(fromObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromFileUri = getValueByPath(fromObject, ['fileUri']); + if (fromFileUri != null) { + setValueByPath(toObject, ['fileUri'], fromFileUri); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function functionCallToMldev$1(fromObject, _rootObject) { + const toObject = {}; + const fromId = getValueByPath(fromObject, ['id']); + if (fromId != null) { + setValueByPath(toObject, ['id'], fromId); + } + const fromArgs = getValueByPath(fromObject, ['args']); + if (fromArgs != null) { + setValueByPath(toObject, ['args'], fromArgs); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + if (getValueByPath(fromObject, ['partialArgs']) !== undefined) { + throw new Error('partialArgs parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['willContinue']) !== undefined) { + throw new Error('willContinue parameter is not supported in Gemini API.'); + } + return toObject; +} +function functionCallingConfigToMldev(fromObject, _rootObject) { + const toObject = {}; + const fromAllowedFunctionNames = getValueByPath(fromObject, [ + 'allowedFunctionNames', + ]); + if (fromAllowedFunctionNames != null) { + setValueByPath(toObject, ['allowedFunctionNames'], fromAllowedFunctionNames); + } + const fromMode = getValueByPath(fromObject, ['mode']); + if (fromMode != null) { + setValueByPath(toObject, ['mode'], fromMode); + } + if (getValueByPath(fromObject, ['streamFunctionCallArguments']) !== + undefined) { + throw new Error('streamFunctionCallArguments parameter is not supported in Gemini API.'); + } + return toObject; +} +function functionDeclarationToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromDescription = getValueByPath(fromObject, ['description']); + if (fromDescription != null) { + setValueByPath(toObject, ['description'], fromDescription); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromParameters = getValueByPath(fromObject, ['parameters']); + if (fromParameters != null) { + setValueByPath(toObject, ['parameters'], fromParameters); + } + const fromParametersJsonSchema = getValueByPath(fromObject, [ + 'parametersJsonSchema', + ]); + if (fromParametersJsonSchema != null) { + setValueByPath(toObject, ['parametersJsonSchema'], fromParametersJsonSchema); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], fromResponse); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + if (getValueByPath(fromObject, ['behavior']) !== undefined) { + throw new Error('behavior parameter is not supported in Vertex AI.'); + } + return toObject; +} +function generateContentConfigToMldev(apiClient, fromObject, parentObject, rootObject) { + const toObject = {}; + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['systemInstruction'], contentToMldev$1(tContent(fromSystemInstruction))); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (fromTemperature != null) { + setValueByPath(toObject, ['temperature'], fromTemperature); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (fromTopP != null) { + setValueByPath(toObject, ['topP'], fromTopP); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (fromTopK != null) { + setValueByPath(toObject, ['topK'], fromTopK); + } + const fromCandidateCount = getValueByPath(fromObject, [ + 'candidateCount', + ]); + if (fromCandidateCount != null) { + setValueByPath(toObject, ['candidateCount'], fromCandidateCount); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (fromMaxOutputTokens != null) { + setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens); + } + const fromStopSequences = getValueByPath(fromObject, [ + 'stopSequences', + ]); + if (fromStopSequences != null) { + setValueByPath(toObject, ['stopSequences'], fromStopSequences); + } + const fromResponseLogprobs = getValueByPath(fromObject, [ + 'responseLogprobs', + ]); + if (fromResponseLogprobs != null) { + setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs); + } + const fromLogprobs = getValueByPath(fromObject, ['logprobs']); + if (fromLogprobs != null) { + setValueByPath(toObject, ['logprobs'], fromLogprobs); + } + const fromPresencePenalty = getValueByPath(fromObject, [ + 'presencePenalty', + ]); + if (fromPresencePenalty != null) { + setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty); + } + const fromFrequencyPenalty = getValueByPath(fromObject, [ + 'frequencyPenalty', + ]); + if (fromFrequencyPenalty != null) { + setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (fromSeed != null) { + setValueByPath(toObject, ['seed'], fromSeed); + } + const fromResponseMimeType = getValueByPath(fromObject, [ + 'responseMimeType', + ]); + if (fromResponseMimeType != null) { + setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType); + } + const fromResponseSchema = getValueByPath(fromObject, [ + 'responseSchema', + ]); + if (fromResponseSchema != null) { + setValueByPath(toObject, ['responseSchema'], tSchema(fromResponseSchema)); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + if (getValueByPath(fromObject, ['routingConfig']) !== undefined) { + throw new Error('routingConfig parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['modelSelectionConfig']) !== undefined) { + throw new Error('modelSelectionConfig parameter is not supported in Gemini API.'); + } + const fromSafetySettings = getValueByPath(fromObject, [ + 'safetySettings', + ]); + if (parentObject !== undefined && fromSafetySettings != null) { + let transformedList = fromSafetySettings; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return safetySettingToMldev(item); + }); + } + setValueByPath(parentObject, ['safetySettings'], transformedList); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = tTools(fromTools); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToMldev$1(tTool(item)); + }); + } + setValueByPath(parentObject, ['tools'], transformedList); + } + const fromToolConfig = getValueByPath(fromObject, ['toolConfig']); + if (parentObject !== undefined && fromToolConfig != null) { + setValueByPath(parentObject, ['toolConfig'], toolConfigToMldev(fromToolConfig)); + } + if (getValueByPath(fromObject, ['labels']) !== undefined) { + throw new Error('labels parameter is not supported in Gemini API.'); + } + const fromCachedContent = getValueByPath(fromObject, [ + 'cachedContent', + ]); + if (parentObject !== undefined && fromCachedContent != null) { + setValueByPath(parentObject, ['cachedContent'], tCachedContentName(apiClient, fromCachedContent)); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (fromResponseModalities != null) { + setValueByPath(toObject, ['responseModalities'], fromResponseModalities); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (fromSpeechConfig != null) { + setValueByPath(toObject, ['speechConfig'], tSpeechConfig(fromSpeechConfig)); + } + if (getValueByPath(fromObject, ['audioTimestamp']) !== undefined) { + throw new Error('audioTimestamp parameter is not supported in Gemini API.'); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (fromThinkingConfig != null) { + setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig); + } + const fromImageConfig = getValueByPath(fromObject, ['imageConfig']); + if (fromImageConfig != null) { + setValueByPath(toObject, ['imageConfig'], imageConfigToMldev(fromImageConfig)); + } + const fromEnableEnhancedCivicAnswers = getValueByPath(fromObject, [ + 'enableEnhancedCivicAnswers', + ]); + if (fromEnableEnhancedCivicAnswers != null) { + setValueByPath(toObject, ['enableEnhancedCivicAnswers'], fromEnableEnhancedCivicAnswers); + } + if (getValueByPath(fromObject, ['modelArmorConfig']) !== undefined) { + throw new Error('modelArmorConfig parameter is not supported in Gemini API.'); + } + return toObject; +} +function generateContentConfigToVertex(apiClient, fromObject, parentObject, rootObject) { + const toObject = {}; + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['systemInstruction'], tContent(fromSystemInstruction)); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (fromTemperature != null) { + setValueByPath(toObject, ['temperature'], fromTemperature); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (fromTopP != null) { + setValueByPath(toObject, ['topP'], fromTopP); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (fromTopK != null) { + setValueByPath(toObject, ['topK'], fromTopK); + } + const fromCandidateCount = getValueByPath(fromObject, [ + 'candidateCount', + ]); + if (fromCandidateCount != null) { + setValueByPath(toObject, ['candidateCount'], fromCandidateCount); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (fromMaxOutputTokens != null) { + setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens); + } + const fromStopSequences = getValueByPath(fromObject, [ + 'stopSequences', + ]); + if (fromStopSequences != null) { + setValueByPath(toObject, ['stopSequences'], fromStopSequences); + } + const fromResponseLogprobs = getValueByPath(fromObject, [ + 'responseLogprobs', + ]); + if (fromResponseLogprobs != null) { + setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs); + } + const fromLogprobs = getValueByPath(fromObject, ['logprobs']); + if (fromLogprobs != null) { + setValueByPath(toObject, ['logprobs'], fromLogprobs); + } + const fromPresencePenalty = getValueByPath(fromObject, [ + 'presencePenalty', + ]); + if (fromPresencePenalty != null) { + setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty); + } + const fromFrequencyPenalty = getValueByPath(fromObject, [ + 'frequencyPenalty', + ]); + if (fromFrequencyPenalty != null) { + setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (fromSeed != null) { + setValueByPath(toObject, ['seed'], fromSeed); + } + const fromResponseMimeType = getValueByPath(fromObject, [ + 'responseMimeType', + ]); + if (fromResponseMimeType != null) { + setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType); + } + const fromResponseSchema = getValueByPath(fromObject, [ + 'responseSchema', + ]); + if (fromResponseSchema != null) { + setValueByPath(toObject, ['responseSchema'], tSchema(fromResponseSchema)); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + const fromRoutingConfig = getValueByPath(fromObject, [ + 'routingConfig', + ]); + if (fromRoutingConfig != null) { + setValueByPath(toObject, ['routingConfig'], fromRoutingConfig); + } + const fromModelSelectionConfig = getValueByPath(fromObject, [ + 'modelSelectionConfig', + ]); + if (fromModelSelectionConfig != null) { + setValueByPath(toObject, ['modelConfig'], fromModelSelectionConfig); + } + const fromSafetySettings = getValueByPath(fromObject, [ + 'safetySettings', + ]); + if (parentObject !== undefined && fromSafetySettings != null) { + let transformedList = fromSafetySettings; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(parentObject, ['safetySettings'], transformedList); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = tTools(fromTools); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToVertex(tTool(item)); + }); + } + setValueByPath(parentObject, ['tools'], transformedList); + } + const fromToolConfig = getValueByPath(fromObject, ['toolConfig']); + if (parentObject !== undefined && fromToolConfig != null) { + setValueByPath(parentObject, ['toolConfig'], fromToolConfig); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (parentObject !== undefined && fromLabels != null) { + setValueByPath(parentObject, ['labels'], fromLabels); + } + const fromCachedContent = getValueByPath(fromObject, [ + 'cachedContent', + ]); + if (parentObject !== undefined && fromCachedContent != null) { + setValueByPath(parentObject, ['cachedContent'], tCachedContentName(apiClient, fromCachedContent)); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (fromResponseModalities != null) { + setValueByPath(toObject, ['responseModalities'], fromResponseModalities); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (fromSpeechConfig != null) { + setValueByPath(toObject, ['speechConfig'], tSpeechConfig(fromSpeechConfig)); + } + const fromAudioTimestamp = getValueByPath(fromObject, [ + 'audioTimestamp', + ]); + if (fromAudioTimestamp != null) { + setValueByPath(toObject, ['audioTimestamp'], fromAudioTimestamp); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (fromThinkingConfig != null) { + setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig); + } + const fromImageConfig = getValueByPath(fromObject, ['imageConfig']); + if (fromImageConfig != null) { + setValueByPath(toObject, ['imageConfig'], imageConfigToVertex(fromImageConfig)); + } + if (getValueByPath(fromObject, ['enableEnhancedCivicAnswers']) !== + undefined) { + throw new Error('enableEnhancedCivicAnswers parameter is not supported in Vertex AI.'); + } + const fromModelArmorConfig = getValueByPath(fromObject, [ + 'modelArmorConfig', + ]); + if (parentObject !== undefined && fromModelArmorConfig != null) { + setValueByPath(parentObject, ['modelArmorConfig'], fromModelArmorConfig); + } + return toObject; +} +function generateContentParametersToMldev(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return contentToMldev$1(item); + }); + } + setValueByPath(toObject, ['contents'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['generationConfig'], generateContentConfigToMldev(apiClient, fromConfig, toObject)); + } + return toObject; +} +function generateContentParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['contents'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['generationConfig'], generateContentConfigToVertex(apiClient, fromConfig, toObject)); + } + return toObject; +} +function generateContentResponseFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromCandidates = getValueByPath(fromObject, ['candidates']); + if (fromCandidates != null) { + let transformedList = fromCandidates; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return candidateFromMldev(item); + }); + } + setValueByPath(toObject, ['candidates'], transformedList); + } + const fromModelVersion = getValueByPath(fromObject, ['modelVersion']); + if (fromModelVersion != null) { + setValueByPath(toObject, ['modelVersion'], fromModelVersion); + } + const fromPromptFeedback = getValueByPath(fromObject, [ + 'promptFeedback', + ]); + if (fromPromptFeedback != null) { + setValueByPath(toObject, ['promptFeedback'], fromPromptFeedback); + } + const fromResponseId = getValueByPath(fromObject, ['responseId']); + if (fromResponseId != null) { + setValueByPath(toObject, ['responseId'], fromResponseId); + } + const fromUsageMetadata = getValueByPath(fromObject, [ + 'usageMetadata', + ]); + if (fromUsageMetadata != null) { + setValueByPath(toObject, ['usageMetadata'], fromUsageMetadata); + } + return toObject; +} +function generateContentResponseFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromCandidates = getValueByPath(fromObject, ['candidates']); + if (fromCandidates != null) { + let transformedList = fromCandidates; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['candidates'], transformedList); + } + const fromCreateTime = getValueByPath(fromObject, ['createTime']); + if (fromCreateTime != null) { + setValueByPath(toObject, ['createTime'], fromCreateTime); + } + const fromModelVersion = getValueByPath(fromObject, ['modelVersion']); + if (fromModelVersion != null) { + setValueByPath(toObject, ['modelVersion'], fromModelVersion); + } + const fromPromptFeedback = getValueByPath(fromObject, [ + 'promptFeedback', + ]); + if (fromPromptFeedback != null) { + setValueByPath(toObject, ['promptFeedback'], fromPromptFeedback); + } + const fromResponseId = getValueByPath(fromObject, ['responseId']); + if (fromResponseId != null) { + setValueByPath(toObject, ['responseId'], fromResponseId); + } + const fromUsageMetadata = getValueByPath(fromObject, [ + 'usageMetadata', + ]); + if (fromUsageMetadata != null) { + setValueByPath(toObject, ['usageMetadata'], fromUsageMetadata); + } + return toObject; +} +function generateImagesConfigToMldev(fromObject, parentObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['outputGcsUri']) !== undefined) { + throw new Error('outputGcsUri parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['negativePrompt']) !== undefined) { + throw new Error('negativePrompt parameter is not supported in Gemini API.'); + } + const fromNumberOfImages = getValueByPath(fromObject, [ + 'numberOfImages', + ]); + if (parentObject !== undefined && fromNumberOfImages != null) { + setValueByPath(parentObject, ['parameters', 'sampleCount'], fromNumberOfImages); + } + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (parentObject !== undefined && fromAspectRatio != null) { + setValueByPath(parentObject, ['parameters', 'aspectRatio'], fromAspectRatio); + } + const fromGuidanceScale = getValueByPath(fromObject, [ + 'guidanceScale', + ]); + if (parentObject !== undefined && fromGuidanceScale != null) { + setValueByPath(parentObject, ['parameters', 'guidanceScale'], fromGuidanceScale); + } + if (getValueByPath(fromObject, ['seed']) !== undefined) { + throw new Error('seed parameter is not supported in Gemini API.'); + } + const fromSafetyFilterLevel = getValueByPath(fromObject, [ + 'safetyFilterLevel', + ]); + if (parentObject !== undefined && fromSafetyFilterLevel != null) { + setValueByPath(parentObject, ['parameters', 'safetySetting'], fromSafetyFilterLevel); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (parentObject !== undefined && fromPersonGeneration != null) { + setValueByPath(parentObject, ['parameters', 'personGeneration'], fromPersonGeneration); + } + const fromIncludeSafetyAttributes = getValueByPath(fromObject, [ + 'includeSafetyAttributes', + ]); + if (parentObject !== undefined && fromIncludeSafetyAttributes != null) { + setValueByPath(parentObject, ['parameters', 'includeSafetyAttributes'], fromIncludeSafetyAttributes); + } + const fromIncludeRaiReason = getValueByPath(fromObject, [ + 'includeRaiReason', + ]); + if (parentObject !== undefined && fromIncludeRaiReason != null) { + setValueByPath(parentObject, ['parameters', 'includeRaiReason'], fromIncludeRaiReason); + } + const fromLanguage = getValueByPath(fromObject, ['language']); + if (parentObject !== undefined && fromLanguage != null) { + setValueByPath(parentObject, ['parameters', 'language'], fromLanguage); + } + const fromOutputMimeType = getValueByPath(fromObject, [ + 'outputMimeType', + ]); + if (parentObject !== undefined && fromOutputMimeType != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'mimeType'], fromOutputMimeType); + } + const fromOutputCompressionQuality = getValueByPath(fromObject, [ + 'outputCompressionQuality', + ]); + if (parentObject !== undefined && fromOutputCompressionQuality != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'compressionQuality'], fromOutputCompressionQuality); + } + if (getValueByPath(fromObject, ['addWatermark']) !== undefined) { + throw new Error('addWatermark parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['labels']) !== undefined) { + throw new Error('labels parameter is not supported in Gemini API.'); + } + const fromImageSize = getValueByPath(fromObject, ['imageSize']); + if (parentObject !== undefined && fromImageSize != null) { + setValueByPath(parentObject, ['parameters', 'sampleImageSize'], fromImageSize); + } + if (getValueByPath(fromObject, ['enhancePrompt']) !== undefined) { + throw new Error('enhancePrompt parameter is not supported in Gemini API.'); + } + return toObject; +} +function generateImagesConfigToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromOutputGcsUri = getValueByPath(fromObject, ['outputGcsUri']); + if (parentObject !== undefined && fromOutputGcsUri != null) { + setValueByPath(parentObject, ['parameters', 'storageUri'], fromOutputGcsUri); + } + const fromNegativePrompt = getValueByPath(fromObject, [ + 'negativePrompt', + ]); + if (parentObject !== undefined && fromNegativePrompt != null) { + setValueByPath(parentObject, ['parameters', 'negativePrompt'], fromNegativePrompt); + } + const fromNumberOfImages = getValueByPath(fromObject, [ + 'numberOfImages', + ]); + if (parentObject !== undefined && fromNumberOfImages != null) { + setValueByPath(parentObject, ['parameters', 'sampleCount'], fromNumberOfImages); + } + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (parentObject !== undefined && fromAspectRatio != null) { + setValueByPath(parentObject, ['parameters', 'aspectRatio'], fromAspectRatio); + } + const fromGuidanceScale = getValueByPath(fromObject, [ + 'guidanceScale', + ]); + if (parentObject !== undefined && fromGuidanceScale != null) { + setValueByPath(parentObject, ['parameters', 'guidanceScale'], fromGuidanceScale); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (parentObject !== undefined && fromSeed != null) { + setValueByPath(parentObject, ['parameters', 'seed'], fromSeed); + } + const fromSafetyFilterLevel = getValueByPath(fromObject, [ + 'safetyFilterLevel', + ]); + if (parentObject !== undefined && fromSafetyFilterLevel != null) { + setValueByPath(parentObject, ['parameters', 'safetySetting'], fromSafetyFilterLevel); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (parentObject !== undefined && fromPersonGeneration != null) { + setValueByPath(parentObject, ['parameters', 'personGeneration'], fromPersonGeneration); + } + const fromIncludeSafetyAttributes = getValueByPath(fromObject, [ + 'includeSafetyAttributes', + ]); + if (parentObject !== undefined && fromIncludeSafetyAttributes != null) { + setValueByPath(parentObject, ['parameters', 'includeSafetyAttributes'], fromIncludeSafetyAttributes); + } + const fromIncludeRaiReason = getValueByPath(fromObject, [ + 'includeRaiReason', + ]); + if (parentObject !== undefined && fromIncludeRaiReason != null) { + setValueByPath(parentObject, ['parameters', 'includeRaiReason'], fromIncludeRaiReason); + } + const fromLanguage = getValueByPath(fromObject, ['language']); + if (parentObject !== undefined && fromLanguage != null) { + setValueByPath(parentObject, ['parameters', 'language'], fromLanguage); + } + const fromOutputMimeType = getValueByPath(fromObject, [ + 'outputMimeType', + ]); + if (parentObject !== undefined && fromOutputMimeType != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'mimeType'], fromOutputMimeType); + } + const fromOutputCompressionQuality = getValueByPath(fromObject, [ + 'outputCompressionQuality', + ]); + if (parentObject !== undefined && fromOutputCompressionQuality != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'compressionQuality'], fromOutputCompressionQuality); + } + const fromAddWatermark = getValueByPath(fromObject, ['addWatermark']); + if (parentObject !== undefined && fromAddWatermark != null) { + setValueByPath(parentObject, ['parameters', 'addWatermark'], fromAddWatermark); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (parentObject !== undefined && fromLabels != null) { + setValueByPath(parentObject, ['labels'], fromLabels); + } + const fromImageSize = getValueByPath(fromObject, ['imageSize']); + if (parentObject !== undefined && fromImageSize != null) { + setValueByPath(parentObject, ['parameters', 'sampleImageSize'], fromImageSize); + } + const fromEnhancePrompt = getValueByPath(fromObject, [ + 'enhancePrompt', + ]); + if (parentObject !== undefined && fromEnhancePrompt != null) { + setValueByPath(parentObject, ['parameters', 'enhancePrompt'], fromEnhancePrompt); + } + return toObject; +} +function generateImagesParametersToMldev(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (fromPrompt != null) { + setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + generateImagesConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function generateImagesParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (fromPrompt != null) { + setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + generateImagesConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function generateImagesResponseFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromGeneratedImages = getValueByPath(fromObject, [ + 'predictions', + ]); + if (fromGeneratedImages != null) { + let transformedList = fromGeneratedImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedImageFromMldev(item); + }); + } + setValueByPath(toObject, ['generatedImages'], transformedList); + } + const fromPositivePromptSafetyAttributes = getValueByPath(fromObject, [ + 'positivePromptSafetyAttributes', + ]); + if (fromPositivePromptSafetyAttributes != null) { + setValueByPath(toObject, ['positivePromptSafetyAttributes'], safetyAttributesFromMldev(fromPositivePromptSafetyAttributes)); + } + return toObject; +} +function generateImagesResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromGeneratedImages = getValueByPath(fromObject, [ + 'predictions', + ]); + if (fromGeneratedImages != null) { + let transformedList = fromGeneratedImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedImageFromVertex(item); + }); + } + setValueByPath(toObject, ['generatedImages'], transformedList); + } + const fromPositivePromptSafetyAttributes = getValueByPath(fromObject, [ + 'positivePromptSafetyAttributes', + ]); + if (fromPositivePromptSafetyAttributes != null) { + setValueByPath(toObject, ['positivePromptSafetyAttributes'], safetyAttributesFromVertex(fromPositivePromptSafetyAttributes)); + } + return toObject; +} +function generateVideosConfigToMldev(fromObject, parentObject, rootObject) { + const toObject = {}; + const fromNumberOfVideos = getValueByPath(fromObject, [ + 'numberOfVideos', + ]); + if (parentObject !== undefined && fromNumberOfVideos != null) { + setValueByPath(parentObject, ['parameters', 'sampleCount'], fromNumberOfVideos); + } + if (getValueByPath(fromObject, ['outputGcsUri']) !== undefined) { + throw new Error('outputGcsUri parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['fps']) !== undefined) { + throw new Error('fps parameter is not supported in Gemini API.'); + } + const fromDurationSeconds = getValueByPath(fromObject, [ + 'durationSeconds', + ]); + if (parentObject !== undefined && fromDurationSeconds != null) { + setValueByPath(parentObject, ['parameters', 'durationSeconds'], fromDurationSeconds); + } + if (getValueByPath(fromObject, ['seed']) !== undefined) { + throw new Error('seed parameter is not supported in Gemini API.'); + } + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (parentObject !== undefined && fromAspectRatio != null) { + setValueByPath(parentObject, ['parameters', 'aspectRatio'], fromAspectRatio); + } + const fromResolution = getValueByPath(fromObject, ['resolution']); + if (parentObject !== undefined && fromResolution != null) { + setValueByPath(parentObject, ['parameters', 'resolution'], fromResolution); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (parentObject !== undefined && fromPersonGeneration != null) { + setValueByPath(parentObject, ['parameters', 'personGeneration'], fromPersonGeneration); + } + if (getValueByPath(fromObject, ['pubsubTopic']) !== undefined) { + throw new Error('pubsubTopic parameter is not supported in Gemini API.'); + } + const fromNegativePrompt = getValueByPath(fromObject, [ + 'negativePrompt', + ]); + if (parentObject !== undefined && fromNegativePrompt != null) { + setValueByPath(parentObject, ['parameters', 'negativePrompt'], fromNegativePrompt); + } + const fromEnhancePrompt = getValueByPath(fromObject, [ + 'enhancePrompt', + ]); + if (parentObject !== undefined && fromEnhancePrompt != null) { + setValueByPath(parentObject, ['parameters', 'enhancePrompt'], fromEnhancePrompt); + } + if (getValueByPath(fromObject, ['generateAudio']) !== undefined) { + throw new Error('generateAudio parameter is not supported in Gemini API.'); + } + const fromLastFrame = getValueByPath(fromObject, ['lastFrame']); + if (parentObject !== undefined && fromLastFrame != null) { + setValueByPath(parentObject, ['instances[0]', 'lastFrame'], imageToMldev(fromLastFrame)); + } + const fromReferenceImages = getValueByPath(fromObject, [ + 'referenceImages', + ]); + if (parentObject !== undefined && fromReferenceImages != null) { + let transformedList = fromReferenceImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return videoGenerationReferenceImageToMldev(item); + }); + } + setValueByPath(parentObject, ['instances[0]', 'referenceImages'], transformedList); + } + if (getValueByPath(fromObject, ['mask']) !== undefined) { + throw new Error('mask parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['compressionQuality']) !== undefined) { + throw new Error('compressionQuality parameter is not supported in Gemini API.'); + } + return toObject; +} +function generateVideosConfigToVertex(fromObject, parentObject, rootObject) { + const toObject = {}; + const fromNumberOfVideos = getValueByPath(fromObject, [ + 'numberOfVideos', + ]); + if (parentObject !== undefined && fromNumberOfVideos != null) { + setValueByPath(parentObject, ['parameters', 'sampleCount'], fromNumberOfVideos); + } + const fromOutputGcsUri = getValueByPath(fromObject, ['outputGcsUri']); + if (parentObject !== undefined && fromOutputGcsUri != null) { + setValueByPath(parentObject, ['parameters', 'storageUri'], fromOutputGcsUri); + } + const fromFps = getValueByPath(fromObject, ['fps']); + if (parentObject !== undefined && fromFps != null) { + setValueByPath(parentObject, ['parameters', 'fps'], fromFps); + } + const fromDurationSeconds = getValueByPath(fromObject, [ + 'durationSeconds', + ]); + if (parentObject !== undefined && fromDurationSeconds != null) { + setValueByPath(parentObject, ['parameters', 'durationSeconds'], fromDurationSeconds); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (parentObject !== undefined && fromSeed != null) { + setValueByPath(parentObject, ['parameters', 'seed'], fromSeed); + } + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (parentObject !== undefined && fromAspectRatio != null) { + setValueByPath(parentObject, ['parameters', 'aspectRatio'], fromAspectRatio); + } + const fromResolution = getValueByPath(fromObject, ['resolution']); + if (parentObject !== undefined && fromResolution != null) { + setValueByPath(parentObject, ['parameters', 'resolution'], fromResolution); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (parentObject !== undefined && fromPersonGeneration != null) { + setValueByPath(parentObject, ['parameters', 'personGeneration'], fromPersonGeneration); + } + const fromPubsubTopic = getValueByPath(fromObject, ['pubsubTopic']); + if (parentObject !== undefined && fromPubsubTopic != null) { + setValueByPath(parentObject, ['parameters', 'pubsubTopic'], fromPubsubTopic); + } + const fromNegativePrompt = getValueByPath(fromObject, [ + 'negativePrompt', + ]); + if (parentObject !== undefined && fromNegativePrompt != null) { + setValueByPath(parentObject, ['parameters', 'negativePrompt'], fromNegativePrompt); + } + const fromEnhancePrompt = getValueByPath(fromObject, [ + 'enhancePrompt', + ]); + if (parentObject !== undefined && fromEnhancePrompt != null) { + setValueByPath(parentObject, ['parameters', 'enhancePrompt'], fromEnhancePrompt); + } + const fromGenerateAudio = getValueByPath(fromObject, [ + 'generateAudio', + ]); + if (parentObject !== undefined && fromGenerateAudio != null) { + setValueByPath(parentObject, ['parameters', 'generateAudio'], fromGenerateAudio); + } + const fromLastFrame = getValueByPath(fromObject, ['lastFrame']); + if (parentObject !== undefined && fromLastFrame != null) { + setValueByPath(parentObject, ['instances[0]', 'lastFrame'], imageToVertex(fromLastFrame)); + } + const fromReferenceImages = getValueByPath(fromObject, [ + 'referenceImages', + ]); + if (parentObject !== undefined && fromReferenceImages != null) { + let transformedList = fromReferenceImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return videoGenerationReferenceImageToVertex(item); + }); + } + setValueByPath(parentObject, ['instances[0]', 'referenceImages'], transformedList); + } + const fromMask = getValueByPath(fromObject, ['mask']); + if (parentObject !== undefined && fromMask != null) { + setValueByPath(parentObject, ['instances[0]', 'mask'], videoGenerationMaskToVertex(fromMask)); + } + const fromCompressionQuality = getValueByPath(fromObject, [ + 'compressionQuality', + ]); + if (parentObject !== undefined && fromCompressionQuality != null) { + setValueByPath(parentObject, ['parameters', 'compressionQuality'], fromCompressionQuality); + } + return toObject; +} +function generateVideosOperationFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromResponse = getValueByPath(fromObject, [ + 'response', + 'generateVideoResponse', + ]); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], generateVideosResponseFromMldev(fromResponse)); + } + return toObject; +} +function generateVideosOperationFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], generateVideosResponseFromVertex(fromResponse)); + } + return toObject; +} +function generateVideosParametersToMldev(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (fromPrompt != null) { + setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromImage = getValueByPath(fromObject, ['image']); + if (fromImage != null) { + setValueByPath(toObject, ['instances[0]', 'image'], imageToMldev(fromImage)); + } + const fromVideo = getValueByPath(fromObject, ['video']); + if (fromVideo != null) { + setValueByPath(toObject, ['instances[0]', 'video'], videoToMldev(fromVideo)); + } + const fromSource = getValueByPath(fromObject, ['source']); + if (fromSource != null) { + generateVideosSourceToMldev(fromSource, toObject); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + generateVideosConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function generateVideosParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (fromPrompt != null) { + setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromImage = getValueByPath(fromObject, ['image']); + if (fromImage != null) { + setValueByPath(toObject, ['instances[0]', 'image'], imageToVertex(fromImage)); + } + const fromVideo = getValueByPath(fromObject, ['video']); + if (fromVideo != null) { + setValueByPath(toObject, ['instances[0]', 'video'], videoToVertex(fromVideo)); + } + const fromSource = getValueByPath(fromObject, ['source']); + if (fromSource != null) { + generateVideosSourceToVertex(fromSource, toObject); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + generateVideosConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function generateVideosResponseFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromGeneratedVideos = getValueByPath(fromObject, [ + 'generatedSamples', + ]); + if (fromGeneratedVideos != null) { + let transformedList = fromGeneratedVideos; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedVideoFromMldev(item); + }); + } + setValueByPath(toObject, ['generatedVideos'], transformedList); + } + const fromRaiMediaFilteredCount = getValueByPath(fromObject, [ + 'raiMediaFilteredCount', + ]); + if (fromRaiMediaFilteredCount != null) { + setValueByPath(toObject, ['raiMediaFilteredCount'], fromRaiMediaFilteredCount); + } + const fromRaiMediaFilteredReasons = getValueByPath(fromObject, [ + 'raiMediaFilteredReasons', + ]); + if (fromRaiMediaFilteredReasons != null) { + setValueByPath(toObject, ['raiMediaFilteredReasons'], fromRaiMediaFilteredReasons); + } + return toObject; +} +function generateVideosResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromGeneratedVideos = getValueByPath(fromObject, ['videos']); + if (fromGeneratedVideos != null) { + let transformedList = fromGeneratedVideos; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedVideoFromVertex(item); + }); + } + setValueByPath(toObject, ['generatedVideos'], transformedList); + } + const fromRaiMediaFilteredCount = getValueByPath(fromObject, [ + 'raiMediaFilteredCount', + ]); + if (fromRaiMediaFilteredCount != null) { + setValueByPath(toObject, ['raiMediaFilteredCount'], fromRaiMediaFilteredCount); + } + const fromRaiMediaFilteredReasons = getValueByPath(fromObject, [ + 'raiMediaFilteredReasons', + ]); + if (fromRaiMediaFilteredReasons != null) { + setValueByPath(toObject, ['raiMediaFilteredReasons'], fromRaiMediaFilteredReasons); + } + return toObject; +} +function generateVideosSourceToMldev(fromObject, parentObject, rootObject) { + const toObject = {}; + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (parentObject !== undefined && fromPrompt != null) { + setValueByPath(parentObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromImage = getValueByPath(fromObject, ['image']); + if (parentObject !== undefined && fromImage != null) { + setValueByPath(parentObject, ['instances[0]', 'image'], imageToMldev(fromImage)); + } + const fromVideo = getValueByPath(fromObject, ['video']); + if (parentObject !== undefined && fromVideo != null) { + setValueByPath(parentObject, ['instances[0]', 'video'], videoToMldev(fromVideo)); + } + return toObject; +} +function generateVideosSourceToVertex(fromObject, parentObject, rootObject) { + const toObject = {}; + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (parentObject !== undefined && fromPrompt != null) { + setValueByPath(parentObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromImage = getValueByPath(fromObject, ['image']); + if (parentObject !== undefined && fromImage != null) { + setValueByPath(parentObject, ['instances[0]', 'image'], imageToVertex(fromImage)); + } + const fromVideo = getValueByPath(fromObject, ['video']); + if (parentObject !== undefined && fromVideo != null) { + setValueByPath(parentObject, ['instances[0]', 'video'], videoToVertex(fromVideo)); + } + return toObject; +} +function generatedImageFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromImage = getValueByPath(fromObject, ['_self']); + if (fromImage != null) { + setValueByPath(toObject, ['image'], imageFromMldev(fromImage)); + } + const fromRaiFilteredReason = getValueByPath(fromObject, [ + 'raiFilteredReason', + ]); + if (fromRaiFilteredReason != null) { + setValueByPath(toObject, ['raiFilteredReason'], fromRaiFilteredReason); + } + const fromSafetyAttributes = getValueByPath(fromObject, ['_self']); + if (fromSafetyAttributes != null) { + setValueByPath(toObject, ['safetyAttributes'], safetyAttributesFromMldev(fromSafetyAttributes)); + } + return toObject; +} +function generatedImageFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromImage = getValueByPath(fromObject, ['_self']); + if (fromImage != null) { + setValueByPath(toObject, ['image'], imageFromVertex(fromImage)); + } + const fromRaiFilteredReason = getValueByPath(fromObject, [ + 'raiFilteredReason', + ]); + if (fromRaiFilteredReason != null) { + setValueByPath(toObject, ['raiFilteredReason'], fromRaiFilteredReason); + } + const fromSafetyAttributes = getValueByPath(fromObject, ['_self']); + if (fromSafetyAttributes != null) { + setValueByPath(toObject, ['safetyAttributes'], safetyAttributesFromVertex(fromSafetyAttributes)); + } + const fromEnhancedPrompt = getValueByPath(fromObject, ['prompt']); + if (fromEnhancedPrompt != null) { + setValueByPath(toObject, ['enhancedPrompt'], fromEnhancedPrompt); + } + return toObject; +} +function generatedImageMaskFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromMask = getValueByPath(fromObject, ['_self']); + if (fromMask != null) { + setValueByPath(toObject, ['mask'], imageFromVertex(fromMask)); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (fromLabels != null) { + let transformedList = fromLabels; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['labels'], transformedList); + } + return toObject; +} +function generatedVideoFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromVideo = getValueByPath(fromObject, ['video']); + if (fromVideo != null) { + setValueByPath(toObject, ['video'], videoFromMldev(fromVideo)); + } + return toObject; +} +function generatedVideoFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromVideo = getValueByPath(fromObject, ['_self']); + if (fromVideo != null) { + setValueByPath(toObject, ['video'], videoFromVertex(fromVideo)); + } + return toObject; +} +function generationConfigToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromModelSelectionConfig = getValueByPath(fromObject, [ + 'modelSelectionConfig', + ]); + if (fromModelSelectionConfig != null) { + setValueByPath(toObject, ['modelConfig'], fromModelSelectionConfig); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + const fromAudioTimestamp = getValueByPath(fromObject, [ + 'audioTimestamp', + ]); + if (fromAudioTimestamp != null) { + setValueByPath(toObject, ['audioTimestamp'], fromAudioTimestamp); + } + const fromCandidateCount = getValueByPath(fromObject, [ + 'candidateCount', + ]); + if (fromCandidateCount != null) { + setValueByPath(toObject, ['candidateCount'], fromCandidateCount); + } + const fromEnableAffectiveDialog = getValueByPath(fromObject, [ + 'enableAffectiveDialog', + ]); + if (fromEnableAffectiveDialog != null) { + setValueByPath(toObject, ['enableAffectiveDialog'], fromEnableAffectiveDialog); + } + const fromFrequencyPenalty = getValueByPath(fromObject, [ + 'frequencyPenalty', + ]); + if (fromFrequencyPenalty != null) { + setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty); + } + const fromLogprobs = getValueByPath(fromObject, ['logprobs']); + if (fromLogprobs != null) { + setValueByPath(toObject, ['logprobs'], fromLogprobs); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (fromMaxOutputTokens != null) { + setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromPresencePenalty = getValueByPath(fromObject, [ + 'presencePenalty', + ]); + if (fromPresencePenalty != null) { + setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty); + } + const fromResponseLogprobs = getValueByPath(fromObject, [ + 'responseLogprobs', + ]); + if (fromResponseLogprobs != null) { + setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs); + } + const fromResponseMimeType = getValueByPath(fromObject, [ + 'responseMimeType', + ]); + if (fromResponseMimeType != null) { + setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (fromResponseModalities != null) { + setValueByPath(toObject, ['responseModalities'], fromResponseModalities); + } + const fromResponseSchema = getValueByPath(fromObject, [ + 'responseSchema', + ]); + if (fromResponseSchema != null) { + setValueByPath(toObject, ['responseSchema'], fromResponseSchema); + } + const fromRoutingConfig = getValueByPath(fromObject, [ + 'routingConfig', + ]); + if (fromRoutingConfig != null) { + setValueByPath(toObject, ['routingConfig'], fromRoutingConfig); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (fromSeed != null) { + setValueByPath(toObject, ['seed'], fromSeed); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (fromSpeechConfig != null) { + setValueByPath(toObject, ['speechConfig'], fromSpeechConfig); + } + const fromStopSequences = getValueByPath(fromObject, [ + 'stopSequences', + ]); + if (fromStopSequences != null) { + setValueByPath(toObject, ['stopSequences'], fromStopSequences); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (fromTemperature != null) { + setValueByPath(toObject, ['temperature'], fromTemperature); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (fromThinkingConfig != null) { + setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (fromTopK != null) { + setValueByPath(toObject, ['topK'], fromTopK); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (fromTopP != null) { + setValueByPath(toObject, ['topP'], fromTopP); + } + if (getValueByPath(fromObject, ['enableEnhancedCivicAnswers']) !== + undefined) { + throw new Error('enableEnhancedCivicAnswers parameter is not supported in Vertex AI.'); + } + return toObject; +} +function getModelParametersToMldev(apiClient, fromObject, _rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'name'], tModel(apiClient, fromModel)); + } + return toObject; +} +function getModelParametersToVertex(apiClient, fromObject, _rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'name'], tModel(apiClient, fromModel)); + } + return toObject; +} +function googleMapsToMldev$1(fromObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['authConfig']) !== undefined) { + throw new Error('authConfig parameter is not supported in Gemini API.'); + } + const fromEnableWidget = getValueByPath(fromObject, ['enableWidget']); + if (fromEnableWidget != null) { + setValueByPath(toObject, ['enableWidget'], fromEnableWidget); + } + return toObject; +} +function googleSearchToMldev$1(fromObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['excludeDomains']) !== undefined) { + throw new Error('excludeDomains parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['blockingConfidence']) !== undefined) { + throw new Error('blockingConfidence parameter is not supported in Gemini API.'); + } + const fromTimeRangeFilter = getValueByPath(fromObject, [ + 'timeRangeFilter', + ]); + if (fromTimeRangeFilter != null) { + setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter); + } + return toObject; +} +function imageConfigToMldev(fromObject, _rootObject) { + const toObject = {}; + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (fromAspectRatio != null) { + setValueByPath(toObject, ['aspectRatio'], fromAspectRatio); + } + const fromImageSize = getValueByPath(fromObject, ['imageSize']); + if (fromImageSize != null) { + setValueByPath(toObject, ['imageSize'], fromImageSize); + } + if (getValueByPath(fromObject, ['personGeneration']) !== undefined) { + throw new Error('personGeneration parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['outputMimeType']) !== undefined) { + throw new Error('outputMimeType parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['outputCompressionQuality']) !== + undefined) { + throw new Error('outputCompressionQuality parameter is not supported in Gemini API.'); + } + return toObject; +} +function imageConfigToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (fromAspectRatio != null) { + setValueByPath(toObject, ['aspectRatio'], fromAspectRatio); + } + const fromImageSize = getValueByPath(fromObject, ['imageSize']); + if (fromImageSize != null) { + setValueByPath(toObject, ['imageSize'], fromImageSize); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (fromPersonGeneration != null) { + setValueByPath(toObject, ['personGeneration'], fromPersonGeneration); + } + const fromOutputMimeType = getValueByPath(fromObject, [ + 'outputMimeType', + ]); + if (fromOutputMimeType != null) { + setValueByPath(toObject, ['imageOutputOptions', 'mimeType'], fromOutputMimeType); + } + const fromOutputCompressionQuality = getValueByPath(fromObject, [ + 'outputCompressionQuality', + ]); + if (fromOutputCompressionQuality != null) { + setValueByPath(toObject, ['imageOutputOptions', 'compressionQuality'], fromOutputCompressionQuality); + } + return toObject; +} +function imageFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromImageBytes = getValueByPath(fromObject, [ + 'bytesBase64Encoded', + ]); + if (fromImageBytes != null) { + setValueByPath(toObject, ['imageBytes'], tBytes(fromImageBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function imageFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (fromGcsUri != null) { + setValueByPath(toObject, ['gcsUri'], fromGcsUri); + } + const fromImageBytes = getValueByPath(fromObject, [ + 'bytesBase64Encoded', + ]); + if (fromImageBytes != null) { + setValueByPath(toObject, ['imageBytes'], tBytes(fromImageBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function imageToMldev(fromObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['gcsUri']) !== undefined) { + throw new Error('gcsUri parameter is not supported in Gemini API.'); + } + const fromImageBytes = getValueByPath(fromObject, ['imageBytes']); + if (fromImageBytes != null) { + setValueByPath(toObject, ['bytesBase64Encoded'], tBytes(fromImageBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function imageToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (fromGcsUri != null) { + setValueByPath(toObject, ['gcsUri'], fromGcsUri); + } + const fromImageBytes = getValueByPath(fromObject, ['imageBytes']); + if (fromImageBytes != null) { + setValueByPath(toObject, ['bytesBase64Encoded'], tBytes(fromImageBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function listModelsConfigToMldev(apiClient, fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + const fromFilter = getValueByPath(fromObject, ['filter']); + if (parentObject !== undefined && fromFilter != null) { + setValueByPath(parentObject, ['_query', 'filter'], fromFilter); + } + const fromQueryBase = getValueByPath(fromObject, ['queryBase']); + if (parentObject !== undefined && fromQueryBase != null) { + setValueByPath(parentObject, ['_url', 'models_url'], tModelsUrl(apiClient, fromQueryBase)); + } + return toObject; +} +function listModelsConfigToVertex(apiClient, fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + const fromFilter = getValueByPath(fromObject, ['filter']); + if (parentObject !== undefined && fromFilter != null) { + setValueByPath(parentObject, ['_query', 'filter'], fromFilter); + } + const fromQueryBase = getValueByPath(fromObject, ['queryBase']); + if (parentObject !== undefined && fromQueryBase != null) { + setValueByPath(parentObject, ['_url', 'models_url'], tModelsUrl(apiClient, fromQueryBase)); + } + return toObject; +} +function listModelsParametersToMldev(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listModelsConfigToMldev(apiClient, fromConfig, toObject); + } + return toObject; +} +function listModelsParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listModelsConfigToVertex(apiClient, fromConfig, toObject); + } + return toObject; +} +function listModelsResponseFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromModels = getValueByPath(fromObject, ['_self']); + if (fromModels != null) { + let transformedList = tExtractModels(fromModels); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return modelFromMldev(item); + }); + } + setValueByPath(toObject, ['models'], transformedList); + } + return toObject; +} +function listModelsResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromModels = getValueByPath(fromObject, ['_self']); + if (fromModels != null) { + let transformedList = tExtractModels(fromModels); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return modelFromVertex(item); + }); + } + setValueByPath(toObject, ['models'], transformedList); + } + return toObject; +} +function maskReferenceConfigToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromMaskMode = getValueByPath(fromObject, ['maskMode']); + if (fromMaskMode != null) { + setValueByPath(toObject, ['maskMode'], fromMaskMode); + } + const fromSegmentationClasses = getValueByPath(fromObject, [ + 'segmentationClasses', + ]); + if (fromSegmentationClasses != null) { + setValueByPath(toObject, ['maskClasses'], fromSegmentationClasses); + } + const fromMaskDilation = getValueByPath(fromObject, ['maskDilation']); + if (fromMaskDilation != null) { + setValueByPath(toObject, ['dilation'], fromMaskDilation); + } + return toObject; +} +function modelFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (fromDisplayName != null) { + setValueByPath(toObject, ['displayName'], fromDisplayName); + } + const fromDescription = getValueByPath(fromObject, ['description']); + if (fromDescription != null) { + setValueByPath(toObject, ['description'], fromDescription); + } + const fromVersion = getValueByPath(fromObject, ['version']); + if (fromVersion != null) { + setValueByPath(toObject, ['version'], fromVersion); + } + const fromTunedModelInfo = getValueByPath(fromObject, ['_self']); + if (fromTunedModelInfo != null) { + setValueByPath(toObject, ['tunedModelInfo'], tunedModelInfoFromMldev(fromTunedModelInfo)); + } + const fromInputTokenLimit = getValueByPath(fromObject, [ + 'inputTokenLimit', + ]); + if (fromInputTokenLimit != null) { + setValueByPath(toObject, ['inputTokenLimit'], fromInputTokenLimit); + } + const fromOutputTokenLimit = getValueByPath(fromObject, [ + 'outputTokenLimit', + ]); + if (fromOutputTokenLimit != null) { + setValueByPath(toObject, ['outputTokenLimit'], fromOutputTokenLimit); + } + const fromSupportedActions = getValueByPath(fromObject, [ + 'supportedGenerationMethods', + ]); + if (fromSupportedActions != null) { + setValueByPath(toObject, ['supportedActions'], fromSupportedActions); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (fromTemperature != null) { + setValueByPath(toObject, ['temperature'], fromTemperature); + } + const fromMaxTemperature = getValueByPath(fromObject, [ + 'maxTemperature', + ]); + if (fromMaxTemperature != null) { + setValueByPath(toObject, ['maxTemperature'], fromMaxTemperature); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (fromTopP != null) { + setValueByPath(toObject, ['topP'], fromTopP); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (fromTopK != null) { + setValueByPath(toObject, ['topK'], fromTopK); + } + const fromThinking = getValueByPath(fromObject, ['thinking']); + if (fromThinking != null) { + setValueByPath(toObject, ['thinking'], fromThinking); + } + return toObject; +} +function modelFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (fromDisplayName != null) { + setValueByPath(toObject, ['displayName'], fromDisplayName); + } + const fromDescription = getValueByPath(fromObject, ['description']); + if (fromDescription != null) { + setValueByPath(toObject, ['description'], fromDescription); + } + const fromVersion = getValueByPath(fromObject, ['versionId']); + if (fromVersion != null) { + setValueByPath(toObject, ['version'], fromVersion); + } + const fromEndpoints = getValueByPath(fromObject, ['deployedModels']); + if (fromEndpoints != null) { + let transformedList = fromEndpoints; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return endpointFromVertex(item); + }); + } + setValueByPath(toObject, ['endpoints'], transformedList); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (fromLabels != null) { + setValueByPath(toObject, ['labels'], fromLabels); + } + const fromTunedModelInfo = getValueByPath(fromObject, ['_self']); + if (fromTunedModelInfo != null) { + setValueByPath(toObject, ['tunedModelInfo'], tunedModelInfoFromVertex(fromTunedModelInfo)); + } + const fromDefaultCheckpointId = getValueByPath(fromObject, [ + 'defaultCheckpointId', + ]); + if (fromDefaultCheckpointId != null) { + setValueByPath(toObject, ['defaultCheckpointId'], fromDefaultCheckpointId); + } + const fromCheckpoints = getValueByPath(fromObject, ['checkpoints']); + if (fromCheckpoints != null) { + let transformedList = fromCheckpoints; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['checkpoints'], transformedList); + } + return toObject; +} +function partToMldev$1(fromObject, rootObject) { + const toObject = {}; + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromCodeExecutionResult = getValueByPath(fromObject, [ + 'codeExecutionResult', + ]); + if (fromCodeExecutionResult != null) { + setValueByPath(toObject, ['codeExecutionResult'], fromCodeExecutionResult); + } + const fromExecutableCode = getValueByPath(fromObject, [ + 'executableCode', + ]); + if (fromExecutableCode != null) { + setValueByPath(toObject, ['executableCode'], fromExecutableCode); + } + const fromFileData = getValueByPath(fromObject, ['fileData']); + if (fromFileData != null) { + setValueByPath(toObject, ['fileData'], fileDataToMldev$1(fromFileData)); + } + const fromFunctionCall = getValueByPath(fromObject, ['functionCall']); + if (fromFunctionCall != null) { + setValueByPath(toObject, ['functionCall'], functionCallToMldev$1(fromFunctionCall)); + } + const fromFunctionResponse = getValueByPath(fromObject, [ + 'functionResponse', + ]); + if (fromFunctionResponse != null) { + setValueByPath(toObject, ['functionResponse'], fromFunctionResponse); + } + const fromInlineData = getValueByPath(fromObject, ['inlineData']); + if (fromInlineData != null) { + setValueByPath(toObject, ['inlineData'], blobToMldev$1(fromInlineData)); + } + const fromText = getValueByPath(fromObject, ['text']); + if (fromText != null) { + setValueByPath(toObject, ['text'], fromText); + } + const fromThought = getValueByPath(fromObject, ['thought']); + if (fromThought != null) { + setValueByPath(toObject, ['thought'], fromThought); + } + const fromThoughtSignature = getValueByPath(fromObject, [ + 'thoughtSignature', + ]); + if (fromThoughtSignature != null) { + setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature); + } + const fromVideoMetadata = getValueByPath(fromObject, [ + 'videoMetadata', + ]); + if (fromVideoMetadata != null) { + setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata); + } + return toObject; +} +function productImageToVertex(fromObject, rootObject) { + const toObject = {}; + const fromProductImage = getValueByPath(fromObject, ['productImage']); + if (fromProductImage != null) { + setValueByPath(toObject, ['image'], imageToVertex(fromProductImage)); + } + return toObject; +} +function recontextImageConfigToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromNumberOfImages = getValueByPath(fromObject, [ + 'numberOfImages', + ]); + if (parentObject !== undefined && fromNumberOfImages != null) { + setValueByPath(parentObject, ['parameters', 'sampleCount'], fromNumberOfImages); + } + const fromBaseSteps = getValueByPath(fromObject, ['baseSteps']); + if (parentObject !== undefined && fromBaseSteps != null) { + setValueByPath(parentObject, ['parameters', 'baseSteps'], fromBaseSteps); + } + const fromOutputGcsUri = getValueByPath(fromObject, ['outputGcsUri']); + if (parentObject !== undefined && fromOutputGcsUri != null) { + setValueByPath(parentObject, ['parameters', 'storageUri'], fromOutputGcsUri); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (parentObject !== undefined && fromSeed != null) { + setValueByPath(parentObject, ['parameters', 'seed'], fromSeed); + } + const fromSafetyFilterLevel = getValueByPath(fromObject, [ + 'safetyFilterLevel', + ]); + if (parentObject !== undefined && fromSafetyFilterLevel != null) { + setValueByPath(parentObject, ['parameters', 'safetySetting'], fromSafetyFilterLevel); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (parentObject !== undefined && fromPersonGeneration != null) { + setValueByPath(parentObject, ['parameters', 'personGeneration'], fromPersonGeneration); + } + const fromAddWatermark = getValueByPath(fromObject, ['addWatermark']); + if (parentObject !== undefined && fromAddWatermark != null) { + setValueByPath(parentObject, ['parameters', 'addWatermark'], fromAddWatermark); + } + const fromOutputMimeType = getValueByPath(fromObject, [ + 'outputMimeType', + ]); + if (parentObject !== undefined && fromOutputMimeType != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'mimeType'], fromOutputMimeType); + } + const fromOutputCompressionQuality = getValueByPath(fromObject, [ + 'outputCompressionQuality', + ]); + if (parentObject !== undefined && fromOutputCompressionQuality != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'compressionQuality'], fromOutputCompressionQuality); + } + const fromEnhancePrompt = getValueByPath(fromObject, [ + 'enhancePrompt', + ]); + if (parentObject !== undefined && fromEnhancePrompt != null) { + setValueByPath(parentObject, ['parameters', 'enhancePrompt'], fromEnhancePrompt); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (parentObject !== undefined && fromLabels != null) { + setValueByPath(parentObject, ['labels'], fromLabels); + } + return toObject; +} +function recontextImageParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromSource = getValueByPath(fromObject, ['source']); + if (fromSource != null) { + recontextImageSourceToVertex(fromSource, toObject); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + recontextImageConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function recontextImageResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromGeneratedImages = getValueByPath(fromObject, [ + 'predictions', + ]); + if (fromGeneratedImages != null) { + let transformedList = fromGeneratedImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedImageFromVertex(item); + }); + } + setValueByPath(toObject, ['generatedImages'], transformedList); + } + return toObject; +} +function recontextImageSourceToVertex(fromObject, parentObject, rootObject) { + const toObject = {}; + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (parentObject !== undefined && fromPrompt != null) { + setValueByPath(parentObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromPersonImage = getValueByPath(fromObject, ['personImage']); + if (parentObject !== undefined && fromPersonImage != null) { + setValueByPath(parentObject, ['instances[0]', 'personImage', 'image'], imageToVertex(fromPersonImage)); + } + const fromProductImages = getValueByPath(fromObject, [ + 'productImages', + ]); + if (parentObject !== undefined && fromProductImages != null) { + let transformedList = fromProductImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return productImageToVertex(item); + }); + } + setValueByPath(parentObject, ['instances[0]', 'productImages'], transformedList); + } + return toObject; +} +function referenceImageAPIInternalToVertex(fromObject, rootObject) { + const toObject = {}; + const fromReferenceImage = getValueByPath(fromObject, [ + 'referenceImage', + ]); + if (fromReferenceImage != null) { + setValueByPath(toObject, ['referenceImage'], imageToVertex(fromReferenceImage)); + } + const fromReferenceId = getValueByPath(fromObject, ['referenceId']); + if (fromReferenceId != null) { + setValueByPath(toObject, ['referenceId'], fromReferenceId); + } + const fromReferenceType = getValueByPath(fromObject, [ + 'referenceType', + ]); + if (fromReferenceType != null) { + setValueByPath(toObject, ['referenceType'], fromReferenceType); + } + const fromMaskImageConfig = getValueByPath(fromObject, [ + 'maskImageConfig', + ]); + if (fromMaskImageConfig != null) { + setValueByPath(toObject, ['maskImageConfig'], maskReferenceConfigToVertex(fromMaskImageConfig)); + } + const fromControlImageConfig = getValueByPath(fromObject, [ + 'controlImageConfig', + ]); + if (fromControlImageConfig != null) { + setValueByPath(toObject, ['controlImageConfig'], controlReferenceConfigToVertex(fromControlImageConfig)); + } + const fromStyleImageConfig = getValueByPath(fromObject, [ + 'styleImageConfig', + ]); + if (fromStyleImageConfig != null) { + setValueByPath(toObject, ['styleImageConfig'], fromStyleImageConfig); + } + const fromSubjectImageConfig = getValueByPath(fromObject, [ + 'subjectImageConfig', + ]); + if (fromSubjectImageConfig != null) { + setValueByPath(toObject, ['subjectImageConfig'], fromSubjectImageConfig); + } + return toObject; +} +function safetyAttributesFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromCategories = getValueByPath(fromObject, [ + 'safetyAttributes', + 'categories', + ]); + if (fromCategories != null) { + setValueByPath(toObject, ['categories'], fromCategories); + } + const fromScores = getValueByPath(fromObject, [ + 'safetyAttributes', + 'scores', + ]); + if (fromScores != null) { + setValueByPath(toObject, ['scores'], fromScores); + } + const fromContentType = getValueByPath(fromObject, ['contentType']); + if (fromContentType != null) { + setValueByPath(toObject, ['contentType'], fromContentType); + } + return toObject; +} +function safetyAttributesFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromCategories = getValueByPath(fromObject, [ + 'safetyAttributes', + 'categories', + ]); + if (fromCategories != null) { + setValueByPath(toObject, ['categories'], fromCategories); + } + const fromScores = getValueByPath(fromObject, [ + 'safetyAttributes', + 'scores', + ]); + if (fromScores != null) { + setValueByPath(toObject, ['scores'], fromScores); + } + const fromContentType = getValueByPath(fromObject, ['contentType']); + if (fromContentType != null) { + setValueByPath(toObject, ['contentType'], fromContentType); + } + return toObject; +} +function safetySettingToMldev(fromObject, _rootObject) { + const toObject = {}; + const fromCategory = getValueByPath(fromObject, ['category']); + if (fromCategory != null) { + setValueByPath(toObject, ['category'], fromCategory); + } + if (getValueByPath(fromObject, ['method']) !== undefined) { + throw new Error('method parameter is not supported in Gemini API.'); + } + const fromThreshold = getValueByPath(fromObject, ['threshold']); + if (fromThreshold != null) { + setValueByPath(toObject, ['threshold'], fromThreshold); + } + return toObject; +} +function scribbleImageToVertex(fromObject, rootObject) { + const toObject = {}; + const fromImage = getValueByPath(fromObject, ['image']); + if (fromImage != null) { + setValueByPath(toObject, ['image'], imageToVertex(fromImage)); + } + return toObject; +} +function segmentImageConfigToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromMode = getValueByPath(fromObject, ['mode']); + if (parentObject !== undefined && fromMode != null) { + setValueByPath(parentObject, ['parameters', 'mode'], fromMode); + } + const fromMaxPredictions = getValueByPath(fromObject, [ + 'maxPredictions', + ]); + if (parentObject !== undefined && fromMaxPredictions != null) { + setValueByPath(parentObject, ['parameters', 'maxPredictions'], fromMaxPredictions); + } + const fromConfidenceThreshold = getValueByPath(fromObject, [ + 'confidenceThreshold', + ]); + if (parentObject !== undefined && fromConfidenceThreshold != null) { + setValueByPath(parentObject, ['parameters', 'confidenceThreshold'], fromConfidenceThreshold); + } + const fromMaskDilation = getValueByPath(fromObject, ['maskDilation']); + if (parentObject !== undefined && fromMaskDilation != null) { + setValueByPath(parentObject, ['parameters', 'maskDilation'], fromMaskDilation); + } + const fromBinaryColorThreshold = getValueByPath(fromObject, [ + 'binaryColorThreshold', + ]); + if (parentObject !== undefined && fromBinaryColorThreshold != null) { + setValueByPath(parentObject, ['parameters', 'binaryColorThreshold'], fromBinaryColorThreshold); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (parentObject !== undefined && fromLabels != null) { + setValueByPath(parentObject, ['labels'], fromLabels); + } + return toObject; +} +function segmentImageParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromSource = getValueByPath(fromObject, ['source']); + if (fromSource != null) { + segmentImageSourceToVertex(fromSource, toObject); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + segmentImageConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function segmentImageResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromGeneratedMasks = getValueByPath(fromObject, ['predictions']); + if (fromGeneratedMasks != null) { + let transformedList = fromGeneratedMasks; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedImageMaskFromVertex(item); + }); + } + setValueByPath(toObject, ['generatedMasks'], transformedList); + } + return toObject; +} +function segmentImageSourceToVertex(fromObject, parentObject, rootObject) { + const toObject = {}; + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (parentObject !== undefined && fromPrompt != null) { + setValueByPath(parentObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromImage = getValueByPath(fromObject, ['image']); + if (parentObject !== undefined && fromImage != null) { + setValueByPath(parentObject, ['instances[0]', 'image'], imageToVertex(fromImage)); + } + const fromScribbleImage = getValueByPath(fromObject, [ + 'scribbleImage', + ]); + if (parentObject !== undefined && fromScribbleImage != null) { + setValueByPath(parentObject, ['instances[0]', 'scribble'], scribbleImageToVertex(fromScribbleImage)); + } + return toObject; +} +function toolConfigToMldev(fromObject, rootObject) { + const toObject = {}; + const fromRetrievalConfig = getValueByPath(fromObject, [ + 'retrievalConfig', + ]); + if (fromRetrievalConfig != null) { + setValueByPath(toObject, ['retrievalConfig'], fromRetrievalConfig); + } + const fromFunctionCallingConfig = getValueByPath(fromObject, [ + 'functionCallingConfig', + ]); + if (fromFunctionCallingConfig != null) { + setValueByPath(toObject, ['functionCallingConfig'], functionCallingConfigToMldev(fromFunctionCallingConfig)); + } + return toObject; +} +function toolToMldev$1(fromObject, rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['retrieval']) !== undefined) { + throw new Error('retrieval parameter is not supported in Gemini API.'); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + const fromFileSearch = getValueByPath(fromObject, ['fileSearch']); + if (fromFileSearch != null) { + setValueByPath(toObject, ['fileSearch'], fromFileSearch); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + if (getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined) { + throw new Error('enterpriseWebSearch parameter is not supported in Gemini API.'); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], googleMapsToMldev$1(fromGoogleMaps)); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], googleSearchToMldev$1(fromGoogleSearch)); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} +function toolToVertex(fromObject, rootObject) { + const toObject = {}; + const fromRetrieval = getValueByPath(fromObject, ['retrieval']); + if (fromRetrieval != null) { + setValueByPath(toObject, ['retrieval'], fromRetrieval); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + if (getValueByPath(fromObject, ['fileSearch']) !== undefined) { + throw new Error('fileSearch parameter is not supported in Vertex AI.'); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + const fromEnterpriseWebSearch = getValueByPath(fromObject, [ + 'enterpriseWebSearch', + ]); + if (fromEnterpriseWebSearch != null) { + setValueByPath(toObject, ['enterpriseWebSearch'], fromEnterpriseWebSearch); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return functionDeclarationToVertex(item); + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], fromGoogleMaps); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], fromGoogleSearch); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} +function tunedModelInfoFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromBaseModel = getValueByPath(fromObject, ['baseModel']); + if (fromBaseModel != null) { + setValueByPath(toObject, ['baseModel'], fromBaseModel); + } + const fromCreateTime = getValueByPath(fromObject, ['createTime']); + if (fromCreateTime != null) { + setValueByPath(toObject, ['createTime'], fromCreateTime); + } + const fromUpdateTime = getValueByPath(fromObject, ['updateTime']); + if (fromUpdateTime != null) { + setValueByPath(toObject, ['updateTime'], fromUpdateTime); + } + return toObject; +} +function tunedModelInfoFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromBaseModel = getValueByPath(fromObject, [ + 'labels', + 'google-vertex-llm-tuning-base-model-id', + ]); + if (fromBaseModel != null) { + setValueByPath(toObject, ['baseModel'], fromBaseModel); + } + const fromCreateTime = getValueByPath(fromObject, ['createTime']); + if (fromCreateTime != null) { + setValueByPath(toObject, ['createTime'], fromCreateTime); + } + const fromUpdateTime = getValueByPath(fromObject, ['updateTime']); + if (fromUpdateTime != null) { + setValueByPath(toObject, ['updateTime'], fromUpdateTime); + } + return toObject; +} +function updateModelConfigToMldev(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromDisplayName); + } + const fromDescription = getValueByPath(fromObject, ['description']); + if (parentObject !== undefined && fromDescription != null) { + setValueByPath(parentObject, ['description'], fromDescription); + } + const fromDefaultCheckpointId = getValueByPath(fromObject, [ + 'defaultCheckpointId', + ]); + if (parentObject !== undefined && fromDefaultCheckpointId != null) { + setValueByPath(parentObject, ['defaultCheckpointId'], fromDefaultCheckpointId); + } + return toObject; +} +function updateModelConfigToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromDisplayName); + } + const fromDescription = getValueByPath(fromObject, ['description']); + if (parentObject !== undefined && fromDescription != null) { + setValueByPath(parentObject, ['description'], fromDescription); + } + const fromDefaultCheckpointId = getValueByPath(fromObject, [ + 'defaultCheckpointId', + ]); + if (parentObject !== undefined && fromDefaultCheckpointId != null) { + setValueByPath(parentObject, ['defaultCheckpointId'], fromDefaultCheckpointId); + } + return toObject; +} +function updateModelParametersToMldev(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'name'], tModel(apiClient, fromModel)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + updateModelConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function updateModelParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + updateModelConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function upscaleImageAPIConfigInternalToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromOutputGcsUri = getValueByPath(fromObject, ['outputGcsUri']); + if (parentObject !== undefined && fromOutputGcsUri != null) { + setValueByPath(parentObject, ['parameters', 'storageUri'], fromOutputGcsUri); + } + const fromSafetyFilterLevel = getValueByPath(fromObject, [ + 'safetyFilterLevel', + ]); + if (parentObject !== undefined && fromSafetyFilterLevel != null) { + setValueByPath(parentObject, ['parameters', 'safetySetting'], fromSafetyFilterLevel); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (parentObject !== undefined && fromPersonGeneration != null) { + setValueByPath(parentObject, ['parameters', 'personGeneration'], fromPersonGeneration); + } + const fromIncludeRaiReason = getValueByPath(fromObject, [ + 'includeRaiReason', + ]); + if (parentObject !== undefined && fromIncludeRaiReason != null) { + setValueByPath(parentObject, ['parameters', 'includeRaiReason'], fromIncludeRaiReason); + } + const fromOutputMimeType = getValueByPath(fromObject, [ + 'outputMimeType', + ]); + if (parentObject !== undefined && fromOutputMimeType != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'mimeType'], fromOutputMimeType); + } + const fromOutputCompressionQuality = getValueByPath(fromObject, [ + 'outputCompressionQuality', + ]); + if (parentObject !== undefined && fromOutputCompressionQuality != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'compressionQuality'], fromOutputCompressionQuality); + } + const fromEnhanceInputImage = getValueByPath(fromObject, [ + 'enhanceInputImage', + ]); + if (parentObject !== undefined && fromEnhanceInputImage != null) { + setValueByPath(parentObject, ['parameters', 'upscaleConfig', 'enhanceInputImage'], fromEnhanceInputImage); + } + const fromImagePreservationFactor = getValueByPath(fromObject, [ + 'imagePreservationFactor', + ]); + if (parentObject !== undefined && fromImagePreservationFactor != null) { + setValueByPath(parentObject, ['parameters', 'upscaleConfig', 'imagePreservationFactor'], fromImagePreservationFactor); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (parentObject !== undefined && fromLabels != null) { + setValueByPath(parentObject, ['labels'], fromLabels); + } + const fromNumberOfImages = getValueByPath(fromObject, [ + 'numberOfImages', + ]); + if (parentObject !== undefined && fromNumberOfImages != null) { + setValueByPath(parentObject, ['parameters', 'sampleCount'], fromNumberOfImages); + } + const fromMode = getValueByPath(fromObject, ['mode']); + if (parentObject !== undefined && fromMode != null) { + setValueByPath(parentObject, ['parameters', 'mode'], fromMode); + } + return toObject; +} +function upscaleImageAPIParametersInternalToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromImage = getValueByPath(fromObject, ['image']); + if (fromImage != null) { + setValueByPath(toObject, ['instances[0]', 'image'], imageToVertex(fromImage)); + } + const fromUpscaleFactor = getValueByPath(fromObject, [ + 'upscaleFactor', + ]); + if (fromUpscaleFactor != null) { + setValueByPath(toObject, ['parameters', 'upscaleConfig', 'upscaleFactor'], fromUpscaleFactor); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + upscaleImageAPIConfigInternalToVertex(fromConfig, toObject); + } + return toObject; +} +function upscaleImageResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromGeneratedImages = getValueByPath(fromObject, [ + 'predictions', + ]); + if (fromGeneratedImages != null) { + let transformedList = fromGeneratedImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedImageFromVertex(item); + }); + } + setValueByPath(toObject, ['generatedImages'], transformedList); + } + return toObject; +} +function videoFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromUri = getValueByPath(fromObject, ['uri']); + if (fromUri != null) { + setValueByPath(toObject, ['uri'], fromUri); + } + const fromVideoBytes = getValueByPath(fromObject, ['encodedVideo']); + if (fromVideoBytes != null) { + setValueByPath(toObject, ['videoBytes'], tBytes(fromVideoBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['encoding']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function videoFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromUri = getValueByPath(fromObject, ['gcsUri']); + if (fromUri != null) { + setValueByPath(toObject, ['uri'], fromUri); + } + const fromVideoBytes = getValueByPath(fromObject, [ + 'bytesBase64Encoded', + ]); + if (fromVideoBytes != null) { + setValueByPath(toObject, ['videoBytes'], tBytes(fromVideoBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function videoGenerationMaskToVertex(fromObject, rootObject) { + const toObject = {}; + const fromImage = getValueByPath(fromObject, ['image']); + if (fromImage != null) { + setValueByPath(toObject, ['_self'], imageToVertex(fromImage)); + } + const fromMaskMode = getValueByPath(fromObject, ['maskMode']); + if (fromMaskMode != null) { + setValueByPath(toObject, ['maskMode'], fromMaskMode); + } + return toObject; +} +function videoGenerationReferenceImageToMldev(fromObject, rootObject) { + const toObject = {}; + const fromImage = getValueByPath(fromObject, ['image']); + if (fromImage != null) { + setValueByPath(toObject, ['image'], imageToMldev(fromImage)); + } + const fromReferenceType = getValueByPath(fromObject, [ + 'referenceType', + ]); + if (fromReferenceType != null) { + setValueByPath(toObject, ['referenceType'], fromReferenceType); + } + return toObject; +} +function videoGenerationReferenceImageToVertex(fromObject, rootObject) { + const toObject = {}; + const fromImage = getValueByPath(fromObject, ['image']); + if (fromImage != null) { + setValueByPath(toObject, ['image'], imageToVertex(fromImage)); + } + const fromReferenceType = getValueByPath(fromObject, [ + 'referenceType', + ]); + if (fromReferenceType != null) { + setValueByPath(toObject, ['referenceType'], fromReferenceType); + } + return toObject; +} +function videoToMldev(fromObject, _rootObject) { + const toObject = {}; + const fromUri = getValueByPath(fromObject, ['uri']); + if (fromUri != null) { + setValueByPath(toObject, ['uri'], fromUri); + } + const fromVideoBytes = getValueByPath(fromObject, ['videoBytes']); + if (fromVideoBytes != null) { + setValueByPath(toObject, ['encodedVideo'], tBytes(fromVideoBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['encoding'], fromMimeType); + } + return toObject; +} +function videoToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromUri = getValueByPath(fromObject, ['uri']); + if (fromUri != null) { + setValueByPath(toObject, ['gcsUri'], fromUri); + } + const fromVideoBytes = getValueByPath(fromObject, ['videoBytes']); + if (fromVideoBytes != null) { + setValueByPath(toObject, ['bytesBase64Encoded'], tBytes(fromVideoBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Code generated by the Google Gen AI SDK generator DO NOT EDIT. +function createFileSearchStoreConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromDisplayName); + } + return toObject; +} +function createFileSearchStoreParametersToMldev(fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createFileSearchStoreConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function deleteFileSearchStoreConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromForce = getValueByPath(fromObject, ['force']); + if (parentObject !== undefined && fromForce != null) { + setValueByPath(parentObject, ['_query', 'force'], fromForce); + } + return toObject; +} +function deleteFileSearchStoreParametersToMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + deleteFileSearchStoreConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function getFileSearchStoreParametersToMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + return toObject; +} +function importFileConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromCustomMetadata = getValueByPath(fromObject, [ + 'customMetadata', + ]); + if (parentObject !== undefined && fromCustomMetadata != null) { + let transformedList = fromCustomMetadata; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(parentObject, ['customMetadata'], transformedList); + } + const fromChunkingConfig = getValueByPath(fromObject, [ + 'chunkingConfig', + ]); + if (parentObject !== undefined && fromChunkingConfig != null) { + setValueByPath(parentObject, ['chunkingConfig'], fromChunkingConfig); + } + return toObject; +} +function importFileOperationFromMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], importFileResponseFromMldev(fromResponse)); + } + return toObject; +} +function importFileParametersToMldev(fromObject) { + const toObject = {}; + const fromFileSearchStoreName = getValueByPath(fromObject, [ + 'fileSearchStoreName', + ]); + if (fromFileSearchStoreName != null) { + setValueByPath(toObject, ['_url', 'file_search_store_name'], fromFileSearchStoreName); + } + const fromFileName = getValueByPath(fromObject, ['fileName']); + if (fromFileName != null) { + setValueByPath(toObject, ['fileName'], fromFileName); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + importFileConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function importFileResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromParent = getValueByPath(fromObject, ['parent']); + if (fromParent != null) { + setValueByPath(toObject, ['parent'], fromParent); + } + const fromDocumentName = getValueByPath(fromObject, ['documentName']); + if (fromDocumentName != null) { + setValueByPath(toObject, ['documentName'], fromDocumentName); + } + return toObject; +} +function listFileSearchStoresConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + return toObject; +} +function listFileSearchStoresParametersToMldev(fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listFileSearchStoresConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function listFileSearchStoresResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromFileSearchStores = getValueByPath(fromObject, [ + 'fileSearchStores', + ]); + if (fromFileSearchStores != null) { + let transformedList = fromFileSearchStores; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['fileSearchStores'], transformedList); + } + return toObject; +} +function uploadToFileSearchStoreConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (parentObject !== undefined && fromMimeType != null) { + setValueByPath(parentObject, ['mimeType'], fromMimeType); + } + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromDisplayName); + } + const fromCustomMetadata = getValueByPath(fromObject, [ + 'customMetadata', + ]); + if (parentObject !== undefined && fromCustomMetadata != null) { + let transformedList = fromCustomMetadata; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(parentObject, ['customMetadata'], transformedList); + } + const fromChunkingConfig = getValueByPath(fromObject, [ + 'chunkingConfig', + ]); + if (parentObject !== undefined && fromChunkingConfig != null) { + setValueByPath(parentObject, ['chunkingConfig'], fromChunkingConfig); + } + return toObject; +} +function uploadToFileSearchStoreParametersToMldev(fromObject) { + const toObject = {}; + const fromFileSearchStoreName = getValueByPath(fromObject, [ + 'fileSearchStoreName', + ]); + if (fromFileSearchStoreName != null) { + setValueByPath(toObject, ['_url', 'file_search_store_name'], fromFileSearchStoreName); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + uploadToFileSearchStoreConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function uploadToFileSearchStoreResumableResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const CONTENT_TYPE_HEADER = 'Content-Type'; +const SERVER_TIMEOUT_HEADER = 'X-Server-Timeout'; +const USER_AGENT_HEADER = 'User-Agent'; +const GOOGLE_API_CLIENT_HEADER = 'x-goog-api-client'; +const SDK_VERSION = '1.41.0'; // x-release-please-version +const LIBRARY_LABEL = `google-genai-sdk/${SDK_VERSION}`; +const VERTEX_AI_API_DEFAULT_VERSION = 'v1beta1'; +const GOOGLE_AI_API_DEFAULT_VERSION = 'v1beta'; +// Default retry options. +// The config is based on https://cloud.google.com/storage/docs/retry-strategy. +const DEFAULT_RETRY_ATTEMPTS = 5; // Including the initial call +// LINT.IfChange +const DEFAULT_RETRY_HTTP_STATUS_CODES = [ + 408, // Request timeout + 429, // Too many requests + 500, // Internal server error + 502, // Bad gateway + 503, // Service unavailable + 504, // Gateway timeout +]; +/** + * The ApiClient class is used to send requests to the Gemini API or Vertex AI + * endpoints. + */ +class ApiClient { + constructor(opts) { + var _a, _b, _c; + this.clientOptions = Object.assign({}, opts); + this.customBaseUrl = (_a = opts.httpOptions) === null || _a === void 0 ? void 0 : _a.baseUrl; + if (this.clientOptions.vertexai) { + if (this.clientOptions.project && this.clientOptions.location) { + this.clientOptions.apiKey = undefined; + } + else if (this.clientOptions.apiKey) { + this.clientOptions.project = undefined; + this.clientOptions.location = undefined; + } + } + const initHttpOptions = {}; + if (this.clientOptions.vertexai) { + if (!this.clientOptions.location && + !this.clientOptions.apiKey && + !this.customBaseUrl) { + this.clientOptions.location = 'global'; + } + const hasSufficientAuth = (this.clientOptions.project && this.clientOptions.location) || + this.clientOptions.apiKey; + if (!hasSufficientAuth && !this.customBaseUrl) { + throw new Error('Authentication is not set up. Please provide either a project and location, or an API key, or a custom base URL.'); + } + const hasConstructorAuth = (opts.project && opts.location) || !!opts.apiKey; + if (this.customBaseUrl && !hasConstructorAuth) { + initHttpOptions.baseUrl = this.customBaseUrl; + this.clientOptions.project = undefined; + this.clientOptions.location = undefined; + } + else if (this.clientOptions.apiKey || + this.clientOptions.location === 'global') { + // Vertex Express or global endpoint case. + initHttpOptions.baseUrl = 'https://aiplatform.googleapis.com/'; + } + else if (this.clientOptions.project && this.clientOptions.location) { + initHttpOptions.baseUrl = `https://${this.clientOptions.location}-aiplatform.googleapis.com/`; + } + initHttpOptions.apiVersion = + (_b = this.clientOptions.apiVersion) !== null && _b !== void 0 ? _b : VERTEX_AI_API_DEFAULT_VERSION; + } + else { + // Gemini API + if (!this.clientOptions.apiKey) { + throw new ApiError({ + message: 'API key must be set when using the Gemini API.', + status: 403, + }); + } + initHttpOptions.apiVersion = + (_c = this.clientOptions.apiVersion) !== null && _c !== void 0 ? _c : GOOGLE_AI_API_DEFAULT_VERSION; + initHttpOptions.baseUrl = `https://generativelanguage.googleapis.com/`; + } + initHttpOptions.headers = this.getDefaultHeaders(); + this.clientOptions.httpOptions = initHttpOptions; + if (opts.httpOptions) { + this.clientOptions.httpOptions = this.patchHttpOptions(initHttpOptions, opts.httpOptions); + } + } + isVertexAI() { + var _a; + return (_a = this.clientOptions.vertexai) !== null && _a !== void 0 ? _a : false; + } + getProject() { + return this.clientOptions.project; + } + getLocation() { + return this.clientOptions.location; + } + getCustomBaseUrl() { + return this.customBaseUrl; + } + async getAuthHeaders() { + const headers = new Headers(); + await this.clientOptions.auth.addAuthHeaders(headers); + return headers; + } + getApiVersion() { + if (this.clientOptions.httpOptions && + this.clientOptions.httpOptions.apiVersion !== undefined) { + return this.clientOptions.httpOptions.apiVersion; + } + throw new Error('API version is not set.'); + } + getBaseUrl() { + if (this.clientOptions.httpOptions && + this.clientOptions.httpOptions.baseUrl !== undefined) { + return this.clientOptions.httpOptions.baseUrl; + } + throw new Error('Base URL is not set.'); + } + getRequestUrl() { + return this.getRequestUrlInternal(this.clientOptions.httpOptions); + } + getHeaders() { + if (this.clientOptions.httpOptions && + this.clientOptions.httpOptions.headers !== undefined) { + return this.clientOptions.httpOptions.headers; + } + else { + throw new Error('Headers are not set.'); + } + } + getRequestUrlInternal(httpOptions) { + if (!httpOptions || + httpOptions.baseUrl === undefined || + httpOptions.apiVersion === undefined) { + throw new Error('HTTP options are not correctly set.'); + } + const baseUrl = httpOptions.baseUrl.endsWith('/') + ? httpOptions.baseUrl.slice(0, -1) + : httpOptions.baseUrl; + const urlElement = [baseUrl]; + if (httpOptions.apiVersion && httpOptions.apiVersion !== '') { + urlElement.push(httpOptions.apiVersion); + } + return urlElement.join('/'); + } + getBaseResourcePath() { + return `projects/${this.clientOptions.project}/locations/${this.clientOptions.location}`; + } + getApiKey() { + return this.clientOptions.apiKey; + } + getWebsocketBaseUrl() { + const baseUrl = this.getBaseUrl(); + const urlParts = new URL(baseUrl); + urlParts.protocol = urlParts.protocol == 'http:' ? 'ws' : 'wss'; + return urlParts.toString(); + } + setBaseUrl(url) { + if (this.clientOptions.httpOptions) { + this.clientOptions.httpOptions.baseUrl = url; + } + else { + throw new Error('HTTP options are not correctly set.'); + } + } + constructUrl(path, httpOptions, prependProjectLocation) { + const urlElement = [this.getRequestUrlInternal(httpOptions)]; + if (prependProjectLocation) { + urlElement.push(this.getBaseResourcePath()); + } + if (path !== '') { + urlElement.push(path); + } + const url = new URL(`${urlElement.join('/')}`); + return url; + } + shouldPrependVertexProjectPath(request, httpOptions) { + if (httpOptions.baseUrl && + httpOptions.baseUrlResourceScope === exports.ResourceScope.COLLECTION) { + return false; + } + if (this.clientOptions.apiKey) { + return false; + } + if (!this.clientOptions.vertexai) { + return false; + } + if (request.path.startsWith('projects/')) { + // Assume the path already starts with + // `projects/<project>/location/<location>`. + return false; + } + if (request.httpMethod === 'GET' && + request.path.startsWith('publishers/google/models')) { + // These paths are used by Vertex's models.get and models.list + // calls. For base models Vertex does not accept a project/location + // prefix (for tuned model the prefix is required). + return false; + } + return true; + } + async request(request) { + let patchedHttpOptions = this.clientOptions.httpOptions; + if (request.httpOptions) { + patchedHttpOptions = this.patchHttpOptions(this.clientOptions.httpOptions, request.httpOptions); + } + const prependProjectLocation = this.shouldPrependVertexProjectPath(request, patchedHttpOptions); + const url = this.constructUrl(request.path, patchedHttpOptions, prependProjectLocation); + if (request.queryParams) { + for (const [key, value] of Object.entries(request.queryParams)) { + url.searchParams.append(key, String(value)); + } + } + let requestInit = {}; + if (request.httpMethod === 'GET') { + if (request.body && request.body !== '{}') { + throw new Error('Request body should be empty for GET request, but got non empty request body'); + } + } + else { + requestInit.body = request.body; + } + requestInit = await this.includeExtraHttpOptionsToRequestInit(requestInit, patchedHttpOptions, url.toString(), request.abortSignal); + return this.unaryApiCall(url, requestInit, request.httpMethod); + } + patchHttpOptions(baseHttpOptions, requestHttpOptions) { + const patchedHttpOptions = JSON.parse(JSON.stringify(baseHttpOptions)); + for (const [key, value] of Object.entries(requestHttpOptions)) { + // Records compile to objects. + if (typeof value === 'object') { + // @ts-expect-error TS2345TS7053: Element implicitly has an 'any' type + // because expression of type 'string' can't be used to index type + // 'HttpOptions'. + patchedHttpOptions[key] = Object.assign(Object.assign({}, patchedHttpOptions[key]), value); + } + else if (value !== undefined) { + // @ts-expect-error TS2345TS7053: Element implicitly has an 'any' type + // because expression of type 'string' can't be used to index type + // 'HttpOptions'. + patchedHttpOptions[key] = value; + } + } + return patchedHttpOptions; + } + async requestStream(request) { + let patchedHttpOptions = this.clientOptions.httpOptions; + if (request.httpOptions) { + patchedHttpOptions = this.patchHttpOptions(this.clientOptions.httpOptions, request.httpOptions); + } + const prependProjectLocation = this.shouldPrependVertexProjectPath(request, patchedHttpOptions); + const url = this.constructUrl(request.path, patchedHttpOptions, prependProjectLocation); + if (!url.searchParams.has('alt') || url.searchParams.get('alt') !== 'sse') { + url.searchParams.set('alt', 'sse'); + } + let requestInit = {}; + requestInit.body = request.body; + requestInit = await this.includeExtraHttpOptionsToRequestInit(requestInit, patchedHttpOptions, url.toString(), request.abortSignal); + return this.streamApiCall(url, requestInit, request.httpMethod); + } + async includeExtraHttpOptionsToRequestInit(requestInit, httpOptions, url, abortSignal) { + if ((httpOptions && httpOptions.timeout) || abortSignal) { + const abortController = new AbortController(); + const signal = abortController.signal; + if (httpOptions.timeout && (httpOptions === null || httpOptions === void 0 ? void 0 : httpOptions.timeout) > 0) { + const timeoutHandle = setTimeout(() => abortController.abort(), httpOptions.timeout); + if (timeoutHandle && + typeof timeoutHandle.unref === + 'function') { + // call unref to prevent nodejs process from hanging, see + // https://nodejs.org/api/timers.html#timeoutunref + timeoutHandle.unref(); + } + } + if (abortSignal) { + abortSignal.addEventListener('abort', () => { + abortController.abort(); + }); + } + requestInit.signal = signal; + } + if (httpOptions && httpOptions.extraBody !== null) { + includeExtraBodyToRequestInit(requestInit, httpOptions.extraBody); + } + requestInit.headers = await this.getHeadersInternal(httpOptions, url); + return requestInit; + } + async unaryApiCall(url, requestInit, httpMethod) { + return this.apiCall(url.toString(), Object.assign(Object.assign({}, requestInit), { method: httpMethod })) + .then(async (response) => { + await throwErrorIfNotOK(response); + return new HttpResponse(response); + }) + .catch((e) => { + if (e instanceof Error) { + throw e; + } + else { + throw new Error(JSON.stringify(e)); + } + }); + } + async streamApiCall(url, requestInit, httpMethod) { + return this.apiCall(url.toString(), Object.assign(Object.assign({}, requestInit), { method: httpMethod })) + .then(async (response) => { + await throwErrorIfNotOK(response); + return this.processStreamResponse(response); + }) + .catch((e) => { + if (e instanceof Error) { + throw e; + } + else { + throw new Error(JSON.stringify(e)); + } + }); + } + processStreamResponse(response) { + return __asyncGenerator(this, arguments, function* processStreamResponse_1() { + var _a; + const reader = (_a = response === null || response === void 0 ? void 0 : response.body) === null || _a === void 0 ? void 0 : _a.getReader(); + const decoder = new TextDecoder('utf-8'); + if (!reader) { + throw new Error('Response body is empty'); + } + try { + let buffer = ''; + const dataPrefix = 'data:'; + const delimiters = ['\n\n', '\r\r', '\r\n\r\n']; + while (true) { + const { done, value } = yield __await(reader.read()); + if (done) { + if (buffer.trim().length > 0) { + throw new Error('Incomplete JSON segment at the end'); + } + break; + } + const chunkString = decoder.decode(value, { stream: true }); + // Parse and throw an error if the chunk contains an error. + try { + const chunkJson = JSON.parse(chunkString); + if ('error' in chunkJson) { + const errorJson = JSON.parse(JSON.stringify(chunkJson['error'])); + const status = errorJson['status']; + const code = errorJson['code']; + const errorMessage = `got status: ${status}. ${JSON.stringify(chunkJson)}`; + if (code >= 400 && code < 600) { + const apiError = new ApiError({ + message: errorMessage, + status: code, + }); + throw apiError; + } + } + } + catch (e) { + const error = e; + if (error.name === 'ApiError') { + throw e; + } + } + buffer += chunkString; + let delimiterIndex = -1; + let delimiterLength = 0; + while (true) { + delimiterIndex = -1; + delimiterLength = 0; + for (const delimiter of delimiters) { + const index = buffer.indexOf(delimiter); + if (index !== -1 && + (delimiterIndex === -1 || index < delimiterIndex)) { + delimiterIndex = index; + delimiterLength = delimiter.length; + } + } + if (delimiterIndex === -1) { + break; // No complete event in buffer + } + const eventString = buffer.substring(0, delimiterIndex); + buffer = buffer.substring(delimiterIndex + delimiterLength); + const trimmedEvent = eventString.trim(); + if (trimmedEvent.startsWith(dataPrefix)) { + const processedChunkString = trimmedEvent + .substring(dataPrefix.length) + .trim(); + try { + const partialResponse = new Response(processedChunkString, { + headers: response === null || response === void 0 ? void 0 : response.headers, + status: response === null || response === void 0 ? void 0 : response.status, + statusText: response === null || response === void 0 ? void 0 : response.statusText, + }); + yield yield __await(new HttpResponse(partialResponse)); + } + catch (e) { + throw new Error(`exception parsing stream chunk ${processedChunkString}. ${e}`); + } + } + } + } + } + finally { + reader.releaseLock(); + } + }); + } + async apiCall(url, requestInit) { + var _a; + if (!this.clientOptions.httpOptions || + !this.clientOptions.httpOptions.retryOptions) { + return fetch(url, requestInit); + } + const retryOptions = this.clientOptions.httpOptions.retryOptions; + const runFetch = async () => { + const response = await fetch(url, requestInit); + if (response.ok) { + return response; + } + if (DEFAULT_RETRY_HTTP_STATUS_CODES.includes(response.status)) { + throw new Error(`Retryable HTTP Error: ${response.statusText}`); + } + throw new pRetry.AbortError(`Non-retryable exception ${response.statusText} sending request`); + }; + return pRetry(runFetch, { + // Retry attempts is one less than the number of total attempts. + retries: ((_a = retryOptions.attempts) !== null && _a !== void 0 ? _a : DEFAULT_RETRY_ATTEMPTS) - 1, + }); + } + getDefaultHeaders() { + const headers = {}; + const versionHeaderValue = LIBRARY_LABEL + ' ' + this.clientOptions.userAgentExtra; + headers[USER_AGENT_HEADER] = versionHeaderValue; + headers[GOOGLE_API_CLIENT_HEADER] = versionHeaderValue; + headers[CONTENT_TYPE_HEADER] = 'application/json'; + return headers; + } + async getHeadersInternal(httpOptions, url) { + const headers = new Headers(); + if (httpOptions && httpOptions.headers) { + for (const [key, value] of Object.entries(httpOptions.headers)) { + headers.append(key, value); + } + // Append a timeout header if it is set, note that the timeout option is + // in milliseconds but the header is in seconds. + if (httpOptions.timeout && httpOptions.timeout > 0) { + headers.append(SERVER_TIMEOUT_HEADER, String(Math.ceil(httpOptions.timeout / 1000))); + } + } + await this.clientOptions.auth.addAuthHeaders(headers, url); + return headers; + } + getFileName(file) { + var _a; + let fileName = ''; + if (typeof file === 'string') { + fileName = file.replace(/[/\\]+$/, ''); + fileName = (_a = fileName.split(/[/\\]/).pop()) !== null && _a !== void 0 ? _a : ''; + } + return fileName; + } + /** + * Uploads a file asynchronously using Gemini API only, this is not supported + * in Vertex AI. + * + * @param file The string path to the file to be uploaded or a Blob object. + * @param config Optional parameters specified in the `UploadFileConfig` + * interface. @see {@link types.UploadFileConfig} + * @return A promise that resolves to a `File` object. + * @throws An error if called on a Vertex AI client. + * @throws An error if the `mimeType` is not provided and can not be inferred, + */ + async uploadFile(file, config) { + var _a; + const fileToUpload = {}; + if (config != null) { + fileToUpload.mimeType = config.mimeType; + fileToUpload.name = config.name; + fileToUpload.displayName = config.displayName; + } + if (fileToUpload.name && !fileToUpload.name.startsWith('files/')) { + fileToUpload.name = `files/${fileToUpload.name}`; + } + const uploader = this.clientOptions.uploader; + const fileStat = await uploader.stat(file); + fileToUpload.sizeBytes = String(fileStat.size); + const mimeType = (_a = config === null || config === void 0 ? void 0 : config.mimeType) !== null && _a !== void 0 ? _a : fileStat.type; + if (mimeType === undefined || mimeType === '') { + throw new Error('Can not determine mimeType. Please provide mimeType in the config.'); + } + fileToUpload.mimeType = mimeType; + const body = { + file: fileToUpload, + }; + const fileName = this.getFileName(file); + const path = formatMap('upload/v1beta/files', body['_url']); + const uploadUrl = await this.fetchUploadUrl(path, fileToUpload.sizeBytes, fileToUpload.mimeType, fileName, body, config === null || config === void 0 ? void 0 : config.httpOptions); + return uploader.upload(file, uploadUrl, this); + } + /** + * Uploads a file to a given file search store asynchronously using Gemini API only, this is not supported + * in Vertex AI. + * + * @param fileSearchStoreName The name of the file search store to upload the file to. + * @param file The string path to the file to be uploaded or a Blob object. + * @param config Optional parameters specified in the `UploadFileConfig` + * interface. @see {@link UploadFileConfig} + * @return A promise that resolves to a `File` object. + * @throws An error if called on a Vertex AI client. + * @throws An error if the `mimeType` is not provided and can not be inferred, + */ + async uploadFileToFileSearchStore(fileSearchStoreName, file, config) { + var _a; + const uploader = this.clientOptions.uploader; + const fileStat = await uploader.stat(file); + const sizeBytes = String(fileStat.size); + const mimeType = (_a = config === null || config === void 0 ? void 0 : config.mimeType) !== null && _a !== void 0 ? _a : fileStat.type; + if (mimeType === undefined || mimeType === '') { + throw new Error('Can not determine mimeType. Please provide mimeType in the config.'); + } + const path = `upload/v1beta/${fileSearchStoreName}:uploadToFileSearchStore`; + const fileName = this.getFileName(file); + const body = {}; + if (config != null) { + uploadToFileSearchStoreConfigToMldev(config, body); + } + const uploadUrl = await this.fetchUploadUrl(path, sizeBytes, mimeType, fileName, body, config === null || config === void 0 ? void 0 : config.httpOptions); + return uploader.uploadToFileSearchStore(file, uploadUrl, this); + } + /** + * Downloads a file asynchronously to the specified path. + * + * @params params - The parameters for the download request, see {@link + * types.DownloadFileParameters} + */ + async downloadFile(params) { + const downloader = this.clientOptions.downloader; + await downloader.download(params, this); + } + async fetchUploadUrl(path, sizeBytes, mimeType, fileName, body, configHttpOptions) { + var _a; + let httpOptions = {}; + if (configHttpOptions) { + httpOptions = configHttpOptions; + } + else { + httpOptions = { + apiVersion: '', // api-version is set in the path. + headers: Object.assign({ 'Content-Type': 'application/json', 'X-Goog-Upload-Protocol': 'resumable', 'X-Goog-Upload-Command': 'start', 'X-Goog-Upload-Header-Content-Length': `${sizeBytes}`, 'X-Goog-Upload-Header-Content-Type': `${mimeType}` }, (fileName ? { 'X-Goog-Upload-File-Name': fileName } : {})), + }; + } + const httpResponse = await this.request({ + path, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions, + }); + if (!httpResponse || !(httpResponse === null || httpResponse === void 0 ? void 0 : httpResponse.headers)) { + throw new Error('Server did not return an HttpResponse or the returned HttpResponse did not have headers.'); + } + const uploadUrl = (_a = httpResponse === null || httpResponse === void 0 ? void 0 : httpResponse.headers) === null || _a === void 0 ? void 0 : _a['x-goog-upload-url']; + if (uploadUrl === undefined) { + throw new Error('Failed to get upload url. Server did not return the x-google-upload-url in the headers'); + } + return uploadUrl; + } +} +async function throwErrorIfNotOK(response) { + var _a; + if (response === undefined) { + throw new Error('response is undefined'); + } + if (!response.ok) { + const status = response.status; + let errorBody; + if ((_a = response.headers.get('content-type')) === null || _a === void 0 ? void 0 : _a.includes('application/json')) { + errorBody = await response.json(); + } + else { + errorBody = { + error: { + message: await response.text(), + code: response.status, + status: response.statusText, + }, + }; + } + const errorMessage = JSON.stringify(errorBody); + if (status >= 400 && status < 600) { + const apiError = new ApiError({ + message: errorMessage, + status: status, + }); + throw apiError; + } + throw new Error(errorMessage); + } +} +/** + * Recursively updates the `requestInit.body` with values from an `extraBody` object. + * + * If `requestInit.body` is a string, it's assumed to be JSON and will be parsed. + * The `extraBody` is then deeply merged into this parsed object. + * If `requestInit.body` is a Blob, `extraBody` will be ignored, and a warning logged, + * as merging structured data into an opaque Blob is not supported. + * + * The function does not enforce that updated values from `extraBody` have the + * same type as existing values in `requestInit.body`. Type mismatches during + * the merge will result in a warning, but the value from `extraBody` will overwrite + * the original. `extraBody` users are responsible for ensuring `extraBody` has the correct structure. + * + * @param requestInit The RequestInit object whose body will be updated. + * @param extraBody The object containing updates to be merged into `requestInit.body`. + */ +function includeExtraBodyToRequestInit(requestInit, extraBody) { + if (!extraBody || Object.keys(extraBody).length === 0) { + return; + } + if (requestInit.body instanceof Blob) { + console.warn('includeExtraBodyToRequestInit: extraBody provided but current request body is a Blob. extraBody will be ignored as merging is not supported for Blob bodies.'); + return; + } + let currentBodyObject = {}; + // If adding new type to HttpRequest.body, please check the code below to + // see if we need to update the logic. + if (typeof requestInit.body === 'string' && requestInit.body.length > 0) { + try { + const parsedBody = JSON.parse(requestInit.body); + if (typeof parsedBody === 'object' && + parsedBody !== null && + !Array.isArray(parsedBody)) { + currentBodyObject = parsedBody; + } + else { + console.warn('includeExtraBodyToRequestInit: Original request body is valid JSON but not a non-array object. Skip applying extraBody to the request body.'); + return; + } + /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ + } + catch (e) { + console.warn('includeExtraBodyToRequestInit: Original request body is not valid JSON. Skip applying extraBody to the request body.'); + return; + } + } + function deepMerge(target, source) { + const output = Object.assign({}, target); + for (const key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + const sourceValue = source[key]; + const targetValue = output[key]; + if (sourceValue && + typeof sourceValue === 'object' && + !Array.isArray(sourceValue) && + targetValue && + typeof targetValue === 'object' && + !Array.isArray(targetValue)) { + output[key] = deepMerge(targetValue, sourceValue); + } + else { + if (targetValue && + sourceValue && + typeof targetValue !== typeof sourceValue) { + console.warn(`includeExtraBodyToRequestInit:deepMerge: Type mismatch for key "${key}". Original type: ${typeof targetValue}, New type: ${typeof sourceValue}. Overwriting.`); + } + output[key] = sourceValue; + } + } + } + return output; + } + const mergedBody = deepMerge(currentBodyObject, extraBody); + requestInit.body = JSON.stringify(mergedBody); +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// TODO: b/416041229 - Determine how to retrieve the MCP package version. +const MCP_LABEL = 'mcp_used/unknown'; +// Whether MCP tool usage is detected from mcpToTool. This is used for +// telemetry. +let hasMcpToolUsageFromMcpToTool = false; +// Checks whether the list of tools contains any MCP tools. +function hasMcpToolUsage(tools) { + for (const tool of tools) { + if (isMcpCallableTool(tool)) { + return true; + } + if (typeof tool === 'object' && 'inputSchema' in tool) { + return true; + } + } + return hasMcpToolUsageFromMcpToTool; +} +// Sets the MCP version label in the Google API client header. +function setMcpUsageHeader(headers) { + var _a; + const existingHeader = (_a = headers[GOOGLE_API_CLIENT_HEADER]) !== null && _a !== void 0 ? _a : ''; + headers[GOOGLE_API_CLIENT_HEADER] = (existingHeader + ` ${MCP_LABEL}`).trimStart(); +} +// Returns true if the object is a MCP CallableTool, otherwise false. +function isMcpCallableTool(object) { + return (object !== null && + typeof object === 'object' && + object instanceof McpCallableTool); +} +// List all tools from the MCP client. +function listAllTools(mcpClient_1) { + return __asyncGenerator(this, arguments, function* listAllTools_1(mcpClient, maxTools = 100) { + let cursor = undefined; + let numTools = 0; + while (numTools < maxTools) { + const t = yield __await(mcpClient.listTools({ cursor })); + for (const tool of t.tools) { + yield yield __await(tool); + numTools++; + } + if (!t.nextCursor) { + break; + } + cursor = t.nextCursor; + } + }); +} +/** + * McpCallableTool can be used for model inference and invoking MCP clients with + * given function call arguments. + * + * @experimental Built-in MCP support is an experimental feature, may change in future + * versions. + */ +class McpCallableTool { + constructor(mcpClients = [], config) { + this.mcpTools = []; + this.functionNameToMcpClient = {}; + this.mcpClients = mcpClients; + this.config = config; + } + /** + * Creates a McpCallableTool. + */ + static create(mcpClients, config) { + return new McpCallableTool(mcpClients, config); + } + /** + * Validates the function names are not duplicate and initialize the function + * name to MCP client mapping. + * + * @throws {Error} if the MCP tools from the MCP clients have duplicate tool + * names. + */ + async initialize() { + var _a, e_1, _b, _c; + if (this.mcpTools.length > 0) { + return; + } + const functionMap = {}; + const mcpTools = []; + for (const mcpClient of this.mcpClients) { + try { + for (var _d = true, _e = (e_1 = void 0, __asyncValues(listAllTools(mcpClient))), _f; _f = await _e.next(), _a = _f.done, !_a; _d = true) { + _c = _f.value; + _d = false; + const mcpTool = _c; + mcpTools.push(mcpTool); + const mcpToolName = mcpTool.name; + if (functionMap[mcpToolName]) { + throw new Error(`Duplicate function name ${mcpToolName} found in MCP tools. Please ensure function names are unique.`); + } + functionMap[mcpToolName] = mcpClient; + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (!_d && !_a && (_b = _e.return)) await _b.call(_e); + } + finally { if (e_1) throw e_1.error; } + } + } + this.mcpTools = mcpTools; + this.functionNameToMcpClient = functionMap; + } + async tool() { + await this.initialize(); + return mcpToolsToGeminiTool(this.mcpTools, this.config); + } + async callTool(functionCalls) { + await this.initialize(); + const functionCallResponseParts = []; + for (const functionCall of functionCalls) { + if (functionCall.name in this.functionNameToMcpClient) { + const mcpClient = this.functionNameToMcpClient[functionCall.name]; + let requestOptions = undefined; + // TODO: b/424238654 - Add support for finer grained timeout control. + if (this.config.timeout) { + requestOptions = { + timeout: this.config.timeout, + }; + } + const callToolResponse = await mcpClient.callTool({ + name: functionCall.name, + arguments: functionCall.args, + }, + // Set the result schema to undefined to allow MCP to rely on the + // default schema. + undefined, requestOptions); + functionCallResponseParts.push({ + functionResponse: { + name: functionCall.name, + response: callToolResponse.isError + ? { error: callToolResponse } + : callToolResponse, + }, + }); + } + } + return functionCallResponseParts; + } +} +function isMcpClient(client) { + return (client !== null && + typeof client === 'object' && + 'listTools' in client && + typeof client.listTools === 'function'); +} +/** + * Creates a McpCallableTool from MCP clients and an optional config. + * + * The callable tool can invoke the MCP clients with given function call + * arguments. (often for automatic function calling). + * Use the config to modify tool parameters such as behavior. + * + * @experimental Built-in MCP support is an experimental feature, may change in future + * versions. + */ +function mcpToTool(...args) { + // Set MCP usage for telemetry. + hasMcpToolUsageFromMcpToTool = true; + if (args.length === 0) { + throw new Error('No MCP clients provided'); + } + const maybeConfig = args[args.length - 1]; + if (isMcpClient(maybeConfig)) { + return McpCallableTool.create(args, {}); + } + return McpCallableTool.create(args.slice(0, args.length - 1), maybeConfig); +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Handles incoming messages from the WebSocket. + * + * @remarks + * This function is responsible for parsing incoming messages, transforming them + * into LiveMusicServerMessage, and then calling the onmessage callback. + * Note that the first message which is received from the server is a + * setupComplete message. + * + * @param apiClient The ApiClient instance. + * @param onmessage The user-provided onmessage callback (if any). + * @param event The MessageEvent from the WebSocket. + */ +async function handleWebSocketMessage$1(apiClient, onmessage, event) { + const serverMessage = new LiveMusicServerMessage(); + let data; + if (event.data instanceof Blob) { + data = JSON.parse(await event.data.text()); + } + else { + data = JSON.parse(event.data); + } + Object.assign(serverMessage, data); + onmessage(serverMessage); +} +/** + LiveMusic class encapsulates the configuration for live music + generation via Lyria Live models. + + @experimental + */ +class LiveMusic { + constructor(apiClient, auth, webSocketFactory) { + this.apiClient = apiClient; + this.auth = auth; + this.webSocketFactory = webSocketFactory; + } + /** + Establishes a connection to the specified model and returns a + LiveMusicSession object representing that connection. + + @experimental + + @remarks + + @param params - The parameters for establishing a connection to the model. + @return A live session. + + @example + ```ts + let model = 'models/lyria-realtime-exp'; + const session = await ai.live.music.connect({ + model: model, + callbacks: { + onmessage: (e: MessageEvent) => { + console.log('Received message from the server: %s\n', debug(e.data)); + }, + onerror: (e: ErrorEvent) => { + console.log('Error occurred: %s\n', debug(e.error)); + }, + onclose: (e: CloseEvent) => { + console.log('Connection closed.'); + }, + }, + }); + ``` + */ + async connect(params) { + var _a, _b; + if (this.apiClient.isVertexAI()) { + throw new Error('Live music is not supported for Vertex AI.'); + } + console.warn('Live music generation is experimental and may change in future versions.'); + const websocketBaseUrl = this.apiClient.getWebsocketBaseUrl(); + const apiVersion = this.apiClient.getApiVersion(); + const headers = mapToHeaders$1(this.apiClient.getDefaultHeaders()); + const apiKey = this.apiClient.getApiKey(); + const url = `${websocketBaseUrl}/ws/google.ai.generativelanguage.${apiVersion}.GenerativeService.BidiGenerateMusic?key=${apiKey}`; + let onopenResolve = () => { }; + const onopenPromise = new Promise((resolve) => { + onopenResolve = resolve; + }); + const callbacks = params.callbacks; + const onopenAwaitedCallback = function () { + onopenResolve({}); + }; + const apiClient = this.apiClient; + const websocketCallbacks = { + onopen: onopenAwaitedCallback, + onmessage: (event) => { + void handleWebSocketMessage$1(apiClient, callbacks.onmessage, event); + }, + onerror: (_a = callbacks === null || callbacks === void 0 ? void 0 : callbacks.onerror) !== null && _a !== void 0 ? _a : function (e) { + }, + onclose: (_b = callbacks === null || callbacks === void 0 ? void 0 : callbacks.onclose) !== null && _b !== void 0 ? _b : function (e) { + }, + }; + const conn = this.webSocketFactory.create(url, headersToMap$1(headers), websocketCallbacks); + conn.connect(); + // Wait for the websocket to open before sending requests. + await onopenPromise; + const model = tModel(this.apiClient, params.model); + const setup = { model }; + const clientMessage = { setup }; + conn.send(JSON.stringify(clientMessage)); + return new LiveMusicSession(conn, this.apiClient); + } +} +/** + Represents a connection to the API. + + @experimental + */ +class LiveMusicSession { + constructor(conn, apiClient) { + this.conn = conn; + this.apiClient = apiClient; + } + /** + Sets inputs to steer music generation. Updates the session's current + weighted prompts. + + @param params - Contains one property, `weightedPrompts`. + + - `weightedPrompts` to send to the model; weights are normalized to + sum to 1.0. + + @experimental + */ + async setWeightedPrompts(params) { + if (!params.weightedPrompts || + Object.keys(params.weightedPrompts).length === 0) { + throw new Error('Weighted prompts must be set and contain at least one entry.'); + } + const clientContent = liveMusicSetWeightedPromptsParametersToMldev(params); + this.conn.send(JSON.stringify({ clientContent })); + } + /** + Sets a configuration to the model. Updates the session's current + music generation config. + + @param params - Contains one property, `musicGenerationConfig`. + + - `musicGenerationConfig` to set in the model. Passing an empty or + undefined config to the model will reset the config to defaults. + + @experimental + */ + async setMusicGenerationConfig(params) { + if (!params.musicGenerationConfig) { + params.musicGenerationConfig = {}; + } + const setConfigParameters = liveMusicSetConfigParametersToMldev(params); + this.conn.send(JSON.stringify(setConfigParameters)); + } + sendPlaybackControl(playbackControl) { + const clientMessage = { playbackControl }; + this.conn.send(JSON.stringify(clientMessage)); + } + /** + * Start the music stream. + * + * @experimental + */ + play() { + this.sendPlaybackControl(exports.LiveMusicPlaybackControl.PLAY); + } + /** + * Temporarily halt the music stream. Use `play` to resume from the current + * position. + * + * @experimental + */ + pause() { + this.sendPlaybackControl(exports.LiveMusicPlaybackControl.PAUSE); + } + /** + * Stop the music stream and reset the state. Retains the current prompts + * and config. + * + * @experimental + */ + stop() { + this.sendPlaybackControl(exports.LiveMusicPlaybackControl.STOP); + } + /** + * Resets the context of the music generation without stopping it. + * Retains the current prompts and config. + * + * @experimental + */ + resetContext() { + this.sendPlaybackControl(exports.LiveMusicPlaybackControl.RESET_CONTEXT); + } + /** + Terminates the WebSocket connection. + + @experimental + */ + close() { + this.conn.close(); + } +} +// Converts an headers object to a "map" object as expected by the WebSocket +// constructor. We use this as the Auth interface works with Headers objects +// while the WebSocket constructor takes a map. +function headersToMap$1(headers) { + const headerMap = {}; + headers.forEach((value, key) => { + headerMap[key] = value; + }); + return headerMap; +} +// Converts a "map" object to a headers object. We use this as the Auth +// interface works with Headers objects while the API client default headers +// returns a map. +function mapToHeaders$1(map) { + const headers = new Headers(); + for (const [key, value] of Object.entries(map)) { + headers.append(key, value); + } + return headers; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const FUNCTION_RESPONSE_REQUIRES_ID = 'FunctionResponse request must have an `id` field from the response of a ToolCall.FunctionalCalls in Google AI.'; +/** + * Handles incoming messages from the WebSocket. + * + * @remarks + * This function is responsible for parsing incoming messages, transforming them + * into LiveServerMessages, and then calling the onmessage callback. Note that + * the first message which is received from the server is a setupComplete + * message. + * + * @param apiClient The ApiClient instance. + * @param onmessage The user-provided onmessage callback (if any). + * @param event The MessageEvent from the WebSocket. + */ +async function handleWebSocketMessage(apiClient, onmessage, event) { + const serverMessage = new LiveServerMessage(); + let jsonData; + if (event.data instanceof Blob) { + jsonData = await event.data.text(); + } + else if (event.data instanceof ArrayBuffer) { + jsonData = new TextDecoder().decode(event.data); + } + else { + jsonData = event.data; + } + const data = JSON.parse(jsonData); + if (apiClient.isVertexAI()) { + const resp = liveServerMessageFromVertex(data); + Object.assign(serverMessage, resp); + } + else { + const resp = data; + Object.assign(serverMessage, resp); + } + onmessage(serverMessage); +} +/** + Live class encapsulates the configuration for live interaction with the + Generative Language API. It embeds ApiClient for general API settings. + + @experimental + */ +class Live { + constructor(apiClient, auth, webSocketFactory) { + this.apiClient = apiClient; + this.auth = auth; + this.webSocketFactory = webSocketFactory; + this.music = new LiveMusic(this.apiClient, this.auth, this.webSocketFactory); + } + /** + Establishes a connection to the specified model with the given + configuration and returns a Session object representing that connection. + + @experimental Built-in MCP support is an experimental feature, may change in + future versions. + + @remarks + + @param params - The parameters for establishing a connection to the model. + @return A live session. + + @example + ```ts + let model: string; + if (GOOGLE_GENAI_USE_VERTEXAI) { + model = 'gemini-2.0-flash-live-preview-04-09'; + } else { + model = 'gemini-live-2.5-flash-preview'; + } + const session = await ai.live.connect({ + model: model, + config: { + responseModalities: [Modality.AUDIO], + }, + callbacks: { + onopen: () => { + console.log('Connected to the socket.'); + }, + onmessage: (e: MessageEvent) => { + console.log('Received message from the server: %s\n', debug(e.data)); + }, + onerror: (e: ErrorEvent) => { + console.log('Error occurred: %s\n', debug(e.error)); + }, + onclose: (e: CloseEvent) => { + console.log('Connection closed.'); + }, + }, + }); + ``` + */ + async connect(params) { + var _a, _b, _c, _d, _e, _f; + // TODO: b/404946746 - Support per request HTTP options. + if (params.config && params.config.httpOptions) { + throw new Error('The Live module does not support httpOptions at request-level in' + + ' LiveConnectConfig yet. Please use the client-level httpOptions' + + ' configuration instead.'); + } + const websocketBaseUrl = this.apiClient.getWebsocketBaseUrl(); + const apiVersion = this.apiClient.getApiVersion(); + let url; + const clientHeaders = this.apiClient.getHeaders(); + if (params.config && + params.config.tools && + hasMcpToolUsage(params.config.tools)) { + setMcpUsageHeader(clientHeaders); + } + const headers = mapToHeaders(clientHeaders); + if (this.apiClient.isVertexAI()) { + const project = this.apiClient.getProject(); + const location = this.apiClient.getLocation(); + const apiKey = this.apiClient.getApiKey(); + const hasStandardAuth = (!!project && !!location) || !!apiKey; + if (this.apiClient.getCustomBaseUrl() && !hasStandardAuth) { + // Custom base URL without standard auth (e.g., proxy). + url = websocketBaseUrl; + // Auth headers are assumed to be in `clientHeaders` from httpOptions. + } + else { + url = `${websocketBaseUrl}/ws/google.cloud.aiplatform.${apiVersion}.LlmBidiService/BidiGenerateContent`; + await this.auth.addAuthHeaders(headers, url); + } + } + else { + const apiKey = this.apiClient.getApiKey(); + let method = 'BidiGenerateContent'; + let keyName = 'key'; + if (apiKey === null || apiKey === void 0 ? void 0 : apiKey.startsWith('auth_tokens/')) { + console.warn('Warning: Ephemeral token support is experimental and may change in future versions.'); + if (apiVersion !== 'v1alpha') { + console.warn("Warning: The SDK's ephemeral token support is in v1alpha only. Please use const ai = new GoogleGenAI({apiKey: token.name, httpOptions: { apiVersion: 'v1alpha' }}); before session connection."); + } + method = 'BidiGenerateContentConstrained'; + keyName = 'access_token'; + } + url = `${websocketBaseUrl}/ws/google.ai.generativelanguage.${apiVersion}.GenerativeService.${method}?${keyName}=${apiKey}`; + } + let onopenResolve = () => { }; + const onopenPromise = new Promise((resolve) => { + onopenResolve = resolve; + }); + const callbacks = params.callbacks; + const onopenAwaitedCallback = function () { + var _a; + (_a = callbacks === null || callbacks === void 0 ? void 0 : callbacks.onopen) === null || _a === void 0 ? void 0 : _a.call(callbacks); + onopenResolve({}); + }; + const apiClient = this.apiClient; + const websocketCallbacks = { + onopen: onopenAwaitedCallback, + onmessage: (event) => { + void handleWebSocketMessage(apiClient, callbacks.onmessage, event); + }, + onerror: (_a = callbacks === null || callbacks === void 0 ? void 0 : callbacks.onerror) !== null && _a !== void 0 ? _a : function (e) { + }, + onclose: (_b = callbacks === null || callbacks === void 0 ? void 0 : callbacks.onclose) !== null && _b !== void 0 ? _b : function (e) { + }, + }; + const conn = this.webSocketFactory.create(url, headersToMap(headers), websocketCallbacks); + conn.connect(); + // Wait for the websocket to open before sending requests. + await onopenPromise; + let transformedModel = tModel(this.apiClient, params.model); + if (this.apiClient.isVertexAI() && + transformedModel.startsWith('publishers/')) { + const project = this.apiClient.getProject(); + const location = this.apiClient.getLocation(); + if (project && location) { + transformedModel = + `projects/${project}/locations/${location}/` + transformedModel; + } + } + let clientMessage = {}; + if (this.apiClient.isVertexAI() && + ((_c = params.config) === null || _c === void 0 ? void 0 : _c.responseModalities) === undefined) { + // Set default to AUDIO to align with MLDev API. + if (params.config === undefined) { + params.config = { responseModalities: [exports.Modality.AUDIO] }; + } + else { + params.config.responseModalities = [exports.Modality.AUDIO]; + } + } + if ((_d = params.config) === null || _d === void 0 ? void 0 : _d.generationConfig) { + // Raise deprecation warning for generationConfig. + console.warn('Setting `LiveConnectConfig.generation_config` is deprecated, please set the fields on `LiveConnectConfig` directly. This will become an error in a future version (not before Q3 2025).'); + } + const inputTools = (_f = (_e = params.config) === null || _e === void 0 ? void 0 : _e.tools) !== null && _f !== void 0 ? _f : []; + const convertedTools = []; + for (const tool of inputTools) { + if (this.isCallableTool(tool)) { + const callableTool = tool; + convertedTools.push(await callableTool.tool()); + } + else { + convertedTools.push(tool); + } + } + if (convertedTools.length > 0) { + params.config.tools = convertedTools; + } + const liveConnectParameters = { + model: transformedModel, + config: params.config, + callbacks: params.callbacks, + }; + if (this.apiClient.isVertexAI()) { + clientMessage = liveConnectParametersToVertex(this.apiClient, liveConnectParameters); + } + else { + clientMessage = liveConnectParametersToMldev(this.apiClient, liveConnectParameters); + } + delete clientMessage['config']; + conn.send(JSON.stringify(clientMessage)); + return new Session(conn, this.apiClient); + } + // TODO: b/416041229 - Abstract this method to a common place. + isCallableTool(tool) { + return 'callTool' in tool && typeof tool.callTool === 'function'; + } +} +const defaultLiveSendClientContentParamerters = { + turnComplete: true, +}; +/** + Represents a connection to the API. + + @experimental + */ +class Session { + constructor(conn, apiClient) { + this.conn = conn; + this.apiClient = apiClient; + } + tLiveClientContent(apiClient, params) { + if (params.turns !== null && params.turns !== undefined) { + let contents = []; + try { + contents = tContents(params.turns); + if (!apiClient.isVertexAI()) { + contents = contents.map((item) => contentToMldev$1(item)); + } + } + catch (_a) { + throw new Error(`Failed to parse client content "turns", type: '${typeof params.turns}'`); + } + return { + clientContent: { turns: contents, turnComplete: params.turnComplete }, + }; + } + return { + clientContent: { turnComplete: params.turnComplete }, + }; + } + tLiveClienttToolResponse(apiClient, params) { + let functionResponses = []; + if (params.functionResponses == null) { + throw new Error('functionResponses is required.'); + } + if (!Array.isArray(params.functionResponses)) { + functionResponses = [params.functionResponses]; + } + else { + functionResponses = params.functionResponses; + } + if (functionResponses.length === 0) { + throw new Error('functionResponses is required.'); + } + for (const functionResponse of functionResponses) { + if (typeof functionResponse !== 'object' || + functionResponse === null || + !('name' in functionResponse) || + !('response' in functionResponse)) { + throw new Error(`Could not parse function response, type '${typeof functionResponse}'.`); + } + if (!apiClient.isVertexAI() && !('id' in functionResponse)) { + throw new Error(FUNCTION_RESPONSE_REQUIRES_ID); + } + } + const clientMessage = { + toolResponse: { functionResponses: functionResponses }, + }; + return clientMessage; + } + /** + Send a message over the established connection. + + @param params - Contains two **optional** properties, `turns` and + `turnComplete`. + + - `turns` will be converted to a `Content[]` + - `turnComplete: true` [default] indicates that you are done sending + content and expect a response. If `turnComplete: false`, the server + will wait for additional messages before starting generation. + + @experimental + + @remarks + There are two ways to send messages to the live API: + `sendClientContent` and `sendRealtimeInput`. + + `sendClientContent` messages are added to the model context **in order**. + Having a conversation using `sendClientContent` messages is roughly + equivalent to using the `Chat.sendMessageStream`, except that the state of + the `chat` history is stored on the API server instead of locally. + + Because of `sendClientContent`'s order guarantee, the model cannot respons + as quickly to `sendClientContent` messages as to `sendRealtimeInput` + messages. This makes the biggest difference when sending objects that have + significant preprocessing time (typically images). + + The `sendClientContent` message sends a `Content[]` + which has more options than the `Blob` sent by `sendRealtimeInput`. + + So the main use-cases for `sendClientContent` over `sendRealtimeInput` are: + + - Sending anything that can't be represented as a `Blob` (text, + `sendClientContent({turns="Hello?"}`)). + - Managing turns when not using audio input and voice activity detection. + (`sendClientContent({turnComplete:true})` or the short form + `sendClientContent()`) + - Prefilling a conversation context + ``` + sendClientContent({ + turns: [ + Content({role:user, parts:...}), + Content({role:user, parts:...}), + ... + ] + }) + ``` + @experimental + */ + sendClientContent(params) { + params = Object.assign(Object.assign({}, defaultLiveSendClientContentParamerters), params); + const clientMessage = this.tLiveClientContent(this.apiClient, params); + this.conn.send(JSON.stringify(clientMessage)); + } + /** + Send a realtime message over the established connection. + + @param params - Contains one property, `media`. + + - `media` will be converted to a `Blob` + + @experimental + + @remarks + Use `sendRealtimeInput` for realtime audio chunks and video frames (images). + + With `sendRealtimeInput` the api will respond to audio automatically + based on voice activity detection (VAD). + + `sendRealtimeInput` is optimized for responsivness at the expense of + deterministic ordering guarantees. Audio and video tokens are to the + context when they become available. + + Note: The Call signature expects a `Blob` object, but only a subset + of audio and image mimetypes are allowed. + */ + sendRealtimeInput(params) { + let clientMessage = {}; + if (this.apiClient.isVertexAI()) { + clientMessage = { + 'realtimeInput': liveSendRealtimeInputParametersToVertex(params), + }; + } + else { + clientMessage = { + 'realtimeInput': liveSendRealtimeInputParametersToMldev(params), + }; + } + this.conn.send(JSON.stringify(clientMessage)); + } + /** + Send a function response message over the established connection. + + @param params - Contains property `functionResponses`. + + - `functionResponses` will be converted to a `functionResponses[]` + + @remarks + Use `sendFunctionResponse` to reply to `LiveServerToolCall` from the server. + + Use {@link types.LiveConnectConfig#tools} to configure the callable functions. + + @experimental + */ + sendToolResponse(params) { + if (params.functionResponses == null) { + throw new Error('Tool response parameters are required.'); + } + const clientMessage = this.tLiveClienttToolResponse(this.apiClient, params); + this.conn.send(JSON.stringify(clientMessage)); + } + /** + Terminates the WebSocket connection. + + @experimental + + @example + ```ts + let model: string; + if (GOOGLE_GENAI_USE_VERTEXAI) { + model = 'gemini-2.0-flash-live-preview-04-09'; + } else { + model = 'gemini-live-2.5-flash-preview'; + } + const session = await ai.live.connect({ + model: model, + config: { + responseModalities: [Modality.AUDIO], + } + }); + + session.close(); + ``` + */ + close() { + this.conn.close(); + } +} +// Converts an headers object to a "map" object as expected by the WebSocket +// constructor. We use this as the Auth interface works with Headers objects +// while the WebSocket constructor takes a map. +function headersToMap(headers) { + const headerMap = {}; + headers.forEach((value, key) => { + headerMap[key] = value; + }); + return headerMap; +} +// Converts a "map" object to a headers object. We use this as the Auth +// interface works with Headers objects while the API client default headers +// returns a map. +function mapToHeaders(map) { + const headers = new Headers(); + for (const [key, value] of Object.entries(map)) { + headers.append(key, value); + } + return headers; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const DEFAULT_MAX_REMOTE_CALLS = 10; +/** Returns whether automatic function calling is disabled. */ +function shouldDisableAfc(config) { + var _a, _b, _c; + if ((_a = config === null || config === void 0 ? void 0 : config.automaticFunctionCalling) === null || _a === void 0 ? void 0 : _a.disable) { + return true; + } + let callableToolsPresent = false; + for (const tool of (_b = config === null || config === void 0 ? void 0 : config.tools) !== null && _b !== void 0 ? _b : []) { + if (isCallableTool(tool)) { + callableToolsPresent = true; + break; + } + } + if (!callableToolsPresent) { + return true; + } + const maxCalls = (_c = config === null || config === void 0 ? void 0 : config.automaticFunctionCalling) === null || _c === void 0 ? void 0 : _c.maximumRemoteCalls; + if ((maxCalls && (maxCalls < 0 || !Number.isInteger(maxCalls))) || + maxCalls == 0) { + console.warn('Invalid maximumRemoteCalls value provided for automatic function calling. Disabled automatic function calling. Please provide a valid integer value greater than 0. maximumRemoteCalls provided:', maxCalls); + return true; + } + return false; +} +function isCallableTool(tool) { + return 'callTool' in tool && typeof tool.callTool === 'function'; +} +// Checks whether the list of tools contains any CallableTools. Will return true +// if there is at least one CallableTool. +function hasCallableTools(params) { + var _a, _b, _c; + return (_c = (_b = (_a = params.config) === null || _a === void 0 ? void 0 : _a.tools) === null || _b === void 0 ? void 0 : _b.some((tool) => isCallableTool(tool))) !== null && _c !== void 0 ? _c : false; +} +/** + * Returns the indexes of the tools that are not compatible with AFC. + */ +function findAfcIncompatibleToolIndexes(params) { + var _a; + // Use number[] for an array of numbers in TypeScript + const afcIncompatibleToolIndexes = []; + if (!((_a = params === null || params === void 0 ? void 0 : params.config) === null || _a === void 0 ? void 0 : _a.tools)) { + return afcIncompatibleToolIndexes; + } + params.config.tools.forEach((tool, index) => { + if (isCallableTool(tool)) { + return; + } + const geminiTool = tool; + if (geminiTool.functionDeclarations && + geminiTool.functionDeclarations.length > 0) { + afcIncompatibleToolIndexes.push(index); + } + }); + return afcIncompatibleToolIndexes; +} +/** + * Returns whether to append automatic function calling history to the + * response. + */ +function shouldAppendAfcHistory(config) { + var _a; + return !((_a = config === null || config === void 0 ? void 0 : config.automaticFunctionCalling) === null || _a === void 0 ? void 0 : _a.ignoreCallHistory); +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Models extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + /** + * Makes an API request to generate content with a given model. + * + * For the `model` parameter, supported formats for Vertex AI API include: + * - The Gemini model ID, for example: 'gemini-2.0-flash' + * - The full resource name starts with 'projects/', for example: + * 'projects/my-project-id/locations/us-central1/publishers/google/models/gemini-2.0-flash' + * - The partial resource name with 'publishers/', for example: + * 'publishers/google/models/gemini-2.0-flash' or + * 'publishers/meta/models/llama-3.1-405b-instruct-maas' + * - `/` separated publisher and model name, for example: + * 'google/gemini-2.0-flash' or 'meta/llama-3.1-405b-instruct-maas' + * + * For the `model` parameter, supported formats for Gemini API include: + * - The Gemini model ID, for example: 'gemini-2.0-flash' + * - The model name starts with 'models/', for example: + * 'models/gemini-2.0-flash' + * - For tuned models, the model name starts with 'tunedModels/', + * for example: + * 'tunedModels/1234567890123456789' + * + * Some models support multimodal input and output. + * + * @param params - The parameters for generating content. + * @return The response from generating content. + * + * @example + * ```ts + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: 'why is the sky blue?', + * config: { + * candidateCount: 2, + * } + * }); + * console.log(response); + * ``` + */ + this.generateContent = async (params) => { + var _a, _b, _c, _d, _e; + const transformedParams = await this.processParamsMaybeAddMcpUsage(params); + this.maybeMoveToResponseJsonSchem(params); + if (!hasCallableTools(params) || shouldDisableAfc(params.config)) { + return await this.generateContentInternal(transformedParams); + } + const incompatibleToolIndexes = findAfcIncompatibleToolIndexes(params); + if (incompatibleToolIndexes.length > 0) { + const formattedIndexes = incompatibleToolIndexes + .map((index) => `tools[${index}]`) + .join(', '); + throw new Error(`Automatic function calling with CallableTools (or MCP objects) and basic FunctionDeclarations is not yet supported. Incompatible tools found at ${formattedIndexes}.`); + } + let response; + let functionResponseContent; + const automaticFunctionCallingHistory = tContents(transformedParams.contents); + const maxRemoteCalls = (_c = (_b = (_a = transformedParams.config) === null || _a === void 0 ? void 0 : _a.automaticFunctionCalling) === null || _b === void 0 ? void 0 : _b.maximumRemoteCalls) !== null && _c !== void 0 ? _c : DEFAULT_MAX_REMOTE_CALLS; + let remoteCalls = 0; + while (remoteCalls < maxRemoteCalls) { + response = await this.generateContentInternal(transformedParams); + if (!response.functionCalls || response.functionCalls.length === 0) { + break; + } + const responseContent = response.candidates[0].content; + const functionResponseParts = []; + for (const tool of (_e = (_d = params.config) === null || _d === void 0 ? void 0 : _d.tools) !== null && _e !== void 0 ? _e : []) { + if (isCallableTool(tool)) { + const callableTool = tool; + const parts = await callableTool.callTool(response.functionCalls); + functionResponseParts.push(...parts); + } + } + remoteCalls++; + functionResponseContent = { + role: 'user', + parts: functionResponseParts, + }; + transformedParams.contents = tContents(transformedParams.contents); + transformedParams.contents.push(responseContent); + transformedParams.contents.push(functionResponseContent); + if (shouldAppendAfcHistory(transformedParams.config)) { + automaticFunctionCallingHistory.push(responseContent); + automaticFunctionCallingHistory.push(functionResponseContent); + } + } + if (shouldAppendAfcHistory(transformedParams.config)) { + response.automaticFunctionCallingHistory = + automaticFunctionCallingHistory; + } + return response; + }; + /** + * Makes an API request to generate content with a given model and yields the + * response in chunks. + * + * For the `model` parameter, supported formats for Vertex AI API include: + * - The Gemini model ID, for example: 'gemini-2.0-flash' + * - The full resource name starts with 'projects/', for example: + * 'projects/my-project-id/locations/us-central1/publishers/google/models/gemini-2.0-flash' + * - The partial resource name with 'publishers/', for example: + * 'publishers/google/models/gemini-2.0-flash' or + * 'publishers/meta/models/llama-3.1-405b-instruct-maas' + * - `/` separated publisher and model name, for example: + * 'google/gemini-2.0-flash' or 'meta/llama-3.1-405b-instruct-maas' + * + * For the `model` parameter, supported formats for Gemini API include: + * - The Gemini model ID, for example: 'gemini-2.0-flash' + * - The model name starts with 'models/', for example: + * 'models/gemini-2.0-flash' + * - For tuned models, the model name starts with 'tunedModels/', + * for example: + * 'tunedModels/1234567890123456789' + * + * Some models support multimodal input and output. + * + * @param params - The parameters for generating content with streaming response. + * @return The response from generating content. + * + * @example + * ```ts + * const response = await ai.models.generateContentStream({ + * model: 'gemini-2.0-flash', + * contents: 'why is the sky blue?', + * config: { + * maxOutputTokens: 200, + * } + * }); + * for await (const chunk of response) { + * console.log(chunk); + * } + * ``` + */ + this.generateContentStream = async (params) => { + var _a, _b, _c, _d, _e; + this.maybeMoveToResponseJsonSchem(params); + if (shouldDisableAfc(params.config)) { + const transformedParams = await this.processParamsMaybeAddMcpUsage(params); + return await this.generateContentStreamInternal(transformedParams); + } + const incompatibleToolIndexes = findAfcIncompatibleToolIndexes(params); + if (incompatibleToolIndexes.length > 0) { + const formattedIndexes = incompatibleToolIndexes + .map((index) => `tools[${index}]`) + .join(', '); + throw new Error(`Incompatible tools found at ${formattedIndexes}. Automatic function calling with CallableTools (or MCP objects) and basic FunctionDeclarations" is not yet supported.`); + } + // With tool compatibility confirmed, validate that the configuration are + // compatible with each other and raise an error if invalid. + const streamFunctionCall = (_c = (_b = (_a = params === null || params === void 0 ? void 0 : params.config) === null || _a === void 0 ? void 0 : _a.toolConfig) === null || _b === void 0 ? void 0 : _b.functionCallingConfig) === null || _c === void 0 ? void 0 : _c.streamFunctionCallArguments; + const disableAfc = (_e = (_d = params === null || params === void 0 ? void 0 : params.config) === null || _d === void 0 ? void 0 : _d.automaticFunctionCalling) === null || _e === void 0 ? void 0 : _e.disable; + if (streamFunctionCall && !disableAfc) { + throw new Error("Running in streaming mode with 'streamFunctionCallArguments' enabled, " + + 'this feature is not compatible with automatic function calling (AFC). ' + + "Please set 'config.automaticFunctionCalling.disable' to true to disable AFC " + + "or leave 'config.toolConfig.functionCallingConfig.streamFunctionCallArguments' " + + 'to be undefined or set to false to disable streaming function call arguments feature.'); + } + return await this.processAfcStream(params); + }; + /** + * Generates an image based on a text description and configuration. + * + * @param params - The parameters for generating images. + * @return The response from the API. + * + * @example + * ```ts + * const response = await client.models.generateImages({ + * model: 'imagen-4.0-generate-001', + * prompt: 'Robot holding a red skateboard', + * config: { + * numberOfImages: 1, + * includeRaiReason: true, + * }, + * }); + * console.log(response?.generatedImages?.[0]?.image?.imageBytes); + * ``` + */ + this.generateImages = async (params) => { + return await this.generateImagesInternal(params).then((apiResponse) => { + var _a; + let positivePromptSafetyAttributes; + const generatedImages = []; + if (apiResponse === null || apiResponse === void 0 ? void 0 : apiResponse.generatedImages) { + for (const generatedImage of apiResponse.generatedImages) { + if (generatedImage && + (generatedImage === null || generatedImage === void 0 ? void 0 : generatedImage.safetyAttributes) && + ((_a = generatedImage === null || generatedImage === void 0 ? void 0 : generatedImage.safetyAttributes) === null || _a === void 0 ? void 0 : _a.contentType) === 'Positive Prompt') { + positivePromptSafetyAttributes = generatedImage === null || generatedImage === void 0 ? void 0 : generatedImage.safetyAttributes; + } + else { + generatedImages.push(generatedImage); + } + } + } + let response; + if (positivePromptSafetyAttributes) { + response = { + generatedImages: generatedImages, + positivePromptSafetyAttributes: positivePromptSafetyAttributes, + sdkHttpResponse: apiResponse.sdkHttpResponse, + }; + } + else { + response = { + generatedImages: generatedImages, + sdkHttpResponse: apiResponse.sdkHttpResponse, + }; + } + return response; + }); + }; + this.list = async (params) => { + var _a; + const defaultConfig = { + queryBase: true, + }; + const actualConfig = Object.assign(Object.assign({}, defaultConfig), params === null || params === void 0 ? void 0 : params.config); + const actualParams = { + config: actualConfig, + }; + if (this.apiClient.isVertexAI()) { + if (!actualParams.config.queryBase) { + if ((_a = actualParams.config) === null || _a === void 0 ? void 0 : _a.filter) { + throw new Error('Filtering tuned models list for Vertex AI is not currently supported'); + } + else { + actualParams.config.filter = 'labels.tune-type:*'; + } + } + } + return new Pager(exports.PagedItem.PAGED_ITEM_MODELS, (x) => this.listInternal(x), await this.listInternal(actualParams), actualParams); + }; + /** + * Edits an image based on a prompt, list of reference images, and configuration. + * + * @param params - The parameters for editing an image. + * @return The response from the API. + * + * @example + * ```ts + * const response = await client.models.editImage({ + * model: 'imagen-3.0-capability-001', + * prompt: 'Generate an image containing a mug with the product logo [1] visible on the side of the mug.', + * referenceImages: [subjectReferenceImage] + * config: { + * numberOfImages: 1, + * includeRaiReason: true, + * }, + * }); + * console.log(response?.generatedImages?.[0]?.image?.imageBytes); + * ``` + */ + this.editImage = async (params) => { + const paramsInternal = { + model: params.model, + prompt: params.prompt, + referenceImages: [], + config: params.config, + }; + if (params.referenceImages) { + if (params.referenceImages) { + paramsInternal.referenceImages = params.referenceImages.map((img) => img.toReferenceImageAPI()); + } + } + return await this.editImageInternal(paramsInternal); + }; + /** + * Upscales an image based on an image, upscale factor, and configuration. + * Only supported in Vertex AI currently. + * + * @param params - The parameters for upscaling an image. + * @return The response from the API. + * + * @example + * ```ts + * const response = await client.models.upscaleImage({ + * model: 'imagen-4.0-upscale-preview', + * image: image, + * upscaleFactor: 'x2', + * config: { + * includeRaiReason: true, + * }, + * }); + * console.log(response?.generatedImages?.[0]?.image?.imageBytes); + * ``` + */ + this.upscaleImage = async (params) => { + let apiConfig = { + numberOfImages: 1, + mode: 'upscale', + }; + if (params.config) { + apiConfig = Object.assign(Object.assign({}, apiConfig), params.config); + } + const apiParams = { + model: params.model, + image: params.image, + upscaleFactor: params.upscaleFactor, + config: apiConfig, + }; + return await this.upscaleImageInternal(apiParams); + }; + /** + * Generates videos based on a text description and configuration. + * + * @param params - The parameters for generating videos. + * @return A Promise<GenerateVideosOperation> which allows you to track the progress and eventually retrieve the generated videos using the operations.get method. + * + * @example + * ```ts + * const operation = await ai.models.generateVideos({ + * model: 'veo-2.0-generate-001', + * source: { + * prompt: 'A neon hologram of a cat driving at top speed', + * }, + * config: { + * numberOfVideos: 1 + * }); + * + * while (!operation.done) { + * await new Promise(resolve => setTimeout(resolve, 10000)); + * operation = await ai.operations.getVideosOperation({operation: operation}); + * } + * + * console.log(operation.response?.generatedVideos?.[0]?.video?.uri); + * ``` + */ + this.generateVideos = async (params) => { + var _a, _b, _c, _d, _e, _f; + if ((params.prompt || params.image || params.video) && params.source) { + throw new Error('Source and prompt/image/video are mutually exclusive. Please only use source.'); + } + // Gemini API does not support video bytes. + if (!this.apiClient.isVertexAI()) { + if (((_a = params.video) === null || _a === void 0 ? void 0 : _a.uri) && ((_b = params.video) === null || _b === void 0 ? void 0 : _b.videoBytes)) { + params.video = { + uri: params.video.uri, + mimeType: params.video.mimeType, + }; + } + else if (((_d = (_c = params.source) === null || _c === void 0 ? void 0 : _c.video) === null || _d === void 0 ? void 0 : _d.uri) && + ((_f = (_e = params.source) === null || _e === void 0 ? void 0 : _e.video) === null || _f === void 0 ? void 0 : _f.videoBytes)) { + params.source.video = { + uri: params.source.video.uri, + mimeType: params.source.video.mimeType, + }; + } + } + return await this.generateVideosInternal(params); + }; + } + /** + * This logic is needed for GenerateContentConfig only. + * Previously we made GenerateContentConfig.responseSchema field to accept + * unknown. Since v1.9.0, we switch to use backend JSON schema support. + * To maintain backward compatibility, we move the data that was treated as + * JSON schema from the responseSchema field to the responseJsonSchema field. + */ + maybeMoveToResponseJsonSchem(params) { + if (params.config && params.config.responseSchema) { + if (!params.config.responseJsonSchema) { + if (Object.keys(params.config.responseSchema).includes('$schema')) { + params.config.responseJsonSchema = params.config.responseSchema; + delete params.config.responseSchema; + } + } + } + return; + } + /** + * Transforms the CallableTools in the parameters to be simply Tools, it + * copies the params into a new object and replaces the tools, it does not + * modify the original params. Also sets the MCP usage header if there are + * MCP tools in the parameters. + */ + async processParamsMaybeAddMcpUsage(params) { + var _a, _b, _c; + const tools = (_a = params.config) === null || _a === void 0 ? void 0 : _a.tools; + if (!tools) { + return params; + } + const transformedTools = await Promise.all(tools.map(async (tool) => { + if (isCallableTool(tool)) { + const callableTool = tool; + return await callableTool.tool(); + } + return tool; + })); + const newParams = { + model: params.model, + contents: params.contents, + config: Object.assign(Object.assign({}, params.config), { tools: transformedTools }), + }; + newParams.config.tools = transformedTools; + if (params.config && + params.config.tools && + hasMcpToolUsage(params.config.tools)) { + const headers = (_c = (_b = params.config.httpOptions) === null || _b === void 0 ? void 0 : _b.headers) !== null && _c !== void 0 ? _c : {}; + let newHeaders = Object.assign({}, headers); + if (Object.keys(newHeaders).length === 0) { + newHeaders = this.apiClient.getDefaultHeaders(); + } + setMcpUsageHeader(newHeaders); + newParams.config.httpOptions = Object.assign(Object.assign({}, params.config.httpOptions), { headers: newHeaders }); + } + return newParams; + } + async initAfcToolsMap(params) { + var _a, _b, _c; + const afcTools = new Map(); + for (const tool of (_b = (_a = params.config) === null || _a === void 0 ? void 0 : _a.tools) !== null && _b !== void 0 ? _b : []) { + if (isCallableTool(tool)) { + const callableTool = tool; + const toolDeclaration = await callableTool.tool(); + for (const declaration of (_c = toolDeclaration.functionDeclarations) !== null && _c !== void 0 ? _c : []) { + if (!declaration.name) { + throw new Error('Function declaration name is required.'); + } + if (afcTools.has(declaration.name)) { + throw new Error(`Duplicate tool declaration name: ${declaration.name}`); + } + afcTools.set(declaration.name, callableTool); + } + } + } + return afcTools; + } + async processAfcStream(params) { + var _a, _b, _c; + const maxRemoteCalls = (_c = (_b = (_a = params.config) === null || _a === void 0 ? void 0 : _a.automaticFunctionCalling) === null || _b === void 0 ? void 0 : _b.maximumRemoteCalls) !== null && _c !== void 0 ? _c : DEFAULT_MAX_REMOTE_CALLS; + let wereFunctionsCalled = false; + let remoteCallCount = 0; + const afcToolsMap = await this.initAfcToolsMap(params); + return (function (models, afcTools, params) { + return __asyncGenerator(this, arguments, function* () { + var _a, e_1, _b, _c; + var _d, _e; + while (remoteCallCount < maxRemoteCalls) { + if (wereFunctionsCalled) { + remoteCallCount++; + wereFunctionsCalled = false; + } + const transformedParams = yield __await(models.processParamsMaybeAddMcpUsage(params)); + const response = yield __await(models.generateContentStreamInternal(transformedParams)); + const functionResponses = []; + const responseContents = []; + try { + for (var _f = true, response_1 = (e_1 = void 0, __asyncValues(response)), response_1_1; response_1_1 = yield __await(response_1.next()), _a = response_1_1.done, !_a; _f = true) { + _c = response_1_1.value; + _f = false; + const chunk = _c; + yield yield __await(chunk); + if (chunk.candidates && ((_d = chunk.candidates[0]) === null || _d === void 0 ? void 0 : _d.content)) { + responseContents.push(chunk.candidates[0].content); + for (const part of (_e = chunk.candidates[0].content.parts) !== null && _e !== void 0 ? _e : []) { + if (remoteCallCount < maxRemoteCalls && part.functionCall) { + if (!part.functionCall.name) { + throw new Error('Function call name was not returned by the model.'); + } + if (!afcTools.has(part.functionCall.name)) { + throw new Error(`Automatic function calling was requested, but not all the tools the model used implement the CallableTool interface. Available tools: ${afcTools.keys()}, mising tool: ${part.functionCall.name}`); + } + else { + const responseParts = yield __await(afcTools + .get(part.functionCall.name) + .callTool([part.functionCall])); + functionResponses.push(...responseParts); + } + } + } + } + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (!_f && !_a && (_b = response_1.return)) yield __await(_b.call(response_1)); + } + finally { if (e_1) throw e_1.error; } + } + if (functionResponses.length > 0) { + wereFunctionsCalled = true; + const typedResponseChunk = new GenerateContentResponse(); + typedResponseChunk.candidates = [ + { + content: { + role: 'user', + parts: functionResponses, + }, + }, + ]; + yield yield __await(typedResponseChunk); + const newContents = []; + newContents.push(...responseContents); + newContents.push({ + role: 'user', + parts: functionResponses, + }); + const updatedContents = tContents(params.contents).concat(newContents); + params.contents = updatedContents; + } + else { + break; + } + } + }); + })(this, afcToolsMap, params); + } + async generateContentInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = generateContentParametersToVertex(this.apiClient, params); + path = formatMap('{model}:generateContent', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = generateContentResponseFromVertex(apiResponse); + const typedResp = new GenerateContentResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = generateContentParametersToMldev(this.apiClient, params); + path = formatMap('{model}:generateContent', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = generateContentResponseFromMldev(apiResponse); + const typedResp = new GenerateContentResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + async generateContentStreamInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = generateContentParametersToVertex(this.apiClient, params); + path = formatMap('{model}:streamGenerateContent?alt=sse', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + const apiClient = this.apiClient; + response = apiClient.requestStream({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }); + return response.then(function (apiResponse) { + return __asyncGenerator(this, arguments, function* () { + var _a, e_2, _b, _c; + try { + for (var _d = true, apiResponse_1 = __asyncValues(apiResponse), apiResponse_1_1; apiResponse_1_1 = yield __await(apiResponse_1.next()), _a = apiResponse_1_1.done, !_a; _d = true) { + _c = apiResponse_1_1.value; + _d = false; + const chunk = _c; + const resp = generateContentResponseFromVertex((yield __await(chunk.json())), params); + resp['sdkHttpResponse'] = { + headers: chunk.headers, + }; + const typedResp = new GenerateContentResponse(); + Object.assign(typedResp, resp); + yield yield __await(typedResp); + } + } + catch (e_2_1) { e_2 = { error: e_2_1 }; } + finally { + try { + if (!_d && !_a && (_b = apiResponse_1.return)) yield __await(_b.call(apiResponse_1)); + } + finally { if (e_2) throw e_2.error; } + } + }); + }); + } + else { + const body = generateContentParametersToMldev(this.apiClient, params); + path = formatMap('{model}:streamGenerateContent?alt=sse', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + const apiClient = this.apiClient; + response = apiClient.requestStream({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }); + return response.then(function (apiResponse) { + return __asyncGenerator(this, arguments, function* () { + var _a, e_3, _b, _c; + try { + for (var _d = true, apiResponse_2 = __asyncValues(apiResponse), apiResponse_2_1; apiResponse_2_1 = yield __await(apiResponse_2.next()), _a = apiResponse_2_1.done, !_a; _d = true) { + _c = apiResponse_2_1.value; + _d = false; + const chunk = _c; + const resp = generateContentResponseFromMldev((yield __await(chunk.json())), params); + resp['sdkHttpResponse'] = { + headers: chunk.headers, + }; + const typedResp = new GenerateContentResponse(); + Object.assign(typedResp, resp); + yield yield __await(typedResp); + } + } + catch (e_3_1) { e_3 = { error: e_3_1 }; } + finally { + try { + if (!_d && !_a && (_b = apiResponse_2.return)) yield __await(_b.call(apiResponse_2)); + } + finally { if (e_3) throw e_3.error; } + } + }); + }); + } + } + /** + * Calculates embeddings for the given contents. Only text is supported. + * + * @param params - The parameters for embedding contents. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.embedContent({ + * model: 'text-embedding-004', + * contents: [ + * 'What is your name?', + * 'What is your favorite color?', + * ], + * config: { + * outputDimensionality: 64, + * }, + * }); + * console.log(response); + * ``` + */ + async embedContent(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = embedContentParametersToVertex(this.apiClient, params); + path = formatMap('{model}:predict', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = embedContentResponseFromVertex(apiResponse); + const typedResp = new EmbedContentResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = embedContentParametersToMldev(this.apiClient, params); + path = formatMap('{model}:batchEmbedContents', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = embedContentResponseFromMldev(apiResponse); + const typedResp = new EmbedContentResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Private method for generating images. + */ + async generateImagesInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = generateImagesParametersToVertex(this.apiClient, params); + path = formatMap('{model}:predict', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = generateImagesResponseFromVertex(apiResponse); + const typedResp = new GenerateImagesResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = generateImagesParametersToMldev(this.apiClient, params); + path = formatMap('{model}:predict', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = generateImagesResponseFromMldev(apiResponse); + const typedResp = new GenerateImagesResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Private method for editing an image. + */ + async editImageInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = editImageParametersInternalToVertex(this.apiClient, params); + path = formatMap('{model}:predict', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = editImageResponseFromVertex(apiResponse); + const typedResp = new EditImageResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + throw new Error('This method is only supported by the Vertex AI.'); + } + } + /** + * Private method for upscaling an image. + */ + async upscaleImageInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = upscaleImageAPIParametersInternalToVertex(this.apiClient, params); + path = formatMap('{model}:predict', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = upscaleImageResponseFromVertex(apiResponse); + const typedResp = new UpscaleImageResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + throw new Error('This method is only supported by the Vertex AI.'); + } + } + /** + * Recontextualizes an image. + * + * There are two types of recontextualization currently supported: + * 1) Imagen Product Recontext - Generate images of products in new scenes + * and contexts. + * 2) Virtual Try-On: Generate images of persons modeling fashion products. + * + * @param params - The parameters for recontextualizing an image. + * @return The response from the API. + * + * @example + * ```ts + * const response1 = await ai.models.recontextImage({ + * model: 'imagen-product-recontext-preview-06-30', + * source: { + * prompt: 'In a modern kitchen setting.', + * productImages: [productImage], + * }, + * config: { + * numberOfImages: 1, + * }, + * }); + * console.log(response1?.generatedImages?.[0]?.image?.imageBytes); + * + * const response2 = await ai.models.recontextImage({ + * model: 'virtual-try-on-001', + * source: { + * personImage: personImage, + * productImages: [productImage], + * }, + * config: { + * numberOfImages: 1, + * }, + * }); + * console.log(response2?.generatedImages?.[0]?.image?.imageBytes); + * ``` + */ + async recontextImage(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = recontextImageParametersToVertex(this.apiClient, params); + path = formatMap('{model}:predict', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = recontextImageResponseFromVertex(apiResponse); + const typedResp = new RecontextImageResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + throw new Error('This method is only supported by the Vertex AI.'); + } + } + /** + * Segments an image, creating a mask of a specified area. + * + * @param params - The parameters for segmenting an image. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.segmentImage({ + * model: 'image-segmentation-001', + * source: { + * image: image, + * }, + * config: { + * mode: 'foreground', + * }, + * }); + * console.log(response?.generatedMasks?.[0]?.mask?.imageBytes); + * ``` + */ + async segmentImage(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = segmentImageParametersToVertex(this.apiClient, params); + path = formatMap('{model}:predict', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = segmentImageResponseFromVertex(apiResponse); + const typedResp = new SegmentImageResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + throw new Error('This method is only supported by the Vertex AI.'); + } + } + /** + * Fetches information about a model by name. + * + * @example + * ```ts + * const modelInfo = await ai.models.get({model: 'gemini-2.0-flash'}); + * ``` + */ + async get(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = getModelParametersToVertex(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = modelFromVertex(apiResponse); + return resp; + }); + } + else { + const body = getModelParametersToMldev(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = modelFromMldev(apiResponse); + return resp; + }); + } + } + async listInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = listModelsParametersToVertex(this.apiClient, params); + path = formatMap('{models_url}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listModelsResponseFromVertex(apiResponse); + const typedResp = new ListModelsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = listModelsParametersToMldev(this.apiClient, params); + path = formatMap('{models_url}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listModelsResponseFromMldev(apiResponse); + const typedResp = new ListModelsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Updates a tuned model by its name. + * + * @param params - The parameters for updating the model. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.update({ + * model: 'tuned-model-name', + * config: { + * displayName: 'New display name', + * description: 'New description', + * }, + * }); + * ``` + */ + async update(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = updateModelParametersToVertex(this.apiClient, params); + path = formatMap('{model}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'PATCH', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = modelFromVertex(apiResponse); + return resp; + }); + } + else { + const body = updateModelParametersToMldev(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'PATCH', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = modelFromMldev(apiResponse); + return resp; + }); + } + } + /** + * Deletes a tuned model by its name. + * + * @param params - The parameters for deleting the model. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.delete({model: 'tuned-model-name'}); + * ``` + */ + async delete(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = deleteModelParametersToVertex(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = deleteModelResponseFromVertex(apiResponse); + const typedResp = new DeleteModelResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = deleteModelParametersToMldev(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = deleteModelResponseFromMldev(apiResponse); + const typedResp = new DeleteModelResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Counts the number of tokens in the given contents. Multimodal input is + * supported for Gemini models. + * + * @param params - The parameters for counting tokens. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.countTokens({ + * model: 'gemini-2.0-flash', + * contents: 'The quick brown fox jumps over the lazy dog.' + * }); + * console.log(response); + * ``` + */ + async countTokens(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = countTokensParametersToVertex(this.apiClient, params); + path = formatMap('{model}:countTokens', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = countTokensResponseFromVertex(apiResponse); + const typedResp = new CountTokensResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = countTokensParametersToMldev(this.apiClient, params); + path = formatMap('{model}:countTokens', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = countTokensResponseFromMldev(apiResponse); + const typedResp = new CountTokensResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Given a list of contents, returns a corresponding TokensInfo containing + * the list of tokens and list of token ids. + * + * This method is not supported by the Gemini Developer API. + * + * @param params - The parameters for computing tokens. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.computeTokens({ + * model: 'gemini-2.0-flash', + * contents: 'What is your name?' + * }); + * console.log(response); + * ``` + */ + async computeTokens(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = computeTokensParametersToVertex(this.apiClient, params); + path = formatMap('{model}:computeTokens', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = computeTokensResponseFromVertex(apiResponse); + const typedResp = new ComputeTokensResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + throw new Error('This method is only supported by the Vertex AI.'); + } + } + /** + * Private method for generating videos. + */ + async generateVideosInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = generateVideosParametersToVertex(this.apiClient, params); + path = formatMap('{model}:predictLongRunning', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = generateVideosOperationFromVertex(apiResponse); + const typedResp = new GenerateVideosOperation(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = generateVideosParametersToMldev(this.apiClient, params); + path = formatMap('{model}:predictLongRunning', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = generateVideosOperationFromMldev(apiResponse); + const typedResp = new GenerateVideosOperation(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Operations extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + } + /** + * Gets the status of a long-running operation. + * + * @param parameters The parameters for the get operation request. + * @return The updated Operation object, with the latest status or result. + */ + async getVideosOperation(parameters) { + const operation = parameters.operation; + const config = parameters.config; + if (operation.name === undefined || operation.name === '') { + throw new Error('Operation name is required.'); + } + if (this.apiClient.isVertexAI()) { + const resourceName = operation.name.split('/operations/')[0]; + let httpOptions = undefined; + if (config && 'httpOptions' in config) { + httpOptions = config.httpOptions; + } + const rawOperation = await this.fetchPredictVideosOperationInternal({ + operationName: operation.name, + resourceName: resourceName, + config: { httpOptions: httpOptions }, + }); + return operation._fromAPIResponse({ + apiResponse: rawOperation, + _isVertexAI: true, + }); + } + else { + const rawOperation = await this.getVideosOperationInternal({ + operationName: operation.name, + config: config, + }); + return operation._fromAPIResponse({ + apiResponse: rawOperation, + _isVertexAI: false, + }); + } + } + /** + * Gets the status of a long-running operation. + * + * @param parameters The parameters for the get operation request. + * @return The updated Operation object, with the latest status or result. + */ + async get(parameters) { + const operation = parameters.operation; + const config = parameters.config; + if (operation.name === undefined || operation.name === '') { + throw new Error('Operation name is required.'); + } + if (this.apiClient.isVertexAI()) { + const resourceName = operation.name.split('/operations/')[0]; + let httpOptions = undefined; + if (config && 'httpOptions' in config) { + httpOptions = config.httpOptions; + } + const rawOperation = await this.fetchPredictVideosOperationInternal({ + operationName: operation.name, + resourceName: resourceName, + config: { httpOptions: httpOptions }, + }); + return operation._fromAPIResponse({ + apiResponse: rawOperation, + _isVertexAI: true, + }); + } + else { + const rawOperation = await this.getVideosOperationInternal({ + operationName: operation.name, + config: config, + }); + return operation._fromAPIResponse({ + apiResponse: rawOperation, + _isVertexAI: false, + }); + } + } + async getVideosOperationInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = getOperationParametersToVertex(params); + path = formatMap('{operationName}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response; + } + else { + const body = getOperationParametersToMldev(params); + path = formatMap('{operationName}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response; + } + } + async fetchPredictVideosOperationInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = fetchPredictOperationParametersToVertex(params); + path = formatMap('{resourceName}:fetchPredictOperation', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response; + } + else { + throw new Error('This method is only supported by the Vertex AI.'); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function blobToMldev(fromObject) { + const toObject = {}; + const fromData = getValueByPath(fromObject, ['data']); + if (fromData != null) { + setValueByPath(toObject, ['data'], fromData); + } + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function contentToMldev(fromObject) { + const toObject = {}; + const fromParts = getValueByPath(fromObject, ['parts']); + if (fromParts != null) { + let transformedList = fromParts; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return partToMldev(item); + }); + } + setValueByPath(toObject, ['parts'], transformedList); + } + const fromRole = getValueByPath(fromObject, ['role']); + if (fromRole != null) { + setValueByPath(toObject, ['role'], fromRole); + } + return toObject; +} +function createAuthTokenConfigToMldev(apiClient, fromObject, parentObject) { + const toObject = {}; + const fromExpireTime = getValueByPath(fromObject, ['expireTime']); + if (parentObject !== undefined && fromExpireTime != null) { + setValueByPath(parentObject, ['expireTime'], fromExpireTime); + } + const fromNewSessionExpireTime = getValueByPath(fromObject, [ + 'newSessionExpireTime', + ]); + if (parentObject !== undefined && fromNewSessionExpireTime != null) { + setValueByPath(parentObject, ['newSessionExpireTime'], fromNewSessionExpireTime); + } + const fromUses = getValueByPath(fromObject, ['uses']); + if (parentObject !== undefined && fromUses != null) { + setValueByPath(parentObject, ['uses'], fromUses); + } + const fromLiveConnectConstraints = getValueByPath(fromObject, [ + 'liveConnectConstraints', + ]); + if (parentObject !== undefined && fromLiveConnectConstraints != null) { + setValueByPath(parentObject, ['bidiGenerateContentSetup'], liveConnectConstraintsToMldev(apiClient, fromLiveConnectConstraints)); + } + const fromLockAdditionalFields = getValueByPath(fromObject, [ + 'lockAdditionalFields', + ]); + if (parentObject !== undefined && fromLockAdditionalFields != null) { + setValueByPath(parentObject, ['fieldMask'], fromLockAdditionalFields); + } + return toObject; +} +function createAuthTokenParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['config'], createAuthTokenConfigToMldev(apiClient, fromConfig, toObject)); + } + return toObject; +} +function fileDataToMldev(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromFileUri = getValueByPath(fromObject, ['fileUri']); + if (fromFileUri != null) { + setValueByPath(toObject, ['fileUri'], fromFileUri); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function functionCallToMldev(fromObject) { + const toObject = {}; + const fromId = getValueByPath(fromObject, ['id']); + if (fromId != null) { + setValueByPath(toObject, ['id'], fromId); + } + const fromArgs = getValueByPath(fromObject, ['args']); + if (fromArgs != null) { + setValueByPath(toObject, ['args'], fromArgs); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + if (getValueByPath(fromObject, ['partialArgs']) !== undefined) { + throw new Error('partialArgs parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['willContinue']) !== undefined) { + throw new Error('willContinue parameter is not supported in Gemini API.'); + } + return toObject; +} +function googleMapsToMldev(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['authConfig']) !== undefined) { + throw new Error('authConfig parameter is not supported in Gemini API.'); + } + const fromEnableWidget = getValueByPath(fromObject, ['enableWidget']); + if (fromEnableWidget != null) { + setValueByPath(toObject, ['enableWidget'], fromEnableWidget); + } + return toObject; +} +function googleSearchToMldev(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['excludeDomains']) !== undefined) { + throw new Error('excludeDomains parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['blockingConfidence']) !== undefined) { + throw new Error('blockingConfidence parameter is not supported in Gemini API.'); + } + const fromTimeRangeFilter = getValueByPath(fromObject, [ + 'timeRangeFilter', + ]); + if (fromTimeRangeFilter != null) { + setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter); + } + return toObject; +} +function liveConnectConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromGenerationConfig = getValueByPath(fromObject, [ + 'generationConfig', + ]); + if (parentObject !== undefined && fromGenerationConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig'], fromGenerationConfig); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (parentObject !== undefined && fromResponseModalities != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'responseModalities'], fromResponseModalities); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (parentObject !== undefined && fromTemperature != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'temperature'], fromTemperature); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (parentObject !== undefined && fromTopP != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'topP'], fromTopP); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (parentObject !== undefined && fromTopK != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'topK'], fromTopK); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (parentObject !== undefined && fromMaxOutputTokens != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'maxOutputTokens'], fromMaxOutputTokens); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (parentObject !== undefined && fromMediaResolution != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'mediaResolution'], fromMediaResolution); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (parentObject !== undefined && fromSeed != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'seed'], fromSeed); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (parentObject !== undefined && fromSpeechConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'speechConfig'], tLiveSpeechConfig(fromSpeechConfig)); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (parentObject !== undefined && fromThinkingConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'thinkingConfig'], fromThinkingConfig); + } + const fromEnableAffectiveDialog = getValueByPath(fromObject, [ + 'enableAffectiveDialog', + ]); + if (parentObject !== undefined && fromEnableAffectiveDialog != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'enableAffectiveDialog'], fromEnableAffectiveDialog); + } + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['setup', 'systemInstruction'], contentToMldev(tContent(fromSystemInstruction))); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = tTools(fromTools); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToMldev(tTool(item)); + }); + } + setValueByPath(parentObject, ['setup', 'tools'], transformedList); + } + const fromSessionResumption = getValueByPath(fromObject, [ + 'sessionResumption', + ]); + if (parentObject !== undefined && fromSessionResumption != null) { + setValueByPath(parentObject, ['setup', 'sessionResumption'], sessionResumptionConfigToMldev(fromSessionResumption)); + } + const fromInputAudioTranscription = getValueByPath(fromObject, [ + 'inputAudioTranscription', + ]); + if (parentObject !== undefined && fromInputAudioTranscription != null) { + setValueByPath(parentObject, ['setup', 'inputAudioTranscription'], fromInputAudioTranscription); + } + const fromOutputAudioTranscription = getValueByPath(fromObject, [ + 'outputAudioTranscription', + ]); + if (parentObject !== undefined && fromOutputAudioTranscription != null) { + setValueByPath(parentObject, ['setup', 'outputAudioTranscription'], fromOutputAudioTranscription); + } + const fromRealtimeInputConfig = getValueByPath(fromObject, [ + 'realtimeInputConfig', + ]); + if (parentObject !== undefined && fromRealtimeInputConfig != null) { + setValueByPath(parentObject, ['setup', 'realtimeInputConfig'], fromRealtimeInputConfig); + } + const fromContextWindowCompression = getValueByPath(fromObject, [ + 'contextWindowCompression', + ]); + if (parentObject !== undefined && fromContextWindowCompression != null) { + setValueByPath(parentObject, ['setup', 'contextWindowCompression'], fromContextWindowCompression); + } + const fromProactivity = getValueByPath(fromObject, ['proactivity']); + if (parentObject !== undefined && fromProactivity != null) { + setValueByPath(parentObject, ['setup', 'proactivity'], fromProactivity); + } + if (getValueByPath(fromObject, ['explicitVadSignal']) !== undefined) { + throw new Error('explicitVadSignal parameter is not supported in Gemini API.'); + } + return toObject; +} +function liveConnectConstraintsToMldev(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['setup', 'model'], tModel(apiClient, fromModel)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['config'], liveConnectConfigToMldev(fromConfig, toObject)); + } + return toObject; +} +function partToMldev(fromObject) { + const toObject = {}; + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromCodeExecutionResult = getValueByPath(fromObject, [ + 'codeExecutionResult', + ]); + if (fromCodeExecutionResult != null) { + setValueByPath(toObject, ['codeExecutionResult'], fromCodeExecutionResult); + } + const fromExecutableCode = getValueByPath(fromObject, [ + 'executableCode', + ]); + if (fromExecutableCode != null) { + setValueByPath(toObject, ['executableCode'], fromExecutableCode); + } + const fromFileData = getValueByPath(fromObject, ['fileData']); + if (fromFileData != null) { + setValueByPath(toObject, ['fileData'], fileDataToMldev(fromFileData)); + } + const fromFunctionCall = getValueByPath(fromObject, ['functionCall']); + if (fromFunctionCall != null) { + setValueByPath(toObject, ['functionCall'], functionCallToMldev(fromFunctionCall)); + } + const fromFunctionResponse = getValueByPath(fromObject, [ + 'functionResponse', + ]); + if (fromFunctionResponse != null) { + setValueByPath(toObject, ['functionResponse'], fromFunctionResponse); + } + const fromInlineData = getValueByPath(fromObject, ['inlineData']); + if (fromInlineData != null) { + setValueByPath(toObject, ['inlineData'], blobToMldev(fromInlineData)); + } + const fromText = getValueByPath(fromObject, ['text']); + if (fromText != null) { + setValueByPath(toObject, ['text'], fromText); + } + const fromThought = getValueByPath(fromObject, ['thought']); + if (fromThought != null) { + setValueByPath(toObject, ['thought'], fromThought); + } + const fromThoughtSignature = getValueByPath(fromObject, [ + 'thoughtSignature', + ]); + if (fromThoughtSignature != null) { + setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature); + } + const fromVideoMetadata = getValueByPath(fromObject, [ + 'videoMetadata', + ]); + if (fromVideoMetadata != null) { + setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata); + } + return toObject; +} +function sessionResumptionConfigToMldev(fromObject) { + const toObject = {}; + const fromHandle = getValueByPath(fromObject, ['handle']); + if (fromHandle != null) { + setValueByPath(toObject, ['handle'], fromHandle); + } + if (getValueByPath(fromObject, ['transparent']) !== undefined) { + throw new Error('transparent parameter is not supported in Gemini API.'); + } + return toObject; +} +function toolToMldev(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['retrieval']) !== undefined) { + throw new Error('retrieval parameter is not supported in Gemini API.'); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + const fromFileSearch = getValueByPath(fromObject, ['fileSearch']); + if (fromFileSearch != null) { + setValueByPath(toObject, ['fileSearch'], fromFileSearch); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + if (getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined) { + throw new Error('enterpriseWebSearch parameter is not supported in Gemini API.'); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], googleMapsToMldev(fromGoogleMaps)); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], googleSearchToMldev(fromGoogleSearch)); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Returns a comma-separated list of field masks from a given object. + * + * @param setup The object to extract field masks from. + * @return A comma-separated list of field masks. + */ +function getFieldMasks(setup) { + const fields = []; + for (const key in setup) { + if (Object.prototype.hasOwnProperty.call(setup, key)) { + const value = setup[key]; + // 2nd layer, recursively get field masks see TODO(b/418290100) + if (typeof value === 'object' && + value != null && + Object.keys(value).length > 0) { + const field = Object.keys(value).map((kk) => `${key}.${kk}`); + fields.push(...field); + } + else { + fields.push(key); // 1st layer + } + } + } + return fields.join(','); +} +/** + * Converts bidiGenerateContentSetup. + * @param requestDict - The request dictionary. + * @param config - The configuration object. + * @return - The modified request dictionary. + */ +function convertBidiSetupToTokenSetup(requestDict, config) { + // Convert bidiGenerateContentSetup from bidiGenerateContentSetup.setup. + let setupForMaskGeneration = null; + const bidiGenerateContentSetupValue = requestDict['bidiGenerateContentSetup']; + if (typeof bidiGenerateContentSetupValue === 'object' && + bidiGenerateContentSetupValue !== null && + 'setup' in bidiGenerateContentSetupValue) { + // Now we know bidiGenerateContentSetupValue is an object and has a 'setup' + // property. + const innerSetup = bidiGenerateContentSetupValue + .setup; + if (typeof innerSetup === 'object' && innerSetup !== null) { + // Valid inner setup found. + requestDict['bidiGenerateContentSetup'] = innerSetup; + setupForMaskGeneration = innerSetup; + } + else { + // `bidiGenerateContentSetupValue.setup` is not a valid object; treat as + // if bidiGenerateContentSetup is invalid. + delete requestDict['bidiGenerateContentSetup']; + } + } + else if (bidiGenerateContentSetupValue !== undefined) { + // `bidiGenerateContentSetup` exists but not in the expected + // shape {setup: {...}}; treat as invalid. + delete requestDict['bidiGenerateContentSetup']; + } + const preExistingFieldMask = requestDict['fieldMask']; + // Handle mask generation setup. + if (setupForMaskGeneration) { + const generatedMaskFromBidi = getFieldMasks(setupForMaskGeneration); + if (Array.isArray(config === null || config === void 0 ? void 0 : config.lockAdditionalFields) && + (config === null || config === void 0 ? void 0 : config.lockAdditionalFields.length) === 0) { + // Case 1: lockAdditionalFields is an empty array. Lock only fields from + // bidi setup. + if (generatedMaskFromBidi) { + // Only assign if mask is not empty + requestDict['fieldMask'] = generatedMaskFromBidi; + } + else { + delete requestDict['fieldMask']; // If mask is empty, effectively no + // specific fields locked by bidi + } + } + else if ((config === null || config === void 0 ? void 0 : config.lockAdditionalFields) && + config.lockAdditionalFields.length > 0 && + preExistingFieldMask !== null && + Array.isArray(preExistingFieldMask) && + preExistingFieldMask.length > 0) { + // Case 2: Lock fields from bidi setup + additional fields + // (preExistingFieldMask). + const generationConfigFields = [ + 'temperature', + 'topK', + 'topP', + 'maxOutputTokens', + 'responseModalities', + 'seed', + 'speechConfig', + ]; + let mappedFieldsFromPreExisting = []; + if (preExistingFieldMask.length > 0) { + mappedFieldsFromPreExisting = preExistingFieldMask.map((field) => { + if (generationConfigFields.includes(field)) { + return `generationConfig.${field}`; + } + return field; // Keep original field name if not in + // generationConfigFields + }); + } + const finalMaskParts = []; + if (generatedMaskFromBidi) { + finalMaskParts.push(generatedMaskFromBidi); + } + if (mappedFieldsFromPreExisting.length > 0) { + finalMaskParts.push(...mappedFieldsFromPreExisting); + } + if (finalMaskParts.length > 0) { + requestDict['fieldMask'] = finalMaskParts.join(','); + } + else { + // If no fields from bidi and no valid additional fields from + // pre-existing mask. + delete requestDict['fieldMask']; + } + } + else { + // Case 3: "Lock all fields" (meaning, don't send a field_mask, let server + // defaults apply or all are mutable). This is hit if: + // - `config.lockAdditionalFields` is undefined. + // - `config.lockAdditionalFields` is non-empty, BUT + // `preExistingFieldMask` is null, not a string, or an empty string. + delete requestDict['fieldMask']; + } + } + else { + // No valid `bidiGenerateContentSetup` was found or extracted. + // "Lock additional null fields if any". + if (preExistingFieldMask !== null && + Array.isArray(preExistingFieldMask) && + preExistingFieldMask.length > 0) { + // If there's a pre-existing field mask, it's a string, and it's not + // empty, then we should lock all fields. + requestDict['fieldMask'] = preExistingFieldMask.join(','); + } + else { + delete requestDict['fieldMask']; + } + } + return requestDict; +} +class Tokens extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + } + /** + * Creates an ephemeral auth token resource. + * + * @experimental + * + * @remarks + * Ephemeral auth tokens is only supported in the Gemini Developer API. + * It can be used for the session connection to the Live constrained API. + * Support in v1alpha only. + * + * @param params - The parameters for the create request. + * @return The created auth token. + * + * @example + * ```ts + * const ai = new GoogleGenAI({ + * apiKey: token.name, + * httpOptions: { apiVersion: 'v1alpha' } // Support in v1alpha only. + * }); + * + * // Case 1: If LiveEphemeralParameters is unset, unlock LiveConnectConfig + * // when using the token in Live API sessions. Each session connection can + * // use a different configuration. + * const config: CreateAuthTokenConfig = { + * uses: 3, + * expireTime: '2025-05-01T00:00:00Z', + * } + * const token = await ai.tokens.create(config); + * + * // Case 2: If LiveEphemeralParameters is set, lock all fields in + * // LiveConnectConfig when using the token in Live API sessions. For + * // example, changing `outputAudioTranscription` in the Live API + * // connection will be ignored by the API. + * const config: CreateAuthTokenConfig = + * uses: 3, + * expireTime: '2025-05-01T00:00:00Z', + * LiveEphemeralParameters: { + * model: 'gemini-2.0-flash-001', + * config: { + * 'responseModalities': ['AUDIO'], + * 'systemInstruction': 'Always answer in English.', + * } + * } + * } + * const token = await ai.tokens.create(config); + * + * // Case 3: If LiveEphemeralParameters is set and lockAdditionalFields is + * // set, lock LiveConnectConfig with set and additional fields (e.g. + * // responseModalities, systemInstruction, temperature in this example) when + * // using the token in Live API sessions. + * const config: CreateAuthTokenConfig = + * uses: 3, + * expireTime: '2025-05-01T00:00:00Z', + * LiveEphemeralParameters: { + * model: 'gemini-2.0-flash-001', + * config: { + * 'responseModalities': ['AUDIO'], + * 'systemInstruction': 'Always answer in English.', + * } + * }, + * lockAdditionalFields: ['temperature'], + * } + * const token = await ai.tokens.create(config); + * + * // Case 4: If LiveEphemeralParameters is set and lockAdditionalFields is + * // empty array, lock LiveConnectConfig with set fields (e.g. + * // responseModalities, systemInstruction in this example) when using the + * // token in Live API sessions. + * const config: CreateAuthTokenConfig = + * uses: 3, + * expireTime: '2025-05-01T00:00:00Z', + * LiveEphemeralParameters: { + * model: 'gemini-2.0-flash-001', + * config: { + * 'responseModalities': ['AUDIO'], + * 'systemInstruction': 'Always answer in English.', + * } + * }, + * lockAdditionalFields: [], + * } + * const token = await ai.tokens.create(config); + * ``` + */ + async create(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('The client.tokens.create method is only supported by the Gemini Developer API.'); + } + else { + const body = createAuthTokenParametersToMldev(this.apiClient, params); + path = formatMap('auth_tokens', body['_url']); + queryParams = body['_query']; + delete body['config']; + delete body['_url']; + delete body['_query']; + const transformedBody = convertBidiSetupToTokenSetup(body, params.config); + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(transformedBody), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Code generated by the Google Gen AI SDK generator DO NOT EDIT. +function deleteDocumentConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromForce = getValueByPath(fromObject, ['force']); + if (parentObject !== undefined && fromForce != null) { + setValueByPath(parentObject, ['_query', 'force'], fromForce); + } + return toObject; +} +function deleteDocumentParametersToMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + deleteDocumentConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function getDocumentParametersToMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + return toObject; +} +function listDocumentsConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + return toObject; +} +function listDocumentsParametersToMldev(fromObject) { + const toObject = {}; + const fromParent = getValueByPath(fromObject, ['parent']); + if (fromParent != null) { + setValueByPath(toObject, ['_url', 'parent'], fromParent); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listDocumentsConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function listDocumentsResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromDocuments = getValueByPath(fromObject, ['documents']); + if (fromDocuments != null) { + let transformedList = fromDocuments; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['documents'], transformedList); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Documents extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + /** + * Lists documents. + * + * @param params - The parameters for the list request. + * @return - A pager of documents. + * + * @example + * ```ts + * const documents = await ai.documents.list({parent:'rag_store_name', config: {'pageSize': 2}}); + * for await (const document of documents) { + * console.log(document); + * } + * ``` + */ + this.list = async (params) => { + return new Pager(exports.PagedItem.PAGED_ITEM_DOCUMENTS, (x) => this.listInternal({ parent: params.parent, config: x.config }), await this.listInternal(params), params); + }; + } + /** + * Gets a Document. + * + * @param params - The parameters for getting a document. + * @return Document. + */ + async get(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = getDocumentParametersToMldev(params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } + /** + * Deletes a Document. + * + * @param params - The parameters for deleting a document. + */ + async delete(params) { + var _a, _b; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = deleteDocumentParametersToMldev(params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + await this.apiClient.request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }); + } + } + async listInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = listDocumentsParametersToMldev(params); + path = formatMap('{parent}/documents', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = listDocumentsResponseFromMldev(apiResponse); + const typedResp = new ListDocumentsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class FileSearchStores extends BaseModule { + constructor(apiClient, documents = new Documents(apiClient)) { + super(); + this.apiClient = apiClient; + this.documents = documents; + /** + * Lists file search stores. + * + * @param params - The parameters for the list request. + * @return - A pager of file search stores. + * + * @example + * ```ts + * const fileSearchStores = await ai.fileSearchStores.list({config: {'pageSize': 2}}); + * for await (const fileSearchStore of fileSearchStores) { + * console.log(fileSearchStore); + * } + * ``` + */ + this.list = async (params = {}) => { + return new Pager(exports.PagedItem.PAGED_ITEM_FILE_SEARCH_STORES, (x) => this.listInternal(x), await this.listInternal(params), params); + }; + } + /** + * Uploads a file asynchronously to a given File Search Store. + * This method is not available in Vertex AI. + * Supported upload sources: + * - Node.js: File path (string) or Blob object. + * - Browser: Blob object (e.g., File). + * + * @remarks + * The `mimeType` can be specified in the `config` parameter. If omitted: + * - For file path (string) inputs, the `mimeType` will be inferred from the + * file extension. + * - For Blob object inputs, the `mimeType` will be set to the Blob's `type` + * property. + * + * This section can contain multiple paragraphs and code examples. + * + * @param params - Optional parameters specified in the + * `types.UploadToFileSearchStoreParameters` interface. + * @see {@link types.UploadToFileSearchStoreParameters#config} for the optional + * config in the parameters. + * @return A promise that resolves to a long running operation. + * @throws An error if called on a Vertex AI client. + * @throws An error if the `mimeType` is not provided and can not be inferred, + * the `mimeType` can be provided in the `params.config` parameter. + * @throws An error occurs if a suitable upload location cannot be established. + * + * @example + * The following code uploads a file to a given file search store. + * + * ```ts + * const operation = await ai.fileSearchStores.upload({fileSearchStoreName: 'fileSearchStores/foo-bar', file: 'file.txt', config: { + * mimeType: 'text/plain', + * }}); + * console.log(operation.name); + * ``` + */ + async uploadToFileSearchStore(params) { + if (this.apiClient.isVertexAI()) { + throw new Error('Vertex AI does not support uploading files to a file search store.'); + } + return this.apiClient.uploadFileToFileSearchStore(params.fileSearchStoreName, params.file, params.config); + } + /** + * Creates a File Search Store. + * + * @param params - The parameters for creating a File Search Store. + * @return FileSearchStore. + */ + async create(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = createFileSearchStoreParametersToMldev(params); + path = formatMap('fileSearchStores', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } + /** + * Gets a File Search Store. + * + * @param params - The parameters for getting a File Search Store. + * @return FileSearchStore. + */ + async get(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = getFileSearchStoreParametersToMldev(params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } + /** + * Deletes a File Search Store. + * + * @param params - The parameters for deleting a File Search Store. + */ + async delete(params) { + var _a, _b; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = deleteFileSearchStoreParametersToMldev(params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + await this.apiClient.request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }); + } + } + async listInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = listFileSearchStoresParametersToMldev(params); + path = formatMap('fileSearchStores', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = listFileSearchStoresResponseFromMldev(apiResponse); + const typedResp = new ListFileSearchStoresResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + async uploadToFileSearchStoreInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = uploadToFileSearchStoreParametersToMldev(params); + path = formatMap('upload/v1beta/{file_search_store_name}:uploadToFileSearchStore', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = uploadToFileSearchStoreResumableResponseFromMldev(apiResponse); + const typedResp = new UploadToFileSearchStoreResumableResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Imports a File from File Service to a FileSearchStore. + * + * This is a long-running operation, see aip.dev/151 + * + * @param params - The parameters for importing a file to a file search store. + * @return ImportFileOperation. + */ + async importFile(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = importFileParametersToMldev(params); + path = formatMap('{file_search_store_name}:importFile', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = importFileOperationFromMldev(apiResponse); + const typedResp = new ImportFileOperation(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +/** + * https://stackoverflow.com/a/2117523 + */ +let uuid4Internal = function () { + const { crypto } = globalThis; + if (crypto === null || crypto === void 0 ? void 0 : crypto.randomUUID) { + uuid4Internal = crypto.randomUUID.bind(crypto); + return crypto.randomUUID(); + } + const u8 = new Uint8Array(1); + const randomByte = crypto ? () => crypto.getRandomValues(u8)[0] : () => (Math.random() * 0xff) & 0xff; + return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, (c) => (+c ^ (randomByte() & (15 >> (+c / 4)))).toString(16)); +}; +const uuid4 = () => uuid4Internal(); + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +function isAbortError(err) { + return (typeof err === 'object' && + err !== null && + // Spec-compliant fetch implementations + (('name' in err && err.name === 'AbortError') || + // Expo fetch + ('message' in err && String(err.message).includes('FetchRequestCanceledException')))); +} +const castToError = (err) => { + if (err instanceof Error) + return err; + if (typeof err === 'object' && err !== null) { + try { + if (Object.prototype.toString.call(err) === '[object Error]') { + // @ts-ignore - not all envs have native support for cause yet + const error = new Error(err.message, err.cause ? { cause: err.cause } : {}); + if (err.stack) + error.stack = err.stack; + // @ts-ignore - not all envs have native support for cause yet + if (err.cause && !error.cause) + error.cause = err.cause; + if (err.name) + error.name = err.name; + return error; + } + } + catch (_a) { } + try { + return new Error(JSON.stringify(err)); + } + catch (_b) { } + } + return new Error(err); +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +class GeminiNextGenAPIClientError extends Error { +} +class APIError extends GeminiNextGenAPIClientError { + constructor(status, error, message, headers) { + super(`${APIError.makeMessage(status, error, message)}`); + this.status = status; + this.headers = headers; + this.error = error; + } + static makeMessage(status, error, message) { + const msg = (error === null || error === void 0 ? void 0 : error.message) ? + typeof error.message === 'string' ? + error.message + : JSON.stringify(error.message) + : error ? JSON.stringify(error) + : message; + if (status && msg) { + return `${status} ${msg}`; + } + if (status) { + return `${status} status code (no body)`; + } + if (msg) { + return msg; + } + return '(no status code or body)'; + } + static generate(status, errorResponse, message, headers) { + if (!status || !headers) { + return new APIConnectionError({ message, cause: castToError(errorResponse) }); + } + const error = errorResponse; + if (status === 400) { + return new BadRequestError(status, error, message, headers); + } + if (status === 401) { + return new AuthenticationError(status, error, message, headers); + } + if (status === 403) { + return new PermissionDeniedError(status, error, message, headers); + } + if (status === 404) { + return new NotFoundError(status, error, message, headers); + } + if (status === 409) { + return new ConflictError(status, error, message, headers); + } + if (status === 422) { + return new UnprocessableEntityError(status, error, message, headers); + } + if (status === 429) { + return new RateLimitError(status, error, message, headers); + } + if (status >= 500) { + return new InternalServerError(status, error, message, headers); + } + return new APIError(status, error, message, headers); + } +} +class APIUserAbortError extends APIError { + constructor({ message } = {}) { + super(undefined, undefined, message || 'Request was aborted.', undefined); + } +} +class APIConnectionError extends APIError { + constructor({ message, cause }) { + super(undefined, undefined, message || 'Connection error.', undefined); + // in some environments the 'cause' property is already declared + // @ts-ignore + if (cause) + this.cause = cause; + } +} +class APIConnectionTimeoutError extends APIConnectionError { + constructor({ message } = {}) { + super({ message: message !== null && message !== void 0 ? message : 'Request timed out.' }); + } +} +class BadRequestError extends APIError { +} +class AuthenticationError extends APIError { +} +class PermissionDeniedError extends APIError { +} +class NotFoundError extends APIError { +} +class ConflictError extends APIError { +} +class UnprocessableEntityError extends APIError { +} +class RateLimitError extends APIError { +} +class InternalServerError extends APIError { +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +// https://url.spec.whatwg.org/#url-scheme-string +const startsWithSchemeRegexp = /^[a-z][a-z0-9+.-]*:/i; +const isAbsoluteURL = (url) => { + return startsWithSchemeRegexp.test(url); +}; +let isArrayInternal = (val) => ((isArrayInternal = Array.isArray), isArrayInternal(val)); +const isArray = isArrayInternal; +let isReadonlyArrayInternal = isArray; +const isReadonlyArray = isReadonlyArrayInternal; +// https://stackoverflow.com/a/34491287 +function isEmptyObj(obj) { + if (!obj) + return true; + for (const _k in obj) + return false; + return true; +} +// https://eslint.org/docs/latest/rules/no-prototype-builtins +function hasOwn(obj, key) { + return Object.prototype.hasOwnProperty.call(obj, key); +} +const validatePositiveInteger = (name, n) => { + if (typeof n !== 'number' || !Number.isInteger(n)) { + throw new GeminiNextGenAPIClientError(`${name} must be an integer`); + } + if (n < 0) { + throw new GeminiNextGenAPIClientError(`${name} must be a positive integer`); + } + return n; +}; +const safeJSON = (text) => { + try { + return JSON.parse(text); + } + catch (err) { + return undefined; + } +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +const sleep$1 = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const VERSION = '0.0.1'; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +/** + * Note this does not detect 'browser'; for that, use getBrowserInfo(). + */ +function getDetectedPlatform() { + if (typeof Deno !== 'undefined' && Deno.build != null) { + return 'deno'; + } + if (typeof EdgeRuntime !== 'undefined') { + return 'edge'; + } + if (Object.prototype.toString.call(typeof globalThis.process !== 'undefined' ? globalThis.process : 0) === '[object process]') { + return 'node'; + } + return 'unknown'; +} +const getPlatformProperties = () => { + var _a, _b, _c, _d, _e; + const detectedPlatform = getDetectedPlatform(); + if (detectedPlatform === 'deno') { + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': VERSION, + 'X-Stainless-OS': normalizePlatform(Deno.build.os), + 'X-Stainless-Arch': normalizeArch(Deno.build.arch), + 'X-Stainless-Runtime': 'deno', + 'X-Stainless-Runtime-Version': typeof Deno.version === 'string' ? Deno.version : (_b = (_a = Deno.version) === null || _a === void 0 ? void 0 : _a.deno) !== null && _b !== void 0 ? _b : 'unknown', + }; + } + if (typeof EdgeRuntime !== 'undefined') { + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': VERSION, + 'X-Stainless-OS': 'Unknown', + 'X-Stainless-Arch': `other:${EdgeRuntime}`, + 'X-Stainless-Runtime': 'edge', + 'X-Stainless-Runtime-Version': globalThis.process.version, + }; + } + // Check if Node.js + if (detectedPlatform === 'node') { + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': VERSION, + 'X-Stainless-OS': normalizePlatform((_c = globalThis.process.platform) !== null && _c !== void 0 ? _c : 'unknown'), + 'X-Stainless-Arch': normalizeArch((_d = globalThis.process.arch) !== null && _d !== void 0 ? _d : 'unknown'), + 'X-Stainless-Runtime': 'node', + 'X-Stainless-Runtime-Version': (_e = globalThis.process.version) !== null && _e !== void 0 ? _e : 'unknown', + }; + } + const browserInfo = getBrowserInfo(); + if (browserInfo) { + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': VERSION, + 'X-Stainless-OS': 'Unknown', + 'X-Stainless-Arch': 'unknown', + 'X-Stainless-Runtime': `browser:${browserInfo.browser}`, + 'X-Stainless-Runtime-Version': browserInfo.version, + }; + } + // TODO add support for Cloudflare workers, etc. + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': VERSION, + 'X-Stainless-OS': 'Unknown', + 'X-Stainless-Arch': 'unknown', + 'X-Stainless-Runtime': 'unknown', + 'X-Stainless-Runtime-Version': 'unknown', + }; +}; +// Note: modified from https://github.com/JS-DevTools/host-environment/blob/b1ab79ecde37db5d6e163c050e54fe7d287d7c92/src/isomorphic.browser.ts +function getBrowserInfo() { + if (typeof navigator === 'undefined' || !navigator) { + return null; + } + // NOTE: The order matters here! + const browserPatterns = [ + { key: 'edge', pattern: /Edge(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'ie', pattern: /MSIE(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'ie', pattern: /Trident(?:.*rv\:(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'chrome', pattern: /Chrome(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'firefox', pattern: /Firefox(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'safari', pattern: /(?:Version\W+(\d+)\.(\d+)(?:\.(\d+))?)?(?:\W+Mobile\S*)?\W+Safari/ }, + ]; + // Find the FIRST matching browser + for (const { key, pattern } of browserPatterns) { + const match = pattern.exec(navigator.userAgent); + if (match) { + const major = match[1] || 0; + const minor = match[2] || 0; + const patch = match[3] || 0; + return { browser: key, version: `${major}.${minor}.${patch}` }; + } + } + return null; +} +const normalizeArch = (arch) => { + // Node docs: + // - https://nodejs.org/api/process.html#processarch + // Deno docs: + // - https://doc.deno.land/deno/stable/~/Deno.build + if (arch === 'x32') + return 'x32'; + if (arch === 'x86_64' || arch === 'x64') + return 'x64'; + if (arch === 'arm') + return 'arm'; + if (arch === 'aarch64' || arch === 'arm64') + return 'arm64'; + if (arch) + return `other:${arch}`; + return 'unknown'; +}; +const normalizePlatform = (platform) => { + // Node platforms: + // - https://nodejs.org/api/process.html#processplatform + // Deno platforms: + // - https://doc.deno.land/deno/stable/~/Deno.build + // - https://github.com/denoland/deno/issues/14799 + platform = platform.toLowerCase(); + // NOTE: this iOS check is untested and may not work + // Node does not work natively on IOS, there is a fork at + // https://github.com/nodejs-mobile/nodejs-mobile + // however it is unknown at the time of writing how to detect if it is running + if (platform.includes('ios')) + return 'iOS'; + if (platform === 'android') + return 'Android'; + if (platform === 'darwin') + return 'MacOS'; + if (platform === 'win32') + return 'Windows'; + if (platform === 'freebsd') + return 'FreeBSD'; + if (platform === 'openbsd') + return 'OpenBSD'; + if (platform === 'linux') + return 'Linux'; + if (platform) + return `Other:${platform}`; + return 'Unknown'; +}; +let _platformHeaders; +const getPlatformHeaders = () => { + return (_platformHeaders !== null && _platformHeaders !== void 0 ? _platformHeaders : (_platformHeaders = getPlatformProperties())); +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function getDefaultFetch() { + if (typeof fetch !== 'undefined') { + return fetch; + } + throw new Error('`fetch` is not defined as a global; Either pass `fetch` to the client, `new GeminiNextGenAPIClient({ fetch })` or polyfill the global, `globalThis.fetch = fetch`'); +} +function makeReadableStream(...args) { + const ReadableStream = globalThis.ReadableStream; + if (typeof ReadableStream === 'undefined') { + // Note: All of the platforms / runtimes we officially support already define + // `ReadableStream` as a global, so this should only ever be hit on unsupported runtimes. + throw new Error('`ReadableStream` is not defined as a global; You will need to polyfill it, `globalThis.ReadableStream = ReadableStream`'); + } + return new ReadableStream(...args); +} +function ReadableStreamFrom(iterable) { + let iter = Symbol.asyncIterator in iterable ? iterable[Symbol.asyncIterator]() : iterable[Symbol.iterator](); + return makeReadableStream({ + start() { }, + async pull(controller) { + const { done, value } = await iter.next(); + if (done) { + controller.close(); + } + else { + controller.enqueue(value); + } + }, + async cancel() { + var _a; + await ((_a = iter.return) === null || _a === void 0 ? void 0 : _a.call(iter)); + }, + }); +} +/** + * Most browsers don't yet have async iterable support for ReadableStream, + * and Node has a very different way of reading bytes from its "ReadableStream". + * + * This polyfill was pulled from https://github.com/MattiasBuelens/web-streams-polyfill/pull/122#issuecomment-1627354490 + */ +function ReadableStreamToAsyncIterable(stream) { + if (stream[Symbol.asyncIterator]) + return stream; + const reader = stream.getReader(); + return { + async next() { + try { + const result = await reader.read(); + if (result === null || result === void 0 ? void 0 : result.done) + reader.releaseLock(); // release lock when stream becomes closed + return result; + } + catch (e) { + reader.releaseLock(); // release lock when stream becomes errored + throw e; + } + }, + async return() { + const cancelPromise = reader.cancel(); + reader.releaseLock(); + await cancelPromise; + return { done: true, value: undefined }; + }, + [Symbol.asyncIterator]() { + return this; + }, + }; +} +/** + * Cancels a ReadableStream we don't need to consume. + * See https://undici.nodejs.org/#/?id=garbage-collection + */ +async function CancelReadableStream(stream) { + var _a, _b; + if (stream === null || typeof stream !== 'object') + return; + if (stream[Symbol.asyncIterator]) { + await ((_b = (_a = stream[Symbol.asyncIterator]()).return) === null || _b === void 0 ? void 0 : _b.call(_a)); + return; + } + const reader = stream.getReader(); + const cancelPromise = reader.cancel(); + reader.releaseLock(); + await cancelPromise; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const FallbackEncoder = ({ headers, body }) => { + return { + bodyHeaders: { + 'content-type': 'application/json', + }, + body: JSON.stringify(body), + }; +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const checkFileSupport = () => { + var _a; + if (typeof File === 'undefined') { + const { process } = globalThis; + const isOldNode = typeof ((_a = process === null || process === void 0 ? void 0 : process.versions) === null || _a === void 0 ? void 0 : _a.node) === 'string' && parseInt(process.versions.node.split('.')) < 20; + throw new Error('`File` is not defined as a global, which is required for file uploads.' + + (isOldNode ? + " Update to Node 20 LTS or newer, or set `globalThis.File` to `import('node:buffer').File`." + : '')); + } +}; +/** + * Construct a `File` instance. This is used to ensure a helpful error is thrown + * for environments that don't define a global `File` yet. + */ +function makeFile(fileBits, fileName, options) { + checkFileSupport(); + return new File(fileBits, fileName !== null && fileName !== void 0 ? fileName : 'unknown_file', options); +} +function getName(value) { + return (((typeof value === 'object' && + value !== null && + (('name' in value && value.name && String(value.name)) || + ('url' in value && value.url && String(value.url)) || + ('filename' in value && value.filename && String(value.filename)) || + ('path' in value && value.path && String(value.path)))) || + '') + .split(/[\\/]/) + .pop() || undefined); +} +const isAsyncIterable = (value) => value != null && typeof value === 'object' && typeof value[Symbol.asyncIterator] === 'function'; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * This check adds the arrayBuffer() method type because it is available and used at runtime + */ +const isBlobLike = (value) => value != null && + typeof value === 'object' && + typeof value.size === 'number' && + typeof value.type === 'string' && + typeof value.text === 'function' && + typeof value.slice === 'function' && + typeof value.arrayBuffer === 'function'; +/** + * This check adds the arrayBuffer() method type because it is available and used at runtime + */ +const isFileLike = (value) => value != null && + typeof value === 'object' && + typeof value.name === 'string' && + typeof value.lastModified === 'number' && + isBlobLike(value); +const isResponseLike = (value) => value != null && + typeof value === 'object' && + typeof value.url === 'string' && + typeof value.blob === 'function'; +/** + * Helper for creating a {@link File} to pass to an SDK upload method from a variety of different data formats + * @param value the raw content of the file. Can be an {@link Uploadable}, BlobLikePart, or AsyncIterable of BlobLikeParts + * @param {string=} name the name of the file. If omitted, toFile will try to determine a file name from bits if possible + * @param {Object=} options additional properties + * @param {string=} options.type the MIME type of the content + * @param {number=} options.lastModified the last modified timestamp + * @returns a {@link File} with the given properties + */ +async function toFile(value, name, options) { + checkFileSupport(); + // If it's a promise, resolve it. + value = await value; + // If we've been given a `File` we don't need to do anything + if (isFileLike(value)) { + if (value instanceof File) { + return value; + } + return makeFile([await value.arrayBuffer()], value.name); + } + if (isResponseLike(value)) { + const blob = await value.blob(); + name || (name = new URL(value.url).pathname.split(/[\\/]/).pop()); + return makeFile(await getBytes(blob), name, options); + } + const parts = await getBytes(value); + name || (name = getName(value)); + if (!(options === null || options === void 0 ? void 0 : options.type)) { + const type = parts.find((part) => typeof part === 'object' && 'type' in part && part.type); + if (typeof type === 'string') { + options = Object.assign(Object.assign({}, options), { type }); + } + } + return makeFile(parts, name, options); +} +async function getBytes(value) { + var _a, e_1, _b, _c; + var _d; + let parts = []; + if (typeof value === 'string' || + ArrayBuffer.isView(value) || // includes Uint8Array, Buffer, etc. + value instanceof ArrayBuffer) { + parts.push(value); + } + else if (isBlobLike(value)) { + parts.push(value instanceof Blob ? value : await value.arrayBuffer()); + } + else if (isAsyncIterable(value) // includes Readable, ReadableStream, etc. + ) { + try { + for (var _e = true, value_1 = __asyncValues(value), value_1_1; value_1_1 = await value_1.next(), _a = value_1_1.done, !_a; _e = true) { + _c = value_1_1.value; + _e = false; + const chunk = _c; + parts.push(...(await getBytes(chunk))); // TODO, consider validating? + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (!_e && !_a && (_b = value_1.return)) await _b.call(value_1); + } + finally { if (e_1) throw e_1.error; } + } + } + else { + const constructor = (_d = value === null || value === void 0 ? void 0 : value.constructor) === null || _d === void 0 ? void 0 : _d.name; + throw new Error(`Unexpected data type: ${typeof value}${constructor ? `; constructor: ${constructor}` : ''}${propsForError(value)}`); + } + return parts; +} +function propsForError(value) { + if (typeof value !== 'object' || value === null) + return ''; + const props = Object.getOwnPropertyNames(value); + return `; props: [${props.map((p) => `"${p}"`).join(', ')}]`; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class APIResource { + constructor(client) { + this._client = client; + } +} +/** + * The key path from the client. For example, a resource accessible as `client.resource.subresource` would + * have a property `static override readonly _key = Object.freeze(['resource', 'subresource'] as const);`. + */ +APIResource._key = []; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Percent-encode everything that isn't safe to have in a path without encoding safe chars. + * + * Taken from https://datatracker.ietf.org/doc/html/rfc3986#section-3.3: + * > unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + * > sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" + * > pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + */ +function encodeURIPath(str) { + return str.replace(/[^A-Za-z0-9\-._~!$&'()*+,;=:@]+/g, encodeURIComponent); +} +const EMPTY = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.create(null)); +const createPathTagFunction = (pathEncoder = encodeURIPath) => (function path(statics, ...params) { + // If there are no params, no processing is needed. + if (statics.length === 1) + return statics[0]; + let postPath = false; + const invalidSegments = []; + const path = statics.reduce((previousValue, currentValue, index) => { + var _a, _b, _c; + if (/[?#]/.test(currentValue)) { + postPath = true; + } + const value = params[index]; + let encoded = (postPath ? encodeURIComponent : pathEncoder)('' + value); + if (index !== params.length && + (value == null || + (typeof value === 'object' && + // handle values from other realms + value.toString === + ((_c = Object.getPrototypeOf((_b = Object.getPrototypeOf((_a = value.hasOwnProperty) !== null && _a !== void 0 ? _a : EMPTY)) !== null && _b !== void 0 ? _b : EMPTY)) === null || _c === void 0 ? void 0 : _c.toString)))) { + encoded = value + ''; + invalidSegments.push({ + start: previousValue.length + currentValue.length, + length: encoded.length, + error: `Value of type ${Object.prototype.toString + .call(value) + .slice(8, -1)} is not a valid path parameter`, + }); + } + return previousValue + currentValue + (index === params.length ? '' : encoded); + }, ''); + const pathOnly = path.split(/[?#]/, 1)[0]; + const invalidSegmentPattern = /(?<=^|\/)(?:\.|%2e){1,2}(?=\/|$)/gi; + let match; + // Find all invalid segments + while ((match = invalidSegmentPattern.exec(pathOnly)) !== null) { + invalidSegments.push({ + start: match.index, + length: match[0].length, + error: `Value "${match[0]}" can\'t be safely passed as a path parameter`, + }); + } + invalidSegments.sort((a, b) => a.start - b.start); + if (invalidSegments.length > 0) { + let lastEnd = 0; + const underline = invalidSegments.reduce((acc, segment) => { + const spaces = ' '.repeat(segment.start - lastEnd); + const arrows = '^'.repeat(segment.length); + lastEnd = segment.start + segment.length; + return acc + spaces + arrows; + }, ''); + throw new GeminiNextGenAPIClientError(`Path parameters result in path with invalid segments:\n${invalidSegments + .map((e) => e.error) + .join('\n')}\n${path}\n${underline}`); + } + return path; +}); +/** + * URI-encodes path params and ensures no unsafe /./ or /../ path segments are introduced. + */ +const path = /* @__PURE__ */ createPathTagFunction(encodeURIPath); + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class BaseInteractions extends APIResource { + create(params, options) { + var _a; + const { api_version = this._client.apiVersion } = params, body = __rest(params, ["api_version"]); + if ('model' in body && 'agent_config' in body) { + throw new GeminiNextGenAPIClientError(`Invalid request: specified \`model\` and \`agent_config\`. If specifying \`model\`, use \`generation_config\`.`); + } + if ('agent' in body && 'generation_config' in body) { + throw new GeminiNextGenAPIClientError(`Invalid request: specified \`agent\` and \`generation_config\`. If specifying \`agent\`, use \`agent_config\`.`); + } + return this._client.post(path `/${api_version}/interactions`, Object.assign(Object.assign({ body }, options), { stream: (_a = params.stream) !== null && _a !== void 0 ? _a : false })); + } + /** + * Deletes the interaction by id. + * + * @example + * ```ts + * const interaction = await client.interactions.delete('id', { + * api_version: 'api_version', + * }); + * ``` + */ + delete(id, params = {}, options) { + const { api_version = this._client.apiVersion } = params !== null && params !== void 0 ? params : {}; + return this._client.delete(path `/${api_version}/interactions/${id}`, options); + } + /** + * Cancels an interaction by id. This only applies to background interactions that are still running. + * + * @example + * ```ts + * const interaction = await client.interactions.cancel('id', { + * api_version: 'api_version', + * }); + * ``` + */ + cancel(id, params = {}, options) { + const { api_version = this._client.apiVersion } = params !== null && params !== void 0 ? params : {}; + return this._client.post(path `/${api_version}/interactions/${id}/cancel`, options); + } + get(id, params = {}, options) { + var _a; + const _b = params !== null && params !== void 0 ? params : {}, { api_version = this._client.apiVersion } = _b, query = __rest(_b, ["api_version"]); + return this._client.get(path `/${api_version}/interactions/${id}`, Object.assign(Object.assign({ query }, options), { stream: (_a = params === null || params === void 0 ? void 0 : params.stream) !== null && _a !== void 0 ? _a : false })); + } +} +BaseInteractions._key = Object.freeze(['interactions']); +class Interactions extends BaseInteractions { +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function concatBytes(buffers) { + let length = 0; + for (const buffer of buffers) { + length += buffer.length; + } + const output = new Uint8Array(length); + let index = 0; + for (const buffer of buffers) { + output.set(buffer, index); + index += buffer.length; + } + return output; +} +let encodeUTF8_; +function encodeUTF8(str) { + let encoder; + return (encodeUTF8_ !== null && encodeUTF8_ !== void 0 ? encodeUTF8_ : ((encoder = new globalThis.TextEncoder()), (encodeUTF8_ = encoder.encode.bind(encoder))))(str); +} +let decodeUTF8_; +function decodeUTF8(bytes) { + let decoder; + return (decodeUTF8_ !== null && decodeUTF8_ !== void 0 ? decodeUTF8_ : ((decoder = new globalThis.TextDecoder()), (decodeUTF8_ = decoder.decode.bind(decoder))))(bytes); +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * A re-implementation of httpx's `LineDecoder` in Python that handles incrementally + * reading lines from text. + * + * https://github.com/encode/httpx/blob/920333ea98118e9cf617f246905d7b202510941c/httpx/_decoders.py#L258 + */ +class LineDecoder { + constructor() { + this.buffer = new Uint8Array(); + this.carriageReturnIndex = null; + } + decode(chunk) { + if (chunk == null) { + return []; + } + const binaryChunk = chunk instanceof ArrayBuffer ? new Uint8Array(chunk) + : typeof chunk === 'string' ? encodeUTF8(chunk) + : chunk; + this.buffer = concatBytes([this.buffer, binaryChunk]); + const lines = []; + let patternIndex; + while ((patternIndex = findNewlineIndex(this.buffer, this.carriageReturnIndex)) != null) { + if (patternIndex.carriage && this.carriageReturnIndex == null) { + // skip until we either get a corresponding `\n`, a new `\r` or nothing + this.carriageReturnIndex = patternIndex.index; + continue; + } + // we got double \r or \rtext\n + if (this.carriageReturnIndex != null && + (patternIndex.index !== this.carriageReturnIndex + 1 || patternIndex.carriage)) { + lines.push(decodeUTF8(this.buffer.subarray(0, this.carriageReturnIndex - 1))); + this.buffer = this.buffer.subarray(this.carriageReturnIndex); + this.carriageReturnIndex = null; + continue; + } + const endIndex = this.carriageReturnIndex !== null ? patternIndex.preceding - 1 : patternIndex.preceding; + const line = decodeUTF8(this.buffer.subarray(0, endIndex)); + lines.push(line); + this.buffer = this.buffer.subarray(patternIndex.index); + this.carriageReturnIndex = null; + } + return lines; + } + flush() { + if (!this.buffer.length) { + return []; + } + return this.decode('\n'); + } +} +// prettier-ignore +LineDecoder.NEWLINE_CHARS = new Set(['\n', '\r']); +LineDecoder.NEWLINE_REGEXP = /\r\n|[\n\r]/g; +/** + * This function searches the buffer for the end patterns, (\r or \n) + * and returns an object with the index preceding the matched newline and the + * index after the newline char. `null` is returned if no new line is found. + * + * ```ts + * findNewLineIndex('abc\ndef') -> { preceding: 2, index: 3 } + * ``` + */ +function findNewlineIndex(buffer, startIndex) { + const newline = 0x0a; // \n + const carriage = 0x0d; // \r + for (let i = startIndex !== null && startIndex !== void 0 ? startIndex : 0; i < buffer.length; i++) { + if (buffer[i] === newline) { + return { preceding: i, index: i + 1, carriage: false }; + } + if (buffer[i] === carriage) { + return { preceding: i, index: i + 1, carriage: true }; + } + } + return null; +} +function findDoubleNewlineIndex(buffer) { + // This function searches the buffer for the end patterns (\r\r, \n\n, \r\n\r\n) + // and returns the index right after the first occurrence of any pattern, + // or -1 if none of the patterns are found. + const newline = 0x0a; // \n + const carriage = 0x0d; // \r + for (let i = 0; i < buffer.length - 1; i++) { + if (buffer[i] === newline && buffer[i + 1] === newline) { + // \n\n + return i + 2; + } + if (buffer[i] === carriage && buffer[i + 1] === carriage) { + // \r\r + return i + 2; + } + if (buffer[i] === carriage && + buffer[i + 1] === newline && + i + 3 < buffer.length && + buffer[i + 2] === carriage && + buffer[i + 3] === newline) { + // \r\n\r\n + return i + 4; + } + } + return -1; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +const levelNumbers = { + off: 0, + error: 200, + warn: 300, + info: 400, + debug: 500, +}; +const parseLogLevel = (maybeLevel, sourceName, client) => { + if (!maybeLevel) { + return undefined; + } + if (hasOwn(levelNumbers, maybeLevel)) { + return maybeLevel; + } + loggerFor(client).warn(`${sourceName} was set to ${JSON.stringify(maybeLevel)}, expected one of ${JSON.stringify(Object.keys(levelNumbers))}`); + return undefined; +}; +function noop() { } +function makeLogFn(fnLevel, logger, logLevel) { + if (!logger || levelNumbers[fnLevel] > levelNumbers[logLevel]) { + return noop; + } + else { + // Don't wrap logger functions, we want the stacktrace intact! + return logger[fnLevel].bind(logger); + } +} +const noopLogger = { + error: noop, + warn: noop, + info: noop, + debug: noop, +}; +let cachedLoggers = /* @__PURE__ */ new WeakMap(); +function loggerFor(client) { + var _a; + const logger = client.logger; + const logLevel = (_a = client.logLevel) !== null && _a !== void 0 ? _a : 'off'; + if (!logger) { + return noopLogger; + } + const cachedLogger = cachedLoggers.get(logger); + if (cachedLogger && cachedLogger[0] === logLevel) { + return cachedLogger[1]; + } + const levelLogger = { + error: makeLogFn('error', logger, logLevel), + warn: makeLogFn('warn', logger, logLevel), + info: makeLogFn('info', logger, logLevel), + debug: makeLogFn('debug', logger, logLevel), + }; + cachedLoggers.set(logger, [logLevel, levelLogger]); + return levelLogger; +} +const formatRequestDetails = (details) => { + if (details.options) { + details.options = Object.assign({}, details.options); + delete details.options['headers']; // redundant + leaks internals + } + if (details.headers) { + details.headers = Object.fromEntries((details.headers instanceof Headers ? [...details.headers] : Object.entries(details.headers)).map(([name, value]) => [ + name, + (name.toLowerCase() === 'x-goog-api-key' || + name.toLowerCase() === 'authorization' || + name.toLowerCase() === 'cookie' || + name.toLowerCase() === 'set-cookie') ? + '***' + : value, + ])); + } + if ('retryOfRequestLogID' in details) { + if (details.retryOfRequestLogID) { + details.retryOf = details.retryOfRequestLogID; + } + delete details.retryOfRequestLogID; + } + return details; +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Stream { + constructor(iterator, controller, client) { + this.iterator = iterator; + this.controller = controller; + this.client = client; + } + static fromSSEResponse(response, controller, client) { + let consumed = false; + const logger = client ? loggerFor(client) : console; + function iterator() { + return __asyncGenerator(this, arguments, function* iterator_1() { + var _a, e_1, _b, _c; + if (consumed) { + throw new GeminiNextGenAPIClientError('Cannot iterate over a consumed stream, use `.tee()` to split the stream.'); + } + consumed = true; + let done = false; + try { + try { + for (var _d = true, _e = __asyncValues(_iterSSEMessages(response, controller)), _f; _f = yield __await(_e.next()), _a = _f.done, !_a; _d = true) { + _c = _f.value; + _d = false; + const sse = _c; + if (done) + continue; + if (sse.data.startsWith('[DONE]')) { + done = true; + continue; + } + else { + try { + // @ts-ignore + yield yield __await(JSON.parse(sse.data)); + } + catch (e) { + logger.error(`Could not parse message into JSON:`, sse.data); + logger.error(`From chunk:`, sse.raw); + throw e; + } + } + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (!_d && !_a && (_b = _e.return)) yield __await(_b.call(_e)); + } + finally { if (e_1) throw e_1.error; } + } + done = true; + } + catch (e) { + // If the user calls `stream.controller.abort()`, we should exit without throwing. + if (isAbortError(e)) + return yield __await(void 0); + throw e; + } + finally { + // If the user `break`s, abort the ongoing request. + if (!done) + controller.abort(); + } + }); + } + return new Stream(iterator, controller, client); + } + /** + * Generates a Stream from a newline-separated ReadableStream + * where each item is a JSON value. + */ + static fromReadableStream(readableStream, controller, client) { + let consumed = false; + function iterLines() { + return __asyncGenerator(this, arguments, function* iterLines_1() { + var _a, e_2, _b, _c; + const lineDecoder = new LineDecoder(); + const iter = ReadableStreamToAsyncIterable(readableStream); + try { + for (var _d = true, iter_1 = __asyncValues(iter), iter_1_1; iter_1_1 = yield __await(iter_1.next()), _a = iter_1_1.done, !_a; _d = true) { + _c = iter_1_1.value; + _d = false; + const chunk = _c; + for (const line of lineDecoder.decode(chunk)) { + yield yield __await(line); + } + } + } + catch (e_2_1) { e_2 = { error: e_2_1 }; } + finally { + try { + if (!_d && !_a && (_b = iter_1.return)) yield __await(_b.call(iter_1)); + } + finally { if (e_2) throw e_2.error; } + } + for (const line of lineDecoder.flush()) { + yield yield __await(line); + } + }); + } + function iterator() { + return __asyncGenerator(this, arguments, function* iterator_2() { + var _a, e_3, _b, _c; + if (consumed) { + throw new GeminiNextGenAPIClientError('Cannot iterate over a consumed stream, use `.tee()` to split the stream.'); + } + consumed = true; + let done = false; + try { + try { + for (var _d = true, _e = __asyncValues(iterLines()), _f; _f = yield __await(_e.next()), _a = _f.done, !_a; _d = true) { + _c = _f.value; + _d = false; + const line = _c; + if (done) + continue; + // @ts-ignore + if (line) + yield yield __await(JSON.parse(line)); + } + } + catch (e_3_1) { e_3 = { error: e_3_1 }; } + finally { + try { + if (!_d && !_a && (_b = _e.return)) yield __await(_b.call(_e)); + } + finally { if (e_3) throw e_3.error; } + } + done = true; + } + catch (e) { + // If the user calls `stream.controller.abort()`, we should exit without throwing. + if (isAbortError(e)) + return yield __await(void 0); + throw e; + } + finally { + // If the user `break`s, abort the ongoing request. + if (!done) + controller.abort(); + } + }); + } + return new Stream(iterator, controller, client); + } + [Symbol.asyncIterator]() { + return this.iterator(); + } + /** + * Splits the stream into two streams which can be + * independently read from at different speeds. + */ + tee() { + const left = []; + const right = []; + const iterator = this.iterator(); + const teeIterator = (queue) => { + return { + next: () => { + if (queue.length === 0) { + const result = iterator.next(); + left.push(result); + right.push(result); + } + return queue.shift(); + }, + }; + }; + return [ + new Stream(() => teeIterator(left), this.controller, this.client), + new Stream(() => teeIterator(right), this.controller, this.client), + ]; + } + /** + * Converts this stream to a newline-separated ReadableStream of + * JSON stringified values in the stream + * which can be turned back into a Stream with `Stream.fromReadableStream()`. + */ + toReadableStream() { + const self = this; + let iter; + return makeReadableStream({ + async start() { + iter = self[Symbol.asyncIterator](); + }, + async pull(ctrl) { + try { + const { value, done } = await iter.next(); + if (done) + return ctrl.close(); + const bytes = encodeUTF8(JSON.stringify(value) + '\n'); + ctrl.enqueue(bytes); + } + catch (err) { + ctrl.error(err); + } + }, + async cancel() { + var _a; + await ((_a = iter.return) === null || _a === void 0 ? void 0 : _a.call(iter)); + }, + }); + } +} +function _iterSSEMessages(response, controller) { + return __asyncGenerator(this, arguments, function* _iterSSEMessages_1() { + var _a, e_4, _b, _c; + if (!response.body) { + controller.abort(); + if (typeof globalThis.navigator !== 'undefined' && + globalThis.navigator.product === 'ReactNative') { + throw new GeminiNextGenAPIClientError(`The default react-native fetch implementation does not support streaming. Please use expo/fetch: https://docs.expo.dev/versions/latest/sdk/expo/#expofetch-api`); + } + throw new GeminiNextGenAPIClientError(`Attempted to iterate over a response with no body`); + } + const sseDecoder = new SSEDecoder(); + const lineDecoder = new LineDecoder(); + const iter = ReadableStreamToAsyncIterable(response.body); + try { + for (var _d = true, _e = __asyncValues(iterSSEChunks(iter)), _f; _f = yield __await(_e.next()), _a = _f.done, !_a; _d = true) { + _c = _f.value; + _d = false; + const sseChunk = _c; + for (const line of lineDecoder.decode(sseChunk)) { + const sse = sseDecoder.decode(line); + if (sse) + yield yield __await(sse); + } + } + } + catch (e_4_1) { e_4 = { error: e_4_1 }; } + finally { + try { + if (!_d && !_a && (_b = _e.return)) yield __await(_b.call(_e)); + } + finally { if (e_4) throw e_4.error; } + } + for (const line of lineDecoder.flush()) { + const sse = sseDecoder.decode(line); + if (sse) + yield yield __await(sse); + } + }); +} +/** + * Given an async iterable iterator, iterates over it and yields full + * SSE chunks, i.e. yields when a double new-line is encountered. + */ +function iterSSEChunks(iterator) { + return __asyncGenerator(this, arguments, function* iterSSEChunks_1() { + var _a, e_5, _b, _c; + let data = new Uint8Array(); + try { + for (var _d = true, iterator_3 = __asyncValues(iterator), iterator_3_1; iterator_3_1 = yield __await(iterator_3.next()), _a = iterator_3_1.done, !_a; _d = true) { + _c = iterator_3_1.value; + _d = false; + const chunk = _c; + if (chunk == null) { + continue; + } + const binaryChunk = chunk instanceof ArrayBuffer ? new Uint8Array(chunk) + : typeof chunk === 'string' ? encodeUTF8(chunk) + : chunk; + let newData = new Uint8Array(data.length + binaryChunk.length); + newData.set(data); + newData.set(binaryChunk, data.length); + data = newData; + let patternIndex; + while ((patternIndex = findDoubleNewlineIndex(data)) !== -1) { + yield yield __await(data.slice(0, patternIndex)); + data = data.slice(patternIndex); + } + } + } + catch (e_5_1) { e_5 = { error: e_5_1 }; } + finally { + try { + if (!_d && !_a && (_b = iterator_3.return)) yield __await(_b.call(iterator_3)); + } + finally { if (e_5) throw e_5.error; } + } + if (data.length > 0) { + yield yield __await(data); + } + }); +} +class SSEDecoder { + constructor() { + this.event = null; + this.data = []; + this.chunks = []; + } + decode(line) { + if (line.endsWith('\r')) { + line = line.substring(0, line.length - 1); + } + if (!line) { + // empty line and we didn't previously encounter any messages + if (!this.event && !this.data.length) + return null; + const sse = { + event: this.event, + data: this.data.join('\n'), + raw: this.chunks, + }; + this.event = null; + this.data = []; + this.chunks = []; + return sse; + } + this.chunks.push(line); + if (line.startsWith(':')) { + return null; + } + let [fieldname, _, value] = partition(line, ':'); + if (value.startsWith(' ')) { + value = value.substring(1); + } + if (fieldname === 'event') { + this.event = value; + } + else if (fieldname === 'data') { + this.data.push(value); + } + return null; + } +} +function partition(str, delimiter) { + const index = str.indexOf(delimiter); + if (index !== -1) { + return [str.substring(0, index), delimiter, str.substring(index + delimiter.length)]; + } + return [str, '', '']; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +async function defaultParseResponse(client, props) { + const { response, requestLogID, retryOfRequestLogID, startTime } = props; + const body = await (async () => { + var _a; + if (props.options.stream) { + loggerFor(client).debug('response', response.status, response.url, response.headers, response.body); + // Note: there is an invariant here that isn't represented in the type system + // that if you set `stream: true` the response type must also be `Stream<T>` + if (props.options.__streamClass) { + return props.options.__streamClass.fromSSEResponse(response, props.controller, client); + } + return Stream.fromSSEResponse(response, props.controller, client); + } + // fetch refuses to read the body when the status code is 204. + if (response.status === 204) { + return null; + } + if (props.options.__binaryResponse) { + return response; + } + const contentType = response.headers.get('content-type'); + const mediaType = (_a = contentType === null || contentType === void 0 ? void 0 : contentType.split(';')[0]) === null || _a === void 0 ? void 0 : _a.trim(); + const isJSON = (mediaType === null || mediaType === void 0 ? void 0 : mediaType.includes('application/json')) || (mediaType === null || mediaType === void 0 ? void 0 : mediaType.endsWith('+json')); + if (isJSON) { + const contentLength = response.headers.get('content-length'); + if (contentLength === '0') { + // if there is no content we can't do anything + return undefined; + } + const json = await response.json(); + return json; + } + const text = await response.text(); + return text; + })(); + loggerFor(client).debug(`[${requestLogID}] response parsed`, formatRequestDetails({ + retryOfRequestLogID, + url: response.url, + status: response.status, + body, + durationMs: Date.now() - startTime, + })); + return body; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * A subclass of `Promise` providing additional helper methods + * for interacting with the SDK. + */ +class APIPromise extends Promise { + constructor(client, responsePromise, parseResponse = defaultParseResponse) { + super((resolve) => { + // this is maybe a bit weird but this has to be a no-op to not implicitly + // parse the response body; instead .then, .catch, .finally are overridden + // to parse the response + resolve(null); + }); + this.responsePromise = responsePromise; + this.parseResponse = parseResponse; + this.client = client; + } + _thenUnwrap(transform) { + return new APIPromise(this.client, this.responsePromise, async (client, props) => transform(await this.parseResponse(client, props), props)); + } + /** + * Gets the raw `Response` instance instead of parsing the response + * data. + * + * If you want to parse the response body but still get the `Response` + * instance, you can use {@link withResponse()}. + * + * 👋 Getting the wrong TypeScript type for `Response`? + * Try setting `"moduleResolution": "NodeNext"` or add `"lib": ["DOM"]` + * to your `tsconfig.json`. + */ + asResponse() { + return this.responsePromise.then((p) => p.response); + } + /** + * Gets the parsed response data and the raw `Response` instance. + * + * If you just want to get the raw `Response` instance without parsing it, + * you can use {@link asResponse()}. + * + * 👋 Getting the wrong TypeScript type for `Response`? + * Try setting `"moduleResolution": "NodeNext"` or add `"lib": ["DOM"]` + * to your `tsconfig.json`. + */ + async withResponse() { + const [data, response] = await Promise.all([this.parse(), this.asResponse()]); + return { data, response }; + } + parse() { + if (!this.parsedPromise) { + this.parsedPromise = this.responsePromise.then((data) => this.parseResponse(this.client, data)); + } + return this.parsedPromise; + } + then(onfulfilled, onrejected) { + return this.parse().then(onfulfilled, onrejected); + } + catch(onrejected) { + return this.parse().catch(onrejected); + } + finally(onfinally) { + return this.parse().finally(onfinally); + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +const brand_privateNullableHeaders = /* @__PURE__ */ Symbol('brand.privateNullableHeaders'); +function* iterateHeaders(headers) { + if (!headers) + return; + if (brand_privateNullableHeaders in headers) { + const { values, nulls } = headers; + yield* values.entries(); + for (const name of nulls) { + yield [name, null]; + } + return; + } + let shouldClear = false; + let iter; + if (headers instanceof Headers) { + iter = headers.entries(); + } + else if (isReadonlyArray(headers)) { + iter = headers; + } + else { + shouldClear = true; + iter = Object.entries(headers !== null && headers !== void 0 ? headers : {}); + } + for (let row of iter) { + const name = row[0]; + if (typeof name !== 'string') + throw new TypeError('expected header name to be a string'); + const values = isReadonlyArray(row[1]) ? row[1] : [row[1]]; + let didClear = false; + for (const value of values) { + if (value === undefined) + continue; + // Objects keys always overwrite older headers, they never append. + // Yield a null to clear the header before adding the new values. + if (shouldClear && !didClear) { + didClear = true; + yield [name, null]; + } + yield [name, value]; + } + } +} +const buildHeaders = (newHeaders) => { + const targetHeaders = new Headers(); + const nullHeaders = new Set(); + for (const headers of newHeaders) { + const seenHeaders = new Set(); + for (const [name, value] of iterateHeaders(headers)) { + const lowerName = name.toLowerCase(); + if (!seenHeaders.has(lowerName)) { + targetHeaders.delete(name); + seenHeaders.add(lowerName); + } + if (value === null) { + targetHeaders.delete(name); + nullHeaders.add(lowerName); + } + else { + targetHeaders.append(name, value); + nullHeaders.delete(lowerName); + } + } + } + return { [brand_privateNullableHeaders]: true, values: targetHeaders, nulls: nullHeaders }; +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +/** + * Read an environment variable. + * + * Trims beginning and trailing whitespace. + * + * Will return undefined if the environment variable doesn't exist or cannot be accessed. + */ +const readEnv = (env) => { + var _a, _b, _c, _d, _e, _f; + if (typeof globalThis.process !== 'undefined') { + return (_c = (_b = (_a = globalThis.process.env) === null || _a === void 0 ? void 0 : _a[env]) === null || _b === void 0 ? void 0 : _b.trim()) !== null && _c !== void 0 ? _c : undefined; + } + if (typeof globalThis.Deno !== 'undefined') { + return (_f = (_e = (_d = globalThis.Deno.env) === null || _d === void 0 ? void 0 : _d.get) === null || _e === void 0 ? void 0 : _e.call(_d, env)) === null || _f === void 0 ? void 0 : _f.trim(); + } + return undefined; +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +var _a; +/** + * Base class for Gemini Next Gen API API clients. + */ +class BaseGeminiNextGenAPIClient { + /** + * API Client for interfacing with the Gemini Next Gen API API. + * + * @param {string | null | undefined} [opts.apiKey=process.env['GEMINI_API_KEY'] ?? null] + * @param {string | undefined} [opts.apiVersion=v1beta] + * @param {string} [opts.baseURL=process.env['GEMINI_NEXT_GEN_API_BASE_URL'] ?? https://generativelanguage.googleapis.com] - Override the default base URL for the API. + * @param {number} [opts.timeout=1 minute] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out. + * @param {MergedRequestInit} [opts.fetchOptions] - Additional `RequestInit` options to be passed to `fetch` calls. + * @param {Fetch} [opts.fetch] - Specify a custom `fetch` function implementation. + * @param {number} [opts.maxRetries=2] - The maximum number of times the client will retry a request. + * @param {HeadersLike} opts.defaultHeaders - Default headers to include with every request to the API. + * @param {Record<string, string | undefined>} opts.defaultQuery - Default query parameters to include with every request to the API. + */ + constructor(_b) { + var _c, _d, _e, _f, _g, _h, _j; + var { baseURL = readEnv('GEMINI_NEXT_GEN_API_BASE_URL'), apiKey = (_c = readEnv('GEMINI_API_KEY')) !== null && _c !== void 0 ? _c : null, apiVersion = 'v1beta' } = _b, opts = __rest(_b, ["baseURL", "apiKey", "apiVersion"]); + const options = Object.assign(Object.assign({ apiKey, + apiVersion }, opts), { baseURL: baseURL || `https://generativelanguage.googleapis.com` }); + this.baseURL = options.baseURL; + this.timeout = (_d = options.timeout) !== null && _d !== void 0 ? _d : BaseGeminiNextGenAPIClient.DEFAULT_TIMEOUT /* 1 minute */; + this.logger = (_e = options.logger) !== null && _e !== void 0 ? _e : console; + const defaultLogLevel = 'warn'; + // Set default logLevel early so that we can log a warning in parseLogLevel. + this.logLevel = defaultLogLevel; + this.logLevel = + (_g = (_f = parseLogLevel(options.logLevel, 'ClientOptions.logLevel', this)) !== null && _f !== void 0 ? _f : parseLogLevel(readEnv('GEMINI_NEXT_GEN_API_LOG'), "process.env['GEMINI_NEXT_GEN_API_LOG']", this)) !== null && _g !== void 0 ? _g : defaultLogLevel; + this.fetchOptions = options.fetchOptions; + this.maxRetries = (_h = options.maxRetries) !== null && _h !== void 0 ? _h : 2; + this.fetch = (_j = options.fetch) !== null && _j !== void 0 ? _j : getDefaultFetch(); + this.encoder = FallbackEncoder; + this._options = options; + this.apiKey = apiKey; + this.apiVersion = apiVersion; + this.clientAdapter = options.clientAdapter; + } + /** + * Create a new client instance re-using the same options given to the current client with optional overriding. + */ + withOptions(options) { + const client = new this.constructor(Object.assign(Object.assign(Object.assign({}, this._options), { baseURL: this.baseURL, maxRetries: this.maxRetries, timeout: this.timeout, logger: this.logger, logLevel: this.logLevel, fetch: this.fetch, fetchOptions: this.fetchOptions, apiKey: this.apiKey, apiVersion: this.apiVersion }), options)); + return client; + } + /** + * Check whether the base URL is set to its default. + */ + baseURLOverridden() { + return this.baseURL !== 'https://generativelanguage.googleapis.com'; + } + defaultQuery() { + return this._options.defaultQuery; + } + validateHeaders({ values, nulls }) { + // The headers object handles case insensitivity. + if (values.has('authorization') || values.has('x-goog-api-key')) { + return; + } + if (this.apiKey && values.get('x-goog-api-key')) { + return; + } + if (nulls.has('x-goog-api-key')) { + return; + } + throw new Error('Could not resolve authentication method. Expected the apiKey to be set. Or for the "x-goog-api-key" headers to be explicitly omitted'); + } + async authHeaders(opts) { + const existingHeaders = buildHeaders([opts.headers]); + if (existingHeaders.values.has('authorization') || existingHeaders.values.has('x-goog-api-key')) { + return undefined; + } + if (this.apiKey) { + return buildHeaders([{ 'x-goog-api-key': this.apiKey }]); + } + if (this.clientAdapter.isVertexAI()) { + return buildHeaders([await this.clientAdapter.getAuthHeaders()]); + } + return undefined; + } + /** + * Basic re-implementation of `qs.stringify` for primitive types. + */ + stringifyQuery(query) { + return Object.entries(query) + .filter(([_, value]) => typeof value !== 'undefined') + .map(([key, value]) => { + if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { + return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`; + } + if (value === null) { + return `${encodeURIComponent(key)}=`; + } + throw new GeminiNextGenAPIClientError(`Cannot stringify type ${typeof value}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`); + }) + .join('&'); + } + getUserAgent() { + return `${this.constructor.name}/JS ${VERSION}`; + } + defaultIdempotencyKey() { + return `stainless-node-retry-${uuid4()}`; + } + makeStatusError(status, error, message, headers) { + return APIError.generate(status, error, message, headers); + } + buildURL(path, query, defaultBaseURL) { + const baseURL = (!this.baseURLOverridden() && defaultBaseURL) || this.baseURL; + const url = isAbsoluteURL(path) ? + new URL(path) + : new URL(baseURL + (baseURL.endsWith('/') && path.startsWith('/') ? path.slice(1) : path)); + const defaultQuery = this.defaultQuery(); + if (!isEmptyObj(defaultQuery)) { + query = Object.assign(Object.assign({}, defaultQuery), query); + } + if (typeof query === 'object' && query && !Array.isArray(query)) { + url.search = this.stringifyQuery(query); + } + return url.toString(); + } + /** + * Used as a callback for mutating the given `FinalRequestOptions` object. + + */ + async prepareOptions(options) { + if (this.clientAdapter && + this.clientAdapter.isVertexAI() && + !options.path.startsWith(`/${this.apiVersion}/projects/`)) { + const oldPath = options.path.slice(this.apiVersion.length + 1); + options.path = `/${this.apiVersion}/projects/${this.clientAdapter.getProject()}/locations/${this.clientAdapter.getLocation()}${oldPath}`; + } + } + /** + * Used as a callback for mutating the given `RequestInit` object. + * + * This is useful for cases where you want to add certain headers based off of + * the request properties, e.g. `method` or `url`. + */ + async prepareRequest(request, { url, options }) { } + get(path, opts) { + return this.methodRequest('get', path, opts); + } + post(path, opts) { + return this.methodRequest('post', path, opts); + } + patch(path, opts) { + return this.methodRequest('patch', path, opts); + } + put(path, opts) { + return this.methodRequest('put', path, opts); + } + delete(path, opts) { + return this.methodRequest('delete', path, opts); + } + methodRequest(method, path, opts) { + return this.request(Promise.resolve(opts).then((opts) => { + return Object.assign({ method, path }, opts); + })); + } + request(options, remainingRetries = null) { + return new APIPromise(this, this.makeRequest(options, remainingRetries, undefined)); + } + async makeRequest(optionsInput, retriesRemaining, retryOfRequestLogID) { + var _b, _c, _d; + const options = await optionsInput; + const maxRetries = (_b = options.maxRetries) !== null && _b !== void 0 ? _b : this.maxRetries; + if (retriesRemaining == null) { + retriesRemaining = maxRetries; + } + await this.prepareOptions(options); + const { req, url, timeout } = await this.buildRequest(options, { + retryCount: maxRetries - retriesRemaining, + }); + await this.prepareRequest(req, { url, options }); + /** Not an API request ID, just for correlating local log entries. */ + const requestLogID = 'log_' + ((Math.random() * (1 << 24)) | 0).toString(16).padStart(6, '0'); + const retryLogStr = retryOfRequestLogID === undefined ? '' : `, retryOf: ${retryOfRequestLogID}`; + const startTime = Date.now(); + loggerFor(this).debug(`[${requestLogID}] sending request`, formatRequestDetails({ + retryOfRequestLogID, + method: options.method, + url, + options, + headers: req.headers, + })); + if ((_c = options.signal) === null || _c === void 0 ? void 0 : _c.aborted) { + throw new APIUserAbortError(); + } + const controller = new AbortController(); + const response = await this.fetchWithTimeout(url, req, timeout, controller).catch(castToError); + const headersTime = Date.now(); + if (response instanceof globalThis.Error) { + const retryMessage = `retrying, ${retriesRemaining} attempts remaining`; + if ((_d = options.signal) === null || _d === void 0 ? void 0 : _d.aborted) { + throw new APIUserAbortError(); + } + // detect native connection timeout errors + // deno throws "TypeError: error sending request for url (https://example/): client error (Connect): tcp connect error: Operation timed out (os error 60): Operation timed out (os error 60)" + // undici throws "TypeError: fetch failed" with cause "ConnectTimeoutError: Connect Timeout Error (attempted address: example:443, timeout: 1ms)" + // others do not provide enough information to distinguish timeouts from other connection errors + const isTimeout = isAbortError(response) || + /timed? ?out/i.test(String(response) + ('cause' in response ? String(response.cause) : '')); + if (retriesRemaining) { + loggerFor(this).info(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - ${retryMessage}`); + loggerFor(this).debug(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (${retryMessage})`, formatRequestDetails({ + retryOfRequestLogID, + url, + durationMs: headersTime - startTime, + message: response.message, + })); + return this.retryRequest(options, retriesRemaining, retryOfRequestLogID !== null && retryOfRequestLogID !== void 0 ? retryOfRequestLogID : requestLogID); + } + loggerFor(this).info(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - error; no more retries left`); + loggerFor(this).debug(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (error; no more retries left)`, formatRequestDetails({ + retryOfRequestLogID, + url, + durationMs: headersTime - startTime, + message: response.message, + })); + if (isTimeout) { + throw new APIConnectionTimeoutError(); + } + throw new APIConnectionError({ cause: response }); + } + const responseInfo = `[${requestLogID}${retryLogStr}] ${req.method} ${url} ${response.ok ? 'succeeded' : 'failed'} with status ${response.status} in ${headersTime - startTime}ms`; + if (!response.ok) { + const shouldRetry = await this.shouldRetry(response); + if (retriesRemaining && shouldRetry) { + const retryMessage = `retrying, ${retriesRemaining} attempts remaining`; + // We don't need the body of this response. + await CancelReadableStream(response.body); + loggerFor(this).info(`${responseInfo} - ${retryMessage}`); + loggerFor(this).debug(`[${requestLogID}] response error (${retryMessage})`, formatRequestDetails({ + retryOfRequestLogID, + url: response.url, + status: response.status, + headers: response.headers, + durationMs: headersTime - startTime, + })); + return this.retryRequest(options, retriesRemaining, retryOfRequestLogID !== null && retryOfRequestLogID !== void 0 ? retryOfRequestLogID : requestLogID, response.headers); + } + const retryMessage = shouldRetry ? `error; no more retries left` : `error; not retryable`; + loggerFor(this).info(`${responseInfo} - ${retryMessage}`); + const errText = await response.text().catch((err) => castToError(err).message); + const errJSON = safeJSON(errText); + const errMessage = errJSON ? undefined : errText; + loggerFor(this).debug(`[${requestLogID}] response error (${retryMessage})`, formatRequestDetails({ + retryOfRequestLogID, + url: response.url, + status: response.status, + headers: response.headers, + message: errMessage, + durationMs: Date.now() - startTime, + })); + // @ts-ignore + const err = this.makeStatusError(response.status, errJSON, errMessage, response.headers); + throw err; + } + loggerFor(this).info(responseInfo); + loggerFor(this).debug(`[${requestLogID}] response start`, formatRequestDetails({ + retryOfRequestLogID, + url: response.url, + status: response.status, + headers: response.headers, + durationMs: headersTime - startTime, + })); + return { response, options, controller, requestLogID, retryOfRequestLogID, startTime }; + } + async fetchWithTimeout(url, init, ms, controller) { + const _b = init || {}, { signal, method } = _b, options = __rest(_b, ["signal", "method"]); + const abort = this._makeAbort(controller); + if (signal) + signal.addEventListener('abort', abort, { once: true }); + const timeout = setTimeout(abort, ms); + const isReadableBody = (globalThis.ReadableStream && options.body instanceof globalThis.ReadableStream) || + (typeof options.body === 'object' && options.body !== null && Symbol.asyncIterator in options.body); + const fetchOptions = Object.assign(Object.assign(Object.assign({ signal: controller.signal }, (isReadableBody ? { duplex: 'half' } : {})), { method: 'GET' }), options); + if (method) { + // Custom methods like 'patch' need to be uppercased + // See https://github.com/nodejs/undici/issues/2294 + fetchOptions.method = method.toUpperCase(); + } + try { + // use undefined this binding; fetch errors if bound to something else in browser/cloudflare + return await this.fetch.call(undefined, url, fetchOptions); + } + finally { + clearTimeout(timeout); + } + } + async shouldRetry(response) { + // Note this is not a standard header. + const shouldRetryHeader = response.headers.get('x-should-retry'); + // If the server explicitly says whether or not to retry, obey. + if (shouldRetryHeader === 'true') + return true; + if (shouldRetryHeader === 'false') + return false; + // Retry on request timeouts. + if (response.status === 408) + return true; + // Retry on lock timeouts. + if (response.status === 409) + return true; + // Retry on rate limits. + if (response.status === 429) + return true; + // Retry internal errors. + if (response.status >= 500) + return true; + return false; + } + async retryRequest(options, retriesRemaining, requestLogID, responseHeaders) { + var _b; + let timeoutMillis; + // Note the `retry-after-ms` header may not be standard, but is a good idea and we'd like proactive support for it. + const retryAfterMillisHeader = responseHeaders === null || responseHeaders === void 0 ? void 0 : responseHeaders.get('retry-after-ms'); + if (retryAfterMillisHeader) { + const timeoutMs = parseFloat(retryAfterMillisHeader); + if (!Number.isNaN(timeoutMs)) { + timeoutMillis = timeoutMs; + } + } + // About the Retry-After header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After + const retryAfterHeader = responseHeaders === null || responseHeaders === void 0 ? void 0 : responseHeaders.get('retry-after'); + if (retryAfterHeader && !timeoutMillis) { + const timeoutSeconds = parseFloat(retryAfterHeader); + if (!Number.isNaN(timeoutSeconds)) { + timeoutMillis = timeoutSeconds * 1000; + } + else { + timeoutMillis = Date.parse(retryAfterHeader) - Date.now(); + } + } + // If the API asks us to wait a certain amount of time (and it's a reasonable amount), + // just do what it says, but otherwise calculate a default + if (!(timeoutMillis && 0 <= timeoutMillis && timeoutMillis < 60 * 1000)) { + const maxRetries = (_b = options.maxRetries) !== null && _b !== void 0 ? _b : this.maxRetries; + timeoutMillis = this.calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries); + } + await sleep$1(timeoutMillis); + return this.makeRequest(options, retriesRemaining - 1, requestLogID); + } + calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries) { + const initialRetryDelay = 0.5; + const maxRetryDelay = 8.0; + const numRetries = maxRetries - retriesRemaining; + // Apply exponential backoff, but not more than the max. + const sleepSeconds = Math.min(initialRetryDelay * Math.pow(2, numRetries), maxRetryDelay); + // Apply some jitter, take up to at most 25 percent of the retry time. + const jitter = 1 - Math.random() * 0.25; + return sleepSeconds * jitter * 1000; + } + async buildRequest(inputOptions, { retryCount = 0 } = {}) { + var _b, _c, _d; + const options = Object.assign({}, inputOptions); + const { method, path, query, defaultBaseURL } = options; + const url = this.buildURL(path, query, defaultBaseURL); + if ('timeout' in options) + validatePositiveInteger('timeout', options.timeout); + options.timeout = (_b = options.timeout) !== null && _b !== void 0 ? _b : this.timeout; + const { bodyHeaders, body } = this.buildBody({ options }); + const reqHeaders = await this.buildHeaders({ options: inputOptions, method, bodyHeaders, retryCount }); + const req = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ method, headers: reqHeaders }, (options.signal && { signal: options.signal })), (globalThis.ReadableStream && + body instanceof globalThis.ReadableStream && { duplex: 'half' })), (body && { body })), ((_c = this.fetchOptions) !== null && _c !== void 0 ? _c : {})), ((_d = options.fetchOptions) !== null && _d !== void 0 ? _d : {})); + return { req, url, timeout: options.timeout }; + } + async buildHeaders({ options, method, bodyHeaders, retryCount, }) { + let idempotencyHeaders = {}; + if (this.idempotencyHeader && method !== 'get') { + if (!options.idempotencyKey) + options.idempotencyKey = this.defaultIdempotencyKey(); + idempotencyHeaders[this.idempotencyHeader] = options.idempotencyKey; + } + const authHeaders = await this.authHeaders(options); + let headers = buildHeaders([ + idempotencyHeaders, + Object.assign(Object.assign({ Accept: 'application/json', 'User-Agent': this.getUserAgent(), 'X-Stainless-Retry-Count': String(retryCount) }, (options.timeout ? { 'X-Stainless-Timeout': String(Math.trunc(options.timeout / 1000)) } : {})), getPlatformHeaders()), + this._options.defaultHeaders, + bodyHeaders, + options.headers, + authHeaders, + ]); + this.validateHeaders(headers); + return headers.values; + } + _makeAbort(controller) { + // note: we can't just inline this method inside `fetchWithTimeout()` because then the closure + // would capture all request options, and cause a memory leak. + return () => controller.abort(); + } + buildBody({ options: { body, headers: rawHeaders } }) { + if (!body) { + return { bodyHeaders: undefined, body: undefined }; + } + const headers = buildHeaders([rawHeaders]); + if ( + // Pass raw type verbatim + ArrayBuffer.isView(body) || + body instanceof ArrayBuffer || + body instanceof DataView || + (typeof body === 'string' && + // Preserve legacy string encoding behavior for now + headers.values.has('content-type')) || + // `Blob` is superset of `File` + (globalThis.Blob && body instanceof globalThis.Blob) || + // `FormData` -> `multipart/form-data` + body instanceof FormData || + // `URLSearchParams` -> `application/x-www-form-urlencoded` + body instanceof URLSearchParams || + // Send chunked stream (each chunk has own `length`) + (globalThis.ReadableStream && body instanceof globalThis.ReadableStream)) { + return { bodyHeaders: undefined, body: body }; + } + else if (typeof body === 'object' && + (Symbol.asyncIterator in body || + (Symbol.iterator in body && 'next' in body && typeof body.next === 'function'))) { + return { bodyHeaders: undefined, body: ReadableStreamFrom(body) }; + } + else { + return this.encoder({ body, headers }); + } + } +} +BaseGeminiNextGenAPIClient.DEFAULT_TIMEOUT = 60000; // 1 minute +/** + * API Client for interfacing with the Gemini Next Gen API API. + */ +class GeminiNextGenAPIClient extends BaseGeminiNextGenAPIClient { + constructor() { + super(...arguments); + this.interactions = new Interactions(this); + } +} +_a = GeminiNextGenAPIClient; +GeminiNextGenAPIClient.GeminiNextGenAPIClient = _a; +GeminiNextGenAPIClient.GeminiNextGenAPIClientError = GeminiNextGenAPIClientError; +GeminiNextGenAPIClient.APIError = APIError; +GeminiNextGenAPIClient.APIConnectionError = APIConnectionError; +GeminiNextGenAPIClient.APIConnectionTimeoutError = APIConnectionTimeoutError; +GeminiNextGenAPIClient.APIUserAbortError = APIUserAbortError; +GeminiNextGenAPIClient.NotFoundError = NotFoundError; +GeminiNextGenAPIClient.ConflictError = ConflictError; +GeminiNextGenAPIClient.RateLimitError = RateLimitError; +GeminiNextGenAPIClient.BadRequestError = BadRequestError; +GeminiNextGenAPIClient.AuthenticationError = AuthenticationError; +GeminiNextGenAPIClient.InternalServerError = InternalServerError; +GeminiNextGenAPIClient.PermissionDeniedError = PermissionDeniedError; +GeminiNextGenAPIClient.UnprocessableEntityError = UnprocessableEntityError; +GeminiNextGenAPIClient.toFile = toFile; +GeminiNextGenAPIClient.Interactions = Interactions; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const GOOGLE_API_KEY_HEADER = 'x-goog-api-key'; +const REQUIRED_VERTEX_AI_SCOPE = 'https://www.googleapis.com/auth/cloud-platform'; +class NodeAuth { + constructor(opts) { + if (opts.apiKey !== undefined) { + this.apiKey = opts.apiKey; + return; + } + const vertexAuthOptions = buildGoogleAuthOptions(opts.googleAuthOptions); + this.googleAuth = new googleAuthLibrary.GoogleAuth(vertexAuthOptions); + } + async addAuthHeaders(headers, url) { + if (this.apiKey !== undefined) { + if (this.apiKey.startsWith('auth_tokens/')) { + throw new Error('Ephemeral tokens are only supported by the live API.'); + } + this.addKeyHeader(headers); + return; + } + return this.addGoogleAuthHeaders(headers, url); + } + addKeyHeader(headers) { + if (headers.get(GOOGLE_API_KEY_HEADER) !== null) { + return; + } + if (this.apiKey === undefined) { + // This should never happen, this method is only called + // when apiKey is set. + throw new Error('Trying to set API key header but apiKey is not set'); + } + headers.append(GOOGLE_API_KEY_HEADER, this.apiKey); + } + async addGoogleAuthHeaders(headers, url) { + if (this.googleAuth === undefined) { + // This should never happen, addGoogleAuthHeaders should only be + // called when there is no apiKey set and in these cases googleAuth + // is set. + throw new Error('Trying to set google-auth headers but googleAuth is unset'); + } + const authHeaders = await this.googleAuth.getRequestHeaders(url); + for (const [key, value] of authHeaders) { + if (headers.get(key) !== null) { + continue; + } + headers.append(key, value); + } + } +} +function buildGoogleAuthOptions(googleAuthOptions) { + let authOptions; + if (!googleAuthOptions) { + authOptions = { + scopes: [REQUIRED_VERTEX_AI_SCOPE], + }; + return authOptions; + } + else { + authOptions = googleAuthOptions; + if (!authOptions.scopes) { + authOptions.scopes = [REQUIRED_VERTEX_AI_SCOPE]; + return authOptions; + } + else if ((typeof authOptions.scopes === 'string' && + authOptions.scopes !== REQUIRED_VERTEX_AI_SCOPE) || + (Array.isArray(authOptions.scopes) && + authOptions.scopes.indexOf(REQUIRED_VERTEX_AI_SCOPE) < 0)) { + throw new Error(`Invalid auth scopes. Scopes must include: ${REQUIRED_VERTEX_AI_SCOPE}`); + } + return authOptions; + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class NodeDownloader { + async download(params, apiClient) { + if (params.downloadPath) { + const response = await downloadFile(params, apiClient); + if (response instanceof HttpResponse) { + const writer = fs.createWriteStream(params.downloadPath); + const body = node_stream.Readable.fromWeb(response.responseInternal.body); + body.pipe(writer); + await promises.finished(writer); + } + else { + try { + await fs$1.writeFile(params.downloadPath, response, { + encoding: 'base64', + }); + } + catch (error) { + throw new Error(`Failed to write file to ${params.downloadPath}: ${error}`); + } + } + } + } +} +async function downloadFile(params, apiClient) { + var _a, _b, _c; + const name = tFileName(params.file); + if (name !== undefined) { + return await apiClient.request({ + path: `files/${name}:download`, + httpMethod: 'GET', + queryParams: { + 'alt': 'media', + }, + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }); + } + else if (isGeneratedVideo(params.file)) { + const videoBytes = (_c = params.file.video) === null || _c === void 0 ? void 0 : _c.videoBytes; + if (typeof videoBytes === 'string') { + return videoBytes; + } + else { + throw new Error('Failed to download generated video, Uri or videoBytes not found.'); + } + } + else if (isVideo(params.file)) { + const videoBytes = params.file.videoBytes; + if (typeof videoBytes === 'string') { + return videoBytes; + } + else { + throw new Error('Failed to download video, Uri or videoBytes not found.'); + } + } + else { + throw new Error('Unsupported file type'); + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class NodeWebSocketFactory { + create(url, headers, callbacks) { + return new NodeWebSocket(url, headers, callbacks); + } +} +class NodeWebSocket { + constructor(url, headers, callbacks) { + this.url = url; + this.headers = headers; + this.callbacks = callbacks; + } + connect() { + this.ws = new NodeWs__namespace.WebSocket(this.url, { headers: this.headers }); + this.ws.onopen = this.callbacks.onopen; + this.ws.onerror = this.callbacks.onerror; + this.ws.onclose = this.callbacks.onclose; + this.ws.onmessage = this.callbacks.onmessage; + } + send(message) { + if (this.ws === undefined) { + throw new Error('WebSocket is not connected'); + } + this.ws.send(message); + } + close() { + if (this.ws === undefined) { + throw new Error('WebSocket is not connected'); + } + this.ws.close(); + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Code generated by the Google Gen AI SDK generator DO NOT EDIT. +function cancelTuningJobParametersToMldev(fromObject, _rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + return toObject; +} +function cancelTuningJobParametersToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + return toObject; +} +function cancelTuningJobResponseFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function cancelTuningJobResponseFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function createTuningJobConfigToMldev(fromObject, parentObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['validationDataset']) !== undefined) { + throw new Error('validationDataset parameter is not supported in Gemini API.'); + } + const fromTunedModelDisplayName = getValueByPath(fromObject, [ + 'tunedModelDisplayName', + ]); + if (parentObject !== undefined && fromTunedModelDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromTunedModelDisplayName); + } + if (getValueByPath(fromObject, ['description']) !== undefined) { + throw new Error('description parameter is not supported in Gemini API.'); + } + const fromEpochCount = getValueByPath(fromObject, ['epochCount']); + if (parentObject !== undefined && fromEpochCount != null) { + setValueByPath(parentObject, ['tuningTask', 'hyperparameters', 'epochCount'], fromEpochCount); + } + const fromLearningRateMultiplier = getValueByPath(fromObject, [ + 'learningRateMultiplier', + ]); + if (fromLearningRateMultiplier != null) { + setValueByPath(toObject, ['tuningTask', 'hyperparameters', 'learningRateMultiplier'], fromLearningRateMultiplier); + } + if (getValueByPath(fromObject, ['exportLastCheckpointOnly']) !== + undefined) { + throw new Error('exportLastCheckpointOnly parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['preTunedModelCheckpointId']) !== + undefined) { + throw new Error('preTunedModelCheckpointId parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['adapterSize']) !== undefined) { + throw new Error('adapterSize parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['tuningMode']) !== undefined) { + throw new Error('tuningMode parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['customBaseModel']) !== undefined) { + throw new Error('customBaseModel parameter is not supported in Gemini API.'); + } + const fromBatchSize = getValueByPath(fromObject, ['batchSize']); + if (parentObject !== undefined && fromBatchSize != null) { + setValueByPath(parentObject, ['tuningTask', 'hyperparameters', 'batchSize'], fromBatchSize); + } + const fromLearningRate = getValueByPath(fromObject, ['learningRate']); + if (parentObject !== undefined && fromLearningRate != null) { + setValueByPath(parentObject, ['tuningTask', 'hyperparameters', 'learningRate'], fromLearningRate); + } + if (getValueByPath(fromObject, ['labels']) !== undefined) { + throw new Error('labels parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['beta']) !== undefined) { + throw new Error('beta parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['baseTeacherModel']) !== undefined) { + throw new Error('baseTeacherModel parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['tunedTeacherModelSource']) !== undefined) { + throw new Error('tunedTeacherModelSource parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['sftLossWeightMultiplier']) !== undefined) { + throw new Error('sftLossWeightMultiplier parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['outputUri']) !== undefined) { + throw new Error('outputUri parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['encryptionSpec']) !== undefined) { + throw new Error('encryptionSpec parameter is not supported in Gemini API.'); + } + return toObject; +} +function createTuningJobConfigToVertex(fromObject, parentObject, rootObject) { + const toObject = {}; + let discriminatorValidationDataset = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorValidationDataset === undefined) { + discriminatorValidationDataset = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorValidationDataset === 'SUPERVISED_FINE_TUNING') { + const fromValidationDataset = getValueByPath(fromObject, [ + 'validationDataset', + ]); + if (parentObject !== undefined && fromValidationDataset != null) { + setValueByPath(parentObject, ['supervisedTuningSpec'], tuningValidationDatasetToVertex(fromValidationDataset)); + } + } + else if (discriminatorValidationDataset === 'PREFERENCE_TUNING') { + const fromValidationDataset = getValueByPath(fromObject, [ + 'validationDataset', + ]); + if (parentObject !== undefined && fromValidationDataset != null) { + setValueByPath(parentObject, ['preferenceOptimizationSpec'], tuningValidationDatasetToVertex(fromValidationDataset)); + } + } + else if (discriminatorValidationDataset === 'DISTILLATION') { + const fromValidationDataset = getValueByPath(fromObject, [ + 'validationDataset', + ]); + if (parentObject !== undefined && fromValidationDataset != null) { + setValueByPath(parentObject, ['distillationSpec'], tuningValidationDatasetToVertex(fromValidationDataset)); + } + } + const fromTunedModelDisplayName = getValueByPath(fromObject, [ + 'tunedModelDisplayName', + ]); + if (parentObject !== undefined && fromTunedModelDisplayName != null) { + setValueByPath(parentObject, ['tunedModelDisplayName'], fromTunedModelDisplayName); + } + const fromDescription = getValueByPath(fromObject, ['description']); + if (parentObject !== undefined && fromDescription != null) { + setValueByPath(parentObject, ['description'], fromDescription); + } + let discriminatorEpochCount = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorEpochCount === undefined) { + discriminatorEpochCount = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorEpochCount === 'SUPERVISED_FINE_TUNING') { + const fromEpochCount = getValueByPath(fromObject, ['epochCount']); + if (parentObject !== undefined && fromEpochCount != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'hyperParameters', 'epochCount'], fromEpochCount); + } + } + else if (discriminatorEpochCount === 'PREFERENCE_TUNING') { + const fromEpochCount = getValueByPath(fromObject, ['epochCount']); + if (parentObject !== undefined && fromEpochCount != null) { + setValueByPath(parentObject, ['preferenceOptimizationSpec', 'hyperParameters', 'epochCount'], fromEpochCount); + } + } + else if (discriminatorEpochCount === 'DISTILLATION') { + const fromEpochCount = getValueByPath(fromObject, ['epochCount']); + if (parentObject !== undefined && fromEpochCount != null) { + setValueByPath(parentObject, ['distillationSpec', 'hyperParameters', 'epochCount'], fromEpochCount); + } + } + let discriminatorLearningRateMultiplier = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorLearningRateMultiplier === undefined) { + discriminatorLearningRateMultiplier = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorLearningRateMultiplier === 'SUPERVISED_FINE_TUNING') { + const fromLearningRateMultiplier = getValueByPath(fromObject, [ + 'learningRateMultiplier', + ]); + if (parentObject !== undefined && fromLearningRateMultiplier != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'hyperParameters', 'learningRateMultiplier'], fromLearningRateMultiplier); + } + } + else if (discriminatorLearningRateMultiplier === 'PREFERENCE_TUNING') { + const fromLearningRateMultiplier = getValueByPath(fromObject, [ + 'learningRateMultiplier', + ]); + if (parentObject !== undefined && fromLearningRateMultiplier != null) { + setValueByPath(parentObject, [ + 'preferenceOptimizationSpec', + 'hyperParameters', + 'learningRateMultiplier', + ], fromLearningRateMultiplier); + } + } + else if (discriminatorLearningRateMultiplier === 'DISTILLATION') { + const fromLearningRateMultiplier = getValueByPath(fromObject, [ + 'learningRateMultiplier', + ]); + if (parentObject !== undefined && fromLearningRateMultiplier != null) { + setValueByPath(parentObject, ['distillationSpec', 'hyperParameters', 'learningRateMultiplier'], fromLearningRateMultiplier); + } + } + let discriminatorExportLastCheckpointOnly = getValueByPath(rootObject, ['config', 'method']); + if (discriminatorExportLastCheckpointOnly === undefined) { + discriminatorExportLastCheckpointOnly = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorExportLastCheckpointOnly === 'SUPERVISED_FINE_TUNING') { + const fromExportLastCheckpointOnly = getValueByPath(fromObject, [ + 'exportLastCheckpointOnly', + ]); + if (parentObject !== undefined && fromExportLastCheckpointOnly != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'exportLastCheckpointOnly'], fromExportLastCheckpointOnly); + } + } + else if (discriminatorExportLastCheckpointOnly === 'PREFERENCE_TUNING') { + const fromExportLastCheckpointOnly = getValueByPath(fromObject, [ + 'exportLastCheckpointOnly', + ]); + if (parentObject !== undefined && fromExportLastCheckpointOnly != null) { + setValueByPath(parentObject, ['preferenceOptimizationSpec', 'exportLastCheckpointOnly'], fromExportLastCheckpointOnly); + } + } + else if (discriminatorExportLastCheckpointOnly === 'DISTILLATION') { + const fromExportLastCheckpointOnly = getValueByPath(fromObject, [ + 'exportLastCheckpointOnly', + ]); + if (parentObject !== undefined && fromExportLastCheckpointOnly != null) { + setValueByPath(parentObject, ['distillationSpec', 'exportLastCheckpointOnly'], fromExportLastCheckpointOnly); + } + } + let discriminatorAdapterSize = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorAdapterSize === undefined) { + discriminatorAdapterSize = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorAdapterSize === 'SUPERVISED_FINE_TUNING') { + const fromAdapterSize = getValueByPath(fromObject, ['adapterSize']); + if (parentObject !== undefined && fromAdapterSize != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'hyperParameters', 'adapterSize'], fromAdapterSize); + } + } + else if (discriminatorAdapterSize === 'PREFERENCE_TUNING') { + const fromAdapterSize = getValueByPath(fromObject, ['adapterSize']); + if (parentObject !== undefined && fromAdapterSize != null) { + setValueByPath(parentObject, ['preferenceOptimizationSpec', 'hyperParameters', 'adapterSize'], fromAdapterSize); + } + } + else if (discriminatorAdapterSize === 'DISTILLATION') { + const fromAdapterSize = getValueByPath(fromObject, ['adapterSize']); + if (parentObject !== undefined && fromAdapterSize != null) { + setValueByPath(parentObject, ['distillationSpec', 'hyperParameters', 'adapterSize'], fromAdapterSize); + } + } + let discriminatorTuningMode = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorTuningMode === undefined) { + discriminatorTuningMode = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorTuningMode === 'SUPERVISED_FINE_TUNING') { + const fromTuningMode = getValueByPath(fromObject, ['tuningMode']); + if (parentObject !== undefined && fromTuningMode != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'tuningMode'], fromTuningMode); + } + } + const fromCustomBaseModel = getValueByPath(fromObject, [ + 'customBaseModel', + ]); + if (parentObject !== undefined && fromCustomBaseModel != null) { + setValueByPath(parentObject, ['customBaseModel'], fromCustomBaseModel); + } + let discriminatorBatchSize = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorBatchSize === undefined) { + discriminatorBatchSize = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorBatchSize === 'SUPERVISED_FINE_TUNING') { + const fromBatchSize = getValueByPath(fromObject, ['batchSize']); + if (parentObject !== undefined && fromBatchSize != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'hyperParameters', 'batchSize'], fromBatchSize); + } + } + let discriminatorLearningRate = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorLearningRate === undefined) { + discriminatorLearningRate = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorLearningRate === 'SUPERVISED_FINE_TUNING') { + const fromLearningRate = getValueByPath(fromObject, [ + 'learningRate', + ]); + if (parentObject !== undefined && fromLearningRate != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'hyperParameters', 'learningRate'], fromLearningRate); + } + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (parentObject !== undefined && fromLabels != null) { + setValueByPath(parentObject, ['labels'], fromLabels); + } + const fromBeta = getValueByPath(fromObject, ['beta']); + if (parentObject !== undefined && fromBeta != null) { + setValueByPath(parentObject, ['preferenceOptimizationSpec', 'hyperParameters', 'beta'], fromBeta); + } + const fromBaseTeacherModel = getValueByPath(fromObject, [ + 'baseTeacherModel', + ]); + if (parentObject !== undefined && fromBaseTeacherModel != null) { + setValueByPath(parentObject, ['distillationSpec', 'baseTeacherModel'], fromBaseTeacherModel); + } + const fromTunedTeacherModelSource = getValueByPath(fromObject, [ + 'tunedTeacherModelSource', + ]); + if (parentObject !== undefined && fromTunedTeacherModelSource != null) { + setValueByPath(parentObject, ['distillationSpec', 'tunedTeacherModelSource'], fromTunedTeacherModelSource); + } + const fromSftLossWeightMultiplier = getValueByPath(fromObject, [ + 'sftLossWeightMultiplier', + ]); + if (parentObject !== undefined && fromSftLossWeightMultiplier != null) { + setValueByPath(parentObject, ['distillationSpec', 'hyperParameters', 'sftLossWeightMultiplier'], fromSftLossWeightMultiplier); + } + const fromOutputUri = getValueByPath(fromObject, ['outputUri']); + if (parentObject !== undefined && fromOutputUri != null) { + setValueByPath(parentObject, ['outputUri'], fromOutputUri); + } + const fromEncryptionSpec = getValueByPath(fromObject, [ + 'encryptionSpec', + ]); + if (parentObject !== undefined && fromEncryptionSpec != null) { + setValueByPath(parentObject, ['encryptionSpec'], fromEncryptionSpec); + } + return toObject; +} +function createTuningJobParametersPrivateToMldev(fromObject, rootObject) { + const toObject = {}; + const fromBaseModel = getValueByPath(fromObject, ['baseModel']); + if (fromBaseModel != null) { + setValueByPath(toObject, ['baseModel'], fromBaseModel); + } + const fromPreTunedModel = getValueByPath(fromObject, [ + 'preTunedModel', + ]); + if (fromPreTunedModel != null) { + setValueByPath(toObject, ['preTunedModel'], fromPreTunedModel); + } + const fromTrainingDataset = getValueByPath(fromObject, [ + 'trainingDataset', + ]); + if (fromTrainingDataset != null) { + tuningDatasetToMldev(fromTrainingDataset); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createTuningJobConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function createTuningJobParametersPrivateToVertex(fromObject, rootObject) { + const toObject = {}; + const fromBaseModel = getValueByPath(fromObject, ['baseModel']); + if (fromBaseModel != null) { + setValueByPath(toObject, ['baseModel'], fromBaseModel); + } + const fromPreTunedModel = getValueByPath(fromObject, [ + 'preTunedModel', + ]); + if (fromPreTunedModel != null) { + setValueByPath(toObject, ['preTunedModel'], fromPreTunedModel); + } + const fromTrainingDataset = getValueByPath(fromObject, [ + 'trainingDataset', + ]); + if (fromTrainingDataset != null) { + tuningDatasetToVertex(fromTrainingDataset, toObject, rootObject); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createTuningJobConfigToVertex(fromConfig, toObject, rootObject); + } + return toObject; +} +function getTuningJobParametersToMldev(fromObject, _rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + return toObject; +} +function getTuningJobParametersToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + return toObject; +} +function listTuningJobsConfigToMldev(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + const fromFilter = getValueByPath(fromObject, ['filter']); + if (parentObject !== undefined && fromFilter != null) { + setValueByPath(parentObject, ['_query', 'filter'], fromFilter); + } + return toObject; +} +function listTuningJobsConfigToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + const fromFilter = getValueByPath(fromObject, ['filter']); + if (parentObject !== undefined && fromFilter != null) { + setValueByPath(parentObject, ['_query', 'filter'], fromFilter); + } + return toObject; +} +function listTuningJobsParametersToMldev(fromObject, rootObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listTuningJobsConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function listTuningJobsParametersToVertex(fromObject, rootObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listTuningJobsConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function listTuningJobsResponseFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromTuningJobs = getValueByPath(fromObject, ['tunedModels']); + if (fromTuningJobs != null) { + let transformedList = fromTuningJobs; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return tuningJobFromMldev(item); + }); + } + setValueByPath(toObject, ['tuningJobs'], transformedList); + } + return toObject; +} +function listTuningJobsResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromTuningJobs = getValueByPath(fromObject, ['tuningJobs']); + if (fromTuningJobs != null) { + let transformedList = fromTuningJobs; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return tuningJobFromVertex(item); + }); + } + setValueByPath(toObject, ['tuningJobs'], transformedList); + } + return toObject; +} +function tunedModelFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['name']); + if (fromModel != null) { + setValueByPath(toObject, ['model'], fromModel); + } + const fromEndpoint = getValueByPath(fromObject, ['name']); + if (fromEndpoint != null) { + setValueByPath(toObject, ['endpoint'], fromEndpoint); + } + return toObject; +} +function tuningDatasetToMldev(fromObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['gcsUri']) !== undefined) { + throw new Error('gcsUri parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['vertexDatasetResource']) !== undefined) { + throw new Error('vertexDatasetResource parameter is not supported in Gemini API.'); + } + const fromExamples = getValueByPath(fromObject, ['examples']); + if (fromExamples != null) { + let transformedList = fromExamples; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['examples', 'examples'], transformedList); + } + return toObject; +} +function tuningDatasetToVertex(fromObject, parentObject, rootObject) { + const toObject = {}; + let discriminatorGcsUri = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorGcsUri === undefined) { + discriminatorGcsUri = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorGcsUri === 'SUPERVISED_FINE_TUNING') { + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (parentObject !== undefined && fromGcsUri != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'trainingDatasetUri'], fromGcsUri); + } + } + else if (discriminatorGcsUri === 'PREFERENCE_TUNING') { + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (parentObject !== undefined && fromGcsUri != null) { + setValueByPath(parentObject, ['preferenceOptimizationSpec', 'trainingDatasetUri'], fromGcsUri); + } + } + else if (discriminatorGcsUri === 'DISTILLATION') { + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (parentObject !== undefined && fromGcsUri != null) { + setValueByPath(parentObject, ['distillationSpec', 'promptDatasetUri'], fromGcsUri); + } + } + let discriminatorVertexDatasetResource = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorVertexDatasetResource === undefined) { + discriminatorVertexDatasetResource = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorVertexDatasetResource === 'SUPERVISED_FINE_TUNING') { + const fromVertexDatasetResource = getValueByPath(fromObject, [ + 'vertexDatasetResource', + ]); + if (parentObject !== undefined && fromVertexDatasetResource != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'trainingDatasetUri'], fromVertexDatasetResource); + } + } + else if (discriminatorVertexDatasetResource === 'PREFERENCE_TUNING') { + const fromVertexDatasetResource = getValueByPath(fromObject, [ + 'vertexDatasetResource', + ]); + if (parentObject !== undefined && fromVertexDatasetResource != null) { + setValueByPath(parentObject, ['preferenceOptimizationSpec', 'trainingDatasetUri'], fromVertexDatasetResource); + } + } + else if (discriminatorVertexDatasetResource === 'DISTILLATION') { + const fromVertexDatasetResource = getValueByPath(fromObject, [ + 'vertexDatasetResource', + ]); + if (parentObject !== undefined && fromVertexDatasetResource != null) { + setValueByPath(parentObject, ['distillationSpec', 'promptDatasetUri'], fromVertexDatasetResource); + } + } + if (getValueByPath(fromObject, ['examples']) !== undefined) { + throw new Error('examples parameter is not supported in Vertex AI.'); + } + return toObject; +} +function tuningJobFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromState = getValueByPath(fromObject, ['state']); + if (fromState != null) { + setValueByPath(toObject, ['state'], tTuningJobStatus(fromState)); + } + const fromCreateTime = getValueByPath(fromObject, ['createTime']); + if (fromCreateTime != null) { + setValueByPath(toObject, ['createTime'], fromCreateTime); + } + const fromStartTime = getValueByPath(fromObject, [ + 'tuningTask', + 'startTime', + ]); + if (fromStartTime != null) { + setValueByPath(toObject, ['startTime'], fromStartTime); + } + const fromEndTime = getValueByPath(fromObject, [ + 'tuningTask', + 'completeTime', + ]); + if (fromEndTime != null) { + setValueByPath(toObject, ['endTime'], fromEndTime); + } + const fromUpdateTime = getValueByPath(fromObject, ['updateTime']); + if (fromUpdateTime != null) { + setValueByPath(toObject, ['updateTime'], fromUpdateTime); + } + const fromDescription = getValueByPath(fromObject, ['description']); + if (fromDescription != null) { + setValueByPath(toObject, ['description'], fromDescription); + } + const fromBaseModel = getValueByPath(fromObject, ['baseModel']); + if (fromBaseModel != null) { + setValueByPath(toObject, ['baseModel'], fromBaseModel); + } + const fromTunedModel = getValueByPath(fromObject, ['_self']); + if (fromTunedModel != null) { + setValueByPath(toObject, ['tunedModel'], tunedModelFromMldev(fromTunedModel)); + } + return toObject; +} +function tuningJobFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromState = getValueByPath(fromObject, ['state']); + if (fromState != null) { + setValueByPath(toObject, ['state'], tTuningJobStatus(fromState)); + } + const fromCreateTime = getValueByPath(fromObject, ['createTime']); + if (fromCreateTime != null) { + setValueByPath(toObject, ['createTime'], fromCreateTime); + } + const fromStartTime = getValueByPath(fromObject, ['startTime']); + if (fromStartTime != null) { + setValueByPath(toObject, ['startTime'], fromStartTime); + } + const fromEndTime = getValueByPath(fromObject, ['endTime']); + if (fromEndTime != null) { + setValueByPath(toObject, ['endTime'], fromEndTime); + } + const fromUpdateTime = getValueByPath(fromObject, ['updateTime']); + if (fromUpdateTime != null) { + setValueByPath(toObject, ['updateTime'], fromUpdateTime); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromDescription = getValueByPath(fromObject, ['description']); + if (fromDescription != null) { + setValueByPath(toObject, ['description'], fromDescription); + } + const fromBaseModel = getValueByPath(fromObject, ['baseModel']); + if (fromBaseModel != null) { + setValueByPath(toObject, ['baseModel'], fromBaseModel); + } + const fromTunedModel = getValueByPath(fromObject, ['tunedModel']); + if (fromTunedModel != null) { + setValueByPath(toObject, ['tunedModel'], fromTunedModel); + } + const fromPreTunedModel = getValueByPath(fromObject, [ + 'preTunedModel', + ]); + if (fromPreTunedModel != null) { + setValueByPath(toObject, ['preTunedModel'], fromPreTunedModel); + } + const fromSupervisedTuningSpec = getValueByPath(fromObject, [ + 'supervisedTuningSpec', + ]); + if (fromSupervisedTuningSpec != null) { + setValueByPath(toObject, ['supervisedTuningSpec'], fromSupervisedTuningSpec); + } + const fromPreferenceOptimizationSpec = getValueByPath(fromObject, [ + 'preferenceOptimizationSpec', + ]); + if (fromPreferenceOptimizationSpec != null) { + setValueByPath(toObject, ['preferenceOptimizationSpec'], fromPreferenceOptimizationSpec); + } + const fromDistillationSpec = getValueByPath(fromObject, [ + 'distillationSpec', + ]); + if (fromDistillationSpec != null) { + setValueByPath(toObject, ['distillationSpec'], fromDistillationSpec); + } + const fromTuningDataStats = getValueByPath(fromObject, [ + 'tuningDataStats', + ]); + if (fromTuningDataStats != null) { + setValueByPath(toObject, ['tuningDataStats'], fromTuningDataStats); + } + const fromEncryptionSpec = getValueByPath(fromObject, [ + 'encryptionSpec', + ]); + if (fromEncryptionSpec != null) { + setValueByPath(toObject, ['encryptionSpec'], fromEncryptionSpec); + } + const fromPartnerModelTuningSpec = getValueByPath(fromObject, [ + 'partnerModelTuningSpec', + ]); + if (fromPartnerModelTuningSpec != null) { + setValueByPath(toObject, ['partnerModelTuningSpec'], fromPartnerModelTuningSpec); + } + const fromCustomBaseModel = getValueByPath(fromObject, [ + 'customBaseModel', + ]); + if (fromCustomBaseModel != null) { + setValueByPath(toObject, ['customBaseModel'], fromCustomBaseModel); + } + const fromExperiment = getValueByPath(fromObject, ['experiment']); + if (fromExperiment != null) { + setValueByPath(toObject, ['experiment'], fromExperiment); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (fromLabels != null) { + setValueByPath(toObject, ['labels'], fromLabels); + } + const fromOutputUri = getValueByPath(fromObject, ['outputUri']); + if (fromOutputUri != null) { + setValueByPath(toObject, ['outputUri'], fromOutputUri); + } + const fromPipelineJob = getValueByPath(fromObject, ['pipelineJob']); + if (fromPipelineJob != null) { + setValueByPath(toObject, ['pipelineJob'], fromPipelineJob); + } + const fromServiceAccount = getValueByPath(fromObject, [ + 'serviceAccount', + ]); + if (fromServiceAccount != null) { + setValueByPath(toObject, ['serviceAccount'], fromServiceAccount); + } + const fromTunedModelDisplayName = getValueByPath(fromObject, [ + 'tunedModelDisplayName', + ]); + if (fromTunedModelDisplayName != null) { + setValueByPath(toObject, ['tunedModelDisplayName'], fromTunedModelDisplayName); + } + const fromVeoTuningSpec = getValueByPath(fromObject, [ + 'veoTuningSpec', + ]); + if (fromVeoTuningSpec != null) { + setValueByPath(toObject, ['veoTuningSpec'], fromVeoTuningSpec); + } + return toObject; +} +function tuningOperationFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + return toObject; +} +function tuningValidationDatasetToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (fromGcsUri != null) { + setValueByPath(toObject, ['validationDatasetUri'], fromGcsUri); + } + const fromVertexDatasetResource = getValueByPath(fromObject, [ + 'vertexDatasetResource', + ]); + if (fromVertexDatasetResource != null) { + setValueByPath(toObject, ['validationDatasetUri'], fromVertexDatasetResource); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Tunings extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + /** + * Lists tuning jobs. + * + * @param params - The parameters for the list request. + * @return - A pager of tuning jobs. + * + * @example + * ```ts + * const tuningJobs = await ai.tunings.list({config: {'pageSize': 2}}); + * for await (const tuningJob of tuningJobs) { + * console.log(tuningJob); + * } + * ``` + */ + this.list = async (params = {}) => { + return new Pager(exports.PagedItem.PAGED_ITEM_TUNING_JOBS, (x) => this.listInternal(x), await this.listInternal(params), params); + }; + /** + * Gets a TuningJob. + * + * @param name - The resource name of the tuning job. + * @return - A TuningJob object. + * + * @experimental - The SDK's tuning implementation is experimental, and may + * change in future versions. + */ + this.get = async (params) => { + return await this.getInternal(params); + }; + /** + * Creates a supervised fine-tuning job. + * + * @param params - The parameters for the tuning job. + * @return - A TuningJob operation. + * + * @experimental - The SDK's tuning implementation is experimental, and may + * change in future versions. + */ + this.tune = async (params) => { + var _a; + if (this.apiClient.isVertexAI()) { + if (params.baseModel.startsWith('projects/')) { + const preTunedModel = { + tunedModelName: params.baseModel, + }; + if ((_a = params.config) === null || _a === void 0 ? void 0 : _a.preTunedModelCheckpointId) { + preTunedModel.checkpointId = params.config.preTunedModelCheckpointId; + } + const paramsPrivate = Object.assign(Object.assign({}, params), { preTunedModel: preTunedModel }); + paramsPrivate.baseModel = undefined; + return await this.tuneInternal(paramsPrivate); + } + else { + const paramsPrivate = Object.assign({}, params); + return await this.tuneInternal(paramsPrivate); + } + } + else { + const paramsPrivate = Object.assign({}, params); + const operation = await this.tuneMldevInternal(paramsPrivate); + let tunedModelName = ''; + if (operation['metadata'] !== undefined && + operation['metadata']['tunedModel'] !== undefined) { + tunedModelName = operation['metadata']['tunedModel']; + } + else if (operation['name'] !== undefined && + operation['name'].includes('/operations/')) { + tunedModelName = operation['name'].split('/operations/')[0]; + } + const tuningJob = { + name: tunedModelName, + state: exports.JobState.JOB_STATE_QUEUED, + }; + return tuningJob; + } + }; + } + async getInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = getTuningJobParametersToVertex(params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = tuningJobFromVertex(apiResponse); + return resp; + }); + } + else { + const body = getTuningJobParametersToMldev(params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = tuningJobFromMldev(apiResponse); + return resp; + }); + } + } + async listInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = listTuningJobsParametersToVertex(params); + path = formatMap('tuningJobs', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listTuningJobsResponseFromVertex(apiResponse); + const typedResp = new ListTuningJobsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = listTuningJobsParametersToMldev(params); + path = formatMap('tunedModels', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listTuningJobsResponseFromMldev(apiResponse); + const typedResp = new ListTuningJobsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Cancels a tuning job. + * + * @param params - The parameters for the cancel request. + * @return The empty response returned by the API. + * + * @example + * ```ts + * await ai.tunings.cancel({name: '...'}); // The server-generated resource name. + * ``` + */ + async cancel(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = cancelTuningJobParametersToVertex(params); + path = formatMap('{name}:cancel', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = cancelTuningJobResponseFromVertex(apiResponse); + const typedResp = new CancelTuningJobResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = cancelTuningJobParametersToMldev(params); + path = formatMap('{name}:cancel', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = cancelTuningJobResponseFromMldev(apiResponse); + const typedResp = new CancelTuningJobResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + async tuneInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = createTuningJobParametersPrivateToVertex(params, params); + path = formatMap('tuningJobs', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = tuningJobFromVertex(apiResponse); + return resp; + }); + } + else { + throw new Error('This method is only supported by the Vertex AI.'); + } + } + async tuneMldevInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = createTuningJobParametersPrivateToMldev(params); + path = formatMap('tunedModels', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = tuningOperationFromMldev(apiResponse); + return resp; + }); + } + } +} + +const MAX_CHUNK_SIZE = 1024 * 1024 * 8; // bytes +const MAX_RETRY_COUNT = 3; +const INITIAL_RETRY_DELAY_MS = 1000; +const DELAY_MULTIPLIER = 2; +const X_GOOG_UPLOAD_STATUS_HEADER_FIELD = 'x-goog-upload-status'; +async function uploadBlob(file, uploadUrl, apiClient) { + var _a; + const response = await uploadBlobInternal(file, uploadUrl, apiClient); + const responseJson = (await (response === null || response === void 0 ? void 0 : response.json())); + if (((_a = response === null || response === void 0 ? void 0 : response.headers) === null || _a === void 0 ? void 0 : _a[X_GOOG_UPLOAD_STATUS_HEADER_FIELD]) !== 'final') { + throw new Error('Failed to upload file: Upload status is not finalized.'); + } + return responseJson['file']; +} +async function uploadBlobToFileSearchStore(file, uploadUrl, apiClient) { + var _a; + const response = await uploadBlobInternal(file, uploadUrl, apiClient); + const responseJson = (await (response === null || response === void 0 ? void 0 : response.json())); + if (((_a = response === null || response === void 0 ? void 0 : response.headers) === null || _a === void 0 ? void 0 : _a[X_GOOG_UPLOAD_STATUS_HEADER_FIELD]) !== 'final') { + throw new Error('Failed to upload file: Upload status is not finalized.'); + } + const resp = uploadToFileSearchStoreOperationFromMldev(responseJson); + const typedResp = new UploadToFileSearchStoreOperation(); + Object.assign(typedResp, resp); + return typedResp; +} +async function uploadBlobInternal(file, uploadUrl, apiClient) { + var _a, _b; + let fileSize = 0; + let offset = 0; + let response = new HttpResponse(new Response()); + let uploadCommand = 'upload'; + fileSize = file.size; + while (offset < fileSize) { + const chunkSize = Math.min(MAX_CHUNK_SIZE, fileSize - offset); + const chunk = file.slice(offset, offset + chunkSize); + if (offset + chunkSize >= fileSize) { + uploadCommand += ', finalize'; + } + let retryCount = 0; + let currentDelayMs = INITIAL_RETRY_DELAY_MS; + while (retryCount < MAX_RETRY_COUNT) { + response = await apiClient.request({ + path: '', + body: chunk, + httpMethod: 'POST', + httpOptions: { + apiVersion: '', + baseUrl: uploadUrl, + headers: { + 'X-Goog-Upload-Command': uploadCommand, + 'X-Goog-Upload-Offset': String(offset), + 'Content-Length': String(chunkSize), + }, + }, + }); + if ((_a = response === null || response === void 0 ? void 0 : response.headers) === null || _a === void 0 ? void 0 : _a[X_GOOG_UPLOAD_STATUS_HEADER_FIELD]) { + break; + } + retryCount++; + await sleep(currentDelayMs); + currentDelayMs = currentDelayMs * DELAY_MULTIPLIER; + } + offset += chunkSize; + // The `x-goog-upload-status` header field can be `active`, `final` and + //`cancelled` in resposne. + if (((_b = response === null || response === void 0 ? void 0 : response.headers) === null || _b === void 0 ? void 0 : _b[X_GOOG_UPLOAD_STATUS_HEADER_FIELD]) !== 'active') { + break; + } + // TODO(b/401391430) Investigate why the upload status is not finalized + // even though all content has been uploaded. + if (fileSize <= offset) { + throw new Error('All content has been uploaded, but the upload status is not finalized.'); + } + } + return response; +} +async function getBlobStat(file) { + const fileStat = { size: file.size, type: file.type }; + return fileStat; +} +function sleep(ms) { + return new Promise((resolvePromise) => setTimeout(resolvePromise, ms)); +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class NodeUploader { + async stat(file) { + const fileStat = { size: 0, type: undefined }; + if (typeof file === 'string') { + const originalStat = await fs__namespace.stat(file); + fileStat.size = originalStat.size; + fileStat.type = this.inferMimeType(file); + return fileStat; + } + else { + return await getBlobStat(file); + } + } + async upload(file, uploadUrl, apiClient) { + if (typeof file === 'string') { + return await this.uploadFileFromPath(file, uploadUrl, apiClient); + } + else { + return uploadBlob(file, uploadUrl, apiClient); + } + } + async uploadToFileSearchStore(file, uploadUrl, apiClient) { + if (typeof file === 'string') { + return await this.uploadFileToFileSearchStoreFromPath(file, uploadUrl, apiClient); + } + else { + return uploadBlobToFileSearchStore(file, uploadUrl, apiClient); + } + } + /** + * Infers the MIME type of a file based on its extension. + * + * @param filePath The path to the file. + * @returns The MIME type of the file, or undefined if it cannot be inferred. + */ + inferMimeType(filePath) { + // Get the file extension. + const fileExtension = filePath.slice(filePath.lastIndexOf('.') + 1); + // Create a map of file extensions to MIME types. + const mimeTypes = { + 'aac': 'audio/aac', + 'abw': 'application/x-abiword', + 'arc': 'application/x-freearc', + 'avi': 'video/x-msvideo', + 'azw': 'application/vnd.amazon.ebook', + 'bin': 'application/octet-stream', + 'bmp': 'image/bmp', + 'bz': 'application/x-bzip', + 'bz2': 'application/x-bzip2', + 'csh': 'application/x-csh', + 'css': 'text/css', + 'csv': 'text/csv', + 'doc': 'application/msword', + 'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'eot': 'application/vnd.ms-fontobject', + 'epub': 'application/epub+zip', + 'gz': 'application/gzip', + 'gif': 'image/gif', + 'htm': 'text/html', + 'html': 'text/html', + 'ico': 'image/vnd.microsoft.icon', + 'ics': 'text/calendar', + 'jar': 'application/java-archive', + 'jpeg': 'image/jpeg', + 'jpg': 'image/jpeg', + 'js': 'text/javascript', + 'json': 'application/json', + 'jsonld': 'application/ld+json', + 'kml': 'application/vnd.google-earth.kml+xml', + 'kmz': 'application/vnd.google-earth.kmz+xml', + 'mjs': 'text/javascript', + 'mp3': 'audio/mpeg', + 'mp4': 'video/mp4', + 'mpeg': 'video/mpeg', + 'mpkg': 'application/vnd.apple.installer+xml', + 'odt': 'application/vnd.oasis.opendocument.text', + 'oga': 'audio/ogg', + 'ogv': 'video/ogg', + 'ogx': 'application/ogg', + 'opus': 'audio/opus', + 'otf': 'font/otf', + 'png': 'image/png', + 'pdf': 'application/pdf', + 'php': 'application/x-httpd-php', + 'ppt': 'application/vnd.ms-powerpoint', + 'pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + 'rar': 'application/vnd.rar', + 'rtf': 'application/rtf', + 'sh': 'application/x-sh', + 'svg': 'image/svg+xml', + 'swf': 'application/x-shockwave-flash', + 'tar': 'application/x-tar', + 'tif': 'image/tiff', + 'tiff': 'image/tiff', + 'ts': 'video/mp2t', + 'ttf': 'font/ttf', + 'txt': 'text/plain', + 'vsd': 'application/vnd.visio', + 'wav': 'audio/wav', + 'weba': 'audio/webm', + 'webm': 'video/webm', + 'webp': 'image/webp', + 'woff': 'font/woff', + 'woff2': 'font/woff2', + 'xhtml': 'application/xhtml+xml', + 'xls': 'application/vnd.ms-excel', + 'xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'xml': 'application/xml', + 'xul': 'application/vnd.mozilla.xul+xml', + 'zip': 'application/zip', + '3gp': 'video/3gpp', + '3g2': 'video/3gpp2', + '7z': 'application/x-7z-compressed', + }; + // Look up the MIME type based on the file extension. + const mimeType = mimeTypes[fileExtension.toLowerCase()]; + // Return the MIME type. + return mimeType; + } + async uploadFileFromPath(file, uploadUrl, apiClient) { + var _a; + const response = await this.uploadFileFromPathInternal(file, uploadUrl, apiClient); + const responseJson = (await (response === null || response === void 0 ? void 0 : response.json())); + if (((_a = response === null || response === void 0 ? void 0 : response.headers) === null || _a === void 0 ? void 0 : _a[X_GOOG_UPLOAD_STATUS_HEADER_FIELD]) !== 'final') { + throw new Error('Failed to upload file: Upload status is not finalized.'); + } + return responseJson['file']; + } + async uploadFileToFileSearchStoreFromPath(file, uploadUrl, apiClient) { + var _a; + const response = await this.uploadFileFromPathInternal(file, uploadUrl, apiClient); + const responseJson = (await (response === null || response === void 0 ? void 0 : response.json())); + if (((_a = response === null || response === void 0 ? void 0 : response.headers) === null || _a === void 0 ? void 0 : _a[X_GOOG_UPLOAD_STATUS_HEADER_FIELD]) !== 'final') { + throw new Error('Failed to upload file: Upload status is not finalized.'); + } + const resp = uploadToFileSearchStoreOperationFromMldev(responseJson); + const typedResp = new UploadToFileSearchStoreOperation(); + Object.assign(typedResp, resp); + return typedResp; + } + async uploadFileFromPathInternal(file, uploadUrl, apiClient) { + var _a, _b; + let fileSize = 0; + let offset = 0; + let response = new HttpResponse(new Response()); + let uploadCommand = 'upload'; + let fileHandle; + const fileName = path__namespace.basename(file); + try { + fileHandle = await fs__namespace.open(file, 'r'); + if (!fileHandle) { + throw new Error(`Failed to open file`); + } + fileSize = (await fileHandle.stat()).size; + while (offset < fileSize) { + const chunkSize = Math.min(MAX_CHUNK_SIZE, fileSize - offset); + if (offset + chunkSize >= fileSize) { + uploadCommand += ', finalize'; + } + const buffer = new Uint8Array(chunkSize); + const { bytesRead: bytesRead } = await fileHandle.read(buffer, 0, chunkSize, offset); + if (bytesRead !== chunkSize) { + throw new Error(`Failed to read ${chunkSize} bytes from file at offset ${offset}. bytes actually read: ${bytesRead}`); + } + const chunk = new Blob([buffer]); + let retryCount = 0; + let currentDelayMs = INITIAL_RETRY_DELAY_MS; + while (retryCount < MAX_RETRY_COUNT) { + response = await apiClient.request({ + path: '', + body: chunk, + httpMethod: 'POST', + httpOptions: { + apiVersion: '', + baseUrl: uploadUrl, + headers: { + 'X-Goog-Upload-Command': uploadCommand, + 'X-Goog-Upload-Offset': String(offset), + 'Content-Length': String(bytesRead), + 'X-Goog-Upload-File-Name': fileName, + }, + }, + }); + if ((_a = response === null || response === void 0 ? void 0 : response.headers) === null || _a === void 0 ? void 0 : _a[X_GOOG_UPLOAD_STATUS_HEADER_FIELD]) { + break; + } + retryCount++; + await sleep(currentDelayMs); + currentDelayMs = currentDelayMs * DELAY_MULTIPLIER; + } + offset += bytesRead; + // The `x-goog-upload-status` header field can be `active`, `final` and + //`cancelled` in resposne. + if (((_b = response === null || response === void 0 ? void 0 : response.headers) === null || _b === void 0 ? void 0 : _b[X_GOOG_UPLOAD_STATUS_HEADER_FIELD]) !== 'active') { + break; + } + if (fileSize <= offset) { + throw new Error('All content has been uploaded, but the upload status is not finalized.'); + } + } + return response; + } + finally { + // Ensure the file handle is always closed + if (fileHandle) { + await fileHandle.close(); + } + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class NodeFiles extends Files { + /** + * Registers Google Cloud Storage files for use with the API. + * This method is only available in Node.js environments. + */ + async registerFiles(params) { + if (typeof process === 'undefined' || + !process.versions || + !process.versions.node) { + throw new Error('registerFiles is only supported in Node.js environments.'); + } + const googleAuth = params.auth; + const authHeaders = await googleAuth.getRequestHeaders(); + const config = params.config || {}; + const httpOptions = config.httpOptions || {}; + const headers = Object.assign({}, (httpOptions.headers || {})); + if (authHeaders) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + if (typeof authHeaders[Symbol.iterator] === 'function') { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + for (const [key, value] of authHeaders) { + headers[key] = value; + } + } + else { + for (const [key, value] of Object.entries(authHeaders)) { + headers[key] = value; + } + } + } + return this._registerFiles({ + uris: params.uris, + config: Object.assign(Object.assign({}, config), { httpOptions: Object.assign(Object.assign({}, httpOptions), { headers }) }), + }); + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const LANGUAGE_LABEL_PREFIX = 'gl-node/'; +/** + * The Google GenAI SDK. + * + * @remarks + * Provides access to the GenAI features through either the {@link + * https://cloud.google.com/vertex-ai/docs/reference/rest | Gemini API} or + * the {@link https://cloud.google.com/vertex-ai/docs/reference/rest | Vertex AI + * API}. + * + * The {@link GoogleGenAIOptions.vertexai} value determines which of the API + * services to use. + * + * When using the Gemini API, a {@link GoogleGenAIOptions.apiKey} must also be + * set. When using Vertex AI, both {@link GoogleGenAIOptions.project} and {@link + * GoogleGenAIOptions.location} must be set, or a {@link + * GoogleGenAIOptions.apiKey} must be set when using Express Mode. + * + * Explicitly passed in values in {@link GoogleGenAIOptions} will always take + * precedence over environment variables. If both project/location and api_key + * exist in the environment variables, the project/location will be used. + * + * @example + * Initializing the SDK for using the Gemini API: + * ```ts + * import {GoogleGenAI} from '@google/genai'; + * const ai = new GoogleGenAI({apiKey: 'GEMINI_API_KEY'}); + * ``` + * + * @example + * Initializing the SDK for using the Vertex AI API: + * ```ts + * import {GoogleGenAI} from '@google/genai'; + * const ai = new GoogleGenAI({ + * vertexai: true, + * project: 'PROJECT_ID', + * location: 'PROJECT_LOCATION' + * }); + * ``` + * + */ +class GoogleGenAI { + get interactions() { + var _a; + if (this._interactions !== undefined) { + return this._interactions; + } + console.warn('GoogleGenAI.interactions: Interactions usage is experimental and may change in future versions.'); + const httpOpts = this.httpOptions; + // Unsupported Options Warnings + if (httpOpts === null || httpOpts === void 0 ? void 0 : httpOpts.extraBody) { + console.warn('GoogleGenAI.interactions: Client level httpOptions.extraBody is not supported by the interactions client and will be ignored.'); + } + const nextGenClient = new GeminiNextGenAPIClient({ + baseURL: this.apiClient.getBaseUrl(), + apiKey: this.apiKey, + apiVersion: this.apiClient.getApiVersion(), + clientAdapter: this.apiClient, + defaultHeaders: this.apiClient.getDefaultHeaders(), + timeout: httpOpts === null || httpOpts === void 0 ? void 0 : httpOpts.timeout, + maxRetries: (_a = httpOpts === null || httpOpts === void 0 ? void 0 : httpOpts.retryOptions) === null || _a === void 0 ? void 0 : _a.attempts, + }); + this._interactions = nextGenClient.interactions; + return this._interactions; + } + constructor(options) { + var _a, _b, _c, _d, _e, _f; + // Validate explicitly set initializer values. + if ((options.project || options.location) && options.apiKey) { + throw new Error('Project/location and API key are mutually exclusive in the client initializer.'); + } + this.vertexai = + (_b = (_a = options.vertexai) !== null && _a !== void 0 ? _a : getBooleanEnv('GOOGLE_GENAI_USE_VERTEXAI')) !== null && _b !== void 0 ? _b : false; + const envApiKey = getApiKeyFromEnv(); + const envProject = getEnv('GOOGLE_CLOUD_PROJECT'); + const envLocation = getEnv('GOOGLE_CLOUD_LOCATION'); + this.apiKey = (_c = options.apiKey) !== null && _c !== void 0 ? _c : envApiKey; + this.project = (_d = options.project) !== null && _d !== void 0 ? _d : envProject; + this.location = (_e = options.location) !== null && _e !== void 0 ? _e : envLocation; + if (!this.vertexai && !this.apiKey) { + throw new Error('API key must be set when using the Gemini API.'); + } + // Handle when to use Vertex AI in express mode (api key) + if (options.vertexai) { + if ((_f = options.googleAuthOptions) === null || _f === void 0 ? void 0 : _f.credentials) { + // Explicit credentials take precedence over implicit api_key. + console.debug('The user provided Google Cloud credentials will take precedence' + + ' over the API key from the environment variable.'); + this.apiKey = undefined; + } + // Explicit api_key and explicit project/location already handled above. + if ((envProject || envLocation) && options.apiKey) { + // Explicit api_key takes precedence over implicit project/location. + console.debug('The user provided Vertex AI API key will take precedence over' + + ' the project/location from the environment variables.'); + this.project = undefined; + this.location = undefined; + } + else if ((options.project || options.location) && envApiKey) { + // Explicit project/location takes precedence over implicit api_key. + console.debug('The user provided project/location will take precedence over' + + ' the API key from the environment variables.'); + this.apiKey = undefined; + } + else if ((envProject || envLocation) && envApiKey) { + // Implicit project/location takes precedence over implicit api_key. + console.debug('The project/location from the environment variables will take' + + ' precedence over the API key from the environment variables.'); + this.apiKey = undefined; + } + if (!this.location && !this.apiKey) { + this.location = 'global'; + } + } + const baseUrl = getBaseUrl(options.httpOptions, options.vertexai, getEnv('GOOGLE_VERTEX_BASE_URL'), getEnv('GOOGLE_GEMINI_BASE_URL')); + if (baseUrl) { + if (options.httpOptions) { + options.httpOptions.baseUrl = baseUrl; + } + else { + options.httpOptions = { baseUrl: baseUrl }; + } + } + this.apiVersion = options.apiVersion; + this.httpOptions = options.httpOptions; + const auth = new NodeAuth({ + apiKey: this.apiKey, + googleAuthOptions: options.googleAuthOptions, + }); + this.apiClient = new ApiClient({ + auth: auth, + project: this.project, + location: this.location, + apiVersion: this.apiVersion, + apiKey: this.apiKey, + vertexai: this.vertexai, + httpOptions: this.httpOptions, + userAgentExtra: LANGUAGE_LABEL_PREFIX + process.version, + uploader: new NodeUploader(), + downloader: new NodeDownloader(), + }); + this.models = new Models(this.apiClient); + this.live = new Live(this.apiClient, auth, new NodeWebSocketFactory()); + this.batches = new Batches(this.apiClient); + this.chats = new Chats(this.models, this.apiClient); + this.caches = new Caches(this.apiClient); + this.files = new NodeFiles(this.apiClient); + this.operations = new Operations(this.apiClient); + this.authTokens = new Tokens(this.apiClient); + this.tunings = new Tunings(this.apiClient); + this.fileSearchStores = new FileSearchStores(this.apiClient); + } +} +function getEnv(env) { + var _a, _b, _c; + return (_c = (_b = (_a = process === null || process === void 0 ? void 0 : process.env) === null || _a === void 0 ? void 0 : _a[env]) === null || _b === void 0 ? void 0 : _b.trim()) !== null && _c !== void 0 ? _c : undefined; +} +function getBooleanEnv(env) { + return stringToBoolean(getEnv(env)); +} +function stringToBoolean(str) { + if (str === undefined) { + return false; + } + return str.toLowerCase() === 'true'; +} +function getApiKeyFromEnv() { + const envGoogleApiKey = getEnv('GOOGLE_API_KEY'); + const envGeminiApiKey = getEnv('GEMINI_API_KEY'); + if (envGoogleApiKey && envGeminiApiKey) { + console.warn('Both GOOGLE_API_KEY and GEMINI_API_KEY are set. Using GOOGLE_API_KEY.'); + } + return envGoogleApiKey || envGeminiApiKey || undefined; +} + +exports.ApiError = ApiError; +exports.Batches = Batches; +exports.Caches = Caches; +exports.CancelTuningJobResponse = CancelTuningJobResponse; +exports.Chat = Chat; +exports.Chats = Chats; +exports.ComputeTokensResponse = ComputeTokensResponse; +exports.ContentReferenceImage = ContentReferenceImage; +exports.ControlReferenceImage = ControlReferenceImage; +exports.CountTokensResponse = CountTokensResponse; +exports.CreateFileResponse = CreateFileResponse; +exports.DeleteCachedContentResponse = DeleteCachedContentResponse; +exports.DeleteFileResponse = DeleteFileResponse; +exports.DeleteModelResponse = DeleteModelResponse; +exports.EditImageResponse = EditImageResponse; +exports.EmbedContentResponse = EmbedContentResponse; +exports.Files = Files; +exports.FunctionResponse = FunctionResponse; +exports.FunctionResponseBlob = FunctionResponseBlob; +exports.FunctionResponseFileData = FunctionResponseFileData; +exports.FunctionResponsePart = FunctionResponsePart; +exports.GenerateContentResponse = GenerateContentResponse; +exports.GenerateContentResponsePromptFeedback = GenerateContentResponsePromptFeedback; +exports.GenerateContentResponseUsageMetadata = GenerateContentResponseUsageMetadata; +exports.GenerateImagesResponse = GenerateImagesResponse; +exports.GenerateVideosOperation = GenerateVideosOperation; +exports.GenerateVideosResponse = GenerateVideosResponse; +exports.GoogleGenAI = GoogleGenAI; +exports.HttpResponse = HttpResponse; +exports.ImportFileOperation = ImportFileOperation; +exports.ImportFileResponse = ImportFileResponse; +exports.InlinedEmbedContentResponse = InlinedEmbedContentResponse; +exports.InlinedResponse = InlinedResponse; +exports.ListBatchJobsResponse = ListBatchJobsResponse; +exports.ListCachedContentsResponse = ListCachedContentsResponse; +exports.ListDocumentsResponse = ListDocumentsResponse; +exports.ListFileSearchStoresResponse = ListFileSearchStoresResponse; +exports.ListFilesResponse = ListFilesResponse; +exports.ListModelsResponse = ListModelsResponse; +exports.ListTuningJobsResponse = ListTuningJobsResponse; +exports.Live = Live; +exports.LiveClientToolResponse = LiveClientToolResponse; +exports.LiveMusicServerMessage = LiveMusicServerMessage; +exports.LiveSendToolResponseParameters = LiveSendToolResponseParameters; +exports.LiveServerMessage = LiveServerMessage; +exports.MaskReferenceImage = MaskReferenceImage; +exports.Models = Models; +exports.Operations = Operations; +exports.Pager = Pager; +exports.RawReferenceImage = RawReferenceImage; +exports.RecontextImageResponse = RecontextImageResponse; +exports.RegisterFilesResponse = RegisterFilesResponse; +exports.ReplayResponse = ReplayResponse; +exports.SegmentImageResponse = SegmentImageResponse; +exports.Session = Session; +exports.SingleEmbedContentResponse = SingleEmbedContentResponse; +exports.StyleReferenceImage = StyleReferenceImage; +exports.SubjectReferenceImage = SubjectReferenceImage; +exports.Tokens = Tokens; +exports.UploadToFileSearchStoreOperation = UploadToFileSearchStoreOperation; +exports.UploadToFileSearchStoreResponse = UploadToFileSearchStoreResponse; +exports.UploadToFileSearchStoreResumableResponse = UploadToFileSearchStoreResumableResponse; +exports.UpscaleImageResponse = UpscaleImageResponse; +exports.createFunctionResponsePartFromBase64 = createFunctionResponsePartFromBase64; +exports.createFunctionResponsePartFromUri = createFunctionResponsePartFromUri; +exports.createModelContent = createModelContent; +exports.createPartFromBase64 = createPartFromBase64; +exports.createPartFromCodeExecutionResult = createPartFromCodeExecutionResult; +exports.createPartFromExecutableCode = createPartFromExecutableCode; +exports.createPartFromFunctionCall = createPartFromFunctionCall; +exports.createPartFromFunctionResponse = createPartFromFunctionResponse; +exports.createPartFromText = createPartFromText; +exports.createPartFromUri = createPartFromUri; +exports.createUserContent = createUserContent; +exports.mcpToTool = mcpToTool; +exports.setDefaultBaseUrls = setDefaultBaseUrls; +//# sourceMappingURL=index.cjs.map diff --git a/server/node_modules/@google/genai/dist/node/index.mjs b/server/node_modules/@google/genai/dist/node/index.mjs new file mode 100644 index 0000000..327c7f6 --- /dev/null +++ b/server/node_modules/@google/genai/dist/node/index.mjs @@ -0,0 +1,19986 @@ +import pRetry, { AbortError } from 'p-retry'; +import { GoogleAuth } from 'google-auth-library'; +import { createWriteStream } from 'fs'; +import * as fs from 'fs/promises'; +import { writeFile } from 'fs/promises'; +import { Readable } from 'node:stream'; +import { finished } from 'node:stream/promises'; +import * as NodeWs from 'ws'; +import * as path$1 from 'path'; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +let _defaultBaseGeminiUrl = undefined; +let _defaultBaseVertexUrl = undefined; +/** + * Overrides the base URLs for the Gemini API and Vertex AI API. + * + * @remarks This function should be called before initializing the SDK. If the + * base URLs are set after initializing the SDK, the base URLs will not be + * updated. Base URLs provided in the HttpOptions will also take precedence over + * URLs set here. + * + * @example + * ```ts + * import {GoogleGenAI, setDefaultBaseUrls} from '@google/genai'; + * // Override the base URL for the Gemini API. + * setDefaultBaseUrls({geminiUrl:'https://gemini.google.com'}); + * + * // Override the base URL for the Vertex AI API. + * setDefaultBaseUrls({vertexUrl: 'https://vertexai.googleapis.com'}); + * + * const ai = new GoogleGenAI({apiKey: 'GEMINI_API_KEY'}); + * ``` + */ +function setDefaultBaseUrls(baseUrlParams) { + _defaultBaseGeminiUrl = baseUrlParams.geminiUrl; + _defaultBaseVertexUrl = baseUrlParams.vertexUrl; +} +/** + * Returns the default base URLs for the Gemini API and Vertex AI API. + */ +function getDefaultBaseUrls() { + return { + geminiUrl: _defaultBaseGeminiUrl, + vertexUrl: _defaultBaseVertexUrl, + }; +} +/** + * Returns the default base URL based on the following priority: + * 1. Base URLs set via HttpOptions. + * 2. Base URLs set via the latest call to setDefaultBaseUrls. + * 3. Base URLs set via environment variables. + */ +function getBaseUrl(httpOptions, vertexai, vertexBaseUrlFromEnv, geminiBaseUrlFromEnv) { + var _a, _b; + if (!(httpOptions === null || httpOptions === void 0 ? void 0 : httpOptions.baseUrl)) { + const defaultBaseUrls = getDefaultBaseUrls(); + if (vertexai) { + return (_a = defaultBaseUrls.vertexUrl) !== null && _a !== void 0 ? _a : vertexBaseUrlFromEnv; + } + else { + return (_b = defaultBaseUrls.geminiUrl) !== null && _b !== void 0 ? _b : geminiBaseUrlFromEnv; + } + } + return httpOptions.baseUrl; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class BaseModule { +} +function formatMap(templateString, valueMap) { + // Use a regular expression to find all placeholders in the template string + const regex = /\{([^}]+)\}/g; + // Replace each placeholder with its corresponding value from the valueMap + return templateString.replace(regex, (match, key) => { + if (Object.prototype.hasOwnProperty.call(valueMap, key)) { + const value = valueMap[key]; + // Convert the value to a string if it's not a string already + return value !== undefined && value !== null ? String(value) : ''; + } + else { + // Handle missing keys + throw new Error(`Key '${key}' not found in valueMap.`); + } + }); +} +function setValueByPath(data, keys, value) { + for (let i = 0; i < keys.length - 1; i++) { + const key = keys[i]; + if (key.endsWith('[]')) { + const keyName = key.slice(0, -2); + if (!(keyName in data)) { + if (Array.isArray(value)) { + data[keyName] = Array.from({ length: value.length }, () => ({})); + } + else { + throw new Error(`Value must be a list given an array path ${key}`); + } + } + if (Array.isArray(data[keyName])) { + const arrayData = data[keyName]; + if (Array.isArray(value)) { + for (let j = 0; j < arrayData.length; j++) { + const entry = arrayData[j]; + setValueByPath(entry, keys.slice(i + 1), value[j]); + } + } + else { + for (const d of arrayData) { + setValueByPath(d, keys.slice(i + 1), value); + } + } + } + return; + } + else if (key.endsWith('[0]')) { + const keyName = key.slice(0, -3); + if (!(keyName in data)) { + data[keyName] = [{}]; + } + const arrayData = data[keyName]; + setValueByPath(arrayData[0], keys.slice(i + 1), value); + return; + } + if (!data[key] || typeof data[key] !== 'object') { + data[key] = {}; + } + data = data[key]; + } + const keyToSet = keys[keys.length - 1]; + const existingData = data[keyToSet]; + if (existingData !== undefined) { + if (!value || + (typeof value === 'object' && Object.keys(value).length === 0)) { + return; + } + if (value === existingData) { + return; + } + if (typeof existingData === 'object' && + typeof value === 'object' && + existingData !== null && + value !== null) { + Object.assign(existingData, value); + } + else { + throw new Error(`Cannot set value for an existing key. Key: ${keyToSet}`); + } + } + else { + if (keyToSet === '_self' && + typeof value === 'object' && + value !== null && + !Array.isArray(value)) { + const valueAsRecord = value; + Object.assign(data, valueAsRecord); + } + else { + data[keyToSet] = value; + } + } +} +function getValueByPath(data, keys, defaultValue = undefined) { + try { + if (keys.length === 1 && keys[0] === '_self') { + return data; + } + for (let i = 0; i < keys.length; i++) { + if (typeof data !== 'object' || data === null) { + return defaultValue; + } + const key = keys[i]; + if (key.endsWith('[]')) { + const keyName = key.slice(0, -2); + if (keyName in data) { + const arrayData = data[keyName]; + if (!Array.isArray(arrayData)) { + return defaultValue; + } + return arrayData.map((d) => getValueByPath(d, keys.slice(i + 1), defaultValue)); + } + else { + return defaultValue; + } + } + else { + data = data[key]; + } + } + return data; + } + catch (error) { + if (error instanceof TypeError) { + return defaultValue; + } + throw error; + } +} +/** + * Moves values from source paths to destination paths. + * + * Examples: + * moveValueByPath( + * {'requests': [{'content': v1}, {'content': v2}]}, + * {'requests[].*': 'requests[].request.*'} + * ) + * -> {'requests': [{'request': {'content': v1}}, {'request': {'content': v2}}]} + */ +function moveValueByPath(data, paths) { + for (const [sourcePath, destPath] of Object.entries(paths)) { + const sourceKeys = sourcePath.split('.'); + const destKeys = destPath.split('.'); + // Determine keys to exclude from wildcard to avoid cyclic references + const excludeKeys = new Set(); + let wildcardIdx = -1; + for (let i = 0; i < sourceKeys.length; i++) { + if (sourceKeys[i] === '*') { + wildcardIdx = i; + break; + } + } + if (wildcardIdx !== -1 && destKeys.length > wildcardIdx) { + // Extract the intermediate key between source and dest paths + // Example: source=['requests[]', '*'], dest=['requests[]', 'request', '*'] + // We want to exclude 'request' + for (let i = wildcardIdx; i < destKeys.length; i++) { + const key = destKeys[i]; + if (key !== '*' && !key.endsWith('[]') && !key.endsWith('[0]')) { + excludeKeys.add(key); + } + } + } + _moveValueRecursive(data, sourceKeys, destKeys, 0, excludeKeys); + } +} +/** + * Recursively moves values from source path to destination path. + */ +function _moveValueRecursive(data, sourceKeys, destKeys, keyIdx, excludeKeys) { + if (keyIdx >= sourceKeys.length) { + return; + } + if (typeof data !== 'object' || data === null) { + return; + } + const key = sourceKeys[keyIdx]; + if (key.endsWith('[]')) { + const keyName = key.slice(0, -2); + const dataRecord = data; + if (keyName in dataRecord && Array.isArray(dataRecord[keyName])) { + for (const item of dataRecord[keyName]) { + _moveValueRecursive(item, sourceKeys, destKeys, keyIdx + 1, excludeKeys); + } + } + } + else if (key === '*') { + // wildcard - move all fields + if (typeof data === 'object' && data !== null && !Array.isArray(data)) { + const dataRecord = data; + const keysToMove = Object.keys(dataRecord).filter((k) => !k.startsWith('_') && !excludeKeys.has(k)); + const valuesToMove = {}; + for (const k of keysToMove) { + valuesToMove[k] = dataRecord[k]; + } + // Set values at destination + for (const [k, v] of Object.entries(valuesToMove)) { + const newDestKeys = []; + for (const dk of destKeys.slice(keyIdx)) { + if (dk === '*') { + newDestKeys.push(k); + } + else { + newDestKeys.push(dk); + } + } + setValueByPath(dataRecord, newDestKeys, v); + } + for (const k of keysToMove) { + delete dataRecord[k]; + } + } + } + else { + // Navigate to next level + const dataRecord = data; + if (key in dataRecord) { + _moveValueRecursive(dataRecord[key], sourceKeys, destKeys, keyIdx + 1, excludeKeys); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function tBytes$1(fromBytes) { + if (typeof fromBytes !== 'string') { + throw new Error('fromImageBytes must be a string'); + } + // TODO(b/389133914): Remove dummy bytes converter. + return fromBytes; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Code generated by the Google Gen AI SDK generator DO NOT EDIT. +function fetchPredictOperationParametersToVertex(fromObject) { + const toObject = {}; + const fromOperationName = getValueByPath(fromObject, [ + 'operationName', + ]); + if (fromOperationName != null) { + setValueByPath(toObject, ['operationName'], fromOperationName); + } + const fromResourceName = getValueByPath(fromObject, ['resourceName']); + if (fromResourceName != null) { + setValueByPath(toObject, ['_url', 'resourceName'], fromResourceName); + } + return toObject; +} +function generateVideosOperationFromMldev$1(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromResponse = getValueByPath(fromObject, [ + 'response', + 'generateVideoResponse', + ]); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], generateVideosResponseFromMldev$1(fromResponse)); + } + return toObject; +} +function generateVideosOperationFromVertex$1(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], generateVideosResponseFromVertex$1(fromResponse)); + } + return toObject; +} +function generateVideosResponseFromMldev$1(fromObject) { + const toObject = {}; + const fromGeneratedVideos = getValueByPath(fromObject, [ + 'generatedSamples', + ]); + if (fromGeneratedVideos != null) { + let transformedList = fromGeneratedVideos; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedVideoFromMldev$1(item); + }); + } + setValueByPath(toObject, ['generatedVideos'], transformedList); + } + const fromRaiMediaFilteredCount = getValueByPath(fromObject, [ + 'raiMediaFilteredCount', + ]); + if (fromRaiMediaFilteredCount != null) { + setValueByPath(toObject, ['raiMediaFilteredCount'], fromRaiMediaFilteredCount); + } + const fromRaiMediaFilteredReasons = getValueByPath(fromObject, [ + 'raiMediaFilteredReasons', + ]); + if (fromRaiMediaFilteredReasons != null) { + setValueByPath(toObject, ['raiMediaFilteredReasons'], fromRaiMediaFilteredReasons); + } + return toObject; +} +function generateVideosResponseFromVertex$1(fromObject) { + const toObject = {}; + const fromGeneratedVideos = getValueByPath(fromObject, ['videos']); + if (fromGeneratedVideos != null) { + let transformedList = fromGeneratedVideos; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedVideoFromVertex$1(item); + }); + } + setValueByPath(toObject, ['generatedVideos'], transformedList); + } + const fromRaiMediaFilteredCount = getValueByPath(fromObject, [ + 'raiMediaFilteredCount', + ]); + if (fromRaiMediaFilteredCount != null) { + setValueByPath(toObject, ['raiMediaFilteredCount'], fromRaiMediaFilteredCount); + } + const fromRaiMediaFilteredReasons = getValueByPath(fromObject, [ + 'raiMediaFilteredReasons', + ]); + if (fromRaiMediaFilteredReasons != null) { + setValueByPath(toObject, ['raiMediaFilteredReasons'], fromRaiMediaFilteredReasons); + } + return toObject; +} +function generatedVideoFromMldev$1(fromObject) { + const toObject = {}; + const fromVideo = getValueByPath(fromObject, ['video']); + if (fromVideo != null) { + setValueByPath(toObject, ['video'], videoFromMldev$1(fromVideo)); + } + return toObject; +} +function generatedVideoFromVertex$1(fromObject) { + const toObject = {}; + const fromVideo = getValueByPath(fromObject, ['_self']); + if (fromVideo != null) { + setValueByPath(toObject, ['video'], videoFromVertex$1(fromVideo)); + } + return toObject; +} +function getOperationParametersToMldev(fromObject) { + const toObject = {}; + const fromOperationName = getValueByPath(fromObject, [ + 'operationName', + ]); + if (fromOperationName != null) { + setValueByPath(toObject, ['_url', 'operationName'], fromOperationName); + } + return toObject; +} +function getOperationParametersToVertex(fromObject) { + const toObject = {}; + const fromOperationName = getValueByPath(fromObject, [ + 'operationName', + ]); + if (fromOperationName != null) { + setValueByPath(toObject, ['_url', 'operationName'], fromOperationName); + } + return toObject; +} +function importFileOperationFromMldev$1(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], importFileResponseFromMldev$1(fromResponse)); + } + return toObject; +} +function importFileResponseFromMldev$1(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromParent = getValueByPath(fromObject, ['parent']); + if (fromParent != null) { + setValueByPath(toObject, ['parent'], fromParent); + } + const fromDocumentName = getValueByPath(fromObject, ['documentName']); + if (fromDocumentName != null) { + setValueByPath(toObject, ['documentName'], fromDocumentName); + } + return toObject; +} +function uploadToFileSearchStoreOperationFromMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], uploadToFileSearchStoreResponseFromMldev(fromResponse)); + } + return toObject; +} +function uploadToFileSearchStoreResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromParent = getValueByPath(fromObject, ['parent']); + if (fromParent != null) { + setValueByPath(toObject, ['parent'], fromParent); + } + const fromDocumentName = getValueByPath(fromObject, ['documentName']); + if (fromDocumentName != null) { + setValueByPath(toObject, ['documentName'], fromDocumentName); + } + return toObject; +} +function videoFromMldev$1(fromObject) { + const toObject = {}; + const fromUri = getValueByPath(fromObject, ['uri']); + if (fromUri != null) { + setValueByPath(toObject, ['uri'], fromUri); + } + const fromVideoBytes = getValueByPath(fromObject, ['encodedVideo']); + if (fromVideoBytes != null) { + setValueByPath(toObject, ['videoBytes'], tBytes$1(fromVideoBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['encoding']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function videoFromVertex$1(fromObject) { + const toObject = {}; + const fromUri = getValueByPath(fromObject, ['gcsUri']); + if (fromUri != null) { + setValueByPath(toObject, ['uri'], fromUri); + } + const fromVideoBytes = getValueByPath(fromObject, [ + 'bytesBase64Encoded', + ]); + if (fromVideoBytes != null) { + setValueByPath(toObject, ['videoBytes'], tBytes$1(fromVideoBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** Outcome of the code execution. */ +var Outcome; +(function (Outcome) { + /** + * Unspecified status. This value should not be used. + */ + Outcome["OUTCOME_UNSPECIFIED"] = "OUTCOME_UNSPECIFIED"; + /** + * Code execution completed successfully. + */ + Outcome["OUTCOME_OK"] = "OUTCOME_OK"; + /** + * Code execution finished but with a failure. `stderr` should contain the reason. + */ + Outcome["OUTCOME_FAILED"] = "OUTCOME_FAILED"; + /** + * Code execution ran for too long, and was cancelled. There may or may not be a partial output present. + */ + Outcome["OUTCOME_DEADLINE_EXCEEDED"] = "OUTCOME_DEADLINE_EXCEEDED"; +})(Outcome || (Outcome = {})); +/** Programming language of the `code`. */ +var Language; +(function (Language) { + /** + * Unspecified language. This value should not be used. + */ + Language["LANGUAGE_UNSPECIFIED"] = "LANGUAGE_UNSPECIFIED"; + /** + * Python >= 3.10, with numpy and simpy available. + */ + Language["PYTHON"] = "PYTHON"; +})(Language || (Language = {})); +/** Specifies how the response should be scheduled in the conversation. */ +var FunctionResponseScheduling; +(function (FunctionResponseScheduling) { + /** + * This value is unused. + */ + FunctionResponseScheduling["SCHEDULING_UNSPECIFIED"] = "SCHEDULING_UNSPECIFIED"; + /** + * Only add the result to the conversation context, do not interrupt or trigger generation. + */ + FunctionResponseScheduling["SILENT"] = "SILENT"; + /** + * Add the result to the conversation context, and prompt to generate output without interrupting ongoing generation. + */ + FunctionResponseScheduling["WHEN_IDLE"] = "WHEN_IDLE"; + /** + * Add the result to the conversation context, interrupt ongoing generation and prompt to generate output. + */ + FunctionResponseScheduling["INTERRUPT"] = "INTERRUPT"; +})(FunctionResponseScheduling || (FunctionResponseScheduling = {})); +/** The type of the data. */ +var Type; +(function (Type) { + /** + * Not specified, should not be used. + */ + Type["TYPE_UNSPECIFIED"] = "TYPE_UNSPECIFIED"; + /** + * OpenAPI string type + */ + Type["STRING"] = "STRING"; + /** + * OpenAPI number type + */ + Type["NUMBER"] = "NUMBER"; + /** + * OpenAPI integer type + */ + Type["INTEGER"] = "INTEGER"; + /** + * OpenAPI boolean type + */ + Type["BOOLEAN"] = "BOOLEAN"; + /** + * OpenAPI array type + */ + Type["ARRAY"] = "ARRAY"; + /** + * OpenAPI object type + */ + Type["OBJECT"] = "OBJECT"; + /** + * Null type + */ + Type["NULL"] = "NULL"; +})(Type || (Type = {})); +/** The API spec that the external API implements. This enum is not supported in Gemini API. */ +var ApiSpec; +(function (ApiSpec) { + /** + * Unspecified API spec. This value should not be used. + */ + ApiSpec["API_SPEC_UNSPECIFIED"] = "API_SPEC_UNSPECIFIED"; + /** + * Simple search API spec. + */ + ApiSpec["SIMPLE_SEARCH"] = "SIMPLE_SEARCH"; + /** + * Elastic search API spec. + */ + ApiSpec["ELASTIC_SEARCH"] = "ELASTIC_SEARCH"; +})(ApiSpec || (ApiSpec = {})); +/** Type of auth scheme. This enum is not supported in Gemini API. */ +var AuthType; +(function (AuthType) { + AuthType["AUTH_TYPE_UNSPECIFIED"] = "AUTH_TYPE_UNSPECIFIED"; + /** + * No Auth. + */ + AuthType["NO_AUTH"] = "NO_AUTH"; + /** + * API Key Auth. + */ + AuthType["API_KEY_AUTH"] = "API_KEY_AUTH"; + /** + * HTTP Basic Auth. + */ + AuthType["HTTP_BASIC_AUTH"] = "HTTP_BASIC_AUTH"; + /** + * Google Service Account Auth. + */ + AuthType["GOOGLE_SERVICE_ACCOUNT_AUTH"] = "GOOGLE_SERVICE_ACCOUNT_AUTH"; + /** + * OAuth auth. + */ + AuthType["OAUTH"] = "OAUTH"; + /** + * OpenID Connect (OIDC) Auth. + */ + AuthType["OIDC_AUTH"] = "OIDC_AUTH"; +})(AuthType || (AuthType = {})); +/** The location of the API key. This enum is not supported in Gemini API. */ +var HttpElementLocation; +(function (HttpElementLocation) { + HttpElementLocation["HTTP_IN_UNSPECIFIED"] = "HTTP_IN_UNSPECIFIED"; + /** + * Element is in the HTTP request query. + */ + HttpElementLocation["HTTP_IN_QUERY"] = "HTTP_IN_QUERY"; + /** + * Element is in the HTTP request header. + */ + HttpElementLocation["HTTP_IN_HEADER"] = "HTTP_IN_HEADER"; + /** + * Element is in the HTTP request path. + */ + HttpElementLocation["HTTP_IN_PATH"] = "HTTP_IN_PATH"; + /** + * Element is in the HTTP request body. + */ + HttpElementLocation["HTTP_IN_BODY"] = "HTTP_IN_BODY"; + /** + * Element is in the HTTP request cookie. + */ + HttpElementLocation["HTTP_IN_COOKIE"] = "HTTP_IN_COOKIE"; +})(HttpElementLocation || (HttpElementLocation = {})); +/** Sites with confidence level chosen & above this value will be blocked from the search results. This enum is not supported in Gemini API. */ +var PhishBlockThreshold; +(function (PhishBlockThreshold) { + /** + * Defaults to unspecified. + */ + PhishBlockThreshold["PHISH_BLOCK_THRESHOLD_UNSPECIFIED"] = "PHISH_BLOCK_THRESHOLD_UNSPECIFIED"; + /** + * Blocks Low and above confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_LOW_AND_ABOVE"] = "BLOCK_LOW_AND_ABOVE"; + /** + * Blocks Medium and above confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_MEDIUM_AND_ABOVE"] = "BLOCK_MEDIUM_AND_ABOVE"; + /** + * Blocks High and above confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_HIGH_AND_ABOVE"] = "BLOCK_HIGH_AND_ABOVE"; + /** + * Blocks Higher and above confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_HIGHER_AND_ABOVE"] = "BLOCK_HIGHER_AND_ABOVE"; + /** + * Blocks Very high and above confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_VERY_HIGH_AND_ABOVE"] = "BLOCK_VERY_HIGH_AND_ABOVE"; + /** + * Blocks Extremely high confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_ONLY_EXTREMELY_HIGH"] = "BLOCK_ONLY_EXTREMELY_HIGH"; +})(PhishBlockThreshold || (PhishBlockThreshold = {})); +/** Specifies the function Behavior. Currently only supported by the BidiGenerateContent method. This enum is not supported in Vertex AI. */ +var Behavior; +(function (Behavior) { + /** + * This value is unused. + */ + Behavior["UNSPECIFIED"] = "UNSPECIFIED"; + /** + * If set, the system will wait to receive the function response before continuing the conversation. + */ + Behavior["BLOCKING"] = "BLOCKING"; + /** + * If set, the system will not wait to receive the function response. Instead, it will attempt to handle function responses as they become available while maintaining the conversation between the user and the model. + */ + Behavior["NON_BLOCKING"] = "NON_BLOCKING"; +})(Behavior || (Behavior = {})); +/** The mode of the predictor to be used in dynamic retrieval. */ +var DynamicRetrievalConfigMode; +(function (DynamicRetrievalConfigMode) { + /** + * Always trigger retrieval. + */ + DynamicRetrievalConfigMode["MODE_UNSPECIFIED"] = "MODE_UNSPECIFIED"; + /** + * Run retrieval only when system decides it is necessary. + */ + DynamicRetrievalConfigMode["MODE_DYNAMIC"] = "MODE_DYNAMIC"; +})(DynamicRetrievalConfigMode || (DynamicRetrievalConfigMode = {})); +/** Function calling mode. */ +var FunctionCallingConfigMode; +(function (FunctionCallingConfigMode) { + /** + * Unspecified function calling mode. This value should not be used. + */ + FunctionCallingConfigMode["MODE_UNSPECIFIED"] = "MODE_UNSPECIFIED"; + /** + * Default model behavior, model decides to predict either function calls or natural language response. + */ + FunctionCallingConfigMode["AUTO"] = "AUTO"; + /** + * Model is constrained to always predicting function calls only. If "allowed_function_names" are set, the predicted function calls will be limited to any one of "allowed_function_names", else the predicted function calls will be any one of the provided "function_declarations". + */ + FunctionCallingConfigMode["ANY"] = "ANY"; + /** + * Model will not predict any function calls. Model behavior is same as when not passing any function declarations. + */ + FunctionCallingConfigMode["NONE"] = "NONE"; + /** + * Model is constrained to predict either function calls or natural language response. If "allowed_function_names" are set, the predicted function calls will be limited to any one of "allowed_function_names", else the predicted function calls will be any one of the provided "function_declarations". + */ + FunctionCallingConfigMode["VALIDATED"] = "VALIDATED"; +})(FunctionCallingConfigMode || (FunctionCallingConfigMode = {})); +/** The number of thoughts tokens that the model should generate. */ +var ThinkingLevel; +(function (ThinkingLevel) { + /** + * Unspecified thinking level. + */ + ThinkingLevel["THINKING_LEVEL_UNSPECIFIED"] = "THINKING_LEVEL_UNSPECIFIED"; + /** + * Low thinking level. + */ + ThinkingLevel["LOW"] = "LOW"; + /** + * Medium thinking level. + */ + ThinkingLevel["MEDIUM"] = "MEDIUM"; + /** + * High thinking level. + */ + ThinkingLevel["HIGH"] = "HIGH"; + /** + * MINIMAL thinking level. + */ + ThinkingLevel["MINIMAL"] = "MINIMAL"; +})(ThinkingLevel || (ThinkingLevel = {})); +/** Harm category. */ +var HarmCategory; +(function (HarmCategory) { + /** + * The harm category is unspecified. + */ + HarmCategory["HARM_CATEGORY_UNSPECIFIED"] = "HARM_CATEGORY_UNSPECIFIED"; + /** + * The harm category is harassment. + */ + HarmCategory["HARM_CATEGORY_HARASSMENT"] = "HARM_CATEGORY_HARASSMENT"; + /** + * The harm category is hate speech. + */ + HarmCategory["HARM_CATEGORY_HATE_SPEECH"] = "HARM_CATEGORY_HATE_SPEECH"; + /** + * The harm category is sexually explicit content. + */ + HarmCategory["HARM_CATEGORY_SEXUALLY_EXPLICIT"] = "HARM_CATEGORY_SEXUALLY_EXPLICIT"; + /** + * The harm category is dangerous content. + */ + HarmCategory["HARM_CATEGORY_DANGEROUS_CONTENT"] = "HARM_CATEGORY_DANGEROUS_CONTENT"; + /** + * Deprecated: Election filter is not longer supported. The harm category is civic integrity. + */ + HarmCategory["HARM_CATEGORY_CIVIC_INTEGRITY"] = "HARM_CATEGORY_CIVIC_INTEGRITY"; + /** + * The harm category is image hate. This enum value is not supported in Gemini API. + */ + HarmCategory["HARM_CATEGORY_IMAGE_HATE"] = "HARM_CATEGORY_IMAGE_HATE"; + /** + * The harm category is image dangerous content. This enum value is not supported in Gemini API. + */ + HarmCategory["HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT"] = "HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT"; + /** + * The harm category is image harassment. This enum value is not supported in Gemini API. + */ + HarmCategory["HARM_CATEGORY_IMAGE_HARASSMENT"] = "HARM_CATEGORY_IMAGE_HARASSMENT"; + /** + * The harm category is image sexually explicit content. This enum value is not supported in Gemini API. + */ + HarmCategory["HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT"] = "HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT"; + /** + * The harm category is for jailbreak prompts. This enum value is not supported in Gemini API. + */ + HarmCategory["HARM_CATEGORY_JAILBREAK"] = "HARM_CATEGORY_JAILBREAK"; +})(HarmCategory || (HarmCategory = {})); +/** Specify if the threshold is used for probability or severity score. If not specified, the threshold is used for probability score. This enum is not supported in Gemini API. */ +var HarmBlockMethod; +(function (HarmBlockMethod) { + /** + * The harm block method is unspecified. + */ + HarmBlockMethod["HARM_BLOCK_METHOD_UNSPECIFIED"] = "HARM_BLOCK_METHOD_UNSPECIFIED"; + /** + * The harm block method uses both probability and severity scores. + */ + HarmBlockMethod["SEVERITY"] = "SEVERITY"; + /** + * The harm block method uses the probability score. + */ + HarmBlockMethod["PROBABILITY"] = "PROBABILITY"; +})(HarmBlockMethod || (HarmBlockMethod = {})); +/** The harm block threshold. */ +var HarmBlockThreshold; +(function (HarmBlockThreshold) { + /** + * Unspecified harm block threshold. + */ + HarmBlockThreshold["HARM_BLOCK_THRESHOLD_UNSPECIFIED"] = "HARM_BLOCK_THRESHOLD_UNSPECIFIED"; + /** + * Block low threshold and above (i.e. block more). + */ + HarmBlockThreshold["BLOCK_LOW_AND_ABOVE"] = "BLOCK_LOW_AND_ABOVE"; + /** + * Block medium threshold and above. + */ + HarmBlockThreshold["BLOCK_MEDIUM_AND_ABOVE"] = "BLOCK_MEDIUM_AND_ABOVE"; + /** + * Block only high threshold (i.e. block less). + */ + HarmBlockThreshold["BLOCK_ONLY_HIGH"] = "BLOCK_ONLY_HIGH"; + /** + * Block none. + */ + HarmBlockThreshold["BLOCK_NONE"] = "BLOCK_NONE"; + /** + * Turn off the safety filter. + */ + HarmBlockThreshold["OFF"] = "OFF"; +})(HarmBlockThreshold || (HarmBlockThreshold = {})); +/** Output only. The reason why the model stopped generating tokens. + +If empty, the model has not stopped generating the tokens. */ +var FinishReason; +(function (FinishReason) { + /** + * The finish reason is unspecified. + */ + FinishReason["FINISH_REASON_UNSPECIFIED"] = "FINISH_REASON_UNSPECIFIED"; + /** + * Token generation reached a natural stopping point or a configured stop sequence. + */ + FinishReason["STOP"] = "STOP"; + /** + * Token generation reached the configured maximum output tokens. + */ + FinishReason["MAX_TOKENS"] = "MAX_TOKENS"; + /** + * Token generation stopped because the content potentially contains safety violations. NOTE: When streaming, [content][] is empty if content filters blocks the output. + */ + FinishReason["SAFETY"] = "SAFETY"; + /** + * The token generation stopped because of potential recitation. + */ + FinishReason["RECITATION"] = "RECITATION"; + /** + * The token generation stopped because of using an unsupported language. + */ + FinishReason["LANGUAGE"] = "LANGUAGE"; + /** + * All other reasons that stopped the token generation. + */ + FinishReason["OTHER"] = "OTHER"; + /** + * Token generation stopped because the content contains forbidden terms. + */ + FinishReason["BLOCKLIST"] = "BLOCKLIST"; + /** + * Token generation stopped for potentially containing prohibited content. + */ + FinishReason["PROHIBITED_CONTENT"] = "PROHIBITED_CONTENT"; + /** + * Token generation stopped because the content potentially contains Sensitive Personally Identifiable Information (SPII). + */ + FinishReason["SPII"] = "SPII"; + /** + * The function call generated by the model is invalid. + */ + FinishReason["MALFORMED_FUNCTION_CALL"] = "MALFORMED_FUNCTION_CALL"; + /** + * Token generation stopped because generated images have safety violations. + */ + FinishReason["IMAGE_SAFETY"] = "IMAGE_SAFETY"; + /** + * The tool call generated by the model is invalid. + */ + FinishReason["UNEXPECTED_TOOL_CALL"] = "UNEXPECTED_TOOL_CALL"; + /** + * Image generation stopped because the generated images have prohibited content. + */ + FinishReason["IMAGE_PROHIBITED_CONTENT"] = "IMAGE_PROHIBITED_CONTENT"; + /** + * The model was expected to generate an image, but none was generated. + */ + FinishReason["NO_IMAGE"] = "NO_IMAGE"; + /** + * Image generation stopped because the generated image may be a recitation from a source. + */ + FinishReason["IMAGE_RECITATION"] = "IMAGE_RECITATION"; + /** + * Image generation stopped for a reason not otherwise specified. + */ + FinishReason["IMAGE_OTHER"] = "IMAGE_OTHER"; +})(FinishReason || (FinishReason = {})); +/** Output only. Harm probability levels in the content. */ +var HarmProbability; +(function (HarmProbability) { + /** + * Harm probability unspecified. + */ + HarmProbability["HARM_PROBABILITY_UNSPECIFIED"] = "HARM_PROBABILITY_UNSPECIFIED"; + /** + * Negligible level of harm. + */ + HarmProbability["NEGLIGIBLE"] = "NEGLIGIBLE"; + /** + * Low level of harm. + */ + HarmProbability["LOW"] = "LOW"; + /** + * Medium level of harm. + */ + HarmProbability["MEDIUM"] = "MEDIUM"; + /** + * High level of harm. + */ + HarmProbability["HIGH"] = "HIGH"; +})(HarmProbability || (HarmProbability = {})); +/** Output only. Harm severity levels in the content. This enum is not supported in Gemini API. */ +var HarmSeverity; +(function (HarmSeverity) { + /** + * Harm severity unspecified. + */ + HarmSeverity["HARM_SEVERITY_UNSPECIFIED"] = "HARM_SEVERITY_UNSPECIFIED"; + /** + * Negligible level of harm severity. + */ + HarmSeverity["HARM_SEVERITY_NEGLIGIBLE"] = "HARM_SEVERITY_NEGLIGIBLE"; + /** + * Low level of harm severity. + */ + HarmSeverity["HARM_SEVERITY_LOW"] = "HARM_SEVERITY_LOW"; + /** + * Medium level of harm severity. + */ + HarmSeverity["HARM_SEVERITY_MEDIUM"] = "HARM_SEVERITY_MEDIUM"; + /** + * High level of harm severity. + */ + HarmSeverity["HARM_SEVERITY_HIGH"] = "HARM_SEVERITY_HIGH"; +})(HarmSeverity || (HarmSeverity = {})); +/** Status of the url retrieval. */ +var UrlRetrievalStatus; +(function (UrlRetrievalStatus) { + /** + * Default value. This value is unused. + */ + UrlRetrievalStatus["URL_RETRIEVAL_STATUS_UNSPECIFIED"] = "URL_RETRIEVAL_STATUS_UNSPECIFIED"; + /** + * Url retrieval is successful. + */ + UrlRetrievalStatus["URL_RETRIEVAL_STATUS_SUCCESS"] = "URL_RETRIEVAL_STATUS_SUCCESS"; + /** + * Url retrieval is failed due to error. + */ + UrlRetrievalStatus["URL_RETRIEVAL_STATUS_ERROR"] = "URL_RETRIEVAL_STATUS_ERROR"; + /** + * Url retrieval is failed because the content is behind paywall. This enum value is not supported in Vertex AI. + */ + UrlRetrievalStatus["URL_RETRIEVAL_STATUS_PAYWALL"] = "URL_RETRIEVAL_STATUS_PAYWALL"; + /** + * Url retrieval is failed because the content is unsafe. This enum value is not supported in Vertex AI. + */ + UrlRetrievalStatus["URL_RETRIEVAL_STATUS_UNSAFE"] = "URL_RETRIEVAL_STATUS_UNSAFE"; +})(UrlRetrievalStatus || (UrlRetrievalStatus = {})); +/** Output only. The reason why the prompt was blocked. */ +var BlockedReason; +(function (BlockedReason) { + /** + * The blocked reason is unspecified. + */ + BlockedReason["BLOCKED_REASON_UNSPECIFIED"] = "BLOCKED_REASON_UNSPECIFIED"; + /** + * The prompt was blocked for safety reasons. + */ + BlockedReason["SAFETY"] = "SAFETY"; + /** + * The prompt was blocked for other reasons. For example, it may be due to the prompt's language, or because it contains other harmful content. + */ + BlockedReason["OTHER"] = "OTHER"; + /** + * The prompt was blocked because it contains a term from the terminology blocklist. + */ + BlockedReason["BLOCKLIST"] = "BLOCKLIST"; + /** + * The prompt was blocked because it contains prohibited content. + */ + BlockedReason["PROHIBITED_CONTENT"] = "PROHIBITED_CONTENT"; + /** + * The prompt was blocked because it contains content that is unsafe for image generation. + */ + BlockedReason["IMAGE_SAFETY"] = "IMAGE_SAFETY"; + /** + * The prompt was blocked by Model Armor. This enum value is not supported in Gemini API. + */ + BlockedReason["MODEL_ARMOR"] = "MODEL_ARMOR"; + /** + * The prompt was blocked as a jailbreak attempt. This enum value is not supported in Gemini API. + */ + BlockedReason["JAILBREAK"] = "JAILBREAK"; +})(BlockedReason || (BlockedReason = {})); +/** Output only. The traffic type for this request. This enum is not supported in Gemini API. */ +var TrafficType; +(function (TrafficType) { + /** + * Unspecified request traffic type. + */ + TrafficType["TRAFFIC_TYPE_UNSPECIFIED"] = "TRAFFIC_TYPE_UNSPECIFIED"; + /** + * The request was processed using Pay-As-You-Go quota. + */ + TrafficType["ON_DEMAND"] = "ON_DEMAND"; + /** + * Type for Provisioned Throughput traffic. + */ + TrafficType["PROVISIONED_THROUGHPUT"] = "PROVISIONED_THROUGHPUT"; +})(TrafficType || (TrafficType = {})); +/** Server content modalities. */ +var Modality; +(function (Modality) { + /** + * The modality is unspecified. + */ + Modality["MODALITY_UNSPECIFIED"] = "MODALITY_UNSPECIFIED"; + /** + * Indicates the model should return text + */ + Modality["TEXT"] = "TEXT"; + /** + * Indicates the model should return images. + */ + Modality["IMAGE"] = "IMAGE"; + /** + * Indicates the model should return audio. + */ + Modality["AUDIO"] = "AUDIO"; +})(Modality || (Modality = {})); +/** The media resolution to use. */ +var MediaResolution; +(function (MediaResolution) { + /** + * Media resolution has not been set + */ + MediaResolution["MEDIA_RESOLUTION_UNSPECIFIED"] = "MEDIA_RESOLUTION_UNSPECIFIED"; + /** + * Media resolution set to low (64 tokens). + */ + MediaResolution["MEDIA_RESOLUTION_LOW"] = "MEDIA_RESOLUTION_LOW"; + /** + * Media resolution set to medium (256 tokens). + */ + MediaResolution["MEDIA_RESOLUTION_MEDIUM"] = "MEDIA_RESOLUTION_MEDIUM"; + /** + * Media resolution set to high (zoomed reframing with 256 tokens). + */ + MediaResolution["MEDIA_RESOLUTION_HIGH"] = "MEDIA_RESOLUTION_HIGH"; +})(MediaResolution || (MediaResolution = {})); +/** Tuning mode. This enum is not supported in Gemini API. */ +var TuningMode; +(function (TuningMode) { + /** + * Tuning mode is unspecified. + */ + TuningMode["TUNING_MODE_UNSPECIFIED"] = "TUNING_MODE_UNSPECIFIED"; + /** + * Full fine-tuning mode. + */ + TuningMode["TUNING_MODE_FULL"] = "TUNING_MODE_FULL"; + /** + * PEFT adapter tuning mode. + */ + TuningMode["TUNING_MODE_PEFT_ADAPTER"] = "TUNING_MODE_PEFT_ADAPTER"; +})(TuningMode || (TuningMode = {})); +/** Adapter size for tuning. This enum is not supported in Gemini API. */ +var AdapterSize; +(function (AdapterSize) { + /** + * Adapter size is unspecified. + */ + AdapterSize["ADAPTER_SIZE_UNSPECIFIED"] = "ADAPTER_SIZE_UNSPECIFIED"; + /** + * Adapter size 1. + */ + AdapterSize["ADAPTER_SIZE_ONE"] = "ADAPTER_SIZE_ONE"; + /** + * Adapter size 2. + */ + AdapterSize["ADAPTER_SIZE_TWO"] = "ADAPTER_SIZE_TWO"; + /** + * Adapter size 4. + */ + AdapterSize["ADAPTER_SIZE_FOUR"] = "ADAPTER_SIZE_FOUR"; + /** + * Adapter size 8. + */ + AdapterSize["ADAPTER_SIZE_EIGHT"] = "ADAPTER_SIZE_EIGHT"; + /** + * Adapter size 16. + */ + AdapterSize["ADAPTER_SIZE_SIXTEEN"] = "ADAPTER_SIZE_SIXTEEN"; + /** + * Adapter size 32. + */ + AdapterSize["ADAPTER_SIZE_THIRTY_TWO"] = "ADAPTER_SIZE_THIRTY_TWO"; +})(AdapterSize || (AdapterSize = {})); +/** Job state. */ +var JobState; +(function (JobState) { + /** + * The job state is unspecified. + */ + JobState["JOB_STATE_UNSPECIFIED"] = "JOB_STATE_UNSPECIFIED"; + /** + * The job has been just created or resumed and processing has not yet begun. + */ + JobState["JOB_STATE_QUEUED"] = "JOB_STATE_QUEUED"; + /** + * The service is preparing to run the job. + */ + JobState["JOB_STATE_PENDING"] = "JOB_STATE_PENDING"; + /** + * The job is in progress. + */ + JobState["JOB_STATE_RUNNING"] = "JOB_STATE_RUNNING"; + /** + * The job completed successfully. + */ + JobState["JOB_STATE_SUCCEEDED"] = "JOB_STATE_SUCCEEDED"; + /** + * The job failed. + */ + JobState["JOB_STATE_FAILED"] = "JOB_STATE_FAILED"; + /** + * The job is being cancelled. From this state the job may only go to either `JOB_STATE_SUCCEEDED`, `JOB_STATE_FAILED` or `JOB_STATE_CANCELLED`. + */ + JobState["JOB_STATE_CANCELLING"] = "JOB_STATE_CANCELLING"; + /** + * The job has been cancelled. + */ + JobState["JOB_STATE_CANCELLED"] = "JOB_STATE_CANCELLED"; + /** + * The job has been stopped, and can be resumed. + */ + JobState["JOB_STATE_PAUSED"] = "JOB_STATE_PAUSED"; + /** + * The job has expired. + */ + JobState["JOB_STATE_EXPIRED"] = "JOB_STATE_EXPIRED"; + /** + * The job is being updated. Only jobs in the `JOB_STATE_RUNNING` state can be updated. After updating, the job goes back to the `JOB_STATE_RUNNING` state. + */ + JobState["JOB_STATE_UPDATING"] = "JOB_STATE_UPDATING"; + /** + * The job is partially succeeded, some results may be missing due to errors. + */ + JobState["JOB_STATE_PARTIALLY_SUCCEEDED"] = "JOB_STATE_PARTIALLY_SUCCEEDED"; +})(JobState || (JobState = {})); +/** The tuning task. Either I2V or T2V. This enum is not supported in Gemini API. */ +var TuningTask; +(function (TuningTask) { + /** + * Default value. This value is unused. + */ + TuningTask["TUNING_TASK_UNSPECIFIED"] = "TUNING_TASK_UNSPECIFIED"; + /** + * Tuning task for image to video. + */ + TuningTask["TUNING_TASK_I2V"] = "TUNING_TASK_I2V"; + /** + * Tuning task for text to video. + */ + TuningTask["TUNING_TASK_T2V"] = "TUNING_TASK_T2V"; + /** + * Tuning task for reference to video. + */ + TuningTask["TUNING_TASK_R2V"] = "TUNING_TASK_R2V"; +})(TuningTask || (TuningTask = {})); +/** The tokenization quality used for given media. */ +var PartMediaResolutionLevel; +(function (PartMediaResolutionLevel) { + /** + * Media resolution has not been set. + */ + PartMediaResolutionLevel["MEDIA_RESOLUTION_UNSPECIFIED"] = "MEDIA_RESOLUTION_UNSPECIFIED"; + /** + * Media resolution set to low. + */ + PartMediaResolutionLevel["MEDIA_RESOLUTION_LOW"] = "MEDIA_RESOLUTION_LOW"; + /** + * Media resolution set to medium. + */ + PartMediaResolutionLevel["MEDIA_RESOLUTION_MEDIUM"] = "MEDIA_RESOLUTION_MEDIUM"; + /** + * Media resolution set to high. + */ + PartMediaResolutionLevel["MEDIA_RESOLUTION_HIGH"] = "MEDIA_RESOLUTION_HIGH"; + /** + * Media resolution set to ultra high. + */ + PartMediaResolutionLevel["MEDIA_RESOLUTION_ULTRA_HIGH"] = "MEDIA_RESOLUTION_ULTRA_HIGH"; +})(PartMediaResolutionLevel || (PartMediaResolutionLevel = {})); +/** Resource scope. */ +var ResourceScope; +(function (ResourceScope) { + /** + * When setting base_url, this value configures resource scope to be the collection. + The resource name will not include api version, project, or location. + For example, if base_url is set to "https://aiplatform.googleapis.com", + then the resource name for a Model would be + "https://aiplatform.googleapis.com/publishers/google/models/gemini-3-pro-preview + */ + ResourceScope["COLLECTION"] = "COLLECTION"; +})(ResourceScope || (ResourceScope = {})); +/** Options for feature selection preference. */ +var FeatureSelectionPreference; +(function (FeatureSelectionPreference) { + FeatureSelectionPreference["FEATURE_SELECTION_PREFERENCE_UNSPECIFIED"] = "FEATURE_SELECTION_PREFERENCE_UNSPECIFIED"; + FeatureSelectionPreference["PRIORITIZE_QUALITY"] = "PRIORITIZE_QUALITY"; + FeatureSelectionPreference["BALANCED"] = "BALANCED"; + FeatureSelectionPreference["PRIORITIZE_COST"] = "PRIORITIZE_COST"; +})(FeatureSelectionPreference || (FeatureSelectionPreference = {})); +/** The environment being operated. */ +var Environment; +(function (Environment) { + /** + * Defaults to browser. + */ + Environment["ENVIRONMENT_UNSPECIFIED"] = "ENVIRONMENT_UNSPECIFIED"; + /** + * Operates in a web browser. + */ + Environment["ENVIRONMENT_BROWSER"] = "ENVIRONMENT_BROWSER"; +})(Environment || (Environment = {})); +/** Enum that controls the safety filter level for objectionable content. */ +var SafetyFilterLevel; +(function (SafetyFilterLevel) { + SafetyFilterLevel["BLOCK_LOW_AND_ABOVE"] = "BLOCK_LOW_AND_ABOVE"; + SafetyFilterLevel["BLOCK_MEDIUM_AND_ABOVE"] = "BLOCK_MEDIUM_AND_ABOVE"; + SafetyFilterLevel["BLOCK_ONLY_HIGH"] = "BLOCK_ONLY_HIGH"; + SafetyFilterLevel["BLOCK_NONE"] = "BLOCK_NONE"; +})(SafetyFilterLevel || (SafetyFilterLevel = {})); +/** Enum that controls the generation of people. */ +var PersonGeneration; +(function (PersonGeneration) { + /** + * Block generation of images of people. + */ + PersonGeneration["DONT_ALLOW"] = "DONT_ALLOW"; + /** + * Generate images of adults, but not children. + */ + PersonGeneration["ALLOW_ADULT"] = "ALLOW_ADULT"; + /** + * Generate images that include adults and children. + */ + PersonGeneration["ALLOW_ALL"] = "ALLOW_ALL"; +})(PersonGeneration || (PersonGeneration = {})); +/** Enum that specifies the language of the text in the prompt. */ +var ImagePromptLanguage; +(function (ImagePromptLanguage) { + /** + * Auto-detect the language. + */ + ImagePromptLanguage["auto"] = "auto"; + /** + * English + */ + ImagePromptLanguage["en"] = "en"; + /** + * Japanese + */ + ImagePromptLanguage["ja"] = "ja"; + /** + * Korean + */ + ImagePromptLanguage["ko"] = "ko"; + /** + * Hindi + */ + ImagePromptLanguage["hi"] = "hi"; + /** + * Chinese + */ + ImagePromptLanguage["zh"] = "zh"; + /** + * Portuguese + */ + ImagePromptLanguage["pt"] = "pt"; + /** + * Spanish + */ + ImagePromptLanguage["es"] = "es"; +})(ImagePromptLanguage || (ImagePromptLanguage = {})); +/** Enum representing the mask mode of a mask reference image. */ +var MaskReferenceMode; +(function (MaskReferenceMode) { + MaskReferenceMode["MASK_MODE_DEFAULT"] = "MASK_MODE_DEFAULT"; + MaskReferenceMode["MASK_MODE_USER_PROVIDED"] = "MASK_MODE_USER_PROVIDED"; + MaskReferenceMode["MASK_MODE_BACKGROUND"] = "MASK_MODE_BACKGROUND"; + MaskReferenceMode["MASK_MODE_FOREGROUND"] = "MASK_MODE_FOREGROUND"; + MaskReferenceMode["MASK_MODE_SEMANTIC"] = "MASK_MODE_SEMANTIC"; +})(MaskReferenceMode || (MaskReferenceMode = {})); +/** Enum representing the control type of a control reference image. */ +var ControlReferenceType; +(function (ControlReferenceType) { + ControlReferenceType["CONTROL_TYPE_DEFAULT"] = "CONTROL_TYPE_DEFAULT"; + ControlReferenceType["CONTROL_TYPE_CANNY"] = "CONTROL_TYPE_CANNY"; + ControlReferenceType["CONTROL_TYPE_SCRIBBLE"] = "CONTROL_TYPE_SCRIBBLE"; + ControlReferenceType["CONTROL_TYPE_FACE_MESH"] = "CONTROL_TYPE_FACE_MESH"; +})(ControlReferenceType || (ControlReferenceType = {})); +/** Enum representing the subject type of a subject reference image. */ +var SubjectReferenceType; +(function (SubjectReferenceType) { + SubjectReferenceType["SUBJECT_TYPE_DEFAULT"] = "SUBJECT_TYPE_DEFAULT"; + SubjectReferenceType["SUBJECT_TYPE_PERSON"] = "SUBJECT_TYPE_PERSON"; + SubjectReferenceType["SUBJECT_TYPE_ANIMAL"] = "SUBJECT_TYPE_ANIMAL"; + SubjectReferenceType["SUBJECT_TYPE_PRODUCT"] = "SUBJECT_TYPE_PRODUCT"; +})(SubjectReferenceType || (SubjectReferenceType = {})); +/** Enum representing the editing mode. */ +var EditMode; +(function (EditMode) { + EditMode["EDIT_MODE_DEFAULT"] = "EDIT_MODE_DEFAULT"; + EditMode["EDIT_MODE_INPAINT_REMOVAL"] = "EDIT_MODE_INPAINT_REMOVAL"; + EditMode["EDIT_MODE_INPAINT_INSERTION"] = "EDIT_MODE_INPAINT_INSERTION"; + EditMode["EDIT_MODE_OUTPAINT"] = "EDIT_MODE_OUTPAINT"; + EditMode["EDIT_MODE_CONTROLLED_EDITING"] = "EDIT_MODE_CONTROLLED_EDITING"; + EditMode["EDIT_MODE_STYLE"] = "EDIT_MODE_STYLE"; + EditMode["EDIT_MODE_BGSWAP"] = "EDIT_MODE_BGSWAP"; + EditMode["EDIT_MODE_PRODUCT_IMAGE"] = "EDIT_MODE_PRODUCT_IMAGE"; +})(EditMode || (EditMode = {})); +/** Enum that represents the segmentation mode. */ +var SegmentMode; +(function (SegmentMode) { + SegmentMode["FOREGROUND"] = "FOREGROUND"; + SegmentMode["BACKGROUND"] = "BACKGROUND"; + SegmentMode["PROMPT"] = "PROMPT"; + SegmentMode["SEMANTIC"] = "SEMANTIC"; + SegmentMode["INTERACTIVE"] = "INTERACTIVE"; +})(SegmentMode || (SegmentMode = {})); +/** Enum for the reference type of a video generation reference image. */ +var VideoGenerationReferenceType; +(function (VideoGenerationReferenceType) { + /** + * A reference image that provides assets to the generated video, + such as the scene, an object, a character, etc. + */ + VideoGenerationReferenceType["ASSET"] = "ASSET"; + /** + * A reference image that provides aesthetics including colors, + lighting, texture, etc., to be used as the style of the generated video, + such as 'anime', 'photography', 'origami', etc. + */ + VideoGenerationReferenceType["STYLE"] = "STYLE"; +})(VideoGenerationReferenceType || (VideoGenerationReferenceType = {})); +/** Enum for the mask mode of a video generation mask. */ +var VideoGenerationMaskMode; +(function (VideoGenerationMaskMode) { + /** + * The image mask contains a masked rectangular region which is + applied on the first frame of the input video. The object described in + the prompt is inserted into this region and will appear in subsequent + frames. + */ + VideoGenerationMaskMode["INSERT"] = "INSERT"; + /** + * The image mask is used to determine an object in the + first video frame to track. This object is removed from the video. + */ + VideoGenerationMaskMode["REMOVE"] = "REMOVE"; + /** + * The image mask is used to determine a region in the + video. Objects in this region will be removed. + */ + VideoGenerationMaskMode["REMOVE_STATIC"] = "REMOVE_STATIC"; + /** + * The image mask contains a masked rectangular region where + the input video will go. The remaining area will be generated. Video + masks are not supported. + */ + VideoGenerationMaskMode["OUTPAINT"] = "OUTPAINT"; +})(VideoGenerationMaskMode || (VideoGenerationMaskMode = {})); +/** Enum that controls the compression quality of the generated videos. */ +var VideoCompressionQuality; +(function (VideoCompressionQuality) { + /** + * Optimized video compression quality. This will produce videos + with a compressed, smaller file size. + */ + VideoCompressionQuality["OPTIMIZED"] = "OPTIMIZED"; + /** + * Lossless video compression quality. This will produce videos + with a larger file size. + */ + VideoCompressionQuality["LOSSLESS"] = "LOSSLESS"; +})(VideoCompressionQuality || (VideoCompressionQuality = {})); +/** Enum representing the tuning method. */ +var TuningMethod; +(function (TuningMethod) { + /** + * Supervised fine tuning. + */ + TuningMethod["SUPERVISED_FINE_TUNING"] = "SUPERVISED_FINE_TUNING"; + /** + * Preference optimization tuning. + */ + TuningMethod["PREFERENCE_TUNING"] = "PREFERENCE_TUNING"; + /** + * Distillation tuning. + */ + TuningMethod["DISTILLATION"] = "DISTILLATION"; +})(TuningMethod || (TuningMethod = {})); +/** State for the lifecycle of a Document. */ +var DocumentState; +(function (DocumentState) { + DocumentState["STATE_UNSPECIFIED"] = "STATE_UNSPECIFIED"; + DocumentState["STATE_PENDING"] = "STATE_PENDING"; + DocumentState["STATE_ACTIVE"] = "STATE_ACTIVE"; + DocumentState["STATE_FAILED"] = "STATE_FAILED"; +})(DocumentState || (DocumentState = {})); +/** State for the lifecycle of a File. */ +var FileState; +(function (FileState) { + FileState["STATE_UNSPECIFIED"] = "STATE_UNSPECIFIED"; + FileState["PROCESSING"] = "PROCESSING"; + FileState["ACTIVE"] = "ACTIVE"; + FileState["FAILED"] = "FAILED"; +})(FileState || (FileState = {})); +/** Source of the File. */ +var FileSource; +(function (FileSource) { + FileSource["SOURCE_UNSPECIFIED"] = "SOURCE_UNSPECIFIED"; + FileSource["UPLOADED"] = "UPLOADED"; + FileSource["GENERATED"] = "GENERATED"; + FileSource["REGISTERED"] = "REGISTERED"; +})(FileSource || (FileSource = {})); +/** The reason why the turn is complete. */ +var TurnCompleteReason; +(function (TurnCompleteReason) { + /** + * Default value. Reason is unspecified. + */ + TurnCompleteReason["TURN_COMPLETE_REASON_UNSPECIFIED"] = "TURN_COMPLETE_REASON_UNSPECIFIED"; + /** + * The function call generated by the model is invalid. + */ + TurnCompleteReason["MALFORMED_FUNCTION_CALL"] = "MALFORMED_FUNCTION_CALL"; + /** + * The response is rejected by the model. + */ + TurnCompleteReason["RESPONSE_REJECTED"] = "RESPONSE_REJECTED"; + /** + * Needs more input from the user. + */ + TurnCompleteReason["NEED_MORE_INPUT"] = "NEED_MORE_INPUT"; +})(TurnCompleteReason || (TurnCompleteReason = {})); +/** Server content modalities. */ +var MediaModality; +(function (MediaModality) { + /** + * The modality is unspecified. + */ + MediaModality["MODALITY_UNSPECIFIED"] = "MODALITY_UNSPECIFIED"; + /** + * Plain text. + */ + MediaModality["TEXT"] = "TEXT"; + /** + * Images. + */ + MediaModality["IMAGE"] = "IMAGE"; + /** + * Video. + */ + MediaModality["VIDEO"] = "VIDEO"; + /** + * Audio. + */ + MediaModality["AUDIO"] = "AUDIO"; + /** + * Document, e.g. PDF. + */ + MediaModality["DOCUMENT"] = "DOCUMENT"; +})(MediaModality || (MediaModality = {})); +/** The type of the VAD signal. */ +var VadSignalType; +(function (VadSignalType) { + /** + * The default is VAD_SIGNAL_TYPE_UNSPECIFIED. + */ + VadSignalType["VAD_SIGNAL_TYPE_UNSPECIFIED"] = "VAD_SIGNAL_TYPE_UNSPECIFIED"; + /** + * Start of sentence signal. + */ + VadSignalType["VAD_SIGNAL_TYPE_SOS"] = "VAD_SIGNAL_TYPE_SOS"; + /** + * End of sentence signal. + */ + VadSignalType["VAD_SIGNAL_TYPE_EOS"] = "VAD_SIGNAL_TYPE_EOS"; +})(VadSignalType || (VadSignalType = {})); +/** The type of the voice activity signal. */ +var VoiceActivityType; +(function (VoiceActivityType) { + /** + * The default is VOICE_ACTIVITY_TYPE_UNSPECIFIED. + */ + VoiceActivityType["TYPE_UNSPECIFIED"] = "TYPE_UNSPECIFIED"; + /** + * Start of sentence signal. + */ + VoiceActivityType["ACTIVITY_START"] = "ACTIVITY_START"; + /** + * End of sentence signal. + */ + VoiceActivityType["ACTIVITY_END"] = "ACTIVITY_END"; +})(VoiceActivityType || (VoiceActivityType = {})); +/** Start of speech sensitivity. */ +var StartSensitivity; +(function (StartSensitivity) { + /** + * The default is START_SENSITIVITY_LOW. + */ + StartSensitivity["START_SENSITIVITY_UNSPECIFIED"] = "START_SENSITIVITY_UNSPECIFIED"; + /** + * Automatic detection will detect the start of speech more often. + */ + StartSensitivity["START_SENSITIVITY_HIGH"] = "START_SENSITIVITY_HIGH"; + /** + * Automatic detection will detect the start of speech less often. + */ + StartSensitivity["START_SENSITIVITY_LOW"] = "START_SENSITIVITY_LOW"; +})(StartSensitivity || (StartSensitivity = {})); +/** End of speech sensitivity. */ +var EndSensitivity; +(function (EndSensitivity) { + /** + * The default is END_SENSITIVITY_LOW. + */ + EndSensitivity["END_SENSITIVITY_UNSPECIFIED"] = "END_SENSITIVITY_UNSPECIFIED"; + /** + * Automatic detection ends speech more often. + */ + EndSensitivity["END_SENSITIVITY_HIGH"] = "END_SENSITIVITY_HIGH"; + /** + * Automatic detection ends speech less often. + */ + EndSensitivity["END_SENSITIVITY_LOW"] = "END_SENSITIVITY_LOW"; +})(EndSensitivity || (EndSensitivity = {})); +/** The different ways of handling user activity. */ +var ActivityHandling; +(function (ActivityHandling) { + /** + * If unspecified, the default behavior is `START_OF_ACTIVITY_INTERRUPTS`. + */ + ActivityHandling["ACTIVITY_HANDLING_UNSPECIFIED"] = "ACTIVITY_HANDLING_UNSPECIFIED"; + /** + * If true, start of activity will interrupt the model's response (also called "barge in"). The model's current response will be cut-off in the moment of the interruption. This is the default behavior. + */ + ActivityHandling["START_OF_ACTIVITY_INTERRUPTS"] = "START_OF_ACTIVITY_INTERRUPTS"; + /** + * The model's response will not be interrupted. + */ + ActivityHandling["NO_INTERRUPTION"] = "NO_INTERRUPTION"; +})(ActivityHandling || (ActivityHandling = {})); +/** Options about which input is included in the user's turn. */ +var TurnCoverage; +(function (TurnCoverage) { + /** + * If unspecified, the default behavior is `TURN_INCLUDES_ONLY_ACTIVITY`. + */ + TurnCoverage["TURN_COVERAGE_UNSPECIFIED"] = "TURN_COVERAGE_UNSPECIFIED"; + /** + * The users turn only includes activity since the last turn, excluding inactivity (e.g. silence on the audio stream). This is the default behavior. + */ + TurnCoverage["TURN_INCLUDES_ONLY_ACTIVITY"] = "TURN_INCLUDES_ONLY_ACTIVITY"; + /** + * The users turn includes all realtime input since the last turn, including inactivity (e.g. silence on the audio stream). + */ + TurnCoverage["TURN_INCLUDES_ALL_INPUT"] = "TURN_INCLUDES_ALL_INPUT"; +})(TurnCoverage || (TurnCoverage = {})); +/** Scale of the generated music. */ +var Scale; +(function (Scale) { + /** + * Default value. This value is unused. + */ + Scale["SCALE_UNSPECIFIED"] = "SCALE_UNSPECIFIED"; + /** + * C major or A minor. + */ + Scale["C_MAJOR_A_MINOR"] = "C_MAJOR_A_MINOR"; + /** + * Db major or Bb minor. + */ + Scale["D_FLAT_MAJOR_B_FLAT_MINOR"] = "D_FLAT_MAJOR_B_FLAT_MINOR"; + /** + * D major or B minor. + */ + Scale["D_MAJOR_B_MINOR"] = "D_MAJOR_B_MINOR"; + /** + * Eb major or C minor + */ + Scale["E_FLAT_MAJOR_C_MINOR"] = "E_FLAT_MAJOR_C_MINOR"; + /** + * E major or Db minor. + */ + Scale["E_MAJOR_D_FLAT_MINOR"] = "E_MAJOR_D_FLAT_MINOR"; + /** + * F major or D minor. + */ + Scale["F_MAJOR_D_MINOR"] = "F_MAJOR_D_MINOR"; + /** + * Gb major or Eb minor. + */ + Scale["G_FLAT_MAJOR_E_FLAT_MINOR"] = "G_FLAT_MAJOR_E_FLAT_MINOR"; + /** + * G major or E minor. + */ + Scale["G_MAJOR_E_MINOR"] = "G_MAJOR_E_MINOR"; + /** + * Ab major or F minor. + */ + Scale["A_FLAT_MAJOR_F_MINOR"] = "A_FLAT_MAJOR_F_MINOR"; + /** + * A major or Gb minor. + */ + Scale["A_MAJOR_G_FLAT_MINOR"] = "A_MAJOR_G_FLAT_MINOR"; + /** + * Bb major or G minor. + */ + Scale["B_FLAT_MAJOR_G_MINOR"] = "B_FLAT_MAJOR_G_MINOR"; + /** + * B major or Ab minor. + */ + Scale["B_MAJOR_A_FLAT_MINOR"] = "B_MAJOR_A_FLAT_MINOR"; +})(Scale || (Scale = {})); +/** The mode of music generation. */ +var MusicGenerationMode; +(function (MusicGenerationMode) { + /** + * Rely on the server default generation mode. + */ + MusicGenerationMode["MUSIC_GENERATION_MODE_UNSPECIFIED"] = "MUSIC_GENERATION_MODE_UNSPECIFIED"; + /** + * Steer text prompts to regions of latent space with higher quality + music. + */ + MusicGenerationMode["QUALITY"] = "QUALITY"; + /** + * Steer text prompts to regions of latent space with a larger + diversity of music. + */ + MusicGenerationMode["DIVERSITY"] = "DIVERSITY"; + /** + * Steer text prompts to regions of latent space more likely to + generate music with vocals. + */ + MusicGenerationMode["VOCALIZATION"] = "VOCALIZATION"; +})(MusicGenerationMode || (MusicGenerationMode = {})); +/** The playback control signal to apply to the music generation. */ +var LiveMusicPlaybackControl; +(function (LiveMusicPlaybackControl) { + /** + * This value is unused. + */ + LiveMusicPlaybackControl["PLAYBACK_CONTROL_UNSPECIFIED"] = "PLAYBACK_CONTROL_UNSPECIFIED"; + /** + * Start generating the music. + */ + LiveMusicPlaybackControl["PLAY"] = "PLAY"; + /** + * Hold the music generation. Use PLAY to resume from the current position. + */ + LiveMusicPlaybackControl["PAUSE"] = "PAUSE"; + /** + * Stop the music generation and reset the context (prompts retained). + Use PLAY to restart the music generation. + */ + LiveMusicPlaybackControl["STOP"] = "STOP"; + /** + * Reset the context of the music generation without stopping it. + Retains the current prompts and config. + */ + LiveMusicPlaybackControl["RESET_CONTEXT"] = "RESET_CONTEXT"; +})(LiveMusicPlaybackControl || (LiveMusicPlaybackControl = {})); +/** Raw media bytes for function response. + +Text should not be sent as raw bytes, use the FunctionResponse.response +field. */ +class FunctionResponseBlob { +} +/** URI based data for function response. */ +class FunctionResponseFileData { +} +/** A datatype containing media that is part of a `FunctionResponse` message. + +A `FunctionResponsePart` consists of data which has an associated datatype. A +`FunctionResponsePart` can only contain one of the accepted types in +`FunctionResponsePart.data`. + +A `FunctionResponsePart` must have a fixed IANA MIME type identifying the +type and subtype of the media if the `inline_data` field is filled with raw +bytes. */ +class FunctionResponsePart { +} +/** + * Creates a `FunctionResponsePart` object from a `base64` encoded `string`. + */ +function createFunctionResponsePartFromBase64(data, mimeType) { + return { + inlineData: { + data: data, + mimeType: mimeType, + }, + }; +} +/** + * Creates a `FunctionResponsePart` object from a `URI` string. + */ +function createFunctionResponsePartFromUri(uri, mimeType) { + return { + fileData: { + fileUri: uri, + mimeType: mimeType, + }, + }; +} +/** A function response. */ +class FunctionResponse { +} +/** + * Creates a `Part` object from a `URI` string. + */ +function createPartFromUri(uri, mimeType, mediaResolution) { + return Object.assign({ fileData: { + fileUri: uri, + mimeType: mimeType, + } }, (mediaResolution && { mediaResolution: { level: mediaResolution } })); +} +/** + * Creates a `Part` object from a `text` string. + */ +function createPartFromText(text) { + return { + text: text, + }; +} +/** + * Creates a `Part` object from a `FunctionCall` object. + */ +function createPartFromFunctionCall(name, args) { + return { + functionCall: { + name: name, + args: args, + }, + }; +} +/** + * Creates a `Part` object from a `FunctionResponse` object. + */ +function createPartFromFunctionResponse(id, name, response, parts = []) { + return { + functionResponse: Object.assign({ id: id, name: name, response: response }, (parts.length > 0 && { parts })), + }; +} +/** + * Creates a `Part` object from a `base64` encoded `string`. + */ +function createPartFromBase64(data, mimeType, mediaResolution) { + return Object.assign({ inlineData: { + data: data, + mimeType: mimeType, + } }, (mediaResolution && { mediaResolution: { level: mediaResolution } })); +} +/** + * Creates a `Part` object from the `outcome` and `output` of a `CodeExecutionResult` object. + */ +function createPartFromCodeExecutionResult(outcome, output) { + return { + codeExecutionResult: { + outcome: outcome, + output: output, + }, + }; +} +/** + * Creates a `Part` object from the `code` and `language` of an `ExecutableCode` object. + */ +function createPartFromExecutableCode(code, language) { + return { + executableCode: { + code: code, + language: language, + }, + }; +} +function _isPart(obj) { + if (typeof obj === 'object' && obj !== null) { + return ('fileData' in obj || + 'text' in obj || + 'functionCall' in obj || + 'functionResponse' in obj || + 'inlineData' in obj || + 'videoMetadata' in obj || + 'codeExecutionResult' in obj || + 'executableCode' in obj); + } + return false; +} +function _toParts(partOrString) { + const parts = []; + if (typeof partOrString === 'string') { + parts.push(createPartFromText(partOrString)); + } + else if (_isPart(partOrString)) { + parts.push(partOrString); + } + else if (Array.isArray(partOrString)) { + if (partOrString.length === 0) { + throw new Error('partOrString cannot be an empty array'); + } + for (const part of partOrString) { + if (typeof part === 'string') { + parts.push(createPartFromText(part)); + } + else if (_isPart(part)) { + parts.push(part); + } + else { + throw new Error('element in PartUnion must be a Part object or string'); + } + } + } + else { + throw new Error('partOrString must be a Part object, string, or array'); + } + return parts; +} +/** + * Creates a `Content` object with a user role from a `PartListUnion` object or `string`. + */ +function createUserContent(partOrString) { + return { + role: 'user', + parts: _toParts(partOrString), + }; +} +/** + * Creates a `Content` object with a model role from a `PartListUnion` object or `string`. + */ +function createModelContent(partOrString) { + return { + role: 'model', + parts: _toParts(partOrString), + }; +} +/** A wrapper class for the http response. */ +class HttpResponse { + constructor(response) { + // Process the headers. + const headers = {}; + for (const pair of response.headers.entries()) { + headers[pair[0]] = pair[1]; + } + this.headers = headers; + // Keep the original response. + this.responseInternal = response; + } + json() { + return this.responseInternal.json(); + } +} +/** Content filter results for a prompt sent in the request. Note: This is sent only in the first stream chunk and only if no candidates were generated due to content violations. */ +class GenerateContentResponsePromptFeedback { +} +/** Usage metadata about the content generation request and response. This message provides a detailed breakdown of token usage and other relevant metrics. This data type is not supported in Gemini API. */ +class GenerateContentResponseUsageMetadata { +} +/** Response message for PredictionService.GenerateContent. */ +class GenerateContentResponse { + /** + * Returns the concatenation of all text parts from the first candidate in the response. + * + * @remarks + * If there are multiple candidates in the response, the text from the first + * one will be returned. + * If there are non-text parts in the response, the concatenation of all text + * parts will be returned, and a warning will be logged. + * If there are thought parts in the response, the concatenation of all text + * parts excluding the thought parts will be returned. + * + * @example + * ```ts + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: + * 'Why is the sky blue?', + * }); + * + * console.debug(response.text); + * ``` + */ + get text() { + var _a, _b, _c, _d, _e, _f, _g, _h; + if (((_d = (_c = (_b = (_a = this.candidates) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.parts) === null || _d === void 0 ? void 0 : _d.length) === 0) { + return undefined; + } + if (this.candidates && this.candidates.length > 1) { + console.warn('there are multiple candidates in the response, returning text from the first one.'); + } + let text = ''; + let anyTextPartText = false; + const nonTextParts = []; + for (const part of (_h = (_g = (_f = (_e = this.candidates) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.content) === null || _g === void 0 ? void 0 : _g.parts) !== null && _h !== void 0 ? _h : []) { + for (const [fieldName, fieldValue] of Object.entries(part)) { + if (fieldName !== 'text' && + fieldName !== 'thought' && + fieldName !== 'thoughtSignature' && + (fieldValue !== null || fieldValue !== undefined)) { + nonTextParts.push(fieldName); + } + } + if (typeof part.text === 'string') { + if (typeof part.thought === 'boolean' && part.thought) { + continue; + } + anyTextPartText = true; + text += part.text; + } + } + if (nonTextParts.length > 0) { + console.warn(`there are non-text parts ${nonTextParts} in the response, returning concatenation of all text parts. Please refer to the non text parts for a full response from model.`); + } + // part.text === '' is different from part.text is null + return anyTextPartText ? text : undefined; + } + /** + * Returns the concatenation of all inline data parts from the first candidate + * in the response. + * + * @remarks + * If there are multiple candidates in the response, the inline data from the + * first one will be returned. If there are non-inline data parts in the + * response, the concatenation of all inline data parts will be returned, and + * a warning will be logged. + */ + get data() { + var _a, _b, _c, _d, _e, _f, _g, _h; + if (((_d = (_c = (_b = (_a = this.candidates) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.parts) === null || _d === void 0 ? void 0 : _d.length) === 0) { + return undefined; + } + if (this.candidates && this.candidates.length > 1) { + console.warn('there are multiple candidates in the response, returning data from the first one.'); + } + let data = ''; + const nonDataParts = []; + for (const part of (_h = (_g = (_f = (_e = this.candidates) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.content) === null || _g === void 0 ? void 0 : _g.parts) !== null && _h !== void 0 ? _h : []) { + for (const [fieldName, fieldValue] of Object.entries(part)) { + if (fieldName !== 'inlineData' && + (fieldValue !== null || fieldValue !== undefined)) { + nonDataParts.push(fieldName); + } + } + if (part.inlineData && typeof part.inlineData.data === 'string') { + data += atob(part.inlineData.data); + } + } + if (nonDataParts.length > 0) { + console.warn(`there are non-data parts ${nonDataParts} in the response, returning concatenation of all data parts. Please refer to the non data parts for a full response from model.`); + } + return data.length > 0 ? btoa(data) : undefined; + } + /** + * Returns the function calls from the first candidate in the response. + * + * @remarks + * If there are multiple candidates in the response, the function calls from + * the first one will be returned. + * If there are no function calls in the response, undefined will be returned. + * + * @example + * ```ts + * const controlLightFunctionDeclaration: FunctionDeclaration = { + * name: 'controlLight', + * parameters: { + * type: Type.OBJECT, + * description: 'Set the brightness and color temperature of a room light.', + * properties: { + * brightness: { + * type: Type.NUMBER, + * description: + * 'Light level from 0 to 100. Zero is off and 100 is full brightness.', + * }, + * colorTemperature: { + * type: Type.STRING, + * description: + * 'Color temperature of the light fixture which can be `daylight`, `cool` or `warm`.', + * }, + * }, + * required: ['brightness', 'colorTemperature'], + * }; + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: 'Dim the lights so the room feels cozy and warm.', + * config: { + * tools: [{functionDeclarations: [controlLightFunctionDeclaration]}], + * toolConfig: { + * functionCallingConfig: { + * mode: FunctionCallingConfigMode.ANY, + * allowedFunctionNames: ['controlLight'], + * }, + * }, + * }, + * }); + * console.debug(JSON.stringify(response.functionCalls)); + * ``` + */ + get functionCalls() { + var _a, _b, _c, _d, _e, _f, _g, _h; + if (((_d = (_c = (_b = (_a = this.candidates) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.parts) === null || _d === void 0 ? void 0 : _d.length) === 0) { + return undefined; + } + if (this.candidates && this.candidates.length > 1) { + console.warn('there are multiple candidates in the response, returning function calls from the first one.'); + } + const functionCalls = (_h = (_g = (_f = (_e = this.candidates) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.content) === null || _g === void 0 ? void 0 : _g.parts) === null || _h === void 0 ? void 0 : _h.filter((part) => part.functionCall).map((part) => part.functionCall).filter((functionCall) => functionCall !== undefined); + if ((functionCalls === null || functionCalls === void 0 ? void 0 : functionCalls.length) === 0) { + return undefined; + } + return functionCalls; + } + /** + * Returns the first executable code from the first candidate in the response. + * + * @remarks + * If there are multiple candidates in the response, the executable code from + * the first one will be returned. + * If there are no executable code in the response, undefined will be + * returned. + * + * @example + * ```ts + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: + * 'What is the sum of the first 50 prime numbers? Generate and run code for the calculation, and make sure you get all 50.' + * config: { + * tools: [{codeExecution: {}}], + * }, + * }); + * + * console.debug(response.executableCode); + * ``` + */ + get executableCode() { + var _a, _b, _c, _d, _e, _f, _g, _h, _j; + if (((_d = (_c = (_b = (_a = this.candidates) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.parts) === null || _d === void 0 ? void 0 : _d.length) === 0) { + return undefined; + } + if (this.candidates && this.candidates.length > 1) { + console.warn('there are multiple candidates in the response, returning executable code from the first one.'); + } + const executableCode = (_h = (_g = (_f = (_e = this.candidates) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.content) === null || _g === void 0 ? void 0 : _g.parts) === null || _h === void 0 ? void 0 : _h.filter((part) => part.executableCode).map((part) => part.executableCode).filter((executableCode) => executableCode !== undefined); + if ((executableCode === null || executableCode === void 0 ? void 0 : executableCode.length) === 0) { + return undefined; + } + return (_j = executableCode === null || executableCode === void 0 ? void 0 : executableCode[0]) === null || _j === void 0 ? void 0 : _j.code; + } + /** + * Returns the first code execution result from the first candidate in the response. + * + * @remarks + * If there are multiple candidates in the response, the code execution result from + * the first one will be returned. + * If there are no code execution result in the response, undefined will be returned. + * + * @example + * ```ts + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: + * 'What is the sum of the first 50 prime numbers? Generate and run code for the calculation, and make sure you get all 50.' + * config: { + * tools: [{codeExecution: {}}], + * }, + * }); + * + * console.debug(response.codeExecutionResult); + * ``` + */ + get codeExecutionResult() { + var _a, _b, _c, _d, _e, _f, _g, _h, _j; + if (((_d = (_c = (_b = (_a = this.candidates) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.parts) === null || _d === void 0 ? void 0 : _d.length) === 0) { + return undefined; + } + if (this.candidates && this.candidates.length > 1) { + console.warn('there are multiple candidates in the response, returning code execution result from the first one.'); + } + const codeExecutionResult = (_h = (_g = (_f = (_e = this.candidates) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.content) === null || _g === void 0 ? void 0 : _g.parts) === null || _h === void 0 ? void 0 : _h.filter((part) => part.codeExecutionResult).map((part) => part.codeExecutionResult).filter((codeExecutionResult) => codeExecutionResult !== undefined); + if ((codeExecutionResult === null || codeExecutionResult === void 0 ? void 0 : codeExecutionResult.length) === 0) { + return undefined; + } + return (_j = codeExecutionResult === null || codeExecutionResult === void 0 ? void 0 : codeExecutionResult[0]) === null || _j === void 0 ? void 0 : _j.output; + } +} +/** Response for the embed_content method. */ +class EmbedContentResponse { +} +/** The output images response. */ +class GenerateImagesResponse { +} +/** Response for the request to edit an image. */ +class EditImageResponse { +} +class UpscaleImageResponse { +} +/** The output images response. */ +class RecontextImageResponse { +} +/** The output images response. */ +class SegmentImageResponse { +} +class ListModelsResponse { +} +class DeleteModelResponse { +} +/** Response for counting tokens. */ +class CountTokensResponse { +} +/** Response for computing tokens. */ +class ComputeTokensResponse { +} +/** Response with generated videos. */ +class GenerateVideosResponse { +} +/** A video generation operation. */ +class GenerateVideosOperation { + /** + * Instantiates an Operation of the same type as the one being called with the fields set from the API response. + * @internal + */ + _fromAPIResponse({ apiResponse, _isVertexAI, }) { + const operation = new GenerateVideosOperation(); + let response; + const op = apiResponse; + if (_isVertexAI) { + response = generateVideosOperationFromVertex$1(op); + } + else { + response = generateVideosOperationFromMldev$1(op); + } + Object.assign(operation, response); + return operation; + } +} +/** Response for the list tuning jobs method. */ +class ListTuningJobsResponse { +} +/** Empty response for tunings.cancel method. */ +class CancelTuningJobResponse { +} +/** Empty response for caches.delete method. */ +class DeleteCachedContentResponse { +} +class ListCachedContentsResponse { +} +/** Config for documents.list return value. */ +class ListDocumentsResponse { +} +/** Config for file_search_stores.list return value. */ +class ListFileSearchStoresResponse { +} +/** Response for the resumable upload method. */ +class UploadToFileSearchStoreResumableResponse { +} +/** Response for ImportFile to import a File API file with a file search store. */ +class ImportFileResponse { +} +/** Long-running operation for importing a file to a FileSearchStore. */ +class ImportFileOperation { + /** + * Instantiates an Operation of the same type as the one being called with the fields set from the API response. + * @internal + */ + _fromAPIResponse({ apiResponse, _isVertexAI, }) { + const operation = new ImportFileOperation(); + const op = apiResponse; + const response = importFileOperationFromMldev$1(op); + Object.assign(operation, response); + return operation; + } +} +/** Response for the list files method. */ +class ListFilesResponse { +} +/** Response for the create file method. */ +class CreateFileResponse { +} +/** Response for the delete file method. */ +class DeleteFileResponse { +} +/** Response for the _register file method. */ +class RegisterFilesResponse { +} +/** Config for `inlined_responses` parameter. */ +class InlinedResponse { +} +/** Config for `response` parameter. */ +class SingleEmbedContentResponse { +} +/** Config for `inlined_embedding_responses` parameter. */ +class InlinedEmbedContentResponse { +} +/** Config for batches.list return value. */ +class ListBatchJobsResponse { +} +/** Represents a single response in a replay. */ +class ReplayResponse { +} +/** A raw reference image. + +A raw reference image represents the base image to edit, provided by the user. +It can optionally be provided in addition to a mask reference image or +a style reference image. */ +class RawReferenceImage { + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI() { + const referenceImageAPI = { + referenceType: 'REFERENCE_TYPE_RAW', + referenceImage: this.referenceImage, + referenceId: this.referenceId, + }; + return referenceImageAPI; + } +} +/** A mask reference image. + +This encapsulates either a mask image provided by the user and configs for +the user provided mask, or only config parameters for the model to generate +a mask. + +A mask image is an image whose non-zero values indicate where to edit the base +image. If the user provides a mask image, the mask must be in the same +dimensions as the raw image. */ +class MaskReferenceImage { + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI() { + const referenceImageAPI = { + referenceType: 'REFERENCE_TYPE_MASK', + referenceImage: this.referenceImage, + referenceId: this.referenceId, + maskImageConfig: this.config, + }; + return referenceImageAPI; + } +} +/** A control reference image. + +The image of the control reference image is either a control image provided +by the user, or a regular image which the backend will use to generate a +control image of. In the case of the latter, the +enable_control_image_computation field in the config should be set to True. + +A control image is an image that represents a sketch image of areas for the +model to fill in based on the prompt. */ +class ControlReferenceImage { + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI() { + const referenceImageAPI = { + referenceType: 'REFERENCE_TYPE_CONTROL', + referenceImage: this.referenceImage, + referenceId: this.referenceId, + controlImageConfig: this.config, + }; + return referenceImageAPI; + } +} +/** A style reference image. + +This encapsulates a style reference image provided by the user, and +additionally optional config parameters for the style reference image. + +A raw reference image can also be provided as a destination for the style to +be applied to. */ +class StyleReferenceImage { + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI() { + const referenceImageAPI = { + referenceType: 'REFERENCE_TYPE_STYLE', + referenceImage: this.referenceImage, + referenceId: this.referenceId, + styleImageConfig: this.config, + }; + return referenceImageAPI; + } +} +/** A subject reference image. + +This encapsulates a subject reference image provided by the user, and +additionally optional config parameters for the subject reference image. + +A raw reference image can also be provided as a destination for the subject to +be applied to. */ +class SubjectReferenceImage { + /* Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI() { + const referenceImageAPI = { + referenceType: 'REFERENCE_TYPE_SUBJECT', + referenceImage: this.referenceImage, + referenceId: this.referenceId, + subjectImageConfig: this.config, + }; + return referenceImageAPI; + } +} +/** A content reference image. + +A content reference image represents a subject to reference (ex. person, +product, animal) provided by the user. It can optionally be provided in +addition to a style reference image (ex. background, style reference). */ +class ContentReferenceImage { + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI() { + const referenceImageAPI = { + referenceType: 'REFERENCE_TYPE_CONTENT', + referenceImage: this.referenceImage, + referenceId: this.referenceId, + }; + return referenceImageAPI; + } +} +/** Response message for API call. */ +class LiveServerMessage { + /** + * Returns the concatenation of all text parts from the server content if present. + * + * @remarks + * If there are non-text parts in the response, the concatenation of all text + * parts will be returned, and a warning will be logged. + */ + get text() { + var _a, _b, _c; + let text = ''; + let anyTextPartFound = false; + const nonTextParts = []; + for (const part of (_c = (_b = (_a = this.serverContent) === null || _a === void 0 ? void 0 : _a.modelTurn) === null || _b === void 0 ? void 0 : _b.parts) !== null && _c !== void 0 ? _c : []) { + for (const [fieldName, fieldValue] of Object.entries(part)) { + if (fieldName !== 'text' && + fieldName !== 'thought' && + fieldValue !== null) { + nonTextParts.push(fieldName); + } + } + if (typeof part.text === 'string') { + if (typeof part.thought === 'boolean' && part.thought) { + continue; + } + anyTextPartFound = true; + text += part.text; + } + } + if (nonTextParts.length > 0) { + console.warn(`there are non-text parts ${nonTextParts} in the response, returning concatenation of all text parts. Please refer to the non text parts for a full response from model.`); + } + // part.text === '' is different from part.text is null + return anyTextPartFound ? text : undefined; + } + /** + * Returns the concatenation of all inline data parts from the server content if present. + * + * @remarks + * If there are non-inline data parts in the + * response, the concatenation of all inline data parts will be returned, and + * a warning will be logged. + */ + get data() { + var _a, _b, _c; + let data = ''; + const nonDataParts = []; + for (const part of (_c = (_b = (_a = this.serverContent) === null || _a === void 0 ? void 0 : _a.modelTurn) === null || _b === void 0 ? void 0 : _b.parts) !== null && _c !== void 0 ? _c : []) { + for (const [fieldName, fieldValue] of Object.entries(part)) { + if (fieldName !== 'inlineData' && fieldValue !== null) { + nonDataParts.push(fieldName); + } + } + if (part.inlineData && typeof part.inlineData.data === 'string') { + data += atob(part.inlineData.data); + } + } + if (nonDataParts.length > 0) { + console.warn(`there are non-data parts ${nonDataParts} in the response, returning concatenation of all data parts. Please refer to the non data parts for a full response from model.`); + } + return data.length > 0 ? btoa(data) : undefined; + } +} +/** Client generated response to a `ToolCall` received from the server. + +Individual `FunctionResponse` objects are matched to the respective +`FunctionCall` objects by the `id` field. + +Note that in the unary and server-streaming GenerateContent APIs function +calling happens by exchanging the `Content` parts, while in the bidi +GenerateContent APIs function calling happens over this dedicated set of +messages. */ +class LiveClientToolResponse { +} +/** Parameters for sending tool responses to the live API. */ +class LiveSendToolResponseParameters { + constructor() { + /** Tool responses to send to the session. */ + this.functionResponses = []; + } +} +/** Response message for the LiveMusicClientMessage call. */ +class LiveMusicServerMessage { + /** + * Returns the first audio chunk from the server content, if present. + * + * @remarks + * If there are no audio chunks in the response, undefined will be returned. + */ + get audioChunk() { + if (this.serverContent && + this.serverContent.audioChunks && + this.serverContent.audioChunks.length > 0) { + return this.serverContent.audioChunks[0]; + } + return undefined; + } +} +/** The response when long-running operation for uploading a file to a FileSearchStore complete. */ +class UploadToFileSearchStoreResponse { +} +/** Long-running operation for uploading a file to a FileSearchStore. */ +class UploadToFileSearchStoreOperation { + /** + * Instantiates an Operation of the same type as the one being called with the fields set from the API response. + * @internal + */ + _fromAPIResponse({ apiResponse, _isVertexAI, }) { + const operation = new UploadToFileSearchStoreOperation(); + const op = apiResponse; + const response = uploadToFileSearchStoreOperationFromMldev(op); + Object.assign(operation, response); + return operation; + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function tModel(apiClient, model) { + if (!model || typeof model !== 'string') { + throw new Error('model is required and must be a string'); + } + if (model.includes('..') || model.includes('?') || model.includes('&')) { + throw new Error('invalid model parameter'); + } + if (apiClient.isVertexAI()) { + if (model.startsWith('publishers/') || + model.startsWith('projects/') || + model.startsWith('models/')) { + return model; + } + else if (model.indexOf('/') >= 0) { + const parts = model.split('/', 2); + return `publishers/${parts[0]}/models/${parts[1]}`; + } + else { + return `publishers/google/models/${model}`; + } + } + else { + if (model.startsWith('models/') || model.startsWith('tunedModels/')) { + return model; + } + else { + return `models/${model}`; + } + } +} +function tCachesModel(apiClient, model) { + const transformedModel = tModel(apiClient, model); + if (!transformedModel) { + return ''; + } + if (transformedModel.startsWith('publishers/') && apiClient.isVertexAI()) { + // vertex caches only support model name start with projects. + return `projects/${apiClient.getProject()}/locations/${apiClient.getLocation()}/${transformedModel}`; + } + else if (transformedModel.startsWith('models/') && apiClient.isVertexAI()) { + return `projects/${apiClient.getProject()}/locations/${apiClient.getLocation()}/publishers/google/${transformedModel}`; + } + else { + return transformedModel; + } +} +function tBlobs(blobs) { + if (Array.isArray(blobs)) { + return blobs.map((blob) => tBlob(blob)); + } + else { + return [tBlob(blobs)]; + } +} +function tBlob(blob) { + if (typeof blob === 'object' && blob !== null) { + return blob; + } + throw new Error(`Could not parse input as Blob. Unsupported blob type: ${typeof blob}`); +} +function tImageBlob(blob) { + const transformedBlob = tBlob(blob); + if (transformedBlob.mimeType && + transformedBlob.mimeType.startsWith('image/')) { + return transformedBlob; + } + throw new Error(`Unsupported mime type: ${transformedBlob.mimeType}`); +} +function tAudioBlob(blob) { + const transformedBlob = tBlob(blob); + if (transformedBlob.mimeType && + transformedBlob.mimeType.startsWith('audio/')) { + return transformedBlob; + } + throw new Error(`Unsupported mime type: ${transformedBlob.mimeType}`); +} +function tPart(origin) { + if (origin === null || origin === undefined) { + throw new Error('PartUnion is required'); + } + if (typeof origin === 'object') { + return origin; + } + if (typeof origin === 'string') { + return { text: origin }; + } + throw new Error(`Unsupported part type: ${typeof origin}`); +} +function tParts(origin) { + if (origin === null || + origin === undefined || + (Array.isArray(origin) && origin.length === 0)) { + throw new Error('PartListUnion is required'); + } + if (Array.isArray(origin)) { + return origin.map((item) => tPart(item)); + } + return [tPart(origin)]; +} +function _isContent(origin) { + return (origin !== null && + origin !== undefined && + typeof origin === 'object' && + 'parts' in origin && + Array.isArray(origin.parts)); +} +function _isFunctionCallPart(origin) { + return (origin !== null && + origin !== undefined && + typeof origin === 'object' && + 'functionCall' in origin); +} +function _isFunctionResponsePart(origin) { + return (origin !== null && + origin !== undefined && + typeof origin === 'object' && + 'functionResponse' in origin); +} +function tContent(origin) { + if (origin === null || origin === undefined) { + throw new Error('ContentUnion is required'); + } + if (_isContent(origin)) { + // _isContent is a utility function that checks if the + // origin is a Content. + return origin; + } + return { + role: 'user', + parts: tParts(origin), + }; +} +function tContentsForEmbed(apiClient, origin) { + if (!origin) { + return []; + } + if (apiClient.isVertexAI() && Array.isArray(origin)) { + return origin.flatMap((item) => { + const content = tContent(item); + if (content.parts && + content.parts.length > 0 && + content.parts[0].text !== undefined) { + return [content.parts[0].text]; + } + return []; + }); + } + else if (apiClient.isVertexAI()) { + const content = tContent(origin); + if (content.parts && + content.parts.length > 0 && + content.parts[0].text !== undefined) { + return [content.parts[0].text]; + } + return []; + } + if (Array.isArray(origin)) { + return origin.map((item) => tContent(item)); + } + return [tContent(origin)]; +} +function tContents(origin) { + if (origin === null || + origin === undefined || + (Array.isArray(origin) && origin.length === 0)) { + throw new Error('contents are required'); + } + if (!Array.isArray(origin)) { + // If it's not an array, it's a single content or a single PartUnion. + if (_isFunctionCallPart(origin) || _isFunctionResponsePart(origin)) { + throw new Error('To specify functionCall or functionResponse parts, please wrap them in a Content object, specifying the role for them'); + } + return [tContent(origin)]; + } + const result = []; + const accumulatedParts = []; + const isContentArray = _isContent(origin[0]); + for (const item of origin) { + const isContent = _isContent(item); + if (isContent != isContentArray) { + throw new Error('Mixing Content and Parts is not supported, please group the parts into a the appropriate Content objects and specify the roles for them'); + } + if (isContent) { + // `isContent` contains the result of _isContent, which is a utility + // function that checks if the item is a Content. + result.push(item); + } + else if (_isFunctionCallPart(item) || _isFunctionResponsePart(item)) { + throw new Error('To specify functionCall or functionResponse parts, please wrap them, and any other parts, in Content objects as appropriate, specifying the role for them'); + } + else { + accumulatedParts.push(item); + } + } + if (!isContentArray) { + result.push({ role: 'user', parts: tParts(accumulatedParts) }); + } + return result; +} +/* +Transform the type field from an array of types to an array of anyOf fields. +Example: + {type: ['STRING', 'NUMBER']} +will be transformed to + {anyOf: [{type: 'STRING'}, {type: 'NUMBER'}]} +*/ +function flattenTypeArrayToAnyOf(typeList, resultingSchema) { + if (typeList.includes('null')) { + resultingSchema['nullable'] = true; + } + const listWithoutNull = typeList.filter((type) => type !== 'null'); + if (listWithoutNull.length === 1) { + resultingSchema['type'] = Object.values(Type).includes(listWithoutNull[0].toUpperCase()) + ? listWithoutNull[0].toUpperCase() + : Type.TYPE_UNSPECIFIED; + } + else { + resultingSchema['anyOf'] = []; + for (const i of listWithoutNull) { + resultingSchema['anyOf'].push({ + 'type': Object.values(Type).includes(i.toUpperCase()) + ? i.toUpperCase() + : Type.TYPE_UNSPECIFIED, + }); + } + } +} +function processJsonSchema(_jsonSchema) { + const genAISchema = {}; + const schemaFieldNames = ['items']; + const listSchemaFieldNames = ['anyOf']; + const dictSchemaFieldNames = ['properties']; + if (_jsonSchema['type'] && _jsonSchema['anyOf']) { + throw new Error('type and anyOf cannot be both populated.'); + } + /* + This is to handle the nullable array or object. The _jsonSchema will + be in the format of {anyOf: [{type: 'null'}, {type: 'object'}]}. The + logic is to check if anyOf has 2 elements and one of the element is null, + if so, the anyOf field is unnecessary, so we need to get rid of the anyOf + field and make the schema nullable. Then use the other element as the new + _jsonSchema for processing. This is because the backend doesn't have a null + type. + This has to be checked before we process any other fields. + For example: + const objectNullable = z.object({ + nullableArray: z.array(z.string()).nullable(), + }); + Will have the raw _jsonSchema as: + { + type: 'OBJECT', + properties: { + nullableArray: { + anyOf: [ + {type: 'null'}, + { + type: 'array', + items: {type: 'string'}, + }, + ], + } + }, + required: [ 'nullableArray' ], + } + Will result in following schema compatible with Gemini API: + { + type: 'OBJECT', + properties: { + nullableArray: { + nullable: true, + type: 'ARRAY', + items: {type: 'string'}, + } + }, + required: [ 'nullableArray' ], + } + */ + const incomingAnyOf = _jsonSchema['anyOf']; + if (incomingAnyOf != null && incomingAnyOf.length == 2) { + if (incomingAnyOf[0]['type'] === 'null') { + genAISchema['nullable'] = true; + _jsonSchema = incomingAnyOf[1]; + } + else if (incomingAnyOf[1]['type'] === 'null') { + genAISchema['nullable'] = true; + _jsonSchema = incomingAnyOf[0]; + } + } + if (_jsonSchema['type'] instanceof Array) { + flattenTypeArrayToAnyOf(_jsonSchema['type'], genAISchema); + } + for (const [fieldName, fieldValue] of Object.entries(_jsonSchema)) { + // Skip if the fieldvalue is undefined or null. + if (fieldValue == null) { + continue; + } + if (fieldName == 'type') { + if (fieldValue === 'null') { + throw new Error('type: null can not be the only possible type for the field.'); + } + if (fieldValue instanceof Array) { + // we have already handled the type field with array of types in the + // beginning of this function. + continue; + } + genAISchema['type'] = Object.values(Type).includes(fieldValue.toUpperCase()) + ? fieldValue.toUpperCase() + : Type.TYPE_UNSPECIFIED; + } + else if (schemaFieldNames.includes(fieldName)) { + genAISchema[fieldName] = + processJsonSchema(fieldValue); + } + else if (listSchemaFieldNames.includes(fieldName)) { + const listSchemaFieldValue = []; + for (const item of fieldValue) { + if (item['type'] == 'null') { + genAISchema['nullable'] = true; + continue; + } + listSchemaFieldValue.push(processJsonSchema(item)); + } + genAISchema[fieldName] = + listSchemaFieldValue; + } + else if (dictSchemaFieldNames.includes(fieldName)) { + const dictSchemaFieldValue = {}; + for (const [key, value] of Object.entries(fieldValue)) { + dictSchemaFieldValue[key] = processJsonSchema(value); + } + genAISchema[fieldName] = + dictSchemaFieldValue; + } + else { + // additionalProperties is not included in JSONSchema, skipping it. + if (fieldName === 'additionalProperties') { + continue; + } + genAISchema[fieldName] = fieldValue; + } + } + return genAISchema; +} +// we take the unknown in the schema field because we want enable user to pass +// the output of major schema declaration tools without casting. Tools such as +// zodToJsonSchema, typebox, zodToJsonSchema function can return JsonSchema7Type +// or object, see details in +// https://github.com/StefanTerdell/zod-to-json-schema/blob/70525efe555cd226691e093d171370a3b10921d1/src/zodToJsonSchema.ts#L7 +// typebox can return unknown, see details in +// https://github.com/sinclairzx81/typebox/blob/5a5431439f7d5ca6b494d0d18fbfd7b1a356d67c/src/type/create/type.ts#L35 +// Note: proper json schemas with the $schema field set never arrive to this +// transformer. Schemas with $schema are routed to the equivalent API json +// schema field. +function tSchema(schema) { + return processJsonSchema(schema); +} +function tSpeechConfig(speechConfig) { + if (typeof speechConfig === 'object') { + return speechConfig; + } + else if (typeof speechConfig === 'string') { + return { + voiceConfig: { + prebuiltVoiceConfig: { + voiceName: speechConfig, + }, + }, + }; + } + else { + throw new Error(`Unsupported speechConfig type: ${typeof speechConfig}`); + } +} +function tLiveSpeechConfig(speechConfig) { + if ('multiSpeakerVoiceConfig' in speechConfig) { + throw new Error('multiSpeakerVoiceConfig is not supported in the live API.'); + } + return speechConfig; +} +function tTool(tool) { + if (tool.functionDeclarations) { + for (const functionDeclaration of tool.functionDeclarations) { + if (functionDeclaration.parameters) { + if (!Object.keys(functionDeclaration.parameters).includes('$schema')) { + functionDeclaration.parameters = processJsonSchema(functionDeclaration.parameters); + } + else { + if (!functionDeclaration.parametersJsonSchema) { + functionDeclaration.parametersJsonSchema = + functionDeclaration.parameters; + delete functionDeclaration.parameters; + } + } + } + if (functionDeclaration.response) { + if (!Object.keys(functionDeclaration.response).includes('$schema')) { + functionDeclaration.response = processJsonSchema(functionDeclaration.response); + } + else { + if (!functionDeclaration.responseJsonSchema) { + functionDeclaration.responseJsonSchema = + functionDeclaration.response; + delete functionDeclaration.response; + } + } + } + } + } + return tool; +} +function tTools(tools) { + // Check if the incoming type is defined. + if (tools === undefined || tools === null) { + throw new Error('tools is required'); + } + if (!Array.isArray(tools)) { + throw new Error('tools is required and must be an array of Tools'); + } + const result = []; + for (const tool of tools) { + result.push(tool); + } + return result; +} +/** + * Prepends resource name with project, location, resource_prefix if needed. + * + * @param client The API client. + * @param resourceName The resource name. + * @param resourcePrefix The resource prefix. + * @param splitsAfterPrefix The number of splits after the prefix. + * @returns The completed resource name. + * + * Examples: + * + * ``` + * resource_name = '123' + * resource_prefix = 'cachedContents' + * splits_after_prefix = 1 + * client.vertexai = True + * client.project = 'bar' + * client.location = 'us-west1' + * _resource_name(client, resource_name, resource_prefix, splits_after_prefix) + * returns: 'projects/bar/locations/us-west1/cachedContents/123' + * ``` + * + * ``` + * resource_name = 'projects/foo/locations/us-central1/cachedContents/123' + * resource_prefix = 'cachedContents' + * splits_after_prefix = 1 + * client.vertexai = True + * client.project = 'bar' + * client.location = 'us-west1' + * _resource_name(client, resource_name, resource_prefix, splits_after_prefix) + * returns: 'projects/foo/locations/us-central1/cachedContents/123' + * ``` + * + * ``` + * resource_name = '123' + * resource_prefix = 'cachedContents' + * splits_after_prefix = 1 + * client.vertexai = False + * _resource_name(client, resource_name, resource_prefix, splits_after_prefix) + * returns 'cachedContents/123' + * ``` + * + * ``` + * resource_name = 'some/wrong/cachedContents/resource/name/123' + * resource_prefix = 'cachedContents' + * splits_after_prefix = 1 + * client.vertexai = False + * # client.vertexai = True + * _resource_name(client, resource_name, resource_prefix, splits_after_prefix) + * -> 'some/wrong/resource/name/123' + * ``` + */ +function resourceName(client, resourceName, resourcePrefix, splitsAfterPrefix = 1) { + const shouldAppendPrefix = !resourceName.startsWith(`${resourcePrefix}/`) && + resourceName.split('/').length === splitsAfterPrefix; + if (client.isVertexAI()) { + if (resourceName.startsWith('projects/')) { + return resourceName; + } + else if (resourceName.startsWith('locations/')) { + return `projects/${client.getProject()}/${resourceName}`; + } + else if (resourceName.startsWith(`${resourcePrefix}/`)) { + return `projects/${client.getProject()}/locations/${client.getLocation()}/${resourceName}`; + } + else if (shouldAppendPrefix) { + return `projects/${client.getProject()}/locations/${client.getLocation()}/${resourcePrefix}/${resourceName}`; + } + else { + return resourceName; + } + } + if (shouldAppendPrefix) { + return `${resourcePrefix}/${resourceName}`; + } + return resourceName; +} +function tCachedContentName(apiClient, name) { + if (typeof name !== 'string') { + throw new Error('name must be a string'); + } + return resourceName(apiClient, name, 'cachedContents'); +} +function tTuningJobStatus(status) { + switch (status) { + case 'STATE_UNSPECIFIED': + return 'JOB_STATE_UNSPECIFIED'; + case 'CREATING': + return 'JOB_STATE_RUNNING'; + case 'ACTIVE': + return 'JOB_STATE_SUCCEEDED'; + case 'FAILED': + return 'JOB_STATE_FAILED'; + default: + return status; + } +} +function tBytes(fromImageBytes) { + return tBytes$1(fromImageBytes); +} +function _isFile(origin) { + return (origin !== null && + origin !== undefined && + typeof origin === 'object' && + 'name' in origin); +} +function isGeneratedVideo(origin) { + return (origin !== null && + origin !== undefined && + typeof origin === 'object' && + 'video' in origin); +} +function isVideo(origin) { + return (origin !== null && + origin !== undefined && + typeof origin === 'object' && + 'uri' in origin); +} +function tFileName(fromName) { + var _a; + let name; + if (_isFile(fromName)) { + name = fromName.name; + } + if (isVideo(fromName)) { + name = fromName.uri; + if (name === undefined) { + return undefined; + } + } + if (isGeneratedVideo(fromName)) { + name = (_a = fromName.video) === null || _a === void 0 ? void 0 : _a.uri; + if (name === undefined) { + return undefined; + } + } + if (typeof fromName === 'string') { + name = fromName; + } + if (name === undefined) { + throw new Error('Could not extract file name from the provided input.'); + } + if (name.startsWith('https://')) { + const suffix = name.split('files/')[1]; + const match = suffix.match(/[a-z0-9]+/); + if (match === null) { + throw new Error(`Could not extract file name from URI ${name}`); + } + name = match[0]; + } + else if (name.startsWith('files/')) { + name = name.split('files/')[1]; + } + return name; +} +function tModelsUrl(apiClient, baseModels) { + let res; + if (apiClient.isVertexAI()) { + res = baseModels ? 'publishers/google/models' : 'models'; + } + else { + res = baseModels ? 'models' : 'tunedModels'; + } + return res; +} +function tExtractModels(response) { + for (const key of ['models', 'tunedModels', 'publisherModels']) { + if (hasField(response, key)) { + return response[key]; + } + } + return []; +} +function hasField(data, fieldName) { + return data !== null && typeof data === 'object' && fieldName in data; +} +function mcpToGeminiTool(mcpTool, config = {}) { + const mcpToolSchema = mcpTool; + const functionDeclaration = { + name: mcpToolSchema['name'], + description: mcpToolSchema['description'], + parametersJsonSchema: mcpToolSchema['inputSchema'], + }; + if (mcpToolSchema['outputSchema']) { + functionDeclaration['responseJsonSchema'] = mcpToolSchema['outputSchema']; + } + if (config.behavior) { + functionDeclaration['behavior'] = config.behavior; + } + const geminiTool = { + functionDeclarations: [ + functionDeclaration, + ], + }; + return geminiTool; +} +/** + * Converts a list of MCP tools to a single Gemini tool with a list of function + * declarations. + */ +function mcpToolsToGeminiTool(mcpTools, config = {}) { + const functionDeclarations = []; + const toolNames = new Set(); + for (const mcpTool of mcpTools) { + const mcpToolName = mcpTool.name; + if (toolNames.has(mcpToolName)) { + throw new Error(`Duplicate function name ${mcpToolName} found in MCP tools. Please ensure function names are unique.`); + } + toolNames.add(mcpToolName); + const geminiTool = mcpToGeminiTool(mcpTool, config); + if (geminiTool.functionDeclarations) { + functionDeclarations.push(...geminiTool.functionDeclarations); + } + } + return { functionDeclarations: functionDeclarations }; +} +// Transforms a source input into a BatchJobSource object with validation. +function tBatchJobSource(client, src) { + let sourceObj; + if (typeof src === 'string') { + if (client.isVertexAI()) { + if (src.startsWith('gs://')) { + sourceObj = { format: 'jsonl', gcsUri: [src] }; + } + else if (src.startsWith('bq://')) { + sourceObj = { format: 'bigquery', bigqueryUri: src }; + } + else { + throw new Error(`Unsupported string source for Vertex AI: ${src}`); + } + } + else { + // MLDEV + if (src.startsWith('files/')) { + sourceObj = { fileName: src }; // Default to fileName for string input + } + else { + throw new Error(`Unsupported string source for Gemini API: ${src}`); + } + } + } + else if (Array.isArray(src)) { + if (client.isVertexAI()) { + throw new Error('InlinedRequest[] is not supported in Vertex AI.'); + } + sourceObj = { inlinedRequests: src }; + } + else { + // It's already a BatchJobSource object + sourceObj = src; + } + // Validation logic + const vertexSourcesCount = [sourceObj.gcsUri, sourceObj.bigqueryUri].filter(Boolean).length; + const mldevSourcesCount = [ + sourceObj.inlinedRequests, + sourceObj.fileName, + ].filter(Boolean).length; + if (client.isVertexAI()) { + if (mldevSourcesCount > 0 || vertexSourcesCount !== 1) { + throw new Error('Exactly one of `gcsUri` or `bigqueryUri` must be set for Vertex AI.'); + } + } + else { + // MLDEV + if (vertexSourcesCount > 0 || mldevSourcesCount !== 1) { + throw new Error('Exactly one of `inlinedRequests`, `fileName`, ' + + 'must be set for Gemini API.'); + } + } + return sourceObj; +} +function tBatchJobDestination(dest) { + if (typeof dest !== 'string') { + return dest; + } + const destString = dest; + if (destString.startsWith('gs://')) { + return { + format: 'jsonl', + gcsUri: destString, + }; + } + else if (destString.startsWith('bq://')) { + return { + format: 'bigquery', + bigqueryUri: destString, + }; + } + else { + throw new Error(`Unsupported destination: ${destString}`); + } +} +function tRecvBatchJobDestination(dest) { + // Ensure dest is a non-null object before proceeding. + if (typeof dest !== 'object' || dest === null) { + // If the input is not an object, it cannot be a valid BatchJobDestination + // based on the operations performed. Return it cast, or handle as an error. + // Casting an empty object might be a safe default. + return {}; + } + // Cast to Record<string, unknown> to allow string property access. + const obj = dest; + // Safely access nested properties. + const inlineResponsesVal = obj['inlinedResponses']; + if (typeof inlineResponsesVal !== 'object' || inlineResponsesVal === null) { + return dest; + } + const inlineResponsesObj = inlineResponsesVal; + const responsesArray = inlineResponsesObj['inlinedResponses']; + if (!Array.isArray(responsesArray) || responsesArray.length === 0) { + return dest; + } + // Check if any response has the 'embedding' property. + let hasEmbedding = false; + for (const responseItem of responsesArray) { + if (typeof responseItem !== 'object' || responseItem === null) { + continue; + } + const responseItemObj = responseItem; + const responseVal = responseItemObj['response']; + if (typeof responseVal !== 'object' || responseVal === null) { + continue; + } + const responseObj = responseVal; + // Check for the existence of the 'embedding' key. + if (responseObj['embedding'] !== undefined) { + hasEmbedding = true; + break; + } + } + // Perform the transformation if an embedding was found. + if (hasEmbedding) { + obj['inlinedEmbedContentResponses'] = obj['inlinedResponses']; + delete obj['inlinedResponses']; + } + // Cast the (potentially) modified object to the target type. + return dest; +} +function tBatchJobName(apiClient, name) { + const nameString = name; + if (!apiClient.isVertexAI()) { + const mldevPattern = /batches\/[^/]+$/; + if (mldevPattern.test(nameString)) { + return nameString.split('/').pop(); + } + else { + throw new Error(`Invalid batch job name: ${nameString}.`); + } + } + const vertexPattern = /^projects\/[^/]+\/locations\/[^/]+\/batchPredictionJobs\/[^/]+$/; + if (vertexPattern.test(nameString)) { + return nameString.split('/').pop(); + } + else if (/^\d+$/.test(nameString)) { + return nameString; + } + else { + throw new Error(`Invalid batch job name: ${nameString}.`); + } +} +function tJobState(state) { + const stateString = state; + if (stateString === 'BATCH_STATE_UNSPECIFIED') { + return 'JOB_STATE_UNSPECIFIED'; + } + else if (stateString === 'BATCH_STATE_PENDING') { + return 'JOB_STATE_PENDING'; + } + else if (stateString === 'BATCH_STATE_RUNNING') { + return 'JOB_STATE_RUNNING'; + } + else if (stateString === 'BATCH_STATE_SUCCEEDED') { + return 'JOB_STATE_SUCCEEDED'; + } + else if (stateString === 'BATCH_STATE_FAILED') { + return 'JOB_STATE_FAILED'; + } + else if (stateString === 'BATCH_STATE_CANCELLED') { + return 'JOB_STATE_CANCELLED'; + } + else if (stateString === 'BATCH_STATE_EXPIRED') { + return 'JOB_STATE_EXPIRED'; + } + else { + return stateString; + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function batchJobDestinationFromMldev(fromObject) { + const toObject = {}; + const fromFileName = getValueByPath(fromObject, ['responsesFile']); + if (fromFileName != null) { + setValueByPath(toObject, ['fileName'], fromFileName); + } + const fromInlinedResponses = getValueByPath(fromObject, [ + 'inlinedResponses', + 'inlinedResponses', + ]); + if (fromInlinedResponses != null) { + let transformedList = fromInlinedResponses; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return inlinedResponseFromMldev(item); + }); + } + setValueByPath(toObject, ['inlinedResponses'], transformedList); + } + const fromInlinedEmbedContentResponses = getValueByPath(fromObject, [ + 'inlinedEmbedContentResponses', + 'inlinedResponses', + ]); + if (fromInlinedEmbedContentResponses != null) { + let transformedList = fromInlinedEmbedContentResponses; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['inlinedEmbedContentResponses'], transformedList); + } + return toObject; +} +function batchJobDestinationFromVertex(fromObject) { + const toObject = {}; + const fromFormat = getValueByPath(fromObject, ['predictionsFormat']); + if (fromFormat != null) { + setValueByPath(toObject, ['format'], fromFormat); + } + const fromGcsUri = getValueByPath(fromObject, [ + 'gcsDestination', + 'outputUriPrefix', + ]); + if (fromGcsUri != null) { + setValueByPath(toObject, ['gcsUri'], fromGcsUri); + } + const fromBigqueryUri = getValueByPath(fromObject, [ + 'bigqueryDestination', + 'outputUri', + ]); + if (fromBigqueryUri != null) { + setValueByPath(toObject, ['bigqueryUri'], fromBigqueryUri); + } + return toObject; +} +function batchJobDestinationToVertex(fromObject) { + const toObject = {}; + const fromFormat = getValueByPath(fromObject, ['format']); + if (fromFormat != null) { + setValueByPath(toObject, ['predictionsFormat'], fromFormat); + } + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (fromGcsUri != null) { + setValueByPath(toObject, ['gcsDestination', 'outputUriPrefix'], fromGcsUri); + } + const fromBigqueryUri = getValueByPath(fromObject, ['bigqueryUri']); + if (fromBigqueryUri != null) { + setValueByPath(toObject, ['bigqueryDestination', 'outputUri'], fromBigqueryUri); + } + if (getValueByPath(fromObject, ['fileName']) !== undefined) { + throw new Error('fileName parameter is not supported in Vertex AI.'); + } + if (getValueByPath(fromObject, ['inlinedResponses']) !== undefined) { + throw new Error('inlinedResponses parameter is not supported in Vertex AI.'); + } + if (getValueByPath(fromObject, ['inlinedEmbedContentResponses']) !== + undefined) { + throw new Error('inlinedEmbedContentResponses parameter is not supported in Vertex AI.'); + } + return toObject; +} +function batchJobFromMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromDisplayName = getValueByPath(fromObject, [ + 'metadata', + 'displayName', + ]); + if (fromDisplayName != null) { + setValueByPath(toObject, ['displayName'], fromDisplayName); + } + const fromState = getValueByPath(fromObject, ['metadata', 'state']); + if (fromState != null) { + setValueByPath(toObject, ['state'], tJobState(fromState)); + } + const fromCreateTime = getValueByPath(fromObject, [ + 'metadata', + 'createTime', + ]); + if (fromCreateTime != null) { + setValueByPath(toObject, ['createTime'], fromCreateTime); + } + const fromEndTime = getValueByPath(fromObject, [ + 'metadata', + 'endTime', + ]); + if (fromEndTime != null) { + setValueByPath(toObject, ['endTime'], fromEndTime); + } + const fromUpdateTime = getValueByPath(fromObject, [ + 'metadata', + 'updateTime', + ]); + if (fromUpdateTime != null) { + setValueByPath(toObject, ['updateTime'], fromUpdateTime); + } + const fromModel = getValueByPath(fromObject, ['metadata', 'model']); + if (fromModel != null) { + setValueByPath(toObject, ['model'], fromModel); + } + const fromDest = getValueByPath(fromObject, ['metadata', 'output']); + if (fromDest != null) { + setValueByPath(toObject, ['dest'], batchJobDestinationFromMldev(tRecvBatchJobDestination(fromDest))); + } + return toObject; +} +function batchJobFromVertex(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (fromDisplayName != null) { + setValueByPath(toObject, ['displayName'], fromDisplayName); + } + const fromState = getValueByPath(fromObject, ['state']); + if (fromState != null) { + setValueByPath(toObject, ['state'], tJobState(fromState)); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromCreateTime = getValueByPath(fromObject, ['createTime']); + if (fromCreateTime != null) { + setValueByPath(toObject, ['createTime'], fromCreateTime); + } + const fromStartTime = getValueByPath(fromObject, ['startTime']); + if (fromStartTime != null) { + setValueByPath(toObject, ['startTime'], fromStartTime); + } + const fromEndTime = getValueByPath(fromObject, ['endTime']); + if (fromEndTime != null) { + setValueByPath(toObject, ['endTime'], fromEndTime); + } + const fromUpdateTime = getValueByPath(fromObject, ['updateTime']); + if (fromUpdateTime != null) { + setValueByPath(toObject, ['updateTime'], fromUpdateTime); + } + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['model'], fromModel); + } + const fromSrc = getValueByPath(fromObject, ['inputConfig']); + if (fromSrc != null) { + setValueByPath(toObject, ['src'], batchJobSourceFromVertex(fromSrc)); + } + const fromDest = getValueByPath(fromObject, ['outputConfig']); + if (fromDest != null) { + setValueByPath(toObject, ['dest'], batchJobDestinationFromVertex(tRecvBatchJobDestination(fromDest))); + } + const fromCompletionStats = getValueByPath(fromObject, [ + 'completionStats', + ]); + if (fromCompletionStats != null) { + setValueByPath(toObject, ['completionStats'], fromCompletionStats); + } + return toObject; +} +function batchJobSourceFromVertex(fromObject) { + const toObject = {}; + const fromFormat = getValueByPath(fromObject, ['instancesFormat']); + if (fromFormat != null) { + setValueByPath(toObject, ['format'], fromFormat); + } + const fromGcsUri = getValueByPath(fromObject, ['gcsSource', 'uris']); + if (fromGcsUri != null) { + setValueByPath(toObject, ['gcsUri'], fromGcsUri); + } + const fromBigqueryUri = getValueByPath(fromObject, [ + 'bigquerySource', + 'inputUri', + ]); + if (fromBigqueryUri != null) { + setValueByPath(toObject, ['bigqueryUri'], fromBigqueryUri); + } + return toObject; +} +function batchJobSourceToMldev(apiClient, fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['format']) !== undefined) { + throw new Error('format parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['gcsUri']) !== undefined) { + throw new Error('gcsUri parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['bigqueryUri']) !== undefined) { + throw new Error('bigqueryUri parameter is not supported in Gemini API.'); + } + const fromFileName = getValueByPath(fromObject, ['fileName']); + if (fromFileName != null) { + setValueByPath(toObject, ['fileName'], fromFileName); + } + const fromInlinedRequests = getValueByPath(fromObject, [ + 'inlinedRequests', + ]); + if (fromInlinedRequests != null) { + let transformedList = fromInlinedRequests; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return inlinedRequestToMldev(apiClient, item); + }); + } + setValueByPath(toObject, ['requests', 'requests'], transformedList); + } + return toObject; +} +function batchJobSourceToVertex(fromObject) { + const toObject = {}; + const fromFormat = getValueByPath(fromObject, ['format']); + if (fromFormat != null) { + setValueByPath(toObject, ['instancesFormat'], fromFormat); + } + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (fromGcsUri != null) { + setValueByPath(toObject, ['gcsSource', 'uris'], fromGcsUri); + } + const fromBigqueryUri = getValueByPath(fromObject, ['bigqueryUri']); + if (fromBigqueryUri != null) { + setValueByPath(toObject, ['bigquerySource', 'inputUri'], fromBigqueryUri); + } + if (getValueByPath(fromObject, ['fileName']) !== undefined) { + throw new Error('fileName parameter is not supported in Vertex AI.'); + } + if (getValueByPath(fromObject, ['inlinedRequests']) !== undefined) { + throw new Error('inlinedRequests parameter is not supported in Vertex AI.'); + } + return toObject; +} +function blobToMldev$4(fromObject) { + const toObject = {}; + const fromData = getValueByPath(fromObject, ['data']); + if (fromData != null) { + setValueByPath(toObject, ['data'], fromData); + } + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function cancelBatchJobParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tBatchJobName(apiClient, fromName)); + } + return toObject; +} +function cancelBatchJobParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tBatchJobName(apiClient, fromName)); + } + return toObject; +} +function candidateFromMldev$1(fromObject) { + const toObject = {}; + const fromContent = getValueByPath(fromObject, ['content']); + if (fromContent != null) { + setValueByPath(toObject, ['content'], fromContent); + } + const fromCitationMetadata = getValueByPath(fromObject, [ + 'citationMetadata', + ]); + if (fromCitationMetadata != null) { + setValueByPath(toObject, ['citationMetadata'], citationMetadataFromMldev$1(fromCitationMetadata)); + } + const fromTokenCount = getValueByPath(fromObject, ['tokenCount']); + if (fromTokenCount != null) { + setValueByPath(toObject, ['tokenCount'], fromTokenCount); + } + const fromFinishReason = getValueByPath(fromObject, ['finishReason']); + if (fromFinishReason != null) { + setValueByPath(toObject, ['finishReason'], fromFinishReason); + } + const fromAvgLogprobs = getValueByPath(fromObject, ['avgLogprobs']); + if (fromAvgLogprobs != null) { + setValueByPath(toObject, ['avgLogprobs'], fromAvgLogprobs); + } + const fromGroundingMetadata = getValueByPath(fromObject, [ + 'groundingMetadata', + ]); + if (fromGroundingMetadata != null) { + setValueByPath(toObject, ['groundingMetadata'], fromGroundingMetadata); + } + const fromIndex = getValueByPath(fromObject, ['index']); + if (fromIndex != null) { + setValueByPath(toObject, ['index'], fromIndex); + } + const fromLogprobsResult = getValueByPath(fromObject, [ + 'logprobsResult', + ]); + if (fromLogprobsResult != null) { + setValueByPath(toObject, ['logprobsResult'], fromLogprobsResult); + } + const fromSafetyRatings = getValueByPath(fromObject, [ + 'safetyRatings', + ]); + if (fromSafetyRatings != null) { + let transformedList = fromSafetyRatings; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['safetyRatings'], transformedList); + } + const fromUrlContextMetadata = getValueByPath(fromObject, [ + 'urlContextMetadata', + ]); + if (fromUrlContextMetadata != null) { + setValueByPath(toObject, ['urlContextMetadata'], fromUrlContextMetadata); + } + return toObject; +} +function citationMetadataFromMldev$1(fromObject) { + const toObject = {}; + const fromCitations = getValueByPath(fromObject, ['citationSources']); + if (fromCitations != null) { + let transformedList = fromCitations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['citations'], transformedList); + } + return toObject; +} +function contentToMldev$4(fromObject) { + const toObject = {}; + const fromParts = getValueByPath(fromObject, ['parts']); + if (fromParts != null) { + let transformedList = fromParts; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return partToMldev$4(item); + }); + } + setValueByPath(toObject, ['parts'], transformedList); + } + const fromRole = getValueByPath(fromObject, ['role']); + if (fromRole != null) { + setValueByPath(toObject, ['role'], fromRole); + } + return toObject; +} +function createBatchJobConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['batch', 'displayName'], fromDisplayName); + } + if (getValueByPath(fromObject, ['dest']) !== undefined) { + throw new Error('dest parameter is not supported in Gemini API.'); + } + return toObject; +} +function createBatchJobConfigToVertex(fromObject, parentObject) { + const toObject = {}; + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromDisplayName); + } + const fromDest = getValueByPath(fromObject, ['dest']); + if (parentObject !== undefined && fromDest != null) { + setValueByPath(parentObject, ['outputConfig'], batchJobDestinationToVertex(tBatchJobDestination(fromDest))); + } + return toObject; +} +function createBatchJobParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromSrc = getValueByPath(fromObject, ['src']); + if (fromSrc != null) { + setValueByPath(toObject, ['batch', 'inputConfig'], batchJobSourceToMldev(apiClient, tBatchJobSource(apiClient, fromSrc))); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createBatchJobConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function createBatchJobParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['model'], tModel(apiClient, fromModel)); + } + const fromSrc = getValueByPath(fromObject, ['src']); + if (fromSrc != null) { + setValueByPath(toObject, ['inputConfig'], batchJobSourceToVertex(tBatchJobSource(apiClient, fromSrc))); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createBatchJobConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function createEmbeddingsBatchJobConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['batch', 'displayName'], fromDisplayName); + } + return toObject; +} +function createEmbeddingsBatchJobParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromSrc = getValueByPath(fromObject, ['src']); + if (fromSrc != null) { + setValueByPath(toObject, ['batch', 'inputConfig'], embeddingsBatchJobSourceToMldev(apiClient, fromSrc)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createEmbeddingsBatchJobConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function deleteBatchJobParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tBatchJobName(apiClient, fromName)); + } + return toObject; +} +function deleteBatchJobParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tBatchJobName(apiClient, fromName)); + } + return toObject; +} +function deleteResourceJobFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + return toObject; +} +function deleteResourceJobFromVertex(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + return toObject; +} +function embedContentBatchToMldev(apiClient, fromObject) { + const toObject = {}; + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContentsForEmbed(apiClient, fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['requests[]', 'request', 'content'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['_self'], embedContentConfigToMldev$1(fromConfig, toObject)); + moveValueByPath(toObject, { 'requests[].*': 'requests[].request.*' }); + } + return toObject; +} +function embedContentConfigToMldev$1(fromObject, parentObject) { + const toObject = {}; + const fromTaskType = getValueByPath(fromObject, ['taskType']); + if (parentObject !== undefined && fromTaskType != null) { + setValueByPath(parentObject, ['requests[]', 'taskType'], fromTaskType); + } + const fromTitle = getValueByPath(fromObject, ['title']); + if (parentObject !== undefined && fromTitle != null) { + setValueByPath(parentObject, ['requests[]', 'title'], fromTitle); + } + const fromOutputDimensionality = getValueByPath(fromObject, [ + 'outputDimensionality', + ]); + if (parentObject !== undefined && fromOutputDimensionality != null) { + setValueByPath(parentObject, ['requests[]', 'outputDimensionality'], fromOutputDimensionality); + } + if (getValueByPath(fromObject, ['mimeType']) !== undefined) { + throw new Error('mimeType parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['autoTruncate']) !== undefined) { + throw new Error('autoTruncate parameter is not supported in Gemini API.'); + } + return toObject; +} +function embeddingsBatchJobSourceToMldev(apiClient, fromObject) { + const toObject = {}; + const fromFileName = getValueByPath(fromObject, ['fileName']); + if (fromFileName != null) { + setValueByPath(toObject, ['file_name'], fromFileName); + } + const fromInlinedRequests = getValueByPath(fromObject, [ + 'inlinedRequests', + ]); + if (fromInlinedRequests != null) { + setValueByPath(toObject, ['requests'], embedContentBatchToMldev(apiClient, fromInlinedRequests)); + } + return toObject; +} +function fileDataToMldev$4(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromFileUri = getValueByPath(fromObject, ['fileUri']); + if (fromFileUri != null) { + setValueByPath(toObject, ['fileUri'], fromFileUri); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function functionCallToMldev$4(fromObject) { + const toObject = {}; + const fromId = getValueByPath(fromObject, ['id']); + if (fromId != null) { + setValueByPath(toObject, ['id'], fromId); + } + const fromArgs = getValueByPath(fromObject, ['args']); + if (fromArgs != null) { + setValueByPath(toObject, ['args'], fromArgs); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + if (getValueByPath(fromObject, ['partialArgs']) !== undefined) { + throw new Error('partialArgs parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['willContinue']) !== undefined) { + throw new Error('willContinue parameter is not supported in Gemini API.'); + } + return toObject; +} +function functionCallingConfigToMldev$2(fromObject) { + const toObject = {}; + const fromAllowedFunctionNames = getValueByPath(fromObject, [ + 'allowedFunctionNames', + ]); + if (fromAllowedFunctionNames != null) { + setValueByPath(toObject, ['allowedFunctionNames'], fromAllowedFunctionNames); + } + const fromMode = getValueByPath(fromObject, ['mode']); + if (fromMode != null) { + setValueByPath(toObject, ['mode'], fromMode); + } + if (getValueByPath(fromObject, ['streamFunctionCallArguments']) !== + undefined) { + throw new Error('streamFunctionCallArguments parameter is not supported in Gemini API.'); + } + return toObject; +} +function generateContentConfigToMldev$1(apiClient, fromObject, parentObject) { + const toObject = {}; + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['systemInstruction'], contentToMldev$4(tContent(fromSystemInstruction))); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (fromTemperature != null) { + setValueByPath(toObject, ['temperature'], fromTemperature); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (fromTopP != null) { + setValueByPath(toObject, ['topP'], fromTopP); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (fromTopK != null) { + setValueByPath(toObject, ['topK'], fromTopK); + } + const fromCandidateCount = getValueByPath(fromObject, [ + 'candidateCount', + ]); + if (fromCandidateCount != null) { + setValueByPath(toObject, ['candidateCount'], fromCandidateCount); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (fromMaxOutputTokens != null) { + setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens); + } + const fromStopSequences = getValueByPath(fromObject, [ + 'stopSequences', + ]); + if (fromStopSequences != null) { + setValueByPath(toObject, ['stopSequences'], fromStopSequences); + } + const fromResponseLogprobs = getValueByPath(fromObject, [ + 'responseLogprobs', + ]); + if (fromResponseLogprobs != null) { + setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs); + } + const fromLogprobs = getValueByPath(fromObject, ['logprobs']); + if (fromLogprobs != null) { + setValueByPath(toObject, ['logprobs'], fromLogprobs); + } + const fromPresencePenalty = getValueByPath(fromObject, [ + 'presencePenalty', + ]); + if (fromPresencePenalty != null) { + setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty); + } + const fromFrequencyPenalty = getValueByPath(fromObject, [ + 'frequencyPenalty', + ]); + if (fromFrequencyPenalty != null) { + setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (fromSeed != null) { + setValueByPath(toObject, ['seed'], fromSeed); + } + const fromResponseMimeType = getValueByPath(fromObject, [ + 'responseMimeType', + ]); + if (fromResponseMimeType != null) { + setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType); + } + const fromResponseSchema = getValueByPath(fromObject, [ + 'responseSchema', + ]); + if (fromResponseSchema != null) { + setValueByPath(toObject, ['responseSchema'], tSchema(fromResponseSchema)); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + if (getValueByPath(fromObject, ['routingConfig']) !== undefined) { + throw new Error('routingConfig parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['modelSelectionConfig']) !== undefined) { + throw new Error('modelSelectionConfig parameter is not supported in Gemini API.'); + } + const fromSafetySettings = getValueByPath(fromObject, [ + 'safetySettings', + ]); + if (parentObject !== undefined && fromSafetySettings != null) { + let transformedList = fromSafetySettings; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return safetySettingToMldev$1(item); + }); + } + setValueByPath(parentObject, ['safetySettings'], transformedList); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = tTools(fromTools); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToMldev$4(tTool(item)); + }); + } + setValueByPath(parentObject, ['tools'], transformedList); + } + const fromToolConfig = getValueByPath(fromObject, ['toolConfig']); + if (parentObject !== undefined && fromToolConfig != null) { + setValueByPath(parentObject, ['toolConfig'], toolConfigToMldev$2(fromToolConfig)); + } + if (getValueByPath(fromObject, ['labels']) !== undefined) { + throw new Error('labels parameter is not supported in Gemini API.'); + } + const fromCachedContent = getValueByPath(fromObject, [ + 'cachedContent', + ]); + if (parentObject !== undefined && fromCachedContent != null) { + setValueByPath(parentObject, ['cachedContent'], tCachedContentName(apiClient, fromCachedContent)); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (fromResponseModalities != null) { + setValueByPath(toObject, ['responseModalities'], fromResponseModalities); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (fromSpeechConfig != null) { + setValueByPath(toObject, ['speechConfig'], tSpeechConfig(fromSpeechConfig)); + } + if (getValueByPath(fromObject, ['audioTimestamp']) !== undefined) { + throw new Error('audioTimestamp parameter is not supported in Gemini API.'); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (fromThinkingConfig != null) { + setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig); + } + const fromImageConfig = getValueByPath(fromObject, ['imageConfig']); + if (fromImageConfig != null) { + setValueByPath(toObject, ['imageConfig'], imageConfigToMldev$1(fromImageConfig)); + } + const fromEnableEnhancedCivicAnswers = getValueByPath(fromObject, [ + 'enableEnhancedCivicAnswers', + ]); + if (fromEnableEnhancedCivicAnswers != null) { + setValueByPath(toObject, ['enableEnhancedCivicAnswers'], fromEnableEnhancedCivicAnswers); + } + if (getValueByPath(fromObject, ['modelArmorConfig']) !== undefined) { + throw new Error('modelArmorConfig parameter is not supported in Gemini API.'); + } + return toObject; +} +function generateContentResponseFromMldev$1(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromCandidates = getValueByPath(fromObject, ['candidates']); + if (fromCandidates != null) { + let transformedList = fromCandidates; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return candidateFromMldev$1(item); + }); + } + setValueByPath(toObject, ['candidates'], transformedList); + } + const fromModelVersion = getValueByPath(fromObject, ['modelVersion']); + if (fromModelVersion != null) { + setValueByPath(toObject, ['modelVersion'], fromModelVersion); + } + const fromPromptFeedback = getValueByPath(fromObject, [ + 'promptFeedback', + ]); + if (fromPromptFeedback != null) { + setValueByPath(toObject, ['promptFeedback'], fromPromptFeedback); + } + const fromResponseId = getValueByPath(fromObject, ['responseId']); + if (fromResponseId != null) { + setValueByPath(toObject, ['responseId'], fromResponseId); + } + const fromUsageMetadata = getValueByPath(fromObject, [ + 'usageMetadata', + ]); + if (fromUsageMetadata != null) { + setValueByPath(toObject, ['usageMetadata'], fromUsageMetadata); + } + return toObject; +} +function getBatchJobParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tBatchJobName(apiClient, fromName)); + } + return toObject; +} +function getBatchJobParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tBatchJobName(apiClient, fromName)); + } + return toObject; +} +function googleMapsToMldev$4(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['authConfig']) !== undefined) { + throw new Error('authConfig parameter is not supported in Gemini API.'); + } + const fromEnableWidget = getValueByPath(fromObject, ['enableWidget']); + if (fromEnableWidget != null) { + setValueByPath(toObject, ['enableWidget'], fromEnableWidget); + } + return toObject; +} +function googleSearchToMldev$4(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['excludeDomains']) !== undefined) { + throw new Error('excludeDomains parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['blockingConfidence']) !== undefined) { + throw new Error('blockingConfidence parameter is not supported in Gemini API.'); + } + const fromTimeRangeFilter = getValueByPath(fromObject, [ + 'timeRangeFilter', + ]); + if (fromTimeRangeFilter != null) { + setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter); + } + return toObject; +} +function imageConfigToMldev$1(fromObject) { + const toObject = {}; + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (fromAspectRatio != null) { + setValueByPath(toObject, ['aspectRatio'], fromAspectRatio); + } + const fromImageSize = getValueByPath(fromObject, ['imageSize']); + if (fromImageSize != null) { + setValueByPath(toObject, ['imageSize'], fromImageSize); + } + if (getValueByPath(fromObject, ['personGeneration']) !== undefined) { + throw new Error('personGeneration parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['outputMimeType']) !== undefined) { + throw new Error('outputMimeType parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['outputCompressionQuality']) !== + undefined) { + throw new Error('outputCompressionQuality parameter is not supported in Gemini API.'); + } + return toObject; +} +function inlinedRequestToMldev(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['request', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return contentToMldev$4(item); + }); + } + setValueByPath(toObject, ['request', 'contents'], transformedList); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['request', 'generationConfig'], generateContentConfigToMldev$1(apiClient, fromConfig, getValueByPath(toObject, ['request'], {}))); + } + return toObject; +} +function inlinedResponseFromMldev(fromObject) { + const toObject = {}; + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], generateContentResponseFromMldev$1(fromResponse)); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + return toObject; +} +function listBatchJobsConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + if (getValueByPath(fromObject, ['filter']) !== undefined) { + throw new Error('filter parameter is not supported in Gemini API.'); + } + return toObject; +} +function listBatchJobsConfigToVertex(fromObject, parentObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + const fromFilter = getValueByPath(fromObject, ['filter']); + if (parentObject !== undefined && fromFilter != null) { + setValueByPath(parentObject, ['_query', 'filter'], fromFilter); + } + return toObject; +} +function listBatchJobsParametersToMldev(fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listBatchJobsConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function listBatchJobsParametersToVertex(fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listBatchJobsConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function listBatchJobsResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromBatchJobs = getValueByPath(fromObject, ['operations']); + if (fromBatchJobs != null) { + let transformedList = fromBatchJobs; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return batchJobFromMldev(item); + }); + } + setValueByPath(toObject, ['batchJobs'], transformedList); + } + return toObject; +} +function listBatchJobsResponseFromVertex(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromBatchJobs = getValueByPath(fromObject, [ + 'batchPredictionJobs', + ]); + if (fromBatchJobs != null) { + let transformedList = fromBatchJobs; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return batchJobFromVertex(item); + }); + } + setValueByPath(toObject, ['batchJobs'], transformedList); + } + return toObject; +} +function partToMldev$4(fromObject) { + const toObject = {}; + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromCodeExecutionResult = getValueByPath(fromObject, [ + 'codeExecutionResult', + ]); + if (fromCodeExecutionResult != null) { + setValueByPath(toObject, ['codeExecutionResult'], fromCodeExecutionResult); + } + const fromExecutableCode = getValueByPath(fromObject, [ + 'executableCode', + ]); + if (fromExecutableCode != null) { + setValueByPath(toObject, ['executableCode'], fromExecutableCode); + } + const fromFileData = getValueByPath(fromObject, ['fileData']); + if (fromFileData != null) { + setValueByPath(toObject, ['fileData'], fileDataToMldev$4(fromFileData)); + } + const fromFunctionCall = getValueByPath(fromObject, ['functionCall']); + if (fromFunctionCall != null) { + setValueByPath(toObject, ['functionCall'], functionCallToMldev$4(fromFunctionCall)); + } + const fromFunctionResponse = getValueByPath(fromObject, [ + 'functionResponse', + ]); + if (fromFunctionResponse != null) { + setValueByPath(toObject, ['functionResponse'], fromFunctionResponse); + } + const fromInlineData = getValueByPath(fromObject, ['inlineData']); + if (fromInlineData != null) { + setValueByPath(toObject, ['inlineData'], blobToMldev$4(fromInlineData)); + } + const fromText = getValueByPath(fromObject, ['text']); + if (fromText != null) { + setValueByPath(toObject, ['text'], fromText); + } + const fromThought = getValueByPath(fromObject, ['thought']); + if (fromThought != null) { + setValueByPath(toObject, ['thought'], fromThought); + } + const fromThoughtSignature = getValueByPath(fromObject, [ + 'thoughtSignature', + ]); + if (fromThoughtSignature != null) { + setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature); + } + const fromVideoMetadata = getValueByPath(fromObject, [ + 'videoMetadata', + ]); + if (fromVideoMetadata != null) { + setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata); + } + return toObject; +} +function safetySettingToMldev$1(fromObject) { + const toObject = {}; + const fromCategory = getValueByPath(fromObject, ['category']); + if (fromCategory != null) { + setValueByPath(toObject, ['category'], fromCategory); + } + if (getValueByPath(fromObject, ['method']) !== undefined) { + throw new Error('method parameter is not supported in Gemini API.'); + } + const fromThreshold = getValueByPath(fromObject, ['threshold']); + if (fromThreshold != null) { + setValueByPath(toObject, ['threshold'], fromThreshold); + } + return toObject; +} +function toolConfigToMldev$2(fromObject) { + const toObject = {}; + const fromRetrievalConfig = getValueByPath(fromObject, [ + 'retrievalConfig', + ]); + if (fromRetrievalConfig != null) { + setValueByPath(toObject, ['retrievalConfig'], fromRetrievalConfig); + } + const fromFunctionCallingConfig = getValueByPath(fromObject, [ + 'functionCallingConfig', + ]); + if (fromFunctionCallingConfig != null) { + setValueByPath(toObject, ['functionCallingConfig'], functionCallingConfigToMldev$2(fromFunctionCallingConfig)); + } + return toObject; +} +function toolToMldev$4(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['retrieval']) !== undefined) { + throw new Error('retrieval parameter is not supported in Gemini API.'); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + const fromFileSearch = getValueByPath(fromObject, ['fileSearch']); + if (fromFileSearch != null) { + setValueByPath(toObject, ['fileSearch'], fromFileSearch); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + if (getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined) { + throw new Error('enterpriseWebSearch parameter is not supported in Gemini API.'); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], googleMapsToMldev$4(fromGoogleMaps)); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], googleSearchToMldev$4(fromGoogleSearch)); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +var PagedItem; +(function (PagedItem) { + PagedItem["PAGED_ITEM_BATCH_JOBS"] = "batchJobs"; + PagedItem["PAGED_ITEM_MODELS"] = "models"; + PagedItem["PAGED_ITEM_TUNING_JOBS"] = "tuningJobs"; + PagedItem["PAGED_ITEM_FILES"] = "files"; + PagedItem["PAGED_ITEM_CACHED_CONTENTS"] = "cachedContents"; + PagedItem["PAGED_ITEM_FILE_SEARCH_STORES"] = "fileSearchStores"; + PagedItem["PAGED_ITEM_DOCUMENTS"] = "documents"; +})(PagedItem || (PagedItem = {})); +/** + * Pager class for iterating through paginated results. + */ +class Pager { + constructor(name, request, response, params) { + this.pageInternal = []; + this.paramsInternal = {}; + this.requestInternal = request; + this.init(name, response, params); + } + init(name, response, params) { + var _a, _b; + this.nameInternal = name; + this.pageInternal = response[this.nameInternal] || []; + this.sdkHttpResponseInternal = response === null || response === void 0 ? void 0 : response.sdkHttpResponse; + this.idxInternal = 0; + let requestParams = { config: {} }; + if (!params || Object.keys(params).length === 0) { + requestParams = { config: {} }; + } + else if (typeof params === 'object') { + requestParams = Object.assign({}, params); + } + else { + requestParams = params; + } + if (requestParams['config']) { + requestParams['config']['pageToken'] = response['nextPageToken']; + } + this.paramsInternal = requestParams; + this.pageInternalSize = + (_b = (_a = requestParams['config']) === null || _a === void 0 ? void 0 : _a['pageSize']) !== null && _b !== void 0 ? _b : this.pageInternal.length; + } + initNextPage(response) { + this.init(this.nameInternal, response, this.paramsInternal); + } + /** + * Returns the current page, which is a list of items. + * + * @remarks + * The first page is retrieved when the pager is created. The returned list of + * items could be a subset of the entire list. + */ + get page() { + return this.pageInternal; + } + /** + * Returns the type of paged item (for example, ``batch_jobs``). + */ + get name() { + return this.nameInternal; + } + /** + * Returns the length of the page fetched each time by this pager. + * + * @remarks + * The number of items in the page is less than or equal to the page length. + */ + get pageSize() { + return this.pageInternalSize; + } + /** + * Returns the headers of the API response. + */ + get sdkHttpResponse() { + return this.sdkHttpResponseInternal; + } + /** + * Returns the parameters when making the API request for the next page. + * + * @remarks + * Parameters contain a set of optional configs that can be + * used to customize the API request. For example, the `pageToken` parameter + * contains the token to request the next page. + */ + get params() { + return this.paramsInternal; + } + /** + * Returns the total number of items in the current page. + */ + get pageLength() { + return this.pageInternal.length; + } + /** + * Returns the item at the given index. + */ + getItem(index) { + return this.pageInternal[index]; + } + /** + * Returns an async iterator that support iterating through all items + * retrieved from the API. + * + * @remarks + * The iterator will automatically fetch the next page if there are more items + * to fetch from the API. + * + * @example + * + * ```ts + * const pager = await ai.files.list({config: {pageSize: 10}}); + * for await (const file of pager) { + * console.log(file.name); + * } + * ``` + */ + [Symbol.asyncIterator]() { + return { + next: async () => { + if (this.idxInternal >= this.pageLength) { + if (this.hasNextPage()) { + await this.nextPage(); + } + else { + return { value: undefined, done: true }; + } + } + const item = this.getItem(this.idxInternal); + this.idxInternal += 1; + return { value: item, done: false }; + }, + return: async () => { + return { value: undefined, done: true }; + }, + }; + } + /** + * Fetches the next page of items. This makes a new API request. + * + * @throws {Error} If there are no more pages to fetch. + * + * @example + * + * ```ts + * const pager = await ai.files.list({config: {pageSize: 10}}); + * let page = pager.page; + * while (true) { + * for (const file of page) { + * console.log(file.name); + * } + * if (!pager.hasNextPage()) { + * break; + * } + * page = await pager.nextPage(); + * } + * ``` + */ + async nextPage() { + if (!this.hasNextPage()) { + throw new Error('No more pages to fetch.'); + } + const response = await this.requestInternal(this.params); + this.initNextPage(response); + return this.page; + } + /** + * Returns true if there are more pages to fetch from the API. + */ + hasNextPage() { + var _a; + if (((_a = this.params['config']) === null || _a === void 0 ? void 0 : _a['pageToken']) !== undefined) { + return true; + } + return false; + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Batches extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + /** + * Lists batch jobs. + * + * @param params - The parameters for the list request. + * @return - A pager of batch jobs. + * + * @example + * ```ts + * const batchJobs = await ai.batches.list({config: {'pageSize': 2}}); + * for await (const batchJob of batchJobs) { + * console.log(batchJob); + * } + * ``` + */ + this.list = async (params = {}) => { + return new Pager(PagedItem.PAGED_ITEM_BATCH_JOBS, (x) => this.listInternal(x), await this.listInternal(params), params); + }; + /** + * Create batch job. + * + * @param params - The parameters for create batch job request. + * @return The created batch job. + * + * @example + * ```ts + * const response = await ai.batches.create({ + * model: 'gemini-2.0-flash', + * src: {gcsUri: 'gs://bucket/path/to/file.jsonl', format: 'jsonl'}, + * config: { + * dest: {gcsUri: 'gs://bucket/path/output/directory', format: 'jsonl'}, + * } + * }); + * console.log(response); + * ``` + */ + this.create = async (params) => { + if (this.apiClient.isVertexAI()) { + // Format destination if not provided + // Cast params.src as Vertex AI path does not handle InlinedRequest[] + params.config = this.formatDestination(params.src, params.config); + } + return this.createInternal(params); + }; + /** + * **Experimental** Creates an embedding batch job. + * + * @param params - The parameters for create embedding batch job request. + * @return The created batch job. + * + * @example + * ```ts + * const response = await ai.batches.createEmbeddings({ + * model: 'text-embedding-004', + * src: {fileName: 'files/my_embedding_input'}, + * }); + * console.log(response); + * ``` + */ + this.createEmbeddings = async (params) => { + console.warn('batches.createEmbeddings() is experimental and may change without notice.'); + if (this.apiClient.isVertexAI()) { + throw new Error('Vertex AI does not support batches.createEmbeddings.'); + } + return this.createEmbeddingsInternal(params); + }; + } + // Helper function to handle inlined generate content requests + createInlinedGenerateContentRequest(params) { + const body = createBatchJobParametersToMldev(this.apiClient, // Use instance apiClient + params); + const urlParams = body['_url']; + const path = formatMap('{model}:batchGenerateContent', urlParams); + const batch = body['batch']; + const inputConfig = batch['inputConfig']; + const requestsWrapper = inputConfig['requests']; + const requests = requestsWrapper['requests']; + const newRequests = []; + for (const request of requests) { + const requestDict = Object.assign({}, request); // Clone + if (requestDict['systemInstruction']) { + const systemInstructionValue = requestDict['systemInstruction']; + delete requestDict['systemInstruction']; + const requestContent = requestDict['request']; + requestContent['systemInstruction'] = systemInstructionValue; + requestDict['request'] = requestContent; + } + newRequests.push(requestDict); + } + requestsWrapper['requests'] = newRequests; + delete body['config']; + delete body['_url']; + delete body['_query']; + return { path, body }; + } + // Helper function to get the first GCS URI + getGcsUri(src) { + if (typeof src === 'string') { + return src.startsWith('gs://') ? src : undefined; + } + if (!Array.isArray(src) && src.gcsUri && src.gcsUri.length > 0) { + return src.gcsUri[0]; + } + return undefined; + } + // Helper function to get the BigQuery URI + getBigqueryUri(src) { + if (typeof src === 'string') { + return src.startsWith('bq://') ? src : undefined; + } + if (!Array.isArray(src)) { + return src.bigqueryUri; + } + return undefined; + } + // Function to format the destination configuration for Vertex AI + formatDestination(src, config) { + const newConfig = config ? Object.assign({}, config) : {}; + const timestampStr = Date.now().toString(); + if (!newConfig.displayName) { + newConfig.displayName = `genaiBatchJob_${timestampStr}`; + } + if (newConfig.dest === undefined) { + const gcsUri = this.getGcsUri(src); + const bigqueryUri = this.getBigqueryUri(src); + if (gcsUri) { + if (gcsUri.endsWith('.jsonl')) { + // For .jsonl files, remove suffix and add /dest + newConfig.dest = `${gcsUri.slice(0, -6)}/dest`; + } + else { + // Fallback for other GCS URIs + newConfig.dest = `${gcsUri}_dest_${timestampStr}`; + } + } + else if (bigqueryUri) { + newConfig.dest = `${bigqueryUri}_dest_${timestampStr}`; + } + else { + throw new Error('Unsupported source for Vertex AI: No GCS or BigQuery URI found.'); + } + } + return newConfig; + } + /** + * Internal method to create batch job. + * + * @param params - The parameters for create batch job request. + * @return The created batch job. + * + */ + async createInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = createBatchJobParametersToVertex(this.apiClient, params); + path = formatMap('batchPredictionJobs', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = batchJobFromVertex(apiResponse); + return resp; + }); + } + else { + const body = createBatchJobParametersToMldev(this.apiClient, params); + path = formatMap('{model}:batchGenerateContent', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = batchJobFromMldev(apiResponse); + return resp; + }); + } + } + /** + * Internal method to create batch job. + * + * @param params - The parameters for create batch job request. + * @return The created batch job. + * + */ + async createEmbeddingsInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = createEmbeddingsBatchJobParametersToMldev(this.apiClient, params); + path = formatMap('{model}:asyncBatchEmbedContent', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = batchJobFromMldev(apiResponse); + return resp; + }); + } + } + /** + * Gets batch job configurations. + * + * @param params - The parameters for the get request. + * @return The batch job. + * + * @example + * ```ts + * await ai.batches.get({name: '...'}); // The server-generated resource name. + * ``` + */ + async get(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = getBatchJobParametersToVertex(this.apiClient, params); + path = formatMap('batchPredictionJobs/{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = batchJobFromVertex(apiResponse); + return resp; + }); + } + else { + const body = getBatchJobParametersToMldev(this.apiClient, params); + path = formatMap('batches/{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = batchJobFromMldev(apiResponse); + return resp; + }); + } + } + /** + * Cancels a batch job. + * + * @param params - The parameters for the cancel request. + * @return The empty response returned by the API. + * + * @example + * ```ts + * await ai.batches.cancel({name: '...'}); // The server-generated resource name. + * ``` + */ + async cancel(params) { + var _a, _b, _c, _d; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = cancelBatchJobParametersToVertex(this.apiClient, params); + path = formatMap('batchPredictionJobs/{name}:cancel', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + await this.apiClient.request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }); + } + else { + const body = cancelBatchJobParametersToMldev(this.apiClient, params); + path = formatMap('batches/{name}:cancel', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + await this.apiClient.request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }); + } + } + async listInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = listBatchJobsParametersToVertex(params); + path = formatMap('batchPredictionJobs', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listBatchJobsResponseFromVertex(apiResponse); + const typedResp = new ListBatchJobsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = listBatchJobsParametersToMldev(params); + path = formatMap('batches', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listBatchJobsResponseFromMldev(apiResponse); + const typedResp = new ListBatchJobsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Deletes a batch job. + * + * @param params - The parameters for the delete request. + * @return The empty response returned by the API. + * + * @example + * ```ts + * await ai.batches.delete({name: '...'}); // The server-generated resource name. + * ``` + */ + async delete(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = deleteBatchJobParametersToVertex(this.apiClient, params); + path = formatMap('batchPredictionJobs/{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = deleteResourceJobFromVertex(apiResponse); + return resp; + }); + } + else { + const body = deleteBatchJobParametersToMldev(this.apiClient, params); + path = formatMap('batches/{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = deleteResourceJobFromMldev(apiResponse); + return resp; + }); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function blobToMldev$3(fromObject) { + const toObject = {}; + const fromData = getValueByPath(fromObject, ['data']); + if (fromData != null) { + setValueByPath(toObject, ['data'], fromData); + } + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function contentToMldev$3(fromObject) { + const toObject = {}; + const fromParts = getValueByPath(fromObject, ['parts']); + if (fromParts != null) { + let transformedList = fromParts; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return partToMldev$3(item); + }); + } + setValueByPath(toObject, ['parts'], transformedList); + } + const fromRole = getValueByPath(fromObject, ['role']); + if (fromRole != null) { + setValueByPath(toObject, ['role'], fromRole); + } + return toObject; +} +function createCachedContentConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromTtl = getValueByPath(fromObject, ['ttl']); + if (parentObject !== undefined && fromTtl != null) { + setValueByPath(parentObject, ['ttl'], fromTtl); + } + const fromExpireTime = getValueByPath(fromObject, ['expireTime']); + if (parentObject !== undefined && fromExpireTime != null) { + setValueByPath(parentObject, ['expireTime'], fromExpireTime); + } + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromDisplayName); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (parentObject !== undefined && fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return contentToMldev$3(item); + }); + } + setValueByPath(parentObject, ['contents'], transformedList); + } + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['systemInstruction'], contentToMldev$3(tContent(fromSystemInstruction))); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = fromTools; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToMldev$3(item); + }); + } + setValueByPath(parentObject, ['tools'], transformedList); + } + const fromToolConfig = getValueByPath(fromObject, ['toolConfig']); + if (parentObject !== undefined && fromToolConfig != null) { + setValueByPath(parentObject, ['toolConfig'], toolConfigToMldev$1(fromToolConfig)); + } + if (getValueByPath(fromObject, ['kmsKeyName']) !== undefined) { + throw new Error('kmsKeyName parameter is not supported in Gemini API.'); + } + return toObject; +} +function createCachedContentConfigToVertex(fromObject, parentObject) { + const toObject = {}; + const fromTtl = getValueByPath(fromObject, ['ttl']); + if (parentObject !== undefined && fromTtl != null) { + setValueByPath(parentObject, ['ttl'], fromTtl); + } + const fromExpireTime = getValueByPath(fromObject, ['expireTime']); + if (parentObject !== undefined && fromExpireTime != null) { + setValueByPath(parentObject, ['expireTime'], fromExpireTime); + } + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromDisplayName); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (parentObject !== undefined && fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(parentObject, ['contents'], transformedList); + } + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['systemInstruction'], tContent(fromSystemInstruction)); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = fromTools; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToVertex$2(item); + }); + } + setValueByPath(parentObject, ['tools'], transformedList); + } + const fromToolConfig = getValueByPath(fromObject, ['toolConfig']); + if (parentObject !== undefined && fromToolConfig != null) { + setValueByPath(parentObject, ['toolConfig'], fromToolConfig); + } + const fromKmsKeyName = getValueByPath(fromObject, ['kmsKeyName']); + if (parentObject !== undefined && fromKmsKeyName != null) { + setValueByPath(parentObject, ['encryption_spec', 'kmsKeyName'], fromKmsKeyName); + } + return toObject; +} +function createCachedContentParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['model'], tCachesModel(apiClient, fromModel)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createCachedContentConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function createCachedContentParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['model'], tCachesModel(apiClient, fromModel)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createCachedContentConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function deleteCachedContentParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tCachedContentName(apiClient, fromName)); + } + return toObject; +} +function deleteCachedContentParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tCachedContentName(apiClient, fromName)); + } + return toObject; +} +function deleteCachedContentResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function deleteCachedContentResponseFromVertex(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function fileDataToMldev$3(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromFileUri = getValueByPath(fromObject, ['fileUri']); + if (fromFileUri != null) { + setValueByPath(toObject, ['fileUri'], fromFileUri); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function functionCallToMldev$3(fromObject) { + const toObject = {}; + const fromId = getValueByPath(fromObject, ['id']); + if (fromId != null) { + setValueByPath(toObject, ['id'], fromId); + } + const fromArgs = getValueByPath(fromObject, ['args']); + if (fromArgs != null) { + setValueByPath(toObject, ['args'], fromArgs); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + if (getValueByPath(fromObject, ['partialArgs']) !== undefined) { + throw new Error('partialArgs parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['willContinue']) !== undefined) { + throw new Error('willContinue parameter is not supported in Gemini API.'); + } + return toObject; +} +function functionCallingConfigToMldev$1(fromObject) { + const toObject = {}; + const fromAllowedFunctionNames = getValueByPath(fromObject, [ + 'allowedFunctionNames', + ]); + if (fromAllowedFunctionNames != null) { + setValueByPath(toObject, ['allowedFunctionNames'], fromAllowedFunctionNames); + } + const fromMode = getValueByPath(fromObject, ['mode']); + if (fromMode != null) { + setValueByPath(toObject, ['mode'], fromMode); + } + if (getValueByPath(fromObject, ['streamFunctionCallArguments']) !== + undefined) { + throw new Error('streamFunctionCallArguments parameter is not supported in Gemini API.'); + } + return toObject; +} +function functionDeclarationToVertex$2(fromObject) { + const toObject = {}; + const fromDescription = getValueByPath(fromObject, ['description']); + if (fromDescription != null) { + setValueByPath(toObject, ['description'], fromDescription); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromParameters = getValueByPath(fromObject, ['parameters']); + if (fromParameters != null) { + setValueByPath(toObject, ['parameters'], fromParameters); + } + const fromParametersJsonSchema = getValueByPath(fromObject, [ + 'parametersJsonSchema', + ]); + if (fromParametersJsonSchema != null) { + setValueByPath(toObject, ['parametersJsonSchema'], fromParametersJsonSchema); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], fromResponse); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + if (getValueByPath(fromObject, ['behavior']) !== undefined) { + throw new Error('behavior parameter is not supported in Vertex AI.'); + } + return toObject; +} +function getCachedContentParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tCachedContentName(apiClient, fromName)); + } + return toObject; +} +function getCachedContentParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tCachedContentName(apiClient, fromName)); + } + return toObject; +} +function googleMapsToMldev$3(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['authConfig']) !== undefined) { + throw new Error('authConfig parameter is not supported in Gemini API.'); + } + const fromEnableWidget = getValueByPath(fromObject, ['enableWidget']); + if (fromEnableWidget != null) { + setValueByPath(toObject, ['enableWidget'], fromEnableWidget); + } + return toObject; +} +function googleSearchToMldev$3(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['excludeDomains']) !== undefined) { + throw new Error('excludeDomains parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['blockingConfidence']) !== undefined) { + throw new Error('blockingConfidence parameter is not supported in Gemini API.'); + } + const fromTimeRangeFilter = getValueByPath(fromObject, [ + 'timeRangeFilter', + ]); + if (fromTimeRangeFilter != null) { + setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter); + } + return toObject; +} +function listCachedContentsConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + return toObject; +} +function listCachedContentsConfigToVertex(fromObject, parentObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + return toObject; +} +function listCachedContentsParametersToMldev(fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listCachedContentsConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function listCachedContentsParametersToVertex(fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listCachedContentsConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function listCachedContentsResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromCachedContents = getValueByPath(fromObject, [ + 'cachedContents', + ]); + if (fromCachedContents != null) { + let transformedList = fromCachedContents; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['cachedContents'], transformedList); + } + return toObject; +} +function listCachedContentsResponseFromVertex(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromCachedContents = getValueByPath(fromObject, [ + 'cachedContents', + ]); + if (fromCachedContents != null) { + let transformedList = fromCachedContents; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['cachedContents'], transformedList); + } + return toObject; +} +function partToMldev$3(fromObject) { + const toObject = {}; + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromCodeExecutionResult = getValueByPath(fromObject, [ + 'codeExecutionResult', + ]); + if (fromCodeExecutionResult != null) { + setValueByPath(toObject, ['codeExecutionResult'], fromCodeExecutionResult); + } + const fromExecutableCode = getValueByPath(fromObject, [ + 'executableCode', + ]); + if (fromExecutableCode != null) { + setValueByPath(toObject, ['executableCode'], fromExecutableCode); + } + const fromFileData = getValueByPath(fromObject, ['fileData']); + if (fromFileData != null) { + setValueByPath(toObject, ['fileData'], fileDataToMldev$3(fromFileData)); + } + const fromFunctionCall = getValueByPath(fromObject, ['functionCall']); + if (fromFunctionCall != null) { + setValueByPath(toObject, ['functionCall'], functionCallToMldev$3(fromFunctionCall)); + } + const fromFunctionResponse = getValueByPath(fromObject, [ + 'functionResponse', + ]); + if (fromFunctionResponse != null) { + setValueByPath(toObject, ['functionResponse'], fromFunctionResponse); + } + const fromInlineData = getValueByPath(fromObject, ['inlineData']); + if (fromInlineData != null) { + setValueByPath(toObject, ['inlineData'], blobToMldev$3(fromInlineData)); + } + const fromText = getValueByPath(fromObject, ['text']); + if (fromText != null) { + setValueByPath(toObject, ['text'], fromText); + } + const fromThought = getValueByPath(fromObject, ['thought']); + if (fromThought != null) { + setValueByPath(toObject, ['thought'], fromThought); + } + const fromThoughtSignature = getValueByPath(fromObject, [ + 'thoughtSignature', + ]); + if (fromThoughtSignature != null) { + setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature); + } + const fromVideoMetadata = getValueByPath(fromObject, [ + 'videoMetadata', + ]); + if (fromVideoMetadata != null) { + setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata); + } + return toObject; +} +function toolConfigToMldev$1(fromObject) { + const toObject = {}; + const fromRetrievalConfig = getValueByPath(fromObject, [ + 'retrievalConfig', + ]); + if (fromRetrievalConfig != null) { + setValueByPath(toObject, ['retrievalConfig'], fromRetrievalConfig); + } + const fromFunctionCallingConfig = getValueByPath(fromObject, [ + 'functionCallingConfig', + ]); + if (fromFunctionCallingConfig != null) { + setValueByPath(toObject, ['functionCallingConfig'], functionCallingConfigToMldev$1(fromFunctionCallingConfig)); + } + return toObject; +} +function toolToMldev$3(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['retrieval']) !== undefined) { + throw new Error('retrieval parameter is not supported in Gemini API.'); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + const fromFileSearch = getValueByPath(fromObject, ['fileSearch']); + if (fromFileSearch != null) { + setValueByPath(toObject, ['fileSearch'], fromFileSearch); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + if (getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined) { + throw new Error('enterpriseWebSearch parameter is not supported in Gemini API.'); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], googleMapsToMldev$3(fromGoogleMaps)); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], googleSearchToMldev$3(fromGoogleSearch)); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} +function toolToVertex$2(fromObject) { + const toObject = {}; + const fromRetrieval = getValueByPath(fromObject, ['retrieval']); + if (fromRetrieval != null) { + setValueByPath(toObject, ['retrieval'], fromRetrieval); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + if (getValueByPath(fromObject, ['fileSearch']) !== undefined) { + throw new Error('fileSearch parameter is not supported in Vertex AI.'); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + const fromEnterpriseWebSearch = getValueByPath(fromObject, [ + 'enterpriseWebSearch', + ]); + if (fromEnterpriseWebSearch != null) { + setValueByPath(toObject, ['enterpriseWebSearch'], fromEnterpriseWebSearch); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return functionDeclarationToVertex$2(item); + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], fromGoogleMaps); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], fromGoogleSearch); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} +function updateCachedContentConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromTtl = getValueByPath(fromObject, ['ttl']); + if (parentObject !== undefined && fromTtl != null) { + setValueByPath(parentObject, ['ttl'], fromTtl); + } + const fromExpireTime = getValueByPath(fromObject, ['expireTime']); + if (parentObject !== undefined && fromExpireTime != null) { + setValueByPath(parentObject, ['expireTime'], fromExpireTime); + } + return toObject; +} +function updateCachedContentConfigToVertex(fromObject, parentObject) { + const toObject = {}; + const fromTtl = getValueByPath(fromObject, ['ttl']); + if (parentObject !== undefined && fromTtl != null) { + setValueByPath(parentObject, ['ttl'], fromTtl); + } + const fromExpireTime = getValueByPath(fromObject, ['expireTime']); + if (parentObject !== undefined && fromExpireTime != null) { + setValueByPath(parentObject, ['expireTime'], fromExpireTime); + } + return toObject; +} +function updateCachedContentParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tCachedContentName(apiClient, fromName)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + updateCachedContentConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function updateCachedContentParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tCachedContentName(apiClient, fromName)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + updateCachedContentConfigToVertex(fromConfig, toObject); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Caches extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + /** + * Lists cached contents. + * + * @param params - The parameters for the list request. + * @return - A pager of cached contents. + * + * @example + * ```ts + * const cachedContents = await ai.caches.list({config: {'pageSize': 2}}); + * for await (const cachedContent of cachedContents) { + * console.log(cachedContent); + * } + * ``` + */ + this.list = async (params = {}) => { + return new Pager(PagedItem.PAGED_ITEM_CACHED_CONTENTS, (x) => this.listInternal(x), await this.listInternal(params), params); + }; + } + /** + * Creates a cached contents resource. + * + * @remarks + * Context caching is only supported for specific models. See [Gemini + * Developer API reference](https://ai.google.dev/gemini-api/docs/caching?lang=node/context-cac) + * and [Vertex AI reference](https://cloud.google.com/vertex-ai/generative-ai/docs/context-cache/context-cache-overview#supported_models) + * for more information. + * + * @param params - The parameters for the create request. + * @return The created cached content. + * + * @example + * ```ts + * const contents = ...; // Initialize the content to cache. + * const response = await ai.caches.create({ + * model: 'gemini-2.0-flash-001', + * config: { + * 'contents': contents, + * 'displayName': 'test cache', + * 'systemInstruction': 'What is the sum of the two pdfs?', + * 'ttl': '86400s', + * } + * }); + * ``` + */ + async create(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = createCachedContentParametersToVertex(this.apiClient, params); + path = formatMap('cachedContents', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + else { + const body = createCachedContentParametersToMldev(this.apiClient, params); + path = formatMap('cachedContents', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } + /** + * Gets cached content configurations. + * + * @param params - The parameters for the get request. + * @return The cached content. + * + * @example + * ```ts + * await ai.caches.get({name: '...'}); // The server-generated resource name. + * ``` + */ + async get(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = getCachedContentParametersToVertex(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + else { + const body = getCachedContentParametersToMldev(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } + /** + * Deletes cached content. + * + * @param params - The parameters for the delete request. + * @return The empty response returned by the API. + * + * @example + * ```ts + * await ai.caches.delete({name: '...'}); // The server-generated resource name. + * ``` + */ + async delete(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = deleteCachedContentParametersToVertex(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = deleteCachedContentResponseFromVertex(apiResponse); + const typedResp = new DeleteCachedContentResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = deleteCachedContentParametersToMldev(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = deleteCachedContentResponseFromMldev(apiResponse); + const typedResp = new DeleteCachedContentResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Updates cached content configurations. + * + * @param params - The parameters for the update request. + * @return The updated cached content. + * + * @example + * ```ts + * const response = await ai.caches.update({ + * name: '...', // The server-generated resource name. + * config: {'ttl': '7600s'} + * }); + * ``` + */ + async update(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = updateCachedContentParametersToVertex(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'PATCH', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + else { + const body = updateCachedContentParametersToMldev(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'PATCH', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } + async listInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = listCachedContentsParametersToVertex(params); + path = formatMap('cachedContents', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listCachedContentsResponseFromVertex(apiResponse); + const typedResp = new ListCachedContentsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = listCachedContentsParametersToMldev(params); + path = formatMap('cachedContents', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listCachedContentsResponseFromMldev(apiResponse); + const typedResp = new ListCachedContentsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } +} + +/****************************************************************************** +Copyright (c) Microsoft Corporation. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +***************************************************************************** */ +/* global Reflect, Promise, SuppressedError, Symbol, Iterator */ + + +function __rest(s, e) { + var t = {}; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) + t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === "function") + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { + if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) + t[p[i]] = s[p[i]]; + } + return t; +} + +function __values(o) { + var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; + if (m) return m.call(o); + if (o && typeof o.length === "number") return { + next: function () { + if (o && i >= o.length) o = void 0; + return { value: o && o[i++], done: !o }; + } + }; + throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); +} + +function __await(v) { + return this instanceof __await ? (this.v = v, this) : new __await(v); +} + +function __asyncGenerator(thisArg, _arguments, generator) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var g = generator.apply(thisArg, _arguments || []), i, q = []; + return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i; + function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; } + function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } } + function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function fulfill(value) { resume("next", value); } + function reject(value) { resume("throw", value); } + function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } +} + +function __asyncValues(o) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var m = o[Symbol.asyncIterator], i; + return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); + function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } + function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } +} + +typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { + var e = new Error(message); + return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Returns true if the response is valid, false otherwise. + */ +function isValidResponse(response) { + var _a; + if (response.candidates == undefined || response.candidates.length === 0) { + return false; + } + const content = (_a = response.candidates[0]) === null || _a === void 0 ? void 0 : _a.content; + if (content === undefined) { + return false; + } + return isValidContent(content); +} +function isValidContent(content) { + if (content.parts === undefined || content.parts.length === 0) { + return false; + } + for (const part of content.parts) { + if (part === undefined || Object.keys(part).length === 0) { + return false; + } + } + return true; +} +/** + * Validates the history contains the correct roles. + * + * @throws Error if the history does not start with a user turn. + * @throws Error if the history contains an invalid role. + */ +function validateHistory(history) { + // Empty history is valid. + if (history.length === 0) { + return; + } + for (const content of history) { + if (content.role !== 'user' && content.role !== 'model') { + throw new Error(`Role must be user or model, but got ${content.role}.`); + } + } +} +/** + * Extracts the curated (valid) history from a comprehensive history. + * + * @remarks + * The model may sometimes generate invalid or empty contents(e.g., due to safty + * filters or recitation). Extracting valid turns from the history + * ensures that subsequent requests could be accpeted by the model. + */ +function extractCuratedHistory(comprehensiveHistory) { + if (comprehensiveHistory === undefined || comprehensiveHistory.length === 0) { + return []; + } + const curatedHistory = []; + const length = comprehensiveHistory.length; + let i = 0; + while (i < length) { + if (comprehensiveHistory[i].role === 'user') { + curatedHistory.push(comprehensiveHistory[i]); + i++; + } + else { + const modelOutput = []; + let isValid = true; + while (i < length && comprehensiveHistory[i].role === 'model') { + modelOutput.push(comprehensiveHistory[i]); + if (isValid && !isValidContent(comprehensiveHistory[i])) { + isValid = false; + } + i++; + } + if (isValid) { + curatedHistory.push(...modelOutput); + } + else { + // Remove the last user input when model content is invalid. + curatedHistory.pop(); + } + } + } + return curatedHistory; +} +/** + * A utility class to create a chat session. + */ +class Chats { + constructor(modelsModule, apiClient) { + this.modelsModule = modelsModule; + this.apiClient = apiClient; + } + /** + * Creates a new chat session. + * + * @remarks + * The config in the params will be used for all requests within the chat + * session unless overridden by a per-request `config` in + * @see {@link types.SendMessageParameters#config}. + * + * @param params - Parameters for creating a chat session. + * @returns A new chat session. + * + * @example + * ```ts + * const chat = ai.chats.create({ + * model: 'gemini-2.0-flash' + * config: { + * temperature: 0.5, + * maxOutputTokens: 1024, + * } + * }); + * ``` + */ + create(params) { + return new Chat(this.apiClient, this.modelsModule, params.model, params.config, + // Deep copy the history to avoid mutating the history outside of the + // chat session. + structuredClone(params.history)); + } +} +/** + * Chat session that enables sending messages to the model with previous + * conversation context. + * + * @remarks + * The session maintains all the turns between user and model. + */ +class Chat { + constructor(apiClient, modelsModule, model, config = {}, history = []) { + this.apiClient = apiClient; + this.modelsModule = modelsModule; + this.model = model; + this.config = config; + this.history = history; + // A promise to represent the current state of the message being sent to the + // model. + this.sendPromise = Promise.resolve(); + validateHistory(history); + } + /** + * Sends a message to the model and returns the response. + * + * @remarks + * This method will wait for the previous message to be processed before + * sending the next message. + * + * @see {@link Chat#sendMessageStream} for streaming method. + * @param params - parameters for sending messages within a chat session. + * @returns The model's response. + * + * @example + * ```ts + * const chat = ai.chats.create({model: 'gemini-2.0-flash'}); + * const response = await chat.sendMessage({ + * message: 'Why is the sky blue?' + * }); + * console.log(response.text); + * ``` + */ + async sendMessage(params) { + var _a; + await this.sendPromise; + const inputContent = tContent(params.message); + const responsePromise = this.modelsModule.generateContent({ + model: this.model, + contents: this.getHistory(true).concat(inputContent), + config: (_a = params.config) !== null && _a !== void 0 ? _a : this.config, + }); + this.sendPromise = (async () => { + var _a, _b, _c; + const response = await responsePromise; + const outputContent = (_b = (_a = response.candidates) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.content; + // Because the AFC input contains the entire curated chat history in + // addition to the new user input, we need to truncate the AFC history + // to deduplicate the existing chat history. + const fullAutomaticFunctionCallingHistory = response.automaticFunctionCallingHistory; + const index = this.getHistory(true).length; + let automaticFunctionCallingHistory = []; + if (fullAutomaticFunctionCallingHistory != null) { + automaticFunctionCallingHistory = + (_c = fullAutomaticFunctionCallingHistory.slice(index)) !== null && _c !== void 0 ? _c : []; + } + const modelOutput = outputContent ? [outputContent] : []; + this.recordHistory(inputContent, modelOutput, automaticFunctionCallingHistory); + return; + })(); + await this.sendPromise.catch(() => { + // Resets sendPromise to avoid subsequent calls failing + this.sendPromise = Promise.resolve(); + }); + return responsePromise; + } + /** + * Sends a message to the model and returns the response in chunks. + * + * @remarks + * This method will wait for the previous message to be processed before + * sending the next message. + * + * @see {@link Chat#sendMessage} for non-streaming method. + * @param params - parameters for sending the message. + * @return The model's response. + * + * @example + * ```ts + * const chat = ai.chats.create({model: 'gemini-2.0-flash'}); + * const response = await chat.sendMessageStream({ + * message: 'Why is the sky blue?' + * }); + * for await (const chunk of response) { + * console.log(chunk.text); + * } + * ``` + */ + async sendMessageStream(params) { + var _a; + await this.sendPromise; + const inputContent = tContent(params.message); + const streamResponse = this.modelsModule.generateContentStream({ + model: this.model, + contents: this.getHistory(true).concat(inputContent), + config: (_a = params.config) !== null && _a !== void 0 ? _a : this.config, + }); + // Resolve the internal tracking of send completion promise - `sendPromise` + // for both success and failure response. The actual failure is still + // propagated by the `await streamResponse`. + this.sendPromise = streamResponse + .then(() => undefined) + .catch(() => undefined); + const response = await streamResponse; + const result = this.processStreamResponse(response, inputContent); + return result; + } + /** + * Returns the chat history. + * + * @remarks + * The history is a list of contents alternating between user and model. + * + * There are two types of history: + * - The `curated history` contains only the valid turns between user and + * model, which will be included in the subsequent requests sent to the model. + * - The `comprehensive history` contains all turns, including invalid or + * empty model outputs, providing a complete record of the history. + * + * The history is updated after receiving the response from the model, + * for streaming response, it means receiving the last chunk of the response. + * + * The `comprehensive history` is returned by default. To get the `curated + * history`, set the `curated` parameter to `true`. + * + * @param curated - whether to return the curated history or the comprehensive + * history. + * @return History contents alternating between user and model for the entire + * chat session. + */ + getHistory(curated = false) { + const history = curated + ? extractCuratedHistory(this.history) + : this.history; + // Deep copy the history to avoid mutating the history outside of the + // chat session. + return structuredClone(history); + } + processStreamResponse(streamResponse, inputContent) { + return __asyncGenerator(this, arguments, function* processStreamResponse_1() { + var _a, e_1, _b, _c; + var _d, _e; + const outputContent = []; + try { + for (var _f = true, streamResponse_1 = __asyncValues(streamResponse), streamResponse_1_1; streamResponse_1_1 = yield __await(streamResponse_1.next()), _a = streamResponse_1_1.done, !_a; _f = true) { + _c = streamResponse_1_1.value; + _f = false; + const chunk = _c; + if (isValidResponse(chunk)) { + const content = (_e = (_d = chunk.candidates) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.content; + if (content !== undefined) { + outputContent.push(content); + } + } + yield yield __await(chunk); + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (!_f && !_a && (_b = streamResponse_1.return)) yield __await(_b.call(streamResponse_1)); + } + finally { if (e_1) throw e_1.error; } + } + this.recordHistory(inputContent, outputContent); + }); + } + recordHistory(userInput, modelOutput, automaticFunctionCallingHistory) { + let outputContents = []; + if (modelOutput.length > 0 && + modelOutput.every((content) => content.role !== undefined)) { + outputContents = modelOutput; + } + else { + // Appends an empty content when model returns empty response, so that the + // history is always alternating between user and model. + outputContents.push({ + role: 'model', + parts: [], + }); + } + if (automaticFunctionCallingHistory && + automaticFunctionCallingHistory.length > 0) { + this.history.push(...extractCuratedHistory(automaticFunctionCallingHistory)); + } + else { + this.history.push(userInput); + } + this.history.push(...outputContents); + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * API errors raised by the GenAI API. + */ +class ApiError extends Error { + constructor(options) { + super(options.message); + this.name = 'ApiError'; + this.status = options.status; + Object.setPrototypeOf(this, ApiError.prototype); + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Code generated by the Google Gen AI SDK generator DO NOT EDIT. +function createFileParametersToMldev(fromObject) { + const toObject = {}; + const fromFile = getValueByPath(fromObject, ['file']); + if (fromFile != null) { + setValueByPath(toObject, ['file'], fromFile); + } + return toObject; +} +function createFileResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function deleteFileParametersToMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'file'], tFileName(fromName)); + } + return toObject; +} +function deleteFileResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function getFileParametersToMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'file'], tFileName(fromName)); + } + return toObject; +} +function internalRegisterFilesParametersToMldev(fromObject) { + const toObject = {}; + const fromUris = getValueByPath(fromObject, ['uris']); + if (fromUris != null) { + setValueByPath(toObject, ['uris'], fromUris); + } + return toObject; +} +function listFilesConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + return toObject; +} +function listFilesParametersToMldev(fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listFilesConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function listFilesResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromFiles = getValueByPath(fromObject, ['files']); + if (fromFiles != null) { + let transformedList = fromFiles; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['files'], transformedList); + } + return toObject; +} +function registerFilesResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromFiles = getValueByPath(fromObject, ['files']); + if (fromFiles != null) { + let transformedList = fromFiles; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['files'], transformedList); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Files extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + /** + * Lists files. + * + * @param params - The parameters for the list request. + * @return - A pager of files. + * + * @example + * ```ts + * const files = await ai.files.list({config: {'pageSize': 2}}); + * for await (const file of files) { + * console.log(file); + * } + * ``` + */ + this.list = async (params = {}) => { + return new Pager(PagedItem.PAGED_ITEM_FILES, (x) => this.listInternal(x), await this.listInternal(params), params); + }; + } + /** + * Uploads a file asynchronously to the Gemini API. + * This method is not available in Vertex AI. + * Supported upload sources: + * - Node.js: File path (string) or Blob object. + * - Browser: Blob object (e.g., File). + * + * @remarks + * The `mimeType` can be specified in the `config` parameter. If omitted: + * - For file path (string) inputs, the `mimeType` will be inferred from the + * file extension. + * - For Blob object inputs, the `mimeType` will be set to the Blob's `type` + * property. + * Somex eamples for file extension to mimeType mapping: + * .txt -> text/plain + * .json -> application/json + * .jpg -> image/jpeg + * .png -> image/png + * .mp3 -> audio/mpeg + * .mp4 -> video/mp4 + * + * This section can contain multiple paragraphs and code examples. + * + * @param params - Optional parameters specified in the + * `types.UploadFileParameters` interface. + * @see {@link types.UploadFileParameters#config} for the optional + * config in the parameters. + * @return A promise that resolves to a `types.File` object. + * @throws An error if called on a Vertex AI client. + * @throws An error if the `mimeType` is not provided and can not be inferred, + * the `mimeType` can be provided in the `params.config` parameter. + * @throws An error occurs if a suitable upload location cannot be established. + * + * @example + * The following code uploads a file to Gemini API. + * + * ```ts + * const file = await ai.files.upload({file: 'file.txt', config: { + * mimeType: 'text/plain', + * }}); + * console.log(file.name); + * ``` + */ + async upload(params) { + if (this.apiClient.isVertexAI()) { + throw new Error('Vertex AI does not support uploading files. You can share files through a GCS bucket.'); + } + return this.apiClient + .uploadFile(params.file, params.config) + .then((resp) => { + return resp; + }); + } + /** + * Downloads a remotely stored file asynchronously to a location specified in + * the `params` object. This method only works on Node environment, to + * download files in the browser, use a browser compliant method like an <a> + * tag. + * + * @param params - The parameters for the download request. + * + * @example + * The following code downloads an example file named "files/mehozpxf877d" as + * "file.txt". + * + * ```ts + * await ai.files.download({file: file.name, downloadPath: 'file.txt'}); + * ``` + */ + async download(params) { + await this.apiClient.downloadFile(params); + } + /** + * Registers Google Cloud Storage files for use with the API. + * This method is only available in Node.js environments. + */ + async registerFiles(params) { + throw new Error('registerFiles is only supported in Node.js environments.'); + } + async _registerFiles(params) { + return this.registerFilesInternal(params); + } + async listInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = listFilesParametersToMldev(params); + path = formatMap('files', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listFilesResponseFromMldev(apiResponse); + const typedResp = new ListFilesResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + async createInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = createFileParametersToMldev(params); + path = formatMap('upload/v1beta/files', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = createFileResponseFromMldev(apiResponse); + const typedResp = new CreateFileResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Retrieves the file information from the service. + * + * @param params - The parameters for the get request + * @return The Promise that resolves to the types.File object requested. + * + * @example + * ```ts + * const config: GetFileParameters = { + * name: fileName, + * }; + * file = await ai.files.get(config); + * console.log(file.name); + * ``` + */ + async get(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = getFileParametersToMldev(params); + path = formatMap('files/{file}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } + /** + * Deletes a remotely stored file. + * + * @param params - The parameters for the delete request. + * @return The DeleteFileResponse, the response for the delete method. + * + * @example + * The following code deletes an example file named "files/mehozpxf877d". + * + * ```ts + * await ai.files.delete({name: file.name}); + * ``` + */ + async delete(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = deleteFileParametersToMldev(params); + path = formatMap('files/{file}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = deleteFileResponseFromMldev(apiResponse); + const typedResp = new DeleteFileResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + async registerFilesInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = internalRegisterFilesParametersToMldev(params); + path = formatMap('files:register', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = registerFilesResponseFromMldev(apiResponse); + const typedResp = new RegisterFilesResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function blobToMldev$2(fromObject) { + const toObject = {}; + const fromData = getValueByPath(fromObject, ['data']); + if (fromData != null) { + setValueByPath(toObject, ['data'], fromData); + } + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function contentToMldev$2(fromObject) { + const toObject = {}; + const fromParts = getValueByPath(fromObject, ['parts']); + if (fromParts != null) { + let transformedList = fromParts; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return partToMldev$2(item); + }); + } + setValueByPath(toObject, ['parts'], transformedList); + } + const fromRole = getValueByPath(fromObject, ['role']); + if (fromRole != null) { + setValueByPath(toObject, ['role'], fromRole); + } + return toObject; +} +function fileDataToMldev$2(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromFileUri = getValueByPath(fromObject, ['fileUri']); + if (fromFileUri != null) { + setValueByPath(toObject, ['fileUri'], fromFileUri); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function functionCallToMldev$2(fromObject) { + const toObject = {}; + const fromId = getValueByPath(fromObject, ['id']); + if (fromId != null) { + setValueByPath(toObject, ['id'], fromId); + } + const fromArgs = getValueByPath(fromObject, ['args']); + if (fromArgs != null) { + setValueByPath(toObject, ['args'], fromArgs); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + if (getValueByPath(fromObject, ['partialArgs']) !== undefined) { + throw new Error('partialArgs parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['willContinue']) !== undefined) { + throw new Error('willContinue parameter is not supported in Gemini API.'); + } + return toObject; +} +function functionDeclarationToVertex$1(fromObject) { + const toObject = {}; + const fromDescription = getValueByPath(fromObject, ['description']); + if (fromDescription != null) { + setValueByPath(toObject, ['description'], fromDescription); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromParameters = getValueByPath(fromObject, ['parameters']); + if (fromParameters != null) { + setValueByPath(toObject, ['parameters'], fromParameters); + } + const fromParametersJsonSchema = getValueByPath(fromObject, [ + 'parametersJsonSchema', + ]); + if (fromParametersJsonSchema != null) { + setValueByPath(toObject, ['parametersJsonSchema'], fromParametersJsonSchema); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], fromResponse); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + if (getValueByPath(fromObject, ['behavior']) !== undefined) { + throw new Error('behavior parameter is not supported in Vertex AI.'); + } + return toObject; +} +function generationConfigToVertex$1(fromObject) { + const toObject = {}; + const fromModelSelectionConfig = getValueByPath(fromObject, [ + 'modelSelectionConfig', + ]); + if (fromModelSelectionConfig != null) { + setValueByPath(toObject, ['modelConfig'], fromModelSelectionConfig); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + const fromAudioTimestamp = getValueByPath(fromObject, [ + 'audioTimestamp', + ]); + if (fromAudioTimestamp != null) { + setValueByPath(toObject, ['audioTimestamp'], fromAudioTimestamp); + } + const fromCandidateCount = getValueByPath(fromObject, [ + 'candidateCount', + ]); + if (fromCandidateCount != null) { + setValueByPath(toObject, ['candidateCount'], fromCandidateCount); + } + const fromEnableAffectiveDialog = getValueByPath(fromObject, [ + 'enableAffectiveDialog', + ]); + if (fromEnableAffectiveDialog != null) { + setValueByPath(toObject, ['enableAffectiveDialog'], fromEnableAffectiveDialog); + } + const fromFrequencyPenalty = getValueByPath(fromObject, [ + 'frequencyPenalty', + ]); + if (fromFrequencyPenalty != null) { + setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty); + } + const fromLogprobs = getValueByPath(fromObject, ['logprobs']); + if (fromLogprobs != null) { + setValueByPath(toObject, ['logprobs'], fromLogprobs); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (fromMaxOutputTokens != null) { + setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromPresencePenalty = getValueByPath(fromObject, [ + 'presencePenalty', + ]); + if (fromPresencePenalty != null) { + setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty); + } + const fromResponseLogprobs = getValueByPath(fromObject, [ + 'responseLogprobs', + ]); + if (fromResponseLogprobs != null) { + setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs); + } + const fromResponseMimeType = getValueByPath(fromObject, [ + 'responseMimeType', + ]); + if (fromResponseMimeType != null) { + setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (fromResponseModalities != null) { + setValueByPath(toObject, ['responseModalities'], fromResponseModalities); + } + const fromResponseSchema = getValueByPath(fromObject, [ + 'responseSchema', + ]); + if (fromResponseSchema != null) { + setValueByPath(toObject, ['responseSchema'], fromResponseSchema); + } + const fromRoutingConfig = getValueByPath(fromObject, [ + 'routingConfig', + ]); + if (fromRoutingConfig != null) { + setValueByPath(toObject, ['routingConfig'], fromRoutingConfig); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (fromSeed != null) { + setValueByPath(toObject, ['seed'], fromSeed); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (fromSpeechConfig != null) { + setValueByPath(toObject, ['speechConfig'], fromSpeechConfig); + } + const fromStopSequences = getValueByPath(fromObject, [ + 'stopSequences', + ]); + if (fromStopSequences != null) { + setValueByPath(toObject, ['stopSequences'], fromStopSequences); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (fromTemperature != null) { + setValueByPath(toObject, ['temperature'], fromTemperature); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (fromThinkingConfig != null) { + setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (fromTopK != null) { + setValueByPath(toObject, ['topK'], fromTopK); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (fromTopP != null) { + setValueByPath(toObject, ['topP'], fromTopP); + } + if (getValueByPath(fromObject, ['enableEnhancedCivicAnswers']) !== + undefined) { + throw new Error('enableEnhancedCivicAnswers parameter is not supported in Vertex AI.'); + } + return toObject; +} +function googleMapsToMldev$2(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['authConfig']) !== undefined) { + throw new Error('authConfig parameter is not supported in Gemini API.'); + } + const fromEnableWidget = getValueByPath(fromObject, ['enableWidget']); + if (fromEnableWidget != null) { + setValueByPath(toObject, ['enableWidget'], fromEnableWidget); + } + return toObject; +} +function googleSearchToMldev$2(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['excludeDomains']) !== undefined) { + throw new Error('excludeDomains parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['blockingConfidence']) !== undefined) { + throw new Error('blockingConfidence parameter is not supported in Gemini API.'); + } + const fromTimeRangeFilter = getValueByPath(fromObject, [ + 'timeRangeFilter', + ]); + if (fromTimeRangeFilter != null) { + setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter); + } + return toObject; +} +function liveConnectConfigToMldev$1(fromObject, parentObject) { + const toObject = {}; + const fromGenerationConfig = getValueByPath(fromObject, [ + 'generationConfig', + ]); + if (parentObject !== undefined && fromGenerationConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig'], fromGenerationConfig); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (parentObject !== undefined && fromResponseModalities != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'responseModalities'], fromResponseModalities); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (parentObject !== undefined && fromTemperature != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'temperature'], fromTemperature); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (parentObject !== undefined && fromTopP != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'topP'], fromTopP); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (parentObject !== undefined && fromTopK != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'topK'], fromTopK); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (parentObject !== undefined && fromMaxOutputTokens != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'maxOutputTokens'], fromMaxOutputTokens); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (parentObject !== undefined && fromMediaResolution != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'mediaResolution'], fromMediaResolution); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (parentObject !== undefined && fromSeed != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'seed'], fromSeed); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (parentObject !== undefined && fromSpeechConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'speechConfig'], tLiveSpeechConfig(fromSpeechConfig)); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (parentObject !== undefined && fromThinkingConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'thinkingConfig'], fromThinkingConfig); + } + const fromEnableAffectiveDialog = getValueByPath(fromObject, [ + 'enableAffectiveDialog', + ]); + if (parentObject !== undefined && fromEnableAffectiveDialog != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'enableAffectiveDialog'], fromEnableAffectiveDialog); + } + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['setup', 'systemInstruction'], contentToMldev$2(tContent(fromSystemInstruction))); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = tTools(fromTools); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToMldev$2(tTool(item)); + }); + } + setValueByPath(parentObject, ['setup', 'tools'], transformedList); + } + const fromSessionResumption = getValueByPath(fromObject, [ + 'sessionResumption', + ]); + if (parentObject !== undefined && fromSessionResumption != null) { + setValueByPath(parentObject, ['setup', 'sessionResumption'], sessionResumptionConfigToMldev$1(fromSessionResumption)); + } + const fromInputAudioTranscription = getValueByPath(fromObject, [ + 'inputAudioTranscription', + ]); + if (parentObject !== undefined && fromInputAudioTranscription != null) { + setValueByPath(parentObject, ['setup', 'inputAudioTranscription'], fromInputAudioTranscription); + } + const fromOutputAudioTranscription = getValueByPath(fromObject, [ + 'outputAudioTranscription', + ]); + if (parentObject !== undefined && fromOutputAudioTranscription != null) { + setValueByPath(parentObject, ['setup', 'outputAudioTranscription'], fromOutputAudioTranscription); + } + const fromRealtimeInputConfig = getValueByPath(fromObject, [ + 'realtimeInputConfig', + ]); + if (parentObject !== undefined && fromRealtimeInputConfig != null) { + setValueByPath(parentObject, ['setup', 'realtimeInputConfig'], fromRealtimeInputConfig); + } + const fromContextWindowCompression = getValueByPath(fromObject, [ + 'contextWindowCompression', + ]); + if (parentObject !== undefined && fromContextWindowCompression != null) { + setValueByPath(parentObject, ['setup', 'contextWindowCompression'], fromContextWindowCompression); + } + const fromProactivity = getValueByPath(fromObject, ['proactivity']); + if (parentObject !== undefined && fromProactivity != null) { + setValueByPath(parentObject, ['setup', 'proactivity'], fromProactivity); + } + if (getValueByPath(fromObject, ['explicitVadSignal']) !== undefined) { + throw new Error('explicitVadSignal parameter is not supported in Gemini API.'); + } + return toObject; +} +function liveConnectConfigToVertex(fromObject, parentObject) { + const toObject = {}; + const fromGenerationConfig = getValueByPath(fromObject, [ + 'generationConfig', + ]); + if (parentObject !== undefined && fromGenerationConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig'], generationConfigToVertex$1(fromGenerationConfig)); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (parentObject !== undefined && fromResponseModalities != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'responseModalities'], fromResponseModalities); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (parentObject !== undefined && fromTemperature != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'temperature'], fromTemperature); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (parentObject !== undefined && fromTopP != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'topP'], fromTopP); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (parentObject !== undefined && fromTopK != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'topK'], fromTopK); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (parentObject !== undefined && fromMaxOutputTokens != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'maxOutputTokens'], fromMaxOutputTokens); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (parentObject !== undefined && fromMediaResolution != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'mediaResolution'], fromMediaResolution); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (parentObject !== undefined && fromSeed != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'seed'], fromSeed); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (parentObject !== undefined && fromSpeechConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'speechConfig'], tLiveSpeechConfig(fromSpeechConfig)); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (parentObject !== undefined && fromThinkingConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'thinkingConfig'], fromThinkingConfig); + } + const fromEnableAffectiveDialog = getValueByPath(fromObject, [ + 'enableAffectiveDialog', + ]); + if (parentObject !== undefined && fromEnableAffectiveDialog != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'enableAffectiveDialog'], fromEnableAffectiveDialog); + } + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['setup', 'systemInstruction'], tContent(fromSystemInstruction)); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = tTools(fromTools); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToVertex$1(tTool(item)); + }); + } + setValueByPath(parentObject, ['setup', 'tools'], transformedList); + } + const fromSessionResumption = getValueByPath(fromObject, [ + 'sessionResumption', + ]); + if (parentObject !== undefined && fromSessionResumption != null) { + setValueByPath(parentObject, ['setup', 'sessionResumption'], fromSessionResumption); + } + const fromInputAudioTranscription = getValueByPath(fromObject, [ + 'inputAudioTranscription', + ]); + if (parentObject !== undefined && fromInputAudioTranscription != null) { + setValueByPath(parentObject, ['setup', 'inputAudioTranscription'], fromInputAudioTranscription); + } + const fromOutputAudioTranscription = getValueByPath(fromObject, [ + 'outputAudioTranscription', + ]); + if (parentObject !== undefined && fromOutputAudioTranscription != null) { + setValueByPath(parentObject, ['setup', 'outputAudioTranscription'], fromOutputAudioTranscription); + } + const fromRealtimeInputConfig = getValueByPath(fromObject, [ + 'realtimeInputConfig', + ]); + if (parentObject !== undefined && fromRealtimeInputConfig != null) { + setValueByPath(parentObject, ['setup', 'realtimeInputConfig'], fromRealtimeInputConfig); + } + const fromContextWindowCompression = getValueByPath(fromObject, [ + 'contextWindowCompression', + ]); + if (parentObject !== undefined && fromContextWindowCompression != null) { + setValueByPath(parentObject, ['setup', 'contextWindowCompression'], fromContextWindowCompression); + } + const fromProactivity = getValueByPath(fromObject, ['proactivity']); + if (parentObject !== undefined && fromProactivity != null) { + setValueByPath(parentObject, ['setup', 'proactivity'], fromProactivity); + } + const fromExplicitVadSignal = getValueByPath(fromObject, [ + 'explicitVadSignal', + ]); + if (parentObject !== undefined && fromExplicitVadSignal != null) { + setValueByPath(parentObject, ['setup', 'explicitVadSignal'], fromExplicitVadSignal); + } + return toObject; +} +function liveConnectParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['setup', 'model'], tModel(apiClient, fromModel)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['config'], liveConnectConfigToMldev$1(fromConfig, toObject)); + } + return toObject; +} +function liveConnectParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['setup', 'model'], tModel(apiClient, fromModel)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['config'], liveConnectConfigToVertex(fromConfig, toObject)); + } + return toObject; +} +function liveMusicSetConfigParametersToMldev(fromObject) { + const toObject = {}; + const fromMusicGenerationConfig = getValueByPath(fromObject, [ + 'musicGenerationConfig', + ]); + if (fromMusicGenerationConfig != null) { + setValueByPath(toObject, ['musicGenerationConfig'], fromMusicGenerationConfig); + } + return toObject; +} +function liveMusicSetWeightedPromptsParametersToMldev(fromObject) { + const toObject = {}; + const fromWeightedPrompts = getValueByPath(fromObject, [ + 'weightedPrompts', + ]); + if (fromWeightedPrompts != null) { + let transformedList = fromWeightedPrompts; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['weightedPrompts'], transformedList); + } + return toObject; +} +function liveSendRealtimeInputParametersToMldev(fromObject) { + const toObject = {}; + const fromMedia = getValueByPath(fromObject, ['media']); + if (fromMedia != null) { + let transformedList = tBlobs(fromMedia); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return blobToMldev$2(item); + }); + } + setValueByPath(toObject, ['mediaChunks'], transformedList); + } + const fromAudio = getValueByPath(fromObject, ['audio']); + if (fromAudio != null) { + setValueByPath(toObject, ['audio'], blobToMldev$2(tAudioBlob(fromAudio))); + } + const fromAudioStreamEnd = getValueByPath(fromObject, [ + 'audioStreamEnd', + ]); + if (fromAudioStreamEnd != null) { + setValueByPath(toObject, ['audioStreamEnd'], fromAudioStreamEnd); + } + const fromVideo = getValueByPath(fromObject, ['video']); + if (fromVideo != null) { + setValueByPath(toObject, ['video'], blobToMldev$2(tImageBlob(fromVideo))); + } + const fromText = getValueByPath(fromObject, ['text']); + if (fromText != null) { + setValueByPath(toObject, ['text'], fromText); + } + const fromActivityStart = getValueByPath(fromObject, [ + 'activityStart', + ]); + if (fromActivityStart != null) { + setValueByPath(toObject, ['activityStart'], fromActivityStart); + } + const fromActivityEnd = getValueByPath(fromObject, ['activityEnd']); + if (fromActivityEnd != null) { + setValueByPath(toObject, ['activityEnd'], fromActivityEnd); + } + return toObject; +} +function liveSendRealtimeInputParametersToVertex(fromObject) { + const toObject = {}; + const fromMedia = getValueByPath(fromObject, ['media']); + if (fromMedia != null) { + let transformedList = tBlobs(fromMedia); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['mediaChunks'], transformedList); + } + const fromAudio = getValueByPath(fromObject, ['audio']); + if (fromAudio != null) { + setValueByPath(toObject, ['audio'], tAudioBlob(fromAudio)); + } + const fromAudioStreamEnd = getValueByPath(fromObject, [ + 'audioStreamEnd', + ]); + if (fromAudioStreamEnd != null) { + setValueByPath(toObject, ['audioStreamEnd'], fromAudioStreamEnd); + } + const fromVideo = getValueByPath(fromObject, ['video']); + if (fromVideo != null) { + setValueByPath(toObject, ['video'], tImageBlob(fromVideo)); + } + const fromText = getValueByPath(fromObject, ['text']); + if (fromText != null) { + setValueByPath(toObject, ['text'], fromText); + } + const fromActivityStart = getValueByPath(fromObject, [ + 'activityStart', + ]); + if (fromActivityStart != null) { + setValueByPath(toObject, ['activityStart'], fromActivityStart); + } + const fromActivityEnd = getValueByPath(fromObject, ['activityEnd']); + if (fromActivityEnd != null) { + setValueByPath(toObject, ['activityEnd'], fromActivityEnd); + } + return toObject; +} +function liveServerMessageFromVertex(fromObject) { + const toObject = {}; + const fromSetupComplete = getValueByPath(fromObject, [ + 'setupComplete', + ]); + if (fromSetupComplete != null) { + setValueByPath(toObject, ['setupComplete'], fromSetupComplete); + } + const fromServerContent = getValueByPath(fromObject, [ + 'serverContent', + ]); + if (fromServerContent != null) { + setValueByPath(toObject, ['serverContent'], fromServerContent); + } + const fromToolCall = getValueByPath(fromObject, ['toolCall']); + if (fromToolCall != null) { + setValueByPath(toObject, ['toolCall'], fromToolCall); + } + const fromToolCallCancellation = getValueByPath(fromObject, [ + 'toolCallCancellation', + ]); + if (fromToolCallCancellation != null) { + setValueByPath(toObject, ['toolCallCancellation'], fromToolCallCancellation); + } + const fromUsageMetadata = getValueByPath(fromObject, [ + 'usageMetadata', + ]); + if (fromUsageMetadata != null) { + setValueByPath(toObject, ['usageMetadata'], usageMetadataFromVertex(fromUsageMetadata)); + } + const fromGoAway = getValueByPath(fromObject, ['goAway']); + if (fromGoAway != null) { + setValueByPath(toObject, ['goAway'], fromGoAway); + } + const fromSessionResumptionUpdate = getValueByPath(fromObject, [ + 'sessionResumptionUpdate', + ]); + if (fromSessionResumptionUpdate != null) { + setValueByPath(toObject, ['sessionResumptionUpdate'], fromSessionResumptionUpdate); + } + const fromVoiceActivityDetectionSignal = getValueByPath(fromObject, [ + 'voiceActivityDetectionSignal', + ]); + if (fromVoiceActivityDetectionSignal != null) { + setValueByPath(toObject, ['voiceActivityDetectionSignal'], fromVoiceActivityDetectionSignal); + } + const fromVoiceActivity = getValueByPath(fromObject, [ + 'voiceActivity', + ]); + if (fromVoiceActivity != null) { + setValueByPath(toObject, ['voiceActivity'], voiceActivityFromVertex(fromVoiceActivity)); + } + return toObject; +} +function partToMldev$2(fromObject) { + const toObject = {}; + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromCodeExecutionResult = getValueByPath(fromObject, [ + 'codeExecutionResult', + ]); + if (fromCodeExecutionResult != null) { + setValueByPath(toObject, ['codeExecutionResult'], fromCodeExecutionResult); + } + const fromExecutableCode = getValueByPath(fromObject, [ + 'executableCode', + ]); + if (fromExecutableCode != null) { + setValueByPath(toObject, ['executableCode'], fromExecutableCode); + } + const fromFileData = getValueByPath(fromObject, ['fileData']); + if (fromFileData != null) { + setValueByPath(toObject, ['fileData'], fileDataToMldev$2(fromFileData)); + } + const fromFunctionCall = getValueByPath(fromObject, ['functionCall']); + if (fromFunctionCall != null) { + setValueByPath(toObject, ['functionCall'], functionCallToMldev$2(fromFunctionCall)); + } + const fromFunctionResponse = getValueByPath(fromObject, [ + 'functionResponse', + ]); + if (fromFunctionResponse != null) { + setValueByPath(toObject, ['functionResponse'], fromFunctionResponse); + } + const fromInlineData = getValueByPath(fromObject, ['inlineData']); + if (fromInlineData != null) { + setValueByPath(toObject, ['inlineData'], blobToMldev$2(fromInlineData)); + } + const fromText = getValueByPath(fromObject, ['text']); + if (fromText != null) { + setValueByPath(toObject, ['text'], fromText); + } + const fromThought = getValueByPath(fromObject, ['thought']); + if (fromThought != null) { + setValueByPath(toObject, ['thought'], fromThought); + } + const fromThoughtSignature = getValueByPath(fromObject, [ + 'thoughtSignature', + ]); + if (fromThoughtSignature != null) { + setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature); + } + const fromVideoMetadata = getValueByPath(fromObject, [ + 'videoMetadata', + ]); + if (fromVideoMetadata != null) { + setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata); + } + return toObject; +} +function sessionResumptionConfigToMldev$1(fromObject) { + const toObject = {}; + const fromHandle = getValueByPath(fromObject, ['handle']); + if (fromHandle != null) { + setValueByPath(toObject, ['handle'], fromHandle); + } + if (getValueByPath(fromObject, ['transparent']) !== undefined) { + throw new Error('transparent parameter is not supported in Gemini API.'); + } + return toObject; +} +function toolToMldev$2(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['retrieval']) !== undefined) { + throw new Error('retrieval parameter is not supported in Gemini API.'); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + const fromFileSearch = getValueByPath(fromObject, ['fileSearch']); + if (fromFileSearch != null) { + setValueByPath(toObject, ['fileSearch'], fromFileSearch); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + if (getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined) { + throw new Error('enterpriseWebSearch parameter is not supported in Gemini API.'); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], googleMapsToMldev$2(fromGoogleMaps)); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], googleSearchToMldev$2(fromGoogleSearch)); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} +function toolToVertex$1(fromObject) { + const toObject = {}; + const fromRetrieval = getValueByPath(fromObject, ['retrieval']); + if (fromRetrieval != null) { + setValueByPath(toObject, ['retrieval'], fromRetrieval); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + if (getValueByPath(fromObject, ['fileSearch']) !== undefined) { + throw new Error('fileSearch parameter is not supported in Vertex AI.'); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + const fromEnterpriseWebSearch = getValueByPath(fromObject, [ + 'enterpriseWebSearch', + ]); + if (fromEnterpriseWebSearch != null) { + setValueByPath(toObject, ['enterpriseWebSearch'], fromEnterpriseWebSearch); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return functionDeclarationToVertex$1(item); + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], fromGoogleMaps); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], fromGoogleSearch); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} +function usageMetadataFromVertex(fromObject) { + const toObject = {}; + const fromPromptTokenCount = getValueByPath(fromObject, [ + 'promptTokenCount', + ]); + if (fromPromptTokenCount != null) { + setValueByPath(toObject, ['promptTokenCount'], fromPromptTokenCount); + } + const fromCachedContentTokenCount = getValueByPath(fromObject, [ + 'cachedContentTokenCount', + ]); + if (fromCachedContentTokenCount != null) { + setValueByPath(toObject, ['cachedContentTokenCount'], fromCachedContentTokenCount); + } + const fromResponseTokenCount = getValueByPath(fromObject, [ + 'candidatesTokenCount', + ]); + if (fromResponseTokenCount != null) { + setValueByPath(toObject, ['responseTokenCount'], fromResponseTokenCount); + } + const fromToolUsePromptTokenCount = getValueByPath(fromObject, [ + 'toolUsePromptTokenCount', + ]); + if (fromToolUsePromptTokenCount != null) { + setValueByPath(toObject, ['toolUsePromptTokenCount'], fromToolUsePromptTokenCount); + } + const fromThoughtsTokenCount = getValueByPath(fromObject, [ + 'thoughtsTokenCount', + ]); + if (fromThoughtsTokenCount != null) { + setValueByPath(toObject, ['thoughtsTokenCount'], fromThoughtsTokenCount); + } + const fromTotalTokenCount = getValueByPath(fromObject, [ + 'totalTokenCount', + ]); + if (fromTotalTokenCount != null) { + setValueByPath(toObject, ['totalTokenCount'], fromTotalTokenCount); + } + const fromPromptTokensDetails = getValueByPath(fromObject, [ + 'promptTokensDetails', + ]); + if (fromPromptTokensDetails != null) { + let transformedList = fromPromptTokensDetails; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['promptTokensDetails'], transformedList); + } + const fromCacheTokensDetails = getValueByPath(fromObject, [ + 'cacheTokensDetails', + ]); + if (fromCacheTokensDetails != null) { + let transformedList = fromCacheTokensDetails; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['cacheTokensDetails'], transformedList); + } + const fromResponseTokensDetails = getValueByPath(fromObject, [ + 'candidatesTokensDetails', + ]); + if (fromResponseTokensDetails != null) { + let transformedList = fromResponseTokensDetails; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['responseTokensDetails'], transformedList); + } + const fromToolUsePromptTokensDetails = getValueByPath(fromObject, [ + 'toolUsePromptTokensDetails', + ]); + if (fromToolUsePromptTokensDetails != null) { + let transformedList = fromToolUsePromptTokensDetails; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['toolUsePromptTokensDetails'], transformedList); + } + const fromTrafficType = getValueByPath(fromObject, ['trafficType']); + if (fromTrafficType != null) { + setValueByPath(toObject, ['trafficType'], fromTrafficType); + } + return toObject; +} +function voiceActivityFromVertex(fromObject) { + const toObject = {}; + const fromVoiceActivityType = getValueByPath(fromObject, ['type']); + if (fromVoiceActivityType != null) { + setValueByPath(toObject, ['voiceActivityType'], fromVoiceActivityType); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function blobToMldev$1(fromObject, _rootObject) { + const toObject = {}; + const fromData = getValueByPath(fromObject, ['data']); + if (fromData != null) { + setValueByPath(toObject, ['data'], fromData); + } + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function candidateFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromContent = getValueByPath(fromObject, ['content']); + if (fromContent != null) { + setValueByPath(toObject, ['content'], fromContent); + } + const fromCitationMetadata = getValueByPath(fromObject, [ + 'citationMetadata', + ]); + if (fromCitationMetadata != null) { + setValueByPath(toObject, ['citationMetadata'], citationMetadataFromMldev(fromCitationMetadata)); + } + const fromTokenCount = getValueByPath(fromObject, ['tokenCount']); + if (fromTokenCount != null) { + setValueByPath(toObject, ['tokenCount'], fromTokenCount); + } + const fromFinishReason = getValueByPath(fromObject, ['finishReason']); + if (fromFinishReason != null) { + setValueByPath(toObject, ['finishReason'], fromFinishReason); + } + const fromAvgLogprobs = getValueByPath(fromObject, ['avgLogprobs']); + if (fromAvgLogprobs != null) { + setValueByPath(toObject, ['avgLogprobs'], fromAvgLogprobs); + } + const fromGroundingMetadata = getValueByPath(fromObject, [ + 'groundingMetadata', + ]); + if (fromGroundingMetadata != null) { + setValueByPath(toObject, ['groundingMetadata'], fromGroundingMetadata); + } + const fromIndex = getValueByPath(fromObject, ['index']); + if (fromIndex != null) { + setValueByPath(toObject, ['index'], fromIndex); + } + const fromLogprobsResult = getValueByPath(fromObject, [ + 'logprobsResult', + ]); + if (fromLogprobsResult != null) { + setValueByPath(toObject, ['logprobsResult'], fromLogprobsResult); + } + const fromSafetyRatings = getValueByPath(fromObject, [ + 'safetyRatings', + ]); + if (fromSafetyRatings != null) { + let transformedList = fromSafetyRatings; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['safetyRatings'], transformedList); + } + const fromUrlContextMetadata = getValueByPath(fromObject, [ + 'urlContextMetadata', + ]); + if (fromUrlContextMetadata != null) { + setValueByPath(toObject, ['urlContextMetadata'], fromUrlContextMetadata); + } + return toObject; +} +function citationMetadataFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromCitations = getValueByPath(fromObject, ['citationSources']); + if (fromCitations != null) { + let transformedList = fromCitations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['citations'], transformedList); + } + return toObject; +} +function computeTokensParametersToVertex(apiClient, fromObject, _rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['contents'], transformedList); + } + return toObject; +} +function computeTokensResponseFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromTokensInfo = getValueByPath(fromObject, ['tokensInfo']); + if (fromTokensInfo != null) { + let transformedList = fromTokensInfo; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['tokensInfo'], transformedList); + } + return toObject; +} +function contentEmbeddingFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromValues = getValueByPath(fromObject, ['values']); + if (fromValues != null) { + setValueByPath(toObject, ['values'], fromValues); + } + const fromStatistics = getValueByPath(fromObject, ['statistics']); + if (fromStatistics != null) { + setValueByPath(toObject, ['statistics'], contentEmbeddingStatisticsFromVertex(fromStatistics)); + } + return toObject; +} +function contentEmbeddingStatisticsFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromTruncated = getValueByPath(fromObject, ['truncated']); + if (fromTruncated != null) { + setValueByPath(toObject, ['truncated'], fromTruncated); + } + const fromTokenCount = getValueByPath(fromObject, ['token_count']); + if (fromTokenCount != null) { + setValueByPath(toObject, ['tokenCount'], fromTokenCount); + } + return toObject; +} +function contentToMldev$1(fromObject, rootObject) { + const toObject = {}; + const fromParts = getValueByPath(fromObject, ['parts']); + if (fromParts != null) { + let transformedList = fromParts; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return partToMldev$1(item); + }); + } + setValueByPath(toObject, ['parts'], transformedList); + } + const fromRole = getValueByPath(fromObject, ['role']); + if (fromRole != null) { + setValueByPath(toObject, ['role'], fromRole); + } + return toObject; +} +function controlReferenceConfigToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromControlType = getValueByPath(fromObject, ['controlType']); + if (fromControlType != null) { + setValueByPath(toObject, ['controlType'], fromControlType); + } + const fromEnableControlImageComputation = getValueByPath(fromObject, [ + 'enableControlImageComputation', + ]); + if (fromEnableControlImageComputation != null) { + setValueByPath(toObject, ['computeControl'], fromEnableControlImageComputation); + } + return toObject; +} +function countTokensConfigToMldev(fromObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['systemInstruction']) !== undefined) { + throw new Error('systemInstruction parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['tools']) !== undefined) { + throw new Error('tools parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['generationConfig']) !== undefined) { + throw new Error('generationConfig parameter is not supported in Gemini API.'); + } + return toObject; +} +function countTokensConfigToVertex(fromObject, parentObject, rootObject) { + const toObject = {}; + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['systemInstruction'], tContent(fromSystemInstruction)); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = fromTools; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToVertex(item); + }); + } + setValueByPath(parentObject, ['tools'], transformedList); + } + const fromGenerationConfig = getValueByPath(fromObject, [ + 'generationConfig', + ]); + if (parentObject !== undefined && fromGenerationConfig != null) { + setValueByPath(parentObject, ['generationConfig'], generationConfigToVertex(fromGenerationConfig)); + } + return toObject; +} +function countTokensParametersToMldev(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return contentToMldev$1(item); + }); + } + setValueByPath(toObject, ['contents'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + countTokensConfigToMldev(fromConfig); + } + return toObject; +} +function countTokensParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['contents'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + countTokensConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function countTokensResponseFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromTotalTokens = getValueByPath(fromObject, ['totalTokens']); + if (fromTotalTokens != null) { + setValueByPath(toObject, ['totalTokens'], fromTotalTokens); + } + const fromCachedContentTokenCount = getValueByPath(fromObject, [ + 'cachedContentTokenCount', + ]); + if (fromCachedContentTokenCount != null) { + setValueByPath(toObject, ['cachedContentTokenCount'], fromCachedContentTokenCount); + } + return toObject; +} +function countTokensResponseFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromTotalTokens = getValueByPath(fromObject, ['totalTokens']); + if (fromTotalTokens != null) { + setValueByPath(toObject, ['totalTokens'], fromTotalTokens); + } + return toObject; +} +function deleteModelParametersToMldev(apiClient, fromObject, _rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'name'], tModel(apiClient, fromModel)); + } + return toObject; +} +function deleteModelParametersToVertex(apiClient, fromObject, _rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'name'], tModel(apiClient, fromModel)); + } + return toObject; +} +function deleteModelResponseFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function deleteModelResponseFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function editImageConfigToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromOutputGcsUri = getValueByPath(fromObject, ['outputGcsUri']); + if (parentObject !== undefined && fromOutputGcsUri != null) { + setValueByPath(parentObject, ['parameters', 'storageUri'], fromOutputGcsUri); + } + const fromNegativePrompt = getValueByPath(fromObject, [ + 'negativePrompt', + ]); + if (parentObject !== undefined && fromNegativePrompt != null) { + setValueByPath(parentObject, ['parameters', 'negativePrompt'], fromNegativePrompt); + } + const fromNumberOfImages = getValueByPath(fromObject, [ + 'numberOfImages', + ]); + if (parentObject !== undefined && fromNumberOfImages != null) { + setValueByPath(parentObject, ['parameters', 'sampleCount'], fromNumberOfImages); + } + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (parentObject !== undefined && fromAspectRatio != null) { + setValueByPath(parentObject, ['parameters', 'aspectRatio'], fromAspectRatio); + } + const fromGuidanceScale = getValueByPath(fromObject, [ + 'guidanceScale', + ]); + if (parentObject !== undefined && fromGuidanceScale != null) { + setValueByPath(parentObject, ['parameters', 'guidanceScale'], fromGuidanceScale); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (parentObject !== undefined && fromSeed != null) { + setValueByPath(parentObject, ['parameters', 'seed'], fromSeed); + } + const fromSafetyFilterLevel = getValueByPath(fromObject, [ + 'safetyFilterLevel', + ]); + if (parentObject !== undefined && fromSafetyFilterLevel != null) { + setValueByPath(parentObject, ['parameters', 'safetySetting'], fromSafetyFilterLevel); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (parentObject !== undefined && fromPersonGeneration != null) { + setValueByPath(parentObject, ['parameters', 'personGeneration'], fromPersonGeneration); + } + const fromIncludeSafetyAttributes = getValueByPath(fromObject, [ + 'includeSafetyAttributes', + ]); + if (parentObject !== undefined && fromIncludeSafetyAttributes != null) { + setValueByPath(parentObject, ['parameters', 'includeSafetyAttributes'], fromIncludeSafetyAttributes); + } + const fromIncludeRaiReason = getValueByPath(fromObject, [ + 'includeRaiReason', + ]); + if (parentObject !== undefined && fromIncludeRaiReason != null) { + setValueByPath(parentObject, ['parameters', 'includeRaiReason'], fromIncludeRaiReason); + } + const fromLanguage = getValueByPath(fromObject, ['language']); + if (parentObject !== undefined && fromLanguage != null) { + setValueByPath(parentObject, ['parameters', 'language'], fromLanguage); + } + const fromOutputMimeType = getValueByPath(fromObject, [ + 'outputMimeType', + ]); + if (parentObject !== undefined && fromOutputMimeType != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'mimeType'], fromOutputMimeType); + } + const fromOutputCompressionQuality = getValueByPath(fromObject, [ + 'outputCompressionQuality', + ]); + if (parentObject !== undefined && fromOutputCompressionQuality != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'compressionQuality'], fromOutputCompressionQuality); + } + const fromAddWatermark = getValueByPath(fromObject, ['addWatermark']); + if (parentObject !== undefined && fromAddWatermark != null) { + setValueByPath(parentObject, ['parameters', 'addWatermark'], fromAddWatermark); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (parentObject !== undefined && fromLabels != null) { + setValueByPath(parentObject, ['labels'], fromLabels); + } + const fromEditMode = getValueByPath(fromObject, ['editMode']); + if (parentObject !== undefined && fromEditMode != null) { + setValueByPath(parentObject, ['parameters', 'editMode'], fromEditMode); + } + const fromBaseSteps = getValueByPath(fromObject, ['baseSteps']); + if (parentObject !== undefined && fromBaseSteps != null) { + setValueByPath(parentObject, ['parameters', 'editConfig', 'baseSteps'], fromBaseSteps); + } + return toObject; +} +function editImageParametersInternalToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (fromPrompt != null) { + setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromReferenceImages = getValueByPath(fromObject, [ + 'referenceImages', + ]); + if (fromReferenceImages != null) { + let transformedList = fromReferenceImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return referenceImageAPIInternalToVertex(item); + }); + } + setValueByPath(toObject, ['instances[0]', 'referenceImages'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + editImageConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function editImageResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromGeneratedImages = getValueByPath(fromObject, [ + 'predictions', + ]); + if (fromGeneratedImages != null) { + let transformedList = fromGeneratedImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedImageFromVertex(item); + }); + } + setValueByPath(toObject, ['generatedImages'], transformedList); + } + return toObject; +} +function embedContentConfigToMldev(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromTaskType = getValueByPath(fromObject, ['taskType']); + if (parentObject !== undefined && fromTaskType != null) { + setValueByPath(parentObject, ['requests[]', 'taskType'], fromTaskType); + } + const fromTitle = getValueByPath(fromObject, ['title']); + if (parentObject !== undefined && fromTitle != null) { + setValueByPath(parentObject, ['requests[]', 'title'], fromTitle); + } + const fromOutputDimensionality = getValueByPath(fromObject, [ + 'outputDimensionality', + ]); + if (parentObject !== undefined && fromOutputDimensionality != null) { + setValueByPath(parentObject, ['requests[]', 'outputDimensionality'], fromOutputDimensionality); + } + if (getValueByPath(fromObject, ['mimeType']) !== undefined) { + throw new Error('mimeType parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['autoTruncate']) !== undefined) { + throw new Error('autoTruncate parameter is not supported in Gemini API.'); + } + return toObject; +} +function embedContentConfigToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromTaskType = getValueByPath(fromObject, ['taskType']); + if (parentObject !== undefined && fromTaskType != null) { + setValueByPath(parentObject, ['instances[]', 'task_type'], fromTaskType); + } + const fromTitle = getValueByPath(fromObject, ['title']); + if (parentObject !== undefined && fromTitle != null) { + setValueByPath(parentObject, ['instances[]', 'title'], fromTitle); + } + const fromOutputDimensionality = getValueByPath(fromObject, [ + 'outputDimensionality', + ]); + if (parentObject !== undefined && fromOutputDimensionality != null) { + setValueByPath(parentObject, ['parameters', 'outputDimensionality'], fromOutputDimensionality); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (parentObject !== undefined && fromMimeType != null) { + setValueByPath(parentObject, ['instances[]', 'mimeType'], fromMimeType); + } + const fromAutoTruncate = getValueByPath(fromObject, ['autoTruncate']); + if (parentObject !== undefined && fromAutoTruncate != null) { + setValueByPath(parentObject, ['parameters', 'autoTruncate'], fromAutoTruncate); + } + return toObject; +} +function embedContentParametersToMldev(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContentsForEmbed(apiClient, fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['requests[]', 'content'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + embedContentConfigToMldev(fromConfig, toObject); + } + const fromModelForEmbedContent = getValueByPath(fromObject, ['model']); + if (fromModelForEmbedContent !== undefined) { + setValueByPath(toObject, ['requests[]', 'model'], tModel(apiClient, fromModelForEmbedContent)); + } + return toObject; +} +function embedContentParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContentsForEmbed(apiClient, fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['instances[]', 'content'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + embedContentConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function embedContentResponseFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromEmbeddings = getValueByPath(fromObject, ['embeddings']); + if (fromEmbeddings != null) { + let transformedList = fromEmbeddings; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['embeddings'], transformedList); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + return toObject; +} +function embedContentResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromEmbeddings = getValueByPath(fromObject, [ + 'predictions[]', + 'embeddings', + ]); + if (fromEmbeddings != null) { + let transformedList = fromEmbeddings; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return contentEmbeddingFromVertex(item); + }); + } + setValueByPath(toObject, ['embeddings'], transformedList); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + return toObject; +} +function endpointFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['endpoint']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromDeployedModelId = getValueByPath(fromObject, [ + 'deployedModelId', + ]); + if (fromDeployedModelId != null) { + setValueByPath(toObject, ['deployedModelId'], fromDeployedModelId); + } + return toObject; +} +function fileDataToMldev$1(fromObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromFileUri = getValueByPath(fromObject, ['fileUri']); + if (fromFileUri != null) { + setValueByPath(toObject, ['fileUri'], fromFileUri); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function functionCallToMldev$1(fromObject, _rootObject) { + const toObject = {}; + const fromId = getValueByPath(fromObject, ['id']); + if (fromId != null) { + setValueByPath(toObject, ['id'], fromId); + } + const fromArgs = getValueByPath(fromObject, ['args']); + if (fromArgs != null) { + setValueByPath(toObject, ['args'], fromArgs); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + if (getValueByPath(fromObject, ['partialArgs']) !== undefined) { + throw new Error('partialArgs parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['willContinue']) !== undefined) { + throw new Error('willContinue parameter is not supported in Gemini API.'); + } + return toObject; +} +function functionCallingConfigToMldev(fromObject, _rootObject) { + const toObject = {}; + const fromAllowedFunctionNames = getValueByPath(fromObject, [ + 'allowedFunctionNames', + ]); + if (fromAllowedFunctionNames != null) { + setValueByPath(toObject, ['allowedFunctionNames'], fromAllowedFunctionNames); + } + const fromMode = getValueByPath(fromObject, ['mode']); + if (fromMode != null) { + setValueByPath(toObject, ['mode'], fromMode); + } + if (getValueByPath(fromObject, ['streamFunctionCallArguments']) !== + undefined) { + throw new Error('streamFunctionCallArguments parameter is not supported in Gemini API.'); + } + return toObject; +} +function functionDeclarationToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromDescription = getValueByPath(fromObject, ['description']); + if (fromDescription != null) { + setValueByPath(toObject, ['description'], fromDescription); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromParameters = getValueByPath(fromObject, ['parameters']); + if (fromParameters != null) { + setValueByPath(toObject, ['parameters'], fromParameters); + } + const fromParametersJsonSchema = getValueByPath(fromObject, [ + 'parametersJsonSchema', + ]); + if (fromParametersJsonSchema != null) { + setValueByPath(toObject, ['parametersJsonSchema'], fromParametersJsonSchema); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], fromResponse); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + if (getValueByPath(fromObject, ['behavior']) !== undefined) { + throw new Error('behavior parameter is not supported in Vertex AI.'); + } + return toObject; +} +function generateContentConfigToMldev(apiClient, fromObject, parentObject, rootObject) { + const toObject = {}; + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['systemInstruction'], contentToMldev$1(tContent(fromSystemInstruction))); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (fromTemperature != null) { + setValueByPath(toObject, ['temperature'], fromTemperature); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (fromTopP != null) { + setValueByPath(toObject, ['topP'], fromTopP); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (fromTopK != null) { + setValueByPath(toObject, ['topK'], fromTopK); + } + const fromCandidateCount = getValueByPath(fromObject, [ + 'candidateCount', + ]); + if (fromCandidateCount != null) { + setValueByPath(toObject, ['candidateCount'], fromCandidateCount); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (fromMaxOutputTokens != null) { + setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens); + } + const fromStopSequences = getValueByPath(fromObject, [ + 'stopSequences', + ]); + if (fromStopSequences != null) { + setValueByPath(toObject, ['stopSequences'], fromStopSequences); + } + const fromResponseLogprobs = getValueByPath(fromObject, [ + 'responseLogprobs', + ]); + if (fromResponseLogprobs != null) { + setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs); + } + const fromLogprobs = getValueByPath(fromObject, ['logprobs']); + if (fromLogprobs != null) { + setValueByPath(toObject, ['logprobs'], fromLogprobs); + } + const fromPresencePenalty = getValueByPath(fromObject, [ + 'presencePenalty', + ]); + if (fromPresencePenalty != null) { + setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty); + } + const fromFrequencyPenalty = getValueByPath(fromObject, [ + 'frequencyPenalty', + ]); + if (fromFrequencyPenalty != null) { + setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (fromSeed != null) { + setValueByPath(toObject, ['seed'], fromSeed); + } + const fromResponseMimeType = getValueByPath(fromObject, [ + 'responseMimeType', + ]); + if (fromResponseMimeType != null) { + setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType); + } + const fromResponseSchema = getValueByPath(fromObject, [ + 'responseSchema', + ]); + if (fromResponseSchema != null) { + setValueByPath(toObject, ['responseSchema'], tSchema(fromResponseSchema)); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + if (getValueByPath(fromObject, ['routingConfig']) !== undefined) { + throw new Error('routingConfig parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['modelSelectionConfig']) !== undefined) { + throw new Error('modelSelectionConfig parameter is not supported in Gemini API.'); + } + const fromSafetySettings = getValueByPath(fromObject, [ + 'safetySettings', + ]); + if (parentObject !== undefined && fromSafetySettings != null) { + let transformedList = fromSafetySettings; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return safetySettingToMldev(item); + }); + } + setValueByPath(parentObject, ['safetySettings'], transformedList); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = tTools(fromTools); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToMldev$1(tTool(item)); + }); + } + setValueByPath(parentObject, ['tools'], transformedList); + } + const fromToolConfig = getValueByPath(fromObject, ['toolConfig']); + if (parentObject !== undefined && fromToolConfig != null) { + setValueByPath(parentObject, ['toolConfig'], toolConfigToMldev(fromToolConfig)); + } + if (getValueByPath(fromObject, ['labels']) !== undefined) { + throw new Error('labels parameter is not supported in Gemini API.'); + } + const fromCachedContent = getValueByPath(fromObject, [ + 'cachedContent', + ]); + if (parentObject !== undefined && fromCachedContent != null) { + setValueByPath(parentObject, ['cachedContent'], tCachedContentName(apiClient, fromCachedContent)); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (fromResponseModalities != null) { + setValueByPath(toObject, ['responseModalities'], fromResponseModalities); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (fromSpeechConfig != null) { + setValueByPath(toObject, ['speechConfig'], tSpeechConfig(fromSpeechConfig)); + } + if (getValueByPath(fromObject, ['audioTimestamp']) !== undefined) { + throw new Error('audioTimestamp parameter is not supported in Gemini API.'); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (fromThinkingConfig != null) { + setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig); + } + const fromImageConfig = getValueByPath(fromObject, ['imageConfig']); + if (fromImageConfig != null) { + setValueByPath(toObject, ['imageConfig'], imageConfigToMldev(fromImageConfig)); + } + const fromEnableEnhancedCivicAnswers = getValueByPath(fromObject, [ + 'enableEnhancedCivicAnswers', + ]); + if (fromEnableEnhancedCivicAnswers != null) { + setValueByPath(toObject, ['enableEnhancedCivicAnswers'], fromEnableEnhancedCivicAnswers); + } + if (getValueByPath(fromObject, ['modelArmorConfig']) !== undefined) { + throw new Error('modelArmorConfig parameter is not supported in Gemini API.'); + } + return toObject; +} +function generateContentConfigToVertex(apiClient, fromObject, parentObject, rootObject) { + const toObject = {}; + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['systemInstruction'], tContent(fromSystemInstruction)); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (fromTemperature != null) { + setValueByPath(toObject, ['temperature'], fromTemperature); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (fromTopP != null) { + setValueByPath(toObject, ['topP'], fromTopP); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (fromTopK != null) { + setValueByPath(toObject, ['topK'], fromTopK); + } + const fromCandidateCount = getValueByPath(fromObject, [ + 'candidateCount', + ]); + if (fromCandidateCount != null) { + setValueByPath(toObject, ['candidateCount'], fromCandidateCount); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (fromMaxOutputTokens != null) { + setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens); + } + const fromStopSequences = getValueByPath(fromObject, [ + 'stopSequences', + ]); + if (fromStopSequences != null) { + setValueByPath(toObject, ['stopSequences'], fromStopSequences); + } + const fromResponseLogprobs = getValueByPath(fromObject, [ + 'responseLogprobs', + ]); + if (fromResponseLogprobs != null) { + setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs); + } + const fromLogprobs = getValueByPath(fromObject, ['logprobs']); + if (fromLogprobs != null) { + setValueByPath(toObject, ['logprobs'], fromLogprobs); + } + const fromPresencePenalty = getValueByPath(fromObject, [ + 'presencePenalty', + ]); + if (fromPresencePenalty != null) { + setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty); + } + const fromFrequencyPenalty = getValueByPath(fromObject, [ + 'frequencyPenalty', + ]); + if (fromFrequencyPenalty != null) { + setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (fromSeed != null) { + setValueByPath(toObject, ['seed'], fromSeed); + } + const fromResponseMimeType = getValueByPath(fromObject, [ + 'responseMimeType', + ]); + if (fromResponseMimeType != null) { + setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType); + } + const fromResponseSchema = getValueByPath(fromObject, [ + 'responseSchema', + ]); + if (fromResponseSchema != null) { + setValueByPath(toObject, ['responseSchema'], tSchema(fromResponseSchema)); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + const fromRoutingConfig = getValueByPath(fromObject, [ + 'routingConfig', + ]); + if (fromRoutingConfig != null) { + setValueByPath(toObject, ['routingConfig'], fromRoutingConfig); + } + const fromModelSelectionConfig = getValueByPath(fromObject, [ + 'modelSelectionConfig', + ]); + if (fromModelSelectionConfig != null) { + setValueByPath(toObject, ['modelConfig'], fromModelSelectionConfig); + } + const fromSafetySettings = getValueByPath(fromObject, [ + 'safetySettings', + ]); + if (parentObject !== undefined && fromSafetySettings != null) { + let transformedList = fromSafetySettings; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(parentObject, ['safetySettings'], transformedList); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = tTools(fromTools); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToVertex(tTool(item)); + }); + } + setValueByPath(parentObject, ['tools'], transformedList); + } + const fromToolConfig = getValueByPath(fromObject, ['toolConfig']); + if (parentObject !== undefined && fromToolConfig != null) { + setValueByPath(parentObject, ['toolConfig'], fromToolConfig); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (parentObject !== undefined && fromLabels != null) { + setValueByPath(parentObject, ['labels'], fromLabels); + } + const fromCachedContent = getValueByPath(fromObject, [ + 'cachedContent', + ]); + if (parentObject !== undefined && fromCachedContent != null) { + setValueByPath(parentObject, ['cachedContent'], tCachedContentName(apiClient, fromCachedContent)); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (fromResponseModalities != null) { + setValueByPath(toObject, ['responseModalities'], fromResponseModalities); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (fromSpeechConfig != null) { + setValueByPath(toObject, ['speechConfig'], tSpeechConfig(fromSpeechConfig)); + } + const fromAudioTimestamp = getValueByPath(fromObject, [ + 'audioTimestamp', + ]); + if (fromAudioTimestamp != null) { + setValueByPath(toObject, ['audioTimestamp'], fromAudioTimestamp); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (fromThinkingConfig != null) { + setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig); + } + const fromImageConfig = getValueByPath(fromObject, ['imageConfig']); + if (fromImageConfig != null) { + setValueByPath(toObject, ['imageConfig'], imageConfigToVertex(fromImageConfig)); + } + if (getValueByPath(fromObject, ['enableEnhancedCivicAnswers']) !== + undefined) { + throw new Error('enableEnhancedCivicAnswers parameter is not supported in Vertex AI.'); + } + const fromModelArmorConfig = getValueByPath(fromObject, [ + 'modelArmorConfig', + ]); + if (parentObject !== undefined && fromModelArmorConfig != null) { + setValueByPath(parentObject, ['modelArmorConfig'], fromModelArmorConfig); + } + return toObject; +} +function generateContentParametersToMldev(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return contentToMldev$1(item); + }); + } + setValueByPath(toObject, ['contents'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['generationConfig'], generateContentConfigToMldev(apiClient, fromConfig, toObject)); + } + return toObject; +} +function generateContentParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['contents'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['generationConfig'], generateContentConfigToVertex(apiClient, fromConfig, toObject)); + } + return toObject; +} +function generateContentResponseFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromCandidates = getValueByPath(fromObject, ['candidates']); + if (fromCandidates != null) { + let transformedList = fromCandidates; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return candidateFromMldev(item); + }); + } + setValueByPath(toObject, ['candidates'], transformedList); + } + const fromModelVersion = getValueByPath(fromObject, ['modelVersion']); + if (fromModelVersion != null) { + setValueByPath(toObject, ['modelVersion'], fromModelVersion); + } + const fromPromptFeedback = getValueByPath(fromObject, [ + 'promptFeedback', + ]); + if (fromPromptFeedback != null) { + setValueByPath(toObject, ['promptFeedback'], fromPromptFeedback); + } + const fromResponseId = getValueByPath(fromObject, ['responseId']); + if (fromResponseId != null) { + setValueByPath(toObject, ['responseId'], fromResponseId); + } + const fromUsageMetadata = getValueByPath(fromObject, [ + 'usageMetadata', + ]); + if (fromUsageMetadata != null) { + setValueByPath(toObject, ['usageMetadata'], fromUsageMetadata); + } + return toObject; +} +function generateContentResponseFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromCandidates = getValueByPath(fromObject, ['candidates']); + if (fromCandidates != null) { + let transformedList = fromCandidates; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['candidates'], transformedList); + } + const fromCreateTime = getValueByPath(fromObject, ['createTime']); + if (fromCreateTime != null) { + setValueByPath(toObject, ['createTime'], fromCreateTime); + } + const fromModelVersion = getValueByPath(fromObject, ['modelVersion']); + if (fromModelVersion != null) { + setValueByPath(toObject, ['modelVersion'], fromModelVersion); + } + const fromPromptFeedback = getValueByPath(fromObject, [ + 'promptFeedback', + ]); + if (fromPromptFeedback != null) { + setValueByPath(toObject, ['promptFeedback'], fromPromptFeedback); + } + const fromResponseId = getValueByPath(fromObject, ['responseId']); + if (fromResponseId != null) { + setValueByPath(toObject, ['responseId'], fromResponseId); + } + const fromUsageMetadata = getValueByPath(fromObject, [ + 'usageMetadata', + ]); + if (fromUsageMetadata != null) { + setValueByPath(toObject, ['usageMetadata'], fromUsageMetadata); + } + return toObject; +} +function generateImagesConfigToMldev(fromObject, parentObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['outputGcsUri']) !== undefined) { + throw new Error('outputGcsUri parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['negativePrompt']) !== undefined) { + throw new Error('negativePrompt parameter is not supported in Gemini API.'); + } + const fromNumberOfImages = getValueByPath(fromObject, [ + 'numberOfImages', + ]); + if (parentObject !== undefined && fromNumberOfImages != null) { + setValueByPath(parentObject, ['parameters', 'sampleCount'], fromNumberOfImages); + } + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (parentObject !== undefined && fromAspectRatio != null) { + setValueByPath(parentObject, ['parameters', 'aspectRatio'], fromAspectRatio); + } + const fromGuidanceScale = getValueByPath(fromObject, [ + 'guidanceScale', + ]); + if (parentObject !== undefined && fromGuidanceScale != null) { + setValueByPath(parentObject, ['parameters', 'guidanceScale'], fromGuidanceScale); + } + if (getValueByPath(fromObject, ['seed']) !== undefined) { + throw new Error('seed parameter is not supported in Gemini API.'); + } + const fromSafetyFilterLevel = getValueByPath(fromObject, [ + 'safetyFilterLevel', + ]); + if (parentObject !== undefined && fromSafetyFilterLevel != null) { + setValueByPath(parentObject, ['parameters', 'safetySetting'], fromSafetyFilterLevel); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (parentObject !== undefined && fromPersonGeneration != null) { + setValueByPath(parentObject, ['parameters', 'personGeneration'], fromPersonGeneration); + } + const fromIncludeSafetyAttributes = getValueByPath(fromObject, [ + 'includeSafetyAttributes', + ]); + if (parentObject !== undefined && fromIncludeSafetyAttributes != null) { + setValueByPath(parentObject, ['parameters', 'includeSafetyAttributes'], fromIncludeSafetyAttributes); + } + const fromIncludeRaiReason = getValueByPath(fromObject, [ + 'includeRaiReason', + ]); + if (parentObject !== undefined && fromIncludeRaiReason != null) { + setValueByPath(parentObject, ['parameters', 'includeRaiReason'], fromIncludeRaiReason); + } + const fromLanguage = getValueByPath(fromObject, ['language']); + if (parentObject !== undefined && fromLanguage != null) { + setValueByPath(parentObject, ['parameters', 'language'], fromLanguage); + } + const fromOutputMimeType = getValueByPath(fromObject, [ + 'outputMimeType', + ]); + if (parentObject !== undefined && fromOutputMimeType != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'mimeType'], fromOutputMimeType); + } + const fromOutputCompressionQuality = getValueByPath(fromObject, [ + 'outputCompressionQuality', + ]); + if (parentObject !== undefined && fromOutputCompressionQuality != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'compressionQuality'], fromOutputCompressionQuality); + } + if (getValueByPath(fromObject, ['addWatermark']) !== undefined) { + throw new Error('addWatermark parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['labels']) !== undefined) { + throw new Error('labels parameter is not supported in Gemini API.'); + } + const fromImageSize = getValueByPath(fromObject, ['imageSize']); + if (parentObject !== undefined && fromImageSize != null) { + setValueByPath(parentObject, ['parameters', 'sampleImageSize'], fromImageSize); + } + if (getValueByPath(fromObject, ['enhancePrompt']) !== undefined) { + throw new Error('enhancePrompt parameter is not supported in Gemini API.'); + } + return toObject; +} +function generateImagesConfigToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromOutputGcsUri = getValueByPath(fromObject, ['outputGcsUri']); + if (parentObject !== undefined && fromOutputGcsUri != null) { + setValueByPath(parentObject, ['parameters', 'storageUri'], fromOutputGcsUri); + } + const fromNegativePrompt = getValueByPath(fromObject, [ + 'negativePrompt', + ]); + if (parentObject !== undefined && fromNegativePrompt != null) { + setValueByPath(parentObject, ['parameters', 'negativePrompt'], fromNegativePrompt); + } + const fromNumberOfImages = getValueByPath(fromObject, [ + 'numberOfImages', + ]); + if (parentObject !== undefined && fromNumberOfImages != null) { + setValueByPath(parentObject, ['parameters', 'sampleCount'], fromNumberOfImages); + } + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (parentObject !== undefined && fromAspectRatio != null) { + setValueByPath(parentObject, ['parameters', 'aspectRatio'], fromAspectRatio); + } + const fromGuidanceScale = getValueByPath(fromObject, [ + 'guidanceScale', + ]); + if (parentObject !== undefined && fromGuidanceScale != null) { + setValueByPath(parentObject, ['parameters', 'guidanceScale'], fromGuidanceScale); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (parentObject !== undefined && fromSeed != null) { + setValueByPath(parentObject, ['parameters', 'seed'], fromSeed); + } + const fromSafetyFilterLevel = getValueByPath(fromObject, [ + 'safetyFilterLevel', + ]); + if (parentObject !== undefined && fromSafetyFilterLevel != null) { + setValueByPath(parentObject, ['parameters', 'safetySetting'], fromSafetyFilterLevel); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (parentObject !== undefined && fromPersonGeneration != null) { + setValueByPath(parentObject, ['parameters', 'personGeneration'], fromPersonGeneration); + } + const fromIncludeSafetyAttributes = getValueByPath(fromObject, [ + 'includeSafetyAttributes', + ]); + if (parentObject !== undefined && fromIncludeSafetyAttributes != null) { + setValueByPath(parentObject, ['parameters', 'includeSafetyAttributes'], fromIncludeSafetyAttributes); + } + const fromIncludeRaiReason = getValueByPath(fromObject, [ + 'includeRaiReason', + ]); + if (parentObject !== undefined && fromIncludeRaiReason != null) { + setValueByPath(parentObject, ['parameters', 'includeRaiReason'], fromIncludeRaiReason); + } + const fromLanguage = getValueByPath(fromObject, ['language']); + if (parentObject !== undefined && fromLanguage != null) { + setValueByPath(parentObject, ['parameters', 'language'], fromLanguage); + } + const fromOutputMimeType = getValueByPath(fromObject, [ + 'outputMimeType', + ]); + if (parentObject !== undefined && fromOutputMimeType != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'mimeType'], fromOutputMimeType); + } + const fromOutputCompressionQuality = getValueByPath(fromObject, [ + 'outputCompressionQuality', + ]); + if (parentObject !== undefined && fromOutputCompressionQuality != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'compressionQuality'], fromOutputCompressionQuality); + } + const fromAddWatermark = getValueByPath(fromObject, ['addWatermark']); + if (parentObject !== undefined && fromAddWatermark != null) { + setValueByPath(parentObject, ['parameters', 'addWatermark'], fromAddWatermark); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (parentObject !== undefined && fromLabels != null) { + setValueByPath(parentObject, ['labels'], fromLabels); + } + const fromImageSize = getValueByPath(fromObject, ['imageSize']); + if (parentObject !== undefined && fromImageSize != null) { + setValueByPath(parentObject, ['parameters', 'sampleImageSize'], fromImageSize); + } + const fromEnhancePrompt = getValueByPath(fromObject, [ + 'enhancePrompt', + ]); + if (parentObject !== undefined && fromEnhancePrompt != null) { + setValueByPath(parentObject, ['parameters', 'enhancePrompt'], fromEnhancePrompt); + } + return toObject; +} +function generateImagesParametersToMldev(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (fromPrompt != null) { + setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + generateImagesConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function generateImagesParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (fromPrompt != null) { + setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + generateImagesConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function generateImagesResponseFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromGeneratedImages = getValueByPath(fromObject, [ + 'predictions', + ]); + if (fromGeneratedImages != null) { + let transformedList = fromGeneratedImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedImageFromMldev(item); + }); + } + setValueByPath(toObject, ['generatedImages'], transformedList); + } + const fromPositivePromptSafetyAttributes = getValueByPath(fromObject, [ + 'positivePromptSafetyAttributes', + ]); + if (fromPositivePromptSafetyAttributes != null) { + setValueByPath(toObject, ['positivePromptSafetyAttributes'], safetyAttributesFromMldev(fromPositivePromptSafetyAttributes)); + } + return toObject; +} +function generateImagesResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromGeneratedImages = getValueByPath(fromObject, [ + 'predictions', + ]); + if (fromGeneratedImages != null) { + let transformedList = fromGeneratedImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedImageFromVertex(item); + }); + } + setValueByPath(toObject, ['generatedImages'], transformedList); + } + const fromPositivePromptSafetyAttributes = getValueByPath(fromObject, [ + 'positivePromptSafetyAttributes', + ]); + if (fromPositivePromptSafetyAttributes != null) { + setValueByPath(toObject, ['positivePromptSafetyAttributes'], safetyAttributesFromVertex(fromPositivePromptSafetyAttributes)); + } + return toObject; +} +function generateVideosConfigToMldev(fromObject, parentObject, rootObject) { + const toObject = {}; + const fromNumberOfVideos = getValueByPath(fromObject, [ + 'numberOfVideos', + ]); + if (parentObject !== undefined && fromNumberOfVideos != null) { + setValueByPath(parentObject, ['parameters', 'sampleCount'], fromNumberOfVideos); + } + if (getValueByPath(fromObject, ['outputGcsUri']) !== undefined) { + throw new Error('outputGcsUri parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['fps']) !== undefined) { + throw new Error('fps parameter is not supported in Gemini API.'); + } + const fromDurationSeconds = getValueByPath(fromObject, [ + 'durationSeconds', + ]); + if (parentObject !== undefined && fromDurationSeconds != null) { + setValueByPath(parentObject, ['parameters', 'durationSeconds'], fromDurationSeconds); + } + if (getValueByPath(fromObject, ['seed']) !== undefined) { + throw new Error('seed parameter is not supported in Gemini API.'); + } + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (parentObject !== undefined && fromAspectRatio != null) { + setValueByPath(parentObject, ['parameters', 'aspectRatio'], fromAspectRatio); + } + const fromResolution = getValueByPath(fromObject, ['resolution']); + if (parentObject !== undefined && fromResolution != null) { + setValueByPath(parentObject, ['parameters', 'resolution'], fromResolution); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (parentObject !== undefined && fromPersonGeneration != null) { + setValueByPath(parentObject, ['parameters', 'personGeneration'], fromPersonGeneration); + } + if (getValueByPath(fromObject, ['pubsubTopic']) !== undefined) { + throw new Error('pubsubTopic parameter is not supported in Gemini API.'); + } + const fromNegativePrompt = getValueByPath(fromObject, [ + 'negativePrompt', + ]); + if (parentObject !== undefined && fromNegativePrompt != null) { + setValueByPath(parentObject, ['parameters', 'negativePrompt'], fromNegativePrompt); + } + const fromEnhancePrompt = getValueByPath(fromObject, [ + 'enhancePrompt', + ]); + if (parentObject !== undefined && fromEnhancePrompt != null) { + setValueByPath(parentObject, ['parameters', 'enhancePrompt'], fromEnhancePrompt); + } + if (getValueByPath(fromObject, ['generateAudio']) !== undefined) { + throw new Error('generateAudio parameter is not supported in Gemini API.'); + } + const fromLastFrame = getValueByPath(fromObject, ['lastFrame']); + if (parentObject !== undefined && fromLastFrame != null) { + setValueByPath(parentObject, ['instances[0]', 'lastFrame'], imageToMldev(fromLastFrame)); + } + const fromReferenceImages = getValueByPath(fromObject, [ + 'referenceImages', + ]); + if (parentObject !== undefined && fromReferenceImages != null) { + let transformedList = fromReferenceImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return videoGenerationReferenceImageToMldev(item); + }); + } + setValueByPath(parentObject, ['instances[0]', 'referenceImages'], transformedList); + } + if (getValueByPath(fromObject, ['mask']) !== undefined) { + throw new Error('mask parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['compressionQuality']) !== undefined) { + throw new Error('compressionQuality parameter is not supported in Gemini API.'); + } + return toObject; +} +function generateVideosConfigToVertex(fromObject, parentObject, rootObject) { + const toObject = {}; + const fromNumberOfVideos = getValueByPath(fromObject, [ + 'numberOfVideos', + ]); + if (parentObject !== undefined && fromNumberOfVideos != null) { + setValueByPath(parentObject, ['parameters', 'sampleCount'], fromNumberOfVideos); + } + const fromOutputGcsUri = getValueByPath(fromObject, ['outputGcsUri']); + if (parentObject !== undefined && fromOutputGcsUri != null) { + setValueByPath(parentObject, ['parameters', 'storageUri'], fromOutputGcsUri); + } + const fromFps = getValueByPath(fromObject, ['fps']); + if (parentObject !== undefined && fromFps != null) { + setValueByPath(parentObject, ['parameters', 'fps'], fromFps); + } + const fromDurationSeconds = getValueByPath(fromObject, [ + 'durationSeconds', + ]); + if (parentObject !== undefined && fromDurationSeconds != null) { + setValueByPath(parentObject, ['parameters', 'durationSeconds'], fromDurationSeconds); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (parentObject !== undefined && fromSeed != null) { + setValueByPath(parentObject, ['parameters', 'seed'], fromSeed); + } + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (parentObject !== undefined && fromAspectRatio != null) { + setValueByPath(parentObject, ['parameters', 'aspectRatio'], fromAspectRatio); + } + const fromResolution = getValueByPath(fromObject, ['resolution']); + if (parentObject !== undefined && fromResolution != null) { + setValueByPath(parentObject, ['parameters', 'resolution'], fromResolution); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (parentObject !== undefined && fromPersonGeneration != null) { + setValueByPath(parentObject, ['parameters', 'personGeneration'], fromPersonGeneration); + } + const fromPubsubTopic = getValueByPath(fromObject, ['pubsubTopic']); + if (parentObject !== undefined && fromPubsubTopic != null) { + setValueByPath(parentObject, ['parameters', 'pubsubTopic'], fromPubsubTopic); + } + const fromNegativePrompt = getValueByPath(fromObject, [ + 'negativePrompt', + ]); + if (parentObject !== undefined && fromNegativePrompt != null) { + setValueByPath(parentObject, ['parameters', 'negativePrompt'], fromNegativePrompt); + } + const fromEnhancePrompt = getValueByPath(fromObject, [ + 'enhancePrompt', + ]); + if (parentObject !== undefined && fromEnhancePrompt != null) { + setValueByPath(parentObject, ['parameters', 'enhancePrompt'], fromEnhancePrompt); + } + const fromGenerateAudio = getValueByPath(fromObject, [ + 'generateAudio', + ]); + if (parentObject !== undefined && fromGenerateAudio != null) { + setValueByPath(parentObject, ['parameters', 'generateAudio'], fromGenerateAudio); + } + const fromLastFrame = getValueByPath(fromObject, ['lastFrame']); + if (parentObject !== undefined && fromLastFrame != null) { + setValueByPath(parentObject, ['instances[0]', 'lastFrame'], imageToVertex(fromLastFrame)); + } + const fromReferenceImages = getValueByPath(fromObject, [ + 'referenceImages', + ]); + if (parentObject !== undefined && fromReferenceImages != null) { + let transformedList = fromReferenceImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return videoGenerationReferenceImageToVertex(item); + }); + } + setValueByPath(parentObject, ['instances[0]', 'referenceImages'], transformedList); + } + const fromMask = getValueByPath(fromObject, ['mask']); + if (parentObject !== undefined && fromMask != null) { + setValueByPath(parentObject, ['instances[0]', 'mask'], videoGenerationMaskToVertex(fromMask)); + } + const fromCompressionQuality = getValueByPath(fromObject, [ + 'compressionQuality', + ]); + if (parentObject !== undefined && fromCompressionQuality != null) { + setValueByPath(parentObject, ['parameters', 'compressionQuality'], fromCompressionQuality); + } + return toObject; +} +function generateVideosOperationFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromResponse = getValueByPath(fromObject, [ + 'response', + 'generateVideoResponse', + ]); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], generateVideosResponseFromMldev(fromResponse)); + } + return toObject; +} +function generateVideosOperationFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], generateVideosResponseFromVertex(fromResponse)); + } + return toObject; +} +function generateVideosParametersToMldev(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (fromPrompt != null) { + setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromImage = getValueByPath(fromObject, ['image']); + if (fromImage != null) { + setValueByPath(toObject, ['instances[0]', 'image'], imageToMldev(fromImage)); + } + const fromVideo = getValueByPath(fromObject, ['video']); + if (fromVideo != null) { + setValueByPath(toObject, ['instances[0]', 'video'], videoToMldev(fromVideo)); + } + const fromSource = getValueByPath(fromObject, ['source']); + if (fromSource != null) { + generateVideosSourceToMldev(fromSource, toObject); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + generateVideosConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function generateVideosParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (fromPrompt != null) { + setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromImage = getValueByPath(fromObject, ['image']); + if (fromImage != null) { + setValueByPath(toObject, ['instances[0]', 'image'], imageToVertex(fromImage)); + } + const fromVideo = getValueByPath(fromObject, ['video']); + if (fromVideo != null) { + setValueByPath(toObject, ['instances[0]', 'video'], videoToVertex(fromVideo)); + } + const fromSource = getValueByPath(fromObject, ['source']); + if (fromSource != null) { + generateVideosSourceToVertex(fromSource, toObject); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + generateVideosConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function generateVideosResponseFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromGeneratedVideos = getValueByPath(fromObject, [ + 'generatedSamples', + ]); + if (fromGeneratedVideos != null) { + let transformedList = fromGeneratedVideos; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedVideoFromMldev(item); + }); + } + setValueByPath(toObject, ['generatedVideos'], transformedList); + } + const fromRaiMediaFilteredCount = getValueByPath(fromObject, [ + 'raiMediaFilteredCount', + ]); + if (fromRaiMediaFilteredCount != null) { + setValueByPath(toObject, ['raiMediaFilteredCount'], fromRaiMediaFilteredCount); + } + const fromRaiMediaFilteredReasons = getValueByPath(fromObject, [ + 'raiMediaFilteredReasons', + ]); + if (fromRaiMediaFilteredReasons != null) { + setValueByPath(toObject, ['raiMediaFilteredReasons'], fromRaiMediaFilteredReasons); + } + return toObject; +} +function generateVideosResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromGeneratedVideos = getValueByPath(fromObject, ['videos']); + if (fromGeneratedVideos != null) { + let transformedList = fromGeneratedVideos; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedVideoFromVertex(item); + }); + } + setValueByPath(toObject, ['generatedVideos'], transformedList); + } + const fromRaiMediaFilteredCount = getValueByPath(fromObject, [ + 'raiMediaFilteredCount', + ]); + if (fromRaiMediaFilteredCount != null) { + setValueByPath(toObject, ['raiMediaFilteredCount'], fromRaiMediaFilteredCount); + } + const fromRaiMediaFilteredReasons = getValueByPath(fromObject, [ + 'raiMediaFilteredReasons', + ]); + if (fromRaiMediaFilteredReasons != null) { + setValueByPath(toObject, ['raiMediaFilteredReasons'], fromRaiMediaFilteredReasons); + } + return toObject; +} +function generateVideosSourceToMldev(fromObject, parentObject, rootObject) { + const toObject = {}; + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (parentObject !== undefined && fromPrompt != null) { + setValueByPath(parentObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromImage = getValueByPath(fromObject, ['image']); + if (parentObject !== undefined && fromImage != null) { + setValueByPath(parentObject, ['instances[0]', 'image'], imageToMldev(fromImage)); + } + const fromVideo = getValueByPath(fromObject, ['video']); + if (parentObject !== undefined && fromVideo != null) { + setValueByPath(parentObject, ['instances[0]', 'video'], videoToMldev(fromVideo)); + } + return toObject; +} +function generateVideosSourceToVertex(fromObject, parentObject, rootObject) { + const toObject = {}; + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (parentObject !== undefined && fromPrompt != null) { + setValueByPath(parentObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromImage = getValueByPath(fromObject, ['image']); + if (parentObject !== undefined && fromImage != null) { + setValueByPath(parentObject, ['instances[0]', 'image'], imageToVertex(fromImage)); + } + const fromVideo = getValueByPath(fromObject, ['video']); + if (parentObject !== undefined && fromVideo != null) { + setValueByPath(parentObject, ['instances[0]', 'video'], videoToVertex(fromVideo)); + } + return toObject; +} +function generatedImageFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromImage = getValueByPath(fromObject, ['_self']); + if (fromImage != null) { + setValueByPath(toObject, ['image'], imageFromMldev(fromImage)); + } + const fromRaiFilteredReason = getValueByPath(fromObject, [ + 'raiFilteredReason', + ]); + if (fromRaiFilteredReason != null) { + setValueByPath(toObject, ['raiFilteredReason'], fromRaiFilteredReason); + } + const fromSafetyAttributes = getValueByPath(fromObject, ['_self']); + if (fromSafetyAttributes != null) { + setValueByPath(toObject, ['safetyAttributes'], safetyAttributesFromMldev(fromSafetyAttributes)); + } + return toObject; +} +function generatedImageFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromImage = getValueByPath(fromObject, ['_self']); + if (fromImage != null) { + setValueByPath(toObject, ['image'], imageFromVertex(fromImage)); + } + const fromRaiFilteredReason = getValueByPath(fromObject, [ + 'raiFilteredReason', + ]); + if (fromRaiFilteredReason != null) { + setValueByPath(toObject, ['raiFilteredReason'], fromRaiFilteredReason); + } + const fromSafetyAttributes = getValueByPath(fromObject, ['_self']); + if (fromSafetyAttributes != null) { + setValueByPath(toObject, ['safetyAttributes'], safetyAttributesFromVertex(fromSafetyAttributes)); + } + const fromEnhancedPrompt = getValueByPath(fromObject, ['prompt']); + if (fromEnhancedPrompt != null) { + setValueByPath(toObject, ['enhancedPrompt'], fromEnhancedPrompt); + } + return toObject; +} +function generatedImageMaskFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromMask = getValueByPath(fromObject, ['_self']); + if (fromMask != null) { + setValueByPath(toObject, ['mask'], imageFromVertex(fromMask)); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (fromLabels != null) { + let transformedList = fromLabels; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['labels'], transformedList); + } + return toObject; +} +function generatedVideoFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromVideo = getValueByPath(fromObject, ['video']); + if (fromVideo != null) { + setValueByPath(toObject, ['video'], videoFromMldev(fromVideo)); + } + return toObject; +} +function generatedVideoFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromVideo = getValueByPath(fromObject, ['_self']); + if (fromVideo != null) { + setValueByPath(toObject, ['video'], videoFromVertex(fromVideo)); + } + return toObject; +} +function generationConfigToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromModelSelectionConfig = getValueByPath(fromObject, [ + 'modelSelectionConfig', + ]); + if (fromModelSelectionConfig != null) { + setValueByPath(toObject, ['modelConfig'], fromModelSelectionConfig); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + const fromAudioTimestamp = getValueByPath(fromObject, [ + 'audioTimestamp', + ]); + if (fromAudioTimestamp != null) { + setValueByPath(toObject, ['audioTimestamp'], fromAudioTimestamp); + } + const fromCandidateCount = getValueByPath(fromObject, [ + 'candidateCount', + ]); + if (fromCandidateCount != null) { + setValueByPath(toObject, ['candidateCount'], fromCandidateCount); + } + const fromEnableAffectiveDialog = getValueByPath(fromObject, [ + 'enableAffectiveDialog', + ]); + if (fromEnableAffectiveDialog != null) { + setValueByPath(toObject, ['enableAffectiveDialog'], fromEnableAffectiveDialog); + } + const fromFrequencyPenalty = getValueByPath(fromObject, [ + 'frequencyPenalty', + ]); + if (fromFrequencyPenalty != null) { + setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty); + } + const fromLogprobs = getValueByPath(fromObject, ['logprobs']); + if (fromLogprobs != null) { + setValueByPath(toObject, ['logprobs'], fromLogprobs); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (fromMaxOutputTokens != null) { + setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromPresencePenalty = getValueByPath(fromObject, [ + 'presencePenalty', + ]); + if (fromPresencePenalty != null) { + setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty); + } + const fromResponseLogprobs = getValueByPath(fromObject, [ + 'responseLogprobs', + ]); + if (fromResponseLogprobs != null) { + setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs); + } + const fromResponseMimeType = getValueByPath(fromObject, [ + 'responseMimeType', + ]); + if (fromResponseMimeType != null) { + setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (fromResponseModalities != null) { + setValueByPath(toObject, ['responseModalities'], fromResponseModalities); + } + const fromResponseSchema = getValueByPath(fromObject, [ + 'responseSchema', + ]); + if (fromResponseSchema != null) { + setValueByPath(toObject, ['responseSchema'], fromResponseSchema); + } + const fromRoutingConfig = getValueByPath(fromObject, [ + 'routingConfig', + ]); + if (fromRoutingConfig != null) { + setValueByPath(toObject, ['routingConfig'], fromRoutingConfig); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (fromSeed != null) { + setValueByPath(toObject, ['seed'], fromSeed); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (fromSpeechConfig != null) { + setValueByPath(toObject, ['speechConfig'], fromSpeechConfig); + } + const fromStopSequences = getValueByPath(fromObject, [ + 'stopSequences', + ]); + if (fromStopSequences != null) { + setValueByPath(toObject, ['stopSequences'], fromStopSequences); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (fromTemperature != null) { + setValueByPath(toObject, ['temperature'], fromTemperature); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (fromThinkingConfig != null) { + setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (fromTopK != null) { + setValueByPath(toObject, ['topK'], fromTopK); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (fromTopP != null) { + setValueByPath(toObject, ['topP'], fromTopP); + } + if (getValueByPath(fromObject, ['enableEnhancedCivicAnswers']) !== + undefined) { + throw new Error('enableEnhancedCivicAnswers parameter is not supported in Vertex AI.'); + } + return toObject; +} +function getModelParametersToMldev(apiClient, fromObject, _rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'name'], tModel(apiClient, fromModel)); + } + return toObject; +} +function getModelParametersToVertex(apiClient, fromObject, _rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'name'], tModel(apiClient, fromModel)); + } + return toObject; +} +function googleMapsToMldev$1(fromObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['authConfig']) !== undefined) { + throw new Error('authConfig parameter is not supported in Gemini API.'); + } + const fromEnableWidget = getValueByPath(fromObject, ['enableWidget']); + if (fromEnableWidget != null) { + setValueByPath(toObject, ['enableWidget'], fromEnableWidget); + } + return toObject; +} +function googleSearchToMldev$1(fromObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['excludeDomains']) !== undefined) { + throw new Error('excludeDomains parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['blockingConfidence']) !== undefined) { + throw new Error('blockingConfidence parameter is not supported in Gemini API.'); + } + const fromTimeRangeFilter = getValueByPath(fromObject, [ + 'timeRangeFilter', + ]); + if (fromTimeRangeFilter != null) { + setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter); + } + return toObject; +} +function imageConfigToMldev(fromObject, _rootObject) { + const toObject = {}; + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (fromAspectRatio != null) { + setValueByPath(toObject, ['aspectRatio'], fromAspectRatio); + } + const fromImageSize = getValueByPath(fromObject, ['imageSize']); + if (fromImageSize != null) { + setValueByPath(toObject, ['imageSize'], fromImageSize); + } + if (getValueByPath(fromObject, ['personGeneration']) !== undefined) { + throw new Error('personGeneration parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['outputMimeType']) !== undefined) { + throw new Error('outputMimeType parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['outputCompressionQuality']) !== + undefined) { + throw new Error('outputCompressionQuality parameter is not supported in Gemini API.'); + } + return toObject; +} +function imageConfigToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (fromAspectRatio != null) { + setValueByPath(toObject, ['aspectRatio'], fromAspectRatio); + } + const fromImageSize = getValueByPath(fromObject, ['imageSize']); + if (fromImageSize != null) { + setValueByPath(toObject, ['imageSize'], fromImageSize); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (fromPersonGeneration != null) { + setValueByPath(toObject, ['personGeneration'], fromPersonGeneration); + } + const fromOutputMimeType = getValueByPath(fromObject, [ + 'outputMimeType', + ]); + if (fromOutputMimeType != null) { + setValueByPath(toObject, ['imageOutputOptions', 'mimeType'], fromOutputMimeType); + } + const fromOutputCompressionQuality = getValueByPath(fromObject, [ + 'outputCompressionQuality', + ]); + if (fromOutputCompressionQuality != null) { + setValueByPath(toObject, ['imageOutputOptions', 'compressionQuality'], fromOutputCompressionQuality); + } + return toObject; +} +function imageFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromImageBytes = getValueByPath(fromObject, [ + 'bytesBase64Encoded', + ]); + if (fromImageBytes != null) { + setValueByPath(toObject, ['imageBytes'], tBytes(fromImageBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function imageFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (fromGcsUri != null) { + setValueByPath(toObject, ['gcsUri'], fromGcsUri); + } + const fromImageBytes = getValueByPath(fromObject, [ + 'bytesBase64Encoded', + ]); + if (fromImageBytes != null) { + setValueByPath(toObject, ['imageBytes'], tBytes(fromImageBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function imageToMldev(fromObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['gcsUri']) !== undefined) { + throw new Error('gcsUri parameter is not supported in Gemini API.'); + } + const fromImageBytes = getValueByPath(fromObject, ['imageBytes']); + if (fromImageBytes != null) { + setValueByPath(toObject, ['bytesBase64Encoded'], tBytes(fromImageBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function imageToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (fromGcsUri != null) { + setValueByPath(toObject, ['gcsUri'], fromGcsUri); + } + const fromImageBytes = getValueByPath(fromObject, ['imageBytes']); + if (fromImageBytes != null) { + setValueByPath(toObject, ['bytesBase64Encoded'], tBytes(fromImageBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function listModelsConfigToMldev(apiClient, fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + const fromFilter = getValueByPath(fromObject, ['filter']); + if (parentObject !== undefined && fromFilter != null) { + setValueByPath(parentObject, ['_query', 'filter'], fromFilter); + } + const fromQueryBase = getValueByPath(fromObject, ['queryBase']); + if (parentObject !== undefined && fromQueryBase != null) { + setValueByPath(parentObject, ['_url', 'models_url'], tModelsUrl(apiClient, fromQueryBase)); + } + return toObject; +} +function listModelsConfigToVertex(apiClient, fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + const fromFilter = getValueByPath(fromObject, ['filter']); + if (parentObject !== undefined && fromFilter != null) { + setValueByPath(parentObject, ['_query', 'filter'], fromFilter); + } + const fromQueryBase = getValueByPath(fromObject, ['queryBase']); + if (parentObject !== undefined && fromQueryBase != null) { + setValueByPath(parentObject, ['_url', 'models_url'], tModelsUrl(apiClient, fromQueryBase)); + } + return toObject; +} +function listModelsParametersToMldev(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listModelsConfigToMldev(apiClient, fromConfig, toObject); + } + return toObject; +} +function listModelsParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listModelsConfigToVertex(apiClient, fromConfig, toObject); + } + return toObject; +} +function listModelsResponseFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromModels = getValueByPath(fromObject, ['_self']); + if (fromModels != null) { + let transformedList = tExtractModels(fromModels); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return modelFromMldev(item); + }); + } + setValueByPath(toObject, ['models'], transformedList); + } + return toObject; +} +function listModelsResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromModels = getValueByPath(fromObject, ['_self']); + if (fromModels != null) { + let transformedList = tExtractModels(fromModels); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return modelFromVertex(item); + }); + } + setValueByPath(toObject, ['models'], transformedList); + } + return toObject; +} +function maskReferenceConfigToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromMaskMode = getValueByPath(fromObject, ['maskMode']); + if (fromMaskMode != null) { + setValueByPath(toObject, ['maskMode'], fromMaskMode); + } + const fromSegmentationClasses = getValueByPath(fromObject, [ + 'segmentationClasses', + ]); + if (fromSegmentationClasses != null) { + setValueByPath(toObject, ['maskClasses'], fromSegmentationClasses); + } + const fromMaskDilation = getValueByPath(fromObject, ['maskDilation']); + if (fromMaskDilation != null) { + setValueByPath(toObject, ['dilation'], fromMaskDilation); + } + return toObject; +} +function modelFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (fromDisplayName != null) { + setValueByPath(toObject, ['displayName'], fromDisplayName); + } + const fromDescription = getValueByPath(fromObject, ['description']); + if (fromDescription != null) { + setValueByPath(toObject, ['description'], fromDescription); + } + const fromVersion = getValueByPath(fromObject, ['version']); + if (fromVersion != null) { + setValueByPath(toObject, ['version'], fromVersion); + } + const fromTunedModelInfo = getValueByPath(fromObject, ['_self']); + if (fromTunedModelInfo != null) { + setValueByPath(toObject, ['tunedModelInfo'], tunedModelInfoFromMldev(fromTunedModelInfo)); + } + const fromInputTokenLimit = getValueByPath(fromObject, [ + 'inputTokenLimit', + ]); + if (fromInputTokenLimit != null) { + setValueByPath(toObject, ['inputTokenLimit'], fromInputTokenLimit); + } + const fromOutputTokenLimit = getValueByPath(fromObject, [ + 'outputTokenLimit', + ]); + if (fromOutputTokenLimit != null) { + setValueByPath(toObject, ['outputTokenLimit'], fromOutputTokenLimit); + } + const fromSupportedActions = getValueByPath(fromObject, [ + 'supportedGenerationMethods', + ]); + if (fromSupportedActions != null) { + setValueByPath(toObject, ['supportedActions'], fromSupportedActions); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (fromTemperature != null) { + setValueByPath(toObject, ['temperature'], fromTemperature); + } + const fromMaxTemperature = getValueByPath(fromObject, [ + 'maxTemperature', + ]); + if (fromMaxTemperature != null) { + setValueByPath(toObject, ['maxTemperature'], fromMaxTemperature); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (fromTopP != null) { + setValueByPath(toObject, ['topP'], fromTopP); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (fromTopK != null) { + setValueByPath(toObject, ['topK'], fromTopK); + } + const fromThinking = getValueByPath(fromObject, ['thinking']); + if (fromThinking != null) { + setValueByPath(toObject, ['thinking'], fromThinking); + } + return toObject; +} +function modelFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (fromDisplayName != null) { + setValueByPath(toObject, ['displayName'], fromDisplayName); + } + const fromDescription = getValueByPath(fromObject, ['description']); + if (fromDescription != null) { + setValueByPath(toObject, ['description'], fromDescription); + } + const fromVersion = getValueByPath(fromObject, ['versionId']); + if (fromVersion != null) { + setValueByPath(toObject, ['version'], fromVersion); + } + const fromEndpoints = getValueByPath(fromObject, ['deployedModels']); + if (fromEndpoints != null) { + let transformedList = fromEndpoints; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return endpointFromVertex(item); + }); + } + setValueByPath(toObject, ['endpoints'], transformedList); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (fromLabels != null) { + setValueByPath(toObject, ['labels'], fromLabels); + } + const fromTunedModelInfo = getValueByPath(fromObject, ['_self']); + if (fromTunedModelInfo != null) { + setValueByPath(toObject, ['tunedModelInfo'], tunedModelInfoFromVertex(fromTunedModelInfo)); + } + const fromDefaultCheckpointId = getValueByPath(fromObject, [ + 'defaultCheckpointId', + ]); + if (fromDefaultCheckpointId != null) { + setValueByPath(toObject, ['defaultCheckpointId'], fromDefaultCheckpointId); + } + const fromCheckpoints = getValueByPath(fromObject, ['checkpoints']); + if (fromCheckpoints != null) { + let transformedList = fromCheckpoints; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['checkpoints'], transformedList); + } + return toObject; +} +function partToMldev$1(fromObject, rootObject) { + const toObject = {}; + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromCodeExecutionResult = getValueByPath(fromObject, [ + 'codeExecutionResult', + ]); + if (fromCodeExecutionResult != null) { + setValueByPath(toObject, ['codeExecutionResult'], fromCodeExecutionResult); + } + const fromExecutableCode = getValueByPath(fromObject, [ + 'executableCode', + ]); + if (fromExecutableCode != null) { + setValueByPath(toObject, ['executableCode'], fromExecutableCode); + } + const fromFileData = getValueByPath(fromObject, ['fileData']); + if (fromFileData != null) { + setValueByPath(toObject, ['fileData'], fileDataToMldev$1(fromFileData)); + } + const fromFunctionCall = getValueByPath(fromObject, ['functionCall']); + if (fromFunctionCall != null) { + setValueByPath(toObject, ['functionCall'], functionCallToMldev$1(fromFunctionCall)); + } + const fromFunctionResponse = getValueByPath(fromObject, [ + 'functionResponse', + ]); + if (fromFunctionResponse != null) { + setValueByPath(toObject, ['functionResponse'], fromFunctionResponse); + } + const fromInlineData = getValueByPath(fromObject, ['inlineData']); + if (fromInlineData != null) { + setValueByPath(toObject, ['inlineData'], blobToMldev$1(fromInlineData)); + } + const fromText = getValueByPath(fromObject, ['text']); + if (fromText != null) { + setValueByPath(toObject, ['text'], fromText); + } + const fromThought = getValueByPath(fromObject, ['thought']); + if (fromThought != null) { + setValueByPath(toObject, ['thought'], fromThought); + } + const fromThoughtSignature = getValueByPath(fromObject, [ + 'thoughtSignature', + ]); + if (fromThoughtSignature != null) { + setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature); + } + const fromVideoMetadata = getValueByPath(fromObject, [ + 'videoMetadata', + ]); + if (fromVideoMetadata != null) { + setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata); + } + return toObject; +} +function productImageToVertex(fromObject, rootObject) { + const toObject = {}; + const fromProductImage = getValueByPath(fromObject, ['productImage']); + if (fromProductImage != null) { + setValueByPath(toObject, ['image'], imageToVertex(fromProductImage)); + } + return toObject; +} +function recontextImageConfigToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromNumberOfImages = getValueByPath(fromObject, [ + 'numberOfImages', + ]); + if (parentObject !== undefined && fromNumberOfImages != null) { + setValueByPath(parentObject, ['parameters', 'sampleCount'], fromNumberOfImages); + } + const fromBaseSteps = getValueByPath(fromObject, ['baseSteps']); + if (parentObject !== undefined && fromBaseSteps != null) { + setValueByPath(parentObject, ['parameters', 'baseSteps'], fromBaseSteps); + } + const fromOutputGcsUri = getValueByPath(fromObject, ['outputGcsUri']); + if (parentObject !== undefined && fromOutputGcsUri != null) { + setValueByPath(parentObject, ['parameters', 'storageUri'], fromOutputGcsUri); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (parentObject !== undefined && fromSeed != null) { + setValueByPath(parentObject, ['parameters', 'seed'], fromSeed); + } + const fromSafetyFilterLevel = getValueByPath(fromObject, [ + 'safetyFilterLevel', + ]); + if (parentObject !== undefined && fromSafetyFilterLevel != null) { + setValueByPath(parentObject, ['parameters', 'safetySetting'], fromSafetyFilterLevel); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (parentObject !== undefined && fromPersonGeneration != null) { + setValueByPath(parentObject, ['parameters', 'personGeneration'], fromPersonGeneration); + } + const fromAddWatermark = getValueByPath(fromObject, ['addWatermark']); + if (parentObject !== undefined && fromAddWatermark != null) { + setValueByPath(parentObject, ['parameters', 'addWatermark'], fromAddWatermark); + } + const fromOutputMimeType = getValueByPath(fromObject, [ + 'outputMimeType', + ]); + if (parentObject !== undefined && fromOutputMimeType != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'mimeType'], fromOutputMimeType); + } + const fromOutputCompressionQuality = getValueByPath(fromObject, [ + 'outputCompressionQuality', + ]); + if (parentObject !== undefined && fromOutputCompressionQuality != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'compressionQuality'], fromOutputCompressionQuality); + } + const fromEnhancePrompt = getValueByPath(fromObject, [ + 'enhancePrompt', + ]); + if (parentObject !== undefined && fromEnhancePrompt != null) { + setValueByPath(parentObject, ['parameters', 'enhancePrompt'], fromEnhancePrompt); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (parentObject !== undefined && fromLabels != null) { + setValueByPath(parentObject, ['labels'], fromLabels); + } + return toObject; +} +function recontextImageParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromSource = getValueByPath(fromObject, ['source']); + if (fromSource != null) { + recontextImageSourceToVertex(fromSource, toObject); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + recontextImageConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function recontextImageResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromGeneratedImages = getValueByPath(fromObject, [ + 'predictions', + ]); + if (fromGeneratedImages != null) { + let transformedList = fromGeneratedImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedImageFromVertex(item); + }); + } + setValueByPath(toObject, ['generatedImages'], transformedList); + } + return toObject; +} +function recontextImageSourceToVertex(fromObject, parentObject, rootObject) { + const toObject = {}; + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (parentObject !== undefined && fromPrompt != null) { + setValueByPath(parentObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromPersonImage = getValueByPath(fromObject, ['personImage']); + if (parentObject !== undefined && fromPersonImage != null) { + setValueByPath(parentObject, ['instances[0]', 'personImage', 'image'], imageToVertex(fromPersonImage)); + } + const fromProductImages = getValueByPath(fromObject, [ + 'productImages', + ]); + if (parentObject !== undefined && fromProductImages != null) { + let transformedList = fromProductImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return productImageToVertex(item); + }); + } + setValueByPath(parentObject, ['instances[0]', 'productImages'], transformedList); + } + return toObject; +} +function referenceImageAPIInternalToVertex(fromObject, rootObject) { + const toObject = {}; + const fromReferenceImage = getValueByPath(fromObject, [ + 'referenceImage', + ]); + if (fromReferenceImage != null) { + setValueByPath(toObject, ['referenceImage'], imageToVertex(fromReferenceImage)); + } + const fromReferenceId = getValueByPath(fromObject, ['referenceId']); + if (fromReferenceId != null) { + setValueByPath(toObject, ['referenceId'], fromReferenceId); + } + const fromReferenceType = getValueByPath(fromObject, [ + 'referenceType', + ]); + if (fromReferenceType != null) { + setValueByPath(toObject, ['referenceType'], fromReferenceType); + } + const fromMaskImageConfig = getValueByPath(fromObject, [ + 'maskImageConfig', + ]); + if (fromMaskImageConfig != null) { + setValueByPath(toObject, ['maskImageConfig'], maskReferenceConfigToVertex(fromMaskImageConfig)); + } + const fromControlImageConfig = getValueByPath(fromObject, [ + 'controlImageConfig', + ]); + if (fromControlImageConfig != null) { + setValueByPath(toObject, ['controlImageConfig'], controlReferenceConfigToVertex(fromControlImageConfig)); + } + const fromStyleImageConfig = getValueByPath(fromObject, [ + 'styleImageConfig', + ]); + if (fromStyleImageConfig != null) { + setValueByPath(toObject, ['styleImageConfig'], fromStyleImageConfig); + } + const fromSubjectImageConfig = getValueByPath(fromObject, [ + 'subjectImageConfig', + ]); + if (fromSubjectImageConfig != null) { + setValueByPath(toObject, ['subjectImageConfig'], fromSubjectImageConfig); + } + return toObject; +} +function safetyAttributesFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromCategories = getValueByPath(fromObject, [ + 'safetyAttributes', + 'categories', + ]); + if (fromCategories != null) { + setValueByPath(toObject, ['categories'], fromCategories); + } + const fromScores = getValueByPath(fromObject, [ + 'safetyAttributes', + 'scores', + ]); + if (fromScores != null) { + setValueByPath(toObject, ['scores'], fromScores); + } + const fromContentType = getValueByPath(fromObject, ['contentType']); + if (fromContentType != null) { + setValueByPath(toObject, ['contentType'], fromContentType); + } + return toObject; +} +function safetyAttributesFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromCategories = getValueByPath(fromObject, [ + 'safetyAttributes', + 'categories', + ]); + if (fromCategories != null) { + setValueByPath(toObject, ['categories'], fromCategories); + } + const fromScores = getValueByPath(fromObject, [ + 'safetyAttributes', + 'scores', + ]); + if (fromScores != null) { + setValueByPath(toObject, ['scores'], fromScores); + } + const fromContentType = getValueByPath(fromObject, ['contentType']); + if (fromContentType != null) { + setValueByPath(toObject, ['contentType'], fromContentType); + } + return toObject; +} +function safetySettingToMldev(fromObject, _rootObject) { + const toObject = {}; + const fromCategory = getValueByPath(fromObject, ['category']); + if (fromCategory != null) { + setValueByPath(toObject, ['category'], fromCategory); + } + if (getValueByPath(fromObject, ['method']) !== undefined) { + throw new Error('method parameter is not supported in Gemini API.'); + } + const fromThreshold = getValueByPath(fromObject, ['threshold']); + if (fromThreshold != null) { + setValueByPath(toObject, ['threshold'], fromThreshold); + } + return toObject; +} +function scribbleImageToVertex(fromObject, rootObject) { + const toObject = {}; + const fromImage = getValueByPath(fromObject, ['image']); + if (fromImage != null) { + setValueByPath(toObject, ['image'], imageToVertex(fromImage)); + } + return toObject; +} +function segmentImageConfigToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromMode = getValueByPath(fromObject, ['mode']); + if (parentObject !== undefined && fromMode != null) { + setValueByPath(parentObject, ['parameters', 'mode'], fromMode); + } + const fromMaxPredictions = getValueByPath(fromObject, [ + 'maxPredictions', + ]); + if (parentObject !== undefined && fromMaxPredictions != null) { + setValueByPath(parentObject, ['parameters', 'maxPredictions'], fromMaxPredictions); + } + const fromConfidenceThreshold = getValueByPath(fromObject, [ + 'confidenceThreshold', + ]); + if (parentObject !== undefined && fromConfidenceThreshold != null) { + setValueByPath(parentObject, ['parameters', 'confidenceThreshold'], fromConfidenceThreshold); + } + const fromMaskDilation = getValueByPath(fromObject, ['maskDilation']); + if (parentObject !== undefined && fromMaskDilation != null) { + setValueByPath(parentObject, ['parameters', 'maskDilation'], fromMaskDilation); + } + const fromBinaryColorThreshold = getValueByPath(fromObject, [ + 'binaryColorThreshold', + ]); + if (parentObject !== undefined && fromBinaryColorThreshold != null) { + setValueByPath(parentObject, ['parameters', 'binaryColorThreshold'], fromBinaryColorThreshold); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (parentObject !== undefined && fromLabels != null) { + setValueByPath(parentObject, ['labels'], fromLabels); + } + return toObject; +} +function segmentImageParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromSource = getValueByPath(fromObject, ['source']); + if (fromSource != null) { + segmentImageSourceToVertex(fromSource, toObject); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + segmentImageConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function segmentImageResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromGeneratedMasks = getValueByPath(fromObject, ['predictions']); + if (fromGeneratedMasks != null) { + let transformedList = fromGeneratedMasks; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedImageMaskFromVertex(item); + }); + } + setValueByPath(toObject, ['generatedMasks'], transformedList); + } + return toObject; +} +function segmentImageSourceToVertex(fromObject, parentObject, rootObject) { + const toObject = {}; + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (parentObject !== undefined && fromPrompt != null) { + setValueByPath(parentObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromImage = getValueByPath(fromObject, ['image']); + if (parentObject !== undefined && fromImage != null) { + setValueByPath(parentObject, ['instances[0]', 'image'], imageToVertex(fromImage)); + } + const fromScribbleImage = getValueByPath(fromObject, [ + 'scribbleImage', + ]); + if (parentObject !== undefined && fromScribbleImage != null) { + setValueByPath(parentObject, ['instances[0]', 'scribble'], scribbleImageToVertex(fromScribbleImage)); + } + return toObject; +} +function toolConfigToMldev(fromObject, rootObject) { + const toObject = {}; + const fromRetrievalConfig = getValueByPath(fromObject, [ + 'retrievalConfig', + ]); + if (fromRetrievalConfig != null) { + setValueByPath(toObject, ['retrievalConfig'], fromRetrievalConfig); + } + const fromFunctionCallingConfig = getValueByPath(fromObject, [ + 'functionCallingConfig', + ]); + if (fromFunctionCallingConfig != null) { + setValueByPath(toObject, ['functionCallingConfig'], functionCallingConfigToMldev(fromFunctionCallingConfig)); + } + return toObject; +} +function toolToMldev$1(fromObject, rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['retrieval']) !== undefined) { + throw new Error('retrieval parameter is not supported in Gemini API.'); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + const fromFileSearch = getValueByPath(fromObject, ['fileSearch']); + if (fromFileSearch != null) { + setValueByPath(toObject, ['fileSearch'], fromFileSearch); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + if (getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined) { + throw new Error('enterpriseWebSearch parameter is not supported in Gemini API.'); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], googleMapsToMldev$1(fromGoogleMaps)); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], googleSearchToMldev$1(fromGoogleSearch)); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} +function toolToVertex(fromObject, rootObject) { + const toObject = {}; + const fromRetrieval = getValueByPath(fromObject, ['retrieval']); + if (fromRetrieval != null) { + setValueByPath(toObject, ['retrieval'], fromRetrieval); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + if (getValueByPath(fromObject, ['fileSearch']) !== undefined) { + throw new Error('fileSearch parameter is not supported in Vertex AI.'); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + const fromEnterpriseWebSearch = getValueByPath(fromObject, [ + 'enterpriseWebSearch', + ]); + if (fromEnterpriseWebSearch != null) { + setValueByPath(toObject, ['enterpriseWebSearch'], fromEnterpriseWebSearch); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return functionDeclarationToVertex(item); + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], fromGoogleMaps); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], fromGoogleSearch); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} +function tunedModelInfoFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromBaseModel = getValueByPath(fromObject, ['baseModel']); + if (fromBaseModel != null) { + setValueByPath(toObject, ['baseModel'], fromBaseModel); + } + const fromCreateTime = getValueByPath(fromObject, ['createTime']); + if (fromCreateTime != null) { + setValueByPath(toObject, ['createTime'], fromCreateTime); + } + const fromUpdateTime = getValueByPath(fromObject, ['updateTime']); + if (fromUpdateTime != null) { + setValueByPath(toObject, ['updateTime'], fromUpdateTime); + } + return toObject; +} +function tunedModelInfoFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromBaseModel = getValueByPath(fromObject, [ + 'labels', + 'google-vertex-llm-tuning-base-model-id', + ]); + if (fromBaseModel != null) { + setValueByPath(toObject, ['baseModel'], fromBaseModel); + } + const fromCreateTime = getValueByPath(fromObject, ['createTime']); + if (fromCreateTime != null) { + setValueByPath(toObject, ['createTime'], fromCreateTime); + } + const fromUpdateTime = getValueByPath(fromObject, ['updateTime']); + if (fromUpdateTime != null) { + setValueByPath(toObject, ['updateTime'], fromUpdateTime); + } + return toObject; +} +function updateModelConfigToMldev(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromDisplayName); + } + const fromDescription = getValueByPath(fromObject, ['description']); + if (parentObject !== undefined && fromDescription != null) { + setValueByPath(parentObject, ['description'], fromDescription); + } + const fromDefaultCheckpointId = getValueByPath(fromObject, [ + 'defaultCheckpointId', + ]); + if (parentObject !== undefined && fromDefaultCheckpointId != null) { + setValueByPath(parentObject, ['defaultCheckpointId'], fromDefaultCheckpointId); + } + return toObject; +} +function updateModelConfigToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromDisplayName); + } + const fromDescription = getValueByPath(fromObject, ['description']); + if (parentObject !== undefined && fromDescription != null) { + setValueByPath(parentObject, ['description'], fromDescription); + } + const fromDefaultCheckpointId = getValueByPath(fromObject, [ + 'defaultCheckpointId', + ]); + if (parentObject !== undefined && fromDefaultCheckpointId != null) { + setValueByPath(parentObject, ['defaultCheckpointId'], fromDefaultCheckpointId); + } + return toObject; +} +function updateModelParametersToMldev(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'name'], tModel(apiClient, fromModel)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + updateModelConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function updateModelParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + updateModelConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function upscaleImageAPIConfigInternalToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromOutputGcsUri = getValueByPath(fromObject, ['outputGcsUri']); + if (parentObject !== undefined && fromOutputGcsUri != null) { + setValueByPath(parentObject, ['parameters', 'storageUri'], fromOutputGcsUri); + } + const fromSafetyFilterLevel = getValueByPath(fromObject, [ + 'safetyFilterLevel', + ]); + if (parentObject !== undefined && fromSafetyFilterLevel != null) { + setValueByPath(parentObject, ['parameters', 'safetySetting'], fromSafetyFilterLevel); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (parentObject !== undefined && fromPersonGeneration != null) { + setValueByPath(parentObject, ['parameters', 'personGeneration'], fromPersonGeneration); + } + const fromIncludeRaiReason = getValueByPath(fromObject, [ + 'includeRaiReason', + ]); + if (parentObject !== undefined && fromIncludeRaiReason != null) { + setValueByPath(parentObject, ['parameters', 'includeRaiReason'], fromIncludeRaiReason); + } + const fromOutputMimeType = getValueByPath(fromObject, [ + 'outputMimeType', + ]); + if (parentObject !== undefined && fromOutputMimeType != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'mimeType'], fromOutputMimeType); + } + const fromOutputCompressionQuality = getValueByPath(fromObject, [ + 'outputCompressionQuality', + ]); + if (parentObject !== undefined && fromOutputCompressionQuality != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'compressionQuality'], fromOutputCompressionQuality); + } + const fromEnhanceInputImage = getValueByPath(fromObject, [ + 'enhanceInputImage', + ]); + if (parentObject !== undefined && fromEnhanceInputImage != null) { + setValueByPath(parentObject, ['parameters', 'upscaleConfig', 'enhanceInputImage'], fromEnhanceInputImage); + } + const fromImagePreservationFactor = getValueByPath(fromObject, [ + 'imagePreservationFactor', + ]); + if (parentObject !== undefined && fromImagePreservationFactor != null) { + setValueByPath(parentObject, ['parameters', 'upscaleConfig', 'imagePreservationFactor'], fromImagePreservationFactor); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (parentObject !== undefined && fromLabels != null) { + setValueByPath(parentObject, ['labels'], fromLabels); + } + const fromNumberOfImages = getValueByPath(fromObject, [ + 'numberOfImages', + ]); + if (parentObject !== undefined && fromNumberOfImages != null) { + setValueByPath(parentObject, ['parameters', 'sampleCount'], fromNumberOfImages); + } + const fromMode = getValueByPath(fromObject, ['mode']); + if (parentObject !== undefined && fromMode != null) { + setValueByPath(parentObject, ['parameters', 'mode'], fromMode); + } + return toObject; +} +function upscaleImageAPIParametersInternalToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromImage = getValueByPath(fromObject, ['image']); + if (fromImage != null) { + setValueByPath(toObject, ['instances[0]', 'image'], imageToVertex(fromImage)); + } + const fromUpscaleFactor = getValueByPath(fromObject, [ + 'upscaleFactor', + ]); + if (fromUpscaleFactor != null) { + setValueByPath(toObject, ['parameters', 'upscaleConfig', 'upscaleFactor'], fromUpscaleFactor); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + upscaleImageAPIConfigInternalToVertex(fromConfig, toObject); + } + return toObject; +} +function upscaleImageResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromGeneratedImages = getValueByPath(fromObject, [ + 'predictions', + ]); + if (fromGeneratedImages != null) { + let transformedList = fromGeneratedImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedImageFromVertex(item); + }); + } + setValueByPath(toObject, ['generatedImages'], transformedList); + } + return toObject; +} +function videoFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromUri = getValueByPath(fromObject, ['uri']); + if (fromUri != null) { + setValueByPath(toObject, ['uri'], fromUri); + } + const fromVideoBytes = getValueByPath(fromObject, ['encodedVideo']); + if (fromVideoBytes != null) { + setValueByPath(toObject, ['videoBytes'], tBytes(fromVideoBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['encoding']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function videoFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromUri = getValueByPath(fromObject, ['gcsUri']); + if (fromUri != null) { + setValueByPath(toObject, ['uri'], fromUri); + } + const fromVideoBytes = getValueByPath(fromObject, [ + 'bytesBase64Encoded', + ]); + if (fromVideoBytes != null) { + setValueByPath(toObject, ['videoBytes'], tBytes(fromVideoBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function videoGenerationMaskToVertex(fromObject, rootObject) { + const toObject = {}; + const fromImage = getValueByPath(fromObject, ['image']); + if (fromImage != null) { + setValueByPath(toObject, ['_self'], imageToVertex(fromImage)); + } + const fromMaskMode = getValueByPath(fromObject, ['maskMode']); + if (fromMaskMode != null) { + setValueByPath(toObject, ['maskMode'], fromMaskMode); + } + return toObject; +} +function videoGenerationReferenceImageToMldev(fromObject, rootObject) { + const toObject = {}; + const fromImage = getValueByPath(fromObject, ['image']); + if (fromImage != null) { + setValueByPath(toObject, ['image'], imageToMldev(fromImage)); + } + const fromReferenceType = getValueByPath(fromObject, [ + 'referenceType', + ]); + if (fromReferenceType != null) { + setValueByPath(toObject, ['referenceType'], fromReferenceType); + } + return toObject; +} +function videoGenerationReferenceImageToVertex(fromObject, rootObject) { + const toObject = {}; + const fromImage = getValueByPath(fromObject, ['image']); + if (fromImage != null) { + setValueByPath(toObject, ['image'], imageToVertex(fromImage)); + } + const fromReferenceType = getValueByPath(fromObject, [ + 'referenceType', + ]); + if (fromReferenceType != null) { + setValueByPath(toObject, ['referenceType'], fromReferenceType); + } + return toObject; +} +function videoToMldev(fromObject, _rootObject) { + const toObject = {}; + const fromUri = getValueByPath(fromObject, ['uri']); + if (fromUri != null) { + setValueByPath(toObject, ['uri'], fromUri); + } + const fromVideoBytes = getValueByPath(fromObject, ['videoBytes']); + if (fromVideoBytes != null) { + setValueByPath(toObject, ['encodedVideo'], tBytes(fromVideoBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['encoding'], fromMimeType); + } + return toObject; +} +function videoToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromUri = getValueByPath(fromObject, ['uri']); + if (fromUri != null) { + setValueByPath(toObject, ['gcsUri'], fromUri); + } + const fromVideoBytes = getValueByPath(fromObject, ['videoBytes']); + if (fromVideoBytes != null) { + setValueByPath(toObject, ['bytesBase64Encoded'], tBytes(fromVideoBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Code generated by the Google Gen AI SDK generator DO NOT EDIT. +function createFileSearchStoreConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromDisplayName); + } + return toObject; +} +function createFileSearchStoreParametersToMldev(fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createFileSearchStoreConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function deleteFileSearchStoreConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromForce = getValueByPath(fromObject, ['force']); + if (parentObject !== undefined && fromForce != null) { + setValueByPath(parentObject, ['_query', 'force'], fromForce); + } + return toObject; +} +function deleteFileSearchStoreParametersToMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + deleteFileSearchStoreConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function getFileSearchStoreParametersToMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + return toObject; +} +function importFileConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromCustomMetadata = getValueByPath(fromObject, [ + 'customMetadata', + ]); + if (parentObject !== undefined && fromCustomMetadata != null) { + let transformedList = fromCustomMetadata; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(parentObject, ['customMetadata'], transformedList); + } + const fromChunkingConfig = getValueByPath(fromObject, [ + 'chunkingConfig', + ]); + if (parentObject !== undefined && fromChunkingConfig != null) { + setValueByPath(parentObject, ['chunkingConfig'], fromChunkingConfig); + } + return toObject; +} +function importFileOperationFromMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], importFileResponseFromMldev(fromResponse)); + } + return toObject; +} +function importFileParametersToMldev(fromObject) { + const toObject = {}; + const fromFileSearchStoreName = getValueByPath(fromObject, [ + 'fileSearchStoreName', + ]); + if (fromFileSearchStoreName != null) { + setValueByPath(toObject, ['_url', 'file_search_store_name'], fromFileSearchStoreName); + } + const fromFileName = getValueByPath(fromObject, ['fileName']); + if (fromFileName != null) { + setValueByPath(toObject, ['fileName'], fromFileName); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + importFileConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function importFileResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromParent = getValueByPath(fromObject, ['parent']); + if (fromParent != null) { + setValueByPath(toObject, ['parent'], fromParent); + } + const fromDocumentName = getValueByPath(fromObject, ['documentName']); + if (fromDocumentName != null) { + setValueByPath(toObject, ['documentName'], fromDocumentName); + } + return toObject; +} +function listFileSearchStoresConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + return toObject; +} +function listFileSearchStoresParametersToMldev(fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listFileSearchStoresConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function listFileSearchStoresResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromFileSearchStores = getValueByPath(fromObject, [ + 'fileSearchStores', + ]); + if (fromFileSearchStores != null) { + let transformedList = fromFileSearchStores; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['fileSearchStores'], transformedList); + } + return toObject; +} +function uploadToFileSearchStoreConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (parentObject !== undefined && fromMimeType != null) { + setValueByPath(parentObject, ['mimeType'], fromMimeType); + } + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromDisplayName); + } + const fromCustomMetadata = getValueByPath(fromObject, [ + 'customMetadata', + ]); + if (parentObject !== undefined && fromCustomMetadata != null) { + let transformedList = fromCustomMetadata; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(parentObject, ['customMetadata'], transformedList); + } + const fromChunkingConfig = getValueByPath(fromObject, [ + 'chunkingConfig', + ]); + if (parentObject !== undefined && fromChunkingConfig != null) { + setValueByPath(parentObject, ['chunkingConfig'], fromChunkingConfig); + } + return toObject; +} +function uploadToFileSearchStoreParametersToMldev(fromObject) { + const toObject = {}; + const fromFileSearchStoreName = getValueByPath(fromObject, [ + 'fileSearchStoreName', + ]); + if (fromFileSearchStoreName != null) { + setValueByPath(toObject, ['_url', 'file_search_store_name'], fromFileSearchStoreName); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + uploadToFileSearchStoreConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function uploadToFileSearchStoreResumableResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const CONTENT_TYPE_HEADER = 'Content-Type'; +const SERVER_TIMEOUT_HEADER = 'X-Server-Timeout'; +const USER_AGENT_HEADER = 'User-Agent'; +const GOOGLE_API_CLIENT_HEADER = 'x-goog-api-client'; +const SDK_VERSION = '1.41.0'; // x-release-please-version +const LIBRARY_LABEL = `google-genai-sdk/${SDK_VERSION}`; +const VERTEX_AI_API_DEFAULT_VERSION = 'v1beta1'; +const GOOGLE_AI_API_DEFAULT_VERSION = 'v1beta'; +// Default retry options. +// The config is based on https://cloud.google.com/storage/docs/retry-strategy. +const DEFAULT_RETRY_ATTEMPTS = 5; // Including the initial call +// LINT.IfChange +const DEFAULT_RETRY_HTTP_STATUS_CODES = [ + 408, // Request timeout + 429, // Too many requests + 500, // Internal server error + 502, // Bad gateway + 503, // Service unavailable + 504, // Gateway timeout +]; +/** + * The ApiClient class is used to send requests to the Gemini API or Vertex AI + * endpoints. + */ +class ApiClient { + constructor(opts) { + var _a, _b, _c; + this.clientOptions = Object.assign({}, opts); + this.customBaseUrl = (_a = opts.httpOptions) === null || _a === void 0 ? void 0 : _a.baseUrl; + if (this.clientOptions.vertexai) { + if (this.clientOptions.project && this.clientOptions.location) { + this.clientOptions.apiKey = undefined; + } + else if (this.clientOptions.apiKey) { + this.clientOptions.project = undefined; + this.clientOptions.location = undefined; + } + } + const initHttpOptions = {}; + if (this.clientOptions.vertexai) { + if (!this.clientOptions.location && + !this.clientOptions.apiKey && + !this.customBaseUrl) { + this.clientOptions.location = 'global'; + } + const hasSufficientAuth = (this.clientOptions.project && this.clientOptions.location) || + this.clientOptions.apiKey; + if (!hasSufficientAuth && !this.customBaseUrl) { + throw new Error('Authentication is not set up. Please provide either a project and location, or an API key, or a custom base URL.'); + } + const hasConstructorAuth = (opts.project && opts.location) || !!opts.apiKey; + if (this.customBaseUrl && !hasConstructorAuth) { + initHttpOptions.baseUrl = this.customBaseUrl; + this.clientOptions.project = undefined; + this.clientOptions.location = undefined; + } + else if (this.clientOptions.apiKey || + this.clientOptions.location === 'global') { + // Vertex Express or global endpoint case. + initHttpOptions.baseUrl = 'https://aiplatform.googleapis.com/'; + } + else if (this.clientOptions.project && this.clientOptions.location) { + initHttpOptions.baseUrl = `https://${this.clientOptions.location}-aiplatform.googleapis.com/`; + } + initHttpOptions.apiVersion = + (_b = this.clientOptions.apiVersion) !== null && _b !== void 0 ? _b : VERTEX_AI_API_DEFAULT_VERSION; + } + else { + // Gemini API + if (!this.clientOptions.apiKey) { + throw new ApiError({ + message: 'API key must be set when using the Gemini API.', + status: 403, + }); + } + initHttpOptions.apiVersion = + (_c = this.clientOptions.apiVersion) !== null && _c !== void 0 ? _c : GOOGLE_AI_API_DEFAULT_VERSION; + initHttpOptions.baseUrl = `https://generativelanguage.googleapis.com/`; + } + initHttpOptions.headers = this.getDefaultHeaders(); + this.clientOptions.httpOptions = initHttpOptions; + if (opts.httpOptions) { + this.clientOptions.httpOptions = this.patchHttpOptions(initHttpOptions, opts.httpOptions); + } + } + isVertexAI() { + var _a; + return (_a = this.clientOptions.vertexai) !== null && _a !== void 0 ? _a : false; + } + getProject() { + return this.clientOptions.project; + } + getLocation() { + return this.clientOptions.location; + } + getCustomBaseUrl() { + return this.customBaseUrl; + } + async getAuthHeaders() { + const headers = new Headers(); + await this.clientOptions.auth.addAuthHeaders(headers); + return headers; + } + getApiVersion() { + if (this.clientOptions.httpOptions && + this.clientOptions.httpOptions.apiVersion !== undefined) { + return this.clientOptions.httpOptions.apiVersion; + } + throw new Error('API version is not set.'); + } + getBaseUrl() { + if (this.clientOptions.httpOptions && + this.clientOptions.httpOptions.baseUrl !== undefined) { + return this.clientOptions.httpOptions.baseUrl; + } + throw new Error('Base URL is not set.'); + } + getRequestUrl() { + return this.getRequestUrlInternal(this.clientOptions.httpOptions); + } + getHeaders() { + if (this.clientOptions.httpOptions && + this.clientOptions.httpOptions.headers !== undefined) { + return this.clientOptions.httpOptions.headers; + } + else { + throw new Error('Headers are not set.'); + } + } + getRequestUrlInternal(httpOptions) { + if (!httpOptions || + httpOptions.baseUrl === undefined || + httpOptions.apiVersion === undefined) { + throw new Error('HTTP options are not correctly set.'); + } + const baseUrl = httpOptions.baseUrl.endsWith('/') + ? httpOptions.baseUrl.slice(0, -1) + : httpOptions.baseUrl; + const urlElement = [baseUrl]; + if (httpOptions.apiVersion && httpOptions.apiVersion !== '') { + urlElement.push(httpOptions.apiVersion); + } + return urlElement.join('/'); + } + getBaseResourcePath() { + return `projects/${this.clientOptions.project}/locations/${this.clientOptions.location}`; + } + getApiKey() { + return this.clientOptions.apiKey; + } + getWebsocketBaseUrl() { + const baseUrl = this.getBaseUrl(); + const urlParts = new URL(baseUrl); + urlParts.protocol = urlParts.protocol == 'http:' ? 'ws' : 'wss'; + return urlParts.toString(); + } + setBaseUrl(url) { + if (this.clientOptions.httpOptions) { + this.clientOptions.httpOptions.baseUrl = url; + } + else { + throw new Error('HTTP options are not correctly set.'); + } + } + constructUrl(path, httpOptions, prependProjectLocation) { + const urlElement = [this.getRequestUrlInternal(httpOptions)]; + if (prependProjectLocation) { + urlElement.push(this.getBaseResourcePath()); + } + if (path !== '') { + urlElement.push(path); + } + const url = new URL(`${urlElement.join('/')}`); + return url; + } + shouldPrependVertexProjectPath(request, httpOptions) { + if (httpOptions.baseUrl && + httpOptions.baseUrlResourceScope === ResourceScope.COLLECTION) { + return false; + } + if (this.clientOptions.apiKey) { + return false; + } + if (!this.clientOptions.vertexai) { + return false; + } + if (request.path.startsWith('projects/')) { + // Assume the path already starts with + // `projects/<project>/location/<location>`. + return false; + } + if (request.httpMethod === 'GET' && + request.path.startsWith('publishers/google/models')) { + // These paths are used by Vertex's models.get and models.list + // calls. For base models Vertex does not accept a project/location + // prefix (for tuned model the prefix is required). + return false; + } + return true; + } + async request(request) { + let patchedHttpOptions = this.clientOptions.httpOptions; + if (request.httpOptions) { + patchedHttpOptions = this.patchHttpOptions(this.clientOptions.httpOptions, request.httpOptions); + } + const prependProjectLocation = this.shouldPrependVertexProjectPath(request, patchedHttpOptions); + const url = this.constructUrl(request.path, patchedHttpOptions, prependProjectLocation); + if (request.queryParams) { + for (const [key, value] of Object.entries(request.queryParams)) { + url.searchParams.append(key, String(value)); + } + } + let requestInit = {}; + if (request.httpMethod === 'GET') { + if (request.body && request.body !== '{}') { + throw new Error('Request body should be empty for GET request, but got non empty request body'); + } + } + else { + requestInit.body = request.body; + } + requestInit = await this.includeExtraHttpOptionsToRequestInit(requestInit, patchedHttpOptions, url.toString(), request.abortSignal); + return this.unaryApiCall(url, requestInit, request.httpMethod); + } + patchHttpOptions(baseHttpOptions, requestHttpOptions) { + const patchedHttpOptions = JSON.parse(JSON.stringify(baseHttpOptions)); + for (const [key, value] of Object.entries(requestHttpOptions)) { + // Records compile to objects. + if (typeof value === 'object') { + // @ts-expect-error TS2345TS7053: Element implicitly has an 'any' type + // because expression of type 'string' can't be used to index type + // 'HttpOptions'. + patchedHttpOptions[key] = Object.assign(Object.assign({}, patchedHttpOptions[key]), value); + } + else if (value !== undefined) { + // @ts-expect-error TS2345TS7053: Element implicitly has an 'any' type + // because expression of type 'string' can't be used to index type + // 'HttpOptions'. + patchedHttpOptions[key] = value; + } + } + return patchedHttpOptions; + } + async requestStream(request) { + let patchedHttpOptions = this.clientOptions.httpOptions; + if (request.httpOptions) { + patchedHttpOptions = this.patchHttpOptions(this.clientOptions.httpOptions, request.httpOptions); + } + const prependProjectLocation = this.shouldPrependVertexProjectPath(request, patchedHttpOptions); + const url = this.constructUrl(request.path, patchedHttpOptions, prependProjectLocation); + if (!url.searchParams.has('alt') || url.searchParams.get('alt') !== 'sse') { + url.searchParams.set('alt', 'sse'); + } + let requestInit = {}; + requestInit.body = request.body; + requestInit = await this.includeExtraHttpOptionsToRequestInit(requestInit, patchedHttpOptions, url.toString(), request.abortSignal); + return this.streamApiCall(url, requestInit, request.httpMethod); + } + async includeExtraHttpOptionsToRequestInit(requestInit, httpOptions, url, abortSignal) { + if ((httpOptions && httpOptions.timeout) || abortSignal) { + const abortController = new AbortController(); + const signal = abortController.signal; + if (httpOptions.timeout && (httpOptions === null || httpOptions === void 0 ? void 0 : httpOptions.timeout) > 0) { + const timeoutHandle = setTimeout(() => abortController.abort(), httpOptions.timeout); + if (timeoutHandle && + typeof timeoutHandle.unref === + 'function') { + // call unref to prevent nodejs process from hanging, see + // https://nodejs.org/api/timers.html#timeoutunref + timeoutHandle.unref(); + } + } + if (abortSignal) { + abortSignal.addEventListener('abort', () => { + abortController.abort(); + }); + } + requestInit.signal = signal; + } + if (httpOptions && httpOptions.extraBody !== null) { + includeExtraBodyToRequestInit(requestInit, httpOptions.extraBody); + } + requestInit.headers = await this.getHeadersInternal(httpOptions, url); + return requestInit; + } + async unaryApiCall(url, requestInit, httpMethod) { + return this.apiCall(url.toString(), Object.assign(Object.assign({}, requestInit), { method: httpMethod })) + .then(async (response) => { + await throwErrorIfNotOK(response); + return new HttpResponse(response); + }) + .catch((e) => { + if (e instanceof Error) { + throw e; + } + else { + throw new Error(JSON.stringify(e)); + } + }); + } + async streamApiCall(url, requestInit, httpMethod) { + return this.apiCall(url.toString(), Object.assign(Object.assign({}, requestInit), { method: httpMethod })) + .then(async (response) => { + await throwErrorIfNotOK(response); + return this.processStreamResponse(response); + }) + .catch((e) => { + if (e instanceof Error) { + throw e; + } + else { + throw new Error(JSON.stringify(e)); + } + }); + } + processStreamResponse(response) { + return __asyncGenerator(this, arguments, function* processStreamResponse_1() { + var _a; + const reader = (_a = response === null || response === void 0 ? void 0 : response.body) === null || _a === void 0 ? void 0 : _a.getReader(); + const decoder = new TextDecoder('utf-8'); + if (!reader) { + throw new Error('Response body is empty'); + } + try { + let buffer = ''; + const dataPrefix = 'data:'; + const delimiters = ['\n\n', '\r\r', '\r\n\r\n']; + while (true) { + const { done, value } = yield __await(reader.read()); + if (done) { + if (buffer.trim().length > 0) { + throw new Error('Incomplete JSON segment at the end'); + } + break; + } + const chunkString = decoder.decode(value, { stream: true }); + // Parse and throw an error if the chunk contains an error. + try { + const chunkJson = JSON.parse(chunkString); + if ('error' in chunkJson) { + const errorJson = JSON.parse(JSON.stringify(chunkJson['error'])); + const status = errorJson['status']; + const code = errorJson['code']; + const errorMessage = `got status: ${status}. ${JSON.stringify(chunkJson)}`; + if (code >= 400 && code < 600) { + const apiError = new ApiError({ + message: errorMessage, + status: code, + }); + throw apiError; + } + } + } + catch (e) { + const error = e; + if (error.name === 'ApiError') { + throw e; + } + } + buffer += chunkString; + let delimiterIndex = -1; + let delimiterLength = 0; + while (true) { + delimiterIndex = -1; + delimiterLength = 0; + for (const delimiter of delimiters) { + const index = buffer.indexOf(delimiter); + if (index !== -1 && + (delimiterIndex === -1 || index < delimiterIndex)) { + delimiterIndex = index; + delimiterLength = delimiter.length; + } + } + if (delimiterIndex === -1) { + break; // No complete event in buffer + } + const eventString = buffer.substring(0, delimiterIndex); + buffer = buffer.substring(delimiterIndex + delimiterLength); + const trimmedEvent = eventString.trim(); + if (trimmedEvent.startsWith(dataPrefix)) { + const processedChunkString = trimmedEvent + .substring(dataPrefix.length) + .trim(); + try { + const partialResponse = new Response(processedChunkString, { + headers: response === null || response === void 0 ? void 0 : response.headers, + status: response === null || response === void 0 ? void 0 : response.status, + statusText: response === null || response === void 0 ? void 0 : response.statusText, + }); + yield yield __await(new HttpResponse(partialResponse)); + } + catch (e) { + throw new Error(`exception parsing stream chunk ${processedChunkString}. ${e}`); + } + } + } + } + } + finally { + reader.releaseLock(); + } + }); + } + async apiCall(url, requestInit) { + var _a; + if (!this.clientOptions.httpOptions || + !this.clientOptions.httpOptions.retryOptions) { + return fetch(url, requestInit); + } + const retryOptions = this.clientOptions.httpOptions.retryOptions; + const runFetch = async () => { + const response = await fetch(url, requestInit); + if (response.ok) { + return response; + } + if (DEFAULT_RETRY_HTTP_STATUS_CODES.includes(response.status)) { + throw new Error(`Retryable HTTP Error: ${response.statusText}`); + } + throw new AbortError(`Non-retryable exception ${response.statusText} sending request`); + }; + return pRetry(runFetch, { + // Retry attempts is one less than the number of total attempts. + retries: ((_a = retryOptions.attempts) !== null && _a !== void 0 ? _a : DEFAULT_RETRY_ATTEMPTS) - 1, + }); + } + getDefaultHeaders() { + const headers = {}; + const versionHeaderValue = LIBRARY_LABEL + ' ' + this.clientOptions.userAgentExtra; + headers[USER_AGENT_HEADER] = versionHeaderValue; + headers[GOOGLE_API_CLIENT_HEADER] = versionHeaderValue; + headers[CONTENT_TYPE_HEADER] = 'application/json'; + return headers; + } + async getHeadersInternal(httpOptions, url) { + const headers = new Headers(); + if (httpOptions && httpOptions.headers) { + for (const [key, value] of Object.entries(httpOptions.headers)) { + headers.append(key, value); + } + // Append a timeout header if it is set, note that the timeout option is + // in milliseconds but the header is in seconds. + if (httpOptions.timeout && httpOptions.timeout > 0) { + headers.append(SERVER_TIMEOUT_HEADER, String(Math.ceil(httpOptions.timeout / 1000))); + } + } + await this.clientOptions.auth.addAuthHeaders(headers, url); + return headers; + } + getFileName(file) { + var _a; + let fileName = ''; + if (typeof file === 'string') { + fileName = file.replace(/[/\\]+$/, ''); + fileName = (_a = fileName.split(/[/\\]/).pop()) !== null && _a !== void 0 ? _a : ''; + } + return fileName; + } + /** + * Uploads a file asynchronously using Gemini API only, this is not supported + * in Vertex AI. + * + * @param file The string path to the file to be uploaded or a Blob object. + * @param config Optional parameters specified in the `UploadFileConfig` + * interface. @see {@link types.UploadFileConfig} + * @return A promise that resolves to a `File` object. + * @throws An error if called on a Vertex AI client. + * @throws An error if the `mimeType` is not provided and can not be inferred, + */ + async uploadFile(file, config) { + var _a; + const fileToUpload = {}; + if (config != null) { + fileToUpload.mimeType = config.mimeType; + fileToUpload.name = config.name; + fileToUpload.displayName = config.displayName; + } + if (fileToUpload.name && !fileToUpload.name.startsWith('files/')) { + fileToUpload.name = `files/${fileToUpload.name}`; + } + const uploader = this.clientOptions.uploader; + const fileStat = await uploader.stat(file); + fileToUpload.sizeBytes = String(fileStat.size); + const mimeType = (_a = config === null || config === void 0 ? void 0 : config.mimeType) !== null && _a !== void 0 ? _a : fileStat.type; + if (mimeType === undefined || mimeType === '') { + throw new Error('Can not determine mimeType. Please provide mimeType in the config.'); + } + fileToUpload.mimeType = mimeType; + const body = { + file: fileToUpload, + }; + const fileName = this.getFileName(file); + const path = formatMap('upload/v1beta/files', body['_url']); + const uploadUrl = await this.fetchUploadUrl(path, fileToUpload.sizeBytes, fileToUpload.mimeType, fileName, body, config === null || config === void 0 ? void 0 : config.httpOptions); + return uploader.upload(file, uploadUrl, this); + } + /** + * Uploads a file to a given file search store asynchronously using Gemini API only, this is not supported + * in Vertex AI. + * + * @param fileSearchStoreName The name of the file search store to upload the file to. + * @param file The string path to the file to be uploaded or a Blob object. + * @param config Optional parameters specified in the `UploadFileConfig` + * interface. @see {@link UploadFileConfig} + * @return A promise that resolves to a `File` object. + * @throws An error if called on a Vertex AI client. + * @throws An error if the `mimeType` is not provided and can not be inferred, + */ + async uploadFileToFileSearchStore(fileSearchStoreName, file, config) { + var _a; + const uploader = this.clientOptions.uploader; + const fileStat = await uploader.stat(file); + const sizeBytes = String(fileStat.size); + const mimeType = (_a = config === null || config === void 0 ? void 0 : config.mimeType) !== null && _a !== void 0 ? _a : fileStat.type; + if (mimeType === undefined || mimeType === '') { + throw new Error('Can not determine mimeType. Please provide mimeType in the config.'); + } + const path = `upload/v1beta/${fileSearchStoreName}:uploadToFileSearchStore`; + const fileName = this.getFileName(file); + const body = {}; + if (config != null) { + uploadToFileSearchStoreConfigToMldev(config, body); + } + const uploadUrl = await this.fetchUploadUrl(path, sizeBytes, mimeType, fileName, body, config === null || config === void 0 ? void 0 : config.httpOptions); + return uploader.uploadToFileSearchStore(file, uploadUrl, this); + } + /** + * Downloads a file asynchronously to the specified path. + * + * @params params - The parameters for the download request, see {@link + * types.DownloadFileParameters} + */ + async downloadFile(params) { + const downloader = this.clientOptions.downloader; + await downloader.download(params, this); + } + async fetchUploadUrl(path, sizeBytes, mimeType, fileName, body, configHttpOptions) { + var _a; + let httpOptions = {}; + if (configHttpOptions) { + httpOptions = configHttpOptions; + } + else { + httpOptions = { + apiVersion: '', // api-version is set in the path. + headers: Object.assign({ 'Content-Type': 'application/json', 'X-Goog-Upload-Protocol': 'resumable', 'X-Goog-Upload-Command': 'start', 'X-Goog-Upload-Header-Content-Length': `${sizeBytes}`, 'X-Goog-Upload-Header-Content-Type': `${mimeType}` }, (fileName ? { 'X-Goog-Upload-File-Name': fileName } : {})), + }; + } + const httpResponse = await this.request({ + path, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions, + }); + if (!httpResponse || !(httpResponse === null || httpResponse === void 0 ? void 0 : httpResponse.headers)) { + throw new Error('Server did not return an HttpResponse or the returned HttpResponse did not have headers.'); + } + const uploadUrl = (_a = httpResponse === null || httpResponse === void 0 ? void 0 : httpResponse.headers) === null || _a === void 0 ? void 0 : _a['x-goog-upload-url']; + if (uploadUrl === undefined) { + throw new Error('Failed to get upload url. Server did not return the x-google-upload-url in the headers'); + } + return uploadUrl; + } +} +async function throwErrorIfNotOK(response) { + var _a; + if (response === undefined) { + throw new Error('response is undefined'); + } + if (!response.ok) { + const status = response.status; + let errorBody; + if ((_a = response.headers.get('content-type')) === null || _a === void 0 ? void 0 : _a.includes('application/json')) { + errorBody = await response.json(); + } + else { + errorBody = { + error: { + message: await response.text(), + code: response.status, + status: response.statusText, + }, + }; + } + const errorMessage = JSON.stringify(errorBody); + if (status >= 400 && status < 600) { + const apiError = new ApiError({ + message: errorMessage, + status: status, + }); + throw apiError; + } + throw new Error(errorMessage); + } +} +/** + * Recursively updates the `requestInit.body` with values from an `extraBody` object. + * + * If `requestInit.body` is a string, it's assumed to be JSON and will be parsed. + * The `extraBody` is then deeply merged into this parsed object. + * If `requestInit.body` is a Blob, `extraBody` will be ignored, and a warning logged, + * as merging structured data into an opaque Blob is not supported. + * + * The function does not enforce that updated values from `extraBody` have the + * same type as existing values in `requestInit.body`. Type mismatches during + * the merge will result in a warning, but the value from `extraBody` will overwrite + * the original. `extraBody` users are responsible for ensuring `extraBody` has the correct structure. + * + * @param requestInit The RequestInit object whose body will be updated. + * @param extraBody The object containing updates to be merged into `requestInit.body`. + */ +function includeExtraBodyToRequestInit(requestInit, extraBody) { + if (!extraBody || Object.keys(extraBody).length === 0) { + return; + } + if (requestInit.body instanceof Blob) { + console.warn('includeExtraBodyToRequestInit: extraBody provided but current request body is a Blob. extraBody will be ignored as merging is not supported for Blob bodies.'); + return; + } + let currentBodyObject = {}; + // If adding new type to HttpRequest.body, please check the code below to + // see if we need to update the logic. + if (typeof requestInit.body === 'string' && requestInit.body.length > 0) { + try { + const parsedBody = JSON.parse(requestInit.body); + if (typeof parsedBody === 'object' && + parsedBody !== null && + !Array.isArray(parsedBody)) { + currentBodyObject = parsedBody; + } + else { + console.warn('includeExtraBodyToRequestInit: Original request body is valid JSON but not a non-array object. Skip applying extraBody to the request body.'); + return; + } + /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ + } + catch (e) { + console.warn('includeExtraBodyToRequestInit: Original request body is not valid JSON. Skip applying extraBody to the request body.'); + return; + } + } + function deepMerge(target, source) { + const output = Object.assign({}, target); + for (const key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + const sourceValue = source[key]; + const targetValue = output[key]; + if (sourceValue && + typeof sourceValue === 'object' && + !Array.isArray(sourceValue) && + targetValue && + typeof targetValue === 'object' && + !Array.isArray(targetValue)) { + output[key] = deepMerge(targetValue, sourceValue); + } + else { + if (targetValue && + sourceValue && + typeof targetValue !== typeof sourceValue) { + console.warn(`includeExtraBodyToRequestInit:deepMerge: Type mismatch for key "${key}". Original type: ${typeof targetValue}, New type: ${typeof sourceValue}. Overwriting.`); + } + output[key] = sourceValue; + } + } + } + return output; + } + const mergedBody = deepMerge(currentBodyObject, extraBody); + requestInit.body = JSON.stringify(mergedBody); +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// TODO: b/416041229 - Determine how to retrieve the MCP package version. +const MCP_LABEL = 'mcp_used/unknown'; +// Whether MCP tool usage is detected from mcpToTool. This is used for +// telemetry. +let hasMcpToolUsageFromMcpToTool = false; +// Checks whether the list of tools contains any MCP tools. +function hasMcpToolUsage(tools) { + for (const tool of tools) { + if (isMcpCallableTool(tool)) { + return true; + } + if (typeof tool === 'object' && 'inputSchema' in tool) { + return true; + } + } + return hasMcpToolUsageFromMcpToTool; +} +// Sets the MCP version label in the Google API client header. +function setMcpUsageHeader(headers) { + var _a; + const existingHeader = (_a = headers[GOOGLE_API_CLIENT_HEADER]) !== null && _a !== void 0 ? _a : ''; + headers[GOOGLE_API_CLIENT_HEADER] = (existingHeader + ` ${MCP_LABEL}`).trimStart(); +} +// Returns true if the object is a MCP CallableTool, otherwise false. +function isMcpCallableTool(object) { + return (object !== null && + typeof object === 'object' && + object instanceof McpCallableTool); +} +// List all tools from the MCP client. +function listAllTools(mcpClient_1) { + return __asyncGenerator(this, arguments, function* listAllTools_1(mcpClient, maxTools = 100) { + let cursor = undefined; + let numTools = 0; + while (numTools < maxTools) { + const t = yield __await(mcpClient.listTools({ cursor })); + for (const tool of t.tools) { + yield yield __await(tool); + numTools++; + } + if (!t.nextCursor) { + break; + } + cursor = t.nextCursor; + } + }); +} +/** + * McpCallableTool can be used for model inference and invoking MCP clients with + * given function call arguments. + * + * @experimental Built-in MCP support is an experimental feature, may change in future + * versions. + */ +class McpCallableTool { + constructor(mcpClients = [], config) { + this.mcpTools = []; + this.functionNameToMcpClient = {}; + this.mcpClients = mcpClients; + this.config = config; + } + /** + * Creates a McpCallableTool. + */ + static create(mcpClients, config) { + return new McpCallableTool(mcpClients, config); + } + /** + * Validates the function names are not duplicate and initialize the function + * name to MCP client mapping. + * + * @throws {Error} if the MCP tools from the MCP clients have duplicate tool + * names. + */ + async initialize() { + var _a, e_1, _b, _c; + if (this.mcpTools.length > 0) { + return; + } + const functionMap = {}; + const mcpTools = []; + for (const mcpClient of this.mcpClients) { + try { + for (var _d = true, _e = (e_1 = void 0, __asyncValues(listAllTools(mcpClient))), _f; _f = await _e.next(), _a = _f.done, !_a; _d = true) { + _c = _f.value; + _d = false; + const mcpTool = _c; + mcpTools.push(mcpTool); + const mcpToolName = mcpTool.name; + if (functionMap[mcpToolName]) { + throw new Error(`Duplicate function name ${mcpToolName} found in MCP tools. Please ensure function names are unique.`); + } + functionMap[mcpToolName] = mcpClient; + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (!_d && !_a && (_b = _e.return)) await _b.call(_e); + } + finally { if (e_1) throw e_1.error; } + } + } + this.mcpTools = mcpTools; + this.functionNameToMcpClient = functionMap; + } + async tool() { + await this.initialize(); + return mcpToolsToGeminiTool(this.mcpTools, this.config); + } + async callTool(functionCalls) { + await this.initialize(); + const functionCallResponseParts = []; + for (const functionCall of functionCalls) { + if (functionCall.name in this.functionNameToMcpClient) { + const mcpClient = this.functionNameToMcpClient[functionCall.name]; + let requestOptions = undefined; + // TODO: b/424238654 - Add support for finer grained timeout control. + if (this.config.timeout) { + requestOptions = { + timeout: this.config.timeout, + }; + } + const callToolResponse = await mcpClient.callTool({ + name: functionCall.name, + arguments: functionCall.args, + }, + // Set the result schema to undefined to allow MCP to rely on the + // default schema. + undefined, requestOptions); + functionCallResponseParts.push({ + functionResponse: { + name: functionCall.name, + response: callToolResponse.isError + ? { error: callToolResponse } + : callToolResponse, + }, + }); + } + } + return functionCallResponseParts; + } +} +function isMcpClient(client) { + return (client !== null && + typeof client === 'object' && + 'listTools' in client && + typeof client.listTools === 'function'); +} +/** + * Creates a McpCallableTool from MCP clients and an optional config. + * + * The callable tool can invoke the MCP clients with given function call + * arguments. (often for automatic function calling). + * Use the config to modify tool parameters such as behavior. + * + * @experimental Built-in MCP support is an experimental feature, may change in future + * versions. + */ +function mcpToTool(...args) { + // Set MCP usage for telemetry. + hasMcpToolUsageFromMcpToTool = true; + if (args.length === 0) { + throw new Error('No MCP clients provided'); + } + const maybeConfig = args[args.length - 1]; + if (isMcpClient(maybeConfig)) { + return McpCallableTool.create(args, {}); + } + return McpCallableTool.create(args.slice(0, args.length - 1), maybeConfig); +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Handles incoming messages from the WebSocket. + * + * @remarks + * This function is responsible for parsing incoming messages, transforming them + * into LiveMusicServerMessage, and then calling the onmessage callback. + * Note that the first message which is received from the server is a + * setupComplete message. + * + * @param apiClient The ApiClient instance. + * @param onmessage The user-provided onmessage callback (if any). + * @param event The MessageEvent from the WebSocket. + */ +async function handleWebSocketMessage$1(apiClient, onmessage, event) { + const serverMessage = new LiveMusicServerMessage(); + let data; + if (event.data instanceof Blob) { + data = JSON.parse(await event.data.text()); + } + else { + data = JSON.parse(event.data); + } + Object.assign(serverMessage, data); + onmessage(serverMessage); +} +/** + LiveMusic class encapsulates the configuration for live music + generation via Lyria Live models. + + @experimental + */ +class LiveMusic { + constructor(apiClient, auth, webSocketFactory) { + this.apiClient = apiClient; + this.auth = auth; + this.webSocketFactory = webSocketFactory; + } + /** + Establishes a connection to the specified model and returns a + LiveMusicSession object representing that connection. + + @experimental + + @remarks + + @param params - The parameters for establishing a connection to the model. + @return A live session. + + @example + ```ts + let model = 'models/lyria-realtime-exp'; + const session = await ai.live.music.connect({ + model: model, + callbacks: { + onmessage: (e: MessageEvent) => { + console.log('Received message from the server: %s\n', debug(e.data)); + }, + onerror: (e: ErrorEvent) => { + console.log('Error occurred: %s\n', debug(e.error)); + }, + onclose: (e: CloseEvent) => { + console.log('Connection closed.'); + }, + }, + }); + ``` + */ + async connect(params) { + var _a, _b; + if (this.apiClient.isVertexAI()) { + throw new Error('Live music is not supported for Vertex AI.'); + } + console.warn('Live music generation is experimental and may change in future versions.'); + const websocketBaseUrl = this.apiClient.getWebsocketBaseUrl(); + const apiVersion = this.apiClient.getApiVersion(); + const headers = mapToHeaders$1(this.apiClient.getDefaultHeaders()); + const apiKey = this.apiClient.getApiKey(); + const url = `${websocketBaseUrl}/ws/google.ai.generativelanguage.${apiVersion}.GenerativeService.BidiGenerateMusic?key=${apiKey}`; + let onopenResolve = () => { }; + const onopenPromise = new Promise((resolve) => { + onopenResolve = resolve; + }); + const callbacks = params.callbacks; + const onopenAwaitedCallback = function () { + onopenResolve({}); + }; + const apiClient = this.apiClient; + const websocketCallbacks = { + onopen: onopenAwaitedCallback, + onmessage: (event) => { + void handleWebSocketMessage$1(apiClient, callbacks.onmessage, event); + }, + onerror: (_a = callbacks === null || callbacks === void 0 ? void 0 : callbacks.onerror) !== null && _a !== void 0 ? _a : function (e) { + }, + onclose: (_b = callbacks === null || callbacks === void 0 ? void 0 : callbacks.onclose) !== null && _b !== void 0 ? _b : function (e) { + }, + }; + const conn = this.webSocketFactory.create(url, headersToMap$1(headers), websocketCallbacks); + conn.connect(); + // Wait for the websocket to open before sending requests. + await onopenPromise; + const model = tModel(this.apiClient, params.model); + const setup = { model }; + const clientMessage = { setup }; + conn.send(JSON.stringify(clientMessage)); + return new LiveMusicSession(conn, this.apiClient); + } +} +/** + Represents a connection to the API. + + @experimental + */ +class LiveMusicSession { + constructor(conn, apiClient) { + this.conn = conn; + this.apiClient = apiClient; + } + /** + Sets inputs to steer music generation. Updates the session's current + weighted prompts. + + @param params - Contains one property, `weightedPrompts`. + + - `weightedPrompts` to send to the model; weights are normalized to + sum to 1.0. + + @experimental + */ + async setWeightedPrompts(params) { + if (!params.weightedPrompts || + Object.keys(params.weightedPrompts).length === 0) { + throw new Error('Weighted prompts must be set and contain at least one entry.'); + } + const clientContent = liveMusicSetWeightedPromptsParametersToMldev(params); + this.conn.send(JSON.stringify({ clientContent })); + } + /** + Sets a configuration to the model. Updates the session's current + music generation config. + + @param params - Contains one property, `musicGenerationConfig`. + + - `musicGenerationConfig` to set in the model. Passing an empty or + undefined config to the model will reset the config to defaults. + + @experimental + */ + async setMusicGenerationConfig(params) { + if (!params.musicGenerationConfig) { + params.musicGenerationConfig = {}; + } + const setConfigParameters = liveMusicSetConfigParametersToMldev(params); + this.conn.send(JSON.stringify(setConfigParameters)); + } + sendPlaybackControl(playbackControl) { + const clientMessage = { playbackControl }; + this.conn.send(JSON.stringify(clientMessage)); + } + /** + * Start the music stream. + * + * @experimental + */ + play() { + this.sendPlaybackControl(LiveMusicPlaybackControl.PLAY); + } + /** + * Temporarily halt the music stream. Use `play` to resume from the current + * position. + * + * @experimental + */ + pause() { + this.sendPlaybackControl(LiveMusicPlaybackControl.PAUSE); + } + /** + * Stop the music stream and reset the state. Retains the current prompts + * and config. + * + * @experimental + */ + stop() { + this.sendPlaybackControl(LiveMusicPlaybackControl.STOP); + } + /** + * Resets the context of the music generation without stopping it. + * Retains the current prompts and config. + * + * @experimental + */ + resetContext() { + this.sendPlaybackControl(LiveMusicPlaybackControl.RESET_CONTEXT); + } + /** + Terminates the WebSocket connection. + + @experimental + */ + close() { + this.conn.close(); + } +} +// Converts an headers object to a "map" object as expected by the WebSocket +// constructor. We use this as the Auth interface works with Headers objects +// while the WebSocket constructor takes a map. +function headersToMap$1(headers) { + const headerMap = {}; + headers.forEach((value, key) => { + headerMap[key] = value; + }); + return headerMap; +} +// Converts a "map" object to a headers object. We use this as the Auth +// interface works with Headers objects while the API client default headers +// returns a map. +function mapToHeaders$1(map) { + const headers = new Headers(); + for (const [key, value] of Object.entries(map)) { + headers.append(key, value); + } + return headers; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const FUNCTION_RESPONSE_REQUIRES_ID = 'FunctionResponse request must have an `id` field from the response of a ToolCall.FunctionalCalls in Google AI.'; +/** + * Handles incoming messages from the WebSocket. + * + * @remarks + * This function is responsible for parsing incoming messages, transforming them + * into LiveServerMessages, and then calling the onmessage callback. Note that + * the first message which is received from the server is a setupComplete + * message. + * + * @param apiClient The ApiClient instance. + * @param onmessage The user-provided onmessage callback (if any). + * @param event The MessageEvent from the WebSocket. + */ +async function handleWebSocketMessage(apiClient, onmessage, event) { + const serverMessage = new LiveServerMessage(); + let jsonData; + if (event.data instanceof Blob) { + jsonData = await event.data.text(); + } + else if (event.data instanceof ArrayBuffer) { + jsonData = new TextDecoder().decode(event.data); + } + else { + jsonData = event.data; + } + const data = JSON.parse(jsonData); + if (apiClient.isVertexAI()) { + const resp = liveServerMessageFromVertex(data); + Object.assign(serverMessage, resp); + } + else { + const resp = data; + Object.assign(serverMessage, resp); + } + onmessage(serverMessage); +} +/** + Live class encapsulates the configuration for live interaction with the + Generative Language API. It embeds ApiClient for general API settings. + + @experimental + */ +class Live { + constructor(apiClient, auth, webSocketFactory) { + this.apiClient = apiClient; + this.auth = auth; + this.webSocketFactory = webSocketFactory; + this.music = new LiveMusic(this.apiClient, this.auth, this.webSocketFactory); + } + /** + Establishes a connection to the specified model with the given + configuration and returns a Session object representing that connection. + + @experimental Built-in MCP support is an experimental feature, may change in + future versions. + + @remarks + + @param params - The parameters for establishing a connection to the model. + @return A live session. + + @example + ```ts + let model: string; + if (GOOGLE_GENAI_USE_VERTEXAI) { + model = 'gemini-2.0-flash-live-preview-04-09'; + } else { + model = 'gemini-live-2.5-flash-preview'; + } + const session = await ai.live.connect({ + model: model, + config: { + responseModalities: [Modality.AUDIO], + }, + callbacks: { + onopen: () => { + console.log('Connected to the socket.'); + }, + onmessage: (e: MessageEvent) => { + console.log('Received message from the server: %s\n', debug(e.data)); + }, + onerror: (e: ErrorEvent) => { + console.log('Error occurred: %s\n', debug(e.error)); + }, + onclose: (e: CloseEvent) => { + console.log('Connection closed.'); + }, + }, + }); + ``` + */ + async connect(params) { + var _a, _b, _c, _d, _e, _f; + // TODO: b/404946746 - Support per request HTTP options. + if (params.config && params.config.httpOptions) { + throw new Error('The Live module does not support httpOptions at request-level in' + + ' LiveConnectConfig yet. Please use the client-level httpOptions' + + ' configuration instead.'); + } + const websocketBaseUrl = this.apiClient.getWebsocketBaseUrl(); + const apiVersion = this.apiClient.getApiVersion(); + let url; + const clientHeaders = this.apiClient.getHeaders(); + if (params.config && + params.config.tools && + hasMcpToolUsage(params.config.tools)) { + setMcpUsageHeader(clientHeaders); + } + const headers = mapToHeaders(clientHeaders); + if (this.apiClient.isVertexAI()) { + const project = this.apiClient.getProject(); + const location = this.apiClient.getLocation(); + const apiKey = this.apiClient.getApiKey(); + const hasStandardAuth = (!!project && !!location) || !!apiKey; + if (this.apiClient.getCustomBaseUrl() && !hasStandardAuth) { + // Custom base URL without standard auth (e.g., proxy). + url = websocketBaseUrl; + // Auth headers are assumed to be in `clientHeaders` from httpOptions. + } + else { + url = `${websocketBaseUrl}/ws/google.cloud.aiplatform.${apiVersion}.LlmBidiService/BidiGenerateContent`; + await this.auth.addAuthHeaders(headers, url); + } + } + else { + const apiKey = this.apiClient.getApiKey(); + let method = 'BidiGenerateContent'; + let keyName = 'key'; + if (apiKey === null || apiKey === void 0 ? void 0 : apiKey.startsWith('auth_tokens/')) { + console.warn('Warning: Ephemeral token support is experimental and may change in future versions.'); + if (apiVersion !== 'v1alpha') { + console.warn("Warning: The SDK's ephemeral token support is in v1alpha only. Please use const ai = new GoogleGenAI({apiKey: token.name, httpOptions: { apiVersion: 'v1alpha' }}); before session connection."); + } + method = 'BidiGenerateContentConstrained'; + keyName = 'access_token'; + } + url = `${websocketBaseUrl}/ws/google.ai.generativelanguage.${apiVersion}.GenerativeService.${method}?${keyName}=${apiKey}`; + } + let onopenResolve = () => { }; + const onopenPromise = new Promise((resolve) => { + onopenResolve = resolve; + }); + const callbacks = params.callbacks; + const onopenAwaitedCallback = function () { + var _a; + (_a = callbacks === null || callbacks === void 0 ? void 0 : callbacks.onopen) === null || _a === void 0 ? void 0 : _a.call(callbacks); + onopenResolve({}); + }; + const apiClient = this.apiClient; + const websocketCallbacks = { + onopen: onopenAwaitedCallback, + onmessage: (event) => { + void handleWebSocketMessage(apiClient, callbacks.onmessage, event); + }, + onerror: (_a = callbacks === null || callbacks === void 0 ? void 0 : callbacks.onerror) !== null && _a !== void 0 ? _a : function (e) { + }, + onclose: (_b = callbacks === null || callbacks === void 0 ? void 0 : callbacks.onclose) !== null && _b !== void 0 ? _b : function (e) { + }, + }; + const conn = this.webSocketFactory.create(url, headersToMap(headers), websocketCallbacks); + conn.connect(); + // Wait for the websocket to open before sending requests. + await onopenPromise; + let transformedModel = tModel(this.apiClient, params.model); + if (this.apiClient.isVertexAI() && + transformedModel.startsWith('publishers/')) { + const project = this.apiClient.getProject(); + const location = this.apiClient.getLocation(); + if (project && location) { + transformedModel = + `projects/${project}/locations/${location}/` + transformedModel; + } + } + let clientMessage = {}; + if (this.apiClient.isVertexAI() && + ((_c = params.config) === null || _c === void 0 ? void 0 : _c.responseModalities) === undefined) { + // Set default to AUDIO to align with MLDev API. + if (params.config === undefined) { + params.config = { responseModalities: [Modality.AUDIO] }; + } + else { + params.config.responseModalities = [Modality.AUDIO]; + } + } + if ((_d = params.config) === null || _d === void 0 ? void 0 : _d.generationConfig) { + // Raise deprecation warning for generationConfig. + console.warn('Setting `LiveConnectConfig.generation_config` is deprecated, please set the fields on `LiveConnectConfig` directly. This will become an error in a future version (not before Q3 2025).'); + } + const inputTools = (_f = (_e = params.config) === null || _e === void 0 ? void 0 : _e.tools) !== null && _f !== void 0 ? _f : []; + const convertedTools = []; + for (const tool of inputTools) { + if (this.isCallableTool(tool)) { + const callableTool = tool; + convertedTools.push(await callableTool.tool()); + } + else { + convertedTools.push(tool); + } + } + if (convertedTools.length > 0) { + params.config.tools = convertedTools; + } + const liveConnectParameters = { + model: transformedModel, + config: params.config, + callbacks: params.callbacks, + }; + if (this.apiClient.isVertexAI()) { + clientMessage = liveConnectParametersToVertex(this.apiClient, liveConnectParameters); + } + else { + clientMessage = liveConnectParametersToMldev(this.apiClient, liveConnectParameters); + } + delete clientMessage['config']; + conn.send(JSON.stringify(clientMessage)); + return new Session(conn, this.apiClient); + } + // TODO: b/416041229 - Abstract this method to a common place. + isCallableTool(tool) { + return 'callTool' in tool && typeof tool.callTool === 'function'; + } +} +const defaultLiveSendClientContentParamerters = { + turnComplete: true, +}; +/** + Represents a connection to the API. + + @experimental + */ +class Session { + constructor(conn, apiClient) { + this.conn = conn; + this.apiClient = apiClient; + } + tLiveClientContent(apiClient, params) { + if (params.turns !== null && params.turns !== undefined) { + let contents = []; + try { + contents = tContents(params.turns); + if (!apiClient.isVertexAI()) { + contents = contents.map((item) => contentToMldev$1(item)); + } + } + catch (_a) { + throw new Error(`Failed to parse client content "turns", type: '${typeof params.turns}'`); + } + return { + clientContent: { turns: contents, turnComplete: params.turnComplete }, + }; + } + return { + clientContent: { turnComplete: params.turnComplete }, + }; + } + tLiveClienttToolResponse(apiClient, params) { + let functionResponses = []; + if (params.functionResponses == null) { + throw new Error('functionResponses is required.'); + } + if (!Array.isArray(params.functionResponses)) { + functionResponses = [params.functionResponses]; + } + else { + functionResponses = params.functionResponses; + } + if (functionResponses.length === 0) { + throw new Error('functionResponses is required.'); + } + for (const functionResponse of functionResponses) { + if (typeof functionResponse !== 'object' || + functionResponse === null || + !('name' in functionResponse) || + !('response' in functionResponse)) { + throw new Error(`Could not parse function response, type '${typeof functionResponse}'.`); + } + if (!apiClient.isVertexAI() && !('id' in functionResponse)) { + throw new Error(FUNCTION_RESPONSE_REQUIRES_ID); + } + } + const clientMessage = { + toolResponse: { functionResponses: functionResponses }, + }; + return clientMessage; + } + /** + Send a message over the established connection. + + @param params - Contains two **optional** properties, `turns` and + `turnComplete`. + + - `turns` will be converted to a `Content[]` + - `turnComplete: true` [default] indicates that you are done sending + content and expect a response. If `turnComplete: false`, the server + will wait for additional messages before starting generation. + + @experimental + + @remarks + There are two ways to send messages to the live API: + `sendClientContent` and `sendRealtimeInput`. + + `sendClientContent` messages are added to the model context **in order**. + Having a conversation using `sendClientContent` messages is roughly + equivalent to using the `Chat.sendMessageStream`, except that the state of + the `chat` history is stored on the API server instead of locally. + + Because of `sendClientContent`'s order guarantee, the model cannot respons + as quickly to `sendClientContent` messages as to `sendRealtimeInput` + messages. This makes the biggest difference when sending objects that have + significant preprocessing time (typically images). + + The `sendClientContent` message sends a `Content[]` + which has more options than the `Blob` sent by `sendRealtimeInput`. + + So the main use-cases for `sendClientContent` over `sendRealtimeInput` are: + + - Sending anything that can't be represented as a `Blob` (text, + `sendClientContent({turns="Hello?"}`)). + - Managing turns when not using audio input and voice activity detection. + (`sendClientContent({turnComplete:true})` or the short form + `sendClientContent()`) + - Prefilling a conversation context + ``` + sendClientContent({ + turns: [ + Content({role:user, parts:...}), + Content({role:user, parts:...}), + ... + ] + }) + ``` + @experimental + */ + sendClientContent(params) { + params = Object.assign(Object.assign({}, defaultLiveSendClientContentParamerters), params); + const clientMessage = this.tLiveClientContent(this.apiClient, params); + this.conn.send(JSON.stringify(clientMessage)); + } + /** + Send a realtime message over the established connection. + + @param params - Contains one property, `media`. + + - `media` will be converted to a `Blob` + + @experimental + + @remarks + Use `sendRealtimeInput` for realtime audio chunks and video frames (images). + + With `sendRealtimeInput` the api will respond to audio automatically + based on voice activity detection (VAD). + + `sendRealtimeInput` is optimized for responsivness at the expense of + deterministic ordering guarantees. Audio and video tokens are to the + context when they become available. + + Note: The Call signature expects a `Blob` object, but only a subset + of audio and image mimetypes are allowed. + */ + sendRealtimeInput(params) { + let clientMessage = {}; + if (this.apiClient.isVertexAI()) { + clientMessage = { + 'realtimeInput': liveSendRealtimeInputParametersToVertex(params), + }; + } + else { + clientMessage = { + 'realtimeInput': liveSendRealtimeInputParametersToMldev(params), + }; + } + this.conn.send(JSON.stringify(clientMessage)); + } + /** + Send a function response message over the established connection. + + @param params - Contains property `functionResponses`. + + - `functionResponses` will be converted to a `functionResponses[]` + + @remarks + Use `sendFunctionResponse` to reply to `LiveServerToolCall` from the server. + + Use {@link types.LiveConnectConfig#tools} to configure the callable functions. + + @experimental + */ + sendToolResponse(params) { + if (params.functionResponses == null) { + throw new Error('Tool response parameters are required.'); + } + const clientMessage = this.tLiveClienttToolResponse(this.apiClient, params); + this.conn.send(JSON.stringify(clientMessage)); + } + /** + Terminates the WebSocket connection. + + @experimental + + @example + ```ts + let model: string; + if (GOOGLE_GENAI_USE_VERTEXAI) { + model = 'gemini-2.0-flash-live-preview-04-09'; + } else { + model = 'gemini-live-2.5-flash-preview'; + } + const session = await ai.live.connect({ + model: model, + config: { + responseModalities: [Modality.AUDIO], + } + }); + + session.close(); + ``` + */ + close() { + this.conn.close(); + } +} +// Converts an headers object to a "map" object as expected by the WebSocket +// constructor. We use this as the Auth interface works with Headers objects +// while the WebSocket constructor takes a map. +function headersToMap(headers) { + const headerMap = {}; + headers.forEach((value, key) => { + headerMap[key] = value; + }); + return headerMap; +} +// Converts a "map" object to a headers object. We use this as the Auth +// interface works with Headers objects while the API client default headers +// returns a map. +function mapToHeaders(map) { + const headers = new Headers(); + for (const [key, value] of Object.entries(map)) { + headers.append(key, value); + } + return headers; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const DEFAULT_MAX_REMOTE_CALLS = 10; +/** Returns whether automatic function calling is disabled. */ +function shouldDisableAfc(config) { + var _a, _b, _c; + if ((_a = config === null || config === void 0 ? void 0 : config.automaticFunctionCalling) === null || _a === void 0 ? void 0 : _a.disable) { + return true; + } + let callableToolsPresent = false; + for (const tool of (_b = config === null || config === void 0 ? void 0 : config.tools) !== null && _b !== void 0 ? _b : []) { + if (isCallableTool(tool)) { + callableToolsPresent = true; + break; + } + } + if (!callableToolsPresent) { + return true; + } + const maxCalls = (_c = config === null || config === void 0 ? void 0 : config.automaticFunctionCalling) === null || _c === void 0 ? void 0 : _c.maximumRemoteCalls; + if ((maxCalls && (maxCalls < 0 || !Number.isInteger(maxCalls))) || + maxCalls == 0) { + console.warn('Invalid maximumRemoteCalls value provided for automatic function calling. Disabled automatic function calling. Please provide a valid integer value greater than 0. maximumRemoteCalls provided:', maxCalls); + return true; + } + return false; +} +function isCallableTool(tool) { + return 'callTool' in tool && typeof tool.callTool === 'function'; +} +// Checks whether the list of tools contains any CallableTools. Will return true +// if there is at least one CallableTool. +function hasCallableTools(params) { + var _a, _b, _c; + return (_c = (_b = (_a = params.config) === null || _a === void 0 ? void 0 : _a.tools) === null || _b === void 0 ? void 0 : _b.some((tool) => isCallableTool(tool))) !== null && _c !== void 0 ? _c : false; +} +/** + * Returns the indexes of the tools that are not compatible with AFC. + */ +function findAfcIncompatibleToolIndexes(params) { + var _a; + // Use number[] for an array of numbers in TypeScript + const afcIncompatibleToolIndexes = []; + if (!((_a = params === null || params === void 0 ? void 0 : params.config) === null || _a === void 0 ? void 0 : _a.tools)) { + return afcIncompatibleToolIndexes; + } + params.config.tools.forEach((tool, index) => { + if (isCallableTool(tool)) { + return; + } + const geminiTool = tool; + if (geminiTool.functionDeclarations && + geminiTool.functionDeclarations.length > 0) { + afcIncompatibleToolIndexes.push(index); + } + }); + return afcIncompatibleToolIndexes; +} +/** + * Returns whether to append automatic function calling history to the + * response. + */ +function shouldAppendAfcHistory(config) { + var _a; + return !((_a = config === null || config === void 0 ? void 0 : config.automaticFunctionCalling) === null || _a === void 0 ? void 0 : _a.ignoreCallHistory); +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Models extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + /** + * Makes an API request to generate content with a given model. + * + * For the `model` parameter, supported formats for Vertex AI API include: + * - The Gemini model ID, for example: 'gemini-2.0-flash' + * - The full resource name starts with 'projects/', for example: + * 'projects/my-project-id/locations/us-central1/publishers/google/models/gemini-2.0-flash' + * - The partial resource name with 'publishers/', for example: + * 'publishers/google/models/gemini-2.0-flash' or + * 'publishers/meta/models/llama-3.1-405b-instruct-maas' + * - `/` separated publisher and model name, for example: + * 'google/gemini-2.0-flash' or 'meta/llama-3.1-405b-instruct-maas' + * + * For the `model` parameter, supported formats for Gemini API include: + * - The Gemini model ID, for example: 'gemini-2.0-flash' + * - The model name starts with 'models/', for example: + * 'models/gemini-2.0-flash' + * - For tuned models, the model name starts with 'tunedModels/', + * for example: + * 'tunedModels/1234567890123456789' + * + * Some models support multimodal input and output. + * + * @param params - The parameters for generating content. + * @return The response from generating content. + * + * @example + * ```ts + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: 'why is the sky blue?', + * config: { + * candidateCount: 2, + * } + * }); + * console.log(response); + * ``` + */ + this.generateContent = async (params) => { + var _a, _b, _c, _d, _e; + const transformedParams = await this.processParamsMaybeAddMcpUsage(params); + this.maybeMoveToResponseJsonSchem(params); + if (!hasCallableTools(params) || shouldDisableAfc(params.config)) { + return await this.generateContentInternal(transformedParams); + } + const incompatibleToolIndexes = findAfcIncompatibleToolIndexes(params); + if (incompatibleToolIndexes.length > 0) { + const formattedIndexes = incompatibleToolIndexes + .map((index) => `tools[${index}]`) + .join(', '); + throw new Error(`Automatic function calling with CallableTools (or MCP objects) and basic FunctionDeclarations is not yet supported. Incompatible tools found at ${formattedIndexes}.`); + } + let response; + let functionResponseContent; + const automaticFunctionCallingHistory = tContents(transformedParams.contents); + const maxRemoteCalls = (_c = (_b = (_a = transformedParams.config) === null || _a === void 0 ? void 0 : _a.automaticFunctionCalling) === null || _b === void 0 ? void 0 : _b.maximumRemoteCalls) !== null && _c !== void 0 ? _c : DEFAULT_MAX_REMOTE_CALLS; + let remoteCalls = 0; + while (remoteCalls < maxRemoteCalls) { + response = await this.generateContentInternal(transformedParams); + if (!response.functionCalls || response.functionCalls.length === 0) { + break; + } + const responseContent = response.candidates[0].content; + const functionResponseParts = []; + for (const tool of (_e = (_d = params.config) === null || _d === void 0 ? void 0 : _d.tools) !== null && _e !== void 0 ? _e : []) { + if (isCallableTool(tool)) { + const callableTool = tool; + const parts = await callableTool.callTool(response.functionCalls); + functionResponseParts.push(...parts); + } + } + remoteCalls++; + functionResponseContent = { + role: 'user', + parts: functionResponseParts, + }; + transformedParams.contents = tContents(transformedParams.contents); + transformedParams.contents.push(responseContent); + transformedParams.contents.push(functionResponseContent); + if (shouldAppendAfcHistory(transformedParams.config)) { + automaticFunctionCallingHistory.push(responseContent); + automaticFunctionCallingHistory.push(functionResponseContent); + } + } + if (shouldAppendAfcHistory(transformedParams.config)) { + response.automaticFunctionCallingHistory = + automaticFunctionCallingHistory; + } + return response; + }; + /** + * Makes an API request to generate content with a given model and yields the + * response in chunks. + * + * For the `model` parameter, supported formats for Vertex AI API include: + * - The Gemini model ID, for example: 'gemini-2.0-flash' + * - The full resource name starts with 'projects/', for example: + * 'projects/my-project-id/locations/us-central1/publishers/google/models/gemini-2.0-flash' + * - The partial resource name with 'publishers/', for example: + * 'publishers/google/models/gemini-2.0-flash' or + * 'publishers/meta/models/llama-3.1-405b-instruct-maas' + * - `/` separated publisher and model name, for example: + * 'google/gemini-2.0-flash' or 'meta/llama-3.1-405b-instruct-maas' + * + * For the `model` parameter, supported formats for Gemini API include: + * - The Gemini model ID, for example: 'gemini-2.0-flash' + * - The model name starts with 'models/', for example: + * 'models/gemini-2.0-flash' + * - For tuned models, the model name starts with 'tunedModels/', + * for example: + * 'tunedModels/1234567890123456789' + * + * Some models support multimodal input and output. + * + * @param params - The parameters for generating content with streaming response. + * @return The response from generating content. + * + * @example + * ```ts + * const response = await ai.models.generateContentStream({ + * model: 'gemini-2.0-flash', + * contents: 'why is the sky blue?', + * config: { + * maxOutputTokens: 200, + * } + * }); + * for await (const chunk of response) { + * console.log(chunk); + * } + * ``` + */ + this.generateContentStream = async (params) => { + var _a, _b, _c, _d, _e; + this.maybeMoveToResponseJsonSchem(params); + if (shouldDisableAfc(params.config)) { + const transformedParams = await this.processParamsMaybeAddMcpUsage(params); + return await this.generateContentStreamInternal(transformedParams); + } + const incompatibleToolIndexes = findAfcIncompatibleToolIndexes(params); + if (incompatibleToolIndexes.length > 0) { + const formattedIndexes = incompatibleToolIndexes + .map((index) => `tools[${index}]`) + .join(', '); + throw new Error(`Incompatible tools found at ${formattedIndexes}. Automatic function calling with CallableTools (or MCP objects) and basic FunctionDeclarations" is not yet supported.`); + } + // With tool compatibility confirmed, validate that the configuration are + // compatible with each other and raise an error if invalid. + const streamFunctionCall = (_c = (_b = (_a = params === null || params === void 0 ? void 0 : params.config) === null || _a === void 0 ? void 0 : _a.toolConfig) === null || _b === void 0 ? void 0 : _b.functionCallingConfig) === null || _c === void 0 ? void 0 : _c.streamFunctionCallArguments; + const disableAfc = (_e = (_d = params === null || params === void 0 ? void 0 : params.config) === null || _d === void 0 ? void 0 : _d.automaticFunctionCalling) === null || _e === void 0 ? void 0 : _e.disable; + if (streamFunctionCall && !disableAfc) { + throw new Error("Running in streaming mode with 'streamFunctionCallArguments' enabled, " + + 'this feature is not compatible with automatic function calling (AFC). ' + + "Please set 'config.automaticFunctionCalling.disable' to true to disable AFC " + + "or leave 'config.toolConfig.functionCallingConfig.streamFunctionCallArguments' " + + 'to be undefined or set to false to disable streaming function call arguments feature.'); + } + return await this.processAfcStream(params); + }; + /** + * Generates an image based on a text description and configuration. + * + * @param params - The parameters for generating images. + * @return The response from the API. + * + * @example + * ```ts + * const response = await client.models.generateImages({ + * model: 'imagen-4.0-generate-001', + * prompt: 'Robot holding a red skateboard', + * config: { + * numberOfImages: 1, + * includeRaiReason: true, + * }, + * }); + * console.log(response?.generatedImages?.[0]?.image?.imageBytes); + * ``` + */ + this.generateImages = async (params) => { + return await this.generateImagesInternal(params).then((apiResponse) => { + var _a; + let positivePromptSafetyAttributes; + const generatedImages = []; + if (apiResponse === null || apiResponse === void 0 ? void 0 : apiResponse.generatedImages) { + for (const generatedImage of apiResponse.generatedImages) { + if (generatedImage && + (generatedImage === null || generatedImage === void 0 ? void 0 : generatedImage.safetyAttributes) && + ((_a = generatedImage === null || generatedImage === void 0 ? void 0 : generatedImage.safetyAttributes) === null || _a === void 0 ? void 0 : _a.contentType) === 'Positive Prompt') { + positivePromptSafetyAttributes = generatedImage === null || generatedImage === void 0 ? void 0 : generatedImage.safetyAttributes; + } + else { + generatedImages.push(generatedImage); + } + } + } + let response; + if (positivePromptSafetyAttributes) { + response = { + generatedImages: generatedImages, + positivePromptSafetyAttributes: positivePromptSafetyAttributes, + sdkHttpResponse: apiResponse.sdkHttpResponse, + }; + } + else { + response = { + generatedImages: generatedImages, + sdkHttpResponse: apiResponse.sdkHttpResponse, + }; + } + return response; + }); + }; + this.list = async (params) => { + var _a; + const defaultConfig = { + queryBase: true, + }; + const actualConfig = Object.assign(Object.assign({}, defaultConfig), params === null || params === void 0 ? void 0 : params.config); + const actualParams = { + config: actualConfig, + }; + if (this.apiClient.isVertexAI()) { + if (!actualParams.config.queryBase) { + if ((_a = actualParams.config) === null || _a === void 0 ? void 0 : _a.filter) { + throw new Error('Filtering tuned models list for Vertex AI is not currently supported'); + } + else { + actualParams.config.filter = 'labels.tune-type:*'; + } + } + } + return new Pager(PagedItem.PAGED_ITEM_MODELS, (x) => this.listInternal(x), await this.listInternal(actualParams), actualParams); + }; + /** + * Edits an image based on a prompt, list of reference images, and configuration. + * + * @param params - The parameters for editing an image. + * @return The response from the API. + * + * @example + * ```ts + * const response = await client.models.editImage({ + * model: 'imagen-3.0-capability-001', + * prompt: 'Generate an image containing a mug with the product logo [1] visible on the side of the mug.', + * referenceImages: [subjectReferenceImage] + * config: { + * numberOfImages: 1, + * includeRaiReason: true, + * }, + * }); + * console.log(response?.generatedImages?.[0]?.image?.imageBytes); + * ``` + */ + this.editImage = async (params) => { + const paramsInternal = { + model: params.model, + prompt: params.prompt, + referenceImages: [], + config: params.config, + }; + if (params.referenceImages) { + if (params.referenceImages) { + paramsInternal.referenceImages = params.referenceImages.map((img) => img.toReferenceImageAPI()); + } + } + return await this.editImageInternal(paramsInternal); + }; + /** + * Upscales an image based on an image, upscale factor, and configuration. + * Only supported in Vertex AI currently. + * + * @param params - The parameters for upscaling an image. + * @return The response from the API. + * + * @example + * ```ts + * const response = await client.models.upscaleImage({ + * model: 'imagen-4.0-upscale-preview', + * image: image, + * upscaleFactor: 'x2', + * config: { + * includeRaiReason: true, + * }, + * }); + * console.log(response?.generatedImages?.[0]?.image?.imageBytes); + * ``` + */ + this.upscaleImage = async (params) => { + let apiConfig = { + numberOfImages: 1, + mode: 'upscale', + }; + if (params.config) { + apiConfig = Object.assign(Object.assign({}, apiConfig), params.config); + } + const apiParams = { + model: params.model, + image: params.image, + upscaleFactor: params.upscaleFactor, + config: apiConfig, + }; + return await this.upscaleImageInternal(apiParams); + }; + /** + * Generates videos based on a text description and configuration. + * + * @param params - The parameters for generating videos. + * @return A Promise<GenerateVideosOperation> which allows you to track the progress and eventually retrieve the generated videos using the operations.get method. + * + * @example + * ```ts + * const operation = await ai.models.generateVideos({ + * model: 'veo-2.0-generate-001', + * source: { + * prompt: 'A neon hologram of a cat driving at top speed', + * }, + * config: { + * numberOfVideos: 1 + * }); + * + * while (!operation.done) { + * await new Promise(resolve => setTimeout(resolve, 10000)); + * operation = await ai.operations.getVideosOperation({operation: operation}); + * } + * + * console.log(operation.response?.generatedVideos?.[0]?.video?.uri); + * ``` + */ + this.generateVideos = async (params) => { + var _a, _b, _c, _d, _e, _f; + if ((params.prompt || params.image || params.video) && params.source) { + throw new Error('Source and prompt/image/video are mutually exclusive. Please only use source.'); + } + // Gemini API does not support video bytes. + if (!this.apiClient.isVertexAI()) { + if (((_a = params.video) === null || _a === void 0 ? void 0 : _a.uri) && ((_b = params.video) === null || _b === void 0 ? void 0 : _b.videoBytes)) { + params.video = { + uri: params.video.uri, + mimeType: params.video.mimeType, + }; + } + else if (((_d = (_c = params.source) === null || _c === void 0 ? void 0 : _c.video) === null || _d === void 0 ? void 0 : _d.uri) && + ((_f = (_e = params.source) === null || _e === void 0 ? void 0 : _e.video) === null || _f === void 0 ? void 0 : _f.videoBytes)) { + params.source.video = { + uri: params.source.video.uri, + mimeType: params.source.video.mimeType, + }; + } + } + return await this.generateVideosInternal(params); + }; + } + /** + * This logic is needed for GenerateContentConfig only. + * Previously we made GenerateContentConfig.responseSchema field to accept + * unknown. Since v1.9.0, we switch to use backend JSON schema support. + * To maintain backward compatibility, we move the data that was treated as + * JSON schema from the responseSchema field to the responseJsonSchema field. + */ + maybeMoveToResponseJsonSchem(params) { + if (params.config && params.config.responseSchema) { + if (!params.config.responseJsonSchema) { + if (Object.keys(params.config.responseSchema).includes('$schema')) { + params.config.responseJsonSchema = params.config.responseSchema; + delete params.config.responseSchema; + } + } + } + return; + } + /** + * Transforms the CallableTools in the parameters to be simply Tools, it + * copies the params into a new object and replaces the tools, it does not + * modify the original params. Also sets the MCP usage header if there are + * MCP tools in the parameters. + */ + async processParamsMaybeAddMcpUsage(params) { + var _a, _b, _c; + const tools = (_a = params.config) === null || _a === void 0 ? void 0 : _a.tools; + if (!tools) { + return params; + } + const transformedTools = await Promise.all(tools.map(async (tool) => { + if (isCallableTool(tool)) { + const callableTool = tool; + return await callableTool.tool(); + } + return tool; + })); + const newParams = { + model: params.model, + contents: params.contents, + config: Object.assign(Object.assign({}, params.config), { tools: transformedTools }), + }; + newParams.config.tools = transformedTools; + if (params.config && + params.config.tools && + hasMcpToolUsage(params.config.tools)) { + const headers = (_c = (_b = params.config.httpOptions) === null || _b === void 0 ? void 0 : _b.headers) !== null && _c !== void 0 ? _c : {}; + let newHeaders = Object.assign({}, headers); + if (Object.keys(newHeaders).length === 0) { + newHeaders = this.apiClient.getDefaultHeaders(); + } + setMcpUsageHeader(newHeaders); + newParams.config.httpOptions = Object.assign(Object.assign({}, params.config.httpOptions), { headers: newHeaders }); + } + return newParams; + } + async initAfcToolsMap(params) { + var _a, _b, _c; + const afcTools = new Map(); + for (const tool of (_b = (_a = params.config) === null || _a === void 0 ? void 0 : _a.tools) !== null && _b !== void 0 ? _b : []) { + if (isCallableTool(tool)) { + const callableTool = tool; + const toolDeclaration = await callableTool.tool(); + for (const declaration of (_c = toolDeclaration.functionDeclarations) !== null && _c !== void 0 ? _c : []) { + if (!declaration.name) { + throw new Error('Function declaration name is required.'); + } + if (afcTools.has(declaration.name)) { + throw new Error(`Duplicate tool declaration name: ${declaration.name}`); + } + afcTools.set(declaration.name, callableTool); + } + } + } + return afcTools; + } + async processAfcStream(params) { + var _a, _b, _c; + const maxRemoteCalls = (_c = (_b = (_a = params.config) === null || _a === void 0 ? void 0 : _a.automaticFunctionCalling) === null || _b === void 0 ? void 0 : _b.maximumRemoteCalls) !== null && _c !== void 0 ? _c : DEFAULT_MAX_REMOTE_CALLS; + let wereFunctionsCalled = false; + let remoteCallCount = 0; + const afcToolsMap = await this.initAfcToolsMap(params); + return (function (models, afcTools, params) { + return __asyncGenerator(this, arguments, function* () { + var _a, e_1, _b, _c; + var _d, _e; + while (remoteCallCount < maxRemoteCalls) { + if (wereFunctionsCalled) { + remoteCallCount++; + wereFunctionsCalled = false; + } + const transformedParams = yield __await(models.processParamsMaybeAddMcpUsage(params)); + const response = yield __await(models.generateContentStreamInternal(transformedParams)); + const functionResponses = []; + const responseContents = []; + try { + for (var _f = true, response_1 = (e_1 = void 0, __asyncValues(response)), response_1_1; response_1_1 = yield __await(response_1.next()), _a = response_1_1.done, !_a; _f = true) { + _c = response_1_1.value; + _f = false; + const chunk = _c; + yield yield __await(chunk); + if (chunk.candidates && ((_d = chunk.candidates[0]) === null || _d === void 0 ? void 0 : _d.content)) { + responseContents.push(chunk.candidates[0].content); + for (const part of (_e = chunk.candidates[0].content.parts) !== null && _e !== void 0 ? _e : []) { + if (remoteCallCount < maxRemoteCalls && part.functionCall) { + if (!part.functionCall.name) { + throw new Error('Function call name was not returned by the model.'); + } + if (!afcTools.has(part.functionCall.name)) { + throw new Error(`Automatic function calling was requested, but not all the tools the model used implement the CallableTool interface. Available tools: ${afcTools.keys()}, mising tool: ${part.functionCall.name}`); + } + else { + const responseParts = yield __await(afcTools + .get(part.functionCall.name) + .callTool([part.functionCall])); + functionResponses.push(...responseParts); + } + } + } + } + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (!_f && !_a && (_b = response_1.return)) yield __await(_b.call(response_1)); + } + finally { if (e_1) throw e_1.error; } + } + if (functionResponses.length > 0) { + wereFunctionsCalled = true; + const typedResponseChunk = new GenerateContentResponse(); + typedResponseChunk.candidates = [ + { + content: { + role: 'user', + parts: functionResponses, + }, + }, + ]; + yield yield __await(typedResponseChunk); + const newContents = []; + newContents.push(...responseContents); + newContents.push({ + role: 'user', + parts: functionResponses, + }); + const updatedContents = tContents(params.contents).concat(newContents); + params.contents = updatedContents; + } + else { + break; + } + } + }); + })(this, afcToolsMap, params); + } + async generateContentInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = generateContentParametersToVertex(this.apiClient, params); + path = formatMap('{model}:generateContent', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = generateContentResponseFromVertex(apiResponse); + const typedResp = new GenerateContentResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = generateContentParametersToMldev(this.apiClient, params); + path = formatMap('{model}:generateContent', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = generateContentResponseFromMldev(apiResponse); + const typedResp = new GenerateContentResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + async generateContentStreamInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = generateContentParametersToVertex(this.apiClient, params); + path = formatMap('{model}:streamGenerateContent?alt=sse', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + const apiClient = this.apiClient; + response = apiClient.requestStream({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }); + return response.then(function (apiResponse) { + return __asyncGenerator(this, arguments, function* () { + var _a, e_2, _b, _c; + try { + for (var _d = true, apiResponse_1 = __asyncValues(apiResponse), apiResponse_1_1; apiResponse_1_1 = yield __await(apiResponse_1.next()), _a = apiResponse_1_1.done, !_a; _d = true) { + _c = apiResponse_1_1.value; + _d = false; + const chunk = _c; + const resp = generateContentResponseFromVertex((yield __await(chunk.json())), params); + resp['sdkHttpResponse'] = { + headers: chunk.headers, + }; + const typedResp = new GenerateContentResponse(); + Object.assign(typedResp, resp); + yield yield __await(typedResp); + } + } + catch (e_2_1) { e_2 = { error: e_2_1 }; } + finally { + try { + if (!_d && !_a && (_b = apiResponse_1.return)) yield __await(_b.call(apiResponse_1)); + } + finally { if (e_2) throw e_2.error; } + } + }); + }); + } + else { + const body = generateContentParametersToMldev(this.apiClient, params); + path = formatMap('{model}:streamGenerateContent?alt=sse', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + const apiClient = this.apiClient; + response = apiClient.requestStream({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }); + return response.then(function (apiResponse) { + return __asyncGenerator(this, arguments, function* () { + var _a, e_3, _b, _c; + try { + for (var _d = true, apiResponse_2 = __asyncValues(apiResponse), apiResponse_2_1; apiResponse_2_1 = yield __await(apiResponse_2.next()), _a = apiResponse_2_1.done, !_a; _d = true) { + _c = apiResponse_2_1.value; + _d = false; + const chunk = _c; + const resp = generateContentResponseFromMldev((yield __await(chunk.json())), params); + resp['sdkHttpResponse'] = { + headers: chunk.headers, + }; + const typedResp = new GenerateContentResponse(); + Object.assign(typedResp, resp); + yield yield __await(typedResp); + } + } + catch (e_3_1) { e_3 = { error: e_3_1 }; } + finally { + try { + if (!_d && !_a && (_b = apiResponse_2.return)) yield __await(_b.call(apiResponse_2)); + } + finally { if (e_3) throw e_3.error; } + } + }); + }); + } + } + /** + * Calculates embeddings for the given contents. Only text is supported. + * + * @param params - The parameters for embedding contents. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.embedContent({ + * model: 'text-embedding-004', + * contents: [ + * 'What is your name?', + * 'What is your favorite color?', + * ], + * config: { + * outputDimensionality: 64, + * }, + * }); + * console.log(response); + * ``` + */ + async embedContent(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = embedContentParametersToVertex(this.apiClient, params); + path = formatMap('{model}:predict', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = embedContentResponseFromVertex(apiResponse); + const typedResp = new EmbedContentResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = embedContentParametersToMldev(this.apiClient, params); + path = formatMap('{model}:batchEmbedContents', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = embedContentResponseFromMldev(apiResponse); + const typedResp = new EmbedContentResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Private method for generating images. + */ + async generateImagesInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = generateImagesParametersToVertex(this.apiClient, params); + path = formatMap('{model}:predict', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = generateImagesResponseFromVertex(apiResponse); + const typedResp = new GenerateImagesResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = generateImagesParametersToMldev(this.apiClient, params); + path = formatMap('{model}:predict', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = generateImagesResponseFromMldev(apiResponse); + const typedResp = new GenerateImagesResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Private method for editing an image. + */ + async editImageInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = editImageParametersInternalToVertex(this.apiClient, params); + path = formatMap('{model}:predict', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = editImageResponseFromVertex(apiResponse); + const typedResp = new EditImageResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + throw new Error('This method is only supported by the Vertex AI.'); + } + } + /** + * Private method for upscaling an image. + */ + async upscaleImageInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = upscaleImageAPIParametersInternalToVertex(this.apiClient, params); + path = formatMap('{model}:predict', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = upscaleImageResponseFromVertex(apiResponse); + const typedResp = new UpscaleImageResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + throw new Error('This method is only supported by the Vertex AI.'); + } + } + /** + * Recontextualizes an image. + * + * There are two types of recontextualization currently supported: + * 1) Imagen Product Recontext - Generate images of products in new scenes + * and contexts. + * 2) Virtual Try-On: Generate images of persons modeling fashion products. + * + * @param params - The parameters for recontextualizing an image. + * @return The response from the API. + * + * @example + * ```ts + * const response1 = await ai.models.recontextImage({ + * model: 'imagen-product-recontext-preview-06-30', + * source: { + * prompt: 'In a modern kitchen setting.', + * productImages: [productImage], + * }, + * config: { + * numberOfImages: 1, + * }, + * }); + * console.log(response1?.generatedImages?.[0]?.image?.imageBytes); + * + * const response2 = await ai.models.recontextImage({ + * model: 'virtual-try-on-001', + * source: { + * personImage: personImage, + * productImages: [productImage], + * }, + * config: { + * numberOfImages: 1, + * }, + * }); + * console.log(response2?.generatedImages?.[0]?.image?.imageBytes); + * ``` + */ + async recontextImage(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = recontextImageParametersToVertex(this.apiClient, params); + path = formatMap('{model}:predict', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = recontextImageResponseFromVertex(apiResponse); + const typedResp = new RecontextImageResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + throw new Error('This method is only supported by the Vertex AI.'); + } + } + /** + * Segments an image, creating a mask of a specified area. + * + * @param params - The parameters for segmenting an image. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.segmentImage({ + * model: 'image-segmentation-001', + * source: { + * image: image, + * }, + * config: { + * mode: 'foreground', + * }, + * }); + * console.log(response?.generatedMasks?.[0]?.mask?.imageBytes); + * ``` + */ + async segmentImage(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = segmentImageParametersToVertex(this.apiClient, params); + path = formatMap('{model}:predict', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = segmentImageResponseFromVertex(apiResponse); + const typedResp = new SegmentImageResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + throw new Error('This method is only supported by the Vertex AI.'); + } + } + /** + * Fetches information about a model by name. + * + * @example + * ```ts + * const modelInfo = await ai.models.get({model: 'gemini-2.0-flash'}); + * ``` + */ + async get(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = getModelParametersToVertex(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = modelFromVertex(apiResponse); + return resp; + }); + } + else { + const body = getModelParametersToMldev(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = modelFromMldev(apiResponse); + return resp; + }); + } + } + async listInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = listModelsParametersToVertex(this.apiClient, params); + path = formatMap('{models_url}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listModelsResponseFromVertex(apiResponse); + const typedResp = new ListModelsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = listModelsParametersToMldev(this.apiClient, params); + path = formatMap('{models_url}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listModelsResponseFromMldev(apiResponse); + const typedResp = new ListModelsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Updates a tuned model by its name. + * + * @param params - The parameters for updating the model. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.update({ + * model: 'tuned-model-name', + * config: { + * displayName: 'New display name', + * description: 'New description', + * }, + * }); + * ``` + */ + async update(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = updateModelParametersToVertex(this.apiClient, params); + path = formatMap('{model}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'PATCH', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = modelFromVertex(apiResponse); + return resp; + }); + } + else { + const body = updateModelParametersToMldev(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'PATCH', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = modelFromMldev(apiResponse); + return resp; + }); + } + } + /** + * Deletes a tuned model by its name. + * + * @param params - The parameters for deleting the model. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.delete({model: 'tuned-model-name'}); + * ``` + */ + async delete(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = deleteModelParametersToVertex(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = deleteModelResponseFromVertex(apiResponse); + const typedResp = new DeleteModelResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = deleteModelParametersToMldev(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = deleteModelResponseFromMldev(apiResponse); + const typedResp = new DeleteModelResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Counts the number of tokens in the given contents. Multimodal input is + * supported for Gemini models. + * + * @param params - The parameters for counting tokens. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.countTokens({ + * model: 'gemini-2.0-flash', + * contents: 'The quick brown fox jumps over the lazy dog.' + * }); + * console.log(response); + * ``` + */ + async countTokens(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = countTokensParametersToVertex(this.apiClient, params); + path = formatMap('{model}:countTokens', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = countTokensResponseFromVertex(apiResponse); + const typedResp = new CountTokensResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = countTokensParametersToMldev(this.apiClient, params); + path = formatMap('{model}:countTokens', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = countTokensResponseFromMldev(apiResponse); + const typedResp = new CountTokensResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Given a list of contents, returns a corresponding TokensInfo containing + * the list of tokens and list of token ids. + * + * This method is not supported by the Gemini Developer API. + * + * @param params - The parameters for computing tokens. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.computeTokens({ + * model: 'gemini-2.0-flash', + * contents: 'What is your name?' + * }); + * console.log(response); + * ``` + */ + async computeTokens(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = computeTokensParametersToVertex(this.apiClient, params); + path = formatMap('{model}:computeTokens', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = computeTokensResponseFromVertex(apiResponse); + const typedResp = new ComputeTokensResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + throw new Error('This method is only supported by the Vertex AI.'); + } + } + /** + * Private method for generating videos. + */ + async generateVideosInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = generateVideosParametersToVertex(this.apiClient, params); + path = formatMap('{model}:predictLongRunning', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = generateVideosOperationFromVertex(apiResponse); + const typedResp = new GenerateVideosOperation(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = generateVideosParametersToMldev(this.apiClient, params); + path = formatMap('{model}:predictLongRunning', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = generateVideosOperationFromMldev(apiResponse); + const typedResp = new GenerateVideosOperation(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Operations extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + } + /** + * Gets the status of a long-running operation. + * + * @param parameters The parameters for the get operation request. + * @return The updated Operation object, with the latest status or result. + */ + async getVideosOperation(parameters) { + const operation = parameters.operation; + const config = parameters.config; + if (operation.name === undefined || operation.name === '') { + throw new Error('Operation name is required.'); + } + if (this.apiClient.isVertexAI()) { + const resourceName = operation.name.split('/operations/')[0]; + let httpOptions = undefined; + if (config && 'httpOptions' in config) { + httpOptions = config.httpOptions; + } + const rawOperation = await this.fetchPredictVideosOperationInternal({ + operationName: operation.name, + resourceName: resourceName, + config: { httpOptions: httpOptions }, + }); + return operation._fromAPIResponse({ + apiResponse: rawOperation, + _isVertexAI: true, + }); + } + else { + const rawOperation = await this.getVideosOperationInternal({ + operationName: operation.name, + config: config, + }); + return operation._fromAPIResponse({ + apiResponse: rawOperation, + _isVertexAI: false, + }); + } + } + /** + * Gets the status of a long-running operation. + * + * @param parameters The parameters for the get operation request. + * @return The updated Operation object, with the latest status or result. + */ + async get(parameters) { + const operation = parameters.operation; + const config = parameters.config; + if (operation.name === undefined || operation.name === '') { + throw new Error('Operation name is required.'); + } + if (this.apiClient.isVertexAI()) { + const resourceName = operation.name.split('/operations/')[0]; + let httpOptions = undefined; + if (config && 'httpOptions' in config) { + httpOptions = config.httpOptions; + } + const rawOperation = await this.fetchPredictVideosOperationInternal({ + operationName: operation.name, + resourceName: resourceName, + config: { httpOptions: httpOptions }, + }); + return operation._fromAPIResponse({ + apiResponse: rawOperation, + _isVertexAI: true, + }); + } + else { + const rawOperation = await this.getVideosOperationInternal({ + operationName: operation.name, + config: config, + }); + return operation._fromAPIResponse({ + apiResponse: rawOperation, + _isVertexAI: false, + }); + } + } + async getVideosOperationInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = getOperationParametersToVertex(params); + path = formatMap('{operationName}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response; + } + else { + const body = getOperationParametersToMldev(params); + path = formatMap('{operationName}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response; + } + } + async fetchPredictVideosOperationInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = fetchPredictOperationParametersToVertex(params); + path = formatMap('{resourceName}:fetchPredictOperation', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response; + } + else { + throw new Error('This method is only supported by the Vertex AI.'); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function blobToMldev(fromObject) { + const toObject = {}; + const fromData = getValueByPath(fromObject, ['data']); + if (fromData != null) { + setValueByPath(toObject, ['data'], fromData); + } + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function contentToMldev(fromObject) { + const toObject = {}; + const fromParts = getValueByPath(fromObject, ['parts']); + if (fromParts != null) { + let transformedList = fromParts; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return partToMldev(item); + }); + } + setValueByPath(toObject, ['parts'], transformedList); + } + const fromRole = getValueByPath(fromObject, ['role']); + if (fromRole != null) { + setValueByPath(toObject, ['role'], fromRole); + } + return toObject; +} +function createAuthTokenConfigToMldev(apiClient, fromObject, parentObject) { + const toObject = {}; + const fromExpireTime = getValueByPath(fromObject, ['expireTime']); + if (parentObject !== undefined && fromExpireTime != null) { + setValueByPath(parentObject, ['expireTime'], fromExpireTime); + } + const fromNewSessionExpireTime = getValueByPath(fromObject, [ + 'newSessionExpireTime', + ]); + if (parentObject !== undefined && fromNewSessionExpireTime != null) { + setValueByPath(parentObject, ['newSessionExpireTime'], fromNewSessionExpireTime); + } + const fromUses = getValueByPath(fromObject, ['uses']); + if (parentObject !== undefined && fromUses != null) { + setValueByPath(parentObject, ['uses'], fromUses); + } + const fromLiveConnectConstraints = getValueByPath(fromObject, [ + 'liveConnectConstraints', + ]); + if (parentObject !== undefined && fromLiveConnectConstraints != null) { + setValueByPath(parentObject, ['bidiGenerateContentSetup'], liveConnectConstraintsToMldev(apiClient, fromLiveConnectConstraints)); + } + const fromLockAdditionalFields = getValueByPath(fromObject, [ + 'lockAdditionalFields', + ]); + if (parentObject !== undefined && fromLockAdditionalFields != null) { + setValueByPath(parentObject, ['fieldMask'], fromLockAdditionalFields); + } + return toObject; +} +function createAuthTokenParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['config'], createAuthTokenConfigToMldev(apiClient, fromConfig, toObject)); + } + return toObject; +} +function fileDataToMldev(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromFileUri = getValueByPath(fromObject, ['fileUri']); + if (fromFileUri != null) { + setValueByPath(toObject, ['fileUri'], fromFileUri); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function functionCallToMldev(fromObject) { + const toObject = {}; + const fromId = getValueByPath(fromObject, ['id']); + if (fromId != null) { + setValueByPath(toObject, ['id'], fromId); + } + const fromArgs = getValueByPath(fromObject, ['args']); + if (fromArgs != null) { + setValueByPath(toObject, ['args'], fromArgs); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + if (getValueByPath(fromObject, ['partialArgs']) !== undefined) { + throw new Error('partialArgs parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['willContinue']) !== undefined) { + throw new Error('willContinue parameter is not supported in Gemini API.'); + } + return toObject; +} +function googleMapsToMldev(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['authConfig']) !== undefined) { + throw new Error('authConfig parameter is not supported in Gemini API.'); + } + const fromEnableWidget = getValueByPath(fromObject, ['enableWidget']); + if (fromEnableWidget != null) { + setValueByPath(toObject, ['enableWidget'], fromEnableWidget); + } + return toObject; +} +function googleSearchToMldev(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['excludeDomains']) !== undefined) { + throw new Error('excludeDomains parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['blockingConfidence']) !== undefined) { + throw new Error('blockingConfidence parameter is not supported in Gemini API.'); + } + const fromTimeRangeFilter = getValueByPath(fromObject, [ + 'timeRangeFilter', + ]); + if (fromTimeRangeFilter != null) { + setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter); + } + return toObject; +} +function liveConnectConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromGenerationConfig = getValueByPath(fromObject, [ + 'generationConfig', + ]); + if (parentObject !== undefined && fromGenerationConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig'], fromGenerationConfig); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (parentObject !== undefined && fromResponseModalities != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'responseModalities'], fromResponseModalities); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (parentObject !== undefined && fromTemperature != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'temperature'], fromTemperature); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (parentObject !== undefined && fromTopP != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'topP'], fromTopP); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (parentObject !== undefined && fromTopK != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'topK'], fromTopK); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (parentObject !== undefined && fromMaxOutputTokens != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'maxOutputTokens'], fromMaxOutputTokens); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (parentObject !== undefined && fromMediaResolution != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'mediaResolution'], fromMediaResolution); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (parentObject !== undefined && fromSeed != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'seed'], fromSeed); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (parentObject !== undefined && fromSpeechConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'speechConfig'], tLiveSpeechConfig(fromSpeechConfig)); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (parentObject !== undefined && fromThinkingConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'thinkingConfig'], fromThinkingConfig); + } + const fromEnableAffectiveDialog = getValueByPath(fromObject, [ + 'enableAffectiveDialog', + ]); + if (parentObject !== undefined && fromEnableAffectiveDialog != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'enableAffectiveDialog'], fromEnableAffectiveDialog); + } + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['setup', 'systemInstruction'], contentToMldev(tContent(fromSystemInstruction))); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = tTools(fromTools); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToMldev(tTool(item)); + }); + } + setValueByPath(parentObject, ['setup', 'tools'], transformedList); + } + const fromSessionResumption = getValueByPath(fromObject, [ + 'sessionResumption', + ]); + if (parentObject !== undefined && fromSessionResumption != null) { + setValueByPath(parentObject, ['setup', 'sessionResumption'], sessionResumptionConfigToMldev(fromSessionResumption)); + } + const fromInputAudioTranscription = getValueByPath(fromObject, [ + 'inputAudioTranscription', + ]); + if (parentObject !== undefined && fromInputAudioTranscription != null) { + setValueByPath(parentObject, ['setup', 'inputAudioTranscription'], fromInputAudioTranscription); + } + const fromOutputAudioTranscription = getValueByPath(fromObject, [ + 'outputAudioTranscription', + ]); + if (parentObject !== undefined && fromOutputAudioTranscription != null) { + setValueByPath(parentObject, ['setup', 'outputAudioTranscription'], fromOutputAudioTranscription); + } + const fromRealtimeInputConfig = getValueByPath(fromObject, [ + 'realtimeInputConfig', + ]); + if (parentObject !== undefined && fromRealtimeInputConfig != null) { + setValueByPath(parentObject, ['setup', 'realtimeInputConfig'], fromRealtimeInputConfig); + } + const fromContextWindowCompression = getValueByPath(fromObject, [ + 'contextWindowCompression', + ]); + if (parentObject !== undefined && fromContextWindowCompression != null) { + setValueByPath(parentObject, ['setup', 'contextWindowCompression'], fromContextWindowCompression); + } + const fromProactivity = getValueByPath(fromObject, ['proactivity']); + if (parentObject !== undefined && fromProactivity != null) { + setValueByPath(parentObject, ['setup', 'proactivity'], fromProactivity); + } + if (getValueByPath(fromObject, ['explicitVadSignal']) !== undefined) { + throw new Error('explicitVadSignal parameter is not supported in Gemini API.'); + } + return toObject; +} +function liveConnectConstraintsToMldev(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['setup', 'model'], tModel(apiClient, fromModel)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['config'], liveConnectConfigToMldev(fromConfig, toObject)); + } + return toObject; +} +function partToMldev(fromObject) { + const toObject = {}; + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromCodeExecutionResult = getValueByPath(fromObject, [ + 'codeExecutionResult', + ]); + if (fromCodeExecutionResult != null) { + setValueByPath(toObject, ['codeExecutionResult'], fromCodeExecutionResult); + } + const fromExecutableCode = getValueByPath(fromObject, [ + 'executableCode', + ]); + if (fromExecutableCode != null) { + setValueByPath(toObject, ['executableCode'], fromExecutableCode); + } + const fromFileData = getValueByPath(fromObject, ['fileData']); + if (fromFileData != null) { + setValueByPath(toObject, ['fileData'], fileDataToMldev(fromFileData)); + } + const fromFunctionCall = getValueByPath(fromObject, ['functionCall']); + if (fromFunctionCall != null) { + setValueByPath(toObject, ['functionCall'], functionCallToMldev(fromFunctionCall)); + } + const fromFunctionResponse = getValueByPath(fromObject, [ + 'functionResponse', + ]); + if (fromFunctionResponse != null) { + setValueByPath(toObject, ['functionResponse'], fromFunctionResponse); + } + const fromInlineData = getValueByPath(fromObject, ['inlineData']); + if (fromInlineData != null) { + setValueByPath(toObject, ['inlineData'], blobToMldev(fromInlineData)); + } + const fromText = getValueByPath(fromObject, ['text']); + if (fromText != null) { + setValueByPath(toObject, ['text'], fromText); + } + const fromThought = getValueByPath(fromObject, ['thought']); + if (fromThought != null) { + setValueByPath(toObject, ['thought'], fromThought); + } + const fromThoughtSignature = getValueByPath(fromObject, [ + 'thoughtSignature', + ]); + if (fromThoughtSignature != null) { + setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature); + } + const fromVideoMetadata = getValueByPath(fromObject, [ + 'videoMetadata', + ]); + if (fromVideoMetadata != null) { + setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata); + } + return toObject; +} +function sessionResumptionConfigToMldev(fromObject) { + const toObject = {}; + const fromHandle = getValueByPath(fromObject, ['handle']); + if (fromHandle != null) { + setValueByPath(toObject, ['handle'], fromHandle); + } + if (getValueByPath(fromObject, ['transparent']) !== undefined) { + throw new Error('transparent parameter is not supported in Gemini API.'); + } + return toObject; +} +function toolToMldev(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['retrieval']) !== undefined) { + throw new Error('retrieval parameter is not supported in Gemini API.'); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + const fromFileSearch = getValueByPath(fromObject, ['fileSearch']); + if (fromFileSearch != null) { + setValueByPath(toObject, ['fileSearch'], fromFileSearch); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + if (getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined) { + throw new Error('enterpriseWebSearch parameter is not supported in Gemini API.'); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], googleMapsToMldev(fromGoogleMaps)); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], googleSearchToMldev(fromGoogleSearch)); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Returns a comma-separated list of field masks from a given object. + * + * @param setup The object to extract field masks from. + * @return A comma-separated list of field masks. + */ +function getFieldMasks(setup) { + const fields = []; + for (const key in setup) { + if (Object.prototype.hasOwnProperty.call(setup, key)) { + const value = setup[key]; + // 2nd layer, recursively get field masks see TODO(b/418290100) + if (typeof value === 'object' && + value != null && + Object.keys(value).length > 0) { + const field = Object.keys(value).map((kk) => `${key}.${kk}`); + fields.push(...field); + } + else { + fields.push(key); // 1st layer + } + } + } + return fields.join(','); +} +/** + * Converts bidiGenerateContentSetup. + * @param requestDict - The request dictionary. + * @param config - The configuration object. + * @return - The modified request dictionary. + */ +function convertBidiSetupToTokenSetup(requestDict, config) { + // Convert bidiGenerateContentSetup from bidiGenerateContentSetup.setup. + let setupForMaskGeneration = null; + const bidiGenerateContentSetupValue = requestDict['bidiGenerateContentSetup']; + if (typeof bidiGenerateContentSetupValue === 'object' && + bidiGenerateContentSetupValue !== null && + 'setup' in bidiGenerateContentSetupValue) { + // Now we know bidiGenerateContentSetupValue is an object and has a 'setup' + // property. + const innerSetup = bidiGenerateContentSetupValue + .setup; + if (typeof innerSetup === 'object' && innerSetup !== null) { + // Valid inner setup found. + requestDict['bidiGenerateContentSetup'] = innerSetup; + setupForMaskGeneration = innerSetup; + } + else { + // `bidiGenerateContentSetupValue.setup` is not a valid object; treat as + // if bidiGenerateContentSetup is invalid. + delete requestDict['bidiGenerateContentSetup']; + } + } + else if (bidiGenerateContentSetupValue !== undefined) { + // `bidiGenerateContentSetup` exists but not in the expected + // shape {setup: {...}}; treat as invalid. + delete requestDict['bidiGenerateContentSetup']; + } + const preExistingFieldMask = requestDict['fieldMask']; + // Handle mask generation setup. + if (setupForMaskGeneration) { + const generatedMaskFromBidi = getFieldMasks(setupForMaskGeneration); + if (Array.isArray(config === null || config === void 0 ? void 0 : config.lockAdditionalFields) && + (config === null || config === void 0 ? void 0 : config.lockAdditionalFields.length) === 0) { + // Case 1: lockAdditionalFields is an empty array. Lock only fields from + // bidi setup. + if (generatedMaskFromBidi) { + // Only assign if mask is not empty + requestDict['fieldMask'] = generatedMaskFromBidi; + } + else { + delete requestDict['fieldMask']; // If mask is empty, effectively no + // specific fields locked by bidi + } + } + else if ((config === null || config === void 0 ? void 0 : config.lockAdditionalFields) && + config.lockAdditionalFields.length > 0 && + preExistingFieldMask !== null && + Array.isArray(preExistingFieldMask) && + preExistingFieldMask.length > 0) { + // Case 2: Lock fields from bidi setup + additional fields + // (preExistingFieldMask). + const generationConfigFields = [ + 'temperature', + 'topK', + 'topP', + 'maxOutputTokens', + 'responseModalities', + 'seed', + 'speechConfig', + ]; + let mappedFieldsFromPreExisting = []; + if (preExistingFieldMask.length > 0) { + mappedFieldsFromPreExisting = preExistingFieldMask.map((field) => { + if (generationConfigFields.includes(field)) { + return `generationConfig.${field}`; + } + return field; // Keep original field name if not in + // generationConfigFields + }); + } + const finalMaskParts = []; + if (generatedMaskFromBidi) { + finalMaskParts.push(generatedMaskFromBidi); + } + if (mappedFieldsFromPreExisting.length > 0) { + finalMaskParts.push(...mappedFieldsFromPreExisting); + } + if (finalMaskParts.length > 0) { + requestDict['fieldMask'] = finalMaskParts.join(','); + } + else { + // If no fields from bidi and no valid additional fields from + // pre-existing mask. + delete requestDict['fieldMask']; + } + } + else { + // Case 3: "Lock all fields" (meaning, don't send a field_mask, let server + // defaults apply or all are mutable). This is hit if: + // - `config.lockAdditionalFields` is undefined. + // - `config.lockAdditionalFields` is non-empty, BUT + // `preExistingFieldMask` is null, not a string, or an empty string. + delete requestDict['fieldMask']; + } + } + else { + // No valid `bidiGenerateContentSetup` was found or extracted. + // "Lock additional null fields if any". + if (preExistingFieldMask !== null && + Array.isArray(preExistingFieldMask) && + preExistingFieldMask.length > 0) { + // If there's a pre-existing field mask, it's a string, and it's not + // empty, then we should lock all fields. + requestDict['fieldMask'] = preExistingFieldMask.join(','); + } + else { + delete requestDict['fieldMask']; + } + } + return requestDict; +} +class Tokens extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + } + /** + * Creates an ephemeral auth token resource. + * + * @experimental + * + * @remarks + * Ephemeral auth tokens is only supported in the Gemini Developer API. + * It can be used for the session connection to the Live constrained API. + * Support in v1alpha only. + * + * @param params - The parameters for the create request. + * @return The created auth token. + * + * @example + * ```ts + * const ai = new GoogleGenAI({ + * apiKey: token.name, + * httpOptions: { apiVersion: 'v1alpha' } // Support in v1alpha only. + * }); + * + * // Case 1: If LiveEphemeralParameters is unset, unlock LiveConnectConfig + * // when using the token in Live API sessions. Each session connection can + * // use a different configuration. + * const config: CreateAuthTokenConfig = { + * uses: 3, + * expireTime: '2025-05-01T00:00:00Z', + * } + * const token = await ai.tokens.create(config); + * + * // Case 2: If LiveEphemeralParameters is set, lock all fields in + * // LiveConnectConfig when using the token in Live API sessions. For + * // example, changing `outputAudioTranscription` in the Live API + * // connection will be ignored by the API. + * const config: CreateAuthTokenConfig = + * uses: 3, + * expireTime: '2025-05-01T00:00:00Z', + * LiveEphemeralParameters: { + * model: 'gemini-2.0-flash-001', + * config: { + * 'responseModalities': ['AUDIO'], + * 'systemInstruction': 'Always answer in English.', + * } + * } + * } + * const token = await ai.tokens.create(config); + * + * // Case 3: If LiveEphemeralParameters is set and lockAdditionalFields is + * // set, lock LiveConnectConfig with set and additional fields (e.g. + * // responseModalities, systemInstruction, temperature in this example) when + * // using the token in Live API sessions. + * const config: CreateAuthTokenConfig = + * uses: 3, + * expireTime: '2025-05-01T00:00:00Z', + * LiveEphemeralParameters: { + * model: 'gemini-2.0-flash-001', + * config: { + * 'responseModalities': ['AUDIO'], + * 'systemInstruction': 'Always answer in English.', + * } + * }, + * lockAdditionalFields: ['temperature'], + * } + * const token = await ai.tokens.create(config); + * + * // Case 4: If LiveEphemeralParameters is set and lockAdditionalFields is + * // empty array, lock LiveConnectConfig with set fields (e.g. + * // responseModalities, systemInstruction in this example) when using the + * // token in Live API sessions. + * const config: CreateAuthTokenConfig = + * uses: 3, + * expireTime: '2025-05-01T00:00:00Z', + * LiveEphemeralParameters: { + * model: 'gemini-2.0-flash-001', + * config: { + * 'responseModalities': ['AUDIO'], + * 'systemInstruction': 'Always answer in English.', + * } + * }, + * lockAdditionalFields: [], + * } + * const token = await ai.tokens.create(config); + * ``` + */ + async create(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('The client.tokens.create method is only supported by the Gemini Developer API.'); + } + else { + const body = createAuthTokenParametersToMldev(this.apiClient, params); + path = formatMap('auth_tokens', body['_url']); + queryParams = body['_query']; + delete body['config']; + delete body['_url']; + delete body['_query']; + const transformedBody = convertBidiSetupToTokenSetup(body, params.config); + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(transformedBody), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Code generated by the Google Gen AI SDK generator DO NOT EDIT. +function deleteDocumentConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromForce = getValueByPath(fromObject, ['force']); + if (parentObject !== undefined && fromForce != null) { + setValueByPath(parentObject, ['_query', 'force'], fromForce); + } + return toObject; +} +function deleteDocumentParametersToMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + deleteDocumentConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function getDocumentParametersToMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + return toObject; +} +function listDocumentsConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + return toObject; +} +function listDocumentsParametersToMldev(fromObject) { + const toObject = {}; + const fromParent = getValueByPath(fromObject, ['parent']); + if (fromParent != null) { + setValueByPath(toObject, ['_url', 'parent'], fromParent); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listDocumentsConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function listDocumentsResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromDocuments = getValueByPath(fromObject, ['documents']); + if (fromDocuments != null) { + let transformedList = fromDocuments; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['documents'], transformedList); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Documents extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + /** + * Lists documents. + * + * @param params - The parameters for the list request. + * @return - A pager of documents. + * + * @example + * ```ts + * const documents = await ai.documents.list({parent:'rag_store_name', config: {'pageSize': 2}}); + * for await (const document of documents) { + * console.log(document); + * } + * ``` + */ + this.list = async (params) => { + return new Pager(PagedItem.PAGED_ITEM_DOCUMENTS, (x) => this.listInternal({ parent: params.parent, config: x.config }), await this.listInternal(params), params); + }; + } + /** + * Gets a Document. + * + * @param params - The parameters for getting a document. + * @return Document. + */ + async get(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = getDocumentParametersToMldev(params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } + /** + * Deletes a Document. + * + * @param params - The parameters for deleting a document. + */ + async delete(params) { + var _a, _b; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = deleteDocumentParametersToMldev(params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + await this.apiClient.request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }); + } + } + async listInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = listDocumentsParametersToMldev(params); + path = formatMap('{parent}/documents', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = listDocumentsResponseFromMldev(apiResponse); + const typedResp = new ListDocumentsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class FileSearchStores extends BaseModule { + constructor(apiClient, documents = new Documents(apiClient)) { + super(); + this.apiClient = apiClient; + this.documents = documents; + /** + * Lists file search stores. + * + * @param params - The parameters for the list request. + * @return - A pager of file search stores. + * + * @example + * ```ts + * const fileSearchStores = await ai.fileSearchStores.list({config: {'pageSize': 2}}); + * for await (const fileSearchStore of fileSearchStores) { + * console.log(fileSearchStore); + * } + * ``` + */ + this.list = async (params = {}) => { + return new Pager(PagedItem.PAGED_ITEM_FILE_SEARCH_STORES, (x) => this.listInternal(x), await this.listInternal(params), params); + }; + } + /** + * Uploads a file asynchronously to a given File Search Store. + * This method is not available in Vertex AI. + * Supported upload sources: + * - Node.js: File path (string) or Blob object. + * - Browser: Blob object (e.g., File). + * + * @remarks + * The `mimeType` can be specified in the `config` parameter. If omitted: + * - For file path (string) inputs, the `mimeType` will be inferred from the + * file extension. + * - For Blob object inputs, the `mimeType` will be set to the Blob's `type` + * property. + * + * This section can contain multiple paragraphs and code examples. + * + * @param params - Optional parameters specified in the + * `types.UploadToFileSearchStoreParameters` interface. + * @see {@link types.UploadToFileSearchStoreParameters#config} for the optional + * config in the parameters. + * @return A promise that resolves to a long running operation. + * @throws An error if called on a Vertex AI client. + * @throws An error if the `mimeType` is not provided and can not be inferred, + * the `mimeType` can be provided in the `params.config` parameter. + * @throws An error occurs if a suitable upload location cannot be established. + * + * @example + * The following code uploads a file to a given file search store. + * + * ```ts + * const operation = await ai.fileSearchStores.upload({fileSearchStoreName: 'fileSearchStores/foo-bar', file: 'file.txt', config: { + * mimeType: 'text/plain', + * }}); + * console.log(operation.name); + * ``` + */ + async uploadToFileSearchStore(params) { + if (this.apiClient.isVertexAI()) { + throw new Error('Vertex AI does not support uploading files to a file search store.'); + } + return this.apiClient.uploadFileToFileSearchStore(params.fileSearchStoreName, params.file, params.config); + } + /** + * Creates a File Search Store. + * + * @param params - The parameters for creating a File Search Store. + * @return FileSearchStore. + */ + async create(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = createFileSearchStoreParametersToMldev(params); + path = formatMap('fileSearchStores', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } + /** + * Gets a File Search Store. + * + * @param params - The parameters for getting a File Search Store. + * @return FileSearchStore. + */ + async get(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = getFileSearchStoreParametersToMldev(params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } + /** + * Deletes a File Search Store. + * + * @param params - The parameters for deleting a File Search Store. + */ + async delete(params) { + var _a, _b; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = deleteFileSearchStoreParametersToMldev(params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + await this.apiClient.request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }); + } + } + async listInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = listFileSearchStoresParametersToMldev(params); + path = formatMap('fileSearchStores', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = listFileSearchStoresResponseFromMldev(apiResponse); + const typedResp = new ListFileSearchStoresResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + async uploadToFileSearchStoreInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = uploadToFileSearchStoreParametersToMldev(params); + path = formatMap('upload/v1beta/{file_search_store_name}:uploadToFileSearchStore', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = uploadToFileSearchStoreResumableResponseFromMldev(apiResponse); + const typedResp = new UploadToFileSearchStoreResumableResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Imports a File from File Service to a FileSearchStore. + * + * This is a long-running operation, see aip.dev/151 + * + * @param params - The parameters for importing a file to a file search store. + * @return ImportFileOperation. + */ + async importFile(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = importFileParametersToMldev(params); + path = formatMap('{file_search_store_name}:importFile', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = importFileOperationFromMldev(apiResponse); + const typedResp = new ImportFileOperation(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +/** + * https://stackoverflow.com/a/2117523 + */ +let uuid4Internal = function () { + const { crypto } = globalThis; + if (crypto === null || crypto === void 0 ? void 0 : crypto.randomUUID) { + uuid4Internal = crypto.randomUUID.bind(crypto); + return crypto.randomUUID(); + } + const u8 = new Uint8Array(1); + const randomByte = crypto ? () => crypto.getRandomValues(u8)[0] : () => (Math.random() * 0xff) & 0xff; + return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, (c) => (+c ^ (randomByte() & (15 >> (+c / 4)))).toString(16)); +}; +const uuid4 = () => uuid4Internal(); + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +function isAbortError(err) { + return (typeof err === 'object' && + err !== null && + // Spec-compliant fetch implementations + (('name' in err && err.name === 'AbortError') || + // Expo fetch + ('message' in err && String(err.message).includes('FetchRequestCanceledException')))); +} +const castToError = (err) => { + if (err instanceof Error) + return err; + if (typeof err === 'object' && err !== null) { + try { + if (Object.prototype.toString.call(err) === '[object Error]') { + // @ts-ignore - not all envs have native support for cause yet + const error = new Error(err.message, err.cause ? { cause: err.cause } : {}); + if (err.stack) + error.stack = err.stack; + // @ts-ignore - not all envs have native support for cause yet + if (err.cause && !error.cause) + error.cause = err.cause; + if (err.name) + error.name = err.name; + return error; + } + } + catch (_a) { } + try { + return new Error(JSON.stringify(err)); + } + catch (_b) { } + } + return new Error(err); +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +class GeminiNextGenAPIClientError extends Error { +} +class APIError extends GeminiNextGenAPIClientError { + constructor(status, error, message, headers) { + super(`${APIError.makeMessage(status, error, message)}`); + this.status = status; + this.headers = headers; + this.error = error; + } + static makeMessage(status, error, message) { + const msg = (error === null || error === void 0 ? void 0 : error.message) ? + typeof error.message === 'string' ? + error.message + : JSON.stringify(error.message) + : error ? JSON.stringify(error) + : message; + if (status && msg) { + return `${status} ${msg}`; + } + if (status) { + return `${status} status code (no body)`; + } + if (msg) { + return msg; + } + return '(no status code or body)'; + } + static generate(status, errorResponse, message, headers) { + if (!status || !headers) { + return new APIConnectionError({ message, cause: castToError(errorResponse) }); + } + const error = errorResponse; + if (status === 400) { + return new BadRequestError(status, error, message, headers); + } + if (status === 401) { + return new AuthenticationError(status, error, message, headers); + } + if (status === 403) { + return new PermissionDeniedError(status, error, message, headers); + } + if (status === 404) { + return new NotFoundError(status, error, message, headers); + } + if (status === 409) { + return new ConflictError(status, error, message, headers); + } + if (status === 422) { + return new UnprocessableEntityError(status, error, message, headers); + } + if (status === 429) { + return new RateLimitError(status, error, message, headers); + } + if (status >= 500) { + return new InternalServerError(status, error, message, headers); + } + return new APIError(status, error, message, headers); + } +} +class APIUserAbortError extends APIError { + constructor({ message } = {}) { + super(undefined, undefined, message || 'Request was aborted.', undefined); + } +} +class APIConnectionError extends APIError { + constructor({ message, cause }) { + super(undefined, undefined, message || 'Connection error.', undefined); + // in some environments the 'cause' property is already declared + // @ts-ignore + if (cause) + this.cause = cause; + } +} +class APIConnectionTimeoutError extends APIConnectionError { + constructor({ message } = {}) { + super({ message: message !== null && message !== void 0 ? message : 'Request timed out.' }); + } +} +class BadRequestError extends APIError { +} +class AuthenticationError extends APIError { +} +class PermissionDeniedError extends APIError { +} +class NotFoundError extends APIError { +} +class ConflictError extends APIError { +} +class UnprocessableEntityError extends APIError { +} +class RateLimitError extends APIError { +} +class InternalServerError extends APIError { +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +// https://url.spec.whatwg.org/#url-scheme-string +const startsWithSchemeRegexp = /^[a-z][a-z0-9+.-]*:/i; +const isAbsoluteURL = (url) => { + return startsWithSchemeRegexp.test(url); +}; +let isArrayInternal = (val) => ((isArrayInternal = Array.isArray), isArrayInternal(val)); +const isArray = isArrayInternal; +let isReadonlyArrayInternal = isArray; +const isReadonlyArray = isReadonlyArrayInternal; +// https://stackoverflow.com/a/34491287 +function isEmptyObj(obj) { + if (!obj) + return true; + for (const _k in obj) + return false; + return true; +} +// https://eslint.org/docs/latest/rules/no-prototype-builtins +function hasOwn(obj, key) { + return Object.prototype.hasOwnProperty.call(obj, key); +} +const validatePositiveInteger = (name, n) => { + if (typeof n !== 'number' || !Number.isInteger(n)) { + throw new GeminiNextGenAPIClientError(`${name} must be an integer`); + } + if (n < 0) { + throw new GeminiNextGenAPIClientError(`${name} must be a positive integer`); + } + return n; +}; +const safeJSON = (text) => { + try { + return JSON.parse(text); + } + catch (err) { + return undefined; + } +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +const sleep$1 = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const VERSION = '0.0.1'; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +/** + * Note this does not detect 'browser'; for that, use getBrowserInfo(). + */ +function getDetectedPlatform() { + if (typeof Deno !== 'undefined' && Deno.build != null) { + return 'deno'; + } + if (typeof EdgeRuntime !== 'undefined') { + return 'edge'; + } + if (Object.prototype.toString.call(typeof globalThis.process !== 'undefined' ? globalThis.process : 0) === '[object process]') { + return 'node'; + } + return 'unknown'; +} +const getPlatformProperties = () => { + var _a, _b, _c, _d, _e; + const detectedPlatform = getDetectedPlatform(); + if (detectedPlatform === 'deno') { + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': VERSION, + 'X-Stainless-OS': normalizePlatform(Deno.build.os), + 'X-Stainless-Arch': normalizeArch(Deno.build.arch), + 'X-Stainless-Runtime': 'deno', + 'X-Stainless-Runtime-Version': typeof Deno.version === 'string' ? Deno.version : (_b = (_a = Deno.version) === null || _a === void 0 ? void 0 : _a.deno) !== null && _b !== void 0 ? _b : 'unknown', + }; + } + if (typeof EdgeRuntime !== 'undefined') { + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': VERSION, + 'X-Stainless-OS': 'Unknown', + 'X-Stainless-Arch': `other:${EdgeRuntime}`, + 'X-Stainless-Runtime': 'edge', + 'X-Stainless-Runtime-Version': globalThis.process.version, + }; + } + // Check if Node.js + if (detectedPlatform === 'node') { + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': VERSION, + 'X-Stainless-OS': normalizePlatform((_c = globalThis.process.platform) !== null && _c !== void 0 ? _c : 'unknown'), + 'X-Stainless-Arch': normalizeArch((_d = globalThis.process.arch) !== null && _d !== void 0 ? _d : 'unknown'), + 'X-Stainless-Runtime': 'node', + 'X-Stainless-Runtime-Version': (_e = globalThis.process.version) !== null && _e !== void 0 ? _e : 'unknown', + }; + } + const browserInfo = getBrowserInfo(); + if (browserInfo) { + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': VERSION, + 'X-Stainless-OS': 'Unknown', + 'X-Stainless-Arch': 'unknown', + 'X-Stainless-Runtime': `browser:${browserInfo.browser}`, + 'X-Stainless-Runtime-Version': browserInfo.version, + }; + } + // TODO add support for Cloudflare workers, etc. + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': VERSION, + 'X-Stainless-OS': 'Unknown', + 'X-Stainless-Arch': 'unknown', + 'X-Stainless-Runtime': 'unknown', + 'X-Stainless-Runtime-Version': 'unknown', + }; +}; +// Note: modified from https://github.com/JS-DevTools/host-environment/blob/b1ab79ecde37db5d6e163c050e54fe7d287d7c92/src/isomorphic.browser.ts +function getBrowserInfo() { + if (typeof navigator === 'undefined' || !navigator) { + return null; + } + // NOTE: The order matters here! + const browserPatterns = [ + { key: 'edge', pattern: /Edge(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'ie', pattern: /MSIE(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'ie', pattern: /Trident(?:.*rv\:(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'chrome', pattern: /Chrome(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'firefox', pattern: /Firefox(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'safari', pattern: /(?:Version\W+(\d+)\.(\d+)(?:\.(\d+))?)?(?:\W+Mobile\S*)?\W+Safari/ }, + ]; + // Find the FIRST matching browser + for (const { key, pattern } of browserPatterns) { + const match = pattern.exec(navigator.userAgent); + if (match) { + const major = match[1] || 0; + const minor = match[2] || 0; + const patch = match[3] || 0; + return { browser: key, version: `${major}.${minor}.${patch}` }; + } + } + return null; +} +const normalizeArch = (arch) => { + // Node docs: + // - https://nodejs.org/api/process.html#processarch + // Deno docs: + // - https://doc.deno.land/deno/stable/~/Deno.build + if (arch === 'x32') + return 'x32'; + if (arch === 'x86_64' || arch === 'x64') + return 'x64'; + if (arch === 'arm') + return 'arm'; + if (arch === 'aarch64' || arch === 'arm64') + return 'arm64'; + if (arch) + return `other:${arch}`; + return 'unknown'; +}; +const normalizePlatform = (platform) => { + // Node platforms: + // - https://nodejs.org/api/process.html#processplatform + // Deno platforms: + // - https://doc.deno.land/deno/stable/~/Deno.build + // - https://github.com/denoland/deno/issues/14799 + platform = platform.toLowerCase(); + // NOTE: this iOS check is untested and may not work + // Node does not work natively on IOS, there is a fork at + // https://github.com/nodejs-mobile/nodejs-mobile + // however it is unknown at the time of writing how to detect if it is running + if (platform.includes('ios')) + return 'iOS'; + if (platform === 'android') + return 'Android'; + if (platform === 'darwin') + return 'MacOS'; + if (platform === 'win32') + return 'Windows'; + if (platform === 'freebsd') + return 'FreeBSD'; + if (platform === 'openbsd') + return 'OpenBSD'; + if (platform === 'linux') + return 'Linux'; + if (platform) + return `Other:${platform}`; + return 'Unknown'; +}; +let _platformHeaders; +const getPlatformHeaders = () => { + return (_platformHeaders !== null && _platformHeaders !== void 0 ? _platformHeaders : (_platformHeaders = getPlatformProperties())); +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function getDefaultFetch() { + if (typeof fetch !== 'undefined') { + return fetch; + } + throw new Error('`fetch` is not defined as a global; Either pass `fetch` to the client, `new GeminiNextGenAPIClient({ fetch })` or polyfill the global, `globalThis.fetch = fetch`'); +} +function makeReadableStream(...args) { + const ReadableStream = globalThis.ReadableStream; + if (typeof ReadableStream === 'undefined') { + // Note: All of the platforms / runtimes we officially support already define + // `ReadableStream` as a global, so this should only ever be hit on unsupported runtimes. + throw new Error('`ReadableStream` is not defined as a global; You will need to polyfill it, `globalThis.ReadableStream = ReadableStream`'); + } + return new ReadableStream(...args); +} +function ReadableStreamFrom(iterable) { + let iter = Symbol.asyncIterator in iterable ? iterable[Symbol.asyncIterator]() : iterable[Symbol.iterator](); + return makeReadableStream({ + start() { }, + async pull(controller) { + const { done, value } = await iter.next(); + if (done) { + controller.close(); + } + else { + controller.enqueue(value); + } + }, + async cancel() { + var _a; + await ((_a = iter.return) === null || _a === void 0 ? void 0 : _a.call(iter)); + }, + }); +} +/** + * Most browsers don't yet have async iterable support for ReadableStream, + * and Node has a very different way of reading bytes from its "ReadableStream". + * + * This polyfill was pulled from https://github.com/MattiasBuelens/web-streams-polyfill/pull/122#issuecomment-1627354490 + */ +function ReadableStreamToAsyncIterable(stream) { + if (stream[Symbol.asyncIterator]) + return stream; + const reader = stream.getReader(); + return { + async next() { + try { + const result = await reader.read(); + if (result === null || result === void 0 ? void 0 : result.done) + reader.releaseLock(); // release lock when stream becomes closed + return result; + } + catch (e) { + reader.releaseLock(); // release lock when stream becomes errored + throw e; + } + }, + async return() { + const cancelPromise = reader.cancel(); + reader.releaseLock(); + await cancelPromise; + return { done: true, value: undefined }; + }, + [Symbol.asyncIterator]() { + return this; + }, + }; +} +/** + * Cancels a ReadableStream we don't need to consume. + * See https://undici.nodejs.org/#/?id=garbage-collection + */ +async function CancelReadableStream(stream) { + var _a, _b; + if (stream === null || typeof stream !== 'object') + return; + if (stream[Symbol.asyncIterator]) { + await ((_b = (_a = stream[Symbol.asyncIterator]()).return) === null || _b === void 0 ? void 0 : _b.call(_a)); + return; + } + const reader = stream.getReader(); + const cancelPromise = reader.cancel(); + reader.releaseLock(); + await cancelPromise; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const FallbackEncoder = ({ headers, body }) => { + return { + bodyHeaders: { + 'content-type': 'application/json', + }, + body: JSON.stringify(body), + }; +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const checkFileSupport = () => { + var _a; + if (typeof File === 'undefined') { + const { process } = globalThis; + const isOldNode = typeof ((_a = process === null || process === void 0 ? void 0 : process.versions) === null || _a === void 0 ? void 0 : _a.node) === 'string' && parseInt(process.versions.node.split('.')) < 20; + throw new Error('`File` is not defined as a global, which is required for file uploads.' + + (isOldNode ? + " Update to Node 20 LTS or newer, or set `globalThis.File` to `import('node:buffer').File`." + : '')); + } +}; +/** + * Construct a `File` instance. This is used to ensure a helpful error is thrown + * for environments that don't define a global `File` yet. + */ +function makeFile(fileBits, fileName, options) { + checkFileSupport(); + return new File(fileBits, fileName !== null && fileName !== void 0 ? fileName : 'unknown_file', options); +} +function getName(value) { + return (((typeof value === 'object' && + value !== null && + (('name' in value && value.name && String(value.name)) || + ('url' in value && value.url && String(value.url)) || + ('filename' in value && value.filename && String(value.filename)) || + ('path' in value && value.path && String(value.path)))) || + '') + .split(/[\\/]/) + .pop() || undefined); +} +const isAsyncIterable = (value) => value != null && typeof value === 'object' && typeof value[Symbol.asyncIterator] === 'function'; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * This check adds the arrayBuffer() method type because it is available and used at runtime + */ +const isBlobLike = (value) => value != null && + typeof value === 'object' && + typeof value.size === 'number' && + typeof value.type === 'string' && + typeof value.text === 'function' && + typeof value.slice === 'function' && + typeof value.arrayBuffer === 'function'; +/** + * This check adds the arrayBuffer() method type because it is available and used at runtime + */ +const isFileLike = (value) => value != null && + typeof value === 'object' && + typeof value.name === 'string' && + typeof value.lastModified === 'number' && + isBlobLike(value); +const isResponseLike = (value) => value != null && + typeof value === 'object' && + typeof value.url === 'string' && + typeof value.blob === 'function'; +/** + * Helper for creating a {@link File} to pass to an SDK upload method from a variety of different data formats + * @param value the raw content of the file. Can be an {@link Uploadable}, BlobLikePart, or AsyncIterable of BlobLikeParts + * @param {string=} name the name of the file. If omitted, toFile will try to determine a file name from bits if possible + * @param {Object=} options additional properties + * @param {string=} options.type the MIME type of the content + * @param {number=} options.lastModified the last modified timestamp + * @returns a {@link File} with the given properties + */ +async function toFile(value, name, options) { + checkFileSupport(); + // If it's a promise, resolve it. + value = await value; + // If we've been given a `File` we don't need to do anything + if (isFileLike(value)) { + if (value instanceof File) { + return value; + } + return makeFile([await value.arrayBuffer()], value.name); + } + if (isResponseLike(value)) { + const blob = await value.blob(); + name || (name = new URL(value.url).pathname.split(/[\\/]/).pop()); + return makeFile(await getBytes(blob), name, options); + } + const parts = await getBytes(value); + name || (name = getName(value)); + if (!(options === null || options === void 0 ? void 0 : options.type)) { + const type = parts.find((part) => typeof part === 'object' && 'type' in part && part.type); + if (typeof type === 'string') { + options = Object.assign(Object.assign({}, options), { type }); + } + } + return makeFile(parts, name, options); +} +async function getBytes(value) { + var _a, e_1, _b, _c; + var _d; + let parts = []; + if (typeof value === 'string' || + ArrayBuffer.isView(value) || // includes Uint8Array, Buffer, etc. + value instanceof ArrayBuffer) { + parts.push(value); + } + else if (isBlobLike(value)) { + parts.push(value instanceof Blob ? value : await value.arrayBuffer()); + } + else if (isAsyncIterable(value) // includes Readable, ReadableStream, etc. + ) { + try { + for (var _e = true, value_1 = __asyncValues(value), value_1_1; value_1_1 = await value_1.next(), _a = value_1_1.done, !_a; _e = true) { + _c = value_1_1.value; + _e = false; + const chunk = _c; + parts.push(...(await getBytes(chunk))); // TODO, consider validating? + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (!_e && !_a && (_b = value_1.return)) await _b.call(value_1); + } + finally { if (e_1) throw e_1.error; } + } + } + else { + const constructor = (_d = value === null || value === void 0 ? void 0 : value.constructor) === null || _d === void 0 ? void 0 : _d.name; + throw new Error(`Unexpected data type: ${typeof value}${constructor ? `; constructor: ${constructor}` : ''}${propsForError(value)}`); + } + return parts; +} +function propsForError(value) { + if (typeof value !== 'object' || value === null) + return ''; + const props = Object.getOwnPropertyNames(value); + return `; props: [${props.map((p) => `"${p}"`).join(', ')}]`; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class APIResource { + constructor(client) { + this._client = client; + } +} +/** + * The key path from the client. For example, a resource accessible as `client.resource.subresource` would + * have a property `static override readonly _key = Object.freeze(['resource', 'subresource'] as const);`. + */ +APIResource._key = []; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Percent-encode everything that isn't safe to have in a path without encoding safe chars. + * + * Taken from https://datatracker.ietf.org/doc/html/rfc3986#section-3.3: + * > unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + * > sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" + * > pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + */ +function encodeURIPath(str) { + return str.replace(/[^A-Za-z0-9\-._~!$&'()*+,;=:@]+/g, encodeURIComponent); +} +const EMPTY = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.create(null)); +const createPathTagFunction = (pathEncoder = encodeURIPath) => (function path(statics, ...params) { + // If there are no params, no processing is needed. + if (statics.length === 1) + return statics[0]; + let postPath = false; + const invalidSegments = []; + const path = statics.reduce((previousValue, currentValue, index) => { + var _a, _b, _c; + if (/[?#]/.test(currentValue)) { + postPath = true; + } + const value = params[index]; + let encoded = (postPath ? encodeURIComponent : pathEncoder)('' + value); + if (index !== params.length && + (value == null || + (typeof value === 'object' && + // handle values from other realms + value.toString === + ((_c = Object.getPrototypeOf((_b = Object.getPrototypeOf((_a = value.hasOwnProperty) !== null && _a !== void 0 ? _a : EMPTY)) !== null && _b !== void 0 ? _b : EMPTY)) === null || _c === void 0 ? void 0 : _c.toString)))) { + encoded = value + ''; + invalidSegments.push({ + start: previousValue.length + currentValue.length, + length: encoded.length, + error: `Value of type ${Object.prototype.toString + .call(value) + .slice(8, -1)} is not a valid path parameter`, + }); + } + return previousValue + currentValue + (index === params.length ? '' : encoded); + }, ''); + const pathOnly = path.split(/[?#]/, 1)[0]; + const invalidSegmentPattern = /(?<=^|\/)(?:\.|%2e){1,2}(?=\/|$)/gi; + let match; + // Find all invalid segments + while ((match = invalidSegmentPattern.exec(pathOnly)) !== null) { + invalidSegments.push({ + start: match.index, + length: match[0].length, + error: `Value "${match[0]}" can\'t be safely passed as a path parameter`, + }); + } + invalidSegments.sort((a, b) => a.start - b.start); + if (invalidSegments.length > 0) { + let lastEnd = 0; + const underline = invalidSegments.reduce((acc, segment) => { + const spaces = ' '.repeat(segment.start - lastEnd); + const arrows = '^'.repeat(segment.length); + lastEnd = segment.start + segment.length; + return acc + spaces + arrows; + }, ''); + throw new GeminiNextGenAPIClientError(`Path parameters result in path with invalid segments:\n${invalidSegments + .map((e) => e.error) + .join('\n')}\n${path}\n${underline}`); + } + return path; +}); +/** + * URI-encodes path params and ensures no unsafe /./ or /../ path segments are introduced. + */ +const path = /* @__PURE__ */ createPathTagFunction(encodeURIPath); + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class BaseInteractions extends APIResource { + create(params, options) { + var _a; + const { api_version = this._client.apiVersion } = params, body = __rest(params, ["api_version"]); + if ('model' in body && 'agent_config' in body) { + throw new GeminiNextGenAPIClientError(`Invalid request: specified \`model\` and \`agent_config\`. If specifying \`model\`, use \`generation_config\`.`); + } + if ('agent' in body && 'generation_config' in body) { + throw new GeminiNextGenAPIClientError(`Invalid request: specified \`agent\` and \`generation_config\`. If specifying \`agent\`, use \`agent_config\`.`); + } + return this._client.post(path `/${api_version}/interactions`, Object.assign(Object.assign({ body }, options), { stream: (_a = params.stream) !== null && _a !== void 0 ? _a : false })); + } + /** + * Deletes the interaction by id. + * + * @example + * ```ts + * const interaction = await client.interactions.delete('id', { + * api_version: 'api_version', + * }); + * ``` + */ + delete(id, params = {}, options) { + const { api_version = this._client.apiVersion } = params !== null && params !== void 0 ? params : {}; + return this._client.delete(path `/${api_version}/interactions/${id}`, options); + } + /** + * Cancels an interaction by id. This only applies to background interactions that are still running. + * + * @example + * ```ts + * const interaction = await client.interactions.cancel('id', { + * api_version: 'api_version', + * }); + * ``` + */ + cancel(id, params = {}, options) { + const { api_version = this._client.apiVersion } = params !== null && params !== void 0 ? params : {}; + return this._client.post(path `/${api_version}/interactions/${id}/cancel`, options); + } + get(id, params = {}, options) { + var _a; + const _b = params !== null && params !== void 0 ? params : {}, { api_version = this._client.apiVersion } = _b, query = __rest(_b, ["api_version"]); + return this._client.get(path `/${api_version}/interactions/${id}`, Object.assign(Object.assign({ query }, options), { stream: (_a = params === null || params === void 0 ? void 0 : params.stream) !== null && _a !== void 0 ? _a : false })); + } +} +BaseInteractions._key = Object.freeze(['interactions']); +class Interactions extends BaseInteractions { +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function concatBytes(buffers) { + let length = 0; + for (const buffer of buffers) { + length += buffer.length; + } + const output = new Uint8Array(length); + let index = 0; + for (const buffer of buffers) { + output.set(buffer, index); + index += buffer.length; + } + return output; +} +let encodeUTF8_; +function encodeUTF8(str) { + let encoder; + return (encodeUTF8_ !== null && encodeUTF8_ !== void 0 ? encodeUTF8_ : ((encoder = new globalThis.TextEncoder()), (encodeUTF8_ = encoder.encode.bind(encoder))))(str); +} +let decodeUTF8_; +function decodeUTF8(bytes) { + let decoder; + return (decodeUTF8_ !== null && decodeUTF8_ !== void 0 ? decodeUTF8_ : ((decoder = new globalThis.TextDecoder()), (decodeUTF8_ = decoder.decode.bind(decoder))))(bytes); +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * A re-implementation of httpx's `LineDecoder` in Python that handles incrementally + * reading lines from text. + * + * https://github.com/encode/httpx/blob/920333ea98118e9cf617f246905d7b202510941c/httpx/_decoders.py#L258 + */ +class LineDecoder { + constructor() { + this.buffer = new Uint8Array(); + this.carriageReturnIndex = null; + } + decode(chunk) { + if (chunk == null) { + return []; + } + const binaryChunk = chunk instanceof ArrayBuffer ? new Uint8Array(chunk) + : typeof chunk === 'string' ? encodeUTF8(chunk) + : chunk; + this.buffer = concatBytes([this.buffer, binaryChunk]); + const lines = []; + let patternIndex; + while ((patternIndex = findNewlineIndex(this.buffer, this.carriageReturnIndex)) != null) { + if (patternIndex.carriage && this.carriageReturnIndex == null) { + // skip until we either get a corresponding `\n`, a new `\r` or nothing + this.carriageReturnIndex = patternIndex.index; + continue; + } + // we got double \r or \rtext\n + if (this.carriageReturnIndex != null && + (patternIndex.index !== this.carriageReturnIndex + 1 || patternIndex.carriage)) { + lines.push(decodeUTF8(this.buffer.subarray(0, this.carriageReturnIndex - 1))); + this.buffer = this.buffer.subarray(this.carriageReturnIndex); + this.carriageReturnIndex = null; + continue; + } + const endIndex = this.carriageReturnIndex !== null ? patternIndex.preceding - 1 : patternIndex.preceding; + const line = decodeUTF8(this.buffer.subarray(0, endIndex)); + lines.push(line); + this.buffer = this.buffer.subarray(patternIndex.index); + this.carriageReturnIndex = null; + } + return lines; + } + flush() { + if (!this.buffer.length) { + return []; + } + return this.decode('\n'); + } +} +// prettier-ignore +LineDecoder.NEWLINE_CHARS = new Set(['\n', '\r']); +LineDecoder.NEWLINE_REGEXP = /\r\n|[\n\r]/g; +/** + * This function searches the buffer for the end patterns, (\r or \n) + * and returns an object with the index preceding the matched newline and the + * index after the newline char. `null` is returned if no new line is found. + * + * ```ts + * findNewLineIndex('abc\ndef') -> { preceding: 2, index: 3 } + * ``` + */ +function findNewlineIndex(buffer, startIndex) { + const newline = 0x0a; // \n + const carriage = 0x0d; // \r + for (let i = startIndex !== null && startIndex !== void 0 ? startIndex : 0; i < buffer.length; i++) { + if (buffer[i] === newline) { + return { preceding: i, index: i + 1, carriage: false }; + } + if (buffer[i] === carriage) { + return { preceding: i, index: i + 1, carriage: true }; + } + } + return null; +} +function findDoubleNewlineIndex(buffer) { + // This function searches the buffer for the end patterns (\r\r, \n\n, \r\n\r\n) + // and returns the index right after the first occurrence of any pattern, + // or -1 if none of the patterns are found. + const newline = 0x0a; // \n + const carriage = 0x0d; // \r + for (let i = 0; i < buffer.length - 1; i++) { + if (buffer[i] === newline && buffer[i + 1] === newline) { + // \n\n + return i + 2; + } + if (buffer[i] === carriage && buffer[i + 1] === carriage) { + // \r\r + return i + 2; + } + if (buffer[i] === carriage && + buffer[i + 1] === newline && + i + 3 < buffer.length && + buffer[i + 2] === carriage && + buffer[i + 3] === newline) { + // \r\n\r\n + return i + 4; + } + } + return -1; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +const levelNumbers = { + off: 0, + error: 200, + warn: 300, + info: 400, + debug: 500, +}; +const parseLogLevel = (maybeLevel, sourceName, client) => { + if (!maybeLevel) { + return undefined; + } + if (hasOwn(levelNumbers, maybeLevel)) { + return maybeLevel; + } + loggerFor(client).warn(`${sourceName} was set to ${JSON.stringify(maybeLevel)}, expected one of ${JSON.stringify(Object.keys(levelNumbers))}`); + return undefined; +}; +function noop() { } +function makeLogFn(fnLevel, logger, logLevel) { + if (!logger || levelNumbers[fnLevel] > levelNumbers[logLevel]) { + return noop; + } + else { + // Don't wrap logger functions, we want the stacktrace intact! + return logger[fnLevel].bind(logger); + } +} +const noopLogger = { + error: noop, + warn: noop, + info: noop, + debug: noop, +}; +let cachedLoggers = /* @__PURE__ */ new WeakMap(); +function loggerFor(client) { + var _a; + const logger = client.logger; + const logLevel = (_a = client.logLevel) !== null && _a !== void 0 ? _a : 'off'; + if (!logger) { + return noopLogger; + } + const cachedLogger = cachedLoggers.get(logger); + if (cachedLogger && cachedLogger[0] === logLevel) { + return cachedLogger[1]; + } + const levelLogger = { + error: makeLogFn('error', logger, logLevel), + warn: makeLogFn('warn', logger, logLevel), + info: makeLogFn('info', logger, logLevel), + debug: makeLogFn('debug', logger, logLevel), + }; + cachedLoggers.set(logger, [logLevel, levelLogger]); + return levelLogger; +} +const formatRequestDetails = (details) => { + if (details.options) { + details.options = Object.assign({}, details.options); + delete details.options['headers']; // redundant + leaks internals + } + if (details.headers) { + details.headers = Object.fromEntries((details.headers instanceof Headers ? [...details.headers] : Object.entries(details.headers)).map(([name, value]) => [ + name, + (name.toLowerCase() === 'x-goog-api-key' || + name.toLowerCase() === 'authorization' || + name.toLowerCase() === 'cookie' || + name.toLowerCase() === 'set-cookie') ? + '***' + : value, + ])); + } + if ('retryOfRequestLogID' in details) { + if (details.retryOfRequestLogID) { + details.retryOf = details.retryOfRequestLogID; + } + delete details.retryOfRequestLogID; + } + return details; +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Stream { + constructor(iterator, controller, client) { + this.iterator = iterator; + this.controller = controller; + this.client = client; + } + static fromSSEResponse(response, controller, client) { + let consumed = false; + const logger = client ? loggerFor(client) : console; + function iterator() { + return __asyncGenerator(this, arguments, function* iterator_1() { + var _a, e_1, _b, _c; + if (consumed) { + throw new GeminiNextGenAPIClientError('Cannot iterate over a consumed stream, use `.tee()` to split the stream.'); + } + consumed = true; + let done = false; + try { + try { + for (var _d = true, _e = __asyncValues(_iterSSEMessages(response, controller)), _f; _f = yield __await(_e.next()), _a = _f.done, !_a; _d = true) { + _c = _f.value; + _d = false; + const sse = _c; + if (done) + continue; + if (sse.data.startsWith('[DONE]')) { + done = true; + continue; + } + else { + try { + // @ts-ignore + yield yield __await(JSON.parse(sse.data)); + } + catch (e) { + logger.error(`Could not parse message into JSON:`, sse.data); + logger.error(`From chunk:`, sse.raw); + throw e; + } + } + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (!_d && !_a && (_b = _e.return)) yield __await(_b.call(_e)); + } + finally { if (e_1) throw e_1.error; } + } + done = true; + } + catch (e) { + // If the user calls `stream.controller.abort()`, we should exit without throwing. + if (isAbortError(e)) + return yield __await(void 0); + throw e; + } + finally { + // If the user `break`s, abort the ongoing request. + if (!done) + controller.abort(); + } + }); + } + return new Stream(iterator, controller, client); + } + /** + * Generates a Stream from a newline-separated ReadableStream + * where each item is a JSON value. + */ + static fromReadableStream(readableStream, controller, client) { + let consumed = false; + function iterLines() { + return __asyncGenerator(this, arguments, function* iterLines_1() { + var _a, e_2, _b, _c; + const lineDecoder = new LineDecoder(); + const iter = ReadableStreamToAsyncIterable(readableStream); + try { + for (var _d = true, iter_1 = __asyncValues(iter), iter_1_1; iter_1_1 = yield __await(iter_1.next()), _a = iter_1_1.done, !_a; _d = true) { + _c = iter_1_1.value; + _d = false; + const chunk = _c; + for (const line of lineDecoder.decode(chunk)) { + yield yield __await(line); + } + } + } + catch (e_2_1) { e_2 = { error: e_2_1 }; } + finally { + try { + if (!_d && !_a && (_b = iter_1.return)) yield __await(_b.call(iter_1)); + } + finally { if (e_2) throw e_2.error; } + } + for (const line of lineDecoder.flush()) { + yield yield __await(line); + } + }); + } + function iterator() { + return __asyncGenerator(this, arguments, function* iterator_2() { + var _a, e_3, _b, _c; + if (consumed) { + throw new GeminiNextGenAPIClientError('Cannot iterate over a consumed stream, use `.tee()` to split the stream.'); + } + consumed = true; + let done = false; + try { + try { + for (var _d = true, _e = __asyncValues(iterLines()), _f; _f = yield __await(_e.next()), _a = _f.done, !_a; _d = true) { + _c = _f.value; + _d = false; + const line = _c; + if (done) + continue; + // @ts-ignore + if (line) + yield yield __await(JSON.parse(line)); + } + } + catch (e_3_1) { e_3 = { error: e_3_1 }; } + finally { + try { + if (!_d && !_a && (_b = _e.return)) yield __await(_b.call(_e)); + } + finally { if (e_3) throw e_3.error; } + } + done = true; + } + catch (e) { + // If the user calls `stream.controller.abort()`, we should exit without throwing. + if (isAbortError(e)) + return yield __await(void 0); + throw e; + } + finally { + // If the user `break`s, abort the ongoing request. + if (!done) + controller.abort(); + } + }); + } + return new Stream(iterator, controller, client); + } + [Symbol.asyncIterator]() { + return this.iterator(); + } + /** + * Splits the stream into two streams which can be + * independently read from at different speeds. + */ + tee() { + const left = []; + const right = []; + const iterator = this.iterator(); + const teeIterator = (queue) => { + return { + next: () => { + if (queue.length === 0) { + const result = iterator.next(); + left.push(result); + right.push(result); + } + return queue.shift(); + }, + }; + }; + return [ + new Stream(() => teeIterator(left), this.controller, this.client), + new Stream(() => teeIterator(right), this.controller, this.client), + ]; + } + /** + * Converts this stream to a newline-separated ReadableStream of + * JSON stringified values in the stream + * which can be turned back into a Stream with `Stream.fromReadableStream()`. + */ + toReadableStream() { + const self = this; + let iter; + return makeReadableStream({ + async start() { + iter = self[Symbol.asyncIterator](); + }, + async pull(ctrl) { + try { + const { value, done } = await iter.next(); + if (done) + return ctrl.close(); + const bytes = encodeUTF8(JSON.stringify(value) + '\n'); + ctrl.enqueue(bytes); + } + catch (err) { + ctrl.error(err); + } + }, + async cancel() { + var _a; + await ((_a = iter.return) === null || _a === void 0 ? void 0 : _a.call(iter)); + }, + }); + } +} +function _iterSSEMessages(response, controller) { + return __asyncGenerator(this, arguments, function* _iterSSEMessages_1() { + var _a, e_4, _b, _c; + if (!response.body) { + controller.abort(); + if (typeof globalThis.navigator !== 'undefined' && + globalThis.navigator.product === 'ReactNative') { + throw new GeminiNextGenAPIClientError(`The default react-native fetch implementation does not support streaming. Please use expo/fetch: https://docs.expo.dev/versions/latest/sdk/expo/#expofetch-api`); + } + throw new GeminiNextGenAPIClientError(`Attempted to iterate over a response with no body`); + } + const sseDecoder = new SSEDecoder(); + const lineDecoder = new LineDecoder(); + const iter = ReadableStreamToAsyncIterable(response.body); + try { + for (var _d = true, _e = __asyncValues(iterSSEChunks(iter)), _f; _f = yield __await(_e.next()), _a = _f.done, !_a; _d = true) { + _c = _f.value; + _d = false; + const sseChunk = _c; + for (const line of lineDecoder.decode(sseChunk)) { + const sse = sseDecoder.decode(line); + if (sse) + yield yield __await(sse); + } + } + } + catch (e_4_1) { e_4 = { error: e_4_1 }; } + finally { + try { + if (!_d && !_a && (_b = _e.return)) yield __await(_b.call(_e)); + } + finally { if (e_4) throw e_4.error; } + } + for (const line of lineDecoder.flush()) { + const sse = sseDecoder.decode(line); + if (sse) + yield yield __await(sse); + } + }); +} +/** + * Given an async iterable iterator, iterates over it and yields full + * SSE chunks, i.e. yields when a double new-line is encountered. + */ +function iterSSEChunks(iterator) { + return __asyncGenerator(this, arguments, function* iterSSEChunks_1() { + var _a, e_5, _b, _c; + let data = new Uint8Array(); + try { + for (var _d = true, iterator_3 = __asyncValues(iterator), iterator_3_1; iterator_3_1 = yield __await(iterator_3.next()), _a = iterator_3_1.done, !_a; _d = true) { + _c = iterator_3_1.value; + _d = false; + const chunk = _c; + if (chunk == null) { + continue; + } + const binaryChunk = chunk instanceof ArrayBuffer ? new Uint8Array(chunk) + : typeof chunk === 'string' ? encodeUTF8(chunk) + : chunk; + let newData = new Uint8Array(data.length + binaryChunk.length); + newData.set(data); + newData.set(binaryChunk, data.length); + data = newData; + let patternIndex; + while ((patternIndex = findDoubleNewlineIndex(data)) !== -1) { + yield yield __await(data.slice(0, patternIndex)); + data = data.slice(patternIndex); + } + } + } + catch (e_5_1) { e_5 = { error: e_5_1 }; } + finally { + try { + if (!_d && !_a && (_b = iterator_3.return)) yield __await(_b.call(iterator_3)); + } + finally { if (e_5) throw e_5.error; } + } + if (data.length > 0) { + yield yield __await(data); + } + }); +} +class SSEDecoder { + constructor() { + this.event = null; + this.data = []; + this.chunks = []; + } + decode(line) { + if (line.endsWith('\r')) { + line = line.substring(0, line.length - 1); + } + if (!line) { + // empty line and we didn't previously encounter any messages + if (!this.event && !this.data.length) + return null; + const sse = { + event: this.event, + data: this.data.join('\n'), + raw: this.chunks, + }; + this.event = null; + this.data = []; + this.chunks = []; + return sse; + } + this.chunks.push(line); + if (line.startsWith(':')) { + return null; + } + let [fieldname, _, value] = partition(line, ':'); + if (value.startsWith(' ')) { + value = value.substring(1); + } + if (fieldname === 'event') { + this.event = value; + } + else if (fieldname === 'data') { + this.data.push(value); + } + return null; + } +} +function partition(str, delimiter) { + const index = str.indexOf(delimiter); + if (index !== -1) { + return [str.substring(0, index), delimiter, str.substring(index + delimiter.length)]; + } + return [str, '', '']; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +async function defaultParseResponse(client, props) { + const { response, requestLogID, retryOfRequestLogID, startTime } = props; + const body = await (async () => { + var _a; + if (props.options.stream) { + loggerFor(client).debug('response', response.status, response.url, response.headers, response.body); + // Note: there is an invariant here that isn't represented in the type system + // that if you set `stream: true` the response type must also be `Stream<T>` + if (props.options.__streamClass) { + return props.options.__streamClass.fromSSEResponse(response, props.controller, client); + } + return Stream.fromSSEResponse(response, props.controller, client); + } + // fetch refuses to read the body when the status code is 204. + if (response.status === 204) { + return null; + } + if (props.options.__binaryResponse) { + return response; + } + const contentType = response.headers.get('content-type'); + const mediaType = (_a = contentType === null || contentType === void 0 ? void 0 : contentType.split(';')[0]) === null || _a === void 0 ? void 0 : _a.trim(); + const isJSON = (mediaType === null || mediaType === void 0 ? void 0 : mediaType.includes('application/json')) || (mediaType === null || mediaType === void 0 ? void 0 : mediaType.endsWith('+json')); + if (isJSON) { + const contentLength = response.headers.get('content-length'); + if (contentLength === '0') { + // if there is no content we can't do anything + return undefined; + } + const json = await response.json(); + return json; + } + const text = await response.text(); + return text; + })(); + loggerFor(client).debug(`[${requestLogID}] response parsed`, formatRequestDetails({ + retryOfRequestLogID, + url: response.url, + status: response.status, + body, + durationMs: Date.now() - startTime, + })); + return body; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * A subclass of `Promise` providing additional helper methods + * for interacting with the SDK. + */ +class APIPromise extends Promise { + constructor(client, responsePromise, parseResponse = defaultParseResponse) { + super((resolve) => { + // this is maybe a bit weird but this has to be a no-op to not implicitly + // parse the response body; instead .then, .catch, .finally are overridden + // to parse the response + resolve(null); + }); + this.responsePromise = responsePromise; + this.parseResponse = parseResponse; + this.client = client; + } + _thenUnwrap(transform) { + return new APIPromise(this.client, this.responsePromise, async (client, props) => transform(await this.parseResponse(client, props), props)); + } + /** + * Gets the raw `Response` instance instead of parsing the response + * data. + * + * If you want to parse the response body but still get the `Response` + * instance, you can use {@link withResponse()}. + * + * 👋 Getting the wrong TypeScript type for `Response`? + * Try setting `"moduleResolution": "NodeNext"` or add `"lib": ["DOM"]` + * to your `tsconfig.json`. + */ + asResponse() { + return this.responsePromise.then((p) => p.response); + } + /** + * Gets the parsed response data and the raw `Response` instance. + * + * If you just want to get the raw `Response` instance without parsing it, + * you can use {@link asResponse()}. + * + * 👋 Getting the wrong TypeScript type for `Response`? + * Try setting `"moduleResolution": "NodeNext"` or add `"lib": ["DOM"]` + * to your `tsconfig.json`. + */ + async withResponse() { + const [data, response] = await Promise.all([this.parse(), this.asResponse()]); + return { data, response }; + } + parse() { + if (!this.parsedPromise) { + this.parsedPromise = this.responsePromise.then((data) => this.parseResponse(this.client, data)); + } + return this.parsedPromise; + } + then(onfulfilled, onrejected) { + return this.parse().then(onfulfilled, onrejected); + } + catch(onrejected) { + return this.parse().catch(onrejected); + } + finally(onfinally) { + return this.parse().finally(onfinally); + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +const brand_privateNullableHeaders = /* @__PURE__ */ Symbol('brand.privateNullableHeaders'); +function* iterateHeaders(headers) { + if (!headers) + return; + if (brand_privateNullableHeaders in headers) { + const { values, nulls } = headers; + yield* values.entries(); + for (const name of nulls) { + yield [name, null]; + } + return; + } + let shouldClear = false; + let iter; + if (headers instanceof Headers) { + iter = headers.entries(); + } + else if (isReadonlyArray(headers)) { + iter = headers; + } + else { + shouldClear = true; + iter = Object.entries(headers !== null && headers !== void 0 ? headers : {}); + } + for (let row of iter) { + const name = row[0]; + if (typeof name !== 'string') + throw new TypeError('expected header name to be a string'); + const values = isReadonlyArray(row[1]) ? row[1] : [row[1]]; + let didClear = false; + for (const value of values) { + if (value === undefined) + continue; + // Objects keys always overwrite older headers, they never append. + // Yield a null to clear the header before adding the new values. + if (shouldClear && !didClear) { + didClear = true; + yield [name, null]; + } + yield [name, value]; + } + } +} +const buildHeaders = (newHeaders) => { + const targetHeaders = new Headers(); + const nullHeaders = new Set(); + for (const headers of newHeaders) { + const seenHeaders = new Set(); + for (const [name, value] of iterateHeaders(headers)) { + const lowerName = name.toLowerCase(); + if (!seenHeaders.has(lowerName)) { + targetHeaders.delete(name); + seenHeaders.add(lowerName); + } + if (value === null) { + targetHeaders.delete(name); + nullHeaders.add(lowerName); + } + else { + targetHeaders.append(name, value); + nullHeaders.delete(lowerName); + } + } + } + return { [brand_privateNullableHeaders]: true, values: targetHeaders, nulls: nullHeaders }; +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +/** + * Read an environment variable. + * + * Trims beginning and trailing whitespace. + * + * Will return undefined if the environment variable doesn't exist or cannot be accessed. + */ +const readEnv = (env) => { + var _a, _b, _c, _d, _e, _f; + if (typeof globalThis.process !== 'undefined') { + return (_c = (_b = (_a = globalThis.process.env) === null || _a === void 0 ? void 0 : _a[env]) === null || _b === void 0 ? void 0 : _b.trim()) !== null && _c !== void 0 ? _c : undefined; + } + if (typeof globalThis.Deno !== 'undefined') { + return (_f = (_e = (_d = globalThis.Deno.env) === null || _d === void 0 ? void 0 : _d.get) === null || _e === void 0 ? void 0 : _e.call(_d, env)) === null || _f === void 0 ? void 0 : _f.trim(); + } + return undefined; +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +var _a; +/** + * Base class for Gemini Next Gen API API clients. + */ +class BaseGeminiNextGenAPIClient { + /** + * API Client for interfacing with the Gemini Next Gen API API. + * + * @param {string | null | undefined} [opts.apiKey=process.env['GEMINI_API_KEY'] ?? null] + * @param {string | undefined} [opts.apiVersion=v1beta] + * @param {string} [opts.baseURL=process.env['GEMINI_NEXT_GEN_API_BASE_URL'] ?? https://generativelanguage.googleapis.com] - Override the default base URL for the API. + * @param {number} [opts.timeout=1 minute] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out. + * @param {MergedRequestInit} [opts.fetchOptions] - Additional `RequestInit` options to be passed to `fetch` calls. + * @param {Fetch} [opts.fetch] - Specify a custom `fetch` function implementation. + * @param {number} [opts.maxRetries=2] - The maximum number of times the client will retry a request. + * @param {HeadersLike} opts.defaultHeaders - Default headers to include with every request to the API. + * @param {Record<string, string | undefined>} opts.defaultQuery - Default query parameters to include with every request to the API. + */ + constructor(_b) { + var _c, _d, _e, _f, _g, _h, _j; + var { baseURL = readEnv('GEMINI_NEXT_GEN_API_BASE_URL'), apiKey = (_c = readEnv('GEMINI_API_KEY')) !== null && _c !== void 0 ? _c : null, apiVersion = 'v1beta' } = _b, opts = __rest(_b, ["baseURL", "apiKey", "apiVersion"]); + const options = Object.assign(Object.assign({ apiKey, + apiVersion }, opts), { baseURL: baseURL || `https://generativelanguage.googleapis.com` }); + this.baseURL = options.baseURL; + this.timeout = (_d = options.timeout) !== null && _d !== void 0 ? _d : BaseGeminiNextGenAPIClient.DEFAULT_TIMEOUT /* 1 minute */; + this.logger = (_e = options.logger) !== null && _e !== void 0 ? _e : console; + const defaultLogLevel = 'warn'; + // Set default logLevel early so that we can log a warning in parseLogLevel. + this.logLevel = defaultLogLevel; + this.logLevel = + (_g = (_f = parseLogLevel(options.logLevel, 'ClientOptions.logLevel', this)) !== null && _f !== void 0 ? _f : parseLogLevel(readEnv('GEMINI_NEXT_GEN_API_LOG'), "process.env['GEMINI_NEXT_GEN_API_LOG']", this)) !== null && _g !== void 0 ? _g : defaultLogLevel; + this.fetchOptions = options.fetchOptions; + this.maxRetries = (_h = options.maxRetries) !== null && _h !== void 0 ? _h : 2; + this.fetch = (_j = options.fetch) !== null && _j !== void 0 ? _j : getDefaultFetch(); + this.encoder = FallbackEncoder; + this._options = options; + this.apiKey = apiKey; + this.apiVersion = apiVersion; + this.clientAdapter = options.clientAdapter; + } + /** + * Create a new client instance re-using the same options given to the current client with optional overriding. + */ + withOptions(options) { + const client = new this.constructor(Object.assign(Object.assign(Object.assign({}, this._options), { baseURL: this.baseURL, maxRetries: this.maxRetries, timeout: this.timeout, logger: this.logger, logLevel: this.logLevel, fetch: this.fetch, fetchOptions: this.fetchOptions, apiKey: this.apiKey, apiVersion: this.apiVersion }), options)); + return client; + } + /** + * Check whether the base URL is set to its default. + */ + baseURLOverridden() { + return this.baseURL !== 'https://generativelanguage.googleapis.com'; + } + defaultQuery() { + return this._options.defaultQuery; + } + validateHeaders({ values, nulls }) { + // The headers object handles case insensitivity. + if (values.has('authorization') || values.has('x-goog-api-key')) { + return; + } + if (this.apiKey && values.get('x-goog-api-key')) { + return; + } + if (nulls.has('x-goog-api-key')) { + return; + } + throw new Error('Could not resolve authentication method. Expected the apiKey to be set. Or for the "x-goog-api-key" headers to be explicitly omitted'); + } + async authHeaders(opts) { + const existingHeaders = buildHeaders([opts.headers]); + if (existingHeaders.values.has('authorization') || existingHeaders.values.has('x-goog-api-key')) { + return undefined; + } + if (this.apiKey) { + return buildHeaders([{ 'x-goog-api-key': this.apiKey }]); + } + if (this.clientAdapter.isVertexAI()) { + return buildHeaders([await this.clientAdapter.getAuthHeaders()]); + } + return undefined; + } + /** + * Basic re-implementation of `qs.stringify` for primitive types. + */ + stringifyQuery(query) { + return Object.entries(query) + .filter(([_, value]) => typeof value !== 'undefined') + .map(([key, value]) => { + if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { + return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`; + } + if (value === null) { + return `${encodeURIComponent(key)}=`; + } + throw new GeminiNextGenAPIClientError(`Cannot stringify type ${typeof value}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`); + }) + .join('&'); + } + getUserAgent() { + return `${this.constructor.name}/JS ${VERSION}`; + } + defaultIdempotencyKey() { + return `stainless-node-retry-${uuid4()}`; + } + makeStatusError(status, error, message, headers) { + return APIError.generate(status, error, message, headers); + } + buildURL(path, query, defaultBaseURL) { + const baseURL = (!this.baseURLOverridden() && defaultBaseURL) || this.baseURL; + const url = isAbsoluteURL(path) ? + new URL(path) + : new URL(baseURL + (baseURL.endsWith('/') && path.startsWith('/') ? path.slice(1) : path)); + const defaultQuery = this.defaultQuery(); + if (!isEmptyObj(defaultQuery)) { + query = Object.assign(Object.assign({}, defaultQuery), query); + } + if (typeof query === 'object' && query && !Array.isArray(query)) { + url.search = this.stringifyQuery(query); + } + return url.toString(); + } + /** + * Used as a callback for mutating the given `FinalRequestOptions` object. + + */ + async prepareOptions(options) { + if (this.clientAdapter && + this.clientAdapter.isVertexAI() && + !options.path.startsWith(`/${this.apiVersion}/projects/`)) { + const oldPath = options.path.slice(this.apiVersion.length + 1); + options.path = `/${this.apiVersion}/projects/${this.clientAdapter.getProject()}/locations/${this.clientAdapter.getLocation()}${oldPath}`; + } + } + /** + * Used as a callback for mutating the given `RequestInit` object. + * + * This is useful for cases where you want to add certain headers based off of + * the request properties, e.g. `method` or `url`. + */ + async prepareRequest(request, { url, options }) { } + get(path, opts) { + return this.methodRequest('get', path, opts); + } + post(path, opts) { + return this.methodRequest('post', path, opts); + } + patch(path, opts) { + return this.methodRequest('patch', path, opts); + } + put(path, opts) { + return this.methodRequest('put', path, opts); + } + delete(path, opts) { + return this.methodRequest('delete', path, opts); + } + methodRequest(method, path, opts) { + return this.request(Promise.resolve(opts).then((opts) => { + return Object.assign({ method, path }, opts); + })); + } + request(options, remainingRetries = null) { + return new APIPromise(this, this.makeRequest(options, remainingRetries, undefined)); + } + async makeRequest(optionsInput, retriesRemaining, retryOfRequestLogID) { + var _b, _c, _d; + const options = await optionsInput; + const maxRetries = (_b = options.maxRetries) !== null && _b !== void 0 ? _b : this.maxRetries; + if (retriesRemaining == null) { + retriesRemaining = maxRetries; + } + await this.prepareOptions(options); + const { req, url, timeout } = await this.buildRequest(options, { + retryCount: maxRetries - retriesRemaining, + }); + await this.prepareRequest(req, { url, options }); + /** Not an API request ID, just for correlating local log entries. */ + const requestLogID = 'log_' + ((Math.random() * (1 << 24)) | 0).toString(16).padStart(6, '0'); + const retryLogStr = retryOfRequestLogID === undefined ? '' : `, retryOf: ${retryOfRequestLogID}`; + const startTime = Date.now(); + loggerFor(this).debug(`[${requestLogID}] sending request`, formatRequestDetails({ + retryOfRequestLogID, + method: options.method, + url, + options, + headers: req.headers, + })); + if ((_c = options.signal) === null || _c === void 0 ? void 0 : _c.aborted) { + throw new APIUserAbortError(); + } + const controller = new AbortController(); + const response = await this.fetchWithTimeout(url, req, timeout, controller).catch(castToError); + const headersTime = Date.now(); + if (response instanceof globalThis.Error) { + const retryMessage = `retrying, ${retriesRemaining} attempts remaining`; + if ((_d = options.signal) === null || _d === void 0 ? void 0 : _d.aborted) { + throw new APIUserAbortError(); + } + // detect native connection timeout errors + // deno throws "TypeError: error sending request for url (https://example/): client error (Connect): tcp connect error: Operation timed out (os error 60): Operation timed out (os error 60)" + // undici throws "TypeError: fetch failed" with cause "ConnectTimeoutError: Connect Timeout Error (attempted address: example:443, timeout: 1ms)" + // others do not provide enough information to distinguish timeouts from other connection errors + const isTimeout = isAbortError(response) || + /timed? ?out/i.test(String(response) + ('cause' in response ? String(response.cause) : '')); + if (retriesRemaining) { + loggerFor(this).info(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - ${retryMessage}`); + loggerFor(this).debug(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (${retryMessage})`, formatRequestDetails({ + retryOfRequestLogID, + url, + durationMs: headersTime - startTime, + message: response.message, + })); + return this.retryRequest(options, retriesRemaining, retryOfRequestLogID !== null && retryOfRequestLogID !== void 0 ? retryOfRequestLogID : requestLogID); + } + loggerFor(this).info(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - error; no more retries left`); + loggerFor(this).debug(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (error; no more retries left)`, formatRequestDetails({ + retryOfRequestLogID, + url, + durationMs: headersTime - startTime, + message: response.message, + })); + if (isTimeout) { + throw new APIConnectionTimeoutError(); + } + throw new APIConnectionError({ cause: response }); + } + const responseInfo = `[${requestLogID}${retryLogStr}] ${req.method} ${url} ${response.ok ? 'succeeded' : 'failed'} with status ${response.status} in ${headersTime - startTime}ms`; + if (!response.ok) { + const shouldRetry = await this.shouldRetry(response); + if (retriesRemaining && shouldRetry) { + const retryMessage = `retrying, ${retriesRemaining} attempts remaining`; + // We don't need the body of this response. + await CancelReadableStream(response.body); + loggerFor(this).info(`${responseInfo} - ${retryMessage}`); + loggerFor(this).debug(`[${requestLogID}] response error (${retryMessage})`, formatRequestDetails({ + retryOfRequestLogID, + url: response.url, + status: response.status, + headers: response.headers, + durationMs: headersTime - startTime, + })); + return this.retryRequest(options, retriesRemaining, retryOfRequestLogID !== null && retryOfRequestLogID !== void 0 ? retryOfRequestLogID : requestLogID, response.headers); + } + const retryMessage = shouldRetry ? `error; no more retries left` : `error; not retryable`; + loggerFor(this).info(`${responseInfo} - ${retryMessage}`); + const errText = await response.text().catch((err) => castToError(err).message); + const errJSON = safeJSON(errText); + const errMessage = errJSON ? undefined : errText; + loggerFor(this).debug(`[${requestLogID}] response error (${retryMessage})`, formatRequestDetails({ + retryOfRequestLogID, + url: response.url, + status: response.status, + headers: response.headers, + message: errMessage, + durationMs: Date.now() - startTime, + })); + // @ts-ignore + const err = this.makeStatusError(response.status, errJSON, errMessage, response.headers); + throw err; + } + loggerFor(this).info(responseInfo); + loggerFor(this).debug(`[${requestLogID}] response start`, formatRequestDetails({ + retryOfRequestLogID, + url: response.url, + status: response.status, + headers: response.headers, + durationMs: headersTime - startTime, + })); + return { response, options, controller, requestLogID, retryOfRequestLogID, startTime }; + } + async fetchWithTimeout(url, init, ms, controller) { + const _b = init || {}, { signal, method } = _b, options = __rest(_b, ["signal", "method"]); + const abort = this._makeAbort(controller); + if (signal) + signal.addEventListener('abort', abort, { once: true }); + const timeout = setTimeout(abort, ms); + const isReadableBody = (globalThis.ReadableStream && options.body instanceof globalThis.ReadableStream) || + (typeof options.body === 'object' && options.body !== null && Symbol.asyncIterator in options.body); + const fetchOptions = Object.assign(Object.assign(Object.assign({ signal: controller.signal }, (isReadableBody ? { duplex: 'half' } : {})), { method: 'GET' }), options); + if (method) { + // Custom methods like 'patch' need to be uppercased + // See https://github.com/nodejs/undici/issues/2294 + fetchOptions.method = method.toUpperCase(); + } + try { + // use undefined this binding; fetch errors if bound to something else in browser/cloudflare + return await this.fetch.call(undefined, url, fetchOptions); + } + finally { + clearTimeout(timeout); + } + } + async shouldRetry(response) { + // Note this is not a standard header. + const shouldRetryHeader = response.headers.get('x-should-retry'); + // If the server explicitly says whether or not to retry, obey. + if (shouldRetryHeader === 'true') + return true; + if (shouldRetryHeader === 'false') + return false; + // Retry on request timeouts. + if (response.status === 408) + return true; + // Retry on lock timeouts. + if (response.status === 409) + return true; + // Retry on rate limits. + if (response.status === 429) + return true; + // Retry internal errors. + if (response.status >= 500) + return true; + return false; + } + async retryRequest(options, retriesRemaining, requestLogID, responseHeaders) { + var _b; + let timeoutMillis; + // Note the `retry-after-ms` header may not be standard, but is a good idea and we'd like proactive support for it. + const retryAfterMillisHeader = responseHeaders === null || responseHeaders === void 0 ? void 0 : responseHeaders.get('retry-after-ms'); + if (retryAfterMillisHeader) { + const timeoutMs = parseFloat(retryAfterMillisHeader); + if (!Number.isNaN(timeoutMs)) { + timeoutMillis = timeoutMs; + } + } + // About the Retry-After header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After + const retryAfterHeader = responseHeaders === null || responseHeaders === void 0 ? void 0 : responseHeaders.get('retry-after'); + if (retryAfterHeader && !timeoutMillis) { + const timeoutSeconds = parseFloat(retryAfterHeader); + if (!Number.isNaN(timeoutSeconds)) { + timeoutMillis = timeoutSeconds * 1000; + } + else { + timeoutMillis = Date.parse(retryAfterHeader) - Date.now(); + } + } + // If the API asks us to wait a certain amount of time (and it's a reasonable amount), + // just do what it says, but otherwise calculate a default + if (!(timeoutMillis && 0 <= timeoutMillis && timeoutMillis < 60 * 1000)) { + const maxRetries = (_b = options.maxRetries) !== null && _b !== void 0 ? _b : this.maxRetries; + timeoutMillis = this.calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries); + } + await sleep$1(timeoutMillis); + return this.makeRequest(options, retriesRemaining - 1, requestLogID); + } + calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries) { + const initialRetryDelay = 0.5; + const maxRetryDelay = 8.0; + const numRetries = maxRetries - retriesRemaining; + // Apply exponential backoff, but not more than the max. + const sleepSeconds = Math.min(initialRetryDelay * Math.pow(2, numRetries), maxRetryDelay); + // Apply some jitter, take up to at most 25 percent of the retry time. + const jitter = 1 - Math.random() * 0.25; + return sleepSeconds * jitter * 1000; + } + async buildRequest(inputOptions, { retryCount = 0 } = {}) { + var _b, _c, _d; + const options = Object.assign({}, inputOptions); + const { method, path, query, defaultBaseURL } = options; + const url = this.buildURL(path, query, defaultBaseURL); + if ('timeout' in options) + validatePositiveInteger('timeout', options.timeout); + options.timeout = (_b = options.timeout) !== null && _b !== void 0 ? _b : this.timeout; + const { bodyHeaders, body } = this.buildBody({ options }); + const reqHeaders = await this.buildHeaders({ options: inputOptions, method, bodyHeaders, retryCount }); + const req = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ method, headers: reqHeaders }, (options.signal && { signal: options.signal })), (globalThis.ReadableStream && + body instanceof globalThis.ReadableStream && { duplex: 'half' })), (body && { body })), ((_c = this.fetchOptions) !== null && _c !== void 0 ? _c : {})), ((_d = options.fetchOptions) !== null && _d !== void 0 ? _d : {})); + return { req, url, timeout: options.timeout }; + } + async buildHeaders({ options, method, bodyHeaders, retryCount, }) { + let idempotencyHeaders = {}; + if (this.idempotencyHeader && method !== 'get') { + if (!options.idempotencyKey) + options.idempotencyKey = this.defaultIdempotencyKey(); + idempotencyHeaders[this.idempotencyHeader] = options.idempotencyKey; + } + const authHeaders = await this.authHeaders(options); + let headers = buildHeaders([ + idempotencyHeaders, + Object.assign(Object.assign({ Accept: 'application/json', 'User-Agent': this.getUserAgent(), 'X-Stainless-Retry-Count': String(retryCount) }, (options.timeout ? { 'X-Stainless-Timeout': String(Math.trunc(options.timeout / 1000)) } : {})), getPlatformHeaders()), + this._options.defaultHeaders, + bodyHeaders, + options.headers, + authHeaders, + ]); + this.validateHeaders(headers); + return headers.values; + } + _makeAbort(controller) { + // note: we can't just inline this method inside `fetchWithTimeout()` because then the closure + // would capture all request options, and cause a memory leak. + return () => controller.abort(); + } + buildBody({ options: { body, headers: rawHeaders } }) { + if (!body) { + return { bodyHeaders: undefined, body: undefined }; + } + const headers = buildHeaders([rawHeaders]); + if ( + // Pass raw type verbatim + ArrayBuffer.isView(body) || + body instanceof ArrayBuffer || + body instanceof DataView || + (typeof body === 'string' && + // Preserve legacy string encoding behavior for now + headers.values.has('content-type')) || + // `Blob` is superset of `File` + (globalThis.Blob && body instanceof globalThis.Blob) || + // `FormData` -> `multipart/form-data` + body instanceof FormData || + // `URLSearchParams` -> `application/x-www-form-urlencoded` + body instanceof URLSearchParams || + // Send chunked stream (each chunk has own `length`) + (globalThis.ReadableStream && body instanceof globalThis.ReadableStream)) { + return { bodyHeaders: undefined, body: body }; + } + else if (typeof body === 'object' && + (Symbol.asyncIterator in body || + (Symbol.iterator in body && 'next' in body && typeof body.next === 'function'))) { + return { bodyHeaders: undefined, body: ReadableStreamFrom(body) }; + } + else { + return this.encoder({ body, headers }); + } + } +} +BaseGeminiNextGenAPIClient.DEFAULT_TIMEOUT = 60000; // 1 minute +/** + * API Client for interfacing with the Gemini Next Gen API API. + */ +class GeminiNextGenAPIClient extends BaseGeminiNextGenAPIClient { + constructor() { + super(...arguments); + this.interactions = new Interactions(this); + } +} +_a = GeminiNextGenAPIClient; +GeminiNextGenAPIClient.GeminiNextGenAPIClient = _a; +GeminiNextGenAPIClient.GeminiNextGenAPIClientError = GeminiNextGenAPIClientError; +GeminiNextGenAPIClient.APIError = APIError; +GeminiNextGenAPIClient.APIConnectionError = APIConnectionError; +GeminiNextGenAPIClient.APIConnectionTimeoutError = APIConnectionTimeoutError; +GeminiNextGenAPIClient.APIUserAbortError = APIUserAbortError; +GeminiNextGenAPIClient.NotFoundError = NotFoundError; +GeminiNextGenAPIClient.ConflictError = ConflictError; +GeminiNextGenAPIClient.RateLimitError = RateLimitError; +GeminiNextGenAPIClient.BadRequestError = BadRequestError; +GeminiNextGenAPIClient.AuthenticationError = AuthenticationError; +GeminiNextGenAPIClient.InternalServerError = InternalServerError; +GeminiNextGenAPIClient.PermissionDeniedError = PermissionDeniedError; +GeminiNextGenAPIClient.UnprocessableEntityError = UnprocessableEntityError; +GeminiNextGenAPIClient.toFile = toFile; +GeminiNextGenAPIClient.Interactions = Interactions; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const GOOGLE_API_KEY_HEADER = 'x-goog-api-key'; +const REQUIRED_VERTEX_AI_SCOPE = 'https://www.googleapis.com/auth/cloud-platform'; +class NodeAuth { + constructor(opts) { + if (opts.apiKey !== undefined) { + this.apiKey = opts.apiKey; + return; + } + const vertexAuthOptions = buildGoogleAuthOptions(opts.googleAuthOptions); + this.googleAuth = new GoogleAuth(vertexAuthOptions); + } + async addAuthHeaders(headers, url) { + if (this.apiKey !== undefined) { + if (this.apiKey.startsWith('auth_tokens/')) { + throw new Error('Ephemeral tokens are only supported by the live API.'); + } + this.addKeyHeader(headers); + return; + } + return this.addGoogleAuthHeaders(headers, url); + } + addKeyHeader(headers) { + if (headers.get(GOOGLE_API_KEY_HEADER) !== null) { + return; + } + if (this.apiKey === undefined) { + // This should never happen, this method is only called + // when apiKey is set. + throw new Error('Trying to set API key header but apiKey is not set'); + } + headers.append(GOOGLE_API_KEY_HEADER, this.apiKey); + } + async addGoogleAuthHeaders(headers, url) { + if (this.googleAuth === undefined) { + // This should never happen, addGoogleAuthHeaders should only be + // called when there is no apiKey set and in these cases googleAuth + // is set. + throw new Error('Trying to set google-auth headers but googleAuth is unset'); + } + const authHeaders = await this.googleAuth.getRequestHeaders(url); + for (const [key, value] of authHeaders) { + if (headers.get(key) !== null) { + continue; + } + headers.append(key, value); + } + } +} +function buildGoogleAuthOptions(googleAuthOptions) { + let authOptions; + if (!googleAuthOptions) { + authOptions = { + scopes: [REQUIRED_VERTEX_AI_SCOPE], + }; + return authOptions; + } + else { + authOptions = googleAuthOptions; + if (!authOptions.scopes) { + authOptions.scopes = [REQUIRED_VERTEX_AI_SCOPE]; + return authOptions; + } + else if ((typeof authOptions.scopes === 'string' && + authOptions.scopes !== REQUIRED_VERTEX_AI_SCOPE) || + (Array.isArray(authOptions.scopes) && + authOptions.scopes.indexOf(REQUIRED_VERTEX_AI_SCOPE) < 0)) { + throw new Error(`Invalid auth scopes. Scopes must include: ${REQUIRED_VERTEX_AI_SCOPE}`); + } + return authOptions; + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class NodeDownloader { + async download(params, apiClient) { + if (params.downloadPath) { + const response = await downloadFile(params, apiClient); + if (response instanceof HttpResponse) { + const writer = createWriteStream(params.downloadPath); + const body = Readable.fromWeb(response.responseInternal.body); + body.pipe(writer); + await finished(writer); + } + else { + try { + await writeFile(params.downloadPath, response, { + encoding: 'base64', + }); + } + catch (error) { + throw new Error(`Failed to write file to ${params.downloadPath}: ${error}`); + } + } + } + } +} +async function downloadFile(params, apiClient) { + var _a, _b, _c; + const name = tFileName(params.file); + if (name !== undefined) { + return await apiClient.request({ + path: `files/${name}:download`, + httpMethod: 'GET', + queryParams: { + 'alt': 'media', + }, + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }); + } + else if (isGeneratedVideo(params.file)) { + const videoBytes = (_c = params.file.video) === null || _c === void 0 ? void 0 : _c.videoBytes; + if (typeof videoBytes === 'string') { + return videoBytes; + } + else { + throw new Error('Failed to download generated video, Uri or videoBytes not found.'); + } + } + else if (isVideo(params.file)) { + const videoBytes = params.file.videoBytes; + if (typeof videoBytes === 'string') { + return videoBytes; + } + else { + throw new Error('Failed to download video, Uri or videoBytes not found.'); + } + } + else { + throw new Error('Unsupported file type'); + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class NodeWebSocketFactory { + create(url, headers, callbacks) { + return new NodeWebSocket(url, headers, callbacks); + } +} +class NodeWebSocket { + constructor(url, headers, callbacks) { + this.url = url; + this.headers = headers; + this.callbacks = callbacks; + } + connect() { + this.ws = new NodeWs.WebSocket(this.url, { headers: this.headers }); + this.ws.onopen = this.callbacks.onopen; + this.ws.onerror = this.callbacks.onerror; + this.ws.onclose = this.callbacks.onclose; + this.ws.onmessage = this.callbacks.onmessage; + } + send(message) { + if (this.ws === undefined) { + throw new Error('WebSocket is not connected'); + } + this.ws.send(message); + } + close() { + if (this.ws === undefined) { + throw new Error('WebSocket is not connected'); + } + this.ws.close(); + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Code generated by the Google Gen AI SDK generator DO NOT EDIT. +function cancelTuningJobParametersToMldev(fromObject, _rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + return toObject; +} +function cancelTuningJobParametersToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + return toObject; +} +function cancelTuningJobResponseFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function cancelTuningJobResponseFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function createTuningJobConfigToMldev(fromObject, parentObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['validationDataset']) !== undefined) { + throw new Error('validationDataset parameter is not supported in Gemini API.'); + } + const fromTunedModelDisplayName = getValueByPath(fromObject, [ + 'tunedModelDisplayName', + ]); + if (parentObject !== undefined && fromTunedModelDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromTunedModelDisplayName); + } + if (getValueByPath(fromObject, ['description']) !== undefined) { + throw new Error('description parameter is not supported in Gemini API.'); + } + const fromEpochCount = getValueByPath(fromObject, ['epochCount']); + if (parentObject !== undefined && fromEpochCount != null) { + setValueByPath(parentObject, ['tuningTask', 'hyperparameters', 'epochCount'], fromEpochCount); + } + const fromLearningRateMultiplier = getValueByPath(fromObject, [ + 'learningRateMultiplier', + ]); + if (fromLearningRateMultiplier != null) { + setValueByPath(toObject, ['tuningTask', 'hyperparameters', 'learningRateMultiplier'], fromLearningRateMultiplier); + } + if (getValueByPath(fromObject, ['exportLastCheckpointOnly']) !== + undefined) { + throw new Error('exportLastCheckpointOnly parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['preTunedModelCheckpointId']) !== + undefined) { + throw new Error('preTunedModelCheckpointId parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['adapterSize']) !== undefined) { + throw new Error('adapterSize parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['tuningMode']) !== undefined) { + throw new Error('tuningMode parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['customBaseModel']) !== undefined) { + throw new Error('customBaseModel parameter is not supported in Gemini API.'); + } + const fromBatchSize = getValueByPath(fromObject, ['batchSize']); + if (parentObject !== undefined && fromBatchSize != null) { + setValueByPath(parentObject, ['tuningTask', 'hyperparameters', 'batchSize'], fromBatchSize); + } + const fromLearningRate = getValueByPath(fromObject, ['learningRate']); + if (parentObject !== undefined && fromLearningRate != null) { + setValueByPath(parentObject, ['tuningTask', 'hyperparameters', 'learningRate'], fromLearningRate); + } + if (getValueByPath(fromObject, ['labels']) !== undefined) { + throw new Error('labels parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['beta']) !== undefined) { + throw new Error('beta parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['baseTeacherModel']) !== undefined) { + throw new Error('baseTeacherModel parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['tunedTeacherModelSource']) !== undefined) { + throw new Error('tunedTeacherModelSource parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['sftLossWeightMultiplier']) !== undefined) { + throw new Error('sftLossWeightMultiplier parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['outputUri']) !== undefined) { + throw new Error('outputUri parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['encryptionSpec']) !== undefined) { + throw new Error('encryptionSpec parameter is not supported in Gemini API.'); + } + return toObject; +} +function createTuningJobConfigToVertex(fromObject, parentObject, rootObject) { + const toObject = {}; + let discriminatorValidationDataset = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorValidationDataset === undefined) { + discriminatorValidationDataset = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorValidationDataset === 'SUPERVISED_FINE_TUNING') { + const fromValidationDataset = getValueByPath(fromObject, [ + 'validationDataset', + ]); + if (parentObject !== undefined && fromValidationDataset != null) { + setValueByPath(parentObject, ['supervisedTuningSpec'], tuningValidationDatasetToVertex(fromValidationDataset)); + } + } + else if (discriminatorValidationDataset === 'PREFERENCE_TUNING') { + const fromValidationDataset = getValueByPath(fromObject, [ + 'validationDataset', + ]); + if (parentObject !== undefined && fromValidationDataset != null) { + setValueByPath(parentObject, ['preferenceOptimizationSpec'], tuningValidationDatasetToVertex(fromValidationDataset)); + } + } + else if (discriminatorValidationDataset === 'DISTILLATION') { + const fromValidationDataset = getValueByPath(fromObject, [ + 'validationDataset', + ]); + if (parentObject !== undefined && fromValidationDataset != null) { + setValueByPath(parentObject, ['distillationSpec'], tuningValidationDatasetToVertex(fromValidationDataset)); + } + } + const fromTunedModelDisplayName = getValueByPath(fromObject, [ + 'tunedModelDisplayName', + ]); + if (parentObject !== undefined && fromTunedModelDisplayName != null) { + setValueByPath(parentObject, ['tunedModelDisplayName'], fromTunedModelDisplayName); + } + const fromDescription = getValueByPath(fromObject, ['description']); + if (parentObject !== undefined && fromDescription != null) { + setValueByPath(parentObject, ['description'], fromDescription); + } + let discriminatorEpochCount = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorEpochCount === undefined) { + discriminatorEpochCount = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorEpochCount === 'SUPERVISED_FINE_TUNING') { + const fromEpochCount = getValueByPath(fromObject, ['epochCount']); + if (parentObject !== undefined && fromEpochCount != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'hyperParameters', 'epochCount'], fromEpochCount); + } + } + else if (discriminatorEpochCount === 'PREFERENCE_TUNING') { + const fromEpochCount = getValueByPath(fromObject, ['epochCount']); + if (parentObject !== undefined && fromEpochCount != null) { + setValueByPath(parentObject, ['preferenceOptimizationSpec', 'hyperParameters', 'epochCount'], fromEpochCount); + } + } + else if (discriminatorEpochCount === 'DISTILLATION') { + const fromEpochCount = getValueByPath(fromObject, ['epochCount']); + if (parentObject !== undefined && fromEpochCount != null) { + setValueByPath(parentObject, ['distillationSpec', 'hyperParameters', 'epochCount'], fromEpochCount); + } + } + let discriminatorLearningRateMultiplier = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorLearningRateMultiplier === undefined) { + discriminatorLearningRateMultiplier = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorLearningRateMultiplier === 'SUPERVISED_FINE_TUNING') { + const fromLearningRateMultiplier = getValueByPath(fromObject, [ + 'learningRateMultiplier', + ]); + if (parentObject !== undefined && fromLearningRateMultiplier != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'hyperParameters', 'learningRateMultiplier'], fromLearningRateMultiplier); + } + } + else if (discriminatorLearningRateMultiplier === 'PREFERENCE_TUNING') { + const fromLearningRateMultiplier = getValueByPath(fromObject, [ + 'learningRateMultiplier', + ]); + if (parentObject !== undefined && fromLearningRateMultiplier != null) { + setValueByPath(parentObject, [ + 'preferenceOptimizationSpec', + 'hyperParameters', + 'learningRateMultiplier', + ], fromLearningRateMultiplier); + } + } + else if (discriminatorLearningRateMultiplier === 'DISTILLATION') { + const fromLearningRateMultiplier = getValueByPath(fromObject, [ + 'learningRateMultiplier', + ]); + if (parentObject !== undefined && fromLearningRateMultiplier != null) { + setValueByPath(parentObject, ['distillationSpec', 'hyperParameters', 'learningRateMultiplier'], fromLearningRateMultiplier); + } + } + let discriminatorExportLastCheckpointOnly = getValueByPath(rootObject, ['config', 'method']); + if (discriminatorExportLastCheckpointOnly === undefined) { + discriminatorExportLastCheckpointOnly = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorExportLastCheckpointOnly === 'SUPERVISED_FINE_TUNING') { + const fromExportLastCheckpointOnly = getValueByPath(fromObject, [ + 'exportLastCheckpointOnly', + ]); + if (parentObject !== undefined && fromExportLastCheckpointOnly != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'exportLastCheckpointOnly'], fromExportLastCheckpointOnly); + } + } + else if (discriminatorExportLastCheckpointOnly === 'PREFERENCE_TUNING') { + const fromExportLastCheckpointOnly = getValueByPath(fromObject, [ + 'exportLastCheckpointOnly', + ]); + if (parentObject !== undefined && fromExportLastCheckpointOnly != null) { + setValueByPath(parentObject, ['preferenceOptimizationSpec', 'exportLastCheckpointOnly'], fromExportLastCheckpointOnly); + } + } + else if (discriminatorExportLastCheckpointOnly === 'DISTILLATION') { + const fromExportLastCheckpointOnly = getValueByPath(fromObject, [ + 'exportLastCheckpointOnly', + ]); + if (parentObject !== undefined && fromExportLastCheckpointOnly != null) { + setValueByPath(parentObject, ['distillationSpec', 'exportLastCheckpointOnly'], fromExportLastCheckpointOnly); + } + } + let discriminatorAdapterSize = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorAdapterSize === undefined) { + discriminatorAdapterSize = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorAdapterSize === 'SUPERVISED_FINE_TUNING') { + const fromAdapterSize = getValueByPath(fromObject, ['adapterSize']); + if (parentObject !== undefined && fromAdapterSize != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'hyperParameters', 'adapterSize'], fromAdapterSize); + } + } + else if (discriminatorAdapterSize === 'PREFERENCE_TUNING') { + const fromAdapterSize = getValueByPath(fromObject, ['adapterSize']); + if (parentObject !== undefined && fromAdapterSize != null) { + setValueByPath(parentObject, ['preferenceOptimizationSpec', 'hyperParameters', 'adapterSize'], fromAdapterSize); + } + } + else if (discriminatorAdapterSize === 'DISTILLATION') { + const fromAdapterSize = getValueByPath(fromObject, ['adapterSize']); + if (parentObject !== undefined && fromAdapterSize != null) { + setValueByPath(parentObject, ['distillationSpec', 'hyperParameters', 'adapterSize'], fromAdapterSize); + } + } + let discriminatorTuningMode = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorTuningMode === undefined) { + discriminatorTuningMode = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorTuningMode === 'SUPERVISED_FINE_TUNING') { + const fromTuningMode = getValueByPath(fromObject, ['tuningMode']); + if (parentObject !== undefined && fromTuningMode != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'tuningMode'], fromTuningMode); + } + } + const fromCustomBaseModel = getValueByPath(fromObject, [ + 'customBaseModel', + ]); + if (parentObject !== undefined && fromCustomBaseModel != null) { + setValueByPath(parentObject, ['customBaseModel'], fromCustomBaseModel); + } + let discriminatorBatchSize = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorBatchSize === undefined) { + discriminatorBatchSize = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorBatchSize === 'SUPERVISED_FINE_TUNING') { + const fromBatchSize = getValueByPath(fromObject, ['batchSize']); + if (parentObject !== undefined && fromBatchSize != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'hyperParameters', 'batchSize'], fromBatchSize); + } + } + let discriminatorLearningRate = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorLearningRate === undefined) { + discriminatorLearningRate = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorLearningRate === 'SUPERVISED_FINE_TUNING') { + const fromLearningRate = getValueByPath(fromObject, [ + 'learningRate', + ]); + if (parentObject !== undefined && fromLearningRate != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'hyperParameters', 'learningRate'], fromLearningRate); + } + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (parentObject !== undefined && fromLabels != null) { + setValueByPath(parentObject, ['labels'], fromLabels); + } + const fromBeta = getValueByPath(fromObject, ['beta']); + if (parentObject !== undefined && fromBeta != null) { + setValueByPath(parentObject, ['preferenceOptimizationSpec', 'hyperParameters', 'beta'], fromBeta); + } + const fromBaseTeacherModel = getValueByPath(fromObject, [ + 'baseTeacherModel', + ]); + if (parentObject !== undefined && fromBaseTeacherModel != null) { + setValueByPath(parentObject, ['distillationSpec', 'baseTeacherModel'], fromBaseTeacherModel); + } + const fromTunedTeacherModelSource = getValueByPath(fromObject, [ + 'tunedTeacherModelSource', + ]); + if (parentObject !== undefined && fromTunedTeacherModelSource != null) { + setValueByPath(parentObject, ['distillationSpec', 'tunedTeacherModelSource'], fromTunedTeacherModelSource); + } + const fromSftLossWeightMultiplier = getValueByPath(fromObject, [ + 'sftLossWeightMultiplier', + ]); + if (parentObject !== undefined && fromSftLossWeightMultiplier != null) { + setValueByPath(parentObject, ['distillationSpec', 'hyperParameters', 'sftLossWeightMultiplier'], fromSftLossWeightMultiplier); + } + const fromOutputUri = getValueByPath(fromObject, ['outputUri']); + if (parentObject !== undefined && fromOutputUri != null) { + setValueByPath(parentObject, ['outputUri'], fromOutputUri); + } + const fromEncryptionSpec = getValueByPath(fromObject, [ + 'encryptionSpec', + ]); + if (parentObject !== undefined && fromEncryptionSpec != null) { + setValueByPath(parentObject, ['encryptionSpec'], fromEncryptionSpec); + } + return toObject; +} +function createTuningJobParametersPrivateToMldev(fromObject, rootObject) { + const toObject = {}; + const fromBaseModel = getValueByPath(fromObject, ['baseModel']); + if (fromBaseModel != null) { + setValueByPath(toObject, ['baseModel'], fromBaseModel); + } + const fromPreTunedModel = getValueByPath(fromObject, [ + 'preTunedModel', + ]); + if (fromPreTunedModel != null) { + setValueByPath(toObject, ['preTunedModel'], fromPreTunedModel); + } + const fromTrainingDataset = getValueByPath(fromObject, [ + 'trainingDataset', + ]); + if (fromTrainingDataset != null) { + tuningDatasetToMldev(fromTrainingDataset); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createTuningJobConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function createTuningJobParametersPrivateToVertex(fromObject, rootObject) { + const toObject = {}; + const fromBaseModel = getValueByPath(fromObject, ['baseModel']); + if (fromBaseModel != null) { + setValueByPath(toObject, ['baseModel'], fromBaseModel); + } + const fromPreTunedModel = getValueByPath(fromObject, [ + 'preTunedModel', + ]); + if (fromPreTunedModel != null) { + setValueByPath(toObject, ['preTunedModel'], fromPreTunedModel); + } + const fromTrainingDataset = getValueByPath(fromObject, [ + 'trainingDataset', + ]); + if (fromTrainingDataset != null) { + tuningDatasetToVertex(fromTrainingDataset, toObject, rootObject); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createTuningJobConfigToVertex(fromConfig, toObject, rootObject); + } + return toObject; +} +function getTuningJobParametersToMldev(fromObject, _rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + return toObject; +} +function getTuningJobParametersToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + return toObject; +} +function listTuningJobsConfigToMldev(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + const fromFilter = getValueByPath(fromObject, ['filter']); + if (parentObject !== undefined && fromFilter != null) { + setValueByPath(parentObject, ['_query', 'filter'], fromFilter); + } + return toObject; +} +function listTuningJobsConfigToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + const fromFilter = getValueByPath(fromObject, ['filter']); + if (parentObject !== undefined && fromFilter != null) { + setValueByPath(parentObject, ['_query', 'filter'], fromFilter); + } + return toObject; +} +function listTuningJobsParametersToMldev(fromObject, rootObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listTuningJobsConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function listTuningJobsParametersToVertex(fromObject, rootObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listTuningJobsConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function listTuningJobsResponseFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromTuningJobs = getValueByPath(fromObject, ['tunedModels']); + if (fromTuningJobs != null) { + let transformedList = fromTuningJobs; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return tuningJobFromMldev(item); + }); + } + setValueByPath(toObject, ['tuningJobs'], transformedList); + } + return toObject; +} +function listTuningJobsResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromTuningJobs = getValueByPath(fromObject, ['tuningJobs']); + if (fromTuningJobs != null) { + let transformedList = fromTuningJobs; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return tuningJobFromVertex(item); + }); + } + setValueByPath(toObject, ['tuningJobs'], transformedList); + } + return toObject; +} +function tunedModelFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['name']); + if (fromModel != null) { + setValueByPath(toObject, ['model'], fromModel); + } + const fromEndpoint = getValueByPath(fromObject, ['name']); + if (fromEndpoint != null) { + setValueByPath(toObject, ['endpoint'], fromEndpoint); + } + return toObject; +} +function tuningDatasetToMldev(fromObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['gcsUri']) !== undefined) { + throw new Error('gcsUri parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['vertexDatasetResource']) !== undefined) { + throw new Error('vertexDatasetResource parameter is not supported in Gemini API.'); + } + const fromExamples = getValueByPath(fromObject, ['examples']); + if (fromExamples != null) { + let transformedList = fromExamples; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['examples', 'examples'], transformedList); + } + return toObject; +} +function tuningDatasetToVertex(fromObject, parentObject, rootObject) { + const toObject = {}; + let discriminatorGcsUri = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorGcsUri === undefined) { + discriminatorGcsUri = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorGcsUri === 'SUPERVISED_FINE_TUNING') { + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (parentObject !== undefined && fromGcsUri != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'trainingDatasetUri'], fromGcsUri); + } + } + else if (discriminatorGcsUri === 'PREFERENCE_TUNING') { + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (parentObject !== undefined && fromGcsUri != null) { + setValueByPath(parentObject, ['preferenceOptimizationSpec', 'trainingDatasetUri'], fromGcsUri); + } + } + else if (discriminatorGcsUri === 'DISTILLATION') { + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (parentObject !== undefined && fromGcsUri != null) { + setValueByPath(parentObject, ['distillationSpec', 'promptDatasetUri'], fromGcsUri); + } + } + let discriminatorVertexDatasetResource = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorVertexDatasetResource === undefined) { + discriminatorVertexDatasetResource = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorVertexDatasetResource === 'SUPERVISED_FINE_TUNING') { + const fromVertexDatasetResource = getValueByPath(fromObject, [ + 'vertexDatasetResource', + ]); + if (parentObject !== undefined && fromVertexDatasetResource != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'trainingDatasetUri'], fromVertexDatasetResource); + } + } + else if (discriminatorVertexDatasetResource === 'PREFERENCE_TUNING') { + const fromVertexDatasetResource = getValueByPath(fromObject, [ + 'vertexDatasetResource', + ]); + if (parentObject !== undefined && fromVertexDatasetResource != null) { + setValueByPath(parentObject, ['preferenceOptimizationSpec', 'trainingDatasetUri'], fromVertexDatasetResource); + } + } + else if (discriminatorVertexDatasetResource === 'DISTILLATION') { + const fromVertexDatasetResource = getValueByPath(fromObject, [ + 'vertexDatasetResource', + ]); + if (parentObject !== undefined && fromVertexDatasetResource != null) { + setValueByPath(parentObject, ['distillationSpec', 'promptDatasetUri'], fromVertexDatasetResource); + } + } + if (getValueByPath(fromObject, ['examples']) !== undefined) { + throw new Error('examples parameter is not supported in Vertex AI.'); + } + return toObject; +} +function tuningJobFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromState = getValueByPath(fromObject, ['state']); + if (fromState != null) { + setValueByPath(toObject, ['state'], tTuningJobStatus(fromState)); + } + const fromCreateTime = getValueByPath(fromObject, ['createTime']); + if (fromCreateTime != null) { + setValueByPath(toObject, ['createTime'], fromCreateTime); + } + const fromStartTime = getValueByPath(fromObject, [ + 'tuningTask', + 'startTime', + ]); + if (fromStartTime != null) { + setValueByPath(toObject, ['startTime'], fromStartTime); + } + const fromEndTime = getValueByPath(fromObject, [ + 'tuningTask', + 'completeTime', + ]); + if (fromEndTime != null) { + setValueByPath(toObject, ['endTime'], fromEndTime); + } + const fromUpdateTime = getValueByPath(fromObject, ['updateTime']); + if (fromUpdateTime != null) { + setValueByPath(toObject, ['updateTime'], fromUpdateTime); + } + const fromDescription = getValueByPath(fromObject, ['description']); + if (fromDescription != null) { + setValueByPath(toObject, ['description'], fromDescription); + } + const fromBaseModel = getValueByPath(fromObject, ['baseModel']); + if (fromBaseModel != null) { + setValueByPath(toObject, ['baseModel'], fromBaseModel); + } + const fromTunedModel = getValueByPath(fromObject, ['_self']); + if (fromTunedModel != null) { + setValueByPath(toObject, ['tunedModel'], tunedModelFromMldev(fromTunedModel)); + } + return toObject; +} +function tuningJobFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromState = getValueByPath(fromObject, ['state']); + if (fromState != null) { + setValueByPath(toObject, ['state'], tTuningJobStatus(fromState)); + } + const fromCreateTime = getValueByPath(fromObject, ['createTime']); + if (fromCreateTime != null) { + setValueByPath(toObject, ['createTime'], fromCreateTime); + } + const fromStartTime = getValueByPath(fromObject, ['startTime']); + if (fromStartTime != null) { + setValueByPath(toObject, ['startTime'], fromStartTime); + } + const fromEndTime = getValueByPath(fromObject, ['endTime']); + if (fromEndTime != null) { + setValueByPath(toObject, ['endTime'], fromEndTime); + } + const fromUpdateTime = getValueByPath(fromObject, ['updateTime']); + if (fromUpdateTime != null) { + setValueByPath(toObject, ['updateTime'], fromUpdateTime); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromDescription = getValueByPath(fromObject, ['description']); + if (fromDescription != null) { + setValueByPath(toObject, ['description'], fromDescription); + } + const fromBaseModel = getValueByPath(fromObject, ['baseModel']); + if (fromBaseModel != null) { + setValueByPath(toObject, ['baseModel'], fromBaseModel); + } + const fromTunedModel = getValueByPath(fromObject, ['tunedModel']); + if (fromTunedModel != null) { + setValueByPath(toObject, ['tunedModel'], fromTunedModel); + } + const fromPreTunedModel = getValueByPath(fromObject, [ + 'preTunedModel', + ]); + if (fromPreTunedModel != null) { + setValueByPath(toObject, ['preTunedModel'], fromPreTunedModel); + } + const fromSupervisedTuningSpec = getValueByPath(fromObject, [ + 'supervisedTuningSpec', + ]); + if (fromSupervisedTuningSpec != null) { + setValueByPath(toObject, ['supervisedTuningSpec'], fromSupervisedTuningSpec); + } + const fromPreferenceOptimizationSpec = getValueByPath(fromObject, [ + 'preferenceOptimizationSpec', + ]); + if (fromPreferenceOptimizationSpec != null) { + setValueByPath(toObject, ['preferenceOptimizationSpec'], fromPreferenceOptimizationSpec); + } + const fromDistillationSpec = getValueByPath(fromObject, [ + 'distillationSpec', + ]); + if (fromDistillationSpec != null) { + setValueByPath(toObject, ['distillationSpec'], fromDistillationSpec); + } + const fromTuningDataStats = getValueByPath(fromObject, [ + 'tuningDataStats', + ]); + if (fromTuningDataStats != null) { + setValueByPath(toObject, ['tuningDataStats'], fromTuningDataStats); + } + const fromEncryptionSpec = getValueByPath(fromObject, [ + 'encryptionSpec', + ]); + if (fromEncryptionSpec != null) { + setValueByPath(toObject, ['encryptionSpec'], fromEncryptionSpec); + } + const fromPartnerModelTuningSpec = getValueByPath(fromObject, [ + 'partnerModelTuningSpec', + ]); + if (fromPartnerModelTuningSpec != null) { + setValueByPath(toObject, ['partnerModelTuningSpec'], fromPartnerModelTuningSpec); + } + const fromCustomBaseModel = getValueByPath(fromObject, [ + 'customBaseModel', + ]); + if (fromCustomBaseModel != null) { + setValueByPath(toObject, ['customBaseModel'], fromCustomBaseModel); + } + const fromExperiment = getValueByPath(fromObject, ['experiment']); + if (fromExperiment != null) { + setValueByPath(toObject, ['experiment'], fromExperiment); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (fromLabels != null) { + setValueByPath(toObject, ['labels'], fromLabels); + } + const fromOutputUri = getValueByPath(fromObject, ['outputUri']); + if (fromOutputUri != null) { + setValueByPath(toObject, ['outputUri'], fromOutputUri); + } + const fromPipelineJob = getValueByPath(fromObject, ['pipelineJob']); + if (fromPipelineJob != null) { + setValueByPath(toObject, ['pipelineJob'], fromPipelineJob); + } + const fromServiceAccount = getValueByPath(fromObject, [ + 'serviceAccount', + ]); + if (fromServiceAccount != null) { + setValueByPath(toObject, ['serviceAccount'], fromServiceAccount); + } + const fromTunedModelDisplayName = getValueByPath(fromObject, [ + 'tunedModelDisplayName', + ]); + if (fromTunedModelDisplayName != null) { + setValueByPath(toObject, ['tunedModelDisplayName'], fromTunedModelDisplayName); + } + const fromVeoTuningSpec = getValueByPath(fromObject, [ + 'veoTuningSpec', + ]); + if (fromVeoTuningSpec != null) { + setValueByPath(toObject, ['veoTuningSpec'], fromVeoTuningSpec); + } + return toObject; +} +function tuningOperationFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + return toObject; +} +function tuningValidationDatasetToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (fromGcsUri != null) { + setValueByPath(toObject, ['validationDatasetUri'], fromGcsUri); + } + const fromVertexDatasetResource = getValueByPath(fromObject, [ + 'vertexDatasetResource', + ]); + if (fromVertexDatasetResource != null) { + setValueByPath(toObject, ['validationDatasetUri'], fromVertexDatasetResource); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Tunings extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + /** + * Lists tuning jobs. + * + * @param params - The parameters for the list request. + * @return - A pager of tuning jobs. + * + * @example + * ```ts + * const tuningJobs = await ai.tunings.list({config: {'pageSize': 2}}); + * for await (const tuningJob of tuningJobs) { + * console.log(tuningJob); + * } + * ``` + */ + this.list = async (params = {}) => { + return new Pager(PagedItem.PAGED_ITEM_TUNING_JOBS, (x) => this.listInternal(x), await this.listInternal(params), params); + }; + /** + * Gets a TuningJob. + * + * @param name - The resource name of the tuning job. + * @return - A TuningJob object. + * + * @experimental - The SDK's tuning implementation is experimental, and may + * change in future versions. + */ + this.get = async (params) => { + return await this.getInternal(params); + }; + /** + * Creates a supervised fine-tuning job. + * + * @param params - The parameters for the tuning job. + * @return - A TuningJob operation. + * + * @experimental - The SDK's tuning implementation is experimental, and may + * change in future versions. + */ + this.tune = async (params) => { + var _a; + if (this.apiClient.isVertexAI()) { + if (params.baseModel.startsWith('projects/')) { + const preTunedModel = { + tunedModelName: params.baseModel, + }; + if ((_a = params.config) === null || _a === void 0 ? void 0 : _a.preTunedModelCheckpointId) { + preTunedModel.checkpointId = params.config.preTunedModelCheckpointId; + } + const paramsPrivate = Object.assign(Object.assign({}, params), { preTunedModel: preTunedModel }); + paramsPrivate.baseModel = undefined; + return await this.tuneInternal(paramsPrivate); + } + else { + const paramsPrivate = Object.assign({}, params); + return await this.tuneInternal(paramsPrivate); + } + } + else { + const paramsPrivate = Object.assign({}, params); + const operation = await this.tuneMldevInternal(paramsPrivate); + let tunedModelName = ''; + if (operation['metadata'] !== undefined && + operation['metadata']['tunedModel'] !== undefined) { + tunedModelName = operation['metadata']['tunedModel']; + } + else if (operation['name'] !== undefined && + operation['name'].includes('/operations/')) { + tunedModelName = operation['name'].split('/operations/')[0]; + } + const tuningJob = { + name: tunedModelName, + state: JobState.JOB_STATE_QUEUED, + }; + return tuningJob; + } + }; + } + async getInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = getTuningJobParametersToVertex(params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = tuningJobFromVertex(apiResponse); + return resp; + }); + } + else { + const body = getTuningJobParametersToMldev(params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = tuningJobFromMldev(apiResponse); + return resp; + }); + } + } + async listInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = listTuningJobsParametersToVertex(params); + path = formatMap('tuningJobs', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listTuningJobsResponseFromVertex(apiResponse); + const typedResp = new ListTuningJobsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = listTuningJobsParametersToMldev(params); + path = formatMap('tunedModels', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listTuningJobsResponseFromMldev(apiResponse); + const typedResp = new ListTuningJobsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Cancels a tuning job. + * + * @param params - The parameters for the cancel request. + * @return The empty response returned by the API. + * + * @example + * ```ts + * await ai.tunings.cancel({name: '...'}); // The server-generated resource name. + * ``` + */ + async cancel(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = cancelTuningJobParametersToVertex(params); + path = formatMap('{name}:cancel', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = cancelTuningJobResponseFromVertex(apiResponse); + const typedResp = new CancelTuningJobResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = cancelTuningJobParametersToMldev(params); + path = formatMap('{name}:cancel', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = cancelTuningJobResponseFromMldev(apiResponse); + const typedResp = new CancelTuningJobResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + async tuneInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = createTuningJobParametersPrivateToVertex(params, params); + path = formatMap('tuningJobs', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = tuningJobFromVertex(apiResponse); + return resp; + }); + } + else { + throw new Error('This method is only supported by the Vertex AI.'); + } + } + async tuneMldevInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = createTuningJobParametersPrivateToMldev(params); + path = formatMap('tunedModels', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = tuningOperationFromMldev(apiResponse); + return resp; + }); + } + } +} + +const MAX_CHUNK_SIZE = 1024 * 1024 * 8; // bytes +const MAX_RETRY_COUNT = 3; +const INITIAL_RETRY_DELAY_MS = 1000; +const DELAY_MULTIPLIER = 2; +const X_GOOG_UPLOAD_STATUS_HEADER_FIELD = 'x-goog-upload-status'; +async function uploadBlob(file, uploadUrl, apiClient) { + var _a; + const response = await uploadBlobInternal(file, uploadUrl, apiClient); + const responseJson = (await (response === null || response === void 0 ? void 0 : response.json())); + if (((_a = response === null || response === void 0 ? void 0 : response.headers) === null || _a === void 0 ? void 0 : _a[X_GOOG_UPLOAD_STATUS_HEADER_FIELD]) !== 'final') { + throw new Error('Failed to upload file: Upload status is not finalized.'); + } + return responseJson['file']; +} +async function uploadBlobToFileSearchStore(file, uploadUrl, apiClient) { + var _a; + const response = await uploadBlobInternal(file, uploadUrl, apiClient); + const responseJson = (await (response === null || response === void 0 ? void 0 : response.json())); + if (((_a = response === null || response === void 0 ? void 0 : response.headers) === null || _a === void 0 ? void 0 : _a[X_GOOG_UPLOAD_STATUS_HEADER_FIELD]) !== 'final') { + throw new Error('Failed to upload file: Upload status is not finalized.'); + } + const resp = uploadToFileSearchStoreOperationFromMldev(responseJson); + const typedResp = new UploadToFileSearchStoreOperation(); + Object.assign(typedResp, resp); + return typedResp; +} +async function uploadBlobInternal(file, uploadUrl, apiClient) { + var _a, _b; + let fileSize = 0; + let offset = 0; + let response = new HttpResponse(new Response()); + let uploadCommand = 'upload'; + fileSize = file.size; + while (offset < fileSize) { + const chunkSize = Math.min(MAX_CHUNK_SIZE, fileSize - offset); + const chunk = file.slice(offset, offset + chunkSize); + if (offset + chunkSize >= fileSize) { + uploadCommand += ', finalize'; + } + let retryCount = 0; + let currentDelayMs = INITIAL_RETRY_DELAY_MS; + while (retryCount < MAX_RETRY_COUNT) { + response = await apiClient.request({ + path: '', + body: chunk, + httpMethod: 'POST', + httpOptions: { + apiVersion: '', + baseUrl: uploadUrl, + headers: { + 'X-Goog-Upload-Command': uploadCommand, + 'X-Goog-Upload-Offset': String(offset), + 'Content-Length': String(chunkSize), + }, + }, + }); + if ((_a = response === null || response === void 0 ? void 0 : response.headers) === null || _a === void 0 ? void 0 : _a[X_GOOG_UPLOAD_STATUS_HEADER_FIELD]) { + break; + } + retryCount++; + await sleep(currentDelayMs); + currentDelayMs = currentDelayMs * DELAY_MULTIPLIER; + } + offset += chunkSize; + // The `x-goog-upload-status` header field can be `active`, `final` and + //`cancelled` in resposne. + if (((_b = response === null || response === void 0 ? void 0 : response.headers) === null || _b === void 0 ? void 0 : _b[X_GOOG_UPLOAD_STATUS_HEADER_FIELD]) !== 'active') { + break; + } + // TODO(b/401391430) Investigate why the upload status is not finalized + // even though all content has been uploaded. + if (fileSize <= offset) { + throw new Error('All content has been uploaded, but the upload status is not finalized.'); + } + } + return response; +} +async function getBlobStat(file) { + const fileStat = { size: file.size, type: file.type }; + return fileStat; +} +function sleep(ms) { + return new Promise((resolvePromise) => setTimeout(resolvePromise, ms)); +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class NodeUploader { + async stat(file) { + const fileStat = { size: 0, type: undefined }; + if (typeof file === 'string') { + const originalStat = await fs.stat(file); + fileStat.size = originalStat.size; + fileStat.type = this.inferMimeType(file); + return fileStat; + } + else { + return await getBlobStat(file); + } + } + async upload(file, uploadUrl, apiClient) { + if (typeof file === 'string') { + return await this.uploadFileFromPath(file, uploadUrl, apiClient); + } + else { + return uploadBlob(file, uploadUrl, apiClient); + } + } + async uploadToFileSearchStore(file, uploadUrl, apiClient) { + if (typeof file === 'string') { + return await this.uploadFileToFileSearchStoreFromPath(file, uploadUrl, apiClient); + } + else { + return uploadBlobToFileSearchStore(file, uploadUrl, apiClient); + } + } + /** + * Infers the MIME type of a file based on its extension. + * + * @param filePath The path to the file. + * @returns The MIME type of the file, or undefined if it cannot be inferred. + */ + inferMimeType(filePath) { + // Get the file extension. + const fileExtension = filePath.slice(filePath.lastIndexOf('.') + 1); + // Create a map of file extensions to MIME types. + const mimeTypes = { + 'aac': 'audio/aac', + 'abw': 'application/x-abiword', + 'arc': 'application/x-freearc', + 'avi': 'video/x-msvideo', + 'azw': 'application/vnd.amazon.ebook', + 'bin': 'application/octet-stream', + 'bmp': 'image/bmp', + 'bz': 'application/x-bzip', + 'bz2': 'application/x-bzip2', + 'csh': 'application/x-csh', + 'css': 'text/css', + 'csv': 'text/csv', + 'doc': 'application/msword', + 'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'eot': 'application/vnd.ms-fontobject', + 'epub': 'application/epub+zip', + 'gz': 'application/gzip', + 'gif': 'image/gif', + 'htm': 'text/html', + 'html': 'text/html', + 'ico': 'image/vnd.microsoft.icon', + 'ics': 'text/calendar', + 'jar': 'application/java-archive', + 'jpeg': 'image/jpeg', + 'jpg': 'image/jpeg', + 'js': 'text/javascript', + 'json': 'application/json', + 'jsonld': 'application/ld+json', + 'kml': 'application/vnd.google-earth.kml+xml', + 'kmz': 'application/vnd.google-earth.kmz+xml', + 'mjs': 'text/javascript', + 'mp3': 'audio/mpeg', + 'mp4': 'video/mp4', + 'mpeg': 'video/mpeg', + 'mpkg': 'application/vnd.apple.installer+xml', + 'odt': 'application/vnd.oasis.opendocument.text', + 'oga': 'audio/ogg', + 'ogv': 'video/ogg', + 'ogx': 'application/ogg', + 'opus': 'audio/opus', + 'otf': 'font/otf', + 'png': 'image/png', + 'pdf': 'application/pdf', + 'php': 'application/x-httpd-php', + 'ppt': 'application/vnd.ms-powerpoint', + 'pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + 'rar': 'application/vnd.rar', + 'rtf': 'application/rtf', + 'sh': 'application/x-sh', + 'svg': 'image/svg+xml', + 'swf': 'application/x-shockwave-flash', + 'tar': 'application/x-tar', + 'tif': 'image/tiff', + 'tiff': 'image/tiff', + 'ts': 'video/mp2t', + 'ttf': 'font/ttf', + 'txt': 'text/plain', + 'vsd': 'application/vnd.visio', + 'wav': 'audio/wav', + 'weba': 'audio/webm', + 'webm': 'video/webm', + 'webp': 'image/webp', + 'woff': 'font/woff', + 'woff2': 'font/woff2', + 'xhtml': 'application/xhtml+xml', + 'xls': 'application/vnd.ms-excel', + 'xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'xml': 'application/xml', + 'xul': 'application/vnd.mozilla.xul+xml', + 'zip': 'application/zip', + '3gp': 'video/3gpp', + '3g2': 'video/3gpp2', + '7z': 'application/x-7z-compressed', + }; + // Look up the MIME type based on the file extension. + const mimeType = mimeTypes[fileExtension.toLowerCase()]; + // Return the MIME type. + return mimeType; + } + async uploadFileFromPath(file, uploadUrl, apiClient) { + var _a; + const response = await this.uploadFileFromPathInternal(file, uploadUrl, apiClient); + const responseJson = (await (response === null || response === void 0 ? void 0 : response.json())); + if (((_a = response === null || response === void 0 ? void 0 : response.headers) === null || _a === void 0 ? void 0 : _a[X_GOOG_UPLOAD_STATUS_HEADER_FIELD]) !== 'final') { + throw new Error('Failed to upload file: Upload status is not finalized.'); + } + return responseJson['file']; + } + async uploadFileToFileSearchStoreFromPath(file, uploadUrl, apiClient) { + var _a; + const response = await this.uploadFileFromPathInternal(file, uploadUrl, apiClient); + const responseJson = (await (response === null || response === void 0 ? void 0 : response.json())); + if (((_a = response === null || response === void 0 ? void 0 : response.headers) === null || _a === void 0 ? void 0 : _a[X_GOOG_UPLOAD_STATUS_HEADER_FIELD]) !== 'final') { + throw new Error('Failed to upload file: Upload status is not finalized.'); + } + const resp = uploadToFileSearchStoreOperationFromMldev(responseJson); + const typedResp = new UploadToFileSearchStoreOperation(); + Object.assign(typedResp, resp); + return typedResp; + } + async uploadFileFromPathInternal(file, uploadUrl, apiClient) { + var _a, _b; + let fileSize = 0; + let offset = 0; + let response = new HttpResponse(new Response()); + let uploadCommand = 'upload'; + let fileHandle; + const fileName = path$1.basename(file); + try { + fileHandle = await fs.open(file, 'r'); + if (!fileHandle) { + throw new Error(`Failed to open file`); + } + fileSize = (await fileHandle.stat()).size; + while (offset < fileSize) { + const chunkSize = Math.min(MAX_CHUNK_SIZE, fileSize - offset); + if (offset + chunkSize >= fileSize) { + uploadCommand += ', finalize'; + } + const buffer = new Uint8Array(chunkSize); + const { bytesRead: bytesRead } = await fileHandle.read(buffer, 0, chunkSize, offset); + if (bytesRead !== chunkSize) { + throw new Error(`Failed to read ${chunkSize} bytes from file at offset ${offset}. bytes actually read: ${bytesRead}`); + } + const chunk = new Blob([buffer]); + let retryCount = 0; + let currentDelayMs = INITIAL_RETRY_DELAY_MS; + while (retryCount < MAX_RETRY_COUNT) { + response = await apiClient.request({ + path: '', + body: chunk, + httpMethod: 'POST', + httpOptions: { + apiVersion: '', + baseUrl: uploadUrl, + headers: { + 'X-Goog-Upload-Command': uploadCommand, + 'X-Goog-Upload-Offset': String(offset), + 'Content-Length': String(bytesRead), + 'X-Goog-Upload-File-Name': fileName, + }, + }, + }); + if ((_a = response === null || response === void 0 ? void 0 : response.headers) === null || _a === void 0 ? void 0 : _a[X_GOOG_UPLOAD_STATUS_HEADER_FIELD]) { + break; + } + retryCount++; + await sleep(currentDelayMs); + currentDelayMs = currentDelayMs * DELAY_MULTIPLIER; + } + offset += bytesRead; + // The `x-goog-upload-status` header field can be `active`, `final` and + //`cancelled` in resposne. + if (((_b = response === null || response === void 0 ? void 0 : response.headers) === null || _b === void 0 ? void 0 : _b[X_GOOG_UPLOAD_STATUS_HEADER_FIELD]) !== 'active') { + break; + } + if (fileSize <= offset) { + throw new Error('All content has been uploaded, but the upload status is not finalized.'); + } + } + return response; + } + finally { + // Ensure the file handle is always closed + if (fileHandle) { + await fileHandle.close(); + } + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class NodeFiles extends Files { + /** + * Registers Google Cloud Storage files for use with the API. + * This method is only available in Node.js environments. + */ + async registerFiles(params) { + if (typeof process === 'undefined' || + !process.versions || + !process.versions.node) { + throw new Error('registerFiles is only supported in Node.js environments.'); + } + const googleAuth = params.auth; + const authHeaders = await googleAuth.getRequestHeaders(); + const config = params.config || {}; + const httpOptions = config.httpOptions || {}; + const headers = Object.assign({}, (httpOptions.headers || {})); + if (authHeaders) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + if (typeof authHeaders[Symbol.iterator] === 'function') { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + for (const [key, value] of authHeaders) { + headers[key] = value; + } + } + else { + for (const [key, value] of Object.entries(authHeaders)) { + headers[key] = value; + } + } + } + return this._registerFiles({ + uris: params.uris, + config: Object.assign(Object.assign({}, config), { httpOptions: Object.assign(Object.assign({}, httpOptions), { headers }) }), + }); + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const LANGUAGE_LABEL_PREFIX = 'gl-node/'; +/** + * The Google GenAI SDK. + * + * @remarks + * Provides access to the GenAI features through either the {@link + * https://cloud.google.com/vertex-ai/docs/reference/rest | Gemini API} or + * the {@link https://cloud.google.com/vertex-ai/docs/reference/rest | Vertex AI + * API}. + * + * The {@link GoogleGenAIOptions.vertexai} value determines which of the API + * services to use. + * + * When using the Gemini API, a {@link GoogleGenAIOptions.apiKey} must also be + * set. When using Vertex AI, both {@link GoogleGenAIOptions.project} and {@link + * GoogleGenAIOptions.location} must be set, or a {@link + * GoogleGenAIOptions.apiKey} must be set when using Express Mode. + * + * Explicitly passed in values in {@link GoogleGenAIOptions} will always take + * precedence over environment variables. If both project/location and api_key + * exist in the environment variables, the project/location will be used. + * + * @example + * Initializing the SDK for using the Gemini API: + * ```ts + * import {GoogleGenAI} from '@google/genai'; + * const ai = new GoogleGenAI({apiKey: 'GEMINI_API_KEY'}); + * ``` + * + * @example + * Initializing the SDK for using the Vertex AI API: + * ```ts + * import {GoogleGenAI} from '@google/genai'; + * const ai = new GoogleGenAI({ + * vertexai: true, + * project: 'PROJECT_ID', + * location: 'PROJECT_LOCATION' + * }); + * ``` + * + */ +class GoogleGenAI { + get interactions() { + var _a; + if (this._interactions !== undefined) { + return this._interactions; + } + console.warn('GoogleGenAI.interactions: Interactions usage is experimental and may change in future versions.'); + const httpOpts = this.httpOptions; + // Unsupported Options Warnings + if (httpOpts === null || httpOpts === void 0 ? void 0 : httpOpts.extraBody) { + console.warn('GoogleGenAI.interactions: Client level httpOptions.extraBody is not supported by the interactions client and will be ignored.'); + } + const nextGenClient = new GeminiNextGenAPIClient({ + baseURL: this.apiClient.getBaseUrl(), + apiKey: this.apiKey, + apiVersion: this.apiClient.getApiVersion(), + clientAdapter: this.apiClient, + defaultHeaders: this.apiClient.getDefaultHeaders(), + timeout: httpOpts === null || httpOpts === void 0 ? void 0 : httpOpts.timeout, + maxRetries: (_a = httpOpts === null || httpOpts === void 0 ? void 0 : httpOpts.retryOptions) === null || _a === void 0 ? void 0 : _a.attempts, + }); + this._interactions = nextGenClient.interactions; + return this._interactions; + } + constructor(options) { + var _a, _b, _c, _d, _e, _f; + // Validate explicitly set initializer values. + if ((options.project || options.location) && options.apiKey) { + throw new Error('Project/location and API key are mutually exclusive in the client initializer.'); + } + this.vertexai = + (_b = (_a = options.vertexai) !== null && _a !== void 0 ? _a : getBooleanEnv('GOOGLE_GENAI_USE_VERTEXAI')) !== null && _b !== void 0 ? _b : false; + const envApiKey = getApiKeyFromEnv(); + const envProject = getEnv('GOOGLE_CLOUD_PROJECT'); + const envLocation = getEnv('GOOGLE_CLOUD_LOCATION'); + this.apiKey = (_c = options.apiKey) !== null && _c !== void 0 ? _c : envApiKey; + this.project = (_d = options.project) !== null && _d !== void 0 ? _d : envProject; + this.location = (_e = options.location) !== null && _e !== void 0 ? _e : envLocation; + if (!this.vertexai && !this.apiKey) { + throw new Error('API key must be set when using the Gemini API.'); + } + // Handle when to use Vertex AI in express mode (api key) + if (options.vertexai) { + if ((_f = options.googleAuthOptions) === null || _f === void 0 ? void 0 : _f.credentials) { + // Explicit credentials take precedence over implicit api_key. + console.debug('The user provided Google Cloud credentials will take precedence' + + ' over the API key from the environment variable.'); + this.apiKey = undefined; + } + // Explicit api_key and explicit project/location already handled above. + if ((envProject || envLocation) && options.apiKey) { + // Explicit api_key takes precedence over implicit project/location. + console.debug('The user provided Vertex AI API key will take precedence over' + + ' the project/location from the environment variables.'); + this.project = undefined; + this.location = undefined; + } + else if ((options.project || options.location) && envApiKey) { + // Explicit project/location takes precedence over implicit api_key. + console.debug('The user provided project/location will take precedence over' + + ' the API key from the environment variables.'); + this.apiKey = undefined; + } + else if ((envProject || envLocation) && envApiKey) { + // Implicit project/location takes precedence over implicit api_key. + console.debug('The project/location from the environment variables will take' + + ' precedence over the API key from the environment variables.'); + this.apiKey = undefined; + } + if (!this.location && !this.apiKey) { + this.location = 'global'; + } + } + const baseUrl = getBaseUrl(options.httpOptions, options.vertexai, getEnv('GOOGLE_VERTEX_BASE_URL'), getEnv('GOOGLE_GEMINI_BASE_URL')); + if (baseUrl) { + if (options.httpOptions) { + options.httpOptions.baseUrl = baseUrl; + } + else { + options.httpOptions = { baseUrl: baseUrl }; + } + } + this.apiVersion = options.apiVersion; + this.httpOptions = options.httpOptions; + const auth = new NodeAuth({ + apiKey: this.apiKey, + googleAuthOptions: options.googleAuthOptions, + }); + this.apiClient = new ApiClient({ + auth: auth, + project: this.project, + location: this.location, + apiVersion: this.apiVersion, + apiKey: this.apiKey, + vertexai: this.vertexai, + httpOptions: this.httpOptions, + userAgentExtra: LANGUAGE_LABEL_PREFIX + process.version, + uploader: new NodeUploader(), + downloader: new NodeDownloader(), + }); + this.models = new Models(this.apiClient); + this.live = new Live(this.apiClient, auth, new NodeWebSocketFactory()); + this.batches = new Batches(this.apiClient); + this.chats = new Chats(this.models, this.apiClient); + this.caches = new Caches(this.apiClient); + this.files = new NodeFiles(this.apiClient); + this.operations = new Operations(this.apiClient); + this.authTokens = new Tokens(this.apiClient); + this.tunings = new Tunings(this.apiClient); + this.fileSearchStores = new FileSearchStores(this.apiClient); + } +} +function getEnv(env) { + var _a, _b, _c; + return (_c = (_b = (_a = process === null || process === void 0 ? void 0 : process.env) === null || _a === void 0 ? void 0 : _a[env]) === null || _b === void 0 ? void 0 : _b.trim()) !== null && _c !== void 0 ? _c : undefined; +} +function getBooleanEnv(env) { + return stringToBoolean(getEnv(env)); +} +function stringToBoolean(str) { + if (str === undefined) { + return false; + } + return str.toLowerCase() === 'true'; +} +function getApiKeyFromEnv() { + const envGoogleApiKey = getEnv('GOOGLE_API_KEY'); + const envGeminiApiKey = getEnv('GEMINI_API_KEY'); + if (envGoogleApiKey && envGeminiApiKey) { + console.warn('Both GOOGLE_API_KEY and GEMINI_API_KEY are set. Using GOOGLE_API_KEY.'); + } + return envGoogleApiKey || envGeminiApiKey || undefined; +} + +export { ActivityHandling, AdapterSize, ApiError, ApiSpec, AuthType, Batches, Behavior, BlockedReason, Caches, CancelTuningJobResponse, Chat, Chats, ComputeTokensResponse, ContentReferenceImage, ControlReferenceImage, ControlReferenceType, CountTokensResponse, CreateFileResponse, DeleteCachedContentResponse, DeleteFileResponse, DeleteModelResponse, DocumentState, DynamicRetrievalConfigMode, EditImageResponse, EditMode, EmbedContentResponse, EndSensitivity, Environment, FeatureSelectionPreference, FileSource, FileState, Files, FinishReason, FunctionCallingConfigMode, FunctionResponse, FunctionResponseBlob, FunctionResponseFileData, FunctionResponsePart, FunctionResponseScheduling, GenerateContentResponse, GenerateContentResponsePromptFeedback, GenerateContentResponseUsageMetadata, GenerateImagesResponse, GenerateVideosOperation, GenerateVideosResponse, GoogleGenAI, HarmBlockMethod, HarmBlockThreshold, HarmCategory, HarmProbability, HarmSeverity, HttpElementLocation, HttpResponse, ImagePromptLanguage, ImportFileOperation, ImportFileResponse, InlinedEmbedContentResponse, InlinedResponse, JobState, Language, ListBatchJobsResponse, ListCachedContentsResponse, ListDocumentsResponse, ListFileSearchStoresResponse, ListFilesResponse, ListModelsResponse, ListTuningJobsResponse, Live, LiveClientToolResponse, LiveMusicPlaybackControl, LiveMusicServerMessage, LiveSendToolResponseParameters, LiveServerMessage, MaskReferenceImage, MaskReferenceMode, MediaModality, MediaResolution, Modality, Models, MusicGenerationMode, Operations, Outcome, PagedItem, Pager, PartMediaResolutionLevel, PersonGeneration, PhishBlockThreshold, RawReferenceImage, RecontextImageResponse, RegisterFilesResponse, ReplayResponse, ResourceScope, SafetyFilterLevel, Scale, SegmentImageResponse, SegmentMode, Session, SingleEmbedContentResponse, StartSensitivity, StyleReferenceImage, SubjectReferenceImage, SubjectReferenceType, ThinkingLevel, Tokens, TrafficType, TuningMethod, TuningMode, TuningTask, TurnCompleteReason, TurnCoverage, Type, UploadToFileSearchStoreOperation, UploadToFileSearchStoreResponse, UploadToFileSearchStoreResumableResponse, UpscaleImageResponse, UrlRetrievalStatus, VadSignalType, VideoCompressionQuality, VideoGenerationMaskMode, VideoGenerationReferenceType, VoiceActivityType, createFunctionResponsePartFromBase64, createFunctionResponsePartFromUri, createModelContent, createPartFromBase64, createPartFromCodeExecutionResult, createPartFromExecutableCode, createPartFromFunctionCall, createPartFromFunctionResponse, createPartFromText, createPartFromUri, createUserContent, mcpToTool, setDefaultBaseUrls }; +//# sourceMappingURL=index.mjs.map diff --git a/server/node_modules/@google/genai/dist/node/index.mjs.map b/server/node_modules/@google/genai/dist/node/index.mjs.map new file mode 100644 index 0000000..83b7c34 --- /dev/null +++ b/server/node_modules/@google/genai/dist/node/index.mjs.map @@ -0,0 +1 @@ +{"version":3,"file":"index.mjs","sources":["../../src/_base_url.ts","../../src/_common.ts","../../src/_base_transformers.ts","../../src/converters/_operations_converters.ts","../../src/types.ts","../../src/_transformers.ts","../../src/converters/_batches_converters.ts","../../src/pagers.ts","../../src/batches.ts","../../src/converters/_caches_converters.ts","../../src/caches.ts","../../src/chats.ts","../../src/errors.ts","../../src/converters/_files_converters.ts","../../src/files.ts","../../src/converters/_live_converters.ts","../../src/converters/_models_converters.ts","../../src/converters/_filesearchstores_converters.ts","../../src/_api_client.ts","../../src/mcp/_mcp.ts","../../src/music.ts","../../src/live.ts","../../src/_afc.ts","../../src/models.ts","../../src/operations.ts","../../src/converters/_tokens_converters.ts","../../src/tokens.ts","../../src/converters/_documents_converters.ts","../../src/documents.ts","../../src/filesearchstores.ts","../../src/interactions/internal/utils/uuid.ts","../../src/interactions/internal/errors.ts","../../src/interactions/core/error.ts","../../src/interactions/internal/utils/values.ts","../../src/interactions/internal/utils/sleep.ts","../../src/interactions/version.ts","../../src/interactions/internal/detect-platform.ts","../../src/interactions/internal/shims.ts","../../src/interactions/internal/request-options.ts","../../src/interactions/internal/uploads.ts","../../src/interactions/internal/to-file.ts","../../src/interactions/core/resource.ts","../../src/interactions/internal/utils/path.ts","../../src/interactions/resources/interactions.ts","../../src/interactions/internal/utils/bytes.ts","../../src/interactions/internal/decoders/line.ts","../../src/interactions/internal/utils/log.ts","../../src/interactions/core/streaming.ts","../../src/interactions/internal/parse.ts","../../src/interactions/core/api-promise.ts","../../src/interactions/internal/headers.ts","../../src/interactions/internal/utils/env.ts","../../src/interactions/client.ts","../../src/node/_node_auth.ts","../../src/node/_node_downloader.ts","../../src/node/_node_websocket.ts","../../src/converters/_tunings_converters.ts","../../src/tunings.ts","../../src/cross/_cross_uploader.ts","../../src/node/_node_uploader.ts","../../src/node/node_files.ts","../../src/node/node_client.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {HttpOptions} from './types.js';\n\nlet _defaultBaseGeminiUrl: string | undefined = undefined;\nlet _defaultBaseVertexUrl: string | undefined = undefined;\n\n/**\n * Parameters for setting the base URLs for the Gemini API and Vertex AI API.\n */\nexport interface BaseUrlParameters {\n geminiUrl?: string;\n vertexUrl?: string;\n}\n\n/**\n * Overrides the base URLs for the Gemini API and Vertex AI API.\n *\n * @remarks This function should be called before initializing the SDK. If the\n * base URLs are set after initializing the SDK, the base URLs will not be\n * updated. Base URLs provided in the HttpOptions will also take precedence over\n * URLs set here.\n *\n * @example\n * ```ts\n * import {GoogleGenAI, setDefaultBaseUrls} from '@google/genai';\n * // Override the base URL for the Gemini API.\n * setDefaultBaseUrls({geminiUrl:'https://gemini.google.com'});\n *\n * // Override the base URL for the Vertex AI API.\n * setDefaultBaseUrls({vertexUrl: 'https://vertexai.googleapis.com'});\n *\n * const ai = new GoogleGenAI({apiKey: 'GEMINI_API_KEY'});\n * ```\n */\nexport function setDefaultBaseUrls(baseUrlParams: BaseUrlParameters) {\n _defaultBaseGeminiUrl = baseUrlParams.geminiUrl;\n _defaultBaseVertexUrl = baseUrlParams.vertexUrl;\n}\n\n/**\n * Returns the default base URLs for the Gemini API and Vertex AI API.\n */\nexport function getDefaultBaseUrls(): BaseUrlParameters {\n return {\n geminiUrl: _defaultBaseGeminiUrl,\n vertexUrl: _defaultBaseVertexUrl,\n };\n}\n\n/**\n * Returns the default base URL based on the following priority:\n * 1. Base URLs set via HttpOptions.\n * 2. Base URLs set via the latest call to setDefaultBaseUrls.\n * 3. Base URLs set via environment variables.\n */\nexport function getBaseUrl(\n httpOptions: HttpOptions | undefined,\n vertexai: boolean | undefined,\n vertexBaseUrlFromEnv: string | undefined,\n geminiBaseUrlFromEnv: string | undefined,\n): string | undefined {\n if (!httpOptions?.baseUrl) {\n const defaultBaseUrls = getDefaultBaseUrls();\n if (vertexai) {\n return defaultBaseUrls.vertexUrl ?? vertexBaseUrlFromEnv;\n } else {\n return defaultBaseUrls.geminiUrl ?? geminiBaseUrlFromEnv;\n }\n }\n\n return httpOptions.baseUrl;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nexport class BaseModule {}\n\nexport function formatMap(\n templateString: string,\n valueMap: Record<string, unknown>,\n): string {\n // Use a regular expression to find all placeholders in the template string\n const regex = /\\{([^}]+)\\}/g;\n\n // Replace each placeholder with its corresponding value from the valueMap\n return templateString.replace(regex, (match, key) => {\n if (Object.prototype.hasOwnProperty.call(valueMap, key)) {\n const value = valueMap[key];\n // Convert the value to a string if it's not a string already\n return value !== undefined && value !== null ? String(value) : '';\n } else {\n // Handle missing keys\n throw new Error(`Key '${key}' not found in valueMap.`);\n }\n });\n}\n\nexport function setValueByPath(\n data: Record<string, unknown>,\n keys: string[],\n value: unknown,\n): void {\n for (let i = 0; i < keys.length - 1; i++) {\n const key = keys[i];\n\n if (key.endsWith('[]')) {\n const keyName = key.slice(0, -2);\n if (!(keyName in data)) {\n if (Array.isArray(value)) {\n data[keyName] = Array.from({length: value.length}, () => ({}));\n } else {\n throw new Error(`Value must be a list given an array path ${key}`);\n }\n }\n\n if (Array.isArray(data[keyName])) {\n const arrayData = data[keyName] as Array<unknown>;\n\n if (Array.isArray(value)) {\n for (let j = 0; j < arrayData.length; j++) {\n const entry = arrayData[j] as Record<string, unknown>;\n setValueByPath(entry, keys.slice(i + 1), value[j]);\n }\n } else {\n for (const d of arrayData) {\n setValueByPath(\n d as Record<string, unknown>,\n keys.slice(i + 1),\n value,\n );\n }\n }\n }\n return;\n } else if (key.endsWith('[0]')) {\n const keyName = key.slice(0, -3);\n if (!(keyName in data)) {\n data[keyName] = [{}];\n }\n const arrayData = (data as Record<string, unknown>)[keyName];\n setValueByPath(\n (arrayData as Array<Record<string, unknown>>)[0],\n keys.slice(i + 1),\n value,\n );\n return;\n }\n\n if (!data[key] || typeof data[key] !== 'object') {\n data[key] = {};\n }\n\n data = data[key] as Record<string, unknown>;\n }\n\n const keyToSet = keys[keys.length - 1];\n const existingData = data[keyToSet];\n\n if (existingData !== undefined) {\n if (\n !value ||\n (typeof value === 'object' && Object.keys(value).length === 0)\n ) {\n return;\n }\n\n if (value === existingData) {\n return;\n }\n\n if (\n typeof existingData === 'object' &&\n typeof value === 'object' &&\n existingData !== null &&\n value !== null\n ) {\n Object.assign(existingData, value);\n } else {\n throw new Error(`Cannot set value for an existing key. Key: ${keyToSet}`);\n }\n } else {\n if (\n keyToSet === '_self' &&\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(value)\n ) {\n const valueAsRecord = value as Record<string, unknown>;\n\n Object.assign(data, valueAsRecord);\n } else {\n data[keyToSet] = value;\n }\n }\n}\n\nexport function getValueByPath(\n data: unknown,\n keys: string[],\n defaultValue: unknown = undefined,\n): unknown {\n try {\n if (keys.length === 1 && keys[0] === '_self') {\n return data;\n }\n\n for (let i = 0; i < keys.length; i++) {\n if (typeof data !== 'object' || data === null) {\n return defaultValue;\n }\n\n const key = keys[i];\n if (key.endsWith('[]')) {\n const keyName = key.slice(0, -2);\n if (keyName in data) {\n const arrayData = (data as Record<string, unknown>)[keyName];\n if (!Array.isArray(arrayData)) {\n return defaultValue;\n }\n return arrayData.map((d) =>\n getValueByPath(d, keys.slice(i + 1), defaultValue),\n );\n } else {\n return defaultValue;\n }\n } else {\n data = (data as Record<string, unknown>)[key];\n }\n }\n\n return data;\n } catch (error) {\n if (error instanceof TypeError) {\n return defaultValue;\n }\n throw error;\n }\n}\n\n/**\n * Moves values from source paths to destination paths.\n *\n * Examples:\n * moveValueByPath(\n * {'requests': [{'content': v1}, {'content': v2}]},\n * {'requests[].*': 'requests[].request.*'}\n * )\n * -> {'requests': [{'request': {'content': v1}}, {'request': {'content': v2}}]}\n */\nexport function moveValueByPath(\n data: unknown,\n paths: Record<string, string>,\n): void {\n for (const [sourcePath, destPath] of Object.entries(paths)) {\n const sourceKeys = sourcePath.split('.');\n const destKeys = destPath.split('.');\n\n // Determine keys to exclude from wildcard to avoid cyclic references\n const excludeKeys = new Set<string>();\n let wildcardIdx = -1;\n for (let i = 0; i < sourceKeys.length; i++) {\n if (sourceKeys[i] === '*') {\n wildcardIdx = i;\n break;\n }\n }\n\n if (wildcardIdx !== -1 && destKeys.length > wildcardIdx) {\n // Extract the intermediate key between source and dest paths\n // Example: source=['requests[]', '*'], dest=['requests[]', 'request', '*']\n // We want to exclude 'request'\n for (let i = wildcardIdx; i < destKeys.length; i++) {\n const key = destKeys[i];\n if (key !== '*' && !key.endsWith('[]') && !key.endsWith('[0]')) {\n excludeKeys.add(key);\n }\n }\n }\n\n _moveValueRecursive(data, sourceKeys, destKeys, 0, excludeKeys);\n }\n}\n\n/**\n * Recursively moves values from source path to destination path.\n */\nfunction _moveValueRecursive(\n data: unknown,\n sourceKeys: string[],\n destKeys: string[],\n keyIdx: number,\n excludeKeys: Set<string>,\n): void {\n if (keyIdx >= sourceKeys.length) {\n return;\n }\n\n if (typeof data !== 'object' || data === null) {\n return;\n }\n\n const key = sourceKeys[keyIdx];\n\n if (key.endsWith('[]')) {\n const keyName = key.slice(0, -2);\n const dataRecord = data as Record<string, unknown>;\n if (keyName in dataRecord && Array.isArray(dataRecord[keyName])) {\n for (const item of dataRecord[keyName] as Array<unknown>) {\n _moveValueRecursive(\n item,\n sourceKeys,\n destKeys,\n keyIdx + 1,\n excludeKeys,\n );\n }\n }\n } else if (key === '*') {\n // wildcard - move all fields\n if (typeof data === 'object' && data !== null && !Array.isArray(data)) {\n const dataRecord = data as Record<string, unknown>;\n const keysToMove = Object.keys(dataRecord).filter(\n (k) => !k.startsWith('_') && !excludeKeys.has(k),\n );\n\n const valuesToMove: Record<string, unknown> = {};\n for (const k of keysToMove) {\n valuesToMove[k] = dataRecord[k];\n }\n\n // Set values at destination\n for (const [k, v] of Object.entries(valuesToMove)) {\n const newDestKeys: string[] = [];\n for (const dk of destKeys.slice(keyIdx)) {\n if (dk === '*') {\n newDestKeys.push(k);\n } else {\n newDestKeys.push(dk);\n }\n }\n setValueByPath(dataRecord, newDestKeys, v);\n }\n\n for (const k of keysToMove) {\n delete dataRecord[k];\n }\n }\n } else {\n // Navigate to next level\n const dataRecord = data as Record<string, unknown>;\n if (key in dataRecord) {\n _moveValueRecursive(\n dataRecord[key],\n sourceKeys,\n destKeys,\n keyIdx + 1,\n excludeKeys,\n );\n }\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nexport function tBytes(fromBytes: string | unknown): string {\n if (typeof fromBytes !== 'string') {\n throw new Error('fromImageBytes must be a string');\n }\n // TODO(b/389133914): Remove dummy bytes converter.\n return fromBytes;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport * as t from '../_base_transformers.js';\nimport * as common from '../_common.js';\nimport type * as types from '../types.js';\n\nexport function fetchPredictOperationParametersToMldev(\n fromObject: types.FetchPredictOperationParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['operationName']) !== undefined) {\n throw new Error('operationName parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['resourceName']) !== undefined) {\n throw new Error('resourceName parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['config']) !== undefined) {\n throw new Error('config parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function fetchPredictOperationParametersToVertex(\n fromObject: types.FetchPredictOperationParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromOperationName = common.getValueByPath(fromObject, [\n 'operationName',\n ]);\n if (fromOperationName != null) {\n common.setValueByPath(toObject, ['operationName'], fromOperationName);\n }\n\n const fromResourceName = common.getValueByPath(fromObject, ['resourceName']);\n if (fromResourceName != null) {\n common.setValueByPath(toObject, ['_url', 'resourceName'], fromResourceName);\n }\n\n return toObject;\n}\n\nexport function generateVideosOperationFromMldev(\n fromObject: types.GenerateVideosOperation,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromMetadata = common.getValueByPath(fromObject, ['metadata']);\n if (fromMetadata != null) {\n common.setValueByPath(toObject, ['metadata'], fromMetadata);\n }\n\n const fromDone = common.getValueByPath(fromObject, ['done']);\n if (fromDone != null) {\n common.setValueByPath(toObject, ['done'], fromDone);\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n const fromResponse = common.getValueByPath(fromObject, [\n 'response',\n 'generateVideoResponse',\n ]);\n if (fromResponse != null) {\n common.setValueByPath(\n toObject,\n ['response'],\n generateVideosResponseFromMldev(fromResponse),\n );\n }\n\n return toObject;\n}\n\nexport function generateVideosOperationFromVertex(\n fromObject: types.GenerateVideosOperation,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromMetadata = common.getValueByPath(fromObject, ['metadata']);\n if (fromMetadata != null) {\n common.setValueByPath(toObject, ['metadata'], fromMetadata);\n }\n\n const fromDone = common.getValueByPath(fromObject, ['done']);\n if (fromDone != null) {\n common.setValueByPath(toObject, ['done'], fromDone);\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n const fromResponse = common.getValueByPath(fromObject, ['response']);\n if (fromResponse != null) {\n common.setValueByPath(\n toObject,\n ['response'],\n generateVideosResponseFromVertex(fromResponse),\n );\n }\n\n return toObject;\n}\n\nexport function generateVideosResponseFromMldev(\n fromObject: types.GenerateVideosResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromGeneratedVideos = common.getValueByPath(fromObject, [\n 'generatedSamples',\n ]);\n if (fromGeneratedVideos != null) {\n let transformedList = fromGeneratedVideos;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return generatedVideoFromMldev(item);\n });\n }\n common.setValueByPath(toObject, ['generatedVideos'], transformedList);\n }\n\n const fromRaiMediaFilteredCount = common.getValueByPath(fromObject, [\n 'raiMediaFilteredCount',\n ]);\n if (fromRaiMediaFilteredCount != null) {\n common.setValueByPath(\n toObject,\n ['raiMediaFilteredCount'],\n fromRaiMediaFilteredCount,\n );\n }\n\n const fromRaiMediaFilteredReasons = common.getValueByPath(fromObject, [\n 'raiMediaFilteredReasons',\n ]);\n if (fromRaiMediaFilteredReasons != null) {\n common.setValueByPath(\n toObject,\n ['raiMediaFilteredReasons'],\n fromRaiMediaFilteredReasons,\n );\n }\n\n return toObject;\n}\n\nexport function generateVideosResponseFromVertex(\n fromObject: types.GenerateVideosResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromGeneratedVideos = common.getValueByPath(fromObject, ['videos']);\n if (fromGeneratedVideos != null) {\n let transformedList = fromGeneratedVideos;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return generatedVideoFromVertex(item);\n });\n }\n common.setValueByPath(toObject, ['generatedVideos'], transformedList);\n }\n\n const fromRaiMediaFilteredCount = common.getValueByPath(fromObject, [\n 'raiMediaFilteredCount',\n ]);\n if (fromRaiMediaFilteredCount != null) {\n common.setValueByPath(\n toObject,\n ['raiMediaFilteredCount'],\n fromRaiMediaFilteredCount,\n );\n }\n\n const fromRaiMediaFilteredReasons = common.getValueByPath(fromObject, [\n 'raiMediaFilteredReasons',\n ]);\n if (fromRaiMediaFilteredReasons != null) {\n common.setValueByPath(\n toObject,\n ['raiMediaFilteredReasons'],\n fromRaiMediaFilteredReasons,\n );\n }\n\n return toObject;\n}\n\nexport function generatedVideoFromMldev(\n fromObject: types.GeneratedVideo,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromVideo = common.getValueByPath(fromObject, ['video']);\n if (fromVideo != null) {\n common.setValueByPath(toObject, ['video'], videoFromMldev(fromVideo));\n }\n\n return toObject;\n}\n\nexport function generatedVideoFromVertex(\n fromObject: types.GeneratedVideo,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromVideo = common.getValueByPath(fromObject, ['_self']);\n if (fromVideo != null) {\n common.setValueByPath(toObject, ['video'], videoFromVertex(fromVideo));\n }\n\n return toObject;\n}\n\nexport function getOperationParametersToMldev(\n fromObject: types.GetOperationParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromOperationName = common.getValueByPath(fromObject, [\n 'operationName',\n ]);\n if (fromOperationName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'operationName'],\n fromOperationName,\n );\n }\n\n return toObject;\n}\n\nexport function getOperationParametersToVertex(\n fromObject: types.GetOperationParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromOperationName = common.getValueByPath(fromObject, [\n 'operationName',\n ]);\n if (fromOperationName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'operationName'],\n fromOperationName,\n );\n }\n\n return toObject;\n}\n\nexport function importFileOperationFromMldev(\n fromObject: types.ImportFileOperation,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromMetadata = common.getValueByPath(fromObject, ['metadata']);\n if (fromMetadata != null) {\n common.setValueByPath(toObject, ['metadata'], fromMetadata);\n }\n\n const fromDone = common.getValueByPath(fromObject, ['done']);\n if (fromDone != null) {\n common.setValueByPath(toObject, ['done'], fromDone);\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n const fromResponse = common.getValueByPath(fromObject, ['response']);\n if (fromResponse != null) {\n common.setValueByPath(\n toObject,\n ['response'],\n importFileResponseFromMldev(fromResponse),\n );\n }\n\n return toObject;\n}\n\nexport function importFileResponseFromMldev(\n fromObject: types.ImportFileResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromParent = common.getValueByPath(fromObject, ['parent']);\n if (fromParent != null) {\n common.setValueByPath(toObject, ['parent'], fromParent);\n }\n\n const fromDocumentName = common.getValueByPath(fromObject, ['documentName']);\n if (fromDocumentName != null) {\n common.setValueByPath(toObject, ['documentName'], fromDocumentName);\n }\n\n return toObject;\n}\n\nexport function uploadToFileSearchStoreOperationFromMldev(\n fromObject: types.UploadToFileSearchStoreOperation,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromMetadata = common.getValueByPath(fromObject, ['metadata']);\n if (fromMetadata != null) {\n common.setValueByPath(toObject, ['metadata'], fromMetadata);\n }\n\n const fromDone = common.getValueByPath(fromObject, ['done']);\n if (fromDone != null) {\n common.setValueByPath(toObject, ['done'], fromDone);\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n const fromResponse = common.getValueByPath(fromObject, ['response']);\n if (fromResponse != null) {\n common.setValueByPath(\n toObject,\n ['response'],\n uploadToFileSearchStoreResponseFromMldev(fromResponse),\n );\n }\n\n return toObject;\n}\n\nexport function uploadToFileSearchStoreResponseFromMldev(\n fromObject: types.UploadToFileSearchStoreResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromParent = common.getValueByPath(fromObject, ['parent']);\n if (fromParent != null) {\n common.setValueByPath(toObject, ['parent'], fromParent);\n }\n\n const fromDocumentName = common.getValueByPath(fromObject, ['documentName']);\n if (fromDocumentName != null) {\n common.setValueByPath(toObject, ['documentName'], fromDocumentName);\n }\n\n return toObject;\n}\n\nexport function videoFromMldev(\n fromObject: types.Video,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromUri = common.getValueByPath(fromObject, ['uri']);\n if (fromUri != null) {\n common.setValueByPath(toObject, ['uri'], fromUri);\n }\n\n const fromVideoBytes = common.getValueByPath(fromObject, ['encodedVideo']);\n if (fromVideoBytes != null) {\n common.setValueByPath(toObject, ['videoBytes'], t.tBytes(fromVideoBytes));\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['encoding']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function videoFromVertex(\n fromObject: types.Video,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromUri = common.getValueByPath(fromObject, ['gcsUri']);\n if (fromUri != null) {\n common.setValueByPath(toObject, ['uri'], fromUri);\n }\n\n const fromVideoBytes = common.getValueByPath(fromObject, [\n 'bytesBase64Encoded',\n ]);\n if (fromVideoBytes != null) {\n common.setValueByPath(toObject, ['videoBytes'], t.tBytes(fromVideoBytes));\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport type {ReferenceImageAPIInternal} from './_internal_types.js';\nimport {\n generateVideosOperationFromMldev,\n generateVideosOperationFromVertex,\n importFileOperationFromMldev,\n uploadToFileSearchStoreOperationFromMldev,\n} from './converters/_operations_converters.js';\n\n/** Outcome of the code execution. */\nexport enum Outcome {\n /**\n * Unspecified status. This value should not be used.\n */\n OUTCOME_UNSPECIFIED = 'OUTCOME_UNSPECIFIED',\n /**\n * Code execution completed successfully.\n */\n OUTCOME_OK = 'OUTCOME_OK',\n /**\n * Code execution finished but with a failure. `stderr` should contain the reason.\n */\n OUTCOME_FAILED = 'OUTCOME_FAILED',\n /**\n * Code execution ran for too long, and was cancelled. There may or may not be a partial output present.\n */\n OUTCOME_DEADLINE_EXCEEDED = 'OUTCOME_DEADLINE_EXCEEDED',\n}\n\n/** Programming language of the `code`. */\nexport enum Language {\n /**\n * Unspecified language. This value should not be used.\n */\n LANGUAGE_UNSPECIFIED = 'LANGUAGE_UNSPECIFIED',\n /**\n * Python >= 3.10, with numpy and simpy available.\n */\n PYTHON = 'PYTHON',\n}\n\n/** Specifies how the response should be scheduled in the conversation. */\nexport enum FunctionResponseScheduling {\n /**\n * This value is unused.\n */\n SCHEDULING_UNSPECIFIED = 'SCHEDULING_UNSPECIFIED',\n /**\n * Only add the result to the conversation context, do not interrupt or trigger generation.\n */\n SILENT = 'SILENT',\n /**\n * Add the result to the conversation context, and prompt to generate output without interrupting ongoing generation.\n */\n WHEN_IDLE = 'WHEN_IDLE',\n /**\n * Add the result to the conversation context, interrupt ongoing generation and prompt to generate output.\n */\n INTERRUPT = 'INTERRUPT',\n}\n\n/** The type of the data. */\nexport enum Type {\n /**\n * Not specified, should not be used.\n */\n TYPE_UNSPECIFIED = 'TYPE_UNSPECIFIED',\n /**\n * OpenAPI string type\n */\n STRING = 'STRING',\n /**\n * OpenAPI number type\n */\n NUMBER = 'NUMBER',\n /**\n * OpenAPI integer type\n */\n INTEGER = 'INTEGER',\n /**\n * OpenAPI boolean type\n */\n BOOLEAN = 'BOOLEAN',\n /**\n * OpenAPI array type\n */\n ARRAY = 'ARRAY',\n /**\n * OpenAPI object type\n */\n OBJECT = 'OBJECT',\n /**\n * Null type\n */\n NULL = 'NULL',\n}\n\n/** The API spec that the external API implements. This enum is not supported in Gemini API. */\nexport enum ApiSpec {\n /**\n * Unspecified API spec. This value should not be used.\n */\n API_SPEC_UNSPECIFIED = 'API_SPEC_UNSPECIFIED',\n /**\n * Simple search API spec.\n */\n SIMPLE_SEARCH = 'SIMPLE_SEARCH',\n /**\n * Elastic search API spec.\n */\n ELASTIC_SEARCH = 'ELASTIC_SEARCH',\n}\n\n/** Type of auth scheme. This enum is not supported in Gemini API. */\nexport enum AuthType {\n AUTH_TYPE_UNSPECIFIED = 'AUTH_TYPE_UNSPECIFIED',\n /**\n * No Auth.\n */\n NO_AUTH = 'NO_AUTH',\n /**\n * API Key Auth.\n */\n API_KEY_AUTH = 'API_KEY_AUTH',\n /**\n * HTTP Basic Auth.\n */\n HTTP_BASIC_AUTH = 'HTTP_BASIC_AUTH',\n /**\n * Google Service Account Auth.\n */\n GOOGLE_SERVICE_ACCOUNT_AUTH = 'GOOGLE_SERVICE_ACCOUNT_AUTH',\n /**\n * OAuth auth.\n */\n OAUTH = 'OAUTH',\n /**\n * OpenID Connect (OIDC) Auth.\n */\n OIDC_AUTH = 'OIDC_AUTH',\n}\n\n/** The location of the API key. This enum is not supported in Gemini API. */\nexport enum HttpElementLocation {\n HTTP_IN_UNSPECIFIED = 'HTTP_IN_UNSPECIFIED',\n /**\n * Element is in the HTTP request query.\n */\n HTTP_IN_QUERY = 'HTTP_IN_QUERY',\n /**\n * Element is in the HTTP request header.\n */\n HTTP_IN_HEADER = 'HTTP_IN_HEADER',\n /**\n * Element is in the HTTP request path.\n */\n HTTP_IN_PATH = 'HTTP_IN_PATH',\n /**\n * Element is in the HTTP request body.\n */\n HTTP_IN_BODY = 'HTTP_IN_BODY',\n /**\n * Element is in the HTTP request cookie.\n */\n HTTP_IN_COOKIE = 'HTTP_IN_COOKIE',\n}\n\n/** Sites with confidence level chosen & above this value will be blocked from the search results. This enum is not supported in Gemini API. */\nexport enum PhishBlockThreshold {\n /**\n * Defaults to unspecified.\n */\n PHISH_BLOCK_THRESHOLD_UNSPECIFIED = 'PHISH_BLOCK_THRESHOLD_UNSPECIFIED',\n /**\n * Blocks Low and above confidence URL that is risky.\n */\n BLOCK_LOW_AND_ABOVE = 'BLOCK_LOW_AND_ABOVE',\n /**\n * Blocks Medium and above confidence URL that is risky.\n */\n BLOCK_MEDIUM_AND_ABOVE = 'BLOCK_MEDIUM_AND_ABOVE',\n /**\n * Blocks High and above confidence URL that is risky.\n */\n BLOCK_HIGH_AND_ABOVE = 'BLOCK_HIGH_AND_ABOVE',\n /**\n * Blocks Higher and above confidence URL that is risky.\n */\n BLOCK_HIGHER_AND_ABOVE = 'BLOCK_HIGHER_AND_ABOVE',\n /**\n * Blocks Very high and above confidence URL that is risky.\n */\n BLOCK_VERY_HIGH_AND_ABOVE = 'BLOCK_VERY_HIGH_AND_ABOVE',\n /**\n * Blocks Extremely high confidence URL that is risky.\n */\n BLOCK_ONLY_EXTREMELY_HIGH = 'BLOCK_ONLY_EXTREMELY_HIGH',\n}\n\n/** Specifies the function Behavior. Currently only supported by the BidiGenerateContent method. This enum is not supported in Vertex AI. */\nexport enum Behavior {\n /**\n * This value is unused.\n */\n UNSPECIFIED = 'UNSPECIFIED',\n /**\n * If set, the system will wait to receive the function response before continuing the conversation.\n */\n BLOCKING = 'BLOCKING',\n /**\n * If set, the system will not wait to receive the function response. Instead, it will attempt to handle function responses as they become available while maintaining the conversation between the user and the model.\n */\n NON_BLOCKING = 'NON_BLOCKING',\n}\n\n/** The mode of the predictor to be used in dynamic retrieval. */\nexport enum DynamicRetrievalConfigMode {\n /**\n * Always trigger retrieval.\n */\n MODE_UNSPECIFIED = 'MODE_UNSPECIFIED',\n /**\n * Run retrieval only when system decides it is necessary.\n */\n MODE_DYNAMIC = 'MODE_DYNAMIC',\n}\n\n/** Function calling mode. */\nexport enum FunctionCallingConfigMode {\n /**\n * Unspecified function calling mode. This value should not be used.\n */\n MODE_UNSPECIFIED = 'MODE_UNSPECIFIED',\n /**\n * Default model behavior, model decides to predict either function calls or natural language response.\n */\n AUTO = 'AUTO',\n /**\n * Model is constrained to always predicting function calls only. If \"allowed_function_names\" are set, the predicted function calls will be limited to any one of \"allowed_function_names\", else the predicted function calls will be any one of the provided \"function_declarations\".\n */\n ANY = 'ANY',\n /**\n * Model will not predict any function calls. Model behavior is same as when not passing any function declarations.\n */\n NONE = 'NONE',\n /**\n * Model is constrained to predict either function calls or natural language response. If \"allowed_function_names\" are set, the predicted function calls will be limited to any one of \"allowed_function_names\", else the predicted function calls will be any one of the provided \"function_declarations\".\n */\n VALIDATED = 'VALIDATED',\n}\n\n/** The number of thoughts tokens that the model should generate. */\nexport enum ThinkingLevel {\n /**\n * Unspecified thinking level.\n */\n THINKING_LEVEL_UNSPECIFIED = 'THINKING_LEVEL_UNSPECIFIED',\n /**\n * Low thinking level.\n */\n LOW = 'LOW',\n /**\n * Medium thinking level.\n */\n MEDIUM = 'MEDIUM',\n /**\n * High thinking level.\n */\n HIGH = 'HIGH',\n /**\n * MINIMAL thinking level.\n */\n MINIMAL = 'MINIMAL',\n}\n\n/** Harm category. */\nexport enum HarmCategory {\n /**\n * The harm category is unspecified.\n */\n HARM_CATEGORY_UNSPECIFIED = 'HARM_CATEGORY_UNSPECIFIED',\n /**\n * The harm category is harassment.\n */\n HARM_CATEGORY_HARASSMENT = 'HARM_CATEGORY_HARASSMENT',\n /**\n * The harm category is hate speech.\n */\n HARM_CATEGORY_HATE_SPEECH = 'HARM_CATEGORY_HATE_SPEECH',\n /**\n * The harm category is sexually explicit content.\n */\n HARM_CATEGORY_SEXUALLY_EXPLICIT = 'HARM_CATEGORY_SEXUALLY_EXPLICIT',\n /**\n * The harm category is dangerous content.\n */\n HARM_CATEGORY_DANGEROUS_CONTENT = 'HARM_CATEGORY_DANGEROUS_CONTENT',\n /**\n * Deprecated: Election filter is not longer supported. The harm category is civic integrity.\n */\n HARM_CATEGORY_CIVIC_INTEGRITY = 'HARM_CATEGORY_CIVIC_INTEGRITY',\n /**\n * The harm category is image hate. This enum value is not supported in Gemini API.\n */\n HARM_CATEGORY_IMAGE_HATE = 'HARM_CATEGORY_IMAGE_HATE',\n /**\n * The harm category is image dangerous content. This enum value is not supported in Gemini API.\n */\n HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT = 'HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT',\n /**\n * The harm category is image harassment. This enum value is not supported in Gemini API.\n */\n HARM_CATEGORY_IMAGE_HARASSMENT = 'HARM_CATEGORY_IMAGE_HARASSMENT',\n /**\n * The harm category is image sexually explicit content. This enum value is not supported in Gemini API.\n */\n HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT = 'HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT',\n /**\n * The harm category is for jailbreak prompts. This enum value is not supported in Gemini API.\n */\n HARM_CATEGORY_JAILBREAK = 'HARM_CATEGORY_JAILBREAK',\n}\n\n/** Specify if the threshold is used for probability or severity score. If not specified, the threshold is used for probability score. This enum is not supported in Gemini API. */\nexport enum HarmBlockMethod {\n /**\n * The harm block method is unspecified.\n */\n HARM_BLOCK_METHOD_UNSPECIFIED = 'HARM_BLOCK_METHOD_UNSPECIFIED',\n /**\n * The harm block method uses both probability and severity scores.\n */\n SEVERITY = 'SEVERITY',\n /**\n * The harm block method uses the probability score.\n */\n PROBABILITY = 'PROBABILITY',\n}\n\n/** The harm block threshold. */\nexport enum HarmBlockThreshold {\n /**\n * Unspecified harm block threshold.\n */\n HARM_BLOCK_THRESHOLD_UNSPECIFIED = 'HARM_BLOCK_THRESHOLD_UNSPECIFIED',\n /**\n * Block low threshold and above (i.e. block more).\n */\n BLOCK_LOW_AND_ABOVE = 'BLOCK_LOW_AND_ABOVE',\n /**\n * Block medium threshold and above.\n */\n BLOCK_MEDIUM_AND_ABOVE = 'BLOCK_MEDIUM_AND_ABOVE',\n /**\n * Block only high threshold (i.e. block less).\n */\n BLOCK_ONLY_HIGH = 'BLOCK_ONLY_HIGH',\n /**\n * Block none.\n */\n BLOCK_NONE = 'BLOCK_NONE',\n /**\n * Turn off the safety filter.\n */\n OFF = 'OFF',\n}\n\n/** Output only. The reason why the model stopped generating tokens.\n\nIf empty, the model has not stopped generating the tokens. */\nexport enum FinishReason {\n /**\n * The finish reason is unspecified.\n */\n FINISH_REASON_UNSPECIFIED = 'FINISH_REASON_UNSPECIFIED',\n /**\n * Token generation reached a natural stopping point or a configured stop sequence.\n */\n STOP = 'STOP',\n /**\n * Token generation reached the configured maximum output tokens.\n */\n MAX_TOKENS = 'MAX_TOKENS',\n /**\n * Token generation stopped because the content potentially contains safety violations. NOTE: When streaming, [content][] is empty if content filters blocks the output.\n */\n SAFETY = 'SAFETY',\n /**\n * The token generation stopped because of potential recitation.\n */\n RECITATION = 'RECITATION',\n /**\n * The token generation stopped because of using an unsupported language.\n */\n LANGUAGE = 'LANGUAGE',\n /**\n * All other reasons that stopped the token generation.\n */\n OTHER = 'OTHER',\n /**\n * Token generation stopped because the content contains forbidden terms.\n */\n BLOCKLIST = 'BLOCKLIST',\n /**\n * Token generation stopped for potentially containing prohibited content.\n */\n PROHIBITED_CONTENT = 'PROHIBITED_CONTENT',\n /**\n * Token generation stopped because the content potentially contains Sensitive Personally Identifiable Information (SPII).\n */\n SPII = 'SPII',\n /**\n * The function call generated by the model is invalid.\n */\n MALFORMED_FUNCTION_CALL = 'MALFORMED_FUNCTION_CALL',\n /**\n * Token generation stopped because generated images have safety violations.\n */\n IMAGE_SAFETY = 'IMAGE_SAFETY',\n /**\n * The tool call generated by the model is invalid.\n */\n UNEXPECTED_TOOL_CALL = 'UNEXPECTED_TOOL_CALL',\n /**\n * Image generation stopped because the generated images have prohibited content.\n */\n IMAGE_PROHIBITED_CONTENT = 'IMAGE_PROHIBITED_CONTENT',\n /**\n * The model was expected to generate an image, but none was generated.\n */\n NO_IMAGE = 'NO_IMAGE',\n /**\n * Image generation stopped because the generated image may be a recitation from a source.\n */\n IMAGE_RECITATION = 'IMAGE_RECITATION',\n /**\n * Image generation stopped for a reason not otherwise specified.\n */\n IMAGE_OTHER = 'IMAGE_OTHER',\n}\n\n/** Output only. Harm probability levels in the content. */\nexport enum HarmProbability {\n /**\n * Harm probability unspecified.\n */\n HARM_PROBABILITY_UNSPECIFIED = 'HARM_PROBABILITY_UNSPECIFIED',\n /**\n * Negligible level of harm.\n */\n NEGLIGIBLE = 'NEGLIGIBLE',\n /**\n * Low level of harm.\n */\n LOW = 'LOW',\n /**\n * Medium level of harm.\n */\n MEDIUM = 'MEDIUM',\n /**\n * High level of harm.\n */\n HIGH = 'HIGH',\n}\n\n/** Output only. Harm severity levels in the content. This enum is not supported in Gemini API. */\nexport enum HarmSeverity {\n /**\n * Harm severity unspecified.\n */\n HARM_SEVERITY_UNSPECIFIED = 'HARM_SEVERITY_UNSPECIFIED',\n /**\n * Negligible level of harm severity.\n */\n HARM_SEVERITY_NEGLIGIBLE = 'HARM_SEVERITY_NEGLIGIBLE',\n /**\n * Low level of harm severity.\n */\n HARM_SEVERITY_LOW = 'HARM_SEVERITY_LOW',\n /**\n * Medium level of harm severity.\n */\n HARM_SEVERITY_MEDIUM = 'HARM_SEVERITY_MEDIUM',\n /**\n * High level of harm severity.\n */\n HARM_SEVERITY_HIGH = 'HARM_SEVERITY_HIGH',\n}\n\n/** Status of the url retrieval. */\nexport enum UrlRetrievalStatus {\n /**\n * Default value. This value is unused.\n */\n URL_RETRIEVAL_STATUS_UNSPECIFIED = 'URL_RETRIEVAL_STATUS_UNSPECIFIED',\n /**\n * Url retrieval is successful.\n */\n URL_RETRIEVAL_STATUS_SUCCESS = 'URL_RETRIEVAL_STATUS_SUCCESS',\n /**\n * Url retrieval is failed due to error.\n */\n URL_RETRIEVAL_STATUS_ERROR = 'URL_RETRIEVAL_STATUS_ERROR',\n /**\n * Url retrieval is failed because the content is behind paywall. This enum value is not supported in Vertex AI.\n */\n URL_RETRIEVAL_STATUS_PAYWALL = 'URL_RETRIEVAL_STATUS_PAYWALL',\n /**\n * Url retrieval is failed because the content is unsafe. This enum value is not supported in Vertex AI.\n */\n URL_RETRIEVAL_STATUS_UNSAFE = 'URL_RETRIEVAL_STATUS_UNSAFE',\n}\n\n/** Output only. The reason why the prompt was blocked. */\nexport enum BlockedReason {\n /**\n * The blocked reason is unspecified.\n */\n BLOCKED_REASON_UNSPECIFIED = 'BLOCKED_REASON_UNSPECIFIED',\n /**\n * The prompt was blocked for safety reasons.\n */\n SAFETY = 'SAFETY',\n /**\n * The prompt was blocked for other reasons. For example, it may be due to the prompt's language, or because it contains other harmful content.\n */\n OTHER = 'OTHER',\n /**\n * The prompt was blocked because it contains a term from the terminology blocklist.\n */\n BLOCKLIST = 'BLOCKLIST',\n /**\n * The prompt was blocked because it contains prohibited content.\n */\n PROHIBITED_CONTENT = 'PROHIBITED_CONTENT',\n /**\n * The prompt was blocked because it contains content that is unsafe for image generation.\n */\n IMAGE_SAFETY = 'IMAGE_SAFETY',\n /**\n * The prompt was blocked by Model Armor. This enum value is not supported in Gemini API.\n */\n MODEL_ARMOR = 'MODEL_ARMOR',\n /**\n * The prompt was blocked as a jailbreak attempt. This enum value is not supported in Gemini API.\n */\n JAILBREAK = 'JAILBREAK',\n}\n\n/** Output only. The traffic type for this request. This enum is not supported in Gemini API. */\nexport enum TrafficType {\n /**\n * Unspecified request traffic type.\n */\n TRAFFIC_TYPE_UNSPECIFIED = 'TRAFFIC_TYPE_UNSPECIFIED',\n /**\n * The request was processed using Pay-As-You-Go quota.\n */\n ON_DEMAND = 'ON_DEMAND',\n /**\n * Type for Provisioned Throughput traffic.\n */\n PROVISIONED_THROUGHPUT = 'PROVISIONED_THROUGHPUT',\n}\n\n/** Server content modalities. */\nexport enum Modality {\n /**\n * The modality is unspecified.\n */\n MODALITY_UNSPECIFIED = 'MODALITY_UNSPECIFIED',\n /**\n * Indicates the model should return text\n */\n TEXT = 'TEXT',\n /**\n * Indicates the model should return images.\n */\n IMAGE = 'IMAGE',\n /**\n * Indicates the model should return audio.\n */\n AUDIO = 'AUDIO',\n}\n\n/** The media resolution to use. */\nexport enum MediaResolution {\n /**\n * Media resolution has not been set\n */\n MEDIA_RESOLUTION_UNSPECIFIED = 'MEDIA_RESOLUTION_UNSPECIFIED',\n /**\n * Media resolution set to low (64 tokens).\n */\n MEDIA_RESOLUTION_LOW = 'MEDIA_RESOLUTION_LOW',\n /**\n * Media resolution set to medium (256 tokens).\n */\n MEDIA_RESOLUTION_MEDIUM = 'MEDIA_RESOLUTION_MEDIUM',\n /**\n * Media resolution set to high (zoomed reframing with 256 tokens).\n */\n MEDIA_RESOLUTION_HIGH = 'MEDIA_RESOLUTION_HIGH',\n}\n\n/** Tuning mode. This enum is not supported in Gemini API. */\nexport enum TuningMode {\n /**\n * Tuning mode is unspecified.\n */\n TUNING_MODE_UNSPECIFIED = 'TUNING_MODE_UNSPECIFIED',\n /**\n * Full fine-tuning mode.\n */\n TUNING_MODE_FULL = 'TUNING_MODE_FULL',\n /**\n * PEFT adapter tuning mode.\n */\n TUNING_MODE_PEFT_ADAPTER = 'TUNING_MODE_PEFT_ADAPTER',\n}\n\n/** Adapter size for tuning. This enum is not supported in Gemini API. */\nexport enum AdapterSize {\n /**\n * Adapter size is unspecified.\n */\n ADAPTER_SIZE_UNSPECIFIED = 'ADAPTER_SIZE_UNSPECIFIED',\n /**\n * Adapter size 1.\n */\n ADAPTER_SIZE_ONE = 'ADAPTER_SIZE_ONE',\n /**\n * Adapter size 2.\n */\n ADAPTER_SIZE_TWO = 'ADAPTER_SIZE_TWO',\n /**\n * Adapter size 4.\n */\n ADAPTER_SIZE_FOUR = 'ADAPTER_SIZE_FOUR',\n /**\n * Adapter size 8.\n */\n ADAPTER_SIZE_EIGHT = 'ADAPTER_SIZE_EIGHT',\n /**\n * Adapter size 16.\n */\n ADAPTER_SIZE_SIXTEEN = 'ADAPTER_SIZE_SIXTEEN',\n /**\n * Adapter size 32.\n */\n ADAPTER_SIZE_THIRTY_TWO = 'ADAPTER_SIZE_THIRTY_TWO',\n}\n\n/** Job state. */\nexport enum JobState {\n /**\n * The job state is unspecified.\n */\n JOB_STATE_UNSPECIFIED = 'JOB_STATE_UNSPECIFIED',\n /**\n * The job has been just created or resumed and processing has not yet begun.\n */\n JOB_STATE_QUEUED = 'JOB_STATE_QUEUED',\n /**\n * The service is preparing to run the job.\n */\n JOB_STATE_PENDING = 'JOB_STATE_PENDING',\n /**\n * The job is in progress.\n */\n JOB_STATE_RUNNING = 'JOB_STATE_RUNNING',\n /**\n * The job completed successfully.\n */\n JOB_STATE_SUCCEEDED = 'JOB_STATE_SUCCEEDED',\n /**\n * The job failed.\n */\n JOB_STATE_FAILED = 'JOB_STATE_FAILED',\n /**\n * The job is being cancelled. From this state the job may only go to either `JOB_STATE_SUCCEEDED`, `JOB_STATE_FAILED` or `JOB_STATE_CANCELLED`.\n */\n JOB_STATE_CANCELLING = 'JOB_STATE_CANCELLING',\n /**\n * The job has been cancelled.\n */\n JOB_STATE_CANCELLED = 'JOB_STATE_CANCELLED',\n /**\n * The job has been stopped, and can be resumed.\n */\n JOB_STATE_PAUSED = 'JOB_STATE_PAUSED',\n /**\n * The job has expired.\n */\n JOB_STATE_EXPIRED = 'JOB_STATE_EXPIRED',\n /**\n * The job is being updated. Only jobs in the `JOB_STATE_RUNNING` state can be updated. After updating, the job goes back to the `JOB_STATE_RUNNING` state.\n */\n JOB_STATE_UPDATING = 'JOB_STATE_UPDATING',\n /**\n * The job is partially succeeded, some results may be missing due to errors.\n */\n JOB_STATE_PARTIALLY_SUCCEEDED = 'JOB_STATE_PARTIALLY_SUCCEEDED',\n}\n\n/** The tuning task. Either I2V or T2V. This enum is not supported in Gemini API. */\nexport enum TuningTask {\n /**\n * Default value. This value is unused.\n */\n TUNING_TASK_UNSPECIFIED = 'TUNING_TASK_UNSPECIFIED',\n /**\n * Tuning task for image to video.\n */\n TUNING_TASK_I2V = 'TUNING_TASK_I2V',\n /**\n * Tuning task for text to video.\n */\n TUNING_TASK_T2V = 'TUNING_TASK_T2V',\n /**\n * Tuning task for reference to video.\n */\n TUNING_TASK_R2V = 'TUNING_TASK_R2V',\n}\n\n/** The tokenization quality used for given media. */\nexport enum PartMediaResolutionLevel {\n /**\n * Media resolution has not been set.\n */\n MEDIA_RESOLUTION_UNSPECIFIED = 'MEDIA_RESOLUTION_UNSPECIFIED',\n /**\n * Media resolution set to low.\n */\n MEDIA_RESOLUTION_LOW = 'MEDIA_RESOLUTION_LOW',\n /**\n * Media resolution set to medium.\n */\n MEDIA_RESOLUTION_MEDIUM = 'MEDIA_RESOLUTION_MEDIUM',\n /**\n * Media resolution set to high.\n */\n MEDIA_RESOLUTION_HIGH = 'MEDIA_RESOLUTION_HIGH',\n /**\n * Media resolution set to ultra high.\n */\n MEDIA_RESOLUTION_ULTRA_HIGH = 'MEDIA_RESOLUTION_ULTRA_HIGH',\n}\n\n/** Resource scope. */\nexport enum ResourceScope {\n /**\n * When setting base_url, this value configures resource scope to be the collection.\n The resource name will not include api version, project, or location.\n For example, if base_url is set to \"https://aiplatform.googleapis.com\",\n then the resource name for a Model would be\n \"https://aiplatform.googleapis.com/publishers/google/models/gemini-3-pro-preview\n */\n COLLECTION = 'COLLECTION',\n}\n\n/** Options for feature selection preference. */\nexport enum FeatureSelectionPreference {\n FEATURE_SELECTION_PREFERENCE_UNSPECIFIED = 'FEATURE_SELECTION_PREFERENCE_UNSPECIFIED',\n PRIORITIZE_QUALITY = 'PRIORITIZE_QUALITY',\n BALANCED = 'BALANCED',\n PRIORITIZE_COST = 'PRIORITIZE_COST',\n}\n\n/** The environment being operated. */\nexport enum Environment {\n /**\n * Defaults to browser.\n */\n ENVIRONMENT_UNSPECIFIED = 'ENVIRONMENT_UNSPECIFIED',\n /**\n * Operates in a web browser.\n */\n ENVIRONMENT_BROWSER = 'ENVIRONMENT_BROWSER',\n}\n\n/** Enum that controls the safety filter level for objectionable content. */\nexport enum SafetyFilterLevel {\n BLOCK_LOW_AND_ABOVE = 'BLOCK_LOW_AND_ABOVE',\n BLOCK_MEDIUM_AND_ABOVE = 'BLOCK_MEDIUM_AND_ABOVE',\n BLOCK_ONLY_HIGH = 'BLOCK_ONLY_HIGH',\n BLOCK_NONE = 'BLOCK_NONE',\n}\n\n/** Enum that controls the generation of people. */\nexport enum PersonGeneration {\n /**\n * Block generation of images of people.\n */\n DONT_ALLOW = 'DONT_ALLOW',\n /**\n * Generate images of adults, but not children.\n */\n ALLOW_ADULT = 'ALLOW_ADULT',\n /**\n * Generate images that include adults and children.\n */\n ALLOW_ALL = 'ALLOW_ALL',\n}\n\n/** Enum that specifies the language of the text in the prompt. */\nexport enum ImagePromptLanguage {\n /**\n * Auto-detect the language.\n */\n auto = 'auto',\n /**\n * English\n */\n en = 'en',\n /**\n * Japanese\n */\n ja = 'ja',\n /**\n * Korean\n */\n ko = 'ko',\n /**\n * Hindi\n */\n hi = 'hi',\n /**\n * Chinese\n */\n zh = 'zh',\n /**\n * Portuguese\n */\n pt = 'pt',\n /**\n * Spanish\n */\n es = 'es',\n}\n\n/** Enum representing the mask mode of a mask reference image. */\nexport enum MaskReferenceMode {\n MASK_MODE_DEFAULT = 'MASK_MODE_DEFAULT',\n MASK_MODE_USER_PROVIDED = 'MASK_MODE_USER_PROVIDED',\n MASK_MODE_BACKGROUND = 'MASK_MODE_BACKGROUND',\n MASK_MODE_FOREGROUND = 'MASK_MODE_FOREGROUND',\n MASK_MODE_SEMANTIC = 'MASK_MODE_SEMANTIC',\n}\n\n/** Enum representing the control type of a control reference image. */\nexport enum ControlReferenceType {\n CONTROL_TYPE_DEFAULT = 'CONTROL_TYPE_DEFAULT',\n CONTROL_TYPE_CANNY = 'CONTROL_TYPE_CANNY',\n CONTROL_TYPE_SCRIBBLE = 'CONTROL_TYPE_SCRIBBLE',\n CONTROL_TYPE_FACE_MESH = 'CONTROL_TYPE_FACE_MESH',\n}\n\n/** Enum representing the subject type of a subject reference image. */\nexport enum SubjectReferenceType {\n SUBJECT_TYPE_DEFAULT = 'SUBJECT_TYPE_DEFAULT',\n SUBJECT_TYPE_PERSON = 'SUBJECT_TYPE_PERSON',\n SUBJECT_TYPE_ANIMAL = 'SUBJECT_TYPE_ANIMAL',\n SUBJECT_TYPE_PRODUCT = 'SUBJECT_TYPE_PRODUCT',\n}\n\n/** Enum representing the editing mode. */\nexport enum EditMode {\n EDIT_MODE_DEFAULT = 'EDIT_MODE_DEFAULT',\n EDIT_MODE_INPAINT_REMOVAL = 'EDIT_MODE_INPAINT_REMOVAL',\n EDIT_MODE_INPAINT_INSERTION = 'EDIT_MODE_INPAINT_INSERTION',\n EDIT_MODE_OUTPAINT = 'EDIT_MODE_OUTPAINT',\n EDIT_MODE_CONTROLLED_EDITING = 'EDIT_MODE_CONTROLLED_EDITING',\n EDIT_MODE_STYLE = 'EDIT_MODE_STYLE',\n EDIT_MODE_BGSWAP = 'EDIT_MODE_BGSWAP',\n EDIT_MODE_PRODUCT_IMAGE = 'EDIT_MODE_PRODUCT_IMAGE',\n}\n\n/** Enum that represents the segmentation mode. */\nexport enum SegmentMode {\n FOREGROUND = 'FOREGROUND',\n BACKGROUND = 'BACKGROUND',\n PROMPT = 'PROMPT',\n SEMANTIC = 'SEMANTIC',\n INTERACTIVE = 'INTERACTIVE',\n}\n\n/** Enum for the reference type of a video generation reference image. */\nexport enum VideoGenerationReferenceType {\n /**\n * A reference image that provides assets to the generated video,\n such as the scene, an object, a character, etc.\n */\n ASSET = 'ASSET',\n /**\n * A reference image that provides aesthetics including colors,\n lighting, texture, etc., to be used as the style of the generated video,\n such as 'anime', 'photography', 'origami', etc.\n */\n STYLE = 'STYLE',\n}\n\n/** Enum for the mask mode of a video generation mask. */\nexport enum VideoGenerationMaskMode {\n /**\n * The image mask contains a masked rectangular region which is\n applied on the first frame of the input video. The object described in\n the prompt is inserted into this region and will appear in subsequent\n frames.\n */\n INSERT = 'INSERT',\n /**\n * The image mask is used to determine an object in the\n first video frame to track. This object is removed from the video.\n */\n REMOVE = 'REMOVE',\n /**\n * The image mask is used to determine a region in the\n video. Objects in this region will be removed.\n */\n REMOVE_STATIC = 'REMOVE_STATIC',\n /**\n * The image mask contains a masked rectangular region where\n the input video will go. The remaining area will be generated. Video\n masks are not supported.\n */\n OUTPAINT = 'OUTPAINT',\n}\n\n/** Enum that controls the compression quality of the generated videos. */\nexport enum VideoCompressionQuality {\n /**\n * Optimized video compression quality. This will produce videos\n with a compressed, smaller file size.\n */\n OPTIMIZED = 'OPTIMIZED',\n /**\n * Lossless video compression quality. This will produce videos\n with a larger file size.\n */\n LOSSLESS = 'LOSSLESS',\n}\n\n/** Enum representing the tuning method. */\nexport enum TuningMethod {\n /**\n * Supervised fine tuning.\n */\n SUPERVISED_FINE_TUNING = 'SUPERVISED_FINE_TUNING',\n /**\n * Preference optimization tuning.\n */\n PREFERENCE_TUNING = 'PREFERENCE_TUNING',\n /**\n * Distillation tuning.\n */\n DISTILLATION = 'DISTILLATION',\n}\n\n/** State for the lifecycle of a Document. */\nexport enum DocumentState {\n STATE_UNSPECIFIED = 'STATE_UNSPECIFIED',\n STATE_PENDING = 'STATE_PENDING',\n STATE_ACTIVE = 'STATE_ACTIVE',\n STATE_FAILED = 'STATE_FAILED',\n}\n\n/** State for the lifecycle of a File. */\nexport enum FileState {\n STATE_UNSPECIFIED = 'STATE_UNSPECIFIED',\n PROCESSING = 'PROCESSING',\n ACTIVE = 'ACTIVE',\n FAILED = 'FAILED',\n}\n\n/** Source of the File. */\nexport enum FileSource {\n SOURCE_UNSPECIFIED = 'SOURCE_UNSPECIFIED',\n UPLOADED = 'UPLOADED',\n GENERATED = 'GENERATED',\n REGISTERED = 'REGISTERED',\n}\n\n/** The reason why the turn is complete. */\nexport enum TurnCompleteReason {\n /**\n * Default value. Reason is unspecified.\n */\n TURN_COMPLETE_REASON_UNSPECIFIED = 'TURN_COMPLETE_REASON_UNSPECIFIED',\n /**\n * The function call generated by the model is invalid.\n */\n MALFORMED_FUNCTION_CALL = 'MALFORMED_FUNCTION_CALL',\n /**\n * The response is rejected by the model.\n */\n RESPONSE_REJECTED = 'RESPONSE_REJECTED',\n /**\n * Needs more input from the user.\n */\n NEED_MORE_INPUT = 'NEED_MORE_INPUT',\n}\n\n/** Server content modalities. */\nexport enum MediaModality {\n /**\n * The modality is unspecified.\n */\n MODALITY_UNSPECIFIED = 'MODALITY_UNSPECIFIED',\n /**\n * Plain text.\n */\n TEXT = 'TEXT',\n /**\n * Images.\n */\n IMAGE = 'IMAGE',\n /**\n * Video.\n */\n VIDEO = 'VIDEO',\n /**\n * Audio.\n */\n AUDIO = 'AUDIO',\n /**\n * Document, e.g. PDF.\n */\n DOCUMENT = 'DOCUMENT',\n}\n\n/** The type of the VAD signal. */\nexport enum VadSignalType {\n /**\n * The default is VAD_SIGNAL_TYPE_UNSPECIFIED.\n */\n VAD_SIGNAL_TYPE_UNSPECIFIED = 'VAD_SIGNAL_TYPE_UNSPECIFIED',\n /**\n * Start of sentence signal.\n */\n VAD_SIGNAL_TYPE_SOS = 'VAD_SIGNAL_TYPE_SOS',\n /**\n * End of sentence signal.\n */\n VAD_SIGNAL_TYPE_EOS = 'VAD_SIGNAL_TYPE_EOS',\n}\n\n/** The type of the voice activity signal. */\nexport enum VoiceActivityType {\n /**\n * The default is VOICE_ACTIVITY_TYPE_UNSPECIFIED.\n */\n TYPE_UNSPECIFIED = 'TYPE_UNSPECIFIED',\n /**\n * Start of sentence signal.\n */\n ACTIVITY_START = 'ACTIVITY_START',\n /**\n * End of sentence signal.\n */\n ACTIVITY_END = 'ACTIVITY_END',\n}\n\n/** Start of speech sensitivity. */\nexport enum StartSensitivity {\n /**\n * The default is START_SENSITIVITY_LOW.\n */\n START_SENSITIVITY_UNSPECIFIED = 'START_SENSITIVITY_UNSPECIFIED',\n /**\n * Automatic detection will detect the start of speech more often.\n */\n START_SENSITIVITY_HIGH = 'START_SENSITIVITY_HIGH',\n /**\n * Automatic detection will detect the start of speech less often.\n */\n START_SENSITIVITY_LOW = 'START_SENSITIVITY_LOW',\n}\n\n/** End of speech sensitivity. */\nexport enum EndSensitivity {\n /**\n * The default is END_SENSITIVITY_LOW.\n */\n END_SENSITIVITY_UNSPECIFIED = 'END_SENSITIVITY_UNSPECIFIED',\n /**\n * Automatic detection ends speech more often.\n */\n END_SENSITIVITY_HIGH = 'END_SENSITIVITY_HIGH',\n /**\n * Automatic detection ends speech less often.\n */\n END_SENSITIVITY_LOW = 'END_SENSITIVITY_LOW',\n}\n\n/** The different ways of handling user activity. */\nexport enum ActivityHandling {\n /**\n * If unspecified, the default behavior is `START_OF_ACTIVITY_INTERRUPTS`.\n */\n ACTIVITY_HANDLING_UNSPECIFIED = 'ACTIVITY_HANDLING_UNSPECIFIED',\n /**\n * If true, start of activity will interrupt the model's response (also called \"barge in\"). The model's current response will be cut-off in the moment of the interruption. This is the default behavior.\n */\n START_OF_ACTIVITY_INTERRUPTS = 'START_OF_ACTIVITY_INTERRUPTS',\n /**\n * The model's response will not be interrupted.\n */\n NO_INTERRUPTION = 'NO_INTERRUPTION',\n}\n\n/** Options about which input is included in the user's turn. */\nexport enum TurnCoverage {\n /**\n * If unspecified, the default behavior is `TURN_INCLUDES_ONLY_ACTIVITY`.\n */\n TURN_COVERAGE_UNSPECIFIED = 'TURN_COVERAGE_UNSPECIFIED',\n /**\n * The users turn only includes activity since the last turn, excluding inactivity (e.g. silence on the audio stream). This is the default behavior.\n */\n TURN_INCLUDES_ONLY_ACTIVITY = 'TURN_INCLUDES_ONLY_ACTIVITY',\n /**\n * The users turn includes all realtime input since the last turn, including inactivity (e.g. silence on the audio stream).\n */\n TURN_INCLUDES_ALL_INPUT = 'TURN_INCLUDES_ALL_INPUT',\n}\n\n/** Scale of the generated music. */\nexport enum Scale {\n /**\n * Default value. This value is unused.\n */\n SCALE_UNSPECIFIED = 'SCALE_UNSPECIFIED',\n /**\n * C major or A minor.\n */\n C_MAJOR_A_MINOR = 'C_MAJOR_A_MINOR',\n /**\n * Db major or Bb minor.\n */\n D_FLAT_MAJOR_B_FLAT_MINOR = 'D_FLAT_MAJOR_B_FLAT_MINOR',\n /**\n * D major or B minor.\n */\n D_MAJOR_B_MINOR = 'D_MAJOR_B_MINOR',\n /**\n * Eb major or C minor\n */\n E_FLAT_MAJOR_C_MINOR = 'E_FLAT_MAJOR_C_MINOR',\n /**\n * E major or Db minor.\n */\n E_MAJOR_D_FLAT_MINOR = 'E_MAJOR_D_FLAT_MINOR',\n /**\n * F major or D minor.\n */\n F_MAJOR_D_MINOR = 'F_MAJOR_D_MINOR',\n /**\n * Gb major or Eb minor.\n */\n G_FLAT_MAJOR_E_FLAT_MINOR = 'G_FLAT_MAJOR_E_FLAT_MINOR',\n /**\n * G major or E minor.\n */\n G_MAJOR_E_MINOR = 'G_MAJOR_E_MINOR',\n /**\n * Ab major or F minor.\n */\n A_FLAT_MAJOR_F_MINOR = 'A_FLAT_MAJOR_F_MINOR',\n /**\n * A major or Gb minor.\n */\n A_MAJOR_G_FLAT_MINOR = 'A_MAJOR_G_FLAT_MINOR',\n /**\n * Bb major or G minor.\n */\n B_FLAT_MAJOR_G_MINOR = 'B_FLAT_MAJOR_G_MINOR',\n /**\n * B major or Ab minor.\n */\n B_MAJOR_A_FLAT_MINOR = 'B_MAJOR_A_FLAT_MINOR',\n}\n\n/** The mode of music generation. */\nexport enum MusicGenerationMode {\n /**\n * Rely on the server default generation mode.\n */\n MUSIC_GENERATION_MODE_UNSPECIFIED = 'MUSIC_GENERATION_MODE_UNSPECIFIED',\n /**\n * Steer text prompts to regions of latent space with higher quality\n music.\n */\n QUALITY = 'QUALITY',\n /**\n * Steer text prompts to regions of latent space with a larger\n diversity of music.\n */\n DIVERSITY = 'DIVERSITY',\n /**\n * Steer text prompts to regions of latent space more likely to\n generate music with vocals.\n */\n VOCALIZATION = 'VOCALIZATION',\n}\n\n/** The playback control signal to apply to the music generation. */\nexport enum LiveMusicPlaybackControl {\n /**\n * This value is unused.\n */\n PLAYBACK_CONTROL_UNSPECIFIED = 'PLAYBACK_CONTROL_UNSPECIFIED',\n /**\n * Start generating the music.\n */\n PLAY = 'PLAY',\n /**\n * Hold the music generation. Use PLAY to resume from the current position.\n */\n PAUSE = 'PAUSE',\n /**\n * Stop the music generation and reset the context (prompts retained).\n Use PLAY to restart the music generation.\n */\n STOP = 'STOP',\n /**\n * Reset the context of the music generation without stopping it.\n Retains the current prompts and config.\n */\n RESET_CONTEXT = 'RESET_CONTEXT',\n}\n\n/** Media resolution for the input media. */\nexport declare interface PartMediaResolution {\n /** The tokenization quality used for given media.\n */\n level?: PartMediaResolutionLevel;\n /** Specifies the required sequence length for media tokenization.\n */\n numTokens?: number;\n}\n\n/** Result of executing the [ExecutableCode]. Only generated when using the [CodeExecution] tool, and always follows a `part` containing the [ExecutableCode]. */\nexport declare interface CodeExecutionResult {\n /** Required. Outcome of the code execution. */\n outcome?: Outcome;\n /** Optional. Contains stdout when code execution is successful, stderr or other description otherwise. */\n output?: string;\n}\n\n/** Code generated by the model that is meant to be executed, and the result returned to the model. Generated when using the [CodeExecution] tool, in which the code will be automatically executed, and a corresponding [CodeExecutionResult] will also be generated. */\nexport declare interface ExecutableCode {\n /** Required. The code to be executed. */\n code?: string;\n /** Required. Programming language of the `code`. */\n language?: Language;\n}\n\n/** URI based data. */\nexport declare interface FileData {\n /** Optional. Display name of the file data. Used to provide a label or filename to distinguish file datas. This field is only returned in PromptMessage for prompt management. It is currently used in the Gemini GenerateContent calls only when server side tools (code_execution, google_search, and url_context) are enabled. This field is not supported in Gemini API. */\n displayName?: string;\n /** Required. URI. */\n fileUri?: string;\n /** Required. The IANA standard MIME type of the source data. */\n mimeType?: string;\n}\n\n/** Partial argument value of the function call. This data type is not supported in Gemini API. */\nexport declare interface PartialArg {\n /** Optional. Represents a null value. */\n nullValue?: 'NULL_VALUE';\n /** Optional. Represents a double value. */\n numberValue?: number;\n /** Optional. Represents a string value. */\n stringValue?: string;\n /** Optional. Represents a boolean value. */\n boolValue?: boolean;\n /** Required. A JSON Path (RFC 9535) to the argument being streamed. https://datatracker.ietf.org/doc/html/rfc9535. e.g. \"$.foo.bar[0].data\". */\n jsonPath?: string;\n /** Optional. Whether this is not the last part of the same json_path. If true, another PartialArg message for the current json_path is expected to follow. */\n willContinue?: boolean;\n}\n\n/** A function call. */\nexport declare interface FunctionCall {\n /** The unique id of the function call. If populated, the client to execute the\n `function_call` and return the response with the matching `id`. */\n id?: string;\n /** Optional. The function parameters and values in JSON object format. See [FunctionDeclaration.parameters] for parameter details. */\n args?: Record<string, unknown>;\n /** Optional. The name of the function to call. Matches [FunctionDeclaration.name]. */\n name?: string;\n /** Optional. The partial argument value of the function call. If provided, represents the arguments/fields that are streamed incrementally. This field is not supported in Gemini API. */\n partialArgs?: PartialArg[];\n /** Optional. Whether this is the last part of the FunctionCall. If true, another partial message for the current FunctionCall is expected to follow. This field is not supported in Gemini API. */\n willContinue?: boolean;\n}\n\n/** Raw media bytes for function response.\n\nText should not be sent as raw bytes, use the FunctionResponse.response\nfield. */\nexport class FunctionResponseBlob {\n /** Required. The IANA standard MIME type of the source data. */\n mimeType?: string;\n /** Required. Inline media bytes.\n * @remarks Encoded as base64 string. */\n data?: string;\n /** Optional. Display name of the blob.\n Used to provide a label or filename to distinguish blobs. */\n displayName?: string;\n}\n\n/** URI based data for function response. */\nexport class FunctionResponseFileData {\n /** Required. URI. */\n fileUri?: string;\n /** Required. The IANA standard MIME type of the source data. */\n mimeType?: string;\n /** Optional. Display name of the file.\n Used to provide a label or filename to distinguish files. */\n displayName?: string;\n}\n\n/** A datatype containing media that is part of a `FunctionResponse` message.\n\nA `FunctionResponsePart` consists of data which has an associated datatype. A\n`FunctionResponsePart` can only contain one of the accepted types in\n`FunctionResponsePart.data`.\n\nA `FunctionResponsePart` must have a fixed IANA MIME type identifying the\ntype and subtype of the media if the `inline_data` field is filled with raw\nbytes. */\nexport class FunctionResponsePart {\n /** Optional. Inline media bytes. */\n inlineData?: FunctionResponseBlob;\n /** Optional. URI based data. */\n fileData?: FunctionResponseFileData;\n}\n/**\n * Creates a `FunctionResponsePart` object from a `base64` encoded `string`.\n */\nexport function createFunctionResponsePartFromBase64(\n data: string,\n mimeType: string,\n): FunctionResponsePart {\n return {\n inlineData: {\n data: data,\n mimeType: mimeType,\n },\n };\n}\n/**\n * Creates a `FunctionResponsePart` object from a `URI` string.\n */\nexport function createFunctionResponsePartFromUri(\n uri: string,\n mimeType: string,\n): FunctionResponsePart {\n return {\n fileData: {\n fileUri: uri,\n mimeType: mimeType,\n },\n };\n}\n\n/** A function response. */\nexport class FunctionResponse {\n /** Signals that function call continues, and more responses will be returned, turning the function call into a generator. Is only applicable to NON_BLOCKING function calls (see FunctionDeclaration.behavior for details), ignored otherwise. If false, the default, future responses will not be considered. Is only applicable to NON_BLOCKING function calls, is ignored otherwise. If set to false, future responses will not be considered. It is allowed to return empty `response` with `will_continue=False` to signal that the function call is finished. */\n willContinue?: boolean;\n /** Specifies how the response should be scheduled in the conversation. Only applicable to NON_BLOCKING function calls, is ignored otherwise. Defaults to WHEN_IDLE. */\n scheduling?: FunctionResponseScheduling;\n /** List of parts that constitute a function response. Each part may\n have a different IANA MIME type. */\n parts?: FunctionResponsePart[];\n /** Optional. The id of the function call this response is for. Populated by the client to match the corresponding function call `id`. */\n id?: string;\n /** Required. The name of the function to call. Matches [FunctionDeclaration.name] and [FunctionCall.name]. */\n name?: string;\n /** Required. The function response in JSON object format. Use \"output\" key to specify function output and \"error\" key to specify error details (if any). If \"output\" and \"error\" keys are not specified, then whole \"response\" is treated as function output. */\n response?: Record<string, unknown>;\n}\n\n/** Content blob. */\nexport declare interface Blob {\n /** Required. Raw bytes.\n * @remarks Encoded as base64 string. */\n data?: string;\n /** Optional. Display name of the blob. Used to provide a label or filename to distinguish blobs. This field is only returned in PromptMessage for prompt management. It is currently used in the Gemini GenerateContent calls only when server side tools (code_execution, google_search, and url_context) are enabled. This field is not supported in Gemini API. */\n displayName?: string;\n /** Required. The IANA standard MIME type of the source data. */\n mimeType?: string;\n}\n\n/** Metadata describes the input video content. */\nexport declare interface VideoMetadata {\n /** Optional. The end offset of the video. */\n endOffset?: string;\n /** Optional. The frame rate of the video sent to the model. If not specified, the default value will be 1.0. The fps range is (0.0, 24.0]. */\n fps?: number;\n /** Optional. The start offset of the video. */\n startOffset?: string;\n}\n\n/** A datatype containing media content.\n\nExactly one field within a Part should be set, representing the specific type\nof content being conveyed. Using multiple fields within the same `Part`\ninstance is considered invalid. */\nexport declare interface Part {\n /** Media resolution for the input media.\n */\n mediaResolution?: PartMediaResolution;\n /** Optional. Result of executing the [ExecutableCode]. */\n codeExecutionResult?: CodeExecutionResult;\n /** Optional. Code generated by the model that is meant to be executed. */\n executableCode?: ExecutableCode;\n /** Optional. URI based data. */\n fileData?: FileData;\n /** Optional. A predicted [FunctionCall] returned from the model that contains a string representing the [FunctionDeclaration.name] with the parameters and their values. */\n functionCall?: FunctionCall;\n /** Optional. The result output of a [FunctionCall] that contains a string representing the [FunctionDeclaration.name] and a structured JSON object containing any output from the function call. It is used as context to the model. */\n functionResponse?: FunctionResponse;\n /** Optional. Inlined bytes data. */\n inlineData?: Blob;\n /** Optional. Text part (can be code). */\n text?: string;\n /** Optional. Indicates if the part is thought from the model. */\n thought?: boolean;\n /** Optional. An opaque signature for the thought so it can be reused in subsequent requests.\n * @remarks Encoded as base64 string. */\n thoughtSignature?: string;\n /** Optional. Video metadata. The metadata should only be specified while the video data is presented in inline_data or file_data. */\n videoMetadata?: VideoMetadata;\n}\n/**\n * Creates a `Part` object from a `URI` string.\n */\nexport function createPartFromUri(\n uri: string,\n mimeType: string,\n mediaResolution?: PartMediaResolutionLevel,\n): Part {\n return {\n fileData: {\n fileUri: uri,\n mimeType: mimeType,\n },\n ...(mediaResolution && {mediaResolution: {level: mediaResolution}}),\n };\n}\n/**\n * Creates a `Part` object from a `text` string.\n */\nexport function createPartFromText(text: string): Part {\n return {\n text: text,\n };\n}\n/**\n * Creates a `Part` object from a `FunctionCall` object.\n */\nexport function createPartFromFunctionCall(\n name: string,\n args: Record<string, unknown>,\n): Part {\n return {\n functionCall: {\n name: name,\n args: args,\n },\n };\n}\n/**\n * Creates a `Part` object from a `FunctionResponse` object.\n */\nexport function createPartFromFunctionResponse(\n id: string,\n name: string,\n response: Record<string, unknown>,\n parts: FunctionResponsePart[] = [],\n): Part {\n return {\n functionResponse: {\n id: id,\n name: name,\n response: response,\n ...(parts.length > 0 && {parts}),\n },\n };\n}\n/**\n * Creates a `Part` object from a `base64` encoded `string`.\n */\nexport function createPartFromBase64(\n data: string,\n mimeType: string,\n mediaResolution?: PartMediaResolutionLevel,\n): Part {\n return {\n inlineData: {\n data: data,\n mimeType: mimeType,\n },\n ...(mediaResolution && {mediaResolution: {level: mediaResolution}}),\n };\n}\n/**\n * Creates a `Part` object from the `outcome` and `output` of a `CodeExecutionResult` object.\n */\nexport function createPartFromCodeExecutionResult(\n outcome: Outcome,\n output: string,\n): Part {\n return {\n codeExecutionResult: {\n outcome: outcome,\n output: output,\n },\n };\n}\n/**\n * Creates a `Part` object from the `code` and `language` of an `ExecutableCode` object.\n */\nexport function createPartFromExecutableCode(\n code: string,\n language: Language,\n): Part {\n return {\n executableCode: {\n code: code,\n language: language,\n },\n };\n}\n\n/** Contains the multi-part content of a message. */\nexport declare interface Content {\n /** List of parts that constitute a single message. Each part may have\n a different IANA MIME type. */\n parts?: Part[];\n /** Optional. The producer of the content. Must be either 'user' or 'model'. Useful to set for multi-turn conversations, otherwise can be left blank or unset. */\n role?: string;\n}\nfunction _isPart(obj: unknown): obj is Part {\n if (typeof obj === 'object' && obj !== null) {\n return (\n 'fileData' in obj ||\n 'text' in obj ||\n 'functionCall' in obj ||\n 'functionResponse' in obj ||\n 'inlineData' in obj ||\n 'videoMetadata' in obj ||\n 'codeExecutionResult' in obj ||\n 'executableCode' in obj\n );\n }\n return false;\n}\nfunction _toParts(partOrString: PartListUnion | string): Part[] {\n const parts: Part[] = [];\n if (typeof partOrString === 'string') {\n parts.push(createPartFromText(partOrString));\n } else if (_isPart(partOrString)) {\n parts.push(partOrString);\n } else if (Array.isArray(partOrString)) {\n if (partOrString.length === 0) {\n throw new Error('partOrString cannot be an empty array');\n }\n for (const part of partOrString) {\n if (typeof part === 'string') {\n parts.push(createPartFromText(part));\n } else if (_isPart(part)) {\n parts.push(part);\n } else {\n throw new Error('element in PartUnion must be a Part object or string');\n }\n }\n } else {\n throw new Error('partOrString must be a Part object, string, or array');\n }\n return parts;\n}\n/**\n * Creates a `Content` object with a user role from a `PartListUnion` object or `string`.\n */\nexport function createUserContent(\n partOrString: PartListUnion | string,\n): Content {\n return {\n role: 'user',\n parts: _toParts(partOrString),\n };\n}\n\n/**\n * Creates a `Content` object with a model role from a `PartListUnion` object or `string`.\n */\nexport function createModelContent(\n partOrString: PartListUnion | string,\n): Content {\n return {\n role: 'model',\n parts: _toParts(partOrString),\n };\n}\n/** HTTP retry options to be used in each of the requests. */\nexport declare interface HttpRetryOptions {\n /** Maximum number of attempts, including the original request.\n If 0 or 1, it means no retries. If not specified, default to 5. */\n attempts?: number;\n}\n\n/** HTTP options to be used in each of the requests. */\nexport declare interface HttpOptions {\n /** The base URL for the AI platform service endpoint. */\n baseUrl?: string;\n /** The resource scope used to constructing the resource name when base_url is set */\n baseUrlResourceScope?: ResourceScope;\n /** Specifies the version of the API to use. */\n apiVersion?: string;\n /** Additional HTTP headers to be sent with the request. */\n headers?: Record<string, string>;\n /** Timeout for the request in milliseconds. */\n timeout?: number;\n /** Extra parameters to add to the request body.\n The structure must match the backend API's request structure.\n - VertexAI backend API docs: https://cloud.google.com/vertex-ai/docs/reference/rest\n - GeminiAPI backend API docs: https://ai.google.dev/api/rest */\n extraBody?: Record<string, unknown>;\n /** HTTP retry options for the request. */\n retryOptions?: HttpRetryOptions;\n}\n\n/** Schema is used to define the format of input/output data.\n\nRepresents a select subset of an [OpenAPI 3.0 schema\nobject](https://spec.openapis.org/oas/v3.0.3#schema-object). More fields may\nbe added in the future as needed. */\nexport declare interface Schema {\n /** Optional. The value should be validated against any (one or more) of the subschemas in the list. */\n anyOf?: Schema[];\n /** Optional. Default value of the data. */\n default?: unknown;\n /** Optional. The description of the data. */\n description?: string;\n /** Optional. Possible values of the element of primitive type with enum format. Examples: 1. We can define direction as : {type:STRING, format:enum, enum:[\"EAST\", NORTH\", \"SOUTH\", \"WEST\"]} 2. We can define apartment number as : {type:INTEGER, format:enum, enum:[\"101\", \"201\", \"301\"]} */\n enum?: string[];\n /** Optional. Example of the object. Will only populated when the object is the root. */\n example?: unknown;\n /** Optional. The format of the data. Supported formats: for NUMBER type: \"float\", \"double\" for INTEGER type: \"int32\", \"int64\" for STRING type: \"email\", \"byte\", etc */\n format?: string;\n /** Optional. SCHEMA FIELDS FOR TYPE ARRAY Schema of the elements of Type.ARRAY. */\n items?: Schema;\n /** Optional. Maximum number of the elements for Type.ARRAY. */\n maxItems?: string;\n /** Optional. Maximum length of the Type.STRING */\n maxLength?: string;\n /** Optional. Maximum number of the properties for Type.OBJECT. */\n maxProperties?: string;\n /** Optional. Maximum value of the Type.INTEGER and Type.NUMBER */\n maximum?: number;\n /** Optional. Minimum number of the elements for Type.ARRAY. */\n minItems?: string;\n /** Optional. SCHEMA FIELDS FOR TYPE STRING Minimum length of the Type.STRING */\n minLength?: string;\n /** Optional. Minimum number of the properties for Type.OBJECT. */\n minProperties?: string;\n /** Optional. SCHEMA FIELDS FOR TYPE INTEGER and NUMBER Minimum value of the Type.INTEGER and Type.NUMBER */\n minimum?: number;\n /** Optional. Indicates if the value may be null. */\n nullable?: boolean;\n /** Optional. Pattern of the Type.STRING to restrict a string to a regular expression. */\n pattern?: string;\n /** Optional. SCHEMA FIELDS FOR TYPE OBJECT Properties of Type.OBJECT. */\n properties?: Record<string, Schema>;\n /** Optional. The order of the properties. Not a standard field in open api spec. Only used to support the order of the properties. */\n propertyOrdering?: string[];\n /** Optional. Required properties of Type.OBJECT. */\n required?: string[];\n /** Optional. The title of the Schema. */\n title?: string;\n /** Optional. The type of the data. */\n type?: Type;\n}\n\n/** Config for model selection. */\nexport declare interface ModelSelectionConfig {\n /** Options for feature selection preference. */\n featureSelectionPreference?: FeatureSelectionPreference;\n}\n\n/** Tool to support computer use. */\nexport declare interface ComputerUse {\n /** Required. The environment being operated. */\n environment?: Environment;\n /** By default, predefined functions are included in the final model call.\n Some of them can be explicitly excluded from being automatically included.\n This can serve two purposes:\n 1. Using a more restricted / different action space.\n 2. Improving the definitions / instructions of predefined functions. */\n excludedPredefinedFunctions?: string[];\n}\n\n/** Tool to retrieve knowledge from the File Search Stores. */\nexport declare interface FileSearch {\n /** The names of the file_search_stores to retrieve from.\n Example: `fileSearchStores/my-file-search-store-123` */\n fileSearchStoreNames?: string[];\n /** The number of file search retrieval chunks to retrieve. */\n topK?: number;\n /** Metadata filter to apply to the file search retrieval documents. See https://google.aip.dev/160 for the syntax of the filter expression. */\n metadataFilter?: string;\n}\n\n/** The API secret. This data type is not supported in Gemini API. */\nexport declare interface ApiAuthApiKeyConfig {\n /** Required. The SecretManager secret version resource name storing API key. e.g. projects/{project}/secrets/{secret}/versions/{version} */\n apiKeySecretVersion?: string;\n /** The API key string. Either this or `api_key_secret_version` must be set. */\n apiKeyString?: string;\n}\n\n/** The generic reusable api auth config. Deprecated. Please use AuthConfig (google/cloud/aiplatform/master/auth.proto) instead. This data type is not supported in Gemini API. */\nexport declare interface ApiAuth {\n /** The API secret. */\n apiKeyConfig?: ApiAuthApiKeyConfig;\n}\n\n/** Config for authentication with API key. This data type is not supported in Gemini API. */\nexport declare interface ApiKeyConfig {\n /** Optional. The name of the SecretManager secret version resource storing the API key. Format: `projects/{project}/secrets/{secrete}/versions/{version}` - If both `api_key_secret` and `api_key_string` are specified, this field takes precedence over `api_key_string`. - If specified, the `secretmanager.versions.access` permission should be granted to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents) on the specified resource. */\n apiKeySecret?: string;\n /** Optional. The API key to be used in the request directly. */\n apiKeyString?: string;\n /** Optional. The location of the API key. */\n httpElementLocation?: HttpElementLocation;\n /** Optional. The parameter name of the API key. E.g. If the API request is \"https://example.com/act?api_key=\", \"api_key\" would be the parameter name. */\n name?: string;\n}\n\n/** Config for Google Service Account Authentication. This data type is not supported in Gemini API. */\nexport declare interface AuthConfigGoogleServiceAccountConfig {\n /** Optional. The service account that the extension execution service runs as. - If the service account is specified, the `iam.serviceAccounts.getAccessToken` permission should be granted to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents) on the specified service account. - If not specified, the Vertex AI Extension Service Agent will be used to execute the Extension. */\n serviceAccount?: string;\n}\n\n/** Config for HTTP Basic Authentication. This data type is not supported in Gemini API. */\nexport declare interface AuthConfigHttpBasicAuthConfig {\n /** Required. The name of the SecretManager secret version resource storing the base64 encoded credentials. Format: `projects/{project}/secrets/{secrete}/versions/{version}` - If specified, the `secretmanager.versions.access` permission should be granted to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents) on the specified resource. */\n credentialSecret?: string;\n}\n\n/** Config for user oauth. This data type is not supported in Gemini API. */\nexport declare interface AuthConfigOauthConfig {\n /** Access token for extension endpoint. Only used to propagate token from [[ExecuteExtensionRequest.runtime_auth_config]] at request time. */\n accessToken?: string;\n /** The service account used to generate access tokens for executing the Extension. - If the service account is specified, the `iam.serviceAccounts.getAccessToken` permission should be granted to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents) on the provided service account. */\n serviceAccount?: string;\n}\n\n/** Config for user OIDC auth. This data type is not supported in Gemini API. */\nexport declare interface AuthConfigOidcConfig {\n /** OpenID Connect formatted ID token for extension endpoint. Only used to propagate token from [[ExecuteExtensionRequest.runtime_auth_config]] at request time. */\n idToken?: string;\n /** The service account used to generate an OpenID Connect (OIDC)-compatible JWT token signed by the Google OIDC Provider (accounts.google.com) for extension endpoint (https://cloud.google.com/iam/docs/create-short-lived-credentials-direct#sa-credentials-oidc). - The audience for the token will be set to the URL in the server url defined in the OpenApi spec. - If the service account is provided, the service account should grant `iam.serviceAccounts.getOpenIdToken` permission to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents). */\n serviceAccount?: string;\n}\n\n/** Auth configuration to run the extension. This data type is not supported in Gemini API. */\nexport declare interface AuthConfig {\n /** Config for API key auth. */\n apiKeyConfig?: ApiKeyConfig;\n /** Type of auth scheme. */\n authType?: AuthType;\n /** Config for Google Service Account auth. */\n googleServiceAccountConfig?: AuthConfigGoogleServiceAccountConfig;\n /** Config for HTTP Basic auth. */\n httpBasicAuthConfig?: AuthConfigHttpBasicAuthConfig;\n /** Config for user oauth. */\n oauthConfig?: AuthConfigOauthConfig;\n /** Config for user OIDC auth. */\n oidcConfig?: AuthConfigOidcConfig;\n}\n\n/** The search parameters to use for the ELASTIC_SEARCH spec. This data type is not supported in Gemini API. */\nexport declare interface ExternalApiElasticSearchParams {\n /** The ElasticSearch index to use. */\n index?: string;\n /** Optional. Number of hits (chunks) to request. When specified, it is passed to Elasticsearch as the `num_hits` param. */\n numHits?: number;\n /** The ElasticSearch search template to use. */\n searchTemplate?: string;\n}\n\n/** The search parameters to use for SIMPLE_SEARCH spec. This data type is not supported in Gemini API. */\nexport declare interface ExternalApiSimpleSearchParams {}\n\n/** Retrieve from data source powered by external API for grounding. The external API is not owned by Google, but need to follow the pre-defined API spec. This data type is not supported in Gemini API. */\nexport declare interface ExternalApi {\n /** The authentication config to access the API. Deprecated. Please use auth_config instead. */\n apiAuth?: ApiAuth;\n /** The API spec that the external API implements. */\n apiSpec?: ApiSpec;\n /** The authentication config to access the API. */\n authConfig?: AuthConfig;\n /** Parameters for the elastic search API. */\n elasticSearchParams?: ExternalApiElasticSearchParams;\n /** The endpoint of the external API. The system will call the API at this endpoint to retrieve the data for grounding. Example: https://acme.com:443/search */\n endpoint?: string;\n /** Parameters for the simple search API. */\n simpleSearchParams?: ExternalApiSimpleSearchParams;\n}\n\n/** Define data stores within engine to filter on in a search call and configurations for those data stores. For more information, see https://cloud.google.com/generative-ai-app-builder/docs/reference/rpc/google.cloud.discoveryengine.v1#datastorespec. This data type is not supported in Gemini API. */\nexport declare interface VertexAISearchDataStoreSpec {\n /** Full resource name of DataStore, such as Format: `projects/{project}/locations/{location}/collections/{collection}/dataStores/{dataStore}` */\n dataStore?: string;\n /** Optional. Filter specification to filter documents in the data store specified by data_store field. For more information on filtering, see [Filtering](https://cloud.google.com/generative-ai-app-builder/docs/filter-search-metadata) */\n filter?: string;\n}\n\n/** Retrieve from Vertex AI Search datastore or engine for grounding. datastore and engine are mutually exclusive. See https://cloud.google.com/products/agent-builder. This data type is not supported in Gemini API. */\nexport declare interface VertexAISearch {\n /** Specifications that define the specific DataStores to be searched, along with configurations for those data stores. This is only considered for Engines with multiple data stores. It should only be set if engine is used. */\n dataStoreSpecs?: VertexAISearchDataStoreSpec[];\n /** Optional. Fully-qualified Vertex AI Search data store resource ID. Format: `projects/{project}/locations/{location}/collections/{collection}/dataStores/{dataStore}` */\n datastore?: string;\n /** Optional. Fully-qualified Vertex AI Search engine resource ID. Format: `projects/{project}/locations/{location}/collections/{collection}/engines/{engine}` */\n engine?: string;\n /** Optional. Filter strings to be passed to the search API. */\n filter?: string;\n /** Optional. Number of search results to return per query. The default value is 10. The maximumm allowed value is 10. */\n maxResults?: number;\n}\n\n/** The definition of the Rag resource. This data type is not supported in Gemini API. */\nexport declare interface VertexRagStoreRagResource {\n /** Optional. RagCorpora resource name. Format: `projects/{project}/locations/{location}/ragCorpora/{rag_corpus}` */\n ragCorpus?: string;\n /** Optional. rag_file_id. The files should be in the same rag_corpus set in rag_corpus field. */\n ragFileIds?: string[];\n}\n\n/** Config for filters. This data type is not supported in Gemini API. */\nexport declare interface RagRetrievalConfigFilter {\n /** Optional. String for metadata filtering. */\n metadataFilter?: string;\n /** Optional. Only returns contexts with vector distance smaller than the threshold. */\n vectorDistanceThreshold?: number;\n /** Optional. Only returns contexts with vector similarity larger than the threshold. */\n vectorSimilarityThreshold?: number;\n}\n\n/** Config for Hybrid Search. This data type is not supported in Gemini API. */\nexport declare interface RagRetrievalConfigHybridSearch {\n /** Optional. Alpha value controls the weight between dense and sparse vector search results. The range is [0, 1], while 0 means sparse vector search only and 1 means dense vector search only. The default value is 0.5 which balances sparse and dense vector search equally. */\n alpha?: number;\n}\n\n/** Config for LlmRanker. This data type is not supported in Gemini API. */\nexport declare interface RagRetrievalConfigRankingLlmRanker {\n /** Optional. The model name used for ranking. See [Supported models](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference#supported-models). */\n modelName?: string;\n}\n\n/** Config for Rank Service. This data type is not supported in Gemini API. */\nexport declare interface RagRetrievalConfigRankingRankService {\n /** Optional. The model name of the rank service. Format: `semantic-ranker-512@latest` */\n modelName?: string;\n}\n\n/** Config for ranking and reranking. This data type is not supported in Gemini API. */\nexport declare interface RagRetrievalConfigRanking {\n /** Optional. Config for LlmRanker. */\n llmRanker?: RagRetrievalConfigRankingLlmRanker;\n /** Optional. Config for Rank Service. */\n rankService?: RagRetrievalConfigRankingRankService;\n}\n\n/** Specifies the context retrieval config. This data type is not supported in Gemini API. */\nexport declare interface RagRetrievalConfig {\n /** Optional. Config for filters. */\n filter?: RagRetrievalConfigFilter;\n /** Optional. Config for Hybrid Search. */\n hybridSearch?: RagRetrievalConfigHybridSearch;\n /** Optional. Config for ranking and reranking. */\n ranking?: RagRetrievalConfigRanking;\n /** Optional. The number of contexts to retrieve. */\n topK?: number;\n}\n\n/** Retrieve from Vertex RAG Store for grounding. This data type is not supported in Gemini API. */\nexport declare interface VertexRagStore {\n /** Optional. Deprecated. Please use rag_resources instead. */\n ragCorpora?: string[];\n /** Optional. The representation of the rag source. It can be used to specify corpus only or ragfiles. Currently only support one corpus or multiple files from one corpus. In the future we may open up multiple corpora support. */\n ragResources?: VertexRagStoreRagResource[];\n /** Optional. The retrieval config for the Rag query. */\n ragRetrievalConfig?: RagRetrievalConfig;\n /** Optional. Number of top k results to return from the selected corpora. */\n similarityTopK?: number;\n /** Optional. Currently only supported for Gemini Multimodal Live API. In Gemini Multimodal Live API, if `store_context` bool is specified, Gemini will leverage it to automatically memorize the interactions between the client and Gemini, and retrieve context when needed to augment the response generation for users' ongoing and future interactions. */\n storeContext?: boolean;\n /** Optional. Only return results with vector distance smaller than the threshold. */\n vectorDistanceThreshold?: number;\n}\n\n/** Defines a retrieval tool that model can call to access external knowledge. This data type is not supported in Gemini API. */\nexport declare interface Retrieval {\n /** Optional. Deprecated. This option is no longer supported. */\n disableAttribution?: boolean;\n /** Use data source powered by external API for grounding. */\n externalApi?: ExternalApi;\n /** Set to use data source powered by Vertex AI Search. */\n vertexAiSearch?: VertexAISearch;\n /** Set to use data source powered by Vertex RAG store. User data is uploaded via the VertexRagDataService. */\n vertexRagStore?: VertexRagStore;\n}\n\n/** Tool that executes code generated by the model, and automatically returns the result to the model. See also [ExecutableCode]and [CodeExecutionResult] which are input and output to this tool. This data type is not supported in Gemini API. */\nexport declare interface ToolCodeExecution {}\n\n/** Tool to search public web data, powered by Vertex AI Search and Sec4 compliance. This data type is not supported in Gemini API. */\nexport declare interface EnterpriseWebSearch {\n /** Optional. List of domains to be excluded from the search results. The default limit is 2000 domains. */\n excludeDomains?: string[];\n /** Optional. Sites with confidence level chosen & above this value will be blocked from the search results. */\n blockingConfidence?: PhishBlockThreshold;\n}\n\n/** Structured representation of a function declaration as defined by the [OpenAPI 3.0 specification](https://spec.openapis.org/oas/v3.0.3). Included in this declaration are the function name, description, parameters and response type. This FunctionDeclaration is a representation of a block of code that can be used as a `Tool` by the model and executed by the client. */\nexport declare interface FunctionDeclaration {\n /** Optional. Description and purpose of the function. Model uses it to decide how and whether to call the function. */\n description?: string;\n /** Required. The name of the function to call. Must start with a letter or an underscore. Must be a-z, A-Z, 0-9, or contain underscores, dots and dashes, with a maximum length of 64. */\n name?: string;\n /** Optional. Describes the parameters to this function in JSON Schema Object format. Reflects the Open API 3.03 Parameter Object. string Key: the name of the parameter. Parameter names are case sensitive. Schema Value: the Schema defining the type used for the parameter. For function with no parameters, this can be left unset. Parameter names must start with a letter or an underscore and must only contain chars a-z, A-Z, 0-9, or underscores with a maximum length of 64. Example with 1 required and 1 optional parameter: type: OBJECT properties: param1: type: STRING param2: type: INTEGER required: - param1 */\n parameters?: Schema;\n /** Optional. Describes the parameters to the function in JSON Schema format. The schema must describe an object where the properties are the parameters to the function. For example: ``` { \"type\": \"object\", \"properties\": { \"name\": { \"type\": \"string\" }, \"age\": { \"type\": \"integer\" } }, \"additionalProperties\": false, \"required\": [\"name\", \"age\"], \"propertyOrdering\": [\"name\", \"age\"] } ``` This field is mutually exclusive with `parameters`. */\n parametersJsonSchema?: unknown;\n /** Optional. Describes the output from this function in JSON Schema format. Reflects the Open API 3.03 Response Object. The Schema defines the type used for the response value of the function. */\n response?: Schema;\n /** Optional. Describes the output from this function in JSON Schema format. The value specified by the schema is the response value of the function. This field is mutually exclusive with `response`. */\n responseJsonSchema?: unknown;\n /** Optional. Specifies the function Behavior. Currently only supported by the BidiGenerateContent method. This field is not supported in Vertex AI. */\n behavior?: Behavior;\n}\n\n/** Tool to retrieve public maps data for grounding, powered by Google. */\nexport declare interface GoogleMaps {\n /** The authentication config to access the API. Only API key is supported. This field is not supported in Gemini API. */\n authConfig?: AuthConfig;\n /** Optional. If true, include the widget context token in the response. */\n enableWidget?: boolean;\n}\n\n/** Represents a time interval, encoded as a Timestamp start (inclusive) and a Timestamp end (exclusive). The start must be less than or equal to the end. When the start equals the end, the interval is empty (matches no time). When both start and end are unspecified, the interval matches any time. */\nexport declare interface Interval {\n /** Optional. Exclusive end of the interval. If specified, a Timestamp matching this interval will have to be before the end. */\n endTime?: string;\n /** Optional. Inclusive start of the interval. If specified, a Timestamp matching this interval will have to be the same or after the start. */\n startTime?: string;\n}\n\n/** GoogleSearch tool type. Tool to support Google Search in Model. Powered by Google. */\nexport declare interface GoogleSearch {\n /** Optional. List of domains to be excluded from the search results. The default limit is 2000 domains. Example: [\"amazon.com\", \"facebook.com\"]. This field is not supported in Gemini API. */\n excludeDomains?: string[];\n /** Optional. Sites with confidence level chosen & above this value will be blocked from the search results. This field is not supported in Gemini API. */\n blockingConfidence?: PhishBlockThreshold;\n /** Optional. Filter search results to a specific time range. If customers set a start time, they must set an end time (and vice versa). This field is not supported in Vertex AI. */\n timeRangeFilter?: Interval;\n}\n\n/** Describes the options to customize dynamic retrieval. */\nexport declare interface DynamicRetrievalConfig {\n /** Optional. The threshold to be used in dynamic retrieval. If not set, a system default value is used. */\n dynamicThreshold?: number;\n /** The mode of the predictor to be used in dynamic retrieval. */\n mode?: DynamicRetrievalConfigMode;\n}\n\n/** Tool to retrieve public web data for grounding, powered by Google. */\nexport declare interface GoogleSearchRetrieval {\n /** Specifies the dynamic retrieval configuration for the given source. */\n dynamicRetrievalConfig?: DynamicRetrievalConfig;\n}\n\n/** Tool to support URL context. */\nexport declare interface UrlContext {}\n\n/** Tool details of a tool that the model may use to generate a response. */\nexport declare interface Tool {\n /** Optional. Retrieval tool type. System will always execute the provided retrieval tool(s) to get external knowledge to answer the prompt. Retrieval results are presented to the model for generation. This field is not supported in Gemini API. */\n retrieval?: Retrieval;\n /** Optional. Tool to support the model interacting directly with the\n computer. If enabled, it automatically populates computer-use specific\n Function Declarations. */\n computerUse?: ComputerUse;\n /** Optional. Tool to retrieve knowledge from the File Search Stores. */\n fileSearch?: FileSearch;\n /** Optional. CodeExecution tool type. Enables the model to execute code as part of generation. */\n codeExecution?: ToolCodeExecution;\n /** Optional. Tool to support searching public web data, powered by Vertex AI Search and Sec4 compliance. This field is not supported in Gemini API. */\n enterpriseWebSearch?: EnterpriseWebSearch;\n /** Optional. Function tool type. One or more function declarations to be passed to the model along with the current user query. Model may decide to call a subset of these functions by populating FunctionCall in the response. User should provide a FunctionResponse for each function call in the next turn. Based on the function responses, Model will generate the final response back to the user. Maximum 512 function declarations can be provided. */\n functionDeclarations?: FunctionDeclaration[];\n /** Optional. GoogleMaps tool type. Tool to support Google Maps in Model. */\n googleMaps?: GoogleMaps;\n /** Optional. GoogleSearch tool type. Tool to support Google Search in Model. Powered by Google. */\n googleSearch?: GoogleSearch;\n /** Optional. Specialized retrieval tool that is powered by Google Search. */\n googleSearchRetrieval?: GoogleSearchRetrieval;\n /** Optional. Tool to support URL context retrieval. */\n urlContext?: UrlContext;\n}\n\n/** An object that represents a latitude/longitude pair.\n\nThis is expressed as a pair of doubles to represent degrees latitude and\ndegrees longitude. Unless specified otherwise, this object must conform to the\n<a href=\"https://en.wikipedia.org/wiki/World_Geodetic_System#1984_version\">\nWGS84 standard</a>. Values must be within normalized ranges. */\nexport declare interface LatLng {\n /** The latitude in degrees. It must be in the range [-90.0, +90.0]. */\n latitude?: number;\n /** The longitude in degrees. It must be in the range [-180.0, +180.0] */\n longitude?: number;\n}\n\n/** Retrieval config.\n */\nexport declare interface RetrievalConfig {\n /** Optional. The location of the user. */\n latLng?: LatLng;\n /** The language code of the user. */\n languageCode?: string;\n}\n\n/** Function calling config. */\nexport declare interface FunctionCallingConfig {\n /** Optional. Function names to call. Only set when the Mode is ANY. Function names should match [FunctionDeclaration.name]. With mode set to ANY, model will predict a function call from the set of function names provided. */\n allowedFunctionNames?: string[];\n /** Optional. Function calling mode. */\n mode?: FunctionCallingConfigMode;\n /** Optional. When set to true, arguments of a single function call will be streamed out in multiple parts/contents/responses. Partial parameter results will be returned in the [FunctionCall.partial_args] field. This field is not supported in Gemini API. */\n streamFunctionCallArguments?: boolean;\n}\n\n/** Tool config.\n\nThis config is shared for all tools provided in the request. */\nexport declare interface ToolConfig {\n /** Optional. Retrieval config. */\n retrievalConfig?: RetrievalConfig;\n /** Optional. Function calling config. */\n functionCallingConfig?: FunctionCallingConfig;\n}\n\n/** ReplicatedVoiceConfig is used to configure replicated voice. */\nexport declare interface ReplicatedVoiceConfig {\n /** The mime type of the replicated voice.\n */\n mimeType?: string;\n /** The sample audio of the replicated voice.\n \n * @remarks Encoded as base64 string. */\n voiceSampleAudio?: string;\n}\n\n/** The configuration for the prebuilt speaker to use. */\nexport declare interface PrebuiltVoiceConfig {\n /** The name of the preset voice to use. */\n voiceName?: string;\n}\n\nexport declare interface VoiceConfig {\n /** If true, the model will use a replicated voice for the response. */\n replicatedVoiceConfig?: ReplicatedVoiceConfig;\n /** The configuration for the prebuilt voice to use. */\n prebuiltVoiceConfig?: PrebuiltVoiceConfig;\n}\n\n/** Configuration for a single speaker in a multi speaker setup. */\nexport declare interface SpeakerVoiceConfig {\n /** Required. The name of the speaker. This should be the same as the speaker name used in the prompt. */\n speaker?: string;\n /** Required. The configuration for the voice of this speaker. */\n voiceConfig?: VoiceConfig;\n}\n\n/** Configuration for a multi-speaker text-to-speech request. */\nexport declare interface MultiSpeakerVoiceConfig {\n /** Required. A list of configurations for the voices of the speakers. Exactly two speaker voice configurations must be provided. */\n speakerVoiceConfigs?: SpeakerVoiceConfig[];\n}\n\nexport declare interface SpeechConfig {\n /** Configuration for the voice of the response. */\n voiceConfig?: VoiceConfig;\n /** Optional. Language code (ISO 639. e.g. en-US) for the speech synthesization. */\n languageCode?: string;\n /** The configuration for a multi-speaker text-to-speech request. This field is mutually exclusive with `voice_config`. */\n multiSpeakerVoiceConfig?: MultiSpeakerVoiceConfig;\n}\n\n/** The configuration for automatic function calling. */\nexport declare interface AutomaticFunctionCallingConfig {\n /** Whether to disable automatic function calling.\n If not set or set to False, will enable automatic function calling.\n If set to True, will disable automatic function calling.\n */\n disable?: boolean;\n /** If automatic function calling is enabled,\n maximum number of remote calls for automatic function calling.\n This number should be a positive integer.\n If not set, SDK will set maximum number of remote calls to 10.\n */\n maximumRemoteCalls?: number;\n /** If automatic function calling is enabled,\n whether to ignore call history to the response.\n If not set, SDK will set ignore_call_history to false,\n and will append the call history to\n GenerateContentResponse.automatic_function_calling_history.\n */\n ignoreCallHistory?: boolean;\n}\n\n/** The thinking features configuration. */\nexport declare interface ThinkingConfig {\n /** Indicates whether to include thoughts in the response. If true, thoughts are returned only if the model supports thought and thoughts are available.\n */\n includeThoughts?: boolean;\n /** Indicates the thinking budget in tokens. 0 is DISABLED. -1 is AUTOMATIC. The default values and allowed ranges are model dependent.\n */\n thinkingBudget?: number;\n /** Optional. The number of thoughts tokens that the model should generate. */\n thinkingLevel?: ThinkingLevel;\n}\n\n/** The image generation configuration to be used in GenerateContentConfig. */\nexport declare interface ImageConfig {\n /** Aspect ratio of the generated images. Supported values are\n \"1:1\", \"2:3\", \"3:2\", \"3:4\", \"4:3\", \"9:16\", \"16:9\", and \"21:9\". */\n aspectRatio?: string;\n /** Optional. Specifies the size of generated images. Supported\n values are `1K`, `2K`, `4K`. If not specified, the model will use default\n value `1K`. */\n imageSize?: string;\n /** Controls the generation of people. Supported values are:\n ALLOW_ALL, ALLOW_ADULT, ALLOW_NONE. */\n personGeneration?: string;\n /** MIME type of the generated image. This field is not\n supported in Gemini API. */\n outputMimeType?: string;\n /** Compression quality of the generated image (for\n ``image/jpeg`` only). This field is not supported in Gemini API. */\n outputCompressionQuality?: number;\n}\n\n/** When automated routing is specified, the routing will be determined by the pretrained routing model and customer provided model routing preference. This data type is not supported in Gemini API. */\nexport declare interface GenerationConfigRoutingConfigAutoRoutingMode {\n /** The model routing preference. */\n modelRoutingPreference?:\n | 'UNKNOWN'\n | 'PRIORITIZE_QUALITY'\n | 'BALANCED'\n | 'PRIORITIZE_COST';\n}\n\n/** When manual routing is set, the specified model will be used directly. This data type is not supported in Gemini API. */\nexport declare interface GenerationConfigRoutingConfigManualRoutingMode {\n /** The model name to use. Only the public LLM models are accepted. See [Supported models](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference#supported-models). */\n modelName?: string;\n}\n\n/** The configuration for routing the request to a specific model. This data type is not supported in Gemini API. */\nexport declare interface GenerationConfigRoutingConfig {\n /** Automated routing. */\n autoMode?: GenerationConfigRoutingConfigAutoRoutingMode;\n /** Manual routing. */\n manualMode?: GenerationConfigRoutingConfigManualRoutingMode;\n}\n\n/** Safety settings. */\nexport declare interface SafetySetting {\n /** Required. Harm category. */\n category?: HarmCategory;\n /** Optional. Specify if the threshold is used for probability or severity score. If not specified, the threshold is used for probability score. This field is not supported in Gemini API. */\n method?: HarmBlockMethod;\n /** Required. The harm block threshold. */\n threshold?: HarmBlockThreshold;\n}\n\n/** Configuration for Model Armor integrations of prompt and responses. This data type is not supported in Gemini API. */\nexport declare interface ModelArmorConfig {\n /** Optional. The name of the Model Armor template to use for prompt sanitization. */\n promptTemplateName?: string;\n /** Optional. The name of the Model Armor template to use for response sanitization. */\n responseTemplateName?: string;\n}\n\n/** Optional model configuration parameters.\n\nFor more information, see `Content generation parameters\n<https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/content-generation-parameters>`_. */\nexport declare interface GenerateContentConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** Instructions for the model to steer it toward better performance.\n For example, \"Answer as concisely as possible\" or \"Don't use technical\n terms in your response\".\n */\n systemInstruction?: ContentUnion;\n /** Value that controls the degree of randomness in token selection.\n Lower temperatures are good for prompts that require a less open-ended or\n creative response, while higher temperatures can lead to more diverse or\n creative results.\n */\n temperature?: number;\n /** Tokens are selected from the most to least probable until the sum\n of their probabilities equals this value. Use a lower value for less\n random responses and a higher value for more random responses.\n */\n topP?: number;\n /** For each token selection step, the ``top_k`` tokens with the\n highest probabilities are sampled. Then tokens are further filtered based\n on ``top_p`` with the final token selected using temperature sampling. Use\n a lower number for less random responses and a higher number for more\n random responses.\n */\n topK?: number;\n /** Number of response variations to return.\n */\n candidateCount?: number;\n /** Maximum number of tokens that can be generated in the response.\n */\n maxOutputTokens?: number;\n /** List of strings that tells the model to stop generating text if one\n of the strings is encountered in the response.\n */\n stopSequences?: string[];\n /** Whether to return the log probabilities of the tokens that were\n chosen by the model at each step.\n */\n responseLogprobs?: boolean;\n /** Number of top candidate tokens to return the log probabilities for\n at each generation step.\n */\n logprobs?: number;\n /** Positive values penalize tokens that already appear in the\n generated text, increasing the probability of generating more diverse\n content.\n */\n presencePenalty?: number;\n /** Positive values penalize tokens that repeatedly appear in the\n generated text, increasing the probability of generating more diverse\n content.\n */\n frequencyPenalty?: number;\n /** When ``seed`` is fixed to a specific number, the model makes a best\n effort to provide the same response for repeated requests. By default, a\n random number is used.\n */\n seed?: number;\n /** Output response mimetype of the generated candidate text.\n Supported mimetype:\n - `text/plain`: (default) Text output.\n - `application/json`: JSON response in the candidates.\n The model needs to be prompted to output the appropriate response type,\n otherwise the behavior is undefined.\n This is a preview feature.\n */\n responseMimeType?: string;\n /** The `Schema` object allows the definition of input and output data types.\n These types can be objects, but also primitives and arrays.\n Represents a select subset of an [OpenAPI 3.0 schema\n object](https://spec.openapis.org/oas/v3.0.3#schema).\n If set, a compatible response_mime_type must also be set.\n Compatible mimetypes: `application/json`: Schema for JSON response.\n\n If `response_schema` doesn't process your schema correctly, try using\n `response_json_schema` instead.\n */\n responseSchema?: SchemaUnion;\n /** Optional. Output schema of the generated response.\n This is an alternative to `response_schema` that accepts [JSON\n Schema](https://json-schema.org/). If set, `response_schema` must be\n omitted, but `response_mime_type` is required. While the full JSON Schema\n may be sent, not all features are supported. Specifically, only the\n following properties are supported: - `$id` - `$defs` - `$ref` - `$anchor`\n - `type` - `format` - `title` - `description` - `enum` (for strings and\n numbers) - `items` - `prefixItems` - `minItems` - `maxItems` - `minimum` -\n `maximum` - `anyOf` - `oneOf` (interpreted the same as `anyOf`) -\n `properties` - `additionalProperties` - `required` The non-standard\n `propertyOrdering` property may also be set. Cyclic references are\n unrolled to a limited degree and, as such, may only be used within\n non-required properties. (Nullable properties are not sufficient.) If\n `$ref` is set on a sub-schema, no other properties, except for than those\n starting as a `$`, may be set. */\n responseJsonSchema?: unknown;\n /** Configuration for model router requests.\n */\n routingConfig?: GenerationConfigRoutingConfig;\n /** Configuration for model selection.\n */\n modelSelectionConfig?: ModelSelectionConfig;\n /** Safety settings in the request to block unsafe content in the\n response.\n */\n safetySettings?: SafetySetting[];\n /** Code that enables the system to interact with external systems to\n perform an action outside of the knowledge and scope of the model.\n */\n tools?: ToolListUnion;\n /** Associates model output to a specific function call.\n */\n toolConfig?: ToolConfig;\n /** Labels with user-defined metadata to break down billed charges. */\n labels?: Record<string, string>;\n /** Resource name of a context cache that can be used in subsequent\n requests.\n */\n cachedContent?: string;\n /** The requested modalities of the response. Represents the set of\n modalities that the model can return.\n */\n responseModalities?: string[];\n /** If specified, the media resolution specified will be used.\n */\n mediaResolution?: MediaResolution;\n /** The speech generation configuration.\n */\n speechConfig?: SpeechConfigUnion;\n /** If enabled, audio timestamp will be included in the request to the\n model.\n */\n audioTimestamp?: boolean;\n /** The configuration for automatic function calling.\n */\n automaticFunctionCalling?: AutomaticFunctionCallingConfig;\n /** The thinking features configuration.\n */\n thinkingConfig?: ThinkingConfig;\n /** The image generation configuration.\n */\n imageConfig?: ImageConfig;\n /** Enables enhanced civic answers. It may not be available for all\n models. This field is not supported in Vertex AI.\n */\n enableEnhancedCivicAnswers?: boolean;\n /** Settings for prompt and response sanitization using the Model Armor\n service. If supplied, safety_settings must not be supplied.\n */\n modelArmorConfig?: ModelArmorConfig;\n}\n\n/** Config for models.generate_content parameters. */\nexport declare interface GenerateContentParameters {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model: string;\n /** Content of the request.\n */\n contents: ContentListUnion;\n /** Configuration that contains optional model parameters.\n */\n config?: GenerateContentConfig;\n}\n\n/** A wrapper class for the http response. */\nexport class HttpResponse {\n /** Used to retain the processed HTTP headers in the response. */\n headers?: Record<string, string>;\n /**\n * The original http response.\n */\n responseInternal: Response;\n\n constructor(response: Response) {\n // Process the headers.\n const headers: Record<string, string> = {};\n for (const pair of response.headers.entries()) {\n headers[pair[0]] = pair[1];\n }\n this.headers = headers;\n\n // Keep the original response.\n this.responseInternal = response;\n }\n\n json(): Promise<unknown> {\n return this.responseInternal.json();\n }\n}\n\n/** Callbacks for the live API. */\nexport interface LiveCallbacks {\n /**\n * Called when the websocket connection is established.\n */\n onopen?: (() => void) | null;\n /**\n * Called when a message is received from the server.\n */\n onmessage: (e: LiveServerMessage) => void;\n /**\n * Called when an error occurs.\n */\n onerror?: ((e: ErrorEvent) => void) | null;\n /**\n * Called when the websocket connection is closed.\n */\n onclose?: ((e: CloseEvent) => void) | null;\n}\n\n/** Represents a whole or partial calendar date, such as a birthday. The time of day and time zone are either specified elsewhere or are insignificant. The date is relative to the Gregorian Calendar. This can represent one of the following: * A full date, with non-zero year, month, and day values. * A month and day, with a zero year (for example, an anniversary). * A year on its own, with a zero month and a zero day. * A year and month, with a zero day (for example, a credit card expiration date). Related types: * google.type.TimeOfDay * google.type.DateTime * google.protobuf.Timestamp. This data type is not supported in Gemini API. */\nexport declare interface GoogleTypeDate {\n /** Day of a month. Must be from 1 to 31 and valid for the year and month, or 0 to specify a year by itself or a year and month where the day isn't significant. */\n day?: number;\n /** Month of a year. Must be from 1 to 12, or 0 to specify a year without a month and day. */\n month?: number;\n /** Year of the date. Must be from 1 to 9999, or 0 to specify a date without a year. */\n year?: number;\n}\n\n/** Source attributions for content. This data type is not supported in Gemini API. */\nexport declare interface Citation {\n /** Output only. End index into the content. */\n endIndex?: number;\n /** Output only. License of the attribution. */\n license?: string;\n /** Output only. Publication date of the attribution. */\n publicationDate?: GoogleTypeDate;\n /** Output only. Start index into the content. */\n startIndex?: number;\n /** Output only. Title of the attribution. */\n title?: string;\n /** Output only. Url reference of the attribution. */\n uri?: string;\n}\n\n/** Citation information when the model quotes another source. */\nexport declare interface CitationMetadata {\n /** Contains citation information when the model directly quotes, at\n length, from another source. Can include traditional websites and code\n repositories.\n */\n citations?: Citation[];\n}\n\n/** Author attribution for a photo or review. This data type is not supported in Gemini API. */\nexport declare interface GroundingChunkMapsPlaceAnswerSourcesAuthorAttribution {\n /** Name of the author of the Photo or Review. */\n displayName?: string;\n /** Profile photo URI of the author of the Photo or Review. */\n photoUri?: string;\n /** URI of the author of the Photo or Review. */\n uri?: string;\n}\n\n/** Encapsulates a review snippet. This data type is not supported in Gemini API. */\nexport declare interface GroundingChunkMapsPlaceAnswerSourcesReviewSnippet {\n /** This review's author. */\n authorAttribution?: GroundingChunkMapsPlaceAnswerSourcesAuthorAttribution;\n /** A link where users can flag a problem with the review. */\n flagContentUri?: string;\n /** A link to show the review on Google Maps. */\n googleMapsUri?: string;\n /** A string of formatted recent time, expressing the review time relative to the current time in a form appropriate for the language and country. */\n relativePublishTimeDescription?: string;\n /** A reference representing this place review which may be used to look up this place review again. */\n review?: string;\n /** Id of the review referencing the place. */\n reviewId?: string;\n /** Title of the review. */\n title?: string;\n}\n\n/** Sources used to generate the place answer. This data type is not supported in Gemini API. */\nexport declare interface GroundingChunkMapsPlaceAnswerSources {\n /** A link where users can flag a problem with the generated answer. */\n flagContentUri?: string;\n /** Snippets of reviews that are used to generate the answer. */\n reviewSnippets?: GroundingChunkMapsPlaceAnswerSourcesReviewSnippet[];\n}\n\n/** Chunk from Google Maps. This data type is not supported in Gemini API. */\nexport declare interface GroundingChunkMaps {\n /** Sources used to generate the place answer. This includes review snippets and photos that were used to generate the answer, as well as uris to flag content. */\n placeAnswerSources?: GroundingChunkMapsPlaceAnswerSources;\n /** This Place's resource name, in `places/{place_id}` format. Can be used to look up the Place. */\n placeId?: string;\n /** Text of the place answer. */\n text?: string;\n /** Title of the place. */\n title?: string;\n /** URI reference of the place. */\n uri?: string;\n}\n\n/** Represents where the chunk starts and ends in the document. This data type is not supported in Gemini API. */\nexport declare interface RagChunkPageSpan {\n /** Page where chunk starts in the document. Inclusive. 1-indexed. */\n firstPage?: number;\n /** Page where chunk ends in the document. Inclusive. 1-indexed. */\n lastPage?: number;\n}\n\n/** A RagChunk includes the content of a chunk of a RagFile, and associated metadata. This data type is not supported in Gemini API. */\nexport declare interface RagChunk {\n /** If populated, represents where the chunk starts and ends in the document. */\n pageSpan?: RagChunkPageSpan;\n /** The content of the chunk. */\n text?: string;\n}\n\n/** Chunk from context retrieved by the retrieval tools. This data type is not supported in Gemini API. */\nexport declare interface GroundingChunkRetrievedContext {\n /** Output only. The full document name for the referenced Vertex AI Search document. */\n documentName?: string;\n /** Additional context for the RAG retrieval result. This is only populated when using the RAG retrieval tool. */\n ragChunk?: RagChunk;\n /** Text of the attribution. */\n text?: string;\n /** Title of the attribution. */\n title?: string;\n /** URI reference of the attribution. */\n uri?: string;\n}\n\n/** Chunk from the web. */\nexport declare interface GroundingChunkWeb {\n /** Domain of the (original) URI. This field is not supported in Gemini API. */\n domain?: string;\n /** Title of the chunk. */\n title?: string;\n /** URI reference of the chunk. */\n uri?: string;\n}\n\n/** Grounding chunk. */\nexport declare interface GroundingChunk {\n /** Grounding chunk from Google Maps. This field is not supported in Gemini API. */\n maps?: GroundingChunkMaps;\n /** Grounding chunk from context retrieved by the retrieval tools. This field is not supported in Gemini API. */\n retrievedContext?: GroundingChunkRetrievedContext;\n /** Grounding chunk from the web. */\n web?: GroundingChunkWeb;\n}\n\n/** Segment of the content. */\nexport declare interface Segment {\n /** Output only. End index in the given Part, measured in bytes. Offset from the start of the Part, exclusive, starting at zero. */\n endIndex?: number;\n /** Output only. The index of a Part object within its parent Content object. */\n partIndex?: number;\n /** Output only. Start index in the given Part, measured in bytes. Offset from the start of the Part, inclusive, starting at zero. */\n startIndex?: number;\n /** Output only. The text corresponding to the segment from the response. */\n text?: string;\n}\n\n/** Grounding support. */\nexport declare interface GroundingSupport {\n /** Confidence score of the support references. Ranges from 0 to 1. 1 is the most confident. For Gemini 2.0 and before, this list must have the same size as the grounding_chunk_indices. For Gemini 2.5 and after, this list will be empty and should be ignored. */\n confidenceScores?: number[];\n /** A list of indices (into 'grounding_chunk') specifying the citations associated with the claim. For instance [1,3,4] means that grounding_chunk[1], grounding_chunk[3], grounding_chunk[4] are the retrieved content attributed to the claim. */\n groundingChunkIndices?: number[];\n /** Segment of the content this support belongs to. */\n segment?: Segment;\n}\n\n/** Metadata related to retrieval in the grounding flow. */\nexport declare interface RetrievalMetadata {\n /** Optional. Score indicating how likely information from Google Search could help answer the prompt. The score is in the range `[0, 1]`, where 0 is the least likely and 1 is the most likely. This score is only populated when Google Search grounding and dynamic retrieval is enabled. It will be compared to the threshold to determine whether to trigger Google Search. */\n googleSearchDynamicRetrievalScore?: number;\n}\n\n/** Google search entry point. */\nexport declare interface SearchEntryPoint {\n /** Optional. Web content snippet that can be embedded in a web page or an app webview. */\n renderedContent?: string;\n /** Optional. Base64 encoded JSON representing array of tuple.\n * @remarks Encoded as base64 string. */\n sdkBlob?: string;\n}\n\n/** Source content flagging uri for a place or review. This is currently populated only for Google Maps grounding. This data type is not supported in Gemini API. */\nexport declare interface GroundingMetadataSourceFlaggingUri {\n /** A link where users can flag a problem with the source (place or review). */\n flagContentUri?: string;\n /** Id of the place or review. */\n sourceId?: string;\n}\n\n/** Metadata returned to client when grounding is enabled. */\nexport declare interface GroundingMetadata {\n /** Optional. Output only. Resource name of the Google Maps widget context token to be used with the PlacesContextElement widget to render contextual data. This is populated only for Google Maps grounding. This field is not supported in Gemini API. */\n googleMapsWidgetContextToken?: string;\n /** List of supporting references retrieved from specified grounding source. */\n groundingChunks?: GroundingChunk[];\n /** Optional. List of grounding support. */\n groundingSupports?: GroundingSupport[];\n /** Optional. Output only. Retrieval metadata. */\n retrievalMetadata?: RetrievalMetadata;\n /** Optional. Queries executed by the retrieval tools. This field is not supported in Gemini API. */\n retrievalQueries?: string[];\n /** Optional. Google search entry for the following-up web searches. */\n searchEntryPoint?: SearchEntryPoint;\n /** Optional. Output only. List of source flagging uris. This is currently populated only for Google Maps grounding. This field is not supported in Gemini API. */\n sourceFlaggingUris?: GroundingMetadataSourceFlaggingUri[];\n /** Optional. Web search queries for the following-up web search. */\n webSearchQueries?: string[];\n}\n\n/** Candidate for the logprobs token and score. */\nexport declare interface LogprobsResultCandidate {\n /** The candidate's log probability. */\n logProbability?: number;\n /** The candidate's token string value. */\n token?: string;\n /** The candidate's token id value. */\n tokenId?: number;\n}\n\n/** Candidates with top log probabilities at each decoding step. */\nexport declare interface LogprobsResultTopCandidates {\n /** Sorted by log probability in descending order. */\n candidates?: LogprobsResultCandidate[];\n}\n\n/** Logprobs Result */\nexport declare interface LogprobsResult {\n /** Length = total number of decoding steps. The chosen candidates may or may not be in top_candidates. */\n chosenCandidates?: LogprobsResultCandidate[];\n /** Length = total number of decoding steps. */\n topCandidates?: LogprobsResultTopCandidates[];\n}\n\n/** Safety rating corresponding to the generated content. */\nexport declare interface SafetyRating {\n /** Output only. Indicates whether the content was filtered out because of this rating. */\n blocked?: boolean;\n /** Output only. Harm category. */\n category?: HarmCategory;\n /** Output only. The overwritten threshold for the safety category of Gemini 2.0 image out. If minors are detected in the output image, the threshold of each safety category will be overwritten if user sets a lower threshold. This field is not supported in Gemini API. */\n overwrittenThreshold?: HarmBlockThreshold;\n /** Output only. Harm probability levels in the content. */\n probability?: HarmProbability;\n /** Output only. Harm probability score. This field is not supported in Gemini API. */\n probabilityScore?: number;\n /** Output only. Harm severity levels in the content. This field is not supported in Gemini API. */\n severity?: HarmSeverity;\n /** Output only. Harm severity score. This field is not supported in Gemini API. */\n severityScore?: number;\n}\n\n/** Context of the a single url retrieval. */\nexport declare interface UrlMetadata {\n /** Retrieved url by the tool. */\n retrievedUrl?: string;\n /** Status of the url retrieval. */\n urlRetrievalStatus?: UrlRetrievalStatus;\n}\n\n/** Metadata related to url context retrieval tool. */\nexport declare interface UrlContextMetadata {\n /** Output only. List of url context. */\n urlMetadata?: UrlMetadata[];\n}\n\n/** A response candidate generated from the model. */\nexport declare interface Candidate {\n /** Contains the multi-part content of the response.\n */\n content?: Content;\n /** Source attribution of the generated content.\n */\n citationMetadata?: CitationMetadata;\n /** Describes the reason the model stopped generating tokens.\n */\n finishMessage?: string;\n /** Number of tokens for this candidate.\n */\n tokenCount?: number;\n /** The reason why the model stopped generating tokens.\n If empty, the model has not stopped generating the tokens.\n */\n finishReason?: FinishReason;\n /** Output only. Average log probability score of the candidate. */\n avgLogprobs?: number;\n /** Output only. Metadata specifies sources used to ground generated content. */\n groundingMetadata?: GroundingMetadata;\n /** Output only. Index of the candidate. */\n index?: number;\n /** Output only. Log-likelihood scores for the response tokens and top tokens */\n logprobsResult?: LogprobsResult;\n /** Output only. List of ratings for the safety of a response candidate. There is at most one rating per category. */\n safetyRatings?: SafetyRating[];\n /** Output only. Metadata related to url context retrieval tool. */\n urlContextMetadata?: UrlContextMetadata;\n}\n\n/** Content filter results for a prompt sent in the request. Note: This is sent only in the first stream chunk and only if no candidates were generated due to content violations. */\nexport class GenerateContentResponsePromptFeedback {\n /** Output only. The reason why the prompt was blocked. */\n blockReason?: BlockedReason;\n /** Output only. A readable message that explains the reason why the prompt was blocked. This field is not supported in Gemini API. */\n blockReasonMessage?: string;\n /** Output only. A list of safety ratings for the prompt. There is one rating per category. */\n safetyRatings?: SafetyRating[];\n}\n\n/** Represents token counting info for a single modality. */\nexport declare interface ModalityTokenCount {\n /** The modality associated with this token count. */\n modality?: MediaModality;\n /** Number of tokens. */\n tokenCount?: number;\n}\n\n/** Usage metadata about the content generation request and response. This message provides a detailed breakdown of token usage and other relevant metrics. This data type is not supported in Gemini API. */\nexport class GenerateContentResponseUsageMetadata {\n /** Output only. A detailed breakdown of the token count for each modality in the cached content. */\n cacheTokensDetails?: ModalityTokenCount[];\n /** Output only. The number of tokens in the cached content that was used for this request. */\n cachedContentTokenCount?: number;\n /** The total number of tokens in the generated candidates. */\n candidatesTokenCount?: number;\n /** Output only. A detailed breakdown of the token count for each modality in the generated candidates. */\n candidatesTokensDetails?: ModalityTokenCount[];\n /** The total number of tokens in the prompt. This includes any text, images, or other media provided in the request. When `cached_content` is set, this also includes the number of tokens in the cached content. */\n promptTokenCount?: number;\n /** Output only. A detailed breakdown of the token count for each modality in the prompt. */\n promptTokensDetails?: ModalityTokenCount[];\n /** Output only. The number of tokens that were part of the model's generated \"thoughts\" output, if applicable. */\n thoughtsTokenCount?: number;\n /** Output only. The number of tokens in the results from tool executions, which are provided back to the model as input, if applicable. */\n toolUsePromptTokenCount?: number;\n /** Output only. A detailed breakdown by modality of the token counts from the results of tool executions, which are provided back to the model as input. */\n toolUsePromptTokensDetails?: ModalityTokenCount[];\n /** The total number of tokens for the entire request. This is the sum of `prompt_token_count`, `candidates_token_count`, `tool_use_prompt_token_count`, and `thoughts_token_count`. */\n totalTokenCount?: number;\n /** Output only. The traffic type for this request. */\n trafficType?: TrafficType;\n}\n\n/** Response message for PredictionService.GenerateContent. */\nexport class GenerateContentResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** Response variations returned by the model.\n */\n candidates?: Candidate[];\n /** Timestamp when the request is made to the server.\n */\n createTime?: string;\n /** The history of automatic function calling.\n */\n automaticFunctionCallingHistory?: Content[];\n /** Output only. The model version used to generate the response. */\n modelVersion?: string;\n /** Output only. Content filter results for a prompt sent in the request. Note: Sent only in the first stream chunk. Only happens when no candidates were generated due to content violations. */\n promptFeedback?: GenerateContentResponsePromptFeedback;\n /** Output only. response_id is used to identify each response. It is the encoding of the event_id. */\n responseId?: string;\n /** Usage metadata about the response(s). */\n usageMetadata?: GenerateContentResponseUsageMetadata;\n /**\n * Returns the concatenation of all text parts from the first candidate in the response.\n *\n * @remarks\n * If there are multiple candidates in the response, the text from the first\n * one will be returned.\n * If there are non-text parts in the response, the concatenation of all text\n * parts will be returned, and a warning will be logged.\n * If there are thought parts in the response, the concatenation of all text\n * parts excluding the thought parts will be returned.\n *\n * @example\n * ```ts\n * const response = await ai.models.generateContent({\n * model: 'gemini-2.0-flash',\n * contents:\n * 'Why is the sky blue?',\n * });\n *\n * console.debug(response.text);\n * ```\n */\n get text(): string | undefined {\n if (this.candidates?.[0]?.content?.parts?.length === 0) {\n return undefined;\n }\n if (this.candidates && this.candidates.length > 1) {\n console.warn(\n 'there are multiple candidates in the response, returning text from the first one.',\n );\n }\n let text = '';\n let anyTextPartText = false;\n const nonTextParts = [];\n for (const part of this.candidates?.[0]?.content?.parts ?? []) {\n for (const [fieldName, fieldValue] of Object.entries(part)) {\n if (\n fieldName !== 'text' &&\n fieldName !== 'thought' &&\n fieldName !== 'thoughtSignature' &&\n (fieldValue !== null || fieldValue !== undefined)\n ) {\n nonTextParts.push(fieldName);\n }\n }\n if (typeof part.text === 'string') {\n if (typeof part.thought === 'boolean' && part.thought) {\n continue;\n }\n anyTextPartText = true;\n text += part.text;\n }\n }\n if (nonTextParts.length > 0) {\n console.warn(\n `there are non-text parts ${nonTextParts} in the response, returning concatenation of all text parts. Please refer to the non text parts for a full response from model.`,\n );\n }\n // part.text === '' is different from part.text is null\n return anyTextPartText ? text : undefined;\n }\n\n /**\n * Returns the concatenation of all inline data parts from the first candidate\n * in the response.\n *\n * @remarks\n * If there are multiple candidates in the response, the inline data from the\n * first one will be returned. If there are non-inline data parts in the\n * response, the concatenation of all inline data parts will be returned, and\n * a warning will be logged.\n */\n get data(): string | undefined {\n if (this.candidates?.[0]?.content?.parts?.length === 0) {\n return undefined;\n }\n if (this.candidates && this.candidates.length > 1) {\n console.warn(\n 'there are multiple candidates in the response, returning data from the first one.',\n );\n }\n let data = '';\n const nonDataParts = [];\n for (const part of this.candidates?.[0]?.content?.parts ?? []) {\n for (const [fieldName, fieldValue] of Object.entries(part)) {\n if (\n fieldName !== 'inlineData' &&\n (fieldValue !== null || fieldValue !== undefined)\n ) {\n nonDataParts.push(fieldName);\n }\n }\n if (part.inlineData && typeof part.inlineData.data === 'string') {\n data += atob(part.inlineData.data);\n }\n }\n if (nonDataParts.length > 0) {\n console.warn(\n `there are non-data parts ${nonDataParts} in the response, returning concatenation of all data parts. Please refer to the non data parts for a full response from model.`,\n );\n }\n return data.length > 0 ? btoa(data) : undefined;\n }\n\n /**\n * Returns the function calls from the first candidate in the response.\n *\n * @remarks\n * If there are multiple candidates in the response, the function calls from\n * the first one will be returned.\n * If there are no function calls in the response, undefined will be returned.\n *\n * @example\n * ```ts\n * const controlLightFunctionDeclaration: FunctionDeclaration = {\n * name: 'controlLight',\n * parameters: {\n * type: Type.OBJECT,\n * description: 'Set the brightness and color temperature of a room light.',\n * properties: {\n * brightness: {\n * type: Type.NUMBER,\n * description:\n * 'Light level from 0 to 100. Zero is off and 100 is full brightness.',\n * },\n * colorTemperature: {\n * type: Type.STRING,\n * description:\n * 'Color temperature of the light fixture which can be `daylight`, `cool` or `warm`.',\n * },\n * },\n * required: ['brightness', 'colorTemperature'],\n * };\n * const response = await ai.models.generateContent({\n * model: 'gemini-2.0-flash',\n * contents: 'Dim the lights so the room feels cozy and warm.',\n * config: {\n * tools: [{functionDeclarations: [controlLightFunctionDeclaration]}],\n * toolConfig: {\n * functionCallingConfig: {\n * mode: FunctionCallingConfigMode.ANY,\n * allowedFunctionNames: ['controlLight'],\n * },\n * },\n * },\n * });\n * console.debug(JSON.stringify(response.functionCalls));\n * ```\n */\n get functionCalls(): FunctionCall[] | undefined {\n if (this.candidates?.[0]?.content?.parts?.length === 0) {\n return undefined;\n }\n if (this.candidates && this.candidates.length > 1) {\n console.warn(\n 'there are multiple candidates in the response, returning function calls from the first one.',\n );\n }\n const functionCalls = this.candidates?.[0]?.content?.parts\n ?.filter((part) => part.functionCall)\n .map((part) => part.functionCall)\n .filter(\n (functionCall): functionCall is FunctionCall =>\n functionCall !== undefined,\n );\n if (functionCalls?.length === 0) {\n return undefined;\n }\n return functionCalls;\n }\n /**\n * Returns the first executable code from the first candidate in the response.\n *\n * @remarks\n * If there are multiple candidates in the response, the executable code from\n * the first one will be returned.\n * If there are no executable code in the response, undefined will be\n * returned.\n *\n * @example\n * ```ts\n * const response = await ai.models.generateContent({\n * model: 'gemini-2.0-flash',\n * contents:\n * 'What is the sum of the first 50 prime numbers? Generate and run code for the calculation, and make sure you get all 50.'\n * config: {\n * tools: [{codeExecution: {}}],\n * },\n * });\n *\n * console.debug(response.executableCode);\n * ```\n */\n get executableCode(): string | undefined {\n if (this.candidates?.[0]?.content?.parts?.length === 0) {\n return undefined;\n }\n if (this.candidates && this.candidates.length > 1) {\n console.warn(\n 'there are multiple candidates in the response, returning executable code from the first one.',\n );\n }\n const executableCode = this.candidates?.[0]?.content?.parts\n ?.filter((part) => part.executableCode)\n .map((part) => part.executableCode)\n .filter(\n (executableCode): executableCode is ExecutableCode =>\n executableCode !== undefined,\n );\n if (executableCode?.length === 0) {\n return undefined;\n }\n\n return executableCode?.[0]?.code;\n }\n /**\n * Returns the first code execution result from the first candidate in the response.\n *\n * @remarks\n * If there are multiple candidates in the response, the code execution result from\n * the first one will be returned.\n * If there are no code execution result in the response, undefined will be returned.\n *\n * @example\n * ```ts\n * const response = await ai.models.generateContent({\n * model: 'gemini-2.0-flash',\n * contents:\n * 'What is the sum of the first 50 prime numbers? Generate and run code for the calculation, and make sure you get all 50.'\n * config: {\n * tools: [{codeExecution: {}}],\n * },\n * });\n *\n * console.debug(response.codeExecutionResult);\n * ```\n */\n get codeExecutionResult(): string | undefined {\n if (this.candidates?.[0]?.content?.parts?.length === 0) {\n return undefined;\n }\n if (this.candidates && this.candidates.length > 1) {\n console.warn(\n 'there are multiple candidates in the response, returning code execution result from the first one.',\n );\n }\n const codeExecutionResult = this.candidates?.[0]?.content?.parts\n ?.filter((part) => part.codeExecutionResult)\n .map((part) => part.codeExecutionResult)\n .filter(\n (codeExecutionResult): codeExecutionResult is CodeExecutionResult =>\n codeExecutionResult !== undefined,\n );\n if (codeExecutionResult?.length === 0) {\n return undefined;\n }\n return codeExecutionResult?.[0]?.output;\n }\n}\n\nexport type ReferenceImage =\n | RawReferenceImage\n | MaskReferenceImage\n | ControlReferenceImage\n | StyleReferenceImage\n | SubjectReferenceImage\n | ContentReferenceImage;\n\n/** Parameters for the request to edit an image. */\nexport declare interface EditImageParameters {\n /** The model to use. */\n model: string;\n /** A text description of the edit to apply to the image. */\n prompt: string;\n /** The reference images for Imagen 3 editing. */\n referenceImages: ReferenceImage[];\n /** Configuration for editing. */\n config?: EditImageConfig;\n}\n\n/** Optional parameters for the embed_content method. */\nexport declare interface EmbedContentConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** Type of task for which the embedding will be used.\n */\n taskType?: string;\n /** Title for the text. Only applicable when TaskType is\n `RETRIEVAL_DOCUMENT`.\n */\n title?: string;\n /** Reduced dimension for the output embedding. If set,\n excessive values in the output embedding are truncated from the end.\n Supported by newer models since 2024 only. You cannot set this value if\n using the earlier model (`models/embedding-001`).\n */\n outputDimensionality?: number;\n /** Vertex API only. The MIME type of the input.\n */\n mimeType?: string;\n /** Vertex API only. Whether to silently truncate inputs longer than\n the max sequence length. If this option is set to false, oversized inputs\n will lead to an INVALID_ARGUMENT error, similar to other text APIs.\n */\n autoTruncate?: boolean;\n}\n\n/** Parameters for the embed_content method. */\nexport declare interface EmbedContentParameters {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model: string;\n /** The content to embed. Only the `parts.text` fields will be counted.\n */\n contents: ContentListUnion;\n /** Configuration that contains optional parameters.\n */\n config?: EmbedContentConfig;\n}\n\n/** Statistics of the input text associated with the result of content embedding. */\nexport declare interface ContentEmbeddingStatistics {\n /** Vertex API only. If the input text was truncated due to having\n a length longer than the allowed maximum input.\n */\n truncated?: boolean;\n /** Vertex API only. Number of tokens of the input text.\n */\n tokenCount?: number;\n}\n\n/** The embedding generated from an input content. */\nexport declare interface ContentEmbedding {\n /** A list of floats representing an embedding.\n */\n values?: number[];\n /** Vertex API only. Statistics of the input text associated with this\n embedding.\n */\n statistics?: ContentEmbeddingStatistics;\n}\n\n/** Request-level metadata for the Vertex Embed Content API. */\nexport declare interface EmbedContentMetadata {\n /** Vertex API only. The total number of billable characters included\n in the request.\n */\n billableCharacterCount?: number;\n}\n\n/** Response for the embed_content method. */\nexport class EmbedContentResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** The embeddings for each request, in the same order as provided in\n the batch request.\n */\n embeddings?: ContentEmbedding[];\n /** Vertex API only. Metadata about the request.\n */\n metadata?: EmbedContentMetadata;\n}\n\n/** The config for generating an images. */\nexport declare interface GenerateImagesConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** Cloud Storage URI used to store the generated images. */\n outputGcsUri?: string;\n /** Description of what to discourage in the generated images. */\n negativePrompt?: string;\n /** Number of images to generate. */\n numberOfImages?: number;\n /** Aspect ratio of the generated images. Supported values are\n \"1:1\", \"3:4\", \"4:3\", \"9:16\", and \"16:9\". */\n aspectRatio?: string;\n /** Controls how much the model adheres to the text prompt. Large\n values increase output and prompt alignment, but may compromise image\n quality. */\n guidanceScale?: number;\n /** Random seed for image generation. This is not available when\n ``add_watermark`` is set to true. */\n seed?: number;\n /** Filter level for safety filtering. */\n safetyFilterLevel?: SafetyFilterLevel;\n /** Allows generation of people by the model. */\n personGeneration?: PersonGeneration;\n /** Whether to report the safety scores of each generated image and\n the positive prompt in the response. */\n includeSafetyAttributes?: boolean;\n /** Whether to include the Responsible AI filter reason if the image\n is filtered out of the response. */\n includeRaiReason?: boolean;\n /** Language of the text in the prompt. */\n language?: ImagePromptLanguage;\n /** MIME type of the generated image. */\n outputMimeType?: string;\n /** Compression quality of the generated image (for ``image/jpeg``\n only). */\n outputCompressionQuality?: number;\n /** Whether to add a watermark to the generated images. */\n addWatermark?: boolean;\n /** User specified labels to track billing usage. */\n labels?: Record<string, string>;\n /** The size of the largest dimension of the generated image.\n Supported sizes are 1K and 2K (not supported for Imagen 3 models). */\n imageSize?: string;\n /** Whether to use the prompt rewriting logic. */\n enhancePrompt?: boolean;\n}\n\n/** The parameters for generating images. */\nexport declare interface GenerateImagesParameters {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model: string;\n /** Text prompt that typically describes the images to output.\n */\n prompt: string;\n /** Configuration for generating images.\n */\n config?: GenerateImagesConfig;\n}\n\n/** An image. */\nexport declare interface Image {\n /** The Cloud Storage URI of the image. ``Image`` can contain a value\n for this field or the ``image_bytes`` field but not both. */\n gcsUri?: string;\n /** The image bytes data. ``Image`` can contain a value for this field\n or the ``gcs_uri`` field but not both.\n * @remarks Encoded as base64 string. */\n imageBytes?: string;\n /** The MIME type of the image. */\n mimeType?: string;\n}\n\n/** Safety attributes of a GeneratedImage or the user-provided prompt. */\nexport declare interface SafetyAttributes {\n /** List of RAI categories. */\n categories?: string[];\n /** List of scores of each categories. */\n scores?: number[];\n /** Internal use only. */\n contentType?: string;\n}\n\n/** An output image. */\nexport declare interface GeneratedImage {\n /** The output image data. */\n image?: Image;\n /** Responsible AI filter reason if the image is filtered out of the\n response. */\n raiFilteredReason?: string;\n /** Safety attributes of the image. Lists of RAI categories and their\n scores of each content. */\n safetyAttributes?: SafetyAttributes;\n /** The rewritten prompt used for the image generation if the prompt\n enhancer is enabled. */\n enhancedPrompt?: string;\n}\n\n/** The output images response. */\nexport class GenerateImagesResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** List of generated images. */\n generatedImages?: GeneratedImage[];\n /** Safety attributes of the positive prompt. Only populated if\n ``include_safety_attributes`` is set to True. */\n positivePromptSafetyAttributes?: SafetyAttributes;\n}\n\n/** Configuration for a Mask reference image. */\nexport declare interface MaskReferenceConfig {\n /** Prompts the model to generate a mask instead of you needing to\n provide one (unless MASK_MODE_USER_PROVIDED is used). */\n maskMode?: MaskReferenceMode;\n /** A list of up to 5 class ids to use for semantic segmentation.\n Automatically creates an image mask based on specific objects. */\n segmentationClasses?: number[];\n /** Dilation percentage of the mask provided.\n Float between 0 and 1. */\n maskDilation?: number;\n}\n\n/** Configuration for a Control reference image. */\nexport declare interface ControlReferenceConfig {\n /** The type of control reference image to use. */\n controlType?: ControlReferenceType;\n /** Defaults to False. When set to True, the control image will be\n computed by the model based on the control type. When set to False,\n the control image must be provided by the user. */\n enableControlImageComputation?: boolean;\n}\n\n/** Configuration for a Style reference image. */\nexport declare interface StyleReferenceConfig {\n /** A text description of the style to use for the generated image. */\n styleDescription?: string;\n}\n\n/** Configuration for a Subject reference image. */\nexport declare interface SubjectReferenceConfig {\n /** The subject type of a subject reference image. */\n subjectType?: SubjectReferenceType;\n /** Subject description for the image. */\n subjectDescription?: string;\n}\n\n/** Configuration for editing an image. */\nexport declare interface EditImageConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** Cloud Storage URI used to store the generated images. */\n outputGcsUri?: string;\n /** Description of what to discourage in the generated images. */\n negativePrompt?: string;\n /** Number of images to generate. */\n numberOfImages?: number;\n /** Aspect ratio of the generated images. Supported values are\n \"1:1\", \"3:4\", \"4:3\", \"9:16\", and \"16:9\". */\n aspectRatio?: string;\n /** Controls how much the model adheres to the text prompt. Large\n values increase output and prompt alignment, but may compromise image\n quality. */\n guidanceScale?: number;\n /** Random seed for image generation. This is not available when\n ``add_watermark`` is set to true. */\n seed?: number;\n /** Filter level for safety filtering. */\n safetyFilterLevel?: SafetyFilterLevel;\n /** Allows generation of people by the model. */\n personGeneration?: PersonGeneration;\n /** Whether to report the safety scores of each generated image and\n the positive prompt in the response. */\n includeSafetyAttributes?: boolean;\n /** Whether to include the Responsible AI filter reason if the image\n is filtered out of the response. */\n includeRaiReason?: boolean;\n /** Language of the text in the prompt. */\n language?: ImagePromptLanguage;\n /** MIME type of the generated image. */\n outputMimeType?: string;\n /** Compression quality of the generated image (for ``image/jpeg``\n only). */\n outputCompressionQuality?: number;\n /** Whether to add a watermark to the generated images. */\n addWatermark?: boolean;\n /** User specified labels to track billing usage. */\n labels?: Record<string, string>;\n /** Describes the editing mode for the request. */\n editMode?: EditMode;\n /** The number of sampling steps. A higher value has better image\n quality, while a lower value has better latency. */\n baseSteps?: number;\n}\n\n/** Response for the request to edit an image. */\nexport class EditImageResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** Generated images. */\n generatedImages?: GeneratedImage[];\n}\n\nexport class UpscaleImageResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** Generated images. */\n generatedImages?: GeneratedImage[];\n}\n\n/** An image of the product. */\nexport declare interface ProductImage {\n /** An image of the product to be recontextualized. */\n productImage?: Image;\n}\n\n/** A set of source input(s) for image recontextualization. */\nexport declare interface RecontextImageSource {\n /** A text prompt for guiding the model during image\n recontextualization. Not supported for Virtual Try-On. */\n prompt?: string;\n /** Image of the person or subject who will be wearing the\n product(s). */\n personImage?: Image;\n /** A list of product images. */\n productImages?: ProductImage[];\n}\n\n/** Configuration for recontextualizing an image. */\nexport declare interface RecontextImageConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** Number of images to generate. */\n numberOfImages?: number;\n /** The number of sampling steps. A higher value has better image\n quality, while a lower value has better latency. */\n baseSteps?: number;\n /** Cloud Storage URI used to store the generated images. */\n outputGcsUri?: string;\n /** Random seed for image generation. */\n seed?: number;\n /** Filter level for safety filtering. */\n safetyFilterLevel?: SafetyFilterLevel;\n /** Whether allow to generate person images, and restrict to specific\n ages. */\n personGeneration?: PersonGeneration;\n /** Whether to add a SynthID watermark to the generated images. */\n addWatermark?: boolean;\n /** MIME type of the generated image. */\n outputMimeType?: string;\n /** Compression quality of the generated image (for ``image/jpeg``\n only). */\n outputCompressionQuality?: number;\n /** Whether to use the prompt rewriting logic. */\n enhancePrompt?: boolean;\n /** User specified labels to track billing usage. */\n labels?: Record<string, string>;\n}\n\n/** The parameters for recontextualizing an image. */\nexport declare interface RecontextImageParameters {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model: string;\n /** A set of source input(s) for image recontextualization. */\n source: RecontextImageSource;\n /** Configuration for image recontextualization. */\n config?: RecontextImageConfig;\n}\n\n/** The output images response. */\nexport class RecontextImageResponse {\n /** List of generated images. */\n generatedImages?: GeneratedImage[];\n}\n\n/** An image mask representing a brush scribble. */\nexport declare interface ScribbleImage {\n /** The brush scribble to guide segmentation. Valid for the interactive mode. */\n image?: Image;\n}\n\n/** A set of source input(s) for image segmentation. */\nexport declare interface SegmentImageSource {\n /** A text prompt for guiding the model during image segmentation.\n Required for prompt mode and semantic mode, disallowed for other modes. */\n prompt?: string;\n /** The image to be segmented. */\n image?: Image;\n /** The brush scribble to guide segmentation.\n Required for the interactive mode, disallowed for other modes. */\n scribbleImage?: ScribbleImage;\n}\n\n/** Configuration for segmenting an image. */\nexport declare interface SegmentImageConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** The segmentation mode to use. */\n mode?: SegmentMode;\n /** The maximum number of predictions to return up to, by top\n confidence score. */\n maxPredictions?: number;\n /** The confidence score threshold for the detections as a decimal\n value. Only predictions with a confidence score higher than this\n threshold will be returned. */\n confidenceThreshold?: number;\n /** A decimal value representing how much dilation to apply to the\n masks. 0 for no dilation. 1.0 means the masked area covers the whole\n image. */\n maskDilation?: number;\n /** The binary color threshold to apply to the masks. The threshold\n can be set to a decimal value between 0 and 255 non-inclusive.\n Set to -1 for no binary color thresholding. */\n binaryColorThreshold?: number;\n /** User specified labels to track billing usage. */\n labels?: Record<string, string>;\n}\n\n/** The parameters for segmenting an image. */\nexport declare interface SegmentImageParameters {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model: string;\n /** A set of source input(s) for image segmentation. */\n source: SegmentImageSource;\n /** Configuration for image segmentation. */\n config?: SegmentImageConfig;\n}\n\n/** An entity representing the segmented area. */\nexport declare interface EntityLabel {\n /** The label of the segmented entity. */\n label?: string;\n /** The confidence score of the detected label. */\n score?: number;\n}\n\n/** A generated image mask. */\nexport declare interface GeneratedImageMask {\n /** The generated image mask. */\n mask?: Image;\n /** The detected entities on the segmented area. */\n labels?: EntityLabel[];\n}\n\n/** The output images response. */\nexport class SegmentImageResponse {\n /** List of generated image masks.\n */\n generatedMasks?: GeneratedImageMask[];\n}\n\n/** Optional parameters for models.get method. */\nexport declare interface GetModelConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\nexport declare interface GetModelParameters {\n model: string;\n /** Optional parameters for the request. */\n config?: GetModelConfig;\n}\n\n/** An endpoint where you deploy models. */\nexport declare interface Endpoint {\n /** Resource name of the endpoint. */\n name?: string;\n /** ID of the model that's deployed to the endpoint. */\n deployedModelId?: string;\n}\n\n/** A tuned machine learning model. */\nexport declare interface TunedModelInfo {\n /** ID of the base model that you want to tune. */\n baseModel?: string;\n /** Date and time when the base model was created. */\n createTime?: string;\n /** Date and time when the base model was last updated. */\n updateTime?: string;\n}\n\n/** Describes the machine learning model version checkpoint. */\nexport declare interface Checkpoint {\n /** The ID of the checkpoint.\n */\n checkpointId?: string;\n /** The epoch of the checkpoint.\n */\n epoch?: string;\n /** The step of the checkpoint.\n */\n step?: string;\n}\n\n/** A trained machine learning model. */\nexport declare interface Model {\n /** Resource name of the model. */\n name?: string;\n /** Display name of the model. */\n displayName?: string;\n /** Description of the model. */\n description?: string;\n /** Version ID of the model. A new version is committed when a new\n model version is uploaded or trained under an existing model ID. The\n version ID is an auto-incrementing decimal number in string\n representation. */\n version?: string;\n /** List of deployed models created from this base model. Note that a\n model could have been deployed to endpoints in different locations. */\n endpoints?: Endpoint[];\n /** Labels with user-defined metadata to organize your models. */\n labels?: Record<string, string>;\n /** Information about the tuned model from the base model. */\n tunedModelInfo?: TunedModelInfo;\n /** The maximum number of input tokens that the model can handle. */\n inputTokenLimit?: number;\n /** The maximum number of output tokens that the model can generate. */\n outputTokenLimit?: number;\n /** List of actions that are supported by the model. */\n supportedActions?: string[];\n /** The default checkpoint id of a model version.\n */\n defaultCheckpointId?: string;\n /** The checkpoints of the model. */\n checkpoints?: Checkpoint[];\n /** Temperature value used for sampling set when the dataset was saved.\n This value is used to tune the degree of randomness. */\n temperature?: number;\n /** The maximum temperature value used for sampling set when the\n dataset was saved. This value is used to tune the degree of randomness. */\n maxTemperature?: number;\n /** Optional. Specifies the nucleus sampling threshold. The model\n considers only the smallest set of tokens whose cumulative probability is\n at least `top_p`. This helps generate more diverse and less repetitive\n responses. For example, a `top_p` of 0.9 means the model considers tokens\n until the cumulative probability of the tokens to select from reaches 0.9.\n It's recommended to adjust either temperature or `top_p`, but not both. */\n topP?: number;\n /** Optional. Specifies the top-k sampling threshold. The model\n considers only the top k most probable tokens for the next token. This can\n be useful for generating more coherent and less random text. For example,\n a `top_k` of 40 means the model will choose the next word from the 40 most\n likely words. */\n topK?: number;\n /** Whether the model supports thinking features. If true, thoughts are\n returned only if the model supports thought and thoughts are available. */\n thinking?: boolean;\n}\n\nexport declare interface ListModelsConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n pageSize?: number;\n pageToken?: string;\n filter?: string;\n /** Set true to list base models, false to list tuned models. */\n queryBase?: boolean;\n}\n\nexport declare interface ListModelsParameters {\n config?: ListModelsConfig;\n}\n\nexport class ListModelsResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n nextPageToken?: string;\n models?: Model[];\n}\n\n/** Configuration for updating a tuned model. */\nexport declare interface UpdateModelConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n displayName?: string;\n description?: string;\n defaultCheckpointId?: string;\n}\n\n/** Configuration for updating a tuned model. */\nexport declare interface UpdateModelParameters {\n model: string;\n config?: UpdateModelConfig;\n}\n\n/** Configuration for deleting a tuned model. */\nexport declare interface DeleteModelConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for deleting a tuned model. */\nexport declare interface DeleteModelParameters {\n model: string;\n /** Optional parameters for the request. */\n config?: DeleteModelConfig;\n}\n\nexport class DeleteModelResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n}\n\n/** Generation config. */\nexport declare interface GenerationConfig {\n /** Optional. Config for model selection. */\n modelSelectionConfig?: ModelSelectionConfig;\n /** Output schema of the generated response. This is an alternative to\n `response_schema` that accepts [JSON Schema](https://json-schema.org/).\n */\n responseJsonSchema?: unknown;\n /** Optional. If enabled, audio timestamp will be included in the request to the model. This field is not supported in Gemini API. */\n audioTimestamp?: boolean;\n /** Optional. Number of candidates to generate. */\n candidateCount?: number;\n /** Optional. If enabled, the model will detect emotions and adapt its responses accordingly. This field is not supported in Gemini API. */\n enableAffectiveDialog?: boolean;\n /** Optional. Frequency penalties. */\n frequencyPenalty?: number;\n /** Optional. Logit probabilities. */\n logprobs?: number;\n /** Optional. The maximum number of output tokens to generate per message. */\n maxOutputTokens?: number;\n /** Optional. If specified, the media resolution specified will be used. */\n mediaResolution?: MediaResolution;\n /** Optional. Positive penalties. */\n presencePenalty?: number;\n /** Optional. If true, export the logprobs results in response. */\n responseLogprobs?: boolean;\n /** Optional. Output response mimetype of the generated candidate text. Supported mimetype: - `text/plain`: (default) Text output. - `application/json`: JSON response in the candidates. The model needs to be prompted to output the appropriate response type, otherwise the behavior is undefined. This is a preview feature. */\n responseMimeType?: string;\n /** Optional. The modalities of the response. */\n responseModalities?: Modality[];\n /** Optional. The `Schema` object allows the definition of input and output data types. These types can be objects, but also primitives and arrays. Represents a select subset of an [OpenAPI 3.0 schema object](https://spec.openapis.org/oas/v3.0.3#schema). If set, a compatible response_mime_type must also be set. Compatible mimetypes: `application/json`: Schema for JSON response. */\n responseSchema?: Schema;\n /** Optional. Routing configuration. This field is not supported in Gemini API. */\n routingConfig?: GenerationConfigRoutingConfig;\n /** Optional. Seed. */\n seed?: number;\n /** Optional. The speech generation config. */\n speechConfig?: SpeechConfig;\n /** Optional. Stop sequences. */\n stopSequences?: string[];\n /** Optional. Controls the randomness of predictions. */\n temperature?: number;\n /** Optional. Config for thinking features. An error will be returned if this field is set for models that don't support thinking. */\n thinkingConfig?: ThinkingConfig;\n /** Optional. If specified, top-k sampling will be used. */\n topK?: number;\n /** Optional. If specified, nucleus sampling will be used. */\n topP?: number;\n /** Optional. Enables enhanced civic answers. It may not be available for all models. This field is not supported in Vertex AI. */\n enableEnhancedCivicAnswers?: boolean;\n}\n\n/** Config for the count_tokens method. */\nexport declare interface CountTokensConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** Instructions for the model to steer it toward better performance.\n */\n systemInstruction?: ContentUnion;\n /** Code that enables the system to interact with external systems to\n perform an action outside of the knowledge and scope of the model.\n */\n tools?: Tool[];\n /** Configuration that the model uses to generate the response. Not\n supported by the Gemini Developer API.\n */\n generationConfig?: GenerationConfig;\n}\n\n/** Parameters for counting tokens. */\nexport declare interface CountTokensParameters {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model: string;\n /** Input content. */\n contents: ContentListUnion;\n /** Configuration for counting tokens. */\n config?: CountTokensConfig;\n}\n\n/** Response for counting tokens. */\nexport class CountTokensResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** Total number of tokens. */\n totalTokens?: number;\n /** Number of tokens in the cached part of the prompt (the cached content). */\n cachedContentTokenCount?: number;\n}\n\n/** Optional parameters for computing tokens. */\nexport declare interface ComputeTokensConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for computing tokens. */\nexport declare interface ComputeTokensParameters {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model: string;\n /** Input content. */\n contents: ContentListUnion;\n /** Optional parameters for the request.\n */\n config?: ComputeTokensConfig;\n}\n\n/** Tokens info with a list of tokens and the corresponding list of token ids. */\nexport declare interface TokensInfo {\n /** Optional fields for the role from the corresponding Content. */\n role?: string;\n /** A list of token ids from the input. */\n tokenIds?: string[];\n /** A list of tokens from the input.\n * @remarks Encoded as base64 string. */\n tokens?: string[];\n}\n\n/** Response for computing tokens. */\nexport class ComputeTokensResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** Lists of tokens info from the input. A ComputeTokensRequest could have multiple instances with a prompt in each instance. We also need to return lists of tokens info for the request with multiple instances. */\n tokensInfo?: TokensInfo[];\n}\n\n/** A generated video. */\nexport declare interface Video {\n /** Path to another storage. */\n uri?: string;\n /** Video bytes.\n * @remarks Encoded as base64 string. */\n videoBytes?: string;\n /** Video encoding, for example ``video/mp4``. */\n mimeType?: string;\n}\n\n/** A set of source input(s) for video generation. */\nexport declare interface GenerateVideosSource {\n /** The text prompt for generating the videos.\n Optional if image or video is provided. */\n prompt?: string;\n /** The input image for generating the videos.\n Optional if prompt is provided. Not allowed if video is provided. */\n image?: Image;\n /** The input video for video extension use cases.\n Optional if prompt is provided. Not allowed if image is provided. */\n video?: Video;\n}\n\n/** A reference image for video generation. */\nexport declare interface VideoGenerationReferenceImage {\n /** The reference image. */\n image?: Image;\n /** The type of the reference image, which defines how the reference\n image will be used to generate the video. */\n referenceType?: VideoGenerationReferenceType;\n}\n\n/** A mask for video generation. */\nexport declare interface VideoGenerationMask {\n /** The image mask to use for generating videos. */\n image?: Image;\n /** Describes how the mask will be used. Inpainting masks must\n match the aspect ratio of the input video. Outpainting masks can be\n either 9:16 or 16:9. */\n maskMode?: VideoGenerationMaskMode;\n}\n\n/** Configuration for generating videos. */\nexport declare interface GenerateVideosConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** Number of output videos. */\n numberOfVideos?: number;\n /** The gcs bucket where to save the generated videos. */\n outputGcsUri?: string;\n /** Frames per second for video generation. */\n fps?: number;\n /** Duration of the clip for video generation in seconds. */\n durationSeconds?: number;\n /** The RNG seed. If RNG seed is exactly same for each request with\n unchanged inputs, the prediction results will be consistent. Otherwise,\n a random RNG seed will be used each time to produce a different\n result. */\n seed?: number;\n /** The aspect ratio for the generated video. 16:9 (landscape) and\n 9:16 (portrait) are supported. */\n aspectRatio?: string;\n /** The resolution for the generated video. 720p and 1080p are\n supported. */\n resolution?: string;\n /** Whether allow to generate person videos, and restrict to specific\n ages. Supported values are: dont_allow, allow_adult. */\n personGeneration?: string;\n /** The pubsub topic where to publish the video generation\n progress. */\n pubsubTopic?: string;\n /** Explicitly state what should not be included in the generated\n videos. */\n negativePrompt?: string;\n /** Whether to use the prompt rewriting logic. */\n enhancePrompt?: boolean;\n /** Whether to generate audio along with the video. */\n generateAudio?: boolean;\n /** Image to use as the last frame of generated videos.\n Only supported for image to video use cases. */\n lastFrame?: Image;\n /** The images to use as the references to generate the videos.\n If this field is provided, the text prompt field must also be provided.\n The image, video, or last_frame field are not supported. Each image must\n be associated with a type. Veo 2 supports up to 3 asset images *or* 1\n style image. */\n referenceImages?: VideoGenerationReferenceImage[];\n /** The mask to use for generating videos. */\n mask?: VideoGenerationMask;\n /** Compression quality of the generated videos. */\n compressionQuality?: VideoCompressionQuality;\n}\n\n/** Class that represents the parameters for generating videos. */\nexport declare interface GenerateVideosParameters {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model: string;\n /** The text prompt for generating the videos.\n Optional if image or video is provided. */\n prompt?: string;\n /** The input image for generating the videos.\n Optional if prompt is provided. Not allowed if video is provided. */\n image?: Image;\n /** The input video for video extension use cases.\n Optional if prompt is provided. Not allowed if image is provided. */\n video?: Video;\n /** A set of source input(s) for video generation. */\n source?: GenerateVideosSource;\n /** Configuration for generating videos. */\n config?: GenerateVideosConfig;\n}\n\n/** A generated video. */\nexport declare interface GeneratedVideo {\n /** The output video */\n video?: Video;\n}\n\n/** Response with generated videos. */\nexport class GenerateVideosResponse {\n /** List of the generated videos */\n generatedVideos?: GeneratedVideo[];\n /** Returns if any videos were filtered due to RAI policies. */\n raiMediaFilteredCount?: number;\n /** Returns rai failure reasons if any. */\n raiMediaFilteredReasons?: string[];\n}\n\n/** A long-running operation. */\nexport declare interface Operation<T> {\n /** The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`. */\n name?: string;\n /** Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata. Any method that returns a long-running operation should document the metadata type, if any. */\n metadata?: Record<string, unknown>;\n /** If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available. */\n done?: boolean;\n /** The error result of the operation in case of failure or cancellation. */\n error?: Record<string, unknown>;\n /** The response if the operation is successful. */\n response?: T;\n /**\n * Instantiates an Operation of the same type as the one being called with the fields set from the API response.\n * @internal\n */\n _fromAPIResponse({\n apiResponse,\n _isVertexAI,\n }: OperationFromAPIResponseParameters): Operation<T>;\n}\n\n/** A video generation operation. */\nexport class GenerateVideosOperation\n implements Operation<GenerateVideosResponse>\n{\n /** The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`. */\n name?: string;\n /** Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata. Any method that returns a long-running operation should document the metadata type, if any. */\n metadata?: Record<string, unknown>;\n /** If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available. */\n done?: boolean;\n /** The error result of the operation in case of failure or cancellation. */\n error?: Record<string, unknown>;\n /** The generated videos. */\n response?: GenerateVideosResponse;\n\n /**\n * Instantiates an Operation of the same type as the one being called with the fields set from the API response.\n * @internal\n */\n _fromAPIResponse({\n apiResponse,\n _isVertexAI,\n }: OperationFromAPIResponseParameters): Operation<GenerateVideosResponse> {\n const operation = new GenerateVideosOperation();\n let response;\n const op = apiResponse as unknown as GenerateVideosOperation;\n\n if (_isVertexAI) {\n response = generateVideosOperationFromVertex(op);\n } else {\n response = generateVideosOperationFromMldev(op);\n }\n Object.assign(operation, response);\n return operation;\n }\n /** The full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n}\n\n/** Optional parameters for tunings.get method. */\nexport declare interface GetTuningJobConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for the get method. */\nexport declare interface GetTuningJobParameters {\n name: string;\n /** Optional parameters for the request. */\n config?: GetTuningJobConfig;\n}\n\n/** TunedModelCheckpoint for the Tuned Model of a Tuning Job. */\nexport declare interface TunedModelCheckpoint {\n /** The ID of the checkpoint.\n */\n checkpointId?: string;\n /** The epoch of the checkpoint.\n */\n epoch?: string;\n /** The step of the checkpoint.\n */\n step?: string;\n /** The Endpoint resource name that the checkpoint is deployed to.\n Format: `projects/{project}/locations/{location}/endpoints/{endpoint}`.\n */\n endpoint?: string;\n}\n\n/** TunedModel for the Tuned Model of a Tuning Job. */\nexport declare interface TunedModel {\n /** Output only. The resource name of the TunedModel.\n Format: `projects/{project}/locations/{location}/models/{model}@{version_id}`\n When tuning from a base model, the version_id will be 1.\n For continuous tuning, the version id will be incremented by 1 from the\n last version id in the parent model. E.g., `projects/{project}/locations/{location}/models/{model}@{last_version_id + 1}`\n */\n model?: string;\n /** Output only. A resource name of an Endpoint.\n Format: `projects/{project}/locations/{location}/endpoints/{endpoint}`.\n */\n endpoint?: string;\n /** The checkpoints associated with this TunedModel.\n This field is only populated for tuning jobs that enable intermediate\n checkpoints. */\n checkpoints?: TunedModelCheckpoint[];\n}\n\n/** Hyperparameters for SFT. This data type is not supported in Gemini API. */\nexport declare interface SupervisedHyperParameters {\n /** Optional. Adapter size for tuning. */\n adapterSize?: AdapterSize;\n /** Optional. Batch size for tuning. This feature is only available for open source models. */\n batchSize?: string;\n /** Optional. Number of complete passes the model makes over the entire training dataset during training. */\n epochCount?: string;\n /** Optional. Learning rate for tuning. Mutually exclusive with `learning_rate_multiplier`. This feature is only available for open source models. */\n learningRate?: number;\n /** Optional. Multiplier for adjusting the default learning rate. Mutually exclusive with `learning_rate`. This feature is only available for 1P models. */\n learningRateMultiplier?: number;\n}\n\n/** Supervised tuning spec for tuning. */\nexport declare interface SupervisedTuningSpec {\n /** Optional. If set to true, disable intermediate checkpoints for SFT and only the last checkpoint will be exported. Otherwise, enable intermediate checkpoints for SFT. Default is false. */\n exportLastCheckpointOnly?: boolean;\n /** Optional. Hyperparameters for SFT. */\n hyperParameters?: SupervisedHyperParameters;\n /** Required. Training dataset used for tuning. The dataset can be specified as either a Cloud Storage path to a JSONL file or as the resource name of a Vertex Multimodal Dataset. */\n trainingDatasetUri?: string;\n /** Tuning mode. */\n tuningMode?: TuningMode;\n /** Optional. Validation dataset used for tuning. The dataset can be specified as either a Cloud Storage path to a JSONL file or as the resource name of a Vertex Multimodal Dataset. */\n validationDatasetUri?: string;\n}\n\n/** Hyperparameters for Preference Optimization. This data type is not supported in Gemini API. */\nexport declare interface PreferenceOptimizationHyperParameters {\n /** Optional. Adapter size for preference optimization. */\n adapterSize?: AdapterSize;\n /** Optional. Weight for KL Divergence regularization. */\n beta?: number;\n /** Optional. Number of complete passes the model makes over the entire training dataset during training. */\n epochCount?: string;\n /** Optional. Multiplier for adjusting the default learning rate. */\n learningRateMultiplier?: number;\n}\n\n/** Preference optimization tuning spec for tuning. */\nexport declare interface PreferenceOptimizationSpec {\n /** Optional. If set to true, disable intermediate checkpoints for Preference Optimization and only the last checkpoint will be exported. Otherwise, enable intermediate checkpoints for Preference Optimization. Default is false. */\n exportLastCheckpointOnly?: boolean;\n /** Optional. Hyperparameters for Preference Optimization. */\n hyperParameters?: PreferenceOptimizationHyperParameters;\n /** Required. Cloud Storage path to file containing training dataset for preference optimization tuning. The dataset must be formatted as a JSONL file. */\n trainingDatasetUri?: string;\n /** Optional. Cloud Storage path to file containing validation dataset for preference optimization tuning. The dataset must be formatted as a JSONL file. */\n validationDatasetUri?: string;\n}\n\n/** Hyperparameters for Distillation. This data type is not supported in Gemini API. */\nexport declare interface DistillationHyperParameters {\n /** Optional. Adapter size for distillation. */\n adapterSize?: AdapterSize;\n /** Optional. Number of complete passes the model makes over the entire training dataset during training. */\n epochCount?: string;\n /** Optional. Multiplier for adjusting the default learning rate. */\n learningRateMultiplier?: number;\n}\n\n/** Distillation tuning spec for tuning. */\nexport declare interface DistillationSpec {\n /** The GCS URI of the prompt dataset to use during distillation. */\n promptDatasetUri?: string;\n /** The base teacher model that is being distilled. See [Supported models](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/tuning#supported_models). */\n baseTeacherModel?: string;\n /** Optional. Hyperparameters for Distillation. */\n hyperParameters?: DistillationHyperParameters;\n /** Deprecated. A path in a Cloud Storage bucket, which will be treated as the root output directory of the distillation pipeline. It is used by the system to generate the paths of output artifacts. */\n pipelineRootDirectory?: string;\n /** The student model that is being tuned, e.g., \"google/gemma-2b-1.1-it\". Deprecated. Use base_model instead. */\n studentModel?: string;\n /** Deprecated. Cloud Storage path to file containing training dataset for tuning. The dataset must be formatted as a JSONL file. */\n trainingDatasetUri?: string;\n /** The resource name of the Tuned teacher model. Format: `projects/{project}/locations/{location}/models/{model}`. */\n tunedTeacherModelSource?: string;\n /** Optional. Cloud Storage path to file containing validation dataset for tuning. The dataset must be formatted as a JSONL file. */\n validationDatasetUri?: string;\n}\n\n/** The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors). This data type is not supported in Gemini API. */\nexport declare interface GoogleRpcStatus {\n /** The status code, which should be an enum value of google.rpc.Code. */\n code?: number;\n /** A list of messages that carry the error details. There is a common set of message types for APIs to use. */\n details?: Record<string, unknown>[];\n /** A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the google.rpc.Status.details field, or localized by the client. */\n message?: string;\n}\n\n/** A pre-tuned model for continuous tuning. This data type is not supported in Gemini API. */\nexport declare interface PreTunedModel {\n /** Output only. The name of the base model this PreTunedModel was tuned from. */\n baseModel?: string;\n /** Optional. The source checkpoint id. If not specified, the default checkpoint will be used. */\n checkpointId?: string;\n /** The resource name of the Model. E.g., a model resource name with a specified version id or alias: `projects/{project}/locations/{location}/models/{model}@{version_id}` `projects/{project}/locations/{location}/models/{model}@{alias}` Or, omit the version id to use the default version: `projects/{project}/locations/{location}/models/{model}` */\n tunedModelName?: string;\n}\n\n/** Dataset bucket used to create a histogram for the distribution given a population of values. This data type is not supported in Gemini API. */\nexport declare interface DatasetDistributionDistributionBucket {\n /** Output only. Number of values in the bucket. */\n count?: string;\n /** Output only. Left bound of the bucket. */\n left?: number;\n /** Output only. Right bound of the bucket. */\n right?: number;\n}\n\n/** Distribution computed over a tuning dataset. This data type is not supported in Gemini API. */\nexport declare interface DatasetDistribution {\n /** Output only. Defines the histogram bucket. */\n buckets?: DatasetDistributionDistributionBucket[];\n /** Output only. The maximum of the population values. */\n max?: number;\n /** Output only. The arithmetic mean of the values in the population. */\n mean?: number;\n /** Output only. The median of the values in the population. */\n median?: number;\n /** Output only. The minimum of the population values. */\n min?: number;\n /** Output only. The 5th percentile of the values in the population. */\n p5?: number;\n /** Output only. The 95th percentile of the values in the population. */\n p95?: number;\n /** Output only. Sum of a given population of values. */\n sum?: number;\n}\n\n/** Statistics computed over a tuning dataset. This data type is not supported in Gemini API. */\nexport declare interface DatasetStats {\n /** Output only. Number of billable characters in the tuning dataset. */\n totalBillableCharacterCount?: string;\n /** Output only. Number of tuning characters in the tuning dataset. */\n totalTuningCharacterCount?: string;\n /** Output only. Number of examples in the tuning dataset. */\n tuningDatasetExampleCount?: string;\n /** Output only. Number of tuning steps for this Tuning Job. */\n tuningStepCount?: string;\n /** Output only. Sample user messages in the training dataset uri. */\n userDatasetExamples?: Content[];\n /** Output only. Dataset distributions for the user input tokens. */\n userInputTokenDistribution?: DatasetDistribution;\n /** Output only. Dataset distributions for the messages per example. */\n userMessagePerExampleDistribution?: DatasetDistribution;\n /** Output only. Dataset distributions for the user output tokens. */\n userOutputTokenDistribution?: DatasetDistribution;\n}\n\n/** Statistics computed for datasets used for distillation. This data type is not supported in Gemini API. */\nexport declare interface DistillationDataStats {\n /** Output only. Statistics computed for the training dataset. */\n trainingDatasetStats?: DatasetStats;\n}\n\n/** Completion and its preference score. This data type is not supported in Gemini API. */\nexport declare interface GeminiPreferenceExampleCompletion {\n /** Single turn completion for the given prompt. */\n completion?: Content;\n /** The score for the given completion. */\n score?: number;\n}\n\n/** Input example for preference optimization. This data type is not supported in Gemini API. */\nexport declare interface GeminiPreferenceExample {\n /** List of completions for a given prompt. */\n completions?: GeminiPreferenceExampleCompletion[];\n /** Multi-turn contents that represents the Prompt. */\n contents?: Content[];\n}\n\n/** Statistics computed for datasets used for preference optimization. This data type is not supported in Gemini API. */\nexport declare interface PreferenceOptimizationDataStats {\n /** Output only. Dataset distributions for scores variance per example. */\n scoreVariancePerExampleDistribution?: DatasetDistribution;\n /** Output only. Dataset distributions for scores. */\n scoresDistribution?: DatasetDistribution;\n /** Output only. Number of billable tokens in the tuning dataset. */\n totalBillableTokenCount?: string;\n /** Output only. Number of examples in the tuning dataset. */\n tuningDatasetExampleCount?: string;\n /** Output only. Number of tuning steps for this Tuning Job. */\n tuningStepCount?: string;\n /** Output only. Sample user examples in the training dataset. */\n userDatasetExamples?: GeminiPreferenceExample[];\n /** Output only. Dataset distributions for the user input tokens. */\n userInputTokenDistribution?: DatasetDistribution;\n /** Output only. Dataset distributions for the user output tokens. */\n userOutputTokenDistribution?: DatasetDistribution;\n}\n\n/** Dataset bucket used to create a histogram for the distribution given a population of values. This data type is not supported in Gemini API. */\nexport declare interface SupervisedTuningDatasetDistributionDatasetBucket {\n /** Output only. Number of values in the bucket. */\n count?: number;\n /** Output only. Left bound of the bucket. */\n left?: number;\n /** Output only. Right bound of the bucket. */\n right?: number;\n}\n\n/** Dataset distribution for Supervised Tuning. This data type is not supported in Gemini API. */\nexport declare interface SupervisedTuningDatasetDistribution {\n /** Output only. Sum of a given population of values that are billable. */\n billableSum?: string;\n /** Output only. Defines the histogram bucket. */\n buckets?: SupervisedTuningDatasetDistributionDatasetBucket[];\n /** Output only. The maximum of the population values. */\n max?: number;\n /** Output only. The arithmetic mean of the values in the population. */\n mean?: number;\n /** Output only. The median of the values in the population. */\n median?: number;\n /** Output only. The minimum of the population values. */\n min?: number;\n /** Output only. The 5th percentile of the values in the population. */\n p5?: number;\n /** Output only. The 95th percentile of the values in the population. */\n p95?: number;\n /** Output only. Sum of a given population of values. */\n sum?: string;\n}\n\n/** Tuning data statistics for Supervised Tuning. This data type is not supported in Gemini API. */\nexport declare interface SupervisedTuningDataStats {\n /** Output only. For each index in `truncated_example_indices`, the user-facing reason why the example was dropped. */\n droppedExampleReasons?: string[];\n /** Output only. Number of billable characters in the tuning dataset. */\n totalBillableCharacterCount?: string;\n /** Output only. Number of billable tokens in the tuning dataset. */\n totalBillableTokenCount?: string;\n /** Output only. The number of examples in the dataset that have been dropped. An example can be dropped for reasons including: too many tokens, contains an invalid image, contains too many images, etc. */\n totalTruncatedExampleCount?: string;\n /** Output only. Number of tuning characters in the tuning dataset. */\n totalTuningCharacterCount?: string;\n /** Output only. A partial sample of the indices (starting from 1) of the dropped examples. */\n truncatedExampleIndices?: string[];\n /** Output only. Number of examples in the tuning dataset. */\n tuningDatasetExampleCount?: string;\n /** Output only. Number of tuning steps for this Tuning Job. */\n tuningStepCount?: string;\n /** Output only. Sample user messages in the training dataset uri. */\n userDatasetExamples?: Content[];\n /** Output only. Dataset distributions for the user input tokens. */\n userInputTokenDistribution?: SupervisedTuningDatasetDistribution;\n /** Output only. Dataset distributions for the messages per example. */\n userMessagePerExampleDistribution?: SupervisedTuningDatasetDistribution;\n /** Output only. Dataset distributions for the user output tokens. */\n userOutputTokenDistribution?: SupervisedTuningDatasetDistribution;\n}\n\n/** The tuning data statistic values for TuningJob. This data type is not supported in Gemini API. */\nexport declare interface TuningDataStats {\n /** Output only. Statistics for distillation. */\n distillationDataStats?: DistillationDataStats;\n /** Output only. Statistics for preference optimization. */\n preferenceOptimizationDataStats?: PreferenceOptimizationDataStats;\n /** The SFT Tuning data stats. */\n supervisedTuningDataStats?: SupervisedTuningDataStats;\n}\n\n/** Represents a customer-managed encryption key spec that can be applied to a top-level resource. This data type is not supported in Gemini API. */\nexport declare interface EncryptionSpec {\n /** Required. The Cloud KMS resource identifier of the customer managed encryption key used to protect a resource. Has the form: `projects/my-project/locations/my-region/keyRings/my-kr/cryptoKeys/my-key`. The key needs to be in the same region as where the compute resource is created. */\n kmsKeyName?: string;\n}\n\n/** Tuning spec for Partner models. This data type is not supported in Gemini API. */\nexport declare interface PartnerModelTuningSpec {\n /** Hyperparameters for tuning. The accepted hyper_parameters and their valid range of values will differ depending on the base model. */\n hyperParameters?: Record<string, unknown>;\n /** Required. Cloud Storage path to file containing training dataset for tuning. The dataset must be formatted as a JSONL file. */\n trainingDatasetUri?: string;\n /** Optional. Cloud Storage path to file containing validation dataset for tuning. The dataset must be formatted as a JSONL file. */\n validationDatasetUri?: string;\n}\n\n/** Hyperparameters for Veo. This data type is not supported in Gemini API. */\nexport declare interface VeoHyperParameters {\n /** Optional. Number of complete passes the model makes over the entire training dataset during training. */\n epochCount?: string;\n /** Optional. Multiplier for adjusting the default learning rate. */\n learningRateMultiplier?: number;\n /** Optional. The tuning task. Either I2V or T2V. */\n tuningTask?: TuningTask;\n}\n\n/** Tuning Spec for Veo Model Tuning. This data type is not supported in Gemini API. */\nexport declare interface VeoTuningSpec {\n /** Optional. Hyperparameters for Veo. */\n hyperParameters?: VeoHyperParameters;\n /** Required. Training dataset used for tuning. The dataset can be specified as either a Cloud Storage path to a JSONL file or as the resource name of a Vertex Multimodal Dataset. */\n trainingDatasetUri?: string;\n /** Optional. Validation dataset used for tuning. The dataset can be specified as either a Cloud Storage path to a JSONL file or as the resource name of a Vertex Multimodal Dataset. */\n validationDatasetUri?: string;\n}\n\n/** A tuning job. */\nexport declare interface TuningJob {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** Output only. Identifier. Resource name of a TuningJob. Format: `projects/{project}/locations/{location}/tuningJobs/{tuning_job}` */\n name?: string;\n /** Output only. The detailed state of the job. */\n state?: JobState;\n /** Output only. Time when the TuningJob was created. */\n createTime?: string;\n /** Output only. Time when the TuningJob for the first time entered the `JOB_STATE_RUNNING` state. */\n startTime?: string;\n /** Output only. Time when the TuningJob entered any of the following JobStates: `JOB_STATE_SUCCEEDED`, `JOB_STATE_FAILED`, `JOB_STATE_CANCELLED`, `JOB_STATE_EXPIRED`. */\n endTime?: string;\n /** Output only. Time when the TuningJob was most recently updated. */\n updateTime?: string;\n /** Output only. Only populated when job's state is `JOB_STATE_FAILED` or `JOB_STATE_CANCELLED`. */\n error?: GoogleRpcStatus;\n /** Optional. The description of the TuningJob. */\n description?: string;\n /** The base model that is being tuned. See [Supported models](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/tuning#supported_models). */\n baseModel?: string;\n /** Output only. The tuned model resources associated with this TuningJob. */\n tunedModel?: TunedModel;\n /** The pre-tuned model for continuous tuning. */\n preTunedModel?: PreTunedModel;\n /** Tuning Spec for Supervised Fine Tuning. */\n supervisedTuningSpec?: SupervisedTuningSpec;\n /** Tuning Spec for Preference Optimization. */\n preferenceOptimizationSpec?: PreferenceOptimizationSpec;\n /** Tuning Spec for Distillation. */\n distillationSpec?: DistillationSpec;\n /** Output only. The tuning data statistics associated with this TuningJob. */\n tuningDataStats?: TuningDataStats;\n /** Customer-managed encryption key options for a TuningJob. If this is set, then all resources created by the TuningJob will be encrypted with the provided encryption key. */\n encryptionSpec?: EncryptionSpec;\n /** Tuning Spec for open sourced and third party Partner models. */\n partnerModelTuningSpec?: PartnerModelTuningSpec;\n /** Optional. The user-provided path to custom model weights. Set this field to tune a custom model. The path must be a Cloud Storage directory that contains the model weights in .safetensors format along with associated model metadata files. If this field is set, the base_model field must still be set to indicate which base model the custom model is derived from. This feature is only available for open source models. */\n customBaseModel?: string;\n /** Output only. The Experiment associated with this TuningJob. */\n experiment?: string;\n /** Optional. The labels with user-defined metadata to organize TuningJob and generated resources such as Model and Endpoint. Label keys and values can be no longer than 64 characters (Unicode codepoints), can only contain lowercase letters, numeric characters, underscores and dashes. International characters are allowed. See https://goo.gl/xmQnxf for more information and examples of labels. */\n labels?: Record<string, string>;\n /** Optional. Cloud Storage path to the directory where tuning job outputs are written to. This field is only available and required for open source models. */\n outputUri?: string;\n /** Output only. The resource name of the PipelineJob associated with the TuningJob. Format: `projects/{project}/locations/{location}/pipelineJobs/{pipeline_job}`. */\n pipelineJob?: string;\n /** The service account that the tuningJob workload runs as. If not specified, the Vertex AI Secure Fine-Tuned Service Agent in the project will be used. See https://cloud.google.com/iam/docs/service-agents#vertex-ai-secure-fine-tuning-service-agent Users starting the pipeline must have the `iam.serviceAccounts.actAs` permission on this service account. */\n serviceAccount?: string;\n /** Optional. The display name of the TunedModel. The name can be up to 128 characters long and can consist of any UTF-8 characters. For continuous tuning, tuned_model_display_name will by default use the same display name as the pre-tuned model. If a new display name is provided, the tuning job will create a new model instead of a new version. */\n tunedModelDisplayName?: string;\n /** Tuning Spec for Veo Tuning. */\n veoTuningSpec?: VeoTuningSpec;\n}\n\n/** Configuration for the list tuning jobs method. */\nexport declare interface ListTuningJobsConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n pageSize?: number;\n pageToken?: string;\n filter?: string;\n}\n\n/** Parameters for the list tuning jobs method. */\nexport declare interface ListTuningJobsParameters {\n config?: ListTuningJobsConfig;\n}\n\n/** Response for the list tuning jobs method. */\nexport class ListTuningJobsResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** A token to retrieve the next page of results. Pass to ListTuningJobsRequest.page_token to obtain that page. */\n nextPageToken?: string;\n /** List of TuningJobs in the requested page. */\n tuningJobs?: TuningJob[];\n}\n\n/** Optional parameters for tunings.cancel method. */\nexport declare interface CancelTuningJobConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for the cancel method. */\nexport declare interface CancelTuningJobParameters {\n /** The resource name of the tuning job. */\n name: string;\n /** Optional parameters for the request. */\n config?: CancelTuningJobConfig;\n}\n\n/** Empty response for tunings.cancel method. */\nexport class CancelTuningJobResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n}\n\n/** A single example for tuning. This data type is not supported in Vertex AI. */\nexport declare interface TuningExample {\n /** Required. The expected model output. */\n output?: string;\n /** Optional. Text model input. */\n textInput?: string;\n}\n\n/** Supervised fine-tuning training dataset. */\nexport declare interface TuningDataset {\n /** GCS URI of the file containing training dataset in JSONL format. */\n gcsUri?: string;\n /** The resource name of the Vertex Multimodal Dataset that is used as training dataset. Example: 'projects/my-project-id-or-number/locations/my-location/datasets/my-dataset-id'. */\n vertexDatasetResource?: string;\n /** Inline examples with simple input/output text. */\n examples?: TuningExample[];\n}\n\nexport declare interface TuningValidationDataset {\n /** GCS URI of the file containing validation dataset in JSONL format. */\n gcsUri?: string;\n /** The resource name of the Vertex Multimodal Dataset that is used as validation dataset. Example: 'projects/my-project-id-or-number/locations/my-location/datasets/my-dataset-id'. */\n vertexDatasetResource?: string;\n}\n\n/** Fine-tuning job creation request - optional fields. */\nexport declare interface CreateTuningJobConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** The method to use for tuning (SUPERVISED_FINE_TUNING or PREFERENCE_TUNING or DISTILLATION). If not set, the default method (SFT) will be used. */\n method?: TuningMethod;\n /** Validation dataset for tuning. The dataset must be formatted as a JSONL file. */\n validationDataset?: TuningValidationDataset;\n /** The display name of the tuned Model. The name can be up to 128 characters long and can consist of any UTF-8 characters. */\n tunedModelDisplayName?: string;\n /** The description of the TuningJob */\n description?: string;\n /** Number of complete passes the model makes over the entire training dataset during training. */\n epochCount?: number;\n /** Multiplier for adjusting the default learning rate. 1P models only. Mutually exclusive with learning_rate. */\n learningRateMultiplier?: number;\n /** If set to true, disable intermediate checkpoints and only the last checkpoint will be exported. Otherwise, enable intermediate checkpoints. */\n exportLastCheckpointOnly?: boolean;\n /** The optional checkpoint id of the pre-tuned model to use for tuning, if applicable. */\n preTunedModelCheckpointId?: string;\n /** Adapter size for tuning. */\n adapterSize?: AdapterSize;\n /** Tuning mode for SFT tuning. */\n tuningMode?: TuningMode;\n /** Custom base model for tuning. This is only supported for OSS models in Vertex. */\n customBaseModel?: string;\n /** The batch size hyperparameter for tuning. This is only supported for OSS models in Vertex. */\n batchSize?: number;\n /** The learning rate for tuning. OSS models only. Mutually exclusive with learning_rate_multiplier. */\n learningRate?: number;\n /** Optional. The labels with user-defined metadata to organize TuningJob and generated resources such as Model and Endpoint. Label keys and values can be no longer than 64 characters (Unicode codepoints), can only contain lowercase letters, numeric characters, underscores and dashes. International characters are allowed. See https://goo.gl/xmQnxf for more information and examples of labels. */\n labels?: Record<string, string>;\n /** Weight for KL Divergence regularization, Preference Optimization tuning only. */\n beta?: number;\n /** The base teacher model that is being distilled. Distillation only. */\n baseTeacherModel?: string;\n /** The resource name of the Tuned teacher model. Distillation only. */\n tunedTeacherModelSource?: string;\n /** Multiplier for adjusting the weight of the SFT loss. Distillation only. */\n sftLossWeightMultiplier?: number;\n /** The Google Cloud Storage location where the tuning job outputs are written. */\n outputUri?: string;\n /** The encryption spec of the tuning job. Customer-managed encryption key options for a TuningJob. If this is set, then all resources created by the TuningJob will be encrypted with provided encryption key. */\n encryptionSpec?: EncryptionSpec;\n}\n\n/** Fine-tuning job creation parameters - optional fields. */\nexport declare interface CreateTuningJobParametersPrivate {\n /** The base model that is being tuned, e.g., \"gemini-2.5-flash\". */\n baseModel?: string;\n /** The PreTunedModel that is being tuned. */\n preTunedModel?: PreTunedModel;\n /** Cloud Storage path to file containing training dataset for tuning. The dataset must be formatted as a JSONL file. */\n trainingDataset: TuningDataset;\n /** Configuration for the tuning job. */\n config?: CreateTuningJobConfig;\n}\n\n/** A long-running operation. */\nexport declare interface TuningOperation {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`. */\n name?: string;\n /** Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata. Any method that returns a long-running operation should document the metadata type, if any. */\n metadata?: Record<string, unknown>;\n /** If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available. */\n done?: boolean;\n /** The error result of the operation in case of failure or cancellation. */\n error?: Record<string, unknown>;\n}\n\n/** Optional configuration for cached content creation. */\nexport declare interface CreateCachedContentConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** The TTL for this resource. The expiration time is computed: now + TTL. It is a duration string, with up to nine fractional digits, terminated by 's'. Example: \"3.5s\". */\n ttl?: string;\n /** Timestamp of when this resource is considered expired. Uses RFC 3339 format, Example: 2014-10-02T15:01:23Z. */\n expireTime?: string;\n /** The user-generated meaningful display name of the cached content.\n */\n displayName?: string;\n /** The content to cache.\n */\n contents?: ContentListUnion;\n /** Developer set system instruction.\n */\n systemInstruction?: ContentUnion;\n /** A list of `Tools` the model may use to generate the next response.\n */\n tools?: Tool[];\n /** Configuration for the tools to use. This config is shared for all tools.\n */\n toolConfig?: ToolConfig;\n /** The Cloud KMS resource identifier of the customer managed\n encryption key used to protect a resource.\n The key needs to be in the same region as where the compute resource is\n created. See\n https://cloud.google.com/vertex-ai/docs/general/cmek for more\n details. If this is set, then all created CachedContent objects\n will be encrypted with the provided encryption key.\n Allowed formats: projects/{project}/locations/{location}/keyRings/{key_ring}/cryptoKeys/{crypto_key}\n */\n kmsKeyName?: string;\n}\n\n/** Parameters for caches.create method. */\nexport declare interface CreateCachedContentParameters {\n /** ID of the model to use. Example: gemini-2.0-flash */\n model: string;\n /** Configuration that contains optional parameters.\n */\n config?: CreateCachedContentConfig;\n}\n\n/** Metadata on the usage of the cached content. */\nexport declare interface CachedContentUsageMetadata {\n /** Duration of audio in seconds. This field is not supported in Gemini API. */\n audioDurationSeconds?: number;\n /** Number of images. This field is not supported in Gemini API. */\n imageCount?: number;\n /** Number of text characters. This field is not supported in Gemini API. */\n textCount?: number;\n /** Total number of tokens that the cached content consumes. */\n totalTokenCount?: number;\n /** Duration of video in seconds. This field is not supported in Gemini API. */\n videoDurationSeconds?: number;\n}\n\n/** A resource used in LLM queries for users to explicitly specify what to cache. */\nexport declare interface CachedContent {\n /** The server-generated resource name of the cached content. */\n name?: string;\n /** The user-generated meaningful display name of the cached content. */\n displayName?: string;\n /** The name of the publisher model to use for cached content. */\n model?: string;\n /** Creation time of the cache entry. */\n createTime?: string;\n /** When the cache entry was last updated in UTC time. */\n updateTime?: string;\n /** Expiration time of the cached content. */\n expireTime?: string;\n /** Metadata on the usage of the cached content. */\n usageMetadata?: CachedContentUsageMetadata;\n}\n\n/** Optional parameters for caches.get method. */\nexport declare interface GetCachedContentConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for caches.get method. */\nexport declare interface GetCachedContentParameters {\n /** The server-generated resource name of the cached content.\n */\n name: string;\n /** Optional parameters for the request.\n */\n config?: GetCachedContentConfig;\n}\n\n/** Optional parameters for caches.delete method. */\nexport declare interface DeleteCachedContentConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for caches.delete method. */\nexport declare interface DeleteCachedContentParameters {\n /** The server-generated resource name of the cached content.\n */\n name: string;\n /** Optional parameters for the request.\n */\n config?: DeleteCachedContentConfig;\n}\n\n/** Empty response for caches.delete method. */\nexport class DeleteCachedContentResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n}\n\n/** Optional parameters for caches.update method. */\nexport declare interface UpdateCachedContentConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** The TTL for this resource. The expiration time is computed: now + TTL. It is a duration string, with up to nine fractional digits, terminated by 's'. Example: \"3.5s\". */\n ttl?: string;\n /** Timestamp of when this resource is considered expired. Uses RFC 3339 format, Example: 2014-10-02T15:01:23Z. */\n expireTime?: string;\n}\n\nexport declare interface UpdateCachedContentParameters {\n /** The server-generated resource name of the cached content.\n */\n name: string;\n /** Configuration that contains optional parameters.\n */\n config?: UpdateCachedContentConfig;\n}\n\n/** Config for caches.list method. */\nexport declare interface ListCachedContentsConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n pageSize?: number;\n pageToken?: string;\n}\n\n/** Parameters for caches.list method. */\nexport declare interface ListCachedContentsParameters {\n /** Configuration that contains optional parameters.\n */\n config?: ListCachedContentsConfig;\n}\n\nexport class ListCachedContentsResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n nextPageToken?: string;\n /** List of cached contents.\n */\n cachedContents?: CachedContent[];\n}\n\n/** Optional Config. */\nexport declare interface GetDocumentConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for documents.get. */\nexport declare interface GetDocumentParameters {\n /** The resource name of the Document.\n Example: fileSearchStores/file-search-store-foo/documents/documents-bar */\n name: string;\n /** Optional parameters for the request. */\n config?: GetDocumentConfig;\n}\n\n/** User provided string values assigned to a single metadata key. This data type is not supported in Vertex AI. */\nexport declare interface StringList {\n /** The string values of the metadata to store. */\n values?: string[];\n}\n\n/** User provided metadata stored as key-value pairs. This data type is not supported in Vertex AI. */\nexport declare interface CustomMetadata {\n /** Required. The key of the metadata to store. */\n key?: string;\n /** The numeric value of the metadata to store. */\n numericValue?: number;\n /** The StringList value of the metadata to store. */\n stringListValue?: StringList;\n /** The string value of the metadata to store. */\n stringValue?: string;\n}\n\n/** A Document is a collection of Chunks. */\nexport declare interface Document {\n /** The resource name of the Document.\n Example: fileSearchStores/file-search-store-foo/documents/documents-bar */\n name?: string;\n /** The human-readable display name for the Document. */\n displayName?: string;\n /** The current state of the Document. */\n state?: DocumentState;\n /** The size of the Document in bytes. */\n sizeBytes?: string;\n /** The MIME type of the Document. */\n mimeType?: string;\n /** Output only. The Timestamp of when the `Document` was created. */\n createTime?: string;\n /** Optional. User provided custom metadata stored as key-value pairs used for querying. A `Document` can have a maximum of 20 `CustomMetadata`. */\n customMetadata?: CustomMetadata[];\n /** Output only. The Timestamp of when the `Document` was last updated. */\n updateTime?: string;\n}\n\n/** Config for optional parameters. */\nexport declare interface DeleteDocumentConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** If set to true, any `Chunk`s and objects related to this `Document` will\n also be deleted.\n */\n force?: boolean;\n}\n\n/** Config for documents.delete parameters. */\nexport declare interface DeleteDocumentParameters {\n /** The resource name of the Document.\n Example: fileSearchStores/file-search-store-foo/documents/documents-bar */\n name: string;\n /** Optional parameters for the request. */\n config?: DeleteDocumentConfig;\n}\n\n/** Config for optional parameters. */\nexport declare interface ListDocumentsConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n pageSize?: number;\n pageToken?: string;\n}\n\n/** Config for documents.list parameters. */\nexport declare interface ListDocumentsParameters {\n /** The resource name of the FileSearchStores. Example: `fileSearchStore/file-search-store-foo` */\n parent: string;\n config?: ListDocumentsConfig;\n}\n\n/** Config for documents.list return value. */\nexport class ListDocumentsResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** A token, which can be sent as `page_token` to retrieve the next page. If this field is omitted, there are no more pages. */\n nextPageToken?: string;\n /** The returned `Document`s. */\n documents?: Document[];\n}\n\n/** Optional parameters for creating a file search store. */\nexport declare interface CreateFileSearchStoreConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** The human-readable display name for the file search store.\n */\n displayName?: string;\n}\n\n/** Config for file_search_stores.create parameters. */\nexport declare interface CreateFileSearchStoreParameters {\n /** Optional parameters for creating a file search store.\n */\n config?: CreateFileSearchStoreConfig;\n}\n\n/** A collection of Documents. */\nexport declare interface FileSearchStore {\n /** The resource name of the FileSearchStore. Example: `fileSearchStores/my-file-search-store-123` */\n name?: string;\n /** The human-readable display name for the FileSearchStore. */\n displayName?: string;\n /** The Timestamp of when the FileSearchStore was created. */\n createTime?: string;\n /** The Timestamp of when the FileSearchStore was last updated. */\n updateTime?: string;\n /** The number of documents in the FileSearchStore that are active and ready for retrieval. */\n activeDocumentsCount?: string;\n /** The number of documents in the FileSearchStore that are being processed. */\n pendingDocumentsCount?: string;\n /** The number of documents in the FileSearchStore that have failed processing. */\n failedDocumentsCount?: string;\n /** The size of raw bytes ingested into the FileSearchStore. This is the\n total size of all the documents in the FileSearchStore. */\n sizeBytes?: string;\n}\n\n/** Optional parameters for getting a FileSearchStore. */\nexport declare interface GetFileSearchStoreConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Config for file_search_stores.get parameters. */\nexport declare interface GetFileSearchStoreParameters {\n /** The resource name of the FileSearchStore. Example: `fileSearchStores/my-file-search-store-123` */\n name: string;\n /** Optional parameters for the request. */\n config?: GetFileSearchStoreConfig;\n}\n\n/** Optional parameters for deleting a FileSearchStore. */\nexport declare interface DeleteFileSearchStoreConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** If set to true, any Documents and objects related to this FileSearchStore will also be deleted.\n If false (the default), a FAILED_PRECONDITION error will be returned if\n the FileSearchStore contains any Documents.\n */\n force?: boolean;\n}\n\n/** Config for file_search_stores.delete parameters. */\nexport declare interface DeleteFileSearchStoreParameters {\n /** The resource name of the FileSearchStore. Example: `fileSearchStores/my-file-search-store-123` */\n name: string;\n /** Optional parameters for the request. */\n config?: DeleteFileSearchStoreConfig;\n}\n\n/** Optional parameters for listing FileSearchStore. */\nexport declare interface ListFileSearchStoresConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n pageSize?: number;\n pageToken?: string;\n}\n\n/** Config for file_search_stores.list parameters. */\nexport declare interface ListFileSearchStoresParameters {\n /** Optional parameters for the list request. */\n config?: ListFileSearchStoresConfig;\n}\n\n/** Config for file_search_stores.list return value. */\nexport class ListFileSearchStoresResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n nextPageToken?: string;\n /** The returned file search stores. */\n fileSearchStores?: FileSearchStore[];\n}\n\n/** Configuration for a white space chunking algorithm. */\nexport declare interface WhiteSpaceConfig {\n /** Maximum number of tokens per chunk. */\n maxTokensPerChunk?: number;\n /** Maximum number of overlapping tokens between two adjacent chunks. */\n maxOverlapTokens?: number;\n}\n\n/** Config for telling the service how to chunk the file. */\nexport declare interface ChunkingConfig {\n /** White space chunking configuration. */\n whiteSpaceConfig?: WhiteSpaceConfig;\n}\n\n/** Optional parameters for uploading a file to a FileSearchStore. */\nexport declare interface UploadToFileSearchStoreConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** MIME type of the file to be uploaded. If not provided, it will be inferred from the file extension. */\n mimeType?: string;\n /** Display name of the created document. */\n displayName?: string;\n /** User provided custom metadata stored as key-value pairs used for querying. */\n customMetadata?: CustomMetadata[];\n /** Config for telling the service how to chunk the file. */\n chunkingConfig?: ChunkingConfig;\n}\n\n/** Generates the parameters for the private _upload_to_file_search_store method. */\nexport declare interface UploadToFileSearchStoreParameters {\n /** The resource name of the FileSearchStore. Example: `fileSearchStores/my-file-search-store-123` */\n fileSearchStoreName: string;\n /** Used to override the default configuration. */\n config?: UploadToFileSearchStoreConfig;\n}\n\n/** Response for the resumable upload method. */\nexport class UploadToFileSearchStoreResumableResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n}\n\n/** Optional parameters for importing a file. */\nexport declare interface ImportFileConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** User provided custom metadata stored as key-value pairs used for querying. */\n customMetadata?: CustomMetadata[];\n /** Config for telling the service how to chunk the file. */\n chunkingConfig?: ChunkingConfig;\n}\n\n/** Config for file_search_stores.import_file parameters. */\nexport declare interface ImportFileParameters {\n /** The resource name of the FileSearchStore. Example: `fileSearchStores/my-file-search-store-123` */\n fileSearchStoreName: string;\n /** The name of the File API File to import. Example: `files/abc-123` */\n fileName: string;\n /** Optional parameters for the request. */\n config?: ImportFileConfig;\n}\n\n/** Response for ImportFile to import a File API file with a file search store. */\nexport class ImportFileResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** The name of the FileSearchStore containing Documents. */\n parent?: string;\n /** The identifier for the Document imported. */\n documentName?: string;\n}\n\n/** Long-running operation for importing a file to a FileSearchStore. */\nexport class ImportFileOperation implements Operation<ImportFileResponse> {\n /** The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`. */\n name?: string;\n /** Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata. Any method that returns a long-running operation should document the metadata type, if any. */\n metadata?: Record<string, unknown>;\n /** If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available. */\n done?: boolean;\n /** The error result of the operation in case of failure or cancellation. */\n error?: Record<string, unknown>;\n /** The result of the ImportFile operation, available when the operation is done. */\n response?: ImportFileResponse;\n\n /**\n * Instantiates an Operation of the same type as the one being called with the fields set from the API response.\n * @internal\n */\n _fromAPIResponse({\n apiResponse,\n _isVertexAI,\n }: OperationFromAPIResponseParameters): Operation<ImportFileResponse> {\n const operation = new ImportFileOperation();\n\n const op = apiResponse as unknown as ImportFileOperation;\n const response = importFileOperationFromMldev(op);\n Object.assign(operation, response);\n return operation;\n }\n /** The full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n}\n\nexport /** Used to override the default configuration. */\ndeclare interface ListFilesConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n pageSize?: number;\n pageToken?: string;\n}\n\n/** Generates the parameters for the list method. */\nexport declare interface ListFilesParameters {\n /** Used to override the default configuration. */\n config?: ListFilesConfig;\n}\n\n/** Status of a File that uses a common error model. */\nexport declare interface FileStatus {\n /** A list of messages that carry the error details. There is a common set of message types for APIs to use. */\n details?: Record<string, unknown>[];\n /** A list of messages that carry the error details. There is a common set of message types for APIs to use. */\n message?: string;\n /** The status code. 0 for OK, 1 for CANCELLED */\n code?: number;\n}\n\n/** A file uploaded to the API. */\nexport declare interface File {\n /** The `File` resource name. The ID (name excluding the \"files/\" prefix) can contain up to 40 characters that are lowercase alphanumeric or dashes (-). The ID cannot start or end with a dash. If the name is empty on create, a unique name will be generated. Example: `files/123-456` */\n name?: string;\n /** Optional. The human-readable display name for the `File`. The display name must be no more than 512 characters in length, including spaces. Example: 'Welcome Image' */\n displayName?: string;\n /** Output only. MIME type of the file. */\n mimeType?: string;\n /** Output only. Size of the file in bytes. */\n sizeBytes?: string;\n /** Output only. The timestamp of when the `File` was created. */\n createTime?: string;\n /** Output only. The timestamp of when the `File` will be deleted. Only set if the `File` is scheduled to expire. */\n expirationTime?: string;\n /** Output only. The timestamp of when the `File` was last updated. */\n updateTime?: string;\n /** Output only. SHA-256 hash of the uploaded bytes. The hash value is encoded in base64 format. */\n sha256Hash?: string;\n /** Output only. The URI of the `File`. */\n uri?: string;\n /** Output only. The URI of the `File`, only set for downloadable (generated) files. */\n downloadUri?: string;\n /** Output only. Processing state of the File. */\n state?: FileState;\n /** Output only. The source of the `File`. */\n source?: FileSource;\n /** Output only. Metadata for a video. */\n videoMetadata?: Record<string, unknown>;\n /** Output only. Error status if File processing failed. */\n error?: FileStatus;\n}\n\n/** Response for the list files method. */\nexport class ListFilesResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** A token that can be sent as a `page_token` into a subsequent `ListFiles` call. */\n nextPageToken?: string;\n /** The list of `File`s. */\n files?: File[];\n}\n\n/** Used to override the default configuration. */\nexport declare interface CreateFileConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Generates the parameters for the private _create method. */\nexport declare interface CreateFileParameters {\n /** The file to be uploaded.\n mime_type: (Required) The MIME type of the file. Must be provided.\n name: (Optional) The name of the file in the destination (e.g.\n 'files/sample-image').\n display_name: (Optional) The display name of the file.\n */\n file: File;\n /** Used to override the default configuration. */\n config?: CreateFileConfig;\n}\n\n/** Response for the create file method. */\nexport class CreateFileResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n}\n\n/** Used to override the default configuration. */\nexport declare interface GetFileConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Generates the parameters for the get method. */\nexport declare interface GetFileParameters {\n /** The name identifier for the file to retrieve. */\n name: string;\n /** Used to override the default configuration. */\n config?: GetFileConfig;\n}\n\n/** Used to override the default configuration. */\nexport declare interface DeleteFileConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Generates the parameters for the get method. */\nexport declare interface DeleteFileParameters {\n /** The name identifier for the file to be deleted. */\n name: string;\n /** Used to override the default configuration. */\n config?: DeleteFileConfig;\n}\n\n/** Response for the delete file method. */\nexport class DeleteFileResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n}\n\n/** Used to override the default configuration. */\nexport declare interface RegisterFilesConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for the private _Register method. */\nexport declare interface InternalRegisterFilesParameters {\n /** The Google Cloud Storage URIs to register. Example: `gs://bucket/object`. */\n uris: string[];\n /** Used to override the default configuration. */\n config?: RegisterFilesConfig;\n}\n\n/** Response for the _register file method. */\nexport class RegisterFilesResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** The registered files. */\n files?: File[];\n}\n\n/** Config for inlined request. */\nexport declare interface InlinedRequest {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model?: string;\n /** Content of the request.\n */\n contents?: ContentListUnion;\n /** The metadata to be associated with the request. */\n metadata?: Record<string, string>;\n /** Configuration that contains optional model parameters.\n */\n config?: GenerateContentConfig;\n}\n\n/** Config for `src` parameter. */\nexport declare interface BatchJobSource {\n /** Storage format of the input files. Must be one of:\n 'jsonl', 'bigquery'.\n */\n format?: string;\n /** The Google Cloud Storage URIs to input files.\n */\n gcsUri?: string[];\n /** The BigQuery URI to input table.\n */\n bigqueryUri?: string;\n /** The Gemini Developer API's file resource name of the input data\n (e.g. \"files/12345\").\n */\n fileName?: string;\n /** The Gemini Developer API's inlined input data to run batch job.\n */\n inlinedRequests?: InlinedRequest[];\n}\n\n/** Job error. */\nexport declare interface JobError {\n /** A list of messages that carry the error details. There is a common set of message types for APIs to use. */\n details?: string[];\n /** The status code. */\n code?: number;\n /** A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the `details` field. */\n message?: string;\n}\n\n/** Config for `inlined_responses` parameter. */\nexport class InlinedResponse {\n /** The response to the request.\n */\n response?: GenerateContentResponse;\n /** The metadata to be associated with the request. */\n metadata?: Record<string, string>;\n /** The error encountered while processing the request.\n */\n error?: JobError;\n}\n\n/** Config for `response` parameter. */\nexport class SingleEmbedContentResponse {\n /** The response to the request.\n */\n embedding?: ContentEmbedding;\n /** The error encountered while processing the request.\n */\n tokenCount?: string;\n}\n\n/** Config for `inlined_embedding_responses` parameter. */\nexport class InlinedEmbedContentResponse {\n /** The response to the request.\n */\n response?: SingleEmbedContentResponse;\n /** The error encountered while processing the request.\n */\n error?: JobError;\n}\n\n/** Config for `des` parameter. */\nexport declare interface BatchJobDestination {\n /** Storage format of the output files. Must be one of:\n 'jsonl', 'bigquery'.\n */\n format?: string;\n /** The Google Cloud Storage URI to the output file.\n */\n gcsUri?: string;\n /** The BigQuery URI to the output table.\n */\n bigqueryUri?: string;\n /** The Gemini Developer API's file resource name of the output data\n (e.g. \"files/12345\"). The file will be a JSONL file with a single response\n per line. The responses will be GenerateContentResponse messages formatted\n as JSON. The responses will be written in the same order as the input\n requests.\n */\n fileName?: string;\n /** The responses to the requests in the batch. Returned when the batch was\n built using inlined requests. The responses will be in the same order as\n the input requests.\n */\n inlinedResponses?: InlinedResponse[];\n /** The responses to the requests in the batch. Returned when the batch was\n built using inlined requests. The responses will be in the same order as\n the input requests.\n */\n inlinedEmbedContentResponses?: InlinedEmbedContentResponse[];\n}\n\n/** Config for optional parameters. */\nexport declare interface CreateBatchJobConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** The user-defined name of this BatchJob.\n */\n displayName?: string;\n /** GCS or BigQuery URI prefix for the output predictions. Example:\n \"gs://path/to/output/data\" or \"bq://projectId.bqDatasetId.bqTableId\".\n */\n dest?: BatchJobDestinationUnion;\n}\n\n/** Config for batches.create parameters. */\nexport declare interface CreateBatchJobParameters {\n /** The name of the model to produces the predictions via the BatchJob.\n */\n model?: string;\n /** GCS URI(-s) or BigQuery URI to your input data to run batch job.\n Example: \"gs://path/to/input/data\" or \"bq://projectId.bqDatasetId.bqTableId\".\n */\n src: BatchJobSourceUnion;\n /** Optional parameters for creating a BatchJob.\n */\n config?: CreateBatchJobConfig;\n}\n\n/** Success and error statistics of processing multiple entities (for example, DataItems or structured data rows) in batch. This data type is not supported in Gemini API. */\nexport declare interface CompletionStats {\n /** Output only. The number of entities for which any error was encountered. */\n failedCount?: string;\n /** Output only. In cases when enough errors are encountered a job, pipeline, or operation may be failed as a whole. Below is the number of entities for which the processing had not been finished (either in successful or failed state). Set to -1 if the number is unknown (for example, the operation failed before the total entity number could be collected). */\n incompleteCount?: string;\n /** Output only. The number of entities that had been processed successfully. */\n successfulCount?: string;\n /** Output only. The number of the successful forecast points that are generated by the forecasting model. This is ONLY used by the forecasting batch prediction. */\n successfulForecastPointCount?: string;\n}\n\n/** Config for batches.create return value. */\nexport declare interface BatchJob {\n /** The resource name of the BatchJob. Output only.\".\n */\n name?: string;\n /** The display name of the BatchJob.\n */\n displayName?: string;\n /** The state of the BatchJob.\n */\n state?: JobState;\n /** Output only. Only populated when the job's state is JOB_STATE_FAILED or JOB_STATE_CANCELLED. */\n error?: JobError;\n /** The time when the BatchJob was created.\n */\n createTime?: string;\n /** Output only. Time when the Job for the first time entered the `JOB_STATE_RUNNING` state. */\n startTime?: string;\n /** The time when the BatchJob was completed. This field is for Vertex AI only.\n */\n endTime?: string;\n /** The time when the BatchJob was last updated.\n */\n updateTime?: string;\n /** The name of the model that produces the predictions via the BatchJob.\n */\n model?: string;\n /** Configuration for the input data. This field is for Vertex AI only.\n */\n src?: BatchJobSource;\n /** Configuration for the output data.\n */\n dest?: BatchJobDestination;\n /** Statistics on completed and failed prediction instances. This field is for Vertex AI only.\n */\n completionStats?: CompletionStats;\n}\n\n/** Parameters for the embed_content method. */\nexport declare interface EmbedContentBatch {\n /** The content to embed. Only the `parts.text` fields will be counted.\n */\n contents?: ContentListUnion;\n /** Configuration that contains optional parameters.\n */\n config?: EmbedContentConfig;\n}\n\nexport declare interface EmbeddingsBatchJobSource {\n /** The Gemini Developer API's file resource name of the input data\n (e.g. \"files/12345\").\n */\n fileName?: string;\n /** The Gemini Developer API's inlined input data to run batch job.\n */\n inlinedRequests?: EmbedContentBatch;\n}\n\n/** Config for optional parameters. */\nexport declare interface CreateEmbeddingsBatchJobConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** The user-defined name of this BatchJob.\n */\n displayName?: string;\n}\n\n/** Config for batches.create parameters. */\nexport declare interface CreateEmbeddingsBatchJobParameters {\n /** The name of the model to produces the predictions via the BatchJob.\n */\n model?: string;\n /** input data to run batch job\".\n */\n src: EmbeddingsBatchJobSource;\n /** Optional parameters for creating a BatchJob.\n */\n config?: CreateEmbeddingsBatchJobConfig;\n}\n\n/** Optional parameters. */\nexport declare interface GetBatchJobConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Config for batches.get parameters. */\nexport declare interface GetBatchJobParameters {\n /** A fully-qualified BatchJob resource name or ID.\n Example: \"projects/.../locations/.../batchPredictionJobs/456\"\n or \"456\" when project and location are initialized in the client.\n */\n name: string;\n /** Optional parameters for the request. */\n config?: GetBatchJobConfig;\n}\n\n/** Optional parameters. */\nexport declare interface CancelBatchJobConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Config for batches.cancel parameters. */\nexport declare interface CancelBatchJobParameters {\n /** A fully-qualified BatchJob resource name or ID.\n Example: \"projects/.../locations/.../batchPredictionJobs/456\"\n or \"456\" when project and location are initialized in the client.\n */\n name: string;\n /** Optional parameters for the request. */\n config?: CancelBatchJobConfig;\n}\n\n/** Config for optional parameters. */\nexport declare interface ListBatchJobsConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n pageSize?: number;\n pageToken?: string;\n filter?: string;\n}\n\n/** Config for batches.list parameters. */\nexport declare interface ListBatchJobsParameters {\n config?: ListBatchJobsConfig;\n}\n\n/** Config for batches.list return value. */\nexport class ListBatchJobsResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n nextPageToken?: string;\n batchJobs?: BatchJob[];\n}\n\n/** Optional parameters for models.get method. */\nexport declare interface DeleteBatchJobConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Config for batches.delete parameters. */\nexport declare interface DeleteBatchJobParameters {\n /** A fully-qualified BatchJob resource name or ID.\n Example: \"projects/.../locations/.../batchPredictionJobs/456\"\n or \"456\" when project and location are initialized in the client.\n */\n name: string;\n /** Optional parameters for the request. */\n config?: DeleteBatchJobConfig;\n}\n\n/** The return value of delete operation. */\nexport declare interface DeleteResourceJob {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n name?: string;\n done?: boolean;\n error?: JobError;\n}\n\nexport declare interface GetOperationConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for the GET method. */\nexport declare interface GetOperationParameters {\n /** The server-assigned name for the operation. */\n operationName: string;\n /** Used to override the default configuration. */\n config?: GetOperationConfig;\n}\n\nexport declare interface FetchPredictOperationConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for the fetchPredictOperation method. */\nexport declare interface FetchPredictOperationParameters {\n /** The server-assigned name for the operation. */\n operationName: string;\n resourceName: string;\n /** Used to override the default configuration. */\n config?: FetchPredictOperationConfig;\n}\n\nexport declare interface TestTableItem {\n /** The name of the test. This is used to derive the replay id. */\n name?: string;\n /** The parameters to the test. Use pydantic models. */\n parameters?: Record<string, unknown>;\n /** Expects an exception for MLDev matching the string. */\n exceptionIfMldev?: string;\n /** Expects an exception for Vertex matching the string. */\n exceptionIfVertex?: string;\n /** Use if you don't want to use the default replay id which is derived from the test name. */\n overrideReplayId?: string;\n /** True if the parameters contain an unsupported union type. This test will be skipped for languages that do not support the union type. */\n hasUnion?: boolean;\n /** When set to a reason string, this test will be skipped in the API mode. Use this flag for tests that can not be reproduced with the real API. E.g. a test that deletes a resource. */\n skipInApiMode?: string;\n /** Keys to ignore when comparing the request and response. This is useful for tests that are not deterministic. */\n ignoreKeys?: string[];\n}\n\nexport declare interface TestTableFile {\n comment?: string;\n testMethod?: string;\n parameterNames?: string[];\n testTable?: TestTableItem[];\n}\n\n/** Represents a single request in a replay. */\nexport declare interface ReplayRequest {\n method?: string;\n url?: string;\n headers?: Record<string, string>;\n bodySegments?: Record<string, unknown>[];\n}\n\n/** Represents a single response in a replay. */\nexport class ReplayResponse {\n statusCode?: number;\n headers?: Record<string, string>;\n bodySegments?: Record<string, unknown>[];\n sdkResponseSegments?: Record<string, unknown>[];\n}\n\n/** Represents a single interaction, request and response in a replay. */\nexport declare interface ReplayInteraction {\n request?: ReplayRequest;\n response?: ReplayResponse;\n}\n\n/** Represents a recorded session. */\nexport declare interface ReplayFile {\n replayId?: string;\n interactions?: ReplayInteraction[];\n}\n\n/** Used to override the default configuration. */\nexport declare interface UploadFileConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** The name of the file in the destination (e.g., 'files/sample-image'. If not provided one will be generated. */\n name?: string;\n /** mime_type: The MIME type of the file. If not provided, it will be inferred from the file extension. */\n mimeType?: string;\n /** Optional display name of the file. */\n displayName?: string;\n}\n\n/** Used to override the default configuration. */\nexport declare interface DownloadFileConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters used to download a file. */\nexport declare interface DownloadFileParameters {\n /** The file to download. It can be a file name, a file object or a generated video. */\n file: DownloadableFileUnion;\n /** Location where the file should be downloaded to. */\n downloadPath: string;\n /** Configuration to for the download operation. */\n config?: DownloadFileConfig;\n}\n\n/** Configuration for upscaling an image.\n\nFor more information on this configuration, refer to\nthe `Imagen API reference documentation\n<https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/imagen-api>`_. */\nexport declare interface UpscaleImageConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** Cloud Storage URI used to store the generated images. */\n outputGcsUri?: string;\n /** Filter level for safety filtering. */\n safetyFilterLevel?: SafetyFilterLevel;\n /** Allows generation of people by the model. */\n personGeneration?: PersonGeneration;\n /** Whether to include a reason for filtered-out images in the\n response. */\n includeRaiReason?: boolean;\n /** The image format that the output should be saved as. */\n outputMimeType?: string;\n /** The level of compression. Only applicable if the\n ``output_mime_type`` is ``image/jpeg``. */\n outputCompressionQuality?: number;\n /** Whether to add an image enhancing step before upscaling.\n It is expected to suppress the noise and JPEG compression artifacts\n from the input image. */\n enhanceInputImage?: boolean;\n /** With a higher image preservation factor, the original image\n pixels are more respected. With a lower image preservation factor, the\n output image will have be more different from the input image, but\n with finer details and less noise. */\n imagePreservationFactor?: number;\n /** User specified labels to track billing usage. */\n labels?: Record<string, string>;\n}\n\n/** User-facing config UpscaleImageParameters. */\nexport declare interface UpscaleImageParameters {\n /** The model to use. */\n model: string;\n /** The input image to upscale. */\n image: Image;\n /** The factor to upscale the image (x2 or x4). */\n upscaleFactor: string;\n /** Configuration for upscaling. */\n config?: UpscaleImageConfig;\n}\n\n/** A raw reference image.\n\nA raw reference image represents the base image to edit, provided by the user.\nIt can optionally be provided in addition to a mask reference image or\na style reference image. */\nexport class RawReferenceImage {\n /** The reference image for the editing operation. */\n referenceImage?: Image;\n /** The id of the reference image. */\n referenceId?: number;\n /** The type of the reference image. Only set by the SDK. */\n referenceType?: string;\n /** Internal method to convert to ReferenceImageAPIInternal. */\n toReferenceImageAPI(): ReferenceImageAPIInternal {\n const referenceImageAPI = {\n referenceType: 'REFERENCE_TYPE_RAW',\n referenceImage: this.referenceImage,\n referenceId: this.referenceId,\n };\n return referenceImageAPI;\n }\n}\n\n/** A mask reference image.\n\nThis encapsulates either a mask image provided by the user and configs for\nthe user provided mask, or only config parameters for the model to generate\na mask.\n\nA mask image is an image whose non-zero values indicate where to edit the base\nimage. If the user provides a mask image, the mask must be in the same\ndimensions as the raw image. */\nexport class MaskReferenceImage {\n /** The reference image for the editing operation. */\n referenceImage?: Image;\n /** The id of the reference image. */\n referenceId?: number;\n /** The type of the reference image. Only set by the SDK. */\n referenceType?: string;\n /** Configuration for the mask reference image. */\n config?: MaskReferenceConfig;\n /** Internal method to convert to ReferenceImageAPIInternal. */\n toReferenceImageAPI(): ReferenceImageAPIInternal {\n const referenceImageAPI = {\n referenceType: 'REFERENCE_TYPE_MASK',\n referenceImage: this.referenceImage,\n referenceId: this.referenceId,\n maskImageConfig: this.config,\n };\n return referenceImageAPI;\n }\n}\n\n/** A control reference image.\n\nThe image of the control reference image is either a control image provided\nby the user, or a regular image which the backend will use to generate a\ncontrol image of. In the case of the latter, the\nenable_control_image_computation field in the config should be set to True.\n\nA control image is an image that represents a sketch image of areas for the\nmodel to fill in based on the prompt. */\nexport class ControlReferenceImage {\n /** The reference image for the editing operation. */\n referenceImage?: Image;\n /** The id of the reference image. */\n referenceId?: number;\n /** The type of the reference image. Only set by the SDK. */\n referenceType?: string;\n /** Configuration for the control reference image. */\n config?: ControlReferenceConfig;\n /** Internal method to convert to ReferenceImageAPIInternal. */\n toReferenceImageAPI(): ReferenceImageAPIInternal {\n const referenceImageAPI = {\n referenceType: 'REFERENCE_TYPE_CONTROL',\n referenceImage: this.referenceImage,\n referenceId: this.referenceId,\n controlImageConfig: this.config,\n };\n return referenceImageAPI;\n }\n}\n\n/** A style reference image.\n\nThis encapsulates a style reference image provided by the user, and\nadditionally optional config parameters for the style reference image.\n\nA raw reference image can also be provided as a destination for the style to\nbe applied to. */\nexport class StyleReferenceImage {\n /** The reference image for the editing operation. */\n referenceImage?: Image;\n /** The id of the reference image. */\n referenceId?: number;\n /** The type of the reference image. Only set by the SDK. */\n referenceType?: string;\n /** Configuration for the style reference image. */\n config?: StyleReferenceConfig;\n /** Internal method to convert to ReferenceImageAPIInternal. */\n toReferenceImageAPI(): ReferenceImageAPIInternal {\n const referenceImageAPI = {\n referenceType: 'REFERENCE_TYPE_STYLE',\n referenceImage: this.referenceImage,\n referenceId: this.referenceId,\n styleImageConfig: this.config,\n };\n return referenceImageAPI;\n }\n}\n\n/** A subject reference image.\n\nThis encapsulates a subject reference image provided by the user, and\nadditionally optional config parameters for the subject reference image.\n\nA raw reference image can also be provided as a destination for the subject to\nbe applied to. */\nexport class SubjectReferenceImage {\n /** The reference image for the editing operation. */\n referenceImage?: Image;\n /** The id of the reference image. */\n referenceId?: number;\n /** The type of the reference image. Only set by the SDK. */\n referenceType?: string;\n /** Configuration for the subject reference image. */\n config?: SubjectReferenceConfig;\n /* Internal method to convert to ReferenceImageAPIInternal. */\n toReferenceImageAPI(): ReferenceImageAPIInternal {\n const referenceImageAPI = {\n referenceType: 'REFERENCE_TYPE_SUBJECT',\n referenceImage: this.referenceImage,\n referenceId: this.referenceId,\n subjectImageConfig: this.config,\n };\n return referenceImageAPI;\n }\n}\n\n/** A content reference image.\n\nA content reference image represents a subject to reference (ex. person,\nproduct, animal) provided by the user. It can optionally be provided in\naddition to a style reference image (ex. background, style reference). */\nexport class ContentReferenceImage {\n /** The reference image for the editing operation. */\n referenceImage?: Image;\n /** The id of the reference image. */\n referenceId?: number;\n /** The type of the reference image. Only set by the SDK. */\n referenceType?: string;\n /** Internal method to convert to ReferenceImageAPIInternal. */\n toReferenceImageAPI(): ReferenceImageAPIInternal {\n const referenceImageAPI = {\n referenceType: 'REFERENCE_TYPE_CONTENT',\n referenceImage: this.referenceImage,\n referenceId: this.referenceId,\n };\n return referenceImageAPI;\n }\n}\n\n/** Sent in response to a `LiveGenerateContentSetup` message from the client. */\nexport declare interface LiveServerSetupComplete {\n /** The session id of the live session. */\n sessionId?: string;\n}\n\n/** Audio transcription in Server Conent. */\nexport declare interface Transcription {\n /** Transcription text.\n */\n text?: string;\n /** The bool indicates the end of the transcription.\n */\n finished?: boolean;\n}\n\n/** Incremental server update generated by the model in response to client messages.\n\nContent is generated as quickly as possible, and not in real time. Clients\nmay choose to buffer and play it out in real time. */\nexport declare interface LiveServerContent {\n /** The content that the model has generated as part of the current conversation with the user. */\n modelTurn?: Content;\n /** If true, indicates that the model is done generating. Generation will only start in response to additional client messages. Can be set alongside `content`, indicating that the `content` is the last in the turn. */\n turnComplete?: boolean;\n /** If true, indicates that a client message has interrupted current model generation. If the client is playing out the content in realtime, this is a good signal to stop and empty the current queue. */\n interrupted?: boolean;\n /** Metadata returned to client when grounding is enabled. */\n groundingMetadata?: GroundingMetadata;\n /** If true, indicates that the model is done generating. When model is\n interrupted while generating there will be no generation_complete message\n in interrupted turn, it will go through interrupted > turn_complete.\n When model assumes realtime playback there will be delay between\n generation_complete and turn_complete that is caused by model\n waiting for playback to finish. If true, indicates that the model\n has finished generating all content. This is a signal to the client\n that it can stop sending messages. */\n generationComplete?: boolean;\n /** Input transcription. The transcription is independent to the model\n turn which means it doesn’t imply any ordering between transcription and\n model turn. */\n inputTranscription?: Transcription;\n /** Output transcription. The transcription is independent to the model\n turn which means it doesn’t imply any ordering between transcription and\n model turn.\n */\n outputTranscription?: Transcription;\n /** Metadata related to url context retrieval tool. */\n urlContextMetadata?: UrlContextMetadata;\n /** Reason for the turn is complete. */\n turnCompleteReason?: TurnCompleteReason;\n /** If true, indicates that the model is not generating content because\n it is waiting for more input from the user, e.g. because it expects the\n user to continue talking. */\n waitingForInput?: boolean;\n}\n\n/** Request for the client to execute the `function_calls` and return the responses with the matching `id`s. */\nexport declare interface LiveServerToolCall {\n /** The function call to be executed. */\n functionCalls?: FunctionCall[];\n}\n\n/** Notification for the client that a previously issued `ToolCallMessage` with the specified `id`s should have been not executed and should be cancelled.\n\nIf there were side-effects to those tool calls, clients may attempt to undo\nthe tool calls. This message occurs only in cases where the clients interrupt\nserver turns. */\nexport declare interface LiveServerToolCallCancellation {\n /** The ids of the tool calls to be cancelled. */\n ids?: string[];\n}\n\n/** Usage metadata about response(s). */\nexport declare interface UsageMetadata {\n /** Number of tokens in the prompt. When `cached_content` is set, this is still the total effective prompt size meaning this includes the number of tokens in the cached content. */\n promptTokenCount?: number;\n /** Number of tokens in the cached part of the prompt (the cached content). */\n cachedContentTokenCount?: number;\n /** Total number of tokens across all the generated response candidates. */\n responseTokenCount?: number;\n /** Number of tokens present in tool-use prompt(s). */\n toolUsePromptTokenCount?: number;\n /** Number of tokens of thoughts for thinking models. */\n thoughtsTokenCount?: number;\n /** Total token count for prompt, response candidates, and tool-use prompts(if present). */\n totalTokenCount?: number;\n /** List of modalities that were processed in the request input. */\n promptTokensDetails?: ModalityTokenCount[];\n /** List of modalities that were processed in the cache input. */\n cacheTokensDetails?: ModalityTokenCount[];\n /** List of modalities that were returned in the response. */\n responseTokensDetails?: ModalityTokenCount[];\n /** List of modalities that were processed in the tool-use prompt. */\n toolUsePromptTokensDetails?: ModalityTokenCount[];\n /** Traffic type. This shows whether a request consumes Pay-As-You-Go\n or Provisioned Throughput quota. */\n trafficType?: TrafficType;\n}\n\n/** Server will not be able to service client soon. */\nexport declare interface LiveServerGoAway {\n /** The remaining time before the connection will be terminated as ABORTED. The minimal time returned here is specified differently together with the rate limits for a given model. */\n timeLeft?: string;\n}\n\n/** Update of the session resumption state.\n\nOnly sent if `session_resumption` was set in the connection config. */\nexport declare interface LiveServerSessionResumptionUpdate {\n /** New handle that represents state that can be resumed. Empty if `resumable`=false. */\n newHandle?: string;\n /** True if session can be resumed at this point. It might be not possible to resume session at some points. In that case we send update empty new_handle and resumable=false. Example of such case could be model executing function calls or just generating. Resuming session (using previous session token) in such state will result in some data loss. */\n resumable?: boolean;\n /** Index of last message sent by client that is included in state represented by this SessionResumptionToken. Only sent when `SessionResumptionConfig.transparent` is set.\n\nPresence of this index allows users to transparently reconnect and avoid issue of losing some part of realtime audio input/video. If client wishes to temporarily disconnect (for example as result of receiving GoAway) they can do it without losing state by buffering messages sent since last `SessionResmumptionTokenUpdate`. This field will enable them to limit buffering (avoid keeping all requests in RAM).\n\nNote: This should not be used for when resuming a session at some time later -- in those cases partial audio and video frames arelikely not needed. */\n lastConsumedClientMessageIndex?: string;\n}\n\nexport declare interface VoiceActivityDetectionSignal {\n /** The type of the VAD signal. */\n vadSignalType?: VadSignalType;\n}\n\n/** Voice activity signal. */\nexport declare interface VoiceActivity {\n /** The type of the voice activity signal. */\n voiceActivityType?: VoiceActivityType;\n}\n\n/** Response message for API call. */\nexport class LiveServerMessage {\n /** Sent in response to a `LiveClientSetup` message from the client. */\n setupComplete?: LiveServerSetupComplete;\n /** Content generated by the model in response to client messages. */\n serverContent?: LiveServerContent;\n /** Request for the client to execute the `function_calls` and return the responses with the matching `id`s. */\n toolCall?: LiveServerToolCall;\n /** Notification for the client that a previously issued `ToolCallMessage` with the specified `id`s should have been not executed and should be cancelled. */\n toolCallCancellation?: LiveServerToolCallCancellation;\n /** Usage metadata about model response(s). */\n usageMetadata?: UsageMetadata;\n /** Server will disconnect soon. */\n goAway?: LiveServerGoAway;\n /** Update of the session resumption state. */\n sessionResumptionUpdate?: LiveServerSessionResumptionUpdate;\n /** Voice activity detection signal. Allowlisted only. */\n voiceActivityDetectionSignal?: VoiceActivityDetectionSignal;\n /** Voice activity signal. */\n voiceActivity?: VoiceActivity;\n /**\n * Returns the concatenation of all text parts from the server content if present.\n *\n * @remarks\n * If there are non-text parts in the response, the concatenation of all text\n * parts will be returned, and a warning will be logged.\n */\n get text(): string | undefined {\n let text = '';\n let anyTextPartFound = false;\n const nonTextParts = [];\n for (const part of this.serverContent?.modelTurn?.parts ?? []) {\n for (const [fieldName, fieldValue] of Object.entries(part)) {\n if (\n fieldName !== 'text' &&\n fieldName !== 'thought' &&\n fieldValue !== null\n ) {\n nonTextParts.push(fieldName);\n }\n }\n if (typeof part.text === 'string') {\n if (typeof part.thought === 'boolean' && part.thought) {\n continue;\n }\n anyTextPartFound = true;\n text += part.text;\n }\n }\n if (nonTextParts.length > 0) {\n console.warn(\n `there are non-text parts ${nonTextParts} in the response, returning concatenation of all text parts. Please refer to the non text parts for a full response from model.`,\n );\n }\n // part.text === '' is different from part.text is null\n return anyTextPartFound ? text : undefined;\n }\n\n /**\n * Returns the concatenation of all inline data parts from the server content if present.\n *\n * @remarks\n * If there are non-inline data parts in the\n * response, the concatenation of all inline data parts will be returned, and\n * a warning will be logged.\n */\n get data(): string | undefined {\n let data = '';\n const nonDataParts = [];\n for (const part of this.serverContent?.modelTurn?.parts ?? []) {\n for (const [fieldName, fieldValue] of Object.entries(part)) {\n if (fieldName !== 'inlineData' && fieldValue !== null) {\n nonDataParts.push(fieldName);\n }\n }\n if (part.inlineData && typeof part.inlineData.data === 'string') {\n data += atob(part.inlineData.data);\n }\n }\n if (nonDataParts.length > 0) {\n console.warn(\n `there are non-data parts ${nonDataParts} in the response, returning concatenation of all data parts. Please refer to the non data parts for a full response from model.`,\n );\n }\n return data.length > 0 ? btoa(data) : undefined;\n }\n}\n\n/** Parameters of the fromAPIResponse method of the Operation class. */\nexport declare interface OperationFromAPIResponseParameters {\n /** The API response to be converted to an Operation. */\n apiResponse: Record<string, unknown>;\n /** Whether the API response is from Vertex AI. */\n _isVertexAI: boolean;\n}\n\n/**\n * Config for thinking feature.\n *\n * @deprecated This interface will be deprecated. Please use `ThinkingConfig` instead.\n */\nexport declare interface GenerationConfigThinkingConfig\n extends ThinkingConfig {}\n\n/** Generates the parameters for the private registerFiles method. */\nexport declare interface RegisterFilesParameters {\n /**\n * The authentication object.\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n auth?: any;\n /**\n * The Google Cloud Storage URIs to register. Example: `gs://bucket/object`.\n */\n uris: string[];\n /** Used to override the default configuration. */\n config?: RegisterFilesConfig;\n}\n\n/** Configures automatic detection of activity. */\nexport declare interface AutomaticActivityDetection {\n /** If enabled, detected voice and text input count as activity. If disabled, the client must send activity signals. */\n disabled?: boolean;\n /** Determines how likely speech is to be detected. */\n startOfSpeechSensitivity?: StartSensitivity;\n /** Determines how likely detected speech is ended. */\n endOfSpeechSensitivity?: EndSensitivity;\n /** The required duration of detected speech before start-of-speech is committed. The lower this value the more sensitive the start-of-speech detection is and the shorter speech can be recognized. However, this also increases the probability of false positives. */\n prefixPaddingMs?: number;\n /** The required duration of detected non-speech (e.g. silence) before end-of-speech is committed. The larger this value, the longer speech gaps can be without interrupting the user's activity but this will increase the model's latency. */\n silenceDurationMs?: number;\n}\n\n/** Marks the end of user activity.\n\nThis can only be sent if automatic (i.e. server-side) activity detection is\ndisabled. */\nexport declare interface RealtimeInputConfig {\n /** If not set, automatic activity detection is enabled by default. If automatic voice detection is disabled, the client must send activity signals. */\n automaticActivityDetection?: AutomaticActivityDetection;\n /** Defines what effect activity has. */\n activityHandling?: ActivityHandling;\n /** Defines which input is included in the user's turn. */\n turnCoverage?: TurnCoverage;\n}\n\n/** Configuration of session resumption mechanism.\n\nIncluded in `LiveConnectConfig.session_resumption`. If included server\nwill send `LiveServerSessionResumptionUpdate` messages. */\nexport declare interface SessionResumptionConfig {\n /** Session resumption handle of previous session (session to restore).\n\nIf not present new session will be started. */\n handle?: string;\n /** If set the server will send `last_consumed_client_message_index` in the `session_resumption_update` messages to allow for transparent reconnections. */\n transparent?: boolean;\n}\n\n/** Context window will be truncated by keeping only suffix of it.\n\nContext window will always be cut at start of USER role turn. System\ninstructions and `BidiGenerateContentSetup.prefix_turns` will not be\nsubject to the sliding window mechanism, they will always stay at the\nbeginning of context window. */\nexport declare interface SlidingWindow {\n /** Session reduction target -- how many tokens we should keep. Window shortening operation has some latency costs, so we should avoid running it on every turn. Should be < trigger_tokens. If not set, trigger_tokens/2 is assumed. */\n targetTokens?: string;\n}\n\n/** Enables context window compression -- mechanism managing model context window so it does not exceed given length. */\nexport declare interface ContextWindowCompressionConfig {\n /** Number of tokens (before running turn) that triggers context window compression mechanism. */\n triggerTokens?: string;\n /** Sliding window compression mechanism. */\n slidingWindow?: SlidingWindow;\n}\n\n/** The audio transcription configuration in Setup. */\nexport declare interface AudioTranscriptionConfig {}\n\n/** Config for proactivity features. */\nexport declare interface ProactivityConfig {\n /** If enabled, the model can reject responding to the last prompt. For\n example, this allows the model to ignore out of context speech or to stay\n silent if the user did not make a request, yet. */\n proactiveAudio?: boolean;\n}\n\n/** Message contains configuration that will apply for the duration of the streaming session. */\nexport declare interface LiveClientSetup {\n /** \n The fully qualified name of the publisher model or tuned model endpoint to\n use.\n */\n model?: string;\n /** The generation configuration for the session.\n Note: only a subset of fields are supported.\n */\n generationConfig?: GenerationConfig;\n /** The user provided system instructions for the model.\n Note: only text should be used in parts and content in each part will be\n in a separate paragraph. */\n systemInstruction?: ContentUnion;\n /** A list of `Tools` the model may use to generate the next response.\n\n A `Tool` is a piece of code that enables the system to interact with\n external systems to perform an action, or set of actions, outside of\n knowledge and scope of the model. */\n tools?: ToolListUnion;\n /** Configures the realtime input behavior in BidiGenerateContent. */\n realtimeInputConfig?: RealtimeInputConfig;\n /** Configures session resumption mechanism.\n\n If included server will send SessionResumptionUpdate messages. */\n sessionResumption?: SessionResumptionConfig;\n /** Configures context window compression mechanism.\n\n If included, server will compress context window to fit into given length. */\n contextWindowCompression?: ContextWindowCompressionConfig;\n /** The transcription of the input aligns with the input audio language.\n */\n inputAudioTranscription?: AudioTranscriptionConfig;\n /** The transcription of the output aligns with the language code\n specified for the output audio.\n */\n outputAudioTranscription?: AudioTranscriptionConfig;\n /** Configures the proactivity of the model. This allows the model to respond proactively to\n the input and to ignore irrelevant input. */\n proactivity?: ProactivityConfig;\n /** Configures the explicit VAD signal. If enabled, the client will send\n vad_signal to indicate the start and end of speech. This allows the server\n to process the audio more efficiently. */\n explicitVadSignal?: boolean;\n}\n\n/** Incremental update of the current conversation delivered from the client.\n\nAll the content here will unconditionally be appended to the conversation\nhistory and used as part of the prompt to the model to generate content.\n\nA message here will interrupt any current model generation. */\nexport declare interface LiveClientContent {\n /** The content appended to the current conversation with the model.\n\n For single-turn queries, this is a single instance. For multi-turn\n queries, this is a repeated field that contains conversation history and\n latest request.\n */\n turns?: Content[];\n /** If true, indicates that the server content generation should start with\n the currently accumulated prompt. Otherwise, the server will await\n additional messages before starting generation. */\n turnComplete?: boolean;\n}\n\n/** Marks the start of user activity.\n\nThis can only be sent if automatic (i.e. server-side) activity detection is\ndisabled. */\nexport declare interface ActivityStart {}\n\n/** Marks the end of user activity.\n\nThis can only be sent if automatic (i.e. server-side) activity detection is\ndisabled. */\nexport declare interface ActivityEnd {}\n\n/** User input that is sent in real time.\n\nThis is different from `LiveClientContent` in a few ways:\n\n - Can be sent continuously without interruption to model generation.\n - If there is a need to mix data interleaved across the\n `LiveClientContent` and the `LiveClientRealtimeInput`, server attempts to\n optimize for best response, but there are no guarantees.\n - End of turn is not explicitly specified, but is rather derived from user\n activity (for example, end of speech).\n - Even before the end of turn, the data is processed incrementally\n to optimize for a fast start of the response from the model.\n - Is always assumed to be the user's input (cannot be used to populate\n conversation history). */\nexport declare interface LiveClientRealtimeInput {\n /** Inlined bytes data for media input. */\n mediaChunks?: Blob[];\n /** The realtime audio input stream. */\n audio?: Blob;\n /** \nIndicates that the audio stream has ended, e.g. because the microphone was\nturned off.\n\nThis should only be sent when automatic activity detection is enabled\n(which is the default).\n\nThe client can reopen the stream by sending an audio message.\n */\n audioStreamEnd?: boolean;\n /** The realtime video input stream. */\n video?: Blob;\n /** The realtime text input stream. */\n text?: string;\n /** Marks the start of user activity. */\n activityStart?: ActivityStart;\n /** Marks the end of user activity. */\n activityEnd?: ActivityEnd;\n}\n\n/** Client generated response to a `ToolCall` received from the server.\n\nIndividual `FunctionResponse` objects are matched to the respective\n`FunctionCall` objects by the `id` field.\n\nNote that in the unary and server-streaming GenerateContent APIs function\ncalling happens by exchanging the `Content` parts, while in the bidi\nGenerateContent APIs function calling happens over this dedicated set of\nmessages. */\nexport class LiveClientToolResponse {\n /** The response to the function calls. */\n functionResponses?: FunctionResponse[];\n}\n\n/** Parameters for sending realtime input to the live API. */\nexport declare interface LiveSendRealtimeInputParameters {\n /** Realtime input to send to the session. */\n media?: BlobImageUnion;\n /** The realtime audio input stream. */\n audio?: Blob;\n /** \nIndicates that the audio stream has ended, e.g. because the microphone was\nturned off.\n\nThis should only be sent when automatic activity detection is enabled\n(which is the default).\n\nThe client can reopen the stream by sending an audio message.\n */\n audioStreamEnd?: boolean;\n /** The realtime video input stream. */\n video?: BlobImageUnion;\n /** The realtime text input stream. */\n text?: string;\n /** Marks the start of user activity. */\n activityStart?: ActivityStart;\n /** Marks the end of user activity. */\n activityEnd?: ActivityEnd;\n}\n\n/** Messages sent by the client in the API call. */\nexport declare interface LiveClientMessage {\n /** Message to be sent by the system when connecting to the API. SDK users should not send this message. */\n setup?: LiveClientSetup;\n /** Incremental update of the current conversation delivered from the client. */\n clientContent?: LiveClientContent;\n /** User input that is sent in real time. */\n realtimeInput?: LiveClientRealtimeInput;\n /** Response to a `ToolCallMessage` received from the server. */\n toolResponse?: LiveClientToolResponse;\n}\n\n/** Session config for the API connection. */\nexport declare interface LiveConnectConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** The generation configuration for the session. */\n generationConfig?: GenerationConfig;\n /** The requested modalities of the response. Represents the set of\n modalities that the model can return. Defaults to AUDIO if not specified.\n */\n responseModalities?: Modality[];\n /** Value that controls the degree of randomness in token selection.\n Lower temperatures are good for prompts that require a less open-ended or\n creative response, while higher temperatures can lead to more diverse or\n creative results.\n */\n temperature?: number;\n /** Tokens are selected from the most to least probable until the sum\n of their probabilities equals this value. Use a lower value for less\n random responses and a higher value for more random responses.\n */\n topP?: number;\n /** For each token selection step, the ``top_k`` tokens with the\n highest probabilities are sampled. Then tokens are further filtered based\n on ``top_p`` with the final token selected using temperature sampling. Use\n a lower number for less random responses and a higher number for more\n random responses.\n */\n topK?: number;\n /** Maximum number of tokens that can be generated in the response.\n */\n maxOutputTokens?: number;\n /** If specified, the media resolution specified will be used.\n */\n mediaResolution?: MediaResolution;\n /** When ``seed`` is fixed to a specific number, the model makes a best\n effort to provide the same response for repeated requests. By default, a\n random number is used.\n */\n seed?: number;\n /** The speech generation configuration.\n */\n speechConfig?: SpeechConfig;\n /** Config for thinking features.\n An error will be returned if this field is set for models that don't\n support thinking.\n */\n thinkingConfig?: ThinkingConfig;\n /** If enabled, the model will detect emotions and adapt its responses accordingly. */\n enableAffectiveDialog?: boolean;\n /** The user provided system instructions for the model.\n Note: only text should be used in parts and content in each part will be\n in a separate paragraph. */\n systemInstruction?: ContentUnion;\n /** A list of `Tools` the model may use to generate the next response.\n\n A `Tool` is a piece of code that enables the system to interact with\n external systems to perform an action, or set of actions, outside of\n knowledge and scope of the model. */\n tools?: ToolListUnion;\n /** Configures session resumption mechanism.\n\nIf included the server will send SessionResumptionUpdate messages. */\n sessionResumption?: SessionResumptionConfig;\n /** The transcription of the input aligns with the input audio language.\n */\n inputAudioTranscription?: AudioTranscriptionConfig;\n /** The transcription of the output aligns with the language code\n specified for the output audio.\n */\n outputAudioTranscription?: AudioTranscriptionConfig;\n /** Configures the realtime input behavior in BidiGenerateContent. */\n realtimeInputConfig?: RealtimeInputConfig;\n /** Configures context window compression mechanism.\n\n If included, server will compress context window to fit into given length. */\n contextWindowCompression?: ContextWindowCompressionConfig;\n /** Configures the proactivity of the model. This allows the model to respond proactively to\n the input and to ignore irrelevant input. */\n proactivity?: ProactivityConfig;\n /** Configures the explicit VAD signal. If enabled, the client will send\n vad_signal to indicate the start and end of speech. This allows the server\n to process the audio more efficiently. */\n explicitVadSignal?: boolean;\n}\n\n/** Parameters for connecting to the live API. */\nexport declare interface LiveConnectParameters {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model: string;\n /** callbacks */\n callbacks: LiveCallbacks;\n /** Optional configuration parameters for the request.\n */\n config?: LiveConnectConfig;\n}\n\n/** Parameters for initializing a new chat session.\n\nThese parameters are used when creating a chat session with the\n`chats.create()` method. */\nexport declare interface CreateChatParameters {\n /** The name of the model to use for the chat session.\n\n For example: 'gemini-2.0-flash', 'gemini-2.0-flash-lite', etc. See Gemini API\n docs to find the available models.\n */\n model: string;\n /** Config for the entire chat session.\n\n This config applies to all requests within the session\n unless overridden by a per-request `config` in `SendMessageParameters`.\n */\n config?: GenerateContentConfig;\n /** The initial conversation history for the chat session.\n\n This allows you to start the chat with a pre-existing history. The history\n must be a list of `Content` alternating between 'user' and 'model' roles.\n It should start with a 'user' message.\n */\n history?: Content[];\n}\n\n/** Parameters for sending a message within a chat session.\n\nThese parameters are used with the `chat.sendMessage()` method. */\nexport declare interface SendMessageParameters {\n /** The message to send to the model.\n\n The SDK will combine all parts into a single 'user' content to send to\n the model.\n */\n message: PartListUnion;\n /** Config for this specific request.\n\n Please note that the per-request config does not change the chat level\n config, nor inherit from it. If you intend to use some values from the\n chat's default config, you must explicitly copy them into this per-request\n config.\n */\n config?: GenerateContentConfig;\n}\n\n/** Parameters for sending client content to the live API. */\nexport declare interface LiveSendClientContentParameters {\n /** Client content to send to the session. */\n turns?: ContentListUnion;\n /** If true, indicates that the server content generation should start with\n the currently accumulated prompt. Otherwise, the server will await\n additional messages before starting generation. */\n turnComplete?: boolean;\n}\n\n/** Parameters for sending tool responses to the live API. */\nexport class LiveSendToolResponseParameters {\n /** Tool responses to send to the session. */\n functionResponses: FunctionResponse[] | FunctionResponse = [];\n}\n\n/** Message to be sent by the system when connecting to the API. */\nexport declare interface LiveMusicClientSetup {\n /** The model's resource name. Format: `models/{model}`. */\n model?: string;\n}\n\n/** Maps a prompt to a relative weight to steer music generation. */\nexport declare interface WeightedPrompt {\n /** Text prompt. */\n text?: string;\n /** Weight of the prompt. The weight is used to control the relative\n importance of the prompt. Higher weights are more important than lower\n weights.\n\n Weight must not be 0. Weights of all weighted_prompts in this\n LiveMusicClientContent message will be normalized. */\n weight?: number;\n}\n\n/** User input to start or steer the music. */\nexport declare interface LiveMusicClientContent {\n /** Weighted prompts as the model input. */\n weightedPrompts?: WeightedPrompt[];\n}\n\n/** Configuration for music generation. */\nexport declare interface LiveMusicGenerationConfig {\n /** Controls the variance in audio generation. Higher values produce\n higher variance. Range is [0.0, 3.0]. */\n temperature?: number;\n /** Controls how the model selects tokens for output. Samples the topK\n tokens with the highest probabilities. Range is [1, 1000]. */\n topK?: number;\n /** Seeds audio generation. If not set, the request uses a randomly\n generated seed. */\n seed?: number;\n /** Controls how closely the model follows prompts.\n Higher guidance follows more closely, but will make transitions more\n abrupt. Range is [0.0, 6.0]. */\n guidance?: number;\n /** Beats per minute. Range is [60, 200]. */\n bpm?: number;\n /** Density of sounds. Range is [0.0, 1.0]. */\n density?: number;\n /** Brightness of the music. Range is [0.0, 1.0]. */\n brightness?: number;\n /** Scale of the generated music. */\n scale?: Scale;\n /** Whether the audio output should contain bass. */\n muteBass?: boolean;\n /** Whether the audio output should contain drums. */\n muteDrums?: boolean;\n /** Whether the audio output should contain only bass and drums. */\n onlyBassAndDrums?: boolean;\n /** The mode of music generation. Default mode is QUALITY. */\n musicGenerationMode?: MusicGenerationMode;\n}\n\n/** Messages sent by the client in the LiveMusicClientMessage call. */\nexport declare interface LiveMusicClientMessage {\n /** Message to be sent in the first (and only in the first) `LiveMusicClientMessage`.\n Clients should wait for a `LiveMusicSetupComplete` message before\n sending any additional messages. */\n setup?: LiveMusicClientSetup;\n /** User input to influence music generation. */\n clientContent?: LiveMusicClientContent;\n /** Configuration for music generation. */\n musicGenerationConfig?: LiveMusicGenerationConfig;\n /** Playback control signal for the music generation. */\n playbackControl?: LiveMusicPlaybackControl;\n}\n\n/** Sent in response to a `LiveMusicClientSetup` message from the client. */\nexport declare interface LiveMusicServerSetupComplete {}\n\n/** Prompts and config used for generating this audio chunk. */\nexport declare interface LiveMusicSourceMetadata {\n /** Weighted prompts for generating this audio chunk. */\n clientContent?: LiveMusicClientContent;\n /** Music generation config for generating this audio chunk. */\n musicGenerationConfig?: LiveMusicGenerationConfig;\n}\n\n/** Representation of an audio chunk. */\nexport declare interface AudioChunk {\n /** Raw bytes of audio data.\n * @remarks Encoded as base64 string. */\n data?: string;\n /** MIME type of the audio chunk. */\n mimeType?: string;\n /** Prompts and config used for generating this audio chunk. */\n sourceMetadata?: LiveMusicSourceMetadata;\n}\n\n/** Server update generated by the model in response to client messages.\n\nContent is generated as quickly as possible, and not in real time.\nClients may choose to buffer and play it out in real time. */\nexport declare interface LiveMusicServerContent {\n /** The audio chunks that the model has generated. */\n audioChunks?: AudioChunk[];\n}\n\n/** A prompt that was filtered with the reason. */\nexport declare interface LiveMusicFilteredPrompt {\n /** The text prompt that was filtered. */\n text?: string;\n /** The reason the prompt was filtered. */\n filteredReason?: string;\n}\n\n/** Response message for the LiveMusicClientMessage call. */\nexport class LiveMusicServerMessage {\n /** Message sent in response to a `LiveMusicClientSetup` message from the client.\n Clients should wait for this message before sending any additional messages. */\n setupComplete?: LiveMusicServerSetupComplete;\n /** Content generated by the model in response to client messages. */\n serverContent?: LiveMusicServerContent;\n /** A prompt that was filtered with the reason. */\n filteredPrompt?: LiveMusicFilteredPrompt;\n /**\n * Returns the first audio chunk from the server content, if present.\n *\n * @remarks\n * If there are no audio chunks in the response, undefined will be returned.\n */\n get audioChunk(): AudioChunk | undefined {\n if (\n this.serverContent &&\n this.serverContent.audioChunks &&\n this.serverContent.audioChunks.length > 0\n ) {\n return this.serverContent.audioChunks[0];\n }\n return undefined;\n }\n}\n\n/** Callbacks for the realtime music API. */\nexport interface LiveMusicCallbacks {\n /**\n * Called when a message is received from the server.\n */\n onmessage: (e: LiveMusicServerMessage) => void;\n /**\n * Called when an error occurs.\n */\n onerror?: ((e: ErrorEvent) => void) | null;\n /**\n * Called when the websocket connection is closed.\n */\n onclose?: ((e: CloseEvent) => void) | null;\n}\n\n/** Parameters for the upload file method. */\nexport interface UploadFileParameters {\n /** The string path to the file to be uploaded or a Blob object. */\n file: string | globalThis.Blob;\n /** Configuration that contains optional parameters. */\n config?: UploadFileConfig;\n}\n\n/** Parameters for the upload file to file search store method. */\nexport interface UploadToFileSearchStoreParameters {\n /** The name of the file search store to upload. */\n fileSearchStoreName: string;\n /** The string path to the file to be uploaded or a Blob object. */\n file: string | globalThis.Blob;\n /** Configuration that contains optional parameters. */\n config?: UploadToFileSearchStoreConfig;\n}\n\n/**\n * CallableTool is an invokable tool that can be executed with external\n * application (e.g., via Model Context Protocol) or local functions with\n * function calling.\n */\nexport interface CallableTool {\n /**\n * Returns tool that can be called by Gemini.\n */\n tool(): Promise<Tool>;\n /**\n * Executes the callable tool with the given function call arguments and\n * returns the response parts from the tool execution.\n */\n callTool(functionCalls: FunctionCall[]): Promise<Part[]>;\n}\n\n/**\n * CallableToolConfig is the configuration for a callable tool.\n */\nexport interface CallableToolConfig {\n /**\n * Specifies the model's behavior after invoking this tool.\n */\n behavior?: Behavior;\n /**\n * Timeout for remote calls in milliseconds. Note this timeout applies only to\n * tool remote calls, and not making HTTP requests to the API. */\n timeout?: number;\n}\n\n/** Parameters for connecting to the live API. */\nexport declare interface LiveMusicConnectParameters {\n /** The model's resource name. */\n model: string;\n /** Callbacks invoked on server events. */\n callbacks: LiveMusicCallbacks;\n}\n\n/** Parameters for setting config for the live music API. */\nexport declare interface LiveMusicSetConfigParameters {\n /** Configuration for music generation. */\n musicGenerationConfig: LiveMusicGenerationConfig;\n}\n\n/** Parameters for setting weighted prompts for the live music API. */\nexport declare interface LiveMusicSetWeightedPromptsParameters {\n /** A map of text prompts to weights to use for the generation request. */\n weightedPrompts: WeightedPrompt[];\n}\n\n/** Config for auth_tokens.create parameters. */\nexport declare interface AuthToken {\n /** The name of the auth token. */\n name?: string;\n}\n\n/** Config for LiveConnectConstraints for Auth Token creation. */\nexport declare interface LiveConnectConstraints {\n /** ID of the model to configure in the ephemeral token for Live API.\n For a list of models, see `Gemini models\n <https://ai.google.dev/gemini-api/docs/models>`. */\n model?: string;\n /** Configuration specific to Live API connections created using this token. */\n config?: LiveConnectConfig;\n}\n\n/** Optional parameters. */\nexport declare interface CreateAuthTokenConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** An optional time after which, when using the resulting token,\n messages in Live API sessions will be rejected. (Gemini may\n preemptively close the session after this time.)\n\n If not set then this defaults to 30 minutes in the future. If set, this\n value must be less than 20 hours in the future. */\n expireTime?: string;\n /** The time after which new Live API sessions using the token\n resulting from this request will be rejected.\n\n If not set this defaults to 60 seconds in the future. If set, this value\n must be less than 20 hours in the future. */\n newSessionExpireTime?: string;\n /** The number of times the token can be used. If this value is zero\n then no limit is applied. Default is 1. Resuming a Live API session does\n not count as a use. */\n uses?: number;\n /** Configuration specific to Live API connections created using this token. */\n liveConnectConstraints?: LiveConnectConstraints;\n /** Additional fields to lock in the effective LiveConnectParameters. */\n lockAdditionalFields?: string[];\n}\n\n/** Config for auth_tokens.create parameters. */\nexport declare interface CreateAuthTokenParameters {\n /** Optional parameters for the request. */\n config?: CreateAuthTokenConfig;\n}\n\n/** Parameters for the get method of the operations module. */\nexport declare interface OperationGetParameters<T, U extends Operation<T>> {\n /** Used to override the default configuration. */\n config?: GetOperationConfig;\n /** The operation to be retrieved. */\n operation: U;\n}\n\n/** Local tokenizer count tokens result. */\nexport declare interface CountTokensResult {\n /** The total number of tokens. */\n totalTokens?: number;\n}\n\n/** Local tokenizer compute tokens result. */\nexport declare interface ComputeTokensResult {\n /** Lists of tokens info from the input. */\n tokensInfo?: TokensInfo[];\n}\n\n/** Fine-tuning job creation parameters - optional fields. */\nexport declare interface CreateTuningJobParameters {\n /** The base model that is being tuned, e.g., \"gemini-2.5-flash\". */\n baseModel: string;\n /** Cloud Storage path to file containing training dataset for tuning. The dataset must be formatted as a JSONL file. */\n trainingDataset: TuningDataset;\n /** Configuration for the tuning job. */\n config?: CreateTuningJobConfig;\n}\n\n/** The response when long-running operation for uploading a file to a FileSearchStore complete. */\nexport class UploadToFileSearchStoreResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** The name of the FileSearchStore containing Documents. */\n parent?: string;\n /** The identifier for the Document imported. */\n documentName?: string;\n}\n\n/** Long-running operation for uploading a file to a FileSearchStore. */\nexport class UploadToFileSearchStoreOperation\n implements Operation<UploadToFileSearchStoreResponse>\n{\n /** The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`. */\n name?: string;\n /** Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata. Any method that returns a long-running operation should document the metadata type, if any. */\n metadata?: Record<string, unknown>;\n /** If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available. */\n done?: boolean;\n /** The error result of the operation in case of failure or cancellation. */\n error?: Record<string, unknown>;\n /** The result of the UploadToFileSearchStore operation, available when the operation is done. */\n response?: UploadToFileSearchStoreResponse;\n\n /**\n * Instantiates an Operation of the same type as the one being called with the fields set from the API response.\n * @internal\n */\n _fromAPIResponse({\n apiResponse,\n _isVertexAI,\n }: OperationFromAPIResponseParameters): Operation<UploadToFileSearchStoreResponse> {\n const operation = new UploadToFileSearchStoreOperation();\n\n const op = apiResponse as unknown as UploadToFileSearchStoreOperation;\n const response = uploadToFileSearchStoreOperationFromMldev(op);\n Object.assign(operation, response);\n return operation;\n }\n /** The full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n}\n\nexport type BlobImageUnion = Blob;\n\nexport type PartUnion = Part | string;\n\nexport type PartListUnion = PartUnion[] | PartUnion;\n\nexport type ContentUnion = Content | PartUnion[] | PartUnion;\n\nexport type ContentListUnion = Content | Content[] | PartUnion | PartUnion[];\n\nexport type SchemaUnion = Schema | unknown;\n\nexport type SpeechConfigUnion = SpeechConfig | string;\n\nexport type ToolUnion = Tool | CallableTool;\n\nexport type ToolListUnion = ToolUnion[];\n\nexport type DownloadableFileUnion = string | File | GeneratedVideo | Video;\n\nexport type BatchJobSourceUnion = BatchJobSource | InlinedRequest[] | string;\n\nexport type BatchJobDestinationUnion = BatchJobDestination | string;\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type {Tool as McpTool} from '@modelcontextprotocol/sdk/types';\n\nimport {ApiClient} from './_api_client.js';\nimport * as baseTransformers from './_base_transformers.js';\nimport * as types from './types.js';\n\nexport function tModel(apiClient: ApiClient, model: string | unknown): string {\n if (!model || typeof model !== 'string') {\n throw new Error('model is required and must be a string');\n }\n if (model.includes('..') || model.includes('?') || model.includes('&')) {\n throw new Error('invalid model parameter');\n }\n\n if (apiClient.isVertexAI()) {\n if (\n model.startsWith('publishers/') ||\n model.startsWith('projects/') ||\n model.startsWith('models/')\n ) {\n return model;\n } else if (model.indexOf('/') >= 0) {\n const parts = model.split('/', 2);\n return `publishers/${parts[0]}/models/${parts[1]}`;\n } else {\n return `publishers/google/models/${model}`;\n }\n } else {\n if (model.startsWith('models/') || model.startsWith('tunedModels/')) {\n return model;\n } else {\n return `models/${model}`;\n }\n }\n}\n\nexport function tCachesModel(\n apiClient: ApiClient,\n model: string | unknown,\n): string {\n const transformedModel = tModel(apiClient, model as string);\n if (!transformedModel) {\n return '';\n }\n\n if (transformedModel.startsWith('publishers/') && apiClient.isVertexAI()) {\n // vertex caches only support model name start with projects.\n return `projects/${apiClient.getProject()}/locations/${apiClient.getLocation()}/${transformedModel}`;\n } else if (transformedModel.startsWith('models/') && apiClient.isVertexAI()) {\n return `projects/${apiClient.getProject()}/locations/${apiClient.getLocation()}/publishers/google/${transformedModel}`;\n } else {\n return transformedModel;\n }\n}\n\nexport function tBlobs(\n blobs: types.BlobImageUnion | types.BlobImageUnion[],\n): types.Blob[] {\n if (Array.isArray(blobs)) {\n return blobs.map((blob) => tBlob(blob));\n } else {\n return [tBlob(blobs)];\n }\n}\n\nexport function tBlob(blob: types.BlobImageUnion): types.Blob {\n if (typeof blob === 'object' && blob !== null) {\n return blob;\n }\n\n throw new Error(\n `Could not parse input as Blob. Unsupported blob type: ${typeof blob}`,\n );\n}\n\nexport function tImageBlob(blob: types.BlobImageUnion): types.Blob {\n const transformedBlob = tBlob(blob);\n if (\n transformedBlob.mimeType &&\n transformedBlob.mimeType.startsWith('image/')\n ) {\n return transformedBlob;\n }\n throw new Error(`Unsupported mime type: ${transformedBlob.mimeType!}`);\n}\n\nexport function tAudioBlob(blob: types.Blob): types.Blob {\n const transformedBlob = tBlob(blob);\n if (\n transformedBlob.mimeType &&\n transformedBlob.mimeType.startsWith('audio/')\n ) {\n return transformedBlob;\n }\n throw new Error(`Unsupported mime type: ${transformedBlob.mimeType!}`);\n}\n\nexport function tPart(origin?: types.PartUnion | null): types.Part {\n if (origin === null || origin === undefined) {\n throw new Error('PartUnion is required');\n }\n if (typeof origin === 'object') {\n return origin;\n }\n if (typeof origin === 'string') {\n return {text: origin};\n }\n throw new Error(`Unsupported part type: ${typeof origin}`);\n}\n\nexport function tParts(origin?: types.PartListUnion | null): types.Part[] {\n if (\n origin === null ||\n origin === undefined ||\n (Array.isArray(origin) && origin.length === 0)\n ) {\n throw new Error('PartListUnion is required');\n }\n if (Array.isArray(origin)) {\n return origin.map((item) => tPart(item as types.PartUnion)!);\n }\n return [tPart(origin)!];\n}\n\nfunction _isContent(origin: unknown): boolean {\n return (\n origin !== null &&\n origin !== undefined &&\n typeof origin === 'object' &&\n 'parts' in origin &&\n Array.isArray(origin.parts)\n );\n}\n\nfunction _isFunctionCallPart(origin: unknown): boolean {\n return (\n origin !== null &&\n origin !== undefined &&\n typeof origin === 'object' &&\n 'functionCall' in origin\n );\n}\n\nfunction _isFunctionResponsePart(origin: unknown): boolean {\n return (\n origin !== null &&\n origin !== undefined &&\n typeof origin === 'object' &&\n 'functionResponse' in origin\n );\n}\n\nexport function tContent(origin?: types.ContentUnion): types.Content {\n if (origin === null || origin === undefined) {\n throw new Error('ContentUnion is required');\n }\n if (_isContent(origin)) {\n // _isContent is a utility function that checks if the\n // origin is a Content.\n return origin as types.Content;\n }\n\n return {\n role: 'user',\n parts: tParts(origin as types.PartListUnion)!,\n };\n}\n\nexport function tContentsForEmbed(\n apiClient: ApiClient,\n origin: types.ContentListUnion,\n): types.ContentUnion[] {\n if (!origin) {\n return [];\n }\n if (apiClient.isVertexAI() && Array.isArray(origin)) {\n return origin.flatMap((item) => {\n const content = tContent(item as types.ContentUnion);\n if (\n content.parts &&\n content.parts.length > 0 &&\n content.parts[0].text !== undefined\n ) {\n return [content.parts[0].text];\n }\n return [];\n });\n } else if (apiClient.isVertexAI()) {\n const content = tContent(origin as types.ContentUnion);\n if (\n content.parts &&\n content.parts.length > 0 &&\n content.parts[0].text !== undefined\n ) {\n return [content.parts[0].text];\n }\n return [];\n }\n if (Array.isArray(origin)) {\n return origin.map((item) => tContent(item as types.ContentUnion)!);\n }\n return [tContent(origin as types.ContentUnion)!];\n}\n\nexport function tContents(origin?: types.ContentListUnion): types.Content[] {\n if (\n origin === null ||\n origin === undefined ||\n (Array.isArray(origin) && origin.length === 0)\n ) {\n throw new Error('contents are required');\n }\n if (!Array.isArray(origin)) {\n // If it's not an array, it's a single content or a single PartUnion.\n if (_isFunctionCallPart(origin) || _isFunctionResponsePart(origin)) {\n throw new Error(\n 'To specify functionCall or functionResponse parts, please wrap them in a Content object, specifying the role for them',\n );\n }\n return [tContent(origin as types.ContentUnion)];\n }\n\n const result: types.Content[] = [];\n const accumulatedParts: types.PartUnion[] = [];\n const isContentArray = _isContent(origin[0]);\n\n for (const item of origin) {\n const isContent = _isContent(item);\n\n if (isContent != isContentArray) {\n throw new Error(\n 'Mixing Content and Parts is not supported, please group the parts into a the appropriate Content objects and specify the roles for them',\n );\n }\n\n if (isContent) {\n // `isContent` contains the result of _isContent, which is a utility\n // function that checks if the item is a Content.\n result.push(item as types.Content);\n } else if (_isFunctionCallPart(item) || _isFunctionResponsePart(item)) {\n throw new Error(\n 'To specify functionCall or functionResponse parts, please wrap them, and any other parts, in Content objects as appropriate, specifying the role for them',\n );\n } else {\n accumulatedParts.push(item as types.PartUnion);\n }\n }\n\n if (!isContentArray) {\n result.push({role: 'user', parts: tParts(accumulatedParts)});\n }\n return result;\n}\n\n/*\nTransform the type field from an array of types to an array of anyOf fields.\nExample:\n {type: ['STRING', 'NUMBER']}\nwill be transformed to\n {anyOf: [{type: 'STRING'}, {type: 'NUMBER'}]}\n*/\nfunction flattenTypeArrayToAnyOf(\n typeList: string[],\n resultingSchema: types.Schema,\n) {\n if (typeList.includes('null')) {\n resultingSchema['nullable'] = true;\n }\n const listWithoutNull = typeList.filter((type) => type !== 'null');\n\n if (listWithoutNull.length === 1) {\n resultingSchema['type'] = Object.values(types.Type).includes(\n listWithoutNull[0].toUpperCase() as types.Type,\n )\n ? (listWithoutNull[0].toUpperCase() as types.Type)\n : types.Type.TYPE_UNSPECIFIED;\n } else {\n resultingSchema['anyOf'] = [];\n for (const i of listWithoutNull) {\n resultingSchema['anyOf'].push({\n 'type': Object.values(types.Type).includes(\n i.toUpperCase() as types.Type,\n )\n ? (i.toUpperCase() as types.Type)\n : types.Type.TYPE_UNSPECIFIED,\n });\n }\n }\n}\n\nexport function processJsonSchema(\n _jsonSchema: types.Schema | Record<string, unknown>,\n): types.Schema {\n const genAISchema: types.Schema = {};\n const schemaFieldNames = ['items'];\n const listSchemaFieldNames = ['anyOf'];\n const dictSchemaFieldNames = ['properties'];\n\n if (_jsonSchema['type'] && _jsonSchema['anyOf']) {\n throw new Error('type and anyOf cannot be both populated.');\n }\n\n /*\n This is to handle the nullable array or object. The _jsonSchema will\n be in the format of {anyOf: [{type: 'null'}, {type: 'object'}]}. The\n logic is to check if anyOf has 2 elements and one of the element is null,\n if so, the anyOf field is unnecessary, so we need to get rid of the anyOf\n field and make the schema nullable. Then use the other element as the new\n _jsonSchema for processing. This is because the backend doesn't have a null\n type.\n This has to be checked before we process any other fields.\n For example:\n const objectNullable = z.object({\n nullableArray: z.array(z.string()).nullable(),\n });\n Will have the raw _jsonSchema as:\n {\n type: 'OBJECT',\n properties: {\n nullableArray: {\n anyOf: [\n {type: 'null'},\n {\n type: 'array',\n items: {type: 'string'},\n },\n ],\n }\n },\n required: [ 'nullableArray' ],\n }\n Will result in following schema compatible with Gemini API:\n {\n type: 'OBJECT',\n properties: {\n nullableArray: {\n nullable: true,\n type: 'ARRAY',\n items: {type: 'string'},\n }\n },\n required: [ 'nullableArray' ],\n }\n */\n const incomingAnyOf = _jsonSchema['anyOf'] as Record<string, unknown>[];\n if (incomingAnyOf != null && incomingAnyOf.length == 2) {\n if (incomingAnyOf[0]!['type'] === 'null') {\n genAISchema['nullable'] = true;\n _jsonSchema = incomingAnyOf![1];\n } else if (incomingAnyOf[1]!['type'] === 'null') {\n genAISchema['nullable'] = true;\n _jsonSchema = incomingAnyOf![0];\n }\n }\n\n if (_jsonSchema['type'] instanceof Array) {\n flattenTypeArrayToAnyOf(_jsonSchema['type'], genAISchema);\n }\n\n for (const [fieldName, fieldValue] of Object.entries(_jsonSchema)) {\n // Skip if the fieldvalue is undefined or null.\n if (fieldValue == null) {\n continue;\n }\n\n if (fieldName == 'type') {\n if (fieldValue === 'null') {\n throw new Error(\n 'type: null can not be the only possible type for the field.',\n );\n }\n if (fieldValue instanceof Array) {\n // we have already handled the type field with array of types in the\n // beginning of this function.\n continue;\n }\n genAISchema['type'] = Object.values(types.Type).includes(\n fieldValue.toUpperCase() as types.Type,\n )\n ? fieldValue.toUpperCase()\n : types.Type.TYPE_UNSPECIFIED;\n } else if (schemaFieldNames.includes(fieldName)) {\n (genAISchema as Record<string, unknown>)[fieldName] =\n processJsonSchema(fieldValue);\n } else if (listSchemaFieldNames.includes(fieldName)) {\n const listSchemaFieldValue: Array<types.Schema> = [];\n for (const item of fieldValue) {\n if (item['type'] == 'null') {\n genAISchema['nullable'] = true;\n continue;\n }\n listSchemaFieldValue.push(\n processJsonSchema(item as Record<string, unknown>),\n );\n }\n (genAISchema as Record<string, unknown>)[fieldName] =\n listSchemaFieldValue;\n } else if (dictSchemaFieldNames.includes(fieldName)) {\n const dictSchemaFieldValue: Record<string, types.Schema> = {};\n for (const [key, value] of Object.entries(\n fieldValue as Record<string, unknown>,\n )) {\n dictSchemaFieldValue[key] = processJsonSchema(\n value as Record<string, unknown>,\n );\n }\n (genAISchema as Record<string, unknown>)[fieldName] =\n dictSchemaFieldValue;\n } else {\n // additionalProperties is not included in JSONSchema, skipping it.\n if (fieldName === 'additionalProperties') {\n continue;\n }\n (genAISchema as Record<string, unknown>)[fieldName] = fieldValue;\n }\n }\n return genAISchema;\n}\n\n// we take the unknown in the schema field because we want enable user to pass\n// the output of major schema declaration tools without casting. Tools such as\n// zodToJsonSchema, typebox, zodToJsonSchema function can return JsonSchema7Type\n// or object, see details in\n// https://github.com/StefanTerdell/zod-to-json-schema/blob/70525efe555cd226691e093d171370a3b10921d1/src/zodToJsonSchema.ts#L7\n// typebox can return unknown, see details in\n// https://github.com/sinclairzx81/typebox/blob/5a5431439f7d5ca6b494d0d18fbfd7b1a356d67c/src/type/create/type.ts#L35\n// Note: proper json schemas with the $schema field set never arrive to this\n// transformer. Schemas with $schema are routed to the equivalent API json\n// schema field.\nexport function tSchema(schema: types.Schema | unknown): types.Schema {\n return processJsonSchema(schema as types.Schema);\n}\n\nexport function tSpeechConfig(\n speechConfig: types.SpeechConfigUnion,\n): types.SpeechConfig {\n if (typeof speechConfig === 'object') {\n return speechConfig;\n } else if (typeof speechConfig === 'string') {\n return {\n voiceConfig: {\n prebuiltVoiceConfig: {\n voiceName: speechConfig,\n },\n },\n };\n } else {\n throw new Error(`Unsupported speechConfig type: ${typeof speechConfig}`);\n }\n}\n\nexport function tLiveSpeechConfig(\n speechConfig: types.SpeechConfig | object,\n): types.SpeechConfig {\n if ('multiSpeakerVoiceConfig' in speechConfig) {\n throw new Error(\n 'multiSpeakerVoiceConfig is not supported in the live API.',\n );\n }\n return speechConfig;\n}\n\nexport function tTool(tool: types.Tool): types.Tool {\n if (tool.functionDeclarations) {\n for (const functionDeclaration of tool.functionDeclarations) {\n if (functionDeclaration.parameters) {\n if (!Object.keys(functionDeclaration.parameters).includes('$schema')) {\n functionDeclaration.parameters = processJsonSchema(\n functionDeclaration.parameters,\n );\n } else {\n if (!functionDeclaration.parametersJsonSchema) {\n functionDeclaration.parametersJsonSchema =\n functionDeclaration.parameters;\n delete functionDeclaration.parameters;\n }\n }\n }\n if (functionDeclaration.response) {\n if (!Object.keys(functionDeclaration.response).includes('$schema')) {\n functionDeclaration.response = processJsonSchema(\n functionDeclaration.response,\n );\n } else {\n if (!functionDeclaration.responseJsonSchema) {\n functionDeclaration.responseJsonSchema =\n functionDeclaration.response;\n delete functionDeclaration.response;\n }\n }\n }\n }\n }\n return tool;\n}\n\nexport function tTools(tools: types.ToolListUnion | unknown): types.Tool[] {\n // Check if the incoming type is defined.\n if (tools === undefined || tools === null) {\n throw new Error('tools is required');\n }\n if (!Array.isArray(tools)) {\n throw new Error('tools is required and must be an array of Tools');\n }\n const result: types.Tool[] = [];\n for (const tool of tools) {\n result.push(tool as types.Tool);\n }\n return result;\n}\n\n/**\n * Prepends resource name with project, location, resource_prefix if needed.\n *\n * @param client The API client.\n * @param resourceName The resource name.\n * @param resourcePrefix The resource prefix.\n * @param splitsAfterPrefix The number of splits after the prefix.\n * @returns The completed resource name.\n *\n * Examples:\n *\n * ```\n * resource_name = '123'\n * resource_prefix = 'cachedContents'\n * splits_after_prefix = 1\n * client.vertexai = True\n * client.project = 'bar'\n * client.location = 'us-west1'\n * _resource_name(client, resource_name, resource_prefix, splits_after_prefix)\n * returns: 'projects/bar/locations/us-west1/cachedContents/123'\n * ```\n *\n * ```\n * resource_name = 'projects/foo/locations/us-central1/cachedContents/123'\n * resource_prefix = 'cachedContents'\n * splits_after_prefix = 1\n * client.vertexai = True\n * client.project = 'bar'\n * client.location = 'us-west1'\n * _resource_name(client, resource_name, resource_prefix, splits_after_prefix)\n * returns: 'projects/foo/locations/us-central1/cachedContents/123'\n * ```\n *\n * ```\n * resource_name = '123'\n * resource_prefix = 'cachedContents'\n * splits_after_prefix = 1\n * client.vertexai = False\n * _resource_name(client, resource_name, resource_prefix, splits_after_prefix)\n * returns 'cachedContents/123'\n * ```\n *\n * ```\n * resource_name = 'some/wrong/cachedContents/resource/name/123'\n * resource_prefix = 'cachedContents'\n * splits_after_prefix = 1\n * client.vertexai = False\n * # client.vertexai = True\n * _resource_name(client, resource_name, resource_prefix, splits_after_prefix)\n * -> 'some/wrong/resource/name/123'\n * ```\n */\nfunction resourceName(\n client: ApiClient,\n resourceName: string,\n resourcePrefix: string,\n splitsAfterPrefix: number = 1,\n): string {\n const shouldAppendPrefix =\n !resourceName.startsWith(`${resourcePrefix}/`) &&\n resourceName.split('/').length === splitsAfterPrefix;\n if (client.isVertexAI()) {\n if (resourceName.startsWith('projects/')) {\n return resourceName;\n } else if (resourceName.startsWith('locations/')) {\n return `projects/${client.getProject()}/${resourceName}`;\n } else if (resourceName.startsWith(`${resourcePrefix}/`)) {\n return `projects/${client.getProject()}/locations/${client.getLocation()}/${resourceName}`;\n } else if (shouldAppendPrefix) {\n return `projects/${client.getProject()}/locations/${client.getLocation()}/${resourcePrefix}/${resourceName}`;\n } else {\n return resourceName;\n }\n }\n if (shouldAppendPrefix) {\n return `${resourcePrefix}/${resourceName}`;\n }\n return resourceName;\n}\n\nexport function tCachedContentName(\n apiClient: ApiClient,\n name: string | unknown,\n): string {\n if (typeof name !== 'string') {\n throw new Error('name must be a string');\n }\n return resourceName(apiClient, name, 'cachedContents');\n}\n\nexport function tTuningJobStatus(status: string | unknown): string {\n switch (status) {\n case 'STATE_UNSPECIFIED':\n return 'JOB_STATE_UNSPECIFIED';\n case 'CREATING':\n return 'JOB_STATE_RUNNING';\n case 'ACTIVE':\n return 'JOB_STATE_SUCCEEDED';\n case 'FAILED':\n return 'JOB_STATE_FAILED';\n default:\n return status as string;\n }\n}\n\nexport function tBytes(fromImageBytes: string | unknown): string {\n return baseTransformers.tBytes(fromImageBytes);\n}\n\nfunction _isFile(origin: unknown): boolean {\n return (\n origin !== null &&\n origin !== undefined &&\n typeof origin === 'object' &&\n 'name' in origin\n );\n}\n\nexport function isGeneratedVideo(origin: unknown): boolean {\n return (\n origin !== null &&\n origin !== undefined &&\n typeof origin === 'object' &&\n 'video' in origin\n );\n}\n\nexport function isVideo(origin: unknown): boolean {\n return (\n origin !== null &&\n origin !== undefined &&\n typeof origin === 'object' &&\n 'uri' in origin\n );\n}\n\nexport function tFileName(\n fromName: string | types.File | types.GeneratedVideo | types.Video,\n): string | undefined {\n let name: string | undefined;\n\n if (_isFile(fromName)) {\n name = (fromName as types.File).name;\n }\n if (isVideo(fromName)) {\n name = (fromName as types.Video).uri;\n if (name === undefined) {\n return undefined;\n }\n }\n if (isGeneratedVideo(fromName)) {\n name = (fromName as types.GeneratedVideo).video?.uri;\n if (name === undefined) {\n return undefined;\n }\n }\n if (typeof fromName === 'string') {\n name = fromName;\n }\n\n if (name === undefined) {\n throw new Error('Could not extract file name from the provided input.');\n }\n\n if (name.startsWith('https://')) {\n const suffix = name.split('files/')[1];\n const match = suffix.match(/[a-z0-9]+/);\n if (match === null) {\n throw new Error(`Could not extract file name from URI ${name}`);\n }\n name = match[0];\n } else if (name.startsWith('files/')) {\n name = name.split('files/')[1];\n }\n return name;\n}\n\nexport function tModelsUrl(\n apiClient: ApiClient,\n baseModels: boolean | unknown,\n): string {\n let res: string;\n if (apiClient.isVertexAI()) {\n res = baseModels ? 'publishers/google/models' : 'models';\n } else {\n res = baseModels ? 'models' : 'tunedModels';\n }\n return res;\n}\n\nexport function tExtractModels(response: unknown): Record<string, unknown>[] {\n for (const key of ['models', 'tunedModels', 'publisherModels']) {\n if (hasField(response, key)) {\n return (response as Record<string, unknown>)[key] as Record<\n string,\n unknown\n >[];\n }\n }\n return [];\n}\n\nfunction hasField(data: unknown, fieldName: string): boolean {\n return data !== null && typeof data === 'object' && fieldName in data;\n}\n\nexport function mcpToGeminiTool(\n mcpTool: McpTool,\n config: types.CallableToolConfig = {},\n): types.Tool {\n const mcpToolSchema = mcpTool as Record<string, unknown>;\n const functionDeclaration: Record<string, unknown> = {\n name: mcpToolSchema['name'],\n description: mcpToolSchema['description'],\n parametersJsonSchema: mcpToolSchema['inputSchema'],\n };\n if (mcpToolSchema['outputSchema']) {\n functionDeclaration['responseJsonSchema'] = mcpToolSchema['outputSchema'];\n }\n if (config.behavior) {\n functionDeclaration['behavior'] = config.behavior;\n }\n\n const geminiTool = {\n functionDeclarations: [\n functionDeclaration as unknown as types.FunctionDeclaration,\n ],\n };\n\n return geminiTool;\n}\n\n/**\n * Converts a list of MCP tools to a single Gemini tool with a list of function\n * declarations.\n */\nexport function mcpToolsToGeminiTool(\n mcpTools: McpTool[],\n config: types.CallableToolConfig = {},\n): types.Tool {\n const functionDeclarations: types.FunctionDeclaration[] = [];\n const toolNames = new Set<string>();\n for (const mcpTool of mcpTools) {\n const mcpToolName = mcpTool.name as string;\n if (toolNames.has(mcpToolName)) {\n throw new Error(\n `Duplicate function name ${\n mcpToolName\n } found in MCP tools. Please ensure function names are unique.`,\n );\n }\n toolNames.add(mcpToolName);\n const geminiTool = mcpToGeminiTool(mcpTool, config);\n if (geminiTool.functionDeclarations) {\n functionDeclarations.push(...geminiTool.functionDeclarations);\n }\n }\n\n return {functionDeclarations: functionDeclarations};\n}\n\n// Transforms a source input into a BatchJobSource object with validation.\nexport function tBatchJobSource(\n client: ApiClient,\n src: string | types.InlinedRequest[] | types.BatchJobSource,\n): types.BatchJobSource {\n let sourceObj: types.BatchJobSource;\n\n if (typeof src === 'string') {\n if (client.isVertexAI()) {\n if (src.startsWith('gs://')) {\n sourceObj = {format: 'jsonl', gcsUri: [src]};\n } else if (src.startsWith('bq://')) {\n sourceObj = {format: 'bigquery', bigqueryUri: src};\n } else {\n throw new Error(`Unsupported string source for Vertex AI: ${src}`);\n }\n } else {\n // MLDEV\n if (src.startsWith('files/')) {\n sourceObj = {fileName: src}; // Default to fileName for string input\n } else {\n throw new Error(`Unsupported string source for Gemini API: ${src}`);\n }\n }\n } else if (Array.isArray(src)) {\n if (client.isVertexAI()) {\n throw new Error('InlinedRequest[] is not supported in Vertex AI.');\n }\n sourceObj = {inlinedRequests: src};\n } else {\n // It's already a BatchJobSource object\n sourceObj = src;\n }\n\n // Validation logic\n const vertexSourcesCount = [sourceObj.gcsUri, sourceObj.bigqueryUri].filter(\n Boolean,\n ).length;\n\n const mldevSourcesCount = [\n sourceObj.inlinedRequests,\n sourceObj.fileName,\n ].filter(Boolean).length;\n\n if (client.isVertexAI()) {\n if (mldevSourcesCount > 0 || vertexSourcesCount !== 1) {\n throw new Error(\n 'Exactly one of `gcsUri` or `bigqueryUri` must be set for Vertex AI.',\n );\n }\n } else {\n // MLDEV\n if (vertexSourcesCount > 0 || mldevSourcesCount !== 1) {\n throw new Error(\n 'Exactly one of `inlinedRequests`, `fileName`, ' +\n 'must be set for Gemini API.',\n );\n }\n }\n\n return sourceObj;\n}\n\nexport function tEmbeddingBatchJobSource(\n client: ApiClient,\n src: types.EmbeddingsBatchJobSource,\n): types.EmbeddingsBatchJobSource {\n if (client.isVertexAI()) {\n throw new Error('Embedding batch jobs are not supported in Vertex AI.');\n }\n\n const sourceObj: types.EmbeddingsBatchJobSource = {...src};\n\n const mldevSources =\n Number(!!sourceObj.inlinedRequests) + Number(!!sourceObj.fileName);\n\n if (mldevSources !== 1) {\n throw new Error(\n 'Exactly one of `inlinedRequests` or `fileName` must be set for Embedding Batch Jobs in the Gemini API.',\n );\n }\n return sourceObj;\n}\n\nexport function tBatchJobDestination(\n dest: string | types.BatchJobDestination,\n): types.BatchJobDestination {\n if (typeof dest !== 'string') {\n return dest as types.BatchJobDestination;\n }\n const destString = dest as string;\n if (destString.startsWith('gs://')) {\n return {\n format: 'jsonl',\n gcsUri: destString,\n };\n } else if (destString.startsWith('bq://')) {\n return {\n format: 'bigquery',\n bigqueryUri: destString,\n };\n } else {\n throw new Error(`Unsupported destination: ${destString}`);\n }\n}\n\nexport function tRecvBatchJobDestination(\n dest: unknown,\n): types.BatchJobDestination {\n // Ensure dest is a non-null object before proceeding.\n if (typeof dest !== 'object' || dest === null) {\n // If the input is not an object, it cannot be a valid BatchJobDestination\n // based on the operations performed. Return it cast, or handle as an error.\n // Casting an empty object might be a safe default.\n return {} as types.BatchJobDestination;\n }\n\n // Cast to Record<string, unknown> to allow string property access.\n const obj = dest as Record<string, unknown>;\n\n // Safely access nested properties.\n const inlineResponsesVal = obj['inlinedResponses'];\n if (typeof inlineResponsesVal !== 'object' || inlineResponsesVal === null) {\n return dest as types.BatchJobDestination;\n }\n const inlineResponsesObj = inlineResponsesVal as Record<string, unknown>;\n\n const responsesArray = inlineResponsesObj['inlinedResponses'];\n if (!Array.isArray(responsesArray) || responsesArray.length === 0) {\n return dest as types.BatchJobDestination;\n }\n\n // Check if any response has the 'embedding' property.\n let hasEmbedding = false;\n for (const responseItem of responsesArray) {\n if (typeof responseItem !== 'object' || responseItem === null) {\n continue;\n }\n const responseItemObj = responseItem as Record<string, unknown>;\n\n const responseVal = responseItemObj['response'];\n if (typeof responseVal !== 'object' || responseVal === null) {\n continue;\n }\n const responseObj = responseVal as Record<string, unknown>;\n\n // Check for the existence of the 'embedding' key.\n if (responseObj['embedding'] !== undefined) {\n hasEmbedding = true;\n break;\n }\n }\n\n // Perform the transformation if an embedding was found.\n if (hasEmbedding) {\n obj['inlinedEmbedContentResponses'] = obj['inlinedResponses'];\n delete obj['inlinedResponses'];\n }\n\n // Cast the (potentially) modified object to the target type.\n return dest as types.BatchJobDestination;\n}\n\nexport function tBatchJobName(apiClient: ApiClient, name: unknown): string {\n const nameString = name as string;\n if (!apiClient.isVertexAI()) {\n const mldevPattern = /batches\\/[^/]+$/;\n\n if (mldevPattern.test(nameString)) {\n return nameString.split('/').pop() as string;\n } else {\n throw new Error(`Invalid batch job name: ${nameString}.`);\n }\n }\n\n const vertexPattern =\n /^projects\\/[^/]+\\/locations\\/[^/]+\\/batchPredictionJobs\\/[^/]+$/;\n\n if (vertexPattern.test(nameString)) {\n return nameString.split('/').pop() as string;\n } else if (/^\\d+$/.test(nameString)) {\n return nameString;\n } else {\n throw new Error(`Invalid batch job name: ${nameString}.`);\n }\n}\n\nexport function tJobState(state: unknown): string {\n const stateString = state as string;\n if (stateString === 'BATCH_STATE_UNSPECIFIED') {\n return 'JOB_STATE_UNSPECIFIED';\n } else if (stateString === 'BATCH_STATE_PENDING') {\n return 'JOB_STATE_PENDING';\n } else if (stateString === 'BATCH_STATE_RUNNING') {\n return 'JOB_STATE_RUNNING';\n } else if (stateString === 'BATCH_STATE_SUCCEEDED') {\n return 'JOB_STATE_SUCCEEDED';\n } else if (stateString === 'BATCH_STATE_FAILED') {\n return 'JOB_STATE_FAILED';\n } else if (stateString === 'BATCH_STATE_CANCELLED') {\n return 'JOB_STATE_CANCELLED';\n } else if (stateString === 'BATCH_STATE_EXPIRED') {\n return 'JOB_STATE_EXPIRED';\n } else {\n return stateString;\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport {ApiClient} from '../_api_client.js';\nimport * as common from '../_common.js';\nimport * as t from '../_transformers.js';\nimport type * as types from '../types.js';\n\nexport function batchJobDestinationFromMldev(\n fromObject: types.BatchJobDestination,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromFileName = common.getValueByPath(fromObject, ['responsesFile']);\n if (fromFileName != null) {\n common.setValueByPath(toObject, ['fileName'], fromFileName);\n }\n\n const fromInlinedResponses = common.getValueByPath(fromObject, [\n 'inlinedResponses',\n 'inlinedResponses',\n ]);\n if (fromInlinedResponses != null) {\n let transformedList = fromInlinedResponses;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return inlinedResponseFromMldev(item);\n });\n }\n common.setValueByPath(toObject, ['inlinedResponses'], transformedList);\n }\n\n const fromInlinedEmbedContentResponses = common.getValueByPath(fromObject, [\n 'inlinedEmbedContentResponses',\n 'inlinedResponses',\n ]);\n if (fromInlinedEmbedContentResponses != null) {\n let transformedList = fromInlinedEmbedContentResponses;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(\n toObject,\n ['inlinedEmbedContentResponses'],\n transformedList,\n );\n }\n\n return toObject;\n}\n\nexport function batchJobDestinationFromVertex(\n fromObject: types.BatchJobDestination,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromFormat = common.getValueByPath(fromObject, ['predictionsFormat']);\n if (fromFormat != null) {\n common.setValueByPath(toObject, ['format'], fromFormat);\n }\n\n const fromGcsUri = common.getValueByPath(fromObject, [\n 'gcsDestination',\n 'outputUriPrefix',\n ]);\n if (fromGcsUri != null) {\n common.setValueByPath(toObject, ['gcsUri'], fromGcsUri);\n }\n\n const fromBigqueryUri = common.getValueByPath(fromObject, [\n 'bigqueryDestination',\n 'outputUri',\n ]);\n if (fromBigqueryUri != null) {\n common.setValueByPath(toObject, ['bigqueryUri'], fromBigqueryUri);\n }\n\n return toObject;\n}\n\nexport function batchJobDestinationToVertex(\n fromObject: types.BatchJobDestination,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromFormat = common.getValueByPath(fromObject, ['format']);\n if (fromFormat != null) {\n common.setValueByPath(toObject, ['predictionsFormat'], fromFormat);\n }\n\n const fromGcsUri = common.getValueByPath(fromObject, ['gcsUri']);\n if (fromGcsUri != null) {\n common.setValueByPath(\n toObject,\n ['gcsDestination', 'outputUriPrefix'],\n fromGcsUri,\n );\n }\n\n const fromBigqueryUri = common.getValueByPath(fromObject, ['bigqueryUri']);\n if (fromBigqueryUri != null) {\n common.setValueByPath(\n toObject,\n ['bigqueryDestination', 'outputUri'],\n fromBigqueryUri,\n );\n }\n\n if (common.getValueByPath(fromObject, ['fileName']) !== undefined) {\n throw new Error('fileName parameter is not supported in Vertex AI.');\n }\n\n if (common.getValueByPath(fromObject, ['inlinedResponses']) !== undefined) {\n throw new Error(\n 'inlinedResponses parameter is not supported in Vertex AI.',\n );\n }\n\n if (\n common.getValueByPath(fromObject, ['inlinedEmbedContentResponses']) !==\n undefined\n ) {\n throw new Error(\n 'inlinedEmbedContentResponses parameter is not supported in Vertex AI.',\n );\n }\n\n return toObject;\n}\n\nexport function batchJobFromMldev(\n fromObject: types.BatchJob,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromDisplayName = common.getValueByPath(fromObject, [\n 'metadata',\n 'displayName',\n ]);\n if (fromDisplayName != null) {\n common.setValueByPath(toObject, ['displayName'], fromDisplayName);\n }\n\n const fromState = common.getValueByPath(fromObject, ['metadata', 'state']);\n if (fromState != null) {\n common.setValueByPath(toObject, ['state'], t.tJobState(fromState));\n }\n\n const fromCreateTime = common.getValueByPath(fromObject, [\n 'metadata',\n 'createTime',\n ]);\n if (fromCreateTime != null) {\n common.setValueByPath(toObject, ['createTime'], fromCreateTime);\n }\n\n const fromEndTime = common.getValueByPath(fromObject, [\n 'metadata',\n 'endTime',\n ]);\n if (fromEndTime != null) {\n common.setValueByPath(toObject, ['endTime'], fromEndTime);\n }\n\n const fromUpdateTime = common.getValueByPath(fromObject, [\n 'metadata',\n 'updateTime',\n ]);\n if (fromUpdateTime != null) {\n common.setValueByPath(toObject, ['updateTime'], fromUpdateTime);\n }\n\n const fromModel = common.getValueByPath(fromObject, ['metadata', 'model']);\n if (fromModel != null) {\n common.setValueByPath(toObject, ['model'], fromModel);\n }\n\n const fromDest = common.getValueByPath(fromObject, ['metadata', 'output']);\n if (fromDest != null) {\n common.setValueByPath(\n toObject,\n ['dest'],\n batchJobDestinationFromMldev(t.tRecvBatchJobDestination(fromDest)),\n );\n }\n\n return toObject;\n}\n\nexport function batchJobFromVertex(\n fromObject: types.BatchJob,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromDisplayName = common.getValueByPath(fromObject, ['displayName']);\n if (fromDisplayName != null) {\n common.setValueByPath(toObject, ['displayName'], fromDisplayName);\n }\n\n const fromState = common.getValueByPath(fromObject, ['state']);\n if (fromState != null) {\n common.setValueByPath(toObject, ['state'], t.tJobState(fromState));\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n const fromCreateTime = common.getValueByPath(fromObject, ['createTime']);\n if (fromCreateTime != null) {\n common.setValueByPath(toObject, ['createTime'], fromCreateTime);\n }\n\n const fromStartTime = common.getValueByPath(fromObject, ['startTime']);\n if (fromStartTime != null) {\n common.setValueByPath(toObject, ['startTime'], fromStartTime);\n }\n\n const fromEndTime = common.getValueByPath(fromObject, ['endTime']);\n if (fromEndTime != null) {\n common.setValueByPath(toObject, ['endTime'], fromEndTime);\n }\n\n const fromUpdateTime = common.getValueByPath(fromObject, ['updateTime']);\n if (fromUpdateTime != null) {\n common.setValueByPath(toObject, ['updateTime'], fromUpdateTime);\n }\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(toObject, ['model'], fromModel);\n }\n\n const fromSrc = common.getValueByPath(fromObject, ['inputConfig']);\n if (fromSrc != null) {\n common.setValueByPath(toObject, ['src'], batchJobSourceFromVertex(fromSrc));\n }\n\n const fromDest = common.getValueByPath(fromObject, ['outputConfig']);\n if (fromDest != null) {\n common.setValueByPath(\n toObject,\n ['dest'],\n batchJobDestinationFromVertex(t.tRecvBatchJobDestination(fromDest)),\n );\n }\n\n const fromCompletionStats = common.getValueByPath(fromObject, [\n 'completionStats',\n ]);\n if (fromCompletionStats != null) {\n common.setValueByPath(toObject, ['completionStats'], fromCompletionStats);\n }\n\n return toObject;\n}\n\nexport function batchJobSourceFromVertex(\n fromObject: types.BatchJobSource,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromFormat = common.getValueByPath(fromObject, ['instancesFormat']);\n if (fromFormat != null) {\n common.setValueByPath(toObject, ['format'], fromFormat);\n }\n\n const fromGcsUri = common.getValueByPath(fromObject, ['gcsSource', 'uris']);\n if (fromGcsUri != null) {\n common.setValueByPath(toObject, ['gcsUri'], fromGcsUri);\n }\n\n const fromBigqueryUri = common.getValueByPath(fromObject, [\n 'bigquerySource',\n 'inputUri',\n ]);\n if (fromBigqueryUri != null) {\n common.setValueByPath(toObject, ['bigqueryUri'], fromBigqueryUri);\n }\n\n return toObject;\n}\n\nexport function batchJobSourceToMldev(\n apiClient: ApiClient,\n fromObject: types.BatchJobSource,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['format']) !== undefined) {\n throw new Error('format parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['gcsUri']) !== undefined) {\n throw new Error('gcsUri parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['bigqueryUri']) !== undefined) {\n throw new Error('bigqueryUri parameter is not supported in Gemini API.');\n }\n\n const fromFileName = common.getValueByPath(fromObject, ['fileName']);\n if (fromFileName != null) {\n common.setValueByPath(toObject, ['fileName'], fromFileName);\n }\n\n const fromInlinedRequests = common.getValueByPath(fromObject, [\n 'inlinedRequests',\n ]);\n if (fromInlinedRequests != null) {\n let transformedList = fromInlinedRequests;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return inlinedRequestToMldev(apiClient, item);\n });\n }\n common.setValueByPath(toObject, ['requests', 'requests'], transformedList);\n }\n\n return toObject;\n}\n\nexport function batchJobSourceToVertex(\n fromObject: types.BatchJobSource,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromFormat = common.getValueByPath(fromObject, ['format']);\n if (fromFormat != null) {\n common.setValueByPath(toObject, ['instancesFormat'], fromFormat);\n }\n\n const fromGcsUri = common.getValueByPath(fromObject, ['gcsUri']);\n if (fromGcsUri != null) {\n common.setValueByPath(toObject, ['gcsSource', 'uris'], fromGcsUri);\n }\n\n const fromBigqueryUri = common.getValueByPath(fromObject, ['bigqueryUri']);\n if (fromBigqueryUri != null) {\n common.setValueByPath(\n toObject,\n ['bigquerySource', 'inputUri'],\n fromBigqueryUri,\n );\n }\n\n if (common.getValueByPath(fromObject, ['fileName']) !== undefined) {\n throw new Error('fileName parameter is not supported in Vertex AI.');\n }\n\n if (common.getValueByPath(fromObject, ['inlinedRequests']) !== undefined) {\n throw new Error('inlinedRequests parameter is not supported in Vertex AI.');\n }\n\n return toObject;\n}\n\nexport function blobToMldev(fromObject: types.Blob): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromData = common.getValueByPath(fromObject, ['data']);\n if (fromData != null) {\n common.setValueByPath(toObject, ['data'], fromData);\n }\n\n if (common.getValueByPath(fromObject, ['displayName']) !== undefined) {\n throw new Error('displayName parameter is not supported in Gemini API.');\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function cancelBatchJobParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.CancelBatchJobParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tBatchJobName(apiClient, fromName),\n );\n }\n\n return toObject;\n}\n\nexport function cancelBatchJobParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.CancelBatchJobParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tBatchJobName(apiClient, fromName),\n );\n }\n\n return toObject;\n}\n\nexport function candidateFromMldev(\n fromObject: types.Candidate,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromContent = common.getValueByPath(fromObject, ['content']);\n if (fromContent != null) {\n common.setValueByPath(toObject, ['content'], fromContent);\n }\n\n const fromCitationMetadata = common.getValueByPath(fromObject, [\n 'citationMetadata',\n ]);\n if (fromCitationMetadata != null) {\n common.setValueByPath(\n toObject,\n ['citationMetadata'],\n citationMetadataFromMldev(fromCitationMetadata),\n );\n }\n\n const fromTokenCount = common.getValueByPath(fromObject, ['tokenCount']);\n if (fromTokenCount != null) {\n common.setValueByPath(toObject, ['tokenCount'], fromTokenCount);\n }\n\n const fromFinishReason = common.getValueByPath(fromObject, ['finishReason']);\n if (fromFinishReason != null) {\n common.setValueByPath(toObject, ['finishReason'], fromFinishReason);\n }\n\n const fromAvgLogprobs = common.getValueByPath(fromObject, ['avgLogprobs']);\n if (fromAvgLogprobs != null) {\n common.setValueByPath(toObject, ['avgLogprobs'], fromAvgLogprobs);\n }\n\n const fromGroundingMetadata = common.getValueByPath(fromObject, [\n 'groundingMetadata',\n ]);\n if (fromGroundingMetadata != null) {\n common.setValueByPath(\n toObject,\n ['groundingMetadata'],\n fromGroundingMetadata,\n );\n }\n\n const fromIndex = common.getValueByPath(fromObject, ['index']);\n if (fromIndex != null) {\n common.setValueByPath(toObject, ['index'], fromIndex);\n }\n\n const fromLogprobsResult = common.getValueByPath(fromObject, [\n 'logprobsResult',\n ]);\n if (fromLogprobsResult != null) {\n common.setValueByPath(toObject, ['logprobsResult'], fromLogprobsResult);\n }\n\n const fromSafetyRatings = common.getValueByPath(fromObject, [\n 'safetyRatings',\n ]);\n if (fromSafetyRatings != null) {\n let transformedList = fromSafetyRatings;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['safetyRatings'], transformedList);\n }\n\n const fromUrlContextMetadata = common.getValueByPath(fromObject, [\n 'urlContextMetadata',\n ]);\n if (fromUrlContextMetadata != null) {\n common.setValueByPath(\n toObject,\n ['urlContextMetadata'],\n fromUrlContextMetadata,\n );\n }\n\n return toObject;\n}\n\nexport function citationMetadataFromMldev(\n fromObject: types.CitationMetadata,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromCitations = common.getValueByPath(fromObject, ['citationSources']);\n if (fromCitations != null) {\n let transformedList = fromCitations;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['citations'], transformedList);\n }\n\n return toObject;\n}\n\nexport function contentToMldev(\n fromObject: types.Content,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromParts = common.getValueByPath(fromObject, ['parts']);\n if (fromParts != null) {\n let transformedList = fromParts;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return partToMldev(item);\n });\n }\n common.setValueByPath(toObject, ['parts'], transformedList);\n }\n\n const fromRole = common.getValueByPath(fromObject, ['role']);\n if (fromRole != null) {\n common.setValueByPath(toObject, ['role'], fromRole);\n }\n\n return toObject;\n}\n\nexport function createBatchJobConfigToMldev(\n fromObject: types.CreateBatchJobConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromDisplayName = common.getValueByPath(fromObject, ['displayName']);\n if (parentObject !== undefined && fromDisplayName != null) {\n common.setValueByPath(\n parentObject,\n ['batch', 'displayName'],\n fromDisplayName,\n );\n }\n\n if (common.getValueByPath(fromObject, ['dest']) !== undefined) {\n throw new Error('dest parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function createBatchJobConfigToVertex(\n fromObject: types.CreateBatchJobConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromDisplayName = common.getValueByPath(fromObject, ['displayName']);\n if (parentObject !== undefined && fromDisplayName != null) {\n common.setValueByPath(parentObject, ['displayName'], fromDisplayName);\n }\n\n const fromDest = common.getValueByPath(fromObject, ['dest']);\n if (parentObject !== undefined && fromDest != null) {\n common.setValueByPath(\n parentObject,\n ['outputConfig'],\n batchJobDestinationToVertex(t.tBatchJobDestination(fromDest)),\n );\n }\n\n return toObject;\n}\n\nexport function createBatchJobParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.CreateBatchJobParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromSrc = common.getValueByPath(fromObject, ['src']);\n if (fromSrc != null) {\n common.setValueByPath(\n toObject,\n ['batch', 'inputConfig'],\n batchJobSourceToMldev(apiClient, t.tBatchJobSource(apiClient, fromSrc)),\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n createBatchJobConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function createBatchJobParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.CreateBatchJobParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(toObject, ['model'], t.tModel(apiClient, fromModel));\n }\n\n const fromSrc = common.getValueByPath(fromObject, ['src']);\n if (fromSrc != null) {\n common.setValueByPath(\n toObject,\n ['inputConfig'],\n batchJobSourceToVertex(t.tBatchJobSource(apiClient, fromSrc)),\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n createBatchJobConfigToVertex(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function createEmbeddingsBatchJobConfigToMldev(\n fromObject: types.CreateEmbeddingsBatchJobConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromDisplayName = common.getValueByPath(fromObject, ['displayName']);\n if (parentObject !== undefined && fromDisplayName != null) {\n common.setValueByPath(\n parentObject,\n ['batch', 'displayName'],\n fromDisplayName,\n );\n }\n\n return toObject;\n}\n\nexport function createEmbeddingsBatchJobParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.CreateEmbeddingsBatchJobParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromSrc = common.getValueByPath(fromObject, ['src']);\n if (fromSrc != null) {\n common.setValueByPath(\n toObject,\n ['batch', 'inputConfig'],\n embeddingsBatchJobSourceToMldev(apiClient, fromSrc),\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n createEmbeddingsBatchJobConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function deleteBatchJobParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.DeleteBatchJobParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tBatchJobName(apiClient, fromName),\n );\n }\n\n return toObject;\n}\n\nexport function deleteBatchJobParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.DeleteBatchJobParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tBatchJobName(apiClient, fromName),\n );\n }\n\n return toObject;\n}\n\nexport function deleteResourceJobFromMldev(\n fromObject: types.DeleteResourceJob,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromDone = common.getValueByPath(fromObject, ['done']);\n if (fromDone != null) {\n common.setValueByPath(toObject, ['done'], fromDone);\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n return toObject;\n}\n\nexport function deleteResourceJobFromVertex(\n fromObject: types.DeleteResourceJob,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromDone = common.getValueByPath(fromObject, ['done']);\n if (fromDone != null) {\n common.setValueByPath(toObject, ['done'], fromDone);\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n return toObject;\n}\n\nexport function embedContentBatchToMldev(\n apiClient: ApiClient,\n fromObject: types.EmbedContentBatch,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromContents = common.getValueByPath(fromObject, ['contents']);\n if (fromContents != null) {\n let transformedList = t.tContentsForEmbed(apiClient, fromContents);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(\n toObject,\n ['requests[]', 'request', 'content'],\n transformedList,\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n common.setValueByPath(\n toObject,\n ['_self'],\n embedContentConfigToMldev(fromConfig, toObject),\n );\n common.moveValueByPath(toObject, {'requests[].*': 'requests[].request.*'});\n }\n\n return toObject;\n}\n\nexport function embedContentConfigToMldev(\n fromObject: types.EmbedContentConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromTaskType = common.getValueByPath(fromObject, ['taskType']);\n if (parentObject !== undefined && fromTaskType != null) {\n common.setValueByPath(\n parentObject,\n ['requests[]', 'taskType'],\n fromTaskType,\n );\n }\n\n const fromTitle = common.getValueByPath(fromObject, ['title']);\n if (parentObject !== undefined && fromTitle != null) {\n common.setValueByPath(parentObject, ['requests[]', 'title'], fromTitle);\n }\n\n const fromOutputDimensionality = common.getValueByPath(fromObject, [\n 'outputDimensionality',\n ]);\n if (parentObject !== undefined && fromOutputDimensionality != null) {\n common.setValueByPath(\n parentObject,\n ['requests[]', 'outputDimensionality'],\n fromOutputDimensionality,\n );\n }\n\n if (common.getValueByPath(fromObject, ['mimeType']) !== undefined) {\n throw new Error('mimeType parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['autoTruncate']) !== undefined) {\n throw new Error('autoTruncate parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function embeddingsBatchJobSourceToMldev(\n apiClient: ApiClient,\n fromObject: types.EmbeddingsBatchJobSource,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromFileName = common.getValueByPath(fromObject, ['fileName']);\n if (fromFileName != null) {\n common.setValueByPath(toObject, ['file_name'], fromFileName);\n }\n\n const fromInlinedRequests = common.getValueByPath(fromObject, [\n 'inlinedRequests',\n ]);\n if (fromInlinedRequests != null) {\n common.setValueByPath(\n toObject,\n ['requests'],\n embedContentBatchToMldev(apiClient, fromInlinedRequests),\n );\n }\n\n return toObject;\n}\n\nexport function fileDataToMldev(\n fromObject: types.FileData,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['displayName']) !== undefined) {\n throw new Error('displayName parameter is not supported in Gemini API.');\n }\n\n const fromFileUri = common.getValueByPath(fromObject, ['fileUri']);\n if (fromFileUri != null) {\n common.setValueByPath(toObject, ['fileUri'], fromFileUri);\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function functionCallToMldev(\n fromObject: types.FunctionCall,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromId = common.getValueByPath(fromObject, ['id']);\n if (fromId != null) {\n common.setValueByPath(toObject, ['id'], fromId);\n }\n\n const fromArgs = common.getValueByPath(fromObject, ['args']);\n if (fromArgs != null) {\n common.setValueByPath(toObject, ['args'], fromArgs);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n if (common.getValueByPath(fromObject, ['partialArgs']) !== undefined) {\n throw new Error('partialArgs parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['willContinue']) !== undefined) {\n throw new Error('willContinue parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function functionCallingConfigToMldev(\n fromObject: types.FunctionCallingConfig,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromAllowedFunctionNames = common.getValueByPath(fromObject, [\n 'allowedFunctionNames',\n ]);\n if (fromAllowedFunctionNames != null) {\n common.setValueByPath(\n toObject,\n ['allowedFunctionNames'],\n fromAllowedFunctionNames,\n );\n }\n\n const fromMode = common.getValueByPath(fromObject, ['mode']);\n if (fromMode != null) {\n common.setValueByPath(toObject, ['mode'], fromMode);\n }\n\n if (\n common.getValueByPath(fromObject, ['streamFunctionCallArguments']) !==\n undefined\n ) {\n throw new Error(\n 'streamFunctionCallArguments parameter is not supported in Gemini API.',\n );\n }\n\n return toObject;\n}\n\nexport function generateContentConfigToMldev(\n apiClient: ApiClient,\n fromObject: types.GenerateContentConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSystemInstruction = common.getValueByPath(fromObject, [\n 'systemInstruction',\n ]);\n if (parentObject !== undefined && fromSystemInstruction != null) {\n common.setValueByPath(\n parentObject,\n ['systemInstruction'],\n contentToMldev(t.tContent(fromSystemInstruction)),\n );\n }\n\n const fromTemperature = common.getValueByPath(fromObject, ['temperature']);\n if (fromTemperature != null) {\n common.setValueByPath(toObject, ['temperature'], fromTemperature);\n }\n\n const fromTopP = common.getValueByPath(fromObject, ['topP']);\n if (fromTopP != null) {\n common.setValueByPath(toObject, ['topP'], fromTopP);\n }\n\n const fromTopK = common.getValueByPath(fromObject, ['topK']);\n if (fromTopK != null) {\n common.setValueByPath(toObject, ['topK'], fromTopK);\n }\n\n const fromCandidateCount = common.getValueByPath(fromObject, [\n 'candidateCount',\n ]);\n if (fromCandidateCount != null) {\n common.setValueByPath(toObject, ['candidateCount'], fromCandidateCount);\n }\n\n const fromMaxOutputTokens = common.getValueByPath(fromObject, [\n 'maxOutputTokens',\n ]);\n if (fromMaxOutputTokens != null) {\n common.setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens);\n }\n\n const fromStopSequences = common.getValueByPath(fromObject, [\n 'stopSequences',\n ]);\n if (fromStopSequences != null) {\n common.setValueByPath(toObject, ['stopSequences'], fromStopSequences);\n }\n\n const fromResponseLogprobs = common.getValueByPath(fromObject, [\n 'responseLogprobs',\n ]);\n if (fromResponseLogprobs != null) {\n common.setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs);\n }\n\n const fromLogprobs = common.getValueByPath(fromObject, ['logprobs']);\n if (fromLogprobs != null) {\n common.setValueByPath(toObject, ['logprobs'], fromLogprobs);\n }\n\n const fromPresencePenalty = common.getValueByPath(fromObject, [\n 'presencePenalty',\n ]);\n if (fromPresencePenalty != null) {\n common.setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty);\n }\n\n const fromFrequencyPenalty = common.getValueByPath(fromObject, [\n 'frequencyPenalty',\n ]);\n if (fromFrequencyPenalty != null) {\n common.setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty);\n }\n\n const fromSeed = common.getValueByPath(fromObject, ['seed']);\n if (fromSeed != null) {\n common.setValueByPath(toObject, ['seed'], fromSeed);\n }\n\n const fromResponseMimeType = common.getValueByPath(fromObject, [\n 'responseMimeType',\n ]);\n if (fromResponseMimeType != null) {\n common.setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType);\n }\n\n const fromResponseSchema = common.getValueByPath(fromObject, [\n 'responseSchema',\n ]);\n if (fromResponseSchema != null) {\n common.setValueByPath(\n toObject,\n ['responseSchema'],\n t.tSchema(fromResponseSchema),\n );\n }\n\n const fromResponseJsonSchema = common.getValueByPath(fromObject, [\n 'responseJsonSchema',\n ]);\n if (fromResponseJsonSchema != null) {\n common.setValueByPath(\n toObject,\n ['responseJsonSchema'],\n fromResponseJsonSchema,\n );\n }\n\n if (common.getValueByPath(fromObject, ['routingConfig']) !== undefined) {\n throw new Error('routingConfig parameter is not supported in Gemini API.');\n }\n\n if (\n common.getValueByPath(fromObject, ['modelSelectionConfig']) !== undefined\n ) {\n throw new Error(\n 'modelSelectionConfig parameter is not supported in Gemini API.',\n );\n }\n\n const fromSafetySettings = common.getValueByPath(fromObject, [\n 'safetySettings',\n ]);\n if (parentObject !== undefined && fromSafetySettings != null) {\n let transformedList = fromSafetySettings;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return safetySettingToMldev(item);\n });\n }\n common.setValueByPath(parentObject, ['safetySettings'], transformedList);\n }\n\n const fromTools = common.getValueByPath(fromObject, ['tools']);\n if (parentObject !== undefined && fromTools != null) {\n let transformedList = t.tTools(fromTools);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return toolToMldev(t.tTool(item));\n });\n }\n common.setValueByPath(parentObject, ['tools'], transformedList);\n }\n\n const fromToolConfig = common.getValueByPath(fromObject, ['toolConfig']);\n if (parentObject !== undefined && fromToolConfig != null) {\n common.setValueByPath(\n parentObject,\n ['toolConfig'],\n toolConfigToMldev(fromToolConfig),\n );\n }\n\n if (common.getValueByPath(fromObject, ['labels']) !== undefined) {\n throw new Error('labels parameter is not supported in Gemini API.');\n }\n\n const fromCachedContent = common.getValueByPath(fromObject, [\n 'cachedContent',\n ]);\n if (parentObject !== undefined && fromCachedContent != null) {\n common.setValueByPath(\n parentObject,\n ['cachedContent'],\n t.tCachedContentName(apiClient, fromCachedContent),\n );\n }\n\n const fromResponseModalities = common.getValueByPath(fromObject, [\n 'responseModalities',\n ]);\n if (fromResponseModalities != null) {\n common.setValueByPath(\n toObject,\n ['responseModalities'],\n fromResponseModalities,\n );\n }\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (fromMediaResolution != null) {\n common.setValueByPath(toObject, ['mediaResolution'], fromMediaResolution);\n }\n\n const fromSpeechConfig = common.getValueByPath(fromObject, ['speechConfig']);\n if (fromSpeechConfig != null) {\n common.setValueByPath(\n toObject,\n ['speechConfig'],\n t.tSpeechConfig(fromSpeechConfig),\n );\n }\n\n if (common.getValueByPath(fromObject, ['audioTimestamp']) !== undefined) {\n throw new Error('audioTimestamp parameter is not supported in Gemini API.');\n }\n\n const fromThinkingConfig = common.getValueByPath(fromObject, [\n 'thinkingConfig',\n ]);\n if (fromThinkingConfig != null) {\n common.setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig);\n }\n\n const fromImageConfig = common.getValueByPath(fromObject, ['imageConfig']);\n if (fromImageConfig != null) {\n common.setValueByPath(\n toObject,\n ['imageConfig'],\n imageConfigToMldev(fromImageConfig),\n );\n }\n\n const fromEnableEnhancedCivicAnswers = common.getValueByPath(fromObject, [\n 'enableEnhancedCivicAnswers',\n ]);\n if (fromEnableEnhancedCivicAnswers != null) {\n common.setValueByPath(\n toObject,\n ['enableEnhancedCivicAnswers'],\n fromEnableEnhancedCivicAnswers,\n );\n }\n\n if (common.getValueByPath(fromObject, ['modelArmorConfig']) !== undefined) {\n throw new Error(\n 'modelArmorConfig parameter is not supported in Gemini API.',\n );\n }\n\n return toObject;\n}\n\nexport function generateContentResponseFromMldev(\n fromObject: types.GenerateContentResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromCandidates = common.getValueByPath(fromObject, ['candidates']);\n if (fromCandidates != null) {\n let transformedList = fromCandidates;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return candidateFromMldev(item);\n });\n }\n common.setValueByPath(toObject, ['candidates'], transformedList);\n }\n\n const fromModelVersion = common.getValueByPath(fromObject, ['modelVersion']);\n if (fromModelVersion != null) {\n common.setValueByPath(toObject, ['modelVersion'], fromModelVersion);\n }\n\n const fromPromptFeedback = common.getValueByPath(fromObject, [\n 'promptFeedback',\n ]);\n if (fromPromptFeedback != null) {\n common.setValueByPath(toObject, ['promptFeedback'], fromPromptFeedback);\n }\n\n const fromResponseId = common.getValueByPath(fromObject, ['responseId']);\n if (fromResponseId != null) {\n common.setValueByPath(toObject, ['responseId'], fromResponseId);\n }\n\n const fromUsageMetadata = common.getValueByPath(fromObject, [\n 'usageMetadata',\n ]);\n if (fromUsageMetadata != null) {\n common.setValueByPath(toObject, ['usageMetadata'], fromUsageMetadata);\n }\n\n return toObject;\n}\n\nexport function getBatchJobParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.GetBatchJobParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tBatchJobName(apiClient, fromName),\n );\n }\n\n return toObject;\n}\n\nexport function getBatchJobParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.GetBatchJobParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tBatchJobName(apiClient, fromName),\n );\n }\n\n return toObject;\n}\n\nexport function googleMapsToMldev(\n fromObject: types.GoogleMaps,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['authConfig']) !== undefined) {\n throw new Error('authConfig parameter is not supported in Gemini API.');\n }\n\n const fromEnableWidget = common.getValueByPath(fromObject, ['enableWidget']);\n if (fromEnableWidget != null) {\n common.setValueByPath(toObject, ['enableWidget'], fromEnableWidget);\n }\n\n return toObject;\n}\n\nexport function googleSearchToMldev(\n fromObject: types.GoogleSearch,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['excludeDomains']) !== undefined) {\n throw new Error('excludeDomains parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['blockingConfidence']) !== undefined) {\n throw new Error(\n 'blockingConfidence parameter is not supported in Gemini API.',\n );\n }\n\n const fromTimeRangeFilter = common.getValueByPath(fromObject, [\n 'timeRangeFilter',\n ]);\n if (fromTimeRangeFilter != null) {\n common.setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter);\n }\n\n return toObject;\n}\n\nexport function imageConfigToMldev(\n fromObject: types.ImageConfig,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromAspectRatio = common.getValueByPath(fromObject, ['aspectRatio']);\n if (fromAspectRatio != null) {\n common.setValueByPath(toObject, ['aspectRatio'], fromAspectRatio);\n }\n\n const fromImageSize = common.getValueByPath(fromObject, ['imageSize']);\n if (fromImageSize != null) {\n common.setValueByPath(toObject, ['imageSize'], fromImageSize);\n }\n\n if (common.getValueByPath(fromObject, ['personGeneration']) !== undefined) {\n throw new Error(\n 'personGeneration parameter is not supported in Gemini API.',\n );\n }\n\n if (common.getValueByPath(fromObject, ['outputMimeType']) !== undefined) {\n throw new Error('outputMimeType parameter is not supported in Gemini API.');\n }\n\n if (\n common.getValueByPath(fromObject, ['outputCompressionQuality']) !==\n undefined\n ) {\n throw new Error(\n 'outputCompressionQuality parameter is not supported in Gemini API.',\n );\n }\n\n return toObject;\n}\n\nexport function inlinedRequestToMldev(\n apiClient: ApiClient,\n fromObject: types.InlinedRequest,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['request', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromContents = common.getValueByPath(fromObject, ['contents']);\n if (fromContents != null) {\n let transformedList = t.tContents(fromContents);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return contentToMldev(item);\n });\n }\n common.setValueByPath(toObject, ['request', 'contents'], transformedList);\n }\n\n const fromMetadata = common.getValueByPath(fromObject, ['metadata']);\n if (fromMetadata != null) {\n common.setValueByPath(toObject, ['metadata'], fromMetadata);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n common.setValueByPath(\n toObject,\n ['request', 'generationConfig'],\n generateContentConfigToMldev(\n apiClient,\n fromConfig,\n common.getValueByPath(toObject, ['request'], {}) as Record<\n string,\n unknown\n >,\n ),\n );\n }\n\n return toObject;\n}\n\nexport function inlinedResponseFromMldev(\n fromObject: types.InlinedResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromResponse = common.getValueByPath(fromObject, ['response']);\n if (fromResponse != null) {\n common.setValueByPath(\n toObject,\n ['response'],\n generateContentResponseFromMldev(\n fromResponse as types.GenerateContentResponse,\n ),\n );\n }\n\n const fromMetadata = common.getValueByPath(fromObject, ['metadata']);\n if (fromMetadata != null) {\n common.setValueByPath(toObject, ['metadata'], fromMetadata);\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n return toObject;\n}\n\nexport function listBatchJobsConfigToMldev(\n fromObject: types.ListBatchJobsConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPageSize = common.getValueByPath(fromObject, ['pageSize']);\n if (parentObject !== undefined && fromPageSize != null) {\n common.setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize);\n }\n\n const fromPageToken = common.getValueByPath(fromObject, ['pageToken']);\n if (parentObject !== undefined && fromPageToken != null) {\n common.setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken);\n }\n\n if (common.getValueByPath(fromObject, ['filter']) !== undefined) {\n throw new Error('filter parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function listBatchJobsConfigToVertex(\n fromObject: types.ListBatchJobsConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPageSize = common.getValueByPath(fromObject, ['pageSize']);\n if (parentObject !== undefined && fromPageSize != null) {\n common.setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize);\n }\n\n const fromPageToken = common.getValueByPath(fromObject, ['pageToken']);\n if (parentObject !== undefined && fromPageToken != null) {\n common.setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken);\n }\n\n const fromFilter = common.getValueByPath(fromObject, ['filter']);\n if (parentObject !== undefined && fromFilter != null) {\n common.setValueByPath(parentObject, ['_query', 'filter'], fromFilter);\n }\n\n return toObject;\n}\n\nexport function listBatchJobsParametersToMldev(\n fromObject: types.ListBatchJobsParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n listBatchJobsConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function listBatchJobsParametersToVertex(\n fromObject: types.ListBatchJobsParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n listBatchJobsConfigToVertex(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function listBatchJobsResponseFromMldev(\n fromObject: types.ListBatchJobsResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromNextPageToken = common.getValueByPath(fromObject, [\n 'nextPageToken',\n ]);\n if (fromNextPageToken != null) {\n common.setValueByPath(toObject, ['nextPageToken'], fromNextPageToken);\n }\n\n const fromBatchJobs = common.getValueByPath(fromObject, ['operations']);\n if (fromBatchJobs != null) {\n let transformedList = fromBatchJobs;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return batchJobFromMldev(item);\n });\n }\n common.setValueByPath(toObject, ['batchJobs'], transformedList);\n }\n\n return toObject;\n}\n\nexport function listBatchJobsResponseFromVertex(\n fromObject: types.ListBatchJobsResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromNextPageToken = common.getValueByPath(fromObject, [\n 'nextPageToken',\n ]);\n if (fromNextPageToken != null) {\n common.setValueByPath(toObject, ['nextPageToken'], fromNextPageToken);\n }\n\n const fromBatchJobs = common.getValueByPath(fromObject, [\n 'batchPredictionJobs',\n ]);\n if (fromBatchJobs != null) {\n let transformedList = fromBatchJobs;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return batchJobFromVertex(item);\n });\n }\n common.setValueByPath(toObject, ['batchJobs'], transformedList);\n }\n\n return toObject;\n}\n\nexport function partToMldev(fromObject: types.Part): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (fromMediaResolution != null) {\n common.setValueByPath(toObject, ['mediaResolution'], fromMediaResolution);\n }\n\n const fromCodeExecutionResult = common.getValueByPath(fromObject, [\n 'codeExecutionResult',\n ]);\n if (fromCodeExecutionResult != null) {\n common.setValueByPath(\n toObject,\n ['codeExecutionResult'],\n fromCodeExecutionResult,\n );\n }\n\n const fromExecutableCode = common.getValueByPath(fromObject, [\n 'executableCode',\n ]);\n if (fromExecutableCode != null) {\n common.setValueByPath(toObject, ['executableCode'], fromExecutableCode);\n }\n\n const fromFileData = common.getValueByPath(fromObject, ['fileData']);\n if (fromFileData != null) {\n common.setValueByPath(\n toObject,\n ['fileData'],\n fileDataToMldev(fromFileData),\n );\n }\n\n const fromFunctionCall = common.getValueByPath(fromObject, ['functionCall']);\n if (fromFunctionCall != null) {\n common.setValueByPath(\n toObject,\n ['functionCall'],\n functionCallToMldev(fromFunctionCall),\n );\n }\n\n const fromFunctionResponse = common.getValueByPath(fromObject, [\n 'functionResponse',\n ]);\n if (fromFunctionResponse != null) {\n common.setValueByPath(toObject, ['functionResponse'], fromFunctionResponse);\n }\n\n const fromInlineData = common.getValueByPath(fromObject, ['inlineData']);\n if (fromInlineData != null) {\n common.setValueByPath(\n toObject,\n ['inlineData'],\n blobToMldev(fromInlineData),\n );\n }\n\n const fromText = common.getValueByPath(fromObject, ['text']);\n if (fromText != null) {\n common.setValueByPath(toObject, ['text'], fromText);\n }\n\n const fromThought = common.getValueByPath(fromObject, ['thought']);\n if (fromThought != null) {\n common.setValueByPath(toObject, ['thought'], fromThought);\n }\n\n const fromThoughtSignature = common.getValueByPath(fromObject, [\n 'thoughtSignature',\n ]);\n if (fromThoughtSignature != null) {\n common.setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature);\n }\n\n const fromVideoMetadata = common.getValueByPath(fromObject, [\n 'videoMetadata',\n ]);\n if (fromVideoMetadata != null) {\n common.setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata);\n }\n\n return toObject;\n}\n\nexport function safetySettingToMldev(\n fromObject: types.SafetySetting,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromCategory = common.getValueByPath(fromObject, ['category']);\n if (fromCategory != null) {\n common.setValueByPath(toObject, ['category'], fromCategory);\n }\n\n if (common.getValueByPath(fromObject, ['method']) !== undefined) {\n throw new Error('method parameter is not supported in Gemini API.');\n }\n\n const fromThreshold = common.getValueByPath(fromObject, ['threshold']);\n if (fromThreshold != null) {\n common.setValueByPath(toObject, ['threshold'], fromThreshold);\n }\n\n return toObject;\n}\n\nexport function toolConfigToMldev(\n fromObject: types.ToolConfig,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromRetrievalConfig = common.getValueByPath(fromObject, [\n 'retrievalConfig',\n ]);\n if (fromRetrievalConfig != null) {\n common.setValueByPath(toObject, ['retrievalConfig'], fromRetrievalConfig);\n }\n\n const fromFunctionCallingConfig = common.getValueByPath(fromObject, [\n 'functionCallingConfig',\n ]);\n if (fromFunctionCallingConfig != null) {\n common.setValueByPath(\n toObject,\n ['functionCallingConfig'],\n functionCallingConfigToMldev(fromFunctionCallingConfig),\n );\n }\n\n return toObject;\n}\n\nexport function toolToMldev(fromObject: types.Tool): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['retrieval']) !== undefined) {\n throw new Error('retrieval parameter is not supported in Gemini API.');\n }\n\n const fromComputerUse = common.getValueByPath(fromObject, ['computerUse']);\n if (fromComputerUse != null) {\n common.setValueByPath(toObject, ['computerUse'], fromComputerUse);\n }\n\n const fromFileSearch = common.getValueByPath(fromObject, ['fileSearch']);\n if (fromFileSearch != null) {\n common.setValueByPath(toObject, ['fileSearch'], fromFileSearch);\n }\n\n const fromCodeExecution = common.getValueByPath(fromObject, [\n 'codeExecution',\n ]);\n if (fromCodeExecution != null) {\n common.setValueByPath(toObject, ['codeExecution'], fromCodeExecution);\n }\n\n if (\n common.getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined\n ) {\n throw new Error(\n 'enterpriseWebSearch parameter is not supported in Gemini API.',\n );\n }\n\n const fromFunctionDeclarations = common.getValueByPath(fromObject, [\n 'functionDeclarations',\n ]);\n if (fromFunctionDeclarations != null) {\n let transformedList = fromFunctionDeclarations;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['functionDeclarations'], transformedList);\n }\n\n const fromGoogleMaps = common.getValueByPath(fromObject, ['googleMaps']);\n if (fromGoogleMaps != null) {\n common.setValueByPath(\n toObject,\n ['googleMaps'],\n googleMapsToMldev(fromGoogleMaps),\n );\n }\n\n const fromGoogleSearch = common.getValueByPath(fromObject, ['googleSearch']);\n if (fromGoogleSearch != null) {\n common.setValueByPath(\n toObject,\n ['googleSearch'],\n googleSearchToMldev(fromGoogleSearch),\n );\n }\n\n const fromGoogleSearchRetrieval = common.getValueByPath(fromObject, [\n 'googleSearchRetrieval',\n ]);\n if (fromGoogleSearchRetrieval != null) {\n common.setValueByPath(\n toObject,\n ['googleSearchRetrieval'],\n fromGoogleSearchRetrieval,\n );\n }\n\n const fromUrlContext = common.getValueByPath(fromObject, ['urlContext']);\n if (fromUrlContext != null) {\n common.setValueByPath(toObject, ['urlContext'], fromUrlContext);\n }\n\n return toObject;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Pagers for the GenAI List APIs.\n */\n\nimport * as types from '../src/types';\n\nexport enum PagedItem {\n PAGED_ITEM_BATCH_JOBS = 'batchJobs',\n PAGED_ITEM_MODELS = 'models',\n PAGED_ITEM_TUNING_JOBS = 'tuningJobs',\n PAGED_ITEM_FILES = 'files',\n PAGED_ITEM_CACHED_CONTENTS = 'cachedContents',\n PAGED_ITEM_FILE_SEARCH_STORES = 'fileSearchStores',\n PAGED_ITEM_DOCUMENTS = 'documents',\n}\n\nexport interface PagedItemConfig {\n parent?: string;\n config?: {\n pageToken?: string;\n pageSize?: number;\n };\n}\n\ninterface PagedItemResponse<T> {\n nextPageToken?: string;\n sdkHttpResponse?: types.HttpResponse;\n batchJobs?: T[];\n models?: T[];\n tuningJobs?: T[];\n files?: T[];\n cachedContents?: T[];\n fileSearchStores?: T[];\n documents?: T[];\n}\n\n/**\n * Pager class for iterating through paginated results.\n */\nexport class Pager<T> implements AsyncIterable<T> {\n private nameInternal!: PagedItem;\n private pageInternal: T[] = [];\n private paramsInternal: PagedItemConfig = {};\n private pageInternalSize!: number;\n private sdkHttpResponseInternal?: types.HttpResponse;\n protected requestInternal!: (\n params: PagedItemConfig,\n ) => Promise<PagedItemResponse<T>>;\n protected idxInternal!: number;\n\n constructor(\n name: PagedItem,\n request: (params: PagedItemConfig) => Promise<PagedItemResponse<T>>,\n response: PagedItemResponse<T>,\n params: PagedItemConfig,\n ) {\n this.requestInternal = request;\n this.init(name, response, params);\n }\n\n private init(\n name: PagedItem,\n response: PagedItemResponse<T>,\n params: PagedItemConfig,\n ) {\n this.nameInternal = name;\n this.pageInternal = response[this.nameInternal] || [];\n\n this.sdkHttpResponseInternal = response?.sdkHttpResponse;\n this.idxInternal = 0;\n let requestParams: PagedItemConfig = {config: {}};\n if (!params || Object.keys(params).length === 0) {\n requestParams = {config: {}};\n } else if (typeof params === 'object') {\n requestParams = {...params};\n } else {\n requestParams = params;\n }\n if (requestParams['config']) {\n requestParams['config']['pageToken'] = response['nextPageToken'];\n }\n this.paramsInternal = requestParams;\n this.pageInternalSize =\n requestParams['config']?.['pageSize'] ?? this.pageInternal.length;\n }\n\n private initNextPage(response: PagedItemResponse<T>): void {\n this.init(this.nameInternal, response, this.paramsInternal);\n }\n\n /**\n * Returns the current page, which is a list of items.\n *\n * @remarks\n * The first page is retrieved when the pager is created. The returned list of\n * items could be a subset of the entire list.\n */\n get page(): T[] {\n return this.pageInternal;\n }\n\n /**\n * Returns the type of paged item (for example, ``batch_jobs``).\n */\n get name(): PagedItem {\n return this.nameInternal;\n }\n\n /**\n * Returns the length of the page fetched each time by this pager.\n *\n * @remarks\n * The number of items in the page is less than or equal to the page length.\n */\n get pageSize(): number {\n return this.pageInternalSize;\n }\n\n /**\n * Returns the headers of the API response.\n */\n get sdkHttpResponse(): types.HttpResponse | undefined {\n return this.sdkHttpResponseInternal;\n }\n\n /**\n * Returns the parameters when making the API request for the next page.\n *\n * @remarks\n * Parameters contain a set of optional configs that can be\n * used to customize the API request. For example, the `pageToken` parameter\n * contains the token to request the next page.\n */\n get params(): PagedItemConfig {\n return this.paramsInternal;\n }\n\n /**\n * Returns the total number of items in the current page.\n */\n get pageLength(): number {\n return this.pageInternal.length;\n }\n\n /**\n * Returns the item at the given index.\n */\n getItem(index: number): T {\n return this.pageInternal[index];\n }\n\n /**\n * Returns an async iterator that support iterating through all items\n * retrieved from the API.\n *\n * @remarks\n * The iterator will automatically fetch the next page if there are more items\n * to fetch from the API.\n *\n * @example\n *\n * ```ts\n * const pager = await ai.files.list({config: {pageSize: 10}});\n * for await (const file of pager) {\n * console.log(file.name);\n * }\n * ```\n */\n [Symbol.asyncIterator](): AsyncIterator<T> {\n return {\n next: async () => {\n if (this.idxInternal >= this.pageLength) {\n if (this.hasNextPage()) {\n await this.nextPage();\n } else {\n return {value: undefined, done: true};\n }\n }\n const item = this.getItem(this.idxInternal);\n this.idxInternal += 1;\n return {value: item, done: false};\n },\n return: async () => {\n return {value: undefined, done: true};\n },\n };\n }\n\n /**\n * Fetches the next page of items. This makes a new API request.\n *\n * @throws {Error} If there are no more pages to fetch.\n *\n * @example\n *\n * ```ts\n * const pager = await ai.files.list({config: {pageSize: 10}});\n * let page = pager.page;\n * while (true) {\n * for (const file of page) {\n * console.log(file.name);\n * }\n * if (!pager.hasNextPage()) {\n * break;\n * }\n * page = await pager.nextPage();\n * }\n * ```\n */\n async nextPage(): Promise<T[]> {\n if (!this.hasNextPage()) {\n throw new Error('No more pages to fetch.');\n }\n const response = await this.requestInternal(this.params);\n this.initNextPage(response);\n return this.page;\n }\n\n /**\n * Returns true if there are more pages to fetch from the API.\n */\n hasNextPage(): boolean {\n if (this.params['config']?.['pageToken'] !== undefined) {\n return true;\n }\n return false;\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport {ApiClient} from './_api_client.js';\nimport * as common from './_common.js';\nimport {BaseModule} from './_common.js';\nimport * as converters from './converters/_batches_converters.js';\nimport {PagedItem, Pager} from './pagers.js';\nimport * as types from './types.js';\n\nexport class Batches extends BaseModule {\n constructor(private readonly apiClient: ApiClient) {\n super();\n }\n\n /**\n * Lists batch jobs.\n *\n * @param params - The parameters for the list request.\n * @return - A pager of batch jobs.\n *\n * @example\n * ```ts\n * const batchJobs = await ai.batches.list({config: {'pageSize': 2}});\n * for await (const batchJob of batchJobs) {\n * console.log(batchJob);\n * }\n * ```\n */\n list = async (\n params: types.ListBatchJobsParameters = {},\n ): Promise<Pager<types.BatchJob>> => {\n return new Pager<types.BatchJob>(\n PagedItem.PAGED_ITEM_BATCH_JOBS,\n (x: types.ListBatchJobsParameters) => this.listInternal(x),\n await this.listInternal(params),\n params,\n );\n };\n\n /**\n * Create batch job.\n *\n * @param params - The parameters for create batch job request.\n * @return The created batch job.\n *\n * @example\n * ```ts\n * const response = await ai.batches.create({\n * model: 'gemini-2.0-flash',\n * src: {gcsUri: 'gs://bucket/path/to/file.jsonl', format: 'jsonl'},\n * config: {\n * dest: {gcsUri: 'gs://bucket/path/output/directory', format: 'jsonl'},\n * }\n * });\n * console.log(response);\n * ```\n */\n create = async (\n params: types.CreateBatchJobParameters,\n ): Promise<types.BatchJob> => {\n if (this.apiClient.isVertexAI()) {\n // Format destination if not provided\n // Cast params.src as Vertex AI path does not handle InlinedRequest[]\n params.config = this.formatDestination(\n params.src as string | types.BatchJobSource,\n params.config,\n );\n }\n return this.createInternal(params);\n };\n\n /**\n * **Experimental** Creates an embedding batch job.\n *\n * @param params - The parameters for create embedding batch job request.\n * @return The created batch job.\n *\n * @example\n * ```ts\n * const response = await ai.batches.createEmbeddings({\n * model: 'text-embedding-004',\n * src: {fileName: 'files/my_embedding_input'},\n * });\n * console.log(response);\n * ```\n */\n createEmbeddings = async (\n params: types.CreateEmbeddingsBatchJobParameters,\n ): Promise<types.BatchJob> => {\n console.warn(\n 'batches.createEmbeddings() is experimental and may change without notice.',\n );\n\n if (this.apiClient.isVertexAI()) {\n throw new Error('Vertex AI does not support batches.createEmbeddings.');\n }\n\n return this.createEmbeddingsInternal(params);\n };\n\n // Helper function to handle inlined generate content requests\n private createInlinedGenerateContentRequest(\n params: types.CreateBatchJobParameters,\n ): {path: string; body: Record<string, unknown>} {\n const body = converters.createBatchJobParametersToMldev(\n this.apiClient, // Use instance apiClient\n params,\n );\n\n const urlParams = body['_url'] as Record<string, unknown>;\n const path = common.formatMap('{model}:batchGenerateContent', urlParams);\n\n const batch = body['batch'] as {[key: string]: unknown};\n const inputConfig = batch['inputConfig'] as {[key: string]: unknown};\n const requestsWrapper = inputConfig['requests'] as {\n [key: string]: unknown;\n };\n const requests = requestsWrapper['requests'] as Array<{\n [key: string]: unknown;\n }>;\n const newRequests = [];\n\n for (const request of requests) {\n const requestDict = {...request}; // Clone\n if (requestDict['systemInstruction']) {\n const systemInstructionValue = requestDict['systemInstruction'];\n delete requestDict['systemInstruction'];\n const requestContent = requestDict['request'] as {\n [key: string]: unknown;\n };\n requestContent['systemInstruction'] = systemInstructionValue;\n requestDict['request'] = requestContent;\n }\n newRequests.push(requestDict);\n }\n requestsWrapper['requests'] = newRequests;\n\n delete body['config'];\n delete body['_url'];\n delete body['_query'];\n\n return {path, body};\n }\n\n // Helper function to get the first GCS URI\n private getGcsUri(src: string | types.BatchJobSource): string | undefined {\n if (typeof src === 'string') {\n return src.startsWith('gs://') ? src : undefined;\n }\n if (!Array.isArray(src) && src.gcsUri && src.gcsUri.length > 0) {\n return src.gcsUri[0];\n }\n return undefined;\n }\n\n // Helper function to get the BigQuery URI\n private getBigqueryUri(\n src: string | types.BatchJobSource,\n ): string | undefined {\n if (typeof src === 'string') {\n return src.startsWith('bq://') ? src : undefined;\n }\n if (!Array.isArray(src)) {\n return src.bigqueryUri;\n }\n return undefined;\n }\n\n // Function to format the destination configuration for Vertex AI\n private formatDestination(\n src: string | types.BatchJobSource,\n config?: types.CreateBatchJobConfig,\n ): types.CreateBatchJobConfig {\n const newConfig = config ? {...config} : {};\n\n const timestampStr = Date.now().toString();\n\n if (!newConfig.displayName) {\n newConfig.displayName = `genaiBatchJob_${timestampStr}`;\n }\n\n if (newConfig.dest === undefined) {\n const gcsUri = this.getGcsUri(src);\n const bigqueryUri = this.getBigqueryUri(src);\n\n if (gcsUri) {\n if (gcsUri.endsWith('.jsonl')) {\n // For .jsonl files, remove suffix and add /dest\n newConfig.dest = `${gcsUri.slice(0, -6)}/dest`;\n } else {\n // Fallback for other GCS URIs\n newConfig.dest = `${gcsUri}_dest_${timestampStr}`;\n }\n } else if (bigqueryUri) {\n newConfig.dest = `${bigqueryUri}_dest_${timestampStr}`;\n } else {\n throw new Error(\n 'Unsupported source for Vertex AI: No GCS or BigQuery URI found.',\n );\n }\n }\n return newConfig;\n }\n\n /**\n * Internal method to create batch job.\n *\n * @param params - The parameters for create batch job request.\n * @return The created batch job.\n *\n */\n private async createInternal(\n params: types.CreateBatchJobParameters,\n ): Promise<types.BatchJob> {\n let response: Promise<types.BatchJob>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.createBatchJobParametersToVertex(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n 'batchPredictionJobs',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.BatchJob>;\n\n return response.then((apiResponse) => {\n const resp = converters.batchJobFromVertex(apiResponse);\n\n return resp as types.BatchJob;\n });\n } else {\n const body = converters.createBatchJobParametersToMldev(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n '{model}:batchGenerateContent',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.BatchJob>;\n\n return response.then((apiResponse) => {\n const resp = converters.batchJobFromMldev(apiResponse);\n\n return resp as types.BatchJob;\n });\n }\n }\n\n /**\n * Internal method to create batch job.\n *\n * @param params - The parameters for create batch job request.\n * @return The created batch job.\n *\n */\n private async createEmbeddingsInternal(\n params: types.CreateEmbeddingsBatchJobParameters,\n ): Promise<types.BatchJob> {\n let response: Promise<types.BatchJob>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.createEmbeddingsBatchJobParametersToMldev(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n '{model}:asyncBatchEmbedContent',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.BatchJob>;\n\n return response.then((apiResponse) => {\n const resp = converters.batchJobFromMldev(apiResponse);\n\n return resp as types.BatchJob;\n });\n }\n }\n\n /**\n * Gets batch job configurations.\n *\n * @param params - The parameters for the get request.\n * @return The batch job.\n *\n * @example\n * ```ts\n * await ai.batches.get({name: '...'}); // The server-generated resource name.\n * ```\n */\n async get(params: types.GetBatchJobParameters): Promise<types.BatchJob> {\n let response: Promise<types.BatchJob>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.getBatchJobParametersToVertex(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n 'batchPredictionJobs/{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.BatchJob>;\n\n return response.then((apiResponse) => {\n const resp = converters.batchJobFromVertex(apiResponse);\n\n return resp as types.BatchJob;\n });\n } else {\n const body = converters.getBatchJobParametersToMldev(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n 'batches/{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.BatchJob>;\n\n return response.then((apiResponse) => {\n const resp = converters.batchJobFromMldev(apiResponse);\n\n return resp as types.BatchJob;\n });\n }\n }\n\n /**\n * Cancels a batch job.\n *\n * @param params - The parameters for the cancel request.\n * @return The empty response returned by the API.\n *\n * @example\n * ```ts\n * await ai.batches.cancel({name: '...'}); // The server-generated resource name.\n * ```\n */\n async cancel(params: types.CancelBatchJobParameters): Promise<void> {\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.cancelBatchJobParametersToVertex(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n 'batchPredictionJobs/{name}:cancel',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n await this.apiClient.request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n });\n } else {\n const body = converters.cancelBatchJobParametersToMldev(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n 'batches/{name}:cancel',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n await this.apiClient.request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n });\n }\n }\n\n private async listInternal(\n params: types.ListBatchJobsParameters,\n ): Promise<types.ListBatchJobsResponse> {\n let response: Promise<types.ListBatchJobsResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.listBatchJobsParametersToVertex(params);\n path = common.formatMap(\n 'batchPredictionJobs',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.ListBatchJobsResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.ListBatchJobsResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.listBatchJobsResponseFromVertex(apiResponse);\n const typedResp = new types.ListBatchJobsResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n const body = converters.listBatchJobsParametersToMldev(params);\n path = common.formatMap(\n 'batches',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.ListBatchJobsResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.ListBatchJobsResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.listBatchJobsResponseFromMldev(apiResponse);\n const typedResp = new types.ListBatchJobsResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n /**\n * Deletes a batch job.\n *\n * @param params - The parameters for the delete request.\n * @return The empty response returned by the API.\n *\n * @example\n * ```ts\n * await ai.batches.delete({name: '...'}); // The server-generated resource name.\n * ```\n */\n async delete(\n params: types.DeleteBatchJobParameters,\n ): Promise<types.DeleteResourceJob> {\n let response: Promise<types.DeleteResourceJob>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.deleteBatchJobParametersToVertex(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n 'batchPredictionJobs/{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'DELETE',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.DeleteResourceJob;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.DeleteResourceJob>;\n\n return response.then((apiResponse) => {\n const resp = converters.deleteResourceJobFromVertex(apiResponse);\n\n return resp as types.DeleteResourceJob;\n });\n } else {\n const body = converters.deleteBatchJobParametersToMldev(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n 'batches/{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'DELETE',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.DeleteResourceJob;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.DeleteResourceJob>;\n\n return response.then((apiResponse) => {\n const resp = converters.deleteResourceJobFromMldev(apiResponse);\n\n return resp as types.DeleteResourceJob;\n });\n }\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport {ApiClient} from '../_api_client.js';\nimport * as common from '../_common.js';\nimport * as t from '../_transformers.js';\nimport type * as types from '../types.js';\n\nexport function blobToMldev(fromObject: types.Blob): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromData = common.getValueByPath(fromObject, ['data']);\n if (fromData != null) {\n common.setValueByPath(toObject, ['data'], fromData);\n }\n\n if (common.getValueByPath(fromObject, ['displayName']) !== undefined) {\n throw new Error('displayName parameter is not supported in Gemini API.');\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function contentToMldev(\n fromObject: types.Content,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromParts = common.getValueByPath(fromObject, ['parts']);\n if (fromParts != null) {\n let transformedList = fromParts;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return partToMldev(item);\n });\n }\n common.setValueByPath(toObject, ['parts'], transformedList);\n }\n\n const fromRole = common.getValueByPath(fromObject, ['role']);\n if (fromRole != null) {\n common.setValueByPath(toObject, ['role'], fromRole);\n }\n\n return toObject;\n}\n\nexport function createCachedContentConfigToMldev(\n fromObject: types.CreateCachedContentConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromTtl = common.getValueByPath(fromObject, ['ttl']);\n if (parentObject !== undefined && fromTtl != null) {\n common.setValueByPath(parentObject, ['ttl'], fromTtl);\n }\n\n const fromExpireTime = common.getValueByPath(fromObject, ['expireTime']);\n if (parentObject !== undefined && fromExpireTime != null) {\n common.setValueByPath(parentObject, ['expireTime'], fromExpireTime);\n }\n\n const fromDisplayName = common.getValueByPath(fromObject, ['displayName']);\n if (parentObject !== undefined && fromDisplayName != null) {\n common.setValueByPath(parentObject, ['displayName'], fromDisplayName);\n }\n\n const fromContents = common.getValueByPath(fromObject, ['contents']);\n if (parentObject !== undefined && fromContents != null) {\n let transformedList = t.tContents(fromContents);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return contentToMldev(item);\n });\n }\n common.setValueByPath(parentObject, ['contents'], transformedList);\n }\n\n const fromSystemInstruction = common.getValueByPath(fromObject, [\n 'systemInstruction',\n ]);\n if (parentObject !== undefined && fromSystemInstruction != null) {\n common.setValueByPath(\n parentObject,\n ['systemInstruction'],\n contentToMldev(t.tContent(fromSystemInstruction)),\n );\n }\n\n const fromTools = common.getValueByPath(fromObject, ['tools']);\n if (parentObject !== undefined && fromTools != null) {\n let transformedList = fromTools;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return toolToMldev(item);\n });\n }\n common.setValueByPath(parentObject, ['tools'], transformedList);\n }\n\n const fromToolConfig = common.getValueByPath(fromObject, ['toolConfig']);\n if (parentObject !== undefined && fromToolConfig != null) {\n common.setValueByPath(\n parentObject,\n ['toolConfig'],\n toolConfigToMldev(fromToolConfig),\n );\n }\n\n if (common.getValueByPath(fromObject, ['kmsKeyName']) !== undefined) {\n throw new Error('kmsKeyName parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function createCachedContentConfigToVertex(\n fromObject: types.CreateCachedContentConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromTtl = common.getValueByPath(fromObject, ['ttl']);\n if (parentObject !== undefined && fromTtl != null) {\n common.setValueByPath(parentObject, ['ttl'], fromTtl);\n }\n\n const fromExpireTime = common.getValueByPath(fromObject, ['expireTime']);\n if (parentObject !== undefined && fromExpireTime != null) {\n common.setValueByPath(parentObject, ['expireTime'], fromExpireTime);\n }\n\n const fromDisplayName = common.getValueByPath(fromObject, ['displayName']);\n if (parentObject !== undefined && fromDisplayName != null) {\n common.setValueByPath(parentObject, ['displayName'], fromDisplayName);\n }\n\n const fromContents = common.getValueByPath(fromObject, ['contents']);\n if (parentObject !== undefined && fromContents != null) {\n let transformedList = t.tContents(fromContents);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(parentObject, ['contents'], transformedList);\n }\n\n const fromSystemInstruction = common.getValueByPath(fromObject, [\n 'systemInstruction',\n ]);\n if (parentObject !== undefined && fromSystemInstruction != null) {\n common.setValueByPath(\n parentObject,\n ['systemInstruction'],\n t.tContent(fromSystemInstruction),\n );\n }\n\n const fromTools = common.getValueByPath(fromObject, ['tools']);\n if (parentObject !== undefined && fromTools != null) {\n let transformedList = fromTools;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return toolToVertex(item);\n });\n }\n common.setValueByPath(parentObject, ['tools'], transformedList);\n }\n\n const fromToolConfig = common.getValueByPath(fromObject, ['toolConfig']);\n if (parentObject !== undefined && fromToolConfig != null) {\n common.setValueByPath(parentObject, ['toolConfig'], fromToolConfig);\n }\n\n const fromKmsKeyName = common.getValueByPath(fromObject, ['kmsKeyName']);\n if (parentObject !== undefined && fromKmsKeyName != null) {\n common.setValueByPath(\n parentObject,\n ['encryption_spec', 'kmsKeyName'],\n fromKmsKeyName,\n );\n }\n\n return toObject;\n}\n\nexport function createCachedContentParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.CreateCachedContentParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['model'],\n t.tCachesModel(apiClient, fromModel),\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n createCachedContentConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function createCachedContentParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.CreateCachedContentParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['model'],\n t.tCachesModel(apiClient, fromModel),\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n createCachedContentConfigToVertex(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function deleteCachedContentParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.DeleteCachedContentParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tCachedContentName(apiClient, fromName),\n );\n }\n\n return toObject;\n}\n\nexport function deleteCachedContentParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.DeleteCachedContentParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tCachedContentName(apiClient, fromName),\n );\n }\n\n return toObject;\n}\n\nexport function deleteCachedContentResponseFromMldev(\n fromObject: types.DeleteCachedContentResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n return toObject;\n}\n\nexport function deleteCachedContentResponseFromVertex(\n fromObject: types.DeleteCachedContentResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n return toObject;\n}\n\nexport function fileDataToMldev(\n fromObject: types.FileData,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['displayName']) !== undefined) {\n throw new Error('displayName parameter is not supported in Gemini API.');\n }\n\n const fromFileUri = common.getValueByPath(fromObject, ['fileUri']);\n if (fromFileUri != null) {\n common.setValueByPath(toObject, ['fileUri'], fromFileUri);\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function functionCallToMldev(\n fromObject: types.FunctionCall,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromId = common.getValueByPath(fromObject, ['id']);\n if (fromId != null) {\n common.setValueByPath(toObject, ['id'], fromId);\n }\n\n const fromArgs = common.getValueByPath(fromObject, ['args']);\n if (fromArgs != null) {\n common.setValueByPath(toObject, ['args'], fromArgs);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n if (common.getValueByPath(fromObject, ['partialArgs']) !== undefined) {\n throw new Error('partialArgs parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['willContinue']) !== undefined) {\n throw new Error('willContinue parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function functionCallingConfigToMldev(\n fromObject: types.FunctionCallingConfig,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromAllowedFunctionNames = common.getValueByPath(fromObject, [\n 'allowedFunctionNames',\n ]);\n if (fromAllowedFunctionNames != null) {\n common.setValueByPath(\n toObject,\n ['allowedFunctionNames'],\n fromAllowedFunctionNames,\n );\n }\n\n const fromMode = common.getValueByPath(fromObject, ['mode']);\n if (fromMode != null) {\n common.setValueByPath(toObject, ['mode'], fromMode);\n }\n\n if (\n common.getValueByPath(fromObject, ['streamFunctionCallArguments']) !==\n undefined\n ) {\n throw new Error(\n 'streamFunctionCallArguments parameter is not supported in Gemini API.',\n );\n }\n\n return toObject;\n}\n\nexport function functionDeclarationToVertex(\n fromObject: types.FunctionDeclaration,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromDescription = common.getValueByPath(fromObject, ['description']);\n if (fromDescription != null) {\n common.setValueByPath(toObject, ['description'], fromDescription);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromParameters = common.getValueByPath(fromObject, ['parameters']);\n if (fromParameters != null) {\n common.setValueByPath(toObject, ['parameters'], fromParameters);\n }\n\n const fromParametersJsonSchema = common.getValueByPath(fromObject, [\n 'parametersJsonSchema',\n ]);\n if (fromParametersJsonSchema != null) {\n common.setValueByPath(\n toObject,\n ['parametersJsonSchema'],\n fromParametersJsonSchema,\n );\n }\n\n const fromResponse = common.getValueByPath(fromObject, ['response']);\n if (fromResponse != null) {\n common.setValueByPath(toObject, ['response'], fromResponse);\n }\n\n const fromResponseJsonSchema = common.getValueByPath(fromObject, [\n 'responseJsonSchema',\n ]);\n if (fromResponseJsonSchema != null) {\n common.setValueByPath(\n toObject,\n ['responseJsonSchema'],\n fromResponseJsonSchema,\n );\n }\n\n if (common.getValueByPath(fromObject, ['behavior']) !== undefined) {\n throw new Error('behavior parameter is not supported in Vertex AI.');\n }\n\n return toObject;\n}\n\nexport function getCachedContentParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.GetCachedContentParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tCachedContentName(apiClient, fromName),\n );\n }\n\n return toObject;\n}\n\nexport function getCachedContentParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.GetCachedContentParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tCachedContentName(apiClient, fromName),\n );\n }\n\n return toObject;\n}\n\nexport function googleMapsToMldev(\n fromObject: types.GoogleMaps,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['authConfig']) !== undefined) {\n throw new Error('authConfig parameter is not supported in Gemini API.');\n }\n\n const fromEnableWidget = common.getValueByPath(fromObject, ['enableWidget']);\n if (fromEnableWidget != null) {\n common.setValueByPath(toObject, ['enableWidget'], fromEnableWidget);\n }\n\n return toObject;\n}\n\nexport function googleSearchToMldev(\n fromObject: types.GoogleSearch,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['excludeDomains']) !== undefined) {\n throw new Error('excludeDomains parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['blockingConfidence']) !== undefined) {\n throw new Error(\n 'blockingConfidence parameter is not supported in Gemini API.',\n );\n }\n\n const fromTimeRangeFilter = common.getValueByPath(fromObject, [\n 'timeRangeFilter',\n ]);\n if (fromTimeRangeFilter != null) {\n common.setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter);\n }\n\n return toObject;\n}\n\nexport function listCachedContentsConfigToMldev(\n fromObject: types.ListCachedContentsConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPageSize = common.getValueByPath(fromObject, ['pageSize']);\n if (parentObject !== undefined && fromPageSize != null) {\n common.setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize);\n }\n\n const fromPageToken = common.getValueByPath(fromObject, ['pageToken']);\n if (parentObject !== undefined && fromPageToken != null) {\n common.setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken);\n }\n\n return toObject;\n}\n\nexport function listCachedContentsConfigToVertex(\n fromObject: types.ListCachedContentsConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPageSize = common.getValueByPath(fromObject, ['pageSize']);\n if (parentObject !== undefined && fromPageSize != null) {\n common.setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize);\n }\n\n const fromPageToken = common.getValueByPath(fromObject, ['pageToken']);\n if (parentObject !== undefined && fromPageToken != null) {\n common.setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken);\n }\n\n return toObject;\n}\n\nexport function listCachedContentsParametersToMldev(\n fromObject: types.ListCachedContentsParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n listCachedContentsConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function listCachedContentsParametersToVertex(\n fromObject: types.ListCachedContentsParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n listCachedContentsConfigToVertex(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function listCachedContentsResponseFromMldev(\n fromObject: types.ListCachedContentsResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromNextPageToken = common.getValueByPath(fromObject, [\n 'nextPageToken',\n ]);\n if (fromNextPageToken != null) {\n common.setValueByPath(toObject, ['nextPageToken'], fromNextPageToken);\n }\n\n const fromCachedContents = common.getValueByPath(fromObject, [\n 'cachedContents',\n ]);\n if (fromCachedContents != null) {\n let transformedList = fromCachedContents;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['cachedContents'], transformedList);\n }\n\n return toObject;\n}\n\nexport function listCachedContentsResponseFromVertex(\n fromObject: types.ListCachedContentsResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromNextPageToken = common.getValueByPath(fromObject, [\n 'nextPageToken',\n ]);\n if (fromNextPageToken != null) {\n common.setValueByPath(toObject, ['nextPageToken'], fromNextPageToken);\n }\n\n const fromCachedContents = common.getValueByPath(fromObject, [\n 'cachedContents',\n ]);\n if (fromCachedContents != null) {\n let transformedList = fromCachedContents;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['cachedContents'], transformedList);\n }\n\n return toObject;\n}\n\nexport function partToMldev(fromObject: types.Part): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (fromMediaResolution != null) {\n common.setValueByPath(toObject, ['mediaResolution'], fromMediaResolution);\n }\n\n const fromCodeExecutionResult = common.getValueByPath(fromObject, [\n 'codeExecutionResult',\n ]);\n if (fromCodeExecutionResult != null) {\n common.setValueByPath(\n toObject,\n ['codeExecutionResult'],\n fromCodeExecutionResult,\n );\n }\n\n const fromExecutableCode = common.getValueByPath(fromObject, [\n 'executableCode',\n ]);\n if (fromExecutableCode != null) {\n common.setValueByPath(toObject, ['executableCode'], fromExecutableCode);\n }\n\n const fromFileData = common.getValueByPath(fromObject, ['fileData']);\n if (fromFileData != null) {\n common.setValueByPath(\n toObject,\n ['fileData'],\n fileDataToMldev(fromFileData),\n );\n }\n\n const fromFunctionCall = common.getValueByPath(fromObject, ['functionCall']);\n if (fromFunctionCall != null) {\n common.setValueByPath(\n toObject,\n ['functionCall'],\n functionCallToMldev(fromFunctionCall),\n );\n }\n\n const fromFunctionResponse = common.getValueByPath(fromObject, [\n 'functionResponse',\n ]);\n if (fromFunctionResponse != null) {\n common.setValueByPath(toObject, ['functionResponse'], fromFunctionResponse);\n }\n\n const fromInlineData = common.getValueByPath(fromObject, ['inlineData']);\n if (fromInlineData != null) {\n common.setValueByPath(\n toObject,\n ['inlineData'],\n blobToMldev(fromInlineData),\n );\n }\n\n const fromText = common.getValueByPath(fromObject, ['text']);\n if (fromText != null) {\n common.setValueByPath(toObject, ['text'], fromText);\n }\n\n const fromThought = common.getValueByPath(fromObject, ['thought']);\n if (fromThought != null) {\n common.setValueByPath(toObject, ['thought'], fromThought);\n }\n\n const fromThoughtSignature = common.getValueByPath(fromObject, [\n 'thoughtSignature',\n ]);\n if (fromThoughtSignature != null) {\n common.setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature);\n }\n\n const fromVideoMetadata = common.getValueByPath(fromObject, [\n 'videoMetadata',\n ]);\n if (fromVideoMetadata != null) {\n common.setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata);\n }\n\n return toObject;\n}\n\nexport function toolConfigToMldev(\n fromObject: types.ToolConfig,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromRetrievalConfig = common.getValueByPath(fromObject, [\n 'retrievalConfig',\n ]);\n if (fromRetrievalConfig != null) {\n common.setValueByPath(toObject, ['retrievalConfig'], fromRetrievalConfig);\n }\n\n const fromFunctionCallingConfig = common.getValueByPath(fromObject, [\n 'functionCallingConfig',\n ]);\n if (fromFunctionCallingConfig != null) {\n common.setValueByPath(\n toObject,\n ['functionCallingConfig'],\n functionCallingConfigToMldev(fromFunctionCallingConfig),\n );\n }\n\n return toObject;\n}\n\nexport function toolToMldev(fromObject: types.Tool): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['retrieval']) !== undefined) {\n throw new Error('retrieval parameter is not supported in Gemini API.');\n }\n\n const fromComputerUse = common.getValueByPath(fromObject, ['computerUse']);\n if (fromComputerUse != null) {\n common.setValueByPath(toObject, ['computerUse'], fromComputerUse);\n }\n\n const fromFileSearch = common.getValueByPath(fromObject, ['fileSearch']);\n if (fromFileSearch != null) {\n common.setValueByPath(toObject, ['fileSearch'], fromFileSearch);\n }\n\n const fromCodeExecution = common.getValueByPath(fromObject, [\n 'codeExecution',\n ]);\n if (fromCodeExecution != null) {\n common.setValueByPath(toObject, ['codeExecution'], fromCodeExecution);\n }\n\n if (\n common.getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined\n ) {\n throw new Error(\n 'enterpriseWebSearch parameter is not supported in Gemini API.',\n );\n }\n\n const fromFunctionDeclarations = common.getValueByPath(fromObject, [\n 'functionDeclarations',\n ]);\n if (fromFunctionDeclarations != null) {\n let transformedList = fromFunctionDeclarations;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['functionDeclarations'], transformedList);\n }\n\n const fromGoogleMaps = common.getValueByPath(fromObject, ['googleMaps']);\n if (fromGoogleMaps != null) {\n common.setValueByPath(\n toObject,\n ['googleMaps'],\n googleMapsToMldev(fromGoogleMaps),\n );\n }\n\n const fromGoogleSearch = common.getValueByPath(fromObject, ['googleSearch']);\n if (fromGoogleSearch != null) {\n common.setValueByPath(\n toObject,\n ['googleSearch'],\n googleSearchToMldev(fromGoogleSearch),\n );\n }\n\n const fromGoogleSearchRetrieval = common.getValueByPath(fromObject, [\n 'googleSearchRetrieval',\n ]);\n if (fromGoogleSearchRetrieval != null) {\n common.setValueByPath(\n toObject,\n ['googleSearchRetrieval'],\n fromGoogleSearchRetrieval,\n );\n }\n\n const fromUrlContext = common.getValueByPath(fromObject, ['urlContext']);\n if (fromUrlContext != null) {\n common.setValueByPath(toObject, ['urlContext'], fromUrlContext);\n }\n\n return toObject;\n}\n\nexport function toolToVertex(fromObject: types.Tool): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromRetrieval = common.getValueByPath(fromObject, ['retrieval']);\n if (fromRetrieval != null) {\n common.setValueByPath(toObject, ['retrieval'], fromRetrieval);\n }\n\n const fromComputerUse = common.getValueByPath(fromObject, ['computerUse']);\n if (fromComputerUse != null) {\n common.setValueByPath(toObject, ['computerUse'], fromComputerUse);\n }\n\n if (common.getValueByPath(fromObject, ['fileSearch']) !== undefined) {\n throw new Error('fileSearch parameter is not supported in Vertex AI.');\n }\n\n const fromCodeExecution = common.getValueByPath(fromObject, [\n 'codeExecution',\n ]);\n if (fromCodeExecution != null) {\n common.setValueByPath(toObject, ['codeExecution'], fromCodeExecution);\n }\n\n const fromEnterpriseWebSearch = common.getValueByPath(fromObject, [\n 'enterpriseWebSearch',\n ]);\n if (fromEnterpriseWebSearch != null) {\n common.setValueByPath(\n toObject,\n ['enterpriseWebSearch'],\n fromEnterpriseWebSearch,\n );\n }\n\n const fromFunctionDeclarations = common.getValueByPath(fromObject, [\n 'functionDeclarations',\n ]);\n if (fromFunctionDeclarations != null) {\n let transformedList = fromFunctionDeclarations;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return functionDeclarationToVertex(item);\n });\n }\n common.setValueByPath(toObject, ['functionDeclarations'], transformedList);\n }\n\n const fromGoogleMaps = common.getValueByPath(fromObject, ['googleMaps']);\n if (fromGoogleMaps != null) {\n common.setValueByPath(toObject, ['googleMaps'], fromGoogleMaps);\n }\n\n const fromGoogleSearch = common.getValueByPath(fromObject, ['googleSearch']);\n if (fromGoogleSearch != null) {\n common.setValueByPath(toObject, ['googleSearch'], fromGoogleSearch);\n }\n\n const fromGoogleSearchRetrieval = common.getValueByPath(fromObject, [\n 'googleSearchRetrieval',\n ]);\n if (fromGoogleSearchRetrieval != null) {\n common.setValueByPath(\n toObject,\n ['googleSearchRetrieval'],\n fromGoogleSearchRetrieval,\n );\n }\n\n const fromUrlContext = common.getValueByPath(fromObject, ['urlContext']);\n if (fromUrlContext != null) {\n common.setValueByPath(toObject, ['urlContext'], fromUrlContext);\n }\n\n return toObject;\n}\n\nexport function updateCachedContentConfigToMldev(\n fromObject: types.UpdateCachedContentConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromTtl = common.getValueByPath(fromObject, ['ttl']);\n if (parentObject !== undefined && fromTtl != null) {\n common.setValueByPath(parentObject, ['ttl'], fromTtl);\n }\n\n const fromExpireTime = common.getValueByPath(fromObject, ['expireTime']);\n if (parentObject !== undefined && fromExpireTime != null) {\n common.setValueByPath(parentObject, ['expireTime'], fromExpireTime);\n }\n\n return toObject;\n}\n\nexport function updateCachedContentConfigToVertex(\n fromObject: types.UpdateCachedContentConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromTtl = common.getValueByPath(fromObject, ['ttl']);\n if (parentObject !== undefined && fromTtl != null) {\n common.setValueByPath(parentObject, ['ttl'], fromTtl);\n }\n\n const fromExpireTime = common.getValueByPath(fromObject, ['expireTime']);\n if (parentObject !== undefined && fromExpireTime != null) {\n common.setValueByPath(parentObject, ['expireTime'], fromExpireTime);\n }\n\n return toObject;\n}\n\nexport function updateCachedContentParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.UpdateCachedContentParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tCachedContentName(apiClient, fromName),\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n updateCachedContentConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function updateCachedContentParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.UpdateCachedContentParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tCachedContentName(apiClient, fromName),\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n updateCachedContentConfigToVertex(fromConfig, toObject);\n }\n\n return toObject;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport {ApiClient} from './_api_client.js';\nimport * as common from './_common.js';\nimport {BaseModule} from './_common.js';\nimport * as converters from './converters/_caches_converters.js';\nimport {PagedItem, Pager} from './pagers.js';\nimport * as types from './types.js';\n\nexport class Caches extends BaseModule {\n constructor(private readonly apiClient: ApiClient) {\n super();\n }\n\n /**\n * Lists cached contents.\n *\n * @param params - The parameters for the list request.\n * @return - A pager of cached contents.\n *\n * @example\n * ```ts\n * const cachedContents = await ai.caches.list({config: {'pageSize': 2}});\n * for await (const cachedContent of cachedContents) {\n * console.log(cachedContent);\n * }\n * ```\n */\n list = async (\n params: types.ListCachedContentsParameters = {},\n ): Promise<Pager<types.CachedContent>> => {\n return new Pager<types.CachedContent>(\n PagedItem.PAGED_ITEM_CACHED_CONTENTS,\n (x: types.ListCachedContentsParameters) => this.listInternal(x),\n await this.listInternal(params),\n params,\n );\n };\n\n /**\n * Creates a cached contents resource.\n *\n * @remarks\n * Context caching is only supported for specific models. See [Gemini\n * Developer API reference](https://ai.google.dev/gemini-api/docs/caching?lang=node/context-cac)\n * and [Vertex AI reference](https://cloud.google.com/vertex-ai/generative-ai/docs/context-cache/context-cache-overview#supported_models)\n * for more information.\n *\n * @param params - The parameters for the create request.\n * @return The created cached content.\n *\n * @example\n * ```ts\n * const contents = ...; // Initialize the content to cache.\n * const response = await ai.caches.create({\n * model: 'gemini-2.0-flash-001',\n * config: {\n * 'contents': contents,\n * 'displayName': 'test cache',\n * 'systemInstruction': 'What is the sum of the two pdfs?',\n * 'ttl': '86400s',\n * }\n * });\n * ```\n */\n async create(\n params: types.CreateCachedContentParameters,\n ): Promise<types.CachedContent> {\n let response: Promise<types.CachedContent>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.createCachedContentParametersToVertex(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n 'cachedContents',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.CachedContent>;\n\n return response.then((resp) => {\n return resp as types.CachedContent;\n });\n } else {\n const body = converters.createCachedContentParametersToMldev(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n 'cachedContents',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.CachedContent>;\n\n return response.then((resp) => {\n return resp as types.CachedContent;\n });\n }\n }\n\n /**\n * Gets cached content configurations.\n *\n * @param params - The parameters for the get request.\n * @return The cached content.\n *\n * @example\n * ```ts\n * await ai.caches.get({name: '...'}); // The server-generated resource name.\n * ```\n */\n async get(\n params: types.GetCachedContentParameters,\n ): Promise<types.CachedContent> {\n let response: Promise<types.CachedContent>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.getCachedContentParametersToVertex(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.CachedContent>;\n\n return response.then((resp) => {\n return resp as types.CachedContent;\n });\n } else {\n const body = converters.getCachedContentParametersToMldev(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.CachedContent>;\n\n return response.then((resp) => {\n return resp as types.CachedContent;\n });\n }\n }\n\n /**\n * Deletes cached content.\n *\n * @param params - The parameters for the delete request.\n * @return The empty response returned by the API.\n *\n * @example\n * ```ts\n * await ai.caches.delete({name: '...'}); // The server-generated resource name.\n * ```\n */\n async delete(\n params: types.DeleteCachedContentParameters,\n ): Promise<types.DeleteCachedContentResponse> {\n let response: Promise<types.DeleteCachedContentResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.deleteCachedContentParametersToVertex(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'DELETE',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.DeleteCachedContentResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.DeleteCachedContentResponse>;\n\n return response.then((apiResponse) => {\n const resp =\n converters.deleteCachedContentResponseFromVertex(apiResponse);\n const typedResp = new types.DeleteCachedContentResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n const body = converters.deleteCachedContentParametersToMldev(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'DELETE',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.DeleteCachedContentResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.DeleteCachedContentResponse>;\n\n return response.then((apiResponse) => {\n const resp =\n converters.deleteCachedContentResponseFromMldev(apiResponse);\n const typedResp = new types.DeleteCachedContentResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n /**\n * Updates cached content configurations.\n *\n * @param params - The parameters for the update request.\n * @return The updated cached content.\n *\n * @example\n * ```ts\n * const response = await ai.caches.update({\n * name: '...', // The server-generated resource name.\n * config: {'ttl': '7600s'}\n * });\n * ```\n */\n async update(\n params: types.UpdateCachedContentParameters,\n ): Promise<types.CachedContent> {\n let response: Promise<types.CachedContent>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.updateCachedContentParametersToVertex(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'PATCH',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.CachedContent>;\n\n return response.then((resp) => {\n return resp as types.CachedContent;\n });\n } else {\n const body = converters.updateCachedContentParametersToMldev(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'PATCH',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.CachedContent>;\n\n return response.then((resp) => {\n return resp as types.CachedContent;\n });\n }\n }\n\n private async listInternal(\n params: types.ListCachedContentsParameters,\n ): Promise<types.ListCachedContentsResponse> {\n let response: Promise<types.ListCachedContentsResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.listCachedContentsParametersToVertex(params);\n path = common.formatMap(\n 'cachedContents',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.ListCachedContentsResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.ListCachedContentsResponse>;\n\n return response.then((apiResponse) => {\n const resp =\n converters.listCachedContentsResponseFromVertex(apiResponse);\n const typedResp = new types.ListCachedContentsResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n const body = converters.listCachedContentsParametersToMldev(params);\n path = common.formatMap(\n 'cachedContents',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.ListCachedContentsResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.ListCachedContentsResponse>;\n\n return response.then((apiResponse) => {\n const resp =\n converters.listCachedContentsResponseFromMldev(apiResponse);\n const typedResp = new types.ListCachedContentsResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {ApiClient} from './_api_client.js';\nimport * as t from './_transformers.js';\nimport {Models} from './models.js';\nimport * as types from './types.js';\n\n/**\n * Returns true if the response is valid, false otherwise.\n */\nfunction isValidResponse(response: types.GenerateContentResponse): boolean {\n if (response.candidates == undefined || response.candidates.length === 0) {\n return false;\n }\n const content = response.candidates[0]?.content;\n if (content === undefined) {\n return false;\n }\n return isValidContent(content);\n}\n\nfunction isValidContent(content: types.Content): boolean {\n if (content.parts === undefined || content.parts.length === 0) {\n return false;\n }\n for (const part of content.parts) {\n if (part === undefined || Object.keys(part).length === 0) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * Validates the history contains the correct roles.\n *\n * @throws Error if the history does not start with a user turn.\n * @throws Error if the history contains an invalid role.\n */\nfunction validateHistory(history: types.Content[]) {\n // Empty history is valid.\n if (history.length === 0) {\n return;\n }\n for (const content of history) {\n if (content.role !== 'user' && content.role !== 'model') {\n throw new Error(`Role must be user or model, but got ${content.role}.`);\n }\n }\n}\n\n/**\n * Extracts the curated (valid) history from a comprehensive history.\n *\n * @remarks\n * The model may sometimes generate invalid or empty contents(e.g., due to safty\n * filters or recitation). Extracting valid turns from the history\n * ensures that subsequent requests could be accpeted by the model.\n */\nfunction extractCuratedHistory(\n comprehensiveHistory: types.Content[],\n): types.Content[] {\n if (comprehensiveHistory === undefined || comprehensiveHistory.length === 0) {\n return [];\n }\n const curatedHistory: types.Content[] = [];\n const length = comprehensiveHistory.length;\n let i = 0;\n while (i < length) {\n if (comprehensiveHistory[i].role === 'user') {\n curatedHistory.push(comprehensiveHistory[i]);\n i++;\n } else {\n const modelOutput: types.Content[] = [];\n let isValid = true;\n while (i < length && comprehensiveHistory[i].role === 'model') {\n modelOutput.push(comprehensiveHistory[i]);\n if (isValid && !isValidContent(comprehensiveHistory[i])) {\n isValid = false;\n }\n i++;\n }\n if (isValid) {\n curatedHistory.push(...modelOutput);\n } else {\n // Remove the last user input when model content is invalid.\n curatedHistory.pop();\n }\n }\n }\n return curatedHistory;\n}\n\n/**\n * A utility class to create a chat session.\n */\nexport class Chats {\n private readonly modelsModule: Models;\n private readonly apiClient: ApiClient;\n\n constructor(modelsModule: Models, apiClient: ApiClient) {\n this.modelsModule = modelsModule;\n this.apiClient = apiClient;\n }\n\n /**\n * Creates a new chat session.\n *\n * @remarks\n * The config in the params will be used for all requests within the chat\n * session unless overridden by a per-request `config` in\n * @see {@link types.SendMessageParameters#config}.\n *\n * @param params - Parameters for creating a chat session.\n * @returns A new chat session.\n *\n * @example\n * ```ts\n * const chat = ai.chats.create({\n * model: 'gemini-2.0-flash'\n * config: {\n * temperature: 0.5,\n * maxOutputTokens: 1024,\n * }\n * });\n * ```\n */\n create(params: types.CreateChatParameters) {\n return new Chat(\n this.apiClient,\n this.modelsModule,\n params.model,\n params.config,\n // Deep copy the history to avoid mutating the history outside of the\n // chat session.\n structuredClone(params.history),\n );\n }\n}\n\n/**\n * Chat session that enables sending messages to the model with previous\n * conversation context.\n *\n * @remarks\n * The session maintains all the turns between user and model.\n */\nexport class Chat {\n // A promise to represent the current state of the message being sent to the\n // model.\n private sendPromise: Promise<void> = Promise.resolve();\n\n constructor(\n private readonly apiClient: ApiClient,\n private readonly modelsModule: Models,\n private readonly model: string,\n private readonly config: types.GenerateContentConfig = {},\n private history: types.Content[] = [],\n ) {\n validateHistory(history);\n }\n\n /**\n * Sends a message to the model and returns the response.\n *\n * @remarks\n * This method will wait for the previous message to be processed before\n * sending the next message.\n *\n * @see {@link Chat#sendMessageStream} for streaming method.\n * @param params - parameters for sending messages within a chat session.\n * @returns The model's response.\n *\n * @example\n * ```ts\n * const chat = ai.chats.create({model: 'gemini-2.0-flash'});\n * const response = await chat.sendMessage({\n * message: 'Why is the sky blue?'\n * });\n * console.log(response.text);\n * ```\n */\n async sendMessage(\n params: types.SendMessageParameters,\n ): Promise<types.GenerateContentResponse> {\n await this.sendPromise;\n const inputContent = t.tContent(params.message);\n const responsePromise = this.modelsModule.generateContent({\n model: this.model,\n contents: this.getHistory(true).concat(inputContent),\n config: params.config ?? this.config,\n });\n this.sendPromise = (async () => {\n const response = await responsePromise;\n const outputContent = response.candidates?.[0]?.content;\n\n // Because the AFC input contains the entire curated chat history in\n // addition to the new user input, we need to truncate the AFC history\n // to deduplicate the existing chat history.\n const fullAutomaticFunctionCallingHistory =\n response.automaticFunctionCallingHistory;\n const index = this.getHistory(true).length;\n\n let automaticFunctionCallingHistory: types.Content[] = [];\n if (fullAutomaticFunctionCallingHistory != null) {\n automaticFunctionCallingHistory =\n fullAutomaticFunctionCallingHistory.slice(index) ?? [];\n }\n\n const modelOutput = outputContent ? [outputContent] : [];\n this.recordHistory(\n inputContent,\n modelOutput,\n automaticFunctionCallingHistory,\n );\n return;\n })();\n await this.sendPromise.catch(() => {\n // Resets sendPromise to avoid subsequent calls failing\n this.sendPromise = Promise.resolve();\n });\n return responsePromise;\n }\n\n /**\n * Sends a message to the model and returns the response in chunks.\n *\n * @remarks\n * This method will wait for the previous message to be processed before\n * sending the next message.\n *\n * @see {@link Chat#sendMessage} for non-streaming method.\n * @param params - parameters for sending the message.\n * @return The model's response.\n *\n * @example\n * ```ts\n * const chat = ai.chats.create({model: 'gemini-2.0-flash'});\n * const response = await chat.sendMessageStream({\n * message: 'Why is the sky blue?'\n * });\n * for await (const chunk of response) {\n * console.log(chunk.text);\n * }\n * ```\n */\n async sendMessageStream(\n params: types.SendMessageParameters,\n ): Promise<AsyncGenerator<types.GenerateContentResponse>> {\n await this.sendPromise;\n const inputContent = t.tContent(params.message);\n const streamResponse = this.modelsModule.generateContentStream({\n model: this.model,\n contents: this.getHistory(true).concat(inputContent),\n config: params.config ?? this.config,\n });\n // Resolve the internal tracking of send completion promise - `sendPromise`\n // for both success and failure response. The actual failure is still\n // propagated by the `await streamResponse`.\n this.sendPromise = streamResponse\n .then(() => undefined)\n .catch(() => undefined);\n const response = await streamResponse;\n const result = this.processStreamResponse(response, inputContent);\n return result;\n }\n\n /**\n * Returns the chat history.\n *\n * @remarks\n * The history is a list of contents alternating between user and model.\n *\n * There are two types of history:\n * - The `curated history` contains only the valid turns between user and\n * model, which will be included in the subsequent requests sent to the model.\n * - The `comprehensive history` contains all turns, including invalid or\n * empty model outputs, providing a complete record of the history.\n *\n * The history is updated after receiving the response from the model,\n * for streaming response, it means receiving the last chunk of the response.\n *\n * The `comprehensive history` is returned by default. To get the `curated\n * history`, set the `curated` parameter to `true`.\n *\n * @param curated - whether to return the curated history or the comprehensive\n * history.\n * @return History contents alternating between user and model for the entire\n * chat session.\n */\n getHistory(curated: boolean = false): types.Content[] {\n const history = curated\n ? extractCuratedHistory(this.history)\n : this.history;\n // Deep copy the history to avoid mutating the history outside of the\n // chat session.\n return structuredClone(history);\n }\n\n private async *processStreamResponse(\n streamResponse: AsyncGenerator<types.GenerateContentResponse>,\n inputContent: types.Content,\n ) {\n const outputContent: types.Content[] = [];\n for await (const chunk of streamResponse) {\n if (isValidResponse(chunk)) {\n const content = chunk.candidates?.[0]?.content;\n if (content !== undefined) {\n outputContent.push(content);\n }\n }\n yield chunk;\n }\n this.recordHistory(inputContent, outputContent);\n }\n\n private recordHistory(\n userInput: types.Content,\n modelOutput: types.Content[],\n automaticFunctionCallingHistory?: types.Content[],\n ) {\n let outputContents: types.Content[] = [];\n if (\n modelOutput.length > 0 &&\n modelOutput.every((content) => content.role !== undefined)\n ) {\n outputContents = modelOutput;\n } else {\n // Appends an empty content when model returns empty response, so that the\n // history is always alternating between user and model.\n outputContents.push({\n role: 'model',\n parts: [],\n } as types.Content);\n }\n if (\n automaticFunctionCallingHistory &&\n automaticFunctionCallingHistory.length > 0\n ) {\n this.history.push(\n ...extractCuratedHistory(automaticFunctionCallingHistory!),\n );\n } else {\n this.history.push(userInput);\n }\n this.history.push(...outputContents);\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Details for errors from calling the API.\n */\nexport interface ApiErrorInfo {\n /** The error message. */\n message: string;\n /** The HTTP status code. */\n status: number;\n}\n\n/**\n * API errors raised by the GenAI API.\n */\nexport class ApiError extends Error {\n /** HTTP status code */\n status: number;\n\n constructor(options: ApiErrorInfo) {\n super(options.message);\n this.name = 'ApiError';\n this.status = options.status;\n Object.setPrototypeOf(this, ApiError.prototype);\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport * as common from '../_common.js';\nimport * as t from '../_transformers.js';\nimport type * as types from '../types.js';\n\nexport function createFileParametersToMldev(\n fromObject: types.CreateFileParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromFile = common.getValueByPath(fromObject, ['file']);\n if (fromFile != null) {\n common.setValueByPath(toObject, ['file'], fromFile);\n }\n\n return toObject;\n}\n\nexport function createFileResponseFromMldev(\n fromObject: types.CreateFileResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n return toObject;\n}\n\nexport function deleteFileParametersToMldev(\n fromObject: types.DeleteFileParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['_url', 'file'], t.tFileName(fromName));\n }\n\n return toObject;\n}\n\nexport function deleteFileResponseFromMldev(\n fromObject: types.DeleteFileResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n return toObject;\n}\n\nexport function getFileParametersToMldev(\n fromObject: types.GetFileParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['_url', 'file'], t.tFileName(fromName));\n }\n\n return toObject;\n}\n\nexport function internalRegisterFilesParametersToMldev(\n fromObject: types.InternalRegisterFilesParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromUris = common.getValueByPath(fromObject, ['uris']);\n if (fromUris != null) {\n common.setValueByPath(toObject, ['uris'], fromUris);\n }\n\n return toObject;\n}\n\nexport function listFilesConfigToMldev(\n fromObject: types.ListFilesConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPageSize = common.getValueByPath(fromObject, ['pageSize']);\n if (parentObject !== undefined && fromPageSize != null) {\n common.setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize);\n }\n\n const fromPageToken = common.getValueByPath(fromObject, ['pageToken']);\n if (parentObject !== undefined && fromPageToken != null) {\n common.setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken);\n }\n\n return toObject;\n}\n\nexport function listFilesParametersToMldev(\n fromObject: types.ListFilesParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n listFilesConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function listFilesResponseFromMldev(\n fromObject: types.ListFilesResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromNextPageToken = common.getValueByPath(fromObject, [\n 'nextPageToken',\n ]);\n if (fromNextPageToken != null) {\n common.setValueByPath(toObject, ['nextPageToken'], fromNextPageToken);\n }\n\n const fromFiles = common.getValueByPath(fromObject, ['files']);\n if (fromFiles != null) {\n let transformedList = fromFiles;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['files'], transformedList);\n }\n\n return toObject;\n}\n\nexport function registerFilesResponseFromMldev(\n fromObject: types.RegisterFilesResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromFiles = common.getValueByPath(fromObject, ['files']);\n if (fromFiles != null) {\n let transformedList = fromFiles;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['files'], transformedList);\n }\n\n return toObject;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport {ApiClient} from './_api_client.js';\nimport * as common from './_common.js';\nimport {BaseModule} from './_common.js';\nimport * as converters from './converters/_files_converters.js';\nimport {PagedItem, Pager} from './pagers.js';\nimport * as types from './types.js';\n\nexport class Files extends BaseModule {\n constructor(private readonly apiClient: ApiClient) {\n super();\n }\n\n /**\n * Lists files.\n *\n * @param params - The parameters for the list request.\n * @return - A pager of files.\n *\n * @example\n * ```ts\n * const files = await ai.files.list({config: {'pageSize': 2}});\n * for await (const file of files) {\n * console.log(file);\n * }\n * ```\n */\n list = async (\n params: types.ListFilesParameters = {},\n ): Promise<Pager<types.File>> => {\n return new Pager<types.File>(\n PagedItem.PAGED_ITEM_FILES,\n (x: types.ListFilesParameters) => this.listInternal(x),\n await this.listInternal(params),\n params,\n );\n };\n\n /**\n * Uploads a file asynchronously to the Gemini API.\n * This method is not available in Vertex AI.\n * Supported upload sources:\n * - Node.js: File path (string) or Blob object.\n * - Browser: Blob object (e.g., File).\n *\n * @remarks\n * The `mimeType` can be specified in the `config` parameter. If omitted:\n * - For file path (string) inputs, the `mimeType` will be inferred from the\n * file extension.\n * - For Blob object inputs, the `mimeType` will be set to the Blob's `type`\n * property.\n * Somex eamples for file extension to mimeType mapping:\n * .txt -> text/plain\n * .json -> application/json\n * .jpg -> image/jpeg\n * .png -> image/png\n * .mp3 -> audio/mpeg\n * .mp4 -> video/mp4\n *\n * This section can contain multiple paragraphs and code examples.\n *\n * @param params - Optional parameters specified in the\n * `types.UploadFileParameters` interface.\n * @see {@link types.UploadFileParameters#config} for the optional\n * config in the parameters.\n * @return A promise that resolves to a `types.File` object.\n * @throws An error if called on a Vertex AI client.\n * @throws An error if the `mimeType` is not provided and can not be inferred,\n * the `mimeType` can be provided in the `params.config` parameter.\n * @throws An error occurs if a suitable upload location cannot be established.\n *\n * @example\n * The following code uploads a file to Gemini API.\n *\n * ```ts\n * const file = await ai.files.upload({file: 'file.txt', config: {\n * mimeType: 'text/plain',\n * }});\n * console.log(file.name);\n * ```\n */\n async upload(params: types.UploadFileParameters): Promise<types.File> {\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'Vertex AI does not support uploading files. You can share files through a GCS bucket.',\n );\n }\n\n return this.apiClient\n .uploadFile(params.file, params.config)\n .then((resp) => {\n return resp as types.File;\n });\n }\n\n /**\n * Downloads a remotely stored file asynchronously to a location specified in\n * the `params` object. This method only works on Node environment, to\n * download files in the browser, use a browser compliant method like an <a>\n * tag.\n *\n * @param params - The parameters for the download request.\n *\n * @example\n * The following code downloads an example file named \"files/mehozpxf877d\" as\n * \"file.txt\".\n *\n * ```ts\n * await ai.files.download({file: file.name, downloadPath: 'file.txt'});\n * ```\n */\n\n async download(params: types.DownloadFileParameters): Promise<void> {\n await this.apiClient.downloadFile(params);\n }\n\n /**\n * Registers Google Cloud Storage files for use with the API.\n * This method is only available in Node.js environments.\n */\n async registerFiles(\n params: types.RegisterFilesParameters,\n ): Promise<types.RegisterFilesResponse> {\n void params;\n throw new Error('registerFiles is only supported in Node.js environments.');\n }\n\n protected async _registerFiles(\n params: types.InternalRegisterFilesParameters,\n ): Promise<types.RegisterFilesResponse> {\n return this.registerFilesInternal(params);\n }\n\n private async listInternal(\n params: types.ListFilesParameters,\n ): Promise<types.ListFilesResponse> {\n let response: Promise<types.ListFilesResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.listFilesParametersToMldev(params);\n path = common.formatMap('files', body['_url'] as Record<string, unknown>);\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.ListFilesResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.ListFilesResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.listFilesResponseFromMldev(apiResponse);\n const typedResp = new types.ListFilesResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n private async createInternal(\n params: types.CreateFileParameters,\n ): Promise<types.CreateFileResponse> {\n let response: Promise<types.CreateFileResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.createFileParametersToMldev(params);\n path = common.formatMap(\n 'upload/v1beta/files',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.CreateFileResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.createFileResponseFromMldev(apiResponse);\n const typedResp = new types.CreateFileResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n /**\n * Retrieves the file information from the service.\n *\n * @param params - The parameters for the get request\n * @return The Promise that resolves to the types.File object requested.\n *\n * @example\n * ```ts\n * const config: GetFileParameters = {\n * name: fileName,\n * };\n * file = await ai.files.get(config);\n * console.log(file.name);\n * ```\n */\n async get(params: types.GetFileParameters): Promise<types.File> {\n let response: Promise<types.File>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.getFileParametersToMldev(params);\n path = common.formatMap(\n 'files/{file}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.File>;\n\n return response.then((resp) => {\n return resp as types.File;\n });\n }\n }\n\n /**\n * Deletes a remotely stored file.\n *\n * @param params - The parameters for the delete request.\n * @return The DeleteFileResponse, the response for the delete method.\n *\n * @example\n * The following code deletes an example file named \"files/mehozpxf877d\".\n *\n * ```ts\n * await ai.files.delete({name: file.name});\n * ```\n */\n async delete(\n params: types.DeleteFileParameters,\n ): Promise<types.DeleteFileResponse> {\n let response: Promise<types.DeleteFileResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.deleteFileParametersToMldev(params);\n path = common.formatMap(\n 'files/{file}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'DELETE',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.DeleteFileResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.DeleteFileResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.deleteFileResponseFromMldev(apiResponse);\n const typedResp = new types.DeleteFileResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n private async registerFilesInternal(\n params: types.InternalRegisterFilesParameters,\n ): Promise<types.RegisterFilesResponse> {\n let response: Promise<types.RegisterFilesResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.internalRegisterFilesParametersToMldev(params);\n path = common.formatMap(\n 'files:register',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.RegisterFilesResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.registerFilesResponseFromMldev(apiResponse);\n const typedResp = new types.RegisterFilesResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport {ApiClient} from '../_api_client.js';\nimport * as common from '../_common.js';\nimport * as t from '../_transformers.js';\nimport type * as types from '../types.js';\n\nexport function blobToMldev(fromObject: types.Blob): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromData = common.getValueByPath(fromObject, ['data']);\n if (fromData != null) {\n common.setValueByPath(toObject, ['data'], fromData);\n }\n\n if (common.getValueByPath(fromObject, ['displayName']) !== undefined) {\n throw new Error('displayName parameter is not supported in Gemini API.');\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function contentToMldev(\n fromObject: types.Content,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromParts = common.getValueByPath(fromObject, ['parts']);\n if (fromParts != null) {\n let transformedList = fromParts;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return partToMldev(item);\n });\n }\n common.setValueByPath(toObject, ['parts'], transformedList);\n }\n\n const fromRole = common.getValueByPath(fromObject, ['role']);\n if (fromRole != null) {\n common.setValueByPath(toObject, ['role'], fromRole);\n }\n\n return toObject;\n}\n\nexport function fileDataToMldev(\n fromObject: types.FileData,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['displayName']) !== undefined) {\n throw new Error('displayName parameter is not supported in Gemini API.');\n }\n\n const fromFileUri = common.getValueByPath(fromObject, ['fileUri']);\n if (fromFileUri != null) {\n common.setValueByPath(toObject, ['fileUri'], fromFileUri);\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function functionCallToMldev(\n fromObject: types.FunctionCall,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromId = common.getValueByPath(fromObject, ['id']);\n if (fromId != null) {\n common.setValueByPath(toObject, ['id'], fromId);\n }\n\n const fromArgs = common.getValueByPath(fromObject, ['args']);\n if (fromArgs != null) {\n common.setValueByPath(toObject, ['args'], fromArgs);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n if (common.getValueByPath(fromObject, ['partialArgs']) !== undefined) {\n throw new Error('partialArgs parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['willContinue']) !== undefined) {\n throw new Error('willContinue parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function functionDeclarationToVertex(\n fromObject: types.FunctionDeclaration,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromDescription = common.getValueByPath(fromObject, ['description']);\n if (fromDescription != null) {\n common.setValueByPath(toObject, ['description'], fromDescription);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromParameters = common.getValueByPath(fromObject, ['parameters']);\n if (fromParameters != null) {\n common.setValueByPath(toObject, ['parameters'], fromParameters);\n }\n\n const fromParametersJsonSchema = common.getValueByPath(fromObject, [\n 'parametersJsonSchema',\n ]);\n if (fromParametersJsonSchema != null) {\n common.setValueByPath(\n toObject,\n ['parametersJsonSchema'],\n fromParametersJsonSchema,\n );\n }\n\n const fromResponse = common.getValueByPath(fromObject, ['response']);\n if (fromResponse != null) {\n common.setValueByPath(toObject, ['response'], fromResponse);\n }\n\n const fromResponseJsonSchema = common.getValueByPath(fromObject, [\n 'responseJsonSchema',\n ]);\n if (fromResponseJsonSchema != null) {\n common.setValueByPath(\n toObject,\n ['responseJsonSchema'],\n fromResponseJsonSchema,\n );\n }\n\n if (common.getValueByPath(fromObject, ['behavior']) !== undefined) {\n throw new Error('behavior parameter is not supported in Vertex AI.');\n }\n\n return toObject;\n}\n\nexport function generationConfigToVertex(\n fromObject: types.GenerationConfig,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModelSelectionConfig = common.getValueByPath(fromObject, [\n 'modelSelectionConfig',\n ]);\n if (fromModelSelectionConfig != null) {\n common.setValueByPath(toObject, ['modelConfig'], fromModelSelectionConfig);\n }\n\n const fromResponseJsonSchema = common.getValueByPath(fromObject, [\n 'responseJsonSchema',\n ]);\n if (fromResponseJsonSchema != null) {\n common.setValueByPath(\n toObject,\n ['responseJsonSchema'],\n fromResponseJsonSchema,\n );\n }\n\n const fromAudioTimestamp = common.getValueByPath(fromObject, [\n 'audioTimestamp',\n ]);\n if (fromAudioTimestamp != null) {\n common.setValueByPath(toObject, ['audioTimestamp'], fromAudioTimestamp);\n }\n\n const fromCandidateCount = common.getValueByPath(fromObject, [\n 'candidateCount',\n ]);\n if (fromCandidateCount != null) {\n common.setValueByPath(toObject, ['candidateCount'], fromCandidateCount);\n }\n\n const fromEnableAffectiveDialog = common.getValueByPath(fromObject, [\n 'enableAffectiveDialog',\n ]);\n if (fromEnableAffectiveDialog != null) {\n common.setValueByPath(\n toObject,\n ['enableAffectiveDialog'],\n fromEnableAffectiveDialog,\n );\n }\n\n const fromFrequencyPenalty = common.getValueByPath(fromObject, [\n 'frequencyPenalty',\n ]);\n if (fromFrequencyPenalty != null) {\n common.setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty);\n }\n\n const fromLogprobs = common.getValueByPath(fromObject, ['logprobs']);\n if (fromLogprobs != null) {\n common.setValueByPath(toObject, ['logprobs'], fromLogprobs);\n }\n\n const fromMaxOutputTokens = common.getValueByPath(fromObject, [\n 'maxOutputTokens',\n ]);\n if (fromMaxOutputTokens != null) {\n common.setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens);\n }\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (fromMediaResolution != null) {\n common.setValueByPath(toObject, ['mediaResolution'], fromMediaResolution);\n }\n\n const fromPresencePenalty = common.getValueByPath(fromObject, [\n 'presencePenalty',\n ]);\n if (fromPresencePenalty != null) {\n common.setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty);\n }\n\n const fromResponseLogprobs = common.getValueByPath(fromObject, [\n 'responseLogprobs',\n ]);\n if (fromResponseLogprobs != null) {\n common.setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs);\n }\n\n const fromResponseMimeType = common.getValueByPath(fromObject, [\n 'responseMimeType',\n ]);\n if (fromResponseMimeType != null) {\n common.setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType);\n }\n\n const fromResponseModalities = common.getValueByPath(fromObject, [\n 'responseModalities',\n ]);\n if (fromResponseModalities != null) {\n common.setValueByPath(\n toObject,\n ['responseModalities'],\n fromResponseModalities,\n );\n }\n\n const fromResponseSchema = common.getValueByPath(fromObject, [\n 'responseSchema',\n ]);\n if (fromResponseSchema != null) {\n common.setValueByPath(toObject, ['responseSchema'], fromResponseSchema);\n }\n\n const fromRoutingConfig = common.getValueByPath(fromObject, [\n 'routingConfig',\n ]);\n if (fromRoutingConfig != null) {\n common.setValueByPath(toObject, ['routingConfig'], fromRoutingConfig);\n }\n\n const fromSeed = common.getValueByPath(fromObject, ['seed']);\n if (fromSeed != null) {\n common.setValueByPath(toObject, ['seed'], fromSeed);\n }\n\n const fromSpeechConfig = common.getValueByPath(fromObject, ['speechConfig']);\n if (fromSpeechConfig != null) {\n common.setValueByPath(toObject, ['speechConfig'], fromSpeechConfig);\n }\n\n const fromStopSequences = common.getValueByPath(fromObject, [\n 'stopSequences',\n ]);\n if (fromStopSequences != null) {\n common.setValueByPath(toObject, ['stopSequences'], fromStopSequences);\n }\n\n const fromTemperature = common.getValueByPath(fromObject, ['temperature']);\n if (fromTemperature != null) {\n common.setValueByPath(toObject, ['temperature'], fromTemperature);\n }\n\n const fromThinkingConfig = common.getValueByPath(fromObject, [\n 'thinkingConfig',\n ]);\n if (fromThinkingConfig != null) {\n common.setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig);\n }\n\n const fromTopK = common.getValueByPath(fromObject, ['topK']);\n if (fromTopK != null) {\n common.setValueByPath(toObject, ['topK'], fromTopK);\n }\n\n const fromTopP = common.getValueByPath(fromObject, ['topP']);\n if (fromTopP != null) {\n common.setValueByPath(toObject, ['topP'], fromTopP);\n }\n\n if (\n common.getValueByPath(fromObject, ['enableEnhancedCivicAnswers']) !==\n undefined\n ) {\n throw new Error(\n 'enableEnhancedCivicAnswers parameter is not supported in Vertex AI.',\n );\n }\n\n return toObject;\n}\n\nexport function googleMapsToMldev(\n fromObject: types.GoogleMaps,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['authConfig']) !== undefined) {\n throw new Error('authConfig parameter is not supported in Gemini API.');\n }\n\n const fromEnableWidget = common.getValueByPath(fromObject, ['enableWidget']);\n if (fromEnableWidget != null) {\n common.setValueByPath(toObject, ['enableWidget'], fromEnableWidget);\n }\n\n return toObject;\n}\n\nexport function googleSearchToMldev(\n fromObject: types.GoogleSearch,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['excludeDomains']) !== undefined) {\n throw new Error('excludeDomains parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['blockingConfidence']) !== undefined) {\n throw new Error(\n 'blockingConfidence parameter is not supported in Gemini API.',\n );\n }\n\n const fromTimeRangeFilter = common.getValueByPath(fromObject, [\n 'timeRangeFilter',\n ]);\n if (fromTimeRangeFilter != null) {\n common.setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter);\n }\n\n return toObject;\n}\n\nexport function liveClientContentToMldev(\n fromObject: types.LiveClientContent,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromTurns = common.getValueByPath(fromObject, ['turns']);\n if (fromTurns != null) {\n let transformedList = fromTurns;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return contentToMldev(item);\n });\n }\n common.setValueByPath(toObject, ['turns'], transformedList);\n }\n\n const fromTurnComplete = common.getValueByPath(fromObject, ['turnComplete']);\n if (fromTurnComplete != null) {\n common.setValueByPath(toObject, ['turnComplete'], fromTurnComplete);\n }\n\n return toObject;\n}\n\nexport function liveClientMessageToMldev(\n fromObject: types.LiveClientMessage,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSetup = common.getValueByPath(fromObject, ['setup']);\n if (fromSetup != null) {\n common.setValueByPath(\n toObject,\n ['setup'],\n liveClientSetupToMldev(fromSetup),\n );\n }\n\n const fromClientContent = common.getValueByPath(fromObject, [\n 'clientContent',\n ]);\n if (fromClientContent != null) {\n common.setValueByPath(\n toObject,\n ['clientContent'],\n liveClientContentToMldev(fromClientContent),\n );\n }\n\n const fromRealtimeInput = common.getValueByPath(fromObject, [\n 'realtimeInput',\n ]);\n if (fromRealtimeInput != null) {\n common.setValueByPath(\n toObject,\n ['realtimeInput'],\n liveClientRealtimeInputToMldev(fromRealtimeInput),\n );\n }\n\n const fromToolResponse = common.getValueByPath(fromObject, ['toolResponse']);\n if (fromToolResponse != null) {\n common.setValueByPath(toObject, ['toolResponse'], fromToolResponse);\n }\n\n return toObject;\n}\n\nexport function liveClientMessageToVertex(\n fromObject: types.LiveClientMessage,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSetup = common.getValueByPath(fromObject, ['setup']);\n if (fromSetup != null) {\n common.setValueByPath(\n toObject,\n ['setup'],\n liveClientSetupToVertex(fromSetup),\n );\n }\n\n const fromClientContent = common.getValueByPath(fromObject, [\n 'clientContent',\n ]);\n if (fromClientContent != null) {\n common.setValueByPath(toObject, ['clientContent'], fromClientContent);\n }\n\n const fromRealtimeInput = common.getValueByPath(fromObject, [\n 'realtimeInput',\n ]);\n if (fromRealtimeInput != null) {\n common.setValueByPath(\n toObject,\n ['realtimeInput'],\n liveClientRealtimeInputToVertex(fromRealtimeInput),\n );\n }\n\n const fromToolResponse = common.getValueByPath(fromObject, ['toolResponse']);\n if (fromToolResponse != null) {\n common.setValueByPath(toObject, ['toolResponse'], fromToolResponse);\n }\n\n return toObject;\n}\n\nexport function liveClientRealtimeInputToMldev(\n fromObject: types.LiveClientRealtimeInput,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMediaChunks = common.getValueByPath(fromObject, ['mediaChunks']);\n if (fromMediaChunks != null) {\n let transformedList = fromMediaChunks;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return blobToMldev(item);\n });\n }\n common.setValueByPath(toObject, ['mediaChunks'], transformedList);\n }\n\n const fromAudio = common.getValueByPath(fromObject, ['audio']);\n if (fromAudio != null) {\n common.setValueByPath(toObject, ['audio'], blobToMldev(fromAudio));\n }\n\n const fromAudioStreamEnd = common.getValueByPath(fromObject, [\n 'audioStreamEnd',\n ]);\n if (fromAudioStreamEnd != null) {\n common.setValueByPath(toObject, ['audioStreamEnd'], fromAudioStreamEnd);\n }\n\n const fromVideo = common.getValueByPath(fromObject, ['video']);\n if (fromVideo != null) {\n common.setValueByPath(toObject, ['video'], blobToMldev(fromVideo));\n }\n\n const fromText = common.getValueByPath(fromObject, ['text']);\n if (fromText != null) {\n common.setValueByPath(toObject, ['text'], fromText);\n }\n\n const fromActivityStart = common.getValueByPath(fromObject, [\n 'activityStart',\n ]);\n if (fromActivityStart != null) {\n common.setValueByPath(toObject, ['activityStart'], fromActivityStart);\n }\n\n const fromActivityEnd = common.getValueByPath(fromObject, ['activityEnd']);\n if (fromActivityEnd != null) {\n common.setValueByPath(toObject, ['activityEnd'], fromActivityEnd);\n }\n\n return toObject;\n}\n\nexport function liveClientRealtimeInputToVertex(\n fromObject: types.LiveClientRealtimeInput,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMediaChunks = common.getValueByPath(fromObject, ['mediaChunks']);\n if (fromMediaChunks != null) {\n let transformedList = fromMediaChunks;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['mediaChunks'], transformedList);\n }\n\n const fromAudio = common.getValueByPath(fromObject, ['audio']);\n if (fromAudio != null) {\n common.setValueByPath(toObject, ['audio'], fromAudio);\n }\n\n if (common.getValueByPath(fromObject, ['audioStreamEnd']) !== undefined) {\n throw new Error('audioStreamEnd parameter is not supported in Vertex AI.');\n }\n\n const fromVideo = common.getValueByPath(fromObject, ['video']);\n if (fromVideo != null) {\n common.setValueByPath(toObject, ['video'], fromVideo);\n }\n\n const fromText = common.getValueByPath(fromObject, ['text']);\n if (fromText != null) {\n common.setValueByPath(toObject, ['text'], fromText);\n }\n\n const fromActivityStart = common.getValueByPath(fromObject, [\n 'activityStart',\n ]);\n if (fromActivityStart != null) {\n common.setValueByPath(toObject, ['activityStart'], fromActivityStart);\n }\n\n const fromActivityEnd = common.getValueByPath(fromObject, ['activityEnd']);\n if (fromActivityEnd != null) {\n common.setValueByPath(toObject, ['activityEnd'], fromActivityEnd);\n }\n\n return toObject;\n}\n\nexport function liveClientSetupToMldev(\n fromObject: types.LiveClientSetup,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(toObject, ['model'], fromModel);\n }\n\n const fromGenerationConfig = common.getValueByPath(fromObject, [\n 'generationConfig',\n ]);\n if (fromGenerationConfig != null) {\n common.setValueByPath(toObject, ['generationConfig'], fromGenerationConfig);\n }\n\n const fromSystemInstruction = common.getValueByPath(fromObject, [\n 'systemInstruction',\n ]);\n if (fromSystemInstruction != null) {\n common.setValueByPath(\n toObject,\n ['systemInstruction'],\n contentToMldev(t.tContent(fromSystemInstruction)),\n );\n }\n\n const fromTools = common.getValueByPath(fromObject, ['tools']);\n if (fromTools != null) {\n let transformedList = t.tTools(fromTools);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return toolToMldev(t.tTool(item));\n });\n }\n common.setValueByPath(toObject, ['tools'], transformedList);\n }\n\n const fromRealtimeInputConfig = common.getValueByPath(fromObject, [\n 'realtimeInputConfig',\n ]);\n if (fromRealtimeInputConfig != null) {\n common.setValueByPath(\n toObject,\n ['realtimeInputConfig'],\n fromRealtimeInputConfig,\n );\n }\n\n const fromSessionResumption = common.getValueByPath(fromObject, [\n 'sessionResumption',\n ]);\n if (fromSessionResumption != null) {\n common.setValueByPath(\n toObject,\n ['sessionResumption'],\n sessionResumptionConfigToMldev(fromSessionResumption),\n );\n }\n\n const fromContextWindowCompression = common.getValueByPath(fromObject, [\n 'contextWindowCompression',\n ]);\n if (fromContextWindowCompression != null) {\n common.setValueByPath(\n toObject,\n ['contextWindowCompression'],\n fromContextWindowCompression,\n );\n }\n\n const fromInputAudioTranscription = common.getValueByPath(fromObject, [\n 'inputAudioTranscription',\n ]);\n if (fromInputAudioTranscription != null) {\n common.setValueByPath(\n toObject,\n ['inputAudioTranscription'],\n fromInputAudioTranscription,\n );\n }\n\n const fromOutputAudioTranscription = common.getValueByPath(fromObject, [\n 'outputAudioTranscription',\n ]);\n if (fromOutputAudioTranscription != null) {\n common.setValueByPath(\n toObject,\n ['outputAudioTranscription'],\n fromOutputAudioTranscription,\n );\n }\n\n const fromProactivity = common.getValueByPath(fromObject, ['proactivity']);\n if (fromProactivity != null) {\n common.setValueByPath(toObject, ['proactivity'], fromProactivity);\n }\n\n if (common.getValueByPath(fromObject, ['explicitVadSignal']) !== undefined) {\n throw new Error(\n 'explicitVadSignal parameter is not supported in Gemini API.',\n );\n }\n\n return toObject;\n}\n\nexport function liveClientSetupToVertex(\n fromObject: types.LiveClientSetup,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(toObject, ['model'], fromModel);\n }\n\n const fromGenerationConfig = common.getValueByPath(fromObject, [\n 'generationConfig',\n ]);\n if (fromGenerationConfig != null) {\n common.setValueByPath(\n toObject,\n ['generationConfig'],\n generationConfigToVertex(fromGenerationConfig),\n );\n }\n\n const fromSystemInstruction = common.getValueByPath(fromObject, [\n 'systemInstruction',\n ]);\n if (fromSystemInstruction != null) {\n common.setValueByPath(\n toObject,\n ['systemInstruction'],\n t.tContent(fromSystemInstruction),\n );\n }\n\n const fromTools = common.getValueByPath(fromObject, ['tools']);\n if (fromTools != null) {\n let transformedList = t.tTools(fromTools);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return toolToVertex(t.tTool(item));\n });\n }\n common.setValueByPath(toObject, ['tools'], transformedList);\n }\n\n const fromRealtimeInputConfig = common.getValueByPath(fromObject, [\n 'realtimeInputConfig',\n ]);\n if (fromRealtimeInputConfig != null) {\n common.setValueByPath(\n toObject,\n ['realtimeInputConfig'],\n fromRealtimeInputConfig,\n );\n }\n\n const fromSessionResumption = common.getValueByPath(fromObject, [\n 'sessionResumption',\n ]);\n if (fromSessionResumption != null) {\n common.setValueByPath(\n toObject,\n ['sessionResumption'],\n fromSessionResumption,\n );\n }\n\n const fromContextWindowCompression = common.getValueByPath(fromObject, [\n 'contextWindowCompression',\n ]);\n if (fromContextWindowCompression != null) {\n common.setValueByPath(\n toObject,\n ['contextWindowCompression'],\n fromContextWindowCompression,\n );\n }\n\n const fromInputAudioTranscription = common.getValueByPath(fromObject, [\n 'inputAudioTranscription',\n ]);\n if (fromInputAudioTranscription != null) {\n common.setValueByPath(\n toObject,\n ['inputAudioTranscription'],\n fromInputAudioTranscription,\n );\n }\n\n const fromOutputAudioTranscription = common.getValueByPath(fromObject, [\n 'outputAudioTranscription',\n ]);\n if (fromOutputAudioTranscription != null) {\n common.setValueByPath(\n toObject,\n ['outputAudioTranscription'],\n fromOutputAudioTranscription,\n );\n }\n\n const fromProactivity = common.getValueByPath(fromObject, ['proactivity']);\n if (fromProactivity != null) {\n common.setValueByPath(toObject, ['proactivity'], fromProactivity);\n }\n\n const fromExplicitVadSignal = common.getValueByPath(fromObject, [\n 'explicitVadSignal',\n ]);\n if (fromExplicitVadSignal != null) {\n common.setValueByPath(\n toObject,\n ['explicitVadSignal'],\n fromExplicitVadSignal,\n );\n }\n\n return toObject;\n}\n\nexport function liveConnectConfigToMldev(\n fromObject: types.LiveConnectConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromGenerationConfig = common.getValueByPath(fromObject, [\n 'generationConfig',\n ]);\n if (parentObject !== undefined && fromGenerationConfig != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig'],\n fromGenerationConfig,\n );\n }\n\n const fromResponseModalities = common.getValueByPath(fromObject, [\n 'responseModalities',\n ]);\n if (parentObject !== undefined && fromResponseModalities != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'responseModalities'],\n fromResponseModalities,\n );\n }\n\n const fromTemperature = common.getValueByPath(fromObject, ['temperature']);\n if (parentObject !== undefined && fromTemperature != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'temperature'],\n fromTemperature,\n );\n }\n\n const fromTopP = common.getValueByPath(fromObject, ['topP']);\n if (parentObject !== undefined && fromTopP != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'topP'],\n fromTopP,\n );\n }\n\n const fromTopK = common.getValueByPath(fromObject, ['topK']);\n if (parentObject !== undefined && fromTopK != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'topK'],\n fromTopK,\n );\n }\n\n const fromMaxOutputTokens = common.getValueByPath(fromObject, [\n 'maxOutputTokens',\n ]);\n if (parentObject !== undefined && fromMaxOutputTokens != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'maxOutputTokens'],\n fromMaxOutputTokens,\n );\n }\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (parentObject !== undefined && fromMediaResolution != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'mediaResolution'],\n fromMediaResolution,\n );\n }\n\n const fromSeed = common.getValueByPath(fromObject, ['seed']);\n if (parentObject !== undefined && fromSeed != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'seed'],\n fromSeed,\n );\n }\n\n const fromSpeechConfig = common.getValueByPath(fromObject, ['speechConfig']);\n if (parentObject !== undefined && fromSpeechConfig != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'speechConfig'],\n t.tLiveSpeechConfig(fromSpeechConfig),\n );\n }\n\n const fromThinkingConfig = common.getValueByPath(fromObject, [\n 'thinkingConfig',\n ]);\n if (parentObject !== undefined && fromThinkingConfig != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'thinkingConfig'],\n fromThinkingConfig,\n );\n }\n\n const fromEnableAffectiveDialog = common.getValueByPath(fromObject, [\n 'enableAffectiveDialog',\n ]);\n if (parentObject !== undefined && fromEnableAffectiveDialog != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'enableAffectiveDialog'],\n fromEnableAffectiveDialog,\n );\n }\n\n const fromSystemInstruction = common.getValueByPath(fromObject, [\n 'systemInstruction',\n ]);\n if (parentObject !== undefined && fromSystemInstruction != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'systemInstruction'],\n contentToMldev(t.tContent(fromSystemInstruction)),\n );\n }\n\n const fromTools = common.getValueByPath(fromObject, ['tools']);\n if (parentObject !== undefined && fromTools != null) {\n let transformedList = t.tTools(fromTools);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return toolToMldev(t.tTool(item));\n });\n }\n common.setValueByPath(parentObject, ['setup', 'tools'], transformedList);\n }\n\n const fromSessionResumption = common.getValueByPath(fromObject, [\n 'sessionResumption',\n ]);\n if (parentObject !== undefined && fromSessionResumption != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'sessionResumption'],\n sessionResumptionConfigToMldev(fromSessionResumption),\n );\n }\n\n const fromInputAudioTranscription = common.getValueByPath(fromObject, [\n 'inputAudioTranscription',\n ]);\n if (parentObject !== undefined && fromInputAudioTranscription != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'inputAudioTranscription'],\n fromInputAudioTranscription,\n );\n }\n\n const fromOutputAudioTranscription = common.getValueByPath(fromObject, [\n 'outputAudioTranscription',\n ]);\n if (parentObject !== undefined && fromOutputAudioTranscription != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'outputAudioTranscription'],\n fromOutputAudioTranscription,\n );\n }\n\n const fromRealtimeInputConfig = common.getValueByPath(fromObject, [\n 'realtimeInputConfig',\n ]);\n if (parentObject !== undefined && fromRealtimeInputConfig != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'realtimeInputConfig'],\n fromRealtimeInputConfig,\n );\n }\n\n const fromContextWindowCompression = common.getValueByPath(fromObject, [\n 'contextWindowCompression',\n ]);\n if (parentObject !== undefined && fromContextWindowCompression != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'contextWindowCompression'],\n fromContextWindowCompression,\n );\n }\n\n const fromProactivity = common.getValueByPath(fromObject, ['proactivity']);\n if (parentObject !== undefined && fromProactivity != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'proactivity'],\n fromProactivity,\n );\n }\n\n if (common.getValueByPath(fromObject, ['explicitVadSignal']) !== undefined) {\n throw new Error(\n 'explicitVadSignal parameter is not supported in Gemini API.',\n );\n }\n\n return toObject;\n}\n\nexport function liveConnectConfigToVertex(\n fromObject: types.LiveConnectConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromGenerationConfig = common.getValueByPath(fromObject, [\n 'generationConfig',\n ]);\n if (parentObject !== undefined && fromGenerationConfig != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig'],\n generationConfigToVertex(fromGenerationConfig),\n );\n }\n\n const fromResponseModalities = common.getValueByPath(fromObject, [\n 'responseModalities',\n ]);\n if (parentObject !== undefined && fromResponseModalities != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'responseModalities'],\n fromResponseModalities,\n );\n }\n\n const fromTemperature = common.getValueByPath(fromObject, ['temperature']);\n if (parentObject !== undefined && fromTemperature != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'temperature'],\n fromTemperature,\n );\n }\n\n const fromTopP = common.getValueByPath(fromObject, ['topP']);\n if (parentObject !== undefined && fromTopP != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'topP'],\n fromTopP,\n );\n }\n\n const fromTopK = common.getValueByPath(fromObject, ['topK']);\n if (parentObject !== undefined && fromTopK != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'topK'],\n fromTopK,\n );\n }\n\n const fromMaxOutputTokens = common.getValueByPath(fromObject, [\n 'maxOutputTokens',\n ]);\n if (parentObject !== undefined && fromMaxOutputTokens != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'maxOutputTokens'],\n fromMaxOutputTokens,\n );\n }\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (parentObject !== undefined && fromMediaResolution != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'mediaResolution'],\n fromMediaResolution,\n );\n }\n\n const fromSeed = common.getValueByPath(fromObject, ['seed']);\n if (parentObject !== undefined && fromSeed != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'seed'],\n fromSeed,\n );\n }\n\n const fromSpeechConfig = common.getValueByPath(fromObject, ['speechConfig']);\n if (parentObject !== undefined && fromSpeechConfig != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'speechConfig'],\n t.tLiveSpeechConfig(fromSpeechConfig),\n );\n }\n\n const fromThinkingConfig = common.getValueByPath(fromObject, [\n 'thinkingConfig',\n ]);\n if (parentObject !== undefined && fromThinkingConfig != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'thinkingConfig'],\n fromThinkingConfig,\n );\n }\n\n const fromEnableAffectiveDialog = common.getValueByPath(fromObject, [\n 'enableAffectiveDialog',\n ]);\n if (parentObject !== undefined && fromEnableAffectiveDialog != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'enableAffectiveDialog'],\n fromEnableAffectiveDialog,\n );\n }\n\n const fromSystemInstruction = common.getValueByPath(fromObject, [\n 'systemInstruction',\n ]);\n if (parentObject !== undefined && fromSystemInstruction != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'systemInstruction'],\n t.tContent(fromSystemInstruction),\n );\n }\n\n const fromTools = common.getValueByPath(fromObject, ['tools']);\n if (parentObject !== undefined && fromTools != null) {\n let transformedList = t.tTools(fromTools);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return toolToVertex(t.tTool(item));\n });\n }\n common.setValueByPath(parentObject, ['setup', 'tools'], transformedList);\n }\n\n const fromSessionResumption = common.getValueByPath(fromObject, [\n 'sessionResumption',\n ]);\n if (parentObject !== undefined && fromSessionResumption != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'sessionResumption'],\n fromSessionResumption,\n );\n }\n\n const fromInputAudioTranscription = common.getValueByPath(fromObject, [\n 'inputAudioTranscription',\n ]);\n if (parentObject !== undefined && fromInputAudioTranscription != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'inputAudioTranscription'],\n fromInputAudioTranscription,\n );\n }\n\n const fromOutputAudioTranscription = common.getValueByPath(fromObject, [\n 'outputAudioTranscription',\n ]);\n if (parentObject !== undefined && fromOutputAudioTranscription != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'outputAudioTranscription'],\n fromOutputAudioTranscription,\n );\n }\n\n const fromRealtimeInputConfig = common.getValueByPath(fromObject, [\n 'realtimeInputConfig',\n ]);\n if (parentObject !== undefined && fromRealtimeInputConfig != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'realtimeInputConfig'],\n fromRealtimeInputConfig,\n );\n }\n\n const fromContextWindowCompression = common.getValueByPath(fromObject, [\n 'contextWindowCompression',\n ]);\n if (parentObject !== undefined && fromContextWindowCompression != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'contextWindowCompression'],\n fromContextWindowCompression,\n );\n }\n\n const fromProactivity = common.getValueByPath(fromObject, ['proactivity']);\n if (parentObject !== undefined && fromProactivity != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'proactivity'],\n fromProactivity,\n );\n }\n\n const fromExplicitVadSignal = common.getValueByPath(fromObject, [\n 'explicitVadSignal',\n ]);\n if (parentObject !== undefined && fromExplicitVadSignal != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'explicitVadSignal'],\n fromExplicitVadSignal,\n );\n }\n\n return toObject;\n}\n\nexport function liveConnectParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.LiveConnectParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['setup', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n common.setValueByPath(\n toObject,\n ['config'],\n liveConnectConfigToMldev(fromConfig, toObject),\n );\n }\n\n return toObject;\n}\n\nexport function liveConnectParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.LiveConnectParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['setup', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n common.setValueByPath(\n toObject,\n ['config'],\n liveConnectConfigToVertex(fromConfig, toObject),\n );\n }\n\n return toObject;\n}\n\nexport function liveMusicClientMessageToVertex(\n fromObject: types.LiveMusicClientMessage,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['setup']) !== undefined) {\n throw new Error('setup parameter is not supported in Vertex AI.');\n }\n\n if (common.getValueByPath(fromObject, ['clientContent']) !== undefined) {\n throw new Error('clientContent parameter is not supported in Vertex AI.');\n }\n\n if (\n common.getValueByPath(fromObject, ['musicGenerationConfig']) !== undefined\n ) {\n throw new Error(\n 'musicGenerationConfig parameter is not supported in Vertex AI.',\n );\n }\n\n if (common.getValueByPath(fromObject, ['playbackControl']) !== undefined) {\n throw new Error('playbackControl parameter is not supported in Vertex AI.');\n }\n\n return toObject;\n}\n\nexport function liveMusicConnectParametersToMldev(\n fromObject: types.LiveMusicConnectParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(toObject, ['setup', 'model'], fromModel);\n }\n\n const fromCallbacks = common.getValueByPath(fromObject, ['callbacks']);\n if (fromCallbacks != null) {\n common.setValueByPath(toObject, ['callbacks'], fromCallbacks);\n }\n\n return toObject;\n}\n\nexport function liveMusicConnectParametersToVertex(\n fromObject: types.LiveMusicConnectParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['model']) !== undefined) {\n throw new Error('model parameter is not supported in Vertex AI.');\n }\n\n if (common.getValueByPath(fromObject, ['callbacks']) !== undefined) {\n throw new Error('callbacks parameter is not supported in Vertex AI.');\n }\n\n return toObject;\n}\n\nexport function liveMusicSetConfigParametersToMldev(\n fromObject: types.LiveMusicSetConfigParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMusicGenerationConfig = common.getValueByPath(fromObject, [\n 'musicGenerationConfig',\n ]);\n if (fromMusicGenerationConfig != null) {\n common.setValueByPath(\n toObject,\n ['musicGenerationConfig'],\n fromMusicGenerationConfig,\n );\n }\n\n return toObject;\n}\n\nexport function liveMusicSetConfigParametersToVertex(\n fromObject: types.LiveMusicSetConfigParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (\n common.getValueByPath(fromObject, ['musicGenerationConfig']) !== undefined\n ) {\n throw new Error(\n 'musicGenerationConfig parameter is not supported in Vertex AI.',\n );\n }\n\n return toObject;\n}\n\nexport function liveMusicSetWeightedPromptsParametersToMldev(\n fromObject: types.LiveMusicSetWeightedPromptsParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromWeightedPrompts = common.getValueByPath(fromObject, [\n 'weightedPrompts',\n ]);\n if (fromWeightedPrompts != null) {\n let transformedList = fromWeightedPrompts;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['weightedPrompts'], transformedList);\n }\n\n return toObject;\n}\n\nexport function liveMusicSetWeightedPromptsParametersToVertex(\n fromObject: types.LiveMusicSetWeightedPromptsParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['weightedPrompts']) !== undefined) {\n throw new Error('weightedPrompts parameter is not supported in Vertex AI.');\n }\n\n return toObject;\n}\n\nexport function liveSendRealtimeInputParametersToMldev(\n fromObject: types.LiveSendRealtimeInputParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMedia = common.getValueByPath(fromObject, ['media']);\n if (fromMedia != null) {\n let transformedList = t.tBlobs(fromMedia);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return blobToMldev(item);\n });\n }\n common.setValueByPath(toObject, ['mediaChunks'], transformedList);\n }\n\n const fromAudio = common.getValueByPath(fromObject, ['audio']);\n if (fromAudio != null) {\n common.setValueByPath(\n toObject,\n ['audio'],\n blobToMldev(t.tAudioBlob(fromAudio)),\n );\n }\n\n const fromAudioStreamEnd = common.getValueByPath(fromObject, [\n 'audioStreamEnd',\n ]);\n if (fromAudioStreamEnd != null) {\n common.setValueByPath(toObject, ['audioStreamEnd'], fromAudioStreamEnd);\n }\n\n const fromVideo = common.getValueByPath(fromObject, ['video']);\n if (fromVideo != null) {\n common.setValueByPath(\n toObject,\n ['video'],\n blobToMldev(t.tImageBlob(fromVideo)),\n );\n }\n\n const fromText = common.getValueByPath(fromObject, ['text']);\n if (fromText != null) {\n common.setValueByPath(toObject, ['text'], fromText);\n }\n\n const fromActivityStart = common.getValueByPath(fromObject, [\n 'activityStart',\n ]);\n if (fromActivityStart != null) {\n common.setValueByPath(toObject, ['activityStart'], fromActivityStart);\n }\n\n const fromActivityEnd = common.getValueByPath(fromObject, ['activityEnd']);\n if (fromActivityEnd != null) {\n common.setValueByPath(toObject, ['activityEnd'], fromActivityEnd);\n }\n\n return toObject;\n}\n\nexport function liveSendRealtimeInputParametersToVertex(\n fromObject: types.LiveSendRealtimeInputParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMedia = common.getValueByPath(fromObject, ['media']);\n if (fromMedia != null) {\n let transformedList = t.tBlobs(fromMedia);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['mediaChunks'], transformedList);\n }\n\n const fromAudio = common.getValueByPath(fromObject, ['audio']);\n if (fromAudio != null) {\n common.setValueByPath(toObject, ['audio'], t.tAudioBlob(fromAudio));\n }\n\n const fromAudioStreamEnd = common.getValueByPath(fromObject, [\n 'audioStreamEnd',\n ]);\n if (fromAudioStreamEnd != null) {\n common.setValueByPath(toObject, ['audioStreamEnd'], fromAudioStreamEnd);\n }\n\n const fromVideo = common.getValueByPath(fromObject, ['video']);\n if (fromVideo != null) {\n common.setValueByPath(toObject, ['video'], t.tImageBlob(fromVideo));\n }\n\n const fromText = common.getValueByPath(fromObject, ['text']);\n if (fromText != null) {\n common.setValueByPath(toObject, ['text'], fromText);\n }\n\n const fromActivityStart = common.getValueByPath(fromObject, [\n 'activityStart',\n ]);\n if (fromActivityStart != null) {\n common.setValueByPath(toObject, ['activityStart'], fromActivityStart);\n }\n\n const fromActivityEnd = common.getValueByPath(fromObject, ['activityEnd']);\n if (fromActivityEnd != null) {\n common.setValueByPath(toObject, ['activityEnd'], fromActivityEnd);\n }\n\n return toObject;\n}\n\nexport function liveServerMessageFromMldev(\n fromObject: types.LiveServerMessage,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSetupComplete = common.getValueByPath(fromObject, [\n 'setupComplete',\n ]);\n if (fromSetupComplete != null) {\n common.setValueByPath(toObject, ['setupComplete'], fromSetupComplete);\n }\n\n const fromServerContent = common.getValueByPath(fromObject, [\n 'serverContent',\n ]);\n if (fromServerContent != null) {\n common.setValueByPath(toObject, ['serverContent'], fromServerContent);\n }\n\n const fromToolCall = common.getValueByPath(fromObject, ['toolCall']);\n if (fromToolCall != null) {\n common.setValueByPath(toObject, ['toolCall'], fromToolCall);\n }\n\n const fromToolCallCancellation = common.getValueByPath(fromObject, [\n 'toolCallCancellation',\n ]);\n if (fromToolCallCancellation != null) {\n common.setValueByPath(\n toObject,\n ['toolCallCancellation'],\n fromToolCallCancellation,\n );\n }\n\n const fromUsageMetadata = common.getValueByPath(fromObject, [\n 'usageMetadata',\n ]);\n if (fromUsageMetadata != null) {\n common.setValueByPath(toObject, ['usageMetadata'], fromUsageMetadata);\n }\n\n const fromGoAway = common.getValueByPath(fromObject, ['goAway']);\n if (fromGoAway != null) {\n common.setValueByPath(toObject, ['goAway'], fromGoAway);\n }\n\n const fromSessionResumptionUpdate = common.getValueByPath(fromObject, [\n 'sessionResumptionUpdate',\n ]);\n if (fromSessionResumptionUpdate != null) {\n common.setValueByPath(\n toObject,\n ['sessionResumptionUpdate'],\n fromSessionResumptionUpdate,\n );\n }\n\n const fromVoiceActivityDetectionSignal = common.getValueByPath(fromObject, [\n 'voiceActivityDetectionSignal',\n ]);\n if (fromVoiceActivityDetectionSignal != null) {\n common.setValueByPath(\n toObject,\n ['voiceActivityDetectionSignal'],\n fromVoiceActivityDetectionSignal,\n );\n }\n\n const fromVoiceActivity = common.getValueByPath(fromObject, [\n 'voiceActivity',\n ]);\n if (fromVoiceActivity != null) {\n common.setValueByPath(\n toObject,\n ['voiceActivity'],\n voiceActivityFromMldev(fromVoiceActivity),\n );\n }\n\n return toObject;\n}\n\nexport function liveServerMessageFromVertex(\n fromObject: types.LiveServerMessage,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSetupComplete = common.getValueByPath(fromObject, [\n 'setupComplete',\n ]);\n if (fromSetupComplete != null) {\n common.setValueByPath(toObject, ['setupComplete'], fromSetupComplete);\n }\n\n const fromServerContent = common.getValueByPath(fromObject, [\n 'serverContent',\n ]);\n if (fromServerContent != null) {\n common.setValueByPath(toObject, ['serverContent'], fromServerContent);\n }\n\n const fromToolCall = common.getValueByPath(fromObject, ['toolCall']);\n if (fromToolCall != null) {\n common.setValueByPath(toObject, ['toolCall'], fromToolCall);\n }\n\n const fromToolCallCancellation = common.getValueByPath(fromObject, [\n 'toolCallCancellation',\n ]);\n if (fromToolCallCancellation != null) {\n common.setValueByPath(\n toObject,\n ['toolCallCancellation'],\n fromToolCallCancellation,\n );\n }\n\n const fromUsageMetadata = common.getValueByPath(fromObject, [\n 'usageMetadata',\n ]);\n if (fromUsageMetadata != null) {\n common.setValueByPath(\n toObject,\n ['usageMetadata'],\n usageMetadataFromVertex(fromUsageMetadata),\n );\n }\n\n const fromGoAway = common.getValueByPath(fromObject, ['goAway']);\n if (fromGoAway != null) {\n common.setValueByPath(toObject, ['goAway'], fromGoAway);\n }\n\n const fromSessionResumptionUpdate = common.getValueByPath(fromObject, [\n 'sessionResumptionUpdate',\n ]);\n if (fromSessionResumptionUpdate != null) {\n common.setValueByPath(\n toObject,\n ['sessionResumptionUpdate'],\n fromSessionResumptionUpdate,\n );\n }\n\n const fromVoiceActivityDetectionSignal = common.getValueByPath(fromObject, [\n 'voiceActivityDetectionSignal',\n ]);\n if (fromVoiceActivityDetectionSignal != null) {\n common.setValueByPath(\n toObject,\n ['voiceActivityDetectionSignal'],\n fromVoiceActivityDetectionSignal,\n );\n }\n\n const fromVoiceActivity = common.getValueByPath(fromObject, [\n 'voiceActivity',\n ]);\n if (fromVoiceActivity != null) {\n common.setValueByPath(\n toObject,\n ['voiceActivity'],\n voiceActivityFromVertex(fromVoiceActivity),\n );\n }\n\n return toObject;\n}\n\nexport function partToMldev(fromObject: types.Part): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (fromMediaResolution != null) {\n common.setValueByPath(toObject, ['mediaResolution'], fromMediaResolution);\n }\n\n const fromCodeExecutionResult = common.getValueByPath(fromObject, [\n 'codeExecutionResult',\n ]);\n if (fromCodeExecutionResult != null) {\n common.setValueByPath(\n toObject,\n ['codeExecutionResult'],\n fromCodeExecutionResult,\n );\n }\n\n const fromExecutableCode = common.getValueByPath(fromObject, [\n 'executableCode',\n ]);\n if (fromExecutableCode != null) {\n common.setValueByPath(toObject, ['executableCode'], fromExecutableCode);\n }\n\n const fromFileData = common.getValueByPath(fromObject, ['fileData']);\n if (fromFileData != null) {\n common.setValueByPath(\n toObject,\n ['fileData'],\n fileDataToMldev(fromFileData),\n );\n }\n\n const fromFunctionCall = common.getValueByPath(fromObject, ['functionCall']);\n if (fromFunctionCall != null) {\n common.setValueByPath(\n toObject,\n ['functionCall'],\n functionCallToMldev(fromFunctionCall),\n );\n }\n\n const fromFunctionResponse = common.getValueByPath(fromObject, [\n 'functionResponse',\n ]);\n if (fromFunctionResponse != null) {\n common.setValueByPath(toObject, ['functionResponse'], fromFunctionResponse);\n }\n\n const fromInlineData = common.getValueByPath(fromObject, ['inlineData']);\n if (fromInlineData != null) {\n common.setValueByPath(\n toObject,\n ['inlineData'],\n blobToMldev(fromInlineData),\n );\n }\n\n const fromText = common.getValueByPath(fromObject, ['text']);\n if (fromText != null) {\n common.setValueByPath(toObject, ['text'], fromText);\n }\n\n const fromThought = common.getValueByPath(fromObject, ['thought']);\n if (fromThought != null) {\n common.setValueByPath(toObject, ['thought'], fromThought);\n }\n\n const fromThoughtSignature = common.getValueByPath(fromObject, [\n 'thoughtSignature',\n ]);\n if (fromThoughtSignature != null) {\n common.setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature);\n }\n\n const fromVideoMetadata = common.getValueByPath(fromObject, [\n 'videoMetadata',\n ]);\n if (fromVideoMetadata != null) {\n common.setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata);\n }\n\n return toObject;\n}\n\nexport function sessionResumptionConfigToMldev(\n fromObject: types.SessionResumptionConfig,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromHandle = common.getValueByPath(fromObject, ['handle']);\n if (fromHandle != null) {\n common.setValueByPath(toObject, ['handle'], fromHandle);\n }\n\n if (common.getValueByPath(fromObject, ['transparent']) !== undefined) {\n throw new Error('transparent parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function toolToMldev(fromObject: types.Tool): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['retrieval']) !== undefined) {\n throw new Error('retrieval parameter is not supported in Gemini API.');\n }\n\n const fromComputerUse = common.getValueByPath(fromObject, ['computerUse']);\n if (fromComputerUse != null) {\n common.setValueByPath(toObject, ['computerUse'], fromComputerUse);\n }\n\n const fromFileSearch = common.getValueByPath(fromObject, ['fileSearch']);\n if (fromFileSearch != null) {\n common.setValueByPath(toObject, ['fileSearch'], fromFileSearch);\n }\n\n const fromCodeExecution = common.getValueByPath(fromObject, [\n 'codeExecution',\n ]);\n if (fromCodeExecution != null) {\n common.setValueByPath(toObject, ['codeExecution'], fromCodeExecution);\n }\n\n if (\n common.getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined\n ) {\n throw new Error(\n 'enterpriseWebSearch parameter is not supported in Gemini API.',\n );\n }\n\n const fromFunctionDeclarations = common.getValueByPath(fromObject, [\n 'functionDeclarations',\n ]);\n if (fromFunctionDeclarations != null) {\n let transformedList = fromFunctionDeclarations;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['functionDeclarations'], transformedList);\n }\n\n const fromGoogleMaps = common.getValueByPath(fromObject, ['googleMaps']);\n if (fromGoogleMaps != null) {\n common.setValueByPath(\n toObject,\n ['googleMaps'],\n googleMapsToMldev(fromGoogleMaps),\n );\n }\n\n const fromGoogleSearch = common.getValueByPath(fromObject, ['googleSearch']);\n if (fromGoogleSearch != null) {\n common.setValueByPath(\n toObject,\n ['googleSearch'],\n googleSearchToMldev(fromGoogleSearch),\n );\n }\n\n const fromGoogleSearchRetrieval = common.getValueByPath(fromObject, [\n 'googleSearchRetrieval',\n ]);\n if (fromGoogleSearchRetrieval != null) {\n common.setValueByPath(\n toObject,\n ['googleSearchRetrieval'],\n fromGoogleSearchRetrieval,\n );\n }\n\n const fromUrlContext = common.getValueByPath(fromObject, ['urlContext']);\n if (fromUrlContext != null) {\n common.setValueByPath(toObject, ['urlContext'], fromUrlContext);\n }\n\n return toObject;\n}\n\nexport function toolToVertex(fromObject: types.Tool): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromRetrieval = common.getValueByPath(fromObject, ['retrieval']);\n if (fromRetrieval != null) {\n common.setValueByPath(toObject, ['retrieval'], fromRetrieval);\n }\n\n const fromComputerUse = common.getValueByPath(fromObject, ['computerUse']);\n if (fromComputerUse != null) {\n common.setValueByPath(toObject, ['computerUse'], fromComputerUse);\n }\n\n if (common.getValueByPath(fromObject, ['fileSearch']) !== undefined) {\n throw new Error('fileSearch parameter is not supported in Vertex AI.');\n }\n\n const fromCodeExecution = common.getValueByPath(fromObject, [\n 'codeExecution',\n ]);\n if (fromCodeExecution != null) {\n common.setValueByPath(toObject, ['codeExecution'], fromCodeExecution);\n }\n\n const fromEnterpriseWebSearch = common.getValueByPath(fromObject, [\n 'enterpriseWebSearch',\n ]);\n if (fromEnterpriseWebSearch != null) {\n common.setValueByPath(\n toObject,\n ['enterpriseWebSearch'],\n fromEnterpriseWebSearch,\n );\n }\n\n const fromFunctionDeclarations = common.getValueByPath(fromObject, [\n 'functionDeclarations',\n ]);\n if (fromFunctionDeclarations != null) {\n let transformedList = fromFunctionDeclarations;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return functionDeclarationToVertex(item);\n });\n }\n common.setValueByPath(toObject, ['functionDeclarations'], transformedList);\n }\n\n const fromGoogleMaps = common.getValueByPath(fromObject, ['googleMaps']);\n if (fromGoogleMaps != null) {\n common.setValueByPath(toObject, ['googleMaps'], fromGoogleMaps);\n }\n\n const fromGoogleSearch = common.getValueByPath(fromObject, ['googleSearch']);\n if (fromGoogleSearch != null) {\n common.setValueByPath(toObject, ['googleSearch'], fromGoogleSearch);\n }\n\n const fromGoogleSearchRetrieval = common.getValueByPath(fromObject, [\n 'googleSearchRetrieval',\n ]);\n if (fromGoogleSearchRetrieval != null) {\n common.setValueByPath(\n toObject,\n ['googleSearchRetrieval'],\n fromGoogleSearchRetrieval,\n );\n }\n\n const fromUrlContext = common.getValueByPath(fromObject, ['urlContext']);\n if (fromUrlContext != null) {\n common.setValueByPath(toObject, ['urlContext'], fromUrlContext);\n }\n\n return toObject;\n}\n\nexport function usageMetadataFromVertex(\n fromObject: types.UsageMetadata,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPromptTokenCount = common.getValueByPath(fromObject, [\n 'promptTokenCount',\n ]);\n if (fromPromptTokenCount != null) {\n common.setValueByPath(toObject, ['promptTokenCount'], fromPromptTokenCount);\n }\n\n const fromCachedContentTokenCount = common.getValueByPath(fromObject, [\n 'cachedContentTokenCount',\n ]);\n if (fromCachedContentTokenCount != null) {\n common.setValueByPath(\n toObject,\n ['cachedContentTokenCount'],\n fromCachedContentTokenCount,\n );\n }\n\n const fromResponseTokenCount = common.getValueByPath(fromObject, [\n 'candidatesTokenCount',\n ]);\n if (fromResponseTokenCount != null) {\n common.setValueByPath(\n toObject,\n ['responseTokenCount'],\n fromResponseTokenCount,\n );\n }\n\n const fromToolUsePromptTokenCount = common.getValueByPath(fromObject, [\n 'toolUsePromptTokenCount',\n ]);\n if (fromToolUsePromptTokenCount != null) {\n common.setValueByPath(\n toObject,\n ['toolUsePromptTokenCount'],\n fromToolUsePromptTokenCount,\n );\n }\n\n const fromThoughtsTokenCount = common.getValueByPath(fromObject, [\n 'thoughtsTokenCount',\n ]);\n if (fromThoughtsTokenCount != null) {\n common.setValueByPath(\n toObject,\n ['thoughtsTokenCount'],\n fromThoughtsTokenCount,\n );\n }\n\n const fromTotalTokenCount = common.getValueByPath(fromObject, [\n 'totalTokenCount',\n ]);\n if (fromTotalTokenCount != null) {\n common.setValueByPath(toObject, ['totalTokenCount'], fromTotalTokenCount);\n }\n\n const fromPromptTokensDetails = common.getValueByPath(fromObject, [\n 'promptTokensDetails',\n ]);\n if (fromPromptTokensDetails != null) {\n let transformedList = fromPromptTokensDetails;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['promptTokensDetails'], transformedList);\n }\n\n const fromCacheTokensDetails = common.getValueByPath(fromObject, [\n 'cacheTokensDetails',\n ]);\n if (fromCacheTokensDetails != null) {\n let transformedList = fromCacheTokensDetails;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['cacheTokensDetails'], transformedList);\n }\n\n const fromResponseTokensDetails = common.getValueByPath(fromObject, [\n 'candidatesTokensDetails',\n ]);\n if (fromResponseTokensDetails != null) {\n let transformedList = fromResponseTokensDetails;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['responseTokensDetails'], transformedList);\n }\n\n const fromToolUsePromptTokensDetails = common.getValueByPath(fromObject, [\n 'toolUsePromptTokensDetails',\n ]);\n if (fromToolUsePromptTokensDetails != null) {\n let transformedList = fromToolUsePromptTokensDetails;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(\n toObject,\n ['toolUsePromptTokensDetails'],\n transformedList,\n );\n }\n\n const fromTrafficType = common.getValueByPath(fromObject, ['trafficType']);\n if (fromTrafficType != null) {\n common.setValueByPath(toObject, ['trafficType'], fromTrafficType);\n }\n\n return toObject;\n}\n\nexport function voiceActivityFromMldev(\n fromObject: types.VoiceActivity,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromVoiceActivityType = common.getValueByPath(fromObject, ['type']);\n if (fromVoiceActivityType != null) {\n common.setValueByPath(\n toObject,\n ['voiceActivityType'],\n fromVoiceActivityType,\n );\n }\n\n return toObject;\n}\n\nexport function voiceActivityFromVertex(\n fromObject: types.VoiceActivity,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromVoiceActivityType = common.getValueByPath(fromObject, ['type']);\n if (fromVoiceActivityType != null) {\n common.setValueByPath(\n toObject,\n ['voiceActivityType'],\n fromVoiceActivityType,\n );\n }\n\n return toObject;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport {ApiClient} from '../_api_client.js';\nimport * as common from '../_common.js';\nimport type * as _internal_types from '../_internal_types.js';\nimport * as t from '../_transformers.js';\nimport type * as types from '../types.js';\n\nexport function blobToMldev(\n fromObject: types.Blob,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromData = common.getValueByPath(fromObject, ['data']);\n if (fromData != null) {\n common.setValueByPath(toObject, ['data'], fromData);\n }\n\n if (common.getValueByPath(fromObject, ['displayName']) !== undefined) {\n throw new Error('displayName parameter is not supported in Gemini API.');\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function candidateFromMldev(\n fromObject: types.Candidate,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromContent = common.getValueByPath(fromObject, ['content']);\n if (fromContent != null) {\n common.setValueByPath(toObject, ['content'], fromContent);\n }\n\n const fromCitationMetadata = common.getValueByPath(fromObject, [\n 'citationMetadata',\n ]);\n if (fromCitationMetadata != null) {\n common.setValueByPath(\n toObject,\n ['citationMetadata'],\n citationMetadataFromMldev(fromCitationMetadata, rootObject),\n );\n }\n\n const fromTokenCount = common.getValueByPath(fromObject, ['tokenCount']);\n if (fromTokenCount != null) {\n common.setValueByPath(toObject, ['tokenCount'], fromTokenCount);\n }\n\n const fromFinishReason = common.getValueByPath(fromObject, ['finishReason']);\n if (fromFinishReason != null) {\n common.setValueByPath(toObject, ['finishReason'], fromFinishReason);\n }\n\n const fromAvgLogprobs = common.getValueByPath(fromObject, ['avgLogprobs']);\n if (fromAvgLogprobs != null) {\n common.setValueByPath(toObject, ['avgLogprobs'], fromAvgLogprobs);\n }\n\n const fromGroundingMetadata = common.getValueByPath(fromObject, [\n 'groundingMetadata',\n ]);\n if (fromGroundingMetadata != null) {\n common.setValueByPath(\n toObject,\n ['groundingMetadata'],\n fromGroundingMetadata,\n );\n }\n\n const fromIndex = common.getValueByPath(fromObject, ['index']);\n if (fromIndex != null) {\n common.setValueByPath(toObject, ['index'], fromIndex);\n }\n\n const fromLogprobsResult = common.getValueByPath(fromObject, [\n 'logprobsResult',\n ]);\n if (fromLogprobsResult != null) {\n common.setValueByPath(toObject, ['logprobsResult'], fromLogprobsResult);\n }\n\n const fromSafetyRatings = common.getValueByPath(fromObject, [\n 'safetyRatings',\n ]);\n if (fromSafetyRatings != null) {\n let transformedList = fromSafetyRatings;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['safetyRatings'], transformedList);\n }\n\n const fromUrlContextMetadata = common.getValueByPath(fromObject, [\n 'urlContextMetadata',\n ]);\n if (fromUrlContextMetadata != null) {\n common.setValueByPath(\n toObject,\n ['urlContextMetadata'],\n fromUrlContextMetadata,\n );\n }\n\n return toObject;\n}\n\nexport function citationMetadataFromMldev(\n fromObject: types.CitationMetadata,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromCitations = common.getValueByPath(fromObject, ['citationSources']);\n if (fromCitations != null) {\n let transformedList = fromCitations;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['citations'], transformedList);\n }\n\n return toObject;\n}\n\nexport function computeTokensParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.ComputeTokensParameters,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromContents = common.getValueByPath(fromObject, ['contents']);\n if (fromContents != null) {\n let transformedList = t.tContents(fromContents);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['contents'], transformedList);\n }\n\n return toObject;\n}\n\nexport function computeTokensResponseFromVertex(\n fromObject: types.ComputeTokensResponse,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromTokensInfo = common.getValueByPath(fromObject, ['tokensInfo']);\n if (fromTokensInfo != null) {\n let transformedList = fromTokensInfo;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['tokensInfo'], transformedList);\n }\n\n return toObject;\n}\n\nexport function contentEmbeddingFromVertex(\n fromObject: types.ContentEmbedding,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromValues = common.getValueByPath(fromObject, ['values']);\n if (fromValues != null) {\n common.setValueByPath(toObject, ['values'], fromValues);\n }\n\n const fromStatistics = common.getValueByPath(fromObject, ['statistics']);\n if (fromStatistics != null) {\n common.setValueByPath(\n toObject,\n ['statistics'],\n contentEmbeddingStatisticsFromVertex(fromStatistics, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function contentEmbeddingStatisticsFromVertex(\n fromObject: types.ContentEmbeddingStatistics,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromTruncated = common.getValueByPath(fromObject, ['truncated']);\n if (fromTruncated != null) {\n common.setValueByPath(toObject, ['truncated'], fromTruncated);\n }\n\n const fromTokenCount = common.getValueByPath(fromObject, ['token_count']);\n if (fromTokenCount != null) {\n common.setValueByPath(toObject, ['tokenCount'], fromTokenCount);\n }\n\n return toObject;\n}\n\nexport function contentToMldev(\n fromObject: types.Content,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromParts = common.getValueByPath(fromObject, ['parts']);\n if (fromParts != null) {\n let transformedList = fromParts;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return partToMldev(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['parts'], transformedList);\n }\n\n const fromRole = common.getValueByPath(fromObject, ['role']);\n if (fromRole != null) {\n common.setValueByPath(toObject, ['role'], fromRole);\n }\n\n return toObject;\n}\n\nexport function controlReferenceConfigToVertex(\n fromObject: types.ControlReferenceConfig,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromControlType = common.getValueByPath(fromObject, ['controlType']);\n if (fromControlType != null) {\n common.setValueByPath(toObject, ['controlType'], fromControlType);\n }\n\n const fromEnableControlImageComputation = common.getValueByPath(fromObject, [\n 'enableControlImageComputation',\n ]);\n if (fromEnableControlImageComputation != null) {\n common.setValueByPath(\n toObject,\n ['computeControl'],\n fromEnableControlImageComputation,\n );\n }\n\n return toObject;\n}\n\nexport function countTokensConfigToMldev(\n fromObject: types.CountTokensConfig,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['systemInstruction']) !== undefined) {\n throw new Error(\n 'systemInstruction parameter is not supported in Gemini API.',\n );\n }\n\n if (common.getValueByPath(fromObject, ['tools']) !== undefined) {\n throw new Error('tools parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['generationConfig']) !== undefined) {\n throw new Error(\n 'generationConfig parameter is not supported in Gemini API.',\n );\n }\n\n return toObject;\n}\n\nexport function countTokensConfigToVertex(\n fromObject: types.CountTokensConfig,\n parentObject: Record<string, unknown>,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSystemInstruction = common.getValueByPath(fromObject, [\n 'systemInstruction',\n ]);\n if (parentObject !== undefined && fromSystemInstruction != null) {\n common.setValueByPath(\n parentObject,\n ['systemInstruction'],\n t.tContent(fromSystemInstruction),\n );\n }\n\n const fromTools = common.getValueByPath(fromObject, ['tools']);\n if (parentObject !== undefined && fromTools != null) {\n let transformedList = fromTools;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return toolToVertex(item, rootObject);\n });\n }\n common.setValueByPath(parentObject, ['tools'], transformedList);\n }\n\n const fromGenerationConfig = common.getValueByPath(fromObject, [\n 'generationConfig',\n ]);\n if (parentObject !== undefined && fromGenerationConfig != null) {\n common.setValueByPath(\n parentObject,\n ['generationConfig'],\n generationConfigToVertex(fromGenerationConfig, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function countTokensParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.CountTokensParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromContents = common.getValueByPath(fromObject, ['contents']);\n if (fromContents != null) {\n let transformedList = t.tContents(fromContents);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return contentToMldev(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['contents'], transformedList);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n countTokensConfigToMldev(fromConfig, rootObject);\n }\n\n return toObject;\n}\n\nexport function countTokensParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.CountTokensParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromContents = common.getValueByPath(fromObject, ['contents']);\n if (fromContents != null) {\n let transformedList = t.tContents(fromContents);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['contents'], transformedList);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n countTokensConfigToVertex(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function countTokensResponseFromMldev(\n fromObject: types.CountTokensResponse,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromTotalTokens = common.getValueByPath(fromObject, ['totalTokens']);\n if (fromTotalTokens != null) {\n common.setValueByPath(toObject, ['totalTokens'], fromTotalTokens);\n }\n\n const fromCachedContentTokenCount = common.getValueByPath(fromObject, [\n 'cachedContentTokenCount',\n ]);\n if (fromCachedContentTokenCount != null) {\n common.setValueByPath(\n toObject,\n ['cachedContentTokenCount'],\n fromCachedContentTokenCount,\n );\n }\n\n return toObject;\n}\n\nexport function countTokensResponseFromVertex(\n fromObject: types.CountTokensResponse,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromTotalTokens = common.getValueByPath(fromObject, ['totalTokens']);\n if (fromTotalTokens != null) {\n common.setValueByPath(toObject, ['totalTokens'], fromTotalTokens);\n }\n\n return toObject;\n}\n\nexport function deleteModelParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.DeleteModelParameters,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n return toObject;\n}\n\nexport function deleteModelParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.DeleteModelParameters,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n return toObject;\n}\n\nexport function deleteModelResponseFromMldev(\n fromObject: types.DeleteModelResponse,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n return toObject;\n}\n\nexport function deleteModelResponseFromVertex(\n fromObject: types.DeleteModelResponse,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n return toObject;\n}\n\nexport function editImageConfigToVertex(\n fromObject: types.EditImageConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromOutputGcsUri = common.getValueByPath(fromObject, ['outputGcsUri']);\n if (parentObject !== undefined && fromOutputGcsUri != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'storageUri'],\n fromOutputGcsUri,\n );\n }\n\n const fromNegativePrompt = common.getValueByPath(fromObject, [\n 'negativePrompt',\n ]);\n if (parentObject !== undefined && fromNegativePrompt != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'negativePrompt'],\n fromNegativePrompt,\n );\n }\n\n const fromNumberOfImages = common.getValueByPath(fromObject, [\n 'numberOfImages',\n ]);\n if (parentObject !== undefined && fromNumberOfImages != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'sampleCount'],\n fromNumberOfImages,\n );\n }\n\n const fromAspectRatio = common.getValueByPath(fromObject, ['aspectRatio']);\n if (parentObject !== undefined && fromAspectRatio != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'aspectRatio'],\n fromAspectRatio,\n );\n }\n\n const fromGuidanceScale = common.getValueByPath(fromObject, [\n 'guidanceScale',\n ]);\n if (parentObject !== undefined && fromGuidanceScale != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'guidanceScale'],\n fromGuidanceScale,\n );\n }\n\n const fromSeed = common.getValueByPath(fromObject, ['seed']);\n if (parentObject !== undefined && fromSeed != null) {\n common.setValueByPath(parentObject, ['parameters', 'seed'], fromSeed);\n }\n\n const fromSafetyFilterLevel = common.getValueByPath(fromObject, [\n 'safetyFilterLevel',\n ]);\n if (parentObject !== undefined && fromSafetyFilterLevel != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'safetySetting'],\n fromSafetyFilterLevel,\n );\n }\n\n const fromPersonGeneration = common.getValueByPath(fromObject, [\n 'personGeneration',\n ]);\n if (parentObject !== undefined && fromPersonGeneration != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'personGeneration'],\n fromPersonGeneration,\n );\n }\n\n const fromIncludeSafetyAttributes = common.getValueByPath(fromObject, [\n 'includeSafetyAttributes',\n ]);\n if (parentObject !== undefined && fromIncludeSafetyAttributes != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'includeSafetyAttributes'],\n fromIncludeSafetyAttributes,\n );\n }\n\n const fromIncludeRaiReason = common.getValueByPath(fromObject, [\n 'includeRaiReason',\n ]);\n if (parentObject !== undefined && fromIncludeRaiReason != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'includeRaiReason'],\n fromIncludeRaiReason,\n );\n }\n\n const fromLanguage = common.getValueByPath(fromObject, ['language']);\n if (parentObject !== undefined && fromLanguage != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'language'],\n fromLanguage,\n );\n }\n\n const fromOutputMimeType = common.getValueByPath(fromObject, [\n 'outputMimeType',\n ]);\n if (parentObject !== undefined && fromOutputMimeType != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'outputOptions', 'mimeType'],\n fromOutputMimeType,\n );\n }\n\n const fromOutputCompressionQuality = common.getValueByPath(fromObject, [\n 'outputCompressionQuality',\n ]);\n if (parentObject !== undefined && fromOutputCompressionQuality != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'outputOptions', 'compressionQuality'],\n fromOutputCompressionQuality,\n );\n }\n\n const fromAddWatermark = common.getValueByPath(fromObject, ['addWatermark']);\n if (parentObject !== undefined && fromAddWatermark != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'addWatermark'],\n fromAddWatermark,\n );\n }\n\n const fromLabels = common.getValueByPath(fromObject, ['labels']);\n if (parentObject !== undefined && fromLabels != null) {\n common.setValueByPath(parentObject, ['labels'], fromLabels);\n }\n\n const fromEditMode = common.getValueByPath(fromObject, ['editMode']);\n if (parentObject !== undefined && fromEditMode != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'editMode'],\n fromEditMode,\n );\n }\n\n const fromBaseSteps = common.getValueByPath(fromObject, ['baseSteps']);\n if (parentObject !== undefined && fromBaseSteps != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'editConfig', 'baseSteps'],\n fromBaseSteps,\n );\n }\n\n return toObject;\n}\n\nexport function editImageParametersInternalToVertex(\n apiClient: ApiClient,\n fromObject: _internal_types.EditImageParametersInternal,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromPrompt = common.getValueByPath(fromObject, ['prompt']);\n if (fromPrompt != null) {\n common.setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt);\n }\n\n const fromReferenceImages = common.getValueByPath(fromObject, [\n 'referenceImages',\n ]);\n if (fromReferenceImages != null) {\n let transformedList = fromReferenceImages;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return referenceImageAPIInternalToVertex(item, rootObject);\n });\n }\n common.setValueByPath(\n toObject,\n ['instances[0]', 'referenceImages'],\n transformedList,\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n editImageConfigToVertex(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function editImageResponseFromVertex(\n fromObject: types.EditImageResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromGeneratedImages = common.getValueByPath(fromObject, [\n 'predictions',\n ]);\n if (fromGeneratedImages != null) {\n let transformedList = fromGeneratedImages;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return generatedImageFromVertex(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['generatedImages'], transformedList);\n }\n\n return toObject;\n}\n\nexport function embedContentConfigToMldev(\n fromObject: types.EmbedContentConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromTaskType = common.getValueByPath(fromObject, ['taskType']);\n if (parentObject !== undefined && fromTaskType != null) {\n common.setValueByPath(\n parentObject,\n ['requests[]', 'taskType'],\n fromTaskType,\n );\n }\n\n const fromTitle = common.getValueByPath(fromObject, ['title']);\n if (parentObject !== undefined && fromTitle != null) {\n common.setValueByPath(parentObject, ['requests[]', 'title'], fromTitle);\n }\n\n const fromOutputDimensionality = common.getValueByPath(fromObject, [\n 'outputDimensionality',\n ]);\n if (parentObject !== undefined && fromOutputDimensionality != null) {\n common.setValueByPath(\n parentObject,\n ['requests[]', 'outputDimensionality'],\n fromOutputDimensionality,\n );\n }\n\n if (common.getValueByPath(fromObject, ['mimeType']) !== undefined) {\n throw new Error('mimeType parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['autoTruncate']) !== undefined) {\n throw new Error('autoTruncate parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function embedContentConfigToVertex(\n fromObject: types.EmbedContentConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromTaskType = common.getValueByPath(fromObject, ['taskType']);\n if (parentObject !== undefined && fromTaskType != null) {\n common.setValueByPath(\n parentObject,\n ['instances[]', 'task_type'],\n fromTaskType,\n );\n }\n\n const fromTitle = common.getValueByPath(fromObject, ['title']);\n if (parentObject !== undefined && fromTitle != null) {\n common.setValueByPath(parentObject, ['instances[]', 'title'], fromTitle);\n }\n\n const fromOutputDimensionality = common.getValueByPath(fromObject, [\n 'outputDimensionality',\n ]);\n if (parentObject !== undefined && fromOutputDimensionality != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'outputDimensionality'],\n fromOutputDimensionality,\n );\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (parentObject !== undefined && fromMimeType != null) {\n common.setValueByPath(\n parentObject,\n ['instances[]', 'mimeType'],\n fromMimeType,\n );\n }\n\n const fromAutoTruncate = common.getValueByPath(fromObject, ['autoTruncate']);\n if (parentObject !== undefined && fromAutoTruncate != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'autoTruncate'],\n fromAutoTruncate,\n );\n }\n\n return toObject;\n}\n\nexport function embedContentParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.EmbedContentParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromContents = common.getValueByPath(fromObject, ['contents']);\n if (fromContents != null) {\n let transformedList = t.tContentsForEmbed(apiClient, fromContents);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['requests[]', 'content'], transformedList);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n embedContentConfigToMldev(fromConfig, toObject, rootObject);\n }\n\n const fromModelForEmbedContent = common.getValueByPath(fromObject, ['model']);\n if (fromModelForEmbedContent !== undefined) {\n common.setValueByPath(\n toObject,\n ['requests[]', 'model'],\n t.tModel(apiClient, fromModelForEmbedContent),\n );\n }\n\n return toObject;\n}\n\nexport function embedContentParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.EmbedContentParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromContents = common.getValueByPath(fromObject, ['contents']);\n if (fromContents != null) {\n let transformedList = t.tContentsForEmbed(apiClient, fromContents);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(\n toObject,\n ['instances[]', 'content'],\n transformedList,\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n embedContentConfigToVertex(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function embedContentResponseFromMldev(\n fromObject: types.EmbedContentResponse,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromEmbeddings = common.getValueByPath(fromObject, ['embeddings']);\n if (fromEmbeddings != null) {\n let transformedList = fromEmbeddings;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['embeddings'], transformedList);\n }\n\n const fromMetadata = common.getValueByPath(fromObject, ['metadata']);\n if (fromMetadata != null) {\n common.setValueByPath(toObject, ['metadata'], fromMetadata);\n }\n\n return toObject;\n}\n\nexport function embedContentResponseFromVertex(\n fromObject: types.EmbedContentResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromEmbeddings = common.getValueByPath(fromObject, [\n 'predictions[]',\n 'embeddings',\n ]);\n if (fromEmbeddings != null) {\n let transformedList = fromEmbeddings;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return contentEmbeddingFromVertex(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['embeddings'], transformedList);\n }\n\n const fromMetadata = common.getValueByPath(fromObject, ['metadata']);\n if (fromMetadata != null) {\n common.setValueByPath(toObject, ['metadata'], fromMetadata);\n }\n\n return toObject;\n}\n\nexport function endpointFromVertex(\n fromObject: types.Endpoint,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['endpoint']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromDeployedModelId = common.getValueByPath(fromObject, [\n 'deployedModelId',\n ]);\n if (fromDeployedModelId != null) {\n common.setValueByPath(toObject, ['deployedModelId'], fromDeployedModelId);\n }\n\n return toObject;\n}\n\nexport function fileDataToMldev(\n fromObject: types.FileData,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['displayName']) !== undefined) {\n throw new Error('displayName parameter is not supported in Gemini API.');\n }\n\n const fromFileUri = common.getValueByPath(fromObject, ['fileUri']);\n if (fromFileUri != null) {\n common.setValueByPath(toObject, ['fileUri'], fromFileUri);\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function functionCallToMldev(\n fromObject: types.FunctionCall,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromId = common.getValueByPath(fromObject, ['id']);\n if (fromId != null) {\n common.setValueByPath(toObject, ['id'], fromId);\n }\n\n const fromArgs = common.getValueByPath(fromObject, ['args']);\n if (fromArgs != null) {\n common.setValueByPath(toObject, ['args'], fromArgs);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n if (common.getValueByPath(fromObject, ['partialArgs']) !== undefined) {\n throw new Error('partialArgs parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['willContinue']) !== undefined) {\n throw new Error('willContinue parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function functionCallingConfigToMldev(\n fromObject: types.FunctionCallingConfig,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromAllowedFunctionNames = common.getValueByPath(fromObject, [\n 'allowedFunctionNames',\n ]);\n if (fromAllowedFunctionNames != null) {\n common.setValueByPath(\n toObject,\n ['allowedFunctionNames'],\n fromAllowedFunctionNames,\n );\n }\n\n const fromMode = common.getValueByPath(fromObject, ['mode']);\n if (fromMode != null) {\n common.setValueByPath(toObject, ['mode'], fromMode);\n }\n\n if (\n common.getValueByPath(fromObject, ['streamFunctionCallArguments']) !==\n undefined\n ) {\n throw new Error(\n 'streamFunctionCallArguments parameter is not supported in Gemini API.',\n );\n }\n\n return toObject;\n}\n\nexport function functionDeclarationToVertex(\n fromObject: types.FunctionDeclaration,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromDescription = common.getValueByPath(fromObject, ['description']);\n if (fromDescription != null) {\n common.setValueByPath(toObject, ['description'], fromDescription);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromParameters = common.getValueByPath(fromObject, ['parameters']);\n if (fromParameters != null) {\n common.setValueByPath(toObject, ['parameters'], fromParameters);\n }\n\n const fromParametersJsonSchema = common.getValueByPath(fromObject, [\n 'parametersJsonSchema',\n ]);\n if (fromParametersJsonSchema != null) {\n common.setValueByPath(\n toObject,\n ['parametersJsonSchema'],\n fromParametersJsonSchema,\n );\n }\n\n const fromResponse = common.getValueByPath(fromObject, ['response']);\n if (fromResponse != null) {\n common.setValueByPath(toObject, ['response'], fromResponse);\n }\n\n const fromResponseJsonSchema = common.getValueByPath(fromObject, [\n 'responseJsonSchema',\n ]);\n if (fromResponseJsonSchema != null) {\n common.setValueByPath(\n toObject,\n ['responseJsonSchema'],\n fromResponseJsonSchema,\n );\n }\n\n if (common.getValueByPath(fromObject, ['behavior']) !== undefined) {\n throw new Error('behavior parameter is not supported in Vertex AI.');\n }\n\n return toObject;\n}\n\nexport function generateContentConfigToMldev(\n apiClient: ApiClient,\n fromObject: types.GenerateContentConfig,\n parentObject: Record<string, unknown>,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSystemInstruction = common.getValueByPath(fromObject, [\n 'systemInstruction',\n ]);\n if (parentObject !== undefined && fromSystemInstruction != null) {\n common.setValueByPath(\n parentObject,\n ['systemInstruction'],\n contentToMldev(t.tContent(fromSystemInstruction), rootObject),\n );\n }\n\n const fromTemperature = common.getValueByPath(fromObject, ['temperature']);\n if (fromTemperature != null) {\n common.setValueByPath(toObject, ['temperature'], fromTemperature);\n }\n\n const fromTopP = common.getValueByPath(fromObject, ['topP']);\n if (fromTopP != null) {\n common.setValueByPath(toObject, ['topP'], fromTopP);\n }\n\n const fromTopK = common.getValueByPath(fromObject, ['topK']);\n if (fromTopK != null) {\n common.setValueByPath(toObject, ['topK'], fromTopK);\n }\n\n const fromCandidateCount = common.getValueByPath(fromObject, [\n 'candidateCount',\n ]);\n if (fromCandidateCount != null) {\n common.setValueByPath(toObject, ['candidateCount'], fromCandidateCount);\n }\n\n const fromMaxOutputTokens = common.getValueByPath(fromObject, [\n 'maxOutputTokens',\n ]);\n if (fromMaxOutputTokens != null) {\n common.setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens);\n }\n\n const fromStopSequences = common.getValueByPath(fromObject, [\n 'stopSequences',\n ]);\n if (fromStopSequences != null) {\n common.setValueByPath(toObject, ['stopSequences'], fromStopSequences);\n }\n\n const fromResponseLogprobs = common.getValueByPath(fromObject, [\n 'responseLogprobs',\n ]);\n if (fromResponseLogprobs != null) {\n common.setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs);\n }\n\n const fromLogprobs = common.getValueByPath(fromObject, ['logprobs']);\n if (fromLogprobs != null) {\n common.setValueByPath(toObject, ['logprobs'], fromLogprobs);\n }\n\n const fromPresencePenalty = common.getValueByPath(fromObject, [\n 'presencePenalty',\n ]);\n if (fromPresencePenalty != null) {\n common.setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty);\n }\n\n const fromFrequencyPenalty = common.getValueByPath(fromObject, [\n 'frequencyPenalty',\n ]);\n if (fromFrequencyPenalty != null) {\n common.setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty);\n }\n\n const fromSeed = common.getValueByPath(fromObject, ['seed']);\n if (fromSeed != null) {\n common.setValueByPath(toObject, ['seed'], fromSeed);\n }\n\n const fromResponseMimeType = common.getValueByPath(fromObject, [\n 'responseMimeType',\n ]);\n if (fromResponseMimeType != null) {\n common.setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType);\n }\n\n const fromResponseSchema = common.getValueByPath(fromObject, [\n 'responseSchema',\n ]);\n if (fromResponseSchema != null) {\n common.setValueByPath(\n toObject,\n ['responseSchema'],\n t.tSchema(fromResponseSchema),\n );\n }\n\n const fromResponseJsonSchema = common.getValueByPath(fromObject, [\n 'responseJsonSchema',\n ]);\n if (fromResponseJsonSchema != null) {\n common.setValueByPath(\n toObject,\n ['responseJsonSchema'],\n fromResponseJsonSchema,\n );\n }\n\n if (common.getValueByPath(fromObject, ['routingConfig']) !== undefined) {\n throw new Error('routingConfig parameter is not supported in Gemini API.');\n }\n\n if (\n common.getValueByPath(fromObject, ['modelSelectionConfig']) !== undefined\n ) {\n throw new Error(\n 'modelSelectionConfig parameter is not supported in Gemini API.',\n );\n }\n\n const fromSafetySettings = common.getValueByPath(fromObject, [\n 'safetySettings',\n ]);\n if (parentObject !== undefined && fromSafetySettings != null) {\n let transformedList = fromSafetySettings;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return safetySettingToMldev(item, rootObject);\n });\n }\n common.setValueByPath(parentObject, ['safetySettings'], transformedList);\n }\n\n const fromTools = common.getValueByPath(fromObject, ['tools']);\n if (parentObject !== undefined && fromTools != null) {\n let transformedList = t.tTools(fromTools);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return toolToMldev(t.tTool(item), rootObject);\n });\n }\n common.setValueByPath(parentObject, ['tools'], transformedList);\n }\n\n const fromToolConfig = common.getValueByPath(fromObject, ['toolConfig']);\n if (parentObject !== undefined && fromToolConfig != null) {\n common.setValueByPath(\n parentObject,\n ['toolConfig'],\n toolConfigToMldev(fromToolConfig, rootObject),\n );\n }\n\n if (common.getValueByPath(fromObject, ['labels']) !== undefined) {\n throw new Error('labels parameter is not supported in Gemini API.');\n }\n\n const fromCachedContent = common.getValueByPath(fromObject, [\n 'cachedContent',\n ]);\n if (parentObject !== undefined && fromCachedContent != null) {\n common.setValueByPath(\n parentObject,\n ['cachedContent'],\n t.tCachedContentName(apiClient, fromCachedContent),\n );\n }\n\n const fromResponseModalities = common.getValueByPath(fromObject, [\n 'responseModalities',\n ]);\n if (fromResponseModalities != null) {\n common.setValueByPath(\n toObject,\n ['responseModalities'],\n fromResponseModalities,\n );\n }\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (fromMediaResolution != null) {\n common.setValueByPath(toObject, ['mediaResolution'], fromMediaResolution);\n }\n\n const fromSpeechConfig = common.getValueByPath(fromObject, ['speechConfig']);\n if (fromSpeechConfig != null) {\n common.setValueByPath(\n toObject,\n ['speechConfig'],\n t.tSpeechConfig(fromSpeechConfig),\n );\n }\n\n if (common.getValueByPath(fromObject, ['audioTimestamp']) !== undefined) {\n throw new Error('audioTimestamp parameter is not supported in Gemini API.');\n }\n\n const fromThinkingConfig = common.getValueByPath(fromObject, [\n 'thinkingConfig',\n ]);\n if (fromThinkingConfig != null) {\n common.setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig);\n }\n\n const fromImageConfig = common.getValueByPath(fromObject, ['imageConfig']);\n if (fromImageConfig != null) {\n common.setValueByPath(\n toObject,\n ['imageConfig'],\n imageConfigToMldev(fromImageConfig, rootObject),\n );\n }\n\n const fromEnableEnhancedCivicAnswers = common.getValueByPath(fromObject, [\n 'enableEnhancedCivicAnswers',\n ]);\n if (fromEnableEnhancedCivicAnswers != null) {\n common.setValueByPath(\n toObject,\n ['enableEnhancedCivicAnswers'],\n fromEnableEnhancedCivicAnswers,\n );\n }\n\n if (common.getValueByPath(fromObject, ['modelArmorConfig']) !== undefined) {\n throw new Error(\n 'modelArmorConfig parameter is not supported in Gemini API.',\n );\n }\n\n return toObject;\n}\n\nexport function generateContentConfigToVertex(\n apiClient: ApiClient,\n fromObject: types.GenerateContentConfig,\n parentObject: Record<string, unknown>,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSystemInstruction = common.getValueByPath(fromObject, [\n 'systemInstruction',\n ]);\n if (parentObject !== undefined && fromSystemInstruction != null) {\n common.setValueByPath(\n parentObject,\n ['systemInstruction'],\n t.tContent(fromSystemInstruction),\n );\n }\n\n const fromTemperature = common.getValueByPath(fromObject, ['temperature']);\n if (fromTemperature != null) {\n common.setValueByPath(toObject, ['temperature'], fromTemperature);\n }\n\n const fromTopP = common.getValueByPath(fromObject, ['topP']);\n if (fromTopP != null) {\n common.setValueByPath(toObject, ['topP'], fromTopP);\n }\n\n const fromTopK = common.getValueByPath(fromObject, ['topK']);\n if (fromTopK != null) {\n common.setValueByPath(toObject, ['topK'], fromTopK);\n }\n\n const fromCandidateCount = common.getValueByPath(fromObject, [\n 'candidateCount',\n ]);\n if (fromCandidateCount != null) {\n common.setValueByPath(toObject, ['candidateCount'], fromCandidateCount);\n }\n\n const fromMaxOutputTokens = common.getValueByPath(fromObject, [\n 'maxOutputTokens',\n ]);\n if (fromMaxOutputTokens != null) {\n common.setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens);\n }\n\n const fromStopSequences = common.getValueByPath(fromObject, [\n 'stopSequences',\n ]);\n if (fromStopSequences != null) {\n common.setValueByPath(toObject, ['stopSequences'], fromStopSequences);\n }\n\n const fromResponseLogprobs = common.getValueByPath(fromObject, [\n 'responseLogprobs',\n ]);\n if (fromResponseLogprobs != null) {\n common.setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs);\n }\n\n const fromLogprobs = common.getValueByPath(fromObject, ['logprobs']);\n if (fromLogprobs != null) {\n common.setValueByPath(toObject, ['logprobs'], fromLogprobs);\n }\n\n const fromPresencePenalty = common.getValueByPath(fromObject, [\n 'presencePenalty',\n ]);\n if (fromPresencePenalty != null) {\n common.setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty);\n }\n\n const fromFrequencyPenalty = common.getValueByPath(fromObject, [\n 'frequencyPenalty',\n ]);\n if (fromFrequencyPenalty != null) {\n common.setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty);\n }\n\n const fromSeed = common.getValueByPath(fromObject, ['seed']);\n if (fromSeed != null) {\n common.setValueByPath(toObject, ['seed'], fromSeed);\n }\n\n const fromResponseMimeType = common.getValueByPath(fromObject, [\n 'responseMimeType',\n ]);\n if (fromResponseMimeType != null) {\n common.setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType);\n }\n\n const fromResponseSchema = common.getValueByPath(fromObject, [\n 'responseSchema',\n ]);\n if (fromResponseSchema != null) {\n common.setValueByPath(\n toObject,\n ['responseSchema'],\n t.tSchema(fromResponseSchema),\n );\n }\n\n const fromResponseJsonSchema = common.getValueByPath(fromObject, [\n 'responseJsonSchema',\n ]);\n if (fromResponseJsonSchema != null) {\n common.setValueByPath(\n toObject,\n ['responseJsonSchema'],\n fromResponseJsonSchema,\n );\n }\n\n const fromRoutingConfig = common.getValueByPath(fromObject, [\n 'routingConfig',\n ]);\n if (fromRoutingConfig != null) {\n common.setValueByPath(toObject, ['routingConfig'], fromRoutingConfig);\n }\n\n const fromModelSelectionConfig = common.getValueByPath(fromObject, [\n 'modelSelectionConfig',\n ]);\n if (fromModelSelectionConfig != null) {\n common.setValueByPath(toObject, ['modelConfig'], fromModelSelectionConfig);\n }\n\n const fromSafetySettings = common.getValueByPath(fromObject, [\n 'safetySettings',\n ]);\n if (parentObject !== undefined && fromSafetySettings != null) {\n let transformedList = fromSafetySettings;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(parentObject, ['safetySettings'], transformedList);\n }\n\n const fromTools = common.getValueByPath(fromObject, ['tools']);\n if (parentObject !== undefined && fromTools != null) {\n let transformedList = t.tTools(fromTools);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return toolToVertex(t.tTool(item), rootObject);\n });\n }\n common.setValueByPath(parentObject, ['tools'], transformedList);\n }\n\n const fromToolConfig = common.getValueByPath(fromObject, ['toolConfig']);\n if (parentObject !== undefined && fromToolConfig != null) {\n common.setValueByPath(parentObject, ['toolConfig'], fromToolConfig);\n }\n\n const fromLabels = common.getValueByPath(fromObject, ['labels']);\n if (parentObject !== undefined && fromLabels != null) {\n common.setValueByPath(parentObject, ['labels'], fromLabels);\n }\n\n const fromCachedContent = common.getValueByPath(fromObject, [\n 'cachedContent',\n ]);\n if (parentObject !== undefined && fromCachedContent != null) {\n common.setValueByPath(\n parentObject,\n ['cachedContent'],\n t.tCachedContentName(apiClient, fromCachedContent),\n );\n }\n\n const fromResponseModalities = common.getValueByPath(fromObject, [\n 'responseModalities',\n ]);\n if (fromResponseModalities != null) {\n common.setValueByPath(\n toObject,\n ['responseModalities'],\n fromResponseModalities,\n );\n }\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (fromMediaResolution != null) {\n common.setValueByPath(toObject, ['mediaResolution'], fromMediaResolution);\n }\n\n const fromSpeechConfig = common.getValueByPath(fromObject, ['speechConfig']);\n if (fromSpeechConfig != null) {\n common.setValueByPath(\n toObject,\n ['speechConfig'],\n t.tSpeechConfig(fromSpeechConfig),\n );\n }\n\n const fromAudioTimestamp = common.getValueByPath(fromObject, [\n 'audioTimestamp',\n ]);\n if (fromAudioTimestamp != null) {\n common.setValueByPath(toObject, ['audioTimestamp'], fromAudioTimestamp);\n }\n\n const fromThinkingConfig = common.getValueByPath(fromObject, [\n 'thinkingConfig',\n ]);\n if (fromThinkingConfig != null) {\n common.setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig);\n }\n\n const fromImageConfig = common.getValueByPath(fromObject, ['imageConfig']);\n if (fromImageConfig != null) {\n common.setValueByPath(\n toObject,\n ['imageConfig'],\n imageConfigToVertex(fromImageConfig, rootObject),\n );\n }\n\n if (\n common.getValueByPath(fromObject, ['enableEnhancedCivicAnswers']) !==\n undefined\n ) {\n throw new Error(\n 'enableEnhancedCivicAnswers parameter is not supported in Vertex AI.',\n );\n }\n\n const fromModelArmorConfig = common.getValueByPath(fromObject, [\n 'modelArmorConfig',\n ]);\n if (parentObject !== undefined && fromModelArmorConfig != null) {\n common.setValueByPath(\n parentObject,\n ['modelArmorConfig'],\n fromModelArmorConfig,\n );\n }\n\n return toObject;\n}\n\nexport function generateContentParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.GenerateContentParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromContents = common.getValueByPath(fromObject, ['contents']);\n if (fromContents != null) {\n let transformedList = t.tContents(fromContents);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return contentToMldev(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['contents'], transformedList);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n common.setValueByPath(\n toObject,\n ['generationConfig'],\n generateContentConfigToMldev(apiClient, fromConfig, toObject, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function generateContentParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.GenerateContentParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromContents = common.getValueByPath(fromObject, ['contents']);\n if (fromContents != null) {\n let transformedList = t.tContents(fromContents);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['contents'], transformedList);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n common.setValueByPath(\n toObject,\n ['generationConfig'],\n generateContentConfigToVertex(\n apiClient,\n fromConfig,\n toObject,\n rootObject,\n ),\n );\n }\n\n return toObject;\n}\n\nexport function generateContentResponseFromMldev(\n fromObject: types.GenerateContentResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromCandidates = common.getValueByPath(fromObject, ['candidates']);\n if (fromCandidates != null) {\n let transformedList = fromCandidates;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return candidateFromMldev(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['candidates'], transformedList);\n }\n\n const fromModelVersion = common.getValueByPath(fromObject, ['modelVersion']);\n if (fromModelVersion != null) {\n common.setValueByPath(toObject, ['modelVersion'], fromModelVersion);\n }\n\n const fromPromptFeedback = common.getValueByPath(fromObject, [\n 'promptFeedback',\n ]);\n if (fromPromptFeedback != null) {\n common.setValueByPath(toObject, ['promptFeedback'], fromPromptFeedback);\n }\n\n const fromResponseId = common.getValueByPath(fromObject, ['responseId']);\n if (fromResponseId != null) {\n common.setValueByPath(toObject, ['responseId'], fromResponseId);\n }\n\n const fromUsageMetadata = common.getValueByPath(fromObject, [\n 'usageMetadata',\n ]);\n if (fromUsageMetadata != null) {\n common.setValueByPath(toObject, ['usageMetadata'], fromUsageMetadata);\n }\n\n return toObject;\n}\n\nexport function generateContentResponseFromVertex(\n fromObject: types.GenerateContentResponse,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromCandidates = common.getValueByPath(fromObject, ['candidates']);\n if (fromCandidates != null) {\n let transformedList = fromCandidates;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['candidates'], transformedList);\n }\n\n const fromCreateTime = common.getValueByPath(fromObject, ['createTime']);\n if (fromCreateTime != null) {\n common.setValueByPath(toObject, ['createTime'], fromCreateTime);\n }\n\n const fromModelVersion = common.getValueByPath(fromObject, ['modelVersion']);\n if (fromModelVersion != null) {\n common.setValueByPath(toObject, ['modelVersion'], fromModelVersion);\n }\n\n const fromPromptFeedback = common.getValueByPath(fromObject, [\n 'promptFeedback',\n ]);\n if (fromPromptFeedback != null) {\n common.setValueByPath(toObject, ['promptFeedback'], fromPromptFeedback);\n }\n\n const fromResponseId = common.getValueByPath(fromObject, ['responseId']);\n if (fromResponseId != null) {\n common.setValueByPath(toObject, ['responseId'], fromResponseId);\n }\n\n const fromUsageMetadata = common.getValueByPath(fromObject, [\n 'usageMetadata',\n ]);\n if (fromUsageMetadata != null) {\n common.setValueByPath(toObject, ['usageMetadata'], fromUsageMetadata);\n }\n\n return toObject;\n}\n\nexport function generateImagesConfigToMldev(\n fromObject: types.GenerateImagesConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['outputGcsUri']) !== undefined) {\n throw new Error('outputGcsUri parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['negativePrompt']) !== undefined) {\n throw new Error('negativePrompt parameter is not supported in Gemini API.');\n }\n\n const fromNumberOfImages = common.getValueByPath(fromObject, [\n 'numberOfImages',\n ]);\n if (parentObject !== undefined && fromNumberOfImages != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'sampleCount'],\n fromNumberOfImages,\n );\n }\n\n const fromAspectRatio = common.getValueByPath(fromObject, ['aspectRatio']);\n if (parentObject !== undefined && fromAspectRatio != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'aspectRatio'],\n fromAspectRatio,\n );\n }\n\n const fromGuidanceScale = common.getValueByPath(fromObject, [\n 'guidanceScale',\n ]);\n if (parentObject !== undefined && fromGuidanceScale != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'guidanceScale'],\n fromGuidanceScale,\n );\n }\n\n if (common.getValueByPath(fromObject, ['seed']) !== undefined) {\n throw new Error('seed parameter is not supported in Gemini API.');\n }\n\n const fromSafetyFilterLevel = common.getValueByPath(fromObject, [\n 'safetyFilterLevel',\n ]);\n if (parentObject !== undefined && fromSafetyFilterLevel != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'safetySetting'],\n fromSafetyFilterLevel,\n );\n }\n\n const fromPersonGeneration = common.getValueByPath(fromObject, [\n 'personGeneration',\n ]);\n if (parentObject !== undefined && fromPersonGeneration != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'personGeneration'],\n fromPersonGeneration,\n );\n }\n\n const fromIncludeSafetyAttributes = common.getValueByPath(fromObject, [\n 'includeSafetyAttributes',\n ]);\n if (parentObject !== undefined && fromIncludeSafetyAttributes != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'includeSafetyAttributes'],\n fromIncludeSafetyAttributes,\n );\n }\n\n const fromIncludeRaiReason = common.getValueByPath(fromObject, [\n 'includeRaiReason',\n ]);\n if (parentObject !== undefined && fromIncludeRaiReason != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'includeRaiReason'],\n fromIncludeRaiReason,\n );\n }\n\n const fromLanguage = common.getValueByPath(fromObject, ['language']);\n if (parentObject !== undefined && fromLanguage != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'language'],\n fromLanguage,\n );\n }\n\n const fromOutputMimeType = common.getValueByPath(fromObject, [\n 'outputMimeType',\n ]);\n if (parentObject !== undefined && fromOutputMimeType != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'outputOptions', 'mimeType'],\n fromOutputMimeType,\n );\n }\n\n const fromOutputCompressionQuality = common.getValueByPath(fromObject, [\n 'outputCompressionQuality',\n ]);\n if (parentObject !== undefined && fromOutputCompressionQuality != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'outputOptions', 'compressionQuality'],\n fromOutputCompressionQuality,\n );\n }\n\n if (common.getValueByPath(fromObject, ['addWatermark']) !== undefined) {\n throw new Error('addWatermark parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['labels']) !== undefined) {\n throw new Error('labels parameter is not supported in Gemini API.');\n }\n\n const fromImageSize = common.getValueByPath(fromObject, ['imageSize']);\n if (parentObject !== undefined && fromImageSize != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'sampleImageSize'],\n fromImageSize,\n );\n }\n\n if (common.getValueByPath(fromObject, ['enhancePrompt']) !== undefined) {\n throw new Error('enhancePrompt parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function generateImagesConfigToVertex(\n fromObject: types.GenerateImagesConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromOutputGcsUri = common.getValueByPath(fromObject, ['outputGcsUri']);\n if (parentObject !== undefined && fromOutputGcsUri != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'storageUri'],\n fromOutputGcsUri,\n );\n }\n\n const fromNegativePrompt = common.getValueByPath(fromObject, [\n 'negativePrompt',\n ]);\n if (parentObject !== undefined && fromNegativePrompt != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'negativePrompt'],\n fromNegativePrompt,\n );\n }\n\n const fromNumberOfImages = common.getValueByPath(fromObject, [\n 'numberOfImages',\n ]);\n if (parentObject !== undefined && fromNumberOfImages != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'sampleCount'],\n fromNumberOfImages,\n );\n }\n\n const fromAspectRatio = common.getValueByPath(fromObject, ['aspectRatio']);\n if (parentObject !== undefined && fromAspectRatio != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'aspectRatio'],\n fromAspectRatio,\n );\n }\n\n const fromGuidanceScale = common.getValueByPath(fromObject, [\n 'guidanceScale',\n ]);\n if (parentObject !== undefined && fromGuidanceScale != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'guidanceScale'],\n fromGuidanceScale,\n );\n }\n\n const fromSeed = common.getValueByPath(fromObject, ['seed']);\n if (parentObject !== undefined && fromSeed != null) {\n common.setValueByPath(parentObject, ['parameters', 'seed'], fromSeed);\n }\n\n const fromSafetyFilterLevel = common.getValueByPath(fromObject, [\n 'safetyFilterLevel',\n ]);\n if (parentObject !== undefined && fromSafetyFilterLevel != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'safetySetting'],\n fromSafetyFilterLevel,\n );\n }\n\n const fromPersonGeneration = common.getValueByPath(fromObject, [\n 'personGeneration',\n ]);\n if (parentObject !== undefined && fromPersonGeneration != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'personGeneration'],\n fromPersonGeneration,\n );\n }\n\n const fromIncludeSafetyAttributes = common.getValueByPath(fromObject, [\n 'includeSafetyAttributes',\n ]);\n if (parentObject !== undefined && fromIncludeSafetyAttributes != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'includeSafetyAttributes'],\n fromIncludeSafetyAttributes,\n );\n }\n\n const fromIncludeRaiReason = common.getValueByPath(fromObject, [\n 'includeRaiReason',\n ]);\n if (parentObject !== undefined && fromIncludeRaiReason != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'includeRaiReason'],\n fromIncludeRaiReason,\n );\n }\n\n const fromLanguage = common.getValueByPath(fromObject, ['language']);\n if (parentObject !== undefined && fromLanguage != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'language'],\n fromLanguage,\n );\n }\n\n const fromOutputMimeType = common.getValueByPath(fromObject, [\n 'outputMimeType',\n ]);\n if (parentObject !== undefined && fromOutputMimeType != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'outputOptions', 'mimeType'],\n fromOutputMimeType,\n );\n }\n\n const fromOutputCompressionQuality = common.getValueByPath(fromObject, [\n 'outputCompressionQuality',\n ]);\n if (parentObject !== undefined && fromOutputCompressionQuality != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'outputOptions', 'compressionQuality'],\n fromOutputCompressionQuality,\n );\n }\n\n const fromAddWatermark = common.getValueByPath(fromObject, ['addWatermark']);\n if (parentObject !== undefined && fromAddWatermark != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'addWatermark'],\n fromAddWatermark,\n );\n }\n\n const fromLabels = common.getValueByPath(fromObject, ['labels']);\n if (parentObject !== undefined && fromLabels != null) {\n common.setValueByPath(parentObject, ['labels'], fromLabels);\n }\n\n const fromImageSize = common.getValueByPath(fromObject, ['imageSize']);\n if (parentObject !== undefined && fromImageSize != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'sampleImageSize'],\n fromImageSize,\n );\n }\n\n const fromEnhancePrompt = common.getValueByPath(fromObject, [\n 'enhancePrompt',\n ]);\n if (parentObject !== undefined && fromEnhancePrompt != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'enhancePrompt'],\n fromEnhancePrompt,\n );\n }\n\n return toObject;\n}\n\nexport function generateImagesParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.GenerateImagesParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromPrompt = common.getValueByPath(fromObject, ['prompt']);\n if (fromPrompt != null) {\n common.setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n generateImagesConfigToMldev(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function generateImagesParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.GenerateImagesParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromPrompt = common.getValueByPath(fromObject, ['prompt']);\n if (fromPrompt != null) {\n common.setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n generateImagesConfigToVertex(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function generateImagesResponseFromMldev(\n fromObject: types.GenerateImagesResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromGeneratedImages = common.getValueByPath(fromObject, [\n 'predictions',\n ]);\n if (fromGeneratedImages != null) {\n let transformedList = fromGeneratedImages;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return generatedImageFromMldev(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['generatedImages'], transformedList);\n }\n\n const fromPositivePromptSafetyAttributes = common.getValueByPath(fromObject, [\n 'positivePromptSafetyAttributes',\n ]);\n if (fromPositivePromptSafetyAttributes != null) {\n common.setValueByPath(\n toObject,\n ['positivePromptSafetyAttributes'],\n safetyAttributesFromMldev(fromPositivePromptSafetyAttributes, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function generateImagesResponseFromVertex(\n fromObject: types.GenerateImagesResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromGeneratedImages = common.getValueByPath(fromObject, [\n 'predictions',\n ]);\n if (fromGeneratedImages != null) {\n let transformedList = fromGeneratedImages;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return generatedImageFromVertex(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['generatedImages'], transformedList);\n }\n\n const fromPositivePromptSafetyAttributes = common.getValueByPath(fromObject, [\n 'positivePromptSafetyAttributes',\n ]);\n if (fromPositivePromptSafetyAttributes != null) {\n common.setValueByPath(\n toObject,\n ['positivePromptSafetyAttributes'],\n safetyAttributesFromVertex(\n fromPositivePromptSafetyAttributes,\n rootObject,\n ),\n );\n }\n\n return toObject;\n}\n\nexport function generateVideosConfigToMldev(\n fromObject: types.GenerateVideosConfig,\n parentObject: Record<string, unknown>,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromNumberOfVideos = common.getValueByPath(fromObject, [\n 'numberOfVideos',\n ]);\n if (parentObject !== undefined && fromNumberOfVideos != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'sampleCount'],\n fromNumberOfVideos,\n );\n }\n\n if (common.getValueByPath(fromObject, ['outputGcsUri']) !== undefined) {\n throw new Error('outputGcsUri parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['fps']) !== undefined) {\n throw new Error('fps parameter is not supported in Gemini API.');\n }\n\n const fromDurationSeconds = common.getValueByPath(fromObject, [\n 'durationSeconds',\n ]);\n if (parentObject !== undefined && fromDurationSeconds != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'durationSeconds'],\n fromDurationSeconds,\n );\n }\n\n if (common.getValueByPath(fromObject, ['seed']) !== undefined) {\n throw new Error('seed parameter is not supported in Gemini API.');\n }\n\n const fromAspectRatio = common.getValueByPath(fromObject, ['aspectRatio']);\n if (parentObject !== undefined && fromAspectRatio != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'aspectRatio'],\n fromAspectRatio,\n );\n }\n\n const fromResolution = common.getValueByPath(fromObject, ['resolution']);\n if (parentObject !== undefined && fromResolution != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'resolution'],\n fromResolution,\n );\n }\n\n const fromPersonGeneration = common.getValueByPath(fromObject, [\n 'personGeneration',\n ]);\n if (parentObject !== undefined && fromPersonGeneration != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'personGeneration'],\n fromPersonGeneration,\n );\n }\n\n if (common.getValueByPath(fromObject, ['pubsubTopic']) !== undefined) {\n throw new Error('pubsubTopic parameter is not supported in Gemini API.');\n }\n\n const fromNegativePrompt = common.getValueByPath(fromObject, [\n 'negativePrompt',\n ]);\n if (parentObject !== undefined && fromNegativePrompt != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'negativePrompt'],\n fromNegativePrompt,\n );\n }\n\n const fromEnhancePrompt = common.getValueByPath(fromObject, [\n 'enhancePrompt',\n ]);\n if (parentObject !== undefined && fromEnhancePrompt != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'enhancePrompt'],\n fromEnhancePrompt,\n );\n }\n\n if (common.getValueByPath(fromObject, ['generateAudio']) !== undefined) {\n throw new Error('generateAudio parameter is not supported in Gemini API.');\n }\n\n const fromLastFrame = common.getValueByPath(fromObject, ['lastFrame']);\n if (parentObject !== undefined && fromLastFrame != null) {\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'lastFrame'],\n imageToMldev(fromLastFrame, rootObject),\n );\n }\n\n const fromReferenceImages = common.getValueByPath(fromObject, [\n 'referenceImages',\n ]);\n if (parentObject !== undefined && fromReferenceImages != null) {\n let transformedList = fromReferenceImages;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return videoGenerationReferenceImageToMldev(item, rootObject);\n });\n }\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'referenceImages'],\n transformedList,\n );\n }\n\n if (common.getValueByPath(fromObject, ['mask']) !== undefined) {\n throw new Error('mask parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['compressionQuality']) !== undefined) {\n throw new Error(\n 'compressionQuality parameter is not supported in Gemini API.',\n );\n }\n\n return toObject;\n}\n\nexport function generateVideosConfigToVertex(\n fromObject: types.GenerateVideosConfig,\n parentObject: Record<string, unknown>,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromNumberOfVideos = common.getValueByPath(fromObject, [\n 'numberOfVideos',\n ]);\n if (parentObject !== undefined && fromNumberOfVideos != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'sampleCount'],\n fromNumberOfVideos,\n );\n }\n\n const fromOutputGcsUri = common.getValueByPath(fromObject, ['outputGcsUri']);\n if (parentObject !== undefined && fromOutputGcsUri != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'storageUri'],\n fromOutputGcsUri,\n );\n }\n\n const fromFps = common.getValueByPath(fromObject, ['fps']);\n if (parentObject !== undefined && fromFps != null) {\n common.setValueByPath(parentObject, ['parameters', 'fps'], fromFps);\n }\n\n const fromDurationSeconds = common.getValueByPath(fromObject, [\n 'durationSeconds',\n ]);\n if (parentObject !== undefined && fromDurationSeconds != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'durationSeconds'],\n fromDurationSeconds,\n );\n }\n\n const fromSeed = common.getValueByPath(fromObject, ['seed']);\n if (parentObject !== undefined && fromSeed != null) {\n common.setValueByPath(parentObject, ['parameters', 'seed'], fromSeed);\n }\n\n const fromAspectRatio = common.getValueByPath(fromObject, ['aspectRatio']);\n if (parentObject !== undefined && fromAspectRatio != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'aspectRatio'],\n fromAspectRatio,\n );\n }\n\n const fromResolution = common.getValueByPath(fromObject, ['resolution']);\n if (parentObject !== undefined && fromResolution != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'resolution'],\n fromResolution,\n );\n }\n\n const fromPersonGeneration = common.getValueByPath(fromObject, [\n 'personGeneration',\n ]);\n if (parentObject !== undefined && fromPersonGeneration != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'personGeneration'],\n fromPersonGeneration,\n );\n }\n\n const fromPubsubTopic = common.getValueByPath(fromObject, ['pubsubTopic']);\n if (parentObject !== undefined && fromPubsubTopic != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'pubsubTopic'],\n fromPubsubTopic,\n );\n }\n\n const fromNegativePrompt = common.getValueByPath(fromObject, [\n 'negativePrompt',\n ]);\n if (parentObject !== undefined && fromNegativePrompt != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'negativePrompt'],\n fromNegativePrompt,\n );\n }\n\n const fromEnhancePrompt = common.getValueByPath(fromObject, [\n 'enhancePrompt',\n ]);\n if (parentObject !== undefined && fromEnhancePrompt != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'enhancePrompt'],\n fromEnhancePrompt,\n );\n }\n\n const fromGenerateAudio = common.getValueByPath(fromObject, [\n 'generateAudio',\n ]);\n if (parentObject !== undefined && fromGenerateAudio != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'generateAudio'],\n fromGenerateAudio,\n );\n }\n\n const fromLastFrame = common.getValueByPath(fromObject, ['lastFrame']);\n if (parentObject !== undefined && fromLastFrame != null) {\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'lastFrame'],\n imageToVertex(fromLastFrame, rootObject),\n );\n }\n\n const fromReferenceImages = common.getValueByPath(fromObject, [\n 'referenceImages',\n ]);\n if (parentObject !== undefined && fromReferenceImages != null) {\n let transformedList = fromReferenceImages;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return videoGenerationReferenceImageToVertex(item, rootObject);\n });\n }\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'referenceImages'],\n transformedList,\n );\n }\n\n const fromMask = common.getValueByPath(fromObject, ['mask']);\n if (parentObject !== undefined && fromMask != null) {\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'mask'],\n videoGenerationMaskToVertex(fromMask, rootObject),\n );\n }\n\n const fromCompressionQuality = common.getValueByPath(fromObject, [\n 'compressionQuality',\n ]);\n if (parentObject !== undefined && fromCompressionQuality != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'compressionQuality'],\n fromCompressionQuality,\n );\n }\n\n return toObject;\n}\n\nexport function generateVideosOperationFromMldev(\n fromObject: types.GenerateVideosOperation,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromMetadata = common.getValueByPath(fromObject, ['metadata']);\n if (fromMetadata != null) {\n common.setValueByPath(toObject, ['metadata'], fromMetadata);\n }\n\n const fromDone = common.getValueByPath(fromObject, ['done']);\n if (fromDone != null) {\n common.setValueByPath(toObject, ['done'], fromDone);\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n const fromResponse = common.getValueByPath(fromObject, [\n 'response',\n 'generateVideoResponse',\n ]);\n if (fromResponse != null) {\n common.setValueByPath(\n toObject,\n ['response'],\n generateVideosResponseFromMldev(fromResponse, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function generateVideosOperationFromVertex(\n fromObject: types.GenerateVideosOperation,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromMetadata = common.getValueByPath(fromObject, ['metadata']);\n if (fromMetadata != null) {\n common.setValueByPath(toObject, ['metadata'], fromMetadata);\n }\n\n const fromDone = common.getValueByPath(fromObject, ['done']);\n if (fromDone != null) {\n common.setValueByPath(toObject, ['done'], fromDone);\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n const fromResponse = common.getValueByPath(fromObject, ['response']);\n if (fromResponse != null) {\n common.setValueByPath(\n toObject,\n ['response'],\n generateVideosResponseFromVertex(fromResponse, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function generateVideosParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.GenerateVideosParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromPrompt = common.getValueByPath(fromObject, ['prompt']);\n if (fromPrompt != null) {\n common.setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt);\n }\n\n const fromImage = common.getValueByPath(fromObject, ['image']);\n if (fromImage != null) {\n common.setValueByPath(\n toObject,\n ['instances[0]', 'image'],\n imageToMldev(fromImage, rootObject),\n );\n }\n\n const fromVideo = common.getValueByPath(fromObject, ['video']);\n if (fromVideo != null) {\n common.setValueByPath(\n toObject,\n ['instances[0]', 'video'],\n videoToMldev(fromVideo, rootObject),\n );\n }\n\n const fromSource = common.getValueByPath(fromObject, ['source']);\n if (fromSource != null) {\n generateVideosSourceToMldev(fromSource, toObject, rootObject);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n generateVideosConfigToMldev(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function generateVideosParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.GenerateVideosParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromPrompt = common.getValueByPath(fromObject, ['prompt']);\n if (fromPrompt != null) {\n common.setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt);\n }\n\n const fromImage = common.getValueByPath(fromObject, ['image']);\n if (fromImage != null) {\n common.setValueByPath(\n toObject,\n ['instances[0]', 'image'],\n imageToVertex(fromImage, rootObject),\n );\n }\n\n const fromVideo = common.getValueByPath(fromObject, ['video']);\n if (fromVideo != null) {\n common.setValueByPath(\n toObject,\n ['instances[0]', 'video'],\n videoToVertex(fromVideo, rootObject),\n );\n }\n\n const fromSource = common.getValueByPath(fromObject, ['source']);\n if (fromSource != null) {\n generateVideosSourceToVertex(fromSource, toObject, rootObject);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n generateVideosConfigToVertex(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function generateVideosResponseFromMldev(\n fromObject: types.GenerateVideosResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromGeneratedVideos = common.getValueByPath(fromObject, [\n 'generatedSamples',\n ]);\n if (fromGeneratedVideos != null) {\n let transformedList = fromGeneratedVideos;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return generatedVideoFromMldev(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['generatedVideos'], transformedList);\n }\n\n const fromRaiMediaFilteredCount = common.getValueByPath(fromObject, [\n 'raiMediaFilteredCount',\n ]);\n if (fromRaiMediaFilteredCount != null) {\n common.setValueByPath(\n toObject,\n ['raiMediaFilteredCount'],\n fromRaiMediaFilteredCount,\n );\n }\n\n const fromRaiMediaFilteredReasons = common.getValueByPath(fromObject, [\n 'raiMediaFilteredReasons',\n ]);\n if (fromRaiMediaFilteredReasons != null) {\n common.setValueByPath(\n toObject,\n ['raiMediaFilteredReasons'],\n fromRaiMediaFilteredReasons,\n );\n }\n\n return toObject;\n}\n\nexport function generateVideosResponseFromVertex(\n fromObject: types.GenerateVideosResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromGeneratedVideos = common.getValueByPath(fromObject, ['videos']);\n if (fromGeneratedVideos != null) {\n let transformedList = fromGeneratedVideos;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return generatedVideoFromVertex(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['generatedVideos'], transformedList);\n }\n\n const fromRaiMediaFilteredCount = common.getValueByPath(fromObject, [\n 'raiMediaFilteredCount',\n ]);\n if (fromRaiMediaFilteredCount != null) {\n common.setValueByPath(\n toObject,\n ['raiMediaFilteredCount'],\n fromRaiMediaFilteredCount,\n );\n }\n\n const fromRaiMediaFilteredReasons = common.getValueByPath(fromObject, [\n 'raiMediaFilteredReasons',\n ]);\n if (fromRaiMediaFilteredReasons != null) {\n common.setValueByPath(\n toObject,\n ['raiMediaFilteredReasons'],\n fromRaiMediaFilteredReasons,\n );\n }\n\n return toObject;\n}\n\nexport function generateVideosSourceToMldev(\n fromObject: types.GenerateVideosSource,\n parentObject: Record<string, unknown>,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPrompt = common.getValueByPath(fromObject, ['prompt']);\n if (parentObject !== undefined && fromPrompt != null) {\n common.setValueByPath(parentObject, ['instances[0]', 'prompt'], fromPrompt);\n }\n\n const fromImage = common.getValueByPath(fromObject, ['image']);\n if (parentObject !== undefined && fromImage != null) {\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'image'],\n imageToMldev(fromImage, rootObject),\n );\n }\n\n const fromVideo = common.getValueByPath(fromObject, ['video']);\n if (parentObject !== undefined && fromVideo != null) {\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'video'],\n videoToMldev(fromVideo, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function generateVideosSourceToVertex(\n fromObject: types.GenerateVideosSource,\n parentObject: Record<string, unknown>,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPrompt = common.getValueByPath(fromObject, ['prompt']);\n if (parentObject !== undefined && fromPrompt != null) {\n common.setValueByPath(parentObject, ['instances[0]', 'prompt'], fromPrompt);\n }\n\n const fromImage = common.getValueByPath(fromObject, ['image']);\n if (parentObject !== undefined && fromImage != null) {\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'image'],\n imageToVertex(fromImage, rootObject),\n );\n }\n\n const fromVideo = common.getValueByPath(fromObject, ['video']);\n if (parentObject !== undefined && fromVideo != null) {\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'video'],\n videoToVertex(fromVideo, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function generatedImageFromMldev(\n fromObject: types.GeneratedImage,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromImage = common.getValueByPath(fromObject, ['_self']);\n if (fromImage != null) {\n common.setValueByPath(\n toObject,\n ['image'],\n imageFromMldev(fromImage, rootObject),\n );\n }\n\n const fromRaiFilteredReason = common.getValueByPath(fromObject, [\n 'raiFilteredReason',\n ]);\n if (fromRaiFilteredReason != null) {\n common.setValueByPath(\n toObject,\n ['raiFilteredReason'],\n fromRaiFilteredReason,\n );\n }\n\n const fromSafetyAttributes = common.getValueByPath(fromObject, ['_self']);\n if (fromSafetyAttributes != null) {\n common.setValueByPath(\n toObject,\n ['safetyAttributes'],\n safetyAttributesFromMldev(fromSafetyAttributes, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function generatedImageFromVertex(\n fromObject: types.GeneratedImage,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromImage = common.getValueByPath(fromObject, ['_self']);\n if (fromImage != null) {\n common.setValueByPath(\n toObject,\n ['image'],\n imageFromVertex(fromImage, rootObject),\n );\n }\n\n const fromRaiFilteredReason = common.getValueByPath(fromObject, [\n 'raiFilteredReason',\n ]);\n if (fromRaiFilteredReason != null) {\n common.setValueByPath(\n toObject,\n ['raiFilteredReason'],\n fromRaiFilteredReason,\n );\n }\n\n const fromSafetyAttributes = common.getValueByPath(fromObject, ['_self']);\n if (fromSafetyAttributes != null) {\n common.setValueByPath(\n toObject,\n ['safetyAttributes'],\n safetyAttributesFromVertex(fromSafetyAttributes, rootObject),\n );\n }\n\n const fromEnhancedPrompt = common.getValueByPath(fromObject, ['prompt']);\n if (fromEnhancedPrompt != null) {\n common.setValueByPath(toObject, ['enhancedPrompt'], fromEnhancedPrompt);\n }\n\n return toObject;\n}\n\nexport function generatedImageMaskFromVertex(\n fromObject: types.GeneratedImageMask,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMask = common.getValueByPath(fromObject, ['_self']);\n if (fromMask != null) {\n common.setValueByPath(\n toObject,\n ['mask'],\n imageFromVertex(fromMask, rootObject),\n );\n }\n\n const fromLabels = common.getValueByPath(fromObject, ['labels']);\n if (fromLabels != null) {\n let transformedList = fromLabels;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['labels'], transformedList);\n }\n\n return toObject;\n}\n\nexport function generatedVideoFromMldev(\n fromObject: types.GeneratedVideo,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromVideo = common.getValueByPath(fromObject, ['video']);\n if (fromVideo != null) {\n common.setValueByPath(\n toObject,\n ['video'],\n videoFromMldev(fromVideo, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function generatedVideoFromVertex(\n fromObject: types.GeneratedVideo,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromVideo = common.getValueByPath(fromObject, ['_self']);\n if (fromVideo != null) {\n common.setValueByPath(\n toObject,\n ['video'],\n videoFromVertex(fromVideo, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function generationConfigToVertex(\n fromObject: types.GenerationConfig,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModelSelectionConfig = common.getValueByPath(fromObject, [\n 'modelSelectionConfig',\n ]);\n if (fromModelSelectionConfig != null) {\n common.setValueByPath(toObject, ['modelConfig'], fromModelSelectionConfig);\n }\n\n const fromResponseJsonSchema = common.getValueByPath(fromObject, [\n 'responseJsonSchema',\n ]);\n if (fromResponseJsonSchema != null) {\n common.setValueByPath(\n toObject,\n ['responseJsonSchema'],\n fromResponseJsonSchema,\n );\n }\n\n const fromAudioTimestamp = common.getValueByPath(fromObject, [\n 'audioTimestamp',\n ]);\n if (fromAudioTimestamp != null) {\n common.setValueByPath(toObject, ['audioTimestamp'], fromAudioTimestamp);\n }\n\n const fromCandidateCount = common.getValueByPath(fromObject, [\n 'candidateCount',\n ]);\n if (fromCandidateCount != null) {\n common.setValueByPath(toObject, ['candidateCount'], fromCandidateCount);\n }\n\n const fromEnableAffectiveDialog = common.getValueByPath(fromObject, [\n 'enableAffectiveDialog',\n ]);\n if (fromEnableAffectiveDialog != null) {\n common.setValueByPath(\n toObject,\n ['enableAffectiveDialog'],\n fromEnableAffectiveDialog,\n );\n }\n\n const fromFrequencyPenalty = common.getValueByPath(fromObject, [\n 'frequencyPenalty',\n ]);\n if (fromFrequencyPenalty != null) {\n common.setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty);\n }\n\n const fromLogprobs = common.getValueByPath(fromObject, ['logprobs']);\n if (fromLogprobs != null) {\n common.setValueByPath(toObject, ['logprobs'], fromLogprobs);\n }\n\n const fromMaxOutputTokens = common.getValueByPath(fromObject, [\n 'maxOutputTokens',\n ]);\n if (fromMaxOutputTokens != null) {\n common.setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens);\n }\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (fromMediaResolution != null) {\n common.setValueByPath(toObject, ['mediaResolution'], fromMediaResolution);\n }\n\n const fromPresencePenalty = common.getValueByPath(fromObject, [\n 'presencePenalty',\n ]);\n if (fromPresencePenalty != null) {\n common.setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty);\n }\n\n const fromResponseLogprobs = common.getValueByPath(fromObject, [\n 'responseLogprobs',\n ]);\n if (fromResponseLogprobs != null) {\n common.setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs);\n }\n\n const fromResponseMimeType = common.getValueByPath(fromObject, [\n 'responseMimeType',\n ]);\n if (fromResponseMimeType != null) {\n common.setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType);\n }\n\n const fromResponseModalities = common.getValueByPath(fromObject, [\n 'responseModalities',\n ]);\n if (fromResponseModalities != null) {\n common.setValueByPath(\n toObject,\n ['responseModalities'],\n fromResponseModalities,\n );\n }\n\n const fromResponseSchema = common.getValueByPath(fromObject, [\n 'responseSchema',\n ]);\n if (fromResponseSchema != null) {\n common.setValueByPath(toObject, ['responseSchema'], fromResponseSchema);\n }\n\n const fromRoutingConfig = common.getValueByPath(fromObject, [\n 'routingConfig',\n ]);\n if (fromRoutingConfig != null) {\n common.setValueByPath(toObject, ['routingConfig'], fromRoutingConfig);\n }\n\n const fromSeed = common.getValueByPath(fromObject, ['seed']);\n if (fromSeed != null) {\n common.setValueByPath(toObject, ['seed'], fromSeed);\n }\n\n const fromSpeechConfig = common.getValueByPath(fromObject, ['speechConfig']);\n if (fromSpeechConfig != null) {\n common.setValueByPath(toObject, ['speechConfig'], fromSpeechConfig);\n }\n\n const fromStopSequences = common.getValueByPath(fromObject, [\n 'stopSequences',\n ]);\n if (fromStopSequences != null) {\n common.setValueByPath(toObject, ['stopSequences'], fromStopSequences);\n }\n\n const fromTemperature = common.getValueByPath(fromObject, ['temperature']);\n if (fromTemperature != null) {\n common.setValueByPath(toObject, ['temperature'], fromTemperature);\n }\n\n const fromThinkingConfig = common.getValueByPath(fromObject, [\n 'thinkingConfig',\n ]);\n if (fromThinkingConfig != null) {\n common.setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig);\n }\n\n const fromTopK = common.getValueByPath(fromObject, ['topK']);\n if (fromTopK != null) {\n common.setValueByPath(toObject, ['topK'], fromTopK);\n }\n\n const fromTopP = common.getValueByPath(fromObject, ['topP']);\n if (fromTopP != null) {\n common.setValueByPath(toObject, ['topP'], fromTopP);\n }\n\n if (\n common.getValueByPath(fromObject, ['enableEnhancedCivicAnswers']) !==\n undefined\n ) {\n throw new Error(\n 'enableEnhancedCivicAnswers parameter is not supported in Vertex AI.',\n );\n }\n\n return toObject;\n}\n\nexport function getModelParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.GetModelParameters,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n return toObject;\n}\n\nexport function getModelParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.GetModelParameters,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n return toObject;\n}\n\nexport function googleMapsToMldev(\n fromObject: types.GoogleMaps,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['authConfig']) !== undefined) {\n throw new Error('authConfig parameter is not supported in Gemini API.');\n }\n\n const fromEnableWidget = common.getValueByPath(fromObject, ['enableWidget']);\n if (fromEnableWidget != null) {\n common.setValueByPath(toObject, ['enableWidget'], fromEnableWidget);\n }\n\n return toObject;\n}\n\nexport function googleSearchToMldev(\n fromObject: types.GoogleSearch,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['excludeDomains']) !== undefined) {\n throw new Error('excludeDomains parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['blockingConfidence']) !== undefined) {\n throw new Error(\n 'blockingConfidence parameter is not supported in Gemini API.',\n );\n }\n\n const fromTimeRangeFilter = common.getValueByPath(fromObject, [\n 'timeRangeFilter',\n ]);\n if (fromTimeRangeFilter != null) {\n common.setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter);\n }\n\n return toObject;\n}\n\nexport function imageConfigToMldev(\n fromObject: types.ImageConfig,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromAspectRatio = common.getValueByPath(fromObject, ['aspectRatio']);\n if (fromAspectRatio != null) {\n common.setValueByPath(toObject, ['aspectRatio'], fromAspectRatio);\n }\n\n const fromImageSize = common.getValueByPath(fromObject, ['imageSize']);\n if (fromImageSize != null) {\n common.setValueByPath(toObject, ['imageSize'], fromImageSize);\n }\n\n if (common.getValueByPath(fromObject, ['personGeneration']) !== undefined) {\n throw new Error(\n 'personGeneration parameter is not supported in Gemini API.',\n );\n }\n\n if (common.getValueByPath(fromObject, ['outputMimeType']) !== undefined) {\n throw new Error('outputMimeType parameter is not supported in Gemini API.');\n }\n\n if (\n common.getValueByPath(fromObject, ['outputCompressionQuality']) !==\n undefined\n ) {\n throw new Error(\n 'outputCompressionQuality parameter is not supported in Gemini API.',\n );\n }\n\n return toObject;\n}\n\nexport function imageConfigToVertex(\n fromObject: types.ImageConfig,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromAspectRatio = common.getValueByPath(fromObject, ['aspectRatio']);\n if (fromAspectRatio != null) {\n common.setValueByPath(toObject, ['aspectRatio'], fromAspectRatio);\n }\n\n const fromImageSize = common.getValueByPath(fromObject, ['imageSize']);\n if (fromImageSize != null) {\n common.setValueByPath(toObject, ['imageSize'], fromImageSize);\n }\n\n const fromPersonGeneration = common.getValueByPath(fromObject, [\n 'personGeneration',\n ]);\n if (fromPersonGeneration != null) {\n common.setValueByPath(toObject, ['personGeneration'], fromPersonGeneration);\n }\n\n const fromOutputMimeType = common.getValueByPath(fromObject, [\n 'outputMimeType',\n ]);\n if (fromOutputMimeType != null) {\n common.setValueByPath(\n toObject,\n ['imageOutputOptions', 'mimeType'],\n fromOutputMimeType,\n );\n }\n\n const fromOutputCompressionQuality = common.getValueByPath(fromObject, [\n 'outputCompressionQuality',\n ]);\n if (fromOutputCompressionQuality != null) {\n common.setValueByPath(\n toObject,\n ['imageOutputOptions', 'compressionQuality'],\n fromOutputCompressionQuality,\n );\n }\n\n return toObject;\n}\n\nexport function imageFromMldev(\n fromObject: types.Image,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromImageBytes = common.getValueByPath(fromObject, [\n 'bytesBase64Encoded',\n ]);\n if (fromImageBytes != null) {\n common.setValueByPath(toObject, ['imageBytes'], t.tBytes(fromImageBytes));\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function imageFromVertex(\n fromObject: types.Image,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromGcsUri = common.getValueByPath(fromObject, ['gcsUri']);\n if (fromGcsUri != null) {\n common.setValueByPath(toObject, ['gcsUri'], fromGcsUri);\n }\n\n const fromImageBytes = common.getValueByPath(fromObject, [\n 'bytesBase64Encoded',\n ]);\n if (fromImageBytes != null) {\n common.setValueByPath(toObject, ['imageBytes'], t.tBytes(fromImageBytes));\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function imageToMldev(\n fromObject: types.Image,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['gcsUri']) !== undefined) {\n throw new Error('gcsUri parameter is not supported in Gemini API.');\n }\n\n const fromImageBytes = common.getValueByPath(fromObject, ['imageBytes']);\n if (fromImageBytes != null) {\n common.setValueByPath(\n toObject,\n ['bytesBase64Encoded'],\n t.tBytes(fromImageBytes),\n );\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function imageToVertex(\n fromObject: types.Image,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromGcsUri = common.getValueByPath(fromObject, ['gcsUri']);\n if (fromGcsUri != null) {\n common.setValueByPath(toObject, ['gcsUri'], fromGcsUri);\n }\n\n const fromImageBytes = common.getValueByPath(fromObject, ['imageBytes']);\n if (fromImageBytes != null) {\n common.setValueByPath(\n toObject,\n ['bytesBase64Encoded'],\n t.tBytes(fromImageBytes),\n );\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function listModelsConfigToMldev(\n apiClient: ApiClient,\n fromObject: types.ListModelsConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPageSize = common.getValueByPath(fromObject, ['pageSize']);\n if (parentObject !== undefined && fromPageSize != null) {\n common.setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize);\n }\n\n const fromPageToken = common.getValueByPath(fromObject, ['pageToken']);\n if (parentObject !== undefined && fromPageToken != null) {\n common.setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken);\n }\n\n const fromFilter = common.getValueByPath(fromObject, ['filter']);\n if (parentObject !== undefined && fromFilter != null) {\n common.setValueByPath(parentObject, ['_query', 'filter'], fromFilter);\n }\n\n const fromQueryBase = common.getValueByPath(fromObject, ['queryBase']);\n if (parentObject !== undefined && fromQueryBase != null) {\n common.setValueByPath(\n parentObject,\n ['_url', 'models_url'],\n t.tModelsUrl(apiClient, fromQueryBase),\n );\n }\n\n return toObject;\n}\n\nexport function listModelsConfigToVertex(\n apiClient: ApiClient,\n fromObject: types.ListModelsConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPageSize = common.getValueByPath(fromObject, ['pageSize']);\n if (parentObject !== undefined && fromPageSize != null) {\n common.setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize);\n }\n\n const fromPageToken = common.getValueByPath(fromObject, ['pageToken']);\n if (parentObject !== undefined && fromPageToken != null) {\n common.setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken);\n }\n\n const fromFilter = common.getValueByPath(fromObject, ['filter']);\n if (parentObject !== undefined && fromFilter != null) {\n common.setValueByPath(parentObject, ['_query', 'filter'], fromFilter);\n }\n\n const fromQueryBase = common.getValueByPath(fromObject, ['queryBase']);\n if (parentObject !== undefined && fromQueryBase != null) {\n common.setValueByPath(\n parentObject,\n ['_url', 'models_url'],\n t.tModelsUrl(apiClient, fromQueryBase),\n );\n }\n\n return toObject;\n}\n\nexport function listModelsParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.ListModelsParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n listModelsConfigToMldev(apiClient, fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function listModelsParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.ListModelsParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n listModelsConfigToVertex(apiClient, fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function listModelsResponseFromMldev(\n fromObject: types.ListModelsResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromNextPageToken = common.getValueByPath(fromObject, [\n 'nextPageToken',\n ]);\n if (fromNextPageToken != null) {\n common.setValueByPath(toObject, ['nextPageToken'], fromNextPageToken);\n }\n\n const fromModels = common.getValueByPath(fromObject, ['_self']);\n if (fromModels != null) {\n let transformedList = t.tExtractModels(fromModels);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return modelFromMldev(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['models'], transformedList);\n }\n\n return toObject;\n}\n\nexport function listModelsResponseFromVertex(\n fromObject: types.ListModelsResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromNextPageToken = common.getValueByPath(fromObject, [\n 'nextPageToken',\n ]);\n if (fromNextPageToken != null) {\n common.setValueByPath(toObject, ['nextPageToken'], fromNextPageToken);\n }\n\n const fromModels = common.getValueByPath(fromObject, ['_self']);\n if (fromModels != null) {\n let transformedList = t.tExtractModels(fromModels);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return modelFromVertex(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['models'], transformedList);\n }\n\n return toObject;\n}\n\nexport function maskReferenceConfigToVertex(\n fromObject: types.MaskReferenceConfig,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMaskMode = common.getValueByPath(fromObject, ['maskMode']);\n if (fromMaskMode != null) {\n common.setValueByPath(toObject, ['maskMode'], fromMaskMode);\n }\n\n const fromSegmentationClasses = common.getValueByPath(fromObject, [\n 'segmentationClasses',\n ]);\n if (fromSegmentationClasses != null) {\n common.setValueByPath(toObject, ['maskClasses'], fromSegmentationClasses);\n }\n\n const fromMaskDilation = common.getValueByPath(fromObject, ['maskDilation']);\n if (fromMaskDilation != null) {\n common.setValueByPath(toObject, ['dilation'], fromMaskDilation);\n }\n\n return toObject;\n}\n\nexport function modelFromMldev(\n fromObject: types.Model,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromDisplayName = common.getValueByPath(fromObject, ['displayName']);\n if (fromDisplayName != null) {\n common.setValueByPath(toObject, ['displayName'], fromDisplayName);\n }\n\n const fromDescription = common.getValueByPath(fromObject, ['description']);\n if (fromDescription != null) {\n common.setValueByPath(toObject, ['description'], fromDescription);\n }\n\n const fromVersion = common.getValueByPath(fromObject, ['version']);\n if (fromVersion != null) {\n common.setValueByPath(toObject, ['version'], fromVersion);\n }\n\n const fromTunedModelInfo = common.getValueByPath(fromObject, ['_self']);\n if (fromTunedModelInfo != null) {\n common.setValueByPath(\n toObject,\n ['tunedModelInfo'],\n tunedModelInfoFromMldev(fromTunedModelInfo, rootObject),\n );\n }\n\n const fromInputTokenLimit = common.getValueByPath(fromObject, [\n 'inputTokenLimit',\n ]);\n if (fromInputTokenLimit != null) {\n common.setValueByPath(toObject, ['inputTokenLimit'], fromInputTokenLimit);\n }\n\n const fromOutputTokenLimit = common.getValueByPath(fromObject, [\n 'outputTokenLimit',\n ]);\n if (fromOutputTokenLimit != null) {\n common.setValueByPath(toObject, ['outputTokenLimit'], fromOutputTokenLimit);\n }\n\n const fromSupportedActions = common.getValueByPath(fromObject, [\n 'supportedGenerationMethods',\n ]);\n if (fromSupportedActions != null) {\n common.setValueByPath(toObject, ['supportedActions'], fromSupportedActions);\n }\n\n const fromTemperature = common.getValueByPath(fromObject, ['temperature']);\n if (fromTemperature != null) {\n common.setValueByPath(toObject, ['temperature'], fromTemperature);\n }\n\n const fromMaxTemperature = common.getValueByPath(fromObject, [\n 'maxTemperature',\n ]);\n if (fromMaxTemperature != null) {\n common.setValueByPath(toObject, ['maxTemperature'], fromMaxTemperature);\n }\n\n const fromTopP = common.getValueByPath(fromObject, ['topP']);\n if (fromTopP != null) {\n common.setValueByPath(toObject, ['topP'], fromTopP);\n }\n\n const fromTopK = common.getValueByPath(fromObject, ['topK']);\n if (fromTopK != null) {\n common.setValueByPath(toObject, ['topK'], fromTopK);\n }\n\n const fromThinking = common.getValueByPath(fromObject, ['thinking']);\n if (fromThinking != null) {\n common.setValueByPath(toObject, ['thinking'], fromThinking);\n }\n\n return toObject;\n}\n\nexport function modelFromVertex(\n fromObject: types.Model,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromDisplayName = common.getValueByPath(fromObject, ['displayName']);\n if (fromDisplayName != null) {\n common.setValueByPath(toObject, ['displayName'], fromDisplayName);\n }\n\n const fromDescription = common.getValueByPath(fromObject, ['description']);\n if (fromDescription != null) {\n common.setValueByPath(toObject, ['description'], fromDescription);\n }\n\n const fromVersion = common.getValueByPath(fromObject, ['versionId']);\n if (fromVersion != null) {\n common.setValueByPath(toObject, ['version'], fromVersion);\n }\n\n const fromEndpoints = common.getValueByPath(fromObject, ['deployedModels']);\n if (fromEndpoints != null) {\n let transformedList = fromEndpoints;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return endpointFromVertex(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['endpoints'], transformedList);\n }\n\n const fromLabels = common.getValueByPath(fromObject, ['labels']);\n if (fromLabels != null) {\n common.setValueByPath(toObject, ['labels'], fromLabels);\n }\n\n const fromTunedModelInfo = common.getValueByPath(fromObject, ['_self']);\n if (fromTunedModelInfo != null) {\n common.setValueByPath(\n toObject,\n ['tunedModelInfo'],\n tunedModelInfoFromVertex(fromTunedModelInfo, rootObject),\n );\n }\n\n const fromDefaultCheckpointId = common.getValueByPath(fromObject, [\n 'defaultCheckpointId',\n ]);\n if (fromDefaultCheckpointId != null) {\n common.setValueByPath(\n toObject,\n ['defaultCheckpointId'],\n fromDefaultCheckpointId,\n );\n }\n\n const fromCheckpoints = common.getValueByPath(fromObject, ['checkpoints']);\n if (fromCheckpoints != null) {\n let transformedList = fromCheckpoints;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['checkpoints'], transformedList);\n }\n\n return toObject;\n}\n\nexport function partToMldev(\n fromObject: types.Part,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (fromMediaResolution != null) {\n common.setValueByPath(toObject, ['mediaResolution'], fromMediaResolution);\n }\n\n const fromCodeExecutionResult = common.getValueByPath(fromObject, [\n 'codeExecutionResult',\n ]);\n if (fromCodeExecutionResult != null) {\n common.setValueByPath(\n toObject,\n ['codeExecutionResult'],\n fromCodeExecutionResult,\n );\n }\n\n const fromExecutableCode = common.getValueByPath(fromObject, [\n 'executableCode',\n ]);\n if (fromExecutableCode != null) {\n common.setValueByPath(toObject, ['executableCode'], fromExecutableCode);\n }\n\n const fromFileData = common.getValueByPath(fromObject, ['fileData']);\n if (fromFileData != null) {\n common.setValueByPath(\n toObject,\n ['fileData'],\n fileDataToMldev(fromFileData, rootObject),\n );\n }\n\n const fromFunctionCall = common.getValueByPath(fromObject, ['functionCall']);\n if (fromFunctionCall != null) {\n common.setValueByPath(\n toObject,\n ['functionCall'],\n functionCallToMldev(fromFunctionCall, rootObject),\n );\n }\n\n const fromFunctionResponse = common.getValueByPath(fromObject, [\n 'functionResponse',\n ]);\n if (fromFunctionResponse != null) {\n common.setValueByPath(toObject, ['functionResponse'], fromFunctionResponse);\n }\n\n const fromInlineData = common.getValueByPath(fromObject, ['inlineData']);\n if (fromInlineData != null) {\n common.setValueByPath(\n toObject,\n ['inlineData'],\n blobToMldev(fromInlineData, rootObject),\n );\n }\n\n const fromText = common.getValueByPath(fromObject, ['text']);\n if (fromText != null) {\n common.setValueByPath(toObject, ['text'], fromText);\n }\n\n const fromThought = common.getValueByPath(fromObject, ['thought']);\n if (fromThought != null) {\n common.setValueByPath(toObject, ['thought'], fromThought);\n }\n\n const fromThoughtSignature = common.getValueByPath(fromObject, [\n 'thoughtSignature',\n ]);\n if (fromThoughtSignature != null) {\n common.setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature);\n }\n\n const fromVideoMetadata = common.getValueByPath(fromObject, [\n 'videoMetadata',\n ]);\n if (fromVideoMetadata != null) {\n common.setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata);\n }\n\n return toObject;\n}\n\nexport function productImageToVertex(\n fromObject: types.ProductImage,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromProductImage = common.getValueByPath(fromObject, ['productImage']);\n if (fromProductImage != null) {\n common.setValueByPath(\n toObject,\n ['image'],\n imageToVertex(fromProductImage, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function recontextImageConfigToVertex(\n fromObject: types.RecontextImageConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromNumberOfImages = common.getValueByPath(fromObject, [\n 'numberOfImages',\n ]);\n if (parentObject !== undefined && fromNumberOfImages != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'sampleCount'],\n fromNumberOfImages,\n );\n }\n\n const fromBaseSteps = common.getValueByPath(fromObject, ['baseSteps']);\n if (parentObject !== undefined && fromBaseSteps != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'baseSteps'],\n fromBaseSteps,\n );\n }\n\n const fromOutputGcsUri = common.getValueByPath(fromObject, ['outputGcsUri']);\n if (parentObject !== undefined && fromOutputGcsUri != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'storageUri'],\n fromOutputGcsUri,\n );\n }\n\n const fromSeed = common.getValueByPath(fromObject, ['seed']);\n if (parentObject !== undefined && fromSeed != null) {\n common.setValueByPath(parentObject, ['parameters', 'seed'], fromSeed);\n }\n\n const fromSafetyFilterLevel = common.getValueByPath(fromObject, [\n 'safetyFilterLevel',\n ]);\n if (parentObject !== undefined && fromSafetyFilterLevel != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'safetySetting'],\n fromSafetyFilterLevel,\n );\n }\n\n const fromPersonGeneration = common.getValueByPath(fromObject, [\n 'personGeneration',\n ]);\n if (parentObject !== undefined && fromPersonGeneration != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'personGeneration'],\n fromPersonGeneration,\n );\n }\n\n const fromAddWatermark = common.getValueByPath(fromObject, ['addWatermark']);\n if (parentObject !== undefined && fromAddWatermark != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'addWatermark'],\n fromAddWatermark,\n );\n }\n\n const fromOutputMimeType = common.getValueByPath(fromObject, [\n 'outputMimeType',\n ]);\n if (parentObject !== undefined && fromOutputMimeType != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'outputOptions', 'mimeType'],\n fromOutputMimeType,\n );\n }\n\n const fromOutputCompressionQuality = common.getValueByPath(fromObject, [\n 'outputCompressionQuality',\n ]);\n if (parentObject !== undefined && fromOutputCompressionQuality != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'outputOptions', 'compressionQuality'],\n fromOutputCompressionQuality,\n );\n }\n\n const fromEnhancePrompt = common.getValueByPath(fromObject, [\n 'enhancePrompt',\n ]);\n if (parentObject !== undefined && fromEnhancePrompt != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'enhancePrompt'],\n fromEnhancePrompt,\n );\n }\n\n const fromLabels = common.getValueByPath(fromObject, ['labels']);\n if (parentObject !== undefined && fromLabels != null) {\n common.setValueByPath(parentObject, ['labels'], fromLabels);\n }\n\n return toObject;\n}\n\nexport function recontextImageParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.RecontextImageParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromSource = common.getValueByPath(fromObject, ['source']);\n if (fromSource != null) {\n recontextImageSourceToVertex(fromSource, toObject, rootObject);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n recontextImageConfigToVertex(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function recontextImageResponseFromVertex(\n fromObject: types.RecontextImageResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromGeneratedImages = common.getValueByPath(fromObject, [\n 'predictions',\n ]);\n if (fromGeneratedImages != null) {\n let transformedList = fromGeneratedImages;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return generatedImageFromVertex(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['generatedImages'], transformedList);\n }\n\n return toObject;\n}\n\nexport function recontextImageSourceToVertex(\n fromObject: types.RecontextImageSource,\n parentObject: Record<string, unknown>,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPrompt = common.getValueByPath(fromObject, ['prompt']);\n if (parentObject !== undefined && fromPrompt != null) {\n common.setValueByPath(parentObject, ['instances[0]', 'prompt'], fromPrompt);\n }\n\n const fromPersonImage = common.getValueByPath(fromObject, ['personImage']);\n if (parentObject !== undefined && fromPersonImage != null) {\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'personImage', 'image'],\n imageToVertex(fromPersonImage, rootObject),\n );\n }\n\n const fromProductImages = common.getValueByPath(fromObject, [\n 'productImages',\n ]);\n if (parentObject !== undefined && fromProductImages != null) {\n let transformedList = fromProductImages;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return productImageToVertex(item, rootObject);\n });\n }\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'productImages'],\n transformedList,\n );\n }\n\n return toObject;\n}\n\nexport function referenceImageAPIInternalToVertex(\n fromObject: _internal_types.ReferenceImageAPIInternal,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromReferenceImage = common.getValueByPath(fromObject, [\n 'referenceImage',\n ]);\n if (fromReferenceImage != null) {\n common.setValueByPath(\n toObject,\n ['referenceImage'],\n imageToVertex(fromReferenceImage, rootObject),\n );\n }\n\n const fromReferenceId = common.getValueByPath(fromObject, ['referenceId']);\n if (fromReferenceId != null) {\n common.setValueByPath(toObject, ['referenceId'], fromReferenceId);\n }\n\n const fromReferenceType = common.getValueByPath(fromObject, [\n 'referenceType',\n ]);\n if (fromReferenceType != null) {\n common.setValueByPath(toObject, ['referenceType'], fromReferenceType);\n }\n\n const fromMaskImageConfig = common.getValueByPath(fromObject, [\n 'maskImageConfig',\n ]);\n if (fromMaskImageConfig != null) {\n common.setValueByPath(\n toObject,\n ['maskImageConfig'],\n maskReferenceConfigToVertex(fromMaskImageConfig, rootObject),\n );\n }\n\n const fromControlImageConfig = common.getValueByPath(fromObject, [\n 'controlImageConfig',\n ]);\n if (fromControlImageConfig != null) {\n common.setValueByPath(\n toObject,\n ['controlImageConfig'],\n controlReferenceConfigToVertex(fromControlImageConfig, rootObject),\n );\n }\n\n const fromStyleImageConfig = common.getValueByPath(fromObject, [\n 'styleImageConfig',\n ]);\n if (fromStyleImageConfig != null) {\n common.setValueByPath(toObject, ['styleImageConfig'], fromStyleImageConfig);\n }\n\n const fromSubjectImageConfig = common.getValueByPath(fromObject, [\n 'subjectImageConfig',\n ]);\n if (fromSubjectImageConfig != null) {\n common.setValueByPath(\n toObject,\n ['subjectImageConfig'],\n fromSubjectImageConfig,\n );\n }\n\n return toObject;\n}\n\nexport function safetyAttributesFromMldev(\n fromObject: types.SafetyAttributes,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromCategories = common.getValueByPath(fromObject, [\n 'safetyAttributes',\n 'categories',\n ]);\n if (fromCategories != null) {\n common.setValueByPath(toObject, ['categories'], fromCategories);\n }\n\n const fromScores = common.getValueByPath(fromObject, [\n 'safetyAttributes',\n 'scores',\n ]);\n if (fromScores != null) {\n common.setValueByPath(toObject, ['scores'], fromScores);\n }\n\n const fromContentType = common.getValueByPath(fromObject, ['contentType']);\n if (fromContentType != null) {\n common.setValueByPath(toObject, ['contentType'], fromContentType);\n }\n\n return toObject;\n}\n\nexport function safetyAttributesFromVertex(\n fromObject: types.SafetyAttributes,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromCategories = common.getValueByPath(fromObject, [\n 'safetyAttributes',\n 'categories',\n ]);\n if (fromCategories != null) {\n common.setValueByPath(toObject, ['categories'], fromCategories);\n }\n\n const fromScores = common.getValueByPath(fromObject, [\n 'safetyAttributes',\n 'scores',\n ]);\n if (fromScores != null) {\n common.setValueByPath(toObject, ['scores'], fromScores);\n }\n\n const fromContentType = common.getValueByPath(fromObject, ['contentType']);\n if (fromContentType != null) {\n common.setValueByPath(toObject, ['contentType'], fromContentType);\n }\n\n return toObject;\n}\n\nexport function safetySettingToMldev(\n fromObject: types.SafetySetting,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromCategory = common.getValueByPath(fromObject, ['category']);\n if (fromCategory != null) {\n common.setValueByPath(toObject, ['category'], fromCategory);\n }\n\n if (common.getValueByPath(fromObject, ['method']) !== undefined) {\n throw new Error('method parameter is not supported in Gemini API.');\n }\n\n const fromThreshold = common.getValueByPath(fromObject, ['threshold']);\n if (fromThreshold != null) {\n common.setValueByPath(toObject, ['threshold'], fromThreshold);\n }\n\n return toObject;\n}\n\nexport function scribbleImageToVertex(\n fromObject: types.ScribbleImage,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromImage = common.getValueByPath(fromObject, ['image']);\n if (fromImage != null) {\n common.setValueByPath(\n toObject,\n ['image'],\n imageToVertex(fromImage, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function segmentImageConfigToVertex(\n fromObject: types.SegmentImageConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMode = common.getValueByPath(fromObject, ['mode']);\n if (parentObject !== undefined && fromMode != null) {\n common.setValueByPath(parentObject, ['parameters', 'mode'], fromMode);\n }\n\n const fromMaxPredictions = common.getValueByPath(fromObject, [\n 'maxPredictions',\n ]);\n if (parentObject !== undefined && fromMaxPredictions != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'maxPredictions'],\n fromMaxPredictions,\n );\n }\n\n const fromConfidenceThreshold = common.getValueByPath(fromObject, [\n 'confidenceThreshold',\n ]);\n if (parentObject !== undefined && fromConfidenceThreshold != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'confidenceThreshold'],\n fromConfidenceThreshold,\n );\n }\n\n const fromMaskDilation = common.getValueByPath(fromObject, ['maskDilation']);\n if (parentObject !== undefined && fromMaskDilation != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'maskDilation'],\n fromMaskDilation,\n );\n }\n\n const fromBinaryColorThreshold = common.getValueByPath(fromObject, [\n 'binaryColorThreshold',\n ]);\n if (parentObject !== undefined && fromBinaryColorThreshold != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'binaryColorThreshold'],\n fromBinaryColorThreshold,\n );\n }\n\n const fromLabels = common.getValueByPath(fromObject, ['labels']);\n if (parentObject !== undefined && fromLabels != null) {\n common.setValueByPath(parentObject, ['labels'], fromLabels);\n }\n\n return toObject;\n}\n\nexport function segmentImageParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.SegmentImageParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromSource = common.getValueByPath(fromObject, ['source']);\n if (fromSource != null) {\n segmentImageSourceToVertex(fromSource, toObject, rootObject);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n segmentImageConfigToVertex(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function segmentImageResponseFromVertex(\n fromObject: types.SegmentImageResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromGeneratedMasks = common.getValueByPath(fromObject, ['predictions']);\n if (fromGeneratedMasks != null) {\n let transformedList = fromGeneratedMasks;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return generatedImageMaskFromVertex(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['generatedMasks'], transformedList);\n }\n\n return toObject;\n}\n\nexport function segmentImageSourceToVertex(\n fromObject: types.SegmentImageSource,\n parentObject: Record<string, unknown>,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPrompt = common.getValueByPath(fromObject, ['prompt']);\n if (parentObject !== undefined && fromPrompt != null) {\n common.setValueByPath(parentObject, ['instances[0]', 'prompt'], fromPrompt);\n }\n\n const fromImage = common.getValueByPath(fromObject, ['image']);\n if (parentObject !== undefined && fromImage != null) {\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'image'],\n imageToVertex(fromImage, rootObject),\n );\n }\n\n const fromScribbleImage = common.getValueByPath(fromObject, [\n 'scribbleImage',\n ]);\n if (parentObject !== undefined && fromScribbleImage != null) {\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'scribble'],\n scribbleImageToVertex(fromScribbleImage, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function toolConfigToMldev(\n fromObject: types.ToolConfig,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromRetrievalConfig = common.getValueByPath(fromObject, [\n 'retrievalConfig',\n ]);\n if (fromRetrievalConfig != null) {\n common.setValueByPath(toObject, ['retrievalConfig'], fromRetrievalConfig);\n }\n\n const fromFunctionCallingConfig = common.getValueByPath(fromObject, [\n 'functionCallingConfig',\n ]);\n if (fromFunctionCallingConfig != null) {\n common.setValueByPath(\n toObject,\n ['functionCallingConfig'],\n functionCallingConfigToMldev(fromFunctionCallingConfig, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function toolToMldev(\n fromObject: types.Tool,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['retrieval']) !== undefined) {\n throw new Error('retrieval parameter is not supported in Gemini API.');\n }\n\n const fromComputerUse = common.getValueByPath(fromObject, ['computerUse']);\n if (fromComputerUse != null) {\n common.setValueByPath(toObject, ['computerUse'], fromComputerUse);\n }\n\n const fromFileSearch = common.getValueByPath(fromObject, ['fileSearch']);\n if (fromFileSearch != null) {\n common.setValueByPath(toObject, ['fileSearch'], fromFileSearch);\n }\n\n const fromCodeExecution = common.getValueByPath(fromObject, [\n 'codeExecution',\n ]);\n if (fromCodeExecution != null) {\n common.setValueByPath(toObject, ['codeExecution'], fromCodeExecution);\n }\n\n if (\n common.getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined\n ) {\n throw new Error(\n 'enterpriseWebSearch parameter is not supported in Gemini API.',\n );\n }\n\n const fromFunctionDeclarations = common.getValueByPath(fromObject, [\n 'functionDeclarations',\n ]);\n if (fromFunctionDeclarations != null) {\n let transformedList = fromFunctionDeclarations;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['functionDeclarations'], transformedList);\n }\n\n const fromGoogleMaps = common.getValueByPath(fromObject, ['googleMaps']);\n if (fromGoogleMaps != null) {\n common.setValueByPath(\n toObject,\n ['googleMaps'],\n googleMapsToMldev(fromGoogleMaps, rootObject),\n );\n }\n\n const fromGoogleSearch = common.getValueByPath(fromObject, ['googleSearch']);\n if (fromGoogleSearch != null) {\n common.setValueByPath(\n toObject,\n ['googleSearch'],\n googleSearchToMldev(fromGoogleSearch, rootObject),\n );\n }\n\n const fromGoogleSearchRetrieval = common.getValueByPath(fromObject, [\n 'googleSearchRetrieval',\n ]);\n if (fromGoogleSearchRetrieval != null) {\n common.setValueByPath(\n toObject,\n ['googleSearchRetrieval'],\n fromGoogleSearchRetrieval,\n );\n }\n\n const fromUrlContext = common.getValueByPath(fromObject, ['urlContext']);\n if (fromUrlContext != null) {\n common.setValueByPath(toObject, ['urlContext'], fromUrlContext);\n }\n\n return toObject;\n}\n\nexport function toolToVertex(\n fromObject: types.Tool,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromRetrieval = common.getValueByPath(fromObject, ['retrieval']);\n if (fromRetrieval != null) {\n common.setValueByPath(toObject, ['retrieval'], fromRetrieval);\n }\n\n const fromComputerUse = common.getValueByPath(fromObject, ['computerUse']);\n if (fromComputerUse != null) {\n common.setValueByPath(toObject, ['computerUse'], fromComputerUse);\n }\n\n if (common.getValueByPath(fromObject, ['fileSearch']) !== undefined) {\n throw new Error('fileSearch parameter is not supported in Vertex AI.');\n }\n\n const fromCodeExecution = common.getValueByPath(fromObject, [\n 'codeExecution',\n ]);\n if (fromCodeExecution != null) {\n common.setValueByPath(toObject, ['codeExecution'], fromCodeExecution);\n }\n\n const fromEnterpriseWebSearch = common.getValueByPath(fromObject, [\n 'enterpriseWebSearch',\n ]);\n if (fromEnterpriseWebSearch != null) {\n common.setValueByPath(\n toObject,\n ['enterpriseWebSearch'],\n fromEnterpriseWebSearch,\n );\n }\n\n const fromFunctionDeclarations = common.getValueByPath(fromObject, [\n 'functionDeclarations',\n ]);\n if (fromFunctionDeclarations != null) {\n let transformedList = fromFunctionDeclarations;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return functionDeclarationToVertex(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['functionDeclarations'], transformedList);\n }\n\n const fromGoogleMaps = common.getValueByPath(fromObject, ['googleMaps']);\n if (fromGoogleMaps != null) {\n common.setValueByPath(toObject, ['googleMaps'], fromGoogleMaps);\n }\n\n const fromGoogleSearch = common.getValueByPath(fromObject, ['googleSearch']);\n if (fromGoogleSearch != null) {\n common.setValueByPath(toObject, ['googleSearch'], fromGoogleSearch);\n }\n\n const fromGoogleSearchRetrieval = common.getValueByPath(fromObject, [\n 'googleSearchRetrieval',\n ]);\n if (fromGoogleSearchRetrieval != null) {\n common.setValueByPath(\n toObject,\n ['googleSearchRetrieval'],\n fromGoogleSearchRetrieval,\n );\n }\n\n const fromUrlContext = common.getValueByPath(fromObject, ['urlContext']);\n if (fromUrlContext != null) {\n common.setValueByPath(toObject, ['urlContext'], fromUrlContext);\n }\n\n return toObject;\n}\n\nexport function tunedModelInfoFromMldev(\n fromObject: types.TunedModelInfo,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromBaseModel = common.getValueByPath(fromObject, ['baseModel']);\n if (fromBaseModel != null) {\n common.setValueByPath(toObject, ['baseModel'], fromBaseModel);\n }\n\n const fromCreateTime = common.getValueByPath(fromObject, ['createTime']);\n if (fromCreateTime != null) {\n common.setValueByPath(toObject, ['createTime'], fromCreateTime);\n }\n\n const fromUpdateTime = common.getValueByPath(fromObject, ['updateTime']);\n if (fromUpdateTime != null) {\n common.setValueByPath(toObject, ['updateTime'], fromUpdateTime);\n }\n\n return toObject;\n}\n\nexport function tunedModelInfoFromVertex(\n fromObject: types.TunedModelInfo,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromBaseModel = common.getValueByPath(fromObject, [\n 'labels',\n 'google-vertex-llm-tuning-base-model-id',\n ]);\n if (fromBaseModel != null) {\n common.setValueByPath(toObject, ['baseModel'], fromBaseModel);\n }\n\n const fromCreateTime = common.getValueByPath(fromObject, ['createTime']);\n if (fromCreateTime != null) {\n common.setValueByPath(toObject, ['createTime'], fromCreateTime);\n }\n\n const fromUpdateTime = common.getValueByPath(fromObject, ['updateTime']);\n if (fromUpdateTime != null) {\n common.setValueByPath(toObject, ['updateTime'], fromUpdateTime);\n }\n\n return toObject;\n}\n\nexport function updateModelConfigToMldev(\n fromObject: types.UpdateModelConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromDisplayName = common.getValueByPath(fromObject, ['displayName']);\n if (parentObject !== undefined && fromDisplayName != null) {\n common.setValueByPath(parentObject, ['displayName'], fromDisplayName);\n }\n\n const fromDescription = common.getValueByPath(fromObject, ['description']);\n if (parentObject !== undefined && fromDescription != null) {\n common.setValueByPath(parentObject, ['description'], fromDescription);\n }\n\n const fromDefaultCheckpointId = common.getValueByPath(fromObject, [\n 'defaultCheckpointId',\n ]);\n if (parentObject !== undefined && fromDefaultCheckpointId != null) {\n common.setValueByPath(\n parentObject,\n ['defaultCheckpointId'],\n fromDefaultCheckpointId,\n );\n }\n\n return toObject;\n}\n\nexport function updateModelConfigToVertex(\n fromObject: types.UpdateModelConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromDisplayName = common.getValueByPath(fromObject, ['displayName']);\n if (parentObject !== undefined && fromDisplayName != null) {\n common.setValueByPath(parentObject, ['displayName'], fromDisplayName);\n }\n\n const fromDescription = common.getValueByPath(fromObject, ['description']);\n if (parentObject !== undefined && fromDescription != null) {\n common.setValueByPath(parentObject, ['description'], fromDescription);\n }\n\n const fromDefaultCheckpointId = common.getValueByPath(fromObject, [\n 'defaultCheckpointId',\n ]);\n if (parentObject !== undefined && fromDefaultCheckpointId != null) {\n common.setValueByPath(\n parentObject,\n ['defaultCheckpointId'],\n fromDefaultCheckpointId,\n );\n }\n\n return toObject;\n}\n\nexport function updateModelParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.UpdateModelParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n updateModelConfigToMldev(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function updateModelParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.UpdateModelParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n updateModelConfigToVertex(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function upscaleImageAPIConfigInternalToVertex(\n fromObject: _internal_types.UpscaleImageAPIConfigInternal,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromOutputGcsUri = common.getValueByPath(fromObject, ['outputGcsUri']);\n if (parentObject !== undefined && fromOutputGcsUri != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'storageUri'],\n fromOutputGcsUri,\n );\n }\n\n const fromSafetyFilterLevel = common.getValueByPath(fromObject, [\n 'safetyFilterLevel',\n ]);\n if (parentObject !== undefined && fromSafetyFilterLevel != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'safetySetting'],\n fromSafetyFilterLevel,\n );\n }\n\n const fromPersonGeneration = common.getValueByPath(fromObject, [\n 'personGeneration',\n ]);\n if (parentObject !== undefined && fromPersonGeneration != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'personGeneration'],\n fromPersonGeneration,\n );\n }\n\n const fromIncludeRaiReason = common.getValueByPath(fromObject, [\n 'includeRaiReason',\n ]);\n if (parentObject !== undefined && fromIncludeRaiReason != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'includeRaiReason'],\n fromIncludeRaiReason,\n );\n }\n\n const fromOutputMimeType = common.getValueByPath(fromObject, [\n 'outputMimeType',\n ]);\n if (parentObject !== undefined && fromOutputMimeType != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'outputOptions', 'mimeType'],\n fromOutputMimeType,\n );\n }\n\n const fromOutputCompressionQuality = common.getValueByPath(fromObject, [\n 'outputCompressionQuality',\n ]);\n if (parentObject !== undefined && fromOutputCompressionQuality != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'outputOptions', 'compressionQuality'],\n fromOutputCompressionQuality,\n );\n }\n\n const fromEnhanceInputImage = common.getValueByPath(fromObject, [\n 'enhanceInputImage',\n ]);\n if (parentObject !== undefined && fromEnhanceInputImage != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'upscaleConfig', 'enhanceInputImage'],\n fromEnhanceInputImage,\n );\n }\n\n const fromImagePreservationFactor = common.getValueByPath(fromObject, [\n 'imagePreservationFactor',\n ]);\n if (parentObject !== undefined && fromImagePreservationFactor != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'upscaleConfig', 'imagePreservationFactor'],\n fromImagePreservationFactor,\n );\n }\n\n const fromLabels = common.getValueByPath(fromObject, ['labels']);\n if (parentObject !== undefined && fromLabels != null) {\n common.setValueByPath(parentObject, ['labels'], fromLabels);\n }\n\n const fromNumberOfImages = common.getValueByPath(fromObject, [\n 'numberOfImages',\n ]);\n if (parentObject !== undefined && fromNumberOfImages != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'sampleCount'],\n fromNumberOfImages,\n );\n }\n\n const fromMode = common.getValueByPath(fromObject, ['mode']);\n if (parentObject !== undefined && fromMode != null) {\n common.setValueByPath(parentObject, ['parameters', 'mode'], fromMode);\n }\n\n return toObject;\n}\n\nexport function upscaleImageAPIParametersInternalToVertex(\n apiClient: ApiClient,\n fromObject: _internal_types.UpscaleImageAPIParametersInternal,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromImage = common.getValueByPath(fromObject, ['image']);\n if (fromImage != null) {\n common.setValueByPath(\n toObject,\n ['instances[0]', 'image'],\n imageToVertex(fromImage, rootObject),\n );\n }\n\n const fromUpscaleFactor = common.getValueByPath(fromObject, [\n 'upscaleFactor',\n ]);\n if (fromUpscaleFactor != null) {\n common.setValueByPath(\n toObject,\n ['parameters', 'upscaleConfig', 'upscaleFactor'],\n fromUpscaleFactor,\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n upscaleImageAPIConfigInternalToVertex(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function upscaleImageResponseFromVertex(\n fromObject: types.UpscaleImageResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromGeneratedImages = common.getValueByPath(fromObject, [\n 'predictions',\n ]);\n if (fromGeneratedImages != null) {\n let transformedList = fromGeneratedImages;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return generatedImageFromVertex(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['generatedImages'], transformedList);\n }\n\n return toObject;\n}\n\nexport function videoFromMldev(\n fromObject: types.Video,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromUri = common.getValueByPath(fromObject, ['uri']);\n if (fromUri != null) {\n common.setValueByPath(toObject, ['uri'], fromUri);\n }\n\n const fromVideoBytes = common.getValueByPath(fromObject, ['encodedVideo']);\n if (fromVideoBytes != null) {\n common.setValueByPath(toObject, ['videoBytes'], t.tBytes(fromVideoBytes));\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['encoding']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function videoFromVertex(\n fromObject: types.Video,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromUri = common.getValueByPath(fromObject, ['gcsUri']);\n if (fromUri != null) {\n common.setValueByPath(toObject, ['uri'], fromUri);\n }\n\n const fromVideoBytes = common.getValueByPath(fromObject, [\n 'bytesBase64Encoded',\n ]);\n if (fromVideoBytes != null) {\n common.setValueByPath(toObject, ['videoBytes'], t.tBytes(fromVideoBytes));\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function videoGenerationMaskToVertex(\n fromObject: types.VideoGenerationMask,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromImage = common.getValueByPath(fromObject, ['image']);\n if (fromImage != null) {\n common.setValueByPath(\n toObject,\n ['_self'],\n imageToVertex(fromImage, rootObject),\n );\n }\n\n const fromMaskMode = common.getValueByPath(fromObject, ['maskMode']);\n if (fromMaskMode != null) {\n common.setValueByPath(toObject, ['maskMode'], fromMaskMode);\n }\n\n return toObject;\n}\n\nexport function videoGenerationReferenceImageToMldev(\n fromObject: types.VideoGenerationReferenceImage,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromImage = common.getValueByPath(fromObject, ['image']);\n if (fromImage != null) {\n common.setValueByPath(\n toObject,\n ['image'],\n imageToMldev(fromImage, rootObject),\n );\n }\n\n const fromReferenceType = common.getValueByPath(fromObject, [\n 'referenceType',\n ]);\n if (fromReferenceType != null) {\n common.setValueByPath(toObject, ['referenceType'], fromReferenceType);\n }\n\n return toObject;\n}\n\nexport function videoGenerationReferenceImageToVertex(\n fromObject: types.VideoGenerationReferenceImage,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromImage = common.getValueByPath(fromObject, ['image']);\n if (fromImage != null) {\n common.setValueByPath(\n toObject,\n ['image'],\n imageToVertex(fromImage, rootObject),\n );\n }\n\n const fromReferenceType = common.getValueByPath(fromObject, [\n 'referenceType',\n ]);\n if (fromReferenceType != null) {\n common.setValueByPath(toObject, ['referenceType'], fromReferenceType);\n }\n\n return toObject;\n}\n\nexport function videoToMldev(\n fromObject: types.Video,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromUri = common.getValueByPath(fromObject, ['uri']);\n if (fromUri != null) {\n common.setValueByPath(toObject, ['uri'], fromUri);\n }\n\n const fromVideoBytes = common.getValueByPath(fromObject, ['videoBytes']);\n if (fromVideoBytes != null) {\n common.setValueByPath(toObject, ['encodedVideo'], t.tBytes(fromVideoBytes));\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['encoding'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function videoToVertex(\n fromObject: types.Video,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromUri = common.getValueByPath(fromObject, ['uri']);\n if (fromUri != null) {\n common.setValueByPath(toObject, ['gcsUri'], fromUri);\n }\n\n const fromVideoBytes = common.getValueByPath(fromObject, ['videoBytes']);\n if (fromVideoBytes != null) {\n common.setValueByPath(\n toObject,\n ['bytesBase64Encoded'],\n t.tBytes(fromVideoBytes),\n );\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport * as common from '../_common.js';\nimport type * as types from '../types.js';\n\nexport function createFileSearchStoreConfigToMldev(\n fromObject: types.CreateFileSearchStoreConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromDisplayName = common.getValueByPath(fromObject, ['displayName']);\n if (parentObject !== undefined && fromDisplayName != null) {\n common.setValueByPath(parentObject, ['displayName'], fromDisplayName);\n }\n\n return toObject;\n}\n\nexport function createFileSearchStoreParametersToMldev(\n fromObject: types.CreateFileSearchStoreParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n createFileSearchStoreConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function deleteFileSearchStoreConfigToMldev(\n fromObject: types.DeleteFileSearchStoreConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromForce = common.getValueByPath(fromObject, ['force']);\n if (parentObject !== undefined && fromForce != null) {\n common.setValueByPath(parentObject, ['_query', 'force'], fromForce);\n }\n\n return toObject;\n}\n\nexport function deleteFileSearchStoreParametersToMldev(\n fromObject: types.DeleteFileSearchStoreParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['_url', 'name'], fromName);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n deleteFileSearchStoreConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function getFileSearchStoreParametersToMldev(\n fromObject: types.GetFileSearchStoreParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['_url', 'name'], fromName);\n }\n\n return toObject;\n}\n\nexport function importFileConfigToMldev(\n fromObject: types.ImportFileConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromCustomMetadata = common.getValueByPath(fromObject, [\n 'customMetadata',\n ]);\n if (parentObject !== undefined && fromCustomMetadata != null) {\n let transformedList = fromCustomMetadata;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(parentObject, ['customMetadata'], transformedList);\n }\n\n const fromChunkingConfig = common.getValueByPath(fromObject, [\n 'chunkingConfig',\n ]);\n if (parentObject !== undefined && fromChunkingConfig != null) {\n common.setValueByPath(parentObject, ['chunkingConfig'], fromChunkingConfig);\n }\n\n return toObject;\n}\n\nexport function importFileOperationFromMldev(\n fromObject: types.ImportFileOperation,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromMetadata = common.getValueByPath(fromObject, ['metadata']);\n if (fromMetadata != null) {\n common.setValueByPath(toObject, ['metadata'], fromMetadata);\n }\n\n const fromDone = common.getValueByPath(fromObject, ['done']);\n if (fromDone != null) {\n common.setValueByPath(toObject, ['done'], fromDone);\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n const fromResponse = common.getValueByPath(fromObject, ['response']);\n if (fromResponse != null) {\n common.setValueByPath(\n toObject,\n ['response'],\n importFileResponseFromMldev(fromResponse),\n );\n }\n\n return toObject;\n}\n\nexport function importFileParametersToMldev(\n fromObject: types.ImportFileParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromFileSearchStoreName = common.getValueByPath(fromObject, [\n 'fileSearchStoreName',\n ]);\n if (fromFileSearchStoreName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'file_search_store_name'],\n fromFileSearchStoreName,\n );\n }\n\n const fromFileName = common.getValueByPath(fromObject, ['fileName']);\n if (fromFileName != null) {\n common.setValueByPath(toObject, ['fileName'], fromFileName);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n importFileConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function importFileResponseFromMldev(\n fromObject: types.ImportFileResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromParent = common.getValueByPath(fromObject, ['parent']);\n if (fromParent != null) {\n common.setValueByPath(toObject, ['parent'], fromParent);\n }\n\n const fromDocumentName = common.getValueByPath(fromObject, ['documentName']);\n if (fromDocumentName != null) {\n common.setValueByPath(toObject, ['documentName'], fromDocumentName);\n }\n\n return toObject;\n}\n\nexport function listFileSearchStoresConfigToMldev(\n fromObject: types.ListFileSearchStoresConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPageSize = common.getValueByPath(fromObject, ['pageSize']);\n if (parentObject !== undefined && fromPageSize != null) {\n common.setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize);\n }\n\n const fromPageToken = common.getValueByPath(fromObject, ['pageToken']);\n if (parentObject !== undefined && fromPageToken != null) {\n common.setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken);\n }\n\n return toObject;\n}\n\nexport function listFileSearchStoresParametersToMldev(\n fromObject: types.ListFileSearchStoresParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n listFileSearchStoresConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function listFileSearchStoresResponseFromMldev(\n fromObject: types.ListFileSearchStoresResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromNextPageToken = common.getValueByPath(fromObject, [\n 'nextPageToken',\n ]);\n if (fromNextPageToken != null) {\n common.setValueByPath(toObject, ['nextPageToken'], fromNextPageToken);\n }\n\n const fromFileSearchStores = common.getValueByPath(fromObject, [\n 'fileSearchStores',\n ]);\n if (fromFileSearchStores != null) {\n let transformedList = fromFileSearchStores;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['fileSearchStores'], transformedList);\n }\n\n return toObject;\n}\n\nexport function uploadToFileSearchStoreConfigToMldev(\n fromObject: types.UploadToFileSearchStoreConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (parentObject !== undefined && fromMimeType != null) {\n common.setValueByPath(parentObject, ['mimeType'], fromMimeType);\n }\n\n const fromDisplayName = common.getValueByPath(fromObject, ['displayName']);\n if (parentObject !== undefined && fromDisplayName != null) {\n common.setValueByPath(parentObject, ['displayName'], fromDisplayName);\n }\n\n const fromCustomMetadata = common.getValueByPath(fromObject, [\n 'customMetadata',\n ]);\n if (parentObject !== undefined && fromCustomMetadata != null) {\n let transformedList = fromCustomMetadata;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(parentObject, ['customMetadata'], transformedList);\n }\n\n const fromChunkingConfig = common.getValueByPath(fromObject, [\n 'chunkingConfig',\n ]);\n if (parentObject !== undefined && fromChunkingConfig != null) {\n common.setValueByPath(parentObject, ['chunkingConfig'], fromChunkingConfig);\n }\n\n return toObject;\n}\n\nexport function uploadToFileSearchStoreParametersToMldev(\n fromObject: types.UploadToFileSearchStoreParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromFileSearchStoreName = common.getValueByPath(fromObject, [\n 'fileSearchStoreName',\n ]);\n if (fromFileSearchStoreName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'file_search_store_name'],\n fromFileSearchStoreName,\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n uploadToFileSearchStoreConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function uploadToFileSearchStoreResumableResponseFromMldev(\n fromObject: types.UploadToFileSearchStoreResumableResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n return toObject;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport pRetry, {AbortError} from 'p-retry';\nimport {Auth} from './_auth.js';\nimport * as common from './_common.js';\nimport {Downloader} from './_downloader.js';\nimport {Uploader} from './_uploader.js';\nimport {uploadToFileSearchStoreConfigToMldev} from './converters/_filesearchstores_converters.js';\nimport {ApiError} from './errors.js';\nimport {GeminiNextGenAPIClientAdapter} from './interactions/client-adapter.js';\nimport * as types from './types.js';\n\nconst CONTENT_TYPE_HEADER = 'Content-Type';\nconst SERVER_TIMEOUT_HEADER = 'X-Server-Timeout';\nconst USER_AGENT_HEADER = 'User-Agent';\nexport const GOOGLE_API_CLIENT_HEADER = 'x-goog-api-client';\nexport const SDK_VERSION = '1.41.0'; // x-release-please-version\nconst LIBRARY_LABEL = `google-genai-sdk/${SDK_VERSION}`;\nconst VERTEX_AI_API_DEFAULT_VERSION = 'v1beta1';\nconst GOOGLE_AI_API_DEFAULT_VERSION = 'v1beta';\n\n// Default retry options.\n// The config is based on https://cloud.google.com/storage/docs/retry-strategy.\nconst DEFAULT_RETRY_ATTEMPTS = 5; // Including the initial call\n// LINT.IfChange\nconst DEFAULT_RETRY_HTTP_STATUS_CODES = [\n 408, // Request timeout\n 429, // Too many requests\n 500, // Internal server error\n 502, // Bad gateway\n 503, // Service unavailable\n 504, // Gateway timeout\n];\n// LINT.ThenChange(//depot/google3/third_party/py/google/genai/_api_client.py)\n\n/**\n * Options for initializing the ApiClient. The ApiClient uses the parameters\n * for authentication purposes as well as to infer if SDK should send the\n * request to Vertex AI or Gemini API.\n */\nexport interface ApiClientInitOptions {\n /**\n * The object used for adding authentication headers to API requests.\n */\n auth: Auth;\n /**\n * The uploader to use for uploading files. This field is required for\n * creating a client, will be set through the Node_client or Web_client.\n */\n uploader: Uploader;\n /**\n * Optional. The downloader to use for downloading files. This field is\n * required for creating a client, will be set through the Node_client or\n * Web_client.\n */\n downloader: Downloader;\n /**\n * Optional. The Google Cloud project ID for Vertex AI users.\n * It is not the numeric project name.\n * If not provided, SDK will try to resolve it from runtime environment.\n */\n project?: string;\n /**\n * Optional. The Google Cloud project location for Vertex AI users.\n * If not provided, SDK will try to resolve it from runtime environment.\n */\n location?: string;\n /**\n * The API Key. This is required for Gemini API users.\n */\n apiKey?: string;\n /**\n * Optional. Set to true if you intend to call Vertex AI endpoints.\n * If unset, default SDK behavior is to call Gemini API.\n */\n vertexai?: boolean;\n /**\n * Optional. The API version for the endpoint.\n * If unset, SDK will choose a default api version.\n */\n apiVersion?: string;\n /**\n * Optional. A set of customizable configuration for HTTP requests.\n */\n httpOptions?: types.HttpOptions;\n /**\n * Optional. An extra string to append at the end of the User-Agent header.\n *\n * This can be used to e.g specify the runtime and its version.\n */\n userAgentExtra?: string;\n}\n\n/**\n * Represents the necessary information to send a request to an API endpoint.\n * This interface defines the structure for constructing and executing HTTP\n * requests.\n */\nexport interface HttpRequest {\n /**\n * URL path from the modules, this path is appended to the base API URL to\n * form the complete request URL.\n *\n * If you wish to set full URL, use httpOptions.baseUrl instead. Example to\n * set full URL in the request:\n *\n * const request: HttpRequest = {\n * path: '',\n * httpOptions: {\n * baseUrl: 'https://<custom-full-url>',\n * apiVersion: '',\n * },\n * httpMethod: 'GET',\n * };\n *\n * The result URL will be: https://<custom-full-url>\n *\n */\n path: string;\n /**\n * Optional query parameters to be appended to the request URL.\n */\n queryParams?: Record<string, string>;\n /**\n * Optional request body in json string or Blob format, GET request doesn't\n * need a request body.\n */\n body?: string | Blob;\n /**\n * The HTTP method to be used for the request.\n */\n httpMethod: 'GET' | 'POST' | 'PATCH' | 'DELETE';\n /**\n * Optional set of customizable configuration for HTTP requests.\n */\n httpOptions?: types.HttpOptions;\n /**\n * Optional abort signal which can be used to cancel the request.\n */\n abortSignal?: AbortSignal;\n}\n\n/**\n * The ApiClient class is used to send requests to the Gemini API or Vertex AI\n * endpoints.\n */\nexport class ApiClient implements GeminiNextGenAPIClientAdapter {\n readonly clientOptions: ApiClientInitOptions;\n private readonly customBaseUrl?: string;\n constructor(opts: ApiClientInitOptions) {\n this.clientOptions = {\n ...opts,\n };\n\n this.customBaseUrl = opts.httpOptions?.baseUrl;\n\n if (this.clientOptions.vertexai) {\n if (this.clientOptions.project && this.clientOptions.location) {\n this.clientOptions.apiKey = undefined;\n } else if (this.clientOptions.apiKey) {\n this.clientOptions.project = undefined;\n this.clientOptions.location = undefined;\n }\n }\n\n const initHttpOptions: types.HttpOptions = {};\n\n if (this.clientOptions.vertexai) {\n if (\n !this.clientOptions.location &&\n !this.clientOptions.apiKey &&\n !this.customBaseUrl\n ) {\n this.clientOptions.location = 'global';\n }\n\n const hasSufficientAuth =\n (this.clientOptions.project && this.clientOptions.location) ||\n this.clientOptions.apiKey;\n\n if (!hasSufficientAuth && !this.customBaseUrl) {\n throw new Error(\n 'Authentication is not set up. Please provide either a project and location, or an API key, or a custom base URL.',\n );\n }\n\n const hasConstructorAuth =\n (opts.project && opts.location) || !!opts.apiKey;\n\n if (this.customBaseUrl && !hasConstructorAuth) {\n initHttpOptions.baseUrl = this.customBaseUrl;\n this.clientOptions.project = undefined;\n this.clientOptions.location = undefined;\n } else if (\n this.clientOptions.apiKey ||\n this.clientOptions.location === 'global'\n ) {\n // Vertex Express or global endpoint case.\n initHttpOptions.baseUrl = 'https://aiplatform.googleapis.com/';\n } else if (this.clientOptions.project && this.clientOptions.location) {\n initHttpOptions.baseUrl = `https://${this.clientOptions.location}-aiplatform.googleapis.com/`;\n }\n\n initHttpOptions.apiVersion =\n this.clientOptions.apiVersion ?? VERTEX_AI_API_DEFAULT_VERSION;\n } else {\n // Gemini API\n if (!this.clientOptions.apiKey) {\n throw new ApiError({\n message: 'API key must be set when using the Gemini API.',\n status: 403,\n });\n }\n initHttpOptions.apiVersion =\n this.clientOptions.apiVersion ?? GOOGLE_AI_API_DEFAULT_VERSION;\n initHttpOptions.baseUrl = `https://generativelanguage.googleapis.com/`;\n }\n\n initHttpOptions.headers = this.getDefaultHeaders();\n\n this.clientOptions.httpOptions = initHttpOptions;\n\n if (opts.httpOptions) {\n this.clientOptions.httpOptions = this.patchHttpOptions(\n initHttpOptions,\n opts.httpOptions,\n );\n }\n }\n\n isVertexAI(): boolean {\n return this.clientOptions.vertexai ?? false;\n }\n\n getProject() {\n return this.clientOptions.project;\n }\n\n getLocation() {\n return this.clientOptions.location;\n }\n\n getCustomBaseUrl(): string | undefined {\n return this.customBaseUrl;\n }\n\n async getAuthHeaders(): Promise<Headers> {\n const headers = new Headers();\n await this.clientOptions.auth.addAuthHeaders(headers);\n return headers;\n }\n\n getApiVersion() {\n if (\n this.clientOptions.httpOptions &&\n this.clientOptions.httpOptions.apiVersion !== undefined\n ) {\n return this.clientOptions.httpOptions.apiVersion;\n }\n throw new Error('API version is not set.');\n }\n\n getBaseUrl() {\n if (\n this.clientOptions.httpOptions &&\n this.clientOptions.httpOptions.baseUrl !== undefined\n ) {\n return this.clientOptions.httpOptions.baseUrl;\n }\n throw new Error('Base URL is not set.');\n }\n\n getRequestUrl() {\n return this.getRequestUrlInternal(this.clientOptions.httpOptions);\n }\n\n getHeaders() {\n if (\n this.clientOptions.httpOptions &&\n this.clientOptions.httpOptions.headers !== undefined\n ) {\n return this.clientOptions.httpOptions.headers;\n } else {\n throw new Error('Headers are not set.');\n }\n }\n\n private getRequestUrlInternal(httpOptions?: types.HttpOptions) {\n if (\n !httpOptions ||\n httpOptions.baseUrl === undefined ||\n httpOptions.apiVersion === undefined\n ) {\n throw new Error('HTTP options are not correctly set.');\n }\n const baseUrl = httpOptions.baseUrl.endsWith('/')\n ? httpOptions.baseUrl.slice(0, -1)\n : httpOptions.baseUrl;\n const urlElement: Array<string> = [baseUrl];\n if (httpOptions.apiVersion && httpOptions.apiVersion !== '') {\n urlElement.push(httpOptions.apiVersion);\n }\n return urlElement.join('/');\n }\n\n getBaseResourcePath() {\n return `projects/${this.clientOptions.project}/locations/${\n this.clientOptions.location\n }`;\n }\n\n getApiKey() {\n return this.clientOptions.apiKey;\n }\n\n getWebsocketBaseUrl() {\n const baseUrl = this.getBaseUrl();\n const urlParts = new URL(baseUrl);\n urlParts.protocol = urlParts.protocol == 'http:' ? 'ws' : 'wss';\n return urlParts.toString();\n }\n\n setBaseUrl(url: string) {\n if (this.clientOptions.httpOptions) {\n this.clientOptions.httpOptions.baseUrl = url;\n } else {\n throw new Error('HTTP options are not correctly set.');\n }\n }\n\n private constructUrl(\n path: string,\n httpOptions: types.HttpOptions,\n prependProjectLocation: boolean,\n ): URL {\n const urlElement: Array<string> = [this.getRequestUrlInternal(httpOptions)];\n if (prependProjectLocation) {\n urlElement.push(this.getBaseResourcePath());\n }\n if (path !== '') {\n urlElement.push(path);\n }\n const url = new URL(`${urlElement.join('/')}`);\n\n return url;\n }\n\n private shouldPrependVertexProjectPath(\n request: HttpRequest,\n httpOptions: types.HttpOptions,\n ): boolean {\n if (\n httpOptions.baseUrl &&\n httpOptions.baseUrlResourceScope === types.ResourceScope.COLLECTION\n ) {\n return false;\n }\n if (this.clientOptions.apiKey) {\n return false;\n }\n if (!this.clientOptions.vertexai) {\n return false;\n }\n if (request.path.startsWith('projects/')) {\n // Assume the path already starts with\n // `projects/<project>/location/<location>`.\n return false;\n }\n if (\n request.httpMethod === 'GET' &&\n request.path.startsWith('publishers/google/models')\n ) {\n // These paths are used by Vertex's models.get and models.list\n // calls. For base models Vertex does not accept a project/location\n // prefix (for tuned model the prefix is required).\n return false;\n }\n return true;\n }\n\n async request(request: HttpRequest): Promise<types.HttpResponse> {\n let patchedHttpOptions = this.clientOptions.httpOptions!;\n if (request.httpOptions) {\n patchedHttpOptions = this.patchHttpOptions(\n this.clientOptions.httpOptions!,\n request.httpOptions,\n );\n }\n\n const prependProjectLocation = this.shouldPrependVertexProjectPath(\n request,\n patchedHttpOptions,\n );\n const url = this.constructUrl(\n request.path,\n patchedHttpOptions,\n prependProjectLocation,\n );\n if (request.queryParams) {\n for (const [key, value] of Object.entries(request.queryParams)) {\n url.searchParams.append(key, String(value));\n }\n }\n let requestInit: RequestInit = {};\n if (request.httpMethod === 'GET') {\n if (request.body && request.body !== '{}') {\n throw new Error(\n 'Request body should be empty for GET request, but got non empty request body',\n );\n }\n } else {\n requestInit.body = request.body;\n }\n requestInit = await this.includeExtraHttpOptionsToRequestInit(\n requestInit,\n patchedHttpOptions,\n url.toString(),\n request.abortSignal,\n );\n return this.unaryApiCall(url, requestInit, request.httpMethod);\n }\n\n private patchHttpOptions(\n baseHttpOptions: types.HttpOptions,\n requestHttpOptions: types.HttpOptions,\n ): types.HttpOptions {\n const patchedHttpOptions = JSON.parse(\n JSON.stringify(baseHttpOptions),\n ) as types.HttpOptions;\n\n for (const [key, value] of Object.entries(requestHttpOptions)) {\n // Records compile to objects.\n if (typeof value === 'object') {\n // @ts-expect-error TS2345TS7053: Element implicitly has an 'any' type\n // because expression of type 'string' can't be used to index type\n // 'HttpOptions'.\n patchedHttpOptions[key] = {...patchedHttpOptions[key], ...value};\n } else if (value !== undefined) {\n // @ts-expect-error TS2345TS7053: Element implicitly has an 'any' type\n // because expression of type 'string' can't be used to index type\n // 'HttpOptions'.\n patchedHttpOptions[key] = value;\n }\n }\n return patchedHttpOptions;\n }\n\n async requestStream(\n request: HttpRequest,\n ): Promise<AsyncGenerator<types.HttpResponse>> {\n let patchedHttpOptions = this.clientOptions.httpOptions!;\n if (request.httpOptions) {\n patchedHttpOptions = this.patchHttpOptions(\n this.clientOptions.httpOptions!,\n request.httpOptions,\n );\n }\n\n const prependProjectLocation = this.shouldPrependVertexProjectPath(\n request,\n patchedHttpOptions,\n );\n const url = this.constructUrl(\n request.path,\n patchedHttpOptions,\n prependProjectLocation,\n );\n if (!url.searchParams.has('alt') || url.searchParams.get('alt') !== 'sse') {\n url.searchParams.set('alt', 'sse');\n }\n let requestInit: RequestInit = {};\n requestInit.body = request.body;\n requestInit = await this.includeExtraHttpOptionsToRequestInit(\n requestInit,\n patchedHttpOptions,\n url.toString(),\n request.abortSignal,\n );\n return this.streamApiCall(url, requestInit, request.httpMethod);\n }\n\n private async includeExtraHttpOptionsToRequestInit(\n requestInit: RequestInit,\n httpOptions: types.HttpOptions,\n url: string,\n abortSignal?: AbortSignal,\n ): Promise<RequestInit> {\n if ((httpOptions && httpOptions.timeout) || abortSignal) {\n const abortController = new AbortController();\n const signal = abortController.signal;\n if (httpOptions.timeout && httpOptions?.timeout > 0) {\n const timeoutHandle = setTimeout(\n () => abortController.abort(),\n httpOptions.timeout,\n );\n if (\n timeoutHandle &&\n typeof (timeoutHandle as unknown as NodeJS.Timeout).unref ===\n 'function'\n ) {\n // call unref to prevent nodejs process from hanging, see\n // https://nodejs.org/api/timers.html#timeoutunref\n timeoutHandle.unref();\n }\n }\n if (abortSignal) {\n abortSignal.addEventListener('abort', () => {\n abortController.abort();\n });\n }\n requestInit.signal = signal;\n }\n if (httpOptions && httpOptions.extraBody !== null) {\n includeExtraBodyToRequestInit(\n requestInit,\n httpOptions.extraBody as Record<string, unknown>,\n );\n }\n requestInit.headers = await this.getHeadersInternal(httpOptions, url);\n return requestInit;\n }\n\n private async unaryApiCall(\n url: URL,\n requestInit: RequestInit,\n httpMethod: 'GET' | 'POST' | 'PATCH' | 'DELETE',\n ): Promise<types.HttpResponse> {\n return this.apiCall(url.toString(), {\n ...requestInit,\n method: httpMethod,\n })\n .then(async (response) => {\n await throwErrorIfNotOK(response);\n return new types.HttpResponse(response);\n })\n .catch((e) => {\n if (e instanceof Error) {\n throw e;\n } else {\n throw new Error(JSON.stringify(e));\n }\n });\n }\n\n private async streamApiCall(\n url: URL,\n requestInit: RequestInit,\n httpMethod: 'GET' | 'POST' | 'PATCH' | 'DELETE',\n ): Promise<AsyncGenerator<types.HttpResponse>> {\n return this.apiCall(url.toString(), {\n ...requestInit,\n method: httpMethod,\n })\n .then(async (response) => {\n await throwErrorIfNotOK(response);\n return this.processStreamResponse(response);\n })\n .catch((e) => {\n if (e instanceof Error) {\n throw e;\n } else {\n throw new Error(JSON.stringify(e));\n }\n });\n }\n\n async *processStreamResponse(\n response: Response,\n ): AsyncGenerator<types.HttpResponse> {\n const reader = response?.body?.getReader();\n const decoder = new TextDecoder('utf-8');\n if (!reader) {\n throw new Error('Response body is empty');\n }\n\n try {\n let buffer = '';\n const dataPrefix = 'data:';\n const delimiters = ['\\n\\n', '\\r\\r', '\\r\\n\\r\\n'];\n\n while (true) {\n const {done, value} = await reader.read();\n if (done) {\n if (buffer.trim().length > 0) {\n throw new Error('Incomplete JSON segment at the end');\n }\n break;\n }\n const chunkString = decoder.decode(value, {stream: true});\n\n // Parse and throw an error if the chunk contains an error.\n try {\n const chunkJson = JSON.parse(chunkString) as Record<string, unknown>;\n if ('error' in chunkJson) {\n const errorJson = JSON.parse(\n JSON.stringify(chunkJson['error']),\n ) as Record<string, unknown>;\n const status = errorJson['status'] as string;\n const code = errorJson['code'] as number;\n const errorMessage = `got status: ${status}. ${JSON.stringify(\n chunkJson,\n )}`;\n if (code >= 400 && code < 600) {\n const apiError = new ApiError({\n message: errorMessage,\n status: code,\n });\n throw apiError;\n }\n }\n } catch (e: unknown) {\n const error = e as Error;\n if (error.name === 'ApiError') {\n throw e;\n }\n }\n buffer += chunkString;\n\n let delimiterIndex = -1;\n let delimiterLength = 0;\n\n while (true) {\n delimiterIndex = -1;\n delimiterLength = 0;\n\n for (const delimiter of delimiters) {\n const index = buffer.indexOf(delimiter);\n if (\n index !== -1 &&\n (delimiterIndex === -1 || index < delimiterIndex)\n ) {\n delimiterIndex = index;\n delimiterLength = delimiter.length;\n }\n }\n\n if (delimiterIndex === -1) {\n break; // No complete event in buffer\n }\n\n const eventString = buffer.substring(0, delimiterIndex);\n buffer = buffer.substring(delimiterIndex + delimiterLength);\n\n const trimmedEvent = eventString.trim();\n\n if (trimmedEvent.startsWith(dataPrefix)) {\n const processedChunkString = trimmedEvent\n .substring(dataPrefix.length)\n .trim();\n try {\n const partialResponse = new Response(processedChunkString, {\n headers: response?.headers,\n status: response?.status,\n statusText: response?.statusText,\n });\n yield new types.HttpResponse(partialResponse);\n } catch (e) {\n throw new Error(\n `exception parsing stream chunk ${processedChunkString}. ${e}`,\n );\n }\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n }\n private async apiCall(\n url: string,\n requestInit: RequestInit,\n ): Promise<Response> {\n if (\n !this.clientOptions.httpOptions ||\n !this.clientOptions.httpOptions.retryOptions\n ) {\n return fetch(url, requestInit);\n }\n\n const retryOptions = this.clientOptions.httpOptions.retryOptions;\n const runFetch = async () => {\n const response = await fetch(url, requestInit);\n\n if (response.ok) {\n return response;\n }\n\n if (DEFAULT_RETRY_HTTP_STATUS_CODES.includes(response.status)) {\n throw new Error(`Retryable HTTP Error: ${response.statusText}`);\n }\n\n throw new AbortError(\n `Non-retryable exception ${response.statusText} sending request`,\n );\n };\n\n return pRetry(runFetch, {\n // Retry attempts is one less than the number of total attempts.\n retries: (retryOptions.attempts ?? DEFAULT_RETRY_ATTEMPTS) - 1,\n });\n }\n\n getDefaultHeaders(): Record<string, string> {\n const headers: Record<string, string> = {};\n\n const versionHeaderValue =\n LIBRARY_LABEL + ' ' + this.clientOptions.userAgentExtra;\n\n headers[USER_AGENT_HEADER] = versionHeaderValue;\n headers[GOOGLE_API_CLIENT_HEADER] = versionHeaderValue;\n headers[CONTENT_TYPE_HEADER] = 'application/json';\n\n return headers;\n }\n\n private async getHeadersInternal(\n httpOptions: types.HttpOptions | undefined,\n url: string,\n ): Promise<Headers> {\n const headers = new Headers();\n if (httpOptions && httpOptions.headers) {\n for (const [key, value] of Object.entries(httpOptions.headers)) {\n headers.append(key, value);\n }\n // Append a timeout header if it is set, note that the timeout option is\n // in milliseconds but the header is in seconds.\n if (httpOptions.timeout && httpOptions.timeout > 0) {\n headers.append(\n SERVER_TIMEOUT_HEADER,\n String(Math.ceil(httpOptions.timeout / 1000)),\n );\n }\n }\n await this.clientOptions.auth.addAuthHeaders(headers, url);\n return headers;\n }\n\n private getFileName(file: string | Blob): string {\n let fileName: string = '';\n if (typeof file === 'string') {\n fileName = file.replace(/[/\\\\]+$/, '');\n fileName = fileName.split(/[/\\\\]/).pop() ?? '';\n }\n return fileName;\n }\n\n /**\n * Uploads a file asynchronously using Gemini API only, this is not supported\n * in Vertex AI.\n *\n * @param file The string path to the file to be uploaded or a Blob object.\n * @param config Optional parameters specified in the `UploadFileConfig`\n * interface. @see {@link types.UploadFileConfig}\n * @return A promise that resolves to a `File` object.\n * @throws An error if called on a Vertex AI client.\n * @throws An error if the `mimeType` is not provided and can not be inferred,\n */\n async uploadFile(\n file: string | Blob,\n config?: types.UploadFileConfig,\n ): Promise<types.File> {\n const fileToUpload: types.File = {};\n if (config != null) {\n fileToUpload.mimeType = config.mimeType;\n fileToUpload.name = config.name;\n fileToUpload.displayName = config.displayName;\n }\n\n if (fileToUpload.name && !fileToUpload.name.startsWith('files/')) {\n fileToUpload.name = `files/${fileToUpload.name}`;\n }\n\n const uploader = this.clientOptions.uploader;\n const fileStat = await uploader.stat(file);\n fileToUpload.sizeBytes = String(fileStat.size);\n const mimeType = config?.mimeType ?? fileStat.type;\n if (mimeType === undefined || mimeType === '') {\n throw new Error(\n 'Can not determine mimeType. Please provide mimeType in the config.',\n );\n }\n fileToUpload.mimeType = mimeType;\n const body: Record<string, unknown> = {\n file: fileToUpload,\n };\n const fileName = this.getFileName(file);\n const path = common.formatMap(\n 'upload/v1beta/files',\n body['_url'] as Record<string, unknown>,\n );\n const uploadUrl = await this.fetchUploadUrl(\n path,\n fileToUpload.sizeBytes,\n fileToUpload.mimeType,\n fileName,\n body,\n config?.httpOptions,\n );\n return uploader.upload(file, uploadUrl, this);\n }\n\n /**\n * Uploads a file to a given file search store asynchronously using Gemini API only, this is not supported\n * in Vertex AI.\n *\n * @param fileSearchStoreName The name of the file search store to upload the file to.\n * @param file The string path to the file to be uploaded or a Blob object.\n * @param config Optional parameters specified in the `UploadFileConfig`\n * interface. @see {@link UploadFileConfig}\n * @return A promise that resolves to a `File` object.\n * @throws An error if called on a Vertex AI client.\n * @throws An error if the `mimeType` is not provided and can not be inferred,\n */\n async uploadFileToFileSearchStore(\n fileSearchStoreName: string,\n file: string | Blob,\n config?: types.UploadToFileSearchStoreConfig,\n ): Promise<types.UploadToFileSearchStoreOperation> {\n const uploader = this.clientOptions.uploader;\n const fileStat = await uploader.stat(file);\n const sizeBytes = String(fileStat.size);\n const mimeType = config?.mimeType ?? fileStat.type;\n if (mimeType === undefined || mimeType === '') {\n throw new Error(\n 'Can not determine mimeType. Please provide mimeType in the config.',\n );\n }\n const path = `upload/v1beta/${fileSearchStoreName}:uploadToFileSearchStore`;\n const fileName = this.getFileName(file);\n const body: Record<string, unknown> = {};\n if (config != null) {\n uploadToFileSearchStoreConfigToMldev(config, body);\n }\n const uploadUrl = await this.fetchUploadUrl(\n path,\n sizeBytes,\n mimeType,\n fileName,\n body,\n config?.httpOptions,\n );\n return uploader.uploadToFileSearchStore(file, uploadUrl, this);\n }\n\n /**\n * Downloads a file asynchronously to the specified path.\n *\n * @params params - The parameters for the download request, see {@link\n * types.DownloadFileParameters}\n */\n async downloadFile(params: types.DownloadFileParameters): Promise<void> {\n const downloader = this.clientOptions.downloader;\n await downloader.download(params, this);\n }\n\n private async fetchUploadUrl(\n path: string,\n sizeBytes: string,\n mimeType: string,\n fileName: string,\n body: Record<string, unknown>,\n configHttpOptions?: types.HttpOptions,\n ): Promise<string> {\n let httpOptions: types.HttpOptions = {};\n if (configHttpOptions) {\n httpOptions = configHttpOptions;\n } else {\n httpOptions = {\n apiVersion: '', // api-version is set in the path.\n headers: {\n 'Content-Type': 'application/json',\n 'X-Goog-Upload-Protocol': 'resumable',\n 'X-Goog-Upload-Command': 'start',\n 'X-Goog-Upload-Header-Content-Length': `${sizeBytes}`,\n 'X-Goog-Upload-Header-Content-Type': `${mimeType}`,\n ...(fileName ? {'X-Goog-Upload-File-Name': fileName} : {}),\n },\n };\n }\n\n const httpResponse = await this.request({\n path,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions,\n });\n\n if (!httpResponse || !httpResponse?.headers) {\n throw new Error(\n 'Server did not return an HttpResponse or the returned HttpResponse did not have headers.',\n );\n }\n\n const uploadUrl: string | undefined =\n httpResponse?.headers?.['x-goog-upload-url'];\n if (uploadUrl === undefined) {\n throw new Error(\n 'Failed to get upload url. Server did not return the x-google-upload-url in the headers',\n );\n }\n return uploadUrl;\n }\n}\n\nasync function throwErrorIfNotOK(response: Response | undefined) {\n if (response === undefined) {\n throw new Error('response is undefined');\n }\n if (!response.ok) {\n const status: number = response.status;\n let errorBody: Record<string, unknown>;\n if (response.headers.get('content-type')?.includes('application/json')) {\n errorBody = await response.json();\n } else {\n errorBody = {\n error: {\n message: await response.text(),\n code: response.status,\n status: response.statusText,\n },\n };\n }\n const errorMessage = JSON.stringify(errorBody);\n if (status >= 400 && status < 600) {\n const apiError = new ApiError({\n message: errorMessage,\n status: status,\n });\n throw apiError;\n }\n throw new Error(errorMessage);\n }\n}\n\n/**\n * Recursively updates the `requestInit.body` with values from an `extraBody` object.\n *\n * If `requestInit.body` is a string, it's assumed to be JSON and will be parsed.\n * The `extraBody` is then deeply merged into this parsed object.\n * If `requestInit.body` is a Blob, `extraBody` will be ignored, and a warning logged,\n * as merging structured data into an opaque Blob is not supported.\n *\n * The function does not enforce that updated values from `extraBody` have the\n * same type as existing values in `requestInit.body`. Type mismatches during\n * the merge will result in a warning, but the value from `extraBody` will overwrite\n * the original. `extraBody` users are responsible for ensuring `extraBody` has the correct structure.\n *\n * @param requestInit The RequestInit object whose body will be updated.\n * @param extraBody The object containing updates to be merged into `requestInit.body`.\n */\nexport function includeExtraBodyToRequestInit(\n requestInit: RequestInit,\n extraBody: Record<string, unknown>,\n) {\n if (!extraBody || Object.keys(extraBody).length === 0) {\n return;\n }\n\n if (requestInit.body instanceof Blob) {\n console.warn(\n 'includeExtraBodyToRequestInit: extraBody provided but current request body is a Blob. extraBody will be ignored as merging is not supported for Blob bodies.',\n );\n return;\n }\n\n let currentBodyObject: Record<string, unknown> = {};\n\n // If adding new type to HttpRequest.body, please check the code below to\n // see if we need to update the logic.\n if (typeof requestInit.body === 'string' && requestInit.body.length > 0) {\n try {\n const parsedBody = JSON.parse(requestInit.body);\n if (\n typeof parsedBody === 'object' &&\n parsedBody !== null &&\n !Array.isArray(parsedBody)\n ) {\n currentBodyObject = parsedBody as Record<string, unknown>;\n } else {\n console.warn(\n 'includeExtraBodyToRequestInit: Original request body is valid JSON but not a non-array object. Skip applying extraBody to the request body.',\n );\n return;\n }\n /* eslint-disable-next-line @typescript-eslint/no-unused-vars */\n } catch (e) {\n console.warn(\n 'includeExtraBodyToRequestInit: Original request body is not valid JSON. Skip applying extraBody to the request body.',\n );\n return;\n }\n }\n\n function deepMerge(\n target: Record<string, unknown>,\n source: Record<string, unknown>,\n ): Record<string, unknown> {\n const output = {...target};\n for (const key in source) {\n if (Object.prototype.hasOwnProperty.call(source, key)) {\n const sourceValue = source[key];\n const targetValue = output[key];\n if (\n sourceValue &&\n typeof sourceValue === 'object' &&\n !Array.isArray(sourceValue) &&\n targetValue &&\n typeof targetValue === 'object' &&\n !Array.isArray(targetValue)\n ) {\n output[key] = deepMerge(\n targetValue as Record<string, unknown>,\n sourceValue as Record<string, unknown>,\n );\n } else {\n if (\n targetValue &&\n sourceValue &&\n typeof targetValue !== typeof sourceValue\n ) {\n console.warn(\n `includeExtraBodyToRequestInit:deepMerge: Type mismatch for key \"${key}\". Original type: ${typeof targetValue}, New type: ${typeof sourceValue}. Overwriting.`,\n );\n }\n output[key] = sourceValue;\n }\n }\n }\n return output;\n }\n\n const mergedBody = deepMerge(currentBodyObject, extraBody);\n requestInit.body = JSON.stringify(mergedBody);\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type {Client as McpClient} from '@modelcontextprotocol/sdk/client/index.js';\nimport type {Tool as McpTool} from '@modelcontextprotocol/sdk/types.js';\n\nimport {GOOGLE_API_CLIENT_HEADER} from '../_api_client.js';\nimport {mcpToolsToGeminiTool} from '../_transformers.js';\nimport {\n CallableTool,\n CallableToolConfig,\n FunctionCall,\n Part,\n Tool,\n ToolListUnion,\n} from '../types.js';\n\n// TODO: b/416041229 - Determine how to retrieve the MCP package version.\nexport const MCP_LABEL = 'mcp_used/unknown';\n\n// Whether MCP tool usage is detected from mcpToTool. This is used for\n// telemetry.\nlet hasMcpToolUsageFromMcpToTool = false;\n\n// Checks whether the list of tools contains any MCP tools.\nexport function hasMcpToolUsage(tools: ToolListUnion): boolean {\n for (const tool of tools) {\n if (isMcpCallableTool(tool)) {\n return true;\n }\n if (typeof tool === 'object' && 'inputSchema' in tool) {\n return true;\n }\n }\n\n return hasMcpToolUsageFromMcpToTool;\n}\n\n// Sets the MCP version label in the Google API client header.\nexport function setMcpUsageHeader(headers: Record<string, string>) {\n const existingHeader = headers[GOOGLE_API_CLIENT_HEADER] ?? '';\n headers[GOOGLE_API_CLIENT_HEADER] = (\n existingHeader + ` ${MCP_LABEL}`\n ).trimStart();\n}\n\n// Returns true if the object is a MCP CallableTool, otherwise false.\nfunction isMcpCallableTool(object: unknown): boolean {\n return (\n object !== null &&\n typeof object === 'object' &&\n object instanceof McpCallableTool\n );\n}\n\n// List all tools from the MCP client.\nasync function* listAllTools(\n mcpClient: McpClient,\n maxTools: number = 100,\n): AsyncGenerator<McpTool> {\n let cursor: string | undefined = undefined;\n let numTools = 0;\n while (numTools < maxTools) {\n const t = await mcpClient.listTools({cursor});\n for (const tool of t.tools) {\n yield tool;\n numTools++;\n }\n if (!t.nextCursor) {\n break;\n }\n cursor = t.nextCursor;\n }\n}\n\n/**\n * McpCallableTool can be used for model inference and invoking MCP clients with\n * given function call arguments.\n *\n * @experimental Built-in MCP support is an experimental feature, may change in future\n * versions.\n */\nexport class McpCallableTool implements CallableTool {\n private readonly mcpClients;\n private mcpTools: McpTool[] = [];\n private functionNameToMcpClient: Record<string, McpClient> = {};\n private readonly config: CallableToolConfig;\n\n private constructor(\n mcpClients: McpClient[] = [],\n config: CallableToolConfig,\n ) {\n this.mcpClients = mcpClients;\n this.config = config;\n }\n\n /**\n * Creates a McpCallableTool.\n */\n public static create(\n mcpClients: McpClient[],\n config: CallableToolConfig,\n ): McpCallableTool {\n return new McpCallableTool(mcpClients, config);\n }\n\n /**\n * Validates the function names are not duplicate and initialize the function\n * name to MCP client mapping.\n *\n * @throws {Error} if the MCP tools from the MCP clients have duplicate tool\n * names.\n */\n async initialize() {\n if (this.mcpTools.length > 0) {\n return;\n }\n\n const functionMap: Record<string, McpClient> = {};\n const mcpTools: McpTool[] = [];\n for (const mcpClient of this.mcpClients) {\n for await (const mcpTool of listAllTools(mcpClient)) {\n mcpTools.push(mcpTool);\n const mcpToolName = mcpTool.name as string;\n if (functionMap[mcpToolName]) {\n throw new Error(\n `Duplicate function name ${\n mcpToolName\n } found in MCP tools. Please ensure function names are unique.`,\n );\n }\n functionMap[mcpToolName] = mcpClient;\n }\n }\n this.mcpTools = mcpTools;\n this.functionNameToMcpClient = functionMap;\n }\n\n public async tool(): Promise<Tool> {\n await this.initialize();\n return mcpToolsToGeminiTool(this.mcpTools, this.config);\n }\n\n public async callTool(functionCalls: FunctionCall[]): Promise<Part[]> {\n await this.initialize();\n const functionCallResponseParts: Part[] = [];\n for (const functionCall of functionCalls) {\n if (functionCall.name! in this.functionNameToMcpClient) {\n const mcpClient = this.functionNameToMcpClient[functionCall.name!];\n let requestOptions = undefined;\n // TODO: b/424238654 - Add support for finer grained timeout control.\n if (this.config.timeout) {\n requestOptions = {\n timeout: this.config.timeout,\n };\n }\n const callToolResponse = await mcpClient.callTool(\n {\n name: functionCall.name!,\n arguments: functionCall.args,\n },\n // Set the result schema to undefined to allow MCP to rely on the\n // default schema.\n undefined,\n requestOptions,\n );\n functionCallResponseParts.push({\n functionResponse: {\n name: functionCall.name,\n response: callToolResponse.isError\n ? {error: callToolResponse}\n : (callToolResponse as Record<string, unknown>),\n },\n });\n }\n }\n return functionCallResponseParts;\n }\n}\n\nfunction isMcpClient(client: unknown): client is McpClient {\n return (\n client !== null &&\n typeof client === 'object' &&\n 'listTools' in client &&\n typeof client.listTools === 'function'\n );\n}\n\n/**\n * Creates a McpCallableTool from MCP clients and an optional config.\n *\n * The callable tool can invoke the MCP clients with given function call\n * arguments. (often for automatic function calling).\n * Use the config to modify tool parameters such as behavior.\n *\n * @experimental Built-in MCP support is an experimental feature, may change in future\n * versions.\n */\nexport function mcpToTool(\n ...args: [...McpClient[], CallableToolConfig | McpClient]\n): CallableTool {\n // Set MCP usage for telemetry.\n hasMcpToolUsageFromMcpToTool = true;\n if (args.length === 0) {\n throw new Error('No MCP clients provided');\n }\n const maybeConfig = args[args.length - 1];\n if (isMcpClient(maybeConfig)) {\n return McpCallableTool.create(args as McpClient[], {});\n }\n return McpCallableTool.create(\n args.slice(0, args.length - 1) as McpClient[],\n maybeConfig,\n );\n}\n\n/**\n * Sets the MCP tool usage flag from calling mcpToTool. This is used for\n * telemetry.\n */\nexport function setMcpToolUsageFromMcpToTool(mcpToolUsage: boolean) {\n hasMcpToolUsageFromMcpToTool = mcpToolUsage;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Live music client.\n *\n * @experimental\n */\n\nimport {ApiClient} from './_api_client.js';\nimport {Auth} from './_auth.js';\nimport * as t from './_transformers.js';\nimport {WebSocket, WebSocketCallbacks, WebSocketFactory} from './_websocket.js';\nimport * as converters from './converters/_live_converters.js';\nimport * as types from './types.js';\n\n/**\n * Handles incoming messages from the WebSocket.\n *\n * @remarks\n * This function is responsible for parsing incoming messages, transforming them\n * into LiveMusicServerMessage, and then calling the onmessage callback.\n * Note that the first message which is received from the server is a\n * setupComplete message.\n *\n * @param apiClient The ApiClient instance.\n * @param onmessage The user-provided onmessage callback (if any).\n * @param event The MessageEvent from the WebSocket.\n */\nasync function handleWebSocketMessage(\n apiClient: ApiClient,\n onmessage: (msg: types.LiveMusicServerMessage) => void,\n event: MessageEvent,\n): Promise<void> {\n const serverMessage: types.LiveMusicServerMessage =\n new types.LiveMusicServerMessage();\n let data: types.LiveMusicServerMessage;\n if (event.data instanceof Blob) {\n data = JSON.parse(await event.data.text()) as types.LiveMusicServerMessage;\n } else {\n data = JSON.parse(event.data) as types.LiveMusicServerMessage;\n }\n Object.assign(serverMessage, data);\n onmessage(serverMessage);\n}\n\n/**\n LiveMusic class encapsulates the configuration for live music\n generation via Lyria Live models.\n\n @experimental\n */\nexport class LiveMusic {\n constructor(\n private readonly apiClient: ApiClient,\n private readonly auth: Auth,\n private readonly webSocketFactory: WebSocketFactory,\n ) {}\n\n /**\n Establishes a connection to the specified model and returns a\n LiveMusicSession object representing that connection.\n\n @experimental\n\n @remarks\n\n @param params - The parameters for establishing a connection to the model.\n @return A live session.\n\n @example\n ```ts\n let model = 'models/lyria-realtime-exp';\n const session = await ai.live.music.connect({\n model: model,\n callbacks: {\n onmessage: (e: MessageEvent) => {\n console.log('Received message from the server: %s\\n', debug(e.data));\n },\n onerror: (e: ErrorEvent) => {\n console.log('Error occurred: %s\\n', debug(e.error));\n },\n onclose: (e: CloseEvent) => {\n console.log('Connection closed.');\n },\n },\n });\n ```\n */\n async connect(\n params: types.LiveMusicConnectParameters,\n ): Promise<LiveMusicSession> {\n if (this.apiClient.isVertexAI()) {\n throw new Error('Live music is not supported for Vertex AI.');\n }\n console.warn(\n 'Live music generation is experimental and may change in future versions.',\n );\n\n const websocketBaseUrl = this.apiClient.getWebsocketBaseUrl();\n const apiVersion = this.apiClient.getApiVersion();\n const headers = mapToHeaders(this.apiClient.getDefaultHeaders());\n const apiKey = this.apiClient.getApiKey();\n const url = `${websocketBaseUrl}/ws/google.ai.generativelanguage.${\n apiVersion\n }.GenerativeService.BidiGenerateMusic?key=${apiKey}`;\n\n let onopenResolve: (value: unknown) => void = () => {};\n const onopenPromise = new Promise((resolve: (value: unknown) => void) => {\n onopenResolve = resolve;\n });\n\n const callbacks: types.LiveMusicCallbacks = params.callbacks;\n\n const onopenAwaitedCallback = function () {\n onopenResolve({});\n };\n\n const apiClient = this.apiClient;\n const websocketCallbacks: WebSocketCallbacks = {\n onopen: onopenAwaitedCallback,\n onmessage: (event: MessageEvent) => {\n void handleWebSocketMessage(apiClient, callbacks.onmessage, event);\n },\n onerror:\n callbacks?.onerror ??\n function (e: ErrorEvent) {\n void e;\n },\n onclose:\n callbacks?.onclose ??\n function (e: CloseEvent) {\n void e;\n },\n };\n\n const conn = this.webSocketFactory.create(\n url,\n headersToMap(headers),\n websocketCallbacks,\n );\n conn.connect();\n // Wait for the websocket to open before sending requests.\n await onopenPromise;\n\n const model = t.tModel(this.apiClient, params.model);\n const setup = {model};\n const clientMessage = {setup};\n conn.send(JSON.stringify(clientMessage));\n\n return new LiveMusicSession(conn, this.apiClient);\n }\n}\n\n/**\n Represents a connection to the API.\n\n @experimental\n */\nexport class LiveMusicSession {\n constructor(\n readonly conn: WebSocket,\n private readonly apiClient: ApiClient,\n ) {}\n\n /**\n Sets inputs to steer music generation. Updates the session's current\n weighted prompts.\n\n @param params - Contains one property, `weightedPrompts`.\n\n - `weightedPrompts` to send to the model; weights are normalized to\n sum to 1.0.\n\n @experimental\n */\n async setWeightedPrompts(\n params: types.LiveMusicSetWeightedPromptsParameters,\n ) {\n if (\n !params.weightedPrompts ||\n Object.keys(params.weightedPrompts).length === 0\n ) {\n throw new Error(\n 'Weighted prompts must be set and contain at least one entry.',\n );\n }\n const clientContent =\n converters.liveMusicSetWeightedPromptsParametersToMldev(params);\n this.conn.send(JSON.stringify({clientContent}));\n }\n\n /**\n Sets a configuration to the model. Updates the session's current\n music generation config.\n\n @param params - Contains one property, `musicGenerationConfig`.\n\n - `musicGenerationConfig` to set in the model. Passing an empty or\n undefined config to the model will reset the config to defaults.\n\n @experimental\n */\n async setMusicGenerationConfig(params: types.LiveMusicSetConfigParameters) {\n if (!params.musicGenerationConfig) {\n params.musicGenerationConfig = {};\n }\n const setConfigParameters =\n converters.liveMusicSetConfigParametersToMldev(params);\n this.conn.send(JSON.stringify(setConfigParameters));\n }\n\n private sendPlaybackControl(playbackControl: types.LiveMusicPlaybackControl) {\n const clientMessage = {playbackControl};\n this.conn.send(JSON.stringify(clientMessage));\n }\n\n /**\n * Start the music stream.\n *\n * @experimental\n */\n play() {\n this.sendPlaybackControl(types.LiveMusicPlaybackControl.PLAY);\n }\n\n /**\n * Temporarily halt the music stream. Use `play` to resume from the current\n * position.\n *\n * @experimental\n */\n pause() {\n this.sendPlaybackControl(types.LiveMusicPlaybackControl.PAUSE);\n }\n\n /**\n * Stop the music stream and reset the state. Retains the current prompts\n * and config.\n *\n * @experimental\n */\n stop() {\n this.sendPlaybackControl(types.LiveMusicPlaybackControl.STOP);\n }\n\n /**\n * Resets the context of the music generation without stopping it.\n * Retains the current prompts and config.\n *\n * @experimental\n */\n resetContext() {\n this.sendPlaybackControl(types.LiveMusicPlaybackControl.RESET_CONTEXT);\n }\n\n /**\n Terminates the WebSocket connection.\n\n @experimental\n */\n close() {\n this.conn.close();\n }\n}\n\n// Converts an headers object to a \"map\" object as expected by the WebSocket\n// constructor. We use this as the Auth interface works with Headers objects\n// while the WebSocket constructor takes a map.\nfunction headersToMap(headers: Headers): Record<string, string> {\n const headerMap: Record<string, string> = {};\n headers.forEach((value, key) => {\n headerMap[key] = value;\n });\n return headerMap;\n}\n\n// Converts a \"map\" object to a headers object. We use this as the Auth\n// interface works with Headers objects while the API client default headers\n// returns a map.\nfunction mapToHeaders(map: Record<string, string>): Headers {\n const headers = new Headers();\n for (const [key, value] of Object.entries(map)) {\n headers.append(key, value);\n }\n return headers;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Live client.\n *\n * @experimental\n */\n\nimport {ApiClient} from './_api_client.js';\nimport {Auth} from './_auth.js';\nimport * as t from './_transformers.js';\nimport {WebSocket, WebSocketCallbacks, WebSocketFactory} from './_websocket.js';\nimport * as converters from './converters/_live_converters.js';\nimport {contentToMldev} from './converters/_models_converters.js';\nimport {hasMcpToolUsage, setMcpUsageHeader} from './mcp/_mcp.js';\nimport {LiveMusic} from './music.js';\nimport * as types from './types.js';\n\nconst FUNCTION_RESPONSE_REQUIRES_ID =\n 'FunctionResponse request must have an `id` field from the response of a ToolCall.FunctionalCalls in Google AI.';\n\n/**\n * Handles incoming messages from the WebSocket.\n *\n * @remarks\n * This function is responsible for parsing incoming messages, transforming them\n * into LiveServerMessages, and then calling the onmessage callback. Note that\n * the first message which is received from the server is a setupComplete\n * message.\n *\n * @param apiClient The ApiClient instance.\n * @param onmessage The user-provided onmessage callback (if any).\n * @param event The MessageEvent from the WebSocket.\n */\nasync function handleWebSocketMessage(\n apiClient: ApiClient,\n onmessage: (msg: types.LiveServerMessage) => void,\n event: MessageEvent,\n): Promise<void> {\n const serverMessage: types.LiveServerMessage = new types.LiveServerMessage();\n let jsonData: string;\n if (event.data instanceof Blob) {\n jsonData = await event.data.text();\n } else if (event.data instanceof ArrayBuffer) {\n jsonData = new TextDecoder().decode(event.data);\n } else {\n jsonData = event.data;\n }\n\n const data = JSON.parse(jsonData) as types.LiveServerMessage;\n\n if (apiClient.isVertexAI()) {\n const resp = converters.liveServerMessageFromVertex(data);\n Object.assign(serverMessage, resp);\n } else {\n const resp = data;\n Object.assign(serverMessage, resp);\n }\n\n onmessage(serverMessage);\n}\n\n/**\n Live class encapsulates the configuration for live interaction with the\n Generative Language API. It embeds ApiClient for general API settings.\n\n @experimental\n */\nexport class Live {\n public readonly music: LiveMusic;\n\n constructor(\n private readonly apiClient: ApiClient,\n private readonly auth: Auth,\n private readonly webSocketFactory: WebSocketFactory,\n ) {\n this.music = new LiveMusic(\n this.apiClient,\n this.auth,\n this.webSocketFactory,\n );\n }\n\n /**\n Establishes a connection to the specified model with the given\n configuration and returns a Session object representing that connection.\n\n @experimental Built-in MCP support is an experimental feature, may change in\n future versions.\n\n @remarks\n\n @param params - The parameters for establishing a connection to the model.\n @return A live session.\n\n @example\n ```ts\n let model: string;\n if (GOOGLE_GENAI_USE_VERTEXAI) {\n model = 'gemini-2.0-flash-live-preview-04-09';\n } else {\n model = 'gemini-live-2.5-flash-preview';\n }\n const session = await ai.live.connect({\n model: model,\n config: {\n responseModalities: [Modality.AUDIO],\n },\n callbacks: {\n onopen: () => {\n console.log('Connected to the socket.');\n },\n onmessage: (e: MessageEvent) => {\n console.log('Received message from the server: %s\\n', debug(e.data));\n },\n onerror: (e: ErrorEvent) => {\n console.log('Error occurred: %s\\n', debug(e.error));\n },\n onclose: (e: CloseEvent) => {\n console.log('Connection closed.');\n },\n },\n });\n ```\n */\n async connect(params: types.LiveConnectParameters): Promise<Session> {\n // TODO: b/404946746 - Support per request HTTP options.\n if (params.config && params.config.httpOptions) {\n throw new Error(\n 'The Live module does not support httpOptions at request-level in' +\n ' LiveConnectConfig yet. Please use the client-level httpOptions' +\n ' configuration instead.',\n );\n }\n const websocketBaseUrl = this.apiClient.getWebsocketBaseUrl();\n const apiVersion = this.apiClient.getApiVersion();\n let url: string;\n const clientHeaders = this.apiClient.getHeaders();\n if (\n params.config &&\n params.config.tools &&\n hasMcpToolUsage(params.config.tools)\n ) {\n setMcpUsageHeader(clientHeaders);\n }\n const headers = mapToHeaders(clientHeaders);\n if (this.apiClient.isVertexAI()) {\n const project = this.apiClient.getProject();\n const location = this.apiClient.getLocation();\n const apiKey = this.apiClient.getApiKey();\n const hasStandardAuth = (!!project && !!location) || !!apiKey;\n\n if (this.apiClient.getCustomBaseUrl() && !hasStandardAuth) {\n // Custom base URL without standard auth (e.g., proxy).\n url = websocketBaseUrl;\n // Auth headers are assumed to be in `clientHeaders` from httpOptions.\n } else {\n url = `${websocketBaseUrl}/ws/google.cloud.aiplatform.${apiVersion}.LlmBidiService/BidiGenerateContent`;\n await this.auth.addAuthHeaders(headers, url);\n }\n } else {\n const apiKey = this.apiClient.getApiKey();\n\n let method = 'BidiGenerateContent';\n let keyName = 'key';\n if (apiKey?.startsWith('auth_tokens/')) {\n console.warn(\n 'Warning: Ephemeral token support is experimental and may change in future versions.',\n );\n if (apiVersion !== 'v1alpha') {\n console.warn(\n \"Warning: The SDK's ephemeral token support is in v1alpha only. Please use const ai = new GoogleGenAI({apiKey: token.name, httpOptions: { apiVersion: 'v1alpha' }}); before session connection.\",\n );\n }\n method = 'BidiGenerateContentConstrained';\n keyName = 'access_token';\n }\n\n url = `${websocketBaseUrl}/ws/google.ai.generativelanguage.${\n apiVersion\n }.GenerativeService.${method}?${keyName}=${apiKey}`;\n }\n\n let onopenResolve: (value: unknown) => void = () => {};\n const onopenPromise = new Promise((resolve: (value: unknown) => void) => {\n onopenResolve = resolve;\n });\n\n const callbacks: types.LiveCallbacks = params.callbacks;\n\n const onopenAwaitedCallback = function () {\n callbacks?.onopen?.();\n onopenResolve({});\n };\n\n const apiClient = this.apiClient;\n\n const websocketCallbacks: WebSocketCallbacks = {\n onopen: onopenAwaitedCallback,\n onmessage: (event: MessageEvent) => {\n void handleWebSocketMessage(apiClient, callbacks.onmessage, event);\n },\n onerror:\n callbacks?.onerror ??\n function (e: ErrorEvent) {\n void e;\n },\n onclose:\n callbacks?.onclose ??\n function (e: CloseEvent) {\n void e;\n },\n };\n\n const conn = this.webSocketFactory.create(\n url,\n headersToMap(headers),\n websocketCallbacks,\n );\n conn.connect();\n // Wait for the websocket to open before sending requests.\n await onopenPromise;\n\n let transformedModel = t.tModel(this.apiClient, params.model);\n if (\n this.apiClient.isVertexAI() &&\n transformedModel.startsWith('publishers/')\n ) {\n const project = this.apiClient.getProject();\n const location = this.apiClient.getLocation();\n if (project && location) {\n transformedModel =\n `projects/${project}/locations/${location}/` + transformedModel;\n }\n }\n\n let clientMessage: Record<string, unknown> = {};\n\n if (\n this.apiClient.isVertexAI() &&\n params.config?.responseModalities === undefined\n ) {\n // Set default to AUDIO to align with MLDev API.\n if (params.config === undefined) {\n params.config = {responseModalities: [types.Modality.AUDIO]};\n } else {\n params.config.responseModalities = [types.Modality.AUDIO];\n }\n }\n if (params.config?.generationConfig) {\n // Raise deprecation warning for generationConfig.\n console.warn(\n 'Setting `LiveConnectConfig.generation_config` is deprecated, please set the fields on `LiveConnectConfig` directly. This will become an error in a future version (not before Q3 2025).',\n );\n }\n const inputTools = params.config?.tools ?? [];\n const convertedTools: types.Tool[] = [];\n for (const tool of inputTools) {\n if (this.isCallableTool(tool)) {\n const callableTool = tool as types.CallableTool;\n convertedTools.push(await callableTool.tool());\n } else {\n convertedTools.push(tool as types.Tool);\n }\n }\n if (convertedTools.length > 0) {\n params.config!.tools = convertedTools;\n }\n const liveConnectParameters: types.LiveConnectParameters = {\n model: transformedModel,\n config: params.config,\n callbacks: params.callbacks,\n };\n if (this.apiClient.isVertexAI()) {\n clientMessage = converters.liveConnectParametersToVertex(\n this.apiClient,\n liveConnectParameters,\n );\n } else {\n clientMessage = converters.liveConnectParametersToMldev(\n this.apiClient,\n liveConnectParameters,\n );\n }\n delete clientMessage['config'];\n conn.send(JSON.stringify(clientMessage));\n return new Session(conn, this.apiClient);\n }\n\n // TODO: b/416041229 - Abstract this method to a common place.\n private isCallableTool(tool: types.ToolUnion): boolean {\n return 'callTool' in tool && typeof tool.callTool === 'function';\n }\n}\n\nconst defaultLiveSendClientContentParamerters: types.LiveSendClientContentParameters =\n {\n turnComplete: true,\n };\n\n/**\n Represents a connection to the API.\n\n @experimental\n */\nexport class Session {\n constructor(\n readonly conn: WebSocket,\n private readonly apiClient: ApiClient,\n ) {}\n\n private tLiveClientContent(\n apiClient: ApiClient,\n params: types.LiveSendClientContentParameters,\n ): types.LiveClientMessage {\n if (params.turns !== null && params.turns !== undefined) {\n let contents: types.Content[] = [];\n try {\n contents = t.tContents(params.turns as types.ContentListUnion);\n if (!apiClient.isVertexAI()) {\n contents = contents.map((item) => contentToMldev(item));\n }\n } catch {\n throw new Error(\n `Failed to parse client content \"turns\", type: '${typeof params.turns}'`,\n );\n }\n return {\n clientContent: {turns: contents, turnComplete: params.turnComplete},\n };\n }\n\n return {\n clientContent: {turnComplete: params.turnComplete},\n };\n }\n\n private tLiveClienttToolResponse(\n apiClient: ApiClient,\n params: types.LiveSendToolResponseParameters,\n ): types.LiveClientMessage {\n let functionResponses: types.FunctionResponse[] = [];\n\n if (params.functionResponses == null) {\n throw new Error('functionResponses is required.');\n }\n\n if (!Array.isArray(params.functionResponses)) {\n functionResponses = [params.functionResponses];\n } else {\n functionResponses = params.functionResponses;\n }\n\n if (functionResponses.length === 0) {\n throw new Error('functionResponses is required.');\n }\n\n for (const functionResponse of functionResponses) {\n if (\n typeof functionResponse !== 'object' ||\n functionResponse === null ||\n !('name' in functionResponse) ||\n !('response' in functionResponse)\n ) {\n throw new Error(\n `Could not parse function response, type '${typeof functionResponse}'.`,\n );\n }\n if (!apiClient.isVertexAI() && !('id' in functionResponse)) {\n throw new Error(FUNCTION_RESPONSE_REQUIRES_ID);\n }\n }\n\n const clientMessage: types.LiveClientMessage = {\n toolResponse: {functionResponses: functionResponses},\n };\n return clientMessage;\n }\n\n /**\n Send a message over the established connection.\n\n @param params - Contains two **optional** properties, `turns` and\n `turnComplete`.\n\n - `turns` will be converted to a `Content[]`\n - `turnComplete: true` [default] indicates that you are done sending\n content and expect a response. If `turnComplete: false`, the server\n will wait for additional messages before starting generation.\n\n @experimental\n\n @remarks\n There are two ways to send messages to the live API:\n `sendClientContent` and `sendRealtimeInput`.\n\n `sendClientContent` messages are added to the model context **in order**.\n Having a conversation using `sendClientContent` messages is roughly\n equivalent to using the `Chat.sendMessageStream`, except that the state of\n the `chat` history is stored on the API server instead of locally.\n\n Because of `sendClientContent`'s order guarantee, the model cannot respons\n as quickly to `sendClientContent` messages as to `sendRealtimeInput`\n messages. This makes the biggest difference when sending objects that have\n significant preprocessing time (typically images).\n\n The `sendClientContent` message sends a `Content[]`\n which has more options than the `Blob` sent by `sendRealtimeInput`.\n\n So the main use-cases for `sendClientContent` over `sendRealtimeInput` are:\n\n - Sending anything that can't be represented as a `Blob` (text,\n `sendClientContent({turns=\"Hello?\"}`)).\n - Managing turns when not using audio input and voice activity detection.\n (`sendClientContent({turnComplete:true})` or the short form\n `sendClientContent()`)\n - Prefilling a conversation context\n ```\n sendClientContent({\n turns: [\n Content({role:user, parts:...}),\n Content({role:user, parts:...}),\n ...\n ]\n })\n ```\n @experimental\n */\n sendClientContent(params: types.LiveSendClientContentParameters) {\n params = {\n ...defaultLiveSendClientContentParamerters,\n ...params,\n };\n\n const clientMessage: types.LiveClientMessage = this.tLiveClientContent(\n this.apiClient,\n params,\n );\n this.conn.send(JSON.stringify(clientMessage));\n }\n\n /**\n Send a realtime message over the established connection.\n\n @param params - Contains one property, `media`.\n\n - `media` will be converted to a `Blob`\n\n @experimental\n\n @remarks\n Use `sendRealtimeInput` for realtime audio chunks and video frames (images).\n\n With `sendRealtimeInput` the api will respond to audio automatically\n based on voice activity detection (VAD).\n\n `sendRealtimeInput` is optimized for responsivness at the expense of\n deterministic ordering guarantees. Audio and video tokens are to the\n context when they become available.\n\n Note: The Call signature expects a `Blob` object, but only a subset\n of audio and image mimetypes are allowed.\n */\n sendRealtimeInput(params: types.LiveSendRealtimeInputParameters) {\n let clientMessage: types.LiveClientMessage = {};\n\n if (this.apiClient.isVertexAI()) {\n clientMessage = {\n 'realtimeInput':\n converters.liveSendRealtimeInputParametersToVertex(params),\n };\n } else {\n clientMessage = {\n 'realtimeInput':\n converters.liveSendRealtimeInputParametersToMldev(params),\n };\n }\n this.conn.send(JSON.stringify(clientMessage));\n }\n\n /**\n Send a function response message over the established connection.\n\n @param params - Contains property `functionResponses`.\n\n - `functionResponses` will be converted to a `functionResponses[]`\n\n @remarks\n Use `sendFunctionResponse` to reply to `LiveServerToolCall` from the server.\n\n Use {@link types.LiveConnectConfig#tools} to configure the callable functions.\n\n @experimental\n */\n sendToolResponse(params: types.LiveSendToolResponseParameters) {\n if (params.functionResponses == null) {\n throw new Error('Tool response parameters are required.');\n }\n\n const clientMessage: types.LiveClientMessage =\n this.tLiveClienttToolResponse(this.apiClient, params);\n this.conn.send(JSON.stringify(clientMessage));\n }\n\n /**\n Terminates the WebSocket connection.\n\n @experimental\n\n @example\n ```ts\n let model: string;\n if (GOOGLE_GENAI_USE_VERTEXAI) {\n model = 'gemini-2.0-flash-live-preview-04-09';\n } else {\n model = 'gemini-live-2.5-flash-preview';\n }\n const session = await ai.live.connect({\n model: model,\n config: {\n responseModalities: [Modality.AUDIO],\n }\n });\n\n session.close();\n ```\n */\n close() {\n this.conn.close();\n }\n}\n\n// Converts an headers object to a \"map\" object as expected by the WebSocket\n// constructor. We use this as the Auth interface works with Headers objects\n// while the WebSocket constructor takes a map.\nfunction headersToMap(headers: Headers): Record<string, string> {\n const headerMap: Record<string, string> = {};\n headers.forEach((value, key) => {\n headerMap[key] = value;\n });\n return headerMap;\n}\n\n// Converts a \"map\" object to a headers object. We use this as the Auth\n// interface works with Headers objects while the API client default headers\n// returns a map.\nfunction mapToHeaders(map: Record<string, string>): Headers {\n const headers = new Headers();\n for (const [key, value] of Object.entries(map)) {\n headers.append(key, value);\n }\n return headers;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport * as types from './types.js';\n\nexport const DEFAULT_MAX_REMOTE_CALLS = 10;\n\n/** Returns whether automatic function calling is disabled. */\nexport function shouldDisableAfc(\n config: types.GenerateContentConfig | undefined,\n): boolean {\n if (config?.automaticFunctionCalling?.disable) {\n return true;\n }\n\n let callableToolsPresent = false;\n for (const tool of config?.tools ?? []) {\n if (isCallableTool(tool)) {\n callableToolsPresent = true;\n break;\n }\n }\n if (!callableToolsPresent) {\n return true;\n }\n\n const maxCalls = config?.automaticFunctionCalling?.maximumRemoteCalls;\n if (\n (maxCalls && (maxCalls < 0 || !Number.isInteger(maxCalls))) ||\n maxCalls == 0\n ) {\n console.warn(\n 'Invalid maximumRemoteCalls value provided for automatic function calling. Disabled automatic function calling. Please provide a valid integer value greater than 0. maximumRemoteCalls provided:',\n maxCalls,\n );\n return true;\n }\n return false;\n}\n\nexport function isCallableTool(tool: types.ToolUnion): boolean {\n return 'callTool' in tool && typeof tool.callTool === 'function';\n}\n\n// Checks whether the list of tools contains any CallableTools. Will return true\n// if there is at least one CallableTool.\nexport function hasCallableTools(\n params: types.GenerateContentParameters,\n): boolean {\n return params.config?.tools?.some((tool) => isCallableTool(tool)) ?? false;\n}\n\n/**\n * Returns the indexes of the tools that are not compatible with AFC.\n */\nexport function findAfcIncompatibleToolIndexes(\n params?: types.GenerateContentParameters,\n): number[] {\n // Use number[] for an array of numbers in TypeScript\n const afcIncompatibleToolIndexes: number[] = [];\n if (!params?.config?.tools) {\n return afcIncompatibleToolIndexes;\n }\n params.config.tools.forEach((tool, index) => {\n if (isCallableTool(tool)) {\n return;\n }\n const geminiTool = tool as types.Tool;\n if (\n geminiTool.functionDeclarations &&\n geminiTool.functionDeclarations.length > 0\n ) {\n afcIncompatibleToolIndexes.push(index);\n }\n });\n\n return afcIncompatibleToolIndexes;\n}\n\n/**\n * Returns whether to append automatic function calling history to the\n * response.\n */\nexport function shouldAppendAfcHistory(\n config: types.GenerateContentConfig | undefined,\n): boolean {\n return !config?.automaticFunctionCalling?.ignoreCallHistory;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport * as afc from './_afc.js';\nimport {ApiClient} from './_api_client.js';\nimport * as common from './_common.js';\nimport {BaseModule} from './_common.js';\nimport * as _internal_types from './_internal_types.js';\nimport {tContents} from './_transformers.js';\nimport * as converters from './converters/_models_converters.js';\nimport * as mcp from './mcp/_mcp.js';\nimport {PagedItem, Pager} from './pagers.js';\nimport * as types from './types.js';\n\nexport class Models extends BaseModule {\n constructor(private readonly apiClient: ApiClient) {\n super();\n }\n\n /**\n * Makes an API request to generate content with a given model.\n *\n * For the `model` parameter, supported formats for Vertex AI API include:\n * - The Gemini model ID, for example: 'gemini-2.0-flash'\n * - The full resource name starts with 'projects/', for example:\n * 'projects/my-project-id/locations/us-central1/publishers/google/models/gemini-2.0-flash'\n * - The partial resource name with 'publishers/', for example:\n * 'publishers/google/models/gemini-2.0-flash' or\n * 'publishers/meta/models/llama-3.1-405b-instruct-maas'\n * - `/` separated publisher and model name, for example:\n * 'google/gemini-2.0-flash' or 'meta/llama-3.1-405b-instruct-maas'\n *\n * For the `model` parameter, supported formats for Gemini API include:\n * - The Gemini model ID, for example: 'gemini-2.0-flash'\n * - The model name starts with 'models/', for example:\n * 'models/gemini-2.0-flash'\n * - For tuned models, the model name starts with 'tunedModels/',\n * for example:\n * 'tunedModels/1234567890123456789'\n *\n * Some models support multimodal input and output.\n *\n * @param params - The parameters for generating content.\n * @return The response from generating content.\n *\n * @example\n * ```ts\n * const response = await ai.models.generateContent({\n * model: 'gemini-2.0-flash',\n * contents: 'why is the sky blue?',\n * config: {\n * candidateCount: 2,\n * }\n * });\n * console.log(response);\n * ```\n */\n generateContent = async (\n params: types.GenerateContentParameters,\n ): Promise<types.GenerateContentResponse> => {\n const transformedParams = await this.processParamsMaybeAddMcpUsage(params);\n this.maybeMoveToResponseJsonSchem(params);\n if (!afc.hasCallableTools(params) || afc.shouldDisableAfc(params.config)) {\n return await this.generateContentInternal(transformedParams);\n }\n\n const incompatibleToolIndexes = afc.findAfcIncompatibleToolIndexes(params);\n if (incompatibleToolIndexes.length > 0) {\n const formattedIndexes = incompatibleToolIndexes\n .map((index: number) => `tools[${index}]`)\n .join(', ');\n throw new Error(\n `Automatic function calling with CallableTools (or MCP objects) and basic FunctionDeclarations is not yet supported. Incompatible tools found at ${formattedIndexes}.`,\n );\n }\n\n let response: types.GenerateContentResponse;\n let functionResponseContent: types.Content;\n const automaticFunctionCallingHistory: types.Content[] = tContents(\n transformedParams.contents,\n );\n const maxRemoteCalls =\n transformedParams.config?.automaticFunctionCalling?.maximumRemoteCalls ??\n afc.DEFAULT_MAX_REMOTE_CALLS;\n let remoteCalls = 0;\n while (remoteCalls < maxRemoteCalls) {\n response = await this.generateContentInternal(transformedParams);\n if (!response.functionCalls || response.functionCalls!.length === 0) {\n break;\n }\n\n const responseContent: types.Content = response.candidates![0].content!;\n const functionResponseParts: types.Part[] = [];\n for (const tool of params.config?.tools ?? []) {\n if (afc.isCallableTool(tool)) {\n const callableTool = tool as types.CallableTool;\n const parts = await callableTool.callTool(response.functionCalls!);\n functionResponseParts.push(...parts);\n }\n }\n\n remoteCalls++;\n\n functionResponseContent = {\n role: 'user',\n parts: functionResponseParts,\n };\n\n transformedParams.contents = tContents(transformedParams.contents);\n (transformedParams.contents as types.Content[]).push(responseContent);\n (transformedParams.contents as types.Content[]).push(\n functionResponseContent,\n );\n\n if (afc.shouldAppendAfcHistory(transformedParams.config)) {\n automaticFunctionCallingHistory.push(responseContent);\n automaticFunctionCallingHistory.push(functionResponseContent);\n }\n }\n if (afc.shouldAppendAfcHistory(transformedParams.config)) {\n response!.automaticFunctionCallingHistory =\n automaticFunctionCallingHistory;\n }\n return response!;\n };\n\n /**\n * This logic is needed for GenerateContentConfig only.\n * Previously we made GenerateContentConfig.responseSchema field to accept\n * unknown. Since v1.9.0, we switch to use backend JSON schema support.\n * To maintain backward compatibility, we move the data that was treated as\n * JSON schema from the responseSchema field to the responseJsonSchema field.\n */\n private maybeMoveToResponseJsonSchem(\n params: types.GenerateContentParameters,\n ): void {\n if (params.config && params.config.responseSchema) {\n if (!params.config.responseJsonSchema) {\n if (Object.keys(params.config.responseSchema).includes('$schema')) {\n params.config.responseJsonSchema = params.config.responseSchema;\n delete params.config.responseSchema;\n }\n }\n }\n return;\n }\n\n /**\n * Makes an API request to generate content with a given model and yields the\n * response in chunks.\n *\n * For the `model` parameter, supported formats for Vertex AI API include:\n * - The Gemini model ID, for example: 'gemini-2.0-flash'\n * - The full resource name starts with 'projects/', for example:\n * 'projects/my-project-id/locations/us-central1/publishers/google/models/gemini-2.0-flash'\n * - The partial resource name with 'publishers/', for example:\n * 'publishers/google/models/gemini-2.0-flash' or\n * 'publishers/meta/models/llama-3.1-405b-instruct-maas'\n * - `/` separated publisher and model name, for example:\n * 'google/gemini-2.0-flash' or 'meta/llama-3.1-405b-instruct-maas'\n *\n * For the `model` parameter, supported formats for Gemini API include:\n * - The Gemini model ID, for example: 'gemini-2.0-flash'\n * - The model name starts with 'models/', for example:\n * 'models/gemini-2.0-flash'\n * - For tuned models, the model name starts with 'tunedModels/',\n * for example:\n * 'tunedModels/1234567890123456789'\n *\n * Some models support multimodal input and output.\n *\n * @param params - The parameters for generating content with streaming response.\n * @return The response from generating content.\n *\n * @example\n * ```ts\n * const response = await ai.models.generateContentStream({\n * model: 'gemini-2.0-flash',\n * contents: 'why is the sky blue?',\n * config: {\n * maxOutputTokens: 200,\n * }\n * });\n * for await (const chunk of response) {\n * console.log(chunk);\n * }\n * ```\n */\n generateContentStream = async (\n params: types.GenerateContentParameters,\n ): Promise<AsyncGenerator<types.GenerateContentResponse>> => {\n this.maybeMoveToResponseJsonSchem(params);\n if (afc.shouldDisableAfc(params.config)) {\n const transformedParams =\n await this.processParamsMaybeAddMcpUsage(params);\n return await this.generateContentStreamInternal(transformedParams);\n }\n const incompatibleToolIndexes = afc.findAfcIncompatibleToolIndexes(params);\n if (incompatibleToolIndexes.length > 0) {\n const formattedIndexes = incompatibleToolIndexes\n .map((index: number) => `tools[${index}]`)\n .join(', ');\n throw new Error(\n `Incompatible tools found at ${formattedIndexes}. Automatic function calling with CallableTools (or MCP objects) and basic FunctionDeclarations\" is not yet supported.`,\n );\n }\n\n // With tool compatibility confirmed, validate that the configuration are\n // compatible with each other and raise an error if invalid.\n const streamFunctionCall =\n params?.config?.toolConfig?.functionCallingConfig\n ?.streamFunctionCallArguments;\n const disableAfc = params?.config?.automaticFunctionCalling?.disable;\n\n if (streamFunctionCall && !disableAfc) {\n throw new Error(\n \"Running in streaming mode with 'streamFunctionCallArguments' enabled, \" +\n 'this feature is not compatible with automatic function calling (AFC). ' +\n \"Please set 'config.automaticFunctionCalling.disable' to true to disable AFC \" +\n \"or leave 'config.toolConfig.functionCallingConfig.streamFunctionCallArguments' \" +\n 'to be undefined or set to false to disable streaming function call arguments feature.',\n );\n }\n\n return await this.processAfcStream(params);\n };\n\n /**\n * Transforms the CallableTools in the parameters to be simply Tools, it\n * copies the params into a new object and replaces the tools, it does not\n * modify the original params. Also sets the MCP usage header if there are\n * MCP tools in the parameters.\n */\n private async processParamsMaybeAddMcpUsage(\n params: types.GenerateContentParameters,\n ): Promise<types.GenerateContentParameters> {\n const tools = params.config?.tools;\n if (!tools) {\n return params;\n }\n const transformedTools = await Promise.all(\n tools.map(async (tool) => {\n if (afc.isCallableTool(tool)) {\n const callableTool = tool as types.CallableTool;\n return await callableTool.tool();\n }\n return tool;\n }),\n );\n const newParams: types.GenerateContentParameters = {\n model: params.model,\n contents: params.contents,\n config: {\n ...params.config,\n tools: transformedTools,\n },\n };\n newParams.config!.tools = transformedTools;\n\n if (\n params.config &&\n params.config.tools &&\n mcp.hasMcpToolUsage(params.config.tools)\n ) {\n const headers = params.config.httpOptions?.headers ?? {};\n let newHeaders = {...headers};\n if (Object.keys(newHeaders).length === 0) {\n newHeaders = this.apiClient.getDefaultHeaders();\n }\n mcp.setMcpUsageHeader(newHeaders);\n newParams.config!.httpOptions = {\n ...params.config.httpOptions,\n headers: newHeaders,\n };\n }\n return newParams;\n }\n\n private async initAfcToolsMap(\n params: types.GenerateContentParameters,\n ): Promise<Map<string, types.CallableTool>> {\n const afcTools: Map<string, types.CallableTool> = new Map();\n for (const tool of params.config?.tools ?? []) {\n if (afc.isCallableTool(tool)) {\n const callableTool = tool as types.CallableTool;\n const toolDeclaration = await callableTool.tool();\n for (const declaration of toolDeclaration.functionDeclarations ?? []) {\n if (!declaration.name) {\n throw new Error('Function declaration name is required.');\n }\n if (afcTools.has(declaration.name)) {\n throw new Error(\n `Duplicate tool declaration name: ${declaration.name}`,\n );\n }\n afcTools.set(declaration.name, callableTool);\n }\n }\n }\n return afcTools;\n }\n\n private async processAfcStream(\n params: types.GenerateContentParameters,\n ): Promise<AsyncGenerator<types.GenerateContentResponse>> {\n const maxRemoteCalls =\n params.config?.automaticFunctionCalling?.maximumRemoteCalls ??\n afc.DEFAULT_MAX_REMOTE_CALLS;\n let wereFunctionsCalled = false;\n let remoteCallCount = 0;\n const afcToolsMap = await this.initAfcToolsMap(params);\n return (async function* (\n models: Models,\n afcTools: Map<string, types.CallableTool>,\n params: types.GenerateContentParameters,\n ) {\n while (remoteCallCount < maxRemoteCalls) {\n if (wereFunctionsCalled) {\n remoteCallCount++;\n wereFunctionsCalled = false;\n }\n const transformedParams =\n await models.processParamsMaybeAddMcpUsage(params);\n const response =\n await models.generateContentStreamInternal(transformedParams);\n\n const functionResponses: types.Part[] = [];\n const responseContents: types.Content[] = [];\n\n for await (const chunk of response) {\n yield chunk;\n if (chunk.candidates && chunk.candidates[0]?.content) {\n responseContents.push(chunk.candidates[0].content);\n for (const part of chunk.candidates[0].content.parts ?? []) {\n if (remoteCallCount < maxRemoteCalls && part.functionCall) {\n if (!part.functionCall.name) {\n throw new Error(\n 'Function call name was not returned by the model.',\n );\n }\n if (!afcTools.has(part.functionCall.name)) {\n throw new Error(\n `Automatic function calling was requested, but not all the tools the model used implement the CallableTool interface. Available tools: ${afcTools.keys()}, mising tool: ${\n part.functionCall.name\n }`,\n );\n } else {\n const responseParts = await afcTools\n .get(part.functionCall.name)!\n .callTool([part.functionCall]);\n functionResponses.push(...responseParts);\n }\n }\n }\n }\n }\n\n if (functionResponses.length > 0) {\n wereFunctionsCalled = true;\n const typedResponseChunk = new types.GenerateContentResponse();\n typedResponseChunk.candidates = [\n {\n content: {\n role: 'user',\n parts: functionResponses,\n },\n },\n ];\n\n yield typedResponseChunk;\n\n const newContents: types.Content[] = [];\n newContents.push(...responseContents);\n newContents.push({\n role: 'user',\n parts: functionResponses,\n });\n const updatedContents = tContents(params.contents).concat(\n newContents,\n );\n\n params.contents = updatedContents;\n } else {\n break;\n }\n }\n })(this, afcToolsMap, params);\n }\n\n /**\n * Generates an image based on a text description and configuration.\n *\n * @param params - The parameters for generating images.\n * @return The response from the API.\n *\n * @example\n * ```ts\n * const response = await client.models.generateImages({\n * model: 'imagen-4.0-generate-001',\n * prompt: 'Robot holding a red skateboard',\n * config: {\n * numberOfImages: 1,\n * includeRaiReason: true,\n * },\n * });\n * console.log(response?.generatedImages?.[0]?.image?.imageBytes);\n * ```\n */\n generateImages = async (\n params: types.GenerateImagesParameters,\n ): Promise<types.GenerateImagesResponse> => {\n return await this.generateImagesInternal(params).then((apiResponse) => {\n let positivePromptSafetyAttributes;\n const generatedImages = [];\n\n if (apiResponse?.generatedImages) {\n for (const generatedImage of apiResponse.generatedImages) {\n if (\n generatedImage &&\n generatedImage?.safetyAttributes &&\n generatedImage?.safetyAttributes?.contentType === 'Positive Prompt'\n ) {\n positivePromptSafetyAttributes = generatedImage?.safetyAttributes;\n } else {\n generatedImages.push(generatedImage);\n }\n }\n }\n let response: types.GenerateImagesResponse;\n\n if (positivePromptSafetyAttributes) {\n response = {\n generatedImages: generatedImages,\n positivePromptSafetyAttributes: positivePromptSafetyAttributes,\n sdkHttpResponse: apiResponse.sdkHttpResponse,\n };\n } else {\n response = {\n generatedImages: generatedImages,\n sdkHttpResponse: apiResponse.sdkHttpResponse,\n };\n }\n return response;\n });\n };\n\n list = async (\n params?: types.ListModelsParameters,\n ): Promise<Pager<types.Model>> => {\n const defaultConfig: types.ListModelsConfig = {\n queryBase: true,\n };\n const actualConfig: types.ListModelsConfig = {\n ...defaultConfig,\n ...params?.config,\n };\n const actualParams: types.ListModelsParameters = {\n config: actualConfig,\n };\n\n if (this.apiClient.isVertexAI()) {\n if (!actualParams.config!.queryBase) {\n if (actualParams.config?.filter) {\n throw new Error(\n 'Filtering tuned models list for Vertex AI is not currently supported',\n );\n } else {\n actualParams.config!.filter = 'labels.tune-type:*';\n }\n }\n }\n\n return new Pager<types.Model>(\n PagedItem.PAGED_ITEM_MODELS,\n (x: types.ListModelsParameters) => this.listInternal(x),\n await this.listInternal(actualParams),\n actualParams,\n );\n };\n\n /**\n * Edits an image based on a prompt, list of reference images, and configuration.\n *\n * @param params - The parameters for editing an image.\n * @return The response from the API.\n *\n * @example\n * ```ts\n * const response = await client.models.editImage({\n * model: 'imagen-3.0-capability-001',\n * prompt: 'Generate an image containing a mug with the product logo [1] visible on the side of the mug.',\n * referenceImages: [subjectReferenceImage]\n * config: {\n * numberOfImages: 1,\n * includeRaiReason: true,\n * },\n * });\n * console.log(response?.generatedImages?.[0]?.image?.imageBytes);\n * ```\n */\n editImage = async (\n params: types.EditImageParameters,\n ): Promise<types.EditImageResponse> => {\n const paramsInternal: _internal_types.EditImageParametersInternal = {\n model: params.model,\n prompt: params.prompt,\n referenceImages: [],\n config: params.config,\n };\n if (params.referenceImages) {\n if (params.referenceImages) {\n paramsInternal.referenceImages = params.referenceImages.map((img) =>\n img.toReferenceImageAPI(),\n );\n }\n }\n return await this.editImageInternal(paramsInternal);\n };\n\n /**\n * Upscales an image based on an image, upscale factor, and configuration.\n * Only supported in Vertex AI currently.\n *\n * @param params - The parameters for upscaling an image.\n * @return The response from the API.\n *\n * @example\n * ```ts\n * const response = await client.models.upscaleImage({\n * model: 'imagen-4.0-upscale-preview',\n * image: image,\n * upscaleFactor: 'x2',\n * config: {\n * includeRaiReason: true,\n * },\n * });\n * console.log(response?.generatedImages?.[0]?.image?.imageBytes);\n * ```\n */\n upscaleImage = async (\n params: types.UpscaleImageParameters,\n ): Promise<types.UpscaleImageResponse> => {\n let apiConfig: _internal_types.UpscaleImageAPIConfigInternal = {\n numberOfImages: 1,\n mode: 'upscale',\n };\n\n if (params.config) {\n apiConfig = {...apiConfig, ...params.config};\n }\n\n const apiParams: _internal_types.UpscaleImageAPIParametersInternal = {\n model: params.model,\n image: params.image,\n upscaleFactor: params.upscaleFactor,\n config: apiConfig,\n };\n return await this.upscaleImageInternal(apiParams);\n };\n\n /**\n * Generates videos based on a text description and configuration.\n *\n * @param params - The parameters for generating videos.\n * @return A Promise<GenerateVideosOperation> which allows you to track the progress and eventually retrieve the generated videos using the operations.get method.\n *\n * @example\n * ```ts\n * const operation = await ai.models.generateVideos({\n * model: 'veo-2.0-generate-001',\n * source: {\n * prompt: 'A neon hologram of a cat driving at top speed',\n * },\n * config: {\n * numberOfVideos: 1\n * });\n *\n * while (!operation.done) {\n * await new Promise(resolve => setTimeout(resolve, 10000));\n * operation = await ai.operations.getVideosOperation({operation: operation});\n * }\n *\n * console.log(operation.response?.generatedVideos?.[0]?.video?.uri);\n * ```\n */\n\n generateVideos = async (\n params: types.GenerateVideosParameters,\n ): Promise<types.GenerateVideosOperation> => {\n if ((params.prompt || params.image || params.video) && params.source) {\n throw new Error(\n 'Source and prompt/image/video are mutually exclusive. Please only use source.',\n );\n }\n // Gemini API does not support video bytes.\n if (!this.apiClient.isVertexAI()) {\n if (params.video?.uri && params.video?.videoBytes) {\n params.video = {\n uri: params.video.uri,\n mimeType: params.video.mimeType,\n };\n } else if (\n params.source?.video?.uri &&\n params.source?.video?.videoBytes\n ) {\n params.source.video = {\n uri: params.source.video.uri,\n mimeType: params.source.video.mimeType,\n };\n }\n }\n return await this.generateVideosInternal(params);\n };\n\n private async generateContentInternal(\n params: types.GenerateContentParameters,\n ): Promise<types.GenerateContentResponse> {\n let response: Promise<types.GenerateContentResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.generateContentParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:generateContent',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.GenerateContentResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.GenerateContentResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.generateContentResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.GenerateContentResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n const body = converters.generateContentParametersToMldev(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:generateContent',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.GenerateContentResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.GenerateContentResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.generateContentResponseFromMldev(\n apiResponse,\n params,\n );\n const typedResp = new types.GenerateContentResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n private async generateContentStreamInternal(\n params: types.GenerateContentParameters,\n ): Promise<AsyncGenerator<types.GenerateContentResponse>> {\n let response: Promise<AsyncGenerator<types.HttpResponse>>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.generateContentParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:streamGenerateContent?alt=sse',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n const apiClient = this.apiClient;\n response = apiClient.requestStream({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n }) as Promise<AsyncGenerator<types.HttpResponse>>;\n\n return response.then(async function* (\n apiResponse: AsyncGenerator<types.HttpResponse>,\n ) {\n for await (const chunk of apiResponse) {\n const resp = converters.generateContentResponseFromVertex(\n (await chunk.json()) as types.GenerateContentResponse,\n params,\n );\n\n resp['sdkHttpResponse'] = {\n headers: chunk.headers,\n } as types.HttpResponse;\n\n const typedResp = new types.GenerateContentResponse();\n Object.assign(typedResp, resp);\n yield typedResp;\n }\n });\n } else {\n const body = converters.generateContentParametersToMldev(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:streamGenerateContent?alt=sse',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n const apiClient = this.apiClient;\n response = apiClient.requestStream({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n }) as Promise<AsyncGenerator<types.HttpResponse>>;\n\n return response.then(async function* (\n apiResponse: AsyncGenerator<types.HttpResponse>,\n ) {\n for await (const chunk of apiResponse) {\n const resp = converters.generateContentResponseFromMldev(\n (await chunk.json()) as types.GenerateContentResponse,\n params,\n );\n\n resp['sdkHttpResponse'] = {\n headers: chunk.headers,\n } as types.HttpResponse;\n\n const typedResp = new types.GenerateContentResponse();\n Object.assign(typedResp, resp);\n yield typedResp;\n }\n });\n }\n }\n\n /**\n * Calculates embeddings for the given contents. Only text is supported.\n *\n * @param params - The parameters for embedding contents.\n * @return The response from the API.\n *\n * @example\n * ```ts\n * const response = await ai.models.embedContent({\n * model: 'text-embedding-004',\n * contents: [\n * 'What is your name?',\n * 'What is your favorite color?',\n * ],\n * config: {\n * outputDimensionality: 64,\n * },\n * });\n * console.log(response);\n * ```\n */\n async embedContent(\n params: types.EmbedContentParameters,\n ): Promise<types.EmbedContentResponse> {\n let response: Promise<types.EmbedContentResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.embedContentParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:predict',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.EmbedContentResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.EmbedContentResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.embedContentResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.EmbedContentResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n const body = converters.embedContentParametersToMldev(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:batchEmbedContents',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.EmbedContentResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.EmbedContentResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.embedContentResponseFromMldev(\n apiResponse,\n params,\n );\n const typedResp = new types.EmbedContentResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n /**\n * Private method for generating images.\n */\n private async generateImagesInternal(\n params: types.GenerateImagesParameters,\n ): Promise<types.GenerateImagesResponse> {\n let response: Promise<types.GenerateImagesResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.generateImagesParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:predict',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.GenerateImagesResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.GenerateImagesResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.generateImagesResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.GenerateImagesResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n const body = converters.generateImagesParametersToMldev(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:predict',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.GenerateImagesResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.GenerateImagesResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.generateImagesResponseFromMldev(\n apiResponse,\n params,\n );\n const typedResp = new types.GenerateImagesResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n /**\n * Private method for editing an image.\n */\n private async editImageInternal(\n params: _internal_types.EditImageParametersInternal,\n ): Promise<types.EditImageResponse> {\n let response: Promise<types.EditImageResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.editImageParametersInternalToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:predict',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.EditImageResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.EditImageResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.editImageResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.EditImageResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n throw new Error('This method is only supported by the Vertex AI.');\n }\n }\n\n /**\n * Private method for upscaling an image.\n */\n private async upscaleImageInternal(\n params: _internal_types.UpscaleImageAPIParametersInternal,\n ): Promise<types.UpscaleImageResponse> {\n let response: Promise<types.UpscaleImageResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.upscaleImageAPIParametersInternalToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:predict',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.UpscaleImageResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.UpscaleImageResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.upscaleImageResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.UpscaleImageResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n throw new Error('This method is only supported by the Vertex AI.');\n }\n }\n\n /**\n * Recontextualizes an image.\n *\n * There are two types of recontextualization currently supported:\n * 1) Imagen Product Recontext - Generate images of products in new scenes\n * and contexts.\n * 2) Virtual Try-On: Generate images of persons modeling fashion products.\n *\n * @param params - The parameters for recontextualizing an image.\n * @return The response from the API.\n *\n * @example\n * ```ts\n * const response1 = await ai.models.recontextImage({\n * model: 'imagen-product-recontext-preview-06-30',\n * source: {\n * prompt: 'In a modern kitchen setting.',\n * productImages: [productImage],\n * },\n * config: {\n * numberOfImages: 1,\n * },\n * });\n * console.log(response1?.generatedImages?.[0]?.image?.imageBytes);\n *\n * const response2 = await ai.models.recontextImage({\n * model: 'virtual-try-on-001',\n * source: {\n * personImage: personImage,\n * productImages: [productImage],\n * },\n * config: {\n * numberOfImages: 1,\n * },\n * });\n * console.log(response2?.generatedImages?.[0]?.image?.imageBytes);\n * ```\n */\n async recontextImage(\n params: types.RecontextImageParameters,\n ): Promise<types.RecontextImageResponse> {\n let response: Promise<types.RecontextImageResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.recontextImageParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:predict',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.RecontextImageResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.recontextImageResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.RecontextImageResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n throw new Error('This method is only supported by the Vertex AI.');\n }\n }\n\n /**\n * Segments an image, creating a mask of a specified area.\n *\n * @param params - The parameters for segmenting an image.\n * @return The response from the API.\n *\n * @example\n * ```ts\n * const response = await ai.models.segmentImage({\n * model: 'image-segmentation-001',\n * source: {\n * image: image,\n * },\n * config: {\n * mode: 'foreground',\n * },\n * });\n * console.log(response?.generatedMasks?.[0]?.mask?.imageBytes);\n * ```\n */\n async segmentImage(\n params: types.SegmentImageParameters,\n ): Promise<types.SegmentImageResponse> {\n let response: Promise<types.SegmentImageResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.segmentImageParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:predict',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.SegmentImageResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.segmentImageResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.SegmentImageResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n throw new Error('This method is only supported by the Vertex AI.');\n }\n }\n\n /**\n * Fetches information about a model by name.\n *\n * @example\n * ```ts\n * const modelInfo = await ai.models.get({model: 'gemini-2.0-flash'});\n * ```\n */\n async get(params: types.GetModelParameters): Promise<types.Model> {\n let response: Promise<types.Model>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.getModelParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.Model>;\n\n return response.then((apiResponse) => {\n const resp = converters.modelFromVertex(apiResponse, params);\n\n return resp as types.Model;\n });\n } else {\n const body = converters.getModelParametersToMldev(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.Model>;\n\n return response.then((apiResponse) => {\n const resp = converters.modelFromMldev(apiResponse, params);\n\n return resp as types.Model;\n });\n }\n }\n\n private async listInternal(\n params: types.ListModelsParameters,\n ): Promise<types.ListModelsResponse> {\n let response: Promise<types.ListModelsResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.listModelsParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{models_url}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.ListModelsResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.ListModelsResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.listModelsResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.ListModelsResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n const body = converters.listModelsParametersToMldev(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{models_url}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.ListModelsResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.ListModelsResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.listModelsResponseFromMldev(\n apiResponse,\n params,\n );\n const typedResp = new types.ListModelsResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n /**\n * Updates a tuned model by its name.\n *\n * @param params - The parameters for updating the model.\n * @return The response from the API.\n *\n * @example\n * ```ts\n * const response = await ai.models.update({\n * model: 'tuned-model-name',\n * config: {\n * displayName: 'New display name',\n * description: 'New description',\n * },\n * });\n * ```\n */\n async update(params: types.UpdateModelParameters): Promise<types.Model> {\n let response: Promise<types.Model>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.updateModelParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'PATCH',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.Model>;\n\n return response.then((apiResponse) => {\n const resp = converters.modelFromVertex(apiResponse, params);\n\n return resp as types.Model;\n });\n } else {\n const body = converters.updateModelParametersToMldev(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'PATCH',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.Model>;\n\n return response.then((apiResponse) => {\n const resp = converters.modelFromMldev(apiResponse, params);\n\n return resp as types.Model;\n });\n }\n }\n\n /**\n * Deletes a tuned model by its name.\n *\n * @param params - The parameters for deleting the model.\n * @return The response from the API.\n *\n * @example\n * ```ts\n * const response = await ai.models.delete({model: 'tuned-model-name'});\n * ```\n */\n async delete(\n params: types.DeleteModelParameters,\n ): Promise<types.DeleteModelResponse> {\n let response: Promise<types.DeleteModelResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.deleteModelParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'DELETE',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.DeleteModelResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.DeleteModelResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.deleteModelResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.DeleteModelResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n const body = converters.deleteModelParametersToMldev(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'DELETE',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.DeleteModelResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.DeleteModelResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.deleteModelResponseFromMldev(\n apiResponse,\n params,\n );\n const typedResp = new types.DeleteModelResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n /**\n * Counts the number of tokens in the given contents. Multimodal input is\n * supported for Gemini models.\n *\n * @param params - The parameters for counting tokens.\n * @return The response from the API.\n *\n * @example\n * ```ts\n * const response = await ai.models.countTokens({\n * model: 'gemini-2.0-flash',\n * contents: 'The quick brown fox jumps over the lazy dog.'\n * });\n * console.log(response);\n * ```\n */\n async countTokens(\n params: types.CountTokensParameters,\n ): Promise<types.CountTokensResponse> {\n let response: Promise<types.CountTokensResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.countTokensParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:countTokens',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.CountTokensResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.CountTokensResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.countTokensResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.CountTokensResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n const body = converters.countTokensParametersToMldev(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:countTokens',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.CountTokensResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.CountTokensResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.countTokensResponseFromMldev(\n apiResponse,\n params,\n );\n const typedResp = new types.CountTokensResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n /**\n * Given a list of contents, returns a corresponding TokensInfo containing\n * the list of tokens and list of token ids.\n *\n * This method is not supported by the Gemini Developer API.\n *\n * @param params - The parameters for computing tokens.\n * @return The response from the API.\n *\n * @example\n * ```ts\n * const response = await ai.models.computeTokens({\n * model: 'gemini-2.0-flash',\n * contents: 'What is your name?'\n * });\n * console.log(response);\n * ```\n */\n async computeTokens(\n params: types.ComputeTokensParameters,\n ): Promise<types.ComputeTokensResponse> {\n let response: Promise<types.ComputeTokensResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.computeTokensParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:computeTokens',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.ComputeTokensResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.ComputeTokensResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.computeTokensResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.ComputeTokensResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n throw new Error('This method is only supported by the Vertex AI.');\n }\n }\n\n /**\n * Private method for generating videos.\n */\n private async generateVideosInternal(\n params: types.GenerateVideosParameters,\n ): Promise<types.GenerateVideosOperation> {\n let response: Promise<types.GenerateVideosOperation>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.generateVideosParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:predictLongRunning',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.GenerateVideosOperation>;\n\n return response.then((apiResponse) => {\n const resp = converters.generateVideosOperationFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.GenerateVideosOperation();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n const body = converters.generateVideosParametersToMldev(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:predictLongRunning',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.GenerateVideosOperation>;\n\n return response.then((apiResponse) => {\n const resp = converters.generateVideosOperationFromMldev(\n apiResponse,\n params,\n );\n const typedResp = new types.GenerateVideosOperation();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport {ApiClient} from './_api_client.js';\nimport * as common from './_common.js';\nimport {BaseModule} from './_common.js';\nimport * as converters from './converters/_operations_converters.js';\nimport * as types from './types.js';\n\nexport class Operations extends BaseModule {\n constructor(private readonly apiClient: ApiClient) {\n super();\n }\n\n /**\n * Gets the status of a long-running operation.\n *\n * @param parameters The parameters for the get operation request.\n * @return The updated Operation object, with the latest status or result.\n */\n async getVideosOperation(\n parameters: types.OperationGetParameters<\n types.GenerateVideosResponse,\n types.GenerateVideosOperation\n >,\n ): Promise<types.GenerateVideosOperation> {\n const operation = parameters.operation;\n const config = parameters.config;\n\n if (operation.name === undefined || operation.name === '') {\n throw new Error('Operation name is required.');\n }\n\n if (this.apiClient.isVertexAI()) {\n const resourceName = operation.name.split('/operations/')[0];\n let httpOptions: types.HttpOptions | undefined = undefined;\n\n if (config && 'httpOptions' in config) {\n httpOptions = config.httpOptions;\n }\n\n const rawOperation = await this.fetchPredictVideosOperationInternal({\n operationName: operation.name,\n resourceName: resourceName,\n config: {httpOptions: httpOptions},\n });\n\n return operation._fromAPIResponse({\n apiResponse: rawOperation,\n _isVertexAI: true,\n });\n } else {\n const rawOperation = await this.getVideosOperationInternal({\n operationName: operation.name,\n config: config,\n });\n return operation._fromAPIResponse({\n apiResponse: rawOperation,\n _isVertexAI: false,\n });\n }\n }\n\n /**\n * Gets the status of a long-running operation.\n *\n * @param parameters The parameters for the get operation request.\n * @return The updated Operation object, with the latest status or result.\n */\n async get<T, U extends types.Operation<T>>(\n parameters: types.OperationGetParameters<T, U>,\n ): Promise<types.Operation<T>> {\n const operation = parameters.operation;\n const config = parameters.config;\n\n if (operation.name === undefined || operation.name === '') {\n throw new Error('Operation name is required.');\n }\n\n if (this.apiClient.isVertexAI()) {\n const resourceName = operation.name.split('/operations/')[0];\n let httpOptions: types.HttpOptions | undefined = undefined;\n\n if (config && 'httpOptions' in config) {\n httpOptions = config.httpOptions;\n }\n\n const rawOperation = await this.fetchPredictVideosOperationInternal({\n operationName: operation.name,\n resourceName: resourceName,\n config: {httpOptions: httpOptions},\n });\n\n return operation._fromAPIResponse({\n apiResponse: rawOperation,\n _isVertexAI: true,\n });\n } else {\n const rawOperation = await this.getVideosOperationInternal({\n operationName: operation.name,\n config: config,\n });\n return operation._fromAPIResponse({\n apiResponse: rawOperation,\n _isVertexAI: false,\n });\n }\n }\n\n private async getVideosOperationInternal(\n params: types.GetOperationParameters,\n ): Promise<Record<string, unknown>> {\n let response: Promise<Record<string, unknown>>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.getOperationParametersToVertex(params);\n path = common.formatMap(\n '{operationName}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<Record<string, unknown>>;\n\n return response;\n } else {\n const body = converters.getOperationParametersToMldev(params);\n path = common.formatMap(\n '{operationName}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<Record<string, unknown>>;\n\n return response;\n }\n }\n\n private async fetchPredictVideosOperationInternal(\n params: types.FetchPredictOperationParameters,\n ): Promise<Record<string, unknown>> {\n let response: Promise<Record<string, unknown>>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.fetchPredictOperationParametersToVertex(params);\n path = common.formatMap(\n '{resourceName}:fetchPredictOperation',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<Record<string, unknown>>;\n\n return response;\n } else {\n throw new Error('This method is only supported by the Vertex AI.');\n }\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport {ApiClient} from '../_api_client.js';\nimport * as common from '../_common.js';\nimport * as t from '../_transformers.js';\nimport type * as types from '../types.js';\n\nexport function blobToMldev(fromObject: types.Blob): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromData = common.getValueByPath(fromObject, ['data']);\n if (fromData != null) {\n common.setValueByPath(toObject, ['data'], fromData);\n }\n\n if (common.getValueByPath(fromObject, ['displayName']) !== undefined) {\n throw new Error('displayName parameter is not supported in Gemini API.');\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function contentToMldev(\n fromObject: types.Content,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromParts = common.getValueByPath(fromObject, ['parts']);\n if (fromParts != null) {\n let transformedList = fromParts;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return partToMldev(item);\n });\n }\n common.setValueByPath(toObject, ['parts'], transformedList);\n }\n\n const fromRole = common.getValueByPath(fromObject, ['role']);\n if (fromRole != null) {\n common.setValueByPath(toObject, ['role'], fromRole);\n }\n\n return toObject;\n}\n\nexport function createAuthTokenConfigToMldev(\n apiClient: ApiClient,\n fromObject: types.CreateAuthTokenConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromExpireTime = common.getValueByPath(fromObject, ['expireTime']);\n if (parentObject !== undefined && fromExpireTime != null) {\n common.setValueByPath(parentObject, ['expireTime'], fromExpireTime);\n }\n\n const fromNewSessionExpireTime = common.getValueByPath(fromObject, [\n 'newSessionExpireTime',\n ]);\n if (parentObject !== undefined && fromNewSessionExpireTime != null) {\n common.setValueByPath(\n parentObject,\n ['newSessionExpireTime'],\n fromNewSessionExpireTime,\n );\n }\n\n const fromUses = common.getValueByPath(fromObject, ['uses']);\n if (parentObject !== undefined && fromUses != null) {\n common.setValueByPath(parentObject, ['uses'], fromUses);\n }\n\n const fromLiveConnectConstraints = common.getValueByPath(fromObject, [\n 'liveConnectConstraints',\n ]);\n if (parentObject !== undefined && fromLiveConnectConstraints != null) {\n common.setValueByPath(\n parentObject,\n ['bidiGenerateContentSetup'],\n liveConnectConstraintsToMldev(apiClient, fromLiveConnectConstraints),\n );\n }\n\n const fromLockAdditionalFields = common.getValueByPath(fromObject, [\n 'lockAdditionalFields',\n ]);\n if (parentObject !== undefined && fromLockAdditionalFields != null) {\n common.setValueByPath(\n parentObject,\n ['fieldMask'],\n fromLockAdditionalFields,\n );\n }\n\n return toObject;\n}\n\nexport function createAuthTokenParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.CreateAuthTokenParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n common.setValueByPath(\n toObject,\n ['config'],\n createAuthTokenConfigToMldev(apiClient, fromConfig, toObject),\n );\n }\n\n return toObject;\n}\n\nexport function createAuthTokenParametersToVertex(\n fromObject: types.CreateAuthTokenParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['config']) !== undefined) {\n throw new Error('config parameter is not supported in Vertex AI.');\n }\n\n return toObject;\n}\n\nexport function fileDataToMldev(\n fromObject: types.FileData,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['displayName']) !== undefined) {\n throw new Error('displayName parameter is not supported in Gemini API.');\n }\n\n const fromFileUri = common.getValueByPath(fromObject, ['fileUri']);\n if (fromFileUri != null) {\n common.setValueByPath(toObject, ['fileUri'], fromFileUri);\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function functionCallToMldev(\n fromObject: types.FunctionCall,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromId = common.getValueByPath(fromObject, ['id']);\n if (fromId != null) {\n common.setValueByPath(toObject, ['id'], fromId);\n }\n\n const fromArgs = common.getValueByPath(fromObject, ['args']);\n if (fromArgs != null) {\n common.setValueByPath(toObject, ['args'], fromArgs);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n if (common.getValueByPath(fromObject, ['partialArgs']) !== undefined) {\n throw new Error('partialArgs parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['willContinue']) !== undefined) {\n throw new Error('willContinue parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function googleMapsToMldev(\n fromObject: types.GoogleMaps,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['authConfig']) !== undefined) {\n throw new Error('authConfig parameter is not supported in Gemini API.');\n }\n\n const fromEnableWidget = common.getValueByPath(fromObject, ['enableWidget']);\n if (fromEnableWidget != null) {\n common.setValueByPath(toObject, ['enableWidget'], fromEnableWidget);\n }\n\n return toObject;\n}\n\nexport function googleSearchToMldev(\n fromObject: types.GoogleSearch,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['excludeDomains']) !== undefined) {\n throw new Error('excludeDomains parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['blockingConfidence']) !== undefined) {\n throw new Error(\n 'blockingConfidence parameter is not supported in Gemini API.',\n );\n }\n\n const fromTimeRangeFilter = common.getValueByPath(fromObject, [\n 'timeRangeFilter',\n ]);\n if (fromTimeRangeFilter != null) {\n common.setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter);\n }\n\n return toObject;\n}\n\nexport function liveConnectConfigToMldev(\n fromObject: types.LiveConnectConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromGenerationConfig = common.getValueByPath(fromObject, [\n 'generationConfig',\n ]);\n if (parentObject !== undefined && fromGenerationConfig != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig'],\n fromGenerationConfig,\n );\n }\n\n const fromResponseModalities = common.getValueByPath(fromObject, [\n 'responseModalities',\n ]);\n if (parentObject !== undefined && fromResponseModalities != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'responseModalities'],\n fromResponseModalities,\n );\n }\n\n const fromTemperature = common.getValueByPath(fromObject, ['temperature']);\n if (parentObject !== undefined && fromTemperature != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'temperature'],\n fromTemperature,\n );\n }\n\n const fromTopP = common.getValueByPath(fromObject, ['topP']);\n if (parentObject !== undefined && fromTopP != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'topP'],\n fromTopP,\n );\n }\n\n const fromTopK = common.getValueByPath(fromObject, ['topK']);\n if (parentObject !== undefined && fromTopK != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'topK'],\n fromTopK,\n );\n }\n\n const fromMaxOutputTokens = common.getValueByPath(fromObject, [\n 'maxOutputTokens',\n ]);\n if (parentObject !== undefined && fromMaxOutputTokens != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'maxOutputTokens'],\n fromMaxOutputTokens,\n );\n }\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (parentObject !== undefined && fromMediaResolution != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'mediaResolution'],\n fromMediaResolution,\n );\n }\n\n const fromSeed = common.getValueByPath(fromObject, ['seed']);\n if (parentObject !== undefined && fromSeed != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'seed'],\n fromSeed,\n );\n }\n\n const fromSpeechConfig = common.getValueByPath(fromObject, ['speechConfig']);\n if (parentObject !== undefined && fromSpeechConfig != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'speechConfig'],\n t.tLiveSpeechConfig(fromSpeechConfig),\n );\n }\n\n const fromThinkingConfig = common.getValueByPath(fromObject, [\n 'thinkingConfig',\n ]);\n if (parentObject !== undefined && fromThinkingConfig != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'thinkingConfig'],\n fromThinkingConfig,\n );\n }\n\n const fromEnableAffectiveDialog = common.getValueByPath(fromObject, [\n 'enableAffectiveDialog',\n ]);\n if (parentObject !== undefined && fromEnableAffectiveDialog != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'enableAffectiveDialog'],\n fromEnableAffectiveDialog,\n );\n }\n\n const fromSystemInstruction = common.getValueByPath(fromObject, [\n 'systemInstruction',\n ]);\n if (parentObject !== undefined && fromSystemInstruction != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'systemInstruction'],\n contentToMldev(t.tContent(fromSystemInstruction)),\n );\n }\n\n const fromTools = common.getValueByPath(fromObject, ['tools']);\n if (parentObject !== undefined && fromTools != null) {\n let transformedList = t.tTools(fromTools);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return toolToMldev(t.tTool(item));\n });\n }\n common.setValueByPath(parentObject, ['setup', 'tools'], transformedList);\n }\n\n const fromSessionResumption = common.getValueByPath(fromObject, [\n 'sessionResumption',\n ]);\n if (parentObject !== undefined && fromSessionResumption != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'sessionResumption'],\n sessionResumptionConfigToMldev(fromSessionResumption),\n );\n }\n\n const fromInputAudioTranscription = common.getValueByPath(fromObject, [\n 'inputAudioTranscription',\n ]);\n if (parentObject !== undefined && fromInputAudioTranscription != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'inputAudioTranscription'],\n fromInputAudioTranscription,\n );\n }\n\n const fromOutputAudioTranscription = common.getValueByPath(fromObject, [\n 'outputAudioTranscription',\n ]);\n if (parentObject !== undefined && fromOutputAudioTranscription != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'outputAudioTranscription'],\n fromOutputAudioTranscription,\n );\n }\n\n const fromRealtimeInputConfig = common.getValueByPath(fromObject, [\n 'realtimeInputConfig',\n ]);\n if (parentObject !== undefined && fromRealtimeInputConfig != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'realtimeInputConfig'],\n fromRealtimeInputConfig,\n );\n }\n\n const fromContextWindowCompression = common.getValueByPath(fromObject, [\n 'contextWindowCompression',\n ]);\n if (parentObject !== undefined && fromContextWindowCompression != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'contextWindowCompression'],\n fromContextWindowCompression,\n );\n }\n\n const fromProactivity = common.getValueByPath(fromObject, ['proactivity']);\n if (parentObject !== undefined && fromProactivity != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'proactivity'],\n fromProactivity,\n );\n }\n\n if (common.getValueByPath(fromObject, ['explicitVadSignal']) !== undefined) {\n throw new Error(\n 'explicitVadSignal parameter is not supported in Gemini API.',\n );\n }\n\n return toObject;\n}\n\nexport function liveConnectConstraintsToMldev(\n apiClient: ApiClient,\n fromObject: types.LiveConnectConstraints,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['setup', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n common.setValueByPath(\n toObject,\n ['config'],\n liveConnectConfigToMldev(fromConfig, toObject),\n );\n }\n\n return toObject;\n}\n\nexport function partToMldev(fromObject: types.Part): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (fromMediaResolution != null) {\n common.setValueByPath(toObject, ['mediaResolution'], fromMediaResolution);\n }\n\n const fromCodeExecutionResult = common.getValueByPath(fromObject, [\n 'codeExecutionResult',\n ]);\n if (fromCodeExecutionResult != null) {\n common.setValueByPath(\n toObject,\n ['codeExecutionResult'],\n fromCodeExecutionResult,\n );\n }\n\n const fromExecutableCode = common.getValueByPath(fromObject, [\n 'executableCode',\n ]);\n if (fromExecutableCode != null) {\n common.setValueByPath(toObject, ['executableCode'], fromExecutableCode);\n }\n\n const fromFileData = common.getValueByPath(fromObject, ['fileData']);\n if (fromFileData != null) {\n common.setValueByPath(\n toObject,\n ['fileData'],\n fileDataToMldev(fromFileData),\n );\n }\n\n const fromFunctionCall = common.getValueByPath(fromObject, ['functionCall']);\n if (fromFunctionCall != null) {\n common.setValueByPath(\n toObject,\n ['functionCall'],\n functionCallToMldev(fromFunctionCall),\n );\n }\n\n const fromFunctionResponse = common.getValueByPath(fromObject, [\n 'functionResponse',\n ]);\n if (fromFunctionResponse != null) {\n common.setValueByPath(toObject, ['functionResponse'], fromFunctionResponse);\n }\n\n const fromInlineData = common.getValueByPath(fromObject, ['inlineData']);\n if (fromInlineData != null) {\n common.setValueByPath(\n toObject,\n ['inlineData'],\n blobToMldev(fromInlineData),\n );\n }\n\n const fromText = common.getValueByPath(fromObject, ['text']);\n if (fromText != null) {\n common.setValueByPath(toObject, ['text'], fromText);\n }\n\n const fromThought = common.getValueByPath(fromObject, ['thought']);\n if (fromThought != null) {\n common.setValueByPath(toObject, ['thought'], fromThought);\n }\n\n const fromThoughtSignature = common.getValueByPath(fromObject, [\n 'thoughtSignature',\n ]);\n if (fromThoughtSignature != null) {\n common.setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature);\n }\n\n const fromVideoMetadata = common.getValueByPath(fromObject, [\n 'videoMetadata',\n ]);\n if (fromVideoMetadata != null) {\n common.setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata);\n }\n\n return toObject;\n}\n\nexport function sessionResumptionConfigToMldev(\n fromObject: types.SessionResumptionConfig,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromHandle = common.getValueByPath(fromObject, ['handle']);\n if (fromHandle != null) {\n common.setValueByPath(toObject, ['handle'], fromHandle);\n }\n\n if (common.getValueByPath(fromObject, ['transparent']) !== undefined) {\n throw new Error('transparent parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function toolToMldev(fromObject: types.Tool): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['retrieval']) !== undefined) {\n throw new Error('retrieval parameter is not supported in Gemini API.');\n }\n\n const fromComputerUse = common.getValueByPath(fromObject, ['computerUse']);\n if (fromComputerUse != null) {\n common.setValueByPath(toObject, ['computerUse'], fromComputerUse);\n }\n\n const fromFileSearch = common.getValueByPath(fromObject, ['fileSearch']);\n if (fromFileSearch != null) {\n common.setValueByPath(toObject, ['fileSearch'], fromFileSearch);\n }\n\n const fromCodeExecution = common.getValueByPath(fromObject, [\n 'codeExecution',\n ]);\n if (fromCodeExecution != null) {\n common.setValueByPath(toObject, ['codeExecution'], fromCodeExecution);\n }\n\n if (\n common.getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined\n ) {\n throw new Error(\n 'enterpriseWebSearch parameter is not supported in Gemini API.',\n );\n }\n\n const fromFunctionDeclarations = common.getValueByPath(fromObject, [\n 'functionDeclarations',\n ]);\n if (fromFunctionDeclarations != null) {\n let transformedList = fromFunctionDeclarations;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['functionDeclarations'], transformedList);\n }\n\n const fromGoogleMaps = common.getValueByPath(fromObject, ['googleMaps']);\n if (fromGoogleMaps != null) {\n common.setValueByPath(\n toObject,\n ['googleMaps'],\n googleMapsToMldev(fromGoogleMaps),\n );\n }\n\n const fromGoogleSearch = common.getValueByPath(fromObject, ['googleSearch']);\n if (fromGoogleSearch != null) {\n common.setValueByPath(\n toObject,\n ['googleSearch'],\n googleSearchToMldev(fromGoogleSearch),\n );\n }\n\n const fromGoogleSearchRetrieval = common.getValueByPath(fromObject, [\n 'googleSearchRetrieval',\n ]);\n if (fromGoogleSearchRetrieval != null) {\n common.setValueByPath(\n toObject,\n ['googleSearchRetrieval'],\n fromGoogleSearchRetrieval,\n );\n }\n\n const fromUrlContext = common.getValueByPath(fromObject, ['urlContext']);\n if (fromUrlContext != null) {\n common.setValueByPath(toObject, ['urlContext'], fromUrlContext);\n }\n\n return toObject;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {ApiClient} from './_api_client.js';\nimport * as common from './_common.js';\nimport {BaseModule} from './_common.js';\nimport * as converters from './converters/_tokens_converters.js';\nimport * as types from './types.js';\n\n/**\n * Returns a comma-separated list of field masks from a given object.\n *\n * @param setup The object to extract field masks from.\n * @return A comma-separated list of field masks.\n */\nfunction getFieldMasks(setup: Record<string, unknown>): string {\n const fields: string[] = [];\n\n for (const key in setup) {\n if (Object.prototype.hasOwnProperty.call(setup, key)) {\n const value = setup[key];\n // 2nd layer, recursively get field masks see TODO(b/418290100)\n if (\n typeof value === 'object' &&\n value != null &&\n Object.keys(value).length > 0\n ) {\n const field = Object.keys(value).map((kk) => `${key}.${kk}`);\n fields.push(...field);\n } else {\n fields.push(key); // 1st layer\n }\n }\n }\n\n return fields.join(',');\n}\n\n/**\n * Converts bidiGenerateContentSetup.\n * @param requestDict - The request dictionary.\n * @param config - The configuration object.\n * @return - The modified request dictionary.\n */\nfunction convertBidiSetupToTokenSetup(\n requestDict: Record<string, unknown>,\n config?: {lockAdditionalFields?: string[]},\n): Record<string, unknown> {\n // Convert bidiGenerateContentSetup from bidiGenerateContentSetup.setup.\n let setupForMaskGeneration: Record<string, unknown> | null = null;\n const bidiGenerateContentSetupValue = requestDict['bidiGenerateContentSetup'];\n if (\n typeof bidiGenerateContentSetupValue === 'object' &&\n bidiGenerateContentSetupValue !== null &&\n 'setup' in bidiGenerateContentSetupValue\n ) {\n // Now we know bidiGenerateContentSetupValue is an object and has a 'setup'\n // property.\n const innerSetup = (bidiGenerateContentSetupValue as {setup: unknown})\n .setup;\n\n if (typeof innerSetup === 'object' && innerSetup !== null) {\n // Valid inner setup found.\n requestDict['bidiGenerateContentSetup'] = innerSetup;\n setupForMaskGeneration = innerSetup as Record<string, unknown>;\n } else {\n // `bidiGenerateContentSetupValue.setup` is not a valid object; treat as\n // if bidiGenerateContentSetup is invalid.\n delete requestDict['bidiGenerateContentSetup'];\n }\n } else if (bidiGenerateContentSetupValue !== undefined) {\n // `bidiGenerateContentSetup` exists but not in the expected\n // shape {setup: {...}}; treat as invalid.\n delete requestDict['bidiGenerateContentSetup'];\n }\n\n const preExistingFieldMask = requestDict['fieldMask'];\n // Handle mask generation setup.\n if (setupForMaskGeneration) {\n const generatedMaskFromBidi = getFieldMasks(setupForMaskGeneration);\n\n if (\n Array.isArray(config?.lockAdditionalFields) &&\n config?.lockAdditionalFields.length === 0\n ) {\n // Case 1: lockAdditionalFields is an empty array. Lock only fields from\n // bidi setup.\n if (generatedMaskFromBidi) {\n // Only assign if mask is not empty\n requestDict['fieldMask'] = generatedMaskFromBidi;\n } else {\n delete requestDict['fieldMask']; // If mask is empty, effectively no\n // specific fields locked by bidi\n }\n } else if (\n config?.lockAdditionalFields &&\n config.lockAdditionalFields.length > 0 &&\n preExistingFieldMask !== null &&\n Array.isArray(preExistingFieldMask) &&\n preExistingFieldMask.length > 0\n ) {\n // Case 2: Lock fields from bidi setup + additional fields\n // (preExistingFieldMask).\n\n const generationConfigFields = [\n 'temperature',\n 'topK',\n 'topP',\n 'maxOutputTokens',\n 'responseModalities',\n 'seed',\n 'speechConfig',\n ];\n\n let mappedFieldsFromPreExisting: string[] = [];\n if (preExistingFieldMask.length > 0) {\n mappedFieldsFromPreExisting = preExistingFieldMask.map((field) => {\n if (generationConfigFields.includes(field)) {\n return `generationConfig.${field}`;\n }\n return field; // Keep original field name if not in\n // generationConfigFields\n });\n }\n\n const finalMaskParts: string[] = [];\n if (generatedMaskFromBidi) {\n finalMaskParts.push(generatedMaskFromBidi);\n }\n if (mappedFieldsFromPreExisting.length > 0) {\n finalMaskParts.push(...mappedFieldsFromPreExisting);\n }\n\n if (finalMaskParts.length > 0) {\n requestDict['fieldMask'] = finalMaskParts.join(',');\n } else {\n // If no fields from bidi and no valid additional fields from\n // pre-existing mask.\n delete requestDict['fieldMask'];\n }\n } else {\n // Case 3: \"Lock all fields\" (meaning, don't send a field_mask, let server\n // defaults apply or all are mutable). This is hit if:\n // - `config.lockAdditionalFields` is undefined.\n // - `config.lockAdditionalFields` is non-empty, BUT\n // `preExistingFieldMask` is null, not a string, or an empty string.\n delete requestDict['fieldMask'];\n }\n } else {\n // No valid `bidiGenerateContentSetup` was found or extracted.\n // \"Lock additional null fields if any\".\n if (\n preExistingFieldMask !== null &&\n Array.isArray(preExistingFieldMask) &&\n preExistingFieldMask.length > 0\n ) {\n // If there's a pre-existing field mask, it's a string, and it's not\n // empty, then we should lock all fields.\n requestDict['fieldMask'] = preExistingFieldMask.join(',');\n } else {\n delete requestDict['fieldMask'];\n }\n }\n\n return requestDict;\n}\n\nexport class Tokens extends BaseModule {\n constructor(private readonly apiClient: ApiClient) {\n super();\n }\n /**\n * Creates an ephemeral auth token resource.\n *\n * @experimental\n *\n * @remarks\n * Ephemeral auth tokens is only supported in the Gemini Developer API.\n * It can be used for the session connection to the Live constrained API.\n * Support in v1alpha only.\n *\n * @param params - The parameters for the create request.\n * @return The created auth token.\n *\n * @example\n * ```ts\n * const ai = new GoogleGenAI({\n * apiKey: token.name,\n * httpOptions: { apiVersion: 'v1alpha' } // Support in v1alpha only.\n * });\n *\n * // Case 1: If LiveEphemeralParameters is unset, unlock LiveConnectConfig\n * // when using the token in Live API sessions. Each session connection can\n * // use a different configuration.\n * const config: CreateAuthTokenConfig = {\n * uses: 3,\n * expireTime: '2025-05-01T00:00:00Z',\n * }\n * const token = await ai.tokens.create(config);\n *\n * // Case 2: If LiveEphemeralParameters is set, lock all fields in\n * // LiveConnectConfig when using the token in Live API sessions. For\n * // example, changing `outputAudioTranscription` in the Live API\n * // connection will be ignored by the API.\n * const config: CreateAuthTokenConfig =\n * uses: 3,\n * expireTime: '2025-05-01T00:00:00Z',\n * LiveEphemeralParameters: {\n * model: 'gemini-2.0-flash-001',\n * config: {\n * 'responseModalities': ['AUDIO'],\n * 'systemInstruction': 'Always answer in English.',\n * }\n * }\n * }\n * const token = await ai.tokens.create(config);\n *\n * // Case 3: If LiveEphemeralParameters is set and lockAdditionalFields is\n * // set, lock LiveConnectConfig with set and additional fields (e.g.\n * // responseModalities, systemInstruction, temperature in this example) when\n * // using the token in Live API sessions.\n * const config: CreateAuthTokenConfig =\n * uses: 3,\n * expireTime: '2025-05-01T00:00:00Z',\n * LiveEphemeralParameters: {\n * model: 'gemini-2.0-flash-001',\n * config: {\n * 'responseModalities': ['AUDIO'],\n * 'systemInstruction': 'Always answer in English.',\n * }\n * },\n * lockAdditionalFields: ['temperature'],\n * }\n * const token = await ai.tokens.create(config);\n *\n * // Case 4: If LiveEphemeralParameters is set and lockAdditionalFields is\n * // empty array, lock LiveConnectConfig with set fields (e.g.\n * // responseModalities, systemInstruction in this example) when using the\n * // token in Live API sessions.\n * const config: CreateAuthTokenConfig =\n * uses: 3,\n * expireTime: '2025-05-01T00:00:00Z',\n * LiveEphemeralParameters: {\n * model: 'gemini-2.0-flash-001',\n * config: {\n * 'responseModalities': ['AUDIO'],\n * 'systemInstruction': 'Always answer in English.',\n * }\n * },\n * lockAdditionalFields: [],\n * }\n * const token = await ai.tokens.create(config);\n * ```\n */\n\n async create(\n params: types.CreateAuthTokenParameters,\n ): Promise<types.AuthToken> {\n let response: Promise<types.AuthToken>;\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'The client.tokens.create method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.createAuthTokenParametersToMldev(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n 'auth_tokens',\n body['_url'] as Record<string, unknown>,\n );\n\n queryParams = body['_query'] as Record<string, string>;\n delete body['config'];\n delete body['_url'];\n delete body['_query'];\n\n const transformedBody = convertBidiSetupToTokenSetup(body, params.config);\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(transformedBody),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.AuthToken>;\n\n return response.then((resp) => {\n return resp as types.AuthToken;\n });\n }\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport * as common from '../_common.js';\nimport type * as types from '../types.js';\n\nexport function deleteDocumentConfigToMldev(\n fromObject: types.DeleteDocumentConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromForce = common.getValueByPath(fromObject, ['force']);\n if (parentObject !== undefined && fromForce != null) {\n common.setValueByPath(parentObject, ['_query', 'force'], fromForce);\n }\n\n return toObject;\n}\n\nexport function deleteDocumentParametersToMldev(\n fromObject: types.DeleteDocumentParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['_url', 'name'], fromName);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n deleteDocumentConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function getDocumentParametersToMldev(\n fromObject: types.GetDocumentParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['_url', 'name'], fromName);\n }\n\n return toObject;\n}\n\nexport function listDocumentsConfigToMldev(\n fromObject: types.ListDocumentsConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPageSize = common.getValueByPath(fromObject, ['pageSize']);\n if (parentObject !== undefined && fromPageSize != null) {\n common.setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize);\n }\n\n const fromPageToken = common.getValueByPath(fromObject, ['pageToken']);\n if (parentObject !== undefined && fromPageToken != null) {\n common.setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken);\n }\n\n return toObject;\n}\n\nexport function listDocumentsParametersToMldev(\n fromObject: types.ListDocumentsParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromParent = common.getValueByPath(fromObject, ['parent']);\n if (fromParent != null) {\n common.setValueByPath(toObject, ['_url', 'parent'], fromParent);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n listDocumentsConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function listDocumentsResponseFromMldev(\n fromObject: types.ListDocumentsResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromNextPageToken = common.getValueByPath(fromObject, [\n 'nextPageToken',\n ]);\n if (fromNextPageToken != null) {\n common.setValueByPath(toObject, ['nextPageToken'], fromNextPageToken);\n }\n\n const fromDocuments = common.getValueByPath(fromObject, ['documents']);\n if (fromDocuments != null) {\n let transformedList = fromDocuments;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['documents'], transformedList);\n }\n\n return toObject;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport {ApiClient} from './_api_client.js';\nimport * as common from './_common.js';\nimport {BaseModule} from './_common.js';\nimport * as converters from './converters/_documents_converters.js';\nimport {PagedItem, PagedItemConfig, Pager} from './pagers.js';\nimport * as types from './types.js';\n\nexport class Documents extends BaseModule {\n constructor(private readonly apiClient: ApiClient) {\n super();\n }\n\n /**\n * Lists documents.\n *\n * @param params - The parameters for the list request.\n * @return - A pager of documents.\n *\n * @example\n * ```ts\n * const documents = await ai.documents.list({parent:'rag_store_name', config: {'pageSize': 2}});\n * for await (const document of documents) {\n * console.log(document);\n * }\n * ```\n */\n\n list = async (\n params: types.ListDocumentsParameters,\n ): Promise<Pager<types.Document>> => {\n return new Pager<types.Document>(\n PagedItem.PAGED_ITEM_DOCUMENTS,\n (x: PagedItemConfig) =>\n this.listInternal({parent: params.parent, config: x.config}),\n await this.listInternal(params),\n params,\n );\n };\n\n /**\n * Gets a Document.\n *\n * @param params - The parameters for getting a document.\n * @return Document.\n */\n\n async get(params: types.GetDocumentParameters): Promise<types.Document> {\n let response: Promise<types.Document>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.getDocumentParametersToMldev(params);\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.Document>;\n\n return response.then((resp) => {\n return resp as types.Document;\n });\n }\n }\n\n /**\n * Deletes a Document.\n *\n * @param params - The parameters for deleting a document.\n */\n\n async delete(params: types.DeleteDocumentParameters): Promise<void> {\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.deleteDocumentParametersToMldev(params);\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n await this.apiClient.request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'DELETE',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n });\n }\n }\n\n private async listInternal(\n params: types.ListDocumentsParameters,\n ): Promise<types.ListDocumentsResponse> {\n let response: Promise<types.ListDocumentsResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.listDocumentsParametersToMldev(params);\n path = common.formatMap(\n '{parent}/documents',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.ListDocumentsResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.listDocumentsResponseFromMldev(apiResponse);\n const typedResp = new types.ListDocumentsResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport {ApiClient} from './_api_client.js';\nimport * as common from './_common.js';\nimport {BaseModule} from './_common.js';\nimport * as converters from './converters/_filesearchstores_converters.js';\nimport {Documents} from './documents.js';\nimport {PagedItem, Pager} from './pagers.js';\nimport * as types from './types.js';\n\nexport class FileSearchStores extends BaseModule {\n constructor(\n private readonly apiClient: ApiClient,\n public readonly documents: Documents = new Documents(apiClient),\n ) {\n super();\n }\n\n /**\n * Lists file search stores.\n *\n * @param params - The parameters for the list request.\n * @return - A pager of file search stores.\n *\n * @example\n * ```ts\n * const fileSearchStores = await ai.fileSearchStores.list({config: {'pageSize': 2}});\n * for await (const fileSearchStore of fileSearchStores) {\n * console.log(fileSearchStore);\n * }\n * ```\n */\n\n list = async (\n params: types.ListFileSearchStoresParameters = {},\n ): Promise<Pager<types.FileSearchStore>> => {\n return new Pager<types.FileSearchStore>(\n PagedItem.PAGED_ITEM_FILE_SEARCH_STORES,\n (x: types.ListFileSearchStoresParameters) => this.listInternal(x),\n await this.listInternal(params),\n params,\n );\n };\n\n /**\n * Uploads a file asynchronously to a given File Search Store.\n * This method is not available in Vertex AI.\n * Supported upload sources:\n * - Node.js: File path (string) or Blob object.\n * - Browser: Blob object (e.g., File).\n *\n * @remarks\n * The `mimeType` can be specified in the `config` parameter. If omitted:\n * - For file path (string) inputs, the `mimeType` will be inferred from the\n * file extension.\n * - For Blob object inputs, the `mimeType` will be set to the Blob's `type`\n * property.\n *\n * This section can contain multiple paragraphs and code examples.\n *\n * @param params - Optional parameters specified in the\n * `types.UploadToFileSearchStoreParameters` interface.\n * @see {@link types.UploadToFileSearchStoreParameters#config} for the optional\n * config in the parameters.\n * @return A promise that resolves to a long running operation.\n * @throws An error if called on a Vertex AI client.\n * @throws An error if the `mimeType` is not provided and can not be inferred,\n * the `mimeType` can be provided in the `params.config` parameter.\n * @throws An error occurs if a suitable upload location cannot be established.\n *\n * @example\n * The following code uploads a file to a given file search store.\n *\n * ```ts\n * const operation = await ai.fileSearchStores.upload({fileSearchStoreName: 'fileSearchStores/foo-bar', file: 'file.txt', config: {\n * mimeType: 'text/plain',\n * }});\n * console.log(operation.name);\n * ```\n */\n async uploadToFileSearchStore(\n params: types.UploadToFileSearchStoreParameters,\n ): Promise<types.UploadToFileSearchStoreOperation> {\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'Vertex AI does not support uploading files to a file search store.',\n );\n }\n\n return this.apiClient.uploadFileToFileSearchStore(\n params.fileSearchStoreName,\n params.file,\n params.config,\n );\n }\n\n /**\n * Creates a File Search Store.\n *\n * @param params - The parameters for creating a File Search Store.\n * @return FileSearchStore.\n */\n\n async create(\n params: types.CreateFileSearchStoreParameters,\n ): Promise<types.FileSearchStore> {\n let response: Promise<types.FileSearchStore>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.createFileSearchStoreParametersToMldev(params);\n path = common.formatMap(\n 'fileSearchStores',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.FileSearchStore>;\n\n return response.then((resp) => {\n return resp as types.FileSearchStore;\n });\n }\n }\n\n /**\n * Gets a File Search Store.\n *\n * @param params - The parameters for getting a File Search Store.\n * @return FileSearchStore.\n */\n\n async get(\n params: types.GetFileSearchStoreParameters,\n ): Promise<types.FileSearchStore> {\n let response: Promise<types.FileSearchStore>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.getFileSearchStoreParametersToMldev(params);\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.FileSearchStore>;\n\n return response.then((resp) => {\n return resp as types.FileSearchStore;\n });\n }\n }\n\n /**\n * Deletes a File Search Store.\n *\n * @param params - The parameters for deleting a File Search Store.\n */\n\n async delete(params: types.DeleteFileSearchStoreParameters): Promise<void> {\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.deleteFileSearchStoreParametersToMldev(params);\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n await this.apiClient.request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'DELETE',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n });\n }\n }\n\n private async listInternal(\n params: types.ListFileSearchStoresParameters,\n ): Promise<types.ListFileSearchStoresResponse> {\n let response: Promise<types.ListFileSearchStoresResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.listFileSearchStoresParametersToMldev(params);\n path = common.formatMap(\n 'fileSearchStores',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.ListFileSearchStoresResponse>;\n\n return response.then((apiResponse) => {\n const resp =\n converters.listFileSearchStoresResponseFromMldev(apiResponse);\n const typedResp = new types.ListFileSearchStoresResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n private async uploadToFileSearchStoreInternal(\n params: types.UploadToFileSearchStoreParameters,\n ): Promise<types.UploadToFileSearchStoreResumableResponse> {\n let response: Promise<types.UploadToFileSearchStoreResumableResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.uploadToFileSearchStoreParametersToMldev(params);\n path = common.formatMap(\n 'upload/v1beta/{file_search_store_name}:uploadToFileSearchStore',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.UploadToFileSearchStoreResumableResponse>;\n\n return response.then((apiResponse) => {\n const resp =\n converters.uploadToFileSearchStoreResumableResponseFromMldev(\n apiResponse,\n );\n const typedResp = new types.UploadToFileSearchStoreResumableResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n /**\n * Imports a File from File Service to a FileSearchStore.\n *\n * This is a long-running operation, see aip.dev/151\n *\n * @param params - The parameters for importing a file to a file search store.\n * @return ImportFileOperation.\n */\n\n async importFile(\n params: types.ImportFileParameters,\n ): Promise<types.ImportFileOperation> {\n let response: Promise<types.ImportFileOperation>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.importFileParametersToMldev(params);\n path = common.formatMap(\n '{file_search_store_name}:importFile',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.ImportFileOperation>;\n\n return response.then((apiResponse) => {\n const resp = converters.importFileOperationFromMldev(apiResponse);\n const typedResp = new types.ImportFileOperation();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\n/**\n * https://stackoverflow.com/a/2117523\n */\nlet uuid4Internal = function (): string {\n const { crypto } = globalThis as any;\n if (crypto?.randomUUID) {\n uuid4Internal = crypto.randomUUID.bind(crypto);\n return crypto.randomUUID();\n }\n const u8 = new Uint8Array(1);\n const randomByte = crypto ? () => crypto.getRandomValues(u8)[0]! : () => (Math.random() * 0xff) & 0xff;\n return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, (c) =>\n (+c ^ (randomByte() & (15 >> (+c / 4)))).toString(16),\n );\n};\n\nexport const uuid4 = (): string => uuid4Internal();\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nexport function isAbortError(err: unknown) {\n return (\n typeof err === 'object' &&\n err !== null &&\n // Spec-compliant fetch implementations\n (('name' in err && (err as any).name === 'AbortError') ||\n // Expo fetch\n ('message' in err && String((err as any).message).includes('FetchRequestCanceledException')))\n );\n}\n\nexport const castToError = (err: any): Error => {\n if (err instanceof Error) return err;\n if (typeof err === 'object' && err !== null) {\n try {\n if (Object.prototype.toString.call(err) === '[object Error]') {\n // @ts-ignore - not all envs have native support for cause yet\n const error = new Error(err.message, err.cause ? { cause: err.cause } : {});\n if (err.stack) error.stack = err.stack;\n // @ts-ignore - not all envs have native support for cause yet\n if (err.cause && !error.cause) error.cause = err.cause;\n if (err.name) error.name = err.name;\n return error;\n }\n } catch {}\n try {\n return new Error(JSON.stringify(err));\n } catch {}\n }\n return new Error(err);\n};\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nimport { castToError } from '../internal/errors.js';\n\nexport class GeminiNextGenAPIClientError extends Error {}\n\nexport class APIError<\n TStatus extends number | undefined = number | undefined,\n THeaders extends Headers | undefined = Headers | undefined,\n TError extends Object | undefined = Object | undefined,\n> extends GeminiNextGenAPIClientError {\n /** HTTP status for the response that caused the error */\n readonly status: TStatus;\n /** HTTP headers for the response that caused the error */\n readonly headers: THeaders;\n /** JSON body of the response that caused the error */\n readonly error: TError;\n\n constructor(status: TStatus, error: TError, message: string | undefined, headers: THeaders) {\n super(`${APIError.makeMessage(status, error, message)}`);\n this.status = status;\n this.headers = headers;\n this.error = error;\n }\n\n private static makeMessage(status: number | undefined, error: any, message: string | undefined) {\n const msg =\n error?.message ?\n typeof error.message === 'string' ?\n error.message\n : JSON.stringify(error.message)\n : error ? JSON.stringify(error)\n : message;\n\n if (status && msg) {\n return `${status} ${msg}`;\n }\n if (status) {\n return `${status} status code (no body)`;\n }\n if (msg) {\n return msg;\n }\n return '(no status code or body)';\n }\n\n static generate(\n status: number | undefined,\n errorResponse: Object | undefined,\n message: string | undefined,\n headers: Headers | undefined,\n ): APIError {\n if (!status || !headers) {\n return new APIConnectionError({ message, cause: castToError(errorResponse) });\n }\n\n const error = errorResponse as Record<string, any>;\n\n if (status === 400) {\n return new BadRequestError(status, error, message, headers);\n }\n\n if (status === 401) {\n return new AuthenticationError(status, error, message, headers);\n }\n\n if (status === 403) {\n return new PermissionDeniedError(status, error, message, headers);\n }\n\n if (status === 404) {\n return new NotFoundError(status, error, message, headers);\n }\n\n if (status === 409) {\n return new ConflictError(status, error, message, headers);\n }\n\n if (status === 422) {\n return new UnprocessableEntityError(status, error, message, headers);\n }\n\n if (status === 429) {\n return new RateLimitError(status, error, message, headers);\n }\n\n if (status >= 500) {\n return new InternalServerError(status, error, message, headers);\n }\n\n return new APIError(status, error, message, headers);\n }\n}\n\nexport class APIUserAbortError extends APIError<undefined, undefined, undefined> {\n constructor({ message }: { message?: string } = {}) {\n super(undefined, undefined, message || 'Request was aborted.', undefined);\n }\n}\n\nexport class APIConnectionError extends APIError<undefined, undefined, undefined> {\n constructor({ message, cause }: { message?: string | undefined; cause?: Error | undefined }) {\n super(undefined, undefined, message || 'Connection error.', undefined);\n // in some environments the 'cause' property is already declared\n // @ts-ignore\n if (cause) this.cause = cause;\n }\n}\n\nexport class APIConnectionTimeoutError extends APIConnectionError {\n constructor({ message }: { message?: string } = {}) {\n super({ message: message ?? 'Request timed out.' });\n }\n}\n\nexport class BadRequestError extends APIError<400, Headers> {}\n\nexport class AuthenticationError extends APIError<401, Headers> {}\n\nexport class PermissionDeniedError extends APIError<403, Headers> {}\n\nexport class NotFoundError extends APIError<404, Headers> {}\n\nexport class ConflictError extends APIError<409, Headers> {}\n\nexport class UnprocessableEntityError extends APIError<422, Headers> {}\n\nexport class RateLimitError extends APIError<429, Headers> {}\n\nexport class InternalServerError extends APIError<number, Headers> {}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nimport { GeminiNextGenAPIClientError } from '../../core/error.js';\n\n// https://url.spec.whatwg.org/#url-scheme-string\nconst startsWithSchemeRegexp = /^[a-z][a-z0-9+.-]*:/i;\n\nexport const isAbsoluteURL = (url: string): boolean => {\n return startsWithSchemeRegexp.test(url);\n};\n\nlet isArrayInternal = (val: unknown): val is unknown[] => (\n (isArrayInternal = Array.isArray), isArrayInternal(val)\n);\nexport const isArray = isArrayInternal;\nlet isReadonlyArrayInternal = isArray as (val: unknown) => val is readonly unknown[];\nexport const isReadonlyArray = isReadonlyArrayInternal;\n\n/** Returns an object if the given value isn't an object, otherwise returns as-is */\nexport function maybeObj(x: unknown): object {\n if (typeof x !== 'object') {\n return {};\n }\n\n return x ?? {};\n}\n\n// https://stackoverflow.com/a/34491287\nexport function isEmptyObj(obj: Object | null | undefined): boolean {\n if (!obj) return true;\n for (const _k in obj) return false;\n return true;\n}\n\n// https://eslint.org/docs/latest/rules/no-prototype-builtins\nexport function hasOwn<T extends object = object>(obj: T, key: PropertyKey): key is keyof T {\n return Object.prototype.hasOwnProperty.call(obj, key);\n}\n\nexport function isObj(obj: unknown): obj is Record<string, unknown> {\n return obj != null && typeof obj === 'object' && !Array.isArray(obj);\n}\n\nexport const ensurePresent = <T>(value: T | null | undefined): T => {\n if (value == null) {\n throw new GeminiNextGenAPIClientError(`Expected a value to be given but received ${value} instead.`);\n }\n\n return value;\n};\n\nexport const validatePositiveInteger = (name: string, n: unknown): number => {\n if (typeof n !== 'number' || !Number.isInteger(n)) {\n throw new GeminiNextGenAPIClientError(`${name} must be an integer`);\n }\n if (n < 0) {\n throw new GeminiNextGenAPIClientError(`${name} must be a positive integer`);\n }\n return n;\n};\n\nexport const coerceInteger = (value: unknown): number => {\n if (typeof value === 'number') return Math.round(value);\n if (typeof value === 'string') return parseInt(value, 10);\n\n throw new GeminiNextGenAPIClientError(`Could not coerce ${value} (type: ${typeof value}) into a number`);\n};\n\nexport const coerceFloat = (value: unknown): number => {\n if (typeof value === 'number') return value;\n if (typeof value === 'string') return parseFloat(value);\n\n throw new GeminiNextGenAPIClientError(`Could not coerce ${value} (type: ${typeof value}) into a number`);\n};\n\nexport const coerceBoolean = (value: unknown): boolean => {\n if (typeof value === 'boolean') return value;\n if (typeof value === 'string') return value === 'true';\n return Boolean(value);\n};\n\nexport const maybeCoerceInteger = (value: unknown): number | undefined => {\n if (value == null) {\n return undefined;\n }\n return coerceInteger(value);\n};\n\nexport const maybeCoerceFloat = (value: unknown): number | undefined => {\n if (value == null) {\n return undefined;\n }\n return coerceFloat(value);\n};\n\nexport const maybeCoerceBoolean = (value: unknown): boolean | undefined => {\n if (value == null) {\n return undefined;\n }\n return coerceBoolean(value);\n};\n\nexport const safeJSON = (text: string) => {\n try {\n return JSON.parse(text);\n } catch (err) {\n return undefined;\n }\n};\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nexport const sleep = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms));\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nexport const VERSION = '0.0.1';\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nimport { VERSION } from '../version.js';\n\nexport const isRunningInBrowser = () => {\n return (\n // @ts-ignore\n (typeof window !== 'undefined' &&\n // @ts-ignore\n typeof window.document !== 'undefined' && typeof navigator !== 'undefined')\n );\n};\n\ntype DetectedPlatform = 'deno' | 'node' | 'edge' | 'unknown';\n\n/**\n * Note this does not detect 'browser'; for that, use getBrowserInfo().\n */\nfunction getDetectedPlatform(): DetectedPlatform {\n if (typeof Deno !== 'undefined' && Deno.build != null) {\n return 'deno';\n }\n if (typeof EdgeRuntime !== 'undefined') {\n return 'edge';\n }\n if (\n Object.prototype.toString.call(\n typeof (globalThis as any).process !== 'undefined' ? (globalThis as any).process : 0,\n ) === '[object process]'\n ) {\n return 'node';\n }\n return 'unknown';\n}\n\ndeclare const Deno: any;\ndeclare const EdgeRuntime: any;\ntype Arch = 'x32' | 'x64' | 'arm' | 'arm64' | `other:${string}` | 'unknown';\ntype PlatformName =\n | 'MacOS'\n | 'Linux'\n | 'Windows'\n | 'FreeBSD'\n | 'OpenBSD'\n | 'iOS'\n | 'Android'\n | `Other:${string}`\n | 'Unknown';\ntype Browser = 'ie' | 'edge' | 'chrome' | 'firefox' | 'safari';\ntype PlatformProperties = {\n 'X-Stainless-Lang': 'js';\n 'X-Stainless-Package-Version': string;\n 'X-Stainless-OS': PlatformName;\n 'X-Stainless-Arch': Arch;\n 'X-Stainless-Runtime': 'node' | 'deno' | 'edge' | `browser:${Browser}` | 'unknown';\n 'X-Stainless-Runtime-Version': string;\n};\nconst getPlatformProperties = (): PlatformProperties => {\n const detectedPlatform = getDetectedPlatform();\n if (detectedPlatform === 'deno') {\n return {\n 'X-Stainless-Lang': 'js',\n 'X-Stainless-Package-Version': VERSION,\n 'X-Stainless-OS': normalizePlatform(Deno.build.os),\n 'X-Stainless-Arch': normalizeArch(Deno.build.arch),\n 'X-Stainless-Runtime': 'deno',\n 'X-Stainless-Runtime-Version':\n typeof Deno.version === 'string' ? Deno.version : Deno.version?.deno ?? 'unknown',\n };\n }\n if (typeof EdgeRuntime !== 'undefined') {\n return {\n 'X-Stainless-Lang': 'js',\n 'X-Stainless-Package-Version': VERSION,\n 'X-Stainless-OS': 'Unknown',\n 'X-Stainless-Arch': `other:${EdgeRuntime}`,\n 'X-Stainless-Runtime': 'edge',\n 'X-Stainless-Runtime-Version': (globalThis as any).process.version,\n };\n }\n // Check if Node.js\n if (detectedPlatform === 'node') {\n return {\n 'X-Stainless-Lang': 'js',\n 'X-Stainless-Package-Version': VERSION,\n 'X-Stainless-OS': normalizePlatform((globalThis as any).process.platform ?? 'unknown'),\n 'X-Stainless-Arch': normalizeArch((globalThis as any).process.arch ?? 'unknown'),\n 'X-Stainless-Runtime': 'node',\n 'X-Stainless-Runtime-Version': (globalThis as any).process.version ?? 'unknown',\n };\n }\n\n const browserInfo = getBrowserInfo();\n if (browserInfo) {\n return {\n 'X-Stainless-Lang': 'js',\n 'X-Stainless-Package-Version': VERSION,\n 'X-Stainless-OS': 'Unknown',\n 'X-Stainless-Arch': 'unknown',\n 'X-Stainless-Runtime': `browser:${browserInfo.browser}`,\n 'X-Stainless-Runtime-Version': browserInfo.version,\n };\n }\n\n // TODO add support for Cloudflare workers, etc.\n return {\n 'X-Stainless-Lang': 'js',\n 'X-Stainless-Package-Version': VERSION,\n 'X-Stainless-OS': 'Unknown',\n 'X-Stainless-Arch': 'unknown',\n 'X-Stainless-Runtime': 'unknown',\n 'X-Stainless-Runtime-Version': 'unknown',\n };\n};\n\ntype BrowserInfo = {\n browser: Browser;\n version: string;\n};\n\ndeclare const navigator: { userAgent: string } | undefined;\n\n// Note: modified from https://github.com/JS-DevTools/host-environment/blob/b1ab79ecde37db5d6e163c050e54fe7d287d7c92/src/isomorphic.browser.ts\nfunction getBrowserInfo(): BrowserInfo | null {\n if (typeof navigator === 'undefined' || !navigator) {\n return null;\n }\n\n // NOTE: The order matters here!\n const browserPatterns = [\n { key: 'edge' as const, pattern: /Edge(?:\\W+(\\d+)\\.(\\d+)(?:\\.(\\d+))?)?/ },\n { key: 'ie' as const, pattern: /MSIE(?:\\W+(\\d+)\\.(\\d+)(?:\\.(\\d+))?)?/ },\n { key: 'ie' as const, pattern: /Trident(?:.*rv\\:(\\d+)\\.(\\d+)(?:\\.(\\d+))?)?/ },\n { key: 'chrome' as const, pattern: /Chrome(?:\\W+(\\d+)\\.(\\d+)(?:\\.(\\d+))?)?/ },\n { key: 'firefox' as const, pattern: /Firefox(?:\\W+(\\d+)\\.(\\d+)(?:\\.(\\d+))?)?/ },\n { key: 'safari' as const, pattern: /(?:Version\\W+(\\d+)\\.(\\d+)(?:\\.(\\d+))?)?(?:\\W+Mobile\\S*)?\\W+Safari/ },\n ];\n\n // Find the FIRST matching browser\n for (const { key, pattern } of browserPatterns) {\n const match = pattern.exec(navigator.userAgent);\n if (match) {\n const major = match[1] || 0;\n const minor = match[2] || 0;\n const patch = match[3] || 0;\n\n return { browser: key, version: `${major}.${minor}.${patch}` };\n }\n }\n\n return null;\n}\n\nconst normalizeArch = (arch: string): Arch => {\n // Node docs:\n // - https://nodejs.org/api/process.html#processarch\n // Deno docs:\n // - https://doc.deno.land/deno/stable/~/Deno.build\n if (arch === 'x32') return 'x32';\n if (arch === 'x86_64' || arch === 'x64') return 'x64';\n if (arch === 'arm') return 'arm';\n if (arch === 'aarch64' || arch === 'arm64') return 'arm64';\n if (arch) return `other:${arch}`;\n return 'unknown';\n};\n\nconst normalizePlatform = (platform: string): PlatformName => {\n // Node platforms:\n // - https://nodejs.org/api/process.html#processplatform\n // Deno platforms:\n // - https://doc.deno.land/deno/stable/~/Deno.build\n // - https://github.com/denoland/deno/issues/14799\n\n platform = platform.toLowerCase();\n\n // NOTE: this iOS check is untested and may not work\n // Node does not work natively on IOS, there is a fork at\n // https://github.com/nodejs-mobile/nodejs-mobile\n // however it is unknown at the time of writing how to detect if it is running\n if (platform.includes('ios')) return 'iOS';\n if (platform === 'android') return 'Android';\n if (platform === 'darwin') return 'MacOS';\n if (platform === 'win32') return 'Windows';\n if (platform === 'freebsd') return 'FreeBSD';\n if (platform === 'openbsd') return 'OpenBSD';\n if (platform === 'linux') return 'Linux';\n if (platform) return `Other:${platform}`;\n return 'Unknown';\n};\n\nlet _platformHeaders: PlatformProperties;\nexport const getPlatformHeaders = () => {\n return (_platformHeaders ??= getPlatformProperties());\n};\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\n/**\n * This module provides internal shims and utility functions for environments where certain Node.js or global types may not be available.\n *\n * These are used to ensure we can provide a consistent behaviour between different JavaScript environments and good error\n * messages in cases where an environment isn't fully supported.\n */\n\nimport type { Fetch } from './builtin-types.js';\nimport type { ReadableStream } from './shim-types.js';\n\nexport function getDefaultFetch(): Fetch {\n if (typeof fetch !== 'undefined') {\n return fetch as any;\n }\n\n throw new Error(\n '`fetch` is not defined as a global; Either pass `fetch` to the client, `new GeminiNextGenAPIClient({ fetch })` or polyfill the global, `globalThis.fetch = fetch`',\n );\n}\n\ntype ReadableStreamArgs = ConstructorParameters<typeof ReadableStream>;\n\nexport function makeReadableStream(...args: ReadableStreamArgs): ReadableStream {\n const ReadableStream = (globalThis as any).ReadableStream;\n if (typeof ReadableStream === 'undefined') {\n // Note: All of the platforms / runtimes we officially support already define\n // `ReadableStream` as a global, so this should only ever be hit on unsupported runtimes.\n throw new Error(\n '`ReadableStream` is not defined as a global; You will need to polyfill it, `globalThis.ReadableStream = ReadableStream`',\n );\n }\n\n return new ReadableStream(...args);\n}\n\nexport function ReadableStreamFrom<T>(iterable: Iterable<T> | AsyncIterable<T>): ReadableStream<T> {\n let iter: AsyncIterator<T> | Iterator<T> =\n Symbol.asyncIterator in iterable ? iterable[Symbol.asyncIterator]() : iterable[Symbol.iterator]();\n\n return makeReadableStream({\n start() {},\n async pull(controller: any) {\n const { done, value } = await iter.next();\n if (done) {\n controller.close();\n } else {\n controller.enqueue(value);\n }\n },\n async cancel() {\n await iter.return?.();\n },\n });\n}\n\n/**\n * Most browsers don't yet have async iterable support for ReadableStream,\n * and Node has a very different way of reading bytes from its \"ReadableStream\".\n *\n * This polyfill was pulled from https://github.com/MattiasBuelens/web-streams-polyfill/pull/122#issuecomment-1627354490\n */\nexport function ReadableStreamToAsyncIterable<T>(stream: any): AsyncIterableIterator<T> {\n if (stream[Symbol.asyncIterator]) return stream;\n\n const reader = stream.getReader();\n return {\n async next() {\n try {\n const result = await reader.read();\n if (result?.done) reader.releaseLock(); // release lock when stream becomes closed\n return result;\n } catch (e) {\n reader.releaseLock(); // release lock when stream becomes errored\n throw e;\n }\n },\n async return() {\n const cancelPromise = reader.cancel();\n reader.releaseLock();\n await cancelPromise;\n return { done: true, value: undefined };\n },\n [Symbol.asyncIterator]() {\n return this;\n },\n };\n}\n\n/**\n * Cancels a ReadableStream we don't need to consume.\n * See https://undici.nodejs.org/#/?id=garbage-collection\n */\nexport async function CancelReadableStream(stream: any): Promise<void> {\n if (stream === null || typeof stream !== 'object') return;\n\n if (stream[Symbol.asyncIterator]) {\n await stream[Symbol.asyncIterator]().return?.();\n return;\n }\n\n const reader = stream.getReader();\n const cancelPromise = reader.cancel();\n reader.releaseLock();\n await cancelPromise;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nimport { NullableHeaders } from './headers.js';\n\nimport type { BodyInit } from './builtin-types.js';\nimport { Stream } from '../core/streaming.js';\nimport type { HTTPMethod, MergedRequestInit } from './types.js';\nimport { type HeadersLike } from './headers.js';\n\nexport type FinalRequestOptions = RequestOptions & { method: HTTPMethod; path: string };\n\nexport type RequestOptions = {\n /**\n * The HTTP method for the request (e.g., 'get', 'post', 'put', 'delete').\n */\n method?: HTTPMethod;\n\n /**\n * The URL path for the request.\n *\n * @example \"/v1/foo\"\n */\n path?: string;\n\n /**\n * Query parameters to include in the request URL.\n */\n query?: object | undefined | null;\n\n /**\n * The request body. Can be a string, JSON object, FormData, or other supported types.\n */\n body?: unknown;\n\n /**\n * HTTP headers to include with the request. Can be a Headers object, plain object, or array of tuples.\n */\n headers?: HeadersLike;\n\n /**\n * The maximum number of times that the client will retry a request in case of a\n * temporary failure, like a network error or a 5XX error from the server.\n *\n * @default 2\n */\n maxRetries?: number;\n\n stream?: boolean | undefined;\n\n /**\n * The maximum amount of time (in milliseconds) that the client should wait for a response\n * from the server before timing out a single request.\n *\n * @unit milliseconds\n */\n timeout?: number;\n\n /**\n * Additional `RequestInit` options to be passed to the underlying `fetch` call.\n * These options will be merged with the client's default fetch options.\n */\n fetchOptions?: MergedRequestInit;\n\n /**\n * An AbortSignal that can be used to cancel the request.\n */\n signal?: AbortSignal | undefined | null;\n\n /**\n * A unique key for this request to enable idempotency.\n */\n idempotencyKey?: string;\n\n /**\n * Override the default base URL for this specific request.\n */\n defaultBaseURL?: string | undefined;\n\n __binaryResponse?: boolean | undefined;\n __streamClass?: typeof Stream;\n};\n\nexport type EncodedContent = { bodyHeaders: HeadersLike; body: BodyInit };\nexport type RequestEncoder = (request: { headers: NullableHeaders; body: unknown }) => EncodedContent;\n\nexport const FallbackEncoder: RequestEncoder = ({ headers, body }) => {\n return {\n bodyHeaders: {\n 'content-type': 'application/json',\n },\n body: JSON.stringify(body),\n };\n};\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { type RequestOptions } from './request-options.js';\nimport type { FilePropertyBag, Fetch } from './builtin-types.js';\nimport type { BaseGeminiNextGenAPIClient } from '../client.js';\nimport { ReadableStreamFrom } from './shims.js';\n\nexport type BlobPart = string | ArrayBuffer | ArrayBufferView | Blob | DataView;\ntype FsReadStream = AsyncIterable<Uint8Array> & { path: string | { toString(): string } };\n\n// https://github.com/oven-sh/bun/issues/5980\ninterface BunFile extends Blob {\n readonly name?: string | undefined;\n}\n\nexport const checkFileSupport = () => {\n if (typeof File === 'undefined') {\n const { process } = globalThis as any;\n const isOldNode =\n typeof process?.versions?.node === 'string' && parseInt(process.versions.node.split('.')) < 20;\n throw new Error(\n '`File` is not defined as a global, which is required for file uploads.' +\n (isOldNode ?\n \" Update to Node 20 LTS or newer, or set `globalThis.File` to `import('node:buffer').File`.\"\n : ''),\n );\n }\n};\n\n/**\n * Typically, this is a native \"File\" class.\n *\n * We provide the {@link toFile} utility to convert a variety of objects\n * into the File class.\n *\n * For convenience, you can also pass a fetch Response, or in Node,\n * the result of fs.createReadStream().\n */\nexport type Uploadable = File | Response | FsReadStream | BunFile;\n\n/**\n * Construct a `File` instance. This is used to ensure a helpful error is thrown\n * for environments that don't define a global `File` yet.\n */\nexport function makeFile(\n fileBits: BlobPart[],\n fileName: string | undefined,\n options?: FilePropertyBag,\n): File {\n checkFileSupport();\n return new File(fileBits as any, fileName ?? 'unknown_file', options);\n}\n\nexport function getName(value: any): string | undefined {\n return ((\n (typeof value === 'object' &&\n value !== null &&\n (('name' in value && value.name && String(value.name)) ||\n ('url' in value && value.url && String(value.url)) ||\n ('filename' in value && value.filename && String(value.filename)) ||\n ('path' in value && value.path && String(value.path)))) ||\n ''\n )\n .split(/[\\\\/]/)\n .pop() || undefined);\n}\n\nexport const isAsyncIterable = (value: any): value is AsyncIterable<any> =>\n value != null && typeof value === 'object' && typeof value[Symbol.asyncIterator] === 'function';\n\n/**\n * Returns a multipart/form-data request if any part of the given request body contains a File / Blob value.\n * Otherwise returns the request as is.\n */\nexport const maybeMultipartFormRequestOptions = async (\n opts: RequestOptions,\n fetch: BaseGeminiNextGenAPIClient | Fetch,\n): Promise<RequestOptions> => {\n if (!hasUploadableValue(opts.body)) return opts;\n\n return { ...opts, body: await createForm(opts.body, fetch) };\n};\n\ntype MultipartFormRequestOptions = Omit<RequestOptions, 'body'> & { body: unknown };\n\nexport const multipartFormRequestOptions = async (\n opts: MultipartFormRequestOptions,\n fetch: BaseGeminiNextGenAPIClient | Fetch,\n): Promise<RequestOptions> => {\n return { ...opts, body: await createForm(opts.body, fetch) };\n};\n\nconst supportsFormDataMap = /* @__PURE__ */ new WeakMap<Fetch, Promise<boolean>>();\n\n/**\n * node-fetch doesn't support the global FormData object in recent node versions. Instead of sending\n * properly-encoded form data, it just stringifies the object, resulting in a request body of \"[object FormData]\".\n * This function detects if the fetch function provided supports the global FormData object to avoid\n * confusing error messages later on.\n */\nfunction supportsFormData(fetchObject: BaseGeminiNextGenAPIClient | Fetch): Promise<boolean> {\n const fetch: Fetch = typeof fetchObject === 'function' ? fetchObject : (fetchObject as any).fetch;\n const cached = supportsFormDataMap.get(fetch);\n if (cached) return cached;\n const promise = (async () => {\n try {\n const FetchResponse = (\n 'Response' in fetch ?\n fetch.Response\n : (await fetch('data:,')).constructor) as typeof Response;\n const data = new FormData();\n if (data.toString() === (await new FetchResponse(data).text())) {\n return false;\n }\n return true;\n } catch {\n // avoid false negatives\n return true;\n }\n })();\n supportsFormDataMap.set(fetch, promise);\n return promise;\n}\n\nexport const createForm = async <T = Record<string, unknown>>(\n body: T | undefined,\n fetch: BaseGeminiNextGenAPIClient | Fetch,\n): Promise<FormData> => {\n if (!(await supportsFormData(fetch))) {\n throw new TypeError(\n 'The provided fetch function does not support file uploads with the current global FormData class.',\n );\n }\n const form = new FormData();\n await Promise.all(Object.entries(body || {}).map(([key, value]) => addFormValue(form, key, value)));\n return form;\n};\n\n// We check for Blob not File because Bun.File doesn't inherit from File,\n// but they both inherit from Blob and have a `name` property at runtime.\nconst isNamedBlob = (value: unknown): value is Blob => value instanceof Blob && 'name' in value;\n\nconst isUploadable = (value: unknown) =>\n typeof value === 'object' &&\n value !== null &&\n (value instanceof Response || isAsyncIterable(value) || isNamedBlob(value));\n\nconst hasUploadableValue = (value: unknown): boolean => {\n if (isUploadable(value)) return true;\n if (Array.isArray(value)) return value.some(hasUploadableValue);\n if (value && typeof value === 'object') {\n for (const k in value) {\n if (hasUploadableValue((value as any)[k])) return true;\n }\n }\n return false;\n};\n\nconst addFormValue = async (form: FormData, key: string, value: unknown): Promise<void> => {\n if (value === undefined) return;\n if (value == null) {\n throw new TypeError(\n `Received null for \"${key}\"; to pass null in FormData, you must use the string 'null'`,\n );\n }\n\n // TODO: make nested formats configurable\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {\n form.append(key, String(value));\n } else if (value instanceof Response) {\n form.append(key, makeFile([await value.blob()], getName(value)));\n } else if (isAsyncIterable(value)) {\n form.append(key, makeFile([await new Response(ReadableStreamFrom(value)).blob()], getName(value)));\n } else if (isNamedBlob(value)) {\n form.append(key, value, getName(value));\n } else if (Array.isArray(value)) {\n await Promise.all(value.map((entry) => addFormValue(form, key + '[]', entry)));\n } else if (typeof value === 'object') {\n await Promise.all(\n Object.entries(value).map(([name, prop]) => addFormValue(form, `${key}[${name}]`, prop)),\n );\n } else {\n throw new TypeError(\n `Invalid value given to form, expected a string, number, boolean, object, Array, File or Blob but got ${value} instead`,\n );\n }\n};\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { BlobPart, getName, makeFile, isAsyncIterable } from './uploads.js';\nimport type { FilePropertyBag } from './builtin-types.js';\nimport { checkFileSupport } from './uploads.js';\n\nexport type BlobLikePart = string | ArrayBuffer | ArrayBufferView | BlobLike | DataView;\n\n/**\n * Intended to match DOM Blob, node-fetch Blob, node:buffer Blob, etc.\n * Don't add arrayBuffer here, node-fetch doesn't have it\n */\nexport interface BlobLike {\n /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/size) */\n readonly size: number;\n /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/type) */\n readonly type: string;\n /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/text) */\n text(): Promise<string>;\n /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/slice) */\n slice(start?: number, end?: number): BlobLike;\n}\n\n/**\n * This check adds the arrayBuffer() method type because it is available and used at runtime\n */\nconst isBlobLike = (value: any): value is BlobLike & { arrayBuffer(): Promise<ArrayBuffer> } =>\n value != null &&\n typeof value === 'object' &&\n typeof value.size === 'number' &&\n typeof value.type === 'string' &&\n typeof value.text === 'function' &&\n typeof value.slice === 'function' &&\n typeof value.arrayBuffer === 'function';\n\n/**\n * Intended to match DOM File, node:buffer File, undici File, etc.\n */\ninterface FileLike extends BlobLike {\n /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/File/lastModified) */\n readonly lastModified: number;\n /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/File/name) */\n readonly name?: string | undefined;\n}\n\n/**\n * This check adds the arrayBuffer() method type because it is available and used at runtime\n */\nconst isFileLike = (value: any): value is FileLike & { arrayBuffer(): Promise<ArrayBuffer> } =>\n value != null &&\n typeof value === 'object' &&\n typeof value.name === 'string' &&\n typeof value.lastModified === 'number' &&\n isBlobLike(value);\n\n/**\n * Intended to match DOM Response, node-fetch Response, undici Response, etc.\n */\nexport interface ResponseLike {\n url: string;\n blob(): Promise<BlobLike>;\n}\n\nconst isResponseLike = (value: any): value is ResponseLike =>\n value != null &&\n typeof value === 'object' &&\n typeof value.url === 'string' &&\n typeof value.blob === 'function';\n\nexport type ToFileInput =\n | FileLike\n | ResponseLike\n | Exclude<BlobLikePart, string>\n | AsyncIterable<BlobLikePart>;\n\n/**\n * Helper for creating a {@link File} to pass to an SDK upload method from a variety of different data formats\n * @param value the raw content of the file. Can be an {@link Uploadable}, BlobLikePart, or AsyncIterable of BlobLikeParts\n * @param {string=} name the name of the file. If omitted, toFile will try to determine a file name from bits if possible\n * @param {Object=} options additional properties\n * @param {string=} options.type the MIME type of the content\n * @param {number=} options.lastModified the last modified timestamp\n * @returns a {@link File} with the given properties\n */\nexport async function toFile(\n value: ToFileInput | PromiseLike<ToFileInput>,\n name?: string | null | undefined,\n options?: FilePropertyBag | undefined,\n): Promise<File> {\n checkFileSupport();\n\n // If it's a promise, resolve it.\n value = await value;\n\n // If we've been given a `File` we don't need to do anything\n if (isFileLike(value)) {\n if (value instanceof File) {\n return value;\n }\n return makeFile([await value.arrayBuffer()], value.name);\n }\n\n if (isResponseLike(value)) {\n const blob = await value.blob();\n name ||= new URL(value.url).pathname.split(/[\\\\/]/).pop();\n\n return makeFile(await getBytes(blob), name, options);\n }\n\n const parts = await getBytes(value);\n\n name ||= getName(value);\n\n if (!options?.type) {\n const type = parts.find((part) => typeof part === 'object' && 'type' in part && part.type);\n if (typeof type === 'string') {\n options = { ...options, type };\n }\n }\n\n return makeFile(parts, name, options);\n}\n\nasync function getBytes(value: BlobLikePart | AsyncIterable<BlobLikePart>): Promise<Array<BlobPart>> {\n let parts: Array<BlobPart> = [];\n if (\n typeof value === 'string' ||\n ArrayBuffer.isView(value) || // includes Uint8Array, Buffer, etc.\n value instanceof ArrayBuffer\n ) {\n parts.push(value);\n } else if (isBlobLike(value)) {\n parts.push(value instanceof Blob ? value : await value.arrayBuffer());\n } else if (\n isAsyncIterable(value) // includes Readable, ReadableStream, etc.\n ) {\n for await (const chunk of value) {\n parts.push(...(await getBytes(chunk as BlobLikePart))); // TODO, consider validating?\n }\n } else {\n const constructor = value?.constructor?.name;\n throw new Error(\n `Unexpected data type: ${typeof value}${\n constructor ? `; constructor: ${constructor}` : ''\n }${propsForError(value)}`,\n );\n }\n\n return parts;\n}\n\nfunction propsForError(value: unknown): string {\n if (typeof value !== 'object' || value === null) return '';\n const props = Object.getOwnPropertyNames(value);\n return `; props: [${props.map((p) => `\"${p}\"`).join(', ')}]`;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nimport { BaseGeminiNextGenAPIClient } from '../client.js';\n\nexport abstract class APIResource {\n /**\n * The key path from the client. For example, a resource accessible as `client.resource.subresource` would\n * have a property `static override readonly _key = Object.freeze(['resource', 'subresource'] as const);`.\n */\n static readonly _key: readonly string[] = [];\n protected _client: BaseGeminiNextGenAPIClient;\n\n constructor(client: BaseGeminiNextGenAPIClient) {\n this._client = client;\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { GeminiNextGenAPIClientError } from '../../core/error.js';\n\n/**\n * Percent-encode everything that isn't safe to have in a path without encoding safe chars.\n *\n * Taken from https://datatracker.ietf.org/doc/html/rfc3986#section-3.3:\n * > unreserved = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n * > sub-delims = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\" / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n * > pchar = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n */\nexport function encodeURIPath(str: string) {\n return str.replace(/[^A-Za-z0-9\\-._~!$&'()*+,;=:@]+/g, encodeURIComponent);\n}\n\nconst EMPTY = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.create(null));\n\nexport const createPathTagFunction = (pathEncoder = encodeURIPath) =>\n (function path(statics: readonly string[], ...params: readonly unknown[]): string {\n // If there are no params, no processing is needed.\n if (statics.length === 1) return statics[0]!;\n\n let postPath = false;\n const invalidSegments = [];\n const path = statics.reduce((previousValue, currentValue, index) => {\n if (/[?#]/.test(currentValue)) {\n postPath = true;\n }\n const value = params[index];\n let encoded = (postPath ? encodeURIComponent : pathEncoder)('' + value);\n if (\n index !== params.length &&\n (value == null ||\n (typeof value === 'object' &&\n // handle values from other realms\n value.toString ===\n Object.getPrototypeOf(Object.getPrototypeOf((value as any).hasOwnProperty ?? EMPTY) ?? EMPTY)\n ?.toString))\n ) {\n encoded = value + '';\n invalidSegments.push({\n start: previousValue.length + currentValue.length,\n length: encoded.length,\n error: `Value of type ${Object.prototype.toString\n .call(value)\n .slice(8, -1)} is not a valid path parameter`,\n });\n }\n return previousValue + currentValue + (index === params.length ? '' : encoded);\n }, '');\n\n const pathOnly = path.split(/[?#]/, 1)[0]!;\n const invalidSegmentPattern = /(?<=^|\\/)(?:\\.|%2e){1,2}(?=\\/|$)/gi;\n let match;\n\n // Find all invalid segments\n while ((match = invalidSegmentPattern.exec(pathOnly)) !== null) {\n invalidSegments.push({\n start: match.index,\n length: match[0].length,\n error: `Value \"${match[0]}\" can\\'t be safely passed as a path parameter`,\n });\n }\n\n invalidSegments.sort((a, b) => a.start - b.start);\n\n if (invalidSegments.length > 0) {\n let lastEnd = 0;\n const underline = invalidSegments.reduce((acc, segment) => {\n const spaces = ' '.repeat(segment.start - lastEnd);\n const arrows = '^'.repeat(segment.length);\n lastEnd = segment.start + segment.length;\n return acc + spaces + arrows;\n }, '');\n\n throw new GeminiNextGenAPIClientError(\n `Path parameters result in path with invalid segments:\\n${invalidSegments\n .map((e) => e.error)\n .join('\\n')}\\n${path}\\n${underline}`,\n );\n }\n\n return path;\n });\n\n/**\n * URI-encodes path params and ensures no unsafe /./ or /../ path segments are introduced.\n */\nexport const path = /* @__PURE__ */ createPathTagFunction(encodeURIPath);\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nimport { APIResource } from '../core/resource.js';\nimport * as Errors from '../core/error.js';\nimport * as InteractionsAPI from './interactions.js';\nimport { APIPromise } from '../core/api-promise.js';\nimport { Stream } from '../core/streaming.js';\nimport { RequestOptions } from '../internal/request-options.js';\nimport { path } from '../internal/utils/path.js';\n\nexport class BaseInteractions extends APIResource {\n static override readonly _key: readonly ['interactions'] = Object.freeze(['interactions'] as const);\n\n /**\n * Creates a new interaction.\n *\n * @example\n * ```ts\n * const interaction = await client.interactions.create({\n * api_version: 'api_version',\n * input: 'string',\n * model: 'gemini-2.5-flash',\n * });\n * ```\n */\n create(params: CreateModelInteractionParamsNonStreaming, options?: RequestOptions): APIPromise<Interaction>;\n create(\n params: CreateModelInteractionParamsStreaming,\n options?: RequestOptions,\n ): APIPromise<Stream<InteractionSSEEvent>>;\n create(params: CreateAgentInteractionParamsNonStreaming, options?: RequestOptions): APIPromise<Interaction>;\n create(\n params: CreateAgentInteractionParamsStreaming,\n options?: RequestOptions,\n ): APIPromise<Stream<InteractionSSEEvent>>;\n create(\n params: BaseCreateModelInteractionParams | BaseCreateAgentInteractionParams,\n options?: RequestOptions,\n ): APIPromise<Stream<InteractionSSEEvent> | Interaction>;\n create(\n params: InteractionCreateParams,\n options?: RequestOptions,\n ): APIPromise<Interaction> | APIPromise<Stream<InteractionSSEEvent>> {\n const { api_version = this._client.apiVersion, ...body } = params;\n if ('model' in body && 'agent_config' in body) {\n throw new Errors.GeminiNextGenAPIClientError(\n `Invalid request: specified \\`model\\` and \\`agent_config\\`. If specifying \\`model\\`, use \\`generation_config\\`.`,\n );\n }\n if ('agent' in body && 'generation_config' in body) {\n throw new Errors.GeminiNextGenAPIClientError(\n `Invalid request: specified \\`agent\\` and \\`generation_config\\`. If specifying \\`agent\\`, use \\`agent_config\\`.`,\n );\n }\n return this._client.post(path`/${api_version}/interactions`, {\n body,\n ...options,\n stream: params.stream ?? false,\n }) as APIPromise<Interaction> | APIPromise<Stream<InteractionSSEEvent>>;\n }\n\n /**\n * Deletes the interaction by id.\n *\n * @example\n * ```ts\n * const interaction = await client.interactions.delete('id', {\n * api_version: 'api_version',\n * });\n * ```\n */\n delete(\n id: string,\n params: InteractionDeleteParams | null | undefined = {},\n options?: RequestOptions,\n ): APIPromise<unknown> {\n const { api_version = this._client.apiVersion } = params ?? {};\n return this._client.delete(path`/${api_version}/interactions/${id}`, options);\n }\n\n /**\n * Cancels an interaction by id. This only applies to background interactions that are still running.\n *\n * @example\n * ```ts\n * const interaction = await client.interactions.cancel('id', {\n * api_version: 'api_version',\n * });\n * ```\n */\n cancel(\n id: string,\n params: InteractionCancelParams | null | undefined = {},\n options?: RequestOptions,\n ): APIPromise<Interaction> {\n const { api_version = this._client.apiVersion } = params ?? {};\n return this._client.post(path`/${api_version}/interactions/${id}/cancel`, options);\n }\n\n /**\n * Retrieves the full details of a single interaction based on its `Interaction.id`.\n *\n * @example\n * ```ts\n * const interaction = await client.interactions.get('id', {\n * api_version: 'api_version',\n * });\n * ```\n */\n get(\n id: string,\n params?: InteractionGetParamsNonStreaming,\n options?: RequestOptions,\n ): APIPromise<Interaction>;\n get(\n id: string,\n params: InteractionGetParamsStreaming,\n options?: RequestOptions,\n ): APIPromise<Stream<InteractionSSEEvent>>;\n get(\n id: string,\n params?: InteractionGetParamsBase | undefined,\n options?: RequestOptions,\n ): APIPromise<Stream<InteractionSSEEvent> | Interaction>;\n get(\n id: string,\n params: InteractionGetParams | undefined = {},\n options?: RequestOptions,\n ): APIPromise<Interaction> | APIPromise<Stream<InteractionSSEEvent>> {\n const { api_version = this._client.apiVersion, ...query } = params ?? {};\n return this._client.get(path`/${api_version}/interactions/${id}`, {\n query,\n ...options,\n stream: params?.stream ?? false,\n }) as APIPromise<Interaction> | APIPromise<Stream<InteractionSSEEvent>>;\n }\n}\nexport class Interactions extends BaseInteractions {}\n\n/**\n * The configuration for allowed tools.\n */\nexport interface AllowedTools {\n /**\n * The mode of the tool choice.\n */\n mode?: ToolChoiceType;\n\n /**\n * The names of the allowed tools.\n */\n tools?: Array<string>;\n}\n\n/**\n * Citation information for model-generated content.\n */\nexport interface Annotation {\n /**\n * End of the attributed segment, exclusive.\n */\n end_index?: number;\n\n /**\n * Source attributed for a portion of the text. Could be a URL, title, or\n * other identifier.\n */\n source?: string;\n\n /**\n * Start of segment of the response that is attributed to this source.\n *\n * Index indicates the start of the segment, measured in bytes.\n */\n start_index?: number;\n}\n\n/**\n * An audio content block.\n */\nexport interface AudioContent {\n type: 'audio';\n\n /**\n * The audio content.\n */\n data?: string;\n\n /**\n * The mime type of the audio.\n */\n mime_type?: AudioMimeType;\n\n /**\n * The URI of the audio.\n */\n uri?: string;\n}\n\n/**\n * The mime type of the audio.\n */\nexport type AudioMimeType =\n | 'audio/wav'\n | 'audio/mp3'\n | 'audio/aiff'\n | 'audio/aac'\n | 'audio/ogg'\n | 'audio/flac'\n | (string & {});\n\n/**\n * The arguments to pass to the code execution.\n */\nexport interface CodeExecutionCallArguments {\n /**\n * The code to be executed.\n */\n code?: string;\n\n /**\n * Programming language of the `code`.\n */\n language?: 'python';\n}\n\n/**\n * Code execution content.\n */\nexport interface CodeExecutionCallContent {\n type: 'code_execution_call';\n\n /**\n * A unique ID for this specific tool call.\n */\n id?: string;\n\n /**\n * The arguments to pass to the code execution.\n */\n arguments?: CodeExecutionCallArguments;\n}\n\n/**\n * Code execution result content.\n */\nexport interface CodeExecutionResultContent {\n type: 'code_execution_result';\n\n /**\n * ID to match the ID from the code execution call block.\n */\n call_id?: string;\n\n /**\n * Whether the code execution resulted in an error.\n */\n is_error?: boolean;\n\n /**\n * The output of the code execution.\n */\n result?: string;\n\n /**\n * A signature hash for backend validation.\n */\n signature?: string;\n}\n\n/**\n * The content of the response.\n */\nexport type Content =\n | TextContent\n | ImageContent\n | AudioContent\n | DocumentContent\n | VideoContent\n | ThoughtContent\n | FunctionCallContent\n | FunctionResultContent\n | CodeExecutionCallContent\n | CodeExecutionResultContent\n | URLContextCallContent\n | URLContextResultContent\n | GoogleSearchCallContent\n | GoogleSearchResultContent\n | MCPServerToolCallContent\n | MCPServerToolResultContent\n | FileSearchCallContent\n | FileSearchResultContent;\n\nexport interface ContentDelta {\n delta?:\n | ContentDelta.TextDelta\n | ContentDelta.ImageDelta\n | ContentDelta.AudioDelta\n | ContentDelta.DocumentDelta\n | ContentDelta.VideoDelta\n | ContentDelta.ThoughtSummaryDelta\n | ContentDelta.ThoughtSignatureDelta\n | ContentDelta.FunctionCallDelta\n | ContentDelta.FunctionResultDelta\n | ContentDelta.CodeExecutionCallDelta\n | ContentDelta.CodeExecutionResultDelta\n | ContentDelta.URLContextCallDelta\n | ContentDelta.URLContextResultDelta\n | ContentDelta.GoogleSearchCallDelta\n | ContentDelta.GoogleSearchResultDelta\n | ContentDelta.MCPServerToolCallDelta\n | ContentDelta.MCPServerToolResultDelta\n | ContentDelta.FileSearchCallDelta\n | ContentDelta.FileSearchResultDelta;\n\n /**\n * The event_id token to be used to resume the interaction stream, from this event.\n */\n event_id?: string;\n\n event_type?: 'content.delta';\n\n index?: number;\n}\n\nexport namespace ContentDelta {\n export interface TextDelta {\n type: 'text';\n\n /**\n * Citation information for model-generated content.\n */\n annotations?: Array<InteractionsAPI.Annotation>;\n\n text?: string;\n }\n\n export interface ImageDelta {\n type: 'image';\n\n data?: string;\n\n /**\n * The mime type of the image.\n */\n mime_type?: InteractionsAPI.ImageMimeType;\n\n /**\n * The resolution of the media.\n */\n resolution?: 'low' | 'medium' | 'high' | 'ultra_high';\n\n uri?: string;\n }\n\n export interface AudioDelta {\n type: 'audio';\n\n data?: string;\n\n /**\n * The mime type of the audio.\n */\n mime_type?: InteractionsAPI.AudioMimeType;\n\n uri?: string;\n }\n\n export interface DocumentDelta {\n type: 'document';\n\n data?: string;\n\n /**\n * The mime type of the document.\n */\n mime_type?: InteractionsAPI.DocumentMimeType;\n\n uri?: string;\n }\n\n export interface VideoDelta {\n type: 'video';\n\n data?: string;\n\n /**\n * The mime type of the video.\n */\n mime_type?: InteractionsAPI.VideoMimeType;\n\n /**\n * The resolution of the media.\n */\n resolution?: 'low' | 'medium' | 'high' | 'ultra_high';\n\n uri?: string;\n }\n\n export interface ThoughtSummaryDelta {\n type: 'thought_summary';\n\n /**\n * A text content block.\n */\n content?: InteractionsAPI.TextContent | InteractionsAPI.ImageContent;\n }\n\n export interface ThoughtSignatureDelta {\n type: 'thought_signature';\n\n /**\n * Signature to match the backend source to be part of the generation.\n */\n signature?: string;\n }\n\n export interface FunctionCallDelta {\n type: 'function_call';\n\n /**\n * A unique ID for this specific tool call.\n */\n id?: string;\n\n arguments?: { [key: string]: unknown };\n\n name?: string;\n }\n\n export interface FunctionResultDelta {\n type: 'function_result';\n\n /**\n * ID to match the ID from the function call block.\n */\n call_id?: string;\n\n is_error?: boolean;\n\n name?: string;\n\n /**\n * Tool call result delta.\n */\n result?: FunctionResultDelta.Items | unknown | string;\n }\n\n export namespace FunctionResultDelta {\n export interface Items {\n items?: Array<InteractionsAPI.TextContent | InteractionsAPI.ImageContent>;\n }\n }\n\n export interface CodeExecutionCallDelta {\n type: 'code_execution_call';\n\n /**\n * A unique ID for this specific tool call.\n */\n id?: string;\n\n /**\n * The arguments to pass to the code execution.\n */\n arguments?: InteractionsAPI.CodeExecutionCallArguments;\n }\n\n export interface CodeExecutionResultDelta {\n type: 'code_execution_result';\n\n /**\n * ID to match the ID from the function call block.\n */\n call_id?: string;\n\n is_error?: boolean;\n\n result?: string;\n\n signature?: string;\n }\n\n export interface URLContextCallDelta {\n type: 'url_context_call';\n\n /**\n * A unique ID for this specific tool call.\n */\n id?: string;\n\n /**\n * The arguments to pass to the URL context.\n */\n arguments?: InteractionsAPI.URLContextCallArguments;\n }\n\n export interface URLContextResultDelta {\n type: 'url_context_result';\n\n /**\n * ID to match the ID from the function call block.\n */\n call_id?: string;\n\n is_error?: boolean;\n\n result?: Array<InteractionsAPI.URLContextResult>;\n\n signature?: string;\n }\n\n export interface GoogleSearchCallDelta {\n type: 'google_search_call';\n\n /**\n * A unique ID for this specific tool call.\n */\n id?: string;\n\n /**\n * The arguments to pass to Google Search.\n */\n arguments?: InteractionsAPI.GoogleSearchCallArguments;\n }\n\n export interface GoogleSearchResultDelta {\n type: 'google_search_result';\n\n /**\n * ID to match the ID from the function call block.\n */\n call_id?: string;\n\n is_error?: boolean;\n\n result?: Array<InteractionsAPI.GoogleSearchResult>;\n\n signature?: string;\n }\n\n export interface MCPServerToolCallDelta {\n type: 'mcp_server_tool_call';\n\n /**\n * A unique ID for this specific tool call.\n */\n id?: string;\n\n arguments?: { [key: string]: unknown };\n\n name?: string;\n\n server_name?: string;\n }\n\n export interface MCPServerToolResultDelta {\n type: 'mcp_server_tool_result';\n\n /**\n * ID to match the ID from the function call block.\n */\n call_id?: string;\n\n name?: string;\n\n /**\n * Tool call result delta.\n */\n result?: MCPServerToolResultDelta.Items | unknown | string;\n\n server_name?: string;\n }\n\n export namespace MCPServerToolResultDelta {\n export interface Items {\n items?: Array<InteractionsAPI.TextContent | InteractionsAPI.ImageContent>;\n }\n }\n\n export interface FileSearchCallDelta {\n type: 'file_search_call';\n\n /**\n * A unique ID for this specific tool call.\n */\n id?: string;\n }\n\n export interface FileSearchResultDelta {\n type: 'file_search_result';\n\n result?: Array<FileSearchResultDelta.Result>;\n }\n\n export namespace FileSearchResultDelta {\n /**\n * The result of the File Search.\n */\n export interface Result {\n /**\n * The name of the file search store.\n */\n file_search_store?: string;\n\n /**\n * The text of the search result.\n */\n text?: string;\n\n /**\n * The title of the search result.\n */\n title?: string;\n }\n }\n}\n\nexport interface ContentStart {\n /**\n * The content of the response.\n */\n content?: Content;\n\n /**\n * The event_id token to be used to resume the interaction stream, from this event.\n */\n event_id?: string;\n\n event_type?: 'content.start';\n\n index?: number;\n}\n\nexport interface ContentStop {\n /**\n * The event_id token to be used to resume the interaction stream, from this event.\n */\n event_id?: string;\n\n event_type?: 'content.stop';\n\n index?: number;\n}\n\n/**\n * Configuration for the Deep Research agent.\n */\nexport interface DeepResearchAgentConfig {\n /**\n * Whether to include thought summaries in the response.\n */\n thinking_summaries?: 'auto' | 'none';\n\n type?: 'deep-research';\n}\n\n/**\n * A document content block.\n */\nexport interface DocumentContent {\n type: 'document';\n\n /**\n * The document content.\n */\n data?: string;\n\n /**\n * The mime type of the document.\n */\n mime_type?: DocumentMimeType;\n\n /**\n * The URI of the document.\n */\n uri?: string;\n}\n\n/**\n * The mime type of the document.\n */\nexport type DocumentMimeType = (string & {}) | 'application/pdf';\n\n/**\n * Configuration for dynamic agents.\n */\nexport interface DynamicAgentConfig {\n type?: 'dynamic';\n\n [k: string]: unknown;\n}\n\nexport interface ErrorEvent {\n /**\n * Error message from an interaction.\n */\n error?: ErrorEvent.Error;\n\n /**\n * The event_id token to be used to resume the interaction stream, from this event.\n */\n event_id?: string;\n\n event_type?: 'error';\n}\n\nexport namespace ErrorEvent {\n /**\n * Error message from an interaction.\n */\n export interface Error {\n /**\n * A URI that identifies the error type.\n */\n code?: string;\n\n /**\n * A human-readable error message.\n */\n message?: string;\n }\n}\n\n/**\n * File Search content.\n */\nexport interface FileSearchCallContent {\n type: 'file_search_call';\n\n /**\n * A unique ID for this specific tool call.\n */\n id?: string;\n}\n\n/**\n * File Search result content.\n */\nexport interface FileSearchResultContent {\n type: 'file_search_result';\n\n /**\n * The results of the File Search.\n */\n result?: Array<FileSearchResultContent.Result>;\n}\n\nexport namespace FileSearchResultContent {\n /**\n * The result of the File Search.\n */\n export interface Result {\n /**\n * The name of the file search store.\n */\n file_search_store?: string;\n\n /**\n * The text of the search result.\n */\n text?: string;\n\n /**\n * The title of the search result.\n */\n title?: string;\n }\n}\n\n/**\n * A tool that can be used by the model.\n */\nexport interface Function {\n type: 'function';\n\n /**\n * A description of the function.\n */\n description?: string;\n\n /**\n * The name of the function.\n */\n name?: string;\n\n /**\n * The JSON Schema for the function's parameters.\n */\n parameters?: unknown;\n}\n\n/**\n * A function tool call content block.\n */\nexport interface FunctionCallContent {\n /**\n * A unique ID for this specific tool call.\n */\n id: string;\n\n /**\n * The arguments to pass to the function.\n */\n arguments: { [key: string]: unknown };\n\n /**\n * The name of the tool to call.\n */\n name: string;\n\n type: 'function_call';\n}\n\n/**\n * A function tool result content block.\n */\nexport interface FunctionResultContent {\n /**\n * ID to match the ID from the function call block.\n */\n call_id: string;\n\n /**\n * The result of the tool call.\n */\n result: FunctionResultContent.Items | unknown | string;\n\n type: 'function_result';\n\n /**\n * Whether the tool call resulted in an error.\n */\n is_error?: boolean;\n\n /**\n * The name of the tool that was called.\n */\n name?: string;\n}\n\nexport namespace FunctionResultContent {\n export interface Items {\n items?: Array<InteractionsAPI.TextContent | InteractionsAPI.ImageContent>;\n }\n}\n\n/**\n * Configuration parameters for model interactions.\n */\nexport interface GenerationConfig {\n /**\n * Configuration for image interaction.\n */\n image_config?: ImageConfig;\n\n /**\n * The maximum number of tokens to include in the response.\n */\n max_output_tokens?: number;\n\n /**\n * Seed used in decoding for reproducibility.\n */\n seed?: number;\n\n /**\n * Configuration for speech interaction.\n */\n speech_config?: Array<SpeechConfig>;\n\n /**\n * A list of character sequences that will stop output interaction.\n */\n stop_sequences?: Array<string>;\n\n /**\n * Controls the randomness of the output.\n */\n temperature?: number;\n\n /**\n * The level of thought tokens that the model should generate.\n */\n thinking_level?: ThinkingLevel;\n\n /**\n * Whether to include thought summaries in the response.\n */\n thinking_summaries?: 'auto' | 'none';\n\n /**\n * The tool choice for the interaction.\n */\n tool_choice?: ToolChoice;\n\n /**\n * The maximum cumulative probability of tokens to consider when sampling.\n */\n top_p?: number;\n}\n\n/**\n * The arguments to pass to Google Search.\n */\nexport interface GoogleSearchCallArguments {\n /**\n * Web search queries for the following-up web search.\n */\n queries?: Array<string>;\n}\n\n/**\n * Google Search content.\n */\nexport interface GoogleSearchCallContent {\n type: 'google_search_call';\n\n /**\n * A unique ID for this specific tool call.\n */\n id?: string;\n\n /**\n * The arguments to pass to Google Search.\n */\n arguments?: GoogleSearchCallArguments;\n}\n\n/**\n * The result of the Google Search.\n */\nexport interface GoogleSearchResult {\n /**\n * Web content snippet that can be embedded in a web page or an app webview.\n */\n rendered_content?: string;\n\n /**\n * Title of the search result.\n */\n title?: string;\n\n /**\n * URI reference of the search result.\n */\n url?: string;\n}\n\n/**\n * Google Search result content.\n */\nexport interface GoogleSearchResultContent {\n type: 'google_search_result';\n\n /**\n * ID to match the ID from the google search call block.\n */\n call_id?: string;\n\n /**\n * Whether the Google Search resulted in an error.\n */\n is_error?: boolean;\n\n /**\n * The results of the Google Search.\n */\n result?: Array<GoogleSearchResult>;\n\n /**\n * The signature of the Google Search result.\n */\n signature?: string;\n}\n\n/**\n * The configuration for image interaction.\n */\nexport interface ImageConfig {\n aspect_ratio?: '1:1' | '2:3' | '3:2' | '3:4' | '4:3' | '4:5' | '5:4' | '9:16' | '16:9' | '21:9';\n\n image_size?: '1K' | '2K' | '4K';\n}\n\n/**\n * An image content block.\n */\nexport interface ImageContent {\n type: 'image';\n\n /**\n * The image content.\n */\n data?: string;\n\n /**\n * The mime type of the image.\n */\n mime_type?: ImageMimeType;\n\n /**\n * The resolution of the media.\n */\n resolution?: 'low' | 'medium' | 'high' | 'ultra_high';\n\n /**\n * The URI of the image.\n */\n uri?: string;\n}\n\n/**\n * The mime type of the image.\n */\nexport type ImageMimeType =\n | 'image/png'\n | 'image/jpeg'\n | 'image/webp'\n | 'image/heic'\n | 'image/heif'\n | (string & {});\n\n/**\n * The Interaction resource.\n */\nexport interface Interaction {\n /**\n * Output only. A unique identifier for the interaction completion.\n */\n id: string;\n\n /**\n * Output only. The status of the interaction.\n */\n status: 'in_progress' | 'requires_action' | 'completed' | 'failed' | 'cancelled' | 'incomplete';\n\n /**\n * The name of the `Agent` used for generating the interaction.\n */\n agent?: (string & {}) | 'deep-research-pro-preview-12-2025';\n\n /**\n * Output only. The time at which the response was created in ISO 8601 format\n * (YYYY-MM-DDThh:mm:ssZ).\n */\n created?: string;\n\n /**\n * The name of the `Model` used for generating the interaction.\n */\n model?: Model;\n\n /**\n * Output only. Responses from the model.\n */\n outputs?: Array<Content>;\n\n /**\n * The ID of the previous interaction, if any.\n */\n previous_interaction_id?: string;\n\n /**\n * Output only. The role of the interaction.\n */\n role?: string;\n\n /**\n * Output only. The time at which the response was last updated in ISO 8601 format\n * (YYYY-MM-DDThh:mm:ssZ).\n */\n updated?: string;\n\n /**\n * Output only. Statistics on the interaction request's token usage.\n */\n usage?: Usage;\n}\n\nexport interface InteractionCompleteEvent {\n /**\n * The event_id token to be used to resume the interaction stream, from this event.\n */\n event_id?: string;\n\n event_type?: 'interaction.complete';\n\n /**\n * The Interaction resource.\n */\n interaction?: Interaction;\n}\n\nexport type InteractionSSEEvent =\n | InteractionStartEvent\n | InteractionCompleteEvent\n | InteractionStatusUpdate\n | ContentStart\n | ContentDelta\n | ContentStop\n | ErrorEvent;\n\nexport interface InteractionStartEvent {\n /**\n * The event_id token to be used to resume the interaction stream, from this event.\n */\n event_id?: string;\n\n event_type?: 'interaction.start';\n\n /**\n * The Interaction resource.\n */\n interaction?: Interaction;\n}\n\nexport interface InteractionStatusUpdate {\n /**\n * The event_id token to be used to resume the interaction stream, from this event.\n */\n event_id?: string;\n\n event_type?: 'interaction.status_update';\n\n interaction_id?: string;\n\n status?: 'in_progress' | 'requires_action' | 'completed' | 'failed' | 'cancelled' | 'incomplete';\n}\n\n/**\n * MCPServer tool call content.\n */\nexport interface MCPServerToolCallContent {\n /**\n * A unique ID for this specific tool call.\n */\n id: string;\n\n /**\n * The JSON object of arguments for the function.\n */\n arguments: { [key: string]: unknown };\n\n /**\n * The name of the tool which was called.\n */\n name: string;\n\n /**\n * The name of the used MCP server.\n */\n server_name: string;\n\n type: 'mcp_server_tool_call';\n}\n\n/**\n * MCPServer tool result content.\n */\nexport interface MCPServerToolResultContent {\n /**\n * ID to match the ID from the MCP server tool call block.\n */\n call_id: string;\n\n /**\n * The result of the tool call.\n */\n result: MCPServerToolResultContent.Items | unknown | string;\n\n type: 'mcp_server_tool_result';\n\n /**\n * Name of the tool which is called for this specific tool call.\n */\n name?: string;\n\n /**\n * The name of the used MCP server.\n */\n server_name?: string;\n}\n\nexport namespace MCPServerToolResultContent {\n export interface Items {\n items?: Array<InteractionsAPI.TextContent | InteractionsAPI.ImageContent>;\n }\n}\n\n/**\n * The model that will complete your prompt.\\n\\nSee [models](https://ai.google.dev/gemini-api/docs/models) for additional details.\n */\nexport type Model =\n | 'gemini-2.5-flash'\n | 'gemini-2.5-flash-image'\n | 'gemini-2.5-flash-lite'\n | 'gemini-2.5-flash-lite-preview-09-2025'\n | 'gemini-2.5-flash-native-audio-preview-12-2025'\n | 'gemini-2.5-flash-preview-09-2025'\n | 'gemini-2.5-flash-preview-tts'\n | 'gemini-2.5-pro'\n | 'gemini-2.5-pro-preview-tts'\n | 'gemini-3-flash-preview'\n | 'gemini-3-pro-image-preview'\n | 'gemini-3-pro-preview'\n | (string & {});\n\n/**\n * The configuration for speech interaction.\n */\nexport interface SpeechConfig {\n /**\n * The language of the speech.\n */\n language?: string;\n\n /**\n * The speaker's name, it should match the speaker name given in the prompt.\n */\n speaker?: string;\n\n /**\n * The voice of the speaker.\n */\n voice?: string;\n}\n\n/**\n * A text content block.\n */\nexport interface TextContent {\n type: 'text';\n\n /**\n * Citation information for model-generated content.\n */\n annotations?: Array<Annotation>;\n\n /**\n * The text content.\n */\n text?: string;\n}\n\nexport type ThinkingLevel = 'minimal' | 'low' | 'medium' | 'high';\n\n/**\n * A thought content block.\n */\nexport interface ThoughtContent {\n type: 'thought';\n\n /**\n * Signature to match the backend source to be part of the generation.\n */\n signature?: string;\n\n /**\n * A summary of the thought.\n */\n summary?: Array<TextContent | ImageContent>;\n}\n\n/**\n * A tool that can be used by the model.\n */\nexport type Tool =\n | Function\n | Tool.GoogleSearch\n | Tool.CodeExecution\n | Tool.URLContext\n | Tool.ComputerUse\n | Tool.MCPServer\n | Tool.FileSearch;\n\nexport namespace Tool {\n /**\n * A tool that can be used by the model to search Google.\n */\n export interface GoogleSearch {\n type: 'google_search';\n }\n\n /**\n * A tool that can be used by the model to execute code.\n */\n export interface CodeExecution {\n type: 'code_execution';\n }\n\n /**\n * A tool that can be used by the model to fetch URL context.\n */\n export interface URLContext {\n type: 'url_context';\n }\n\n /**\n * A tool that can be used by the model to interact with the computer.\n */\n export interface ComputerUse {\n type: 'computer_use';\n\n /**\n * The environment being operated.\n */\n environment?: 'browser';\n\n /**\n * The list of predefined functions that are excluded from the model call.\n */\n excludedPredefinedFunctions?: Array<string>;\n }\n\n /**\n * A MCPServer is a server that can be called by the model to perform actions.\n */\n export interface MCPServer {\n type: 'mcp_server';\n\n /**\n * The allowed tools.\n */\n allowed_tools?: Array<InteractionsAPI.AllowedTools>;\n\n /**\n * Optional: Fields for authentication headers, timeouts, etc., if needed.\n */\n headers?: { [key: string]: string };\n\n /**\n * The name of the MCPServer.\n */\n name?: string;\n\n /**\n * The full URL for the MCPServer endpoint.\n * Example: \"https://api.example.com/mcp\"\n */\n url?: string;\n }\n\n /**\n * A tool that can be used by the model to search files.\n */\n export interface FileSearch {\n type: 'file_search';\n\n /**\n * The file search store names to search.\n */\n file_search_store_names?: Array<string>;\n\n /**\n * Metadata filter to apply to the semantic retrieval documents and chunks.\n */\n metadata_filter?: string;\n\n /**\n * The number of semantic retrieval chunks to retrieve.\n */\n top_k?: number;\n }\n}\n\n/**\n * The configuration for tool choice.\n */\nexport type ToolChoice = ToolChoiceType | ToolChoiceConfig;\n\nexport interface ToolChoiceConfig {\n /**\n * The configuration for allowed tools.\n */\n allowed_tools?: AllowedTools;\n}\n\nexport type ToolChoiceType = 'auto' | 'any' | 'none' | 'validated';\n\nexport interface Turn {\n /**\n * The content of the turn.\n */\n content?: string | Array<Content>;\n\n /**\n * The originator of this turn. Must be user for input or model for\n * model output.\n */\n role?: string;\n}\n\n/**\n * The arguments to pass to the URL context.\n */\nexport interface URLContextCallArguments {\n /**\n * The URLs to fetch.\n */\n urls?: Array<string>;\n}\n\n/**\n * URL context content.\n */\nexport interface URLContextCallContent {\n type: 'url_context_call';\n\n /**\n * A unique ID for this specific tool call.\n */\n id?: string;\n\n /**\n * The arguments to pass to the URL context.\n */\n arguments?: URLContextCallArguments;\n}\n\n/**\n * The result of the URL context.\n */\nexport interface URLContextResult {\n /**\n * The status of the URL retrieval.\n */\n status?: 'success' | 'error' | 'paywall' | 'unsafe';\n\n /**\n * The URL that was fetched.\n */\n url?: string;\n}\n\n/**\n * URL context result content.\n */\nexport interface URLContextResultContent {\n type: 'url_context_result';\n\n /**\n * ID to match the ID from the url context call block.\n */\n call_id?: string;\n\n /**\n * Whether the URL context resulted in an error.\n */\n is_error?: boolean;\n\n /**\n * The results of the URL context.\n */\n result?: Array<URLContextResult>;\n\n /**\n * The signature of the URL context result.\n */\n signature?: string;\n}\n\n/**\n * Statistics on the interaction request's token usage.\n */\nexport interface Usage {\n /**\n * A breakdown of cached token usage by modality.\n */\n cached_tokens_by_modality?: Array<Usage.CachedTokensByModality>;\n\n /**\n * A breakdown of input token usage by modality.\n */\n input_tokens_by_modality?: Array<Usage.InputTokensByModality>;\n\n /**\n * A breakdown of output token usage by modality.\n */\n output_tokens_by_modality?: Array<Usage.OutputTokensByModality>;\n\n /**\n * A breakdown of tool-use token usage by modality.\n */\n tool_use_tokens_by_modality?: Array<Usage.ToolUseTokensByModality>;\n\n /**\n * Number of tokens in the cached part of the prompt (the cached content).\n */\n total_cached_tokens?: number;\n\n /**\n * Number of tokens in the prompt (context).\n */\n total_input_tokens?: number;\n\n /**\n * Total number of tokens across all the generated responses.\n */\n total_output_tokens?: number;\n\n /**\n * Number of tokens of thoughts for thinking models.\n */\n total_thought_tokens?: number;\n\n /**\n * Total token count for the interaction request (prompt + responses + other\n * internal tokens).\n */\n total_tokens?: number;\n\n /**\n * Number of tokens present in tool-use prompt(s).\n */\n total_tool_use_tokens?: number;\n}\n\nexport namespace Usage {\n /**\n * The token count for a single response modality.\n */\n export interface CachedTokensByModality {\n /**\n * The modality associated with the token count.\n */\n modality?: 'text' | 'image' | 'audio';\n\n /**\n * Number of tokens for the modality.\n */\n tokens?: number;\n }\n\n /**\n * The token count for a single response modality.\n */\n export interface InputTokensByModality {\n /**\n * The modality associated with the token count.\n */\n modality?: 'text' | 'image' | 'audio';\n\n /**\n * Number of tokens for the modality.\n */\n tokens?: number;\n }\n\n /**\n * The token count for a single response modality.\n */\n export interface OutputTokensByModality {\n /**\n * The modality associated with the token count.\n */\n modality?: 'text' | 'image' | 'audio';\n\n /**\n * Number of tokens for the modality.\n */\n tokens?: number;\n }\n\n /**\n * The token count for a single response modality.\n */\n export interface ToolUseTokensByModality {\n /**\n * The modality associated with the token count.\n */\n modality?: 'text' | 'image' | 'audio';\n\n /**\n * Number of tokens for the modality.\n */\n tokens?: number;\n }\n}\n\n/**\n * A video content block.\n */\nexport interface VideoContent {\n type: 'video';\n\n /**\n * The video content.\n */\n data?: string;\n\n /**\n * The mime type of the video.\n */\n mime_type?: VideoMimeType;\n\n /**\n * The resolution of the media.\n */\n resolution?: 'low' | 'medium' | 'high' | 'ultra_high';\n\n /**\n * The URI of the video.\n */\n uri?: string;\n}\n\n/**\n * The mime type of the video.\n */\nexport type VideoMimeType =\n | 'video/mp4'\n | 'video/mpeg'\n | 'video/mov'\n | 'video/avi'\n | 'video/x-flv'\n | 'video/mpg'\n | 'video/webm'\n | 'video/wmv'\n | 'video/3gpp'\n | (string & {});\n\nexport type InteractionDeleteResponse = unknown;\n\nexport type InteractionCreateParams =\n | CreateModelInteractionParamsNonStreaming\n | CreateModelInteractionParamsStreaming\n | CreateAgentInteractionParamsNonStreaming\n | CreateAgentInteractionParamsStreaming;\n\nexport interface BaseCreateModelInteractionParams {\n /**\n * Path param: Which version of the API to use.\n */\n api_version?: string;\n\n /**\n * Body param: The inputs for the interaction.\n */\n input:\n | string\n | Array<Content>\n | Array<Turn>\n | TextContent\n | ImageContent\n | AudioContent\n | DocumentContent\n | VideoContent\n | ThoughtContent\n | FunctionCallContent\n | FunctionResultContent\n | CodeExecutionCallContent\n | CodeExecutionResultContent\n | URLContextCallContent\n | URLContextResultContent\n | GoogleSearchCallContent\n | GoogleSearchResultContent\n | MCPServerToolCallContent\n | MCPServerToolResultContent\n | FileSearchCallContent\n | FileSearchResultContent;\n\n /**\n * Body param: The name of the `Model` used for generating the interaction.\n */\n model: Model;\n\n /**\n * Body param: Input only. Whether to run the model interaction in the background.\n */\n background?: boolean;\n\n /**\n * Body param: Input only. Configuration parameters for the model interaction.\n */\n generation_config?: GenerationConfig;\n\n /**\n * Body param: The ID of the previous interaction, if any.\n */\n previous_interaction_id?: string;\n\n /**\n * Body param: Enforces that the generated response is a JSON object that complies with\n * the JSON schema specified in this field.\n */\n response_format?: unknown;\n\n /**\n * Body param: The mime type of the response. This is required if response_format is set.\n */\n response_mime_type?: string;\n\n /**\n * Body param: The requested modalities of the response (TEXT, IMAGE, AUDIO).\n */\n response_modalities?: Array<'text' | 'image' | 'audio'>;\n\n /**\n * Body param: Input only. Whether to store the response and request for later retrieval.\n */\n store?: boolean;\n\n /**\n * Body param: Input only. Whether the interaction will be streamed.\n */\n stream?: boolean;\n\n /**\n * Body param: System instruction for the interaction.\n */\n system_instruction?: string;\n\n /**\n * Body param: A list of tool declarations the model may call during interaction.\n */\n tools?: Array<Tool>;\n}\n\nexport interface BaseCreateAgentInteractionParams {\n /**\n * Path param: Which version of the API to use.\n */\n api_version?: string;\n\n /**\n * Body param: The name of the `Agent` used for generating the interaction.\n */\n agent: (string & {}) | 'deep-research-pro-preview-12-2025';\n\n /**\n * Body param: The inputs for the interaction.\n */\n input:\n | string\n | Array<Content>\n | Array<Turn>\n | TextContent\n | ImageContent\n | AudioContent\n | DocumentContent\n | VideoContent\n | ThoughtContent\n | FunctionCallContent\n | FunctionResultContent\n | CodeExecutionCallContent\n | CodeExecutionResultContent\n | URLContextCallContent\n | URLContextResultContent\n | GoogleSearchCallContent\n | GoogleSearchResultContent\n | MCPServerToolCallContent\n | MCPServerToolResultContent\n | FileSearchCallContent\n | FileSearchResultContent;\n\n /**\n * Body param: Configuration for the agent.\n */\n agent_config?: DynamicAgentConfig | DeepResearchAgentConfig;\n\n /**\n * Body param: Input only. Whether to run the model interaction in the background.\n */\n background?: boolean;\n\n /**\n * Body param: The ID of the previous interaction, if any.\n */\n previous_interaction_id?: string;\n\n /**\n * Body param: Enforces that the generated response is a JSON object that complies with\n * the JSON schema specified in this field.\n */\n response_format?: unknown;\n\n /**\n * Body param: The mime type of the response. This is required if response_format is set.\n */\n response_mime_type?: string;\n\n /**\n * Body param: The requested modalities of the response (TEXT, IMAGE, AUDIO).\n */\n response_modalities?: Array<'text' | 'image' | 'audio'>;\n\n /**\n * Body param: Input only. Whether to store the response and request for later retrieval.\n */\n store?: boolean;\n\n /**\n * Body param: Input only. Whether the interaction will be streamed.\n */\n stream?: boolean;\n\n /**\n * Body param: System instruction for the interaction.\n */\n system_instruction?: string;\n\n /**\n * Body param: A list of tool declarations the model may call during interaction.\n */\n tools?: Array<Tool>;\n}\n\nexport interface CreateModelInteractionParamsNonStreaming extends BaseCreateModelInteractionParams {\n /**\n * Body param: Input only. Whether the interaction will be streamed.\n */\n stream?: false;\n}\n\nexport interface CreateModelInteractionParamsStreaming extends BaseCreateModelInteractionParams {\n /**\n * Body param: Input only. Whether the interaction will be streamed.\n */\n stream: true;\n}\n\nexport interface CreateAgentInteractionParamsNonStreaming extends BaseCreateAgentInteractionParams {\n /**\n * Body param: Input only. Whether the interaction will be streamed.\n */\n stream?: false;\n}\n\nexport interface CreateAgentInteractionParamsStreaming extends BaseCreateAgentInteractionParams {\n /**\n * Body param: Input only. Whether the interaction will be streamed.\n */\n stream: true;\n}\n\nexport interface InteractionDeleteParams {\n /**\n * Which version of the API to use.\n */\n api_version?: string;\n}\n\nexport interface InteractionCancelParams {\n /**\n * Which version of the API to use.\n */\n api_version?: string;\n}\n\nexport type InteractionGetParams = InteractionGetParamsNonStreaming | InteractionGetParamsStreaming;\n\nexport interface InteractionGetParamsBase {\n /**\n * Path param: Which version of the API to use.\n */\n api_version?: string;\n\n /**\n * Query param: If set to true, includes the input in the response.\n */\n include_input?: boolean;\n\n /**\n * Query param: Optional. If set, resumes the interaction stream from the next chunk after the event marked by the event id. Can only be used if `stream` is true.\n */\n last_event_id?: string;\n\n /**\n * Query param: If set to true, the generated content will be streamed incrementally.\n */\n stream?: boolean;\n}\n\nexport namespace InteractionGetParams {\n export type InteractionGetParamsNonStreaming = InteractionsAPI.InteractionGetParamsNonStreaming;\n export type InteractionGetParamsStreaming = InteractionsAPI.InteractionGetParamsStreaming;\n}\n\nexport interface InteractionGetParamsNonStreaming extends InteractionGetParamsBase {\n /**\n * Query param: If set to true, the generated content will be streamed incrementally.\n */\n stream?: false;\n}\n\nexport interface InteractionGetParamsStreaming extends InteractionGetParamsBase {\n /**\n * Query param: If set to true, the generated content will be streamed incrementally.\n */\n stream: true;\n}\n\nexport declare namespace Interactions {\n export {\n type AllowedTools as AllowedTools,\n type Annotation as Annotation,\n type AudioContent as AudioContent,\n type AudioMimeType as AudioMimeType,\n type CodeExecutionCallArguments as CodeExecutionCallArguments,\n type CodeExecutionCallContent as CodeExecutionCallContent,\n type CodeExecutionResultContent as CodeExecutionResultContent,\n type Content as Content,\n type ContentDelta as ContentDelta,\n type ContentStart as ContentStart,\n type ContentStop as ContentStop,\n type DeepResearchAgentConfig as DeepResearchAgentConfig,\n type DocumentContent as DocumentContent,\n type DocumentMimeType as DocumentMimeType,\n type DynamicAgentConfig as DynamicAgentConfig,\n type ErrorEvent as ErrorEvent,\n type FileSearchCallContent as FileSearchCallContent,\n type FileSearchResultContent as FileSearchResultContent,\n type Function as Function,\n type FunctionCallContent as FunctionCallContent,\n type FunctionResultContent as FunctionResultContent,\n type GenerationConfig as GenerationConfig,\n type GoogleSearchCallArguments as GoogleSearchCallArguments,\n type GoogleSearchCallContent as GoogleSearchCallContent,\n type GoogleSearchResult as GoogleSearchResult,\n type GoogleSearchResultContent as GoogleSearchResultContent,\n type ImageConfig as ImageConfig,\n type ImageContent as ImageContent,\n type ImageMimeType as ImageMimeType,\n type Interaction as Interaction,\n type InteractionCompleteEvent as InteractionCompleteEvent,\n type InteractionSSEEvent as InteractionSSEEvent,\n type InteractionStartEvent as InteractionStartEvent,\n type InteractionStatusUpdate as InteractionStatusUpdate,\n type MCPServerToolCallContent as MCPServerToolCallContent,\n type MCPServerToolResultContent as MCPServerToolResultContent,\n type Model as Model,\n type SpeechConfig as SpeechConfig,\n type TextContent as TextContent,\n type ThinkingLevel as ThinkingLevel,\n type ThoughtContent as ThoughtContent,\n type Tool as Tool,\n type ToolChoice as ToolChoice,\n type ToolChoiceConfig as ToolChoiceConfig,\n type ToolChoiceType as ToolChoiceType,\n type Turn as Turn,\n type URLContextCallArguments as URLContextCallArguments,\n type URLContextCallContent as URLContextCallContent,\n type URLContextResult as URLContextResult,\n type URLContextResultContent as URLContextResultContent,\n type Usage as Usage,\n type VideoContent as VideoContent,\n type VideoMimeType as VideoMimeType,\n type InteractionDeleteResponse as InteractionDeleteResponse,\n type InteractionCreateParams as InteractionCreateParams,\n type CreateModelInteractionParamsNonStreaming as CreateModelInteractionParamsNonStreaming,\n type CreateModelInteractionParamsStreaming as CreateModelInteractionParamsStreaming,\n type CreateAgentInteractionParamsNonStreaming as CreateAgentInteractionParamsNonStreaming,\n type CreateAgentInteractionParamsStreaming as CreateAgentInteractionParamsStreaming,\n type InteractionDeleteParams as InteractionDeleteParams,\n type InteractionCancelParams as InteractionCancelParams,\n type InteractionGetParams as InteractionGetParams,\n type InteractionGetParamsNonStreaming as InteractionGetParamsNonStreaming,\n type InteractionGetParamsStreaming as InteractionGetParamsStreaming,\n };\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nexport function concatBytes(buffers: Uint8Array[]): Uint8Array {\n let length = 0;\n for (const buffer of buffers) {\n length += buffer.length;\n }\n const output = new Uint8Array(length);\n let index = 0;\n for (const buffer of buffers) {\n output.set(buffer, index);\n index += buffer.length;\n }\n\n return output;\n}\n\nlet encodeUTF8_: (str: string) => Uint8Array;\nexport function encodeUTF8(str: string) {\n let encoder;\n return (\n encodeUTF8_ ??\n ((encoder = new (globalThis as any).TextEncoder()), (encodeUTF8_ = encoder.encode.bind(encoder)))\n )(str);\n}\n\nlet decodeUTF8_: (bytes: Uint8Array) => string;\nexport function decodeUTF8(bytes: Uint8Array) {\n let decoder;\n return (\n decodeUTF8_ ??\n ((decoder = new (globalThis as any).TextDecoder()), (decodeUTF8_ = decoder.decode.bind(decoder)))\n )(bytes);\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { concatBytes, decodeUTF8, encodeUTF8 } from '../utils/bytes.js';\n\nexport type Bytes = string | ArrayBuffer | Uint8Array | null | undefined;\n\n/**\n * A re-implementation of httpx's `LineDecoder` in Python that handles incrementally\n * reading lines from text.\n *\n * https://github.com/encode/httpx/blob/920333ea98118e9cf617f246905d7b202510941c/httpx/_decoders.py#L258\n */\nexport class LineDecoder {\n // prettier-ignore\n static NEWLINE_CHARS = new Set(['\\n', '\\r']);\n static NEWLINE_REGEXP = /\\r\\n|[\\n\\r]/g;\n\n private buffer: Uint8Array;\n private carriageReturnIndex: number | null;\n\n constructor() {\n this.buffer = new Uint8Array();\n this.carriageReturnIndex = null;\n }\n\n decode(chunk: Bytes): string[] {\n if (chunk == null) {\n return [];\n }\n\n const binaryChunk =\n chunk instanceof ArrayBuffer ? new Uint8Array(chunk)\n : typeof chunk === 'string' ? encodeUTF8(chunk)\n : chunk;\n\n this.buffer = concatBytes([this.buffer, binaryChunk]);\n\n const lines: string[] = [];\n let patternIndex;\n while ((patternIndex = findNewlineIndex(this.buffer, this.carriageReturnIndex)) != null) {\n if (patternIndex.carriage && this.carriageReturnIndex == null) {\n // skip until we either get a corresponding `\\n`, a new `\\r` or nothing\n this.carriageReturnIndex = patternIndex.index;\n continue;\n }\n\n // we got double \\r or \\rtext\\n\n if (\n this.carriageReturnIndex != null &&\n (patternIndex.index !== this.carriageReturnIndex + 1 || patternIndex.carriage)\n ) {\n lines.push(decodeUTF8(this.buffer.subarray(0, this.carriageReturnIndex - 1)));\n this.buffer = this.buffer.subarray(this.carriageReturnIndex);\n this.carriageReturnIndex = null;\n continue;\n }\n\n const endIndex =\n this.carriageReturnIndex !== null ? patternIndex.preceding - 1 : patternIndex.preceding;\n\n const line = decodeUTF8(this.buffer.subarray(0, endIndex));\n lines.push(line);\n\n this.buffer = this.buffer.subarray(patternIndex.index);\n this.carriageReturnIndex = null;\n }\n\n return lines;\n }\n\n flush(): string[] {\n if (!this.buffer.length) {\n return [];\n }\n return this.decode('\\n');\n }\n}\n\n/**\n * This function searches the buffer for the end patterns, (\\r or \\n)\n * and returns an object with the index preceding the matched newline and the\n * index after the newline char. `null` is returned if no new line is found.\n *\n * ```ts\n * findNewLineIndex('abc\\ndef') -> { preceding: 2, index: 3 }\n * ```\n */\nfunction findNewlineIndex(\n buffer: Uint8Array,\n startIndex: number | null,\n): { preceding: number; index: number; carriage: boolean } | null {\n const newline = 0x0a; // \\n\n const carriage = 0x0d; // \\r\n\n for (let i = startIndex ?? 0; i < buffer.length; i++) {\n if (buffer[i] === newline) {\n return { preceding: i, index: i + 1, carriage: false };\n }\n\n if (buffer[i] === carriage) {\n return { preceding: i, index: i + 1, carriage: true };\n }\n }\n\n return null;\n}\n\nexport function findDoubleNewlineIndex(buffer: Uint8Array): number {\n // This function searches the buffer for the end patterns (\\r\\r, \\n\\n, \\r\\n\\r\\n)\n // and returns the index right after the first occurrence of any pattern,\n // or -1 if none of the patterns are found.\n const newline = 0x0a; // \\n\n const carriage = 0x0d; // \\r\n\n for (let i = 0; i < buffer.length - 1; i++) {\n if (buffer[i] === newline && buffer[i + 1] === newline) {\n // \\n\\n\n return i + 2;\n }\n if (buffer[i] === carriage && buffer[i + 1] === carriage) {\n // \\r\\r\n return i + 2;\n }\n if (\n buffer[i] === carriage &&\n buffer[i + 1] === newline &&\n i + 3 < buffer.length &&\n buffer[i + 2] === carriage &&\n buffer[i + 3] === newline\n ) {\n // \\r\\n\\r\\n\n return i + 4;\n }\n }\n\n return -1;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nimport { hasOwn } from './values.js';\nimport { type BaseGeminiNextGenAPIClient } from '../../client.js';\nimport { RequestOptions } from '../request-options.js';\n\ntype LogFn = (message: string, ...rest: unknown[]) => void;\nexport type Logger = {\n error: LogFn;\n warn: LogFn;\n info: LogFn;\n debug: LogFn;\n};\nexport type LogLevel = 'off' | 'error' | 'warn' | 'info' | 'debug';\n\nconst levelNumbers = {\n off: 0,\n error: 200,\n warn: 300,\n info: 400,\n debug: 500,\n};\n\nexport const parseLogLevel = (\n maybeLevel: string | undefined,\n sourceName: string,\n client: BaseGeminiNextGenAPIClient,\n): LogLevel | undefined => {\n if (!maybeLevel) {\n return undefined;\n }\n if (hasOwn(levelNumbers, maybeLevel)) {\n return maybeLevel;\n }\n loggerFor(client).warn(\n `${sourceName} was set to ${JSON.stringify(maybeLevel)}, expected one of ${JSON.stringify(\n Object.keys(levelNumbers),\n )}`,\n );\n return undefined;\n};\n\nfunction noop() {}\n\nfunction makeLogFn(fnLevel: keyof Logger, logger: Logger | undefined, logLevel: LogLevel) {\n if (!logger || levelNumbers[fnLevel] > levelNumbers[logLevel]) {\n return noop;\n } else {\n // Don't wrap logger functions, we want the stacktrace intact!\n return logger[fnLevel].bind(logger);\n }\n}\n\nconst noopLogger = {\n error: noop,\n warn: noop,\n info: noop,\n debug: noop,\n};\n\nlet cachedLoggers = /* @__PURE__ */ new WeakMap<Logger, [LogLevel, Logger]>();\n\nexport function loggerFor(client: BaseGeminiNextGenAPIClient): Logger {\n const logger = client.logger;\n const logLevel = client.logLevel ?? 'off';\n if (!logger) {\n return noopLogger;\n }\n\n const cachedLogger = cachedLoggers.get(logger);\n if (cachedLogger && cachedLogger[0] === logLevel) {\n return cachedLogger[1];\n }\n\n const levelLogger = {\n error: makeLogFn('error', logger, logLevel),\n warn: makeLogFn('warn', logger, logLevel),\n info: makeLogFn('info', logger, logLevel),\n debug: makeLogFn('debug', logger, logLevel),\n };\n\n cachedLoggers.set(logger, [logLevel, levelLogger]);\n\n return levelLogger;\n}\n\nexport const formatRequestDetails = (details: {\n options?: RequestOptions | undefined;\n headers?: Headers | Record<string, string> | undefined;\n retryOfRequestLogID?: string | undefined;\n retryOf?: string | undefined;\n url?: string | undefined;\n status?: number | undefined;\n method?: string | undefined;\n durationMs?: number | undefined;\n message?: unknown;\n body?: unknown;\n}) => {\n if (details.options) {\n details.options = { ...details.options };\n delete details.options['headers']; // redundant + leaks internals\n }\n if (details.headers) {\n details.headers = Object.fromEntries(\n (details.headers instanceof Headers ? [...details.headers] : Object.entries(details.headers)).map(\n ([name, value]) => [\n name,\n (\n name.toLowerCase() === 'x-goog-api-key' ||\n name.toLowerCase() === 'authorization' ||\n name.toLowerCase() === 'cookie' ||\n name.toLowerCase() === 'set-cookie'\n ) ?\n '***'\n : value,\n ],\n ),\n );\n }\n if ('retryOfRequestLogID' in details) {\n if (details.retryOfRequestLogID) {\n details.retryOf = details.retryOfRequestLogID;\n }\n delete details.retryOfRequestLogID;\n }\n return details;\n};\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { GeminiNextGenAPIClientError } from './error.js';\nimport { type ReadableStream } from '../internal/shim-types.js';\nimport { makeReadableStream } from '../internal/shims.js';\nimport { findDoubleNewlineIndex, LineDecoder } from '../internal/decoders/line.js';\nimport { ReadableStreamToAsyncIterable } from '../internal/shims.js';\nimport { isAbortError } from '../internal/errors.js';\nimport { encodeUTF8 } from '../internal/utils/bytes.js';\nimport { loggerFor } from '../internal/utils/log.js';\nimport type { BaseGeminiNextGenAPIClient } from '../client.js';\n\ntype Bytes = string | ArrayBuffer | Uint8Array | null | undefined;\n\nexport type ServerSentEvent = {\n event: string | null;\n data: string;\n raw: string[];\n};\n\nexport class Stream<Item> implements AsyncIterable<Item> {\n controller: AbortController;\n private client: BaseGeminiNextGenAPIClient | undefined;\n\n constructor(\n private iterator: () => AsyncIterator<Item>,\n controller: AbortController,\n client?: BaseGeminiNextGenAPIClient,\n ) {\n this.controller = controller;\n this.client = client;\n }\n\n static fromSSEResponse<Item>(\n response: Response,\n controller: AbortController,\n client?: BaseGeminiNextGenAPIClient,\n ): Stream<Item> {\n let consumed = false;\n const logger = client ? loggerFor(client) : console;\n\n async function* iterator(): AsyncIterator<Item, any, undefined> {\n if (consumed) {\n throw new GeminiNextGenAPIClientError(\n 'Cannot iterate over a consumed stream, use `.tee()` to split the stream.',\n );\n }\n consumed = true;\n let done = false;\n try {\n for await (const sse of _iterSSEMessages(response, controller)) {\n if (done) continue;\n\n if (sse.data.startsWith('[DONE]')) {\n done = true;\n continue;\n } else {\n try {\n // @ts-ignore\n yield JSON.parse(sse.data);\n } catch (e) {\n logger.error(`Could not parse message into JSON:`, sse.data);\n logger.error(`From chunk:`, sse.raw);\n throw e;\n }\n }\n }\n done = true;\n } catch (e) {\n // If the user calls `stream.controller.abort()`, we should exit without throwing.\n if (isAbortError(e)) return;\n throw e;\n } finally {\n // If the user `break`s, abort the ongoing request.\n if (!done) controller.abort();\n }\n }\n\n return new Stream(iterator, controller, client);\n }\n\n /**\n * Generates a Stream from a newline-separated ReadableStream\n * where each item is a JSON value.\n */\n static fromReadableStream<Item>(\n readableStream: ReadableStream,\n controller: AbortController,\n client?: BaseGeminiNextGenAPIClient,\n ): Stream<Item> {\n let consumed = false;\n\n async function* iterLines(): AsyncGenerator<string, void, unknown> {\n const lineDecoder = new LineDecoder();\n\n const iter = ReadableStreamToAsyncIterable<Bytes>(readableStream);\n for await (const chunk of iter) {\n for (const line of lineDecoder.decode(chunk)) {\n yield line;\n }\n }\n\n for (const line of lineDecoder.flush()) {\n yield line;\n }\n }\n\n async function* iterator(): AsyncIterator<Item, any, undefined> {\n if (consumed) {\n throw new GeminiNextGenAPIClientError(\n 'Cannot iterate over a consumed stream, use `.tee()` to split the stream.',\n );\n }\n consumed = true;\n let done = false;\n try {\n for await (const line of iterLines()) {\n if (done) continue;\n // @ts-ignore\n if (line) yield JSON.parse(line);\n }\n done = true;\n } catch (e) {\n // If the user calls `stream.controller.abort()`, we should exit without throwing.\n if (isAbortError(e)) return;\n throw e;\n } finally {\n // If the user `break`s, abort the ongoing request.\n if (!done) controller.abort();\n }\n }\n\n return new Stream(iterator, controller, client);\n }\n\n [Symbol.asyncIterator](): AsyncIterator<Item> {\n return this.iterator();\n }\n\n /**\n * Splits the stream into two streams which can be\n * independently read from at different speeds.\n */\n tee(): [Stream<Item>, Stream<Item>] {\n const left: Array<Promise<IteratorResult<Item>>> = [];\n const right: Array<Promise<IteratorResult<Item>>> = [];\n const iterator = this.iterator();\n\n const teeIterator = (queue: Array<Promise<IteratorResult<Item>>>): AsyncIterator<Item> => {\n return {\n next: () => {\n if (queue.length === 0) {\n const result = iterator.next();\n left.push(result);\n right.push(result);\n }\n return queue.shift()!;\n },\n };\n };\n\n return [\n new Stream(() => teeIterator(left), this.controller, this.client),\n new Stream(() => teeIterator(right), this.controller, this.client),\n ];\n }\n\n /**\n * Converts this stream to a newline-separated ReadableStream of\n * JSON stringified values in the stream\n * which can be turned back into a Stream with `Stream.fromReadableStream()`.\n */\n toReadableStream(): ReadableStream {\n const self = this;\n let iter: AsyncIterator<Item>;\n\n return makeReadableStream({\n async start() {\n iter = self[Symbol.asyncIterator]();\n },\n async pull(ctrl: any) {\n try {\n const { value, done } = await iter.next();\n if (done) return ctrl.close();\n\n const bytes = encodeUTF8(JSON.stringify(value) + '\\n');\n\n ctrl.enqueue(bytes);\n } catch (err) {\n ctrl.error(err);\n }\n },\n async cancel() {\n await iter.return?.();\n },\n });\n }\n}\n\nexport async function* _iterSSEMessages(\n response: Response,\n controller: AbortController,\n): AsyncGenerator<ServerSentEvent, void, unknown> {\n if (!response.body) {\n controller.abort();\n if (\n typeof (globalThis as any).navigator !== 'undefined' &&\n (globalThis as any).navigator.product === 'ReactNative'\n ) {\n throw new GeminiNextGenAPIClientError(\n `The default react-native fetch implementation does not support streaming. Please use expo/fetch: https://docs.expo.dev/versions/latest/sdk/expo/#expofetch-api`,\n );\n }\n throw new GeminiNextGenAPIClientError(`Attempted to iterate over a response with no body`);\n }\n\n const sseDecoder = new SSEDecoder();\n const lineDecoder = new LineDecoder();\n\n const iter = ReadableStreamToAsyncIterable<Bytes>(response.body);\n for await (const sseChunk of iterSSEChunks(iter)) {\n for (const line of lineDecoder.decode(sseChunk)) {\n const sse = sseDecoder.decode(line);\n if (sse) yield sse;\n }\n }\n\n for (const line of lineDecoder.flush()) {\n const sse = sseDecoder.decode(line);\n if (sse) yield sse;\n }\n}\n\n/**\n * Given an async iterable iterator, iterates over it and yields full\n * SSE chunks, i.e. yields when a double new-line is encountered.\n */\nasync function* iterSSEChunks(iterator: AsyncIterableIterator<Bytes>): AsyncGenerator<Uint8Array> {\n let data = new Uint8Array();\n\n for await (const chunk of iterator) {\n if (chunk == null) {\n continue;\n }\n\n const binaryChunk =\n chunk instanceof ArrayBuffer ? new Uint8Array(chunk)\n : typeof chunk === 'string' ? encodeUTF8(chunk)\n : chunk;\n\n let newData = new Uint8Array(data.length + binaryChunk.length);\n newData.set(data);\n newData.set(binaryChunk, data.length);\n data = newData;\n\n let patternIndex;\n while ((patternIndex = findDoubleNewlineIndex(data)) !== -1) {\n yield data.slice(0, patternIndex);\n data = data.slice(patternIndex);\n }\n }\n\n if (data.length > 0) {\n yield data;\n }\n}\n\nclass SSEDecoder {\n private data: string[];\n private event: string | null;\n private chunks: string[];\n\n constructor() {\n this.event = null;\n this.data = [];\n this.chunks = [];\n }\n\n decode(line: string) {\n if (line.endsWith('\\r')) {\n line = line.substring(0, line.length - 1);\n }\n\n if (!line) {\n // empty line and we didn't previously encounter any messages\n if (!this.event && !this.data.length) return null;\n\n const sse: ServerSentEvent = {\n event: this.event,\n data: this.data.join('\\n'),\n raw: this.chunks,\n };\n\n this.event = null;\n this.data = [];\n this.chunks = [];\n\n return sse;\n }\n\n this.chunks.push(line);\n\n if (line.startsWith(':')) {\n return null;\n }\n\n let [fieldname, _, value] = partition(line, ':');\n\n if (value.startsWith(' ')) {\n value = value.substring(1);\n }\n\n if (fieldname === 'event') {\n this.event = value;\n } else if (fieldname === 'data') {\n this.data.push(value);\n }\n\n return null;\n }\n}\n\nfunction partition(str: string, delimiter: string): [string, string, string] {\n const index = str.indexOf(delimiter);\n if (index !== -1) {\n return [str.substring(0, index), delimiter, str.substring(index + delimiter.length)];\n }\n\n return [str, '', ''];\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nimport type { FinalRequestOptions } from './request-options.js';\nimport { Stream } from '../core/streaming.js';\nimport { type BaseGeminiNextGenAPIClient } from '../client.js';\nimport { formatRequestDetails, loggerFor } from './utils/log.js';\n\nexport type APIResponseProps = {\n response: Response;\n options: FinalRequestOptions;\n controller: AbortController;\n requestLogID: string;\n retryOfRequestLogID: string | undefined;\n startTime: number;\n};\n\nexport async function defaultParseResponse<T>(\n client: BaseGeminiNextGenAPIClient,\n props: APIResponseProps,\n): Promise<T> {\n const { response, requestLogID, retryOfRequestLogID, startTime } = props;\n const body = await (async () => {\n if (props.options.stream) {\n loggerFor(client).debug('response', response.status, response.url, response.headers, response.body);\n\n // Note: there is an invariant here that isn't represented in the type system\n // that if you set `stream: true` the response type must also be `Stream<T>`\n\n if (props.options.__streamClass) {\n return props.options.__streamClass.fromSSEResponse(response, props.controller, client) as any;\n }\n\n return Stream.fromSSEResponse(response, props.controller, client) as any;\n }\n\n // fetch refuses to read the body when the status code is 204.\n if (response.status === 204) {\n return null as T;\n }\n\n if (props.options.__binaryResponse) {\n return response as unknown as T;\n }\n\n const contentType = response.headers.get('content-type');\n const mediaType = contentType?.split(';')[0]?.trim();\n const isJSON = mediaType?.includes('application/json') || mediaType?.endsWith('+json');\n if (isJSON) {\n const contentLength = response.headers.get('content-length');\n if (contentLength === '0') {\n // if there is no content we can't do anything\n return undefined as T;\n }\n\n const json = await response.json();\n return json as T;\n }\n\n const text = await response.text();\n return text as unknown as T;\n })();\n loggerFor(client).debug(\n `[${requestLogID}] response parsed`,\n formatRequestDetails({\n retryOfRequestLogID,\n url: response.url,\n status: response.status,\n body,\n durationMs: Date.now() - startTime,\n }),\n );\n return body;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nimport { type BaseGeminiNextGenAPIClient } from '../client.js';\n\nimport { type PromiseOrValue } from '../internal/types.js';\nimport { APIResponseProps, defaultParseResponse } from '../internal/parse.js';\n\n/**\n * A subclass of `Promise` providing additional helper methods\n * for interacting with the SDK.\n */\nexport class APIPromise<T> extends Promise<T> {\n private parsedPromise: Promise<T> | undefined;\n private client: BaseGeminiNextGenAPIClient;\n\n constructor(\n client: BaseGeminiNextGenAPIClient,\n private responsePromise: Promise<APIResponseProps>,\n private parseResponse: (\n client: BaseGeminiNextGenAPIClient,\n props: APIResponseProps,\n ) => PromiseOrValue<T> = defaultParseResponse,\n ) {\n super((resolve) => {\n // this is maybe a bit weird but this has to be a no-op to not implicitly\n // parse the response body; instead .then, .catch, .finally are overridden\n // to parse the response\n resolve(null as any);\n });\n this.client = client;\n }\n\n _thenUnwrap<U>(transform: (data: T, props: APIResponseProps) => U): APIPromise<U> {\n return new APIPromise(this.client, this.responsePromise, async (client, props) =>\n transform(await this.parseResponse(client, props), props),\n );\n }\n\n /**\n * Gets the raw `Response` instance instead of parsing the response\n * data.\n *\n * If you want to parse the response body but still get the `Response`\n * instance, you can use {@link withResponse()}.\n *\n * 👋 Getting the wrong TypeScript type for `Response`?\n * Try setting `\"moduleResolution\": \"NodeNext\"` or add `\"lib\": [\"DOM\"]`\n * to your `tsconfig.json`.\n */\n asResponse(): Promise<Response> {\n return this.responsePromise.then((p) => p.response);\n }\n\n /**\n * Gets the parsed response data and the raw `Response` instance.\n *\n * If you just want to get the raw `Response` instance without parsing it,\n * you can use {@link asResponse()}.\n *\n * 👋 Getting the wrong TypeScript type for `Response`?\n * Try setting `\"moduleResolution\": \"NodeNext\"` or add `\"lib\": [\"DOM\"]`\n * to your `tsconfig.json`.\n */\n async withResponse(): Promise<{ data: T; response: Response }> {\n const [data, response] = await Promise.all([this.parse(), this.asResponse()]);\n return { data, response };\n }\n\n private parse(): Promise<T> {\n if (!this.parsedPromise) {\n this.parsedPromise = this.responsePromise.then((data) => this.parseResponse(this.client, data));\n }\n return this.parsedPromise;\n }\n\n override then<TResult1 = T, TResult2 = never>(\n onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null,\n onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null,\n ): Promise<TResult1 | TResult2> {\n return this.parse().then(onfulfilled, onrejected);\n }\n\n override catch<TResult = never>(\n onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null,\n ): Promise<T | TResult> {\n return this.parse().catch(onrejected);\n }\n\n override finally(onfinally?: (() => void) | undefined | null): Promise<T> {\n return this.parse().finally(onfinally);\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nimport { isReadonlyArray } from './utils/values.js';\n\ntype HeaderValue = string | undefined | null;\nexport type HeadersLike =\n | Headers\n | readonly HeaderValue[][]\n | Record<string, HeaderValue | readonly HeaderValue[]>\n | undefined\n | null\n | NullableHeaders;\n\nconst brand_privateNullableHeaders = /* @__PURE__ */ Symbol('brand.privateNullableHeaders');\n\n/**\n * @internal\n * Users can pass explicit nulls to unset default headers. When we parse them\n * into a standard headers type we need to preserve that information.\n */\nexport type NullableHeaders = {\n /** Brand check, prevent users from creating a NullableHeaders. */\n [brand_privateNullableHeaders]: true;\n /** Parsed headers. */\n values: Headers;\n /** Set of lowercase header names explicitly set to null. */\n nulls: Set<string>;\n};\n\nfunction* iterateHeaders(headers: HeadersLike): IterableIterator<readonly [string, string | null]> {\n if (!headers) return;\n\n if (brand_privateNullableHeaders in headers) {\n const { values, nulls } = headers;\n yield* values.entries();\n for (const name of nulls) {\n yield [name, null];\n }\n return;\n }\n\n let shouldClear = false;\n let iter: Iterable<readonly (HeaderValue | readonly HeaderValue[])[]>;\n if (headers instanceof Headers) {\n iter = headers.entries();\n } else if (isReadonlyArray(headers)) {\n iter = headers;\n } else {\n shouldClear = true;\n iter = Object.entries(headers ?? {});\n }\n for (let row of iter) {\n const name = row[0];\n if (typeof name !== 'string') throw new TypeError('expected header name to be a string');\n const values = isReadonlyArray(row[1]) ? row[1] : [row[1]];\n let didClear = false;\n for (const value of values) {\n if (value === undefined) continue;\n\n // Objects keys always overwrite older headers, they never append.\n // Yield a null to clear the header before adding the new values.\n if (shouldClear && !didClear) {\n didClear = true;\n yield [name, null];\n }\n yield [name, value];\n }\n }\n}\n\nexport const buildHeaders = (newHeaders: HeadersLike[]): NullableHeaders => {\n const targetHeaders = new Headers();\n const nullHeaders = new Set<string>();\n for (const headers of newHeaders) {\n const seenHeaders = new Set<string>();\n for (const [name, value] of iterateHeaders(headers)) {\n const lowerName = name.toLowerCase();\n if (!seenHeaders.has(lowerName)) {\n targetHeaders.delete(name);\n seenHeaders.add(lowerName);\n }\n if (value === null) {\n targetHeaders.delete(name);\n nullHeaders.add(lowerName);\n } else {\n targetHeaders.append(name, value);\n nullHeaders.delete(lowerName);\n }\n }\n }\n return { [brand_privateNullableHeaders]: true, values: targetHeaders, nulls: nullHeaders };\n};\n\nexport const isEmptyHeaders = (headers: HeadersLike) => {\n for (const _ of iterateHeaders(headers)) return false;\n return true;\n};\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\n/**\n * Read an environment variable.\n *\n * Trims beginning and trailing whitespace.\n *\n * Will return undefined if the environment variable doesn't exist or cannot be accessed.\n */\nexport const readEnv = (env: string): string | undefined => {\n if (typeof (globalThis as any).process !== 'undefined') {\n return (globalThis as any).process.env?.[env]?.trim() ?? undefined;\n }\n if (typeof (globalThis as any).Deno !== 'undefined') {\n return (globalThis as any).Deno.env?.get?.(env)?.trim();\n }\n return undefined;\n};\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nimport type { RequestInit, RequestInfo, BodyInit } from './internal/builtin-types.js';\nimport type { HTTPMethod, PromiseOrValue, MergedRequestInit, FinalizedRequestInit } from './internal/types.js';\nimport { uuid4 } from './internal/utils/uuid.js';\nimport { validatePositiveInteger, isAbsoluteURL, safeJSON } from './internal/utils/values.js';\nimport { sleep } from './internal/utils/sleep.js';\nexport type { Logger, LogLevel } from './internal/utils/log.js';\nimport { castToError, isAbortError } from './internal/errors.js';\nimport type { APIResponseProps } from './internal/parse.js';\nimport { getPlatformHeaders } from './internal/detect-platform.js';\nimport * as Shims from './internal/shims.js';\nimport * as Opts from './internal/request-options.js';\nimport { VERSION } from './version.js';\nimport * as Errors from './core/error.js';\nimport * as Uploads from './core/uploads.js';\nimport * as API from './resources/index.js';\nimport { APIPromise } from './core/api-promise.js';\nimport {\n AllowedTools,\n Annotation,\n AudioContent,\n AudioMimeType,\n CodeExecutionCallArguments,\n CodeExecutionCallContent,\n CodeExecutionResultContent,\n Content,\n ContentDelta,\n ContentStart,\n ContentStop,\n CreateAgentInteractionParamsNonStreaming,\n CreateAgentInteractionParamsStreaming,\n CreateModelInteractionParamsNonStreaming,\n CreateModelInteractionParamsStreaming,\n DeepResearchAgentConfig,\n DocumentContent,\n DocumentMimeType,\n DynamicAgentConfig,\n ErrorEvent,\n FileSearchCallContent,\n FileSearchResultContent,\n Function,\n FunctionCallContent,\n FunctionResultContent,\n GenerationConfig,\n GoogleSearchCallArguments,\n GoogleSearchCallContent,\n GoogleSearchResult,\n GoogleSearchResultContent,\n ImageConfig,\n ImageContent,\n ImageMimeType,\n Interaction,\n InteractionCancelParams,\n InteractionCompleteEvent,\n InteractionCreateParams,\n InteractionDeleteParams,\n InteractionDeleteResponse,\n InteractionGetParams,\n InteractionGetParamsNonStreaming,\n InteractionGetParamsStreaming,\n InteractionSSEEvent,\n InteractionStartEvent,\n InteractionStatusUpdate,\n Interactions,\n MCPServerToolCallContent,\n MCPServerToolResultContent,\n Model,\n SpeechConfig,\n TextContent,\n ThinkingLevel,\n ThoughtContent,\n Tool,\n ToolChoice,\n ToolChoiceConfig,\n ToolChoiceType,\n Turn,\n URLContextCallArguments,\n URLContextCallContent,\n URLContextResult,\n URLContextResultContent,\n Usage,\n VideoContent,\n VideoMimeType,\n} from './resources/interactions.js';\nimport { type Fetch } from './internal/builtin-types.js';\nimport { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers.js';\nimport { FinalRequestOptions, RequestOptions } from './internal/request-options.js';\nimport { readEnv } from './internal/utils/env.js';\nimport {\n type LogLevel,\n type Logger,\n formatRequestDetails,\n loggerFor,\n parseLogLevel,\n} from './internal/utils/log.js';\nimport { isEmptyObj } from './internal/utils/values.js';\nimport { GeminiNextGenAPIClientAdapter } from './client-adapter.js';\n\nexport interface ClientOptions {\n /**\n * Defaults to process.env['GEMINI_API_KEY'].\n */\n apiKey?: string | null | undefined;\n\n apiVersion?: string | undefined;\n\n /**\n * Override the default base URL for the API, e.g., \"https://api.example.com/v2/\"\n *\n * Defaults to process.env['GEMINI_NEXT_GEN_API_BASE_URL'].\n */\n baseURL?: string | null | undefined;\n\n /**\n * The maximum amount of time (in milliseconds) that the client should wait for a response\n * from the server before timing out a single request.\n *\n * Note that request timeouts are retried by default, so in a worst-case scenario you may wait\n * much longer than this timeout before the promise succeeds or fails.\n *\n * @unit milliseconds\n */\n timeout?: number | undefined;\n /**\n * Additional `RequestInit` options to be passed to `fetch` calls.\n * Properties will be overridden by per-request `fetchOptions`.\n */\n fetchOptions?: MergedRequestInit | undefined;\n\n /**\n * Specify a custom `fetch` function implementation.\n *\n * If not provided, we expect that `fetch` is defined globally.\n */\n fetch?: Fetch | undefined;\n\n /**\n * The maximum number of times that the client will retry a request in case of a\n * temporary failure, like a network error or a 5XX error from the server.\n *\n * @default 2\n */\n maxRetries?: number | undefined;\n\n /**\n * Default headers to include with every request to the API.\n *\n * These can be removed in individual requests by explicitly setting the\n * header to `null` in request options.\n */\n defaultHeaders?: HeadersLike | undefined;\n\n /**\n * Default query parameters to include with every request to the API.\n *\n * These can be removed in individual requests by explicitly setting the\n * param to `undefined` in request options.\n */\n defaultQuery?: Record<string, string | undefined> | undefined;\n\n /**\n * Set the log level.\n *\n * Defaults to process.env['GEMINI_NEXT_GEN_API_LOG'] or 'warn' if it isn't set.\n */\n logLevel?: LogLevel | undefined;\n\n /**\n * Set the logger.\n *\n * Defaults to globalThis.console.\n */\n logger?: Logger | undefined;\n\n /**\n * The adapter to the parent API client instance (for accessing auth, project, location)\n */\n clientAdapter: GeminiNextGenAPIClientAdapter;\n}\n\n/**\n * Base class for Gemini Next Gen API API clients.\n */\nexport class BaseGeminiNextGenAPIClient {\n apiKey: string | null;\n apiVersion: string;\n\n baseURL: string;\n maxRetries: number;\n timeout: number;\n logger: Logger;\n logLevel: LogLevel | undefined;\n fetchOptions: MergedRequestInit | undefined;\n\n private fetch: Fetch;\n private encoder: Opts.RequestEncoder;\n protected idempotencyHeader?: string;\n private _options: ClientOptions;\n private clientAdapter: GeminiNextGenAPIClientAdapter;\n\n /**\n * API Client for interfacing with the Gemini Next Gen API API.\n *\n * @param {string | null | undefined} [opts.apiKey=process.env['GEMINI_API_KEY'] ?? null]\n * @param {string | undefined} [opts.apiVersion=v1beta]\n * @param {string} [opts.baseURL=process.env['GEMINI_NEXT_GEN_API_BASE_URL'] ?? https://generativelanguage.googleapis.com] - Override the default base URL for the API.\n * @param {number} [opts.timeout=1 minute] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out.\n * @param {MergedRequestInit} [opts.fetchOptions] - Additional `RequestInit` options to be passed to `fetch` calls.\n * @param {Fetch} [opts.fetch] - Specify a custom `fetch` function implementation.\n * @param {number} [opts.maxRetries=2] - The maximum number of times the client will retry a request.\n * @param {HeadersLike} opts.defaultHeaders - Default headers to include with every request to the API.\n * @param {Record<string, string | undefined>} opts.defaultQuery - Default query parameters to include with every request to the API.\n */\n constructor({\n baseURL = readEnv('GEMINI_NEXT_GEN_API_BASE_URL'),\n apiKey = readEnv('GEMINI_API_KEY') ?? null,\n apiVersion = 'v1beta',\n ...opts\n }: ClientOptions) {\n const options: ClientOptions = {\n apiKey,\n apiVersion,\n ...opts,\n baseURL: baseURL || `https://generativelanguage.googleapis.com`,\n };\n\n this.baseURL = options.baseURL!;\n this.timeout = options.timeout ?? BaseGeminiNextGenAPIClient.DEFAULT_TIMEOUT /* 1 minute */;\n this.logger = options.logger ?? console;\n const defaultLogLevel = 'warn';\n // Set default logLevel early so that we can log a warning in parseLogLevel.\n this.logLevel = defaultLogLevel;\n this.logLevel =\n parseLogLevel(options.logLevel, 'ClientOptions.logLevel', this) ??\n parseLogLevel(readEnv('GEMINI_NEXT_GEN_API_LOG'), \"process.env['GEMINI_NEXT_GEN_API_LOG']\", this) ??\n defaultLogLevel;\n this.fetchOptions = options.fetchOptions;\n this.maxRetries = options.maxRetries ?? 2;\n this.fetch = options.fetch ?? Shims.getDefaultFetch();\n this.encoder = Opts.FallbackEncoder;\n\n this._options = options;\n\n this.apiKey = apiKey;\n this.apiVersion = apiVersion;\n this.clientAdapter = options.clientAdapter;\n }\n\n /**\n * Create a new client instance re-using the same options given to the current client with optional overriding.\n */\n withOptions(options: Partial<ClientOptions>): this {\n const client = new (this.constructor as any as new (props: ClientOptions) => typeof this)({\n ...this._options,\n baseURL: this.baseURL,\n maxRetries: this.maxRetries,\n timeout: this.timeout,\n logger: this.logger,\n logLevel: this.logLevel,\n fetch: this.fetch,\n fetchOptions: this.fetchOptions,\n apiKey: this.apiKey,\n apiVersion: this.apiVersion,\n ...options,\n });\n return client;\n }\n\n /**\n * Check whether the base URL is set to its default.\n */\n private baseURLOverridden() {\n return this.baseURL !== 'https://generativelanguage.googleapis.com';\n }\n\n protected defaultQuery(): Record<string, string | undefined> | undefined {\n return this._options.defaultQuery;\n }\n\n protected validateHeaders({ values, nulls }: NullableHeaders) {\n // The headers object handles case insensitivity.\n if (values.has('authorization') || values.has('x-goog-api-key')) {\n return;\n }\n if (this.apiKey && values.get('x-goog-api-key')) {\n return;\n }\n if (nulls.has('x-goog-api-key')) {\n return;\n }\n\n throw new Error(\n 'Could not resolve authentication method. Expected the apiKey to be set. Or for the \"x-goog-api-key\" headers to be explicitly omitted',\n );\n }\n\n protected async authHeaders(opts: FinalRequestOptions): Promise<NullableHeaders | undefined> {\n const existingHeaders = buildHeaders([opts.headers]);\n\n if (existingHeaders.values.has('authorization') || existingHeaders.values.has('x-goog-api-key')) {\n return undefined;\n }\n\n if (this.apiKey) {\n return buildHeaders([{ 'x-goog-api-key': this.apiKey }]);\n }\n\n if (this.clientAdapter.isVertexAI()) {\n return buildHeaders([await this.clientAdapter.getAuthHeaders()]);\n }\n\n return undefined;\n }\n\n /**\n * Basic re-implementation of `qs.stringify` for primitive types.\n */\n protected stringifyQuery(query: Record<string, unknown>): string {\n return Object.entries(query)\n .filter(([_, value]) => typeof value !== 'undefined')\n .map(([key, value]) => {\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {\n return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;\n }\n if (value === null) {\n return `${encodeURIComponent(key)}=`;\n }\n throw new Errors.GeminiNextGenAPIClientError(\n `Cannot stringify type ${typeof value}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`,\n );\n })\n .join('&');\n }\n\n private getUserAgent(): string {\n return `${this.constructor.name}/JS ${VERSION}`;\n }\n\n protected defaultIdempotencyKey(): string {\n return `stainless-node-retry-${uuid4()}`;\n }\n\n protected makeStatusError(\n status: number,\n error: Object,\n message: string | undefined,\n headers: Headers,\n ): Errors.APIError {\n return Errors.APIError.generate(status, error, message, headers);\n }\n\n buildURL(\n path: string,\n query: Record<string, unknown> | null | undefined,\n defaultBaseURL?: string | undefined,\n ): string {\n const baseURL = (!this.baseURLOverridden() && defaultBaseURL) || this.baseURL;\n const url =\n isAbsoluteURL(path) ?\n new URL(path)\n : new URL(baseURL + (baseURL.endsWith('/') && path.startsWith('/') ? path.slice(1) : path));\n\n const defaultQuery = this.defaultQuery();\n if (!isEmptyObj(defaultQuery)) {\n query = { ...defaultQuery, ...query };\n }\n\n if (typeof query === 'object' && query && !Array.isArray(query)) {\n url.search = this.stringifyQuery(query as Record<string, unknown>);\n }\n\n return url.toString();\n }\n\n /**\n * Used as a callback for mutating the given `FinalRequestOptions` object.\n\n */\n protected async prepareOptions(options: FinalRequestOptions): Promise<void> {\n if (\n this.clientAdapter &&\n this.clientAdapter.isVertexAI() &&\n !options.path.startsWith(`/${this.apiVersion}/projects/`)\n ) {\n const oldPath = options.path.slice(this.apiVersion.length + 1);\n options.path = `/${\n this.apiVersion\n }/projects/${this.clientAdapter.getProject()}/locations/${this.clientAdapter.getLocation()}${oldPath}`;\n }\n }\n\n /**\n * Used as a callback for mutating the given `RequestInit` object.\n *\n * This is useful for cases where you want to add certain headers based off of\n * the request properties, e.g. `method` or `url`.\n */\n protected async prepareRequest(\n request: RequestInit,\n { url, options }: { url: string; options: FinalRequestOptions },\n ): Promise<void> {}\n\n get<Rsp>(path: string, opts?: PromiseOrValue<RequestOptions>): APIPromise<Rsp> {\n return this.methodRequest('get', path, opts);\n }\n\n post<Rsp>(path: string, opts?: PromiseOrValue<RequestOptions>): APIPromise<Rsp> {\n return this.methodRequest('post', path, opts);\n }\n\n patch<Rsp>(path: string, opts?: PromiseOrValue<RequestOptions>): APIPromise<Rsp> {\n return this.methodRequest('patch', path, opts);\n }\n\n put<Rsp>(path: string, opts?: PromiseOrValue<RequestOptions>): APIPromise<Rsp> {\n return this.methodRequest('put', path, opts);\n }\n\n delete<Rsp>(path: string, opts?: PromiseOrValue<RequestOptions>): APIPromise<Rsp> {\n return this.methodRequest('delete', path, opts);\n }\n\n private methodRequest<Rsp>(\n method: HTTPMethod,\n path: string,\n opts?: PromiseOrValue<RequestOptions>,\n ): APIPromise<Rsp> {\n return this.request(\n Promise.resolve(opts).then((opts) => {\n return { method, path, ...opts };\n }),\n );\n }\n\n request<Rsp>(\n options: PromiseOrValue<FinalRequestOptions>,\n remainingRetries: number | null = null,\n ): APIPromise<Rsp> {\n return new APIPromise(this, this.makeRequest(options, remainingRetries, undefined));\n }\n\n private async makeRequest(\n optionsInput: PromiseOrValue<FinalRequestOptions>,\n retriesRemaining: number | null,\n retryOfRequestLogID: string | undefined,\n ): Promise<APIResponseProps> {\n const options = await optionsInput;\n const maxRetries = options.maxRetries ?? this.maxRetries;\n if (retriesRemaining == null) {\n retriesRemaining = maxRetries;\n }\n\n await this.prepareOptions(options);\n\n const { req, url, timeout } = await this.buildRequest(options, {\n retryCount: maxRetries - retriesRemaining,\n });\n\n await this.prepareRequest(req, { url, options });\n\n /** Not an API request ID, just for correlating local log entries. */\n const requestLogID = 'log_' + ((Math.random() * (1 << 24)) | 0).toString(16).padStart(6, '0');\n const retryLogStr = retryOfRequestLogID === undefined ? '' : `, retryOf: ${retryOfRequestLogID}`;\n const startTime = Date.now();\n\n loggerFor(this).debug(\n `[${requestLogID}] sending request`,\n formatRequestDetails({\n retryOfRequestLogID,\n method: options.method,\n url,\n options,\n headers: req.headers,\n }),\n );\n\n if (options.signal?.aborted) {\n throw new Errors.APIUserAbortError();\n }\n\n const controller = new AbortController();\n const response = await this.fetchWithTimeout(url, req, timeout, controller).catch(castToError);\n const headersTime = Date.now();\n\n if (response instanceof globalThis.Error) {\n const retryMessage = `retrying, ${retriesRemaining} attempts remaining`;\n if (options.signal?.aborted) {\n throw new Errors.APIUserAbortError();\n }\n // detect native connection timeout errors\n // deno throws \"TypeError: error sending request for url (https://example/): client error (Connect): tcp connect error: Operation timed out (os error 60): Operation timed out (os error 60)\"\n // undici throws \"TypeError: fetch failed\" with cause \"ConnectTimeoutError: Connect Timeout Error (attempted address: example:443, timeout: 1ms)\"\n // others do not provide enough information to distinguish timeouts from other connection errors\n const isTimeout =\n isAbortError(response) ||\n /timed? ?out/i.test(String(response) + ('cause' in response ? String(response.cause) : ''));\n if (retriesRemaining) {\n loggerFor(this).info(\n `[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - ${retryMessage}`,\n );\n loggerFor(this).debug(\n `[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (${retryMessage})`,\n formatRequestDetails({\n retryOfRequestLogID,\n url,\n durationMs: headersTime - startTime,\n message: response.message,\n }),\n );\n return this.retryRequest(options, retriesRemaining, retryOfRequestLogID ?? requestLogID);\n }\n loggerFor(this).info(\n `[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - error; no more retries left`,\n );\n loggerFor(this).debug(\n `[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (error; no more retries left)`,\n formatRequestDetails({\n retryOfRequestLogID,\n url,\n durationMs: headersTime - startTime,\n message: response.message,\n }),\n );\n if (isTimeout) {\n throw new Errors.APIConnectionTimeoutError();\n }\n throw new Errors.APIConnectionError({ cause: response });\n }\n\n const responseInfo = `[${requestLogID}${retryLogStr}] ${req.method} ${url} ${\n response.ok ? 'succeeded' : 'failed'\n } with status ${response.status} in ${headersTime - startTime}ms`;\n\n if (!response.ok) {\n const shouldRetry = await this.shouldRetry(response);\n if (retriesRemaining && shouldRetry) {\n const retryMessage = `retrying, ${retriesRemaining} attempts remaining`;\n\n // We don't need the body of this response.\n await Shims.CancelReadableStream(response.body);\n loggerFor(this).info(`${responseInfo} - ${retryMessage}`);\n loggerFor(this).debug(\n `[${requestLogID}] response error (${retryMessage})`,\n formatRequestDetails({\n retryOfRequestLogID,\n url: response.url,\n status: response.status,\n headers: response.headers,\n durationMs: headersTime - startTime,\n }),\n );\n return this.retryRequest(\n options,\n retriesRemaining,\n retryOfRequestLogID ?? requestLogID,\n response.headers,\n );\n }\n\n const retryMessage = shouldRetry ? `error; no more retries left` : `error; not retryable`;\n\n loggerFor(this).info(`${responseInfo} - ${retryMessage}`);\n\n const errText = await response.text().catch((err: any) => castToError(err).message);\n const errJSON = safeJSON(errText);\n const errMessage = errJSON ? undefined : errText;\n\n loggerFor(this).debug(\n `[${requestLogID}] response error (${retryMessage})`,\n formatRequestDetails({\n retryOfRequestLogID,\n url: response.url,\n status: response.status,\n headers: response.headers,\n message: errMessage,\n durationMs: Date.now() - startTime,\n }),\n );\n // @ts-ignore\n const err = this.makeStatusError(response.status, errJSON, errMessage, response.headers);\n throw err;\n }\n\n loggerFor(this).info(responseInfo);\n loggerFor(this).debug(\n `[${requestLogID}] response start`,\n formatRequestDetails({\n retryOfRequestLogID,\n url: response.url,\n status: response.status,\n headers: response.headers,\n durationMs: headersTime - startTime,\n }),\n );\n\n return { response, options, controller, requestLogID, retryOfRequestLogID, startTime };\n }\n\n async fetchWithTimeout(\n url: RequestInfo,\n init: RequestInit | undefined,\n ms: number,\n controller: AbortController,\n ): Promise<Response> {\n const { signal, method, ...options } = init || {};\n const abort = this._makeAbort(controller);\n if (signal) signal.addEventListener('abort', abort, { once: true });\n\n const timeout = setTimeout(abort, ms);\n\n const isReadableBody =\n ((globalThis as any).ReadableStream && options.body instanceof (globalThis as any).ReadableStream) ||\n (typeof options.body === 'object' && options.body !== null && Symbol.asyncIterator in options.body);\n\n const fetchOptions: RequestInit = {\n signal: controller.signal as any,\n ...(isReadableBody ? { duplex: 'half' } : {}),\n method: 'GET',\n ...options,\n };\n if (method) {\n // Custom methods like 'patch' need to be uppercased\n // See https://github.com/nodejs/undici/issues/2294\n fetchOptions.method = method.toUpperCase();\n }\n\n try {\n // use undefined this binding; fetch errors if bound to something else in browser/cloudflare\n return await this.fetch.call(undefined, url, fetchOptions);\n } finally {\n clearTimeout(timeout);\n }\n }\n\n private async shouldRetry(response: Response): Promise<boolean> {\n // Note this is not a standard header.\n const shouldRetryHeader = response.headers.get('x-should-retry');\n\n // If the server explicitly says whether or not to retry, obey.\n if (shouldRetryHeader === 'true') return true;\n if (shouldRetryHeader === 'false') return false;\n\n // Retry on request timeouts.\n if (response.status === 408) return true;\n\n // Retry on lock timeouts.\n if (response.status === 409) return true;\n\n // Retry on rate limits.\n if (response.status === 429) return true;\n\n // Retry internal errors.\n if (response.status >= 500) return true;\n\n return false;\n }\n\n private async retryRequest(\n options: FinalRequestOptions,\n retriesRemaining: number,\n requestLogID: string,\n responseHeaders?: Headers | undefined,\n ): Promise<APIResponseProps> {\n let timeoutMillis: number | undefined;\n\n // Note the `retry-after-ms` header may not be standard, but is a good idea and we'd like proactive support for it.\n const retryAfterMillisHeader = responseHeaders?.get('retry-after-ms');\n if (retryAfterMillisHeader) {\n const timeoutMs = parseFloat(retryAfterMillisHeader);\n if (!Number.isNaN(timeoutMs)) {\n timeoutMillis = timeoutMs;\n }\n }\n\n // About the Retry-After header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After\n const retryAfterHeader = responseHeaders?.get('retry-after');\n if (retryAfterHeader && !timeoutMillis) {\n const timeoutSeconds = parseFloat(retryAfterHeader);\n if (!Number.isNaN(timeoutSeconds)) {\n timeoutMillis = timeoutSeconds * 1000;\n } else {\n timeoutMillis = Date.parse(retryAfterHeader) - Date.now();\n }\n }\n\n // If the API asks us to wait a certain amount of time (and it's a reasonable amount),\n // just do what it says, but otherwise calculate a default\n if (!(timeoutMillis && 0 <= timeoutMillis && timeoutMillis < 60 * 1000)) {\n const maxRetries = options.maxRetries ?? this.maxRetries;\n timeoutMillis = this.calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries);\n }\n await sleep(timeoutMillis);\n\n return this.makeRequest(options, retriesRemaining - 1, requestLogID);\n }\n\n private calculateDefaultRetryTimeoutMillis(retriesRemaining: number, maxRetries: number): number {\n const initialRetryDelay = 0.5;\n const maxRetryDelay = 8.0;\n\n const numRetries = maxRetries - retriesRemaining;\n\n // Apply exponential backoff, but not more than the max.\n const sleepSeconds = Math.min(initialRetryDelay * Math.pow(2, numRetries), maxRetryDelay);\n\n // Apply some jitter, take up to at most 25 percent of the retry time.\n const jitter = 1 - Math.random() * 0.25;\n\n return sleepSeconds * jitter * 1000;\n }\n\n async buildRequest(\n inputOptions: FinalRequestOptions,\n { retryCount = 0 }: { retryCount?: number } = {},\n ): Promise<{ req: FinalizedRequestInit; url: string; timeout: number }> {\n const options = { ...inputOptions };\n const { method, path, query, defaultBaseURL } = options;\n\n const url = this.buildURL(path!, query as Record<string, unknown>, defaultBaseURL);\n if ('timeout' in options) validatePositiveInteger('timeout', options.timeout);\n options.timeout = options.timeout ?? this.timeout;\n const { bodyHeaders, body } = this.buildBody({ options });\n const reqHeaders = await this.buildHeaders({ options: inputOptions, method, bodyHeaders, retryCount });\n\n const req: FinalizedRequestInit = {\n method,\n headers: reqHeaders,\n ...(options.signal && { signal: options.signal }),\n ...((globalThis as any).ReadableStream &&\n body instanceof (globalThis as any).ReadableStream && { duplex: 'half' }),\n ...(body && { body }),\n ...((this.fetchOptions as any) ?? {}),\n ...((options.fetchOptions as any) ?? {}),\n };\n\n return { req, url, timeout: options.timeout };\n }\n\n private async buildHeaders({\n options,\n method,\n bodyHeaders,\n retryCount,\n }: {\n options: FinalRequestOptions;\n method: HTTPMethod;\n bodyHeaders: HeadersLike;\n retryCount: number;\n }): Promise<Headers> {\n let idempotencyHeaders: HeadersLike = {};\n if (this.idempotencyHeader && method !== 'get') {\n if (!options.idempotencyKey) options.idempotencyKey = this.defaultIdempotencyKey();\n idempotencyHeaders[this.idempotencyHeader] = options.idempotencyKey;\n }\n\n const authHeaders = await this.authHeaders(options);\n\n let headers = buildHeaders([\n idempotencyHeaders,\n {\n Accept: 'application/json',\n 'User-Agent': this.getUserAgent(),\n 'X-Stainless-Retry-Count': String(retryCount),\n ...(options.timeout ? { 'X-Stainless-Timeout': String(Math.trunc(options.timeout / 1000)) } : {}),\n ...getPlatformHeaders(),\n },\n this._options.defaultHeaders,\n bodyHeaders,\n options.headers,\n authHeaders,\n ]);\n\n this.validateHeaders(headers);\n\n return headers.values;\n }\n\n private _makeAbort(controller: AbortController) {\n // note: we can't just inline this method inside `fetchWithTimeout()` because then the closure\n // would capture all request options, and cause a memory leak.\n return () => controller.abort();\n }\n\n private buildBody({ options: { body, headers: rawHeaders } }: { options: FinalRequestOptions }): {\n bodyHeaders: HeadersLike;\n body: BodyInit | undefined;\n } {\n if (!body) {\n return { bodyHeaders: undefined, body: undefined };\n }\n const headers = buildHeaders([rawHeaders]);\n if (\n // Pass raw type verbatim\n ArrayBuffer.isView(body) ||\n body instanceof ArrayBuffer ||\n body instanceof DataView ||\n (typeof body === 'string' &&\n // Preserve legacy string encoding behavior for now\n headers.values.has('content-type')) ||\n // `Blob` is superset of `File`\n ((globalThis as any).Blob && body instanceof (globalThis as any).Blob) ||\n // `FormData` -> `multipart/form-data`\n body instanceof FormData ||\n // `URLSearchParams` -> `application/x-www-form-urlencoded`\n body instanceof URLSearchParams ||\n // Send chunked stream (each chunk has own `length`)\n ((globalThis as any).ReadableStream && body instanceof (globalThis as any).ReadableStream)\n ) {\n return { bodyHeaders: undefined, body: body as BodyInit };\n } else if (\n typeof body === 'object' &&\n (Symbol.asyncIterator in body ||\n (Symbol.iterator in body && 'next' in body && typeof body.next === 'function'))\n ) {\n return { bodyHeaders: undefined, body: Shims.ReadableStreamFrom(body as AsyncIterable<Uint8Array>) };\n } else {\n return this.encoder({ body, headers });\n }\n }\n\n static DEFAULT_TIMEOUT = 60000; // 1 minute\n}\n\n/**\n * API Client for interfacing with the Gemini Next Gen API API.\n */\nexport class GeminiNextGenAPIClient extends BaseGeminiNextGenAPIClient {\n static GeminiNextGenAPIClient = this;\n\n static GeminiNextGenAPIClientError = Errors.GeminiNextGenAPIClientError;\n static APIError = Errors.APIError;\n static APIConnectionError = Errors.APIConnectionError;\n static APIConnectionTimeoutError = Errors.APIConnectionTimeoutError;\n static APIUserAbortError = Errors.APIUserAbortError;\n static NotFoundError = Errors.NotFoundError;\n static ConflictError = Errors.ConflictError;\n static RateLimitError = Errors.RateLimitError;\n static BadRequestError = Errors.BadRequestError;\n static AuthenticationError = Errors.AuthenticationError;\n static InternalServerError = Errors.InternalServerError;\n static PermissionDeniedError = Errors.PermissionDeniedError;\n static UnprocessableEntityError = Errors.UnprocessableEntityError;\n\n static toFile = Uploads.toFile;\n\n interactions: API.Interactions = new API.Interactions(this);\n}\n\nGeminiNextGenAPIClient.Interactions = Interactions;\n\nexport declare namespace GeminiNextGenAPIClient {\n export type RequestOptions = Opts.RequestOptions;\n\n export {\n Interactions as Interactions,\n type AllowedTools as AllowedTools,\n type Annotation as Annotation,\n type AudioContent as AudioContent,\n type AudioMimeType as AudioMimeType,\n type CodeExecutionCallArguments as CodeExecutionCallArguments,\n type CodeExecutionCallContent as CodeExecutionCallContent,\n type CodeExecutionResultContent as CodeExecutionResultContent,\n type Content as Content,\n type ContentDelta as ContentDelta,\n type ContentStart as ContentStart,\n type ContentStop as ContentStop,\n type DeepResearchAgentConfig as DeepResearchAgentConfig,\n type DocumentContent as DocumentContent,\n type DocumentMimeType as DocumentMimeType,\n type DynamicAgentConfig as DynamicAgentConfig,\n type ErrorEvent as ErrorEvent,\n type FileSearchCallContent as FileSearchCallContent,\n type FileSearchResultContent as FileSearchResultContent,\n type Function as Function,\n type FunctionCallContent as FunctionCallContent,\n type FunctionResultContent as FunctionResultContent,\n type GenerationConfig as GenerationConfig,\n type GoogleSearchCallArguments as GoogleSearchCallArguments,\n type GoogleSearchCallContent as GoogleSearchCallContent,\n type GoogleSearchResult as GoogleSearchResult,\n type GoogleSearchResultContent as GoogleSearchResultContent,\n type ImageConfig as ImageConfig,\n type ImageContent as ImageContent,\n type ImageMimeType as ImageMimeType,\n type Interaction as Interaction,\n type InteractionCompleteEvent as InteractionCompleteEvent,\n type InteractionSSEEvent as InteractionSSEEvent,\n type InteractionStartEvent as InteractionStartEvent,\n type InteractionStatusUpdate as InteractionStatusUpdate,\n type MCPServerToolCallContent as MCPServerToolCallContent,\n type MCPServerToolResultContent as MCPServerToolResultContent,\n type Model as Model,\n type SpeechConfig as SpeechConfig,\n type TextContent as TextContent,\n type ThinkingLevel as ThinkingLevel,\n type ThoughtContent as ThoughtContent,\n type Tool as Tool,\n type ToolChoice as ToolChoice,\n type ToolChoiceConfig as ToolChoiceConfig,\n type ToolChoiceType as ToolChoiceType,\n type Turn as Turn,\n type URLContextCallArguments as URLContextCallArguments,\n type URLContextCallContent as URLContextCallContent,\n type URLContextResult as URLContextResult,\n type URLContextResultContent as URLContextResultContent,\n type Usage as Usage,\n type VideoContent as VideoContent,\n type VideoMimeType as VideoMimeType,\n type InteractionDeleteResponse as InteractionDeleteResponse,\n type InteractionCreateParams as InteractionCreateParams,\n type CreateModelInteractionParamsNonStreaming as CreateModelInteractionParamsNonStreaming,\n type CreateModelInteractionParamsStreaming as CreateModelInteractionParamsStreaming,\n type CreateAgentInteractionParamsNonStreaming as CreateAgentInteractionParamsNonStreaming,\n type CreateAgentInteractionParamsStreaming as CreateAgentInteractionParamsStreaming,\n type InteractionDeleteParams as InteractionDeleteParams,\n type InteractionCancelParams as InteractionCancelParams,\n type InteractionGetParams as InteractionGetParams,\n type InteractionGetParamsNonStreaming as InteractionGetParamsNonStreaming,\n type InteractionGetParamsStreaming as InteractionGetParamsStreaming,\n };\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {GoogleAuth, GoogleAuthOptions} from 'google-auth-library';\n\nimport {Auth} from '../_auth.js';\n\nexport const GOOGLE_API_KEY_HEADER = 'x-goog-api-key';\nconst REQUIRED_VERTEX_AI_SCOPE =\n 'https://www.googleapis.com/auth/cloud-platform';\n\nexport interface NodeAuthOptions {\n /**\n * The API Key. This is required for Gemini API users.\n */\n apiKey?: string;\n /**\n * Optional. These are the authentication options provided by google-auth-library for Vertex AI users.\n * Complete list of authentication options are documented in the\n * GoogleAuthOptions interface:\n * https://github.com/googleapis/google-auth-library-nodejs/blob/main/src/auth/googleauth.ts.\n */\n googleAuthOptions?: GoogleAuthOptions;\n}\n\nexport class NodeAuth implements Auth {\n private readonly googleAuth?: GoogleAuth;\n private readonly apiKey?: string;\n\n constructor(opts: NodeAuthOptions) {\n if (opts.apiKey !== undefined) {\n this.apiKey = opts.apiKey;\n return;\n }\n const vertexAuthOptions = buildGoogleAuthOptions(opts.googleAuthOptions);\n this.googleAuth = new GoogleAuth(vertexAuthOptions);\n }\n\n async addAuthHeaders(headers: Headers, url?: string): Promise<void> {\n if (this.apiKey !== undefined) {\n if (this.apiKey.startsWith('auth_tokens/')) {\n throw new Error('Ephemeral tokens are only supported by the live API.');\n }\n this.addKeyHeader(headers);\n return;\n }\n\n return this.addGoogleAuthHeaders(headers, url);\n }\n\n private addKeyHeader(headers: Headers) {\n if (headers.get(GOOGLE_API_KEY_HEADER) !== null) {\n return;\n }\n if (this.apiKey === undefined) {\n // This should never happen, this method is only called\n // when apiKey is set.\n throw new Error('Trying to set API key header but apiKey is not set');\n }\n headers.append(GOOGLE_API_KEY_HEADER, this.apiKey);\n }\n\n private async addGoogleAuthHeaders(\n headers: Headers,\n url?: string,\n ): Promise<void> {\n if (this.googleAuth === undefined) {\n // This should never happen, addGoogleAuthHeaders should only be\n // called when there is no apiKey set and in these cases googleAuth\n // is set.\n throw new Error(\n 'Trying to set google-auth headers but googleAuth is unset',\n );\n }\n const authHeaders = await this.googleAuth.getRequestHeaders(url);\n for (const [key, value] of authHeaders) {\n if (headers.get(key) !== null) {\n continue;\n }\n headers.append(key, value);\n }\n }\n}\n\nfunction buildGoogleAuthOptions(\n googleAuthOptions?: GoogleAuthOptions,\n): GoogleAuthOptions {\n let authOptions: GoogleAuthOptions;\n if (!googleAuthOptions) {\n authOptions = {\n scopes: [REQUIRED_VERTEX_AI_SCOPE],\n };\n return authOptions;\n } else {\n authOptions = googleAuthOptions;\n if (!authOptions.scopes) {\n authOptions.scopes = [REQUIRED_VERTEX_AI_SCOPE];\n return authOptions;\n } else if (\n (typeof authOptions.scopes === 'string' &&\n authOptions.scopes !== REQUIRED_VERTEX_AI_SCOPE) ||\n (Array.isArray(authOptions.scopes) &&\n authOptions.scopes.indexOf(REQUIRED_VERTEX_AI_SCOPE) < 0)\n ) {\n throw new Error(\n `Invalid auth scopes. Scopes must include: ${REQUIRED_VERTEX_AI_SCOPE}`,\n );\n }\n return authOptions;\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {createWriteStream} from 'fs';\nimport {writeFile} from 'fs/promises';\nimport {Readable} from 'node:stream';\nimport {finished} from 'node:stream/promises';\nimport type {ReadableStream} from 'node:stream/web';\n\nimport {ApiClient} from '../_api_client.js';\nimport {Downloader} from '../_downloader.js';\nimport {isGeneratedVideo, isVideo, tFileName} from '../_transformers.js';\nimport {\n DownloadFileParameters,\n GeneratedVideo,\n HttpResponse,\n Video,\n} from '../types.js';\n\nexport class NodeDownloader implements Downloader {\n async download(\n params: DownloadFileParameters,\n apiClient: ApiClient,\n ): Promise<void> {\n if (params.downloadPath) {\n const response = await downloadFile(params, apiClient);\n if (response instanceof HttpResponse) {\n const writer = createWriteStream(params.downloadPath);\n const body = Readable.fromWeb(\n response.responseInternal.body as ReadableStream<Uint8Array>,\n );\n body.pipe(writer);\n await finished(writer);\n } else {\n try {\n await writeFile(params.downloadPath, response as string, {\n encoding: 'base64',\n });\n } catch (error) {\n throw new Error(\n `Failed to write file to ${params.downloadPath}: ${error}`,\n );\n }\n }\n }\n }\n}\n\nasync function downloadFile(\n params: DownloadFileParameters,\n apiClient: ApiClient,\n): Promise<HttpResponse | string> {\n const name = tFileName(params.file);\n if (name !== undefined) {\n return await apiClient.request({\n path: `files/${name}:download`,\n httpMethod: 'GET',\n queryParams: {\n 'alt': 'media',\n },\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n });\n } else if (isGeneratedVideo(params.file)) {\n const videoBytes = (params.file as GeneratedVideo).video?.videoBytes;\n if (typeof videoBytes === 'string') {\n return videoBytes;\n } else {\n throw new Error(\n 'Failed to download generated video, Uri or videoBytes not found.',\n );\n }\n } else if (isVideo(params.file)) {\n const videoBytes = (params.file as Video).videoBytes;\n if (typeof videoBytes === 'string') {\n return videoBytes;\n } else {\n throw new Error('Failed to download video, Uri or videoBytes not found.');\n }\n } else {\n throw new Error('Unsupported file type');\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport * as NodeWs from 'ws';\n\nimport {\n WebSocket,\n WebSocketCallbacks,\n WebSocketFactory,\n} from '../_websocket.js';\n\nexport class NodeWebSocketFactory implements WebSocketFactory {\n create(\n url: string,\n headers: Record<string, string>,\n callbacks: WebSocketCallbacks,\n ): WebSocket {\n return new NodeWebSocket(url, headers, callbacks);\n }\n}\n\nexport class NodeWebSocket implements WebSocket {\n private ws?: NodeWs.WebSocket;\n\n constructor(\n private readonly url: string,\n private readonly headers: Record<string, string>,\n private readonly callbacks: WebSocketCallbacks,\n ) {}\n\n connect(): void {\n this.ws = new NodeWs.WebSocket(this.url, {headers: this.headers});\n\n this.ws.onopen = this.callbacks.onopen;\n this.ws.onerror = this.callbacks.onerror;\n this.ws.onclose = this.callbacks.onclose;\n this.ws.onmessage = this.callbacks.onmessage;\n }\n\n send(message: string) {\n if (this.ws === undefined) {\n throw new Error('WebSocket is not connected');\n }\n\n this.ws.send(message);\n }\n\n close() {\n if (this.ws === undefined) {\n throw new Error('WebSocket is not connected');\n }\n\n this.ws.close();\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport * as common from '../_common.js';\nimport * as t from '../_transformers.js';\nimport type * as types from '../types.js';\n\nexport function cancelTuningJobParametersToMldev(\n fromObject: types.CancelTuningJobParameters,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['_url', 'name'], fromName);\n }\n\n return toObject;\n}\n\nexport function cancelTuningJobParametersToVertex(\n fromObject: types.CancelTuningJobParameters,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['_url', 'name'], fromName);\n }\n\n return toObject;\n}\n\nexport function cancelTuningJobResponseFromMldev(\n fromObject: types.CancelTuningJobResponse,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n return toObject;\n}\n\nexport function cancelTuningJobResponseFromVertex(\n fromObject: types.CancelTuningJobResponse,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n return toObject;\n}\n\nexport function createTuningJobConfigToMldev(\n fromObject: types.CreateTuningJobConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['validationDataset']) !== undefined) {\n throw new Error(\n 'validationDataset parameter is not supported in Gemini API.',\n );\n }\n\n const fromTunedModelDisplayName = common.getValueByPath(fromObject, [\n 'tunedModelDisplayName',\n ]);\n if (parentObject !== undefined && fromTunedModelDisplayName != null) {\n common.setValueByPath(\n parentObject,\n ['displayName'],\n fromTunedModelDisplayName,\n );\n }\n\n if (common.getValueByPath(fromObject, ['description']) !== undefined) {\n throw new Error('description parameter is not supported in Gemini API.');\n }\n\n const fromEpochCount = common.getValueByPath(fromObject, ['epochCount']);\n if (parentObject !== undefined && fromEpochCount != null) {\n common.setValueByPath(\n parentObject,\n ['tuningTask', 'hyperparameters', 'epochCount'],\n fromEpochCount,\n );\n }\n\n const fromLearningRateMultiplier = common.getValueByPath(fromObject, [\n 'learningRateMultiplier',\n ]);\n if (fromLearningRateMultiplier != null) {\n common.setValueByPath(\n toObject,\n ['tuningTask', 'hyperparameters', 'learningRateMultiplier'],\n fromLearningRateMultiplier,\n );\n }\n\n if (\n common.getValueByPath(fromObject, ['exportLastCheckpointOnly']) !==\n undefined\n ) {\n throw new Error(\n 'exportLastCheckpointOnly parameter is not supported in Gemini API.',\n );\n }\n\n if (\n common.getValueByPath(fromObject, ['preTunedModelCheckpointId']) !==\n undefined\n ) {\n throw new Error(\n 'preTunedModelCheckpointId parameter is not supported in Gemini API.',\n );\n }\n\n if (common.getValueByPath(fromObject, ['adapterSize']) !== undefined) {\n throw new Error('adapterSize parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['tuningMode']) !== undefined) {\n throw new Error('tuningMode parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['customBaseModel']) !== undefined) {\n throw new Error(\n 'customBaseModel parameter is not supported in Gemini API.',\n );\n }\n\n const fromBatchSize = common.getValueByPath(fromObject, ['batchSize']);\n if (parentObject !== undefined && fromBatchSize != null) {\n common.setValueByPath(\n parentObject,\n ['tuningTask', 'hyperparameters', 'batchSize'],\n fromBatchSize,\n );\n }\n\n const fromLearningRate = common.getValueByPath(fromObject, ['learningRate']);\n if (parentObject !== undefined && fromLearningRate != null) {\n common.setValueByPath(\n parentObject,\n ['tuningTask', 'hyperparameters', 'learningRate'],\n fromLearningRate,\n );\n }\n\n if (common.getValueByPath(fromObject, ['labels']) !== undefined) {\n throw new Error('labels parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['beta']) !== undefined) {\n throw new Error('beta parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['baseTeacherModel']) !== undefined) {\n throw new Error(\n 'baseTeacherModel parameter is not supported in Gemini API.',\n );\n }\n\n if (\n common.getValueByPath(fromObject, ['tunedTeacherModelSource']) !== undefined\n ) {\n throw new Error(\n 'tunedTeacherModelSource parameter is not supported in Gemini API.',\n );\n }\n\n if (\n common.getValueByPath(fromObject, ['sftLossWeightMultiplier']) !== undefined\n ) {\n throw new Error(\n 'sftLossWeightMultiplier parameter is not supported in Gemini API.',\n );\n }\n\n if (common.getValueByPath(fromObject, ['outputUri']) !== undefined) {\n throw new Error('outputUri parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['encryptionSpec']) !== undefined) {\n throw new Error('encryptionSpec parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function createTuningJobConfigToVertex(\n fromObject: types.CreateTuningJobConfig,\n parentObject: Record<string, unknown>,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n let discriminatorValidationDataset = common.getValueByPath(rootObject, [\n 'config',\n 'method',\n ]);\n if (discriminatorValidationDataset === undefined) {\n discriminatorValidationDataset = 'SUPERVISED_FINE_TUNING';\n }\n if (discriminatorValidationDataset === 'SUPERVISED_FINE_TUNING') {\n const fromValidationDataset = common.getValueByPath(fromObject, [\n 'validationDataset',\n ]);\n if (parentObject !== undefined && fromValidationDataset != null) {\n common.setValueByPath(\n parentObject,\n ['supervisedTuningSpec'],\n tuningValidationDatasetToVertex(fromValidationDataset, rootObject),\n );\n }\n } else if (discriminatorValidationDataset === 'PREFERENCE_TUNING') {\n const fromValidationDataset = common.getValueByPath(fromObject, [\n 'validationDataset',\n ]);\n if (parentObject !== undefined && fromValidationDataset != null) {\n common.setValueByPath(\n parentObject,\n ['preferenceOptimizationSpec'],\n tuningValidationDatasetToVertex(fromValidationDataset, rootObject),\n );\n }\n } else if (discriminatorValidationDataset === 'DISTILLATION') {\n const fromValidationDataset = common.getValueByPath(fromObject, [\n 'validationDataset',\n ]);\n if (parentObject !== undefined && fromValidationDataset != null) {\n common.setValueByPath(\n parentObject,\n ['distillationSpec'],\n tuningValidationDatasetToVertex(fromValidationDataset, rootObject),\n );\n }\n }\n\n const fromTunedModelDisplayName = common.getValueByPath(fromObject, [\n 'tunedModelDisplayName',\n ]);\n if (parentObject !== undefined && fromTunedModelDisplayName != null) {\n common.setValueByPath(\n parentObject,\n ['tunedModelDisplayName'],\n fromTunedModelDisplayName,\n );\n }\n\n const fromDescription = common.getValueByPath(fromObject, ['description']);\n if (parentObject !== undefined && fromDescription != null) {\n common.setValueByPath(parentObject, ['description'], fromDescription);\n }\n\n let discriminatorEpochCount = common.getValueByPath(rootObject, [\n 'config',\n 'method',\n ]);\n if (discriminatorEpochCount === undefined) {\n discriminatorEpochCount = 'SUPERVISED_FINE_TUNING';\n }\n if (discriminatorEpochCount === 'SUPERVISED_FINE_TUNING') {\n const fromEpochCount = common.getValueByPath(fromObject, ['epochCount']);\n if (parentObject !== undefined && fromEpochCount != null) {\n common.setValueByPath(\n parentObject,\n ['supervisedTuningSpec', 'hyperParameters', 'epochCount'],\n fromEpochCount,\n );\n }\n } else if (discriminatorEpochCount === 'PREFERENCE_TUNING') {\n const fromEpochCount = common.getValueByPath(fromObject, ['epochCount']);\n if (parentObject !== undefined && fromEpochCount != null) {\n common.setValueByPath(\n parentObject,\n ['preferenceOptimizationSpec', 'hyperParameters', 'epochCount'],\n fromEpochCount,\n );\n }\n } else if (discriminatorEpochCount === 'DISTILLATION') {\n const fromEpochCount = common.getValueByPath(fromObject, ['epochCount']);\n if (parentObject !== undefined && fromEpochCount != null) {\n common.setValueByPath(\n parentObject,\n ['distillationSpec', 'hyperParameters', 'epochCount'],\n fromEpochCount,\n );\n }\n }\n\n let discriminatorLearningRateMultiplier = common.getValueByPath(rootObject, [\n 'config',\n 'method',\n ]);\n if (discriminatorLearningRateMultiplier === undefined) {\n discriminatorLearningRateMultiplier = 'SUPERVISED_FINE_TUNING';\n }\n if (discriminatorLearningRateMultiplier === 'SUPERVISED_FINE_TUNING') {\n const fromLearningRateMultiplier = common.getValueByPath(fromObject, [\n 'learningRateMultiplier',\n ]);\n if (parentObject !== undefined && fromLearningRateMultiplier != null) {\n common.setValueByPath(\n parentObject,\n ['supervisedTuningSpec', 'hyperParameters', 'learningRateMultiplier'],\n fromLearningRateMultiplier,\n );\n }\n } else if (discriminatorLearningRateMultiplier === 'PREFERENCE_TUNING') {\n const fromLearningRateMultiplier = common.getValueByPath(fromObject, [\n 'learningRateMultiplier',\n ]);\n if (parentObject !== undefined && fromLearningRateMultiplier != null) {\n common.setValueByPath(\n parentObject,\n [\n 'preferenceOptimizationSpec',\n 'hyperParameters',\n 'learningRateMultiplier',\n ],\n fromLearningRateMultiplier,\n );\n }\n } else if (discriminatorLearningRateMultiplier === 'DISTILLATION') {\n const fromLearningRateMultiplier = common.getValueByPath(fromObject, [\n 'learningRateMultiplier',\n ]);\n if (parentObject !== undefined && fromLearningRateMultiplier != null) {\n common.setValueByPath(\n parentObject,\n ['distillationSpec', 'hyperParameters', 'learningRateMultiplier'],\n fromLearningRateMultiplier,\n );\n }\n }\n\n let discriminatorExportLastCheckpointOnly = common.getValueByPath(\n rootObject,\n ['config', 'method'],\n );\n if (discriminatorExportLastCheckpointOnly === undefined) {\n discriminatorExportLastCheckpointOnly = 'SUPERVISED_FINE_TUNING';\n }\n if (discriminatorExportLastCheckpointOnly === 'SUPERVISED_FINE_TUNING') {\n const fromExportLastCheckpointOnly = common.getValueByPath(fromObject, [\n 'exportLastCheckpointOnly',\n ]);\n if (parentObject !== undefined && fromExportLastCheckpointOnly != null) {\n common.setValueByPath(\n parentObject,\n ['supervisedTuningSpec', 'exportLastCheckpointOnly'],\n fromExportLastCheckpointOnly,\n );\n }\n } else if (discriminatorExportLastCheckpointOnly === 'PREFERENCE_TUNING') {\n const fromExportLastCheckpointOnly = common.getValueByPath(fromObject, [\n 'exportLastCheckpointOnly',\n ]);\n if (parentObject !== undefined && fromExportLastCheckpointOnly != null) {\n common.setValueByPath(\n parentObject,\n ['preferenceOptimizationSpec', 'exportLastCheckpointOnly'],\n fromExportLastCheckpointOnly,\n );\n }\n } else if (discriminatorExportLastCheckpointOnly === 'DISTILLATION') {\n const fromExportLastCheckpointOnly = common.getValueByPath(fromObject, [\n 'exportLastCheckpointOnly',\n ]);\n if (parentObject !== undefined && fromExportLastCheckpointOnly != null) {\n common.setValueByPath(\n parentObject,\n ['distillationSpec', 'exportLastCheckpointOnly'],\n fromExportLastCheckpointOnly,\n );\n }\n }\n\n let discriminatorAdapterSize = common.getValueByPath(rootObject, [\n 'config',\n 'method',\n ]);\n if (discriminatorAdapterSize === undefined) {\n discriminatorAdapterSize = 'SUPERVISED_FINE_TUNING';\n }\n if (discriminatorAdapterSize === 'SUPERVISED_FINE_TUNING') {\n const fromAdapterSize = common.getValueByPath(fromObject, ['adapterSize']);\n if (parentObject !== undefined && fromAdapterSize != null) {\n common.setValueByPath(\n parentObject,\n ['supervisedTuningSpec', 'hyperParameters', 'adapterSize'],\n fromAdapterSize,\n );\n }\n } else if (discriminatorAdapterSize === 'PREFERENCE_TUNING') {\n const fromAdapterSize = common.getValueByPath(fromObject, ['adapterSize']);\n if (parentObject !== undefined && fromAdapterSize != null) {\n common.setValueByPath(\n parentObject,\n ['preferenceOptimizationSpec', 'hyperParameters', 'adapterSize'],\n fromAdapterSize,\n );\n }\n } else if (discriminatorAdapterSize === 'DISTILLATION') {\n const fromAdapterSize = common.getValueByPath(fromObject, ['adapterSize']);\n if (parentObject !== undefined && fromAdapterSize != null) {\n common.setValueByPath(\n parentObject,\n ['distillationSpec', 'hyperParameters', 'adapterSize'],\n fromAdapterSize,\n );\n }\n }\n\n let discriminatorTuningMode = common.getValueByPath(rootObject, [\n 'config',\n 'method',\n ]);\n if (discriminatorTuningMode === undefined) {\n discriminatorTuningMode = 'SUPERVISED_FINE_TUNING';\n }\n if (discriminatorTuningMode === 'SUPERVISED_FINE_TUNING') {\n const fromTuningMode = common.getValueByPath(fromObject, ['tuningMode']);\n if (parentObject !== undefined && fromTuningMode != null) {\n common.setValueByPath(\n parentObject,\n ['supervisedTuningSpec', 'tuningMode'],\n fromTuningMode,\n );\n }\n }\n\n const fromCustomBaseModel = common.getValueByPath(fromObject, [\n 'customBaseModel',\n ]);\n if (parentObject !== undefined && fromCustomBaseModel != null) {\n common.setValueByPath(\n parentObject,\n ['customBaseModel'],\n fromCustomBaseModel,\n );\n }\n\n let discriminatorBatchSize = common.getValueByPath(rootObject, [\n 'config',\n 'method',\n ]);\n if (discriminatorBatchSize === undefined) {\n discriminatorBatchSize = 'SUPERVISED_FINE_TUNING';\n }\n if (discriminatorBatchSize === 'SUPERVISED_FINE_TUNING') {\n const fromBatchSize = common.getValueByPath(fromObject, ['batchSize']);\n if (parentObject !== undefined && fromBatchSize != null) {\n common.setValueByPath(\n parentObject,\n ['supervisedTuningSpec', 'hyperParameters', 'batchSize'],\n fromBatchSize,\n );\n }\n }\n\n let discriminatorLearningRate = common.getValueByPath(rootObject, [\n 'config',\n 'method',\n ]);\n if (discriminatorLearningRate === undefined) {\n discriminatorLearningRate = 'SUPERVISED_FINE_TUNING';\n }\n if (discriminatorLearningRate === 'SUPERVISED_FINE_TUNING') {\n const fromLearningRate = common.getValueByPath(fromObject, [\n 'learningRate',\n ]);\n if (parentObject !== undefined && fromLearningRate != null) {\n common.setValueByPath(\n parentObject,\n ['supervisedTuningSpec', 'hyperParameters', 'learningRate'],\n fromLearningRate,\n );\n }\n }\n\n const fromLabels = common.getValueByPath(fromObject, ['labels']);\n if (parentObject !== undefined && fromLabels != null) {\n common.setValueByPath(parentObject, ['labels'], fromLabels);\n }\n\n const fromBeta = common.getValueByPath(fromObject, ['beta']);\n if (parentObject !== undefined && fromBeta != null) {\n common.setValueByPath(\n parentObject,\n ['preferenceOptimizationSpec', 'hyperParameters', 'beta'],\n fromBeta,\n );\n }\n\n const fromBaseTeacherModel = common.getValueByPath(fromObject, [\n 'baseTeacherModel',\n ]);\n if (parentObject !== undefined && fromBaseTeacherModel != null) {\n common.setValueByPath(\n parentObject,\n ['distillationSpec', 'baseTeacherModel'],\n fromBaseTeacherModel,\n );\n }\n\n const fromTunedTeacherModelSource = common.getValueByPath(fromObject, [\n 'tunedTeacherModelSource',\n ]);\n if (parentObject !== undefined && fromTunedTeacherModelSource != null) {\n common.setValueByPath(\n parentObject,\n ['distillationSpec', 'tunedTeacherModelSource'],\n fromTunedTeacherModelSource,\n );\n }\n\n const fromSftLossWeightMultiplier = common.getValueByPath(fromObject, [\n 'sftLossWeightMultiplier',\n ]);\n if (parentObject !== undefined && fromSftLossWeightMultiplier != null) {\n common.setValueByPath(\n parentObject,\n ['distillationSpec', 'hyperParameters', 'sftLossWeightMultiplier'],\n fromSftLossWeightMultiplier,\n );\n }\n\n const fromOutputUri = common.getValueByPath(fromObject, ['outputUri']);\n if (parentObject !== undefined && fromOutputUri != null) {\n common.setValueByPath(parentObject, ['outputUri'], fromOutputUri);\n }\n\n const fromEncryptionSpec = common.getValueByPath(fromObject, [\n 'encryptionSpec',\n ]);\n if (parentObject !== undefined && fromEncryptionSpec != null) {\n common.setValueByPath(parentObject, ['encryptionSpec'], fromEncryptionSpec);\n }\n\n return toObject;\n}\n\nexport function createTuningJobParametersPrivateToMldev(\n fromObject: types.CreateTuningJobParametersPrivate,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromBaseModel = common.getValueByPath(fromObject, ['baseModel']);\n if (fromBaseModel != null) {\n common.setValueByPath(toObject, ['baseModel'], fromBaseModel);\n }\n\n const fromPreTunedModel = common.getValueByPath(fromObject, [\n 'preTunedModel',\n ]);\n if (fromPreTunedModel != null) {\n common.setValueByPath(toObject, ['preTunedModel'], fromPreTunedModel);\n }\n\n const fromTrainingDataset = common.getValueByPath(fromObject, [\n 'trainingDataset',\n ]);\n if (fromTrainingDataset != null) {\n tuningDatasetToMldev(fromTrainingDataset, rootObject);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n createTuningJobConfigToMldev(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function createTuningJobParametersPrivateToVertex(\n fromObject: types.CreateTuningJobParametersPrivate,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromBaseModel = common.getValueByPath(fromObject, ['baseModel']);\n if (fromBaseModel != null) {\n common.setValueByPath(toObject, ['baseModel'], fromBaseModel);\n }\n\n const fromPreTunedModel = common.getValueByPath(fromObject, [\n 'preTunedModel',\n ]);\n if (fromPreTunedModel != null) {\n common.setValueByPath(toObject, ['preTunedModel'], fromPreTunedModel);\n }\n\n const fromTrainingDataset = common.getValueByPath(fromObject, [\n 'trainingDataset',\n ]);\n if (fromTrainingDataset != null) {\n tuningDatasetToVertex(fromTrainingDataset, toObject, rootObject);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n createTuningJobConfigToVertex(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function getTuningJobParametersToMldev(\n fromObject: types.GetTuningJobParameters,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['_url', 'name'], fromName);\n }\n\n return toObject;\n}\n\nexport function getTuningJobParametersToVertex(\n fromObject: types.GetTuningJobParameters,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['_url', 'name'], fromName);\n }\n\n return toObject;\n}\n\nexport function listTuningJobsConfigToMldev(\n fromObject: types.ListTuningJobsConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPageSize = common.getValueByPath(fromObject, ['pageSize']);\n if (parentObject !== undefined && fromPageSize != null) {\n common.setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize);\n }\n\n const fromPageToken = common.getValueByPath(fromObject, ['pageToken']);\n if (parentObject !== undefined && fromPageToken != null) {\n common.setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken);\n }\n\n const fromFilter = common.getValueByPath(fromObject, ['filter']);\n if (parentObject !== undefined && fromFilter != null) {\n common.setValueByPath(parentObject, ['_query', 'filter'], fromFilter);\n }\n\n return toObject;\n}\n\nexport function listTuningJobsConfigToVertex(\n fromObject: types.ListTuningJobsConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPageSize = common.getValueByPath(fromObject, ['pageSize']);\n if (parentObject !== undefined && fromPageSize != null) {\n common.setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize);\n }\n\n const fromPageToken = common.getValueByPath(fromObject, ['pageToken']);\n if (parentObject !== undefined && fromPageToken != null) {\n common.setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken);\n }\n\n const fromFilter = common.getValueByPath(fromObject, ['filter']);\n if (parentObject !== undefined && fromFilter != null) {\n common.setValueByPath(parentObject, ['_query', 'filter'], fromFilter);\n }\n\n return toObject;\n}\n\nexport function listTuningJobsParametersToMldev(\n fromObject: types.ListTuningJobsParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n listTuningJobsConfigToMldev(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function listTuningJobsParametersToVertex(\n fromObject: types.ListTuningJobsParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n listTuningJobsConfigToVertex(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function listTuningJobsResponseFromMldev(\n fromObject: types.ListTuningJobsResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromNextPageToken = common.getValueByPath(fromObject, [\n 'nextPageToken',\n ]);\n if (fromNextPageToken != null) {\n common.setValueByPath(toObject, ['nextPageToken'], fromNextPageToken);\n }\n\n const fromTuningJobs = common.getValueByPath(fromObject, ['tunedModels']);\n if (fromTuningJobs != null) {\n let transformedList = fromTuningJobs;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return tuningJobFromMldev(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['tuningJobs'], transformedList);\n }\n\n return toObject;\n}\n\nexport function listTuningJobsResponseFromVertex(\n fromObject: types.ListTuningJobsResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromNextPageToken = common.getValueByPath(fromObject, [\n 'nextPageToken',\n ]);\n if (fromNextPageToken != null) {\n common.setValueByPath(toObject, ['nextPageToken'], fromNextPageToken);\n }\n\n const fromTuningJobs = common.getValueByPath(fromObject, ['tuningJobs']);\n if (fromTuningJobs != null) {\n let transformedList = fromTuningJobs;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return tuningJobFromVertex(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['tuningJobs'], transformedList);\n }\n\n return toObject;\n}\n\nexport function tunedModelFromMldev(\n fromObject: types.TunedModel,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['name']);\n if (fromModel != null) {\n common.setValueByPath(toObject, ['model'], fromModel);\n }\n\n const fromEndpoint = common.getValueByPath(fromObject, ['name']);\n if (fromEndpoint != null) {\n common.setValueByPath(toObject, ['endpoint'], fromEndpoint);\n }\n\n return toObject;\n}\n\nexport function tuningDatasetToMldev(\n fromObject: types.TuningDataset,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['gcsUri']) !== undefined) {\n throw new Error('gcsUri parameter is not supported in Gemini API.');\n }\n\n if (\n common.getValueByPath(fromObject, ['vertexDatasetResource']) !== undefined\n ) {\n throw new Error(\n 'vertexDatasetResource parameter is not supported in Gemini API.',\n );\n }\n\n const fromExamples = common.getValueByPath(fromObject, ['examples']);\n if (fromExamples != null) {\n let transformedList = fromExamples;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['examples', 'examples'], transformedList);\n }\n\n return toObject;\n}\n\nexport function tuningDatasetToVertex(\n fromObject: types.TuningDataset,\n parentObject: Record<string, unknown>,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n let discriminatorGcsUri = common.getValueByPath(rootObject, [\n 'config',\n 'method',\n ]);\n if (discriminatorGcsUri === undefined) {\n discriminatorGcsUri = 'SUPERVISED_FINE_TUNING';\n }\n if (discriminatorGcsUri === 'SUPERVISED_FINE_TUNING') {\n const fromGcsUri = common.getValueByPath(fromObject, ['gcsUri']);\n if (parentObject !== undefined && fromGcsUri != null) {\n common.setValueByPath(\n parentObject,\n ['supervisedTuningSpec', 'trainingDatasetUri'],\n fromGcsUri,\n );\n }\n } else if (discriminatorGcsUri === 'PREFERENCE_TUNING') {\n const fromGcsUri = common.getValueByPath(fromObject, ['gcsUri']);\n if (parentObject !== undefined && fromGcsUri != null) {\n common.setValueByPath(\n parentObject,\n ['preferenceOptimizationSpec', 'trainingDatasetUri'],\n fromGcsUri,\n );\n }\n } else if (discriminatorGcsUri === 'DISTILLATION') {\n const fromGcsUri = common.getValueByPath(fromObject, ['gcsUri']);\n if (parentObject !== undefined && fromGcsUri != null) {\n common.setValueByPath(\n parentObject,\n ['distillationSpec', 'promptDatasetUri'],\n fromGcsUri,\n );\n }\n }\n\n let discriminatorVertexDatasetResource = common.getValueByPath(rootObject, [\n 'config',\n 'method',\n ]);\n if (discriminatorVertexDatasetResource === undefined) {\n discriminatorVertexDatasetResource = 'SUPERVISED_FINE_TUNING';\n }\n if (discriminatorVertexDatasetResource === 'SUPERVISED_FINE_TUNING') {\n const fromVertexDatasetResource = common.getValueByPath(fromObject, [\n 'vertexDatasetResource',\n ]);\n if (parentObject !== undefined && fromVertexDatasetResource != null) {\n common.setValueByPath(\n parentObject,\n ['supervisedTuningSpec', 'trainingDatasetUri'],\n fromVertexDatasetResource,\n );\n }\n } else if (discriminatorVertexDatasetResource === 'PREFERENCE_TUNING') {\n const fromVertexDatasetResource = common.getValueByPath(fromObject, [\n 'vertexDatasetResource',\n ]);\n if (parentObject !== undefined && fromVertexDatasetResource != null) {\n common.setValueByPath(\n parentObject,\n ['preferenceOptimizationSpec', 'trainingDatasetUri'],\n fromVertexDatasetResource,\n );\n }\n } else if (discriminatorVertexDatasetResource === 'DISTILLATION') {\n const fromVertexDatasetResource = common.getValueByPath(fromObject, [\n 'vertexDatasetResource',\n ]);\n if (parentObject !== undefined && fromVertexDatasetResource != null) {\n common.setValueByPath(\n parentObject,\n ['distillationSpec', 'promptDatasetUri'],\n fromVertexDatasetResource,\n );\n }\n }\n if (common.getValueByPath(fromObject, ['examples']) !== undefined) {\n throw new Error('examples parameter is not supported in Vertex AI.');\n }\n\n return toObject;\n}\n\nexport function tuningJobFromMldev(\n fromObject: types.TuningJob,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromState = common.getValueByPath(fromObject, ['state']);\n if (fromState != null) {\n common.setValueByPath(toObject, ['state'], t.tTuningJobStatus(fromState));\n }\n\n const fromCreateTime = common.getValueByPath(fromObject, ['createTime']);\n if (fromCreateTime != null) {\n common.setValueByPath(toObject, ['createTime'], fromCreateTime);\n }\n\n const fromStartTime = common.getValueByPath(fromObject, [\n 'tuningTask',\n 'startTime',\n ]);\n if (fromStartTime != null) {\n common.setValueByPath(toObject, ['startTime'], fromStartTime);\n }\n\n const fromEndTime = common.getValueByPath(fromObject, [\n 'tuningTask',\n 'completeTime',\n ]);\n if (fromEndTime != null) {\n common.setValueByPath(toObject, ['endTime'], fromEndTime);\n }\n\n const fromUpdateTime = common.getValueByPath(fromObject, ['updateTime']);\n if (fromUpdateTime != null) {\n common.setValueByPath(toObject, ['updateTime'], fromUpdateTime);\n }\n\n const fromDescription = common.getValueByPath(fromObject, ['description']);\n if (fromDescription != null) {\n common.setValueByPath(toObject, ['description'], fromDescription);\n }\n\n const fromBaseModel = common.getValueByPath(fromObject, ['baseModel']);\n if (fromBaseModel != null) {\n common.setValueByPath(toObject, ['baseModel'], fromBaseModel);\n }\n\n const fromTunedModel = common.getValueByPath(fromObject, ['_self']);\n if (fromTunedModel != null) {\n common.setValueByPath(\n toObject,\n ['tunedModel'],\n tunedModelFromMldev(fromTunedModel, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function tuningJobFromVertex(\n fromObject: types.TuningJob,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromState = common.getValueByPath(fromObject, ['state']);\n if (fromState != null) {\n common.setValueByPath(toObject, ['state'], t.tTuningJobStatus(fromState));\n }\n\n const fromCreateTime = common.getValueByPath(fromObject, ['createTime']);\n if (fromCreateTime != null) {\n common.setValueByPath(toObject, ['createTime'], fromCreateTime);\n }\n\n const fromStartTime = common.getValueByPath(fromObject, ['startTime']);\n if (fromStartTime != null) {\n common.setValueByPath(toObject, ['startTime'], fromStartTime);\n }\n\n const fromEndTime = common.getValueByPath(fromObject, ['endTime']);\n if (fromEndTime != null) {\n common.setValueByPath(toObject, ['endTime'], fromEndTime);\n }\n\n const fromUpdateTime = common.getValueByPath(fromObject, ['updateTime']);\n if (fromUpdateTime != null) {\n common.setValueByPath(toObject, ['updateTime'], fromUpdateTime);\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n const fromDescription = common.getValueByPath(fromObject, ['description']);\n if (fromDescription != null) {\n common.setValueByPath(toObject, ['description'], fromDescription);\n }\n\n const fromBaseModel = common.getValueByPath(fromObject, ['baseModel']);\n if (fromBaseModel != null) {\n common.setValueByPath(toObject, ['baseModel'], fromBaseModel);\n }\n\n const fromTunedModel = common.getValueByPath(fromObject, ['tunedModel']);\n if (fromTunedModel != null) {\n common.setValueByPath(toObject, ['tunedModel'], fromTunedModel);\n }\n\n const fromPreTunedModel = common.getValueByPath(fromObject, [\n 'preTunedModel',\n ]);\n if (fromPreTunedModel != null) {\n common.setValueByPath(toObject, ['preTunedModel'], fromPreTunedModel);\n }\n\n const fromSupervisedTuningSpec = common.getValueByPath(fromObject, [\n 'supervisedTuningSpec',\n ]);\n if (fromSupervisedTuningSpec != null) {\n common.setValueByPath(\n toObject,\n ['supervisedTuningSpec'],\n fromSupervisedTuningSpec,\n );\n }\n\n const fromPreferenceOptimizationSpec = common.getValueByPath(fromObject, [\n 'preferenceOptimizationSpec',\n ]);\n if (fromPreferenceOptimizationSpec != null) {\n common.setValueByPath(\n toObject,\n ['preferenceOptimizationSpec'],\n fromPreferenceOptimizationSpec,\n );\n }\n\n const fromDistillationSpec = common.getValueByPath(fromObject, [\n 'distillationSpec',\n ]);\n if (fromDistillationSpec != null) {\n common.setValueByPath(toObject, ['distillationSpec'], fromDistillationSpec);\n }\n\n const fromTuningDataStats = common.getValueByPath(fromObject, [\n 'tuningDataStats',\n ]);\n if (fromTuningDataStats != null) {\n common.setValueByPath(toObject, ['tuningDataStats'], fromTuningDataStats);\n }\n\n const fromEncryptionSpec = common.getValueByPath(fromObject, [\n 'encryptionSpec',\n ]);\n if (fromEncryptionSpec != null) {\n common.setValueByPath(toObject, ['encryptionSpec'], fromEncryptionSpec);\n }\n\n const fromPartnerModelTuningSpec = common.getValueByPath(fromObject, [\n 'partnerModelTuningSpec',\n ]);\n if (fromPartnerModelTuningSpec != null) {\n common.setValueByPath(\n toObject,\n ['partnerModelTuningSpec'],\n fromPartnerModelTuningSpec,\n );\n }\n\n const fromCustomBaseModel = common.getValueByPath(fromObject, [\n 'customBaseModel',\n ]);\n if (fromCustomBaseModel != null) {\n common.setValueByPath(toObject, ['customBaseModel'], fromCustomBaseModel);\n }\n\n const fromExperiment = common.getValueByPath(fromObject, ['experiment']);\n if (fromExperiment != null) {\n common.setValueByPath(toObject, ['experiment'], fromExperiment);\n }\n\n const fromLabels = common.getValueByPath(fromObject, ['labels']);\n if (fromLabels != null) {\n common.setValueByPath(toObject, ['labels'], fromLabels);\n }\n\n const fromOutputUri = common.getValueByPath(fromObject, ['outputUri']);\n if (fromOutputUri != null) {\n common.setValueByPath(toObject, ['outputUri'], fromOutputUri);\n }\n\n const fromPipelineJob = common.getValueByPath(fromObject, ['pipelineJob']);\n if (fromPipelineJob != null) {\n common.setValueByPath(toObject, ['pipelineJob'], fromPipelineJob);\n }\n\n const fromServiceAccount = common.getValueByPath(fromObject, [\n 'serviceAccount',\n ]);\n if (fromServiceAccount != null) {\n common.setValueByPath(toObject, ['serviceAccount'], fromServiceAccount);\n }\n\n const fromTunedModelDisplayName = common.getValueByPath(fromObject, [\n 'tunedModelDisplayName',\n ]);\n if (fromTunedModelDisplayName != null) {\n common.setValueByPath(\n toObject,\n ['tunedModelDisplayName'],\n fromTunedModelDisplayName,\n );\n }\n\n const fromVeoTuningSpec = common.getValueByPath(fromObject, [\n 'veoTuningSpec',\n ]);\n if (fromVeoTuningSpec != null) {\n common.setValueByPath(toObject, ['veoTuningSpec'], fromVeoTuningSpec);\n }\n\n return toObject;\n}\n\nexport function tuningOperationFromMldev(\n fromObject: types.TuningOperation,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromMetadata = common.getValueByPath(fromObject, ['metadata']);\n if (fromMetadata != null) {\n common.setValueByPath(toObject, ['metadata'], fromMetadata);\n }\n\n const fromDone = common.getValueByPath(fromObject, ['done']);\n if (fromDone != null) {\n common.setValueByPath(toObject, ['done'], fromDone);\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n return toObject;\n}\n\nexport function tuningValidationDatasetToVertex(\n fromObject: types.TuningValidationDataset,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromGcsUri = common.getValueByPath(fromObject, ['gcsUri']);\n if (fromGcsUri != null) {\n common.setValueByPath(toObject, ['validationDatasetUri'], fromGcsUri);\n }\n\n const fromVertexDatasetResource = common.getValueByPath(fromObject, [\n 'vertexDatasetResource',\n ]);\n if (fromVertexDatasetResource != null) {\n common.setValueByPath(\n toObject,\n ['validationDatasetUri'],\n fromVertexDatasetResource,\n );\n }\n\n return toObject;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport {ApiClient} from './_api_client.js';\nimport * as common from './_common.js';\nimport {BaseModule} from './_common.js';\nimport * as converters from './converters/_tunings_converters.js';\nimport {PagedItem, Pager} from './pagers.js';\nimport * as types from './types.js';\n\nexport class Tunings extends BaseModule {\n constructor(private readonly apiClient: ApiClient) {\n super();\n }\n\n /**\n * Lists tuning jobs.\n *\n * @param params - The parameters for the list request.\n * @return - A pager of tuning jobs.\n *\n * @example\n * ```ts\n * const tuningJobs = await ai.tunings.list({config: {'pageSize': 2}});\n * for await (const tuningJob of tuningJobs) {\n * console.log(tuningJob);\n * }\n * ```\n */\n list = async (\n params: types.ListTuningJobsParameters = {},\n ): Promise<Pager<types.TuningJob>> => {\n return new Pager<types.TuningJob>(\n PagedItem.PAGED_ITEM_TUNING_JOBS,\n (x: types.ListTuningJobsParameters) => this.listInternal(x),\n await this.listInternal(params),\n params,\n );\n };\n\n /**\n * Gets a TuningJob.\n *\n * @param name - The resource name of the tuning job.\n * @return - A TuningJob object.\n *\n * @experimental - The SDK's tuning implementation is experimental, and may\n * change in future versions.\n */\n get = async (\n params: types.GetTuningJobParameters,\n ): Promise<types.TuningJob> => {\n return await this.getInternal(params);\n };\n\n /**\n * Creates a supervised fine-tuning job.\n *\n * @param params - The parameters for the tuning job.\n * @return - A TuningJob operation.\n *\n * @experimental - The SDK's tuning implementation is experimental, and may\n * change in future versions.\n */\n tune = async (\n params: types.CreateTuningJobParameters,\n ): Promise<types.TuningJob> => {\n if (this.apiClient.isVertexAI()) {\n if (params.baseModel.startsWith('projects/')) {\n const preTunedModel: types.PreTunedModel = {\n tunedModelName: params.baseModel,\n };\n if (params.config?.preTunedModelCheckpointId) {\n preTunedModel.checkpointId = params.config.preTunedModelCheckpointId;\n }\n const paramsPrivate: types.CreateTuningJobParametersPrivate = {\n ...params,\n preTunedModel: preTunedModel,\n };\n paramsPrivate.baseModel = undefined;\n return await this.tuneInternal(paramsPrivate);\n } else {\n const paramsPrivate: types.CreateTuningJobParametersPrivate = {\n ...params,\n };\n return await this.tuneInternal(paramsPrivate);\n }\n } else {\n const paramsPrivate: types.CreateTuningJobParametersPrivate = {\n ...params,\n };\n const operation = await this.tuneMldevInternal(paramsPrivate);\n let tunedModelName = '';\n if (\n operation['metadata'] !== undefined &&\n operation['metadata']['tunedModel'] !== undefined\n ) {\n tunedModelName = operation['metadata']['tunedModel'] as string;\n } else if (\n operation['name'] !== undefined &&\n operation['name'].includes('/operations/')\n ) {\n tunedModelName = operation['name'].split('/operations/')[0];\n }\n const tuningJob: types.TuningJob = {\n name: tunedModelName,\n state: types.JobState.JOB_STATE_QUEUED,\n };\n\n return tuningJob;\n }\n };\n\n private async getInternal(\n params: types.GetTuningJobParameters,\n ): Promise<types.TuningJob> {\n let response: Promise<types.TuningJob>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.getTuningJobParametersToVertex(params, params);\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.TuningJob;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.TuningJob>;\n\n return response.then((apiResponse) => {\n const resp = converters.tuningJobFromVertex(apiResponse, params);\n\n return resp as types.TuningJob;\n });\n } else {\n const body = converters.getTuningJobParametersToMldev(params, params);\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.TuningJob;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.TuningJob>;\n\n return response.then((apiResponse) => {\n const resp = converters.tuningJobFromMldev(apiResponse, params);\n\n return resp as types.TuningJob;\n });\n }\n }\n\n private async listInternal(\n params: types.ListTuningJobsParameters,\n ): Promise<types.ListTuningJobsResponse> {\n let response: Promise<types.ListTuningJobsResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.listTuningJobsParametersToVertex(params, params);\n path = common.formatMap(\n 'tuningJobs',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.ListTuningJobsResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.ListTuningJobsResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.listTuningJobsResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.ListTuningJobsResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n const body = converters.listTuningJobsParametersToMldev(params, params);\n path = common.formatMap(\n 'tunedModels',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.ListTuningJobsResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.ListTuningJobsResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.listTuningJobsResponseFromMldev(\n apiResponse,\n params,\n );\n const typedResp = new types.ListTuningJobsResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n /**\n * Cancels a tuning job.\n *\n * @param params - The parameters for the cancel request.\n * @return The empty response returned by the API.\n *\n * @example\n * ```ts\n * await ai.tunings.cancel({name: '...'}); // The server-generated resource name.\n * ```\n */\n async cancel(\n params: types.CancelTuningJobParameters,\n ): Promise<types.CancelTuningJobResponse> {\n let response: Promise<types.CancelTuningJobResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.cancelTuningJobParametersToVertex(params, params);\n path = common.formatMap(\n '{name}:cancel',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.CancelTuningJobResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.CancelTuningJobResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.cancelTuningJobResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.CancelTuningJobResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n const body = converters.cancelTuningJobParametersToMldev(params, params);\n path = common.formatMap(\n '{name}:cancel',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.CancelTuningJobResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.CancelTuningJobResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.cancelTuningJobResponseFromMldev(\n apiResponse,\n params,\n );\n const typedResp = new types.CancelTuningJobResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n private async tuneInternal(\n params: types.CreateTuningJobParametersPrivate,\n ): Promise<types.TuningJob> {\n let response: Promise<types.TuningJob>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.createTuningJobParametersPrivateToVertex(\n params,\n params,\n );\n path = common.formatMap(\n 'tuningJobs',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.TuningJob;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.TuningJob>;\n\n return response.then((apiResponse) => {\n const resp = converters.tuningJobFromVertex(apiResponse, params);\n\n return resp as types.TuningJob;\n });\n } else {\n throw new Error('This method is only supported by the Vertex AI.');\n }\n }\n\n private async tuneMldevInternal(\n params: types.CreateTuningJobParametersPrivate,\n ): Promise<types.TuningOperation> {\n let response: Promise<types.TuningOperation>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.createTuningJobParametersPrivateToMldev(\n params,\n params,\n );\n path = common.formatMap(\n 'tunedModels',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.TuningOperation;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.TuningOperation>;\n\n return response.then((apiResponse) => {\n const resp = converters.tuningOperationFromMldev(apiResponse, params);\n\n return resp as types.TuningOperation;\n });\n }\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {ApiClient} from '../_api_client.js';\nimport {FileStat, Uploader} from '../_uploader.js';\nimport * as _converters from '../converters/_operations_converters.js';\nimport {\n File,\n HttpResponse,\n UploadToFileSearchStoreOperation,\n} from '../types.js';\nimport {crossError} from './_cross_error.js';\n\nexport const MAX_CHUNK_SIZE = 1024 * 1024 * 8; // bytes\nexport const MAX_RETRY_COUNT = 3;\nexport const INITIAL_RETRY_DELAY_MS = 1000;\nexport const DELAY_MULTIPLIER = 2;\nexport const X_GOOG_UPLOAD_STATUS_HEADER_FIELD = 'x-goog-upload-status';\n\nexport class CrossUploader implements Uploader {\n async upload(\n file: string | Blob,\n uploadUrl: string,\n apiClient: ApiClient,\n ): Promise<File> {\n if (typeof file === 'string') {\n throw crossError();\n } else {\n return uploadBlob(file, uploadUrl, apiClient);\n }\n }\n\n async uploadToFileSearchStore(\n file: string | Blob,\n uploadUrl: string,\n apiClient: ApiClient,\n ): Promise<UploadToFileSearchStoreOperation> {\n if (typeof file === 'string') {\n throw crossError();\n } else {\n return uploadBlobToFileSearchStore(file, uploadUrl, apiClient);\n }\n }\n\n async stat(file: string | Blob): Promise<FileStat> {\n if (typeof file === 'string') {\n throw crossError();\n } else {\n return getBlobStat(file);\n }\n }\n}\n\nexport async function uploadBlob(\n file: Blob,\n uploadUrl: string,\n apiClient: ApiClient,\n): Promise<File> {\n const response = await uploadBlobInternal(file, uploadUrl, apiClient);\n const responseJson = (await response?.json()) as Record<\n string,\n File | unknown\n >;\n if (response?.headers?.[X_GOOG_UPLOAD_STATUS_HEADER_FIELD] !== 'final') {\n throw new Error('Failed to upload file: Upload status is not finalized.');\n }\n return responseJson['file'] as File;\n}\n\nexport async function uploadBlobToFileSearchStore(\n file: Blob,\n uploadUrl: string,\n apiClient: ApiClient,\n): Promise<UploadToFileSearchStoreOperation> {\n const response = await uploadBlobInternal(file, uploadUrl, apiClient);\n const responseJson =\n (await response?.json()) as UploadToFileSearchStoreOperation;\n if (response?.headers?.[X_GOOG_UPLOAD_STATUS_HEADER_FIELD] !== 'final') {\n throw new Error('Failed to upload file: Upload status is not finalized.');\n }\n const resp =\n _converters.uploadToFileSearchStoreOperationFromMldev(responseJson);\n const typedResp = new UploadToFileSearchStoreOperation();\n Object.assign(typedResp, resp);\n return typedResp;\n}\n\nasync function uploadBlobInternal(\n file: Blob,\n uploadUrl: string,\n apiClient: ApiClient,\n): Promise<HttpResponse> {\n let fileSize = 0;\n let offset = 0;\n let response: HttpResponse = new HttpResponse(new Response());\n let uploadCommand = 'upload';\n fileSize = file.size;\n while (offset < fileSize) {\n const chunkSize = Math.min(MAX_CHUNK_SIZE, fileSize - offset);\n const chunk = file.slice(offset, offset + chunkSize);\n if (offset + chunkSize >= fileSize) {\n uploadCommand += ', finalize';\n }\n let retryCount = 0;\n let currentDelayMs = INITIAL_RETRY_DELAY_MS;\n while (retryCount < MAX_RETRY_COUNT) {\n response = await apiClient.request({\n path: '',\n body: chunk,\n httpMethod: 'POST',\n httpOptions: {\n apiVersion: '',\n baseUrl: uploadUrl,\n headers: {\n 'X-Goog-Upload-Command': uploadCommand,\n 'X-Goog-Upload-Offset': String(offset),\n 'Content-Length': String(chunkSize),\n },\n },\n });\n if (response?.headers?.[X_GOOG_UPLOAD_STATUS_HEADER_FIELD]) {\n break;\n }\n retryCount++;\n await sleep(currentDelayMs);\n currentDelayMs = currentDelayMs * DELAY_MULTIPLIER;\n }\n offset += chunkSize;\n // The `x-goog-upload-status` header field can be `active`, `final` and\n //`cancelled` in resposne.\n if (response?.headers?.[X_GOOG_UPLOAD_STATUS_HEADER_FIELD] !== 'active') {\n break;\n }\n // TODO(b/401391430) Investigate why the upload status is not finalized\n // even though all content has been uploaded.\n if (fileSize <= offset) {\n throw new Error(\n 'All content has been uploaded, but the upload status is not finalized.',\n );\n }\n }\n\n return response;\n}\n\nexport async function getBlobStat(file: Blob): Promise<FileStat> {\n const fileStat: FileStat = {size: file.size, type: file.type};\n return fileStat;\n}\n\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolvePromise) => setTimeout(resolvePromise, ms));\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\nimport * as fs from 'fs/promises';\nimport * as path from 'path';\n\nimport {ApiClient} from '../_api_client.js';\nimport {FileStat, Uploader} from '../_uploader.js';\nimport * as _converters from '../converters/_operations_converters.js';\nimport {\n DELAY_MULTIPLIER,\n INITIAL_RETRY_DELAY_MS,\n MAX_CHUNK_SIZE,\n MAX_RETRY_COUNT,\n X_GOOG_UPLOAD_STATUS_HEADER_FIELD,\n getBlobStat,\n sleep,\n uploadBlob,\n uploadBlobToFileSearchStore,\n} from '../cross/_cross_uploader.js';\nimport {\n File,\n HttpResponse,\n UploadToFileSearchStoreOperation,\n} from '../types.js';\n\nexport class NodeUploader implements Uploader {\n async stat(file: string | Blob): Promise<FileStat> {\n const fileStat: FileStat = {size: 0, type: undefined};\n if (typeof file === 'string') {\n const originalStat = await fs.stat(file);\n fileStat.size = originalStat.size;\n fileStat.type = this.inferMimeType(file);\n return fileStat;\n } else {\n return await getBlobStat(file);\n }\n }\n\n async upload(\n file: string | Blob,\n uploadUrl: string,\n apiClient: ApiClient,\n ): Promise<File> {\n if (typeof file === 'string') {\n return await this.uploadFileFromPath(file, uploadUrl, apiClient);\n } else {\n return uploadBlob(file, uploadUrl, apiClient);\n }\n }\n\n async uploadToFileSearchStore(\n file: string | Blob,\n uploadUrl: string,\n apiClient: ApiClient,\n ): Promise<UploadToFileSearchStoreOperation> {\n if (typeof file === 'string') {\n return await this.uploadFileToFileSearchStoreFromPath(\n file,\n uploadUrl,\n apiClient,\n );\n } else {\n return uploadBlobToFileSearchStore(file, uploadUrl, apiClient);\n }\n }\n\n /**\n * Infers the MIME type of a file based on its extension.\n *\n * @param filePath The path to the file.\n * @returns The MIME type of the file, or undefined if it cannot be inferred.\n */\n private inferMimeType(filePath: string): string | undefined {\n // Get the file extension.\n const fileExtension = filePath.slice(filePath.lastIndexOf('.') + 1);\n\n // Create a map of file extensions to MIME types.\n const mimeTypes: {[key: string]: string} = {\n 'aac': 'audio/aac',\n 'abw': 'application/x-abiword',\n 'arc': 'application/x-freearc',\n 'avi': 'video/x-msvideo',\n 'azw': 'application/vnd.amazon.ebook',\n 'bin': 'application/octet-stream',\n 'bmp': 'image/bmp',\n 'bz': 'application/x-bzip',\n 'bz2': 'application/x-bzip2',\n 'csh': 'application/x-csh',\n 'css': 'text/css',\n 'csv': 'text/csv',\n 'doc': 'application/msword',\n 'docx':\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n 'eot': 'application/vnd.ms-fontobject',\n 'epub': 'application/epub+zip',\n 'gz': 'application/gzip',\n 'gif': 'image/gif',\n 'htm': 'text/html',\n 'html': 'text/html',\n 'ico': 'image/vnd.microsoft.icon',\n 'ics': 'text/calendar',\n 'jar': 'application/java-archive',\n 'jpeg': 'image/jpeg',\n 'jpg': 'image/jpeg',\n 'js': 'text/javascript',\n 'json': 'application/json',\n 'jsonld': 'application/ld+json',\n 'kml': 'application/vnd.google-earth.kml+xml',\n 'kmz': 'application/vnd.google-earth.kmz+xml',\n 'mjs': 'text/javascript',\n 'mp3': 'audio/mpeg',\n 'mp4': 'video/mp4',\n 'mpeg': 'video/mpeg',\n 'mpkg': 'application/vnd.apple.installer+xml',\n 'odt': 'application/vnd.oasis.opendocument.text',\n 'oga': 'audio/ogg',\n 'ogv': 'video/ogg',\n 'ogx': 'application/ogg',\n 'opus': 'audio/opus',\n 'otf': 'font/otf',\n 'png': 'image/png',\n 'pdf': 'application/pdf',\n 'php': 'application/x-httpd-php',\n 'ppt': 'application/vnd.ms-powerpoint',\n 'pptx':\n 'application/vnd.openxmlformats-officedocument.presentationml.presentation',\n 'rar': 'application/vnd.rar',\n 'rtf': 'application/rtf',\n 'sh': 'application/x-sh',\n 'svg': 'image/svg+xml',\n 'swf': 'application/x-shockwave-flash',\n 'tar': 'application/x-tar',\n 'tif': 'image/tiff',\n 'tiff': 'image/tiff',\n 'ts': 'video/mp2t',\n 'ttf': 'font/ttf',\n 'txt': 'text/plain',\n 'vsd': 'application/vnd.visio',\n 'wav': 'audio/wav',\n 'weba': 'audio/webm',\n 'webm': 'video/webm',\n 'webp': 'image/webp',\n 'woff': 'font/woff',\n 'woff2': 'font/woff2',\n 'xhtml': 'application/xhtml+xml',\n 'xls': 'application/vnd.ms-excel',\n 'xlsx':\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n 'xml': 'application/xml',\n 'xul': 'application/vnd.mozilla.xul+xml',\n 'zip': 'application/zip',\n '3gp': 'video/3gpp',\n '3g2': 'video/3gpp2',\n '7z': 'application/x-7z-compressed',\n };\n\n // Look up the MIME type based on the file extension.\n const mimeType = mimeTypes[fileExtension.toLowerCase()];\n\n // Return the MIME type.\n return mimeType;\n }\n\n private async uploadFileFromPath(\n file: string,\n uploadUrl: string,\n apiClient: ApiClient,\n ): Promise<File> {\n const response = await this.uploadFileFromPathInternal(\n file,\n uploadUrl,\n apiClient,\n );\n const responseJson = (await response?.json()) as Record<\n string,\n File | unknown\n >;\n if (response?.headers?.[X_GOOG_UPLOAD_STATUS_HEADER_FIELD] !== 'final') {\n throw new Error('Failed to upload file: Upload status is not finalized.');\n }\n return responseJson['file'] as File;\n }\n\n private async uploadFileToFileSearchStoreFromPath(\n file: string,\n uploadUrl: string,\n apiClient: ApiClient,\n ): Promise<UploadToFileSearchStoreOperation> {\n const response = await this.uploadFileFromPathInternal(\n file,\n uploadUrl,\n apiClient,\n );\n const responseJson =\n (await response?.json()) as UploadToFileSearchStoreOperation;\n if (response?.headers?.[X_GOOG_UPLOAD_STATUS_HEADER_FIELD] !== 'final') {\n throw new Error('Failed to upload file: Upload status is not finalized.');\n }\n const resp =\n _converters.uploadToFileSearchStoreOperationFromMldev(responseJson);\n const typedResp = new UploadToFileSearchStoreOperation();\n Object.assign(typedResp, resp);\n return typedResp;\n }\n\n private async uploadFileFromPathInternal(\n file: string,\n uploadUrl: string,\n apiClient: ApiClient,\n ): Promise<HttpResponse> {\n let fileSize = 0;\n let offset = 0;\n let response: HttpResponse = new HttpResponse(new Response());\n let uploadCommand = 'upload';\n let fileHandle: fs.FileHandle | undefined;\n const fileName = path.basename(file);\n try {\n fileHandle = await fs.open(file, 'r');\n if (!fileHandle) {\n throw new Error(`Failed to open file`);\n }\n fileSize = (await fileHandle.stat()).size;\n while (offset < fileSize) {\n const chunkSize = Math.min(MAX_CHUNK_SIZE, fileSize - offset);\n if (offset + chunkSize >= fileSize) {\n uploadCommand += ', finalize';\n }\n const buffer = new Uint8Array(chunkSize);\n const {bytesRead: bytesRead} = await fileHandle.read(\n buffer,\n 0,\n chunkSize,\n offset,\n );\n\n if (bytesRead !== chunkSize) {\n throw new Error(\n `Failed to read ${chunkSize} bytes from file at offset ${\n offset\n }. bytes actually read: ${bytesRead}`,\n );\n }\n\n const chunk = new Blob([buffer]);\n let retryCount = 0;\n let currentDelayMs = INITIAL_RETRY_DELAY_MS;\n while (retryCount < MAX_RETRY_COUNT) {\n response = await apiClient.request({\n path: '',\n body: chunk,\n httpMethod: 'POST',\n httpOptions: {\n apiVersion: '',\n baseUrl: uploadUrl,\n headers: {\n 'X-Goog-Upload-Command': uploadCommand,\n 'X-Goog-Upload-Offset': String(offset),\n 'Content-Length': String(bytesRead),\n 'X-Goog-Upload-File-Name': fileName,\n },\n },\n });\n if (response?.headers?.[X_GOOG_UPLOAD_STATUS_HEADER_FIELD]) {\n break;\n }\n retryCount++;\n await sleep(currentDelayMs);\n currentDelayMs = currentDelayMs * DELAY_MULTIPLIER;\n }\n offset += bytesRead;\n // The `x-goog-upload-status` header field can be `active`, `final` and\n //`cancelled` in resposne.\n if (\n response?.headers?.[X_GOOG_UPLOAD_STATUS_HEADER_FIELD] !== 'active'\n ) {\n break;\n }\n if (fileSize <= offset) {\n throw new Error(\n 'All content has been uploaded, but the upload status is not finalized.',\n );\n }\n }\n return response;\n } finally {\n // Ensure the file handle is always closed\n if (fileHandle) {\n await fileHandle.close();\n }\n }\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {GoogleAuth} from 'google-auth-library';\n\nimport {Files} from '../files.js';\nimport * as types from '../types.js';\n\n/**\n * Node-specific parameters for registerFiles, including GoogleAuth.\n */\nexport interface NodeRegisterFilesParameters\n extends types.RegisterFilesParameters {\n /** The authentication object. */\n auth: GoogleAuth;\n}\n\nexport class NodeFiles extends Files {\n /**\n * Registers Google Cloud Storage files for use with the API.\n * This method is only available in Node.js environments.\n */\n override async registerFiles(\n params: NodeRegisterFilesParameters,\n ): Promise<types.RegisterFilesResponse> {\n if (\n typeof process === 'undefined' ||\n !process.versions ||\n !process.versions.node\n ) {\n throw new Error(\n 'registerFiles is only supported in Node.js environments.',\n );\n }\n const googleAuth = params.auth;\n\n const authHeaders = await googleAuth.getRequestHeaders();\n const config = params.config || {};\n const httpOptions = config.httpOptions || {};\n const headers: Record<string, string> = {\n ...(httpOptions.headers || {}),\n };\n\n if (authHeaders) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n if (typeof (authHeaders as any)[Symbol.iterator] === 'function') {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n for (const [key, value] of authHeaders as any) {\n headers[key] = value;\n }\n } else {\n for (const [key, value] of Object.entries(authHeaders)) {\n headers[key] = value;\n }\n }\n }\n\n return this._registerFiles({\n uris: params.uris,\n config: {\n ...config,\n httpOptions: {\n ...httpOptions,\n headers,\n },\n },\n });\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {GoogleAuthOptions} from 'google-auth-library';\n\nimport {ApiClient} from '../_api_client.js';\nimport {getBaseUrl} from '../_base_url.js';\nimport {Batches} from '../batches.js';\nimport {Caches} from '../caches.js';\nimport {Chats} from '../chats.js';\nimport {GoogleGenAIOptions} from '../client.js';\nimport {Files} from '../files.js';\nimport {FileSearchStores} from '../filesearchstores.js';\nimport GeminiNextGenAPI from '../interactions/index.js';\nimport {Interactions as GeminiNextGenInteractions} from '../interactions/resources/interactions.js';\nimport {Live} from '../live.js';\nimport {Models} from '../models.js';\nimport {NodeAuth} from '../node/_node_auth.js';\nimport {NodeDownloader} from '../node/_node_downloader.js';\nimport {NodeWebSocketFactory} from '../node/_node_websocket.js';\nimport {Operations} from '../operations.js';\nimport {Tokens} from '../tokens.js';\nimport {Tunings} from '../tunings.js';\nimport {HttpOptions} from '../types.js';\n\nimport {NodeUploader} from './_node_uploader.js';\nimport {NodeFiles} from './node_files.js';\n\nconst LANGUAGE_LABEL_PREFIX = 'gl-node/';\n\n/**\n * The Google GenAI SDK.\n *\n * @remarks\n * Provides access to the GenAI features through either the {@link\n * https://cloud.google.com/vertex-ai/docs/reference/rest | Gemini API} or\n * the {@link https://cloud.google.com/vertex-ai/docs/reference/rest | Vertex AI\n * API}.\n *\n * The {@link GoogleGenAIOptions.vertexai} value determines which of the API\n * services to use.\n *\n * When using the Gemini API, a {@link GoogleGenAIOptions.apiKey} must also be\n * set. When using Vertex AI, both {@link GoogleGenAIOptions.project} and {@link\n * GoogleGenAIOptions.location} must be set, or a {@link\n * GoogleGenAIOptions.apiKey} must be set when using Express Mode.\n *\n * Explicitly passed in values in {@link GoogleGenAIOptions} will always take\n * precedence over environment variables. If both project/location and api_key\n * exist in the environment variables, the project/location will be used.\n *\n * @example\n * Initializing the SDK for using the Gemini API:\n * ```ts\n * import {GoogleGenAI} from '@google/genai';\n * const ai = new GoogleGenAI({apiKey: 'GEMINI_API_KEY'});\n * ```\n *\n * @example\n * Initializing the SDK for using the Vertex AI API:\n * ```ts\n * import {GoogleGenAI} from '@google/genai';\n * const ai = new GoogleGenAI({\n * vertexai: true,\n * project: 'PROJECT_ID',\n * location: 'PROJECT_LOCATION'\n * });\n * ```\n *\n */\nexport class GoogleGenAI {\n protected readonly apiClient: ApiClient;\n private readonly apiKey?: string;\n public readonly vertexai: boolean;\n private readonly googleAuthOptions?: GoogleAuthOptions;\n private readonly project?: string;\n private readonly location?: string;\n private readonly apiVersion?: string;\n private readonly httpOptions?: HttpOptions;\n readonly models: Models;\n readonly live: Live;\n readonly batches: Batches;\n readonly chats: Chats;\n readonly caches: Caches;\n readonly files: Files;\n readonly operations: Operations;\n readonly authTokens: Tokens;\n readonly tunings: Tunings;\n readonly fileSearchStores: FileSearchStores;\n private _interactions: GeminiNextGenInteractions | undefined;\n\n get interactions(): GeminiNextGenInteractions {\n if (this._interactions !== undefined) {\n return this._interactions;\n }\n\n console.warn(\n 'GoogleGenAI.interactions: Interactions usage is experimental and may change in future versions.',\n );\n\n const httpOpts = this.httpOptions;\n\n // Unsupported Options Warnings\n if (httpOpts?.extraBody) {\n console.warn(\n 'GoogleGenAI.interactions: Client level httpOptions.extraBody is not supported by the interactions client and will be ignored.',\n );\n }\n\n const nextGenClient = new GeminiNextGenAPI({\n baseURL: this.apiClient.getBaseUrl(),\n apiKey: this.apiKey,\n apiVersion: this.apiClient.getApiVersion(),\n clientAdapter: this.apiClient,\n defaultHeaders: this.apiClient.getDefaultHeaders(),\n timeout: httpOpts?.timeout,\n maxRetries: httpOpts?.retryOptions?.attempts,\n });\n this._interactions = nextGenClient.interactions;\n\n return this._interactions;\n }\n constructor(options: GoogleGenAIOptions) {\n // Validate explicitly set initializer values.\n if ((options.project || options.location) && options.apiKey) {\n throw new Error(\n 'Project/location and API key are mutually exclusive in the client initializer.',\n );\n }\n\n this.vertexai =\n options.vertexai ?? getBooleanEnv('GOOGLE_GENAI_USE_VERTEXAI') ?? false;\n const envApiKey = getApiKeyFromEnv();\n const envProject = getEnv('GOOGLE_CLOUD_PROJECT');\n const envLocation = getEnv('GOOGLE_CLOUD_LOCATION');\n\n this.apiKey = options.apiKey ?? envApiKey;\n this.project = options.project ?? envProject;\n this.location = options.location ?? envLocation;\n\n if (!this.vertexai && !this.apiKey) {\n throw new Error('API key must be set when using the Gemini API.');\n }\n\n // Handle when to use Vertex AI in express mode (api key)\n if (options.vertexai) {\n if (options.googleAuthOptions?.credentials) {\n // Explicit credentials take precedence over implicit api_key.\n console.debug(\n 'The user provided Google Cloud credentials will take precedence' +\n ' over the API key from the environment variable.',\n );\n this.apiKey = undefined;\n }\n // Explicit api_key and explicit project/location already handled above.\n if ((envProject || envLocation) && options.apiKey) {\n // Explicit api_key takes precedence over implicit project/location.\n console.debug(\n 'The user provided Vertex AI API key will take precedence over' +\n ' the project/location from the environment variables.',\n );\n this.project = undefined;\n this.location = undefined;\n } else if ((options.project || options.location) && envApiKey) {\n // Explicit project/location takes precedence over implicit api_key.\n console.debug(\n 'The user provided project/location will take precedence over' +\n ' the API key from the environment variables.',\n );\n this.apiKey = undefined;\n } else if ((envProject || envLocation) && envApiKey) {\n // Implicit project/location takes precedence over implicit api_key.\n console.debug(\n 'The project/location from the environment variables will take' +\n ' precedence over the API key from the environment variables.',\n );\n this.apiKey = undefined;\n }\n\n if (!this.location && !this.apiKey) {\n this.location = 'global';\n }\n }\n\n const baseUrl = getBaseUrl(\n options.httpOptions,\n options.vertexai,\n getEnv('GOOGLE_VERTEX_BASE_URL'),\n getEnv('GOOGLE_GEMINI_BASE_URL'),\n );\n if (baseUrl) {\n if (options.httpOptions) {\n options.httpOptions.baseUrl = baseUrl;\n } else {\n options.httpOptions = {baseUrl: baseUrl};\n }\n }\n\n this.apiVersion = options.apiVersion;\n this.httpOptions = options.httpOptions;\n const auth = new NodeAuth({\n apiKey: this.apiKey,\n googleAuthOptions: options.googleAuthOptions,\n });\n this.apiClient = new ApiClient({\n auth: auth,\n project: this.project,\n location: this.location,\n apiVersion: this.apiVersion,\n apiKey: this.apiKey,\n vertexai: this.vertexai,\n httpOptions: this.httpOptions,\n userAgentExtra: LANGUAGE_LABEL_PREFIX + process.version,\n uploader: new NodeUploader(),\n downloader: new NodeDownloader(),\n });\n this.models = new Models(this.apiClient);\n this.live = new Live(this.apiClient, auth, new NodeWebSocketFactory());\n this.batches = new Batches(this.apiClient);\n this.chats = new Chats(this.models, this.apiClient);\n this.caches = new Caches(this.apiClient);\n this.files = new NodeFiles(this.apiClient);\n this.operations = new Operations(this.apiClient);\n this.authTokens = new Tokens(this.apiClient);\n this.tunings = new Tunings(this.apiClient);\n this.fileSearchStores = new FileSearchStores(this.apiClient);\n }\n}\n\nfunction getEnv(env: string): string | undefined {\n return process?.env?.[env]?.trim() ?? undefined;\n}\n\nfunction getBooleanEnv(env: string): boolean {\n return stringToBoolean(getEnv(env));\n}\n\nfunction stringToBoolean(str?: string): boolean {\n if (str === undefined) {\n return false;\n }\n return str.toLowerCase() === 'true';\n}\n\nfunction getApiKeyFromEnv(): string | undefined {\n const envGoogleApiKey = getEnv('GOOGLE_API_KEY');\n const envGeminiApiKey = getEnv('GEMINI_API_KEY');\n if (envGoogleApiKey && envGeminiApiKey) {\n console.warn(\n 'Both GOOGLE_API_KEY and GEMINI_API_KEY are set. Using GOOGLE_API_KEY.',\n );\n }\n return envGoogleApiKey || envGeminiApiKey || undefined;\n}\n"],"names":["tBytes","common.getValueByPath","common.setValueByPath","generateVideosOperationFromMldev","generateVideosResponseFromMldev","generateVideosOperationFromVertex","generateVideosResponseFromVertex","generatedVideoFromMldev","generatedVideoFromVertex","videoFromMldev","videoFromVertex","importFileOperationFromMldev","importFileResponseFromMldev","t.tBytes","types.Type","baseTransformers.tBytes","t.tJobState","t.tRecvBatchJobDestination","blobToMldev","t.tBatchJobName","candidateFromMldev","citationMetadataFromMldev","contentToMldev","partToMldev","t.tBatchJobDestination","t.tModel","t.tBatchJobSource","t.tContentsForEmbed","embedContentConfigToMldev","common.moveValueByPath","fileDataToMldev","functionCallToMldev","functionCallingConfigToMldev","generateContentConfigToMldev","t.tContent","t.tSchema","safetySettingToMldev","t.tTools","toolToMldev","t.tTool","toolConfigToMldev","t.tCachedContentName","t.tSpeechConfig","imageConfigToMldev","generateContentResponseFromMldev","googleMapsToMldev","googleSearchToMldev","t.tContents","converters.createBatchJobParametersToMldev","common.formatMap","converters.createBatchJobParametersToVertex","converters.batchJobFromVertex","converters.batchJobFromMldev","converters.createEmbeddingsBatchJobParametersToMldev","converters.getBatchJobParametersToVertex","converters.getBatchJobParametersToMldev","converters.cancelBatchJobParametersToVertex","converters.cancelBatchJobParametersToMldev","converters.listBatchJobsParametersToVertex","converters.listBatchJobsResponseFromVertex","types.ListBatchJobsResponse","converters.listBatchJobsParametersToMldev","converters.listBatchJobsResponseFromMldev","converters.deleteBatchJobParametersToVertex","converters.deleteResourceJobFromVertex","converters.deleteBatchJobParametersToMldev","converters.deleteResourceJobFromMldev","toolToVertex","t.tCachesModel","functionDeclarationToVertex","converters.createCachedContentParametersToVertex","converters.createCachedContentParametersToMldev","converters.getCachedContentParametersToVertex","converters.getCachedContentParametersToMldev","converters.deleteCachedContentParametersToVertex","converters.deleteCachedContentResponseFromVertex","types.DeleteCachedContentResponse","converters.deleteCachedContentParametersToMldev","converters.deleteCachedContentResponseFromMldev","converters.updateCachedContentParametersToVertex","converters.updateCachedContentParametersToMldev","converters.listCachedContentsParametersToVertex","converters.listCachedContentsResponseFromVertex","types.ListCachedContentsResponse","converters.listCachedContentsParametersToMldev","converters.listCachedContentsResponseFromMldev","t.tFileName","converters.listFilesParametersToMldev","converters.listFilesResponseFromMldev","types.ListFilesResponse","converters.createFileParametersToMldev","converters.createFileResponseFromMldev","types.CreateFileResponse","converters.getFileParametersToMldev","converters.deleteFileParametersToMldev","converters.deleteFileResponseFromMldev","types.DeleteFileResponse","converters.internalRegisterFilesParametersToMldev","converters.registerFilesResponseFromMldev","types.RegisterFilesResponse","generationConfigToVertex","liveConnectConfigToMldev","t.tLiveSpeechConfig","sessionResumptionConfigToMldev","t.tBlobs","t.tAudioBlob","t.tImageBlob","t.tModelsUrl","t.tExtractModels","types.ResourceScope","types.HttpResponse","handleWebSocketMessage","types.LiveMusicServerMessage","mapToHeaders","headersToMap","converters.liveMusicSetWeightedPromptsParametersToMldev","converters.liveMusicSetConfigParametersToMldev","types.LiveMusicPlaybackControl","types.LiveServerMessage","converters.liveServerMessageFromVertex","types.Modality","converters.liveConnectParametersToVertex","converters.liveConnectParametersToMldev","converters.liveSendRealtimeInputParametersToVertex","converters.liveSendRealtimeInputParametersToMldev","afc.hasCallableTools","afc.shouldDisableAfc","afc.findAfcIncompatibleToolIndexes","afc.DEFAULT_MAX_REMOTE_CALLS","afc.isCallableTool","afc.shouldAppendAfcHistory","mcp.hasMcpToolUsage","mcp.setMcpUsageHeader","types.GenerateContentResponse","converters.generateContentParametersToVertex","converters.generateContentResponseFromVertex","converters.generateContentParametersToMldev","converters.generateContentResponseFromMldev","converters.embedContentParametersToVertex","converters.embedContentResponseFromVertex","types.EmbedContentResponse","converters.embedContentParametersToMldev","converters.embedContentResponseFromMldev","converters.generateImagesParametersToVertex","converters.generateImagesResponseFromVertex","types.GenerateImagesResponse","converters.generateImagesParametersToMldev","converters.generateImagesResponseFromMldev","converters.editImageParametersInternalToVertex","converters.editImageResponseFromVertex","types.EditImageResponse","converters.upscaleImageAPIParametersInternalToVertex","converters.upscaleImageResponseFromVertex","types.UpscaleImageResponse","converters.recontextImageParametersToVertex","converters.recontextImageResponseFromVertex","types.RecontextImageResponse","converters.segmentImageParametersToVertex","converters.segmentImageResponseFromVertex","types.SegmentImageResponse","converters.getModelParametersToVertex","converters.modelFromVertex","converters.getModelParametersToMldev","converters.modelFromMldev","converters.listModelsParametersToVertex","converters.listModelsResponseFromVertex","types.ListModelsResponse","converters.listModelsParametersToMldev","converters.listModelsResponseFromMldev","converters.updateModelParametersToVertex","converters.updateModelParametersToMldev","converters.deleteModelParametersToVertex","converters.deleteModelResponseFromVertex","types.DeleteModelResponse","converters.deleteModelParametersToMldev","converters.deleteModelResponseFromMldev","converters.countTokensParametersToVertex","converters.countTokensResponseFromVertex","types.CountTokensResponse","converters.countTokensParametersToMldev","converters.countTokensResponseFromMldev","converters.computeTokensParametersToVertex","converters.computeTokensResponseFromVertex","types.ComputeTokensResponse","converters.generateVideosParametersToVertex","converters.generateVideosOperationFromVertex","types.GenerateVideosOperation","converters.generateVideosParametersToMldev","converters.generateVideosOperationFromMldev","converters.getOperationParametersToVertex","converters.getOperationParametersToMldev","converters.fetchPredictOperationParametersToVertex","converters.createAuthTokenParametersToMldev","converters.getDocumentParametersToMldev","converters.deleteDocumentParametersToMldev","converters.listDocumentsParametersToMldev","converters.listDocumentsResponseFromMldev","types.ListDocumentsResponse","converters.createFileSearchStoreParametersToMldev","converters.getFileSearchStoreParametersToMldev","converters.deleteFileSearchStoreParametersToMldev","converters.listFileSearchStoresParametersToMldev","converters.listFileSearchStoresResponseFromMldev","types.ListFileSearchStoresResponse","converters.uploadToFileSearchStoreParametersToMldev","converters.uploadToFileSearchStoreResumableResponseFromMldev","types.UploadToFileSearchStoreResumableResponse","converters.importFileParametersToMldev","converters.importFileOperationFromMldev","types.ImportFileOperation","sleep","Errors.GeminiNextGenAPIClientError","Shims.getDefaultFetch","Opts.FallbackEncoder","Errors.APIError","Errors.APIUserAbortError","Errors.APIConnectionTimeoutError","Errors.APIConnectionError","Shims.CancelReadableStream","Shims.ReadableStreamFrom","API.Interactions","Errors.NotFoundError","Errors.ConflictError","Errors.RateLimitError","Errors.BadRequestError","Errors.AuthenticationError","Errors.InternalServerError","Errors.PermissionDeniedError","Errors.UnprocessableEntityError","Uploads.toFile","t.tTuningJobStatus","types.JobState","converters.getTuningJobParametersToVertex","converters.tuningJobFromVertex","converters.getTuningJobParametersToMldev","converters.tuningJobFromMldev","converters.listTuningJobsParametersToVertex","converters.listTuningJobsResponseFromVertex","types.ListTuningJobsResponse","converters.listTuningJobsParametersToMldev","converters.listTuningJobsResponseFromMldev","converters.cancelTuningJobParametersToVertex","converters.cancelTuningJobResponseFromVertex","types.CancelTuningJobResponse","converters.cancelTuningJobParametersToMldev","converters.cancelTuningJobResponseFromMldev","converters.createTuningJobParametersPrivateToVertex","converters.createTuningJobParametersPrivateToMldev","converters.tuningOperationFromMldev","_converters.uploadToFileSearchStoreOperationFromMldev","path","GeminiNextGenAPI"],"mappings":"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"} \ No newline at end of file diff --git a/server/node_modules/@google/genai/dist/node/node.d.ts b/server/node_modules/@google/genai/dist/node/node.d.ts new file mode 100644 index 0000000..d20d1f0 --- /dev/null +++ b/server/node_modules/@google/genai/dist/node/node.d.ts @@ -0,0 +1,11256 @@ +/// <reference types="node" /> + +import type { Client } from '@modelcontextprotocol/sdk/client/index.js'; +import { GoogleAuthOptions } from 'google-auth-library'; +import { ReadableStream as ReadableStream_2 } from 'stream/web'; + +/** Marks the end of user activity. + + This can only be sent if automatic (i.e. server-side) activity detection is + disabled. */ +export declare interface ActivityEnd { +} + +/** The different ways of handling user activity. */ +export declare enum ActivityHandling { + /** + * If unspecified, the default behavior is `START_OF_ACTIVITY_INTERRUPTS`. + */ + ACTIVITY_HANDLING_UNSPECIFIED = "ACTIVITY_HANDLING_UNSPECIFIED", + /** + * If true, start of activity will interrupt the model's response (also called "barge in"). The model's current response will be cut-off in the moment of the interruption. This is the default behavior. + */ + START_OF_ACTIVITY_INTERRUPTS = "START_OF_ACTIVITY_INTERRUPTS", + /** + * The model's response will not be interrupted. + */ + NO_INTERRUPTION = "NO_INTERRUPTION" +} + +/** Marks the start of user activity. + + This can only be sent if automatic (i.e. server-side) activity detection is + disabled. */ +export declare interface ActivityStart { +} + +/** Adapter size for tuning. This enum is not supported in Gemini API. */ +export declare enum AdapterSize { + /** + * Adapter size is unspecified. + */ + ADAPTER_SIZE_UNSPECIFIED = "ADAPTER_SIZE_UNSPECIFIED", + /** + * Adapter size 1. + */ + ADAPTER_SIZE_ONE = "ADAPTER_SIZE_ONE", + /** + * Adapter size 2. + */ + ADAPTER_SIZE_TWO = "ADAPTER_SIZE_TWO", + /** + * Adapter size 4. + */ + ADAPTER_SIZE_FOUR = "ADAPTER_SIZE_FOUR", + /** + * Adapter size 8. + */ + ADAPTER_SIZE_EIGHT = "ADAPTER_SIZE_EIGHT", + /** + * Adapter size 16. + */ + ADAPTER_SIZE_SIXTEEN = "ADAPTER_SIZE_SIXTEEN", + /** + * Adapter size 32. + */ + ADAPTER_SIZE_THIRTY_TWO = "ADAPTER_SIZE_THIRTY_TWO" +} + +/** + * The configuration for allowed tools. + */ +declare interface AllowedTools { + /** + * The mode of the tool choice. + */ + mode?: ToolChoiceType; + /** + * The names of the allowed tools. + */ + tools?: Array<string>; +} + +/** + * Citation information for model-generated content. + */ +declare interface Annotation { + /** + * End of the attributed segment, exclusive. + */ + end_index?: number; + /** + * Source attributed for a portion of the text. Could be a URL, title, or + * other identifier. + */ + source?: string; + /** + * Start of segment of the response that is attributed to this source. + * + * Index indicates the start of the segment, measured in bytes. + */ + start_index?: number; +} + +/** The generic reusable api auth config. Deprecated. Please use AuthConfig (google/cloud/aiplatform/master/auth.proto) instead. This data type is not supported in Gemini API. */ +export declare interface ApiAuth { + /** The API secret. */ + apiKeyConfig?: ApiAuthApiKeyConfig; +} + +/** The API secret. This data type is not supported in Gemini API. */ +export declare interface ApiAuthApiKeyConfig { + /** Required. The SecretManager secret version resource name storing API key. e.g. projects/{project}/secrets/{secret}/versions/{version} */ + apiKeySecretVersion?: string; + /** The API key string. Either this or `api_key_secret_version` must be set. */ + apiKeyString?: string; +} + +/** + * The ApiClient class is used to send requests to the Gemini API or Vertex AI + * endpoints. + */ +declare class ApiClient implements GeminiNextGenAPIClientAdapter { + readonly clientOptions: ApiClientInitOptions; + private readonly customBaseUrl?; + constructor(opts: ApiClientInitOptions); + isVertexAI(): boolean; + getProject(): string | undefined; + getLocation(): string | undefined; + getCustomBaseUrl(): string | undefined; + getAuthHeaders(): Promise<Headers>; + getApiVersion(): string; + getBaseUrl(): string; + getRequestUrl(): string; + getHeaders(): Record<string, string>; + private getRequestUrlInternal; + getBaseResourcePath(): string; + getApiKey(): string | undefined; + getWebsocketBaseUrl(): string; + setBaseUrl(url: string): void; + private constructUrl; + private shouldPrependVertexProjectPath; + request(request: HttpRequest): Promise<types.HttpResponse>; + private patchHttpOptions; + requestStream(request: HttpRequest): Promise<AsyncGenerator<types.HttpResponse>>; + private includeExtraHttpOptionsToRequestInit; + private unaryApiCall; + private streamApiCall; + processStreamResponse(response: Response): AsyncGenerator<types.HttpResponse>; + private apiCall; + getDefaultHeaders(): Record<string, string>; + private getHeadersInternal; + private getFileName; + /** + * Uploads a file asynchronously using Gemini API only, this is not supported + * in Vertex AI. + * + * @param file The string path to the file to be uploaded or a Blob object. + * @param config Optional parameters specified in the `UploadFileConfig` + * interface. @see {@link types.UploadFileConfig} + * @return A promise that resolves to a `File` object. + * @throws An error if called on a Vertex AI client. + * @throws An error if the `mimeType` is not provided and can not be inferred, + */ + uploadFile(file: string | Blob, config?: types.UploadFileConfig): Promise<types.File>; + /** + * Uploads a file to a given file search store asynchronously using Gemini API only, this is not supported + * in Vertex AI. + * + * @param fileSearchStoreName The name of the file search store to upload the file to. + * @param file The string path to the file to be uploaded or a Blob object. + * @param config Optional parameters specified in the `UploadFileConfig` + * interface. @see {@link UploadFileConfig} + * @return A promise that resolves to a `File` object. + * @throws An error if called on a Vertex AI client. + * @throws An error if the `mimeType` is not provided and can not be inferred, + */ + uploadFileToFileSearchStore(fileSearchStoreName: string, file: string | Blob, config?: types.UploadToFileSearchStoreConfig): Promise<types.UploadToFileSearchStoreOperation>; + /** + * Downloads a file asynchronously to the specified path. + * + * @params params - The parameters for the download request, see {@link + * types.DownloadFileParameters} + */ + downloadFile(params: types.DownloadFileParameters): Promise<void>; + private fetchUploadUrl; +} + +/** + * Options for initializing the ApiClient. The ApiClient uses the parameters + * for authentication purposes as well as to infer if SDK should send the + * request to Vertex AI or Gemini API. + */ +declare interface ApiClientInitOptions { + /** + * The object used for adding authentication headers to API requests. + */ + auth: Auth; + /** + * The uploader to use for uploading files. This field is required for + * creating a client, will be set through the Node_client or Web_client. + */ + uploader: Uploader; + /** + * Optional. The downloader to use for downloading files. This field is + * required for creating a client, will be set through the Node_client or + * Web_client. + */ + downloader: Downloader; + /** + * Optional. The Google Cloud project ID for Vertex AI users. + * It is not the numeric project name. + * If not provided, SDK will try to resolve it from runtime environment. + */ + project?: string; + /** + * Optional. The Google Cloud project location for Vertex AI users. + * If not provided, SDK will try to resolve it from runtime environment. + */ + location?: string; + /** + * The API Key. This is required for Gemini API users. + */ + apiKey?: string; + /** + * Optional. Set to true if you intend to call Vertex AI endpoints. + * If unset, default SDK behavior is to call Gemini API. + */ + vertexai?: boolean; + /** + * Optional. The API version for the endpoint. + * If unset, SDK will choose a default api version. + */ + apiVersion?: string; + /** + * Optional. A set of customizable configuration for HTTP requests. + */ + httpOptions?: types.HttpOptions; + /** + * Optional. An extra string to append at the end of the User-Agent header. + * + * This can be used to e.g specify the runtime and its version. + */ + userAgentExtra?: string; +} + +declare class APIConnectionError extends APIError<undefined, undefined, undefined> { + constructor({ message, cause }: { + message?: string | undefined; + cause?: Error | undefined; + }); +} + +declare class APIConnectionTimeoutError extends APIConnectionError { + constructor({ message }?: { + message?: string; + }); +} + +declare class APIError<TStatus extends number | undefined = number | undefined, THeaders extends Headers | undefined = Headers | undefined, TError extends Object | undefined = Object | undefined> extends GeminiNextGenAPIClientError { + /** HTTP status for the response that caused the error */ + readonly status: TStatus; + /** HTTP headers for the response that caused the error */ + readonly headers: THeaders; + /** JSON body of the response that caused the error */ + readonly error: TError; + constructor(status: TStatus, error: TError, message: string | undefined, headers: THeaders); + private static makeMessage; + static generate(status: number | undefined, errorResponse: Object | undefined, message: string | undefined, headers: Headers | undefined): APIError; +} + +/** + * API errors raised by the GenAI API. + */ +export declare class ApiError extends Error { + /** HTTP status code */ + status: number; + constructor(options: ApiErrorInfo); +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Details for errors from calling the API. + */ +export declare interface ApiErrorInfo { + /** The error message. */ + message: string; + /** The HTTP status code. */ + status: number; +} + +/** Config for authentication with API key. This data type is not supported in Gemini API. */ +export declare interface ApiKeyConfig { + /** Optional. The name of the SecretManager secret version resource storing the API key. Format: `projects/{project}/secrets/{secrete}/versions/{version}` - If both `api_key_secret` and `api_key_string` are specified, this field takes precedence over `api_key_string`. - If specified, the `secretmanager.versions.access` permission should be granted to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents) on the specified resource. */ + apiKeySecret?: string; + /** Optional. The API key to be used in the request directly. */ + apiKeyString?: string; + /** Optional. The location of the API key. */ + httpElementLocation?: HttpElementLocation; + /** Optional. The parameter name of the API key. E.g. If the API request is "https://example.com/act?api_key=", "api_key" would be the parameter name. */ + name?: string; +} + +/** + * A subclass of `Promise` providing additional helper methods + * for interacting with the SDK. + */ +declare class APIPromise<T> extends Promise<T> { + private responsePromise; + private parseResponse; + private parsedPromise; + private client; + constructor(client: BaseGeminiNextGenAPIClient, responsePromise: Promise<APIResponseProps>, parseResponse?: (client: BaseGeminiNextGenAPIClient, props: APIResponseProps) => PromiseOrValue<T>); + _thenUnwrap<U>(transform: (data: T, props: APIResponseProps) => U): APIPromise<U>; + /** + * Gets the raw `Response` instance instead of parsing the response + * data. + * + * If you want to parse the response body but still get the `Response` + * instance, you can use {@link withResponse()}. + * + * 👋 Getting the wrong TypeScript type for `Response`? + * Try setting `"moduleResolution": "NodeNext"` or add `"lib": ["DOM"]` + * to your `tsconfig.json`. + */ + asResponse(): Promise<Response>; + /** + * Gets the parsed response data and the raw `Response` instance. + * + * If you just want to get the raw `Response` instance without parsing it, + * you can use {@link asResponse()}. + * + * 👋 Getting the wrong TypeScript type for `Response`? + * Try setting `"moduleResolution": "NodeNext"` or add `"lib": ["DOM"]` + * to your `tsconfig.json`. + */ + withResponse(): Promise<{ + data: T; + response: Response; + }>; + private parse; + then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>; + catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): Promise<T | TResult>; + finally(onfinally?: (() => void) | undefined | null): Promise<T>; +} + +declare abstract class APIResource { + /** + * The key path from the client. For example, a resource accessible as `client.resource.subresource` would + * have a property `static override readonly _key = Object.freeze(['resource', 'subresource'] as const);`. + */ + static readonly _key: readonly string[]; + protected _client: BaseGeminiNextGenAPIClient; + constructor(client: BaseGeminiNextGenAPIClient); +} + +declare type APIResponseProps = { + response: Response; + options: FinalRequestOptions; + controller: AbortController; + requestLogID: string; + retryOfRequestLogID: string | undefined; + startTime: number; +}; + +/** The API spec that the external API implements. This enum is not supported in Gemini API. */ +export declare enum ApiSpec { + /** + * Unspecified API spec. This value should not be used. + */ + API_SPEC_UNSPECIFIED = "API_SPEC_UNSPECIFIED", + /** + * Simple search API spec. + */ + SIMPLE_SEARCH = "SIMPLE_SEARCH", + /** + * Elastic search API spec. + */ + ELASTIC_SEARCH = "ELASTIC_SEARCH" +} + +declare class APIUserAbortError extends APIError<undefined, undefined, undefined> { + constructor({ message }?: { + message?: string; + }); +} + +/** Representation of an audio chunk. */ +export declare interface AudioChunk { + /** Raw bytes of audio data. + * @remarks Encoded as base64 string. */ + data?: string; + /** MIME type of the audio chunk. */ + mimeType?: string; + /** Prompts and config used for generating this audio chunk. */ + sourceMetadata?: LiveMusicSourceMetadata; +} + +/** + * An audio content block. + */ +declare interface AudioContent { + type: 'audio'; + /** + * The audio content. + */ + data?: string; + /** + * The mime type of the audio. + */ + mime_type?: AudioMimeType; + /** + * The URI of the audio. + */ + uri?: string; +} + +/** + * The mime type of the audio. + */ +declare type AudioMimeType = 'audio/wav' | 'audio/mp3' | 'audio/aiff' | 'audio/aac' | 'audio/ogg' | 'audio/flac' | (string & {}); + +/** The audio transcription configuration in Setup. */ +export declare interface AudioTranscriptionConfig { +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * The Auth interface is used to authenticate with the API service. + */ +declare interface Auth { + /** + * Sets the headers needed to authenticate with the API service. + * + * @param headers - The Headers object that will be updated with the authentication headers. + * @param url - The URL of the request. + */ + addAuthHeaders(headers: Headers, url?: string): Promise<void>; +} + +/** Auth configuration to run the extension. This data type is not supported in Gemini API. */ +export declare interface AuthConfig { + /** Config for API key auth. */ + apiKeyConfig?: ApiKeyConfig; + /** Type of auth scheme. */ + authType?: AuthType; + /** Config for Google Service Account auth. */ + googleServiceAccountConfig?: AuthConfigGoogleServiceAccountConfig; + /** Config for HTTP Basic auth. */ + httpBasicAuthConfig?: AuthConfigHttpBasicAuthConfig; + /** Config for user oauth. */ + oauthConfig?: AuthConfigOauthConfig; + /** Config for user OIDC auth. */ + oidcConfig?: AuthConfigOidcConfig; +} + +/** Config for Google Service Account Authentication. This data type is not supported in Gemini API. */ +export declare interface AuthConfigGoogleServiceAccountConfig { + /** Optional. The service account that the extension execution service runs as. - If the service account is specified, the `iam.serviceAccounts.getAccessToken` permission should be granted to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents) on the specified service account. - If not specified, the Vertex AI Extension Service Agent will be used to execute the Extension. */ + serviceAccount?: string; +} + +/** Config for HTTP Basic Authentication. This data type is not supported in Gemini API. */ +export declare interface AuthConfigHttpBasicAuthConfig { + /** Required. The name of the SecretManager secret version resource storing the base64 encoded credentials. Format: `projects/{project}/secrets/{secrete}/versions/{version}` - If specified, the `secretmanager.versions.access` permission should be granted to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents) on the specified resource. */ + credentialSecret?: string; +} + +/** Config for user oauth. This data type is not supported in Gemini API. */ +export declare interface AuthConfigOauthConfig { + /** Access token for extension endpoint. Only used to propagate token from [[ExecuteExtensionRequest.runtime_auth_config]] at request time. */ + accessToken?: string; + /** The service account used to generate access tokens for executing the Extension. - If the service account is specified, the `iam.serviceAccounts.getAccessToken` permission should be granted to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents) on the provided service account. */ + serviceAccount?: string; +} + +/** Config for user OIDC auth. This data type is not supported in Gemini API. */ +export declare interface AuthConfigOidcConfig { + /** OpenID Connect formatted ID token for extension endpoint. Only used to propagate token from [[ExecuteExtensionRequest.runtime_auth_config]] at request time. */ + idToken?: string; + /** The service account used to generate an OpenID Connect (OIDC)-compatible JWT token signed by the Google OIDC Provider (accounts.google.com) for extension endpoint (https://cloud.google.com/iam/docs/create-short-lived-credentials-direct#sa-credentials-oidc). - The audience for the token will be set to the URL in the server url defined in the OpenApi spec. - If the service account is provided, the service account should grant `iam.serviceAccounts.getOpenIdToken` permission to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents). */ + serviceAccount?: string; +} + +declare class AuthenticationError extends APIError<401, Headers> { +} + +/** Config for auth_tokens.create parameters. */ +export declare interface AuthToken { + /** The name of the auth token. */ + name?: string; +} + +/** Type of auth scheme. This enum is not supported in Gemini API. */ +export declare enum AuthType { + AUTH_TYPE_UNSPECIFIED = "AUTH_TYPE_UNSPECIFIED", + /** + * No Auth. + */ + NO_AUTH = "NO_AUTH", + /** + * API Key Auth. + */ + API_KEY_AUTH = "API_KEY_AUTH", + /** + * HTTP Basic Auth. + */ + HTTP_BASIC_AUTH = "HTTP_BASIC_AUTH", + /** + * Google Service Account Auth. + */ + GOOGLE_SERVICE_ACCOUNT_AUTH = "GOOGLE_SERVICE_ACCOUNT_AUTH", + /** + * OAuth auth. + */ + OAUTH = "OAUTH", + /** + * OpenID Connect (OIDC) Auth. + */ + OIDC_AUTH = "OIDC_AUTH" +} + +/** Configures automatic detection of activity. */ +export declare interface AutomaticActivityDetection { + /** If enabled, detected voice and text input count as activity. If disabled, the client must send activity signals. */ + disabled?: boolean; + /** Determines how likely speech is to be detected. */ + startOfSpeechSensitivity?: StartSensitivity; + /** Determines how likely detected speech is ended. */ + endOfSpeechSensitivity?: EndSensitivity; + /** The required duration of detected speech before start-of-speech is committed. The lower this value the more sensitive the start-of-speech detection is and the shorter speech can be recognized. However, this also increases the probability of false positives. */ + prefixPaddingMs?: number; + /** The required duration of detected non-speech (e.g. silence) before end-of-speech is committed. The larger this value, the longer speech gaps can be without interrupting the user's activity but this will increase the model's latency. */ + silenceDurationMs?: number; +} + +/** The configuration for automatic function calling. */ +export declare interface AutomaticFunctionCallingConfig { + /** Whether to disable automatic function calling. + If not set or set to False, will enable automatic function calling. + If set to True, will disable automatic function calling. + */ + disable?: boolean; + /** If automatic function calling is enabled, + maximum number of remote calls for automatic function calling. + This number should be a positive integer. + If not set, SDK will set maximum number of remote calls to 10. + */ + maximumRemoteCalls?: number; + /** If automatic function calling is enabled, + whether to ignore call history to the response. + If not set, SDK will set ignore_call_history to false, + and will append the call history to + GenerateContentResponse.automatic_function_calling_history. + */ + ignoreCallHistory?: boolean; +} + +declare class BadRequestError extends APIError<400, Headers> { +} + +declare interface BaseCreateAgentInteractionParams { + /** + * Path param: Which version of the API to use. + */ + api_version?: string; + /** + * Body param: The name of the `Agent` used for generating the interaction. + */ + agent: (string & {}) | 'deep-research-pro-preview-12-2025'; + /** + * Body param: The inputs for the interaction. + */ + input: string | Array<Content_2> | Array<Turn> | TextContent | ImageContent | AudioContent | DocumentContent | VideoContent | ThoughtContent | FunctionCallContent | FunctionResultContent | CodeExecutionCallContent | CodeExecutionResultContent | URLContextCallContent | URLContextResultContent | GoogleSearchCallContent | GoogleSearchResultContent | MCPServerToolCallContent | MCPServerToolResultContent | FileSearchCallContent | FileSearchResultContent; + /** + * Body param: Configuration for the agent. + */ + agent_config?: DynamicAgentConfig | DeepResearchAgentConfig; + /** + * Body param: Input only. Whether to run the model interaction in the background. + */ + background?: boolean; + /** + * Body param: The ID of the previous interaction, if any. + */ + previous_interaction_id?: string; + /** + * Body param: Enforces that the generated response is a JSON object that complies with + * the JSON schema specified in this field. + */ + response_format?: unknown; + /** + * Body param: The mime type of the response. This is required if response_format is set. + */ + response_mime_type?: string; + /** + * Body param: The requested modalities of the response (TEXT, IMAGE, AUDIO). + */ + response_modalities?: Array<'text' | 'image' | 'audio'>; + /** + * Body param: Input only. Whether to store the response and request for later retrieval. + */ + store?: boolean; + /** + * Body param: Input only. Whether the interaction will be streamed. + */ + stream?: boolean; + /** + * Body param: System instruction for the interaction. + */ + system_instruction?: string; + /** + * Body param: A list of tool declarations the model may call during interaction. + */ + tools?: Array<Tool_2>; +} + +declare interface BaseCreateModelInteractionParams { + /** + * Path param: Which version of the API to use. + */ + api_version?: string; + /** + * Body param: The inputs for the interaction. + */ + input: string | Array<Content_2> | Array<Turn> | TextContent | ImageContent | AudioContent | DocumentContent | VideoContent | ThoughtContent | FunctionCallContent | FunctionResultContent | CodeExecutionCallContent | CodeExecutionResultContent | URLContextCallContent | URLContextResultContent | GoogleSearchCallContent | GoogleSearchResultContent | MCPServerToolCallContent | MCPServerToolResultContent | FileSearchCallContent | FileSearchResultContent; + /** + * Body param: The name of the `Model` used for generating the interaction. + */ + model: Model_2; + /** + * Body param: Input only. Whether to run the model interaction in the background. + */ + background?: boolean; + /** + * Body param: Input only. Configuration parameters for the model interaction. + */ + generation_config?: GenerationConfig_2; + /** + * Body param: The ID of the previous interaction, if any. + */ + previous_interaction_id?: string; + /** + * Body param: Enforces that the generated response is a JSON object that complies with + * the JSON schema specified in this field. + */ + response_format?: unknown; + /** + * Body param: The mime type of the response. This is required if response_format is set. + */ + response_mime_type?: string; + /** + * Body param: The requested modalities of the response (TEXT, IMAGE, AUDIO). + */ + response_modalities?: Array<'text' | 'image' | 'audio'>; + /** + * Body param: Input only. Whether to store the response and request for later retrieval. + */ + store?: boolean; + /** + * Body param: Input only. Whether the interaction will be streamed. + */ + stream?: boolean; + /** + * Body param: System instruction for the interaction. + */ + system_instruction?: string; + /** + * Body param: A list of tool declarations the model may call during interaction. + */ + tools?: Array<Tool_2>; +} + +/** + * Base class for Gemini Next Gen API API clients. + */ +declare class BaseGeminiNextGenAPIClient { + apiKey: string | null; + apiVersion: string; + baseURL: string; + maxRetries: number; + timeout: number; + logger: Logger; + logLevel: LogLevel | undefined; + fetchOptions: MergedRequestInit | undefined; + private fetch; + private encoder; + protected idempotencyHeader?: string; + private _options; + private clientAdapter; + /** + * API Client for interfacing with the Gemini Next Gen API API. + * + * @param {string | null | undefined} [opts.apiKey=process.env['GEMINI_API_KEY'] ?? null] + * @param {string | undefined} [opts.apiVersion=v1beta] + * @param {string} [opts.baseURL=process.env['GEMINI_NEXT_GEN_API_BASE_URL'] ?? https://generativelanguage.googleapis.com] - Override the default base URL for the API. + * @param {number} [opts.timeout=1 minute] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out. + * @param {MergedRequestInit} [opts.fetchOptions] - Additional `RequestInit` options to be passed to `fetch` calls. + * @param {Fetch} [opts.fetch] - Specify a custom `fetch` function implementation. + * @param {number} [opts.maxRetries=2] - The maximum number of times the client will retry a request. + * @param {HeadersLike} opts.defaultHeaders - Default headers to include with every request to the API. + * @param {Record<string, string | undefined>} opts.defaultQuery - Default query parameters to include with every request to the API. + */ + constructor({ baseURL, apiKey, apiVersion, ...opts }: ClientOptions); + /** + * Create a new client instance re-using the same options given to the current client with optional overriding. + */ + withOptions(options: Partial<ClientOptions>): this; + /** + * Check whether the base URL is set to its default. + */ + private baseURLOverridden; + protected defaultQuery(): Record<string, string | undefined> | undefined; + protected validateHeaders({ values, nulls }: NullableHeaders): void; + protected authHeaders(opts: FinalRequestOptions): Promise<NullableHeaders | undefined>; + /** + * Basic re-implementation of `qs.stringify` for primitive types. + */ + protected stringifyQuery(query: Record<string, unknown>): string; + private getUserAgent; + protected defaultIdempotencyKey(): string; + protected makeStatusError(status: number, error: Object, message: string | undefined, headers: Headers): Errors.APIError; + buildURL(path: string, query: Record<string, unknown> | null | undefined, defaultBaseURL?: string | undefined): string; + /** + * Used as a callback for mutating the given `FinalRequestOptions` object. + + */ + protected prepareOptions(options: FinalRequestOptions): Promise<void>; + /** + * Used as a callback for mutating the given `RequestInit` object. + * + * This is useful for cases where you want to add certain headers based off of + * the request properties, e.g. `method` or `url`. + */ + protected prepareRequest(request: _RequestInit, { url, options }: { + url: string; + options: FinalRequestOptions; + }): Promise<void>; + get<Rsp>(path: string, opts?: PromiseOrValue<RequestOptions>): APIPromise<Rsp>; + post<Rsp>(path: string, opts?: PromiseOrValue<RequestOptions>): APIPromise<Rsp>; + patch<Rsp>(path: string, opts?: PromiseOrValue<RequestOptions>): APIPromise<Rsp>; + put<Rsp>(path: string, opts?: PromiseOrValue<RequestOptions>): APIPromise<Rsp>; + delete<Rsp>(path: string, opts?: PromiseOrValue<RequestOptions>): APIPromise<Rsp>; + private methodRequest; + request<Rsp>(options: PromiseOrValue<FinalRequestOptions>, remainingRetries?: number | null): APIPromise<Rsp>; + private makeRequest; + fetchWithTimeout(url: _RequestInfo, init: _RequestInit | undefined, ms: number, controller: AbortController): Promise<Response>; + private shouldRetry; + private retryRequest; + private calculateDefaultRetryTimeoutMillis; + buildRequest(inputOptions: FinalRequestOptions, { retryCount }?: { + retryCount?: number; + }): Promise<{ + req: FinalizedRequestInit; + url: string; + timeout: number; + }>; + private buildHeaders; + private _makeAbort; + private buildBody; + static DEFAULT_TIMEOUT: number; +} + +declare class BaseInteractions extends APIResource { + static readonly _key: readonly ['interactions']; + /** + * Creates a new interaction. + * + * @example + * ```ts + * const interaction = await client.interactions.create({ + * api_version: 'api_version', + * input: 'string', + * model: 'gemini-2.5-flash', + * }); + * ``` + */ + create(params: CreateModelInteractionParamsNonStreaming, options?: RequestOptions): APIPromise<Interaction>; + create(params: CreateModelInteractionParamsStreaming, options?: RequestOptions): APIPromise<Stream<InteractionSSEEvent>>; + create(params: CreateAgentInteractionParamsNonStreaming, options?: RequestOptions): APIPromise<Interaction>; + create(params: CreateAgentInteractionParamsStreaming, options?: RequestOptions): APIPromise<Stream<InteractionSSEEvent>>; + create(params: BaseCreateModelInteractionParams | BaseCreateAgentInteractionParams, options?: RequestOptions): APIPromise<Stream<InteractionSSEEvent> | Interaction>; + /** + * Deletes the interaction by id. + * + * @example + * ```ts + * const interaction = await client.interactions.delete('id', { + * api_version: 'api_version', + * }); + * ``` + */ + delete(id: string, params?: InteractionDeleteParams | null | undefined, options?: RequestOptions): APIPromise<unknown>; + /** + * Cancels an interaction by id. This only applies to background interactions that are still running. + * + * @example + * ```ts + * const interaction = await client.interactions.cancel('id', { + * api_version: 'api_version', + * }); + * ``` + */ + cancel(id: string, params?: InteractionCancelParams | null | undefined, options?: RequestOptions): APIPromise<Interaction>; + /** + * Retrieves the full details of a single interaction based on its `Interaction.id`. + * + * @example + * ```ts + * const interaction = await client.interactions.get('id', { + * api_version: 'api_version', + * }); + * ``` + */ + get(id: string, params?: InteractionGetParamsNonStreaming, options?: RequestOptions): APIPromise<Interaction>; + get(id: string, params: InteractionGetParamsStreaming, options?: RequestOptions): APIPromise<Stream<InteractionSSEEvent>>; + get(id: string, params?: InteractionGetParamsBase | undefined, options?: RequestOptions): APIPromise<Stream<InteractionSSEEvent> | Interaction>; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +declare class BaseModule { +} + +/** + * Parameters for setting the base URLs for the Gemini API and Vertex AI API. + */ +export declare interface BaseUrlParameters { + geminiUrl?: string; + vertexUrl?: string; +} + +export declare class Batches extends BaseModule { + private readonly apiClient; + constructor(apiClient: ApiClient); + /** + * Lists batch jobs. + * + * @param params - The parameters for the list request. + * @return - A pager of batch jobs. + * + * @example + * ```ts + * const batchJobs = await ai.batches.list({config: {'pageSize': 2}}); + * for await (const batchJob of batchJobs) { + * console.log(batchJob); + * } + * ``` + */ + list: (params?: types.ListBatchJobsParameters) => Promise<Pager<types.BatchJob>>; + /** + * Create batch job. + * + * @param params - The parameters for create batch job request. + * @return The created batch job. + * + * @example + * ```ts + * const response = await ai.batches.create({ + * model: 'gemini-2.0-flash', + * src: {gcsUri: 'gs://bucket/path/to/file.jsonl', format: 'jsonl'}, + * config: { + * dest: {gcsUri: 'gs://bucket/path/output/directory', format: 'jsonl'}, + * } + * }); + * console.log(response); + * ``` + */ + create: (params: types.CreateBatchJobParameters) => Promise<types.BatchJob>; + /** + * **Experimental** Creates an embedding batch job. + * + * @param params - The parameters for create embedding batch job request. + * @return The created batch job. + * + * @example + * ```ts + * const response = await ai.batches.createEmbeddings({ + * model: 'text-embedding-004', + * src: {fileName: 'files/my_embedding_input'}, + * }); + * console.log(response); + * ``` + */ + createEmbeddings: (params: types.CreateEmbeddingsBatchJobParameters) => Promise<types.BatchJob>; + private createInlinedGenerateContentRequest; + private getGcsUri; + private getBigqueryUri; + private formatDestination; + /** + * Internal method to create batch job. + * + * @param params - The parameters for create batch job request. + * @return The created batch job. + * + */ + private createInternal; + /** + * Internal method to create batch job. + * + * @param params - The parameters for create batch job request. + * @return The created batch job. + * + */ + private createEmbeddingsInternal; + /** + * Gets batch job configurations. + * + * @param params - The parameters for the get request. + * @return The batch job. + * + * @example + * ```ts + * await ai.batches.get({name: '...'}); // The server-generated resource name. + * ``` + */ + get(params: types.GetBatchJobParameters): Promise<types.BatchJob>; + /** + * Cancels a batch job. + * + * @param params - The parameters for the cancel request. + * @return The empty response returned by the API. + * + * @example + * ```ts + * await ai.batches.cancel({name: '...'}); // The server-generated resource name. + * ``` + */ + cancel(params: types.CancelBatchJobParameters): Promise<void>; + private listInternal; + /** + * Deletes a batch job. + * + * @param params - The parameters for the delete request. + * @return The empty response returned by the API. + * + * @example + * ```ts + * await ai.batches.delete({name: '...'}); // The server-generated resource name. + * ``` + */ + delete(params: types.DeleteBatchJobParameters): Promise<types.DeleteResourceJob>; +} + +/** Config for batches.create return value. */ +export declare interface BatchJob { + /** The resource name of the BatchJob. Output only.". + */ + name?: string; + /** The display name of the BatchJob. + */ + displayName?: string; + /** The state of the BatchJob. + */ + state?: JobState; + /** Output only. Only populated when the job's state is JOB_STATE_FAILED or JOB_STATE_CANCELLED. */ + error?: JobError; + /** The time when the BatchJob was created. + */ + createTime?: string; + /** Output only. Time when the Job for the first time entered the `JOB_STATE_RUNNING` state. */ + startTime?: string; + /** The time when the BatchJob was completed. This field is for Vertex AI only. + */ + endTime?: string; + /** The time when the BatchJob was last updated. + */ + updateTime?: string; + /** The name of the model that produces the predictions via the BatchJob. + */ + model?: string; + /** Configuration for the input data. This field is for Vertex AI only. + */ + src?: BatchJobSource; + /** Configuration for the output data. + */ + dest?: BatchJobDestination; + /** Statistics on completed and failed prediction instances. This field is for Vertex AI only. + */ + completionStats?: CompletionStats; +} + +/** Config for `des` parameter. */ +export declare interface BatchJobDestination { + /** Storage format of the output files. Must be one of: + 'jsonl', 'bigquery'. + */ + format?: string; + /** The Google Cloud Storage URI to the output file. + */ + gcsUri?: string; + /** The BigQuery URI to the output table. + */ + bigqueryUri?: string; + /** The Gemini Developer API's file resource name of the output data + (e.g. "files/12345"). The file will be a JSONL file with a single response + per line. The responses will be GenerateContentResponse messages formatted + as JSON. The responses will be written in the same order as the input + requests. + */ + fileName?: string; + /** The responses to the requests in the batch. Returned when the batch was + built using inlined requests. The responses will be in the same order as + the input requests. + */ + inlinedResponses?: InlinedResponse[]; + /** The responses to the requests in the batch. Returned when the batch was + built using inlined requests. The responses will be in the same order as + the input requests. + */ + inlinedEmbedContentResponses?: InlinedEmbedContentResponse[]; +} + +export declare type BatchJobDestinationUnion = BatchJobDestination | string; + +/** Config for `src` parameter. */ +export declare interface BatchJobSource { + /** Storage format of the input files. Must be one of: + 'jsonl', 'bigquery'. + */ + format?: string; + /** The Google Cloud Storage URIs to input files. + */ + gcsUri?: string[]; + /** The BigQuery URI to input table. + */ + bigqueryUri?: string; + /** The Gemini Developer API's file resource name of the input data + (e.g. "files/12345"). + */ + fileName?: string; + /** The Gemini Developer API's inlined input data to run batch job. + */ + inlinedRequests?: InlinedRequest[]; +} + +export declare type BatchJobSourceUnion = BatchJobSource | InlinedRequest[] | string; + +/** Specifies the function Behavior. Currently only supported by the BidiGenerateContent method. This enum is not supported in Vertex AI. */ +export declare enum Behavior { + /** + * This value is unused. + */ + UNSPECIFIED = "UNSPECIFIED", + /** + * If set, the system will wait to receive the function response before continuing the conversation. + */ + BLOCKING = "BLOCKING", + /** + * If set, the system will not wait to receive the function response. Instead, it will attempt to handle function responses as they become available while maintaining the conversation between the user and the model. + */ + NON_BLOCKING = "NON_BLOCKING" +} + +/** Content blob. */ +declare interface Blob_2 { + /** Required. Raw bytes. + * @remarks Encoded as base64 string. */ + data?: string; + /** Optional. Display name of the blob. Used to provide a label or filename to distinguish blobs. This field is only returned in PromptMessage for prompt management. It is currently used in the Gemini GenerateContent calls only when server side tools (code_execution, google_search, and url_context) are enabled. This field is not supported in Gemini API. */ + displayName?: string; + /** Required. The IANA standard MIME type of the source data. */ + mimeType?: string; +} +export { Blob_2 as Blob } + +export declare type BlobImageUnion = Blob_2; + +/** Output only. The reason why the prompt was blocked. */ +export declare enum BlockedReason { + /** + * The blocked reason is unspecified. + */ + BLOCKED_REASON_UNSPECIFIED = "BLOCKED_REASON_UNSPECIFIED", + /** + * The prompt was blocked for safety reasons. + */ + SAFETY = "SAFETY", + /** + * The prompt was blocked for other reasons. For example, it may be due to the prompt's language, or because it contains other harmful content. + */ + OTHER = "OTHER", + /** + * The prompt was blocked because it contains a term from the terminology blocklist. + */ + BLOCKLIST = "BLOCKLIST", + /** + * The prompt was blocked because it contains prohibited content. + */ + PROHIBITED_CONTENT = "PROHIBITED_CONTENT", + /** + * The prompt was blocked because it contains content that is unsafe for image generation. + */ + IMAGE_SAFETY = "IMAGE_SAFETY", + /** + * The prompt was blocked by Model Armor. This enum value is not supported in Gemini API. + */ + MODEL_ARMOR = "MODEL_ARMOR", + /** + * The prompt was blocked as a jailbreak attempt. This enum value is not supported in Gemini API. + */ + JAILBREAK = "JAILBREAK" +} + +declare const brand_privateNullableHeaders: unique symbol; + +/** @ts-ignore For users with \@types/bun */ +declare type BunRequestInit = globalThis.FetchRequestInit; + +/** A resource used in LLM queries for users to explicitly specify what to cache. */ +export declare interface CachedContent { + /** The server-generated resource name of the cached content. */ + name?: string; + /** The user-generated meaningful display name of the cached content. */ + displayName?: string; + /** The name of the publisher model to use for cached content. */ + model?: string; + /** Creation time of the cache entry. */ + createTime?: string; + /** When the cache entry was last updated in UTC time. */ + updateTime?: string; + /** Expiration time of the cached content. */ + expireTime?: string; + /** Metadata on the usage of the cached content. */ + usageMetadata?: CachedContentUsageMetadata; +} + +/** Metadata on the usage of the cached content. */ +export declare interface CachedContentUsageMetadata { + /** Duration of audio in seconds. This field is not supported in Gemini API. */ + audioDurationSeconds?: number; + /** Number of images. This field is not supported in Gemini API. */ + imageCount?: number; + /** Number of text characters. This field is not supported in Gemini API. */ + textCount?: number; + /** Total number of tokens that the cached content consumes. */ + totalTokenCount?: number; + /** Duration of video in seconds. This field is not supported in Gemini API. */ + videoDurationSeconds?: number; +} + +export declare class Caches extends BaseModule { + private readonly apiClient; + constructor(apiClient: ApiClient); + /** + * Lists cached contents. + * + * @param params - The parameters for the list request. + * @return - A pager of cached contents. + * + * @example + * ```ts + * const cachedContents = await ai.caches.list({config: {'pageSize': 2}}); + * for await (const cachedContent of cachedContents) { + * console.log(cachedContent); + * } + * ``` + */ + list: (params?: types.ListCachedContentsParameters) => Promise<Pager<types.CachedContent>>; + /** + * Creates a cached contents resource. + * + * @remarks + * Context caching is only supported for specific models. See [Gemini + * Developer API reference](https://ai.google.dev/gemini-api/docs/caching?lang=node/context-cac) + * and [Vertex AI reference](https://cloud.google.com/vertex-ai/generative-ai/docs/context-cache/context-cache-overview#supported_models) + * for more information. + * + * @param params - The parameters for the create request. + * @return The created cached content. + * + * @example + * ```ts + * const contents = ...; // Initialize the content to cache. + * const response = await ai.caches.create({ + * model: 'gemini-2.0-flash-001', + * config: { + * 'contents': contents, + * 'displayName': 'test cache', + * 'systemInstruction': 'What is the sum of the two pdfs?', + * 'ttl': '86400s', + * } + * }); + * ``` + */ + create(params: types.CreateCachedContentParameters): Promise<types.CachedContent>; + /** + * Gets cached content configurations. + * + * @param params - The parameters for the get request. + * @return The cached content. + * + * @example + * ```ts + * await ai.caches.get({name: '...'}); // The server-generated resource name. + * ``` + */ + get(params: types.GetCachedContentParameters): Promise<types.CachedContent>; + /** + * Deletes cached content. + * + * @param params - The parameters for the delete request. + * @return The empty response returned by the API. + * + * @example + * ```ts + * await ai.caches.delete({name: '...'}); // The server-generated resource name. + * ``` + */ + delete(params: types.DeleteCachedContentParameters): Promise<types.DeleteCachedContentResponse>; + /** + * Updates cached content configurations. + * + * @param params - The parameters for the update request. + * @return The updated cached content. + * + * @example + * ```ts + * const response = await ai.caches.update({ + * name: '...', // The server-generated resource name. + * config: {'ttl': '7600s'} + * }); + * ``` + */ + update(params: types.UpdateCachedContentParameters): Promise<types.CachedContent>; + private listInternal; +} + +/** + * CallableTool is an invokable tool that can be executed with external + * application (e.g., via Model Context Protocol) or local functions with + * function calling. + */ +export declare interface CallableTool { + /** + * Returns tool that can be called by Gemini. + */ + tool(): Promise<Tool>; + /** + * Executes the callable tool with the given function call arguments and + * returns the response parts from the tool execution. + */ + callTool(functionCalls: FunctionCall[]): Promise<Part[]>; +} + +/** + * CallableToolConfig is the configuration for a callable tool. + */ +export declare interface CallableToolConfig { + /** + * Specifies the model's behavior after invoking this tool. + */ + behavior?: Behavior; + /** + * Timeout for remote calls in milliseconds. Note this timeout applies only to + * tool remote calls, and not making HTTP requests to the API. */ + timeout?: number; +} + +/** Optional parameters. */ +export declare interface CancelBatchJobConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Config for batches.cancel parameters. */ +export declare interface CancelBatchJobParameters { + /** A fully-qualified BatchJob resource name or ID. + Example: "projects/.../locations/.../batchPredictionJobs/456" + or "456" when project and location are initialized in the client. + */ + name: string; + /** Optional parameters for the request. */ + config?: CancelBatchJobConfig; +} + +/** Optional parameters for tunings.cancel method. */ +export declare interface CancelTuningJobConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Parameters for the cancel method. */ +export declare interface CancelTuningJobParameters { + /** The resource name of the tuning job. */ + name: string; + /** Optional parameters for the request. */ + config?: CancelTuningJobConfig; +} + +/** Empty response for tunings.cancel method. */ +export declare class CancelTuningJobResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; +} + +/** A response candidate generated from the model. */ +export declare interface Candidate { + /** Contains the multi-part content of the response. + */ + content?: Content; + /** Source attribution of the generated content. + */ + citationMetadata?: CitationMetadata; + /** Describes the reason the model stopped generating tokens. + */ + finishMessage?: string; + /** Number of tokens for this candidate. + */ + tokenCount?: number; + /** The reason why the model stopped generating tokens. + If empty, the model has not stopped generating the tokens. + */ + finishReason?: FinishReason; + /** Output only. Average log probability score of the candidate. */ + avgLogprobs?: number; + /** Output only. Metadata specifies sources used to ground generated content. */ + groundingMetadata?: GroundingMetadata; + /** Output only. Index of the candidate. */ + index?: number; + /** Output only. Log-likelihood scores for the response tokens and top tokens */ + logprobsResult?: LogprobsResult; + /** Output only. List of ratings for the safety of a response candidate. There is at most one rating per category. */ + safetyRatings?: SafetyRating[]; + /** Output only. Metadata related to url context retrieval tool. */ + urlContextMetadata?: UrlContextMetadata; +} + +/** + * Chat session that enables sending messages to the model with previous + * conversation context. + * + * @remarks + * The session maintains all the turns between user and model. + */ +export declare class Chat { + private readonly apiClient; + private readonly modelsModule; + private readonly model; + private readonly config; + private history; + private sendPromise; + constructor(apiClient: ApiClient, modelsModule: Models, model: string, config?: types.GenerateContentConfig, history?: types.Content[]); + /** + * Sends a message to the model and returns the response. + * + * @remarks + * This method will wait for the previous message to be processed before + * sending the next message. + * + * @see {@link Chat#sendMessageStream} for streaming method. + * @param params - parameters for sending messages within a chat session. + * @returns The model's response. + * + * @example + * ```ts + * const chat = ai.chats.create({model: 'gemini-2.0-flash'}); + * const response = await chat.sendMessage({ + * message: 'Why is the sky blue?' + * }); + * console.log(response.text); + * ``` + */ + sendMessage(params: types.SendMessageParameters): Promise<types.GenerateContentResponse>; + /** + * Sends a message to the model and returns the response in chunks. + * + * @remarks + * This method will wait for the previous message to be processed before + * sending the next message. + * + * @see {@link Chat#sendMessage} for non-streaming method. + * @param params - parameters for sending the message. + * @return The model's response. + * + * @example + * ```ts + * const chat = ai.chats.create({model: 'gemini-2.0-flash'}); + * const response = await chat.sendMessageStream({ + * message: 'Why is the sky blue?' + * }); + * for await (const chunk of response) { + * console.log(chunk.text); + * } + * ``` + */ + sendMessageStream(params: types.SendMessageParameters): Promise<AsyncGenerator<types.GenerateContentResponse>>; + /** + * Returns the chat history. + * + * @remarks + * The history is a list of contents alternating between user and model. + * + * There are two types of history: + * - The `curated history` contains only the valid turns between user and + * model, which will be included in the subsequent requests sent to the model. + * - The `comprehensive history` contains all turns, including invalid or + * empty model outputs, providing a complete record of the history. + * + * The history is updated after receiving the response from the model, + * for streaming response, it means receiving the last chunk of the response. + * + * The `comprehensive history` is returned by default. To get the `curated + * history`, set the `curated` parameter to `true`. + * + * @param curated - whether to return the curated history or the comprehensive + * history. + * @return History contents alternating between user and model for the entire + * chat session. + */ + getHistory(curated?: boolean): types.Content[]; + private processStreamResponse; + private recordHistory; +} + +/** + * A utility class to create a chat session. + */ +export declare class Chats { + private readonly modelsModule; + private readonly apiClient; + constructor(modelsModule: Models, apiClient: ApiClient); + /** + * Creates a new chat session. + * + * @remarks + * The config in the params will be used for all requests within the chat + * session unless overridden by a per-request `config` in + * @see {@link types.SendMessageParameters#config}. + * + * @param params - Parameters for creating a chat session. + * @returns A new chat session. + * + * @example + * ```ts + * const chat = ai.chats.create({ + * model: 'gemini-2.0-flash' + * config: { + * temperature: 0.5, + * maxOutputTokens: 1024, + * } + * }); + * ``` + */ + create(params: types.CreateChatParameters): Chat; +} + +/** Describes the machine learning model version checkpoint. */ +export declare interface Checkpoint { + /** The ID of the checkpoint. + */ + checkpointId?: string; + /** The epoch of the checkpoint. + */ + epoch?: string; + /** The step of the checkpoint. + */ + step?: string; +} + +/** Config for telling the service how to chunk the file. */ +export declare interface ChunkingConfig { + /** White space chunking configuration. */ + whiteSpaceConfig?: WhiteSpaceConfig; +} + +/** Source attributions for content. This data type is not supported in Gemini API. */ +export declare interface Citation { + /** Output only. End index into the content. */ + endIndex?: number; + /** Output only. License of the attribution. */ + license?: string; + /** Output only. Publication date of the attribution. */ + publicationDate?: GoogleTypeDate; + /** Output only. Start index into the content. */ + startIndex?: number; + /** Output only. Title of the attribution. */ + title?: string; + /** Output only. Url reference of the attribution. */ + uri?: string; +} + +/** Citation information when the model quotes another source. */ +export declare interface CitationMetadata { + /** Contains citation information when the model directly quotes, at + length, from another source. Can include traditional websites and code + repositories. + */ + citations?: Citation[]; +} + +declare interface ClientOptions { + /** + * Defaults to process.env['GEMINI_API_KEY']. + */ + apiKey?: string | null | undefined; + apiVersion?: string | undefined; + /** + * Override the default base URL for the API, e.g., "https://api.example.com/v2/" + * + * Defaults to process.env['GEMINI_NEXT_GEN_API_BASE_URL']. + */ + baseURL?: string | null | undefined; + /** + * The maximum amount of time (in milliseconds) that the client should wait for a response + * from the server before timing out a single request. + * + * Note that request timeouts are retried by default, so in a worst-case scenario you may wait + * much longer than this timeout before the promise succeeds or fails. + * + * @unit milliseconds + */ + timeout?: number | undefined; + /** + * Additional `RequestInit` options to be passed to `fetch` calls. + * Properties will be overridden by per-request `fetchOptions`. + */ + fetchOptions?: MergedRequestInit | undefined; + /** + * Specify a custom `fetch` function implementation. + * + * If not provided, we expect that `fetch` is defined globally. + */ + fetch?: Fetch | undefined; + /** + * The maximum number of times that the client will retry a request in case of a + * temporary failure, like a network error or a 5XX error from the server. + * + * @default 2 + */ + maxRetries?: number | undefined; + /** + * Default headers to include with every request to the API. + * + * These can be removed in individual requests by explicitly setting the + * header to `null` in request options. + */ + defaultHeaders?: HeadersLike | undefined; + /** + * Default query parameters to include with every request to the API. + * + * These can be removed in individual requests by explicitly setting the + * param to `undefined` in request options. + */ + defaultQuery?: Record<string, string | undefined> | undefined; + /** + * Set the log level. + * + * Defaults to process.env['GEMINI_NEXT_GEN_API_LOG'] or 'warn' if it isn't set. + */ + logLevel?: LogLevel | undefined; + /** + * Set the logger. + * + * Defaults to globalThis.console. + */ + logger?: Logger | undefined; + /** + * The adapter to the parent API client instance (for accessing auth, project, location) + */ + clientAdapter: GeminiNextGenAPIClientAdapter; +} + +/** + * The arguments to pass to the code execution. + */ +declare interface CodeExecutionCallArguments { + /** + * The code to be executed. + */ + code?: string; + /** + * Programming language of the `code`. + */ + language?: 'python'; +} + +/** + * Code execution content. + */ +declare interface CodeExecutionCallContent { + type: 'code_execution_call'; + /** + * A unique ID for this specific tool call. + */ + id?: string; + /** + * The arguments to pass to the code execution. + */ + arguments?: CodeExecutionCallArguments; +} + +/** Result of executing the [ExecutableCode]. Only generated when using the [CodeExecution] tool, and always follows a `part` containing the [ExecutableCode]. */ +export declare interface CodeExecutionResult { + /** Required. Outcome of the code execution. */ + outcome?: Outcome; + /** Optional. Contains stdout when code execution is successful, stderr or other description otherwise. */ + output?: string; +} + +/** + * Code execution result content. + */ +declare interface CodeExecutionResultContent { + type: 'code_execution_result'; + /** + * ID to match the ID from the code execution call block. + */ + call_id?: string; + /** + * Whether the code execution resulted in an error. + */ + is_error?: boolean; + /** + * The output of the code execution. + */ + result?: string; + /** + * A signature hash for backend validation. + */ + signature?: string; +} + +/** Success and error statistics of processing multiple entities (for example, DataItems or structured data rows) in batch. This data type is not supported in Gemini API. */ +export declare interface CompletionStats { + /** Output only. The number of entities for which any error was encountered. */ + failedCount?: string; + /** Output only. In cases when enough errors are encountered a job, pipeline, or operation may be failed as a whole. Below is the number of entities for which the processing had not been finished (either in successful or failed state). Set to -1 if the number is unknown (for example, the operation failed before the total entity number could be collected). */ + incompleteCount?: string; + /** Output only. The number of entities that had been processed successfully. */ + successfulCount?: string; + /** Output only. The number of the successful forecast points that are generated by the forecasting model. This is ONLY used by the forecasting batch prediction. */ + successfulForecastPointCount?: string; +} + +/** Tool to support computer use. */ +export declare interface ComputerUse { + /** Required. The environment being operated. */ + environment?: Environment; + /** By default, predefined functions are included in the final model call. + Some of them can be explicitly excluded from being automatically included. + This can serve two purposes: + 1. Using a more restricted / different action space. + 2. Improving the definitions / instructions of predefined functions. */ + excludedPredefinedFunctions?: string[]; +} + +/** Optional parameters for computing tokens. */ +export declare interface ComputeTokensConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Parameters for computing tokens. */ +export declare interface ComputeTokensParameters { + /** ID of the model to use. For a list of models, see `Google models + <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */ + model: string; + /** Input content. */ + contents: ContentListUnion; + /** Optional parameters for the request. + */ + config?: ComputeTokensConfig; +} + +/** Response for computing tokens. */ +export declare class ComputeTokensResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** Lists of tokens info from the input. A ComputeTokensRequest could have multiple instances with a prompt in each instance. We also need to return lists of tokens info for the request with multiple instances. */ + tokensInfo?: TokensInfo[]; +} + +/** Local tokenizer compute tokens result. */ +export declare interface ComputeTokensResult { + /** Lists of tokens info from the input. */ + tokensInfo?: TokensInfo[]; +} + +declare type _ConditionalNodeReadableStream<R = any> = typeof globalThis extends { + ReadableStream: any; +} ? never : _NodeReadableStream<R>; + +declare class ConflictError extends APIError<409, Headers> { +} + +/** Contains the multi-part content of a message. */ +export declare interface Content { + /** List of parts that constitute a single message. Each part may have + a different IANA MIME type. */ + parts?: Part[]; + /** Optional. The producer of the content. Must be either 'user' or 'model'. Useful to set for multi-turn conversations, otherwise can be left blank or unset. */ + role?: string; +} + +/** + * The content of the response. + */ +declare type Content_2 = TextContent | ImageContent | AudioContent | DocumentContent | VideoContent | ThoughtContent | FunctionCallContent | FunctionResultContent | CodeExecutionCallContent | CodeExecutionResultContent | URLContextCallContent | URLContextResultContent | GoogleSearchCallContent | GoogleSearchResultContent | MCPServerToolCallContent | MCPServerToolResultContent | FileSearchCallContent | FileSearchResultContent; + +declare interface ContentDelta { + delta?: ContentDelta.TextDelta | ContentDelta.ImageDelta | ContentDelta.AudioDelta | ContentDelta.DocumentDelta | ContentDelta.VideoDelta | ContentDelta.ThoughtSummaryDelta | ContentDelta.ThoughtSignatureDelta | ContentDelta.FunctionCallDelta | ContentDelta.FunctionResultDelta | ContentDelta.CodeExecutionCallDelta | ContentDelta.CodeExecutionResultDelta | ContentDelta.URLContextCallDelta | ContentDelta.URLContextResultDelta | ContentDelta.GoogleSearchCallDelta | ContentDelta.GoogleSearchResultDelta | ContentDelta.MCPServerToolCallDelta | ContentDelta.MCPServerToolResultDelta | ContentDelta.FileSearchCallDelta | ContentDelta.FileSearchResultDelta; + /** + * The event_id token to be used to resume the interaction stream, from this event. + */ + event_id?: string; + event_type?: 'content.delta'; + index?: number; +} + +declare namespace ContentDelta { + interface TextDelta { + type: 'text'; + /** + * Citation information for model-generated content. + */ + annotations?: Array<InteractionsAPI.Annotation>; + text?: string; + } + interface ImageDelta { + type: 'image'; + data?: string; + /** + * The mime type of the image. + */ + mime_type?: InteractionsAPI.ImageMimeType; + /** + * The resolution of the media. + */ + resolution?: 'low' | 'medium' | 'high' | 'ultra_high'; + uri?: string; + } + interface AudioDelta { + type: 'audio'; + data?: string; + /** + * The mime type of the audio. + */ + mime_type?: InteractionsAPI.AudioMimeType; + uri?: string; + } + interface DocumentDelta { + type: 'document'; + data?: string; + /** + * The mime type of the document. + */ + mime_type?: InteractionsAPI.DocumentMimeType; + uri?: string; + } + interface VideoDelta { + type: 'video'; + data?: string; + /** + * The mime type of the video. + */ + mime_type?: InteractionsAPI.VideoMimeType; + /** + * The resolution of the media. + */ + resolution?: 'low' | 'medium' | 'high' | 'ultra_high'; + uri?: string; + } + interface ThoughtSummaryDelta { + type: 'thought_summary'; + /** + * A text content block. + */ + content?: InteractionsAPI.TextContent | InteractionsAPI.ImageContent; + } + interface ThoughtSignatureDelta { + type: 'thought_signature'; + /** + * Signature to match the backend source to be part of the generation. + */ + signature?: string; + } + interface FunctionCallDelta { + type: 'function_call'; + /** + * A unique ID for this specific tool call. + */ + id?: string; + arguments?: { + [key: string]: unknown; + }; + name?: string; + } + interface FunctionResultDelta { + type: 'function_result'; + /** + * ID to match the ID from the function call block. + */ + call_id?: string; + is_error?: boolean; + name?: string; + /** + * Tool call result delta. + */ + result?: FunctionResultDelta.Items | unknown | string; + } + namespace FunctionResultDelta { + interface Items { + items?: Array<InteractionsAPI.TextContent | InteractionsAPI.ImageContent>; + } + } + interface CodeExecutionCallDelta { + type: 'code_execution_call'; + /** + * A unique ID for this specific tool call. + */ + id?: string; + /** + * The arguments to pass to the code execution. + */ + arguments?: InteractionsAPI.CodeExecutionCallArguments; + } + interface CodeExecutionResultDelta { + type: 'code_execution_result'; + /** + * ID to match the ID from the function call block. + */ + call_id?: string; + is_error?: boolean; + result?: string; + signature?: string; + } + interface URLContextCallDelta { + type: 'url_context_call'; + /** + * A unique ID for this specific tool call. + */ + id?: string; + /** + * The arguments to pass to the URL context. + */ + arguments?: InteractionsAPI.URLContextCallArguments; + } + interface URLContextResultDelta { + type: 'url_context_result'; + /** + * ID to match the ID from the function call block. + */ + call_id?: string; + is_error?: boolean; + result?: Array<InteractionsAPI.URLContextResult>; + signature?: string; + } + interface GoogleSearchCallDelta { + type: 'google_search_call'; + /** + * A unique ID for this specific tool call. + */ + id?: string; + /** + * The arguments to pass to Google Search. + */ + arguments?: InteractionsAPI.GoogleSearchCallArguments; + } + interface GoogleSearchResultDelta { + type: 'google_search_result'; + /** + * ID to match the ID from the function call block. + */ + call_id?: string; + is_error?: boolean; + result?: Array<InteractionsAPI.GoogleSearchResult>; + signature?: string; + } + interface MCPServerToolCallDelta { + type: 'mcp_server_tool_call'; + /** + * A unique ID for this specific tool call. + */ + id?: string; + arguments?: { + [key: string]: unknown; + }; + name?: string; + server_name?: string; + } + interface MCPServerToolResultDelta { + type: 'mcp_server_tool_result'; + /** + * ID to match the ID from the function call block. + */ + call_id?: string; + name?: string; + /** + * Tool call result delta. + */ + result?: MCPServerToolResultDelta.Items | unknown | string; + server_name?: string; + } + namespace MCPServerToolResultDelta { + interface Items { + items?: Array<InteractionsAPI.TextContent | InteractionsAPI.ImageContent>; + } + } + interface FileSearchCallDelta { + type: 'file_search_call'; + /** + * A unique ID for this specific tool call. + */ + id?: string; + } + interface FileSearchResultDelta { + type: 'file_search_result'; + result?: Array<FileSearchResultDelta.Result>; + } + namespace FileSearchResultDelta { + /** + * The result of the File Search. + */ + interface Result { + /** + * The name of the file search store. + */ + file_search_store?: string; + /** + * The text of the search result. + */ + text?: string; + /** + * The title of the search result. + */ + title?: string; + } + } +} + +/** The embedding generated from an input content. */ +export declare interface ContentEmbedding { + /** A list of floats representing an embedding. + */ + values?: number[]; + /** Vertex API only. Statistics of the input text associated with this + embedding. + */ + statistics?: ContentEmbeddingStatistics; +} + +/** Statistics of the input text associated with the result of content embedding. */ +export declare interface ContentEmbeddingStatistics { + /** Vertex API only. If the input text was truncated due to having + a length longer than the allowed maximum input. + */ + truncated?: boolean; + /** Vertex API only. Number of tokens of the input text. + */ + tokenCount?: number; +} + +export declare type ContentListUnion = Content | Content[] | PartUnion | PartUnion[]; + +/** A content reference image. + + A content reference image represents a subject to reference (ex. person, + product, animal) provided by the user. It can optionally be provided in + addition to a style reference image (ex. background, style reference). */ +export declare class ContentReferenceImage { + /** The reference image for the editing operation. */ + referenceImage?: Image_2; + /** The id of the reference image. */ + referenceId?: number; + /** The type of the reference image. Only set by the SDK. */ + referenceType?: string; + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI(): ReferenceImageAPIInternal; +} + +declare interface ContentStart { + /** + * The content of the response. + */ + content?: Content_2; + /** + * The event_id token to be used to resume the interaction stream, from this event. + */ + event_id?: string; + event_type?: 'content.start'; + index?: number; +} + +declare interface ContentStop { + /** + * The event_id token to be used to resume the interaction stream, from this event. + */ + event_id?: string; + event_type?: 'content.stop'; + index?: number; +} + +export declare type ContentUnion = Content | PartUnion[] | PartUnion; + +/** Enables context window compression -- mechanism managing model context window so it does not exceed given length. */ +export declare interface ContextWindowCompressionConfig { + /** Number of tokens (before running turn) that triggers context window compression mechanism. */ + triggerTokens?: string; + /** Sliding window compression mechanism. */ + slidingWindow?: SlidingWindow; +} + +/** Configuration for a Control reference image. */ +export declare interface ControlReferenceConfig { + /** The type of control reference image to use. */ + controlType?: ControlReferenceType; + /** Defaults to False. When set to True, the control image will be + computed by the model based on the control type. When set to False, + the control image must be provided by the user. */ + enableControlImageComputation?: boolean; +} + +/** A control reference image. + + The image of the control reference image is either a control image provided + by the user, or a regular image which the backend will use to generate a + control image of. In the case of the latter, the + enable_control_image_computation field in the config should be set to True. + + A control image is an image that represents a sketch image of areas for the + model to fill in based on the prompt. */ +export declare class ControlReferenceImage { + /** The reference image for the editing operation. */ + referenceImage?: Image_2; + /** The id of the reference image. */ + referenceId?: number; + /** The type of the reference image. Only set by the SDK. */ + referenceType?: string; + /** Configuration for the control reference image. */ + config?: ControlReferenceConfig; + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI(): ReferenceImageAPIInternal; +} + +/** Enum representing the control type of a control reference image. */ +export declare enum ControlReferenceType { + CONTROL_TYPE_DEFAULT = "CONTROL_TYPE_DEFAULT", + CONTROL_TYPE_CANNY = "CONTROL_TYPE_CANNY", + CONTROL_TYPE_SCRIBBLE = "CONTROL_TYPE_SCRIBBLE", + CONTROL_TYPE_FACE_MESH = "CONTROL_TYPE_FACE_MESH" +} + +/** Config for the count_tokens method. */ +export declare interface CountTokensConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** Instructions for the model to steer it toward better performance. + */ + systemInstruction?: ContentUnion; + /** Code that enables the system to interact with external systems to + perform an action outside of the knowledge and scope of the model. + */ + tools?: Tool[]; + /** Configuration that the model uses to generate the response. Not + supported by the Gemini Developer API. + */ + generationConfig?: GenerationConfig; +} + +/** Parameters for counting tokens. */ +export declare interface CountTokensParameters { + /** ID of the model to use. For a list of models, see `Google models + <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */ + model: string; + /** Input content. */ + contents: ContentListUnion; + /** Configuration for counting tokens. */ + config?: CountTokensConfig; +} + +/** Response for counting tokens. */ +export declare class CountTokensResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** Total number of tokens. */ + totalTokens?: number; + /** Number of tokens in the cached part of the prompt (the cached content). */ + cachedContentTokenCount?: number; +} + +/** Local tokenizer count tokens result. */ +export declare interface CountTokensResult { + /** The total number of tokens. */ + totalTokens?: number; +} + +declare interface CreateAgentInteractionParamsNonStreaming extends BaseCreateAgentInteractionParams { + /** + * Body param: Input only. Whether the interaction will be streamed. + */ + stream?: false; +} + +declare interface CreateAgentInteractionParamsStreaming extends BaseCreateAgentInteractionParams { + /** + * Body param: Input only. Whether the interaction will be streamed. + */ + stream: true; +} + +/** Optional parameters. */ +export declare interface CreateAuthTokenConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** An optional time after which, when using the resulting token, + messages in Live API sessions will be rejected. (Gemini may + preemptively close the session after this time.) + + If not set then this defaults to 30 minutes in the future. If set, this + value must be less than 20 hours in the future. */ + expireTime?: string; + /** The time after which new Live API sessions using the token + resulting from this request will be rejected. + + If not set this defaults to 60 seconds in the future. If set, this value + must be less than 20 hours in the future. */ + newSessionExpireTime?: string; + /** The number of times the token can be used. If this value is zero + then no limit is applied. Default is 1. Resuming a Live API session does + not count as a use. */ + uses?: number; + /** Configuration specific to Live API connections created using this token. */ + liveConnectConstraints?: LiveConnectConstraints; + /** Additional fields to lock in the effective LiveConnectParameters. */ + lockAdditionalFields?: string[]; +} + +/** Config for auth_tokens.create parameters. */ +export declare interface CreateAuthTokenParameters { + /** Optional parameters for the request. */ + config?: CreateAuthTokenConfig; +} + +/** Config for optional parameters. */ +export declare interface CreateBatchJobConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** The user-defined name of this BatchJob. + */ + displayName?: string; + /** GCS or BigQuery URI prefix for the output predictions. Example: + "gs://path/to/output/data" or "bq://projectId.bqDatasetId.bqTableId". + */ + dest?: BatchJobDestinationUnion; +} + +/** Config for batches.create parameters. */ +export declare interface CreateBatchJobParameters { + /** The name of the model to produces the predictions via the BatchJob. + */ + model?: string; + /** GCS URI(-s) or BigQuery URI to your input data to run batch job. + Example: "gs://path/to/input/data" or "bq://projectId.bqDatasetId.bqTableId". + */ + src: BatchJobSourceUnion; + /** Optional parameters for creating a BatchJob. + */ + config?: CreateBatchJobConfig; +} + +/** Optional configuration for cached content creation. */ +export declare interface CreateCachedContentConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** The TTL for this resource. The expiration time is computed: now + TTL. It is a duration string, with up to nine fractional digits, terminated by 's'. Example: "3.5s". */ + ttl?: string; + /** Timestamp of when this resource is considered expired. Uses RFC 3339 format, Example: 2014-10-02T15:01:23Z. */ + expireTime?: string; + /** The user-generated meaningful display name of the cached content. + */ + displayName?: string; + /** The content to cache. + */ + contents?: ContentListUnion; + /** Developer set system instruction. + */ + systemInstruction?: ContentUnion; + /** A list of `Tools` the model may use to generate the next response. + */ + tools?: Tool[]; + /** Configuration for the tools to use. This config is shared for all tools. + */ + toolConfig?: ToolConfig; + /** The Cloud KMS resource identifier of the customer managed + encryption key used to protect a resource. + The key needs to be in the same region as where the compute resource is + created. See + https://cloud.google.com/vertex-ai/docs/general/cmek for more + details. If this is set, then all created CachedContent objects + will be encrypted with the provided encryption key. + Allowed formats: projects/{project}/locations/{location}/keyRings/{key_ring}/cryptoKeys/{crypto_key} + */ + kmsKeyName?: string; +} + +/** Parameters for caches.create method. */ +export declare interface CreateCachedContentParameters { + /** ID of the model to use. Example: gemini-2.0-flash */ + model: string; + /** Configuration that contains optional parameters. + */ + config?: CreateCachedContentConfig; +} + +/** Parameters for initializing a new chat session. + + These parameters are used when creating a chat session with the + `chats.create()` method. */ +export declare interface CreateChatParameters { + /** The name of the model to use for the chat session. + + For example: 'gemini-2.0-flash', 'gemini-2.0-flash-lite', etc. See Gemini API + docs to find the available models. + */ + model: string; + /** Config for the entire chat session. + + This config applies to all requests within the session + unless overridden by a per-request `config` in `SendMessageParameters`. + */ + config?: GenerateContentConfig; + /** The initial conversation history for the chat session. + + This allows you to start the chat with a pre-existing history. The history + must be a list of `Content` alternating between 'user' and 'model' roles. + It should start with a 'user' message. + */ + history?: Content[]; +} + +/** Config for optional parameters. */ +export declare interface CreateEmbeddingsBatchJobConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** The user-defined name of this BatchJob. + */ + displayName?: string; +} + +/** Config for batches.create parameters. */ +export declare interface CreateEmbeddingsBatchJobParameters { + /** The name of the model to produces the predictions via the BatchJob. + */ + model?: string; + /** input data to run batch job". + */ + src: EmbeddingsBatchJobSource; + /** Optional parameters for creating a BatchJob. + */ + config?: CreateEmbeddingsBatchJobConfig; +} + +/** Used to override the default configuration. */ +export declare interface CreateFileConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Generates the parameters for the private _create method. */ +export declare interface CreateFileParameters { + /** The file to be uploaded. + mime_type: (Required) The MIME type of the file. Must be provided. + name: (Optional) The name of the file in the destination (e.g. + 'files/sample-image'). + display_name: (Optional) The display name of the file. + */ + file: File_2; + /** Used to override the default configuration. */ + config?: CreateFileConfig; +} + +/** Response for the create file method. */ +export declare class CreateFileResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; +} + +/** Optional parameters for creating a file search store. */ +export declare interface CreateFileSearchStoreConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** The human-readable display name for the file search store. + */ + displayName?: string; +} + +/** Config for file_search_stores.create parameters. */ +export declare interface CreateFileSearchStoreParameters { + /** Optional parameters for creating a file search store. + */ + config?: CreateFileSearchStoreConfig; +} + +/** + * Creates a `FunctionResponsePart` object from a `base64` encoded `string`. + */ +export declare function createFunctionResponsePartFromBase64(data: string, mimeType: string): FunctionResponsePart; + +/** + * Creates a `FunctionResponsePart` object from a `URI` string. + */ +export declare function createFunctionResponsePartFromUri(uri: string, mimeType: string): FunctionResponsePart; + +/** + * Creates a `Content` object with a model role from a `PartListUnion` object or `string`. + */ +export declare function createModelContent(partOrString: PartListUnion | string): Content; + +declare interface CreateModelInteractionParamsNonStreaming extends BaseCreateModelInteractionParams { + /** + * Body param: Input only. Whether the interaction will be streamed. + */ + stream?: false; +} + +declare interface CreateModelInteractionParamsStreaming extends BaseCreateModelInteractionParams { + /** + * Body param: Input only. Whether the interaction will be streamed. + */ + stream: true; +} + +/** + * Creates a `Part` object from a `base64` encoded `string`. + */ +export declare function createPartFromBase64(data: string, mimeType: string, mediaResolution?: PartMediaResolutionLevel): Part; + +/** + * Creates a `Part` object from the `outcome` and `output` of a `CodeExecutionResult` object. + */ +export declare function createPartFromCodeExecutionResult(outcome: Outcome, output: string): Part; + +/** + * Creates a `Part` object from the `code` and `language` of an `ExecutableCode` object. + */ +export declare function createPartFromExecutableCode(code: string, language: Language): Part; + +/** + * Creates a `Part` object from a `FunctionCall` object. + */ +export declare function createPartFromFunctionCall(name: string, args: Record<string, unknown>): Part; + +/** + * Creates a `Part` object from a `FunctionResponse` object. + */ +export declare function createPartFromFunctionResponse(id: string, name: string, response: Record<string, unknown>, parts?: FunctionResponsePart[]): Part; + +/** + * Creates a `Part` object from a `text` string. + */ +export declare function createPartFromText(text: string): Part; + +/** + * Creates a `Part` object from a `URI` string. + */ +export declare function createPartFromUri(uri: string, mimeType: string, mediaResolution?: PartMediaResolutionLevel): Part; + +/** Fine-tuning job creation request - optional fields. */ +export declare interface CreateTuningJobConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** The method to use for tuning (SUPERVISED_FINE_TUNING or PREFERENCE_TUNING or DISTILLATION). If not set, the default method (SFT) will be used. */ + method?: TuningMethod; + /** Validation dataset for tuning. The dataset must be formatted as a JSONL file. */ + validationDataset?: TuningValidationDataset; + /** The display name of the tuned Model. The name can be up to 128 characters long and can consist of any UTF-8 characters. */ + tunedModelDisplayName?: string; + /** The description of the TuningJob */ + description?: string; + /** Number of complete passes the model makes over the entire training dataset during training. */ + epochCount?: number; + /** Multiplier for adjusting the default learning rate. 1P models only. Mutually exclusive with learning_rate. */ + learningRateMultiplier?: number; + /** If set to true, disable intermediate checkpoints and only the last checkpoint will be exported. Otherwise, enable intermediate checkpoints. */ + exportLastCheckpointOnly?: boolean; + /** The optional checkpoint id of the pre-tuned model to use for tuning, if applicable. */ + preTunedModelCheckpointId?: string; + /** Adapter size for tuning. */ + adapterSize?: AdapterSize; + /** Tuning mode for SFT tuning. */ + tuningMode?: TuningMode; + /** Custom base model for tuning. This is only supported for OSS models in Vertex. */ + customBaseModel?: string; + /** The batch size hyperparameter for tuning. This is only supported for OSS models in Vertex. */ + batchSize?: number; + /** The learning rate for tuning. OSS models only. Mutually exclusive with learning_rate_multiplier. */ + learningRate?: number; + /** Optional. The labels with user-defined metadata to organize TuningJob and generated resources such as Model and Endpoint. Label keys and values can be no longer than 64 characters (Unicode codepoints), can only contain lowercase letters, numeric characters, underscores and dashes. International characters are allowed. See https://goo.gl/xmQnxf for more information and examples of labels. */ + labels?: Record<string, string>; + /** Weight for KL Divergence regularization, Preference Optimization tuning only. */ + beta?: number; + /** The base teacher model that is being distilled. Distillation only. */ + baseTeacherModel?: string; + /** The resource name of the Tuned teacher model. Distillation only. */ + tunedTeacherModelSource?: string; + /** Multiplier for adjusting the weight of the SFT loss. Distillation only. */ + sftLossWeightMultiplier?: number; + /** The Google Cloud Storage location where the tuning job outputs are written. */ + outputUri?: string; + /** The encryption spec of the tuning job. Customer-managed encryption key options for a TuningJob. If this is set, then all resources created by the TuningJob will be encrypted with provided encryption key. */ + encryptionSpec?: EncryptionSpec; +} + +/** Fine-tuning job creation parameters - optional fields. */ +export declare interface CreateTuningJobParameters { + /** The base model that is being tuned, e.g., "gemini-2.5-flash". */ + baseModel: string; + /** Cloud Storage path to file containing training dataset for tuning. The dataset must be formatted as a JSONL file. */ + trainingDataset: TuningDataset; + /** Configuration for the tuning job. */ + config?: CreateTuningJobConfig; +} + +/** Fine-tuning job creation parameters - optional fields. */ +export declare interface CreateTuningJobParametersPrivate { + /** The base model that is being tuned, e.g., "gemini-2.5-flash". */ + baseModel?: string; + /** The PreTunedModel that is being tuned. */ + preTunedModel?: PreTunedModel; + /** Cloud Storage path to file containing training dataset for tuning. The dataset must be formatted as a JSONL file. */ + trainingDataset: TuningDataset; + /** Configuration for the tuning job. */ + config?: CreateTuningJobConfig; +} + +/** + * Creates a `Content` object with a user role from a `PartListUnion` object or `string`. + */ +export declare function createUserContent(partOrString: PartListUnion | string): Content; + +/** User provided metadata stored as key-value pairs. This data type is not supported in Vertex AI. */ +export declare interface CustomMetadata { + /** Required. The key of the metadata to store. */ + key?: string; + /** The numeric value of the metadata to store. */ + numericValue?: number; + /** The StringList value of the metadata to store. */ + stringListValue?: StringList; + /** The string value of the metadata to store. */ + stringValue?: string; +} + +/** Distribution computed over a tuning dataset. This data type is not supported in Gemini API. */ +export declare interface DatasetDistribution { + /** Output only. Defines the histogram bucket. */ + buckets?: DatasetDistributionDistributionBucket[]; + /** Output only. The maximum of the population values. */ + max?: number; + /** Output only. The arithmetic mean of the values in the population. */ + mean?: number; + /** Output only. The median of the values in the population. */ + median?: number; + /** Output only. The minimum of the population values. */ + min?: number; + /** Output only. The 5th percentile of the values in the population. */ + p5?: number; + /** Output only. The 95th percentile of the values in the population. */ + p95?: number; + /** Output only. Sum of a given population of values. */ + sum?: number; +} + +/** Dataset bucket used to create a histogram for the distribution given a population of values. This data type is not supported in Gemini API. */ +export declare interface DatasetDistributionDistributionBucket { + /** Output only. Number of values in the bucket. */ + count?: string; + /** Output only. Left bound of the bucket. */ + left?: number; + /** Output only. Right bound of the bucket. */ + right?: number; +} + +/** Statistics computed over a tuning dataset. This data type is not supported in Gemini API. */ +export declare interface DatasetStats { + /** Output only. Number of billable characters in the tuning dataset. */ + totalBillableCharacterCount?: string; + /** Output only. Number of tuning characters in the tuning dataset. */ + totalTuningCharacterCount?: string; + /** Output only. Number of examples in the tuning dataset. */ + tuningDatasetExampleCount?: string; + /** Output only. Number of tuning steps for this Tuning Job. */ + tuningStepCount?: string; + /** Output only. Sample user messages in the training dataset uri. */ + userDatasetExamples?: Content[]; + /** Output only. Dataset distributions for the user input tokens. */ + userInputTokenDistribution?: DatasetDistribution; + /** Output only. Dataset distributions for the messages per example. */ + userMessagePerExampleDistribution?: DatasetDistribution; + /** Output only. Dataset distributions for the user output tokens. */ + userOutputTokenDistribution?: DatasetDistribution; +} + +/** + * Configuration for the Deep Research agent. + */ +declare interface DeepResearchAgentConfig { + /** + * Whether to include thought summaries in the response. + */ + thinking_summaries?: 'auto' | 'none'; + type?: 'deep-research'; +} + +/** Optional parameters for models.get method. */ +export declare interface DeleteBatchJobConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Config for batches.delete parameters. */ +export declare interface DeleteBatchJobParameters { + /** A fully-qualified BatchJob resource name or ID. + Example: "projects/.../locations/.../batchPredictionJobs/456" + or "456" when project and location are initialized in the client. + */ + name: string; + /** Optional parameters for the request. */ + config?: DeleteBatchJobConfig; +} + +/** Optional parameters for caches.delete method. */ +export declare interface DeleteCachedContentConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Parameters for caches.delete method. */ +export declare interface DeleteCachedContentParameters { + /** The server-generated resource name of the cached content. + */ + name: string; + /** Optional parameters for the request. + */ + config?: DeleteCachedContentConfig; +} + +/** Empty response for caches.delete method. */ +export declare class DeleteCachedContentResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; +} + +/** Config for optional parameters. */ +export declare interface DeleteDocumentConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** If set to true, any `Chunk`s and objects related to this `Document` will + also be deleted. + */ + force?: boolean; +} + +/** Config for documents.delete parameters. */ +export declare interface DeleteDocumentParameters { + /** The resource name of the Document. + Example: fileSearchStores/file-search-store-foo/documents/documents-bar */ + name: string; + /** Optional parameters for the request. */ + config?: DeleteDocumentConfig; +} + +/** Used to override the default configuration. */ +export declare interface DeleteFileConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Generates the parameters for the get method. */ +export declare interface DeleteFileParameters { + /** The name identifier for the file to be deleted. */ + name: string; + /** Used to override the default configuration. */ + config?: DeleteFileConfig; +} + +/** Response for the delete file method. */ +export declare class DeleteFileResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; +} + +/** Optional parameters for deleting a FileSearchStore. */ +export declare interface DeleteFileSearchStoreConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** If set to true, any Documents and objects related to this FileSearchStore will also be deleted. + If false (the default), a FAILED_PRECONDITION error will be returned if + the FileSearchStore contains any Documents. + */ + force?: boolean; +} + +/** Config for file_search_stores.delete parameters. */ +export declare interface DeleteFileSearchStoreParameters { + /** The resource name of the FileSearchStore. Example: `fileSearchStores/my-file-search-store-123` */ + name: string; + /** Optional parameters for the request. */ + config?: DeleteFileSearchStoreConfig; +} + +/** Configuration for deleting a tuned model. */ +export declare interface DeleteModelConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Parameters for deleting a tuned model. */ +export declare interface DeleteModelParameters { + model: string; + /** Optional parameters for the request. */ + config?: DeleteModelConfig; +} + +export declare class DeleteModelResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; +} + +/** The return value of delete operation. */ +export declare interface DeleteResourceJob { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + name?: string; + done?: boolean; + error?: JobError; +} + +/** Statistics computed for datasets used for distillation. This data type is not supported in Gemini API. */ +export declare interface DistillationDataStats { + /** Output only. Statistics computed for the training dataset. */ + trainingDatasetStats?: DatasetStats; +} + +/** Hyperparameters for Distillation. This data type is not supported in Gemini API. */ +export declare interface DistillationHyperParameters { + /** Optional. Adapter size for distillation. */ + adapterSize?: AdapterSize; + /** Optional. Number of complete passes the model makes over the entire training dataset during training. */ + epochCount?: string; + /** Optional. Multiplier for adjusting the default learning rate. */ + learningRateMultiplier?: number; +} + +/** Distillation tuning spec for tuning. */ +export declare interface DistillationSpec { + /** The GCS URI of the prompt dataset to use during distillation. */ + promptDatasetUri?: string; + /** The base teacher model that is being distilled. See [Supported models](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/tuning#supported_models). */ + baseTeacherModel?: string; + /** Optional. Hyperparameters for Distillation. */ + hyperParameters?: DistillationHyperParameters; + /** Deprecated. A path in a Cloud Storage bucket, which will be treated as the root output directory of the distillation pipeline. It is used by the system to generate the paths of output artifacts. */ + pipelineRootDirectory?: string; + /** The student model that is being tuned, e.g., "google/gemma-2b-1.1-it". Deprecated. Use base_model instead. */ + studentModel?: string; + /** Deprecated. Cloud Storage path to file containing training dataset for tuning. The dataset must be formatted as a JSONL file. */ + trainingDatasetUri?: string; + /** The resource name of the Tuned teacher model. Format: `projects/{project}/locations/{location}/models/{model}`. */ + tunedTeacherModelSource?: string; + /** Optional. Cloud Storage path to file containing validation dataset for tuning. The dataset must be formatted as a JSONL file. */ + validationDatasetUri?: string; +} + +/** A Document is a collection of Chunks. */ +declare interface Document_2 { + /** The resource name of the Document. + Example: fileSearchStores/file-search-store-foo/documents/documents-bar */ + name?: string; + /** The human-readable display name for the Document. */ + displayName?: string; + /** The current state of the Document. */ + state?: DocumentState; + /** The size of the Document in bytes. */ + sizeBytes?: string; + /** The MIME type of the Document. */ + mimeType?: string; + /** Output only. The Timestamp of when the `Document` was created. */ + createTime?: string; + /** Optional. User provided custom metadata stored as key-value pairs used for querying. A `Document` can have a maximum of 20 `CustomMetadata`. */ + customMetadata?: CustomMetadata[]; + /** Output only. The Timestamp of when the `Document` was last updated. */ + updateTime?: string; +} +export { Document_2 as Document } + +/** + * A document content block. + */ +declare interface DocumentContent { + type: 'document'; + /** + * The document content. + */ + data?: string; + /** + * The mime type of the document. + */ + mime_type?: DocumentMimeType; + /** + * The URI of the document. + */ + uri?: string; +} + +/** + * The mime type of the document. + */ +declare type DocumentMimeType = (string & {}) | 'application/pdf'; + +declare class Documents extends BaseModule { + private readonly apiClient; + constructor(apiClient: ApiClient); + /** + * Lists documents. + * + * @param params - The parameters for the list request. + * @return - A pager of documents. + * + * @example + * ```ts + * const documents = await ai.documents.list({parent:'rag_store_name', config: {'pageSize': 2}}); + * for await (const document of documents) { + * console.log(document); + * } + * ``` + */ + list: (params: types.ListDocumentsParameters) => Promise<Pager<types.Document>>; + /** + * Gets a Document. + * + * @param params - The parameters for getting a document. + * @return Document. + */ + get(params: types.GetDocumentParameters): Promise<types.Document>; + /** + * Deletes a Document. + * + * @param params - The parameters for deleting a document. + */ + delete(params: types.DeleteDocumentParameters): Promise<void>; + private listInternal; +} + +/** State for the lifecycle of a Document. */ +export declare enum DocumentState { + STATE_UNSPECIFIED = "STATE_UNSPECIFIED", + STATE_PENDING = "STATE_PENDING", + STATE_ACTIVE = "STATE_ACTIVE", + STATE_FAILED = "STATE_FAILED" +} + +/** @ts-ignore */ +declare type _DOMReadableStream<R = any> = globalThis.ReadableStream<R>; + +export declare type DownloadableFileUnion = string | File_2 | GeneratedVideo | Video; + +declare interface Downloader { + /** + * Downloads a file to the given location. + * + * @param params The parameters for downloading the file. + * @param apiClient The ApiClient to use for uploading. + * @return A Promises that resolves when the download is complete. + */ + download(params: DownloadFileParameters, apiClient: ApiClient): Promise<void>; +} + +/** Used to override the default configuration. */ +export declare interface DownloadFileConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Parameters used to download a file. */ +export declare interface DownloadFileParameters { + /** The file to download. It can be a file name, a file object or a generated video. */ + file: DownloadableFileUnion; + /** Location where the file should be downloaded to. */ + downloadPath: string; + /** Configuration to for the download operation. */ + config?: DownloadFileConfig; +} + +/** + * Configuration for dynamic agents. + */ +declare interface DynamicAgentConfig { + type?: 'dynamic'; + [k: string]: unknown; +} + +/** Describes the options to customize dynamic retrieval. */ +export declare interface DynamicRetrievalConfig { + /** Optional. The threshold to be used in dynamic retrieval. If not set, a system default value is used. */ + dynamicThreshold?: number; + /** The mode of the predictor to be used in dynamic retrieval. */ + mode?: DynamicRetrievalConfigMode; +} + +/** The mode of the predictor to be used in dynamic retrieval. */ +export declare enum DynamicRetrievalConfigMode { + /** + * Always trigger retrieval. + */ + MODE_UNSPECIFIED = "MODE_UNSPECIFIED", + /** + * Run retrieval only when system decides it is necessary. + */ + MODE_DYNAMIC = "MODE_DYNAMIC" +} + +/** Configuration for editing an image. */ +export declare interface EditImageConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** Cloud Storage URI used to store the generated images. */ + outputGcsUri?: string; + /** Description of what to discourage in the generated images. */ + negativePrompt?: string; + /** Number of images to generate. */ + numberOfImages?: number; + /** Aspect ratio of the generated images. Supported values are + "1:1", "3:4", "4:3", "9:16", and "16:9". */ + aspectRatio?: string; + /** Controls how much the model adheres to the text prompt. Large + values increase output and prompt alignment, but may compromise image + quality. */ + guidanceScale?: number; + /** Random seed for image generation. This is not available when + ``add_watermark`` is set to true. */ + seed?: number; + /** Filter level for safety filtering. */ + safetyFilterLevel?: SafetyFilterLevel; + /** Allows generation of people by the model. */ + personGeneration?: PersonGeneration; + /** Whether to report the safety scores of each generated image and + the positive prompt in the response. */ + includeSafetyAttributes?: boolean; + /** Whether to include the Responsible AI filter reason if the image + is filtered out of the response. */ + includeRaiReason?: boolean; + /** Language of the text in the prompt. */ + language?: ImagePromptLanguage; + /** MIME type of the generated image. */ + outputMimeType?: string; + /** Compression quality of the generated image (for ``image/jpeg`` + only). */ + outputCompressionQuality?: number; + /** Whether to add a watermark to the generated images. */ + addWatermark?: boolean; + /** User specified labels to track billing usage. */ + labels?: Record<string, string>; + /** Describes the editing mode for the request. */ + editMode?: EditMode; + /** The number of sampling steps. A higher value has better image + quality, while a lower value has better latency. */ + baseSteps?: number; +} + +/** Parameters for the request to edit an image. */ +export declare interface EditImageParameters { + /** The model to use. */ + model: string; + /** A text description of the edit to apply to the image. */ + prompt: string; + /** The reference images for Imagen 3 editing. */ + referenceImages: ReferenceImage[]; + /** Configuration for editing. */ + config?: EditImageConfig; +} + +/** Response for the request to edit an image. */ +export declare class EditImageResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** Generated images. */ + generatedImages?: GeneratedImage[]; +} + +/** Enum representing the editing mode. */ +export declare enum EditMode { + EDIT_MODE_DEFAULT = "EDIT_MODE_DEFAULT", + EDIT_MODE_INPAINT_REMOVAL = "EDIT_MODE_INPAINT_REMOVAL", + EDIT_MODE_INPAINT_INSERTION = "EDIT_MODE_INPAINT_INSERTION", + EDIT_MODE_OUTPAINT = "EDIT_MODE_OUTPAINT", + EDIT_MODE_CONTROLLED_EDITING = "EDIT_MODE_CONTROLLED_EDITING", + EDIT_MODE_STYLE = "EDIT_MODE_STYLE", + EDIT_MODE_BGSWAP = "EDIT_MODE_BGSWAP", + EDIT_MODE_PRODUCT_IMAGE = "EDIT_MODE_PRODUCT_IMAGE" +} + +/** Parameters for the embed_content method. */ +export declare interface EmbedContentBatch { + /** The content to embed. Only the `parts.text` fields will be counted. + */ + contents?: ContentListUnion; + /** Configuration that contains optional parameters. + */ + config?: EmbedContentConfig; +} + +/** Optional parameters for the embed_content method. */ +export declare interface EmbedContentConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** Type of task for which the embedding will be used. + */ + taskType?: string; + /** Title for the text. Only applicable when TaskType is + `RETRIEVAL_DOCUMENT`. + */ + title?: string; + /** Reduced dimension for the output embedding. If set, + excessive values in the output embedding are truncated from the end. + Supported by newer models since 2024 only. You cannot set this value if + using the earlier model (`models/embedding-001`). + */ + outputDimensionality?: number; + /** Vertex API only. The MIME type of the input. + */ + mimeType?: string; + /** Vertex API only. Whether to silently truncate inputs longer than + the max sequence length. If this option is set to false, oversized inputs + will lead to an INVALID_ARGUMENT error, similar to other text APIs. + */ + autoTruncate?: boolean; +} + +/** Request-level metadata for the Vertex Embed Content API. */ +export declare interface EmbedContentMetadata { + /** Vertex API only. The total number of billable characters included + in the request. + */ + billableCharacterCount?: number; +} + +/** Parameters for the embed_content method. */ +export declare interface EmbedContentParameters { + /** ID of the model to use. For a list of models, see `Google models + <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */ + model: string; + /** The content to embed. Only the `parts.text` fields will be counted. + */ + contents: ContentListUnion; + /** Configuration that contains optional parameters. + */ + config?: EmbedContentConfig; +} + +/** Response for the embed_content method. */ +export declare class EmbedContentResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** The embeddings for each request, in the same order as provided in + the batch request. + */ + embeddings?: ContentEmbedding[]; + /** Vertex API only. Metadata about the request. + */ + metadata?: EmbedContentMetadata; +} + +export declare interface EmbeddingsBatchJobSource { + /** The Gemini Developer API's file resource name of the input data + (e.g. "files/12345"). + */ + fileName?: string; + /** The Gemini Developer API's inlined input data to run batch job. + */ + inlinedRequests?: EmbedContentBatch; +} + +/** Represents a customer-managed encryption key spec that can be applied to a top-level resource. This data type is not supported in Gemini API. */ +export declare interface EncryptionSpec { + /** Required. The Cloud KMS resource identifier of the customer managed encryption key used to protect a resource. Has the form: `projects/my-project/locations/my-region/keyRings/my-kr/cryptoKeys/my-key`. The key needs to be in the same region as where the compute resource is created. */ + kmsKeyName?: string; +} + +/** An endpoint where you deploy models. */ +export declare interface Endpoint { + /** Resource name of the endpoint. */ + name?: string; + /** ID of the model that's deployed to the endpoint. */ + deployedModelId?: string; +} + +/** End of speech sensitivity. */ +export declare enum EndSensitivity { + /** + * The default is END_SENSITIVITY_LOW. + */ + END_SENSITIVITY_UNSPECIFIED = "END_SENSITIVITY_UNSPECIFIED", + /** + * Automatic detection ends speech more often. + */ + END_SENSITIVITY_HIGH = "END_SENSITIVITY_HIGH", + /** + * Automatic detection ends speech less often. + */ + END_SENSITIVITY_LOW = "END_SENSITIVITY_LOW" +} + +/** Tool to search public web data, powered by Vertex AI Search and Sec4 compliance. This data type is not supported in Gemini API. */ +export declare interface EnterpriseWebSearch { + /** Optional. List of domains to be excluded from the search results. The default limit is 2000 domains. */ + excludeDomains?: string[]; + /** Optional. Sites with confidence level chosen & above this value will be blocked from the search results. */ + blockingConfidence?: PhishBlockThreshold; +} + +/** An entity representing the segmented area. */ +export declare interface EntityLabel { + /** The label of the segmented entity. */ + label?: string; + /** The confidence score of the detected label. */ + score?: number; +} + +/** The environment being operated. */ +export declare enum Environment { + /** + * Defaults to browser. + */ + ENVIRONMENT_UNSPECIFIED = "ENVIRONMENT_UNSPECIFIED", + /** + * Operates in a web browser. + */ + ENVIRONMENT_BROWSER = "ENVIRONMENT_BROWSER" +} + +declare interface ErrorEvent_2 { + /** + * Error message from an interaction. + */ + error?: ErrorEvent_2.Error; + /** + * The event_id token to be used to resume the interaction stream, from this event. + */ + event_id?: string; + event_type?: 'error'; +} + +declare namespace ErrorEvent_2 { + /** + * Error message from an interaction. + */ + interface Error { + /** + * A URI that identifies the error type. + */ + code?: string; + /** + * A human-readable error message. + */ + message?: string; + } +} + +declare namespace Errors { + export { + GeminiNextGenAPIClientError, + APIError, + APIUserAbortError, + APIConnectionError, + APIConnectionTimeoutError, + BadRequestError, + AuthenticationError, + PermissionDeniedError, + NotFoundError, + ConflictError, + UnprocessableEntityError, + RateLimitError, + InternalServerError + } +} + +/** Code generated by the model that is meant to be executed, and the result returned to the model. Generated when using the [CodeExecution] tool, in which the code will be automatically executed, and a corresponding [CodeExecutionResult] will also be generated. */ +export declare interface ExecutableCode { + /** Required. The code to be executed. */ + code?: string; + /** Required. Programming language of the `code`. */ + language?: Language; +} + +/** Retrieve from data source powered by external API for grounding. The external API is not owned by Google, but need to follow the pre-defined API spec. This data type is not supported in Gemini API. */ +export declare interface ExternalApi { + /** The authentication config to access the API. Deprecated. Please use auth_config instead. */ + apiAuth?: ApiAuth; + /** The API spec that the external API implements. */ + apiSpec?: ApiSpec; + /** The authentication config to access the API. */ + authConfig?: AuthConfig; + /** Parameters for the elastic search API. */ + elasticSearchParams?: ExternalApiElasticSearchParams; + /** The endpoint of the external API. The system will call the API at this endpoint to retrieve the data for grounding. Example: https://acme.com:443/search */ + endpoint?: string; + /** Parameters for the simple search API. */ + simpleSearchParams?: ExternalApiSimpleSearchParams; +} + +/** The search parameters to use for the ELASTIC_SEARCH spec. This data type is not supported in Gemini API. */ +export declare interface ExternalApiElasticSearchParams { + /** The ElasticSearch index to use. */ + index?: string; + /** Optional. Number of hits (chunks) to request. When specified, it is passed to Elasticsearch as the `num_hits` param. */ + numHits?: number; + /** The ElasticSearch search template to use. */ + searchTemplate?: string; +} + +/** The search parameters to use for SIMPLE_SEARCH spec. This data type is not supported in Gemini API. */ +export declare interface ExternalApiSimpleSearchParams { +} + +/** Options for feature selection preference. */ +export declare enum FeatureSelectionPreference { + FEATURE_SELECTION_PREFERENCE_UNSPECIFIED = "FEATURE_SELECTION_PREFERENCE_UNSPECIFIED", + PRIORITIZE_QUALITY = "PRIORITIZE_QUALITY", + BALANCED = "BALANCED", + PRIORITIZE_COST = "PRIORITIZE_COST" +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +declare type Fetch = (input: string | URL | Request, init?: RequestInit) => Promise<Response>; + +export declare interface FetchPredictOperationConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Parameters for the fetchPredictOperation method. */ +export declare interface FetchPredictOperationParameters { + /** The server-assigned name for the operation. */ + operationName: string; + resourceName: string; + /** Used to override the default configuration. */ + config?: FetchPredictOperationConfig; +} + +/** @ts-ignore For users who use Deno */ +declare type FetchRequestInit = NonNullable<OverloadedParameters<typeof fetch>[1]>; + +/** A file uploaded to the API. */ +declare interface File_2 { + /** The `File` resource name. The ID (name excluding the "files/" prefix) can contain up to 40 characters that are lowercase alphanumeric or dashes (-). The ID cannot start or end with a dash. If the name is empty on create, a unique name will be generated. Example: `files/123-456` */ + name?: string; + /** Optional. The human-readable display name for the `File`. The display name must be no more than 512 characters in length, including spaces. Example: 'Welcome Image' */ + displayName?: string; + /** Output only. MIME type of the file. */ + mimeType?: string; + /** Output only. Size of the file in bytes. */ + sizeBytes?: string; + /** Output only. The timestamp of when the `File` was created. */ + createTime?: string; + /** Output only. The timestamp of when the `File` will be deleted. Only set if the `File` is scheduled to expire. */ + expirationTime?: string; + /** Output only. The timestamp of when the `File` was last updated. */ + updateTime?: string; + /** Output only. SHA-256 hash of the uploaded bytes. The hash value is encoded in base64 format. */ + sha256Hash?: string; + /** Output only. The URI of the `File`. */ + uri?: string; + /** Output only. The URI of the `File`, only set for downloadable (generated) files. */ + downloadUri?: string; + /** Output only. Processing state of the File. */ + state?: FileState; + /** Output only. The source of the `File`. */ + source?: FileSource; + /** Output only. Metadata for a video. */ + videoMetadata?: Record<string, unknown>; + /** Output only. Error status if File processing failed. */ + error?: FileStatus; +} +export { File_2 as File } + +/** URI based data. */ +export declare interface FileData { + /** Optional. Display name of the file data. Used to provide a label or filename to distinguish file datas. This field is only returned in PromptMessage for prompt management. It is currently used in the Gemini GenerateContent calls only when server side tools (code_execution, google_search, and url_context) are enabled. This field is not supported in Gemini API. */ + displayName?: string; + /** Required. URI. */ + fileUri?: string; + /** Required. The IANA standard MIME type of the source data. */ + mimeType?: string; +} + +export declare class Files extends BaseModule { + private readonly apiClient; + constructor(apiClient: ApiClient); + /** + * Lists files. + * + * @param params - The parameters for the list request. + * @return - A pager of files. + * + * @example + * ```ts + * const files = await ai.files.list({config: {'pageSize': 2}}); + * for await (const file of files) { + * console.log(file); + * } + * ``` + */ + list: (params?: types.ListFilesParameters) => Promise<Pager<types.File>>; + /** + * Uploads a file asynchronously to the Gemini API. + * This method is not available in Vertex AI. + * Supported upload sources: + * - Node.js: File path (string) or Blob object. + * - Browser: Blob object (e.g., File). + * + * @remarks + * The `mimeType` can be specified in the `config` parameter. If omitted: + * - For file path (string) inputs, the `mimeType` will be inferred from the + * file extension. + * - For Blob object inputs, the `mimeType` will be set to the Blob's `type` + * property. + * Somex eamples for file extension to mimeType mapping: + * .txt -> text/plain + * .json -> application/json + * .jpg -> image/jpeg + * .png -> image/png + * .mp3 -> audio/mpeg + * .mp4 -> video/mp4 + * + * This section can contain multiple paragraphs and code examples. + * + * @param params - Optional parameters specified in the + * `types.UploadFileParameters` interface. + * @see {@link types.UploadFileParameters#config} for the optional + * config in the parameters. + * @return A promise that resolves to a `types.File` object. + * @throws An error if called on a Vertex AI client. + * @throws An error if the `mimeType` is not provided and can not be inferred, + * the `mimeType` can be provided in the `params.config` parameter. + * @throws An error occurs if a suitable upload location cannot be established. + * + * @example + * The following code uploads a file to Gemini API. + * + * ```ts + * const file = await ai.files.upload({file: 'file.txt', config: { + * mimeType: 'text/plain', + * }}); + * console.log(file.name); + * ``` + */ + upload(params: types.UploadFileParameters): Promise<types.File>; + /** + * Downloads a remotely stored file asynchronously to a location specified in + * the `params` object. This method only works on Node environment, to + * download files in the browser, use a browser compliant method like an <a> + * tag. + * + * @param params - The parameters for the download request. + * + * @example + * The following code downloads an example file named "files/mehozpxf877d" as + * "file.txt". + * + * ```ts + * await ai.files.download({file: file.name, downloadPath: 'file.txt'}); + * ``` + */ + download(params: types.DownloadFileParameters): Promise<void>; + /** + * Registers Google Cloud Storage files for use with the API. + * This method is only available in Node.js environments. + */ + registerFiles(params: types.RegisterFilesParameters): Promise<types.RegisterFilesResponse>; + protected _registerFiles(params: types.InternalRegisterFilesParameters): Promise<types.RegisterFilesResponse>; + private listInternal; + private createInternal; + /** + * Retrieves the file information from the service. + * + * @param params - The parameters for the get request + * @return The Promise that resolves to the types.File object requested. + * + * @example + * ```ts + * const config: GetFileParameters = { + * name: fileName, + * }; + * file = await ai.files.get(config); + * console.log(file.name); + * ``` + */ + get(params: types.GetFileParameters): Promise<types.File>; + /** + * Deletes a remotely stored file. + * + * @param params - The parameters for the delete request. + * @return The DeleteFileResponse, the response for the delete method. + * + * @example + * The following code deletes an example file named "files/mehozpxf877d". + * + * ```ts + * await ai.files.delete({name: file.name}); + * ``` + */ + delete(params: types.DeleteFileParameters): Promise<types.DeleteFileResponse>; + private registerFilesInternal; +} + +/** Tool to retrieve knowledge from the File Search Stores. */ +export declare interface FileSearch { + /** The names of the file_search_stores to retrieve from. + Example: `fileSearchStores/my-file-search-store-123` */ + fileSearchStoreNames?: string[]; + /** The number of file search retrieval chunks to retrieve. */ + topK?: number; + /** Metadata filter to apply to the file search retrieval documents. See https://google.aip.dev/160 for the syntax of the filter expression. */ + metadataFilter?: string; +} + +/** + * File Search content. + */ +declare interface FileSearchCallContent { + type: 'file_search_call'; + /** + * A unique ID for this specific tool call. + */ + id?: string; +} + +/** + * File Search result content. + */ +declare interface FileSearchResultContent { + type: 'file_search_result'; + /** + * The results of the File Search. + */ + result?: Array<FileSearchResultContent.Result>; +} + +declare namespace FileSearchResultContent { + /** + * The result of the File Search. + */ + interface Result { + /** + * The name of the file search store. + */ + file_search_store?: string; + /** + * The text of the search result. + */ + text?: string; + /** + * The title of the search result. + */ + title?: string; + } +} + +/** A collection of Documents. */ +export declare interface FileSearchStore { + /** The resource name of the FileSearchStore. Example: `fileSearchStores/my-file-search-store-123` */ + name?: string; + /** The human-readable display name for the FileSearchStore. */ + displayName?: string; + /** The Timestamp of when the FileSearchStore was created. */ + createTime?: string; + /** The Timestamp of when the FileSearchStore was last updated. */ + updateTime?: string; + /** The number of documents in the FileSearchStore that are active and ready for retrieval. */ + activeDocumentsCount?: string; + /** The number of documents in the FileSearchStore that are being processed. */ + pendingDocumentsCount?: string; + /** The number of documents in the FileSearchStore that have failed processing. */ + failedDocumentsCount?: string; + /** The size of raw bytes ingested into the FileSearchStore. This is the + total size of all the documents in the FileSearchStore. */ + sizeBytes?: string; +} + +declare class FileSearchStores extends BaseModule { + private readonly apiClient; + readonly documents: Documents; + constructor(apiClient: ApiClient, documents?: Documents); + /** + * Lists file search stores. + * + * @param params - The parameters for the list request. + * @return - A pager of file search stores. + * + * @example + * ```ts + * const fileSearchStores = await ai.fileSearchStores.list({config: {'pageSize': 2}}); + * for await (const fileSearchStore of fileSearchStores) { + * console.log(fileSearchStore); + * } + * ``` + */ + list: (params?: types.ListFileSearchStoresParameters) => Promise<Pager<types.FileSearchStore>>; + /** + * Uploads a file asynchronously to a given File Search Store. + * This method is not available in Vertex AI. + * Supported upload sources: + * - Node.js: File path (string) or Blob object. + * - Browser: Blob object (e.g., File). + * + * @remarks + * The `mimeType` can be specified in the `config` parameter. If omitted: + * - For file path (string) inputs, the `mimeType` will be inferred from the + * file extension. + * - For Blob object inputs, the `mimeType` will be set to the Blob's `type` + * property. + * + * This section can contain multiple paragraphs and code examples. + * + * @param params - Optional parameters specified in the + * `types.UploadToFileSearchStoreParameters` interface. + * @see {@link types.UploadToFileSearchStoreParameters#config} for the optional + * config in the parameters. + * @return A promise that resolves to a long running operation. + * @throws An error if called on a Vertex AI client. + * @throws An error if the `mimeType` is not provided and can not be inferred, + * the `mimeType` can be provided in the `params.config` parameter. + * @throws An error occurs if a suitable upload location cannot be established. + * + * @example + * The following code uploads a file to a given file search store. + * + * ```ts + * const operation = await ai.fileSearchStores.upload({fileSearchStoreName: 'fileSearchStores/foo-bar', file: 'file.txt', config: { + * mimeType: 'text/plain', + * }}); + * console.log(operation.name); + * ``` + */ + uploadToFileSearchStore(params: types.UploadToFileSearchStoreParameters): Promise<types.UploadToFileSearchStoreOperation>; + /** + * Creates a File Search Store. + * + * @param params - The parameters for creating a File Search Store. + * @return FileSearchStore. + */ + create(params: types.CreateFileSearchStoreParameters): Promise<types.FileSearchStore>; + /** + * Gets a File Search Store. + * + * @param params - The parameters for getting a File Search Store. + * @return FileSearchStore. + */ + get(params: types.GetFileSearchStoreParameters): Promise<types.FileSearchStore>; + /** + * Deletes a File Search Store. + * + * @param params - The parameters for deleting a File Search Store. + */ + delete(params: types.DeleteFileSearchStoreParameters): Promise<void>; + private listInternal; + private uploadToFileSearchStoreInternal; + /** + * Imports a File from File Service to a FileSearchStore. + * + * This is a long-running operation, see aip.dev/151 + * + * @param params - The parameters for importing a file to a file search store. + * @return ImportFileOperation. + */ + importFile(params: types.ImportFileParameters): Promise<types.ImportFileOperation>; +} + +/** Source of the File. */ +export declare enum FileSource { + SOURCE_UNSPECIFIED = "SOURCE_UNSPECIFIED", + UPLOADED = "UPLOADED", + GENERATED = "GENERATED", + REGISTERED = "REGISTERED" +} + +/** + * Represents the size and mimeType of a file. The information is used to + * request the upload URL from the https://generativelanguage.googleapis.com/upload/v1beta/files endpoint. + * This interface defines the structure for constructing and executing HTTP + * requests. + */ +declare interface FileStat { + /** + * The size of the file in bytes. + */ + size: number; + /** + * The MIME type of the file. + */ + type: string | undefined; +} + +/** State for the lifecycle of a File. */ +export declare enum FileState { + STATE_UNSPECIFIED = "STATE_UNSPECIFIED", + PROCESSING = "PROCESSING", + ACTIVE = "ACTIVE", + FAILED = "FAILED" +} + +/** Status of a File that uses a common error model. */ +export declare interface FileStatus { + /** A list of messages that carry the error details. There is a common set of message types for APIs to use. */ + details?: Record<string, unknown>[]; + /** A list of messages that carry the error details. There is a common set of message types for APIs to use. */ + message?: string; + /** The status code. 0 for OK, 1 for CANCELLED */ + code?: number; +} + +declare type FinalizedRequestInit = RequestInit & { + headers: Headers; +}; + +declare type FinalRequestOptions = RequestOptions & { + method: HTTPMethod; + path: string; +}; + +/** Output only. The reason why the model stopped generating tokens. + + If empty, the model has not stopped generating the tokens. */ +export declare enum FinishReason { + /** + * The finish reason is unspecified. + */ + FINISH_REASON_UNSPECIFIED = "FINISH_REASON_UNSPECIFIED", + /** + * Token generation reached a natural stopping point or a configured stop sequence. + */ + STOP = "STOP", + /** + * Token generation reached the configured maximum output tokens. + */ + MAX_TOKENS = "MAX_TOKENS", + /** + * Token generation stopped because the content potentially contains safety violations. NOTE: When streaming, [content][] is empty if content filters blocks the output. + */ + SAFETY = "SAFETY", + /** + * The token generation stopped because of potential recitation. + */ + RECITATION = "RECITATION", + /** + * The token generation stopped because of using an unsupported language. + */ + LANGUAGE = "LANGUAGE", + /** + * All other reasons that stopped the token generation. + */ + OTHER = "OTHER", + /** + * Token generation stopped because the content contains forbidden terms. + */ + BLOCKLIST = "BLOCKLIST", + /** + * Token generation stopped for potentially containing prohibited content. + */ + PROHIBITED_CONTENT = "PROHIBITED_CONTENT", + /** + * Token generation stopped because the content potentially contains Sensitive Personally Identifiable Information (SPII). + */ + SPII = "SPII", + /** + * The function call generated by the model is invalid. + */ + MALFORMED_FUNCTION_CALL = "MALFORMED_FUNCTION_CALL", + /** + * Token generation stopped because generated images have safety violations. + */ + IMAGE_SAFETY = "IMAGE_SAFETY", + /** + * The tool call generated by the model is invalid. + */ + UNEXPECTED_TOOL_CALL = "UNEXPECTED_TOOL_CALL", + /** + * Image generation stopped because the generated images have prohibited content. + */ + IMAGE_PROHIBITED_CONTENT = "IMAGE_PROHIBITED_CONTENT", + /** + * The model was expected to generate an image, but none was generated. + */ + NO_IMAGE = "NO_IMAGE", + /** + * Image generation stopped because the generated image may be a recitation from a source. + */ + IMAGE_RECITATION = "IMAGE_RECITATION", + /** + * Image generation stopped for a reason not otherwise specified. + */ + IMAGE_OTHER = "IMAGE_OTHER" +} + +/** + * A tool that can be used by the model. + */ +declare interface Function_2 { + type: 'function'; + /** + * A description of the function. + */ + description?: string; + /** + * The name of the function. + */ + name?: string; + /** + * The JSON Schema for the function's parameters. + */ + parameters?: unknown; +} + +/** A function call. */ +export declare interface FunctionCall { + /** The unique id of the function call. If populated, the client to execute the + `function_call` and return the response with the matching `id`. */ + id?: string; + /** Optional. The function parameters and values in JSON object format. See [FunctionDeclaration.parameters] for parameter details. */ + args?: Record<string, unknown>; + /** Optional. The name of the function to call. Matches [FunctionDeclaration.name]. */ + name?: string; + /** Optional. The partial argument value of the function call. If provided, represents the arguments/fields that are streamed incrementally. This field is not supported in Gemini API. */ + partialArgs?: PartialArg[]; + /** Optional. Whether this is the last part of the FunctionCall. If true, another partial message for the current FunctionCall is expected to follow. This field is not supported in Gemini API. */ + willContinue?: boolean; +} + +/** + * A function tool call content block. + */ +declare interface FunctionCallContent { + /** + * A unique ID for this specific tool call. + */ + id: string; + /** + * The arguments to pass to the function. + */ + arguments: { + [key: string]: unknown; + }; + /** + * The name of the tool to call. + */ + name: string; + type: 'function_call'; +} + +/** Function calling config. */ +export declare interface FunctionCallingConfig { + /** Optional. Function names to call. Only set when the Mode is ANY. Function names should match [FunctionDeclaration.name]. With mode set to ANY, model will predict a function call from the set of function names provided. */ + allowedFunctionNames?: string[]; + /** Optional. Function calling mode. */ + mode?: FunctionCallingConfigMode; + /** Optional. When set to true, arguments of a single function call will be streamed out in multiple parts/contents/responses. Partial parameter results will be returned in the [FunctionCall.partial_args] field. This field is not supported in Gemini API. */ + streamFunctionCallArguments?: boolean; +} + +/** Function calling mode. */ +export declare enum FunctionCallingConfigMode { + /** + * Unspecified function calling mode. This value should not be used. + */ + MODE_UNSPECIFIED = "MODE_UNSPECIFIED", + /** + * Default model behavior, model decides to predict either function calls or natural language response. + */ + AUTO = "AUTO", + /** + * Model is constrained to always predicting function calls only. If "allowed_function_names" are set, the predicted function calls will be limited to any one of "allowed_function_names", else the predicted function calls will be any one of the provided "function_declarations". + */ + ANY = "ANY", + /** + * Model will not predict any function calls. Model behavior is same as when not passing any function declarations. + */ + NONE = "NONE", + /** + * Model is constrained to predict either function calls or natural language response. If "allowed_function_names" are set, the predicted function calls will be limited to any one of "allowed_function_names", else the predicted function calls will be any one of the provided "function_declarations". + */ + VALIDATED = "VALIDATED" +} + +/** Structured representation of a function declaration as defined by the [OpenAPI 3.0 specification](https://spec.openapis.org/oas/v3.0.3). Included in this declaration are the function name, description, parameters and response type. This FunctionDeclaration is a representation of a block of code that can be used as a `Tool` by the model and executed by the client. */ +export declare interface FunctionDeclaration { + /** Optional. Description and purpose of the function. Model uses it to decide how and whether to call the function. */ + description?: string; + /** Required. The name of the function to call. Must start with a letter or an underscore. Must be a-z, A-Z, 0-9, or contain underscores, dots and dashes, with a maximum length of 64. */ + name?: string; + /** Optional. Describes the parameters to this function in JSON Schema Object format. Reflects the Open API 3.03 Parameter Object. string Key: the name of the parameter. Parameter names are case sensitive. Schema Value: the Schema defining the type used for the parameter. For function with no parameters, this can be left unset. Parameter names must start with a letter or an underscore and must only contain chars a-z, A-Z, 0-9, or underscores with a maximum length of 64. Example with 1 required and 1 optional parameter: type: OBJECT properties: param1: type: STRING param2: type: INTEGER required: - param1 */ + parameters?: Schema; + /** Optional. Describes the parameters to the function in JSON Schema format. The schema must describe an object where the properties are the parameters to the function. For example: ``` { "type": "object", "properties": { "name": { "type": "string" }, "age": { "type": "integer" } }, "additionalProperties": false, "required": ["name", "age"], "propertyOrdering": ["name", "age"] } ``` This field is mutually exclusive with `parameters`. */ + parametersJsonSchema?: unknown; + /** Optional. Describes the output from this function in JSON Schema format. Reflects the Open API 3.03 Response Object. The Schema defines the type used for the response value of the function. */ + response?: Schema; + /** Optional. Describes the output from this function in JSON Schema format. The value specified by the schema is the response value of the function. This field is mutually exclusive with `response`. */ + responseJsonSchema?: unknown; + /** Optional. Specifies the function Behavior. Currently only supported by the BidiGenerateContent method. This field is not supported in Vertex AI. */ + behavior?: Behavior; +} + +/** A function response. */ +export declare class FunctionResponse { + /** Signals that function call continues, and more responses will be returned, turning the function call into a generator. Is only applicable to NON_BLOCKING function calls (see FunctionDeclaration.behavior for details), ignored otherwise. If false, the default, future responses will not be considered. Is only applicable to NON_BLOCKING function calls, is ignored otherwise. If set to false, future responses will not be considered. It is allowed to return empty `response` with `will_continue=False` to signal that the function call is finished. */ + willContinue?: boolean; + /** Specifies how the response should be scheduled in the conversation. Only applicable to NON_BLOCKING function calls, is ignored otherwise. Defaults to WHEN_IDLE. */ + scheduling?: FunctionResponseScheduling; + /** List of parts that constitute a function response. Each part may + have a different IANA MIME type. */ + parts?: FunctionResponsePart[]; + /** Optional. The id of the function call this response is for. Populated by the client to match the corresponding function call `id`. */ + id?: string; + /** Required. The name of the function to call. Matches [FunctionDeclaration.name] and [FunctionCall.name]. */ + name?: string; + /** Required. The function response in JSON object format. Use "output" key to specify function output and "error" key to specify error details (if any). If "output" and "error" keys are not specified, then whole "response" is treated as function output. */ + response?: Record<string, unknown>; +} + +/** Raw media bytes for function response. + + Text should not be sent as raw bytes, use the FunctionResponse.response + field. */ +export declare class FunctionResponseBlob { + /** Required. The IANA standard MIME type of the source data. */ + mimeType?: string; + /** Required. Inline media bytes. + * @remarks Encoded as base64 string. */ + data?: string; + /** Optional. Display name of the blob. + Used to provide a label or filename to distinguish blobs. */ + displayName?: string; +} + +/** URI based data for function response. */ +export declare class FunctionResponseFileData { + /** Required. URI. */ + fileUri?: string; + /** Required. The IANA standard MIME type of the source data. */ + mimeType?: string; + /** Optional. Display name of the file. + Used to provide a label or filename to distinguish files. */ + displayName?: string; +} + +/** A datatype containing media that is part of a `FunctionResponse` message. + + A `FunctionResponsePart` consists of data which has an associated datatype. A + `FunctionResponsePart` can only contain one of the accepted types in + `FunctionResponsePart.data`. + + A `FunctionResponsePart` must have a fixed IANA MIME type identifying the + type and subtype of the media if the `inline_data` field is filled with raw + bytes. */ +export declare class FunctionResponsePart { + /** Optional. Inline media bytes. */ + inlineData?: FunctionResponseBlob; + /** Optional. URI based data. */ + fileData?: FunctionResponseFileData; +} + +/** Specifies how the response should be scheduled in the conversation. */ +export declare enum FunctionResponseScheduling { + /** + * This value is unused. + */ + SCHEDULING_UNSPECIFIED = "SCHEDULING_UNSPECIFIED", + /** + * Only add the result to the conversation context, do not interrupt or trigger generation. + */ + SILENT = "SILENT", + /** + * Add the result to the conversation context, and prompt to generate output without interrupting ongoing generation. + */ + WHEN_IDLE = "WHEN_IDLE", + /** + * Add the result to the conversation context, interrupt ongoing generation and prompt to generate output. + */ + INTERRUPT = "INTERRUPT" +} + +/** + * A function tool result content block. + */ +declare interface FunctionResultContent { + /** + * ID to match the ID from the function call block. + */ + call_id: string; + /** + * The result of the tool call. + */ + result: FunctionResultContent.Items | unknown | string; + type: 'function_result'; + /** + * Whether the tool call resulted in an error. + */ + is_error?: boolean; + /** + * The name of the tool that was called. + */ + name?: string; +} + +declare namespace FunctionResultContent { + interface Items { + items?: Array<InteractionsAPI.TextContent | InteractionsAPI.ImageContent>; + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +declare interface GeminiNextGenAPIClientAdapter { + isVertexAI: () => boolean; + getProject: () => string | undefined; + getLocation: () => string | undefined; + getAuthHeaders: () => Headers | Promise<Headers>; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +declare class GeminiNextGenAPIClientError extends Error { +} + +/** Input example for preference optimization. This data type is not supported in Gemini API. */ +export declare interface GeminiPreferenceExample { + /** List of completions for a given prompt. */ + completions?: GeminiPreferenceExampleCompletion[]; + /** Multi-turn contents that represents the Prompt. */ + contents?: Content[]; +} + +/** Completion and its preference score. This data type is not supported in Gemini API. */ +export declare interface GeminiPreferenceExampleCompletion { + /** Single turn completion for the given prompt. */ + completion?: Content; + /** The score for the given completion. */ + score?: number; +} + +/** Optional model configuration parameters. + + For more information, see `Content generation parameters + <https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/content-generation-parameters>`_. */ +export declare interface GenerateContentConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** Instructions for the model to steer it toward better performance. + For example, "Answer as concisely as possible" or "Don't use technical + terms in your response". + */ + systemInstruction?: ContentUnion; + /** Value that controls the degree of randomness in token selection. + Lower temperatures are good for prompts that require a less open-ended or + creative response, while higher temperatures can lead to more diverse or + creative results. + */ + temperature?: number; + /** Tokens are selected from the most to least probable until the sum + of their probabilities equals this value. Use a lower value for less + random responses and a higher value for more random responses. + */ + topP?: number; + /** For each token selection step, the ``top_k`` tokens with the + highest probabilities are sampled. Then tokens are further filtered based + on ``top_p`` with the final token selected using temperature sampling. Use + a lower number for less random responses and a higher number for more + random responses. + */ + topK?: number; + /** Number of response variations to return. + */ + candidateCount?: number; + /** Maximum number of tokens that can be generated in the response. + */ + maxOutputTokens?: number; + /** List of strings that tells the model to stop generating text if one + of the strings is encountered in the response. + */ + stopSequences?: string[]; + /** Whether to return the log probabilities of the tokens that were + chosen by the model at each step. + */ + responseLogprobs?: boolean; + /** Number of top candidate tokens to return the log probabilities for + at each generation step. + */ + logprobs?: number; + /** Positive values penalize tokens that already appear in the + generated text, increasing the probability of generating more diverse + content. + */ + presencePenalty?: number; + /** Positive values penalize tokens that repeatedly appear in the + generated text, increasing the probability of generating more diverse + content. + */ + frequencyPenalty?: number; + /** When ``seed`` is fixed to a specific number, the model makes a best + effort to provide the same response for repeated requests. By default, a + random number is used. + */ + seed?: number; + /** Output response mimetype of the generated candidate text. + Supported mimetype: + - `text/plain`: (default) Text output. + - `application/json`: JSON response in the candidates. + The model needs to be prompted to output the appropriate response type, + otherwise the behavior is undefined. + This is a preview feature. + */ + responseMimeType?: string; + /** The `Schema` object allows the definition of input and output data types. + These types can be objects, but also primitives and arrays. + Represents a select subset of an [OpenAPI 3.0 schema + object](https://spec.openapis.org/oas/v3.0.3#schema). + If set, a compatible response_mime_type must also be set. + Compatible mimetypes: `application/json`: Schema for JSON response. + + If `response_schema` doesn't process your schema correctly, try using + `response_json_schema` instead. + */ + responseSchema?: SchemaUnion; + /** Optional. Output schema of the generated response. + This is an alternative to `response_schema` that accepts [JSON + Schema](https://json-schema.org/). If set, `response_schema` must be + omitted, but `response_mime_type` is required. While the full JSON Schema + may be sent, not all features are supported. Specifically, only the + following properties are supported: - `$id` - `$defs` - `$ref` - `$anchor` + - `type` - `format` - `title` - `description` - `enum` (for strings and + numbers) - `items` - `prefixItems` - `minItems` - `maxItems` - `minimum` - + `maximum` - `anyOf` - `oneOf` (interpreted the same as `anyOf`) - + `properties` - `additionalProperties` - `required` The non-standard + `propertyOrdering` property may also be set. Cyclic references are + unrolled to a limited degree and, as such, may only be used within + non-required properties. (Nullable properties are not sufficient.) If + `$ref` is set on a sub-schema, no other properties, except for than those + starting as a `$`, may be set. */ + responseJsonSchema?: unknown; + /** Configuration for model router requests. + */ + routingConfig?: GenerationConfigRoutingConfig; + /** Configuration for model selection. + */ + modelSelectionConfig?: ModelSelectionConfig; + /** Safety settings in the request to block unsafe content in the + response. + */ + safetySettings?: SafetySetting[]; + /** Code that enables the system to interact with external systems to + perform an action outside of the knowledge and scope of the model. + */ + tools?: ToolListUnion; + /** Associates model output to a specific function call. + */ + toolConfig?: ToolConfig; + /** Labels with user-defined metadata to break down billed charges. */ + labels?: Record<string, string>; + /** Resource name of a context cache that can be used in subsequent + requests. + */ + cachedContent?: string; + /** The requested modalities of the response. Represents the set of + modalities that the model can return. + */ + responseModalities?: string[]; + /** If specified, the media resolution specified will be used. + */ + mediaResolution?: MediaResolution; + /** The speech generation configuration. + */ + speechConfig?: SpeechConfigUnion; + /** If enabled, audio timestamp will be included in the request to the + model. + */ + audioTimestamp?: boolean; + /** The configuration for automatic function calling. + */ + automaticFunctionCalling?: AutomaticFunctionCallingConfig; + /** The thinking features configuration. + */ + thinkingConfig?: ThinkingConfig; + /** The image generation configuration. + */ + imageConfig?: ImageConfig; + /** Enables enhanced civic answers. It may not be available for all + models. This field is not supported in Vertex AI. + */ + enableEnhancedCivicAnswers?: boolean; + /** Settings for prompt and response sanitization using the Model Armor + service. If supplied, safety_settings must not be supplied. + */ + modelArmorConfig?: ModelArmorConfig; +} + +/** Config for models.generate_content parameters. */ +export declare interface GenerateContentParameters { + /** ID of the model to use. For a list of models, see `Google models + <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */ + model: string; + /** Content of the request. + */ + contents: ContentListUnion; + /** Configuration that contains optional model parameters. + */ + config?: GenerateContentConfig; +} + +/** Response message for PredictionService.GenerateContent. */ +export declare class GenerateContentResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** Response variations returned by the model. + */ + candidates?: Candidate[]; + /** Timestamp when the request is made to the server. + */ + createTime?: string; + /** The history of automatic function calling. + */ + automaticFunctionCallingHistory?: Content[]; + /** Output only. The model version used to generate the response. */ + modelVersion?: string; + /** Output only. Content filter results for a prompt sent in the request. Note: Sent only in the first stream chunk. Only happens when no candidates were generated due to content violations. */ + promptFeedback?: GenerateContentResponsePromptFeedback; + /** Output only. response_id is used to identify each response. It is the encoding of the event_id. */ + responseId?: string; + /** Usage metadata about the response(s). */ + usageMetadata?: GenerateContentResponseUsageMetadata; + /** + * Returns the concatenation of all text parts from the first candidate in the response. + * + * @remarks + * If there are multiple candidates in the response, the text from the first + * one will be returned. + * If there are non-text parts in the response, the concatenation of all text + * parts will be returned, and a warning will be logged. + * If there are thought parts in the response, the concatenation of all text + * parts excluding the thought parts will be returned. + * + * @example + * ```ts + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: + * 'Why is the sky blue?', + * }); + * + * console.debug(response.text); + * ``` + */ + get text(): string | undefined; + /** + * Returns the concatenation of all inline data parts from the first candidate + * in the response. + * + * @remarks + * If there are multiple candidates in the response, the inline data from the + * first one will be returned. If there are non-inline data parts in the + * response, the concatenation of all inline data parts will be returned, and + * a warning will be logged. + */ + get data(): string | undefined; + /** + * Returns the function calls from the first candidate in the response. + * + * @remarks + * If there are multiple candidates in the response, the function calls from + * the first one will be returned. + * If there are no function calls in the response, undefined will be returned. + * + * @example + * ```ts + * const controlLightFunctionDeclaration: FunctionDeclaration = { + * name: 'controlLight', + * parameters: { + * type: Type.OBJECT, + * description: 'Set the brightness and color temperature of a room light.', + * properties: { + * brightness: { + * type: Type.NUMBER, + * description: + * 'Light level from 0 to 100. Zero is off and 100 is full brightness.', + * }, + * colorTemperature: { + * type: Type.STRING, + * description: + * 'Color temperature of the light fixture which can be `daylight`, `cool` or `warm`.', + * }, + * }, + * required: ['brightness', 'colorTemperature'], + * }; + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: 'Dim the lights so the room feels cozy and warm.', + * config: { + * tools: [{functionDeclarations: [controlLightFunctionDeclaration]}], + * toolConfig: { + * functionCallingConfig: { + * mode: FunctionCallingConfigMode.ANY, + * allowedFunctionNames: ['controlLight'], + * }, + * }, + * }, + * }); + * console.debug(JSON.stringify(response.functionCalls)); + * ``` + */ + get functionCalls(): FunctionCall[] | undefined; + /** + * Returns the first executable code from the first candidate in the response. + * + * @remarks + * If there are multiple candidates in the response, the executable code from + * the first one will be returned. + * If there are no executable code in the response, undefined will be + * returned. + * + * @example + * ```ts + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: + * 'What is the sum of the first 50 prime numbers? Generate and run code for the calculation, and make sure you get all 50.' + * config: { + * tools: [{codeExecution: {}}], + * }, + * }); + * + * console.debug(response.executableCode); + * ``` + */ + get executableCode(): string | undefined; + /** + * Returns the first code execution result from the first candidate in the response. + * + * @remarks + * If there are multiple candidates in the response, the code execution result from + * the first one will be returned. + * If there are no code execution result in the response, undefined will be returned. + * + * @example + * ```ts + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: + * 'What is the sum of the first 50 prime numbers? Generate and run code for the calculation, and make sure you get all 50.' + * config: { + * tools: [{codeExecution: {}}], + * }, + * }); + * + * console.debug(response.codeExecutionResult); + * ``` + */ + get codeExecutionResult(): string | undefined; +} + +/** Content filter results for a prompt sent in the request. Note: This is sent only in the first stream chunk and only if no candidates were generated due to content violations. */ +export declare class GenerateContentResponsePromptFeedback { + /** Output only. The reason why the prompt was blocked. */ + blockReason?: BlockedReason; + /** Output only. A readable message that explains the reason why the prompt was blocked. This field is not supported in Gemini API. */ + blockReasonMessage?: string; + /** Output only. A list of safety ratings for the prompt. There is one rating per category. */ + safetyRatings?: SafetyRating[]; +} + +/** Usage metadata about the content generation request and response. This message provides a detailed breakdown of token usage and other relevant metrics. This data type is not supported in Gemini API. */ +export declare class GenerateContentResponseUsageMetadata { + /** Output only. A detailed breakdown of the token count for each modality in the cached content. */ + cacheTokensDetails?: ModalityTokenCount[]; + /** Output only. The number of tokens in the cached content that was used for this request. */ + cachedContentTokenCount?: number; + /** The total number of tokens in the generated candidates. */ + candidatesTokenCount?: number; + /** Output only. A detailed breakdown of the token count for each modality in the generated candidates. */ + candidatesTokensDetails?: ModalityTokenCount[]; + /** The total number of tokens in the prompt. This includes any text, images, or other media provided in the request. When `cached_content` is set, this also includes the number of tokens in the cached content. */ + promptTokenCount?: number; + /** Output only. A detailed breakdown of the token count for each modality in the prompt. */ + promptTokensDetails?: ModalityTokenCount[]; + /** Output only. The number of tokens that were part of the model's generated "thoughts" output, if applicable. */ + thoughtsTokenCount?: number; + /** Output only. The number of tokens in the results from tool executions, which are provided back to the model as input, if applicable. */ + toolUsePromptTokenCount?: number; + /** Output only. A detailed breakdown by modality of the token counts from the results of tool executions, which are provided back to the model as input. */ + toolUsePromptTokensDetails?: ModalityTokenCount[]; + /** The total number of tokens for the entire request. This is the sum of `prompt_token_count`, `candidates_token_count`, `tool_use_prompt_token_count`, and `thoughts_token_count`. */ + totalTokenCount?: number; + /** Output only. The traffic type for this request. */ + trafficType?: TrafficType; +} + +/** An output image. */ +export declare interface GeneratedImage { + /** The output image data. */ + image?: Image_2; + /** Responsible AI filter reason if the image is filtered out of the + response. */ + raiFilteredReason?: string; + /** Safety attributes of the image. Lists of RAI categories and their + scores of each content. */ + safetyAttributes?: SafetyAttributes; + /** The rewritten prompt used for the image generation if the prompt + enhancer is enabled. */ + enhancedPrompt?: string; +} + +/** A generated image mask. */ +export declare interface GeneratedImageMask { + /** The generated image mask. */ + mask?: Image_2; + /** The detected entities on the segmented area. */ + labels?: EntityLabel[]; +} + +/** A generated video. */ +export declare interface GeneratedVideo { + /** The output video */ + video?: Video; +} + +/** The config for generating an images. */ +export declare interface GenerateImagesConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** Cloud Storage URI used to store the generated images. */ + outputGcsUri?: string; + /** Description of what to discourage in the generated images. */ + negativePrompt?: string; + /** Number of images to generate. */ + numberOfImages?: number; + /** Aspect ratio of the generated images. Supported values are + "1:1", "3:4", "4:3", "9:16", and "16:9". */ + aspectRatio?: string; + /** Controls how much the model adheres to the text prompt. Large + values increase output and prompt alignment, but may compromise image + quality. */ + guidanceScale?: number; + /** Random seed for image generation. This is not available when + ``add_watermark`` is set to true. */ + seed?: number; + /** Filter level for safety filtering. */ + safetyFilterLevel?: SafetyFilterLevel; + /** Allows generation of people by the model. */ + personGeneration?: PersonGeneration; + /** Whether to report the safety scores of each generated image and + the positive prompt in the response. */ + includeSafetyAttributes?: boolean; + /** Whether to include the Responsible AI filter reason if the image + is filtered out of the response. */ + includeRaiReason?: boolean; + /** Language of the text in the prompt. */ + language?: ImagePromptLanguage; + /** MIME type of the generated image. */ + outputMimeType?: string; + /** Compression quality of the generated image (for ``image/jpeg`` + only). */ + outputCompressionQuality?: number; + /** Whether to add a watermark to the generated images. */ + addWatermark?: boolean; + /** User specified labels to track billing usage. */ + labels?: Record<string, string>; + /** The size of the largest dimension of the generated image. + Supported sizes are 1K and 2K (not supported for Imagen 3 models). */ + imageSize?: string; + /** Whether to use the prompt rewriting logic. */ + enhancePrompt?: boolean; +} + +/** The parameters for generating images. */ +export declare interface GenerateImagesParameters { + /** ID of the model to use. For a list of models, see `Google models + <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */ + model: string; + /** Text prompt that typically describes the images to output. + */ + prompt: string; + /** Configuration for generating images. + */ + config?: GenerateImagesConfig; +} + +/** The output images response. */ +export declare class GenerateImagesResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** List of generated images. */ + generatedImages?: GeneratedImage[]; + /** Safety attributes of the positive prompt. Only populated if + ``include_safety_attributes`` is set to True. */ + positivePromptSafetyAttributes?: SafetyAttributes; +} + +/** Configuration for generating videos. */ +export declare interface GenerateVideosConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** Number of output videos. */ + numberOfVideos?: number; + /** The gcs bucket where to save the generated videos. */ + outputGcsUri?: string; + /** Frames per second for video generation. */ + fps?: number; + /** Duration of the clip for video generation in seconds. */ + durationSeconds?: number; + /** The RNG seed. If RNG seed is exactly same for each request with + unchanged inputs, the prediction results will be consistent. Otherwise, + a random RNG seed will be used each time to produce a different + result. */ + seed?: number; + /** The aspect ratio for the generated video. 16:9 (landscape) and + 9:16 (portrait) are supported. */ + aspectRatio?: string; + /** The resolution for the generated video. 720p and 1080p are + supported. */ + resolution?: string; + /** Whether allow to generate person videos, and restrict to specific + ages. Supported values are: dont_allow, allow_adult. */ + personGeneration?: string; + /** The pubsub topic where to publish the video generation + progress. */ + pubsubTopic?: string; + /** Explicitly state what should not be included in the generated + videos. */ + negativePrompt?: string; + /** Whether to use the prompt rewriting logic. */ + enhancePrompt?: boolean; + /** Whether to generate audio along with the video. */ + generateAudio?: boolean; + /** Image to use as the last frame of generated videos. + Only supported for image to video use cases. */ + lastFrame?: Image_2; + /** The images to use as the references to generate the videos. + If this field is provided, the text prompt field must also be provided. + The image, video, or last_frame field are not supported. Each image must + be associated with a type. Veo 2 supports up to 3 asset images *or* 1 + style image. */ + referenceImages?: VideoGenerationReferenceImage[]; + /** The mask to use for generating videos. */ + mask?: VideoGenerationMask; + /** Compression quality of the generated videos. */ + compressionQuality?: VideoCompressionQuality; +} + +/** A video generation operation. */ +export declare class GenerateVideosOperation implements Operation<GenerateVideosResponse> { + /** The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`. */ + name?: string; + /** Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata. Any method that returns a long-running operation should document the metadata type, if any. */ + metadata?: Record<string, unknown>; + /** If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available. */ + done?: boolean; + /** The error result of the operation in case of failure or cancellation. */ + error?: Record<string, unknown>; + /** The generated videos. */ + response?: GenerateVideosResponse; + /** + * Instantiates an Operation of the same type as the one being called with the fields set from the API response. + * @internal + */ + _fromAPIResponse({ apiResponse, _isVertexAI, }: OperationFromAPIResponseParameters): Operation<GenerateVideosResponse>; + /** The full HTTP response. */ + sdkHttpResponse?: HttpResponse; +} + +/** Class that represents the parameters for generating videos. */ +export declare interface GenerateVideosParameters { + /** ID of the model to use. For a list of models, see `Google models + <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */ + model: string; + /** The text prompt for generating the videos. + Optional if image or video is provided. */ + prompt?: string; + /** The input image for generating the videos. + Optional if prompt is provided. Not allowed if video is provided. */ + image?: Image_2; + /** The input video for video extension use cases. + Optional if prompt is provided. Not allowed if image is provided. */ + video?: Video; + /** A set of source input(s) for video generation. */ + source?: GenerateVideosSource; + /** Configuration for generating videos. */ + config?: GenerateVideosConfig; +} + +/** Response with generated videos. */ +export declare class GenerateVideosResponse { + /** List of the generated videos */ + generatedVideos?: GeneratedVideo[]; + /** Returns if any videos were filtered due to RAI policies. */ + raiMediaFilteredCount?: number; + /** Returns rai failure reasons if any. */ + raiMediaFilteredReasons?: string[]; +} + +/** A set of source input(s) for video generation. */ +export declare interface GenerateVideosSource { + /** The text prompt for generating the videos. + Optional if image or video is provided. */ + prompt?: string; + /** The input image for generating the videos. + Optional if prompt is provided. Not allowed if video is provided. */ + image?: Image_2; + /** The input video for video extension use cases. + Optional if prompt is provided. Not allowed if image is provided. */ + video?: Video; +} + +/** Generation config. */ +export declare interface GenerationConfig { + /** Optional. Config for model selection. */ + modelSelectionConfig?: ModelSelectionConfig; + /** Output schema of the generated response. This is an alternative to + `response_schema` that accepts [JSON Schema](https://json-schema.org/). + */ + responseJsonSchema?: unknown; + /** Optional. If enabled, audio timestamp will be included in the request to the model. This field is not supported in Gemini API. */ + audioTimestamp?: boolean; + /** Optional. Number of candidates to generate. */ + candidateCount?: number; + /** Optional. If enabled, the model will detect emotions and adapt its responses accordingly. This field is not supported in Gemini API. */ + enableAffectiveDialog?: boolean; + /** Optional. Frequency penalties. */ + frequencyPenalty?: number; + /** Optional. Logit probabilities. */ + logprobs?: number; + /** Optional. The maximum number of output tokens to generate per message. */ + maxOutputTokens?: number; + /** Optional. If specified, the media resolution specified will be used. */ + mediaResolution?: MediaResolution; + /** Optional. Positive penalties. */ + presencePenalty?: number; + /** Optional. If true, export the logprobs results in response. */ + responseLogprobs?: boolean; + /** Optional. Output response mimetype of the generated candidate text. Supported mimetype: - `text/plain`: (default) Text output. - `application/json`: JSON response in the candidates. The model needs to be prompted to output the appropriate response type, otherwise the behavior is undefined. This is a preview feature. */ + responseMimeType?: string; + /** Optional. The modalities of the response. */ + responseModalities?: Modality[]; + /** Optional. The `Schema` object allows the definition of input and output data types. These types can be objects, but also primitives and arrays. Represents a select subset of an [OpenAPI 3.0 schema object](https://spec.openapis.org/oas/v3.0.3#schema). If set, a compatible response_mime_type must also be set. Compatible mimetypes: `application/json`: Schema for JSON response. */ + responseSchema?: Schema; + /** Optional. Routing configuration. This field is not supported in Gemini API. */ + routingConfig?: GenerationConfigRoutingConfig; + /** Optional. Seed. */ + seed?: number; + /** Optional. The speech generation config. */ + speechConfig?: SpeechConfig; + /** Optional. Stop sequences. */ + stopSequences?: string[]; + /** Optional. Controls the randomness of predictions. */ + temperature?: number; + /** Optional. Config for thinking features. An error will be returned if this field is set for models that don't support thinking. */ + thinkingConfig?: ThinkingConfig; + /** Optional. If specified, top-k sampling will be used. */ + topK?: number; + /** Optional. If specified, nucleus sampling will be used. */ + topP?: number; + /** Optional. Enables enhanced civic answers. It may not be available for all models. This field is not supported in Vertex AI. */ + enableEnhancedCivicAnswers?: boolean; +} + +/** + * Configuration parameters for model interactions. + */ +declare interface GenerationConfig_2 { + /** + * Configuration for image interaction. + */ + image_config?: ImageConfig_2; + /** + * The maximum number of tokens to include in the response. + */ + max_output_tokens?: number; + /** + * Seed used in decoding for reproducibility. + */ + seed?: number; + /** + * Configuration for speech interaction. + */ + speech_config?: Array<SpeechConfig_2>; + /** + * A list of character sequences that will stop output interaction. + */ + stop_sequences?: Array<string>; + /** + * Controls the randomness of the output. + */ + temperature?: number; + /** + * The level of thought tokens that the model should generate. + */ + thinking_level?: ThinkingLevel_2; + /** + * Whether to include thought summaries in the response. + */ + thinking_summaries?: 'auto' | 'none'; + /** + * The tool choice for the interaction. + */ + tool_choice?: ToolChoice; + /** + * The maximum cumulative probability of tokens to consider when sampling. + */ + top_p?: number; +} + +/** The configuration for routing the request to a specific model. This data type is not supported in Gemini API. */ +export declare interface GenerationConfigRoutingConfig { + /** Automated routing. */ + autoMode?: GenerationConfigRoutingConfigAutoRoutingMode; + /** Manual routing. */ + manualMode?: GenerationConfigRoutingConfigManualRoutingMode; +} + +/** When automated routing is specified, the routing will be determined by the pretrained routing model and customer provided model routing preference. This data type is not supported in Gemini API. */ +export declare interface GenerationConfigRoutingConfigAutoRoutingMode { + /** The model routing preference. */ + modelRoutingPreference?: 'UNKNOWN' | 'PRIORITIZE_QUALITY' | 'BALANCED' | 'PRIORITIZE_COST'; +} + +/** When manual routing is set, the specified model will be used directly. This data type is not supported in Gemini API. */ +export declare interface GenerationConfigRoutingConfigManualRoutingMode { + /** The model name to use. Only the public LLM models are accepted. See [Supported models](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference#supported-models). */ + modelName?: string; +} + +/** + * Config for thinking feature. + * + * @deprecated This interface will be deprecated. Please use `ThinkingConfig` instead. + */ +export declare interface GenerationConfigThinkingConfig extends ThinkingConfig { +} + +/** Optional parameters. */ +export declare interface GetBatchJobConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Config for batches.get parameters. */ +export declare interface GetBatchJobParameters { + /** A fully-qualified BatchJob resource name or ID. + Example: "projects/.../locations/.../batchPredictionJobs/456" + or "456" when project and location are initialized in the client. + */ + name: string; + /** Optional parameters for the request. */ + config?: GetBatchJobConfig; +} + +/** Optional parameters for caches.get method. */ +export declare interface GetCachedContentConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Parameters for caches.get method. */ +export declare interface GetCachedContentParameters { + /** The server-generated resource name of the cached content. + */ + name: string; + /** Optional parameters for the request. + */ + config?: GetCachedContentConfig; +} + +/** Optional Config. */ +export declare interface GetDocumentConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Parameters for documents.get. */ +export declare interface GetDocumentParameters { + /** The resource name of the Document. + Example: fileSearchStores/file-search-store-foo/documents/documents-bar */ + name: string; + /** Optional parameters for the request. */ + config?: GetDocumentConfig; +} + +/** Used to override the default configuration. */ +export declare interface GetFileConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Generates the parameters for the get method. */ +export declare interface GetFileParameters { + /** The name identifier for the file to retrieve. */ + name: string; + /** Used to override the default configuration. */ + config?: GetFileConfig; +} + +/** Optional parameters for getting a FileSearchStore. */ +export declare interface GetFileSearchStoreConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Config for file_search_stores.get parameters. */ +export declare interface GetFileSearchStoreParameters { + /** The resource name of the FileSearchStore. Example: `fileSearchStores/my-file-search-store-123` */ + name: string; + /** Optional parameters for the request. */ + config?: GetFileSearchStoreConfig; +} + +/** Optional parameters for models.get method. */ +export declare interface GetModelConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +export declare interface GetModelParameters { + model: string; + /** Optional parameters for the request. */ + config?: GetModelConfig; +} + +export declare interface GetOperationConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Parameters for the GET method. */ +export declare interface GetOperationParameters { + /** The server-assigned name for the operation. */ + operationName: string; + /** Used to override the default configuration. */ + config?: GetOperationConfig; +} + +/** Optional parameters for tunings.get method. */ +export declare interface GetTuningJobConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Parameters for the get method. */ +export declare interface GetTuningJobParameters { + name: string; + /** Optional parameters for the request. */ + config?: GetTuningJobConfig; +} + +/** + * The Google GenAI SDK. + * + * @remarks + * Provides access to the GenAI features through either the {@link + * https://cloud.google.com/vertex-ai/docs/reference/rest | Gemini API} or + * the {@link https://cloud.google.com/vertex-ai/docs/reference/rest | Vertex AI + * API}. + * + * The {@link GoogleGenAIOptions.vertexai} value determines which of the API + * services to use. + * + * When using the Gemini API, a {@link GoogleGenAIOptions.apiKey} must also be + * set. When using Vertex AI, both {@link GoogleGenAIOptions.project} and {@link + * GoogleGenAIOptions.location} must be set, or a {@link + * GoogleGenAIOptions.apiKey} must be set when using Express Mode. + * + * Explicitly passed in values in {@link GoogleGenAIOptions} will always take + * precedence over environment variables. If both project/location and api_key + * exist in the environment variables, the project/location will be used. + * + * @example + * Initializing the SDK for using the Gemini API: + * ```ts + * import {GoogleGenAI} from '@google/genai'; + * const ai = new GoogleGenAI({apiKey: 'GEMINI_API_KEY'}); + * ``` + * + * @example + * Initializing the SDK for using the Vertex AI API: + * ```ts + * import {GoogleGenAI} from '@google/genai'; + * const ai = new GoogleGenAI({ + * vertexai: true, + * project: 'PROJECT_ID', + * location: 'PROJECT_LOCATION' + * }); + * ``` + * + */ +export declare class GoogleGenAI { + protected readonly apiClient: ApiClient; + private readonly apiKey?; + readonly vertexai: boolean; + private readonly googleAuthOptions?; + private readonly project?; + private readonly location?; + private readonly apiVersion?; + private readonly httpOptions?; + readonly models: Models; + readonly live: Live; + readonly batches: Batches; + readonly chats: Chats; + readonly caches: Caches; + readonly files: Files; + readonly operations: Operations; + readonly authTokens: Tokens; + readonly tunings: Tunings; + readonly fileSearchStores: FileSearchStores; + private _interactions; + get interactions(): Interactions; + constructor(options: GoogleGenAIOptions); +} + +/** + * Google Gen AI SDK's configuration options. + * + * See {@link GoogleGenAI} for usage samples. + */ +export declare interface GoogleGenAIOptions { + /** + * Optional. Determines whether to use the Vertex AI or the Gemini API. + * + * @remarks + * When true, the {@link https://cloud.google.com/vertex-ai/docs/reference/rest | Vertex AI API} will used. + * When false, the {@link https://ai.google.dev/api | Gemini API} will be used. + * + * If unset, default SDK behavior is to use the Gemini API service. + */ + vertexai?: boolean; + /** + * Optional. The Google Cloud project ID for Vertex AI clients. + * + * Find your project ID: https://cloud.google.com/resource-manager/docs/creating-managing-projects#identifying_projects + * + * @remarks + * Only supported on Node runtimes, ignored on browser runtimes. + */ + project?: string; + /** + * Optional. The Google Cloud project {@link https://cloud.google.com/vertex-ai/generative-ai/docs/learn/locations | location} for Vertex AI clients. + * + * @remarks + * Only supported on Node runtimes, ignored on browser runtimes. + * + */ + location?: string; + /** + * The API Key, required for Gemini API clients. + * + * @remarks + * Required on browser runtimes. + */ + apiKey?: string; + /** + * Optional. The API version to use. + * + * @remarks + * If unset, the default API version will be used. + */ + apiVersion?: string; + /** + * Optional. Authentication options defined by the by google-auth-library for Vertex AI clients. + * + * @remarks + * @see {@link https://github.com/googleapis/google-auth-library-nodejs/blob/v9.15.0/src/auth/googleauth.ts | GoogleAuthOptions interface in google-auth-library-nodejs}. + * + * Only supported on Node runtimes, ignored on browser runtimes. + * + */ + googleAuthOptions?: GoogleAuthOptions; + /** + * Optional. A set of customizable configuration for HTTP requests. + */ + httpOptions?: HttpOptions; +} + +/** Tool to retrieve public maps data for grounding, powered by Google. */ +export declare interface GoogleMaps { + /** The authentication config to access the API. Only API key is supported. This field is not supported in Gemini API. */ + authConfig?: AuthConfig; + /** Optional. If true, include the widget context token in the response. */ + enableWidget?: boolean; +} + +/** The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors). This data type is not supported in Gemini API. */ +export declare interface GoogleRpcStatus { + /** The status code, which should be an enum value of google.rpc.Code. */ + code?: number; + /** A list of messages that carry the error details. There is a common set of message types for APIs to use. */ + details?: Record<string, unknown>[]; + /** A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the google.rpc.Status.details field, or localized by the client. */ + message?: string; +} + +/** GoogleSearch tool type. Tool to support Google Search in Model. Powered by Google. */ +export declare interface GoogleSearch { + /** Optional. List of domains to be excluded from the search results. The default limit is 2000 domains. Example: ["amazon.com", "facebook.com"]. This field is not supported in Gemini API. */ + excludeDomains?: string[]; + /** Optional. Sites with confidence level chosen & above this value will be blocked from the search results. This field is not supported in Gemini API. */ + blockingConfidence?: PhishBlockThreshold; + /** Optional. Filter search results to a specific time range. If customers set a start time, they must set an end time (and vice versa). This field is not supported in Vertex AI. */ + timeRangeFilter?: Interval; +} + +/** + * The arguments to pass to Google Search. + */ +declare interface GoogleSearchCallArguments { + /** + * Web search queries for the following-up web search. + */ + queries?: Array<string>; +} + +/** + * Google Search content. + */ +declare interface GoogleSearchCallContent { + type: 'google_search_call'; + /** + * A unique ID for this specific tool call. + */ + id?: string; + /** + * The arguments to pass to Google Search. + */ + arguments?: GoogleSearchCallArguments; +} + +/** + * The result of the Google Search. + */ +declare interface GoogleSearchResult { + /** + * Web content snippet that can be embedded in a web page or an app webview. + */ + rendered_content?: string; + /** + * Title of the search result. + */ + title?: string; + /** + * URI reference of the search result. + */ + url?: string; +} + +/** + * Google Search result content. + */ +declare interface GoogleSearchResultContent { + type: 'google_search_result'; + /** + * ID to match the ID from the google search call block. + */ + call_id?: string; + /** + * Whether the Google Search resulted in an error. + */ + is_error?: boolean; + /** + * The results of the Google Search. + */ + result?: Array<GoogleSearchResult>; + /** + * The signature of the Google Search result. + */ + signature?: string; +} + +/** Tool to retrieve public web data for grounding, powered by Google. */ +export declare interface GoogleSearchRetrieval { + /** Specifies the dynamic retrieval configuration for the given source. */ + dynamicRetrievalConfig?: DynamicRetrievalConfig; +} + +/** Represents a whole or partial calendar date, such as a birthday. The time of day and time zone are either specified elsewhere or are insignificant. The date is relative to the Gregorian Calendar. This can represent one of the following: * A full date, with non-zero year, month, and day values. * A month and day, with a zero year (for example, an anniversary). * A year on its own, with a zero month and a zero day. * A year and month, with a zero day (for example, a credit card expiration date). Related types: * google.type.TimeOfDay * google.type.DateTime * google.protobuf.Timestamp. This data type is not supported in Gemini API. */ +export declare interface GoogleTypeDate { + /** Day of a month. Must be from 1 to 31 and valid for the year and month, or 0 to specify a year by itself or a year and month where the day isn't significant. */ + day?: number; + /** Month of a year. Must be from 1 to 12, or 0 to specify a year without a month and day. */ + month?: number; + /** Year of the date. Must be from 1 to 9999, or 0 to specify a date without a year. */ + year?: number; +} + +/** Grounding chunk. */ +export declare interface GroundingChunk { + /** Grounding chunk from Google Maps. This field is not supported in Gemini API. */ + maps?: GroundingChunkMaps; + /** Grounding chunk from context retrieved by the retrieval tools. This field is not supported in Gemini API. */ + retrievedContext?: GroundingChunkRetrievedContext; + /** Grounding chunk from the web. */ + web?: GroundingChunkWeb; +} + +/** Chunk from Google Maps. This data type is not supported in Gemini API. */ +export declare interface GroundingChunkMaps { + /** Sources used to generate the place answer. This includes review snippets and photos that were used to generate the answer, as well as uris to flag content. */ + placeAnswerSources?: GroundingChunkMapsPlaceAnswerSources; + /** This Place's resource name, in `places/{place_id}` format. Can be used to look up the Place. */ + placeId?: string; + /** Text of the place answer. */ + text?: string; + /** Title of the place. */ + title?: string; + /** URI reference of the place. */ + uri?: string; +} + +/** Sources used to generate the place answer. This data type is not supported in Gemini API. */ +export declare interface GroundingChunkMapsPlaceAnswerSources { + /** A link where users can flag a problem with the generated answer. */ + flagContentUri?: string; + /** Snippets of reviews that are used to generate the answer. */ + reviewSnippets?: GroundingChunkMapsPlaceAnswerSourcesReviewSnippet[]; +} + +/** Author attribution for a photo or review. This data type is not supported in Gemini API. */ +export declare interface GroundingChunkMapsPlaceAnswerSourcesAuthorAttribution { + /** Name of the author of the Photo or Review. */ + displayName?: string; + /** Profile photo URI of the author of the Photo or Review. */ + photoUri?: string; + /** URI of the author of the Photo or Review. */ + uri?: string; +} + +/** Encapsulates a review snippet. This data type is not supported in Gemini API. */ +export declare interface GroundingChunkMapsPlaceAnswerSourcesReviewSnippet { + /** This review's author. */ + authorAttribution?: GroundingChunkMapsPlaceAnswerSourcesAuthorAttribution; + /** A link where users can flag a problem with the review. */ + flagContentUri?: string; + /** A link to show the review on Google Maps. */ + googleMapsUri?: string; + /** A string of formatted recent time, expressing the review time relative to the current time in a form appropriate for the language and country. */ + relativePublishTimeDescription?: string; + /** A reference representing this place review which may be used to look up this place review again. */ + review?: string; + /** Id of the review referencing the place. */ + reviewId?: string; + /** Title of the review. */ + title?: string; +} + +/** Chunk from context retrieved by the retrieval tools. This data type is not supported in Gemini API. */ +export declare interface GroundingChunkRetrievedContext { + /** Output only. The full document name for the referenced Vertex AI Search document. */ + documentName?: string; + /** Additional context for the RAG retrieval result. This is only populated when using the RAG retrieval tool. */ + ragChunk?: RagChunk; + /** Text of the attribution. */ + text?: string; + /** Title of the attribution. */ + title?: string; + /** URI reference of the attribution. */ + uri?: string; +} + +/** Chunk from the web. */ +export declare interface GroundingChunkWeb { + /** Domain of the (original) URI. This field is not supported in Gemini API. */ + domain?: string; + /** Title of the chunk. */ + title?: string; + /** URI reference of the chunk. */ + uri?: string; +} + +/** Metadata returned to client when grounding is enabled. */ +export declare interface GroundingMetadata { + /** Optional. Output only. Resource name of the Google Maps widget context token to be used with the PlacesContextElement widget to render contextual data. This is populated only for Google Maps grounding. This field is not supported in Gemini API. */ + googleMapsWidgetContextToken?: string; + /** List of supporting references retrieved from specified grounding source. */ + groundingChunks?: GroundingChunk[]; + /** Optional. List of grounding support. */ + groundingSupports?: GroundingSupport[]; + /** Optional. Output only. Retrieval metadata. */ + retrievalMetadata?: RetrievalMetadata; + /** Optional. Queries executed by the retrieval tools. This field is not supported in Gemini API. */ + retrievalQueries?: string[]; + /** Optional. Google search entry for the following-up web searches. */ + searchEntryPoint?: SearchEntryPoint; + /** Optional. Output only. List of source flagging uris. This is currently populated only for Google Maps grounding. This field is not supported in Gemini API. */ + sourceFlaggingUris?: GroundingMetadataSourceFlaggingUri[]; + /** Optional. Web search queries for the following-up web search. */ + webSearchQueries?: string[]; +} + +/** Source content flagging uri for a place or review. This is currently populated only for Google Maps grounding. This data type is not supported in Gemini API. */ +export declare interface GroundingMetadataSourceFlaggingUri { + /** A link where users can flag a problem with the source (place or review). */ + flagContentUri?: string; + /** Id of the place or review. */ + sourceId?: string; +} + +/** Grounding support. */ +export declare interface GroundingSupport { + /** Confidence score of the support references. Ranges from 0 to 1. 1 is the most confident. For Gemini 2.0 and before, this list must have the same size as the grounding_chunk_indices. For Gemini 2.5 and after, this list will be empty and should be ignored. */ + confidenceScores?: number[]; + /** A list of indices (into 'grounding_chunk') specifying the citations associated with the claim. For instance [1,3,4] means that grounding_chunk[1], grounding_chunk[3], grounding_chunk[4] are the retrieved content attributed to the claim. */ + groundingChunkIndices?: number[]; + /** Segment of the content this support belongs to. */ + segment?: Segment; +} + +/** Specify if the threshold is used for probability or severity score. If not specified, the threshold is used for probability score. This enum is not supported in Gemini API. */ +export declare enum HarmBlockMethod { + /** + * The harm block method is unspecified. + */ + HARM_BLOCK_METHOD_UNSPECIFIED = "HARM_BLOCK_METHOD_UNSPECIFIED", + /** + * The harm block method uses both probability and severity scores. + */ + SEVERITY = "SEVERITY", + /** + * The harm block method uses the probability score. + */ + PROBABILITY = "PROBABILITY" +} + +/** The harm block threshold. */ +export declare enum HarmBlockThreshold { + /** + * Unspecified harm block threshold. + */ + HARM_BLOCK_THRESHOLD_UNSPECIFIED = "HARM_BLOCK_THRESHOLD_UNSPECIFIED", + /** + * Block low threshold and above (i.e. block more). + */ + BLOCK_LOW_AND_ABOVE = "BLOCK_LOW_AND_ABOVE", + /** + * Block medium threshold and above. + */ + BLOCK_MEDIUM_AND_ABOVE = "BLOCK_MEDIUM_AND_ABOVE", + /** + * Block only high threshold (i.e. block less). + */ + BLOCK_ONLY_HIGH = "BLOCK_ONLY_HIGH", + /** + * Block none. + */ + BLOCK_NONE = "BLOCK_NONE", + /** + * Turn off the safety filter. + */ + OFF = "OFF" +} + +/** Harm category. */ +export declare enum HarmCategory { + /** + * The harm category is unspecified. + */ + HARM_CATEGORY_UNSPECIFIED = "HARM_CATEGORY_UNSPECIFIED", + /** + * The harm category is harassment. + */ + HARM_CATEGORY_HARASSMENT = "HARM_CATEGORY_HARASSMENT", + /** + * The harm category is hate speech. + */ + HARM_CATEGORY_HATE_SPEECH = "HARM_CATEGORY_HATE_SPEECH", + /** + * The harm category is sexually explicit content. + */ + HARM_CATEGORY_SEXUALLY_EXPLICIT = "HARM_CATEGORY_SEXUALLY_EXPLICIT", + /** + * The harm category is dangerous content. + */ + HARM_CATEGORY_DANGEROUS_CONTENT = "HARM_CATEGORY_DANGEROUS_CONTENT", + /** + * Deprecated: Election filter is not longer supported. The harm category is civic integrity. + */ + HARM_CATEGORY_CIVIC_INTEGRITY = "HARM_CATEGORY_CIVIC_INTEGRITY", + /** + * The harm category is image hate. This enum value is not supported in Gemini API. + */ + HARM_CATEGORY_IMAGE_HATE = "HARM_CATEGORY_IMAGE_HATE", + /** + * The harm category is image dangerous content. This enum value is not supported in Gemini API. + */ + HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT = "HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT", + /** + * The harm category is image harassment. This enum value is not supported in Gemini API. + */ + HARM_CATEGORY_IMAGE_HARASSMENT = "HARM_CATEGORY_IMAGE_HARASSMENT", + /** + * The harm category is image sexually explicit content. This enum value is not supported in Gemini API. + */ + HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT = "HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT", + /** + * The harm category is for jailbreak prompts. This enum value is not supported in Gemini API. + */ + HARM_CATEGORY_JAILBREAK = "HARM_CATEGORY_JAILBREAK" +} + +/** Output only. Harm probability levels in the content. */ +export declare enum HarmProbability { + /** + * Harm probability unspecified. + */ + HARM_PROBABILITY_UNSPECIFIED = "HARM_PROBABILITY_UNSPECIFIED", + /** + * Negligible level of harm. + */ + NEGLIGIBLE = "NEGLIGIBLE", + /** + * Low level of harm. + */ + LOW = "LOW", + /** + * Medium level of harm. + */ + MEDIUM = "MEDIUM", + /** + * High level of harm. + */ + HIGH = "HIGH" +} + +/** Output only. Harm severity levels in the content. This enum is not supported in Gemini API. */ +export declare enum HarmSeverity { + /** + * Harm severity unspecified. + */ + HARM_SEVERITY_UNSPECIFIED = "HARM_SEVERITY_UNSPECIFIED", + /** + * Negligible level of harm severity. + */ + HARM_SEVERITY_NEGLIGIBLE = "HARM_SEVERITY_NEGLIGIBLE", + /** + * Low level of harm severity. + */ + HARM_SEVERITY_LOW = "HARM_SEVERITY_LOW", + /** + * Medium level of harm severity. + */ + HARM_SEVERITY_MEDIUM = "HARM_SEVERITY_MEDIUM", + /** + * High level of harm severity. + */ + HARM_SEVERITY_HIGH = "HARM_SEVERITY_HIGH" +} + +declare type HeadersLike = Headers | readonly HeaderValue[][] | Record<string, HeaderValue | readonly HeaderValue[]> | undefined | null | NullableHeaders; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +declare type HeaderValue = string | undefined | null; + +/** The location of the API key. This enum is not supported in Gemini API. */ +export declare enum HttpElementLocation { + HTTP_IN_UNSPECIFIED = "HTTP_IN_UNSPECIFIED", + /** + * Element is in the HTTP request query. + */ + HTTP_IN_QUERY = "HTTP_IN_QUERY", + /** + * Element is in the HTTP request header. + */ + HTTP_IN_HEADER = "HTTP_IN_HEADER", + /** + * Element is in the HTTP request path. + */ + HTTP_IN_PATH = "HTTP_IN_PATH", + /** + * Element is in the HTTP request body. + */ + HTTP_IN_BODY = "HTTP_IN_BODY", + /** + * Element is in the HTTP request cookie. + */ + HTTP_IN_COOKIE = "HTTP_IN_COOKIE" +} + +declare type HTTPMethod = 'get' | 'post' | 'put' | 'patch' | 'delete'; + +/** HTTP options to be used in each of the requests. */ +export declare interface HttpOptions { + /** The base URL for the AI platform service endpoint. */ + baseUrl?: string; + /** The resource scope used to constructing the resource name when base_url is set */ + baseUrlResourceScope?: ResourceScope; + /** Specifies the version of the API to use. */ + apiVersion?: string; + /** Additional HTTP headers to be sent with the request. */ + headers?: Record<string, string>; + /** Timeout for the request in milliseconds. */ + timeout?: number; + /** Extra parameters to add to the request body. + The structure must match the backend API's request structure. + - VertexAI backend API docs: https://cloud.google.com/vertex-ai/docs/reference/rest + - GeminiAPI backend API docs: https://ai.google.dev/api/rest */ + extraBody?: Record<string, unknown>; + /** HTTP retry options for the request. */ + retryOptions?: HttpRetryOptions; +} + +/** + * Represents the necessary information to send a request to an API endpoint. + * This interface defines the structure for constructing and executing HTTP + * requests. + */ +declare interface HttpRequest { + /** + * URL path from the modules, this path is appended to the base API URL to + * form the complete request URL. + * + * If you wish to set full URL, use httpOptions.baseUrl instead. Example to + * set full URL in the request: + * + * const request: HttpRequest = { + * path: '', + * httpOptions: { + * baseUrl: 'https://<custom-full-url>', + * apiVersion: '', + * }, + * httpMethod: 'GET', + * }; + * + * The result URL will be: https://<custom-full-url> + * + */ + path: string; + /** + * Optional query parameters to be appended to the request URL. + */ + queryParams?: Record<string, string>; + /** + * Optional request body in json string or Blob format, GET request doesn't + * need a request body. + */ + body?: string | Blob; + /** + * The HTTP method to be used for the request. + */ + httpMethod: 'GET' | 'POST' | 'PATCH' | 'DELETE'; + /** + * Optional set of customizable configuration for HTTP requests. + */ + httpOptions?: types.HttpOptions; + /** + * Optional abort signal which can be used to cancel the request. + */ + abortSignal?: AbortSignal; +} + +/** A wrapper class for the http response. */ +export declare class HttpResponse { + /** Used to retain the processed HTTP headers in the response. */ + headers?: Record<string, string>; + /** + * The original http response. + */ + responseInternal: Response; + constructor(response: Response); + json(): Promise<unknown>; +} + +/** HTTP retry options to be used in each of the requests. */ +export declare interface HttpRetryOptions { + /** Maximum number of attempts, including the original request. + If 0 or 1, it means no retries. If not specified, default to 5. */ + attempts?: number; +} + +/** An image. */ +declare interface Image_2 { + /** The Cloud Storage URI of the image. ``Image`` can contain a value + for this field or the ``image_bytes`` field but not both. */ + gcsUri?: string; + /** The image bytes data. ``Image`` can contain a value for this field + or the ``gcs_uri`` field but not both. + * @remarks Encoded as base64 string. */ + imageBytes?: string; + /** The MIME type of the image. */ + mimeType?: string; +} +export { Image_2 as Image } + +/** The image generation configuration to be used in GenerateContentConfig. */ +export declare interface ImageConfig { + /** Aspect ratio of the generated images. Supported values are + "1:1", "2:3", "3:2", "3:4", "4:3", "9:16", "16:9", and "21:9". */ + aspectRatio?: string; + /** Optional. Specifies the size of generated images. Supported + values are `1K`, `2K`, `4K`. If not specified, the model will use default + value `1K`. */ + imageSize?: string; + /** Controls the generation of people. Supported values are: + ALLOW_ALL, ALLOW_ADULT, ALLOW_NONE. */ + personGeneration?: string; + /** MIME type of the generated image. This field is not + supported in Gemini API. */ + outputMimeType?: string; + /** Compression quality of the generated image (for + ``image/jpeg`` only). This field is not supported in Gemini API. */ + outputCompressionQuality?: number; +} + +/** + * The configuration for image interaction. + */ +declare interface ImageConfig_2 { + aspect_ratio?: '1:1' | '2:3' | '3:2' | '3:4' | '4:3' | '4:5' | '5:4' | '9:16' | '16:9' | '21:9'; + image_size?: '1K' | '2K' | '4K'; +} + +/** + * An image content block. + */ +declare interface ImageContent { + type: 'image'; + /** + * The image content. + */ + data?: string; + /** + * The mime type of the image. + */ + mime_type?: ImageMimeType; + /** + * The resolution of the media. + */ + resolution?: 'low' | 'medium' | 'high' | 'ultra_high'; + /** + * The URI of the image. + */ + uri?: string; +} + +/** + * The mime type of the image. + */ +declare type ImageMimeType = 'image/png' | 'image/jpeg' | 'image/webp' | 'image/heic' | 'image/heif' | (string & {}); + +/** Enum that specifies the language of the text in the prompt. */ +export declare enum ImagePromptLanguage { + /** + * Auto-detect the language. + */ + auto = "auto", + /** + * English + */ + en = "en", + /** + * Japanese + */ + ja = "ja", + /** + * Korean + */ + ko = "ko", + /** + * Hindi + */ + hi = "hi", + /** + * Chinese + */ + zh = "zh", + /** + * Portuguese + */ + pt = "pt", + /** + * Spanish + */ + es = "es" +} + +/** Optional parameters for importing a file. */ +export declare interface ImportFileConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** User provided custom metadata stored as key-value pairs used for querying. */ + customMetadata?: CustomMetadata[]; + /** Config for telling the service how to chunk the file. */ + chunkingConfig?: ChunkingConfig; +} + +/** Long-running operation for importing a file to a FileSearchStore. */ +export declare class ImportFileOperation implements Operation<ImportFileResponse> { + /** The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`. */ + name?: string; + /** Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata. Any method that returns a long-running operation should document the metadata type, if any. */ + metadata?: Record<string, unknown>; + /** If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available. */ + done?: boolean; + /** The error result of the operation in case of failure or cancellation. */ + error?: Record<string, unknown>; + /** The result of the ImportFile operation, available when the operation is done. */ + response?: ImportFileResponse; + /** + * Instantiates an Operation of the same type as the one being called with the fields set from the API response. + * @internal + */ + _fromAPIResponse({ apiResponse, _isVertexAI, }: OperationFromAPIResponseParameters): Operation<ImportFileResponse>; + /** The full HTTP response. */ + sdkHttpResponse?: HttpResponse; +} + +/** Config for file_search_stores.import_file parameters. */ +export declare interface ImportFileParameters { + /** The resource name of the FileSearchStore. Example: `fileSearchStores/my-file-search-store-123` */ + fileSearchStoreName: string; + /** The name of the File API File to import. Example: `files/abc-123` */ + fileName: string; + /** Optional parameters for the request. */ + config?: ImportFileConfig; +} + +/** Response for ImportFile to import a File API file with a file search store. */ +export declare class ImportFileResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** The name of the FileSearchStore containing Documents. */ + parent?: string; + /** The identifier for the Document imported. */ + documentName?: string; +} + +/** Config for `inlined_embedding_responses` parameter. */ +export declare class InlinedEmbedContentResponse { + /** The response to the request. + */ + response?: SingleEmbedContentResponse; + /** The error encountered while processing the request. + */ + error?: JobError; +} + +/** Config for inlined request. */ +export declare interface InlinedRequest { + /** ID of the model to use. For a list of models, see `Google models + <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */ + model?: string; + /** Content of the request. + */ + contents?: ContentListUnion; + /** The metadata to be associated with the request. */ + metadata?: Record<string, string>; + /** Configuration that contains optional model parameters. + */ + config?: GenerateContentConfig; +} + +/** Config for `inlined_responses` parameter. */ +export declare class InlinedResponse { + /** The response to the request. + */ + response?: GenerateContentResponse; + /** The metadata to be associated with the request. */ + metadata?: Record<string, string>; + /** The error encountered while processing the request. + */ + error?: JobError; +} + +/** + * The Interaction resource. + */ +declare interface Interaction { + /** + * Output only. A unique identifier for the interaction completion. + */ + id: string; + /** + * Output only. The status of the interaction. + */ + status: 'in_progress' | 'requires_action' | 'completed' | 'failed' | 'cancelled' | 'incomplete'; + /** + * The name of the `Agent` used for generating the interaction. + */ + agent?: (string & {}) | 'deep-research-pro-preview-12-2025'; + /** + * Output only. The time at which the response was created in ISO 8601 format + * (YYYY-MM-DDThh:mm:ssZ). + */ + created?: string; + /** + * The name of the `Model` used for generating the interaction. + */ + model?: Model_2; + /** + * Output only. Responses from the model. + */ + outputs?: Array<Content_2>; + /** + * The ID of the previous interaction, if any. + */ + previous_interaction_id?: string; + /** + * Output only. The role of the interaction. + */ + role?: string; + /** + * Output only. The time at which the response was last updated in ISO 8601 format + * (YYYY-MM-DDThh:mm:ssZ). + */ + updated?: string; + /** + * Output only. Statistics on the interaction request's token usage. + */ + usage?: Usage; +} + +declare interface InteractionCancelParams { + /** + * Which version of the API to use. + */ + api_version?: string; +} + +declare interface InteractionCompleteEvent { + /** + * The event_id token to be used to resume the interaction stream, from this event. + */ + event_id?: string; + event_type?: 'interaction.complete'; + /** + * The Interaction resource. + */ + interaction?: Interaction; +} + +declare type InteractionCreateParams = CreateModelInteractionParamsNonStreaming | CreateModelInteractionParamsStreaming | CreateAgentInteractionParamsNonStreaming | CreateAgentInteractionParamsStreaming; + +declare interface InteractionDeleteParams { + /** + * Which version of the API to use. + */ + api_version?: string; +} + +declare type InteractionDeleteResponse = unknown; + +declare type InteractionGetParams = InteractionGetParamsNonStreaming | InteractionGetParamsStreaming; + +declare namespace InteractionGetParams { + type InteractionGetParamsNonStreaming = InteractionsAPI.InteractionGetParamsNonStreaming; + type InteractionGetParamsStreaming = InteractionsAPI.InteractionGetParamsStreaming; +} + +declare interface InteractionGetParamsBase { + /** + * Path param: Which version of the API to use. + */ + api_version?: string; + /** + * Query param: If set to true, includes the input in the response. + */ + include_input?: boolean; + /** + * Query param: Optional. If set, resumes the interaction stream from the next chunk after the event marked by the event id. Can only be used if `stream` is true. + */ + last_event_id?: string; + /** + * Query param: If set to true, the generated content will be streamed incrementally. + */ + stream?: boolean; +} + +declare interface InteractionGetParamsNonStreaming extends InteractionGetParamsBase { + /** + * Query param: If set to true, the generated content will be streamed incrementally. + */ + stream?: false; +} + +declare interface InteractionGetParamsStreaming extends InteractionGetParamsBase { + /** + * Query param: If set to true, the generated content will be streamed incrementally. + */ + stream: true; +} + +export declare class Interactions extends BaseInteractions { +} + +export declare namespace Interactions { + export { type AllowedTools as AllowedTools, type Annotation as Annotation, type AudioContent as AudioContent, type AudioMimeType as AudioMimeType, type CodeExecutionCallArguments as CodeExecutionCallArguments, type CodeExecutionCallContent as CodeExecutionCallContent, type CodeExecutionResultContent as CodeExecutionResultContent, type Content_2 as Content, type ContentDelta as ContentDelta, type ContentStart as ContentStart, type ContentStop as ContentStop, type DeepResearchAgentConfig as DeepResearchAgentConfig, type DocumentContent as DocumentContent, type DocumentMimeType as DocumentMimeType, type DynamicAgentConfig as DynamicAgentConfig, type ErrorEvent_2 as ErrorEvent, type FileSearchCallContent as FileSearchCallContent, type FileSearchResultContent as FileSearchResultContent, type Function_2 as Function, type FunctionCallContent as FunctionCallContent, type FunctionResultContent as FunctionResultContent, type GenerationConfig_2 as GenerationConfig, type GoogleSearchCallArguments as GoogleSearchCallArguments, type GoogleSearchCallContent as GoogleSearchCallContent, type GoogleSearchResult as GoogleSearchResult, type GoogleSearchResultContent as GoogleSearchResultContent, type ImageConfig_2 as ImageConfig, type ImageContent as ImageContent, type ImageMimeType as ImageMimeType, type Interaction as Interaction, type InteractionCompleteEvent as InteractionCompleteEvent, type InteractionSSEEvent as InteractionSSEEvent, type InteractionStartEvent as InteractionStartEvent, type InteractionStatusUpdate as InteractionStatusUpdate, type MCPServerToolCallContent as MCPServerToolCallContent, type MCPServerToolResultContent as MCPServerToolResultContent, type Model_2 as Model, type SpeechConfig_2 as SpeechConfig, type TextContent as TextContent, type ThinkingLevel_2 as ThinkingLevel, type ThoughtContent as ThoughtContent, type Tool_2 as Tool, type ToolChoice as ToolChoice, type ToolChoiceConfig as ToolChoiceConfig, type ToolChoiceType as ToolChoiceType, type Turn as Turn, type URLContextCallArguments as URLContextCallArguments, type URLContextCallContent as URLContextCallContent, type URLContextResult as URLContextResult, type URLContextResultContent as URLContextResultContent, type Usage as Usage, type VideoContent as VideoContent, type VideoMimeType as VideoMimeType, type InteractionDeleteResponse as InteractionDeleteResponse, type InteractionCreateParams as InteractionCreateParams, type CreateModelInteractionParamsNonStreaming as CreateModelInteractionParamsNonStreaming, type CreateModelInteractionParamsStreaming as CreateModelInteractionParamsStreaming, type CreateAgentInteractionParamsNonStreaming as CreateAgentInteractionParamsNonStreaming, type CreateAgentInteractionParamsStreaming as CreateAgentInteractionParamsStreaming, type InteractionDeleteParams as InteractionDeleteParams, type InteractionCancelParams as InteractionCancelParams, type InteractionGetParams as InteractionGetParams, type InteractionGetParamsNonStreaming as InteractionGetParamsNonStreaming, type InteractionGetParamsStreaming as InteractionGetParamsStreaming, }; +} + +declare namespace InteractionsAPI { + export { + BaseInteractions, + Interactions, + AllowedTools, + Annotation, + AudioContent, + AudioMimeType, + CodeExecutionCallArguments, + CodeExecutionCallContent, + CodeExecutionResultContent, + Content_2 as Content, + ContentDelta, + ContentStart, + ContentStop, + DeepResearchAgentConfig, + DocumentContent, + DocumentMimeType, + DynamicAgentConfig, + ErrorEvent_2 as ErrorEvent, + FileSearchCallContent, + FileSearchResultContent, + Function_2 as Function, + FunctionCallContent, + FunctionResultContent, + GenerationConfig_2 as GenerationConfig, + GoogleSearchCallArguments, + GoogleSearchCallContent, + GoogleSearchResult, + GoogleSearchResultContent, + ImageConfig_2 as ImageConfig, + ImageContent, + ImageMimeType, + Interaction, + InteractionCompleteEvent, + InteractionSSEEvent, + InteractionStartEvent, + InteractionStatusUpdate, + MCPServerToolCallContent, + MCPServerToolResultContent, + Model_2 as Model, + SpeechConfig_2 as SpeechConfig, + TextContent, + ThinkingLevel_2 as ThinkingLevel, + ThoughtContent, + Tool_2 as Tool, + ToolChoice, + ToolChoiceConfig, + ToolChoiceType, + Turn, + URLContextCallArguments, + URLContextCallContent, + URLContextResult, + URLContextResultContent, + Usage, + VideoContent, + VideoMimeType, + InteractionDeleteResponse, + InteractionCreateParams, + BaseCreateModelInteractionParams, + BaseCreateAgentInteractionParams, + CreateModelInteractionParamsNonStreaming, + CreateModelInteractionParamsStreaming, + CreateAgentInteractionParamsNonStreaming, + CreateAgentInteractionParamsStreaming, + InteractionDeleteParams, + InteractionCancelParams, + InteractionGetParams, + InteractionGetParamsBase, + InteractionGetParamsNonStreaming, + InteractionGetParamsStreaming + } +} + +declare type InteractionSSEEvent = InteractionStartEvent | InteractionCompleteEvent | InteractionStatusUpdate | ContentStart | ContentDelta | ContentStop | ErrorEvent_2; + +declare interface InteractionStartEvent { + /** + * The event_id token to be used to resume the interaction stream, from this event. + */ + event_id?: string; + event_type?: 'interaction.start'; + /** + * The Interaction resource. + */ + interaction?: Interaction; +} + +declare interface InteractionStatusUpdate { + /** + * The event_id token to be used to resume the interaction stream, from this event. + */ + event_id?: string; + event_type?: 'interaction.status_update'; + interaction_id?: string; + status?: 'in_progress' | 'requires_action' | 'completed' | 'failed' | 'cancelled' | 'incomplete'; +} + +/** Parameters for the private _Register method. */ +export declare interface InternalRegisterFilesParameters { + /** The Google Cloud Storage URIs to register. Example: `gs://bucket/object`. */ + uris: string[]; + /** Used to override the default configuration. */ + config?: RegisterFilesConfig; +} + +declare class InternalServerError extends APIError<number, Headers> { +} + +/** Represents a time interval, encoded as a Timestamp start (inclusive) and a Timestamp end (exclusive). The start must be less than or equal to the end. When the start equals the end, the interval is empty (matches no time). When both start and end are unspecified, the interval matches any time. */ +export declare interface Interval { + /** Optional. Exclusive end of the interval. If specified, a Timestamp matching this interval will have to be before the end. */ + endTime?: string; + /** Optional. Inclusive start of the interval. If specified, a Timestamp matching this interval will have to be the same or after the start. */ + startTime?: string; +} + +/** Job error. */ +export declare interface JobError { + /** A list of messages that carry the error details. There is a common set of message types for APIs to use. */ + details?: string[]; + /** The status code. */ + code?: number; + /** A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the `details` field. */ + message?: string; +} + +/** Job state. */ +export declare enum JobState { + /** + * The job state is unspecified. + */ + JOB_STATE_UNSPECIFIED = "JOB_STATE_UNSPECIFIED", + /** + * The job has been just created or resumed and processing has not yet begun. + */ + JOB_STATE_QUEUED = "JOB_STATE_QUEUED", + /** + * The service is preparing to run the job. + */ + JOB_STATE_PENDING = "JOB_STATE_PENDING", + /** + * The job is in progress. + */ + JOB_STATE_RUNNING = "JOB_STATE_RUNNING", + /** + * The job completed successfully. + */ + JOB_STATE_SUCCEEDED = "JOB_STATE_SUCCEEDED", + /** + * The job failed. + */ + JOB_STATE_FAILED = "JOB_STATE_FAILED", + /** + * The job is being cancelled. From this state the job may only go to either `JOB_STATE_SUCCEEDED`, `JOB_STATE_FAILED` or `JOB_STATE_CANCELLED`. + */ + JOB_STATE_CANCELLING = "JOB_STATE_CANCELLING", + /** + * The job has been cancelled. + */ + JOB_STATE_CANCELLED = "JOB_STATE_CANCELLED", + /** + * The job has been stopped, and can be resumed. + */ + JOB_STATE_PAUSED = "JOB_STATE_PAUSED", + /** + * The job has expired. + */ + JOB_STATE_EXPIRED = "JOB_STATE_EXPIRED", + /** + * The job is being updated. Only jobs in the `JOB_STATE_RUNNING` state can be updated. After updating, the job goes back to the `JOB_STATE_RUNNING` state. + */ + JOB_STATE_UPDATING = "JOB_STATE_UPDATING", + /** + * The job is partially succeeded, some results may be missing due to errors. + */ + JOB_STATE_PARTIALLY_SUCCEEDED = "JOB_STATE_PARTIALLY_SUCCEEDED" +} + +/** Programming language of the `code`. */ +export declare enum Language { + /** + * Unspecified language. This value should not be used. + */ + LANGUAGE_UNSPECIFIED = "LANGUAGE_UNSPECIFIED", + /** + * Python >= 3.10, with numpy and simpy available. + */ + PYTHON = "PYTHON" +} + +/** An object that represents a latitude/longitude pair. + + This is expressed as a pair of doubles to represent degrees latitude and + degrees longitude. Unless specified otherwise, this object must conform to the + <a href="https://en.wikipedia.org/wiki/World_Geodetic_System#1984_version"> + WGS84 standard</a>. Values must be within normalized ranges. */ +export declare interface LatLng { + /** The latitude in degrees. It must be in the range [-90.0, +90.0]. */ + latitude?: number; + /** The longitude in degrees. It must be in the range [-180.0, +180.0] */ + longitude?: number; +} + +/** Config for optional parameters. */ +export declare interface ListBatchJobsConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + pageSize?: number; + pageToken?: string; + filter?: string; +} + +/** Config for batches.list parameters. */ +export declare interface ListBatchJobsParameters { + config?: ListBatchJobsConfig; +} + +/** Config for batches.list return value. */ +export declare class ListBatchJobsResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + nextPageToken?: string; + batchJobs?: BatchJob[]; +} + +/** Config for caches.list method. */ +export declare interface ListCachedContentsConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + pageSize?: number; + pageToken?: string; +} + +/** Parameters for caches.list method. */ +export declare interface ListCachedContentsParameters { + /** Configuration that contains optional parameters. + */ + config?: ListCachedContentsConfig; +} + +export declare class ListCachedContentsResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + nextPageToken?: string; + /** List of cached contents. + */ + cachedContents?: CachedContent[]; +} + +/** Config for optional parameters. */ +export declare interface ListDocumentsConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + pageSize?: number; + pageToken?: string; +} + +/** Config for documents.list parameters. */ +export declare interface ListDocumentsParameters { + /** The resource name of the FileSearchStores. Example: `fileSearchStore/file-search-store-foo` */ + parent: string; + config?: ListDocumentsConfig; +} + +/** Config for documents.list return value. */ +export declare class ListDocumentsResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** A token, which can be sent as `page_token` to retrieve the next page. If this field is omitted, there are no more pages. */ + nextPageToken?: string; + /** The returned `Document`s. */ + documents?: Document_2[]; +} + +export declare interface ListFilesConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + pageSize?: number; + pageToken?: string; +} + +/** Optional parameters for listing FileSearchStore. */ +export declare interface ListFileSearchStoresConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + pageSize?: number; + pageToken?: string; +} + +/** Config for file_search_stores.list parameters. */ +export declare interface ListFileSearchStoresParameters { + /** Optional parameters for the list request. */ + config?: ListFileSearchStoresConfig; +} + +/** Config for file_search_stores.list return value. */ +export declare class ListFileSearchStoresResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + nextPageToken?: string; + /** The returned file search stores. */ + fileSearchStores?: FileSearchStore[]; +} + +/** Generates the parameters for the list method. */ +export declare interface ListFilesParameters { + /** Used to override the default configuration. */ + config?: ListFilesConfig; +} + +/** Response for the list files method. */ +export declare class ListFilesResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** A token that can be sent as a `page_token` into a subsequent `ListFiles` call. */ + nextPageToken?: string; + /** The list of `File`s. */ + files?: File_2[]; +} + +export declare interface ListModelsConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + pageSize?: number; + pageToken?: string; + filter?: string; + /** Set true to list base models, false to list tuned models. */ + queryBase?: boolean; +} + +export declare interface ListModelsParameters { + config?: ListModelsConfig; +} + +export declare class ListModelsResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + nextPageToken?: string; + models?: Model[]; +} + +/** Configuration for the list tuning jobs method. */ +export declare interface ListTuningJobsConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + pageSize?: number; + pageToken?: string; + filter?: string; +} + +/** Parameters for the list tuning jobs method. */ +export declare interface ListTuningJobsParameters { + config?: ListTuningJobsConfig; +} + +/** Response for the list tuning jobs method. */ +export declare class ListTuningJobsResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** A token to retrieve the next page of results. Pass to ListTuningJobsRequest.page_token to obtain that page. */ + nextPageToken?: string; + /** List of TuningJobs in the requested page. */ + tuningJobs?: TuningJob[]; +} + +/** + Live class encapsulates the configuration for live interaction with the + Generative Language API. It embeds ApiClient for general API settings. + + @experimental + */ +export declare class Live { + private readonly apiClient; + private readonly auth; + private readonly webSocketFactory; + readonly music: LiveMusic; + constructor(apiClient: ApiClient, auth: Auth, webSocketFactory: WebSocketFactory); + /** + Establishes a connection to the specified model with the given + configuration and returns a Session object representing that connection. + + @experimental Built-in MCP support is an experimental feature, may change in + future versions. + + @remarks + + @param params - The parameters for establishing a connection to the model. + @return A live session. + + @example + ```ts + let model: string; + if (GOOGLE_GENAI_USE_VERTEXAI) { + model = 'gemini-2.0-flash-live-preview-04-09'; + } else { + model = 'gemini-live-2.5-flash-preview'; + } + const session = await ai.live.connect({ + model: model, + config: { + responseModalities: [Modality.AUDIO], + }, + callbacks: { + onopen: () => { + console.log('Connected to the socket.'); + }, + onmessage: (e: MessageEvent) => { + console.log('Received message from the server: %s\n', debug(e.data)); + }, + onerror: (e: ErrorEvent) => { + console.log('Error occurred: %s\n', debug(e.error)); + }, + onclose: (e: CloseEvent) => { + console.log('Connection closed.'); + }, + }, + }); + ``` + */ + connect(params: types.LiveConnectParameters): Promise<Session>; + private isCallableTool; +} + +/** Callbacks for the live API. */ +export declare interface LiveCallbacks { + /** + * Called when the websocket connection is established. + */ + onopen?: (() => void) | null; + /** + * Called when a message is received from the server. + */ + onmessage: (e: LiveServerMessage) => void; + /** + * Called when an error occurs. + */ + onerror?: ((e: ErrorEvent) => void) | null; + /** + * Called when the websocket connection is closed. + */ + onclose?: ((e: CloseEvent) => void) | null; +} + +/** Incremental update of the current conversation delivered from the client. + + All the content here will unconditionally be appended to the conversation + history and used as part of the prompt to the model to generate content. + + A message here will interrupt any current model generation. */ +export declare interface LiveClientContent { + /** The content appended to the current conversation with the model. + + For single-turn queries, this is a single instance. For multi-turn + queries, this is a repeated field that contains conversation history and + latest request. + */ + turns?: Content[]; + /** If true, indicates that the server content generation should start with + the currently accumulated prompt. Otherwise, the server will await + additional messages before starting generation. */ + turnComplete?: boolean; +} + +/** Messages sent by the client in the API call. */ +export declare interface LiveClientMessage { + /** Message to be sent by the system when connecting to the API. SDK users should not send this message. */ + setup?: LiveClientSetup; + /** Incremental update of the current conversation delivered from the client. */ + clientContent?: LiveClientContent; + /** User input that is sent in real time. */ + realtimeInput?: LiveClientRealtimeInput; + /** Response to a `ToolCallMessage` received from the server. */ + toolResponse?: LiveClientToolResponse; +} + +/** User input that is sent in real time. + + This is different from `LiveClientContent` in a few ways: + + - Can be sent continuously without interruption to model generation. + - If there is a need to mix data interleaved across the + `LiveClientContent` and the `LiveClientRealtimeInput`, server attempts to + optimize for best response, but there are no guarantees. + - End of turn is not explicitly specified, but is rather derived from user + activity (for example, end of speech). + - Even before the end of turn, the data is processed incrementally + to optimize for a fast start of the response from the model. + - Is always assumed to be the user's input (cannot be used to populate + conversation history). */ +export declare interface LiveClientRealtimeInput { + /** Inlined bytes data for media input. */ + mediaChunks?: Blob_2[]; + /** The realtime audio input stream. */ + audio?: Blob_2; + /** + Indicates that the audio stream has ended, e.g. because the microphone was + turned off. + + This should only be sent when automatic activity detection is enabled + (which is the default). + + The client can reopen the stream by sending an audio message. + */ + audioStreamEnd?: boolean; + /** The realtime video input stream. */ + video?: Blob_2; + /** The realtime text input stream. */ + text?: string; + /** Marks the start of user activity. */ + activityStart?: ActivityStart; + /** Marks the end of user activity. */ + activityEnd?: ActivityEnd; +} + +/** Message contains configuration that will apply for the duration of the streaming session. */ +export declare interface LiveClientSetup { + /** + The fully qualified name of the publisher model or tuned model endpoint to + use. + */ + model?: string; + /** The generation configuration for the session. + Note: only a subset of fields are supported. + */ + generationConfig?: GenerationConfig; + /** The user provided system instructions for the model. + Note: only text should be used in parts and content in each part will be + in a separate paragraph. */ + systemInstruction?: ContentUnion; + /** A list of `Tools` the model may use to generate the next response. + + A `Tool` is a piece of code that enables the system to interact with + external systems to perform an action, or set of actions, outside of + knowledge and scope of the model. */ + tools?: ToolListUnion; + /** Configures the realtime input behavior in BidiGenerateContent. */ + realtimeInputConfig?: RealtimeInputConfig; + /** Configures session resumption mechanism. + + If included server will send SessionResumptionUpdate messages. */ + sessionResumption?: SessionResumptionConfig; + /** Configures context window compression mechanism. + + If included, server will compress context window to fit into given length. */ + contextWindowCompression?: ContextWindowCompressionConfig; + /** The transcription of the input aligns with the input audio language. + */ + inputAudioTranscription?: AudioTranscriptionConfig; + /** The transcription of the output aligns with the language code + specified for the output audio. + */ + outputAudioTranscription?: AudioTranscriptionConfig; + /** Configures the proactivity of the model. This allows the model to respond proactively to + the input and to ignore irrelevant input. */ + proactivity?: ProactivityConfig; + /** Configures the explicit VAD signal. If enabled, the client will send + vad_signal to indicate the start and end of speech. This allows the server + to process the audio more efficiently. */ + explicitVadSignal?: boolean; +} + +/** Client generated response to a `ToolCall` received from the server. + + Individual `FunctionResponse` objects are matched to the respective + `FunctionCall` objects by the `id` field. + + Note that in the unary and server-streaming GenerateContent APIs function + calling happens by exchanging the `Content` parts, while in the bidi + GenerateContent APIs function calling happens over this dedicated set of + messages. */ +export declare class LiveClientToolResponse { + /** The response to the function calls. */ + functionResponses?: FunctionResponse[]; +} + +/** Session config for the API connection. */ +export declare interface LiveConnectConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** The generation configuration for the session. */ + generationConfig?: GenerationConfig; + /** The requested modalities of the response. Represents the set of + modalities that the model can return. Defaults to AUDIO if not specified. + */ + responseModalities?: Modality[]; + /** Value that controls the degree of randomness in token selection. + Lower temperatures are good for prompts that require a less open-ended or + creative response, while higher temperatures can lead to more diverse or + creative results. + */ + temperature?: number; + /** Tokens are selected from the most to least probable until the sum + of their probabilities equals this value. Use a lower value for less + random responses and a higher value for more random responses. + */ + topP?: number; + /** For each token selection step, the ``top_k`` tokens with the + highest probabilities are sampled. Then tokens are further filtered based + on ``top_p`` with the final token selected using temperature sampling. Use + a lower number for less random responses and a higher number for more + random responses. + */ + topK?: number; + /** Maximum number of tokens that can be generated in the response. + */ + maxOutputTokens?: number; + /** If specified, the media resolution specified will be used. + */ + mediaResolution?: MediaResolution; + /** When ``seed`` is fixed to a specific number, the model makes a best + effort to provide the same response for repeated requests. By default, a + random number is used. + */ + seed?: number; + /** The speech generation configuration. + */ + speechConfig?: SpeechConfig; + /** Config for thinking features. + An error will be returned if this field is set for models that don't + support thinking. + */ + thinkingConfig?: ThinkingConfig; + /** If enabled, the model will detect emotions and adapt its responses accordingly. */ + enableAffectiveDialog?: boolean; + /** The user provided system instructions for the model. + Note: only text should be used in parts and content in each part will be + in a separate paragraph. */ + systemInstruction?: ContentUnion; + /** A list of `Tools` the model may use to generate the next response. + + A `Tool` is a piece of code that enables the system to interact with + external systems to perform an action, or set of actions, outside of + knowledge and scope of the model. */ + tools?: ToolListUnion; + /** Configures session resumption mechanism. + + If included the server will send SessionResumptionUpdate messages. */ + sessionResumption?: SessionResumptionConfig; + /** The transcription of the input aligns with the input audio language. + */ + inputAudioTranscription?: AudioTranscriptionConfig; + /** The transcription of the output aligns with the language code + specified for the output audio. + */ + outputAudioTranscription?: AudioTranscriptionConfig; + /** Configures the realtime input behavior in BidiGenerateContent. */ + realtimeInputConfig?: RealtimeInputConfig; + /** Configures context window compression mechanism. + + If included, server will compress context window to fit into given length. */ + contextWindowCompression?: ContextWindowCompressionConfig; + /** Configures the proactivity of the model. This allows the model to respond proactively to + the input and to ignore irrelevant input. */ + proactivity?: ProactivityConfig; + /** Configures the explicit VAD signal. If enabled, the client will send + vad_signal to indicate the start and end of speech. This allows the server + to process the audio more efficiently. */ + explicitVadSignal?: boolean; +} + +/** Config for LiveConnectConstraints for Auth Token creation. */ +export declare interface LiveConnectConstraints { + /** ID of the model to configure in the ephemeral token for Live API. + For a list of models, see `Gemini models + <https://ai.google.dev/gemini-api/docs/models>`. */ + model?: string; + /** Configuration specific to Live API connections created using this token. */ + config?: LiveConnectConfig; +} + +/** Parameters for connecting to the live API. */ +export declare interface LiveConnectParameters { + /** ID of the model to use. For a list of models, see `Google models + <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */ + model: string; + /** callbacks */ + callbacks: LiveCallbacks; + /** Optional configuration parameters for the request. + */ + config?: LiveConnectConfig; +} + +/** + LiveMusic class encapsulates the configuration for live music + generation via Lyria Live models. + + @experimental + */ +declare class LiveMusic { + private readonly apiClient; + private readonly auth; + private readonly webSocketFactory; + constructor(apiClient: ApiClient, auth: Auth, webSocketFactory: WebSocketFactory); + /** + Establishes a connection to the specified model and returns a + LiveMusicSession object representing that connection. + + @experimental + + @remarks + + @param params - The parameters for establishing a connection to the model. + @return A live session. + + @example + ```ts + let model = 'models/lyria-realtime-exp'; + const session = await ai.live.music.connect({ + model: model, + callbacks: { + onmessage: (e: MessageEvent) => { + console.log('Received message from the server: %s\n', debug(e.data)); + }, + onerror: (e: ErrorEvent) => { + console.log('Error occurred: %s\n', debug(e.error)); + }, + onclose: (e: CloseEvent) => { + console.log('Connection closed.'); + }, + }, + }); + ``` + */ + connect(params: types.LiveMusicConnectParameters): Promise<LiveMusicSession>; +} + +/** Callbacks for the realtime music API. */ +export declare interface LiveMusicCallbacks { + /** + * Called when a message is received from the server. + */ + onmessage: (e: LiveMusicServerMessage) => void; + /** + * Called when an error occurs. + */ + onerror?: ((e: ErrorEvent) => void) | null; + /** + * Called when the websocket connection is closed. + */ + onclose?: ((e: CloseEvent) => void) | null; +} + +/** User input to start or steer the music. */ +export declare interface LiveMusicClientContent { + /** Weighted prompts as the model input. */ + weightedPrompts?: WeightedPrompt[]; +} + +/** Messages sent by the client in the LiveMusicClientMessage call. */ +export declare interface LiveMusicClientMessage { + /** Message to be sent in the first (and only in the first) `LiveMusicClientMessage`. + Clients should wait for a `LiveMusicSetupComplete` message before + sending any additional messages. */ + setup?: LiveMusicClientSetup; + /** User input to influence music generation. */ + clientContent?: LiveMusicClientContent; + /** Configuration for music generation. */ + musicGenerationConfig?: LiveMusicGenerationConfig; + /** Playback control signal for the music generation. */ + playbackControl?: LiveMusicPlaybackControl; +} + +/** Message to be sent by the system when connecting to the API. */ +export declare interface LiveMusicClientSetup { + /** The model's resource name. Format: `models/{model}`. */ + model?: string; +} + +/** Parameters for connecting to the live API. */ +export declare interface LiveMusicConnectParameters { + /** The model's resource name. */ + model: string; + /** Callbacks invoked on server events. */ + callbacks: LiveMusicCallbacks; +} + +/** A prompt that was filtered with the reason. */ +export declare interface LiveMusicFilteredPrompt { + /** The text prompt that was filtered. */ + text?: string; + /** The reason the prompt was filtered. */ + filteredReason?: string; +} + +/** Configuration for music generation. */ +export declare interface LiveMusicGenerationConfig { + /** Controls the variance in audio generation. Higher values produce + higher variance. Range is [0.0, 3.0]. */ + temperature?: number; + /** Controls how the model selects tokens for output. Samples the topK + tokens with the highest probabilities. Range is [1, 1000]. */ + topK?: number; + /** Seeds audio generation. If not set, the request uses a randomly + generated seed. */ + seed?: number; + /** Controls how closely the model follows prompts. + Higher guidance follows more closely, but will make transitions more + abrupt. Range is [0.0, 6.0]. */ + guidance?: number; + /** Beats per minute. Range is [60, 200]. */ + bpm?: number; + /** Density of sounds. Range is [0.0, 1.0]. */ + density?: number; + /** Brightness of the music. Range is [0.0, 1.0]. */ + brightness?: number; + /** Scale of the generated music. */ + scale?: Scale; + /** Whether the audio output should contain bass. */ + muteBass?: boolean; + /** Whether the audio output should contain drums. */ + muteDrums?: boolean; + /** Whether the audio output should contain only bass and drums. */ + onlyBassAndDrums?: boolean; + /** The mode of music generation. Default mode is QUALITY. */ + musicGenerationMode?: MusicGenerationMode; +} + +/** The playback control signal to apply to the music generation. */ +export declare enum LiveMusicPlaybackControl { + /** + * This value is unused. + */ + PLAYBACK_CONTROL_UNSPECIFIED = "PLAYBACK_CONTROL_UNSPECIFIED", + /** + * Start generating the music. + */ + PLAY = "PLAY", + /** + * Hold the music generation. Use PLAY to resume from the current position. + */ + PAUSE = "PAUSE", + /** + * Stop the music generation and reset the context (prompts retained). + Use PLAY to restart the music generation. + */ + STOP = "STOP", + /** + * Reset the context of the music generation without stopping it. + Retains the current prompts and config. + */ + RESET_CONTEXT = "RESET_CONTEXT" +} + +/** Server update generated by the model in response to client messages. + + Content is generated as quickly as possible, and not in real time. + Clients may choose to buffer and play it out in real time. */ +export declare interface LiveMusicServerContent { + /** The audio chunks that the model has generated. */ + audioChunks?: AudioChunk[]; +} + +/** Response message for the LiveMusicClientMessage call. */ +export declare class LiveMusicServerMessage { + /** Message sent in response to a `LiveMusicClientSetup` message from the client. + Clients should wait for this message before sending any additional messages. */ + setupComplete?: LiveMusicServerSetupComplete; + /** Content generated by the model in response to client messages. */ + serverContent?: LiveMusicServerContent; + /** A prompt that was filtered with the reason. */ + filteredPrompt?: LiveMusicFilteredPrompt; + /** + * Returns the first audio chunk from the server content, if present. + * + * @remarks + * If there are no audio chunks in the response, undefined will be returned. + */ + get audioChunk(): AudioChunk | undefined; +} + +/** Sent in response to a `LiveMusicClientSetup` message from the client. */ +export declare interface LiveMusicServerSetupComplete { +} + +/** + Represents a connection to the API. + + @experimental + */ +export declare class LiveMusicSession { + readonly conn: WebSocket_2; + private readonly apiClient; + constructor(conn: WebSocket_2, apiClient: ApiClient); + /** + Sets inputs to steer music generation. Updates the session's current + weighted prompts. + + @param params - Contains one property, `weightedPrompts`. + + - `weightedPrompts` to send to the model; weights are normalized to + sum to 1.0. + + @experimental + */ + setWeightedPrompts(params: types.LiveMusicSetWeightedPromptsParameters): Promise<void>; + /** + Sets a configuration to the model. Updates the session's current + music generation config. + + @param params - Contains one property, `musicGenerationConfig`. + + - `musicGenerationConfig` to set in the model. Passing an empty or + undefined config to the model will reset the config to defaults. + + @experimental + */ + setMusicGenerationConfig(params: types.LiveMusicSetConfigParameters): Promise<void>; + private sendPlaybackControl; + /** + * Start the music stream. + * + * @experimental + */ + play(): void; + /** + * Temporarily halt the music stream. Use `play` to resume from the current + * position. + * + * @experimental + */ + pause(): void; + /** + * Stop the music stream and reset the state. Retains the current prompts + * and config. + * + * @experimental + */ + stop(): void; + /** + * Resets the context of the music generation without stopping it. + * Retains the current prompts and config. + * + * @experimental + */ + resetContext(): void; + /** + Terminates the WebSocket connection. + + @experimental + */ + close(): void; +} + +/** Parameters for setting config for the live music API. */ +export declare interface LiveMusicSetConfigParameters { + /** Configuration for music generation. */ + musicGenerationConfig: LiveMusicGenerationConfig; +} + +/** Parameters for setting weighted prompts for the live music API. */ +export declare interface LiveMusicSetWeightedPromptsParameters { + /** A map of text prompts to weights to use for the generation request. */ + weightedPrompts: WeightedPrompt[]; +} + +/** Prompts and config used for generating this audio chunk. */ +export declare interface LiveMusicSourceMetadata { + /** Weighted prompts for generating this audio chunk. */ + clientContent?: LiveMusicClientContent; + /** Music generation config for generating this audio chunk. */ + musicGenerationConfig?: LiveMusicGenerationConfig; +} + +/** Parameters for sending client content to the live API. */ +export declare interface LiveSendClientContentParameters { + /** Client content to send to the session. */ + turns?: ContentListUnion; + /** If true, indicates that the server content generation should start with + the currently accumulated prompt. Otherwise, the server will await + additional messages before starting generation. */ + turnComplete?: boolean; +} + +/** Parameters for sending realtime input to the live API. */ +export declare interface LiveSendRealtimeInputParameters { + /** Realtime input to send to the session. */ + media?: BlobImageUnion; + /** The realtime audio input stream. */ + audio?: Blob_2; + /** + Indicates that the audio stream has ended, e.g. because the microphone was + turned off. + + This should only be sent when automatic activity detection is enabled + (which is the default). + + The client can reopen the stream by sending an audio message. + */ + audioStreamEnd?: boolean; + /** The realtime video input stream. */ + video?: BlobImageUnion; + /** The realtime text input stream. */ + text?: string; + /** Marks the start of user activity. */ + activityStart?: ActivityStart; + /** Marks the end of user activity. */ + activityEnd?: ActivityEnd; +} + +/** Parameters for sending tool responses to the live API. */ +export declare class LiveSendToolResponseParameters { + /** Tool responses to send to the session. */ + functionResponses: FunctionResponse[] | FunctionResponse; +} + +/** Incremental server update generated by the model in response to client messages. + + Content is generated as quickly as possible, and not in real time. Clients + may choose to buffer and play it out in real time. */ +export declare interface LiveServerContent { + /** The content that the model has generated as part of the current conversation with the user. */ + modelTurn?: Content; + /** If true, indicates that the model is done generating. Generation will only start in response to additional client messages. Can be set alongside `content`, indicating that the `content` is the last in the turn. */ + turnComplete?: boolean; + /** If true, indicates that a client message has interrupted current model generation. If the client is playing out the content in realtime, this is a good signal to stop and empty the current queue. */ + interrupted?: boolean; + /** Metadata returned to client when grounding is enabled. */ + groundingMetadata?: GroundingMetadata; + /** If true, indicates that the model is done generating. When model is + interrupted while generating there will be no generation_complete message + in interrupted turn, it will go through interrupted > turn_complete. + When model assumes realtime playback there will be delay between + generation_complete and turn_complete that is caused by model + waiting for playback to finish. If true, indicates that the model + has finished generating all content. This is a signal to the client + that it can stop sending messages. */ + generationComplete?: boolean; + /** Input transcription. The transcription is independent to the model + turn which means it doesn’t imply any ordering between transcription and + model turn. */ + inputTranscription?: Transcription; + /** Output transcription. The transcription is independent to the model + turn which means it doesn’t imply any ordering between transcription and + model turn. + */ + outputTranscription?: Transcription; + /** Metadata related to url context retrieval tool. */ + urlContextMetadata?: UrlContextMetadata; + /** Reason for the turn is complete. */ + turnCompleteReason?: TurnCompleteReason; + /** If true, indicates that the model is not generating content because + it is waiting for more input from the user, e.g. because it expects the + user to continue talking. */ + waitingForInput?: boolean; +} + +/** Server will not be able to service client soon. */ +export declare interface LiveServerGoAway { + /** The remaining time before the connection will be terminated as ABORTED. The minimal time returned here is specified differently together with the rate limits for a given model. */ + timeLeft?: string; +} + +/** Response message for API call. */ +export declare class LiveServerMessage { + /** Sent in response to a `LiveClientSetup` message from the client. */ + setupComplete?: LiveServerSetupComplete; + /** Content generated by the model in response to client messages. */ + serverContent?: LiveServerContent; + /** Request for the client to execute the `function_calls` and return the responses with the matching `id`s. */ + toolCall?: LiveServerToolCall; + /** Notification for the client that a previously issued `ToolCallMessage` with the specified `id`s should have been not executed and should be cancelled. */ + toolCallCancellation?: LiveServerToolCallCancellation; + /** Usage metadata about model response(s). */ + usageMetadata?: UsageMetadata; + /** Server will disconnect soon. */ + goAway?: LiveServerGoAway; + /** Update of the session resumption state. */ + sessionResumptionUpdate?: LiveServerSessionResumptionUpdate; + /** Voice activity detection signal. Allowlisted only. */ + voiceActivityDetectionSignal?: VoiceActivityDetectionSignal; + /** Voice activity signal. */ + voiceActivity?: VoiceActivity; + /** + * Returns the concatenation of all text parts from the server content if present. + * + * @remarks + * If there are non-text parts in the response, the concatenation of all text + * parts will be returned, and a warning will be logged. + */ + get text(): string | undefined; + /** + * Returns the concatenation of all inline data parts from the server content if present. + * + * @remarks + * If there are non-inline data parts in the + * response, the concatenation of all inline data parts will be returned, and + * a warning will be logged. + */ + get data(): string | undefined; +} + +/** Update of the session resumption state. + + Only sent if `session_resumption` was set in the connection config. */ +export declare interface LiveServerSessionResumptionUpdate { + /** New handle that represents state that can be resumed. Empty if `resumable`=false. */ + newHandle?: string; + /** True if session can be resumed at this point. It might be not possible to resume session at some points. In that case we send update empty new_handle and resumable=false. Example of such case could be model executing function calls or just generating. Resuming session (using previous session token) in such state will result in some data loss. */ + resumable?: boolean; + /** Index of last message sent by client that is included in state represented by this SessionResumptionToken. Only sent when `SessionResumptionConfig.transparent` is set. + + Presence of this index allows users to transparently reconnect and avoid issue of losing some part of realtime audio input/video. If client wishes to temporarily disconnect (for example as result of receiving GoAway) they can do it without losing state by buffering messages sent since last `SessionResmumptionTokenUpdate`. This field will enable them to limit buffering (avoid keeping all requests in RAM). + + Note: This should not be used for when resuming a session at some time later -- in those cases partial audio and video frames arelikely not needed. */ + lastConsumedClientMessageIndex?: string; +} + +/** Sent in response to a `LiveGenerateContentSetup` message from the client. */ +export declare interface LiveServerSetupComplete { + /** The session id of the live session. */ + sessionId?: string; +} + +/** Request for the client to execute the `function_calls` and return the responses with the matching `id`s. */ +export declare interface LiveServerToolCall { + /** The function call to be executed. */ + functionCalls?: FunctionCall[]; +} + +/** Notification for the client that a previously issued `ToolCallMessage` with the specified `id`s should have been not executed and should be cancelled. + + If there were side-effects to those tool calls, clients may attempt to undo + the tool calls. This message occurs only in cases where the clients interrupt + server turns. */ +export declare interface LiveServerToolCallCancellation { + /** The ids of the tool calls to be cancelled. */ + ids?: string[]; +} + +declare type LogFn = (message: string, ...rest: unknown[]) => void; + +declare type Logger = { + error: LogFn; + warn: LogFn; + info: LogFn; + debug: LogFn; +}; + +declare type LogLevel = 'off' | 'error' | 'warn' | 'info' | 'debug'; + +/** Logprobs Result */ +export declare interface LogprobsResult { + /** Length = total number of decoding steps. The chosen candidates may or may not be in top_candidates. */ + chosenCandidates?: LogprobsResultCandidate[]; + /** Length = total number of decoding steps. */ + topCandidates?: LogprobsResultTopCandidates[]; +} + +/** Candidate for the logprobs token and score. */ +export declare interface LogprobsResultCandidate { + /** The candidate's log probability. */ + logProbability?: number; + /** The candidate's token string value. */ + token?: string; + /** The candidate's token id value. */ + tokenId?: number; +} + +/** Candidates with top log probabilities at each decoding step. */ +export declare interface LogprobsResultTopCandidates { + /** Sorted by log probability in descending order. */ + candidates?: LogprobsResultCandidate[]; +} + +/** Configuration for a Mask reference image. */ +export declare interface MaskReferenceConfig { + /** Prompts the model to generate a mask instead of you needing to + provide one (unless MASK_MODE_USER_PROVIDED is used). */ + maskMode?: MaskReferenceMode; + /** A list of up to 5 class ids to use for semantic segmentation. + Automatically creates an image mask based on specific objects. */ + segmentationClasses?: number[]; + /** Dilation percentage of the mask provided. + Float between 0 and 1. */ + maskDilation?: number; +} + +/** A mask reference image. + + This encapsulates either a mask image provided by the user and configs for + the user provided mask, or only config parameters for the model to generate + a mask. + + A mask image is an image whose non-zero values indicate where to edit the base + image. If the user provides a mask image, the mask must be in the same + dimensions as the raw image. */ +export declare class MaskReferenceImage { + /** The reference image for the editing operation. */ + referenceImage?: Image_2; + /** The id of the reference image. */ + referenceId?: number; + /** The type of the reference image. Only set by the SDK. */ + referenceType?: string; + /** Configuration for the mask reference image. */ + config?: MaskReferenceConfig; + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI(): ReferenceImageAPIInternal; +} + +/** Enum representing the mask mode of a mask reference image. */ +export declare enum MaskReferenceMode { + MASK_MODE_DEFAULT = "MASK_MODE_DEFAULT", + MASK_MODE_USER_PROVIDED = "MASK_MODE_USER_PROVIDED", + MASK_MODE_BACKGROUND = "MASK_MODE_BACKGROUND", + MASK_MODE_FOREGROUND = "MASK_MODE_FOREGROUND", + MASK_MODE_SEMANTIC = "MASK_MODE_SEMANTIC" +} + +/** + * MCPServer tool call content. + */ +declare interface MCPServerToolCallContent { + /** + * A unique ID for this specific tool call. + */ + id: string; + /** + * The JSON object of arguments for the function. + */ + arguments: { + [key: string]: unknown; + }; + /** + * The name of the tool which was called. + */ + name: string; + /** + * The name of the used MCP server. + */ + server_name: string; + type: 'mcp_server_tool_call'; +} + +/** + * MCPServer tool result content. + */ +declare interface MCPServerToolResultContent { + /** + * ID to match the ID from the MCP server tool call block. + */ + call_id: string; + /** + * The result of the tool call. + */ + result: MCPServerToolResultContent.Items | unknown | string; + type: 'mcp_server_tool_result'; + /** + * Name of the tool which is called for this specific tool call. + */ + name?: string; + /** + * The name of the used MCP server. + */ + server_name?: string; +} + +declare namespace MCPServerToolResultContent { + interface Items { + items?: Array<InteractionsAPI.TextContent | InteractionsAPI.ImageContent>; + } +} + +/** + * Creates a McpCallableTool from MCP clients and an optional config. + * + * The callable tool can invoke the MCP clients with given function call + * arguments. (often for automatic function calling). + * Use the config to modify tool parameters such as behavior. + * + * @experimental Built-in MCP support is an experimental feature, may change in future + * versions. + */ +export declare function mcpToTool(...args: [...Client[], CallableToolConfig | Client]): CallableTool; + +/** Server content modalities. */ +export declare enum MediaModality { + /** + * The modality is unspecified. + */ + MODALITY_UNSPECIFIED = "MODALITY_UNSPECIFIED", + /** + * Plain text. + */ + TEXT = "TEXT", + /** + * Images. + */ + IMAGE = "IMAGE", + /** + * Video. + */ + VIDEO = "VIDEO", + /** + * Audio. + */ + AUDIO = "AUDIO", + /** + * Document, e.g. PDF. + */ + DOCUMENT = "DOCUMENT" +} + +/** The media resolution to use. */ +export declare enum MediaResolution { + /** + * Media resolution has not been set + */ + MEDIA_RESOLUTION_UNSPECIFIED = "MEDIA_RESOLUTION_UNSPECIFIED", + /** + * Media resolution set to low (64 tokens). + */ + MEDIA_RESOLUTION_LOW = "MEDIA_RESOLUTION_LOW", + /** + * Media resolution set to medium (256 tokens). + */ + MEDIA_RESOLUTION_MEDIUM = "MEDIA_RESOLUTION_MEDIUM", + /** + * Media resolution set to high (zoomed reframing with 256 tokens). + */ + MEDIA_RESOLUTION_HIGH = "MEDIA_RESOLUTION_HIGH" +} + +/** + * This type contains `RequestInit` options that may be available on the current runtime, + * including per-platform extensions like `dispatcher`, `agent`, `client`, etc. + */ +declare type MergedRequestInit = RequestInits & +/** We don't include these in the types as they'll be overridden for every request. */ +Partial<Record<'body' | 'headers' | 'method' | 'signal', never>>; + +/** Server content modalities. */ +export declare enum Modality { + /** + * The modality is unspecified. + */ + MODALITY_UNSPECIFIED = "MODALITY_UNSPECIFIED", + /** + * Indicates the model should return text + */ + TEXT = "TEXT", + /** + * Indicates the model should return images. + */ + IMAGE = "IMAGE", + /** + * Indicates the model should return audio. + */ + AUDIO = "AUDIO" +} + +/** Represents token counting info for a single modality. */ +export declare interface ModalityTokenCount { + /** The modality associated with this token count. */ + modality?: MediaModality; + /** Number of tokens. */ + tokenCount?: number; +} + +/** A trained machine learning model. */ +export declare interface Model { + /** Resource name of the model. */ + name?: string; + /** Display name of the model. */ + displayName?: string; + /** Description of the model. */ + description?: string; + /** Version ID of the model. A new version is committed when a new + model version is uploaded or trained under an existing model ID. The + version ID is an auto-incrementing decimal number in string + representation. */ + version?: string; + /** List of deployed models created from this base model. Note that a + model could have been deployed to endpoints in different locations. */ + endpoints?: Endpoint[]; + /** Labels with user-defined metadata to organize your models. */ + labels?: Record<string, string>; + /** Information about the tuned model from the base model. */ + tunedModelInfo?: TunedModelInfo; + /** The maximum number of input tokens that the model can handle. */ + inputTokenLimit?: number; + /** The maximum number of output tokens that the model can generate. */ + outputTokenLimit?: number; + /** List of actions that are supported by the model. */ + supportedActions?: string[]; + /** The default checkpoint id of a model version. + */ + defaultCheckpointId?: string; + /** The checkpoints of the model. */ + checkpoints?: Checkpoint[]; + /** Temperature value used for sampling set when the dataset was saved. + This value is used to tune the degree of randomness. */ + temperature?: number; + /** The maximum temperature value used for sampling set when the + dataset was saved. This value is used to tune the degree of randomness. */ + maxTemperature?: number; + /** Optional. Specifies the nucleus sampling threshold. The model + considers only the smallest set of tokens whose cumulative probability is + at least `top_p`. This helps generate more diverse and less repetitive + responses. For example, a `top_p` of 0.9 means the model considers tokens + until the cumulative probability of the tokens to select from reaches 0.9. + It's recommended to adjust either temperature or `top_p`, but not both. */ + topP?: number; + /** Optional. Specifies the top-k sampling threshold. The model + considers only the top k most probable tokens for the next token. This can + be useful for generating more coherent and less random text. For example, + a `top_k` of 40 means the model will choose the next word from the 40 most + likely words. */ + topK?: number; + /** Whether the model supports thinking features. If true, thoughts are + returned only if the model supports thought and thoughts are available. */ + thinking?: boolean; +} + +/** + * The model that will complete your prompt.\n\nSee [models](https://ai.google.dev/gemini-api/docs/models) for additional details. + */ +declare type Model_2 = 'gemini-2.5-flash' | 'gemini-2.5-flash-image' | 'gemini-2.5-flash-lite' | 'gemini-2.5-flash-lite-preview-09-2025' | 'gemini-2.5-flash-native-audio-preview-12-2025' | 'gemini-2.5-flash-preview-09-2025' | 'gemini-2.5-flash-preview-tts' | 'gemini-2.5-pro' | 'gemini-2.5-pro-preview-tts' | 'gemini-3-flash-preview' | 'gemini-3-pro-image-preview' | 'gemini-3-pro-preview' | (string & {}); + +/** Configuration for Model Armor integrations of prompt and responses. This data type is not supported in Gemini API. */ +export declare interface ModelArmorConfig { + /** Optional. The name of the Model Armor template to use for prompt sanitization. */ + promptTemplateName?: string; + /** Optional. The name of the Model Armor template to use for response sanitization. */ + responseTemplateName?: string; +} + +export declare class Models extends BaseModule { + private readonly apiClient; + constructor(apiClient: ApiClient); + /** + * Makes an API request to generate content with a given model. + * + * For the `model` parameter, supported formats for Vertex AI API include: + * - The Gemini model ID, for example: 'gemini-2.0-flash' + * - The full resource name starts with 'projects/', for example: + * 'projects/my-project-id/locations/us-central1/publishers/google/models/gemini-2.0-flash' + * - The partial resource name with 'publishers/', for example: + * 'publishers/google/models/gemini-2.0-flash' or + * 'publishers/meta/models/llama-3.1-405b-instruct-maas' + * - `/` separated publisher and model name, for example: + * 'google/gemini-2.0-flash' or 'meta/llama-3.1-405b-instruct-maas' + * + * For the `model` parameter, supported formats for Gemini API include: + * - The Gemini model ID, for example: 'gemini-2.0-flash' + * - The model name starts with 'models/', for example: + * 'models/gemini-2.0-flash' + * - For tuned models, the model name starts with 'tunedModels/', + * for example: + * 'tunedModels/1234567890123456789' + * + * Some models support multimodal input and output. + * + * @param params - The parameters for generating content. + * @return The response from generating content. + * + * @example + * ```ts + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: 'why is the sky blue?', + * config: { + * candidateCount: 2, + * } + * }); + * console.log(response); + * ``` + */ + generateContent: (params: types.GenerateContentParameters) => Promise<types.GenerateContentResponse>; + /** + * This logic is needed for GenerateContentConfig only. + * Previously we made GenerateContentConfig.responseSchema field to accept + * unknown. Since v1.9.0, we switch to use backend JSON schema support. + * To maintain backward compatibility, we move the data that was treated as + * JSON schema from the responseSchema field to the responseJsonSchema field. + */ + private maybeMoveToResponseJsonSchem; + /** + * Makes an API request to generate content with a given model and yields the + * response in chunks. + * + * For the `model` parameter, supported formats for Vertex AI API include: + * - The Gemini model ID, for example: 'gemini-2.0-flash' + * - The full resource name starts with 'projects/', for example: + * 'projects/my-project-id/locations/us-central1/publishers/google/models/gemini-2.0-flash' + * - The partial resource name with 'publishers/', for example: + * 'publishers/google/models/gemini-2.0-flash' or + * 'publishers/meta/models/llama-3.1-405b-instruct-maas' + * - `/` separated publisher and model name, for example: + * 'google/gemini-2.0-flash' or 'meta/llama-3.1-405b-instruct-maas' + * + * For the `model` parameter, supported formats for Gemini API include: + * - The Gemini model ID, for example: 'gemini-2.0-flash' + * - The model name starts with 'models/', for example: + * 'models/gemini-2.0-flash' + * - For tuned models, the model name starts with 'tunedModels/', + * for example: + * 'tunedModels/1234567890123456789' + * + * Some models support multimodal input and output. + * + * @param params - The parameters for generating content with streaming response. + * @return The response from generating content. + * + * @example + * ```ts + * const response = await ai.models.generateContentStream({ + * model: 'gemini-2.0-flash', + * contents: 'why is the sky blue?', + * config: { + * maxOutputTokens: 200, + * } + * }); + * for await (const chunk of response) { + * console.log(chunk); + * } + * ``` + */ + generateContentStream: (params: types.GenerateContentParameters) => Promise<AsyncGenerator<types.GenerateContentResponse>>; + /** + * Transforms the CallableTools in the parameters to be simply Tools, it + * copies the params into a new object and replaces the tools, it does not + * modify the original params. Also sets the MCP usage header if there are + * MCP tools in the parameters. + */ + private processParamsMaybeAddMcpUsage; + private initAfcToolsMap; + private processAfcStream; + /** + * Generates an image based on a text description and configuration. + * + * @param params - The parameters for generating images. + * @return The response from the API. + * + * @example + * ```ts + * const response = await client.models.generateImages({ + * model: 'imagen-4.0-generate-001', + * prompt: 'Robot holding a red skateboard', + * config: { + * numberOfImages: 1, + * includeRaiReason: true, + * }, + * }); + * console.log(response?.generatedImages?.[0]?.image?.imageBytes); + * ``` + */ + generateImages: (params: types.GenerateImagesParameters) => Promise<types.GenerateImagesResponse>; + list: (params?: types.ListModelsParameters) => Promise<Pager<types.Model>>; + /** + * Edits an image based on a prompt, list of reference images, and configuration. + * + * @param params - The parameters for editing an image. + * @return The response from the API. + * + * @example + * ```ts + * const response = await client.models.editImage({ + * model: 'imagen-3.0-capability-001', + * prompt: 'Generate an image containing a mug with the product logo [1] visible on the side of the mug.', + * referenceImages: [subjectReferenceImage] + * config: { + * numberOfImages: 1, + * includeRaiReason: true, + * }, + * }); + * console.log(response?.generatedImages?.[0]?.image?.imageBytes); + * ``` + */ + editImage: (params: types.EditImageParameters) => Promise<types.EditImageResponse>; + /** + * Upscales an image based on an image, upscale factor, and configuration. + * Only supported in Vertex AI currently. + * + * @param params - The parameters for upscaling an image. + * @return The response from the API. + * + * @example + * ```ts + * const response = await client.models.upscaleImage({ + * model: 'imagen-4.0-upscale-preview', + * image: image, + * upscaleFactor: 'x2', + * config: { + * includeRaiReason: true, + * }, + * }); + * console.log(response?.generatedImages?.[0]?.image?.imageBytes); + * ``` + */ + upscaleImage: (params: types.UpscaleImageParameters) => Promise<types.UpscaleImageResponse>; + /** + * Generates videos based on a text description and configuration. + * + * @param params - The parameters for generating videos. + * @return A Promise<GenerateVideosOperation> which allows you to track the progress and eventually retrieve the generated videos using the operations.get method. + * + * @example + * ```ts + * const operation = await ai.models.generateVideos({ + * model: 'veo-2.0-generate-001', + * source: { + * prompt: 'A neon hologram of a cat driving at top speed', + * }, + * config: { + * numberOfVideos: 1 + * }); + * + * while (!operation.done) { + * await new Promise(resolve => setTimeout(resolve, 10000)); + * operation = await ai.operations.getVideosOperation({operation: operation}); + * } + * + * console.log(operation.response?.generatedVideos?.[0]?.video?.uri); + * ``` + */ + generateVideos: (params: types.GenerateVideosParameters) => Promise<types.GenerateVideosOperation>; + private generateContentInternal; + private generateContentStreamInternal; + /** + * Calculates embeddings for the given contents. Only text is supported. + * + * @param params - The parameters for embedding contents. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.embedContent({ + * model: 'text-embedding-004', + * contents: [ + * 'What is your name?', + * 'What is your favorite color?', + * ], + * config: { + * outputDimensionality: 64, + * }, + * }); + * console.log(response); + * ``` + */ + embedContent(params: types.EmbedContentParameters): Promise<types.EmbedContentResponse>; + /** + * Private method for generating images. + */ + private generateImagesInternal; + /** + * Private method for editing an image. + */ + private editImageInternal; + /** + * Private method for upscaling an image. + */ + private upscaleImageInternal; + /** + * Recontextualizes an image. + * + * There are two types of recontextualization currently supported: + * 1) Imagen Product Recontext - Generate images of products in new scenes + * and contexts. + * 2) Virtual Try-On: Generate images of persons modeling fashion products. + * + * @param params - The parameters for recontextualizing an image. + * @return The response from the API. + * + * @example + * ```ts + * const response1 = await ai.models.recontextImage({ + * model: 'imagen-product-recontext-preview-06-30', + * source: { + * prompt: 'In a modern kitchen setting.', + * productImages: [productImage], + * }, + * config: { + * numberOfImages: 1, + * }, + * }); + * console.log(response1?.generatedImages?.[0]?.image?.imageBytes); + * + * const response2 = await ai.models.recontextImage({ + * model: 'virtual-try-on-001', + * source: { + * personImage: personImage, + * productImages: [productImage], + * }, + * config: { + * numberOfImages: 1, + * }, + * }); + * console.log(response2?.generatedImages?.[0]?.image?.imageBytes); + * ``` + */ + recontextImage(params: types.RecontextImageParameters): Promise<types.RecontextImageResponse>; + /** + * Segments an image, creating a mask of a specified area. + * + * @param params - The parameters for segmenting an image. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.segmentImage({ + * model: 'image-segmentation-001', + * source: { + * image: image, + * }, + * config: { + * mode: 'foreground', + * }, + * }); + * console.log(response?.generatedMasks?.[0]?.mask?.imageBytes); + * ``` + */ + segmentImage(params: types.SegmentImageParameters): Promise<types.SegmentImageResponse>; + /** + * Fetches information about a model by name. + * + * @example + * ```ts + * const modelInfo = await ai.models.get({model: 'gemini-2.0-flash'}); + * ``` + */ + get(params: types.GetModelParameters): Promise<types.Model>; + private listInternal; + /** + * Updates a tuned model by its name. + * + * @param params - The parameters for updating the model. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.update({ + * model: 'tuned-model-name', + * config: { + * displayName: 'New display name', + * description: 'New description', + * }, + * }); + * ``` + */ + update(params: types.UpdateModelParameters): Promise<types.Model>; + /** + * Deletes a tuned model by its name. + * + * @param params - The parameters for deleting the model. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.delete({model: 'tuned-model-name'}); + * ``` + */ + delete(params: types.DeleteModelParameters): Promise<types.DeleteModelResponse>; + /** + * Counts the number of tokens in the given contents. Multimodal input is + * supported for Gemini models. + * + * @param params - The parameters for counting tokens. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.countTokens({ + * model: 'gemini-2.0-flash', + * contents: 'The quick brown fox jumps over the lazy dog.' + * }); + * console.log(response); + * ``` + */ + countTokens(params: types.CountTokensParameters): Promise<types.CountTokensResponse>; + /** + * Given a list of contents, returns a corresponding TokensInfo containing + * the list of tokens and list of token ids. + * + * This method is not supported by the Gemini Developer API. + * + * @param params - The parameters for computing tokens. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.computeTokens({ + * model: 'gemini-2.0-flash', + * contents: 'What is your name?' + * }); + * console.log(response); + * ``` + */ + computeTokens(params: types.ComputeTokensParameters): Promise<types.ComputeTokensResponse>; + /** + * Private method for generating videos. + */ + private generateVideosInternal; +} + +/** Config for model selection. */ +export declare interface ModelSelectionConfig { + /** Options for feature selection preference. */ + featureSelectionPreference?: FeatureSelectionPreference; +} + +/** Configuration for a multi-speaker text-to-speech request. */ +export declare interface MultiSpeakerVoiceConfig { + /** Required. A list of configurations for the voices of the speakers. Exactly two speaker voice configurations must be provided. */ + speakerVoiceConfigs?: SpeakerVoiceConfig[]; +} + +/** The mode of music generation. */ +export declare enum MusicGenerationMode { + /** + * Rely on the server default generation mode. + */ + MUSIC_GENERATION_MODE_UNSPECIFIED = "MUSIC_GENERATION_MODE_UNSPECIFIED", + /** + * Steer text prompts to regions of latent space with higher quality + music. + */ + QUALITY = "QUALITY", + /** + * Steer text prompts to regions of latent space with a larger + diversity of music. + */ + DIVERSITY = "DIVERSITY", + /** + * Steer text prompts to regions of latent space more likely to + generate music with vocals. + */ + VOCALIZATION = "VOCALIZATION" +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/// <reference types="node" /> +/** + * Shims for types that we can't always rely on being available globally. + * + * Note: these only exist at the type-level, there is no corresponding runtime + * version for any of these symbols. + */ +declare type NeverToAny<T> = T extends never ? any : T; + +/** @ts-ignore For users with node-fetch@2 */ +declare type NodeFetch2RequestInit = NotAny<import('../node_modules/@types/node-fetch/index.d.ts').RequestInit> | NotAny<import('../../node_modules/@types/node-fetch/index.d.ts').RequestInit> | NotAny<import('../../../node_modules/@types/node-fetch/index.d.ts').RequestInit> | NotAny<import('../../../../node_modules/@types/node-fetch/index.d.ts').RequestInit> | NotAny<import('../../../../../node_modules/@types/node-fetch/index.d.ts').RequestInit> | NotAny<import('../../../../../../node_modules/@types/node-fetch/index.d.ts').RequestInit> | NotAny<import('../../../../../../../node_modules/@types/node-fetch/index.d.ts').RequestInit> | NotAny<import('../../../../../../../../node_modules/@types/node-fetch/index.d.ts').RequestInit> | NotAny<import('../../../../../../../../../node_modules/@types/node-fetch/index.d.ts').RequestInit> | NotAny<import('../../../../../../../../../../node_modules/@types/node-fetch/index.d.ts').RequestInit>; + +/** @ts-ignore For users with node-fetch@3, doesn't need file extension because types are at ./@types/index.d.ts */ +declare type NodeFetch3RequestInit = NotAny<import('../node_modules/node-fetch').RequestInit> | NotAny<import('../../node_modules/node-fetch').RequestInit> | NotAny<import('../../../node_modules/node-fetch').RequestInit> | NotAny<import('../../../../node_modules/node-fetch').RequestInit> | NotAny<import('../../../../../node_modules/node-fetch').RequestInit> | NotAny<import('../../../../../../node_modules/node-fetch').RequestInit> | NotAny<import('../../../../../../../node_modules/node-fetch').RequestInit> | NotAny<import('../../../../../../../../node_modules/node-fetch').RequestInit> | NotAny<import('../../../../../../../../../node_modules/node-fetch').RequestInit> | NotAny<import('../../../../../../../../../../node_modules/node-fetch').RequestInit>; + +/** @ts-ignore */ +declare type _NodeReadableStream<R = any> = ReadableStream_2<R>; + +declare type NotAny<T> = [0] extends [1 & T] ? never : T; + +declare class NotFoundError extends APIError<404, Headers> { +} + +/** + * @internal + * Users can pass explicit nulls to unset default headers. When we parse them + * into a standard headers type we need to preserve that information. + */ +declare type NullableHeaders = { + /** Brand check, prevent users from creating a NullableHeaders. */ + [brand_privateNullableHeaders]: true; + /** Parsed headers. */ + values: Headers; + /** Set of lowercase header names explicitly set to null. */ + nulls: Set<string>; +}; + +/** A long-running operation. */ +export declare interface Operation<T> { + /** The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`. */ + name?: string; + /** Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata. Any method that returns a long-running operation should document the metadata type, if any. */ + metadata?: Record<string, unknown>; + /** If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available. */ + done?: boolean; + /** The error result of the operation in case of failure or cancellation. */ + error?: Record<string, unknown>; + /** The response if the operation is successful. */ + response?: T; + /** + * Instantiates an Operation of the same type as the one being called with the fields set from the API response. + * @internal + */ + _fromAPIResponse({ apiResponse, _isVertexAI, }: OperationFromAPIResponseParameters): Operation<T>; +} + +/** Parameters of the fromAPIResponse method of the Operation class. */ +export declare interface OperationFromAPIResponseParameters { + /** The API response to be converted to an Operation. */ + apiResponse: Record<string, unknown>; + /** Whether the API response is from Vertex AI. */ + _isVertexAI: boolean; +} + +/** Parameters for the get method of the operations module. */ +export declare interface OperationGetParameters<T, U extends Operation<T>> { + /** Used to override the default configuration. */ + config?: GetOperationConfig; + /** The operation to be retrieved. */ + operation: U; +} + +export declare class Operations extends BaseModule { + private readonly apiClient; + constructor(apiClient: ApiClient); + /** + * Gets the status of a long-running operation. + * + * @param parameters The parameters for the get operation request. + * @return The updated Operation object, with the latest status or result. + */ + getVideosOperation(parameters: types.OperationGetParameters<types.GenerateVideosResponse, types.GenerateVideosOperation>): Promise<types.GenerateVideosOperation>; + /** + * Gets the status of a long-running operation. + * + * @param parameters The parameters for the get operation request. + * @return The updated Operation object, with the latest status or result. + */ + get<T, U extends types.Operation<T>>(parameters: types.OperationGetParameters<T, U>): Promise<types.Operation<T>>; + private getVideosOperationInternal; + private fetchPredictVideosOperationInternal; +} + +/** Outcome of the code execution. */ +export declare enum Outcome { + /** + * Unspecified status. This value should not be used. + */ + OUTCOME_UNSPECIFIED = "OUTCOME_UNSPECIFIED", + /** + * Code execution completed successfully. + */ + OUTCOME_OK = "OUTCOME_OK", + /** + * Code execution finished but with a failure. `stderr` should contain the reason. + */ + OUTCOME_FAILED = "OUTCOME_FAILED", + /** + * Code execution ran for too long, and was cancelled. There may or may not be a partial output present. + */ + OUTCOME_DEADLINE_EXCEEDED = "OUTCOME_DEADLINE_EXCEEDED" +} + +/** + * Some environments overload the global fetch function, and Parameters<T> only gets the last signature. + */ +declare type OverloadedParameters<T> = T extends ({ + (...args: infer A): unknown; + (...args: infer B): unknown; + (...args: infer C): unknown; + (...args: infer D): unknown; +}) ? A | B | C | D : T extends ({ + (...args: infer A): unknown; + (...args: infer B): unknown; + (...args: infer C): unknown; +}) ? A | B | C : T extends ({ + (...args: infer A): unknown; + (...args: infer B): unknown; +}) ? A | B : T extends (...args: infer A) => unknown ? A : never; + +export declare enum PagedItem { + PAGED_ITEM_BATCH_JOBS = "batchJobs", + PAGED_ITEM_MODELS = "models", + PAGED_ITEM_TUNING_JOBS = "tuningJobs", + PAGED_ITEM_FILES = "files", + PAGED_ITEM_CACHED_CONTENTS = "cachedContents", + PAGED_ITEM_FILE_SEARCH_STORES = "fileSearchStores", + PAGED_ITEM_DOCUMENTS = "documents" +} + +declare interface PagedItemConfig { + parent?: string; + config?: { + pageToken?: string; + pageSize?: number; + }; +} + +declare interface PagedItemResponse<T> { + nextPageToken?: string; + sdkHttpResponse?: types.HttpResponse; + batchJobs?: T[]; + models?: T[]; + tuningJobs?: T[]; + files?: T[]; + cachedContents?: T[]; + fileSearchStores?: T[]; + documents?: T[]; +} + +/** + * Pager class for iterating through paginated results. + */ +export declare class Pager<T> implements AsyncIterable<T> { + private nameInternal; + private pageInternal; + private paramsInternal; + private pageInternalSize; + private sdkHttpResponseInternal?; + protected requestInternal: (params: PagedItemConfig) => Promise<PagedItemResponse<T>>; + protected idxInternal: number; + constructor(name: PagedItem, request: (params: PagedItemConfig) => Promise<PagedItemResponse<T>>, response: PagedItemResponse<T>, params: PagedItemConfig); + private init; + private initNextPage; + /** + * Returns the current page, which is a list of items. + * + * @remarks + * The first page is retrieved when the pager is created. The returned list of + * items could be a subset of the entire list. + */ + get page(): T[]; + /** + * Returns the type of paged item (for example, ``batch_jobs``). + */ + get name(): PagedItem; + /** + * Returns the length of the page fetched each time by this pager. + * + * @remarks + * The number of items in the page is less than or equal to the page length. + */ + get pageSize(): number; + /** + * Returns the headers of the API response. + */ + get sdkHttpResponse(): types.HttpResponse | undefined; + /** + * Returns the parameters when making the API request for the next page. + * + * @remarks + * Parameters contain a set of optional configs that can be + * used to customize the API request. For example, the `pageToken` parameter + * contains the token to request the next page. + */ + get params(): PagedItemConfig; + /** + * Returns the total number of items in the current page. + */ + get pageLength(): number; + /** + * Returns the item at the given index. + */ + getItem(index: number): T; + /** + * Returns an async iterator that support iterating through all items + * retrieved from the API. + * + * @remarks + * The iterator will automatically fetch the next page if there are more items + * to fetch from the API. + * + * @example + * + * ```ts + * const pager = await ai.files.list({config: {pageSize: 10}}); + * for await (const file of pager) { + * console.log(file.name); + * } + * ``` + */ + [Symbol.asyncIterator](): AsyncIterator<T>; + /** + * Fetches the next page of items. This makes a new API request. + * + * @throws {Error} If there are no more pages to fetch. + * + * @example + * + * ```ts + * const pager = await ai.files.list({config: {pageSize: 10}}); + * let page = pager.page; + * while (true) { + * for (const file of page) { + * console.log(file.name); + * } + * if (!pager.hasNextPage()) { + * break; + * } + * page = await pager.nextPage(); + * } + * ``` + */ + nextPage(): Promise<T[]>; + /** + * Returns true if there are more pages to fetch from the API. + */ + hasNextPage(): boolean; +} + +/** A datatype containing media content. + + Exactly one field within a Part should be set, representing the specific type + of content being conveyed. Using multiple fields within the same `Part` + instance is considered invalid. */ +export declare interface Part { + /** Media resolution for the input media. + */ + mediaResolution?: PartMediaResolution; + /** Optional. Result of executing the [ExecutableCode]. */ + codeExecutionResult?: CodeExecutionResult; + /** Optional. Code generated by the model that is meant to be executed. */ + executableCode?: ExecutableCode; + /** Optional. URI based data. */ + fileData?: FileData; + /** Optional. A predicted [FunctionCall] returned from the model that contains a string representing the [FunctionDeclaration.name] with the parameters and their values. */ + functionCall?: FunctionCall; + /** Optional. The result output of a [FunctionCall] that contains a string representing the [FunctionDeclaration.name] and a structured JSON object containing any output from the function call. It is used as context to the model. */ + functionResponse?: FunctionResponse; + /** Optional. Inlined bytes data. */ + inlineData?: Blob_2; + /** Optional. Text part (can be code). */ + text?: string; + /** Optional. Indicates if the part is thought from the model. */ + thought?: boolean; + /** Optional. An opaque signature for the thought so it can be reused in subsequent requests. + * @remarks Encoded as base64 string. */ + thoughtSignature?: string; + /** Optional. Video metadata. The metadata should only be specified while the video data is presented in inline_data or file_data. */ + videoMetadata?: VideoMetadata; +} + +/** Partial argument value of the function call. This data type is not supported in Gemini API. */ +export declare interface PartialArg { + /** Optional. Represents a null value. */ + nullValue?: 'NULL_VALUE'; + /** Optional. Represents a double value. */ + numberValue?: number; + /** Optional. Represents a string value. */ + stringValue?: string; + /** Optional. Represents a boolean value. */ + boolValue?: boolean; + /** Required. A JSON Path (RFC 9535) to the argument being streamed. https://datatracker.ietf.org/doc/html/rfc9535. e.g. "$.foo.bar[0].data". */ + jsonPath?: string; + /** Optional. Whether this is not the last part of the same json_path. If true, another PartialArg message for the current json_path is expected to follow. */ + willContinue?: boolean; +} + +export declare type PartListUnion = PartUnion[] | PartUnion; + +/** Media resolution for the input media. */ +export declare interface PartMediaResolution { + /** The tokenization quality used for given media. + */ + level?: PartMediaResolutionLevel; + /** Specifies the required sequence length for media tokenization. + */ + numTokens?: number; +} + +/** The tokenization quality used for given media. */ +export declare enum PartMediaResolutionLevel { + /** + * Media resolution has not been set. + */ + MEDIA_RESOLUTION_UNSPECIFIED = "MEDIA_RESOLUTION_UNSPECIFIED", + /** + * Media resolution set to low. + */ + MEDIA_RESOLUTION_LOW = "MEDIA_RESOLUTION_LOW", + /** + * Media resolution set to medium. + */ + MEDIA_RESOLUTION_MEDIUM = "MEDIA_RESOLUTION_MEDIUM", + /** + * Media resolution set to high. + */ + MEDIA_RESOLUTION_HIGH = "MEDIA_RESOLUTION_HIGH", + /** + * Media resolution set to ultra high. + */ + MEDIA_RESOLUTION_ULTRA_HIGH = "MEDIA_RESOLUTION_ULTRA_HIGH" +} + +/** Tuning spec for Partner models. This data type is not supported in Gemini API. */ +export declare interface PartnerModelTuningSpec { + /** Hyperparameters for tuning. The accepted hyper_parameters and their valid range of values will differ depending on the base model. */ + hyperParameters?: Record<string, unknown>; + /** Required. Cloud Storage path to file containing training dataset for tuning. The dataset must be formatted as a JSONL file. */ + trainingDatasetUri?: string; + /** Optional. Cloud Storage path to file containing validation dataset for tuning. The dataset must be formatted as a JSONL file. */ + validationDatasetUri?: string; +} + +export declare type PartUnion = Part | string; + +declare class PermissionDeniedError extends APIError<403, Headers> { +} + +/** Enum that controls the generation of people. */ +export declare enum PersonGeneration { + /** + * Block generation of images of people. + */ + DONT_ALLOW = "DONT_ALLOW", + /** + * Generate images of adults, but not children. + */ + ALLOW_ADULT = "ALLOW_ADULT", + /** + * Generate images that include adults and children. + */ + ALLOW_ALL = "ALLOW_ALL" +} + +/** Sites with confidence level chosen & above this value will be blocked from the search results. This enum is not supported in Gemini API. */ +export declare enum PhishBlockThreshold { + /** + * Defaults to unspecified. + */ + PHISH_BLOCK_THRESHOLD_UNSPECIFIED = "PHISH_BLOCK_THRESHOLD_UNSPECIFIED", + /** + * Blocks Low and above confidence URL that is risky. + */ + BLOCK_LOW_AND_ABOVE = "BLOCK_LOW_AND_ABOVE", + /** + * Blocks Medium and above confidence URL that is risky. + */ + BLOCK_MEDIUM_AND_ABOVE = "BLOCK_MEDIUM_AND_ABOVE", + /** + * Blocks High and above confidence URL that is risky. + */ + BLOCK_HIGH_AND_ABOVE = "BLOCK_HIGH_AND_ABOVE", + /** + * Blocks Higher and above confidence URL that is risky. + */ + BLOCK_HIGHER_AND_ABOVE = "BLOCK_HIGHER_AND_ABOVE", + /** + * Blocks Very high and above confidence URL that is risky. + */ + BLOCK_VERY_HIGH_AND_ABOVE = "BLOCK_VERY_HIGH_AND_ABOVE", + /** + * Blocks Extremely high confidence URL that is risky. + */ + BLOCK_ONLY_EXTREMELY_HIGH = "BLOCK_ONLY_EXTREMELY_HIGH" +} + +/** The configuration for the prebuilt speaker to use. */ +export declare interface PrebuiltVoiceConfig { + /** The name of the preset voice to use. */ + voiceName?: string; +} + +/** Statistics computed for datasets used for preference optimization. This data type is not supported in Gemini API. */ +export declare interface PreferenceOptimizationDataStats { + /** Output only. Dataset distributions for scores variance per example. */ + scoreVariancePerExampleDistribution?: DatasetDistribution; + /** Output only. Dataset distributions for scores. */ + scoresDistribution?: DatasetDistribution; + /** Output only. Number of billable tokens in the tuning dataset. */ + totalBillableTokenCount?: string; + /** Output only. Number of examples in the tuning dataset. */ + tuningDatasetExampleCount?: string; + /** Output only. Number of tuning steps for this Tuning Job. */ + tuningStepCount?: string; + /** Output only. Sample user examples in the training dataset. */ + userDatasetExamples?: GeminiPreferenceExample[]; + /** Output only. Dataset distributions for the user input tokens. */ + userInputTokenDistribution?: DatasetDistribution; + /** Output only. Dataset distributions for the user output tokens. */ + userOutputTokenDistribution?: DatasetDistribution; +} + +/** Hyperparameters for Preference Optimization. This data type is not supported in Gemini API. */ +export declare interface PreferenceOptimizationHyperParameters { + /** Optional. Adapter size for preference optimization. */ + adapterSize?: AdapterSize; + /** Optional. Weight for KL Divergence regularization. */ + beta?: number; + /** Optional. Number of complete passes the model makes over the entire training dataset during training. */ + epochCount?: string; + /** Optional. Multiplier for adjusting the default learning rate. */ + learningRateMultiplier?: number; +} + +/** Preference optimization tuning spec for tuning. */ +export declare interface PreferenceOptimizationSpec { + /** Optional. If set to true, disable intermediate checkpoints for Preference Optimization and only the last checkpoint will be exported. Otherwise, enable intermediate checkpoints for Preference Optimization. Default is false. */ + exportLastCheckpointOnly?: boolean; + /** Optional. Hyperparameters for Preference Optimization. */ + hyperParameters?: PreferenceOptimizationHyperParameters; + /** Required. Cloud Storage path to file containing training dataset for preference optimization tuning. The dataset must be formatted as a JSONL file. */ + trainingDatasetUri?: string; + /** Optional. Cloud Storage path to file containing validation dataset for preference optimization tuning. The dataset must be formatted as a JSONL file. */ + validationDatasetUri?: string; +} + +/** A pre-tuned model for continuous tuning. This data type is not supported in Gemini API. */ +export declare interface PreTunedModel { + /** Output only. The name of the base model this PreTunedModel was tuned from. */ + baseModel?: string; + /** Optional. The source checkpoint id. If not specified, the default checkpoint will be used. */ + checkpointId?: string; + /** The resource name of the Model. E.g., a model resource name with a specified version id or alias: `projects/{project}/locations/{location}/models/{model}@{version_id}` `projects/{project}/locations/{location}/models/{model}@{alias}` Or, omit the version id to use the default version: `projects/{project}/locations/{location}/models/{model}` */ + tunedModelName?: string; +} + +/** Config for proactivity features. */ +export declare interface ProactivityConfig { + /** If enabled, the model can reject responding to the last prompt. For + example, this allows the model to ignore out of context speech or to stay + silent if the user did not make a request, yet. */ + proactiveAudio?: boolean; +} + +/** An image of the product. */ +export declare interface ProductImage { + /** An image of the product to be recontextualized. */ + productImage?: Image_2; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +declare type PromiseOrValue<T> = T | Promise<T>; + +/** A RagChunk includes the content of a chunk of a RagFile, and associated metadata. This data type is not supported in Gemini API. */ +export declare interface RagChunk { + /** If populated, represents where the chunk starts and ends in the document. */ + pageSpan?: RagChunkPageSpan; + /** The content of the chunk. */ + text?: string; +} + +/** Represents where the chunk starts and ends in the document. This data type is not supported in Gemini API. */ +export declare interface RagChunkPageSpan { + /** Page where chunk starts in the document. Inclusive. 1-indexed. */ + firstPage?: number; + /** Page where chunk ends in the document. Inclusive. 1-indexed. */ + lastPage?: number; +} + +/** Specifies the context retrieval config. This data type is not supported in Gemini API. */ +export declare interface RagRetrievalConfig { + /** Optional. Config for filters. */ + filter?: RagRetrievalConfigFilter; + /** Optional. Config for Hybrid Search. */ + hybridSearch?: RagRetrievalConfigHybridSearch; + /** Optional. Config for ranking and reranking. */ + ranking?: RagRetrievalConfigRanking; + /** Optional. The number of contexts to retrieve. */ + topK?: number; +} + +/** Config for filters. This data type is not supported in Gemini API. */ +export declare interface RagRetrievalConfigFilter { + /** Optional. String for metadata filtering. */ + metadataFilter?: string; + /** Optional. Only returns contexts with vector distance smaller than the threshold. */ + vectorDistanceThreshold?: number; + /** Optional. Only returns contexts with vector similarity larger than the threshold. */ + vectorSimilarityThreshold?: number; +} + +/** Config for Hybrid Search. This data type is not supported in Gemini API. */ +export declare interface RagRetrievalConfigHybridSearch { + /** Optional. Alpha value controls the weight between dense and sparse vector search results. The range is [0, 1], while 0 means sparse vector search only and 1 means dense vector search only. The default value is 0.5 which balances sparse and dense vector search equally. */ + alpha?: number; +} + +/** Config for ranking and reranking. This data type is not supported in Gemini API. */ +export declare interface RagRetrievalConfigRanking { + /** Optional. Config for LlmRanker. */ + llmRanker?: RagRetrievalConfigRankingLlmRanker; + /** Optional. Config for Rank Service. */ + rankService?: RagRetrievalConfigRankingRankService; +} + +/** Config for LlmRanker. This data type is not supported in Gemini API. */ +export declare interface RagRetrievalConfigRankingLlmRanker { + /** Optional. The model name used for ranking. See [Supported models](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference#supported-models). */ + modelName?: string; +} + +/** Config for Rank Service. This data type is not supported in Gemini API. */ +export declare interface RagRetrievalConfigRankingRankService { + /** Optional. The model name of the rank service. Format: `semantic-ranker-512@latest` */ + modelName?: string; +} + +declare class RateLimitError extends APIError<429, Headers> { +} + +/** A raw reference image. + + A raw reference image represents the base image to edit, provided by the user. + It can optionally be provided in addition to a mask reference image or + a style reference image. */ +export declare class RawReferenceImage { + /** The reference image for the editing operation. */ + referenceImage?: Image_2; + /** The id of the reference image. */ + referenceId?: number; + /** The type of the reference image. Only set by the SDK. */ + referenceType?: string; + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI(): ReferenceImageAPIInternal; +} + +declare type _ReadableStream_2<R = any> = NeverToAny<([0] extends [1 & _DOMReadableStream<R>] ? never : _DOMReadableStream<R>) | ([0] extends [1 & _ConditionalNodeReadableStream<R>] ? never : _ConditionalNodeReadableStream<R>)>; + +/** Marks the end of user activity. + + This can only be sent if automatic (i.e. server-side) activity detection is + disabled. */ +export declare interface RealtimeInputConfig { + /** If not set, automatic activity detection is enabled by default. If automatic voice detection is disabled, the client must send activity signals. */ + automaticActivityDetection?: AutomaticActivityDetection; + /** Defines what effect activity has. */ + activityHandling?: ActivityHandling; + /** Defines which input is included in the user's turn. */ + turnCoverage?: TurnCoverage; +} + +/** Configuration for recontextualizing an image. */ +export declare interface RecontextImageConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** Number of images to generate. */ + numberOfImages?: number; + /** The number of sampling steps. A higher value has better image + quality, while a lower value has better latency. */ + baseSteps?: number; + /** Cloud Storage URI used to store the generated images. */ + outputGcsUri?: string; + /** Random seed for image generation. */ + seed?: number; + /** Filter level for safety filtering. */ + safetyFilterLevel?: SafetyFilterLevel; + /** Whether allow to generate person images, and restrict to specific + ages. */ + personGeneration?: PersonGeneration; + /** Whether to add a SynthID watermark to the generated images. */ + addWatermark?: boolean; + /** MIME type of the generated image. */ + outputMimeType?: string; + /** Compression quality of the generated image (for ``image/jpeg`` + only). */ + outputCompressionQuality?: number; + /** Whether to use the prompt rewriting logic. */ + enhancePrompt?: boolean; + /** User specified labels to track billing usage. */ + labels?: Record<string, string>; +} + +/** The parameters for recontextualizing an image. */ +export declare interface RecontextImageParameters { + /** ID of the model to use. For a list of models, see `Google models + <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */ + model: string; + /** A set of source input(s) for image recontextualization. */ + source: RecontextImageSource; + /** Configuration for image recontextualization. */ + config?: RecontextImageConfig; +} + +/** The output images response. */ +export declare class RecontextImageResponse { + /** List of generated images. */ + generatedImages?: GeneratedImage[]; +} + +/** A set of source input(s) for image recontextualization. */ +export declare interface RecontextImageSource { + /** A text prompt for guiding the model during image + recontextualization. Not supported for Virtual Try-On. */ + prompt?: string; + /** Image of the person or subject who will be wearing the + product(s). */ + personImage?: Image_2; + /** A list of product images. */ + productImages?: ProductImage[]; +} + +export declare type ReferenceImage = RawReferenceImage | MaskReferenceImage | ControlReferenceImage | StyleReferenceImage | SubjectReferenceImage | ContentReferenceImage; + +/** Private class that represents a Reference image that is sent to API. */ +declare interface ReferenceImageAPIInternal { + /** The reference image for the editing operation. */ + referenceImage?: types.Image; + /** The id of the reference image. */ + referenceId?: number; + /** The type of the reference image. Only set by the SDK. */ + referenceType?: string; + /** Configuration for the mask reference image. */ + maskImageConfig?: types.MaskReferenceConfig; + /** Configuration for the control reference image. */ + controlImageConfig?: types.ControlReferenceConfig; + /** Configuration for the style reference image. */ + styleImageConfig?: types.StyleReferenceConfig; + /** Configuration for the subject reference image. */ + subjectImageConfig?: types.SubjectReferenceConfig; +} + +/** Used to override the default configuration. */ +export declare interface RegisterFilesConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Generates the parameters for the private registerFiles method. */ +export declare interface RegisterFilesParameters { + /** + * The authentication object. + */ + auth?: any; + /** + * The Google Cloud Storage URIs to register. Example: `gs://bucket/object`. + */ + uris: string[]; + /** Used to override the default configuration. */ + config?: RegisterFilesConfig; +} + +/** Response for the _register file method. */ +export declare class RegisterFilesResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** The registered files. */ + files?: File_2[]; +} + +/** Represents a recorded session. */ +export declare interface ReplayFile { + replayId?: string; + interactions?: ReplayInteraction[]; +} + +/** Represents a single interaction, request and response in a replay. */ +export declare interface ReplayInteraction { + request?: ReplayRequest; + response?: ReplayResponse; +} + +/** Represents a single request in a replay. */ +export declare interface ReplayRequest { + method?: string; + url?: string; + headers?: Record<string, string>; + bodySegments?: Record<string, unknown>[]; +} + +/** Represents a single response in a replay. */ +export declare class ReplayResponse { + statusCode?: number; + headers?: Record<string, string>; + bodySegments?: Record<string, unknown>[]; + sdkResponseSegments?: Record<string, unknown>[]; +} + +/** ReplicatedVoiceConfig is used to configure replicated voice. */ +export declare interface ReplicatedVoiceConfig { + /** The mime type of the replicated voice. + */ + mimeType?: string; + /** The sample audio of the replicated voice. + + * @remarks Encoded as base64 string. */ + voiceSampleAudio?: string; +} + +/** + * The type for the first argument to `fetch`. + * + * https://developer.mozilla.org/docs/Web/API/Window/fetch#resource + */ +declare type _RequestInfo = Request | URL | string; + +/** + * An alias to the builtin `RequestInit` type so we can + * easily alias it in import statements if there are name clashes. + * + * https://developer.mozilla.org/docs/Web/API/RequestInit + */ +declare type _RequestInit = RequestInit; + +declare type RequestInits = NotAny<UndiciTypesRequestInit> | NotAny<UndiciRequestInit> | NotAny<BunRequestInit> | NotAny<NodeFetch2RequestInit> | NotAny<NodeFetch3RequestInit> | NotAny<RequestInit> | NotAny<FetchRequestInit>; + +declare type RequestOptions = { + /** + * The HTTP method for the request (e.g., 'get', 'post', 'put', 'delete'). + */ + method?: HTTPMethod; + /** + * The URL path for the request. + * + * @example "/v1/foo" + */ + path?: string; + /** + * Query parameters to include in the request URL. + */ + query?: object | undefined | null; + /** + * The request body. Can be a string, JSON object, FormData, or other supported types. + */ + body?: unknown; + /** + * HTTP headers to include with the request. Can be a Headers object, plain object, or array of tuples. + */ + headers?: HeadersLike; + /** + * The maximum number of times that the client will retry a request in case of a + * temporary failure, like a network error or a 5XX error from the server. + * + * @default 2 + */ + maxRetries?: number; + stream?: boolean | undefined; + /** + * The maximum amount of time (in milliseconds) that the client should wait for a response + * from the server before timing out a single request. + * + * @unit milliseconds + */ + timeout?: number; + /** + * Additional `RequestInit` options to be passed to the underlying `fetch` call. + * These options will be merged with the client's default fetch options. + */ + fetchOptions?: MergedRequestInit; + /** + * An AbortSignal that can be used to cancel the request. + */ + signal?: AbortSignal | undefined | null; + /** + * A unique key for this request to enable idempotency. + */ + idempotencyKey?: string; + /** + * Override the default base URL for this specific request. + */ + defaultBaseURL?: string | undefined; + __binaryResponse?: boolean | undefined; + __streamClass?: typeof Stream; +}; + +/** Resource scope. */ +export declare enum ResourceScope { + /** + * When setting base_url, this value configures resource scope to be the collection. + The resource name will not include api version, project, or location. + For example, if base_url is set to "https://aiplatform.googleapis.com", + then the resource name for a Model would be + "https://aiplatform.googleapis.com/publishers/google/models/gemini-3-pro-preview + */ + COLLECTION = "COLLECTION" +} + +/** Defines a retrieval tool that model can call to access external knowledge. This data type is not supported in Gemini API. */ +export declare interface Retrieval { + /** Optional. Deprecated. This option is no longer supported. */ + disableAttribution?: boolean; + /** Use data source powered by external API for grounding. */ + externalApi?: ExternalApi; + /** Set to use data source powered by Vertex AI Search. */ + vertexAiSearch?: VertexAISearch; + /** Set to use data source powered by Vertex RAG store. User data is uploaded via the VertexRagDataService. */ + vertexRagStore?: VertexRagStore; +} + +/** Retrieval config. + */ +export declare interface RetrievalConfig { + /** Optional. The location of the user. */ + latLng?: LatLng; + /** The language code of the user. */ + languageCode?: string; +} + +/** Metadata related to retrieval in the grounding flow. */ +export declare interface RetrievalMetadata { + /** Optional. Score indicating how likely information from Google Search could help answer the prompt. The score is in the range `[0, 1]`, where 0 is the least likely and 1 is the most likely. This score is only populated when Google Search grounding and dynamic retrieval is enabled. It will be compared to the threshold to determine whether to trigger Google Search. */ + googleSearchDynamicRetrievalScore?: number; +} + +/** Safety attributes of a GeneratedImage or the user-provided prompt. */ +export declare interface SafetyAttributes { + /** List of RAI categories. */ + categories?: string[]; + /** List of scores of each categories. */ + scores?: number[]; + /** Internal use only. */ + contentType?: string; +} + +/** Enum that controls the safety filter level for objectionable content. */ +export declare enum SafetyFilterLevel { + BLOCK_LOW_AND_ABOVE = "BLOCK_LOW_AND_ABOVE", + BLOCK_MEDIUM_AND_ABOVE = "BLOCK_MEDIUM_AND_ABOVE", + BLOCK_ONLY_HIGH = "BLOCK_ONLY_HIGH", + BLOCK_NONE = "BLOCK_NONE" +} + +/** Safety rating corresponding to the generated content. */ +export declare interface SafetyRating { + /** Output only. Indicates whether the content was filtered out because of this rating. */ + blocked?: boolean; + /** Output only. Harm category. */ + category?: HarmCategory; + /** Output only. The overwritten threshold for the safety category of Gemini 2.0 image out. If minors are detected in the output image, the threshold of each safety category will be overwritten if user sets a lower threshold. This field is not supported in Gemini API. */ + overwrittenThreshold?: HarmBlockThreshold; + /** Output only. Harm probability levels in the content. */ + probability?: HarmProbability; + /** Output only. Harm probability score. This field is not supported in Gemini API. */ + probabilityScore?: number; + /** Output only. Harm severity levels in the content. This field is not supported in Gemini API. */ + severity?: HarmSeverity; + /** Output only. Harm severity score. This field is not supported in Gemini API. */ + severityScore?: number; +} + +/** Safety settings. */ +export declare interface SafetySetting { + /** Required. Harm category. */ + category?: HarmCategory; + /** Optional. Specify if the threshold is used for probability or severity score. If not specified, the threshold is used for probability score. This field is not supported in Gemini API. */ + method?: HarmBlockMethod; + /** Required. The harm block threshold. */ + threshold?: HarmBlockThreshold; +} + +/** Scale of the generated music. */ +export declare enum Scale { + /** + * Default value. This value is unused. + */ + SCALE_UNSPECIFIED = "SCALE_UNSPECIFIED", + /** + * C major or A minor. + */ + C_MAJOR_A_MINOR = "C_MAJOR_A_MINOR", + /** + * Db major or Bb minor. + */ + D_FLAT_MAJOR_B_FLAT_MINOR = "D_FLAT_MAJOR_B_FLAT_MINOR", + /** + * D major or B minor. + */ + D_MAJOR_B_MINOR = "D_MAJOR_B_MINOR", + /** + * Eb major or C minor + */ + E_FLAT_MAJOR_C_MINOR = "E_FLAT_MAJOR_C_MINOR", + /** + * E major or Db minor. + */ + E_MAJOR_D_FLAT_MINOR = "E_MAJOR_D_FLAT_MINOR", + /** + * F major or D minor. + */ + F_MAJOR_D_MINOR = "F_MAJOR_D_MINOR", + /** + * Gb major or Eb minor. + */ + G_FLAT_MAJOR_E_FLAT_MINOR = "G_FLAT_MAJOR_E_FLAT_MINOR", + /** + * G major or E minor. + */ + G_MAJOR_E_MINOR = "G_MAJOR_E_MINOR", + /** + * Ab major or F minor. + */ + A_FLAT_MAJOR_F_MINOR = "A_FLAT_MAJOR_F_MINOR", + /** + * A major or Gb minor. + */ + A_MAJOR_G_FLAT_MINOR = "A_MAJOR_G_FLAT_MINOR", + /** + * Bb major or G minor. + */ + B_FLAT_MAJOR_G_MINOR = "B_FLAT_MAJOR_G_MINOR", + /** + * B major or Ab minor. + */ + B_MAJOR_A_FLAT_MINOR = "B_MAJOR_A_FLAT_MINOR" +} + +/** Schema is used to define the format of input/output data. + + Represents a select subset of an [OpenAPI 3.0 schema + object](https://spec.openapis.org/oas/v3.0.3#schema-object). More fields may + be added in the future as needed. */ +export declare interface Schema { + /** Optional. The value should be validated against any (one or more) of the subschemas in the list. */ + anyOf?: Schema[]; + /** Optional. Default value of the data. */ + default?: unknown; + /** Optional. The description of the data. */ + description?: string; + /** Optional. Possible values of the element of primitive type with enum format. Examples: 1. We can define direction as : {type:STRING, format:enum, enum:["EAST", NORTH", "SOUTH", "WEST"]} 2. We can define apartment number as : {type:INTEGER, format:enum, enum:["101", "201", "301"]} */ + enum?: string[]; + /** Optional. Example of the object. Will only populated when the object is the root. */ + example?: unknown; + /** Optional. The format of the data. Supported formats: for NUMBER type: "float", "double" for INTEGER type: "int32", "int64" for STRING type: "email", "byte", etc */ + format?: string; + /** Optional. SCHEMA FIELDS FOR TYPE ARRAY Schema of the elements of Type.ARRAY. */ + items?: Schema; + /** Optional. Maximum number of the elements for Type.ARRAY. */ + maxItems?: string; + /** Optional. Maximum length of the Type.STRING */ + maxLength?: string; + /** Optional. Maximum number of the properties for Type.OBJECT. */ + maxProperties?: string; + /** Optional. Maximum value of the Type.INTEGER and Type.NUMBER */ + maximum?: number; + /** Optional. Minimum number of the elements for Type.ARRAY. */ + minItems?: string; + /** Optional. SCHEMA FIELDS FOR TYPE STRING Minimum length of the Type.STRING */ + minLength?: string; + /** Optional. Minimum number of the properties for Type.OBJECT. */ + minProperties?: string; + /** Optional. SCHEMA FIELDS FOR TYPE INTEGER and NUMBER Minimum value of the Type.INTEGER and Type.NUMBER */ + minimum?: number; + /** Optional. Indicates if the value may be null. */ + nullable?: boolean; + /** Optional. Pattern of the Type.STRING to restrict a string to a regular expression. */ + pattern?: string; + /** Optional. SCHEMA FIELDS FOR TYPE OBJECT Properties of Type.OBJECT. */ + properties?: Record<string, Schema>; + /** Optional. The order of the properties. Not a standard field in open api spec. Only used to support the order of the properties. */ + propertyOrdering?: string[]; + /** Optional. Required properties of Type.OBJECT. */ + required?: string[]; + /** Optional. The title of the Schema. */ + title?: string; + /** Optional. The type of the data. */ + type?: Type; +} + +export declare type SchemaUnion = Schema | unknown; + +/** An image mask representing a brush scribble. */ +export declare interface ScribbleImage { + /** The brush scribble to guide segmentation. Valid for the interactive mode. */ + image?: Image_2; +} + +/** Google search entry point. */ +export declare interface SearchEntryPoint { + /** Optional. Web content snippet that can be embedded in a web page or an app webview. */ + renderedContent?: string; + /** Optional. Base64 encoded JSON representing array of tuple. + * @remarks Encoded as base64 string. */ + sdkBlob?: string; +} + +/** Segment of the content. */ +export declare interface Segment { + /** Output only. End index in the given Part, measured in bytes. Offset from the start of the Part, exclusive, starting at zero. */ + endIndex?: number; + /** Output only. The index of a Part object within its parent Content object. */ + partIndex?: number; + /** Output only. Start index in the given Part, measured in bytes. Offset from the start of the Part, inclusive, starting at zero. */ + startIndex?: number; + /** Output only. The text corresponding to the segment from the response. */ + text?: string; +} + +/** Configuration for segmenting an image. */ +export declare interface SegmentImageConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** The segmentation mode to use. */ + mode?: SegmentMode; + /** The maximum number of predictions to return up to, by top + confidence score. */ + maxPredictions?: number; + /** The confidence score threshold for the detections as a decimal + value. Only predictions with a confidence score higher than this + threshold will be returned. */ + confidenceThreshold?: number; + /** A decimal value representing how much dilation to apply to the + masks. 0 for no dilation. 1.0 means the masked area covers the whole + image. */ + maskDilation?: number; + /** The binary color threshold to apply to the masks. The threshold + can be set to a decimal value between 0 and 255 non-inclusive. + Set to -1 for no binary color thresholding. */ + binaryColorThreshold?: number; + /** User specified labels to track billing usage. */ + labels?: Record<string, string>; +} + +/** The parameters for segmenting an image. */ +export declare interface SegmentImageParameters { + /** ID of the model to use. For a list of models, see `Google models + <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */ + model: string; + /** A set of source input(s) for image segmentation. */ + source: SegmentImageSource; + /** Configuration for image segmentation. */ + config?: SegmentImageConfig; +} + +/** The output images response. */ +export declare class SegmentImageResponse { + /** List of generated image masks. + */ + generatedMasks?: GeneratedImageMask[]; +} + +/** A set of source input(s) for image segmentation. */ +export declare interface SegmentImageSource { + /** A text prompt for guiding the model during image segmentation. + Required for prompt mode and semantic mode, disallowed for other modes. */ + prompt?: string; + /** The image to be segmented. */ + image?: Image_2; + /** The brush scribble to guide segmentation. + Required for the interactive mode, disallowed for other modes. */ + scribbleImage?: ScribbleImage; +} + +/** Enum that represents the segmentation mode. */ +export declare enum SegmentMode { + FOREGROUND = "FOREGROUND", + BACKGROUND = "BACKGROUND", + PROMPT = "PROMPT", + SEMANTIC = "SEMANTIC", + INTERACTIVE = "INTERACTIVE" +} + +/** Parameters for sending a message within a chat session. + + These parameters are used with the `chat.sendMessage()` method. */ +export declare interface SendMessageParameters { + /** The message to send to the model. + + The SDK will combine all parts into a single 'user' content to send to + the model. + */ + message: PartListUnion; + /** Config for this specific request. + + Please note that the per-request config does not change the chat level + config, nor inherit from it. If you intend to use some values from the + chat's default config, you must explicitly copy them into this per-request + config. + */ + config?: GenerateContentConfig; +} + +/** + Represents a connection to the API. + + @experimental + */ +export declare class Session { + readonly conn: WebSocket_2; + private readonly apiClient; + constructor(conn: WebSocket_2, apiClient: ApiClient); + private tLiveClientContent; + private tLiveClienttToolResponse; + /** + Send a message over the established connection. + + @param params - Contains two **optional** properties, `turns` and + `turnComplete`. + + - `turns` will be converted to a `Content[]` + - `turnComplete: true` [default] indicates that you are done sending + content and expect a response. If `turnComplete: false`, the server + will wait for additional messages before starting generation. + + @experimental + + @remarks + There are two ways to send messages to the live API: + `sendClientContent` and `sendRealtimeInput`. + + `sendClientContent` messages are added to the model context **in order**. + Having a conversation using `sendClientContent` messages is roughly + equivalent to using the `Chat.sendMessageStream`, except that the state of + the `chat` history is stored on the API server instead of locally. + + Because of `sendClientContent`'s order guarantee, the model cannot respons + as quickly to `sendClientContent` messages as to `sendRealtimeInput` + messages. This makes the biggest difference when sending objects that have + significant preprocessing time (typically images). + + The `sendClientContent` message sends a `Content[]` + which has more options than the `Blob` sent by `sendRealtimeInput`. + + So the main use-cases for `sendClientContent` over `sendRealtimeInput` are: + + - Sending anything that can't be represented as a `Blob` (text, + `sendClientContent({turns="Hello?"}`)). + - Managing turns when not using audio input and voice activity detection. + (`sendClientContent({turnComplete:true})` or the short form + `sendClientContent()`) + - Prefilling a conversation context + ``` + sendClientContent({ + turns: [ + Content({role:user, parts:...}), + Content({role:user, parts:...}), + ... + ] + }) + ``` + @experimental + */ + sendClientContent(params: types.LiveSendClientContentParameters): void; + /** + Send a realtime message over the established connection. + + @param params - Contains one property, `media`. + + - `media` will be converted to a `Blob` + + @experimental + + @remarks + Use `sendRealtimeInput` for realtime audio chunks and video frames (images). + + With `sendRealtimeInput` the api will respond to audio automatically + based on voice activity detection (VAD). + + `sendRealtimeInput` is optimized for responsivness at the expense of + deterministic ordering guarantees. Audio and video tokens are to the + context when they become available. + + Note: The Call signature expects a `Blob` object, but only a subset + of audio and image mimetypes are allowed. + */ + sendRealtimeInput(params: types.LiveSendRealtimeInputParameters): void; + /** + Send a function response message over the established connection. + + @param params - Contains property `functionResponses`. + + - `functionResponses` will be converted to a `functionResponses[]` + + @remarks + Use `sendFunctionResponse` to reply to `LiveServerToolCall` from the server. + + Use {@link types.LiveConnectConfig#tools} to configure the callable functions. + + @experimental + */ + sendToolResponse(params: types.LiveSendToolResponseParameters): void; + /** + Terminates the WebSocket connection. + + @experimental + + @example + ```ts + let model: string; + if (GOOGLE_GENAI_USE_VERTEXAI) { + model = 'gemini-2.0-flash-live-preview-04-09'; + } else { + model = 'gemini-live-2.5-flash-preview'; + } + const session = await ai.live.connect({ + model: model, + config: { + responseModalities: [Modality.AUDIO], + } + }); + + session.close(); + ``` + */ + close(): void; +} + +/** Configuration of session resumption mechanism. + + Included in `LiveConnectConfig.session_resumption`. If included server + will send `LiveServerSessionResumptionUpdate` messages. */ +export declare interface SessionResumptionConfig { + /** Session resumption handle of previous session (session to restore). + + If not present new session will be started. */ + handle?: string; + /** If set the server will send `last_consumed_client_message_index` in the `session_resumption_update` messages to allow for transparent reconnections. */ + transparent?: boolean; +} + +/** + * Overrides the base URLs for the Gemini API and Vertex AI API. + * + * @remarks This function should be called before initializing the SDK. If the + * base URLs are set after initializing the SDK, the base URLs will not be + * updated. Base URLs provided in the HttpOptions will also take precedence over + * URLs set here. + * + * @example + * ```ts + * import {GoogleGenAI, setDefaultBaseUrls} from '@google/genai'; + * // Override the base URL for the Gemini API. + * setDefaultBaseUrls({geminiUrl:'https://gemini.google.com'}); + * + * // Override the base URL for the Vertex AI API. + * setDefaultBaseUrls({vertexUrl: 'https://vertexai.googleapis.com'}); + * + * const ai = new GoogleGenAI({apiKey: 'GEMINI_API_KEY'}); + * ``` + */ +export declare function setDefaultBaseUrls(baseUrlParams: BaseUrlParameters): void; + +/** Config for `response` parameter. */ +export declare class SingleEmbedContentResponse { + /** The response to the request. + */ + embedding?: ContentEmbedding; + /** The error encountered while processing the request. + */ + tokenCount?: string; +} + +/** Context window will be truncated by keeping only suffix of it. + + Context window will always be cut at start of USER role turn. System + instructions and `BidiGenerateContentSetup.prefix_turns` will not be + subject to the sliding window mechanism, they will always stay at the + beginning of context window. */ +export declare interface SlidingWindow { + /** Session reduction target -- how many tokens we should keep. Window shortening operation has some latency costs, so we should avoid running it on every turn. Should be < trigger_tokens. If not set, trigger_tokens/2 is assumed. */ + targetTokens?: string; +} + +/** Configuration for a single speaker in a multi speaker setup. */ +export declare interface SpeakerVoiceConfig { + /** Required. The name of the speaker. This should be the same as the speaker name used in the prompt. */ + speaker?: string; + /** Required. The configuration for the voice of this speaker. */ + voiceConfig?: VoiceConfig; +} + +export declare interface SpeechConfig { + /** Configuration for the voice of the response. */ + voiceConfig?: VoiceConfig; + /** Optional. Language code (ISO 639. e.g. en-US) for the speech synthesization. */ + languageCode?: string; + /** The configuration for a multi-speaker text-to-speech request. This field is mutually exclusive with `voice_config`. */ + multiSpeakerVoiceConfig?: MultiSpeakerVoiceConfig; +} + +/** + * The configuration for speech interaction. + */ +declare interface SpeechConfig_2 { + /** + * The language of the speech. + */ + language?: string; + /** + * The speaker's name, it should match the speaker name given in the prompt. + */ + speaker?: string; + /** + * The voice of the speaker. + */ + voice?: string; +} + +export declare type SpeechConfigUnion = SpeechConfig | string; + +/** Start of speech sensitivity. */ +export declare enum StartSensitivity { + /** + * The default is START_SENSITIVITY_LOW. + */ + START_SENSITIVITY_UNSPECIFIED = "START_SENSITIVITY_UNSPECIFIED", + /** + * Automatic detection will detect the start of speech more often. + */ + START_SENSITIVITY_HIGH = "START_SENSITIVITY_HIGH", + /** + * Automatic detection will detect the start of speech less often. + */ + START_SENSITIVITY_LOW = "START_SENSITIVITY_LOW" +} + +declare class Stream<Item> implements AsyncIterable<Item> { + private iterator; + controller: AbortController; + private client; + constructor(iterator: () => AsyncIterator<Item>, controller: AbortController, client?: BaseGeminiNextGenAPIClient); + static fromSSEResponse<Item>(response: Response, controller: AbortController, client?: BaseGeminiNextGenAPIClient): Stream<Item>; + /** + * Generates a Stream from a newline-separated ReadableStream + * where each item is a JSON value. + */ + static fromReadableStream<Item>(readableStream: _ReadableStream_2, controller: AbortController, client?: BaseGeminiNextGenAPIClient): Stream<Item>; + [Symbol.asyncIterator](): AsyncIterator<Item>; + /** + * Splits the stream into two streams which can be + * independently read from at different speeds. + */ + tee(): [Stream<Item>, Stream<Item>]; + /** + * Converts this stream to a newline-separated ReadableStream of + * JSON stringified values in the stream + * which can be turned back into a Stream with `Stream.fromReadableStream()`. + */ + toReadableStream(): _ReadableStream_2; +} + +/** User provided string values assigned to a single metadata key. This data type is not supported in Vertex AI. */ +export declare interface StringList { + /** The string values of the metadata to store. */ + values?: string[]; +} + +/** Configuration for a Style reference image. */ +export declare interface StyleReferenceConfig { + /** A text description of the style to use for the generated image. */ + styleDescription?: string; +} + +/** A style reference image. + + This encapsulates a style reference image provided by the user, and + additionally optional config parameters for the style reference image. + + A raw reference image can also be provided as a destination for the style to + be applied to. */ +export declare class StyleReferenceImage { + /** The reference image for the editing operation. */ + referenceImage?: Image_2; + /** The id of the reference image. */ + referenceId?: number; + /** The type of the reference image. Only set by the SDK. */ + referenceType?: string; + /** Configuration for the style reference image. */ + config?: StyleReferenceConfig; + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI(): ReferenceImageAPIInternal; +} + +/** Configuration for a Subject reference image. */ +export declare interface SubjectReferenceConfig { + /** The subject type of a subject reference image. */ + subjectType?: SubjectReferenceType; + /** Subject description for the image. */ + subjectDescription?: string; +} + +/** A subject reference image. + + This encapsulates a subject reference image provided by the user, and + additionally optional config parameters for the subject reference image. + + A raw reference image can also be provided as a destination for the subject to + be applied to. */ +export declare class SubjectReferenceImage { + /** The reference image for the editing operation. */ + referenceImage?: Image_2; + /** The id of the reference image. */ + referenceId?: number; + /** The type of the reference image. Only set by the SDK. */ + referenceType?: string; + /** Configuration for the subject reference image. */ + config?: SubjectReferenceConfig; + toReferenceImageAPI(): ReferenceImageAPIInternal; +} + +/** Enum representing the subject type of a subject reference image. */ +export declare enum SubjectReferenceType { + SUBJECT_TYPE_DEFAULT = "SUBJECT_TYPE_DEFAULT", + SUBJECT_TYPE_PERSON = "SUBJECT_TYPE_PERSON", + SUBJECT_TYPE_ANIMAL = "SUBJECT_TYPE_ANIMAL", + SUBJECT_TYPE_PRODUCT = "SUBJECT_TYPE_PRODUCT" +} + +/** Hyperparameters for SFT. This data type is not supported in Gemini API. */ +export declare interface SupervisedHyperParameters { + /** Optional. Adapter size for tuning. */ + adapterSize?: AdapterSize; + /** Optional. Batch size for tuning. This feature is only available for open source models. */ + batchSize?: string; + /** Optional. Number of complete passes the model makes over the entire training dataset during training. */ + epochCount?: string; + /** Optional. Learning rate for tuning. Mutually exclusive with `learning_rate_multiplier`. This feature is only available for open source models. */ + learningRate?: number; + /** Optional. Multiplier for adjusting the default learning rate. Mutually exclusive with `learning_rate`. This feature is only available for 1P models. */ + learningRateMultiplier?: number; +} + +/** Dataset distribution for Supervised Tuning. This data type is not supported in Gemini API. */ +export declare interface SupervisedTuningDatasetDistribution { + /** Output only. Sum of a given population of values that are billable. */ + billableSum?: string; + /** Output only. Defines the histogram bucket. */ + buckets?: SupervisedTuningDatasetDistributionDatasetBucket[]; + /** Output only. The maximum of the population values. */ + max?: number; + /** Output only. The arithmetic mean of the values in the population. */ + mean?: number; + /** Output only. The median of the values in the population. */ + median?: number; + /** Output only. The minimum of the population values. */ + min?: number; + /** Output only. The 5th percentile of the values in the population. */ + p5?: number; + /** Output only. The 95th percentile of the values in the population. */ + p95?: number; + /** Output only. Sum of a given population of values. */ + sum?: string; +} + +/** Dataset bucket used to create a histogram for the distribution given a population of values. This data type is not supported in Gemini API. */ +export declare interface SupervisedTuningDatasetDistributionDatasetBucket { + /** Output only. Number of values in the bucket. */ + count?: number; + /** Output only. Left bound of the bucket. */ + left?: number; + /** Output only. Right bound of the bucket. */ + right?: number; +} + +/** Tuning data statistics for Supervised Tuning. This data type is not supported in Gemini API. */ +export declare interface SupervisedTuningDataStats { + /** Output only. For each index in `truncated_example_indices`, the user-facing reason why the example was dropped. */ + droppedExampleReasons?: string[]; + /** Output only. Number of billable characters in the tuning dataset. */ + totalBillableCharacterCount?: string; + /** Output only. Number of billable tokens in the tuning dataset. */ + totalBillableTokenCount?: string; + /** Output only. The number of examples in the dataset that have been dropped. An example can be dropped for reasons including: too many tokens, contains an invalid image, contains too many images, etc. */ + totalTruncatedExampleCount?: string; + /** Output only. Number of tuning characters in the tuning dataset. */ + totalTuningCharacterCount?: string; + /** Output only. A partial sample of the indices (starting from 1) of the dropped examples. */ + truncatedExampleIndices?: string[]; + /** Output only. Number of examples in the tuning dataset. */ + tuningDatasetExampleCount?: string; + /** Output only. Number of tuning steps for this Tuning Job. */ + tuningStepCount?: string; + /** Output only. Sample user messages in the training dataset uri. */ + userDatasetExamples?: Content[]; + /** Output only. Dataset distributions for the user input tokens. */ + userInputTokenDistribution?: SupervisedTuningDatasetDistribution; + /** Output only. Dataset distributions for the messages per example. */ + userMessagePerExampleDistribution?: SupervisedTuningDatasetDistribution; + /** Output only. Dataset distributions for the user output tokens. */ + userOutputTokenDistribution?: SupervisedTuningDatasetDistribution; +} + +/** Supervised tuning spec for tuning. */ +export declare interface SupervisedTuningSpec { + /** Optional. If set to true, disable intermediate checkpoints for SFT and only the last checkpoint will be exported. Otherwise, enable intermediate checkpoints for SFT. Default is false. */ + exportLastCheckpointOnly?: boolean; + /** Optional. Hyperparameters for SFT. */ + hyperParameters?: SupervisedHyperParameters; + /** Required. Training dataset used for tuning. The dataset can be specified as either a Cloud Storage path to a JSONL file or as the resource name of a Vertex Multimodal Dataset. */ + trainingDatasetUri?: string; + /** Tuning mode. */ + tuningMode?: TuningMode; + /** Optional. Validation dataset used for tuning. The dataset can be specified as either a Cloud Storage path to a JSONL file or as the resource name of a Vertex Multimodal Dataset. */ + validationDatasetUri?: string; +} + +export declare interface TestTableFile { + comment?: string; + testMethod?: string; + parameterNames?: string[]; + testTable?: TestTableItem[]; +} + +export declare interface TestTableItem { + /** The name of the test. This is used to derive the replay id. */ + name?: string; + /** The parameters to the test. Use pydantic models. */ + parameters?: Record<string, unknown>; + /** Expects an exception for MLDev matching the string. */ + exceptionIfMldev?: string; + /** Expects an exception for Vertex matching the string. */ + exceptionIfVertex?: string; + /** Use if you don't want to use the default replay id which is derived from the test name. */ + overrideReplayId?: string; + /** True if the parameters contain an unsupported union type. This test will be skipped for languages that do not support the union type. */ + hasUnion?: boolean; + /** When set to a reason string, this test will be skipped in the API mode. Use this flag for tests that can not be reproduced with the real API. E.g. a test that deletes a resource. */ + skipInApiMode?: string; + /** Keys to ignore when comparing the request and response. This is useful for tests that are not deterministic. */ + ignoreKeys?: string[]; +} + +/** + * A text content block. + */ +declare interface TextContent { + type: 'text'; + /** + * Citation information for model-generated content. + */ + annotations?: Array<Annotation>; + /** + * The text content. + */ + text?: string; +} + +/** The thinking features configuration. */ +export declare interface ThinkingConfig { + /** Indicates whether to include thoughts in the response. If true, thoughts are returned only if the model supports thought and thoughts are available. + */ + includeThoughts?: boolean; + /** Indicates the thinking budget in tokens. 0 is DISABLED. -1 is AUTOMATIC. The default values and allowed ranges are model dependent. + */ + thinkingBudget?: number; + /** Optional. The number of thoughts tokens that the model should generate. */ + thinkingLevel?: ThinkingLevel; +} + +/** The number of thoughts tokens that the model should generate. */ +export declare enum ThinkingLevel { + /** + * Unspecified thinking level. + */ + THINKING_LEVEL_UNSPECIFIED = "THINKING_LEVEL_UNSPECIFIED", + /** + * Low thinking level. + */ + LOW = "LOW", + /** + * Medium thinking level. + */ + MEDIUM = "MEDIUM", + /** + * High thinking level. + */ + HIGH = "HIGH", + /** + * MINIMAL thinking level. + */ + MINIMAL = "MINIMAL" +} + +declare type ThinkingLevel_2 = 'minimal' | 'low' | 'medium' | 'high'; + +/** + * A thought content block. + */ +declare interface ThoughtContent { + type: 'thought'; + /** + * Signature to match the backend source to be part of the generation. + */ + signature?: string; + /** + * A summary of the thought. + */ + summary?: Array<TextContent | ImageContent>; +} + +export declare class Tokens extends BaseModule { + private readonly apiClient; + constructor(apiClient: ApiClient); + /** + * Creates an ephemeral auth token resource. + * + * @experimental + * + * @remarks + * Ephemeral auth tokens is only supported in the Gemini Developer API. + * It can be used for the session connection to the Live constrained API. + * Support in v1alpha only. + * + * @param params - The parameters for the create request. + * @return The created auth token. + * + * @example + * ```ts + * const ai = new GoogleGenAI({ + * apiKey: token.name, + * httpOptions: { apiVersion: 'v1alpha' } // Support in v1alpha only. + * }); + * + * // Case 1: If LiveEphemeralParameters is unset, unlock LiveConnectConfig + * // when using the token in Live API sessions. Each session connection can + * // use a different configuration. + * const config: CreateAuthTokenConfig = { + * uses: 3, + * expireTime: '2025-05-01T00:00:00Z', + * } + * const token = await ai.tokens.create(config); + * + * // Case 2: If LiveEphemeralParameters is set, lock all fields in + * // LiveConnectConfig when using the token in Live API sessions. For + * // example, changing `outputAudioTranscription` in the Live API + * // connection will be ignored by the API. + * const config: CreateAuthTokenConfig = + * uses: 3, + * expireTime: '2025-05-01T00:00:00Z', + * LiveEphemeralParameters: { + * model: 'gemini-2.0-flash-001', + * config: { + * 'responseModalities': ['AUDIO'], + * 'systemInstruction': 'Always answer in English.', + * } + * } + * } + * const token = await ai.tokens.create(config); + * + * // Case 3: If LiveEphemeralParameters is set and lockAdditionalFields is + * // set, lock LiveConnectConfig with set and additional fields (e.g. + * // responseModalities, systemInstruction, temperature in this example) when + * // using the token in Live API sessions. + * const config: CreateAuthTokenConfig = + * uses: 3, + * expireTime: '2025-05-01T00:00:00Z', + * LiveEphemeralParameters: { + * model: 'gemini-2.0-flash-001', + * config: { + * 'responseModalities': ['AUDIO'], + * 'systemInstruction': 'Always answer in English.', + * } + * }, + * lockAdditionalFields: ['temperature'], + * } + * const token = await ai.tokens.create(config); + * + * // Case 4: If LiveEphemeralParameters is set and lockAdditionalFields is + * // empty array, lock LiveConnectConfig with set fields (e.g. + * // responseModalities, systemInstruction in this example) when using the + * // token in Live API sessions. + * const config: CreateAuthTokenConfig = + * uses: 3, + * expireTime: '2025-05-01T00:00:00Z', + * LiveEphemeralParameters: { + * model: 'gemini-2.0-flash-001', + * config: { + * 'responseModalities': ['AUDIO'], + * 'systemInstruction': 'Always answer in English.', + * } + * }, + * lockAdditionalFields: [], + * } + * const token = await ai.tokens.create(config); + * ``` + */ + create(params: types.CreateAuthTokenParameters): Promise<types.AuthToken>; +} + +/** Tokens info with a list of tokens and the corresponding list of token ids. */ +export declare interface TokensInfo { + /** Optional fields for the role from the corresponding Content. */ + role?: string; + /** A list of token ids from the input. */ + tokenIds?: string[]; + /** A list of tokens from the input. + * @remarks Encoded as base64 string. */ + tokens?: string[]; +} + +/** Tool details of a tool that the model may use to generate a response. */ +export declare interface Tool { + /** Optional. Retrieval tool type. System will always execute the provided retrieval tool(s) to get external knowledge to answer the prompt. Retrieval results are presented to the model for generation. This field is not supported in Gemini API. */ + retrieval?: Retrieval; + /** Optional. Tool to support the model interacting directly with the + computer. If enabled, it automatically populates computer-use specific + Function Declarations. */ + computerUse?: ComputerUse; + /** Optional. Tool to retrieve knowledge from the File Search Stores. */ + fileSearch?: FileSearch; + /** Optional. CodeExecution tool type. Enables the model to execute code as part of generation. */ + codeExecution?: ToolCodeExecution; + /** Optional. Tool to support searching public web data, powered by Vertex AI Search and Sec4 compliance. This field is not supported in Gemini API. */ + enterpriseWebSearch?: EnterpriseWebSearch; + /** Optional. Function tool type. One or more function declarations to be passed to the model along with the current user query. Model may decide to call a subset of these functions by populating FunctionCall in the response. User should provide a FunctionResponse for each function call in the next turn. Based on the function responses, Model will generate the final response back to the user. Maximum 512 function declarations can be provided. */ + functionDeclarations?: FunctionDeclaration[]; + /** Optional. GoogleMaps tool type. Tool to support Google Maps in Model. */ + googleMaps?: GoogleMaps; + /** Optional. GoogleSearch tool type. Tool to support Google Search in Model. Powered by Google. */ + googleSearch?: GoogleSearch; + /** Optional. Specialized retrieval tool that is powered by Google Search. */ + googleSearchRetrieval?: GoogleSearchRetrieval; + /** Optional. Tool to support URL context retrieval. */ + urlContext?: UrlContext; +} + +/** + * A tool that can be used by the model. + */ +declare type Tool_2 = Function_2 | Tool_2.GoogleSearch | Tool_2.CodeExecution | Tool_2.URLContext | Tool_2.ComputerUse | Tool_2.MCPServer | Tool_2.FileSearch; + +declare namespace Tool_2 { + /** + * A tool that can be used by the model to search Google. + */ + interface GoogleSearch { + type: 'google_search'; + } + /** + * A tool that can be used by the model to execute code. + */ + interface CodeExecution { + type: 'code_execution'; + } + /** + * A tool that can be used by the model to fetch URL context. + */ + interface URLContext { + type: 'url_context'; + } + /** + * A tool that can be used by the model to interact with the computer. + */ + interface ComputerUse { + type: 'computer_use'; + /** + * The environment being operated. + */ + environment?: 'browser'; + /** + * The list of predefined functions that are excluded from the model call. + */ + excludedPredefinedFunctions?: Array<string>; + } + /** + * A MCPServer is a server that can be called by the model to perform actions. + */ + interface MCPServer { + type: 'mcp_server'; + /** + * The allowed tools. + */ + allowed_tools?: Array<InteractionsAPI.AllowedTools>; + /** + * Optional: Fields for authentication headers, timeouts, etc., if needed. + */ + headers?: { + [key: string]: string; + }; + /** + * The name of the MCPServer. + */ + name?: string; + /** + * The full URL for the MCPServer endpoint. + * Example: "https://api.example.com/mcp" + */ + url?: string; + } + /** + * A tool that can be used by the model to search files. + */ + interface FileSearch { + type: 'file_search'; + /** + * The file search store names to search. + */ + file_search_store_names?: Array<string>; + /** + * Metadata filter to apply to the semantic retrieval documents and chunks. + */ + metadata_filter?: string; + /** + * The number of semantic retrieval chunks to retrieve. + */ + top_k?: number; + } +} + +/** + * The configuration for tool choice. + */ +declare type ToolChoice = ToolChoiceType | ToolChoiceConfig; + +declare interface ToolChoiceConfig { + /** + * The configuration for allowed tools. + */ + allowed_tools?: AllowedTools; +} + +declare type ToolChoiceType = 'auto' | 'any' | 'none' | 'validated'; + +/** Tool that executes code generated by the model, and automatically returns the result to the model. See also [ExecutableCode]and [CodeExecutionResult] which are input and output to this tool. This data type is not supported in Gemini API. */ +export declare interface ToolCodeExecution { +} + +/** Tool config. + + This config is shared for all tools provided in the request. */ +export declare interface ToolConfig { + /** Optional. Retrieval config. */ + retrievalConfig?: RetrievalConfig; + /** Optional. Function calling config. */ + functionCallingConfig?: FunctionCallingConfig; +} + +export declare type ToolListUnion = ToolUnion[]; + +export declare type ToolUnion = Tool | CallableTool; + +/** Output only. The traffic type for this request. This enum is not supported in Gemini API. */ +export declare enum TrafficType { + /** + * Unspecified request traffic type. + */ + TRAFFIC_TYPE_UNSPECIFIED = "TRAFFIC_TYPE_UNSPECIFIED", + /** + * The request was processed using Pay-As-You-Go quota. + */ + ON_DEMAND = "ON_DEMAND", + /** + * Type for Provisioned Throughput traffic. + */ + PROVISIONED_THROUGHPUT = "PROVISIONED_THROUGHPUT" +} + +/** Audio transcription in Server Conent. */ +export declare interface Transcription { + /** Transcription text. + */ + text?: string; + /** The bool indicates the end of the transcription. + */ + finished?: boolean; +} + +/** TunedModel for the Tuned Model of a Tuning Job. */ +export declare interface TunedModel { + /** Output only. The resource name of the TunedModel. + Format: `projects/{project}/locations/{location}/models/{model}@{version_id}` + When tuning from a base model, the version_id will be 1. + For continuous tuning, the version id will be incremented by 1 from the + last version id in the parent model. E.g., `projects/{project}/locations/{location}/models/{model}@{last_version_id + 1}` + */ + model?: string; + /** Output only. A resource name of an Endpoint. + Format: `projects/{project}/locations/{location}/endpoints/{endpoint}`. + */ + endpoint?: string; + /** The checkpoints associated with this TunedModel. + This field is only populated for tuning jobs that enable intermediate + checkpoints. */ + checkpoints?: TunedModelCheckpoint[]; +} + +/** TunedModelCheckpoint for the Tuned Model of a Tuning Job. */ +export declare interface TunedModelCheckpoint { + /** The ID of the checkpoint. + */ + checkpointId?: string; + /** The epoch of the checkpoint. + */ + epoch?: string; + /** The step of the checkpoint. + */ + step?: string; + /** The Endpoint resource name that the checkpoint is deployed to. + Format: `projects/{project}/locations/{location}/endpoints/{endpoint}`. + */ + endpoint?: string; +} + +/** A tuned machine learning model. */ +export declare interface TunedModelInfo { + /** ID of the base model that you want to tune. */ + baseModel?: string; + /** Date and time when the base model was created. */ + createTime?: string; + /** Date and time when the base model was last updated. */ + updateTime?: string; +} + +/** Supervised fine-tuning training dataset. */ +export declare interface TuningDataset { + /** GCS URI of the file containing training dataset in JSONL format. */ + gcsUri?: string; + /** The resource name of the Vertex Multimodal Dataset that is used as training dataset. Example: 'projects/my-project-id-or-number/locations/my-location/datasets/my-dataset-id'. */ + vertexDatasetResource?: string; + /** Inline examples with simple input/output text. */ + examples?: TuningExample[]; +} + +/** The tuning data statistic values for TuningJob. This data type is not supported in Gemini API. */ +export declare interface TuningDataStats { + /** Output only. Statistics for distillation. */ + distillationDataStats?: DistillationDataStats; + /** Output only. Statistics for preference optimization. */ + preferenceOptimizationDataStats?: PreferenceOptimizationDataStats; + /** The SFT Tuning data stats. */ + supervisedTuningDataStats?: SupervisedTuningDataStats; +} + +/** A single example for tuning. This data type is not supported in Vertex AI. */ +export declare interface TuningExample { + /** Required. The expected model output. */ + output?: string; + /** Optional. Text model input. */ + textInput?: string; +} + +/** A tuning job. */ +export declare interface TuningJob { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** Output only. Identifier. Resource name of a TuningJob. Format: `projects/{project}/locations/{location}/tuningJobs/{tuning_job}` */ + name?: string; + /** Output only. The detailed state of the job. */ + state?: JobState; + /** Output only. Time when the TuningJob was created. */ + createTime?: string; + /** Output only. Time when the TuningJob for the first time entered the `JOB_STATE_RUNNING` state. */ + startTime?: string; + /** Output only. Time when the TuningJob entered any of the following JobStates: `JOB_STATE_SUCCEEDED`, `JOB_STATE_FAILED`, `JOB_STATE_CANCELLED`, `JOB_STATE_EXPIRED`. */ + endTime?: string; + /** Output only. Time when the TuningJob was most recently updated. */ + updateTime?: string; + /** Output only. Only populated when job's state is `JOB_STATE_FAILED` or `JOB_STATE_CANCELLED`. */ + error?: GoogleRpcStatus; + /** Optional. The description of the TuningJob. */ + description?: string; + /** The base model that is being tuned. See [Supported models](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/tuning#supported_models). */ + baseModel?: string; + /** Output only. The tuned model resources associated with this TuningJob. */ + tunedModel?: TunedModel; + /** The pre-tuned model for continuous tuning. */ + preTunedModel?: PreTunedModel; + /** Tuning Spec for Supervised Fine Tuning. */ + supervisedTuningSpec?: SupervisedTuningSpec; + /** Tuning Spec for Preference Optimization. */ + preferenceOptimizationSpec?: PreferenceOptimizationSpec; + /** Tuning Spec for Distillation. */ + distillationSpec?: DistillationSpec; + /** Output only. The tuning data statistics associated with this TuningJob. */ + tuningDataStats?: TuningDataStats; + /** Customer-managed encryption key options for a TuningJob. If this is set, then all resources created by the TuningJob will be encrypted with the provided encryption key. */ + encryptionSpec?: EncryptionSpec; + /** Tuning Spec for open sourced and third party Partner models. */ + partnerModelTuningSpec?: PartnerModelTuningSpec; + /** Optional. The user-provided path to custom model weights. Set this field to tune a custom model. The path must be a Cloud Storage directory that contains the model weights in .safetensors format along with associated model metadata files. If this field is set, the base_model field must still be set to indicate which base model the custom model is derived from. This feature is only available for open source models. */ + customBaseModel?: string; + /** Output only. The Experiment associated with this TuningJob. */ + experiment?: string; + /** Optional. The labels with user-defined metadata to organize TuningJob and generated resources such as Model and Endpoint. Label keys and values can be no longer than 64 characters (Unicode codepoints), can only contain lowercase letters, numeric characters, underscores and dashes. International characters are allowed. See https://goo.gl/xmQnxf for more information and examples of labels. */ + labels?: Record<string, string>; + /** Optional. Cloud Storage path to the directory where tuning job outputs are written to. This field is only available and required for open source models. */ + outputUri?: string; + /** Output only. The resource name of the PipelineJob associated with the TuningJob. Format: `projects/{project}/locations/{location}/pipelineJobs/{pipeline_job}`. */ + pipelineJob?: string; + /** The service account that the tuningJob workload runs as. If not specified, the Vertex AI Secure Fine-Tuned Service Agent in the project will be used. See https://cloud.google.com/iam/docs/service-agents#vertex-ai-secure-fine-tuning-service-agent Users starting the pipeline must have the `iam.serviceAccounts.actAs` permission on this service account. */ + serviceAccount?: string; + /** Optional. The display name of the TunedModel. The name can be up to 128 characters long and can consist of any UTF-8 characters. For continuous tuning, tuned_model_display_name will by default use the same display name as the pre-tuned model. If a new display name is provided, the tuning job will create a new model instead of a new version. */ + tunedModelDisplayName?: string; + /** Tuning Spec for Veo Tuning. */ + veoTuningSpec?: VeoTuningSpec; +} + +/** Enum representing the tuning method. */ +export declare enum TuningMethod { + /** + * Supervised fine tuning. + */ + SUPERVISED_FINE_TUNING = "SUPERVISED_FINE_TUNING", + /** + * Preference optimization tuning. + */ + PREFERENCE_TUNING = "PREFERENCE_TUNING", + /** + * Distillation tuning. + */ + DISTILLATION = "DISTILLATION" +} + +/** Tuning mode. This enum is not supported in Gemini API. */ +export declare enum TuningMode { + /** + * Tuning mode is unspecified. + */ + TUNING_MODE_UNSPECIFIED = "TUNING_MODE_UNSPECIFIED", + /** + * Full fine-tuning mode. + */ + TUNING_MODE_FULL = "TUNING_MODE_FULL", + /** + * PEFT adapter tuning mode. + */ + TUNING_MODE_PEFT_ADAPTER = "TUNING_MODE_PEFT_ADAPTER" +} + +/** A long-running operation. */ +export declare interface TuningOperation { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`. */ + name?: string; + /** Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata. Any method that returns a long-running operation should document the metadata type, if any. */ + metadata?: Record<string, unknown>; + /** If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available. */ + done?: boolean; + /** The error result of the operation in case of failure or cancellation. */ + error?: Record<string, unknown>; +} + +declare class Tunings extends BaseModule { + private readonly apiClient; + constructor(apiClient: ApiClient); + /** + * Lists tuning jobs. + * + * @param params - The parameters for the list request. + * @return - A pager of tuning jobs. + * + * @example + * ```ts + * const tuningJobs = await ai.tunings.list({config: {'pageSize': 2}}); + * for await (const tuningJob of tuningJobs) { + * console.log(tuningJob); + * } + * ``` + */ + list: (params?: types.ListTuningJobsParameters) => Promise<Pager<types.TuningJob>>; + /** + * Gets a TuningJob. + * + * @param name - The resource name of the tuning job. + * @return - A TuningJob object. + * + * @experimental - The SDK's tuning implementation is experimental, and may + * change in future versions. + */ + get: (params: types.GetTuningJobParameters) => Promise<types.TuningJob>; + /** + * Creates a supervised fine-tuning job. + * + * @param params - The parameters for the tuning job. + * @return - A TuningJob operation. + * + * @experimental - The SDK's tuning implementation is experimental, and may + * change in future versions. + */ + tune: (params: types.CreateTuningJobParameters) => Promise<types.TuningJob>; + private getInternal; + private listInternal; + /** + * Cancels a tuning job. + * + * @param params - The parameters for the cancel request. + * @return The empty response returned by the API. + * + * @example + * ```ts + * await ai.tunings.cancel({name: '...'}); // The server-generated resource name. + * ``` + */ + cancel(params: types.CancelTuningJobParameters): Promise<types.CancelTuningJobResponse>; + private tuneInternal; + private tuneMldevInternal; +} + +/** The tuning task. Either I2V or T2V. This enum is not supported in Gemini API. */ +export declare enum TuningTask { + /** + * Default value. This value is unused. + */ + TUNING_TASK_UNSPECIFIED = "TUNING_TASK_UNSPECIFIED", + /** + * Tuning task for image to video. + */ + TUNING_TASK_I2V = "TUNING_TASK_I2V", + /** + * Tuning task for text to video. + */ + TUNING_TASK_T2V = "TUNING_TASK_T2V", + /** + * Tuning task for reference to video. + */ + TUNING_TASK_R2V = "TUNING_TASK_R2V" +} + +export declare interface TuningValidationDataset { + /** GCS URI of the file containing validation dataset in JSONL format. */ + gcsUri?: string; + /** The resource name of the Vertex Multimodal Dataset that is used as validation dataset. Example: 'projects/my-project-id-or-number/locations/my-location/datasets/my-dataset-id'. */ + vertexDatasetResource?: string; +} + +declare interface Turn { + /** + * The content of the turn. + */ + content?: string | Array<Content_2>; + /** + * The originator of this turn. Must be user for input or model for + * model output. + */ + role?: string; +} + +/** The reason why the turn is complete. */ +export declare enum TurnCompleteReason { + /** + * Default value. Reason is unspecified. + */ + TURN_COMPLETE_REASON_UNSPECIFIED = "TURN_COMPLETE_REASON_UNSPECIFIED", + /** + * The function call generated by the model is invalid. + */ + MALFORMED_FUNCTION_CALL = "MALFORMED_FUNCTION_CALL", + /** + * The response is rejected by the model. + */ + RESPONSE_REJECTED = "RESPONSE_REJECTED", + /** + * Needs more input from the user. + */ + NEED_MORE_INPUT = "NEED_MORE_INPUT" +} + +/** Options about which input is included in the user's turn. */ +export declare enum TurnCoverage { + /** + * If unspecified, the default behavior is `TURN_INCLUDES_ONLY_ACTIVITY`. + */ + TURN_COVERAGE_UNSPECIFIED = "TURN_COVERAGE_UNSPECIFIED", + /** + * The users turn only includes activity since the last turn, excluding inactivity (e.g. silence on the audio stream). This is the default behavior. + */ + TURN_INCLUDES_ONLY_ACTIVITY = "TURN_INCLUDES_ONLY_ACTIVITY", + /** + * The users turn includes all realtime input since the last turn, including inactivity (e.g. silence on the audio stream). + */ + TURN_INCLUDES_ALL_INPUT = "TURN_INCLUDES_ALL_INPUT" +} + +/** The type of the data. */ +export declare enum Type { + /** + * Not specified, should not be used. + */ + TYPE_UNSPECIFIED = "TYPE_UNSPECIFIED", + /** + * OpenAPI string type + */ + STRING = "STRING", + /** + * OpenAPI number type + */ + NUMBER = "NUMBER", + /** + * OpenAPI integer type + */ + INTEGER = "INTEGER", + /** + * OpenAPI boolean type + */ + BOOLEAN = "BOOLEAN", + /** + * OpenAPI array type + */ + ARRAY = "ARRAY", + /** + * OpenAPI object type + */ + OBJECT = "OBJECT", + /** + * Null type + */ + NULL = "NULL" +} + +declare namespace types { + export { + createFunctionResponsePartFromBase64, + createFunctionResponsePartFromUri, + createPartFromUri, + createPartFromText, + createPartFromFunctionCall, + createPartFromFunctionResponse, + createPartFromBase64, + createPartFromCodeExecutionResult, + createPartFromExecutableCode, + createUserContent, + createModelContent, + Outcome, + Language, + FunctionResponseScheduling, + Type, + ApiSpec, + AuthType, + HttpElementLocation, + PhishBlockThreshold, + Behavior, + DynamicRetrievalConfigMode, + FunctionCallingConfigMode, + ThinkingLevel, + HarmCategory, + HarmBlockMethod, + HarmBlockThreshold, + FinishReason, + HarmProbability, + HarmSeverity, + UrlRetrievalStatus, + BlockedReason, + TrafficType, + Modality, + MediaResolution, + TuningMode, + AdapterSize, + JobState, + TuningTask, + PartMediaResolutionLevel, + ResourceScope, + FeatureSelectionPreference, + Environment, + SafetyFilterLevel, + PersonGeneration, + ImagePromptLanguage, + MaskReferenceMode, + ControlReferenceType, + SubjectReferenceType, + EditMode, + SegmentMode, + VideoGenerationReferenceType, + VideoGenerationMaskMode, + VideoCompressionQuality, + TuningMethod, + DocumentState, + FileState, + FileSource, + TurnCompleteReason, + MediaModality, + VadSignalType, + VoiceActivityType, + StartSensitivity, + EndSensitivity, + ActivityHandling, + TurnCoverage, + Scale, + MusicGenerationMode, + LiveMusicPlaybackControl, + PartMediaResolution, + CodeExecutionResult, + ExecutableCode, + FileData, + PartialArg, + FunctionCall, + FunctionResponseBlob, + FunctionResponseFileData, + FunctionResponsePart, + FunctionResponse, + Blob_2 as Blob, + VideoMetadata, + Part, + Content, + HttpRetryOptions, + HttpOptions, + Schema, + ModelSelectionConfig, + ComputerUse, + FileSearch, + ApiAuthApiKeyConfig, + ApiAuth, + ApiKeyConfig, + AuthConfigGoogleServiceAccountConfig, + AuthConfigHttpBasicAuthConfig, + AuthConfigOauthConfig, + AuthConfigOidcConfig, + AuthConfig, + ExternalApiElasticSearchParams, + ExternalApiSimpleSearchParams, + ExternalApi, + VertexAISearchDataStoreSpec, + VertexAISearch, + VertexRagStoreRagResource, + RagRetrievalConfigFilter, + RagRetrievalConfigHybridSearch, + RagRetrievalConfigRankingLlmRanker, + RagRetrievalConfigRankingRankService, + RagRetrievalConfigRanking, + RagRetrievalConfig, + VertexRagStore, + Retrieval, + ToolCodeExecution, + EnterpriseWebSearch, + FunctionDeclaration, + GoogleMaps, + Interval, + GoogleSearch, + DynamicRetrievalConfig, + GoogleSearchRetrieval, + UrlContext, + Tool, + LatLng, + RetrievalConfig, + FunctionCallingConfig, + ToolConfig, + ReplicatedVoiceConfig, + PrebuiltVoiceConfig, + VoiceConfig, + SpeakerVoiceConfig, + MultiSpeakerVoiceConfig, + SpeechConfig, + AutomaticFunctionCallingConfig, + ThinkingConfig, + ImageConfig, + GenerationConfigRoutingConfigAutoRoutingMode, + GenerationConfigRoutingConfigManualRoutingMode, + GenerationConfigRoutingConfig, + SafetySetting, + ModelArmorConfig, + GenerateContentConfig, + GenerateContentParameters, + HttpResponse, + LiveCallbacks, + GoogleTypeDate, + Citation, + CitationMetadata, + GroundingChunkMapsPlaceAnswerSourcesAuthorAttribution, + GroundingChunkMapsPlaceAnswerSourcesReviewSnippet, + GroundingChunkMapsPlaceAnswerSources, + GroundingChunkMaps, + RagChunkPageSpan, + RagChunk, + GroundingChunkRetrievedContext, + GroundingChunkWeb, + GroundingChunk, + Segment, + GroundingSupport, + RetrievalMetadata, + SearchEntryPoint, + GroundingMetadataSourceFlaggingUri, + GroundingMetadata, + LogprobsResultCandidate, + LogprobsResultTopCandidates, + LogprobsResult, + SafetyRating, + UrlMetadata, + UrlContextMetadata, + Candidate, + GenerateContentResponsePromptFeedback, + ModalityTokenCount, + GenerateContentResponseUsageMetadata, + GenerateContentResponse, + ReferenceImage, + EditImageParameters, + EmbedContentConfig, + EmbedContentParameters, + ContentEmbeddingStatistics, + ContentEmbedding, + EmbedContentMetadata, + EmbedContentResponse, + GenerateImagesConfig, + GenerateImagesParameters, + Image_2 as Image, + SafetyAttributes, + GeneratedImage, + GenerateImagesResponse, + MaskReferenceConfig, + ControlReferenceConfig, + StyleReferenceConfig, + SubjectReferenceConfig, + EditImageConfig, + EditImageResponse, + UpscaleImageResponse, + ProductImage, + RecontextImageSource, + RecontextImageConfig, + RecontextImageParameters, + RecontextImageResponse, + ScribbleImage, + SegmentImageSource, + SegmentImageConfig, + SegmentImageParameters, + EntityLabel, + GeneratedImageMask, + SegmentImageResponse, + GetModelConfig, + GetModelParameters, + Endpoint, + TunedModelInfo, + Checkpoint, + Model, + ListModelsConfig, + ListModelsParameters, + ListModelsResponse, + UpdateModelConfig, + UpdateModelParameters, + DeleteModelConfig, + DeleteModelParameters, + DeleteModelResponse, + GenerationConfig, + CountTokensConfig, + CountTokensParameters, + CountTokensResponse, + ComputeTokensConfig, + ComputeTokensParameters, + TokensInfo, + ComputeTokensResponse, + Video, + GenerateVideosSource, + VideoGenerationReferenceImage, + VideoGenerationMask, + GenerateVideosConfig, + GenerateVideosParameters, + GeneratedVideo, + GenerateVideosResponse, + Operation, + GenerateVideosOperation, + GetTuningJobConfig, + GetTuningJobParameters, + TunedModelCheckpoint, + TunedModel, + SupervisedHyperParameters, + SupervisedTuningSpec, + PreferenceOptimizationHyperParameters, + PreferenceOptimizationSpec, + DistillationHyperParameters, + DistillationSpec, + GoogleRpcStatus, + PreTunedModel, + DatasetDistributionDistributionBucket, + DatasetDistribution, + DatasetStats, + DistillationDataStats, + GeminiPreferenceExampleCompletion, + GeminiPreferenceExample, + PreferenceOptimizationDataStats, + SupervisedTuningDatasetDistributionDatasetBucket, + SupervisedTuningDatasetDistribution, + SupervisedTuningDataStats, + TuningDataStats, + EncryptionSpec, + PartnerModelTuningSpec, + VeoHyperParameters, + VeoTuningSpec, + TuningJob, + ListTuningJobsConfig, + ListTuningJobsParameters, + ListTuningJobsResponse, + CancelTuningJobConfig, + CancelTuningJobParameters, + CancelTuningJobResponse, + TuningExample, + TuningDataset, + TuningValidationDataset, + CreateTuningJobConfig, + CreateTuningJobParametersPrivate, + TuningOperation, + CreateCachedContentConfig, + CreateCachedContentParameters, + CachedContentUsageMetadata, + CachedContent, + GetCachedContentConfig, + GetCachedContentParameters, + DeleteCachedContentConfig, + DeleteCachedContentParameters, + DeleteCachedContentResponse, + UpdateCachedContentConfig, + UpdateCachedContentParameters, + ListCachedContentsConfig, + ListCachedContentsParameters, + ListCachedContentsResponse, + GetDocumentConfig, + GetDocumentParameters, + StringList, + CustomMetadata, + Document_2 as Document, + DeleteDocumentConfig, + DeleteDocumentParameters, + ListDocumentsConfig, + ListDocumentsParameters, + ListDocumentsResponse, + CreateFileSearchStoreConfig, + CreateFileSearchStoreParameters, + FileSearchStore, + GetFileSearchStoreConfig, + GetFileSearchStoreParameters, + DeleteFileSearchStoreConfig, + DeleteFileSearchStoreParameters, + ListFileSearchStoresConfig, + ListFileSearchStoresParameters, + ListFileSearchStoresResponse, + WhiteSpaceConfig, + ChunkingConfig, + UploadToFileSearchStoreConfig, + UploadToFileSearchStoreParameters, + UploadToFileSearchStoreResumableResponse, + ImportFileConfig, + ImportFileParameters, + ImportFileResponse, + ImportFileOperation, + ListFilesConfig, + ListFilesParameters, + FileStatus, + File_2 as File, + ListFilesResponse, + CreateFileConfig, + CreateFileParameters, + CreateFileResponse, + GetFileConfig, + GetFileParameters, + DeleteFileConfig, + DeleteFileParameters, + DeleteFileResponse, + RegisterFilesConfig, + InternalRegisterFilesParameters, + RegisterFilesResponse, + InlinedRequest, + BatchJobSource, + JobError, + InlinedResponse, + SingleEmbedContentResponse, + InlinedEmbedContentResponse, + BatchJobDestination, + CreateBatchJobConfig, + CreateBatchJobParameters, + CompletionStats, + BatchJob, + EmbedContentBatch, + EmbeddingsBatchJobSource, + CreateEmbeddingsBatchJobConfig, + CreateEmbeddingsBatchJobParameters, + GetBatchJobConfig, + GetBatchJobParameters, + CancelBatchJobConfig, + CancelBatchJobParameters, + ListBatchJobsConfig, + ListBatchJobsParameters, + ListBatchJobsResponse, + DeleteBatchJobConfig, + DeleteBatchJobParameters, + DeleteResourceJob, + GetOperationConfig, + GetOperationParameters, + FetchPredictOperationConfig, + FetchPredictOperationParameters, + TestTableItem, + TestTableFile, + ReplayRequest, + ReplayResponse, + ReplayInteraction, + ReplayFile, + UploadFileConfig, + DownloadFileConfig, + DownloadFileParameters, + UpscaleImageConfig, + UpscaleImageParameters, + RawReferenceImage, + MaskReferenceImage, + ControlReferenceImage, + StyleReferenceImage, + SubjectReferenceImage, + ContentReferenceImage, + LiveServerSetupComplete, + Transcription, + LiveServerContent, + LiveServerToolCall, + LiveServerToolCallCancellation, + UsageMetadata, + LiveServerGoAway, + LiveServerSessionResumptionUpdate, + VoiceActivityDetectionSignal, + VoiceActivity, + LiveServerMessage, + OperationFromAPIResponseParameters, + GenerationConfigThinkingConfig, + RegisterFilesParameters, + AutomaticActivityDetection, + RealtimeInputConfig, + SessionResumptionConfig, + SlidingWindow, + ContextWindowCompressionConfig, + AudioTranscriptionConfig, + ProactivityConfig, + LiveClientSetup, + LiveClientContent, + ActivityStart, + ActivityEnd, + LiveClientRealtimeInput, + LiveClientToolResponse, + LiveSendRealtimeInputParameters, + LiveClientMessage, + LiveConnectConfig, + LiveConnectParameters, + CreateChatParameters, + SendMessageParameters, + LiveSendClientContentParameters, + LiveSendToolResponseParameters, + LiveMusicClientSetup, + WeightedPrompt, + LiveMusicClientContent, + LiveMusicGenerationConfig, + LiveMusicClientMessage, + LiveMusicServerSetupComplete, + LiveMusicSourceMetadata, + AudioChunk, + LiveMusicServerContent, + LiveMusicFilteredPrompt, + LiveMusicServerMessage, + LiveMusicCallbacks, + UploadFileParameters, + CallableTool, + CallableToolConfig, + LiveMusicConnectParameters, + LiveMusicSetConfigParameters, + LiveMusicSetWeightedPromptsParameters, + AuthToken, + LiveConnectConstraints, + CreateAuthTokenConfig, + CreateAuthTokenParameters, + OperationGetParameters, + CountTokensResult, + ComputeTokensResult, + CreateTuningJobParameters, + UploadToFileSearchStoreResponse, + UploadToFileSearchStoreOperation, + BlobImageUnion, + PartUnion, + PartListUnion, + ContentUnion, + ContentListUnion, + SchemaUnion, + SpeechConfigUnion, + ToolUnion, + ToolListUnion, + DownloadableFileUnion, + BatchJobSourceUnion, + BatchJobDestinationUnion + } +} + +/** @ts-ignore For users with undici */ +declare type UndiciRequestInit = NotAny<import('../node_modules/undici/index.d.ts').RequestInit> | NotAny<import('../../node_modules/undici/index.d.ts').RequestInit> | NotAny<import('../../../node_modules/undici/index.d.ts').RequestInit> | NotAny<import('../../../../node_modules/undici/index.d.ts').RequestInit> | NotAny<import('../../../../../node_modules/undici/index.d.ts').RequestInit> | NotAny<import('../../../../../../node_modules/undici/index.d.ts').RequestInit> | NotAny<import('../../../../../../../node_modules/undici/index.d.ts').RequestInit> | NotAny<import('../../../../../../../../node_modules/undici/index.d.ts').RequestInit> | NotAny<import('../../../../../../../../../node_modules/undici/index.d.ts').RequestInit> | NotAny<import('../../../../../../../../../../node_modules/undici/index.d.ts').RequestInit>; + +/** + * These imports attempt to get types from a parent package's dependencies. + * Unresolved bare specifiers can trigger [automatic type acquisition][1] in some projects, which + * would cause typescript to show types not present at runtime. To avoid this, we import + * directly from parent node_modules folders. + * + * We need to check multiple levels because we don't know what directory structure we'll be in. + * For example, pnpm generates directories like this: + * ``` + * node_modules + * ├── .pnpm + * │ └── pkg@1.0.0 + * │ └── node_modules + * │ └── pkg + * │ └── internal + * │ └── types.d.ts + * ├── pkg -> .pnpm/pkg@1.0.0/node_modules/pkg + * └── undici + * ``` + * + * [1]: https://www.typescriptlang.org/tsconfig/#typeAcquisition + */ +/** @ts-ignore For users with \@types/node */ +declare type UndiciTypesRequestInit = NotAny<import('../node_modules/undici-types/index.d.ts').RequestInit> | NotAny<import('../../node_modules/undici-types/index.d.ts').RequestInit> | NotAny<import('../../../node_modules/undici-types/index.d.ts').RequestInit> | NotAny<import('../../../../node_modules/undici-types/index.d.ts').RequestInit> | NotAny<import('../../../../../node_modules/undici-types/index.d.ts').RequestInit> | NotAny<import('../../../../../../node_modules/undici-types/index.d.ts').RequestInit> | NotAny<import('../../../../../../../node_modules/undici-types/index.d.ts').RequestInit> | NotAny<import('../../../../../../../../node_modules/undici-types/index.d.ts').RequestInit> | NotAny<import('../../../../../../../../../node_modules/undici-types/index.d.ts').RequestInit> | NotAny<import('../../../../../../../../../../node_modules/undici-types/index.d.ts').RequestInit>; + +declare class UnprocessableEntityError extends APIError<422, Headers> { +} + +/** Optional parameters for caches.update method. */ +export declare interface UpdateCachedContentConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** The TTL for this resource. The expiration time is computed: now + TTL. It is a duration string, with up to nine fractional digits, terminated by 's'. Example: "3.5s". */ + ttl?: string; + /** Timestamp of when this resource is considered expired. Uses RFC 3339 format, Example: 2014-10-02T15:01:23Z. */ + expireTime?: string; +} + +export declare interface UpdateCachedContentParameters { + /** The server-generated resource name of the cached content. + */ + name: string; + /** Configuration that contains optional parameters. + */ + config?: UpdateCachedContentConfig; +} + +/** Configuration for updating a tuned model. */ +export declare interface UpdateModelConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + displayName?: string; + description?: string; + defaultCheckpointId?: string; +} + +/** Configuration for updating a tuned model. */ +export declare interface UpdateModelParameters { + model: string; + config?: UpdateModelConfig; +} + +declare interface Uploader { + /** + * Uploads a file to the given upload url. + * + * @param file The file to upload. file is in string type or a Blob. + * @param uploadUrl The upload URL as a string is where the file will be + * uploaded to. The uploadUrl must be a url that was returned by the + * https://generativelanguage.googleapis.com/upload/v1beta/files endpoint + * @param apiClient The ApiClient to use for uploading. + * @return A Promise that resolves to types.File. + */ + upload(file: string | Blob, uploadUrl: string, apiClient: ApiClient): Promise<File_2>; + /** + * Uploads a file to file search store via the given upload url. + * + * @param file The file to upload. file is in string type or a Blob. + * @param uploadUrl The upload URL as a string is where the file will be + * uploaded to. The uploadUrl must be a url that was returned by the + * https://generativelanguage.googleapis.com/upload/v1beta/{file_search_store_name}:uploadToFileSearchStore endpoint + * @param apiClient The ApiClient to use for uploading. + * @return A Promise that resolves to types.UploadToFileSearchStoreOperation. + */ + uploadToFileSearchStore(file: string | Blob, uploadUrl: string, apiClient: ApiClient): Promise<UploadToFileSearchStoreOperation>; + /** + * Returns the file's mimeType and the size of a given file. If the file is a + * string path, the file type is determined by the file extension. If the + * file's type cannot be determined, the type will be set to undefined. + * + * @param file The file to get the stat for. Can be a string path or a Blob. + * @return A Promise that resolves to the file stat of the given file. + */ + stat(file: string | Blob): Promise<FileStat>; +} + +/** Used to override the default configuration. */ +export declare interface UploadFileConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** The name of the file in the destination (e.g., 'files/sample-image'. If not provided one will be generated. */ + name?: string; + /** mime_type: The MIME type of the file. If not provided, it will be inferred from the file extension. */ + mimeType?: string; + /** Optional display name of the file. */ + displayName?: string; +} + +/** Parameters for the upload file method. */ +export declare interface UploadFileParameters { + /** The string path to the file to be uploaded or a Blob object. */ + file: string | globalThis.Blob; + /** Configuration that contains optional parameters. */ + config?: UploadFileConfig; +} + +/** Optional parameters for uploading a file to a FileSearchStore. */ +export declare interface UploadToFileSearchStoreConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** MIME type of the file to be uploaded. If not provided, it will be inferred from the file extension. */ + mimeType?: string; + /** Display name of the created document. */ + displayName?: string; + /** User provided custom metadata stored as key-value pairs used for querying. */ + customMetadata?: CustomMetadata[]; + /** Config for telling the service how to chunk the file. */ + chunkingConfig?: ChunkingConfig; +} + +/** Long-running operation for uploading a file to a FileSearchStore. */ +export declare class UploadToFileSearchStoreOperation implements Operation<UploadToFileSearchStoreResponse> { + /** The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`. */ + name?: string; + /** Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata. Any method that returns a long-running operation should document the metadata type, if any. */ + metadata?: Record<string, unknown>; + /** If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available. */ + done?: boolean; + /** The error result of the operation in case of failure or cancellation. */ + error?: Record<string, unknown>; + /** The result of the UploadToFileSearchStore operation, available when the operation is done. */ + response?: UploadToFileSearchStoreResponse; + /** + * Instantiates an Operation of the same type as the one being called with the fields set from the API response. + * @internal + */ + _fromAPIResponse({ apiResponse, _isVertexAI, }: OperationFromAPIResponseParameters): Operation<UploadToFileSearchStoreResponse>; + /** The full HTTP response. */ + sdkHttpResponse?: HttpResponse; +} + +/** Generates the parameters for the private _upload_to_file_search_store method. */ +export declare interface UploadToFileSearchStoreParameters { + /** The resource name of the FileSearchStore. Example: `fileSearchStores/my-file-search-store-123` */ + fileSearchStoreName: string; + /** Used to override the default configuration. */ + config?: UploadToFileSearchStoreConfig; +} + +/** Parameters for the upload file to file search store method. */ +export declare interface UploadToFileSearchStoreParameters { + /** The name of the file search store to upload. */ + fileSearchStoreName: string; + /** The string path to the file to be uploaded or a Blob object. */ + file: string | globalThis.Blob; + /** Configuration that contains optional parameters. */ + config?: UploadToFileSearchStoreConfig; +} + +/** The response when long-running operation for uploading a file to a FileSearchStore complete. */ +export declare class UploadToFileSearchStoreResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** The name of the FileSearchStore containing Documents. */ + parent?: string; + /** The identifier for the Document imported. */ + documentName?: string; +} + +/** Response for the resumable upload method. */ +export declare class UploadToFileSearchStoreResumableResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; +} + +/** Configuration for upscaling an image. + + For more information on this configuration, refer to + the `Imagen API reference documentation + <https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/imagen-api>`_. */ +export declare interface UpscaleImageConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** Cloud Storage URI used to store the generated images. */ + outputGcsUri?: string; + /** Filter level for safety filtering. */ + safetyFilterLevel?: SafetyFilterLevel; + /** Allows generation of people by the model. */ + personGeneration?: PersonGeneration; + /** Whether to include a reason for filtered-out images in the + response. */ + includeRaiReason?: boolean; + /** The image format that the output should be saved as. */ + outputMimeType?: string; + /** The level of compression. Only applicable if the + ``output_mime_type`` is ``image/jpeg``. */ + outputCompressionQuality?: number; + /** Whether to add an image enhancing step before upscaling. + It is expected to suppress the noise and JPEG compression artifacts + from the input image. */ + enhanceInputImage?: boolean; + /** With a higher image preservation factor, the original image + pixels are more respected. With a lower image preservation factor, the + output image will have be more different from the input image, but + with finer details and less noise. */ + imagePreservationFactor?: number; + /** User specified labels to track billing usage. */ + labels?: Record<string, string>; +} + +/** User-facing config UpscaleImageParameters. */ +export declare interface UpscaleImageParameters { + /** The model to use. */ + model: string; + /** The input image to upscale. */ + image: Image_2; + /** The factor to upscale the image (x2 or x4). */ + upscaleFactor: string; + /** Configuration for upscaling. */ + config?: UpscaleImageConfig; +} + +export declare class UpscaleImageResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** Generated images. */ + generatedImages?: GeneratedImage[]; +} + +/** Tool to support URL context. */ +export declare interface UrlContext { +} + +/** + * The arguments to pass to the URL context. + */ +declare interface URLContextCallArguments { + /** + * The URLs to fetch. + */ + urls?: Array<string>; +} + +/** + * URL context content. + */ +declare interface URLContextCallContent { + type: 'url_context_call'; + /** + * A unique ID for this specific tool call. + */ + id?: string; + /** + * The arguments to pass to the URL context. + */ + arguments?: URLContextCallArguments; +} + +/** Metadata related to url context retrieval tool. */ +export declare interface UrlContextMetadata { + /** Output only. List of url context. */ + urlMetadata?: UrlMetadata[]; +} + +/** + * The result of the URL context. + */ +declare interface URLContextResult { + /** + * The status of the URL retrieval. + */ + status?: 'success' | 'error' | 'paywall' | 'unsafe'; + /** + * The URL that was fetched. + */ + url?: string; +} + +/** + * URL context result content. + */ +declare interface URLContextResultContent { + type: 'url_context_result'; + /** + * ID to match the ID from the url context call block. + */ + call_id?: string; + /** + * Whether the URL context resulted in an error. + */ + is_error?: boolean; + /** + * The results of the URL context. + */ + result?: Array<URLContextResult>; + /** + * The signature of the URL context result. + */ + signature?: string; +} + +/** Context of the a single url retrieval. */ +export declare interface UrlMetadata { + /** Retrieved url by the tool. */ + retrievedUrl?: string; + /** Status of the url retrieval. */ + urlRetrievalStatus?: UrlRetrievalStatus; +} + +/** Status of the url retrieval. */ +export declare enum UrlRetrievalStatus { + /** + * Default value. This value is unused. + */ + URL_RETRIEVAL_STATUS_UNSPECIFIED = "URL_RETRIEVAL_STATUS_UNSPECIFIED", + /** + * Url retrieval is successful. + */ + URL_RETRIEVAL_STATUS_SUCCESS = "URL_RETRIEVAL_STATUS_SUCCESS", + /** + * Url retrieval is failed due to error. + */ + URL_RETRIEVAL_STATUS_ERROR = "URL_RETRIEVAL_STATUS_ERROR", + /** + * Url retrieval is failed because the content is behind paywall. This enum value is not supported in Vertex AI. + */ + URL_RETRIEVAL_STATUS_PAYWALL = "URL_RETRIEVAL_STATUS_PAYWALL", + /** + * Url retrieval is failed because the content is unsafe. This enum value is not supported in Vertex AI. + */ + URL_RETRIEVAL_STATUS_UNSAFE = "URL_RETRIEVAL_STATUS_UNSAFE" +} + +/** + * Statistics on the interaction request's token usage. + */ +declare interface Usage { + /** + * A breakdown of cached token usage by modality. + */ + cached_tokens_by_modality?: Array<Usage.CachedTokensByModality>; + /** + * A breakdown of input token usage by modality. + */ + input_tokens_by_modality?: Array<Usage.InputTokensByModality>; + /** + * A breakdown of output token usage by modality. + */ + output_tokens_by_modality?: Array<Usage.OutputTokensByModality>; + /** + * A breakdown of tool-use token usage by modality. + */ + tool_use_tokens_by_modality?: Array<Usage.ToolUseTokensByModality>; + /** + * Number of tokens in the cached part of the prompt (the cached content). + */ + total_cached_tokens?: number; + /** + * Number of tokens in the prompt (context). + */ + total_input_tokens?: number; + /** + * Total number of tokens across all the generated responses. + */ + total_output_tokens?: number; + /** + * Number of tokens of thoughts for thinking models. + */ + total_thought_tokens?: number; + /** + * Total token count for the interaction request (prompt + responses + other + * internal tokens). + */ + total_tokens?: number; + /** + * Number of tokens present in tool-use prompt(s). + */ + total_tool_use_tokens?: number; +} + +declare namespace Usage { + /** + * The token count for a single response modality. + */ + interface CachedTokensByModality { + /** + * The modality associated with the token count. + */ + modality?: 'text' | 'image' | 'audio'; + /** + * Number of tokens for the modality. + */ + tokens?: number; + } + /** + * The token count for a single response modality. + */ + interface InputTokensByModality { + /** + * The modality associated with the token count. + */ + modality?: 'text' | 'image' | 'audio'; + /** + * Number of tokens for the modality. + */ + tokens?: number; + } + /** + * The token count for a single response modality. + */ + interface OutputTokensByModality { + /** + * The modality associated with the token count. + */ + modality?: 'text' | 'image' | 'audio'; + /** + * Number of tokens for the modality. + */ + tokens?: number; + } + /** + * The token count for a single response modality. + */ + interface ToolUseTokensByModality { + /** + * The modality associated with the token count. + */ + modality?: 'text' | 'image' | 'audio'; + /** + * Number of tokens for the modality. + */ + tokens?: number; + } +} + +/** Usage metadata about response(s). */ +export declare interface UsageMetadata { + /** Number of tokens in the prompt. When `cached_content` is set, this is still the total effective prompt size meaning this includes the number of tokens in the cached content. */ + promptTokenCount?: number; + /** Number of tokens in the cached part of the prompt (the cached content). */ + cachedContentTokenCount?: number; + /** Total number of tokens across all the generated response candidates. */ + responseTokenCount?: number; + /** Number of tokens present in tool-use prompt(s). */ + toolUsePromptTokenCount?: number; + /** Number of tokens of thoughts for thinking models. */ + thoughtsTokenCount?: number; + /** Total token count for prompt, response candidates, and tool-use prompts(if present). */ + totalTokenCount?: number; + /** List of modalities that were processed in the request input. */ + promptTokensDetails?: ModalityTokenCount[]; + /** List of modalities that were processed in the cache input. */ + cacheTokensDetails?: ModalityTokenCount[]; + /** List of modalities that were returned in the response. */ + responseTokensDetails?: ModalityTokenCount[]; + /** List of modalities that were processed in the tool-use prompt. */ + toolUsePromptTokensDetails?: ModalityTokenCount[]; + /** Traffic type. This shows whether a request consumes Pay-As-You-Go + or Provisioned Throughput quota. */ + trafficType?: TrafficType; +} + +/** The type of the VAD signal. */ +export declare enum VadSignalType { + /** + * The default is VAD_SIGNAL_TYPE_UNSPECIFIED. + */ + VAD_SIGNAL_TYPE_UNSPECIFIED = "VAD_SIGNAL_TYPE_UNSPECIFIED", + /** + * Start of sentence signal. + */ + VAD_SIGNAL_TYPE_SOS = "VAD_SIGNAL_TYPE_SOS", + /** + * End of sentence signal. + */ + VAD_SIGNAL_TYPE_EOS = "VAD_SIGNAL_TYPE_EOS" +} + +/** Hyperparameters for Veo. This data type is not supported in Gemini API. */ +export declare interface VeoHyperParameters { + /** Optional. Number of complete passes the model makes over the entire training dataset during training. */ + epochCount?: string; + /** Optional. Multiplier for adjusting the default learning rate. */ + learningRateMultiplier?: number; + /** Optional. The tuning task. Either I2V or T2V. */ + tuningTask?: TuningTask; +} + +/** Tuning Spec for Veo Model Tuning. This data type is not supported in Gemini API. */ +export declare interface VeoTuningSpec { + /** Optional. Hyperparameters for Veo. */ + hyperParameters?: VeoHyperParameters; + /** Required. Training dataset used for tuning. The dataset can be specified as either a Cloud Storage path to a JSONL file or as the resource name of a Vertex Multimodal Dataset. */ + trainingDatasetUri?: string; + /** Optional. Validation dataset used for tuning. The dataset can be specified as either a Cloud Storage path to a JSONL file or as the resource name of a Vertex Multimodal Dataset. */ + validationDatasetUri?: string; +} + +/** Retrieve from Vertex AI Search datastore or engine for grounding. datastore and engine are mutually exclusive. See https://cloud.google.com/products/agent-builder. This data type is not supported in Gemini API. */ +export declare interface VertexAISearch { + /** Specifications that define the specific DataStores to be searched, along with configurations for those data stores. This is only considered for Engines with multiple data stores. It should only be set if engine is used. */ + dataStoreSpecs?: VertexAISearchDataStoreSpec[]; + /** Optional. Fully-qualified Vertex AI Search data store resource ID. Format: `projects/{project}/locations/{location}/collections/{collection}/dataStores/{dataStore}` */ + datastore?: string; + /** Optional. Fully-qualified Vertex AI Search engine resource ID. Format: `projects/{project}/locations/{location}/collections/{collection}/engines/{engine}` */ + engine?: string; + /** Optional. Filter strings to be passed to the search API. */ + filter?: string; + /** Optional. Number of search results to return per query. The default value is 10. The maximumm allowed value is 10. */ + maxResults?: number; +} + +/** Define data stores within engine to filter on in a search call and configurations for those data stores. For more information, see https://cloud.google.com/generative-ai-app-builder/docs/reference/rpc/google.cloud.discoveryengine.v1#datastorespec. This data type is not supported in Gemini API. */ +export declare interface VertexAISearchDataStoreSpec { + /** Full resource name of DataStore, such as Format: `projects/{project}/locations/{location}/collections/{collection}/dataStores/{dataStore}` */ + dataStore?: string; + /** Optional. Filter specification to filter documents in the data store specified by data_store field. For more information on filtering, see [Filtering](https://cloud.google.com/generative-ai-app-builder/docs/filter-search-metadata) */ + filter?: string; +} + +/** Retrieve from Vertex RAG Store for grounding. This data type is not supported in Gemini API. */ +export declare interface VertexRagStore { + /** Optional. Deprecated. Please use rag_resources instead. */ + ragCorpora?: string[]; + /** Optional. The representation of the rag source. It can be used to specify corpus only or ragfiles. Currently only support one corpus or multiple files from one corpus. In the future we may open up multiple corpora support. */ + ragResources?: VertexRagStoreRagResource[]; + /** Optional. The retrieval config for the Rag query. */ + ragRetrievalConfig?: RagRetrievalConfig; + /** Optional. Number of top k results to return from the selected corpora. */ + similarityTopK?: number; + /** Optional. Currently only supported for Gemini Multimodal Live API. In Gemini Multimodal Live API, if `store_context` bool is specified, Gemini will leverage it to automatically memorize the interactions between the client and Gemini, and retrieve context when needed to augment the response generation for users' ongoing and future interactions. */ + storeContext?: boolean; + /** Optional. Only return results with vector distance smaller than the threshold. */ + vectorDistanceThreshold?: number; +} + +/** The definition of the Rag resource. This data type is not supported in Gemini API. */ +export declare interface VertexRagStoreRagResource { + /** Optional. RagCorpora resource name. Format: `projects/{project}/locations/{location}/ragCorpora/{rag_corpus}` */ + ragCorpus?: string; + /** Optional. rag_file_id. The files should be in the same rag_corpus set in rag_corpus field. */ + ragFileIds?: string[]; +} + +/** A generated video. */ +export declare interface Video { + /** Path to another storage. */ + uri?: string; + /** Video bytes. + * @remarks Encoded as base64 string. */ + videoBytes?: string; + /** Video encoding, for example ``video/mp4``. */ + mimeType?: string; +} + +/** Enum that controls the compression quality of the generated videos. */ +export declare enum VideoCompressionQuality { + /** + * Optimized video compression quality. This will produce videos + with a compressed, smaller file size. + */ + OPTIMIZED = "OPTIMIZED", + /** + * Lossless video compression quality. This will produce videos + with a larger file size. + */ + LOSSLESS = "LOSSLESS" +} + +/** + * A video content block. + */ +declare interface VideoContent { + type: 'video'; + /** + * The video content. + */ + data?: string; + /** + * The mime type of the video. + */ + mime_type?: VideoMimeType; + /** + * The resolution of the media. + */ + resolution?: 'low' | 'medium' | 'high' | 'ultra_high'; + /** + * The URI of the video. + */ + uri?: string; +} + +/** A mask for video generation. */ +export declare interface VideoGenerationMask { + /** The image mask to use for generating videos. */ + image?: Image_2; + /** Describes how the mask will be used. Inpainting masks must + match the aspect ratio of the input video. Outpainting masks can be + either 9:16 or 16:9. */ + maskMode?: VideoGenerationMaskMode; +} + +/** Enum for the mask mode of a video generation mask. */ +export declare enum VideoGenerationMaskMode { + /** + * The image mask contains a masked rectangular region which is + applied on the first frame of the input video. The object described in + the prompt is inserted into this region and will appear in subsequent + frames. + */ + INSERT = "INSERT", + /** + * The image mask is used to determine an object in the + first video frame to track. This object is removed from the video. + */ + REMOVE = "REMOVE", + /** + * The image mask is used to determine a region in the + video. Objects in this region will be removed. + */ + REMOVE_STATIC = "REMOVE_STATIC", + /** + * The image mask contains a masked rectangular region where + the input video will go. The remaining area will be generated. Video + masks are not supported. + */ + OUTPAINT = "OUTPAINT" +} + +/** A reference image for video generation. */ +export declare interface VideoGenerationReferenceImage { + /** The reference image. */ + image?: Image_2; + /** The type of the reference image, which defines how the reference + image will be used to generate the video. */ + referenceType?: VideoGenerationReferenceType; +} + +/** Enum for the reference type of a video generation reference image. */ +export declare enum VideoGenerationReferenceType { + /** + * A reference image that provides assets to the generated video, + such as the scene, an object, a character, etc. + */ + ASSET = "ASSET", + /** + * A reference image that provides aesthetics including colors, + lighting, texture, etc., to be used as the style of the generated video, + such as 'anime', 'photography', 'origami', etc. + */ + STYLE = "STYLE" +} + +/** Metadata describes the input video content. */ +export declare interface VideoMetadata { + /** Optional. The end offset of the video. */ + endOffset?: string; + /** Optional. The frame rate of the video sent to the model. If not specified, the default value will be 1.0. The fps range is (0.0, 24.0]. */ + fps?: number; + /** Optional. The start offset of the video. */ + startOffset?: string; +} + +/** + * The mime type of the video. + */ +declare type VideoMimeType = 'video/mp4' | 'video/mpeg' | 'video/mov' | 'video/avi' | 'video/x-flv' | 'video/mpg' | 'video/webm' | 'video/wmv' | 'video/3gpp' | (string & {}); + +/** Voice activity signal. */ +export declare interface VoiceActivity { + /** The type of the voice activity signal. */ + voiceActivityType?: VoiceActivityType; +} + +export declare interface VoiceActivityDetectionSignal { + /** The type of the VAD signal. */ + vadSignalType?: VadSignalType; +} + +/** The type of the voice activity signal. */ +export declare enum VoiceActivityType { + /** + * The default is VOICE_ACTIVITY_TYPE_UNSPECIFIED. + */ + TYPE_UNSPECIFIED = "TYPE_UNSPECIFIED", + /** + * Start of sentence signal. + */ + ACTIVITY_START = "ACTIVITY_START", + /** + * End of sentence signal. + */ + ACTIVITY_END = "ACTIVITY_END" +} + +export declare interface VoiceConfig { + /** If true, the model will use a replicated voice for the response. */ + replicatedVoiceConfig?: ReplicatedVoiceConfig; + /** The configuration for the prebuilt voice to use. */ + prebuiltVoiceConfig?: PrebuiltVoiceConfig; +} + +declare interface WebSocket_2 { + /** + * Connects the socket to the server. + */ + connect(): void; + /** + * Sends a message to the server. + */ + send(message: string): void; + /** + * Closes the socket connection. + */ + close(): void; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +declare interface WebSocketCallbacks { + onopen: () => void; + onerror: (e: any) => void; + onmessage: (e: any) => void; + onclose: (e: any) => void; +} + +declare interface WebSocketFactory { + /** + * Returns a new WebSocket instance. + */ + create(url: string, headers: Record<string, string>, callbacks: WebSocketCallbacks): WebSocket_2; +} + +/** Maps a prompt to a relative weight to steer music generation. */ +export declare interface WeightedPrompt { + /** Text prompt. */ + text?: string; + /** Weight of the prompt. The weight is used to control the relative + importance of the prompt. Higher weights are more important than lower + weights. + + Weight must not be 0. Weights of all weighted_prompts in this + LiveMusicClientContent message will be normalized. */ + weight?: number; +} + +/** Configuration for a white space chunking algorithm. */ +export declare interface WhiteSpaceConfig { + /** Maximum number of tokens per chunk. */ + maxTokensPerChunk?: number; + /** Maximum number of overlapping tokens between two adjacent chunks. */ + maxOverlapTokens?: number; +} + +export { } diff --git a/server/node_modules/@google/genai/dist/tokenizer/node.cjs b/server/node_modules/@google/genai/dist/tokenizer/node.cjs new file mode 100644 index 0000000..e6e5a4a --- /dev/null +++ b/server/node_modules/@google/genai/dist/tokenizer/node.cjs @@ -0,0 +1,5680 @@ +'use strict'; + +var $protobuf = require('protobufjs/minimal.js'); +var crypto = require('crypto'); +var fs = require('fs/promises'); +var os = require('os'); +var path = require('path'); + +function _interopNamespaceDefault(e) { + var n = Object.create(null); + if (e) { + Object.keys(e).forEach(function (k) { + if (k !== 'default') { + var d = Object.getOwnPropertyDescriptor(e, k); + Object.defineProperty(n, k, d.get ? d : { + enumerable: true, + get: function () { return e[k]; } + }); + } + }); + } + n.default = e; + return Object.freeze(n); +} + +var crypto__namespace = /*#__PURE__*/_interopNamespaceDefault(crypto); +var fs__namespace = /*#__PURE__*/_interopNamespaceDefault(fs); +var os__namespace = /*#__PURE__*/_interopNamespaceDefault(os); +var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path); + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** Outcome of the code execution. */ +var Outcome; +(function (Outcome) { + /** + * Unspecified status. This value should not be used. + */ + Outcome["OUTCOME_UNSPECIFIED"] = "OUTCOME_UNSPECIFIED"; + /** + * Code execution completed successfully. + */ + Outcome["OUTCOME_OK"] = "OUTCOME_OK"; + /** + * Code execution finished but with a failure. `stderr` should contain the reason. + */ + Outcome["OUTCOME_FAILED"] = "OUTCOME_FAILED"; + /** + * Code execution ran for too long, and was cancelled. There may or may not be a partial output present. + */ + Outcome["OUTCOME_DEADLINE_EXCEEDED"] = "OUTCOME_DEADLINE_EXCEEDED"; +})(Outcome || (Outcome = {})); +/** Programming language of the `code`. */ +var Language; +(function (Language) { + /** + * Unspecified language. This value should not be used. + */ + Language["LANGUAGE_UNSPECIFIED"] = "LANGUAGE_UNSPECIFIED"; + /** + * Python >= 3.10, with numpy and simpy available. + */ + Language["PYTHON"] = "PYTHON"; +})(Language || (Language = {})); +/** Specifies how the response should be scheduled in the conversation. */ +var FunctionResponseScheduling; +(function (FunctionResponseScheduling) { + /** + * This value is unused. + */ + FunctionResponseScheduling["SCHEDULING_UNSPECIFIED"] = "SCHEDULING_UNSPECIFIED"; + /** + * Only add the result to the conversation context, do not interrupt or trigger generation. + */ + FunctionResponseScheduling["SILENT"] = "SILENT"; + /** + * Add the result to the conversation context, and prompt to generate output without interrupting ongoing generation. + */ + FunctionResponseScheduling["WHEN_IDLE"] = "WHEN_IDLE"; + /** + * Add the result to the conversation context, interrupt ongoing generation and prompt to generate output. + */ + FunctionResponseScheduling["INTERRUPT"] = "INTERRUPT"; +})(FunctionResponseScheduling || (FunctionResponseScheduling = {})); +/** The type of the data. */ +var Type; +(function (Type) { + /** + * Not specified, should not be used. + */ + Type["TYPE_UNSPECIFIED"] = "TYPE_UNSPECIFIED"; + /** + * OpenAPI string type + */ + Type["STRING"] = "STRING"; + /** + * OpenAPI number type + */ + Type["NUMBER"] = "NUMBER"; + /** + * OpenAPI integer type + */ + Type["INTEGER"] = "INTEGER"; + /** + * OpenAPI boolean type + */ + Type["BOOLEAN"] = "BOOLEAN"; + /** + * OpenAPI array type + */ + Type["ARRAY"] = "ARRAY"; + /** + * OpenAPI object type + */ + Type["OBJECT"] = "OBJECT"; + /** + * Null type + */ + Type["NULL"] = "NULL"; +})(Type || (Type = {})); +/** The API spec that the external API implements. This enum is not supported in Gemini API. */ +var ApiSpec; +(function (ApiSpec) { + /** + * Unspecified API spec. This value should not be used. + */ + ApiSpec["API_SPEC_UNSPECIFIED"] = "API_SPEC_UNSPECIFIED"; + /** + * Simple search API spec. + */ + ApiSpec["SIMPLE_SEARCH"] = "SIMPLE_SEARCH"; + /** + * Elastic search API spec. + */ + ApiSpec["ELASTIC_SEARCH"] = "ELASTIC_SEARCH"; +})(ApiSpec || (ApiSpec = {})); +/** Type of auth scheme. This enum is not supported in Gemini API. */ +var AuthType; +(function (AuthType) { + AuthType["AUTH_TYPE_UNSPECIFIED"] = "AUTH_TYPE_UNSPECIFIED"; + /** + * No Auth. + */ + AuthType["NO_AUTH"] = "NO_AUTH"; + /** + * API Key Auth. + */ + AuthType["API_KEY_AUTH"] = "API_KEY_AUTH"; + /** + * HTTP Basic Auth. + */ + AuthType["HTTP_BASIC_AUTH"] = "HTTP_BASIC_AUTH"; + /** + * Google Service Account Auth. + */ + AuthType["GOOGLE_SERVICE_ACCOUNT_AUTH"] = "GOOGLE_SERVICE_ACCOUNT_AUTH"; + /** + * OAuth auth. + */ + AuthType["OAUTH"] = "OAUTH"; + /** + * OpenID Connect (OIDC) Auth. + */ + AuthType["OIDC_AUTH"] = "OIDC_AUTH"; +})(AuthType || (AuthType = {})); +/** The location of the API key. This enum is not supported in Gemini API. */ +var HttpElementLocation; +(function (HttpElementLocation) { + HttpElementLocation["HTTP_IN_UNSPECIFIED"] = "HTTP_IN_UNSPECIFIED"; + /** + * Element is in the HTTP request query. + */ + HttpElementLocation["HTTP_IN_QUERY"] = "HTTP_IN_QUERY"; + /** + * Element is in the HTTP request header. + */ + HttpElementLocation["HTTP_IN_HEADER"] = "HTTP_IN_HEADER"; + /** + * Element is in the HTTP request path. + */ + HttpElementLocation["HTTP_IN_PATH"] = "HTTP_IN_PATH"; + /** + * Element is in the HTTP request body. + */ + HttpElementLocation["HTTP_IN_BODY"] = "HTTP_IN_BODY"; + /** + * Element is in the HTTP request cookie. + */ + HttpElementLocation["HTTP_IN_COOKIE"] = "HTTP_IN_COOKIE"; +})(HttpElementLocation || (HttpElementLocation = {})); +/** Sites with confidence level chosen & above this value will be blocked from the search results. This enum is not supported in Gemini API. */ +var PhishBlockThreshold; +(function (PhishBlockThreshold) { + /** + * Defaults to unspecified. + */ + PhishBlockThreshold["PHISH_BLOCK_THRESHOLD_UNSPECIFIED"] = "PHISH_BLOCK_THRESHOLD_UNSPECIFIED"; + /** + * Blocks Low and above confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_LOW_AND_ABOVE"] = "BLOCK_LOW_AND_ABOVE"; + /** + * Blocks Medium and above confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_MEDIUM_AND_ABOVE"] = "BLOCK_MEDIUM_AND_ABOVE"; + /** + * Blocks High and above confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_HIGH_AND_ABOVE"] = "BLOCK_HIGH_AND_ABOVE"; + /** + * Blocks Higher and above confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_HIGHER_AND_ABOVE"] = "BLOCK_HIGHER_AND_ABOVE"; + /** + * Blocks Very high and above confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_VERY_HIGH_AND_ABOVE"] = "BLOCK_VERY_HIGH_AND_ABOVE"; + /** + * Blocks Extremely high confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_ONLY_EXTREMELY_HIGH"] = "BLOCK_ONLY_EXTREMELY_HIGH"; +})(PhishBlockThreshold || (PhishBlockThreshold = {})); +/** Specifies the function Behavior. Currently only supported by the BidiGenerateContent method. This enum is not supported in Vertex AI. */ +var Behavior; +(function (Behavior) { + /** + * This value is unused. + */ + Behavior["UNSPECIFIED"] = "UNSPECIFIED"; + /** + * If set, the system will wait to receive the function response before continuing the conversation. + */ + Behavior["BLOCKING"] = "BLOCKING"; + /** + * If set, the system will not wait to receive the function response. Instead, it will attempt to handle function responses as they become available while maintaining the conversation between the user and the model. + */ + Behavior["NON_BLOCKING"] = "NON_BLOCKING"; +})(Behavior || (Behavior = {})); +/** The mode of the predictor to be used in dynamic retrieval. */ +var DynamicRetrievalConfigMode; +(function (DynamicRetrievalConfigMode) { + /** + * Always trigger retrieval. + */ + DynamicRetrievalConfigMode["MODE_UNSPECIFIED"] = "MODE_UNSPECIFIED"; + /** + * Run retrieval only when system decides it is necessary. + */ + DynamicRetrievalConfigMode["MODE_DYNAMIC"] = "MODE_DYNAMIC"; +})(DynamicRetrievalConfigMode || (DynamicRetrievalConfigMode = {})); +/** Function calling mode. */ +var FunctionCallingConfigMode; +(function (FunctionCallingConfigMode) { + /** + * Unspecified function calling mode. This value should not be used. + */ + FunctionCallingConfigMode["MODE_UNSPECIFIED"] = "MODE_UNSPECIFIED"; + /** + * Default model behavior, model decides to predict either function calls or natural language response. + */ + FunctionCallingConfigMode["AUTO"] = "AUTO"; + /** + * Model is constrained to always predicting function calls only. If "allowed_function_names" are set, the predicted function calls will be limited to any one of "allowed_function_names", else the predicted function calls will be any one of the provided "function_declarations". + */ + FunctionCallingConfigMode["ANY"] = "ANY"; + /** + * Model will not predict any function calls. Model behavior is same as when not passing any function declarations. + */ + FunctionCallingConfigMode["NONE"] = "NONE"; + /** + * Model is constrained to predict either function calls or natural language response. If "allowed_function_names" are set, the predicted function calls will be limited to any one of "allowed_function_names", else the predicted function calls will be any one of the provided "function_declarations". + */ + FunctionCallingConfigMode["VALIDATED"] = "VALIDATED"; +})(FunctionCallingConfigMode || (FunctionCallingConfigMode = {})); +/** The number of thoughts tokens that the model should generate. */ +var ThinkingLevel; +(function (ThinkingLevel) { + /** + * Unspecified thinking level. + */ + ThinkingLevel["THINKING_LEVEL_UNSPECIFIED"] = "THINKING_LEVEL_UNSPECIFIED"; + /** + * Low thinking level. + */ + ThinkingLevel["LOW"] = "LOW"; + /** + * Medium thinking level. + */ + ThinkingLevel["MEDIUM"] = "MEDIUM"; + /** + * High thinking level. + */ + ThinkingLevel["HIGH"] = "HIGH"; + /** + * MINIMAL thinking level. + */ + ThinkingLevel["MINIMAL"] = "MINIMAL"; +})(ThinkingLevel || (ThinkingLevel = {})); +/** Harm category. */ +var HarmCategory; +(function (HarmCategory) { + /** + * The harm category is unspecified. + */ + HarmCategory["HARM_CATEGORY_UNSPECIFIED"] = "HARM_CATEGORY_UNSPECIFIED"; + /** + * The harm category is harassment. + */ + HarmCategory["HARM_CATEGORY_HARASSMENT"] = "HARM_CATEGORY_HARASSMENT"; + /** + * The harm category is hate speech. + */ + HarmCategory["HARM_CATEGORY_HATE_SPEECH"] = "HARM_CATEGORY_HATE_SPEECH"; + /** + * The harm category is sexually explicit content. + */ + HarmCategory["HARM_CATEGORY_SEXUALLY_EXPLICIT"] = "HARM_CATEGORY_SEXUALLY_EXPLICIT"; + /** + * The harm category is dangerous content. + */ + HarmCategory["HARM_CATEGORY_DANGEROUS_CONTENT"] = "HARM_CATEGORY_DANGEROUS_CONTENT"; + /** + * Deprecated: Election filter is not longer supported. The harm category is civic integrity. + */ + HarmCategory["HARM_CATEGORY_CIVIC_INTEGRITY"] = "HARM_CATEGORY_CIVIC_INTEGRITY"; + /** + * The harm category is image hate. This enum value is not supported in Gemini API. + */ + HarmCategory["HARM_CATEGORY_IMAGE_HATE"] = "HARM_CATEGORY_IMAGE_HATE"; + /** + * The harm category is image dangerous content. This enum value is not supported in Gemini API. + */ + HarmCategory["HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT"] = "HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT"; + /** + * The harm category is image harassment. This enum value is not supported in Gemini API. + */ + HarmCategory["HARM_CATEGORY_IMAGE_HARASSMENT"] = "HARM_CATEGORY_IMAGE_HARASSMENT"; + /** + * The harm category is image sexually explicit content. This enum value is not supported in Gemini API. + */ + HarmCategory["HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT"] = "HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT"; + /** + * The harm category is for jailbreak prompts. This enum value is not supported in Gemini API. + */ + HarmCategory["HARM_CATEGORY_JAILBREAK"] = "HARM_CATEGORY_JAILBREAK"; +})(HarmCategory || (HarmCategory = {})); +/** Specify if the threshold is used for probability or severity score. If not specified, the threshold is used for probability score. This enum is not supported in Gemini API. */ +var HarmBlockMethod; +(function (HarmBlockMethod) { + /** + * The harm block method is unspecified. + */ + HarmBlockMethod["HARM_BLOCK_METHOD_UNSPECIFIED"] = "HARM_BLOCK_METHOD_UNSPECIFIED"; + /** + * The harm block method uses both probability and severity scores. + */ + HarmBlockMethod["SEVERITY"] = "SEVERITY"; + /** + * The harm block method uses the probability score. + */ + HarmBlockMethod["PROBABILITY"] = "PROBABILITY"; +})(HarmBlockMethod || (HarmBlockMethod = {})); +/** The harm block threshold. */ +var HarmBlockThreshold; +(function (HarmBlockThreshold) { + /** + * Unspecified harm block threshold. + */ + HarmBlockThreshold["HARM_BLOCK_THRESHOLD_UNSPECIFIED"] = "HARM_BLOCK_THRESHOLD_UNSPECIFIED"; + /** + * Block low threshold and above (i.e. block more). + */ + HarmBlockThreshold["BLOCK_LOW_AND_ABOVE"] = "BLOCK_LOW_AND_ABOVE"; + /** + * Block medium threshold and above. + */ + HarmBlockThreshold["BLOCK_MEDIUM_AND_ABOVE"] = "BLOCK_MEDIUM_AND_ABOVE"; + /** + * Block only high threshold (i.e. block less). + */ + HarmBlockThreshold["BLOCK_ONLY_HIGH"] = "BLOCK_ONLY_HIGH"; + /** + * Block none. + */ + HarmBlockThreshold["BLOCK_NONE"] = "BLOCK_NONE"; + /** + * Turn off the safety filter. + */ + HarmBlockThreshold["OFF"] = "OFF"; +})(HarmBlockThreshold || (HarmBlockThreshold = {})); +/** Output only. The reason why the model stopped generating tokens. + +If empty, the model has not stopped generating the tokens. */ +var FinishReason; +(function (FinishReason) { + /** + * The finish reason is unspecified. + */ + FinishReason["FINISH_REASON_UNSPECIFIED"] = "FINISH_REASON_UNSPECIFIED"; + /** + * Token generation reached a natural stopping point or a configured stop sequence. + */ + FinishReason["STOP"] = "STOP"; + /** + * Token generation reached the configured maximum output tokens. + */ + FinishReason["MAX_TOKENS"] = "MAX_TOKENS"; + /** + * Token generation stopped because the content potentially contains safety violations. NOTE: When streaming, [content][] is empty if content filters blocks the output. + */ + FinishReason["SAFETY"] = "SAFETY"; + /** + * The token generation stopped because of potential recitation. + */ + FinishReason["RECITATION"] = "RECITATION"; + /** + * The token generation stopped because of using an unsupported language. + */ + FinishReason["LANGUAGE"] = "LANGUAGE"; + /** + * All other reasons that stopped the token generation. + */ + FinishReason["OTHER"] = "OTHER"; + /** + * Token generation stopped because the content contains forbidden terms. + */ + FinishReason["BLOCKLIST"] = "BLOCKLIST"; + /** + * Token generation stopped for potentially containing prohibited content. + */ + FinishReason["PROHIBITED_CONTENT"] = "PROHIBITED_CONTENT"; + /** + * Token generation stopped because the content potentially contains Sensitive Personally Identifiable Information (SPII). + */ + FinishReason["SPII"] = "SPII"; + /** + * The function call generated by the model is invalid. + */ + FinishReason["MALFORMED_FUNCTION_CALL"] = "MALFORMED_FUNCTION_CALL"; + /** + * Token generation stopped because generated images have safety violations. + */ + FinishReason["IMAGE_SAFETY"] = "IMAGE_SAFETY"; + /** + * The tool call generated by the model is invalid. + */ + FinishReason["UNEXPECTED_TOOL_CALL"] = "UNEXPECTED_TOOL_CALL"; + /** + * Image generation stopped because the generated images have prohibited content. + */ + FinishReason["IMAGE_PROHIBITED_CONTENT"] = "IMAGE_PROHIBITED_CONTENT"; + /** + * The model was expected to generate an image, but none was generated. + */ + FinishReason["NO_IMAGE"] = "NO_IMAGE"; + /** + * Image generation stopped because the generated image may be a recitation from a source. + */ + FinishReason["IMAGE_RECITATION"] = "IMAGE_RECITATION"; + /** + * Image generation stopped for a reason not otherwise specified. + */ + FinishReason["IMAGE_OTHER"] = "IMAGE_OTHER"; +})(FinishReason || (FinishReason = {})); +/** Output only. Harm probability levels in the content. */ +var HarmProbability; +(function (HarmProbability) { + /** + * Harm probability unspecified. + */ + HarmProbability["HARM_PROBABILITY_UNSPECIFIED"] = "HARM_PROBABILITY_UNSPECIFIED"; + /** + * Negligible level of harm. + */ + HarmProbability["NEGLIGIBLE"] = "NEGLIGIBLE"; + /** + * Low level of harm. + */ + HarmProbability["LOW"] = "LOW"; + /** + * Medium level of harm. + */ + HarmProbability["MEDIUM"] = "MEDIUM"; + /** + * High level of harm. + */ + HarmProbability["HIGH"] = "HIGH"; +})(HarmProbability || (HarmProbability = {})); +/** Output only. Harm severity levels in the content. This enum is not supported in Gemini API. */ +var HarmSeverity; +(function (HarmSeverity) { + /** + * Harm severity unspecified. + */ + HarmSeverity["HARM_SEVERITY_UNSPECIFIED"] = "HARM_SEVERITY_UNSPECIFIED"; + /** + * Negligible level of harm severity. + */ + HarmSeverity["HARM_SEVERITY_NEGLIGIBLE"] = "HARM_SEVERITY_NEGLIGIBLE"; + /** + * Low level of harm severity. + */ + HarmSeverity["HARM_SEVERITY_LOW"] = "HARM_SEVERITY_LOW"; + /** + * Medium level of harm severity. + */ + HarmSeverity["HARM_SEVERITY_MEDIUM"] = "HARM_SEVERITY_MEDIUM"; + /** + * High level of harm severity. + */ + HarmSeverity["HARM_SEVERITY_HIGH"] = "HARM_SEVERITY_HIGH"; +})(HarmSeverity || (HarmSeverity = {})); +/** Status of the url retrieval. */ +var UrlRetrievalStatus; +(function (UrlRetrievalStatus) { + /** + * Default value. This value is unused. + */ + UrlRetrievalStatus["URL_RETRIEVAL_STATUS_UNSPECIFIED"] = "URL_RETRIEVAL_STATUS_UNSPECIFIED"; + /** + * Url retrieval is successful. + */ + UrlRetrievalStatus["URL_RETRIEVAL_STATUS_SUCCESS"] = "URL_RETRIEVAL_STATUS_SUCCESS"; + /** + * Url retrieval is failed due to error. + */ + UrlRetrievalStatus["URL_RETRIEVAL_STATUS_ERROR"] = "URL_RETRIEVAL_STATUS_ERROR"; + /** + * Url retrieval is failed because the content is behind paywall. This enum value is not supported in Vertex AI. + */ + UrlRetrievalStatus["URL_RETRIEVAL_STATUS_PAYWALL"] = "URL_RETRIEVAL_STATUS_PAYWALL"; + /** + * Url retrieval is failed because the content is unsafe. This enum value is not supported in Vertex AI. + */ + UrlRetrievalStatus["URL_RETRIEVAL_STATUS_UNSAFE"] = "URL_RETRIEVAL_STATUS_UNSAFE"; +})(UrlRetrievalStatus || (UrlRetrievalStatus = {})); +/** Output only. The reason why the prompt was blocked. */ +var BlockedReason; +(function (BlockedReason) { + /** + * The blocked reason is unspecified. + */ + BlockedReason["BLOCKED_REASON_UNSPECIFIED"] = "BLOCKED_REASON_UNSPECIFIED"; + /** + * The prompt was blocked for safety reasons. + */ + BlockedReason["SAFETY"] = "SAFETY"; + /** + * The prompt was blocked for other reasons. For example, it may be due to the prompt's language, or because it contains other harmful content. + */ + BlockedReason["OTHER"] = "OTHER"; + /** + * The prompt was blocked because it contains a term from the terminology blocklist. + */ + BlockedReason["BLOCKLIST"] = "BLOCKLIST"; + /** + * The prompt was blocked because it contains prohibited content. + */ + BlockedReason["PROHIBITED_CONTENT"] = "PROHIBITED_CONTENT"; + /** + * The prompt was blocked because it contains content that is unsafe for image generation. + */ + BlockedReason["IMAGE_SAFETY"] = "IMAGE_SAFETY"; + /** + * The prompt was blocked by Model Armor. This enum value is not supported in Gemini API. + */ + BlockedReason["MODEL_ARMOR"] = "MODEL_ARMOR"; + /** + * The prompt was blocked as a jailbreak attempt. This enum value is not supported in Gemini API. + */ + BlockedReason["JAILBREAK"] = "JAILBREAK"; +})(BlockedReason || (BlockedReason = {})); +/** Output only. The traffic type for this request. This enum is not supported in Gemini API. */ +var TrafficType; +(function (TrafficType) { + /** + * Unspecified request traffic type. + */ + TrafficType["TRAFFIC_TYPE_UNSPECIFIED"] = "TRAFFIC_TYPE_UNSPECIFIED"; + /** + * The request was processed using Pay-As-You-Go quota. + */ + TrafficType["ON_DEMAND"] = "ON_DEMAND"; + /** + * Type for Provisioned Throughput traffic. + */ + TrafficType["PROVISIONED_THROUGHPUT"] = "PROVISIONED_THROUGHPUT"; +})(TrafficType || (TrafficType = {})); +/** Server content modalities. */ +var Modality; +(function (Modality) { + /** + * The modality is unspecified. + */ + Modality["MODALITY_UNSPECIFIED"] = "MODALITY_UNSPECIFIED"; + /** + * Indicates the model should return text + */ + Modality["TEXT"] = "TEXT"; + /** + * Indicates the model should return images. + */ + Modality["IMAGE"] = "IMAGE"; + /** + * Indicates the model should return audio. + */ + Modality["AUDIO"] = "AUDIO"; +})(Modality || (Modality = {})); +/** The media resolution to use. */ +var MediaResolution; +(function (MediaResolution) { + /** + * Media resolution has not been set + */ + MediaResolution["MEDIA_RESOLUTION_UNSPECIFIED"] = "MEDIA_RESOLUTION_UNSPECIFIED"; + /** + * Media resolution set to low (64 tokens). + */ + MediaResolution["MEDIA_RESOLUTION_LOW"] = "MEDIA_RESOLUTION_LOW"; + /** + * Media resolution set to medium (256 tokens). + */ + MediaResolution["MEDIA_RESOLUTION_MEDIUM"] = "MEDIA_RESOLUTION_MEDIUM"; + /** + * Media resolution set to high (zoomed reframing with 256 tokens). + */ + MediaResolution["MEDIA_RESOLUTION_HIGH"] = "MEDIA_RESOLUTION_HIGH"; +})(MediaResolution || (MediaResolution = {})); +/** Tuning mode. This enum is not supported in Gemini API. */ +var TuningMode; +(function (TuningMode) { + /** + * Tuning mode is unspecified. + */ + TuningMode["TUNING_MODE_UNSPECIFIED"] = "TUNING_MODE_UNSPECIFIED"; + /** + * Full fine-tuning mode. + */ + TuningMode["TUNING_MODE_FULL"] = "TUNING_MODE_FULL"; + /** + * PEFT adapter tuning mode. + */ + TuningMode["TUNING_MODE_PEFT_ADAPTER"] = "TUNING_MODE_PEFT_ADAPTER"; +})(TuningMode || (TuningMode = {})); +/** Adapter size for tuning. This enum is not supported in Gemini API. */ +var AdapterSize; +(function (AdapterSize) { + /** + * Adapter size is unspecified. + */ + AdapterSize["ADAPTER_SIZE_UNSPECIFIED"] = "ADAPTER_SIZE_UNSPECIFIED"; + /** + * Adapter size 1. + */ + AdapterSize["ADAPTER_SIZE_ONE"] = "ADAPTER_SIZE_ONE"; + /** + * Adapter size 2. + */ + AdapterSize["ADAPTER_SIZE_TWO"] = "ADAPTER_SIZE_TWO"; + /** + * Adapter size 4. + */ + AdapterSize["ADAPTER_SIZE_FOUR"] = "ADAPTER_SIZE_FOUR"; + /** + * Adapter size 8. + */ + AdapterSize["ADAPTER_SIZE_EIGHT"] = "ADAPTER_SIZE_EIGHT"; + /** + * Adapter size 16. + */ + AdapterSize["ADAPTER_SIZE_SIXTEEN"] = "ADAPTER_SIZE_SIXTEEN"; + /** + * Adapter size 32. + */ + AdapterSize["ADAPTER_SIZE_THIRTY_TWO"] = "ADAPTER_SIZE_THIRTY_TWO"; +})(AdapterSize || (AdapterSize = {})); +/** Job state. */ +var JobState; +(function (JobState) { + /** + * The job state is unspecified. + */ + JobState["JOB_STATE_UNSPECIFIED"] = "JOB_STATE_UNSPECIFIED"; + /** + * The job has been just created or resumed and processing has not yet begun. + */ + JobState["JOB_STATE_QUEUED"] = "JOB_STATE_QUEUED"; + /** + * The service is preparing to run the job. + */ + JobState["JOB_STATE_PENDING"] = "JOB_STATE_PENDING"; + /** + * The job is in progress. + */ + JobState["JOB_STATE_RUNNING"] = "JOB_STATE_RUNNING"; + /** + * The job completed successfully. + */ + JobState["JOB_STATE_SUCCEEDED"] = "JOB_STATE_SUCCEEDED"; + /** + * The job failed. + */ + JobState["JOB_STATE_FAILED"] = "JOB_STATE_FAILED"; + /** + * The job is being cancelled. From this state the job may only go to either `JOB_STATE_SUCCEEDED`, `JOB_STATE_FAILED` or `JOB_STATE_CANCELLED`. + */ + JobState["JOB_STATE_CANCELLING"] = "JOB_STATE_CANCELLING"; + /** + * The job has been cancelled. + */ + JobState["JOB_STATE_CANCELLED"] = "JOB_STATE_CANCELLED"; + /** + * The job has been stopped, and can be resumed. + */ + JobState["JOB_STATE_PAUSED"] = "JOB_STATE_PAUSED"; + /** + * The job has expired. + */ + JobState["JOB_STATE_EXPIRED"] = "JOB_STATE_EXPIRED"; + /** + * The job is being updated. Only jobs in the `JOB_STATE_RUNNING` state can be updated. After updating, the job goes back to the `JOB_STATE_RUNNING` state. + */ + JobState["JOB_STATE_UPDATING"] = "JOB_STATE_UPDATING"; + /** + * The job is partially succeeded, some results may be missing due to errors. + */ + JobState["JOB_STATE_PARTIALLY_SUCCEEDED"] = "JOB_STATE_PARTIALLY_SUCCEEDED"; +})(JobState || (JobState = {})); +/** The tuning task. Either I2V or T2V. This enum is not supported in Gemini API. */ +var TuningTask; +(function (TuningTask) { + /** + * Default value. This value is unused. + */ + TuningTask["TUNING_TASK_UNSPECIFIED"] = "TUNING_TASK_UNSPECIFIED"; + /** + * Tuning task for image to video. + */ + TuningTask["TUNING_TASK_I2V"] = "TUNING_TASK_I2V"; + /** + * Tuning task for text to video. + */ + TuningTask["TUNING_TASK_T2V"] = "TUNING_TASK_T2V"; + /** + * Tuning task for reference to video. + */ + TuningTask["TUNING_TASK_R2V"] = "TUNING_TASK_R2V"; +})(TuningTask || (TuningTask = {})); +/** The tokenization quality used for given media. */ +var PartMediaResolutionLevel; +(function (PartMediaResolutionLevel) { + /** + * Media resolution has not been set. + */ + PartMediaResolutionLevel["MEDIA_RESOLUTION_UNSPECIFIED"] = "MEDIA_RESOLUTION_UNSPECIFIED"; + /** + * Media resolution set to low. + */ + PartMediaResolutionLevel["MEDIA_RESOLUTION_LOW"] = "MEDIA_RESOLUTION_LOW"; + /** + * Media resolution set to medium. + */ + PartMediaResolutionLevel["MEDIA_RESOLUTION_MEDIUM"] = "MEDIA_RESOLUTION_MEDIUM"; + /** + * Media resolution set to high. + */ + PartMediaResolutionLevel["MEDIA_RESOLUTION_HIGH"] = "MEDIA_RESOLUTION_HIGH"; + /** + * Media resolution set to ultra high. + */ + PartMediaResolutionLevel["MEDIA_RESOLUTION_ULTRA_HIGH"] = "MEDIA_RESOLUTION_ULTRA_HIGH"; +})(PartMediaResolutionLevel || (PartMediaResolutionLevel = {})); +/** Resource scope. */ +var ResourceScope; +(function (ResourceScope) { + /** + * When setting base_url, this value configures resource scope to be the collection. + The resource name will not include api version, project, or location. + For example, if base_url is set to "https://aiplatform.googleapis.com", + then the resource name for a Model would be + "https://aiplatform.googleapis.com/publishers/google/models/gemini-3-pro-preview + */ + ResourceScope["COLLECTION"] = "COLLECTION"; +})(ResourceScope || (ResourceScope = {})); +/** Options for feature selection preference. */ +var FeatureSelectionPreference; +(function (FeatureSelectionPreference) { + FeatureSelectionPreference["FEATURE_SELECTION_PREFERENCE_UNSPECIFIED"] = "FEATURE_SELECTION_PREFERENCE_UNSPECIFIED"; + FeatureSelectionPreference["PRIORITIZE_QUALITY"] = "PRIORITIZE_QUALITY"; + FeatureSelectionPreference["BALANCED"] = "BALANCED"; + FeatureSelectionPreference["PRIORITIZE_COST"] = "PRIORITIZE_COST"; +})(FeatureSelectionPreference || (FeatureSelectionPreference = {})); +/** The environment being operated. */ +var Environment; +(function (Environment) { + /** + * Defaults to browser. + */ + Environment["ENVIRONMENT_UNSPECIFIED"] = "ENVIRONMENT_UNSPECIFIED"; + /** + * Operates in a web browser. + */ + Environment["ENVIRONMENT_BROWSER"] = "ENVIRONMENT_BROWSER"; +})(Environment || (Environment = {})); +/** Enum that controls the safety filter level for objectionable content. */ +var SafetyFilterLevel; +(function (SafetyFilterLevel) { + SafetyFilterLevel["BLOCK_LOW_AND_ABOVE"] = "BLOCK_LOW_AND_ABOVE"; + SafetyFilterLevel["BLOCK_MEDIUM_AND_ABOVE"] = "BLOCK_MEDIUM_AND_ABOVE"; + SafetyFilterLevel["BLOCK_ONLY_HIGH"] = "BLOCK_ONLY_HIGH"; + SafetyFilterLevel["BLOCK_NONE"] = "BLOCK_NONE"; +})(SafetyFilterLevel || (SafetyFilterLevel = {})); +/** Enum that controls the generation of people. */ +var PersonGeneration; +(function (PersonGeneration) { + /** + * Block generation of images of people. + */ + PersonGeneration["DONT_ALLOW"] = "DONT_ALLOW"; + /** + * Generate images of adults, but not children. + */ + PersonGeneration["ALLOW_ADULT"] = "ALLOW_ADULT"; + /** + * Generate images that include adults and children. + */ + PersonGeneration["ALLOW_ALL"] = "ALLOW_ALL"; +})(PersonGeneration || (PersonGeneration = {})); +/** Enum that specifies the language of the text in the prompt. */ +var ImagePromptLanguage; +(function (ImagePromptLanguage) { + /** + * Auto-detect the language. + */ + ImagePromptLanguage["auto"] = "auto"; + /** + * English + */ + ImagePromptLanguage["en"] = "en"; + /** + * Japanese + */ + ImagePromptLanguage["ja"] = "ja"; + /** + * Korean + */ + ImagePromptLanguage["ko"] = "ko"; + /** + * Hindi + */ + ImagePromptLanguage["hi"] = "hi"; + /** + * Chinese + */ + ImagePromptLanguage["zh"] = "zh"; + /** + * Portuguese + */ + ImagePromptLanguage["pt"] = "pt"; + /** + * Spanish + */ + ImagePromptLanguage["es"] = "es"; +})(ImagePromptLanguage || (ImagePromptLanguage = {})); +/** Enum representing the mask mode of a mask reference image. */ +var MaskReferenceMode; +(function (MaskReferenceMode) { + MaskReferenceMode["MASK_MODE_DEFAULT"] = "MASK_MODE_DEFAULT"; + MaskReferenceMode["MASK_MODE_USER_PROVIDED"] = "MASK_MODE_USER_PROVIDED"; + MaskReferenceMode["MASK_MODE_BACKGROUND"] = "MASK_MODE_BACKGROUND"; + MaskReferenceMode["MASK_MODE_FOREGROUND"] = "MASK_MODE_FOREGROUND"; + MaskReferenceMode["MASK_MODE_SEMANTIC"] = "MASK_MODE_SEMANTIC"; +})(MaskReferenceMode || (MaskReferenceMode = {})); +/** Enum representing the control type of a control reference image. */ +var ControlReferenceType; +(function (ControlReferenceType) { + ControlReferenceType["CONTROL_TYPE_DEFAULT"] = "CONTROL_TYPE_DEFAULT"; + ControlReferenceType["CONTROL_TYPE_CANNY"] = "CONTROL_TYPE_CANNY"; + ControlReferenceType["CONTROL_TYPE_SCRIBBLE"] = "CONTROL_TYPE_SCRIBBLE"; + ControlReferenceType["CONTROL_TYPE_FACE_MESH"] = "CONTROL_TYPE_FACE_MESH"; +})(ControlReferenceType || (ControlReferenceType = {})); +/** Enum representing the subject type of a subject reference image. */ +var SubjectReferenceType; +(function (SubjectReferenceType) { + SubjectReferenceType["SUBJECT_TYPE_DEFAULT"] = "SUBJECT_TYPE_DEFAULT"; + SubjectReferenceType["SUBJECT_TYPE_PERSON"] = "SUBJECT_TYPE_PERSON"; + SubjectReferenceType["SUBJECT_TYPE_ANIMAL"] = "SUBJECT_TYPE_ANIMAL"; + SubjectReferenceType["SUBJECT_TYPE_PRODUCT"] = "SUBJECT_TYPE_PRODUCT"; +})(SubjectReferenceType || (SubjectReferenceType = {})); +/** Enum representing the editing mode. */ +var EditMode; +(function (EditMode) { + EditMode["EDIT_MODE_DEFAULT"] = "EDIT_MODE_DEFAULT"; + EditMode["EDIT_MODE_INPAINT_REMOVAL"] = "EDIT_MODE_INPAINT_REMOVAL"; + EditMode["EDIT_MODE_INPAINT_INSERTION"] = "EDIT_MODE_INPAINT_INSERTION"; + EditMode["EDIT_MODE_OUTPAINT"] = "EDIT_MODE_OUTPAINT"; + EditMode["EDIT_MODE_CONTROLLED_EDITING"] = "EDIT_MODE_CONTROLLED_EDITING"; + EditMode["EDIT_MODE_STYLE"] = "EDIT_MODE_STYLE"; + EditMode["EDIT_MODE_BGSWAP"] = "EDIT_MODE_BGSWAP"; + EditMode["EDIT_MODE_PRODUCT_IMAGE"] = "EDIT_MODE_PRODUCT_IMAGE"; +})(EditMode || (EditMode = {})); +/** Enum that represents the segmentation mode. */ +var SegmentMode; +(function (SegmentMode) { + SegmentMode["FOREGROUND"] = "FOREGROUND"; + SegmentMode["BACKGROUND"] = "BACKGROUND"; + SegmentMode["PROMPT"] = "PROMPT"; + SegmentMode["SEMANTIC"] = "SEMANTIC"; + SegmentMode["INTERACTIVE"] = "INTERACTIVE"; +})(SegmentMode || (SegmentMode = {})); +/** Enum for the reference type of a video generation reference image. */ +var VideoGenerationReferenceType; +(function (VideoGenerationReferenceType) { + /** + * A reference image that provides assets to the generated video, + such as the scene, an object, a character, etc. + */ + VideoGenerationReferenceType["ASSET"] = "ASSET"; + /** + * A reference image that provides aesthetics including colors, + lighting, texture, etc., to be used as the style of the generated video, + such as 'anime', 'photography', 'origami', etc. + */ + VideoGenerationReferenceType["STYLE"] = "STYLE"; +})(VideoGenerationReferenceType || (VideoGenerationReferenceType = {})); +/** Enum for the mask mode of a video generation mask. */ +var VideoGenerationMaskMode; +(function (VideoGenerationMaskMode) { + /** + * The image mask contains a masked rectangular region which is + applied on the first frame of the input video. The object described in + the prompt is inserted into this region and will appear in subsequent + frames. + */ + VideoGenerationMaskMode["INSERT"] = "INSERT"; + /** + * The image mask is used to determine an object in the + first video frame to track. This object is removed from the video. + */ + VideoGenerationMaskMode["REMOVE"] = "REMOVE"; + /** + * The image mask is used to determine a region in the + video. Objects in this region will be removed. + */ + VideoGenerationMaskMode["REMOVE_STATIC"] = "REMOVE_STATIC"; + /** + * The image mask contains a masked rectangular region where + the input video will go. The remaining area will be generated. Video + masks are not supported. + */ + VideoGenerationMaskMode["OUTPAINT"] = "OUTPAINT"; +})(VideoGenerationMaskMode || (VideoGenerationMaskMode = {})); +/** Enum that controls the compression quality of the generated videos. */ +var VideoCompressionQuality; +(function (VideoCompressionQuality) { + /** + * Optimized video compression quality. This will produce videos + with a compressed, smaller file size. + */ + VideoCompressionQuality["OPTIMIZED"] = "OPTIMIZED"; + /** + * Lossless video compression quality. This will produce videos + with a larger file size. + */ + VideoCompressionQuality["LOSSLESS"] = "LOSSLESS"; +})(VideoCompressionQuality || (VideoCompressionQuality = {})); +/** Enum representing the tuning method. */ +var TuningMethod; +(function (TuningMethod) { + /** + * Supervised fine tuning. + */ + TuningMethod["SUPERVISED_FINE_TUNING"] = "SUPERVISED_FINE_TUNING"; + /** + * Preference optimization tuning. + */ + TuningMethod["PREFERENCE_TUNING"] = "PREFERENCE_TUNING"; + /** + * Distillation tuning. + */ + TuningMethod["DISTILLATION"] = "DISTILLATION"; +})(TuningMethod || (TuningMethod = {})); +/** State for the lifecycle of a Document. */ +var DocumentState; +(function (DocumentState) { + DocumentState["STATE_UNSPECIFIED"] = "STATE_UNSPECIFIED"; + DocumentState["STATE_PENDING"] = "STATE_PENDING"; + DocumentState["STATE_ACTIVE"] = "STATE_ACTIVE"; + DocumentState["STATE_FAILED"] = "STATE_FAILED"; +})(DocumentState || (DocumentState = {})); +/** State for the lifecycle of a File. */ +var FileState; +(function (FileState) { + FileState["STATE_UNSPECIFIED"] = "STATE_UNSPECIFIED"; + FileState["PROCESSING"] = "PROCESSING"; + FileState["ACTIVE"] = "ACTIVE"; + FileState["FAILED"] = "FAILED"; +})(FileState || (FileState = {})); +/** Source of the File. */ +var FileSource; +(function (FileSource) { + FileSource["SOURCE_UNSPECIFIED"] = "SOURCE_UNSPECIFIED"; + FileSource["UPLOADED"] = "UPLOADED"; + FileSource["GENERATED"] = "GENERATED"; + FileSource["REGISTERED"] = "REGISTERED"; +})(FileSource || (FileSource = {})); +/** The reason why the turn is complete. */ +var TurnCompleteReason; +(function (TurnCompleteReason) { + /** + * Default value. Reason is unspecified. + */ + TurnCompleteReason["TURN_COMPLETE_REASON_UNSPECIFIED"] = "TURN_COMPLETE_REASON_UNSPECIFIED"; + /** + * The function call generated by the model is invalid. + */ + TurnCompleteReason["MALFORMED_FUNCTION_CALL"] = "MALFORMED_FUNCTION_CALL"; + /** + * The response is rejected by the model. + */ + TurnCompleteReason["RESPONSE_REJECTED"] = "RESPONSE_REJECTED"; + /** + * Needs more input from the user. + */ + TurnCompleteReason["NEED_MORE_INPUT"] = "NEED_MORE_INPUT"; +})(TurnCompleteReason || (TurnCompleteReason = {})); +/** Server content modalities. */ +var MediaModality; +(function (MediaModality) { + /** + * The modality is unspecified. + */ + MediaModality["MODALITY_UNSPECIFIED"] = "MODALITY_UNSPECIFIED"; + /** + * Plain text. + */ + MediaModality["TEXT"] = "TEXT"; + /** + * Images. + */ + MediaModality["IMAGE"] = "IMAGE"; + /** + * Video. + */ + MediaModality["VIDEO"] = "VIDEO"; + /** + * Audio. + */ + MediaModality["AUDIO"] = "AUDIO"; + /** + * Document, e.g. PDF. + */ + MediaModality["DOCUMENT"] = "DOCUMENT"; +})(MediaModality || (MediaModality = {})); +/** The type of the VAD signal. */ +var VadSignalType; +(function (VadSignalType) { + /** + * The default is VAD_SIGNAL_TYPE_UNSPECIFIED. + */ + VadSignalType["VAD_SIGNAL_TYPE_UNSPECIFIED"] = "VAD_SIGNAL_TYPE_UNSPECIFIED"; + /** + * Start of sentence signal. + */ + VadSignalType["VAD_SIGNAL_TYPE_SOS"] = "VAD_SIGNAL_TYPE_SOS"; + /** + * End of sentence signal. + */ + VadSignalType["VAD_SIGNAL_TYPE_EOS"] = "VAD_SIGNAL_TYPE_EOS"; +})(VadSignalType || (VadSignalType = {})); +/** The type of the voice activity signal. */ +var VoiceActivityType; +(function (VoiceActivityType) { + /** + * The default is VOICE_ACTIVITY_TYPE_UNSPECIFIED. + */ + VoiceActivityType["TYPE_UNSPECIFIED"] = "TYPE_UNSPECIFIED"; + /** + * Start of sentence signal. + */ + VoiceActivityType["ACTIVITY_START"] = "ACTIVITY_START"; + /** + * End of sentence signal. + */ + VoiceActivityType["ACTIVITY_END"] = "ACTIVITY_END"; +})(VoiceActivityType || (VoiceActivityType = {})); +/** Start of speech sensitivity. */ +var StartSensitivity; +(function (StartSensitivity) { + /** + * The default is START_SENSITIVITY_LOW. + */ + StartSensitivity["START_SENSITIVITY_UNSPECIFIED"] = "START_SENSITIVITY_UNSPECIFIED"; + /** + * Automatic detection will detect the start of speech more often. + */ + StartSensitivity["START_SENSITIVITY_HIGH"] = "START_SENSITIVITY_HIGH"; + /** + * Automatic detection will detect the start of speech less often. + */ + StartSensitivity["START_SENSITIVITY_LOW"] = "START_SENSITIVITY_LOW"; +})(StartSensitivity || (StartSensitivity = {})); +/** End of speech sensitivity. */ +var EndSensitivity; +(function (EndSensitivity) { + /** + * The default is END_SENSITIVITY_LOW. + */ + EndSensitivity["END_SENSITIVITY_UNSPECIFIED"] = "END_SENSITIVITY_UNSPECIFIED"; + /** + * Automatic detection ends speech more often. + */ + EndSensitivity["END_SENSITIVITY_HIGH"] = "END_SENSITIVITY_HIGH"; + /** + * Automatic detection ends speech less often. + */ + EndSensitivity["END_SENSITIVITY_LOW"] = "END_SENSITIVITY_LOW"; +})(EndSensitivity || (EndSensitivity = {})); +/** The different ways of handling user activity. */ +var ActivityHandling; +(function (ActivityHandling) { + /** + * If unspecified, the default behavior is `START_OF_ACTIVITY_INTERRUPTS`. + */ + ActivityHandling["ACTIVITY_HANDLING_UNSPECIFIED"] = "ACTIVITY_HANDLING_UNSPECIFIED"; + /** + * If true, start of activity will interrupt the model's response (also called "barge in"). The model's current response will be cut-off in the moment of the interruption. This is the default behavior. + */ + ActivityHandling["START_OF_ACTIVITY_INTERRUPTS"] = "START_OF_ACTIVITY_INTERRUPTS"; + /** + * The model's response will not be interrupted. + */ + ActivityHandling["NO_INTERRUPTION"] = "NO_INTERRUPTION"; +})(ActivityHandling || (ActivityHandling = {})); +/** Options about which input is included in the user's turn. */ +var TurnCoverage; +(function (TurnCoverage) { + /** + * If unspecified, the default behavior is `TURN_INCLUDES_ONLY_ACTIVITY`. + */ + TurnCoverage["TURN_COVERAGE_UNSPECIFIED"] = "TURN_COVERAGE_UNSPECIFIED"; + /** + * The users turn only includes activity since the last turn, excluding inactivity (e.g. silence on the audio stream). This is the default behavior. + */ + TurnCoverage["TURN_INCLUDES_ONLY_ACTIVITY"] = "TURN_INCLUDES_ONLY_ACTIVITY"; + /** + * The users turn includes all realtime input since the last turn, including inactivity (e.g. silence on the audio stream). + */ + TurnCoverage["TURN_INCLUDES_ALL_INPUT"] = "TURN_INCLUDES_ALL_INPUT"; +})(TurnCoverage || (TurnCoverage = {})); +/** Scale of the generated music. */ +var Scale; +(function (Scale) { + /** + * Default value. This value is unused. + */ + Scale["SCALE_UNSPECIFIED"] = "SCALE_UNSPECIFIED"; + /** + * C major or A minor. + */ + Scale["C_MAJOR_A_MINOR"] = "C_MAJOR_A_MINOR"; + /** + * Db major or Bb minor. + */ + Scale["D_FLAT_MAJOR_B_FLAT_MINOR"] = "D_FLAT_MAJOR_B_FLAT_MINOR"; + /** + * D major or B minor. + */ + Scale["D_MAJOR_B_MINOR"] = "D_MAJOR_B_MINOR"; + /** + * Eb major or C minor + */ + Scale["E_FLAT_MAJOR_C_MINOR"] = "E_FLAT_MAJOR_C_MINOR"; + /** + * E major or Db minor. + */ + Scale["E_MAJOR_D_FLAT_MINOR"] = "E_MAJOR_D_FLAT_MINOR"; + /** + * F major or D minor. + */ + Scale["F_MAJOR_D_MINOR"] = "F_MAJOR_D_MINOR"; + /** + * Gb major or Eb minor. + */ + Scale["G_FLAT_MAJOR_E_FLAT_MINOR"] = "G_FLAT_MAJOR_E_FLAT_MINOR"; + /** + * G major or E minor. + */ + Scale["G_MAJOR_E_MINOR"] = "G_MAJOR_E_MINOR"; + /** + * Ab major or F minor. + */ + Scale["A_FLAT_MAJOR_F_MINOR"] = "A_FLAT_MAJOR_F_MINOR"; + /** + * A major or Gb minor. + */ + Scale["A_MAJOR_G_FLAT_MINOR"] = "A_MAJOR_G_FLAT_MINOR"; + /** + * Bb major or G minor. + */ + Scale["B_FLAT_MAJOR_G_MINOR"] = "B_FLAT_MAJOR_G_MINOR"; + /** + * B major or Ab minor. + */ + Scale["B_MAJOR_A_FLAT_MINOR"] = "B_MAJOR_A_FLAT_MINOR"; +})(Scale || (Scale = {})); +/** The mode of music generation. */ +var MusicGenerationMode; +(function (MusicGenerationMode) { + /** + * Rely on the server default generation mode. + */ + MusicGenerationMode["MUSIC_GENERATION_MODE_UNSPECIFIED"] = "MUSIC_GENERATION_MODE_UNSPECIFIED"; + /** + * Steer text prompts to regions of latent space with higher quality + music. + */ + MusicGenerationMode["QUALITY"] = "QUALITY"; + /** + * Steer text prompts to regions of latent space with a larger + diversity of music. + */ + MusicGenerationMode["DIVERSITY"] = "DIVERSITY"; + /** + * Steer text prompts to regions of latent space more likely to + generate music with vocals. + */ + MusicGenerationMode["VOCALIZATION"] = "VOCALIZATION"; +})(MusicGenerationMode || (MusicGenerationMode = {})); +/** The playback control signal to apply to the music generation. */ +var LiveMusicPlaybackControl; +(function (LiveMusicPlaybackControl) { + /** + * This value is unused. + */ + LiveMusicPlaybackControl["PLAYBACK_CONTROL_UNSPECIFIED"] = "PLAYBACK_CONTROL_UNSPECIFIED"; + /** + * Start generating the music. + */ + LiveMusicPlaybackControl["PLAY"] = "PLAY"; + /** + * Hold the music generation. Use PLAY to resume from the current position. + */ + LiveMusicPlaybackControl["PAUSE"] = "PAUSE"; + /** + * Stop the music generation and reset the context (prompts retained). + Use PLAY to restart the music generation. + */ + LiveMusicPlaybackControl["STOP"] = "STOP"; + /** + * Reset the context of the music generation without stopping it. + Retains the current prompts and config. + */ + LiveMusicPlaybackControl["RESET_CONTEXT"] = "RESET_CONTEXT"; +})(LiveMusicPlaybackControl || (LiveMusicPlaybackControl = {})); + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function tPart(origin) { + if (origin === null || origin === undefined) { + throw new Error('PartUnion is required'); + } + if (typeof origin === 'object') { + return origin; + } + if (typeof origin === 'string') { + return { text: origin }; + } + throw new Error(`Unsupported part type: ${typeof origin}`); +} +function tParts(origin) { + if (origin === null || + origin === undefined || + (Array.isArray(origin) && origin.length === 0)) { + throw new Error('PartListUnion is required'); + } + if (Array.isArray(origin)) { + return origin.map((item) => tPart(item)); + } + return [tPart(origin)]; +} +function _isContent(origin) { + return (origin !== null && + origin !== undefined && + typeof origin === 'object' && + 'parts' in origin && + Array.isArray(origin.parts)); +} +function _isFunctionCallPart(origin) { + return (origin !== null && + origin !== undefined && + typeof origin === 'object' && + 'functionCall' in origin); +} +function _isFunctionResponsePart(origin) { + return (origin !== null && + origin !== undefined && + typeof origin === 'object' && + 'functionResponse' in origin); +} +function tContent(origin) { + if (origin === null || origin === undefined) { + throw new Error('ContentUnion is required'); + } + if (_isContent(origin)) { + // _isContent is a utility function that checks if the + // origin is a Content. + return origin; + } + return { + role: 'user', + parts: tParts(origin), + }; +} +function tContents(origin) { + if (origin === null || + origin === undefined || + (Array.isArray(origin) && origin.length === 0)) { + throw new Error('contents are required'); + } + if (!Array.isArray(origin)) { + // If it's not an array, it's a single content or a single PartUnion. + if (_isFunctionCallPart(origin) || _isFunctionResponsePart(origin)) { + throw new Error('To specify functionCall or functionResponse parts, please wrap them in a Content object, specifying the role for them'); + } + return [tContent(origin)]; + } + const result = []; + const accumulatedParts = []; + const isContentArray = _isContent(origin[0]); + for (const item of origin) { + const isContent = _isContent(item); + if (isContent != isContentArray) { + throw new Error('Mixing Content and Parts is not supported, please group the parts into a the appropriate Content objects and specify the roles for them'); + } + if (isContent) { + // `isContent` contains the result of _isContent, which is a utility + // function that checks if the item is a Content. + result.push(item); + } + else if (_isFunctionCallPart(item) || _isFunctionResponsePart(item)) { + throw new Error('To specify functionCall or functionResponse parts, please wrap them, and any other parts, in Content objects as appropriate, specifying the role for them'); + } + else { + accumulatedParts.push(item); + } + } + if (!isContentArray) { + result.push({ role: 'user', parts: tParts(accumulatedParts) }); + } + return result; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * TypeScript representation of the SentencePiece model protobuf. + * Translated from sentencepiece_model.proto + */ +var ModelType; +(function (ModelType) { + ModelType[ModelType["UNIGRAM"] = 1] = "UNIGRAM"; + ModelType[ModelType["BPE"] = 2] = "BPE"; + ModelType[ModelType["WORD"] = 3] = "WORD"; + ModelType[ModelType["CHAR"] = 4] = "CHAR"; +})(ModelType || (ModelType = {})); +var SentencePieceType; +(function (SentencePieceType) { + SentencePieceType[SentencePieceType["NORMAL"] = 1] = "NORMAL"; + SentencePieceType[SentencePieceType["UNKNOWN"] = 2] = "UNKNOWN"; + SentencePieceType[SentencePieceType["CONTROL"] = 3] = "CONTROL"; + SentencePieceType[SentencePieceType["USER_DEFINED"] = 4] = "USER_DEFINED"; + SentencePieceType[SentencePieceType["BYTE"] = 6] = "BYTE"; + SentencePieceType[SentencePieceType["UNUSED"] = 5] = "UNUSED"; +})(SentencePieceType || (SentencePieceType = {})); + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function newTrieNode() { + return { + children: new Map(), + final: false, + }; +} +/** + * PrefixMatcher finds the longest prefix of a string that matches + * a vocabulary word using a trie data structure. + */ +class PrefixMatcher { + /** + * Creates a new PrefixMatcher from a set of vocabulary strings. + */ + constructor(vocab) { + this.root = newTrieNode(); + for (const word of vocab) { + this.add(word); + } + } + /** + * Finds the longest prefix of text that matches a vocabulary word. + * Returns the length of the prefix, or 0 if no prefix was found. + */ + findPrefixLen(text) { + let node = this.root; + let maxLen = 0; + let i = 0; + for (const char of text) { + const child = node.children.get(char); + if (!child) { + return maxLen; + } + if (child.final) { + maxLen = i + 1; + } + node = child; + i++; + } + return maxLen; + } + /** + * Adds a word to the trie. + */ + add(word) { + let node = this.root; + for (const char of word) { + let child = node.children.get(char); + if (!child) { + child = newTrieNode(); + node.children.set(char, child); + } + node = child; + } + node.final = true; + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Generic priority queue with Insert, PopMax, and RemoveFunc operations. + * Translated from go-sentencepiece/internal/priorityqueue + * + * Uses a binary heap data structure where items[0] is unused, + * and elements are stored at indices 1...N. + */ +class PriorityQueue { + /** + * Creates a new PriorityQueue. + * + * @param sizeHint Initial capacity hint for the queue + * @param cmp Comparison function that returns > 0 if a has higher priority than b, + * 0 if equal priority, < 0 otherwise + */ + constructor(sizeHint, cmp) { + this.cmp = cmp; + this.items = new Array(Math.max(1, sizeHint + 1)); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + this.items[0] = null; + this.items.length = 1; + } + /** + * Returns the number of items in the queue. + */ + len() { + return this.items.length - 1; + } + /** + * Inserts a new element into the priority queue. + */ + insert(elem) { + this.items.push(elem); + this.siftUp(this.items.length - 1); + } + /** + * Returns and removes the element with the maximal priority. + * Throws if the queue is empty. + */ + popMax() { + if (this.items.length < 2) { + throw new Error('popping from empty priority queue'); + } + const maxItem = this.items[1]; + this.items[1] = this.items[this.items.length - 1]; + this.items.pop(); + if (this.items.length > 1) { + this.siftDown(1); + } + return maxItem; + } + /** + * Removes all elements for which the predicate returns true. + */ + removeFunc(rm) { + let i = 1; + while (i < this.items.length && !rm(this.items[i])) { + i++; + } + if (i === this.items.length) { + return; + } + for (let j = i + 1; j < this.items.length; j++) { + if (!rm(this.items[j])) { + this.items[i] = this.items[j]; + i++; + } + } + this.items.length = i; + this.rebuildHeap(); + } + /** + * Rebuilds the entire heap from scratch. + */ + rebuildHeap() { + for (let i = Math.floor(this.items.length / 2); i >= 1; i--) { + this.siftDown(i); + } + } + /** + * Moves an element up the heap until heap property is restored. + */ + siftUp(n) { + let i = n; + while (i > 1) { + const p = Math.floor(i / 2); + if (this.cmp(this.items[p], this.items[i]) >= 0) { + return; + } + [this.items[i], this.items[p]] = [this.items[p], this.items[i]]; + i = p; + } + } + /** + * Moves an element down the heap until heap property is restored. + */ + siftDown(i) { + // eslint-disable-next-line + while (true) { + const c = 2 * i; + if (c >= this.items.length) { + return; + } + let maxChild = c; + if (c + 1 < this.items.length) { + if (this.cmp(this.items[c + 1], this.items[c]) > 0) { + maxChild = c + 1; + } + } + if (this.cmp(this.items[i], this.items[maxChild]) >= 0) { + return; + } + [this.items[i], this.items[maxChild]] = [ + this.items[maxChild], + this.items[i], + ]; + i = maxChild; + } + } +} + +/*eslint-disable block-scoped-var, id-length, no-control-regex, + * no-magic-numbers, no-prototype-builtins, no-redeclare, no-shadow, no-var, + * sort-vars*/ + + +// Common aliases +const $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, + $util = $protobuf.util; + +// Exported root namespace +const $root = $protobuf.roots['default'] || ($protobuf.roots['default'] = {}); + +const sentencepiece = $root.sentencepiece = (() => { + /** + * Namespace sentencepiece. + * @exports sentencepiece + * @namespace + */ + const sentencepiece = {}; + + sentencepiece.TrainerSpec = (function() { + /** + * Properties of a TrainerSpec. + * @memberof sentencepiece + * @interface ITrainerSpec + * @property {Array.<string>|null} [input] TrainerSpec input + * @property {string|null} [inputFormat] TrainerSpec inputFormat + * @property {string|null} [modelPrefix] TrainerSpec modelPrefix + * @property {sentencepiece.TrainerSpec.ModelType|null} [modelType] + * TrainerSpec modelType + * @property {number|null} [vocabSize] TrainerSpec vocabSize + * @property {Array.<string>|null} [acceptLanguage] TrainerSpec + * acceptLanguage + * @property {number|null} [selfTestSampleSize] TrainerSpec + * selfTestSampleSize + * @property {boolean|null} [enableDifferentialPrivacy] TrainerSpec + * enableDifferentialPrivacy + * @property {number|null} [differentialPrivacyNoiseLevel] TrainerSpec + * differentialPrivacyNoiseLevel + * @property {number|Long|null} [differentialPrivacyClippingThreshold] + * TrainerSpec differentialPrivacyClippingThreshold + * @property {number|null} [characterCoverage] TrainerSpec characterCoverage + * @property {number|Long|null} [inputSentenceSize] TrainerSpec + * inputSentenceSize + * @property {boolean|null} [shuffleInputSentence] TrainerSpec + * shuffleInputSentence + * @property {number|null} [miningSentenceSize] TrainerSpec + * miningSentenceSize + * @property {number|null} [trainingSentenceSize] TrainerSpec + * trainingSentenceSize + * @property {number|null} [seedSentencepieceSize] TrainerSpec + * seedSentencepieceSize + * @property {number|null} [shrinkingFactor] TrainerSpec shrinkingFactor + * @property {number|null} [maxSentenceLength] TrainerSpec maxSentenceLength + * @property {number|null} [numThreads] TrainerSpec numThreads + * @property {number|null} [numSubIterations] TrainerSpec numSubIterations + * @property {number|null} [maxSentencepieceLength] TrainerSpec + * maxSentencepieceLength + * @property {boolean|null} [splitByUnicodeScript] TrainerSpec + * splitByUnicodeScript + * @property {boolean|null} [splitByNumber] TrainerSpec splitByNumber + * @property {boolean|null} [splitByWhitespace] TrainerSpec + * splitByWhitespace + * @property {boolean|null} [treatWhitespaceAsSuffix] TrainerSpec + * treatWhitespaceAsSuffix + * @property {boolean|null} [allowWhitespaceOnlyPieces] TrainerSpec + * allowWhitespaceOnlyPieces + * @property {boolean|null} [splitDigits] TrainerSpec splitDigits + * @property {string|null} [pretokenizationDelimiter] TrainerSpec + * pretokenizationDelimiter + * @property {Array.<string>|null} [controlSymbols] TrainerSpec + * controlSymbols + * @property {Array.<string>|null} [userDefinedSymbols] TrainerSpec + * userDefinedSymbols + * @property {string|null} [requiredChars] TrainerSpec requiredChars + * @property {boolean|null} [byteFallback] TrainerSpec byteFallback + * @property {boolean|null} [vocabularyOutputPieceScore] TrainerSpec + * vocabularyOutputPieceScore + * @property {boolean|null} [hardVocabLimit] TrainerSpec hardVocabLimit + * @property {boolean|null} [useAllVocab] TrainerSpec useAllVocab + * @property {number|null} [unkId] TrainerSpec unkId + * @property {number|null} [bosId] TrainerSpec bosId + * @property {number|null} [eosId] TrainerSpec eosId + * @property {number|null} [padId] TrainerSpec padId + * @property {string|null} [unkPiece] TrainerSpec unkPiece + * @property {string|null} [bosPiece] TrainerSpec bosPiece + * @property {string|null} [eosPiece] TrainerSpec eosPiece + * @property {string|null} [padPiece] TrainerSpec padPiece + * @property {string|null} [unkSurface] TrainerSpec unkSurface + * @property {boolean|null} [trainExtremelyLargeCorpus] TrainerSpec + * trainExtremelyLargeCorpus + * @property {string|null} [seedSentencepiecesFile] TrainerSpec + * seedSentencepiecesFile + */ + + /** + * Constructs a new TrainerSpec. + * @memberof sentencepiece + * @classdesc Represents a TrainerSpec. + * @implements ITrainerSpec + * @constructor + * @param {sentencepiece.ITrainerSpec=} [properties] Properties to set + */ + function TrainerSpec(properties) { + this.input = []; + this.acceptLanguage = []; + this.controlSymbols = []; + this.userDefinedSymbols = []; + if (properties) + for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * TrainerSpec input. + * @member {Array.<string>} input + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.input = $util.emptyArray; + + /** + * TrainerSpec inputFormat. + * @member {string} inputFormat + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.inputFormat = ''; + + /** + * TrainerSpec modelPrefix. + * @member {string} modelPrefix + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.modelPrefix = ''; + + /** + * TrainerSpec modelType. + * @member {sentencepiece.TrainerSpec.ModelType} modelType + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.modelType = 1; + + /** + * TrainerSpec vocabSize. + * @member {number} vocabSize + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.vocabSize = 8000; + + /** + * TrainerSpec acceptLanguage. + * @member {Array.<string>} acceptLanguage + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.acceptLanguage = $util.emptyArray; + + /** + * TrainerSpec selfTestSampleSize. + * @member {number} selfTestSampleSize + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.selfTestSampleSize = 0; + + /** + * TrainerSpec enableDifferentialPrivacy. + * @member {boolean} enableDifferentialPrivacy + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.enableDifferentialPrivacy = false; + + /** + * TrainerSpec differentialPrivacyNoiseLevel. + * @member {number} differentialPrivacyNoiseLevel + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.differentialPrivacyNoiseLevel = 0; + + /** + * TrainerSpec differentialPrivacyClippingThreshold. + * @member {number|Long} differentialPrivacyClippingThreshold + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.differentialPrivacyClippingThreshold = + $util.Long ? $util.Long.fromBits(0, 0, true) : 0; + + /** + * TrainerSpec characterCoverage. + * @member {number} characterCoverage + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.characterCoverage = 0.9995; + + /** + * TrainerSpec inputSentenceSize. + * @member {number|Long} inputSentenceSize + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.inputSentenceSize = + $util.Long ? $util.Long.fromBits(0, 0, true) : 0; + + /** + * TrainerSpec shuffleInputSentence. + * @member {boolean} shuffleInputSentence + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.shuffleInputSentence = true; + + /** + * TrainerSpec miningSentenceSize. + * @member {number} miningSentenceSize + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.miningSentenceSize = 0; + + /** + * TrainerSpec trainingSentenceSize. + * @member {number} trainingSentenceSize + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.trainingSentenceSize = 0; + + /** + * TrainerSpec seedSentencepieceSize. + * @member {number} seedSentencepieceSize + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.seedSentencepieceSize = 1000000; + + /** + * TrainerSpec shrinkingFactor. + * @member {number} shrinkingFactor + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.shrinkingFactor = 0.75; + + /** + * TrainerSpec maxSentenceLength. + * @member {number} maxSentenceLength + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.maxSentenceLength = 4192; + + /** + * TrainerSpec numThreads. + * @member {number} numThreads + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.numThreads = 16; + + /** + * TrainerSpec numSubIterations. + * @member {number} numSubIterations + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.numSubIterations = 2; + + /** + * TrainerSpec maxSentencepieceLength. + * @member {number} maxSentencepieceLength + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.maxSentencepieceLength = 16; + + /** + * TrainerSpec splitByUnicodeScript. + * @member {boolean} splitByUnicodeScript + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.splitByUnicodeScript = true; + + /** + * TrainerSpec splitByNumber. + * @member {boolean} splitByNumber + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.splitByNumber = true; + + /** + * TrainerSpec splitByWhitespace. + * @member {boolean} splitByWhitespace + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.splitByWhitespace = true; + + /** + * TrainerSpec treatWhitespaceAsSuffix. + * @member {boolean} treatWhitespaceAsSuffix + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.treatWhitespaceAsSuffix = false; + + /** + * TrainerSpec allowWhitespaceOnlyPieces. + * @member {boolean} allowWhitespaceOnlyPieces + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.allowWhitespaceOnlyPieces = false; + + /** + * TrainerSpec splitDigits. + * @member {boolean} splitDigits + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.splitDigits = false; + + /** + * TrainerSpec pretokenizationDelimiter. + * @member {string} pretokenizationDelimiter + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.pretokenizationDelimiter = ''; + + /** + * TrainerSpec controlSymbols. + * @member {Array.<string>} controlSymbols + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.controlSymbols = $util.emptyArray; + + /** + * TrainerSpec userDefinedSymbols. + * @member {Array.<string>} userDefinedSymbols + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.userDefinedSymbols = $util.emptyArray; + + /** + * TrainerSpec requiredChars. + * @member {string} requiredChars + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.requiredChars = ''; + + /** + * TrainerSpec byteFallback. + * @member {boolean} byteFallback + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.byteFallback = false; + + /** + * TrainerSpec vocabularyOutputPieceScore. + * @member {boolean} vocabularyOutputPieceScore + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.vocabularyOutputPieceScore = true; + + /** + * TrainerSpec hardVocabLimit. + * @member {boolean} hardVocabLimit + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.hardVocabLimit = true; + + /** + * TrainerSpec useAllVocab. + * @member {boolean} useAllVocab + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.useAllVocab = false; + + /** + * TrainerSpec unkId. + * @member {number} unkId + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.unkId = 0; + + /** + * TrainerSpec bosId. + * @member {number} bosId + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.bosId = 1; + + /** + * TrainerSpec eosId. + * @member {number} eosId + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.eosId = 2; + + /** + * TrainerSpec padId. + * @member {number} padId + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.padId = -1; + + /** + * TrainerSpec unkPiece. + * @member {string} unkPiece + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.unkPiece = '<unk>'; + + /** + * TrainerSpec bosPiece. + * @member {string} bosPiece + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.bosPiece = '<s>'; + + /** + * TrainerSpec eosPiece. + * @member {string} eosPiece + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.eosPiece = '</s>'; + + /** + * TrainerSpec padPiece. + * @member {string} padPiece + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.padPiece = '<pad>'; + + /** + * TrainerSpec unkSurface. + * @member {string} unkSurface + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.unkSurface = ' E28187 '; + + /** + * TrainerSpec trainExtremelyLargeCorpus. + * @member {boolean} trainExtremelyLargeCorpus + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.trainExtremelyLargeCorpus = false; + + /** + * TrainerSpec seedSentencepiecesFile. + * @member {string} seedSentencepiecesFile + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.seedSentencepiecesFile = ''; + + /** + * Creates a new TrainerSpec instance using the specified properties. + * @function create + * @memberof sentencepiece.TrainerSpec + * @static + * @param {sentencepiece.ITrainerSpec=} [properties] Properties to set + * @returns {sentencepiece.TrainerSpec} TrainerSpec instance + */ + TrainerSpec.create = function create(properties) { + return new TrainerSpec(properties); + }; + + /** + * Encodes the specified TrainerSpec message. Does not implicitly {@link + * sentencepiece.TrainerSpec.verify|verify} messages. + * @function encode + * @memberof sentencepiece.TrainerSpec + * @static + * @param {sentencepiece.ITrainerSpec} message TrainerSpec message or plain + * object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + TrainerSpec.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.input != null && message.input.length) + for (let i = 0; i < message.input.length; ++i) + writer.uint32(/* id 1, wireType 2 =*/ 10).string(message.input[i]); + if (message.modelPrefix != null && + Object.hasOwnProperty.call(message, 'modelPrefix')) + writer.uint32(/* id 2, wireType 2 =*/ 18).string(message.modelPrefix); + if (message.modelType != null && + Object.hasOwnProperty.call(message, 'modelType')) + writer.uint32(/* id 3, wireType 0 =*/ 24).int32(message.modelType); + if (message.vocabSize != null && + Object.hasOwnProperty.call(message, 'vocabSize')) + writer.uint32(/* id 4, wireType 0 =*/ 32).int32(message.vocabSize); + if (message.acceptLanguage != null && message.acceptLanguage.length) + for (let i = 0; i < message.acceptLanguage.length; ++i) + writer.uint32(/* id 5, wireType 2 =*/ 42) + .string(message.acceptLanguage[i]); + if (message.selfTestSampleSize != null && + Object.hasOwnProperty.call(message, 'selfTestSampleSize')) + writer.uint32(/* id 6, wireType 0 =*/ 48) + .int32(message.selfTestSampleSize); + if (message.inputFormat != null && + Object.hasOwnProperty.call(message, 'inputFormat')) + writer.uint32(/* id 7, wireType 2 =*/ 58).string(message.inputFormat); + if (message.characterCoverage != null && + Object.hasOwnProperty.call(message, 'characterCoverage')) + writer.uint32(/* id 10, wireType 5 =*/ 85) + .float(message.characterCoverage); + if (message.inputSentenceSize != null && + Object.hasOwnProperty.call(message, 'inputSentenceSize')) + writer.uint32(/* id 11, wireType 0 =*/ 88) + .uint64(message.inputSentenceSize); + if (message.miningSentenceSize != null && + Object.hasOwnProperty.call(message, 'miningSentenceSize')) + writer.uint32(/* id 12, wireType 0 =*/ 96) + .int32(message.miningSentenceSize); + if (message.trainingSentenceSize != null && + Object.hasOwnProperty.call(message, 'trainingSentenceSize')) + writer.uint32(/* id 13, wireType 0 =*/ 104) + .int32(message.trainingSentenceSize); + if (message.seedSentencepieceSize != null && + Object.hasOwnProperty.call(message, 'seedSentencepieceSize')) + writer.uint32(/* id 14, wireType 0 =*/ 112) + .int32(message.seedSentencepieceSize); + if (message.shrinkingFactor != null && + Object.hasOwnProperty.call(message, 'shrinkingFactor')) + writer.uint32(/* id 15, wireType 5 =*/ 125) + .float(message.shrinkingFactor); + if (message.numThreads != null && + Object.hasOwnProperty.call(message, 'numThreads')) + writer.uint32(/* id 16, wireType 0 =*/ 128).int32(message.numThreads); + if (message.numSubIterations != null && + Object.hasOwnProperty.call(message, 'numSubIterations')) + writer.uint32(/* id 17, wireType 0 =*/ 136) + .int32(message.numSubIterations); + if (message.maxSentenceLength != null && + Object.hasOwnProperty.call(message, 'maxSentenceLength')) + writer.uint32(/* id 18, wireType 0 =*/ 144) + .int32(message.maxSentenceLength); + if (message.shuffleInputSentence != null && + Object.hasOwnProperty.call(message, 'shuffleInputSentence')) + writer.uint32(/* id 19, wireType 0 =*/ 152) + .bool(message.shuffleInputSentence); + if (message.maxSentencepieceLength != null && + Object.hasOwnProperty.call(message, 'maxSentencepieceLength')) + writer.uint32(/* id 20, wireType 0 =*/ 160) + .int32(message.maxSentencepieceLength); + if (message.splitByUnicodeScript != null && + Object.hasOwnProperty.call(message, 'splitByUnicodeScript')) + writer.uint32(/* id 21, wireType 0 =*/ 168) + .bool(message.splitByUnicodeScript); + if (message.splitByWhitespace != null && + Object.hasOwnProperty.call(message, 'splitByWhitespace')) + writer.uint32(/* id 22, wireType 0 =*/ 176) + .bool(message.splitByWhitespace); + if (message.splitByNumber != null && + Object.hasOwnProperty.call(message, 'splitByNumber')) + writer.uint32(/* id 23, wireType 0 =*/ 184).bool(message.splitByNumber); + if (message.treatWhitespaceAsSuffix != null && + Object.hasOwnProperty.call(message, 'treatWhitespaceAsSuffix')) + writer.uint32(/* id 24, wireType 0 =*/ 192) + .bool(message.treatWhitespaceAsSuffix); + if (message.splitDigits != null && + Object.hasOwnProperty.call(message, 'splitDigits')) + writer.uint32(/* id 25, wireType 0 =*/ 200).bool(message.splitDigits); + if (message.allowWhitespaceOnlyPieces != null && + Object.hasOwnProperty.call(message, 'allowWhitespaceOnlyPieces')) + writer.uint32(/* id 26, wireType 0 =*/ 208) + .bool(message.allowWhitespaceOnlyPieces); + if (message.controlSymbols != null && message.controlSymbols.length) + for (let i = 0; i < message.controlSymbols.length; ++i) + writer.uint32(/* id 30, wireType 2 =*/ 242) + .string(message.controlSymbols[i]); + if (message.userDefinedSymbols != null && + message.userDefinedSymbols.length) + for (let i = 0; i < message.userDefinedSymbols.length; ++i) + writer.uint32(/* id 31, wireType 2 =*/ 250) + .string(message.userDefinedSymbols[i]); + if (message.vocabularyOutputPieceScore != null && + Object.hasOwnProperty.call(message, 'vocabularyOutputPieceScore')) + writer.uint32(/* id 32, wireType 0 =*/ 256) + .bool(message.vocabularyOutputPieceScore); + if (message.hardVocabLimit != null && + Object.hasOwnProperty.call(message, 'hardVocabLimit')) + writer.uint32(/* id 33, wireType 0 =*/ 264) + .bool(message.hardVocabLimit); + if (message.useAllVocab != null && + Object.hasOwnProperty.call(message, 'useAllVocab')) + writer.uint32(/* id 34, wireType 0 =*/ 272).bool(message.useAllVocab); + if (message.byteFallback != null && + Object.hasOwnProperty.call(message, 'byteFallback')) + writer.uint32(/* id 35, wireType 0 =*/ 280).bool(message.byteFallback); + if (message.requiredChars != null && + Object.hasOwnProperty.call(message, 'requiredChars')) + writer.uint32(/* id 36, wireType 2 =*/ 290) + .string(message.requiredChars); + if (message.unkId != null && Object.hasOwnProperty.call(message, 'unkId')) + writer.uint32(/* id 40, wireType 0 =*/ 320).int32(message.unkId); + if (message.bosId != null && Object.hasOwnProperty.call(message, 'bosId')) + writer.uint32(/* id 41, wireType 0 =*/ 328).int32(message.bosId); + if (message.eosId != null && Object.hasOwnProperty.call(message, 'eosId')) + writer.uint32(/* id 42, wireType 0 =*/ 336).int32(message.eosId); + if (message.padId != null && Object.hasOwnProperty.call(message, 'padId')) + writer.uint32(/* id 43, wireType 0 =*/ 344).int32(message.padId); + if (message.unkSurface != null && + Object.hasOwnProperty.call(message, 'unkSurface')) + writer.uint32(/* id 44, wireType 2 =*/ 354).string(message.unkSurface); + if (message.unkPiece != null && + Object.hasOwnProperty.call(message, 'unkPiece')) + writer.uint32(/* id 45, wireType 2 =*/ 362).string(message.unkPiece); + if (message.bosPiece != null && + Object.hasOwnProperty.call(message, 'bosPiece')) + writer.uint32(/* id 46, wireType 2 =*/ 370).string(message.bosPiece); + if (message.eosPiece != null && + Object.hasOwnProperty.call(message, 'eosPiece')) + writer.uint32(/* id 47, wireType 2 =*/ 378).string(message.eosPiece); + if (message.padPiece != null && + Object.hasOwnProperty.call(message, 'padPiece')) + writer.uint32(/* id 48, wireType 2 =*/ 386).string(message.padPiece); + if (message.trainExtremelyLargeCorpus != null && + Object.hasOwnProperty.call(message, 'trainExtremelyLargeCorpus')) + writer.uint32(/* id 49, wireType 0 =*/ 392) + .bool(message.trainExtremelyLargeCorpus); + if (message.enableDifferentialPrivacy != null && + Object.hasOwnProperty.call(message, 'enableDifferentialPrivacy')) + writer.uint32(/* id 50, wireType 0 =*/ 400) + .bool(message.enableDifferentialPrivacy); + if (message.differentialPrivacyNoiseLevel != null && + Object.hasOwnProperty.call(message, 'differentialPrivacyNoiseLevel')) + writer.uint32(/* id 51, wireType 5 =*/ 413) + .float(message.differentialPrivacyNoiseLevel); + if (message.differentialPrivacyClippingThreshold != null && + Object.hasOwnProperty.call( + message, 'differentialPrivacyClippingThreshold')) + writer.uint32(/* id 52, wireType 0 =*/ 416) + .uint64(message.differentialPrivacyClippingThreshold); + if (message.pretokenizationDelimiter != null && + Object.hasOwnProperty.call(message, 'pretokenizationDelimiter')) + writer.uint32(/* id 53, wireType 2 =*/ 426) + .string(message.pretokenizationDelimiter); + if (message.seedSentencepiecesFile != null && + Object.hasOwnProperty.call(message, 'seedSentencepiecesFile')) + writer.uint32(/* id 54, wireType 2 =*/ 434) + .string(message.seedSentencepiecesFile); + return writer; + }; + + /** + * Encodes the specified TrainerSpec message, length delimited. Does not + * implicitly {@link sentencepiece.TrainerSpec.verify|verify} messages. + * @function encodeDelimited + * @memberof sentencepiece.TrainerSpec + * @static + * @param {sentencepiece.ITrainerSpec} message TrainerSpec message or plain + * object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + TrainerSpec.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a TrainerSpec message from the specified reader or buffer. + * @function decode + * @memberof sentencepiece.TrainerSpec + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode + * from + * @param {number} [length] Message length if known beforehand + * @returns {sentencepiece.TrainerSpec} TrainerSpec + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + TrainerSpec.decode = function decode(reader, length, error) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + let end = length === undefined ? reader.len : reader.pos + length, + message = new $root.sentencepiece.TrainerSpec(); + while (reader.pos < end) { + let tag = reader.uint32(); + if (tag === error) break; + switch (tag >>> 3) { + case 1: { + if (!(message.input && message.input.length)) message.input = []; + message.input.push(reader.string()); + break; + } + case 7: { + message.inputFormat = reader.string(); + break; + } + case 2: { + message.modelPrefix = reader.string(); + break; + } + case 3: { + message.modelType = reader.int32(); + break; + } + case 4: { + message.vocabSize = reader.int32(); + break; + } + case 5: { + if (!(message.acceptLanguage && message.acceptLanguage.length)) + message.acceptLanguage = []; + message.acceptLanguage.push(reader.string()); + break; + } + case 6: { + message.selfTestSampleSize = reader.int32(); + break; + } + case 50: { + message.enableDifferentialPrivacy = reader.bool(); + break; + } + case 51: { + message.differentialPrivacyNoiseLevel = reader.float(); + break; + } + case 52: { + message.differentialPrivacyClippingThreshold = reader.uint64(); + break; + } + case 10: { + message.characterCoverage = reader.float(); + break; + } + case 11: { + message.inputSentenceSize = reader.uint64(); + break; + } + case 19: { + message.shuffleInputSentence = reader.bool(); + break; + } + case 12: { + message.miningSentenceSize = reader.int32(); + break; + } + case 13: { + message.trainingSentenceSize = reader.int32(); + break; + } + case 14: { + message.seedSentencepieceSize = reader.int32(); + break; + } + case 15: { + message.shrinkingFactor = reader.float(); + break; + } + case 18: { + message.maxSentenceLength = reader.int32(); + break; + } + case 16: { + message.numThreads = reader.int32(); + break; + } + case 17: { + message.numSubIterations = reader.int32(); + break; + } + case 20: { + message.maxSentencepieceLength = reader.int32(); + break; + } + case 21: { + message.splitByUnicodeScript = reader.bool(); + break; + } + case 23: { + message.splitByNumber = reader.bool(); + break; + } + case 22: { + message.splitByWhitespace = reader.bool(); + break; + } + case 24: { + message.treatWhitespaceAsSuffix = reader.bool(); + break; + } + case 26: { + message.allowWhitespaceOnlyPieces = reader.bool(); + break; + } + case 25: { + message.splitDigits = reader.bool(); + break; + } + case 53: { + message.pretokenizationDelimiter = reader.string(); + break; + } + case 30: { + if (!(message.controlSymbols && message.controlSymbols.length)) + message.controlSymbols = []; + message.controlSymbols.push(reader.string()); + break; + } + case 31: { + if (!(message.userDefinedSymbols && + message.userDefinedSymbols.length)) + message.userDefinedSymbols = []; + message.userDefinedSymbols.push(reader.string()); + break; + } + case 36: { + message.requiredChars = reader.string(); + break; + } + case 35: { + message.byteFallback = reader.bool(); + break; + } + case 32: { + message.vocabularyOutputPieceScore = reader.bool(); + break; + } + case 33: { + message.hardVocabLimit = reader.bool(); + break; + } + case 34: { + message.useAllVocab = reader.bool(); + break; + } + case 40: { + message.unkId = reader.int32(); + break; + } + case 41: { + message.bosId = reader.int32(); + break; + } + case 42: { + message.eosId = reader.int32(); + break; + } + case 43: { + message.padId = reader.int32(); + break; + } + case 45: { + message.unkPiece = reader.string(); + break; + } + case 46: { + message.bosPiece = reader.string(); + break; + } + case 47: { + message.eosPiece = reader.string(); + break; + } + case 48: { + message.padPiece = reader.string(); + break; + } + case 44: { + message.unkSurface = reader.string(); + break; + } + case 49: { + message.trainExtremelyLargeCorpus = reader.bool(); + break; + } + case 54: { + message.seedSentencepiecesFile = reader.string(); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a TrainerSpec message from the specified reader or buffer, length + * delimited. + * @function decodeDelimited + * @memberof sentencepiece.TrainerSpec + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode + * from + * @returns {sentencepiece.TrainerSpec} TrainerSpec + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + TrainerSpec.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a TrainerSpec message. + * @function verify + * @memberof sentencepiece.TrainerSpec + * @static + * @param {Object.<string,*>} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is + * not + */ + TrainerSpec.verify = function verify(message) { + if (typeof message !== 'object' || message === null) + return 'object expected'; + if (message.input != null && message.hasOwnProperty('input')) { + if (!Array.isArray(message.input)) return 'input: array expected'; + for (let i = 0; i < message.input.length; ++i) + if (!$util.isString(message.input[i])) + return 'input: string[] expected'; + } + if (message.inputFormat != null && message.hasOwnProperty('inputFormat')) + if (!$util.isString(message.inputFormat)) + return 'inputFormat: string expected'; + if (message.modelPrefix != null && message.hasOwnProperty('modelPrefix')) + if (!$util.isString(message.modelPrefix)) + return 'modelPrefix: string expected'; + if (message.modelType != null && message.hasOwnProperty('modelType')) + switch (message.modelType) { + default: + return 'modelType: enum value expected'; + case 1: + case 2: + case 3: + case 4: + break; + } + if (message.vocabSize != null && message.hasOwnProperty('vocabSize')) + if (!$util.isInteger(message.vocabSize)) + return 'vocabSize: integer expected'; + if (message.acceptLanguage != null && + message.hasOwnProperty('acceptLanguage')) { + if (!Array.isArray(message.acceptLanguage)) + return 'acceptLanguage: array expected'; + for (let i = 0; i < message.acceptLanguage.length; ++i) + if (!$util.isString(message.acceptLanguage[i])) + return 'acceptLanguage: string[] expected'; + } + if (message.selfTestSampleSize != null && + message.hasOwnProperty('selfTestSampleSize')) + if (!$util.isInteger(message.selfTestSampleSize)) + return 'selfTestSampleSize: integer expected'; + if (message.enableDifferentialPrivacy != null && + message.hasOwnProperty('enableDifferentialPrivacy')) + if (typeof message.enableDifferentialPrivacy !== 'boolean') + return 'enableDifferentialPrivacy: boolean expected'; + if (message.differentialPrivacyNoiseLevel != null && + message.hasOwnProperty('differentialPrivacyNoiseLevel')) + if (typeof message.differentialPrivacyNoiseLevel !== 'number') + return 'differentialPrivacyNoiseLevel: number expected'; + if (message.differentialPrivacyClippingThreshold != null && + message.hasOwnProperty('differentialPrivacyClippingThreshold')) + if (!$util.isInteger(message.differentialPrivacyClippingThreshold) && + !(message.differentialPrivacyClippingThreshold && + $util.isInteger( + message.differentialPrivacyClippingThreshold.low) && + $util.isInteger( + message.differentialPrivacyClippingThreshold.high))) + return 'differentialPrivacyClippingThreshold: integer|Long expected'; + if (message.characterCoverage != null && + message.hasOwnProperty('characterCoverage')) + if (typeof message.characterCoverage !== 'number') + return 'characterCoverage: number expected'; + if (message.inputSentenceSize != null && + message.hasOwnProperty('inputSentenceSize')) + if (!$util.isInteger(message.inputSentenceSize) && + !(message.inputSentenceSize && + $util.isInteger(message.inputSentenceSize.low) && + $util.isInteger(message.inputSentenceSize.high))) + return 'inputSentenceSize: integer|Long expected'; + if (message.shuffleInputSentence != null && + message.hasOwnProperty('shuffleInputSentence')) + if (typeof message.shuffleInputSentence !== 'boolean') + return 'shuffleInputSentence: boolean expected'; + if (message.miningSentenceSize != null && + message.hasOwnProperty('miningSentenceSize')) + if (!$util.isInteger(message.miningSentenceSize)) + return 'miningSentenceSize: integer expected'; + if (message.trainingSentenceSize != null && + message.hasOwnProperty('trainingSentenceSize')) + if (!$util.isInteger(message.trainingSentenceSize)) + return 'trainingSentenceSize: integer expected'; + if (message.seedSentencepieceSize != null && + message.hasOwnProperty('seedSentencepieceSize')) + if (!$util.isInteger(message.seedSentencepieceSize)) + return 'seedSentencepieceSize: integer expected'; + if (message.shrinkingFactor != null && + message.hasOwnProperty('shrinkingFactor')) + if (typeof message.shrinkingFactor !== 'number') + return 'shrinkingFactor: number expected'; + if (message.maxSentenceLength != null && + message.hasOwnProperty('maxSentenceLength')) + if (!$util.isInteger(message.maxSentenceLength)) + return 'maxSentenceLength: integer expected'; + if (message.numThreads != null && message.hasOwnProperty('numThreads')) + if (!$util.isInteger(message.numThreads)) + return 'numThreads: integer expected'; + if (message.numSubIterations != null && + message.hasOwnProperty('numSubIterations')) + if (!$util.isInteger(message.numSubIterations)) + return 'numSubIterations: integer expected'; + if (message.maxSentencepieceLength != null && + message.hasOwnProperty('maxSentencepieceLength')) + if (!$util.isInteger(message.maxSentencepieceLength)) + return 'maxSentencepieceLength: integer expected'; + if (message.splitByUnicodeScript != null && + message.hasOwnProperty('splitByUnicodeScript')) + if (typeof message.splitByUnicodeScript !== 'boolean') + return 'splitByUnicodeScript: boolean expected'; + if (message.splitByNumber != null && + message.hasOwnProperty('splitByNumber')) + if (typeof message.splitByNumber !== 'boolean') + return 'splitByNumber: boolean expected'; + if (message.splitByWhitespace != null && + message.hasOwnProperty('splitByWhitespace')) + if (typeof message.splitByWhitespace !== 'boolean') + return 'splitByWhitespace: boolean expected'; + if (message.treatWhitespaceAsSuffix != null && + message.hasOwnProperty('treatWhitespaceAsSuffix')) + if (typeof message.treatWhitespaceAsSuffix !== 'boolean') + return 'treatWhitespaceAsSuffix: boolean expected'; + if (message.allowWhitespaceOnlyPieces != null && + message.hasOwnProperty('allowWhitespaceOnlyPieces')) + if (typeof message.allowWhitespaceOnlyPieces !== 'boolean') + return 'allowWhitespaceOnlyPieces: boolean expected'; + if (message.splitDigits != null && message.hasOwnProperty('splitDigits')) + if (typeof message.splitDigits !== 'boolean') + return 'splitDigits: boolean expected'; + if (message.pretokenizationDelimiter != null && + message.hasOwnProperty('pretokenizationDelimiter')) + if (!$util.isString(message.pretokenizationDelimiter)) + return 'pretokenizationDelimiter: string expected'; + if (message.controlSymbols != null && + message.hasOwnProperty('controlSymbols')) { + if (!Array.isArray(message.controlSymbols)) + return 'controlSymbols: array expected'; + for (let i = 0; i < message.controlSymbols.length; ++i) + if (!$util.isString(message.controlSymbols[i])) + return 'controlSymbols: string[] expected'; + } + if (message.userDefinedSymbols != null && + message.hasOwnProperty('userDefinedSymbols')) { + if (!Array.isArray(message.userDefinedSymbols)) + return 'userDefinedSymbols: array expected'; + for (let i = 0; i < message.userDefinedSymbols.length; ++i) + if (!$util.isString(message.userDefinedSymbols[i])) + return 'userDefinedSymbols: string[] expected'; + } + if (message.requiredChars != null && + message.hasOwnProperty('requiredChars')) + if (!$util.isString(message.requiredChars)) + return 'requiredChars: string expected'; + if (message.byteFallback != null && + message.hasOwnProperty('byteFallback')) + if (typeof message.byteFallback !== 'boolean') + return 'byteFallback: boolean expected'; + if (message.vocabularyOutputPieceScore != null && + message.hasOwnProperty('vocabularyOutputPieceScore')) + if (typeof message.vocabularyOutputPieceScore !== 'boolean') + return 'vocabularyOutputPieceScore: boolean expected'; + if (message.hardVocabLimit != null && + message.hasOwnProperty('hardVocabLimit')) + if (typeof message.hardVocabLimit !== 'boolean') + return 'hardVocabLimit: boolean expected'; + if (message.useAllVocab != null && message.hasOwnProperty('useAllVocab')) + if (typeof message.useAllVocab !== 'boolean') + return 'useAllVocab: boolean expected'; + if (message.unkId != null && message.hasOwnProperty('unkId')) + if (!$util.isInteger(message.unkId)) return 'unkId: integer expected'; + if (message.bosId != null && message.hasOwnProperty('bosId')) + if (!$util.isInteger(message.bosId)) return 'bosId: integer expected'; + if (message.eosId != null && message.hasOwnProperty('eosId')) + if (!$util.isInteger(message.eosId)) return 'eosId: integer expected'; + if (message.padId != null && message.hasOwnProperty('padId')) + if (!$util.isInteger(message.padId)) return 'padId: integer expected'; + if (message.unkPiece != null && message.hasOwnProperty('unkPiece')) + if (!$util.isString(message.unkPiece)) + return 'unkPiece: string expected'; + if (message.bosPiece != null && message.hasOwnProperty('bosPiece')) + if (!$util.isString(message.bosPiece)) + return 'bosPiece: string expected'; + if (message.eosPiece != null && message.hasOwnProperty('eosPiece')) + if (!$util.isString(message.eosPiece)) + return 'eosPiece: string expected'; + if (message.padPiece != null && message.hasOwnProperty('padPiece')) + if (!$util.isString(message.padPiece)) + return 'padPiece: string expected'; + if (message.unkSurface != null && message.hasOwnProperty('unkSurface')) + if (!$util.isString(message.unkSurface)) + return 'unkSurface: string expected'; + if (message.trainExtremelyLargeCorpus != null && + message.hasOwnProperty('trainExtremelyLargeCorpus')) + if (typeof message.trainExtremelyLargeCorpus !== 'boolean') + return 'trainExtremelyLargeCorpus: boolean expected'; + if (message.seedSentencepiecesFile != null && + message.hasOwnProperty('seedSentencepiecesFile')) + if (!$util.isString(message.seedSentencepiecesFile)) + return 'seedSentencepiecesFile: string expected'; + return null; + }; + + /** + * Creates a TrainerSpec message from a plain object. Also converts values + * to their respective internal types. + * @function fromObject + * @memberof sentencepiece.TrainerSpec + * @static + * @param {Object.<string,*>} object Plain object + * @returns {sentencepiece.TrainerSpec} TrainerSpec + */ + TrainerSpec.fromObject = function fromObject(object) { + if (object instanceof $root.sentencepiece.TrainerSpec) return object; + let message = new $root.sentencepiece.TrainerSpec(); + if (object.input) { + if (!Array.isArray(object.input)) + throw TypeError('.sentencepiece.TrainerSpec.input: array expected'); + message.input = []; + for (let i = 0; i < object.input.length; ++i) + message.input[i] = String(object.input[i]); + } + if (object.inputFormat != null) + message.inputFormat = String(object.inputFormat); + if (object.modelPrefix != null) + message.modelPrefix = String(object.modelPrefix); + switch (object.modelType) { + default: + if (typeof object.modelType === 'number') { + message.modelType = object.modelType; + break; + } + break; + case 'UNIGRAM': + case 1: + message.modelType = 1; + break; + case 'BPE': + case 2: + message.modelType = 2; + break; + case 'WORD': + case 3: + message.modelType = 3; + break; + case 'CHAR': + case 4: + message.modelType = 4; + break; + } + if (object.vocabSize != null) message.vocabSize = object.vocabSize | 0; + if (object.acceptLanguage) { + if (!Array.isArray(object.acceptLanguage)) + throw TypeError( + '.sentencepiece.TrainerSpec.acceptLanguage: array expected'); + message.acceptLanguage = []; + for (let i = 0; i < object.acceptLanguage.length; ++i) + message.acceptLanguage[i] = String(object.acceptLanguage[i]); + } + if (object.selfTestSampleSize != null) + message.selfTestSampleSize = object.selfTestSampleSize | 0; + if (object.enableDifferentialPrivacy != null) + message.enableDifferentialPrivacy = + Boolean(object.enableDifferentialPrivacy); + if (object.differentialPrivacyNoiseLevel != null) + message.differentialPrivacyNoiseLevel = + Number(object.differentialPrivacyNoiseLevel); + if (object.differentialPrivacyClippingThreshold != null) + if ($util.Long) + (message.differentialPrivacyClippingThreshold = $util.Long.fromValue( + object.differentialPrivacyClippingThreshold)) + .unsigned = true; + else if ( + typeof object.differentialPrivacyClippingThreshold === 'string') + message.differentialPrivacyClippingThreshold = + parseInt(object.differentialPrivacyClippingThreshold, 10); + else if ( + typeof object.differentialPrivacyClippingThreshold === 'number') + message.differentialPrivacyClippingThreshold = + object.differentialPrivacyClippingThreshold; + else if ( + typeof object.differentialPrivacyClippingThreshold === 'object') + message.differentialPrivacyClippingThreshold = + new $util + .LongBits( + object.differentialPrivacyClippingThreshold.low >>> 0, + object.differentialPrivacyClippingThreshold.high >>> 0) + .toNumber(true); + if (object.characterCoverage != null) + message.characterCoverage = Number(object.characterCoverage); + if (object.inputSentenceSize != null) + if ($util.Long) + (message.inputSentenceSize = + $util.Long.fromValue(object.inputSentenceSize)) + .unsigned = true; + else if (typeof object.inputSentenceSize === 'string') + message.inputSentenceSize = parseInt(object.inputSentenceSize, 10); + else if (typeof object.inputSentenceSize === 'number') + message.inputSentenceSize = object.inputSentenceSize; + else if (typeof object.inputSentenceSize === 'object') + message.inputSentenceSize = + new $util + .LongBits( + object.inputSentenceSize.low >>> 0, + object.inputSentenceSize.high >>> 0) + .toNumber(true); + if (object.shuffleInputSentence != null) + message.shuffleInputSentence = Boolean(object.shuffleInputSentence); + if (object.miningSentenceSize != null) + message.miningSentenceSize = object.miningSentenceSize | 0; + if (object.trainingSentenceSize != null) + message.trainingSentenceSize = object.trainingSentenceSize | 0; + if (object.seedSentencepieceSize != null) + message.seedSentencepieceSize = object.seedSentencepieceSize | 0; + if (object.shrinkingFactor != null) + message.shrinkingFactor = Number(object.shrinkingFactor); + if (object.maxSentenceLength != null) + message.maxSentenceLength = object.maxSentenceLength | 0; + if (object.numThreads != null) message.numThreads = object.numThreads | 0; + if (object.numSubIterations != null) + message.numSubIterations = object.numSubIterations | 0; + if (object.maxSentencepieceLength != null) + message.maxSentencepieceLength = object.maxSentencepieceLength | 0; + if (object.splitByUnicodeScript != null) + message.splitByUnicodeScript = Boolean(object.splitByUnicodeScript); + if (object.splitByNumber != null) + message.splitByNumber = Boolean(object.splitByNumber); + if (object.splitByWhitespace != null) + message.splitByWhitespace = Boolean(object.splitByWhitespace); + if (object.treatWhitespaceAsSuffix != null) + message.treatWhitespaceAsSuffix = + Boolean(object.treatWhitespaceAsSuffix); + if (object.allowWhitespaceOnlyPieces != null) + message.allowWhitespaceOnlyPieces = + Boolean(object.allowWhitespaceOnlyPieces); + if (object.splitDigits != null) + message.splitDigits = Boolean(object.splitDigits); + if (object.pretokenizationDelimiter != null) + message.pretokenizationDelimiter = + String(object.pretokenizationDelimiter); + if (object.controlSymbols) { + if (!Array.isArray(object.controlSymbols)) + throw TypeError( + '.sentencepiece.TrainerSpec.controlSymbols: array expected'); + message.controlSymbols = []; + for (let i = 0; i < object.controlSymbols.length; ++i) + message.controlSymbols[i] = String(object.controlSymbols[i]); + } + if (object.userDefinedSymbols) { + if (!Array.isArray(object.userDefinedSymbols)) + throw TypeError( + '.sentencepiece.TrainerSpec.userDefinedSymbols: array expected'); + message.userDefinedSymbols = []; + for (let i = 0; i < object.userDefinedSymbols.length; ++i) + message.userDefinedSymbols[i] = String(object.userDefinedSymbols[i]); + } + if (object.requiredChars != null) + message.requiredChars = String(object.requiredChars); + if (object.byteFallback != null) + message.byteFallback = Boolean(object.byteFallback); + if (object.vocabularyOutputPieceScore != null) + message.vocabularyOutputPieceScore = + Boolean(object.vocabularyOutputPieceScore); + if (object.hardVocabLimit != null) + message.hardVocabLimit = Boolean(object.hardVocabLimit); + if (object.useAllVocab != null) + message.useAllVocab = Boolean(object.useAllVocab); + if (object.unkId != null) message.unkId = object.unkId | 0; + if (object.bosId != null) message.bosId = object.bosId | 0; + if (object.eosId != null) message.eosId = object.eosId | 0; + if (object.padId != null) message.padId = object.padId | 0; + if (object.unkPiece != null) message.unkPiece = String(object.unkPiece); + if (object.bosPiece != null) message.bosPiece = String(object.bosPiece); + if (object.eosPiece != null) message.eosPiece = String(object.eosPiece); + if (object.padPiece != null) message.padPiece = String(object.padPiece); + if (object.unkSurface != null) + message.unkSurface = String(object.unkSurface); + if (object.trainExtremelyLargeCorpus != null) + message.trainExtremelyLargeCorpus = + Boolean(object.trainExtremelyLargeCorpus); + if (object.seedSentencepiecesFile != null) + message.seedSentencepiecesFile = String(object.seedSentencepiecesFile); + return message; + }; + + /** + * Creates a plain object from a TrainerSpec message. Also converts values + * to other types if specified. + * @function toObject + * @memberof sentencepiece.TrainerSpec + * @static + * @param {sentencepiece.TrainerSpec} message TrainerSpec + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.<string,*>} Plain object + */ + TrainerSpec.toObject = function toObject(message, options) { + if (!options) options = {}; + let object = {}; + if (options.arrays || options.defaults) { + object.input = []; + object.acceptLanguage = []; + object.controlSymbols = []; + object.userDefinedSymbols = []; + } + if (options.defaults) { + object.modelPrefix = ''; + object.modelType = options.enums === String ? 'UNIGRAM' : 1; + object.vocabSize = 8000; + object.selfTestSampleSize = 0; + object.inputFormat = ''; + object.characterCoverage = 0.9995; + if ($util.Long) { + let long = new $util.Long(0, 0, true); + object.inputSentenceSize = options.longs === String ? + long.toString() : + options.longs === Number ? long.toNumber() : + long; + } else + object.inputSentenceSize = options.longs === String ? '0' : 0; + object.miningSentenceSize = 0; + object.trainingSentenceSize = 0; + object.seedSentencepieceSize = 1000000; + object.shrinkingFactor = 0.75; + object.numThreads = 16; + object.numSubIterations = 2; + object.maxSentenceLength = 4192; + object.shuffleInputSentence = true; + object.maxSentencepieceLength = 16; + object.splitByUnicodeScript = true; + object.splitByWhitespace = true; + object.splitByNumber = true; + object.treatWhitespaceAsSuffix = false; + object.splitDigits = false; + object.allowWhitespaceOnlyPieces = false; + object.vocabularyOutputPieceScore = true; + object.hardVocabLimit = true; + object.useAllVocab = false; + object.byteFallback = false; + object.requiredChars = ''; + object.unkId = 0; + object.bosId = 1; + object.eosId = 2; + object.padId = -1; + object.unkSurface = ' E28187 '; + object.unkPiece = '<unk>'; + object.bosPiece = '<s>'; + object.eosPiece = '</s>'; + object.padPiece = '<pad>'; + object.trainExtremelyLargeCorpus = false; + object.enableDifferentialPrivacy = false; + object.differentialPrivacyNoiseLevel = 0; + if ($util.Long) { + let long = new $util.Long(0, 0, true); + object.differentialPrivacyClippingThreshold = + options.longs === String ? long.toString() : + options.longs === Number ? long.toNumber() : + long; + } else + object.differentialPrivacyClippingThreshold = + options.longs === String ? '0' : 0; + object.pretokenizationDelimiter = ''; + object.seedSentencepiecesFile = ''; + } + if (message.input && message.input.length) { + object.input = []; + for (let j = 0; j < message.input.length; ++j) + object.input[j] = message.input[j]; + } + if (message.modelPrefix != null && message.hasOwnProperty('modelPrefix')) + object.modelPrefix = message.modelPrefix; + if (message.modelType != null && message.hasOwnProperty('modelType')) + object.modelType = options.enums === String ? + $root.sentencepiece.TrainerSpec.ModelType[message.modelType] === + undefined ? + message.modelType : + $root.sentencepiece.TrainerSpec.ModelType[message.modelType] : + message.modelType; + if (message.vocabSize != null && message.hasOwnProperty('vocabSize')) + object.vocabSize = message.vocabSize; + if (message.acceptLanguage && message.acceptLanguage.length) { + object.acceptLanguage = []; + for (let j = 0; j < message.acceptLanguage.length; ++j) + object.acceptLanguage[j] = message.acceptLanguage[j]; + } + if (message.selfTestSampleSize != null && + message.hasOwnProperty('selfTestSampleSize')) + object.selfTestSampleSize = message.selfTestSampleSize; + if (message.inputFormat != null && message.hasOwnProperty('inputFormat')) + object.inputFormat = message.inputFormat; + if (message.characterCoverage != null && + message.hasOwnProperty('characterCoverage')) + object.characterCoverage = + options.json && !isFinite(message.characterCoverage) ? + String(message.characterCoverage) : + message.characterCoverage; + if (message.inputSentenceSize != null && + message.hasOwnProperty('inputSentenceSize')) + if (typeof message.inputSentenceSize === 'number') + object.inputSentenceSize = options.longs === String ? + String(message.inputSentenceSize) : + message.inputSentenceSize; + else + object.inputSentenceSize = options.longs === String ? + $util.Long.prototype.toString.call(message.inputSentenceSize) : + options.longs === Number ? + new $util + .LongBits( + message.inputSentenceSize.low >>> 0, + message.inputSentenceSize.high >>> 0) + .toNumber(true) : + message.inputSentenceSize; + if (message.miningSentenceSize != null && + message.hasOwnProperty('miningSentenceSize')) + object.miningSentenceSize = message.miningSentenceSize; + if (message.trainingSentenceSize != null && + message.hasOwnProperty('trainingSentenceSize')) + object.trainingSentenceSize = message.trainingSentenceSize; + if (message.seedSentencepieceSize != null && + message.hasOwnProperty('seedSentencepieceSize')) + object.seedSentencepieceSize = message.seedSentencepieceSize; + if (message.shrinkingFactor != null && + message.hasOwnProperty('shrinkingFactor')) + object.shrinkingFactor = + options.json && !isFinite(message.shrinkingFactor) ? + String(message.shrinkingFactor) : + message.shrinkingFactor; + if (message.numThreads != null && message.hasOwnProperty('numThreads')) + object.numThreads = message.numThreads; + if (message.numSubIterations != null && + message.hasOwnProperty('numSubIterations')) + object.numSubIterations = message.numSubIterations; + if (message.maxSentenceLength != null && + message.hasOwnProperty('maxSentenceLength')) + object.maxSentenceLength = message.maxSentenceLength; + if (message.shuffleInputSentence != null && + message.hasOwnProperty('shuffleInputSentence')) + object.shuffleInputSentence = message.shuffleInputSentence; + if (message.maxSentencepieceLength != null && + message.hasOwnProperty('maxSentencepieceLength')) + object.maxSentencepieceLength = message.maxSentencepieceLength; + if (message.splitByUnicodeScript != null && + message.hasOwnProperty('splitByUnicodeScript')) + object.splitByUnicodeScript = message.splitByUnicodeScript; + if (message.splitByWhitespace != null && + message.hasOwnProperty('splitByWhitespace')) + object.splitByWhitespace = message.splitByWhitespace; + if (message.splitByNumber != null && + message.hasOwnProperty('splitByNumber')) + object.splitByNumber = message.splitByNumber; + if (message.treatWhitespaceAsSuffix != null && + message.hasOwnProperty('treatWhitespaceAsSuffix')) + object.treatWhitespaceAsSuffix = message.treatWhitespaceAsSuffix; + if (message.splitDigits != null && message.hasOwnProperty('splitDigits')) + object.splitDigits = message.splitDigits; + if (message.allowWhitespaceOnlyPieces != null && + message.hasOwnProperty('allowWhitespaceOnlyPieces')) + object.allowWhitespaceOnlyPieces = message.allowWhitespaceOnlyPieces; + if (message.controlSymbols && message.controlSymbols.length) { + object.controlSymbols = []; + for (let j = 0; j < message.controlSymbols.length; ++j) + object.controlSymbols[j] = message.controlSymbols[j]; + } + if (message.userDefinedSymbols && message.userDefinedSymbols.length) { + object.userDefinedSymbols = []; + for (let j = 0; j < message.userDefinedSymbols.length; ++j) + object.userDefinedSymbols[j] = message.userDefinedSymbols[j]; + } + if (message.vocabularyOutputPieceScore != null && + message.hasOwnProperty('vocabularyOutputPieceScore')) + object.vocabularyOutputPieceScore = message.vocabularyOutputPieceScore; + if (message.hardVocabLimit != null && + message.hasOwnProperty('hardVocabLimit')) + object.hardVocabLimit = message.hardVocabLimit; + if (message.useAllVocab != null && message.hasOwnProperty('useAllVocab')) + object.useAllVocab = message.useAllVocab; + if (message.byteFallback != null && + message.hasOwnProperty('byteFallback')) + object.byteFallback = message.byteFallback; + if (message.requiredChars != null && + message.hasOwnProperty('requiredChars')) + object.requiredChars = message.requiredChars; + if (message.unkId != null && message.hasOwnProperty('unkId')) + object.unkId = message.unkId; + if (message.bosId != null && message.hasOwnProperty('bosId')) + object.bosId = message.bosId; + if (message.eosId != null && message.hasOwnProperty('eosId')) + object.eosId = message.eosId; + if (message.padId != null && message.hasOwnProperty('padId')) + object.padId = message.padId; + if (message.unkSurface != null && message.hasOwnProperty('unkSurface')) + object.unkSurface = message.unkSurface; + if (message.unkPiece != null && message.hasOwnProperty('unkPiece')) + object.unkPiece = message.unkPiece; + if (message.bosPiece != null && message.hasOwnProperty('bosPiece')) + object.bosPiece = message.bosPiece; + if (message.eosPiece != null && message.hasOwnProperty('eosPiece')) + object.eosPiece = message.eosPiece; + if (message.padPiece != null && message.hasOwnProperty('padPiece')) + object.padPiece = message.padPiece; + if (message.trainExtremelyLargeCorpus != null && + message.hasOwnProperty('trainExtremelyLargeCorpus')) + object.trainExtremelyLargeCorpus = message.trainExtremelyLargeCorpus; + if (message.enableDifferentialPrivacy != null && + message.hasOwnProperty('enableDifferentialPrivacy')) + object.enableDifferentialPrivacy = message.enableDifferentialPrivacy; + if (message.differentialPrivacyNoiseLevel != null && + message.hasOwnProperty('differentialPrivacyNoiseLevel')) + object.differentialPrivacyNoiseLevel = + options.json && !isFinite(message.differentialPrivacyNoiseLevel) ? + String(message.differentialPrivacyNoiseLevel) : + message.differentialPrivacyNoiseLevel; + if (message.differentialPrivacyClippingThreshold != null && + message.hasOwnProperty('differentialPrivacyClippingThreshold')) + if (typeof message.differentialPrivacyClippingThreshold === 'number') + object.differentialPrivacyClippingThreshold = + options.longs === String ? + String(message.differentialPrivacyClippingThreshold) : + message.differentialPrivacyClippingThreshold; + else + object.differentialPrivacyClippingThreshold = + options.longs === String ? + $util.Long.prototype.toString.call( + message.differentialPrivacyClippingThreshold) : + options.longs === Number ? + new $util + .LongBits( + message.differentialPrivacyClippingThreshold.low >>> 0, + message.differentialPrivacyClippingThreshold.high >>> 0) + .toNumber(true) : + message.differentialPrivacyClippingThreshold; + if (message.pretokenizationDelimiter != null && + message.hasOwnProperty('pretokenizationDelimiter')) + object.pretokenizationDelimiter = message.pretokenizationDelimiter; + if (message.seedSentencepiecesFile != null && + message.hasOwnProperty('seedSentencepiecesFile')) + object.seedSentencepiecesFile = message.seedSentencepiecesFile; + return object; + }; + + /** + * Converts this TrainerSpec to JSON. + * @function toJSON + * @memberof sentencepiece.TrainerSpec + * @instance + * @returns {Object.<string,*>} JSON object + */ + TrainerSpec.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for TrainerSpec + * @function getTypeUrl + * @memberof sentencepiece.TrainerSpec + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default + * "type.googleapis.com") + * @returns {string} The default type url + */ + TrainerSpec.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/sentencepiece.TrainerSpec'; + }; + + /** + * ModelType enum. + * @name sentencepiece.TrainerSpec.ModelType + * @enum {number} + * @property {number} UNIGRAM=1 UNIGRAM value + * @property {number} BPE=2 BPE value + * @property {number} WORD=3 WORD value + * @property {number} CHAR=4 CHAR value + */ + TrainerSpec.ModelType = (function() { + const valuesById = {}, values = Object.create(valuesById); + values[valuesById[1] = 'UNIGRAM'] = 1; + values[valuesById[2] = 'BPE'] = 2; + values[valuesById[3] = 'WORD'] = 3; + values[valuesById[4] = 'CHAR'] = 4; + return values; + })(); + + return TrainerSpec; + })(); + + sentencepiece.NormalizerSpec = (function() { + /** + * Properties of a NormalizerSpec. + * @memberof sentencepiece + * @interface INormalizerSpec + * @property {string|null} [name] NormalizerSpec name + * @property {Uint8Array|null} [precompiledCharsmap] NormalizerSpec + * precompiledCharsmap + * @property {boolean|null} [addDummyPrefix] NormalizerSpec addDummyPrefix + * @property {boolean|null} [removeExtraWhitespaces] NormalizerSpec + * removeExtraWhitespaces + * @property {boolean|null} [escapeWhitespaces] NormalizerSpec + * escapeWhitespaces + * @property {string|null} [normalizationRuleTsv] NormalizerSpec + * normalizationRuleTsv + */ + + /** + * Constructs a new NormalizerSpec. + * @memberof sentencepiece + * @classdesc Represents a NormalizerSpec. + * @implements INormalizerSpec + * @constructor + * @param {sentencepiece.INormalizerSpec=} [properties] Properties to set + */ + function NormalizerSpec(properties) { + if (properties) + for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * NormalizerSpec name. + * @member {string} name + * @memberof sentencepiece.NormalizerSpec + * @instance + */ + NormalizerSpec.prototype.name = ''; + + /** + * NormalizerSpec precompiledCharsmap. + * @member {Uint8Array} precompiledCharsmap + * @memberof sentencepiece.NormalizerSpec + * @instance + */ + NormalizerSpec.prototype.precompiledCharsmap = $util.newBuffer([]); + + /** + * NormalizerSpec addDummyPrefix. + * @member {boolean} addDummyPrefix + * @memberof sentencepiece.NormalizerSpec + * @instance + */ + NormalizerSpec.prototype.addDummyPrefix = true; + + /** + * NormalizerSpec removeExtraWhitespaces. + * @member {boolean} removeExtraWhitespaces + * @memberof sentencepiece.NormalizerSpec + * @instance + */ + NormalizerSpec.prototype.removeExtraWhitespaces = true; + + /** + * NormalizerSpec escapeWhitespaces. + * @member {boolean} escapeWhitespaces + * @memberof sentencepiece.NormalizerSpec + * @instance + */ + NormalizerSpec.prototype.escapeWhitespaces = true; + + /** + * NormalizerSpec normalizationRuleTsv. + * @member {string} normalizationRuleTsv + * @memberof sentencepiece.NormalizerSpec + * @instance + */ + NormalizerSpec.prototype.normalizationRuleTsv = ''; + + /** + * Creates a new NormalizerSpec instance using the specified properties. + * @function create + * @memberof sentencepiece.NormalizerSpec + * @static + * @param {sentencepiece.INormalizerSpec=} [properties] Properties to set + * @returns {sentencepiece.NormalizerSpec} NormalizerSpec instance + */ + NormalizerSpec.create = function create(properties) { + return new NormalizerSpec(properties); + }; + + /** + * Encodes the specified NormalizerSpec message. Does not implicitly {@link + * sentencepiece.NormalizerSpec.verify|verify} messages. + * @function encode + * @memberof sentencepiece.NormalizerSpec + * @static + * @param {sentencepiece.INormalizerSpec} message NormalizerSpec message or + * plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + NormalizerSpec.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.name != null && Object.hasOwnProperty.call(message, 'name')) + writer.uint32(/* id 1, wireType 2 =*/ 10).string(message.name); + if (message.precompiledCharsmap != null && + Object.hasOwnProperty.call(message, 'precompiledCharsmap')) + writer.uint32(/* id 2, wireType 2 =*/ 18) + .bytes(message.precompiledCharsmap); + if (message.addDummyPrefix != null && + Object.hasOwnProperty.call(message, 'addDummyPrefix')) + writer.uint32(/* id 3, wireType 0 =*/ 24).bool(message.addDummyPrefix); + if (message.removeExtraWhitespaces != null && + Object.hasOwnProperty.call(message, 'removeExtraWhitespaces')) + writer.uint32(/* id 4, wireType 0 =*/ 32) + .bool(message.removeExtraWhitespaces); + if (message.escapeWhitespaces != null && + Object.hasOwnProperty.call(message, 'escapeWhitespaces')) + writer.uint32(/* id 5, wireType 0 =*/ 40) + .bool(message.escapeWhitespaces); + if (message.normalizationRuleTsv != null && + Object.hasOwnProperty.call(message, 'normalizationRuleTsv')) + writer.uint32(/* id 6, wireType 2 =*/ 50) + .string(message.normalizationRuleTsv); + return writer; + }; + + /** + * Encodes the specified NormalizerSpec message, length delimited. Does not + * implicitly {@link sentencepiece.NormalizerSpec.verify|verify} messages. + * @function encodeDelimited + * @memberof sentencepiece.NormalizerSpec + * @static + * @param {sentencepiece.INormalizerSpec} message NormalizerSpec message or + * plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + NormalizerSpec.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a NormalizerSpec message from the specified reader or buffer. + * @function decode + * @memberof sentencepiece.NormalizerSpec + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode + * from + * @param {number} [length] Message length if known beforehand + * @returns {sentencepiece.NormalizerSpec} NormalizerSpec + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + NormalizerSpec.decode = function decode(reader, length, error) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + let end = length === undefined ? reader.len : reader.pos + length, + message = new $root.sentencepiece.NormalizerSpec(); + while (reader.pos < end) { + let tag = reader.uint32(); + if (tag === error) break; + switch (tag >>> 3) { + case 1: { + message.name = reader.string(); + break; + } + case 2: { + message.precompiledCharsmap = reader.bytes(); + break; + } + case 3: { + message.addDummyPrefix = reader.bool(); + break; + } + case 4: { + message.removeExtraWhitespaces = reader.bool(); + break; + } + case 5: { + message.escapeWhitespaces = reader.bool(); + break; + } + case 6: { + message.normalizationRuleTsv = reader.string(); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a NormalizerSpec message from the specified reader or buffer, + * length delimited. + * @function decodeDelimited + * @memberof sentencepiece.NormalizerSpec + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode + * from + * @returns {sentencepiece.NormalizerSpec} NormalizerSpec + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + NormalizerSpec.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a NormalizerSpec message. + * @function verify + * @memberof sentencepiece.NormalizerSpec + * @static + * @param {Object.<string,*>} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is + * not + */ + NormalizerSpec.verify = function verify(message) { + if (typeof message !== 'object' || message === null) + return 'object expected'; + if (message.name != null && message.hasOwnProperty('name')) + if (!$util.isString(message.name)) return 'name: string expected'; + if (message.precompiledCharsmap != null && + message.hasOwnProperty('precompiledCharsmap')) + if (!(message.precompiledCharsmap && + typeof message.precompiledCharsmap.length === 'number' || + $util.isString(message.precompiledCharsmap))) + return 'precompiledCharsmap: buffer expected'; + if (message.addDummyPrefix != null && + message.hasOwnProperty('addDummyPrefix')) + if (typeof message.addDummyPrefix !== 'boolean') + return 'addDummyPrefix: boolean expected'; + if (message.removeExtraWhitespaces != null && + message.hasOwnProperty('removeExtraWhitespaces')) + if (typeof message.removeExtraWhitespaces !== 'boolean') + return 'removeExtraWhitespaces: boolean expected'; + if (message.escapeWhitespaces != null && + message.hasOwnProperty('escapeWhitespaces')) + if (typeof message.escapeWhitespaces !== 'boolean') + return 'escapeWhitespaces: boolean expected'; + if (message.normalizationRuleTsv != null && + message.hasOwnProperty('normalizationRuleTsv')) + if (!$util.isString(message.normalizationRuleTsv)) + return 'normalizationRuleTsv: string expected'; + return null; + }; + + /** + * Creates a NormalizerSpec message from a plain object. Also converts + * values to their respective internal types. + * @function fromObject + * @memberof sentencepiece.NormalizerSpec + * @static + * @param {Object.<string,*>} object Plain object + * @returns {sentencepiece.NormalizerSpec} NormalizerSpec + */ + NormalizerSpec.fromObject = function fromObject(object) { + if (object instanceof $root.sentencepiece.NormalizerSpec) return object; + let message = new $root.sentencepiece.NormalizerSpec(); + if (object.name != null) message.name = String(object.name); + if (object.precompiledCharsmap != null) + if (typeof object.precompiledCharsmap === 'string') + $util.base64.decode( + object.precompiledCharsmap, + message.precompiledCharsmap = $util.newBuffer( + $util.base64.length(object.precompiledCharsmap)), + 0); + else if (object.precompiledCharsmap.length >= 0) + message.precompiledCharsmap = object.precompiledCharsmap; + if (object.addDummyPrefix != null) + message.addDummyPrefix = Boolean(object.addDummyPrefix); + if (object.removeExtraWhitespaces != null) + message.removeExtraWhitespaces = Boolean(object.removeExtraWhitespaces); + if (object.escapeWhitespaces != null) + message.escapeWhitespaces = Boolean(object.escapeWhitespaces); + if (object.normalizationRuleTsv != null) + message.normalizationRuleTsv = String(object.normalizationRuleTsv); + return message; + }; + + /** + * Creates a plain object from a NormalizerSpec message. Also converts + * values to other types if specified. + * @function toObject + * @memberof sentencepiece.NormalizerSpec + * @static + * @param {sentencepiece.NormalizerSpec} message NormalizerSpec + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.<string,*>} Plain object + */ + NormalizerSpec.toObject = function toObject(message, options) { + if (!options) options = {}; + let object = {}; + if (options.defaults) { + object.name = ''; + if (options.bytes === String) + object.precompiledCharsmap = ''; + else { + object.precompiledCharsmap = []; + if (options.bytes !== Array) + object.precompiledCharsmap = + $util.newBuffer(object.precompiledCharsmap); + } + object.addDummyPrefix = true; + object.removeExtraWhitespaces = true; + object.escapeWhitespaces = true; + object.normalizationRuleTsv = ''; + } + if (message.name != null && message.hasOwnProperty('name')) + object.name = message.name; + if (message.precompiledCharsmap != null && + message.hasOwnProperty('precompiledCharsmap')) + object.precompiledCharsmap = options.bytes === String ? + $util.base64.encode( + message.precompiledCharsmap, 0, + message.precompiledCharsmap.length) : + options.bytes === Array ? + Array.prototype.slice.call(message.precompiledCharsmap) : + message.precompiledCharsmap; + if (message.addDummyPrefix != null && + message.hasOwnProperty('addDummyPrefix')) + object.addDummyPrefix = message.addDummyPrefix; + if (message.removeExtraWhitespaces != null && + message.hasOwnProperty('removeExtraWhitespaces')) + object.removeExtraWhitespaces = message.removeExtraWhitespaces; + if (message.escapeWhitespaces != null && + message.hasOwnProperty('escapeWhitespaces')) + object.escapeWhitespaces = message.escapeWhitespaces; + if (message.normalizationRuleTsv != null && + message.hasOwnProperty('normalizationRuleTsv')) + object.normalizationRuleTsv = message.normalizationRuleTsv; + return object; + }; + + /** + * Converts this NormalizerSpec to JSON. + * @function toJSON + * @memberof sentencepiece.NormalizerSpec + * @instance + * @returns {Object.<string,*>} JSON object + */ + NormalizerSpec.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for NormalizerSpec + * @function getTypeUrl + * @memberof sentencepiece.NormalizerSpec + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default + * "type.googleapis.com") + * @returns {string} The default type url + */ + NormalizerSpec.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/sentencepiece.NormalizerSpec'; + }; + + return NormalizerSpec; + })(); + + sentencepiece.SelfTestData = (function() { + /** + * Properties of a SelfTestData. + * @memberof sentencepiece + * @interface ISelfTestData + * @property {Array.<sentencepiece.SelfTestData.ISample>|null} [samples] + * SelfTestData samples + */ + + /** + * Constructs a new SelfTestData. + * @memberof sentencepiece + * @classdesc Represents a SelfTestData. + * @implements ISelfTestData + * @constructor + * @param {sentencepiece.ISelfTestData=} [properties] Properties to set + */ + function SelfTestData(properties) { + this.samples = []; + if (properties) + for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * SelfTestData samples. + * @member {Array.<sentencepiece.SelfTestData.ISample>} samples + * @memberof sentencepiece.SelfTestData + * @instance + */ + SelfTestData.prototype.samples = $util.emptyArray; + + /** + * Creates a new SelfTestData instance using the specified properties. + * @function create + * @memberof sentencepiece.SelfTestData + * @static + * @param {sentencepiece.ISelfTestData=} [properties] Properties to set + * @returns {sentencepiece.SelfTestData} SelfTestData instance + */ + SelfTestData.create = function create(properties) { + return new SelfTestData(properties); + }; + + /** + * Encodes the specified SelfTestData message. Does not implicitly {@link + * sentencepiece.SelfTestData.verify|verify} messages. + * @function encode + * @memberof sentencepiece.SelfTestData + * @static + * @param {sentencepiece.ISelfTestData} message SelfTestData message or + * plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + SelfTestData.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.samples != null && message.samples.length) + for (let i = 0; i < message.samples.length; ++i) + $root.sentencepiece.SelfTestData.Sample + .encode( + message.samples[i], + writer.uint32(/* id 1, wireType 2 =*/ 10).fork()) + .ldelim(); + return writer; + }; + + /** + * Encodes the specified SelfTestData message, length delimited. Does not + * implicitly {@link sentencepiece.SelfTestData.verify|verify} messages. + * @function encodeDelimited + * @memberof sentencepiece.SelfTestData + * @static + * @param {sentencepiece.ISelfTestData} message SelfTestData message or + * plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + SelfTestData.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a SelfTestData message from the specified reader or buffer. + * @function decode + * @memberof sentencepiece.SelfTestData + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode + * from + * @param {number} [length] Message length if known beforehand + * @returns {sentencepiece.SelfTestData} SelfTestData + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + SelfTestData.decode = function decode(reader, length, error) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + let end = length === undefined ? reader.len : reader.pos + length, + message = new $root.sentencepiece.SelfTestData(); + while (reader.pos < end) { + let tag = reader.uint32(); + if (tag === error) break; + switch (tag >>> 3) { + case 1: { + if (!(message.samples && message.samples.length)) + message.samples = []; + message.samples.push($root.sentencepiece.SelfTestData.Sample.decode( + reader, reader.uint32())); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a SelfTestData message from the specified reader or buffer, + * length delimited. + * @function decodeDelimited + * @memberof sentencepiece.SelfTestData + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode + * from + * @returns {sentencepiece.SelfTestData} SelfTestData + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + SelfTestData.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a SelfTestData message. + * @function verify + * @memberof sentencepiece.SelfTestData + * @static + * @param {Object.<string,*>} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is + * not + */ + SelfTestData.verify = function verify(message) { + if (typeof message !== 'object' || message === null) + return 'object expected'; + if (message.samples != null && message.hasOwnProperty('samples')) { + if (!Array.isArray(message.samples)) return 'samples: array expected'; + for (let i = 0; i < message.samples.length; ++i) { + let error = $root.sentencepiece.SelfTestData.Sample.verify( + message.samples[i]); + if (error) return 'samples.' + error; + } + } + return null; + }; + + /** + * Creates a SelfTestData message from a plain object. Also converts values + * to their respective internal types. + * @function fromObject + * @memberof sentencepiece.SelfTestData + * @static + * @param {Object.<string,*>} object Plain object + * @returns {sentencepiece.SelfTestData} SelfTestData + */ + SelfTestData.fromObject = function fromObject(object) { + if (object instanceof $root.sentencepiece.SelfTestData) return object; + let message = new $root.sentencepiece.SelfTestData(); + if (object.samples) { + if (!Array.isArray(object.samples)) + throw TypeError( + '.sentencepiece.SelfTestData.samples: array expected'); + message.samples = []; + for (let i = 0; i < object.samples.length; ++i) { + if (typeof object.samples[i] !== 'object') + throw TypeError( + '.sentencepiece.SelfTestData.samples: object expected'); + message.samples[i] = + $root.sentencepiece.SelfTestData.Sample.fromObject( + object.samples[i]); + } + } + return message; + }; + + /** + * Creates a plain object from a SelfTestData message. Also converts values + * to other types if specified. + * @function toObject + * @memberof sentencepiece.SelfTestData + * @static + * @param {sentencepiece.SelfTestData} message SelfTestData + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.<string,*>} Plain object + */ + SelfTestData.toObject = function toObject(message, options) { + if (!options) options = {}; + let object = {}; + if (options.arrays || options.defaults) object.samples = []; + if (message.samples && message.samples.length) { + object.samples = []; + for (let j = 0; j < message.samples.length; ++j) + object.samples[j] = $root.sentencepiece.SelfTestData.Sample.toObject( + message.samples[j], options); + } + return object; + }; + + /** + * Converts this SelfTestData to JSON. + * @function toJSON + * @memberof sentencepiece.SelfTestData + * @instance + * @returns {Object.<string,*>} JSON object + */ + SelfTestData.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for SelfTestData + * @function getTypeUrl + * @memberof sentencepiece.SelfTestData + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default + * "type.googleapis.com") + * @returns {string} The default type url + */ + SelfTestData.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/sentencepiece.SelfTestData'; + }; + + SelfTestData.Sample = (function() { + /** + * Properties of a Sample. + * @memberof sentencepiece.SelfTestData + * @interface ISample + * @property {string|null} [input] Sample input + * @property {string|null} [expected] Sample expected + */ + + /** + * Constructs a new Sample. + * @memberof sentencepiece.SelfTestData + * @classdesc Represents a Sample. + * @implements ISample + * @constructor + * @param {sentencepiece.SelfTestData.ISample=} [properties] Properties to + * set + */ + function Sample(properties) { + if (properties) + for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * Sample input. + * @member {string} input + * @memberof sentencepiece.SelfTestData.Sample + * @instance + */ + Sample.prototype.input = ''; + + /** + * Sample expected. + * @member {string} expected + * @memberof sentencepiece.SelfTestData.Sample + * @instance + */ + Sample.prototype.expected = ''; + + /** + * Creates a new Sample instance using the specified properties. + * @function create + * @memberof sentencepiece.SelfTestData.Sample + * @static + * @param {sentencepiece.SelfTestData.ISample=} [properties] Properties to + * set + * @returns {sentencepiece.SelfTestData.Sample} Sample instance + */ + Sample.create = function create(properties) { + return new Sample(properties); + }; + + /** + * Encodes the specified Sample message. Does not implicitly {@link + * sentencepiece.SelfTestData.Sample.verify|verify} messages. + * @function encode + * @memberof sentencepiece.SelfTestData.Sample + * @static + * @param {sentencepiece.SelfTestData.ISample} message Sample message or + * plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Sample.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.input != null && + Object.hasOwnProperty.call(message, 'input')) + writer.uint32(/* id 1, wireType 2 =*/ 10).string(message.input); + if (message.expected != null && + Object.hasOwnProperty.call(message, 'expected')) + writer.uint32(/* id 2, wireType 2 =*/ 18).string(message.expected); + return writer; + }; + + /** + * Encodes the specified Sample message, length delimited. Does not + * implicitly {@link sentencepiece.SelfTestData.Sample.verify|verify} + * messages. + * @function encodeDelimited + * @memberof sentencepiece.SelfTestData.Sample + * @static + * @param {sentencepiece.SelfTestData.ISample} message Sample message or + * plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Sample.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a Sample message from the specified reader or buffer. + * @function decode + * @memberof sentencepiece.SelfTestData.Sample + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode + * from + * @param {number} [length] Message length if known beforehand + * @returns {sentencepiece.SelfTestData.Sample} Sample + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Sample.decode = function decode(reader, length, error) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + let end = length === undefined ? reader.len : reader.pos + length, + message = new $root.sentencepiece.SelfTestData.Sample(); + while (reader.pos < end) { + let tag = reader.uint32(); + if (tag === error) break; + switch (tag >>> 3) { + case 1: { + message.input = reader.string(); + break; + } + case 2: { + message.expected = reader.string(); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a Sample message from the specified reader or buffer, length + * delimited. + * @function decodeDelimited + * @memberof sentencepiece.SelfTestData.Sample + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode + * from + * @returns {sentencepiece.SelfTestData.Sample} Sample + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Sample.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a Sample message. + * @function verify + * @memberof sentencepiece.SelfTestData.Sample + * @static + * @param {Object.<string,*>} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is + * not + */ + Sample.verify = function verify(message) { + if (typeof message !== 'object' || message === null) + return 'object expected'; + if (message.input != null && message.hasOwnProperty('input')) + if (!$util.isString(message.input)) return 'input: string expected'; + if (message.expected != null && message.hasOwnProperty('expected')) + if (!$util.isString(message.expected)) + return 'expected: string expected'; + return null; + }; + + /** + * Creates a Sample message from a plain object. Also converts values to + * their respective internal types. + * @function fromObject + * @memberof sentencepiece.SelfTestData.Sample + * @static + * @param {Object.<string,*>} object Plain object + * @returns {sentencepiece.SelfTestData.Sample} Sample + */ + Sample.fromObject = function fromObject(object) { + if (object instanceof $root.sentencepiece.SelfTestData.Sample) + return object; + let message = new $root.sentencepiece.SelfTestData.Sample(); + if (object.input != null) message.input = String(object.input); + if (object.expected != null) message.expected = String(object.expected); + return message; + }; + + /** + * Creates a plain object from a Sample message. Also converts values to + * other types if specified. + * @function toObject + * @memberof sentencepiece.SelfTestData.Sample + * @static + * @param {sentencepiece.SelfTestData.Sample} message Sample + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.<string,*>} Plain object + */ + Sample.toObject = function toObject(message, options) { + if (!options) options = {}; + let object = {}; + if (options.defaults) { + object.input = ''; + object.expected = ''; + } + if (message.input != null && message.hasOwnProperty('input')) + object.input = message.input; + if (message.expected != null && message.hasOwnProperty('expected')) + object.expected = message.expected; + return object; + }; + + /** + * Converts this Sample to JSON. + * @function toJSON + * @memberof sentencepiece.SelfTestData.Sample + * @instance + * @returns {Object.<string,*>} JSON object + */ + Sample.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for Sample + * @function getTypeUrl + * @memberof sentencepiece.SelfTestData.Sample + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default + * "type.googleapis.com") + * @returns {string} The default type url + */ + Sample.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/sentencepiece.SelfTestData.Sample'; + }; + + return Sample; + })(); + + return SelfTestData; + })(); + + sentencepiece.ModelProto = (function() { + /** + * Properties of a ModelProto. + * @memberof sentencepiece + * @interface IModelProto + * @property {Array.<sentencepiece.ModelProto.ISentencePiece>|null} [pieces] + * ModelProto pieces + * @property {sentencepiece.ITrainerSpec|null} [trainerSpec] ModelProto + * trainerSpec + * @property {sentencepiece.INormalizerSpec|null} [normalizerSpec] + * ModelProto normalizerSpec + * @property {sentencepiece.ISelfTestData|null} [selfTestData] ModelProto + * selfTestData + * @property {sentencepiece.INormalizerSpec|null} [denormalizerSpec] + * ModelProto denormalizerSpec + */ + + /** + * Constructs a new ModelProto. + * @memberof sentencepiece + * @classdesc Represents a ModelProto. + * @implements IModelProto + * @constructor + * @param {sentencepiece.IModelProto=} [properties] Properties to set + */ + function ModelProto(properties) { + this.pieces = []; + if (properties) + for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * ModelProto pieces. + * @member {Array.<sentencepiece.ModelProto.ISentencePiece>} pieces + * @memberof sentencepiece.ModelProto + * @instance + */ + ModelProto.prototype.pieces = $util.emptyArray; + + /** + * ModelProto trainerSpec. + * @member {sentencepiece.ITrainerSpec|null|undefined} trainerSpec + * @memberof sentencepiece.ModelProto + * @instance + */ + ModelProto.prototype.trainerSpec = null; + + /** + * ModelProto normalizerSpec. + * @member {sentencepiece.INormalizerSpec|null|undefined} normalizerSpec + * @memberof sentencepiece.ModelProto + * @instance + */ + ModelProto.prototype.normalizerSpec = null; + + /** + * ModelProto selfTestData. + * @member {sentencepiece.ISelfTestData|null|undefined} selfTestData + * @memberof sentencepiece.ModelProto + * @instance + */ + ModelProto.prototype.selfTestData = null; + + /** + * ModelProto denormalizerSpec. + * @member {sentencepiece.INormalizerSpec|null|undefined} denormalizerSpec + * @memberof sentencepiece.ModelProto + * @instance + */ + ModelProto.prototype.denormalizerSpec = null; + + /** + * Creates a new ModelProto instance using the specified properties. + * @function create + * @memberof sentencepiece.ModelProto + * @static + * @param {sentencepiece.IModelProto=} [properties] Properties to set + * @returns {sentencepiece.ModelProto} ModelProto instance + */ + ModelProto.create = function create(properties) { + return new ModelProto(properties); + }; + + /** + * Encodes the specified ModelProto message. Does not implicitly {@link + * sentencepiece.ModelProto.verify|verify} messages. + * @function encode + * @memberof sentencepiece.ModelProto + * @static + * @param {sentencepiece.IModelProto} message ModelProto message or plain + * object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + ModelProto.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.pieces != null && message.pieces.length) + for (let i = 0; i < message.pieces.length; ++i) + $root.sentencepiece.ModelProto.SentencePiece + .encode( + message.pieces[i], + writer.uint32(/* id 1, wireType 2 =*/ 10).fork()) + .ldelim(); + if (message.trainerSpec != null && + Object.hasOwnProperty.call(message, 'trainerSpec')) + $root.sentencepiece.TrainerSpec + .encode( + message.trainerSpec, + writer.uint32(/* id 2, wireType 2 =*/ 18).fork()) + .ldelim(); + if (message.normalizerSpec != null && + Object.hasOwnProperty.call(message, 'normalizerSpec')) + $root.sentencepiece.NormalizerSpec + .encode( + message.normalizerSpec, + writer.uint32(/* id 3, wireType 2 =*/ 26).fork()) + .ldelim(); + if (message.selfTestData != null && + Object.hasOwnProperty.call(message, 'selfTestData')) + $root.sentencepiece.SelfTestData + .encode( + message.selfTestData, + writer.uint32(/* id 4, wireType 2 =*/ 34).fork()) + .ldelim(); + if (message.denormalizerSpec != null && + Object.hasOwnProperty.call(message, 'denormalizerSpec')) + $root.sentencepiece.NormalizerSpec + .encode( + message.denormalizerSpec, + writer.uint32(/* id 5, wireType 2 =*/ 42).fork()) + .ldelim(); + return writer; + }; + + /** + * Encodes the specified ModelProto message, length delimited. Does not + * implicitly {@link sentencepiece.ModelProto.verify|verify} messages. + * @function encodeDelimited + * @memberof sentencepiece.ModelProto + * @static + * @param {sentencepiece.IModelProto} message ModelProto message or plain + * object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + ModelProto.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a ModelProto message from the specified reader or buffer. + * @function decode + * @memberof sentencepiece.ModelProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode + * from + * @param {number} [length] Message length if known beforehand + * @returns {sentencepiece.ModelProto} ModelProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + ModelProto.decode = function decode(reader, length, error) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + let end = length === undefined ? reader.len : reader.pos + length, + message = new $root.sentencepiece.ModelProto(); + while (reader.pos < end) { + let tag = reader.uint32(); + if (tag === error) break; + switch (tag >>> 3) { + case 1: { + if (!(message.pieces && message.pieces.length)) message.pieces = []; + message.pieces.push( + $root.sentencepiece.ModelProto.SentencePiece.decode( + reader, reader.uint32())); + break; + } + case 2: { + message.trainerSpec = + $root.sentencepiece.TrainerSpec.decode(reader, reader.uint32()); + break; + } + case 3: { + message.normalizerSpec = $root.sentencepiece.NormalizerSpec.decode( + reader, reader.uint32()); + break; + } + case 4: { + message.selfTestData = $root.sentencepiece.SelfTestData.decode( + reader, reader.uint32()); + break; + } + case 5: { + message.denormalizerSpec = + $root.sentencepiece.NormalizerSpec.decode( + reader, reader.uint32()); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a ModelProto message from the specified reader or buffer, length + * delimited. + * @function decodeDelimited + * @memberof sentencepiece.ModelProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode + * from + * @returns {sentencepiece.ModelProto} ModelProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + ModelProto.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a ModelProto message. + * @function verify + * @memberof sentencepiece.ModelProto + * @static + * @param {Object.<string,*>} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is + * not + */ + ModelProto.verify = function verify(message) { + if (typeof message !== 'object' || message === null) + return 'object expected'; + if (message.pieces != null && message.hasOwnProperty('pieces')) { + if (!Array.isArray(message.pieces)) return 'pieces: array expected'; + for (let i = 0; i < message.pieces.length; ++i) { + let error = $root.sentencepiece.ModelProto.SentencePiece.verify( + message.pieces[i]); + if (error) return 'pieces.' + error; + } + } + if (message.trainerSpec != null && + message.hasOwnProperty('trainerSpec')) { + let error = $root.sentencepiece.TrainerSpec.verify(message.trainerSpec); + if (error) return 'trainerSpec.' + error; + } + if (message.normalizerSpec != null && + message.hasOwnProperty('normalizerSpec')) { + let error = + $root.sentencepiece.NormalizerSpec.verify(message.normalizerSpec); + if (error) return 'normalizerSpec.' + error; + } + if (message.selfTestData != null && + message.hasOwnProperty('selfTestData')) { + let error = + $root.sentencepiece.SelfTestData.verify(message.selfTestData); + if (error) return 'selfTestData.' + error; + } + if (message.denormalizerSpec != null && + message.hasOwnProperty('denormalizerSpec')) { + let error = + $root.sentencepiece.NormalizerSpec.verify(message.denormalizerSpec); + if (error) return 'denormalizerSpec.' + error; + } + return null; + }; + + /** + * Creates a ModelProto message from a plain object. Also converts values to + * their respective internal types. + * @function fromObject + * @memberof sentencepiece.ModelProto + * @static + * @param {Object.<string,*>} object Plain object + * @returns {sentencepiece.ModelProto} ModelProto + */ + ModelProto.fromObject = function fromObject(object) { + if (object instanceof $root.sentencepiece.ModelProto) return object; + let message = new $root.sentencepiece.ModelProto(); + if (object.pieces) { + if (!Array.isArray(object.pieces)) + throw TypeError('.sentencepiece.ModelProto.pieces: array expected'); + message.pieces = []; + for (let i = 0; i < object.pieces.length; ++i) { + if (typeof object.pieces[i] !== 'object') + throw TypeError( + '.sentencepiece.ModelProto.pieces: object expected'); + message.pieces[i] = + $root.sentencepiece.ModelProto.SentencePiece.fromObject( + object.pieces[i]); + } + } + if (object.trainerSpec != null) { + if (typeof object.trainerSpec !== 'object') + throw TypeError( + '.sentencepiece.ModelProto.trainerSpec: object expected'); + message.trainerSpec = + $root.sentencepiece.TrainerSpec.fromObject(object.trainerSpec); + } + if (object.normalizerSpec != null) { + if (typeof object.normalizerSpec !== 'object') + throw TypeError( + '.sentencepiece.ModelProto.normalizerSpec: object expected'); + message.normalizerSpec = $root.sentencepiece.NormalizerSpec.fromObject( + object.normalizerSpec); + } + if (object.selfTestData != null) { + if (typeof object.selfTestData !== 'object') + throw TypeError( + '.sentencepiece.ModelProto.selfTestData: object expected'); + message.selfTestData = + $root.sentencepiece.SelfTestData.fromObject(object.selfTestData); + } + if (object.denormalizerSpec != null) { + if (typeof object.denormalizerSpec !== 'object') + throw TypeError( + '.sentencepiece.ModelProto.denormalizerSpec: object expected'); + message.denormalizerSpec = + $root.sentencepiece.NormalizerSpec.fromObject( + object.denormalizerSpec); + } + return message; + }; + + /** + * Creates a plain object from a ModelProto message. Also converts values to + * other types if specified. + * @function toObject + * @memberof sentencepiece.ModelProto + * @static + * @param {sentencepiece.ModelProto} message ModelProto + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.<string,*>} Plain object + */ + ModelProto.toObject = function toObject(message, options) { + if (!options) options = {}; + let object = {}; + if (options.arrays || options.defaults) object.pieces = []; + if (options.defaults) { + object.trainerSpec = null; + object.normalizerSpec = null; + object.selfTestData = null; + object.denormalizerSpec = null; + } + if (message.pieces && message.pieces.length) { + object.pieces = []; + for (let j = 0; j < message.pieces.length; ++j) + object.pieces[j] = + $root.sentencepiece.ModelProto.SentencePiece.toObject( + message.pieces[j], options); + } + if (message.trainerSpec != null && message.hasOwnProperty('trainerSpec')) + object.trainerSpec = $root.sentencepiece.TrainerSpec.toObject( + message.trainerSpec, options); + if (message.normalizerSpec != null && + message.hasOwnProperty('normalizerSpec')) + object.normalizerSpec = $root.sentencepiece.NormalizerSpec.toObject( + message.normalizerSpec, options); + if (message.selfTestData != null && + message.hasOwnProperty('selfTestData')) + object.selfTestData = $root.sentencepiece.SelfTestData.toObject( + message.selfTestData, options); + if (message.denormalizerSpec != null && + message.hasOwnProperty('denormalizerSpec')) + object.denormalizerSpec = $root.sentencepiece.NormalizerSpec.toObject( + message.denormalizerSpec, options); + return object; + }; + + /** + * Converts this ModelProto to JSON. + * @function toJSON + * @memberof sentencepiece.ModelProto + * @instance + * @returns {Object.<string,*>} JSON object + */ + ModelProto.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for ModelProto + * @function getTypeUrl + * @memberof sentencepiece.ModelProto + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default + * "type.googleapis.com") + * @returns {string} The default type url + */ + ModelProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/sentencepiece.ModelProto'; + }; + + ModelProto.SentencePiece = (function() { + /** + * Properties of a SentencePiece. + * @memberof sentencepiece.ModelProto + * @interface ISentencePiece + * @property {string|null} [piece] SentencePiece piece + * @property {number|null} [score] SentencePiece score + * @property {sentencepiece.ModelProto.SentencePiece.Type|null} [type] + * SentencePiece type + */ + + /** + * Constructs a new SentencePiece. + * @memberof sentencepiece.ModelProto + * @classdesc Represents a SentencePiece. + * @implements ISentencePiece + * @constructor + * @param {sentencepiece.ModelProto.ISentencePiece=} [properties] + * Properties to set + */ + function SentencePiece(properties) { + if (properties) + for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * SentencePiece piece. + * @member {string} piece + * @memberof sentencepiece.ModelProto.SentencePiece + * @instance + */ + SentencePiece.prototype.piece = ''; + + /** + * SentencePiece score. + * @member {number} score + * @memberof sentencepiece.ModelProto.SentencePiece + * @instance + */ + SentencePiece.prototype.score = 0; + + /** + * SentencePiece type. + * @member {sentencepiece.ModelProto.SentencePiece.Type} type + * @memberof sentencepiece.ModelProto.SentencePiece + * @instance + */ + SentencePiece.prototype.type = 1; + + /** + * Creates a new SentencePiece instance using the specified properties. + * @function create + * @memberof sentencepiece.ModelProto.SentencePiece + * @static + * @param {sentencepiece.ModelProto.ISentencePiece=} [properties] + * Properties to set + * @returns {sentencepiece.ModelProto.SentencePiece} SentencePiece + * instance + */ + SentencePiece.create = function create(properties) { + return new SentencePiece(properties); + }; + + /** + * Encodes the specified SentencePiece message. Does not implicitly {@link + * sentencepiece.ModelProto.SentencePiece.verify|verify} messages. + * @function encode + * @memberof sentencepiece.ModelProto.SentencePiece + * @static + * @param {sentencepiece.ModelProto.ISentencePiece} message SentencePiece + * message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + SentencePiece.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.piece != null && + Object.hasOwnProperty.call(message, 'piece')) + writer.uint32(/* id 1, wireType 2 =*/ 10).string(message.piece); + if (message.score != null && + Object.hasOwnProperty.call(message, 'score')) + writer.uint32(/* id 2, wireType 5 =*/ 21).float(message.score); + if (message.type != null && Object.hasOwnProperty.call(message, 'type')) + writer.uint32(/* id 3, wireType 0 =*/ 24).int32(message.type); + return writer; + }; + + /** + * Encodes the specified SentencePiece message, length delimited. Does not + * implicitly {@link sentencepiece.ModelProto.SentencePiece.verify|verify} + * messages. + * @function encodeDelimited + * @memberof sentencepiece.ModelProto.SentencePiece + * @static + * @param {sentencepiece.ModelProto.ISentencePiece} message SentencePiece + * message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + SentencePiece.encodeDelimited = function encodeDelimited( + message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a SentencePiece message from the specified reader or buffer. + * @function decode + * @memberof sentencepiece.ModelProto.SentencePiece + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode + * from + * @param {number} [length] Message length if known beforehand + * @returns {sentencepiece.ModelProto.SentencePiece} SentencePiece + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + SentencePiece.decode = function decode(reader, length, error) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + let end = length === undefined ? reader.len : reader.pos + length, + message = new $root.sentencepiece.ModelProto.SentencePiece(); + while (reader.pos < end) { + let tag = reader.uint32(); + if (tag === error) break; + switch (tag >>> 3) { + case 1: { + message.piece = reader.string(); + break; + } + case 2: { + message.score = reader.float(); + break; + } + case 3: { + message.type = reader.int32(); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a SentencePiece message from the specified reader or buffer, + * length delimited. + * @function decodeDelimited + * @memberof sentencepiece.ModelProto.SentencePiece + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode + * from + * @returns {sentencepiece.ModelProto.SentencePiece} SentencePiece + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + SentencePiece.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a SentencePiece message. + * @function verify + * @memberof sentencepiece.ModelProto.SentencePiece + * @static + * @param {Object.<string,*>} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is + * not + */ + SentencePiece.verify = function verify(message) { + if (typeof message !== 'object' || message === null) + return 'object expected'; + if (message.piece != null && message.hasOwnProperty('piece')) + if (!$util.isString(message.piece)) return 'piece: string expected'; + if (message.score != null && message.hasOwnProperty('score')) + if (typeof message.score !== 'number') + return 'score: number expected'; + if (message.type != null && message.hasOwnProperty('type')) + switch (message.type) { + default: + return 'type: enum value expected'; + case 1: + case 2: + case 3: + case 4: + case 6: + case 5: + break; + } + return null; + }; + + /** + * Creates a SentencePiece message from a plain object. Also converts + * values to their respective internal types. + * @function fromObject + * @memberof sentencepiece.ModelProto.SentencePiece + * @static + * @param {Object.<string,*>} object Plain object + * @returns {sentencepiece.ModelProto.SentencePiece} SentencePiece + */ + SentencePiece.fromObject = function fromObject(object) { + if (object instanceof $root.sentencepiece.ModelProto.SentencePiece) + return object; + let message = new $root.sentencepiece.ModelProto.SentencePiece(); + if (object.piece != null) message.piece = String(object.piece); + if (object.score != null) message.score = Number(object.score); + switch (object.type) { + default: + if (typeof object.type === 'number') { + message.type = object.type; + break; + } + break; + case 'NORMAL': + case 1: + message.type = 1; + break; + case 'UNKNOWN': + case 2: + message.type = 2; + break; + case 'CONTROL': + case 3: + message.type = 3; + break; + case 'USER_DEFINED': + case 4: + message.type = 4; + break; + case 'BYTE': + case 6: + message.type = 6; + break; + case 'UNUSED': + case 5: + message.type = 5; + break; + } + return message; + }; + + /** + * Creates a plain object from a SentencePiece message. Also converts + * values to other types if specified. + * @function toObject + * @memberof sentencepiece.ModelProto.SentencePiece + * @static + * @param {sentencepiece.ModelProto.SentencePiece} message SentencePiece + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.<string,*>} Plain object + */ + SentencePiece.toObject = function toObject(message, options) { + if (!options) options = {}; + let object = {}; + if (options.defaults) { + object.piece = ''; + object.score = 0; + object.type = options.enums === String ? 'NORMAL' : 1; + } + if (message.piece != null && message.hasOwnProperty('piece')) + object.piece = message.piece; + if (message.score != null && message.hasOwnProperty('score')) + object.score = options.json && !isFinite(message.score) ? + String(message.score) : + message.score; + if (message.type != null && message.hasOwnProperty('type')) + object.type = options.enums === String ? + $root.sentencepiece.ModelProto.SentencePiece + .Type[message.type] === undefined ? + message.type : + $root.sentencepiece.ModelProto.SentencePiece.Type[message.type] : + message.type; + return object; + }; + + /** + * Converts this SentencePiece to JSON. + * @function toJSON + * @memberof sentencepiece.ModelProto.SentencePiece + * @instance + * @returns {Object.<string,*>} JSON object + */ + SentencePiece.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for SentencePiece + * @function getTypeUrl + * @memberof sentencepiece.ModelProto.SentencePiece + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default + * "type.googleapis.com") + * @returns {string} The default type url + */ + SentencePiece.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/sentencepiece.ModelProto.SentencePiece'; + }; + + /** + * Type enum. + * @name sentencepiece.ModelProto.SentencePiece.Type + * @enum {number} + * @property {number} NORMAL=1 NORMAL value + * @property {number} UNKNOWN=2 UNKNOWN value + * @property {number} CONTROL=3 CONTROL value + * @property {number} USER_DEFINED=4 USER_DEFINED value + * @property {number} BYTE=6 BYTE value + * @property {number} UNUSED=5 UNUSED value + */ + SentencePiece.Type = (function() { + const valuesById = {}, values = Object.create(valuesById); + values[valuesById[1] = 'NORMAL'] = 1; + values[valuesById[2] = 'UNKNOWN'] = 2; + values[valuesById[3] = 'CONTROL'] = 3; + values[valuesById[4] = 'USER_DEFINED'] = 4; + values[valuesById[6] = 'BYTE'] = 6; + values[valuesById[5] = 'UNUSED'] = 5; + return values; + })(); + + return SentencePiece; + })(); + + return ModelProto; + })(); + + return sentencepiece; +})(); + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Pure TypeScript implementation of SentencePiece tokenizer. + * Translated from github.com/eliben/go-sentencepiece + */ +const WHITESPACE_SEPARATOR = '▁'; +const SYMBOL_BOS = '<bos>'; +const SYMBOL_EOS = '<eos>'; +const SYMBOL_PAD = '<pad>'; +/** + * Processor represents a SentencePiece processor (tokenizer). + * It converts input text into a sequence of tokens and back. + */ +class SentencePieceProcessor { + /** + * Creates a new Processor from model proto bytes. + */ + constructor(modelProtoBytes) { + var _a, _b; + this.model = this.parseModelProto(modelProtoBytes); + const tspec = this.model.trainerSpec; + if (!tspec || tspec.modelType !== ModelType.BPE) { + throw new Error(`Model type ${tspec === null || tspec === void 0 ? void 0 : tspec.modelType} not supported, only BPE is supported`); + } + const nspec = this.model.normalizerSpec; + if ((nspec === null || nspec === void 0 ? void 0 : nspec.addDummyPrefix) || (nspec === null || nspec === void 0 ? void 0 : nspec.removeExtraWhitespaces)) { + throw new Error(`Normalizer spec options not supported: ${JSON.stringify(nspec)}`); + } + const userDefined = new Set(); + this.pieces = new Map(); + this.reserved = new Map(); + this.byte2Token = new Map(); + this.idToByte = new Map(); + this.unknownID = -1; + this.maxPieceLength = 0; + if (!this.model.pieces) { + throw new Error('Model has no pieces'); + } + for (let i = 0; i < this.model.pieces.length; i++) { + const piece = this.model.pieces[i]; + const pieceText = (_a = piece.piece) !== null && _a !== void 0 ? _a : ''; + const pieceType = (_b = piece.type) !== null && _b !== void 0 ? _b : SentencePieceType.NORMAL; + const isNormalPiece = pieceType === SentencePieceType.NORMAL || + pieceType === SentencePieceType.USER_DEFINED || + pieceType === SentencePieceType.UNUSED; + if (isNormalPiece) { + this.pieces.set(pieceText, i); + this.maxPieceLength = Math.max(this.maxPieceLength, pieceText.length); + } + else { + this.reserved.set(pieceText, i); + } + if (pieceType === SentencePieceType.USER_DEFINED) { + userDefined.add(pieceText); + } + else if (pieceType === SentencePieceType.UNKNOWN) { + if (this.unknownID >= 0) { + throw new Error('unk redefined'); + } + this.unknownID = i; + } + else if (pieceType === SentencePieceType.BYTE) { + if (!tspec.byteFallback) { + throw new Error(`byte piece "${pieceText}" found although byte_fallback=false`); + } + const bv = convertHexValue(pieceText); + if (bv >= 0 && bv < 256) { + this.byte2Token.set(bv, { id: i, text: pieceText }); + this.idToByte.set(i, bv); + } + } + } + if (this.unknownID < 0) { + throw new Error('unk symbol is not defined'); + } + // If byte_fallback is specified, ensure all 256 byte values are present + if (tspec.byteFallback) { + for (let i = 0; i < 256; i++) { + if (!this.byte2Token.has(i)) { + throw new Error(`byte value 0x${i.toString(16).padStart(2, '0')} not found`); + } + } + } + this.userDefinedMatcher = new PrefixMatcher(userDefined); + } + /** + * Encodes text into a list of tokens. + */ + encode(text) { + var _a; + text = this.normalize(text); + const symList = []; + while (text.length > 0) { + const [slen, found] = this.symbolMatch(text); + const sym = { + noMerge: found, + symbol: text.substring(0, slen), + prev: symList.length - 1, + next: symList.length + 1, + }; + symList.push(sym); + text = text.substring(slen); + } + if (symList.length === 0) { + return []; + } + symList[symList.length - 1].next = -1; + const mergeQueue = new PriorityQueue(symList.length, (a, b) => { + if (a.score > b.score || (a.score === b.score && a.left < b.left)) { + return 1; + } + return -1; + }); + const findMerged = (x, y) => { + var _a; + const merged = x.symbol + y.symbol; + const id = this.pieces.get(merged); + if (id !== undefined && this.model.pieces) { + return [(_a = this.model.pieces[id].piece) !== null && _a !== void 0 ? _a : '', id, true]; + } + return ['', 0, false]; + }; + const suggestNewMergePair = (left, right) => { + var _a; + if (left === -1 || + right === -1 || + symList[left].noMerge || + symList[right].noMerge) { + return; + } + const [mergedSymbol, id, ok] = findMerged(symList[left], symList[right]); + if (ok && this.model.pieces) { + mergeQueue.insert({ + left, + right, + length: mergedSymbol.length, + score: (_a = this.model.pieces[id].score) !== null && _a !== void 0 ? _a : 0, + }); + } + }; + for (let i = 1; i < symList.length; i++) { + suggestNewMergePair(i - 1, i); + } + const candidateIsDead = (candidate) => { + const leftSymbol = symList[candidate.left].symbol; + const rightSymbol = symList[candidate.right].symbol; + return (leftSymbol === '' || + rightSymbol === '' || + leftSymbol.length + rightSymbol.length !== candidate.length); + }; + let mergeQueueDead = 0; + while (mergeQueue.len() > 0) { + const candidate = mergeQueue.popMax(); + const leftSymbol = symList[candidate.left]; + const rightSymbol = symList[candidate.right]; + if (candidateIsDead(candidate)) { + mergeQueueDead--; + continue; + } + if (mergeQueueDead * 3 > mergeQueue.len()) { + mergeQueue.removeFunc(candidateIsDead); + mergeQueueDead = 0; + } + const [mergedSymbol, , ok] = findMerged(leftSymbol, rightSymbol); + if (!ok) { + throw new Error('failed to merge symbols'); + } + symList[candidate.left].symbol = mergedSymbol; + symList[candidate.left].next = rightSymbol.next; + if (rightSymbol.next >= 0) { + symList[rightSymbol.next].prev = candidate.left; + } + symList[candidate.right].symbol = ''; + mergeQueueDead++; + suggestNewMergePair(leftSymbol.prev, candidate.left); + suggestNewMergePair(candidate.left, rightSymbol.next); + } + const tokens = []; + for (let i = 0; i >= 0; i = symList[i].next) { + const symbol = symList[i].symbol; + const id = this.symbolToID(symbol); + if (id === this.unknownID && ((_a = this.model.trainerSpec) === null || _a === void 0 ? void 0 : _a.byteFallback)) { + // Need to convert byte to token at UTF-8 bytes level + const bytes = new TextEncoder().encode(symbol); + for (let j = 0; j < bytes.length; j++) { + const byteToken = this.byte2Token.get(bytes[j]); + if (byteToken) { + tokens.push(byteToken); + } + } + } + else { + tokens.push({ id, text: symbol }); + } + } + return tokens; + } + /** + * Decodes a list of token IDs back into text. + */ + decode(ids) { + var _a, _b, _c; + const parts = []; + let i = 0; + while (i < ids.length) { + let nextNonByte = i; + while (nextNonByte < ids.length && this.isByteID(ids[nextNonByte])) { + nextNonByte++; + } + const numBytes = nextNonByte - i; + if (numBytes > 0) { + const bytes = []; + for (let bi = i; bi < nextNonByte; bi++) { + const byte = this.idToByte.get(ids[bi]); + if (byte !== undefined) { + bytes.push(byte); + } + } + const textDecoder = new TextDecoder('utf-8', { fatal: false }); + const text = textDecoder.decode(new Uint8Array(bytes)); + parts.push(text); + } + if (nextNonByte >= ids.length) { + break; + } + const id = ids[nextNonByte]; + // eslint-disable-next-line no-empty + if (this.isControlID(id)) ; + else if (id === this.unknownID) { + parts.push((_b = (_a = this.model.trainerSpec) === null || _a === void 0 ? void 0 : _a.unkSurface) !== null && _b !== void 0 ? _b : ''); + } + else if (this.model.pieces && this.model.pieces[id]) { + const piece = (_c = this.model.pieces[id].piece) !== null && _c !== void 0 ? _c : ''; + parts.push(this.replaceSeparatorsBySpace(piece)); + } + i = nextNonByte + 1; + } + return parts.join(''); + } + /** + * Decodes a list of tokens back into text. + */ + decodeTokens(tokens) { + return this.decode(tokens.map((t) => t.id)); + } + /** + * Returns information about the loaded model. + */ + modelInfo() { + var _a, _b; + const getControlID = (symbol) => { + const id = this.symbolToID(symbol); + return this.isControlID(id) ? id : -1; + }; + return { + vocabularySize: (_b = (_a = this.model.pieces) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0, + beginningOfSentenceID: getControlID(SYMBOL_BOS), + endOfSentenceID: getControlID(SYMBOL_EOS), + padID: getControlID(SYMBOL_PAD), + unknownID: this.unknownID, + }; + } + normalize(text) { + return text.replace(/ /g, WHITESPACE_SEPARATOR); + } + replaceSeparatorsBySpace(text) { + return text.replace(new RegExp(WHITESPACE_SEPARATOR, 'g'), ' '); + } + symbolMatch(text) { + const prefixLen = this.userDefinedMatcher.findPrefixLen(text); + if (prefixLen > 0) { + return [prefixLen, true]; + } + // Return character length (1), not byte length + // This matches the Java implementation where i++ advances by 1 character + return [1, false]; + } + symbolToID(symbol) { + const reservedID = this.reserved.get(symbol); + if (reservedID !== undefined) { + return reservedID; + } + const pieceID = this.pieces.get(symbol); + if (pieceID !== undefined) { + return pieceID; + } + return this.unknownID; + } + isByteID(id) { + if (!this.model.pieces || id >= this.model.pieces.length) { + return false; + } + return this.model.pieces[id].type === SentencePieceType.BYTE; + } + isControlID(id) { + if (!this.model.pieces || id >= this.model.pieces.length) { + return false; + } + return this.model.pieces[id].type === SentencePieceType.CONTROL; + } + parseModelProto(data) { + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l; + const decoded = sentencepiece.ModelProto.decode(data); + const model = { + pieces: (_a = decoded.pieces) === null || _a === void 0 ? void 0 : _a.map((p) => { + var _a, _b, _c; + return ({ + piece: (_a = p.piece) !== null && _a !== void 0 ? _a : undefined, + score: (_b = p.score) !== null && _b !== void 0 ? _b : undefined, + type: (_c = p.type) !== null && _c !== void 0 ? _c : undefined, + }); + }), + trainerSpec: decoded.trainerSpec + ? { + modelType: (_b = decoded.trainerSpec.modelType) !== null && _b !== void 0 ? _b : undefined, + vocabSize: (_c = decoded.trainerSpec.vocabSize) !== null && _c !== void 0 ? _c : undefined, + characterCoverage: (_d = decoded.trainerSpec.characterCoverage) !== null && _d !== void 0 ? _d : undefined, + byteFallback: (_e = decoded.trainerSpec.byteFallback) !== null && _e !== void 0 ? _e : undefined, + unkSurface: (_f = decoded.trainerSpec.unkSurface) !== null && _f !== void 0 ? _f : undefined, + } + : undefined, + normalizerSpec: decoded.normalizerSpec + ? { + name: (_g = decoded.normalizerSpec.name) !== null && _g !== void 0 ? _g : undefined, + precompiledCharsmap: decoded.normalizerSpec.precompiledCharsmap + ? new Uint8Array(decoded.normalizerSpec.precompiledCharsmap) + : undefined, + addDummyPrefix: (_h = decoded.normalizerSpec.addDummyPrefix) !== null && _h !== void 0 ? _h : undefined, + removeExtraWhitespaces: (_j = decoded.normalizerSpec.removeExtraWhitespaces) !== null && _j !== void 0 ? _j : undefined, + escapeWhitespaces: (_k = decoded.normalizerSpec.escapeWhitespaces) !== null && _k !== void 0 ? _k : undefined, + normalizationRuleTsv: (_l = decoded.normalizerSpec.normalizationRuleTsv) !== null && _l !== void 0 ? _l : undefined, + } + : undefined, + }; + return model; + } +} +function convertHexValue(bv) { + const match = bv.match(/^<0x([0-9A-Fa-f]{2})>$/); + if (!match) { + return -1; + } + return parseInt(match[1], 16); +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Source of truth: https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models + */ +const GEMINI_MODELS_TO_TOKENIZER_NAMES = { + 'gemini-2.5-pro': 'gemma3', + 'gemini-2.5-flash': 'gemma3', + 'gemini-2.5-flash-lite': 'gemma3', + 'gemini-2.0-flash': 'gemma3', + 'gemini-2.0-flash-lite': 'gemma3', +}; +const GEMINI_STABLE_MODELS_TO_TOKENIZER_NAMES = { + 'gemini-3-pro-preview': 'gemma3', + 'gemini-2.5-pro-preview-06-05': 'gemma3', + 'gemini-2.5-pro-preview-05-06': 'gemma3', + 'gemini-2.5-pro-exp-03-25': 'gemma3', + 'gemini-live-2.5-flash': 'gemma3', + 'gemini-2.5-flash-preview-05-20': 'gemma3', + 'gemini-2.5-flash-preview-04-17': 'gemma3', + 'gemini-2.5-flash-lite-preview-06-17': 'gemma3', + 'gemini-2.0-flash-001': 'gemma3', + 'gemini-2.0-flash-lite-001': 'gemma3', +}; +const TOKENIZERS = { + gemma2: { + modelUrl: 'https://raw.githubusercontent.com/google/gemma_pytorch/33b652c465537c6158f9a472ea5700e5e770ad3f/tokenizer/tokenizer.model', + modelHash: '61a7b147390c64585d6c3543dd6fc636906c9af3865a5548f27f31aee1d4c8e2', + }, + gemma3: { + modelUrl: 'https://raw.githubusercontent.com/google/gemma_pytorch/014acb7ac4563a5f77c76d7ff98f31b568c16508/tokenizer/gemma3_cleaned_262144_v2.spiece.model', + modelHash: '1299c11d7cf632ef3b4e11937501358ada021bbdf7c47638d13c0ee982f2e79c', + }, +}; +/** + * Gets the tokenizer name for the given model name. + * + * @param modelName The Gemini model name + * @return The tokenizer name to use + * @throws Error if the model is not supported + */ +function getTokenizerName(modelName) { + if (modelName in GEMINI_MODELS_TO_TOKENIZER_NAMES) { + return GEMINI_MODELS_TO_TOKENIZER_NAMES[modelName]; + } + if (modelName in GEMINI_STABLE_MODELS_TO_TOKENIZER_NAMES) { + return GEMINI_STABLE_MODELS_TO_TOKENIZER_NAMES[modelName]; + } + const supportedModels = [ + ...Object.keys(GEMINI_MODELS_TO_TOKENIZER_NAMES), + ...Object.keys(GEMINI_STABLE_MODELS_TO_TOKENIZER_NAMES), + ].join(', '); + throw new Error(`Model ${modelName} is not supported for local tokenization. Supported models: ${supportedModels}.`); +} +/** + * Gets the tokenizer configuration for the given tokenizer name. + * + * @param tokenizerName The tokenizer name + * @return The tokenizer configuration + * @throws Error if the tokenizer is not found + */ +function getTokenizerConfig(tokenizerName) { + if (!(tokenizerName in TOKENIZERS)) { + throw new Error(`Tokenizer ${tokenizerName} is not supported. Supported tokenizers: ${Object.keys(TOKENIZERS).join(', ')}`); + } + return TOKENIZERS[tokenizerName]; +} +/** + * Loads tokenizer model bytes from cache or URL. + * + * @param tokenizerName The tokenizer name + * @param platform Platform-specific implementations + * @return The model bytes + */ +async function loadModelProtoBytes(tokenizerName, platform) { + const config = getTokenizerConfig(tokenizerName); + const encoder = new TextEncoder(); + const cacheKey = await platform.fileSystem.computeSha1(encoder.encode(config.modelUrl)); + let modelData = await platform.cache.load(cacheKey, config.modelHash); + if (!modelData) { + modelData = await platform.fileSystem.fetchFromUrl(config.modelUrl); + const isValid = await platform.fileSystem.validateHash(modelData, config.modelHash); + if (!isValid) { + const actualHash = await platform.fileSystem.computeSha1(modelData); + throw new Error(`Downloaded model file is corrupted. Expected hash ${config.modelHash}. Got file hash ${actualHash}.`); + } + await platform.cache.save(cacheKey, modelData); + } + return modelData; +} + +/* eslint-disable @typescript-eslint/no-explicit-any */ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Accumulates countable texts from Content and Tool objects. + */ +class TextsAccumulator { + constructor() { + this.texts = []; + } + /** + * Returns all accumulated texts. + */ + getTexts() { + return this.texts; + } + /** + * Adds multiple Content objects. + */ + addContents(contents) { + for (const content of contents) { + this.addContent(content); + } + } + addContent(content) { + const countedContent = { + parts: [], + role: content.role, + }; + if (content.parts) { + for (const part of content.parts) { + const countedPart = {}; + if (part.fileData || part.inlineData) { + throw new Error('LocalTokenizers do not support non-text content types.'); + } + if (part.videoMetadata) { + countedPart.videoMetadata = part.videoMetadata; + } + if (part.functionCall) { + this.addFunctionCall(part.functionCall); + countedPart.functionCall = part.functionCall; + } + if (part.functionResponse) { + this.addFunctionResponse(part.functionResponse); + countedPart.functionResponse = part.functionResponse; + } + if (part.text) { + countedPart.text = part.text; + this.texts.push(part.text); + } + if (countedContent.parts) { + countedContent.parts.push(countedPart); + } + } + } + if (!this.deepEqual(content, countedContent)) { + console.warn(`Content contains unsupported types for token counting. ` + + `Supported fields: ${JSON.stringify(countedContent)}. ` + + `Got: ${JSON.stringify(content)}.`); + } + } + addFunctionCall(functionCall) { + if (functionCall.name) { + this.texts.push(functionCall.name); + } + if (functionCall.args) { + this.dictTraverse(functionCall.args); + } + } + addTools(tools) { + for (const tool of tools) { + this.addTool(tool); + } + } + addTool(tool) { + if (tool.functionDeclarations) { + for (const functionDeclaration of tool.functionDeclarations) { + this.functionDeclarationTraverse(functionDeclaration); + } + } + } + addFunctionResponses(functionResponses) { + for (const functionResponse of functionResponses) { + this.addFunctionResponse(functionResponse); + } + } + addFunctionResponse(functionResponse) { + if (functionResponse.name) { + this.texts.push(functionResponse.name); + } + if (functionResponse.response) { + this.dictTraverse(functionResponse.response); + } + } + functionDeclarationTraverse(functionDeclaration) { + if (functionDeclaration.name) { + this.texts.push(functionDeclaration.name); + } + if (functionDeclaration.description) { + this.texts.push(functionDeclaration.description); + } + if (functionDeclaration.parameters) { + this.addSchema(functionDeclaration.parameters); + } + if (functionDeclaration.response) { + this.addSchema(functionDeclaration.response); + } + } + addSchema(schema) { + if (schema.format) { + this.texts.push(schema.format); + } + if (schema.description) { + this.texts.push(schema.description); + } + if (schema.enum) { + this.texts.push(...schema.enum); + } + if (schema.required) { + this.texts.push(...schema.required); + } + if (schema.items) { + this.addSchema(schema.items); + } + if (schema.properties) { + for (const [key, value] of Object.entries(schema.properties)) { + this.texts.push(key); + this.addSchema(value); + } + } + if (schema.example !== undefined && schema.example !== null) { + this.anyTraverse(schema.example); + } + } + dictTraverse(obj) { + this.texts.push(...Object.keys(obj)); + for (const value of Object.values(obj)) { + this.anyTraverse(value); + } + } + anyTraverse(value) { + if (typeof value === 'string') { + this.texts.push(value); + } + else if (typeof value === 'object' && value !== null) { + if (Array.isArray(value)) { + for (const item of value) { + this.anyTraverse(item); + } + } + else { + this.dictTraverse(value); + } + } + } + deepEqual(obj1, obj2) { + if (obj1 === obj2) + return true; + if (obj1 == null || obj2 == null) + return obj1 === obj2; + if (typeof obj1 !== 'object' || typeof obj2 !== 'object') + return false; + if (Array.isArray(obj1) && Array.isArray(obj2)) { + if (obj1.length !== obj2.length) + return false; + for (let i = 0; i < obj1.length; i++) { + if (!this.deepEqual(obj1[i], obj2[i])) + return false; + } + return true; + } + const keys1 = Object.keys(obj1).filter((k) => obj1[k] !== undefined); + const keys2 = Object.keys(obj2).filter((k) => obj2[k] !== undefined); + if (keys1.length !== keys2.length) + return false; + for (const key of keys1) { + if (!keys2.includes(key)) + return false; + if (!this.deepEqual(obj1[key], obj2[key])) + return false; + } + return true; + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * LocalTokenizer implementation that integrates SentencePiece with platform-specific + * caching and file operations. + * + * This is the main implementation that brings together: + * - SentencePiece BPE tokenizer + * - Platform-specific model loading and caching + * - Text extraction from Content/Tool/Schema objects + */ +/** + * LocalTokenizer provides text-only local tokenization for Gemini models. + * + * LIMITATIONS: + * - Only supports text-based tokenization (no multimodal) + * - Forward compatibility depends on open-source tokenizer models + * - For tools/schemas, only supports types.Tool and types.Schema objects + * (Python functions or Pydantic models cannot be passed directly) + */ +let LocalTokenizer$1 = class LocalTokenizer { + /** + * Creates a new LocalTokenizer. + * + * @param modelName Gemini model name (e.g., 'gemini-2.0-flash-001') + * @param platform Platform-specific implementations for caching and file operations + */ + constructor(modelName, platform, ProcessorClass = SentencePieceProcessor) { + this.ProcessorClass = ProcessorClass; + this.modelName = modelName; + this.tokenizerName = getTokenizerName(modelName); + this.platform = platform; + } + async ensureProcessor() { + if (this.processor) { + return; + } + const modelBytes = await loadModelProtoBytes(this.tokenizerName, this.platform); + this.processor = new this.ProcessorClass(modelBytes); + } + /** + * Counts the number of tokens in the given content. + * + * @param contents The contents to tokenize + * @param config Optional configuration for counting tokens + * @return A CountTokensResult containing the total number of tokens + * + * @example + * ```typescript + * const tokenizer = new LocalTokenizer('gemini-2.0-flash-001', platform); + * const result = await tokenizer.countTokens("What is your name?"); + * console.log(result.totalTokens); // 5 + * ``` + */ + async countTokens(contents, config) { + var _a; + await this.ensureProcessor(); + const processedContents = tContents(contents); + const textAccumulator = new TextsAccumulator(); + textAccumulator.addContents(processedContents); + if (config === null || config === void 0 ? void 0 : config.systemInstruction) { + const systemContent = tContent(config.systemInstruction); + textAccumulator.addContents([systemContent]); + } + if (config === null || config === void 0 ? void 0 : config.tools) { + textAccumulator.addTools(config.tools); + } + if ((_a = config === null || config === void 0 ? void 0 : config.generationConfig) === null || _a === void 0 ? void 0 : _a.responseSchema) { + textAccumulator.addSchema(config.generationConfig.responseSchema); + } + const texts = textAccumulator.getTexts(); + let totalTokens = 0; + for (const text of texts) { + const tokens = this.processor.encode(text); + totalTokens += tokens.length; + } + return { + totalTokens, + }; + } + /** + * Computes detailed token information for the given content. + * + * @param contents The contents to tokenize + * @return A ComputeTokensResult containing token IDs, bytes, and roles + * + * @example + * ```typescript + * const tokenizer = new LocalTokenizer('gemini-2.0-flash-001', platform); + * const result = await tokenizer.computeTokens("What is your name?"); + * console.log(result.tokensInfo); + * // [{tokenIds: [279, 329, 1313, 2508, 13], tokens: [' What', ' is', ...], role: 'user'}] + * ``` + */ + async computeTokens(contents) { + await this.ensureProcessor(); + const processedContents = tContents(contents); + const tokensInfo = []; + for (const content of processedContents) { + const textAccumulator = new TextsAccumulator(); + textAccumulator.addContent(content); + const texts = textAccumulator.getTexts(); + const allTokenIds = []; + const allTokens = []; + for (const text of texts) { + const tokens = this.processor.encode(text); + allTokenIds.push(...tokens.map((t) => t.id)); + allTokens.push(...tokens.map((t) => this.tokenTextToBase64(t.text))); + } + if (allTokenIds.length > 0) { + tokensInfo.push({ + tokenIds: allTokenIds.map((id) => id.toString()), + tokens: allTokens, + role: content.role, + }); + } + } + return { + tokensInfo, + }; + } + tokenTextToBase64(text) { + const encoder = new TextEncoder(); + const bytes = encoder.encode(text.replace(/▁/g, ' ')); + let binary = ''; + for (let i = 0; i < bytes.length; i++) { + binary += String.fromCharCode(bytes[i]); + } + return btoa(binary); + } +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Node.js implementation of tokenizer cache using the file system. + */ +class NodeTokenizerCache { + constructor() { + this.cacheDir = path__namespace.join(os__namespace.tmpdir(), 'vertexai_tokenizer_model'); + } + async load(cacheKey, expectedHash) { + const filePath = path__namespace.join(this.cacheDir, cacheKey); + try { + const data = await fs__namespace.readFile(filePath); + const hash = crypto__namespace.createHash('sha256').update(data).digest('hex'); + if (hash === expectedHash) { + return new Uint8Array(data); + } + await this.removeFile(filePath); + return null; + // eslint-disable-next-line @typescript-eslint/no-unused-vars + } + catch (error) { + return null; + } + } + async save(cacheKey, data) { + const filePath = path__namespace.join(this.cacheDir, cacheKey); + try { + await fs__namespace.mkdir(this.cacheDir, { recursive: true }); + const tmpPath = `${this.cacheDir}.${crypto__namespace.randomUUID()}.tmp`; + await fs__namespace.writeFile(tmpPath, data); + await fs__namespace.rename(tmpPath, filePath); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + } + catch (error) { + // Cache is optional, so errors are silently ignored + } + } + async removeFile(filePath) { + try { + await fs__namespace.unlink(filePath); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + } + catch (error) { + // Cache is optional, so errors are silently ignored + } + } +} +/** + * Node.js implementation of tokenizer file system operations. + */ +class NodeTokenizerFileSystem { + async fetchFromUrl(url) { + const response = await fetch(url); + if (!response.ok) { + throw new Error(`Failed to fetch tokenizer model from ${url}: ${response.statusText}`); + } + const arrayBuffer = await response.arrayBuffer(); + return new Uint8Array(arrayBuffer); + } + async validateHash(data, expectedHash) { + const hash = crypto__namespace.createHash('sha256').update(data).digest('hex'); + return hash === expectedHash; + } + async computeSha1(text) { + const hash = crypto__namespace.createHash('sha1').update(text).digest('hex'); + return hash; + } +} +/** + * Node.js platform implementation for tokenizer. + */ +class NodeTokenizerPlatform { + constructor() { + this.cache = new NodeTokenizerCache(); + this.fileSystem = new NodeTokenizerFileSystem(); + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Node.js-specific LocalTokenizer implementation. + * + * This wrapper automatically uses the Node.js platform (filesystem caching, crypto hashing) + * without requiring users to manually create a platform instance. + */ +/** + * LocalTokenizer for Node.js environment. + * + * Provides local tokenization for Gemini models without requiring API calls. + * Automatically uses Node.js platform (filesystem caching in temp directory). + * + * @example + * ```typescript + * import {LocalTokenizer} from '@google/genai/node'; + * + * const tokenizer = new LocalTokenizer('gemini-2.0-flash-001'); + * const result = await tokenizer.countTokens("What is your name?"); + * console.log(result.totalTokens); // 5 + * ``` + * + * @experimental This API is experimental and may change in future versions. + */ +class LocalTokenizer { + /** + * Creates a new LocalTokenizer for Node.js. + * + * @param modelName Gemini model name (e.g., 'gemini-2.0-flash-001') + */ + constructor(modelName) { + const platform = new NodeTokenizerPlatform(); + this.baseTokenizer = new LocalTokenizer$1(modelName, platform); + } + /** + * Counts the number of tokens in the given content. + * + * @param contents The contents to tokenize + * @param config Optional configuration for counting tokens + * @return A CountTokensResult containing the total number of tokens + */ + async countTokens(contents, config) { + return this.baseTokenizer.countTokens(contents, config); + } + /** + * Computes detailed token information for the given content. + * + * @param contents The contents to tokenize + * @return A ComputeTokensResult containing token IDs, bytes, and roles + */ + async computeTokens(contents) { + return this.baseTokenizer.computeTokens(contents); + } +} + +exports.LocalTokenizer = LocalTokenizer; +//# sourceMappingURL=node.cjs.map diff --git a/server/node_modules/@google/genai/dist/tokenizer/node.d.ts b/server/node_modules/@google/genai/dist/tokenizer/node.d.ts new file mode 100644 index 0000000..2f8b021 --- /dev/null +++ b/server/node_modules/@google/genai/dist/tokenizer/node.d.ts @@ -0,0 +1,1168 @@ +/** The generic reusable api auth config. Deprecated. Please use AuthConfig (google/cloud/aiplatform/master/auth.proto) instead. This data type is not supported in Gemini API. */ +declare interface ApiAuth { + /** The API secret. */ + apiKeyConfig?: ApiAuthApiKeyConfig; +} + +/** The API secret. This data type is not supported in Gemini API. */ +declare interface ApiAuthApiKeyConfig { + /** Required. The SecretManager secret version resource name storing API key. e.g. projects/{project}/secrets/{secret}/versions/{version} */ + apiKeySecretVersion?: string; + /** The API key string. Either this or `api_key_secret_version` must be set. */ + apiKeyString?: string; +} + +/** Config for authentication with API key. This data type is not supported in Gemini API. */ +declare interface ApiKeyConfig { + /** Optional. The name of the SecretManager secret version resource storing the API key. Format: `projects/{project}/secrets/{secrete}/versions/{version}` - If both `api_key_secret` and `api_key_string` are specified, this field takes precedence over `api_key_string`. - If specified, the `secretmanager.versions.access` permission should be granted to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents) on the specified resource. */ + apiKeySecret?: string; + /** Optional. The API key to be used in the request directly. */ + apiKeyString?: string; + /** Optional. The location of the API key. */ + httpElementLocation?: HttpElementLocation; + /** Optional. The parameter name of the API key. E.g. If the API request is "https://example.com/act?api_key=", "api_key" would be the parameter name. */ + name?: string; +} + +/** The API spec that the external API implements. This enum is not supported in Gemini API. */ +declare enum ApiSpec { + /** + * Unspecified API spec. This value should not be used. + */ + API_SPEC_UNSPECIFIED = "API_SPEC_UNSPECIFIED", + /** + * Simple search API spec. + */ + SIMPLE_SEARCH = "SIMPLE_SEARCH", + /** + * Elastic search API spec. + */ + ELASTIC_SEARCH = "ELASTIC_SEARCH" +} + +/** Auth configuration to run the extension. This data type is not supported in Gemini API. */ +declare interface AuthConfig { + /** Config for API key auth. */ + apiKeyConfig?: ApiKeyConfig; + /** Type of auth scheme. */ + authType?: AuthType; + /** Config for Google Service Account auth. */ + googleServiceAccountConfig?: AuthConfigGoogleServiceAccountConfig; + /** Config for HTTP Basic auth. */ + httpBasicAuthConfig?: AuthConfigHttpBasicAuthConfig; + /** Config for user oauth. */ + oauthConfig?: AuthConfigOauthConfig; + /** Config for user OIDC auth. */ + oidcConfig?: AuthConfigOidcConfig; +} + +/** Config for Google Service Account Authentication. This data type is not supported in Gemini API. */ +declare interface AuthConfigGoogleServiceAccountConfig { + /** Optional. The service account that the extension execution service runs as. - If the service account is specified, the `iam.serviceAccounts.getAccessToken` permission should be granted to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents) on the specified service account. - If not specified, the Vertex AI Extension Service Agent will be used to execute the Extension. */ + serviceAccount?: string; +} + +/** Config for HTTP Basic Authentication. This data type is not supported in Gemini API. */ +declare interface AuthConfigHttpBasicAuthConfig { + /** Required. The name of the SecretManager secret version resource storing the base64 encoded credentials. Format: `projects/{project}/secrets/{secrete}/versions/{version}` - If specified, the `secretmanager.versions.access` permission should be granted to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents) on the specified resource. */ + credentialSecret?: string; +} + +/** Config for user oauth. This data type is not supported in Gemini API. */ +declare interface AuthConfigOauthConfig { + /** Access token for extension endpoint. Only used to propagate token from [[ExecuteExtensionRequest.runtime_auth_config]] at request time. */ + accessToken?: string; + /** The service account used to generate access tokens for executing the Extension. - If the service account is specified, the `iam.serviceAccounts.getAccessToken` permission should be granted to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents) on the provided service account. */ + serviceAccount?: string; +} + +/** Config for user OIDC auth. This data type is not supported in Gemini API. */ +declare interface AuthConfigOidcConfig { + /** OpenID Connect formatted ID token for extension endpoint. Only used to propagate token from [[ExecuteExtensionRequest.runtime_auth_config]] at request time. */ + idToken?: string; + /** The service account used to generate an OpenID Connect (OIDC)-compatible JWT token signed by the Google OIDC Provider (accounts.google.com) for extension endpoint (https://cloud.google.com/iam/docs/create-short-lived-credentials-direct#sa-credentials-oidc). - The audience for the token will be set to the URL in the server url defined in the OpenApi spec. - If the service account is provided, the service account should grant `iam.serviceAccounts.getOpenIdToken` permission to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents). */ + serviceAccount?: string; +} + +/** Type of auth scheme. This enum is not supported in Gemini API. */ +declare enum AuthType { + AUTH_TYPE_UNSPECIFIED = "AUTH_TYPE_UNSPECIFIED", + /** + * No Auth. + */ + NO_AUTH = "NO_AUTH", + /** + * API Key Auth. + */ + API_KEY_AUTH = "API_KEY_AUTH", + /** + * HTTP Basic Auth. + */ + HTTP_BASIC_AUTH = "HTTP_BASIC_AUTH", + /** + * Google Service Account Auth. + */ + GOOGLE_SERVICE_ACCOUNT_AUTH = "GOOGLE_SERVICE_ACCOUNT_AUTH", + /** + * OAuth auth. + */ + OAUTH = "OAUTH", + /** + * OpenID Connect (OIDC) Auth. + */ + OIDC_AUTH = "OIDC_AUTH" +} + +/** Specifies the function Behavior. Currently only supported by the BidiGenerateContent method. This enum is not supported in Vertex AI. */ +declare enum Behavior { + /** + * This value is unused. + */ + UNSPECIFIED = "UNSPECIFIED", + /** + * If set, the system will wait to receive the function response before continuing the conversation. + */ + BLOCKING = "BLOCKING", + /** + * If set, the system will not wait to receive the function response. Instead, it will attempt to handle function responses as they become available while maintaining the conversation between the user and the model. + */ + NON_BLOCKING = "NON_BLOCKING" +} + +/** Content blob. */ +declare interface Blob_2 { + /** Required. Raw bytes. + * @remarks Encoded as base64 string. */ + data?: string; + /** Optional. Display name of the blob. Used to provide a label or filename to distinguish blobs. This field is only returned in PromptMessage for prompt management. It is currently used in the Gemini GenerateContent calls only when server side tools (code_execution, google_search, and url_context) are enabled. This field is not supported in Gemini API. */ + displayName?: string; + /** Required. The IANA standard MIME type of the source data. */ + mimeType?: string; +} + +/** Result of executing the [ExecutableCode]. Only generated when using the [CodeExecution] tool, and always follows a `part` containing the [ExecutableCode]. */ +declare interface CodeExecutionResult { + /** Required. Outcome of the code execution. */ + outcome?: Outcome; + /** Optional. Contains stdout when code execution is successful, stderr or other description otherwise. */ + output?: string; +} + +/** Tool to support computer use. */ +declare interface ComputerUse { + /** Required. The environment being operated. */ + environment?: Environment; + /** By default, predefined functions are included in the final model call. + Some of them can be explicitly excluded from being automatically included. + This can serve two purposes: + 1. Using a more restricted / different action space. + 2. Improving the definitions / instructions of predefined functions. */ + excludedPredefinedFunctions?: string[]; +} + +/** Local tokenizer compute tokens result. */ +export declare interface ComputeTokensResult { + /** Lists of tokens info from the input. */ + tokensInfo?: TokensInfo[]; +} + +/** Contains the multi-part content of a message. */ +declare interface Content { + /** List of parts that constitute a single message. Each part may have + a different IANA MIME type. */ + parts?: Part[]; + /** Optional. The producer of the content. Must be either 'user' or 'model'. Useful to set for multi-turn conversations, otherwise can be left blank or unset. */ + role?: string; +} + +declare type ContentListUnion = Content | Content[] | PartUnion | PartUnion[]; + +declare type ContentUnion = Content | PartUnion[] | PartUnion; + +/** Config for the count_tokens method. */ +declare interface CountTokensConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** Instructions for the model to steer it toward better performance. + */ + systemInstruction?: ContentUnion; + /** Code that enables the system to interact with external systems to + perform an action outside of the knowledge and scope of the model. + */ + tools?: Tool[]; + /** Configuration that the model uses to generate the response. Not + supported by the Gemini Developer API. + */ + generationConfig?: GenerationConfig; +} + +/** Local tokenizer count tokens result. */ +export declare interface CountTokensResult { + /** The total number of tokens. */ + totalTokens?: number; +} + +/** Describes the options to customize dynamic retrieval. */ +declare interface DynamicRetrievalConfig { + /** Optional. The threshold to be used in dynamic retrieval. If not set, a system default value is used. */ + dynamicThreshold?: number; + /** The mode of the predictor to be used in dynamic retrieval. */ + mode?: DynamicRetrievalConfigMode; +} + +/** The mode of the predictor to be used in dynamic retrieval. */ +declare enum DynamicRetrievalConfigMode { + /** + * Always trigger retrieval. + */ + MODE_UNSPECIFIED = "MODE_UNSPECIFIED", + /** + * Run retrieval only when system decides it is necessary. + */ + MODE_DYNAMIC = "MODE_DYNAMIC" +} + +/** Tool to search public web data, powered by Vertex AI Search and Sec4 compliance. This data type is not supported in Gemini API. */ +declare interface EnterpriseWebSearch { + /** Optional. List of domains to be excluded from the search results. The default limit is 2000 domains. */ + excludeDomains?: string[]; + /** Optional. Sites with confidence level chosen & above this value will be blocked from the search results. */ + blockingConfidence?: PhishBlockThreshold; +} + +/** The environment being operated. */ +declare enum Environment { + /** + * Defaults to browser. + */ + ENVIRONMENT_UNSPECIFIED = "ENVIRONMENT_UNSPECIFIED", + /** + * Operates in a web browser. + */ + ENVIRONMENT_BROWSER = "ENVIRONMENT_BROWSER" +} + +/** Code generated by the model that is meant to be executed, and the result returned to the model. Generated when using the [CodeExecution] tool, in which the code will be automatically executed, and a corresponding [CodeExecutionResult] will also be generated. */ +declare interface ExecutableCode { + /** Required. The code to be executed. */ + code?: string; + /** Required. Programming language of the `code`. */ + language?: Language; +} + +/** Retrieve from data source powered by external API for grounding. The external API is not owned by Google, but need to follow the pre-defined API spec. This data type is not supported in Gemini API. */ +declare interface ExternalApi { + /** The authentication config to access the API. Deprecated. Please use auth_config instead. */ + apiAuth?: ApiAuth; + /** The API spec that the external API implements. */ + apiSpec?: ApiSpec; + /** The authentication config to access the API. */ + authConfig?: AuthConfig; + /** Parameters for the elastic search API. */ + elasticSearchParams?: ExternalApiElasticSearchParams; + /** The endpoint of the external API. The system will call the API at this endpoint to retrieve the data for grounding. Example: https://acme.com:443/search */ + endpoint?: string; + /** Parameters for the simple search API. */ + simpleSearchParams?: ExternalApiSimpleSearchParams; +} + +/** The search parameters to use for the ELASTIC_SEARCH spec. This data type is not supported in Gemini API. */ +declare interface ExternalApiElasticSearchParams { + /** The ElasticSearch index to use. */ + index?: string; + /** Optional. Number of hits (chunks) to request. When specified, it is passed to Elasticsearch as the `num_hits` param. */ + numHits?: number; + /** The ElasticSearch search template to use. */ + searchTemplate?: string; +} + +/** The search parameters to use for SIMPLE_SEARCH spec. This data type is not supported in Gemini API. */ +declare interface ExternalApiSimpleSearchParams { +} + +/** Options for feature selection preference. */ +declare enum FeatureSelectionPreference { + FEATURE_SELECTION_PREFERENCE_UNSPECIFIED = "FEATURE_SELECTION_PREFERENCE_UNSPECIFIED", + PRIORITIZE_QUALITY = "PRIORITIZE_QUALITY", + BALANCED = "BALANCED", + PRIORITIZE_COST = "PRIORITIZE_COST" +} + +/** URI based data. */ +declare interface FileData { + /** Optional. Display name of the file data. Used to provide a label or filename to distinguish file datas. This field is only returned in PromptMessage for prompt management. It is currently used in the Gemini GenerateContent calls only when server side tools (code_execution, google_search, and url_context) are enabled. This field is not supported in Gemini API. */ + displayName?: string; + /** Required. URI. */ + fileUri?: string; + /** Required. The IANA standard MIME type of the source data. */ + mimeType?: string; +} + +/** Tool to retrieve knowledge from the File Search Stores. */ +declare interface FileSearch { + /** The names of the file_search_stores to retrieve from. + Example: `fileSearchStores/my-file-search-store-123` */ + fileSearchStoreNames?: string[]; + /** The number of file search retrieval chunks to retrieve. */ + topK?: number; + /** Metadata filter to apply to the file search retrieval documents. See https://google.aip.dev/160 for the syntax of the filter expression. */ + metadataFilter?: string; +} + +/** A function call. */ +declare interface FunctionCall { + /** The unique id of the function call. If populated, the client to execute the + `function_call` and return the response with the matching `id`. */ + id?: string; + /** Optional. The function parameters and values in JSON object format. See [FunctionDeclaration.parameters] for parameter details. */ + args?: Record<string, unknown>; + /** Optional. The name of the function to call. Matches [FunctionDeclaration.name]. */ + name?: string; + /** Optional. The partial argument value of the function call. If provided, represents the arguments/fields that are streamed incrementally. This field is not supported in Gemini API. */ + partialArgs?: PartialArg[]; + /** Optional. Whether this is the last part of the FunctionCall. If true, another partial message for the current FunctionCall is expected to follow. This field is not supported in Gemini API. */ + willContinue?: boolean; +} + +/** Structured representation of a function declaration as defined by the [OpenAPI 3.0 specification](https://spec.openapis.org/oas/v3.0.3). Included in this declaration are the function name, description, parameters and response type. This FunctionDeclaration is a representation of a block of code that can be used as a `Tool` by the model and executed by the client. */ +declare interface FunctionDeclaration { + /** Optional. Description and purpose of the function. Model uses it to decide how and whether to call the function. */ + description?: string; + /** Required. The name of the function to call. Must start with a letter or an underscore. Must be a-z, A-Z, 0-9, or contain underscores, dots and dashes, with a maximum length of 64. */ + name?: string; + /** Optional. Describes the parameters to this function in JSON Schema Object format. Reflects the Open API 3.03 Parameter Object. string Key: the name of the parameter. Parameter names are case sensitive. Schema Value: the Schema defining the type used for the parameter. For function with no parameters, this can be left unset. Parameter names must start with a letter or an underscore and must only contain chars a-z, A-Z, 0-9, or underscores with a maximum length of 64. Example with 1 required and 1 optional parameter: type: OBJECT properties: param1: type: STRING param2: type: INTEGER required: - param1 */ + parameters?: Schema; + /** Optional. Describes the parameters to the function in JSON Schema format. The schema must describe an object where the properties are the parameters to the function. For example: ``` { "type": "object", "properties": { "name": { "type": "string" }, "age": { "type": "integer" } }, "additionalProperties": false, "required": ["name", "age"], "propertyOrdering": ["name", "age"] } ``` This field is mutually exclusive with `parameters`. */ + parametersJsonSchema?: unknown; + /** Optional. Describes the output from this function in JSON Schema format. Reflects the Open API 3.03 Response Object. The Schema defines the type used for the response value of the function. */ + response?: Schema; + /** Optional. Describes the output from this function in JSON Schema format. The value specified by the schema is the response value of the function. This field is mutually exclusive with `response`. */ + responseJsonSchema?: unknown; + /** Optional. Specifies the function Behavior. Currently only supported by the BidiGenerateContent method. This field is not supported in Vertex AI. */ + behavior?: Behavior; +} + +/** A function response. */ +declare class FunctionResponse { + /** Signals that function call continues, and more responses will be returned, turning the function call into a generator. Is only applicable to NON_BLOCKING function calls (see FunctionDeclaration.behavior for details), ignored otherwise. If false, the default, future responses will not be considered. Is only applicable to NON_BLOCKING function calls, is ignored otherwise. If set to false, future responses will not be considered. It is allowed to return empty `response` with `will_continue=False` to signal that the function call is finished. */ + willContinue?: boolean; + /** Specifies how the response should be scheduled in the conversation. Only applicable to NON_BLOCKING function calls, is ignored otherwise. Defaults to WHEN_IDLE. */ + scheduling?: FunctionResponseScheduling; + /** List of parts that constitute a function response. Each part may + have a different IANA MIME type. */ + parts?: FunctionResponsePart[]; + /** Optional. The id of the function call this response is for. Populated by the client to match the corresponding function call `id`. */ + id?: string; + /** Required. The name of the function to call. Matches [FunctionDeclaration.name] and [FunctionCall.name]. */ + name?: string; + /** Required. The function response in JSON object format. Use "output" key to specify function output and "error" key to specify error details (if any). If "output" and "error" keys are not specified, then whole "response" is treated as function output. */ + response?: Record<string, unknown>; +} + +/** Raw media bytes for function response. + + Text should not be sent as raw bytes, use the FunctionResponse.response + field. */ +declare class FunctionResponseBlob { + /** Required. The IANA standard MIME type of the source data. */ + mimeType?: string; + /** Required. Inline media bytes. + * @remarks Encoded as base64 string. */ + data?: string; + /** Optional. Display name of the blob. + Used to provide a label or filename to distinguish blobs. */ + displayName?: string; +} + +/** URI based data for function response. */ +declare class FunctionResponseFileData { + /** Required. URI. */ + fileUri?: string; + /** Required. The IANA standard MIME type of the source data. */ + mimeType?: string; + /** Optional. Display name of the file. + Used to provide a label or filename to distinguish files. */ + displayName?: string; +} + +/** A datatype containing media that is part of a `FunctionResponse` message. + + A `FunctionResponsePart` consists of data which has an associated datatype. A + `FunctionResponsePart` can only contain one of the accepted types in + `FunctionResponsePart.data`. + + A `FunctionResponsePart` must have a fixed IANA MIME type identifying the + type and subtype of the media if the `inline_data` field is filled with raw + bytes. */ +declare class FunctionResponsePart { + /** Optional. Inline media bytes. */ + inlineData?: FunctionResponseBlob; + /** Optional. URI based data. */ + fileData?: FunctionResponseFileData; +} + +/** Specifies how the response should be scheduled in the conversation. */ +declare enum FunctionResponseScheduling { + /** + * This value is unused. + */ + SCHEDULING_UNSPECIFIED = "SCHEDULING_UNSPECIFIED", + /** + * Only add the result to the conversation context, do not interrupt or trigger generation. + */ + SILENT = "SILENT", + /** + * Add the result to the conversation context, and prompt to generate output without interrupting ongoing generation. + */ + WHEN_IDLE = "WHEN_IDLE", + /** + * Add the result to the conversation context, interrupt ongoing generation and prompt to generate output. + */ + INTERRUPT = "INTERRUPT" +} + +/** Generation config. */ +declare interface GenerationConfig { + /** Optional. Config for model selection. */ + modelSelectionConfig?: ModelSelectionConfig; + /** Output schema of the generated response. This is an alternative to + `response_schema` that accepts [JSON Schema](https://json-schema.org/). + */ + responseJsonSchema?: unknown; + /** Optional. If enabled, audio timestamp will be included in the request to the model. This field is not supported in Gemini API. */ + audioTimestamp?: boolean; + /** Optional. Number of candidates to generate. */ + candidateCount?: number; + /** Optional. If enabled, the model will detect emotions and adapt its responses accordingly. This field is not supported in Gemini API. */ + enableAffectiveDialog?: boolean; + /** Optional. Frequency penalties. */ + frequencyPenalty?: number; + /** Optional. Logit probabilities. */ + logprobs?: number; + /** Optional. The maximum number of output tokens to generate per message. */ + maxOutputTokens?: number; + /** Optional. If specified, the media resolution specified will be used. */ + mediaResolution?: MediaResolution; + /** Optional. Positive penalties. */ + presencePenalty?: number; + /** Optional. If true, export the logprobs results in response. */ + responseLogprobs?: boolean; + /** Optional. Output response mimetype of the generated candidate text. Supported mimetype: - `text/plain`: (default) Text output. - `application/json`: JSON response in the candidates. The model needs to be prompted to output the appropriate response type, otherwise the behavior is undefined. This is a preview feature. */ + responseMimeType?: string; + /** Optional. The modalities of the response. */ + responseModalities?: Modality[]; + /** Optional. The `Schema` object allows the definition of input and output data types. These types can be objects, but also primitives and arrays. Represents a select subset of an [OpenAPI 3.0 schema object](https://spec.openapis.org/oas/v3.0.3#schema). If set, a compatible response_mime_type must also be set. Compatible mimetypes: `application/json`: Schema for JSON response. */ + responseSchema?: Schema; + /** Optional. Routing configuration. This field is not supported in Gemini API. */ + routingConfig?: GenerationConfigRoutingConfig; + /** Optional. Seed. */ + seed?: number; + /** Optional. The speech generation config. */ + speechConfig?: SpeechConfig; + /** Optional. Stop sequences. */ + stopSequences?: string[]; + /** Optional. Controls the randomness of predictions. */ + temperature?: number; + /** Optional. Config for thinking features. An error will be returned if this field is set for models that don't support thinking. */ + thinkingConfig?: ThinkingConfig; + /** Optional. If specified, top-k sampling will be used. */ + topK?: number; + /** Optional. If specified, nucleus sampling will be used. */ + topP?: number; + /** Optional. Enables enhanced civic answers. It may not be available for all models. This field is not supported in Vertex AI. */ + enableEnhancedCivicAnswers?: boolean; +} + +/** The configuration for routing the request to a specific model. This data type is not supported in Gemini API. */ +declare interface GenerationConfigRoutingConfig { + /** Automated routing. */ + autoMode?: GenerationConfigRoutingConfigAutoRoutingMode; + /** Manual routing. */ + manualMode?: GenerationConfigRoutingConfigManualRoutingMode; +} + +/** When automated routing is specified, the routing will be determined by the pretrained routing model and customer provided model routing preference. This data type is not supported in Gemini API. */ +declare interface GenerationConfigRoutingConfigAutoRoutingMode { + /** The model routing preference. */ + modelRoutingPreference?: 'UNKNOWN' | 'PRIORITIZE_QUALITY' | 'BALANCED' | 'PRIORITIZE_COST'; +} + +/** When manual routing is set, the specified model will be used directly. This data type is not supported in Gemini API. */ +declare interface GenerationConfigRoutingConfigManualRoutingMode { + /** The model name to use. Only the public LLM models are accepted. See [Supported models](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference#supported-models). */ + modelName?: string; +} + +/** Tool to retrieve public maps data for grounding, powered by Google. */ +declare interface GoogleMaps { + /** The authentication config to access the API. Only API key is supported. This field is not supported in Gemini API. */ + authConfig?: AuthConfig; + /** Optional. If true, include the widget context token in the response. */ + enableWidget?: boolean; +} + +/** GoogleSearch tool type. Tool to support Google Search in Model. Powered by Google. */ +declare interface GoogleSearch { + /** Optional. List of domains to be excluded from the search results. The default limit is 2000 domains. Example: ["amazon.com", "facebook.com"]. This field is not supported in Gemini API. */ + excludeDomains?: string[]; + /** Optional. Sites with confidence level chosen & above this value will be blocked from the search results. This field is not supported in Gemini API. */ + blockingConfidence?: PhishBlockThreshold; + /** Optional. Filter search results to a specific time range. If customers set a start time, they must set an end time (and vice versa). This field is not supported in Vertex AI. */ + timeRangeFilter?: Interval; +} + +/** Tool to retrieve public web data for grounding, powered by Google. */ +declare interface GoogleSearchRetrieval { + /** Specifies the dynamic retrieval configuration for the given source. */ + dynamicRetrievalConfig?: DynamicRetrievalConfig; +} + +/** The location of the API key. This enum is not supported in Gemini API. */ +declare enum HttpElementLocation { + HTTP_IN_UNSPECIFIED = "HTTP_IN_UNSPECIFIED", + /** + * Element is in the HTTP request query. + */ + HTTP_IN_QUERY = "HTTP_IN_QUERY", + /** + * Element is in the HTTP request header. + */ + HTTP_IN_HEADER = "HTTP_IN_HEADER", + /** + * Element is in the HTTP request path. + */ + HTTP_IN_PATH = "HTTP_IN_PATH", + /** + * Element is in the HTTP request body. + */ + HTTP_IN_BODY = "HTTP_IN_BODY", + /** + * Element is in the HTTP request cookie. + */ + HTTP_IN_COOKIE = "HTTP_IN_COOKIE" +} + +/** HTTP options to be used in each of the requests. */ +declare interface HttpOptions { + /** The base URL for the AI platform service endpoint. */ + baseUrl?: string; + /** The resource scope used to constructing the resource name when base_url is set */ + baseUrlResourceScope?: ResourceScope; + /** Specifies the version of the API to use. */ + apiVersion?: string; + /** Additional HTTP headers to be sent with the request. */ + headers?: Record<string, string>; + /** Timeout for the request in milliseconds. */ + timeout?: number; + /** Extra parameters to add to the request body. + The structure must match the backend API's request structure. + - VertexAI backend API docs: https://cloud.google.com/vertex-ai/docs/reference/rest + - GeminiAPI backend API docs: https://ai.google.dev/api/rest */ + extraBody?: Record<string, unknown>; + /** HTTP retry options for the request. */ + retryOptions?: HttpRetryOptions; +} + +/** HTTP retry options to be used in each of the requests. */ +declare interface HttpRetryOptions { + /** Maximum number of attempts, including the original request. + If 0 or 1, it means no retries. If not specified, default to 5. */ + attempts?: number; +} + +/** Represents a time interval, encoded as a Timestamp start (inclusive) and a Timestamp end (exclusive). The start must be less than or equal to the end. When the start equals the end, the interval is empty (matches no time). When both start and end are unspecified, the interval matches any time. */ +declare interface Interval { + /** Optional. Exclusive end of the interval. If specified, a Timestamp matching this interval will have to be before the end. */ + endTime?: string; + /** Optional. Inclusive start of the interval. If specified, a Timestamp matching this interval will have to be the same or after the start. */ + startTime?: string; +} + +/** Programming language of the `code`. */ +declare enum Language { + /** + * Unspecified language. This value should not be used. + */ + LANGUAGE_UNSPECIFIED = "LANGUAGE_UNSPECIFIED", + /** + * Python >= 3.10, with numpy and simpy available. + */ + PYTHON = "PYTHON" +} + +/** + * LocalTokenizer for Node.js environment. + * + * Provides local tokenization for Gemini models without requiring API calls. + * Automatically uses Node.js platform (filesystem caching in temp directory). + * + * @example + * ```typescript + * import {LocalTokenizer} from '@google/genai/node'; + * + * const tokenizer = new LocalTokenizer('gemini-2.0-flash-001'); + * const result = await tokenizer.countTokens("What is your name?"); + * console.log(result.totalTokens); // 5 + * ``` + * + * @experimental This API is experimental and may change in future versions. + */ +export declare class LocalTokenizer { + private baseTokenizer; + /** + * Creates a new LocalTokenizer for Node.js. + * + * @param modelName Gemini model name (e.g., 'gemini-2.0-flash-001') + */ + constructor(modelName: string); + /** + * Counts the number of tokens in the given content. + * + * @param contents The contents to tokenize + * @param config Optional configuration for counting tokens + * @return A CountTokensResult containing the total number of tokens + */ + countTokens(contents: ContentListUnion, config?: CountTokensConfig): Promise<CountTokensResult>; + /** + * Computes detailed token information for the given content. + * + * @param contents The contents to tokenize + * @return A ComputeTokensResult containing token IDs, bytes, and roles + */ + computeTokens(contents: ContentListUnion): Promise<ComputeTokensResult>; +} + +/** The media resolution to use. */ +declare enum MediaResolution { + /** + * Media resolution has not been set + */ + MEDIA_RESOLUTION_UNSPECIFIED = "MEDIA_RESOLUTION_UNSPECIFIED", + /** + * Media resolution set to low (64 tokens). + */ + MEDIA_RESOLUTION_LOW = "MEDIA_RESOLUTION_LOW", + /** + * Media resolution set to medium (256 tokens). + */ + MEDIA_RESOLUTION_MEDIUM = "MEDIA_RESOLUTION_MEDIUM", + /** + * Media resolution set to high (zoomed reframing with 256 tokens). + */ + MEDIA_RESOLUTION_HIGH = "MEDIA_RESOLUTION_HIGH" +} + +/** Server content modalities. */ +declare enum Modality { + /** + * The modality is unspecified. + */ + MODALITY_UNSPECIFIED = "MODALITY_UNSPECIFIED", + /** + * Indicates the model should return text + */ + TEXT = "TEXT", + /** + * Indicates the model should return images. + */ + IMAGE = "IMAGE", + /** + * Indicates the model should return audio. + */ + AUDIO = "AUDIO" +} + +/** Config for model selection. */ +declare interface ModelSelectionConfig { + /** Options for feature selection preference. */ + featureSelectionPreference?: FeatureSelectionPreference; +} + +/** Configuration for a multi-speaker text-to-speech request. */ +declare interface MultiSpeakerVoiceConfig { + /** Required. A list of configurations for the voices of the speakers. Exactly two speaker voice configurations must be provided. */ + speakerVoiceConfigs?: SpeakerVoiceConfig[]; +} + +/** Outcome of the code execution. */ +declare enum Outcome { + /** + * Unspecified status. This value should not be used. + */ + OUTCOME_UNSPECIFIED = "OUTCOME_UNSPECIFIED", + /** + * Code execution completed successfully. + */ + OUTCOME_OK = "OUTCOME_OK", + /** + * Code execution finished but with a failure. `stderr` should contain the reason. + */ + OUTCOME_FAILED = "OUTCOME_FAILED", + /** + * Code execution ran for too long, and was cancelled. There may or may not be a partial output present. + */ + OUTCOME_DEADLINE_EXCEEDED = "OUTCOME_DEADLINE_EXCEEDED" +} + +/** A datatype containing media content. + + Exactly one field within a Part should be set, representing the specific type + of content being conveyed. Using multiple fields within the same `Part` + instance is considered invalid. */ +declare interface Part { + /** Media resolution for the input media. + */ + mediaResolution?: PartMediaResolution; + /** Optional. Result of executing the [ExecutableCode]. */ + codeExecutionResult?: CodeExecutionResult; + /** Optional. Code generated by the model that is meant to be executed. */ + executableCode?: ExecutableCode; + /** Optional. URI based data. */ + fileData?: FileData; + /** Optional. A predicted [FunctionCall] returned from the model that contains a string representing the [FunctionDeclaration.name] with the parameters and their values. */ + functionCall?: FunctionCall; + /** Optional. The result output of a [FunctionCall] that contains a string representing the [FunctionDeclaration.name] and a structured JSON object containing any output from the function call. It is used as context to the model. */ + functionResponse?: FunctionResponse; + /** Optional. Inlined bytes data. */ + inlineData?: Blob_2; + /** Optional. Text part (can be code). */ + text?: string; + /** Optional. Indicates if the part is thought from the model. */ + thought?: boolean; + /** Optional. An opaque signature for the thought so it can be reused in subsequent requests. + * @remarks Encoded as base64 string. */ + thoughtSignature?: string; + /** Optional. Video metadata. The metadata should only be specified while the video data is presented in inline_data or file_data. */ + videoMetadata?: VideoMetadata; +} + +/** Partial argument value of the function call. This data type is not supported in Gemini API. */ +declare interface PartialArg { + /** Optional. Represents a null value. */ + nullValue?: 'NULL_VALUE'; + /** Optional. Represents a double value. */ + numberValue?: number; + /** Optional. Represents a string value. */ + stringValue?: string; + /** Optional. Represents a boolean value. */ + boolValue?: boolean; + /** Required. A JSON Path (RFC 9535) to the argument being streamed. https://datatracker.ietf.org/doc/html/rfc9535. e.g. "$.foo.bar[0].data". */ + jsonPath?: string; + /** Optional. Whether this is not the last part of the same json_path. If true, another PartialArg message for the current json_path is expected to follow. */ + willContinue?: boolean; +} + +/** Media resolution for the input media. */ +declare interface PartMediaResolution { + /** The tokenization quality used for given media. + */ + level?: PartMediaResolutionLevel; + /** Specifies the required sequence length for media tokenization. + */ + numTokens?: number; +} + +/** The tokenization quality used for given media. */ +declare enum PartMediaResolutionLevel { + /** + * Media resolution has not been set. + */ + MEDIA_RESOLUTION_UNSPECIFIED = "MEDIA_RESOLUTION_UNSPECIFIED", + /** + * Media resolution set to low. + */ + MEDIA_RESOLUTION_LOW = "MEDIA_RESOLUTION_LOW", + /** + * Media resolution set to medium. + */ + MEDIA_RESOLUTION_MEDIUM = "MEDIA_RESOLUTION_MEDIUM", + /** + * Media resolution set to high. + */ + MEDIA_RESOLUTION_HIGH = "MEDIA_RESOLUTION_HIGH", + /** + * Media resolution set to ultra high. + */ + MEDIA_RESOLUTION_ULTRA_HIGH = "MEDIA_RESOLUTION_ULTRA_HIGH" +} + +declare type PartUnion = Part | string; + +/** Sites with confidence level chosen & above this value will be blocked from the search results. This enum is not supported in Gemini API. */ +declare enum PhishBlockThreshold { + /** + * Defaults to unspecified. + */ + PHISH_BLOCK_THRESHOLD_UNSPECIFIED = "PHISH_BLOCK_THRESHOLD_UNSPECIFIED", + /** + * Blocks Low and above confidence URL that is risky. + */ + BLOCK_LOW_AND_ABOVE = "BLOCK_LOW_AND_ABOVE", + /** + * Blocks Medium and above confidence URL that is risky. + */ + BLOCK_MEDIUM_AND_ABOVE = "BLOCK_MEDIUM_AND_ABOVE", + /** + * Blocks High and above confidence URL that is risky. + */ + BLOCK_HIGH_AND_ABOVE = "BLOCK_HIGH_AND_ABOVE", + /** + * Blocks Higher and above confidence URL that is risky. + */ + BLOCK_HIGHER_AND_ABOVE = "BLOCK_HIGHER_AND_ABOVE", + /** + * Blocks Very high and above confidence URL that is risky. + */ + BLOCK_VERY_HIGH_AND_ABOVE = "BLOCK_VERY_HIGH_AND_ABOVE", + /** + * Blocks Extremely high confidence URL that is risky. + */ + BLOCK_ONLY_EXTREMELY_HIGH = "BLOCK_ONLY_EXTREMELY_HIGH" +} + +/** The configuration for the prebuilt speaker to use. */ +declare interface PrebuiltVoiceConfig { + /** The name of the preset voice to use. */ + voiceName?: string; +} + +/** Specifies the context retrieval config. This data type is not supported in Gemini API. */ +declare interface RagRetrievalConfig { + /** Optional. Config for filters. */ + filter?: RagRetrievalConfigFilter; + /** Optional. Config for Hybrid Search. */ + hybridSearch?: RagRetrievalConfigHybridSearch; + /** Optional. Config for ranking and reranking. */ + ranking?: RagRetrievalConfigRanking; + /** Optional. The number of contexts to retrieve. */ + topK?: number; +} + +/** Config for filters. This data type is not supported in Gemini API. */ +declare interface RagRetrievalConfigFilter { + /** Optional. String for metadata filtering. */ + metadataFilter?: string; + /** Optional. Only returns contexts with vector distance smaller than the threshold. */ + vectorDistanceThreshold?: number; + /** Optional. Only returns contexts with vector similarity larger than the threshold. */ + vectorSimilarityThreshold?: number; +} + +/** Config for Hybrid Search. This data type is not supported in Gemini API. */ +declare interface RagRetrievalConfigHybridSearch { + /** Optional. Alpha value controls the weight between dense and sparse vector search results. The range is [0, 1], while 0 means sparse vector search only and 1 means dense vector search only. The default value is 0.5 which balances sparse and dense vector search equally. */ + alpha?: number; +} + +/** Config for ranking and reranking. This data type is not supported in Gemini API. */ +declare interface RagRetrievalConfigRanking { + /** Optional. Config for LlmRanker. */ + llmRanker?: RagRetrievalConfigRankingLlmRanker; + /** Optional. Config for Rank Service. */ + rankService?: RagRetrievalConfigRankingRankService; +} + +/** Config for LlmRanker. This data type is not supported in Gemini API. */ +declare interface RagRetrievalConfigRankingLlmRanker { + /** Optional. The model name used for ranking. See [Supported models](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference#supported-models). */ + modelName?: string; +} + +/** Config for Rank Service. This data type is not supported in Gemini API. */ +declare interface RagRetrievalConfigRankingRankService { + /** Optional. The model name of the rank service. Format: `semantic-ranker-512@latest` */ + modelName?: string; +} + +/** ReplicatedVoiceConfig is used to configure replicated voice. */ +declare interface ReplicatedVoiceConfig { + /** The mime type of the replicated voice. + */ + mimeType?: string; + /** The sample audio of the replicated voice. + + * @remarks Encoded as base64 string. */ + voiceSampleAudio?: string; +} + +/** Resource scope. */ +declare enum ResourceScope { + /** + * When setting base_url, this value configures resource scope to be the collection. + The resource name will not include api version, project, or location. + For example, if base_url is set to "https://aiplatform.googleapis.com", + then the resource name for a Model would be + "https://aiplatform.googleapis.com/publishers/google/models/gemini-3-pro-preview + */ + COLLECTION = "COLLECTION" +} + +/** Defines a retrieval tool that model can call to access external knowledge. This data type is not supported in Gemini API. */ +declare interface Retrieval { + /** Optional. Deprecated. This option is no longer supported. */ + disableAttribution?: boolean; + /** Use data source powered by external API for grounding. */ + externalApi?: ExternalApi; + /** Set to use data source powered by Vertex AI Search. */ + vertexAiSearch?: VertexAISearch; + /** Set to use data source powered by Vertex RAG store. User data is uploaded via the VertexRagDataService. */ + vertexRagStore?: VertexRagStore; +} + +/** Schema is used to define the format of input/output data. + + Represents a select subset of an [OpenAPI 3.0 schema + object](https://spec.openapis.org/oas/v3.0.3#schema-object). More fields may + be added in the future as needed. */ +declare interface Schema { + /** Optional. The value should be validated against any (one or more) of the subschemas in the list. */ + anyOf?: Schema[]; + /** Optional. Default value of the data. */ + default?: unknown; + /** Optional. The description of the data. */ + description?: string; + /** Optional. Possible values of the element of primitive type with enum format. Examples: 1. We can define direction as : {type:STRING, format:enum, enum:["EAST", NORTH", "SOUTH", "WEST"]} 2. We can define apartment number as : {type:INTEGER, format:enum, enum:["101", "201", "301"]} */ + enum?: string[]; + /** Optional. Example of the object. Will only populated when the object is the root. */ + example?: unknown; + /** Optional. The format of the data. Supported formats: for NUMBER type: "float", "double" for INTEGER type: "int32", "int64" for STRING type: "email", "byte", etc */ + format?: string; + /** Optional. SCHEMA FIELDS FOR TYPE ARRAY Schema of the elements of Type.ARRAY. */ + items?: Schema; + /** Optional. Maximum number of the elements for Type.ARRAY. */ + maxItems?: string; + /** Optional. Maximum length of the Type.STRING */ + maxLength?: string; + /** Optional. Maximum number of the properties for Type.OBJECT. */ + maxProperties?: string; + /** Optional. Maximum value of the Type.INTEGER and Type.NUMBER */ + maximum?: number; + /** Optional. Minimum number of the elements for Type.ARRAY. */ + minItems?: string; + /** Optional. SCHEMA FIELDS FOR TYPE STRING Minimum length of the Type.STRING */ + minLength?: string; + /** Optional. Minimum number of the properties for Type.OBJECT. */ + minProperties?: string; + /** Optional. SCHEMA FIELDS FOR TYPE INTEGER and NUMBER Minimum value of the Type.INTEGER and Type.NUMBER */ + minimum?: number; + /** Optional. Indicates if the value may be null. */ + nullable?: boolean; + /** Optional. Pattern of the Type.STRING to restrict a string to a regular expression. */ + pattern?: string; + /** Optional. SCHEMA FIELDS FOR TYPE OBJECT Properties of Type.OBJECT. */ + properties?: Record<string, Schema>; + /** Optional. The order of the properties. Not a standard field in open api spec. Only used to support the order of the properties. */ + propertyOrdering?: string[]; + /** Optional. Required properties of Type.OBJECT. */ + required?: string[]; + /** Optional. The title of the Schema. */ + title?: string; + /** Optional. The type of the data. */ + type?: Type; +} + +/** Configuration for a single speaker in a multi speaker setup. */ +declare interface SpeakerVoiceConfig { + /** Required. The name of the speaker. This should be the same as the speaker name used in the prompt. */ + speaker?: string; + /** Required. The configuration for the voice of this speaker. */ + voiceConfig?: VoiceConfig; +} + +declare interface SpeechConfig { + /** Configuration for the voice of the response. */ + voiceConfig?: VoiceConfig; + /** Optional. Language code (ISO 639. e.g. en-US) for the speech synthesization. */ + languageCode?: string; + /** The configuration for a multi-speaker text-to-speech request. This field is mutually exclusive with `voice_config`. */ + multiSpeakerVoiceConfig?: MultiSpeakerVoiceConfig; +} + +/** The thinking features configuration. */ +declare interface ThinkingConfig { + /** Indicates whether to include thoughts in the response. If true, thoughts are returned only if the model supports thought and thoughts are available. + */ + includeThoughts?: boolean; + /** Indicates the thinking budget in tokens. 0 is DISABLED. -1 is AUTOMATIC. The default values and allowed ranges are model dependent. + */ + thinkingBudget?: number; + /** Optional. The number of thoughts tokens that the model should generate. */ + thinkingLevel?: ThinkingLevel; +} + +/** The number of thoughts tokens that the model should generate. */ +declare enum ThinkingLevel { + /** + * Unspecified thinking level. + */ + THINKING_LEVEL_UNSPECIFIED = "THINKING_LEVEL_UNSPECIFIED", + /** + * Low thinking level. + */ + LOW = "LOW", + /** + * Medium thinking level. + */ + MEDIUM = "MEDIUM", + /** + * High thinking level. + */ + HIGH = "HIGH", + /** + * MINIMAL thinking level. + */ + MINIMAL = "MINIMAL" +} + +/** Tokens info with a list of tokens and the corresponding list of token ids. */ +export declare interface TokensInfo { + /** Optional fields for the role from the corresponding Content. */ + role?: string; + /** A list of token ids from the input. */ + tokenIds?: string[]; + /** A list of tokens from the input. + * @remarks Encoded as base64 string. */ + tokens?: string[]; +} + +/** Tool details of a tool that the model may use to generate a response. */ +declare interface Tool { + /** Optional. Retrieval tool type. System will always execute the provided retrieval tool(s) to get external knowledge to answer the prompt. Retrieval results are presented to the model for generation. This field is not supported in Gemini API. */ + retrieval?: Retrieval; + /** Optional. Tool to support the model interacting directly with the + computer. If enabled, it automatically populates computer-use specific + Function Declarations. */ + computerUse?: ComputerUse; + /** Optional. Tool to retrieve knowledge from the File Search Stores. */ + fileSearch?: FileSearch; + /** Optional. CodeExecution tool type. Enables the model to execute code as part of generation. */ + codeExecution?: ToolCodeExecution; + /** Optional. Tool to support searching public web data, powered by Vertex AI Search and Sec4 compliance. This field is not supported in Gemini API. */ + enterpriseWebSearch?: EnterpriseWebSearch; + /** Optional. Function tool type. One or more function declarations to be passed to the model along with the current user query. Model may decide to call a subset of these functions by populating FunctionCall in the response. User should provide a FunctionResponse for each function call in the next turn. Based on the function responses, Model will generate the final response back to the user. Maximum 512 function declarations can be provided. */ + functionDeclarations?: FunctionDeclaration[]; + /** Optional. GoogleMaps tool type. Tool to support Google Maps in Model. */ + googleMaps?: GoogleMaps; + /** Optional. GoogleSearch tool type. Tool to support Google Search in Model. Powered by Google. */ + googleSearch?: GoogleSearch; + /** Optional. Specialized retrieval tool that is powered by Google Search. */ + googleSearchRetrieval?: GoogleSearchRetrieval; + /** Optional. Tool to support URL context retrieval. */ + urlContext?: UrlContext; +} + +/** Tool that executes code generated by the model, and automatically returns the result to the model. See also [ExecutableCode]and [CodeExecutionResult] which are input and output to this tool. This data type is not supported in Gemini API. */ +declare interface ToolCodeExecution { +} + +/** The type of the data. */ +declare enum Type { + /** + * Not specified, should not be used. + */ + TYPE_UNSPECIFIED = "TYPE_UNSPECIFIED", + /** + * OpenAPI string type + */ + STRING = "STRING", + /** + * OpenAPI number type + */ + NUMBER = "NUMBER", + /** + * OpenAPI integer type + */ + INTEGER = "INTEGER", + /** + * OpenAPI boolean type + */ + BOOLEAN = "BOOLEAN", + /** + * OpenAPI array type + */ + ARRAY = "ARRAY", + /** + * OpenAPI object type + */ + OBJECT = "OBJECT", + /** + * Null type + */ + NULL = "NULL" +} + +/** Tool to support URL context. */ +declare interface UrlContext { +} + +/** Retrieve from Vertex AI Search datastore or engine for grounding. datastore and engine are mutually exclusive. See https://cloud.google.com/products/agent-builder. This data type is not supported in Gemini API. */ +declare interface VertexAISearch { + /** Specifications that define the specific DataStores to be searched, along with configurations for those data stores. This is only considered for Engines with multiple data stores. It should only be set if engine is used. */ + dataStoreSpecs?: VertexAISearchDataStoreSpec[]; + /** Optional. Fully-qualified Vertex AI Search data store resource ID. Format: `projects/{project}/locations/{location}/collections/{collection}/dataStores/{dataStore}` */ + datastore?: string; + /** Optional. Fully-qualified Vertex AI Search engine resource ID. Format: `projects/{project}/locations/{location}/collections/{collection}/engines/{engine}` */ + engine?: string; + /** Optional. Filter strings to be passed to the search API. */ + filter?: string; + /** Optional. Number of search results to return per query. The default value is 10. The maximumm allowed value is 10. */ + maxResults?: number; +} + +/** Define data stores within engine to filter on in a search call and configurations for those data stores. For more information, see https://cloud.google.com/generative-ai-app-builder/docs/reference/rpc/google.cloud.discoveryengine.v1#datastorespec. This data type is not supported in Gemini API. */ +declare interface VertexAISearchDataStoreSpec { + /** Full resource name of DataStore, such as Format: `projects/{project}/locations/{location}/collections/{collection}/dataStores/{dataStore}` */ + dataStore?: string; + /** Optional. Filter specification to filter documents in the data store specified by data_store field. For more information on filtering, see [Filtering](https://cloud.google.com/generative-ai-app-builder/docs/filter-search-metadata) */ + filter?: string; +} + +/** Retrieve from Vertex RAG Store for grounding. This data type is not supported in Gemini API. */ +declare interface VertexRagStore { + /** Optional. Deprecated. Please use rag_resources instead. */ + ragCorpora?: string[]; + /** Optional. The representation of the rag source. It can be used to specify corpus only or ragfiles. Currently only support one corpus or multiple files from one corpus. In the future we may open up multiple corpora support. */ + ragResources?: VertexRagStoreRagResource[]; + /** Optional. The retrieval config for the Rag query. */ + ragRetrievalConfig?: RagRetrievalConfig; + /** Optional. Number of top k results to return from the selected corpora. */ + similarityTopK?: number; + /** Optional. Currently only supported for Gemini Multimodal Live API. In Gemini Multimodal Live API, if `store_context` bool is specified, Gemini will leverage it to automatically memorize the interactions between the client and Gemini, and retrieve context when needed to augment the response generation for users' ongoing and future interactions. */ + storeContext?: boolean; + /** Optional. Only return results with vector distance smaller than the threshold. */ + vectorDistanceThreshold?: number; +} + +/** The definition of the Rag resource. This data type is not supported in Gemini API. */ +declare interface VertexRagStoreRagResource { + /** Optional. RagCorpora resource name. Format: `projects/{project}/locations/{location}/ragCorpora/{rag_corpus}` */ + ragCorpus?: string; + /** Optional. rag_file_id. The files should be in the same rag_corpus set in rag_corpus field. */ + ragFileIds?: string[]; +} + +/** Metadata describes the input video content. */ +declare interface VideoMetadata { + /** Optional. The end offset of the video. */ + endOffset?: string; + /** Optional. The frame rate of the video sent to the model. If not specified, the default value will be 1.0. The fps range is (0.0, 24.0]. */ + fps?: number; + /** Optional. The start offset of the video. */ + startOffset?: string; +} + +declare interface VoiceConfig { + /** If true, the model will use a replicated voice for the response. */ + replicatedVoiceConfig?: ReplicatedVoiceConfig; + /** The configuration for the prebuilt voice to use. */ + prebuiltVoiceConfig?: PrebuiltVoiceConfig; +} + +export { } diff --git a/server/node_modules/@google/genai/dist/tokenizer/node.mjs b/server/node_modules/@google/genai/dist/tokenizer/node.mjs new file mode 100644 index 0000000..8ec4884 --- /dev/null +++ b/server/node_modules/@google/genai/dist/tokenizer/node.mjs @@ -0,0 +1,5656 @@ +import $protobuf from 'protobufjs/minimal.js'; +import * as crypto from 'crypto'; +import * as fs from 'fs/promises'; +import * as os from 'os'; +import * as path from 'path'; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** Outcome of the code execution. */ +var Outcome; +(function (Outcome) { + /** + * Unspecified status. This value should not be used. + */ + Outcome["OUTCOME_UNSPECIFIED"] = "OUTCOME_UNSPECIFIED"; + /** + * Code execution completed successfully. + */ + Outcome["OUTCOME_OK"] = "OUTCOME_OK"; + /** + * Code execution finished but with a failure. `stderr` should contain the reason. + */ + Outcome["OUTCOME_FAILED"] = "OUTCOME_FAILED"; + /** + * Code execution ran for too long, and was cancelled. There may or may not be a partial output present. + */ + Outcome["OUTCOME_DEADLINE_EXCEEDED"] = "OUTCOME_DEADLINE_EXCEEDED"; +})(Outcome || (Outcome = {})); +/** Programming language of the `code`. */ +var Language; +(function (Language) { + /** + * Unspecified language. This value should not be used. + */ + Language["LANGUAGE_UNSPECIFIED"] = "LANGUAGE_UNSPECIFIED"; + /** + * Python >= 3.10, with numpy and simpy available. + */ + Language["PYTHON"] = "PYTHON"; +})(Language || (Language = {})); +/** Specifies how the response should be scheduled in the conversation. */ +var FunctionResponseScheduling; +(function (FunctionResponseScheduling) { + /** + * This value is unused. + */ + FunctionResponseScheduling["SCHEDULING_UNSPECIFIED"] = "SCHEDULING_UNSPECIFIED"; + /** + * Only add the result to the conversation context, do not interrupt or trigger generation. + */ + FunctionResponseScheduling["SILENT"] = "SILENT"; + /** + * Add the result to the conversation context, and prompt to generate output without interrupting ongoing generation. + */ + FunctionResponseScheduling["WHEN_IDLE"] = "WHEN_IDLE"; + /** + * Add the result to the conversation context, interrupt ongoing generation and prompt to generate output. + */ + FunctionResponseScheduling["INTERRUPT"] = "INTERRUPT"; +})(FunctionResponseScheduling || (FunctionResponseScheduling = {})); +/** The type of the data. */ +var Type; +(function (Type) { + /** + * Not specified, should not be used. + */ + Type["TYPE_UNSPECIFIED"] = "TYPE_UNSPECIFIED"; + /** + * OpenAPI string type + */ + Type["STRING"] = "STRING"; + /** + * OpenAPI number type + */ + Type["NUMBER"] = "NUMBER"; + /** + * OpenAPI integer type + */ + Type["INTEGER"] = "INTEGER"; + /** + * OpenAPI boolean type + */ + Type["BOOLEAN"] = "BOOLEAN"; + /** + * OpenAPI array type + */ + Type["ARRAY"] = "ARRAY"; + /** + * OpenAPI object type + */ + Type["OBJECT"] = "OBJECT"; + /** + * Null type + */ + Type["NULL"] = "NULL"; +})(Type || (Type = {})); +/** The API spec that the external API implements. This enum is not supported in Gemini API. */ +var ApiSpec; +(function (ApiSpec) { + /** + * Unspecified API spec. This value should not be used. + */ + ApiSpec["API_SPEC_UNSPECIFIED"] = "API_SPEC_UNSPECIFIED"; + /** + * Simple search API spec. + */ + ApiSpec["SIMPLE_SEARCH"] = "SIMPLE_SEARCH"; + /** + * Elastic search API spec. + */ + ApiSpec["ELASTIC_SEARCH"] = "ELASTIC_SEARCH"; +})(ApiSpec || (ApiSpec = {})); +/** Type of auth scheme. This enum is not supported in Gemini API. */ +var AuthType; +(function (AuthType) { + AuthType["AUTH_TYPE_UNSPECIFIED"] = "AUTH_TYPE_UNSPECIFIED"; + /** + * No Auth. + */ + AuthType["NO_AUTH"] = "NO_AUTH"; + /** + * API Key Auth. + */ + AuthType["API_KEY_AUTH"] = "API_KEY_AUTH"; + /** + * HTTP Basic Auth. + */ + AuthType["HTTP_BASIC_AUTH"] = "HTTP_BASIC_AUTH"; + /** + * Google Service Account Auth. + */ + AuthType["GOOGLE_SERVICE_ACCOUNT_AUTH"] = "GOOGLE_SERVICE_ACCOUNT_AUTH"; + /** + * OAuth auth. + */ + AuthType["OAUTH"] = "OAUTH"; + /** + * OpenID Connect (OIDC) Auth. + */ + AuthType["OIDC_AUTH"] = "OIDC_AUTH"; +})(AuthType || (AuthType = {})); +/** The location of the API key. This enum is not supported in Gemini API. */ +var HttpElementLocation; +(function (HttpElementLocation) { + HttpElementLocation["HTTP_IN_UNSPECIFIED"] = "HTTP_IN_UNSPECIFIED"; + /** + * Element is in the HTTP request query. + */ + HttpElementLocation["HTTP_IN_QUERY"] = "HTTP_IN_QUERY"; + /** + * Element is in the HTTP request header. + */ + HttpElementLocation["HTTP_IN_HEADER"] = "HTTP_IN_HEADER"; + /** + * Element is in the HTTP request path. + */ + HttpElementLocation["HTTP_IN_PATH"] = "HTTP_IN_PATH"; + /** + * Element is in the HTTP request body. + */ + HttpElementLocation["HTTP_IN_BODY"] = "HTTP_IN_BODY"; + /** + * Element is in the HTTP request cookie. + */ + HttpElementLocation["HTTP_IN_COOKIE"] = "HTTP_IN_COOKIE"; +})(HttpElementLocation || (HttpElementLocation = {})); +/** Sites with confidence level chosen & above this value will be blocked from the search results. This enum is not supported in Gemini API. */ +var PhishBlockThreshold; +(function (PhishBlockThreshold) { + /** + * Defaults to unspecified. + */ + PhishBlockThreshold["PHISH_BLOCK_THRESHOLD_UNSPECIFIED"] = "PHISH_BLOCK_THRESHOLD_UNSPECIFIED"; + /** + * Blocks Low and above confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_LOW_AND_ABOVE"] = "BLOCK_LOW_AND_ABOVE"; + /** + * Blocks Medium and above confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_MEDIUM_AND_ABOVE"] = "BLOCK_MEDIUM_AND_ABOVE"; + /** + * Blocks High and above confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_HIGH_AND_ABOVE"] = "BLOCK_HIGH_AND_ABOVE"; + /** + * Blocks Higher and above confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_HIGHER_AND_ABOVE"] = "BLOCK_HIGHER_AND_ABOVE"; + /** + * Blocks Very high and above confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_VERY_HIGH_AND_ABOVE"] = "BLOCK_VERY_HIGH_AND_ABOVE"; + /** + * Blocks Extremely high confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_ONLY_EXTREMELY_HIGH"] = "BLOCK_ONLY_EXTREMELY_HIGH"; +})(PhishBlockThreshold || (PhishBlockThreshold = {})); +/** Specifies the function Behavior. Currently only supported by the BidiGenerateContent method. This enum is not supported in Vertex AI. */ +var Behavior; +(function (Behavior) { + /** + * This value is unused. + */ + Behavior["UNSPECIFIED"] = "UNSPECIFIED"; + /** + * If set, the system will wait to receive the function response before continuing the conversation. + */ + Behavior["BLOCKING"] = "BLOCKING"; + /** + * If set, the system will not wait to receive the function response. Instead, it will attempt to handle function responses as they become available while maintaining the conversation between the user and the model. + */ + Behavior["NON_BLOCKING"] = "NON_BLOCKING"; +})(Behavior || (Behavior = {})); +/** The mode of the predictor to be used in dynamic retrieval. */ +var DynamicRetrievalConfigMode; +(function (DynamicRetrievalConfigMode) { + /** + * Always trigger retrieval. + */ + DynamicRetrievalConfigMode["MODE_UNSPECIFIED"] = "MODE_UNSPECIFIED"; + /** + * Run retrieval only when system decides it is necessary. + */ + DynamicRetrievalConfigMode["MODE_DYNAMIC"] = "MODE_DYNAMIC"; +})(DynamicRetrievalConfigMode || (DynamicRetrievalConfigMode = {})); +/** Function calling mode. */ +var FunctionCallingConfigMode; +(function (FunctionCallingConfigMode) { + /** + * Unspecified function calling mode. This value should not be used. + */ + FunctionCallingConfigMode["MODE_UNSPECIFIED"] = "MODE_UNSPECIFIED"; + /** + * Default model behavior, model decides to predict either function calls or natural language response. + */ + FunctionCallingConfigMode["AUTO"] = "AUTO"; + /** + * Model is constrained to always predicting function calls only. If "allowed_function_names" are set, the predicted function calls will be limited to any one of "allowed_function_names", else the predicted function calls will be any one of the provided "function_declarations". + */ + FunctionCallingConfigMode["ANY"] = "ANY"; + /** + * Model will not predict any function calls. Model behavior is same as when not passing any function declarations. + */ + FunctionCallingConfigMode["NONE"] = "NONE"; + /** + * Model is constrained to predict either function calls or natural language response. If "allowed_function_names" are set, the predicted function calls will be limited to any one of "allowed_function_names", else the predicted function calls will be any one of the provided "function_declarations". + */ + FunctionCallingConfigMode["VALIDATED"] = "VALIDATED"; +})(FunctionCallingConfigMode || (FunctionCallingConfigMode = {})); +/** The number of thoughts tokens that the model should generate. */ +var ThinkingLevel; +(function (ThinkingLevel) { + /** + * Unspecified thinking level. + */ + ThinkingLevel["THINKING_LEVEL_UNSPECIFIED"] = "THINKING_LEVEL_UNSPECIFIED"; + /** + * Low thinking level. + */ + ThinkingLevel["LOW"] = "LOW"; + /** + * Medium thinking level. + */ + ThinkingLevel["MEDIUM"] = "MEDIUM"; + /** + * High thinking level. + */ + ThinkingLevel["HIGH"] = "HIGH"; + /** + * MINIMAL thinking level. + */ + ThinkingLevel["MINIMAL"] = "MINIMAL"; +})(ThinkingLevel || (ThinkingLevel = {})); +/** Harm category. */ +var HarmCategory; +(function (HarmCategory) { + /** + * The harm category is unspecified. + */ + HarmCategory["HARM_CATEGORY_UNSPECIFIED"] = "HARM_CATEGORY_UNSPECIFIED"; + /** + * The harm category is harassment. + */ + HarmCategory["HARM_CATEGORY_HARASSMENT"] = "HARM_CATEGORY_HARASSMENT"; + /** + * The harm category is hate speech. + */ + HarmCategory["HARM_CATEGORY_HATE_SPEECH"] = "HARM_CATEGORY_HATE_SPEECH"; + /** + * The harm category is sexually explicit content. + */ + HarmCategory["HARM_CATEGORY_SEXUALLY_EXPLICIT"] = "HARM_CATEGORY_SEXUALLY_EXPLICIT"; + /** + * The harm category is dangerous content. + */ + HarmCategory["HARM_CATEGORY_DANGEROUS_CONTENT"] = "HARM_CATEGORY_DANGEROUS_CONTENT"; + /** + * Deprecated: Election filter is not longer supported. The harm category is civic integrity. + */ + HarmCategory["HARM_CATEGORY_CIVIC_INTEGRITY"] = "HARM_CATEGORY_CIVIC_INTEGRITY"; + /** + * The harm category is image hate. This enum value is not supported in Gemini API. + */ + HarmCategory["HARM_CATEGORY_IMAGE_HATE"] = "HARM_CATEGORY_IMAGE_HATE"; + /** + * The harm category is image dangerous content. This enum value is not supported in Gemini API. + */ + HarmCategory["HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT"] = "HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT"; + /** + * The harm category is image harassment. This enum value is not supported in Gemini API. + */ + HarmCategory["HARM_CATEGORY_IMAGE_HARASSMENT"] = "HARM_CATEGORY_IMAGE_HARASSMENT"; + /** + * The harm category is image sexually explicit content. This enum value is not supported in Gemini API. + */ + HarmCategory["HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT"] = "HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT"; + /** + * The harm category is for jailbreak prompts. This enum value is not supported in Gemini API. + */ + HarmCategory["HARM_CATEGORY_JAILBREAK"] = "HARM_CATEGORY_JAILBREAK"; +})(HarmCategory || (HarmCategory = {})); +/** Specify if the threshold is used for probability or severity score. If not specified, the threshold is used for probability score. This enum is not supported in Gemini API. */ +var HarmBlockMethod; +(function (HarmBlockMethod) { + /** + * The harm block method is unspecified. + */ + HarmBlockMethod["HARM_BLOCK_METHOD_UNSPECIFIED"] = "HARM_BLOCK_METHOD_UNSPECIFIED"; + /** + * The harm block method uses both probability and severity scores. + */ + HarmBlockMethod["SEVERITY"] = "SEVERITY"; + /** + * The harm block method uses the probability score. + */ + HarmBlockMethod["PROBABILITY"] = "PROBABILITY"; +})(HarmBlockMethod || (HarmBlockMethod = {})); +/** The harm block threshold. */ +var HarmBlockThreshold; +(function (HarmBlockThreshold) { + /** + * Unspecified harm block threshold. + */ + HarmBlockThreshold["HARM_BLOCK_THRESHOLD_UNSPECIFIED"] = "HARM_BLOCK_THRESHOLD_UNSPECIFIED"; + /** + * Block low threshold and above (i.e. block more). + */ + HarmBlockThreshold["BLOCK_LOW_AND_ABOVE"] = "BLOCK_LOW_AND_ABOVE"; + /** + * Block medium threshold and above. + */ + HarmBlockThreshold["BLOCK_MEDIUM_AND_ABOVE"] = "BLOCK_MEDIUM_AND_ABOVE"; + /** + * Block only high threshold (i.e. block less). + */ + HarmBlockThreshold["BLOCK_ONLY_HIGH"] = "BLOCK_ONLY_HIGH"; + /** + * Block none. + */ + HarmBlockThreshold["BLOCK_NONE"] = "BLOCK_NONE"; + /** + * Turn off the safety filter. + */ + HarmBlockThreshold["OFF"] = "OFF"; +})(HarmBlockThreshold || (HarmBlockThreshold = {})); +/** Output only. The reason why the model stopped generating tokens. + +If empty, the model has not stopped generating the tokens. */ +var FinishReason; +(function (FinishReason) { + /** + * The finish reason is unspecified. + */ + FinishReason["FINISH_REASON_UNSPECIFIED"] = "FINISH_REASON_UNSPECIFIED"; + /** + * Token generation reached a natural stopping point or a configured stop sequence. + */ + FinishReason["STOP"] = "STOP"; + /** + * Token generation reached the configured maximum output tokens. + */ + FinishReason["MAX_TOKENS"] = "MAX_TOKENS"; + /** + * Token generation stopped because the content potentially contains safety violations. NOTE: When streaming, [content][] is empty if content filters blocks the output. + */ + FinishReason["SAFETY"] = "SAFETY"; + /** + * The token generation stopped because of potential recitation. + */ + FinishReason["RECITATION"] = "RECITATION"; + /** + * The token generation stopped because of using an unsupported language. + */ + FinishReason["LANGUAGE"] = "LANGUAGE"; + /** + * All other reasons that stopped the token generation. + */ + FinishReason["OTHER"] = "OTHER"; + /** + * Token generation stopped because the content contains forbidden terms. + */ + FinishReason["BLOCKLIST"] = "BLOCKLIST"; + /** + * Token generation stopped for potentially containing prohibited content. + */ + FinishReason["PROHIBITED_CONTENT"] = "PROHIBITED_CONTENT"; + /** + * Token generation stopped because the content potentially contains Sensitive Personally Identifiable Information (SPII). + */ + FinishReason["SPII"] = "SPII"; + /** + * The function call generated by the model is invalid. + */ + FinishReason["MALFORMED_FUNCTION_CALL"] = "MALFORMED_FUNCTION_CALL"; + /** + * Token generation stopped because generated images have safety violations. + */ + FinishReason["IMAGE_SAFETY"] = "IMAGE_SAFETY"; + /** + * The tool call generated by the model is invalid. + */ + FinishReason["UNEXPECTED_TOOL_CALL"] = "UNEXPECTED_TOOL_CALL"; + /** + * Image generation stopped because the generated images have prohibited content. + */ + FinishReason["IMAGE_PROHIBITED_CONTENT"] = "IMAGE_PROHIBITED_CONTENT"; + /** + * The model was expected to generate an image, but none was generated. + */ + FinishReason["NO_IMAGE"] = "NO_IMAGE"; + /** + * Image generation stopped because the generated image may be a recitation from a source. + */ + FinishReason["IMAGE_RECITATION"] = "IMAGE_RECITATION"; + /** + * Image generation stopped for a reason not otherwise specified. + */ + FinishReason["IMAGE_OTHER"] = "IMAGE_OTHER"; +})(FinishReason || (FinishReason = {})); +/** Output only. Harm probability levels in the content. */ +var HarmProbability; +(function (HarmProbability) { + /** + * Harm probability unspecified. + */ + HarmProbability["HARM_PROBABILITY_UNSPECIFIED"] = "HARM_PROBABILITY_UNSPECIFIED"; + /** + * Negligible level of harm. + */ + HarmProbability["NEGLIGIBLE"] = "NEGLIGIBLE"; + /** + * Low level of harm. + */ + HarmProbability["LOW"] = "LOW"; + /** + * Medium level of harm. + */ + HarmProbability["MEDIUM"] = "MEDIUM"; + /** + * High level of harm. + */ + HarmProbability["HIGH"] = "HIGH"; +})(HarmProbability || (HarmProbability = {})); +/** Output only. Harm severity levels in the content. This enum is not supported in Gemini API. */ +var HarmSeverity; +(function (HarmSeverity) { + /** + * Harm severity unspecified. + */ + HarmSeverity["HARM_SEVERITY_UNSPECIFIED"] = "HARM_SEVERITY_UNSPECIFIED"; + /** + * Negligible level of harm severity. + */ + HarmSeverity["HARM_SEVERITY_NEGLIGIBLE"] = "HARM_SEVERITY_NEGLIGIBLE"; + /** + * Low level of harm severity. + */ + HarmSeverity["HARM_SEVERITY_LOW"] = "HARM_SEVERITY_LOW"; + /** + * Medium level of harm severity. + */ + HarmSeverity["HARM_SEVERITY_MEDIUM"] = "HARM_SEVERITY_MEDIUM"; + /** + * High level of harm severity. + */ + HarmSeverity["HARM_SEVERITY_HIGH"] = "HARM_SEVERITY_HIGH"; +})(HarmSeverity || (HarmSeverity = {})); +/** Status of the url retrieval. */ +var UrlRetrievalStatus; +(function (UrlRetrievalStatus) { + /** + * Default value. This value is unused. + */ + UrlRetrievalStatus["URL_RETRIEVAL_STATUS_UNSPECIFIED"] = "URL_RETRIEVAL_STATUS_UNSPECIFIED"; + /** + * Url retrieval is successful. + */ + UrlRetrievalStatus["URL_RETRIEVAL_STATUS_SUCCESS"] = "URL_RETRIEVAL_STATUS_SUCCESS"; + /** + * Url retrieval is failed due to error. + */ + UrlRetrievalStatus["URL_RETRIEVAL_STATUS_ERROR"] = "URL_RETRIEVAL_STATUS_ERROR"; + /** + * Url retrieval is failed because the content is behind paywall. This enum value is not supported in Vertex AI. + */ + UrlRetrievalStatus["URL_RETRIEVAL_STATUS_PAYWALL"] = "URL_RETRIEVAL_STATUS_PAYWALL"; + /** + * Url retrieval is failed because the content is unsafe. This enum value is not supported in Vertex AI. + */ + UrlRetrievalStatus["URL_RETRIEVAL_STATUS_UNSAFE"] = "URL_RETRIEVAL_STATUS_UNSAFE"; +})(UrlRetrievalStatus || (UrlRetrievalStatus = {})); +/** Output only. The reason why the prompt was blocked. */ +var BlockedReason; +(function (BlockedReason) { + /** + * The blocked reason is unspecified. + */ + BlockedReason["BLOCKED_REASON_UNSPECIFIED"] = "BLOCKED_REASON_UNSPECIFIED"; + /** + * The prompt was blocked for safety reasons. + */ + BlockedReason["SAFETY"] = "SAFETY"; + /** + * The prompt was blocked for other reasons. For example, it may be due to the prompt's language, or because it contains other harmful content. + */ + BlockedReason["OTHER"] = "OTHER"; + /** + * The prompt was blocked because it contains a term from the terminology blocklist. + */ + BlockedReason["BLOCKLIST"] = "BLOCKLIST"; + /** + * The prompt was blocked because it contains prohibited content. + */ + BlockedReason["PROHIBITED_CONTENT"] = "PROHIBITED_CONTENT"; + /** + * The prompt was blocked because it contains content that is unsafe for image generation. + */ + BlockedReason["IMAGE_SAFETY"] = "IMAGE_SAFETY"; + /** + * The prompt was blocked by Model Armor. This enum value is not supported in Gemini API. + */ + BlockedReason["MODEL_ARMOR"] = "MODEL_ARMOR"; + /** + * The prompt was blocked as a jailbreak attempt. This enum value is not supported in Gemini API. + */ + BlockedReason["JAILBREAK"] = "JAILBREAK"; +})(BlockedReason || (BlockedReason = {})); +/** Output only. The traffic type for this request. This enum is not supported in Gemini API. */ +var TrafficType; +(function (TrafficType) { + /** + * Unspecified request traffic type. + */ + TrafficType["TRAFFIC_TYPE_UNSPECIFIED"] = "TRAFFIC_TYPE_UNSPECIFIED"; + /** + * The request was processed using Pay-As-You-Go quota. + */ + TrafficType["ON_DEMAND"] = "ON_DEMAND"; + /** + * Type for Provisioned Throughput traffic. + */ + TrafficType["PROVISIONED_THROUGHPUT"] = "PROVISIONED_THROUGHPUT"; +})(TrafficType || (TrafficType = {})); +/** Server content modalities. */ +var Modality; +(function (Modality) { + /** + * The modality is unspecified. + */ + Modality["MODALITY_UNSPECIFIED"] = "MODALITY_UNSPECIFIED"; + /** + * Indicates the model should return text + */ + Modality["TEXT"] = "TEXT"; + /** + * Indicates the model should return images. + */ + Modality["IMAGE"] = "IMAGE"; + /** + * Indicates the model should return audio. + */ + Modality["AUDIO"] = "AUDIO"; +})(Modality || (Modality = {})); +/** The media resolution to use. */ +var MediaResolution; +(function (MediaResolution) { + /** + * Media resolution has not been set + */ + MediaResolution["MEDIA_RESOLUTION_UNSPECIFIED"] = "MEDIA_RESOLUTION_UNSPECIFIED"; + /** + * Media resolution set to low (64 tokens). + */ + MediaResolution["MEDIA_RESOLUTION_LOW"] = "MEDIA_RESOLUTION_LOW"; + /** + * Media resolution set to medium (256 tokens). + */ + MediaResolution["MEDIA_RESOLUTION_MEDIUM"] = "MEDIA_RESOLUTION_MEDIUM"; + /** + * Media resolution set to high (zoomed reframing with 256 tokens). + */ + MediaResolution["MEDIA_RESOLUTION_HIGH"] = "MEDIA_RESOLUTION_HIGH"; +})(MediaResolution || (MediaResolution = {})); +/** Tuning mode. This enum is not supported in Gemini API. */ +var TuningMode; +(function (TuningMode) { + /** + * Tuning mode is unspecified. + */ + TuningMode["TUNING_MODE_UNSPECIFIED"] = "TUNING_MODE_UNSPECIFIED"; + /** + * Full fine-tuning mode. + */ + TuningMode["TUNING_MODE_FULL"] = "TUNING_MODE_FULL"; + /** + * PEFT adapter tuning mode. + */ + TuningMode["TUNING_MODE_PEFT_ADAPTER"] = "TUNING_MODE_PEFT_ADAPTER"; +})(TuningMode || (TuningMode = {})); +/** Adapter size for tuning. This enum is not supported in Gemini API. */ +var AdapterSize; +(function (AdapterSize) { + /** + * Adapter size is unspecified. + */ + AdapterSize["ADAPTER_SIZE_UNSPECIFIED"] = "ADAPTER_SIZE_UNSPECIFIED"; + /** + * Adapter size 1. + */ + AdapterSize["ADAPTER_SIZE_ONE"] = "ADAPTER_SIZE_ONE"; + /** + * Adapter size 2. + */ + AdapterSize["ADAPTER_SIZE_TWO"] = "ADAPTER_SIZE_TWO"; + /** + * Adapter size 4. + */ + AdapterSize["ADAPTER_SIZE_FOUR"] = "ADAPTER_SIZE_FOUR"; + /** + * Adapter size 8. + */ + AdapterSize["ADAPTER_SIZE_EIGHT"] = "ADAPTER_SIZE_EIGHT"; + /** + * Adapter size 16. + */ + AdapterSize["ADAPTER_SIZE_SIXTEEN"] = "ADAPTER_SIZE_SIXTEEN"; + /** + * Adapter size 32. + */ + AdapterSize["ADAPTER_SIZE_THIRTY_TWO"] = "ADAPTER_SIZE_THIRTY_TWO"; +})(AdapterSize || (AdapterSize = {})); +/** Job state. */ +var JobState; +(function (JobState) { + /** + * The job state is unspecified. + */ + JobState["JOB_STATE_UNSPECIFIED"] = "JOB_STATE_UNSPECIFIED"; + /** + * The job has been just created or resumed and processing has not yet begun. + */ + JobState["JOB_STATE_QUEUED"] = "JOB_STATE_QUEUED"; + /** + * The service is preparing to run the job. + */ + JobState["JOB_STATE_PENDING"] = "JOB_STATE_PENDING"; + /** + * The job is in progress. + */ + JobState["JOB_STATE_RUNNING"] = "JOB_STATE_RUNNING"; + /** + * The job completed successfully. + */ + JobState["JOB_STATE_SUCCEEDED"] = "JOB_STATE_SUCCEEDED"; + /** + * The job failed. + */ + JobState["JOB_STATE_FAILED"] = "JOB_STATE_FAILED"; + /** + * The job is being cancelled. From this state the job may only go to either `JOB_STATE_SUCCEEDED`, `JOB_STATE_FAILED` or `JOB_STATE_CANCELLED`. + */ + JobState["JOB_STATE_CANCELLING"] = "JOB_STATE_CANCELLING"; + /** + * The job has been cancelled. + */ + JobState["JOB_STATE_CANCELLED"] = "JOB_STATE_CANCELLED"; + /** + * The job has been stopped, and can be resumed. + */ + JobState["JOB_STATE_PAUSED"] = "JOB_STATE_PAUSED"; + /** + * The job has expired. + */ + JobState["JOB_STATE_EXPIRED"] = "JOB_STATE_EXPIRED"; + /** + * The job is being updated. Only jobs in the `JOB_STATE_RUNNING` state can be updated. After updating, the job goes back to the `JOB_STATE_RUNNING` state. + */ + JobState["JOB_STATE_UPDATING"] = "JOB_STATE_UPDATING"; + /** + * The job is partially succeeded, some results may be missing due to errors. + */ + JobState["JOB_STATE_PARTIALLY_SUCCEEDED"] = "JOB_STATE_PARTIALLY_SUCCEEDED"; +})(JobState || (JobState = {})); +/** The tuning task. Either I2V or T2V. This enum is not supported in Gemini API. */ +var TuningTask; +(function (TuningTask) { + /** + * Default value. This value is unused. + */ + TuningTask["TUNING_TASK_UNSPECIFIED"] = "TUNING_TASK_UNSPECIFIED"; + /** + * Tuning task for image to video. + */ + TuningTask["TUNING_TASK_I2V"] = "TUNING_TASK_I2V"; + /** + * Tuning task for text to video. + */ + TuningTask["TUNING_TASK_T2V"] = "TUNING_TASK_T2V"; + /** + * Tuning task for reference to video. + */ + TuningTask["TUNING_TASK_R2V"] = "TUNING_TASK_R2V"; +})(TuningTask || (TuningTask = {})); +/** The tokenization quality used for given media. */ +var PartMediaResolutionLevel; +(function (PartMediaResolutionLevel) { + /** + * Media resolution has not been set. + */ + PartMediaResolutionLevel["MEDIA_RESOLUTION_UNSPECIFIED"] = "MEDIA_RESOLUTION_UNSPECIFIED"; + /** + * Media resolution set to low. + */ + PartMediaResolutionLevel["MEDIA_RESOLUTION_LOW"] = "MEDIA_RESOLUTION_LOW"; + /** + * Media resolution set to medium. + */ + PartMediaResolutionLevel["MEDIA_RESOLUTION_MEDIUM"] = "MEDIA_RESOLUTION_MEDIUM"; + /** + * Media resolution set to high. + */ + PartMediaResolutionLevel["MEDIA_RESOLUTION_HIGH"] = "MEDIA_RESOLUTION_HIGH"; + /** + * Media resolution set to ultra high. + */ + PartMediaResolutionLevel["MEDIA_RESOLUTION_ULTRA_HIGH"] = "MEDIA_RESOLUTION_ULTRA_HIGH"; +})(PartMediaResolutionLevel || (PartMediaResolutionLevel = {})); +/** Resource scope. */ +var ResourceScope; +(function (ResourceScope) { + /** + * When setting base_url, this value configures resource scope to be the collection. + The resource name will not include api version, project, or location. + For example, if base_url is set to "https://aiplatform.googleapis.com", + then the resource name for a Model would be + "https://aiplatform.googleapis.com/publishers/google/models/gemini-3-pro-preview + */ + ResourceScope["COLLECTION"] = "COLLECTION"; +})(ResourceScope || (ResourceScope = {})); +/** Options for feature selection preference. */ +var FeatureSelectionPreference; +(function (FeatureSelectionPreference) { + FeatureSelectionPreference["FEATURE_SELECTION_PREFERENCE_UNSPECIFIED"] = "FEATURE_SELECTION_PREFERENCE_UNSPECIFIED"; + FeatureSelectionPreference["PRIORITIZE_QUALITY"] = "PRIORITIZE_QUALITY"; + FeatureSelectionPreference["BALANCED"] = "BALANCED"; + FeatureSelectionPreference["PRIORITIZE_COST"] = "PRIORITIZE_COST"; +})(FeatureSelectionPreference || (FeatureSelectionPreference = {})); +/** The environment being operated. */ +var Environment; +(function (Environment) { + /** + * Defaults to browser. + */ + Environment["ENVIRONMENT_UNSPECIFIED"] = "ENVIRONMENT_UNSPECIFIED"; + /** + * Operates in a web browser. + */ + Environment["ENVIRONMENT_BROWSER"] = "ENVIRONMENT_BROWSER"; +})(Environment || (Environment = {})); +/** Enum that controls the safety filter level for objectionable content. */ +var SafetyFilterLevel; +(function (SafetyFilterLevel) { + SafetyFilterLevel["BLOCK_LOW_AND_ABOVE"] = "BLOCK_LOW_AND_ABOVE"; + SafetyFilterLevel["BLOCK_MEDIUM_AND_ABOVE"] = "BLOCK_MEDIUM_AND_ABOVE"; + SafetyFilterLevel["BLOCK_ONLY_HIGH"] = "BLOCK_ONLY_HIGH"; + SafetyFilterLevel["BLOCK_NONE"] = "BLOCK_NONE"; +})(SafetyFilterLevel || (SafetyFilterLevel = {})); +/** Enum that controls the generation of people. */ +var PersonGeneration; +(function (PersonGeneration) { + /** + * Block generation of images of people. + */ + PersonGeneration["DONT_ALLOW"] = "DONT_ALLOW"; + /** + * Generate images of adults, but not children. + */ + PersonGeneration["ALLOW_ADULT"] = "ALLOW_ADULT"; + /** + * Generate images that include adults and children. + */ + PersonGeneration["ALLOW_ALL"] = "ALLOW_ALL"; +})(PersonGeneration || (PersonGeneration = {})); +/** Enum that specifies the language of the text in the prompt. */ +var ImagePromptLanguage; +(function (ImagePromptLanguage) { + /** + * Auto-detect the language. + */ + ImagePromptLanguage["auto"] = "auto"; + /** + * English + */ + ImagePromptLanguage["en"] = "en"; + /** + * Japanese + */ + ImagePromptLanguage["ja"] = "ja"; + /** + * Korean + */ + ImagePromptLanguage["ko"] = "ko"; + /** + * Hindi + */ + ImagePromptLanguage["hi"] = "hi"; + /** + * Chinese + */ + ImagePromptLanguage["zh"] = "zh"; + /** + * Portuguese + */ + ImagePromptLanguage["pt"] = "pt"; + /** + * Spanish + */ + ImagePromptLanguage["es"] = "es"; +})(ImagePromptLanguage || (ImagePromptLanguage = {})); +/** Enum representing the mask mode of a mask reference image. */ +var MaskReferenceMode; +(function (MaskReferenceMode) { + MaskReferenceMode["MASK_MODE_DEFAULT"] = "MASK_MODE_DEFAULT"; + MaskReferenceMode["MASK_MODE_USER_PROVIDED"] = "MASK_MODE_USER_PROVIDED"; + MaskReferenceMode["MASK_MODE_BACKGROUND"] = "MASK_MODE_BACKGROUND"; + MaskReferenceMode["MASK_MODE_FOREGROUND"] = "MASK_MODE_FOREGROUND"; + MaskReferenceMode["MASK_MODE_SEMANTIC"] = "MASK_MODE_SEMANTIC"; +})(MaskReferenceMode || (MaskReferenceMode = {})); +/** Enum representing the control type of a control reference image. */ +var ControlReferenceType; +(function (ControlReferenceType) { + ControlReferenceType["CONTROL_TYPE_DEFAULT"] = "CONTROL_TYPE_DEFAULT"; + ControlReferenceType["CONTROL_TYPE_CANNY"] = "CONTROL_TYPE_CANNY"; + ControlReferenceType["CONTROL_TYPE_SCRIBBLE"] = "CONTROL_TYPE_SCRIBBLE"; + ControlReferenceType["CONTROL_TYPE_FACE_MESH"] = "CONTROL_TYPE_FACE_MESH"; +})(ControlReferenceType || (ControlReferenceType = {})); +/** Enum representing the subject type of a subject reference image. */ +var SubjectReferenceType; +(function (SubjectReferenceType) { + SubjectReferenceType["SUBJECT_TYPE_DEFAULT"] = "SUBJECT_TYPE_DEFAULT"; + SubjectReferenceType["SUBJECT_TYPE_PERSON"] = "SUBJECT_TYPE_PERSON"; + SubjectReferenceType["SUBJECT_TYPE_ANIMAL"] = "SUBJECT_TYPE_ANIMAL"; + SubjectReferenceType["SUBJECT_TYPE_PRODUCT"] = "SUBJECT_TYPE_PRODUCT"; +})(SubjectReferenceType || (SubjectReferenceType = {})); +/** Enum representing the editing mode. */ +var EditMode; +(function (EditMode) { + EditMode["EDIT_MODE_DEFAULT"] = "EDIT_MODE_DEFAULT"; + EditMode["EDIT_MODE_INPAINT_REMOVAL"] = "EDIT_MODE_INPAINT_REMOVAL"; + EditMode["EDIT_MODE_INPAINT_INSERTION"] = "EDIT_MODE_INPAINT_INSERTION"; + EditMode["EDIT_MODE_OUTPAINT"] = "EDIT_MODE_OUTPAINT"; + EditMode["EDIT_MODE_CONTROLLED_EDITING"] = "EDIT_MODE_CONTROLLED_EDITING"; + EditMode["EDIT_MODE_STYLE"] = "EDIT_MODE_STYLE"; + EditMode["EDIT_MODE_BGSWAP"] = "EDIT_MODE_BGSWAP"; + EditMode["EDIT_MODE_PRODUCT_IMAGE"] = "EDIT_MODE_PRODUCT_IMAGE"; +})(EditMode || (EditMode = {})); +/** Enum that represents the segmentation mode. */ +var SegmentMode; +(function (SegmentMode) { + SegmentMode["FOREGROUND"] = "FOREGROUND"; + SegmentMode["BACKGROUND"] = "BACKGROUND"; + SegmentMode["PROMPT"] = "PROMPT"; + SegmentMode["SEMANTIC"] = "SEMANTIC"; + SegmentMode["INTERACTIVE"] = "INTERACTIVE"; +})(SegmentMode || (SegmentMode = {})); +/** Enum for the reference type of a video generation reference image. */ +var VideoGenerationReferenceType; +(function (VideoGenerationReferenceType) { + /** + * A reference image that provides assets to the generated video, + such as the scene, an object, a character, etc. + */ + VideoGenerationReferenceType["ASSET"] = "ASSET"; + /** + * A reference image that provides aesthetics including colors, + lighting, texture, etc., to be used as the style of the generated video, + such as 'anime', 'photography', 'origami', etc. + */ + VideoGenerationReferenceType["STYLE"] = "STYLE"; +})(VideoGenerationReferenceType || (VideoGenerationReferenceType = {})); +/** Enum for the mask mode of a video generation mask. */ +var VideoGenerationMaskMode; +(function (VideoGenerationMaskMode) { + /** + * The image mask contains a masked rectangular region which is + applied on the first frame of the input video. The object described in + the prompt is inserted into this region and will appear in subsequent + frames. + */ + VideoGenerationMaskMode["INSERT"] = "INSERT"; + /** + * The image mask is used to determine an object in the + first video frame to track. This object is removed from the video. + */ + VideoGenerationMaskMode["REMOVE"] = "REMOVE"; + /** + * The image mask is used to determine a region in the + video. Objects in this region will be removed. + */ + VideoGenerationMaskMode["REMOVE_STATIC"] = "REMOVE_STATIC"; + /** + * The image mask contains a masked rectangular region where + the input video will go. The remaining area will be generated. Video + masks are not supported. + */ + VideoGenerationMaskMode["OUTPAINT"] = "OUTPAINT"; +})(VideoGenerationMaskMode || (VideoGenerationMaskMode = {})); +/** Enum that controls the compression quality of the generated videos. */ +var VideoCompressionQuality; +(function (VideoCompressionQuality) { + /** + * Optimized video compression quality. This will produce videos + with a compressed, smaller file size. + */ + VideoCompressionQuality["OPTIMIZED"] = "OPTIMIZED"; + /** + * Lossless video compression quality. This will produce videos + with a larger file size. + */ + VideoCompressionQuality["LOSSLESS"] = "LOSSLESS"; +})(VideoCompressionQuality || (VideoCompressionQuality = {})); +/** Enum representing the tuning method. */ +var TuningMethod; +(function (TuningMethod) { + /** + * Supervised fine tuning. + */ + TuningMethod["SUPERVISED_FINE_TUNING"] = "SUPERVISED_FINE_TUNING"; + /** + * Preference optimization tuning. + */ + TuningMethod["PREFERENCE_TUNING"] = "PREFERENCE_TUNING"; + /** + * Distillation tuning. + */ + TuningMethod["DISTILLATION"] = "DISTILLATION"; +})(TuningMethod || (TuningMethod = {})); +/** State for the lifecycle of a Document. */ +var DocumentState; +(function (DocumentState) { + DocumentState["STATE_UNSPECIFIED"] = "STATE_UNSPECIFIED"; + DocumentState["STATE_PENDING"] = "STATE_PENDING"; + DocumentState["STATE_ACTIVE"] = "STATE_ACTIVE"; + DocumentState["STATE_FAILED"] = "STATE_FAILED"; +})(DocumentState || (DocumentState = {})); +/** State for the lifecycle of a File. */ +var FileState; +(function (FileState) { + FileState["STATE_UNSPECIFIED"] = "STATE_UNSPECIFIED"; + FileState["PROCESSING"] = "PROCESSING"; + FileState["ACTIVE"] = "ACTIVE"; + FileState["FAILED"] = "FAILED"; +})(FileState || (FileState = {})); +/** Source of the File. */ +var FileSource; +(function (FileSource) { + FileSource["SOURCE_UNSPECIFIED"] = "SOURCE_UNSPECIFIED"; + FileSource["UPLOADED"] = "UPLOADED"; + FileSource["GENERATED"] = "GENERATED"; + FileSource["REGISTERED"] = "REGISTERED"; +})(FileSource || (FileSource = {})); +/** The reason why the turn is complete. */ +var TurnCompleteReason; +(function (TurnCompleteReason) { + /** + * Default value. Reason is unspecified. + */ + TurnCompleteReason["TURN_COMPLETE_REASON_UNSPECIFIED"] = "TURN_COMPLETE_REASON_UNSPECIFIED"; + /** + * The function call generated by the model is invalid. + */ + TurnCompleteReason["MALFORMED_FUNCTION_CALL"] = "MALFORMED_FUNCTION_CALL"; + /** + * The response is rejected by the model. + */ + TurnCompleteReason["RESPONSE_REJECTED"] = "RESPONSE_REJECTED"; + /** + * Needs more input from the user. + */ + TurnCompleteReason["NEED_MORE_INPUT"] = "NEED_MORE_INPUT"; +})(TurnCompleteReason || (TurnCompleteReason = {})); +/** Server content modalities. */ +var MediaModality; +(function (MediaModality) { + /** + * The modality is unspecified. + */ + MediaModality["MODALITY_UNSPECIFIED"] = "MODALITY_UNSPECIFIED"; + /** + * Plain text. + */ + MediaModality["TEXT"] = "TEXT"; + /** + * Images. + */ + MediaModality["IMAGE"] = "IMAGE"; + /** + * Video. + */ + MediaModality["VIDEO"] = "VIDEO"; + /** + * Audio. + */ + MediaModality["AUDIO"] = "AUDIO"; + /** + * Document, e.g. PDF. + */ + MediaModality["DOCUMENT"] = "DOCUMENT"; +})(MediaModality || (MediaModality = {})); +/** The type of the VAD signal. */ +var VadSignalType; +(function (VadSignalType) { + /** + * The default is VAD_SIGNAL_TYPE_UNSPECIFIED. + */ + VadSignalType["VAD_SIGNAL_TYPE_UNSPECIFIED"] = "VAD_SIGNAL_TYPE_UNSPECIFIED"; + /** + * Start of sentence signal. + */ + VadSignalType["VAD_SIGNAL_TYPE_SOS"] = "VAD_SIGNAL_TYPE_SOS"; + /** + * End of sentence signal. + */ + VadSignalType["VAD_SIGNAL_TYPE_EOS"] = "VAD_SIGNAL_TYPE_EOS"; +})(VadSignalType || (VadSignalType = {})); +/** The type of the voice activity signal. */ +var VoiceActivityType; +(function (VoiceActivityType) { + /** + * The default is VOICE_ACTIVITY_TYPE_UNSPECIFIED. + */ + VoiceActivityType["TYPE_UNSPECIFIED"] = "TYPE_UNSPECIFIED"; + /** + * Start of sentence signal. + */ + VoiceActivityType["ACTIVITY_START"] = "ACTIVITY_START"; + /** + * End of sentence signal. + */ + VoiceActivityType["ACTIVITY_END"] = "ACTIVITY_END"; +})(VoiceActivityType || (VoiceActivityType = {})); +/** Start of speech sensitivity. */ +var StartSensitivity; +(function (StartSensitivity) { + /** + * The default is START_SENSITIVITY_LOW. + */ + StartSensitivity["START_SENSITIVITY_UNSPECIFIED"] = "START_SENSITIVITY_UNSPECIFIED"; + /** + * Automatic detection will detect the start of speech more often. + */ + StartSensitivity["START_SENSITIVITY_HIGH"] = "START_SENSITIVITY_HIGH"; + /** + * Automatic detection will detect the start of speech less often. + */ + StartSensitivity["START_SENSITIVITY_LOW"] = "START_SENSITIVITY_LOW"; +})(StartSensitivity || (StartSensitivity = {})); +/** End of speech sensitivity. */ +var EndSensitivity; +(function (EndSensitivity) { + /** + * The default is END_SENSITIVITY_LOW. + */ + EndSensitivity["END_SENSITIVITY_UNSPECIFIED"] = "END_SENSITIVITY_UNSPECIFIED"; + /** + * Automatic detection ends speech more often. + */ + EndSensitivity["END_SENSITIVITY_HIGH"] = "END_SENSITIVITY_HIGH"; + /** + * Automatic detection ends speech less often. + */ + EndSensitivity["END_SENSITIVITY_LOW"] = "END_SENSITIVITY_LOW"; +})(EndSensitivity || (EndSensitivity = {})); +/** The different ways of handling user activity. */ +var ActivityHandling; +(function (ActivityHandling) { + /** + * If unspecified, the default behavior is `START_OF_ACTIVITY_INTERRUPTS`. + */ + ActivityHandling["ACTIVITY_HANDLING_UNSPECIFIED"] = "ACTIVITY_HANDLING_UNSPECIFIED"; + /** + * If true, start of activity will interrupt the model's response (also called "barge in"). The model's current response will be cut-off in the moment of the interruption. This is the default behavior. + */ + ActivityHandling["START_OF_ACTIVITY_INTERRUPTS"] = "START_OF_ACTIVITY_INTERRUPTS"; + /** + * The model's response will not be interrupted. + */ + ActivityHandling["NO_INTERRUPTION"] = "NO_INTERRUPTION"; +})(ActivityHandling || (ActivityHandling = {})); +/** Options about which input is included in the user's turn. */ +var TurnCoverage; +(function (TurnCoverage) { + /** + * If unspecified, the default behavior is `TURN_INCLUDES_ONLY_ACTIVITY`. + */ + TurnCoverage["TURN_COVERAGE_UNSPECIFIED"] = "TURN_COVERAGE_UNSPECIFIED"; + /** + * The users turn only includes activity since the last turn, excluding inactivity (e.g. silence on the audio stream). This is the default behavior. + */ + TurnCoverage["TURN_INCLUDES_ONLY_ACTIVITY"] = "TURN_INCLUDES_ONLY_ACTIVITY"; + /** + * The users turn includes all realtime input since the last turn, including inactivity (e.g. silence on the audio stream). + */ + TurnCoverage["TURN_INCLUDES_ALL_INPUT"] = "TURN_INCLUDES_ALL_INPUT"; +})(TurnCoverage || (TurnCoverage = {})); +/** Scale of the generated music. */ +var Scale; +(function (Scale) { + /** + * Default value. This value is unused. + */ + Scale["SCALE_UNSPECIFIED"] = "SCALE_UNSPECIFIED"; + /** + * C major or A minor. + */ + Scale["C_MAJOR_A_MINOR"] = "C_MAJOR_A_MINOR"; + /** + * Db major or Bb minor. + */ + Scale["D_FLAT_MAJOR_B_FLAT_MINOR"] = "D_FLAT_MAJOR_B_FLAT_MINOR"; + /** + * D major or B minor. + */ + Scale["D_MAJOR_B_MINOR"] = "D_MAJOR_B_MINOR"; + /** + * Eb major or C minor + */ + Scale["E_FLAT_MAJOR_C_MINOR"] = "E_FLAT_MAJOR_C_MINOR"; + /** + * E major or Db minor. + */ + Scale["E_MAJOR_D_FLAT_MINOR"] = "E_MAJOR_D_FLAT_MINOR"; + /** + * F major or D minor. + */ + Scale["F_MAJOR_D_MINOR"] = "F_MAJOR_D_MINOR"; + /** + * Gb major or Eb minor. + */ + Scale["G_FLAT_MAJOR_E_FLAT_MINOR"] = "G_FLAT_MAJOR_E_FLAT_MINOR"; + /** + * G major or E minor. + */ + Scale["G_MAJOR_E_MINOR"] = "G_MAJOR_E_MINOR"; + /** + * Ab major or F minor. + */ + Scale["A_FLAT_MAJOR_F_MINOR"] = "A_FLAT_MAJOR_F_MINOR"; + /** + * A major or Gb minor. + */ + Scale["A_MAJOR_G_FLAT_MINOR"] = "A_MAJOR_G_FLAT_MINOR"; + /** + * Bb major or G minor. + */ + Scale["B_FLAT_MAJOR_G_MINOR"] = "B_FLAT_MAJOR_G_MINOR"; + /** + * B major or Ab minor. + */ + Scale["B_MAJOR_A_FLAT_MINOR"] = "B_MAJOR_A_FLAT_MINOR"; +})(Scale || (Scale = {})); +/** The mode of music generation. */ +var MusicGenerationMode; +(function (MusicGenerationMode) { + /** + * Rely on the server default generation mode. + */ + MusicGenerationMode["MUSIC_GENERATION_MODE_UNSPECIFIED"] = "MUSIC_GENERATION_MODE_UNSPECIFIED"; + /** + * Steer text prompts to regions of latent space with higher quality + music. + */ + MusicGenerationMode["QUALITY"] = "QUALITY"; + /** + * Steer text prompts to regions of latent space with a larger + diversity of music. + */ + MusicGenerationMode["DIVERSITY"] = "DIVERSITY"; + /** + * Steer text prompts to regions of latent space more likely to + generate music with vocals. + */ + MusicGenerationMode["VOCALIZATION"] = "VOCALIZATION"; +})(MusicGenerationMode || (MusicGenerationMode = {})); +/** The playback control signal to apply to the music generation. */ +var LiveMusicPlaybackControl; +(function (LiveMusicPlaybackControl) { + /** + * This value is unused. + */ + LiveMusicPlaybackControl["PLAYBACK_CONTROL_UNSPECIFIED"] = "PLAYBACK_CONTROL_UNSPECIFIED"; + /** + * Start generating the music. + */ + LiveMusicPlaybackControl["PLAY"] = "PLAY"; + /** + * Hold the music generation. Use PLAY to resume from the current position. + */ + LiveMusicPlaybackControl["PAUSE"] = "PAUSE"; + /** + * Stop the music generation and reset the context (prompts retained). + Use PLAY to restart the music generation. + */ + LiveMusicPlaybackControl["STOP"] = "STOP"; + /** + * Reset the context of the music generation without stopping it. + Retains the current prompts and config. + */ + LiveMusicPlaybackControl["RESET_CONTEXT"] = "RESET_CONTEXT"; +})(LiveMusicPlaybackControl || (LiveMusicPlaybackControl = {})); + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function tPart(origin) { + if (origin === null || origin === undefined) { + throw new Error('PartUnion is required'); + } + if (typeof origin === 'object') { + return origin; + } + if (typeof origin === 'string') { + return { text: origin }; + } + throw new Error(`Unsupported part type: ${typeof origin}`); +} +function tParts(origin) { + if (origin === null || + origin === undefined || + (Array.isArray(origin) && origin.length === 0)) { + throw new Error('PartListUnion is required'); + } + if (Array.isArray(origin)) { + return origin.map((item) => tPart(item)); + } + return [tPart(origin)]; +} +function _isContent(origin) { + return (origin !== null && + origin !== undefined && + typeof origin === 'object' && + 'parts' in origin && + Array.isArray(origin.parts)); +} +function _isFunctionCallPart(origin) { + return (origin !== null && + origin !== undefined && + typeof origin === 'object' && + 'functionCall' in origin); +} +function _isFunctionResponsePart(origin) { + return (origin !== null && + origin !== undefined && + typeof origin === 'object' && + 'functionResponse' in origin); +} +function tContent(origin) { + if (origin === null || origin === undefined) { + throw new Error('ContentUnion is required'); + } + if (_isContent(origin)) { + // _isContent is a utility function that checks if the + // origin is a Content. + return origin; + } + return { + role: 'user', + parts: tParts(origin), + }; +} +function tContents(origin) { + if (origin === null || + origin === undefined || + (Array.isArray(origin) && origin.length === 0)) { + throw new Error('contents are required'); + } + if (!Array.isArray(origin)) { + // If it's not an array, it's a single content or a single PartUnion. + if (_isFunctionCallPart(origin) || _isFunctionResponsePart(origin)) { + throw new Error('To specify functionCall or functionResponse parts, please wrap them in a Content object, specifying the role for them'); + } + return [tContent(origin)]; + } + const result = []; + const accumulatedParts = []; + const isContentArray = _isContent(origin[0]); + for (const item of origin) { + const isContent = _isContent(item); + if (isContent != isContentArray) { + throw new Error('Mixing Content and Parts is not supported, please group the parts into a the appropriate Content objects and specify the roles for them'); + } + if (isContent) { + // `isContent` contains the result of _isContent, which is a utility + // function that checks if the item is a Content. + result.push(item); + } + else if (_isFunctionCallPart(item) || _isFunctionResponsePart(item)) { + throw new Error('To specify functionCall or functionResponse parts, please wrap them, and any other parts, in Content objects as appropriate, specifying the role for them'); + } + else { + accumulatedParts.push(item); + } + } + if (!isContentArray) { + result.push({ role: 'user', parts: tParts(accumulatedParts) }); + } + return result; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * TypeScript representation of the SentencePiece model protobuf. + * Translated from sentencepiece_model.proto + */ +var ModelType; +(function (ModelType) { + ModelType[ModelType["UNIGRAM"] = 1] = "UNIGRAM"; + ModelType[ModelType["BPE"] = 2] = "BPE"; + ModelType[ModelType["WORD"] = 3] = "WORD"; + ModelType[ModelType["CHAR"] = 4] = "CHAR"; +})(ModelType || (ModelType = {})); +var SentencePieceType; +(function (SentencePieceType) { + SentencePieceType[SentencePieceType["NORMAL"] = 1] = "NORMAL"; + SentencePieceType[SentencePieceType["UNKNOWN"] = 2] = "UNKNOWN"; + SentencePieceType[SentencePieceType["CONTROL"] = 3] = "CONTROL"; + SentencePieceType[SentencePieceType["USER_DEFINED"] = 4] = "USER_DEFINED"; + SentencePieceType[SentencePieceType["BYTE"] = 6] = "BYTE"; + SentencePieceType[SentencePieceType["UNUSED"] = 5] = "UNUSED"; +})(SentencePieceType || (SentencePieceType = {})); + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function newTrieNode() { + return { + children: new Map(), + final: false, + }; +} +/** + * PrefixMatcher finds the longest prefix of a string that matches + * a vocabulary word using a trie data structure. + */ +class PrefixMatcher { + /** + * Creates a new PrefixMatcher from a set of vocabulary strings. + */ + constructor(vocab) { + this.root = newTrieNode(); + for (const word of vocab) { + this.add(word); + } + } + /** + * Finds the longest prefix of text that matches a vocabulary word. + * Returns the length of the prefix, or 0 if no prefix was found. + */ + findPrefixLen(text) { + let node = this.root; + let maxLen = 0; + let i = 0; + for (const char of text) { + const child = node.children.get(char); + if (!child) { + return maxLen; + } + if (child.final) { + maxLen = i + 1; + } + node = child; + i++; + } + return maxLen; + } + /** + * Adds a word to the trie. + */ + add(word) { + let node = this.root; + for (const char of word) { + let child = node.children.get(char); + if (!child) { + child = newTrieNode(); + node.children.set(char, child); + } + node = child; + } + node.final = true; + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Generic priority queue with Insert, PopMax, and RemoveFunc operations. + * Translated from go-sentencepiece/internal/priorityqueue + * + * Uses a binary heap data structure where items[0] is unused, + * and elements are stored at indices 1...N. + */ +class PriorityQueue { + /** + * Creates a new PriorityQueue. + * + * @param sizeHint Initial capacity hint for the queue + * @param cmp Comparison function that returns > 0 if a has higher priority than b, + * 0 if equal priority, < 0 otherwise + */ + constructor(sizeHint, cmp) { + this.cmp = cmp; + this.items = new Array(Math.max(1, sizeHint + 1)); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + this.items[0] = null; + this.items.length = 1; + } + /** + * Returns the number of items in the queue. + */ + len() { + return this.items.length - 1; + } + /** + * Inserts a new element into the priority queue. + */ + insert(elem) { + this.items.push(elem); + this.siftUp(this.items.length - 1); + } + /** + * Returns and removes the element with the maximal priority. + * Throws if the queue is empty. + */ + popMax() { + if (this.items.length < 2) { + throw new Error('popping from empty priority queue'); + } + const maxItem = this.items[1]; + this.items[1] = this.items[this.items.length - 1]; + this.items.pop(); + if (this.items.length > 1) { + this.siftDown(1); + } + return maxItem; + } + /** + * Removes all elements for which the predicate returns true. + */ + removeFunc(rm) { + let i = 1; + while (i < this.items.length && !rm(this.items[i])) { + i++; + } + if (i === this.items.length) { + return; + } + for (let j = i + 1; j < this.items.length; j++) { + if (!rm(this.items[j])) { + this.items[i] = this.items[j]; + i++; + } + } + this.items.length = i; + this.rebuildHeap(); + } + /** + * Rebuilds the entire heap from scratch. + */ + rebuildHeap() { + for (let i = Math.floor(this.items.length / 2); i >= 1; i--) { + this.siftDown(i); + } + } + /** + * Moves an element up the heap until heap property is restored. + */ + siftUp(n) { + let i = n; + while (i > 1) { + const p = Math.floor(i / 2); + if (this.cmp(this.items[p], this.items[i]) >= 0) { + return; + } + [this.items[i], this.items[p]] = [this.items[p], this.items[i]]; + i = p; + } + } + /** + * Moves an element down the heap until heap property is restored. + */ + siftDown(i) { + // eslint-disable-next-line + while (true) { + const c = 2 * i; + if (c >= this.items.length) { + return; + } + let maxChild = c; + if (c + 1 < this.items.length) { + if (this.cmp(this.items[c + 1], this.items[c]) > 0) { + maxChild = c + 1; + } + } + if (this.cmp(this.items[i], this.items[maxChild]) >= 0) { + return; + } + [this.items[i], this.items[maxChild]] = [ + this.items[maxChild], + this.items[i], + ]; + i = maxChild; + } + } +} + +/*eslint-disable block-scoped-var, id-length, no-control-regex, + * no-magic-numbers, no-prototype-builtins, no-redeclare, no-shadow, no-var, + * sort-vars*/ + + +// Common aliases +const $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, + $util = $protobuf.util; + +// Exported root namespace +const $root = $protobuf.roots['default'] || ($protobuf.roots['default'] = {}); + +const sentencepiece = $root.sentencepiece = (() => { + /** + * Namespace sentencepiece. + * @exports sentencepiece + * @namespace + */ + const sentencepiece = {}; + + sentencepiece.TrainerSpec = (function() { + /** + * Properties of a TrainerSpec. + * @memberof sentencepiece + * @interface ITrainerSpec + * @property {Array.<string>|null} [input] TrainerSpec input + * @property {string|null} [inputFormat] TrainerSpec inputFormat + * @property {string|null} [modelPrefix] TrainerSpec modelPrefix + * @property {sentencepiece.TrainerSpec.ModelType|null} [modelType] + * TrainerSpec modelType + * @property {number|null} [vocabSize] TrainerSpec vocabSize + * @property {Array.<string>|null} [acceptLanguage] TrainerSpec + * acceptLanguage + * @property {number|null} [selfTestSampleSize] TrainerSpec + * selfTestSampleSize + * @property {boolean|null} [enableDifferentialPrivacy] TrainerSpec + * enableDifferentialPrivacy + * @property {number|null} [differentialPrivacyNoiseLevel] TrainerSpec + * differentialPrivacyNoiseLevel + * @property {number|Long|null} [differentialPrivacyClippingThreshold] + * TrainerSpec differentialPrivacyClippingThreshold + * @property {number|null} [characterCoverage] TrainerSpec characterCoverage + * @property {number|Long|null} [inputSentenceSize] TrainerSpec + * inputSentenceSize + * @property {boolean|null} [shuffleInputSentence] TrainerSpec + * shuffleInputSentence + * @property {number|null} [miningSentenceSize] TrainerSpec + * miningSentenceSize + * @property {number|null} [trainingSentenceSize] TrainerSpec + * trainingSentenceSize + * @property {number|null} [seedSentencepieceSize] TrainerSpec + * seedSentencepieceSize + * @property {number|null} [shrinkingFactor] TrainerSpec shrinkingFactor + * @property {number|null} [maxSentenceLength] TrainerSpec maxSentenceLength + * @property {number|null} [numThreads] TrainerSpec numThreads + * @property {number|null} [numSubIterations] TrainerSpec numSubIterations + * @property {number|null} [maxSentencepieceLength] TrainerSpec + * maxSentencepieceLength + * @property {boolean|null} [splitByUnicodeScript] TrainerSpec + * splitByUnicodeScript + * @property {boolean|null} [splitByNumber] TrainerSpec splitByNumber + * @property {boolean|null} [splitByWhitespace] TrainerSpec + * splitByWhitespace + * @property {boolean|null} [treatWhitespaceAsSuffix] TrainerSpec + * treatWhitespaceAsSuffix + * @property {boolean|null} [allowWhitespaceOnlyPieces] TrainerSpec + * allowWhitespaceOnlyPieces + * @property {boolean|null} [splitDigits] TrainerSpec splitDigits + * @property {string|null} [pretokenizationDelimiter] TrainerSpec + * pretokenizationDelimiter + * @property {Array.<string>|null} [controlSymbols] TrainerSpec + * controlSymbols + * @property {Array.<string>|null} [userDefinedSymbols] TrainerSpec + * userDefinedSymbols + * @property {string|null} [requiredChars] TrainerSpec requiredChars + * @property {boolean|null} [byteFallback] TrainerSpec byteFallback + * @property {boolean|null} [vocabularyOutputPieceScore] TrainerSpec + * vocabularyOutputPieceScore + * @property {boolean|null} [hardVocabLimit] TrainerSpec hardVocabLimit + * @property {boolean|null} [useAllVocab] TrainerSpec useAllVocab + * @property {number|null} [unkId] TrainerSpec unkId + * @property {number|null} [bosId] TrainerSpec bosId + * @property {number|null} [eosId] TrainerSpec eosId + * @property {number|null} [padId] TrainerSpec padId + * @property {string|null} [unkPiece] TrainerSpec unkPiece + * @property {string|null} [bosPiece] TrainerSpec bosPiece + * @property {string|null} [eosPiece] TrainerSpec eosPiece + * @property {string|null} [padPiece] TrainerSpec padPiece + * @property {string|null} [unkSurface] TrainerSpec unkSurface + * @property {boolean|null} [trainExtremelyLargeCorpus] TrainerSpec + * trainExtremelyLargeCorpus + * @property {string|null} [seedSentencepiecesFile] TrainerSpec + * seedSentencepiecesFile + */ + + /** + * Constructs a new TrainerSpec. + * @memberof sentencepiece + * @classdesc Represents a TrainerSpec. + * @implements ITrainerSpec + * @constructor + * @param {sentencepiece.ITrainerSpec=} [properties] Properties to set + */ + function TrainerSpec(properties) { + this.input = []; + this.acceptLanguage = []; + this.controlSymbols = []; + this.userDefinedSymbols = []; + if (properties) + for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * TrainerSpec input. + * @member {Array.<string>} input + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.input = $util.emptyArray; + + /** + * TrainerSpec inputFormat. + * @member {string} inputFormat + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.inputFormat = ''; + + /** + * TrainerSpec modelPrefix. + * @member {string} modelPrefix + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.modelPrefix = ''; + + /** + * TrainerSpec modelType. + * @member {sentencepiece.TrainerSpec.ModelType} modelType + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.modelType = 1; + + /** + * TrainerSpec vocabSize. + * @member {number} vocabSize + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.vocabSize = 8000; + + /** + * TrainerSpec acceptLanguage. + * @member {Array.<string>} acceptLanguage + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.acceptLanguage = $util.emptyArray; + + /** + * TrainerSpec selfTestSampleSize. + * @member {number} selfTestSampleSize + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.selfTestSampleSize = 0; + + /** + * TrainerSpec enableDifferentialPrivacy. + * @member {boolean} enableDifferentialPrivacy + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.enableDifferentialPrivacy = false; + + /** + * TrainerSpec differentialPrivacyNoiseLevel. + * @member {number} differentialPrivacyNoiseLevel + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.differentialPrivacyNoiseLevel = 0; + + /** + * TrainerSpec differentialPrivacyClippingThreshold. + * @member {number|Long} differentialPrivacyClippingThreshold + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.differentialPrivacyClippingThreshold = + $util.Long ? $util.Long.fromBits(0, 0, true) : 0; + + /** + * TrainerSpec characterCoverage. + * @member {number} characterCoverage + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.characterCoverage = 0.9995; + + /** + * TrainerSpec inputSentenceSize. + * @member {number|Long} inputSentenceSize + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.inputSentenceSize = + $util.Long ? $util.Long.fromBits(0, 0, true) : 0; + + /** + * TrainerSpec shuffleInputSentence. + * @member {boolean} shuffleInputSentence + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.shuffleInputSentence = true; + + /** + * TrainerSpec miningSentenceSize. + * @member {number} miningSentenceSize + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.miningSentenceSize = 0; + + /** + * TrainerSpec trainingSentenceSize. + * @member {number} trainingSentenceSize + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.trainingSentenceSize = 0; + + /** + * TrainerSpec seedSentencepieceSize. + * @member {number} seedSentencepieceSize + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.seedSentencepieceSize = 1000000; + + /** + * TrainerSpec shrinkingFactor. + * @member {number} shrinkingFactor + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.shrinkingFactor = 0.75; + + /** + * TrainerSpec maxSentenceLength. + * @member {number} maxSentenceLength + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.maxSentenceLength = 4192; + + /** + * TrainerSpec numThreads. + * @member {number} numThreads + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.numThreads = 16; + + /** + * TrainerSpec numSubIterations. + * @member {number} numSubIterations + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.numSubIterations = 2; + + /** + * TrainerSpec maxSentencepieceLength. + * @member {number} maxSentencepieceLength + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.maxSentencepieceLength = 16; + + /** + * TrainerSpec splitByUnicodeScript. + * @member {boolean} splitByUnicodeScript + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.splitByUnicodeScript = true; + + /** + * TrainerSpec splitByNumber. + * @member {boolean} splitByNumber + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.splitByNumber = true; + + /** + * TrainerSpec splitByWhitespace. + * @member {boolean} splitByWhitespace + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.splitByWhitespace = true; + + /** + * TrainerSpec treatWhitespaceAsSuffix. + * @member {boolean} treatWhitespaceAsSuffix + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.treatWhitespaceAsSuffix = false; + + /** + * TrainerSpec allowWhitespaceOnlyPieces. + * @member {boolean} allowWhitespaceOnlyPieces + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.allowWhitespaceOnlyPieces = false; + + /** + * TrainerSpec splitDigits. + * @member {boolean} splitDigits + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.splitDigits = false; + + /** + * TrainerSpec pretokenizationDelimiter. + * @member {string} pretokenizationDelimiter + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.pretokenizationDelimiter = ''; + + /** + * TrainerSpec controlSymbols. + * @member {Array.<string>} controlSymbols + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.controlSymbols = $util.emptyArray; + + /** + * TrainerSpec userDefinedSymbols. + * @member {Array.<string>} userDefinedSymbols + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.userDefinedSymbols = $util.emptyArray; + + /** + * TrainerSpec requiredChars. + * @member {string} requiredChars + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.requiredChars = ''; + + /** + * TrainerSpec byteFallback. + * @member {boolean} byteFallback + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.byteFallback = false; + + /** + * TrainerSpec vocabularyOutputPieceScore. + * @member {boolean} vocabularyOutputPieceScore + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.vocabularyOutputPieceScore = true; + + /** + * TrainerSpec hardVocabLimit. + * @member {boolean} hardVocabLimit + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.hardVocabLimit = true; + + /** + * TrainerSpec useAllVocab. + * @member {boolean} useAllVocab + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.useAllVocab = false; + + /** + * TrainerSpec unkId. + * @member {number} unkId + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.unkId = 0; + + /** + * TrainerSpec bosId. + * @member {number} bosId + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.bosId = 1; + + /** + * TrainerSpec eosId. + * @member {number} eosId + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.eosId = 2; + + /** + * TrainerSpec padId. + * @member {number} padId + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.padId = -1; + + /** + * TrainerSpec unkPiece. + * @member {string} unkPiece + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.unkPiece = '<unk>'; + + /** + * TrainerSpec bosPiece. + * @member {string} bosPiece + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.bosPiece = '<s>'; + + /** + * TrainerSpec eosPiece. + * @member {string} eosPiece + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.eosPiece = '</s>'; + + /** + * TrainerSpec padPiece. + * @member {string} padPiece + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.padPiece = '<pad>'; + + /** + * TrainerSpec unkSurface. + * @member {string} unkSurface + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.unkSurface = ' E28187 '; + + /** + * TrainerSpec trainExtremelyLargeCorpus. + * @member {boolean} trainExtremelyLargeCorpus + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.trainExtremelyLargeCorpus = false; + + /** + * TrainerSpec seedSentencepiecesFile. + * @member {string} seedSentencepiecesFile + * @memberof sentencepiece.TrainerSpec + * @instance + */ + TrainerSpec.prototype.seedSentencepiecesFile = ''; + + /** + * Creates a new TrainerSpec instance using the specified properties. + * @function create + * @memberof sentencepiece.TrainerSpec + * @static + * @param {sentencepiece.ITrainerSpec=} [properties] Properties to set + * @returns {sentencepiece.TrainerSpec} TrainerSpec instance + */ + TrainerSpec.create = function create(properties) { + return new TrainerSpec(properties); + }; + + /** + * Encodes the specified TrainerSpec message. Does not implicitly {@link + * sentencepiece.TrainerSpec.verify|verify} messages. + * @function encode + * @memberof sentencepiece.TrainerSpec + * @static + * @param {sentencepiece.ITrainerSpec} message TrainerSpec message or plain + * object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + TrainerSpec.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.input != null && message.input.length) + for (let i = 0; i < message.input.length; ++i) + writer.uint32(/* id 1, wireType 2 =*/ 10).string(message.input[i]); + if (message.modelPrefix != null && + Object.hasOwnProperty.call(message, 'modelPrefix')) + writer.uint32(/* id 2, wireType 2 =*/ 18).string(message.modelPrefix); + if (message.modelType != null && + Object.hasOwnProperty.call(message, 'modelType')) + writer.uint32(/* id 3, wireType 0 =*/ 24).int32(message.modelType); + if (message.vocabSize != null && + Object.hasOwnProperty.call(message, 'vocabSize')) + writer.uint32(/* id 4, wireType 0 =*/ 32).int32(message.vocabSize); + if (message.acceptLanguage != null && message.acceptLanguage.length) + for (let i = 0; i < message.acceptLanguage.length; ++i) + writer.uint32(/* id 5, wireType 2 =*/ 42) + .string(message.acceptLanguage[i]); + if (message.selfTestSampleSize != null && + Object.hasOwnProperty.call(message, 'selfTestSampleSize')) + writer.uint32(/* id 6, wireType 0 =*/ 48) + .int32(message.selfTestSampleSize); + if (message.inputFormat != null && + Object.hasOwnProperty.call(message, 'inputFormat')) + writer.uint32(/* id 7, wireType 2 =*/ 58).string(message.inputFormat); + if (message.characterCoverage != null && + Object.hasOwnProperty.call(message, 'characterCoverage')) + writer.uint32(/* id 10, wireType 5 =*/ 85) + .float(message.characterCoverage); + if (message.inputSentenceSize != null && + Object.hasOwnProperty.call(message, 'inputSentenceSize')) + writer.uint32(/* id 11, wireType 0 =*/ 88) + .uint64(message.inputSentenceSize); + if (message.miningSentenceSize != null && + Object.hasOwnProperty.call(message, 'miningSentenceSize')) + writer.uint32(/* id 12, wireType 0 =*/ 96) + .int32(message.miningSentenceSize); + if (message.trainingSentenceSize != null && + Object.hasOwnProperty.call(message, 'trainingSentenceSize')) + writer.uint32(/* id 13, wireType 0 =*/ 104) + .int32(message.trainingSentenceSize); + if (message.seedSentencepieceSize != null && + Object.hasOwnProperty.call(message, 'seedSentencepieceSize')) + writer.uint32(/* id 14, wireType 0 =*/ 112) + .int32(message.seedSentencepieceSize); + if (message.shrinkingFactor != null && + Object.hasOwnProperty.call(message, 'shrinkingFactor')) + writer.uint32(/* id 15, wireType 5 =*/ 125) + .float(message.shrinkingFactor); + if (message.numThreads != null && + Object.hasOwnProperty.call(message, 'numThreads')) + writer.uint32(/* id 16, wireType 0 =*/ 128).int32(message.numThreads); + if (message.numSubIterations != null && + Object.hasOwnProperty.call(message, 'numSubIterations')) + writer.uint32(/* id 17, wireType 0 =*/ 136) + .int32(message.numSubIterations); + if (message.maxSentenceLength != null && + Object.hasOwnProperty.call(message, 'maxSentenceLength')) + writer.uint32(/* id 18, wireType 0 =*/ 144) + .int32(message.maxSentenceLength); + if (message.shuffleInputSentence != null && + Object.hasOwnProperty.call(message, 'shuffleInputSentence')) + writer.uint32(/* id 19, wireType 0 =*/ 152) + .bool(message.shuffleInputSentence); + if (message.maxSentencepieceLength != null && + Object.hasOwnProperty.call(message, 'maxSentencepieceLength')) + writer.uint32(/* id 20, wireType 0 =*/ 160) + .int32(message.maxSentencepieceLength); + if (message.splitByUnicodeScript != null && + Object.hasOwnProperty.call(message, 'splitByUnicodeScript')) + writer.uint32(/* id 21, wireType 0 =*/ 168) + .bool(message.splitByUnicodeScript); + if (message.splitByWhitespace != null && + Object.hasOwnProperty.call(message, 'splitByWhitespace')) + writer.uint32(/* id 22, wireType 0 =*/ 176) + .bool(message.splitByWhitespace); + if (message.splitByNumber != null && + Object.hasOwnProperty.call(message, 'splitByNumber')) + writer.uint32(/* id 23, wireType 0 =*/ 184).bool(message.splitByNumber); + if (message.treatWhitespaceAsSuffix != null && + Object.hasOwnProperty.call(message, 'treatWhitespaceAsSuffix')) + writer.uint32(/* id 24, wireType 0 =*/ 192) + .bool(message.treatWhitespaceAsSuffix); + if (message.splitDigits != null && + Object.hasOwnProperty.call(message, 'splitDigits')) + writer.uint32(/* id 25, wireType 0 =*/ 200).bool(message.splitDigits); + if (message.allowWhitespaceOnlyPieces != null && + Object.hasOwnProperty.call(message, 'allowWhitespaceOnlyPieces')) + writer.uint32(/* id 26, wireType 0 =*/ 208) + .bool(message.allowWhitespaceOnlyPieces); + if (message.controlSymbols != null && message.controlSymbols.length) + for (let i = 0; i < message.controlSymbols.length; ++i) + writer.uint32(/* id 30, wireType 2 =*/ 242) + .string(message.controlSymbols[i]); + if (message.userDefinedSymbols != null && + message.userDefinedSymbols.length) + for (let i = 0; i < message.userDefinedSymbols.length; ++i) + writer.uint32(/* id 31, wireType 2 =*/ 250) + .string(message.userDefinedSymbols[i]); + if (message.vocabularyOutputPieceScore != null && + Object.hasOwnProperty.call(message, 'vocabularyOutputPieceScore')) + writer.uint32(/* id 32, wireType 0 =*/ 256) + .bool(message.vocabularyOutputPieceScore); + if (message.hardVocabLimit != null && + Object.hasOwnProperty.call(message, 'hardVocabLimit')) + writer.uint32(/* id 33, wireType 0 =*/ 264) + .bool(message.hardVocabLimit); + if (message.useAllVocab != null && + Object.hasOwnProperty.call(message, 'useAllVocab')) + writer.uint32(/* id 34, wireType 0 =*/ 272).bool(message.useAllVocab); + if (message.byteFallback != null && + Object.hasOwnProperty.call(message, 'byteFallback')) + writer.uint32(/* id 35, wireType 0 =*/ 280).bool(message.byteFallback); + if (message.requiredChars != null && + Object.hasOwnProperty.call(message, 'requiredChars')) + writer.uint32(/* id 36, wireType 2 =*/ 290) + .string(message.requiredChars); + if (message.unkId != null && Object.hasOwnProperty.call(message, 'unkId')) + writer.uint32(/* id 40, wireType 0 =*/ 320).int32(message.unkId); + if (message.bosId != null && Object.hasOwnProperty.call(message, 'bosId')) + writer.uint32(/* id 41, wireType 0 =*/ 328).int32(message.bosId); + if (message.eosId != null && Object.hasOwnProperty.call(message, 'eosId')) + writer.uint32(/* id 42, wireType 0 =*/ 336).int32(message.eosId); + if (message.padId != null && Object.hasOwnProperty.call(message, 'padId')) + writer.uint32(/* id 43, wireType 0 =*/ 344).int32(message.padId); + if (message.unkSurface != null && + Object.hasOwnProperty.call(message, 'unkSurface')) + writer.uint32(/* id 44, wireType 2 =*/ 354).string(message.unkSurface); + if (message.unkPiece != null && + Object.hasOwnProperty.call(message, 'unkPiece')) + writer.uint32(/* id 45, wireType 2 =*/ 362).string(message.unkPiece); + if (message.bosPiece != null && + Object.hasOwnProperty.call(message, 'bosPiece')) + writer.uint32(/* id 46, wireType 2 =*/ 370).string(message.bosPiece); + if (message.eosPiece != null && + Object.hasOwnProperty.call(message, 'eosPiece')) + writer.uint32(/* id 47, wireType 2 =*/ 378).string(message.eosPiece); + if (message.padPiece != null && + Object.hasOwnProperty.call(message, 'padPiece')) + writer.uint32(/* id 48, wireType 2 =*/ 386).string(message.padPiece); + if (message.trainExtremelyLargeCorpus != null && + Object.hasOwnProperty.call(message, 'trainExtremelyLargeCorpus')) + writer.uint32(/* id 49, wireType 0 =*/ 392) + .bool(message.trainExtremelyLargeCorpus); + if (message.enableDifferentialPrivacy != null && + Object.hasOwnProperty.call(message, 'enableDifferentialPrivacy')) + writer.uint32(/* id 50, wireType 0 =*/ 400) + .bool(message.enableDifferentialPrivacy); + if (message.differentialPrivacyNoiseLevel != null && + Object.hasOwnProperty.call(message, 'differentialPrivacyNoiseLevel')) + writer.uint32(/* id 51, wireType 5 =*/ 413) + .float(message.differentialPrivacyNoiseLevel); + if (message.differentialPrivacyClippingThreshold != null && + Object.hasOwnProperty.call( + message, 'differentialPrivacyClippingThreshold')) + writer.uint32(/* id 52, wireType 0 =*/ 416) + .uint64(message.differentialPrivacyClippingThreshold); + if (message.pretokenizationDelimiter != null && + Object.hasOwnProperty.call(message, 'pretokenizationDelimiter')) + writer.uint32(/* id 53, wireType 2 =*/ 426) + .string(message.pretokenizationDelimiter); + if (message.seedSentencepiecesFile != null && + Object.hasOwnProperty.call(message, 'seedSentencepiecesFile')) + writer.uint32(/* id 54, wireType 2 =*/ 434) + .string(message.seedSentencepiecesFile); + return writer; + }; + + /** + * Encodes the specified TrainerSpec message, length delimited. Does not + * implicitly {@link sentencepiece.TrainerSpec.verify|verify} messages. + * @function encodeDelimited + * @memberof sentencepiece.TrainerSpec + * @static + * @param {sentencepiece.ITrainerSpec} message TrainerSpec message or plain + * object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + TrainerSpec.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a TrainerSpec message from the specified reader or buffer. + * @function decode + * @memberof sentencepiece.TrainerSpec + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode + * from + * @param {number} [length] Message length if known beforehand + * @returns {sentencepiece.TrainerSpec} TrainerSpec + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + TrainerSpec.decode = function decode(reader, length, error) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + let end = length === undefined ? reader.len : reader.pos + length, + message = new $root.sentencepiece.TrainerSpec(); + while (reader.pos < end) { + let tag = reader.uint32(); + if (tag === error) break; + switch (tag >>> 3) { + case 1: { + if (!(message.input && message.input.length)) message.input = []; + message.input.push(reader.string()); + break; + } + case 7: { + message.inputFormat = reader.string(); + break; + } + case 2: { + message.modelPrefix = reader.string(); + break; + } + case 3: { + message.modelType = reader.int32(); + break; + } + case 4: { + message.vocabSize = reader.int32(); + break; + } + case 5: { + if (!(message.acceptLanguage && message.acceptLanguage.length)) + message.acceptLanguage = []; + message.acceptLanguage.push(reader.string()); + break; + } + case 6: { + message.selfTestSampleSize = reader.int32(); + break; + } + case 50: { + message.enableDifferentialPrivacy = reader.bool(); + break; + } + case 51: { + message.differentialPrivacyNoiseLevel = reader.float(); + break; + } + case 52: { + message.differentialPrivacyClippingThreshold = reader.uint64(); + break; + } + case 10: { + message.characterCoverage = reader.float(); + break; + } + case 11: { + message.inputSentenceSize = reader.uint64(); + break; + } + case 19: { + message.shuffleInputSentence = reader.bool(); + break; + } + case 12: { + message.miningSentenceSize = reader.int32(); + break; + } + case 13: { + message.trainingSentenceSize = reader.int32(); + break; + } + case 14: { + message.seedSentencepieceSize = reader.int32(); + break; + } + case 15: { + message.shrinkingFactor = reader.float(); + break; + } + case 18: { + message.maxSentenceLength = reader.int32(); + break; + } + case 16: { + message.numThreads = reader.int32(); + break; + } + case 17: { + message.numSubIterations = reader.int32(); + break; + } + case 20: { + message.maxSentencepieceLength = reader.int32(); + break; + } + case 21: { + message.splitByUnicodeScript = reader.bool(); + break; + } + case 23: { + message.splitByNumber = reader.bool(); + break; + } + case 22: { + message.splitByWhitespace = reader.bool(); + break; + } + case 24: { + message.treatWhitespaceAsSuffix = reader.bool(); + break; + } + case 26: { + message.allowWhitespaceOnlyPieces = reader.bool(); + break; + } + case 25: { + message.splitDigits = reader.bool(); + break; + } + case 53: { + message.pretokenizationDelimiter = reader.string(); + break; + } + case 30: { + if (!(message.controlSymbols && message.controlSymbols.length)) + message.controlSymbols = []; + message.controlSymbols.push(reader.string()); + break; + } + case 31: { + if (!(message.userDefinedSymbols && + message.userDefinedSymbols.length)) + message.userDefinedSymbols = []; + message.userDefinedSymbols.push(reader.string()); + break; + } + case 36: { + message.requiredChars = reader.string(); + break; + } + case 35: { + message.byteFallback = reader.bool(); + break; + } + case 32: { + message.vocabularyOutputPieceScore = reader.bool(); + break; + } + case 33: { + message.hardVocabLimit = reader.bool(); + break; + } + case 34: { + message.useAllVocab = reader.bool(); + break; + } + case 40: { + message.unkId = reader.int32(); + break; + } + case 41: { + message.bosId = reader.int32(); + break; + } + case 42: { + message.eosId = reader.int32(); + break; + } + case 43: { + message.padId = reader.int32(); + break; + } + case 45: { + message.unkPiece = reader.string(); + break; + } + case 46: { + message.bosPiece = reader.string(); + break; + } + case 47: { + message.eosPiece = reader.string(); + break; + } + case 48: { + message.padPiece = reader.string(); + break; + } + case 44: { + message.unkSurface = reader.string(); + break; + } + case 49: { + message.trainExtremelyLargeCorpus = reader.bool(); + break; + } + case 54: { + message.seedSentencepiecesFile = reader.string(); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a TrainerSpec message from the specified reader or buffer, length + * delimited. + * @function decodeDelimited + * @memberof sentencepiece.TrainerSpec + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode + * from + * @returns {sentencepiece.TrainerSpec} TrainerSpec + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + TrainerSpec.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a TrainerSpec message. + * @function verify + * @memberof sentencepiece.TrainerSpec + * @static + * @param {Object.<string,*>} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is + * not + */ + TrainerSpec.verify = function verify(message) { + if (typeof message !== 'object' || message === null) + return 'object expected'; + if (message.input != null && message.hasOwnProperty('input')) { + if (!Array.isArray(message.input)) return 'input: array expected'; + for (let i = 0; i < message.input.length; ++i) + if (!$util.isString(message.input[i])) + return 'input: string[] expected'; + } + if (message.inputFormat != null && message.hasOwnProperty('inputFormat')) + if (!$util.isString(message.inputFormat)) + return 'inputFormat: string expected'; + if (message.modelPrefix != null && message.hasOwnProperty('modelPrefix')) + if (!$util.isString(message.modelPrefix)) + return 'modelPrefix: string expected'; + if (message.modelType != null && message.hasOwnProperty('modelType')) + switch (message.modelType) { + default: + return 'modelType: enum value expected'; + case 1: + case 2: + case 3: + case 4: + break; + } + if (message.vocabSize != null && message.hasOwnProperty('vocabSize')) + if (!$util.isInteger(message.vocabSize)) + return 'vocabSize: integer expected'; + if (message.acceptLanguage != null && + message.hasOwnProperty('acceptLanguage')) { + if (!Array.isArray(message.acceptLanguage)) + return 'acceptLanguage: array expected'; + for (let i = 0; i < message.acceptLanguage.length; ++i) + if (!$util.isString(message.acceptLanguage[i])) + return 'acceptLanguage: string[] expected'; + } + if (message.selfTestSampleSize != null && + message.hasOwnProperty('selfTestSampleSize')) + if (!$util.isInteger(message.selfTestSampleSize)) + return 'selfTestSampleSize: integer expected'; + if (message.enableDifferentialPrivacy != null && + message.hasOwnProperty('enableDifferentialPrivacy')) + if (typeof message.enableDifferentialPrivacy !== 'boolean') + return 'enableDifferentialPrivacy: boolean expected'; + if (message.differentialPrivacyNoiseLevel != null && + message.hasOwnProperty('differentialPrivacyNoiseLevel')) + if (typeof message.differentialPrivacyNoiseLevel !== 'number') + return 'differentialPrivacyNoiseLevel: number expected'; + if (message.differentialPrivacyClippingThreshold != null && + message.hasOwnProperty('differentialPrivacyClippingThreshold')) + if (!$util.isInteger(message.differentialPrivacyClippingThreshold) && + !(message.differentialPrivacyClippingThreshold && + $util.isInteger( + message.differentialPrivacyClippingThreshold.low) && + $util.isInteger( + message.differentialPrivacyClippingThreshold.high))) + return 'differentialPrivacyClippingThreshold: integer|Long expected'; + if (message.characterCoverage != null && + message.hasOwnProperty('characterCoverage')) + if (typeof message.characterCoverage !== 'number') + return 'characterCoverage: number expected'; + if (message.inputSentenceSize != null && + message.hasOwnProperty('inputSentenceSize')) + if (!$util.isInteger(message.inputSentenceSize) && + !(message.inputSentenceSize && + $util.isInteger(message.inputSentenceSize.low) && + $util.isInteger(message.inputSentenceSize.high))) + return 'inputSentenceSize: integer|Long expected'; + if (message.shuffleInputSentence != null && + message.hasOwnProperty('shuffleInputSentence')) + if (typeof message.shuffleInputSentence !== 'boolean') + return 'shuffleInputSentence: boolean expected'; + if (message.miningSentenceSize != null && + message.hasOwnProperty('miningSentenceSize')) + if (!$util.isInteger(message.miningSentenceSize)) + return 'miningSentenceSize: integer expected'; + if (message.trainingSentenceSize != null && + message.hasOwnProperty('trainingSentenceSize')) + if (!$util.isInteger(message.trainingSentenceSize)) + return 'trainingSentenceSize: integer expected'; + if (message.seedSentencepieceSize != null && + message.hasOwnProperty('seedSentencepieceSize')) + if (!$util.isInteger(message.seedSentencepieceSize)) + return 'seedSentencepieceSize: integer expected'; + if (message.shrinkingFactor != null && + message.hasOwnProperty('shrinkingFactor')) + if (typeof message.shrinkingFactor !== 'number') + return 'shrinkingFactor: number expected'; + if (message.maxSentenceLength != null && + message.hasOwnProperty('maxSentenceLength')) + if (!$util.isInteger(message.maxSentenceLength)) + return 'maxSentenceLength: integer expected'; + if (message.numThreads != null && message.hasOwnProperty('numThreads')) + if (!$util.isInteger(message.numThreads)) + return 'numThreads: integer expected'; + if (message.numSubIterations != null && + message.hasOwnProperty('numSubIterations')) + if (!$util.isInteger(message.numSubIterations)) + return 'numSubIterations: integer expected'; + if (message.maxSentencepieceLength != null && + message.hasOwnProperty('maxSentencepieceLength')) + if (!$util.isInteger(message.maxSentencepieceLength)) + return 'maxSentencepieceLength: integer expected'; + if (message.splitByUnicodeScript != null && + message.hasOwnProperty('splitByUnicodeScript')) + if (typeof message.splitByUnicodeScript !== 'boolean') + return 'splitByUnicodeScript: boolean expected'; + if (message.splitByNumber != null && + message.hasOwnProperty('splitByNumber')) + if (typeof message.splitByNumber !== 'boolean') + return 'splitByNumber: boolean expected'; + if (message.splitByWhitespace != null && + message.hasOwnProperty('splitByWhitespace')) + if (typeof message.splitByWhitespace !== 'boolean') + return 'splitByWhitespace: boolean expected'; + if (message.treatWhitespaceAsSuffix != null && + message.hasOwnProperty('treatWhitespaceAsSuffix')) + if (typeof message.treatWhitespaceAsSuffix !== 'boolean') + return 'treatWhitespaceAsSuffix: boolean expected'; + if (message.allowWhitespaceOnlyPieces != null && + message.hasOwnProperty('allowWhitespaceOnlyPieces')) + if (typeof message.allowWhitespaceOnlyPieces !== 'boolean') + return 'allowWhitespaceOnlyPieces: boolean expected'; + if (message.splitDigits != null && message.hasOwnProperty('splitDigits')) + if (typeof message.splitDigits !== 'boolean') + return 'splitDigits: boolean expected'; + if (message.pretokenizationDelimiter != null && + message.hasOwnProperty('pretokenizationDelimiter')) + if (!$util.isString(message.pretokenizationDelimiter)) + return 'pretokenizationDelimiter: string expected'; + if (message.controlSymbols != null && + message.hasOwnProperty('controlSymbols')) { + if (!Array.isArray(message.controlSymbols)) + return 'controlSymbols: array expected'; + for (let i = 0; i < message.controlSymbols.length; ++i) + if (!$util.isString(message.controlSymbols[i])) + return 'controlSymbols: string[] expected'; + } + if (message.userDefinedSymbols != null && + message.hasOwnProperty('userDefinedSymbols')) { + if (!Array.isArray(message.userDefinedSymbols)) + return 'userDefinedSymbols: array expected'; + for (let i = 0; i < message.userDefinedSymbols.length; ++i) + if (!$util.isString(message.userDefinedSymbols[i])) + return 'userDefinedSymbols: string[] expected'; + } + if (message.requiredChars != null && + message.hasOwnProperty('requiredChars')) + if (!$util.isString(message.requiredChars)) + return 'requiredChars: string expected'; + if (message.byteFallback != null && + message.hasOwnProperty('byteFallback')) + if (typeof message.byteFallback !== 'boolean') + return 'byteFallback: boolean expected'; + if (message.vocabularyOutputPieceScore != null && + message.hasOwnProperty('vocabularyOutputPieceScore')) + if (typeof message.vocabularyOutputPieceScore !== 'boolean') + return 'vocabularyOutputPieceScore: boolean expected'; + if (message.hardVocabLimit != null && + message.hasOwnProperty('hardVocabLimit')) + if (typeof message.hardVocabLimit !== 'boolean') + return 'hardVocabLimit: boolean expected'; + if (message.useAllVocab != null && message.hasOwnProperty('useAllVocab')) + if (typeof message.useAllVocab !== 'boolean') + return 'useAllVocab: boolean expected'; + if (message.unkId != null && message.hasOwnProperty('unkId')) + if (!$util.isInteger(message.unkId)) return 'unkId: integer expected'; + if (message.bosId != null && message.hasOwnProperty('bosId')) + if (!$util.isInteger(message.bosId)) return 'bosId: integer expected'; + if (message.eosId != null && message.hasOwnProperty('eosId')) + if (!$util.isInteger(message.eosId)) return 'eosId: integer expected'; + if (message.padId != null && message.hasOwnProperty('padId')) + if (!$util.isInteger(message.padId)) return 'padId: integer expected'; + if (message.unkPiece != null && message.hasOwnProperty('unkPiece')) + if (!$util.isString(message.unkPiece)) + return 'unkPiece: string expected'; + if (message.bosPiece != null && message.hasOwnProperty('bosPiece')) + if (!$util.isString(message.bosPiece)) + return 'bosPiece: string expected'; + if (message.eosPiece != null && message.hasOwnProperty('eosPiece')) + if (!$util.isString(message.eosPiece)) + return 'eosPiece: string expected'; + if (message.padPiece != null && message.hasOwnProperty('padPiece')) + if (!$util.isString(message.padPiece)) + return 'padPiece: string expected'; + if (message.unkSurface != null && message.hasOwnProperty('unkSurface')) + if (!$util.isString(message.unkSurface)) + return 'unkSurface: string expected'; + if (message.trainExtremelyLargeCorpus != null && + message.hasOwnProperty('trainExtremelyLargeCorpus')) + if (typeof message.trainExtremelyLargeCorpus !== 'boolean') + return 'trainExtremelyLargeCorpus: boolean expected'; + if (message.seedSentencepiecesFile != null && + message.hasOwnProperty('seedSentencepiecesFile')) + if (!$util.isString(message.seedSentencepiecesFile)) + return 'seedSentencepiecesFile: string expected'; + return null; + }; + + /** + * Creates a TrainerSpec message from a plain object. Also converts values + * to their respective internal types. + * @function fromObject + * @memberof sentencepiece.TrainerSpec + * @static + * @param {Object.<string,*>} object Plain object + * @returns {sentencepiece.TrainerSpec} TrainerSpec + */ + TrainerSpec.fromObject = function fromObject(object) { + if (object instanceof $root.sentencepiece.TrainerSpec) return object; + let message = new $root.sentencepiece.TrainerSpec(); + if (object.input) { + if (!Array.isArray(object.input)) + throw TypeError('.sentencepiece.TrainerSpec.input: array expected'); + message.input = []; + for (let i = 0; i < object.input.length; ++i) + message.input[i] = String(object.input[i]); + } + if (object.inputFormat != null) + message.inputFormat = String(object.inputFormat); + if (object.modelPrefix != null) + message.modelPrefix = String(object.modelPrefix); + switch (object.modelType) { + default: + if (typeof object.modelType === 'number') { + message.modelType = object.modelType; + break; + } + break; + case 'UNIGRAM': + case 1: + message.modelType = 1; + break; + case 'BPE': + case 2: + message.modelType = 2; + break; + case 'WORD': + case 3: + message.modelType = 3; + break; + case 'CHAR': + case 4: + message.modelType = 4; + break; + } + if (object.vocabSize != null) message.vocabSize = object.vocabSize | 0; + if (object.acceptLanguage) { + if (!Array.isArray(object.acceptLanguage)) + throw TypeError( + '.sentencepiece.TrainerSpec.acceptLanguage: array expected'); + message.acceptLanguage = []; + for (let i = 0; i < object.acceptLanguage.length; ++i) + message.acceptLanguage[i] = String(object.acceptLanguage[i]); + } + if (object.selfTestSampleSize != null) + message.selfTestSampleSize = object.selfTestSampleSize | 0; + if (object.enableDifferentialPrivacy != null) + message.enableDifferentialPrivacy = + Boolean(object.enableDifferentialPrivacy); + if (object.differentialPrivacyNoiseLevel != null) + message.differentialPrivacyNoiseLevel = + Number(object.differentialPrivacyNoiseLevel); + if (object.differentialPrivacyClippingThreshold != null) + if ($util.Long) + (message.differentialPrivacyClippingThreshold = $util.Long.fromValue( + object.differentialPrivacyClippingThreshold)) + .unsigned = true; + else if ( + typeof object.differentialPrivacyClippingThreshold === 'string') + message.differentialPrivacyClippingThreshold = + parseInt(object.differentialPrivacyClippingThreshold, 10); + else if ( + typeof object.differentialPrivacyClippingThreshold === 'number') + message.differentialPrivacyClippingThreshold = + object.differentialPrivacyClippingThreshold; + else if ( + typeof object.differentialPrivacyClippingThreshold === 'object') + message.differentialPrivacyClippingThreshold = + new $util + .LongBits( + object.differentialPrivacyClippingThreshold.low >>> 0, + object.differentialPrivacyClippingThreshold.high >>> 0) + .toNumber(true); + if (object.characterCoverage != null) + message.characterCoverage = Number(object.characterCoverage); + if (object.inputSentenceSize != null) + if ($util.Long) + (message.inputSentenceSize = + $util.Long.fromValue(object.inputSentenceSize)) + .unsigned = true; + else if (typeof object.inputSentenceSize === 'string') + message.inputSentenceSize = parseInt(object.inputSentenceSize, 10); + else if (typeof object.inputSentenceSize === 'number') + message.inputSentenceSize = object.inputSentenceSize; + else if (typeof object.inputSentenceSize === 'object') + message.inputSentenceSize = + new $util + .LongBits( + object.inputSentenceSize.low >>> 0, + object.inputSentenceSize.high >>> 0) + .toNumber(true); + if (object.shuffleInputSentence != null) + message.shuffleInputSentence = Boolean(object.shuffleInputSentence); + if (object.miningSentenceSize != null) + message.miningSentenceSize = object.miningSentenceSize | 0; + if (object.trainingSentenceSize != null) + message.trainingSentenceSize = object.trainingSentenceSize | 0; + if (object.seedSentencepieceSize != null) + message.seedSentencepieceSize = object.seedSentencepieceSize | 0; + if (object.shrinkingFactor != null) + message.shrinkingFactor = Number(object.shrinkingFactor); + if (object.maxSentenceLength != null) + message.maxSentenceLength = object.maxSentenceLength | 0; + if (object.numThreads != null) message.numThreads = object.numThreads | 0; + if (object.numSubIterations != null) + message.numSubIterations = object.numSubIterations | 0; + if (object.maxSentencepieceLength != null) + message.maxSentencepieceLength = object.maxSentencepieceLength | 0; + if (object.splitByUnicodeScript != null) + message.splitByUnicodeScript = Boolean(object.splitByUnicodeScript); + if (object.splitByNumber != null) + message.splitByNumber = Boolean(object.splitByNumber); + if (object.splitByWhitespace != null) + message.splitByWhitespace = Boolean(object.splitByWhitespace); + if (object.treatWhitespaceAsSuffix != null) + message.treatWhitespaceAsSuffix = + Boolean(object.treatWhitespaceAsSuffix); + if (object.allowWhitespaceOnlyPieces != null) + message.allowWhitespaceOnlyPieces = + Boolean(object.allowWhitespaceOnlyPieces); + if (object.splitDigits != null) + message.splitDigits = Boolean(object.splitDigits); + if (object.pretokenizationDelimiter != null) + message.pretokenizationDelimiter = + String(object.pretokenizationDelimiter); + if (object.controlSymbols) { + if (!Array.isArray(object.controlSymbols)) + throw TypeError( + '.sentencepiece.TrainerSpec.controlSymbols: array expected'); + message.controlSymbols = []; + for (let i = 0; i < object.controlSymbols.length; ++i) + message.controlSymbols[i] = String(object.controlSymbols[i]); + } + if (object.userDefinedSymbols) { + if (!Array.isArray(object.userDefinedSymbols)) + throw TypeError( + '.sentencepiece.TrainerSpec.userDefinedSymbols: array expected'); + message.userDefinedSymbols = []; + for (let i = 0; i < object.userDefinedSymbols.length; ++i) + message.userDefinedSymbols[i] = String(object.userDefinedSymbols[i]); + } + if (object.requiredChars != null) + message.requiredChars = String(object.requiredChars); + if (object.byteFallback != null) + message.byteFallback = Boolean(object.byteFallback); + if (object.vocabularyOutputPieceScore != null) + message.vocabularyOutputPieceScore = + Boolean(object.vocabularyOutputPieceScore); + if (object.hardVocabLimit != null) + message.hardVocabLimit = Boolean(object.hardVocabLimit); + if (object.useAllVocab != null) + message.useAllVocab = Boolean(object.useAllVocab); + if (object.unkId != null) message.unkId = object.unkId | 0; + if (object.bosId != null) message.bosId = object.bosId | 0; + if (object.eosId != null) message.eosId = object.eosId | 0; + if (object.padId != null) message.padId = object.padId | 0; + if (object.unkPiece != null) message.unkPiece = String(object.unkPiece); + if (object.bosPiece != null) message.bosPiece = String(object.bosPiece); + if (object.eosPiece != null) message.eosPiece = String(object.eosPiece); + if (object.padPiece != null) message.padPiece = String(object.padPiece); + if (object.unkSurface != null) + message.unkSurface = String(object.unkSurface); + if (object.trainExtremelyLargeCorpus != null) + message.trainExtremelyLargeCorpus = + Boolean(object.trainExtremelyLargeCorpus); + if (object.seedSentencepiecesFile != null) + message.seedSentencepiecesFile = String(object.seedSentencepiecesFile); + return message; + }; + + /** + * Creates a plain object from a TrainerSpec message. Also converts values + * to other types if specified. + * @function toObject + * @memberof sentencepiece.TrainerSpec + * @static + * @param {sentencepiece.TrainerSpec} message TrainerSpec + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.<string,*>} Plain object + */ + TrainerSpec.toObject = function toObject(message, options) { + if (!options) options = {}; + let object = {}; + if (options.arrays || options.defaults) { + object.input = []; + object.acceptLanguage = []; + object.controlSymbols = []; + object.userDefinedSymbols = []; + } + if (options.defaults) { + object.modelPrefix = ''; + object.modelType = options.enums === String ? 'UNIGRAM' : 1; + object.vocabSize = 8000; + object.selfTestSampleSize = 0; + object.inputFormat = ''; + object.characterCoverage = 0.9995; + if ($util.Long) { + let long = new $util.Long(0, 0, true); + object.inputSentenceSize = options.longs === String ? + long.toString() : + options.longs === Number ? long.toNumber() : + long; + } else + object.inputSentenceSize = options.longs === String ? '0' : 0; + object.miningSentenceSize = 0; + object.trainingSentenceSize = 0; + object.seedSentencepieceSize = 1000000; + object.shrinkingFactor = 0.75; + object.numThreads = 16; + object.numSubIterations = 2; + object.maxSentenceLength = 4192; + object.shuffleInputSentence = true; + object.maxSentencepieceLength = 16; + object.splitByUnicodeScript = true; + object.splitByWhitespace = true; + object.splitByNumber = true; + object.treatWhitespaceAsSuffix = false; + object.splitDigits = false; + object.allowWhitespaceOnlyPieces = false; + object.vocabularyOutputPieceScore = true; + object.hardVocabLimit = true; + object.useAllVocab = false; + object.byteFallback = false; + object.requiredChars = ''; + object.unkId = 0; + object.bosId = 1; + object.eosId = 2; + object.padId = -1; + object.unkSurface = ' E28187 '; + object.unkPiece = '<unk>'; + object.bosPiece = '<s>'; + object.eosPiece = '</s>'; + object.padPiece = '<pad>'; + object.trainExtremelyLargeCorpus = false; + object.enableDifferentialPrivacy = false; + object.differentialPrivacyNoiseLevel = 0; + if ($util.Long) { + let long = new $util.Long(0, 0, true); + object.differentialPrivacyClippingThreshold = + options.longs === String ? long.toString() : + options.longs === Number ? long.toNumber() : + long; + } else + object.differentialPrivacyClippingThreshold = + options.longs === String ? '0' : 0; + object.pretokenizationDelimiter = ''; + object.seedSentencepiecesFile = ''; + } + if (message.input && message.input.length) { + object.input = []; + for (let j = 0; j < message.input.length; ++j) + object.input[j] = message.input[j]; + } + if (message.modelPrefix != null && message.hasOwnProperty('modelPrefix')) + object.modelPrefix = message.modelPrefix; + if (message.modelType != null && message.hasOwnProperty('modelType')) + object.modelType = options.enums === String ? + $root.sentencepiece.TrainerSpec.ModelType[message.modelType] === + undefined ? + message.modelType : + $root.sentencepiece.TrainerSpec.ModelType[message.modelType] : + message.modelType; + if (message.vocabSize != null && message.hasOwnProperty('vocabSize')) + object.vocabSize = message.vocabSize; + if (message.acceptLanguage && message.acceptLanguage.length) { + object.acceptLanguage = []; + for (let j = 0; j < message.acceptLanguage.length; ++j) + object.acceptLanguage[j] = message.acceptLanguage[j]; + } + if (message.selfTestSampleSize != null && + message.hasOwnProperty('selfTestSampleSize')) + object.selfTestSampleSize = message.selfTestSampleSize; + if (message.inputFormat != null && message.hasOwnProperty('inputFormat')) + object.inputFormat = message.inputFormat; + if (message.characterCoverage != null && + message.hasOwnProperty('characterCoverage')) + object.characterCoverage = + options.json && !isFinite(message.characterCoverage) ? + String(message.characterCoverage) : + message.characterCoverage; + if (message.inputSentenceSize != null && + message.hasOwnProperty('inputSentenceSize')) + if (typeof message.inputSentenceSize === 'number') + object.inputSentenceSize = options.longs === String ? + String(message.inputSentenceSize) : + message.inputSentenceSize; + else + object.inputSentenceSize = options.longs === String ? + $util.Long.prototype.toString.call(message.inputSentenceSize) : + options.longs === Number ? + new $util + .LongBits( + message.inputSentenceSize.low >>> 0, + message.inputSentenceSize.high >>> 0) + .toNumber(true) : + message.inputSentenceSize; + if (message.miningSentenceSize != null && + message.hasOwnProperty('miningSentenceSize')) + object.miningSentenceSize = message.miningSentenceSize; + if (message.trainingSentenceSize != null && + message.hasOwnProperty('trainingSentenceSize')) + object.trainingSentenceSize = message.trainingSentenceSize; + if (message.seedSentencepieceSize != null && + message.hasOwnProperty('seedSentencepieceSize')) + object.seedSentencepieceSize = message.seedSentencepieceSize; + if (message.shrinkingFactor != null && + message.hasOwnProperty('shrinkingFactor')) + object.shrinkingFactor = + options.json && !isFinite(message.shrinkingFactor) ? + String(message.shrinkingFactor) : + message.shrinkingFactor; + if (message.numThreads != null && message.hasOwnProperty('numThreads')) + object.numThreads = message.numThreads; + if (message.numSubIterations != null && + message.hasOwnProperty('numSubIterations')) + object.numSubIterations = message.numSubIterations; + if (message.maxSentenceLength != null && + message.hasOwnProperty('maxSentenceLength')) + object.maxSentenceLength = message.maxSentenceLength; + if (message.shuffleInputSentence != null && + message.hasOwnProperty('shuffleInputSentence')) + object.shuffleInputSentence = message.shuffleInputSentence; + if (message.maxSentencepieceLength != null && + message.hasOwnProperty('maxSentencepieceLength')) + object.maxSentencepieceLength = message.maxSentencepieceLength; + if (message.splitByUnicodeScript != null && + message.hasOwnProperty('splitByUnicodeScript')) + object.splitByUnicodeScript = message.splitByUnicodeScript; + if (message.splitByWhitespace != null && + message.hasOwnProperty('splitByWhitespace')) + object.splitByWhitespace = message.splitByWhitespace; + if (message.splitByNumber != null && + message.hasOwnProperty('splitByNumber')) + object.splitByNumber = message.splitByNumber; + if (message.treatWhitespaceAsSuffix != null && + message.hasOwnProperty('treatWhitespaceAsSuffix')) + object.treatWhitespaceAsSuffix = message.treatWhitespaceAsSuffix; + if (message.splitDigits != null && message.hasOwnProperty('splitDigits')) + object.splitDigits = message.splitDigits; + if (message.allowWhitespaceOnlyPieces != null && + message.hasOwnProperty('allowWhitespaceOnlyPieces')) + object.allowWhitespaceOnlyPieces = message.allowWhitespaceOnlyPieces; + if (message.controlSymbols && message.controlSymbols.length) { + object.controlSymbols = []; + for (let j = 0; j < message.controlSymbols.length; ++j) + object.controlSymbols[j] = message.controlSymbols[j]; + } + if (message.userDefinedSymbols && message.userDefinedSymbols.length) { + object.userDefinedSymbols = []; + for (let j = 0; j < message.userDefinedSymbols.length; ++j) + object.userDefinedSymbols[j] = message.userDefinedSymbols[j]; + } + if (message.vocabularyOutputPieceScore != null && + message.hasOwnProperty('vocabularyOutputPieceScore')) + object.vocabularyOutputPieceScore = message.vocabularyOutputPieceScore; + if (message.hardVocabLimit != null && + message.hasOwnProperty('hardVocabLimit')) + object.hardVocabLimit = message.hardVocabLimit; + if (message.useAllVocab != null && message.hasOwnProperty('useAllVocab')) + object.useAllVocab = message.useAllVocab; + if (message.byteFallback != null && + message.hasOwnProperty('byteFallback')) + object.byteFallback = message.byteFallback; + if (message.requiredChars != null && + message.hasOwnProperty('requiredChars')) + object.requiredChars = message.requiredChars; + if (message.unkId != null && message.hasOwnProperty('unkId')) + object.unkId = message.unkId; + if (message.bosId != null && message.hasOwnProperty('bosId')) + object.bosId = message.bosId; + if (message.eosId != null && message.hasOwnProperty('eosId')) + object.eosId = message.eosId; + if (message.padId != null && message.hasOwnProperty('padId')) + object.padId = message.padId; + if (message.unkSurface != null && message.hasOwnProperty('unkSurface')) + object.unkSurface = message.unkSurface; + if (message.unkPiece != null && message.hasOwnProperty('unkPiece')) + object.unkPiece = message.unkPiece; + if (message.bosPiece != null && message.hasOwnProperty('bosPiece')) + object.bosPiece = message.bosPiece; + if (message.eosPiece != null && message.hasOwnProperty('eosPiece')) + object.eosPiece = message.eosPiece; + if (message.padPiece != null && message.hasOwnProperty('padPiece')) + object.padPiece = message.padPiece; + if (message.trainExtremelyLargeCorpus != null && + message.hasOwnProperty('trainExtremelyLargeCorpus')) + object.trainExtremelyLargeCorpus = message.trainExtremelyLargeCorpus; + if (message.enableDifferentialPrivacy != null && + message.hasOwnProperty('enableDifferentialPrivacy')) + object.enableDifferentialPrivacy = message.enableDifferentialPrivacy; + if (message.differentialPrivacyNoiseLevel != null && + message.hasOwnProperty('differentialPrivacyNoiseLevel')) + object.differentialPrivacyNoiseLevel = + options.json && !isFinite(message.differentialPrivacyNoiseLevel) ? + String(message.differentialPrivacyNoiseLevel) : + message.differentialPrivacyNoiseLevel; + if (message.differentialPrivacyClippingThreshold != null && + message.hasOwnProperty('differentialPrivacyClippingThreshold')) + if (typeof message.differentialPrivacyClippingThreshold === 'number') + object.differentialPrivacyClippingThreshold = + options.longs === String ? + String(message.differentialPrivacyClippingThreshold) : + message.differentialPrivacyClippingThreshold; + else + object.differentialPrivacyClippingThreshold = + options.longs === String ? + $util.Long.prototype.toString.call( + message.differentialPrivacyClippingThreshold) : + options.longs === Number ? + new $util + .LongBits( + message.differentialPrivacyClippingThreshold.low >>> 0, + message.differentialPrivacyClippingThreshold.high >>> 0) + .toNumber(true) : + message.differentialPrivacyClippingThreshold; + if (message.pretokenizationDelimiter != null && + message.hasOwnProperty('pretokenizationDelimiter')) + object.pretokenizationDelimiter = message.pretokenizationDelimiter; + if (message.seedSentencepiecesFile != null && + message.hasOwnProperty('seedSentencepiecesFile')) + object.seedSentencepiecesFile = message.seedSentencepiecesFile; + return object; + }; + + /** + * Converts this TrainerSpec to JSON. + * @function toJSON + * @memberof sentencepiece.TrainerSpec + * @instance + * @returns {Object.<string,*>} JSON object + */ + TrainerSpec.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for TrainerSpec + * @function getTypeUrl + * @memberof sentencepiece.TrainerSpec + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default + * "type.googleapis.com") + * @returns {string} The default type url + */ + TrainerSpec.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/sentencepiece.TrainerSpec'; + }; + + /** + * ModelType enum. + * @name sentencepiece.TrainerSpec.ModelType + * @enum {number} + * @property {number} UNIGRAM=1 UNIGRAM value + * @property {number} BPE=2 BPE value + * @property {number} WORD=3 WORD value + * @property {number} CHAR=4 CHAR value + */ + TrainerSpec.ModelType = (function() { + const valuesById = {}, values = Object.create(valuesById); + values[valuesById[1] = 'UNIGRAM'] = 1; + values[valuesById[2] = 'BPE'] = 2; + values[valuesById[3] = 'WORD'] = 3; + values[valuesById[4] = 'CHAR'] = 4; + return values; + })(); + + return TrainerSpec; + })(); + + sentencepiece.NormalizerSpec = (function() { + /** + * Properties of a NormalizerSpec. + * @memberof sentencepiece + * @interface INormalizerSpec + * @property {string|null} [name] NormalizerSpec name + * @property {Uint8Array|null} [precompiledCharsmap] NormalizerSpec + * precompiledCharsmap + * @property {boolean|null} [addDummyPrefix] NormalizerSpec addDummyPrefix + * @property {boolean|null} [removeExtraWhitespaces] NormalizerSpec + * removeExtraWhitespaces + * @property {boolean|null} [escapeWhitespaces] NormalizerSpec + * escapeWhitespaces + * @property {string|null} [normalizationRuleTsv] NormalizerSpec + * normalizationRuleTsv + */ + + /** + * Constructs a new NormalizerSpec. + * @memberof sentencepiece + * @classdesc Represents a NormalizerSpec. + * @implements INormalizerSpec + * @constructor + * @param {sentencepiece.INormalizerSpec=} [properties] Properties to set + */ + function NormalizerSpec(properties) { + if (properties) + for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * NormalizerSpec name. + * @member {string} name + * @memberof sentencepiece.NormalizerSpec + * @instance + */ + NormalizerSpec.prototype.name = ''; + + /** + * NormalizerSpec precompiledCharsmap. + * @member {Uint8Array} precompiledCharsmap + * @memberof sentencepiece.NormalizerSpec + * @instance + */ + NormalizerSpec.prototype.precompiledCharsmap = $util.newBuffer([]); + + /** + * NormalizerSpec addDummyPrefix. + * @member {boolean} addDummyPrefix + * @memberof sentencepiece.NormalizerSpec + * @instance + */ + NormalizerSpec.prototype.addDummyPrefix = true; + + /** + * NormalizerSpec removeExtraWhitespaces. + * @member {boolean} removeExtraWhitespaces + * @memberof sentencepiece.NormalizerSpec + * @instance + */ + NormalizerSpec.prototype.removeExtraWhitespaces = true; + + /** + * NormalizerSpec escapeWhitespaces. + * @member {boolean} escapeWhitespaces + * @memberof sentencepiece.NormalizerSpec + * @instance + */ + NormalizerSpec.prototype.escapeWhitespaces = true; + + /** + * NormalizerSpec normalizationRuleTsv. + * @member {string} normalizationRuleTsv + * @memberof sentencepiece.NormalizerSpec + * @instance + */ + NormalizerSpec.prototype.normalizationRuleTsv = ''; + + /** + * Creates a new NormalizerSpec instance using the specified properties. + * @function create + * @memberof sentencepiece.NormalizerSpec + * @static + * @param {sentencepiece.INormalizerSpec=} [properties] Properties to set + * @returns {sentencepiece.NormalizerSpec} NormalizerSpec instance + */ + NormalizerSpec.create = function create(properties) { + return new NormalizerSpec(properties); + }; + + /** + * Encodes the specified NormalizerSpec message. Does not implicitly {@link + * sentencepiece.NormalizerSpec.verify|verify} messages. + * @function encode + * @memberof sentencepiece.NormalizerSpec + * @static + * @param {sentencepiece.INormalizerSpec} message NormalizerSpec message or + * plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + NormalizerSpec.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.name != null && Object.hasOwnProperty.call(message, 'name')) + writer.uint32(/* id 1, wireType 2 =*/ 10).string(message.name); + if (message.precompiledCharsmap != null && + Object.hasOwnProperty.call(message, 'precompiledCharsmap')) + writer.uint32(/* id 2, wireType 2 =*/ 18) + .bytes(message.precompiledCharsmap); + if (message.addDummyPrefix != null && + Object.hasOwnProperty.call(message, 'addDummyPrefix')) + writer.uint32(/* id 3, wireType 0 =*/ 24).bool(message.addDummyPrefix); + if (message.removeExtraWhitespaces != null && + Object.hasOwnProperty.call(message, 'removeExtraWhitespaces')) + writer.uint32(/* id 4, wireType 0 =*/ 32) + .bool(message.removeExtraWhitespaces); + if (message.escapeWhitespaces != null && + Object.hasOwnProperty.call(message, 'escapeWhitespaces')) + writer.uint32(/* id 5, wireType 0 =*/ 40) + .bool(message.escapeWhitespaces); + if (message.normalizationRuleTsv != null && + Object.hasOwnProperty.call(message, 'normalizationRuleTsv')) + writer.uint32(/* id 6, wireType 2 =*/ 50) + .string(message.normalizationRuleTsv); + return writer; + }; + + /** + * Encodes the specified NormalizerSpec message, length delimited. Does not + * implicitly {@link sentencepiece.NormalizerSpec.verify|verify} messages. + * @function encodeDelimited + * @memberof sentencepiece.NormalizerSpec + * @static + * @param {sentencepiece.INormalizerSpec} message NormalizerSpec message or + * plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + NormalizerSpec.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a NormalizerSpec message from the specified reader or buffer. + * @function decode + * @memberof sentencepiece.NormalizerSpec + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode + * from + * @param {number} [length] Message length if known beforehand + * @returns {sentencepiece.NormalizerSpec} NormalizerSpec + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + NormalizerSpec.decode = function decode(reader, length, error) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + let end = length === undefined ? reader.len : reader.pos + length, + message = new $root.sentencepiece.NormalizerSpec(); + while (reader.pos < end) { + let tag = reader.uint32(); + if (tag === error) break; + switch (tag >>> 3) { + case 1: { + message.name = reader.string(); + break; + } + case 2: { + message.precompiledCharsmap = reader.bytes(); + break; + } + case 3: { + message.addDummyPrefix = reader.bool(); + break; + } + case 4: { + message.removeExtraWhitespaces = reader.bool(); + break; + } + case 5: { + message.escapeWhitespaces = reader.bool(); + break; + } + case 6: { + message.normalizationRuleTsv = reader.string(); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a NormalizerSpec message from the specified reader or buffer, + * length delimited. + * @function decodeDelimited + * @memberof sentencepiece.NormalizerSpec + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode + * from + * @returns {sentencepiece.NormalizerSpec} NormalizerSpec + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + NormalizerSpec.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a NormalizerSpec message. + * @function verify + * @memberof sentencepiece.NormalizerSpec + * @static + * @param {Object.<string,*>} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is + * not + */ + NormalizerSpec.verify = function verify(message) { + if (typeof message !== 'object' || message === null) + return 'object expected'; + if (message.name != null && message.hasOwnProperty('name')) + if (!$util.isString(message.name)) return 'name: string expected'; + if (message.precompiledCharsmap != null && + message.hasOwnProperty('precompiledCharsmap')) + if (!(message.precompiledCharsmap && + typeof message.precompiledCharsmap.length === 'number' || + $util.isString(message.precompiledCharsmap))) + return 'precompiledCharsmap: buffer expected'; + if (message.addDummyPrefix != null && + message.hasOwnProperty('addDummyPrefix')) + if (typeof message.addDummyPrefix !== 'boolean') + return 'addDummyPrefix: boolean expected'; + if (message.removeExtraWhitespaces != null && + message.hasOwnProperty('removeExtraWhitespaces')) + if (typeof message.removeExtraWhitespaces !== 'boolean') + return 'removeExtraWhitespaces: boolean expected'; + if (message.escapeWhitespaces != null && + message.hasOwnProperty('escapeWhitespaces')) + if (typeof message.escapeWhitespaces !== 'boolean') + return 'escapeWhitespaces: boolean expected'; + if (message.normalizationRuleTsv != null && + message.hasOwnProperty('normalizationRuleTsv')) + if (!$util.isString(message.normalizationRuleTsv)) + return 'normalizationRuleTsv: string expected'; + return null; + }; + + /** + * Creates a NormalizerSpec message from a plain object. Also converts + * values to their respective internal types. + * @function fromObject + * @memberof sentencepiece.NormalizerSpec + * @static + * @param {Object.<string,*>} object Plain object + * @returns {sentencepiece.NormalizerSpec} NormalizerSpec + */ + NormalizerSpec.fromObject = function fromObject(object) { + if (object instanceof $root.sentencepiece.NormalizerSpec) return object; + let message = new $root.sentencepiece.NormalizerSpec(); + if (object.name != null) message.name = String(object.name); + if (object.precompiledCharsmap != null) + if (typeof object.precompiledCharsmap === 'string') + $util.base64.decode( + object.precompiledCharsmap, + message.precompiledCharsmap = $util.newBuffer( + $util.base64.length(object.precompiledCharsmap)), + 0); + else if (object.precompiledCharsmap.length >= 0) + message.precompiledCharsmap = object.precompiledCharsmap; + if (object.addDummyPrefix != null) + message.addDummyPrefix = Boolean(object.addDummyPrefix); + if (object.removeExtraWhitespaces != null) + message.removeExtraWhitespaces = Boolean(object.removeExtraWhitespaces); + if (object.escapeWhitespaces != null) + message.escapeWhitespaces = Boolean(object.escapeWhitespaces); + if (object.normalizationRuleTsv != null) + message.normalizationRuleTsv = String(object.normalizationRuleTsv); + return message; + }; + + /** + * Creates a plain object from a NormalizerSpec message. Also converts + * values to other types if specified. + * @function toObject + * @memberof sentencepiece.NormalizerSpec + * @static + * @param {sentencepiece.NormalizerSpec} message NormalizerSpec + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.<string,*>} Plain object + */ + NormalizerSpec.toObject = function toObject(message, options) { + if (!options) options = {}; + let object = {}; + if (options.defaults) { + object.name = ''; + if (options.bytes === String) + object.precompiledCharsmap = ''; + else { + object.precompiledCharsmap = []; + if (options.bytes !== Array) + object.precompiledCharsmap = + $util.newBuffer(object.precompiledCharsmap); + } + object.addDummyPrefix = true; + object.removeExtraWhitespaces = true; + object.escapeWhitespaces = true; + object.normalizationRuleTsv = ''; + } + if (message.name != null && message.hasOwnProperty('name')) + object.name = message.name; + if (message.precompiledCharsmap != null && + message.hasOwnProperty('precompiledCharsmap')) + object.precompiledCharsmap = options.bytes === String ? + $util.base64.encode( + message.precompiledCharsmap, 0, + message.precompiledCharsmap.length) : + options.bytes === Array ? + Array.prototype.slice.call(message.precompiledCharsmap) : + message.precompiledCharsmap; + if (message.addDummyPrefix != null && + message.hasOwnProperty('addDummyPrefix')) + object.addDummyPrefix = message.addDummyPrefix; + if (message.removeExtraWhitespaces != null && + message.hasOwnProperty('removeExtraWhitespaces')) + object.removeExtraWhitespaces = message.removeExtraWhitespaces; + if (message.escapeWhitespaces != null && + message.hasOwnProperty('escapeWhitespaces')) + object.escapeWhitespaces = message.escapeWhitespaces; + if (message.normalizationRuleTsv != null && + message.hasOwnProperty('normalizationRuleTsv')) + object.normalizationRuleTsv = message.normalizationRuleTsv; + return object; + }; + + /** + * Converts this NormalizerSpec to JSON. + * @function toJSON + * @memberof sentencepiece.NormalizerSpec + * @instance + * @returns {Object.<string,*>} JSON object + */ + NormalizerSpec.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for NormalizerSpec + * @function getTypeUrl + * @memberof sentencepiece.NormalizerSpec + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default + * "type.googleapis.com") + * @returns {string} The default type url + */ + NormalizerSpec.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/sentencepiece.NormalizerSpec'; + }; + + return NormalizerSpec; + })(); + + sentencepiece.SelfTestData = (function() { + /** + * Properties of a SelfTestData. + * @memberof sentencepiece + * @interface ISelfTestData + * @property {Array.<sentencepiece.SelfTestData.ISample>|null} [samples] + * SelfTestData samples + */ + + /** + * Constructs a new SelfTestData. + * @memberof sentencepiece + * @classdesc Represents a SelfTestData. + * @implements ISelfTestData + * @constructor + * @param {sentencepiece.ISelfTestData=} [properties] Properties to set + */ + function SelfTestData(properties) { + this.samples = []; + if (properties) + for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * SelfTestData samples. + * @member {Array.<sentencepiece.SelfTestData.ISample>} samples + * @memberof sentencepiece.SelfTestData + * @instance + */ + SelfTestData.prototype.samples = $util.emptyArray; + + /** + * Creates a new SelfTestData instance using the specified properties. + * @function create + * @memberof sentencepiece.SelfTestData + * @static + * @param {sentencepiece.ISelfTestData=} [properties] Properties to set + * @returns {sentencepiece.SelfTestData} SelfTestData instance + */ + SelfTestData.create = function create(properties) { + return new SelfTestData(properties); + }; + + /** + * Encodes the specified SelfTestData message. Does not implicitly {@link + * sentencepiece.SelfTestData.verify|verify} messages. + * @function encode + * @memberof sentencepiece.SelfTestData + * @static + * @param {sentencepiece.ISelfTestData} message SelfTestData message or + * plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + SelfTestData.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.samples != null && message.samples.length) + for (let i = 0; i < message.samples.length; ++i) + $root.sentencepiece.SelfTestData.Sample + .encode( + message.samples[i], + writer.uint32(/* id 1, wireType 2 =*/ 10).fork()) + .ldelim(); + return writer; + }; + + /** + * Encodes the specified SelfTestData message, length delimited. Does not + * implicitly {@link sentencepiece.SelfTestData.verify|verify} messages. + * @function encodeDelimited + * @memberof sentencepiece.SelfTestData + * @static + * @param {sentencepiece.ISelfTestData} message SelfTestData message or + * plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + SelfTestData.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a SelfTestData message from the specified reader or buffer. + * @function decode + * @memberof sentencepiece.SelfTestData + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode + * from + * @param {number} [length] Message length if known beforehand + * @returns {sentencepiece.SelfTestData} SelfTestData + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + SelfTestData.decode = function decode(reader, length, error) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + let end = length === undefined ? reader.len : reader.pos + length, + message = new $root.sentencepiece.SelfTestData(); + while (reader.pos < end) { + let tag = reader.uint32(); + if (tag === error) break; + switch (tag >>> 3) { + case 1: { + if (!(message.samples && message.samples.length)) + message.samples = []; + message.samples.push($root.sentencepiece.SelfTestData.Sample.decode( + reader, reader.uint32())); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a SelfTestData message from the specified reader or buffer, + * length delimited. + * @function decodeDelimited + * @memberof sentencepiece.SelfTestData + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode + * from + * @returns {sentencepiece.SelfTestData} SelfTestData + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + SelfTestData.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a SelfTestData message. + * @function verify + * @memberof sentencepiece.SelfTestData + * @static + * @param {Object.<string,*>} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is + * not + */ + SelfTestData.verify = function verify(message) { + if (typeof message !== 'object' || message === null) + return 'object expected'; + if (message.samples != null && message.hasOwnProperty('samples')) { + if (!Array.isArray(message.samples)) return 'samples: array expected'; + for (let i = 0; i < message.samples.length; ++i) { + let error = $root.sentencepiece.SelfTestData.Sample.verify( + message.samples[i]); + if (error) return 'samples.' + error; + } + } + return null; + }; + + /** + * Creates a SelfTestData message from a plain object. Also converts values + * to their respective internal types. + * @function fromObject + * @memberof sentencepiece.SelfTestData + * @static + * @param {Object.<string,*>} object Plain object + * @returns {sentencepiece.SelfTestData} SelfTestData + */ + SelfTestData.fromObject = function fromObject(object) { + if (object instanceof $root.sentencepiece.SelfTestData) return object; + let message = new $root.sentencepiece.SelfTestData(); + if (object.samples) { + if (!Array.isArray(object.samples)) + throw TypeError( + '.sentencepiece.SelfTestData.samples: array expected'); + message.samples = []; + for (let i = 0; i < object.samples.length; ++i) { + if (typeof object.samples[i] !== 'object') + throw TypeError( + '.sentencepiece.SelfTestData.samples: object expected'); + message.samples[i] = + $root.sentencepiece.SelfTestData.Sample.fromObject( + object.samples[i]); + } + } + return message; + }; + + /** + * Creates a plain object from a SelfTestData message. Also converts values + * to other types if specified. + * @function toObject + * @memberof sentencepiece.SelfTestData + * @static + * @param {sentencepiece.SelfTestData} message SelfTestData + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.<string,*>} Plain object + */ + SelfTestData.toObject = function toObject(message, options) { + if (!options) options = {}; + let object = {}; + if (options.arrays || options.defaults) object.samples = []; + if (message.samples && message.samples.length) { + object.samples = []; + for (let j = 0; j < message.samples.length; ++j) + object.samples[j] = $root.sentencepiece.SelfTestData.Sample.toObject( + message.samples[j], options); + } + return object; + }; + + /** + * Converts this SelfTestData to JSON. + * @function toJSON + * @memberof sentencepiece.SelfTestData + * @instance + * @returns {Object.<string,*>} JSON object + */ + SelfTestData.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for SelfTestData + * @function getTypeUrl + * @memberof sentencepiece.SelfTestData + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default + * "type.googleapis.com") + * @returns {string} The default type url + */ + SelfTestData.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/sentencepiece.SelfTestData'; + }; + + SelfTestData.Sample = (function() { + /** + * Properties of a Sample. + * @memberof sentencepiece.SelfTestData + * @interface ISample + * @property {string|null} [input] Sample input + * @property {string|null} [expected] Sample expected + */ + + /** + * Constructs a new Sample. + * @memberof sentencepiece.SelfTestData + * @classdesc Represents a Sample. + * @implements ISample + * @constructor + * @param {sentencepiece.SelfTestData.ISample=} [properties] Properties to + * set + */ + function Sample(properties) { + if (properties) + for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * Sample input. + * @member {string} input + * @memberof sentencepiece.SelfTestData.Sample + * @instance + */ + Sample.prototype.input = ''; + + /** + * Sample expected. + * @member {string} expected + * @memberof sentencepiece.SelfTestData.Sample + * @instance + */ + Sample.prototype.expected = ''; + + /** + * Creates a new Sample instance using the specified properties. + * @function create + * @memberof sentencepiece.SelfTestData.Sample + * @static + * @param {sentencepiece.SelfTestData.ISample=} [properties] Properties to + * set + * @returns {sentencepiece.SelfTestData.Sample} Sample instance + */ + Sample.create = function create(properties) { + return new Sample(properties); + }; + + /** + * Encodes the specified Sample message. Does not implicitly {@link + * sentencepiece.SelfTestData.Sample.verify|verify} messages. + * @function encode + * @memberof sentencepiece.SelfTestData.Sample + * @static + * @param {sentencepiece.SelfTestData.ISample} message Sample message or + * plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Sample.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.input != null && + Object.hasOwnProperty.call(message, 'input')) + writer.uint32(/* id 1, wireType 2 =*/ 10).string(message.input); + if (message.expected != null && + Object.hasOwnProperty.call(message, 'expected')) + writer.uint32(/* id 2, wireType 2 =*/ 18).string(message.expected); + return writer; + }; + + /** + * Encodes the specified Sample message, length delimited. Does not + * implicitly {@link sentencepiece.SelfTestData.Sample.verify|verify} + * messages. + * @function encodeDelimited + * @memberof sentencepiece.SelfTestData.Sample + * @static + * @param {sentencepiece.SelfTestData.ISample} message Sample message or + * plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Sample.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a Sample message from the specified reader or buffer. + * @function decode + * @memberof sentencepiece.SelfTestData.Sample + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode + * from + * @param {number} [length] Message length if known beforehand + * @returns {sentencepiece.SelfTestData.Sample} Sample + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Sample.decode = function decode(reader, length, error) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + let end = length === undefined ? reader.len : reader.pos + length, + message = new $root.sentencepiece.SelfTestData.Sample(); + while (reader.pos < end) { + let tag = reader.uint32(); + if (tag === error) break; + switch (tag >>> 3) { + case 1: { + message.input = reader.string(); + break; + } + case 2: { + message.expected = reader.string(); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a Sample message from the specified reader or buffer, length + * delimited. + * @function decodeDelimited + * @memberof sentencepiece.SelfTestData.Sample + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode + * from + * @returns {sentencepiece.SelfTestData.Sample} Sample + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Sample.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a Sample message. + * @function verify + * @memberof sentencepiece.SelfTestData.Sample + * @static + * @param {Object.<string,*>} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is + * not + */ + Sample.verify = function verify(message) { + if (typeof message !== 'object' || message === null) + return 'object expected'; + if (message.input != null && message.hasOwnProperty('input')) + if (!$util.isString(message.input)) return 'input: string expected'; + if (message.expected != null && message.hasOwnProperty('expected')) + if (!$util.isString(message.expected)) + return 'expected: string expected'; + return null; + }; + + /** + * Creates a Sample message from a plain object. Also converts values to + * their respective internal types. + * @function fromObject + * @memberof sentencepiece.SelfTestData.Sample + * @static + * @param {Object.<string,*>} object Plain object + * @returns {sentencepiece.SelfTestData.Sample} Sample + */ + Sample.fromObject = function fromObject(object) { + if (object instanceof $root.sentencepiece.SelfTestData.Sample) + return object; + let message = new $root.sentencepiece.SelfTestData.Sample(); + if (object.input != null) message.input = String(object.input); + if (object.expected != null) message.expected = String(object.expected); + return message; + }; + + /** + * Creates a plain object from a Sample message. Also converts values to + * other types if specified. + * @function toObject + * @memberof sentencepiece.SelfTestData.Sample + * @static + * @param {sentencepiece.SelfTestData.Sample} message Sample + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.<string,*>} Plain object + */ + Sample.toObject = function toObject(message, options) { + if (!options) options = {}; + let object = {}; + if (options.defaults) { + object.input = ''; + object.expected = ''; + } + if (message.input != null && message.hasOwnProperty('input')) + object.input = message.input; + if (message.expected != null && message.hasOwnProperty('expected')) + object.expected = message.expected; + return object; + }; + + /** + * Converts this Sample to JSON. + * @function toJSON + * @memberof sentencepiece.SelfTestData.Sample + * @instance + * @returns {Object.<string,*>} JSON object + */ + Sample.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for Sample + * @function getTypeUrl + * @memberof sentencepiece.SelfTestData.Sample + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default + * "type.googleapis.com") + * @returns {string} The default type url + */ + Sample.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/sentencepiece.SelfTestData.Sample'; + }; + + return Sample; + })(); + + return SelfTestData; + })(); + + sentencepiece.ModelProto = (function() { + /** + * Properties of a ModelProto. + * @memberof sentencepiece + * @interface IModelProto + * @property {Array.<sentencepiece.ModelProto.ISentencePiece>|null} [pieces] + * ModelProto pieces + * @property {sentencepiece.ITrainerSpec|null} [trainerSpec] ModelProto + * trainerSpec + * @property {sentencepiece.INormalizerSpec|null} [normalizerSpec] + * ModelProto normalizerSpec + * @property {sentencepiece.ISelfTestData|null} [selfTestData] ModelProto + * selfTestData + * @property {sentencepiece.INormalizerSpec|null} [denormalizerSpec] + * ModelProto denormalizerSpec + */ + + /** + * Constructs a new ModelProto. + * @memberof sentencepiece + * @classdesc Represents a ModelProto. + * @implements IModelProto + * @constructor + * @param {sentencepiece.IModelProto=} [properties] Properties to set + */ + function ModelProto(properties) { + this.pieces = []; + if (properties) + for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * ModelProto pieces. + * @member {Array.<sentencepiece.ModelProto.ISentencePiece>} pieces + * @memberof sentencepiece.ModelProto + * @instance + */ + ModelProto.prototype.pieces = $util.emptyArray; + + /** + * ModelProto trainerSpec. + * @member {sentencepiece.ITrainerSpec|null|undefined} trainerSpec + * @memberof sentencepiece.ModelProto + * @instance + */ + ModelProto.prototype.trainerSpec = null; + + /** + * ModelProto normalizerSpec. + * @member {sentencepiece.INormalizerSpec|null|undefined} normalizerSpec + * @memberof sentencepiece.ModelProto + * @instance + */ + ModelProto.prototype.normalizerSpec = null; + + /** + * ModelProto selfTestData. + * @member {sentencepiece.ISelfTestData|null|undefined} selfTestData + * @memberof sentencepiece.ModelProto + * @instance + */ + ModelProto.prototype.selfTestData = null; + + /** + * ModelProto denormalizerSpec. + * @member {sentencepiece.INormalizerSpec|null|undefined} denormalizerSpec + * @memberof sentencepiece.ModelProto + * @instance + */ + ModelProto.prototype.denormalizerSpec = null; + + /** + * Creates a new ModelProto instance using the specified properties. + * @function create + * @memberof sentencepiece.ModelProto + * @static + * @param {sentencepiece.IModelProto=} [properties] Properties to set + * @returns {sentencepiece.ModelProto} ModelProto instance + */ + ModelProto.create = function create(properties) { + return new ModelProto(properties); + }; + + /** + * Encodes the specified ModelProto message. Does not implicitly {@link + * sentencepiece.ModelProto.verify|verify} messages. + * @function encode + * @memberof sentencepiece.ModelProto + * @static + * @param {sentencepiece.IModelProto} message ModelProto message or plain + * object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + ModelProto.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.pieces != null && message.pieces.length) + for (let i = 0; i < message.pieces.length; ++i) + $root.sentencepiece.ModelProto.SentencePiece + .encode( + message.pieces[i], + writer.uint32(/* id 1, wireType 2 =*/ 10).fork()) + .ldelim(); + if (message.trainerSpec != null && + Object.hasOwnProperty.call(message, 'trainerSpec')) + $root.sentencepiece.TrainerSpec + .encode( + message.trainerSpec, + writer.uint32(/* id 2, wireType 2 =*/ 18).fork()) + .ldelim(); + if (message.normalizerSpec != null && + Object.hasOwnProperty.call(message, 'normalizerSpec')) + $root.sentencepiece.NormalizerSpec + .encode( + message.normalizerSpec, + writer.uint32(/* id 3, wireType 2 =*/ 26).fork()) + .ldelim(); + if (message.selfTestData != null && + Object.hasOwnProperty.call(message, 'selfTestData')) + $root.sentencepiece.SelfTestData + .encode( + message.selfTestData, + writer.uint32(/* id 4, wireType 2 =*/ 34).fork()) + .ldelim(); + if (message.denormalizerSpec != null && + Object.hasOwnProperty.call(message, 'denormalizerSpec')) + $root.sentencepiece.NormalizerSpec + .encode( + message.denormalizerSpec, + writer.uint32(/* id 5, wireType 2 =*/ 42).fork()) + .ldelim(); + return writer; + }; + + /** + * Encodes the specified ModelProto message, length delimited. Does not + * implicitly {@link sentencepiece.ModelProto.verify|verify} messages. + * @function encodeDelimited + * @memberof sentencepiece.ModelProto + * @static + * @param {sentencepiece.IModelProto} message ModelProto message or plain + * object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + ModelProto.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a ModelProto message from the specified reader or buffer. + * @function decode + * @memberof sentencepiece.ModelProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode + * from + * @param {number} [length] Message length if known beforehand + * @returns {sentencepiece.ModelProto} ModelProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + ModelProto.decode = function decode(reader, length, error) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + let end = length === undefined ? reader.len : reader.pos + length, + message = new $root.sentencepiece.ModelProto(); + while (reader.pos < end) { + let tag = reader.uint32(); + if (tag === error) break; + switch (tag >>> 3) { + case 1: { + if (!(message.pieces && message.pieces.length)) message.pieces = []; + message.pieces.push( + $root.sentencepiece.ModelProto.SentencePiece.decode( + reader, reader.uint32())); + break; + } + case 2: { + message.trainerSpec = + $root.sentencepiece.TrainerSpec.decode(reader, reader.uint32()); + break; + } + case 3: { + message.normalizerSpec = $root.sentencepiece.NormalizerSpec.decode( + reader, reader.uint32()); + break; + } + case 4: { + message.selfTestData = $root.sentencepiece.SelfTestData.decode( + reader, reader.uint32()); + break; + } + case 5: { + message.denormalizerSpec = + $root.sentencepiece.NormalizerSpec.decode( + reader, reader.uint32()); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a ModelProto message from the specified reader or buffer, length + * delimited. + * @function decodeDelimited + * @memberof sentencepiece.ModelProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode + * from + * @returns {sentencepiece.ModelProto} ModelProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + ModelProto.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a ModelProto message. + * @function verify + * @memberof sentencepiece.ModelProto + * @static + * @param {Object.<string,*>} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is + * not + */ + ModelProto.verify = function verify(message) { + if (typeof message !== 'object' || message === null) + return 'object expected'; + if (message.pieces != null && message.hasOwnProperty('pieces')) { + if (!Array.isArray(message.pieces)) return 'pieces: array expected'; + for (let i = 0; i < message.pieces.length; ++i) { + let error = $root.sentencepiece.ModelProto.SentencePiece.verify( + message.pieces[i]); + if (error) return 'pieces.' + error; + } + } + if (message.trainerSpec != null && + message.hasOwnProperty('trainerSpec')) { + let error = $root.sentencepiece.TrainerSpec.verify(message.trainerSpec); + if (error) return 'trainerSpec.' + error; + } + if (message.normalizerSpec != null && + message.hasOwnProperty('normalizerSpec')) { + let error = + $root.sentencepiece.NormalizerSpec.verify(message.normalizerSpec); + if (error) return 'normalizerSpec.' + error; + } + if (message.selfTestData != null && + message.hasOwnProperty('selfTestData')) { + let error = + $root.sentencepiece.SelfTestData.verify(message.selfTestData); + if (error) return 'selfTestData.' + error; + } + if (message.denormalizerSpec != null && + message.hasOwnProperty('denormalizerSpec')) { + let error = + $root.sentencepiece.NormalizerSpec.verify(message.denormalizerSpec); + if (error) return 'denormalizerSpec.' + error; + } + return null; + }; + + /** + * Creates a ModelProto message from a plain object. Also converts values to + * their respective internal types. + * @function fromObject + * @memberof sentencepiece.ModelProto + * @static + * @param {Object.<string,*>} object Plain object + * @returns {sentencepiece.ModelProto} ModelProto + */ + ModelProto.fromObject = function fromObject(object) { + if (object instanceof $root.sentencepiece.ModelProto) return object; + let message = new $root.sentencepiece.ModelProto(); + if (object.pieces) { + if (!Array.isArray(object.pieces)) + throw TypeError('.sentencepiece.ModelProto.pieces: array expected'); + message.pieces = []; + for (let i = 0; i < object.pieces.length; ++i) { + if (typeof object.pieces[i] !== 'object') + throw TypeError( + '.sentencepiece.ModelProto.pieces: object expected'); + message.pieces[i] = + $root.sentencepiece.ModelProto.SentencePiece.fromObject( + object.pieces[i]); + } + } + if (object.trainerSpec != null) { + if (typeof object.trainerSpec !== 'object') + throw TypeError( + '.sentencepiece.ModelProto.trainerSpec: object expected'); + message.trainerSpec = + $root.sentencepiece.TrainerSpec.fromObject(object.trainerSpec); + } + if (object.normalizerSpec != null) { + if (typeof object.normalizerSpec !== 'object') + throw TypeError( + '.sentencepiece.ModelProto.normalizerSpec: object expected'); + message.normalizerSpec = $root.sentencepiece.NormalizerSpec.fromObject( + object.normalizerSpec); + } + if (object.selfTestData != null) { + if (typeof object.selfTestData !== 'object') + throw TypeError( + '.sentencepiece.ModelProto.selfTestData: object expected'); + message.selfTestData = + $root.sentencepiece.SelfTestData.fromObject(object.selfTestData); + } + if (object.denormalizerSpec != null) { + if (typeof object.denormalizerSpec !== 'object') + throw TypeError( + '.sentencepiece.ModelProto.denormalizerSpec: object expected'); + message.denormalizerSpec = + $root.sentencepiece.NormalizerSpec.fromObject( + object.denormalizerSpec); + } + return message; + }; + + /** + * Creates a plain object from a ModelProto message. Also converts values to + * other types if specified. + * @function toObject + * @memberof sentencepiece.ModelProto + * @static + * @param {sentencepiece.ModelProto} message ModelProto + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.<string,*>} Plain object + */ + ModelProto.toObject = function toObject(message, options) { + if (!options) options = {}; + let object = {}; + if (options.arrays || options.defaults) object.pieces = []; + if (options.defaults) { + object.trainerSpec = null; + object.normalizerSpec = null; + object.selfTestData = null; + object.denormalizerSpec = null; + } + if (message.pieces && message.pieces.length) { + object.pieces = []; + for (let j = 0; j < message.pieces.length; ++j) + object.pieces[j] = + $root.sentencepiece.ModelProto.SentencePiece.toObject( + message.pieces[j], options); + } + if (message.trainerSpec != null && message.hasOwnProperty('trainerSpec')) + object.trainerSpec = $root.sentencepiece.TrainerSpec.toObject( + message.trainerSpec, options); + if (message.normalizerSpec != null && + message.hasOwnProperty('normalizerSpec')) + object.normalizerSpec = $root.sentencepiece.NormalizerSpec.toObject( + message.normalizerSpec, options); + if (message.selfTestData != null && + message.hasOwnProperty('selfTestData')) + object.selfTestData = $root.sentencepiece.SelfTestData.toObject( + message.selfTestData, options); + if (message.denormalizerSpec != null && + message.hasOwnProperty('denormalizerSpec')) + object.denormalizerSpec = $root.sentencepiece.NormalizerSpec.toObject( + message.denormalizerSpec, options); + return object; + }; + + /** + * Converts this ModelProto to JSON. + * @function toJSON + * @memberof sentencepiece.ModelProto + * @instance + * @returns {Object.<string,*>} JSON object + */ + ModelProto.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for ModelProto + * @function getTypeUrl + * @memberof sentencepiece.ModelProto + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default + * "type.googleapis.com") + * @returns {string} The default type url + */ + ModelProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/sentencepiece.ModelProto'; + }; + + ModelProto.SentencePiece = (function() { + /** + * Properties of a SentencePiece. + * @memberof sentencepiece.ModelProto + * @interface ISentencePiece + * @property {string|null} [piece] SentencePiece piece + * @property {number|null} [score] SentencePiece score + * @property {sentencepiece.ModelProto.SentencePiece.Type|null} [type] + * SentencePiece type + */ + + /** + * Constructs a new SentencePiece. + * @memberof sentencepiece.ModelProto + * @classdesc Represents a SentencePiece. + * @implements ISentencePiece + * @constructor + * @param {sentencepiece.ModelProto.ISentencePiece=} [properties] + * Properties to set + */ + function SentencePiece(properties) { + if (properties) + for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * SentencePiece piece. + * @member {string} piece + * @memberof sentencepiece.ModelProto.SentencePiece + * @instance + */ + SentencePiece.prototype.piece = ''; + + /** + * SentencePiece score. + * @member {number} score + * @memberof sentencepiece.ModelProto.SentencePiece + * @instance + */ + SentencePiece.prototype.score = 0; + + /** + * SentencePiece type. + * @member {sentencepiece.ModelProto.SentencePiece.Type} type + * @memberof sentencepiece.ModelProto.SentencePiece + * @instance + */ + SentencePiece.prototype.type = 1; + + /** + * Creates a new SentencePiece instance using the specified properties. + * @function create + * @memberof sentencepiece.ModelProto.SentencePiece + * @static + * @param {sentencepiece.ModelProto.ISentencePiece=} [properties] + * Properties to set + * @returns {sentencepiece.ModelProto.SentencePiece} SentencePiece + * instance + */ + SentencePiece.create = function create(properties) { + return new SentencePiece(properties); + }; + + /** + * Encodes the specified SentencePiece message. Does not implicitly {@link + * sentencepiece.ModelProto.SentencePiece.verify|verify} messages. + * @function encode + * @memberof sentencepiece.ModelProto.SentencePiece + * @static + * @param {sentencepiece.ModelProto.ISentencePiece} message SentencePiece + * message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + SentencePiece.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.piece != null && + Object.hasOwnProperty.call(message, 'piece')) + writer.uint32(/* id 1, wireType 2 =*/ 10).string(message.piece); + if (message.score != null && + Object.hasOwnProperty.call(message, 'score')) + writer.uint32(/* id 2, wireType 5 =*/ 21).float(message.score); + if (message.type != null && Object.hasOwnProperty.call(message, 'type')) + writer.uint32(/* id 3, wireType 0 =*/ 24).int32(message.type); + return writer; + }; + + /** + * Encodes the specified SentencePiece message, length delimited. Does not + * implicitly {@link sentencepiece.ModelProto.SentencePiece.verify|verify} + * messages. + * @function encodeDelimited + * @memberof sentencepiece.ModelProto.SentencePiece + * @static + * @param {sentencepiece.ModelProto.ISentencePiece} message SentencePiece + * message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + SentencePiece.encodeDelimited = function encodeDelimited( + message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a SentencePiece message from the specified reader or buffer. + * @function decode + * @memberof sentencepiece.ModelProto.SentencePiece + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode + * from + * @param {number} [length] Message length if known beforehand + * @returns {sentencepiece.ModelProto.SentencePiece} SentencePiece + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + SentencePiece.decode = function decode(reader, length, error) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + let end = length === undefined ? reader.len : reader.pos + length, + message = new $root.sentencepiece.ModelProto.SentencePiece(); + while (reader.pos < end) { + let tag = reader.uint32(); + if (tag === error) break; + switch (tag >>> 3) { + case 1: { + message.piece = reader.string(); + break; + } + case 2: { + message.score = reader.float(); + break; + } + case 3: { + message.type = reader.int32(); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a SentencePiece message from the specified reader or buffer, + * length delimited. + * @function decodeDelimited + * @memberof sentencepiece.ModelProto.SentencePiece + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode + * from + * @returns {sentencepiece.ModelProto.SentencePiece} SentencePiece + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + SentencePiece.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a SentencePiece message. + * @function verify + * @memberof sentencepiece.ModelProto.SentencePiece + * @static + * @param {Object.<string,*>} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is + * not + */ + SentencePiece.verify = function verify(message) { + if (typeof message !== 'object' || message === null) + return 'object expected'; + if (message.piece != null && message.hasOwnProperty('piece')) + if (!$util.isString(message.piece)) return 'piece: string expected'; + if (message.score != null && message.hasOwnProperty('score')) + if (typeof message.score !== 'number') + return 'score: number expected'; + if (message.type != null && message.hasOwnProperty('type')) + switch (message.type) { + default: + return 'type: enum value expected'; + case 1: + case 2: + case 3: + case 4: + case 6: + case 5: + break; + } + return null; + }; + + /** + * Creates a SentencePiece message from a plain object. Also converts + * values to their respective internal types. + * @function fromObject + * @memberof sentencepiece.ModelProto.SentencePiece + * @static + * @param {Object.<string,*>} object Plain object + * @returns {sentencepiece.ModelProto.SentencePiece} SentencePiece + */ + SentencePiece.fromObject = function fromObject(object) { + if (object instanceof $root.sentencepiece.ModelProto.SentencePiece) + return object; + let message = new $root.sentencepiece.ModelProto.SentencePiece(); + if (object.piece != null) message.piece = String(object.piece); + if (object.score != null) message.score = Number(object.score); + switch (object.type) { + default: + if (typeof object.type === 'number') { + message.type = object.type; + break; + } + break; + case 'NORMAL': + case 1: + message.type = 1; + break; + case 'UNKNOWN': + case 2: + message.type = 2; + break; + case 'CONTROL': + case 3: + message.type = 3; + break; + case 'USER_DEFINED': + case 4: + message.type = 4; + break; + case 'BYTE': + case 6: + message.type = 6; + break; + case 'UNUSED': + case 5: + message.type = 5; + break; + } + return message; + }; + + /** + * Creates a plain object from a SentencePiece message. Also converts + * values to other types if specified. + * @function toObject + * @memberof sentencepiece.ModelProto.SentencePiece + * @static + * @param {sentencepiece.ModelProto.SentencePiece} message SentencePiece + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.<string,*>} Plain object + */ + SentencePiece.toObject = function toObject(message, options) { + if (!options) options = {}; + let object = {}; + if (options.defaults) { + object.piece = ''; + object.score = 0; + object.type = options.enums === String ? 'NORMAL' : 1; + } + if (message.piece != null && message.hasOwnProperty('piece')) + object.piece = message.piece; + if (message.score != null && message.hasOwnProperty('score')) + object.score = options.json && !isFinite(message.score) ? + String(message.score) : + message.score; + if (message.type != null && message.hasOwnProperty('type')) + object.type = options.enums === String ? + $root.sentencepiece.ModelProto.SentencePiece + .Type[message.type] === undefined ? + message.type : + $root.sentencepiece.ModelProto.SentencePiece.Type[message.type] : + message.type; + return object; + }; + + /** + * Converts this SentencePiece to JSON. + * @function toJSON + * @memberof sentencepiece.ModelProto.SentencePiece + * @instance + * @returns {Object.<string,*>} JSON object + */ + SentencePiece.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for SentencePiece + * @function getTypeUrl + * @memberof sentencepiece.ModelProto.SentencePiece + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default + * "type.googleapis.com") + * @returns {string} The default type url + */ + SentencePiece.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/sentencepiece.ModelProto.SentencePiece'; + }; + + /** + * Type enum. + * @name sentencepiece.ModelProto.SentencePiece.Type + * @enum {number} + * @property {number} NORMAL=1 NORMAL value + * @property {number} UNKNOWN=2 UNKNOWN value + * @property {number} CONTROL=3 CONTROL value + * @property {number} USER_DEFINED=4 USER_DEFINED value + * @property {number} BYTE=6 BYTE value + * @property {number} UNUSED=5 UNUSED value + */ + SentencePiece.Type = (function() { + const valuesById = {}, values = Object.create(valuesById); + values[valuesById[1] = 'NORMAL'] = 1; + values[valuesById[2] = 'UNKNOWN'] = 2; + values[valuesById[3] = 'CONTROL'] = 3; + values[valuesById[4] = 'USER_DEFINED'] = 4; + values[valuesById[6] = 'BYTE'] = 6; + values[valuesById[5] = 'UNUSED'] = 5; + return values; + })(); + + return SentencePiece; + })(); + + return ModelProto; + })(); + + return sentencepiece; +})(); + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Pure TypeScript implementation of SentencePiece tokenizer. + * Translated from github.com/eliben/go-sentencepiece + */ +const WHITESPACE_SEPARATOR = '▁'; +const SYMBOL_BOS = '<bos>'; +const SYMBOL_EOS = '<eos>'; +const SYMBOL_PAD = '<pad>'; +/** + * Processor represents a SentencePiece processor (tokenizer). + * It converts input text into a sequence of tokens and back. + */ +class SentencePieceProcessor { + /** + * Creates a new Processor from model proto bytes. + */ + constructor(modelProtoBytes) { + var _a, _b; + this.model = this.parseModelProto(modelProtoBytes); + const tspec = this.model.trainerSpec; + if (!tspec || tspec.modelType !== ModelType.BPE) { + throw new Error(`Model type ${tspec === null || tspec === void 0 ? void 0 : tspec.modelType} not supported, only BPE is supported`); + } + const nspec = this.model.normalizerSpec; + if ((nspec === null || nspec === void 0 ? void 0 : nspec.addDummyPrefix) || (nspec === null || nspec === void 0 ? void 0 : nspec.removeExtraWhitespaces)) { + throw new Error(`Normalizer spec options not supported: ${JSON.stringify(nspec)}`); + } + const userDefined = new Set(); + this.pieces = new Map(); + this.reserved = new Map(); + this.byte2Token = new Map(); + this.idToByte = new Map(); + this.unknownID = -1; + this.maxPieceLength = 0; + if (!this.model.pieces) { + throw new Error('Model has no pieces'); + } + for (let i = 0; i < this.model.pieces.length; i++) { + const piece = this.model.pieces[i]; + const pieceText = (_a = piece.piece) !== null && _a !== void 0 ? _a : ''; + const pieceType = (_b = piece.type) !== null && _b !== void 0 ? _b : SentencePieceType.NORMAL; + const isNormalPiece = pieceType === SentencePieceType.NORMAL || + pieceType === SentencePieceType.USER_DEFINED || + pieceType === SentencePieceType.UNUSED; + if (isNormalPiece) { + this.pieces.set(pieceText, i); + this.maxPieceLength = Math.max(this.maxPieceLength, pieceText.length); + } + else { + this.reserved.set(pieceText, i); + } + if (pieceType === SentencePieceType.USER_DEFINED) { + userDefined.add(pieceText); + } + else if (pieceType === SentencePieceType.UNKNOWN) { + if (this.unknownID >= 0) { + throw new Error('unk redefined'); + } + this.unknownID = i; + } + else if (pieceType === SentencePieceType.BYTE) { + if (!tspec.byteFallback) { + throw new Error(`byte piece "${pieceText}" found although byte_fallback=false`); + } + const bv = convertHexValue(pieceText); + if (bv >= 0 && bv < 256) { + this.byte2Token.set(bv, { id: i, text: pieceText }); + this.idToByte.set(i, bv); + } + } + } + if (this.unknownID < 0) { + throw new Error('unk symbol is not defined'); + } + // If byte_fallback is specified, ensure all 256 byte values are present + if (tspec.byteFallback) { + for (let i = 0; i < 256; i++) { + if (!this.byte2Token.has(i)) { + throw new Error(`byte value 0x${i.toString(16).padStart(2, '0')} not found`); + } + } + } + this.userDefinedMatcher = new PrefixMatcher(userDefined); + } + /** + * Encodes text into a list of tokens. + */ + encode(text) { + var _a; + text = this.normalize(text); + const symList = []; + while (text.length > 0) { + const [slen, found] = this.symbolMatch(text); + const sym = { + noMerge: found, + symbol: text.substring(0, slen), + prev: symList.length - 1, + next: symList.length + 1, + }; + symList.push(sym); + text = text.substring(slen); + } + if (symList.length === 0) { + return []; + } + symList[symList.length - 1].next = -1; + const mergeQueue = new PriorityQueue(symList.length, (a, b) => { + if (a.score > b.score || (a.score === b.score && a.left < b.left)) { + return 1; + } + return -1; + }); + const findMerged = (x, y) => { + var _a; + const merged = x.symbol + y.symbol; + const id = this.pieces.get(merged); + if (id !== undefined && this.model.pieces) { + return [(_a = this.model.pieces[id].piece) !== null && _a !== void 0 ? _a : '', id, true]; + } + return ['', 0, false]; + }; + const suggestNewMergePair = (left, right) => { + var _a; + if (left === -1 || + right === -1 || + symList[left].noMerge || + symList[right].noMerge) { + return; + } + const [mergedSymbol, id, ok] = findMerged(symList[left], symList[right]); + if (ok && this.model.pieces) { + mergeQueue.insert({ + left, + right, + length: mergedSymbol.length, + score: (_a = this.model.pieces[id].score) !== null && _a !== void 0 ? _a : 0, + }); + } + }; + for (let i = 1; i < symList.length; i++) { + suggestNewMergePair(i - 1, i); + } + const candidateIsDead = (candidate) => { + const leftSymbol = symList[candidate.left].symbol; + const rightSymbol = symList[candidate.right].symbol; + return (leftSymbol === '' || + rightSymbol === '' || + leftSymbol.length + rightSymbol.length !== candidate.length); + }; + let mergeQueueDead = 0; + while (mergeQueue.len() > 0) { + const candidate = mergeQueue.popMax(); + const leftSymbol = symList[candidate.left]; + const rightSymbol = symList[candidate.right]; + if (candidateIsDead(candidate)) { + mergeQueueDead--; + continue; + } + if (mergeQueueDead * 3 > mergeQueue.len()) { + mergeQueue.removeFunc(candidateIsDead); + mergeQueueDead = 0; + } + const [mergedSymbol, , ok] = findMerged(leftSymbol, rightSymbol); + if (!ok) { + throw new Error('failed to merge symbols'); + } + symList[candidate.left].symbol = mergedSymbol; + symList[candidate.left].next = rightSymbol.next; + if (rightSymbol.next >= 0) { + symList[rightSymbol.next].prev = candidate.left; + } + symList[candidate.right].symbol = ''; + mergeQueueDead++; + suggestNewMergePair(leftSymbol.prev, candidate.left); + suggestNewMergePair(candidate.left, rightSymbol.next); + } + const tokens = []; + for (let i = 0; i >= 0; i = symList[i].next) { + const symbol = symList[i].symbol; + const id = this.symbolToID(symbol); + if (id === this.unknownID && ((_a = this.model.trainerSpec) === null || _a === void 0 ? void 0 : _a.byteFallback)) { + // Need to convert byte to token at UTF-8 bytes level + const bytes = new TextEncoder().encode(symbol); + for (let j = 0; j < bytes.length; j++) { + const byteToken = this.byte2Token.get(bytes[j]); + if (byteToken) { + tokens.push(byteToken); + } + } + } + else { + tokens.push({ id, text: symbol }); + } + } + return tokens; + } + /** + * Decodes a list of token IDs back into text. + */ + decode(ids) { + var _a, _b, _c; + const parts = []; + let i = 0; + while (i < ids.length) { + let nextNonByte = i; + while (nextNonByte < ids.length && this.isByteID(ids[nextNonByte])) { + nextNonByte++; + } + const numBytes = nextNonByte - i; + if (numBytes > 0) { + const bytes = []; + for (let bi = i; bi < nextNonByte; bi++) { + const byte = this.idToByte.get(ids[bi]); + if (byte !== undefined) { + bytes.push(byte); + } + } + const textDecoder = new TextDecoder('utf-8', { fatal: false }); + const text = textDecoder.decode(new Uint8Array(bytes)); + parts.push(text); + } + if (nextNonByte >= ids.length) { + break; + } + const id = ids[nextNonByte]; + // eslint-disable-next-line no-empty + if (this.isControlID(id)) ; + else if (id === this.unknownID) { + parts.push((_b = (_a = this.model.trainerSpec) === null || _a === void 0 ? void 0 : _a.unkSurface) !== null && _b !== void 0 ? _b : ''); + } + else if (this.model.pieces && this.model.pieces[id]) { + const piece = (_c = this.model.pieces[id].piece) !== null && _c !== void 0 ? _c : ''; + parts.push(this.replaceSeparatorsBySpace(piece)); + } + i = nextNonByte + 1; + } + return parts.join(''); + } + /** + * Decodes a list of tokens back into text. + */ + decodeTokens(tokens) { + return this.decode(tokens.map((t) => t.id)); + } + /** + * Returns information about the loaded model. + */ + modelInfo() { + var _a, _b; + const getControlID = (symbol) => { + const id = this.symbolToID(symbol); + return this.isControlID(id) ? id : -1; + }; + return { + vocabularySize: (_b = (_a = this.model.pieces) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0, + beginningOfSentenceID: getControlID(SYMBOL_BOS), + endOfSentenceID: getControlID(SYMBOL_EOS), + padID: getControlID(SYMBOL_PAD), + unknownID: this.unknownID, + }; + } + normalize(text) { + return text.replace(/ /g, WHITESPACE_SEPARATOR); + } + replaceSeparatorsBySpace(text) { + return text.replace(new RegExp(WHITESPACE_SEPARATOR, 'g'), ' '); + } + symbolMatch(text) { + const prefixLen = this.userDefinedMatcher.findPrefixLen(text); + if (prefixLen > 0) { + return [prefixLen, true]; + } + // Return character length (1), not byte length + // This matches the Java implementation where i++ advances by 1 character + return [1, false]; + } + symbolToID(symbol) { + const reservedID = this.reserved.get(symbol); + if (reservedID !== undefined) { + return reservedID; + } + const pieceID = this.pieces.get(symbol); + if (pieceID !== undefined) { + return pieceID; + } + return this.unknownID; + } + isByteID(id) { + if (!this.model.pieces || id >= this.model.pieces.length) { + return false; + } + return this.model.pieces[id].type === SentencePieceType.BYTE; + } + isControlID(id) { + if (!this.model.pieces || id >= this.model.pieces.length) { + return false; + } + return this.model.pieces[id].type === SentencePieceType.CONTROL; + } + parseModelProto(data) { + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l; + const decoded = sentencepiece.ModelProto.decode(data); + const model = { + pieces: (_a = decoded.pieces) === null || _a === void 0 ? void 0 : _a.map((p) => { + var _a, _b, _c; + return ({ + piece: (_a = p.piece) !== null && _a !== void 0 ? _a : undefined, + score: (_b = p.score) !== null && _b !== void 0 ? _b : undefined, + type: (_c = p.type) !== null && _c !== void 0 ? _c : undefined, + }); + }), + trainerSpec: decoded.trainerSpec + ? { + modelType: (_b = decoded.trainerSpec.modelType) !== null && _b !== void 0 ? _b : undefined, + vocabSize: (_c = decoded.trainerSpec.vocabSize) !== null && _c !== void 0 ? _c : undefined, + characterCoverage: (_d = decoded.trainerSpec.characterCoverage) !== null && _d !== void 0 ? _d : undefined, + byteFallback: (_e = decoded.trainerSpec.byteFallback) !== null && _e !== void 0 ? _e : undefined, + unkSurface: (_f = decoded.trainerSpec.unkSurface) !== null && _f !== void 0 ? _f : undefined, + } + : undefined, + normalizerSpec: decoded.normalizerSpec + ? { + name: (_g = decoded.normalizerSpec.name) !== null && _g !== void 0 ? _g : undefined, + precompiledCharsmap: decoded.normalizerSpec.precompiledCharsmap + ? new Uint8Array(decoded.normalizerSpec.precompiledCharsmap) + : undefined, + addDummyPrefix: (_h = decoded.normalizerSpec.addDummyPrefix) !== null && _h !== void 0 ? _h : undefined, + removeExtraWhitespaces: (_j = decoded.normalizerSpec.removeExtraWhitespaces) !== null && _j !== void 0 ? _j : undefined, + escapeWhitespaces: (_k = decoded.normalizerSpec.escapeWhitespaces) !== null && _k !== void 0 ? _k : undefined, + normalizationRuleTsv: (_l = decoded.normalizerSpec.normalizationRuleTsv) !== null && _l !== void 0 ? _l : undefined, + } + : undefined, + }; + return model; + } +} +function convertHexValue(bv) { + const match = bv.match(/^<0x([0-9A-Fa-f]{2})>$/); + if (!match) { + return -1; + } + return parseInt(match[1], 16); +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Source of truth: https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models + */ +const GEMINI_MODELS_TO_TOKENIZER_NAMES = { + 'gemini-2.5-pro': 'gemma3', + 'gemini-2.5-flash': 'gemma3', + 'gemini-2.5-flash-lite': 'gemma3', + 'gemini-2.0-flash': 'gemma3', + 'gemini-2.0-flash-lite': 'gemma3', +}; +const GEMINI_STABLE_MODELS_TO_TOKENIZER_NAMES = { + 'gemini-3-pro-preview': 'gemma3', + 'gemini-2.5-pro-preview-06-05': 'gemma3', + 'gemini-2.5-pro-preview-05-06': 'gemma3', + 'gemini-2.5-pro-exp-03-25': 'gemma3', + 'gemini-live-2.5-flash': 'gemma3', + 'gemini-2.5-flash-preview-05-20': 'gemma3', + 'gemini-2.5-flash-preview-04-17': 'gemma3', + 'gemini-2.5-flash-lite-preview-06-17': 'gemma3', + 'gemini-2.0-flash-001': 'gemma3', + 'gemini-2.0-flash-lite-001': 'gemma3', +}; +const TOKENIZERS = { + gemma2: { + modelUrl: 'https://raw.githubusercontent.com/google/gemma_pytorch/33b652c465537c6158f9a472ea5700e5e770ad3f/tokenizer/tokenizer.model', + modelHash: '61a7b147390c64585d6c3543dd6fc636906c9af3865a5548f27f31aee1d4c8e2', + }, + gemma3: { + modelUrl: 'https://raw.githubusercontent.com/google/gemma_pytorch/014acb7ac4563a5f77c76d7ff98f31b568c16508/tokenizer/gemma3_cleaned_262144_v2.spiece.model', + modelHash: '1299c11d7cf632ef3b4e11937501358ada021bbdf7c47638d13c0ee982f2e79c', + }, +}; +/** + * Gets the tokenizer name for the given model name. + * + * @param modelName The Gemini model name + * @return The tokenizer name to use + * @throws Error if the model is not supported + */ +function getTokenizerName(modelName) { + if (modelName in GEMINI_MODELS_TO_TOKENIZER_NAMES) { + return GEMINI_MODELS_TO_TOKENIZER_NAMES[modelName]; + } + if (modelName in GEMINI_STABLE_MODELS_TO_TOKENIZER_NAMES) { + return GEMINI_STABLE_MODELS_TO_TOKENIZER_NAMES[modelName]; + } + const supportedModels = [ + ...Object.keys(GEMINI_MODELS_TO_TOKENIZER_NAMES), + ...Object.keys(GEMINI_STABLE_MODELS_TO_TOKENIZER_NAMES), + ].join(', '); + throw new Error(`Model ${modelName} is not supported for local tokenization. Supported models: ${supportedModels}.`); +} +/** + * Gets the tokenizer configuration for the given tokenizer name. + * + * @param tokenizerName The tokenizer name + * @return The tokenizer configuration + * @throws Error if the tokenizer is not found + */ +function getTokenizerConfig(tokenizerName) { + if (!(tokenizerName in TOKENIZERS)) { + throw new Error(`Tokenizer ${tokenizerName} is not supported. Supported tokenizers: ${Object.keys(TOKENIZERS).join(', ')}`); + } + return TOKENIZERS[tokenizerName]; +} +/** + * Loads tokenizer model bytes from cache or URL. + * + * @param tokenizerName The tokenizer name + * @param platform Platform-specific implementations + * @return The model bytes + */ +async function loadModelProtoBytes(tokenizerName, platform) { + const config = getTokenizerConfig(tokenizerName); + const encoder = new TextEncoder(); + const cacheKey = await platform.fileSystem.computeSha1(encoder.encode(config.modelUrl)); + let modelData = await platform.cache.load(cacheKey, config.modelHash); + if (!modelData) { + modelData = await platform.fileSystem.fetchFromUrl(config.modelUrl); + const isValid = await platform.fileSystem.validateHash(modelData, config.modelHash); + if (!isValid) { + const actualHash = await platform.fileSystem.computeSha1(modelData); + throw new Error(`Downloaded model file is corrupted. Expected hash ${config.modelHash}. Got file hash ${actualHash}.`); + } + await platform.cache.save(cacheKey, modelData); + } + return modelData; +} + +/* eslint-disable @typescript-eslint/no-explicit-any */ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Accumulates countable texts from Content and Tool objects. + */ +class TextsAccumulator { + constructor() { + this.texts = []; + } + /** + * Returns all accumulated texts. + */ + getTexts() { + return this.texts; + } + /** + * Adds multiple Content objects. + */ + addContents(contents) { + for (const content of contents) { + this.addContent(content); + } + } + addContent(content) { + const countedContent = { + parts: [], + role: content.role, + }; + if (content.parts) { + for (const part of content.parts) { + const countedPart = {}; + if (part.fileData || part.inlineData) { + throw new Error('LocalTokenizers do not support non-text content types.'); + } + if (part.videoMetadata) { + countedPart.videoMetadata = part.videoMetadata; + } + if (part.functionCall) { + this.addFunctionCall(part.functionCall); + countedPart.functionCall = part.functionCall; + } + if (part.functionResponse) { + this.addFunctionResponse(part.functionResponse); + countedPart.functionResponse = part.functionResponse; + } + if (part.text) { + countedPart.text = part.text; + this.texts.push(part.text); + } + if (countedContent.parts) { + countedContent.parts.push(countedPart); + } + } + } + if (!this.deepEqual(content, countedContent)) { + console.warn(`Content contains unsupported types for token counting. ` + + `Supported fields: ${JSON.stringify(countedContent)}. ` + + `Got: ${JSON.stringify(content)}.`); + } + } + addFunctionCall(functionCall) { + if (functionCall.name) { + this.texts.push(functionCall.name); + } + if (functionCall.args) { + this.dictTraverse(functionCall.args); + } + } + addTools(tools) { + for (const tool of tools) { + this.addTool(tool); + } + } + addTool(tool) { + if (tool.functionDeclarations) { + for (const functionDeclaration of tool.functionDeclarations) { + this.functionDeclarationTraverse(functionDeclaration); + } + } + } + addFunctionResponses(functionResponses) { + for (const functionResponse of functionResponses) { + this.addFunctionResponse(functionResponse); + } + } + addFunctionResponse(functionResponse) { + if (functionResponse.name) { + this.texts.push(functionResponse.name); + } + if (functionResponse.response) { + this.dictTraverse(functionResponse.response); + } + } + functionDeclarationTraverse(functionDeclaration) { + if (functionDeclaration.name) { + this.texts.push(functionDeclaration.name); + } + if (functionDeclaration.description) { + this.texts.push(functionDeclaration.description); + } + if (functionDeclaration.parameters) { + this.addSchema(functionDeclaration.parameters); + } + if (functionDeclaration.response) { + this.addSchema(functionDeclaration.response); + } + } + addSchema(schema) { + if (schema.format) { + this.texts.push(schema.format); + } + if (schema.description) { + this.texts.push(schema.description); + } + if (schema.enum) { + this.texts.push(...schema.enum); + } + if (schema.required) { + this.texts.push(...schema.required); + } + if (schema.items) { + this.addSchema(schema.items); + } + if (schema.properties) { + for (const [key, value] of Object.entries(schema.properties)) { + this.texts.push(key); + this.addSchema(value); + } + } + if (schema.example !== undefined && schema.example !== null) { + this.anyTraverse(schema.example); + } + } + dictTraverse(obj) { + this.texts.push(...Object.keys(obj)); + for (const value of Object.values(obj)) { + this.anyTraverse(value); + } + } + anyTraverse(value) { + if (typeof value === 'string') { + this.texts.push(value); + } + else if (typeof value === 'object' && value !== null) { + if (Array.isArray(value)) { + for (const item of value) { + this.anyTraverse(item); + } + } + else { + this.dictTraverse(value); + } + } + } + deepEqual(obj1, obj2) { + if (obj1 === obj2) + return true; + if (obj1 == null || obj2 == null) + return obj1 === obj2; + if (typeof obj1 !== 'object' || typeof obj2 !== 'object') + return false; + if (Array.isArray(obj1) && Array.isArray(obj2)) { + if (obj1.length !== obj2.length) + return false; + for (let i = 0; i < obj1.length; i++) { + if (!this.deepEqual(obj1[i], obj2[i])) + return false; + } + return true; + } + const keys1 = Object.keys(obj1).filter((k) => obj1[k] !== undefined); + const keys2 = Object.keys(obj2).filter((k) => obj2[k] !== undefined); + if (keys1.length !== keys2.length) + return false; + for (const key of keys1) { + if (!keys2.includes(key)) + return false; + if (!this.deepEqual(obj1[key], obj2[key])) + return false; + } + return true; + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * LocalTokenizer implementation that integrates SentencePiece with platform-specific + * caching and file operations. + * + * This is the main implementation that brings together: + * - SentencePiece BPE tokenizer + * - Platform-specific model loading and caching + * - Text extraction from Content/Tool/Schema objects + */ +/** + * LocalTokenizer provides text-only local tokenization for Gemini models. + * + * LIMITATIONS: + * - Only supports text-based tokenization (no multimodal) + * - Forward compatibility depends on open-source tokenizer models + * - For tools/schemas, only supports types.Tool and types.Schema objects + * (Python functions or Pydantic models cannot be passed directly) + */ +let LocalTokenizer$1 = class LocalTokenizer { + /** + * Creates a new LocalTokenizer. + * + * @param modelName Gemini model name (e.g., 'gemini-2.0-flash-001') + * @param platform Platform-specific implementations for caching and file operations + */ + constructor(modelName, platform, ProcessorClass = SentencePieceProcessor) { + this.ProcessorClass = ProcessorClass; + this.modelName = modelName; + this.tokenizerName = getTokenizerName(modelName); + this.platform = platform; + } + async ensureProcessor() { + if (this.processor) { + return; + } + const modelBytes = await loadModelProtoBytes(this.tokenizerName, this.platform); + this.processor = new this.ProcessorClass(modelBytes); + } + /** + * Counts the number of tokens in the given content. + * + * @param contents The contents to tokenize + * @param config Optional configuration for counting tokens + * @return A CountTokensResult containing the total number of tokens + * + * @example + * ```typescript + * const tokenizer = new LocalTokenizer('gemini-2.0-flash-001', platform); + * const result = await tokenizer.countTokens("What is your name?"); + * console.log(result.totalTokens); // 5 + * ``` + */ + async countTokens(contents, config) { + var _a; + await this.ensureProcessor(); + const processedContents = tContents(contents); + const textAccumulator = new TextsAccumulator(); + textAccumulator.addContents(processedContents); + if (config === null || config === void 0 ? void 0 : config.systemInstruction) { + const systemContent = tContent(config.systemInstruction); + textAccumulator.addContents([systemContent]); + } + if (config === null || config === void 0 ? void 0 : config.tools) { + textAccumulator.addTools(config.tools); + } + if ((_a = config === null || config === void 0 ? void 0 : config.generationConfig) === null || _a === void 0 ? void 0 : _a.responseSchema) { + textAccumulator.addSchema(config.generationConfig.responseSchema); + } + const texts = textAccumulator.getTexts(); + let totalTokens = 0; + for (const text of texts) { + const tokens = this.processor.encode(text); + totalTokens += tokens.length; + } + return { + totalTokens, + }; + } + /** + * Computes detailed token information for the given content. + * + * @param contents The contents to tokenize + * @return A ComputeTokensResult containing token IDs, bytes, and roles + * + * @example + * ```typescript + * const tokenizer = new LocalTokenizer('gemini-2.0-flash-001', platform); + * const result = await tokenizer.computeTokens("What is your name?"); + * console.log(result.tokensInfo); + * // [{tokenIds: [279, 329, 1313, 2508, 13], tokens: [' What', ' is', ...], role: 'user'}] + * ``` + */ + async computeTokens(contents) { + await this.ensureProcessor(); + const processedContents = tContents(contents); + const tokensInfo = []; + for (const content of processedContents) { + const textAccumulator = new TextsAccumulator(); + textAccumulator.addContent(content); + const texts = textAccumulator.getTexts(); + const allTokenIds = []; + const allTokens = []; + for (const text of texts) { + const tokens = this.processor.encode(text); + allTokenIds.push(...tokens.map((t) => t.id)); + allTokens.push(...tokens.map((t) => this.tokenTextToBase64(t.text))); + } + if (allTokenIds.length > 0) { + tokensInfo.push({ + tokenIds: allTokenIds.map((id) => id.toString()), + tokens: allTokens, + role: content.role, + }); + } + } + return { + tokensInfo, + }; + } + tokenTextToBase64(text) { + const encoder = new TextEncoder(); + const bytes = encoder.encode(text.replace(/▁/g, ' ')); + let binary = ''; + for (let i = 0; i < bytes.length; i++) { + binary += String.fromCharCode(bytes[i]); + } + return btoa(binary); + } +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Node.js implementation of tokenizer cache using the file system. + */ +class NodeTokenizerCache { + constructor() { + this.cacheDir = path.join(os.tmpdir(), 'vertexai_tokenizer_model'); + } + async load(cacheKey, expectedHash) { + const filePath = path.join(this.cacheDir, cacheKey); + try { + const data = await fs.readFile(filePath); + const hash = crypto.createHash('sha256').update(data).digest('hex'); + if (hash === expectedHash) { + return new Uint8Array(data); + } + await this.removeFile(filePath); + return null; + // eslint-disable-next-line @typescript-eslint/no-unused-vars + } + catch (error) { + return null; + } + } + async save(cacheKey, data) { + const filePath = path.join(this.cacheDir, cacheKey); + try { + await fs.mkdir(this.cacheDir, { recursive: true }); + const tmpPath = `${this.cacheDir}.${crypto.randomUUID()}.tmp`; + await fs.writeFile(tmpPath, data); + await fs.rename(tmpPath, filePath); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + } + catch (error) { + // Cache is optional, so errors are silently ignored + } + } + async removeFile(filePath) { + try { + await fs.unlink(filePath); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + } + catch (error) { + // Cache is optional, so errors are silently ignored + } + } +} +/** + * Node.js implementation of tokenizer file system operations. + */ +class NodeTokenizerFileSystem { + async fetchFromUrl(url) { + const response = await fetch(url); + if (!response.ok) { + throw new Error(`Failed to fetch tokenizer model from ${url}: ${response.statusText}`); + } + const arrayBuffer = await response.arrayBuffer(); + return new Uint8Array(arrayBuffer); + } + async validateHash(data, expectedHash) { + const hash = crypto.createHash('sha256').update(data).digest('hex'); + return hash === expectedHash; + } + async computeSha1(text) { + const hash = crypto.createHash('sha1').update(text).digest('hex'); + return hash; + } +} +/** + * Node.js platform implementation for tokenizer. + */ +class NodeTokenizerPlatform { + constructor() { + this.cache = new NodeTokenizerCache(); + this.fileSystem = new NodeTokenizerFileSystem(); + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Node.js-specific LocalTokenizer implementation. + * + * This wrapper automatically uses the Node.js platform (filesystem caching, crypto hashing) + * without requiring users to manually create a platform instance. + */ +/** + * LocalTokenizer for Node.js environment. + * + * Provides local tokenization for Gemini models without requiring API calls. + * Automatically uses Node.js platform (filesystem caching in temp directory). + * + * @example + * ```typescript + * import {LocalTokenizer} from '@google/genai/node'; + * + * const tokenizer = new LocalTokenizer('gemini-2.0-flash-001'); + * const result = await tokenizer.countTokens("What is your name?"); + * console.log(result.totalTokens); // 5 + * ``` + * + * @experimental This API is experimental and may change in future versions. + */ +class LocalTokenizer { + /** + * Creates a new LocalTokenizer for Node.js. + * + * @param modelName Gemini model name (e.g., 'gemini-2.0-flash-001') + */ + constructor(modelName) { + const platform = new NodeTokenizerPlatform(); + this.baseTokenizer = new LocalTokenizer$1(modelName, platform); + } + /** + * Counts the number of tokens in the given content. + * + * @param contents The contents to tokenize + * @param config Optional configuration for counting tokens + * @return A CountTokensResult containing the total number of tokens + */ + async countTokens(contents, config) { + return this.baseTokenizer.countTokens(contents, config); + } + /** + * Computes detailed token information for the given content. + * + * @param contents The contents to tokenize + * @return A ComputeTokensResult containing token IDs, bytes, and roles + */ + async computeTokens(contents) { + return this.baseTokenizer.computeTokens(contents); + } +} + +export { LocalTokenizer }; +//# sourceMappingURL=node.mjs.map diff --git a/server/node_modules/@google/genai/dist/tokenizer/node.mjs.map b/server/node_modules/@google/genai/dist/tokenizer/node.mjs.map new file mode 100644 index 0000000..1cda855 --- /dev/null +++ b/server/node_modules/@google/genai/dist/tokenizer/node.mjs.map @@ -0,0 +1 @@ +{"version":3,"file":"node.mjs","sources":["../../src/types.ts","../../src/_transformers.ts","../../src/cross/sentencepiece/_model.ts","../../src/cross/sentencepiece/_prefix_matcher.ts","../../src/cross/sentencepiece/_priority_queue.ts","../../src/cross/sentencepiece/sentencepiece_model.pb.js","../../src/cross/sentencepiece/_processor.ts","../../src/cross/tokenizer/_loader.ts","../../src/cross/tokenizer/_texts_accumulator.ts","../../src/cross/tokenizer/_local_tokenizer_impl.ts","../../src/node/_node_tokenizer_platform.ts","../../src/node/local_tokenizer.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport type {ReferenceImageAPIInternal} from './_internal_types.js';\nimport {\n generateVideosOperationFromMldev,\n generateVideosOperationFromVertex,\n importFileOperationFromMldev,\n uploadToFileSearchStoreOperationFromMldev,\n} from './converters/_operations_converters.js';\n\n/** Outcome of the code execution. */\nexport enum Outcome {\n /**\n * Unspecified status. This value should not be used.\n */\n OUTCOME_UNSPECIFIED = 'OUTCOME_UNSPECIFIED',\n /**\n * Code execution completed successfully.\n */\n OUTCOME_OK = 'OUTCOME_OK',\n /**\n * Code execution finished but with a failure. `stderr` should contain the reason.\n */\n OUTCOME_FAILED = 'OUTCOME_FAILED',\n /**\n * Code execution ran for too long, and was cancelled. There may or may not be a partial output present.\n */\n OUTCOME_DEADLINE_EXCEEDED = 'OUTCOME_DEADLINE_EXCEEDED',\n}\n\n/** Programming language of the `code`. */\nexport enum Language {\n /**\n * Unspecified language. This value should not be used.\n */\n LANGUAGE_UNSPECIFIED = 'LANGUAGE_UNSPECIFIED',\n /**\n * Python >= 3.10, with numpy and simpy available.\n */\n PYTHON = 'PYTHON',\n}\n\n/** Specifies how the response should be scheduled in the conversation. */\nexport enum FunctionResponseScheduling {\n /**\n * This value is unused.\n */\n SCHEDULING_UNSPECIFIED = 'SCHEDULING_UNSPECIFIED',\n /**\n * Only add the result to the conversation context, do not interrupt or trigger generation.\n */\n SILENT = 'SILENT',\n /**\n * Add the result to the conversation context, and prompt to generate output without interrupting ongoing generation.\n */\n WHEN_IDLE = 'WHEN_IDLE',\n /**\n * Add the result to the conversation context, interrupt ongoing generation and prompt to generate output.\n */\n INTERRUPT = 'INTERRUPT',\n}\n\n/** The type of the data. */\nexport enum Type {\n /**\n * Not specified, should not be used.\n */\n TYPE_UNSPECIFIED = 'TYPE_UNSPECIFIED',\n /**\n * OpenAPI string type\n */\n STRING = 'STRING',\n /**\n * OpenAPI number type\n */\n NUMBER = 'NUMBER',\n /**\n * OpenAPI integer type\n */\n INTEGER = 'INTEGER',\n /**\n * OpenAPI boolean type\n */\n BOOLEAN = 'BOOLEAN',\n /**\n * OpenAPI array type\n */\n ARRAY = 'ARRAY',\n /**\n * OpenAPI object type\n */\n OBJECT = 'OBJECT',\n /**\n * Null type\n */\n NULL = 'NULL',\n}\n\n/** The API spec that the external API implements. This enum is not supported in Gemini API. */\nexport enum ApiSpec {\n /**\n * Unspecified API spec. This value should not be used.\n */\n API_SPEC_UNSPECIFIED = 'API_SPEC_UNSPECIFIED',\n /**\n * Simple search API spec.\n */\n SIMPLE_SEARCH = 'SIMPLE_SEARCH',\n /**\n * Elastic search API spec.\n */\n ELASTIC_SEARCH = 'ELASTIC_SEARCH',\n}\n\n/** Type of auth scheme. This enum is not supported in Gemini API. */\nexport enum AuthType {\n AUTH_TYPE_UNSPECIFIED = 'AUTH_TYPE_UNSPECIFIED',\n /**\n * No Auth.\n */\n NO_AUTH = 'NO_AUTH',\n /**\n * API Key Auth.\n */\n API_KEY_AUTH = 'API_KEY_AUTH',\n /**\n * HTTP Basic Auth.\n */\n HTTP_BASIC_AUTH = 'HTTP_BASIC_AUTH',\n /**\n * Google Service Account Auth.\n */\n GOOGLE_SERVICE_ACCOUNT_AUTH = 'GOOGLE_SERVICE_ACCOUNT_AUTH',\n /**\n * OAuth auth.\n */\n OAUTH = 'OAUTH',\n /**\n * OpenID Connect (OIDC) Auth.\n */\n OIDC_AUTH = 'OIDC_AUTH',\n}\n\n/** The location of the API key. This enum is not supported in Gemini API. */\nexport enum HttpElementLocation {\n HTTP_IN_UNSPECIFIED = 'HTTP_IN_UNSPECIFIED',\n /**\n * Element is in the HTTP request query.\n */\n HTTP_IN_QUERY = 'HTTP_IN_QUERY',\n /**\n * Element is in the HTTP request header.\n */\n HTTP_IN_HEADER = 'HTTP_IN_HEADER',\n /**\n * Element is in the HTTP request path.\n */\n HTTP_IN_PATH = 'HTTP_IN_PATH',\n /**\n * Element is in the HTTP request body.\n */\n HTTP_IN_BODY = 'HTTP_IN_BODY',\n /**\n * Element is in the HTTP request cookie.\n */\n HTTP_IN_COOKIE = 'HTTP_IN_COOKIE',\n}\n\n/** Sites with confidence level chosen & above this value will be blocked from the search results. This enum is not supported in Gemini API. */\nexport enum PhishBlockThreshold {\n /**\n * Defaults to unspecified.\n */\n PHISH_BLOCK_THRESHOLD_UNSPECIFIED = 'PHISH_BLOCK_THRESHOLD_UNSPECIFIED',\n /**\n * Blocks Low and above confidence URL that is risky.\n */\n BLOCK_LOW_AND_ABOVE = 'BLOCK_LOW_AND_ABOVE',\n /**\n * Blocks Medium and above confidence URL that is risky.\n */\n BLOCK_MEDIUM_AND_ABOVE = 'BLOCK_MEDIUM_AND_ABOVE',\n /**\n * Blocks High and above confidence URL that is risky.\n */\n BLOCK_HIGH_AND_ABOVE = 'BLOCK_HIGH_AND_ABOVE',\n /**\n * Blocks Higher and above confidence URL that is risky.\n */\n BLOCK_HIGHER_AND_ABOVE = 'BLOCK_HIGHER_AND_ABOVE',\n /**\n * Blocks Very high and above confidence URL that is risky.\n */\n BLOCK_VERY_HIGH_AND_ABOVE = 'BLOCK_VERY_HIGH_AND_ABOVE',\n /**\n * Blocks Extremely high confidence URL that is risky.\n */\n BLOCK_ONLY_EXTREMELY_HIGH = 'BLOCK_ONLY_EXTREMELY_HIGH',\n}\n\n/** Specifies the function Behavior. Currently only supported by the BidiGenerateContent method. This enum is not supported in Vertex AI. */\nexport enum Behavior {\n /**\n * This value is unused.\n */\n UNSPECIFIED = 'UNSPECIFIED',\n /**\n * If set, the system will wait to receive the function response before continuing the conversation.\n */\n BLOCKING = 'BLOCKING',\n /**\n * If set, the system will not wait to receive the function response. Instead, it will attempt to handle function responses as they become available while maintaining the conversation between the user and the model.\n */\n NON_BLOCKING = 'NON_BLOCKING',\n}\n\n/** The mode of the predictor to be used in dynamic retrieval. */\nexport enum DynamicRetrievalConfigMode {\n /**\n * Always trigger retrieval.\n */\n MODE_UNSPECIFIED = 'MODE_UNSPECIFIED',\n /**\n * Run retrieval only when system decides it is necessary.\n */\n MODE_DYNAMIC = 'MODE_DYNAMIC',\n}\n\n/** Function calling mode. */\nexport enum FunctionCallingConfigMode {\n /**\n * Unspecified function calling mode. This value should not be used.\n */\n MODE_UNSPECIFIED = 'MODE_UNSPECIFIED',\n /**\n * Default model behavior, model decides to predict either function calls or natural language response.\n */\n AUTO = 'AUTO',\n /**\n * Model is constrained to always predicting function calls only. If \"allowed_function_names\" are set, the predicted function calls will be limited to any one of \"allowed_function_names\", else the predicted function calls will be any one of the provided \"function_declarations\".\n */\n ANY = 'ANY',\n /**\n * Model will not predict any function calls. Model behavior is same as when not passing any function declarations.\n */\n NONE = 'NONE',\n /**\n * Model is constrained to predict either function calls or natural language response. If \"allowed_function_names\" are set, the predicted function calls will be limited to any one of \"allowed_function_names\", else the predicted function calls will be any one of the provided \"function_declarations\".\n */\n VALIDATED = 'VALIDATED',\n}\n\n/** The number of thoughts tokens that the model should generate. */\nexport enum ThinkingLevel {\n /**\n * Unspecified thinking level.\n */\n THINKING_LEVEL_UNSPECIFIED = 'THINKING_LEVEL_UNSPECIFIED',\n /**\n * Low thinking level.\n */\n LOW = 'LOW',\n /**\n * Medium thinking level.\n */\n MEDIUM = 'MEDIUM',\n /**\n * High thinking level.\n */\n HIGH = 'HIGH',\n /**\n * MINIMAL thinking level.\n */\n MINIMAL = 'MINIMAL',\n}\n\n/** Harm category. */\nexport enum HarmCategory {\n /**\n * The harm category is unspecified.\n */\n HARM_CATEGORY_UNSPECIFIED = 'HARM_CATEGORY_UNSPECIFIED',\n /**\n * The harm category is harassment.\n */\n HARM_CATEGORY_HARASSMENT = 'HARM_CATEGORY_HARASSMENT',\n /**\n * The harm category is hate speech.\n */\n HARM_CATEGORY_HATE_SPEECH = 'HARM_CATEGORY_HATE_SPEECH',\n /**\n * The harm category is sexually explicit content.\n */\n HARM_CATEGORY_SEXUALLY_EXPLICIT = 'HARM_CATEGORY_SEXUALLY_EXPLICIT',\n /**\n * The harm category is dangerous content.\n */\n HARM_CATEGORY_DANGEROUS_CONTENT = 'HARM_CATEGORY_DANGEROUS_CONTENT',\n /**\n * Deprecated: Election filter is not longer supported. The harm category is civic integrity.\n */\n HARM_CATEGORY_CIVIC_INTEGRITY = 'HARM_CATEGORY_CIVIC_INTEGRITY',\n /**\n * The harm category is image hate. This enum value is not supported in Gemini API.\n */\n HARM_CATEGORY_IMAGE_HATE = 'HARM_CATEGORY_IMAGE_HATE',\n /**\n * The harm category is image dangerous content. This enum value is not supported in Gemini API.\n */\n HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT = 'HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT',\n /**\n * The harm category is image harassment. This enum value is not supported in Gemini API.\n */\n HARM_CATEGORY_IMAGE_HARASSMENT = 'HARM_CATEGORY_IMAGE_HARASSMENT',\n /**\n * The harm category is image sexually explicit content. This enum value is not supported in Gemini API.\n */\n HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT = 'HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT',\n /**\n * The harm category is for jailbreak prompts. This enum value is not supported in Gemini API.\n */\n HARM_CATEGORY_JAILBREAK = 'HARM_CATEGORY_JAILBREAK',\n}\n\n/** Specify if the threshold is used for probability or severity score. If not specified, the threshold is used for probability score. This enum is not supported in Gemini API. */\nexport enum HarmBlockMethod {\n /**\n * The harm block method is unspecified.\n */\n HARM_BLOCK_METHOD_UNSPECIFIED = 'HARM_BLOCK_METHOD_UNSPECIFIED',\n /**\n * The harm block method uses both probability and severity scores.\n */\n SEVERITY = 'SEVERITY',\n /**\n * The harm block method uses the probability score.\n */\n PROBABILITY = 'PROBABILITY',\n}\n\n/** The harm block threshold. */\nexport enum HarmBlockThreshold {\n /**\n * Unspecified harm block threshold.\n */\n HARM_BLOCK_THRESHOLD_UNSPECIFIED = 'HARM_BLOCK_THRESHOLD_UNSPECIFIED',\n /**\n * Block low threshold and above (i.e. block more).\n */\n BLOCK_LOW_AND_ABOVE = 'BLOCK_LOW_AND_ABOVE',\n /**\n * Block medium threshold and above.\n */\n BLOCK_MEDIUM_AND_ABOVE = 'BLOCK_MEDIUM_AND_ABOVE',\n /**\n * Block only high threshold (i.e. block less).\n */\n BLOCK_ONLY_HIGH = 'BLOCK_ONLY_HIGH',\n /**\n * Block none.\n */\n BLOCK_NONE = 'BLOCK_NONE',\n /**\n * Turn off the safety filter.\n */\n OFF = 'OFF',\n}\n\n/** Output only. The reason why the model stopped generating tokens.\n\nIf empty, the model has not stopped generating the tokens. */\nexport enum FinishReason {\n /**\n * The finish reason is unspecified.\n */\n FINISH_REASON_UNSPECIFIED = 'FINISH_REASON_UNSPECIFIED',\n /**\n * Token generation reached a natural stopping point or a configured stop sequence.\n */\n STOP = 'STOP',\n /**\n * Token generation reached the configured maximum output tokens.\n */\n MAX_TOKENS = 'MAX_TOKENS',\n /**\n * Token generation stopped because the content potentially contains safety violations. NOTE: When streaming, [content][] is empty if content filters blocks the output.\n */\n SAFETY = 'SAFETY',\n /**\n * The token generation stopped because of potential recitation.\n */\n RECITATION = 'RECITATION',\n /**\n * The token generation stopped because of using an unsupported language.\n */\n LANGUAGE = 'LANGUAGE',\n /**\n * All other reasons that stopped the token generation.\n */\n OTHER = 'OTHER',\n /**\n * Token generation stopped because the content contains forbidden terms.\n */\n BLOCKLIST = 'BLOCKLIST',\n /**\n * Token generation stopped for potentially containing prohibited content.\n */\n PROHIBITED_CONTENT = 'PROHIBITED_CONTENT',\n /**\n * Token generation stopped because the content potentially contains Sensitive Personally Identifiable Information (SPII).\n */\n SPII = 'SPII',\n /**\n * The function call generated by the model is invalid.\n */\n MALFORMED_FUNCTION_CALL = 'MALFORMED_FUNCTION_CALL',\n /**\n * Token generation stopped because generated images have safety violations.\n */\n IMAGE_SAFETY = 'IMAGE_SAFETY',\n /**\n * The tool call generated by the model is invalid.\n */\n UNEXPECTED_TOOL_CALL = 'UNEXPECTED_TOOL_CALL',\n /**\n * Image generation stopped because the generated images have prohibited content.\n */\n IMAGE_PROHIBITED_CONTENT = 'IMAGE_PROHIBITED_CONTENT',\n /**\n * The model was expected to generate an image, but none was generated.\n */\n NO_IMAGE = 'NO_IMAGE',\n /**\n * Image generation stopped because the generated image may be a recitation from a source.\n */\n IMAGE_RECITATION = 'IMAGE_RECITATION',\n /**\n * Image generation stopped for a reason not otherwise specified.\n */\n IMAGE_OTHER = 'IMAGE_OTHER',\n}\n\n/** Output only. Harm probability levels in the content. */\nexport enum HarmProbability {\n /**\n * Harm probability unspecified.\n */\n HARM_PROBABILITY_UNSPECIFIED = 'HARM_PROBABILITY_UNSPECIFIED',\n /**\n * Negligible level of harm.\n */\n NEGLIGIBLE = 'NEGLIGIBLE',\n /**\n * Low level of harm.\n */\n LOW = 'LOW',\n /**\n * Medium level of harm.\n */\n MEDIUM = 'MEDIUM',\n /**\n * High level of harm.\n */\n HIGH = 'HIGH',\n}\n\n/** Output only. Harm severity levels in the content. This enum is not supported in Gemini API. */\nexport enum HarmSeverity {\n /**\n * Harm severity unspecified.\n */\n HARM_SEVERITY_UNSPECIFIED = 'HARM_SEVERITY_UNSPECIFIED',\n /**\n * Negligible level of harm severity.\n */\n HARM_SEVERITY_NEGLIGIBLE = 'HARM_SEVERITY_NEGLIGIBLE',\n /**\n * Low level of harm severity.\n */\n HARM_SEVERITY_LOW = 'HARM_SEVERITY_LOW',\n /**\n * Medium level of harm severity.\n */\n HARM_SEVERITY_MEDIUM = 'HARM_SEVERITY_MEDIUM',\n /**\n * High level of harm severity.\n */\n HARM_SEVERITY_HIGH = 'HARM_SEVERITY_HIGH',\n}\n\n/** Status of the url retrieval. */\nexport enum UrlRetrievalStatus {\n /**\n * Default value. This value is unused.\n */\n URL_RETRIEVAL_STATUS_UNSPECIFIED = 'URL_RETRIEVAL_STATUS_UNSPECIFIED',\n /**\n * Url retrieval is successful.\n */\n URL_RETRIEVAL_STATUS_SUCCESS = 'URL_RETRIEVAL_STATUS_SUCCESS',\n /**\n * Url retrieval is failed due to error.\n */\n URL_RETRIEVAL_STATUS_ERROR = 'URL_RETRIEVAL_STATUS_ERROR',\n /**\n * Url retrieval is failed because the content is behind paywall. This enum value is not supported in Vertex AI.\n */\n URL_RETRIEVAL_STATUS_PAYWALL = 'URL_RETRIEVAL_STATUS_PAYWALL',\n /**\n * Url retrieval is failed because the content is unsafe. This enum value is not supported in Vertex AI.\n */\n URL_RETRIEVAL_STATUS_UNSAFE = 'URL_RETRIEVAL_STATUS_UNSAFE',\n}\n\n/** Output only. The reason why the prompt was blocked. */\nexport enum BlockedReason {\n /**\n * The blocked reason is unspecified.\n */\n BLOCKED_REASON_UNSPECIFIED = 'BLOCKED_REASON_UNSPECIFIED',\n /**\n * The prompt was blocked for safety reasons.\n */\n SAFETY = 'SAFETY',\n /**\n * The prompt was blocked for other reasons. For example, it may be due to the prompt's language, or because it contains other harmful content.\n */\n OTHER = 'OTHER',\n /**\n * The prompt was blocked because it contains a term from the terminology blocklist.\n */\n BLOCKLIST = 'BLOCKLIST',\n /**\n * The prompt was blocked because it contains prohibited content.\n */\n PROHIBITED_CONTENT = 'PROHIBITED_CONTENT',\n /**\n * The prompt was blocked because it contains content that is unsafe for image generation.\n */\n IMAGE_SAFETY = 'IMAGE_SAFETY',\n /**\n * The prompt was blocked by Model Armor. This enum value is not supported in Gemini API.\n */\n MODEL_ARMOR = 'MODEL_ARMOR',\n /**\n * The prompt was blocked as a jailbreak attempt. This enum value is not supported in Gemini API.\n */\n JAILBREAK = 'JAILBREAK',\n}\n\n/** Output only. The traffic type for this request. This enum is not supported in Gemini API. */\nexport enum TrafficType {\n /**\n * Unspecified request traffic type.\n */\n TRAFFIC_TYPE_UNSPECIFIED = 'TRAFFIC_TYPE_UNSPECIFIED',\n /**\n * The request was processed using Pay-As-You-Go quota.\n */\n ON_DEMAND = 'ON_DEMAND',\n /**\n * Type for Provisioned Throughput traffic.\n */\n PROVISIONED_THROUGHPUT = 'PROVISIONED_THROUGHPUT',\n}\n\n/** Server content modalities. */\nexport enum Modality {\n /**\n * The modality is unspecified.\n */\n MODALITY_UNSPECIFIED = 'MODALITY_UNSPECIFIED',\n /**\n * Indicates the model should return text\n */\n TEXT = 'TEXT',\n /**\n * Indicates the model should return images.\n */\n IMAGE = 'IMAGE',\n /**\n * Indicates the model should return audio.\n */\n AUDIO = 'AUDIO',\n}\n\n/** The media resolution to use. */\nexport enum MediaResolution {\n /**\n * Media resolution has not been set\n */\n MEDIA_RESOLUTION_UNSPECIFIED = 'MEDIA_RESOLUTION_UNSPECIFIED',\n /**\n * Media resolution set to low (64 tokens).\n */\n MEDIA_RESOLUTION_LOW = 'MEDIA_RESOLUTION_LOW',\n /**\n * Media resolution set to medium (256 tokens).\n */\n MEDIA_RESOLUTION_MEDIUM = 'MEDIA_RESOLUTION_MEDIUM',\n /**\n * Media resolution set to high (zoomed reframing with 256 tokens).\n */\n MEDIA_RESOLUTION_HIGH = 'MEDIA_RESOLUTION_HIGH',\n}\n\n/** Tuning mode. This enum is not supported in Gemini API. */\nexport enum TuningMode {\n /**\n * Tuning mode is unspecified.\n */\n TUNING_MODE_UNSPECIFIED = 'TUNING_MODE_UNSPECIFIED',\n /**\n * Full fine-tuning mode.\n */\n TUNING_MODE_FULL = 'TUNING_MODE_FULL',\n /**\n * PEFT adapter tuning mode.\n */\n TUNING_MODE_PEFT_ADAPTER = 'TUNING_MODE_PEFT_ADAPTER',\n}\n\n/** Adapter size for tuning. This enum is not supported in Gemini API. */\nexport enum AdapterSize {\n /**\n * Adapter size is unspecified.\n */\n ADAPTER_SIZE_UNSPECIFIED = 'ADAPTER_SIZE_UNSPECIFIED',\n /**\n * Adapter size 1.\n */\n ADAPTER_SIZE_ONE = 'ADAPTER_SIZE_ONE',\n /**\n * Adapter size 2.\n */\n ADAPTER_SIZE_TWO = 'ADAPTER_SIZE_TWO',\n /**\n * Adapter size 4.\n */\n ADAPTER_SIZE_FOUR = 'ADAPTER_SIZE_FOUR',\n /**\n * Adapter size 8.\n */\n ADAPTER_SIZE_EIGHT = 'ADAPTER_SIZE_EIGHT',\n /**\n * Adapter size 16.\n */\n ADAPTER_SIZE_SIXTEEN = 'ADAPTER_SIZE_SIXTEEN',\n /**\n * Adapter size 32.\n */\n ADAPTER_SIZE_THIRTY_TWO = 'ADAPTER_SIZE_THIRTY_TWO',\n}\n\n/** Job state. */\nexport enum JobState {\n /**\n * The job state is unspecified.\n */\n JOB_STATE_UNSPECIFIED = 'JOB_STATE_UNSPECIFIED',\n /**\n * The job has been just created or resumed and processing has not yet begun.\n */\n JOB_STATE_QUEUED = 'JOB_STATE_QUEUED',\n /**\n * The service is preparing to run the job.\n */\n JOB_STATE_PENDING = 'JOB_STATE_PENDING',\n /**\n * The job is in progress.\n */\n JOB_STATE_RUNNING = 'JOB_STATE_RUNNING',\n /**\n * The job completed successfully.\n */\n JOB_STATE_SUCCEEDED = 'JOB_STATE_SUCCEEDED',\n /**\n * The job failed.\n */\n JOB_STATE_FAILED = 'JOB_STATE_FAILED',\n /**\n * The job is being cancelled. From this state the job may only go to either `JOB_STATE_SUCCEEDED`, `JOB_STATE_FAILED` or `JOB_STATE_CANCELLED`.\n */\n JOB_STATE_CANCELLING = 'JOB_STATE_CANCELLING',\n /**\n * The job has been cancelled.\n */\n JOB_STATE_CANCELLED = 'JOB_STATE_CANCELLED',\n /**\n * The job has been stopped, and can be resumed.\n */\n JOB_STATE_PAUSED = 'JOB_STATE_PAUSED',\n /**\n * The job has expired.\n */\n JOB_STATE_EXPIRED = 'JOB_STATE_EXPIRED',\n /**\n * The job is being updated. Only jobs in the `JOB_STATE_RUNNING` state can be updated. After updating, the job goes back to the `JOB_STATE_RUNNING` state.\n */\n JOB_STATE_UPDATING = 'JOB_STATE_UPDATING',\n /**\n * The job is partially succeeded, some results may be missing due to errors.\n */\n JOB_STATE_PARTIALLY_SUCCEEDED = 'JOB_STATE_PARTIALLY_SUCCEEDED',\n}\n\n/** The tuning task. Either I2V or T2V. This enum is not supported in Gemini API. */\nexport enum TuningTask {\n /**\n * Default value. This value is unused.\n */\n TUNING_TASK_UNSPECIFIED = 'TUNING_TASK_UNSPECIFIED',\n /**\n * Tuning task for image to video.\n */\n TUNING_TASK_I2V = 'TUNING_TASK_I2V',\n /**\n * Tuning task for text to video.\n */\n TUNING_TASK_T2V = 'TUNING_TASK_T2V',\n /**\n * Tuning task for reference to video.\n */\n TUNING_TASK_R2V = 'TUNING_TASK_R2V',\n}\n\n/** The tokenization quality used for given media. */\nexport enum PartMediaResolutionLevel {\n /**\n * Media resolution has not been set.\n */\n MEDIA_RESOLUTION_UNSPECIFIED = 'MEDIA_RESOLUTION_UNSPECIFIED',\n /**\n * Media resolution set to low.\n */\n MEDIA_RESOLUTION_LOW = 'MEDIA_RESOLUTION_LOW',\n /**\n * Media resolution set to medium.\n */\n MEDIA_RESOLUTION_MEDIUM = 'MEDIA_RESOLUTION_MEDIUM',\n /**\n * Media resolution set to high.\n */\n MEDIA_RESOLUTION_HIGH = 'MEDIA_RESOLUTION_HIGH',\n /**\n * Media resolution set to ultra high.\n */\n MEDIA_RESOLUTION_ULTRA_HIGH = 'MEDIA_RESOLUTION_ULTRA_HIGH',\n}\n\n/** Resource scope. */\nexport enum ResourceScope {\n /**\n * When setting base_url, this value configures resource scope to be the collection.\n The resource name will not include api version, project, or location.\n For example, if base_url is set to \"https://aiplatform.googleapis.com\",\n then the resource name for a Model would be\n \"https://aiplatform.googleapis.com/publishers/google/models/gemini-3-pro-preview\n */\n COLLECTION = 'COLLECTION',\n}\n\n/** Options for feature selection preference. */\nexport enum FeatureSelectionPreference {\n FEATURE_SELECTION_PREFERENCE_UNSPECIFIED = 'FEATURE_SELECTION_PREFERENCE_UNSPECIFIED',\n PRIORITIZE_QUALITY = 'PRIORITIZE_QUALITY',\n BALANCED = 'BALANCED',\n PRIORITIZE_COST = 'PRIORITIZE_COST',\n}\n\n/** The environment being operated. */\nexport enum Environment {\n /**\n * Defaults to browser.\n */\n ENVIRONMENT_UNSPECIFIED = 'ENVIRONMENT_UNSPECIFIED',\n /**\n * Operates in a web browser.\n */\n ENVIRONMENT_BROWSER = 'ENVIRONMENT_BROWSER',\n}\n\n/** Enum that controls the safety filter level for objectionable content. */\nexport enum SafetyFilterLevel {\n BLOCK_LOW_AND_ABOVE = 'BLOCK_LOW_AND_ABOVE',\n BLOCK_MEDIUM_AND_ABOVE = 'BLOCK_MEDIUM_AND_ABOVE',\n BLOCK_ONLY_HIGH = 'BLOCK_ONLY_HIGH',\n BLOCK_NONE = 'BLOCK_NONE',\n}\n\n/** Enum that controls the generation of people. */\nexport enum PersonGeneration {\n /**\n * Block generation of images of people.\n */\n DONT_ALLOW = 'DONT_ALLOW',\n /**\n * Generate images of adults, but not children.\n */\n ALLOW_ADULT = 'ALLOW_ADULT',\n /**\n * Generate images that include adults and children.\n */\n ALLOW_ALL = 'ALLOW_ALL',\n}\n\n/** Enum that specifies the language of the text in the prompt. */\nexport enum ImagePromptLanguage {\n /**\n * Auto-detect the language.\n */\n auto = 'auto',\n /**\n * English\n */\n en = 'en',\n /**\n * Japanese\n */\n ja = 'ja',\n /**\n * Korean\n */\n ko = 'ko',\n /**\n * Hindi\n */\n hi = 'hi',\n /**\n * Chinese\n */\n zh = 'zh',\n /**\n * Portuguese\n */\n pt = 'pt',\n /**\n * Spanish\n */\n es = 'es',\n}\n\n/** Enum representing the mask mode of a mask reference image. */\nexport enum MaskReferenceMode {\n MASK_MODE_DEFAULT = 'MASK_MODE_DEFAULT',\n MASK_MODE_USER_PROVIDED = 'MASK_MODE_USER_PROVIDED',\n MASK_MODE_BACKGROUND = 'MASK_MODE_BACKGROUND',\n MASK_MODE_FOREGROUND = 'MASK_MODE_FOREGROUND',\n MASK_MODE_SEMANTIC = 'MASK_MODE_SEMANTIC',\n}\n\n/** Enum representing the control type of a control reference image. */\nexport enum ControlReferenceType {\n CONTROL_TYPE_DEFAULT = 'CONTROL_TYPE_DEFAULT',\n CONTROL_TYPE_CANNY = 'CONTROL_TYPE_CANNY',\n CONTROL_TYPE_SCRIBBLE = 'CONTROL_TYPE_SCRIBBLE',\n CONTROL_TYPE_FACE_MESH = 'CONTROL_TYPE_FACE_MESH',\n}\n\n/** Enum representing the subject type of a subject reference image. */\nexport enum SubjectReferenceType {\n SUBJECT_TYPE_DEFAULT = 'SUBJECT_TYPE_DEFAULT',\n SUBJECT_TYPE_PERSON = 'SUBJECT_TYPE_PERSON',\n SUBJECT_TYPE_ANIMAL = 'SUBJECT_TYPE_ANIMAL',\n SUBJECT_TYPE_PRODUCT = 'SUBJECT_TYPE_PRODUCT',\n}\n\n/** Enum representing the editing mode. */\nexport enum EditMode {\n EDIT_MODE_DEFAULT = 'EDIT_MODE_DEFAULT',\n EDIT_MODE_INPAINT_REMOVAL = 'EDIT_MODE_INPAINT_REMOVAL',\n EDIT_MODE_INPAINT_INSERTION = 'EDIT_MODE_INPAINT_INSERTION',\n EDIT_MODE_OUTPAINT = 'EDIT_MODE_OUTPAINT',\n EDIT_MODE_CONTROLLED_EDITING = 'EDIT_MODE_CONTROLLED_EDITING',\n EDIT_MODE_STYLE = 'EDIT_MODE_STYLE',\n EDIT_MODE_BGSWAP = 'EDIT_MODE_BGSWAP',\n EDIT_MODE_PRODUCT_IMAGE = 'EDIT_MODE_PRODUCT_IMAGE',\n}\n\n/** Enum that represents the segmentation mode. */\nexport enum SegmentMode {\n FOREGROUND = 'FOREGROUND',\n BACKGROUND = 'BACKGROUND',\n PROMPT = 'PROMPT',\n SEMANTIC = 'SEMANTIC',\n INTERACTIVE = 'INTERACTIVE',\n}\n\n/** Enum for the reference type of a video generation reference image. */\nexport enum VideoGenerationReferenceType {\n /**\n * A reference image that provides assets to the generated video,\n such as the scene, an object, a character, etc.\n */\n ASSET = 'ASSET',\n /**\n * A reference image that provides aesthetics including colors,\n lighting, texture, etc., to be used as the style of the generated video,\n such as 'anime', 'photography', 'origami', etc.\n */\n STYLE = 'STYLE',\n}\n\n/** Enum for the mask mode of a video generation mask. */\nexport enum VideoGenerationMaskMode {\n /**\n * The image mask contains a masked rectangular region which is\n applied on the first frame of the input video. The object described in\n the prompt is inserted into this region and will appear in subsequent\n frames.\n */\n INSERT = 'INSERT',\n /**\n * The image mask is used to determine an object in the\n first video frame to track. This object is removed from the video.\n */\n REMOVE = 'REMOVE',\n /**\n * The image mask is used to determine a region in the\n video. Objects in this region will be removed.\n */\n REMOVE_STATIC = 'REMOVE_STATIC',\n /**\n * The image mask contains a masked rectangular region where\n the input video will go. The remaining area will be generated. Video\n masks are not supported.\n */\n OUTPAINT = 'OUTPAINT',\n}\n\n/** Enum that controls the compression quality of the generated videos. */\nexport enum VideoCompressionQuality {\n /**\n * Optimized video compression quality. This will produce videos\n with a compressed, smaller file size.\n */\n OPTIMIZED = 'OPTIMIZED',\n /**\n * Lossless video compression quality. This will produce videos\n with a larger file size.\n */\n LOSSLESS = 'LOSSLESS',\n}\n\n/** Enum representing the tuning method. */\nexport enum TuningMethod {\n /**\n * Supervised fine tuning.\n */\n SUPERVISED_FINE_TUNING = 'SUPERVISED_FINE_TUNING',\n /**\n * Preference optimization tuning.\n */\n PREFERENCE_TUNING = 'PREFERENCE_TUNING',\n /**\n * Distillation tuning.\n */\n DISTILLATION = 'DISTILLATION',\n}\n\n/** State for the lifecycle of a Document. */\nexport enum DocumentState {\n STATE_UNSPECIFIED = 'STATE_UNSPECIFIED',\n STATE_PENDING = 'STATE_PENDING',\n STATE_ACTIVE = 'STATE_ACTIVE',\n STATE_FAILED = 'STATE_FAILED',\n}\n\n/** State for the lifecycle of a File. */\nexport enum FileState {\n STATE_UNSPECIFIED = 'STATE_UNSPECIFIED',\n PROCESSING = 'PROCESSING',\n ACTIVE = 'ACTIVE',\n FAILED = 'FAILED',\n}\n\n/** Source of the File. */\nexport enum FileSource {\n SOURCE_UNSPECIFIED = 'SOURCE_UNSPECIFIED',\n UPLOADED = 'UPLOADED',\n GENERATED = 'GENERATED',\n REGISTERED = 'REGISTERED',\n}\n\n/** The reason why the turn is complete. */\nexport enum TurnCompleteReason {\n /**\n * Default value. Reason is unspecified.\n */\n TURN_COMPLETE_REASON_UNSPECIFIED = 'TURN_COMPLETE_REASON_UNSPECIFIED',\n /**\n * The function call generated by the model is invalid.\n */\n MALFORMED_FUNCTION_CALL = 'MALFORMED_FUNCTION_CALL',\n /**\n * The response is rejected by the model.\n */\n RESPONSE_REJECTED = 'RESPONSE_REJECTED',\n /**\n * Needs more input from the user.\n */\n NEED_MORE_INPUT = 'NEED_MORE_INPUT',\n}\n\n/** Server content modalities. */\nexport enum MediaModality {\n /**\n * The modality is unspecified.\n */\n MODALITY_UNSPECIFIED = 'MODALITY_UNSPECIFIED',\n /**\n * Plain text.\n */\n TEXT = 'TEXT',\n /**\n * Images.\n */\n IMAGE = 'IMAGE',\n /**\n * Video.\n */\n VIDEO = 'VIDEO',\n /**\n * Audio.\n */\n AUDIO = 'AUDIO',\n /**\n * Document, e.g. PDF.\n */\n DOCUMENT = 'DOCUMENT',\n}\n\n/** The type of the VAD signal. */\nexport enum VadSignalType {\n /**\n * The default is VAD_SIGNAL_TYPE_UNSPECIFIED.\n */\n VAD_SIGNAL_TYPE_UNSPECIFIED = 'VAD_SIGNAL_TYPE_UNSPECIFIED',\n /**\n * Start of sentence signal.\n */\n VAD_SIGNAL_TYPE_SOS = 'VAD_SIGNAL_TYPE_SOS',\n /**\n * End of sentence signal.\n */\n VAD_SIGNAL_TYPE_EOS = 'VAD_SIGNAL_TYPE_EOS',\n}\n\n/** The type of the voice activity signal. */\nexport enum VoiceActivityType {\n /**\n * The default is VOICE_ACTIVITY_TYPE_UNSPECIFIED.\n */\n TYPE_UNSPECIFIED = 'TYPE_UNSPECIFIED',\n /**\n * Start of sentence signal.\n */\n ACTIVITY_START = 'ACTIVITY_START',\n /**\n * End of sentence signal.\n */\n ACTIVITY_END = 'ACTIVITY_END',\n}\n\n/** Start of speech sensitivity. */\nexport enum StartSensitivity {\n /**\n * The default is START_SENSITIVITY_LOW.\n */\n START_SENSITIVITY_UNSPECIFIED = 'START_SENSITIVITY_UNSPECIFIED',\n /**\n * Automatic detection will detect the start of speech more often.\n */\n START_SENSITIVITY_HIGH = 'START_SENSITIVITY_HIGH',\n /**\n * Automatic detection will detect the start of speech less often.\n */\n START_SENSITIVITY_LOW = 'START_SENSITIVITY_LOW',\n}\n\n/** End of speech sensitivity. */\nexport enum EndSensitivity {\n /**\n * The default is END_SENSITIVITY_LOW.\n */\n END_SENSITIVITY_UNSPECIFIED = 'END_SENSITIVITY_UNSPECIFIED',\n /**\n * Automatic detection ends speech more often.\n */\n END_SENSITIVITY_HIGH = 'END_SENSITIVITY_HIGH',\n /**\n * Automatic detection ends speech less often.\n */\n END_SENSITIVITY_LOW = 'END_SENSITIVITY_LOW',\n}\n\n/** The different ways of handling user activity. */\nexport enum ActivityHandling {\n /**\n * If unspecified, the default behavior is `START_OF_ACTIVITY_INTERRUPTS`.\n */\n ACTIVITY_HANDLING_UNSPECIFIED = 'ACTIVITY_HANDLING_UNSPECIFIED',\n /**\n * If true, start of activity will interrupt the model's response (also called \"barge in\"). The model's current response will be cut-off in the moment of the interruption. This is the default behavior.\n */\n START_OF_ACTIVITY_INTERRUPTS = 'START_OF_ACTIVITY_INTERRUPTS',\n /**\n * The model's response will not be interrupted.\n */\n NO_INTERRUPTION = 'NO_INTERRUPTION',\n}\n\n/** Options about which input is included in the user's turn. */\nexport enum TurnCoverage {\n /**\n * If unspecified, the default behavior is `TURN_INCLUDES_ONLY_ACTIVITY`.\n */\n TURN_COVERAGE_UNSPECIFIED = 'TURN_COVERAGE_UNSPECIFIED',\n /**\n * The users turn only includes activity since the last turn, excluding inactivity (e.g. silence on the audio stream). This is the default behavior.\n */\n TURN_INCLUDES_ONLY_ACTIVITY = 'TURN_INCLUDES_ONLY_ACTIVITY',\n /**\n * The users turn includes all realtime input since the last turn, including inactivity (e.g. silence on the audio stream).\n */\n TURN_INCLUDES_ALL_INPUT = 'TURN_INCLUDES_ALL_INPUT',\n}\n\n/** Scale of the generated music. */\nexport enum Scale {\n /**\n * Default value. This value is unused.\n */\n SCALE_UNSPECIFIED = 'SCALE_UNSPECIFIED',\n /**\n * C major or A minor.\n */\n C_MAJOR_A_MINOR = 'C_MAJOR_A_MINOR',\n /**\n * Db major or Bb minor.\n */\n D_FLAT_MAJOR_B_FLAT_MINOR = 'D_FLAT_MAJOR_B_FLAT_MINOR',\n /**\n * D major or B minor.\n */\n D_MAJOR_B_MINOR = 'D_MAJOR_B_MINOR',\n /**\n * Eb major or C minor\n */\n E_FLAT_MAJOR_C_MINOR = 'E_FLAT_MAJOR_C_MINOR',\n /**\n * E major or Db minor.\n */\n E_MAJOR_D_FLAT_MINOR = 'E_MAJOR_D_FLAT_MINOR',\n /**\n * F major or D minor.\n */\n F_MAJOR_D_MINOR = 'F_MAJOR_D_MINOR',\n /**\n * Gb major or Eb minor.\n */\n G_FLAT_MAJOR_E_FLAT_MINOR = 'G_FLAT_MAJOR_E_FLAT_MINOR',\n /**\n * G major or E minor.\n */\n G_MAJOR_E_MINOR = 'G_MAJOR_E_MINOR',\n /**\n * Ab major or F minor.\n */\n A_FLAT_MAJOR_F_MINOR = 'A_FLAT_MAJOR_F_MINOR',\n /**\n * A major or Gb minor.\n */\n A_MAJOR_G_FLAT_MINOR = 'A_MAJOR_G_FLAT_MINOR',\n /**\n * Bb major or G minor.\n */\n B_FLAT_MAJOR_G_MINOR = 'B_FLAT_MAJOR_G_MINOR',\n /**\n * B major or Ab minor.\n */\n B_MAJOR_A_FLAT_MINOR = 'B_MAJOR_A_FLAT_MINOR',\n}\n\n/** The mode of music generation. */\nexport enum MusicGenerationMode {\n /**\n * Rely on the server default generation mode.\n */\n MUSIC_GENERATION_MODE_UNSPECIFIED = 'MUSIC_GENERATION_MODE_UNSPECIFIED',\n /**\n * Steer text prompts to regions of latent space with higher quality\n music.\n */\n QUALITY = 'QUALITY',\n /**\n * Steer text prompts to regions of latent space with a larger\n diversity of music.\n */\n DIVERSITY = 'DIVERSITY',\n /**\n * Steer text prompts to regions of latent space more likely to\n generate music with vocals.\n */\n VOCALIZATION = 'VOCALIZATION',\n}\n\n/** The playback control signal to apply to the music generation. */\nexport enum LiveMusicPlaybackControl {\n /**\n * This value is unused.\n */\n PLAYBACK_CONTROL_UNSPECIFIED = 'PLAYBACK_CONTROL_UNSPECIFIED',\n /**\n * Start generating the music.\n */\n PLAY = 'PLAY',\n /**\n * Hold the music generation. Use PLAY to resume from the current position.\n */\n PAUSE = 'PAUSE',\n /**\n * Stop the music generation and reset the context (prompts retained).\n Use PLAY to restart the music generation.\n */\n STOP = 'STOP',\n /**\n * Reset the context of the music generation without stopping it.\n Retains the current prompts and config.\n */\n RESET_CONTEXT = 'RESET_CONTEXT',\n}\n\n/** Media resolution for the input media. */\nexport declare interface PartMediaResolution {\n /** The tokenization quality used for given media.\n */\n level?: PartMediaResolutionLevel;\n /** Specifies the required sequence length for media tokenization.\n */\n numTokens?: number;\n}\n\n/** Result of executing the [ExecutableCode]. Only generated when using the [CodeExecution] tool, and always follows a `part` containing the [ExecutableCode]. */\nexport declare interface CodeExecutionResult {\n /** Required. Outcome of the code execution. */\n outcome?: Outcome;\n /** Optional. Contains stdout when code execution is successful, stderr or other description otherwise. */\n output?: string;\n}\n\n/** Code generated by the model that is meant to be executed, and the result returned to the model. Generated when using the [CodeExecution] tool, in which the code will be automatically executed, and a corresponding [CodeExecutionResult] will also be generated. */\nexport declare interface ExecutableCode {\n /** Required. The code to be executed. */\n code?: string;\n /** Required. Programming language of the `code`. */\n language?: Language;\n}\n\n/** URI based data. */\nexport declare interface FileData {\n /** Optional. Display name of the file data. Used to provide a label or filename to distinguish file datas. This field is only returned in PromptMessage for prompt management. It is currently used in the Gemini GenerateContent calls only when server side tools (code_execution, google_search, and url_context) are enabled. This field is not supported in Gemini API. */\n displayName?: string;\n /** Required. URI. */\n fileUri?: string;\n /** Required. The IANA standard MIME type of the source data. */\n mimeType?: string;\n}\n\n/** Partial argument value of the function call. This data type is not supported in Gemini API. */\nexport declare interface PartialArg {\n /** Optional. Represents a null value. */\n nullValue?: 'NULL_VALUE';\n /** Optional. Represents a double value. */\n numberValue?: number;\n /** Optional. Represents a string value. */\n stringValue?: string;\n /** Optional. Represents a boolean value. */\n boolValue?: boolean;\n /** Required. A JSON Path (RFC 9535) to the argument being streamed. https://datatracker.ietf.org/doc/html/rfc9535. e.g. \"$.foo.bar[0].data\". */\n jsonPath?: string;\n /** Optional. Whether this is not the last part of the same json_path. If true, another PartialArg message for the current json_path is expected to follow. */\n willContinue?: boolean;\n}\n\n/** A function call. */\nexport declare interface FunctionCall {\n /** The unique id of the function call. If populated, the client to execute the\n `function_call` and return the response with the matching `id`. */\n id?: string;\n /** Optional. The function parameters and values in JSON object format. See [FunctionDeclaration.parameters] for parameter details. */\n args?: Record<string, unknown>;\n /** Optional. The name of the function to call. Matches [FunctionDeclaration.name]. */\n name?: string;\n /** Optional. The partial argument value of the function call. If provided, represents the arguments/fields that are streamed incrementally. This field is not supported in Gemini API. */\n partialArgs?: PartialArg[];\n /** Optional. Whether this is the last part of the FunctionCall. If true, another partial message for the current FunctionCall is expected to follow. This field is not supported in Gemini API. */\n willContinue?: boolean;\n}\n\n/** Raw media bytes for function response.\n\nText should not be sent as raw bytes, use the FunctionResponse.response\nfield. */\nexport class FunctionResponseBlob {\n /** Required. The IANA standard MIME type of the source data. */\n mimeType?: string;\n /** Required. Inline media bytes.\n * @remarks Encoded as base64 string. */\n data?: string;\n /** Optional. Display name of the blob.\n Used to provide a label or filename to distinguish blobs. */\n displayName?: string;\n}\n\n/** URI based data for function response. */\nexport class FunctionResponseFileData {\n /** Required. URI. */\n fileUri?: string;\n /** Required. The IANA standard MIME type of the source data. */\n mimeType?: string;\n /** Optional. Display name of the file.\n Used to provide a label or filename to distinguish files. */\n displayName?: string;\n}\n\n/** A datatype containing media that is part of a `FunctionResponse` message.\n\nA `FunctionResponsePart` consists of data which has an associated datatype. A\n`FunctionResponsePart` can only contain one of the accepted types in\n`FunctionResponsePart.data`.\n\nA `FunctionResponsePart` must have a fixed IANA MIME type identifying the\ntype and subtype of the media if the `inline_data` field is filled with raw\nbytes. */\nexport class FunctionResponsePart {\n /** Optional. Inline media bytes. */\n inlineData?: FunctionResponseBlob;\n /** Optional. URI based data. */\n fileData?: FunctionResponseFileData;\n}\n/**\n * Creates a `FunctionResponsePart` object from a `base64` encoded `string`.\n */\nexport function createFunctionResponsePartFromBase64(\n data: string,\n mimeType: string,\n): FunctionResponsePart {\n return {\n inlineData: {\n data: data,\n mimeType: mimeType,\n },\n };\n}\n/**\n * Creates a `FunctionResponsePart` object from a `URI` string.\n */\nexport function createFunctionResponsePartFromUri(\n uri: string,\n mimeType: string,\n): FunctionResponsePart {\n return {\n fileData: {\n fileUri: uri,\n mimeType: mimeType,\n },\n };\n}\n\n/** A function response. */\nexport class FunctionResponse {\n /** Signals that function call continues, and more responses will be returned, turning the function call into a generator. Is only applicable to NON_BLOCKING function calls (see FunctionDeclaration.behavior for details), ignored otherwise. If false, the default, future responses will not be considered. Is only applicable to NON_BLOCKING function calls, is ignored otherwise. If set to false, future responses will not be considered. It is allowed to return empty `response` with `will_continue=False` to signal that the function call is finished. */\n willContinue?: boolean;\n /** Specifies how the response should be scheduled in the conversation. Only applicable to NON_BLOCKING function calls, is ignored otherwise. Defaults to WHEN_IDLE. */\n scheduling?: FunctionResponseScheduling;\n /** List of parts that constitute a function response. Each part may\n have a different IANA MIME type. */\n parts?: FunctionResponsePart[];\n /** Optional. The id of the function call this response is for. Populated by the client to match the corresponding function call `id`. */\n id?: string;\n /** Required. The name of the function to call. Matches [FunctionDeclaration.name] and [FunctionCall.name]. */\n name?: string;\n /** Required. The function response in JSON object format. Use \"output\" key to specify function output and \"error\" key to specify error details (if any). If \"output\" and \"error\" keys are not specified, then whole \"response\" is treated as function output. */\n response?: Record<string, unknown>;\n}\n\n/** Content blob. */\nexport declare interface Blob {\n /** Required. Raw bytes.\n * @remarks Encoded as base64 string. */\n data?: string;\n /** Optional. Display name of the blob. Used to provide a label or filename to distinguish blobs. This field is only returned in PromptMessage for prompt management. It is currently used in the Gemini GenerateContent calls only when server side tools (code_execution, google_search, and url_context) are enabled. This field is not supported in Gemini API. */\n displayName?: string;\n /** Required. The IANA standard MIME type of the source data. */\n mimeType?: string;\n}\n\n/** Metadata describes the input video content. */\nexport declare interface VideoMetadata {\n /** Optional. The end offset of the video. */\n endOffset?: string;\n /** Optional. The frame rate of the video sent to the model. If not specified, the default value will be 1.0. The fps range is (0.0, 24.0]. */\n fps?: number;\n /** Optional. The start offset of the video. */\n startOffset?: string;\n}\n\n/** A datatype containing media content.\n\nExactly one field within a Part should be set, representing the specific type\nof content being conveyed. Using multiple fields within the same `Part`\ninstance is considered invalid. */\nexport declare interface Part {\n /** Media resolution for the input media.\n */\n mediaResolution?: PartMediaResolution;\n /** Optional. Result of executing the [ExecutableCode]. */\n codeExecutionResult?: CodeExecutionResult;\n /** Optional. Code generated by the model that is meant to be executed. */\n executableCode?: ExecutableCode;\n /** Optional. URI based data. */\n fileData?: FileData;\n /** Optional. A predicted [FunctionCall] returned from the model that contains a string representing the [FunctionDeclaration.name] with the parameters and their values. */\n functionCall?: FunctionCall;\n /** Optional. The result output of a [FunctionCall] that contains a string representing the [FunctionDeclaration.name] and a structured JSON object containing any output from the function call. It is used as context to the model. */\n functionResponse?: FunctionResponse;\n /** Optional. Inlined bytes data. */\n inlineData?: Blob;\n /** Optional. Text part (can be code). */\n text?: string;\n /** Optional. Indicates if the part is thought from the model. */\n thought?: boolean;\n /** Optional. An opaque signature for the thought so it can be reused in subsequent requests.\n * @remarks Encoded as base64 string. */\n thoughtSignature?: string;\n /** Optional. Video metadata. The metadata should only be specified while the video data is presented in inline_data or file_data. */\n videoMetadata?: VideoMetadata;\n}\n/**\n * Creates a `Part` object from a `URI` string.\n */\nexport function createPartFromUri(\n uri: string,\n mimeType: string,\n mediaResolution?: PartMediaResolutionLevel,\n): Part {\n return {\n fileData: {\n fileUri: uri,\n mimeType: mimeType,\n },\n ...(mediaResolution && {mediaResolution: {level: mediaResolution}}),\n };\n}\n/**\n * Creates a `Part` object from a `text` string.\n */\nexport function createPartFromText(text: string): Part {\n return {\n text: text,\n };\n}\n/**\n * Creates a `Part` object from a `FunctionCall` object.\n */\nexport function createPartFromFunctionCall(\n name: string,\n args: Record<string, unknown>,\n): Part {\n return {\n functionCall: {\n name: name,\n args: args,\n },\n };\n}\n/**\n * Creates a `Part` object from a `FunctionResponse` object.\n */\nexport function createPartFromFunctionResponse(\n id: string,\n name: string,\n response: Record<string, unknown>,\n parts: FunctionResponsePart[] = [],\n): Part {\n return {\n functionResponse: {\n id: id,\n name: name,\n response: response,\n ...(parts.length > 0 && {parts}),\n },\n };\n}\n/**\n * Creates a `Part` object from a `base64` encoded `string`.\n */\nexport function createPartFromBase64(\n data: string,\n mimeType: string,\n mediaResolution?: PartMediaResolutionLevel,\n): Part {\n return {\n inlineData: {\n data: data,\n mimeType: mimeType,\n },\n ...(mediaResolution && {mediaResolution: {level: mediaResolution}}),\n };\n}\n/**\n * Creates a `Part` object from the `outcome` and `output` of a `CodeExecutionResult` object.\n */\nexport function createPartFromCodeExecutionResult(\n outcome: Outcome,\n output: string,\n): Part {\n return {\n codeExecutionResult: {\n outcome: outcome,\n output: output,\n },\n };\n}\n/**\n * Creates a `Part` object from the `code` and `language` of an `ExecutableCode` object.\n */\nexport function createPartFromExecutableCode(\n code: string,\n language: Language,\n): Part {\n return {\n executableCode: {\n code: code,\n language: language,\n },\n };\n}\n\n/** Contains the multi-part content of a message. */\nexport declare interface Content {\n /** List of parts that constitute a single message. Each part may have\n a different IANA MIME type. */\n parts?: Part[];\n /** Optional. The producer of the content. Must be either 'user' or 'model'. Useful to set for multi-turn conversations, otherwise can be left blank or unset. */\n role?: string;\n}\nfunction _isPart(obj: unknown): obj is Part {\n if (typeof obj === 'object' && obj !== null) {\n return (\n 'fileData' in obj ||\n 'text' in obj ||\n 'functionCall' in obj ||\n 'functionResponse' in obj ||\n 'inlineData' in obj ||\n 'videoMetadata' in obj ||\n 'codeExecutionResult' in obj ||\n 'executableCode' in obj\n );\n }\n return false;\n}\nfunction _toParts(partOrString: PartListUnion | string): Part[] {\n const parts: Part[] = [];\n if (typeof partOrString === 'string') {\n parts.push(createPartFromText(partOrString));\n } else if (_isPart(partOrString)) {\n parts.push(partOrString);\n } else if (Array.isArray(partOrString)) {\n if (partOrString.length === 0) {\n throw new Error('partOrString cannot be an empty array');\n }\n for (const part of partOrString) {\n if (typeof part === 'string') {\n parts.push(createPartFromText(part));\n } else if (_isPart(part)) {\n parts.push(part);\n } else {\n throw new Error('element in PartUnion must be a Part object or string');\n }\n }\n } else {\n throw new Error('partOrString must be a Part object, string, or array');\n }\n return parts;\n}\n/**\n * Creates a `Content` object with a user role from a `PartListUnion` object or `string`.\n */\nexport function createUserContent(\n partOrString: PartListUnion | string,\n): Content {\n return {\n role: 'user',\n parts: _toParts(partOrString),\n };\n}\n\n/**\n * Creates a `Content` object with a model role from a `PartListUnion` object or `string`.\n */\nexport function createModelContent(\n partOrString: PartListUnion | string,\n): Content {\n return {\n role: 'model',\n parts: _toParts(partOrString),\n };\n}\n/** HTTP retry options to be used in each of the requests. */\nexport declare interface HttpRetryOptions {\n /** Maximum number of attempts, including the original request.\n If 0 or 1, it means no retries. If not specified, default to 5. */\n attempts?: number;\n}\n\n/** HTTP options to be used in each of the requests. */\nexport declare interface HttpOptions {\n /** The base URL for the AI platform service endpoint. */\n baseUrl?: string;\n /** The resource scope used to constructing the resource name when base_url is set */\n baseUrlResourceScope?: ResourceScope;\n /** Specifies the version of the API to use. */\n apiVersion?: string;\n /** Additional HTTP headers to be sent with the request. */\n headers?: Record<string, string>;\n /** Timeout for the request in milliseconds. */\n timeout?: number;\n /** Extra parameters to add to the request body.\n The structure must match the backend API's request structure.\n - VertexAI backend API docs: https://cloud.google.com/vertex-ai/docs/reference/rest\n - GeminiAPI backend API docs: https://ai.google.dev/api/rest */\n extraBody?: Record<string, unknown>;\n /** HTTP retry options for the request. */\n retryOptions?: HttpRetryOptions;\n}\n\n/** Schema is used to define the format of input/output data.\n\nRepresents a select subset of an [OpenAPI 3.0 schema\nobject](https://spec.openapis.org/oas/v3.0.3#schema-object). More fields may\nbe added in the future as needed. */\nexport declare interface Schema {\n /** Optional. The value should be validated against any (one or more) of the subschemas in the list. */\n anyOf?: Schema[];\n /** Optional. Default value of the data. */\n default?: unknown;\n /** Optional. The description of the data. */\n description?: string;\n /** Optional. Possible values of the element of primitive type with enum format. Examples: 1. We can define direction as : {type:STRING, format:enum, enum:[\"EAST\", NORTH\", \"SOUTH\", \"WEST\"]} 2. We can define apartment number as : {type:INTEGER, format:enum, enum:[\"101\", \"201\", \"301\"]} */\n enum?: string[];\n /** Optional. Example of the object. Will only populated when the object is the root. */\n example?: unknown;\n /** Optional. The format of the data. Supported formats: for NUMBER type: \"float\", \"double\" for INTEGER type: \"int32\", \"int64\" for STRING type: \"email\", \"byte\", etc */\n format?: string;\n /** Optional. SCHEMA FIELDS FOR TYPE ARRAY Schema of the elements of Type.ARRAY. */\n items?: Schema;\n /** Optional. Maximum number of the elements for Type.ARRAY. */\n maxItems?: string;\n /** Optional. Maximum length of the Type.STRING */\n maxLength?: string;\n /** Optional. Maximum number of the properties for Type.OBJECT. */\n maxProperties?: string;\n /** Optional. Maximum value of the Type.INTEGER and Type.NUMBER */\n maximum?: number;\n /** Optional. Minimum number of the elements for Type.ARRAY. */\n minItems?: string;\n /** Optional. SCHEMA FIELDS FOR TYPE STRING Minimum length of the Type.STRING */\n minLength?: string;\n /** Optional. Minimum number of the properties for Type.OBJECT. */\n minProperties?: string;\n /** Optional. SCHEMA FIELDS FOR TYPE INTEGER and NUMBER Minimum value of the Type.INTEGER and Type.NUMBER */\n minimum?: number;\n /** Optional. Indicates if the value may be null. */\n nullable?: boolean;\n /** Optional. Pattern of the Type.STRING to restrict a string to a regular expression. */\n pattern?: string;\n /** Optional. SCHEMA FIELDS FOR TYPE OBJECT Properties of Type.OBJECT. */\n properties?: Record<string, Schema>;\n /** Optional. The order of the properties. Not a standard field in open api spec. Only used to support the order of the properties. */\n propertyOrdering?: string[];\n /** Optional. Required properties of Type.OBJECT. */\n required?: string[];\n /** Optional. The title of the Schema. */\n title?: string;\n /** Optional. The type of the data. */\n type?: Type;\n}\n\n/** Config for model selection. */\nexport declare interface ModelSelectionConfig {\n /** Options for feature selection preference. */\n featureSelectionPreference?: FeatureSelectionPreference;\n}\n\n/** Tool to support computer use. */\nexport declare interface ComputerUse {\n /** Required. The environment being operated. */\n environment?: Environment;\n /** By default, predefined functions are included in the final model call.\n Some of them can be explicitly excluded from being automatically included.\n This can serve two purposes:\n 1. Using a more restricted / different action space.\n 2. Improving the definitions / instructions of predefined functions. */\n excludedPredefinedFunctions?: string[];\n}\n\n/** Tool to retrieve knowledge from the File Search Stores. */\nexport declare interface FileSearch {\n /** The names of the file_search_stores to retrieve from.\n Example: `fileSearchStores/my-file-search-store-123` */\n fileSearchStoreNames?: string[];\n /** The number of file search retrieval chunks to retrieve. */\n topK?: number;\n /** Metadata filter to apply to the file search retrieval documents. See https://google.aip.dev/160 for the syntax of the filter expression. */\n metadataFilter?: string;\n}\n\n/** The API secret. This data type is not supported in Gemini API. */\nexport declare interface ApiAuthApiKeyConfig {\n /** Required. The SecretManager secret version resource name storing API key. e.g. projects/{project}/secrets/{secret}/versions/{version} */\n apiKeySecretVersion?: string;\n /** The API key string. Either this or `api_key_secret_version` must be set. */\n apiKeyString?: string;\n}\n\n/** The generic reusable api auth config. Deprecated. Please use AuthConfig (google/cloud/aiplatform/master/auth.proto) instead. This data type is not supported in Gemini API. */\nexport declare interface ApiAuth {\n /** The API secret. */\n apiKeyConfig?: ApiAuthApiKeyConfig;\n}\n\n/** Config for authentication with API key. This data type is not supported in Gemini API. */\nexport declare interface ApiKeyConfig {\n /** Optional. The name of the SecretManager secret version resource storing the API key. Format: `projects/{project}/secrets/{secrete}/versions/{version}` - If both `api_key_secret` and `api_key_string` are specified, this field takes precedence over `api_key_string`. - If specified, the `secretmanager.versions.access` permission should be granted to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents) on the specified resource. */\n apiKeySecret?: string;\n /** Optional. The API key to be used in the request directly. */\n apiKeyString?: string;\n /** Optional. The location of the API key. */\n httpElementLocation?: HttpElementLocation;\n /** Optional. The parameter name of the API key. E.g. If the API request is \"https://example.com/act?api_key=\", \"api_key\" would be the parameter name. */\n name?: string;\n}\n\n/** Config for Google Service Account Authentication. This data type is not supported in Gemini API. */\nexport declare interface AuthConfigGoogleServiceAccountConfig {\n /** Optional. The service account that the extension execution service runs as. - If the service account is specified, the `iam.serviceAccounts.getAccessToken` permission should be granted to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents) on the specified service account. - If not specified, the Vertex AI Extension Service Agent will be used to execute the Extension. */\n serviceAccount?: string;\n}\n\n/** Config for HTTP Basic Authentication. This data type is not supported in Gemini API. */\nexport declare interface AuthConfigHttpBasicAuthConfig {\n /** Required. The name of the SecretManager secret version resource storing the base64 encoded credentials. Format: `projects/{project}/secrets/{secrete}/versions/{version}` - If specified, the `secretmanager.versions.access` permission should be granted to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents) on the specified resource. */\n credentialSecret?: string;\n}\n\n/** Config for user oauth. This data type is not supported in Gemini API. */\nexport declare interface AuthConfigOauthConfig {\n /** Access token for extension endpoint. Only used to propagate token from [[ExecuteExtensionRequest.runtime_auth_config]] at request time. */\n accessToken?: string;\n /** The service account used to generate access tokens for executing the Extension. - If the service account is specified, the `iam.serviceAccounts.getAccessToken` permission should be granted to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents) on the provided service account. */\n serviceAccount?: string;\n}\n\n/** Config for user OIDC auth. This data type is not supported in Gemini API. */\nexport declare interface AuthConfigOidcConfig {\n /** OpenID Connect formatted ID token for extension endpoint. Only used to propagate token from [[ExecuteExtensionRequest.runtime_auth_config]] at request time. */\n idToken?: string;\n /** The service account used to generate an OpenID Connect (OIDC)-compatible JWT token signed by the Google OIDC Provider (accounts.google.com) for extension endpoint (https://cloud.google.com/iam/docs/create-short-lived-credentials-direct#sa-credentials-oidc). - The audience for the token will be set to the URL in the server url defined in the OpenApi spec. - If the service account is provided, the service account should grant `iam.serviceAccounts.getOpenIdToken` permission to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents). */\n serviceAccount?: string;\n}\n\n/** Auth configuration to run the extension. This data type is not supported in Gemini API. */\nexport declare interface AuthConfig {\n /** Config for API key auth. */\n apiKeyConfig?: ApiKeyConfig;\n /** Type of auth scheme. */\n authType?: AuthType;\n /** Config for Google Service Account auth. */\n googleServiceAccountConfig?: AuthConfigGoogleServiceAccountConfig;\n /** Config for HTTP Basic auth. */\n httpBasicAuthConfig?: AuthConfigHttpBasicAuthConfig;\n /** Config for user oauth. */\n oauthConfig?: AuthConfigOauthConfig;\n /** Config for user OIDC auth. */\n oidcConfig?: AuthConfigOidcConfig;\n}\n\n/** The search parameters to use for the ELASTIC_SEARCH spec. This data type is not supported in Gemini API. */\nexport declare interface ExternalApiElasticSearchParams {\n /** The ElasticSearch index to use. */\n index?: string;\n /** Optional. Number of hits (chunks) to request. When specified, it is passed to Elasticsearch as the `num_hits` param. */\n numHits?: number;\n /** The ElasticSearch search template to use. */\n searchTemplate?: string;\n}\n\n/** The search parameters to use for SIMPLE_SEARCH spec. This data type is not supported in Gemini API. */\nexport declare interface ExternalApiSimpleSearchParams {}\n\n/** Retrieve from data source powered by external API for grounding. The external API is not owned by Google, but need to follow the pre-defined API spec. This data type is not supported in Gemini API. */\nexport declare interface ExternalApi {\n /** The authentication config to access the API. Deprecated. Please use auth_config instead. */\n apiAuth?: ApiAuth;\n /** The API spec that the external API implements. */\n apiSpec?: ApiSpec;\n /** The authentication config to access the API. */\n authConfig?: AuthConfig;\n /** Parameters for the elastic search API. */\n elasticSearchParams?: ExternalApiElasticSearchParams;\n /** The endpoint of the external API. The system will call the API at this endpoint to retrieve the data for grounding. Example: https://acme.com:443/search */\n endpoint?: string;\n /** Parameters for the simple search API. */\n simpleSearchParams?: ExternalApiSimpleSearchParams;\n}\n\n/** Define data stores within engine to filter on in a search call and configurations for those data stores. For more information, see https://cloud.google.com/generative-ai-app-builder/docs/reference/rpc/google.cloud.discoveryengine.v1#datastorespec. This data type is not supported in Gemini API. */\nexport declare interface VertexAISearchDataStoreSpec {\n /** Full resource name of DataStore, such as Format: `projects/{project}/locations/{location}/collections/{collection}/dataStores/{dataStore}` */\n dataStore?: string;\n /** Optional. Filter specification to filter documents in the data store specified by data_store field. For more information on filtering, see [Filtering](https://cloud.google.com/generative-ai-app-builder/docs/filter-search-metadata) */\n filter?: string;\n}\n\n/** Retrieve from Vertex AI Search datastore or engine for grounding. datastore and engine are mutually exclusive. See https://cloud.google.com/products/agent-builder. This data type is not supported in Gemini API. */\nexport declare interface VertexAISearch {\n /** Specifications that define the specific DataStores to be searched, along with configurations for those data stores. This is only considered for Engines with multiple data stores. It should only be set if engine is used. */\n dataStoreSpecs?: VertexAISearchDataStoreSpec[];\n /** Optional. Fully-qualified Vertex AI Search data store resource ID. Format: `projects/{project}/locations/{location}/collections/{collection}/dataStores/{dataStore}` */\n datastore?: string;\n /** Optional. Fully-qualified Vertex AI Search engine resource ID. Format: `projects/{project}/locations/{location}/collections/{collection}/engines/{engine}` */\n engine?: string;\n /** Optional. Filter strings to be passed to the search API. */\n filter?: string;\n /** Optional. Number of search results to return per query. The default value is 10. The maximumm allowed value is 10. */\n maxResults?: number;\n}\n\n/** The definition of the Rag resource. This data type is not supported in Gemini API. */\nexport declare interface VertexRagStoreRagResource {\n /** Optional. RagCorpora resource name. Format: `projects/{project}/locations/{location}/ragCorpora/{rag_corpus}` */\n ragCorpus?: string;\n /** Optional. rag_file_id. The files should be in the same rag_corpus set in rag_corpus field. */\n ragFileIds?: string[];\n}\n\n/** Config for filters. This data type is not supported in Gemini API. */\nexport declare interface RagRetrievalConfigFilter {\n /** Optional. String for metadata filtering. */\n metadataFilter?: string;\n /** Optional. Only returns contexts with vector distance smaller than the threshold. */\n vectorDistanceThreshold?: number;\n /** Optional. Only returns contexts with vector similarity larger than the threshold. */\n vectorSimilarityThreshold?: number;\n}\n\n/** Config for Hybrid Search. This data type is not supported in Gemini API. */\nexport declare interface RagRetrievalConfigHybridSearch {\n /** Optional. Alpha value controls the weight between dense and sparse vector search results. The range is [0, 1], while 0 means sparse vector search only and 1 means dense vector search only. The default value is 0.5 which balances sparse and dense vector search equally. */\n alpha?: number;\n}\n\n/** Config for LlmRanker. This data type is not supported in Gemini API. */\nexport declare interface RagRetrievalConfigRankingLlmRanker {\n /** Optional. The model name used for ranking. See [Supported models](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference#supported-models). */\n modelName?: string;\n}\n\n/** Config for Rank Service. This data type is not supported in Gemini API. */\nexport declare interface RagRetrievalConfigRankingRankService {\n /** Optional. The model name of the rank service. Format: `semantic-ranker-512@latest` */\n modelName?: string;\n}\n\n/** Config for ranking and reranking. This data type is not supported in Gemini API. */\nexport declare interface RagRetrievalConfigRanking {\n /** Optional. Config for LlmRanker. */\n llmRanker?: RagRetrievalConfigRankingLlmRanker;\n /** Optional. Config for Rank Service. */\n rankService?: RagRetrievalConfigRankingRankService;\n}\n\n/** Specifies the context retrieval config. This data type is not supported in Gemini API. */\nexport declare interface RagRetrievalConfig {\n /** Optional. Config for filters. */\n filter?: RagRetrievalConfigFilter;\n /** Optional. Config for Hybrid Search. */\n hybridSearch?: RagRetrievalConfigHybridSearch;\n /** Optional. Config for ranking and reranking. */\n ranking?: RagRetrievalConfigRanking;\n /** Optional. The number of contexts to retrieve. */\n topK?: number;\n}\n\n/** Retrieve from Vertex RAG Store for grounding. This data type is not supported in Gemini API. */\nexport declare interface VertexRagStore {\n /** Optional. Deprecated. Please use rag_resources instead. */\n ragCorpora?: string[];\n /** Optional. The representation of the rag source. It can be used to specify corpus only or ragfiles. Currently only support one corpus or multiple files from one corpus. In the future we may open up multiple corpora support. */\n ragResources?: VertexRagStoreRagResource[];\n /** Optional. The retrieval config for the Rag query. */\n ragRetrievalConfig?: RagRetrievalConfig;\n /** Optional. Number of top k results to return from the selected corpora. */\n similarityTopK?: number;\n /** Optional. Currently only supported for Gemini Multimodal Live API. In Gemini Multimodal Live API, if `store_context` bool is specified, Gemini will leverage it to automatically memorize the interactions between the client and Gemini, and retrieve context when needed to augment the response generation for users' ongoing and future interactions. */\n storeContext?: boolean;\n /** Optional. Only return results with vector distance smaller than the threshold. */\n vectorDistanceThreshold?: number;\n}\n\n/** Defines a retrieval tool that model can call to access external knowledge. This data type is not supported in Gemini API. */\nexport declare interface Retrieval {\n /** Optional. Deprecated. This option is no longer supported. */\n disableAttribution?: boolean;\n /** Use data source powered by external API for grounding. */\n externalApi?: ExternalApi;\n /** Set to use data source powered by Vertex AI Search. */\n vertexAiSearch?: VertexAISearch;\n /** Set to use data source powered by Vertex RAG store. User data is uploaded via the VertexRagDataService. */\n vertexRagStore?: VertexRagStore;\n}\n\n/** Tool that executes code generated by the model, and automatically returns the result to the model. See also [ExecutableCode]and [CodeExecutionResult] which are input and output to this tool. This data type is not supported in Gemini API. */\nexport declare interface ToolCodeExecution {}\n\n/** Tool to search public web data, powered by Vertex AI Search and Sec4 compliance. This data type is not supported in Gemini API. */\nexport declare interface EnterpriseWebSearch {\n /** Optional. List of domains to be excluded from the search results. The default limit is 2000 domains. */\n excludeDomains?: string[];\n /** Optional. Sites with confidence level chosen & above this value will be blocked from the search results. */\n blockingConfidence?: PhishBlockThreshold;\n}\n\n/** Structured representation of a function declaration as defined by the [OpenAPI 3.0 specification](https://spec.openapis.org/oas/v3.0.3). Included in this declaration are the function name, description, parameters and response type. This FunctionDeclaration is a representation of a block of code that can be used as a `Tool` by the model and executed by the client. */\nexport declare interface FunctionDeclaration {\n /** Optional. Description and purpose of the function. Model uses it to decide how and whether to call the function. */\n description?: string;\n /** Required. The name of the function to call. Must start with a letter or an underscore. Must be a-z, A-Z, 0-9, or contain underscores, dots and dashes, with a maximum length of 64. */\n name?: string;\n /** Optional. Describes the parameters to this function in JSON Schema Object format. Reflects the Open API 3.03 Parameter Object. string Key: the name of the parameter. Parameter names are case sensitive. Schema Value: the Schema defining the type used for the parameter. For function with no parameters, this can be left unset. Parameter names must start with a letter or an underscore and must only contain chars a-z, A-Z, 0-9, or underscores with a maximum length of 64. Example with 1 required and 1 optional parameter: type: OBJECT properties: param1: type: STRING param2: type: INTEGER required: - param1 */\n parameters?: Schema;\n /** Optional. Describes the parameters to the function in JSON Schema format. The schema must describe an object where the properties are the parameters to the function. For example: ``` { \"type\": \"object\", \"properties\": { \"name\": { \"type\": \"string\" }, \"age\": { \"type\": \"integer\" } }, \"additionalProperties\": false, \"required\": [\"name\", \"age\"], \"propertyOrdering\": [\"name\", \"age\"] } ``` This field is mutually exclusive with `parameters`. */\n parametersJsonSchema?: unknown;\n /** Optional. Describes the output from this function in JSON Schema format. Reflects the Open API 3.03 Response Object. The Schema defines the type used for the response value of the function. */\n response?: Schema;\n /** Optional. Describes the output from this function in JSON Schema format. The value specified by the schema is the response value of the function. This field is mutually exclusive with `response`. */\n responseJsonSchema?: unknown;\n /** Optional. Specifies the function Behavior. Currently only supported by the BidiGenerateContent method. This field is not supported in Vertex AI. */\n behavior?: Behavior;\n}\n\n/** Tool to retrieve public maps data for grounding, powered by Google. */\nexport declare interface GoogleMaps {\n /** The authentication config to access the API. Only API key is supported. This field is not supported in Gemini API. */\n authConfig?: AuthConfig;\n /** Optional. If true, include the widget context token in the response. */\n enableWidget?: boolean;\n}\n\n/** Represents a time interval, encoded as a Timestamp start (inclusive) and a Timestamp end (exclusive). The start must be less than or equal to the end. When the start equals the end, the interval is empty (matches no time). When both start and end are unspecified, the interval matches any time. */\nexport declare interface Interval {\n /** Optional. Exclusive end of the interval. If specified, a Timestamp matching this interval will have to be before the end. */\n endTime?: string;\n /** Optional. Inclusive start of the interval. If specified, a Timestamp matching this interval will have to be the same or after the start. */\n startTime?: string;\n}\n\n/** GoogleSearch tool type. Tool to support Google Search in Model. Powered by Google. */\nexport declare interface GoogleSearch {\n /** Optional. List of domains to be excluded from the search results. The default limit is 2000 domains. Example: [\"amazon.com\", \"facebook.com\"]. This field is not supported in Gemini API. */\n excludeDomains?: string[];\n /** Optional. Sites with confidence level chosen & above this value will be blocked from the search results. This field is not supported in Gemini API. */\n blockingConfidence?: PhishBlockThreshold;\n /** Optional. Filter search results to a specific time range. If customers set a start time, they must set an end time (and vice versa). This field is not supported in Vertex AI. */\n timeRangeFilter?: Interval;\n}\n\n/** Describes the options to customize dynamic retrieval. */\nexport declare interface DynamicRetrievalConfig {\n /** Optional. The threshold to be used in dynamic retrieval. If not set, a system default value is used. */\n dynamicThreshold?: number;\n /** The mode of the predictor to be used in dynamic retrieval. */\n mode?: DynamicRetrievalConfigMode;\n}\n\n/** Tool to retrieve public web data for grounding, powered by Google. */\nexport declare interface GoogleSearchRetrieval {\n /** Specifies the dynamic retrieval configuration for the given source. */\n dynamicRetrievalConfig?: DynamicRetrievalConfig;\n}\n\n/** Tool to support URL context. */\nexport declare interface UrlContext {}\n\n/** Tool details of a tool that the model may use to generate a response. */\nexport declare interface Tool {\n /** Optional. Retrieval tool type. System will always execute the provided retrieval tool(s) to get external knowledge to answer the prompt. Retrieval results are presented to the model for generation. This field is not supported in Gemini API. */\n retrieval?: Retrieval;\n /** Optional. Tool to support the model interacting directly with the\n computer. If enabled, it automatically populates computer-use specific\n Function Declarations. */\n computerUse?: ComputerUse;\n /** Optional. Tool to retrieve knowledge from the File Search Stores. */\n fileSearch?: FileSearch;\n /** Optional. CodeExecution tool type. Enables the model to execute code as part of generation. */\n codeExecution?: ToolCodeExecution;\n /** Optional. Tool to support searching public web data, powered by Vertex AI Search and Sec4 compliance. This field is not supported in Gemini API. */\n enterpriseWebSearch?: EnterpriseWebSearch;\n /** Optional. Function tool type. One or more function declarations to be passed to the model along with the current user query. Model may decide to call a subset of these functions by populating FunctionCall in the response. User should provide a FunctionResponse for each function call in the next turn. Based on the function responses, Model will generate the final response back to the user. Maximum 512 function declarations can be provided. */\n functionDeclarations?: FunctionDeclaration[];\n /** Optional. GoogleMaps tool type. Tool to support Google Maps in Model. */\n googleMaps?: GoogleMaps;\n /** Optional. GoogleSearch tool type. Tool to support Google Search in Model. Powered by Google. */\n googleSearch?: GoogleSearch;\n /** Optional. Specialized retrieval tool that is powered by Google Search. */\n googleSearchRetrieval?: GoogleSearchRetrieval;\n /** Optional. Tool to support URL context retrieval. */\n urlContext?: UrlContext;\n}\n\n/** An object that represents a latitude/longitude pair.\n\nThis is expressed as a pair of doubles to represent degrees latitude and\ndegrees longitude. Unless specified otherwise, this object must conform to the\n<a href=\"https://en.wikipedia.org/wiki/World_Geodetic_System#1984_version\">\nWGS84 standard</a>. Values must be within normalized ranges. */\nexport declare interface LatLng {\n /** The latitude in degrees. It must be in the range [-90.0, +90.0]. */\n latitude?: number;\n /** The longitude in degrees. It must be in the range [-180.0, +180.0] */\n longitude?: number;\n}\n\n/** Retrieval config.\n */\nexport declare interface RetrievalConfig {\n /** Optional. The location of the user. */\n latLng?: LatLng;\n /** The language code of the user. */\n languageCode?: string;\n}\n\n/** Function calling config. */\nexport declare interface FunctionCallingConfig {\n /** Optional. Function names to call. Only set when the Mode is ANY. Function names should match [FunctionDeclaration.name]. With mode set to ANY, model will predict a function call from the set of function names provided. */\n allowedFunctionNames?: string[];\n /** Optional. Function calling mode. */\n mode?: FunctionCallingConfigMode;\n /** Optional. When set to true, arguments of a single function call will be streamed out in multiple parts/contents/responses. Partial parameter results will be returned in the [FunctionCall.partial_args] field. This field is not supported in Gemini API. */\n streamFunctionCallArguments?: boolean;\n}\n\n/** Tool config.\n\nThis config is shared for all tools provided in the request. */\nexport declare interface ToolConfig {\n /** Optional. Retrieval config. */\n retrievalConfig?: RetrievalConfig;\n /** Optional. Function calling config. */\n functionCallingConfig?: FunctionCallingConfig;\n}\n\n/** ReplicatedVoiceConfig is used to configure replicated voice. */\nexport declare interface ReplicatedVoiceConfig {\n /** The mime type of the replicated voice.\n */\n mimeType?: string;\n /** The sample audio of the replicated voice.\n \n * @remarks Encoded as base64 string. */\n voiceSampleAudio?: string;\n}\n\n/** The configuration for the prebuilt speaker to use. */\nexport declare interface PrebuiltVoiceConfig {\n /** The name of the preset voice to use. */\n voiceName?: string;\n}\n\nexport declare interface VoiceConfig {\n /** If true, the model will use a replicated voice for the response. */\n replicatedVoiceConfig?: ReplicatedVoiceConfig;\n /** The configuration for the prebuilt voice to use. */\n prebuiltVoiceConfig?: PrebuiltVoiceConfig;\n}\n\n/** Configuration for a single speaker in a multi speaker setup. */\nexport declare interface SpeakerVoiceConfig {\n /** Required. The name of the speaker. This should be the same as the speaker name used in the prompt. */\n speaker?: string;\n /** Required. The configuration for the voice of this speaker. */\n voiceConfig?: VoiceConfig;\n}\n\n/** Configuration for a multi-speaker text-to-speech request. */\nexport declare interface MultiSpeakerVoiceConfig {\n /** Required. A list of configurations for the voices of the speakers. Exactly two speaker voice configurations must be provided. */\n speakerVoiceConfigs?: SpeakerVoiceConfig[];\n}\n\nexport declare interface SpeechConfig {\n /** Configuration for the voice of the response. */\n voiceConfig?: VoiceConfig;\n /** Optional. Language code (ISO 639. e.g. en-US) for the speech synthesization. */\n languageCode?: string;\n /** The configuration for a multi-speaker text-to-speech request. This field is mutually exclusive with `voice_config`. */\n multiSpeakerVoiceConfig?: MultiSpeakerVoiceConfig;\n}\n\n/** The configuration for automatic function calling. */\nexport declare interface AutomaticFunctionCallingConfig {\n /** Whether to disable automatic function calling.\n If not set or set to False, will enable automatic function calling.\n If set to True, will disable automatic function calling.\n */\n disable?: boolean;\n /** If automatic function calling is enabled,\n maximum number of remote calls for automatic function calling.\n This number should be a positive integer.\n If not set, SDK will set maximum number of remote calls to 10.\n */\n maximumRemoteCalls?: number;\n /** If automatic function calling is enabled,\n whether to ignore call history to the response.\n If not set, SDK will set ignore_call_history to false,\n and will append the call history to\n GenerateContentResponse.automatic_function_calling_history.\n */\n ignoreCallHistory?: boolean;\n}\n\n/** The thinking features configuration. */\nexport declare interface ThinkingConfig {\n /** Indicates whether to include thoughts in the response. If true, thoughts are returned only if the model supports thought and thoughts are available.\n */\n includeThoughts?: boolean;\n /** Indicates the thinking budget in tokens. 0 is DISABLED. -1 is AUTOMATIC. The default values and allowed ranges are model dependent.\n */\n thinkingBudget?: number;\n /** Optional. The number of thoughts tokens that the model should generate. */\n thinkingLevel?: ThinkingLevel;\n}\n\n/** The image generation configuration to be used in GenerateContentConfig. */\nexport declare interface ImageConfig {\n /** Aspect ratio of the generated images. Supported values are\n \"1:1\", \"2:3\", \"3:2\", \"3:4\", \"4:3\", \"9:16\", \"16:9\", and \"21:9\". */\n aspectRatio?: string;\n /** Optional. Specifies the size of generated images. Supported\n values are `1K`, `2K`, `4K`. If not specified, the model will use default\n value `1K`. */\n imageSize?: string;\n /** Controls the generation of people. Supported values are:\n ALLOW_ALL, ALLOW_ADULT, ALLOW_NONE. */\n personGeneration?: string;\n /** MIME type of the generated image. This field is not\n supported in Gemini API. */\n outputMimeType?: string;\n /** Compression quality of the generated image (for\n ``image/jpeg`` only). This field is not supported in Gemini API. */\n outputCompressionQuality?: number;\n}\n\n/** When automated routing is specified, the routing will be determined by the pretrained routing model and customer provided model routing preference. This data type is not supported in Gemini API. */\nexport declare interface GenerationConfigRoutingConfigAutoRoutingMode {\n /** The model routing preference. */\n modelRoutingPreference?:\n | 'UNKNOWN'\n | 'PRIORITIZE_QUALITY'\n | 'BALANCED'\n | 'PRIORITIZE_COST';\n}\n\n/** When manual routing is set, the specified model will be used directly. This data type is not supported in Gemini API. */\nexport declare interface GenerationConfigRoutingConfigManualRoutingMode {\n /** The model name to use. Only the public LLM models are accepted. See [Supported models](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference#supported-models). */\n modelName?: string;\n}\n\n/** The configuration for routing the request to a specific model. This data type is not supported in Gemini API. */\nexport declare interface GenerationConfigRoutingConfig {\n /** Automated routing. */\n autoMode?: GenerationConfigRoutingConfigAutoRoutingMode;\n /** Manual routing. */\n manualMode?: GenerationConfigRoutingConfigManualRoutingMode;\n}\n\n/** Safety settings. */\nexport declare interface SafetySetting {\n /** Required. Harm category. */\n category?: HarmCategory;\n /** Optional. Specify if the threshold is used for probability or severity score. If not specified, the threshold is used for probability score. This field is not supported in Gemini API. */\n method?: HarmBlockMethod;\n /** Required. The harm block threshold. */\n threshold?: HarmBlockThreshold;\n}\n\n/** Configuration for Model Armor integrations of prompt and responses. This data type is not supported in Gemini API. */\nexport declare interface ModelArmorConfig {\n /** Optional. The name of the Model Armor template to use for prompt sanitization. */\n promptTemplateName?: string;\n /** Optional. The name of the Model Armor template to use for response sanitization. */\n responseTemplateName?: string;\n}\n\n/** Optional model configuration parameters.\n\nFor more information, see `Content generation parameters\n<https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/content-generation-parameters>`_. */\nexport declare interface GenerateContentConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** Instructions for the model to steer it toward better performance.\n For example, \"Answer as concisely as possible\" or \"Don't use technical\n terms in your response\".\n */\n systemInstruction?: ContentUnion;\n /** Value that controls the degree of randomness in token selection.\n Lower temperatures are good for prompts that require a less open-ended or\n creative response, while higher temperatures can lead to more diverse or\n creative results.\n */\n temperature?: number;\n /** Tokens are selected from the most to least probable until the sum\n of their probabilities equals this value. Use a lower value for less\n random responses and a higher value for more random responses.\n */\n topP?: number;\n /** For each token selection step, the ``top_k`` tokens with the\n highest probabilities are sampled. Then tokens are further filtered based\n on ``top_p`` with the final token selected using temperature sampling. Use\n a lower number for less random responses and a higher number for more\n random responses.\n */\n topK?: number;\n /** Number of response variations to return.\n */\n candidateCount?: number;\n /** Maximum number of tokens that can be generated in the response.\n */\n maxOutputTokens?: number;\n /** List of strings that tells the model to stop generating text if one\n of the strings is encountered in the response.\n */\n stopSequences?: string[];\n /** Whether to return the log probabilities of the tokens that were\n chosen by the model at each step.\n */\n responseLogprobs?: boolean;\n /** Number of top candidate tokens to return the log probabilities for\n at each generation step.\n */\n logprobs?: number;\n /** Positive values penalize tokens that already appear in the\n generated text, increasing the probability of generating more diverse\n content.\n */\n presencePenalty?: number;\n /** Positive values penalize tokens that repeatedly appear in the\n generated text, increasing the probability of generating more diverse\n content.\n */\n frequencyPenalty?: number;\n /** When ``seed`` is fixed to a specific number, the model makes a best\n effort to provide the same response for repeated requests. By default, a\n random number is used.\n */\n seed?: number;\n /** Output response mimetype of the generated candidate text.\n Supported mimetype:\n - `text/plain`: (default) Text output.\n - `application/json`: JSON response in the candidates.\n The model needs to be prompted to output the appropriate response type,\n otherwise the behavior is undefined.\n This is a preview feature.\n */\n responseMimeType?: string;\n /** The `Schema` object allows the definition of input and output data types.\n These types can be objects, but also primitives and arrays.\n Represents a select subset of an [OpenAPI 3.0 schema\n object](https://spec.openapis.org/oas/v3.0.3#schema).\n If set, a compatible response_mime_type must also be set.\n Compatible mimetypes: `application/json`: Schema for JSON response.\n\n If `response_schema` doesn't process your schema correctly, try using\n `response_json_schema` instead.\n */\n responseSchema?: SchemaUnion;\n /** Optional. Output schema of the generated response.\n This is an alternative to `response_schema` that accepts [JSON\n Schema](https://json-schema.org/). If set, `response_schema` must be\n omitted, but `response_mime_type` is required. While the full JSON Schema\n may be sent, not all features are supported. Specifically, only the\n following properties are supported: - `$id` - `$defs` - `$ref` - `$anchor`\n - `type` - `format` - `title` - `description` - `enum` (for strings and\n numbers) - `items` - `prefixItems` - `minItems` - `maxItems` - `minimum` -\n `maximum` - `anyOf` - `oneOf` (interpreted the same as `anyOf`) -\n `properties` - `additionalProperties` - `required` The non-standard\n `propertyOrdering` property may also be set. Cyclic references are\n unrolled to a limited degree and, as such, may only be used within\n non-required properties. (Nullable properties are not sufficient.) If\n `$ref` is set on a sub-schema, no other properties, except for than those\n starting as a `$`, may be set. */\n responseJsonSchema?: unknown;\n /** Configuration for model router requests.\n */\n routingConfig?: GenerationConfigRoutingConfig;\n /** Configuration for model selection.\n */\n modelSelectionConfig?: ModelSelectionConfig;\n /** Safety settings in the request to block unsafe content in the\n response.\n */\n safetySettings?: SafetySetting[];\n /** Code that enables the system to interact with external systems to\n perform an action outside of the knowledge and scope of the model.\n */\n tools?: ToolListUnion;\n /** Associates model output to a specific function call.\n */\n toolConfig?: ToolConfig;\n /** Labels with user-defined metadata to break down billed charges. */\n labels?: Record<string, string>;\n /** Resource name of a context cache that can be used in subsequent\n requests.\n */\n cachedContent?: string;\n /** The requested modalities of the response. Represents the set of\n modalities that the model can return.\n */\n responseModalities?: string[];\n /** If specified, the media resolution specified will be used.\n */\n mediaResolution?: MediaResolution;\n /** The speech generation configuration.\n */\n speechConfig?: SpeechConfigUnion;\n /** If enabled, audio timestamp will be included in the request to the\n model.\n */\n audioTimestamp?: boolean;\n /** The configuration for automatic function calling.\n */\n automaticFunctionCalling?: AutomaticFunctionCallingConfig;\n /** The thinking features configuration.\n */\n thinkingConfig?: ThinkingConfig;\n /** The image generation configuration.\n */\n imageConfig?: ImageConfig;\n /** Enables enhanced civic answers. It may not be available for all\n models. This field is not supported in Vertex AI.\n */\n enableEnhancedCivicAnswers?: boolean;\n /** Settings for prompt and response sanitization using the Model Armor\n service. If supplied, safety_settings must not be supplied.\n */\n modelArmorConfig?: ModelArmorConfig;\n}\n\n/** Config for models.generate_content parameters. */\nexport declare interface GenerateContentParameters {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model: string;\n /** Content of the request.\n */\n contents: ContentListUnion;\n /** Configuration that contains optional model parameters.\n */\n config?: GenerateContentConfig;\n}\n\n/** A wrapper class for the http response. */\nexport class HttpResponse {\n /** Used to retain the processed HTTP headers in the response. */\n headers?: Record<string, string>;\n /**\n * The original http response.\n */\n responseInternal: Response;\n\n constructor(response: Response) {\n // Process the headers.\n const headers: Record<string, string> = {};\n for (const pair of response.headers.entries()) {\n headers[pair[0]] = pair[1];\n }\n this.headers = headers;\n\n // Keep the original response.\n this.responseInternal = response;\n }\n\n json(): Promise<unknown> {\n return this.responseInternal.json();\n }\n}\n\n/** Callbacks for the live API. */\nexport interface LiveCallbacks {\n /**\n * Called when the websocket connection is established.\n */\n onopen?: (() => void) | null;\n /**\n * Called when a message is received from the server.\n */\n onmessage: (e: LiveServerMessage) => void;\n /**\n * Called when an error occurs.\n */\n onerror?: ((e: ErrorEvent) => void) | null;\n /**\n * Called when the websocket connection is closed.\n */\n onclose?: ((e: CloseEvent) => void) | null;\n}\n\n/** Represents a whole or partial calendar date, such as a birthday. The time of day and time zone are either specified elsewhere or are insignificant. The date is relative to the Gregorian Calendar. This can represent one of the following: * A full date, with non-zero year, month, and day values. * A month and day, with a zero year (for example, an anniversary). * A year on its own, with a zero month and a zero day. * A year and month, with a zero day (for example, a credit card expiration date). Related types: * google.type.TimeOfDay * google.type.DateTime * google.protobuf.Timestamp. This data type is not supported in Gemini API. */\nexport declare interface GoogleTypeDate {\n /** Day of a month. Must be from 1 to 31 and valid for the year and month, or 0 to specify a year by itself or a year and month where the day isn't significant. */\n day?: number;\n /** Month of a year. Must be from 1 to 12, or 0 to specify a year without a month and day. */\n month?: number;\n /** Year of the date. Must be from 1 to 9999, or 0 to specify a date without a year. */\n year?: number;\n}\n\n/** Source attributions for content. This data type is not supported in Gemini API. */\nexport declare interface Citation {\n /** Output only. End index into the content. */\n endIndex?: number;\n /** Output only. License of the attribution. */\n license?: string;\n /** Output only. Publication date of the attribution. */\n publicationDate?: GoogleTypeDate;\n /** Output only. Start index into the content. */\n startIndex?: number;\n /** Output only. Title of the attribution. */\n title?: string;\n /** Output only. Url reference of the attribution. */\n uri?: string;\n}\n\n/** Citation information when the model quotes another source. */\nexport declare interface CitationMetadata {\n /** Contains citation information when the model directly quotes, at\n length, from another source. Can include traditional websites and code\n repositories.\n */\n citations?: Citation[];\n}\n\n/** Author attribution for a photo or review. This data type is not supported in Gemini API. */\nexport declare interface GroundingChunkMapsPlaceAnswerSourcesAuthorAttribution {\n /** Name of the author of the Photo or Review. */\n displayName?: string;\n /** Profile photo URI of the author of the Photo or Review. */\n photoUri?: string;\n /** URI of the author of the Photo or Review. */\n uri?: string;\n}\n\n/** Encapsulates a review snippet. This data type is not supported in Gemini API. */\nexport declare interface GroundingChunkMapsPlaceAnswerSourcesReviewSnippet {\n /** This review's author. */\n authorAttribution?: GroundingChunkMapsPlaceAnswerSourcesAuthorAttribution;\n /** A link where users can flag a problem with the review. */\n flagContentUri?: string;\n /** A link to show the review on Google Maps. */\n googleMapsUri?: string;\n /** A string of formatted recent time, expressing the review time relative to the current time in a form appropriate for the language and country. */\n relativePublishTimeDescription?: string;\n /** A reference representing this place review which may be used to look up this place review again. */\n review?: string;\n /** Id of the review referencing the place. */\n reviewId?: string;\n /** Title of the review. */\n title?: string;\n}\n\n/** Sources used to generate the place answer. This data type is not supported in Gemini API. */\nexport declare interface GroundingChunkMapsPlaceAnswerSources {\n /** A link where users can flag a problem with the generated answer. */\n flagContentUri?: string;\n /** Snippets of reviews that are used to generate the answer. */\n reviewSnippets?: GroundingChunkMapsPlaceAnswerSourcesReviewSnippet[];\n}\n\n/** Chunk from Google Maps. This data type is not supported in Gemini API. */\nexport declare interface GroundingChunkMaps {\n /** Sources used to generate the place answer. This includes review snippets and photos that were used to generate the answer, as well as uris to flag content. */\n placeAnswerSources?: GroundingChunkMapsPlaceAnswerSources;\n /** This Place's resource name, in `places/{place_id}` format. Can be used to look up the Place. */\n placeId?: string;\n /** Text of the place answer. */\n text?: string;\n /** Title of the place. */\n title?: string;\n /** URI reference of the place. */\n uri?: string;\n}\n\n/** Represents where the chunk starts and ends in the document. This data type is not supported in Gemini API. */\nexport declare interface RagChunkPageSpan {\n /** Page where chunk starts in the document. Inclusive. 1-indexed. */\n firstPage?: number;\n /** Page where chunk ends in the document. Inclusive. 1-indexed. */\n lastPage?: number;\n}\n\n/** A RagChunk includes the content of a chunk of a RagFile, and associated metadata. This data type is not supported in Gemini API. */\nexport declare interface RagChunk {\n /** If populated, represents where the chunk starts and ends in the document. */\n pageSpan?: RagChunkPageSpan;\n /** The content of the chunk. */\n text?: string;\n}\n\n/** Chunk from context retrieved by the retrieval tools. This data type is not supported in Gemini API. */\nexport declare interface GroundingChunkRetrievedContext {\n /** Output only. The full document name for the referenced Vertex AI Search document. */\n documentName?: string;\n /** Additional context for the RAG retrieval result. This is only populated when using the RAG retrieval tool. */\n ragChunk?: RagChunk;\n /** Text of the attribution. */\n text?: string;\n /** Title of the attribution. */\n title?: string;\n /** URI reference of the attribution. */\n uri?: string;\n}\n\n/** Chunk from the web. */\nexport declare interface GroundingChunkWeb {\n /** Domain of the (original) URI. This field is not supported in Gemini API. */\n domain?: string;\n /** Title of the chunk. */\n title?: string;\n /** URI reference of the chunk. */\n uri?: string;\n}\n\n/** Grounding chunk. */\nexport declare interface GroundingChunk {\n /** Grounding chunk from Google Maps. This field is not supported in Gemini API. */\n maps?: GroundingChunkMaps;\n /** Grounding chunk from context retrieved by the retrieval tools. This field is not supported in Gemini API. */\n retrievedContext?: GroundingChunkRetrievedContext;\n /** Grounding chunk from the web. */\n web?: GroundingChunkWeb;\n}\n\n/** Segment of the content. */\nexport declare interface Segment {\n /** Output only. End index in the given Part, measured in bytes. Offset from the start of the Part, exclusive, starting at zero. */\n endIndex?: number;\n /** Output only. The index of a Part object within its parent Content object. */\n partIndex?: number;\n /** Output only. Start index in the given Part, measured in bytes. Offset from the start of the Part, inclusive, starting at zero. */\n startIndex?: number;\n /** Output only. The text corresponding to the segment from the response. */\n text?: string;\n}\n\n/** Grounding support. */\nexport declare interface GroundingSupport {\n /** Confidence score of the support references. Ranges from 0 to 1. 1 is the most confident. For Gemini 2.0 and before, this list must have the same size as the grounding_chunk_indices. For Gemini 2.5 and after, this list will be empty and should be ignored. */\n confidenceScores?: number[];\n /** A list of indices (into 'grounding_chunk') specifying the citations associated with the claim. For instance [1,3,4] means that grounding_chunk[1], grounding_chunk[3], grounding_chunk[4] are the retrieved content attributed to the claim. */\n groundingChunkIndices?: number[];\n /** Segment of the content this support belongs to. */\n segment?: Segment;\n}\n\n/** Metadata related to retrieval in the grounding flow. */\nexport declare interface RetrievalMetadata {\n /** Optional. Score indicating how likely information from Google Search could help answer the prompt. The score is in the range `[0, 1]`, where 0 is the least likely and 1 is the most likely. This score is only populated when Google Search grounding and dynamic retrieval is enabled. It will be compared to the threshold to determine whether to trigger Google Search. */\n googleSearchDynamicRetrievalScore?: number;\n}\n\n/** Google search entry point. */\nexport declare interface SearchEntryPoint {\n /** Optional. Web content snippet that can be embedded in a web page or an app webview. */\n renderedContent?: string;\n /** Optional. Base64 encoded JSON representing array of tuple.\n * @remarks Encoded as base64 string. */\n sdkBlob?: string;\n}\n\n/** Source content flagging uri for a place or review. This is currently populated only for Google Maps grounding. This data type is not supported in Gemini API. */\nexport declare interface GroundingMetadataSourceFlaggingUri {\n /** A link where users can flag a problem with the source (place or review). */\n flagContentUri?: string;\n /** Id of the place or review. */\n sourceId?: string;\n}\n\n/** Metadata returned to client when grounding is enabled. */\nexport declare interface GroundingMetadata {\n /** Optional. Output only. Resource name of the Google Maps widget context token to be used with the PlacesContextElement widget to render contextual data. This is populated only for Google Maps grounding. This field is not supported in Gemini API. */\n googleMapsWidgetContextToken?: string;\n /** List of supporting references retrieved from specified grounding source. */\n groundingChunks?: GroundingChunk[];\n /** Optional. List of grounding support. */\n groundingSupports?: GroundingSupport[];\n /** Optional. Output only. Retrieval metadata. */\n retrievalMetadata?: RetrievalMetadata;\n /** Optional. Queries executed by the retrieval tools. This field is not supported in Gemini API. */\n retrievalQueries?: string[];\n /** Optional. Google search entry for the following-up web searches. */\n searchEntryPoint?: SearchEntryPoint;\n /** Optional. Output only. List of source flagging uris. This is currently populated only for Google Maps grounding. This field is not supported in Gemini API. */\n sourceFlaggingUris?: GroundingMetadataSourceFlaggingUri[];\n /** Optional. Web search queries for the following-up web search. */\n webSearchQueries?: string[];\n}\n\n/** Candidate for the logprobs token and score. */\nexport declare interface LogprobsResultCandidate {\n /** The candidate's log probability. */\n logProbability?: number;\n /** The candidate's token string value. */\n token?: string;\n /** The candidate's token id value. */\n tokenId?: number;\n}\n\n/** Candidates with top log probabilities at each decoding step. */\nexport declare interface LogprobsResultTopCandidates {\n /** Sorted by log probability in descending order. */\n candidates?: LogprobsResultCandidate[];\n}\n\n/** Logprobs Result */\nexport declare interface LogprobsResult {\n /** Length = total number of decoding steps. The chosen candidates may or may not be in top_candidates. */\n chosenCandidates?: LogprobsResultCandidate[];\n /** Length = total number of decoding steps. */\n topCandidates?: LogprobsResultTopCandidates[];\n}\n\n/** Safety rating corresponding to the generated content. */\nexport declare interface SafetyRating {\n /** Output only. Indicates whether the content was filtered out because of this rating. */\n blocked?: boolean;\n /** Output only. Harm category. */\n category?: HarmCategory;\n /** Output only. The overwritten threshold for the safety category of Gemini 2.0 image out. If minors are detected in the output image, the threshold of each safety category will be overwritten if user sets a lower threshold. This field is not supported in Gemini API. */\n overwrittenThreshold?: HarmBlockThreshold;\n /** Output only. Harm probability levels in the content. */\n probability?: HarmProbability;\n /** Output only. Harm probability score. This field is not supported in Gemini API. */\n probabilityScore?: number;\n /** Output only. Harm severity levels in the content. This field is not supported in Gemini API. */\n severity?: HarmSeverity;\n /** Output only. Harm severity score. This field is not supported in Gemini API. */\n severityScore?: number;\n}\n\n/** Context of the a single url retrieval. */\nexport declare interface UrlMetadata {\n /** Retrieved url by the tool. */\n retrievedUrl?: string;\n /** Status of the url retrieval. */\n urlRetrievalStatus?: UrlRetrievalStatus;\n}\n\n/** Metadata related to url context retrieval tool. */\nexport declare interface UrlContextMetadata {\n /** Output only. List of url context. */\n urlMetadata?: UrlMetadata[];\n}\n\n/** A response candidate generated from the model. */\nexport declare interface Candidate {\n /** Contains the multi-part content of the response.\n */\n content?: Content;\n /** Source attribution of the generated content.\n */\n citationMetadata?: CitationMetadata;\n /** Describes the reason the model stopped generating tokens.\n */\n finishMessage?: string;\n /** Number of tokens for this candidate.\n */\n tokenCount?: number;\n /** The reason why the model stopped generating tokens.\n If empty, the model has not stopped generating the tokens.\n */\n finishReason?: FinishReason;\n /** Output only. Average log probability score of the candidate. */\n avgLogprobs?: number;\n /** Output only. Metadata specifies sources used to ground generated content. */\n groundingMetadata?: GroundingMetadata;\n /** Output only. Index of the candidate. */\n index?: number;\n /** Output only. Log-likelihood scores for the response tokens and top tokens */\n logprobsResult?: LogprobsResult;\n /** Output only. List of ratings for the safety of a response candidate. There is at most one rating per category. */\n safetyRatings?: SafetyRating[];\n /** Output only. Metadata related to url context retrieval tool. */\n urlContextMetadata?: UrlContextMetadata;\n}\n\n/** Content filter results for a prompt sent in the request. Note: This is sent only in the first stream chunk and only if no candidates were generated due to content violations. */\nexport class GenerateContentResponsePromptFeedback {\n /** Output only. The reason why the prompt was blocked. */\n blockReason?: BlockedReason;\n /** Output only. A readable message that explains the reason why the prompt was blocked. This field is not supported in Gemini API. */\n blockReasonMessage?: string;\n /** Output only. A list of safety ratings for the prompt. There is one rating per category. */\n safetyRatings?: SafetyRating[];\n}\n\n/** Represents token counting info for a single modality. */\nexport declare interface ModalityTokenCount {\n /** The modality associated with this token count. */\n modality?: MediaModality;\n /** Number of tokens. */\n tokenCount?: number;\n}\n\n/** Usage metadata about the content generation request and response. This message provides a detailed breakdown of token usage and other relevant metrics. This data type is not supported in Gemini API. */\nexport class GenerateContentResponseUsageMetadata {\n /** Output only. A detailed breakdown of the token count for each modality in the cached content. */\n cacheTokensDetails?: ModalityTokenCount[];\n /** Output only. The number of tokens in the cached content that was used for this request. */\n cachedContentTokenCount?: number;\n /** The total number of tokens in the generated candidates. */\n candidatesTokenCount?: number;\n /** Output only. A detailed breakdown of the token count for each modality in the generated candidates. */\n candidatesTokensDetails?: ModalityTokenCount[];\n /** The total number of tokens in the prompt. This includes any text, images, or other media provided in the request. When `cached_content` is set, this also includes the number of tokens in the cached content. */\n promptTokenCount?: number;\n /** Output only. A detailed breakdown of the token count for each modality in the prompt. */\n promptTokensDetails?: ModalityTokenCount[];\n /** Output only. The number of tokens that were part of the model's generated \"thoughts\" output, if applicable. */\n thoughtsTokenCount?: number;\n /** Output only. The number of tokens in the results from tool executions, which are provided back to the model as input, if applicable. */\n toolUsePromptTokenCount?: number;\n /** Output only. A detailed breakdown by modality of the token counts from the results of tool executions, which are provided back to the model as input. */\n toolUsePromptTokensDetails?: ModalityTokenCount[];\n /** The total number of tokens for the entire request. This is the sum of `prompt_token_count`, `candidates_token_count`, `tool_use_prompt_token_count`, and `thoughts_token_count`. */\n totalTokenCount?: number;\n /** Output only. The traffic type for this request. */\n trafficType?: TrafficType;\n}\n\n/** Response message for PredictionService.GenerateContent. */\nexport class GenerateContentResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** Response variations returned by the model.\n */\n candidates?: Candidate[];\n /** Timestamp when the request is made to the server.\n */\n createTime?: string;\n /** The history of automatic function calling.\n */\n automaticFunctionCallingHistory?: Content[];\n /** Output only. The model version used to generate the response. */\n modelVersion?: string;\n /** Output only. Content filter results for a prompt sent in the request. Note: Sent only in the first stream chunk. Only happens when no candidates were generated due to content violations. */\n promptFeedback?: GenerateContentResponsePromptFeedback;\n /** Output only. response_id is used to identify each response. It is the encoding of the event_id. */\n responseId?: string;\n /** Usage metadata about the response(s). */\n usageMetadata?: GenerateContentResponseUsageMetadata;\n /**\n * Returns the concatenation of all text parts from the first candidate in the response.\n *\n * @remarks\n * If there are multiple candidates in the response, the text from the first\n * one will be returned.\n * If there are non-text parts in the response, the concatenation of all text\n * parts will be returned, and a warning will be logged.\n * If there are thought parts in the response, the concatenation of all text\n * parts excluding the thought parts will be returned.\n *\n * @example\n * ```ts\n * const response = await ai.models.generateContent({\n * model: 'gemini-2.0-flash',\n * contents:\n * 'Why is the sky blue?',\n * });\n *\n * console.debug(response.text);\n * ```\n */\n get text(): string | undefined {\n if (this.candidates?.[0]?.content?.parts?.length === 0) {\n return undefined;\n }\n if (this.candidates && this.candidates.length > 1) {\n console.warn(\n 'there are multiple candidates in the response, returning text from the first one.',\n );\n }\n let text = '';\n let anyTextPartText = false;\n const nonTextParts = [];\n for (const part of this.candidates?.[0]?.content?.parts ?? []) {\n for (const [fieldName, fieldValue] of Object.entries(part)) {\n if (\n fieldName !== 'text' &&\n fieldName !== 'thought' &&\n fieldName !== 'thoughtSignature' &&\n (fieldValue !== null || fieldValue !== undefined)\n ) {\n nonTextParts.push(fieldName);\n }\n }\n if (typeof part.text === 'string') {\n if (typeof part.thought === 'boolean' && part.thought) {\n continue;\n }\n anyTextPartText = true;\n text += part.text;\n }\n }\n if (nonTextParts.length > 0) {\n console.warn(\n `there are non-text parts ${nonTextParts} in the response, returning concatenation of all text parts. Please refer to the non text parts for a full response from model.`,\n );\n }\n // part.text === '' is different from part.text is null\n return anyTextPartText ? text : undefined;\n }\n\n /**\n * Returns the concatenation of all inline data parts from the first candidate\n * in the response.\n *\n * @remarks\n * If there are multiple candidates in the response, the inline data from the\n * first one will be returned. If there are non-inline data parts in the\n * response, the concatenation of all inline data parts will be returned, and\n * a warning will be logged.\n */\n get data(): string | undefined {\n if (this.candidates?.[0]?.content?.parts?.length === 0) {\n return undefined;\n }\n if (this.candidates && this.candidates.length > 1) {\n console.warn(\n 'there are multiple candidates in the response, returning data from the first one.',\n );\n }\n let data = '';\n const nonDataParts = [];\n for (const part of this.candidates?.[0]?.content?.parts ?? []) {\n for (const [fieldName, fieldValue] of Object.entries(part)) {\n if (\n fieldName !== 'inlineData' &&\n (fieldValue !== null || fieldValue !== undefined)\n ) {\n nonDataParts.push(fieldName);\n }\n }\n if (part.inlineData && typeof part.inlineData.data === 'string') {\n data += atob(part.inlineData.data);\n }\n }\n if (nonDataParts.length > 0) {\n console.warn(\n `there are non-data parts ${nonDataParts} in the response, returning concatenation of all data parts. Please refer to the non data parts for a full response from model.`,\n );\n }\n return data.length > 0 ? btoa(data) : undefined;\n }\n\n /**\n * Returns the function calls from the first candidate in the response.\n *\n * @remarks\n * If there are multiple candidates in the response, the function calls from\n * the first one will be returned.\n * If there are no function calls in the response, undefined will be returned.\n *\n * @example\n * ```ts\n * const controlLightFunctionDeclaration: FunctionDeclaration = {\n * name: 'controlLight',\n * parameters: {\n * type: Type.OBJECT,\n * description: 'Set the brightness and color temperature of a room light.',\n * properties: {\n * brightness: {\n * type: Type.NUMBER,\n * description:\n * 'Light level from 0 to 100. Zero is off and 100 is full brightness.',\n * },\n * colorTemperature: {\n * type: Type.STRING,\n * description:\n * 'Color temperature of the light fixture which can be `daylight`, `cool` or `warm`.',\n * },\n * },\n * required: ['brightness', 'colorTemperature'],\n * };\n * const response = await ai.models.generateContent({\n * model: 'gemini-2.0-flash',\n * contents: 'Dim the lights so the room feels cozy and warm.',\n * config: {\n * tools: [{functionDeclarations: [controlLightFunctionDeclaration]}],\n * toolConfig: {\n * functionCallingConfig: {\n * mode: FunctionCallingConfigMode.ANY,\n * allowedFunctionNames: ['controlLight'],\n * },\n * },\n * },\n * });\n * console.debug(JSON.stringify(response.functionCalls));\n * ```\n */\n get functionCalls(): FunctionCall[] | undefined {\n if (this.candidates?.[0]?.content?.parts?.length === 0) {\n return undefined;\n }\n if (this.candidates && this.candidates.length > 1) {\n console.warn(\n 'there are multiple candidates in the response, returning function calls from the first one.',\n );\n }\n const functionCalls = this.candidates?.[0]?.content?.parts\n ?.filter((part) => part.functionCall)\n .map((part) => part.functionCall)\n .filter(\n (functionCall): functionCall is FunctionCall =>\n functionCall !== undefined,\n );\n if (functionCalls?.length === 0) {\n return undefined;\n }\n return functionCalls;\n }\n /**\n * Returns the first executable code from the first candidate in the response.\n *\n * @remarks\n * If there are multiple candidates in the response, the executable code from\n * the first one will be returned.\n * If there are no executable code in the response, undefined will be\n * returned.\n *\n * @example\n * ```ts\n * const response = await ai.models.generateContent({\n * model: 'gemini-2.0-flash',\n * contents:\n * 'What is the sum of the first 50 prime numbers? Generate and run code for the calculation, and make sure you get all 50.'\n * config: {\n * tools: [{codeExecution: {}}],\n * },\n * });\n *\n * console.debug(response.executableCode);\n * ```\n */\n get executableCode(): string | undefined {\n if (this.candidates?.[0]?.content?.parts?.length === 0) {\n return undefined;\n }\n if (this.candidates && this.candidates.length > 1) {\n console.warn(\n 'there are multiple candidates in the response, returning executable code from the first one.',\n );\n }\n const executableCode = this.candidates?.[0]?.content?.parts\n ?.filter((part) => part.executableCode)\n .map((part) => part.executableCode)\n .filter(\n (executableCode): executableCode is ExecutableCode =>\n executableCode !== undefined,\n );\n if (executableCode?.length === 0) {\n return undefined;\n }\n\n return executableCode?.[0]?.code;\n }\n /**\n * Returns the first code execution result from the first candidate in the response.\n *\n * @remarks\n * If there are multiple candidates in the response, the code execution result from\n * the first one will be returned.\n * If there are no code execution result in the response, undefined will be returned.\n *\n * @example\n * ```ts\n * const response = await ai.models.generateContent({\n * model: 'gemini-2.0-flash',\n * contents:\n * 'What is the sum of the first 50 prime numbers? Generate and run code for the calculation, and make sure you get all 50.'\n * config: {\n * tools: [{codeExecution: {}}],\n * },\n * });\n *\n * console.debug(response.codeExecutionResult);\n * ```\n */\n get codeExecutionResult(): string | undefined {\n if (this.candidates?.[0]?.content?.parts?.length === 0) {\n return undefined;\n }\n if (this.candidates && this.candidates.length > 1) {\n console.warn(\n 'there are multiple candidates in the response, returning code execution result from the first one.',\n );\n }\n const codeExecutionResult = this.candidates?.[0]?.content?.parts\n ?.filter((part) => part.codeExecutionResult)\n .map((part) => part.codeExecutionResult)\n .filter(\n (codeExecutionResult): codeExecutionResult is CodeExecutionResult =>\n codeExecutionResult !== undefined,\n );\n if (codeExecutionResult?.length === 0) {\n return undefined;\n }\n return codeExecutionResult?.[0]?.output;\n }\n}\n\nexport type ReferenceImage =\n | RawReferenceImage\n | MaskReferenceImage\n | ControlReferenceImage\n | StyleReferenceImage\n | SubjectReferenceImage\n | ContentReferenceImage;\n\n/** Parameters for the request to edit an image. */\nexport declare interface EditImageParameters {\n /** The model to use. */\n model: string;\n /** A text description of the edit to apply to the image. */\n prompt: string;\n /** The reference images for Imagen 3 editing. */\n referenceImages: ReferenceImage[];\n /** Configuration for editing. */\n config?: EditImageConfig;\n}\n\n/** Optional parameters for the embed_content method. */\nexport declare interface EmbedContentConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** Type of task for which the embedding will be used.\n */\n taskType?: string;\n /** Title for the text. Only applicable when TaskType is\n `RETRIEVAL_DOCUMENT`.\n */\n title?: string;\n /** Reduced dimension for the output embedding. If set,\n excessive values in the output embedding are truncated from the end.\n Supported by newer models since 2024 only. You cannot set this value if\n using the earlier model (`models/embedding-001`).\n */\n outputDimensionality?: number;\n /** Vertex API only. The MIME type of the input.\n */\n mimeType?: string;\n /** Vertex API only. Whether to silently truncate inputs longer than\n the max sequence length. If this option is set to false, oversized inputs\n will lead to an INVALID_ARGUMENT error, similar to other text APIs.\n */\n autoTruncate?: boolean;\n}\n\n/** Parameters for the embed_content method. */\nexport declare interface EmbedContentParameters {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model: string;\n /** The content to embed. Only the `parts.text` fields will be counted.\n */\n contents: ContentListUnion;\n /** Configuration that contains optional parameters.\n */\n config?: EmbedContentConfig;\n}\n\n/** Statistics of the input text associated with the result of content embedding. */\nexport declare interface ContentEmbeddingStatistics {\n /** Vertex API only. If the input text was truncated due to having\n a length longer than the allowed maximum input.\n */\n truncated?: boolean;\n /** Vertex API only. Number of tokens of the input text.\n */\n tokenCount?: number;\n}\n\n/** The embedding generated from an input content. */\nexport declare interface ContentEmbedding {\n /** A list of floats representing an embedding.\n */\n values?: number[];\n /** Vertex API only. Statistics of the input text associated with this\n embedding.\n */\n statistics?: ContentEmbeddingStatistics;\n}\n\n/** Request-level metadata for the Vertex Embed Content API. */\nexport declare interface EmbedContentMetadata {\n /** Vertex API only. The total number of billable characters included\n in the request.\n */\n billableCharacterCount?: number;\n}\n\n/** Response for the embed_content method. */\nexport class EmbedContentResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** The embeddings for each request, in the same order as provided in\n the batch request.\n */\n embeddings?: ContentEmbedding[];\n /** Vertex API only. Metadata about the request.\n */\n metadata?: EmbedContentMetadata;\n}\n\n/** The config for generating an images. */\nexport declare interface GenerateImagesConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** Cloud Storage URI used to store the generated images. */\n outputGcsUri?: string;\n /** Description of what to discourage in the generated images. */\n negativePrompt?: string;\n /** Number of images to generate. */\n numberOfImages?: number;\n /** Aspect ratio of the generated images. Supported values are\n \"1:1\", \"3:4\", \"4:3\", \"9:16\", and \"16:9\". */\n aspectRatio?: string;\n /** Controls how much the model adheres to the text prompt. Large\n values increase output and prompt alignment, but may compromise image\n quality. */\n guidanceScale?: number;\n /** Random seed for image generation. This is not available when\n ``add_watermark`` is set to true. */\n seed?: number;\n /** Filter level for safety filtering. */\n safetyFilterLevel?: SafetyFilterLevel;\n /** Allows generation of people by the model. */\n personGeneration?: PersonGeneration;\n /** Whether to report the safety scores of each generated image and\n the positive prompt in the response. */\n includeSafetyAttributes?: boolean;\n /** Whether to include the Responsible AI filter reason if the image\n is filtered out of the response. */\n includeRaiReason?: boolean;\n /** Language of the text in the prompt. */\n language?: ImagePromptLanguage;\n /** MIME type of the generated image. */\n outputMimeType?: string;\n /** Compression quality of the generated image (for ``image/jpeg``\n only). */\n outputCompressionQuality?: number;\n /** Whether to add a watermark to the generated images. */\n addWatermark?: boolean;\n /** User specified labels to track billing usage. */\n labels?: Record<string, string>;\n /** The size of the largest dimension of the generated image.\n Supported sizes are 1K and 2K (not supported for Imagen 3 models). */\n imageSize?: string;\n /** Whether to use the prompt rewriting logic. */\n enhancePrompt?: boolean;\n}\n\n/** The parameters for generating images. */\nexport declare interface GenerateImagesParameters {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model: string;\n /** Text prompt that typically describes the images to output.\n */\n prompt: string;\n /** Configuration for generating images.\n */\n config?: GenerateImagesConfig;\n}\n\n/** An image. */\nexport declare interface Image {\n /** The Cloud Storage URI of the image. ``Image`` can contain a value\n for this field or the ``image_bytes`` field but not both. */\n gcsUri?: string;\n /** The image bytes data. ``Image`` can contain a value for this field\n or the ``gcs_uri`` field but not both.\n * @remarks Encoded as base64 string. */\n imageBytes?: string;\n /** The MIME type of the image. */\n mimeType?: string;\n}\n\n/** Safety attributes of a GeneratedImage or the user-provided prompt. */\nexport declare interface SafetyAttributes {\n /** List of RAI categories. */\n categories?: string[];\n /** List of scores of each categories. */\n scores?: number[];\n /** Internal use only. */\n contentType?: string;\n}\n\n/** An output image. */\nexport declare interface GeneratedImage {\n /** The output image data. */\n image?: Image;\n /** Responsible AI filter reason if the image is filtered out of the\n response. */\n raiFilteredReason?: string;\n /** Safety attributes of the image. Lists of RAI categories and their\n scores of each content. */\n safetyAttributes?: SafetyAttributes;\n /** The rewritten prompt used for the image generation if the prompt\n enhancer is enabled. */\n enhancedPrompt?: string;\n}\n\n/** The output images response. */\nexport class GenerateImagesResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** List of generated images. */\n generatedImages?: GeneratedImage[];\n /** Safety attributes of the positive prompt. Only populated if\n ``include_safety_attributes`` is set to True. */\n positivePromptSafetyAttributes?: SafetyAttributes;\n}\n\n/** Configuration for a Mask reference image. */\nexport declare interface MaskReferenceConfig {\n /** Prompts the model to generate a mask instead of you needing to\n provide one (unless MASK_MODE_USER_PROVIDED is used). */\n maskMode?: MaskReferenceMode;\n /** A list of up to 5 class ids to use for semantic segmentation.\n Automatically creates an image mask based on specific objects. */\n segmentationClasses?: number[];\n /** Dilation percentage of the mask provided.\n Float between 0 and 1. */\n maskDilation?: number;\n}\n\n/** Configuration for a Control reference image. */\nexport declare interface ControlReferenceConfig {\n /** The type of control reference image to use. */\n controlType?: ControlReferenceType;\n /** Defaults to False. When set to True, the control image will be\n computed by the model based on the control type. When set to False,\n the control image must be provided by the user. */\n enableControlImageComputation?: boolean;\n}\n\n/** Configuration for a Style reference image. */\nexport declare interface StyleReferenceConfig {\n /** A text description of the style to use for the generated image. */\n styleDescription?: string;\n}\n\n/** Configuration for a Subject reference image. */\nexport declare interface SubjectReferenceConfig {\n /** The subject type of a subject reference image. */\n subjectType?: SubjectReferenceType;\n /** Subject description for the image. */\n subjectDescription?: string;\n}\n\n/** Configuration for editing an image. */\nexport declare interface EditImageConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** Cloud Storage URI used to store the generated images. */\n outputGcsUri?: string;\n /** Description of what to discourage in the generated images. */\n negativePrompt?: string;\n /** Number of images to generate. */\n numberOfImages?: number;\n /** Aspect ratio of the generated images. Supported values are\n \"1:1\", \"3:4\", \"4:3\", \"9:16\", and \"16:9\". */\n aspectRatio?: string;\n /** Controls how much the model adheres to the text prompt. Large\n values increase output and prompt alignment, but may compromise image\n quality. */\n guidanceScale?: number;\n /** Random seed for image generation. This is not available when\n ``add_watermark`` is set to true. */\n seed?: number;\n /** Filter level for safety filtering. */\n safetyFilterLevel?: SafetyFilterLevel;\n /** Allows generation of people by the model. */\n personGeneration?: PersonGeneration;\n /** Whether to report the safety scores of each generated image and\n the positive prompt in the response. */\n includeSafetyAttributes?: boolean;\n /** Whether to include the Responsible AI filter reason if the image\n is filtered out of the response. */\n includeRaiReason?: boolean;\n /** Language of the text in the prompt. */\n language?: ImagePromptLanguage;\n /** MIME type of the generated image. */\n outputMimeType?: string;\n /** Compression quality of the generated image (for ``image/jpeg``\n only). */\n outputCompressionQuality?: number;\n /** Whether to add a watermark to the generated images. */\n addWatermark?: boolean;\n /** User specified labels to track billing usage. */\n labels?: Record<string, string>;\n /** Describes the editing mode for the request. */\n editMode?: EditMode;\n /** The number of sampling steps. A higher value has better image\n quality, while a lower value has better latency. */\n baseSteps?: number;\n}\n\n/** Response for the request to edit an image. */\nexport class EditImageResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** Generated images. */\n generatedImages?: GeneratedImage[];\n}\n\nexport class UpscaleImageResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** Generated images. */\n generatedImages?: GeneratedImage[];\n}\n\n/** An image of the product. */\nexport declare interface ProductImage {\n /** An image of the product to be recontextualized. */\n productImage?: Image;\n}\n\n/** A set of source input(s) for image recontextualization. */\nexport declare interface RecontextImageSource {\n /** A text prompt for guiding the model during image\n recontextualization. Not supported for Virtual Try-On. */\n prompt?: string;\n /** Image of the person or subject who will be wearing the\n product(s). */\n personImage?: Image;\n /** A list of product images. */\n productImages?: ProductImage[];\n}\n\n/** Configuration for recontextualizing an image. */\nexport declare interface RecontextImageConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** Number of images to generate. */\n numberOfImages?: number;\n /** The number of sampling steps. A higher value has better image\n quality, while a lower value has better latency. */\n baseSteps?: number;\n /** Cloud Storage URI used to store the generated images. */\n outputGcsUri?: string;\n /** Random seed for image generation. */\n seed?: number;\n /** Filter level for safety filtering. */\n safetyFilterLevel?: SafetyFilterLevel;\n /** Whether allow to generate person images, and restrict to specific\n ages. */\n personGeneration?: PersonGeneration;\n /** Whether to add a SynthID watermark to the generated images. */\n addWatermark?: boolean;\n /** MIME type of the generated image. */\n outputMimeType?: string;\n /** Compression quality of the generated image (for ``image/jpeg``\n only). */\n outputCompressionQuality?: number;\n /** Whether to use the prompt rewriting logic. */\n enhancePrompt?: boolean;\n /** User specified labels to track billing usage. */\n labels?: Record<string, string>;\n}\n\n/** The parameters for recontextualizing an image. */\nexport declare interface RecontextImageParameters {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model: string;\n /** A set of source input(s) for image recontextualization. */\n source: RecontextImageSource;\n /** Configuration for image recontextualization. */\n config?: RecontextImageConfig;\n}\n\n/** The output images response. */\nexport class RecontextImageResponse {\n /** List of generated images. */\n generatedImages?: GeneratedImage[];\n}\n\n/** An image mask representing a brush scribble. */\nexport declare interface ScribbleImage {\n /** The brush scribble to guide segmentation. Valid for the interactive mode. */\n image?: Image;\n}\n\n/** A set of source input(s) for image segmentation. */\nexport declare interface SegmentImageSource {\n /** A text prompt for guiding the model during image segmentation.\n Required for prompt mode and semantic mode, disallowed for other modes. */\n prompt?: string;\n /** The image to be segmented. */\n image?: Image;\n /** The brush scribble to guide segmentation.\n Required for the interactive mode, disallowed for other modes. */\n scribbleImage?: ScribbleImage;\n}\n\n/** Configuration for segmenting an image. */\nexport declare interface SegmentImageConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** The segmentation mode to use. */\n mode?: SegmentMode;\n /** The maximum number of predictions to return up to, by top\n confidence score. */\n maxPredictions?: number;\n /** The confidence score threshold for the detections as a decimal\n value. Only predictions with a confidence score higher than this\n threshold will be returned. */\n confidenceThreshold?: number;\n /** A decimal value representing how much dilation to apply to the\n masks. 0 for no dilation. 1.0 means the masked area covers the whole\n image. */\n maskDilation?: number;\n /** The binary color threshold to apply to the masks. The threshold\n can be set to a decimal value between 0 and 255 non-inclusive.\n Set to -1 for no binary color thresholding. */\n binaryColorThreshold?: number;\n /** User specified labels to track billing usage. */\n labels?: Record<string, string>;\n}\n\n/** The parameters for segmenting an image. */\nexport declare interface SegmentImageParameters {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model: string;\n /** A set of source input(s) for image segmentation. */\n source: SegmentImageSource;\n /** Configuration for image segmentation. */\n config?: SegmentImageConfig;\n}\n\n/** An entity representing the segmented area. */\nexport declare interface EntityLabel {\n /** The label of the segmented entity. */\n label?: string;\n /** The confidence score of the detected label. */\n score?: number;\n}\n\n/** A generated image mask. */\nexport declare interface GeneratedImageMask {\n /** The generated image mask. */\n mask?: Image;\n /** The detected entities on the segmented area. */\n labels?: EntityLabel[];\n}\n\n/** The output images response. */\nexport class SegmentImageResponse {\n /** List of generated image masks.\n */\n generatedMasks?: GeneratedImageMask[];\n}\n\n/** Optional parameters for models.get method. */\nexport declare interface GetModelConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\nexport declare interface GetModelParameters {\n model: string;\n /** Optional parameters for the request. */\n config?: GetModelConfig;\n}\n\n/** An endpoint where you deploy models. */\nexport declare interface Endpoint {\n /** Resource name of the endpoint. */\n name?: string;\n /** ID of the model that's deployed to the endpoint. */\n deployedModelId?: string;\n}\n\n/** A tuned machine learning model. */\nexport declare interface TunedModelInfo {\n /** ID of the base model that you want to tune. */\n baseModel?: string;\n /** Date and time when the base model was created. */\n createTime?: string;\n /** Date and time when the base model was last updated. */\n updateTime?: string;\n}\n\n/** Describes the machine learning model version checkpoint. */\nexport declare interface Checkpoint {\n /** The ID of the checkpoint.\n */\n checkpointId?: string;\n /** The epoch of the checkpoint.\n */\n epoch?: string;\n /** The step of the checkpoint.\n */\n step?: string;\n}\n\n/** A trained machine learning model. */\nexport declare interface Model {\n /** Resource name of the model. */\n name?: string;\n /** Display name of the model. */\n displayName?: string;\n /** Description of the model. */\n description?: string;\n /** Version ID of the model. A new version is committed when a new\n model version is uploaded or trained under an existing model ID. The\n version ID is an auto-incrementing decimal number in string\n representation. */\n version?: string;\n /** List of deployed models created from this base model. Note that a\n model could have been deployed to endpoints in different locations. */\n endpoints?: Endpoint[];\n /** Labels with user-defined metadata to organize your models. */\n labels?: Record<string, string>;\n /** Information about the tuned model from the base model. */\n tunedModelInfo?: TunedModelInfo;\n /** The maximum number of input tokens that the model can handle. */\n inputTokenLimit?: number;\n /** The maximum number of output tokens that the model can generate. */\n outputTokenLimit?: number;\n /** List of actions that are supported by the model. */\n supportedActions?: string[];\n /** The default checkpoint id of a model version.\n */\n defaultCheckpointId?: string;\n /** The checkpoints of the model. */\n checkpoints?: Checkpoint[];\n /** Temperature value used for sampling set when the dataset was saved.\n This value is used to tune the degree of randomness. */\n temperature?: number;\n /** The maximum temperature value used for sampling set when the\n dataset was saved. This value is used to tune the degree of randomness. */\n maxTemperature?: number;\n /** Optional. Specifies the nucleus sampling threshold. The model\n considers only the smallest set of tokens whose cumulative probability is\n at least `top_p`. This helps generate more diverse and less repetitive\n responses. For example, a `top_p` of 0.9 means the model considers tokens\n until the cumulative probability of the tokens to select from reaches 0.9.\n It's recommended to adjust either temperature or `top_p`, but not both. */\n topP?: number;\n /** Optional. Specifies the top-k sampling threshold. The model\n considers only the top k most probable tokens for the next token. This can\n be useful for generating more coherent and less random text. For example,\n a `top_k` of 40 means the model will choose the next word from the 40 most\n likely words. */\n topK?: number;\n /** Whether the model supports thinking features. If true, thoughts are\n returned only if the model supports thought and thoughts are available. */\n thinking?: boolean;\n}\n\nexport declare interface ListModelsConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n pageSize?: number;\n pageToken?: string;\n filter?: string;\n /** Set true to list base models, false to list tuned models. */\n queryBase?: boolean;\n}\n\nexport declare interface ListModelsParameters {\n config?: ListModelsConfig;\n}\n\nexport class ListModelsResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n nextPageToken?: string;\n models?: Model[];\n}\n\n/** Configuration for updating a tuned model. */\nexport declare interface UpdateModelConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n displayName?: string;\n description?: string;\n defaultCheckpointId?: string;\n}\n\n/** Configuration for updating a tuned model. */\nexport declare interface UpdateModelParameters {\n model: string;\n config?: UpdateModelConfig;\n}\n\n/** Configuration for deleting a tuned model. */\nexport declare interface DeleteModelConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for deleting a tuned model. */\nexport declare interface DeleteModelParameters {\n model: string;\n /** Optional parameters for the request. */\n config?: DeleteModelConfig;\n}\n\nexport class DeleteModelResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n}\n\n/** Generation config. */\nexport declare interface GenerationConfig {\n /** Optional. Config for model selection. */\n modelSelectionConfig?: ModelSelectionConfig;\n /** Output schema of the generated response. This is an alternative to\n `response_schema` that accepts [JSON Schema](https://json-schema.org/).\n */\n responseJsonSchema?: unknown;\n /** Optional. If enabled, audio timestamp will be included in the request to the model. This field is not supported in Gemini API. */\n audioTimestamp?: boolean;\n /** Optional. Number of candidates to generate. */\n candidateCount?: number;\n /** Optional. If enabled, the model will detect emotions and adapt its responses accordingly. This field is not supported in Gemini API. */\n enableAffectiveDialog?: boolean;\n /** Optional. Frequency penalties. */\n frequencyPenalty?: number;\n /** Optional. Logit probabilities. */\n logprobs?: number;\n /** Optional. The maximum number of output tokens to generate per message. */\n maxOutputTokens?: number;\n /** Optional. If specified, the media resolution specified will be used. */\n mediaResolution?: MediaResolution;\n /** Optional. Positive penalties. */\n presencePenalty?: number;\n /** Optional. If true, export the logprobs results in response. */\n responseLogprobs?: boolean;\n /** Optional. Output response mimetype of the generated candidate text. Supported mimetype: - `text/plain`: (default) Text output. - `application/json`: JSON response in the candidates. The model needs to be prompted to output the appropriate response type, otherwise the behavior is undefined. This is a preview feature. */\n responseMimeType?: string;\n /** Optional. The modalities of the response. */\n responseModalities?: Modality[];\n /** Optional. The `Schema` object allows the definition of input and output data types. These types can be objects, but also primitives and arrays. Represents a select subset of an [OpenAPI 3.0 schema object](https://spec.openapis.org/oas/v3.0.3#schema). If set, a compatible response_mime_type must also be set. Compatible mimetypes: `application/json`: Schema for JSON response. */\n responseSchema?: Schema;\n /** Optional. Routing configuration. This field is not supported in Gemini API. */\n routingConfig?: GenerationConfigRoutingConfig;\n /** Optional. Seed. */\n seed?: number;\n /** Optional. The speech generation config. */\n speechConfig?: SpeechConfig;\n /** Optional. Stop sequences. */\n stopSequences?: string[];\n /** Optional. Controls the randomness of predictions. */\n temperature?: number;\n /** Optional. Config for thinking features. An error will be returned if this field is set for models that don't support thinking. */\n thinkingConfig?: ThinkingConfig;\n /** Optional. If specified, top-k sampling will be used. */\n topK?: number;\n /** Optional. If specified, nucleus sampling will be used. */\n topP?: number;\n /** Optional. Enables enhanced civic answers. It may not be available for all models. This field is not supported in Vertex AI. */\n enableEnhancedCivicAnswers?: boolean;\n}\n\n/** Config for the count_tokens method. */\nexport declare interface CountTokensConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** Instructions for the model to steer it toward better performance.\n */\n systemInstruction?: ContentUnion;\n /** Code that enables the system to interact with external systems to\n perform an action outside of the knowledge and scope of the model.\n */\n tools?: Tool[];\n /** Configuration that the model uses to generate the response. Not\n supported by the Gemini Developer API.\n */\n generationConfig?: GenerationConfig;\n}\n\n/** Parameters for counting tokens. */\nexport declare interface CountTokensParameters {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model: string;\n /** Input content. */\n contents: ContentListUnion;\n /** Configuration for counting tokens. */\n config?: CountTokensConfig;\n}\n\n/** Response for counting tokens. */\nexport class CountTokensResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** Total number of tokens. */\n totalTokens?: number;\n /** Number of tokens in the cached part of the prompt (the cached content). */\n cachedContentTokenCount?: number;\n}\n\n/** Optional parameters for computing tokens. */\nexport declare interface ComputeTokensConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for computing tokens. */\nexport declare interface ComputeTokensParameters {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model: string;\n /** Input content. */\n contents: ContentListUnion;\n /** Optional parameters for the request.\n */\n config?: ComputeTokensConfig;\n}\n\n/** Tokens info with a list of tokens and the corresponding list of token ids. */\nexport declare interface TokensInfo {\n /** Optional fields for the role from the corresponding Content. */\n role?: string;\n /** A list of token ids from the input. */\n tokenIds?: string[];\n /** A list of tokens from the input.\n * @remarks Encoded as base64 string. */\n tokens?: string[];\n}\n\n/** Response for computing tokens. */\nexport class ComputeTokensResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** Lists of tokens info from the input. A ComputeTokensRequest could have multiple instances with a prompt in each instance. We also need to return lists of tokens info for the request with multiple instances. */\n tokensInfo?: TokensInfo[];\n}\n\n/** A generated video. */\nexport declare interface Video {\n /** Path to another storage. */\n uri?: string;\n /** Video bytes.\n * @remarks Encoded as base64 string. */\n videoBytes?: string;\n /** Video encoding, for example ``video/mp4``. */\n mimeType?: string;\n}\n\n/** A set of source input(s) for video generation. */\nexport declare interface GenerateVideosSource {\n /** The text prompt for generating the videos.\n Optional if image or video is provided. */\n prompt?: string;\n /** The input image for generating the videos.\n Optional if prompt is provided. Not allowed if video is provided. */\n image?: Image;\n /** The input video for video extension use cases.\n Optional if prompt is provided. Not allowed if image is provided. */\n video?: Video;\n}\n\n/** A reference image for video generation. */\nexport declare interface VideoGenerationReferenceImage {\n /** The reference image. */\n image?: Image;\n /** The type of the reference image, which defines how the reference\n image will be used to generate the video. */\n referenceType?: VideoGenerationReferenceType;\n}\n\n/** A mask for video generation. */\nexport declare interface VideoGenerationMask {\n /** The image mask to use for generating videos. */\n image?: Image;\n /** Describes how the mask will be used. Inpainting masks must\n match the aspect ratio of the input video. Outpainting masks can be\n either 9:16 or 16:9. */\n maskMode?: VideoGenerationMaskMode;\n}\n\n/** Configuration for generating videos. */\nexport declare interface GenerateVideosConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** Number of output videos. */\n numberOfVideos?: number;\n /** The gcs bucket where to save the generated videos. */\n outputGcsUri?: string;\n /** Frames per second for video generation. */\n fps?: number;\n /** Duration of the clip for video generation in seconds. */\n durationSeconds?: number;\n /** The RNG seed. If RNG seed is exactly same for each request with\n unchanged inputs, the prediction results will be consistent. Otherwise,\n a random RNG seed will be used each time to produce a different\n result. */\n seed?: number;\n /** The aspect ratio for the generated video. 16:9 (landscape) and\n 9:16 (portrait) are supported. */\n aspectRatio?: string;\n /** The resolution for the generated video. 720p and 1080p are\n supported. */\n resolution?: string;\n /** Whether allow to generate person videos, and restrict to specific\n ages. Supported values are: dont_allow, allow_adult. */\n personGeneration?: string;\n /** The pubsub topic where to publish the video generation\n progress. */\n pubsubTopic?: string;\n /** Explicitly state what should not be included in the generated\n videos. */\n negativePrompt?: string;\n /** Whether to use the prompt rewriting logic. */\n enhancePrompt?: boolean;\n /** Whether to generate audio along with the video. */\n generateAudio?: boolean;\n /** Image to use as the last frame of generated videos.\n Only supported for image to video use cases. */\n lastFrame?: Image;\n /** The images to use as the references to generate the videos.\n If this field is provided, the text prompt field must also be provided.\n The image, video, or last_frame field are not supported. Each image must\n be associated with a type. Veo 2 supports up to 3 asset images *or* 1\n style image. */\n referenceImages?: VideoGenerationReferenceImage[];\n /** The mask to use for generating videos. */\n mask?: VideoGenerationMask;\n /** Compression quality of the generated videos. */\n compressionQuality?: VideoCompressionQuality;\n}\n\n/** Class that represents the parameters for generating videos. */\nexport declare interface GenerateVideosParameters {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model: string;\n /** The text prompt for generating the videos.\n Optional if image or video is provided. */\n prompt?: string;\n /** The input image for generating the videos.\n Optional if prompt is provided. Not allowed if video is provided. */\n image?: Image;\n /** The input video for video extension use cases.\n Optional if prompt is provided. Not allowed if image is provided. */\n video?: Video;\n /** A set of source input(s) for video generation. */\n source?: GenerateVideosSource;\n /** Configuration for generating videos. */\n config?: GenerateVideosConfig;\n}\n\n/** A generated video. */\nexport declare interface GeneratedVideo {\n /** The output video */\n video?: Video;\n}\n\n/** Response with generated videos. */\nexport class GenerateVideosResponse {\n /** List of the generated videos */\n generatedVideos?: GeneratedVideo[];\n /** Returns if any videos were filtered due to RAI policies. */\n raiMediaFilteredCount?: number;\n /** Returns rai failure reasons if any. */\n raiMediaFilteredReasons?: string[];\n}\n\n/** A long-running operation. */\nexport declare interface Operation<T> {\n /** The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`. */\n name?: string;\n /** Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata. Any method that returns a long-running operation should document the metadata type, if any. */\n metadata?: Record<string, unknown>;\n /** If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available. */\n done?: boolean;\n /** The error result of the operation in case of failure or cancellation. */\n error?: Record<string, unknown>;\n /** The response if the operation is successful. */\n response?: T;\n /**\n * Instantiates an Operation of the same type as the one being called with the fields set from the API response.\n * @internal\n */\n _fromAPIResponse({\n apiResponse,\n _isVertexAI,\n }: OperationFromAPIResponseParameters): Operation<T>;\n}\n\n/** A video generation operation. */\nexport class GenerateVideosOperation\n implements Operation<GenerateVideosResponse>\n{\n /** The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`. */\n name?: string;\n /** Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata. Any method that returns a long-running operation should document the metadata type, if any. */\n metadata?: Record<string, unknown>;\n /** If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available. */\n done?: boolean;\n /** The error result of the operation in case of failure or cancellation. */\n error?: Record<string, unknown>;\n /** The generated videos. */\n response?: GenerateVideosResponse;\n\n /**\n * Instantiates an Operation of the same type as the one being called with the fields set from the API response.\n * @internal\n */\n _fromAPIResponse({\n apiResponse,\n _isVertexAI,\n }: OperationFromAPIResponseParameters): Operation<GenerateVideosResponse> {\n const operation = new GenerateVideosOperation();\n let response;\n const op = apiResponse as unknown as GenerateVideosOperation;\n\n if (_isVertexAI) {\n response = generateVideosOperationFromVertex(op);\n } else {\n response = generateVideosOperationFromMldev(op);\n }\n Object.assign(operation, response);\n return operation;\n }\n /** The full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n}\n\n/** Optional parameters for tunings.get method. */\nexport declare interface GetTuningJobConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for the get method. */\nexport declare interface GetTuningJobParameters {\n name: string;\n /** Optional parameters for the request. */\n config?: GetTuningJobConfig;\n}\n\n/** TunedModelCheckpoint for the Tuned Model of a Tuning Job. */\nexport declare interface TunedModelCheckpoint {\n /** The ID of the checkpoint.\n */\n checkpointId?: string;\n /** The epoch of the checkpoint.\n */\n epoch?: string;\n /** The step of the checkpoint.\n */\n step?: string;\n /** The Endpoint resource name that the checkpoint is deployed to.\n Format: `projects/{project}/locations/{location}/endpoints/{endpoint}`.\n */\n endpoint?: string;\n}\n\n/** TunedModel for the Tuned Model of a Tuning Job. */\nexport declare interface TunedModel {\n /** Output only. The resource name of the TunedModel.\n Format: `projects/{project}/locations/{location}/models/{model}@{version_id}`\n When tuning from a base model, the version_id will be 1.\n For continuous tuning, the version id will be incremented by 1 from the\n last version id in the parent model. E.g., `projects/{project}/locations/{location}/models/{model}@{last_version_id + 1}`\n */\n model?: string;\n /** Output only. A resource name of an Endpoint.\n Format: `projects/{project}/locations/{location}/endpoints/{endpoint}`.\n */\n endpoint?: string;\n /** The checkpoints associated with this TunedModel.\n This field is only populated for tuning jobs that enable intermediate\n checkpoints. */\n checkpoints?: TunedModelCheckpoint[];\n}\n\n/** Hyperparameters for SFT. This data type is not supported in Gemini API. */\nexport declare interface SupervisedHyperParameters {\n /** Optional. Adapter size for tuning. */\n adapterSize?: AdapterSize;\n /** Optional. Batch size for tuning. This feature is only available for open source models. */\n batchSize?: string;\n /** Optional. Number of complete passes the model makes over the entire training dataset during training. */\n epochCount?: string;\n /** Optional. Learning rate for tuning. Mutually exclusive with `learning_rate_multiplier`. This feature is only available for open source models. */\n learningRate?: number;\n /** Optional. Multiplier for adjusting the default learning rate. Mutually exclusive with `learning_rate`. This feature is only available for 1P models. */\n learningRateMultiplier?: number;\n}\n\n/** Supervised tuning spec for tuning. */\nexport declare interface SupervisedTuningSpec {\n /** Optional. If set to true, disable intermediate checkpoints for SFT and only the last checkpoint will be exported. Otherwise, enable intermediate checkpoints for SFT. Default is false. */\n exportLastCheckpointOnly?: boolean;\n /** Optional. Hyperparameters for SFT. */\n hyperParameters?: SupervisedHyperParameters;\n /** Required. Training dataset used for tuning. The dataset can be specified as either a Cloud Storage path to a JSONL file or as the resource name of a Vertex Multimodal Dataset. */\n trainingDatasetUri?: string;\n /** Tuning mode. */\n tuningMode?: TuningMode;\n /** Optional. Validation dataset used for tuning. The dataset can be specified as either a Cloud Storage path to a JSONL file or as the resource name of a Vertex Multimodal Dataset. */\n validationDatasetUri?: string;\n}\n\n/** Hyperparameters for Preference Optimization. This data type is not supported in Gemini API. */\nexport declare interface PreferenceOptimizationHyperParameters {\n /** Optional. Adapter size for preference optimization. */\n adapterSize?: AdapterSize;\n /** Optional. Weight for KL Divergence regularization. */\n beta?: number;\n /** Optional. Number of complete passes the model makes over the entire training dataset during training. */\n epochCount?: string;\n /** Optional. Multiplier for adjusting the default learning rate. */\n learningRateMultiplier?: number;\n}\n\n/** Preference optimization tuning spec for tuning. */\nexport declare interface PreferenceOptimizationSpec {\n /** Optional. If set to true, disable intermediate checkpoints for Preference Optimization and only the last checkpoint will be exported. Otherwise, enable intermediate checkpoints for Preference Optimization. Default is false. */\n exportLastCheckpointOnly?: boolean;\n /** Optional. Hyperparameters for Preference Optimization. */\n hyperParameters?: PreferenceOptimizationHyperParameters;\n /** Required. Cloud Storage path to file containing training dataset for preference optimization tuning. The dataset must be formatted as a JSONL file. */\n trainingDatasetUri?: string;\n /** Optional. Cloud Storage path to file containing validation dataset for preference optimization tuning. The dataset must be formatted as a JSONL file. */\n validationDatasetUri?: string;\n}\n\n/** Hyperparameters for Distillation. This data type is not supported in Gemini API. */\nexport declare interface DistillationHyperParameters {\n /** Optional. Adapter size for distillation. */\n adapterSize?: AdapterSize;\n /** Optional. Number of complete passes the model makes over the entire training dataset during training. */\n epochCount?: string;\n /** Optional. Multiplier for adjusting the default learning rate. */\n learningRateMultiplier?: number;\n}\n\n/** Distillation tuning spec for tuning. */\nexport declare interface DistillationSpec {\n /** The GCS URI of the prompt dataset to use during distillation. */\n promptDatasetUri?: string;\n /** The base teacher model that is being distilled. See [Supported models](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/tuning#supported_models). */\n baseTeacherModel?: string;\n /** Optional. Hyperparameters for Distillation. */\n hyperParameters?: DistillationHyperParameters;\n /** Deprecated. A path in a Cloud Storage bucket, which will be treated as the root output directory of the distillation pipeline. It is used by the system to generate the paths of output artifacts. */\n pipelineRootDirectory?: string;\n /** The student model that is being tuned, e.g., \"google/gemma-2b-1.1-it\". Deprecated. Use base_model instead. */\n studentModel?: string;\n /** Deprecated. Cloud Storage path to file containing training dataset for tuning. The dataset must be formatted as a JSONL file. */\n trainingDatasetUri?: string;\n /** The resource name of the Tuned teacher model. Format: `projects/{project}/locations/{location}/models/{model}`. */\n tunedTeacherModelSource?: string;\n /** Optional. Cloud Storage path to file containing validation dataset for tuning. The dataset must be formatted as a JSONL file. */\n validationDatasetUri?: string;\n}\n\n/** The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors). This data type is not supported in Gemini API. */\nexport declare interface GoogleRpcStatus {\n /** The status code, which should be an enum value of google.rpc.Code. */\n code?: number;\n /** A list of messages that carry the error details. There is a common set of message types for APIs to use. */\n details?: Record<string, unknown>[];\n /** A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the google.rpc.Status.details field, or localized by the client. */\n message?: string;\n}\n\n/** A pre-tuned model for continuous tuning. This data type is not supported in Gemini API. */\nexport declare interface PreTunedModel {\n /** Output only. The name of the base model this PreTunedModel was tuned from. */\n baseModel?: string;\n /** Optional. The source checkpoint id. If not specified, the default checkpoint will be used. */\n checkpointId?: string;\n /** The resource name of the Model. E.g., a model resource name with a specified version id or alias: `projects/{project}/locations/{location}/models/{model}@{version_id}` `projects/{project}/locations/{location}/models/{model}@{alias}` Or, omit the version id to use the default version: `projects/{project}/locations/{location}/models/{model}` */\n tunedModelName?: string;\n}\n\n/** Dataset bucket used to create a histogram for the distribution given a population of values. This data type is not supported in Gemini API. */\nexport declare interface DatasetDistributionDistributionBucket {\n /** Output only. Number of values in the bucket. */\n count?: string;\n /** Output only. Left bound of the bucket. */\n left?: number;\n /** Output only. Right bound of the bucket. */\n right?: number;\n}\n\n/** Distribution computed over a tuning dataset. This data type is not supported in Gemini API. */\nexport declare interface DatasetDistribution {\n /** Output only. Defines the histogram bucket. */\n buckets?: DatasetDistributionDistributionBucket[];\n /** Output only. The maximum of the population values. */\n max?: number;\n /** Output only. The arithmetic mean of the values in the population. */\n mean?: number;\n /** Output only. The median of the values in the population. */\n median?: number;\n /** Output only. The minimum of the population values. */\n min?: number;\n /** Output only. The 5th percentile of the values in the population. */\n p5?: number;\n /** Output only. The 95th percentile of the values in the population. */\n p95?: number;\n /** Output only. Sum of a given population of values. */\n sum?: number;\n}\n\n/** Statistics computed over a tuning dataset. This data type is not supported in Gemini API. */\nexport declare interface DatasetStats {\n /** Output only. Number of billable characters in the tuning dataset. */\n totalBillableCharacterCount?: string;\n /** Output only. Number of tuning characters in the tuning dataset. */\n totalTuningCharacterCount?: string;\n /** Output only. Number of examples in the tuning dataset. */\n tuningDatasetExampleCount?: string;\n /** Output only. Number of tuning steps for this Tuning Job. */\n tuningStepCount?: string;\n /** Output only. Sample user messages in the training dataset uri. */\n userDatasetExamples?: Content[];\n /** Output only. Dataset distributions for the user input tokens. */\n userInputTokenDistribution?: DatasetDistribution;\n /** Output only. Dataset distributions for the messages per example. */\n userMessagePerExampleDistribution?: DatasetDistribution;\n /** Output only. Dataset distributions for the user output tokens. */\n userOutputTokenDistribution?: DatasetDistribution;\n}\n\n/** Statistics computed for datasets used for distillation. This data type is not supported in Gemini API. */\nexport declare interface DistillationDataStats {\n /** Output only. Statistics computed for the training dataset. */\n trainingDatasetStats?: DatasetStats;\n}\n\n/** Completion and its preference score. This data type is not supported in Gemini API. */\nexport declare interface GeminiPreferenceExampleCompletion {\n /** Single turn completion for the given prompt. */\n completion?: Content;\n /** The score for the given completion. */\n score?: number;\n}\n\n/** Input example for preference optimization. This data type is not supported in Gemini API. */\nexport declare interface GeminiPreferenceExample {\n /** List of completions for a given prompt. */\n completions?: GeminiPreferenceExampleCompletion[];\n /** Multi-turn contents that represents the Prompt. */\n contents?: Content[];\n}\n\n/** Statistics computed for datasets used for preference optimization. This data type is not supported in Gemini API. */\nexport declare interface PreferenceOptimizationDataStats {\n /** Output only. Dataset distributions for scores variance per example. */\n scoreVariancePerExampleDistribution?: DatasetDistribution;\n /** Output only. Dataset distributions for scores. */\n scoresDistribution?: DatasetDistribution;\n /** Output only. Number of billable tokens in the tuning dataset. */\n totalBillableTokenCount?: string;\n /** Output only. Number of examples in the tuning dataset. */\n tuningDatasetExampleCount?: string;\n /** Output only. Number of tuning steps for this Tuning Job. */\n tuningStepCount?: string;\n /** Output only. Sample user examples in the training dataset. */\n userDatasetExamples?: GeminiPreferenceExample[];\n /** Output only. Dataset distributions for the user input tokens. */\n userInputTokenDistribution?: DatasetDistribution;\n /** Output only. Dataset distributions for the user output tokens. */\n userOutputTokenDistribution?: DatasetDistribution;\n}\n\n/** Dataset bucket used to create a histogram for the distribution given a population of values. This data type is not supported in Gemini API. */\nexport declare interface SupervisedTuningDatasetDistributionDatasetBucket {\n /** Output only. Number of values in the bucket. */\n count?: number;\n /** Output only. Left bound of the bucket. */\n left?: number;\n /** Output only. Right bound of the bucket. */\n right?: number;\n}\n\n/** Dataset distribution for Supervised Tuning. This data type is not supported in Gemini API. */\nexport declare interface SupervisedTuningDatasetDistribution {\n /** Output only. Sum of a given population of values that are billable. */\n billableSum?: string;\n /** Output only. Defines the histogram bucket. */\n buckets?: SupervisedTuningDatasetDistributionDatasetBucket[];\n /** Output only. The maximum of the population values. */\n max?: number;\n /** Output only. The arithmetic mean of the values in the population. */\n mean?: number;\n /** Output only. The median of the values in the population. */\n median?: number;\n /** Output only. The minimum of the population values. */\n min?: number;\n /** Output only. The 5th percentile of the values in the population. */\n p5?: number;\n /** Output only. The 95th percentile of the values in the population. */\n p95?: number;\n /** Output only. Sum of a given population of values. */\n sum?: string;\n}\n\n/** Tuning data statistics for Supervised Tuning. This data type is not supported in Gemini API. */\nexport declare interface SupervisedTuningDataStats {\n /** Output only. For each index in `truncated_example_indices`, the user-facing reason why the example was dropped. */\n droppedExampleReasons?: string[];\n /** Output only. Number of billable characters in the tuning dataset. */\n totalBillableCharacterCount?: string;\n /** Output only. Number of billable tokens in the tuning dataset. */\n totalBillableTokenCount?: string;\n /** Output only. The number of examples in the dataset that have been dropped. An example can be dropped for reasons including: too many tokens, contains an invalid image, contains too many images, etc. */\n totalTruncatedExampleCount?: string;\n /** Output only. Number of tuning characters in the tuning dataset. */\n totalTuningCharacterCount?: string;\n /** Output only. A partial sample of the indices (starting from 1) of the dropped examples. */\n truncatedExampleIndices?: string[];\n /** Output only. Number of examples in the tuning dataset. */\n tuningDatasetExampleCount?: string;\n /** Output only. Number of tuning steps for this Tuning Job. */\n tuningStepCount?: string;\n /** Output only. Sample user messages in the training dataset uri. */\n userDatasetExamples?: Content[];\n /** Output only. Dataset distributions for the user input tokens. */\n userInputTokenDistribution?: SupervisedTuningDatasetDistribution;\n /** Output only. Dataset distributions for the messages per example. */\n userMessagePerExampleDistribution?: SupervisedTuningDatasetDistribution;\n /** Output only. Dataset distributions for the user output tokens. */\n userOutputTokenDistribution?: SupervisedTuningDatasetDistribution;\n}\n\n/** The tuning data statistic values for TuningJob. This data type is not supported in Gemini API. */\nexport declare interface TuningDataStats {\n /** Output only. Statistics for distillation. */\n distillationDataStats?: DistillationDataStats;\n /** Output only. Statistics for preference optimization. */\n preferenceOptimizationDataStats?: PreferenceOptimizationDataStats;\n /** The SFT Tuning data stats. */\n supervisedTuningDataStats?: SupervisedTuningDataStats;\n}\n\n/** Represents a customer-managed encryption key spec that can be applied to a top-level resource. This data type is not supported in Gemini API. */\nexport declare interface EncryptionSpec {\n /** Required. The Cloud KMS resource identifier of the customer managed encryption key used to protect a resource. Has the form: `projects/my-project/locations/my-region/keyRings/my-kr/cryptoKeys/my-key`. The key needs to be in the same region as where the compute resource is created. */\n kmsKeyName?: string;\n}\n\n/** Tuning spec for Partner models. This data type is not supported in Gemini API. */\nexport declare interface PartnerModelTuningSpec {\n /** Hyperparameters for tuning. The accepted hyper_parameters and their valid range of values will differ depending on the base model. */\n hyperParameters?: Record<string, unknown>;\n /** Required. Cloud Storage path to file containing training dataset for tuning. The dataset must be formatted as a JSONL file. */\n trainingDatasetUri?: string;\n /** Optional. Cloud Storage path to file containing validation dataset for tuning. The dataset must be formatted as a JSONL file. */\n validationDatasetUri?: string;\n}\n\n/** Hyperparameters for Veo. This data type is not supported in Gemini API. */\nexport declare interface VeoHyperParameters {\n /** Optional. Number of complete passes the model makes over the entire training dataset during training. */\n epochCount?: string;\n /** Optional. Multiplier for adjusting the default learning rate. */\n learningRateMultiplier?: number;\n /** Optional. The tuning task. Either I2V or T2V. */\n tuningTask?: TuningTask;\n}\n\n/** Tuning Spec for Veo Model Tuning. This data type is not supported in Gemini API. */\nexport declare interface VeoTuningSpec {\n /** Optional. Hyperparameters for Veo. */\n hyperParameters?: VeoHyperParameters;\n /** Required. Training dataset used for tuning. The dataset can be specified as either a Cloud Storage path to a JSONL file or as the resource name of a Vertex Multimodal Dataset. */\n trainingDatasetUri?: string;\n /** Optional. Validation dataset used for tuning. The dataset can be specified as either a Cloud Storage path to a JSONL file or as the resource name of a Vertex Multimodal Dataset. */\n validationDatasetUri?: string;\n}\n\n/** A tuning job. */\nexport declare interface TuningJob {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** Output only. Identifier. Resource name of a TuningJob. Format: `projects/{project}/locations/{location}/tuningJobs/{tuning_job}` */\n name?: string;\n /** Output only. The detailed state of the job. */\n state?: JobState;\n /** Output only. Time when the TuningJob was created. */\n createTime?: string;\n /** Output only. Time when the TuningJob for the first time entered the `JOB_STATE_RUNNING` state. */\n startTime?: string;\n /** Output only. Time when the TuningJob entered any of the following JobStates: `JOB_STATE_SUCCEEDED`, `JOB_STATE_FAILED`, `JOB_STATE_CANCELLED`, `JOB_STATE_EXPIRED`. */\n endTime?: string;\n /** Output only. Time when the TuningJob was most recently updated. */\n updateTime?: string;\n /** Output only. Only populated when job's state is `JOB_STATE_FAILED` or `JOB_STATE_CANCELLED`. */\n error?: GoogleRpcStatus;\n /** Optional. The description of the TuningJob. */\n description?: string;\n /** The base model that is being tuned. See [Supported models](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/tuning#supported_models). */\n baseModel?: string;\n /** Output only. The tuned model resources associated with this TuningJob. */\n tunedModel?: TunedModel;\n /** The pre-tuned model for continuous tuning. */\n preTunedModel?: PreTunedModel;\n /** Tuning Spec for Supervised Fine Tuning. */\n supervisedTuningSpec?: SupervisedTuningSpec;\n /** Tuning Spec for Preference Optimization. */\n preferenceOptimizationSpec?: PreferenceOptimizationSpec;\n /** Tuning Spec for Distillation. */\n distillationSpec?: DistillationSpec;\n /** Output only. The tuning data statistics associated with this TuningJob. */\n tuningDataStats?: TuningDataStats;\n /** Customer-managed encryption key options for a TuningJob. If this is set, then all resources created by the TuningJob will be encrypted with the provided encryption key. */\n encryptionSpec?: EncryptionSpec;\n /** Tuning Spec for open sourced and third party Partner models. */\n partnerModelTuningSpec?: PartnerModelTuningSpec;\n /** Optional. The user-provided path to custom model weights. Set this field to tune a custom model. The path must be a Cloud Storage directory that contains the model weights in .safetensors format along with associated model metadata files. If this field is set, the base_model field must still be set to indicate which base model the custom model is derived from. This feature is only available for open source models. */\n customBaseModel?: string;\n /** Output only. The Experiment associated with this TuningJob. */\n experiment?: string;\n /** Optional. The labels with user-defined metadata to organize TuningJob and generated resources such as Model and Endpoint. Label keys and values can be no longer than 64 characters (Unicode codepoints), can only contain lowercase letters, numeric characters, underscores and dashes. International characters are allowed. See https://goo.gl/xmQnxf for more information and examples of labels. */\n labels?: Record<string, string>;\n /** Optional. Cloud Storage path to the directory where tuning job outputs are written to. This field is only available and required for open source models. */\n outputUri?: string;\n /** Output only. The resource name of the PipelineJob associated with the TuningJob. Format: `projects/{project}/locations/{location}/pipelineJobs/{pipeline_job}`. */\n pipelineJob?: string;\n /** The service account that the tuningJob workload runs as. If not specified, the Vertex AI Secure Fine-Tuned Service Agent in the project will be used. See https://cloud.google.com/iam/docs/service-agents#vertex-ai-secure-fine-tuning-service-agent Users starting the pipeline must have the `iam.serviceAccounts.actAs` permission on this service account. */\n serviceAccount?: string;\n /** Optional. The display name of the TunedModel. The name can be up to 128 characters long and can consist of any UTF-8 characters. For continuous tuning, tuned_model_display_name will by default use the same display name as the pre-tuned model. If a new display name is provided, the tuning job will create a new model instead of a new version. */\n tunedModelDisplayName?: string;\n /** Tuning Spec for Veo Tuning. */\n veoTuningSpec?: VeoTuningSpec;\n}\n\n/** Configuration for the list tuning jobs method. */\nexport declare interface ListTuningJobsConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n pageSize?: number;\n pageToken?: string;\n filter?: string;\n}\n\n/** Parameters for the list tuning jobs method. */\nexport declare interface ListTuningJobsParameters {\n config?: ListTuningJobsConfig;\n}\n\n/** Response for the list tuning jobs method. */\nexport class ListTuningJobsResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** A token to retrieve the next page of results. Pass to ListTuningJobsRequest.page_token to obtain that page. */\n nextPageToken?: string;\n /** List of TuningJobs in the requested page. */\n tuningJobs?: TuningJob[];\n}\n\n/** Optional parameters for tunings.cancel method. */\nexport declare interface CancelTuningJobConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for the cancel method. */\nexport declare interface CancelTuningJobParameters {\n /** The resource name of the tuning job. */\n name: string;\n /** Optional parameters for the request. */\n config?: CancelTuningJobConfig;\n}\n\n/** Empty response for tunings.cancel method. */\nexport class CancelTuningJobResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n}\n\n/** A single example for tuning. This data type is not supported in Vertex AI. */\nexport declare interface TuningExample {\n /** Required. The expected model output. */\n output?: string;\n /** Optional. Text model input. */\n textInput?: string;\n}\n\n/** Supervised fine-tuning training dataset. */\nexport declare interface TuningDataset {\n /** GCS URI of the file containing training dataset in JSONL format. */\n gcsUri?: string;\n /** The resource name of the Vertex Multimodal Dataset that is used as training dataset. Example: 'projects/my-project-id-or-number/locations/my-location/datasets/my-dataset-id'. */\n vertexDatasetResource?: string;\n /** Inline examples with simple input/output text. */\n examples?: TuningExample[];\n}\n\nexport declare interface TuningValidationDataset {\n /** GCS URI of the file containing validation dataset in JSONL format. */\n gcsUri?: string;\n /** The resource name of the Vertex Multimodal Dataset that is used as validation dataset. Example: 'projects/my-project-id-or-number/locations/my-location/datasets/my-dataset-id'. */\n vertexDatasetResource?: string;\n}\n\n/** Fine-tuning job creation request - optional fields. */\nexport declare interface CreateTuningJobConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** The method to use for tuning (SUPERVISED_FINE_TUNING or PREFERENCE_TUNING or DISTILLATION). If not set, the default method (SFT) will be used. */\n method?: TuningMethod;\n /** Validation dataset for tuning. The dataset must be formatted as a JSONL file. */\n validationDataset?: TuningValidationDataset;\n /** The display name of the tuned Model. The name can be up to 128 characters long and can consist of any UTF-8 characters. */\n tunedModelDisplayName?: string;\n /** The description of the TuningJob */\n description?: string;\n /** Number of complete passes the model makes over the entire training dataset during training. */\n epochCount?: number;\n /** Multiplier for adjusting the default learning rate. 1P models only. Mutually exclusive with learning_rate. */\n learningRateMultiplier?: number;\n /** If set to true, disable intermediate checkpoints and only the last checkpoint will be exported. Otherwise, enable intermediate checkpoints. */\n exportLastCheckpointOnly?: boolean;\n /** The optional checkpoint id of the pre-tuned model to use for tuning, if applicable. */\n preTunedModelCheckpointId?: string;\n /** Adapter size for tuning. */\n adapterSize?: AdapterSize;\n /** Tuning mode for SFT tuning. */\n tuningMode?: TuningMode;\n /** Custom base model for tuning. This is only supported for OSS models in Vertex. */\n customBaseModel?: string;\n /** The batch size hyperparameter for tuning. This is only supported for OSS models in Vertex. */\n batchSize?: number;\n /** The learning rate for tuning. OSS models only. Mutually exclusive with learning_rate_multiplier. */\n learningRate?: number;\n /** Optional. The labels with user-defined metadata to organize TuningJob and generated resources such as Model and Endpoint. Label keys and values can be no longer than 64 characters (Unicode codepoints), can only contain lowercase letters, numeric characters, underscores and dashes. International characters are allowed. See https://goo.gl/xmQnxf for more information and examples of labels. */\n labels?: Record<string, string>;\n /** Weight for KL Divergence regularization, Preference Optimization tuning only. */\n beta?: number;\n /** The base teacher model that is being distilled. Distillation only. */\n baseTeacherModel?: string;\n /** The resource name of the Tuned teacher model. Distillation only. */\n tunedTeacherModelSource?: string;\n /** Multiplier for adjusting the weight of the SFT loss. Distillation only. */\n sftLossWeightMultiplier?: number;\n /** The Google Cloud Storage location where the tuning job outputs are written. */\n outputUri?: string;\n /** The encryption spec of the tuning job. Customer-managed encryption key options for a TuningJob. If this is set, then all resources created by the TuningJob will be encrypted with provided encryption key. */\n encryptionSpec?: EncryptionSpec;\n}\n\n/** Fine-tuning job creation parameters - optional fields. */\nexport declare interface CreateTuningJobParametersPrivate {\n /** The base model that is being tuned, e.g., \"gemini-2.5-flash\". */\n baseModel?: string;\n /** The PreTunedModel that is being tuned. */\n preTunedModel?: PreTunedModel;\n /** Cloud Storage path to file containing training dataset for tuning. The dataset must be formatted as a JSONL file. */\n trainingDataset: TuningDataset;\n /** Configuration for the tuning job. */\n config?: CreateTuningJobConfig;\n}\n\n/** A long-running operation. */\nexport declare interface TuningOperation {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`. */\n name?: string;\n /** Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata. Any method that returns a long-running operation should document the metadata type, if any. */\n metadata?: Record<string, unknown>;\n /** If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available. */\n done?: boolean;\n /** The error result of the operation in case of failure or cancellation. */\n error?: Record<string, unknown>;\n}\n\n/** Optional configuration for cached content creation. */\nexport declare interface CreateCachedContentConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** The TTL for this resource. The expiration time is computed: now + TTL. It is a duration string, with up to nine fractional digits, terminated by 's'. Example: \"3.5s\". */\n ttl?: string;\n /** Timestamp of when this resource is considered expired. Uses RFC 3339 format, Example: 2014-10-02T15:01:23Z. */\n expireTime?: string;\n /** The user-generated meaningful display name of the cached content.\n */\n displayName?: string;\n /** The content to cache.\n */\n contents?: ContentListUnion;\n /** Developer set system instruction.\n */\n systemInstruction?: ContentUnion;\n /** A list of `Tools` the model may use to generate the next response.\n */\n tools?: Tool[];\n /** Configuration for the tools to use. This config is shared for all tools.\n */\n toolConfig?: ToolConfig;\n /** The Cloud KMS resource identifier of the customer managed\n encryption key used to protect a resource.\n The key needs to be in the same region as where the compute resource is\n created. See\n https://cloud.google.com/vertex-ai/docs/general/cmek for more\n details. If this is set, then all created CachedContent objects\n will be encrypted with the provided encryption key.\n Allowed formats: projects/{project}/locations/{location}/keyRings/{key_ring}/cryptoKeys/{crypto_key}\n */\n kmsKeyName?: string;\n}\n\n/** Parameters for caches.create method. */\nexport declare interface CreateCachedContentParameters {\n /** ID of the model to use. Example: gemini-2.0-flash */\n model: string;\n /** Configuration that contains optional parameters.\n */\n config?: CreateCachedContentConfig;\n}\n\n/** Metadata on the usage of the cached content. */\nexport declare interface CachedContentUsageMetadata {\n /** Duration of audio in seconds. This field is not supported in Gemini API. */\n audioDurationSeconds?: number;\n /** Number of images. This field is not supported in Gemini API. */\n imageCount?: number;\n /** Number of text characters. This field is not supported in Gemini API. */\n textCount?: number;\n /** Total number of tokens that the cached content consumes. */\n totalTokenCount?: number;\n /** Duration of video in seconds. This field is not supported in Gemini API. */\n videoDurationSeconds?: number;\n}\n\n/** A resource used in LLM queries for users to explicitly specify what to cache. */\nexport declare interface CachedContent {\n /** The server-generated resource name of the cached content. */\n name?: string;\n /** The user-generated meaningful display name of the cached content. */\n displayName?: string;\n /** The name of the publisher model to use for cached content. */\n model?: string;\n /** Creation time of the cache entry. */\n createTime?: string;\n /** When the cache entry was last updated in UTC time. */\n updateTime?: string;\n /** Expiration time of the cached content. */\n expireTime?: string;\n /** Metadata on the usage of the cached content. */\n usageMetadata?: CachedContentUsageMetadata;\n}\n\n/** Optional parameters for caches.get method. */\nexport declare interface GetCachedContentConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for caches.get method. */\nexport declare interface GetCachedContentParameters {\n /** The server-generated resource name of the cached content.\n */\n name: string;\n /** Optional parameters for the request.\n */\n config?: GetCachedContentConfig;\n}\n\n/** Optional parameters for caches.delete method. */\nexport declare interface DeleteCachedContentConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for caches.delete method. */\nexport declare interface DeleteCachedContentParameters {\n /** The server-generated resource name of the cached content.\n */\n name: string;\n /** Optional parameters for the request.\n */\n config?: DeleteCachedContentConfig;\n}\n\n/** Empty response for caches.delete method. */\nexport class DeleteCachedContentResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n}\n\n/** Optional parameters for caches.update method. */\nexport declare interface UpdateCachedContentConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** The TTL for this resource. The expiration time is computed: now + TTL. It is a duration string, with up to nine fractional digits, terminated by 's'. Example: \"3.5s\". */\n ttl?: string;\n /** Timestamp of when this resource is considered expired. Uses RFC 3339 format, Example: 2014-10-02T15:01:23Z. */\n expireTime?: string;\n}\n\nexport declare interface UpdateCachedContentParameters {\n /** The server-generated resource name of the cached content.\n */\n name: string;\n /** Configuration that contains optional parameters.\n */\n config?: UpdateCachedContentConfig;\n}\n\n/** Config for caches.list method. */\nexport declare interface ListCachedContentsConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n pageSize?: number;\n pageToken?: string;\n}\n\n/** Parameters for caches.list method. */\nexport declare interface ListCachedContentsParameters {\n /** Configuration that contains optional parameters.\n */\n config?: ListCachedContentsConfig;\n}\n\nexport class ListCachedContentsResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n nextPageToken?: string;\n /** List of cached contents.\n */\n cachedContents?: CachedContent[];\n}\n\n/** Optional Config. */\nexport declare interface GetDocumentConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for documents.get. */\nexport declare interface GetDocumentParameters {\n /** The resource name of the Document.\n Example: fileSearchStores/file-search-store-foo/documents/documents-bar */\n name: string;\n /** Optional parameters for the request. */\n config?: GetDocumentConfig;\n}\n\n/** User provided string values assigned to a single metadata key. This data type is not supported in Vertex AI. */\nexport declare interface StringList {\n /** The string values of the metadata to store. */\n values?: string[];\n}\n\n/** User provided metadata stored as key-value pairs. This data type is not supported in Vertex AI. */\nexport declare interface CustomMetadata {\n /** Required. The key of the metadata to store. */\n key?: string;\n /** The numeric value of the metadata to store. */\n numericValue?: number;\n /** The StringList value of the metadata to store. */\n stringListValue?: StringList;\n /** The string value of the metadata to store. */\n stringValue?: string;\n}\n\n/** A Document is a collection of Chunks. */\nexport declare interface Document {\n /** The resource name of the Document.\n Example: fileSearchStores/file-search-store-foo/documents/documents-bar */\n name?: string;\n /** The human-readable display name for the Document. */\n displayName?: string;\n /** The current state of the Document. */\n state?: DocumentState;\n /** The size of the Document in bytes. */\n sizeBytes?: string;\n /** The MIME type of the Document. */\n mimeType?: string;\n /** Output only. The Timestamp of when the `Document` was created. */\n createTime?: string;\n /** Optional. User provided custom metadata stored as key-value pairs used for querying. A `Document` can have a maximum of 20 `CustomMetadata`. */\n customMetadata?: CustomMetadata[];\n /** Output only. The Timestamp of when the `Document` was last updated. */\n updateTime?: string;\n}\n\n/** Config for optional parameters. */\nexport declare interface DeleteDocumentConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** If set to true, any `Chunk`s and objects related to this `Document` will\n also be deleted.\n */\n force?: boolean;\n}\n\n/** Config for documents.delete parameters. */\nexport declare interface DeleteDocumentParameters {\n /** The resource name of the Document.\n Example: fileSearchStores/file-search-store-foo/documents/documents-bar */\n name: string;\n /** Optional parameters for the request. */\n config?: DeleteDocumentConfig;\n}\n\n/** Config for optional parameters. */\nexport declare interface ListDocumentsConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n pageSize?: number;\n pageToken?: string;\n}\n\n/** Config for documents.list parameters. */\nexport declare interface ListDocumentsParameters {\n /** The resource name of the FileSearchStores. Example: `fileSearchStore/file-search-store-foo` */\n parent: string;\n config?: ListDocumentsConfig;\n}\n\n/** Config for documents.list return value. */\nexport class ListDocumentsResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** A token, which can be sent as `page_token` to retrieve the next page. If this field is omitted, there are no more pages. */\n nextPageToken?: string;\n /** The returned `Document`s. */\n documents?: Document[];\n}\n\n/** Optional parameters for creating a file search store. */\nexport declare interface CreateFileSearchStoreConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** The human-readable display name for the file search store.\n */\n displayName?: string;\n}\n\n/** Config for file_search_stores.create parameters. */\nexport declare interface CreateFileSearchStoreParameters {\n /** Optional parameters for creating a file search store.\n */\n config?: CreateFileSearchStoreConfig;\n}\n\n/** A collection of Documents. */\nexport declare interface FileSearchStore {\n /** The resource name of the FileSearchStore. Example: `fileSearchStores/my-file-search-store-123` */\n name?: string;\n /** The human-readable display name for the FileSearchStore. */\n displayName?: string;\n /** The Timestamp of when the FileSearchStore was created. */\n createTime?: string;\n /** The Timestamp of when the FileSearchStore was last updated. */\n updateTime?: string;\n /** The number of documents in the FileSearchStore that are active and ready for retrieval. */\n activeDocumentsCount?: string;\n /** The number of documents in the FileSearchStore that are being processed. */\n pendingDocumentsCount?: string;\n /** The number of documents in the FileSearchStore that have failed processing. */\n failedDocumentsCount?: string;\n /** The size of raw bytes ingested into the FileSearchStore. This is the\n total size of all the documents in the FileSearchStore. */\n sizeBytes?: string;\n}\n\n/** Optional parameters for getting a FileSearchStore. */\nexport declare interface GetFileSearchStoreConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Config for file_search_stores.get parameters. */\nexport declare interface GetFileSearchStoreParameters {\n /** The resource name of the FileSearchStore. Example: `fileSearchStores/my-file-search-store-123` */\n name: string;\n /** Optional parameters for the request. */\n config?: GetFileSearchStoreConfig;\n}\n\n/** Optional parameters for deleting a FileSearchStore. */\nexport declare interface DeleteFileSearchStoreConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** If set to true, any Documents and objects related to this FileSearchStore will also be deleted.\n If false (the default), a FAILED_PRECONDITION error will be returned if\n the FileSearchStore contains any Documents.\n */\n force?: boolean;\n}\n\n/** Config for file_search_stores.delete parameters. */\nexport declare interface DeleteFileSearchStoreParameters {\n /** The resource name of the FileSearchStore. Example: `fileSearchStores/my-file-search-store-123` */\n name: string;\n /** Optional parameters for the request. */\n config?: DeleteFileSearchStoreConfig;\n}\n\n/** Optional parameters for listing FileSearchStore. */\nexport declare interface ListFileSearchStoresConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n pageSize?: number;\n pageToken?: string;\n}\n\n/** Config for file_search_stores.list parameters. */\nexport declare interface ListFileSearchStoresParameters {\n /** Optional parameters for the list request. */\n config?: ListFileSearchStoresConfig;\n}\n\n/** Config for file_search_stores.list return value. */\nexport class ListFileSearchStoresResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n nextPageToken?: string;\n /** The returned file search stores. */\n fileSearchStores?: FileSearchStore[];\n}\n\n/** Configuration for a white space chunking algorithm. */\nexport declare interface WhiteSpaceConfig {\n /** Maximum number of tokens per chunk. */\n maxTokensPerChunk?: number;\n /** Maximum number of overlapping tokens between two adjacent chunks. */\n maxOverlapTokens?: number;\n}\n\n/** Config for telling the service how to chunk the file. */\nexport declare interface ChunkingConfig {\n /** White space chunking configuration. */\n whiteSpaceConfig?: WhiteSpaceConfig;\n}\n\n/** Optional parameters for uploading a file to a FileSearchStore. */\nexport declare interface UploadToFileSearchStoreConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** MIME type of the file to be uploaded. If not provided, it will be inferred from the file extension. */\n mimeType?: string;\n /** Display name of the created document. */\n displayName?: string;\n /** User provided custom metadata stored as key-value pairs used for querying. */\n customMetadata?: CustomMetadata[];\n /** Config for telling the service how to chunk the file. */\n chunkingConfig?: ChunkingConfig;\n}\n\n/** Generates the parameters for the private _upload_to_file_search_store method. */\nexport declare interface UploadToFileSearchStoreParameters {\n /** The resource name of the FileSearchStore. Example: `fileSearchStores/my-file-search-store-123` */\n fileSearchStoreName: string;\n /** Used to override the default configuration. */\n config?: UploadToFileSearchStoreConfig;\n}\n\n/** Response for the resumable upload method. */\nexport class UploadToFileSearchStoreResumableResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n}\n\n/** Optional parameters for importing a file. */\nexport declare interface ImportFileConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** User provided custom metadata stored as key-value pairs used for querying. */\n customMetadata?: CustomMetadata[];\n /** Config for telling the service how to chunk the file. */\n chunkingConfig?: ChunkingConfig;\n}\n\n/** Config for file_search_stores.import_file parameters. */\nexport declare interface ImportFileParameters {\n /** The resource name of the FileSearchStore. Example: `fileSearchStores/my-file-search-store-123` */\n fileSearchStoreName: string;\n /** The name of the File API File to import. Example: `files/abc-123` */\n fileName: string;\n /** Optional parameters for the request. */\n config?: ImportFileConfig;\n}\n\n/** Response for ImportFile to import a File API file with a file search store. */\nexport class ImportFileResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** The name of the FileSearchStore containing Documents. */\n parent?: string;\n /** The identifier for the Document imported. */\n documentName?: string;\n}\n\n/** Long-running operation for importing a file to a FileSearchStore. */\nexport class ImportFileOperation implements Operation<ImportFileResponse> {\n /** The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`. */\n name?: string;\n /** Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata. Any method that returns a long-running operation should document the metadata type, if any. */\n metadata?: Record<string, unknown>;\n /** If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available. */\n done?: boolean;\n /** The error result of the operation in case of failure or cancellation. */\n error?: Record<string, unknown>;\n /** The result of the ImportFile operation, available when the operation is done. */\n response?: ImportFileResponse;\n\n /**\n * Instantiates an Operation of the same type as the one being called with the fields set from the API response.\n * @internal\n */\n _fromAPIResponse({\n apiResponse,\n _isVertexAI,\n }: OperationFromAPIResponseParameters): Operation<ImportFileResponse> {\n const operation = new ImportFileOperation();\n\n const op = apiResponse as unknown as ImportFileOperation;\n const response = importFileOperationFromMldev(op);\n Object.assign(operation, response);\n return operation;\n }\n /** The full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n}\n\nexport /** Used to override the default configuration. */\ndeclare interface ListFilesConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n pageSize?: number;\n pageToken?: string;\n}\n\n/** Generates the parameters for the list method. */\nexport declare interface ListFilesParameters {\n /** Used to override the default configuration. */\n config?: ListFilesConfig;\n}\n\n/** Status of a File that uses a common error model. */\nexport declare interface FileStatus {\n /** A list of messages that carry the error details. There is a common set of message types for APIs to use. */\n details?: Record<string, unknown>[];\n /** A list of messages that carry the error details. There is a common set of message types for APIs to use. */\n message?: string;\n /** The status code. 0 for OK, 1 for CANCELLED */\n code?: number;\n}\n\n/** A file uploaded to the API. */\nexport declare interface File {\n /** The `File` resource name. The ID (name excluding the \"files/\" prefix) can contain up to 40 characters that are lowercase alphanumeric or dashes (-). The ID cannot start or end with a dash. If the name is empty on create, a unique name will be generated. Example: `files/123-456` */\n name?: string;\n /** Optional. The human-readable display name for the `File`. The display name must be no more than 512 characters in length, including spaces. Example: 'Welcome Image' */\n displayName?: string;\n /** Output only. MIME type of the file. */\n mimeType?: string;\n /** Output only. Size of the file in bytes. */\n sizeBytes?: string;\n /** Output only. The timestamp of when the `File` was created. */\n createTime?: string;\n /** Output only. The timestamp of when the `File` will be deleted. Only set if the `File` is scheduled to expire. */\n expirationTime?: string;\n /** Output only. The timestamp of when the `File` was last updated. */\n updateTime?: string;\n /** Output only. SHA-256 hash of the uploaded bytes. The hash value is encoded in base64 format. */\n sha256Hash?: string;\n /** Output only. The URI of the `File`. */\n uri?: string;\n /** Output only. The URI of the `File`, only set for downloadable (generated) files. */\n downloadUri?: string;\n /** Output only. Processing state of the File. */\n state?: FileState;\n /** Output only. The source of the `File`. */\n source?: FileSource;\n /** Output only. Metadata for a video. */\n videoMetadata?: Record<string, unknown>;\n /** Output only. Error status if File processing failed. */\n error?: FileStatus;\n}\n\n/** Response for the list files method. */\nexport class ListFilesResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** A token that can be sent as a `page_token` into a subsequent `ListFiles` call. */\n nextPageToken?: string;\n /** The list of `File`s. */\n files?: File[];\n}\n\n/** Used to override the default configuration. */\nexport declare interface CreateFileConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Generates the parameters for the private _create method. */\nexport declare interface CreateFileParameters {\n /** The file to be uploaded.\n mime_type: (Required) The MIME type of the file. Must be provided.\n name: (Optional) The name of the file in the destination (e.g.\n 'files/sample-image').\n display_name: (Optional) The display name of the file.\n */\n file: File;\n /** Used to override the default configuration. */\n config?: CreateFileConfig;\n}\n\n/** Response for the create file method. */\nexport class CreateFileResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n}\n\n/** Used to override the default configuration. */\nexport declare interface GetFileConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Generates the parameters for the get method. */\nexport declare interface GetFileParameters {\n /** The name identifier for the file to retrieve. */\n name: string;\n /** Used to override the default configuration. */\n config?: GetFileConfig;\n}\n\n/** Used to override the default configuration. */\nexport declare interface DeleteFileConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Generates the parameters for the get method. */\nexport declare interface DeleteFileParameters {\n /** The name identifier for the file to be deleted. */\n name: string;\n /** Used to override the default configuration. */\n config?: DeleteFileConfig;\n}\n\n/** Response for the delete file method. */\nexport class DeleteFileResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n}\n\n/** Used to override the default configuration. */\nexport declare interface RegisterFilesConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for the private _Register method. */\nexport declare interface InternalRegisterFilesParameters {\n /** The Google Cloud Storage URIs to register. Example: `gs://bucket/object`. */\n uris: string[];\n /** Used to override the default configuration. */\n config?: RegisterFilesConfig;\n}\n\n/** Response for the _register file method. */\nexport class RegisterFilesResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** The registered files. */\n files?: File[];\n}\n\n/** Config for inlined request. */\nexport declare interface InlinedRequest {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model?: string;\n /** Content of the request.\n */\n contents?: ContentListUnion;\n /** The metadata to be associated with the request. */\n metadata?: Record<string, string>;\n /** Configuration that contains optional model parameters.\n */\n config?: GenerateContentConfig;\n}\n\n/** Config for `src` parameter. */\nexport declare interface BatchJobSource {\n /** Storage format of the input files. Must be one of:\n 'jsonl', 'bigquery'.\n */\n format?: string;\n /** The Google Cloud Storage URIs to input files.\n */\n gcsUri?: string[];\n /** The BigQuery URI to input table.\n */\n bigqueryUri?: string;\n /** The Gemini Developer API's file resource name of the input data\n (e.g. \"files/12345\").\n */\n fileName?: string;\n /** The Gemini Developer API's inlined input data to run batch job.\n */\n inlinedRequests?: InlinedRequest[];\n}\n\n/** Job error. */\nexport declare interface JobError {\n /** A list of messages that carry the error details. There is a common set of message types for APIs to use. */\n details?: string[];\n /** The status code. */\n code?: number;\n /** A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the `details` field. */\n message?: string;\n}\n\n/** Config for `inlined_responses` parameter. */\nexport class InlinedResponse {\n /** The response to the request.\n */\n response?: GenerateContentResponse;\n /** The metadata to be associated with the request. */\n metadata?: Record<string, string>;\n /** The error encountered while processing the request.\n */\n error?: JobError;\n}\n\n/** Config for `response` parameter. */\nexport class SingleEmbedContentResponse {\n /** The response to the request.\n */\n embedding?: ContentEmbedding;\n /** The error encountered while processing the request.\n */\n tokenCount?: string;\n}\n\n/** Config for `inlined_embedding_responses` parameter. */\nexport class InlinedEmbedContentResponse {\n /** The response to the request.\n */\n response?: SingleEmbedContentResponse;\n /** The error encountered while processing the request.\n */\n error?: JobError;\n}\n\n/** Config for `des` parameter. */\nexport declare interface BatchJobDestination {\n /** Storage format of the output files. Must be one of:\n 'jsonl', 'bigquery'.\n */\n format?: string;\n /** The Google Cloud Storage URI to the output file.\n */\n gcsUri?: string;\n /** The BigQuery URI to the output table.\n */\n bigqueryUri?: string;\n /** The Gemini Developer API's file resource name of the output data\n (e.g. \"files/12345\"). The file will be a JSONL file with a single response\n per line. The responses will be GenerateContentResponse messages formatted\n as JSON. The responses will be written in the same order as the input\n requests.\n */\n fileName?: string;\n /** The responses to the requests in the batch. Returned when the batch was\n built using inlined requests. The responses will be in the same order as\n the input requests.\n */\n inlinedResponses?: InlinedResponse[];\n /** The responses to the requests in the batch. Returned when the batch was\n built using inlined requests. The responses will be in the same order as\n the input requests.\n */\n inlinedEmbedContentResponses?: InlinedEmbedContentResponse[];\n}\n\n/** Config for optional parameters. */\nexport declare interface CreateBatchJobConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** The user-defined name of this BatchJob.\n */\n displayName?: string;\n /** GCS or BigQuery URI prefix for the output predictions. Example:\n \"gs://path/to/output/data\" or \"bq://projectId.bqDatasetId.bqTableId\".\n */\n dest?: BatchJobDestinationUnion;\n}\n\n/** Config for batches.create parameters. */\nexport declare interface CreateBatchJobParameters {\n /** The name of the model to produces the predictions via the BatchJob.\n */\n model?: string;\n /** GCS URI(-s) or BigQuery URI to your input data to run batch job.\n Example: \"gs://path/to/input/data\" or \"bq://projectId.bqDatasetId.bqTableId\".\n */\n src: BatchJobSourceUnion;\n /** Optional parameters for creating a BatchJob.\n */\n config?: CreateBatchJobConfig;\n}\n\n/** Success and error statistics of processing multiple entities (for example, DataItems or structured data rows) in batch. This data type is not supported in Gemini API. */\nexport declare interface CompletionStats {\n /** Output only. The number of entities for which any error was encountered. */\n failedCount?: string;\n /** Output only. In cases when enough errors are encountered a job, pipeline, or operation may be failed as a whole. Below is the number of entities for which the processing had not been finished (either in successful or failed state). Set to -1 if the number is unknown (for example, the operation failed before the total entity number could be collected). */\n incompleteCount?: string;\n /** Output only. The number of entities that had been processed successfully. */\n successfulCount?: string;\n /** Output only. The number of the successful forecast points that are generated by the forecasting model. This is ONLY used by the forecasting batch prediction. */\n successfulForecastPointCount?: string;\n}\n\n/** Config for batches.create return value. */\nexport declare interface BatchJob {\n /** The resource name of the BatchJob. Output only.\".\n */\n name?: string;\n /** The display name of the BatchJob.\n */\n displayName?: string;\n /** The state of the BatchJob.\n */\n state?: JobState;\n /** Output only. Only populated when the job's state is JOB_STATE_FAILED or JOB_STATE_CANCELLED. */\n error?: JobError;\n /** The time when the BatchJob was created.\n */\n createTime?: string;\n /** Output only. Time when the Job for the first time entered the `JOB_STATE_RUNNING` state. */\n startTime?: string;\n /** The time when the BatchJob was completed. This field is for Vertex AI only.\n */\n endTime?: string;\n /** The time when the BatchJob was last updated.\n */\n updateTime?: string;\n /** The name of the model that produces the predictions via the BatchJob.\n */\n model?: string;\n /** Configuration for the input data. This field is for Vertex AI only.\n */\n src?: BatchJobSource;\n /** Configuration for the output data.\n */\n dest?: BatchJobDestination;\n /** Statistics on completed and failed prediction instances. This field is for Vertex AI only.\n */\n completionStats?: CompletionStats;\n}\n\n/** Parameters for the embed_content method. */\nexport declare interface EmbedContentBatch {\n /** The content to embed. Only the `parts.text` fields will be counted.\n */\n contents?: ContentListUnion;\n /** Configuration that contains optional parameters.\n */\n config?: EmbedContentConfig;\n}\n\nexport declare interface EmbeddingsBatchJobSource {\n /** The Gemini Developer API's file resource name of the input data\n (e.g. \"files/12345\").\n */\n fileName?: string;\n /** The Gemini Developer API's inlined input data to run batch job.\n */\n inlinedRequests?: EmbedContentBatch;\n}\n\n/** Config for optional parameters. */\nexport declare interface CreateEmbeddingsBatchJobConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** The user-defined name of this BatchJob.\n */\n displayName?: string;\n}\n\n/** Config for batches.create parameters. */\nexport declare interface CreateEmbeddingsBatchJobParameters {\n /** The name of the model to produces the predictions via the BatchJob.\n */\n model?: string;\n /** input data to run batch job\".\n */\n src: EmbeddingsBatchJobSource;\n /** Optional parameters for creating a BatchJob.\n */\n config?: CreateEmbeddingsBatchJobConfig;\n}\n\n/** Optional parameters. */\nexport declare interface GetBatchJobConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Config for batches.get parameters. */\nexport declare interface GetBatchJobParameters {\n /** A fully-qualified BatchJob resource name or ID.\n Example: \"projects/.../locations/.../batchPredictionJobs/456\"\n or \"456\" when project and location are initialized in the client.\n */\n name: string;\n /** Optional parameters for the request. */\n config?: GetBatchJobConfig;\n}\n\n/** Optional parameters. */\nexport declare interface CancelBatchJobConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Config for batches.cancel parameters. */\nexport declare interface CancelBatchJobParameters {\n /** A fully-qualified BatchJob resource name or ID.\n Example: \"projects/.../locations/.../batchPredictionJobs/456\"\n or \"456\" when project and location are initialized in the client.\n */\n name: string;\n /** Optional parameters for the request. */\n config?: CancelBatchJobConfig;\n}\n\n/** Config for optional parameters. */\nexport declare interface ListBatchJobsConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n pageSize?: number;\n pageToken?: string;\n filter?: string;\n}\n\n/** Config for batches.list parameters. */\nexport declare interface ListBatchJobsParameters {\n config?: ListBatchJobsConfig;\n}\n\n/** Config for batches.list return value. */\nexport class ListBatchJobsResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n nextPageToken?: string;\n batchJobs?: BatchJob[];\n}\n\n/** Optional parameters for models.get method. */\nexport declare interface DeleteBatchJobConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Config for batches.delete parameters. */\nexport declare interface DeleteBatchJobParameters {\n /** A fully-qualified BatchJob resource name or ID.\n Example: \"projects/.../locations/.../batchPredictionJobs/456\"\n or \"456\" when project and location are initialized in the client.\n */\n name: string;\n /** Optional parameters for the request. */\n config?: DeleteBatchJobConfig;\n}\n\n/** The return value of delete operation. */\nexport declare interface DeleteResourceJob {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n name?: string;\n done?: boolean;\n error?: JobError;\n}\n\nexport declare interface GetOperationConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for the GET method. */\nexport declare interface GetOperationParameters {\n /** The server-assigned name for the operation. */\n operationName: string;\n /** Used to override the default configuration. */\n config?: GetOperationConfig;\n}\n\nexport declare interface FetchPredictOperationConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for the fetchPredictOperation method. */\nexport declare interface FetchPredictOperationParameters {\n /** The server-assigned name for the operation. */\n operationName: string;\n resourceName: string;\n /** Used to override the default configuration. */\n config?: FetchPredictOperationConfig;\n}\n\nexport declare interface TestTableItem {\n /** The name of the test. This is used to derive the replay id. */\n name?: string;\n /** The parameters to the test. Use pydantic models. */\n parameters?: Record<string, unknown>;\n /** Expects an exception for MLDev matching the string. */\n exceptionIfMldev?: string;\n /** Expects an exception for Vertex matching the string. */\n exceptionIfVertex?: string;\n /** Use if you don't want to use the default replay id which is derived from the test name. */\n overrideReplayId?: string;\n /** True if the parameters contain an unsupported union type. This test will be skipped for languages that do not support the union type. */\n hasUnion?: boolean;\n /** When set to a reason string, this test will be skipped in the API mode. Use this flag for tests that can not be reproduced with the real API. E.g. a test that deletes a resource. */\n skipInApiMode?: string;\n /** Keys to ignore when comparing the request and response. This is useful for tests that are not deterministic. */\n ignoreKeys?: string[];\n}\n\nexport declare interface TestTableFile {\n comment?: string;\n testMethod?: string;\n parameterNames?: string[];\n testTable?: TestTableItem[];\n}\n\n/** Represents a single request in a replay. */\nexport declare interface ReplayRequest {\n method?: string;\n url?: string;\n headers?: Record<string, string>;\n bodySegments?: Record<string, unknown>[];\n}\n\n/** Represents a single response in a replay. */\nexport class ReplayResponse {\n statusCode?: number;\n headers?: Record<string, string>;\n bodySegments?: Record<string, unknown>[];\n sdkResponseSegments?: Record<string, unknown>[];\n}\n\n/** Represents a single interaction, request and response in a replay. */\nexport declare interface ReplayInteraction {\n request?: ReplayRequest;\n response?: ReplayResponse;\n}\n\n/** Represents a recorded session. */\nexport declare interface ReplayFile {\n replayId?: string;\n interactions?: ReplayInteraction[];\n}\n\n/** Used to override the default configuration. */\nexport declare interface UploadFileConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** The name of the file in the destination (e.g., 'files/sample-image'. If not provided one will be generated. */\n name?: string;\n /** mime_type: The MIME type of the file. If not provided, it will be inferred from the file extension. */\n mimeType?: string;\n /** Optional display name of the file. */\n displayName?: string;\n}\n\n/** Used to override the default configuration. */\nexport declare interface DownloadFileConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters used to download a file. */\nexport declare interface DownloadFileParameters {\n /** The file to download. It can be a file name, a file object or a generated video. */\n file: DownloadableFileUnion;\n /** Location where the file should be downloaded to. */\n downloadPath: string;\n /** Configuration to for the download operation. */\n config?: DownloadFileConfig;\n}\n\n/** Configuration for upscaling an image.\n\nFor more information on this configuration, refer to\nthe `Imagen API reference documentation\n<https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/imagen-api>`_. */\nexport declare interface UpscaleImageConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** Cloud Storage URI used to store the generated images. */\n outputGcsUri?: string;\n /** Filter level for safety filtering. */\n safetyFilterLevel?: SafetyFilterLevel;\n /** Allows generation of people by the model. */\n personGeneration?: PersonGeneration;\n /** Whether to include a reason for filtered-out images in the\n response. */\n includeRaiReason?: boolean;\n /** The image format that the output should be saved as. */\n outputMimeType?: string;\n /** The level of compression. Only applicable if the\n ``output_mime_type`` is ``image/jpeg``. */\n outputCompressionQuality?: number;\n /** Whether to add an image enhancing step before upscaling.\n It is expected to suppress the noise and JPEG compression artifacts\n from the input image. */\n enhanceInputImage?: boolean;\n /** With a higher image preservation factor, the original image\n pixels are more respected. With a lower image preservation factor, the\n output image will have be more different from the input image, but\n with finer details and less noise. */\n imagePreservationFactor?: number;\n /** User specified labels to track billing usage. */\n labels?: Record<string, string>;\n}\n\n/** User-facing config UpscaleImageParameters. */\nexport declare interface UpscaleImageParameters {\n /** The model to use. */\n model: string;\n /** The input image to upscale. */\n image: Image;\n /** The factor to upscale the image (x2 or x4). */\n upscaleFactor: string;\n /** Configuration for upscaling. */\n config?: UpscaleImageConfig;\n}\n\n/** A raw reference image.\n\nA raw reference image represents the base image to edit, provided by the user.\nIt can optionally be provided in addition to a mask reference image or\na style reference image. */\nexport class RawReferenceImage {\n /** The reference image for the editing operation. */\n referenceImage?: Image;\n /** The id of the reference image. */\n referenceId?: number;\n /** The type of the reference image. Only set by the SDK. */\n referenceType?: string;\n /** Internal method to convert to ReferenceImageAPIInternal. */\n toReferenceImageAPI(): ReferenceImageAPIInternal {\n const referenceImageAPI = {\n referenceType: 'REFERENCE_TYPE_RAW',\n referenceImage: this.referenceImage,\n referenceId: this.referenceId,\n };\n return referenceImageAPI;\n }\n}\n\n/** A mask reference image.\n\nThis encapsulates either a mask image provided by the user and configs for\nthe user provided mask, or only config parameters for the model to generate\na mask.\n\nA mask image is an image whose non-zero values indicate where to edit the base\nimage. If the user provides a mask image, the mask must be in the same\ndimensions as the raw image. */\nexport class MaskReferenceImage {\n /** The reference image for the editing operation. */\n referenceImage?: Image;\n /** The id of the reference image. */\n referenceId?: number;\n /** The type of the reference image. Only set by the SDK. */\n referenceType?: string;\n /** Configuration for the mask reference image. */\n config?: MaskReferenceConfig;\n /** Internal method to convert to ReferenceImageAPIInternal. */\n toReferenceImageAPI(): ReferenceImageAPIInternal {\n const referenceImageAPI = {\n referenceType: 'REFERENCE_TYPE_MASK',\n referenceImage: this.referenceImage,\n referenceId: this.referenceId,\n maskImageConfig: this.config,\n };\n return referenceImageAPI;\n }\n}\n\n/** A control reference image.\n\nThe image of the control reference image is either a control image provided\nby the user, or a regular image which the backend will use to generate a\ncontrol image of. In the case of the latter, the\nenable_control_image_computation field in the config should be set to True.\n\nA control image is an image that represents a sketch image of areas for the\nmodel to fill in based on the prompt. */\nexport class ControlReferenceImage {\n /** The reference image for the editing operation. */\n referenceImage?: Image;\n /** The id of the reference image. */\n referenceId?: number;\n /** The type of the reference image. Only set by the SDK. */\n referenceType?: string;\n /** Configuration for the control reference image. */\n config?: ControlReferenceConfig;\n /** Internal method to convert to ReferenceImageAPIInternal. */\n toReferenceImageAPI(): ReferenceImageAPIInternal {\n const referenceImageAPI = {\n referenceType: 'REFERENCE_TYPE_CONTROL',\n referenceImage: this.referenceImage,\n referenceId: this.referenceId,\n controlImageConfig: this.config,\n };\n return referenceImageAPI;\n }\n}\n\n/** A style reference image.\n\nThis encapsulates a style reference image provided by the user, and\nadditionally optional config parameters for the style reference image.\n\nA raw reference image can also be provided as a destination for the style to\nbe applied to. */\nexport class StyleReferenceImage {\n /** The reference image for the editing operation. */\n referenceImage?: Image;\n /** The id of the reference image. */\n referenceId?: number;\n /** The type of the reference image. Only set by the SDK. */\n referenceType?: string;\n /** Configuration for the style reference image. */\n config?: StyleReferenceConfig;\n /** Internal method to convert to ReferenceImageAPIInternal. */\n toReferenceImageAPI(): ReferenceImageAPIInternal {\n const referenceImageAPI = {\n referenceType: 'REFERENCE_TYPE_STYLE',\n referenceImage: this.referenceImage,\n referenceId: this.referenceId,\n styleImageConfig: this.config,\n };\n return referenceImageAPI;\n }\n}\n\n/** A subject reference image.\n\nThis encapsulates a subject reference image provided by the user, and\nadditionally optional config parameters for the subject reference image.\n\nA raw reference image can also be provided as a destination for the subject to\nbe applied to. */\nexport class SubjectReferenceImage {\n /** The reference image for the editing operation. */\n referenceImage?: Image;\n /** The id of the reference image. */\n referenceId?: number;\n /** The type of the reference image. Only set by the SDK. */\n referenceType?: string;\n /** Configuration for the subject reference image. */\n config?: SubjectReferenceConfig;\n /* Internal method to convert to ReferenceImageAPIInternal. */\n toReferenceImageAPI(): ReferenceImageAPIInternal {\n const referenceImageAPI = {\n referenceType: 'REFERENCE_TYPE_SUBJECT',\n referenceImage: this.referenceImage,\n referenceId: this.referenceId,\n subjectImageConfig: this.config,\n };\n return referenceImageAPI;\n }\n}\n\n/** A content reference image.\n\nA content reference image represents a subject to reference (ex. person,\nproduct, animal) provided by the user. It can optionally be provided in\naddition to a style reference image (ex. background, style reference). */\nexport class ContentReferenceImage {\n /** The reference image for the editing operation. */\n referenceImage?: Image;\n /** The id of the reference image. */\n referenceId?: number;\n /** The type of the reference image. Only set by the SDK. */\n referenceType?: string;\n /** Internal method to convert to ReferenceImageAPIInternal. */\n toReferenceImageAPI(): ReferenceImageAPIInternal {\n const referenceImageAPI = {\n referenceType: 'REFERENCE_TYPE_CONTENT',\n referenceImage: this.referenceImage,\n referenceId: this.referenceId,\n };\n return referenceImageAPI;\n }\n}\n\n/** Sent in response to a `LiveGenerateContentSetup` message from the client. */\nexport declare interface LiveServerSetupComplete {\n /** The session id of the live session. */\n sessionId?: string;\n}\n\n/** Audio transcription in Server Conent. */\nexport declare interface Transcription {\n /** Transcription text.\n */\n text?: string;\n /** The bool indicates the end of the transcription.\n */\n finished?: boolean;\n}\n\n/** Incremental server update generated by the model in response to client messages.\n\nContent is generated as quickly as possible, and not in real time. Clients\nmay choose to buffer and play it out in real time. */\nexport declare interface LiveServerContent {\n /** The content that the model has generated as part of the current conversation with the user. */\n modelTurn?: Content;\n /** If true, indicates that the model is done generating. Generation will only start in response to additional client messages. Can be set alongside `content`, indicating that the `content` is the last in the turn. */\n turnComplete?: boolean;\n /** If true, indicates that a client message has interrupted current model generation. If the client is playing out the content in realtime, this is a good signal to stop and empty the current queue. */\n interrupted?: boolean;\n /** Metadata returned to client when grounding is enabled. */\n groundingMetadata?: GroundingMetadata;\n /** If true, indicates that the model is done generating. When model is\n interrupted while generating there will be no generation_complete message\n in interrupted turn, it will go through interrupted > turn_complete.\n When model assumes realtime playback there will be delay between\n generation_complete and turn_complete that is caused by model\n waiting for playback to finish. If true, indicates that the model\n has finished generating all content. This is a signal to the client\n that it can stop sending messages. */\n generationComplete?: boolean;\n /** Input transcription. The transcription is independent to the model\n turn which means it doesn’t imply any ordering between transcription and\n model turn. */\n inputTranscription?: Transcription;\n /** Output transcription. The transcription is independent to the model\n turn which means it doesn’t imply any ordering between transcription and\n model turn.\n */\n outputTranscription?: Transcription;\n /** Metadata related to url context retrieval tool. */\n urlContextMetadata?: UrlContextMetadata;\n /** Reason for the turn is complete. */\n turnCompleteReason?: TurnCompleteReason;\n /** If true, indicates that the model is not generating content because\n it is waiting for more input from the user, e.g. because it expects the\n user to continue talking. */\n waitingForInput?: boolean;\n}\n\n/** Request for the client to execute the `function_calls` and return the responses with the matching `id`s. */\nexport declare interface LiveServerToolCall {\n /** The function call to be executed. */\n functionCalls?: FunctionCall[];\n}\n\n/** Notification for the client that a previously issued `ToolCallMessage` with the specified `id`s should have been not executed and should be cancelled.\n\nIf there were side-effects to those tool calls, clients may attempt to undo\nthe tool calls. This message occurs only in cases where the clients interrupt\nserver turns. */\nexport declare interface LiveServerToolCallCancellation {\n /** The ids of the tool calls to be cancelled. */\n ids?: string[];\n}\n\n/** Usage metadata about response(s). */\nexport declare interface UsageMetadata {\n /** Number of tokens in the prompt. When `cached_content` is set, this is still the total effective prompt size meaning this includes the number of tokens in the cached content. */\n promptTokenCount?: number;\n /** Number of tokens in the cached part of the prompt (the cached content). */\n cachedContentTokenCount?: number;\n /** Total number of tokens across all the generated response candidates. */\n responseTokenCount?: number;\n /** Number of tokens present in tool-use prompt(s). */\n toolUsePromptTokenCount?: number;\n /** Number of tokens of thoughts for thinking models. */\n thoughtsTokenCount?: number;\n /** Total token count for prompt, response candidates, and tool-use prompts(if present). */\n totalTokenCount?: number;\n /** List of modalities that were processed in the request input. */\n promptTokensDetails?: ModalityTokenCount[];\n /** List of modalities that were processed in the cache input. */\n cacheTokensDetails?: ModalityTokenCount[];\n /** List of modalities that were returned in the response. */\n responseTokensDetails?: ModalityTokenCount[];\n /** List of modalities that were processed in the tool-use prompt. */\n toolUsePromptTokensDetails?: ModalityTokenCount[];\n /** Traffic type. This shows whether a request consumes Pay-As-You-Go\n or Provisioned Throughput quota. */\n trafficType?: TrafficType;\n}\n\n/** Server will not be able to service client soon. */\nexport declare interface LiveServerGoAway {\n /** The remaining time before the connection will be terminated as ABORTED. The minimal time returned here is specified differently together with the rate limits for a given model. */\n timeLeft?: string;\n}\n\n/** Update of the session resumption state.\n\nOnly sent if `session_resumption` was set in the connection config. */\nexport declare interface LiveServerSessionResumptionUpdate {\n /** New handle that represents state that can be resumed. Empty if `resumable`=false. */\n newHandle?: string;\n /** True if session can be resumed at this point. It might be not possible to resume session at some points. In that case we send update empty new_handle and resumable=false. Example of such case could be model executing function calls or just generating. Resuming session (using previous session token) in such state will result in some data loss. */\n resumable?: boolean;\n /** Index of last message sent by client that is included in state represented by this SessionResumptionToken. Only sent when `SessionResumptionConfig.transparent` is set.\n\nPresence of this index allows users to transparently reconnect and avoid issue of losing some part of realtime audio input/video. If client wishes to temporarily disconnect (for example as result of receiving GoAway) they can do it without losing state by buffering messages sent since last `SessionResmumptionTokenUpdate`. This field will enable them to limit buffering (avoid keeping all requests in RAM).\n\nNote: This should not be used for when resuming a session at some time later -- in those cases partial audio and video frames arelikely not needed. */\n lastConsumedClientMessageIndex?: string;\n}\n\nexport declare interface VoiceActivityDetectionSignal {\n /** The type of the VAD signal. */\n vadSignalType?: VadSignalType;\n}\n\n/** Voice activity signal. */\nexport declare interface VoiceActivity {\n /** The type of the voice activity signal. */\n voiceActivityType?: VoiceActivityType;\n}\n\n/** Response message for API call. */\nexport class LiveServerMessage {\n /** Sent in response to a `LiveClientSetup` message from the client. */\n setupComplete?: LiveServerSetupComplete;\n /** Content generated by the model in response to client messages. */\n serverContent?: LiveServerContent;\n /** Request for the client to execute the `function_calls` and return the responses with the matching `id`s. */\n toolCall?: LiveServerToolCall;\n /** Notification for the client that a previously issued `ToolCallMessage` with the specified `id`s should have been not executed and should be cancelled. */\n toolCallCancellation?: LiveServerToolCallCancellation;\n /** Usage metadata about model response(s). */\n usageMetadata?: UsageMetadata;\n /** Server will disconnect soon. */\n goAway?: LiveServerGoAway;\n /** Update of the session resumption state. */\n sessionResumptionUpdate?: LiveServerSessionResumptionUpdate;\n /** Voice activity detection signal. Allowlisted only. */\n voiceActivityDetectionSignal?: VoiceActivityDetectionSignal;\n /** Voice activity signal. */\n voiceActivity?: VoiceActivity;\n /**\n * Returns the concatenation of all text parts from the server content if present.\n *\n * @remarks\n * If there are non-text parts in the response, the concatenation of all text\n * parts will be returned, and a warning will be logged.\n */\n get text(): string | undefined {\n let text = '';\n let anyTextPartFound = false;\n const nonTextParts = [];\n for (const part of this.serverContent?.modelTurn?.parts ?? []) {\n for (const [fieldName, fieldValue] of Object.entries(part)) {\n if (\n fieldName !== 'text' &&\n fieldName !== 'thought' &&\n fieldValue !== null\n ) {\n nonTextParts.push(fieldName);\n }\n }\n if (typeof part.text === 'string') {\n if (typeof part.thought === 'boolean' && part.thought) {\n continue;\n }\n anyTextPartFound = true;\n text += part.text;\n }\n }\n if (nonTextParts.length > 0) {\n console.warn(\n `there are non-text parts ${nonTextParts} in the response, returning concatenation of all text parts. Please refer to the non text parts for a full response from model.`,\n );\n }\n // part.text === '' is different from part.text is null\n return anyTextPartFound ? text : undefined;\n }\n\n /**\n * Returns the concatenation of all inline data parts from the server content if present.\n *\n * @remarks\n * If there are non-inline data parts in the\n * response, the concatenation of all inline data parts will be returned, and\n * a warning will be logged.\n */\n get data(): string | undefined {\n let data = '';\n const nonDataParts = [];\n for (const part of this.serverContent?.modelTurn?.parts ?? []) {\n for (const [fieldName, fieldValue] of Object.entries(part)) {\n if (fieldName !== 'inlineData' && fieldValue !== null) {\n nonDataParts.push(fieldName);\n }\n }\n if (part.inlineData && typeof part.inlineData.data === 'string') {\n data += atob(part.inlineData.data);\n }\n }\n if (nonDataParts.length > 0) {\n console.warn(\n `there are non-data parts ${nonDataParts} in the response, returning concatenation of all data parts. Please refer to the non data parts for a full response from model.`,\n );\n }\n return data.length > 0 ? btoa(data) : undefined;\n }\n}\n\n/** Parameters of the fromAPIResponse method of the Operation class. */\nexport declare interface OperationFromAPIResponseParameters {\n /** The API response to be converted to an Operation. */\n apiResponse: Record<string, unknown>;\n /** Whether the API response is from Vertex AI. */\n _isVertexAI: boolean;\n}\n\n/**\n * Config for thinking feature.\n *\n * @deprecated This interface will be deprecated. Please use `ThinkingConfig` instead.\n */\nexport declare interface GenerationConfigThinkingConfig\n extends ThinkingConfig {}\n\n/** Generates the parameters for the private registerFiles method. */\nexport declare interface RegisterFilesParameters {\n /**\n * The authentication object.\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n auth?: any;\n /**\n * The Google Cloud Storage URIs to register. Example: `gs://bucket/object`.\n */\n uris: string[];\n /** Used to override the default configuration. */\n config?: RegisterFilesConfig;\n}\n\n/** Configures automatic detection of activity. */\nexport declare interface AutomaticActivityDetection {\n /** If enabled, detected voice and text input count as activity. If disabled, the client must send activity signals. */\n disabled?: boolean;\n /** Determines how likely speech is to be detected. */\n startOfSpeechSensitivity?: StartSensitivity;\n /** Determines how likely detected speech is ended. */\n endOfSpeechSensitivity?: EndSensitivity;\n /** The required duration of detected speech before start-of-speech is committed. The lower this value the more sensitive the start-of-speech detection is and the shorter speech can be recognized. However, this also increases the probability of false positives. */\n prefixPaddingMs?: number;\n /** The required duration of detected non-speech (e.g. silence) before end-of-speech is committed. The larger this value, the longer speech gaps can be without interrupting the user's activity but this will increase the model's latency. */\n silenceDurationMs?: number;\n}\n\n/** Marks the end of user activity.\n\nThis can only be sent if automatic (i.e. server-side) activity detection is\ndisabled. */\nexport declare interface RealtimeInputConfig {\n /** If not set, automatic activity detection is enabled by default. If automatic voice detection is disabled, the client must send activity signals. */\n automaticActivityDetection?: AutomaticActivityDetection;\n /** Defines what effect activity has. */\n activityHandling?: ActivityHandling;\n /** Defines which input is included in the user's turn. */\n turnCoverage?: TurnCoverage;\n}\n\n/** Configuration of session resumption mechanism.\n\nIncluded in `LiveConnectConfig.session_resumption`. If included server\nwill send `LiveServerSessionResumptionUpdate` messages. */\nexport declare interface SessionResumptionConfig {\n /** Session resumption handle of previous session (session to restore).\n\nIf not present new session will be started. */\n handle?: string;\n /** If set the server will send `last_consumed_client_message_index` in the `session_resumption_update` messages to allow for transparent reconnections. */\n transparent?: boolean;\n}\n\n/** Context window will be truncated by keeping only suffix of it.\n\nContext window will always be cut at start of USER role turn. System\ninstructions and `BidiGenerateContentSetup.prefix_turns` will not be\nsubject to the sliding window mechanism, they will always stay at the\nbeginning of context window. */\nexport declare interface SlidingWindow {\n /** Session reduction target -- how many tokens we should keep. Window shortening operation has some latency costs, so we should avoid running it on every turn. Should be < trigger_tokens. If not set, trigger_tokens/2 is assumed. */\n targetTokens?: string;\n}\n\n/** Enables context window compression -- mechanism managing model context window so it does not exceed given length. */\nexport declare interface ContextWindowCompressionConfig {\n /** Number of tokens (before running turn) that triggers context window compression mechanism. */\n triggerTokens?: string;\n /** Sliding window compression mechanism. */\n slidingWindow?: SlidingWindow;\n}\n\n/** The audio transcription configuration in Setup. */\nexport declare interface AudioTranscriptionConfig {}\n\n/** Config for proactivity features. */\nexport declare interface ProactivityConfig {\n /** If enabled, the model can reject responding to the last prompt. For\n example, this allows the model to ignore out of context speech or to stay\n silent if the user did not make a request, yet. */\n proactiveAudio?: boolean;\n}\n\n/** Message contains configuration that will apply for the duration of the streaming session. */\nexport declare interface LiveClientSetup {\n /** \n The fully qualified name of the publisher model or tuned model endpoint to\n use.\n */\n model?: string;\n /** The generation configuration for the session.\n Note: only a subset of fields are supported.\n */\n generationConfig?: GenerationConfig;\n /** The user provided system instructions for the model.\n Note: only text should be used in parts and content in each part will be\n in a separate paragraph. */\n systemInstruction?: ContentUnion;\n /** A list of `Tools` the model may use to generate the next response.\n\n A `Tool` is a piece of code that enables the system to interact with\n external systems to perform an action, or set of actions, outside of\n knowledge and scope of the model. */\n tools?: ToolListUnion;\n /** Configures the realtime input behavior in BidiGenerateContent. */\n realtimeInputConfig?: RealtimeInputConfig;\n /** Configures session resumption mechanism.\n\n If included server will send SessionResumptionUpdate messages. */\n sessionResumption?: SessionResumptionConfig;\n /** Configures context window compression mechanism.\n\n If included, server will compress context window to fit into given length. */\n contextWindowCompression?: ContextWindowCompressionConfig;\n /** The transcription of the input aligns with the input audio language.\n */\n inputAudioTranscription?: AudioTranscriptionConfig;\n /** The transcription of the output aligns with the language code\n specified for the output audio.\n */\n outputAudioTranscription?: AudioTranscriptionConfig;\n /** Configures the proactivity of the model. This allows the model to respond proactively to\n the input and to ignore irrelevant input. */\n proactivity?: ProactivityConfig;\n /** Configures the explicit VAD signal. If enabled, the client will send\n vad_signal to indicate the start and end of speech. This allows the server\n to process the audio more efficiently. */\n explicitVadSignal?: boolean;\n}\n\n/** Incremental update of the current conversation delivered from the client.\n\nAll the content here will unconditionally be appended to the conversation\nhistory and used as part of the prompt to the model to generate content.\n\nA message here will interrupt any current model generation. */\nexport declare interface LiveClientContent {\n /** The content appended to the current conversation with the model.\n\n For single-turn queries, this is a single instance. For multi-turn\n queries, this is a repeated field that contains conversation history and\n latest request.\n */\n turns?: Content[];\n /** If true, indicates that the server content generation should start with\n the currently accumulated prompt. Otherwise, the server will await\n additional messages before starting generation. */\n turnComplete?: boolean;\n}\n\n/** Marks the start of user activity.\n\nThis can only be sent if automatic (i.e. server-side) activity detection is\ndisabled. */\nexport declare interface ActivityStart {}\n\n/** Marks the end of user activity.\n\nThis can only be sent if automatic (i.e. server-side) activity detection is\ndisabled. */\nexport declare interface ActivityEnd {}\n\n/** User input that is sent in real time.\n\nThis is different from `LiveClientContent` in a few ways:\n\n - Can be sent continuously without interruption to model generation.\n - If there is a need to mix data interleaved across the\n `LiveClientContent` and the `LiveClientRealtimeInput`, server attempts to\n optimize for best response, but there are no guarantees.\n - End of turn is not explicitly specified, but is rather derived from user\n activity (for example, end of speech).\n - Even before the end of turn, the data is processed incrementally\n to optimize for a fast start of the response from the model.\n - Is always assumed to be the user's input (cannot be used to populate\n conversation history). */\nexport declare interface LiveClientRealtimeInput {\n /** Inlined bytes data for media input. */\n mediaChunks?: Blob[];\n /** The realtime audio input stream. */\n audio?: Blob;\n /** \nIndicates that the audio stream has ended, e.g. because the microphone was\nturned off.\n\nThis should only be sent when automatic activity detection is enabled\n(which is the default).\n\nThe client can reopen the stream by sending an audio message.\n */\n audioStreamEnd?: boolean;\n /** The realtime video input stream. */\n video?: Blob;\n /** The realtime text input stream. */\n text?: string;\n /** Marks the start of user activity. */\n activityStart?: ActivityStart;\n /** Marks the end of user activity. */\n activityEnd?: ActivityEnd;\n}\n\n/** Client generated response to a `ToolCall` received from the server.\n\nIndividual `FunctionResponse` objects are matched to the respective\n`FunctionCall` objects by the `id` field.\n\nNote that in the unary and server-streaming GenerateContent APIs function\ncalling happens by exchanging the `Content` parts, while in the bidi\nGenerateContent APIs function calling happens over this dedicated set of\nmessages. */\nexport class LiveClientToolResponse {\n /** The response to the function calls. */\n functionResponses?: FunctionResponse[];\n}\n\n/** Parameters for sending realtime input to the live API. */\nexport declare interface LiveSendRealtimeInputParameters {\n /** Realtime input to send to the session. */\n media?: BlobImageUnion;\n /** The realtime audio input stream. */\n audio?: Blob;\n /** \nIndicates that the audio stream has ended, e.g. because the microphone was\nturned off.\n\nThis should only be sent when automatic activity detection is enabled\n(which is the default).\n\nThe client can reopen the stream by sending an audio message.\n */\n audioStreamEnd?: boolean;\n /** The realtime video input stream. */\n video?: BlobImageUnion;\n /** The realtime text input stream. */\n text?: string;\n /** Marks the start of user activity. */\n activityStart?: ActivityStart;\n /** Marks the end of user activity. */\n activityEnd?: ActivityEnd;\n}\n\n/** Messages sent by the client in the API call. */\nexport declare interface LiveClientMessage {\n /** Message to be sent by the system when connecting to the API. SDK users should not send this message. */\n setup?: LiveClientSetup;\n /** Incremental update of the current conversation delivered from the client. */\n clientContent?: LiveClientContent;\n /** User input that is sent in real time. */\n realtimeInput?: LiveClientRealtimeInput;\n /** Response to a `ToolCallMessage` received from the server. */\n toolResponse?: LiveClientToolResponse;\n}\n\n/** Session config for the API connection. */\nexport declare interface LiveConnectConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** The generation configuration for the session. */\n generationConfig?: GenerationConfig;\n /** The requested modalities of the response. Represents the set of\n modalities that the model can return. Defaults to AUDIO if not specified.\n */\n responseModalities?: Modality[];\n /** Value that controls the degree of randomness in token selection.\n Lower temperatures are good for prompts that require a less open-ended or\n creative response, while higher temperatures can lead to more diverse or\n creative results.\n */\n temperature?: number;\n /** Tokens are selected from the most to least probable until the sum\n of their probabilities equals this value. Use a lower value for less\n random responses and a higher value for more random responses.\n */\n topP?: number;\n /** For each token selection step, the ``top_k`` tokens with the\n highest probabilities are sampled. Then tokens are further filtered based\n on ``top_p`` with the final token selected using temperature sampling. Use\n a lower number for less random responses and a higher number for more\n random responses.\n */\n topK?: number;\n /** Maximum number of tokens that can be generated in the response.\n */\n maxOutputTokens?: number;\n /** If specified, the media resolution specified will be used.\n */\n mediaResolution?: MediaResolution;\n /** When ``seed`` is fixed to a specific number, the model makes a best\n effort to provide the same response for repeated requests. By default, a\n random number is used.\n */\n seed?: number;\n /** The speech generation configuration.\n */\n speechConfig?: SpeechConfig;\n /** Config for thinking features.\n An error will be returned if this field is set for models that don't\n support thinking.\n */\n thinkingConfig?: ThinkingConfig;\n /** If enabled, the model will detect emotions and adapt its responses accordingly. */\n enableAffectiveDialog?: boolean;\n /** The user provided system instructions for the model.\n Note: only text should be used in parts and content in each part will be\n in a separate paragraph. */\n systemInstruction?: ContentUnion;\n /** A list of `Tools` the model may use to generate the next response.\n\n A `Tool` is a piece of code that enables the system to interact with\n external systems to perform an action, or set of actions, outside of\n knowledge and scope of the model. */\n tools?: ToolListUnion;\n /** Configures session resumption mechanism.\n\nIf included the server will send SessionResumptionUpdate messages. */\n sessionResumption?: SessionResumptionConfig;\n /** The transcription of the input aligns with the input audio language.\n */\n inputAudioTranscription?: AudioTranscriptionConfig;\n /** The transcription of the output aligns with the language code\n specified for the output audio.\n */\n outputAudioTranscription?: AudioTranscriptionConfig;\n /** Configures the realtime input behavior in BidiGenerateContent. */\n realtimeInputConfig?: RealtimeInputConfig;\n /** Configures context window compression mechanism.\n\n If included, server will compress context window to fit into given length. */\n contextWindowCompression?: ContextWindowCompressionConfig;\n /** Configures the proactivity of the model. This allows the model to respond proactively to\n the input and to ignore irrelevant input. */\n proactivity?: ProactivityConfig;\n /** Configures the explicit VAD signal. If enabled, the client will send\n vad_signal to indicate the start and end of speech. This allows the server\n to process the audio more efficiently. */\n explicitVadSignal?: boolean;\n}\n\n/** Parameters for connecting to the live API. */\nexport declare interface LiveConnectParameters {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model: string;\n /** callbacks */\n callbacks: LiveCallbacks;\n /** Optional configuration parameters for the request.\n */\n config?: LiveConnectConfig;\n}\n\n/** Parameters for initializing a new chat session.\n\nThese parameters are used when creating a chat session with the\n`chats.create()` method. */\nexport declare interface CreateChatParameters {\n /** The name of the model to use for the chat session.\n\n For example: 'gemini-2.0-flash', 'gemini-2.0-flash-lite', etc. See Gemini API\n docs to find the available models.\n */\n model: string;\n /** Config for the entire chat session.\n\n This config applies to all requests within the session\n unless overridden by a per-request `config` in `SendMessageParameters`.\n */\n config?: GenerateContentConfig;\n /** The initial conversation history for the chat session.\n\n This allows you to start the chat with a pre-existing history. The history\n must be a list of `Content` alternating between 'user' and 'model' roles.\n It should start with a 'user' message.\n */\n history?: Content[];\n}\n\n/** Parameters for sending a message within a chat session.\n\nThese parameters are used with the `chat.sendMessage()` method. */\nexport declare interface SendMessageParameters {\n /** The message to send to the model.\n\n The SDK will combine all parts into a single 'user' content to send to\n the model.\n */\n message: PartListUnion;\n /** Config for this specific request.\n\n Please note that the per-request config does not change the chat level\n config, nor inherit from it. If you intend to use some values from the\n chat's default config, you must explicitly copy them into this per-request\n config.\n */\n config?: GenerateContentConfig;\n}\n\n/** Parameters for sending client content to the live API. */\nexport declare interface LiveSendClientContentParameters {\n /** Client content to send to the session. */\n turns?: ContentListUnion;\n /** If true, indicates that the server content generation should start with\n the currently accumulated prompt. Otherwise, the server will await\n additional messages before starting generation. */\n turnComplete?: boolean;\n}\n\n/** Parameters for sending tool responses to the live API. */\nexport class LiveSendToolResponseParameters {\n /** Tool responses to send to the session. */\n functionResponses: FunctionResponse[] | FunctionResponse = [];\n}\n\n/** Message to be sent by the system when connecting to the API. */\nexport declare interface LiveMusicClientSetup {\n /** The model's resource name. Format: `models/{model}`. */\n model?: string;\n}\n\n/** Maps a prompt to a relative weight to steer music generation. */\nexport declare interface WeightedPrompt {\n /** Text prompt. */\n text?: string;\n /** Weight of the prompt. The weight is used to control the relative\n importance of the prompt. Higher weights are more important than lower\n weights.\n\n Weight must not be 0. Weights of all weighted_prompts in this\n LiveMusicClientContent message will be normalized. */\n weight?: number;\n}\n\n/** User input to start or steer the music. */\nexport declare interface LiveMusicClientContent {\n /** Weighted prompts as the model input. */\n weightedPrompts?: WeightedPrompt[];\n}\n\n/** Configuration for music generation. */\nexport declare interface LiveMusicGenerationConfig {\n /** Controls the variance in audio generation. Higher values produce\n higher variance. Range is [0.0, 3.0]. */\n temperature?: number;\n /** Controls how the model selects tokens for output. Samples the topK\n tokens with the highest probabilities. Range is [1, 1000]. */\n topK?: number;\n /** Seeds audio generation. If not set, the request uses a randomly\n generated seed. */\n seed?: number;\n /** Controls how closely the model follows prompts.\n Higher guidance follows more closely, but will make transitions more\n abrupt. Range is [0.0, 6.0]. */\n guidance?: number;\n /** Beats per minute. Range is [60, 200]. */\n bpm?: number;\n /** Density of sounds. Range is [0.0, 1.0]. */\n density?: number;\n /** Brightness of the music. Range is [0.0, 1.0]. */\n brightness?: number;\n /** Scale of the generated music. */\n scale?: Scale;\n /** Whether the audio output should contain bass. */\n muteBass?: boolean;\n /** Whether the audio output should contain drums. */\n muteDrums?: boolean;\n /** Whether the audio output should contain only bass and drums. */\n onlyBassAndDrums?: boolean;\n /** The mode of music generation. Default mode is QUALITY. */\n musicGenerationMode?: MusicGenerationMode;\n}\n\n/** Messages sent by the client in the LiveMusicClientMessage call. */\nexport declare interface LiveMusicClientMessage {\n /** Message to be sent in the first (and only in the first) `LiveMusicClientMessage`.\n Clients should wait for a `LiveMusicSetupComplete` message before\n sending any additional messages. */\n setup?: LiveMusicClientSetup;\n /** User input to influence music generation. */\n clientContent?: LiveMusicClientContent;\n /** Configuration for music generation. */\n musicGenerationConfig?: LiveMusicGenerationConfig;\n /** Playback control signal for the music generation. */\n playbackControl?: LiveMusicPlaybackControl;\n}\n\n/** Sent in response to a `LiveMusicClientSetup` message from the client. */\nexport declare interface LiveMusicServerSetupComplete {}\n\n/** Prompts and config used for generating this audio chunk. */\nexport declare interface LiveMusicSourceMetadata {\n /** Weighted prompts for generating this audio chunk. */\n clientContent?: LiveMusicClientContent;\n /** Music generation config for generating this audio chunk. */\n musicGenerationConfig?: LiveMusicGenerationConfig;\n}\n\n/** Representation of an audio chunk. */\nexport declare interface AudioChunk {\n /** Raw bytes of audio data.\n * @remarks Encoded as base64 string. */\n data?: string;\n /** MIME type of the audio chunk. */\n mimeType?: string;\n /** Prompts and config used for generating this audio chunk. */\n sourceMetadata?: LiveMusicSourceMetadata;\n}\n\n/** Server update generated by the model in response to client messages.\n\nContent is generated as quickly as possible, and not in real time.\nClients may choose to buffer and play it out in real time. */\nexport declare interface LiveMusicServerContent {\n /** The audio chunks that the model has generated. */\n audioChunks?: AudioChunk[];\n}\n\n/** A prompt that was filtered with the reason. */\nexport declare interface LiveMusicFilteredPrompt {\n /** The text prompt that was filtered. */\n text?: string;\n /** The reason the prompt was filtered. */\n filteredReason?: string;\n}\n\n/** Response message for the LiveMusicClientMessage call. */\nexport class LiveMusicServerMessage {\n /** Message sent in response to a `LiveMusicClientSetup` message from the client.\n Clients should wait for this message before sending any additional messages. */\n setupComplete?: LiveMusicServerSetupComplete;\n /** Content generated by the model in response to client messages. */\n serverContent?: LiveMusicServerContent;\n /** A prompt that was filtered with the reason. */\n filteredPrompt?: LiveMusicFilteredPrompt;\n /**\n * Returns the first audio chunk from the server content, if present.\n *\n * @remarks\n * If there are no audio chunks in the response, undefined will be returned.\n */\n get audioChunk(): AudioChunk | undefined {\n if (\n this.serverContent &&\n this.serverContent.audioChunks &&\n this.serverContent.audioChunks.length > 0\n ) {\n return this.serverContent.audioChunks[0];\n }\n return undefined;\n }\n}\n\n/** Callbacks for the realtime music API. */\nexport interface LiveMusicCallbacks {\n /**\n * Called when a message is received from the server.\n */\n onmessage: (e: LiveMusicServerMessage) => void;\n /**\n * Called when an error occurs.\n */\n onerror?: ((e: ErrorEvent) => void) | null;\n /**\n * Called when the websocket connection is closed.\n */\n onclose?: ((e: CloseEvent) => void) | null;\n}\n\n/** Parameters for the upload file method. */\nexport interface UploadFileParameters {\n /** The string path to the file to be uploaded or a Blob object. */\n file: string | globalThis.Blob;\n /** Configuration that contains optional parameters. */\n config?: UploadFileConfig;\n}\n\n/** Parameters for the upload file to file search store method. */\nexport interface UploadToFileSearchStoreParameters {\n /** The name of the file search store to upload. */\n fileSearchStoreName: string;\n /** The string path to the file to be uploaded or a Blob object. */\n file: string | globalThis.Blob;\n /** Configuration that contains optional parameters. */\n config?: UploadToFileSearchStoreConfig;\n}\n\n/**\n * CallableTool is an invokable tool that can be executed with external\n * application (e.g., via Model Context Protocol) or local functions with\n * function calling.\n */\nexport interface CallableTool {\n /**\n * Returns tool that can be called by Gemini.\n */\n tool(): Promise<Tool>;\n /**\n * Executes the callable tool with the given function call arguments and\n * returns the response parts from the tool execution.\n */\n callTool(functionCalls: FunctionCall[]): Promise<Part[]>;\n}\n\n/**\n * CallableToolConfig is the configuration for a callable tool.\n */\nexport interface CallableToolConfig {\n /**\n * Specifies the model's behavior after invoking this tool.\n */\n behavior?: Behavior;\n /**\n * Timeout for remote calls in milliseconds. Note this timeout applies only to\n * tool remote calls, and not making HTTP requests to the API. */\n timeout?: number;\n}\n\n/** Parameters for connecting to the live API. */\nexport declare interface LiveMusicConnectParameters {\n /** The model's resource name. */\n model: string;\n /** Callbacks invoked on server events. */\n callbacks: LiveMusicCallbacks;\n}\n\n/** Parameters for setting config for the live music API. */\nexport declare interface LiveMusicSetConfigParameters {\n /** Configuration for music generation. */\n musicGenerationConfig: LiveMusicGenerationConfig;\n}\n\n/** Parameters for setting weighted prompts for the live music API. */\nexport declare interface LiveMusicSetWeightedPromptsParameters {\n /** A map of text prompts to weights to use for the generation request. */\n weightedPrompts: WeightedPrompt[];\n}\n\n/** Config for auth_tokens.create parameters. */\nexport declare interface AuthToken {\n /** The name of the auth token. */\n name?: string;\n}\n\n/** Config for LiveConnectConstraints for Auth Token creation. */\nexport declare interface LiveConnectConstraints {\n /** ID of the model to configure in the ephemeral token for Live API.\n For a list of models, see `Gemini models\n <https://ai.google.dev/gemini-api/docs/models>`. */\n model?: string;\n /** Configuration specific to Live API connections created using this token. */\n config?: LiveConnectConfig;\n}\n\n/** Optional parameters. */\nexport declare interface CreateAuthTokenConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** An optional time after which, when using the resulting token,\n messages in Live API sessions will be rejected. (Gemini may\n preemptively close the session after this time.)\n\n If not set then this defaults to 30 minutes in the future. If set, this\n value must be less than 20 hours in the future. */\n expireTime?: string;\n /** The time after which new Live API sessions using the token\n resulting from this request will be rejected.\n\n If not set this defaults to 60 seconds in the future. If set, this value\n must be less than 20 hours in the future. */\n newSessionExpireTime?: string;\n /** The number of times the token can be used. If this value is zero\n then no limit is applied. Default is 1. Resuming a Live API session does\n not count as a use. */\n uses?: number;\n /** Configuration specific to Live API connections created using this token. */\n liveConnectConstraints?: LiveConnectConstraints;\n /** Additional fields to lock in the effective LiveConnectParameters. */\n lockAdditionalFields?: string[];\n}\n\n/** Config for auth_tokens.create parameters. */\nexport declare interface CreateAuthTokenParameters {\n /** Optional parameters for the request. */\n config?: CreateAuthTokenConfig;\n}\n\n/** Parameters for the get method of the operations module. */\nexport declare interface OperationGetParameters<T, U extends Operation<T>> {\n /** Used to override the default configuration. */\n config?: GetOperationConfig;\n /** The operation to be retrieved. */\n operation: U;\n}\n\n/** Local tokenizer count tokens result. */\nexport declare interface CountTokensResult {\n /** The total number of tokens. */\n totalTokens?: number;\n}\n\n/** Local tokenizer compute tokens result. */\nexport declare interface ComputeTokensResult {\n /** Lists of tokens info from the input. */\n tokensInfo?: TokensInfo[];\n}\n\n/** Fine-tuning job creation parameters - optional fields. */\nexport declare interface CreateTuningJobParameters {\n /** The base model that is being tuned, e.g., \"gemini-2.5-flash\". */\n baseModel: string;\n /** Cloud Storage path to file containing training dataset for tuning. The dataset must be formatted as a JSONL file. */\n trainingDataset: TuningDataset;\n /** Configuration for the tuning job. */\n config?: CreateTuningJobConfig;\n}\n\n/** The response when long-running operation for uploading a file to a FileSearchStore complete. */\nexport class UploadToFileSearchStoreResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** The name of the FileSearchStore containing Documents. */\n parent?: string;\n /** The identifier for the Document imported. */\n documentName?: string;\n}\n\n/** Long-running operation for uploading a file to a FileSearchStore. */\nexport class UploadToFileSearchStoreOperation\n implements Operation<UploadToFileSearchStoreResponse>\n{\n /** The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`. */\n name?: string;\n /** Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata. Any method that returns a long-running operation should document the metadata type, if any. */\n metadata?: Record<string, unknown>;\n /** If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available. */\n done?: boolean;\n /** The error result of the operation in case of failure or cancellation. */\n error?: Record<string, unknown>;\n /** The result of the UploadToFileSearchStore operation, available when the operation is done. */\n response?: UploadToFileSearchStoreResponse;\n\n /**\n * Instantiates an Operation of the same type as the one being called with the fields set from the API response.\n * @internal\n */\n _fromAPIResponse({\n apiResponse,\n _isVertexAI,\n }: OperationFromAPIResponseParameters): Operation<UploadToFileSearchStoreResponse> {\n const operation = new UploadToFileSearchStoreOperation();\n\n const op = apiResponse as unknown as UploadToFileSearchStoreOperation;\n const response = uploadToFileSearchStoreOperationFromMldev(op);\n Object.assign(operation, response);\n return operation;\n }\n /** The full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n}\n\nexport type BlobImageUnion = Blob;\n\nexport type PartUnion = Part | string;\n\nexport type PartListUnion = PartUnion[] | PartUnion;\n\nexport type ContentUnion = Content | PartUnion[] | PartUnion;\n\nexport type ContentListUnion = Content | Content[] | PartUnion | PartUnion[];\n\nexport type SchemaUnion = Schema | unknown;\n\nexport type SpeechConfigUnion = SpeechConfig | string;\n\nexport type ToolUnion = Tool | CallableTool;\n\nexport type ToolListUnion = ToolUnion[];\n\nexport type DownloadableFileUnion = string | File | GeneratedVideo | Video;\n\nexport type BatchJobSourceUnion = BatchJobSource | InlinedRequest[] | string;\n\nexport type BatchJobDestinationUnion = BatchJobDestination | string;\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type {Tool as McpTool} from '@modelcontextprotocol/sdk/types';\n\nimport {ApiClient} from './_api_client.js';\nimport * as baseTransformers from './_base_transformers.js';\nimport * as types from './types.js';\n\nexport function tModel(apiClient: ApiClient, model: string | unknown): string {\n if (!model || typeof model !== 'string') {\n throw new Error('model is required and must be a string');\n }\n if (model.includes('..') || model.includes('?') || model.includes('&')) {\n throw new Error('invalid model parameter');\n }\n\n if (apiClient.isVertexAI()) {\n if (\n model.startsWith('publishers/') ||\n model.startsWith('projects/') ||\n model.startsWith('models/')\n ) {\n return model;\n } else if (model.indexOf('/') >= 0) {\n const parts = model.split('/', 2);\n return `publishers/${parts[0]}/models/${parts[1]}`;\n } else {\n return `publishers/google/models/${model}`;\n }\n } else {\n if (model.startsWith('models/') || model.startsWith('tunedModels/')) {\n return model;\n } else {\n return `models/${model}`;\n }\n }\n}\n\nexport function tCachesModel(\n apiClient: ApiClient,\n model: string | unknown,\n): string {\n const transformedModel = tModel(apiClient, model as string);\n if (!transformedModel) {\n return '';\n }\n\n if (transformedModel.startsWith('publishers/') && apiClient.isVertexAI()) {\n // vertex caches only support model name start with projects.\n return `projects/${apiClient.getProject()}/locations/${apiClient.getLocation()}/${transformedModel}`;\n } else if (transformedModel.startsWith('models/') && apiClient.isVertexAI()) {\n return `projects/${apiClient.getProject()}/locations/${apiClient.getLocation()}/publishers/google/${transformedModel}`;\n } else {\n return transformedModel;\n }\n}\n\nexport function tBlobs(\n blobs: types.BlobImageUnion | types.BlobImageUnion[],\n): types.Blob[] {\n if (Array.isArray(blobs)) {\n return blobs.map((blob) => tBlob(blob));\n } else {\n return [tBlob(blobs)];\n }\n}\n\nexport function tBlob(blob: types.BlobImageUnion): types.Blob {\n if (typeof blob === 'object' && blob !== null) {\n return blob;\n }\n\n throw new Error(\n `Could not parse input as Blob. Unsupported blob type: ${typeof blob}`,\n );\n}\n\nexport function tImageBlob(blob: types.BlobImageUnion): types.Blob {\n const transformedBlob = tBlob(blob);\n if (\n transformedBlob.mimeType &&\n transformedBlob.mimeType.startsWith('image/')\n ) {\n return transformedBlob;\n }\n throw new Error(`Unsupported mime type: ${transformedBlob.mimeType!}`);\n}\n\nexport function tAudioBlob(blob: types.Blob): types.Blob {\n const transformedBlob = tBlob(blob);\n if (\n transformedBlob.mimeType &&\n transformedBlob.mimeType.startsWith('audio/')\n ) {\n return transformedBlob;\n }\n throw new Error(`Unsupported mime type: ${transformedBlob.mimeType!}`);\n}\n\nexport function tPart(origin?: types.PartUnion | null): types.Part {\n if (origin === null || origin === undefined) {\n throw new Error('PartUnion is required');\n }\n if (typeof origin === 'object') {\n return origin;\n }\n if (typeof origin === 'string') {\n return {text: origin};\n }\n throw new Error(`Unsupported part type: ${typeof origin}`);\n}\n\nexport function tParts(origin?: types.PartListUnion | null): types.Part[] {\n if (\n origin === null ||\n origin === undefined ||\n (Array.isArray(origin) && origin.length === 0)\n ) {\n throw new Error('PartListUnion is required');\n }\n if (Array.isArray(origin)) {\n return origin.map((item) => tPart(item as types.PartUnion)!);\n }\n return [tPart(origin)!];\n}\n\nfunction _isContent(origin: unknown): boolean {\n return (\n origin !== null &&\n origin !== undefined &&\n typeof origin === 'object' &&\n 'parts' in origin &&\n Array.isArray(origin.parts)\n );\n}\n\nfunction _isFunctionCallPart(origin: unknown): boolean {\n return (\n origin !== null &&\n origin !== undefined &&\n typeof origin === 'object' &&\n 'functionCall' in origin\n );\n}\n\nfunction _isFunctionResponsePart(origin: unknown): boolean {\n return (\n origin !== null &&\n origin !== undefined &&\n typeof origin === 'object' &&\n 'functionResponse' in origin\n );\n}\n\nexport function tContent(origin?: types.ContentUnion): types.Content {\n if (origin === null || origin === undefined) {\n throw new Error('ContentUnion is required');\n }\n if (_isContent(origin)) {\n // _isContent is a utility function that checks if the\n // origin is a Content.\n return origin as types.Content;\n }\n\n return {\n role: 'user',\n parts: tParts(origin as types.PartListUnion)!,\n };\n}\n\nexport function tContentsForEmbed(\n apiClient: ApiClient,\n origin: types.ContentListUnion,\n): types.ContentUnion[] {\n if (!origin) {\n return [];\n }\n if (apiClient.isVertexAI() && Array.isArray(origin)) {\n return origin.flatMap((item) => {\n const content = tContent(item as types.ContentUnion);\n if (\n content.parts &&\n content.parts.length > 0 &&\n content.parts[0].text !== undefined\n ) {\n return [content.parts[0].text];\n }\n return [];\n });\n } else if (apiClient.isVertexAI()) {\n const content = tContent(origin as types.ContentUnion);\n if (\n content.parts &&\n content.parts.length > 0 &&\n content.parts[0].text !== undefined\n ) {\n return [content.parts[0].text];\n }\n return [];\n }\n if (Array.isArray(origin)) {\n return origin.map((item) => tContent(item as types.ContentUnion)!);\n }\n return [tContent(origin as types.ContentUnion)!];\n}\n\nexport function tContents(origin?: types.ContentListUnion): types.Content[] {\n if (\n origin === null ||\n origin === undefined ||\n (Array.isArray(origin) && origin.length === 0)\n ) {\n throw new Error('contents are required');\n }\n if (!Array.isArray(origin)) {\n // If it's not an array, it's a single content or a single PartUnion.\n if (_isFunctionCallPart(origin) || _isFunctionResponsePart(origin)) {\n throw new Error(\n 'To specify functionCall or functionResponse parts, please wrap them in a Content object, specifying the role for them',\n );\n }\n return [tContent(origin as types.ContentUnion)];\n }\n\n const result: types.Content[] = [];\n const accumulatedParts: types.PartUnion[] = [];\n const isContentArray = _isContent(origin[0]);\n\n for (const item of origin) {\n const isContent = _isContent(item);\n\n if (isContent != isContentArray) {\n throw new Error(\n 'Mixing Content and Parts is not supported, please group the parts into a the appropriate Content objects and specify the roles for them',\n );\n }\n\n if (isContent) {\n // `isContent` contains the result of _isContent, which is a utility\n // function that checks if the item is a Content.\n result.push(item as types.Content);\n } else if (_isFunctionCallPart(item) || _isFunctionResponsePart(item)) {\n throw new Error(\n 'To specify functionCall or functionResponse parts, please wrap them, and any other parts, in Content objects as appropriate, specifying the role for them',\n );\n } else {\n accumulatedParts.push(item as types.PartUnion);\n }\n }\n\n if (!isContentArray) {\n result.push({role: 'user', parts: tParts(accumulatedParts)});\n }\n return result;\n}\n\n/*\nTransform the type field from an array of types to an array of anyOf fields.\nExample:\n {type: ['STRING', 'NUMBER']}\nwill be transformed to\n {anyOf: [{type: 'STRING'}, {type: 'NUMBER'}]}\n*/\nfunction flattenTypeArrayToAnyOf(\n typeList: string[],\n resultingSchema: types.Schema,\n) {\n if (typeList.includes('null')) {\n resultingSchema['nullable'] = true;\n }\n const listWithoutNull = typeList.filter((type) => type !== 'null');\n\n if (listWithoutNull.length === 1) {\n resultingSchema['type'] = Object.values(types.Type).includes(\n listWithoutNull[0].toUpperCase() as types.Type,\n )\n ? (listWithoutNull[0].toUpperCase() as types.Type)\n : types.Type.TYPE_UNSPECIFIED;\n } else {\n resultingSchema['anyOf'] = [];\n for (const i of listWithoutNull) {\n resultingSchema['anyOf'].push({\n 'type': Object.values(types.Type).includes(\n i.toUpperCase() as types.Type,\n )\n ? (i.toUpperCase() as types.Type)\n : types.Type.TYPE_UNSPECIFIED,\n });\n }\n }\n}\n\nexport function processJsonSchema(\n _jsonSchema: types.Schema | Record<string, unknown>,\n): types.Schema {\n const genAISchema: types.Schema = {};\n const schemaFieldNames = ['items'];\n const listSchemaFieldNames = ['anyOf'];\n const dictSchemaFieldNames = ['properties'];\n\n if (_jsonSchema['type'] && _jsonSchema['anyOf']) {\n throw new Error('type and anyOf cannot be both populated.');\n }\n\n /*\n This is to handle the nullable array or object. The _jsonSchema will\n be in the format of {anyOf: [{type: 'null'}, {type: 'object'}]}. The\n logic is to check if anyOf has 2 elements and one of the element is null,\n if so, the anyOf field is unnecessary, so we need to get rid of the anyOf\n field and make the schema nullable. Then use the other element as the new\n _jsonSchema for processing. This is because the backend doesn't have a null\n type.\n This has to be checked before we process any other fields.\n For example:\n const objectNullable = z.object({\n nullableArray: z.array(z.string()).nullable(),\n });\n Will have the raw _jsonSchema as:\n {\n type: 'OBJECT',\n properties: {\n nullableArray: {\n anyOf: [\n {type: 'null'},\n {\n type: 'array',\n items: {type: 'string'},\n },\n ],\n }\n },\n required: [ 'nullableArray' ],\n }\n Will result in following schema compatible with Gemini API:\n {\n type: 'OBJECT',\n properties: {\n nullableArray: {\n nullable: true,\n type: 'ARRAY',\n items: {type: 'string'},\n }\n },\n required: [ 'nullableArray' ],\n }\n */\n const incomingAnyOf = _jsonSchema['anyOf'] as Record<string, unknown>[];\n if (incomingAnyOf != null && incomingAnyOf.length == 2) {\n if (incomingAnyOf[0]!['type'] === 'null') {\n genAISchema['nullable'] = true;\n _jsonSchema = incomingAnyOf![1];\n } else if (incomingAnyOf[1]!['type'] === 'null') {\n genAISchema['nullable'] = true;\n _jsonSchema = incomingAnyOf![0];\n }\n }\n\n if (_jsonSchema['type'] instanceof Array) {\n flattenTypeArrayToAnyOf(_jsonSchema['type'], genAISchema);\n }\n\n for (const [fieldName, fieldValue] of Object.entries(_jsonSchema)) {\n // Skip if the fieldvalue is undefined or null.\n if (fieldValue == null) {\n continue;\n }\n\n if (fieldName == 'type') {\n if (fieldValue === 'null') {\n throw new Error(\n 'type: null can not be the only possible type for the field.',\n );\n }\n if (fieldValue instanceof Array) {\n // we have already handled the type field with array of types in the\n // beginning of this function.\n continue;\n }\n genAISchema['type'] = Object.values(types.Type).includes(\n fieldValue.toUpperCase() as types.Type,\n )\n ? fieldValue.toUpperCase()\n : types.Type.TYPE_UNSPECIFIED;\n } else if (schemaFieldNames.includes(fieldName)) {\n (genAISchema as Record<string, unknown>)[fieldName] =\n processJsonSchema(fieldValue);\n } else if (listSchemaFieldNames.includes(fieldName)) {\n const listSchemaFieldValue: Array<types.Schema> = [];\n for (const item of fieldValue) {\n if (item['type'] == 'null') {\n genAISchema['nullable'] = true;\n continue;\n }\n listSchemaFieldValue.push(\n processJsonSchema(item as Record<string, unknown>),\n );\n }\n (genAISchema as Record<string, unknown>)[fieldName] =\n listSchemaFieldValue;\n } else if (dictSchemaFieldNames.includes(fieldName)) {\n const dictSchemaFieldValue: Record<string, types.Schema> = {};\n for (const [key, value] of Object.entries(\n fieldValue as Record<string, unknown>,\n )) {\n dictSchemaFieldValue[key] = processJsonSchema(\n value as Record<string, unknown>,\n );\n }\n (genAISchema as Record<string, unknown>)[fieldName] =\n dictSchemaFieldValue;\n } else {\n // additionalProperties is not included in JSONSchema, skipping it.\n if (fieldName === 'additionalProperties') {\n continue;\n }\n (genAISchema as Record<string, unknown>)[fieldName] = fieldValue;\n }\n }\n return genAISchema;\n}\n\n// we take the unknown in the schema field because we want enable user to pass\n// the output of major schema declaration tools without casting. Tools such as\n// zodToJsonSchema, typebox, zodToJsonSchema function can return JsonSchema7Type\n// or object, see details in\n// https://github.com/StefanTerdell/zod-to-json-schema/blob/70525efe555cd226691e093d171370a3b10921d1/src/zodToJsonSchema.ts#L7\n// typebox can return unknown, see details in\n// https://github.com/sinclairzx81/typebox/blob/5a5431439f7d5ca6b494d0d18fbfd7b1a356d67c/src/type/create/type.ts#L35\n// Note: proper json schemas with the $schema field set never arrive to this\n// transformer. Schemas with $schema are routed to the equivalent API json\n// schema field.\nexport function tSchema(schema: types.Schema | unknown): types.Schema {\n return processJsonSchema(schema as types.Schema);\n}\n\nexport function tSpeechConfig(\n speechConfig: types.SpeechConfigUnion,\n): types.SpeechConfig {\n if (typeof speechConfig === 'object') {\n return speechConfig;\n } else if (typeof speechConfig === 'string') {\n return {\n voiceConfig: {\n prebuiltVoiceConfig: {\n voiceName: speechConfig,\n },\n },\n };\n } else {\n throw new Error(`Unsupported speechConfig type: ${typeof speechConfig}`);\n }\n}\n\nexport function tLiveSpeechConfig(\n speechConfig: types.SpeechConfig | object,\n): types.SpeechConfig {\n if ('multiSpeakerVoiceConfig' in speechConfig) {\n throw new Error(\n 'multiSpeakerVoiceConfig is not supported in the live API.',\n );\n }\n return speechConfig;\n}\n\nexport function tTool(tool: types.Tool): types.Tool {\n if (tool.functionDeclarations) {\n for (const functionDeclaration of tool.functionDeclarations) {\n if (functionDeclaration.parameters) {\n if (!Object.keys(functionDeclaration.parameters).includes('$schema')) {\n functionDeclaration.parameters = processJsonSchema(\n functionDeclaration.parameters,\n );\n } else {\n if (!functionDeclaration.parametersJsonSchema) {\n functionDeclaration.parametersJsonSchema =\n functionDeclaration.parameters;\n delete functionDeclaration.parameters;\n }\n }\n }\n if (functionDeclaration.response) {\n if (!Object.keys(functionDeclaration.response).includes('$schema')) {\n functionDeclaration.response = processJsonSchema(\n functionDeclaration.response,\n );\n } else {\n if (!functionDeclaration.responseJsonSchema) {\n functionDeclaration.responseJsonSchema =\n functionDeclaration.response;\n delete functionDeclaration.response;\n }\n }\n }\n }\n }\n return tool;\n}\n\nexport function tTools(tools: types.ToolListUnion | unknown): types.Tool[] {\n // Check if the incoming type is defined.\n if (tools === undefined || tools === null) {\n throw new Error('tools is required');\n }\n if (!Array.isArray(tools)) {\n throw new Error('tools is required and must be an array of Tools');\n }\n const result: types.Tool[] = [];\n for (const tool of tools) {\n result.push(tool as types.Tool);\n }\n return result;\n}\n\n/**\n * Prepends resource name with project, location, resource_prefix if needed.\n *\n * @param client The API client.\n * @param resourceName The resource name.\n * @param resourcePrefix The resource prefix.\n * @param splitsAfterPrefix The number of splits after the prefix.\n * @returns The completed resource name.\n *\n * Examples:\n *\n * ```\n * resource_name = '123'\n * resource_prefix = 'cachedContents'\n * splits_after_prefix = 1\n * client.vertexai = True\n * client.project = 'bar'\n * client.location = 'us-west1'\n * _resource_name(client, resource_name, resource_prefix, splits_after_prefix)\n * returns: 'projects/bar/locations/us-west1/cachedContents/123'\n * ```\n *\n * ```\n * resource_name = 'projects/foo/locations/us-central1/cachedContents/123'\n * resource_prefix = 'cachedContents'\n * splits_after_prefix = 1\n * client.vertexai = True\n * client.project = 'bar'\n * client.location = 'us-west1'\n * _resource_name(client, resource_name, resource_prefix, splits_after_prefix)\n * returns: 'projects/foo/locations/us-central1/cachedContents/123'\n * ```\n *\n * ```\n * resource_name = '123'\n * resource_prefix = 'cachedContents'\n * splits_after_prefix = 1\n * client.vertexai = False\n * _resource_name(client, resource_name, resource_prefix, splits_after_prefix)\n * returns 'cachedContents/123'\n * ```\n *\n * ```\n * resource_name = 'some/wrong/cachedContents/resource/name/123'\n * resource_prefix = 'cachedContents'\n * splits_after_prefix = 1\n * client.vertexai = False\n * # client.vertexai = True\n * _resource_name(client, resource_name, resource_prefix, splits_after_prefix)\n * -> 'some/wrong/resource/name/123'\n * ```\n */\nfunction resourceName(\n client: ApiClient,\n resourceName: string,\n resourcePrefix: string,\n splitsAfterPrefix: number = 1,\n): string {\n const shouldAppendPrefix =\n !resourceName.startsWith(`${resourcePrefix}/`) &&\n resourceName.split('/').length === splitsAfterPrefix;\n if (client.isVertexAI()) {\n if (resourceName.startsWith('projects/')) {\n return resourceName;\n } else if (resourceName.startsWith('locations/')) {\n return `projects/${client.getProject()}/${resourceName}`;\n } else if (resourceName.startsWith(`${resourcePrefix}/`)) {\n return `projects/${client.getProject()}/locations/${client.getLocation()}/${resourceName}`;\n } else if (shouldAppendPrefix) {\n return `projects/${client.getProject()}/locations/${client.getLocation()}/${resourcePrefix}/${resourceName}`;\n } else {\n return resourceName;\n }\n }\n if (shouldAppendPrefix) {\n return `${resourcePrefix}/${resourceName}`;\n }\n return resourceName;\n}\n\nexport function tCachedContentName(\n apiClient: ApiClient,\n name: string | unknown,\n): string {\n if (typeof name !== 'string') {\n throw new Error('name must be a string');\n }\n return resourceName(apiClient, name, 'cachedContents');\n}\n\nexport function tTuningJobStatus(status: string | unknown): string {\n switch (status) {\n case 'STATE_UNSPECIFIED':\n return 'JOB_STATE_UNSPECIFIED';\n case 'CREATING':\n return 'JOB_STATE_RUNNING';\n case 'ACTIVE':\n return 'JOB_STATE_SUCCEEDED';\n case 'FAILED':\n return 'JOB_STATE_FAILED';\n default:\n return status as string;\n }\n}\n\nexport function tBytes(fromImageBytes: string | unknown): string {\n return baseTransformers.tBytes(fromImageBytes);\n}\n\nfunction _isFile(origin: unknown): boolean {\n return (\n origin !== null &&\n origin !== undefined &&\n typeof origin === 'object' &&\n 'name' in origin\n );\n}\n\nexport function isGeneratedVideo(origin: unknown): boolean {\n return (\n origin !== null &&\n origin !== undefined &&\n typeof origin === 'object' &&\n 'video' in origin\n );\n}\n\nexport function isVideo(origin: unknown): boolean {\n return (\n origin !== null &&\n origin !== undefined &&\n typeof origin === 'object' &&\n 'uri' in origin\n );\n}\n\nexport function tFileName(\n fromName: string | types.File | types.GeneratedVideo | types.Video,\n): string | undefined {\n let name: string | undefined;\n\n if (_isFile(fromName)) {\n name = (fromName as types.File).name;\n }\n if (isVideo(fromName)) {\n name = (fromName as types.Video).uri;\n if (name === undefined) {\n return undefined;\n }\n }\n if (isGeneratedVideo(fromName)) {\n name = (fromName as types.GeneratedVideo).video?.uri;\n if (name === undefined) {\n return undefined;\n }\n }\n if (typeof fromName === 'string') {\n name = fromName;\n }\n\n if (name === undefined) {\n throw new Error('Could not extract file name from the provided input.');\n }\n\n if (name.startsWith('https://')) {\n const suffix = name.split('files/')[1];\n const match = suffix.match(/[a-z0-9]+/);\n if (match === null) {\n throw new Error(`Could not extract file name from URI ${name}`);\n }\n name = match[0];\n } else if (name.startsWith('files/')) {\n name = name.split('files/')[1];\n }\n return name;\n}\n\nexport function tModelsUrl(\n apiClient: ApiClient,\n baseModels: boolean | unknown,\n): string {\n let res: string;\n if (apiClient.isVertexAI()) {\n res = baseModels ? 'publishers/google/models' : 'models';\n } else {\n res = baseModels ? 'models' : 'tunedModels';\n }\n return res;\n}\n\nexport function tExtractModels(response: unknown): Record<string, unknown>[] {\n for (const key of ['models', 'tunedModels', 'publisherModels']) {\n if (hasField(response, key)) {\n return (response as Record<string, unknown>)[key] as Record<\n string,\n unknown\n >[];\n }\n }\n return [];\n}\n\nfunction hasField(data: unknown, fieldName: string): boolean {\n return data !== null && typeof data === 'object' && fieldName in data;\n}\n\nexport function mcpToGeminiTool(\n mcpTool: McpTool,\n config: types.CallableToolConfig = {},\n): types.Tool {\n const mcpToolSchema = mcpTool as Record<string, unknown>;\n const functionDeclaration: Record<string, unknown> = {\n name: mcpToolSchema['name'],\n description: mcpToolSchema['description'],\n parametersJsonSchema: mcpToolSchema['inputSchema'],\n };\n if (mcpToolSchema['outputSchema']) {\n functionDeclaration['responseJsonSchema'] = mcpToolSchema['outputSchema'];\n }\n if (config.behavior) {\n functionDeclaration['behavior'] = config.behavior;\n }\n\n const geminiTool = {\n functionDeclarations: [\n functionDeclaration as unknown as types.FunctionDeclaration,\n ],\n };\n\n return geminiTool;\n}\n\n/**\n * Converts a list of MCP tools to a single Gemini tool with a list of function\n * declarations.\n */\nexport function mcpToolsToGeminiTool(\n mcpTools: McpTool[],\n config: types.CallableToolConfig = {},\n): types.Tool {\n const functionDeclarations: types.FunctionDeclaration[] = [];\n const toolNames = new Set<string>();\n for (const mcpTool of mcpTools) {\n const mcpToolName = mcpTool.name as string;\n if (toolNames.has(mcpToolName)) {\n throw new Error(\n `Duplicate function name ${\n mcpToolName\n } found in MCP tools. Please ensure function names are unique.`,\n );\n }\n toolNames.add(mcpToolName);\n const geminiTool = mcpToGeminiTool(mcpTool, config);\n if (geminiTool.functionDeclarations) {\n functionDeclarations.push(...geminiTool.functionDeclarations);\n }\n }\n\n return {functionDeclarations: functionDeclarations};\n}\n\n// Transforms a source input into a BatchJobSource object with validation.\nexport function tBatchJobSource(\n client: ApiClient,\n src: string | types.InlinedRequest[] | types.BatchJobSource,\n): types.BatchJobSource {\n let sourceObj: types.BatchJobSource;\n\n if (typeof src === 'string') {\n if (client.isVertexAI()) {\n if (src.startsWith('gs://')) {\n sourceObj = {format: 'jsonl', gcsUri: [src]};\n } else if (src.startsWith('bq://')) {\n sourceObj = {format: 'bigquery', bigqueryUri: src};\n } else {\n throw new Error(`Unsupported string source for Vertex AI: ${src}`);\n }\n } else {\n // MLDEV\n if (src.startsWith('files/')) {\n sourceObj = {fileName: src}; // Default to fileName for string input\n } else {\n throw new Error(`Unsupported string source for Gemini API: ${src}`);\n }\n }\n } else if (Array.isArray(src)) {\n if (client.isVertexAI()) {\n throw new Error('InlinedRequest[] is not supported in Vertex AI.');\n }\n sourceObj = {inlinedRequests: src};\n } else {\n // It's already a BatchJobSource object\n sourceObj = src;\n }\n\n // Validation logic\n const vertexSourcesCount = [sourceObj.gcsUri, sourceObj.bigqueryUri].filter(\n Boolean,\n ).length;\n\n const mldevSourcesCount = [\n sourceObj.inlinedRequests,\n sourceObj.fileName,\n ].filter(Boolean).length;\n\n if (client.isVertexAI()) {\n if (mldevSourcesCount > 0 || vertexSourcesCount !== 1) {\n throw new Error(\n 'Exactly one of `gcsUri` or `bigqueryUri` must be set for Vertex AI.',\n );\n }\n } else {\n // MLDEV\n if (vertexSourcesCount > 0 || mldevSourcesCount !== 1) {\n throw new Error(\n 'Exactly one of `inlinedRequests`, `fileName`, ' +\n 'must be set for Gemini API.',\n );\n }\n }\n\n return sourceObj;\n}\n\nexport function tEmbeddingBatchJobSource(\n client: ApiClient,\n src: types.EmbeddingsBatchJobSource,\n): types.EmbeddingsBatchJobSource {\n if (client.isVertexAI()) {\n throw new Error('Embedding batch jobs are not supported in Vertex AI.');\n }\n\n const sourceObj: types.EmbeddingsBatchJobSource = {...src};\n\n const mldevSources =\n Number(!!sourceObj.inlinedRequests) + Number(!!sourceObj.fileName);\n\n if (mldevSources !== 1) {\n throw new Error(\n 'Exactly one of `inlinedRequests` or `fileName` must be set for Embedding Batch Jobs in the Gemini API.',\n );\n }\n return sourceObj;\n}\n\nexport function tBatchJobDestination(\n dest: string | types.BatchJobDestination,\n): types.BatchJobDestination {\n if (typeof dest !== 'string') {\n return dest as types.BatchJobDestination;\n }\n const destString = dest as string;\n if (destString.startsWith('gs://')) {\n return {\n format: 'jsonl',\n gcsUri: destString,\n };\n } else if (destString.startsWith('bq://')) {\n return {\n format: 'bigquery',\n bigqueryUri: destString,\n };\n } else {\n throw new Error(`Unsupported destination: ${destString}`);\n }\n}\n\nexport function tRecvBatchJobDestination(\n dest: unknown,\n): types.BatchJobDestination {\n // Ensure dest is a non-null object before proceeding.\n if (typeof dest !== 'object' || dest === null) {\n // If the input is not an object, it cannot be a valid BatchJobDestination\n // based on the operations performed. Return it cast, or handle as an error.\n // Casting an empty object might be a safe default.\n return {} as types.BatchJobDestination;\n }\n\n // Cast to Record<string, unknown> to allow string property access.\n const obj = dest as Record<string, unknown>;\n\n // Safely access nested properties.\n const inlineResponsesVal = obj['inlinedResponses'];\n if (typeof inlineResponsesVal !== 'object' || inlineResponsesVal === null) {\n return dest as types.BatchJobDestination;\n }\n const inlineResponsesObj = inlineResponsesVal as Record<string, unknown>;\n\n const responsesArray = inlineResponsesObj['inlinedResponses'];\n if (!Array.isArray(responsesArray) || responsesArray.length === 0) {\n return dest as types.BatchJobDestination;\n }\n\n // Check if any response has the 'embedding' property.\n let hasEmbedding = false;\n for (const responseItem of responsesArray) {\n if (typeof responseItem !== 'object' || responseItem === null) {\n continue;\n }\n const responseItemObj = responseItem as Record<string, unknown>;\n\n const responseVal = responseItemObj['response'];\n if (typeof responseVal !== 'object' || responseVal === null) {\n continue;\n }\n const responseObj = responseVal as Record<string, unknown>;\n\n // Check for the existence of the 'embedding' key.\n if (responseObj['embedding'] !== undefined) {\n hasEmbedding = true;\n break;\n }\n }\n\n // Perform the transformation if an embedding was found.\n if (hasEmbedding) {\n obj['inlinedEmbedContentResponses'] = obj['inlinedResponses'];\n delete obj['inlinedResponses'];\n }\n\n // Cast the (potentially) modified object to the target type.\n return dest as types.BatchJobDestination;\n}\n\nexport function tBatchJobName(apiClient: ApiClient, name: unknown): string {\n const nameString = name as string;\n if (!apiClient.isVertexAI()) {\n const mldevPattern = /batches\\/[^/]+$/;\n\n if (mldevPattern.test(nameString)) {\n return nameString.split('/').pop() as string;\n } else {\n throw new Error(`Invalid batch job name: ${nameString}.`);\n }\n }\n\n const vertexPattern =\n /^projects\\/[^/]+\\/locations\\/[^/]+\\/batchPredictionJobs\\/[^/]+$/;\n\n if (vertexPattern.test(nameString)) {\n return nameString.split('/').pop() as string;\n } else if (/^\\d+$/.test(nameString)) {\n return nameString;\n } else {\n throw new Error(`Invalid batch job name: ${nameString}.`);\n }\n}\n\nexport function tJobState(state: unknown): string {\n const stateString = state as string;\n if (stateString === 'BATCH_STATE_UNSPECIFIED') {\n return 'JOB_STATE_UNSPECIFIED';\n } else if (stateString === 'BATCH_STATE_PENDING') {\n return 'JOB_STATE_PENDING';\n } else if (stateString === 'BATCH_STATE_RUNNING') {\n return 'JOB_STATE_RUNNING';\n } else if (stateString === 'BATCH_STATE_SUCCEEDED') {\n return 'JOB_STATE_SUCCEEDED';\n } else if (stateString === 'BATCH_STATE_FAILED') {\n return 'JOB_STATE_FAILED';\n } else if (stateString === 'BATCH_STATE_CANCELLED') {\n return 'JOB_STATE_CANCELLED';\n } else if (stateString === 'BATCH_STATE_EXPIRED') {\n return 'JOB_STATE_EXPIRED';\n } else {\n return stateString;\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * TypeScript representation of the SentencePiece model protobuf.\n * Translated from sentencepiece_model.proto\n */\n\nexport enum ModelType {\n UNIGRAM = 1,\n BPE = 2,\n WORD = 3,\n CHAR = 4,\n}\n\nexport enum SentencePieceType {\n NORMAL = 1,\n UNKNOWN = 2,\n CONTROL = 3,\n USER_DEFINED = 4,\n BYTE = 6,\n UNUSED = 5,\n}\n\nexport interface TrainerSpec {\n modelType?: ModelType;\n vocabSize?: number;\n characterCoverage?: number;\n byteFallback?: boolean;\n unkSurface?: string;\n // Add other fields as needed\n}\n\nexport interface NormalizerSpec {\n name?: string;\n precompiledCharsmap?: Uint8Array;\n addDummyPrefix?: boolean;\n removeExtraWhitespaces?: boolean;\n escapeWhitespaces?: boolean;\n normalizationRuleTsv?: string;\n}\n\nexport interface SentencePiece {\n piece?: string;\n score?: number;\n type?: SentencePieceType;\n}\n\nexport interface ModelProto {\n pieces?: SentencePiece[];\n trainerSpec?: TrainerSpec;\n normalizerSpec?: NormalizerSpec;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * PrefixMatcher helps find longest prefixes using a trie data structure.\n * Translated from go-sentencepiece/internal/prefixmatcher\n */\n\ninterface TrieNode {\n children: Map<string, TrieNode>;\n final: boolean;\n}\n\nfunction newTrieNode(): TrieNode {\n return {\n children: new Map(),\n final: false,\n };\n}\n\n/**\n * PrefixMatcher finds the longest prefix of a string that matches\n * a vocabulary word using a trie data structure.\n */\nexport class PrefixMatcher {\n private root: TrieNode;\n\n /**\n * Creates a new PrefixMatcher from a set of vocabulary strings.\n */\n constructor(vocab: Set<string>) {\n this.root = newTrieNode();\n for (const word of vocab) {\n this.add(word);\n }\n }\n\n /**\n * Finds the longest prefix of text that matches a vocabulary word.\n * Returns the length of the prefix, or 0 if no prefix was found.\n */\n findPrefixLen(text: string): number {\n let node = this.root;\n let maxLen = 0;\n\n let i = 0;\n for (const char of text) {\n const child = node.children.get(char);\n if (!child) {\n return maxLen;\n }\n if (child.final) {\n maxLen = i + 1;\n }\n node = child;\n i++;\n }\n\n return maxLen;\n }\n\n /**\n * Adds a word to the trie.\n */\n private add(word: string): void {\n let node = this.root;\n\n for (const char of word) {\n let child = node.children.get(char);\n if (!child) {\n child = newTrieNode();\n node.children.set(char, child);\n }\n node = child;\n }\n\n node.final = true;\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Generic priority queue with Insert, PopMax, and RemoveFunc operations.\n * Translated from go-sentencepiece/internal/priorityqueue\n *\n * Uses a binary heap data structure where items[0] is unused,\n * and elements are stored at indices 1...N.\n */\nexport class PriorityQueue<T> {\n private cmp: (a: T, b: T) => number;\n private items: T[];\n\n /**\n * Creates a new PriorityQueue.\n *\n * @param sizeHint Initial capacity hint for the queue\n * @param cmp Comparison function that returns > 0 if a has higher priority than b,\n * 0 if equal priority, < 0 otherwise\n */\n constructor(sizeHint: number, cmp: (a: T, b: T) => number) {\n this.cmp = cmp;\n this.items = new Array(Math.max(1, sizeHint + 1));\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this.items[0] = null as any;\n this.items.length = 1;\n }\n\n /**\n * Returns the number of items in the queue.\n */\n len(): number {\n return this.items.length - 1;\n }\n\n /**\n * Inserts a new element into the priority queue.\n */\n insert(elem: T): void {\n this.items.push(elem);\n this.siftUp(this.items.length - 1);\n }\n\n /**\n * Returns and removes the element with the maximal priority.\n * Throws if the queue is empty.\n */\n popMax(): T {\n if (this.items.length < 2) {\n throw new Error('popping from empty priority queue');\n }\n const maxItem = this.items[1];\n this.items[1] = this.items[this.items.length - 1];\n this.items.pop();\n if (this.items.length > 1) {\n this.siftDown(1);\n }\n return maxItem;\n }\n\n /**\n * Removes all elements for which the predicate returns true.\n */\n removeFunc(rm: (elem: T) => boolean): void {\n let i = 1;\n while (i < this.items.length && !rm(this.items[i])) {\n i++;\n }\n if (i === this.items.length) {\n return;\n }\n\n for (let j = i + 1; j < this.items.length; j++) {\n if (!rm(this.items[j])) {\n this.items[i] = this.items[j];\n i++;\n }\n }\n\n this.items.length = i;\n\n this.rebuildHeap();\n }\n\n /**\n * Rebuilds the entire heap from scratch.\n */\n private rebuildHeap(): void {\n for (let i = Math.floor(this.items.length / 2); i >= 1; i--) {\n this.siftDown(i);\n }\n }\n\n /**\n * Moves an element up the heap until heap property is restored.\n */\n private siftUp(n: number): void {\n let i = n;\n while (i > 1) {\n const p = Math.floor(i / 2);\n if (this.cmp(this.items[p], this.items[i]) >= 0) {\n return;\n }\n [this.items[i], this.items[p]] = [this.items[p], this.items[i]];\n i = p;\n }\n }\n\n /**\n * Moves an element down the heap until heap property is restored.\n */\n private siftDown(i: number): void {\n // eslint-disable-next-line\n while (true) {\n const c = 2 * i;\n if (c >= this.items.length) {\n return;\n }\n\n let maxChild = c;\n if (c + 1 < this.items.length) {\n if (this.cmp(this.items[c + 1], this.items[c]) > 0) {\n maxChild = c + 1;\n }\n }\n\n if (this.cmp(this.items[i], this.items[maxChild]) >= 0) {\n return;\n }\n\n [this.items[i], this.items[maxChild]] = [\n this.items[maxChild],\n this.items[i],\n ];\n i = maxChild;\n }\n }\n}\n","/*eslint-disable block-scoped-var, id-length, no-control-regex,\n * no-magic-numbers, no-prototype-builtins, no-redeclare, no-shadow, no-var,\n * sort-vars*/\n\n/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport $protobuf from 'protobufjs/minimal.js';\n\n// Common aliases\nconst $Reader = $protobuf.Reader, $Writer = $protobuf.Writer,\n $util = $protobuf.util;\n\n// Exported root namespace\nconst $root = $protobuf.roots['default'] || ($protobuf.roots['default'] = {});\n\nexport const sentencepiece = $root.sentencepiece = (() => {\n /**\n * Namespace sentencepiece.\n * @exports sentencepiece\n * @namespace\n */\n const sentencepiece = {};\n\n sentencepiece.TrainerSpec = (function() {\n /**\n * Properties of a TrainerSpec.\n * @memberof sentencepiece\n * @interface ITrainerSpec\n * @property {Array.<string>|null} [input] TrainerSpec input\n * @property {string|null} [inputFormat] TrainerSpec inputFormat\n * @property {string|null} [modelPrefix] TrainerSpec modelPrefix\n * @property {sentencepiece.TrainerSpec.ModelType|null} [modelType]\n * TrainerSpec modelType\n * @property {number|null} [vocabSize] TrainerSpec vocabSize\n * @property {Array.<string>|null} [acceptLanguage] TrainerSpec\n * acceptLanguage\n * @property {number|null} [selfTestSampleSize] TrainerSpec\n * selfTestSampleSize\n * @property {boolean|null} [enableDifferentialPrivacy] TrainerSpec\n * enableDifferentialPrivacy\n * @property {number|null} [differentialPrivacyNoiseLevel] TrainerSpec\n * differentialPrivacyNoiseLevel\n * @property {number|Long|null} [differentialPrivacyClippingThreshold]\n * TrainerSpec differentialPrivacyClippingThreshold\n * @property {number|null} [characterCoverage] TrainerSpec characterCoverage\n * @property {number|Long|null} [inputSentenceSize] TrainerSpec\n * inputSentenceSize\n * @property {boolean|null} [shuffleInputSentence] TrainerSpec\n * shuffleInputSentence\n * @property {number|null} [miningSentenceSize] TrainerSpec\n * miningSentenceSize\n * @property {number|null} [trainingSentenceSize] TrainerSpec\n * trainingSentenceSize\n * @property {number|null} [seedSentencepieceSize] TrainerSpec\n * seedSentencepieceSize\n * @property {number|null} [shrinkingFactor] TrainerSpec shrinkingFactor\n * @property {number|null} [maxSentenceLength] TrainerSpec maxSentenceLength\n * @property {number|null} [numThreads] TrainerSpec numThreads\n * @property {number|null} [numSubIterations] TrainerSpec numSubIterations\n * @property {number|null} [maxSentencepieceLength] TrainerSpec\n * maxSentencepieceLength\n * @property {boolean|null} [splitByUnicodeScript] TrainerSpec\n * splitByUnicodeScript\n * @property {boolean|null} [splitByNumber] TrainerSpec splitByNumber\n * @property {boolean|null} [splitByWhitespace] TrainerSpec\n * splitByWhitespace\n * @property {boolean|null} [treatWhitespaceAsSuffix] TrainerSpec\n * treatWhitespaceAsSuffix\n * @property {boolean|null} [allowWhitespaceOnlyPieces] TrainerSpec\n * allowWhitespaceOnlyPieces\n * @property {boolean|null} [splitDigits] TrainerSpec splitDigits\n * @property {string|null} [pretokenizationDelimiter] TrainerSpec\n * pretokenizationDelimiter\n * @property {Array.<string>|null} [controlSymbols] TrainerSpec\n * controlSymbols\n * @property {Array.<string>|null} [userDefinedSymbols] TrainerSpec\n * userDefinedSymbols\n * @property {string|null} [requiredChars] TrainerSpec requiredChars\n * @property {boolean|null} [byteFallback] TrainerSpec byteFallback\n * @property {boolean|null} [vocabularyOutputPieceScore] TrainerSpec\n * vocabularyOutputPieceScore\n * @property {boolean|null} [hardVocabLimit] TrainerSpec hardVocabLimit\n * @property {boolean|null} [useAllVocab] TrainerSpec useAllVocab\n * @property {number|null} [unkId] TrainerSpec unkId\n * @property {number|null} [bosId] TrainerSpec bosId\n * @property {number|null} [eosId] TrainerSpec eosId\n * @property {number|null} [padId] TrainerSpec padId\n * @property {string|null} [unkPiece] TrainerSpec unkPiece\n * @property {string|null} [bosPiece] TrainerSpec bosPiece\n * @property {string|null} [eosPiece] TrainerSpec eosPiece\n * @property {string|null} [padPiece] TrainerSpec padPiece\n * @property {string|null} [unkSurface] TrainerSpec unkSurface\n * @property {boolean|null} [trainExtremelyLargeCorpus] TrainerSpec\n * trainExtremelyLargeCorpus\n * @property {string|null} [seedSentencepiecesFile] TrainerSpec\n * seedSentencepiecesFile\n */\n\n /**\n * Constructs a new TrainerSpec.\n * @memberof sentencepiece\n * @classdesc Represents a TrainerSpec.\n * @implements ITrainerSpec\n * @constructor\n * @param {sentencepiece.ITrainerSpec=} [properties] Properties to set\n */\n function TrainerSpec(properties) {\n this.input = [];\n this.acceptLanguage = [];\n this.controlSymbols = [];\n this.userDefinedSymbols = [];\n if (properties)\n for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i)\n if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]];\n }\n\n /**\n * TrainerSpec input.\n * @member {Array.<string>} input\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.input = $util.emptyArray;\n\n /**\n * TrainerSpec inputFormat.\n * @member {string} inputFormat\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.inputFormat = '';\n\n /**\n * TrainerSpec modelPrefix.\n * @member {string} modelPrefix\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.modelPrefix = '';\n\n /**\n * TrainerSpec modelType.\n * @member {sentencepiece.TrainerSpec.ModelType} modelType\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.modelType = 1;\n\n /**\n * TrainerSpec vocabSize.\n * @member {number} vocabSize\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.vocabSize = 8000;\n\n /**\n * TrainerSpec acceptLanguage.\n * @member {Array.<string>} acceptLanguage\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.acceptLanguage = $util.emptyArray;\n\n /**\n * TrainerSpec selfTestSampleSize.\n * @member {number} selfTestSampleSize\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.selfTestSampleSize = 0;\n\n /**\n * TrainerSpec enableDifferentialPrivacy.\n * @member {boolean} enableDifferentialPrivacy\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.enableDifferentialPrivacy = false;\n\n /**\n * TrainerSpec differentialPrivacyNoiseLevel.\n * @member {number} differentialPrivacyNoiseLevel\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.differentialPrivacyNoiseLevel = 0;\n\n /**\n * TrainerSpec differentialPrivacyClippingThreshold.\n * @member {number|Long} differentialPrivacyClippingThreshold\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.differentialPrivacyClippingThreshold =\n $util.Long ? $util.Long.fromBits(0, 0, true) : 0;\n\n /**\n * TrainerSpec characterCoverage.\n * @member {number} characterCoverage\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.characterCoverage = 0.9995;\n\n /**\n * TrainerSpec inputSentenceSize.\n * @member {number|Long} inputSentenceSize\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.inputSentenceSize =\n $util.Long ? $util.Long.fromBits(0, 0, true) : 0;\n\n /**\n * TrainerSpec shuffleInputSentence.\n * @member {boolean} shuffleInputSentence\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.shuffleInputSentence = true;\n\n /**\n * TrainerSpec miningSentenceSize.\n * @member {number} miningSentenceSize\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.miningSentenceSize = 0;\n\n /**\n * TrainerSpec trainingSentenceSize.\n * @member {number} trainingSentenceSize\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.trainingSentenceSize = 0;\n\n /**\n * TrainerSpec seedSentencepieceSize.\n * @member {number} seedSentencepieceSize\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.seedSentencepieceSize = 1000000;\n\n /**\n * TrainerSpec shrinkingFactor.\n * @member {number} shrinkingFactor\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.shrinkingFactor = 0.75;\n\n /**\n * TrainerSpec maxSentenceLength.\n * @member {number} maxSentenceLength\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.maxSentenceLength = 4192;\n\n /**\n * TrainerSpec numThreads.\n * @member {number} numThreads\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.numThreads = 16;\n\n /**\n * TrainerSpec numSubIterations.\n * @member {number} numSubIterations\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.numSubIterations = 2;\n\n /**\n * TrainerSpec maxSentencepieceLength.\n * @member {number} maxSentencepieceLength\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.maxSentencepieceLength = 16;\n\n /**\n * TrainerSpec splitByUnicodeScript.\n * @member {boolean} splitByUnicodeScript\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.splitByUnicodeScript = true;\n\n /**\n * TrainerSpec splitByNumber.\n * @member {boolean} splitByNumber\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.splitByNumber = true;\n\n /**\n * TrainerSpec splitByWhitespace.\n * @member {boolean} splitByWhitespace\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.splitByWhitespace = true;\n\n /**\n * TrainerSpec treatWhitespaceAsSuffix.\n * @member {boolean} treatWhitespaceAsSuffix\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.treatWhitespaceAsSuffix = false;\n\n /**\n * TrainerSpec allowWhitespaceOnlyPieces.\n * @member {boolean} allowWhitespaceOnlyPieces\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.allowWhitespaceOnlyPieces = false;\n\n /**\n * TrainerSpec splitDigits.\n * @member {boolean} splitDigits\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.splitDigits = false;\n\n /**\n * TrainerSpec pretokenizationDelimiter.\n * @member {string} pretokenizationDelimiter\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.pretokenizationDelimiter = '';\n\n /**\n * TrainerSpec controlSymbols.\n * @member {Array.<string>} controlSymbols\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.controlSymbols = $util.emptyArray;\n\n /**\n * TrainerSpec userDefinedSymbols.\n * @member {Array.<string>} userDefinedSymbols\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.userDefinedSymbols = $util.emptyArray;\n\n /**\n * TrainerSpec requiredChars.\n * @member {string} requiredChars\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.requiredChars = '';\n\n /**\n * TrainerSpec byteFallback.\n * @member {boolean} byteFallback\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.byteFallback = false;\n\n /**\n * TrainerSpec vocabularyOutputPieceScore.\n * @member {boolean} vocabularyOutputPieceScore\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.vocabularyOutputPieceScore = true;\n\n /**\n * TrainerSpec hardVocabLimit.\n * @member {boolean} hardVocabLimit\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.hardVocabLimit = true;\n\n /**\n * TrainerSpec useAllVocab.\n * @member {boolean} useAllVocab\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.useAllVocab = false;\n\n /**\n * TrainerSpec unkId.\n * @member {number} unkId\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.unkId = 0;\n\n /**\n * TrainerSpec bosId.\n * @member {number} bosId\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.bosId = 1;\n\n /**\n * TrainerSpec eosId.\n * @member {number} eosId\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.eosId = 2;\n\n /**\n * TrainerSpec padId.\n * @member {number} padId\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.padId = -1;\n\n /**\n * TrainerSpec unkPiece.\n * @member {string} unkPiece\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.unkPiece = '<unk>';\n\n /**\n * TrainerSpec bosPiece.\n * @member {string} bosPiece\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.bosPiece = '<s>';\n\n /**\n * TrainerSpec eosPiece.\n * @member {string} eosPiece\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.eosPiece = '</s>';\n\n /**\n * TrainerSpec padPiece.\n * @member {string} padPiece\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.padPiece = '<pad>';\n\n /**\n * TrainerSpec unkSurface.\n * @member {string} unkSurface\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.unkSurface = ' E28187 ';\n\n /**\n * TrainerSpec trainExtremelyLargeCorpus.\n * @member {boolean} trainExtremelyLargeCorpus\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.trainExtremelyLargeCorpus = false;\n\n /**\n * TrainerSpec seedSentencepiecesFile.\n * @member {string} seedSentencepiecesFile\n * @memberof sentencepiece.TrainerSpec\n * @instance\n */\n TrainerSpec.prototype.seedSentencepiecesFile = '';\n\n /**\n * Creates a new TrainerSpec instance using the specified properties.\n * @function create\n * @memberof sentencepiece.TrainerSpec\n * @static\n * @param {sentencepiece.ITrainerSpec=} [properties] Properties to set\n * @returns {sentencepiece.TrainerSpec} TrainerSpec instance\n */\n TrainerSpec.create = function create(properties) {\n return new TrainerSpec(properties);\n };\n\n /**\n * Encodes the specified TrainerSpec message. Does not implicitly {@link\n * sentencepiece.TrainerSpec.verify|verify} messages.\n * @function encode\n * @memberof sentencepiece.TrainerSpec\n * @static\n * @param {sentencepiece.ITrainerSpec} message TrainerSpec message or plain\n * object to encode\n * @param {$protobuf.Writer} [writer] Writer to encode to\n * @returns {$protobuf.Writer} Writer\n */\n TrainerSpec.encode = function encode(message, writer) {\n if (!writer) writer = $Writer.create();\n if (message.input != null && message.input.length)\n for (let i = 0; i < message.input.length; ++i)\n writer.uint32(/* id 1, wireType 2 =*/ 10).string(message.input[i]);\n if (message.modelPrefix != null &&\n Object.hasOwnProperty.call(message, 'modelPrefix'))\n writer.uint32(/* id 2, wireType 2 =*/ 18).string(message.modelPrefix);\n if (message.modelType != null &&\n Object.hasOwnProperty.call(message, 'modelType'))\n writer.uint32(/* id 3, wireType 0 =*/ 24).int32(message.modelType);\n if (message.vocabSize != null &&\n Object.hasOwnProperty.call(message, 'vocabSize'))\n writer.uint32(/* id 4, wireType 0 =*/ 32).int32(message.vocabSize);\n if (message.acceptLanguage != null && message.acceptLanguage.length)\n for (let i = 0; i < message.acceptLanguage.length; ++i)\n writer.uint32(/* id 5, wireType 2 =*/ 42)\n .string(message.acceptLanguage[i]);\n if (message.selfTestSampleSize != null &&\n Object.hasOwnProperty.call(message, 'selfTestSampleSize'))\n writer.uint32(/* id 6, wireType 0 =*/ 48)\n .int32(message.selfTestSampleSize);\n if (message.inputFormat != null &&\n Object.hasOwnProperty.call(message, 'inputFormat'))\n writer.uint32(/* id 7, wireType 2 =*/ 58).string(message.inputFormat);\n if (message.characterCoverage != null &&\n Object.hasOwnProperty.call(message, 'characterCoverage'))\n writer.uint32(/* id 10, wireType 5 =*/ 85)\n .float(message.characterCoverage);\n if (message.inputSentenceSize != null &&\n Object.hasOwnProperty.call(message, 'inputSentenceSize'))\n writer.uint32(/* id 11, wireType 0 =*/ 88)\n .uint64(message.inputSentenceSize);\n if (message.miningSentenceSize != null &&\n Object.hasOwnProperty.call(message, 'miningSentenceSize'))\n writer.uint32(/* id 12, wireType 0 =*/ 96)\n .int32(message.miningSentenceSize);\n if (message.trainingSentenceSize != null &&\n Object.hasOwnProperty.call(message, 'trainingSentenceSize'))\n writer.uint32(/* id 13, wireType 0 =*/ 104)\n .int32(message.trainingSentenceSize);\n if (message.seedSentencepieceSize != null &&\n Object.hasOwnProperty.call(message, 'seedSentencepieceSize'))\n writer.uint32(/* id 14, wireType 0 =*/ 112)\n .int32(message.seedSentencepieceSize);\n if (message.shrinkingFactor != null &&\n Object.hasOwnProperty.call(message, 'shrinkingFactor'))\n writer.uint32(/* id 15, wireType 5 =*/ 125)\n .float(message.shrinkingFactor);\n if (message.numThreads != null &&\n Object.hasOwnProperty.call(message, 'numThreads'))\n writer.uint32(/* id 16, wireType 0 =*/ 128).int32(message.numThreads);\n if (message.numSubIterations != null &&\n Object.hasOwnProperty.call(message, 'numSubIterations'))\n writer.uint32(/* id 17, wireType 0 =*/ 136)\n .int32(message.numSubIterations);\n if (message.maxSentenceLength != null &&\n Object.hasOwnProperty.call(message, 'maxSentenceLength'))\n writer.uint32(/* id 18, wireType 0 =*/ 144)\n .int32(message.maxSentenceLength);\n if (message.shuffleInputSentence != null &&\n Object.hasOwnProperty.call(message, 'shuffleInputSentence'))\n writer.uint32(/* id 19, wireType 0 =*/ 152)\n .bool(message.shuffleInputSentence);\n if (message.maxSentencepieceLength != null &&\n Object.hasOwnProperty.call(message, 'maxSentencepieceLength'))\n writer.uint32(/* id 20, wireType 0 =*/ 160)\n .int32(message.maxSentencepieceLength);\n if (message.splitByUnicodeScript != null &&\n Object.hasOwnProperty.call(message, 'splitByUnicodeScript'))\n writer.uint32(/* id 21, wireType 0 =*/ 168)\n .bool(message.splitByUnicodeScript);\n if (message.splitByWhitespace != null &&\n Object.hasOwnProperty.call(message, 'splitByWhitespace'))\n writer.uint32(/* id 22, wireType 0 =*/ 176)\n .bool(message.splitByWhitespace);\n if (message.splitByNumber != null &&\n Object.hasOwnProperty.call(message, 'splitByNumber'))\n writer.uint32(/* id 23, wireType 0 =*/ 184).bool(message.splitByNumber);\n if (message.treatWhitespaceAsSuffix != null &&\n Object.hasOwnProperty.call(message, 'treatWhitespaceAsSuffix'))\n writer.uint32(/* id 24, wireType 0 =*/ 192)\n .bool(message.treatWhitespaceAsSuffix);\n if (message.splitDigits != null &&\n Object.hasOwnProperty.call(message, 'splitDigits'))\n writer.uint32(/* id 25, wireType 0 =*/ 200).bool(message.splitDigits);\n if (message.allowWhitespaceOnlyPieces != null &&\n Object.hasOwnProperty.call(message, 'allowWhitespaceOnlyPieces'))\n writer.uint32(/* id 26, wireType 0 =*/ 208)\n .bool(message.allowWhitespaceOnlyPieces);\n if (message.controlSymbols != null && message.controlSymbols.length)\n for (let i = 0; i < message.controlSymbols.length; ++i)\n writer.uint32(/* id 30, wireType 2 =*/ 242)\n .string(message.controlSymbols[i]);\n if (message.userDefinedSymbols != null &&\n message.userDefinedSymbols.length)\n for (let i = 0; i < message.userDefinedSymbols.length; ++i)\n writer.uint32(/* id 31, wireType 2 =*/ 250)\n .string(message.userDefinedSymbols[i]);\n if (message.vocabularyOutputPieceScore != null &&\n Object.hasOwnProperty.call(message, 'vocabularyOutputPieceScore'))\n writer.uint32(/* id 32, wireType 0 =*/ 256)\n .bool(message.vocabularyOutputPieceScore);\n if (message.hardVocabLimit != null &&\n Object.hasOwnProperty.call(message, 'hardVocabLimit'))\n writer.uint32(/* id 33, wireType 0 =*/ 264)\n .bool(message.hardVocabLimit);\n if (message.useAllVocab != null &&\n Object.hasOwnProperty.call(message, 'useAllVocab'))\n writer.uint32(/* id 34, wireType 0 =*/ 272).bool(message.useAllVocab);\n if (message.byteFallback != null &&\n Object.hasOwnProperty.call(message, 'byteFallback'))\n writer.uint32(/* id 35, wireType 0 =*/ 280).bool(message.byteFallback);\n if (message.requiredChars != null &&\n Object.hasOwnProperty.call(message, 'requiredChars'))\n writer.uint32(/* id 36, wireType 2 =*/ 290)\n .string(message.requiredChars);\n if (message.unkId != null && Object.hasOwnProperty.call(message, 'unkId'))\n writer.uint32(/* id 40, wireType 0 =*/ 320).int32(message.unkId);\n if (message.bosId != null && Object.hasOwnProperty.call(message, 'bosId'))\n writer.uint32(/* id 41, wireType 0 =*/ 328).int32(message.bosId);\n if (message.eosId != null && Object.hasOwnProperty.call(message, 'eosId'))\n writer.uint32(/* id 42, wireType 0 =*/ 336).int32(message.eosId);\n if (message.padId != null && Object.hasOwnProperty.call(message, 'padId'))\n writer.uint32(/* id 43, wireType 0 =*/ 344).int32(message.padId);\n if (message.unkSurface != null &&\n Object.hasOwnProperty.call(message, 'unkSurface'))\n writer.uint32(/* id 44, wireType 2 =*/ 354).string(message.unkSurface);\n if (message.unkPiece != null &&\n Object.hasOwnProperty.call(message, 'unkPiece'))\n writer.uint32(/* id 45, wireType 2 =*/ 362).string(message.unkPiece);\n if (message.bosPiece != null &&\n Object.hasOwnProperty.call(message, 'bosPiece'))\n writer.uint32(/* id 46, wireType 2 =*/ 370).string(message.bosPiece);\n if (message.eosPiece != null &&\n Object.hasOwnProperty.call(message, 'eosPiece'))\n writer.uint32(/* id 47, wireType 2 =*/ 378).string(message.eosPiece);\n if (message.padPiece != null &&\n Object.hasOwnProperty.call(message, 'padPiece'))\n writer.uint32(/* id 48, wireType 2 =*/ 386).string(message.padPiece);\n if (message.trainExtremelyLargeCorpus != null &&\n Object.hasOwnProperty.call(message, 'trainExtremelyLargeCorpus'))\n writer.uint32(/* id 49, wireType 0 =*/ 392)\n .bool(message.trainExtremelyLargeCorpus);\n if (message.enableDifferentialPrivacy != null &&\n Object.hasOwnProperty.call(message, 'enableDifferentialPrivacy'))\n writer.uint32(/* id 50, wireType 0 =*/ 400)\n .bool(message.enableDifferentialPrivacy);\n if (message.differentialPrivacyNoiseLevel != null &&\n Object.hasOwnProperty.call(message, 'differentialPrivacyNoiseLevel'))\n writer.uint32(/* id 51, wireType 5 =*/ 413)\n .float(message.differentialPrivacyNoiseLevel);\n if (message.differentialPrivacyClippingThreshold != null &&\n Object.hasOwnProperty.call(\n message, 'differentialPrivacyClippingThreshold'))\n writer.uint32(/* id 52, wireType 0 =*/ 416)\n .uint64(message.differentialPrivacyClippingThreshold);\n if (message.pretokenizationDelimiter != null &&\n Object.hasOwnProperty.call(message, 'pretokenizationDelimiter'))\n writer.uint32(/* id 53, wireType 2 =*/ 426)\n .string(message.pretokenizationDelimiter);\n if (message.seedSentencepiecesFile != null &&\n Object.hasOwnProperty.call(message, 'seedSentencepiecesFile'))\n writer.uint32(/* id 54, wireType 2 =*/ 434)\n .string(message.seedSentencepiecesFile);\n return writer;\n };\n\n /**\n * Encodes the specified TrainerSpec message, length delimited. Does not\n * implicitly {@link sentencepiece.TrainerSpec.verify|verify} messages.\n * @function encodeDelimited\n * @memberof sentencepiece.TrainerSpec\n * @static\n * @param {sentencepiece.ITrainerSpec} message TrainerSpec message or plain\n * object to encode\n * @param {$protobuf.Writer} [writer] Writer to encode to\n * @returns {$protobuf.Writer} Writer\n */\n TrainerSpec.encodeDelimited = function encodeDelimited(message, writer) {\n return this.encode(message, writer).ldelim();\n };\n\n /**\n * Decodes a TrainerSpec message from the specified reader or buffer.\n * @function decode\n * @memberof sentencepiece.TrainerSpec\n * @static\n * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode\n * from\n * @param {number} [length] Message length if known beforehand\n * @returns {sentencepiece.TrainerSpec} TrainerSpec\n * @throws {Error} If the payload is not a reader or valid buffer\n * @throws {$protobuf.util.ProtocolError} If required fields are missing\n */\n TrainerSpec.decode = function decode(reader, length, error) {\n if (!(reader instanceof $Reader)) reader = $Reader.create(reader);\n let end = length === undefined ? reader.len : reader.pos + length,\n message = new $root.sentencepiece.TrainerSpec();\n while (reader.pos < end) {\n let tag = reader.uint32();\n if (tag === error) break;\n switch (tag >>> 3) {\n case 1: {\n if (!(message.input && message.input.length)) message.input = [];\n message.input.push(reader.string());\n break;\n }\n case 7: {\n message.inputFormat = reader.string();\n break;\n }\n case 2: {\n message.modelPrefix = reader.string();\n break;\n }\n case 3: {\n message.modelType = reader.int32();\n break;\n }\n case 4: {\n message.vocabSize = reader.int32();\n break;\n }\n case 5: {\n if (!(message.acceptLanguage && message.acceptLanguage.length))\n message.acceptLanguage = [];\n message.acceptLanguage.push(reader.string());\n break;\n }\n case 6: {\n message.selfTestSampleSize = reader.int32();\n break;\n }\n case 50: {\n message.enableDifferentialPrivacy = reader.bool();\n break;\n }\n case 51: {\n message.differentialPrivacyNoiseLevel = reader.float();\n break;\n }\n case 52: {\n message.differentialPrivacyClippingThreshold = reader.uint64();\n break;\n }\n case 10: {\n message.characterCoverage = reader.float();\n break;\n }\n case 11: {\n message.inputSentenceSize = reader.uint64();\n break;\n }\n case 19: {\n message.shuffleInputSentence = reader.bool();\n break;\n }\n case 12: {\n message.miningSentenceSize = reader.int32();\n break;\n }\n case 13: {\n message.trainingSentenceSize = reader.int32();\n break;\n }\n case 14: {\n message.seedSentencepieceSize = reader.int32();\n break;\n }\n case 15: {\n message.shrinkingFactor = reader.float();\n break;\n }\n case 18: {\n message.maxSentenceLength = reader.int32();\n break;\n }\n case 16: {\n message.numThreads = reader.int32();\n break;\n }\n case 17: {\n message.numSubIterations = reader.int32();\n break;\n }\n case 20: {\n message.maxSentencepieceLength = reader.int32();\n break;\n }\n case 21: {\n message.splitByUnicodeScript = reader.bool();\n break;\n }\n case 23: {\n message.splitByNumber = reader.bool();\n break;\n }\n case 22: {\n message.splitByWhitespace = reader.bool();\n break;\n }\n case 24: {\n message.treatWhitespaceAsSuffix = reader.bool();\n break;\n }\n case 26: {\n message.allowWhitespaceOnlyPieces = reader.bool();\n break;\n }\n case 25: {\n message.splitDigits = reader.bool();\n break;\n }\n case 53: {\n message.pretokenizationDelimiter = reader.string();\n break;\n }\n case 30: {\n if (!(message.controlSymbols && message.controlSymbols.length))\n message.controlSymbols = [];\n message.controlSymbols.push(reader.string());\n break;\n }\n case 31: {\n if (!(message.userDefinedSymbols &&\n message.userDefinedSymbols.length))\n message.userDefinedSymbols = [];\n message.userDefinedSymbols.push(reader.string());\n break;\n }\n case 36: {\n message.requiredChars = reader.string();\n break;\n }\n case 35: {\n message.byteFallback = reader.bool();\n break;\n }\n case 32: {\n message.vocabularyOutputPieceScore = reader.bool();\n break;\n }\n case 33: {\n message.hardVocabLimit = reader.bool();\n break;\n }\n case 34: {\n message.useAllVocab = reader.bool();\n break;\n }\n case 40: {\n message.unkId = reader.int32();\n break;\n }\n case 41: {\n message.bosId = reader.int32();\n break;\n }\n case 42: {\n message.eosId = reader.int32();\n break;\n }\n case 43: {\n message.padId = reader.int32();\n break;\n }\n case 45: {\n message.unkPiece = reader.string();\n break;\n }\n case 46: {\n message.bosPiece = reader.string();\n break;\n }\n case 47: {\n message.eosPiece = reader.string();\n break;\n }\n case 48: {\n message.padPiece = reader.string();\n break;\n }\n case 44: {\n message.unkSurface = reader.string();\n break;\n }\n case 49: {\n message.trainExtremelyLargeCorpus = reader.bool();\n break;\n }\n case 54: {\n message.seedSentencepiecesFile = reader.string();\n break;\n }\n default:\n reader.skipType(tag & 7);\n break;\n }\n }\n return message;\n };\n\n /**\n * Decodes a TrainerSpec message from the specified reader or buffer, length\n * delimited.\n * @function decodeDelimited\n * @memberof sentencepiece.TrainerSpec\n * @static\n * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode\n * from\n * @returns {sentencepiece.TrainerSpec} TrainerSpec\n * @throws {Error} If the payload is not a reader or valid buffer\n * @throws {$protobuf.util.ProtocolError} If required fields are missing\n */\n TrainerSpec.decodeDelimited = function decodeDelimited(reader) {\n if (!(reader instanceof $Reader)) reader = new $Reader(reader);\n return this.decode(reader, reader.uint32());\n };\n\n /**\n * Verifies a TrainerSpec message.\n * @function verify\n * @memberof sentencepiece.TrainerSpec\n * @static\n * @param {Object.<string,*>} message Plain object to verify\n * @returns {string|null} `null` if valid, otherwise the reason why it is\n * not\n */\n TrainerSpec.verify = function verify(message) {\n if (typeof message !== 'object' || message === null)\n return 'object expected';\n if (message.input != null && message.hasOwnProperty('input')) {\n if (!Array.isArray(message.input)) return 'input: array expected';\n for (let i = 0; i < message.input.length; ++i)\n if (!$util.isString(message.input[i]))\n return 'input: string[] expected';\n }\n if (message.inputFormat != null && message.hasOwnProperty('inputFormat'))\n if (!$util.isString(message.inputFormat))\n return 'inputFormat: string expected';\n if (message.modelPrefix != null && message.hasOwnProperty('modelPrefix'))\n if (!$util.isString(message.modelPrefix))\n return 'modelPrefix: string expected';\n if (message.modelType != null && message.hasOwnProperty('modelType'))\n switch (message.modelType) {\n default:\n return 'modelType: enum value expected';\n case 1:\n case 2:\n case 3:\n case 4:\n break;\n }\n if (message.vocabSize != null && message.hasOwnProperty('vocabSize'))\n if (!$util.isInteger(message.vocabSize))\n return 'vocabSize: integer expected';\n if (message.acceptLanguage != null &&\n message.hasOwnProperty('acceptLanguage')) {\n if (!Array.isArray(message.acceptLanguage))\n return 'acceptLanguage: array expected';\n for (let i = 0; i < message.acceptLanguage.length; ++i)\n if (!$util.isString(message.acceptLanguage[i]))\n return 'acceptLanguage: string[] expected';\n }\n if (message.selfTestSampleSize != null &&\n message.hasOwnProperty('selfTestSampleSize'))\n if (!$util.isInteger(message.selfTestSampleSize))\n return 'selfTestSampleSize: integer expected';\n if (message.enableDifferentialPrivacy != null &&\n message.hasOwnProperty('enableDifferentialPrivacy'))\n if (typeof message.enableDifferentialPrivacy !== 'boolean')\n return 'enableDifferentialPrivacy: boolean expected';\n if (message.differentialPrivacyNoiseLevel != null &&\n message.hasOwnProperty('differentialPrivacyNoiseLevel'))\n if (typeof message.differentialPrivacyNoiseLevel !== 'number')\n return 'differentialPrivacyNoiseLevel: number expected';\n if (message.differentialPrivacyClippingThreshold != null &&\n message.hasOwnProperty('differentialPrivacyClippingThreshold'))\n if (!$util.isInteger(message.differentialPrivacyClippingThreshold) &&\n !(message.differentialPrivacyClippingThreshold &&\n $util.isInteger(\n message.differentialPrivacyClippingThreshold.low) &&\n $util.isInteger(\n message.differentialPrivacyClippingThreshold.high)))\n return 'differentialPrivacyClippingThreshold: integer|Long expected';\n if (message.characterCoverage != null &&\n message.hasOwnProperty('characterCoverage'))\n if (typeof message.characterCoverage !== 'number')\n return 'characterCoverage: number expected';\n if (message.inputSentenceSize != null &&\n message.hasOwnProperty('inputSentenceSize'))\n if (!$util.isInteger(message.inputSentenceSize) &&\n !(message.inputSentenceSize &&\n $util.isInteger(message.inputSentenceSize.low) &&\n $util.isInteger(message.inputSentenceSize.high)))\n return 'inputSentenceSize: integer|Long expected';\n if (message.shuffleInputSentence != null &&\n message.hasOwnProperty('shuffleInputSentence'))\n if (typeof message.shuffleInputSentence !== 'boolean')\n return 'shuffleInputSentence: boolean expected';\n if (message.miningSentenceSize != null &&\n message.hasOwnProperty('miningSentenceSize'))\n if (!$util.isInteger(message.miningSentenceSize))\n return 'miningSentenceSize: integer expected';\n if (message.trainingSentenceSize != null &&\n message.hasOwnProperty('trainingSentenceSize'))\n if (!$util.isInteger(message.trainingSentenceSize))\n return 'trainingSentenceSize: integer expected';\n if (message.seedSentencepieceSize != null &&\n message.hasOwnProperty('seedSentencepieceSize'))\n if (!$util.isInteger(message.seedSentencepieceSize))\n return 'seedSentencepieceSize: integer expected';\n if (message.shrinkingFactor != null &&\n message.hasOwnProperty('shrinkingFactor'))\n if (typeof message.shrinkingFactor !== 'number')\n return 'shrinkingFactor: number expected';\n if (message.maxSentenceLength != null &&\n message.hasOwnProperty('maxSentenceLength'))\n if (!$util.isInteger(message.maxSentenceLength))\n return 'maxSentenceLength: integer expected';\n if (message.numThreads != null && message.hasOwnProperty('numThreads'))\n if (!$util.isInteger(message.numThreads))\n return 'numThreads: integer expected';\n if (message.numSubIterations != null &&\n message.hasOwnProperty('numSubIterations'))\n if (!$util.isInteger(message.numSubIterations))\n return 'numSubIterations: integer expected';\n if (message.maxSentencepieceLength != null &&\n message.hasOwnProperty('maxSentencepieceLength'))\n if (!$util.isInteger(message.maxSentencepieceLength))\n return 'maxSentencepieceLength: integer expected';\n if (message.splitByUnicodeScript != null &&\n message.hasOwnProperty('splitByUnicodeScript'))\n if (typeof message.splitByUnicodeScript !== 'boolean')\n return 'splitByUnicodeScript: boolean expected';\n if (message.splitByNumber != null &&\n message.hasOwnProperty('splitByNumber'))\n if (typeof message.splitByNumber !== 'boolean')\n return 'splitByNumber: boolean expected';\n if (message.splitByWhitespace != null &&\n message.hasOwnProperty('splitByWhitespace'))\n if (typeof message.splitByWhitespace !== 'boolean')\n return 'splitByWhitespace: boolean expected';\n if (message.treatWhitespaceAsSuffix != null &&\n message.hasOwnProperty('treatWhitespaceAsSuffix'))\n if (typeof message.treatWhitespaceAsSuffix !== 'boolean')\n return 'treatWhitespaceAsSuffix: boolean expected';\n if (message.allowWhitespaceOnlyPieces != null &&\n message.hasOwnProperty('allowWhitespaceOnlyPieces'))\n if (typeof message.allowWhitespaceOnlyPieces !== 'boolean')\n return 'allowWhitespaceOnlyPieces: boolean expected';\n if (message.splitDigits != null && message.hasOwnProperty('splitDigits'))\n if (typeof message.splitDigits !== 'boolean')\n return 'splitDigits: boolean expected';\n if (message.pretokenizationDelimiter != null &&\n message.hasOwnProperty('pretokenizationDelimiter'))\n if (!$util.isString(message.pretokenizationDelimiter))\n return 'pretokenizationDelimiter: string expected';\n if (message.controlSymbols != null &&\n message.hasOwnProperty('controlSymbols')) {\n if (!Array.isArray(message.controlSymbols))\n return 'controlSymbols: array expected';\n for (let i = 0; i < message.controlSymbols.length; ++i)\n if (!$util.isString(message.controlSymbols[i]))\n return 'controlSymbols: string[] expected';\n }\n if (message.userDefinedSymbols != null &&\n message.hasOwnProperty('userDefinedSymbols')) {\n if (!Array.isArray(message.userDefinedSymbols))\n return 'userDefinedSymbols: array expected';\n for (let i = 0; i < message.userDefinedSymbols.length; ++i)\n if (!$util.isString(message.userDefinedSymbols[i]))\n return 'userDefinedSymbols: string[] expected';\n }\n if (message.requiredChars != null &&\n message.hasOwnProperty('requiredChars'))\n if (!$util.isString(message.requiredChars))\n return 'requiredChars: string expected';\n if (message.byteFallback != null &&\n message.hasOwnProperty('byteFallback'))\n if (typeof message.byteFallback !== 'boolean')\n return 'byteFallback: boolean expected';\n if (message.vocabularyOutputPieceScore != null &&\n message.hasOwnProperty('vocabularyOutputPieceScore'))\n if (typeof message.vocabularyOutputPieceScore !== 'boolean')\n return 'vocabularyOutputPieceScore: boolean expected';\n if (message.hardVocabLimit != null &&\n message.hasOwnProperty('hardVocabLimit'))\n if (typeof message.hardVocabLimit !== 'boolean')\n return 'hardVocabLimit: boolean expected';\n if (message.useAllVocab != null && message.hasOwnProperty('useAllVocab'))\n if (typeof message.useAllVocab !== 'boolean')\n return 'useAllVocab: boolean expected';\n if (message.unkId != null && message.hasOwnProperty('unkId'))\n if (!$util.isInteger(message.unkId)) return 'unkId: integer expected';\n if (message.bosId != null && message.hasOwnProperty('bosId'))\n if (!$util.isInteger(message.bosId)) return 'bosId: integer expected';\n if (message.eosId != null && message.hasOwnProperty('eosId'))\n if (!$util.isInteger(message.eosId)) return 'eosId: integer expected';\n if (message.padId != null && message.hasOwnProperty('padId'))\n if (!$util.isInteger(message.padId)) return 'padId: integer expected';\n if (message.unkPiece != null && message.hasOwnProperty('unkPiece'))\n if (!$util.isString(message.unkPiece))\n return 'unkPiece: string expected';\n if (message.bosPiece != null && message.hasOwnProperty('bosPiece'))\n if (!$util.isString(message.bosPiece))\n return 'bosPiece: string expected';\n if (message.eosPiece != null && message.hasOwnProperty('eosPiece'))\n if (!$util.isString(message.eosPiece))\n return 'eosPiece: string expected';\n if (message.padPiece != null && message.hasOwnProperty('padPiece'))\n if (!$util.isString(message.padPiece))\n return 'padPiece: string expected';\n if (message.unkSurface != null && message.hasOwnProperty('unkSurface'))\n if (!$util.isString(message.unkSurface))\n return 'unkSurface: string expected';\n if (message.trainExtremelyLargeCorpus != null &&\n message.hasOwnProperty('trainExtremelyLargeCorpus'))\n if (typeof message.trainExtremelyLargeCorpus !== 'boolean')\n return 'trainExtremelyLargeCorpus: boolean expected';\n if (message.seedSentencepiecesFile != null &&\n message.hasOwnProperty('seedSentencepiecesFile'))\n if (!$util.isString(message.seedSentencepiecesFile))\n return 'seedSentencepiecesFile: string expected';\n return null;\n };\n\n /**\n * Creates a TrainerSpec message from a plain object. Also converts values\n * to their respective internal types.\n * @function fromObject\n * @memberof sentencepiece.TrainerSpec\n * @static\n * @param {Object.<string,*>} object Plain object\n * @returns {sentencepiece.TrainerSpec} TrainerSpec\n */\n TrainerSpec.fromObject = function fromObject(object) {\n if (object instanceof $root.sentencepiece.TrainerSpec) return object;\n let message = new $root.sentencepiece.TrainerSpec();\n if (object.input) {\n if (!Array.isArray(object.input))\n throw TypeError('.sentencepiece.TrainerSpec.input: array expected');\n message.input = [];\n for (let i = 0; i < object.input.length; ++i)\n message.input[i] = String(object.input[i]);\n }\n if (object.inputFormat != null)\n message.inputFormat = String(object.inputFormat);\n if (object.modelPrefix != null)\n message.modelPrefix = String(object.modelPrefix);\n switch (object.modelType) {\n default:\n if (typeof object.modelType === 'number') {\n message.modelType = object.modelType;\n break;\n }\n break;\n case 'UNIGRAM':\n case 1:\n message.modelType = 1;\n break;\n case 'BPE':\n case 2:\n message.modelType = 2;\n break;\n case 'WORD':\n case 3:\n message.modelType = 3;\n break;\n case 'CHAR':\n case 4:\n message.modelType = 4;\n break;\n }\n if (object.vocabSize != null) message.vocabSize = object.vocabSize | 0;\n if (object.acceptLanguage) {\n if (!Array.isArray(object.acceptLanguage))\n throw TypeError(\n '.sentencepiece.TrainerSpec.acceptLanguage: array expected');\n message.acceptLanguage = [];\n for (let i = 0; i < object.acceptLanguage.length; ++i)\n message.acceptLanguage[i] = String(object.acceptLanguage[i]);\n }\n if (object.selfTestSampleSize != null)\n message.selfTestSampleSize = object.selfTestSampleSize | 0;\n if (object.enableDifferentialPrivacy != null)\n message.enableDifferentialPrivacy =\n Boolean(object.enableDifferentialPrivacy);\n if (object.differentialPrivacyNoiseLevel != null)\n message.differentialPrivacyNoiseLevel =\n Number(object.differentialPrivacyNoiseLevel);\n if (object.differentialPrivacyClippingThreshold != null)\n if ($util.Long)\n (message.differentialPrivacyClippingThreshold = $util.Long.fromValue(\n object.differentialPrivacyClippingThreshold))\n .unsigned = true;\n else if (\n typeof object.differentialPrivacyClippingThreshold === 'string')\n message.differentialPrivacyClippingThreshold =\n parseInt(object.differentialPrivacyClippingThreshold, 10);\n else if (\n typeof object.differentialPrivacyClippingThreshold === 'number')\n message.differentialPrivacyClippingThreshold =\n object.differentialPrivacyClippingThreshold;\n else if (\n typeof object.differentialPrivacyClippingThreshold === 'object')\n message.differentialPrivacyClippingThreshold =\n new $util\n .LongBits(\n object.differentialPrivacyClippingThreshold.low >>> 0,\n object.differentialPrivacyClippingThreshold.high >>> 0)\n .toNumber(true);\n if (object.characterCoverage != null)\n message.characterCoverage = Number(object.characterCoverage);\n if (object.inputSentenceSize != null)\n if ($util.Long)\n (message.inputSentenceSize =\n $util.Long.fromValue(object.inputSentenceSize))\n .unsigned = true;\n else if (typeof object.inputSentenceSize === 'string')\n message.inputSentenceSize = parseInt(object.inputSentenceSize, 10);\n else if (typeof object.inputSentenceSize === 'number')\n message.inputSentenceSize = object.inputSentenceSize;\n else if (typeof object.inputSentenceSize === 'object')\n message.inputSentenceSize =\n new $util\n .LongBits(\n object.inputSentenceSize.low >>> 0,\n object.inputSentenceSize.high >>> 0)\n .toNumber(true);\n if (object.shuffleInputSentence != null)\n message.shuffleInputSentence = Boolean(object.shuffleInputSentence);\n if (object.miningSentenceSize != null)\n message.miningSentenceSize = object.miningSentenceSize | 0;\n if (object.trainingSentenceSize != null)\n message.trainingSentenceSize = object.trainingSentenceSize | 0;\n if (object.seedSentencepieceSize != null)\n message.seedSentencepieceSize = object.seedSentencepieceSize | 0;\n if (object.shrinkingFactor != null)\n message.shrinkingFactor = Number(object.shrinkingFactor);\n if (object.maxSentenceLength != null)\n message.maxSentenceLength = object.maxSentenceLength | 0;\n if (object.numThreads != null) message.numThreads = object.numThreads | 0;\n if (object.numSubIterations != null)\n message.numSubIterations = object.numSubIterations | 0;\n if (object.maxSentencepieceLength != null)\n message.maxSentencepieceLength = object.maxSentencepieceLength | 0;\n if (object.splitByUnicodeScript != null)\n message.splitByUnicodeScript = Boolean(object.splitByUnicodeScript);\n if (object.splitByNumber != null)\n message.splitByNumber = Boolean(object.splitByNumber);\n if (object.splitByWhitespace != null)\n message.splitByWhitespace = Boolean(object.splitByWhitespace);\n if (object.treatWhitespaceAsSuffix != null)\n message.treatWhitespaceAsSuffix =\n Boolean(object.treatWhitespaceAsSuffix);\n if (object.allowWhitespaceOnlyPieces != null)\n message.allowWhitespaceOnlyPieces =\n Boolean(object.allowWhitespaceOnlyPieces);\n if (object.splitDigits != null)\n message.splitDigits = Boolean(object.splitDigits);\n if (object.pretokenizationDelimiter != null)\n message.pretokenizationDelimiter =\n String(object.pretokenizationDelimiter);\n if (object.controlSymbols) {\n if (!Array.isArray(object.controlSymbols))\n throw TypeError(\n '.sentencepiece.TrainerSpec.controlSymbols: array expected');\n message.controlSymbols = [];\n for (let i = 0; i < object.controlSymbols.length; ++i)\n message.controlSymbols[i] = String(object.controlSymbols[i]);\n }\n if (object.userDefinedSymbols) {\n if (!Array.isArray(object.userDefinedSymbols))\n throw TypeError(\n '.sentencepiece.TrainerSpec.userDefinedSymbols: array expected');\n message.userDefinedSymbols = [];\n for (let i = 0; i < object.userDefinedSymbols.length; ++i)\n message.userDefinedSymbols[i] = String(object.userDefinedSymbols[i]);\n }\n if (object.requiredChars != null)\n message.requiredChars = String(object.requiredChars);\n if (object.byteFallback != null)\n message.byteFallback = Boolean(object.byteFallback);\n if (object.vocabularyOutputPieceScore != null)\n message.vocabularyOutputPieceScore =\n Boolean(object.vocabularyOutputPieceScore);\n if (object.hardVocabLimit != null)\n message.hardVocabLimit = Boolean(object.hardVocabLimit);\n if (object.useAllVocab != null)\n message.useAllVocab = Boolean(object.useAllVocab);\n if (object.unkId != null) message.unkId = object.unkId | 0;\n if (object.bosId != null) message.bosId = object.bosId | 0;\n if (object.eosId != null) message.eosId = object.eosId | 0;\n if (object.padId != null) message.padId = object.padId | 0;\n if (object.unkPiece != null) message.unkPiece = String(object.unkPiece);\n if (object.bosPiece != null) message.bosPiece = String(object.bosPiece);\n if (object.eosPiece != null) message.eosPiece = String(object.eosPiece);\n if (object.padPiece != null) message.padPiece = String(object.padPiece);\n if (object.unkSurface != null)\n message.unkSurface = String(object.unkSurface);\n if (object.trainExtremelyLargeCorpus != null)\n message.trainExtremelyLargeCorpus =\n Boolean(object.trainExtremelyLargeCorpus);\n if (object.seedSentencepiecesFile != null)\n message.seedSentencepiecesFile = String(object.seedSentencepiecesFile);\n return message;\n };\n\n /**\n * Creates a plain object from a TrainerSpec message. Also converts values\n * to other types if specified.\n * @function toObject\n * @memberof sentencepiece.TrainerSpec\n * @static\n * @param {sentencepiece.TrainerSpec} message TrainerSpec\n * @param {$protobuf.IConversionOptions} [options] Conversion options\n * @returns {Object.<string,*>} Plain object\n */\n TrainerSpec.toObject = function toObject(message, options) {\n if (!options) options = {};\n let object = {};\n if (options.arrays || options.defaults) {\n object.input = [];\n object.acceptLanguage = [];\n object.controlSymbols = [];\n object.userDefinedSymbols = [];\n }\n if (options.defaults) {\n object.modelPrefix = '';\n object.modelType = options.enums === String ? 'UNIGRAM' : 1;\n object.vocabSize = 8000;\n object.selfTestSampleSize = 0;\n object.inputFormat = '';\n object.characterCoverage = 0.9995;\n if ($util.Long) {\n let long = new $util.Long(0, 0, true);\n object.inputSentenceSize = options.longs === String ?\n long.toString() :\n options.longs === Number ? long.toNumber() :\n long;\n } else\n object.inputSentenceSize = options.longs === String ? '0' : 0;\n object.miningSentenceSize = 0;\n object.trainingSentenceSize = 0;\n object.seedSentencepieceSize = 1000000;\n object.shrinkingFactor = 0.75;\n object.numThreads = 16;\n object.numSubIterations = 2;\n object.maxSentenceLength = 4192;\n object.shuffleInputSentence = true;\n object.maxSentencepieceLength = 16;\n object.splitByUnicodeScript = true;\n object.splitByWhitespace = true;\n object.splitByNumber = true;\n object.treatWhitespaceAsSuffix = false;\n object.splitDigits = false;\n object.allowWhitespaceOnlyPieces = false;\n object.vocabularyOutputPieceScore = true;\n object.hardVocabLimit = true;\n object.useAllVocab = false;\n object.byteFallback = false;\n object.requiredChars = '';\n object.unkId = 0;\n object.bosId = 1;\n object.eosId = 2;\n object.padId = -1;\n object.unkSurface = ' E28187 ';\n object.unkPiece = '<unk>';\n object.bosPiece = '<s>';\n object.eosPiece = '</s>';\n object.padPiece = '<pad>';\n object.trainExtremelyLargeCorpus = false;\n object.enableDifferentialPrivacy = false;\n object.differentialPrivacyNoiseLevel = 0;\n if ($util.Long) {\n let long = new $util.Long(0, 0, true);\n object.differentialPrivacyClippingThreshold =\n options.longs === String ? long.toString() :\n options.longs === Number ? long.toNumber() :\n long;\n } else\n object.differentialPrivacyClippingThreshold =\n options.longs === String ? '0' : 0;\n object.pretokenizationDelimiter = '';\n object.seedSentencepiecesFile = '';\n }\n if (message.input && message.input.length) {\n object.input = [];\n for (let j = 0; j < message.input.length; ++j)\n object.input[j] = message.input[j];\n }\n if (message.modelPrefix != null && message.hasOwnProperty('modelPrefix'))\n object.modelPrefix = message.modelPrefix;\n if (message.modelType != null && message.hasOwnProperty('modelType'))\n object.modelType = options.enums === String ?\n $root.sentencepiece.TrainerSpec.ModelType[message.modelType] ===\n undefined ?\n message.modelType :\n $root.sentencepiece.TrainerSpec.ModelType[message.modelType] :\n message.modelType;\n if (message.vocabSize != null && message.hasOwnProperty('vocabSize'))\n object.vocabSize = message.vocabSize;\n if (message.acceptLanguage && message.acceptLanguage.length) {\n object.acceptLanguage = [];\n for (let j = 0; j < message.acceptLanguage.length; ++j)\n object.acceptLanguage[j] = message.acceptLanguage[j];\n }\n if (message.selfTestSampleSize != null &&\n message.hasOwnProperty('selfTestSampleSize'))\n object.selfTestSampleSize = message.selfTestSampleSize;\n if (message.inputFormat != null && message.hasOwnProperty('inputFormat'))\n object.inputFormat = message.inputFormat;\n if (message.characterCoverage != null &&\n message.hasOwnProperty('characterCoverage'))\n object.characterCoverage =\n options.json && !isFinite(message.characterCoverage) ?\n String(message.characterCoverage) :\n message.characterCoverage;\n if (message.inputSentenceSize != null &&\n message.hasOwnProperty('inputSentenceSize'))\n if (typeof message.inputSentenceSize === 'number')\n object.inputSentenceSize = options.longs === String ?\n String(message.inputSentenceSize) :\n message.inputSentenceSize;\n else\n object.inputSentenceSize = options.longs === String ?\n $util.Long.prototype.toString.call(message.inputSentenceSize) :\n options.longs === Number ?\n new $util\n .LongBits(\n message.inputSentenceSize.low >>> 0,\n message.inputSentenceSize.high >>> 0)\n .toNumber(true) :\n message.inputSentenceSize;\n if (message.miningSentenceSize != null &&\n message.hasOwnProperty('miningSentenceSize'))\n object.miningSentenceSize = message.miningSentenceSize;\n if (message.trainingSentenceSize != null &&\n message.hasOwnProperty('trainingSentenceSize'))\n object.trainingSentenceSize = message.trainingSentenceSize;\n if (message.seedSentencepieceSize != null &&\n message.hasOwnProperty('seedSentencepieceSize'))\n object.seedSentencepieceSize = message.seedSentencepieceSize;\n if (message.shrinkingFactor != null &&\n message.hasOwnProperty('shrinkingFactor'))\n object.shrinkingFactor =\n options.json && !isFinite(message.shrinkingFactor) ?\n String(message.shrinkingFactor) :\n message.shrinkingFactor;\n if (message.numThreads != null && message.hasOwnProperty('numThreads'))\n object.numThreads = message.numThreads;\n if (message.numSubIterations != null &&\n message.hasOwnProperty('numSubIterations'))\n object.numSubIterations = message.numSubIterations;\n if (message.maxSentenceLength != null &&\n message.hasOwnProperty('maxSentenceLength'))\n object.maxSentenceLength = message.maxSentenceLength;\n if (message.shuffleInputSentence != null &&\n message.hasOwnProperty('shuffleInputSentence'))\n object.shuffleInputSentence = message.shuffleInputSentence;\n if (message.maxSentencepieceLength != null &&\n message.hasOwnProperty('maxSentencepieceLength'))\n object.maxSentencepieceLength = message.maxSentencepieceLength;\n if (message.splitByUnicodeScript != null &&\n message.hasOwnProperty('splitByUnicodeScript'))\n object.splitByUnicodeScript = message.splitByUnicodeScript;\n if (message.splitByWhitespace != null &&\n message.hasOwnProperty('splitByWhitespace'))\n object.splitByWhitespace = message.splitByWhitespace;\n if (message.splitByNumber != null &&\n message.hasOwnProperty('splitByNumber'))\n object.splitByNumber = message.splitByNumber;\n if (message.treatWhitespaceAsSuffix != null &&\n message.hasOwnProperty('treatWhitespaceAsSuffix'))\n object.treatWhitespaceAsSuffix = message.treatWhitespaceAsSuffix;\n if (message.splitDigits != null && message.hasOwnProperty('splitDigits'))\n object.splitDigits = message.splitDigits;\n if (message.allowWhitespaceOnlyPieces != null &&\n message.hasOwnProperty('allowWhitespaceOnlyPieces'))\n object.allowWhitespaceOnlyPieces = message.allowWhitespaceOnlyPieces;\n if (message.controlSymbols && message.controlSymbols.length) {\n object.controlSymbols = [];\n for (let j = 0; j < message.controlSymbols.length; ++j)\n object.controlSymbols[j] = message.controlSymbols[j];\n }\n if (message.userDefinedSymbols && message.userDefinedSymbols.length) {\n object.userDefinedSymbols = [];\n for (let j = 0; j < message.userDefinedSymbols.length; ++j)\n object.userDefinedSymbols[j] = message.userDefinedSymbols[j];\n }\n if (message.vocabularyOutputPieceScore != null &&\n message.hasOwnProperty('vocabularyOutputPieceScore'))\n object.vocabularyOutputPieceScore = message.vocabularyOutputPieceScore;\n if (message.hardVocabLimit != null &&\n message.hasOwnProperty('hardVocabLimit'))\n object.hardVocabLimit = message.hardVocabLimit;\n if (message.useAllVocab != null && message.hasOwnProperty('useAllVocab'))\n object.useAllVocab = message.useAllVocab;\n if (message.byteFallback != null &&\n message.hasOwnProperty('byteFallback'))\n object.byteFallback = message.byteFallback;\n if (message.requiredChars != null &&\n message.hasOwnProperty('requiredChars'))\n object.requiredChars = message.requiredChars;\n if (message.unkId != null && message.hasOwnProperty('unkId'))\n object.unkId = message.unkId;\n if (message.bosId != null && message.hasOwnProperty('bosId'))\n object.bosId = message.bosId;\n if (message.eosId != null && message.hasOwnProperty('eosId'))\n object.eosId = message.eosId;\n if (message.padId != null && message.hasOwnProperty('padId'))\n object.padId = message.padId;\n if (message.unkSurface != null && message.hasOwnProperty('unkSurface'))\n object.unkSurface = message.unkSurface;\n if (message.unkPiece != null && message.hasOwnProperty('unkPiece'))\n object.unkPiece = message.unkPiece;\n if (message.bosPiece != null && message.hasOwnProperty('bosPiece'))\n object.bosPiece = message.bosPiece;\n if (message.eosPiece != null && message.hasOwnProperty('eosPiece'))\n object.eosPiece = message.eosPiece;\n if (message.padPiece != null && message.hasOwnProperty('padPiece'))\n object.padPiece = message.padPiece;\n if (message.trainExtremelyLargeCorpus != null &&\n message.hasOwnProperty('trainExtremelyLargeCorpus'))\n object.trainExtremelyLargeCorpus = message.trainExtremelyLargeCorpus;\n if (message.enableDifferentialPrivacy != null &&\n message.hasOwnProperty('enableDifferentialPrivacy'))\n object.enableDifferentialPrivacy = message.enableDifferentialPrivacy;\n if (message.differentialPrivacyNoiseLevel != null &&\n message.hasOwnProperty('differentialPrivacyNoiseLevel'))\n object.differentialPrivacyNoiseLevel =\n options.json && !isFinite(message.differentialPrivacyNoiseLevel) ?\n String(message.differentialPrivacyNoiseLevel) :\n message.differentialPrivacyNoiseLevel;\n if (message.differentialPrivacyClippingThreshold != null &&\n message.hasOwnProperty('differentialPrivacyClippingThreshold'))\n if (typeof message.differentialPrivacyClippingThreshold === 'number')\n object.differentialPrivacyClippingThreshold =\n options.longs === String ?\n String(message.differentialPrivacyClippingThreshold) :\n message.differentialPrivacyClippingThreshold;\n else\n object.differentialPrivacyClippingThreshold =\n options.longs === String ?\n $util.Long.prototype.toString.call(\n message.differentialPrivacyClippingThreshold) :\n options.longs === Number ?\n new $util\n .LongBits(\n message.differentialPrivacyClippingThreshold.low >>> 0,\n message.differentialPrivacyClippingThreshold.high >>> 0)\n .toNumber(true) :\n message.differentialPrivacyClippingThreshold;\n if (message.pretokenizationDelimiter != null &&\n message.hasOwnProperty('pretokenizationDelimiter'))\n object.pretokenizationDelimiter = message.pretokenizationDelimiter;\n if (message.seedSentencepiecesFile != null &&\n message.hasOwnProperty('seedSentencepiecesFile'))\n object.seedSentencepiecesFile = message.seedSentencepiecesFile;\n return object;\n };\n\n /**\n * Converts this TrainerSpec to JSON.\n * @function toJSON\n * @memberof sentencepiece.TrainerSpec\n * @instance\n * @returns {Object.<string,*>} JSON object\n */\n TrainerSpec.prototype.toJSON = function toJSON() {\n return this.constructor.toObject(this, $protobuf.util.toJSONOptions);\n };\n\n /**\n * Gets the default type url for TrainerSpec\n * @function getTypeUrl\n * @memberof sentencepiece.TrainerSpec\n * @static\n * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default\n * \"type.googleapis.com\")\n * @returns {string} The default type url\n */\n TrainerSpec.getTypeUrl = function getTypeUrl(typeUrlPrefix) {\n if (typeUrlPrefix === undefined) {\n typeUrlPrefix = 'type.googleapis.com';\n }\n return typeUrlPrefix + '/sentencepiece.TrainerSpec';\n };\n\n /**\n * ModelType enum.\n * @name sentencepiece.TrainerSpec.ModelType\n * @enum {number}\n * @property {number} UNIGRAM=1 UNIGRAM value\n * @property {number} BPE=2 BPE value\n * @property {number} WORD=3 WORD value\n * @property {number} CHAR=4 CHAR value\n */\n TrainerSpec.ModelType = (function() {\n const valuesById = {}, values = Object.create(valuesById);\n values[valuesById[1] = 'UNIGRAM'] = 1;\n values[valuesById[2] = 'BPE'] = 2;\n values[valuesById[3] = 'WORD'] = 3;\n values[valuesById[4] = 'CHAR'] = 4;\n return values;\n })();\n\n return TrainerSpec;\n })();\n\n sentencepiece.NormalizerSpec = (function() {\n /**\n * Properties of a NormalizerSpec.\n * @memberof sentencepiece\n * @interface INormalizerSpec\n * @property {string|null} [name] NormalizerSpec name\n * @property {Uint8Array|null} [precompiledCharsmap] NormalizerSpec\n * precompiledCharsmap\n * @property {boolean|null} [addDummyPrefix] NormalizerSpec addDummyPrefix\n * @property {boolean|null} [removeExtraWhitespaces] NormalizerSpec\n * removeExtraWhitespaces\n * @property {boolean|null} [escapeWhitespaces] NormalizerSpec\n * escapeWhitespaces\n * @property {string|null} [normalizationRuleTsv] NormalizerSpec\n * normalizationRuleTsv\n */\n\n /**\n * Constructs a new NormalizerSpec.\n * @memberof sentencepiece\n * @classdesc Represents a NormalizerSpec.\n * @implements INormalizerSpec\n * @constructor\n * @param {sentencepiece.INormalizerSpec=} [properties] Properties to set\n */\n function NormalizerSpec(properties) {\n if (properties)\n for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i)\n if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]];\n }\n\n /**\n * NormalizerSpec name.\n * @member {string} name\n * @memberof sentencepiece.NormalizerSpec\n * @instance\n */\n NormalizerSpec.prototype.name = '';\n\n /**\n * NormalizerSpec precompiledCharsmap.\n * @member {Uint8Array} precompiledCharsmap\n * @memberof sentencepiece.NormalizerSpec\n * @instance\n */\n NormalizerSpec.prototype.precompiledCharsmap = $util.newBuffer([]);\n\n /**\n * NormalizerSpec addDummyPrefix.\n * @member {boolean} addDummyPrefix\n * @memberof sentencepiece.NormalizerSpec\n * @instance\n */\n NormalizerSpec.prototype.addDummyPrefix = true;\n\n /**\n * NormalizerSpec removeExtraWhitespaces.\n * @member {boolean} removeExtraWhitespaces\n * @memberof sentencepiece.NormalizerSpec\n * @instance\n */\n NormalizerSpec.prototype.removeExtraWhitespaces = true;\n\n /**\n * NormalizerSpec escapeWhitespaces.\n * @member {boolean} escapeWhitespaces\n * @memberof sentencepiece.NormalizerSpec\n * @instance\n */\n NormalizerSpec.prototype.escapeWhitespaces = true;\n\n /**\n * NormalizerSpec normalizationRuleTsv.\n * @member {string} normalizationRuleTsv\n * @memberof sentencepiece.NormalizerSpec\n * @instance\n */\n NormalizerSpec.prototype.normalizationRuleTsv = '';\n\n /**\n * Creates a new NormalizerSpec instance using the specified properties.\n * @function create\n * @memberof sentencepiece.NormalizerSpec\n * @static\n * @param {sentencepiece.INormalizerSpec=} [properties] Properties to set\n * @returns {sentencepiece.NormalizerSpec} NormalizerSpec instance\n */\n NormalizerSpec.create = function create(properties) {\n return new NormalizerSpec(properties);\n };\n\n /**\n * Encodes the specified NormalizerSpec message. Does not implicitly {@link\n * sentencepiece.NormalizerSpec.verify|verify} messages.\n * @function encode\n * @memberof sentencepiece.NormalizerSpec\n * @static\n * @param {sentencepiece.INormalizerSpec} message NormalizerSpec message or\n * plain object to encode\n * @param {$protobuf.Writer} [writer] Writer to encode to\n * @returns {$protobuf.Writer} Writer\n */\n NormalizerSpec.encode = function encode(message, writer) {\n if (!writer) writer = $Writer.create();\n if (message.name != null && Object.hasOwnProperty.call(message, 'name'))\n writer.uint32(/* id 1, wireType 2 =*/ 10).string(message.name);\n if (message.precompiledCharsmap != null &&\n Object.hasOwnProperty.call(message, 'precompiledCharsmap'))\n writer.uint32(/* id 2, wireType 2 =*/ 18)\n .bytes(message.precompiledCharsmap);\n if (message.addDummyPrefix != null &&\n Object.hasOwnProperty.call(message, 'addDummyPrefix'))\n writer.uint32(/* id 3, wireType 0 =*/ 24).bool(message.addDummyPrefix);\n if (message.removeExtraWhitespaces != null &&\n Object.hasOwnProperty.call(message, 'removeExtraWhitespaces'))\n writer.uint32(/* id 4, wireType 0 =*/ 32)\n .bool(message.removeExtraWhitespaces);\n if (message.escapeWhitespaces != null &&\n Object.hasOwnProperty.call(message, 'escapeWhitespaces'))\n writer.uint32(/* id 5, wireType 0 =*/ 40)\n .bool(message.escapeWhitespaces);\n if (message.normalizationRuleTsv != null &&\n Object.hasOwnProperty.call(message, 'normalizationRuleTsv'))\n writer.uint32(/* id 6, wireType 2 =*/ 50)\n .string(message.normalizationRuleTsv);\n return writer;\n };\n\n /**\n * Encodes the specified NormalizerSpec message, length delimited. Does not\n * implicitly {@link sentencepiece.NormalizerSpec.verify|verify} messages.\n * @function encodeDelimited\n * @memberof sentencepiece.NormalizerSpec\n * @static\n * @param {sentencepiece.INormalizerSpec} message NormalizerSpec message or\n * plain object to encode\n * @param {$protobuf.Writer} [writer] Writer to encode to\n * @returns {$protobuf.Writer} Writer\n */\n NormalizerSpec.encodeDelimited = function encodeDelimited(message, writer) {\n return this.encode(message, writer).ldelim();\n };\n\n /**\n * Decodes a NormalizerSpec message from the specified reader or buffer.\n * @function decode\n * @memberof sentencepiece.NormalizerSpec\n * @static\n * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode\n * from\n * @param {number} [length] Message length if known beforehand\n * @returns {sentencepiece.NormalizerSpec} NormalizerSpec\n * @throws {Error} If the payload is not a reader or valid buffer\n * @throws {$protobuf.util.ProtocolError} If required fields are missing\n */\n NormalizerSpec.decode = function decode(reader, length, error) {\n if (!(reader instanceof $Reader)) reader = $Reader.create(reader);\n let end = length === undefined ? reader.len : reader.pos + length,\n message = new $root.sentencepiece.NormalizerSpec();\n while (reader.pos < end) {\n let tag = reader.uint32();\n if (tag === error) break;\n switch (tag >>> 3) {\n case 1: {\n message.name = reader.string();\n break;\n }\n case 2: {\n message.precompiledCharsmap = reader.bytes();\n break;\n }\n case 3: {\n message.addDummyPrefix = reader.bool();\n break;\n }\n case 4: {\n message.removeExtraWhitespaces = reader.bool();\n break;\n }\n case 5: {\n message.escapeWhitespaces = reader.bool();\n break;\n }\n case 6: {\n message.normalizationRuleTsv = reader.string();\n break;\n }\n default:\n reader.skipType(tag & 7);\n break;\n }\n }\n return message;\n };\n\n /**\n * Decodes a NormalizerSpec message from the specified reader or buffer,\n * length delimited.\n * @function decodeDelimited\n * @memberof sentencepiece.NormalizerSpec\n * @static\n * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode\n * from\n * @returns {sentencepiece.NormalizerSpec} NormalizerSpec\n * @throws {Error} If the payload is not a reader or valid buffer\n * @throws {$protobuf.util.ProtocolError} If required fields are missing\n */\n NormalizerSpec.decodeDelimited = function decodeDelimited(reader) {\n if (!(reader instanceof $Reader)) reader = new $Reader(reader);\n return this.decode(reader, reader.uint32());\n };\n\n /**\n * Verifies a NormalizerSpec message.\n * @function verify\n * @memberof sentencepiece.NormalizerSpec\n * @static\n * @param {Object.<string,*>} message Plain object to verify\n * @returns {string|null} `null` if valid, otherwise the reason why it is\n * not\n */\n NormalizerSpec.verify = function verify(message) {\n if (typeof message !== 'object' || message === null)\n return 'object expected';\n if (message.name != null && message.hasOwnProperty('name'))\n if (!$util.isString(message.name)) return 'name: string expected';\n if (message.precompiledCharsmap != null &&\n message.hasOwnProperty('precompiledCharsmap'))\n if (!(message.precompiledCharsmap &&\n typeof message.precompiledCharsmap.length === 'number' ||\n $util.isString(message.precompiledCharsmap)))\n return 'precompiledCharsmap: buffer expected';\n if (message.addDummyPrefix != null &&\n message.hasOwnProperty('addDummyPrefix'))\n if (typeof message.addDummyPrefix !== 'boolean')\n return 'addDummyPrefix: boolean expected';\n if (message.removeExtraWhitespaces != null &&\n message.hasOwnProperty('removeExtraWhitespaces'))\n if (typeof message.removeExtraWhitespaces !== 'boolean')\n return 'removeExtraWhitespaces: boolean expected';\n if (message.escapeWhitespaces != null &&\n message.hasOwnProperty('escapeWhitespaces'))\n if (typeof message.escapeWhitespaces !== 'boolean')\n return 'escapeWhitespaces: boolean expected';\n if (message.normalizationRuleTsv != null &&\n message.hasOwnProperty('normalizationRuleTsv'))\n if (!$util.isString(message.normalizationRuleTsv))\n return 'normalizationRuleTsv: string expected';\n return null;\n };\n\n /**\n * Creates a NormalizerSpec message from a plain object. Also converts\n * values to their respective internal types.\n * @function fromObject\n * @memberof sentencepiece.NormalizerSpec\n * @static\n * @param {Object.<string,*>} object Plain object\n * @returns {sentencepiece.NormalizerSpec} NormalizerSpec\n */\n NormalizerSpec.fromObject = function fromObject(object) {\n if (object instanceof $root.sentencepiece.NormalizerSpec) return object;\n let message = new $root.sentencepiece.NormalizerSpec();\n if (object.name != null) message.name = String(object.name);\n if (object.precompiledCharsmap != null)\n if (typeof object.precompiledCharsmap === 'string')\n $util.base64.decode(\n object.precompiledCharsmap,\n message.precompiledCharsmap = $util.newBuffer(\n $util.base64.length(object.precompiledCharsmap)),\n 0);\n else if (object.precompiledCharsmap.length >= 0)\n message.precompiledCharsmap = object.precompiledCharsmap;\n if (object.addDummyPrefix != null)\n message.addDummyPrefix = Boolean(object.addDummyPrefix);\n if (object.removeExtraWhitespaces != null)\n message.removeExtraWhitespaces = Boolean(object.removeExtraWhitespaces);\n if (object.escapeWhitespaces != null)\n message.escapeWhitespaces = Boolean(object.escapeWhitespaces);\n if (object.normalizationRuleTsv != null)\n message.normalizationRuleTsv = String(object.normalizationRuleTsv);\n return message;\n };\n\n /**\n * Creates a plain object from a NormalizerSpec message. Also converts\n * values to other types if specified.\n * @function toObject\n * @memberof sentencepiece.NormalizerSpec\n * @static\n * @param {sentencepiece.NormalizerSpec} message NormalizerSpec\n * @param {$protobuf.IConversionOptions} [options] Conversion options\n * @returns {Object.<string,*>} Plain object\n */\n NormalizerSpec.toObject = function toObject(message, options) {\n if (!options) options = {};\n let object = {};\n if (options.defaults) {\n object.name = '';\n if (options.bytes === String)\n object.precompiledCharsmap = '';\n else {\n object.precompiledCharsmap = [];\n if (options.bytes !== Array)\n object.precompiledCharsmap =\n $util.newBuffer(object.precompiledCharsmap);\n }\n object.addDummyPrefix = true;\n object.removeExtraWhitespaces = true;\n object.escapeWhitespaces = true;\n object.normalizationRuleTsv = '';\n }\n if (message.name != null && message.hasOwnProperty('name'))\n object.name = message.name;\n if (message.precompiledCharsmap != null &&\n message.hasOwnProperty('precompiledCharsmap'))\n object.precompiledCharsmap = options.bytes === String ?\n $util.base64.encode(\n message.precompiledCharsmap, 0,\n message.precompiledCharsmap.length) :\n options.bytes === Array ?\n Array.prototype.slice.call(message.precompiledCharsmap) :\n message.precompiledCharsmap;\n if (message.addDummyPrefix != null &&\n message.hasOwnProperty('addDummyPrefix'))\n object.addDummyPrefix = message.addDummyPrefix;\n if (message.removeExtraWhitespaces != null &&\n message.hasOwnProperty('removeExtraWhitespaces'))\n object.removeExtraWhitespaces = message.removeExtraWhitespaces;\n if (message.escapeWhitespaces != null &&\n message.hasOwnProperty('escapeWhitespaces'))\n object.escapeWhitespaces = message.escapeWhitespaces;\n if (message.normalizationRuleTsv != null &&\n message.hasOwnProperty('normalizationRuleTsv'))\n object.normalizationRuleTsv = message.normalizationRuleTsv;\n return object;\n };\n\n /**\n * Converts this NormalizerSpec to JSON.\n * @function toJSON\n * @memberof sentencepiece.NormalizerSpec\n * @instance\n * @returns {Object.<string,*>} JSON object\n */\n NormalizerSpec.prototype.toJSON = function toJSON() {\n return this.constructor.toObject(this, $protobuf.util.toJSONOptions);\n };\n\n /**\n * Gets the default type url for NormalizerSpec\n * @function getTypeUrl\n * @memberof sentencepiece.NormalizerSpec\n * @static\n * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default\n * \"type.googleapis.com\")\n * @returns {string} The default type url\n */\n NormalizerSpec.getTypeUrl = function getTypeUrl(typeUrlPrefix) {\n if (typeUrlPrefix === undefined) {\n typeUrlPrefix = 'type.googleapis.com';\n }\n return typeUrlPrefix + '/sentencepiece.NormalizerSpec';\n };\n\n return NormalizerSpec;\n })();\n\n sentencepiece.SelfTestData = (function() {\n /**\n * Properties of a SelfTestData.\n * @memberof sentencepiece\n * @interface ISelfTestData\n * @property {Array.<sentencepiece.SelfTestData.ISample>|null} [samples]\n * SelfTestData samples\n */\n\n /**\n * Constructs a new SelfTestData.\n * @memberof sentencepiece\n * @classdesc Represents a SelfTestData.\n * @implements ISelfTestData\n * @constructor\n * @param {sentencepiece.ISelfTestData=} [properties] Properties to set\n */\n function SelfTestData(properties) {\n this.samples = [];\n if (properties)\n for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i)\n if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]];\n }\n\n /**\n * SelfTestData samples.\n * @member {Array.<sentencepiece.SelfTestData.ISample>} samples\n * @memberof sentencepiece.SelfTestData\n * @instance\n */\n SelfTestData.prototype.samples = $util.emptyArray;\n\n /**\n * Creates a new SelfTestData instance using the specified properties.\n * @function create\n * @memberof sentencepiece.SelfTestData\n * @static\n * @param {sentencepiece.ISelfTestData=} [properties] Properties to set\n * @returns {sentencepiece.SelfTestData} SelfTestData instance\n */\n SelfTestData.create = function create(properties) {\n return new SelfTestData(properties);\n };\n\n /**\n * Encodes the specified SelfTestData message. Does not implicitly {@link\n * sentencepiece.SelfTestData.verify|verify} messages.\n * @function encode\n * @memberof sentencepiece.SelfTestData\n * @static\n * @param {sentencepiece.ISelfTestData} message SelfTestData message or\n * plain object to encode\n * @param {$protobuf.Writer} [writer] Writer to encode to\n * @returns {$protobuf.Writer} Writer\n */\n SelfTestData.encode = function encode(message, writer) {\n if (!writer) writer = $Writer.create();\n if (message.samples != null && message.samples.length)\n for (let i = 0; i < message.samples.length; ++i)\n $root.sentencepiece.SelfTestData.Sample\n .encode(\n message.samples[i],\n writer.uint32(/* id 1, wireType 2 =*/ 10).fork())\n .ldelim();\n return writer;\n };\n\n /**\n * Encodes the specified SelfTestData message, length delimited. Does not\n * implicitly {@link sentencepiece.SelfTestData.verify|verify} messages.\n * @function encodeDelimited\n * @memberof sentencepiece.SelfTestData\n * @static\n * @param {sentencepiece.ISelfTestData} message SelfTestData message or\n * plain object to encode\n * @param {$protobuf.Writer} [writer] Writer to encode to\n * @returns {$protobuf.Writer} Writer\n */\n SelfTestData.encodeDelimited = function encodeDelimited(message, writer) {\n return this.encode(message, writer).ldelim();\n };\n\n /**\n * Decodes a SelfTestData message from the specified reader or buffer.\n * @function decode\n * @memberof sentencepiece.SelfTestData\n * @static\n * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode\n * from\n * @param {number} [length] Message length if known beforehand\n * @returns {sentencepiece.SelfTestData} SelfTestData\n * @throws {Error} If the payload is not a reader or valid buffer\n * @throws {$protobuf.util.ProtocolError} If required fields are missing\n */\n SelfTestData.decode = function decode(reader, length, error) {\n if (!(reader instanceof $Reader)) reader = $Reader.create(reader);\n let end = length === undefined ? reader.len : reader.pos + length,\n message = new $root.sentencepiece.SelfTestData();\n while (reader.pos < end) {\n let tag = reader.uint32();\n if (tag === error) break;\n switch (tag >>> 3) {\n case 1: {\n if (!(message.samples && message.samples.length))\n message.samples = [];\n message.samples.push($root.sentencepiece.SelfTestData.Sample.decode(\n reader, reader.uint32()));\n break;\n }\n default:\n reader.skipType(tag & 7);\n break;\n }\n }\n return message;\n };\n\n /**\n * Decodes a SelfTestData message from the specified reader or buffer,\n * length delimited.\n * @function decodeDelimited\n * @memberof sentencepiece.SelfTestData\n * @static\n * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode\n * from\n * @returns {sentencepiece.SelfTestData} SelfTestData\n * @throws {Error} If the payload is not a reader or valid buffer\n * @throws {$protobuf.util.ProtocolError} If required fields are missing\n */\n SelfTestData.decodeDelimited = function decodeDelimited(reader) {\n if (!(reader instanceof $Reader)) reader = new $Reader(reader);\n return this.decode(reader, reader.uint32());\n };\n\n /**\n * Verifies a SelfTestData message.\n * @function verify\n * @memberof sentencepiece.SelfTestData\n * @static\n * @param {Object.<string,*>} message Plain object to verify\n * @returns {string|null} `null` if valid, otherwise the reason why it is\n * not\n */\n SelfTestData.verify = function verify(message) {\n if (typeof message !== 'object' || message === null)\n return 'object expected';\n if (message.samples != null && message.hasOwnProperty('samples')) {\n if (!Array.isArray(message.samples)) return 'samples: array expected';\n for (let i = 0; i < message.samples.length; ++i) {\n let error = $root.sentencepiece.SelfTestData.Sample.verify(\n message.samples[i]);\n if (error) return 'samples.' + error;\n }\n }\n return null;\n };\n\n /**\n * Creates a SelfTestData message from a plain object. Also converts values\n * to their respective internal types.\n * @function fromObject\n * @memberof sentencepiece.SelfTestData\n * @static\n * @param {Object.<string,*>} object Plain object\n * @returns {sentencepiece.SelfTestData} SelfTestData\n */\n SelfTestData.fromObject = function fromObject(object) {\n if (object instanceof $root.sentencepiece.SelfTestData) return object;\n let message = new $root.sentencepiece.SelfTestData();\n if (object.samples) {\n if (!Array.isArray(object.samples))\n throw TypeError(\n '.sentencepiece.SelfTestData.samples: array expected');\n message.samples = [];\n for (let i = 0; i < object.samples.length; ++i) {\n if (typeof object.samples[i] !== 'object')\n throw TypeError(\n '.sentencepiece.SelfTestData.samples: object expected');\n message.samples[i] =\n $root.sentencepiece.SelfTestData.Sample.fromObject(\n object.samples[i]);\n }\n }\n return message;\n };\n\n /**\n * Creates a plain object from a SelfTestData message. Also converts values\n * to other types if specified.\n * @function toObject\n * @memberof sentencepiece.SelfTestData\n * @static\n * @param {sentencepiece.SelfTestData} message SelfTestData\n * @param {$protobuf.IConversionOptions} [options] Conversion options\n * @returns {Object.<string,*>} Plain object\n */\n SelfTestData.toObject = function toObject(message, options) {\n if (!options) options = {};\n let object = {};\n if (options.arrays || options.defaults) object.samples = [];\n if (message.samples && message.samples.length) {\n object.samples = [];\n for (let j = 0; j < message.samples.length; ++j)\n object.samples[j] = $root.sentencepiece.SelfTestData.Sample.toObject(\n message.samples[j], options);\n }\n return object;\n };\n\n /**\n * Converts this SelfTestData to JSON.\n * @function toJSON\n * @memberof sentencepiece.SelfTestData\n * @instance\n * @returns {Object.<string,*>} JSON object\n */\n SelfTestData.prototype.toJSON = function toJSON() {\n return this.constructor.toObject(this, $protobuf.util.toJSONOptions);\n };\n\n /**\n * Gets the default type url for SelfTestData\n * @function getTypeUrl\n * @memberof sentencepiece.SelfTestData\n * @static\n * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default\n * \"type.googleapis.com\")\n * @returns {string} The default type url\n */\n SelfTestData.getTypeUrl = function getTypeUrl(typeUrlPrefix) {\n if (typeUrlPrefix === undefined) {\n typeUrlPrefix = 'type.googleapis.com';\n }\n return typeUrlPrefix + '/sentencepiece.SelfTestData';\n };\n\n SelfTestData.Sample = (function() {\n /**\n * Properties of a Sample.\n * @memberof sentencepiece.SelfTestData\n * @interface ISample\n * @property {string|null} [input] Sample input\n * @property {string|null} [expected] Sample expected\n */\n\n /**\n * Constructs a new Sample.\n * @memberof sentencepiece.SelfTestData\n * @classdesc Represents a Sample.\n * @implements ISample\n * @constructor\n * @param {sentencepiece.SelfTestData.ISample=} [properties] Properties to\n * set\n */\n function Sample(properties) {\n if (properties)\n for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i)\n if (properties[keys[i]] != null)\n this[keys[i]] = properties[keys[i]];\n }\n\n /**\n * Sample input.\n * @member {string} input\n * @memberof sentencepiece.SelfTestData.Sample\n * @instance\n */\n Sample.prototype.input = '';\n\n /**\n * Sample expected.\n * @member {string} expected\n * @memberof sentencepiece.SelfTestData.Sample\n * @instance\n */\n Sample.prototype.expected = '';\n\n /**\n * Creates a new Sample instance using the specified properties.\n * @function create\n * @memberof sentencepiece.SelfTestData.Sample\n * @static\n * @param {sentencepiece.SelfTestData.ISample=} [properties] Properties to\n * set\n * @returns {sentencepiece.SelfTestData.Sample} Sample instance\n */\n Sample.create = function create(properties) {\n return new Sample(properties);\n };\n\n /**\n * Encodes the specified Sample message. Does not implicitly {@link\n * sentencepiece.SelfTestData.Sample.verify|verify} messages.\n * @function encode\n * @memberof sentencepiece.SelfTestData.Sample\n * @static\n * @param {sentencepiece.SelfTestData.ISample} message Sample message or\n * plain object to encode\n * @param {$protobuf.Writer} [writer] Writer to encode to\n * @returns {$protobuf.Writer} Writer\n */\n Sample.encode = function encode(message, writer) {\n if (!writer) writer = $Writer.create();\n if (message.input != null &&\n Object.hasOwnProperty.call(message, 'input'))\n writer.uint32(/* id 1, wireType 2 =*/ 10).string(message.input);\n if (message.expected != null &&\n Object.hasOwnProperty.call(message, 'expected'))\n writer.uint32(/* id 2, wireType 2 =*/ 18).string(message.expected);\n return writer;\n };\n\n /**\n * Encodes the specified Sample message, length delimited. Does not\n * implicitly {@link sentencepiece.SelfTestData.Sample.verify|verify}\n * messages.\n * @function encodeDelimited\n * @memberof sentencepiece.SelfTestData.Sample\n * @static\n * @param {sentencepiece.SelfTestData.ISample} message Sample message or\n * plain object to encode\n * @param {$protobuf.Writer} [writer] Writer to encode to\n * @returns {$protobuf.Writer} Writer\n */\n Sample.encodeDelimited = function encodeDelimited(message, writer) {\n return this.encode(message, writer).ldelim();\n };\n\n /**\n * Decodes a Sample message from the specified reader or buffer.\n * @function decode\n * @memberof sentencepiece.SelfTestData.Sample\n * @static\n * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode\n * from\n * @param {number} [length] Message length if known beforehand\n * @returns {sentencepiece.SelfTestData.Sample} Sample\n * @throws {Error} If the payload is not a reader or valid buffer\n * @throws {$protobuf.util.ProtocolError} If required fields are missing\n */\n Sample.decode = function decode(reader, length, error) {\n if (!(reader instanceof $Reader)) reader = $Reader.create(reader);\n let end = length === undefined ? reader.len : reader.pos + length,\n message = new $root.sentencepiece.SelfTestData.Sample();\n while (reader.pos < end) {\n let tag = reader.uint32();\n if (tag === error) break;\n switch (tag >>> 3) {\n case 1: {\n message.input = reader.string();\n break;\n }\n case 2: {\n message.expected = reader.string();\n break;\n }\n default:\n reader.skipType(tag & 7);\n break;\n }\n }\n return message;\n };\n\n /**\n * Decodes a Sample message from the specified reader or buffer, length\n * delimited.\n * @function decodeDelimited\n * @memberof sentencepiece.SelfTestData.Sample\n * @static\n * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode\n * from\n * @returns {sentencepiece.SelfTestData.Sample} Sample\n * @throws {Error} If the payload is not a reader or valid buffer\n * @throws {$protobuf.util.ProtocolError} If required fields are missing\n */\n Sample.decodeDelimited = function decodeDelimited(reader) {\n if (!(reader instanceof $Reader)) reader = new $Reader(reader);\n return this.decode(reader, reader.uint32());\n };\n\n /**\n * Verifies a Sample message.\n * @function verify\n * @memberof sentencepiece.SelfTestData.Sample\n * @static\n * @param {Object.<string,*>} message Plain object to verify\n * @returns {string|null} `null` if valid, otherwise the reason why it is\n * not\n */\n Sample.verify = function verify(message) {\n if (typeof message !== 'object' || message === null)\n return 'object expected';\n if (message.input != null && message.hasOwnProperty('input'))\n if (!$util.isString(message.input)) return 'input: string expected';\n if (message.expected != null && message.hasOwnProperty('expected'))\n if (!$util.isString(message.expected))\n return 'expected: string expected';\n return null;\n };\n\n /**\n * Creates a Sample message from a plain object. Also converts values to\n * their respective internal types.\n * @function fromObject\n * @memberof sentencepiece.SelfTestData.Sample\n * @static\n * @param {Object.<string,*>} object Plain object\n * @returns {sentencepiece.SelfTestData.Sample} Sample\n */\n Sample.fromObject = function fromObject(object) {\n if (object instanceof $root.sentencepiece.SelfTestData.Sample)\n return object;\n let message = new $root.sentencepiece.SelfTestData.Sample();\n if (object.input != null) message.input = String(object.input);\n if (object.expected != null) message.expected = String(object.expected);\n return message;\n };\n\n /**\n * Creates a plain object from a Sample message. Also converts values to\n * other types if specified.\n * @function toObject\n * @memberof sentencepiece.SelfTestData.Sample\n * @static\n * @param {sentencepiece.SelfTestData.Sample} message Sample\n * @param {$protobuf.IConversionOptions} [options] Conversion options\n * @returns {Object.<string,*>} Plain object\n */\n Sample.toObject = function toObject(message, options) {\n if (!options) options = {};\n let object = {};\n if (options.defaults) {\n object.input = '';\n object.expected = '';\n }\n if (message.input != null && message.hasOwnProperty('input'))\n object.input = message.input;\n if (message.expected != null && message.hasOwnProperty('expected'))\n object.expected = message.expected;\n return object;\n };\n\n /**\n * Converts this Sample to JSON.\n * @function toJSON\n * @memberof sentencepiece.SelfTestData.Sample\n * @instance\n * @returns {Object.<string,*>} JSON object\n */\n Sample.prototype.toJSON = function toJSON() {\n return this.constructor.toObject(this, $protobuf.util.toJSONOptions);\n };\n\n /**\n * Gets the default type url for Sample\n * @function getTypeUrl\n * @memberof sentencepiece.SelfTestData.Sample\n * @static\n * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default\n * \"type.googleapis.com\")\n * @returns {string} The default type url\n */\n Sample.getTypeUrl = function getTypeUrl(typeUrlPrefix) {\n if (typeUrlPrefix === undefined) {\n typeUrlPrefix = 'type.googleapis.com';\n }\n return typeUrlPrefix + '/sentencepiece.SelfTestData.Sample';\n };\n\n return Sample;\n })();\n\n return SelfTestData;\n })();\n\n sentencepiece.ModelProto = (function() {\n /**\n * Properties of a ModelProto.\n * @memberof sentencepiece\n * @interface IModelProto\n * @property {Array.<sentencepiece.ModelProto.ISentencePiece>|null} [pieces]\n * ModelProto pieces\n * @property {sentencepiece.ITrainerSpec|null} [trainerSpec] ModelProto\n * trainerSpec\n * @property {sentencepiece.INormalizerSpec|null} [normalizerSpec]\n * ModelProto normalizerSpec\n * @property {sentencepiece.ISelfTestData|null} [selfTestData] ModelProto\n * selfTestData\n * @property {sentencepiece.INormalizerSpec|null} [denormalizerSpec]\n * ModelProto denormalizerSpec\n */\n\n /**\n * Constructs a new ModelProto.\n * @memberof sentencepiece\n * @classdesc Represents a ModelProto.\n * @implements IModelProto\n * @constructor\n * @param {sentencepiece.IModelProto=} [properties] Properties to set\n */\n function ModelProto(properties) {\n this.pieces = [];\n if (properties)\n for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i)\n if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]];\n }\n\n /**\n * ModelProto pieces.\n * @member {Array.<sentencepiece.ModelProto.ISentencePiece>} pieces\n * @memberof sentencepiece.ModelProto\n * @instance\n */\n ModelProto.prototype.pieces = $util.emptyArray;\n\n /**\n * ModelProto trainerSpec.\n * @member {sentencepiece.ITrainerSpec|null|undefined} trainerSpec\n * @memberof sentencepiece.ModelProto\n * @instance\n */\n ModelProto.prototype.trainerSpec = null;\n\n /**\n * ModelProto normalizerSpec.\n * @member {sentencepiece.INormalizerSpec|null|undefined} normalizerSpec\n * @memberof sentencepiece.ModelProto\n * @instance\n */\n ModelProto.prototype.normalizerSpec = null;\n\n /**\n * ModelProto selfTestData.\n * @member {sentencepiece.ISelfTestData|null|undefined} selfTestData\n * @memberof sentencepiece.ModelProto\n * @instance\n */\n ModelProto.prototype.selfTestData = null;\n\n /**\n * ModelProto denormalizerSpec.\n * @member {sentencepiece.INormalizerSpec|null|undefined} denormalizerSpec\n * @memberof sentencepiece.ModelProto\n * @instance\n */\n ModelProto.prototype.denormalizerSpec = null;\n\n /**\n * Creates a new ModelProto instance using the specified properties.\n * @function create\n * @memberof sentencepiece.ModelProto\n * @static\n * @param {sentencepiece.IModelProto=} [properties] Properties to set\n * @returns {sentencepiece.ModelProto} ModelProto instance\n */\n ModelProto.create = function create(properties) {\n return new ModelProto(properties);\n };\n\n /**\n * Encodes the specified ModelProto message. Does not implicitly {@link\n * sentencepiece.ModelProto.verify|verify} messages.\n * @function encode\n * @memberof sentencepiece.ModelProto\n * @static\n * @param {sentencepiece.IModelProto} message ModelProto message or plain\n * object to encode\n * @param {$protobuf.Writer} [writer] Writer to encode to\n * @returns {$protobuf.Writer} Writer\n */\n ModelProto.encode = function encode(message, writer) {\n if (!writer) writer = $Writer.create();\n if (message.pieces != null && message.pieces.length)\n for (let i = 0; i < message.pieces.length; ++i)\n $root.sentencepiece.ModelProto.SentencePiece\n .encode(\n message.pieces[i],\n writer.uint32(/* id 1, wireType 2 =*/ 10).fork())\n .ldelim();\n if (message.trainerSpec != null &&\n Object.hasOwnProperty.call(message, 'trainerSpec'))\n $root.sentencepiece.TrainerSpec\n .encode(\n message.trainerSpec,\n writer.uint32(/* id 2, wireType 2 =*/ 18).fork())\n .ldelim();\n if (message.normalizerSpec != null &&\n Object.hasOwnProperty.call(message, 'normalizerSpec'))\n $root.sentencepiece.NormalizerSpec\n .encode(\n message.normalizerSpec,\n writer.uint32(/* id 3, wireType 2 =*/ 26).fork())\n .ldelim();\n if (message.selfTestData != null &&\n Object.hasOwnProperty.call(message, 'selfTestData'))\n $root.sentencepiece.SelfTestData\n .encode(\n message.selfTestData,\n writer.uint32(/* id 4, wireType 2 =*/ 34).fork())\n .ldelim();\n if (message.denormalizerSpec != null &&\n Object.hasOwnProperty.call(message, 'denormalizerSpec'))\n $root.sentencepiece.NormalizerSpec\n .encode(\n message.denormalizerSpec,\n writer.uint32(/* id 5, wireType 2 =*/ 42).fork())\n .ldelim();\n return writer;\n };\n\n /**\n * Encodes the specified ModelProto message, length delimited. Does not\n * implicitly {@link sentencepiece.ModelProto.verify|verify} messages.\n * @function encodeDelimited\n * @memberof sentencepiece.ModelProto\n * @static\n * @param {sentencepiece.IModelProto} message ModelProto message or plain\n * object to encode\n * @param {$protobuf.Writer} [writer] Writer to encode to\n * @returns {$protobuf.Writer} Writer\n */\n ModelProto.encodeDelimited = function encodeDelimited(message, writer) {\n return this.encode(message, writer).ldelim();\n };\n\n /**\n * Decodes a ModelProto message from the specified reader or buffer.\n * @function decode\n * @memberof sentencepiece.ModelProto\n * @static\n * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode\n * from\n * @param {number} [length] Message length if known beforehand\n * @returns {sentencepiece.ModelProto} ModelProto\n * @throws {Error} If the payload is not a reader or valid buffer\n * @throws {$protobuf.util.ProtocolError} If required fields are missing\n */\n ModelProto.decode = function decode(reader, length, error) {\n if (!(reader instanceof $Reader)) reader = $Reader.create(reader);\n let end = length === undefined ? reader.len : reader.pos + length,\n message = new $root.sentencepiece.ModelProto();\n while (reader.pos < end) {\n let tag = reader.uint32();\n if (tag === error) break;\n switch (tag >>> 3) {\n case 1: {\n if (!(message.pieces && message.pieces.length)) message.pieces = [];\n message.pieces.push(\n $root.sentencepiece.ModelProto.SentencePiece.decode(\n reader, reader.uint32()));\n break;\n }\n case 2: {\n message.trainerSpec =\n $root.sentencepiece.TrainerSpec.decode(reader, reader.uint32());\n break;\n }\n case 3: {\n message.normalizerSpec = $root.sentencepiece.NormalizerSpec.decode(\n reader, reader.uint32());\n break;\n }\n case 4: {\n message.selfTestData = $root.sentencepiece.SelfTestData.decode(\n reader, reader.uint32());\n break;\n }\n case 5: {\n message.denormalizerSpec =\n $root.sentencepiece.NormalizerSpec.decode(\n reader, reader.uint32());\n break;\n }\n default:\n reader.skipType(tag & 7);\n break;\n }\n }\n return message;\n };\n\n /**\n * Decodes a ModelProto message from the specified reader or buffer, length\n * delimited.\n * @function decodeDelimited\n * @memberof sentencepiece.ModelProto\n * @static\n * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode\n * from\n * @returns {sentencepiece.ModelProto} ModelProto\n * @throws {Error} If the payload is not a reader or valid buffer\n * @throws {$protobuf.util.ProtocolError} If required fields are missing\n */\n ModelProto.decodeDelimited = function decodeDelimited(reader) {\n if (!(reader instanceof $Reader)) reader = new $Reader(reader);\n return this.decode(reader, reader.uint32());\n };\n\n /**\n * Verifies a ModelProto message.\n * @function verify\n * @memberof sentencepiece.ModelProto\n * @static\n * @param {Object.<string,*>} message Plain object to verify\n * @returns {string|null} `null` if valid, otherwise the reason why it is\n * not\n */\n ModelProto.verify = function verify(message) {\n if (typeof message !== 'object' || message === null)\n return 'object expected';\n if (message.pieces != null && message.hasOwnProperty('pieces')) {\n if (!Array.isArray(message.pieces)) return 'pieces: array expected';\n for (let i = 0; i < message.pieces.length; ++i) {\n let error = $root.sentencepiece.ModelProto.SentencePiece.verify(\n message.pieces[i]);\n if (error) return 'pieces.' + error;\n }\n }\n if (message.trainerSpec != null &&\n message.hasOwnProperty('trainerSpec')) {\n let error = $root.sentencepiece.TrainerSpec.verify(message.trainerSpec);\n if (error) return 'trainerSpec.' + error;\n }\n if (message.normalizerSpec != null &&\n message.hasOwnProperty('normalizerSpec')) {\n let error =\n $root.sentencepiece.NormalizerSpec.verify(message.normalizerSpec);\n if (error) return 'normalizerSpec.' + error;\n }\n if (message.selfTestData != null &&\n message.hasOwnProperty('selfTestData')) {\n let error =\n $root.sentencepiece.SelfTestData.verify(message.selfTestData);\n if (error) return 'selfTestData.' + error;\n }\n if (message.denormalizerSpec != null &&\n message.hasOwnProperty('denormalizerSpec')) {\n let error =\n $root.sentencepiece.NormalizerSpec.verify(message.denormalizerSpec);\n if (error) return 'denormalizerSpec.' + error;\n }\n return null;\n };\n\n /**\n * Creates a ModelProto message from a plain object. Also converts values to\n * their respective internal types.\n * @function fromObject\n * @memberof sentencepiece.ModelProto\n * @static\n * @param {Object.<string,*>} object Plain object\n * @returns {sentencepiece.ModelProto} ModelProto\n */\n ModelProto.fromObject = function fromObject(object) {\n if (object instanceof $root.sentencepiece.ModelProto) return object;\n let message = new $root.sentencepiece.ModelProto();\n if (object.pieces) {\n if (!Array.isArray(object.pieces))\n throw TypeError('.sentencepiece.ModelProto.pieces: array expected');\n message.pieces = [];\n for (let i = 0; i < object.pieces.length; ++i) {\n if (typeof object.pieces[i] !== 'object')\n throw TypeError(\n '.sentencepiece.ModelProto.pieces: object expected');\n message.pieces[i] =\n $root.sentencepiece.ModelProto.SentencePiece.fromObject(\n object.pieces[i]);\n }\n }\n if (object.trainerSpec != null) {\n if (typeof object.trainerSpec !== 'object')\n throw TypeError(\n '.sentencepiece.ModelProto.trainerSpec: object expected');\n message.trainerSpec =\n $root.sentencepiece.TrainerSpec.fromObject(object.trainerSpec);\n }\n if (object.normalizerSpec != null) {\n if (typeof object.normalizerSpec !== 'object')\n throw TypeError(\n '.sentencepiece.ModelProto.normalizerSpec: object expected');\n message.normalizerSpec = $root.sentencepiece.NormalizerSpec.fromObject(\n object.normalizerSpec);\n }\n if (object.selfTestData != null) {\n if (typeof object.selfTestData !== 'object')\n throw TypeError(\n '.sentencepiece.ModelProto.selfTestData: object expected');\n message.selfTestData =\n $root.sentencepiece.SelfTestData.fromObject(object.selfTestData);\n }\n if (object.denormalizerSpec != null) {\n if (typeof object.denormalizerSpec !== 'object')\n throw TypeError(\n '.sentencepiece.ModelProto.denormalizerSpec: object expected');\n message.denormalizerSpec =\n $root.sentencepiece.NormalizerSpec.fromObject(\n object.denormalizerSpec);\n }\n return message;\n };\n\n /**\n * Creates a plain object from a ModelProto message. Also converts values to\n * other types if specified.\n * @function toObject\n * @memberof sentencepiece.ModelProto\n * @static\n * @param {sentencepiece.ModelProto} message ModelProto\n * @param {$protobuf.IConversionOptions} [options] Conversion options\n * @returns {Object.<string,*>} Plain object\n */\n ModelProto.toObject = function toObject(message, options) {\n if (!options) options = {};\n let object = {};\n if (options.arrays || options.defaults) object.pieces = [];\n if (options.defaults) {\n object.trainerSpec = null;\n object.normalizerSpec = null;\n object.selfTestData = null;\n object.denormalizerSpec = null;\n }\n if (message.pieces && message.pieces.length) {\n object.pieces = [];\n for (let j = 0; j < message.pieces.length; ++j)\n object.pieces[j] =\n $root.sentencepiece.ModelProto.SentencePiece.toObject(\n message.pieces[j], options);\n }\n if (message.trainerSpec != null && message.hasOwnProperty('trainerSpec'))\n object.trainerSpec = $root.sentencepiece.TrainerSpec.toObject(\n message.trainerSpec, options);\n if (message.normalizerSpec != null &&\n message.hasOwnProperty('normalizerSpec'))\n object.normalizerSpec = $root.sentencepiece.NormalizerSpec.toObject(\n message.normalizerSpec, options);\n if (message.selfTestData != null &&\n message.hasOwnProperty('selfTestData'))\n object.selfTestData = $root.sentencepiece.SelfTestData.toObject(\n message.selfTestData, options);\n if (message.denormalizerSpec != null &&\n message.hasOwnProperty('denormalizerSpec'))\n object.denormalizerSpec = $root.sentencepiece.NormalizerSpec.toObject(\n message.denormalizerSpec, options);\n return object;\n };\n\n /**\n * Converts this ModelProto to JSON.\n * @function toJSON\n * @memberof sentencepiece.ModelProto\n * @instance\n * @returns {Object.<string,*>} JSON object\n */\n ModelProto.prototype.toJSON = function toJSON() {\n return this.constructor.toObject(this, $protobuf.util.toJSONOptions);\n };\n\n /**\n * Gets the default type url for ModelProto\n * @function getTypeUrl\n * @memberof sentencepiece.ModelProto\n * @static\n * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default\n * \"type.googleapis.com\")\n * @returns {string} The default type url\n */\n ModelProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) {\n if (typeUrlPrefix === undefined) {\n typeUrlPrefix = 'type.googleapis.com';\n }\n return typeUrlPrefix + '/sentencepiece.ModelProto';\n };\n\n ModelProto.SentencePiece = (function() {\n /**\n * Properties of a SentencePiece.\n * @memberof sentencepiece.ModelProto\n * @interface ISentencePiece\n * @property {string|null} [piece] SentencePiece piece\n * @property {number|null} [score] SentencePiece score\n * @property {sentencepiece.ModelProto.SentencePiece.Type|null} [type]\n * SentencePiece type\n */\n\n /**\n * Constructs a new SentencePiece.\n * @memberof sentencepiece.ModelProto\n * @classdesc Represents a SentencePiece.\n * @implements ISentencePiece\n * @constructor\n * @param {sentencepiece.ModelProto.ISentencePiece=} [properties]\n * Properties to set\n */\n function SentencePiece(properties) {\n if (properties)\n for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i)\n if (properties[keys[i]] != null)\n this[keys[i]] = properties[keys[i]];\n }\n\n /**\n * SentencePiece piece.\n * @member {string} piece\n * @memberof sentencepiece.ModelProto.SentencePiece\n * @instance\n */\n SentencePiece.prototype.piece = '';\n\n /**\n * SentencePiece score.\n * @member {number} score\n * @memberof sentencepiece.ModelProto.SentencePiece\n * @instance\n */\n SentencePiece.prototype.score = 0;\n\n /**\n * SentencePiece type.\n * @member {sentencepiece.ModelProto.SentencePiece.Type} type\n * @memberof sentencepiece.ModelProto.SentencePiece\n * @instance\n */\n SentencePiece.prototype.type = 1;\n\n /**\n * Creates a new SentencePiece instance using the specified properties.\n * @function create\n * @memberof sentencepiece.ModelProto.SentencePiece\n * @static\n * @param {sentencepiece.ModelProto.ISentencePiece=} [properties]\n * Properties to set\n * @returns {sentencepiece.ModelProto.SentencePiece} SentencePiece\n * instance\n */\n SentencePiece.create = function create(properties) {\n return new SentencePiece(properties);\n };\n\n /**\n * Encodes the specified SentencePiece message. Does not implicitly {@link\n * sentencepiece.ModelProto.SentencePiece.verify|verify} messages.\n * @function encode\n * @memberof sentencepiece.ModelProto.SentencePiece\n * @static\n * @param {sentencepiece.ModelProto.ISentencePiece} message SentencePiece\n * message or plain object to encode\n * @param {$protobuf.Writer} [writer] Writer to encode to\n * @returns {$protobuf.Writer} Writer\n */\n SentencePiece.encode = function encode(message, writer) {\n if (!writer) writer = $Writer.create();\n if (message.piece != null &&\n Object.hasOwnProperty.call(message, 'piece'))\n writer.uint32(/* id 1, wireType 2 =*/ 10).string(message.piece);\n if (message.score != null &&\n Object.hasOwnProperty.call(message, 'score'))\n writer.uint32(/* id 2, wireType 5 =*/ 21).float(message.score);\n if (message.type != null && Object.hasOwnProperty.call(message, 'type'))\n writer.uint32(/* id 3, wireType 0 =*/ 24).int32(message.type);\n return writer;\n };\n\n /**\n * Encodes the specified SentencePiece message, length delimited. Does not\n * implicitly {@link sentencepiece.ModelProto.SentencePiece.verify|verify}\n * messages.\n * @function encodeDelimited\n * @memberof sentencepiece.ModelProto.SentencePiece\n * @static\n * @param {sentencepiece.ModelProto.ISentencePiece} message SentencePiece\n * message or plain object to encode\n * @param {$protobuf.Writer} [writer] Writer to encode to\n * @returns {$protobuf.Writer} Writer\n */\n SentencePiece.encodeDelimited = function encodeDelimited(\n message, writer) {\n return this.encode(message, writer).ldelim();\n };\n\n /**\n * Decodes a SentencePiece message from the specified reader or buffer.\n * @function decode\n * @memberof sentencepiece.ModelProto.SentencePiece\n * @static\n * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode\n * from\n * @param {number} [length] Message length if known beforehand\n * @returns {sentencepiece.ModelProto.SentencePiece} SentencePiece\n * @throws {Error} If the payload is not a reader or valid buffer\n * @throws {$protobuf.util.ProtocolError} If required fields are missing\n */\n SentencePiece.decode = function decode(reader, length, error) {\n if (!(reader instanceof $Reader)) reader = $Reader.create(reader);\n let end = length === undefined ? reader.len : reader.pos + length,\n message = new $root.sentencepiece.ModelProto.SentencePiece();\n while (reader.pos < end) {\n let tag = reader.uint32();\n if (tag === error) break;\n switch (tag >>> 3) {\n case 1: {\n message.piece = reader.string();\n break;\n }\n case 2: {\n message.score = reader.float();\n break;\n }\n case 3: {\n message.type = reader.int32();\n break;\n }\n default:\n reader.skipType(tag & 7);\n break;\n }\n }\n return message;\n };\n\n /**\n * Decodes a SentencePiece message from the specified reader or buffer,\n * length delimited.\n * @function decodeDelimited\n * @memberof sentencepiece.ModelProto.SentencePiece\n * @static\n * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode\n * from\n * @returns {sentencepiece.ModelProto.SentencePiece} SentencePiece\n * @throws {Error} If the payload is not a reader or valid buffer\n * @throws {$protobuf.util.ProtocolError} If required fields are missing\n */\n SentencePiece.decodeDelimited = function decodeDelimited(reader) {\n if (!(reader instanceof $Reader)) reader = new $Reader(reader);\n return this.decode(reader, reader.uint32());\n };\n\n /**\n * Verifies a SentencePiece message.\n * @function verify\n * @memberof sentencepiece.ModelProto.SentencePiece\n * @static\n * @param {Object.<string,*>} message Plain object to verify\n * @returns {string|null} `null` if valid, otherwise the reason why it is\n * not\n */\n SentencePiece.verify = function verify(message) {\n if (typeof message !== 'object' || message === null)\n return 'object expected';\n if (message.piece != null && message.hasOwnProperty('piece'))\n if (!$util.isString(message.piece)) return 'piece: string expected';\n if (message.score != null && message.hasOwnProperty('score'))\n if (typeof message.score !== 'number')\n return 'score: number expected';\n if (message.type != null && message.hasOwnProperty('type'))\n switch (message.type) {\n default:\n return 'type: enum value expected';\n case 1:\n case 2:\n case 3:\n case 4:\n case 6:\n case 5:\n break;\n }\n return null;\n };\n\n /**\n * Creates a SentencePiece message from a plain object. Also converts\n * values to their respective internal types.\n * @function fromObject\n * @memberof sentencepiece.ModelProto.SentencePiece\n * @static\n * @param {Object.<string,*>} object Plain object\n * @returns {sentencepiece.ModelProto.SentencePiece} SentencePiece\n */\n SentencePiece.fromObject = function fromObject(object) {\n if (object instanceof $root.sentencepiece.ModelProto.SentencePiece)\n return object;\n let message = new $root.sentencepiece.ModelProto.SentencePiece();\n if (object.piece != null) message.piece = String(object.piece);\n if (object.score != null) message.score = Number(object.score);\n switch (object.type) {\n default:\n if (typeof object.type === 'number') {\n message.type = object.type;\n break;\n }\n break;\n case 'NORMAL':\n case 1:\n message.type = 1;\n break;\n case 'UNKNOWN':\n case 2:\n message.type = 2;\n break;\n case 'CONTROL':\n case 3:\n message.type = 3;\n break;\n case 'USER_DEFINED':\n case 4:\n message.type = 4;\n break;\n case 'BYTE':\n case 6:\n message.type = 6;\n break;\n case 'UNUSED':\n case 5:\n message.type = 5;\n break;\n }\n return message;\n };\n\n /**\n * Creates a plain object from a SentencePiece message. Also converts\n * values to other types if specified.\n * @function toObject\n * @memberof sentencepiece.ModelProto.SentencePiece\n * @static\n * @param {sentencepiece.ModelProto.SentencePiece} message SentencePiece\n * @param {$protobuf.IConversionOptions} [options] Conversion options\n * @returns {Object.<string,*>} Plain object\n */\n SentencePiece.toObject = function toObject(message, options) {\n if (!options) options = {};\n let object = {};\n if (options.defaults) {\n object.piece = '';\n object.score = 0;\n object.type = options.enums === String ? 'NORMAL' : 1;\n }\n if (message.piece != null && message.hasOwnProperty('piece'))\n object.piece = message.piece;\n if (message.score != null && message.hasOwnProperty('score'))\n object.score = options.json && !isFinite(message.score) ?\n String(message.score) :\n message.score;\n if (message.type != null && message.hasOwnProperty('type'))\n object.type = options.enums === String ?\n $root.sentencepiece.ModelProto.SentencePiece\n .Type[message.type] === undefined ?\n message.type :\n $root.sentencepiece.ModelProto.SentencePiece.Type[message.type] :\n message.type;\n return object;\n };\n\n /**\n * Converts this SentencePiece to JSON.\n * @function toJSON\n * @memberof sentencepiece.ModelProto.SentencePiece\n * @instance\n * @returns {Object.<string,*>} JSON object\n */\n SentencePiece.prototype.toJSON = function toJSON() {\n return this.constructor.toObject(this, $protobuf.util.toJSONOptions);\n };\n\n /**\n * Gets the default type url for SentencePiece\n * @function getTypeUrl\n * @memberof sentencepiece.ModelProto.SentencePiece\n * @static\n * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default\n * \"type.googleapis.com\")\n * @returns {string} The default type url\n */\n SentencePiece.getTypeUrl = function getTypeUrl(typeUrlPrefix) {\n if (typeUrlPrefix === undefined) {\n typeUrlPrefix = 'type.googleapis.com';\n }\n return typeUrlPrefix + '/sentencepiece.ModelProto.SentencePiece';\n };\n\n /**\n * Type enum.\n * @name sentencepiece.ModelProto.SentencePiece.Type\n * @enum {number}\n * @property {number} NORMAL=1 NORMAL value\n * @property {number} UNKNOWN=2 UNKNOWN value\n * @property {number} CONTROL=3 CONTROL value\n * @property {number} USER_DEFINED=4 USER_DEFINED value\n * @property {number} BYTE=6 BYTE value\n * @property {number} UNUSED=5 UNUSED value\n */\n SentencePiece.Type = (function() {\n const valuesById = {}, values = Object.create(valuesById);\n values[valuesById[1] = 'NORMAL'] = 1;\n values[valuesById[2] = 'UNKNOWN'] = 2;\n values[valuesById[3] = 'CONTROL'] = 3;\n values[valuesById[4] = 'USER_DEFINED'] = 4;\n values[valuesById[6] = 'BYTE'] = 6;\n values[valuesById[5] = 'UNUSED'] = 5;\n return values;\n })();\n\n return SentencePiece;\n })();\n\n return ModelProto;\n })();\n\n return sentencepiece;\n})();\n\nexport {$root as default};\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Pure TypeScript implementation of SentencePiece tokenizer.\n * Translated from github.com/eliben/go-sentencepiece\n */\n\nimport {ModelProto, ModelType, SentencePieceType} from './_model.js';\nimport {PrefixMatcher} from './_prefix_matcher.js';\nimport {PriorityQueue} from './_priority_queue.js';\nimport {sentencepiece} from './sentencepiece_model.pb.js';\n\nconst WHITESPACE_SEPARATOR = '▁';\n\n/** Token represents a single token from the input text */\nexport interface Token {\n id: number;\n text: string;\n}\n\n/** Model information */\nexport interface ModelInfo {\n vocabularySize: number;\n beginningOfSentenceID: number;\n endOfSentenceID: number;\n unknownID: number;\n padID: number;\n}\n\nconst SYMBOL_BOS = '<bos>';\nconst SYMBOL_EOS = '<eos>';\nconst SYMBOL_PAD = '<pad>';\n\n/**\n * Processor represents a SentencePiece processor (tokenizer).\n * It converts input text into a sequence of tokens and back.\n */\nexport class SentencePieceProcessor {\n private model: ModelProto;\n private pieces: Map<string, number>;\n private reserved: Map<string, number>;\n private unknownID: number;\n private userDefinedMatcher: PrefixMatcher;\n private byte2Token: Map<number, Token>;\n private idToByte: Map<number, number>;\n private maxPieceLength: number;\n\n /**\n * Creates a new Processor from model proto bytes.\n */\n constructor(modelProtoBytes: Uint8Array) {\n this.model = this.parseModelProto(modelProtoBytes);\n\n const tspec = this.model.trainerSpec;\n if (!tspec || tspec.modelType !== ModelType.BPE) {\n throw new Error(\n `Model type ${tspec?.modelType} not supported, only BPE is supported`,\n );\n }\n\n const nspec = this.model.normalizerSpec;\n if (nspec?.addDummyPrefix || nspec?.removeExtraWhitespaces) {\n throw new Error(\n `Normalizer spec options not supported: ${JSON.stringify(nspec)}`,\n );\n }\n\n const userDefined = new Set<string>();\n this.pieces = new Map();\n this.reserved = new Map();\n this.byte2Token = new Map();\n this.idToByte = new Map();\n this.unknownID = -1;\n this.maxPieceLength = 0;\n\n if (!this.model.pieces) {\n throw new Error('Model has no pieces');\n }\n\n for (let i = 0; i < this.model.pieces.length; i++) {\n const piece = this.model.pieces[i];\n const pieceText = piece.piece ?? '';\n const pieceType = piece.type ?? SentencePieceType.NORMAL;\n\n const isNormalPiece =\n pieceType === SentencePieceType.NORMAL ||\n pieceType === SentencePieceType.USER_DEFINED ||\n pieceType === SentencePieceType.UNUSED;\n\n if (isNormalPiece) {\n this.pieces.set(pieceText, i);\n this.maxPieceLength = Math.max(this.maxPieceLength, pieceText.length);\n } else {\n this.reserved.set(pieceText, i);\n }\n\n if (pieceType === SentencePieceType.USER_DEFINED) {\n userDefined.add(pieceText);\n } else if (pieceType === SentencePieceType.UNKNOWN) {\n if (this.unknownID >= 0) {\n throw new Error('unk redefined');\n }\n this.unknownID = i;\n } else if (pieceType === SentencePieceType.BYTE) {\n if (!tspec.byteFallback) {\n throw new Error(\n `byte piece \"${pieceText}\" found although byte_fallback=false`,\n );\n }\n const bv = convertHexValue(pieceText);\n if (bv >= 0 && bv < 256) {\n this.byte2Token.set(bv, {id: i, text: pieceText});\n this.idToByte.set(i, bv);\n }\n }\n }\n\n if (this.unknownID < 0) {\n throw new Error('unk symbol is not defined');\n }\n\n // If byte_fallback is specified, ensure all 256 byte values are present\n if (tspec.byteFallback) {\n for (let i = 0; i < 256; i++) {\n if (!this.byte2Token.has(i)) {\n throw new Error(\n `byte value 0x${i.toString(16).padStart(2, '0')} not found`,\n );\n }\n }\n }\n\n this.userDefinedMatcher = new PrefixMatcher(userDefined);\n }\n\n /**\n * Encodes text into a list of tokens.\n */\n encode(text: string): Token[] {\n text = this.normalize(text);\n\n // Symbol list element type\n interface SymListElem {\n prev: number;\n next: number;\n noMerge: boolean;\n symbol: string;\n }\n\n const symList: SymListElem[] = [];\n\n while (text.length > 0) {\n const [slen, found] = this.symbolMatch(text);\n\n const sym: SymListElem = {\n noMerge: found,\n symbol: text.substring(0, slen),\n prev: symList.length - 1,\n next: symList.length + 1,\n };\n symList.push(sym);\n\n text = text.substring(slen);\n }\n\n if (symList.length === 0) {\n return [];\n }\n\n symList[symList.length - 1].next = -1;\n let _nTokens = symList.length;\n\n interface MergeCandidate {\n left: number;\n right: number;\n length: number;\n score: number;\n }\n\n const mergeQueue = new PriorityQueue<MergeCandidate>(\n symList.length,\n (a, b) => {\n if (a.score > b.score || (a.score === b.score && a.left < b.left)) {\n return 1;\n }\n return -1;\n },\n );\n\n const findMerged = (\n x: SymListElem,\n y: SymListElem,\n ): [string, number, boolean] => {\n const merged = x.symbol + y.symbol;\n const id = this.pieces.get(merged);\n if (id !== undefined && this.model.pieces) {\n return [this.model.pieces[id].piece ?? '', id, true];\n }\n return ['', 0, false];\n };\n\n const suggestNewMergePair = (left: number, right: number) => {\n if (\n left === -1 ||\n right === -1 ||\n symList[left].noMerge ||\n symList[right].noMerge\n ) {\n return;\n }\n\n const [mergedSymbol, id, ok] = findMerged(symList[left], symList[right]);\n if (ok && this.model.pieces) {\n mergeQueue.insert({\n left,\n right,\n length: mergedSymbol.length,\n score: this.model.pieces[id].score ?? 0,\n });\n }\n };\n\n for (let i = 1; i < symList.length; i++) {\n suggestNewMergePair(i - 1, i);\n }\n\n const candidateIsDead = (candidate: MergeCandidate): boolean => {\n const leftSymbol = symList[candidate.left].symbol;\n const rightSymbol = symList[candidate.right].symbol;\n return (\n leftSymbol === '' ||\n rightSymbol === '' ||\n leftSymbol.length + rightSymbol.length !== candidate.length\n );\n };\n\n let mergeQueueDead = 0;\n while (mergeQueue.len() > 0) {\n const candidate = mergeQueue.popMax();\n const leftSymbol = symList[candidate.left];\n const rightSymbol = symList[candidate.right];\n\n if (candidateIsDead(candidate)) {\n mergeQueueDead--;\n continue;\n }\n\n if (mergeQueueDead * 3 > mergeQueue.len()) {\n mergeQueue.removeFunc(candidateIsDead);\n mergeQueueDead = 0;\n }\n\n const [mergedSymbol, , ok] = findMerged(leftSymbol, rightSymbol);\n if (!ok) {\n throw new Error('failed to merge symbols');\n }\n symList[candidate.left].symbol = mergedSymbol;\n _nTokens--;\n\n symList[candidate.left].next = rightSymbol.next;\n if (rightSymbol.next >= 0) {\n symList[rightSymbol.next].prev = candidate.left;\n }\n\n symList[candidate.right].symbol = '';\n mergeQueueDead++;\n\n suggestNewMergePair(leftSymbol.prev, candidate.left);\n suggestNewMergePair(candidate.left, rightSymbol.next);\n }\n\n const tokens: Token[] = [];\n for (let i = 0; i >= 0; i = symList[i].next) {\n const symbol = symList[i].symbol;\n const id = this.symbolToID(symbol);\n if (id === this.unknownID && this.model.trainerSpec?.byteFallback) {\n // Need to convert byte to token at UTF-8 bytes level\n const bytes = new TextEncoder().encode(symbol);\n for (let j = 0; j < bytes.length; j++) {\n const byteToken = this.byte2Token.get(bytes[j]);\n if (byteToken) {\n tokens.push(byteToken);\n }\n }\n } else {\n tokens.push({id, text: symbol});\n }\n }\n\n return tokens;\n }\n\n /**\n * Decodes a list of token IDs back into text.\n */\n decode(ids: number[]): string {\n const parts: string[] = [];\n\n let i = 0;\n while (i < ids.length) {\n let nextNonByte = i;\n while (nextNonByte < ids.length && this.isByteID(ids[nextNonByte])) {\n nextNonByte++;\n }\n const numBytes = nextNonByte - i;\n\n if (numBytes > 0) {\n const bytes: number[] = [];\n for (let bi = i; bi < nextNonByte; bi++) {\n const byte = this.idToByte.get(ids[bi]);\n if (byte !== undefined) {\n bytes.push(byte);\n }\n }\n\n const textDecoder = new TextDecoder('utf-8', {fatal: false});\n const text = textDecoder.decode(new Uint8Array(bytes));\n parts.push(text);\n }\n\n if (nextNonByte >= ids.length) {\n break;\n }\n\n const id = ids[nextNonByte];\n // eslint-disable-next-line no-empty\n if (this.isControlID(id)) {\n } else if (id === this.unknownID) {\n parts.push(this.model.trainerSpec?.unkSurface ?? '');\n } else if (this.model.pieces && this.model.pieces[id]) {\n const piece = this.model.pieces[id].piece ?? '';\n parts.push(this.replaceSeparatorsBySpace(piece));\n }\n i = nextNonByte + 1;\n }\n\n return parts.join('');\n }\n\n /**\n * Decodes a list of tokens back into text.\n */\n decodeTokens(tokens: Token[]): string {\n return this.decode(tokens.map((t) => t.id));\n }\n\n /**\n * Returns information about the loaded model.\n */\n modelInfo(): ModelInfo {\n const getControlID = (symbol: string): number => {\n const id = this.symbolToID(symbol);\n return this.isControlID(id) ? id : -1;\n };\n\n return {\n vocabularySize: this.model.pieces?.length ?? 0,\n beginningOfSentenceID: getControlID(SYMBOL_BOS),\n endOfSentenceID: getControlID(SYMBOL_EOS),\n padID: getControlID(SYMBOL_PAD),\n unknownID: this.unknownID,\n };\n }\n\n private normalize(text: string): string {\n return text.replace(/ /g, WHITESPACE_SEPARATOR);\n }\n\n private replaceSeparatorsBySpace(text: string): string {\n return text.replace(new RegExp(WHITESPACE_SEPARATOR, 'g'), ' ');\n }\n\n private symbolMatch(text: string): [number, boolean] {\n const prefixLen = this.userDefinedMatcher.findPrefixLen(text);\n if (prefixLen > 0) {\n return [prefixLen, true];\n }\n\n // Return character length (1), not byte length\n // This matches the Java implementation where i++ advances by 1 character\n return [1, false];\n }\n\n private symbolToID(symbol: string): number {\n const reservedID = this.reserved.get(symbol);\n if (reservedID !== undefined) {\n return reservedID;\n }\n const pieceID = this.pieces.get(symbol);\n if (pieceID !== undefined) {\n return pieceID;\n }\n return this.unknownID;\n }\n\n private isByteID(id: number): boolean {\n if (!this.model.pieces || id >= this.model.pieces.length) {\n return false;\n }\n return this.model.pieces[id].type === SentencePieceType.BYTE;\n }\n\n private isControlID(id: number): boolean {\n if (!this.model.pieces || id >= this.model.pieces.length) {\n return false;\n }\n return this.model.pieces[id].type === SentencePieceType.CONTROL;\n }\n\n private parseModelProto(data: Uint8Array): ModelProto {\n const decoded = sentencepiece.ModelProto.decode(data);\n\n const model: ModelProto = {\n pieces: decoded.pieces?.map(\n (p: sentencepiece.ModelProto.ISentencePiece) => ({\n piece: p.piece ?? undefined,\n score: p.score ?? undefined,\n type: (p.type as unknown as SentencePieceType) ?? undefined,\n }),\n ),\n trainerSpec: decoded.trainerSpec\n ? {\n modelType:\n (decoded.trainerSpec.modelType as unknown as ModelType) ??\n undefined,\n vocabSize: decoded.trainerSpec.vocabSize ?? undefined,\n characterCoverage:\n decoded.trainerSpec.characterCoverage ?? undefined,\n byteFallback: decoded.trainerSpec.byteFallback ?? undefined,\n unkSurface: decoded.trainerSpec.unkSurface ?? undefined,\n }\n : undefined,\n normalizerSpec: decoded.normalizerSpec\n ? {\n name: decoded.normalizerSpec.name ?? undefined,\n precompiledCharsmap: decoded.normalizerSpec.precompiledCharsmap\n ? new Uint8Array(decoded.normalizerSpec.precompiledCharsmap)\n : undefined,\n addDummyPrefix: decoded.normalizerSpec.addDummyPrefix ?? undefined,\n removeExtraWhitespaces:\n decoded.normalizerSpec.removeExtraWhitespaces ?? undefined,\n escapeWhitespaces:\n decoded.normalizerSpec.escapeWhitespaces ?? undefined,\n normalizationRuleTsv:\n decoded.normalizerSpec.normalizationRuleTsv ?? undefined,\n }\n : undefined,\n };\n\n return model;\n }\n}\n\nfunction convertHexValue(bv: string): number {\n const match = bv.match(/^<0x([0-9A-Fa-f]{2})>$/);\n if (!match) {\n return -1;\n }\n return parseInt(match[1], 16);\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {TokenizerConfig, TokenizerPlatform} from './_interfaces.js';\n\n/**\n * Source of truth: https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models\n */\nconst GEMINI_MODELS_TO_TOKENIZER_NAMES: Record<string, string> = {\n 'gemini-2.5-pro': 'gemma3',\n 'gemini-2.5-flash': 'gemma3',\n 'gemini-2.5-flash-lite': 'gemma3',\n 'gemini-2.0-flash': 'gemma3',\n 'gemini-2.0-flash-lite': 'gemma3',\n};\n\nconst GEMINI_STABLE_MODELS_TO_TOKENIZER_NAMES: Record<string, string> = {\n 'gemini-3-pro-preview': 'gemma3',\n 'gemini-2.5-pro-preview-06-05': 'gemma3',\n 'gemini-2.5-pro-preview-05-06': 'gemma3',\n 'gemini-2.5-pro-exp-03-25': 'gemma3',\n 'gemini-live-2.5-flash': 'gemma3',\n 'gemini-2.5-flash-preview-05-20': 'gemma3',\n 'gemini-2.5-flash-preview-04-17': 'gemma3',\n 'gemini-2.5-flash-lite-preview-06-17': 'gemma3',\n 'gemini-2.0-flash-001': 'gemma3',\n 'gemini-2.0-flash-lite-001': 'gemma3',\n};\n\nconst TOKENIZERS: Record<string, TokenizerConfig> = {\n gemma2: {\n modelUrl:\n 'https://raw.githubusercontent.com/google/gemma_pytorch/33b652c465537c6158f9a472ea5700e5e770ad3f/tokenizer/tokenizer.model',\n modelHash:\n '61a7b147390c64585d6c3543dd6fc636906c9af3865a5548f27f31aee1d4c8e2',\n },\n gemma3: {\n modelUrl:\n 'https://raw.githubusercontent.com/google/gemma_pytorch/014acb7ac4563a5f77c76d7ff98f31b568c16508/tokenizer/gemma3_cleaned_262144_v2.spiece.model',\n modelHash:\n '1299c11d7cf632ef3b4e11937501358ada021bbdf7c47638d13c0ee982f2e79c',\n },\n};\n\n/**\n * Gets the tokenizer name for the given model name.\n *\n * @param modelName The Gemini model name\n * @return The tokenizer name to use\n * @throws Error if the model is not supported\n */\nexport function getTokenizerName(modelName: string): string {\n if (modelName in GEMINI_MODELS_TO_TOKENIZER_NAMES) {\n return GEMINI_MODELS_TO_TOKENIZER_NAMES[modelName];\n }\n if (modelName in GEMINI_STABLE_MODELS_TO_TOKENIZER_NAMES) {\n return GEMINI_STABLE_MODELS_TO_TOKENIZER_NAMES[modelName];\n }\n\n const supportedModels = [\n ...Object.keys(GEMINI_MODELS_TO_TOKENIZER_NAMES),\n ...Object.keys(GEMINI_STABLE_MODELS_TO_TOKENIZER_NAMES),\n ].join(', ');\n\n throw new Error(\n `Model ${modelName} is not supported for local tokenization. Supported models: ${supportedModels}.`,\n );\n}\n\n/**\n * Gets the tokenizer configuration for the given tokenizer name.\n *\n * @param tokenizerName The tokenizer name\n * @return The tokenizer configuration\n * @throws Error if the tokenizer is not found\n */\nexport function getTokenizerConfig(tokenizerName: string): TokenizerConfig {\n if (!(tokenizerName in TOKENIZERS)) {\n throw new Error(\n `Tokenizer ${tokenizerName} is not supported. Supported tokenizers: ${Object.keys(TOKENIZERS).join(', ')}`,\n );\n }\n return TOKENIZERS[tokenizerName];\n}\n\n/**\n * Loads tokenizer model bytes from cache or URL.\n *\n * @param tokenizerName The tokenizer name\n * @param platform Platform-specific implementations\n * @return The model bytes\n */\nexport async function loadModelProtoBytes(\n tokenizerName: string,\n platform: TokenizerPlatform,\n): Promise<Uint8Array> {\n const config = getTokenizerConfig(tokenizerName);\n\n const encoder = new TextEncoder();\n const cacheKey = await platform.fileSystem.computeSha1(\n encoder.encode(config.modelUrl),\n );\n\n let modelData = await platform.cache.load(cacheKey, config.modelHash);\n\n if (!modelData) {\n modelData = await platform.fileSystem.fetchFromUrl(config.modelUrl);\n\n const isValid = await platform.fileSystem.validateHash(\n modelData,\n config.modelHash,\n );\n\n if (!isValid) {\n const actualHash = await platform.fileSystem.computeSha1(modelData);\n throw new Error(\n `Downloaded model file is corrupted. Expected hash ${config.modelHash}. Got file hash ${actualHash}.`,\n );\n }\n\n await platform.cache.save(cacheKey, modelData);\n }\n\n return modelData;\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * TextsAccumulator extracts countable text from Content and Tool objects.\n *\n * This class traverses complex Content and Tool objects and extracts all text\n * content that should be included when calculating token counts.\n *\n * A key feature is its ability to detect unsupported fields in Content objects.\n * If a user provides a Content object with fields that this local tokenizer\n * doesn't recognize, this class will log a warning.\n *\n * Translated from python-genai/local_tokenizer.py\n */\n\nimport type {\n Content,\n FunctionCall,\n FunctionDeclaration,\n FunctionResponse,\n Part,\n Schema,\n Tool,\n} from '../../types.js';\n\n/**\n * Accumulates countable texts from Content and Tool objects.\n */\nexport class TextsAccumulator {\n private texts: string[];\n\n constructor() {\n this.texts = [];\n }\n\n /**\n * Returns all accumulated texts.\n */\n getTexts(): string[] {\n return this.texts;\n }\n\n /**\n * Adds multiple Content objects.\n */\n addContents(contents: Content[]): void {\n for (const content of contents) {\n this.addContent(content);\n }\n }\n\n addContent(content: Content): void {\n const countedContent: Content = {\n parts: [],\n role: content.role,\n };\n\n if (content.parts) {\n for (const part of content.parts) {\n const countedPart: Part = {};\n\n if (part.fileData || part.inlineData) {\n throw new Error(\n 'LocalTokenizers do not support non-text content types.',\n );\n }\n\n if (part.videoMetadata) {\n countedPart.videoMetadata = part.videoMetadata;\n }\n\n if (part.functionCall) {\n this.addFunctionCall(part.functionCall);\n countedPart.functionCall = part.functionCall;\n }\n\n if (part.functionResponse) {\n this.addFunctionResponse(part.functionResponse);\n countedPart.functionResponse = part.functionResponse;\n }\n\n if (part.text) {\n countedPart.text = part.text;\n this.texts.push(part.text);\n }\n\n if (countedContent.parts) {\n countedContent.parts.push(countedPart);\n }\n }\n }\n\n if (!this.deepEqual(content, countedContent)) {\n console.warn(\n `Content contains unsupported types for token counting. ` +\n `Supported fields: ${JSON.stringify(countedContent)}. ` +\n `Got: ${JSON.stringify(content)}.`,\n );\n }\n }\n\n addFunctionCall(functionCall: FunctionCall): void {\n if (functionCall.name) {\n this.texts.push(functionCall.name);\n }\n\n if (functionCall.args) {\n this.dictTraverse(functionCall.args);\n }\n }\n\n addTools(tools: Tool[]): void {\n for (const tool of tools) {\n this.addTool(tool);\n }\n }\n\n addTool(tool: Tool): void {\n if (tool.functionDeclarations) {\n for (const functionDeclaration of tool.functionDeclarations) {\n this.functionDeclarationTraverse(functionDeclaration);\n }\n }\n }\n\n addFunctionResponses(functionResponses: FunctionResponse[]): void {\n for (const functionResponse of functionResponses) {\n this.addFunctionResponse(functionResponse);\n }\n }\n\n addFunctionResponse(functionResponse: FunctionResponse): void {\n if (functionResponse.name) {\n this.texts.push(functionResponse.name);\n }\n\n if (functionResponse.response) {\n this.dictTraverse(functionResponse.response);\n }\n }\n\n private functionDeclarationTraverse(\n functionDeclaration: FunctionDeclaration,\n ): void {\n if (functionDeclaration.name) {\n this.texts.push(functionDeclaration.name);\n }\n\n if (functionDeclaration.description) {\n this.texts.push(functionDeclaration.description);\n }\n\n if (functionDeclaration.parameters) {\n this.addSchema(functionDeclaration.parameters);\n }\n\n if (functionDeclaration.response) {\n this.addSchema(functionDeclaration.response);\n }\n }\n\n addSchema(schema: Schema): void {\n if (schema.format) {\n this.texts.push(schema.format);\n }\n\n if (schema.description) {\n this.texts.push(schema.description);\n }\n\n if (schema.enum) {\n this.texts.push(...schema.enum);\n }\n\n if (schema.required) {\n this.texts.push(...schema.required);\n }\n\n if (schema.items) {\n this.addSchema(schema.items);\n }\n\n if (schema.properties) {\n for (const [key, value] of Object.entries(schema.properties)) {\n this.texts.push(key);\n this.addSchema(value);\n }\n }\n\n if (schema.example !== undefined && schema.example !== null) {\n this.anyTraverse(schema.example);\n }\n }\n\n private dictTraverse(obj: Record<string, any>): void {\n this.texts.push(...Object.keys(obj));\n for (const value of Object.values(obj)) {\n this.anyTraverse(value);\n }\n }\n\n private anyTraverse(value: any): void {\n if (typeof value === 'string') {\n this.texts.push(value);\n } else if (typeof value === 'object' && value !== null) {\n if (Array.isArray(value)) {\n for (const item of value) {\n this.anyTraverse(item);\n }\n } else {\n this.dictTraverse(value);\n }\n }\n }\n\n private deepEqual(obj1: any, obj2: any): boolean {\n if (obj1 === obj2) return true;\n if (obj1 == null || obj2 == null) return obj1 === obj2;\n if (typeof obj1 !== 'object' || typeof obj2 !== 'object') return false;\n\n if (Array.isArray(obj1) && Array.isArray(obj2)) {\n if (obj1.length !== obj2.length) return false;\n for (let i = 0; i < obj1.length; i++) {\n if (!this.deepEqual(obj1[i], obj2[i])) return false;\n }\n return true;\n }\n\n const keys1 = Object.keys(obj1).filter((k) => obj1[k] !== undefined);\n const keys2 = Object.keys(obj2).filter((k) => obj2[k] !== undefined);\n\n if (keys1.length !== keys2.length) return false;\n\n for (const key of keys1) {\n if (!keys2.includes(key)) return false;\n if (!this.deepEqual(obj1[key], obj2[key])) return false;\n }\n\n return true;\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * LocalTokenizer implementation that integrates SentencePiece with platform-specific\n * caching and file operations.\n *\n * This is the main implementation that brings together:\n * - SentencePiece BPE tokenizer\n * - Platform-specific model loading and caching\n * - Text extraction from Content/Tool/Schema objects\n */\n\nimport {tContent, tContents} from '../../_transformers.js';\nimport type {\n ComputeTokensResult,\n ContentListUnion,\n CountTokensConfig,\n CountTokensResult,\n TokensInfo,\n} from '../../types.js';\nimport {SentencePieceProcessor} from '../sentencepiece/_processor.js';\nimport {ILocalTokenizer, TokenizerPlatform} from './_interfaces.js';\nimport {getTokenizerName, loadModelProtoBytes} from './_loader.js';\nimport {TextsAccumulator} from './_texts_accumulator.js';\n\ntype SentencePieceProcessorConstructor = new (\n modelBytes: Uint8Array,\n) => SentencePieceProcessor;\n\n/**\n * LocalTokenizer provides text-only local tokenization for Gemini models.\n *\n * LIMITATIONS:\n * - Only supports text-based tokenization (no multimodal)\n * - Forward compatibility depends on open-source tokenizer models\n * - For tools/schemas, only supports types.Tool and types.Schema objects\n * (Python functions or Pydantic models cannot be passed directly)\n */\nexport class LocalTokenizer implements ILocalTokenizer {\n private tokenizerName: string;\n private platform: TokenizerPlatform;\n private processor?: SentencePieceProcessor;\n private modelName: string;\n\n /**\n * Creates a new LocalTokenizer.\n *\n * @param modelName Gemini model name (e.g., 'gemini-2.0-flash-001')\n * @param platform Platform-specific implementations for caching and file operations\n */\n constructor(\n modelName: string,\n platform: TokenizerPlatform,\n private readonly ProcessorClass: SentencePieceProcessorConstructor = SentencePieceProcessor,\n ) {\n this.modelName = modelName;\n this.tokenizerName = getTokenizerName(modelName);\n this.platform = platform;\n }\n\n private async ensureProcessor(): Promise<void> {\n if (this.processor) {\n return;\n }\n\n const modelBytes = await loadModelProtoBytes(\n this.tokenizerName,\n this.platform,\n );\n\n this.processor = new this.ProcessorClass(modelBytes);\n }\n\n /**\n * Counts the number of tokens in the given content.\n *\n * @param contents The contents to tokenize\n * @param config Optional configuration for counting tokens\n * @return A CountTokensResult containing the total number of tokens\n *\n * @example\n * ```typescript\n * const tokenizer = new LocalTokenizer('gemini-2.0-flash-001', platform);\n * const result = await tokenizer.countTokens(\"What is your name?\");\n * console.log(result.totalTokens); // 5\n * ```\n */\n async countTokens(\n contents: ContentListUnion,\n config?: CountTokensConfig,\n ): Promise<CountTokensResult> {\n await this.ensureProcessor();\n\n const processedContents = tContents(contents);\n\n const textAccumulator = new TextsAccumulator();\n textAccumulator.addContents(processedContents);\n\n if (config?.systemInstruction) {\n const systemContent = tContent(config.systemInstruction);\n textAccumulator.addContents([systemContent]);\n }\n\n if (config?.tools) {\n textAccumulator.addTools(config.tools);\n }\n\n if (config?.generationConfig?.responseSchema) {\n textAccumulator.addSchema(config.generationConfig.responseSchema);\n }\n\n const texts = textAccumulator.getTexts();\n let totalTokens = 0;\n\n for (const text of texts) {\n const tokens = this.processor!.encode(text);\n totalTokens += tokens.length;\n }\n\n return {\n totalTokens,\n };\n }\n\n /**\n * Computes detailed token information for the given content.\n *\n * @param contents The contents to tokenize\n * @return A ComputeTokensResult containing token IDs, bytes, and roles\n *\n * @example\n * ```typescript\n * const tokenizer = new LocalTokenizer('gemini-2.0-flash-001', platform);\n * const result = await tokenizer.computeTokens(\"What is your name?\");\n * console.log(result.tokensInfo);\n * // [{tokenIds: [279, 329, 1313, 2508, 13], tokens: [' What', ' is', ...], role: 'user'}]\n * ```\n */\n async computeTokens(\n contents: ContentListUnion,\n ): Promise<ComputeTokensResult> {\n await this.ensureProcessor();\n\n const processedContents = tContents(contents);\n\n const tokensInfo: TokensInfo[] = [];\n\n for (const content of processedContents) {\n const textAccumulator = new TextsAccumulator();\n textAccumulator.addContent(content);\n\n const texts = textAccumulator.getTexts();\n\n const allTokenIds: number[] = [];\n const allTokens: string[] = [];\n\n for (const text of texts) {\n const tokens = this.processor!.encode(text);\n allTokenIds.push(...tokens.map((t) => t.id));\n allTokens.push(...tokens.map((t) => this.tokenTextToBase64(t.text)));\n }\n\n if (allTokenIds.length > 0) {\n tokensInfo.push({\n tokenIds: allTokenIds.map((id) => id.toString()),\n tokens: allTokens,\n role: content.role,\n });\n }\n }\n\n return {\n tokensInfo,\n };\n }\n\n private tokenTextToBase64(text: string): string {\n const encoder = new TextEncoder();\n const bytes = encoder.encode(text.replace(/▁/g, ' '));\n\n let binary = '';\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport * as crypto from 'crypto';\nimport * as fs from 'fs/promises';\nimport * as os from 'os';\nimport * as path from 'path';\n\nimport {\n TokenizerCache,\n TokenizerFileSystem,\n TokenizerPlatform,\n} from '../cross/tokenizer/_interfaces.js';\n\n/**\n * Node.js implementation of tokenizer cache using the file system.\n */\nexport class NodeTokenizerCache implements TokenizerCache {\n private cacheDir: string;\n\n constructor() {\n this.cacheDir = path.join(os.tmpdir(), 'vertexai_tokenizer_model');\n }\n\n async load(\n cacheKey: string,\n expectedHash: string,\n ): Promise<Uint8Array | null> {\n const filePath = path.join(this.cacheDir, cacheKey);\n try {\n const data = await fs.readFile(filePath);\n const hash = crypto.createHash('sha256').update(data).digest('hex');\n\n if (hash === expectedHash) {\n return new Uint8Array(data);\n }\n\n await this.removeFile(filePath);\n return null;\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (error) {\n return null;\n }\n }\n\n async save(cacheKey: string, data: Uint8Array): Promise<void> {\n const filePath = path.join(this.cacheDir, cacheKey);\n try {\n await fs.mkdir(this.cacheDir, {recursive: true});\n\n const tmpPath = `${this.cacheDir}.${crypto.randomUUID()}.tmp`;\n await fs.writeFile(tmpPath, data);\n await fs.rename(tmpPath, filePath);\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (error) {\n // Cache is optional, so errors are silently ignored\n }\n }\n\n private async removeFile(filePath: string): Promise<void> {\n try {\n await fs.unlink(filePath);\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (error) {\n // Cache is optional, so errors are silently ignored\n }\n }\n}\n\n/**\n * Node.js implementation of tokenizer file system operations.\n */\nexport class NodeTokenizerFileSystem implements TokenizerFileSystem {\n async fetchFromUrl(url: string): Promise<Uint8Array> {\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(\n `Failed to fetch tokenizer model from ${url}: ${response.statusText}`,\n );\n }\n const arrayBuffer = await response.arrayBuffer();\n return new Uint8Array(arrayBuffer);\n }\n\n async validateHash(data: Uint8Array, expectedHash: string): Promise<boolean> {\n const hash = crypto.createHash('sha256').update(data).digest('hex');\n return hash === expectedHash;\n }\n\n async computeSha1(text: Uint8Array): Promise<string> {\n const hash = crypto.createHash('sha1').update(text).digest('hex');\n return hash;\n }\n}\n\n/**\n * Node.js platform implementation for tokenizer.\n */\nexport class NodeTokenizerPlatform implements TokenizerPlatform {\n cache: TokenizerCache;\n fileSystem: TokenizerFileSystem;\n\n constructor() {\n this.cache = new NodeTokenizerCache();\n this.fileSystem = new NodeTokenizerFileSystem();\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Node.js-specific LocalTokenizer implementation.\n *\n * This wrapper automatically uses the Node.js platform (filesystem caching, crypto hashing)\n * without requiring users to manually create a platform instance.\n */\n\nimport {LocalTokenizer as BaseLocalTokenizer} from '../cross/tokenizer/_local_tokenizer_impl.js';\nimport type {\n ComputeTokensResult,\n ContentListUnion,\n CountTokensConfig,\n CountTokensResult,\n} from '../types.js';\nimport {NodeTokenizerPlatform} from './_node_tokenizer_platform.js';\n\n/**\n * LocalTokenizer for Node.js environment.\n *\n * Provides local tokenization for Gemini models without requiring API calls.\n * Automatically uses Node.js platform (filesystem caching in temp directory).\n *\n * @example\n * ```typescript\n * import {LocalTokenizer} from '@google/genai/node';\n *\n * const tokenizer = new LocalTokenizer('gemini-2.0-flash-001');\n * const result = await tokenizer.countTokens(\"What is your name?\");\n * console.log(result.totalTokens); // 5\n * ```\n *\n * @experimental This API is experimental and may change in future versions.\n */\nexport class LocalTokenizer {\n private baseTokenizer: BaseLocalTokenizer;\n\n /**\n * Creates a new LocalTokenizer for Node.js.\n *\n * @param modelName Gemini model name (e.g., 'gemini-2.0-flash-001')\n */\n constructor(modelName: string) {\n const platform = new NodeTokenizerPlatform();\n this.baseTokenizer = new BaseLocalTokenizer(modelName, platform);\n }\n\n /**\n * Counts the number of tokens in the given content.\n *\n * @param contents The contents to tokenize\n * @param config Optional configuration for counting tokens\n * @return A CountTokensResult containing the total number of tokens\n */\n async countTokens(\n contents: ContentListUnion,\n config?: CountTokensConfig,\n ): Promise<CountTokensResult> {\n return this.baseTokenizer.countTokens(contents, config);\n }\n\n /**\n * Computes detailed token information for the given content.\n *\n * @param contents The contents to tokenize\n * @return A ComputeTokensResult containing token IDs, bytes, and roles\n */\n async computeTokens(\n contents: ContentListUnion,\n ): Promise<ComputeTokensResult> {\n return this.baseTokenizer.computeTokens(contents);\n }\n}\n"],"names":["BaseLocalTokenizer"],"mappings":";;;;;;AAAA;;;;AAIG;AAYH;AACA,IAAY,OAiBX;AAjBD,CAAA,UAAY,OAAO,EAAA;AACjB;;AAEG;AACH,IAAA,OAAA,CAAA,qBAAA,CAAA,GAAA,qBAA2C;AAC3C;;AAEG;AACH,IAAA,OAAA,CAAA,YAAA,CAAA,GAAA,YAAyB;AACzB;;AAEG;AACH,IAAA,OAAA,CAAA,gBAAA,CAAA,GAAA,gBAAiC;AACjC;;AAEG;AACH,IAAA,OAAA,CAAA,2BAAA,CAAA,GAAA,2BAAuD;AACzD,CAAC,EAjBW,OAAO,KAAP,OAAO,GAAA,EAAA,CAAA,CAAA;AAmBnB;AACA,IAAY,QASX;AATD,CAAA,UAAY,QAAQ,EAAA;AAClB;;AAEG;AACH,IAAA,QAAA,CAAA,sBAAA,CAAA,GAAA,sBAA6C;AAC7C;;AAEG;AACH,IAAA,QAAA,CAAA,QAAA,CAAA,GAAA,QAAiB;AACnB,CAAC,EATW,QAAQ,KAAR,QAAQ,GAAA,EAAA,CAAA,CAAA;AAWpB;AACA,IAAY,0BAiBX;AAjBD,CAAA,UAAY,0BAA0B,EAAA;AACpC;;AAEG;AACH,IAAA,0BAAA,CAAA,wBAAA,CAAA,GAAA,wBAAiD;AACjD;;AAEG;AACH,IAAA,0BAAA,CAAA,QAAA,CAAA,GAAA,QAAiB;AACjB;;AAEG;AACH,IAAA,0BAAA,CAAA,WAAA,CAAA,GAAA,WAAuB;AACvB;;AAEG;AACH,IAAA,0BAAA,CAAA,WAAA,CAAA,GAAA,WAAuB;AACzB,CAAC,EAjBW,0BAA0B,KAA1B,0BAA0B,GAAA,EAAA,CAAA,CAAA;AAmBtC;AACA,IAAY,IAiCX;AAjCD,CAAA,UAAY,IAAI,EAAA;AACd;;AAEG;AACH,IAAA,IAAA,CAAA,kBAAA,CAAA,GAAA,kBAAqC;AACrC;;AAEG;AACH,IAAA,IAAA,CAAA,QAAA,CAAA,GAAA,QAAiB;AACjB;;AAEG;AACH,IAAA,IAAA,CAAA,QAAA,CAAA,GAAA,QAAiB;AACjB;;AAEG;AACH,IAAA,IAAA,CAAA,SAAA,CAAA,GAAA,SAAmB;AACnB;;AAEG;AACH,IAAA,IAAA,CAAA,SAAA,CAAA,GAAA,SAAmB;AACnB;;AAEG;AACH,IAAA,IAAA,CAAA,OAAA,CAAA,GAAA,OAAe;AACf;;AAEG;AACH,IAAA,IAAA,CAAA,QAAA,CAAA,GAAA,QAAiB;AACjB;;AAEG;AACH,IAAA,IAAA,CAAA,MAAA,CAAA,GAAA,MAAa;AACf,CAAC,EAjCW,IAAI,KAAJ,IAAI,GAAA,EAAA,CAAA,CAAA;AAmChB;AACA,IAAY,OAaX;AAbD,CAAA,UAAY,OAAO,EAAA;AACjB;;AAEG;AACH,IAAA,OAAA,CAAA,sBAAA,CAAA,GAAA,sBAA6C;AAC7C;;AAEG;AACH,IAAA,OAAA,CAAA,eAAA,CAAA,GAAA,eAA+B;AAC/B;;AAEG;AACH,IAAA,OAAA,CAAA,gBAAA,CAAA,GAAA,gBAAiC;AACnC,CAAC,EAbW,OAAO,KAAP,OAAO,GAAA,EAAA,CAAA,CAAA;AAenB;AACA,IAAY,QA0BX;AA1BD,CAAA,UAAY,QAAQ,EAAA;AAClB,IAAA,QAAA,CAAA,uBAAA,CAAA,GAAA,uBAA+C;AAC/C;;AAEG;AACH,IAAA,QAAA,CAAA,SAAA,CAAA,GAAA,SAAmB;AACnB;;AAEG;AACH,IAAA,QAAA,CAAA,cAAA,CAAA,GAAA,cAA6B;AAC7B;;AAEG;AACH,IAAA,QAAA,CAAA,iBAAA,CAAA,GAAA,iBAAmC;AACnC;;AAEG;AACH,IAAA,QAAA,CAAA,6BAAA,CAAA,GAAA,6BAA2D;AAC3D;;AAEG;AACH,IAAA,QAAA,CAAA,OAAA,CAAA,GAAA,OAAe;AACf;;AAEG;AACH,IAAA,QAAA,CAAA,WAAA,CAAA,GAAA,WAAuB;AACzB,CAAC,EA1BW,QAAQ,KAAR,QAAQ,GAAA,EAAA,CAAA,CAAA;AA4BpB;AACA,IAAY,mBAsBX;AAtBD,CAAA,UAAY,mBAAmB,EAAA;AAC7B,IAAA,mBAAA,CAAA,qBAAA,CAAA,GAAA,qBAA2C;AAC3C;;AAEG;AACH,IAAA,mBAAA,CAAA,eAAA,CAAA,GAAA,eAA+B;AAC/B;;AAEG;AACH,IAAA,mBAAA,CAAA,gBAAA,CAAA,GAAA,gBAAiC;AACjC;;AAEG;AACH,IAAA,mBAAA,CAAA,cAAA,CAAA,GAAA,cAA6B;AAC7B;;AAEG;AACH,IAAA,mBAAA,CAAA,cAAA,CAAA,GAAA,cAA6B;AAC7B;;AAEG;AACH,IAAA,mBAAA,CAAA,gBAAA,CAAA,GAAA,gBAAiC;AACnC,CAAC,EAtBW,mBAAmB,KAAnB,mBAAmB,GAAA,EAAA,CAAA,CAAA;AAwB/B;AACA,IAAY,mBA6BX;AA7BD,CAAA,UAAY,mBAAmB,EAAA;AAC7B;;AAEG;AACH,IAAA,mBAAA,CAAA,mCAAA,CAAA,GAAA,mCAAuE;AACvE;;AAEG;AACH,IAAA,mBAAA,CAAA,qBAAA,CAAA,GAAA,qBAA2C;AAC3C;;AAEG;AACH,IAAA,mBAAA,CAAA,wBAAA,CAAA,GAAA,wBAAiD;AACjD;;AAEG;AACH,IAAA,mBAAA,CAAA,sBAAA,CAAA,GAAA,sBAA6C;AAC7C;;AAEG;AACH,IAAA,mBAAA,CAAA,wBAAA,CAAA,GAAA,wBAAiD;AACjD;;AAEG;AACH,IAAA,mBAAA,CAAA,2BAAA,CAAA,GAAA,2BAAuD;AACvD;;AAEG;AACH,IAAA,mBAAA,CAAA,2BAAA,CAAA,GAAA,2BAAuD;AACzD,CAAC,EA7BW,mBAAmB,KAAnB,mBAAmB,GAAA,EAAA,CAAA,CAAA;AA+B/B;AACA,IAAY,QAaX;AAbD,CAAA,UAAY,QAAQ,EAAA;AAClB;;AAEG;AACH,IAAA,QAAA,CAAA,aAAA,CAAA,GAAA,aAA2B;AAC3B;;AAEG;AACH,IAAA,QAAA,CAAA,UAAA,CAAA,GAAA,UAAqB;AACrB;;AAEG;AACH,IAAA,QAAA,CAAA,cAAA,CAAA,GAAA,cAA6B;AAC/B,CAAC,EAbW,QAAQ,KAAR,QAAQ,GAAA,EAAA,CAAA,CAAA;AAepB;AACA,IAAY,0BASX;AATD,CAAA,UAAY,0BAA0B,EAAA;AACpC;;AAEG;AACH,IAAA,0BAAA,CAAA,kBAAA,CAAA,GAAA,kBAAqC;AACrC;;AAEG;AACH,IAAA,0BAAA,CAAA,cAAA,CAAA,GAAA,cAA6B;AAC/B,CAAC,EATW,0BAA0B,KAA1B,0BAA0B,GAAA,EAAA,CAAA,CAAA;AAWtC;AACA,IAAY,yBAqBX;AArBD,CAAA,UAAY,yBAAyB,EAAA;AACnC;;AAEG;AACH,IAAA,yBAAA,CAAA,kBAAA,CAAA,GAAA,kBAAqC;AACrC;;AAEG;AACH,IAAA,yBAAA,CAAA,MAAA,CAAA,GAAA,MAAa;AACb;;AAEG;AACH,IAAA,yBAAA,CAAA,KAAA,CAAA,GAAA,KAAW;AACX;;AAEG;AACH,IAAA,yBAAA,CAAA,MAAA,CAAA,GAAA,MAAa;AACb;;AAEG;AACH,IAAA,yBAAA,CAAA,WAAA,CAAA,GAAA,WAAuB;AACzB,CAAC,EArBW,yBAAyB,KAAzB,yBAAyB,GAAA,EAAA,CAAA,CAAA;AAuBrC;AACA,IAAY,aAqBX;AArBD,CAAA,UAAY,aAAa,EAAA;AACvB;;AAEG;AACH,IAAA,aAAA,CAAA,4BAAA,CAAA,GAAA,4BAAyD;AACzD;;AAEG;AACH,IAAA,aAAA,CAAA,KAAA,CAAA,GAAA,KAAW;AACX;;AAEG;AACH,IAAA,aAAA,CAAA,QAAA,CAAA,GAAA,QAAiB;AACjB;;AAEG;AACH,IAAA,aAAA,CAAA,MAAA,CAAA,GAAA,MAAa;AACb;;AAEG;AACH,IAAA,aAAA,CAAA,SAAA,CAAA,GAAA,SAAmB;AACrB,CAAC,EArBW,aAAa,KAAb,aAAa,GAAA,EAAA,CAAA,CAAA;AAuBzB;AACA,IAAY,YA6CX;AA7CD,CAAA,UAAY,YAAY,EAAA;AACtB;;AAEG;AACH,IAAA,YAAA,CAAA,2BAAA,CAAA,GAAA,2BAAuD;AACvD;;AAEG;AACH,IAAA,YAAA,CAAA,0BAAA,CAAA,GAAA,0BAAqD;AACrD;;AAEG;AACH,IAAA,YAAA,CAAA,2BAAA,CAAA,GAAA,2BAAuD;AACvD;;AAEG;AACH,IAAA,YAAA,CAAA,iCAAA,CAAA,GAAA,iCAAmE;AACnE;;AAEG;AACH,IAAA,YAAA,CAAA,iCAAA,CAAA,GAAA,iCAAmE;AACnE;;AAEG;AACH,IAAA,YAAA,CAAA,+BAAA,CAAA,GAAA,+BAA+D;AAC/D;;AAEG;AACH,IAAA,YAAA,CAAA,0BAAA,CAAA,GAAA,0BAAqD;AACrD;;AAEG;AACH,IAAA,YAAA,CAAA,uCAAA,CAAA,GAAA,uCAA+E;AAC/E;;AAEG;AACH,IAAA,YAAA,CAAA,gCAAA,CAAA,GAAA,gCAAiE;AACjE;;AAEG;AACH,IAAA,YAAA,CAAA,uCAAA,CAAA,GAAA,uCAA+E;AAC/E;;AAEG;AACH,IAAA,YAAA,CAAA,yBAAA,CAAA,GAAA,yBAAmD;AACrD,CAAC,EA7CW,YAAY,KAAZ,YAAY,GAAA,EAAA,CAAA,CAAA;AA+CxB;AACA,IAAY,eAaX;AAbD,CAAA,UAAY,eAAe,EAAA;AACzB;;AAEG;AACH,IAAA,eAAA,CAAA,+BAAA,CAAA,GAAA,+BAA+D;AAC/D;;AAEG;AACH,IAAA,eAAA,CAAA,UAAA,CAAA,GAAA,UAAqB;AACrB;;AAEG;AACH,IAAA,eAAA,CAAA,aAAA,CAAA,GAAA,aAA2B;AAC7B,CAAC,EAbW,eAAe,KAAf,eAAe,GAAA,EAAA,CAAA,CAAA;AAe3B;AACA,IAAY,kBAyBX;AAzBD,CAAA,UAAY,kBAAkB,EAAA;AAC5B;;AAEG;AACH,IAAA,kBAAA,CAAA,kCAAA,CAAA,GAAA,kCAAqE;AACrE;;AAEG;AACH,IAAA,kBAAA,CAAA,qBAAA,CAAA,GAAA,qBAA2C;AAC3C;;AAEG;AACH,IAAA,kBAAA,CAAA,wBAAA,CAAA,GAAA,wBAAiD;AACjD;;AAEG;AACH,IAAA,kBAAA,CAAA,iBAAA,CAAA,GAAA,iBAAmC;AACnC;;AAEG;AACH,IAAA,kBAAA,CAAA,YAAA,CAAA,GAAA,YAAyB;AACzB;;AAEG;AACH,IAAA,kBAAA,CAAA,KAAA,CAAA,GAAA,KAAW;AACb,CAAC,EAzBW,kBAAkB,KAAlB,kBAAkB,GAAA,EAAA,CAAA,CAAA;AA2B9B;;AAE6D;AAC7D,IAAY,YAqEX;AArED,CAAA,UAAY,YAAY,EAAA;AACtB;;AAEG;AACH,IAAA,YAAA,CAAA,2BAAA,CAAA,GAAA,2BAAuD;AACvD;;AAEG;AACH,IAAA,YAAA,CAAA,MAAA,CAAA,GAAA,MAAa;AACb;;AAEG;AACH,IAAA,YAAA,CAAA,YAAA,CAAA,GAAA,YAAyB;AACzB;;AAEG;AACH,IAAA,YAAA,CAAA,QAAA,CAAA,GAAA,QAAiB;AACjB;;AAEG;AACH,IAAA,YAAA,CAAA,YAAA,CAAA,GAAA,YAAyB;AACzB;;AAEG;AACH,IAAA,YAAA,CAAA,UAAA,CAAA,GAAA,UAAqB;AACrB;;AAEG;AACH,IAAA,YAAA,CAAA,OAAA,CAAA,GAAA,OAAe;AACf;;AAEG;AACH,IAAA,YAAA,CAAA,WAAA,CAAA,GAAA,WAAuB;AACvB;;AAEG;AACH,IAAA,YAAA,CAAA,oBAAA,CAAA,GAAA,oBAAyC;AACzC;;AAEG;AACH,IAAA,YAAA,CAAA,MAAA,CAAA,GAAA,MAAa;AACb;;AAEG;AACH,IAAA,YAAA,CAAA,yBAAA,CAAA,GAAA,yBAAmD;AACnD;;AAEG;AACH,IAAA,YAAA,CAAA,cAAA,CAAA,GAAA,cAA6B;AAC7B;;AAEG;AACH,IAAA,YAAA,CAAA,sBAAA,CAAA,GAAA,sBAA6C;AAC7C;;AAEG;AACH,IAAA,YAAA,CAAA,0BAAA,CAAA,GAAA,0BAAqD;AACrD;;AAEG;AACH,IAAA,YAAA,CAAA,UAAA,CAAA,GAAA,UAAqB;AACrB;;AAEG;AACH,IAAA,YAAA,CAAA,kBAAA,CAAA,GAAA,kBAAqC;AACrC;;AAEG;AACH,IAAA,YAAA,CAAA,aAAA,CAAA,GAAA,aAA2B;AAC7B,CAAC,EArEW,YAAY,KAAZ,YAAY,GAAA,EAAA,CAAA,CAAA;AAuExB;AACA,IAAY,eAqBX;AArBD,CAAA,UAAY,eAAe,EAAA;AACzB;;AAEG;AACH,IAAA,eAAA,CAAA,8BAAA,CAAA,GAAA,8BAA6D;AAC7D;;AAEG;AACH,IAAA,eAAA,CAAA,YAAA,CAAA,GAAA,YAAyB;AACzB;;AAEG;AACH,IAAA,eAAA,CAAA,KAAA,CAAA,GAAA,KAAW;AACX;;AAEG;AACH,IAAA,eAAA,CAAA,QAAA,CAAA,GAAA,QAAiB;AACjB;;AAEG;AACH,IAAA,eAAA,CAAA,MAAA,CAAA,GAAA,MAAa;AACf,CAAC,EArBW,eAAe,KAAf,eAAe,GAAA,EAAA,CAAA,CAAA;AAuB3B;AACA,IAAY,YAqBX;AArBD,CAAA,UAAY,YAAY,EAAA;AACtB;;AAEG;AACH,IAAA,YAAA,CAAA,2BAAA,CAAA,GAAA,2BAAuD;AACvD;;AAEG;AACH,IAAA,YAAA,CAAA,0BAAA,CAAA,GAAA,0BAAqD;AACrD;;AAEG;AACH,IAAA,YAAA,CAAA,mBAAA,CAAA,GAAA,mBAAuC;AACvC;;AAEG;AACH,IAAA,YAAA,CAAA,sBAAA,CAAA,GAAA,sBAA6C;AAC7C;;AAEG;AACH,IAAA,YAAA,CAAA,oBAAA,CAAA,GAAA,oBAAyC;AAC3C,CAAC,EArBW,YAAY,KAAZ,YAAY,GAAA,EAAA,CAAA,CAAA;AAuBxB;AACA,IAAY,kBAqBX;AArBD,CAAA,UAAY,kBAAkB,EAAA;AAC5B;;AAEG;AACH,IAAA,kBAAA,CAAA,kCAAA,CAAA,GAAA,kCAAqE;AACrE;;AAEG;AACH,IAAA,kBAAA,CAAA,8BAAA,CAAA,GAAA,8BAA6D;AAC7D;;AAEG;AACH,IAAA,kBAAA,CAAA,4BAAA,CAAA,GAAA,4BAAyD;AACzD;;AAEG;AACH,IAAA,kBAAA,CAAA,8BAAA,CAAA,GAAA,8BAA6D;AAC7D;;AAEG;AACH,IAAA,kBAAA,CAAA,6BAAA,CAAA,GAAA,6BAA2D;AAC7D,CAAC,EArBW,kBAAkB,KAAlB,kBAAkB,GAAA,EAAA,CAAA,CAAA;AAuB9B;AACA,IAAY,aAiCX;AAjCD,CAAA,UAAY,aAAa,EAAA;AACvB;;AAEG;AACH,IAAA,aAAA,CAAA,4BAAA,CAAA,GAAA,4BAAyD;AACzD;;AAEG;AACH,IAAA,aAAA,CAAA,QAAA,CAAA,GAAA,QAAiB;AACjB;;AAEG;AACH,IAAA,aAAA,CAAA,OAAA,CAAA,GAAA,OAAe;AACf;;AAEG;AACH,IAAA,aAAA,CAAA,WAAA,CAAA,GAAA,WAAuB;AACvB;;AAEG;AACH,IAAA,aAAA,CAAA,oBAAA,CAAA,GAAA,oBAAyC;AACzC;;AAEG;AACH,IAAA,aAAA,CAAA,cAAA,CAAA,GAAA,cAA6B;AAC7B;;AAEG;AACH,IAAA,aAAA,CAAA,aAAA,CAAA,GAAA,aAA2B;AAC3B;;AAEG;AACH,IAAA,aAAA,CAAA,WAAA,CAAA,GAAA,WAAuB;AACzB,CAAC,EAjCW,aAAa,KAAb,aAAa,GAAA,EAAA,CAAA,CAAA;AAmCzB;AACA,IAAY,WAaX;AAbD,CAAA,UAAY,WAAW,EAAA;AACrB;;AAEG;AACH,IAAA,WAAA,CAAA,0BAAA,CAAA,GAAA,0BAAqD;AACrD;;AAEG;AACH,IAAA,WAAA,CAAA,WAAA,CAAA,GAAA,WAAuB;AACvB;;AAEG;AACH,IAAA,WAAA,CAAA,wBAAA,CAAA,GAAA,wBAAiD;AACnD,CAAC,EAbW,WAAW,KAAX,WAAW,GAAA,EAAA,CAAA,CAAA;AAevB;AACA,IAAY,QAiBX;AAjBD,CAAA,UAAY,QAAQ,EAAA;AAClB;;AAEG;AACH,IAAA,QAAA,CAAA,sBAAA,CAAA,GAAA,sBAA6C;AAC7C;;AAEG;AACH,IAAA,QAAA,CAAA,MAAA,CAAA,GAAA,MAAa;AACb;;AAEG;AACH,IAAA,QAAA,CAAA,OAAA,CAAA,GAAA,OAAe;AACf;;AAEG;AACH,IAAA,QAAA,CAAA,OAAA,CAAA,GAAA,OAAe;AACjB,CAAC,EAjBW,QAAQ,KAAR,QAAQ,GAAA,EAAA,CAAA,CAAA;AAmBpB;AACA,IAAY,eAiBX;AAjBD,CAAA,UAAY,eAAe,EAAA;AACzB;;AAEG;AACH,IAAA,eAAA,CAAA,8BAAA,CAAA,GAAA,8BAA6D;AAC7D;;AAEG;AACH,IAAA,eAAA,CAAA,sBAAA,CAAA,GAAA,sBAA6C;AAC7C;;AAEG;AACH,IAAA,eAAA,CAAA,yBAAA,CAAA,GAAA,yBAAmD;AACnD;;AAEG;AACH,IAAA,eAAA,CAAA,uBAAA,CAAA,GAAA,uBAA+C;AACjD,CAAC,EAjBW,eAAe,KAAf,eAAe,GAAA,EAAA,CAAA,CAAA;AAmB3B;AACA,IAAY,UAaX;AAbD,CAAA,UAAY,UAAU,EAAA;AACpB;;AAEG;AACH,IAAA,UAAA,CAAA,yBAAA,CAAA,GAAA,yBAAmD;AACnD;;AAEG;AACH,IAAA,UAAA,CAAA,kBAAA,CAAA,GAAA,kBAAqC;AACrC;;AAEG;AACH,IAAA,UAAA,CAAA,0BAAA,CAAA,GAAA,0BAAqD;AACvD,CAAC,EAbW,UAAU,KAAV,UAAU,GAAA,EAAA,CAAA,CAAA;AAetB;AACA,IAAY,WA6BX;AA7BD,CAAA,UAAY,WAAW,EAAA;AACrB;;AAEG;AACH,IAAA,WAAA,CAAA,0BAAA,CAAA,GAAA,0BAAqD;AACrD;;AAEG;AACH,IAAA,WAAA,CAAA,kBAAA,CAAA,GAAA,kBAAqC;AACrC;;AAEG;AACH,IAAA,WAAA,CAAA,kBAAA,CAAA,GAAA,kBAAqC;AACrC;;AAEG;AACH,IAAA,WAAA,CAAA,mBAAA,CAAA,GAAA,mBAAuC;AACvC;;AAEG;AACH,IAAA,WAAA,CAAA,oBAAA,CAAA,GAAA,oBAAyC;AACzC;;AAEG;AACH,IAAA,WAAA,CAAA,sBAAA,CAAA,GAAA,sBAA6C;AAC7C;;AAEG;AACH,IAAA,WAAA,CAAA,yBAAA,CAAA,GAAA,yBAAmD;AACrD,CAAC,EA7BW,WAAW,KAAX,WAAW,GAAA,EAAA,CAAA,CAAA;AA+BvB;AACA,IAAY,QAiDX;AAjDD,CAAA,UAAY,QAAQ,EAAA;AAClB;;AAEG;AACH,IAAA,QAAA,CAAA,uBAAA,CAAA,GAAA,uBAA+C;AAC/C;;AAEG;AACH,IAAA,QAAA,CAAA,kBAAA,CAAA,GAAA,kBAAqC;AACrC;;AAEG;AACH,IAAA,QAAA,CAAA,mBAAA,CAAA,GAAA,mBAAuC;AACvC;;AAEG;AACH,IAAA,QAAA,CAAA,mBAAA,CAAA,GAAA,mBAAuC;AACvC;;AAEG;AACH,IAAA,QAAA,CAAA,qBAAA,CAAA,GAAA,qBAA2C;AAC3C;;AAEG;AACH,IAAA,QAAA,CAAA,kBAAA,CAAA,GAAA,kBAAqC;AACrC;;AAEG;AACH,IAAA,QAAA,CAAA,sBAAA,CAAA,GAAA,sBAA6C;AAC7C;;AAEG;AACH,IAAA,QAAA,CAAA,qBAAA,CAAA,GAAA,qBAA2C;AAC3C;;AAEG;AACH,IAAA,QAAA,CAAA,kBAAA,CAAA,GAAA,kBAAqC;AACrC;;AAEG;AACH,IAAA,QAAA,CAAA,mBAAA,CAAA,GAAA,mBAAuC;AACvC;;AAEG;AACH,IAAA,QAAA,CAAA,oBAAA,CAAA,GAAA,oBAAyC;AACzC;;AAEG;AACH,IAAA,QAAA,CAAA,+BAAA,CAAA,GAAA,+BAA+D;AACjE,CAAC,EAjDW,QAAQ,KAAR,QAAQ,GAAA,EAAA,CAAA,CAAA;AAmDpB;AACA,IAAY,UAiBX;AAjBD,CAAA,UAAY,UAAU,EAAA;AACpB;;AAEG;AACH,IAAA,UAAA,CAAA,yBAAA,CAAA,GAAA,yBAAmD;AACnD;;AAEG;AACH,IAAA,UAAA,CAAA,iBAAA,CAAA,GAAA,iBAAmC;AACnC;;AAEG;AACH,IAAA,UAAA,CAAA,iBAAA,CAAA,GAAA,iBAAmC;AACnC;;AAEG;AACH,IAAA,UAAA,CAAA,iBAAA,CAAA,GAAA,iBAAmC;AACrC,CAAC,EAjBW,UAAU,KAAV,UAAU,GAAA,EAAA,CAAA,CAAA;AAmBtB;AACA,IAAY,wBAqBX;AArBD,CAAA,UAAY,wBAAwB,EAAA;AAClC;;AAEG;AACH,IAAA,wBAAA,CAAA,8BAAA,CAAA,GAAA,8BAA6D;AAC7D;;AAEG;AACH,IAAA,wBAAA,CAAA,sBAAA,CAAA,GAAA,sBAA6C;AAC7C;;AAEG;AACH,IAAA,wBAAA,CAAA,yBAAA,CAAA,GAAA,yBAAmD;AACnD;;AAEG;AACH,IAAA,wBAAA,CAAA,uBAAA,CAAA,GAAA,uBAA+C;AAC/C;;AAEG;AACH,IAAA,wBAAA,CAAA,6BAAA,CAAA,GAAA,6BAA2D;AAC7D,CAAC,EArBW,wBAAwB,KAAxB,wBAAwB,GAAA,EAAA,CAAA,CAAA;AAuBpC;AACA,IAAY,aASX;AATD,CAAA,UAAY,aAAa,EAAA;AACvB;;;;;;AAMG;AACH,IAAA,aAAA,CAAA,YAAA,CAAA,GAAA,YAAyB;AAC3B,CAAC,EATW,aAAa,KAAb,aAAa,GAAA,EAAA,CAAA,CAAA;AAWzB;AACA,IAAY,0BAKX;AALD,CAAA,UAAY,0BAA0B,EAAA;AACpC,IAAA,0BAAA,CAAA,0CAAA,CAAA,GAAA,0CAAqF;AACrF,IAAA,0BAAA,CAAA,oBAAA,CAAA,GAAA,oBAAyC;AACzC,IAAA,0BAAA,CAAA,UAAA,CAAA,GAAA,UAAqB;AACrB,IAAA,0BAAA,CAAA,iBAAA,CAAA,GAAA,iBAAmC;AACrC,CAAC,EALW,0BAA0B,KAA1B,0BAA0B,GAAA,EAAA,CAAA,CAAA;AAOtC;AACA,IAAY,WASX;AATD,CAAA,UAAY,WAAW,EAAA;AACrB;;AAEG;AACH,IAAA,WAAA,CAAA,yBAAA,CAAA,GAAA,yBAAmD;AACnD;;AAEG;AACH,IAAA,WAAA,CAAA,qBAAA,CAAA,GAAA,qBAA2C;AAC7C,CAAC,EATW,WAAW,KAAX,WAAW,GAAA,EAAA,CAAA,CAAA;AAWvB;AACA,IAAY,iBAKX;AALD,CAAA,UAAY,iBAAiB,EAAA;AAC3B,IAAA,iBAAA,CAAA,qBAAA,CAAA,GAAA,qBAA2C;AAC3C,IAAA,iBAAA,CAAA,wBAAA,CAAA,GAAA,wBAAiD;AACjD,IAAA,iBAAA,CAAA,iBAAA,CAAA,GAAA,iBAAmC;AACnC,IAAA,iBAAA,CAAA,YAAA,CAAA,GAAA,YAAyB;AAC3B,CAAC,EALW,iBAAiB,KAAjB,iBAAiB,GAAA,EAAA,CAAA,CAAA;AAO7B;AACA,IAAY,gBAaX;AAbD,CAAA,UAAY,gBAAgB,EAAA;AAC1B;;AAEG;AACH,IAAA,gBAAA,CAAA,YAAA,CAAA,GAAA,YAAyB;AACzB;;AAEG;AACH,IAAA,gBAAA,CAAA,aAAA,CAAA,GAAA,aAA2B;AAC3B;;AAEG;AACH,IAAA,gBAAA,CAAA,WAAA,CAAA,GAAA,WAAuB;AACzB,CAAC,EAbW,gBAAgB,KAAhB,gBAAgB,GAAA,EAAA,CAAA,CAAA;AAe5B;AACA,IAAY,mBAiCX;AAjCD,CAAA,UAAY,mBAAmB,EAAA;AAC7B;;AAEG;AACH,IAAA,mBAAA,CAAA,MAAA,CAAA,GAAA,MAAa;AACb;;AAEG;AACH,IAAA,mBAAA,CAAA,IAAA,CAAA,GAAA,IAAS;AACT;;AAEG;AACH,IAAA,mBAAA,CAAA,IAAA,CAAA,GAAA,IAAS;AACT;;AAEG;AACH,IAAA,mBAAA,CAAA,IAAA,CAAA,GAAA,IAAS;AACT;;AAEG;AACH,IAAA,mBAAA,CAAA,IAAA,CAAA,GAAA,IAAS;AACT;;AAEG;AACH,IAAA,mBAAA,CAAA,IAAA,CAAA,GAAA,IAAS;AACT;;AAEG;AACH,IAAA,mBAAA,CAAA,IAAA,CAAA,GAAA,IAAS;AACT;;AAEG;AACH,IAAA,mBAAA,CAAA,IAAA,CAAA,GAAA,IAAS;AACX,CAAC,EAjCW,mBAAmB,KAAnB,mBAAmB,GAAA,EAAA,CAAA,CAAA;AAmC/B;AACA,IAAY,iBAMX;AAND,CAAA,UAAY,iBAAiB,EAAA;AAC3B,IAAA,iBAAA,CAAA,mBAAA,CAAA,GAAA,mBAAuC;AACvC,IAAA,iBAAA,CAAA,yBAAA,CAAA,GAAA,yBAAmD;AACnD,IAAA,iBAAA,CAAA,sBAAA,CAAA,GAAA,sBAA6C;AAC7C,IAAA,iBAAA,CAAA,sBAAA,CAAA,GAAA,sBAA6C;AAC7C,IAAA,iBAAA,CAAA,oBAAA,CAAA,GAAA,oBAAyC;AAC3C,CAAC,EANW,iBAAiB,KAAjB,iBAAiB,GAAA,EAAA,CAAA,CAAA;AAQ7B;AACA,IAAY,oBAKX;AALD,CAAA,UAAY,oBAAoB,EAAA;AAC9B,IAAA,oBAAA,CAAA,sBAAA,CAAA,GAAA,sBAA6C;AAC7C,IAAA,oBAAA,CAAA,oBAAA,CAAA,GAAA,oBAAyC;AACzC,IAAA,oBAAA,CAAA,uBAAA,CAAA,GAAA,uBAA+C;AAC/C,IAAA,oBAAA,CAAA,wBAAA,CAAA,GAAA,wBAAiD;AACnD,CAAC,EALW,oBAAoB,KAApB,oBAAoB,GAAA,EAAA,CAAA,CAAA;AAOhC;AACA,IAAY,oBAKX;AALD,CAAA,UAAY,oBAAoB,EAAA;AAC9B,IAAA,oBAAA,CAAA,sBAAA,CAAA,GAAA,sBAA6C;AAC7C,IAAA,oBAAA,CAAA,qBAAA,CAAA,GAAA,qBAA2C;AAC3C,IAAA,oBAAA,CAAA,qBAAA,CAAA,GAAA,qBAA2C;AAC3C,IAAA,oBAAA,CAAA,sBAAA,CAAA,GAAA,sBAA6C;AAC/C,CAAC,EALW,oBAAoB,KAApB,oBAAoB,GAAA,EAAA,CAAA,CAAA;AAOhC;AACA,IAAY,QASX;AATD,CAAA,UAAY,QAAQ,EAAA;AAClB,IAAA,QAAA,CAAA,mBAAA,CAAA,GAAA,mBAAuC;AACvC,IAAA,QAAA,CAAA,2BAAA,CAAA,GAAA,2BAAuD;AACvD,IAAA,QAAA,CAAA,6BAAA,CAAA,GAAA,6BAA2D;AAC3D,IAAA,QAAA,CAAA,oBAAA,CAAA,GAAA,oBAAyC;AACzC,IAAA,QAAA,CAAA,8BAAA,CAAA,GAAA,8BAA6D;AAC7D,IAAA,QAAA,CAAA,iBAAA,CAAA,GAAA,iBAAmC;AACnC,IAAA,QAAA,CAAA,kBAAA,CAAA,GAAA,kBAAqC;AACrC,IAAA,QAAA,CAAA,yBAAA,CAAA,GAAA,yBAAmD;AACrD,CAAC,EATW,QAAQ,KAAR,QAAQ,GAAA,EAAA,CAAA,CAAA;AAWpB;AACA,IAAY,WAMX;AAND,CAAA,UAAY,WAAW,EAAA;AACrB,IAAA,WAAA,CAAA,YAAA,CAAA,GAAA,YAAyB;AACzB,IAAA,WAAA,CAAA,YAAA,CAAA,GAAA,YAAyB;AACzB,IAAA,WAAA,CAAA,QAAA,CAAA,GAAA,QAAiB;AACjB,IAAA,WAAA,CAAA,UAAA,CAAA,GAAA,UAAqB;AACrB,IAAA,WAAA,CAAA,aAAA,CAAA,GAAA,aAA2B;AAC7B,CAAC,EANW,WAAW,KAAX,WAAW,GAAA,EAAA,CAAA,CAAA;AAQvB;AACA,IAAY,4BAYX;AAZD,CAAA,UAAY,4BAA4B,EAAA;AACtC;;;AAGG;AACH,IAAA,4BAAA,CAAA,OAAA,CAAA,GAAA,OAAe;AACf;;;;AAIG;AACH,IAAA,4BAAA,CAAA,OAAA,CAAA,GAAA,OAAe;AACjB,CAAC,EAZW,4BAA4B,KAA5B,4BAA4B,GAAA,EAAA,CAAA,CAAA;AAcxC;AACA,IAAY,uBAwBX;AAxBD,CAAA,UAAY,uBAAuB,EAAA;AACjC;;;;;AAKG;AACH,IAAA,uBAAA,CAAA,QAAA,CAAA,GAAA,QAAiB;AACjB;;;AAGG;AACH,IAAA,uBAAA,CAAA,QAAA,CAAA,GAAA,QAAiB;AACjB;;;AAGG;AACH,IAAA,uBAAA,CAAA,eAAA,CAAA,GAAA,eAA+B;AAC/B;;;;AAIG;AACH,IAAA,uBAAA,CAAA,UAAA,CAAA,GAAA,UAAqB;AACvB,CAAC,EAxBW,uBAAuB,KAAvB,uBAAuB,GAAA,EAAA,CAAA,CAAA;AA0BnC;AACA,IAAY,uBAWX;AAXD,CAAA,UAAY,uBAAuB,EAAA;AACjC;;;AAGG;AACH,IAAA,uBAAA,CAAA,WAAA,CAAA,GAAA,WAAuB;AACvB;;;AAGG;AACH,IAAA,uBAAA,CAAA,UAAA,CAAA,GAAA,UAAqB;AACvB,CAAC,EAXW,uBAAuB,KAAvB,uBAAuB,GAAA,EAAA,CAAA,CAAA;AAanC;AACA,IAAY,YAaX;AAbD,CAAA,UAAY,YAAY,EAAA;AACtB;;AAEG;AACH,IAAA,YAAA,CAAA,wBAAA,CAAA,GAAA,wBAAiD;AACjD;;AAEG;AACH,IAAA,YAAA,CAAA,mBAAA,CAAA,GAAA,mBAAuC;AACvC;;AAEG;AACH,IAAA,YAAA,CAAA,cAAA,CAAA,GAAA,cAA6B;AAC/B,CAAC,EAbW,YAAY,KAAZ,YAAY,GAAA,EAAA,CAAA,CAAA;AAexB;AACA,IAAY,aAKX;AALD,CAAA,UAAY,aAAa,EAAA;AACvB,IAAA,aAAA,CAAA,mBAAA,CAAA,GAAA,mBAAuC;AACvC,IAAA,aAAA,CAAA,eAAA,CAAA,GAAA,eAA+B;AAC/B,IAAA,aAAA,CAAA,cAAA,CAAA,GAAA,cAA6B;AAC7B,IAAA,aAAA,CAAA,cAAA,CAAA,GAAA,cAA6B;AAC/B,CAAC,EALW,aAAa,KAAb,aAAa,GAAA,EAAA,CAAA,CAAA;AAOzB;AACA,IAAY,SAKX;AALD,CAAA,UAAY,SAAS,EAAA;AACnB,IAAA,SAAA,CAAA,mBAAA,CAAA,GAAA,mBAAuC;AACvC,IAAA,SAAA,CAAA,YAAA,CAAA,GAAA,YAAyB;AACzB,IAAA,SAAA,CAAA,QAAA,CAAA,GAAA,QAAiB;AACjB,IAAA,SAAA,CAAA,QAAA,CAAA,GAAA,QAAiB;AACnB,CAAC,EALW,SAAS,KAAT,SAAS,GAAA,EAAA,CAAA,CAAA;AAOrB;AACA,IAAY,UAKX;AALD,CAAA,UAAY,UAAU,EAAA;AACpB,IAAA,UAAA,CAAA,oBAAA,CAAA,GAAA,oBAAyC;AACzC,IAAA,UAAA,CAAA,UAAA,CAAA,GAAA,UAAqB;AACrB,IAAA,UAAA,CAAA,WAAA,CAAA,GAAA,WAAuB;AACvB,IAAA,UAAA,CAAA,YAAA,CAAA,GAAA,YAAyB;AAC3B,CAAC,EALW,UAAU,KAAV,UAAU,GAAA,EAAA,CAAA,CAAA;AAOtB;AACA,IAAY,kBAiBX;AAjBD,CAAA,UAAY,kBAAkB,EAAA;AAC5B;;AAEG;AACH,IAAA,kBAAA,CAAA,kCAAA,CAAA,GAAA,kCAAqE;AACrE;;AAEG;AACH,IAAA,kBAAA,CAAA,yBAAA,CAAA,GAAA,yBAAmD;AACnD;;AAEG;AACH,IAAA,kBAAA,CAAA,mBAAA,CAAA,GAAA,mBAAuC;AACvC;;AAEG;AACH,IAAA,kBAAA,CAAA,iBAAA,CAAA,GAAA,iBAAmC;AACrC,CAAC,EAjBW,kBAAkB,KAAlB,kBAAkB,GAAA,EAAA,CAAA,CAAA;AAmB9B;AACA,IAAY,aAyBX;AAzBD,CAAA,UAAY,aAAa,EAAA;AACvB;;AAEG;AACH,IAAA,aAAA,CAAA,sBAAA,CAAA,GAAA,sBAA6C;AAC7C;;AAEG;AACH,IAAA,aAAA,CAAA,MAAA,CAAA,GAAA,MAAa;AACb;;AAEG;AACH,IAAA,aAAA,CAAA,OAAA,CAAA,GAAA,OAAe;AACf;;AAEG;AACH,IAAA,aAAA,CAAA,OAAA,CAAA,GAAA,OAAe;AACf;;AAEG;AACH,IAAA,aAAA,CAAA,OAAA,CAAA,GAAA,OAAe;AACf;;AAEG;AACH,IAAA,aAAA,CAAA,UAAA,CAAA,GAAA,UAAqB;AACvB,CAAC,EAzBW,aAAa,KAAb,aAAa,GAAA,EAAA,CAAA,CAAA;AA2BzB;AACA,IAAY,aAaX;AAbD,CAAA,UAAY,aAAa,EAAA;AACvB;;AAEG;AACH,IAAA,aAAA,CAAA,6BAAA,CAAA,GAAA,6BAA2D;AAC3D;;AAEG;AACH,IAAA,aAAA,CAAA,qBAAA,CAAA,GAAA,qBAA2C;AAC3C;;AAEG;AACH,IAAA,aAAA,CAAA,qBAAA,CAAA,GAAA,qBAA2C;AAC7C,CAAC,EAbW,aAAa,KAAb,aAAa,GAAA,EAAA,CAAA,CAAA;AAezB;AACA,IAAY,iBAaX;AAbD,CAAA,UAAY,iBAAiB,EAAA;AAC3B;;AAEG;AACH,IAAA,iBAAA,CAAA,kBAAA,CAAA,GAAA,kBAAqC;AACrC;;AAEG;AACH,IAAA,iBAAA,CAAA,gBAAA,CAAA,GAAA,gBAAiC;AACjC;;AAEG;AACH,IAAA,iBAAA,CAAA,cAAA,CAAA,GAAA,cAA6B;AAC/B,CAAC,EAbW,iBAAiB,KAAjB,iBAAiB,GAAA,EAAA,CAAA,CAAA;AAe7B;AACA,IAAY,gBAaX;AAbD,CAAA,UAAY,gBAAgB,EAAA;AAC1B;;AAEG;AACH,IAAA,gBAAA,CAAA,+BAAA,CAAA,GAAA,+BAA+D;AAC/D;;AAEG;AACH,IAAA,gBAAA,CAAA,wBAAA,CAAA,GAAA,wBAAiD;AACjD;;AAEG;AACH,IAAA,gBAAA,CAAA,uBAAA,CAAA,GAAA,uBAA+C;AACjD,CAAC,EAbW,gBAAgB,KAAhB,gBAAgB,GAAA,EAAA,CAAA,CAAA;AAe5B;AACA,IAAY,cAaX;AAbD,CAAA,UAAY,cAAc,EAAA;AACxB;;AAEG;AACH,IAAA,cAAA,CAAA,6BAAA,CAAA,GAAA,6BAA2D;AAC3D;;AAEG;AACH,IAAA,cAAA,CAAA,sBAAA,CAAA,GAAA,sBAA6C;AAC7C;;AAEG;AACH,IAAA,cAAA,CAAA,qBAAA,CAAA,GAAA,qBAA2C;AAC7C,CAAC,EAbW,cAAc,KAAd,cAAc,GAAA,EAAA,CAAA,CAAA;AAe1B;AACA,IAAY,gBAaX;AAbD,CAAA,UAAY,gBAAgB,EAAA;AAC1B;;AAEG;AACH,IAAA,gBAAA,CAAA,+BAAA,CAAA,GAAA,+BAA+D;AAC/D;;AAEG;AACH,IAAA,gBAAA,CAAA,8BAAA,CAAA,GAAA,8BAA6D;AAC7D;;AAEG;AACH,IAAA,gBAAA,CAAA,iBAAA,CAAA,GAAA,iBAAmC;AACrC,CAAC,EAbW,gBAAgB,KAAhB,gBAAgB,GAAA,EAAA,CAAA,CAAA;AAe5B;AACA,IAAY,YAaX;AAbD,CAAA,UAAY,YAAY,EAAA;AACtB;;AAEG;AACH,IAAA,YAAA,CAAA,2BAAA,CAAA,GAAA,2BAAuD;AACvD;;AAEG;AACH,IAAA,YAAA,CAAA,6BAAA,CAAA,GAAA,6BAA2D;AAC3D;;AAEG;AACH,IAAA,YAAA,CAAA,yBAAA,CAAA,GAAA,yBAAmD;AACrD,CAAC,EAbW,YAAY,KAAZ,YAAY,GAAA,EAAA,CAAA,CAAA;AAexB;AACA,IAAY,KAqDX;AArDD,CAAA,UAAY,KAAK,EAAA;AACf;;AAEG;AACH,IAAA,KAAA,CAAA,mBAAA,CAAA,GAAA,mBAAuC;AACvC;;AAEG;AACH,IAAA,KAAA,CAAA,iBAAA,CAAA,GAAA,iBAAmC;AACnC;;AAEG;AACH,IAAA,KAAA,CAAA,2BAAA,CAAA,GAAA,2BAAuD;AACvD;;AAEG;AACH,IAAA,KAAA,CAAA,iBAAA,CAAA,GAAA,iBAAmC;AACnC;;AAEG;AACH,IAAA,KAAA,CAAA,sBAAA,CAAA,GAAA,sBAA6C;AAC7C;;AAEG;AACH,IAAA,KAAA,CAAA,sBAAA,CAAA,GAAA,sBAA6C;AAC7C;;AAEG;AACH,IAAA,KAAA,CAAA,iBAAA,CAAA,GAAA,iBAAmC;AACnC;;AAEG;AACH,IAAA,KAAA,CAAA,2BAAA,CAAA,GAAA,2BAAuD;AACvD;;AAEG;AACH,IAAA,KAAA,CAAA,iBAAA,CAAA,GAAA,iBAAmC;AACnC;;AAEG;AACH,IAAA,KAAA,CAAA,sBAAA,CAAA,GAAA,sBAA6C;AAC7C;;AAEG;AACH,IAAA,KAAA,CAAA,sBAAA,CAAA,GAAA,sBAA6C;AAC7C;;AAEG;AACH,IAAA,KAAA,CAAA,sBAAA,CAAA,GAAA,sBAA6C;AAC7C;;AAEG;AACH,IAAA,KAAA,CAAA,sBAAA,CAAA,GAAA,sBAA6C;AAC/C,CAAC,EArDW,KAAK,KAAL,KAAK,GAAA,EAAA,CAAA,CAAA;AAuDjB;AACA,IAAY,mBAoBX;AApBD,CAAA,UAAY,mBAAmB,EAAA;AAC7B;;AAEG;AACH,IAAA,mBAAA,CAAA,mCAAA,CAAA,GAAA,mCAAuE;AACvE;;;AAGG;AACH,IAAA,mBAAA,CAAA,SAAA,CAAA,GAAA,SAAmB;AACnB;;;AAGG;AACH,IAAA,mBAAA,CAAA,WAAA,CAAA,GAAA,WAAuB;AACvB;;;AAGG;AACH,IAAA,mBAAA,CAAA,cAAA,CAAA,GAAA,cAA6B;AAC/B,CAAC,EApBW,mBAAmB,KAAnB,mBAAmB,GAAA,EAAA,CAAA,CAAA;AAsB/B;AACA,IAAY,wBAuBX;AAvBD,CAAA,UAAY,wBAAwB,EAAA;AAClC;;AAEG;AACH,IAAA,wBAAA,CAAA,8BAAA,CAAA,GAAA,8BAA6D;AAC7D;;AAEG;AACH,IAAA,wBAAA,CAAA,MAAA,CAAA,GAAA,MAAa;AACb;;AAEG;AACH,IAAA,wBAAA,CAAA,OAAA,CAAA,GAAA,OAAe;AACf;;;AAGG;AACH,IAAA,wBAAA,CAAA,MAAA,CAAA,GAAA,MAAa;AACb;;;AAGG;AACH,IAAA,wBAAA,CAAA,eAAA,CAAA,GAAA,eAA+B;AACjC,CAAC,EAvBW,wBAAwB,KAAxB,wBAAwB,GAAA,EAAA,CAAA,CAAA;;AC9rCpC;;;;AAIG;AAmGG,SAAU,KAAK,CAAC,MAA+B,EAAA;IACnD,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,SAAS,EAAE;AAC3C,QAAA,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC;IAC1C;AACA,IAAA,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;AAC9B,QAAA,OAAO,MAAM;IACf;AACA,IAAA,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;AAC9B,QAAA,OAAO,EAAC,IAAI,EAAE,MAAM,EAAC;IACvB;IACA,MAAM,IAAI,KAAK,CAAC,CAAA,uBAAA,EAA0B,OAAO,MAAM,CAAA,CAAE,CAAC;AAC5D;AAEM,SAAU,MAAM,CAAC,MAAmC,EAAA;IACxD,IACE,MAAM,KAAK,IAAI;AACf,QAAA,MAAM,KAAK,SAAS;AACpB,SAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,EAC9C;AACA,QAAA,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC;IAC9C;AACA,IAAA,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;AACzB,QAAA,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,IAAuB,CAAE,CAAC;IAC9D;AACA,IAAA,OAAO,CAAC,KAAK,CAAC,MAAM,CAAE,CAAC;AACzB;AAEA,SAAS,UAAU,CAAC,MAAe,EAAA;IACjC,QACE,MAAM,KAAK,IAAI;AACf,QAAA,MAAM,KAAK,SAAS;QACpB,OAAO,MAAM,KAAK,QAAQ;AAC1B,QAAA,OAAO,IAAI,MAAM;QACjB,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;AAE/B;AAEA,SAAS,mBAAmB,CAAC,MAAe,EAAA;IAC1C,QACE,MAAM,KAAK,IAAI;AACf,QAAA,MAAM,KAAK,SAAS;QACpB,OAAO,MAAM,KAAK,QAAQ;QAC1B,cAAc,IAAI,MAAM;AAE5B;AAEA,SAAS,uBAAuB,CAAC,MAAe,EAAA;IAC9C,QACE,MAAM,KAAK,IAAI;AACf,QAAA,MAAM,KAAK,SAAS;QACpB,OAAO,MAAM,KAAK,QAAQ;QAC1B,kBAAkB,IAAI,MAAM;AAEhC;AAEM,SAAU,QAAQ,CAAC,MAA2B,EAAA;IAClD,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,SAAS,EAAE;AAC3C,QAAA,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC;IAC7C;AACA,IAAA,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE;;;AAGtB,QAAA,OAAO,MAAuB;IAChC;IAEA,OAAO;AACL,QAAA,IAAI,EAAE,MAAM;AACZ,QAAA,KAAK,EAAE,MAAM,CAAC,MAA6B,CAAE;KAC9C;AACH;AAsCM,SAAU,SAAS,CAAC,MAA+B,EAAA;IACvD,IACE,MAAM,KAAK,IAAI;AACf,QAAA,MAAM,KAAK,SAAS;AACpB,SAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,EAC9C;AACA,QAAA,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC;IAC1C;IACA,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;;QAE1B,IAAI,mBAAmB,CAAC,MAAM,CAAC,IAAI,uBAAuB,CAAC,MAAM,CAAC,EAAE;AAClE,YAAA,MAAM,IAAI,KAAK,CACb,uHAAuH,CACxH;QACH;AACA,QAAA,OAAO,CAAC,QAAQ,CAAC,MAA4B,CAAC,CAAC;IACjD;IAEA,MAAM,MAAM,GAAoB,EAAE;IAClC,MAAM,gBAAgB,GAAsB,EAAE;IAC9C,MAAM,cAAc,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAE5C,IAAA,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE;AACzB,QAAA,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC;AAElC,QAAA,IAAI,SAAS,IAAI,cAAc,EAAE;AAC/B,YAAA,MAAM,IAAI,KAAK,CACb,yIAAyI,CAC1I;QACH;QAEA,IAAI,SAAS,EAAE;;;AAGb,YAAA,MAAM,CAAC,IAAI,CAAC,IAAqB,CAAC;QACpC;aAAO,IAAI,mBAAmB,CAAC,IAAI,CAAC,IAAI,uBAAuB,CAAC,IAAI,CAAC,EAAE;AACrE,YAAA,MAAM,IAAI,KAAK,CACb,2JAA2J,CAC5J;QACH;aAAO;AACL,YAAA,gBAAgB,CAAC,IAAI,CAAC,IAAuB,CAAC;QAChD;IACF;IAEA,IAAI,CAAC,cAAc,EAAE;AACnB,QAAA,MAAM,CAAC,IAAI,CAAC,EAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,gBAAgB,CAAC,EAAC,CAAC;IAC9D;AACA,IAAA,OAAO,MAAM;AACf;;AClQA;;;;AAIG;AAEH;;;AAGG;AAEH,IAAY,SAKX;AALD,CAAA,UAAY,SAAS,EAAA;AACnB,IAAA,SAAA,CAAA,SAAA,CAAA,SAAA,CAAA,GAAA,CAAA,CAAA,GAAA,SAAW;AACX,IAAA,SAAA,CAAA,SAAA,CAAA,KAAA,CAAA,GAAA,CAAA,CAAA,GAAA,KAAO;AACP,IAAA,SAAA,CAAA,SAAA,CAAA,MAAA,CAAA,GAAA,CAAA,CAAA,GAAA,MAAQ;AACR,IAAA,SAAA,CAAA,SAAA,CAAA,MAAA,CAAA,GAAA,CAAA,CAAA,GAAA,MAAQ;AACV,CAAC,EALW,SAAS,KAAT,SAAS,GAAA,EAAA,CAAA,CAAA;AAOrB,IAAY,iBAOX;AAPD,CAAA,UAAY,iBAAiB,EAAA;AAC3B,IAAA,iBAAA,CAAA,iBAAA,CAAA,QAAA,CAAA,GAAA,CAAA,CAAA,GAAA,QAAU;AACV,IAAA,iBAAA,CAAA,iBAAA,CAAA,SAAA,CAAA,GAAA,CAAA,CAAA,GAAA,SAAW;AACX,IAAA,iBAAA,CAAA,iBAAA,CAAA,SAAA,CAAA,GAAA,CAAA,CAAA,GAAA,SAAW;AACX,IAAA,iBAAA,CAAA,iBAAA,CAAA,cAAA,CAAA,GAAA,CAAA,CAAA,GAAA,cAAgB;AAChB,IAAA,iBAAA,CAAA,iBAAA,CAAA,MAAA,CAAA,GAAA,CAAA,CAAA,GAAA,MAAQ;AACR,IAAA,iBAAA,CAAA,iBAAA,CAAA,QAAA,CAAA,GAAA,CAAA,CAAA,GAAA,QAAU;AACZ,CAAC,EAPW,iBAAiB,KAAjB,iBAAiB,GAAA,EAAA,CAAA,CAAA;;AClB7B;;;;AAIG;AAYH,SAAS,WAAW,GAAA;IAClB,OAAO;QACL,QAAQ,EAAE,IAAI,GAAG,EAAE;AACnB,QAAA,KAAK,EAAE,KAAK;KACb;AACH;AAEA;;;AAGG;MACU,aAAa,CAAA;AAGxB;;AAEG;AACH,IAAA,WAAA,CAAY,KAAkB,EAAA;AAC5B,QAAA,IAAI,CAAC,IAAI,GAAG,WAAW,EAAE;AACzB,QAAA,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;AACxB,YAAA,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;QAChB;IACF;AAEA;;;AAGG;AACH,IAAA,aAAa,CAAC,IAAY,EAAA;AACxB,QAAA,IAAI,IAAI,GAAG,IAAI,CAAC,IAAI;QACpB,IAAI,MAAM,GAAG,CAAC;QAEd,IAAI,CAAC,GAAG,CAAC;AACT,QAAA,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE;YACvB,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;YACrC,IAAI,CAAC,KAAK,EAAE;AACV,gBAAA,OAAO,MAAM;YACf;AACA,YAAA,IAAI,KAAK,CAAC,KAAK,EAAE;AACf,gBAAA,MAAM,GAAG,CAAC,GAAG,CAAC;YAChB;YACA,IAAI,GAAG,KAAK;AACZ,YAAA,CAAC,EAAE;QACL;AAEA,QAAA,OAAO,MAAM;IACf;AAEA;;AAEG;AACK,IAAA,GAAG,CAAC,IAAY,EAAA;AACtB,QAAA,IAAI,IAAI,GAAG,IAAI,CAAC,IAAI;AAEpB,QAAA,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE;YACvB,IAAI,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;YACnC,IAAI,CAAC,KAAK,EAAE;gBACV,KAAK,GAAG,WAAW,EAAE;gBACrB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC;YAChC;YACA,IAAI,GAAG,KAAK;QACd;AAEA,QAAA,IAAI,CAAC,KAAK,GAAG,IAAI;IACnB;AACD;;ACjFD;;;;AAIG;AAEH;;;;;;AAMG;MACU,aAAa,CAAA;AAIxB;;;;;;AAMG;IACH,WAAA,CAAY,QAAgB,EAAE,GAA2B,EAAA;AACvD,QAAA,IAAI,CAAC,GAAG,GAAG,GAAG;AACd,QAAA,IAAI,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,GAAG,CAAC,CAAC,CAAC;;AAEjD,QAAA,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAW;AAC3B,QAAA,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;IACvB;AAEA;;AAEG;IACH,GAAG,GAAA;AACD,QAAA,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;IAC9B;AAEA;;AAEG;AACH,IAAA,MAAM,CAAC,IAAO,EAAA;AACZ,QAAA,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;QACrB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;IACpC;AAEA;;;AAGG;IACH,MAAM,GAAA;QACJ,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE;AACzB,YAAA,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC;QACtD;QACA,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;AAC7B,QAAA,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;AACjD,QAAA,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE;QAChB,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE;AACzB,YAAA,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;QAClB;AACA,QAAA,OAAO,OAAO;IAChB;AAEA;;AAEG;AACH,IAAA,UAAU,CAAC,EAAwB,EAAA;QACjC,IAAI,CAAC,GAAG,CAAC;AACT,QAAA,OAAO,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE;AAClD,YAAA,CAAC,EAAE;QACL;QACA,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;YAC3B;QACF;AAEA,QAAA,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YAC9C,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE;AACtB,gBAAA,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;AAC7B,gBAAA,CAAC,EAAE;YACL;QACF;AAEA,QAAA,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;QAErB,IAAI,CAAC,WAAW,EAAE;IACpB;AAEA;;AAEG;IACK,WAAW,GAAA;QACjB,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE;AAC3D,YAAA,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;QAClB;IACF;AAEA;;AAEG;AACK,IAAA,MAAM,CAAC,CAAS,EAAA;QACtB,IAAI,CAAC,GAAG,CAAC;AACT,QAAA,OAAO,CAAC,GAAG,CAAC,EAAE;YACZ,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC;YAC3B,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE;gBAC/C;YACF;AACA,YAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAC/D,CAAC,GAAG,CAAC;QACP;IACF;AAEA;;AAEG;AACK,IAAA,QAAQ,CAAC,CAAS,EAAA;;QAExB,OAAO,IAAI,EAAE;AACX,YAAA,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC;YACf,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;gBAC1B;YACF;YAEA,IAAI,QAAQ,GAAG,CAAC;YAChB,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;gBAC7B,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE;AAClD,oBAAA,QAAQ,GAAG,CAAC,GAAG,CAAC;gBAClB;YACF;YAEA,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,EAAE;gBACtD;YACF;AAEA,YAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,GAAG;AACtC,gBAAA,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;AACpB,gBAAA,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;aACd;YACD,CAAC,GAAG,QAAQ;QACd;IACF;AACD;;AC7ID;AACA;AACA;;;AAUA;AACA,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,EAAE,OAAO,GAAG,SAAS,CAAC,MAAM;AAC5D,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI;;AAE5B;AACA,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC;;AAEtE,MAAM,aAAa,GAAG,KAAK,CAAC,aAAa,GAAG,CAAC,MAAM;AAC1D;AACA;AACA;AACA;AACA;AACA,EAAE,MAAM,aAAa,GAAG,EAAE;;AAE1B,EAAE,aAAa,CAAC,WAAW,GAAG,CAAC,WAAW;AAC1C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,SAAS,WAAW,CAAC,UAAU,EAAE;AACrC,MAAM,IAAI,CAAC,KAAK,GAAG,EAAE;AACrB,MAAM,IAAI,CAAC,cAAc,GAAG,EAAE;AAC9B,MAAM,IAAI,CAAC,cAAc,GAAG,EAAE;AAC9B,MAAM,IAAI,CAAC,kBAAkB,GAAG,EAAE;AAClC,MAAM,IAAI,UAAU;AACpB,QAAQ,KAAK,IAAI,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;AAC5E,UAAU,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC9E,IAAI;;AAEJ;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,KAAK,GAAG,KAAK,CAAC,UAAU;;AAElD;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,WAAW,GAAG,EAAE;;AAE1C;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,WAAW,GAAG,EAAE;;AAE1C;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,SAAS,GAAG,CAAC;;AAEvC;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,SAAS,GAAG,IAAI;;AAE1C;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,cAAc,GAAG,KAAK,CAAC,UAAU;;AAE3D;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,kBAAkB,GAAG,CAAC;;AAEhD;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,yBAAyB,GAAG,KAAK;;AAE3D;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,6BAA6B,GAAG,CAAC;;AAE3D;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,oCAAoC;AAC9D,QAAQ,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC;;AAExD;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,iBAAiB,GAAG,MAAM;;AAEpD;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,iBAAiB;AAC3C,QAAQ,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC;;AAExD;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,oBAAoB,GAAG,IAAI;;AAErD;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,kBAAkB,GAAG,CAAC;;AAEhD;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,oBAAoB,GAAG,CAAC;;AAElD;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,qBAAqB,GAAG,OAAO;;AAEzD;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,eAAe,GAAG,IAAI;;AAEhD;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,iBAAiB,GAAG,IAAI;;AAElD;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,UAAU,GAAG,EAAE;;AAEzC;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,gBAAgB,GAAG,CAAC;;AAE9C;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,sBAAsB,GAAG,EAAE;;AAErD;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,oBAAoB,GAAG,IAAI;;AAErD;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,aAAa,GAAG,IAAI;;AAE9C;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,iBAAiB,GAAG,IAAI;;AAElD;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,uBAAuB,GAAG,KAAK;;AAEzD;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,yBAAyB,GAAG,KAAK;;AAE3D;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,WAAW,GAAG,KAAK;;AAE7C;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,wBAAwB,GAAG,EAAE;;AAEvD;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,cAAc,GAAG,KAAK,CAAC,UAAU;;AAE3D;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,kBAAkB,GAAG,KAAK,CAAC,UAAU;;AAE/D;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,aAAa,GAAG,EAAE;;AAE5C;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,YAAY,GAAG,KAAK;;AAE9C;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,0BAA0B,GAAG,IAAI;;AAE3D;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI;;AAE/C;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,WAAW,GAAG,KAAK;;AAE7C;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,KAAK,GAAG,CAAC;;AAEnC;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,KAAK,GAAG,CAAC;;AAEnC;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,KAAK,GAAG,CAAC;;AAEnC;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,KAAK,GAAG,EAAE;;AAEpC;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,QAAQ,GAAG,OAAO;;AAE5C;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,QAAQ,GAAG,KAAK;;AAE1C;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,QAAQ,GAAG,MAAM;;AAE3C;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,QAAQ,GAAG,OAAO;;AAE5C;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,UAAU,GAAG,UAAU;;AAEjD;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,yBAAyB,GAAG,KAAK;;AAE3D;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,sBAAsB,GAAG,EAAE;;AAErD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,MAAM,GAAG,SAAS,MAAM,CAAC,UAAU,EAAE;AACrD,MAAM,OAAO,IAAI,WAAW,CAAC,UAAU,CAAC;AACxC,IAAI,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,MAAM,GAAG,SAAS,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE;AAC1D,MAAM,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE;AAC5C,MAAM,IAAI,OAAO,CAAC,KAAK,IAAI,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM;AACvD,QAAQ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;AACrD,UAAU,MAAM,CAAC,MAAM,yBAAyB,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC5E,MAAM,IAAI,OAAO,CAAC,WAAW,IAAI,IAAI;AACrC,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC;AAC5D,QAAQ,MAAM,CAAC,MAAM,yBAAyB,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC;AAC7E,MAAM,IAAI,OAAO,CAAC,SAAS,IAAI,IAAI;AACnC,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC;AAC1D,QAAQ,MAAM,CAAC,MAAM,yBAAyB,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC;AAC1E,MAAM,IAAI,OAAO,CAAC,SAAS,IAAI,IAAI;AACnC,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC;AAC1D,QAAQ,MAAM,CAAC,MAAM,yBAAyB,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC;AAC1E,MAAM,IAAI,OAAO,CAAC,cAAc,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,MAAM;AACzE,QAAQ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC,MAAM,EAAE,EAAE,CAAC;AAC9D,UAAU,MAAM,CAAC,MAAM,yBAAyB,EAAE;AAClD,eAAe,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;AAChD,MAAM,IAAI,OAAO,CAAC,kBAAkB,IAAI,IAAI;AAC5C,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,oBAAoB,CAAC;AACnE,QAAQ,MAAM,CAAC,MAAM,yBAAyB,EAAE;AAChD,aAAa,KAAK,CAAC,OAAO,CAAC,kBAAkB,CAAC;AAC9C,MAAM,IAAI,OAAO,CAAC,WAAW,IAAI,IAAI;AACrC,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC;AAC5D,QAAQ,MAAM,CAAC,MAAM,yBAAyB,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC;AAC7E,MAAM,IAAI,OAAO,CAAC,iBAAiB,IAAI,IAAI;AAC3C,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,mBAAmB,CAAC;AAClE,QAAQ,MAAM,CAAC,MAAM,0BAA0B,EAAE;AACjD,aAAa,KAAK,CAAC,OAAO,CAAC,iBAAiB,CAAC;AAC7C,MAAM,IAAI,OAAO,CAAC,iBAAiB,IAAI,IAAI;AAC3C,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,mBAAmB,CAAC;AAClE,QAAQ,MAAM,CAAC,MAAM,0BAA0B,EAAE;AACjD,aAAa,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC;AAC9C,MAAM,IAAI,OAAO,CAAC,kBAAkB,IAAI,IAAI;AAC5C,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,oBAAoB,CAAC;AACnE,QAAQ,MAAM,CAAC,MAAM,0BAA0B,EAAE;AACjD,aAAa,KAAK,CAAC,OAAO,CAAC,kBAAkB,CAAC;AAC9C,MAAM,IAAI,OAAO,CAAC,oBAAoB,IAAI,IAAI;AAC9C,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,sBAAsB,CAAC;AACrE,QAAQ,MAAM,CAAC,MAAM,0BAA0B,GAAG;AAClD,aAAa,KAAK,CAAC,OAAO,CAAC,oBAAoB,CAAC;AAChD,MAAM,IAAI,OAAO,CAAC,qBAAqB,IAAI,IAAI;AAC/C,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,uBAAuB,CAAC;AACtE,QAAQ,MAAM,CAAC,MAAM,0BAA0B,GAAG;AAClD,aAAa,KAAK,CAAC,OAAO,CAAC,qBAAqB,CAAC;AACjD,MAAM,IAAI,OAAO,CAAC,eAAe,IAAI,IAAI;AACzC,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,iBAAiB,CAAC;AAChE,QAAQ,MAAM,CAAC,MAAM,0BAA0B,GAAG;AAClD,aAAa,KAAK,CAAC,OAAO,CAAC,eAAe,CAAC;AAC3C,MAAM,IAAI,OAAO,CAAC,UAAU,IAAI,IAAI;AACpC,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC;AAC3D,QAAQ,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC;AAC7E,MAAM,IAAI,OAAO,CAAC,gBAAgB,IAAI,IAAI;AAC1C,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,kBAAkB,CAAC;AACjE,QAAQ,MAAM,CAAC,MAAM,0BAA0B,GAAG;AAClD,aAAa,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC;AAC5C,MAAM,IAAI,OAAO,CAAC,iBAAiB,IAAI,IAAI;AAC3C,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,mBAAmB,CAAC;AAClE,QAAQ,MAAM,CAAC,MAAM,0BAA0B,GAAG;AAClD,aAAa,KAAK,CAAC,OAAO,CAAC,iBAAiB,CAAC;AAC7C,MAAM,IAAI,OAAO,CAAC,oBAAoB,IAAI,IAAI;AAC9C,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,sBAAsB,CAAC;AACrE,QAAQ,MAAM,CAAC,MAAM,0BAA0B,GAAG;AAClD,aAAa,IAAI,CAAC,OAAO,CAAC,oBAAoB,CAAC;AAC/C,MAAM,IAAI,OAAO,CAAC,sBAAsB,IAAI,IAAI;AAChD,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,wBAAwB,CAAC;AACvE,QAAQ,MAAM,CAAC,MAAM,0BAA0B,GAAG;AAClD,aAAa,KAAK,CAAC,OAAO,CAAC,sBAAsB,CAAC;AAClD,MAAM,IAAI,OAAO,CAAC,oBAAoB,IAAI,IAAI;AAC9C,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,sBAAsB,CAAC;AACrE,QAAQ,MAAM,CAAC,MAAM,0BAA0B,GAAG;AAClD,aAAa,IAAI,CAAC,OAAO,CAAC,oBAAoB,CAAC;AAC/C,MAAM,IAAI,OAAO,CAAC,iBAAiB,IAAI,IAAI;AAC3C,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,mBAAmB,CAAC;AAClE,QAAQ,MAAM,CAAC,MAAM,0BAA0B,GAAG;AAClD,aAAa,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC;AAC5C,MAAM,IAAI,OAAO,CAAC,aAAa,IAAI,IAAI;AACvC,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC;AAC9D,QAAQ,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC;AAC/E,MAAM,IAAI,OAAO,CAAC,uBAAuB,IAAI,IAAI;AACjD,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,yBAAyB,CAAC;AACxE,QAAQ,MAAM,CAAC,MAAM,0BAA0B,GAAG;AAClD,aAAa,IAAI,CAAC,OAAO,CAAC,uBAAuB,CAAC;AAClD,MAAM,IAAI,OAAO,CAAC,WAAW,IAAI,IAAI;AACrC,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC;AAC5D,QAAQ,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC;AAC7E,MAAM,IAAI,OAAO,CAAC,yBAAyB,IAAI,IAAI;AACnD,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,2BAA2B,CAAC;AAC1E,QAAQ,MAAM,CAAC,MAAM,0BAA0B,GAAG;AAClD,aAAa,IAAI,CAAC,OAAO,CAAC,yBAAyB,CAAC;AACpD,MAAM,IAAI,OAAO,CAAC,cAAc,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,MAAM;AACzE,QAAQ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC,MAAM,EAAE,EAAE,CAAC;AAC9D,UAAU,MAAM,CAAC,MAAM,0BAA0B,GAAG;AACpD,eAAe,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;AAChD,MAAM,IAAI,OAAO,CAAC,kBAAkB,IAAI,IAAI;AAC5C,UAAU,OAAO,CAAC,kBAAkB,CAAC,MAAM;AAC3C,QAAQ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,kBAAkB,CAAC,MAAM,EAAE,EAAE,CAAC;AAClE,UAAU,MAAM,CAAC,MAAM,0BAA0B,GAAG;AACpD,eAAe,MAAM,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC;AACpD,MAAM,IAAI,OAAO,CAAC,0BAA0B,IAAI,IAAI;AACpD,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,4BAA4B,CAAC;AAC3E,QAAQ,MAAM,CAAC,MAAM,0BAA0B,GAAG;AAClD,aAAa,IAAI,CAAC,OAAO,CAAC,0BAA0B,CAAC;AACrD,MAAM,IAAI,OAAO,CAAC,cAAc,IAAI,IAAI;AACxC,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,gBAAgB,CAAC;AAC/D,QAAQ,MAAM,CAAC,MAAM,0BAA0B,GAAG;AAClD,aAAa,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC;AACzC,MAAM,IAAI,OAAO,CAAC,WAAW,IAAI,IAAI;AACrC,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC;AAC5D,QAAQ,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC;AAC7E,MAAM,IAAI,OAAO,CAAC,YAAY,IAAI,IAAI;AACtC,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC;AAC7D,QAAQ,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC;AAC9E,MAAM,IAAI,OAAO,CAAC,aAAa,IAAI,IAAI;AACvC,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC;AAC9D,QAAQ,MAAM,CAAC,MAAM,0BAA0B,GAAG;AAClD,aAAa,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC;AAC1C,MAAM,IAAI,OAAO,CAAC,KAAK,IAAI,IAAI,IAAI,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC;AAC/E,QAAQ,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;AACxE,MAAM,IAAI,OAAO,CAAC,KAAK,IAAI,IAAI,IAAI,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC;AAC/E,QAAQ,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;AACxE,MAAM,IAAI,OAAO,CAAC,KAAK,IAAI,IAAI,IAAI,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC;AAC/E,QAAQ,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;AACxE,MAAM,IAAI,OAAO,CAAC,KAAK,IAAI,IAAI,IAAI,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC;AAC/E,QAAQ,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;AACxE,MAAM,IAAI,OAAO,CAAC,UAAU,IAAI,IAAI;AACpC,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC;AAC3D,QAAQ,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;AAC9E,MAAM,IAAI,OAAO,CAAC,QAAQ,IAAI,IAAI;AAClC,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC;AACzD,QAAQ,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC;AAC5E,MAAM,IAAI,OAAO,CAAC,QAAQ,IAAI,IAAI;AAClC,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC;AACzD,QAAQ,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC;AAC5E,MAAM,IAAI,OAAO,CAAC,QAAQ,IAAI,IAAI;AAClC,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC;AACzD,QAAQ,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC;AAC5E,MAAM,IAAI,OAAO,CAAC,QAAQ,IAAI,IAAI;AAClC,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC;AACzD,QAAQ,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC;AAC5E,MAAM,IAAI,OAAO,CAAC,yBAAyB,IAAI,IAAI;AACnD,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,2BAA2B,CAAC;AAC1E,QAAQ,MAAM,CAAC,MAAM,0BAA0B,GAAG;AAClD,aAAa,IAAI,CAAC,OAAO,CAAC,yBAAyB,CAAC;AACpD,MAAM,IAAI,OAAO,CAAC,yBAAyB,IAAI,IAAI;AACnD,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,2BAA2B,CAAC;AAC1E,QAAQ,MAAM,CAAC,MAAM,0BAA0B,GAAG;AAClD,aAAa,IAAI,CAAC,OAAO,CAAC,yBAAyB,CAAC;AACpD,MAAM,IAAI,OAAO,CAAC,6BAA6B,IAAI,IAAI;AACvD,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,+BAA+B,CAAC;AAC9E,QAAQ,MAAM,CAAC,MAAM,0BAA0B,GAAG;AAClD,aAAa,KAAK,CAAC,OAAO,CAAC,6BAA6B,CAAC;AACzD,MAAM,IAAI,OAAO,CAAC,oCAAoC,IAAI,IAAI;AAC9D,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI;AACpC,cAAc,OAAO,EAAE,sCAAsC,CAAC;AAC9D,QAAQ,MAAM,CAAC,MAAM,0BAA0B,GAAG;AAClD,aAAa,MAAM,CAAC,OAAO,CAAC,oCAAoC,CAAC;AACjE,MAAM,IAAI,OAAO,CAAC,wBAAwB,IAAI,IAAI;AAClD,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,0BAA0B,CAAC;AACzE,QAAQ,MAAM,CAAC,MAAM,0BAA0B,GAAG;AAClD,aAAa,MAAM,CAAC,OAAO,CAAC,wBAAwB,CAAC;AACrD,MAAM,IAAI,OAAO,CAAC,sBAAsB,IAAI,IAAI;AAChD,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,wBAAwB,CAAC;AACvE,QAAQ,MAAM,CAAC,MAAM,0BAA0B,GAAG;AAClD,aAAa,MAAM,CAAC,OAAO,CAAC,sBAAsB,CAAC;AACnD,MAAM,OAAO,MAAM;AACnB,IAAI,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,eAAe,GAAG,SAAS,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE;AAC5E,MAAM,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,MAAM,EAAE;AAClD,IAAI,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,MAAM,GAAG,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE;AAChE,MAAM,IAAI,EAAE,MAAM,YAAY,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC;AACvE,MAAM,IAAI,GAAG,GAAG,MAAM,KAAK,SAAS,GAAG,MAAM,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,GAAG,MAAM;AACvE,UAAU,OAAO,GAAG,IAAI,KAAK,CAAC,aAAa,CAAC,WAAW,EAAE;AACzD,MAAM,OAAO,MAAM,CAAC,GAAG,GAAG,GAAG,EAAE;AAC/B,QAAQ,IAAI,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE;AACjC,QAAQ,IAAI,GAAG,KAAK,KAAK,EAAE;AAC3B,QAAQ,QAAQ,GAAG,KAAK,CAAC;AACzB,UAAU,KAAK,CAAC,EAAE;AAClB,YAAY,IAAI,EAAE,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,KAAK,GAAG,EAAE;AAC5E,YAAY,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;AAC/C,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,CAAC,EAAE;AAClB,YAAY,OAAO,CAAC,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE;AACjD,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,CAAC,EAAE;AAClB,YAAY,OAAO,CAAC,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE;AACjD,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,CAAC,EAAE;AAClB,YAAY,OAAO,CAAC,SAAS,GAAG,MAAM,CAAC,KAAK,EAAE;AAC9C,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,CAAC,EAAE;AAClB,YAAY,OAAO,CAAC,SAAS,GAAG,MAAM,CAAC,KAAK,EAAE;AAC9C,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,CAAC,EAAE;AAClB,YAAY,IAAI,EAAE,OAAO,CAAC,cAAc,IAAI,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC;AAC1E,cAAc,OAAO,CAAC,cAAc,GAAG,EAAE;AACzC,YAAY,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;AACxD,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,CAAC,EAAE;AAClB,YAAY,OAAO,CAAC,kBAAkB,GAAG,MAAM,CAAC,KAAK,EAAE;AACvD,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,OAAO,CAAC,yBAAyB,GAAG,MAAM,CAAC,IAAI,EAAE;AAC7D,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,OAAO,CAAC,6BAA6B,GAAG,MAAM,CAAC,KAAK,EAAE;AAClE,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,OAAO,CAAC,oCAAoC,GAAG,MAAM,CAAC,MAAM,EAAE;AAC1E,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,OAAO,CAAC,iBAAiB,GAAG,MAAM,CAAC,KAAK,EAAE;AACtD,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,OAAO,CAAC,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE;AACvD,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,OAAO,CAAC,oBAAoB,GAAG,MAAM,CAAC,IAAI,EAAE;AACxD,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,OAAO,CAAC,kBAAkB,GAAG,MAAM,CAAC,KAAK,EAAE;AACvD,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,OAAO,CAAC,oBAAoB,GAAG,MAAM,CAAC,KAAK,EAAE;AACzD,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,OAAO,CAAC,qBAAqB,GAAG,MAAM,CAAC,KAAK,EAAE;AAC1D,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,OAAO,CAAC,eAAe,GAAG,MAAM,CAAC,KAAK,EAAE;AACpD,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,OAAO,CAAC,iBAAiB,GAAG,MAAM,CAAC,KAAK,EAAE;AACtD,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,OAAO,CAAC,UAAU,GAAG,MAAM,CAAC,KAAK,EAAE;AAC/C,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,OAAO,CAAC,gBAAgB,GAAG,MAAM,CAAC,KAAK,EAAE;AACrD,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,OAAO,CAAC,sBAAsB,GAAG,MAAM,CAAC,KAAK,EAAE;AAC3D,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,OAAO,CAAC,oBAAoB,GAAG,MAAM,CAAC,IAAI,EAAE;AACxD,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,OAAO,CAAC,aAAa,GAAG,MAAM,CAAC,IAAI,EAAE;AACjD,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,OAAO,CAAC,iBAAiB,GAAG,MAAM,CAAC,IAAI,EAAE;AACrD,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,OAAO,CAAC,uBAAuB,GAAG,MAAM,CAAC,IAAI,EAAE;AAC3D,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,OAAO,CAAC,yBAAyB,GAAG,MAAM,CAAC,IAAI,EAAE;AAC7D,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,OAAO,CAAC,WAAW,GAAG,MAAM,CAAC,IAAI,EAAE;AAC/C,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,OAAO,CAAC,wBAAwB,GAAG,MAAM,CAAC,MAAM,EAAE;AAC9D,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,IAAI,EAAE,OAAO,CAAC,cAAc,IAAI,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC;AAC1E,cAAc,OAAO,CAAC,cAAc,GAAG,EAAE;AACzC,YAAY,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;AACxD,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,IAAI,EAAE,OAAO,CAAC,kBAAkB;AAC5C,kBAAkB,OAAO,CAAC,kBAAkB,CAAC,MAAM,CAAC;AACpD,cAAc,OAAO,CAAC,kBAAkB,GAAG,EAAE;AAC7C,YAAY,OAAO,CAAC,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;AAC5D,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,OAAO,CAAC,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE;AACnD,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,OAAO,CAAC,YAAY,GAAG,MAAM,CAAC,IAAI,EAAE;AAChD,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,OAAO,CAAC,0BAA0B,GAAG,MAAM,CAAC,IAAI,EAAE;AAC9D,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,OAAO,CAAC,cAAc,GAAG,MAAM,CAAC,IAAI,EAAE;AAClD,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,OAAO,CAAC,WAAW,GAAG,MAAM,CAAC,IAAI,EAAE;AAC/C,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE;AAC1C,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE;AAC1C,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE;AAC1C,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE;AAC1C,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE;AAC9C,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE;AAC9C,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE;AAC9C,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE;AAC9C,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,OAAO,CAAC,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE;AAChD,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,OAAO,CAAC,yBAAyB,GAAG,MAAM,CAAC,IAAI,EAAE;AAC7D,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,EAAE,EAAE;AACnB,YAAY,OAAO,CAAC,sBAAsB,GAAG,MAAM,CAAC,MAAM,EAAE;AAC5D,YAAY;AACZ,UAAU;AACV,UAAU;AACV,YAAY,MAAM,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC,CAAC;AACpC,YAAY;AACZ;AACA,MAAM;AACN,MAAM,OAAO,OAAO;AACpB,IAAI,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,eAAe,GAAG,SAAS,eAAe,CAAC,MAAM,EAAE;AACnE,MAAM,IAAI,EAAE,MAAM,YAAY,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;AACpE,MAAM,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;AACjD,IAAI,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,MAAM,GAAG,SAAS,MAAM,CAAC,OAAO,EAAE;AAClD,MAAM,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI;AACzD,QAAQ,OAAO,iBAAiB;AAChC,MAAM,IAAI,OAAO,CAAC,KAAK,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE;AACpE,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,OAAO,uBAAuB;AACzE,QAAQ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;AACrD,UAAU,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC/C,YAAY,OAAO,0BAA0B;AAC7C,MAAM;AACN,MAAM,IAAI,OAAO,CAAC,WAAW,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,aAAa,CAAC;AAC9E,QAAQ,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,WAAW,CAAC;AAChD,UAAU,OAAO,8BAA8B;AAC/C,MAAM,IAAI,OAAO,CAAC,WAAW,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,aAAa,CAAC;AAC9E,QAAQ,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,WAAW,CAAC;AAChD,UAAU,OAAO,8BAA8B;AAC/C,MAAM,IAAI,OAAO,CAAC,SAAS,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,WAAW,CAAC;AAC1E,QAAQ,QAAQ,OAAO,CAAC,SAAS;AACjC,UAAU;AACV,YAAY,OAAO,gCAAgC;AACnD,UAAU,KAAK,CAAC;AAChB,UAAU,KAAK,CAAC;AAChB,UAAU,KAAK,CAAC;AAChB,UAAU,KAAK,CAAC;AAChB,YAAY;AACZ;AACA,MAAM,IAAI,OAAO,CAAC,SAAS,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,WAAW,CAAC;AAC1E,QAAQ,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC;AAC/C,UAAU,OAAO,6BAA6B;AAC9C,MAAM,IAAI,OAAO,CAAC,cAAc,IAAI,IAAI;AACxC,UAAU,OAAO,CAAC,cAAc,CAAC,gBAAgB,CAAC,EAAE;AACpD,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC;AAClD,UAAU,OAAO,gCAAgC;AACjD,QAAQ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC,MAAM,EAAE,EAAE,CAAC;AAC9D,UAAU,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;AACxD,YAAY,OAAO,mCAAmC;AACtD,MAAM;AACN,MAAM,IAAI,OAAO,CAAC,kBAAkB,IAAI,IAAI;AAC5C,UAAU,OAAO,CAAC,cAAc,CAAC,oBAAoB,CAAC;AACtD,QAAQ,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,kBAAkB,CAAC;AACxD,UAAU,OAAO,sCAAsC;AACvD,MAAM,IAAI,OAAO,CAAC,yBAAyB,IAAI,IAAI;AACnD,UAAU,OAAO,CAAC,cAAc,CAAC,2BAA2B,CAAC;AAC7D,QAAQ,IAAI,OAAO,OAAO,CAAC,yBAAyB,KAAK,SAAS;AAClE,UAAU,OAAO,6CAA6C;AAC9D,MAAM,IAAI,OAAO,CAAC,6BAA6B,IAAI,IAAI;AACvD,UAAU,OAAO,CAAC,cAAc,CAAC,+BAA+B,CAAC;AACjE,QAAQ,IAAI,OAAO,OAAO,CAAC,6BAA6B,KAAK,QAAQ;AACrE,UAAU,OAAO,gDAAgD;AACjE,MAAM,IAAI,OAAO,CAAC,oCAAoC,IAAI,IAAI;AAC9D,UAAU,OAAO,CAAC,cAAc,CAAC,sCAAsC,CAAC;AACxE,QAAQ,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,oCAAoC,CAAC;AAC1E,YAAY,EAAE,OAAO,CAAC,oCAAoC;AAC1D,cAAc,KAAK,CAAC,SAAS;AAC7B,kBAAkB,OAAO,CAAC,oCAAoC,CAAC,GAAG,CAAC;AACnE,cAAc,KAAK,CAAC,SAAS;AAC7B,kBAAkB,OAAO,CAAC,oCAAoC,CAAC,IAAI,CAAC,CAAC;AACrE,UAAU,OAAO,6DAA6D;AAC9E,MAAM,IAAI,OAAO,CAAC,iBAAiB,IAAI,IAAI;AAC3C,UAAU,OAAO,CAAC,cAAc,CAAC,mBAAmB,CAAC;AACrD,QAAQ,IAAI,OAAO,OAAO,CAAC,iBAAiB,KAAK,QAAQ;AACzD,UAAU,OAAO,oCAAoC;AACrD,MAAM,IAAI,OAAO,CAAC,iBAAiB,IAAI,IAAI;AAC3C,UAAU,OAAO,CAAC,cAAc,CAAC,mBAAmB,CAAC;AACrD,QAAQ,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,iBAAiB,CAAC;AACvD,YAAY,EAAE,OAAO,CAAC,iBAAiB;AACvC,cAAc,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,iBAAiB,CAAC,GAAG,CAAC;AAC5D,cAAc,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;AAC9D,UAAU,OAAO,0CAA0C;AAC3D,MAAM,IAAI,OAAO,CAAC,oBAAoB,IAAI,IAAI;AAC9C,UAAU,OAAO,CAAC,cAAc,CAAC,sBAAsB,CAAC;AACxD,QAAQ,IAAI,OAAO,OAAO,CAAC,oBAAoB,KAAK,SAAS;AAC7D,UAAU,OAAO,wCAAwC;AACzD,MAAM,IAAI,OAAO,CAAC,kBAAkB,IAAI,IAAI;AAC5C,UAAU,OAAO,CAAC,cAAc,CAAC,oBAAoB,CAAC;AACtD,QAAQ,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,kBAAkB,CAAC;AACxD,UAAU,OAAO,sCAAsC;AACvD,MAAM,IAAI,OAAO,CAAC,oBAAoB,IAAI,IAAI;AAC9C,UAAU,OAAO,CAAC,cAAc,CAAC,sBAAsB,CAAC;AACxD,QAAQ,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,oBAAoB,CAAC;AAC1D,UAAU,OAAO,wCAAwC;AACzD,MAAM,IAAI,OAAO,CAAC,qBAAqB,IAAI,IAAI;AAC/C,UAAU,OAAO,CAAC,cAAc,CAAC,uBAAuB,CAAC;AACzD,QAAQ,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,qBAAqB,CAAC;AAC3D,UAAU,OAAO,yCAAyC;AAC1D,MAAM,IAAI,OAAO,CAAC,eAAe,IAAI,IAAI;AACzC,UAAU,OAAO,CAAC,cAAc,CAAC,iBAAiB,CAAC;AACnD,QAAQ,IAAI,OAAO,OAAO,CAAC,eAAe,KAAK,QAAQ;AACvD,UAAU,OAAO,kCAAkC;AACnD,MAAM,IAAI,OAAO,CAAC,iBAAiB,IAAI,IAAI;AAC3C,UAAU,OAAO,CAAC,cAAc,CAAC,mBAAmB,CAAC;AACrD,QAAQ,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,iBAAiB,CAAC;AACvD,UAAU,OAAO,qCAAqC;AACtD,MAAM,IAAI,OAAO,CAAC,UAAU,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,YAAY,CAAC;AAC5E,QAAQ,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,UAAU,CAAC;AAChD,UAAU,OAAO,8BAA8B;AAC/C,MAAM,IAAI,OAAO,CAAC,gBAAgB,IAAI,IAAI;AAC1C,UAAU,OAAO,CAAC,cAAc,CAAC,kBAAkB,CAAC;AACpD,QAAQ,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,gBAAgB,CAAC;AACtD,UAAU,OAAO,oCAAoC;AACrD,MAAM,IAAI,OAAO,CAAC,sBAAsB,IAAI,IAAI;AAChD,UAAU,OAAO,CAAC,cAAc,CAAC,wBAAwB,CAAC;AAC1D,QAAQ,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,sBAAsB,CAAC;AAC5D,UAAU,OAAO,0CAA0C;AAC3D,MAAM,IAAI,OAAO,CAAC,oBAAoB,IAAI,IAAI;AAC9C,UAAU,OAAO,CAAC,cAAc,CAAC,sBAAsB,CAAC;AACxD,QAAQ,IAAI,OAAO,OAAO,CAAC,oBAAoB,KAAK,SAAS;AAC7D,UAAU,OAAO,wCAAwC;AACzD,MAAM,IAAI,OAAO,CAAC,aAAa,IAAI,IAAI;AACvC,UAAU,OAAO,CAAC,cAAc,CAAC,eAAe,CAAC;AACjD,QAAQ,IAAI,OAAO,OAAO,CAAC,aAAa,KAAK,SAAS;AACtD,UAAU,OAAO,iCAAiC;AAClD,MAAM,IAAI,OAAO,CAAC,iBAAiB,IAAI,IAAI;AAC3C,UAAU,OAAO,CAAC,cAAc,CAAC,mBAAmB,CAAC;AACrD,QAAQ,IAAI,OAAO,OAAO,CAAC,iBAAiB,KAAK,SAAS;AAC1D,UAAU,OAAO,qCAAqC;AACtD,MAAM,IAAI,OAAO,CAAC,uBAAuB,IAAI,IAAI;AACjD,UAAU,OAAO,CAAC,cAAc,CAAC,yBAAyB,CAAC;AAC3D,QAAQ,IAAI,OAAO,OAAO,CAAC,uBAAuB,KAAK,SAAS;AAChE,UAAU,OAAO,2CAA2C;AAC5D,MAAM,IAAI,OAAO,CAAC,yBAAyB,IAAI,IAAI;AACnD,UAAU,OAAO,CAAC,cAAc,CAAC,2BAA2B,CAAC;AAC7D,QAAQ,IAAI,OAAO,OAAO,CAAC,yBAAyB,KAAK,SAAS;AAClE,UAAU,OAAO,6CAA6C;AAC9D,MAAM,IAAI,OAAO,CAAC,WAAW,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,aAAa,CAAC;AAC9E,QAAQ,IAAI,OAAO,OAAO,CAAC,WAAW,KAAK,SAAS;AACpD,UAAU,OAAO,+BAA+B;AAChD,MAAM,IAAI,OAAO,CAAC,wBAAwB,IAAI,IAAI;AAClD,UAAU,OAAO,CAAC,cAAc,CAAC,0BAA0B,CAAC;AAC5D,QAAQ,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,wBAAwB,CAAC;AAC7D,UAAU,OAAO,2CAA2C;AAC5D,MAAM,IAAI,OAAO,CAAC,cAAc,IAAI,IAAI;AACxC,UAAU,OAAO,CAAC,cAAc,CAAC,gBAAgB,CAAC,EAAE;AACpD,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC;AAClD,UAAU,OAAO,gCAAgC;AACjD,QAAQ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC,MAAM,EAAE,EAAE,CAAC;AAC9D,UAAU,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;AACxD,YAAY,OAAO,mCAAmC;AACtD,MAAM;AACN,MAAM,IAAI,OAAO,CAAC,kBAAkB,IAAI,IAAI;AAC5C,UAAU,OAAO,CAAC,cAAc,CAAC,oBAAoB,CAAC,EAAE;AACxD,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,kBAAkB,CAAC;AACtD,UAAU,OAAO,oCAAoC;AACrD,QAAQ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,kBAAkB,CAAC,MAAM,EAAE,EAAE,CAAC;AAClE,UAAU,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC;AAC5D,YAAY,OAAO,uCAAuC;AAC1D,MAAM;AACN,MAAM,IAAI,OAAO,CAAC,aAAa,IAAI,IAAI;AACvC,UAAU,OAAO,CAAC,cAAc,CAAC,eAAe,CAAC;AACjD,QAAQ,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,aAAa,CAAC;AAClD,UAAU,OAAO,gCAAgC;AACjD,MAAM,IAAI,OAAO,CAAC,YAAY,IAAI,IAAI;AACtC,UAAU,OAAO,CAAC,cAAc,CAAC,cAAc,CAAC;AAChD,QAAQ,IAAI,OAAO,OAAO,CAAC,YAAY,KAAK,SAAS;AACrD,UAAU,OAAO,gCAAgC;AACjD,MAAM,IAAI,OAAO,CAAC,0BAA0B,IAAI,IAAI;AACpD,UAAU,OAAO,CAAC,cAAc,CAAC,4BAA4B,CAAC;AAC9D,QAAQ,IAAI,OAAO,OAAO,CAAC,0BAA0B,KAAK,SAAS;AACnE,UAAU,OAAO,8CAA8C;AAC/D,MAAM,IAAI,OAAO,CAAC,cAAc,IAAI,IAAI;AACxC,UAAU,OAAO,CAAC,cAAc,CAAC,gBAAgB,CAAC;AAClD,QAAQ,IAAI,OAAO,OAAO,CAAC,cAAc,KAAK,SAAS;AACvD,UAAU,OAAO,kCAAkC;AACnD,MAAM,IAAI,OAAO,CAAC,WAAW,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,aAAa,CAAC;AAC9E,QAAQ,IAAI,OAAO,OAAO,CAAC,WAAW,KAAK,SAAS;AACpD,UAAU,OAAO,+BAA+B;AAChD,MAAM,IAAI,OAAO,CAAC,KAAK,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC;AAClE,QAAQ,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,OAAO,yBAAyB;AAC7E,MAAM,IAAI,OAAO,CAAC,KAAK,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC;AAClE,QAAQ,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,OAAO,yBAAyB;AAC7E,MAAM,IAAI,OAAO,CAAC,KAAK,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC;AAClE,QAAQ,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,OAAO,yBAAyB;AAC7E,MAAM,IAAI,OAAO,CAAC,KAAK,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC;AAClE,QAAQ,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,OAAO,yBAAyB;AAC7E,MAAM,IAAI,OAAO,CAAC,QAAQ,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC;AACxE,QAAQ,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC;AAC7C,UAAU,OAAO,2BAA2B;AAC5C,MAAM,IAAI,OAAO,CAAC,QAAQ,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC;AACxE,QAAQ,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC;AAC7C,UAAU,OAAO,2BAA2B;AAC5C,MAAM,IAAI,OAAO,CAAC,QAAQ,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC;AACxE,QAAQ,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC;AAC7C,UAAU,OAAO,2BAA2B;AAC5C,MAAM,IAAI,OAAO,CAAC,QAAQ,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC;AACxE,QAAQ,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC;AAC7C,UAAU,OAAO,2BAA2B;AAC5C,MAAM,IAAI,OAAO,CAAC,UAAU,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,YAAY,CAAC;AAC5E,QAAQ,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,CAAC;AAC/C,UAAU,OAAO,6BAA6B;AAC9C,MAAM,IAAI,OAAO,CAAC,yBAAyB,IAAI,IAAI;AACnD,UAAU,OAAO,CAAC,cAAc,CAAC,2BAA2B,CAAC;AAC7D,QAAQ,IAAI,OAAO,OAAO,CAAC,yBAAyB,KAAK,SAAS;AAClE,UAAU,OAAO,6CAA6C;AAC9D,MAAM,IAAI,OAAO,CAAC,sBAAsB,IAAI,IAAI;AAChD,UAAU,OAAO,CAAC,cAAc,CAAC,wBAAwB,CAAC;AAC1D,QAAQ,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,sBAAsB,CAAC;AAC3D,UAAU,OAAO,yCAAyC;AAC1D,MAAM,OAAO,IAAI;AACjB,IAAI,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,UAAU,GAAG,SAAS,UAAU,CAAC,MAAM,EAAE;AACzD,MAAM,IAAI,MAAM,YAAY,KAAK,CAAC,aAAa,CAAC,WAAW,EAAE,OAAO,MAAM;AAC1E,MAAM,IAAI,OAAO,GAAG,IAAI,KAAK,CAAC,aAAa,CAAC,WAAW,EAAE;AACzD,MAAM,IAAI,MAAM,CAAC,KAAK,EAAE;AACxB,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;AACxC,UAAU,MAAM,SAAS,CAAC,kDAAkD,CAAC;AAC7E,QAAQ,OAAO,CAAC,KAAK,GAAG,EAAE;AAC1B,QAAQ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;AACpD,UAAU,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACpD,MAAM;AACN,MAAM,IAAI,MAAM,CAAC,WAAW,IAAI,IAAI;AACpC,QAAQ,OAAO,CAAC,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC;AACxD,MAAM,IAAI,MAAM,CAAC,WAAW,IAAI,IAAI;AACpC,QAAQ,OAAO,CAAC,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC;AACxD,MAAM,QAAQ,MAAM,CAAC,SAAS;AAC9B,QAAQ;AACR,UAAU,IAAI,OAAO,MAAM,CAAC,SAAS,KAAK,QAAQ,EAAE;AACpD,YAAY,OAAO,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS;AAChD,YAAY;AACZ,UAAU;AACV,UAAU;AACV,QAAQ,KAAK,SAAS;AACtB,QAAQ,KAAK,CAAC;AACd,UAAU,OAAO,CAAC,SAAS,GAAG,CAAC;AAC/B,UAAU;AACV,QAAQ,KAAK,KAAK;AAClB,QAAQ,KAAK,CAAC;AACd,UAAU,OAAO,CAAC,SAAS,GAAG,CAAC;AAC/B,UAAU;AACV,QAAQ,KAAK,MAAM;AACnB,QAAQ,KAAK,CAAC;AACd,UAAU,OAAO,CAAC,SAAS,GAAG,CAAC;AAC/B,UAAU;AACV,QAAQ,KAAK,MAAM;AACnB,QAAQ,KAAK,CAAC;AACd,UAAU,OAAO,CAAC,SAAS,GAAG,CAAC;AAC/B,UAAU;AACV;AACA,MAAM,IAAI,MAAM,CAAC,SAAS,IAAI,IAAI,EAAE,OAAO,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,GAAG,CAAC;AAC5E,MAAM,IAAI,MAAM,CAAC,cAAc,EAAE;AACjC,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC;AACjD,UAAU,MAAM,SAAS;AACzB,cAAc,2DAA2D,CAAC;AAC1E,QAAQ,OAAO,CAAC,cAAc,GAAG,EAAE;AACnC,QAAQ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,EAAE,CAAC;AAC7D,UAAU,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;AACtE,MAAM;AACN,MAAM,IAAI,MAAM,CAAC,kBAAkB,IAAI,IAAI;AAC3C,QAAQ,OAAO,CAAC,kBAAkB,GAAG,MAAM,CAAC,kBAAkB,GAAG,CAAC;AAClE,MAAM,IAAI,MAAM,CAAC,yBAAyB,IAAI,IAAI;AAClD,QAAQ,OAAO,CAAC,yBAAyB;AACzC,YAAY,OAAO,CAAC,MAAM,CAAC,yBAAyB,CAAC;AACrD,MAAM,IAAI,MAAM,CAAC,6BAA6B,IAAI,IAAI;AACtD,QAAQ,OAAO,CAAC,6BAA6B;AAC7C,YAAY,MAAM,CAAC,MAAM,CAAC,6BAA6B,CAAC;AACxD,MAAM,IAAI,MAAM,CAAC,oCAAoC,IAAI,IAAI;AAC7D,QAAQ,IAAI,KAAK,CAAC,IAAI;AACtB,UAAU,CAAC,OAAO,CAAC,oCAAoC,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS;AAC9E,eAAe,MAAM,CAAC,oCAAoC,CAAC;AAC3D,eAAe,QAAQ,GAAG,IAAI;AAC9B,aAAa;AACb,YAAY,OAAO,MAAM,CAAC,oCAAoC,KAAK,QAAQ;AAC3E,UAAU,OAAO,CAAC,oCAAoC;AACtD,cAAc,QAAQ,CAAC,MAAM,CAAC,oCAAoC,EAAE,EAAE,CAAC;AACvE,aAAa;AACb,YAAY,OAAO,MAAM,CAAC,oCAAoC,KAAK,QAAQ;AAC3E,UAAU,OAAO,CAAC,oCAAoC;AACtD,cAAc,MAAM,CAAC,oCAAoC;AACzD,aAAa;AACb,YAAY,OAAO,MAAM,CAAC,oCAAoC,KAAK,QAAQ;AAC3E,UAAU,OAAO,CAAC,oCAAoC;AACtD,cAAc,IAAI;AAClB,mBAAmB,QAAQ;AAC3B,sBAAsB,MAAM,CAAC,oCAAoC,CAAC,GAAG,KAAK,CAAC;AAC3E,sBAAsB,MAAM,CAAC,oCAAoC,CAAC,IAAI,KAAK,CAAC;AAC5E,mBAAmB,QAAQ,CAAC,IAAI,CAAC;AACjC,MAAM,IAAI,MAAM,CAAC,iBAAiB,IAAI,IAAI;AAC1C,QAAQ,OAAO,CAAC,iBAAiB,GAAG,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC;AACpE,MAAM,IAAI,MAAM,CAAC,iBAAiB,IAAI,IAAI;AAC1C,QAAQ,IAAI,KAAK,CAAC,IAAI;AACtB,UAAU,CAAC,OAAO,CAAC,iBAAiB;AACpC,eAAe,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,iBAAiB,CAAC;AAC7D,eAAe,QAAQ,GAAG,IAAI;AAC9B,aAAa,IAAI,OAAO,MAAM,CAAC,iBAAiB,KAAK,QAAQ;AAC7D,UAAU,OAAO,CAAC,iBAAiB,GAAG,QAAQ,CAAC,MAAM,CAAC,iBAAiB,EAAE,EAAE,CAAC;AAC5E,aAAa,IAAI,OAAO,MAAM,CAAC,iBAAiB,KAAK,QAAQ;AAC7D,UAAU,OAAO,CAAC,iBAAiB,GAAG,MAAM,CAAC,iBAAiB;AAC9D,aAAa,IAAI,OAAO,MAAM,CAAC,iBAAiB,KAAK,QAAQ;AAC7D,UAAU,OAAO,CAAC,iBAAiB;AACnC,cAAc,IAAI;AAClB,mBAAmB,QAAQ;AAC3B,sBAAsB,MAAM,CAAC,iBAAiB,CAAC,GAAG,KAAK,CAAC;AACxD,sBAAsB,MAAM,CAAC,iBAAiB,CAAC,IAAI,KAAK,CAAC;AACzD,mBAAmB,QAAQ,CAAC,IAAI,CAAC;AACjC,MAAM,IAAI,MAAM,CAAC,oBAAoB,IAAI,IAAI;AAC7C,QAAQ,OAAO,CAAC,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,oBAAoB,CAAC;AAC3E,MAAM,IAAI,MAAM,CAAC,kBAAkB,IAAI,IAAI;AAC3C,QAAQ,OAAO,CAAC,kBAAkB,GAAG,MAAM,CAAC,kBAAkB,GAAG,CAAC;AAClE,MAAM,IAAI,MAAM,CAAC,oBAAoB,IAAI,IAAI;AAC7C,QAAQ,OAAO,CAAC,oBAAoB,GAAG,MAAM,CAAC,oBAAoB,GAAG,CAAC;AACtE,MAAM,IAAI,MAAM,CAAC,qBAAqB,IAAI,IAAI;AAC9C,QAAQ,OAAO,CAAC,qBAAqB,GAAG,MAAM,CAAC,qBAAqB,GAAG,CAAC;AACxE,MAAM,IAAI,MAAM,CAAC,eAAe,IAAI,IAAI;AACxC,QAAQ,OAAO,CAAC,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC;AAChE,MAAM,IAAI,MAAM,CAAC,iBAAiB,IAAI,IAAI;AAC1C,QAAQ,OAAO,CAAC,iBAAiB,GAAG,MAAM,CAAC,iBAAiB,GAAG,CAAC;AAChE,MAAM,IAAI,MAAM,CAAC,UAAU,IAAI,IAAI,EAAE,OAAO,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,GAAG,CAAC;AAC/E,MAAM,IAAI,MAAM,CAAC,gBAAgB,IAAI,IAAI;AACzC,QAAQ,OAAO,CAAC,gBAAgB,GAAG,MAAM,CAAC,gBAAgB,GAAG,CAAC;AAC9D,MAAM,IAAI,MAAM,CAAC,sBAAsB,IAAI,IAAI;AAC/C,QAAQ,OAAO,CAAC,sBAAsB,GAAG,MAAM,CAAC,sBAAsB,GAAG,CAAC;AAC1E,MAAM,IAAI,MAAM,CAAC,oBAAoB,IAAI,IAAI;AAC7C,QAAQ,OAAO,CAAC,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,oBAAoB,CAAC;AAC3E,MAAM,IAAI,MAAM,CAAC,aAAa,IAAI,IAAI;AACtC,QAAQ,OAAO,CAAC,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC;AAC7D,MAAM,IAAI,MAAM,CAAC,iBAAiB,IAAI,IAAI;AAC1C,QAAQ,OAAO,CAAC,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAC;AACrE,MAAM,IAAI,MAAM,CAAC,uBAAuB,IAAI,IAAI;AAChD,QAAQ,OAAO,CAAC,uBAAuB;AACvC,YAAY,OAAO,CAAC,MAAM,CAAC,uBAAuB,CAAC;AACnD,MAAM,IAAI,MAAM,CAAC,yBAAyB,IAAI,IAAI;AAClD,QAAQ,OAAO,CAAC,yBAAyB;AACzC,YAAY,OAAO,CAAC,MAAM,CAAC,yBAAyB,CAAC;AACrD,MAAM,IAAI,MAAM,CAAC,WAAW,IAAI,IAAI;AACpC,QAAQ,OAAO,CAAC,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC;AACzD,MAAM,IAAI,MAAM,CAAC,wBAAwB,IAAI,IAAI;AACjD,QAAQ,OAAO,CAAC,wBAAwB;AACxC,YAAY,MAAM,CAAC,MAAM,CAAC,wBAAwB,CAAC;AACnD,MAAM,IAAI,MAAM,CAAC,cAAc,EAAE;AACjC,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC;AACjD,UAAU,MAAM,SAAS;AACzB,cAAc,2DAA2D,CAAC;AAC1E,QAAQ,OAAO,CAAC,cAAc,GAAG,EAAE;AACnC,QAAQ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,EAAE,CAAC;AAC7D,UAAU,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;AACtE,MAAM;AACN,MAAM,IAAI,MAAM,CAAC,kBAAkB,EAAE;AACrC,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAC;AACrD,UAAU,MAAM,SAAS;AACzB,cAAc,+DAA+D,CAAC;AAC9E,QAAQ,OAAO,CAAC,kBAAkB,GAAG,EAAE;AACvC,QAAQ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,kBAAkB,CAAC,MAAM,EAAE,EAAE,CAAC;AACjE,UAAU,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC;AAC9E,MAAM;AACN,MAAM,IAAI,MAAM,CAAC,aAAa,IAAI,IAAI;AACtC,QAAQ,OAAO,CAAC,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC;AAC5D,MAAM,IAAI,MAAM,CAAC,YAAY,IAAI,IAAI;AACrC,QAAQ,OAAO,CAAC,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC;AAC3D,MAAM,IAAI,MAAM,CAAC,0BAA0B,IAAI,IAAI;AACnD,QAAQ,OAAO,CAAC,0BAA0B;AAC1C,YAAY,OAAO,CAAC,MAAM,CAAC,0BAA0B,CAAC;AACtD,MAAM,IAAI,MAAM,CAAC,cAAc,IAAI,IAAI;AACvC,QAAQ,OAAO,CAAC,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC;AAC/D,MAAM,IAAI,MAAM,CAAC,WAAW,IAAI,IAAI;AACpC,QAAQ,OAAO,CAAC,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC;AACzD,MAAM,IAAI,MAAM,CAAC,KAAK,IAAI,IAAI,EAAE,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,GAAG,CAAC;AAChE,MAAM,IAAI,MAAM,CAAC,KAAK,IAAI,IAAI,EAAE,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,GAAG,CAAC;AAChE,MAAM,IAAI,MAAM,CAAC,KAAK,IAAI,IAAI,EAAE,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,GAAG,CAAC;AAChE,MAAM,IAAI,MAAM,CAAC,KAAK,IAAI,IAAI,EAAE,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,GAAG,CAAC;AAChE,MAAM,IAAI,MAAM,CAAC,QAAQ,IAAI,IAAI,EAAE,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC;AAC7E,MAAM,IAAI,MAAM,CAAC,QAAQ,IAAI,IAAI,EAAE,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC;AAC7E,MAAM,IAAI,MAAM,CAAC,QAAQ,IAAI,IAAI,EAAE,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC;AAC7E,MAAM,IAAI,MAAM,CAAC,QAAQ,IAAI,IAAI,EAAE,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC;AAC7E,MAAM,IAAI,MAAM,CAAC,UAAU,IAAI,IAAI;AACnC,QAAQ,OAAO,CAAC,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC;AACtD,MAAM,IAAI,MAAM,CAAC,yBAAyB,IAAI,IAAI;AAClD,QAAQ,OAAO,CAAC,yBAAyB;AACzC,YAAY,OAAO,CAAC,MAAM,CAAC,yBAAyB,CAAC;AACrD,MAAM,IAAI,MAAM,CAAC,sBAAsB,IAAI,IAAI;AAC/C,QAAQ,OAAO,CAAC,sBAAsB,GAAG,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC;AAC9E,MAAM,OAAO,OAAO;AACpB,IAAI,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,QAAQ,GAAG,SAAS,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE;AAC/D,MAAM,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,EAAE;AAChC,MAAM,IAAI,MAAM,GAAG,EAAE;AACrB,MAAM,IAAI,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,QAAQ,EAAE;AAC9C,QAAQ,MAAM,CAAC,KAAK,GAAG,EAAE;AACzB,QAAQ,MAAM,CAAC,cAAc,GAAG,EAAE;AAClC,QAAQ,MAAM,CAAC,cAAc,GAAG,EAAE;AAClC,QAAQ,MAAM,CAAC,kBAAkB,GAAG,EAAE;AACtC,MAAM;AACN,MAAM,IAAI,OAAO,CAAC,QAAQ,EAAE;AAC5B,QAAQ,MAAM,CAAC,WAAW,GAAG,EAAE;AAC/B,QAAQ,MAAM,CAAC,SAAS,GAAG,OAAO,CAAC,KAAK,KAAK,MAAM,GAAG,SAAS,GAAG,CAAC;AACnE,QAAQ,MAAM,CAAC,SAAS,GAAG,IAAI;AAC/B,QAAQ,MAAM,CAAC,kBAAkB,GAAG,CAAC;AACrC,QAAQ,MAAM,CAAC,WAAW,GAAG,EAAE;AAC/B,QAAQ,MAAM,CAAC,iBAAiB,GAAG,MAAM;AACzC,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE;AACxB,UAAU,IAAI,IAAI,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC;AAC/C,UAAU,MAAM,CAAC,iBAAiB,GAAG,OAAO,CAAC,KAAK,KAAK,MAAM;AAC7D,cAAc,IAAI,CAAC,QAAQ,EAAE;AAC7B,cAAc,OAAO,CAAC,KAAK,KAAK,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAE;AACxD,yCAAyC,IAAI;AAC7C,QAAQ,CAAC;AACT,UAAU,MAAM,CAAC,iBAAiB,GAAG,OAAO,CAAC,KAAK,KAAK,MAAM,GAAG,GAAG,GAAG,CAAC;AACvE,QAAQ,MAAM,CAAC,kBAAkB,GAAG,CAAC;AACrC,QAAQ,MAAM,CAAC,oBAAoB,GAAG,CAAC;AACvC,QAAQ,MAAM,CAAC,qBAAqB,GAAG,OAAO;AAC9C,QAAQ,MAAM,CAAC,eAAe,GAAG,IAAI;AACrC,QAAQ,MAAM,CAAC,UAAU,GAAG,EAAE;AAC9B,QAAQ,MAAM,CAAC,gBAAgB,GAAG,CAAC;AACnC,QAAQ,MAAM,CAAC,iBAAiB,GAAG,IAAI;AACvC,QAAQ,MAAM,CAAC,oBAAoB,GAAG,IAAI;AAC1C,QAAQ,MAAM,CAAC,sBAAsB,GAAG,EAAE;AAC1C,QAAQ,MAAM,CAAC,oBAAoB,GAAG,IAAI;AAC1C,QAAQ,MAAM,CAAC,iBAAiB,GAAG,IAAI;AACvC,QAAQ,MAAM,CAAC,aAAa,GAAG,IAAI;AACnC,QAAQ,MAAM,CAAC,uBAAuB,GAAG,KAAK;AAC9C,QAAQ,MAAM,CAAC,WAAW,GAAG,KAAK;AAClC,QAAQ,MAAM,CAAC,yBAAyB,GAAG,KAAK;AAChD,QAAQ,MAAM,CAAC,0BAA0B,GAAG,IAAI;AAChD,QAAQ,MAAM,CAAC,cAAc,GAAG,IAAI;AACpC,QAAQ,MAAM,CAAC,WAAW,GAAG,KAAK;AAClC,QAAQ,MAAM,CAAC,YAAY,GAAG,KAAK;AACnC,QAAQ,MAAM,CAAC,aAAa,GAAG,EAAE;AACjC,QAAQ,MAAM,CAAC,KAAK,GAAG,CAAC;AACxB,QAAQ,MAAM,CAAC,KAAK,GAAG,CAAC;AACxB,QAAQ,MAAM,CAAC,KAAK,GAAG,CAAC;AACxB,QAAQ,MAAM,CAAC,KAAK,GAAG,EAAE;AACzB,QAAQ,MAAM,CAAC,UAAU,GAAG,UAAU;AACtC,QAAQ,MAAM,CAAC,QAAQ,GAAG,OAAO;AACjC,QAAQ,MAAM,CAAC,QAAQ,GAAG,KAAK;AAC/B,QAAQ,MAAM,CAAC,QAAQ,GAAG,MAAM;AAChC,QAAQ,MAAM,CAAC,QAAQ,GAAG,OAAO;AACjC,QAAQ,MAAM,CAAC,yBAAyB,GAAG,KAAK;AAChD,QAAQ,MAAM,CAAC,yBAAyB,GAAG,KAAK;AAChD,QAAQ,MAAM,CAAC,6BAA6B,GAAG,CAAC;AAChD,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE;AACxB,UAAU,IAAI,IAAI,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC;AAC/C,UAAU,MAAM,CAAC,oCAAoC;AACrD,cAAc,OAAO,CAAC,KAAK,KAAK,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAE;AACxD,cAAc,OAAO,CAAC,KAAK,KAAK,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAE;AACxD,yCAAyC,IAAI;AAC7C,QAAQ,CAAC;AACT,UAAU,MAAM,CAAC,oCAAoC;AACrD,cAAc,OAAO,CAAC,KAAK,KAAK,MAAM,GAAG,GAAG,GAAG,CAAC;AAChD,QAAQ,MAAM,CAAC,wBAAwB,GAAG,EAAE;AAC5C,QAAQ,MAAM,CAAC,sBAAsB,GAAG,EAAE;AAC1C,MAAM;AACN,MAAM,IAAI,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE;AACjD,QAAQ,MAAM,CAAC,KAAK,GAAG,EAAE;AACzB,QAAQ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;AACrD,UAAU,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;AAC5C,MAAM;AACN,MAAM,IAAI,OAAO,CAAC,WAAW,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,aAAa,CAAC;AAC9E,QAAQ,MAAM,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW;AAChD,MAAM,IAAI,OAAO,CAAC,SAAS,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,WAAW,CAAC;AAC1E,QAAQ,MAAM,CAAC,SAAS,GAAG,OAAO,CAAC,KAAK,KAAK,MAAM;AACnD,YAAY,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC;AACxE,oBAAoB,SAAS;AAC7B,YAAY,OAAO,CAAC,SAAS;AAC7B,YAAY,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC;AACxE,YAAY,OAAO,CAAC,SAAS;AAC7B,MAAM,IAAI,OAAO,CAAC,SAAS,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,WAAW,CAAC;AAC1E,QAAQ,MAAM,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS;AAC5C,MAAM,IAAI,OAAO,CAAC,cAAc,IAAI,OAAO,CAAC,cAAc,CAAC,MAAM,EAAE;AACnE,QAAQ,MAAM,CAAC,cAAc,GAAG,EAAE;AAClC,QAAQ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC,MAAM,EAAE,EAAE,CAAC;AAC9D,UAAU,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC;AAC9D,MAAM;AACN,MAAM,IAAI,OAAO,CAAC,kBAAkB,IAAI,IAAI;AAC5C,UAAU,OAAO,CAAC,cAAc,CAAC,oBAAoB,CAAC;AACtD,QAAQ,MAAM,CAAC,kBAAkB,GAAG,OAAO,CAAC,kBAAkB;AAC9D,MAAM,IAAI,OAAO,CAAC,WAAW,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,aAAa,CAAC;AAC9E,QAAQ,MAAM,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW;AAChD,MAAM,IAAI,OAAO,CAAC,iBAAiB,IAAI,IAAI;AAC3C,UAAU,OAAO,CAAC,cAAc,CAAC,mBAAmB,CAAC;AACrD,QAAQ,MAAM,CAAC,iBAAiB;AAChC,YAAY,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,iBAAiB,CAAC;AAChE,YAAY,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC;AAC7C,YAAY,OAAO,CAAC,iBAAiB;AACrC,MAAM,IAAI,OAAO,CAAC,iBAAiB,IAAI,IAAI;AAC3C,UAAU,OAAO,CAAC,cAAc,CAAC,mBAAmB,CAAC;AACrD,QAAQ,IAAI,OAAO,OAAO,CAAC,iBAAiB,KAAK,QAAQ;AACzD,UAAU,MAAM,CAAC,iBAAiB,GAAG,OAAO,CAAC,KAAK,KAAK,MAAM;AAC7D,cAAc,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC;AAC/C,cAAc,OAAO,CAAC,iBAAiB;AACvC;AACA,UAAU,MAAM,CAAC,iBAAiB,GAAG,OAAO,CAAC,KAAK,KAAK,MAAM;AAC7D,cAAc,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC;AAC3E,cAAc,OAAO,CAAC,KAAK,KAAK,MAAM;AACtC,cAAc,IAAI;AAClB,mBAAmB,QAAQ;AAC3B,sBAAsB,OAAO,CAAC,iBAAiB,CAAC,GAAG,KAAK,CAAC;AACzD,sBAAsB,OAAO,CAAC,iBAAiB,CAAC,IAAI,KAAK,CAAC;AAC1D,mBAAmB,QAAQ,CAAC,IAAI,CAAC;AACjC,cAAc,OAAO,CAAC,iBAAiB;AACvC,MAAM,IAAI,OAAO,CAAC,kBAAkB,IAAI,IAAI;AAC5C,UAAU,OAAO,CAAC,cAAc,CAAC,oBAAoB,CAAC;AACtD,QAAQ,MAAM,CAAC,kBAAkB,GAAG,OAAO,CAAC,kBAAkB;AAC9D,MAAM,IAAI,OAAO,CAAC,oBAAoB,IAAI,IAAI;AAC9C,UAAU,OAAO,CAAC,cAAc,CAAC,sBAAsB,CAAC;AACxD,QAAQ,MAAM,CAAC,oBAAoB,GAAG,OAAO,CAAC,oBAAoB;AAClE,MAAM,IAAI,OAAO,CAAC,qBAAqB,IAAI,IAAI;AAC/C,UAAU,OAAO,CAAC,cAAc,CAAC,uBAAuB,CAAC;AACzD,QAAQ,MAAM,CAAC,qBAAqB,GAAG,OAAO,CAAC,qBAAqB;AACpE,MAAM,IAAI,OAAO,CAAC,eAAe,IAAI,IAAI;AACzC,UAAU,OAAO,CAAC,cAAc,CAAC,iBAAiB,CAAC;AACnD,QAAQ,MAAM,CAAC,eAAe;AAC9B,YAAY,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,eAAe,CAAC;AAC9D,YAAY,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC;AAC3C,YAAY,OAAO,CAAC,eAAe;AACnC,MAAM,IAAI,OAAO,CAAC,UAAU,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,YAAY,CAAC;AAC5E,QAAQ,MAAM,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU;AAC9C,MAAM,IAAI,OAAO,CAAC,gBAAgB,IAAI,IAAI;AAC1C,UAAU,OAAO,CAAC,cAAc,CAAC,kBAAkB,CAAC;AACpD,QAAQ,MAAM,CAAC,gBAAgB,GAAG,OAAO,CAAC,gBAAgB;AAC1D,MAAM,IAAI,OAAO,CAAC,iBAAiB,IAAI,IAAI;AAC3C,UAAU,OAAO,CAAC,cAAc,CAAC,mBAAmB,CAAC;AACrD,QAAQ,MAAM,CAAC,iBAAiB,GAAG,OAAO,CAAC,iBAAiB;AAC5D,MAAM,IAAI,OAAO,CAAC,oBAAoB,IAAI,IAAI;AAC9C,UAAU,OAAO,CAAC,cAAc,CAAC,sBAAsB,CAAC;AACxD,QAAQ,MAAM,CAAC,oBAAoB,GAAG,OAAO,CAAC,oBAAoB;AAClE,MAAM,IAAI,OAAO,CAAC,sBAAsB,IAAI,IAAI;AAChD,UAAU,OAAO,CAAC,cAAc,CAAC,wBAAwB,CAAC;AAC1D,QAAQ,MAAM,CAAC,sBAAsB,GAAG,OAAO,CAAC,sBAAsB;AACtE,MAAM,IAAI,OAAO,CAAC,oBAAoB,IAAI,IAAI;AAC9C,UAAU,OAAO,CAAC,cAAc,CAAC,sBAAsB,CAAC;AACxD,QAAQ,MAAM,CAAC,oBAAoB,GAAG,OAAO,CAAC,oBAAoB;AAClE,MAAM,IAAI,OAAO,CAAC,iBAAiB,IAAI,IAAI;AAC3C,UAAU,OAAO,CAAC,cAAc,CAAC,mBAAmB,CAAC;AACrD,QAAQ,MAAM,CAAC,iBAAiB,GAAG,OAAO,CAAC,iBAAiB;AAC5D,MAAM,IAAI,OAAO,CAAC,aAAa,IAAI,IAAI;AACvC,UAAU,OAAO,CAAC,cAAc,CAAC,eAAe,CAAC;AACjD,QAAQ,MAAM,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa;AACpD,MAAM,IAAI,OAAO,CAAC,uBAAuB,IAAI,IAAI;AACjD,UAAU,OAAO,CAAC,cAAc,CAAC,yBAAyB,CAAC;AAC3D,QAAQ,MAAM,CAAC,uBAAuB,GAAG,OAAO,CAAC,uBAAuB;AACxE,MAAM,IAAI,OAAO,CAAC,WAAW,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,aAAa,CAAC;AAC9E,QAAQ,MAAM,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW;AAChD,MAAM,IAAI,OAAO,CAAC,yBAAyB,IAAI,IAAI;AACnD,UAAU,OAAO,CAAC,cAAc,CAAC,2BAA2B,CAAC;AAC7D,QAAQ,MAAM,CAAC,yBAAyB,GAAG,OAAO,CAAC,yBAAyB;AAC5E,MAAM,IAAI,OAAO,CAAC,cAAc,IAAI,OAAO,CAAC,cAAc,CAAC,MAAM,EAAE;AACnE,QAAQ,MAAM,CAAC,cAAc,GAAG,EAAE;AAClC,QAAQ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC,MAAM,EAAE,EAAE,CAAC;AAC9D,UAAU,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC;AAC9D,MAAM;AACN,MAAM,IAAI,OAAO,CAAC,kBAAkB,IAAI,OAAO,CAAC,kBAAkB,CAAC,MAAM,EAAE;AAC3E,QAAQ,MAAM,CAAC,kBAAkB,GAAG,EAAE;AACtC,QAAQ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,kBAAkB,CAAC,MAAM,EAAE,EAAE,CAAC;AAClE,UAAU,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC;AACtE,MAAM;AACN,MAAM,IAAI,OAAO,CAAC,0BAA0B,IAAI,IAAI;AACpD,UAAU,OAAO,CAAC,cAAc,CAAC,4BAA4B,CAAC;AAC9D,QAAQ,MAAM,CAAC,0BAA0B,GAAG,OAAO,CAAC,0BAA0B;AAC9E,MAAM,IAAI,OAAO,CAAC,cAAc,IAAI,IAAI;AACxC,UAAU,OAAO,CAAC,cAAc,CAAC,gBAAgB,CAAC;AAClD,QAAQ,MAAM,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc;AACtD,MAAM,IAAI,OAAO,CAAC,WAAW,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,aAAa,CAAC;AAC9E,QAAQ,MAAM,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW;AAChD,MAAM,IAAI,OAAO,CAAC,YAAY,IAAI,IAAI;AACtC,UAAU,OAAO,CAAC,cAAc,CAAC,cAAc,CAAC;AAChD,QAAQ,MAAM,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY;AAClD,MAAM,IAAI,OAAO,CAAC,aAAa,IAAI,IAAI;AACvC,UAAU,OAAO,CAAC,cAAc,CAAC,eAAe,CAAC;AACjD,QAAQ,MAAM,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa;AACpD,MAAM,IAAI,OAAO,CAAC,KAAK,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC;AAClE,QAAQ,MAAM,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK;AACpC,MAAM,IAAI,OAAO,CAAC,KAAK,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC;AAClE,QAAQ,MAAM,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK;AACpC,MAAM,IAAI,OAAO,CAAC,KAAK,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC;AAClE,QAAQ,MAAM,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK;AACpC,MAAM,IAAI,OAAO,CAAC,KAAK,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC;AAClE,QAAQ,MAAM,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK;AACpC,MAAM,IAAI,OAAO,CAAC,UAAU,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,YAAY,CAAC;AAC5E,QAAQ,MAAM,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU;AAC9C,MAAM,IAAI,OAAO,CAAC,QAAQ,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC;AACxE,QAAQ,MAAM,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ;AAC1C,MAAM,IAAI,OAAO,CAAC,QAAQ,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC;AACxE,QAAQ,MAAM,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ;AAC1C,MAAM,IAAI,OAAO,CAAC,QAAQ,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC;AACxE,QAAQ,MAAM,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ;AAC1C,MAAM,IAAI,OAAO,CAAC,QAAQ,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC;AACxE,QAAQ,MAAM,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ;AAC1C,MAAM,IAAI,OAAO,CAAC,yBAAyB,IAAI,IAAI;AACnD,UAAU,OAAO,CAAC,cAAc,CAAC,2BAA2B,CAAC;AAC7D,QAAQ,MAAM,CAAC,yBAAyB,GAAG,OAAO,CAAC,yBAAyB;AAC5E,MAAM,IAAI,OAAO,CAAC,yBAAyB,IAAI,IAAI;AACnD,UAAU,OAAO,CAAC,cAAc,CAAC,2BAA2B,CAAC;AAC7D,QAAQ,MAAM,CAAC,yBAAyB,GAAG,OAAO,CAAC,yBAAyB;AAC5E,MAAM,IAAI,OAAO,CAAC,6BAA6B,IAAI,IAAI;AACvD,UAAU,OAAO,CAAC,cAAc,CAAC,+BAA+B,CAAC;AACjE,QAAQ,MAAM,CAAC,6BAA6B;AAC5C,YAAY,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,6BAA6B,CAAC;AAC5E,YAAY,MAAM,CAAC,OAAO,CAAC,6BAA6B,CAAC;AACzD,YAAY,OAAO,CAAC,6BAA6B;AACjD,MAAM,IAAI,OAAO,CAAC,oCAAoC,IAAI,IAAI;AAC9D,UAAU,OAAO,CAAC,cAAc,CAAC,sCAAsC,CAAC;AACxE,QAAQ,IAAI,OAAO,OAAO,CAAC,oCAAoC,KAAK,QAAQ;AAC5E,UAAU,MAAM,CAAC,oCAAoC;AACrD,cAAc,OAAO,CAAC,KAAK,KAAK,MAAM;AACtC,cAAc,MAAM,CAAC,OAAO,CAAC,oCAAoC,CAAC;AAClE,cAAc,OAAO,CAAC,oCAAoC;AAC1D;AACA,UAAU,MAAM,CAAC,oCAAoC;AACrD,cAAc,OAAO,CAAC,KAAK,KAAK,MAAM;AACtC,cAAc,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI;AAChD,kBAAkB,OAAO,CAAC,oCAAoC,CAAC;AAC/D,cAAc,OAAO,CAAC,KAAK,KAAK,MAAM;AACtC,cAAc,IAAI;AAClB,mBAAmB,QAAQ;AAC3B,sBAAsB,OAAO,CAAC,oCAAoC,CAAC,GAAG,KAAK,CAAC;AAC5E,sBAAsB,OAAO,CAAC,oCAAoC,CAAC,IAAI,KAAK,CAAC;AAC7E,mBAAmB,QAAQ,CAAC,IAAI,CAAC;AACjC,cAAc,OAAO,CAAC,oCAAoC;AAC1D,MAAM,IAAI,OAAO,CAAC,wBAAwB,IAAI,IAAI;AAClD,UAAU,OAAO,CAAC,cAAc,CAAC,0BAA0B,CAAC;AAC5D,QAAQ,MAAM,CAAC,wBAAwB,GAAG,OAAO,CAAC,wBAAwB;AAC1E,MAAM,IAAI,OAAO,CAAC,sBAAsB,IAAI,IAAI;AAChD,UAAU,OAAO,CAAC,cAAc,CAAC,wBAAwB,CAAC;AAC1D,QAAQ,MAAM,CAAC,sBAAsB,GAAG,OAAO,CAAC,sBAAsB;AACtE,MAAM,OAAO,MAAM;AACnB,IAAI,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,CAAC,MAAM,GAAG,SAAS,MAAM,GAAG;AACrD,MAAM,OAAO,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC;AAC1E,IAAI,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,UAAU,GAAG,SAAS,UAAU,CAAC,aAAa,EAAE;AAChE,MAAM,IAAI,aAAa,KAAK,SAAS,EAAE;AACvC,QAAQ,aAAa,GAAG,qBAAqB;AAC7C,MAAM;AACN,MAAM,OAAO,aAAa,GAAG,4BAA4B;AACzD,IAAI,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,SAAS,GAAG,CAAC,WAAW;AACxC,MAAM,MAAM,UAAU,GAAG,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC;AAC/D,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,GAAG,CAAC;AAC3C,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC;AACvC,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC;AACxC,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC;AACxC,MAAM,OAAO,MAAM;AACnB,IAAI,CAAC,GAAG;;AAER,IAAI,OAAO,WAAW;AACtB,EAAE,CAAC,GAAG;;AAEN,EAAE,aAAa,CAAC,cAAc,GAAG,CAAC,WAAW;AAC7C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,SAAS,cAAc,CAAC,UAAU,EAAE;AACxC,MAAM,IAAI,UAAU;AACpB,QAAQ,KAAK,IAAI,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;AAC5E,UAAU,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC9E,IAAI;;AAEJ;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,cAAc,CAAC,SAAS,CAAC,IAAI,GAAG,EAAE;;AAEtC;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,cAAc,CAAC,SAAS,CAAC,mBAAmB,GAAG,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;;AAEtE;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,cAAc,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI;;AAElD;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,cAAc,CAAC,SAAS,CAAC,sBAAsB,GAAG,IAAI;;AAE1D;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,cAAc,CAAC,SAAS,CAAC,iBAAiB,GAAG,IAAI;;AAErD;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,cAAc,CAAC,SAAS,CAAC,oBAAoB,GAAG,EAAE;;AAEtD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,cAAc,CAAC,MAAM,GAAG,SAAS,MAAM,CAAC,UAAU,EAAE;AACxD,MAAM,OAAO,IAAI,cAAc,CAAC,UAAU,CAAC;AAC3C,IAAI,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,cAAc,CAAC,MAAM,GAAG,SAAS,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE;AAC7D,MAAM,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE;AAC5C,MAAM,IAAI,OAAO,CAAC,IAAI,IAAI,IAAI,IAAI,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC;AAC7E,QAAQ,MAAM,CAAC,MAAM,yBAAyB,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;AACtE,MAAM,IAAI,OAAO,CAAC,mBAAmB,IAAI,IAAI;AAC7C,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,qBAAqB,CAAC;AACpE,QAAQ,MAAM,CAAC,MAAM,yBAAyB,EAAE;AAChD,aAAa,KAAK,CAAC,OAAO,CAAC,mBAAmB,CAAC;AAC/C,MAAM,IAAI,OAAO,CAAC,cAAc,IAAI,IAAI;AACxC,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,gBAAgB,CAAC;AAC/D,QAAQ,MAAM,CAAC,MAAM,yBAAyB,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC;AAC9E,MAAM,IAAI,OAAO,CAAC,sBAAsB,IAAI,IAAI;AAChD,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,wBAAwB,CAAC;AACvE,QAAQ,MAAM,CAAC,MAAM,yBAAyB,EAAE;AAChD,aAAa,IAAI,CAAC,OAAO,CAAC,sBAAsB,CAAC;AACjD,MAAM,IAAI,OAAO,CAAC,iBAAiB,IAAI,IAAI;AAC3C,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,mBAAmB,CAAC;AAClE,QAAQ,MAAM,CAAC,MAAM,yBAAyB,EAAE;AAChD,aAAa,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC;AAC5C,MAAM,IAAI,OAAO,CAAC,oBAAoB,IAAI,IAAI;AAC9C,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,sBAAsB,CAAC;AACrE,QAAQ,MAAM,CAAC,MAAM,yBAAyB,EAAE;AAChD,aAAa,MAAM,CAAC,OAAO,CAAC,oBAAoB,CAAC;AACjD,MAAM,OAAO,MAAM;AACnB,IAAI,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,cAAc,CAAC,eAAe,GAAG,SAAS,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE;AAC/E,MAAM,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,MAAM,EAAE;AAClD,IAAI,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,cAAc,CAAC,MAAM,GAAG,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE;AACnE,MAAM,IAAI,EAAE,MAAM,YAAY,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC;AACvE,MAAM,IAAI,GAAG,GAAG,MAAM,KAAK,SAAS,GAAG,MAAM,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,GAAG,MAAM;AACvE,UAAU,OAAO,GAAG,IAAI,KAAK,CAAC,aAAa,CAAC,cAAc,EAAE;AAC5D,MAAM,OAAO,MAAM,CAAC,GAAG,GAAG,GAAG,EAAE;AAC/B,QAAQ,IAAI,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE;AACjC,QAAQ,IAAI,GAAG,KAAK,KAAK,EAAE;AAC3B,QAAQ,QAAQ,GAAG,KAAK,CAAC;AACzB,UAAU,KAAK,CAAC,EAAE;AAClB,YAAY,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE;AAC1C,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,CAAC,EAAE;AAClB,YAAY,OAAO,CAAC,mBAAmB,GAAG,MAAM,CAAC,KAAK,EAAE;AACxD,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,CAAC,EAAE;AAClB,YAAY,OAAO,CAAC,cAAc,GAAG,MAAM,CAAC,IAAI,EAAE;AAClD,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,CAAC,EAAE;AAClB,YAAY,OAAO,CAAC,sBAAsB,GAAG,MAAM,CAAC,IAAI,EAAE;AAC1D,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,CAAC,EAAE;AAClB,YAAY,OAAO,CAAC,iBAAiB,GAAG,MAAM,CAAC,IAAI,EAAE;AACrD,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,CAAC,EAAE;AAClB,YAAY,OAAO,CAAC,oBAAoB,GAAG,MAAM,CAAC,MAAM,EAAE;AAC1D,YAAY;AACZ,UAAU;AACV,UAAU;AACV,YAAY,MAAM,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC,CAAC;AACpC,YAAY;AACZ;AACA,MAAM;AACN,MAAM,OAAO,OAAO;AACpB,IAAI,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,cAAc,CAAC,eAAe,GAAG,SAAS,eAAe,CAAC,MAAM,EAAE;AACtE,MAAM,IAAI,EAAE,MAAM,YAAY,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;AACpE,MAAM,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;AACjD,IAAI,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,cAAc,CAAC,MAAM,GAAG,SAAS,MAAM,CAAC,OAAO,EAAE;AACrD,MAAM,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI;AACzD,QAAQ,OAAO,iBAAiB;AAChC,MAAM,IAAI,OAAO,CAAC,IAAI,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC;AAChE,QAAQ,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,uBAAuB;AACzE,MAAM,IAAI,OAAO,CAAC,mBAAmB,IAAI,IAAI;AAC7C,UAAU,OAAO,CAAC,cAAc,CAAC,qBAAqB,CAAC;AACvD,QAAQ,IAAI,EAAE,OAAO,CAAC,mBAAmB;AACzC,kBAAkB,OAAO,OAAO,CAAC,mBAAmB,CAAC,MAAM,KAAK,QAAQ;AACxE,cAAc,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;AAC1D,UAAU,OAAO,sCAAsC;AACvD,MAAM,IAAI,OAAO,CAAC,cAAc,IAAI,IAAI;AACxC,UAAU,OAAO,CAAC,cAAc,CAAC,gBAAgB,CAAC;AAClD,QAAQ,IAAI,OAAO,OAAO,CAAC,cAAc,KAAK,SAAS;AACvD,UAAU,OAAO,kCAAkC;AACnD,MAAM,IAAI,OAAO,CAAC,sBAAsB,IAAI,IAAI;AAChD,UAAU,OAAO,CAAC,cAAc,CAAC,wBAAwB,CAAC;AAC1D,QAAQ,IAAI,OAAO,OAAO,CAAC,sBAAsB,KAAK,SAAS;AAC/D,UAAU,OAAO,0CAA0C;AAC3D,MAAM,IAAI,OAAO,CAAC,iBAAiB,IAAI,IAAI;AAC3C,UAAU,OAAO,CAAC,cAAc,CAAC,mBAAmB,CAAC;AACrD,QAAQ,IAAI,OAAO,OAAO,CAAC,iBAAiB,KAAK,SAAS;AAC1D,UAAU,OAAO,qCAAqC;AACtD,MAAM,IAAI,OAAO,CAAC,oBAAoB,IAAI,IAAI;AAC9C,UAAU,OAAO,CAAC,cAAc,CAAC,sBAAsB,CAAC;AACxD,QAAQ,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,oBAAoB,CAAC;AACzD,UAAU,OAAO,uCAAuC;AACxD,MAAM,OAAO,IAAI;AACjB,IAAI,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,cAAc,CAAC,UAAU,GAAG,SAAS,UAAU,CAAC,MAAM,EAAE;AAC5D,MAAM,IAAI,MAAM,YAAY,KAAK,CAAC,aAAa,CAAC,cAAc,EAAE,OAAO,MAAM;AAC7E,MAAM,IAAI,OAAO,GAAG,IAAI,KAAK,CAAC,aAAa,CAAC,cAAc,EAAE;AAC5D,MAAM,IAAI,MAAM,CAAC,IAAI,IAAI,IAAI,EAAE,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;AACjE,MAAM,IAAI,MAAM,CAAC,mBAAmB,IAAI,IAAI;AAC5C,QAAQ,IAAI,OAAO,MAAM,CAAC,mBAAmB,KAAK,QAAQ;AAC1D,UAAU,KAAK,CAAC,MAAM,CAAC,MAAM;AAC7B,cAAc,MAAM,CAAC,mBAAmB;AACxC,cAAc,OAAO,CAAC,mBAAmB,GAAG,KAAK,CAAC,SAAS;AAC3D,kBAAkB,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;AAClE,cAAc,CAAC,CAAC;AAChB,aAAa,IAAI,MAAM,CAAC,mBAAmB,CAAC,MAAM,IAAI,CAAC;AACvD,UAAU,OAAO,CAAC,mBAAmB,GAAG,MAAM,CAAC,mBAAmB;AAClE,MAAM,IAAI,MAAM,CAAC,cAAc,IAAI,IAAI;AACvC,QAAQ,OAAO,CAAC,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC;AAC/D,MAAM,IAAI,MAAM,CAAC,sBAAsB,IAAI,IAAI;AAC/C,QAAQ,OAAO,CAAC,sBAAsB,GAAG,OAAO,CAAC,MAAM,CAAC,sBAAsB,CAAC;AAC/E,MAAM,IAAI,MAAM,CAAC,iBAAiB,IAAI,IAAI;AAC1C,QAAQ,OAAO,CAAC,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAC;AACrE,MAAM,IAAI,MAAM,CAAC,oBAAoB,IAAI,IAAI;AAC7C,QAAQ,OAAO,CAAC,oBAAoB,GAAG,MAAM,CAAC,MAAM,CAAC,oBAAoB,CAAC;AAC1E,MAAM,OAAO,OAAO;AACpB,IAAI,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,cAAc,CAAC,QAAQ,GAAG,SAAS,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE;AAClE,MAAM,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,EAAE;AAChC,MAAM,IAAI,MAAM,GAAG,EAAE;AACrB,MAAM,IAAI,OAAO,CAAC,QAAQ,EAAE;AAC5B,QAAQ,MAAM,CAAC,IAAI,GAAG,EAAE;AACxB,QAAQ,IAAI,OAAO,CAAC,KAAK,KAAK,MAAM;AACpC,UAAU,MAAM,CAAC,mBAAmB,GAAG,EAAE;AACzC,aAAa;AACb,UAAU,MAAM,CAAC,mBAAmB,GAAG,EAAE;AACzC,UAAU,IAAI,OAAO,CAAC,KAAK,KAAK,KAAK;AACrC,YAAY,MAAM,CAAC,mBAAmB;AACtC,gBAAgB,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,mBAAmB,CAAC;AAC3D,QAAQ;AACR,QAAQ,MAAM,CAAC,cAAc,GAAG,IAAI;AACpC,QAAQ,MAAM,CAAC,sBAAsB,GAAG,IAAI;AAC5C,QAAQ,MAAM,CAAC,iBAAiB,GAAG,IAAI;AACvC,QAAQ,MAAM,CAAC,oBAAoB,GAAG,EAAE;AACxC,MAAM;AACN,MAAM,IAAI,OAAO,CAAC,IAAI,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC;AAChE,QAAQ,MAAM,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI;AAClC,MAAM,IAAI,OAAO,CAAC,mBAAmB,IAAI,IAAI;AAC7C,UAAU,OAAO,CAAC,cAAc,CAAC,qBAAqB,CAAC;AACvD,QAAQ,MAAM,CAAC,mBAAmB,GAAG,OAAO,CAAC,KAAK,KAAK,MAAM;AAC7D,YAAY,KAAK,CAAC,MAAM,CAAC,MAAM;AAC/B,gBAAgB,OAAO,CAAC,mBAAmB,EAAE,CAAC;AAC9C,gBAAgB,OAAO,CAAC,mBAAmB,CAAC,MAAM,CAAC;AACnD,YAAY,OAAO,CAAC,KAAK,KAAK,KAAK;AACnC,YAAY,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,mBAAmB,CAAC;AACnE,YAAY,OAAO,CAAC,mBAAmB;AACvC,MAAM,IAAI,OAAO,CAAC,cAAc,IAAI,IAAI;AACxC,UAAU,OAAO,CAAC,cAAc,CAAC,gBAAgB,CAAC;AAClD,QAAQ,MAAM,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc;AACtD,MAAM,IAAI,OAAO,CAAC,sBAAsB,IAAI,IAAI;AAChD,UAAU,OAAO,CAAC,cAAc,CAAC,wBAAwB,CAAC;AAC1D,QAAQ,MAAM,CAAC,sBAAsB,GAAG,OAAO,CAAC,sBAAsB;AACtE,MAAM,IAAI,OAAO,CAAC,iBAAiB,IAAI,IAAI;AAC3C,UAAU,OAAO,CAAC,cAAc,CAAC,mBAAmB,CAAC;AACrD,QAAQ,MAAM,CAAC,iBAAiB,GAAG,OAAO,CAAC,iBAAiB;AAC5D,MAAM,IAAI,OAAO,CAAC,oBAAoB,IAAI,IAAI;AAC9C,UAAU,OAAO,CAAC,cAAc,CAAC,sBAAsB,CAAC;AACxD,QAAQ,MAAM,CAAC,oBAAoB,GAAG,OAAO,CAAC,oBAAoB;AAClE,MAAM,OAAO,MAAM;AACnB,IAAI,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,cAAc,CAAC,SAAS,CAAC,MAAM,GAAG,SAAS,MAAM,GAAG;AACxD,MAAM,OAAO,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC;AAC1E,IAAI,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,cAAc,CAAC,UAAU,GAAG,SAAS,UAAU,CAAC,aAAa,EAAE;AACnE,MAAM,IAAI,aAAa,KAAK,SAAS,EAAE;AACvC,QAAQ,aAAa,GAAG,qBAAqB;AAC7C,MAAM;AACN,MAAM,OAAO,aAAa,GAAG,+BAA+B;AAC5D,IAAI,CAAC;;AAEL,IAAI,OAAO,cAAc;AACzB,EAAE,CAAC,GAAG;;AAEN,EAAE,aAAa,CAAC,YAAY,GAAG,CAAC,WAAW;AAC3C;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,SAAS,YAAY,CAAC,UAAU,EAAE;AACtC,MAAM,IAAI,CAAC,OAAO,GAAG,EAAE;AACvB,MAAM,IAAI,UAAU;AACpB,QAAQ,KAAK,IAAI,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;AAC5E,UAAU,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC9E,IAAI;;AAEJ;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,YAAY,CAAC,SAAS,CAAC,OAAO,GAAG,KAAK,CAAC,UAAU;;AAErD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,YAAY,CAAC,MAAM,GAAG,SAAS,MAAM,CAAC,UAAU,EAAE;AACtD,MAAM,OAAO,IAAI,YAAY,CAAC,UAAU,CAAC;AACzC,IAAI,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,YAAY,CAAC,MAAM,GAAG,SAAS,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE;AAC3D,MAAM,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE;AAC5C,MAAM,IAAI,OAAO,CAAC,OAAO,IAAI,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM;AAC3D,QAAQ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;AACvD,UAAU,KAAK,CAAC,aAAa,CAAC,YAAY,CAAC;AAC3C,eAAe,MAAM;AACrB,kBAAkB,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;AACpC,kBAAkB,MAAM,CAAC,MAAM,yBAAyB,EAAE,CAAC,CAAC,IAAI,EAAE;AAClE,eAAe,MAAM,EAAE;AACvB,MAAM,OAAO,MAAM;AACnB,IAAI,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,YAAY,CAAC,eAAe,GAAG,SAAS,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE;AAC7E,MAAM,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,MAAM,EAAE;AAClD,IAAI,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,YAAY,CAAC,MAAM,GAAG,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE;AACjE,MAAM,IAAI,EAAE,MAAM,YAAY,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC;AACvE,MAAM,IAAI,GAAG,GAAG,MAAM,KAAK,SAAS,GAAG,MAAM,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,GAAG,MAAM;AACvE,UAAU,OAAO,GAAG,IAAI,KAAK,CAAC,aAAa,CAAC,YAAY,EAAE;AAC1D,MAAM,OAAO,MAAM,CAAC,GAAG,GAAG,GAAG,EAAE;AAC/B,QAAQ,IAAI,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE;AACjC,QAAQ,IAAI,GAAG,KAAK,KAAK,EAAE;AAC3B,QAAQ,QAAQ,GAAG,KAAK,CAAC;AACzB,UAAU,KAAK,CAAC,EAAE;AAClB,YAAY,IAAI,EAAE,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC;AAC5D,cAAc,OAAO,CAAC,OAAO,GAAG,EAAE;AAClC,YAAY,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,YAAY,CAAC,MAAM,CAAC,MAAM;AAC/E,gBAAgB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;AACzC,YAAY;AACZ,UAAU;AACV,UAAU;AACV,YAAY,MAAM,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC,CAAC;AACpC,YAAY;AACZ;AACA,MAAM;AACN,MAAM,OAAO,OAAO;AACpB,IAAI,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,YAAY,CAAC,eAAe,GAAG,SAAS,eAAe,CAAC,MAAM,EAAE;AACpE,MAAM,IAAI,EAAE,MAAM,YAAY,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;AACpE,MAAM,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;AACjD,IAAI,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,YAAY,CAAC,MAAM,GAAG,SAAS,MAAM,CAAC,OAAO,EAAE;AACnD,MAAM,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI;AACzD,QAAQ,OAAO,iBAAiB;AAChC,MAAM,IAAI,OAAO,CAAC,OAAO,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,SAAS,CAAC,EAAE;AACxE,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,OAAO,yBAAyB;AAC7E,QAAQ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE;AACzD,UAAU,IAAI,KAAK,GAAG,KAAK,CAAC,aAAa,CAAC,YAAY,CAAC,MAAM,CAAC,MAAM;AACpE,cAAc,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AACjC,UAAU,IAAI,KAAK,EAAE,OAAO,UAAU,GAAG,KAAK;AAC9C,QAAQ;AACR,MAAM;AACN,MAAM,OAAO,IAAI;AACjB,IAAI,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,YAAY,CAAC,UAAU,GAAG,SAAS,UAAU,CAAC,MAAM,EAAE;AAC1D,MAAM,IAAI,MAAM,YAAY,KAAK,CAAC,aAAa,CAAC,YAAY,EAAE,OAAO,MAAM;AAC3E,MAAM,IAAI,OAAO,GAAG,IAAI,KAAK,CAAC,aAAa,CAAC,YAAY,EAAE;AAC1D,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE;AAC1B,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC;AAC1C,UAAU,MAAM,SAAS;AACzB,cAAc,qDAAqD,CAAC;AACpE,QAAQ,OAAO,CAAC,OAAO,GAAG,EAAE;AAC5B,QAAQ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE;AACxD,UAAU,IAAI,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,QAAQ;AACnD,YAAY,MAAM,SAAS;AAC3B,gBAAgB,sDAAsD,CAAC;AACvE,UAAU,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;AAC5B,cAAc,KAAK,CAAC,aAAa,CAAC,YAAY,CAAC,MAAM,CAAC,UAAU;AAChE,kBAAkB,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AACpC,QAAQ;AACR,MAAM;AACN,MAAM,OAAO,OAAO;AACpB,IAAI,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,YAAY,CAAC,QAAQ,GAAG,SAAS,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE;AAChE,MAAM,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,EAAE;AAChC,MAAM,IAAI,MAAM,GAAG,EAAE;AACrB,MAAM,IAAI,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,OAAO,GAAG,EAAE;AACjE,MAAM,IAAI,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE;AACrD,QAAQ,MAAM,CAAC,OAAO,GAAG,EAAE;AAC3B,QAAQ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;AACvD,UAAU,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,aAAa,CAAC,YAAY,CAAC,MAAM,CAAC,QAAQ;AAC9E,cAAc,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC;AAC1C,MAAM;AACN,MAAM,OAAO,MAAM;AACnB,IAAI,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,YAAY,CAAC,SAAS,CAAC,MAAM,GAAG,SAAS,MAAM,GAAG;AACtD,MAAM,OAAO,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC;AAC1E,IAAI,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,YAAY,CAAC,UAAU,GAAG,SAAS,UAAU,CAAC,aAAa,EAAE;AACjE,MAAM,IAAI,aAAa,KAAK,SAAS,EAAE;AACvC,QAAQ,aAAa,GAAG,qBAAqB;AAC7C,MAAM;AACN,MAAM,OAAO,aAAa,GAAG,6BAA6B;AAC1D,IAAI,CAAC;;AAEL,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,WAAW;AACtC;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,SAAS,MAAM,CAAC,UAAU,EAAE;AAClC,QAAQ,IAAI,UAAU;AACtB,UAAU,KAAK,IAAI,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;AAC9E,YAAY,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI;AAC3C,cAAc,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACjD,MAAM;;AAEN;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,MAAM,CAAC,SAAS,CAAC,KAAK,GAAG,EAAE;;AAEjC;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,MAAM,CAAC,SAAS,CAAC,QAAQ,GAAG,EAAE;;AAEpC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,MAAM,CAAC,MAAM,GAAG,SAAS,MAAM,CAAC,UAAU,EAAE;AAClD,QAAQ,OAAO,IAAI,MAAM,CAAC,UAAU,CAAC;AACrC,MAAM,CAAC;;AAEP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,MAAM,CAAC,MAAM,GAAG,SAAS,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE;AACvD,QAAQ,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE;AAC9C,QAAQ,IAAI,OAAO,CAAC,KAAK,IAAI,IAAI;AACjC,YAAY,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC;AACxD,UAAU,MAAM,CAAC,MAAM,yBAAyB,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;AACzE,QAAQ,IAAI,OAAO,CAAC,QAAQ,IAAI,IAAI;AACpC,YAAY,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC;AAC3D,UAAU,MAAM,CAAC,MAAM,yBAAyB,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC;AAC5E,QAAQ,OAAO,MAAM;AACrB,MAAM,CAAC;;AAEP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,MAAM,CAAC,eAAe,GAAG,SAAS,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE;AACzE,QAAQ,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,MAAM,EAAE;AACpD,MAAM,CAAC;;AAEP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,MAAM,CAAC,MAAM,GAAG,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE;AAC7D,QAAQ,IAAI,EAAE,MAAM,YAAY,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC;AACzE,QAAQ,IAAI,GAAG,GAAG,MAAM,KAAK,SAAS,GAAG,MAAM,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,GAAG,MAAM;AACzE,YAAY,OAAO,GAAG,IAAI,KAAK,CAAC,aAAa,CAAC,YAAY,CAAC,MAAM,EAAE;AACnE,QAAQ,OAAO,MAAM,CAAC,GAAG,GAAG,GAAG,EAAE;AACjC,UAAU,IAAI,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE;AACnC,UAAU,IAAI,GAAG,KAAK,KAAK,EAAE;AAC7B,UAAU,QAAQ,GAAG,KAAK,CAAC;AAC3B,YAAY,KAAK,CAAC,EAAE;AACpB,cAAc,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE;AAC7C,cAAc;AACd,YAAY;AACZ,YAAY,KAAK,CAAC,EAAE;AACpB,cAAc,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE;AAChD,cAAc;AACd,YAAY;AACZ,YAAY;AACZ,cAAc,MAAM,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC,CAAC;AACtC,cAAc;AACd;AACA,QAAQ;AACR,QAAQ,OAAO,OAAO;AACtB,MAAM,CAAC;;AAEP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,MAAM,CAAC,eAAe,GAAG,SAAS,eAAe,CAAC,MAAM,EAAE;AAChE,QAAQ,IAAI,EAAE,MAAM,YAAY,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;AACtE,QAAQ,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;AACnD,MAAM,CAAC;;AAEP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,MAAM,CAAC,MAAM,GAAG,SAAS,MAAM,CAAC,OAAO,EAAE;AAC/C,QAAQ,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI;AAC3D,UAAU,OAAO,iBAAiB;AAClC,QAAQ,IAAI,OAAO,CAAC,KAAK,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC;AACpE,UAAU,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,OAAO,wBAAwB;AAC7E,QAAQ,IAAI,OAAO,CAAC,QAAQ,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC;AAC1E,UAAU,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC;AAC/C,YAAY,OAAO,2BAA2B;AAC9C,QAAQ,OAAO,IAAI;AACnB,MAAM,CAAC;;AAEP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,MAAM,CAAC,UAAU,GAAG,SAAS,UAAU,CAAC,MAAM,EAAE;AACtD,QAAQ,IAAI,MAAM,YAAY,KAAK,CAAC,aAAa,CAAC,YAAY,CAAC,MAAM;AACrE,UAAU,OAAO,MAAM;AACvB,QAAQ,IAAI,OAAO,GAAG,IAAI,KAAK,CAAC,aAAa,CAAC,YAAY,CAAC,MAAM,EAAE;AACnE,QAAQ,IAAI,MAAM,CAAC,KAAK,IAAI,IAAI,EAAE,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;AACtE,QAAQ,IAAI,MAAM,CAAC,QAAQ,IAAI,IAAI,EAAE,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC;AAC/E,QAAQ,OAAO,OAAO;AACtB,MAAM,CAAC;;AAEP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,MAAM,CAAC,QAAQ,GAAG,SAAS,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE;AAC5D,QAAQ,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,EAAE;AAClC,QAAQ,IAAI,MAAM,GAAG,EAAE;AACvB,QAAQ,IAAI,OAAO,CAAC,QAAQ,EAAE;AAC9B,UAAU,MAAM,CAAC,KAAK,GAAG,EAAE;AAC3B,UAAU,MAAM,CAAC,QAAQ,GAAG,EAAE;AAC9B,QAAQ;AACR,QAAQ,IAAI,OAAO,CAAC,KAAK,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC;AACpE,UAAU,MAAM,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK;AACtC,QAAQ,IAAI,OAAO,CAAC,QAAQ,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC;AAC1E,UAAU,MAAM,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ;AAC5C,QAAQ,OAAO,MAAM;AACrB,MAAM,CAAC;;AAEP;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,MAAM,CAAC,SAAS,CAAC,MAAM,GAAG,SAAS,MAAM,GAAG;AAClD,QAAQ,OAAO,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC;AAC5E,MAAM,CAAC;;AAEP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,MAAM,CAAC,UAAU,GAAG,SAAS,UAAU,CAAC,aAAa,EAAE;AAC7D,QAAQ,IAAI,aAAa,KAAK,SAAS,EAAE;AACzC,UAAU,aAAa,GAAG,qBAAqB;AAC/C,QAAQ;AACR,QAAQ,OAAO,aAAa,GAAG,oCAAoC;AACnE,MAAM,CAAC;;AAEP,MAAM,OAAO,MAAM;AACnB,IAAI,CAAC,GAAG;;AAER,IAAI,OAAO,YAAY;AACvB,EAAE,CAAC,GAAG;;AAEN,EAAE,aAAa,CAAC,UAAU,GAAG,CAAC,WAAW;AACzC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,SAAS,UAAU,CAAC,UAAU,EAAE;AACpC,MAAM,IAAI,CAAC,MAAM,GAAG,EAAE;AACtB,MAAM,IAAI,UAAU;AACpB,QAAQ,KAAK,IAAI,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;AAC5E,UAAU,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC9E,IAAI;;AAEJ;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,UAAU,CAAC,SAAS,CAAC,MAAM,GAAG,KAAK,CAAC,UAAU;;AAElD;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,UAAU,CAAC,SAAS,CAAC,WAAW,GAAG,IAAI;;AAE3C;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,UAAU,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI;;AAE9C;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,UAAU,CAAC,SAAS,CAAC,YAAY,GAAG,IAAI;;AAE5C;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,UAAU,CAAC,SAAS,CAAC,gBAAgB,GAAG,IAAI;;AAEhD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,UAAU,CAAC,MAAM,GAAG,SAAS,MAAM,CAAC,UAAU,EAAE;AACpD,MAAM,OAAO,IAAI,UAAU,CAAC,UAAU,CAAC;AACvC,IAAI,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,UAAU,CAAC,MAAM,GAAG,SAAS,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE;AACzD,MAAM,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE;AAC5C,MAAM,IAAI,OAAO,CAAC,MAAM,IAAI,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM;AACzD,QAAQ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;AACtD,UAAU,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC;AACzC,eAAe,MAAM;AACrB,kBAAkB,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;AACnC,kBAAkB,MAAM,CAAC,MAAM,yBAAyB,EAAE,CAAC,CAAC,IAAI,EAAE;AAClE,eAAe,MAAM,EAAE;AACvB,MAAM,IAAI,OAAO,CAAC,WAAW,IAAI,IAAI;AACrC,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC;AAC5D,QAAQ,KAAK,CAAC,aAAa,CAAC;AAC5B,aAAa,MAAM;AACnB,gBAAgB,OAAO,CAAC,WAAW;AACnC,gBAAgB,MAAM,CAAC,MAAM,yBAAyB,EAAE,CAAC,CAAC,IAAI,EAAE;AAChE,aAAa,MAAM,EAAE;AACrB,MAAM,IAAI,OAAO,CAAC,cAAc,IAAI,IAAI;AACxC,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,gBAAgB,CAAC;AAC/D,QAAQ,KAAK,CAAC,aAAa,CAAC;AAC5B,aAAa,MAAM;AACnB,gBAAgB,OAAO,CAAC,cAAc;AACtC,gBAAgB,MAAM,CAAC,MAAM,yBAAyB,EAAE,CAAC,CAAC,IAAI,EAAE;AAChE,aAAa,MAAM,EAAE;AACrB,MAAM,IAAI,OAAO,CAAC,YAAY,IAAI,IAAI;AACtC,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC;AAC7D,QAAQ,KAAK,CAAC,aAAa,CAAC;AAC5B,aAAa,MAAM;AACnB,gBAAgB,OAAO,CAAC,YAAY;AACpC,gBAAgB,MAAM,CAAC,MAAM,yBAAyB,EAAE,CAAC,CAAC,IAAI,EAAE;AAChE,aAAa,MAAM,EAAE;AACrB,MAAM,IAAI,OAAO,CAAC,gBAAgB,IAAI,IAAI;AAC1C,UAAU,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,kBAAkB,CAAC;AACjE,QAAQ,KAAK,CAAC,aAAa,CAAC;AAC5B,aAAa,MAAM;AACnB,gBAAgB,OAAO,CAAC,gBAAgB;AACxC,gBAAgB,MAAM,CAAC,MAAM,yBAAyB,EAAE,CAAC,CAAC,IAAI,EAAE;AAChE,aAAa,MAAM,EAAE;AACrB,MAAM,OAAO,MAAM;AACnB,IAAI,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,UAAU,CAAC,eAAe,GAAG,SAAS,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE;AAC3E,MAAM,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,MAAM,EAAE;AAClD,IAAI,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,UAAU,CAAC,MAAM,GAAG,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE;AAC/D,MAAM,IAAI,EAAE,MAAM,YAAY,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC;AACvE,MAAM,IAAI,GAAG,GAAG,MAAM,KAAK,SAAS,GAAG,MAAM,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,GAAG,MAAM;AACvE,UAAU,OAAO,GAAG,IAAI,KAAK,CAAC,aAAa,CAAC,UAAU,EAAE;AACxD,MAAM,OAAO,MAAM,CAAC,GAAG,GAAG,GAAG,EAAE;AAC/B,QAAQ,IAAI,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE;AACjC,QAAQ,IAAI,GAAG,KAAK,KAAK,EAAE;AAC3B,QAAQ,QAAQ,GAAG,KAAK,CAAC;AACzB,UAAU,KAAK,CAAC,EAAE;AAClB,YAAY,IAAI,EAAE,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,GAAG,EAAE;AAC/E,YAAY,OAAO,CAAC,MAAM,CAAC,IAAI;AAC/B,gBAAgB,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC,aAAa,CAAC,MAAM;AACnE,oBAAoB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;AAC7C,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,CAAC,EAAE;AAClB,YAAY,OAAO,CAAC,WAAW;AAC/B,gBAAgB,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;AAC/E,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,CAAC,EAAE;AAClB,YAAY,OAAO,CAAC,cAAc,GAAG,KAAK,CAAC,aAAa,CAAC,cAAc,CAAC,MAAM;AAC9E,gBAAgB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;AACxC,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,CAAC,EAAE;AAClB,YAAY,OAAO,CAAC,YAAY,GAAG,KAAK,CAAC,aAAa,CAAC,YAAY,CAAC,MAAM;AAC1E,gBAAgB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;AACxC,YAAY;AACZ,UAAU;AACV,UAAU,KAAK,CAAC,EAAE;AAClB,YAAY,OAAO,CAAC,gBAAgB;AACpC,gBAAgB,KAAK,CAAC,aAAa,CAAC,cAAc,CAAC,MAAM;AACzD,oBAAoB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;AAC5C,YAAY;AACZ,UAAU;AACV,UAAU;AACV,YAAY,MAAM,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC,CAAC;AACpC,YAAY;AACZ;AACA,MAAM;AACN,MAAM,OAAO,OAAO;AACpB,IAAI,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,UAAU,CAAC,eAAe,GAAG,SAAS,eAAe,CAAC,MAAM,EAAE;AAClE,MAAM,IAAI,EAAE,MAAM,YAAY,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;AACpE,MAAM,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;AACjD,IAAI,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,UAAU,CAAC,MAAM,GAAG,SAAS,MAAM,CAAC,OAAO,EAAE;AACjD,MAAM,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI;AACzD,QAAQ,OAAO,iBAAiB;AAChC,MAAM,IAAI,OAAO,CAAC,MAAM,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE;AACtE,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,OAAO,wBAAwB;AAC3E,QAAQ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE;AACxD,UAAU,IAAI,KAAK,GAAG,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC,aAAa,CAAC,MAAM;AACzE,cAAc,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAChC,UAAU,IAAI,KAAK,EAAE,OAAO,SAAS,GAAG,KAAK;AAC7C,QAAQ;AACR,MAAM;AACN,MAAM,IAAI,OAAO,CAAC,WAAW,IAAI,IAAI;AACrC,UAAU,OAAO,CAAC,cAAc,CAAC,aAAa,CAAC,EAAE;AACjD,QAAQ,IAAI,KAAK,GAAG,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC;AAC/E,QAAQ,IAAI,KAAK,EAAE,OAAO,cAAc,GAAG,KAAK;AAChD,MAAM;AACN,MAAM,IAAI,OAAO,CAAC,cAAc,IAAI,IAAI;AACxC,UAAU,OAAO,CAAC,cAAc,CAAC,gBAAgB,CAAC,EAAE;AACpD,QAAQ,IAAI,KAAK;AACjB,YAAY,KAAK,CAAC,aAAa,CAAC,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC;AAC7E,QAAQ,IAAI,KAAK,EAAE,OAAO,iBAAiB,GAAG,KAAK;AACnD,MAAM;AACN,MAAM,IAAI,OAAO,CAAC,YAAY,IAAI,IAAI;AACtC,UAAU,OAAO,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE;AAClD,QAAQ,IAAI,KAAK;AACjB,YAAY,KAAK,CAAC,aAAa,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC;AACzE,QAAQ,IAAI,KAAK,EAAE,OAAO,eAAe,GAAG,KAAK;AACjD,MAAM;AACN,MAAM,IAAI,OAAO,CAAC,gBAAgB,IAAI,IAAI;AAC1C,UAAU,OAAO,CAAC,cAAc,CAAC,kBAAkB,CAAC,EAAE;AACtD,QAAQ,IAAI,KAAK;AACjB,YAAY,KAAK,CAAC,aAAa,CAAC,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC;AAC/E,QAAQ,IAAI,KAAK,EAAE,OAAO,mBAAmB,GAAG,KAAK;AACrD,MAAM;AACN,MAAM,OAAO,IAAI;AACjB,IAAI,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,UAAU,CAAC,UAAU,GAAG,SAAS,UAAU,CAAC,MAAM,EAAE;AACxD,MAAM,IAAI,MAAM,YAAY,KAAK,CAAC,aAAa,CAAC,UAAU,EAAE,OAAO,MAAM;AACzE,MAAM,IAAI,OAAO,GAAG,IAAI,KAAK,CAAC,aAAa,CAAC,UAAU,EAAE;AACxD,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE;AACzB,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC;AACzC,UAAU,MAAM,SAAS,CAAC,kDAAkD,CAAC;AAC7E,QAAQ,OAAO,CAAC,MAAM,GAAG,EAAE;AAC3B,QAAQ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE;AACvD,UAAU,IAAI,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,QAAQ;AAClD,YAAY,MAAM,SAAS;AAC3B,gBAAgB,mDAAmD,CAAC;AACpE,UAAU,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;AAC3B,cAAc,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC,aAAa,CAAC,UAAU;AACrE,kBAAkB,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACnC,QAAQ;AACR,MAAM;AACN,MAAM,IAAI,MAAM,CAAC,WAAW,IAAI,IAAI,EAAE;AACtC,QAAQ,IAAI,OAAO,MAAM,CAAC,WAAW,KAAK,QAAQ;AAClD,UAAU,MAAM,SAAS;AACzB,cAAc,wDAAwD,CAAC;AACvE,QAAQ,OAAO,CAAC,WAAW;AAC3B,YAAY,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC,UAAU,CAAC,MAAM,CAAC,WAAW,CAAC;AAC1E,MAAM;AACN,MAAM,IAAI,MAAM,CAAC,cAAc,IAAI,IAAI,EAAE;AACzC,QAAQ,IAAI,OAAO,MAAM,CAAC,cAAc,KAAK,QAAQ;AACrD,UAAU,MAAM,SAAS;AACzB,cAAc,2DAA2D,CAAC;AAC1E,QAAQ,OAAO,CAAC,cAAc,GAAG,KAAK,CAAC,aAAa,CAAC,cAAc,CAAC,UAAU;AAC9E,YAAY,MAAM,CAAC,cAAc,CAAC;AAClC,MAAM;AACN,MAAM,IAAI,MAAM,CAAC,YAAY,IAAI,IAAI,EAAE;AACvC,QAAQ,IAAI,OAAO,MAAM,CAAC,YAAY,KAAK,QAAQ;AACnD,UAAU,MAAM,SAAS;AACzB,cAAc,yDAAyD,CAAC;AACxE,QAAQ,OAAO,CAAC,YAAY;AAC5B,YAAY,KAAK,CAAC,aAAa,CAAC,YAAY,CAAC,UAAU,CAAC,MAAM,CAAC,YAAY,CAAC;AAC5E,MAAM;AACN,MAAM,IAAI,MAAM,CAAC,gBAAgB,IAAI,IAAI,EAAE;AAC3C,QAAQ,IAAI,OAAO,MAAM,CAAC,gBAAgB,KAAK,QAAQ;AACvD,UAAU,MAAM,SAAS;AACzB,cAAc,6DAA6D,CAAC;AAC5E,QAAQ,OAAO,CAAC,gBAAgB;AAChC,YAAY,KAAK,CAAC,aAAa,CAAC,cAAc,CAAC,UAAU;AACzD,gBAAgB,MAAM,CAAC,gBAAgB,CAAC;AACxC,MAAM;AACN,MAAM,OAAO,OAAO;AACpB,IAAI,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,UAAU,CAAC,QAAQ,GAAG,SAAS,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE;AAC9D,MAAM,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,EAAE;AAChC,MAAM,IAAI,MAAM,GAAG,EAAE;AACrB,MAAM,IAAI,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,GAAG,EAAE;AAChE,MAAM,IAAI,OAAO,CAAC,QAAQ,EAAE;AAC5B,QAAQ,MAAM,CAAC,WAAW,GAAG,IAAI;AACjC,QAAQ,MAAM,CAAC,cAAc,GAAG,IAAI;AACpC,QAAQ,MAAM,CAAC,YAAY,GAAG,IAAI;AAClC,QAAQ,MAAM,CAAC,gBAAgB,GAAG,IAAI;AACtC,MAAM;AACN,MAAM,IAAI,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE;AACnD,QAAQ,MAAM,CAAC,MAAM,GAAG,EAAE;AAC1B,QAAQ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;AACtD,UAAU,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;AAC1B,cAAc,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC,aAAa,CAAC,QAAQ;AACnE,kBAAkB,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC;AAC7C,MAAM;AACN,MAAM,IAAI,OAAO,CAAC,WAAW,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,aAAa,CAAC;AAC9E,QAAQ,MAAM,CAAC,WAAW,GAAG,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC,QAAQ;AACrE,YAAY,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC;AACzC,MAAM,IAAI,OAAO,CAAC,cAAc,IAAI,IAAI;AACxC,UAAU,OAAO,CAAC,cAAc,CAAC,gBAAgB,CAAC;AAClD,QAAQ,MAAM,CAAC,cAAc,GAAG,KAAK,CAAC,aAAa,CAAC,cAAc,CAAC,QAAQ;AAC3E,YAAY,OAAO,CAAC,cAAc,EAAE,OAAO,CAAC;AAC5C,MAAM,IAAI,OAAO,CAAC,YAAY,IAAI,IAAI;AACtC,UAAU,OAAO,CAAC,cAAc,CAAC,cAAc,CAAC;AAChD,QAAQ,MAAM,CAAC,YAAY,GAAG,KAAK,CAAC,aAAa,CAAC,YAAY,CAAC,QAAQ;AACvE,YAAY,OAAO,CAAC,YAAY,EAAE,OAAO,CAAC;AAC1C,MAAM,IAAI,OAAO,CAAC,gBAAgB,IAAI,IAAI;AAC1C,UAAU,OAAO,CAAC,cAAc,CAAC,kBAAkB,CAAC;AACpD,QAAQ,MAAM,CAAC,gBAAgB,GAAG,KAAK,CAAC,aAAa,CAAC,cAAc,CAAC,QAAQ;AAC7E,YAAY,OAAO,CAAC,gBAAgB,EAAE,OAAO,CAAC;AAC9C,MAAM,OAAO,MAAM;AACnB,IAAI,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,UAAU,CAAC,SAAS,CAAC,MAAM,GAAG,SAAS,MAAM,GAAG;AACpD,MAAM,OAAO,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC;AAC1E,IAAI,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,UAAU,CAAC,UAAU,GAAG,SAAS,UAAU,CAAC,aAAa,EAAE;AAC/D,MAAM,IAAI,aAAa,KAAK,SAAS,EAAE;AACvC,QAAQ,aAAa,GAAG,qBAAqB;AAC7C,MAAM;AACN,MAAM,OAAO,aAAa,GAAG,2BAA2B;AACxD,IAAI,CAAC;;AAEL,IAAI,UAAU,CAAC,aAAa,GAAG,CAAC,WAAW;AAC3C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,SAAS,aAAa,CAAC,UAAU,EAAE;AACzC,QAAQ,IAAI,UAAU;AACtB,UAAU,KAAK,IAAI,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;AAC9E,YAAY,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI;AAC3C,cAAc,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACjD,MAAM;;AAEN;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,aAAa,CAAC,SAAS,CAAC,KAAK,GAAG,EAAE;;AAExC;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,aAAa,CAAC,SAAS,CAAC,KAAK,GAAG,CAAC;;AAEvC;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,aAAa,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC;;AAEtC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,aAAa,CAAC,MAAM,GAAG,SAAS,MAAM,CAAC,UAAU,EAAE;AACzD,QAAQ,OAAO,IAAI,aAAa,CAAC,UAAU,CAAC;AAC5C,MAAM,CAAC;;AAEP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,aAAa,CAAC,MAAM,GAAG,SAAS,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE;AAC9D,QAAQ,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE;AAC9C,QAAQ,IAAI,OAAO,CAAC,KAAK,IAAI,IAAI;AACjC,YAAY,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC;AACxD,UAAU,MAAM,CAAC,MAAM,yBAAyB,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;AACzE,QAAQ,IAAI,OAAO,CAAC,KAAK,IAAI,IAAI;AACjC,YAAY,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC;AACxD,UAAU,MAAM,CAAC,MAAM,yBAAyB,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;AACxE,QAAQ,IAAI,OAAO,CAAC,IAAI,IAAI,IAAI,IAAI,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC;AAC/E,UAAU,MAAM,CAAC,MAAM,yBAAyB,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;AACvE,QAAQ,OAAO,MAAM;AACrB,MAAM,CAAC;;AAEP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,aAAa,CAAC,eAAe,GAAG,SAAS,eAAe;AAC9D,UAAU,OAAO,EAAE,MAAM,EAAE;AAC3B,QAAQ,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,MAAM,EAAE;AACpD,MAAM,CAAC;;AAEP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,aAAa,CAAC,MAAM,GAAG,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE;AACpE,QAAQ,IAAI,EAAE,MAAM,YAAY,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC;AACzE,QAAQ,IAAI,GAAG,GAAG,MAAM,KAAK,SAAS,GAAG,MAAM,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,GAAG,MAAM;AACzE,YAAY,OAAO,GAAG,IAAI,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC,aAAa,EAAE;AACxE,QAAQ,OAAO,MAAM,CAAC,GAAG,GAAG,GAAG,EAAE;AACjC,UAAU,IAAI,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE;AACnC,UAAU,IAAI,GAAG,KAAK,KAAK,EAAE;AAC7B,UAAU,QAAQ,GAAG,KAAK,CAAC;AAC3B,YAAY,KAAK,CAAC,EAAE;AACpB,cAAc,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE;AAC7C,cAAc;AACd,YAAY;AACZ,YAAY,KAAK,CAAC,EAAE;AACpB,cAAc,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE;AAC5C,cAAc;AACd,YAAY;AACZ,YAAY,KAAK,CAAC,EAAE;AACpB,cAAc,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,KAAK,EAAE;AAC3C,cAAc;AACd,YAAY;AACZ,YAAY;AACZ,cAAc,MAAM,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC,CAAC;AACtC,cAAc;AACd;AACA,QAAQ;AACR,QAAQ,OAAO,OAAO;AACtB,MAAM,CAAC;;AAEP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,aAAa,CAAC,eAAe,GAAG,SAAS,eAAe,CAAC,MAAM,EAAE;AACvE,QAAQ,IAAI,EAAE,MAAM,YAAY,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;AACtE,QAAQ,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;AACnD,MAAM,CAAC;;AAEP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,aAAa,CAAC,MAAM,GAAG,SAAS,MAAM,CAAC,OAAO,EAAE;AACtD,QAAQ,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI;AAC3D,UAAU,OAAO,iBAAiB;AAClC,QAAQ,IAAI,OAAO,CAAC,KAAK,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC;AACpE,UAAU,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,OAAO,wBAAwB;AAC7E,QAAQ,IAAI,OAAO,CAAC,KAAK,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC;AACpE,UAAU,IAAI,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ;AAC/C,YAAY,OAAO,wBAAwB;AAC3C,QAAQ,IAAI,OAAO,CAAC,IAAI,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC;AAClE,UAAU,QAAQ,OAAO,CAAC,IAAI;AAC9B,YAAY;AACZ,cAAc,OAAO,2BAA2B;AAChD,YAAY,KAAK,CAAC;AAClB,YAAY,KAAK,CAAC;AAClB,YAAY,KAAK,CAAC;AAClB,YAAY,KAAK,CAAC;AAClB,YAAY,KAAK,CAAC;AAClB,YAAY,KAAK,CAAC;AAClB,cAAc;AACd;AACA,QAAQ,OAAO,IAAI;AACnB,MAAM,CAAC;;AAEP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,aAAa,CAAC,UAAU,GAAG,SAAS,UAAU,CAAC,MAAM,EAAE;AAC7D,QAAQ,IAAI,MAAM,YAAY,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC,aAAa;AAC1E,UAAU,OAAO,MAAM;AACvB,QAAQ,IAAI,OAAO,GAAG,IAAI,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC,aAAa,EAAE;AACxE,QAAQ,IAAI,MAAM,CAAC,KAAK,IAAI,IAAI,EAAE,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;AACtE,QAAQ,IAAI,MAAM,CAAC,KAAK,IAAI,IAAI,EAAE,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;AACtE,QAAQ,QAAQ,MAAM,CAAC,IAAI;AAC3B,UAAU;AACV,YAAY,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE;AACjD,cAAc,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI;AACxC,cAAc;AACd,YAAY;AACZ,YAAY;AACZ,UAAU,KAAK,QAAQ;AACvB,UAAU,KAAK,CAAC;AAChB,YAAY,OAAO,CAAC,IAAI,GAAG,CAAC;AAC5B,YAAY;AACZ,UAAU,KAAK,SAAS;AACxB,UAAU,KAAK,CAAC;AAChB,YAAY,OAAO,CAAC,IAAI,GAAG,CAAC;AAC5B,YAAY;AACZ,UAAU,KAAK,SAAS;AACxB,UAAU,KAAK,CAAC;AAChB,YAAY,OAAO,CAAC,IAAI,GAAG,CAAC;AAC5B,YAAY;AACZ,UAAU,KAAK,cAAc;AAC7B,UAAU,KAAK,CAAC;AAChB,YAAY,OAAO,CAAC,IAAI,GAAG,CAAC;AAC5B,YAAY;AACZ,UAAU,KAAK,MAAM;AACrB,UAAU,KAAK,CAAC;AAChB,YAAY,OAAO,CAAC,IAAI,GAAG,CAAC;AAC5B,YAAY;AACZ,UAAU,KAAK,QAAQ;AACvB,UAAU,KAAK,CAAC;AAChB,YAAY,OAAO,CAAC,IAAI,GAAG,CAAC;AAC5B,YAAY;AACZ;AACA,QAAQ,OAAO,OAAO;AACtB,MAAM,CAAC;;AAEP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,aAAa,CAAC,QAAQ,GAAG,SAAS,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE;AACnE,QAAQ,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,EAAE;AAClC,QAAQ,IAAI,MAAM,GAAG,EAAE;AACvB,QAAQ,IAAI,OAAO,CAAC,QAAQ,EAAE;AAC9B,UAAU,MAAM,CAAC,KAAK,GAAG,EAAE;AAC3B,UAAU,MAAM,CAAC,KAAK,GAAG,CAAC;AAC1B,UAAU,MAAM,CAAC,IAAI,GAAG,OAAO,CAAC,KAAK,KAAK,MAAM,GAAG,QAAQ,GAAG,CAAC;AAC/D,QAAQ;AACR,QAAQ,IAAI,OAAO,CAAC,KAAK,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC;AACpE,UAAU,MAAM,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK;AACtC,QAAQ,IAAI,OAAO,CAAC,KAAK,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC;AACpE,UAAU,MAAM,CAAC,KAAK,GAAG,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC;AACjE,cAAc,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;AACnC,cAAc,OAAO,CAAC,KAAK;AAC3B,QAAQ,IAAI,OAAO,CAAC,IAAI,IAAI,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC;AAClE,UAAU,MAAM,CAAC,IAAI,GAAG,OAAO,CAAC,KAAK,KAAK,MAAM;AAChD,cAAc,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC;AAC7C,2BAA2B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,SAAS;AAC3D,cAAc,OAAO,CAAC,IAAI;AAC1B,cAAc,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;AAC7E,cAAc,OAAO,CAAC,IAAI;AAC1B,QAAQ,OAAO,MAAM;AACrB,MAAM,CAAC;;AAEP;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,aAAa,CAAC,SAAS,CAAC,MAAM,GAAG,SAAS,MAAM,GAAG;AACzD,QAAQ,OAAO,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC;AAC5E,MAAM,CAAC;;AAEP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,aAAa,CAAC,UAAU,GAAG,SAAS,UAAU,CAAC,aAAa,EAAE;AACpE,QAAQ,IAAI,aAAa,KAAK,SAAS,EAAE;AACzC,UAAU,aAAa,GAAG,qBAAqB;AAC/C,QAAQ;AACR,QAAQ,OAAO,aAAa,GAAG,yCAAyC;AACxE,MAAM,CAAC;;AAEP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,aAAa,CAAC,IAAI,GAAG,CAAC,WAAW;AACvC,QAAQ,MAAM,UAAU,GAAG,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC;AACjE,QAAQ,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC;AAC5C,QAAQ,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,GAAG,CAAC;AAC7C,QAAQ,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,GAAG,CAAC;AAC7C,QAAQ,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,GAAG,CAAC;AAClD,QAAQ,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC;AAC1C,QAAQ,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC;AAC5C,QAAQ,OAAO,MAAM;AACrB,MAAM,CAAC,GAAG;;AAEV,MAAM,OAAO,aAAa;AAC1B,IAAI,CAAC,GAAG;;AAER,IAAI,OAAO,UAAU;AACrB,EAAE,CAAC,GAAG;;AAEN,EAAE,OAAO,aAAa;AACtB,CAAC,GAAG;;ACloGJ;;;;AAIG;AAEH;;;AAGG;AAOH,MAAM,oBAAoB,GAAG,GAAG;AAiBhC,MAAM,UAAU,GAAG,OAAO;AAC1B,MAAM,UAAU,GAAG,OAAO;AAC1B,MAAM,UAAU,GAAG,OAAO;AAE1B;;;AAGG;MACU,sBAAsB,CAAA;AAUjC;;AAEG;AACH,IAAA,WAAA,CAAY,eAA2B,EAAA;;QACrC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,eAAe,CAAC,eAAe,CAAC;AAElD,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW;QACpC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS,CAAC,GAAG,EAAE;AAC/C,YAAA,MAAM,IAAI,KAAK,CACb,CAAA,WAAA,EAAc,KAAK,KAAA,IAAA,IAAL,KAAK,KAAA,MAAA,GAAA,MAAA,GAAL,KAAK,CAAE,SAAS,CAAA,qCAAA,CAAuC,CACtE;QACH;AAEA,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc;AACvC,QAAA,IAAI,CAAA,KAAK,KAAA,IAAA,IAAL,KAAK,KAAA,MAAA,GAAA,MAAA,GAAL,KAAK,CAAE,cAAc,MAAI,KAAK,KAAA,IAAA,IAAL,KAAK,KAAA,MAAA,GAAA,MAAA,GAAL,KAAK,CAAE,sBAAsB,CAAA,EAAE;AAC1D,YAAA,MAAM,IAAI,KAAK,CACb,CAAA,uCAAA,EAA0C,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA,CAAE,CAClE;QACH;AAEA,QAAA,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU;AACrC,QAAA,IAAI,CAAC,MAAM,GAAG,IAAI,GAAG,EAAE;AACvB,QAAA,IAAI,CAAC,QAAQ,GAAG,IAAI,GAAG,EAAE;AACzB,QAAA,IAAI,CAAC,UAAU,GAAG,IAAI,GAAG,EAAE;AAC3B,QAAA,IAAI,CAAC,QAAQ,GAAG,IAAI,GAAG,EAAE;AACzB,QAAA,IAAI,CAAC,SAAS,GAAG,EAAE;AACnB,QAAA,IAAI,CAAC,cAAc,GAAG,CAAC;AAEvB,QAAA,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;AACtB,YAAA,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC;QACxC;AAEA,QAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YACjD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;YAClC,MAAM,SAAS,GAAG,CAAA,EAAA,GAAA,KAAK,CAAC,KAAK,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,EAAA,GAAI,EAAE;YACnC,MAAM,SAAS,GAAG,CAAA,EAAA,GAAA,KAAK,CAAC,IAAI,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,EAAA,GAAI,iBAAiB,CAAC,MAAM;AAExD,YAAA,MAAM,aAAa,GACjB,SAAS,KAAK,iBAAiB,CAAC,MAAM;gBACtC,SAAS,KAAK,iBAAiB,CAAC,YAAY;AAC5C,gBAAA,SAAS,KAAK,iBAAiB,CAAC,MAAM;YAExC,IAAI,aAAa,EAAE;gBACjB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC;AAC7B,gBAAA,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC,MAAM,CAAC;YACvE;iBAAO;gBACL,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC;YACjC;AAEA,YAAA,IAAI,SAAS,KAAK,iBAAiB,CAAC,YAAY,EAAE;AAChD,gBAAA,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC;YAC5B;AAAO,iBAAA,IAAI,SAAS,KAAK,iBAAiB,CAAC,OAAO,EAAE;AAClD,gBAAA,IAAI,IAAI,CAAC,SAAS,IAAI,CAAC,EAAE;AACvB,oBAAA,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC;gBAClC;AACA,gBAAA,IAAI,CAAC,SAAS,GAAG,CAAC;YACpB;AAAO,iBAAA,IAAI,SAAS,KAAK,iBAAiB,CAAC,IAAI,EAAE;AAC/C,gBAAA,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE;AACvB,oBAAA,MAAM,IAAI,KAAK,CACb,eAAe,SAAS,CAAA,oCAAA,CAAsC,CAC/D;gBACH;AACA,gBAAA,MAAM,EAAE,GAAG,eAAe,CAAC,SAAS,CAAC;gBACrC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,GAAG,EAAE;AACvB,oBAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,EAAE,EAAC,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAC,CAAC;oBACjD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC;gBAC1B;YACF;QACF;AAEA,QAAA,IAAI,IAAI,CAAC,SAAS,GAAG,CAAC,EAAE;AACtB,YAAA,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC;QAC9C;;AAGA,QAAA,IAAI,KAAK,CAAC,YAAY,EAAE;AACtB,YAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE;gBAC5B,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;AAC3B,oBAAA,MAAM,IAAI,KAAK,CACb,gBAAgB,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA,UAAA,CAAY,CAC5D;gBACH;YACF;QACF;QAEA,IAAI,CAAC,kBAAkB,GAAG,IAAI,aAAa,CAAC,WAAW,CAAC;IAC1D;AAEA;;AAEG;AACH,IAAA,MAAM,CAAC,IAAY,EAAA;;AACjB,QAAA,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;QAU3B,MAAM,OAAO,GAAkB,EAAE;AAEjC,QAAA,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE;AACtB,YAAA,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;AAE5C,YAAA,MAAM,GAAG,GAAgB;AACvB,gBAAA,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC;AAC/B,gBAAA,IAAI,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC;AACxB,gBAAA,IAAI,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC;aACzB;AACD,YAAA,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC;AAEjB,YAAA,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;QAC7B;AAEA,QAAA,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE;AACxB,YAAA,OAAO,EAAE;QACX;AAEA,QAAA,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE;AAUrC,QAAA,MAAM,UAAU,GAAG,IAAI,aAAa,CAClC,OAAO,CAAC,MAAM,EACd,CAAC,CAAC,EAAE,CAAC,KAAI;YACP,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE;AACjE,gBAAA,OAAO,CAAC;YACV;YACA,OAAO,EAAE;AACX,QAAA,CAAC,CACF;AAED,QAAA,MAAM,UAAU,GAAG,CACjB,CAAc,EACd,CAAc,KACe;;YAC7B,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM;YAClC,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC;YAClC,IAAI,EAAE,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;AACzC,gBAAA,OAAO,CAAC,CAAA,EAAA,GAAA,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,KAAK,mCAAI,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC;YACtD;AACA,YAAA,OAAO,CAAC,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC;AACvB,QAAA,CAAC;AAED,QAAA,MAAM,mBAAmB,GAAG,CAAC,IAAY,EAAE,KAAa,KAAI;;YAC1D,IACE,IAAI,KAAK,EAAE;gBACX,KAAK,KAAK,EAAE;AACZ,gBAAA,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO;AACrB,gBAAA,OAAO,CAAC,KAAK,CAAC,CAAC,OAAO,EACtB;gBACA;YACF;YAEA,MAAM,CAAC,YAAY,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;YACxE,IAAI,EAAE,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;gBAC3B,UAAU,CAAC,MAAM,CAAC;oBAChB,IAAI;oBACJ,KAAK;oBACL,MAAM,EAAE,YAAY,CAAC,MAAM;AAC3B,oBAAA,KAAK,EAAE,CAAA,EAAA,GAAA,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,KAAK,mCAAI,CAAC;AACxC,iBAAA,CAAC;YACJ;AACF,QAAA,CAAC;AAED,QAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AACvC,YAAA,mBAAmB,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC/B;AAEA,QAAA,MAAM,eAAe,GAAG,CAAC,SAAyB,KAAa;YAC7D,MAAM,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,MAAM;YACjD,MAAM,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,MAAM;YACnD,QACE,UAAU,KAAK,EAAE;AACjB,gBAAA,WAAW,KAAK,EAAE;gBAClB,UAAU,CAAC,MAAM,GAAG,WAAW,CAAC,MAAM,KAAK,SAAS,CAAC,MAAM;AAE/D,QAAA,CAAC;QAED,IAAI,cAAc,GAAG,CAAC;AACtB,QAAA,OAAO,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE;AAC3B,YAAA,MAAM,SAAS,GAAG,UAAU,CAAC,MAAM,EAAE;YACrC,MAAM,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC;YAC1C,MAAM,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC;AAE5C,YAAA,IAAI,eAAe,CAAC,SAAS,CAAC,EAAE;AAC9B,gBAAA,cAAc,EAAE;gBAChB;YACF;YAEA,IAAI,cAAc,GAAG,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE,EAAE;AACzC,gBAAA,UAAU,CAAC,UAAU,CAAC,eAAe,CAAC;gBACtC,cAAc,GAAG,CAAC;YACpB;AAEA,YAAA,MAAM,CAAC,YAAY,IAAI,EAAE,CAAC,GAAG,UAAU,CAAC,UAAU,EAAE,WAAW,CAAC;YAChE,IAAI,CAAC,EAAE,EAAE;AACP,gBAAA,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC;YAC5C;YACA,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,YAAY;YAG7C,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,WAAW,CAAC,IAAI;AAC/C,YAAA,IAAI,WAAW,CAAC,IAAI,IAAI,CAAC,EAAE;gBACzB,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,SAAS,CAAC,IAAI;YACjD;YAEA,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,EAAE;AACpC,YAAA,cAAc,EAAE;YAEhB,mBAAmB,CAAC,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC;YACpD,mBAAmB,CAAC,SAAS,CAAC,IAAI,EAAE,WAAW,CAAC,IAAI,CAAC;QACvD;QAEA,MAAM,MAAM,GAAY,EAAE;AAC1B,QAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE;YAC3C,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM;YAChC,MAAM,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;AAClC,YAAA,IAAI,EAAE,KAAK,IAAI,CAAC,SAAS,KAAI,CAAA,EAAA,GAAA,IAAI,CAAC,KAAK,CAAC,WAAW,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,MAAA,GAAA,EAAA,CAAE,YAAY,CAAA,EAAE;;gBAEjE,MAAM,KAAK,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC;AAC9C,gBAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AACrC,oBAAA,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;oBAC/C,IAAI,SAAS,EAAE;AACb,wBAAA,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;oBACxB;gBACF;YACF;iBAAO;gBACL,MAAM,CAAC,IAAI,CAAC,EAAC,EAAE,EAAE,IAAI,EAAE,MAAM,EAAC,CAAC;YACjC;QACF;AAEA,QAAA,OAAO,MAAM;IACf;AAEA;;AAEG;AACH,IAAA,MAAM,CAAC,GAAa,EAAA;;QAClB,MAAM,KAAK,GAAa,EAAE;QAE1B,IAAI,CAAC,GAAG,CAAC;AACT,QAAA,OAAO,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE;YACrB,IAAI,WAAW,GAAG,CAAC;AACnB,YAAA,OAAO,WAAW,GAAG,GAAG,CAAC,MAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,EAAE;AAClE,gBAAA,WAAW,EAAE;YACf;AACA,YAAA,MAAM,QAAQ,GAAG,WAAW,GAAG,CAAC;AAEhC,YAAA,IAAI,QAAQ,GAAG,CAAC,EAAE;gBAChB,MAAM,KAAK,GAAa,EAAE;AAC1B,gBAAA,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,WAAW,EAAE,EAAE,EAAE,EAAE;AACvC,oBAAA,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AACvC,oBAAA,IAAI,IAAI,KAAK,SAAS,EAAE;AACtB,wBAAA,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;oBAClB;gBACF;AAEA,gBAAA,MAAM,WAAW,GAAG,IAAI,WAAW,CAAC,OAAO,EAAE,EAAC,KAAK,EAAE,KAAK,EAAC,CAAC;AAC5D,gBAAA,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;AACtD,gBAAA,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;YAClB;AAEA,YAAA,IAAI,WAAW,IAAI,GAAG,CAAC,MAAM,EAAE;gBAC7B;YACF;AAEA,YAAA,MAAM,EAAE,GAAG,GAAG,CAAC,WAAW,CAAC;;AAE3B,YAAA,IAAI,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,EAAE;AACnB,iBAAA,IAAI,EAAE,KAAK,IAAI,CAAC,SAAS,EAAE;AAChC,gBAAA,KAAK,CAAC,IAAI,CAAC,CAAA,EAAA,GAAA,MAAA,IAAI,CAAC,KAAK,CAAC,WAAW,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,MAAA,GAAA,EAAA,CAAE,UAAU,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,EAAA,GAAI,EAAE,CAAC;YACtD;AAAO,iBAAA,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE;AACrD,gBAAA,MAAM,KAAK,GAAG,CAAA,EAAA,GAAA,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,KAAK,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,EAAA,GAAI,EAAE;gBAC/C,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,wBAAwB,CAAC,KAAK,CAAC,CAAC;YAClD;AACA,YAAA,CAAC,GAAG,WAAW,GAAG,CAAC;QACrB;AAEA,QAAA,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;IACvB;AAEA;;AAEG;AACH,IAAA,YAAY,CAAC,MAAe,EAAA;AAC1B,QAAA,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;IAC7C;AAEA;;AAEG;IACH,SAAS,GAAA;;AACP,QAAA,MAAM,YAAY,GAAG,CAAC,MAAc,KAAY;YAC9C,MAAM,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;AAClC,YAAA,OAAO,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE;AACvC,QAAA,CAAC;QAED,OAAO;YACL,cAAc,EAAE,CAAA,EAAA,GAAA,CAAA,EAAA,GAAA,IAAI,CAAC,KAAK,CAAC,MAAM,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,MAAA,GAAA,EAAA,CAAE,MAAM,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,EAAA,GAAI,CAAC;AAC9C,YAAA,qBAAqB,EAAE,YAAY,CAAC,UAAU,CAAC;AAC/C,YAAA,eAAe,EAAE,YAAY,CAAC,UAAU,CAAC;AACzC,YAAA,KAAK,EAAE,YAAY,CAAC,UAAU,CAAC;YAC/B,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B;IACH;AAEQ,IAAA,SAAS,CAAC,IAAY,EAAA;QAC5B,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,oBAAoB,CAAC;IACjD;AAEQ,IAAA,wBAAwB,CAAC,IAAY,EAAA;AAC3C,QAAA,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,oBAAoB,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC;IACjE;AAEQ,IAAA,WAAW,CAAC,IAAY,EAAA;QAC9B,MAAM,SAAS,GAAG,IAAI,CAAC,kBAAkB,CAAC,aAAa,CAAC,IAAI,CAAC;AAC7D,QAAA,IAAI,SAAS,GAAG,CAAC,EAAE;AACjB,YAAA,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC;QAC1B;;;AAIA,QAAA,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC;IACnB;AAEQ,IAAA,UAAU,CAAC,MAAc,EAAA;QAC/B,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC;AAC5C,QAAA,IAAI,UAAU,KAAK,SAAS,EAAE;AAC5B,YAAA,OAAO,UAAU;QACnB;QACA,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC;AACvC,QAAA,IAAI,OAAO,KAAK,SAAS,EAAE;AACzB,YAAA,OAAO,OAAO;QAChB;QACA,OAAO,IAAI,CAAC,SAAS;IACvB;AAEQ,IAAA,QAAQ,CAAC,EAAU,EAAA;AACzB,QAAA,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,EAAE,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE;AACxD,YAAA,OAAO,KAAK;QACd;AACA,QAAA,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,KAAK,iBAAiB,CAAC,IAAI;IAC9D;AAEQ,IAAA,WAAW,CAAC,EAAU,EAAA;AAC5B,QAAA,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,EAAE,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE;AACxD,YAAA,OAAO,KAAK;QACd;AACA,QAAA,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,KAAK,iBAAiB,CAAC,OAAO;IACjE;AAEQ,IAAA,eAAe,CAAC,IAAgB,EAAA;;QACtC,MAAM,OAAO,GAAG,aAAa,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC;AAErD,QAAA,MAAM,KAAK,GAAe;YACxB,MAAM,EAAE,CAAA,EAAA,GAAA,OAAO,CAAC,MAAM,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,MAAA,GAAA,EAAA,CAAE,GAAG,CACzB,CAAC,CAA0C,KAAI;;AAAC,gBAAA,QAAC;AAC/C,oBAAA,KAAK,EAAE,CAAA,EAAA,GAAA,CAAC,CAAC,KAAK,mCAAI,SAAS;AAC3B,oBAAA,KAAK,EAAE,CAAA,EAAA,GAAA,CAAC,CAAC,KAAK,mCAAI,SAAS;AAC3B,oBAAA,IAAI,EAAE,CAAA,EAAA,GAAC,CAAC,CAAC,IAAqC,mCAAI,SAAS;AAC5D,iBAAA;aAAC,CACH;YACD,WAAW,EAAE,OAAO,CAAC;AACnB,kBAAE;oBACE,SAAS,EACP,MAAC,OAAO,CAAC,WAAW,CAAC,SAAkC,mCACvD,SAAS;oBACX,SAAS,EAAE,MAAA,OAAO,CAAC,WAAW,CAAC,SAAS,mCAAI,SAAS;oBACrD,iBAAiB,EACf,MAAA,OAAO,CAAC,WAAW,CAAC,iBAAiB,mCAAI,SAAS;oBACpD,YAAY,EAAE,MAAA,OAAO,CAAC,WAAW,CAAC,YAAY,mCAAI,SAAS;oBAC3D,UAAU,EAAE,MAAA,OAAO,CAAC,WAAW,CAAC,UAAU,mCAAI,SAAS;AACxD;AACH,kBAAE,SAAS;YACb,cAAc,EAAE,OAAO,CAAC;AACtB,kBAAE;oBACE,IAAI,EAAE,MAAA,OAAO,CAAC,cAAc,CAAC,IAAI,mCAAI,SAAS;AAC9C,oBAAA,mBAAmB,EAAE,OAAO,CAAC,cAAc,CAAC;0BACxC,IAAI,UAAU,CAAC,OAAO,CAAC,cAAc,CAAC,mBAAmB;AAC3D,0BAAE,SAAS;oBACb,cAAc,EAAE,MAAA,OAAO,CAAC,cAAc,CAAC,cAAc,mCAAI,SAAS;oBAClE,sBAAsB,EACpB,MAAA,OAAO,CAAC,cAAc,CAAC,sBAAsB,mCAAI,SAAS;oBAC5D,iBAAiB,EACf,MAAA,OAAO,CAAC,cAAc,CAAC,iBAAiB,mCAAI,SAAS;oBACvD,oBAAoB,EAClB,MAAA,OAAO,CAAC,cAAc,CAAC,oBAAoB,mCAAI,SAAS;AAC3D;AACH,kBAAE,SAAS;SACd;AAED,QAAA,OAAO,KAAK;IACd;AACD;AAED,SAAS,eAAe,CAAC,EAAU,EAAA;IACjC,MAAM,KAAK,GAAG,EAAE,CAAC,KAAK,CAAC,wBAAwB,CAAC;IAChD,IAAI,CAAC,KAAK,EAAE;QACV,OAAO,EAAE;IACX;IACA,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;AAC/B;;AC/cA;;;;AAIG;AAIH;;AAEG;AACH,MAAM,gCAAgC,GAA2B;AAC/D,IAAA,gBAAgB,EAAE,QAAQ;AAC1B,IAAA,kBAAkB,EAAE,QAAQ;AAC5B,IAAA,uBAAuB,EAAE,QAAQ;AACjC,IAAA,kBAAkB,EAAE,QAAQ;AAC5B,IAAA,uBAAuB,EAAE,QAAQ;CAClC;AAED,MAAM,uCAAuC,GAA2B;AACtE,IAAA,sBAAsB,EAAE,QAAQ;AAChC,IAAA,8BAA8B,EAAE,QAAQ;AACxC,IAAA,8BAA8B,EAAE,QAAQ;AACxC,IAAA,0BAA0B,EAAE,QAAQ;AACpC,IAAA,uBAAuB,EAAE,QAAQ;AACjC,IAAA,gCAAgC,EAAE,QAAQ;AAC1C,IAAA,gCAAgC,EAAE,QAAQ;AAC1C,IAAA,qCAAqC,EAAE,QAAQ;AAC/C,IAAA,sBAAsB,EAAE,QAAQ;AAChC,IAAA,2BAA2B,EAAE,QAAQ;CACtC;AAED,MAAM,UAAU,GAAoC;AAClD,IAAA,MAAM,EAAE;AACN,QAAA,QAAQ,EACN,2HAA2H;AAC7H,QAAA,SAAS,EACP,kEAAkE;AACrE,KAAA;AACD,IAAA,MAAM,EAAE;AACN,QAAA,QAAQ,EACN,iJAAiJ;AACnJ,QAAA,SAAS,EACP,kEAAkE;AACrE,KAAA;CACF;AAED;;;;;;AAMG;AACG,SAAU,gBAAgB,CAAC,SAAiB,EAAA;AAChD,IAAA,IAAI,SAAS,IAAI,gCAAgC,EAAE;AACjD,QAAA,OAAO,gCAAgC,CAAC,SAAS,CAAC;IACpD;AACA,IAAA,IAAI,SAAS,IAAI,uCAAuC,EAAE;AACxD,QAAA,OAAO,uCAAuC,CAAC,SAAS,CAAC;IAC3D;AAEA,IAAA,MAAM,eAAe,GAAG;AACtB,QAAA,GAAG,MAAM,CAAC,IAAI,CAAC,gCAAgC,CAAC;AAChD,QAAA,GAAG,MAAM,CAAC,IAAI,CAAC,uCAAuC,CAAC;AACxD,KAAA,CAAC,IAAI,CAAC,IAAI,CAAC;IAEZ,MAAM,IAAI,KAAK,CACb,CAAA,MAAA,EAAS,SAAS,CAAA,4DAAA,EAA+D,eAAe,CAAA,CAAA,CAAG,CACpG;AACH;AAEA;;;;;;AAMG;AACG,SAAU,kBAAkB,CAAC,aAAqB,EAAA;AACtD,IAAA,IAAI,EAAE,aAAa,IAAI,UAAU,CAAC,EAAE;AAClC,QAAA,MAAM,IAAI,KAAK,CACb,aAAa,aAAa,CAAA,yCAAA,EAA4C,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA,CAAE,CAC3G;IACH;AACA,IAAA,OAAO,UAAU,CAAC,aAAa,CAAC;AAClC;AAEA;;;;;;AAMG;AACI,eAAe,mBAAmB,CACvC,aAAqB,EACrB,QAA2B,EAAA;AAE3B,IAAA,MAAM,MAAM,GAAG,kBAAkB,CAAC,aAAa,CAAC;AAEhD,IAAA,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE;AACjC,IAAA,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,UAAU,CAAC,WAAW,CACpD,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAChC;AAED,IAAA,IAAI,SAAS,GAAG,MAAM,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,SAAS,CAAC;IAErE,IAAI,CAAC,SAAS,EAAE;AACd,QAAA,SAAS,GAAG,MAAM,QAAQ,CAAC,UAAU,CAAC,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC;AAEnE,QAAA,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,UAAU,CAAC,YAAY,CACpD,SAAS,EACT,MAAM,CAAC,SAAS,CACjB;QAED,IAAI,CAAC,OAAO,EAAE;YACZ,MAAM,UAAU,GAAG,MAAM,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC,SAAS,CAAC;YACnE,MAAM,IAAI,KAAK,CACb,CAAA,kDAAA,EAAqD,MAAM,CAAC,SAAS,CAAA,gBAAA,EAAmB,UAAU,CAAA,CAAA,CAAG,CACtG;QACH;QAEA,MAAM,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC;IAChD;AAEA,IAAA,OAAO,SAAS;AAClB;;AC/HA;AACA;;;;AAIG;AAyBH;;AAEG;MACU,gBAAgB,CAAA;AAG3B,IAAA,WAAA,GAAA;AACE,QAAA,IAAI,CAAC,KAAK,GAAG,EAAE;IACjB;AAEA;;AAEG;IACH,QAAQ,GAAA;QACN,OAAO,IAAI,CAAC,KAAK;IACnB;AAEA;;AAEG;AACH,IAAA,WAAW,CAAC,QAAmB,EAAA;AAC7B,QAAA,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE;AAC9B,YAAA,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;QAC1B;IACF;AAEA,IAAA,UAAU,CAAC,OAAgB,EAAA;AACzB,QAAA,MAAM,cAAc,GAAY;AAC9B,YAAA,KAAK,EAAE,EAAE;YACT,IAAI,EAAE,OAAO,CAAC,IAAI;SACnB;AAED,QAAA,IAAI,OAAO,CAAC,KAAK,EAAE;AACjB,YAAA,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE;gBAChC,MAAM,WAAW,GAAS,EAAE;gBAE5B,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,UAAU,EAAE;AACpC,oBAAA,MAAM,IAAI,KAAK,CACb,wDAAwD,CACzD;gBACH;AAEA,gBAAA,IAAI,IAAI,CAAC,aAAa,EAAE;AACtB,oBAAA,WAAW,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa;gBAChD;AAEA,gBAAA,IAAI,IAAI,CAAC,YAAY,EAAE;AACrB,oBAAA,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,YAAY,CAAC;AACvC,oBAAA,WAAW,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY;gBAC9C;AAEA,gBAAA,IAAI,IAAI,CAAC,gBAAgB,EAAE;AACzB,oBAAA,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,gBAAgB,CAAC;AAC/C,oBAAA,WAAW,CAAC,gBAAgB,GAAG,IAAI,CAAC,gBAAgB;gBACtD;AAEA,gBAAA,IAAI,IAAI,CAAC,IAAI,EAAE;AACb,oBAAA,WAAW,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI;oBAC5B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;gBAC5B;AAEA,gBAAA,IAAI,cAAc,CAAC,KAAK,EAAE;AACxB,oBAAA,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC;gBACxC;YACF;QACF;QAEA,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,cAAc,CAAC,EAAE;YAC5C,OAAO,CAAC,IAAI,CACV,CAAA,uDAAA,CAAyD;AACvD,gBAAA,CAAA,kBAAA,EAAqB,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,CAAA,EAAA,CAAI;gBACvD,CAAA,KAAA,EAAQ,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA,CAAA,CAAG,CACrC;QACH;IACF;AAEA,IAAA,eAAe,CAAC,YAA0B,EAAA;AACxC,QAAA,IAAI,YAAY,CAAC,IAAI,EAAE;YACrB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC;QACpC;AAEA,QAAA,IAAI,YAAY,CAAC,IAAI,EAAE;AACrB,YAAA,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,IAAI,CAAC;QACtC;IACF;AAEA,IAAA,QAAQ,CAAC,KAAa,EAAA;AACpB,QAAA,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;AACxB,YAAA,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;QACpB;IACF;AAEA,IAAA,OAAO,CAAC,IAAU,EAAA;AAChB,QAAA,IAAI,IAAI,CAAC,oBAAoB,EAAE;AAC7B,YAAA,KAAK,MAAM,mBAAmB,IAAI,IAAI,CAAC,oBAAoB,EAAE;AAC3D,gBAAA,IAAI,CAAC,2BAA2B,CAAC,mBAAmB,CAAC;YACvD;QACF;IACF;AAEA,IAAA,oBAAoB,CAAC,iBAAqC,EAAA;AACxD,QAAA,KAAK,MAAM,gBAAgB,IAAI,iBAAiB,EAAE;AAChD,YAAA,IAAI,CAAC,mBAAmB,CAAC,gBAAgB,CAAC;QAC5C;IACF;AAEA,IAAA,mBAAmB,CAAC,gBAAkC,EAAA;AACpD,QAAA,IAAI,gBAAgB,CAAC,IAAI,EAAE;YACzB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC;QACxC;AAEA,QAAA,IAAI,gBAAgB,CAAC,QAAQ,EAAE;AAC7B,YAAA,IAAI,CAAC,YAAY,CAAC,gBAAgB,CAAC,QAAQ,CAAC;QAC9C;IACF;AAEQ,IAAA,2BAA2B,CACjC,mBAAwC,EAAA;AAExC,QAAA,IAAI,mBAAmB,CAAC,IAAI,EAAE;YAC5B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC;QAC3C;AAEA,QAAA,IAAI,mBAAmB,CAAC,WAAW,EAAE;YACnC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,WAAW,CAAC;QAClD;AAEA,QAAA,IAAI,mBAAmB,CAAC,UAAU,EAAE;AAClC,YAAA,IAAI,CAAC,SAAS,CAAC,mBAAmB,CAAC,UAAU,CAAC;QAChD;AAEA,QAAA,IAAI,mBAAmB,CAAC,QAAQ,EAAE;AAChC,YAAA,IAAI,CAAC,SAAS,CAAC,mBAAmB,CAAC,QAAQ,CAAC;QAC9C;IACF;AAEA,IAAA,SAAS,CAAC,MAAc,EAAA;AACtB,QAAA,IAAI,MAAM,CAAC,MAAM,EAAE;YACjB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;QAChC;AAEA,QAAA,IAAI,MAAM,CAAC,WAAW,EAAE;YACtB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC;QACrC;AAEA,QAAA,IAAI,MAAM,CAAC,IAAI,EAAE;YACf,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC;QACjC;AAEA,QAAA,IAAI,MAAM,CAAC,QAAQ,EAAE;YACnB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC;QACrC;AAEA,QAAA,IAAI,MAAM,CAAC,KAAK,EAAE;AAChB,YAAA,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC;QAC9B;AAEA,QAAA,IAAI,MAAM,CAAC,UAAU,EAAE;AACrB,YAAA,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE;AAC5D,gBAAA,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC;AACpB,gBAAA,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;YACvB;QACF;AAEA,QAAA,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,IAAI,MAAM,CAAC,OAAO,KAAK,IAAI,EAAE;AAC3D,YAAA,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC;QAClC;IACF;AAEQ,IAAA,YAAY,CAAC,GAAwB,EAAA;AAC3C,QAAA,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACpC,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;AACtC,YAAA,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;QACzB;IACF;AAEQ,IAAA,WAAW,CAAC,KAAU,EAAA;AAC5B,QAAA,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;AAC7B,YAAA,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;QACxB;aAAO,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE;AACtD,YAAA,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;AACxB,gBAAA,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;AACxB,oBAAA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;gBACxB;YACF;iBAAO;AACL,gBAAA,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC;YAC1B;QACF;IACF;IAEQ,SAAS,CAAC,IAAS,EAAE,IAAS,EAAA;QACpC,IAAI,IAAI,KAAK,IAAI;AAAE,YAAA,OAAO,IAAI;AAC9B,QAAA,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI;YAAE,OAAO,IAAI,KAAK,IAAI;QACtD,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,OAAO,IAAI,KAAK,QAAQ;AAAE,YAAA,OAAO,KAAK;AAEtE,QAAA,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;AAC9C,YAAA,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM;AAAE,gBAAA,OAAO,KAAK;AAC7C,YAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AACpC,gBAAA,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;AAAE,oBAAA,OAAO,KAAK;YACrD;AACA,YAAA,OAAO,IAAI;QACb;QAEA,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC;QACpE,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC;AAEpE,QAAA,IAAI,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM;AAAE,YAAA,OAAO,KAAK;AAE/C,QAAA,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE;AACvB,YAAA,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC;AAAE,gBAAA,OAAO,KAAK;AACtC,YAAA,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;AAAE,gBAAA,OAAO,KAAK;QACzD;AAEA,QAAA,OAAO,IAAI;IACb;AACD;;ACrPD;;;;AAIG;AAEH;;;;;;;;AAQG;AAmBH;;;;;;;;AAQG;6BACU,cAAc,CAAA;AAMzB;;;;;AAKG;AACH,IAAA,WAAA,CACE,SAAiB,EACjB,QAA2B,EACV,iBAAoD,sBAAsB,EAAA;QAA1E,IAAA,CAAA,cAAc,GAAd,cAAc;AAE/B,QAAA,IAAI,CAAC,SAAS,GAAG,SAAS;AAC1B,QAAA,IAAI,CAAC,aAAa,GAAG,gBAAgB,CAAC,SAAS,CAAC;AAChD,QAAA,IAAI,CAAC,QAAQ,GAAG,QAAQ;IAC1B;AAEQ,IAAA,MAAM,eAAe,GAAA;AAC3B,QAAA,IAAI,IAAI,CAAC,SAAS,EAAE;YAClB;QACF;AAEA,QAAA,MAAM,UAAU,GAAG,MAAM,mBAAmB,CAC1C,IAAI,CAAC,aAAa,EAClB,IAAI,CAAC,QAAQ,CACd;QAED,IAAI,CAAC,SAAS,GAAG,IAAI,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC;IACtD;AAEA;;;;;;;;;;;;;AAaG;AACH,IAAA,MAAM,WAAW,CACf,QAA0B,EAC1B,MAA0B,EAAA;;AAE1B,QAAA,MAAM,IAAI,CAAC,eAAe,EAAE;AAE5B,QAAA,MAAM,iBAAiB,GAAG,SAAS,CAAC,QAAQ,CAAC;AAE7C,QAAA,MAAM,eAAe,GAAG,IAAI,gBAAgB,EAAE;AAC9C,QAAA,eAAe,CAAC,WAAW,CAAC,iBAAiB,CAAC;QAE9C,IAAI,MAAM,aAAN,MAAM,KAAA,MAAA,GAAA,MAAA,GAAN,MAAM,CAAE,iBAAiB,EAAE;YAC7B,MAAM,aAAa,GAAG,QAAQ,CAAC,MAAM,CAAC,iBAAiB,CAAC;AACxD,YAAA,eAAe,CAAC,WAAW,CAAC,CAAC,aAAa,CAAC,CAAC;QAC9C;QAEA,IAAI,MAAM,aAAN,MAAM,KAAA,MAAA,GAAA,MAAA,GAAN,MAAM,CAAE,KAAK,EAAE;AACjB,YAAA,eAAe,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC;QACxC;QAEA,IAAI,CAAA,EAAA,GAAA,MAAM,KAAA,IAAA,IAAN,MAAM,KAAA,MAAA,GAAA,MAAA,GAAN,MAAM,CAAE,gBAAgB,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,MAAA,GAAA,EAAA,CAAE,cAAc,EAAE;YAC5C,eAAe,CAAC,SAAS,CAAC,MAAM,CAAC,gBAAgB,CAAC,cAAc,CAAC;QACnE;AAEA,QAAA,MAAM,KAAK,GAAG,eAAe,CAAC,QAAQ,EAAE;QACxC,IAAI,WAAW,GAAG,CAAC;AAEnB,QAAA,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;YACxB,MAAM,MAAM,GAAG,IAAI,CAAC,SAAU,CAAC,MAAM,CAAC,IAAI,CAAC;AAC3C,YAAA,WAAW,IAAI,MAAM,CAAC,MAAM;QAC9B;QAEA,OAAO;YACL,WAAW;SACZ;IACH;AAEA;;;;;;;;;;;;;AAaG;IACH,MAAM,aAAa,CACjB,QAA0B,EAAA;AAE1B,QAAA,MAAM,IAAI,CAAC,eAAe,EAAE;AAE5B,QAAA,MAAM,iBAAiB,GAAG,SAAS,CAAC,QAAQ,CAAC;QAE7C,MAAM,UAAU,GAAiB,EAAE;AAEnC,QAAA,KAAK,MAAM,OAAO,IAAI,iBAAiB,EAAE;AACvC,YAAA,MAAM,eAAe,GAAG,IAAI,gBAAgB,EAAE;AAC9C,YAAA,eAAe,CAAC,UAAU,CAAC,OAAO,CAAC;AAEnC,YAAA,MAAM,KAAK,GAAG,eAAe,CAAC,QAAQ,EAAE;YAExC,MAAM,WAAW,GAAa,EAAE;YAChC,MAAM,SAAS,GAAa,EAAE;AAE9B,YAAA,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;gBACxB,MAAM,MAAM,GAAG,IAAI,CAAC,SAAU,CAAC,MAAM,CAAC,IAAI,CAAC;AAC3C,gBAAA,WAAW,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;gBAC5C,SAAS,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;YACtE;AAEA,YAAA,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE;gBAC1B,UAAU,CAAC,IAAI,CAAC;AACd,oBAAA,QAAQ,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,CAAC;AAChD,oBAAA,MAAM,EAAE,SAAS;oBACjB,IAAI,EAAE,OAAO,CAAC,IAAI;AACnB,iBAAA,CAAC;YACJ;QACF;QAEA,OAAO;YACL,UAAU;SACX;IACH;AAEQ,IAAA,iBAAiB,CAAC,IAAY,EAAA;AACpC,QAAA,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE;AACjC,QAAA,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAErD,IAAI,MAAM,GAAG,EAAE;AACf,QAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YACrC,MAAM,IAAI,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACzC;AACA,QAAA,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB;AACD;;AC9LD;;;;AAIG;AAaH;;AAEG;MACU,kBAAkB,CAAA;AAG7B,IAAA,WAAA,GAAA;AACE,QAAA,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,0BAA0B,CAAC;IACpE;AAEA,IAAA,MAAM,IAAI,CACR,QAAgB,EAChB,YAAoB,EAAA;AAEpB,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC;AACnD,QAAA,IAAI;YACF,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC;AACxC,YAAA,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;AAEnE,YAAA,IAAI,IAAI,KAAK,YAAY,EAAE;AACzB,gBAAA,OAAO,IAAI,UAAU,CAAC,IAAI,CAAC;YAC7B;AAEA,YAAA,MAAM,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;AAC/B,YAAA,OAAO,IAAI;;QAEb;QAAE,OAAO,KAAK,EAAE;AACd,YAAA,OAAO,IAAI;QACb;IACF;AAEA,IAAA,MAAM,IAAI,CAAC,QAAgB,EAAE,IAAgB,EAAA;AAC3C,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC;AACnD,QAAA,IAAI;AACF,YAAA,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAC,SAAS,EAAE,IAAI,EAAC,CAAC;AAEhD,YAAA,MAAM,OAAO,GAAG,CAAA,EAAG,IAAI,CAAC,QAAQ,CAAA,CAAA,EAAI,MAAM,CAAC,UAAU,EAAE,CAAA,IAAA,CAAM;YAC7D,MAAM,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC;YACjC,MAAM,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC;;QAEpC;QAAE,OAAO,KAAK,EAAE;;QAEhB;IACF;IAEQ,MAAM,UAAU,CAAC,QAAgB,EAAA;AACvC,QAAA,IAAI;AACF,YAAA,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC;;QAE3B;QAAE,OAAO,KAAK,EAAE;;QAEhB;IACF;AACD;AAED;;AAEG;MACU,uBAAuB,CAAA;IAClC,MAAM,YAAY,CAAC,GAAW,EAAA;AAC5B,QAAA,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC;AACjC,QAAA,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE;YAChB,MAAM,IAAI,KAAK,CACb,CAAA,qCAAA,EAAwC,GAAG,CAAA,EAAA,EAAK,QAAQ,CAAC,UAAU,CAAA,CAAE,CACtE;QACH;AACA,QAAA,MAAM,WAAW,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE;AAChD,QAAA,OAAO,IAAI,UAAU,CAAC,WAAW,CAAC;IACpC;AAEA,IAAA,MAAM,YAAY,CAAC,IAAgB,EAAE,YAAoB,EAAA;AACvD,QAAA,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;QACnE,OAAO,IAAI,KAAK,YAAY;IAC9B;IAEA,MAAM,WAAW,CAAC,IAAgB,EAAA;AAChC,QAAA,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;AACjE,QAAA,OAAO,IAAI;IACb;AACD;AAED;;AAEG;MACU,qBAAqB,CAAA;AAIhC,IAAA,WAAA,GAAA;AACE,QAAA,IAAI,CAAC,KAAK,GAAG,IAAI,kBAAkB,EAAE;AACrC,QAAA,IAAI,CAAC,UAAU,GAAG,IAAI,uBAAuB,EAAE;IACjD;AACD;;AC7GD;;;;AAIG;AAEH;;;;;AAKG;AAWH;;;;;;;;;;;;;;;;AAgBG;MACU,cAAc,CAAA;AAGzB;;;;AAIG;AACH,IAAA,WAAA,CAAY,SAAiB,EAAA;AAC3B,QAAA,MAAM,QAAQ,GAAG,IAAI,qBAAqB,EAAE;QAC5C,IAAI,CAAC,aAAa,GAAG,IAAIA,gBAAkB,CAAC,SAAS,EAAE,QAAQ,CAAC;IAClE;AAEA;;;;;;AAMG;AACH,IAAA,MAAM,WAAW,CACf,QAA0B,EAC1B,MAA0B,EAAA;QAE1B,OAAO,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,QAAQ,EAAE,MAAM,CAAC;IACzD;AAEA;;;;;AAKG;IACH,MAAM,aAAa,CACjB,QAA0B,EAAA;QAE1B,OAAO,IAAI,CAAC,aAAa,CAAC,aAAa,CAAC,QAAQ,CAAC;IACnD;AACD;;;;"} \ No newline at end of file diff --git a/server/node_modules/@google/genai/dist/web/index.mjs b/server/node_modules/@google/genai/dist/web/index.mjs new file mode 100644 index 0000000..3e77cbc --- /dev/null +++ b/server/node_modules/@google/genai/dist/web/index.mjs @@ -0,0 +1,19573 @@ +import pRetry, { AbortError } from 'p-retry'; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +let _defaultBaseGeminiUrl = undefined; +let _defaultBaseVertexUrl = undefined; +/** + * Overrides the base URLs for the Gemini API and Vertex AI API. + * + * @remarks This function should be called before initializing the SDK. If the + * base URLs are set after initializing the SDK, the base URLs will not be + * updated. Base URLs provided in the HttpOptions will also take precedence over + * URLs set here. + * + * @example + * ```ts + * import {GoogleGenAI, setDefaultBaseUrls} from '@google/genai'; + * // Override the base URL for the Gemini API. + * setDefaultBaseUrls({geminiUrl:'https://gemini.google.com'}); + * + * // Override the base URL for the Vertex AI API. + * setDefaultBaseUrls({vertexUrl: 'https://vertexai.googleapis.com'}); + * + * const ai = new GoogleGenAI({apiKey: 'GEMINI_API_KEY'}); + * ``` + */ +function setDefaultBaseUrls(baseUrlParams) { + _defaultBaseGeminiUrl = baseUrlParams.geminiUrl; + _defaultBaseVertexUrl = baseUrlParams.vertexUrl; +} +/** + * Returns the default base URLs for the Gemini API and Vertex AI API. + */ +function getDefaultBaseUrls() { + return { + geminiUrl: _defaultBaseGeminiUrl, + vertexUrl: _defaultBaseVertexUrl, + }; +} +/** + * Returns the default base URL based on the following priority: + * 1. Base URLs set via HttpOptions. + * 2. Base URLs set via the latest call to setDefaultBaseUrls. + * 3. Base URLs set via environment variables. + */ +function getBaseUrl(httpOptions, vertexai, vertexBaseUrlFromEnv, geminiBaseUrlFromEnv) { + var _a, _b; + if (!(httpOptions === null || httpOptions === void 0 ? void 0 : httpOptions.baseUrl)) { + const defaultBaseUrls = getDefaultBaseUrls(); + if (vertexai) { + return (_a = defaultBaseUrls.vertexUrl) !== null && _a !== void 0 ? _a : vertexBaseUrlFromEnv; + } + else { + return (_b = defaultBaseUrls.geminiUrl) !== null && _b !== void 0 ? _b : geminiBaseUrlFromEnv; + } + } + return httpOptions.baseUrl; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class BaseModule { +} +function formatMap(templateString, valueMap) { + // Use a regular expression to find all placeholders in the template string + const regex = /\{([^}]+)\}/g; + // Replace each placeholder with its corresponding value from the valueMap + return templateString.replace(regex, (match, key) => { + if (Object.prototype.hasOwnProperty.call(valueMap, key)) { + const value = valueMap[key]; + // Convert the value to a string if it's not a string already + return value !== undefined && value !== null ? String(value) : ''; + } + else { + // Handle missing keys + throw new Error(`Key '${key}' not found in valueMap.`); + } + }); +} +function setValueByPath(data, keys, value) { + for (let i = 0; i < keys.length - 1; i++) { + const key = keys[i]; + if (key.endsWith('[]')) { + const keyName = key.slice(0, -2); + if (!(keyName in data)) { + if (Array.isArray(value)) { + data[keyName] = Array.from({ length: value.length }, () => ({})); + } + else { + throw new Error(`Value must be a list given an array path ${key}`); + } + } + if (Array.isArray(data[keyName])) { + const arrayData = data[keyName]; + if (Array.isArray(value)) { + for (let j = 0; j < arrayData.length; j++) { + const entry = arrayData[j]; + setValueByPath(entry, keys.slice(i + 1), value[j]); + } + } + else { + for (const d of arrayData) { + setValueByPath(d, keys.slice(i + 1), value); + } + } + } + return; + } + else if (key.endsWith('[0]')) { + const keyName = key.slice(0, -3); + if (!(keyName in data)) { + data[keyName] = [{}]; + } + const arrayData = data[keyName]; + setValueByPath(arrayData[0], keys.slice(i + 1), value); + return; + } + if (!data[key] || typeof data[key] !== 'object') { + data[key] = {}; + } + data = data[key]; + } + const keyToSet = keys[keys.length - 1]; + const existingData = data[keyToSet]; + if (existingData !== undefined) { + if (!value || + (typeof value === 'object' && Object.keys(value).length === 0)) { + return; + } + if (value === existingData) { + return; + } + if (typeof existingData === 'object' && + typeof value === 'object' && + existingData !== null && + value !== null) { + Object.assign(existingData, value); + } + else { + throw new Error(`Cannot set value for an existing key. Key: ${keyToSet}`); + } + } + else { + if (keyToSet === '_self' && + typeof value === 'object' && + value !== null && + !Array.isArray(value)) { + const valueAsRecord = value; + Object.assign(data, valueAsRecord); + } + else { + data[keyToSet] = value; + } + } +} +function getValueByPath(data, keys, defaultValue = undefined) { + try { + if (keys.length === 1 && keys[0] === '_self') { + return data; + } + for (let i = 0; i < keys.length; i++) { + if (typeof data !== 'object' || data === null) { + return defaultValue; + } + const key = keys[i]; + if (key.endsWith('[]')) { + const keyName = key.slice(0, -2); + if (keyName in data) { + const arrayData = data[keyName]; + if (!Array.isArray(arrayData)) { + return defaultValue; + } + return arrayData.map((d) => getValueByPath(d, keys.slice(i + 1), defaultValue)); + } + else { + return defaultValue; + } + } + else { + data = data[key]; + } + } + return data; + } + catch (error) { + if (error instanceof TypeError) { + return defaultValue; + } + throw error; + } +} +/** + * Moves values from source paths to destination paths. + * + * Examples: + * moveValueByPath( + * {'requests': [{'content': v1}, {'content': v2}]}, + * {'requests[].*': 'requests[].request.*'} + * ) + * -> {'requests': [{'request': {'content': v1}}, {'request': {'content': v2}}]} + */ +function moveValueByPath(data, paths) { + for (const [sourcePath, destPath] of Object.entries(paths)) { + const sourceKeys = sourcePath.split('.'); + const destKeys = destPath.split('.'); + // Determine keys to exclude from wildcard to avoid cyclic references + const excludeKeys = new Set(); + let wildcardIdx = -1; + for (let i = 0; i < sourceKeys.length; i++) { + if (sourceKeys[i] === '*') { + wildcardIdx = i; + break; + } + } + if (wildcardIdx !== -1 && destKeys.length > wildcardIdx) { + // Extract the intermediate key between source and dest paths + // Example: source=['requests[]', '*'], dest=['requests[]', 'request', '*'] + // We want to exclude 'request' + for (let i = wildcardIdx; i < destKeys.length; i++) { + const key = destKeys[i]; + if (key !== '*' && !key.endsWith('[]') && !key.endsWith('[0]')) { + excludeKeys.add(key); + } + } + } + _moveValueRecursive(data, sourceKeys, destKeys, 0, excludeKeys); + } +} +/** + * Recursively moves values from source path to destination path. + */ +function _moveValueRecursive(data, sourceKeys, destKeys, keyIdx, excludeKeys) { + if (keyIdx >= sourceKeys.length) { + return; + } + if (typeof data !== 'object' || data === null) { + return; + } + const key = sourceKeys[keyIdx]; + if (key.endsWith('[]')) { + const keyName = key.slice(0, -2); + const dataRecord = data; + if (keyName in dataRecord && Array.isArray(dataRecord[keyName])) { + for (const item of dataRecord[keyName]) { + _moveValueRecursive(item, sourceKeys, destKeys, keyIdx + 1, excludeKeys); + } + } + } + else if (key === '*') { + // wildcard - move all fields + if (typeof data === 'object' && data !== null && !Array.isArray(data)) { + const dataRecord = data; + const keysToMove = Object.keys(dataRecord).filter((k) => !k.startsWith('_') && !excludeKeys.has(k)); + const valuesToMove = {}; + for (const k of keysToMove) { + valuesToMove[k] = dataRecord[k]; + } + // Set values at destination + for (const [k, v] of Object.entries(valuesToMove)) { + const newDestKeys = []; + for (const dk of destKeys.slice(keyIdx)) { + if (dk === '*') { + newDestKeys.push(k); + } + else { + newDestKeys.push(dk); + } + } + setValueByPath(dataRecord, newDestKeys, v); + } + for (const k of keysToMove) { + delete dataRecord[k]; + } + } + } + else { + // Navigate to next level + const dataRecord = data; + if (key in dataRecord) { + _moveValueRecursive(dataRecord[key], sourceKeys, destKeys, keyIdx + 1, excludeKeys); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function tBytes$1(fromBytes) { + if (typeof fromBytes !== 'string') { + throw new Error('fromImageBytes must be a string'); + } + // TODO(b/389133914): Remove dummy bytes converter. + return fromBytes; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Code generated by the Google Gen AI SDK generator DO NOT EDIT. +function fetchPredictOperationParametersToVertex(fromObject) { + const toObject = {}; + const fromOperationName = getValueByPath(fromObject, [ + 'operationName', + ]); + if (fromOperationName != null) { + setValueByPath(toObject, ['operationName'], fromOperationName); + } + const fromResourceName = getValueByPath(fromObject, ['resourceName']); + if (fromResourceName != null) { + setValueByPath(toObject, ['_url', 'resourceName'], fromResourceName); + } + return toObject; +} +function generateVideosOperationFromMldev$1(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromResponse = getValueByPath(fromObject, [ + 'response', + 'generateVideoResponse', + ]); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], generateVideosResponseFromMldev$1(fromResponse)); + } + return toObject; +} +function generateVideosOperationFromVertex$1(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], generateVideosResponseFromVertex$1(fromResponse)); + } + return toObject; +} +function generateVideosResponseFromMldev$1(fromObject) { + const toObject = {}; + const fromGeneratedVideos = getValueByPath(fromObject, [ + 'generatedSamples', + ]); + if (fromGeneratedVideos != null) { + let transformedList = fromGeneratedVideos; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedVideoFromMldev$1(item); + }); + } + setValueByPath(toObject, ['generatedVideos'], transformedList); + } + const fromRaiMediaFilteredCount = getValueByPath(fromObject, [ + 'raiMediaFilteredCount', + ]); + if (fromRaiMediaFilteredCount != null) { + setValueByPath(toObject, ['raiMediaFilteredCount'], fromRaiMediaFilteredCount); + } + const fromRaiMediaFilteredReasons = getValueByPath(fromObject, [ + 'raiMediaFilteredReasons', + ]); + if (fromRaiMediaFilteredReasons != null) { + setValueByPath(toObject, ['raiMediaFilteredReasons'], fromRaiMediaFilteredReasons); + } + return toObject; +} +function generateVideosResponseFromVertex$1(fromObject) { + const toObject = {}; + const fromGeneratedVideos = getValueByPath(fromObject, ['videos']); + if (fromGeneratedVideos != null) { + let transformedList = fromGeneratedVideos; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedVideoFromVertex$1(item); + }); + } + setValueByPath(toObject, ['generatedVideos'], transformedList); + } + const fromRaiMediaFilteredCount = getValueByPath(fromObject, [ + 'raiMediaFilteredCount', + ]); + if (fromRaiMediaFilteredCount != null) { + setValueByPath(toObject, ['raiMediaFilteredCount'], fromRaiMediaFilteredCount); + } + const fromRaiMediaFilteredReasons = getValueByPath(fromObject, [ + 'raiMediaFilteredReasons', + ]); + if (fromRaiMediaFilteredReasons != null) { + setValueByPath(toObject, ['raiMediaFilteredReasons'], fromRaiMediaFilteredReasons); + } + return toObject; +} +function generatedVideoFromMldev$1(fromObject) { + const toObject = {}; + const fromVideo = getValueByPath(fromObject, ['video']); + if (fromVideo != null) { + setValueByPath(toObject, ['video'], videoFromMldev$1(fromVideo)); + } + return toObject; +} +function generatedVideoFromVertex$1(fromObject) { + const toObject = {}; + const fromVideo = getValueByPath(fromObject, ['_self']); + if (fromVideo != null) { + setValueByPath(toObject, ['video'], videoFromVertex$1(fromVideo)); + } + return toObject; +} +function getOperationParametersToMldev(fromObject) { + const toObject = {}; + const fromOperationName = getValueByPath(fromObject, [ + 'operationName', + ]); + if (fromOperationName != null) { + setValueByPath(toObject, ['_url', 'operationName'], fromOperationName); + } + return toObject; +} +function getOperationParametersToVertex(fromObject) { + const toObject = {}; + const fromOperationName = getValueByPath(fromObject, [ + 'operationName', + ]); + if (fromOperationName != null) { + setValueByPath(toObject, ['_url', 'operationName'], fromOperationName); + } + return toObject; +} +function importFileOperationFromMldev$1(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], importFileResponseFromMldev$1(fromResponse)); + } + return toObject; +} +function importFileResponseFromMldev$1(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromParent = getValueByPath(fromObject, ['parent']); + if (fromParent != null) { + setValueByPath(toObject, ['parent'], fromParent); + } + const fromDocumentName = getValueByPath(fromObject, ['documentName']); + if (fromDocumentName != null) { + setValueByPath(toObject, ['documentName'], fromDocumentName); + } + return toObject; +} +function uploadToFileSearchStoreOperationFromMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], uploadToFileSearchStoreResponseFromMldev(fromResponse)); + } + return toObject; +} +function uploadToFileSearchStoreResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromParent = getValueByPath(fromObject, ['parent']); + if (fromParent != null) { + setValueByPath(toObject, ['parent'], fromParent); + } + const fromDocumentName = getValueByPath(fromObject, ['documentName']); + if (fromDocumentName != null) { + setValueByPath(toObject, ['documentName'], fromDocumentName); + } + return toObject; +} +function videoFromMldev$1(fromObject) { + const toObject = {}; + const fromUri = getValueByPath(fromObject, ['uri']); + if (fromUri != null) { + setValueByPath(toObject, ['uri'], fromUri); + } + const fromVideoBytes = getValueByPath(fromObject, ['encodedVideo']); + if (fromVideoBytes != null) { + setValueByPath(toObject, ['videoBytes'], tBytes$1(fromVideoBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['encoding']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function videoFromVertex$1(fromObject) { + const toObject = {}; + const fromUri = getValueByPath(fromObject, ['gcsUri']); + if (fromUri != null) { + setValueByPath(toObject, ['uri'], fromUri); + } + const fromVideoBytes = getValueByPath(fromObject, [ + 'bytesBase64Encoded', + ]); + if (fromVideoBytes != null) { + setValueByPath(toObject, ['videoBytes'], tBytes$1(fromVideoBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** Outcome of the code execution. */ +var Outcome; +(function (Outcome) { + /** + * Unspecified status. This value should not be used. + */ + Outcome["OUTCOME_UNSPECIFIED"] = "OUTCOME_UNSPECIFIED"; + /** + * Code execution completed successfully. + */ + Outcome["OUTCOME_OK"] = "OUTCOME_OK"; + /** + * Code execution finished but with a failure. `stderr` should contain the reason. + */ + Outcome["OUTCOME_FAILED"] = "OUTCOME_FAILED"; + /** + * Code execution ran for too long, and was cancelled. There may or may not be a partial output present. + */ + Outcome["OUTCOME_DEADLINE_EXCEEDED"] = "OUTCOME_DEADLINE_EXCEEDED"; +})(Outcome || (Outcome = {})); +/** Programming language of the `code`. */ +var Language; +(function (Language) { + /** + * Unspecified language. This value should not be used. + */ + Language["LANGUAGE_UNSPECIFIED"] = "LANGUAGE_UNSPECIFIED"; + /** + * Python >= 3.10, with numpy and simpy available. + */ + Language["PYTHON"] = "PYTHON"; +})(Language || (Language = {})); +/** Specifies how the response should be scheduled in the conversation. */ +var FunctionResponseScheduling; +(function (FunctionResponseScheduling) { + /** + * This value is unused. + */ + FunctionResponseScheduling["SCHEDULING_UNSPECIFIED"] = "SCHEDULING_UNSPECIFIED"; + /** + * Only add the result to the conversation context, do not interrupt or trigger generation. + */ + FunctionResponseScheduling["SILENT"] = "SILENT"; + /** + * Add the result to the conversation context, and prompt to generate output without interrupting ongoing generation. + */ + FunctionResponseScheduling["WHEN_IDLE"] = "WHEN_IDLE"; + /** + * Add the result to the conversation context, interrupt ongoing generation and prompt to generate output. + */ + FunctionResponseScheduling["INTERRUPT"] = "INTERRUPT"; +})(FunctionResponseScheduling || (FunctionResponseScheduling = {})); +/** The type of the data. */ +var Type; +(function (Type) { + /** + * Not specified, should not be used. + */ + Type["TYPE_UNSPECIFIED"] = "TYPE_UNSPECIFIED"; + /** + * OpenAPI string type + */ + Type["STRING"] = "STRING"; + /** + * OpenAPI number type + */ + Type["NUMBER"] = "NUMBER"; + /** + * OpenAPI integer type + */ + Type["INTEGER"] = "INTEGER"; + /** + * OpenAPI boolean type + */ + Type["BOOLEAN"] = "BOOLEAN"; + /** + * OpenAPI array type + */ + Type["ARRAY"] = "ARRAY"; + /** + * OpenAPI object type + */ + Type["OBJECT"] = "OBJECT"; + /** + * Null type + */ + Type["NULL"] = "NULL"; +})(Type || (Type = {})); +/** The API spec that the external API implements. This enum is not supported in Gemini API. */ +var ApiSpec; +(function (ApiSpec) { + /** + * Unspecified API spec. This value should not be used. + */ + ApiSpec["API_SPEC_UNSPECIFIED"] = "API_SPEC_UNSPECIFIED"; + /** + * Simple search API spec. + */ + ApiSpec["SIMPLE_SEARCH"] = "SIMPLE_SEARCH"; + /** + * Elastic search API spec. + */ + ApiSpec["ELASTIC_SEARCH"] = "ELASTIC_SEARCH"; +})(ApiSpec || (ApiSpec = {})); +/** Type of auth scheme. This enum is not supported in Gemini API. */ +var AuthType; +(function (AuthType) { + AuthType["AUTH_TYPE_UNSPECIFIED"] = "AUTH_TYPE_UNSPECIFIED"; + /** + * No Auth. + */ + AuthType["NO_AUTH"] = "NO_AUTH"; + /** + * API Key Auth. + */ + AuthType["API_KEY_AUTH"] = "API_KEY_AUTH"; + /** + * HTTP Basic Auth. + */ + AuthType["HTTP_BASIC_AUTH"] = "HTTP_BASIC_AUTH"; + /** + * Google Service Account Auth. + */ + AuthType["GOOGLE_SERVICE_ACCOUNT_AUTH"] = "GOOGLE_SERVICE_ACCOUNT_AUTH"; + /** + * OAuth auth. + */ + AuthType["OAUTH"] = "OAUTH"; + /** + * OpenID Connect (OIDC) Auth. + */ + AuthType["OIDC_AUTH"] = "OIDC_AUTH"; +})(AuthType || (AuthType = {})); +/** The location of the API key. This enum is not supported in Gemini API. */ +var HttpElementLocation; +(function (HttpElementLocation) { + HttpElementLocation["HTTP_IN_UNSPECIFIED"] = "HTTP_IN_UNSPECIFIED"; + /** + * Element is in the HTTP request query. + */ + HttpElementLocation["HTTP_IN_QUERY"] = "HTTP_IN_QUERY"; + /** + * Element is in the HTTP request header. + */ + HttpElementLocation["HTTP_IN_HEADER"] = "HTTP_IN_HEADER"; + /** + * Element is in the HTTP request path. + */ + HttpElementLocation["HTTP_IN_PATH"] = "HTTP_IN_PATH"; + /** + * Element is in the HTTP request body. + */ + HttpElementLocation["HTTP_IN_BODY"] = "HTTP_IN_BODY"; + /** + * Element is in the HTTP request cookie. + */ + HttpElementLocation["HTTP_IN_COOKIE"] = "HTTP_IN_COOKIE"; +})(HttpElementLocation || (HttpElementLocation = {})); +/** Sites with confidence level chosen & above this value will be blocked from the search results. This enum is not supported in Gemini API. */ +var PhishBlockThreshold; +(function (PhishBlockThreshold) { + /** + * Defaults to unspecified. + */ + PhishBlockThreshold["PHISH_BLOCK_THRESHOLD_UNSPECIFIED"] = "PHISH_BLOCK_THRESHOLD_UNSPECIFIED"; + /** + * Blocks Low and above confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_LOW_AND_ABOVE"] = "BLOCK_LOW_AND_ABOVE"; + /** + * Blocks Medium and above confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_MEDIUM_AND_ABOVE"] = "BLOCK_MEDIUM_AND_ABOVE"; + /** + * Blocks High and above confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_HIGH_AND_ABOVE"] = "BLOCK_HIGH_AND_ABOVE"; + /** + * Blocks Higher and above confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_HIGHER_AND_ABOVE"] = "BLOCK_HIGHER_AND_ABOVE"; + /** + * Blocks Very high and above confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_VERY_HIGH_AND_ABOVE"] = "BLOCK_VERY_HIGH_AND_ABOVE"; + /** + * Blocks Extremely high confidence URL that is risky. + */ + PhishBlockThreshold["BLOCK_ONLY_EXTREMELY_HIGH"] = "BLOCK_ONLY_EXTREMELY_HIGH"; +})(PhishBlockThreshold || (PhishBlockThreshold = {})); +/** Specifies the function Behavior. Currently only supported by the BidiGenerateContent method. This enum is not supported in Vertex AI. */ +var Behavior; +(function (Behavior) { + /** + * This value is unused. + */ + Behavior["UNSPECIFIED"] = "UNSPECIFIED"; + /** + * If set, the system will wait to receive the function response before continuing the conversation. + */ + Behavior["BLOCKING"] = "BLOCKING"; + /** + * If set, the system will not wait to receive the function response. Instead, it will attempt to handle function responses as they become available while maintaining the conversation between the user and the model. + */ + Behavior["NON_BLOCKING"] = "NON_BLOCKING"; +})(Behavior || (Behavior = {})); +/** The mode of the predictor to be used in dynamic retrieval. */ +var DynamicRetrievalConfigMode; +(function (DynamicRetrievalConfigMode) { + /** + * Always trigger retrieval. + */ + DynamicRetrievalConfigMode["MODE_UNSPECIFIED"] = "MODE_UNSPECIFIED"; + /** + * Run retrieval only when system decides it is necessary. + */ + DynamicRetrievalConfigMode["MODE_DYNAMIC"] = "MODE_DYNAMIC"; +})(DynamicRetrievalConfigMode || (DynamicRetrievalConfigMode = {})); +/** Function calling mode. */ +var FunctionCallingConfigMode; +(function (FunctionCallingConfigMode) { + /** + * Unspecified function calling mode. This value should not be used. + */ + FunctionCallingConfigMode["MODE_UNSPECIFIED"] = "MODE_UNSPECIFIED"; + /** + * Default model behavior, model decides to predict either function calls or natural language response. + */ + FunctionCallingConfigMode["AUTO"] = "AUTO"; + /** + * Model is constrained to always predicting function calls only. If "allowed_function_names" are set, the predicted function calls will be limited to any one of "allowed_function_names", else the predicted function calls will be any one of the provided "function_declarations". + */ + FunctionCallingConfigMode["ANY"] = "ANY"; + /** + * Model will not predict any function calls. Model behavior is same as when not passing any function declarations. + */ + FunctionCallingConfigMode["NONE"] = "NONE"; + /** + * Model is constrained to predict either function calls or natural language response. If "allowed_function_names" are set, the predicted function calls will be limited to any one of "allowed_function_names", else the predicted function calls will be any one of the provided "function_declarations". + */ + FunctionCallingConfigMode["VALIDATED"] = "VALIDATED"; +})(FunctionCallingConfigMode || (FunctionCallingConfigMode = {})); +/** The number of thoughts tokens that the model should generate. */ +var ThinkingLevel; +(function (ThinkingLevel) { + /** + * Unspecified thinking level. + */ + ThinkingLevel["THINKING_LEVEL_UNSPECIFIED"] = "THINKING_LEVEL_UNSPECIFIED"; + /** + * Low thinking level. + */ + ThinkingLevel["LOW"] = "LOW"; + /** + * Medium thinking level. + */ + ThinkingLevel["MEDIUM"] = "MEDIUM"; + /** + * High thinking level. + */ + ThinkingLevel["HIGH"] = "HIGH"; + /** + * MINIMAL thinking level. + */ + ThinkingLevel["MINIMAL"] = "MINIMAL"; +})(ThinkingLevel || (ThinkingLevel = {})); +/** Harm category. */ +var HarmCategory; +(function (HarmCategory) { + /** + * The harm category is unspecified. + */ + HarmCategory["HARM_CATEGORY_UNSPECIFIED"] = "HARM_CATEGORY_UNSPECIFIED"; + /** + * The harm category is harassment. + */ + HarmCategory["HARM_CATEGORY_HARASSMENT"] = "HARM_CATEGORY_HARASSMENT"; + /** + * The harm category is hate speech. + */ + HarmCategory["HARM_CATEGORY_HATE_SPEECH"] = "HARM_CATEGORY_HATE_SPEECH"; + /** + * The harm category is sexually explicit content. + */ + HarmCategory["HARM_CATEGORY_SEXUALLY_EXPLICIT"] = "HARM_CATEGORY_SEXUALLY_EXPLICIT"; + /** + * The harm category is dangerous content. + */ + HarmCategory["HARM_CATEGORY_DANGEROUS_CONTENT"] = "HARM_CATEGORY_DANGEROUS_CONTENT"; + /** + * Deprecated: Election filter is not longer supported. The harm category is civic integrity. + */ + HarmCategory["HARM_CATEGORY_CIVIC_INTEGRITY"] = "HARM_CATEGORY_CIVIC_INTEGRITY"; + /** + * The harm category is image hate. This enum value is not supported in Gemini API. + */ + HarmCategory["HARM_CATEGORY_IMAGE_HATE"] = "HARM_CATEGORY_IMAGE_HATE"; + /** + * The harm category is image dangerous content. This enum value is not supported in Gemini API. + */ + HarmCategory["HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT"] = "HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT"; + /** + * The harm category is image harassment. This enum value is not supported in Gemini API. + */ + HarmCategory["HARM_CATEGORY_IMAGE_HARASSMENT"] = "HARM_CATEGORY_IMAGE_HARASSMENT"; + /** + * The harm category is image sexually explicit content. This enum value is not supported in Gemini API. + */ + HarmCategory["HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT"] = "HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT"; + /** + * The harm category is for jailbreak prompts. This enum value is not supported in Gemini API. + */ + HarmCategory["HARM_CATEGORY_JAILBREAK"] = "HARM_CATEGORY_JAILBREAK"; +})(HarmCategory || (HarmCategory = {})); +/** Specify if the threshold is used for probability or severity score. If not specified, the threshold is used for probability score. This enum is not supported in Gemini API. */ +var HarmBlockMethod; +(function (HarmBlockMethod) { + /** + * The harm block method is unspecified. + */ + HarmBlockMethod["HARM_BLOCK_METHOD_UNSPECIFIED"] = "HARM_BLOCK_METHOD_UNSPECIFIED"; + /** + * The harm block method uses both probability and severity scores. + */ + HarmBlockMethod["SEVERITY"] = "SEVERITY"; + /** + * The harm block method uses the probability score. + */ + HarmBlockMethod["PROBABILITY"] = "PROBABILITY"; +})(HarmBlockMethod || (HarmBlockMethod = {})); +/** The harm block threshold. */ +var HarmBlockThreshold; +(function (HarmBlockThreshold) { + /** + * Unspecified harm block threshold. + */ + HarmBlockThreshold["HARM_BLOCK_THRESHOLD_UNSPECIFIED"] = "HARM_BLOCK_THRESHOLD_UNSPECIFIED"; + /** + * Block low threshold and above (i.e. block more). + */ + HarmBlockThreshold["BLOCK_LOW_AND_ABOVE"] = "BLOCK_LOW_AND_ABOVE"; + /** + * Block medium threshold and above. + */ + HarmBlockThreshold["BLOCK_MEDIUM_AND_ABOVE"] = "BLOCK_MEDIUM_AND_ABOVE"; + /** + * Block only high threshold (i.e. block less). + */ + HarmBlockThreshold["BLOCK_ONLY_HIGH"] = "BLOCK_ONLY_HIGH"; + /** + * Block none. + */ + HarmBlockThreshold["BLOCK_NONE"] = "BLOCK_NONE"; + /** + * Turn off the safety filter. + */ + HarmBlockThreshold["OFF"] = "OFF"; +})(HarmBlockThreshold || (HarmBlockThreshold = {})); +/** Output only. The reason why the model stopped generating tokens. + +If empty, the model has not stopped generating the tokens. */ +var FinishReason; +(function (FinishReason) { + /** + * The finish reason is unspecified. + */ + FinishReason["FINISH_REASON_UNSPECIFIED"] = "FINISH_REASON_UNSPECIFIED"; + /** + * Token generation reached a natural stopping point or a configured stop sequence. + */ + FinishReason["STOP"] = "STOP"; + /** + * Token generation reached the configured maximum output tokens. + */ + FinishReason["MAX_TOKENS"] = "MAX_TOKENS"; + /** + * Token generation stopped because the content potentially contains safety violations. NOTE: When streaming, [content][] is empty if content filters blocks the output. + */ + FinishReason["SAFETY"] = "SAFETY"; + /** + * The token generation stopped because of potential recitation. + */ + FinishReason["RECITATION"] = "RECITATION"; + /** + * The token generation stopped because of using an unsupported language. + */ + FinishReason["LANGUAGE"] = "LANGUAGE"; + /** + * All other reasons that stopped the token generation. + */ + FinishReason["OTHER"] = "OTHER"; + /** + * Token generation stopped because the content contains forbidden terms. + */ + FinishReason["BLOCKLIST"] = "BLOCKLIST"; + /** + * Token generation stopped for potentially containing prohibited content. + */ + FinishReason["PROHIBITED_CONTENT"] = "PROHIBITED_CONTENT"; + /** + * Token generation stopped because the content potentially contains Sensitive Personally Identifiable Information (SPII). + */ + FinishReason["SPII"] = "SPII"; + /** + * The function call generated by the model is invalid. + */ + FinishReason["MALFORMED_FUNCTION_CALL"] = "MALFORMED_FUNCTION_CALL"; + /** + * Token generation stopped because generated images have safety violations. + */ + FinishReason["IMAGE_SAFETY"] = "IMAGE_SAFETY"; + /** + * The tool call generated by the model is invalid. + */ + FinishReason["UNEXPECTED_TOOL_CALL"] = "UNEXPECTED_TOOL_CALL"; + /** + * Image generation stopped because the generated images have prohibited content. + */ + FinishReason["IMAGE_PROHIBITED_CONTENT"] = "IMAGE_PROHIBITED_CONTENT"; + /** + * The model was expected to generate an image, but none was generated. + */ + FinishReason["NO_IMAGE"] = "NO_IMAGE"; + /** + * Image generation stopped because the generated image may be a recitation from a source. + */ + FinishReason["IMAGE_RECITATION"] = "IMAGE_RECITATION"; + /** + * Image generation stopped for a reason not otherwise specified. + */ + FinishReason["IMAGE_OTHER"] = "IMAGE_OTHER"; +})(FinishReason || (FinishReason = {})); +/** Output only. Harm probability levels in the content. */ +var HarmProbability; +(function (HarmProbability) { + /** + * Harm probability unspecified. + */ + HarmProbability["HARM_PROBABILITY_UNSPECIFIED"] = "HARM_PROBABILITY_UNSPECIFIED"; + /** + * Negligible level of harm. + */ + HarmProbability["NEGLIGIBLE"] = "NEGLIGIBLE"; + /** + * Low level of harm. + */ + HarmProbability["LOW"] = "LOW"; + /** + * Medium level of harm. + */ + HarmProbability["MEDIUM"] = "MEDIUM"; + /** + * High level of harm. + */ + HarmProbability["HIGH"] = "HIGH"; +})(HarmProbability || (HarmProbability = {})); +/** Output only. Harm severity levels in the content. This enum is not supported in Gemini API. */ +var HarmSeverity; +(function (HarmSeverity) { + /** + * Harm severity unspecified. + */ + HarmSeverity["HARM_SEVERITY_UNSPECIFIED"] = "HARM_SEVERITY_UNSPECIFIED"; + /** + * Negligible level of harm severity. + */ + HarmSeverity["HARM_SEVERITY_NEGLIGIBLE"] = "HARM_SEVERITY_NEGLIGIBLE"; + /** + * Low level of harm severity. + */ + HarmSeverity["HARM_SEVERITY_LOW"] = "HARM_SEVERITY_LOW"; + /** + * Medium level of harm severity. + */ + HarmSeverity["HARM_SEVERITY_MEDIUM"] = "HARM_SEVERITY_MEDIUM"; + /** + * High level of harm severity. + */ + HarmSeverity["HARM_SEVERITY_HIGH"] = "HARM_SEVERITY_HIGH"; +})(HarmSeverity || (HarmSeverity = {})); +/** Status of the url retrieval. */ +var UrlRetrievalStatus; +(function (UrlRetrievalStatus) { + /** + * Default value. This value is unused. + */ + UrlRetrievalStatus["URL_RETRIEVAL_STATUS_UNSPECIFIED"] = "URL_RETRIEVAL_STATUS_UNSPECIFIED"; + /** + * Url retrieval is successful. + */ + UrlRetrievalStatus["URL_RETRIEVAL_STATUS_SUCCESS"] = "URL_RETRIEVAL_STATUS_SUCCESS"; + /** + * Url retrieval is failed due to error. + */ + UrlRetrievalStatus["URL_RETRIEVAL_STATUS_ERROR"] = "URL_RETRIEVAL_STATUS_ERROR"; + /** + * Url retrieval is failed because the content is behind paywall. This enum value is not supported in Vertex AI. + */ + UrlRetrievalStatus["URL_RETRIEVAL_STATUS_PAYWALL"] = "URL_RETRIEVAL_STATUS_PAYWALL"; + /** + * Url retrieval is failed because the content is unsafe. This enum value is not supported in Vertex AI. + */ + UrlRetrievalStatus["URL_RETRIEVAL_STATUS_UNSAFE"] = "URL_RETRIEVAL_STATUS_UNSAFE"; +})(UrlRetrievalStatus || (UrlRetrievalStatus = {})); +/** Output only. The reason why the prompt was blocked. */ +var BlockedReason; +(function (BlockedReason) { + /** + * The blocked reason is unspecified. + */ + BlockedReason["BLOCKED_REASON_UNSPECIFIED"] = "BLOCKED_REASON_UNSPECIFIED"; + /** + * The prompt was blocked for safety reasons. + */ + BlockedReason["SAFETY"] = "SAFETY"; + /** + * The prompt was blocked for other reasons. For example, it may be due to the prompt's language, or because it contains other harmful content. + */ + BlockedReason["OTHER"] = "OTHER"; + /** + * The prompt was blocked because it contains a term from the terminology blocklist. + */ + BlockedReason["BLOCKLIST"] = "BLOCKLIST"; + /** + * The prompt was blocked because it contains prohibited content. + */ + BlockedReason["PROHIBITED_CONTENT"] = "PROHIBITED_CONTENT"; + /** + * The prompt was blocked because it contains content that is unsafe for image generation. + */ + BlockedReason["IMAGE_SAFETY"] = "IMAGE_SAFETY"; + /** + * The prompt was blocked by Model Armor. This enum value is not supported in Gemini API. + */ + BlockedReason["MODEL_ARMOR"] = "MODEL_ARMOR"; + /** + * The prompt was blocked as a jailbreak attempt. This enum value is not supported in Gemini API. + */ + BlockedReason["JAILBREAK"] = "JAILBREAK"; +})(BlockedReason || (BlockedReason = {})); +/** Output only. The traffic type for this request. This enum is not supported in Gemini API. */ +var TrafficType; +(function (TrafficType) { + /** + * Unspecified request traffic type. + */ + TrafficType["TRAFFIC_TYPE_UNSPECIFIED"] = "TRAFFIC_TYPE_UNSPECIFIED"; + /** + * The request was processed using Pay-As-You-Go quota. + */ + TrafficType["ON_DEMAND"] = "ON_DEMAND"; + /** + * Type for Provisioned Throughput traffic. + */ + TrafficType["PROVISIONED_THROUGHPUT"] = "PROVISIONED_THROUGHPUT"; +})(TrafficType || (TrafficType = {})); +/** Server content modalities. */ +var Modality; +(function (Modality) { + /** + * The modality is unspecified. + */ + Modality["MODALITY_UNSPECIFIED"] = "MODALITY_UNSPECIFIED"; + /** + * Indicates the model should return text + */ + Modality["TEXT"] = "TEXT"; + /** + * Indicates the model should return images. + */ + Modality["IMAGE"] = "IMAGE"; + /** + * Indicates the model should return audio. + */ + Modality["AUDIO"] = "AUDIO"; +})(Modality || (Modality = {})); +/** The media resolution to use. */ +var MediaResolution; +(function (MediaResolution) { + /** + * Media resolution has not been set + */ + MediaResolution["MEDIA_RESOLUTION_UNSPECIFIED"] = "MEDIA_RESOLUTION_UNSPECIFIED"; + /** + * Media resolution set to low (64 tokens). + */ + MediaResolution["MEDIA_RESOLUTION_LOW"] = "MEDIA_RESOLUTION_LOW"; + /** + * Media resolution set to medium (256 tokens). + */ + MediaResolution["MEDIA_RESOLUTION_MEDIUM"] = "MEDIA_RESOLUTION_MEDIUM"; + /** + * Media resolution set to high (zoomed reframing with 256 tokens). + */ + MediaResolution["MEDIA_RESOLUTION_HIGH"] = "MEDIA_RESOLUTION_HIGH"; +})(MediaResolution || (MediaResolution = {})); +/** Tuning mode. This enum is not supported in Gemini API. */ +var TuningMode; +(function (TuningMode) { + /** + * Tuning mode is unspecified. + */ + TuningMode["TUNING_MODE_UNSPECIFIED"] = "TUNING_MODE_UNSPECIFIED"; + /** + * Full fine-tuning mode. + */ + TuningMode["TUNING_MODE_FULL"] = "TUNING_MODE_FULL"; + /** + * PEFT adapter tuning mode. + */ + TuningMode["TUNING_MODE_PEFT_ADAPTER"] = "TUNING_MODE_PEFT_ADAPTER"; +})(TuningMode || (TuningMode = {})); +/** Adapter size for tuning. This enum is not supported in Gemini API. */ +var AdapterSize; +(function (AdapterSize) { + /** + * Adapter size is unspecified. + */ + AdapterSize["ADAPTER_SIZE_UNSPECIFIED"] = "ADAPTER_SIZE_UNSPECIFIED"; + /** + * Adapter size 1. + */ + AdapterSize["ADAPTER_SIZE_ONE"] = "ADAPTER_SIZE_ONE"; + /** + * Adapter size 2. + */ + AdapterSize["ADAPTER_SIZE_TWO"] = "ADAPTER_SIZE_TWO"; + /** + * Adapter size 4. + */ + AdapterSize["ADAPTER_SIZE_FOUR"] = "ADAPTER_SIZE_FOUR"; + /** + * Adapter size 8. + */ + AdapterSize["ADAPTER_SIZE_EIGHT"] = "ADAPTER_SIZE_EIGHT"; + /** + * Adapter size 16. + */ + AdapterSize["ADAPTER_SIZE_SIXTEEN"] = "ADAPTER_SIZE_SIXTEEN"; + /** + * Adapter size 32. + */ + AdapterSize["ADAPTER_SIZE_THIRTY_TWO"] = "ADAPTER_SIZE_THIRTY_TWO"; +})(AdapterSize || (AdapterSize = {})); +/** Job state. */ +var JobState; +(function (JobState) { + /** + * The job state is unspecified. + */ + JobState["JOB_STATE_UNSPECIFIED"] = "JOB_STATE_UNSPECIFIED"; + /** + * The job has been just created or resumed and processing has not yet begun. + */ + JobState["JOB_STATE_QUEUED"] = "JOB_STATE_QUEUED"; + /** + * The service is preparing to run the job. + */ + JobState["JOB_STATE_PENDING"] = "JOB_STATE_PENDING"; + /** + * The job is in progress. + */ + JobState["JOB_STATE_RUNNING"] = "JOB_STATE_RUNNING"; + /** + * The job completed successfully. + */ + JobState["JOB_STATE_SUCCEEDED"] = "JOB_STATE_SUCCEEDED"; + /** + * The job failed. + */ + JobState["JOB_STATE_FAILED"] = "JOB_STATE_FAILED"; + /** + * The job is being cancelled. From this state the job may only go to either `JOB_STATE_SUCCEEDED`, `JOB_STATE_FAILED` or `JOB_STATE_CANCELLED`. + */ + JobState["JOB_STATE_CANCELLING"] = "JOB_STATE_CANCELLING"; + /** + * The job has been cancelled. + */ + JobState["JOB_STATE_CANCELLED"] = "JOB_STATE_CANCELLED"; + /** + * The job has been stopped, and can be resumed. + */ + JobState["JOB_STATE_PAUSED"] = "JOB_STATE_PAUSED"; + /** + * The job has expired. + */ + JobState["JOB_STATE_EXPIRED"] = "JOB_STATE_EXPIRED"; + /** + * The job is being updated. Only jobs in the `JOB_STATE_RUNNING` state can be updated. After updating, the job goes back to the `JOB_STATE_RUNNING` state. + */ + JobState["JOB_STATE_UPDATING"] = "JOB_STATE_UPDATING"; + /** + * The job is partially succeeded, some results may be missing due to errors. + */ + JobState["JOB_STATE_PARTIALLY_SUCCEEDED"] = "JOB_STATE_PARTIALLY_SUCCEEDED"; +})(JobState || (JobState = {})); +/** The tuning task. Either I2V or T2V. This enum is not supported in Gemini API. */ +var TuningTask; +(function (TuningTask) { + /** + * Default value. This value is unused. + */ + TuningTask["TUNING_TASK_UNSPECIFIED"] = "TUNING_TASK_UNSPECIFIED"; + /** + * Tuning task for image to video. + */ + TuningTask["TUNING_TASK_I2V"] = "TUNING_TASK_I2V"; + /** + * Tuning task for text to video. + */ + TuningTask["TUNING_TASK_T2V"] = "TUNING_TASK_T2V"; + /** + * Tuning task for reference to video. + */ + TuningTask["TUNING_TASK_R2V"] = "TUNING_TASK_R2V"; +})(TuningTask || (TuningTask = {})); +/** The tokenization quality used for given media. */ +var PartMediaResolutionLevel; +(function (PartMediaResolutionLevel) { + /** + * Media resolution has not been set. + */ + PartMediaResolutionLevel["MEDIA_RESOLUTION_UNSPECIFIED"] = "MEDIA_RESOLUTION_UNSPECIFIED"; + /** + * Media resolution set to low. + */ + PartMediaResolutionLevel["MEDIA_RESOLUTION_LOW"] = "MEDIA_RESOLUTION_LOW"; + /** + * Media resolution set to medium. + */ + PartMediaResolutionLevel["MEDIA_RESOLUTION_MEDIUM"] = "MEDIA_RESOLUTION_MEDIUM"; + /** + * Media resolution set to high. + */ + PartMediaResolutionLevel["MEDIA_RESOLUTION_HIGH"] = "MEDIA_RESOLUTION_HIGH"; + /** + * Media resolution set to ultra high. + */ + PartMediaResolutionLevel["MEDIA_RESOLUTION_ULTRA_HIGH"] = "MEDIA_RESOLUTION_ULTRA_HIGH"; +})(PartMediaResolutionLevel || (PartMediaResolutionLevel = {})); +/** Resource scope. */ +var ResourceScope; +(function (ResourceScope) { + /** + * When setting base_url, this value configures resource scope to be the collection. + The resource name will not include api version, project, or location. + For example, if base_url is set to "https://aiplatform.googleapis.com", + then the resource name for a Model would be + "https://aiplatform.googleapis.com/publishers/google/models/gemini-3-pro-preview + */ + ResourceScope["COLLECTION"] = "COLLECTION"; +})(ResourceScope || (ResourceScope = {})); +/** Options for feature selection preference. */ +var FeatureSelectionPreference; +(function (FeatureSelectionPreference) { + FeatureSelectionPreference["FEATURE_SELECTION_PREFERENCE_UNSPECIFIED"] = "FEATURE_SELECTION_PREFERENCE_UNSPECIFIED"; + FeatureSelectionPreference["PRIORITIZE_QUALITY"] = "PRIORITIZE_QUALITY"; + FeatureSelectionPreference["BALANCED"] = "BALANCED"; + FeatureSelectionPreference["PRIORITIZE_COST"] = "PRIORITIZE_COST"; +})(FeatureSelectionPreference || (FeatureSelectionPreference = {})); +/** The environment being operated. */ +var Environment; +(function (Environment) { + /** + * Defaults to browser. + */ + Environment["ENVIRONMENT_UNSPECIFIED"] = "ENVIRONMENT_UNSPECIFIED"; + /** + * Operates in a web browser. + */ + Environment["ENVIRONMENT_BROWSER"] = "ENVIRONMENT_BROWSER"; +})(Environment || (Environment = {})); +/** Enum that controls the safety filter level for objectionable content. */ +var SafetyFilterLevel; +(function (SafetyFilterLevel) { + SafetyFilterLevel["BLOCK_LOW_AND_ABOVE"] = "BLOCK_LOW_AND_ABOVE"; + SafetyFilterLevel["BLOCK_MEDIUM_AND_ABOVE"] = "BLOCK_MEDIUM_AND_ABOVE"; + SafetyFilterLevel["BLOCK_ONLY_HIGH"] = "BLOCK_ONLY_HIGH"; + SafetyFilterLevel["BLOCK_NONE"] = "BLOCK_NONE"; +})(SafetyFilterLevel || (SafetyFilterLevel = {})); +/** Enum that controls the generation of people. */ +var PersonGeneration; +(function (PersonGeneration) { + /** + * Block generation of images of people. + */ + PersonGeneration["DONT_ALLOW"] = "DONT_ALLOW"; + /** + * Generate images of adults, but not children. + */ + PersonGeneration["ALLOW_ADULT"] = "ALLOW_ADULT"; + /** + * Generate images that include adults and children. + */ + PersonGeneration["ALLOW_ALL"] = "ALLOW_ALL"; +})(PersonGeneration || (PersonGeneration = {})); +/** Enum that specifies the language of the text in the prompt. */ +var ImagePromptLanguage; +(function (ImagePromptLanguage) { + /** + * Auto-detect the language. + */ + ImagePromptLanguage["auto"] = "auto"; + /** + * English + */ + ImagePromptLanguage["en"] = "en"; + /** + * Japanese + */ + ImagePromptLanguage["ja"] = "ja"; + /** + * Korean + */ + ImagePromptLanguage["ko"] = "ko"; + /** + * Hindi + */ + ImagePromptLanguage["hi"] = "hi"; + /** + * Chinese + */ + ImagePromptLanguage["zh"] = "zh"; + /** + * Portuguese + */ + ImagePromptLanguage["pt"] = "pt"; + /** + * Spanish + */ + ImagePromptLanguage["es"] = "es"; +})(ImagePromptLanguage || (ImagePromptLanguage = {})); +/** Enum representing the mask mode of a mask reference image. */ +var MaskReferenceMode; +(function (MaskReferenceMode) { + MaskReferenceMode["MASK_MODE_DEFAULT"] = "MASK_MODE_DEFAULT"; + MaskReferenceMode["MASK_MODE_USER_PROVIDED"] = "MASK_MODE_USER_PROVIDED"; + MaskReferenceMode["MASK_MODE_BACKGROUND"] = "MASK_MODE_BACKGROUND"; + MaskReferenceMode["MASK_MODE_FOREGROUND"] = "MASK_MODE_FOREGROUND"; + MaskReferenceMode["MASK_MODE_SEMANTIC"] = "MASK_MODE_SEMANTIC"; +})(MaskReferenceMode || (MaskReferenceMode = {})); +/** Enum representing the control type of a control reference image. */ +var ControlReferenceType; +(function (ControlReferenceType) { + ControlReferenceType["CONTROL_TYPE_DEFAULT"] = "CONTROL_TYPE_DEFAULT"; + ControlReferenceType["CONTROL_TYPE_CANNY"] = "CONTROL_TYPE_CANNY"; + ControlReferenceType["CONTROL_TYPE_SCRIBBLE"] = "CONTROL_TYPE_SCRIBBLE"; + ControlReferenceType["CONTROL_TYPE_FACE_MESH"] = "CONTROL_TYPE_FACE_MESH"; +})(ControlReferenceType || (ControlReferenceType = {})); +/** Enum representing the subject type of a subject reference image. */ +var SubjectReferenceType; +(function (SubjectReferenceType) { + SubjectReferenceType["SUBJECT_TYPE_DEFAULT"] = "SUBJECT_TYPE_DEFAULT"; + SubjectReferenceType["SUBJECT_TYPE_PERSON"] = "SUBJECT_TYPE_PERSON"; + SubjectReferenceType["SUBJECT_TYPE_ANIMAL"] = "SUBJECT_TYPE_ANIMAL"; + SubjectReferenceType["SUBJECT_TYPE_PRODUCT"] = "SUBJECT_TYPE_PRODUCT"; +})(SubjectReferenceType || (SubjectReferenceType = {})); +/** Enum representing the editing mode. */ +var EditMode; +(function (EditMode) { + EditMode["EDIT_MODE_DEFAULT"] = "EDIT_MODE_DEFAULT"; + EditMode["EDIT_MODE_INPAINT_REMOVAL"] = "EDIT_MODE_INPAINT_REMOVAL"; + EditMode["EDIT_MODE_INPAINT_INSERTION"] = "EDIT_MODE_INPAINT_INSERTION"; + EditMode["EDIT_MODE_OUTPAINT"] = "EDIT_MODE_OUTPAINT"; + EditMode["EDIT_MODE_CONTROLLED_EDITING"] = "EDIT_MODE_CONTROLLED_EDITING"; + EditMode["EDIT_MODE_STYLE"] = "EDIT_MODE_STYLE"; + EditMode["EDIT_MODE_BGSWAP"] = "EDIT_MODE_BGSWAP"; + EditMode["EDIT_MODE_PRODUCT_IMAGE"] = "EDIT_MODE_PRODUCT_IMAGE"; +})(EditMode || (EditMode = {})); +/** Enum that represents the segmentation mode. */ +var SegmentMode; +(function (SegmentMode) { + SegmentMode["FOREGROUND"] = "FOREGROUND"; + SegmentMode["BACKGROUND"] = "BACKGROUND"; + SegmentMode["PROMPT"] = "PROMPT"; + SegmentMode["SEMANTIC"] = "SEMANTIC"; + SegmentMode["INTERACTIVE"] = "INTERACTIVE"; +})(SegmentMode || (SegmentMode = {})); +/** Enum for the reference type of a video generation reference image. */ +var VideoGenerationReferenceType; +(function (VideoGenerationReferenceType) { + /** + * A reference image that provides assets to the generated video, + such as the scene, an object, a character, etc. + */ + VideoGenerationReferenceType["ASSET"] = "ASSET"; + /** + * A reference image that provides aesthetics including colors, + lighting, texture, etc., to be used as the style of the generated video, + such as 'anime', 'photography', 'origami', etc. + */ + VideoGenerationReferenceType["STYLE"] = "STYLE"; +})(VideoGenerationReferenceType || (VideoGenerationReferenceType = {})); +/** Enum for the mask mode of a video generation mask. */ +var VideoGenerationMaskMode; +(function (VideoGenerationMaskMode) { + /** + * The image mask contains a masked rectangular region which is + applied on the first frame of the input video. The object described in + the prompt is inserted into this region and will appear in subsequent + frames. + */ + VideoGenerationMaskMode["INSERT"] = "INSERT"; + /** + * The image mask is used to determine an object in the + first video frame to track. This object is removed from the video. + */ + VideoGenerationMaskMode["REMOVE"] = "REMOVE"; + /** + * The image mask is used to determine a region in the + video. Objects in this region will be removed. + */ + VideoGenerationMaskMode["REMOVE_STATIC"] = "REMOVE_STATIC"; + /** + * The image mask contains a masked rectangular region where + the input video will go. The remaining area will be generated. Video + masks are not supported. + */ + VideoGenerationMaskMode["OUTPAINT"] = "OUTPAINT"; +})(VideoGenerationMaskMode || (VideoGenerationMaskMode = {})); +/** Enum that controls the compression quality of the generated videos. */ +var VideoCompressionQuality; +(function (VideoCompressionQuality) { + /** + * Optimized video compression quality. This will produce videos + with a compressed, smaller file size. + */ + VideoCompressionQuality["OPTIMIZED"] = "OPTIMIZED"; + /** + * Lossless video compression quality. This will produce videos + with a larger file size. + */ + VideoCompressionQuality["LOSSLESS"] = "LOSSLESS"; +})(VideoCompressionQuality || (VideoCompressionQuality = {})); +/** Enum representing the tuning method. */ +var TuningMethod; +(function (TuningMethod) { + /** + * Supervised fine tuning. + */ + TuningMethod["SUPERVISED_FINE_TUNING"] = "SUPERVISED_FINE_TUNING"; + /** + * Preference optimization tuning. + */ + TuningMethod["PREFERENCE_TUNING"] = "PREFERENCE_TUNING"; + /** + * Distillation tuning. + */ + TuningMethod["DISTILLATION"] = "DISTILLATION"; +})(TuningMethod || (TuningMethod = {})); +/** State for the lifecycle of a Document. */ +var DocumentState; +(function (DocumentState) { + DocumentState["STATE_UNSPECIFIED"] = "STATE_UNSPECIFIED"; + DocumentState["STATE_PENDING"] = "STATE_PENDING"; + DocumentState["STATE_ACTIVE"] = "STATE_ACTIVE"; + DocumentState["STATE_FAILED"] = "STATE_FAILED"; +})(DocumentState || (DocumentState = {})); +/** State for the lifecycle of a File. */ +var FileState; +(function (FileState) { + FileState["STATE_UNSPECIFIED"] = "STATE_UNSPECIFIED"; + FileState["PROCESSING"] = "PROCESSING"; + FileState["ACTIVE"] = "ACTIVE"; + FileState["FAILED"] = "FAILED"; +})(FileState || (FileState = {})); +/** Source of the File. */ +var FileSource; +(function (FileSource) { + FileSource["SOURCE_UNSPECIFIED"] = "SOURCE_UNSPECIFIED"; + FileSource["UPLOADED"] = "UPLOADED"; + FileSource["GENERATED"] = "GENERATED"; + FileSource["REGISTERED"] = "REGISTERED"; +})(FileSource || (FileSource = {})); +/** The reason why the turn is complete. */ +var TurnCompleteReason; +(function (TurnCompleteReason) { + /** + * Default value. Reason is unspecified. + */ + TurnCompleteReason["TURN_COMPLETE_REASON_UNSPECIFIED"] = "TURN_COMPLETE_REASON_UNSPECIFIED"; + /** + * The function call generated by the model is invalid. + */ + TurnCompleteReason["MALFORMED_FUNCTION_CALL"] = "MALFORMED_FUNCTION_CALL"; + /** + * The response is rejected by the model. + */ + TurnCompleteReason["RESPONSE_REJECTED"] = "RESPONSE_REJECTED"; + /** + * Needs more input from the user. + */ + TurnCompleteReason["NEED_MORE_INPUT"] = "NEED_MORE_INPUT"; +})(TurnCompleteReason || (TurnCompleteReason = {})); +/** Server content modalities. */ +var MediaModality; +(function (MediaModality) { + /** + * The modality is unspecified. + */ + MediaModality["MODALITY_UNSPECIFIED"] = "MODALITY_UNSPECIFIED"; + /** + * Plain text. + */ + MediaModality["TEXT"] = "TEXT"; + /** + * Images. + */ + MediaModality["IMAGE"] = "IMAGE"; + /** + * Video. + */ + MediaModality["VIDEO"] = "VIDEO"; + /** + * Audio. + */ + MediaModality["AUDIO"] = "AUDIO"; + /** + * Document, e.g. PDF. + */ + MediaModality["DOCUMENT"] = "DOCUMENT"; +})(MediaModality || (MediaModality = {})); +/** The type of the VAD signal. */ +var VadSignalType; +(function (VadSignalType) { + /** + * The default is VAD_SIGNAL_TYPE_UNSPECIFIED. + */ + VadSignalType["VAD_SIGNAL_TYPE_UNSPECIFIED"] = "VAD_SIGNAL_TYPE_UNSPECIFIED"; + /** + * Start of sentence signal. + */ + VadSignalType["VAD_SIGNAL_TYPE_SOS"] = "VAD_SIGNAL_TYPE_SOS"; + /** + * End of sentence signal. + */ + VadSignalType["VAD_SIGNAL_TYPE_EOS"] = "VAD_SIGNAL_TYPE_EOS"; +})(VadSignalType || (VadSignalType = {})); +/** The type of the voice activity signal. */ +var VoiceActivityType; +(function (VoiceActivityType) { + /** + * The default is VOICE_ACTIVITY_TYPE_UNSPECIFIED. + */ + VoiceActivityType["TYPE_UNSPECIFIED"] = "TYPE_UNSPECIFIED"; + /** + * Start of sentence signal. + */ + VoiceActivityType["ACTIVITY_START"] = "ACTIVITY_START"; + /** + * End of sentence signal. + */ + VoiceActivityType["ACTIVITY_END"] = "ACTIVITY_END"; +})(VoiceActivityType || (VoiceActivityType = {})); +/** Start of speech sensitivity. */ +var StartSensitivity; +(function (StartSensitivity) { + /** + * The default is START_SENSITIVITY_LOW. + */ + StartSensitivity["START_SENSITIVITY_UNSPECIFIED"] = "START_SENSITIVITY_UNSPECIFIED"; + /** + * Automatic detection will detect the start of speech more often. + */ + StartSensitivity["START_SENSITIVITY_HIGH"] = "START_SENSITIVITY_HIGH"; + /** + * Automatic detection will detect the start of speech less often. + */ + StartSensitivity["START_SENSITIVITY_LOW"] = "START_SENSITIVITY_LOW"; +})(StartSensitivity || (StartSensitivity = {})); +/** End of speech sensitivity. */ +var EndSensitivity; +(function (EndSensitivity) { + /** + * The default is END_SENSITIVITY_LOW. + */ + EndSensitivity["END_SENSITIVITY_UNSPECIFIED"] = "END_SENSITIVITY_UNSPECIFIED"; + /** + * Automatic detection ends speech more often. + */ + EndSensitivity["END_SENSITIVITY_HIGH"] = "END_SENSITIVITY_HIGH"; + /** + * Automatic detection ends speech less often. + */ + EndSensitivity["END_SENSITIVITY_LOW"] = "END_SENSITIVITY_LOW"; +})(EndSensitivity || (EndSensitivity = {})); +/** The different ways of handling user activity. */ +var ActivityHandling; +(function (ActivityHandling) { + /** + * If unspecified, the default behavior is `START_OF_ACTIVITY_INTERRUPTS`. + */ + ActivityHandling["ACTIVITY_HANDLING_UNSPECIFIED"] = "ACTIVITY_HANDLING_UNSPECIFIED"; + /** + * If true, start of activity will interrupt the model's response (also called "barge in"). The model's current response will be cut-off in the moment of the interruption. This is the default behavior. + */ + ActivityHandling["START_OF_ACTIVITY_INTERRUPTS"] = "START_OF_ACTIVITY_INTERRUPTS"; + /** + * The model's response will not be interrupted. + */ + ActivityHandling["NO_INTERRUPTION"] = "NO_INTERRUPTION"; +})(ActivityHandling || (ActivityHandling = {})); +/** Options about which input is included in the user's turn. */ +var TurnCoverage; +(function (TurnCoverage) { + /** + * If unspecified, the default behavior is `TURN_INCLUDES_ONLY_ACTIVITY`. + */ + TurnCoverage["TURN_COVERAGE_UNSPECIFIED"] = "TURN_COVERAGE_UNSPECIFIED"; + /** + * The users turn only includes activity since the last turn, excluding inactivity (e.g. silence on the audio stream). This is the default behavior. + */ + TurnCoverage["TURN_INCLUDES_ONLY_ACTIVITY"] = "TURN_INCLUDES_ONLY_ACTIVITY"; + /** + * The users turn includes all realtime input since the last turn, including inactivity (e.g. silence on the audio stream). + */ + TurnCoverage["TURN_INCLUDES_ALL_INPUT"] = "TURN_INCLUDES_ALL_INPUT"; +})(TurnCoverage || (TurnCoverage = {})); +/** Scale of the generated music. */ +var Scale; +(function (Scale) { + /** + * Default value. This value is unused. + */ + Scale["SCALE_UNSPECIFIED"] = "SCALE_UNSPECIFIED"; + /** + * C major or A minor. + */ + Scale["C_MAJOR_A_MINOR"] = "C_MAJOR_A_MINOR"; + /** + * Db major or Bb minor. + */ + Scale["D_FLAT_MAJOR_B_FLAT_MINOR"] = "D_FLAT_MAJOR_B_FLAT_MINOR"; + /** + * D major or B minor. + */ + Scale["D_MAJOR_B_MINOR"] = "D_MAJOR_B_MINOR"; + /** + * Eb major or C minor + */ + Scale["E_FLAT_MAJOR_C_MINOR"] = "E_FLAT_MAJOR_C_MINOR"; + /** + * E major or Db minor. + */ + Scale["E_MAJOR_D_FLAT_MINOR"] = "E_MAJOR_D_FLAT_MINOR"; + /** + * F major or D minor. + */ + Scale["F_MAJOR_D_MINOR"] = "F_MAJOR_D_MINOR"; + /** + * Gb major or Eb minor. + */ + Scale["G_FLAT_MAJOR_E_FLAT_MINOR"] = "G_FLAT_MAJOR_E_FLAT_MINOR"; + /** + * G major or E minor. + */ + Scale["G_MAJOR_E_MINOR"] = "G_MAJOR_E_MINOR"; + /** + * Ab major or F minor. + */ + Scale["A_FLAT_MAJOR_F_MINOR"] = "A_FLAT_MAJOR_F_MINOR"; + /** + * A major or Gb minor. + */ + Scale["A_MAJOR_G_FLAT_MINOR"] = "A_MAJOR_G_FLAT_MINOR"; + /** + * Bb major or G minor. + */ + Scale["B_FLAT_MAJOR_G_MINOR"] = "B_FLAT_MAJOR_G_MINOR"; + /** + * B major or Ab minor. + */ + Scale["B_MAJOR_A_FLAT_MINOR"] = "B_MAJOR_A_FLAT_MINOR"; +})(Scale || (Scale = {})); +/** The mode of music generation. */ +var MusicGenerationMode; +(function (MusicGenerationMode) { + /** + * Rely on the server default generation mode. + */ + MusicGenerationMode["MUSIC_GENERATION_MODE_UNSPECIFIED"] = "MUSIC_GENERATION_MODE_UNSPECIFIED"; + /** + * Steer text prompts to regions of latent space with higher quality + music. + */ + MusicGenerationMode["QUALITY"] = "QUALITY"; + /** + * Steer text prompts to regions of latent space with a larger + diversity of music. + */ + MusicGenerationMode["DIVERSITY"] = "DIVERSITY"; + /** + * Steer text prompts to regions of latent space more likely to + generate music with vocals. + */ + MusicGenerationMode["VOCALIZATION"] = "VOCALIZATION"; +})(MusicGenerationMode || (MusicGenerationMode = {})); +/** The playback control signal to apply to the music generation. */ +var LiveMusicPlaybackControl; +(function (LiveMusicPlaybackControl) { + /** + * This value is unused. + */ + LiveMusicPlaybackControl["PLAYBACK_CONTROL_UNSPECIFIED"] = "PLAYBACK_CONTROL_UNSPECIFIED"; + /** + * Start generating the music. + */ + LiveMusicPlaybackControl["PLAY"] = "PLAY"; + /** + * Hold the music generation. Use PLAY to resume from the current position. + */ + LiveMusicPlaybackControl["PAUSE"] = "PAUSE"; + /** + * Stop the music generation and reset the context (prompts retained). + Use PLAY to restart the music generation. + */ + LiveMusicPlaybackControl["STOP"] = "STOP"; + /** + * Reset the context of the music generation without stopping it. + Retains the current prompts and config. + */ + LiveMusicPlaybackControl["RESET_CONTEXT"] = "RESET_CONTEXT"; +})(LiveMusicPlaybackControl || (LiveMusicPlaybackControl = {})); +/** Raw media bytes for function response. + +Text should not be sent as raw bytes, use the FunctionResponse.response +field. */ +class FunctionResponseBlob { +} +/** URI based data for function response. */ +class FunctionResponseFileData { +} +/** A datatype containing media that is part of a `FunctionResponse` message. + +A `FunctionResponsePart` consists of data which has an associated datatype. A +`FunctionResponsePart` can only contain one of the accepted types in +`FunctionResponsePart.data`. + +A `FunctionResponsePart` must have a fixed IANA MIME type identifying the +type and subtype of the media if the `inline_data` field is filled with raw +bytes. */ +class FunctionResponsePart { +} +/** + * Creates a `FunctionResponsePart` object from a `base64` encoded `string`. + */ +function createFunctionResponsePartFromBase64(data, mimeType) { + return { + inlineData: { + data: data, + mimeType: mimeType, + }, + }; +} +/** + * Creates a `FunctionResponsePart` object from a `URI` string. + */ +function createFunctionResponsePartFromUri(uri, mimeType) { + return { + fileData: { + fileUri: uri, + mimeType: mimeType, + }, + }; +} +/** A function response. */ +class FunctionResponse { +} +/** + * Creates a `Part` object from a `URI` string. + */ +function createPartFromUri(uri, mimeType, mediaResolution) { + return Object.assign({ fileData: { + fileUri: uri, + mimeType: mimeType, + } }, (mediaResolution && { mediaResolution: { level: mediaResolution } })); +} +/** + * Creates a `Part` object from a `text` string. + */ +function createPartFromText(text) { + return { + text: text, + }; +} +/** + * Creates a `Part` object from a `FunctionCall` object. + */ +function createPartFromFunctionCall(name, args) { + return { + functionCall: { + name: name, + args: args, + }, + }; +} +/** + * Creates a `Part` object from a `FunctionResponse` object. + */ +function createPartFromFunctionResponse(id, name, response, parts = []) { + return { + functionResponse: Object.assign({ id: id, name: name, response: response }, (parts.length > 0 && { parts })), + }; +} +/** + * Creates a `Part` object from a `base64` encoded `string`. + */ +function createPartFromBase64(data, mimeType, mediaResolution) { + return Object.assign({ inlineData: { + data: data, + mimeType: mimeType, + } }, (mediaResolution && { mediaResolution: { level: mediaResolution } })); +} +/** + * Creates a `Part` object from the `outcome` and `output` of a `CodeExecutionResult` object. + */ +function createPartFromCodeExecutionResult(outcome, output) { + return { + codeExecutionResult: { + outcome: outcome, + output: output, + }, + }; +} +/** + * Creates a `Part` object from the `code` and `language` of an `ExecutableCode` object. + */ +function createPartFromExecutableCode(code, language) { + return { + executableCode: { + code: code, + language: language, + }, + }; +} +function _isPart(obj) { + if (typeof obj === 'object' && obj !== null) { + return ('fileData' in obj || + 'text' in obj || + 'functionCall' in obj || + 'functionResponse' in obj || + 'inlineData' in obj || + 'videoMetadata' in obj || + 'codeExecutionResult' in obj || + 'executableCode' in obj); + } + return false; +} +function _toParts(partOrString) { + const parts = []; + if (typeof partOrString === 'string') { + parts.push(createPartFromText(partOrString)); + } + else if (_isPart(partOrString)) { + parts.push(partOrString); + } + else if (Array.isArray(partOrString)) { + if (partOrString.length === 0) { + throw new Error('partOrString cannot be an empty array'); + } + for (const part of partOrString) { + if (typeof part === 'string') { + parts.push(createPartFromText(part)); + } + else if (_isPart(part)) { + parts.push(part); + } + else { + throw new Error('element in PartUnion must be a Part object or string'); + } + } + } + else { + throw new Error('partOrString must be a Part object, string, or array'); + } + return parts; +} +/** + * Creates a `Content` object with a user role from a `PartListUnion` object or `string`. + */ +function createUserContent(partOrString) { + return { + role: 'user', + parts: _toParts(partOrString), + }; +} +/** + * Creates a `Content` object with a model role from a `PartListUnion` object or `string`. + */ +function createModelContent(partOrString) { + return { + role: 'model', + parts: _toParts(partOrString), + }; +} +/** A wrapper class for the http response. */ +class HttpResponse { + constructor(response) { + // Process the headers. + const headers = {}; + for (const pair of response.headers.entries()) { + headers[pair[0]] = pair[1]; + } + this.headers = headers; + // Keep the original response. + this.responseInternal = response; + } + json() { + return this.responseInternal.json(); + } +} +/** Content filter results for a prompt sent in the request. Note: This is sent only in the first stream chunk and only if no candidates were generated due to content violations. */ +class GenerateContentResponsePromptFeedback { +} +/** Usage metadata about the content generation request and response. This message provides a detailed breakdown of token usage and other relevant metrics. This data type is not supported in Gemini API. */ +class GenerateContentResponseUsageMetadata { +} +/** Response message for PredictionService.GenerateContent. */ +class GenerateContentResponse { + /** + * Returns the concatenation of all text parts from the first candidate in the response. + * + * @remarks + * If there are multiple candidates in the response, the text from the first + * one will be returned. + * If there are non-text parts in the response, the concatenation of all text + * parts will be returned, and a warning will be logged. + * If there are thought parts in the response, the concatenation of all text + * parts excluding the thought parts will be returned. + * + * @example + * ```ts + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: + * 'Why is the sky blue?', + * }); + * + * console.debug(response.text); + * ``` + */ + get text() { + var _a, _b, _c, _d, _e, _f, _g, _h; + if (((_d = (_c = (_b = (_a = this.candidates) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.parts) === null || _d === void 0 ? void 0 : _d.length) === 0) { + return undefined; + } + if (this.candidates && this.candidates.length > 1) { + console.warn('there are multiple candidates in the response, returning text from the first one.'); + } + let text = ''; + let anyTextPartText = false; + const nonTextParts = []; + for (const part of (_h = (_g = (_f = (_e = this.candidates) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.content) === null || _g === void 0 ? void 0 : _g.parts) !== null && _h !== void 0 ? _h : []) { + for (const [fieldName, fieldValue] of Object.entries(part)) { + if (fieldName !== 'text' && + fieldName !== 'thought' && + fieldName !== 'thoughtSignature' && + (fieldValue !== null || fieldValue !== undefined)) { + nonTextParts.push(fieldName); + } + } + if (typeof part.text === 'string') { + if (typeof part.thought === 'boolean' && part.thought) { + continue; + } + anyTextPartText = true; + text += part.text; + } + } + if (nonTextParts.length > 0) { + console.warn(`there are non-text parts ${nonTextParts} in the response, returning concatenation of all text parts. Please refer to the non text parts for a full response from model.`); + } + // part.text === '' is different from part.text is null + return anyTextPartText ? text : undefined; + } + /** + * Returns the concatenation of all inline data parts from the first candidate + * in the response. + * + * @remarks + * If there are multiple candidates in the response, the inline data from the + * first one will be returned. If there are non-inline data parts in the + * response, the concatenation of all inline data parts will be returned, and + * a warning will be logged. + */ + get data() { + var _a, _b, _c, _d, _e, _f, _g, _h; + if (((_d = (_c = (_b = (_a = this.candidates) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.parts) === null || _d === void 0 ? void 0 : _d.length) === 0) { + return undefined; + } + if (this.candidates && this.candidates.length > 1) { + console.warn('there are multiple candidates in the response, returning data from the first one.'); + } + let data = ''; + const nonDataParts = []; + for (const part of (_h = (_g = (_f = (_e = this.candidates) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.content) === null || _g === void 0 ? void 0 : _g.parts) !== null && _h !== void 0 ? _h : []) { + for (const [fieldName, fieldValue] of Object.entries(part)) { + if (fieldName !== 'inlineData' && + (fieldValue !== null || fieldValue !== undefined)) { + nonDataParts.push(fieldName); + } + } + if (part.inlineData && typeof part.inlineData.data === 'string') { + data += atob(part.inlineData.data); + } + } + if (nonDataParts.length > 0) { + console.warn(`there are non-data parts ${nonDataParts} in the response, returning concatenation of all data parts. Please refer to the non data parts for a full response from model.`); + } + return data.length > 0 ? btoa(data) : undefined; + } + /** + * Returns the function calls from the first candidate in the response. + * + * @remarks + * If there are multiple candidates in the response, the function calls from + * the first one will be returned. + * If there are no function calls in the response, undefined will be returned. + * + * @example + * ```ts + * const controlLightFunctionDeclaration: FunctionDeclaration = { + * name: 'controlLight', + * parameters: { + * type: Type.OBJECT, + * description: 'Set the brightness and color temperature of a room light.', + * properties: { + * brightness: { + * type: Type.NUMBER, + * description: + * 'Light level from 0 to 100. Zero is off and 100 is full brightness.', + * }, + * colorTemperature: { + * type: Type.STRING, + * description: + * 'Color temperature of the light fixture which can be `daylight`, `cool` or `warm`.', + * }, + * }, + * required: ['brightness', 'colorTemperature'], + * }; + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: 'Dim the lights so the room feels cozy and warm.', + * config: { + * tools: [{functionDeclarations: [controlLightFunctionDeclaration]}], + * toolConfig: { + * functionCallingConfig: { + * mode: FunctionCallingConfigMode.ANY, + * allowedFunctionNames: ['controlLight'], + * }, + * }, + * }, + * }); + * console.debug(JSON.stringify(response.functionCalls)); + * ``` + */ + get functionCalls() { + var _a, _b, _c, _d, _e, _f, _g, _h; + if (((_d = (_c = (_b = (_a = this.candidates) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.parts) === null || _d === void 0 ? void 0 : _d.length) === 0) { + return undefined; + } + if (this.candidates && this.candidates.length > 1) { + console.warn('there are multiple candidates in the response, returning function calls from the first one.'); + } + const functionCalls = (_h = (_g = (_f = (_e = this.candidates) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.content) === null || _g === void 0 ? void 0 : _g.parts) === null || _h === void 0 ? void 0 : _h.filter((part) => part.functionCall).map((part) => part.functionCall).filter((functionCall) => functionCall !== undefined); + if ((functionCalls === null || functionCalls === void 0 ? void 0 : functionCalls.length) === 0) { + return undefined; + } + return functionCalls; + } + /** + * Returns the first executable code from the first candidate in the response. + * + * @remarks + * If there are multiple candidates in the response, the executable code from + * the first one will be returned. + * If there are no executable code in the response, undefined will be + * returned. + * + * @example + * ```ts + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: + * 'What is the sum of the first 50 prime numbers? Generate and run code for the calculation, and make sure you get all 50.' + * config: { + * tools: [{codeExecution: {}}], + * }, + * }); + * + * console.debug(response.executableCode); + * ``` + */ + get executableCode() { + var _a, _b, _c, _d, _e, _f, _g, _h, _j; + if (((_d = (_c = (_b = (_a = this.candidates) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.parts) === null || _d === void 0 ? void 0 : _d.length) === 0) { + return undefined; + } + if (this.candidates && this.candidates.length > 1) { + console.warn('there are multiple candidates in the response, returning executable code from the first one.'); + } + const executableCode = (_h = (_g = (_f = (_e = this.candidates) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.content) === null || _g === void 0 ? void 0 : _g.parts) === null || _h === void 0 ? void 0 : _h.filter((part) => part.executableCode).map((part) => part.executableCode).filter((executableCode) => executableCode !== undefined); + if ((executableCode === null || executableCode === void 0 ? void 0 : executableCode.length) === 0) { + return undefined; + } + return (_j = executableCode === null || executableCode === void 0 ? void 0 : executableCode[0]) === null || _j === void 0 ? void 0 : _j.code; + } + /** + * Returns the first code execution result from the first candidate in the response. + * + * @remarks + * If there are multiple candidates in the response, the code execution result from + * the first one will be returned. + * If there are no code execution result in the response, undefined will be returned. + * + * @example + * ```ts + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: + * 'What is the sum of the first 50 prime numbers? Generate and run code for the calculation, and make sure you get all 50.' + * config: { + * tools: [{codeExecution: {}}], + * }, + * }); + * + * console.debug(response.codeExecutionResult); + * ``` + */ + get codeExecutionResult() { + var _a, _b, _c, _d, _e, _f, _g, _h, _j; + if (((_d = (_c = (_b = (_a = this.candidates) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.parts) === null || _d === void 0 ? void 0 : _d.length) === 0) { + return undefined; + } + if (this.candidates && this.candidates.length > 1) { + console.warn('there are multiple candidates in the response, returning code execution result from the first one.'); + } + const codeExecutionResult = (_h = (_g = (_f = (_e = this.candidates) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.content) === null || _g === void 0 ? void 0 : _g.parts) === null || _h === void 0 ? void 0 : _h.filter((part) => part.codeExecutionResult).map((part) => part.codeExecutionResult).filter((codeExecutionResult) => codeExecutionResult !== undefined); + if ((codeExecutionResult === null || codeExecutionResult === void 0 ? void 0 : codeExecutionResult.length) === 0) { + return undefined; + } + return (_j = codeExecutionResult === null || codeExecutionResult === void 0 ? void 0 : codeExecutionResult[0]) === null || _j === void 0 ? void 0 : _j.output; + } +} +/** Response for the embed_content method. */ +class EmbedContentResponse { +} +/** The output images response. */ +class GenerateImagesResponse { +} +/** Response for the request to edit an image. */ +class EditImageResponse { +} +class UpscaleImageResponse { +} +/** The output images response. */ +class RecontextImageResponse { +} +/** The output images response. */ +class SegmentImageResponse { +} +class ListModelsResponse { +} +class DeleteModelResponse { +} +/** Response for counting tokens. */ +class CountTokensResponse { +} +/** Response for computing tokens. */ +class ComputeTokensResponse { +} +/** Response with generated videos. */ +class GenerateVideosResponse { +} +/** A video generation operation. */ +class GenerateVideosOperation { + /** + * Instantiates an Operation of the same type as the one being called with the fields set from the API response. + * @internal + */ + _fromAPIResponse({ apiResponse, _isVertexAI, }) { + const operation = new GenerateVideosOperation(); + let response; + const op = apiResponse; + if (_isVertexAI) { + response = generateVideosOperationFromVertex$1(op); + } + else { + response = generateVideosOperationFromMldev$1(op); + } + Object.assign(operation, response); + return operation; + } +} +/** Response for the list tuning jobs method. */ +class ListTuningJobsResponse { +} +/** Empty response for tunings.cancel method. */ +class CancelTuningJobResponse { +} +/** Empty response for caches.delete method. */ +class DeleteCachedContentResponse { +} +class ListCachedContentsResponse { +} +/** Config for documents.list return value. */ +class ListDocumentsResponse { +} +/** Config for file_search_stores.list return value. */ +class ListFileSearchStoresResponse { +} +/** Response for the resumable upload method. */ +class UploadToFileSearchStoreResumableResponse { +} +/** Response for ImportFile to import a File API file with a file search store. */ +class ImportFileResponse { +} +/** Long-running operation for importing a file to a FileSearchStore. */ +class ImportFileOperation { + /** + * Instantiates an Operation of the same type as the one being called with the fields set from the API response. + * @internal + */ + _fromAPIResponse({ apiResponse, _isVertexAI, }) { + const operation = new ImportFileOperation(); + const op = apiResponse; + const response = importFileOperationFromMldev$1(op); + Object.assign(operation, response); + return operation; + } +} +/** Response for the list files method. */ +class ListFilesResponse { +} +/** Response for the create file method. */ +class CreateFileResponse { +} +/** Response for the delete file method. */ +class DeleteFileResponse { +} +/** Response for the _register file method. */ +class RegisterFilesResponse { +} +/** Config for `inlined_responses` parameter. */ +class InlinedResponse { +} +/** Config for `response` parameter. */ +class SingleEmbedContentResponse { +} +/** Config for `inlined_embedding_responses` parameter. */ +class InlinedEmbedContentResponse { +} +/** Config for batches.list return value. */ +class ListBatchJobsResponse { +} +/** Represents a single response in a replay. */ +class ReplayResponse { +} +/** A raw reference image. + +A raw reference image represents the base image to edit, provided by the user. +It can optionally be provided in addition to a mask reference image or +a style reference image. */ +class RawReferenceImage { + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI() { + const referenceImageAPI = { + referenceType: 'REFERENCE_TYPE_RAW', + referenceImage: this.referenceImage, + referenceId: this.referenceId, + }; + return referenceImageAPI; + } +} +/** A mask reference image. + +This encapsulates either a mask image provided by the user and configs for +the user provided mask, or only config parameters for the model to generate +a mask. + +A mask image is an image whose non-zero values indicate where to edit the base +image. If the user provides a mask image, the mask must be in the same +dimensions as the raw image. */ +class MaskReferenceImage { + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI() { + const referenceImageAPI = { + referenceType: 'REFERENCE_TYPE_MASK', + referenceImage: this.referenceImage, + referenceId: this.referenceId, + maskImageConfig: this.config, + }; + return referenceImageAPI; + } +} +/** A control reference image. + +The image of the control reference image is either a control image provided +by the user, or a regular image which the backend will use to generate a +control image of. In the case of the latter, the +enable_control_image_computation field in the config should be set to True. + +A control image is an image that represents a sketch image of areas for the +model to fill in based on the prompt. */ +class ControlReferenceImage { + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI() { + const referenceImageAPI = { + referenceType: 'REFERENCE_TYPE_CONTROL', + referenceImage: this.referenceImage, + referenceId: this.referenceId, + controlImageConfig: this.config, + }; + return referenceImageAPI; + } +} +/** A style reference image. + +This encapsulates a style reference image provided by the user, and +additionally optional config parameters for the style reference image. + +A raw reference image can also be provided as a destination for the style to +be applied to. */ +class StyleReferenceImage { + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI() { + const referenceImageAPI = { + referenceType: 'REFERENCE_TYPE_STYLE', + referenceImage: this.referenceImage, + referenceId: this.referenceId, + styleImageConfig: this.config, + }; + return referenceImageAPI; + } +} +/** A subject reference image. + +This encapsulates a subject reference image provided by the user, and +additionally optional config parameters for the subject reference image. + +A raw reference image can also be provided as a destination for the subject to +be applied to. */ +class SubjectReferenceImage { + /* Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI() { + const referenceImageAPI = { + referenceType: 'REFERENCE_TYPE_SUBJECT', + referenceImage: this.referenceImage, + referenceId: this.referenceId, + subjectImageConfig: this.config, + }; + return referenceImageAPI; + } +} +/** A content reference image. + +A content reference image represents a subject to reference (ex. person, +product, animal) provided by the user. It can optionally be provided in +addition to a style reference image (ex. background, style reference). */ +class ContentReferenceImage { + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI() { + const referenceImageAPI = { + referenceType: 'REFERENCE_TYPE_CONTENT', + referenceImage: this.referenceImage, + referenceId: this.referenceId, + }; + return referenceImageAPI; + } +} +/** Response message for API call. */ +class LiveServerMessage { + /** + * Returns the concatenation of all text parts from the server content if present. + * + * @remarks + * If there are non-text parts in the response, the concatenation of all text + * parts will be returned, and a warning will be logged. + */ + get text() { + var _a, _b, _c; + let text = ''; + let anyTextPartFound = false; + const nonTextParts = []; + for (const part of (_c = (_b = (_a = this.serverContent) === null || _a === void 0 ? void 0 : _a.modelTurn) === null || _b === void 0 ? void 0 : _b.parts) !== null && _c !== void 0 ? _c : []) { + for (const [fieldName, fieldValue] of Object.entries(part)) { + if (fieldName !== 'text' && + fieldName !== 'thought' && + fieldValue !== null) { + nonTextParts.push(fieldName); + } + } + if (typeof part.text === 'string') { + if (typeof part.thought === 'boolean' && part.thought) { + continue; + } + anyTextPartFound = true; + text += part.text; + } + } + if (nonTextParts.length > 0) { + console.warn(`there are non-text parts ${nonTextParts} in the response, returning concatenation of all text parts. Please refer to the non text parts for a full response from model.`); + } + // part.text === '' is different from part.text is null + return anyTextPartFound ? text : undefined; + } + /** + * Returns the concatenation of all inline data parts from the server content if present. + * + * @remarks + * If there are non-inline data parts in the + * response, the concatenation of all inline data parts will be returned, and + * a warning will be logged. + */ + get data() { + var _a, _b, _c; + let data = ''; + const nonDataParts = []; + for (const part of (_c = (_b = (_a = this.serverContent) === null || _a === void 0 ? void 0 : _a.modelTurn) === null || _b === void 0 ? void 0 : _b.parts) !== null && _c !== void 0 ? _c : []) { + for (const [fieldName, fieldValue] of Object.entries(part)) { + if (fieldName !== 'inlineData' && fieldValue !== null) { + nonDataParts.push(fieldName); + } + } + if (part.inlineData && typeof part.inlineData.data === 'string') { + data += atob(part.inlineData.data); + } + } + if (nonDataParts.length > 0) { + console.warn(`there are non-data parts ${nonDataParts} in the response, returning concatenation of all data parts. Please refer to the non data parts for a full response from model.`); + } + return data.length > 0 ? btoa(data) : undefined; + } +} +/** Client generated response to a `ToolCall` received from the server. + +Individual `FunctionResponse` objects are matched to the respective +`FunctionCall` objects by the `id` field. + +Note that in the unary and server-streaming GenerateContent APIs function +calling happens by exchanging the `Content` parts, while in the bidi +GenerateContent APIs function calling happens over this dedicated set of +messages. */ +class LiveClientToolResponse { +} +/** Parameters for sending tool responses to the live API. */ +class LiveSendToolResponseParameters { + constructor() { + /** Tool responses to send to the session. */ + this.functionResponses = []; + } +} +/** Response message for the LiveMusicClientMessage call. */ +class LiveMusicServerMessage { + /** + * Returns the first audio chunk from the server content, if present. + * + * @remarks + * If there are no audio chunks in the response, undefined will be returned. + */ + get audioChunk() { + if (this.serverContent && + this.serverContent.audioChunks && + this.serverContent.audioChunks.length > 0) { + return this.serverContent.audioChunks[0]; + } + return undefined; + } +} +/** The response when long-running operation for uploading a file to a FileSearchStore complete. */ +class UploadToFileSearchStoreResponse { +} +/** Long-running operation for uploading a file to a FileSearchStore. */ +class UploadToFileSearchStoreOperation { + /** + * Instantiates an Operation of the same type as the one being called with the fields set from the API response. + * @internal + */ + _fromAPIResponse({ apiResponse, _isVertexAI, }) { + const operation = new UploadToFileSearchStoreOperation(); + const op = apiResponse; + const response = uploadToFileSearchStoreOperationFromMldev(op); + Object.assign(operation, response); + return operation; + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function tModel(apiClient, model) { + if (!model || typeof model !== 'string') { + throw new Error('model is required and must be a string'); + } + if (model.includes('..') || model.includes('?') || model.includes('&')) { + throw new Error('invalid model parameter'); + } + if (apiClient.isVertexAI()) { + if (model.startsWith('publishers/') || + model.startsWith('projects/') || + model.startsWith('models/')) { + return model; + } + else if (model.indexOf('/') >= 0) { + const parts = model.split('/', 2); + return `publishers/${parts[0]}/models/${parts[1]}`; + } + else { + return `publishers/google/models/${model}`; + } + } + else { + if (model.startsWith('models/') || model.startsWith('tunedModels/')) { + return model; + } + else { + return `models/${model}`; + } + } +} +function tCachesModel(apiClient, model) { + const transformedModel = tModel(apiClient, model); + if (!transformedModel) { + return ''; + } + if (transformedModel.startsWith('publishers/') && apiClient.isVertexAI()) { + // vertex caches only support model name start with projects. + return `projects/${apiClient.getProject()}/locations/${apiClient.getLocation()}/${transformedModel}`; + } + else if (transformedModel.startsWith('models/') && apiClient.isVertexAI()) { + return `projects/${apiClient.getProject()}/locations/${apiClient.getLocation()}/publishers/google/${transformedModel}`; + } + else { + return transformedModel; + } +} +function tBlobs(blobs) { + if (Array.isArray(blobs)) { + return blobs.map((blob) => tBlob(blob)); + } + else { + return [tBlob(blobs)]; + } +} +function tBlob(blob) { + if (typeof blob === 'object' && blob !== null) { + return blob; + } + throw new Error(`Could not parse input as Blob. Unsupported blob type: ${typeof blob}`); +} +function tImageBlob(blob) { + const transformedBlob = tBlob(blob); + if (transformedBlob.mimeType && + transformedBlob.mimeType.startsWith('image/')) { + return transformedBlob; + } + throw new Error(`Unsupported mime type: ${transformedBlob.mimeType}`); +} +function tAudioBlob(blob) { + const transformedBlob = tBlob(blob); + if (transformedBlob.mimeType && + transformedBlob.mimeType.startsWith('audio/')) { + return transformedBlob; + } + throw new Error(`Unsupported mime type: ${transformedBlob.mimeType}`); +} +function tPart(origin) { + if (origin === null || origin === undefined) { + throw new Error('PartUnion is required'); + } + if (typeof origin === 'object') { + return origin; + } + if (typeof origin === 'string') { + return { text: origin }; + } + throw new Error(`Unsupported part type: ${typeof origin}`); +} +function tParts(origin) { + if (origin === null || + origin === undefined || + (Array.isArray(origin) && origin.length === 0)) { + throw new Error('PartListUnion is required'); + } + if (Array.isArray(origin)) { + return origin.map((item) => tPart(item)); + } + return [tPart(origin)]; +} +function _isContent(origin) { + return (origin !== null && + origin !== undefined && + typeof origin === 'object' && + 'parts' in origin && + Array.isArray(origin.parts)); +} +function _isFunctionCallPart(origin) { + return (origin !== null && + origin !== undefined && + typeof origin === 'object' && + 'functionCall' in origin); +} +function _isFunctionResponsePart(origin) { + return (origin !== null && + origin !== undefined && + typeof origin === 'object' && + 'functionResponse' in origin); +} +function tContent(origin) { + if (origin === null || origin === undefined) { + throw new Error('ContentUnion is required'); + } + if (_isContent(origin)) { + // _isContent is a utility function that checks if the + // origin is a Content. + return origin; + } + return { + role: 'user', + parts: tParts(origin), + }; +} +function tContentsForEmbed(apiClient, origin) { + if (!origin) { + return []; + } + if (apiClient.isVertexAI() && Array.isArray(origin)) { + return origin.flatMap((item) => { + const content = tContent(item); + if (content.parts && + content.parts.length > 0 && + content.parts[0].text !== undefined) { + return [content.parts[0].text]; + } + return []; + }); + } + else if (apiClient.isVertexAI()) { + const content = tContent(origin); + if (content.parts && + content.parts.length > 0 && + content.parts[0].text !== undefined) { + return [content.parts[0].text]; + } + return []; + } + if (Array.isArray(origin)) { + return origin.map((item) => tContent(item)); + } + return [tContent(origin)]; +} +function tContents(origin) { + if (origin === null || + origin === undefined || + (Array.isArray(origin) && origin.length === 0)) { + throw new Error('contents are required'); + } + if (!Array.isArray(origin)) { + // If it's not an array, it's a single content or a single PartUnion. + if (_isFunctionCallPart(origin) || _isFunctionResponsePart(origin)) { + throw new Error('To specify functionCall or functionResponse parts, please wrap them in a Content object, specifying the role for them'); + } + return [tContent(origin)]; + } + const result = []; + const accumulatedParts = []; + const isContentArray = _isContent(origin[0]); + for (const item of origin) { + const isContent = _isContent(item); + if (isContent != isContentArray) { + throw new Error('Mixing Content and Parts is not supported, please group the parts into a the appropriate Content objects and specify the roles for them'); + } + if (isContent) { + // `isContent` contains the result of _isContent, which is a utility + // function that checks if the item is a Content. + result.push(item); + } + else if (_isFunctionCallPart(item) || _isFunctionResponsePart(item)) { + throw new Error('To specify functionCall or functionResponse parts, please wrap them, and any other parts, in Content objects as appropriate, specifying the role for them'); + } + else { + accumulatedParts.push(item); + } + } + if (!isContentArray) { + result.push({ role: 'user', parts: tParts(accumulatedParts) }); + } + return result; +} +/* +Transform the type field from an array of types to an array of anyOf fields. +Example: + {type: ['STRING', 'NUMBER']} +will be transformed to + {anyOf: [{type: 'STRING'}, {type: 'NUMBER'}]} +*/ +function flattenTypeArrayToAnyOf(typeList, resultingSchema) { + if (typeList.includes('null')) { + resultingSchema['nullable'] = true; + } + const listWithoutNull = typeList.filter((type) => type !== 'null'); + if (listWithoutNull.length === 1) { + resultingSchema['type'] = Object.values(Type).includes(listWithoutNull[0].toUpperCase()) + ? listWithoutNull[0].toUpperCase() + : Type.TYPE_UNSPECIFIED; + } + else { + resultingSchema['anyOf'] = []; + for (const i of listWithoutNull) { + resultingSchema['anyOf'].push({ + 'type': Object.values(Type).includes(i.toUpperCase()) + ? i.toUpperCase() + : Type.TYPE_UNSPECIFIED, + }); + } + } +} +function processJsonSchema(_jsonSchema) { + const genAISchema = {}; + const schemaFieldNames = ['items']; + const listSchemaFieldNames = ['anyOf']; + const dictSchemaFieldNames = ['properties']; + if (_jsonSchema['type'] && _jsonSchema['anyOf']) { + throw new Error('type and anyOf cannot be both populated.'); + } + /* + This is to handle the nullable array or object. The _jsonSchema will + be in the format of {anyOf: [{type: 'null'}, {type: 'object'}]}. The + logic is to check if anyOf has 2 elements and one of the element is null, + if so, the anyOf field is unnecessary, so we need to get rid of the anyOf + field and make the schema nullable. Then use the other element as the new + _jsonSchema for processing. This is because the backend doesn't have a null + type. + This has to be checked before we process any other fields. + For example: + const objectNullable = z.object({ + nullableArray: z.array(z.string()).nullable(), + }); + Will have the raw _jsonSchema as: + { + type: 'OBJECT', + properties: { + nullableArray: { + anyOf: [ + {type: 'null'}, + { + type: 'array', + items: {type: 'string'}, + }, + ], + } + }, + required: [ 'nullableArray' ], + } + Will result in following schema compatible with Gemini API: + { + type: 'OBJECT', + properties: { + nullableArray: { + nullable: true, + type: 'ARRAY', + items: {type: 'string'}, + } + }, + required: [ 'nullableArray' ], + } + */ + const incomingAnyOf = _jsonSchema['anyOf']; + if (incomingAnyOf != null && incomingAnyOf.length == 2) { + if (incomingAnyOf[0]['type'] === 'null') { + genAISchema['nullable'] = true; + _jsonSchema = incomingAnyOf[1]; + } + else if (incomingAnyOf[1]['type'] === 'null') { + genAISchema['nullable'] = true; + _jsonSchema = incomingAnyOf[0]; + } + } + if (_jsonSchema['type'] instanceof Array) { + flattenTypeArrayToAnyOf(_jsonSchema['type'], genAISchema); + } + for (const [fieldName, fieldValue] of Object.entries(_jsonSchema)) { + // Skip if the fieldvalue is undefined or null. + if (fieldValue == null) { + continue; + } + if (fieldName == 'type') { + if (fieldValue === 'null') { + throw new Error('type: null can not be the only possible type for the field.'); + } + if (fieldValue instanceof Array) { + // we have already handled the type field with array of types in the + // beginning of this function. + continue; + } + genAISchema['type'] = Object.values(Type).includes(fieldValue.toUpperCase()) + ? fieldValue.toUpperCase() + : Type.TYPE_UNSPECIFIED; + } + else if (schemaFieldNames.includes(fieldName)) { + genAISchema[fieldName] = + processJsonSchema(fieldValue); + } + else if (listSchemaFieldNames.includes(fieldName)) { + const listSchemaFieldValue = []; + for (const item of fieldValue) { + if (item['type'] == 'null') { + genAISchema['nullable'] = true; + continue; + } + listSchemaFieldValue.push(processJsonSchema(item)); + } + genAISchema[fieldName] = + listSchemaFieldValue; + } + else if (dictSchemaFieldNames.includes(fieldName)) { + const dictSchemaFieldValue = {}; + for (const [key, value] of Object.entries(fieldValue)) { + dictSchemaFieldValue[key] = processJsonSchema(value); + } + genAISchema[fieldName] = + dictSchemaFieldValue; + } + else { + // additionalProperties is not included in JSONSchema, skipping it. + if (fieldName === 'additionalProperties') { + continue; + } + genAISchema[fieldName] = fieldValue; + } + } + return genAISchema; +} +// we take the unknown in the schema field because we want enable user to pass +// the output of major schema declaration tools without casting. Tools such as +// zodToJsonSchema, typebox, zodToJsonSchema function can return JsonSchema7Type +// or object, see details in +// https://github.com/StefanTerdell/zod-to-json-schema/blob/70525efe555cd226691e093d171370a3b10921d1/src/zodToJsonSchema.ts#L7 +// typebox can return unknown, see details in +// https://github.com/sinclairzx81/typebox/blob/5a5431439f7d5ca6b494d0d18fbfd7b1a356d67c/src/type/create/type.ts#L35 +// Note: proper json schemas with the $schema field set never arrive to this +// transformer. Schemas with $schema are routed to the equivalent API json +// schema field. +function tSchema(schema) { + return processJsonSchema(schema); +} +function tSpeechConfig(speechConfig) { + if (typeof speechConfig === 'object') { + return speechConfig; + } + else if (typeof speechConfig === 'string') { + return { + voiceConfig: { + prebuiltVoiceConfig: { + voiceName: speechConfig, + }, + }, + }; + } + else { + throw new Error(`Unsupported speechConfig type: ${typeof speechConfig}`); + } +} +function tLiveSpeechConfig(speechConfig) { + if ('multiSpeakerVoiceConfig' in speechConfig) { + throw new Error('multiSpeakerVoiceConfig is not supported in the live API.'); + } + return speechConfig; +} +function tTool(tool) { + if (tool.functionDeclarations) { + for (const functionDeclaration of tool.functionDeclarations) { + if (functionDeclaration.parameters) { + if (!Object.keys(functionDeclaration.parameters).includes('$schema')) { + functionDeclaration.parameters = processJsonSchema(functionDeclaration.parameters); + } + else { + if (!functionDeclaration.parametersJsonSchema) { + functionDeclaration.parametersJsonSchema = + functionDeclaration.parameters; + delete functionDeclaration.parameters; + } + } + } + if (functionDeclaration.response) { + if (!Object.keys(functionDeclaration.response).includes('$schema')) { + functionDeclaration.response = processJsonSchema(functionDeclaration.response); + } + else { + if (!functionDeclaration.responseJsonSchema) { + functionDeclaration.responseJsonSchema = + functionDeclaration.response; + delete functionDeclaration.response; + } + } + } + } + } + return tool; +} +function tTools(tools) { + // Check if the incoming type is defined. + if (tools === undefined || tools === null) { + throw new Error('tools is required'); + } + if (!Array.isArray(tools)) { + throw new Error('tools is required and must be an array of Tools'); + } + const result = []; + for (const tool of tools) { + result.push(tool); + } + return result; +} +/** + * Prepends resource name with project, location, resource_prefix if needed. + * + * @param client The API client. + * @param resourceName The resource name. + * @param resourcePrefix The resource prefix. + * @param splitsAfterPrefix The number of splits after the prefix. + * @returns The completed resource name. + * + * Examples: + * + * ``` + * resource_name = '123' + * resource_prefix = 'cachedContents' + * splits_after_prefix = 1 + * client.vertexai = True + * client.project = 'bar' + * client.location = 'us-west1' + * _resource_name(client, resource_name, resource_prefix, splits_after_prefix) + * returns: 'projects/bar/locations/us-west1/cachedContents/123' + * ``` + * + * ``` + * resource_name = 'projects/foo/locations/us-central1/cachedContents/123' + * resource_prefix = 'cachedContents' + * splits_after_prefix = 1 + * client.vertexai = True + * client.project = 'bar' + * client.location = 'us-west1' + * _resource_name(client, resource_name, resource_prefix, splits_after_prefix) + * returns: 'projects/foo/locations/us-central1/cachedContents/123' + * ``` + * + * ``` + * resource_name = '123' + * resource_prefix = 'cachedContents' + * splits_after_prefix = 1 + * client.vertexai = False + * _resource_name(client, resource_name, resource_prefix, splits_after_prefix) + * returns 'cachedContents/123' + * ``` + * + * ``` + * resource_name = 'some/wrong/cachedContents/resource/name/123' + * resource_prefix = 'cachedContents' + * splits_after_prefix = 1 + * client.vertexai = False + * # client.vertexai = True + * _resource_name(client, resource_name, resource_prefix, splits_after_prefix) + * -> 'some/wrong/resource/name/123' + * ``` + */ +function resourceName(client, resourceName, resourcePrefix, splitsAfterPrefix = 1) { + const shouldAppendPrefix = !resourceName.startsWith(`${resourcePrefix}/`) && + resourceName.split('/').length === splitsAfterPrefix; + if (client.isVertexAI()) { + if (resourceName.startsWith('projects/')) { + return resourceName; + } + else if (resourceName.startsWith('locations/')) { + return `projects/${client.getProject()}/${resourceName}`; + } + else if (resourceName.startsWith(`${resourcePrefix}/`)) { + return `projects/${client.getProject()}/locations/${client.getLocation()}/${resourceName}`; + } + else if (shouldAppendPrefix) { + return `projects/${client.getProject()}/locations/${client.getLocation()}/${resourcePrefix}/${resourceName}`; + } + else { + return resourceName; + } + } + if (shouldAppendPrefix) { + return `${resourcePrefix}/${resourceName}`; + } + return resourceName; +} +function tCachedContentName(apiClient, name) { + if (typeof name !== 'string') { + throw new Error('name must be a string'); + } + return resourceName(apiClient, name, 'cachedContents'); +} +function tTuningJobStatus(status) { + switch (status) { + case 'STATE_UNSPECIFIED': + return 'JOB_STATE_UNSPECIFIED'; + case 'CREATING': + return 'JOB_STATE_RUNNING'; + case 'ACTIVE': + return 'JOB_STATE_SUCCEEDED'; + case 'FAILED': + return 'JOB_STATE_FAILED'; + default: + return status; + } +} +function tBytes(fromImageBytes) { + return tBytes$1(fromImageBytes); +} +function _isFile(origin) { + return (origin !== null && + origin !== undefined && + typeof origin === 'object' && + 'name' in origin); +} +function isGeneratedVideo(origin) { + return (origin !== null && + origin !== undefined && + typeof origin === 'object' && + 'video' in origin); +} +function isVideo(origin) { + return (origin !== null && + origin !== undefined && + typeof origin === 'object' && + 'uri' in origin); +} +function tFileName(fromName) { + var _a; + let name; + if (_isFile(fromName)) { + name = fromName.name; + } + if (isVideo(fromName)) { + name = fromName.uri; + if (name === undefined) { + return undefined; + } + } + if (isGeneratedVideo(fromName)) { + name = (_a = fromName.video) === null || _a === void 0 ? void 0 : _a.uri; + if (name === undefined) { + return undefined; + } + } + if (typeof fromName === 'string') { + name = fromName; + } + if (name === undefined) { + throw new Error('Could not extract file name from the provided input.'); + } + if (name.startsWith('https://')) { + const suffix = name.split('files/')[1]; + const match = suffix.match(/[a-z0-9]+/); + if (match === null) { + throw new Error(`Could not extract file name from URI ${name}`); + } + name = match[0]; + } + else if (name.startsWith('files/')) { + name = name.split('files/')[1]; + } + return name; +} +function tModelsUrl(apiClient, baseModels) { + let res; + if (apiClient.isVertexAI()) { + res = baseModels ? 'publishers/google/models' : 'models'; + } + else { + res = baseModels ? 'models' : 'tunedModels'; + } + return res; +} +function tExtractModels(response) { + for (const key of ['models', 'tunedModels', 'publisherModels']) { + if (hasField(response, key)) { + return response[key]; + } + } + return []; +} +function hasField(data, fieldName) { + return data !== null && typeof data === 'object' && fieldName in data; +} +function mcpToGeminiTool(mcpTool, config = {}) { + const mcpToolSchema = mcpTool; + const functionDeclaration = { + name: mcpToolSchema['name'], + description: mcpToolSchema['description'], + parametersJsonSchema: mcpToolSchema['inputSchema'], + }; + if (mcpToolSchema['outputSchema']) { + functionDeclaration['responseJsonSchema'] = mcpToolSchema['outputSchema']; + } + if (config.behavior) { + functionDeclaration['behavior'] = config.behavior; + } + const geminiTool = { + functionDeclarations: [ + functionDeclaration, + ], + }; + return geminiTool; +} +/** + * Converts a list of MCP tools to a single Gemini tool with a list of function + * declarations. + */ +function mcpToolsToGeminiTool(mcpTools, config = {}) { + const functionDeclarations = []; + const toolNames = new Set(); + for (const mcpTool of mcpTools) { + const mcpToolName = mcpTool.name; + if (toolNames.has(mcpToolName)) { + throw new Error(`Duplicate function name ${mcpToolName} found in MCP tools. Please ensure function names are unique.`); + } + toolNames.add(mcpToolName); + const geminiTool = mcpToGeminiTool(mcpTool, config); + if (geminiTool.functionDeclarations) { + functionDeclarations.push(...geminiTool.functionDeclarations); + } + } + return { functionDeclarations: functionDeclarations }; +} +// Transforms a source input into a BatchJobSource object with validation. +function tBatchJobSource(client, src) { + let sourceObj; + if (typeof src === 'string') { + if (client.isVertexAI()) { + if (src.startsWith('gs://')) { + sourceObj = { format: 'jsonl', gcsUri: [src] }; + } + else if (src.startsWith('bq://')) { + sourceObj = { format: 'bigquery', bigqueryUri: src }; + } + else { + throw new Error(`Unsupported string source for Vertex AI: ${src}`); + } + } + else { + // MLDEV + if (src.startsWith('files/')) { + sourceObj = { fileName: src }; // Default to fileName for string input + } + else { + throw new Error(`Unsupported string source for Gemini API: ${src}`); + } + } + } + else if (Array.isArray(src)) { + if (client.isVertexAI()) { + throw new Error('InlinedRequest[] is not supported in Vertex AI.'); + } + sourceObj = { inlinedRequests: src }; + } + else { + // It's already a BatchJobSource object + sourceObj = src; + } + // Validation logic + const vertexSourcesCount = [sourceObj.gcsUri, sourceObj.bigqueryUri].filter(Boolean).length; + const mldevSourcesCount = [ + sourceObj.inlinedRequests, + sourceObj.fileName, + ].filter(Boolean).length; + if (client.isVertexAI()) { + if (mldevSourcesCount > 0 || vertexSourcesCount !== 1) { + throw new Error('Exactly one of `gcsUri` or `bigqueryUri` must be set for Vertex AI.'); + } + } + else { + // MLDEV + if (vertexSourcesCount > 0 || mldevSourcesCount !== 1) { + throw new Error('Exactly one of `inlinedRequests`, `fileName`, ' + + 'must be set for Gemini API.'); + } + } + return sourceObj; +} +function tBatchJobDestination(dest) { + if (typeof dest !== 'string') { + return dest; + } + const destString = dest; + if (destString.startsWith('gs://')) { + return { + format: 'jsonl', + gcsUri: destString, + }; + } + else if (destString.startsWith('bq://')) { + return { + format: 'bigquery', + bigqueryUri: destString, + }; + } + else { + throw new Error(`Unsupported destination: ${destString}`); + } +} +function tRecvBatchJobDestination(dest) { + // Ensure dest is a non-null object before proceeding. + if (typeof dest !== 'object' || dest === null) { + // If the input is not an object, it cannot be a valid BatchJobDestination + // based on the operations performed. Return it cast, or handle as an error. + // Casting an empty object might be a safe default. + return {}; + } + // Cast to Record<string, unknown> to allow string property access. + const obj = dest; + // Safely access nested properties. + const inlineResponsesVal = obj['inlinedResponses']; + if (typeof inlineResponsesVal !== 'object' || inlineResponsesVal === null) { + return dest; + } + const inlineResponsesObj = inlineResponsesVal; + const responsesArray = inlineResponsesObj['inlinedResponses']; + if (!Array.isArray(responsesArray) || responsesArray.length === 0) { + return dest; + } + // Check if any response has the 'embedding' property. + let hasEmbedding = false; + for (const responseItem of responsesArray) { + if (typeof responseItem !== 'object' || responseItem === null) { + continue; + } + const responseItemObj = responseItem; + const responseVal = responseItemObj['response']; + if (typeof responseVal !== 'object' || responseVal === null) { + continue; + } + const responseObj = responseVal; + // Check for the existence of the 'embedding' key. + if (responseObj['embedding'] !== undefined) { + hasEmbedding = true; + break; + } + } + // Perform the transformation if an embedding was found. + if (hasEmbedding) { + obj['inlinedEmbedContentResponses'] = obj['inlinedResponses']; + delete obj['inlinedResponses']; + } + // Cast the (potentially) modified object to the target type. + return dest; +} +function tBatchJobName(apiClient, name) { + const nameString = name; + if (!apiClient.isVertexAI()) { + const mldevPattern = /batches\/[^/]+$/; + if (mldevPattern.test(nameString)) { + return nameString.split('/').pop(); + } + else { + throw new Error(`Invalid batch job name: ${nameString}.`); + } + } + const vertexPattern = /^projects\/[^/]+\/locations\/[^/]+\/batchPredictionJobs\/[^/]+$/; + if (vertexPattern.test(nameString)) { + return nameString.split('/').pop(); + } + else if (/^\d+$/.test(nameString)) { + return nameString; + } + else { + throw new Error(`Invalid batch job name: ${nameString}.`); + } +} +function tJobState(state) { + const stateString = state; + if (stateString === 'BATCH_STATE_UNSPECIFIED') { + return 'JOB_STATE_UNSPECIFIED'; + } + else if (stateString === 'BATCH_STATE_PENDING') { + return 'JOB_STATE_PENDING'; + } + else if (stateString === 'BATCH_STATE_RUNNING') { + return 'JOB_STATE_RUNNING'; + } + else if (stateString === 'BATCH_STATE_SUCCEEDED') { + return 'JOB_STATE_SUCCEEDED'; + } + else if (stateString === 'BATCH_STATE_FAILED') { + return 'JOB_STATE_FAILED'; + } + else if (stateString === 'BATCH_STATE_CANCELLED') { + return 'JOB_STATE_CANCELLED'; + } + else if (stateString === 'BATCH_STATE_EXPIRED') { + return 'JOB_STATE_EXPIRED'; + } + else { + return stateString; + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function batchJobDestinationFromMldev(fromObject) { + const toObject = {}; + const fromFileName = getValueByPath(fromObject, ['responsesFile']); + if (fromFileName != null) { + setValueByPath(toObject, ['fileName'], fromFileName); + } + const fromInlinedResponses = getValueByPath(fromObject, [ + 'inlinedResponses', + 'inlinedResponses', + ]); + if (fromInlinedResponses != null) { + let transformedList = fromInlinedResponses; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return inlinedResponseFromMldev(item); + }); + } + setValueByPath(toObject, ['inlinedResponses'], transformedList); + } + const fromInlinedEmbedContentResponses = getValueByPath(fromObject, [ + 'inlinedEmbedContentResponses', + 'inlinedResponses', + ]); + if (fromInlinedEmbedContentResponses != null) { + let transformedList = fromInlinedEmbedContentResponses; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['inlinedEmbedContentResponses'], transformedList); + } + return toObject; +} +function batchJobDestinationFromVertex(fromObject) { + const toObject = {}; + const fromFormat = getValueByPath(fromObject, ['predictionsFormat']); + if (fromFormat != null) { + setValueByPath(toObject, ['format'], fromFormat); + } + const fromGcsUri = getValueByPath(fromObject, [ + 'gcsDestination', + 'outputUriPrefix', + ]); + if (fromGcsUri != null) { + setValueByPath(toObject, ['gcsUri'], fromGcsUri); + } + const fromBigqueryUri = getValueByPath(fromObject, [ + 'bigqueryDestination', + 'outputUri', + ]); + if (fromBigqueryUri != null) { + setValueByPath(toObject, ['bigqueryUri'], fromBigqueryUri); + } + return toObject; +} +function batchJobDestinationToVertex(fromObject) { + const toObject = {}; + const fromFormat = getValueByPath(fromObject, ['format']); + if (fromFormat != null) { + setValueByPath(toObject, ['predictionsFormat'], fromFormat); + } + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (fromGcsUri != null) { + setValueByPath(toObject, ['gcsDestination', 'outputUriPrefix'], fromGcsUri); + } + const fromBigqueryUri = getValueByPath(fromObject, ['bigqueryUri']); + if (fromBigqueryUri != null) { + setValueByPath(toObject, ['bigqueryDestination', 'outputUri'], fromBigqueryUri); + } + if (getValueByPath(fromObject, ['fileName']) !== undefined) { + throw new Error('fileName parameter is not supported in Vertex AI.'); + } + if (getValueByPath(fromObject, ['inlinedResponses']) !== undefined) { + throw new Error('inlinedResponses parameter is not supported in Vertex AI.'); + } + if (getValueByPath(fromObject, ['inlinedEmbedContentResponses']) !== + undefined) { + throw new Error('inlinedEmbedContentResponses parameter is not supported in Vertex AI.'); + } + return toObject; +} +function batchJobFromMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromDisplayName = getValueByPath(fromObject, [ + 'metadata', + 'displayName', + ]); + if (fromDisplayName != null) { + setValueByPath(toObject, ['displayName'], fromDisplayName); + } + const fromState = getValueByPath(fromObject, ['metadata', 'state']); + if (fromState != null) { + setValueByPath(toObject, ['state'], tJobState(fromState)); + } + const fromCreateTime = getValueByPath(fromObject, [ + 'metadata', + 'createTime', + ]); + if (fromCreateTime != null) { + setValueByPath(toObject, ['createTime'], fromCreateTime); + } + const fromEndTime = getValueByPath(fromObject, [ + 'metadata', + 'endTime', + ]); + if (fromEndTime != null) { + setValueByPath(toObject, ['endTime'], fromEndTime); + } + const fromUpdateTime = getValueByPath(fromObject, [ + 'metadata', + 'updateTime', + ]); + if (fromUpdateTime != null) { + setValueByPath(toObject, ['updateTime'], fromUpdateTime); + } + const fromModel = getValueByPath(fromObject, ['metadata', 'model']); + if (fromModel != null) { + setValueByPath(toObject, ['model'], fromModel); + } + const fromDest = getValueByPath(fromObject, ['metadata', 'output']); + if (fromDest != null) { + setValueByPath(toObject, ['dest'], batchJobDestinationFromMldev(tRecvBatchJobDestination(fromDest))); + } + return toObject; +} +function batchJobFromVertex(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (fromDisplayName != null) { + setValueByPath(toObject, ['displayName'], fromDisplayName); + } + const fromState = getValueByPath(fromObject, ['state']); + if (fromState != null) { + setValueByPath(toObject, ['state'], tJobState(fromState)); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromCreateTime = getValueByPath(fromObject, ['createTime']); + if (fromCreateTime != null) { + setValueByPath(toObject, ['createTime'], fromCreateTime); + } + const fromStartTime = getValueByPath(fromObject, ['startTime']); + if (fromStartTime != null) { + setValueByPath(toObject, ['startTime'], fromStartTime); + } + const fromEndTime = getValueByPath(fromObject, ['endTime']); + if (fromEndTime != null) { + setValueByPath(toObject, ['endTime'], fromEndTime); + } + const fromUpdateTime = getValueByPath(fromObject, ['updateTime']); + if (fromUpdateTime != null) { + setValueByPath(toObject, ['updateTime'], fromUpdateTime); + } + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['model'], fromModel); + } + const fromSrc = getValueByPath(fromObject, ['inputConfig']); + if (fromSrc != null) { + setValueByPath(toObject, ['src'], batchJobSourceFromVertex(fromSrc)); + } + const fromDest = getValueByPath(fromObject, ['outputConfig']); + if (fromDest != null) { + setValueByPath(toObject, ['dest'], batchJobDestinationFromVertex(tRecvBatchJobDestination(fromDest))); + } + const fromCompletionStats = getValueByPath(fromObject, [ + 'completionStats', + ]); + if (fromCompletionStats != null) { + setValueByPath(toObject, ['completionStats'], fromCompletionStats); + } + return toObject; +} +function batchJobSourceFromVertex(fromObject) { + const toObject = {}; + const fromFormat = getValueByPath(fromObject, ['instancesFormat']); + if (fromFormat != null) { + setValueByPath(toObject, ['format'], fromFormat); + } + const fromGcsUri = getValueByPath(fromObject, ['gcsSource', 'uris']); + if (fromGcsUri != null) { + setValueByPath(toObject, ['gcsUri'], fromGcsUri); + } + const fromBigqueryUri = getValueByPath(fromObject, [ + 'bigquerySource', + 'inputUri', + ]); + if (fromBigqueryUri != null) { + setValueByPath(toObject, ['bigqueryUri'], fromBigqueryUri); + } + return toObject; +} +function batchJobSourceToMldev(apiClient, fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['format']) !== undefined) { + throw new Error('format parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['gcsUri']) !== undefined) { + throw new Error('gcsUri parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['bigqueryUri']) !== undefined) { + throw new Error('bigqueryUri parameter is not supported in Gemini API.'); + } + const fromFileName = getValueByPath(fromObject, ['fileName']); + if (fromFileName != null) { + setValueByPath(toObject, ['fileName'], fromFileName); + } + const fromInlinedRequests = getValueByPath(fromObject, [ + 'inlinedRequests', + ]); + if (fromInlinedRequests != null) { + let transformedList = fromInlinedRequests; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return inlinedRequestToMldev(apiClient, item); + }); + } + setValueByPath(toObject, ['requests', 'requests'], transformedList); + } + return toObject; +} +function batchJobSourceToVertex(fromObject) { + const toObject = {}; + const fromFormat = getValueByPath(fromObject, ['format']); + if (fromFormat != null) { + setValueByPath(toObject, ['instancesFormat'], fromFormat); + } + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (fromGcsUri != null) { + setValueByPath(toObject, ['gcsSource', 'uris'], fromGcsUri); + } + const fromBigqueryUri = getValueByPath(fromObject, ['bigqueryUri']); + if (fromBigqueryUri != null) { + setValueByPath(toObject, ['bigquerySource', 'inputUri'], fromBigqueryUri); + } + if (getValueByPath(fromObject, ['fileName']) !== undefined) { + throw new Error('fileName parameter is not supported in Vertex AI.'); + } + if (getValueByPath(fromObject, ['inlinedRequests']) !== undefined) { + throw new Error('inlinedRequests parameter is not supported in Vertex AI.'); + } + return toObject; +} +function blobToMldev$4(fromObject) { + const toObject = {}; + const fromData = getValueByPath(fromObject, ['data']); + if (fromData != null) { + setValueByPath(toObject, ['data'], fromData); + } + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function cancelBatchJobParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tBatchJobName(apiClient, fromName)); + } + return toObject; +} +function cancelBatchJobParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tBatchJobName(apiClient, fromName)); + } + return toObject; +} +function candidateFromMldev$1(fromObject) { + const toObject = {}; + const fromContent = getValueByPath(fromObject, ['content']); + if (fromContent != null) { + setValueByPath(toObject, ['content'], fromContent); + } + const fromCitationMetadata = getValueByPath(fromObject, [ + 'citationMetadata', + ]); + if (fromCitationMetadata != null) { + setValueByPath(toObject, ['citationMetadata'], citationMetadataFromMldev$1(fromCitationMetadata)); + } + const fromTokenCount = getValueByPath(fromObject, ['tokenCount']); + if (fromTokenCount != null) { + setValueByPath(toObject, ['tokenCount'], fromTokenCount); + } + const fromFinishReason = getValueByPath(fromObject, ['finishReason']); + if (fromFinishReason != null) { + setValueByPath(toObject, ['finishReason'], fromFinishReason); + } + const fromAvgLogprobs = getValueByPath(fromObject, ['avgLogprobs']); + if (fromAvgLogprobs != null) { + setValueByPath(toObject, ['avgLogprobs'], fromAvgLogprobs); + } + const fromGroundingMetadata = getValueByPath(fromObject, [ + 'groundingMetadata', + ]); + if (fromGroundingMetadata != null) { + setValueByPath(toObject, ['groundingMetadata'], fromGroundingMetadata); + } + const fromIndex = getValueByPath(fromObject, ['index']); + if (fromIndex != null) { + setValueByPath(toObject, ['index'], fromIndex); + } + const fromLogprobsResult = getValueByPath(fromObject, [ + 'logprobsResult', + ]); + if (fromLogprobsResult != null) { + setValueByPath(toObject, ['logprobsResult'], fromLogprobsResult); + } + const fromSafetyRatings = getValueByPath(fromObject, [ + 'safetyRatings', + ]); + if (fromSafetyRatings != null) { + let transformedList = fromSafetyRatings; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['safetyRatings'], transformedList); + } + const fromUrlContextMetadata = getValueByPath(fromObject, [ + 'urlContextMetadata', + ]); + if (fromUrlContextMetadata != null) { + setValueByPath(toObject, ['urlContextMetadata'], fromUrlContextMetadata); + } + return toObject; +} +function citationMetadataFromMldev$1(fromObject) { + const toObject = {}; + const fromCitations = getValueByPath(fromObject, ['citationSources']); + if (fromCitations != null) { + let transformedList = fromCitations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['citations'], transformedList); + } + return toObject; +} +function contentToMldev$4(fromObject) { + const toObject = {}; + const fromParts = getValueByPath(fromObject, ['parts']); + if (fromParts != null) { + let transformedList = fromParts; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return partToMldev$4(item); + }); + } + setValueByPath(toObject, ['parts'], transformedList); + } + const fromRole = getValueByPath(fromObject, ['role']); + if (fromRole != null) { + setValueByPath(toObject, ['role'], fromRole); + } + return toObject; +} +function createBatchJobConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['batch', 'displayName'], fromDisplayName); + } + if (getValueByPath(fromObject, ['dest']) !== undefined) { + throw new Error('dest parameter is not supported in Gemini API.'); + } + return toObject; +} +function createBatchJobConfigToVertex(fromObject, parentObject) { + const toObject = {}; + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromDisplayName); + } + const fromDest = getValueByPath(fromObject, ['dest']); + if (parentObject !== undefined && fromDest != null) { + setValueByPath(parentObject, ['outputConfig'], batchJobDestinationToVertex(tBatchJobDestination(fromDest))); + } + return toObject; +} +function createBatchJobParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromSrc = getValueByPath(fromObject, ['src']); + if (fromSrc != null) { + setValueByPath(toObject, ['batch', 'inputConfig'], batchJobSourceToMldev(apiClient, tBatchJobSource(apiClient, fromSrc))); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createBatchJobConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function createBatchJobParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['model'], tModel(apiClient, fromModel)); + } + const fromSrc = getValueByPath(fromObject, ['src']); + if (fromSrc != null) { + setValueByPath(toObject, ['inputConfig'], batchJobSourceToVertex(tBatchJobSource(apiClient, fromSrc))); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createBatchJobConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function createEmbeddingsBatchJobConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['batch', 'displayName'], fromDisplayName); + } + return toObject; +} +function createEmbeddingsBatchJobParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromSrc = getValueByPath(fromObject, ['src']); + if (fromSrc != null) { + setValueByPath(toObject, ['batch', 'inputConfig'], embeddingsBatchJobSourceToMldev(apiClient, fromSrc)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createEmbeddingsBatchJobConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function deleteBatchJobParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tBatchJobName(apiClient, fromName)); + } + return toObject; +} +function deleteBatchJobParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tBatchJobName(apiClient, fromName)); + } + return toObject; +} +function deleteResourceJobFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + return toObject; +} +function deleteResourceJobFromVertex(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + return toObject; +} +function embedContentBatchToMldev(apiClient, fromObject) { + const toObject = {}; + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContentsForEmbed(apiClient, fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['requests[]', 'request', 'content'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['_self'], embedContentConfigToMldev$1(fromConfig, toObject)); + moveValueByPath(toObject, { 'requests[].*': 'requests[].request.*' }); + } + return toObject; +} +function embedContentConfigToMldev$1(fromObject, parentObject) { + const toObject = {}; + const fromTaskType = getValueByPath(fromObject, ['taskType']); + if (parentObject !== undefined && fromTaskType != null) { + setValueByPath(parentObject, ['requests[]', 'taskType'], fromTaskType); + } + const fromTitle = getValueByPath(fromObject, ['title']); + if (parentObject !== undefined && fromTitle != null) { + setValueByPath(parentObject, ['requests[]', 'title'], fromTitle); + } + const fromOutputDimensionality = getValueByPath(fromObject, [ + 'outputDimensionality', + ]); + if (parentObject !== undefined && fromOutputDimensionality != null) { + setValueByPath(parentObject, ['requests[]', 'outputDimensionality'], fromOutputDimensionality); + } + if (getValueByPath(fromObject, ['mimeType']) !== undefined) { + throw new Error('mimeType parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['autoTruncate']) !== undefined) { + throw new Error('autoTruncate parameter is not supported in Gemini API.'); + } + return toObject; +} +function embeddingsBatchJobSourceToMldev(apiClient, fromObject) { + const toObject = {}; + const fromFileName = getValueByPath(fromObject, ['fileName']); + if (fromFileName != null) { + setValueByPath(toObject, ['file_name'], fromFileName); + } + const fromInlinedRequests = getValueByPath(fromObject, [ + 'inlinedRequests', + ]); + if (fromInlinedRequests != null) { + setValueByPath(toObject, ['requests'], embedContentBatchToMldev(apiClient, fromInlinedRequests)); + } + return toObject; +} +function fileDataToMldev$4(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromFileUri = getValueByPath(fromObject, ['fileUri']); + if (fromFileUri != null) { + setValueByPath(toObject, ['fileUri'], fromFileUri); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function functionCallToMldev$4(fromObject) { + const toObject = {}; + const fromId = getValueByPath(fromObject, ['id']); + if (fromId != null) { + setValueByPath(toObject, ['id'], fromId); + } + const fromArgs = getValueByPath(fromObject, ['args']); + if (fromArgs != null) { + setValueByPath(toObject, ['args'], fromArgs); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + if (getValueByPath(fromObject, ['partialArgs']) !== undefined) { + throw new Error('partialArgs parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['willContinue']) !== undefined) { + throw new Error('willContinue parameter is not supported in Gemini API.'); + } + return toObject; +} +function functionCallingConfigToMldev$2(fromObject) { + const toObject = {}; + const fromAllowedFunctionNames = getValueByPath(fromObject, [ + 'allowedFunctionNames', + ]); + if (fromAllowedFunctionNames != null) { + setValueByPath(toObject, ['allowedFunctionNames'], fromAllowedFunctionNames); + } + const fromMode = getValueByPath(fromObject, ['mode']); + if (fromMode != null) { + setValueByPath(toObject, ['mode'], fromMode); + } + if (getValueByPath(fromObject, ['streamFunctionCallArguments']) !== + undefined) { + throw new Error('streamFunctionCallArguments parameter is not supported in Gemini API.'); + } + return toObject; +} +function generateContentConfigToMldev$1(apiClient, fromObject, parentObject) { + const toObject = {}; + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['systemInstruction'], contentToMldev$4(tContent(fromSystemInstruction))); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (fromTemperature != null) { + setValueByPath(toObject, ['temperature'], fromTemperature); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (fromTopP != null) { + setValueByPath(toObject, ['topP'], fromTopP); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (fromTopK != null) { + setValueByPath(toObject, ['topK'], fromTopK); + } + const fromCandidateCount = getValueByPath(fromObject, [ + 'candidateCount', + ]); + if (fromCandidateCount != null) { + setValueByPath(toObject, ['candidateCount'], fromCandidateCount); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (fromMaxOutputTokens != null) { + setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens); + } + const fromStopSequences = getValueByPath(fromObject, [ + 'stopSequences', + ]); + if (fromStopSequences != null) { + setValueByPath(toObject, ['stopSequences'], fromStopSequences); + } + const fromResponseLogprobs = getValueByPath(fromObject, [ + 'responseLogprobs', + ]); + if (fromResponseLogprobs != null) { + setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs); + } + const fromLogprobs = getValueByPath(fromObject, ['logprobs']); + if (fromLogprobs != null) { + setValueByPath(toObject, ['logprobs'], fromLogprobs); + } + const fromPresencePenalty = getValueByPath(fromObject, [ + 'presencePenalty', + ]); + if (fromPresencePenalty != null) { + setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty); + } + const fromFrequencyPenalty = getValueByPath(fromObject, [ + 'frequencyPenalty', + ]); + if (fromFrequencyPenalty != null) { + setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (fromSeed != null) { + setValueByPath(toObject, ['seed'], fromSeed); + } + const fromResponseMimeType = getValueByPath(fromObject, [ + 'responseMimeType', + ]); + if (fromResponseMimeType != null) { + setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType); + } + const fromResponseSchema = getValueByPath(fromObject, [ + 'responseSchema', + ]); + if (fromResponseSchema != null) { + setValueByPath(toObject, ['responseSchema'], tSchema(fromResponseSchema)); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + if (getValueByPath(fromObject, ['routingConfig']) !== undefined) { + throw new Error('routingConfig parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['modelSelectionConfig']) !== undefined) { + throw new Error('modelSelectionConfig parameter is not supported in Gemini API.'); + } + const fromSafetySettings = getValueByPath(fromObject, [ + 'safetySettings', + ]); + if (parentObject !== undefined && fromSafetySettings != null) { + let transformedList = fromSafetySettings; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return safetySettingToMldev$1(item); + }); + } + setValueByPath(parentObject, ['safetySettings'], transformedList); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = tTools(fromTools); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToMldev$4(tTool(item)); + }); + } + setValueByPath(parentObject, ['tools'], transformedList); + } + const fromToolConfig = getValueByPath(fromObject, ['toolConfig']); + if (parentObject !== undefined && fromToolConfig != null) { + setValueByPath(parentObject, ['toolConfig'], toolConfigToMldev$2(fromToolConfig)); + } + if (getValueByPath(fromObject, ['labels']) !== undefined) { + throw new Error('labels parameter is not supported in Gemini API.'); + } + const fromCachedContent = getValueByPath(fromObject, [ + 'cachedContent', + ]); + if (parentObject !== undefined && fromCachedContent != null) { + setValueByPath(parentObject, ['cachedContent'], tCachedContentName(apiClient, fromCachedContent)); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (fromResponseModalities != null) { + setValueByPath(toObject, ['responseModalities'], fromResponseModalities); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (fromSpeechConfig != null) { + setValueByPath(toObject, ['speechConfig'], tSpeechConfig(fromSpeechConfig)); + } + if (getValueByPath(fromObject, ['audioTimestamp']) !== undefined) { + throw new Error('audioTimestamp parameter is not supported in Gemini API.'); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (fromThinkingConfig != null) { + setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig); + } + const fromImageConfig = getValueByPath(fromObject, ['imageConfig']); + if (fromImageConfig != null) { + setValueByPath(toObject, ['imageConfig'], imageConfigToMldev$1(fromImageConfig)); + } + const fromEnableEnhancedCivicAnswers = getValueByPath(fromObject, [ + 'enableEnhancedCivicAnswers', + ]); + if (fromEnableEnhancedCivicAnswers != null) { + setValueByPath(toObject, ['enableEnhancedCivicAnswers'], fromEnableEnhancedCivicAnswers); + } + if (getValueByPath(fromObject, ['modelArmorConfig']) !== undefined) { + throw new Error('modelArmorConfig parameter is not supported in Gemini API.'); + } + return toObject; +} +function generateContentResponseFromMldev$1(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromCandidates = getValueByPath(fromObject, ['candidates']); + if (fromCandidates != null) { + let transformedList = fromCandidates; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return candidateFromMldev$1(item); + }); + } + setValueByPath(toObject, ['candidates'], transformedList); + } + const fromModelVersion = getValueByPath(fromObject, ['modelVersion']); + if (fromModelVersion != null) { + setValueByPath(toObject, ['modelVersion'], fromModelVersion); + } + const fromPromptFeedback = getValueByPath(fromObject, [ + 'promptFeedback', + ]); + if (fromPromptFeedback != null) { + setValueByPath(toObject, ['promptFeedback'], fromPromptFeedback); + } + const fromResponseId = getValueByPath(fromObject, ['responseId']); + if (fromResponseId != null) { + setValueByPath(toObject, ['responseId'], fromResponseId); + } + const fromUsageMetadata = getValueByPath(fromObject, [ + 'usageMetadata', + ]); + if (fromUsageMetadata != null) { + setValueByPath(toObject, ['usageMetadata'], fromUsageMetadata); + } + return toObject; +} +function getBatchJobParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tBatchJobName(apiClient, fromName)); + } + return toObject; +} +function getBatchJobParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tBatchJobName(apiClient, fromName)); + } + return toObject; +} +function googleMapsToMldev$4(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['authConfig']) !== undefined) { + throw new Error('authConfig parameter is not supported in Gemini API.'); + } + const fromEnableWidget = getValueByPath(fromObject, ['enableWidget']); + if (fromEnableWidget != null) { + setValueByPath(toObject, ['enableWidget'], fromEnableWidget); + } + return toObject; +} +function googleSearchToMldev$4(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['excludeDomains']) !== undefined) { + throw new Error('excludeDomains parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['blockingConfidence']) !== undefined) { + throw new Error('blockingConfidence parameter is not supported in Gemini API.'); + } + const fromTimeRangeFilter = getValueByPath(fromObject, [ + 'timeRangeFilter', + ]); + if (fromTimeRangeFilter != null) { + setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter); + } + return toObject; +} +function imageConfigToMldev$1(fromObject) { + const toObject = {}; + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (fromAspectRatio != null) { + setValueByPath(toObject, ['aspectRatio'], fromAspectRatio); + } + const fromImageSize = getValueByPath(fromObject, ['imageSize']); + if (fromImageSize != null) { + setValueByPath(toObject, ['imageSize'], fromImageSize); + } + if (getValueByPath(fromObject, ['personGeneration']) !== undefined) { + throw new Error('personGeneration parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['outputMimeType']) !== undefined) { + throw new Error('outputMimeType parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['outputCompressionQuality']) !== + undefined) { + throw new Error('outputCompressionQuality parameter is not supported in Gemini API.'); + } + return toObject; +} +function inlinedRequestToMldev(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['request', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return contentToMldev$4(item); + }); + } + setValueByPath(toObject, ['request', 'contents'], transformedList); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['request', 'generationConfig'], generateContentConfigToMldev$1(apiClient, fromConfig, getValueByPath(toObject, ['request'], {}))); + } + return toObject; +} +function inlinedResponseFromMldev(fromObject) { + const toObject = {}; + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], generateContentResponseFromMldev$1(fromResponse)); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + return toObject; +} +function listBatchJobsConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + if (getValueByPath(fromObject, ['filter']) !== undefined) { + throw new Error('filter parameter is not supported in Gemini API.'); + } + return toObject; +} +function listBatchJobsConfigToVertex(fromObject, parentObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + const fromFilter = getValueByPath(fromObject, ['filter']); + if (parentObject !== undefined && fromFilter != null) { + setValueByPath(parentObject, ['_query', 'filter'], fromFilter); + } + return toObject; +} +function listBatchJobsParametersToMldev(fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listBatchJobsConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function listBatchJobsParametersToVertex(fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listBatchJobsConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function listBatchJobsResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromBatchJobs = getValueByPath(fromObject, ['operations']); + if (fromBatchJobs != null) { + let transformedList = fromBatchJobs; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return batchJobFromMldev(item); + }); + } + setValueByPath(toObject, ['batchJobs'], transformedList); + } + return toObject; +} +function listBatchJobsResponseFromVertex(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromBatchJobs = getValueByPath(fromObject, [ + 'batchPredictionJobs', + ]); + if (fromBatchJobs != null) { + let transformedList = fromBatchJobs; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return batchJobFromVertex(item); + }); + } + setValueByPath(toObject, ['batchJobs'], transformedList); + } + return toObject; +} +function partToMldev$4(fromObject) { + const toObject = {}; + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromCodeExecutionResult = getValueByPath(fromObject, [ + 'codeExecutionResult', + ]); + if (fromCodeExecutionResult != null) { + setValueByPath(toObject, ['codeExecutionResult'], fromCodeExecutionResult); + } + const fromExecutableCode = getValueByPath(fromObject, [ + 'executableCode', + ]); + if (fromExecutableCode != null) { + setValueByPath(toObject, ['executableCode'], fromExecutableCode); + } + const fromFileData = getValueByPath(fromObject, ['fileData']); + if (fromFileData != null) { + setValueByPath(toObject, ['fileData'], fileDataToMldev$4(fromFileData)); + } + const fromFunctionCall = getValueByPath(fromObject, ['functionCall']); + if (fromFunctionCall != null) { + setValueByPath(toObject, ['functionCall'], functionCallToMldev$4(fromFunctionCall)); + } + const fromFunctionResponse = getValueByPath(fromObject, [ + 'functionResponse', + ]); + if (fromFunctionResponse != null) { + setValueByPath(toObject, ['functionResponse'], fromFunctionResponse); + } + const fromInlineData = getValueByPath(fromObject, ['inlineData']); + if (fromInlineData != null) { + setValueByPath(toObject, ['inlineData'], blobToMldev$4(fromInlineData)); + } + const fromText = getValueByPath(fromObject, ['text']); + if (fromText != null) { + setValueByPath(toObject, ['text'], fromText); + } + const fromThought = getValueByPath(fromObject, ['thought']); + if (fromThought != null) { + setValueByPath(toObject, ['thought'], fromThought); + } + const fromThoughtSignature = getValueByPath(fromObject, [ + 'thoughtSignature', + ]); + if (fromThoughtSignature != null) { + setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature); + } + const fromVideoMetadata = getValueByPath(fromObject, [ + 'videoMetadata', + ]); + if (fromVideoMetadata != null) { + setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata); + } + return toObject; +} +function safetySettingToMldev$1(fromObject) { + const toObject = {}; + const fromCategory = getValueByPath(fromObject, ['category']); + if (fromCategory != null) { + setValueByPath(toObject, ['category'], fromCategory); + } + if (getValueByPath(fromObject, ['method']) !== undefined) { + throw new Error('method parameter is not supported in Gemini API.'); + } + const fromThreshold = getValueByPath(fromObject, ['threshold']); + if (fromThreshold != null) { + setValueByPath(toObject, ['threshold'], fromThreshold); + } + return toObject; +} +function toolConfigToMldev$2(fromObject) { + const toObject = {}; + const fromRetrievalConfig = getValueByPath(fromObject, [ + 'retrievalConfig', + ]); + if (fromRetrievalConfig != null) { + setValueByPath(toObject, ['retrievalConfig'], fromRetrievalConfig); + } + const fromFunctionCallingConfig = getValueByPath(fromObject, [ + 'functionCallingConfig', + ]); + if (fromFunctionCallingConfig != null) { + setValueByPath(toObject, ['functionCallingConfig'], functionCallingConfigToMldev$2(fromFunctionCallingConfig)); + } + return toObject; +} +function toolToMldev$4(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['retrieval']) !== undefined) { + throw new Error('retrieval parameter is not supported in Gemini API.'); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + const fromFileSearch = getValueByPath(fromObject, ['fileSearch']); + if (fromFileSearch != null) { + setValueByPath(toObject, ['fileSearch'], fromFileSearch); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + if (getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined) { + throw new Error('enterpriseWebSearch parameter is not supported in Gemini API.'); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], googleMapsToMldev$4(fromGoogleMaps)); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], googleSearchToMldev$4(fromGoogleSearch)); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +var PagedItem; +(function (PagedItem) { + PagedItem["PAGED_ITEM_BATCH_JOBS"] = "batchJobs"; + PagedItem["PAGED_ITEM_MODELS"] = "models"; + PagedItem["PAGED_ITEM_TUNING_JOBS"] = "tuningJobs"; + PagedItem["PAGED_ITEM_FILES"] = "files"; + PagedItem["PAGED_ITEM_CACHED_CONTENTS"] = "cachedContents"; + PagedItem["PAGED_ITEM_FILE_SEARCH_STORES"] = "fileSearchStores"; + PagedItem["PAGED_ITEM_DOCUMENTS"] = "documents"; +})(PagedItem || (PagedItem = {})); +/** + * Pager class for iterating through paginated results. + */ +class Pager { + constructor(name, request, response, params) { + this.pageInternal = []; + this.paramsInternal = {}; + this.requestInternal = request; + this.init(name, response, params); + } + init(name, response, params) { + var _a, _b; + this.nameInternal = name; + this.pageInternal = response[this.nameInternal] || []; + this.sdkHttpResponseInternal = response === null || response === void 0 ? void 0 : response.sdkHttpResponse; + this.idxInternal = 0; + let requestParams = { config: {} }; + if (!params || Object.keys(params).length === 0) { + requestParams = { config: {} }; + } + else if (typeof params === 'object') { + requestParams = Object.assign({}, params); + } + else { + requestParams = params; + } + if (requestParams['config']) { + requestParams['config']['pageToken'] = response['nextPageToken']; + } + this.paramsInternal = requestParams; + this.pageInternalSize = + (_b = (_a = requestParams['config']) === null || _a === void 0 ? void 0 : _a['pageSize']) !== null && _b !== void 0 ? _b : this.pageInternal.length; + } + initNextPage(response) { + this.init(this.nameInternal, response, this.paramsInternal); + } + /** + * Returns the current page, which is a list of items. + * + * @remarks + * The first page is retrieved when the pager is created. The returned list of + * items could be a subset of the entire list. + */ + get page() { + return this.pageInternal; + } + /** + * Returns the type of paged item (for example, ``batch_jobs``). + */ + get name() { + return this.nameInternal; + } + /** + * Returns the length of the page fetched each time by this pager. + * + * @remarks + * The number of items in the page is less than or equal to the page length. + */ + get pageSize() { + return this.pageInternalSize; + } + /** + * Returns the headers of the API response. + */ + get sdkHttpResponse() { + return this.sdkHttpResponseInternal; + } + /** + * Returns the parameters when making the API request for the next page. + * + * @remarks + * Parameters contain a set of optional configs that can be + * used to customize the API request. For example, the `pageToken` parameter + * contains the token to request the next page. + */ + get params() { + return this.paramsInternal; + } + /** + * Returns the total number of items in the current page. + */ + get pageLength() { + return this.pageInternal.length; + } + /** + * Returns the item at the given index. + */ + getItem(index) { + return this.pageInternal[index]; + } + /** + * Returns an async iterator that support iterating through all items + * retrieved from the API. + * + * @remarks + * The iterator will automatically fetch the next page if there are more items + * to fetch from the API. + * + * @example + * + * ```ts + * const pager = await ai.files.list({config: {pageSize: 10}}); + * for await (const file of pager) { + * console.log(file.name); + * } + * ``` + */ + [Symbol.asyncIterator]() { + return { + next: async () => { + if (this.idxInternal >= this.pageLength) { + if (this.hasNextPage()) { + await this.nextPage(); + } + else { + return { value: undefined, done: true }; + } + } + const item = this.getItem(this.idxInternal); + this.idxInternal += 1; + return { value: item, done: false }; + }, + return: async () => { + return { value: undefined, done: true }; + }, + }; + } + /** + * Fetches the next page of items. This makes a new API request. + * + * @throws {Error} If there are no more pages to fetch. + * + * @example + * + * ```ts + * const pager = await ai.files.list({config: {pageSize: 10}}); + * let page = pager.page; + * while (true) { + * for (const file of page) { + * console.log(file.name); + * } + * if (!pager.hasNextPage()) { + * break; + * } + * page = await pager.nextPage(); + * } + * ``` + */ + async nextPage() { + if (!this.hasNextPage()) { + throw new Error('No more pages to fetch.'); + } + const response = await this.requestInternal(this.params); + this.initNextPage(response); + return this.page; + } + /** + * Returns true if there are more pages to fetch from the API. + */ + hasNextPage() { + var _a; + if (((_a = this.params['config']) === null || _a === void 0 ? void 0 : _a['pageToken']) !== undefined) { + return true; + } + return false; + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Batches extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + /** + * Lists batch jobs. + * + * @param params - The parameters for the list request. + * @return - A pager of batch jobs. + * + * @example + * ```ts + * const batchJobs = await ai.batches.list({config: {'pageSize': 2}}); + * for await (const batchJob of batchJobs) { + * console.log(batchJob); + * } + * ``` + */ + this.list = async (params = {}) => { + return new Pager(PagedItem.PAGED_ITEM_BATCH_JOBS, (x) => this.listInternal(x), await this.listInternal(params), params); + }; + /** + * Create batch job. + * + * @param params - The parameters for create batch job request. + * @return The created batch job. + * + * @example + * ```ts + * const response = await ai.batches.create({ + * model: 'gemini-2.0-flash', + * src: {gcsUri: 'gs://bucket/path/to/file.jsonl', format: 'jsonl'}, + * config: { + * dest: {gcsUri: 'gs://bucket/path/output/directory', format: 'jsonl'}, + * } + * }); + * console.log(response); + * ``` + */ + this.create = async (params) => { + if (this.apiClient.isVertexAI()) { + // Format destination if not provided + // Cast params.src as Vertex AI path does not handle InlinedRequest[] + params.config = this.formatDestination(params.src, params.config); + } + return this.createInternal(params); + }; + /** + * **Experimental** Creates an embedding batch job. + * + * @param params - The parameters for create embedding batch job request. + * @return The created batch job. + * + * @example + * ```ts + * const response = await ai.batches.createEmbeddings({ + * model: 'text-embedding-004', + * src: {fileName: 'files/my_embedding_input'}, + * }); + * console.log(response); + * ``` + */ + this.createEmbeddings = async (params) => { + console.warn('batches.createEmbeddings() is experimental and may change without notice.'); + if (this.apiClient.isVertexAI()) { + throw new Error('Vertex AI does not support batches.createEmbeddings.'); + } + return this.createEmbeddingsInternal(params); + }; + } + // Helper function to handle inlined generate content requests + createInlinedGenerateContentRequest(params) { + const body = createBatchJobParametersToMldev(this.apiClient, // Use instance apiClient + params); + const urlParams = body['_url']; + const path = formatMap('{model}:batchGenerateContent', urlParams); + const batch = body['batch']; + const inputConfig = batch['inputConfig']; + const requestsWrapper = inputConfig['requests']; + const requests = requestsWrapper['requests']; + const newRequests = []; + for (const request of requests) { + const requestDict = Object.assign({}, request); // Clone + if (requestDict['systemInstruction']) { + const systemInstructionValue = requestDict['systemInstruction']; + delete requestDict['systemInstruction']; + const requestContent = requestDict['request']; + requestContent['systemInstruction'] = systemInstructionValue; + requestDict['request'] = requestContent; + } + newRequests.push(requestDict); + } + requestsWrapper['requests'] = newRequests; + delete body['config']; + delete body['_url']; + delete body['_query']; + return { path, body }; + } + // Helper function to get the first GCS URI + getGcsUri(src) { + if (typeof src === 'string') { + return src.startsWith('gs://') ? src : undefined; + } + if (!Array.isArray(src) && src.gcsUri && src.gcsUri.length > 0) { + return src.gcsUri[0]; + } + return undefined; + } + // Helper function to get the BigQuery URI + getBigqueryUri(src) { + if (typeof src === 'string') { + return src.startsWith('bq://') ? src : undefined; + } + if (!Array.isArray(src)) { + return src.bigqueryUri; + } + return undefined; + } + // Function to format the destination configuration for Vertex AI + formatDestination(src, config) { + const newConfig = config ? Object.assign({}, config) : {}; + const timestampStr = Date.now().toString(); + if (!newConfig.displayName) { + newConfig.displayName = `genaiBatchJob_${timestampStr}`; + } + if (newConfig.dest === undefined) { + const gcsUri = this.getGcsUri(src); + const bigqueryUri = this.getBigqueryUri(src); + if (gcsUri) { + if (gcsUri.endsWith('.jsonl')) { + // For .jsonl files, remove suffix and add /dest + newConfig.dest = `${gcsUri.slice(0, -6)}/dest`; + } + else { + // Fallback for other GCS URIs + newConfig.dest = `${gcsUri}_dest_${timestampStr}`; + } + } + else if (bigqueryUri) { + newConfig.dest = `${bigqueryUri}_dest_${timestampStr}`; + } + else { + throw new Error('Unsupported source for Vertex AI: No GCS or BigQuery URI found.'); + } + } + return newConfig; + } + /** + * Internal method to create batch job. + * + * @param params - The parameters for create batch job request. + * @return The created batch job. + * + */ + async createInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = createBatchJobParametersToVertex(this.apiClient, params); + path = formatMap('batchPredictionJobs', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = batchJobFromVertex(apiResponse); + return resp; + }); + } + else { + const body = createBatchJobParametersToMldev(this.apiClient, params); + path = formatMap('{model}:batchGenerateContent', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = batchJobFromMldev(apiResponse); + return resp; + }); + } + } + /** + * Internal method to create batch job. + * + * @param params - The parameters for create batch job request. + * @return The created batch job. + * + */ + async createEmbeddingsInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = createEmbeddingsBatchJobParametersToMldev(this.apiClient, params); + path = formatMap('{model}:asyncBatchEmbedContent', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = batchJobFromMldev(apiResponse); + return resp; + }); + } + } + /** + * Gets batch job configurations. + * + * @param params - The parameters for the get request. + * @return The batch job. + * + * @example + * ```ts + * await ai.batches.get({name: '...'}); // The server-generated resource name. + * ``` + */ + async get(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = getBatchJobParametersToVertex(this.apiClient, params); + path = formatMap('batchPredictionJobs/{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = batchJobFromVertex(apiResponse); + return resp; + }); + } + else { + const body = getBatchJobParametersToMldev(this.apiClient, params); + path = formatMap('batches/{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = batchJobFromMldev(apiResponse); + return resp; + }); + } + } + /** + * Cancels a batch job. + * + * @param params - The parameters for the cancel request. + * @return The empty response returned by the API. + * + * @example + * ```ts + * await ai.batches.cancel({name: '...'}); // The server-generated resource name. + * ``` + */ + async cancel(params) { + var _a, _b, _c, _d; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = cancelBatchJobParametersToVertex(this.apiClient, params); + path = formatMap('batchPredictionJobs/{name}:cancel', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + await this.apiClient.request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }); + } + else { + const body = cancelBatchJobParametersToMldev(this.apiClient, params); + path = formatMap('batches/{name}:cancel', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + await this.apiClient.request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }); + } + } + async listInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = listBatchJobsParametersToVertex(params); + path = formatMap('batchPredictionJobs', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listBatchJobsResponseFromVertex(apiResponse); + const typedResp = new ListBatchJobsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = listBatchJobsParametersToMldev(params); + path = formatMap('batches', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listBatchJobsResponseFromMldev(apiResponse); + const typedResp = new ListBatchJobsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Deletes a batch job. + * + * @param params - The parameters for the delete request. + * @return The empty response returned by the API. + * + * @example + * ```ts + * await ai.batches.delete({name: '...'}); // The server-generated resource name. + * ``` + */ + async delete(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = deleteBatchJobParametersToVertex(this.apiClient, params); + path = formatMap('batchPredictionJobs/{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = deleteResourceJobFromVertex(apiResponse); + return resp; + }); + } + else { + const body = deleteBatchJobParametersToMldev(this.apiClient, params); + path = formatMap('batches/{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = deleteResourceJobFromMldev(apiResponse); + return resp; + }); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function blobToMldev$3(fromObject) { + const toObject = {}; + const fromData = getValueByPath(fromObject, ['data']); + if (fromData != null) { + setValueByPath(toObject, ['data'], fromData); + } + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function contentToMldev$3(fromObject) { + const toObject = {}; + const fromParts = getValueByPath(fromObject, ['parts']); + if (fromParts != null) { + let transformedList = fromParts; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return partToMldev$3(item); + }); + } + setValueByPath(toObject, ['parts'], transformedList); + } + const fromRole = getValueByPath(fromObject, ['role']); + if (fromRole != null) { + setValueByPath(toObject, ['role'], fromRole); + } + return toObject; +} +function createCachedContentConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromTtl = getValueByPath(fromObject, ['ttl']); + if (parentObject !== undefined && fromTtl != null) { + setValueByPath(parentObject, ['ttl'], fromTtl); + } + const fromExpireTime = getValueByPath(fromObject, ['expireTime']); + if (parentObject !== undefined && fromExpireTime != null) { + setValueByPath(parentObject, ['expireTime'], fromExpireTime); + } + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromDisplayName); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (parentObject !== undefined && fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return contentToMldev$3(item); + }); + } + setValueByPath(parentObject, ['contents'], transformedList); + } + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['systemInstruction'], contentToMldev$3(tContent(fromSystemInstruction))); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = fromTools; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToMldev$3(item); + }); + } + setValueByPath(parentObject, ['tools'], transformedList); + } + const fromToolConfig = getValueByPath(fromObject, ['toolConfig']); + if (parentObject !== undefined && fromToolConfig != null) { + setValueByPath(parentObject, ['toolConfig'], toolConfigToMldev$1(fromToolConfig)); + } + if (getValueByPath(fromObject, ['kmsKeyName']) !== undefined) { + throw new Error('kmsKeyName parameter is not supported in Gemini API.'); + } + return toObject; +} +function createCachedContentConfigToVertex(fromObject, parentObject) { + const toObject = {}; + const fromTtl = getValueByPath(fromObject, ['ttl']); + if (parentObject !== undefined && fromTtl != null) { + setValueByPath(parentObject, ['ttl'], fromTtl); + } + const fromExpireTime = getValueByPath(fromObject, ['expireTime']); + if (parentObject !== undefined && fromExpireTime != null) { + setValueByPath(parentObject, ['expireTime'], fromExpireTime); + } + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromDisplayName); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (parentObject !== undefined && fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(parentObject, ['contents'], transformedList); + } + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['systemInstruction'], tContent(fromSystemInstruction)); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = fromTools; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToVertex$2(item); + }); + } + setValueByPath(parentObject, ['tools'], transformedList); + } + const fromToolConfig = getValueByPath(fromObject, ['toolConfig']); + if (parentObject !== undefined && fromToolConfig != null) { + setValueByPath(parentObject, ['toolConfig'], fromToolConfig); + } + const fromKmsKeyName = getValueByPath(fromObject, ['kmsKeyName']); + if (parentObject !== undefined && fromKmsKeyName != null) { + setValueByPath(parentObject, ['encryption_spec', 'kmsKeyName'], fromKmsKeyName); + } + return toObject; +} +function createCachedContentParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['model'], tCachesModel(apiClient, fromModel)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createCachedContentConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function createCachedContentParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['model'], tCachesModel(apiClient, fromModel)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createCachedContentConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function deleteCachedContentParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tCachedContentName(apiClient, fromName)); + } + return toObject; +} +function deleteCachedContentParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tCachedContentName(apiClient, fromName)); + } + return toObject; +} +function deleteCachedContentResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function deleteCachedContentResponseFromVertex(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function fileDataToMldev$3(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromFileUri = getValueByPath(fromObject, ['fileUri']); + if (fromFileUri != null) { + setValueByPath(toObject, ['fileUri'], fromFileUri); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function functionCallToMldev$3(fromObject) { + const toObject = {}; + const fromId = getValueByPath(fromObject, ['id']); + if (fromId != null) { + setValueByPath(toObject, ['id'], fromId); + } + const fromArgs = getValueByPath(fromObject, ['args']); + if (fromArgs != null) { + setValueByPath(toObject, ['args'], fromArgs); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + if (getValueByPath(fromObject, ['partialArgs']) !== undefined) { + throw new Error('partialArgs parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['willContinue']) !== undefined) { + throw new Error('willContinue parameter is not supported in Gemini API.'); + } + return toObject; +} +function functionCallingConfigToMldev$1(fromObject) { + const toObject = {}; + const fromAllowedFunctionNames = getValueByPath(fromObject, [ + 'allowedFunctionNames', + ]); + if (fromAllowedFunctionNames != null) { + setValueByPath(toObject, ['allowedFunctionNames'], fromAllowedFunctionNames); + } + const fromMode = getValueByPath(fromObject, ['mode']); + if (fromMode != null) { + setValueByPath(toObject, ['mode'], fromMode); + } + if (getValueByPath(fromObject, ['streamFunctionCallArguments']) !== + undefined) { + throw new Error('streamFunctionCallArguments parameter is not supported in Gemini API.'); + } + return toObject; +} +function functionDeclarationToVertex$2(fromObject) { + const toObject = {}; + const fromDescription = getValueByPath(fromObject, ['description']); + if (fromDescription != null) { + setValueByPath(toObject, ['description'], fromDescription); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromParameters = getValueByPath(fromObject, ['parameters']); + if (fromParameters != null) { + setValueByPath(toObject, ['parameters'], fromParameters); + } + const fromParametersJsonSchema = getValueByPath(fromObject, [ + 'parametersJsonSchema', + ]); + if (fromParametersJsonSchema != null) { + setValueByPath(toObject, ['parametersJsonSchema'], fromParametersJsonSchema); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], fromResponse); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + if (getValueByPath(fromObject, ['behavior']) !== undefined) { + throw new Error('behavior parameter is not supported in Vertex AI.'); + } + return toObject; +} +function getCachedContentParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tCachedContentName(apiClient, fromName)); + } + return toObject; +} +function getCachedContentParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tCachedContentName(apiClient, fromName)); + } + return toObject; +} +function googleMapsToMldev$3(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['authConfig']) !== undefined) { + throw new Error('authConfig parameter is not supported in Gemini API.'); + } + const fromEnableWidget = getValueByPath(fromObject, ['enableWidget']); + if (fromEnableWidget != null) { + setValueByPath(toObject, ['enableWidget'], fromEnableWidget); + } + return toObject; +} +function googleSearchToMldev$3(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['excludeDomains']) !== undefined) { + throw new Error('excludeDomains parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['blockingConfidence']) !== undefined) { + throw new Error('blockingConfidence parameter is not supported in Gemini API.'); + } + const fromTimeRangeFilter = getValueByPath(fromObject, [ + 'timeRangeFilter', + ]); + if (fromTimeRangeFilter != null) { + setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter); + } + return toObject; +} +function listCachedContentsConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + return toObject; +} +function listCachedContentsConfigToVertex(fromObject, parentObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + return toObject; +} +function listCachedContentsParametersToMldev(fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listCachedContentsConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function listCachedContentsParametersToVertex(fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listCachedContentsConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function listCachedContentsResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromCachedContents = getValueByPath(fromObject, [ + 'cachedContents', + ]); + if (fromCachedContents != null) { + let transformedList = fromCachedContents; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['cachedContents'], transformedList); + } + return toObject; +} +function listCachedContentsResponseFromVertex(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromCachedContents = getValueByPath(fromObject, [ + 'cachedContents', + ]); + if (fromCachedContents != null) { + let transformedList = fromCachedContents; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['cachedContents'], transformedList); + } + return toObject; +} +function partToMldev$3(fromObject) { + const toObject = {}; + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromCodeExecutionResult = getValueByPath(fromObject, [ + 'codeExecutionResult', + ]); + if (fromCodeExecutionResult != null) { + setValueByPath(toObject, ['codeExecutionResult'], fromCodeExecutionResult); + } + const fromExecutableCode = getValueByPath(fromObject, [ + 'executableCode', + ]); + if (fromExecutableCode != null) { + setValueByPath(toObject, ['executableCode'], fromExecutableCode); + } + const fromFileData = getValueByPath(fromObject, ['fileData']); + if (fromFileData != null) { + setValueByPath(toObject, ['fileData'], fileDataToMldev$3(fromFileData)); + } + const fromFunctionCall = getValueByPath(fromObject, ['functionCall']); + if (fromFunctionCall != null) { + setValueByPath(toObject, ['functionCall'], functionCallToMldev$3(fromFunctionCall)); + } + const fromFunctionResponse = getValueByPath(fromObject, [ + 'functionResponse', + ]); + if (fromFunctionResponse != null) { + setValueByPath(toObject, ['functionResponse'], fromFunctionResponse); + } + const fromInlineData = getValueByPath(fromObject, ['inlineData']); + if (fromInlineData != null) { + setValueByPath(toObject, ['inlineData'], blobToMldev$3(fromInlineData)); + } + const fromText = getValueByPath(fromObject, ['text']); + if (fromText != null) { + setValueByPath(toObject, ['text'], fromText); + } + const fromThought = getValueByPath(fromObject, ['thought']); + if (fromThought != null) { + setValueByPath(toObject, ['thought'], fromThought); + } + const fromThoughtSignature = getValueByPath(fromObject, [ + 'thoughtSignature', + ]); + if (fromThoughtSignature != null) { + setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature); + } + const fromVideoMetadata = getValueByPath(fromObject, [ + 'videoMetadata', + ]); + if (fromVideoMetadata != null) { + setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata); + } + return toObject; +} +function toolConfigToMldev$1(fromObject) { + const toObject = {}; + const fromRetrievalConfig = getValueByPath(fromObject, [ + 'retrievalConfig', + ]); + if (fromRetrievalConfig != null) { + setValueByPath(toObject, ['retrievalConfig'], fromRetrievalConfig); + } + const fromFunctionCallingConfig = getValueByPath(fromObject, [ + 'functionCallingConfig', + ]); + if (fromFunctionCallingConfig != null) { + setValueByPath(toObject, ['functionCallingConfig'], functionCallingConfigToMldev$1(fromFunctionCallingConfig)); + } + return toObject; +} +function toolToMldev$3(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['retrieval']) !== undefined) { + throw new Error('retrieval parameter is not supported in Gemini API.'); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + const fromFileSearch = getValueByPath(fromObject, ['fileSearch']); + if (fromFileSearch != null) { + setValueByPath(toObject, ['fileSearch'], fromFileSearch); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + if (getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined) { + throw new Error('enterpriseWebSearch parameter is not supported in Gemini API.'); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], googleMapsToMldev$3(fromGoogleMaps)); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], googleSearchToMldev$3(fromGoogleSearch)); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} +function toolToVertex$2(fromObject) { + const toObject = {}; + const fromRetrieval = getValueByPath(fromObject, ['retrieval']); + if (fromRetrieval != null) { + setValueByPath(toObject, ['retrieval'], fromRetrieval); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + if (getValueByPath(fromObject, ['fileSearch']) !== undefined) { + throw new Error('fileSearch parameter is not supported in Vertex AI.'); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + const fromEnterpriseWebSearch = getValueByPath(fromObject, [ + 'enterpriseWebSearch', + ]); + if (fromEnterpriseWebSearch != null) { + setValueByPath(toObject, ['enterpriseWebSearch'], fromEnterpriseWebSearch); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return functionDeclarationToVertex$2(item); + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], fromGoogleMaps); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], fromGoogleSearch); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} +function updateCachedContentConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromTtl = getValueByPath(fromObject, ['ttl']); + if (parentObject !== undefined && fromTtl != null) { + setValueByPath(parentObject, ['ttl'], fromTtl); + } + const fromExpireTime = getValueByPath(fromObject, ['expireTime']); + if (parentObject !== undefined && fromExpireTime != null) { + setValueByPath(parentObject, ['expireTime'], fromExpireTime); + } + return toObject; +} +function updateCachedContentConfigToVertex(fromObject, parentObject) { + const toObject = {}; + const fromTtl = getValueByPath(fromObject, ['ttl']); + if (parentObject !== undefined && fromTtl != null) { + setValueByPath(parentObject, ['ttl'], fromTtl); + } + const fromExpireTime = getValueByPath(fromObject, ['expireTime']); + if (parentObject !== undefined && fromExpireTime != null) { + setValueByPath(parentObject, ['expireTime'], fromExpireTime); + } + return toObject; +} +function updateCachedContentParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tCachedContentName(apiClient, fromName)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + updateCachedContentConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function updateCachedContentParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], tCachedContentName(apiClient, fromName)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + updateCachedContentConfigToVertex(fromConfig, toObject); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Caches extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + /** + * Lists cached contents. + * + * @param params - The parameters for the list request. + * @return - A pager of cached contents. + * + * @example + * ```ts + * const cachedContents = await ai.caches.list({config: {'pageSize': 2}}); + * for await (const cachedContent of cachedContents) { + * console.log(cachedContent); + * } + * ``` + */ + this.list = async (params = {}) => { + return new Pager(PagedItem.PAGED_ITEM_CACHED_CONTENTS, (x) => this.listInternal(x), await this.listInternal(params), params); + }; + } + /** + * Creates a cached contents resource. + * + * @remarks + * Context caching is only supported for specific models. See [Gemini + * Developer API reference](https://ai.google.dev/gemini-api/docs/caching?lang=node/context-cac) + * and [Vertex AI reference](https://cloud.google.com/vertex-ai/generative-ai/docs/context-cache/context-cache-overview#supported_models) + * for more information. + * + * @param params - The parameters for the create request. + * @return The created cached content. + * + * @example + * ```ts + * const contents = ...; // Initialize the content to cache. + * const response = await ai.caches.create({ + * model: 'gemini-2.0-flash-001', + * config: { + * 'contents': contents, + * 'displayName': 'test cache', + * 'systemInstruction': 'What is the sum of the two pdfs?', + * 'ttl': '86400s', + * } + * }); + * ``` + */ + async create(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = createCachedContentParametersToVertex(this.apiClient, params); + path = formatMap('cachedContents', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + else { + const body = createCachedContentParametersToMldev(this.apiClient, params); + path = formatMap('cachedContents', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } + /** + * Gets cached content configurations. + * + * @param params - The parameters for the get request. + * @return The cached content. + * + * @example + * ```ts + * await ai.caches.get({name: '...'}); // The server-generated resource name. + * ``` + */ + async get(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = getCachedContentParametersToVertex(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + else { + const body = getCachedContentParametersToMldev(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } + /** + * Deletes cached content. + * + * @param params - The parameters for the delete request. + * @return The empty response returned by the API. + * + * @example + * ```ts + * await ai.caches.delete({name: '...'}); // The server-generated resource name. + * ``` + */ + async delete(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = deleteCachedContentParametersToVertex(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = deleteCachedContentResponseFromVertex(apiResponse); + const typedResp = new DeleteCachedContentResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = deleteCachedContentParametersToMldev(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = deleteCachedContentResponseFromMldev(apiResponse); + const typedResp = new DeleteCachedContentResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Updates cached content configurations. + * + * @param params - The parameters for the update request. + * @return The updated cached content. + * + * @example + * ```ts + * const response = await ai.caches.update({ + * name: '...', // The server-generated resource name. + * config: {'ttl': '7600s'} + * }); + * ``` + */ + async update(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = updateCachedContentParametersToVertex(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'PATCH', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + else { + const body = updateCachedContentParametersToMldev(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'PATCH', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } + async listInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = listCachedContentsParametersToVertex(params); + path = formatMap('cachedContents', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listCachedContentsResponseFromVertex(apiResponse); + const typedResp = new ListCachedContentsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = listCachedContentsParametersToMldev(params); + path = formatMap('cachedContents', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listCachedContentsResponseFromMldev(apiResponse); + const typedResp = new ListCachedContentsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } +} + +/****************************************************************************** +Copyright (c) Microsoft Corporation. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +***************************************************************************** */ +/* global Reflect, Promise, SuppressedError, Symbol, Iterator */ + + +function __rest(s, e) { + var t = {}; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) + t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === "function") + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { + if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) + t[p[i]] = s[p[i]]; + } + return t; +} + +function __values(o) { + var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; + if (m) return m.call(o); + if (o && typeof o.length === "number") return { + next: function () { + if (o && i >= o.length) o = void 0; + return { value: o && o[i++], done: !o }; + } + }; + throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); +} + +function __await(v) { + return this instanceof __await ? (this.v = v, this) : new __await(v); +} + +function __asyncGenerator(thisArg, _arguments, generator) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var g = generator.apply(thisArg, _arguments || []), i, q = []; + return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i; + function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; } + function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } } + function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function fulfill(value) { resume("next", value); } + function reject(value) { resume("throw", value); } + function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } +} + +function __asyncValues(o) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var m = o[Symbol.asyncIterator], i; + return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); + function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } + function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } +} + +typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { + var e = new Error(message); + return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Returns true if the response is valid, false otherwise. + */ +function isValidResponse(response) { + var _a; + if (response.candidates == undefined || response.candidates.length === 0) { + return false; + } + const content = (_a = response.candidates[0]) === null || _a === void 0 ? void 0 : _a.content; + if (content === undefined) { + return false; + } + return isValidContent(content); +} +function isValidContent(content) { + if (content.parts === undefined || content.parts.length === 0) { + return false; + } + for (const part of content.parts) { + if (part === undefined || Object.keys(part).length === 0) { + return false; + } + } + return true; +} +/** + * Validates the history contains the correct roles. + * + * @throws Error if the history does not start with a user turn. + * @throws Error if the history contains an invalid role. + */ +function validateHistory(history) { + // Empty history is valid. + if (history.length === 0) { + return; + } + for (const content of history) { + if (content.role !== 'user' && content.role !== 'model') { + throw new Error(`Role must be user or model, but got ${content.role}.`); + } + } +} +/** + * Extracts the curated (valid) history from a comprehensive history. + * + * @remarks + * The model may sometimes generate invalid or empty contents(e.g., due to safty + * filters or recitation). Extracting valid turns from the history + * ensures that subsequent requests could be accpeted by the model. + */ +function extractCuratedHistory(comprehensiveHistory) { + if (comprehensiveHistory === undefined || comprehensiveHistory.length === 0) { + return []; + } + const curatedHistory = []; + const length = comprehensiveHistory.length; + let i = 0; + while (i < length) { + if (comprehensiveHistory[i].role === 'user') { + curatedHistory.push(comprehensiveHistory[i]); + i++; + } + else { + const modelOutput = []; + let isValid = true; + while (i < length && comprehensiveHistory[i].role === 'model') { + modelOutput.push(comprehensiveHistory[i]); + if (isValid && !isValidContent(comprehensiveHistory[i])) { + isValid = false; + } + i++; + } + if (isValid) { + curatedHistory.push(...modelOutput); + } + else { + // Remove the last user input when model content is invalid. + curatedHistory.pop(); + } + } + } + return curatedHistory; +} +/** + * A utility class to create a chat session. + */ +class Chats { + constructor(modelsModule, apiClient) { + this.modelsModule = modelsModule; + this.apiClient = apiClient; + } + /** + * Creates a new chat session. + * + * @remarks + * The config in the params will be used for all requests within the chat + * session unless overridden by a per-request `config` in + * @see {@link types.SendMessageParameters#config}. + * + * @param params - Parameters for creating a chat session. + * @returns A new chat session. + * + * @example + * ```ts + * const chat = ai.chats.create({ + * model: 'gemini-2.0-flash' + * config: { + * temperature: 0.5, + * maxOutputTokens: 1024, + * } + * }); + * ``` + */ + create(params) { + return new Chat(this.apiClient, this.modelsModule, params.model, params.config, + // Deep copy the history to avoid mutating the history outside of the + // chat session. + structuredClone(params.history)); + } +} +/** + * Chat session that enables sending messages to the model with previous + * conversation context. + * + * @remarks + * The session maintains all the turns between user and model. + */ +class Chat { + constructor(apiClient, modelsModule, model, config = {}, history = []) { + this.apiClient = apiClient; + this.modelsModule = modelsModule; + this.model = model; + this.config = config; + this.history = history; + // A promise to represent the current state of the message being sent to the + // model. + this.sendPromise = Promise.resolve(); + validateHistory(history); + } + /** + * Sends a message to the model and returns the response. + * + * @remarks + * This method will wait for the previous message to be processed before + * sending the next message. + * + * @see {@link Chat#sendMessageStream} for streaming method. + * @param params - parameters for sending messages within a chat session. + * @returns The model's response. + * + * @example + * ```ts + * const chat = ai.chats.create({model: 'gemini-2.0-flash'}); + * const response = await chat.sendMessage({ + * message: 'Why is the sky blue?' + * }); + * console.log(response.text); + * ``` + */ + async sendMessage(params) { + var _a; + await this.sendPromise; + const inputContent = tContent(params.message); + const responsePromise = this.modelsModule.generateContent({ + model: this.model, + contents: this.getHistory(true).concat(inputContent), + config: (_a = params.config) !== null && _a !== void 0 ? _a : this.config, + }); + this.sendPromise = (async () => { + var _a, _b, _c; + const response = await responsePromise; + const outputContent = (_b = (_a = response.candidates) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.content; + // Because the AFC input contains the entire curated chat history in + // addition to the new user input, we need to truncate the AFC history + // to deduplicate the existing chat history. + const fullAutomaticFunctionCallingHistory = response.automaticFunctionCallingHistory; + const index = this.getHistory(true).length; + let automaticFunctionCallingHistory = []; + if (fullAutomaticFunctionCallingHistory != null) { + automaticFunctionCallingHistory = + (_c = fullAutomaticFunctionCallingHistory.slice(index)) !== null && _c !== void 0 ? _c : []; + } + const modelOutput = outputContent ? [outputContent] : []; + this.recordHistory(inputContent, modelOutput, automaticFunctionCallingHistory); + return; + })(); + await this.sendPromise.catch(() => { + // Resets sendPromise to avoid subsequent calls failing + this.sendPromise = Promise.resolve(); + }); + return responsePromise; + } + /** + * Sends a message to the model and returns the response in chunks. + * + * @remarks + * This method will wait for the previous message to be processed before + * sending the next message. + * + * @see {@link Chat#sendMessage} for non-streaming method. + * @param params - parameters for sending the message. + * @return The model's response. + * + * @example + * ```ts + * const chat = ai.chats.create({model: 'gemini-2.0-flash'}); + * const response = await chat.sendMessageStream({ + * message: 'Why is the sky blue?' + * }); + * for await (const chunk of response) { + * console.log(chunk.text); + * } + * ``` + */ + async sendMessageStream(params) { + var _a; + await this.sendPromise; + const inputContent = tContent(params.message); + const streamResponse = this.modelsModule.generateContentStream({ + model: this.model, + contents: this.getHistory(true).concat(inputContent), + config: (_a = params.config) !== null && _a !== void 0 ? _a : this.config, + }); + // Resolve the internal tracking of send completion promise - `sendPromise` + // for both success and failure response. The actual failure is still + // propagated by the `await streamResponse`. + this.sendPromise = streamResponse + .then(() => undefined) + .catch(() => undefined); + const response = await streamResponse; + const result = this.processStreamResponse(response, inputContent); + return result; + } + /** + * Returns the chat history. + * + * @remarks + * The history is a list of contents alternating between user and model. + * + * There are two types of history: + * - The `curated history` contains only the valid turns between user and + * model, which will be included in the subsequent requests sent to the model. + * - The `comprehensive history` contains all turns, including invalid or + * empty model outputs, providing a complete record of the history. + * + * The history is updated after receiving the response from the model, + * for streaming response, it means receiving the last chunk of the response. + * + * The `comprehensive history` is returned by default. To get the `curated + * history`, set the `curated` parameter to `true`. + * + * @param curated - whether to return the curated history or the comprehensive + * history. + * @return History contents alternating between user and model for the entire + * chat session. + */ + getHistory(curated = false) { + const history = curated + ? extractCuratedHistory(this.history) + : this.history; + // Deep copy the history to avoid mutating the history outside of the + // chat session. + return structuredClone(history); + } + processStreamResponse(streamResponse, inputContent) { + return __asyncGenerator(this, arguments, function* processStreamResponse_1() { + var _a, e_1, _b, _c; + var _d, _e; + const outputContent = []; + try { + for (var _f = true, streamResponse_1 = __asyncValues(streamResponse), streamResponse_1_1; streamResponse_1_1 = yield __await(streamResponse_1.next()), _a = streamResponse_1_1.done, !_a; _f = true) { + _c = streamResponse_1_1.value; + _f = false; + const chunk = _c; + if (isValidResponse(chunk)) { + const content = (_e = (_d = chunk.candidates) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.content; + if (content !== undefined) { + outputContent.push(content); + } + } + yield yield __await(chunk); + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (!_f && !_a && (_b = streamResponse_1.return)) yield __await(_b.call(streamResponse_1)); + } + finally { if (e_1) throw e_1.error; } + } + this.recordHistory(inputContent, outputContent); + }); + } + recordHistory(userInput, modelOutput, automaticFunctionCallingHistory) { + let outputContents = []; + if (modelOutput.length > 0 && + modelOutput.every((content) => content.role !== undefined)) { + outputContents = modelOutput; + } + else { + // Appends an empty content when model returns empty response, so that the + // history is always alternating between user and model. + outputContents.push({ + role: 'model', + parts: [], + }); + } + if (automaticFunctionCallingHistory && + automaticFunctionCallingHistory.length > 0) { + this.history.push(...extractCuratedHistory(automaticFunctionCallingHistory)); + } + else { + this.history.push(userInput); + } + this.history.push(...outputContents); + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * API errors raised by the GenAI API. + */ +class ApiError extends Error { + constructor(options) { + super(options.message); + this.name = 'ApiError'; + this.status = options.status; + Object.setPrototypeOf(this, ApiError.prototype); + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Code generated by the Google Gen AI SDK generator DO NOT EDIT. +function createFileParametersToMldev(fromObject) { + const toObject = {}; + const fromFile = getValueByPath(fromObject, ['file']); + if (fromFile != null) { + setValueByPath(toObject, ['file'], fromFile); + } + return toObject; +} +function createFileResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function deleteFileParametersToMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'file'], tFileName(fromName)); + } + return toObject; +} +function deleteFileResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function getFileParametersToMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'file'], tFileName(fromName)); + } + return toObject; +} +function internalRegisterFilesParametersToMldev(fromObject) { + const toObject = {}; + const fromUris = getValueByPath(fromObject, ['uris']); + if (fromUris != null) { + setValueByPath(toObject, ['uris'], fromUris); + } + return toObject; +} +function listFilesConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + return toObject; +} +function listFilesParametersToMldev(fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listFilesConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function listFilesResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromFiles = getValueByPath(fromObject, ['files']); + if (fromFiles != null) { + let transformedList = fromFiles; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['files'], transformedList); + } + return toObject; +} +function registerFilesResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromFiles = getValueByPath(fromObject, ['files']); + if (fromFiles != null) { + let transformedList = fromFiles; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['files'], transformedList); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Files extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + /** + * Lists files. + * + * @param params - The parameters for the list request. + * @return - A pager of files. + * + * @example + * ```ts + * const files = await ai.files.list({config: {'pageSize': 2}}); + * for await (const file of files) { + * console.log(file); + * } + * ``` + */ + this.list = async (params = {}) => { + return new Pager(PagedItem.PAGED_ITEM_FILES, (x) => this.listInternal(x), await this.listInternal(params), params); + }; + } + /** + * Uploads a file asynchronously to the Gemini API. + * This method is not available in Vertex AI. + * Supported upload sources: + * - Node.js: File path (string) or Blob object. + * - Browser: Blob object (e.g., File). + * + * @remarks + * The `mimeType` can be specified in the `config` parameter. If omitted: + * - For file path (string) inputs, the `mimeType` will be inferred from the + * file extension. + * - For Blob object inputs, the `mimeType` will be set to the Blob's `type` + * property. + * Somex eamples for file extension to mimeType mapping: + * .txt -> text/plain + * .json -> application/json + * .jpg -> image/jpeg + * .png -> image/png + * .mp3 -> audio/mpeg + * .mp4 -> video/mp4 + * + * This section can contain multiple paragraphs and code examples. + * + * @param params - Optional parameters specified in the + * `types.UploadFileParameters` interface. + * @see {@link types.UploadFileParameters#config} for the optional + * config in the parameters. + * @return A promise that resolves to a `types.File` object. + * @throws An error if called on a Vertex AI client. + * @throws An error if the `mimeType` is not provided and can not be inferred, + * the `mimeType` can be provided in the `params.config` parameter. + * @throws An error occurs if a suitable upload location cannot be established. + * + * @example + * The following code uploads a file to Gemini API. + * + * ```ts + * const file = await ai.files.upload({file: 'file.txt', config: { + * mimeType: 'text/plain', + * }}); + * console.log(file.name); + * ``` + */ + async upload(params) { + if (this.apiClient.isVertexAI()) { + throw new Error('Vertex AI does not support uploading files. You can share files through a GCS bucket.'); + } + return this.apiClient + .uploadFile(params.file, params.config) + .then((resp) => { + return resp; + }); + } + /** + * Downloads a remotely stored file asynchronously to a location specified in + * the `params` object. This method only works on Node environment, to + * download files in the browser, use a browser compliant method like an <a> + * tag. + * + * @param params - The parameters for the download request. + * + * @example + * The following code downloads an example file named "files/mehozpxf877d" as + * "file.txt". + * + * ```ts + * await ai.files.download({file: file.name, downloadPath: 'file.txt'}); + * ``` + */ + async download(params) { + await this.apiClient.downloadFile(params); + } + /** + * Registers Google Cloud Storage files for use with the API. + * This method is only available in Node.js environments. + */ + async registerFiles(params) { + throw new Error('registerFiles is only supported in Node.js environments.'); + } + async _registerFiles(params) { + return this.registerFilesInternal(params); + } + async listInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = listFilesParametersToMldev(params); + path = formatMap('files', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listFilesResponseFromMldev(apiResponse); + const typedResp = new ListFilesResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + async createInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = createFileParametersToMldev(params); + path = formatMap('upload/v1beta/files', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = createFileResponseFromMldev(apiResponse); + const typedResp = new CreateFileResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Retrieves the file information from the service. + * + * @param params - The parameters for the get request + * @return The Promise that resolves to the types.File object requested. + * + * @example + * ```ts + * const config: GetFileParameters = { + * name: fileName, + * }; + * file = await ai.files.get(config); + * console.log(file.name); + * ``` + */ + async get(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = getFileParametersToMldev(params); + path = formatMap('files/{file}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } + /** + * Deletes a remotely stored file. + * + * @param params - The parameters for the delete request. + * @return The DeleteFileResponse, the response for the delete method. + * + * @example + * The following code deletes an example file named "files/mehozpxf877d". + * + * ```ts + * await ai.files.delete({name: file.name}); + * ``` + */ + async delete(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = deleteFileParametersToMldev(params); + path = formatMap('files/{file}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = deleteFileResponseFromMldev(apiResponse); + const typedResp = new DeleteFileResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + async registerFilesInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = internalRegisterFilesParametersToMldev(params); + path = formatMap('files:register', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = registerFilesResponseFromMldev(apiResponse); + const typedResp = new RegisterFilesResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function blobToMldev$2(fromObject) { + const toObject = {}; + const fromData = getValueByPath(fromObject, ['data']); + if (fromData != null) { + setValueByPath(toObject, ['data'], fromData); + } + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function contentToMldev$2(fromObject) { + const toObject = {}; + const fromParts = getValueByPath(fromObject, ['parts']); + if (fromParts != null) { + let transformedList = fromParts; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return partToMldev$2(item); + }); + } + setValueByPath(toObject, ['parts'], transformedList); + } + const fromRole = getValueByPath(fromObject, ['role']); + if (fromRole != null) { + setValueByPath(toObject, ['role'], fromRole); + } + return toObject; +} +function fileDataToMldev$2(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromFileUri = getValueByPath(fromObject, ['fileUri']); + if (fromFileUri != null) { + setValueByPath(toObject, ['fileUri'], fromFileUri); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function functionCallToMldev$2(fromObject) { + const toObject = {}; + const fromId = getValueByPath(fromObject, ['id']); + if (fromId != null) { + setValueByPath(toObject, ['id'], fromId); + } + const fromArgs = getValueByPath(fromObject, ['args']); + if (fromArgs != null) { + setValueByPath(toObject, ['args'], fromArgs); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + if (getValueByPath(fromObject, ['partialArgs']) !== undefined) { + throw new Error('partialArgs parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['willContinue']) !== undefined) { + throw new Error('willContinue parameter is not supported in Gemini API.'); + } + return toObject; +} +function functionDeclarationToVertex$1(fromObject) { + const toObject = {}; + const fromDescription = getValueByPath(fromObject, ['description']); + if (fromDescription != null) { + setValueByPath(toObject, ['description'], fromDescription); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromParameters = getValueByPath(fromObject, ['parameters']); + if (fromParameters != null) { + setValueByPath(toObject, ['parameters'], fromParameters); + } + const fromParametersJsonSchema = getValueByPath(fromObject, [ + 'parametersJsonSchema', + ]); + if (fromParametersJsonSchema != null) { + setValueByPath(toObject, ['parametersJsonSchema'], fromParametersJsonSchema); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], fromResponse); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + if (getValueByPath(fromObject, ['behavior']) !== undefined) { + throw new Error('behavior parameter is not supported in Vertex AI.'); + } + return toObject; +} +function generationConfigToVertex$1(fromObject) { + const toObject = {}; + const fromModelSelectionConfig = getValueByPath(fromObject, [ + 'modelSelectionConfig', + ]); + if (fromModelSelectionConfig != null) { + setValueByPath(toObject, ['modelConfig'], fromModelSelectionConfig); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + const fromAudioTimestamp = getValueByPath(fromObject, [ + 'audioTimestamp', + ]); + if (fromAudioTimestamp != null) { + setValueByPath(toObject, ['audioTimestamp'], fromAudioTimestamp); + } + const fromCandidateCount = getValueByPath(fromObject, [ + 'candidateCount', + ]); + if (fromCandidateCount != null) { + setValueByPath(toObject, ['candidateCount'], fromCandidateCount); + } + const fromEnableAffectiveDialog = getValueByPath(fromObject, [ + 'enableAffectiveDialog', + ]); + if (fromEnableAffectiveDialog != null) { + setValueByPath(toObject, ['enableAffectiveDialog'], fromEnableAffectiveDialog); + } + const fromFrequencyPenalty = getValueByPath(fromObject, [ + 'frequencyPenalty', + ]); + if (fromFrequencyPenalty != null) { + setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty); + } + const fromLogprobs = getValueByPath(fromObject, ['logprobs']); + if (fromLogprobs != null) { + setValueByPath(toObject, ['logprobs'], fromLogprobs); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (fromMaxOutputTokens != null) { + setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromPresencePenalty = getValueByPath(fromObject, [ + 'presencePenalty', + ]); + if (fromPresencePenalty != null) { + setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty); + } + const fromResponseLogprobs = getValueByPath(fromObject, [ + 'responseLogprobs', + ]); + if (fromResponseLogprobs != null) { + setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs); + } + const fromResponseMimeType = getValueByPath(fromObject, [ + 'responseMimeType', + ]); + if (fromResponseMimeType != null) { + setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (fromResponseModalities != null) { + setValueByPath(toObject, ['responseModalities'], fromResponseModalities); + } + const fromResponseSchema = getValueByPath(fromObject, [ + 'responseSchema', + ]); + if (fromResponseSchema != null) { + setValueByPath(toObject, ['responseSchema'], fromResponseSchema); + } + const fromRoutingConfig = getValueByPath(fromObject, [ + 'routingConfig', + ]); + if (fromRoutingConfig != null) { + setValueByPath(toObject, ['routingConfig'], fromRoutingConfig); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (fromSeed != null) { + setValueByPath(toObject, ['seed'], fromSeed); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (fromSpeechConfig != null) { + setValueByPath(toObject, ['speechConfig'], fromSpeechConfig); + } + const fromStopSequences = getValueByPath(fromObject, [ + 'stopSequences', + ]); + if (fromStopSequences != null) { + setValueByPath(toObject, ['stopSequences'], fromStopSequences); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (fromTemperature != null) { + setValueByPath(toObject, ['temperature'], fromTemperature); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (fromThinkingConfig != null) { + setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (fromTopK != null) { + setValueByPath(toObject, ['topK'], fromTopK); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (fromTopP != null) { + setValueByPath(toObject, ['topP'], fromTopP); + } + if (getValueByPath(fromObject, ['enableEnhancedCivicAnswers']) !== + undefined) { + throw new Error('enableEnhancedCivicAnswers parameter is not supported in Vertex AI.'); + } + return toObject; +} +function googleMapsToMldev$2(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['authConfig']) !== undefined) { + throw new Error('authConfig parameter is not supported in Gemini API.'); + } + const fromEnableWidget = getValueByPath(fromObject, ['enableWidget']); + if (fromEnableWidget != null) { + setValueByPath(toObject, ['enableWidget'], fromEnableWidget); + } + return toObject; +} +function googleSearchToMldev$2(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['excludeDomains']) !== undefined) { + throw new Error('excludeDomains parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['blockingConfidence']) !== undefined) { + throw new Error('blockingConfidence parameter is not supported in Gemini API.'); + } + const fromTimeRangeFilter = getValueByPath(fromObject, [ + 'timeRangeFilter', + ]); + if (fromTimeRangeFilter != null) { + setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter); + } + return toObject; +} +function liveConnectConfigToMldev$1(fromObject, parentObject) { + const toObject = {}; + const fromGenerationConfig = getValueByPath(fromObject, [ + 'generationConfig', + ]); + if (parentObject !== undefined && fromGenerationConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig'], fromGenerationConfig); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (parentObject !== undefined && fromResponseModalities != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'responseModalities'], fromResponseModalities); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (parentObject !== undefined && fromTemperature != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'temperature'], fromTemperature); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (parentObject !== undefined && fromTopP != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'topP'], fromTopP); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (parentObject !== undefined && fromTopK != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'topK'], fromTopK); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (parentObject !== undefined && fromMaxOutputTokens != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'maxOutputTokens'], fromMaxOutputTokens); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (parentObject !== undefined && fromMediaResolution != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'mediaResolution'], fromMediaResolution); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (parentObject !== undefined && fromSeed != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'seed'], fromSeed); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (parentObject !== undefined && fromSpeechConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'speechConfig'], tLiveSpeechConfig(fromSpeechConfig)); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (parentObject !== undefined && fromThinkingConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'thinkingConfig'], fromThinkingConfig); + } + const fromEnableAffectiveDialog = getValueByPath(fromObject, [ + 'enableAffectiveDialog', + ]); + if (parentObject !== undefined && fromEnableAffectiveDialog != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'enableAffectiveDialog'], fromEnableAffectiveDialog); + } + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['setup', 'systemInstruction'], contentToMldev$2(tContent(fromSystemInstruction))); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = tTools(fromTools); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToMldev$2(tTool(item)); + }); + } + setValueByPath(parentObject, ['setup', 'tools'], transformedList); + } + const fromSessionResumption = getValueByPath(fromObject, [ + 'sessionResumption', + ]); + if (parentObject !== undefined && fromSessionResumption != null) { + setValueByPath(parentObject, ['setup', 'sessionResumption'], sessionResumptionConfigToMldev$1(fromSessionResumption)); + } + const fromInputAudioTranscription = getValueByPath(fromObject, [ + 'inputAudioTranscription', + ]); + if (parentObject !== undefined && fromInputAudioTranscription != null) { + setValueByPath(parentObject, ['setup', 'inputAudioTranscription'], fromInputAudioTranscription); + } + const fromOutputAudioTranscription = getValueByPath(fromObject, [ + 'outputAudioTranscription', + ]); + if (parentObject !== undefined && fromOutputAudioTranscription != null) { + setValueByPath(parentObject, ['setup', 'outputAudioTranscription'], fromOutputAudioTranscription); + } + const fromRealtimeInputConfig = getValueByPath(fromObject, [ + 'realtimeInputConfig', + ]); + if (parentObject !== undefined && fromRealtimeInputConfig != null) { + setValueByPath(parentObject, ['setup', 'realtimeInputConfig'], fromRealtimeInputConfig); + } + const fromContextWindowCompression = getValueByPath(fromObject, [ + 'contextWindowCompression', + ]); + if (parentObject !== undefined && fromContextWindowCompression != null) { + setValueByPath(parentObject, ['setup', 'contextWindowCompression'], fromContextWindowCompression); + } + const fromProactivity = getValueByPath(fromObject, ['proactivity']); + if (parentObject !== undefined && fromProactivity != null) { + setValueByPath(parentObject, ['setup', 'proactivity'], fromProactivity); + } + if (getValueByPath(fromObject, ['explicitVadSignal']) !== undefined) { + throw new Error('explicitVadSignal parameter is not supported in Gemini API.'); + } + return toObject; +} +function liveConnectConfigToVertex(fromObject, parentObject) { + const toObject = {}; + const fromGenerationConfig = getValueByPath(fromObject, [ + 'generationConfig', + ]); + if (parentObject !== undefined && fromGenerationConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig'], generationConfigToVertex$1(fromGenerationConfig)); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (parentObject !== undefined && fromResponseModalities != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'responseModalities'], fromResponseModalities); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (parentObject !== undefined && fromTemperature != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'temperature'], fromTemperature); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (parentObject !== undefined && fromTopP != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'topP'], fromTopP); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (parentObject !== undefined && fromTopK != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'topK'], fromTopK); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (parentObject !== undefined && fromMaxOutputTokens != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'maxOutputTokens'], fromMaxOutputTokens); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (parentObject !== undefined && fromMediaResolution != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'mediaResolution'], fromMediaResolution); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (parentObject !== undefined && fromSeed != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'seed'], fromSeed); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (parentObject !== undefined && fromSpeechConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'speechConfig'], tLiveSpeechConfig(fromSpeechConfig)); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (parentObject !== undefined && fromThinkingConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'thinkingConfig'], fromThinkingConfig); + } + const fromEnableAffectiveDialog = getValueByPath(fromObject, [ + 'enableAffectiveDialog', + ]); + if (parentObject !== undefined && fromEnableAffectiveDialog != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'enableAffectiveDialog'], fromEnableAffectiveDialog); + } + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['setup', 'systemInstruction'], tContent(fromSystemInstruction)); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = tTools(fromTools); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToVertex$1(tTool(item)); + }); + } + setValueByPath(parentObject, ['setup', 'tools'], transformedList); + } + const fromSessionResumption = getValueByPath(fromObject, [ + 'sessionResumption', + ]); + if (parentObject !== undefined && fromSessionResumption != null) { + setValueByPath(parentObject, ['setup', 'sessionResumption'], fromSessionResumption); + } + const fromInputAudioTranscription = getValueByPath(fromObject, [ + 'inputAudioTranscription', + ]); + if (parentObject !== undefined && fromInputAudioTranscription != null) { + setValueByPath(parentObject, ['setup', 'inputAudioTranscription'], fromInputAudioTranscription); + } + const fromOutputAudioTranscription = getValueByPath(fromObject, [ + 'outputAudioTranscription', + ]); + if (parentObject !== undefined && fromOutputAudioTranscription != null) { + setValueByPath(parentObject, ['setup', 'outputAudioTranscription'], fromOutputAudioTranscription); + } + const fromRealtimeInputConfig = getValueByPath(fromObject, [ + 'realtimeInputConfig', + ]); + if (parentObject !== undefined && fromRealtimeInputConfig != null) { + setValueByPath(parentObject, ['setup', 'realtimeInputConfig'], fromRealtimeInputConfig); + } + const fromContextWindowCompression = getValueByPath(fromObject, [ + 'contextWindowCompression', + ]); + if (parentObject !== undefined && fromContextWindowCompression != null) { + setValueByPath(parentObject, ['setup', 'contextWindowCompression'], fromContextWindowCompression); + } + const fromProactivity = getValueByPath(fromObject, ['proactivity']); + if (parentObject !== undefined && fromProactivity != null) { + setValueByPath(parentObject, ['setup', 'proactivity'], fromProactivity); + } + const fromExplicitVadSignal = getValueByPath(fromObject, [ + 'explicitVadSignal', + ]); + if (parentObject !== undefined && fromExplicitVadSignal != null) { + setValueByPath(parentObject, ['setup', 'explicitVadSignal'], fromExplicitVadSignal); + } + return toObject; +} +function liveConnectParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['setup', 'model'], tModel(apiClient, fromModel)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['config'], liveConnectConfigToMldev$1(fromConfig, toObject)); + } + return toObject; +} +function liveConnectParametersToVertex(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['setup', 'model'], tModel(apiClient, fromModel)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['config'], liveConnectConfigToVertex(fromConfig, toObject)); + } + return toObject; +} +function liveMusicSetConfigParametersToMldev(fromObject) { + const toObject = {}; + const fromMusicGenerationConfig = getValueByPath(fromObject, [ + 'musicGenerationConfig', + ]); + if (fromMusicGenerationConfig != null) { + setValueByPath(toObject, ['musicGenerationConfig'], fromMusicGenerationConfig); + } + return toObject; +} +function liveMusicSetWeightedPromptsParametersToMldev(fromObject) { + const toObject = {}; + const fromWeightedPrompts = getValueByPath(fromObject, [ + 'weightedPrompts', + ]); + if (fromWeightedPrompts != null) { + let transformedList = fromWeightedPrompts; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['weightedPrompts'], transformedList); + } + return toObject; +} +function liveSendRealtimeInputParametersToMldev(fromObject) { + const toObject = {}; + const fromMedia = getValueByPath(fromObject, ['media']); + if (fromMedia != null) { + let transformedList = tBlobs(fromMedia); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return blobToMldev$2(item); + }); + } + setValueByPath(toObject, ['mediaChunks'], transformedList); + } + const fromAudio = getValueByPath(fromObject, ['audio']); + if (fromAudio != null) { + setValueByPath(toObject, ['audio'], blobToMldev$2(tAudioBlob(fromAudio))); + } + const fromAudioStreamEnd = getValueByPath(fromObject, [ + 'audioStreamEnd', + ]); + if (fromAudioStreamEnd != null) { + setValueByPath(toObject, ['audioStreamEnd'], fromAudioStreamEnd); + } + const fromVideo = getValueByPath(fromObject, ['video']); + if (fromVideo != null) { + setValueByPath(toObject, ['video'], blobToMldev$2(tImageBlob(fromVideo))); + } + const fromText = getValueByPath(fromObject, ['text']); + if (fromText != null) { + setValueByPath(toObject, ['text'], fromText); + } + const fromActivityStart = getValueByPath(fromObject, [ + 'activityStart', + ]); + if (fromActivityStart != null) { + setValueByPath(toObject, ['activityStart'], fromActivityStart); + } + const fromActivityEnd = getValueByPath(fromObject, ['activityEnd']); + if (fromActivityEnd != null) { + setValueByPath(toObject, ['activityEnd'], fromActivityEnd); + } + return toObject; +} +function liveSendRealtimeInputParametersToVertex(fromObject) { + const toObject = {}; + const fromMedia = getValueByPath(fromObject, ['media']); + if (fromMedia != null) { + let transformedList = tBlobs(fromMedia); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['mediaChunks'], transformedList); + } + const fromAudio = getValueByPath(fromObject, ['audio']); + if (fromAudio != null) { + setValueByPath(toObject, ['audio'], tAudioBlob(fromAudio)); + } + const fromAudioStreamEnd = getValueByPath(fromObject, [ + 'audioStreamEnd', + ]); + if (fromAudioStreamEnd != null) { + setValueByPath(toObject, ['audioStreamEnd'], fromAudioStreamEnd); + } + const fromVideo = getValueByPath(fromObject, ['video']); + if (fromVideo != null) { + setValueByPath(toObject, ['video'], tImageBlob(fromVideo)); + } + const fromText = getValueByPath(fromObject, ['text']); + if (fromText != null) { + setValueByPath(toObject, ['text'], fromText); + } + const fromActivityStart = getValueByPath(fromObject, [ + 'activityStart', + ]); + if (fromActivityStart != null) { + setValueByPath(toObject, ['activityStart'], fromActivityStart); + } + const fromActivityEnd = getValueByPath(fromObject, ['activityEnd']); + if (fromActivityEnd != null) { + setValueByPath(toObject, ['activityEnd'], fromActivityEnd); + } + return toObject; +} +function liveServerMessageFromVertex(fromObject) { + const toObject = {}; + const fromSetupComplete = getValueByPath(fromObject, [ + 'setupComplete', + ]); + if (fromSetupComplete != null) { + setValueByPath(toObject, ['setupComplete'], fromSetupComplete); + } + const fromServerContent = getValueByPath(fromObject, [ + 'serverContent', + ]); + if (fromServerContent != null) { + setValueByPath(toObject, ['serverContent'], fromServerContent); + } + const fromToolCall = getValueByPath(fromObject, ['toolCall']); + if (fromToolCall != null) { + setValueByPath(toObject, ['toolCall'], fromToolCall); + } + const fromToolCallCancellation = getValueByPath(fromObject, [ + 'toolCallCancellation', + ]); + if (fromToolCallCancellation != null) { + setValueByPath(toObject, ['toolCallCancellation'], fromToolCallCancellation); + } + const fromUsageMetadata = getValueByPath(fromObject, [ + 'usageMetadata', + ]); + if (fromUsageMetadata != null) { + setValueByPath(toObject, ['usageMetadata'], usageMetadataFromVertex(fromUsageMetadata)); + } + const fromGoAway = getValueByPath(fromObject, ['goAway']); + if (fromGoAway != null) { + setValueByPath(toObject, ['goAway'], fromGoAway); + } + const fromSessionResumptionUpdate = getValueByPath(fromObject, [ + 'sessionResumptionUpdate', + ]); + if (fromSessionResumptionUpdate != null) { + setValueByPath(toObject, ['sessionResumptionUpdate'], fromSessionResumptionUpdate); + } + const fromVoiceActivityDetectionSignal = getValueByPath(fromObject, [ + 'voiceActivityDetectionSignal', + ]); + if (fromVoiceActivityDetectionSignal != null) { + setValueByPath(toObject, ['voiceActivityDetectionSignal'], fromVoiceActivityDetectionSignal); + } + const fromVoiceActivity = getValueByPath(fromObject, [ + 'voiceActivity', + ]); + if (fromVoiceActivity != null) { + setValueByPath(toObject, ['voiceActivity'], voiceActivityFromVertex(fromVoiceActivity)); + } + return toObject; +} +function partToMldev$2(fromObject) { + const toObject = {}; + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromCodeExecutionResult = getValueByPath(fromObject, [ + 'codeExecutionResult', + ]); + if (fromCodeExecutionResult != null) { + setValueByPath(toObject, ['codeExecutionResult'], fromCodeExecutionResult); + } + const fromExecutableCode = getValueByPath(fromObject, [ + 'executableCode', + ]); + if (fromExecutableCode != null) { + setValueByPath(toObject, ['executableCode'], fromExecutableCode); + } + const fromFileData = getValueByPath(fromObject, ['fileData']); + if (fromFileData != null) { + setValueByPath(toObject, ['fileData'], fileDataToMldev$2(fromFileData)); + } + const fromFunctionCall = getValueByPath(fromObject, ['functionCall']); + if (fromFunctionCall != null) { + setValueByPath(toObject, ['functionCall'], functionCallToMldev$2(fromFunctionCall)); + } + const fromFunctionResponse = getValueByPath(fromObject, [ + 'functionResponse', + ]); + if (fromFunctionResponse != null) { + setValueByPath(toObject, ['functionResponse'], fromFunctionResponse); + } + const fromInlineData = getValueByPath(fromObject, ['inlineData']); + if (fromInlineData != null) { + setValueByPath(toObject, ['inlineData'], blobToMldev$2(fromInlineData)); + } + const fromText = getValueByPath(fromObject, ['text']); + if (fromText != null) { + setValueByPath(toObject, ['text'], fromText); + } + const fromThought = getValueByPath(fromObject, ['thought']); + if (fromThought != null) { + setValueByPath(toObject, ['thought'], fromThought); + } + const fromThoughtSignature = getValueByPath(fromObject, [ + 'thoughtSignature', + ]); + if (fromThoughtSignature != null) { + setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature); + } + const fromVideoMetadata = getValueByPath(fromObject, [ + 'videoMetadata', + ]); + if (fromVideoMetadata != null) { + setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata); + } + return toObject; +} +function sessionResumptionConfigToMldev$1(fromObject) { + const toObject = {}; + const fromHandle = getValueByPath(fromObject, ['handle']); + if (fromHandle != null) { + setValueByPath(toObject, ['handle'], fromHandle); + } + if (getValueByPath(fromObject, ['transparent']) !== undefined) { + throw new Error('transparent parameter is not supported in Gemini API.'); + } + return toObject; +} +function toolToMldev$2(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['retrieval']) !== undefined) { + throw new Error('retrieval parameter is not supported in Gemini API.'); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + const fromFileSearch = getValueByPath(fromObject, ['fileSearch']); + if (fromFileSearch != null) { + setValueByPath(toObject, ['fileSearch'], fromFileSearch); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + if (getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined) { + throw new Error('enterpriseWebSearch parameter is not supported in Gemini API.'); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], googleMapsToMldev$2(fromGoogleMaps)); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], googleSearchToMldev$2(fromGoogleSearch)); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} +function toolToVertex$1(fromObject) { + const toObject = {}; + const fromRetrieval = getValueByPath(fromObject, ['retrieval']); + if (fromRetrieval != null) { + setValueByPath(toObject, ['retrieval'], fromRetrieval); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + if (getValueByPath(fromObject, ['fileSearch']) !== undefined) { + throw new Error('fileSearch parameter is not supported in Vertex AI.'); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + const fromEnterpriseWebSearch = getValueByPath(fromObject, [ + 'enterpriseWebSearch', + ]); + if (fromEnterpriseWebSearch != null) { + setValueByPath(toObject, ['enterpriseWebSearch'], fromEnterpriseWebSearch); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return functionDeclarationToVertex$1(item); + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], fromGoogleMaps); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], fromGoogleSearch); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} +function usageMetadataFromVertex(fromObject) { + const toObject = {}; + const fromPromptTokenCount = getValueByPath(fromObject, [ + 'promptTokenCount', + ]); + if (fromPromptTokenCount != null) { + setValueByPath(toObject, ['promptTokenCount'], fromPromptTokenCount); + } + const fromCachedContentTokenCount = getValueByPath(fromObject, [ + 'cachedContentTokenCount', + ]); + if (fromCachedContentTokenCount != null) { + setValueByPath(toObject, ['cachedContentTokenCount'], fromCachedContentTokenCount); + } + const fromResponseTokenCount = getValueByPath(fromObject, [ + 'candidatesTokenCount', + ]); + if (fromResponseTokenCount != null) { + setValueByPath(toObject, ['responseTokenCount'], fromResponseTokenCount); + } + const fromToolUsePromptTokenCount = getValueByPath(fromObject, [ + 'toolUsePromptTokenCount', + ]); + if (fromToolUsePromptTokenCount != null) { + setValueByPath(toObject, ['toolUsePromptTokenCount'], fromToolUsePromptTokenCount); + } + const fromThoughtsTokenCount = getValueByPath(fromObject, [ + 'thoughtsTokenCount', + ]); + if (fromThoughtsTokenCount != null) { + setValueByPath(toObject, ['thoughtsTokenCount'], fromThoughtsTokenCount); + } + const fromTotalTokenCount = getValueByPath(fromObject, [ + 'totalTokenCount', + ]); + if (fromTotalTokenCount != null) { + setValueByPath(toObject, ['totalTokenCount'], fromTotalTokenCount); + } + const fromPromptTokensDetails = getValueByPath(fromObject, [ + 'promptTokensDetails', + ]); + if (fromPromptTokensDetails != null) { + let transformedList = fromPromptTokensDetails; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['promptTokensDetails'], transformedList); + } + const fromCacheTokensDetails = getValueByPath(fromObject, [ + 'cacheTokensDetails', + ]); + if (fromCacheTokensDetails != null) { + let transformedList = fromCacheTokensDetails; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['cacheTokensDetails'], transformedList); + } + const fromResponseTokensDetails = getValueByPath(fromObject, [ + 'candidatesTokensDetails', + ]); + if (fromResponseTokensDetails != null) { + let transformedList = fromResponseTokensDetails; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['responseTokensDetails'], transformedList); + } + const fromToolUsePromptTokensDetails = getValueByPath(fromObject, [ + 'toolUsePromptTokensDetails', + ]); + if (fromToolUsePromptTokensDetails != null) { + let transformedList = fromToolUsePromptTokensDetails; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['toolUsePromptTokensDetails'], transformedList); + } + const fromTrafficType = getValueByPath(fromObject, ['trafficType']); + if (fromTrafficType != null) { + setValueByPath(toObject, ['trafficType'], fromTrafficType); + } + return toObject; +} +function voiceActivityFromVertex(fromObject) { + const toObject = {}; + const fromVoiceActivityType = getValueByPath(fromObject, ['type']); + if (fromVoiceActivityType != null) { + setValueByPath(toObject, ['voiceActivityType'], fromVoiceActivityType); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function blobToMldev$1(fromObject, _rootObject) { + const toObject = {}; + const fromData = getValueByPath(fromObject, ['data']); + if (fromData != null) { + setValueByPath(toObject, ['data'], fromData); + } + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function candidateFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromContent = getValueByPath(fromObject, ['content']); + if (fromContent != null) { + setValueByPath(toObject, ['content'], fromContent); + } + const fromCitationMetadata = getValueByPath(fromObject, [ + 'citationMetadata', + ]); + if (fromCitationMetadata != null) { + setValueByPath(toObject, ['citationMetadata'], citationMetadataFromMldev(fromCitationMetadata)); + } + const fromTokenCount = getValueByPath(fromObject, ['tokenCount']); + if (fromTokenCount != null) { + setValueByPath(toObject, ['tokenCount'], fromTokenCount); + } + const fromFinishReason = getValueByPath(fromObject, ['finishReason']); + if (fromFinishReason != null) { + setValueByPath(toObject, ['finishReason'], fromFinishReason); + } + const fromAvgLogprobs = getValueByPath(fromObject, ['avgLogprobs']); + if (fromAvgLogprobs != null) { + setValueByPath(toObject, ['avgLogprobs'], fromAvgLogprobs); + } + const fromGroundingMetadata = getValueByPath(fromObject, [ + 'groundingMetadata', + ]); + if (fromGroundingMetadata != null) { + setValueByPath(toObject, ['groundingMetadata'], fromGroundingMetadata); + } + const fromIndex = getValueByPath(fromObject, ['index']); + if (fromIndex != null) { + setValueByPath(toObject, ['index'], fromIndex); + } + const fromLogprobsResult = getValueByPath(fromObject, [ + 'logprobsResult', + ]); + if (fromLogprobsResult != null) { + setValueByPath(toObject, ['logprobsResult'], fromLogprobsResult); + } + const fromSafetyRatings = getValueByPath(fromObject, [ + 'safetyRatings', + ]); + if (fromSafetyRatings != null) { + let transformedList = fromSafetyRatings; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['safetyRatings'], transformedList); + } + const fromUrlContextMetadata = getValueByPath(fromObject, [ + 'urlContextMetadata', + ]); + if (fromUrlContextMetadata != null) { + setValueByPath(toObject, ['urlContextMetadata'], fromUrlContextMetadata); + } + return toObject; +} +function citationMetadataFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromCitations = getValueByPath(fromObject, ['citationSources']); + if (fromCitations != null) { + let transformedList = fromCitations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['citations'], transformedList); + } + return toObject; +} +function computeTokensParametersToVertex(apiClient, fromObject, _rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['contents'], transformedList); + } + return toObject; +} +function computeTokensResponseFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromTokensInfo = getValueByPath(fromObject, ['tokensInfo']); + if (fromTokensInfo != null) { + let transformedList = fromTokensInfo; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['tokensInfo'], transformedList); + } + return toObject; +} +function contentEmbeddingFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromValues = getValueByPath(fromObject, ['values']); + if (fromValues != null) { + setValueByPath(toObject, ['values'], fromValues); + } + const fromStatistics = getValueByPath(fromObject, ['statistics']); + if (fromStatistics != null) { + setValueByPath(toObject, ['statistics'], contentEmbeddingStatisticsFromVertex(fromStatistics)); + } + return toObject; +} +function contentEmbeddingStatisticsFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromTruncated = getValueByPath(fromObject, ['truncated']); + if (fromTruncated != null) { + setValueByPath(toObject, ['truncated'], fromTruncated); + } + const fromTokenCount = getValueByPath(fromObject, ['token_count']); + if (fromTokenCount != null) { + setValueByPath(toObject, ['tokenCount'], fromTokenCount); + } + return toObject; +} +function contentToMldev$1(fromObject, rootObject) { + const toObject = {}; + const fromParts = getValueByPath(fromObject, ['parts']); + if (fromParts != null) { + let transformedList = fromParts; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return partToMldev$1(item); + }); + } + setValueByPath(toObject, ['parts'], transformedList); + } + const fromRole = getValueByPath(fromObject, ['role']); + if (fromRole != null) { + setValueByPath(toObject, ['role'], fromRole); + } + return toObject; +} +function controlReferenceConfigToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromControlType = getValueByPath(fromObject, ['controlType']); + if (fromControlType != null) { + setValueByPath(toObject, ['controlType'], fromControlType); + } + const fromEnableControlImageComputation = getValueByPath(fromObject, [ + 'enableControlImageComputation', + ]); + if (fromEnableControlImageComputation != null) { + setValueByPath(toObject, ['computeControl'], fromEnableControlImageComputation); + } + return toObject; +} +function countTokensConfigToMldev(fromObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['systemInstruction']) !== undefined) { + throw new Error('systemInstruction parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['tools']) !== undefined) { + throw new Error('tools parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['generationConfig']) !== undefined) { + throw new Error('generationConfig parameter is not supported in Gemini API.'); + } + return toObject; +} +function countTokensConfigToVertex(fromObject, parentObject, rootObject) { + const toObject = {}; + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['systemInstruction'], tContent(fromSystemInstruction)); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = fromTools; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToVertex(item); + }); + } + setValueByPath(parentObject, ['tools'], transformedList); + } + const fromGenerationConfig = getValueByPath(fromObject, [ + 'generationConfig', + ]); + if (parentObject !== undefined && fromGenerationConfig != null) { + setValueByPath(parentObject, ['generationConfig'], generationConfigToVertex(fromGenerationConfig)); + } + return toObject; +} +function countTokensParametersToMldev(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return contentToMldev$1(item); + }); + } + setValueByPath(toObject, ['contents'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + countTokensConfigToMldev(fromConfig); + } + return toObject; +} +function countTokensParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['contents'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + countTokensConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function countTokensResponseFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromTotalTokens = getValueByPath(fromObject, ['totalTokens']); + if (fromTotalTokens != null) { + setValueByPath(toObject, ['totalTokens'], fromTotalTokens); + } + const fromCachedContentTokenCount = getValueByPath(fromObject, [ + 'cachedContentTokenCount', + ]); + if (fromCachedContentTokenCount != null) { + setValueByPath(toObject, ['cachedContentTokenCount'], fromCachedContentTokenCount); + } + return toObject; +} +function countTokensResponseFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromTotalTokens = getValueByPath(fromObject, ['totalTokens']); + if (fromTotalTokens != null) { + setValueByPath(toObject, ['totalTokens'], fromTotalTokens); + } + return toObject; +} +function deleteModelParametersToMldev(apiClient, fromObject, _rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'name'], tModel(apiClient, fromModel)); + } + return toObject; +} +function deleteModelParametersToVertex(apiClient, fromObject, _rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'name'], tModel(apiClient, fromModel)); + } + return toObject; +} +function deleteModelResponseFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function deleteModelResponseFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function editImageConfigToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromOutputGcsUri = getValueByPath(fromObject, ['outputGcsUri']); + if (parentObject !== undefined && fromOutputGcsUri != null) { + setValueByPath(parentObject, ['parameters', 'storageUri'], fromOutputGcsUri); + } + const fromNegativePrompt = getValueByPath(fromObject, [ + 'negativePrompt', + ]); + if (parentObject !== undefined && fromNegativePrompt != null) { + setValueByPath(parentObject, ['parameters', 'negativePrompt'], fromNegativePrompt); + } + const fromNumberOfImages = getValueByPath(fromObject, [ + 'numberOfImages', + ]); + if (parentObject !== undefined && fromNumberOfImages != null) { + setValueByPath(parentObject, ['parameters', 'sampleCount'], fromNumberOfImages); + } + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (parentObject !== undefined && fromAspectRatio != null) { + setValueByPath(parentObject, ['parameters', 'aspectRatio'], fromAspectRatio); + } + const fromGuidanceScale = getValueByPath(fromObject, [ + 'guidanceScale', + ]); + if (parentObject !== undefined && fromGuidanceScale != null) { + setValueByPath(parentObject, ['parameters', 'guidanceScale'], fromGuidanceScale); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (parentObject !== undefined && fromSeed != null) { + setValueByPath(parentObject, ['parameters', 'seed'], fromSeed); + } + const fromSafetyFilterLevel = getValueByPath(fromObject, [ + 'safetyFilterLevel', + ]); + if (parentObject !== undefined && fromSafetyFilterLevel != null) { + setValueByPath(parentObject, ['parameters', 'safetySetting'], fromSafetyFilterLevel); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (parentObject !== undefined && fromPersonGeneration != null) { + setValueByPath(parentObject, ['parameters', 'personGeneration'], fromPersonGeneration); + } + const fromIncludeSafetyAttributes = getValueByPath(fromObject, [ + 'includeSafetyAttributes', + ]); + if (parentObject !== undefined && fromIncludeSafetyAttributes != null) { + setValueByPath(parentObject, ['parameters', 'includeSafetyAttributes'], fromIncludeSafetyAttributes); + } + const fromIncludeRaiReason = getValueByPath(fromObject, [ + 'includeRaiReason', + ]); + if (parentObject !== undefined && fromIncludeRaiReason != null) { + setValueByPath(parentObject, ['parameters', 'includeRaiReason'], fromIncludeRaiReason); + } + const fromLanguage = getValueByPath(fromObject, ['language']); + if (parentObject !== undefined && fromLanguage != null) { + setValueByPath(parentObject, ['parameters', 'language'], fromLanguage); + } + const fromOutputMimeType = getValueByPath(fromObject, [ + 'outputMimeType', + ]); + if (parentObject !== undefined && fromOutputMimeType != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'mimeType'], fromOutputMimeType); + } + const fromOutputCompressionQuality = getValueByPath(fromObject, [ + 'outputCompressionQuality', + ]); + if (parentObject !== undefined && fromOutputCompressionQuality != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'compressionQuality'], fromOutputCompressionQuality); + } + const fromAddWatermark = getValueByPath(fromObject, ['addWatermark']); + if (parentObject !== undefined && fromAddWatermark != null) { + setValueByPath(parentObject, ['parameters', 'addWatermark'], fromAddWatermark); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (parentObject !== undefined && fromLabels != null) { + setValueByPath(parentObject, ['labels'], fromLabels); + } + const fromEditMode = getValueByPath(fromObject, ['editMode']); + if (parentObject !== undefined && fromEditMode != null) { + setValueByPath(parentObject, ['parameters', 'editMode'], fromEditMode); + } + const fromBaseSteps = getValueByPath(fromObject, ['baseSteps']); + if (parentObject !== undefined && fromBaseSteps != null) { + setValueByPath(parentObject, ['parameters', 'editConfig', 'baseSteps'], fromBaseSteps); + } + return toObject; +} +function editImageParametersInternalToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (fromPrompt != null) { + setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromReferenceImages = getValueByPath(fromObject, [ + 'referenceImages', + ]); + if (fromReferenceImages != null) { + let transformedList = fromReferenceImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return referenceImageAPIInternalToVertex(item); + }); + } + setValueByPath(toObject, ['instances[0]', 'referenceImages'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + editImageConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function editImageResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromGeneratedImages = getValueByPath(fromObject, [ + 'predictions', + ]); + if (fromGeneratedImages != null) { + let transformedList = fromGeneratedImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedImageFromVertex(item); + }); + } + setValueByPath(toObject, ['generatedImages'], transformedList); + } + return toObject; +} +function embedContentConfigToMldev(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromTaskType = getValueByPath(fromObject, ['taskType']); + if (parentObject !== undefined && fromTaskType != null) { + setValueByPath(parentObject, ['requests[]', 'taskType'], fromTaskType); + } + const fromTitle = getValueByPath(fromObject, ['title']); + if (parentObject !== undefined && fromTitle != null) { + setValueByPath(parentObject, ['requests[]', 'title'], fromTitle); + } + const fromOutputDimensionality = getValueByPath(fromObject, [ + 'outputDimensionality', + ]); + if (parentObject !== undefined && fromOutputDimensionality != null) { + setValueByPath(parentObject, ['requests[]', 'outputDimensionality'], fromOutputDimensionality); + } + if (getValueByPath(fromObject, ['mimeType']) !== undefined) { + throw new Error('mimeType parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['autoTruncate']) !== undefined) { + throw new Error('autoTruncate parameter is not supported in Gemini API.'); + } + return toObject; +} +function embedContentConfigToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromTaskType = getValueByPath(fromObject, ['taskType']); + if (parentObject !== undefined && fromTaskType != null) { + setValueByPath(parentObject, ['instances[]', 'task_type'], fromTaskType); + } + const fromTitle = getValueByPath(fromObject, ['title']); + if (parentObject !== undefined && fromTitle != null) { + setValueByPath(parentObject, ['instances[]', 'title'], fromTitle); + } + const fromOutputDimensionality = getValueByPath(fromObject, [ + 'outputDimensionality', + ]); + if (parentObject !== undefined && fromOutputDimensionality != null) { + setValueByPath(parentObject, ['parameters', 'outputDimensionality'], fromOutputDimensionality); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (parentObject !== undefined && fromMimeType != null) { + setValueByPath(parentObject, ['instances[]', 'mimeType'], fromMimeType); + } + const fromAutoTruncate = getValueByPath(fromObject, ['autoTruncate']); + if (parentObject !== undefined && fromAutoTruncate != null) { + setValueByPath(parentObject, ['parameters', 'autoTruncate'], fromAutoTruncate); + } + return toObject; +} +function embedContentParametersToMldev(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContentsForEmbed(apiClient, fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['requests[]', 'content'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + embedContentConfigToMldev(fromConfig, toObject); + } + const fromModelForEmbedContent = getValueByPath(fromObject, ['model']); + if (fromModelForEmbedContent !== undefined) { + setValueByPath(toObject, ['requests[]', 'model'], tModel(apiClient, fromModelForEmbedContent)); + } + return toObject; +} +function embedContentParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContentsForEmbed(apiClient, fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['instances[]', 'content'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + embedContentConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function embedContentResponseFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromEmbeddings = getValueByPath(fromObject, ['embeddings']); + if (fromEmbeddings != null) { + let transformedList = fromEmbeddings; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['embeddings'], transformedList); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + return toObject; +} +function embedContentResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromEmbeddings = getValueByPath(fromObject, [ + 'predictions[]', + 'embeddings', + ]); + if (fromEmbeddings != null) { + let transformedList = fromEmbeddings; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return contentEmbeddingFromVertex(item); + }); + } + setValueByPath(toObject, ['embeddings'], transformedList); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + return toObject; +} +function endpointFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['endpoint']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromDeployedModelId = getValueByPath(fromObject, [ + 'deployedModelId', + ]); + if (fromDeployedModelId != null) { + setValueByPath(toObject, ['deployedModelId'], fromDeployedModelId); + } + return toObject; +} +function fileDataToMldev$1(fromObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromFileUri = getValueByPath(fromObject, ['fileUri']); + if (fromFileUri != null) { + setValueByPath(toObject, ['fileUri'], fromFileUri); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function functionCallToMldev$1(fromObject, _rootObject) { + const toObject = {}; + const fromId = getValueByPath(fromObject, ['id']); + if (fromId != null) { + setValueByPath(toObject, ['id'], fromId); + } + const fromArgs = getValueByPath(fromObject, ['args']); + if (fromArgs != null) { + setValueByPath(toObject, ['args'], fromArgs); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + if (getValueByPath(fromObject, ['partialArgs']) !== undefined) { + throw new Error('partialArgs parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['willContinue']) !== undefined) { + throw new Error('willContinue parameter is not supported in Gemini API.'); + } + return toObject; +} +function functionCallingConfigToMldev(fromObject, _rootObject) { + const toObject = {}; + const fromAllowedFunctionNames = getValueByPath(fromObject, [ + 'allowedFunctionNames', + ]); + if (fromAllowedFunctionNames != null) { + setValueByPath(toObject, ['allowedFunctionNames'], fromAllowedFunctionNames); + } + const fromMode = getValueByPath(fromObject, ['mode']); + if (fromMode != null) { + setValueByPath(toObject, ['mode'], fromMode); + } + if (getValueByPath(fromObject, ['streamFunctionCallArguments']) !== + undefined) { + throw new Error('streamFunctionCallArguments parameter is not supported in Gemini API.'); + } + return toObject; +} +function functionDeclarationToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromDescription = getValueByPath(fromObject, ['description']); + if (fromDescription != null) { + setValueByPath(toObject, ['description'], fromDescription); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromParameters = getValueByPath(fromObject, ['parameters']); + if (fromParameters != null) { + setValueByPath(toObject, ['parameters'], fromParameters); + } + const fromParametersJsonSchema = getValueByPath(fromObject, [ + 'parametersJsonSchema', + ]); + if (fromParametersJsonSchema != null) { + setValueByPath(toObject, ['parametersJsonSchema'], fromParametersJsonSchema); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], fromResponse); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + if (getValueByPath(fromObject, ['behavior']) !== undefined) { + throw new Error('behavior parameter is not supported in Vertex AI.'); + } + return toObject; +} +function generateContentConfigToMldev(apiClient, fromObject, parentObject, rootObject) { + const toObject = {}; + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['systemInstruction'], contentToMldev$1(tContent(fromSystemInstruction))); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (fromTemperature != null) { + setValueByPath(toObject, ['temperature'], fromTemperature); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (fromTopP != null) { + setValueByPath(toObject, ['topP'], fromTopP); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (fromTopK != null) { + setValueByPath(toObject, ['topK'], fromTopK); + } + const fromCandidateCount = getValueByPath(fromObject, [ + 'candidateCount', + ]); + if (fromCandidateCount != null) { + setValueByPath(toObject, ['candidateCount'], fromCandidateCount); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (fromMaxOutputTokens != null) { + setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens); + } + const fromStopSequences = getValueByPath(fromObject, [ + 'stopSequences', + ]); + if (fromStopSequences != null) { + setValueByPath(toObject, ['stopSequences'], fromStopSequences); + } + const fromResponseLogprobs = getValueByPath(fromObject, [ + 'responseLogprobs', + ]); + if (fromResponseLogprobs != null) { + setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs); + } + const fromLogprobs = getValueByPath(fromObject, ['logprobs']); + if (fromLogprobs != null) { + setValueByPath(toObject, ['logprobs'], fromLogprobs); + } + const fromPresencePenalty = getValueByPath(fromObject, [ + 'presencePenalty', + ]); + if (fromPresencePenalty != null) { + setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty); + } + const fromFrequencyPenalty = getValueByPath(fromObject, [ + 'frequencyPenalty', + ]); + if (fromFrequencyPenalty != null) { + setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (fromSeed != null) { + setValueByPath(toObject, ['seed'], fromSeed); + } + const fromResponseMimeType = getValueByPath(fromObject, [ + 'responseMimeType', + ]); + if (fromResponseMimeType != null) { + setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType); + } + const fromResponseSchema = getValueByPath(fromObject, [ + 'responseSchema', + ]); + if (fromResponseSchema != null) { + setValueByPath(toObject, ['responseSchema'], tSchema(fromResponseSchema)); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + if (getValueByPath(fromObject, ['routingConfig']) !== undefined) { + throw new Error('routingConfig parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['modelSelectionConfig']) !== undefined) { + throw new Error('modelSelectionConfig parameter is not supported in Gemini API.'); + } + const fromSafetySettings = getValueByPath(fromObject, [ + 'safetySettings', + ]); + if (parentObject !== undefined && fromSafetySettings != null) { + let transformedList = fromSafetySettings; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return safetySettingToMldev(item); + }); + } + setValueByPath(parentObject, ['safetySettings'], transformedList); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = tTools(fromTools); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToMldev$1(tTool(item)); + }); + } + setValueByPath(parentObject, ['tools'], transformedList); + } + const fromToolConfig = getValueByPath(fromObject, ['toolConfig']); + if (parentObject !== undefined && fromToolConfig != null) { + setValueByPath(parentObject, ['toolConfig'], toolConfigToMldev(fromToolConfig)); + } + if (getValueByPath(fromObject, ['labels']) !== undefined) { + throw new Error('labels parameter is not supported in Gemini API.'); + } + const fromCachedContent = getValueByPath(fromObject, [ + 'cachedContent', + ]); + if (parentObject !== undefined && fromCachedContent != null) { + setValueByPath(parentObject, ['cachedContent'], tCachedContentName(apiClient, fromCachedContent)); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (fromResponseModalities != null) { + setValueByPath(toObject, ['responseModalities'], fromResponseModalities); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (fromSpeechConfig != null) { + setValueByPath(toObject, ['speechConfig'], tSpeechConfig(fromSpeechConfig)); + } + if (getValueByPath(fromObject, ['audioTimestamp']) !== undefined) { + throw new Error('audioTimestamp parameter is not supported in Gemini API.'); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (fromThinkingConfig != null) { + setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig); + } + const fromImageConfig = getValueByPath(fromObject, ['imageConfig']); + if (fromImageConfig != null) { + setValueByPath(toObject, ['imageConfig'], imageConfigToMldev(fromImageConfig)); + } + const fromEnableEnhancedCivicAnswers = getValueByPath(fromObject, [ + 'enableEnhancedCivicAnswers', + ]); + if (fromEnableEnhancedCivicAnswers != null) { + setValueByPath(toObject, ['enableEnhancedCivicAnswers'], fromEnableEnhancedCivicAnswers); + } + if (getValueByPath(fromObject, ['modelArmorConfig']) !== undefined) { + throw new Error('modelArmorConfig parameter is not supported in Gemini API.'); + } + return toObject; +} +function generateContentConfigToVertex(apiClient, fromObject, parentObject, rootObject) { + const toObject = {}; + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['systemInstruction'], tContent(fromSystemInstruction)); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (fromTemperature != null) { + setValueByPath(toObject, ['temperature'], fromTemperature); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (fromTopP != null) { + setValueByPath(toObject, ['topP'], fromTopP); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (fromTopK != null) { + setValueByPath(toObject, ['topK'], fromTopK); + } + const fromCandidateCount = getValueByPath(fromObject, [ + 'candidateCount', + ]); + if (fromCandidateCount != null) { + setValueByPath(toObject, ['candidateCount'], fromCandidateCount); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (fromMaxOutputTokens != null) { + setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens); + } + const fromStopSequences = getValueByPath(fromObject, [ + 'stopSequences', + ]); + if (fromStopSequences != null) { + setValueByPath(toObject, ['stopSequences'], fromStopSequences); + } + const fromResponseLogprobs = getValueByPath(fromObject, [ + 'responseLogprobs', + ]); + if (fromResponseLogprobs != null) { + setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs); + } + const fromLogprobs = getValueByPath(fromObject, ['logprobs']); + if (fromLogprobs != null) { + setValueByPath(toObject, ['logprobs'], fromLogprobs); + } + const fromPresencePenalty = getValueByPath(fromObject, [ + 'presencePenalty', + ]); + if (fromPresencePenalty != null) { + setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty); + } + const fromFrequencyPenalty = getValueByPath(fromObject, [ + 'frequencyPenalty', + ]); + if (fromFrequencyPenalty != null) { + setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (fromSeed != null) { + setValueByPath(toObject, ['seed'], fromSeed); + } + const fromResponseMimeType = getValueByPath(fromObject, [ + 'responseMimeType', + ]); + if (fromResponseMimeType != null) { + setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType); + } + const fromResponseSchema = getValueByPath(fromObject, [ + 'responseSchema', + ]); + if (fromResponseSchema != null) { + setValueByPath(toObject, ['responseSchema'], tSchema(fromResponseSchema)); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + const fromRoutingConfig = getValueByPath(fromObject, [ + 'routingConfig', + ]); + if (fromRoutingConfig != null) { + setValueByPath(toObject, ['routingConfig'], fromRoutingConfig); + } + const fromModelSelectionConfig = getValueByPath(fromObject, [ + 'modelSelectionConfig', + ]); + if (fromModelSelectionConfig != null) { + setValueByPath(toObject, ['modelConfig'], fromModelSelectionConfig); + } + const fromSafetySettings = getValueByPath(fromObject, [ + 'safetySettings', + ]); + if (parentObject !== undefined && fromSafetySettings != null) { + let transformedList = fromSafetySettings; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(parentObject, ['safetySettings'], transformedList); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = tTools(fromTools); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToVertex(tTool(item)); + }); + } + setValueByPath(parentObject, ['tools'], transformedList); + } + const fromToolConfig = getValueByPath(fromObject, ['toolConfig']); + if (parentObject !== undefined && fromToolConfig != null) { + setValueByPath(parentObject, ['toolConfig'], fromToolConfig); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (parentObject !== undefined && fromLabels != null) { + setValueByPath(parentObject, ['labels'], fromLabels); + } + const fromCachedContent = getValueByPath(fromObject, [ + 'cachedContent', + ]); + if (parentObject !== undefined && fromCachedContent != null) { + setValueByPath(parentObject, ['cachedContent'], tCachedContentName(apiClient, fromCachedContent)); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (fromResponseModalities != null) { + setValueByPath(toObject, ['responseModalities'], fromResponseModalities); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (fromSpeechConfig != null) { + setValueByPath(toObject, ['speechConfig'], tSpeechConfig(fromSpeechConfig)); + } + const fromAudioTimestamp = getValueByPath(fromObject, [ + 'audioTimestamp', + ]); + if (fromAudioTimestamp != null) { + setValueByPath(toObject, ['audioTimestamp'], fromAudioTimestamp); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (fromThinkingConfig != null) { + setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig); + } + const fromImageConfig = getValueByPath(fromObject, ['imageConfig']); + if (fromImageConfig != null) { + setValueByPath(toObject, ['imageConfig'], imageConfigToVertex(fromImageConfig)); + } + if (getValueByPath(fromObject, ['enableEnhancedCivicAnswers']) !== + undefined) { + throw new Error('enableEnhancedCivicAnswers parameter is not supported in Vertex AI.'); + } + const fromModelArmorConfig = getValueByPath(fromObject, [ + 'modelArmorConfig', + ]); + if (parentObject !== undefined && fromModelArmorConfig != null) { + setValueByPath(parentObject, ['modelArmorConfig'], fromModelArmorConfig); + } + return toObject; +} +function generateContentParametersToMldev(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return contentToMldev$1(item); + }); + } + setValueByPath(toObject, ['contents'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['generationConfig'], generateContentConfigToMldev(apiClient, fromConfig, toObject)); + } + return toObject; +} +function generateContentParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromContents = getValueByPath(fromObject, ['contents']); + if (fromContents != null) { + let transformedList = tContents(fromContents); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['contents'], transformedList); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['generationConfig'], generateContentConfigToVertex(apiClient, fromConfig, toObject)); + } + return toObject; +} +function generateContentResponseFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromCandidates = getValueByPath(fromObject, ['candidates']); + if (fromCandidates != null) { + let transformedList = fromCandidates; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return candidateFromMldev(item); + }); + } + setValueByPath(toObject, ['candidates'], transformedList); + } + const fromModelVersion = getValueByPath(fromObject, ['modelVersion']); + if (fromModelVersion != null) { + setValueByPath(toObject, ['modelVersion'], fromModelVersion); + } + const fromPromptFeedback = getValueByPath(fromObject, [ + 'promptFeedback', + ]); + if (fromPromptFeedback != null) { + setValueByPath(toObject, ['promptFeedback'], fromPromptFeedback); + } + const fromResponseId = getValueByPath(fromObject, ['responseId']); + if (fromResponseId != null) { + setValueByPath(toObject, ['responseId'], fromResponseId); + } + const fromUsageMetadata = getValueByPath(fromObject, [ + 'usageMetadata', + ]); + if (fromUsageMetadata != null) { + setValueByPath(toObject, ['usageMetadata'], fromUsageMetadata); + } + return toObject; +} +function generateContentResponseFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromCandidates = getValueByPath(fromObject, ['candidates']); + if (fromCandidates != null) { + let transformedList = fromCandidates; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['candidates'], transformedList); + } + const fromCreateTime = getValueByPath(fromObject, ['createTime']); + if (fromCreateTime != null) { + setValueByPath(toObject, ['createTime'], fromCreateTime); + } + const fromModelVersion = getValueByPath(fromObject, ['modelVersion']); + if (fromModelVersion != null) { + setValueByPath(toObject, ['modelVersion'], fromModelVersion); + } + const fromPromptFeedback = getValueByPath(fromObject, [ + 'promptFeedback', + ]); + if (fromPromptFeedback != null) { + setValueByPath(toObject, ['promptFeedback'], fromPromptFeedback); + } + const fromResponseId = getValueByPath(fromObject, ['responseId']); + if (fromResponseId != null) { + setValueByPath(toObject, ['responseId'], fromResponseId); + } + const fromUsageMetadata = getValueByPath(fromObject, [ + 'usageMetadata', + ]); + if (fromUsageMetadata != null) { + setValueByPath(toObject, ['usageMetadata'], fromUsageMetadata); + } + return toObject; +} +function generateImagesConfigToMldev(fromObject, parentObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['outputGcsUri']) !== undefined) { + throw new Error('outputGcsUri parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['negativePrompt']) !== undefined) { + throw new Error('negativePrompt parameter is not supported in Gemini API.'); + } + const fromNumberOfImages = getValueByPath(fromObject, [ + 'numberOfImages', + ]); + if (parentObject !== undefined && fromNumberOfImages != null) { + setValueByPath(parentObject, ['parameters', 'sampleCount'], fromNumberOfImages); + } + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (parentObject !== undefined && fromAspectRatio != null) { + setValueByPath(parentObject, ['parameters', 'aspectRatio'], fromAspectRatio); + } + const fromGuidanceScale = getValueByPath(fromObject, [ + 'guidanceScale', + ]); + if (parentObject !== undefined && fromGuidanceScale != null) { + setValueByPath(parentObject, ['parameters', 'guidanceScale'], fromGuidanceScale); + } + if (getValueByPath(fromObject, ['seed']) !== undefined) { + throw new Error('seed parameter is not supported in Gemini API.'); + } + const fromSafetyFilterLevel = getValueByPath(fromObject, [ + 'safetyFilterLevel', + ]); + if (parentObject !== undefined && fromSafetyFilterLevel != null) { + setValueByPath(parentObject, ['parameters', 'safetySetting'], fromSafetyFilterLevel); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (parentObject !== undefined && fromPersonGeneration != null) { + setValueByPath(parentObject, ['parameters', 'personGeneration'], fromPersonGeneration); + } + const fromIncludeSafetyAttributes = getValueByPath(fromObject, [ + 'includeSafetyAttributes', + ]); + if (parentObject !== undefined && fromIncludeSafetyAttributes != null) { + setValueByPath(parentObject, ['parameters', 'includeSafetyAttributes'], fromIncludeSafetyAttributes); + } + const fromIncludeRaiReason = getValueByPath(fromObject, [ + 'includeRaiReason', + ]); + if (parentObject !== undefined && fromIncludeRaiReason != null) { + setValueByPath(parentObject, ['parameters', 'includeRaiReason'], fromIncludeRaiReason); + } + const fromLanguage = getValueByPath(fromObject, ['language']); + if (parentObject !== undefined && fromLanguage != null) { + setValueByPath(parentObject, ['parameters', 'language'], fromLanguage); + } + const fromOutputMimeType = getValueByPath(fromObject, [ + 'outputMimeType', + ]); + if (parentObject !== undefined && fromOutputMimeType != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'mimeType'], fromOutputMimeType); + } + const fromOutputCompressionQuality = getValueByPath(fromObject, [ + 'outputCompressionQuality', + ]); + if (parentObject !== undefined && fromOutputCompressionQuality != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'compressionQuality'], fromOutputCompressionQuality); + } + if (getValueByPath(fromObject, ['addWatermark']) !== undefined) { + throw new Error('addWatermark parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['labels']) !== undefined) { + throw new Error('labels parameter is not supported in Gemini API.'); + } + const fromImageSize = getValueByPath(fromObject, ['imageSize']); + if (parentObject !== undefined && fromImageSize != null) { + setValueByPath(parentObject, ['parameters', 'sampleImageSize'], fromImageSize); + } + if (getValueByPath(fromObject, ['enhancePrompt']) !== undefined) { + throw new Error('enhancePrompt parameter is not supported in Gemini API.'); + } + return toObject; +} +function generateImagesConfigToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromOutputGcsUri = getValueByPath(fromObject, ['outputGcsUri']); + if (parentObject !== undefined && fromOutputGcsUri != null) { + setValueByPath(parentObject, ['parameters', 'storageUri'], fromOutputGcsUri); + } + const fromNegativePrompt = getValueByPath(fromObject, [ + 'negativePrompt', + ]); + if (parentObject !== undefined && fromNegativePrompt != null) { + setValueByPath(parentObject, ['parameters', 'negativePrompt'], fromNegativePrompt); + } + const fromNumberOfImages = getValueByPath(fromObject, [ + 'numberOfImages', + ]); + if (parentObject !== undefined && fromNumberOfImages != null) { + setValueByPath(parentObject, ['parameters', 'sampleCount'], fromNumberOfImages); + } + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (parentObject !== undefined && fromAspectRatio != null) { + setValueByPath(parentObject, ['parameters', 'aspectRatio'], fromAspectRatio); + } + const fromGuidanceScale = getValueByPath(fromObject, [ + 'guidanceScale', + ]); + if (parentObject !== undefined && fromGuidanceScale != null) { + setValueByPath(parentObject, ['parameters', 'guidanceScale'], fromGuidanceScale); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (parentObject !== undefined && fromSeed != null) { + setValueByPath(parentObject, ['parameters', 'seed'], fromSeed); + } + const fromSafetyFilterLevel = getValueByPath(fromObject, [ + 'safetyFilterLevel', + ]); + if (parentObject !== undefined && fromSafetyFilterLevel != null) { + setValueByPath(parentObject, ['parameters', 'safetySetting'], fromSafetyFilterLevel); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (parentObject !== undefined && fromPersonGeneration != null) { + setValueByPath(parentObject, ['parameters', 'personGeneration'], fromPersonGeneration); + } + const fromIncludeSafetyAttributes = getValueByPath(fromObject, [ + 'includeSafetyAttributes', + ]); + if (parentObject !== undefined && fromIncludeSafetyAttributes != null) { + setValueByPath(parentObject, ['parameters', 'includeSafetyAttributes'], fromIncludeSafetyAttributes); + } + const fromIncludeRaiReason = getValueByPath(fromObject, [ + 'includeRaiReason', + ]); + if (parentObject !== undefined && fromIncludeRaiReason != null) { + setValueByPath(parentObject, ['parameters', 'includeRaiReason'], fromIncludeRaiReason); + } + const fromLanguage = getValueByPath(fromObject, ['language']); + if (parentObject !== undefined && fromLanguage != null) { + setValueByPath(parentObject, ['parameters', 'language'], fromLanguage); + } + const fromOutputMimeType = getValueByPath(fromObject, [ + 'outputMimeType', + ]); + if (parentObject !== undefined && fromOutputMimeType != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'mimeType'], fromOutputMimeType); + } + const fromOutputCompressionQuality = getValueByPath(fromObject, [ + 'outputCompressionQuality', + ]); + if (parentObject !== undefined && fromOutputCompressionQuality != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'compressionQuality'], fromOutputCompressionQuality); + } + const fromAddWatermark = getValueByPath(fromObject, ['addWatermark']); + if (parentObject !== undefined && fromAddWatermark != null) { + setValueByPath(parentObject, ['parameters', 'addWatermark'], fromAddWatermark); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (parentObject !== undefined && fromLabels != null) { + setValueByPath(parentObject, ['labels'], fromLabels); + } + const fromImageSize = getValueByPath(fromObject, ['imageSize']); + if (parentObject !== undefined && fromImageSize != null) { + setValueByPath(parentObject, ['parameters', 'sampleImageSize'], fromImageSize); + } + const fromEnhancePrompt = getValueByPath(fromObject, [ + 'enhancePrompt', + ]); + if (parentObject !== undefined && fromEnhancePrompt != null) { + setValueByPath(parentObject, ['parameters', 'enhancePrompt'], fromEnhancePrompt); + } + return toObject; +} +function generateImagesParametersToMldev(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (fromPrompt != null) { + setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + generateImagesConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function generateImagesParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (fromPrompt != null) { + setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + generateImagesConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function generateImagesResponseFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromGeneratedImages = getValueByPath(fromObject, [ + 'predictions', + ]); + if (fromGeneratedImages != null) { + let transformedList = fromGeneratedImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedImageFromMldev(item); + }); + } + setValueByPath(toObject, ['generatedImages'], transformedList); + } + const fromPositivePromptSafetyAttributes = getValueByPath(fromObject, [ + 'positivePromptSafetyAttributes', + ]); + if (fromPositivePromptSafetyAttributes != null) { + setValueByPath(toObject, ['positivePromptSafetyAttributes'], safetyAttributesFromMldev(fromPositivePromptSafetyAttributes)); + } + return toObject; +} +function generateImagesResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromGeneratedImages = getValueByPath(fromObject, [ + 'predictions', + ]); + if (fromGeneratedImages != null) { + let transformedList = fromGeneratedImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedImageFromVertex(item); + }); + } + setValueByPath(toObject, ['generatedImages'], transformedList); + } + const fromPositivePromptSafetyAttributes = getValueByPath(fromObject, [ + 'positivePromptSafetyAttributes', + ]); + if (fromPositivePromptSafetyAttributes != null) { + setValueByPath(toObject, ['positivePromptSafetyAttributes'], safetyAttributesFromVertex(fromPositivePromptSafetyAttributes)); + } + return toObject; +} +function generateVideosConfigToMldev(fromObject, parentObject, rootObject) { + const toObject = {}; + const fromNumberOfVideos = getValueByPath(fromObject, [ + 'numberOfVideos', + ]); + if (parentObject !== undefined && fromNumberOfVideos != null) { + setValueByPath(parentObject, ['parameters', 'sampleCount'], fromNumberOfVideos); + } + if (getValueByPath(fromObject, ['outputGcsUri']) !== undefined) { + throw new Error('outputGcsUri parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['fps']) !== undefined) { + throw new Error('fps parameter is not supported in Gemini API.'); + } + const fromDurationSeconds = getValueByPath(fromObject, [ + 'durationSeconds', + ]); + if (parentObject !== undefined && fromDurationSeconds != null) { + setValueByPath(parentObject, ['parameters', 'durationSeconds'], fromDurationSeconds); + } + if (getValueByPath(fromObject, ['seed']) !== undefined) { + throw new Error('seed parameter is not supported in Gemini API.'); + } + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (parentObject !== undefined && fromAspectRatio != null) { + setValueByPath(parentObject, ['parameters', 'aspectRatio'], fromAspectRatio); + } + const fromResolution = getValueByPath(fromObject, ['resolution']); + if (parentObject !== undefined && fromResolution != null) { + setValueByPath(parentObject, ['parameters', 'resolution'], fromResolution); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (parentObject !== undefined && fromPersonGeneration != null) { + setValueByPath(parentObject, ['parameters', 'personGeneration'], fromPersonGeneration); + } + if (getValueByPath(fromObject, ['pubsubTopic']) !== undefined) { + throw new Error('pubsubTopic parameter is not supported in Gemini API.'); + } + const fromNegativePrompt = getValueByPath(fromObject, [ + 'negativePrompt', + ]); + if (parentObject !== undefined && fromNegativePrompt != null) { + setValueByPath(parentObject, ['parameters', 'negativePrompt'], fromNegativePrompt); + } + const fromEnhancePrompt = getValueByPath(fromObject, [ + 'enhancePrompt', + ]); + if (parentObject !== undefined && fromEnhancePrompt != null) { + setValueByPath(parentObject, ['parameters', 'enhancePrompt'], fromEnhancePrompt); + } + if (getValueByPath(fromObject, ['generateAudio']) !== undefined) { + throw new Error('generateAudio parameter is not supported in Gemini API.'); + } + const fromLastFrame = getValueByPath(fromObject, ['lastFrame']); + if (parentObject !== undefined && fromLastFrame != null) { + setValueByPath(parentObject, ['instances[0]', 'lastFrame'], imageToMldev(fromLastFrame)); + } + const fromReferenceImages = getValueByPath(fromObject, [ + 'referenceImages', + ]); + if (parentObject !== undefined && fromReferenceImages != null) { + let transformedList = fromReferenceImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return videoGenerationReferenceImageToMldev(item); + }); + } + setValueByPath(parentObject, ['instances[0]', 'referenceImages'], transformedList); + } + if (getValueByPath(fromObject, ['mask']) !== undefined) { + throw new Error('mask parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['compressionQuality']) !== undefined) { + throw new Error('compressionQuality parameter is not supported in Gemini API.'); + } + return toObject; +} +function generateVideosConfigToVertex(fromObject, parentObject, rootObject) { + const toObject = {}; + const fromNumberOfVideos = getValueByPath(fromObject, [ + 'numberOfVideos', + ]); + if (parentObject !== undefined && fromNumberOfVideos != null) { + setValueByPath(parentObject, ['parameters', 'sampleCount'], fromNumberOfVideos); + } + const fromOutputGcsUri = getValueByPath(fromObject, ['outputGcsUri']); + if (parentObject !== undefined && fromOutputGcsUri != null) { + setValueByPath(parentObject, ['parameters', 'storageUri'], fromOutputGcsUri); + } + const fromFps = getValueByPath(fromObject, ['fps']); + if (parentObject !== undefined && fromFps != null) { + setValueByPath(parentObject, ['parameters', 'fps'], fromFps); + } + const fromDurationSeconds = getValueByPath(fromObject, [ + 'durationSeconds', + ]); + if (parentObject !== undefined && fromDurationSeconds != null) { + setValueByPath(parentObject, ['parameters', 'durationSeconds'], fromDurationSeconds); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (parentObject !== undefined && fromSeed != null) { + setValueByPath(parentObject, ['parameters', 'seed'], fromSeed); + } + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (parentObject !== undefined && fromAspectRatio != null) { + setValueByPath(parentObject, ['parameters', 'aspectRatio'], fromAspectRatio); + } + const fromResolution = getValueByPath(fromObject, ['resolution']); + if (parentObject !== undefined && fromResolution != null) { + setValueByPath(parentObject, ['parameters', 'resolution'], fromResolution); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (parentObject !== undefined && fromPersonGeneration != null) { + setValueByPath(parentObject, ['parameters', 'personGeneration'], fromPersonGeneration); + } + const fromPubsubTopic = getValueByPath(fromObject, ['pubsubTopic']); + if (parentObject !== undefined && fromPubsubTopic != null) { + setValueByPath(parentObject, ['parameters', 'pubsubTopic'], fromPubsubTopic); + } + const fromNegativePrompt = getValueByPath(fromObject, [ + 'negativePrompt', + ]); + if (parentObject !== undefined && fromNegativePrompt != null) { + setValueByPath(parentObject, ['parameters', 'negativePrompt'], fromNegativePrompt); + } + const fromEnhancePrompt = getValueByPath(fromObject, [ + 'enhancePrompt', + ]); + if (parentObject !== undefined && fromEnhancePrompt != null) { + setValueByPath(parentObject, ['parameters', 'enhancePrompt'], fromEnhancePrompt); + } + const fromGenerateAudio = getValueByPath(fromObject, [ + 'generateAudio', + ]); + if (parentObject !== undefined && fromGenerateAudio != null) { + setValueByPath(parentObject, ['parameters', 'generateAudio'], fromGenerateAudio); + } + const fromLastFrame = getValueByPath(fromObject, ['lastFrame']); + if (parentObject !== undefined && fromLastFrame != null) { + setValueByPath(parentObject, ['instances[0]', 'lastFrame'], imageToVertex(fromLastFrame)); + } + const fromReferenceImages = getValueByPath(fromObject, [ + 'referenceImages', + ]); + if (parentObject !== undefined && fromReferenceImages != null) { + let transformedList = fromReferenceImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return videoGenerationReferenceImageToVertex(item); + }); + } + setValueByPath(parentObject, ['instances[0]', 'referenceImages'], transformedList); + } + const fromMask = getValueByPath(fromObject, ['mask']); + if (parentObject !== undefined && fromMask != null) { + setValueByPath(parentObject, ['instances[0]', 'mask'], videoGenerationMaskToVertex(fromMask)); + } + const fromCompressionQuality = getValueByPath(fromObject, [ + 'compressionQuality', + ]); + if (parentObject !== undefined && fromCompressionQuality != null) { + setValueByPath(parentObject, ['parameters', 'compressionQuality'], fromCompressionQuality); + } + return toObject; +} +function generateVideosOperationFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromResponse = getValueByPath(fromObject, [ + 'response', + 'generateVideoResponse', + ]); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], generateVideosResponseFromMldev(fromResponse)); + } + return toObject; +} +function generateVideosOperationFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], generateVideosResponseFromVertex(fromResponse)); + } + return toObject; +} +function generateVideosParametersToMldev(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (fromPrompt != null) { + setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromImage = getValueByPath(fromObject, ['image']); + if (fromImage != null) { + setValueByPath(toObject, ['instances[0]', 'image'], imageToMldev(fromImage)); + } + const fromVideo = getValueByPath(fromObject, ['video']); + if (fromVideo != null) { + setValueByPath(toObject, ['instances[0]', 'video'], videoToMldev(fromVideo)); + } + const fromSource = getValueByPath(fromObject, ['source']); + if (fromSource != null) { + generateVideosSourceToMldev(fromSource, toObject); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + generateVideosConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function generateVideosParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (fromPrompt != null) { + setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromImage = getValueByPath(fromObject, ['image']); + if (fromImage != null) { + setValueByPath(toObject, ['instances[0]', 'image'], imageToVertex(fromImage)); + } + const fromVideo = getValueByPath(fromObject, ['video']); + if (fromVideo != null) { + setValueByPath(toObject, ['instances[0]', 'video'], videoToVertex(fromVideo)); + } + const fromSource = getValueByPath(fromObject, ['source']); + if (fromSource != null) { + generateVideosSourceToVertex(fromSource, toObject); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + generateVideosConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function generateVideosResponseFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromGeneratedVideos = getValueByPath(fromObject, [ + 'generatedSamples', + ]); + if (fromGeneratedVideos != null) { + let transformedList = fromGeneratedVideos; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedVideoFromMldev(item); + }); + } + setValueByPath(toObject, ['generatedVideos'], transformedList); + } + const fromRaiMediaFilteredCount = getValueByPath(fromObject, [ + 'raiMediaFilteredCount', + ]); + if (fromRaiMediaFilteredCount != null) { + setValueByPath(toObject, ['raiMediaFilteredCount'], fromRaiMediaFilteredCount); + } + const fromRaiMediaFilteredReasons = getValueByPath(fromObject, [ + 'raiMediaFilteredReasons', + ]); + if (fromRaiMediaFilteredReasons != null) { + setValueByPath(toObject, ['raiMediaFilteredReasons'], fromRaiMediaFilteredReasons); + } + return toObject; +} +function generateVideosResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromGeneratedVideos = getValueByPath(fromObject, ['videos']); + if (fromGeneratedVideos != null) { + let transformedList = fromGeneratedVideos; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedVideoFromVertex(item); + }); + } + setValueByPath(toObject, ['generatedVideos'], transformedList); + } + const fromRaiMediaFilteredCount = getValueByPath(fromObject, [ + 'raiMediaFilteredCount', + ]); + if (fromRaiMediaFilteredCount != null) { + setValueByPath(toObject, ['raiMediaFilteredCount'], fromRaiMediaFilteredCount); + } + const fromRaiMediaFilteredReasons = getValueByPath(fromObject, [ + 'raiMediaFilteredReasons', + ]); + if (fromRaiMediaFilteredReasons != null) { + setValueByPath(toObject, ['raiMediaFilteredReasons'], fromRaiMediaFilteredReasons); + } + return toObject; +} +function generateVideosSourceToMldev(fromObject, parentObject, rootObject) { + const toObject = {}; + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (parentObject !== undefined && fromPrompt != null) { + setValueByPath(parentObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromImage = getValueByPath(fromObject, ['image']); + if (parentObject !== undefined && fromImage != null) { + setValueByPath(parentObject, ['instances[0]', 'image'], imageToMldev(fromImage)); + } + const fromVideo = getValueByPath(fromObject, ['video']); + if (parentObject !== undefined && fromVideo != null) { + setValueByPath(parentObject, ['instances[0]', 'video'], videoToMldev(fromVideo)); + } + return toObject; +} +function generateVideosSourceToVertex(fromObject, parentObject, rootObject) { + const toObject = {}; + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (parentObject !== undefined && fromPrompt != null) { + setValueByPath(parentObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromImage = getValueByPath(fromObject, ['image']); + if (parentObject !== undefined && fromImage != null) { + setValueByPath(parentObject, ['instances[0]', 'image'], imageToVertex(fromImage)); + } + const fromVideo = getValueByPath(fromObject, ['video']); + if (parentObject !== undefined && fromVideo != null) { + setValueByPath(parentObject, ['instances[0]', 'video'], videoToVertex(fromVideo)); + } + return toObject; +} +function generatedImageFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromImage = getValueByPath(fromObject, ['_self']); + if (fromImage != null) { + setValueByPath(toObject, ['image'], imageFromMldev(fromImage)); + } + const fromRaiFilteredReason = getValueByPath(fromObject, [ + 'raiFilteredReason', + ]); + if (fromRaiFilteredReason != null) { + setValueByPath(toObject, ['raiFilteredReason'], fromRaiFilteredReason); + } + const fromSafetyAttributes = getValueByPath(fromObject, ['_self']); + if (fromSafetyAttributes != null) { + setValueByPath(toObject, ['safetyAttributes'], safetyAttributesFromMldev(fromSafetyAttributes)); + } + return toObject; +} +function generatedImageFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromImage = getValueByPath(fromObject, ['_self']); + if (fromImage != null) { + setValueByPath(toObject, ['image'], imageFromVertex(fromImage)); + } + const fromRaiFilteredReason = getValueByPath(fromObject, [ + 'raiFilteredReason', + ]); + if (fromRaiFilteredReason != null) { + setValueByPath(toObject, ['raiFilteredReason'], fromRaiFilteredReason); + } + const fromSafetyAttributes = getValueByPath(fromObject, ['_self']); + if (fromSafetyAttributes != null) { + setValueByPath(toObject, ['safetyAttributes'], safetyAttributesFromVertex(fromSafetyAttributes)); + } + const fromEnhancedPrompt = getValueByPath(fromObject, ['prompt']); + if (fromEnhancedPrompt != null) { + setValueByPath(toObject, ['enhancedPrompt'], fromEnhancedPrompt); + } + return toObject; +} +function generatedImageMaskFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromMask = getValueByPath(fromObject, ['_self']); + if (fromMask != null) { + setValueByPath(toObject, ['mask'], imageFromVertex(fromMask)); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (fromLabels != null) { + let transformedList = fromLabels; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['labels'], transformedList); + } + return toObject; +} +function generatedVideoFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromVideo = getValueByPath(fromObject, ['video']); + if (fromVideo != null) { + setValueByPath(toObject, ['video'], videoFromMldev(fromVideo)); + } + return toObject; +} +function generatedVideoFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromVideo = getValueByPath(fromObject, ['_self']); + if (fromVideo != null) { + setValueByPath(toObject, ['video'], videoFromVertex(fromVideo)); + } + return toObject; +} +function generationConfigToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromModelSelectionConfig = getValueByPath(fromObject, [ + 'modelSelectionConfig', + ]); + if (fromModelSelectionConfig != null) { + setValueByPath(toObject, ['modelConfig'], fromModelSelectionConfig); + } + const fromResponseJsonSchema = getValueByPath(fromObject, [ + 'responseJsonSchema', + ]); + if (fromResponseJsonSchema != null) { + setValueByPath(toObject, ['responseJsonSchema'], fromResponseJsonSchema); + } + const fromAudioTimestamp = getValueByPath(fromObject, [ + 'audioTimestamp', + ]); + if (fromAudioTimestamp != null) { + setValueByPath(toObject, ['audioTimestamp'], fromAudioTimestamp); + } + const fromCandidateCount = getValueByPath(fromObject, [ + 'candidateCount', + ]); + if (fromCandidateCount != null) { + setValueByPath(toObject, ['candidateCount'], fromCandidateCount); + } + const fromEnableAffectiveDialog = getValueByPath(fromObject, [ + 'enableAffectiveDialog', + ]); + if (fromEnableAffectiveDialog != null) { + setValueByPath(toObject, ['enableAffectiveDialog'], fromEnableAffectiveDialog); + } + const fromFrequencyPenalty = getValueByPath(fromObject, [ + 'frequencyPenalty', + ]); + if (fromFrequencyPenalty != null) { + setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty); + } + const fromLogprobs = getValueByPath(fromObject, ['logprobs']); + if (fromLogprobs != null) { + setValueByPath(toObject, ['logprobs'], fromLogprobs); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (fromMaxOutputTokens != null) { + setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromPresencePenalty = getValueByPath(fromObject, [ + 'presencePenalty', + ]); + if (fromPresencePenalty != null) { + setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty); + } + const fromResponseLogprobs = getValueByPath(fromObject, [ + 'responseLogprobs', + ]); + if (fromResponseLogprobs != null) { + setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs); + } + const fromResponseMimeType = getValueByPath(fromObject, [ + 'responseMimeType', + ]); + if (fromResponseMimeType != null) { + setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (fromResponseModalities != null) { + setValueByPath(toObject, ['responseModalities'], fromResponseModalities); + } + const fromResponseSchema = getValueByPath(fromObject, [ + 'responseSchema', + ]); + if (fromResponseSchema != null) { + setValueByPath(toObject, ['responseSchema'], fromResponseSchema); + } + const fromRoutingConfig = getValueByPath(fromObject, [ + 'routingConfig', + ]); + if (fromRoutingConfig != null) { + setValueByPath(toObject, ['routingConfig'], fromRoutingConfig); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (fromSeed != null) { + setValueByPath(toObject, ['seed'], fromSeed); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (fromSpeechConfig != null) { + setValueByPath(toObject, ['speechConfig'], fromSpeechConfig); + } + const fromStopSequences = getValueByPath(fromObject, [ + 'stopSequences', + ]); + if (fromStopSequences != null) { + setValueByPath(toObject, ['stopSequences'], fromStopSequences); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (fromTemperature != null) { + setValueByPath(toObject, ['temperature'], fromTemperature); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (fromThinkingConfig != null) { + setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (fromTopK != null) { + setValueByPath(toObject, ['topK'], fromTopK); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (fromTopP != null) { + setValueByPath(toObject, ['topP'], fromTopP); + } + if (getValueByPath(fromObject, ['enableEnhancedCivicAnswers']) !== + undefined) { + throw new Error('enableEnhancedCivicAnswers parameter is not supported in Vertex AI.'); + } + return toObject; +} +function getModelParametersToMldev(apiClient, fromObject, _rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'name'], tModel(apiClient, fromModel)); + } + return toObject; +} +function getModelParametersToVertex(apiClient, fromObject, _rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'name'], tModel(apiClient, fromModel)); + } + return toObject; +} +function googleMapsToMldev$1(fromObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['authConfig']) !== undefined) { + throw new Error('authConfig parameter is not supported in Gemini API.'); + } + const fromEnableWidget = getValueByPath(fromObject, ['enableWidget']); + if (fromEnableWidget != null) { + setValueByPath(toObject, ['enableWidget'], fromEnableWidget); + } + return toObject; +} +function googleSearchToMldev$1(fromObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['excludeDomains']) !== undefined) { + throw new Error('excludeDomains parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['blockingConfidence']) !== undefined) { + throw new Error('blockingConfidence parameter is not supported in Gemini API.'); + } + const fromTimeRangeFilter = getValueByPath(fromObject, [ + 'timeRangeFilter', + ]); + if (fromTimeRangeFilter != null) { + setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter); + } + return toObject; +} +function imageConfigToMldev(fromObject, _rootObject) { + const toObject = {}; + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (fromAspectRatio != null) { + setValueByPath(toObject, ['aspectRatio'], fromAspectRatio); + } + const fromImageSize = getValueByPath(fromObject, ['imageSize']); + if (fromImageSize != null) { + setValueByPath(toObject, ['imageSize'], fromImageSize); + } + if (getValueByPath(fromObject, ['personGeneration']) !== undefined) { + throw new Error('personGeneration parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['outputMimeType']) !== undefined) { + throw new Error('outputMimeType parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['outputCompressionQuality']) !== + undefined) { + throw new Error('outputCompressionQuality parameter is not supported in Gemini API.'); + } + return toObject; +} +function imageConfigToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromAspectRatio = getValueByPath(fromObject, ['aspectRatio']); + if (fromAspectRatio != null) { + setValueByPath(toObject, ['aspectRatio'], fromAspectRatio); + } + const fromImageSize = getValueByPath(fromObject, ['imageSize']); + if (fromImageSize != null) { + setValueByPath(toObject, ['imageSize'], fromImageSize); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (fromPersonGeneration != null) { + setValueByPath(toObject, ['personGeneration'], fromPersonGeneration); + } + const fromOutputMimeType = getValueByPath(fromObject, [ + 'outputMimeType', + ]); + if (fromOutputMimeType != null) { + setValueByPath(toObject, ['imageOutputOptions', 'mimeType'], fromOutputMimeType); + } + const fromOutputCompressionQuality = getValueByPath(fromObject, [ + 'outputCompressionQuality', + ]); + if (fromOutputCompressionQuality != null) { + setValueByPath(toObject, ['imageOutputOptions', 'compressionQuality'], fromOutputCompressionQuality); + } + return toObject; +} +function imageFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromImageBytes = getValueByPath(fromObject, [ + 'bytesBase64Encoded', + ]); + if (fromImageBytes != null) { + setValueByPath(toObject, ['imageBytes'], tBytes(fromImageBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function imageFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (fromGcsUri != null) { + setValueByPath(toObject, ['gcsUri'], fromGcsUri); + } + const fromImageBytes = getValueByPath(fromObject, [ + 'bytesBase64Encoded', + ]); + if (fromImageBytes != null) { + setValueByPath(toObject, ['imageBytes'], tBytes(fromImageBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function imageToMldev(fromObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['gcsUri']) !== undefined) { + throw new Error('gcsUri parameter is not supported in Gemini API.'); + } + const fromImageBytes = getValueByPath(fromObject, ['imageBytes']); + if (fromImageBytes != null) { + setValueByPath(toObject, ['bytesBase64Encoded'], tBytes(fromImageBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function imageToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (fromGcsUri != null) { + setValueByPath(toObject, ['gcsUri'], fromGcsUri); + } + const fromImageBytes = getValueByPath(fromObject, ['imageBytes']); + if (fromImageBytes != null) { + setValueByPath(toObject, ['bytesBase64Encoded'], tBytes(fromImageBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function listModelsConfigToMldev(apiClient, fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + const fromFilter = getValueByPath(fromObject, ['filter']); + if (parentObject !== undefined && fromFilter != null) { + setValueByPath(parentObject, ['_query', 'filter'], fromFilter); + } + const fromQueryBase = getValueByPath(fromObject, ['queryBase']); + if (parentObject !== undefined && fromQueryBase != null) { + setValueByPath(parentObject, ['_url', 'models_url'], tModelsUrl(apiClient, fromQueryBase)); + } + return toObject; +} +function listModelsConfigToVertex(apiClient, fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + const fromFilter = getValueByPath(fromObject, ['filter']); + if (parentObject !== undefined && fromFilter != null) { + setValueByPath(parentObject, ['_query', 'filter'], fromFilter); + } + const fromQueryBase = getValueByPath(fromObject, ['queryBase']); + if (parentObject !== undefined && fromQueryBase != null) { + setValueByPath(parentObject, ['_url', 'models_url'], tModelsUrl(apiClient, fromQueryBase)); + } + return toObject; +} +function listModelsParametersToMldev(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listModelsConfigToMldev(apiClient, fromConfig, toObject); + } + return toObject; +} +function listModelsParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listModelsConfigToVertex(apiClient, fromConfig, toObject); + } + return toObject; +} +function listModelsResponseFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromModels = getValueByPath(fromObject, ['_self']); + if (fromModels != null) { + let transformedList = tExtractModels(fromModels); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return modelFromMldev(item); + }); + } + setValueByPath(toObject, ['models'], transformedList); + } + return toObject; +} +function listModelsResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromModels = getValueByPath(fromObject, ['_self']); + if (fromModels != null) { + let transformedList = tExtractModels(fromModels); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return modelFromVertex(item); + }); + } + setValueByPath(toObject, ['models'], transformedList); + } + return toObject; +} +function maskReferenceConfigToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromMaskMode = getValueByPath(fromObject, ['maskMode']); + if (fromMaskMode != null) { + setValueByPath(toObject, ['maskMode'], fromMaskMode); + } + const fromSegmentationClasses = getValueByPath(fromObject, [ + 'segmentationClasses', + ]); + if (fromSegmentationClasses != null) { + setValueByPath(toObject, ['maskClasses'], fromSegmentationClasses); + } + const fromMaskDilation = getValueByPath(fromObject, ['maskDilation']); + if (fromMaskDilation != null) { + setValueByPath(toObject, ['dilation'], fromMaskDilation); + } + return toObject; +} +function modelFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (fromDisplayName != null) { + setValueByPath(toObject, ['displayName'], fromDisplayName); + } + const fromDescription = getValueByPath(fromObject, ['description']); + if (fromDescription != null) { + setValueByPath(toObject, ['description'], fromDescription); + } + const fromVersion = getValueByPath(fromObject, ['version']); + if (fromVersion != null) { + setValueByPath(toObject, ['version'], fromVersion); + } + const fromTunedModelInfo = getValueByPath(fromObject, ['_self']); + if (fromTunedModelInfo != null) { + setValueByPath(toObject, ['tunedModelInfo'], tunedModelInfoFromMldev(fromTunedModelInfo)); + } + const fromInputTokenLimit = getValueByPath(fromObject, [ + 'inputTokenLimit', + ]); + if (fromInputTokenLimit != null) { + setValueByPath(toObject, ['inputTokenLimit'], fromInputTokenLimit); + } + const fromOutputTokenLimit = getValueByPath(fromObject, [ + 'outputTokenLimit', + ]); + if (fromOutputTokenLimit != null) { + setValueByPath(toObject, ['outputTokenLimit'], fromOutputTokenLimit); + } + const fromSupportedActions = getValueByPath(fromObject, [ + 'supportedGenerationMethods', + ]); + if (fromSupportedActions != null) { + setValueByPath(toObject, ['supportedActions'], fromSupportedActions); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (fromTemperature != null) { + setValueByPath(toObject, ['temperature'], fromTemperature); + } + const fromMaxTemperature = getValueByPath(fromObject, [ + 'maxTemperature', + ]); + if (fromMaxTemperature != null) { + setValueByPath(toObject, ['maxTemperature'], fromMaxTemperature); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (fromTopP != null) { + setValueByPath(toObject, ['topP'], fromTopP); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (fromTopK != null) { + setValueByPath(toObject, ['topK'], fromTopK); + } + const fromThinking = getValueByPath(fromObject, ['thinking']); + if (fromThinking != null) { + setValueByPath(toObject, ['thinking'], fromThinking); + } + return toObject; +} +function modelFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (fromDisplayName != null) { + setValueByPath(toObject, ['displayName'], fromDisplayName); + } + const fromDescription = getValueByPath(fromObject, ['description']); + if (fromDescription != null) { + setValueByPath(toObject, ['description'], fromDescription); + } + const fromVersion = getValueByPath(fromObject, ['versionId']); + if (fromVersion != null) { + setValueByPath(toObject, ['version'], fromVersion); + } + const fromEndpoints = getValueByPath(fromObject, ['deployedModels']); + if (fromEndpoints != null) { + let transformedList = fromEndpoints; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return endpointFromVertex(item); + }); + } + setValueByPath(toObject, ['endpoints'], transformedList); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (fromLabels != null) { + setValueByPath(toObject, ['labels'], fromLabels); + } + const fromTunedModelInfo = getValueByPath(fromObject, ['_self']); + if (fromTunedModelInfo != null) { + setValueByPath(toObject, ['tunedModelInfo'], tunedModelInfoFromVertex(fromTunedModelInfo)); + } + const fromDefaultCheckpointId = getValueByPath(fromObject, [ + 'defaultCheckpointId', + ]); + if (fromDefaultCheckpointId != null) { + setValueByPath(toObject, ['defaultCheckpointId'], fromDefaultCheckpointId); + } + const fromCheckpoints = getValueByPath(fromObject, ['checkpoints']); + if (fromCheckpoints != null) { + let transformedList = fromCheckpoints; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['checkpoints'], transformedList); + } + return toObject; +} +function partToMldev$1(fromObject, rootObject) { + const toObject = {}; + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromCodeExecutionResult = getValueByPath(fromObject, [ + 'codeExecutionResult', + ]); + if (fromCodeExecutionResult != null) { + setValueByPath(toObject, ['codeExecutionResult'], fromCodeExecutionResult); + } + const fromExecutableCode = getValueByPath(fromObject, [ + 'executableCode', + ]); + if (fromExecutableCode != null) { + setValueByPath(toObject, ['executableCode'], fromExecutableCode); + } + const fromFileData = getValueByPath(fromObject, ['fileData']); + if (fromFileData != null) { + setValueByPath(toObject, ['fileData'], fileDataToMldev$1(fromFileData)); + } + const fromFunctionCall = getValueByPath(fromObject, ['functionCall']); + if (fromFunctionCall != null) { + setValueByPath(toObject, ['functionCall'], functionCallToMldev$1(fromFunctionCall)); + } + const fromFunctionResponse = getValueByPath(fromObject, [ + 'functionResponse', + ]); + if (fromFunctionResponse != null) { + setValueByPath(toObject, ['functionResponse'], fromFunctionResponse); + } + const fromInlineData = getValueByPath(fromObject, ['inlineData']); + if (fromInlineData != null) { + setValueByPath(toObject, ['inlineData'], blobToMldev$1(fromInlineData)); + } + const fromText = getValueByPath(fromObject, ['text']); + if (fromText != null) { + setValueByPath(toObject, ['text'], fromText); + } + const fromThought = getValueByPath(fromObject, ['thought']); + if (fromThought != null) { + setValueByPath(toObject, ['thought'], fromThought); + } + const fromThoughtSignature = getValueByPath(fromObject, [ + 'thoughtSignature', + ]); + if (fromThoughtSignature != null) { + setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature); + } + const fromVideoMetadata = getValueByPath(fromObject, [ + 'videoMetadata', + ]); + if (fromVideoMetadata != null) { + setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata); + } + return toObject; +} +function productImageToVertex(fromObject, rootObject) { + const toObject = {}; + const fromProductImage = getValueByPath(fromObject, ['productImage']); + if (fromProductImage != null) { + setValueByPath(toObject, ['image'], imageToVertex(fromProductImage)); + } + return toObject; +} +function recontextImageConfigToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromNumberOfImages = getValueByPath(fromObject, [ + 'numberOfImages', + ]); + if (parentObject !== undefined && fromNumberOfImages != null) { + setValueByPath(parentObject, ['parameters', 'sampleCount'], fromNumberOfImages); + } + const fromBaseSteps = getValueByPath(fromObject, ['baseSteps']); + if (parentObject !== undefined && fromBaseSteps != null) { + setValueByPath(parentObject, ['parameters', 'baseSteps'], fromBaseSteps); + } + const fromOutputGcsUri = getValueByPath(fromObject, ['outputGcsUri']); + if (parentObject !== undefined && fromOutputGcsUri != null) { + setValueByPath(parentObject, ['parameters', 'storageUri'], fromOutputGcsUri); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (parentObject !== undefined && fromSeed != null) { + setValueByPath(parentObject, ['parameters', 'seed'], fromSeed); + } + const fromSafetyFilterLevel = getValueByPath(fromObject, [ + 'safetyFilterLevel', + ]); + if (parentObject !== undefined && fromSafetyFilterLevel != null) { + setValueByPath(parentObject, ['parameters', 'safetySetting'], fromSafetyFilterLevel); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (parentObject !== undefined && fromPersonGeneration != null) { + setValueByPath(parentObject, ['parameters', 'personGeneration'], fromPersonGeneration); + } + const fromAddWatermark = getValueByPath(fromObject, ['addWatermark']); + if (parentObject !== undefined && fromAddWatermark != null) { + setValueByPath(parentObject, ['parameters', 'addWatermark'], fromAddWatermark); + } + const fromOutputMimeType = getValueByPath(fromObject, [ + 'outputMimeType', + ]); + if (parentObject !== undefined && fromOutputMimeType != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'mimeType'], fromOutputMimeType); + } + const fromOutputCompressionQuality = getValueByPath(fromObject, [ + 'outputCompressionQuality', + ]); + if (parentObject !== undefined && fromOutputCompressionQuality != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'compressionQuality'], fromOutputCompressionQuality); + } + const fromEnhancePrompt = getValueByPath(fromObject, [ + 'enhancePrompt', + ]); + if (parentObject !== undefined && fromEnhancePrompt != null) { + setValueByPath(parentObject, ['parameters', 'enhancePrompt'], fromEnhancePrompt); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (parentObject !== undefined && fromLabels != null) { + setValueByPath(parentObject, ['labels'], fromLabels); + } + return toObject; +} +function recontextImageParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromSource = getValueByPath(fromObject, ['source']); + if (fromSource != null) { + recontextImageSourceToVertex(fromSource, toObject); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + recontextImageConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function recontextImageResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromGeneratedImages = getValueByPath(fromObject, [ + 'predictions', + ]); + if (fromGeneratedImages != null) { + let transformedList = fromGeneratedImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedImageFromVertex(item); + }); + } + setValueByPath(toObject, ['generatedImages'], transformedList); + } + return toObject; +} +function recontextImageSourceToVertex(fromObject, parentObject, rootObject) { + const toObject = {}; + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (parentObject !== undefined && fromPrompt != null) { + setValueByPath(parentObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromPersonImage = getValueByPath(fromObject, ['personImage']); + if (parentObject !== undefined && fromPersonImage != null) { + setValueByPath(parentObject, ['instances[0]', 'personImage', 'image'], imageToVertex(fromPersonImage)); + } + const fromProductImages = getValueByPath(fromObject, [ + 'productImages', + ]); + if (parentObject !== undefined && fromProductImages != null) { + let transformedList = fromProductImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return productImageToVertex(item); + }); + } + setValueByPath(parentObject, ['instances[0]', 'productImages'], transformedList); + } + return toObject; +} +function referenceImageAPIInternalToVertex(fromObject, rootObject) { + const toObject = {}; + const fromReferenceImage = getValueByPath(fromObject, [ + 'referenceImage', + ]); + if (fromReferenceImage != null) { + setValueByPath(toObject, ['referenceImage'], imageToVertex(fromReferenceImage)); + } + const fromReferenceId = getValueByPath(fromObject, ['referenceId']); + if (fromReferenceId != null) { + setValueByPath(toObject, ['referenceId'], fromReferenceId); + } + const fromReferenceType = getValueByPath(fromObject, [ + 'referenceType', + ]); + if (fromReferenceType != null) { + setValueByPath(toObject, ['referenceType'], fromReferenceType); + } + const fromMaskImageConfig = getValueByPath(fromObject, [ + 'maskImageConfig', + ]); + if (fromMaskImageConfig != null) { + setValueByPath(toObject, ['maskImageConfig'], maskReferenceConfigToVertex(fromMaskImageConfig)); + } + const fromControlImageConfig = getValueByPath(fromObject, [ + 'controlImageConfig', + ]); + if (fromControlImageConfig != null) { + setValueByPath(toObject, ['controlImageConfig'], controlReferenceConfigToVertex(fromControlImageConfig)); + } + const fromStyleImageConfig = getValueByPath(fromObject, [ + 'styleImageConfig', + ]); + if (fromStyleImageConfig != null) { + setValueByPath(toObject, ['styleImageConfig'], fromStyleImageConfig); + } + const fromSubjectImageConfig = getValueByPath(fromObject, [ + 'subjectImageConfig', + ]); + if (fromSubjectImageConfig != null) { + setValueByPath(toObject, ['subjectImageConfig'], fromSubjectImageConfig); + } + return toObject; +} +function safetyAttributesFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromCategories = getValueByPath(fromObject, [ + 'safetyAttributes', + 'categories', + ]); + if (fromCategories != null) { + setValueByPath(toObject, ['categories'], fromCategories); + } + const fromScores = getValueByPath(fromObject, [ + 'safetyAttributes', + 'scores', + ]); + if (fromScores != null) { + setValueByPath(toObject, ['scores'], fromScores); + } + const fromContentType = getValueByPath(fromObject, ['contentType']); + if (fromContentType != null) { + setValueByPath(toObject, ['contentType'], fromContentType); + } + return toObject; +} +function safetyAttributesFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromCategories = getValueByPath(fromObject, [ + 'safetyAttributes', + 'categories', + ]); + if (fromCategories != null) { + setValueByPath(toObject, ['categories'], fromCategories); + } + const fromScores = getValueByPath(fromObject, [ + 'safetyAttributes', + 'scores', + ]); + if (fromScores != null) { + setValueByPath(toObject, ['scores'], fromScores); + } + const fromContentType = getValueByPath(fromObject, ['contentType']); + if (fromContentType != null) { + setValueByPath(toObject, ['contentType'], fromContentType); + } + return toObject; +} +function safetySettingToMldev(fromObject, _rootObject) { + const toObject = {}; + const fromCategory = getValueByPath(fromObject, ['category']); + if (fromCategory != null) { + setValueByPath(toObject, ['category'], fromCategory); + } + if (getValueByPath(fromObject, ['method']) !== undefined) { + throw new Error('method parameter is not supported in Gemini API.'); + } + const fromThreshold = getValueByPath(fromObject, ['threshold']); + if (fromThreshold != null) { + setValueByPath(toObject, ['threshold'], fromThreshold); + } + return toObject; +} +function scribbleImageToVertex(fromObject, rootObject) { + const toObject = {}; + const fromImage = getValueByPath(fromObject, ['image']); + if (fromImage != null) { + setValueByPath(toObject, ['image'], imageToVertex(fromImage)); + } + return toObject; +} +function segmentImageConfigToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromMode = getValueByPath(fromObject, ['mode']); + if (parentObject !== undefined && fromMode != null) { + setValueByPath(parentObject, ['parameters', 'mode'], fromMode); + } + const fromMaxPredictions = getValueByPath(fromObject, [ + 'maxPredictions', + ]); + if (parentObject !== undefined && fromMaxPredictions != null) { + setValueByPath(parentObject, ['parameters', 'maxPredictions'], fromMaxPredictions); + } + const fromConfidenceThreshold = getValueByPath(fromObject, [ + 'confidenceThreshold', + ]); + if (parentObject !== undefined && fromConfidenceThreshold != null) { + setValueByPath(parentObject, ['parameters', 'confidenceThreshold'], fromConfidenceThreshold); + } + const fromMaskDilation = getValueByPath(fromObject, ['maskDilation']); + if (parentObject !== undefined && fromMaskDilation != null) { + setValueByPath(parentObject, ['parameters', 'maskDilation'], fromMaskDilation); + } + const fromBinaryColorThreshold = getValueByPath(fromObject, [ + 'binaryColorThreshold', + ]); + if (parentObject !== undefined && fromBinaryColorThreshold != null) { + setValueByPath(parentObject, ['parameters', 'binaryColorThreshold'], fromBinaryColorThreshold); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (parentObject !== undefined && fromLabels != null) { + setValueByPath(parentObject, ['labels'], fromLabels); + } + return toObject; +} +function segmentImageParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromSource = getValueByPath(fromObject, ['source']); + if (fromSource != null) { + segmentImageSourceToVertex(fromSource, toObject); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + segmentImageConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function segmentImageResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromGeneratedMasks = getValueByPath(fromObject, ['predictions']); + if (fromGeneratedMasks != null) { + let transformedList = fromGeneratedMasks; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedImageMaskFromVertex(item); + }); + } + setValueByPath(toObject, ['generatedMasks'], transformedList); + } + return toObject; +} +function segmentImageSourceToVertex(fromObject, parentObject, rootObject) { + const toObject = {}; + const fromPrompt = getValueByPath(fromObject, ['prompt']); + if (parentObject !== undefined && fromPrompt != null) { + setValueByPath(parentObject, ['instances[0]', 'prompt'], fromPrompt); + } + const fromImage = getValueByPath(fromObject, ['image']); + if (parentObject !== undefined && fromImage != null) { + setValueByPath(parentObject, ['instances[0]', 'image'], imageToVertex(fromImage)); + } + const fromScribbleImage = getValueByPath(fromObject, [ + 'scribbleImage', + ]); + if (parentObject !== undefined && fromScribbleImage != null) { + setValueByPath(parentObject, ['instances[0]', 'scribble'], scribbleImageToVertex(fromScribbleImage)); + } + return toObject; +} +function toolConfigToMldev(fromObject, rootObject) { + const toObject = {}; + const fromRetrievalConfig = getValueByPath(fromObject, [ + 'retrievalConfig', + ]); + if (fromRetrievalConfig != null) { + setValueByPath(toObject, ['retrievalConfig'], fromRetrievalConfig); + } + const fromFunctionCallingConfig = getValueByPath(fromObject, [ + 'functionCallingConfig', + ]); + if (fromFunctionCallingConfig != null) { + setValueByPath(toObject, ['functionCallingConfig'], functionCallingConfigToMldev(fromFunctionCallingConfig)); + } + return toObject; +} +function toolToMldev$1(fromObject, rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['retrieval']) !== undefined) { + throw new Error('retrieval parameter is not supported in Gemini API.'); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + const fromFileSearch = getValueByPath(fromObject, ['fileSearch']); + if (fromFileSearch != null) { + setValueByPath(toObject, ['fileSearch'], fromFileSearch); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + if (getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined) { + throw new Error('enterpriseWebSearch parameter is not supported in Gemini API.'); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], googleMapsToMldev$1(fromGoogleMaps)); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], googleSearchToMldev$1(fromGoogleSearch)); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} +function toolToVertex(fromObject, rootObject) { + const toObject = {}; + const fromRetrieval = getValueByPath(fromObject, ['retrieval']); + if (fromRetrieval != null) { + setValueByPath(toObject, ['retrieval'], fromRetrieval); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + if (getValueByPath(fromObject, ['fileSearch']) !== undefined) { + throw new Error('fileSearch parameter is not supported in Vertex AI.'); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + const fromEnterpriseWebSearch = getValueByPath(fromObject, [ + 'enterpriseWebSearch', + ]); + if (fromEnterpriseWebSearch != null) { + setValueByPath(toObject, ['enterpriseWebSearch'], fromEnterpriseWebSearch); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return functionDeclarationToVertex(item); + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], fromGoogleMaps); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], fromGoogleSearch); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} +function tunedModelInfoFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromBaseModel = getValueByPath(fromObject, ['baseModel']); + if (fromBaseModel != null) { + setValueByPath(toObject, ['baseModel'], fromBaseModel); + } + const fromCreateTime = getValueByPath(fromObject, ['createTime']); + if (fromCreateTime != null) { + setValueByPath(toObject, ['createTime'], fromCreateTime); + } + const fromUpdateTime = getValueByPath(fromObject, ['updateTime']); + if (fromUpdateTime != null) { + setValueByPath(toObject, ['updateTime'], fromUpdateTime); + } + return toObject; +} +function tunedModelInfoFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromBaseModel = getValueByPath(fromObject, [ + 'labels', + 'google-vertex-llm-tuning-base-model-id', + ]); + if (fromBaseModel != null) { + setValueByPath(toObject, ['baseModel'], fromBaseModel); + } + const fromCreateTime = getValueByPath(fromObject, ['createTime']); + if (fromCreateTime != null) { + setValueByPath(toObject, ['createTime'], fromCreateTime); + } + const fromUpdateTime = getValueByPath(fromObject, ['updateTime']); + if (fromUpdateTime != null) { + setValueByPath(toObject, ['updateTime'], fromUpdateTime); + } + return toObject; +} +function updateModelConfigToMldev(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromDisplayName); + } + const fromDescription = getValueByPath(fromObject, ['description']); + if (parentObject !== undefined && fromDescription != null) { + setValueByPath(parentObject, ['description'], fromDescription); + } + const fromDefaultCheckpointId = getValueByPath(fromObject, [ + 'defaultCheckpointId', + ]); + if (parentObject !== undefined && fromDefaultCheckpointId != null) { + setValueByPath(parentObject, ['defaultCheckpointId'], fromDefaultCheckpointId); + } + return toObject; +} +function updateModelConfigToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromDisplayName); + } + const fromDescription = getValueByPath(fromObject, ['description']); + if (parentObject !== undefined && fromDescription != null) { + setValueByPath(parentObject, ['description'], fromDescription); + } + const fromDefaultCheckpointId = getValueByPath(fromObject, [ + 'defaultCheckpointId', + ]); + if (parentObject !== undefined && fromDefaultCheckpointId != null) { + setValueByPath(parentObject, ['defaultCheckpointId'], fromDefaultCheckpointId); + } + return toObject; +} +function updateModelParametersToMldev(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'name'], tModel(apiClient, fromModel)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + updateModelConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function updateModelParametersToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + updateModelConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function upscaleImageAPIConfigInternalToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromOutputGcsUri = getValueByPath(fromObject, ['outputGcsUri']); + if (parentObject !== undefined && fromOutputGcsUri != null) { + setValueByPath(parentObject, ['parameters', 'storageUri'], fromOutputGcsUri); + } + const fromSafetyFilterLevel = getValueByPath(fromObject, [ + 'safetyFilterLevel', + ]); + if (parentObject !== undefined && fromSafetyFilterLevel != null) { + setValueByPath(parentObject, ['parameters', 'safetySetting'], fromSafetyFilterLevel); + } + const fromPersonGeneration = getValueByPath(fromObject, [ + 'personGeneration', + ]); + if (parentObject !== undefined && fromPersonGeneration != null) { + setValueByPath(parentObject, ['parameters', 'personGeneration'], fromPersonGeneration); + } + const fromIncludeRaiReason = getValueByPath(fromObject, [ + 'includeRaiReason', + ]); + if (parentObject !== undefined && fromIncludeRaiReason != null) { + setValueByPath(parentObject, ['parameters', 'includeRaiReason'], fromIncludeRaiReason); + } + const fromOutputMimeType = getValueByPath(fromObject, [ + 'outputMimeType', + ]); + if (parentObject !== undefined && fromOutputMimeType != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'mimeType'], fromOutputMimeType); + } + const fromOutputCompressionQuality = getValueByPath(fromObject, [ + 'outputCompressionQuality', + ]); + if (parentObject !== undefined && fromOutputCompressionQuality != null) { + setValueByPath(parentObject, ['parameters', 'outputOptions', 'compressionQuality'], fromOutputCompressionQuality); + } + const fromEnhanceInputImage = getValueByPath(fromObject, [ + 'enhanceInputImage', + ]); + if (parentObject !== undefined && fromEnhanceInputImage != null) { + setValueByPath(parentObject, ['parameters', 'upscaleConfig', 'enhanceInputImage'], fromEnhanceInputImage); + } + const fromImagePreservationFactor = getValueByPath(fromObject, [ + 'imagePreservationFactor', + ]); + if (parentObject !== undefined && fromImagePreservationFactor != null) { + setValueByPath(parentObject, ['parameters', 'upscaleConfig', 'imagePreservationFactor'], fromImagePreservationFactor); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (parentObject !== undefined && fromLabels != null) { + setValueByPath(parentObject, ['labels'], fromLabels); + } + const fromNumberOfImages = getValueByPath(fromObject, [ + 'numberOfImages', + ]); + if (parentObject !== undefined && fromNumberOfImages != null) { + setValueByPath(parentObject, ['parameters', 'sampleCount'], fromNumberOfImages); + } + const fromMode = getValueByPath(fromObject, ['mode']); + if (parentObject !== undefined && fromMode != null) { + setValueByPath(parentObject, ['parameters', 'mode'], fromMode); + } + return toObject; +} +function upscaleImageAPIParametersInternalToVertex(apiClient, fromObject, rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['_url', 'model'], tModel(apiClient, fromModel)); + } + const fromImage = getValueByPath(fromObject, ['image']); + if (fromImage != null) { + setValueByPath(toObject, ['instances[0]', 'image'], imageToVertex(fromImage)); + } + const fromUpscaleFactor = getValueByPath(fromObject, [ + 'upscaleFactor', + ]); + if (fromUpscaleFactor != null) { + setValueByPath(toObject, ['parameters', 'upscaleConfig', 'upscaleFactor'], fromUpscaleFactor); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + upscaleImageAPIConfigInternalToVertex(fromConfig, toObject); + } + return toObject; +} +function upscaleImageResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromGeneratedImages = getValueByPath(fromObject, [ + 'predictions', + ]); + if (fromGeneratedImages != null) { + let transformedList = fromGeneratedImages; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return generatedImageFromVertex(item); + }); + } + setValueByPath(toObject, ['generatedImages'], transformedList); + } + return toObject; +} +function videoFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromUri = getValueByPath(fromObject, ['uri']); + if (fromUri != null) { + setValueByPath(toObject, ['uri'], fromUri); + } + const fromVideoBytes = getValueByPath(fromObject, ['encodedVideo']); + if (fromVideoBytes != null) { + setValueByPath(toObject, ['videoBytes'], tBytes(fromVideoBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['encoding']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function videoFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromUri = getValueByPath(fromObject, ['gcsUri']); + if (fromUri != null) { + setValueByPath(toObject, ['uri'], fromUri); + } + const fromVideoBytes = getValueByPath(fromObject, [ + 'bytesBase64Encoded', + ]); + if (fromVideoBytes != null) { + setValueByPath(toObject, ['videoBytes'], tBytes(fromVideoBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function videoGenerationMaskToVertex(fromObject, rootObject) { + const toObject = {}; + const fromImage = getValueByPath(fromObject, ['image']); + if (fromImage != null) { + setValueByPath(toObject, ['_self'], imageToVertex(fromImage)); + } + const fromMaskMode = getValueByPath(fromObject, ['maskMode']); + if (fromMaskMode != null) { + setValueByPath(toObject, ['maskMode'], fromMaskMode); + } + return toObject; +} +function videoGenerationReferenceImageToMldev(fromObject, rootObject) { + const toObject = {}; + const fromImage = getValueByPath(fromObject, ['image']); + if (fromImage != null) { + setValueByPath(toObject, ['image'], imageToMldev(fromImage)); + } + const fromReferenceType = getValueByPath(fromObject, [ + 'referenceType', + ]); + if (fromReferenceType != null) { + setValueByPath(toObject, ['referenceType'], fromReferenceType); + } + return toObject; +} +function videoGenerationReferenceImageToVertex(fromObject, rootObject) { + const toObject = {}; + const fromImage = getValueByPath(fromObject, ['image']); + if (fromImage != null) { + setValueByPath(toObject, ['image'], imageToVertex(fromImage)); + } + const fromReferenceType = getValueByPath(fromObject, [ + 'referenceType', + ]); + if (fromReferenceType != null) { + setValueByPath(toObject, ['referenceType'], fromReferenceType); + } + return toObject; +} +function videoToMldev(fromObject, _rootObject) { + const toObject = {}; + const fromUri = getValueByPath(fromObject, ['uri']); + if (fromUri != null) { + setValueByPath(toObject, ['uri'], fromUri); + } + const fromVideoBytes = getValueByPath(fromObject, ['videoBytes']); + if (fromVideoBytes != null) { + setValueByPath(toObject, ['encodedVideo'], tBytes(fromVideoBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['encoding'], fromMimeType); + } + return toObject; +} +function videoToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromUri = getValueByPath(fromObject, ['uri']); + if (fromUri != null) { + setValueByPath(toObject, ['gcsUri'], fromUri); + } + const fromVideoBytes = getValueByPath(fromObject, ['videoBytes']); + if (fromVideoBytes != null) { + setValueByPath(toObject, ['bytesBase64Encoded'], tBytes(fromVideoBytes)); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Code generated by the Google Gen AI SDK generator DO NOT EDIT. +function createFileSearchStoreConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromDisplayName); + } + return toObject; +} +function createFileSearchStoreParametersToMldev(fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createFileSearchStoreConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function deleteFileSearchStoreConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromForce = getValueByPath(fromObject, ['force']); + if (parentObject !== undefined && fromForce != null) { + setValueByPath(parentObject, ['_query', 'force'], fromForce); + } + return toObject; +} +function deleteFileSearchStoreParametersToMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + deleteFileSearchStoreConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function getFileSearchStoreParametersToMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + return toObject; +} +function importFileConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromCustomMetadata = getValueByPath(fromObject, [ + 'customMetadata', + ]); + if (parentObject !== undefined && fromCustomMetadata != null) { + let transformedList = fromCustomMetadata; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(parentObject, ['customMetadata'], transformedList); + } + const fromChunkingConfig = getValueByPath(fromObject, [ + 'chunkingConfig', + ]); + if (parentObject !== undefined && fromChunkingConfig != null) { + setValueByPath(parentObject, ['chunkingConfig'], fromChunkingConfig); + } + return toObject; +} +function importFileOperationFromMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromResponse = getValueByPath(fromObject, ['response']); + if (fromResponse != null) { + setValueByPath(toObject, ['response'], importFileResponseFromMldev(fromResponse)); + } + return toObject; +} +function importFileParametersToMldev(fromObject) { + const toObject = {}; + const fromFileSearchStoreName = getValueByPath(fromObject, [ + 'fileSearchStoreName', + ]); + if (fromFileSearchStoreName != null) { + setValueByPath(toObject, ['_url', 'file_search_store_name'], fromFileSearchStoreName); + } + const fromFileName = getValueByPath(fromObject, ['fileName']); + if (fromFileName != null) { + setValueByPath(toObject, ['fileName'], fromFileName); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + importFileConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function importFileResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromParent = getValueByPath(fromObject, ['parent']); + if (fromParent != null) { + setValueByPath(toObject, ['parent'], fromParent); + } + const fromDocumentName = getValueByPath(fromObject, ['documentName']); + if (fromDocumentName != null) { + setValueByPath(toObject, ['documentName'], fromDocumentName); + } + return toObject; +} +function listFileSearchStoresConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + return toObject; +} +function listFileSearchStoresParametersToMldev(fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listFileSearchStoresConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function listFileSearchStoresResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromFileSearchStores = getValueByPath(fromObject, [ + 'fileSearchStores', + ]); + if (fromFileSearchStores != null) { + let transformedList = fromFileSearchStores; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['fileSearchStores'], transformedList); + } + return toObject; +} +function uploadToFileSearchStoreConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (parentObject !== undefined && fromMimeType != null) { + setValueByPath(parentObject, ['mimeType'], fromMimeType); + } + const fromDisplayName = getValueByPath(fromObject, ['displayName']); + if (parentObject !== undefined && fromDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromDisplayName); + } + const fromCustomMetadata = getValueByPath(fromObject, [ + 'customMetadata', + ]); + if (parentObject !== undefined && fromCustomMetadata != null) { + let transformedList = fromCustomMetadata; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(parentObject, ['customMetadata'], transformedList); + } + const fromChunkingConfig = getValueByPath(fromObject, [ + 'chunkingConfig', + ]); + if (parentObject !== undefined && fromChunkingConfig != null) { + setValueByPath(parentObject, ['chunkingConfig'], fromChunkingConfig); + } + return toObject; +} +function uploadToFileSearchStoreParametersToMldev(fromObject) { + const toObject = {}; + const fromFileSearchStoreName = getValueByPath(fromObject, [ + 'fileSearchStoreName', + ]); + if (fromFileSearchStoreName != null) { + setValueByPath(toObject, ['_url', 'file_search_store_name'], fromFileSearchStoreName); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + uploadToFileSearchStoreConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function uploadToFileSearchStoreResumableResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const CONTENT_TYPE_HEADER = 'Content-Type'; +const SERVER_TIMEOUT_HEADER = 'X-Server-Timeout'; +const USER_AGENT_HEADER = 'User-Agent'; +const GOOGLE_API_CLIENT_HEADER = 'x-goog-api-client'; +const SDK_VERSION = '1.41.0'; // x-release-please-version +const LIBRARY_LABEL = `google-genai-sdk/${SDK_VERSION}`; +const VERTEX_AI_API_DEFAULT_VERSION = 'v1beta1'; +const GOOGLE_AI_API_DEFAULT_VERSION = 'v1beta'; +// Default retry options. +// The config is based on https://cloud.google.com/storage/docs/retry-strategy. +const DEFAULT_RETRY_ATTEMPTS = 5; // Including the initial call +// LINT.IfChange +const DEFAULT_RETRY_HTTP_STATUS_CODES = [ + 408, // Request timeout + 429, // Too many requests + 500, // Internal server error + 502, // Bad gateway + 503, // Service unavailable + 504, // Gateway timeout +]; +/** + * The ApiClient class is used to send requests to the Gemini API or Vertex AI + * endpoints. + */ +class ApiClient { + constructor(opts) { + var _a, _b, _c; + this.clientOptions = Object.assign({}, opts); + this.customBaseUrl = (_a = opts.httpOptions) === null || _a === void 0 ? void 0 : _a.baseUrl; + if (this.clientOptions.vertexai) { + if (this.clientOptions.project && this.clientOptions.location) { + this.clientOptions.apiKey = undefined; + } + else if (this.clientOptions.apiKey) { + this.clientOptions.project = undefined; + this.clientOptions.location = undefined; + } + } + const initHttpOptions = {}; + if (this.clientOptions.vertexai) { + if (!this.clientOptions.location && + !this.clientOptions.apiKey && + !this.customBaseUrl) { + this.clientOptions.location = 'global'; + } + const hasSufficientAuth = (this.clientOptions.project && this.clientOptions.location) || + this.clientOptions.apiKey; + if (!hasSufficientAuth && !this.customBaseUrl) { + throw new Error('Authentication is not set up. Please provide either a project and location, or an API key, or a custom base URL.'); + } + const hasConstructorAuth = (opts.project && opts.location) || !!opts.apiKey; + if (this.customBaseUrl && !hasConstructorAuth) { + initHttpOptions.baseUrl = this.customBaseUrl; + this.clientOptions.project = undefined; + this.clientOptions.location = undefined; + } + else if (this.clientOptions.apiKey || + this.clientOptions.location === 'global') { + // Vertex Express or global endpoint case. + initHttpOptions.baseUrl = 'https://aiplatform.googleapis.com/'; + } + else if (this.clientOptions.project && this.clientOptions.location) { + initHttpOptions.baseUrl = `https://${this.clientOptions.location}-aiplatform.googleapis.com/`; + } + initHttpOptions.apiVersion = + (_b = this.clientOptions.apiVersion) !== null && _b !== void 0 ? _b : VERTEX_AI_API_DEFAULT_VERSION; + } + else { + // Gemini API + if (!this.clientOptions.apiKey) { + throw new ApiError({ + message: 'API key must be set when using the Gemini API.', + status: 403, + }); + } + initHttpOptions.apiVersion = + (_c = this.clientOptions.apiVersion) !== null && _c !== void 0 ? _c : GOOGLE_AI_API_DEFAULT_VERSION; + initHttpOptions.baseUrl = `https://generativelanguage.googleapis.com/`; + } + initHttpOptions.headers = this.getDefaultHeaders(); + this.clientOptions.httpOptions = initHttpOptions; + if (opts.httpOptions) { + this.clientOptions.httpOptions = this.patchHttpOptions(initHttpOptions, opts.httpOptions); + } + } + isVertexAI() { + var _a; + return (_a = this.clientOptions.vertexai) !== null && _a !== void 0 ? _a : false; + } + getProject() { + return this.clientOptions.project; + } + getLocation() { + return this.clientOptions.location; + } + getCustomBaseUrl() { + return this.customBaseUrl; + } + async getAuthHeaders() { + const headers = new Headers(); + await this.clientOptions.auth.addAuthHeaders(headers); + return headers; + } + getApiVersion() { + if (this.clientOptions.httpOptions && + this.clientOptions.httpOptions.apiVersion !== undefined) { + return this.clientOptions.httpOptions.apiVersion; + } + throw new Error('API version is not set.'); + } + getBaseUrl() { + if (this.clientOptions.httpOptions && + this.clientOptions.httpOptions.baseUrl !== undefined) { + return this.clientOptions.httpOptions.baseUrl; + } + throw new Error('Base URL is not set.'); + } + getRequestUrl() { + return this.getRequestUrlInternal(this.clientOptions.httpOptions); + } + getHeaders() { + if (this.clientOptions.httpOptions && + this.clientOptions.httpOptions.headers !== undefined) { + return this.clientOptions.httpOptions.headers; + } + else { + throw new Error('Headers are not set.'); + } + } + getRequestUrlInternal(httpOptions) { + if (!httpOptions || + httpOptions.baseUrl === undefined || + httpOptions.apiVersion === undefined) { + throw new Error('HTTP options are not correctly set.'); + } + const baseUrl = httpOptions.baseUrl.endsWith('/') + ? httpOptions.baseUrl.slice(0, -1) + : httpOptions.baseUrl; + const urlElement = [baseUrl]; + if (httpOptions.apiVersion && httpOptions.apiVersion !== '') { + urlElement.push(httpOptions.apiVersion); + } + return urlElement.join('/'); + } + getBaseResourcePath() { + return `projects/${this.clientOptions.project}/locations/${this.clientOptions.location}`; + } + getApiKey() { + return this.clientOptions.apiKey; + } + getWebsocketBaseUrl() { + const baseUrl = this.getBaseUrl(); + const urlParts = new URL(baseUrl); + urlParts.protocol = urlParts.protocol == 'http:' ? 'ws' : 'wss'; + return urlParts.toString(); + } + setBaseUrl(url) { + if (this.clientOptions.httpOptions) { + this.clientOptions.httpOptions.baseUrl = url; + } + else { + throw new Error('HTTP options are not correctly set.'); + } + } + constructUrl(path, httpOptions, prependProjectLocation) { + const urlElement = [this.getRequestUrlInternal(httpOptions)]; + if (prependProjectLocation) { + urlElement.push(this.getBaseResourcePath()); + } + if (path !== '') { + urlElement.push(path); + } + const url = new URL(`${urlElement.join('/')}`); + return url; + } + shouldPrependVertexProjectPath(request, httpOptions) { + if (httpOptions.baseUrl && + httpOptions.baseUrlResourceScope === ResourceScope.COLLECTION) { + return false; + } + if (this.clientOptions.apiKey) { + return false; + } + if (!this.clientOptions.vertexai) { + return false; + } + if (request.path.startsWith('projects/')) { + // Assume the path already starts with + // `projects/<project>/location/<location>`. + return false; + } + if (request.httpMethod === 'GET' && + request.path.startsWith('publishers/google/models')) { + // These paths are used by Vertex's models.get and models.list + // calls. For base models Vertex does not accept a project/location + // prefix (for tuned model the prefix is required). + return false; + } + return true; + } + async request(request) { + let patchedHttpOptions = this.clientOptions.httpOptions; + if (request.httpOptions) { + patchedHttpOptions = this.patchHttpOptions(this.clientOptions.httpOptions, request.httpOptions); + } + const prependProjectLocation = this.shouldPrependVertexProjectPath(request, patchedHttpOptions); + const url = this.constructUrl(request.path, patchedHttpOptions, prependProjectLocation); + if (request.queryParams) { + for (const [key, value] of Object.entries(request.queryParams)) { + url.searchParams.append(key, String(value)); + } + } + let requestInit = {}; + if (request.httpMethod === 'GET') { + if (request.body && request.body !== '{}') { + throw new Error('Request body should be empty for GET request, but got non empty request body'); + } + } + else { + requestInit.body = request.body; + } + requestInit = await this.includeExtraHttpOptionsToRequestInit(requestInit, patchedHttpOptions, url.toString(), request.abortSignal); + return this.unaryApiCall(url, requestInit, request.httpMethod); + } + patchHttpOptions(baseHttpOptions, requestHttpOptions) { + const patchedHttpOptions = JSON.parse(JSON.stringify(baseHttpOptions)); + for (const [key, value] of Object.entries(requestHttpOptions)) { + // Records compile to objects. + if (typeof value === 'object') { + // @ts-expect-error TS2345TS7053: Element implicitly has an 'any' type + // because expression of type 'string' can't be used to index type + // 'HttpOptions'. + patchedHttpOptions[key] = Object.assign(Object.assign({}, patchedHttpOptions[key]), value); + } + else if (value !== undefined) { + // @ts-expect-error TS2345TS7053: Element implicitly has an 'any' type + // because expression of type 'string' can't be used to index type + // 'HttpOptions'. + patchedHttpOptions[key] = value; + } + } + return patchedHttpOptions; + } + async requestStream(request) { + let patchedHttpOptions = this.clientOptions.httpOptions; + if (request.httpOptions) { + patchedHttpOptions = this.patchHttpOptions(this.clientOptions.httpOptions, request.httpOptions); + } + const prependProjectLocation = this.shouldPrependVertexProjectPath(request, patchedHttpOptions); + const url = this.constructUrl(request.path, patchedHttpOptions, prependProjectLocation); + if (!url.searchParams.has('alt') || url.searchParams.get('alt') !== 'sse') { + url.searchParams.set('alt', 'sse'); + } + let requestInit = {}; + requestInit.body = request.body; + requestInit = await this.includeExtraHttpOptionsToRequestInit(requestInit, patchedHttpOptions, url.toString(), request.abortSignal); + return this.streamApiCall(url, requestInit, request.httpMethod); + } + async includeExtraHttpOptionsToRequestInit(requestInit, httpOptions, url, abortSignal) { + if ((httpOptions && httpOptions.timeout) || abortSignal) { + const abortController = new AbortController(); + const signal = abortController.signal; + if (httpOptions.timeout && (httpOptions === null || httpOptions === void 0 ? void 0 : httpOptions.timeout) > 0) { + const timeoutHandle = setTimeout(() => abortController.abort(), httpOptions.timeout); + if (timeoutHandle && + typeof timeoutHandle.unref === + 'function') { + // call unref to prevent nodejs process from hanging, see + // https://nodejs.org/api/timers.html#timeoutunref + timeoutHandle.unref(); + } + } + if (abortSignal) { + abortSignal.addEventListener('abort', () => { + abortController.abort(); + }); + } + requestInit.signal = signal; + } + if (httpOptions && httpOptions.extraBody !== null) { + includeExtraBodyToRequestInit(requestInit, httpOptions.extraBody); + } + requestInit.headers = await this.getHeadersInternal(httpOptions, url); + return requestInit; + } + async unaryApiCall(url, requestInit, httpMethod) { + return this.apiCall(url.toString(), Object.assign(Object.assign({}, requestInit), { method: httpMethod })) + .then(async (response) => { + await throwErrorIfNotOK(response); + return new HttpResponse(response); + }) + .catch((e) => { + if (e instanceof Error) { + throw e; + } + else { + throw new Error(JSON.stringify(e)); + } + }); + } + async streamApiCall(url, requestInit, httpMethod) { + return this.apiCall(url.toString(), Object.assign(Object.assign({}, requestInit), { method: httpMethod })) + .then(async (response) => { + await throwErrorIfNotOK(response); + return this.processStreamResponse(response); + }) + .catch((e) => { + if (e instanceof Error) { + throw e; + } + else { + throw new Error(JSON.stringify(e)); + } + }); + } + processStreamResponse(response) { + return __asyncGenerator(this, arguments, function* processStreamResponse_1() { + var _a; + const reader = (_a = response === null || response === void 0 ? void 0 : response.body) === null || _a === void 0 ? void 0 : _a.getReader(); + const decoder = new TextDecoder('utf-8'); + if (!reader) { + throw new Error('Response body is empty'); + } + try { + let buffer = ''; + const dataPrefix = 'data:'; + const delimiters = ['\n\n', '\r\r', '\r\n\r\n']; + while (true) { + const { done, value } = yield __await(reader.read()); + if (done) { + if (buffer.trim().length > 0) { + throw new Error('Incomplete JSON segment at the end'); + } + break; + } + const chunkString = decoder.decode(value, { stream: true }); + // Parse and throw an error if the chunk contains an error. + try { + const chunkJson = JSON.parse(chunkString); + if ('error' in chunkJson) { + const errorJson = JSON.parse(JSON.stringify(chunkJson['error'])); + const status = errorJson['status']; + const code = errorJson['code']; + const errorMessage = `got status: ${status}. ${JSON.stringify(chunkJson)}`; + if (code >= 400 && code < 600) { + const apiError = new ApiError({ + message: errorMessage, + status: code, + }); + throw apiError; + } + } + } + catch (e) { + const error = e; + if (error.name === 'ApiError') { + throw e; + } + } + buffer += chunkString; + let delimiterIndex = -1; + let delimiterLength = 0; + while (true) { + delimiterIndex = -1; + delimiterLength = 0; + for (const delimiter of delimiters) { + const index = buffer.indexOf(delimiter); + if (index !== -1 && + (delimiterIndex === -1 || index < delimiterIndex)) { + delimiterIndex = index; + delimiterLength = delimiter.length; + } + } + if (delimiterIndex === -1) { + break; // No complete event in buffer + } + const eventString = buffer.substring(0, delimiterIndex); + buffer = buffer.substring(delimiterIndex + delimiterLength); + const trimmedEvent = eventString.trim(); + if (trimmedEvent.startsWith(dataPrefix)) { + const processedChunkString = trimmedEvent + .substring(dataPrefix.length) + .trim(); + try { + const partialResponse = new Response(processedChunkString, { + headers: response === null || response === void 0 ? void 0 : response.headers, + status: response === null || response === void 0 ? void 0 : response.status, + statusText: response === null || response === void 0 ? void 0 : response.statusText, + }); + yield yield __await(new HttpResponse(partialResponse)); + } + catch (e) { + throw new Error(`exception parsing stream chunk ${processedChunkString}. ${e}`); + } + } + } + } + } + finally { + reader.releaseLock(); + } + }); + } + async apiCall(url, requestInit) { + var _a; + if (!this.clientOptions.httpOptions || + !this.clientOptions.httpOptions.retryOptions) { + return fetch(url, requestInit); + } + const retryOptions = this.clientOptions.httpOptions.retryOptions; + const runFetch = async () => { + const response = await fetch(url, requestInit); + if (response.ok) { + return response; + } + if (DEFAULT_RETRY_HTTP_STATUS_CODES.includes(response.status)) { + throw new Error(`Retryable HTTP Error: ${response.statusText}`); + } + throw new AbortError(`Non-retryable exception ${response.statusText} sending request`); + }; + return pRetry(runFetch, { + // Retry attempts is one less than the number of total attempts. + retries: ((_a = retryOptions.attempts) !== null && _a !== void 0 ? _a : DEFAULT_RETRY_ATTEMPTS) - 1, + }); + } + getDefaultHeaders() { + const headers = {}; + const versionHeaderValue = LIBRARY_LABEL + ' ' + this.clientOptions.userAgentExtra; + headers[USER_AGENT_HEADER] = versionHeaderValue; + headers[GOOGLE_API_CLIENT_HEADER] = versionHeaderValue; + headers[CONTENT_TYPE_HEADER] = 'application/json'; + return headers; + } + async getHeadersInternal(httpOptions, url) { + const headers = new Headers(); + if (httpOptions && httpOptions.headers) { + for (const [key, value] of Object.entries(httpOptions.headers)) { + headers.append(key, value); + } + // Append a timeout header if it is set, note that the timeout option is + // in milliseconds but the header is in seconds. + if (httpOptions.timeout && httpOptions.timeout > 0) { + headers.append(SERVER_TIMEOUT_HEADER, String(Math.ceil(httpOptions.timeout / 1000))); + } + } + await this.clientOptions.auth.addAuthHeaders(headers, url); + return headers; + } + getFileName(file) { + var _a; + let fileName = ''; + if (typeof file === 'string') { + fileName = file.replace(/[/\\]+$/, ''); + fileName = (_a = fileName.split(/[/\\]/).pop()) !== null && _a !== void 0 ? _a : ''; + } + return fileName; + } + /** + * Uploads a file asynchronously using Gemini API only, this is not supported + * in Vertex AI. + * + * @param file The string path to the file to be uploaded or a Blob object. + * @param config Optional parameters specified in the `UploadFileConfig` + * interface. @see {@link types.UploadFileConfig} + * @return A promise that resolves to a `File` object. + * @throws An error if called on a Vertex AI client. + * @throws An error if the `mimeType` is not provided and can not be inferred, + */ + async uploadFile(file, config) { + var _a; + const fileToUpload = {}; + if (config != null) { + fileToUpload.mimeType = config.mimeType; + fileToUpload.name = config.name; + fileToUpload.displayName = config.displayName; + } + if (fileToUpload.name && !fileToUpload.name.startsWith('files/')) { + fileToUpload.name = `files/${fileToUpload.name}`; + } + const uploader = this.clientOptions.uploader; + const fileStat = await uploader.stat(file); + fileToUpload.sizeBytes = String(fileStat.size); + const mimeType = (_a = config === null || config === void 0 ? void 0 : config.mimeType) !== null && _a !== void 0 ? _a : fileStat.type; + if (mimeType === undefined || mimeType === '') { + throw new Error('Can not determine mimeType. Please provide mimeType in the config.'); + } + fileToUpload.mimeType = mimeType; + const body = { + file: fileToUpload, + }; + const fileName = this.getFileName(file); + const path = formatMap('upload/v1beta/files', body['_url']); + const uploadUrl = await this.fetchUploadUrl(path, fileToUpload.sizeBytes, fileToUpload.mimeType, fileName, body, config === null || config === void 0 ? void 0 : config.httpOptions); + return uploader.upload(file, uploadUrl, this); + } + /** + * Uploads a file to a given file search store asynchronously using Gemini API only, this is not supported + * in Vertex AI. + * + * @param fileSearchStoreName The name of the file search store to upload the file to. + * @param file The string path to the file to be uploaded or a Blob object. + * @param config Optional parameters specified in the `UploadFileConfig` + * interface. @see {@link UploadFileConfig} + * @return A promise that resolves to a `File` object. + * @throws An error if called on a Vertex AI client. + * @throws An error if the `mimeType` is not provided and can not be inferred, + */ + async uploadFileToFileSearchStore(fileSearchStoreName, file, config) { + var _a; + const uploader = this.clientOptions.uploader; + const fileStat = await uploader.stat(file); + const sizeBytes = String(fileStat.size); + const mimeType = (_a = config === null || config === void 0 ? void 0 : config.mimeType) !== null && _a !== void 0 ? _a : fileStat.type; + if (mimeType === undefined || mimeType === '') { + throw new Error('Can not determine mimeType. Please provide mimeType in the config.'); + } + const path = `upload/v1beta/${fileSearchStoreName}:uploadToFileSearchStore`; + const fileName = this.getFileName(file); + const body = {}; + if (config != null) { + uploadToFileSearchStoreConfigToMldev(config, body); + } + const uploadUrl = await this.fetchUploadUrl(path, sizeBytes, mimeType, fileName, body, config === null || config === void 0 ? void 0 : config.httpOptions); + return uploader.uploadToFileSearchStore(file, uploadUrl, this); + } + /** + * Downloads a file asynchronously to the specified path. + * + * @params params - The parameters for the download request, see {@link + * types.DownloadFileParameters} + */ + async downloadFile(params) { + const downloader = this.clientOptions.downloader; + await downloader.download(params, this); + } + async fetchUploadUrl(path, sizeBytes, mimeType, fileName, body, configHttpOptions) { + var _a; + let httpOptions = {}; + if (configHttpOptions) { + httpOptions = configHttpOptions; + } + else { + httpOptions = { + apiVersion: '', // api-version is set in the path. + headers: Object.assign({ 'Content-Type': 'application/json', 'X-Goog-Upload-Protocol': 'resumable', 'X-Goog-Upload-Command': 'start', 'X-Goog-Upload-Header-Content-Length': `${sizeBytes}`, 'X-Goog-Upload-Header-Content-Type': `${mimeType}` }, (fileName ? { 'X-Goog-Upload-File-Name': fileName } : {})), + }; + } + const httpResponse = await this.request({ + path, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions, + }); + if (!httpResponse || !(httpResponse === null || httpResponse === void 0 ? void 0 : httpResponse.headers)) { + throw new Error('Server did not return an HttpResponse or the returned HttpResponse did not have headers.'); + } + const uploadUrl = (_a = httpResponse === null || httpResponse === void 0 ? void 0 : httpResponse.headers) === null || _a === void 0 ? void 0 : _a['x-goog-upload-url']; + if (uploadUrl === undefined) { + throw new Error('Failed to get upload url. Server did not return the x-google-upload-url in the headers'); + } + return uploadUrl; + } +} +async function throwErrorIfNotOK(response) { + var _a; + if (response === undefined) { + throw new Error('response is undefined'); + } + if (!response.ok) { + const status = response.status; + let errorBody; + if ((_a = response.headers.get('content-type')) === null || _a === void 0 ? void 0 : _a.includes('application/json')) { + errorBody = await response.json(); + } + else { + errorBody = { + error: { + message: await response.text(), + code: response.status, + status: response.statusText, + }, + }; + } + const errorMessage = JSON.stringify(errorBody); + if (status >= 400 && status < 600) { + const apiError = new ApiError({ + message: errorMessage, + status: status, + }); + throw apiError; + } + throw new Error(errorMessage); + } +} +/** + * Recursively updates the `requestInit.body` with values from an `extraBody` object. + * + * If `requestInit.body` is a string, it's assumed to be JSON and will be parsed. + * The `extraBody` is then deeply merged into this parsed object. + * If `requestInit.body` is a Blob, `extraBody` will be ignored, and a warning logged, + * as merging structured data into an opaque Blob is not supported. + * + * The function does not enforce that updated values from `extraBody` have the + * same type as existing values in `requestInit.body`. Type mismatches during + * the merge will result in a warning, but the value from `extraBody` will overwrite + * the original. `extraBody` users are responsible for ensuring `extraBody` has the correct structure. + * + * @param requestInit The RequestInit object whose body will be updated. + * @param extraBody The object containing updates to be merged into `requestInit.body`. + */ +function includeExtraBodyToRequestInit(requestInit, extraBody) { + if (!extraBody || Object.keys(extraBody).length === 0) { + return; + } + if (requestInit.body instanceof Blob) { + console.warn('includeExtraBodyToRequestInit: extraBody provided but current request body is a Blob. extraBody will be ignored as merging is not supported for Blob bodies.'); + return; + } + let currentBodyObject = {}; + // If adding new type to HttpRequest.body, please check the code below to + // see if we need to update the logic. + if (typeof requestInit.body === 'string' && requestInit.body.length > 0) { + try { + const parsedBody = JSON.parse(requestInit.body); + if (typeof parsedBody === 'object' && + parsedBody !== null && + !Array.isArray(parsedBody)) { + currentBodyObject = parsedBody; + } + else { + console.warn('includeExtraBodyToRequestInit: Original request body is valid JSON but not a non-array object. Skip applying extraBody to the request body.'); + return; + } + /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ + } + catch (e) { + console.warn('includeExtraBodyToRequestInit: Original request body is not valid JSON. Skip applying extraBody to the request body.'); + return; + } + } + function deepMerge(target, source) { + const output = Object.assign({}, target); + for (const key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + const sourceValue = source[key]; + const targetValue = output[key]; + if (sourceValue && + typeof sourceValue === 'object' && + !Array.isArray(sourceValue) && + targetValue && + typeof targetValue === 'object' && + !Array.isArray(targetValue)) { + output[key] = deepMerge(targetValue, sourceValue); + } + else { + if (targetValue && + sourceValue && + typeof targetValue !== typeof sourceValue) { + console.warn(`includeExtraBodyToRequestInit:deepMerge: Type mismatch for key "${key}". Original type: ${typeof targetValue}, New type: ${typeof sourceValue}. Overwriting.`); + } + output[key] = sourceValue; + } + } + } + return output; + } + const mergedBody = deepMerge(currentBodyObject, extraBody); + requestInit.body = JSON.stringify(mergedBody); +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// TODO: b/416041229 - Determine how to retrieve the MCP package version. +const MCP_LABEL = 'mcp_used/unknown'; +// Whether MCP tool usage is detected from mcpToTool. This is used for +// telemetry. +let hasMcpToolUsageFromMcpToTool = false; +// Checks whether the list of tools contains any MCP tools. +function hasMcpToolUsage(tools) { + for (const tool of tools) { + if (isMcpCallableTool(tool)) { + return true; + } + if (typeof tool === 'object' && 'inputSchema' in tool) { + return true; + } + } + return hasMcpToolUsageFromMcpToTool; +} +// Sets the MCP version label in the Google API client header. +function setMcpUsageHeader(headers) { + var _a; + const existingHeader = (_a = headers[GOOGLE_API_CLIENT_HEADER]) !== null && _a !== void 0 ? _a : ''; + headers[GOOGLE_API_CLIENT_HEADER] = (existingHeader + ` ${MCP_LABEL}`).trimStart(); +} +// Returns true if the object is a MCP CallableTool, otherwise false. +function isMcpCallableTool(object) { + return (object !== null && + typeof object === 'object' && + object instanceof McpCallableTool); +} +// List all tools from the MCP client. +function listAllTools(mcpClient_1) { + return __asyncGenerator(this, arguments, function* listAllTools_1(mcpClient, maxTools = 100) { + let cursor = undefined; + let numTools = 0; + while (numTools < maxTools) { + const t = yield __await(mcpClient.listTools({ cursor })); + for (const tool of t.tools) { + yield yield __await(tool); + numTools++; + } + if (!t.nextCursor) { + break; + } + cursor = t.nextCursor; + } + }); +} +/** + * McpCallableTool can be used for model inference and invoking MCP clients with + * given function call arguments. + * + * @experimental Built-in MCP support is an experimental feature, may change in future + * versions. + */ +class McpCallableTool { + constructor(mcpClients = [], config) { + this.mcpTools = []; + this.functionNameToMcpClient = {}; + this.mcpClients = mcpClients; + this.config = config; + } + /** + * Creates a McpCallableTool. + */ + static create(mcpClients, config) { + return new McpCallableTool(mcpClients, config); + } + /** + * Validates the function names are not duplicate and initialize the function + * name to MCP client mapping. + * + * @throws {Error} if the MCP tools from the MCP clients have duplicate tool + * names. + */ + async initialize() { + var _a, e_1, _b, _c; + if (this.mcpTools.length > 0) { + return; + } + const functionMap = {}; + const mcpTools = []; + for (const mcpClient of this.mcpClients) { + try { + for (var _d = true, _e = (e_1 = void 0, __asyncValues(listAllTools(mcpClient))), _f; _f = await _e.next(), _a = _f.done, !_a; _d = true) { + _c = _f.value; + _d = false; + const mcpTool = _c; + mcpTools.push(mcpTool); + const mcpToolName = mcpTool.name; + if (functionMap[mcpToolName]) { + throw new Error(`Duplicate function name ${mcpToolName} found in MCP tools. Please ensure function names are unique.`); + } + functionMap[mcpToolName] = mcpClient; + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (!_d && !_a && (_b = _e.return)) await _b.call(_e); + } + finally { if (e_1) throw e_1.error; } + } + } + this.mcpTools = mcpTools; + this.functionNameToMcpClient = functionMap; + } + async tool() { + await this.initialize(); + return mcpToolsToGeminiTool(this.mcpTools, this.config); + } + async callTool(functionCalls) { + await this.initialize(); + const functionCallResponseParts = []; + for (const functionCall of functionCalls) { + if (functionCall.name in this.functionNameToMcpClient) { + const mcpClient = this.functionNameToMcpClient[functionCall.name]; + let requestOptions = undefined; + // TODO: b/424238654 - Add support for finer grained timeout control. + if (this.config.timeout) { + requestOptions = { + timeout: this.config.timeout, + }; + } + const callToolResponse = await mcpClient.callTool({ + name: functionCall.name, + arguments: functionCall.args, + }, + // Set the result schema to undefined to allow MCP to rely on the + // default schema. + undefined, requestOptions); + functionCallResponseParts.push({ + functionResponse: { + name: functionCall.name, + response: callToolResponse.isError + ? { error: callToolResponse } + : callToolResponse, + }, + }); + } + } + return functionCallResponseParts; + } +} +function isMcpClient(client) { + return (client !== null && + typeof client === 'object' && + 'listTools' in client && + typeof client.listTools === 'function'); +} +/** + * Creates a McpCallableTool from MCP clients and an optional config. + * + * The callable tool can invoke the MCP clients with given function call + * arguments. (often for automatic function calling). + * Use the config to modify tool parameters such as behavior. + * + * @experimental Built-in MCP support is an experimental feature, may change in future + * versions. + */ +function mcpToTool(...args) { + // Set MCP usage for telemetry. + hasMcpToolUsageFromMcpToTool = true; + if (args.length === 0) { + throw new Error('No MCP clients provided'); + } + const maybeConfig = args[args.length - 1]; + if (isMcpClient(maybeConfig)) { + return McpCallableTool.create(args, {}); + } + return McpCallableTool.create(args.slice(0, args.length - 1), maybeConfig); +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Handles incoming messages from the WebSocket. + * + * @remarks + * This function is responsible for parsing incoming messages, transforming them + * into LiveMusicServerMessage, and then calling the onmessage callback. + * Note that the first message which is received from the server is a + * setupComplete message. + * + * @param apiClient The ApiClient instance. + * @param onmessage The user-provided onmessage callback (if any). + * @param event The MessageEvent from the WebSocket. + */ +async function handleWebSocketMessage$1(apiClient, onmessage, event) { + const serverMessage = new LiveMusicServerMessage(); + let data; + if (event.data instanceof Blob) { + data = JSON.parse(await event.data.text()); + } + else { + data = JSON.parse(event.data); + } + Object.assign(serverMessage, data); + onmessage(serverMessage); +} +/** + LiveMusic class encapsulates the configuration for live music + generation via Lyria Live models. + + @experimental + */ +class LiveMusic { + constructor(apiClient, auth, webSocketFactory) { + this.apiClient = apiClient; + this.auth = auth; + this.webSocketFactory = webSocketFactory; + } + /** + Establishes a connection to the specified model and returns a + LiveMusicSession object representing that connection. + + @experimental + + @remarks + + @param params - The parameters for establishing a connection to the model. + @return A live session. + + @example + ```ts + let model = 'models/lyria-realtime-exp'; + const session = await ai.live.music.connect({ + model: model, + callbacks: { + onmessage: (e: MessageEvent) => { + console.log('Received message from the server: %s\n', debug(e.data)); + }, + onerror: (e: ErrorEvent) => { + console.log('Error occurred: %s\n', debug(e.error)); + }, + onclose: (e: CloseEvent) => { + console.log('Connection closed.'); + }, + }, + }); + ``` + */ + async connect(params) { + var _a, _b; + if (this.apiClient.isVertexAI()) { + throw new Error('Live music is not supported for Vertex AI.'); + } + console.warn('Live music generation is experimental and may change in future versions.'); + const websocketBaseUrl = this.apiClient.getWebsocketBaseUrl(); + const apiVersion = this.apiClient.getApiVersion(); + const headers = mapToHeaders$1(this.apiClient.getDefaultHeaders()); + const apiKey = this.apiClient.getApiKey(); + const url = `${websocketBaseUrl}/ws/google.ai.generativelanguage.${apiVersion}.GenerativeService.BidiGenerateMusic?key=${apiKey}`; + let onopenResolve = () => { }; + const onopenPromise = new Promise((resolve) => { + onopenResolve = resolve; + }); + const callbacks = params.callbacks; + const onopenAwaitedCallback = function () { + onopenResolve({}); + }; + const apiClient = this.apiClient; + const websocketCallbacks = { + onopen: onopenAwaitedCallback, + onmessage: (event) => { + void handleWebSocketMessage$1(apiClient, callbacks.onmessage, event); + }, + onerror: (_a = callbacks === null || callbacks === void 0 ? void 0 : callbacks.onerror) !== null && _a !== void 0 ? _a : function (e) { + }, + onclose: (_b = callbacks === null || callbacks === void 0 ? void 0 : callbacks.onclose) !== null && _b !== void 0 ? _b : function (e) { + }, + }; + const conn = this.webSocketFactory.create(url, headersToMap$1(headers), websocketCallbacks); + conn.connect(); + // Wait for the websocket to open before sending requests. + await onopenPromise; + const model = tModel(this.apiClient, params.model); + const setup = { model }; + const clientMessage = { setup }; + conn.send(JSON.stringify(clientMessage)); + return new LiveMusicSession(conn, this.apiClient); + } +} +/** + Represents a connection to the API. + + @experimental + */ +class LiveMusicSession { + constructor(conn, apiClient) { + this.conn = conn; + this.apiClient = apiClient; + } + /** + Sets inputs to steer music generation. Updates the session's current + weighted prompts. + + @param params - Contains one property, `weightedPrompts`. + + - `weightedPrompts` to send to the model; weights are normalized to + sum to 1.0. + + @experimental + */ + async setWeightedPrompts(params) { + if (!params.weightedPrompts || + Object.keys(params.weightedPrompts).length === 0) { + throw new Error('Weighted prompts must be set and contain at least one entry.'); + } + const clientContent = liveMusicSetWeightedPromptsParametersToMldev(params); + this.conn.send(JSON.stringify({ clientContent })); + } + /** + Sets a configuration to the model. Updates the session's current + music generation config. + + @param params - Contains one property, `musicGenerationConfig`. + + - `musicGenerationConfig` to set in the model. Passing an empty or + undefined config to the model will reset the config to defaults. + + @experimental + */ + async setMusicGenerationConfig(params) { + if (!params.musicGenerationConfig) { + params.musicGenerationConfig = {}; + } + const setConfigParameters = liveMusicSetConfigParametersToMldev(params); + this.conn.send(JSON.stringify(setConfigParameters)); + } + sendPlaybackControl(playbackControl) { + const clientMessage = { playbackControl }; + this.conn.send(JSON.stringify(clientMessage)); + } + /** + * Start the music stream. + * + * @experimental + */ + play() { + this.sendPlaybackControl(LiveMusicPlaybackControl.PLAY); + } + /** + * Temporarily halt the music stream. Use `play` to resume from the current + * position. + * + * @experimental + */ + pause() { + this.sendPlaybackControl(LiveMusicPlaybackControl.PAUSE); + } + /** + * Stop the music stream and reset the state. Retains the current prompts + * and config. + * + * @experimental + */ + stop() { + this.sendPlaybackControl(LiveMusicPlaybackControl.STOP); + } + /** + * Resets the context of the music generation without stopping it. + * Retains the current prompts and config. + * + * @experimental + */ + resetContext() { + this.sendPlaybackControl(LiveMusicPlaybackControl.RESET_CONTEXT); + } + /** + Terminates the WebSocket connection. + + @experimental + */ + close() { + this.conn.close(); + } +} +// Converts an headers object to a "map" object as expected by the WebSocket +// constructor. We use this as the Auth interface works with Headers objects +// while the WebSocket constructor takes a map. +function headersToMap$1(headers) { + const headerMap = {}; + headers.forEach((value, key) => { + headerMap[key] = value; + }); + return headerMap; +} +// Converts a "map" object to a headers object. We use this as the Auth +// interface works with Headers objects while the API client default headers +// returns a map. +function mapToHeaders$1(map) { + const headers = new Headers(); + for (const [key, value] of Object.entries(map)) { + headers.append(key, value); + } + return headers; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const FUNCTION_RESPONSE_REQUIRES_ID = 'FunctionResponse request must have an `id` field from the response of a ToolCall.FunctionalCalls in Google AI.'; +/** + * Handles incoming messages from the WebSocket. + * + * @remarks + * This function is responsible for parsing incoming messages, transforming them + * into LiveServerMessages, and then calling the onmessage callback. Note that + * the first message which is received from the server is a setupComplete + * message. + * + * @param apiClient The ApiClient instance. + * @param onmessage The user-provided onmessage callback (if any). + * @param event The MessageEvent from the WebSocket. + */ +async function handleWebSocketMessage(apiClient, onmessage, event) { + const serverMessage = new LiveServerMessage(); + let jsonData; + if (event.data instanceof Blob) { + jsonData = await event.data.text(); + } + else if (event.data instanceof ArrayBuffer) { + jsonData = new TextDecoder().decode(event.data); + } + else { + jsonData = event.data; + } + const data = JSON.parse(jsonData); + if (apiClient.isVertexAI()) { + const resp = liveServerMessageFromVertex(data); + Object.assign(serverMessage, resp); + } + else { + const resp = data; + Object.assign(serverMessage, resp); + } + onmessage(serverMessage); +} +/** + Live class encapsulates the configuration for live interaction with the + Generative Language API. It embeds ApiClient for general API settings. + + @experimental + */ +class Live { + constructor(apiClient, auth, webSocketFactory) { + this.apiClient = apiClient; + this.auth = auth; + this.webSocketFactory = webSocketFactory; + this.music = new LiveMusic(this.apiClient, this.auth, this.webSocketFactory); + } + /** + Establishes a connection to the specified model with the given + configuration and returns a Session object representing that connection. + + @experimental Built-in MCP support is an experimental feature, may change in + future versions. + + @remarks + + @param params - The parameters for establishing a connection to the model. + @return A live session. + + @example + ```ts + let model: string; + if (GOOGLE_GENAI_USE_VERTEXAI) { + model = 'gemini-2.0-flash-live-preview-04-09'; + } else { + model = 'gemini-live-2.5-flash-preview'; + } + const session = await ai.live.connect({ + model: model, + config: { + responseModalities: [Modality.AUDIO], + }, + callbacks: { + onopen: () => { + console.log('Connected to the socket.'); + }, + onmessage: (e: MessageEvent) => { + console.log('Received message from the server: %s\n', debug(e.data)); + }, + onerror: (e: ErrorEvent) => { + console.log('Error occurred: %s\n', debug(e.error)); + }, + onclose: (e: CloseEvent) => { + console.log('Connection closed.'); + }, + }, + }); + ``` + */ + async connect(params) { + var _a, _b, _c, _d, _e, _f; + // TODO: b/404946746 - Support per request HTTP options. + if (params.config && params.config.httpOptions) { + throw new Error('The Live module does not support httpOptions at request-level in' + + ' LiveConnectConfig yet. Please use the client-level httpOptions' + + ' configuration instead.'); + } + const websocketBaseUrl = this.apiClient.getWebsocketBaseUrl(); + const apiVersion = this.apiClient.getApiVersion(); + let url; + const clientHeaders = this.apiClient.getHeaders(); + if (params.config && + params.config.tools && + hasMcpToolUsage(params.config.tools)) { + setMcpUsageHeader(clientHeaders); + } + const headers = mapToHeaders(clientHeaders); + if (this.apiClient.isVertexAI()) { + const project = this.apiClient.getProject(); + const location = this.apiClient.getLocation(); + const apiKey = this.apiClient.getApiKey(); + const hasStandardAuth = (!!project && !!location) || !!apiKey; + if (this.apiClient.getCustomBaseUrl() && !hasStandardAuth) { + // Custom base URL without standard auth (e.g., proxy). + url = websocketBaseUrl; + // Auth headers are assumed to be in `clientHeaders` from httpOptions. + } + else { + url = `${websocketBaseUrl}/ws/google.cloud.aiplatform.${apiVersion}.LlmBidiService/BidiGenerateContent`; + await this.auth.addAuthHeaders(headers, url); + } + } + else { + const apiKey = this.apiClient.getApiKey(); + let method = 'BidiGenerateContent'; + let keyName = 'key'; + if (apiKey === null || apiKey === void 0 ? void 0 : apiKey.startsWith('auth_tokens/')) { + console.warn('Warning: Ephemeral token support is experimental and may change in future versions.'); + if (apiVersion !== 'v1alpha') { + console.warn("Warning: The SDK's ephemeral token support is in v1alpha only. Please use const ai = new GoogleGenAI({apiKey: token.name, httpOptions: { apiVersion: 'v1alpha' }}); before session connection."); + } + method = 'BidiGenerateContentConstrained'; + keyName = 'access_token'; + } + url = `${websocketBaseUrl}/ws/google.ai.generativelanguage.${apiVersion}.GenerativeService.${method}?${keyName}=${apiKey}`; + } + let onopenResolve = () => { }; + const onopenPromise = new Promise((resolve) => { + onopenResolve = resolve; + }); + const callbacks = params.callbacks; + const onopenAwaitedCallback = function () { + var _a; + (_a = callbacks === null || callbacks === void 0 ? void 0 : callbacks.onopen) === null || _a === void 0 ? void 0 : _a.call(callbacks); + onopenResolve({}); + }; + const apiClient = this.apiClient; + const websocketCallbacks = { + onopen: onopenAwaitedCallback, + onmessage: (event) => { + void handleWebSocketMessage(apiClient, callbacks.onmessage, event); + }, + onerror: (_a = callbacks === null || callbacks === void 0 ? void 0 : callbacks.onerror) !== null && _a !== void 0 ? _a : function (e) { + }, + onclose: (_b = callbacks === null || callbacks === void 0 ? void 0 : callbacks.onclose) !== null && _b !== void 0 ? _b : function (e) { + }, + }; + const conn = this.webSocketFactory.create(url, headersToMap(headers), websocketCallbacks); + conn.connect(); + // Wait for the websocket to open before sending requests. + await onopenPromise; + let transformedModel = tModel(this.apiClient, params.model); + if (this.apiClient.isVertexAI() && + transformedModel.startsWith('publishers/')) { + const project = this.apiClient.getProject(); + const location = this.apiClient.getLocation(); + if (project && location) { + transformedModel = + `projects/${project}/locations/${location}/` + transformedModel; + } + } + let clientMessage = {}; + if (this.apiClient.isVertexAI() && + ((_c = params.config) === null || _c === void 0 ? void 0 : _c.responseModalities) === undefined) { + // Set default to AUDIO to align with MLDev API. + if (params.config === undefined) { + params.config = { responseModalities: [Modality.AUDIO] }; + } + else { + params.config.responseModalities = [Modality.AUDIO]; + } + } + if ((_d = params.config) === null || _d === void 0 ? void 0 : _d.generationConfig) { + // Raise deprecation warning for generationConfig. + console.warn('Setting `LiveConnectConfig.generation_config` is deprecated, please set the fields on `LiveConnectConfig` directly. This will become an error in a future version (not before Q3 2025).'); + } + const inputTools = (_f = (_e = params.config) === null || _e === void 0 ? void 0 : _e.tools) !== null && _f !== void 0 ? _f : []; + const convertedTools = []; + for (const tool of inputTools) { + if (this.isCallableTool(tool)) { + const callableTool = tool; + convertedTools.push(await callableTool.tool()); + } + else { + convertedTools.push(tool); + } + } + if (convertedTools.length > 0) { + params.config.tools = convertedTools; + } + const liveConnectParameters = { + model: transformedModel, + config: params.config, + callbacks: params.callbacks, + }; + if (this.apiClient.isVertexAI()) { + clientMessage = liveConnectParametersToVertex(this.apiClient, liveConnectParameters); + } + else { + clientMessage = liveConnectParametersToMldev(this.apiClient, liveConnectParameters); + } + delete clientMessage['config']; + conn.send(JSON.stringify(clientMessage)); + return new Session(conn, this.apiClient); + } + // TODO: b/416041229 - Abstract this method to a common place. + isCallableTool(tool) { + return 'callTool' in tool && typeof tool.callTool === 'function'; + } +} +const defaultLiveSendClientContentParamerters = { + turnComplete: true, +}; +/** + Represents a connection to the API. + + @experimental + */ +class Session { + constructor(conn, apiClient) { + this.conn = conn; + this.apiClient = apiClient; + } + tLiveClientContent(apiClient, params) { + if (params.turns !== null && params.turns !== undefined) { + let contents = []; + try { + contents = tContents(params.turns); + if (!apiClient.isVertexAI()) { + contents = contents.map((item) => contentToMldev$1(item)); + } + } + catch (_a) { + throw new Error(`Failed to parse client content "turns", type: '${typeof params.turns}'`); + } + return { + clientContent: { turns: contents, turnComplete: params.turnComplete }, + }; + } + return { + clientContent: { turnComplete: params.turnComplete }, + }; + } + tLiveClienttToolResponse(apiClient, params) { + let functionResponses = []; + if (params.functionResponses == null) { + throw new Error('functionResponses is required.'); + } + if (!Array.isArray(params.functionResponses)) { + functionResponses = [params.functionResponses]; + } + else { + functionResponses = params.functionResponses; + } + if (functionResponses.length === 0) { + throw new Error('functionResponses is required.'); + } + for (const functionResponse of functionResponses) { + if (typeof functionResponse !== 'object' || + functionResponse === null || + !('name' in functionResponse) || + !('response' in functionResponse)) { + throw new Error(`Could not parse function response, type '${typeof functionResponse}'.`); + } + if (!apiClient.isVertexAI() && !('id' in functionResponse)) { + throw new Error(FUNCTION_RESPONSE_REQUIRES_ID); + } + } + const clientMessage = { + toolResponse: { functionResponses: functionResponses }, + }; + return clientMessage; + } + /** + Send a message over the established connection. + + @param params - Contains two **optional** properties, `turns` and + `turnComplete`. + + - `turns` will be converted to a `Content[]` + - `turnComplete: true` [default] indicates that you are done sending + content and expect a response. If `turnComplete: false`, the server + will wait for additional messages before starting generation. + + @experimental + + @remarks + There are two ways to send messages to the live API: + `sendClientContent` and `sendRealtimeInput`. + + `sendClientContent` messages are added to the model context **in order**. + Having a conversation using `sendClientContent` messages is roughly + equivalent to using the `Chat.sendMessageStream`, except that the state of + the `chat` history is stored on the API server instead of locally. + + Because of `sendClientContent`'s order guarantee, the model cannot respons + as quickly to `sendClientContent` messages as to `sendRealtimeInput` + messages. This makes the biggest difference when sending objects that have + significant preprocessing time (typically images). + + The `sendClientContent` message sends a `Content[]` + which has more options than the `Blob` sent by `sendRealtimeInput`. + + So the main use-cases for `sendClientContent` over `sendRealtimeInput` are: + + - Sending anything that can't be represented as a `Blob` (text, + `sendClientContent({turns="Hello?"}`)). + - Managing turns when not using audio input and voice activity detection. + (`sendClientContent({turnComplete:true})` or the short form + `sendClientContent()`) + - Prefilling a conversation context + ``` + sendClientContent({ + turns: [ + Content({role:user, parts:...}), + Content({role:user, parts:...}), + ... + ] + }) + ``` + @experimental + */ + sendClientContent(params) { + params = Object.assign(Object.assign({}, defaultLiveSendClientContentParamerters), params); + const clientMessage = this.tLiveClientContent(this.apiClient, params); + this.conn.send(JSON.stringify(clientMessage)); + } + /** + Send a realtime message over the established connection. + + @param params - Contains one property, `media`. + + - `media` will be converted to a `Blob` + + @experimental + + @remarks + Use `sendRealtimeInput` for realtime audio chunks and video frames (images). + + With `sendRealtimeInput` the api will respond to audio automatically + based on voice activity detection (VAD). + + `sendRealtimeInput` is optimized for responsivness at the expense of + deterministic ordering guarantees. Audio and video tokens are to the + context when they become available. + + Note: The Call signature expects a `Blob` object, but only a subset + of audio and image mimetypes are allowed. + */ + sendRealtimeInput(params) { + let clientMessage = {}; + if (this.apiClient.isVertexAI()) { + clientMessage = { + 'realtimeInput': liveSendRealtimeInputParametersToVertex(params), + }; + } + else { + clientMessage = { + 'realtimeInput': liveSendRealtimeInputParametersToMldev(params), + }; + } + this.conn.send(JSON.stringify(clientMessage)); + } + /** + Send a function response message over the established connection. + + @param params - Contains property `functionResponses`. + + - `functionResponses` will be converted to a `functionResponses[]` + + @remarks + Use `sendFunctionResponse` to reply to `LiveServerToolCall` from the server. + + Use {@link types.LiveConnectConfig#tools} to configure the callable functions. + + @experimental + */ + sendToolResponse(params) { + if (params.functionResponses == null) { + throw new Error('Tool response parameters are required.'); + } + const clientMessage = this.tLiveClienttToolResponse(this.apiClient, params); + this.conn.send(JSON.stringify(clientMessage)); + } + /** + Terminates the WebSocket connection. + + @experimental + + @example + ```ts + let model: string; + if (GOOGLE_GENAI_USE_VERTEXAI) { + model = 'gemini-2.0-flash-live-preview-04-09'; + } else { + model = 'gemini-live-2.5-flash-preview'; + } + const session = await ai.live.connect({ + model: model, + config: { + responseModalities: [Modality.AUDIO], + } + }); + + session.close(); + ``` + */ + close() { + this.conn.close(); + } +} +// Converts an headers object to a "map" object as expected by the WebSocket +// constructor. We use this as the Auth interface works with Headers objects +// while the WebSocket constructor takes a map. +function headersToMap(headers) { + const headerMap = {}; + headers.forEach((value, key) => { + headerMap[key] = value; + }); + return headerMap; +} +// Converts a "map" object to a headers object. We use this as the Auth +// interface works with Headers objects while the API client default headers +// returns a map. +function mapToHeaders(map) { + const headers = new Headers(); + for (const [key, value] of Object.entries(map)) { + headers.append(key, value); + } + return headers; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const DEFAULT_MAX_REMOTE_CALLS = 10; +/** Returns whether automatic function calling is disabled. */ +function shouldDisableAfc(config) { + var _a, _b, _c; + if ((_a = config === null || config === void 0 ? void 0 : config.automaticFunctionCalling) === null || _a === void 0 ? void 0 : _a.disable) { + return true; + } + let callableToolsPresent = false; + for (const tool of (_b = config === null || config === void 0 ? void 0 : config.tools) !== null && _b !== void 0 ? _b : []) { + if (isCallableTool(tool)) { + callableToolsPresent = true; + break; + } + } + if (!callableToolsPresent) { + return true; + } + const maxCalls = (_c = config === null || config === void 0 ? void 0 : config.automaticFunctionCalling) === null || _c === void 0 ? void 0 : _c.maximumRemoteCalls; + if ((maxCalls && (maxCalls < 0 || !Number.isInteger(maxCalls))) || + maxCalls == 0) { + console.warn('Invalid maximumRemoteCalls value provided for automatic function calling. Disabled automatic function calling. Please provide a valid integer value greater than 0. maximumRemoteCalls provided:', maxCalls); + return true; + } + return false; +} +function isCallableTool(tool) { + return 'callTool' in tool && typeof tool.callTool === 'function'; +} +// Checks whether the list of tools contains any CallableTools. Will return true +// if there is at least one CallableTool. +function hasCallableTools(params) { + var _a, _b, _c; + return (_c = (_b = (_a = params.config) === null || _a === void 0 ? void 0 : _a.tools) === null || _b === void 0 ? void 0 : _b.some((tool) => isCallableTool(tool))) !== null && _c !== void 0 ? _c : false; +} +/** + * Returns the indexes of the tools that are not compatible with AFC. + */ +function findAfcIncompatibleToolIndexes(params) { + var _a; + // Use number[] for an array of numbers in TypeScript + const afcIncompatibleToolIndexes = []; + if (!((_a = params === null || params === void 0 ? void 0 : params.config) === null || _a === void 0 ? void 0 : _a.tools)) { + return afcIncompatibleToolIndexes; + } + params.config.tools.forEach((tool, index) => { + if (isCallableTool(tool)) { + return; + } + const geminiTool = tool; + if (geminiTool.functionDeclarations && + geminiTool.functionDeclarations.length > 0) { + afcIncompatibleToolIndexes.push(index); + } + }); + return afcIncompatibleToolIndexes; +} +/** + * Returns whether to append automatic function calling history to the + * response. + */ +function shouldAppendAfcHistory(config) { + var _a; + return !((_a = config === null || config === void 0 ? void 0 : config.automaticFunctionCalling) === null || _a === void 0 ? void 0 : _a.ignoreCallHistory); +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Models extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + /** + * Makes an API request to generate content with a given model. + * + * For the `model` parameter, supported formats for Vertex AI API include: + * - The Gemini model ID, for example: 'gemini-2.0-flash' + * - The full resource name starts with 'projects/', for example: + * 'projects/my-project-id/locations/us-central1/publishers/google/models/gemini-2.0-flash' + * - The partial resource name with 'publishers/', for example: + * 'publishers/google/models/gemini-2.0-flash' or + * 'publishers/meta/models/llama-3.1-405b-instruct-maas' + * - `/` separated publisher and model name, for example: + * 'google/gemini-2.0-flash' or 'meta/llama-3.1-405b-instruct-maas' + * + * For the `model` parameter, supported formats for Gemini API include: + * - The Gemini model ID, for example: 'gemini-2.0-flash' + * - The model name starts with 'models/', for example: + * 'models/gemini-2.0-flash' + * - For tuned models, the model name starts with 'tunedModels/', + * for example: + * 'tunedModels/1234567890123456789' + * + * Some models support multimodal input and output. + * + * @param params - The parameters for generating content. + * @return The response from generating content. + * + * @example + * ```ts + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: 'why is the sky blue?', + * config: { + * candidateCount: 2, + * } + * }); + * console.log(response); + * ``` + */ + this.generateContent = async (params) => { + var _a, _b, _c, _d, _e; + const transformedParams = await this.processParamsMaybeAddMcpUsage(params); + this.maybeMoveToResponseJsonSchem(params); + if (!hasCallableTools(params) || shouldDisableAfc(params.config)) { + return await this.generateContentInternal(transformedParams); + } + const incompatibleToolIndexes = findAfcIncompatibleToolIndexes(params); + if (incompatibleToolIndexes.length > 0) { + const formattedIndexes = incompatibleToolIndexes + .map((index) => `tools[${index}]`) + .join(', '); + throw new Error(`Automatic function calling with CallableTools (or MCP objects) and basic FunctionDeclarations is not yet supported. Incompatible tools found at ${formattedIndexes}.`); + } + let response; + let functionResponseContent; + const automaticFunctionCallingHistory = tContents(transformedParams.contents); + const maxRemoteCalls = (_c = (_b = (_a = transformedParams.config) === null || _a === void 0 ? void 0 : _a.automaticFunctionCalling) === null || _b === void 0 ? void 0 : _b.maximumRemoteCalls) !== null && _c !== void 0 ? _c : DEFAULT_MAX_REMOTE_CALLS; + let remoteCalls = 0; + while (remoteCalls < maxRemoteCalls) { + response = await this.generateContentInternal(transformedParams); + if (!response.functionCalls || response.functionCalls.length === 0) { + break; + } + const responseContent = response.candidates[0].content; + const functionResponseParts = []; + for (const tool of (_e = (_d = params.config) === null || _d === void 0 ? void 0 : _d.tools) !== null && _e !== void 0 ? _e : []) { + if (isCallableTool(tool)) { + const callableTool = tool; + const parts = await callableTool.callTool(response.functionCalls); + functionResponseParts.push(...parts); + } + } + remoteCalls++; + functionResponseContent = { + role: 'user', + parts: functionResponseParts, + }; + transformedParams.contents = tContents(transformedParams.contents); + transformedParams.contents.push(responseContent); + transformedParams.contents.push(functionResponseContent); + if (shouldAppendAfcHistory(transformedParams.config)) { + automaticFunctionCallingHistory.push(responseContent); + automaticFunctionCallingHistory.push(functionResponseContent); + } + } + if (shouldAppendAfcHistory(transformedParams.config)) { + response.automaticFunctionCallingHistory = + automaticFunctionCallingHistory; + } + return response; + }; + /** + * Makes an API request to generate content with a given model and yields the + * response in chunks. + * + * For the `model` parameter, supported formats for Vertex AI API include: + * - The Gemini model ID, for example: 'gemini-2.0-flash' + * - The full resource name starts with 'projects/', for example: + * 'projects/my-project-id/locations/us-central1/publishers/google/models/gemini-2.0-flash' + * - The partial resource name with 'publishers/', for example: + * 'publishers/google/models/gemini-2.0-flash' or + * 'publishers/meta/models/llama-3.1-405b-instruct-maas' + * - `/` separated publisher and model name, for example: + * 'google/gemini-2.0-flash' or 'meta/llama-3.1-405b-instruct-maas' + * + * For the `model` parameter, supported formats for Gemini API include: + * - The Gemini model ID, for example: 'gemini-2.0-flash' + * - The model name starts with 'models/', for example: + * 'models/gemini-2.0-flash' + * - For tuned models, the model name starts with 'tunedModels/', + * for example: + * 'tunedModels/1234567890123456789' + * + * Some models support multimodal input and output. + * + * @param params - The parameters for generating content with streaming response. + * @return The response from generating content. + * + * @example + * ```ts + * const response = await ai.models.generateContentStream({ + * model: 'gemini-2.0-flash', + * contents: 'why is the sky blue?', + * config: { + * maxOutputTokens: 200, + * } + * }); + * for await (const chunk of response) { + * console.log(chunk); + * } + * ``` + */ + this.generateContentStream = async (params) => { + var _a, _b, _c, _d, _e; + this.maybeMoveToResponseJsonSchem(params); + if (shouldDisableAfc(params.config)) { + const transformedParams = await this.processParamsMaybeAddMcpUsage(params); + return await this.generateContentStreamInternal(transformedParams); + } + const incompatibleToolIndexes = findAfcIncompatibleToolIndexes(params); + if (incompatibleToolIndexes.length > 0) { + const formattedIndexes = incompatibleToolIndexes + .map((index) => `tools[${index}]`) + .join(', '); + throw new Error(`Incompatible tools found at ${formattedIndexes}. Automatic function calling with CallableTools (or MCP objects) and basic FunctionDeclarations" is not yet supported.`); + } + // With tool compatibility confirmed, validate that the configuration are + // compatible with each other and raise an error if invalid. + const streamFunctionCall = (_c = (_b = (_a = params === null || params === void 0 ? void 0 : params.config) === null || _a === void 0 ? void 0 : _a.toolConfig) === null || _b === void 0 ? void 0 : _b.functionCallingConfig) === null || _c === void 0 ? void 0 : _c.streamFunctionCallArguments; + const disableAfc = (_e = (_d = params === null || params === void 0 ? void 0 : params.config) === null || _d === void 0 ? void 0 : _d.automaticFunctionCalling) === null || _e === void 0 ? void 0 : _e.disable; + if (streamFunctionCall && !disableAfc) { + throw new Error("Running in streaming mode with 'streamFunctionCallArguments' enabled, " + + 'this feature is not compatible with automatic function calling (AFC). ' + + "Please set 'config.automaticFunctionCalling.disable' to true to disable AFC " + + "or leave 'config.toolConfig.functionCallingConfig.streamFunctionCallArguments' " + + 'to be undefined or set to false to disable streaming function call arguments feature.'); + } + return await this.processAfcStream(params); + }; + /** + * Generates an image based on a text description and configuration. + * + * @param params - The parameters for generating images. + * @return The response from the API. + * + * @example + * ```ts + * const response = await client.models.generateImages({ + * model: 'imagen-4.0-generate-001', + * prompt: 'Robot holding a red skateboard', + * config: { + * numberOfImages: 1, + * includeRaiReason: true, + * }, + * }); + * console.log(response?.generatedImages?.[0]?.image?.imageBytes); + * ``` + */ + this.generateImages = async (params) => { + return await this.generateImagesInternal(params).then((apiResponse) => { + var _a; + let positivePromptSafetyAttributes; + const generatedImages = []; + if (apiResponse === null || apiResponse === void 0 ? void 0 : apiResponse.generatedImages) { + for (const generatedImage of apiResponse.generatedImages) { + if (generatedImage && + (generatedImage === null || generatedImage === void 0 ? void 0 : generatedImage.safetyAttributes) && + ((_a = generatedImage === null || generatedImage === void 0 ? void 0 : generatedImage.safetyAttributes) === null || _a === void 0 ? void 0 : _a.contentType) === 'Positive Prompt') { + positivePromptSafetyAttributes = generatedImage === null || generatedImage === void 0 ? void 0 : generatedImage.safetyAttributes; + } + else { + generatedImages.push(generatedImage); + } + } + } + let response; + if (positivePromptSafetyAttributes) { + response = { + generatedImages: generatedImages, + positivePromptSafetyAttributes: positivePromptSafetyAttributes, + sdkHttpResponse: apiResponse.sdkHttpResponse, + }; + } + else { + response = { + generatedImages: generatedImages, + sdkHttpResponse: apiResponse.sdkHttpResponse, + }; + } + return response; + }); + }; + this.list = async (params) => { + var _a; + const defaultConfig = { + queryBase: true, + }; + const actualConfig = Object.assign(Object.assign({}, defaultConfig), params === null || params === void 0 ? void 0 : params.config); + const actualParams = { + config: actualConfig, + }; + if (this.apiClient.isVertexAI()) { + if (!actualParams.config.queryBase) { + if ((_a = actualParams.config) === null || _a === void 0 ? void 0 : _a.filter) { + throw new Error('Filtering tuned models list for Vertex AI is not currently supported'); + } + else { + actualParams.config.filter = 'labels.tune-type:*'; + } + } + } + return new Pager(PagedItem.PAGED_ITEM_MODELS, (x) => this.listInternal(x), await this.listInternal(actualParams), actualParams); + }; + /** + * Edits an image based on a prompt, list of reference images, and configuration. + * + * @param params - The parameters for editing an image. + * @return The response from the API. + * + * @example + * ```ts + * const response = await client.models.editImage({ + * model: 'imagen-3.0-capability-001', + * prompt: 'Generate an image containing a mug with the product logo [1] visible on the side of the mug.', + * referenceImages: [subjectReferenceImage] + * config: { + * numberOfImages: 1, + * includeRaiReason: true, + * }, + * }); + * console.log(response?.generatedImages?.[0]?.image?.imageBytes); + * ``` + */ + this.editImage = async (params) => { + const paramsInternal = { + model: params.model, + prompt: params.prompt, + referenceImages: [], + config: params.config, + }; + if (params.referenceImages) { + if (params.referenceImages) { + paramsInternal.referenceImages = params.referenceImages.map((img) => img.toReferenceImageAPI()); + } + } + return await this.editImageInternal(paramsInternal); + }; + /** + * Upscales an image based on an image, upscale factor, and configuration. + * Only supported in Vertex AI currently. + * + * @param params - The parameters for upscaling an image. + * @return The response from the API. + * + * @example + * ```ts + * const response = await client.models.upscaleImage({ + * model: 'imagen-4.0-upscale-preview', + * image: image, + * upscaleFactor: 'x2', + * config: { + * includeRaiReason: true, + * }, + * }); + * console.log(response?.generatedImages?.[0]?.image?.imageBytes); + * ``` + */ + this.upscaleImage = async (params) => { + let apiConfig = { + numberOfImages: 1, + mode: 'upscale', + }; + if (params.config) { + apiConfig = Object.assign(Object.assign({}, apiConfig), params.config); + } + const apiParams = { + model: params.model, + image: params.image, + upscaleFactor: params.upscaleFactor, + config: apiConfig, + }; + return await this.upscaleImageInternal(apiParams); + }; + /** + * Generates videos based on a text description and configuration. + * + * @param params - The parameters for generating videos. + * @return A Promise<GenerateVideosOperation> which allows you to track the progress and eventually retrieve the generated videos using the operations.get method. + * + * @example + * ```ts + * const operation = await ai.models.generateVideos({ + * model: 'veo-2.0-generate-001', + * source: { + * prompt: 'A neon hologram of a cat driving at top speed', + * }, + * config: { + * numberOfVideos: 1 + * }); + * + * while (!operation.done) { + * await new Promise(resolve => setTimeout(resolve, 10000)); + * operation = await ai.operations.getVideosOperation({operation: operation}); + * } + * + * console.log(operation.response?.generatedVideos?.[0]?.video?.uri); + * ``` + */ + this.generateVideos = async (params) => { + var _a, _b, _c, _d, _e, _f; + if ((params.prompt || params.image || params.video) && params.source) { + throw new Error('Source and prompt/image/video are mutually exclusive. Please only use source.'); + } + // Gemini API does not support video bytes. + if (!this.apiClient.isVertexAI()) { + if (((_a = params.video) === null || _a === void 0 ? void 0 : _a.uri) && ((_b = params.video) === null || _b === void 0 ? void 0 : _b.videoBytes)) { + params.video = { + uri: params.video.uri, + mimeType: params.video.mimeType, + }; + } + else if (((_d = (_c = params.source) === null || _c === void 0 ? void 0 : _c.video) === null || _d === void 0 ? void 0 : _d.uri) && + ((_f = (_e = params.source) === null || _e === void 0 ? void 0 : _e.video) === null || _f === void 0 ? void 0 : _f.videoBytes)) { + params.source.video = { + uri: params.source.video.uri, + mimeType: params.source.video.mimeType, + }; + } + } + return await this.generateVideosInternal(params); + }; + } + /** + * This logic is needed for GenerateContentConfig only. + * Previously we made GenerateContentConfig.responseSchema field to accept + * unknown. Since v1.9.0, we switch to use backend JSON schema support. + * To maintain backward compatibility, we move the data that was treated as + * JSON schema from the responseSchema field to the responseJsonSchema field. + */ + maybeMoveToResponseJsonSchem(params) { + if (params.config && params.config.responseSchema) { + if (!params.config.responseJsonSchema) { + if (Object.keys(params.config.responseSchema).includes('$schema')) { + params.config.responseJsonSchema = params.config.responseSchema; + delete params.config.responseSchema; + } + } + } + return; + } + /** + * Transforms the CallableTools in the parameters to be simply Tools, it + * copies the params into a new object and replaces the tools, it does not + * modify the original params. Also sets the MCP usage header if there are + * MCP tools in the parameters. + */ + async processParamsMaybeAddMcpUsage(params) { + var _a, _b, _c; + const tools = (_a = params.config) === null || _a === void 0 ? void 0 : _a.tools; + if (!tools) { + return params; + } + const transformedTools = await Promise.all(tools.map(async (tool) => { + if (isCallableTool(tool)) { + const callableTool = tool; + return await callableTool.tool(); + } + return tool; + })); + const newParams = { + model: params.model, + contents: params.contents, + config: Object.assign(Object.assign({}, params.config), { tools: transformedTools }), + }; + newParams.config.tools = transformedTools; + if (params.config && + params.config.tools && + hasMcpToolUsage(params.config.tools)) { + const headers = (_c = (_b = params.config.httpOptions) === null || _b === void 0 ? void 0 : _b.headers) !== null && _c !== void 0 ? _c : {}; + let newHeaders = Object.assign({}, headers); + if (Object.keys(newHeaders).length === 0) { + newHeaders = this.apiClient.getDefaultHeaders(); + } + setMcpUsageHeader(newHeaders); + newParams.config.httpOptions = Object.assign(Object.assign({}, params.config.httpOptions), { headers: newHeaders }); + } + return newParams; + } + async initAfcToolsMap(params) { + var _a, _b, _c; + const afcTools = new Map(); + for (const tool of (_b = (_a = params.config) === null || _a === void 0 ? void 0 : _a.tools) !== null && _b !== void 0 ? _b : []) { + if (isCallableTool(tool)) { + const callableTool = tool; + const toolDeclaration = await callableTool.tool(); + for (const declaration of (_c = toolDeclaration.functionDeclarations) !== null && _c !== void 0 ? _c : []) { + if (!declaration.name) { + throw new Error('Function declaration name is required.'); + } + if (afcTools.has(declaration.name)) { + throw new Error(`Duplicate tool declaration name: ${declaration.name}`); + } + afcTools.set(declaration.name, callableTool); + } + } + } + return afcTools; + } + async processAfcStream(params) { + var _a, _b, _c; + const maxRemoteCalls = (_c = (_b = (_a = params.config) === null || _a === void 0 ? void 0 : _a.automaticFunctionCalling) === null || _b === void 0 ? void 0 : _b.maximumRemoteCalls) !== null && _c !== void 0 ? _c : DEFAULT_MAX_REMOTE_CALLS; + let wereFunctionsCalled = false; + let remoteCallCount = 0; + const afcToolsMap = await this.initAfcToolsMap(params); + return (function (models, afcTools, params) { + return __asyncGenerator(this, arguments, function* () { + var _a, e_1, _b, _c; + var _d, _e; + while (remoteCallCount < maxRemoteCalls) { + if (wereFunctionsCalled) { + remoteCallCount++; + wereFunctionsCalled = false; + } + const transformedParams = yield __await(models.processParamsMaybeAddMcpUsage(params)); + const response = yield __await(models.generateContentStreamInternal(transformedParams)); + const functionResponses = []; + const responseContents = []; + try { + for (var _f = true, response_1 = (e_1 = void 0, __asyncValues(response)), response_1_1; response_1_1 = yield __await(response_1.next()), _a = response_1_1.done, !_a; _f = true) { + _c = response_1_1.value; + _f = false; + const chunk = _c; + yield yield __await(chunk); + if (chunk.candidates && ((_d = chunk.candidates[0]) === null || _d === void 0 ? void 0 : _d.content)) { + responseContents.push(chunk.candidates[0].content); + for (const part of (_e = chunk.candidates[0].content.parts) !== null && _e !== void 0 ? _e : []) { + if (remoteCallCount < maxRemoteCalls && part.functionCall) { + if (!part.functionCall.name) { + throw new Error('Function call name was not returned by the model.'); + } + if (!afcTools.has(part.functionCall.name)) { + throw new Error(`Automatic function calling was requested, but not all the tools the model used implement the CallableTool interface. Available tools: ${afcTools.keys()}, mising tool: ${part.functionCall.name}`); + } + else { + const responseParts = yield __await(afcTools + .get(part.functionCall.name) + .callTool([part.functionCall])); + functionResponses.push(...responseParts); + } + } + } + } + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (!_f && !_a && (_b = response_1.return)) yield __await(_b.call(response_1)); + } + finally { if (e_1) throw e_1.error; } + } + if (functionResponses.length > 0) { + wereFunctionsCalled = true; + const typedResponseChunk = new GenerateContentResponse(); + typedResponseChunk.candidates = [ + { + content: { + role: 'user', + parts: functionResponses, + }, + }, + ]; + yield yield __await(typedResponseChunk); + const newContents = []; + newContents.push(...responseContents); + newContents.push({ + role: 'user', + parts: functionResponses, + }); + const updatedContents = tContents(params.contents).concat(newContents); + params.contents = updatedContents; + } + else { + break; + } + } + }); + })(this, afcToolsMap, params); + } + async generateContentInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = generateContentParametersToVertex(this.apiClient, params); + path = formatMap('{model}:generateContent', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = generateContentResponseFromVertex(apiResponse); + const typedResp = new GenerateContentResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = generateContentParametersToMldev(this.apiClient, params); + path = formatMap('{model}:generateContent', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = generateContentResponseFromMldev(apiResponse); + const typedResp = new GenerateContentResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + async generateContentStreamInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = generateContentParametersToVertex(this.apiClient, params); + path = formatMap('{model}:streamGenerateContent?alt=sse', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + const apiClient = this.apiClient; + response = apiClient.requestStream({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }); + return response.then(function (apiResponse) { + return __asyncGenerator(this, arguments, function* () { + var _a, e_2, _b, _c; + try { + for (var _d = true, apiResponse_1 = __asyncValues(apiResponse), apiResponse_1_1; apiResponse_1_1 = yield __await(apiResponse_1.next()), _a = apiResponse_1_1.done, !_a; _d = true) { + _c = apiResponse_1_1.value; + _d = false; + const chunk = _c; + const resp = generateContentResponseFromVertex((yield __await(chunk.json())), params); + resp['sdkHttpResponse'] = { + headers: chunk.headers, + }; + const typedResp = new GenerateContentResponse(); + Object.assign(typedResp, resp); + yield yield __await(typedResp); + } + } + catch (e_2_1) { e_2 = { error: e_2_1 }; } + finally { + try { + if (!_d && !_a && (_b = apiResponse_1.return)) yield __await(_b.call(apiResponse_1)); + } + finally { if (e_2) throw e_2.error; } + } + }); + }); + } + else { + const body = generateContentParametersToMldev(this.apiClient, params); + path = formatMap('{model}:streamGenerateContent?alt=sse', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + const apiClient = this.apiClient; + response = apiClient.requestStream({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }); + return response.then(function (apiResponse) { + return __asyncGenerator(this, arguments, function* () { + var _a, e_3, _b, _c; + try { + for (var _d = true, apiResponse_2 = __asyncValues(apiResponse), apiResponse_2_1; apiResponse_2_1 = yield __await(apiResponse_2.next()), _a = apiResponse_2_1.done, !_a; _d = true) { + _c = apiResponse_2_1.value; + _d = false; + const chunk = _c; + const resp = generateContentResponseFromMldev((yield __await(chunk.json())), params); + resp['sdkHttpResponse'] = { + headers: chunk.headers, + }; + const typedResp = new GenerateContentResponse(); + Object.assign(typedResp, resp); + yield yield __await(typedResp); + } + } + catch (e_3_1) { e_3 = { error: e_3_1 }; } + finally { + try { + if (!_d && !_a && (_b = apiResponse_2.return)) yield __await(_b.call(apiResponse_2)); + } + finally { if (e_3) throw e_3.error; } + } + }); + }); + } + } + /** + * Calculates embeddings for the given contents. Only text is supported. + * + * @param params - The parameters for embedding contents. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.embedContent({ + * model: 'text-embedding-004', + * contents: [ + * 'What is your name?', + * 'What is your favorite color?', + * ], + * config: { + * outputDimensionality: 64, + * }, + * }); + * console.log(response); + * ``` + */ + async embedContent(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = embedContentParametersToVertex(this.apiClient, params); + path = formatMap('{model}:predict', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = embedContentResponseFromVertex(apiResponse); + const typedResp = new EmbedContentResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = embedContentParametersToMldev(this.apiClient, params); + path = formatMap('{model}:batchEmbedContents', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = embedContentResponseFromMldev(apiResponse); + const typedResp = new EmbedContentResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Private method for generating images. + */ + async generateImagesInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = generateImagesParametersToVertex(this.apiClient, params); + path = formatMap('{model}:predict', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = generateImagesResponseFromVertex(apiResponse); + const typedResp = new GenerateImagesResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = generateImagesParametersToMldev(this.apiClient, params); + path = formatMap('{model}:predict', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = generateImagesResponseFromMldev(apiResponse); + const typedResp = new GenerateImagesResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Private method for editing an image. + */ + async editImageInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = editImageParametersInternalToVertex(this.apiClient, params); + path = formatMap('{model}:predict', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = editImageResponseFromVertex(apiResponse); + const typedResp = new EditImageResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + throw new Error('This method is only supported by the Vertex AI.'); + } + } + /** + * Private method for upscaling an image. + */ + async upscaleImageInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = upscaleImageAPIParametersInternalToVertex(this.apiClient, params); + path = formatMap('{model}:predict', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = upscaleImageResponseFromVertex(apiResponse); + const typedResp = new UpscaleImageResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + throw new Error('This method is only supported by the Vertex AI.'); + } + } + /** + * Recontextualizes an image. + * + * There are two types of recontextualization currently supported: + * 1) Imagen Product Recontext - Generate images of products in new scenes + * and contexts. + * 2) Virtual Try-On: Generate images of persons modeling fashion products. + * + * @param params - The parameters for recontextualizing an image. + * @return The response from the API. + * + * @example + * ```ts + * const response1 = await ai.models.recontextImage({ + * model: 'imagen-product-recontext-preview-06-30', + * source: { + * prompt: 'In a modern kitchen setting.', + * productImages: [productImage], + * }, + * config: { + * numberOfImages: 1, + * }, + * }); + * console.log(response1?.generatedImages?.[0]?.image?.imageBytes); + * + * const response2 = await ai.models.recontextImage({ + * model: 'virtual-try-on-001', + * source: { + * personImage: personImage, + * productImages: [productImage], + * }, + * config: { + * numberOfImages: 1, + * }, + * }); + * console.log(response2?.generatedImages?.[0]?.image?.imageBytes); + * ``` + */ + async recontextImage(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = recontextImageParametersToVertex(this.apiClient, params); + path = formatMap('{model}:predict', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = recontextImageResponseFromVertex(apiResponse); + const typedResp = new RecontextImageResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + throw new Error('This method is only supported by the Vertex AI.'); + } + } + /** + * Segments an image, creating a mask of a specified area. + * + * @param params - The parameters for segmenting an image. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.segmentImage({ + * model: 'image-segmentation-001', + * source: { + * image: image, + * }, + * config: { + * mode: 'foreground', + * }, + * }); + * console.log(response?.generatedMasks?.[0]?.mask?.imageBytes); + * ``` + */ + async segmentImage(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = segmentImageParametersToVertex(this.apiClient, params); + path = formatMap('{model}:predict', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = segmentImageResponseFromVertex(apiResponse); + const typedResp = new SegmentImageResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + throw new Error('This method is only supported by the Vertex AI.'); + } + } + /** + * Fetches information about a model by name. + * + * @example + * ```ts + * const modelInfo = await ai.models.get({model: 'gemini-2.0-flash'}); + * ``` + */ + async get(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = getModelParametersToVertex(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = modelFromVertex(apiResponse); + return resp; + }); + } + else { + const body = getModelParametersToMldev(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = modelFromMldev(apiResponse); + return resp; + }); + } + } + async listInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = listModelsParametersToVertex(this.apiClient, params); + path = formatMap('{models_url}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listModelsResponseFromVertex(apiResponse); + const typedResp = new ListModelsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = listModelsParametersToMldev(this.apiClient, params); + path = formatMap('{models_url}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listModelsResponseFromMldev(apiResponse); + const typedResp = new ListModelsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Updates a tuned model by its name. + * + * @param params - The parameters for updating the model. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.update({ + * model: 'tuned-model-name', + * config: { + * displayName: 'New display name', + * description: 'New description', + * }, + * }); + * ``` + */ + async update(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = updateModelParametersToVertex(this.apiClient, params); + path = formatMap('{model}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'PATCH', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = modelFromVertex(apiResponse); + return resp; + }); + } + else { + const body = updateModelParametersToMldev(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'PATCH', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = modelFromMldev(apiResponse); + return resp; + }); + } + } + /** + * Deletes a tuned model by its name. + * + * @param params - The parameters for deleting the model. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.delete({model: 'tuned-model-name'}); + * ``` + */ + async delete(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = deleteModelParametersToVertex(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = deleteModelResponseFromVertex(apiResponse); + const typedResp = new DeleteModelResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = deleteModelParametersToMldev(this.apiClient, params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = deleteModelResponseFromMldev(apiResponse); + const typedResp = new DeleteModelResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Counts the number of tokens in the given contents. Multimodal input is + * supported for Gemini models. + * + * @param params - The parameters for counting tokens. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.countTokens({ + * model: 'gemini-2.0-flash', + * contents: 'The quick brown fox jumps over the lazy dog.' + * }); + * console.log(response); + * ``` + */ + async countTokens(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = countTokensParametersToVertex(this.apiClient, params); + path = formatMap('{model}:countTokens', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = countTokensResponseFromVertex(apiResponse); + const typedResp = new CountTokensResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = countTokensParametersToMldev(this.apiClient, params); + path = formatMap('{model}:countTokens', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = countTokensResponseFromMldev(apiResponse); + const typedResp = new CountTokensResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Given a list of contents, returns a corresponding TokensInfo containing + * the list of tokens and list of token ids. + * + * This method is not supported by the Gemini Developer API. + * + * @param params - The parameters for computing tokens. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.computeTokens({ + * model: 'gemini-2.0-flash', + * contents: 'What is your name?' + * }); + * console.log(response); + * ``` + */ + async computeTokens(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = computeTokensParametersToVertex(this.apiClient, params); + path = formatMap('{model}:computeTokens', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = computeTokensResponseFromVertex(apiResponse); + const typedResp = new ComputeTokensResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + throw new Error('This method is only supported by the Vertex AI.'); + } + } + /** + * Private method for generating videos. + */ + async generateVideosInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = generateVideosParametersToVertex(this.apiClient, params); + path = formatMap('{model}:predictLongRunning', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = generateVideosOperationFromVertex(apiResponse); + const typedResp = new GenerateVideosOperation(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = generateVideosParametersToMldev(this.apiClient, params); + path = formatMap('{model}:predictLongRunning', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = generateVideosOperationFromMldev(apiResponse); + const typedResp = new GenerateVideosOperation(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Operations extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + } + /** + * Gets the status of a long-running operation. + * + * @param parameters The parameters for the get operation request. + * @return The updated Operation object, with the latest status or result. + */ + async getVideosOperation(parameters) { + const operation = parameters.operation; + const config = parameters.config; + if (operation.name === undefined || operation.name === '') { + throw new Error('Operation name is required.'); + } + if (this.apiClient.isVertexAI()) { + const resourceName = operation.name.split('/operations/')[0]; + let httpOptions = undefined; + if (config && 'httpOptions' in config) { + httpOptions = config.httpOptions; + } + const rawOperation = await this.fetchPredictVideosOperationInternal({ + operationName: operation.name, + resourceName: resourceName, + config: { httpOptions: httpOptions }, + }); + return operation._fromAPIResponse({ + apiResponse: rawOperation, + _isVertexAI: true, + }); + } + else { + const rawOperation = await this.getVideosOperationInternal({ + operationName: operation.name, + config: config, + }); + return operation._fromAPIResponse({ + apiResponse: rawOperation, + _isVertexAI: false, + }); + } + } + /** + * Gets the status of a long-running operation. + * + * @param parameters The parameters for the get operation request. + * @return The updated Operation object, with the latest status or result. + */ + async get(parameters) { + const operation = parameters.operation; + const config = parameters.config; + if (operation.name === undefined || operation.name === '') { + throw new Error('Operation name is required.'); + } + if (this.apiClient.isVertexAI()) { + const resourceName = operation.name.split('/operations/')[0]; + let httpOptions = undefined; + if (config && 'httpOptions' in config) { + httpOptions = config.httpOptions; + } + const rawOperation = await this.fetchPredictVideosOperationInternal({ + operationName: operation.name, + resourceName: resourceName, + config: { httpOptions: httpOptions }, + }); + return operation._fromAPIResponse({ + apiResponse: rawOperation, + _isVertexAI: true, + }); + } + else { + const rawOperation = await this.getVideosOperationInternal({ + operationName: operation.name, + config: config, + }); + return operation._fromAPIResponse({ + apiResponse: rawOperation, + _isVertexAI: false, + }); + } + } + async getVideosOperationInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = getOperationParametersToVertex(params); + path = formatMap('{operationName}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response; + } + else { + const body = getOperationParametersToMldev(params); + path = formatMap('{operationName}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response; + } + } + async fetchPredictVideosOperationInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = fetchPredictOperationParametersToVertex(params); + path = formatMap('{resourceName}:fetchPredictOperation', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response; + } + else { + throw new Error('This method is only supported by the Vertex AI.'); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function blobToMldev(fromObject) { + const toObject = {}; + const fromData = getValueByPath(fromObject, ['data']); + if (fromData != null) { + setValueByPath(toObject, ['data'], fromData); + } + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function contentToMldev(fromObject) { + const toObject = {}; + const fromParts = getValueByPath(fromObject, ['parts']); + if (fromParts != null) { + let transformedList = fromParts; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return partToMldev(item); + }); + } + setValueByPath(toObject, ['parts'], transformedList); + } + const fromRole = getValueByPath(fromObject, ['role']); + if (fromRole != null) { + setValueByPath(toObject, ['role'], fromRole); + } + return toObject; +} +function createAuthTokenConfigToMldev(apiClient, fromObject, parentObject) { + const toObject = {}; + const fromExpireTime = getValueByPath(fromObject, ['expireTime']); + if (parentObject !== undefined && fromExpireTime != null) { + setValueByPath(parentObject, ['expireTime'], fromExpireTime); + } + const fromNewSessionExpireTime = getValueByPath(fromObject, [ + 'newSessionExpireTime', + ]); + if (parentObject !== undefined && fromNewSessionExpireTime != null) { + setValueByPath(parentObject, ['newSessionExpireTime'], fromNewSessionExpireTime); + } + const fromUses = getValueByPath(fromObject, ['uses']); + if (parentObject !== undefined && fromUses != null) { + setValueByPath(parentObject, ['uses'], fromUses); + } + const fromLiveConnectConstraints = getValueByPath(fromObject, [ + 'liveConnectConstraints', + ]); + if (parentObject !== undefined && fromLiveConnectConstraints != null) { + setValueByPath(parentObject, ['bidiGenerateContentSetup'], liveConnectConstraintsToMldev(apiClient, fromLiveConnectConstraints)); + } + const fromLockAdditionalFields = getValueByPath(fromObject, [ + 'lockAdditionalFields', + ]); + if (parentObject !== undefined && fromLockAdditionalFields != null) { + setValueByPath(parentObject, ['fieldMask'], fromLockAdditionalFields); + } + return toObject; +} +function createAuthTokenParametersToMldev(apiClient, fromObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['config'], createAuthTokenConfigToMldev(apiClient, fromConfig, toObject)); + } + return toObject; +} +function fileDataToMldev(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['displayName']) !== undefined) { + throw new Error('displayName parameter is not supported in Gemini API.'); + } + const fromFileUri = getValueByPath(fromObject, ['fileUri']); + if (fromFileUri != null) { + setValueByPath(toObject, ['fileUri'], fromFileUri); + } + const fromMimeType = getValueByPath(fromObject, ['mimeType']); + if (fromMimeType != null) { + setValueByPath(toObject, ['mimeType'], fromMimeType); + } + return toObject; +} +function functionCallToMldev(fromObject) { + const toObject = {}; + const fromId = getValueByPath(fromObject, ['id']); + if (fromId != null) { + setValueByPath(toObject, ['id'], fromId); + } + const fromArgs = getValueByPath(fromObject, ['args']); + if (fromArgs != null) { + setValueByPath(toObject, ['args'], fromArgs); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + if (getValueByPath(fromObject, ['partialArgs']) !== undefined) { + throw new Error('partialArgs parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['willContinue']) !== undefined) { + throw new Error('willContinue parameter is not supported in Gemini API.'); + } + return toObject; +} +function googleMapsToMldev(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['authConfig']) !== undefined) { + throw new Error('authConfig parameter is not supported in Gemini API.'); + } + const fromEnableWidget = getValueByPath(fromObject, ['enableWidget']); + if (fromEnableWidget != null) { + setValueByPath(toObject, ['enableWidget'], fromEnableWidget); + } + return toObject; +} +function googleSearchToMldev(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['excludeDomains']) !== undefined) { + throw new Error('excludeDomains parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['blockingConfidence']) !== undefined) { + throw new Error('blockingConfidence parameter is not supported in Gemini API.'); + } + const fromTimeRangeFilter = getValueByPath(fromObject, [ + 'timeRangeFilter', + ]); + if (fromTimeRangeFilter != null) { + setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter); + } + return toObject; +} +function liveConnectConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromGenerationConfig = getValueByPath(fromObject, [ + 'generationConfig', + ]); + if (parentObject !== undefined && fromGenerationConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig'], fromGenerationConfig); + } + const fromResponseModalities = getValueByPath(fromObject, [ + 'responseModalities', + ]); + if (parentObject !== undefined && fromResponseModalities != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'responseModalities'], fromResponseModalities); + } + const fromTemperature = getValueByPath(fromObject, ['temperature']); + if (parentObject !== undefined && fromTemperature != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'temperature'], fromTemperature); + } + const fromTopP = getValueByPath(fromObject, ['topP']); + if (parentObject !== undefined && fromTopP != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'topP'], fromTopP); + } + const fromTopK = getValueByPath(fromObject, ['topK']); + if (parentObject !== undefined && fromTopK != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'topK'], fromTopK); + } + const fromMaxOutputTokens = getValueByPath(fromObject, [ + 'maxOutputTokens', + ]); + if (parentObject !== undefined && fromMaxOutputTokens != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'maxOutputTokens'], fromMaxOutputTokens); + } + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (parentObject !== undefined && fromMediaResolution != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'mediaResolution'], fromMediaResolution); + } + const fromSeed = getValueByPath(fromObject, ['seed']); + if (parentObject !== undefined && fromSeed != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'seed'], fromSeed); + } + const fromSpeechConfig = getValueByPath(fromObject, ['speechConfig']); + if (parentObject !== undefined && fromSpeechConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'speechConfig'], tLiveSpeechConfig(fromSpeechConfig)); + } + const fromThinkingConfig = getValueByPath(fromObject, [ + 'thinkingConfig', + ]); + if (parentObject !== undefined && fromThinkingConfig != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'thinkingConfig'], fromThinkingConfig); + } + const fromEnableAffectiveDialog = getValueByPath(fromObject, [ + 'enableAffectiveDialog', + ]); + if (parentObject !== undefined && fromEnableAffectiveDialog != null) { + setValueByPath(parentObject, ['setup', 'generationConfig', 'enableAffectiveDialog'], fromEnableAffectiveDialog); + } + const fromSystemInstruction = getValueByPath(fromObject, [ + 'systemInstruction', + ]); + if (parentObject !== undefined && fromSystemInstruction != null) { + setValueByPath(parentObject, ['setup', 'systemInstruction'], contentToMldev(tContent(fromSystemInstruction))); + } + const fromTools = getValueByPath(fromObject, ['tools']); + if (parentObject !== undefined && fromTools != null) { + let transformedList = tTools(fromTools); + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return toolToMldev(tTool(item)); + }); + } + setValueByPath(parentObject, ['setup', 'tools'], transformedList); + } + const fromSessionResumption = getValueByPath(fromObject, [ + 'sessionResumption', + ]); + if (parentObject !== undefined && fromSessionResumption != null) { + setValueByPath(parentObject, ['setup', 'sessionResumption'], sessionResumptionConfigToMldev(fromSessionResumption)); + } + const fromInputAudioTranscription = getValueByPath(fromObject, [ + 'inputAudioTranscription', + ]); + if (parentObject !== undefined && fromInputAudioTranscription != null) { + setValueByPath(parentObject, ['setup', 'inputAudioTranscription'], fromInputAudioTranscription); + } + const fromOutputAudioTranscription = getValueByPath(fromObject, [ + 'outputAudioTranscription', + ]); + if (parentObject !== undefined && fromOutputAudioTranscription != null) { + setValueByPath(parentObject, ['setup', 'outputAudioTranscription'], fromOutputAudioTranscription); + } + const fromRealtimeInputConfig = getValueByPath(fromObject, [ + 'realtimeInputConfig', + ]); + if (parentObject !== undefined && fromRealtimeInputConfig != null) { + setValueByPath(parentObject, ['setup', 'realtimeInputConfig'], fromRealtimeInputConfig); + } + const fromContextWindowCompression = getValueByPath(fromObject, [ + 'contextWindowCompression', + ]); + if (parentObject !== undefined && fromContextWindowCompression != null) { + setValueByPath(parentObject, ['setup', 'contextWindowCompression'], fromContextWindowCompression); + } + const fromProactivity = getValueByPath(fromObject, ['proactivity']); + if (parentObject !== undefined && fromProactivity != null) { + setValueByPath(parentObject, ['setup', 'proactivity'], fromProactivity); + } + if (getValueByPath(fromObject, ['explicitVadSignal']) !== undefined) { + throw new Error('explicitVadSignal parameter is not supported in Gemini API.'); + } + return toObject; +} +function liveConnectConstraintsToMldev(apiClient, fromObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['model']); + if (fromModel != null) { + setValueByPath(toObject, ['setup', 'model'], tModel(apiClient, fromModel)); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + setValueByPath(toObject, ['config'], liveConnectConfigToMldev(fromConfig, toObject)); + } + return toObject; +} +function partToMldev(fromObject) { + const toObject = {}; + const fromMediaResolution = getValueByPath(fromObject, [ + 'mediaResolution', + ]); + if (fromMediaResolution != null) { + setValueByPath(toObject, ['mediaResolution'], fromMediaResolution); + } + const fromCodeExecutionResult = getValueByPath(fromObject, [ + 'codeExecutionResult', + ]); + if (fromCodeExecutionResult != null) { + setValueByPath(toObject, ['codeExecutionResult'], fromCodeExecutionResult); + } + const fromExecutableCode = getValueByPath(fromObject, [ + 'executableCode', + ]); + if (fromExecutableCode != null) { + setValueByPath(toObject, ['executableCode'], fromExecutableCode); + } + const fromFileData = getValueByPath(fromObject, ['fileData']); + if (fromFileData != null) { + setValueByPath(toObject, ['fileData'], fileDataToMldev(fromFileData)); + } + const fromFunctionCall = getValueByPath(fromObject, ['functionCall']); + if (fromFunctionCall != null) { + setValueByPath(toObject, ['functionCall'], functionCallToMldev(fromFunctionCall)); + } + const fromFunctionResponse = getValueByPath(fromObject, [ + 'functionResponse', + ]); + if (fromFunctionResponse != null) { + setValueByPath(toObject, ['functionResponse'], fromFunctionResponse); + } + const fromInlineData = getValueByPath(fromObject, ['inlineData']); + if (fromInlineData != null) { + setValueByPath(toObject, ['inlineData'], blobToMldev(fromInlineData)); + } + const fromText = getValueByPath(fromObject, ['text']); + if (fromText != null) { + setValueByPath(toObject, ['text'], fromText); + } + const fromThought = getValueByPath(fromObject, ['thought']); + if (fromThought != null) { + setValueByPath(toObject, ['thought'], fromThought); + } + const fromThoughtSignature = getValueByPath(fromObject, [ + 'thoughtSignature', + ]); + if (fromThoughtSignature != null) { + setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature); + } + const fromVideoMetadata = getValueByPath(fromObject, [ + 'videoMetadata', + ]); + if (fromVideoMetadata != null) { + setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata); + } + return toObject; +} +function sessionResumptionConfigToMldev(fromObject) { + const toObject = {}; + const fromHandle = getValueByPath(fromObject, ['handle']); + if (fromHandle != null) { + setValueByPath(toObject, ['handle'], fromHandle); + } + if (getValueByPath(fromObject, ['transparent']) !== undefined) { + throw new Error('transparent parameter is not supported in Gemini API.'); + } + return toObject; +} +function toolToMldev(fromObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['retrieval']) !== undefined) { + throw new Error('retrieval parameter is not supported in Gemini API.'); + } + const fromComputerUse = getValueByPath(fromObject, ['computerUse']); + if (fromComputerUse != null) { + setValueByPath(toObject, ['computerUse'], fromComputerUse); + } + const fromFileSearch = getValueByPath(fromObject, ['fileSearch']); + if (fromFileSearch != null) { + setValueByPath(toObject, ['fileSearch'], fromFileSearch); + } + const fromCodeExecution = getValueByPath(fromObject, [ + 'codeExecution', + ]); + if (fromCodeExecution != null) { + setValueByPath(toObject, ['codeExecution'], fromCodeExecution); + } + if (getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined) { + throw new Error('enterpriseWebSearch parameter is not supported in Gemini API.'); + } + const fromFunctionDeclarations = getValueByPath(fromObject, [ + 'functionDeclarations', + ]); + if (fromFunctionDeclarations != null) { + let transformedList = fromFunctionDeclarations; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['functionDeclarations'], transformedList); + } + const fromGoogleMaps = getValueByPath(fromObject, ['googleMaps']); + if (fromGoogleMaps != null) { + setValueByPath(toObject, ['googleMaps'], googleMapsToMldev(fromGoogleMaps)); + } + const fromGoogleSearch = getValueByPath(fromObject, ['googleSearch']); + if (fromGoogleSearch != null) { + setValueByPath(toObject, ['googleSearch'], googleSearchToMldev(fromGoogleSearch)); + } + const fromGoogleSearchRetrieval = getValueByPath(fromObject, [ + 'googleSearchRetrieval', + ]); + if (fromGoogleSearchRetrieval != null) { + setValueByPath(toObject, ['googleSearchRetrieval'], fromGoogleSearchRetrieval); + } + const fromUrlContext = getValueByPath(fromObject, ['urlContext']); + if (fromUrlContext != null) { + setValueByPath(toObject, ['urlContext'], fromUrlContext); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Returns a comma-separated list of field masks from a given object. + * + * @param setup The object to extract field masks from. + * @return A comma-separated list of field masks. + */ +function getFieldMasks(setup) { + const fields = []; + for (const key in setup) { + if (Object.prototype.hasOwnProperty.call(setup, key)) { + const value = setup[key]; + // 2nd layer, recursively get field masks see TODO(b/418290100) + if (typeof value === 'object' && + value != null && + Object.keys(value).length > 0) { + const field = Object.keys(value).map((kk) => `${key}.${kk}`); + fields.push(...field); + } + else { + fields.push(key); // 1st layer + } + } + } + return fields.join(','); +} +/** + * Converts bidiGenerateContentSetup. + * @param requestDict - The request dictionary. + * @param config - The configuration object. + * @return - The modified request dictionary. + */ +function convertBidiSetupToTokenSetup(requestDict, config) { + // Convert bidiGenerateContentSetup from bidiGenerateContentSetup.setup. + let setupForMaskGeneration = null; + const bidiGenerateContentSetupValue = requestDict['bidiGenerateContentSetup']; + if (typeof bidiGenerateContentSetupValue === 'object' && + bidiGenerateContentSetupValue !== null && + 'setup' in bidiGenerateContentSetupValue) { + // Now we know bidiGenerateContentSetupValue is an object and has a 'setup' + // property. + const innerSetup = bidiGenerateContentSetupValue + .setup; + if (typeof innerSetup === 'object' && innerSetup !== null) { + // Valid inner setup found. + requestDict['bidiGenerateContentSetup'] = innerSetup; + setupForMaskGeneration = innerSetup; + } + else { + // `bidiGenerateContentSetupValue.setup` is not a valid object; treat as + // if bidiGenerateContentSetup is invalid. + delete requestDict['bidiGenerateContentSetup']; + } + } + else if (bidiGenerateContentSetupValue !== undefined) { + // `bidiGenerateContentSetup` exists but not in the expected + // shape {setup: {...}}; treat as invalid. + delete requestDict['bidiGenerateContentSetup']; + } + const preExistingFieldMask = requestDict['fieldMask']; + // Handle mask generation setup. + if (setupForMaskGeneration) { + const generatedMaskFromBidi = getFieldMasks(setupForMaskGeneration); + if (Array.isArray(config === null || config === void 0 ? void 0 : config.lockAdditionalFields) && + (config === null || config === void 0 ? void 0 : config.lockAdditionalFields.length) === 0) { + // Case 1: lockAdditionalFields is an empty array. Lock only fields from + // bidi setup. + if (generatedMaskFromBidi) { + // Only assign if mask is not empty + requestDict['fieldMask'] = generatedMaskFromBidi; + } + else { + delete requestDict['fieldMask']; // If mask is empty, effectively no + // specific fields locked by bidi + } + } + else if ((config === null || config === void 0 ? void 0 : config.lockAdditionalFields) && + config.lockAdditionalFields.length > 0 && + preExistingFieldMask !== null && + Array.isArray(preExistingFieldMask) && + preExistingFieldMask.length > 0) { + // Case 2: Lock fields from bidi setup + additional fields + // (preExistingFieldMask). + const generationConfigFields = [ + 'temperature', + 'topK', + 'topP', + 'maxOutputTokens', + 'responseModalities', + 'seed', + 'speechConfig', + ]; + let mappedFieldsFromPreExisting = []; + if (preExistingFieldMask.length > 0) { + mappedFieldsFromPreExisting = preExistingFieldMask.map((field) => { + if (generationConfigFields.includes(field)) { + return `generationConfig.${field}`; + } + return field; // Keep original field name if not in + // generationConfigFields + }); + } + const finalMaskParts = []; + if (generatedMaskFromBidi) { + finalMaskParts.push(generatedMaskFromBidi); + } + if (mappedFieldsFromPreExisting.length > 0) { + finalMaskParts.push(...mappedFieldsFromPreExisting); + } + if (finalMaskParts.length > 0) { + requestDict['fieldMask'] = finalMaskParts.join(','); + } + else { + // If no fields from bidi and no valid additional fields from + // pre-existing mask. + delete requestDict['fieldMask']; + } + } + else { + // Case 3: "Lock all fields" (meaning, don't send a field_mask, let server + // defaults apply or all are mutable). This is hit if: + // - `config.lockAdditionalFields` is undefined. + // - `config.lockAdditionalFields` is non-empty, BUT + // `preExistingFieldMask` is null, not a string, or an empty string. + delete requestDict['fieldMask']; + } + } + else { + // No valid `bidiGenerateContentSetup` was found or extracted. + // "Lock additional null fields if any". + if (preExistingFieldMask !== null && + Array.isArray(preExistingFieldMask) && + preExistingFieldMask.length > 0) { + // If there's a pre-existing field mask, it's a string, and it's not + // empty, then we should lock all fields. + requestDict['fieldMask'] = preExistingFieldMask.join(','); + } + else { + delete requestDict['fieldMask']; + } + } + return requestDict; +} +class Tokens extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + } + /** + * Creates an ephemeral auth token resource. + * + * @experimental + * + * @remarks + * Ephemeral auth tokens is only supported in the Gemini Developer API. + * It can be used for the session connection to the Live constrained API. + * Support in v1alpha only. + * + * @param params - The parameters for the create request. + * @return The created auth token. + * + * @example + * ```ts + * const ai = new GoogleGenAI({ + * apiKey: token.name, + * httpOptions: { apiVersion: 'v1alpha' } // Support in v1alpha only. + * }); + * + * // Case 1: If LiveEphemeralParameters is unset, unlock LiveConnectConfig + * // when using the token in Live API sessions. Each session connection can + * // use a different configuration. + * const config: CreateAuthTokenConfig = { + * uses: 3, + * expireTime: '2025-05-01T00:00:00Z', + * } + * const token = await ai.tokens.create(config); + * + * // Case 2: If LiveEphemeralParameters is set, lock all fields in + * // LiveConnectConfig when using the token in Live API sessions. For + * // example, changing `outputAudioTranscription` in the Live API + * // connection will be ignored by the API. + * const config: CreateAuthTokenConfig = + * uses: 3, + * expireTime: '2025-05-01T00:00:00Z', + * LiveEphemeralParameters: { + * model: 'gemini-2.0-flash-001', + * config: { + * 'responseModalities': ['AUDIO'], + * 'systemInstruction': 'Always answer in English.', + * } + * } + * } + * const token = await ai.tokens.create(config); + * + * // Case 3: If LiveEphemeralParameters is set and lockAdditionalFields is + * // set, lock LiveConnectConfig with set and additional fields (e.g. + * // responseModalities, systemInstruction, temperature in this example) when + * // using the token in Live API sessions. + * const config: CreateAuthTokenConfig = + * uses: 3, + * expireTime: '2025-05-01T00:00:00Z', + * LiveEphemeralParameters: { + * model: 'gemini-2.0-flash-001', + * config: { + * 'responseModalities': ['AUDIO'], + * 'systemInstruction': 'Always answer in English.', + * } + * }, + * lockAdditionalFields: ['temperature'], + * } + * const token = await ai.tokens.create(config); + * + * // Case 4: If LiveEphemeralParameters is set and lockAdditionalFields is + * // empty array, lock LiveConnectConfig with set fields (e.g. + * // responseModalities, systemInstruction in this example) when using the + * // token in Live API sessions. + * const config: CreateAuthTokenConfig = + * uses: 3, + * expireTime: '2025-05-01T00:00:00Z', + * LiveEphemeralParameters: { + * model: 'gemini-2.0-flash-001', + * config: { + * 'responseModalities': ['AUDIO'], + * 'systemInstruction': 'Always answer in English.', + * } + * }, + * lockAdditionalFields: [], + * } + * const token = await ai.tokens.create(config); + * ``` + */ + async create(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('The client.tokens.create method is only supported by the Gemini Developer API.'); + } + else { + const body = createAuthTokenParametersToMldev(this.apiClient, params); + path = formatMap('auth_tokens', body['_url']); + queryParams = body['_query']; + delete body['config']; + delete body['_url']; + delete body['_query']; + const transformedBody = convertBidiSetupToTokenSetup(body, params.config); + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(transformedBody), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Code generated by the Google Gen AI SDK generator DO NOT EDIT. +function deleteDocumentConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromForce = getValueByPath(fromObject, ['force']); + if (parentObject !== undefined && fromForce != null) { + setValueByPath(parentObject, ['_query', 'force'], fromForce); + } + return toObject; +} +function deleteDocumentParametersToMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + deleteDocumentConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function getDocumentParametersToMldev(fromObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + return toObject; +} +function listDocumentsConfigToMldev(fromObject, parentObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + return toObject; +} +function listDocumentsParametersToMldev(fromObject) { + const toObject = {}; + const fromParent = getValueByPath(fromObject, ['parent']); + if (fromParent != null) { + setValueByPath(toObject, ['_url', 'parent'], fromParent); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listDocumentsConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function listDocumentsResponseFromMldev(fromObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromDocuments = getValueByPath(fromObject, ['documents']); + if (fromDocuments != null) { + let transformedList = fromDocuments; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['documents'], transformedList); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Documents extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + /** + * Lists documents. + * + * @param params - The parameters for the list request. + * @return - A pager of documents. + * + * @example + * ```ts + * const documents = await ai.documents.list({parent:'rag_store_name', config: {'pageSize': 2}}); + * for await (const document of documents) { + * console.log(document); + * } + * ``` + */ + this.list = async (params) => { + return new Pager(PagedItem.PAGED_ITEM_DOCUMENTS, (x) => this.listInternal({ parent: params.parent, config: x.config }), await this.listInternal(params), params); + }; + } + /** + * Gets a Document. + * + * @param params - The parameters for getting a document. + * @return Document. + */ + async get(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = getDocumentParametersToMldev(params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } + /** + * Deletes a Document. + * + * @param params - The parameters for deleting a document. + */ + async delete(params) { + var _a, _b; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = deleteDocumentParametersToMldev(params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + await this.apiClient.request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }); + } + } + async listInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = listDocumentsParametersToMldev(params); + path = formatMap('{parent}/documents', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = listDocumentsResponseFromMldev(apiResponse); + const typedResp = new ListDocumentsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class FileSearchStores extends BaseModule { + constructor(apiClient, documents = new Documents(apiClient)) { + super(); + this.apiClient = apiClient; + this.documents = documents; + /** + * Lists file search stores. + * + * @param params - The parameters for the list request. + * @return - A pager of file search stores. + * + * @example + * ```ts + * const fileSearchStores = await ai.fileSearchStores.list({config: {'pageSize': 2}}); + * for await (const fileSearchStore of fileSearchStores) { + * console.log(fileSearchStore); + * } + * ``` + */ + this.list = async (params = {}) => { + return new Pager(PagedItem.PAGED_ITEM_FILE_SEARCH_STORES, (x) => this.listInternal(x), await this.listInternal(params), params); + }; + } + /** + * Uploads a file asynchronously to a given File Search Store. + * This method is not available in Vertex AI. + * Supported upload sources: + * - Node.js: File path (string) or Blob object. + * - Browser: Blob object (e.g., File). + * + * @remarks + * The `mimeType` can be specified in the `config` parameter. If omitted: + * - For file path (string) inputs, the `mimeType` will be inferred from the + * file extension. + * - For Blob object inputs, the `mimeType` will be set to the Blob's `type` + * property. + * + * This section can contain multiple paragraphs and code examples. + * + * @param params - Optional parameters specified in the + * `types.UploadToFileSearchStoreParameters` interface. + * @see {@link types.UploadToFileSearchStoreParameters#config} for the optional + * config in the parameters. + * @return A promise that resolves to a long running operation. + * @throws An error if called on a Vertex AI client. + * @throws An error if the `mimeType` is not provided and can not be inferred, + * the `mimeType` can be provided in the `params.config` parameter. + * @throws An error occurs if a suitable upload location cannot be established. + * + * @example + * The following code uploads a file to a given file search store. + * + * ```ts + * const operation = await ai.fileSearchStores.upload({fileSearchStoreName: 'fileSearchStores/foo-bar', file: 'file.txt', config: { + * mimeType: 'text/plain', + * }}); + * console.log(operation.name); + * ``` + */ + async uploadToFileSearchStore(params) { + if (this.apiClient.isVertexAI()) { + throw new Error('Vertex AI does not support uploading files to a file search store.'); + } + return this.apiClient.uploadFileToFileSearchStore(params.fileSearchStoreName, params.file, params.config); + } + /** + * Creates a File Search Store. + * + * @param params - The parameters for creating a File Search Store. + * @return FileSearchStore. + */ + async create(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = createFileSearchStoreParametersToMldev(params); + path = formatMap('fileSearchStores', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } + /** + * Gets a File Search Store. + * + * @param params - The parameters for getting a File Search Store. + * @return FileSearchStore. + */ + async get(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = getFileSearchStoreParametersToMldev(params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((resp) => { + return resp; + }); + } + } + /** + * Deletes a File Search Store. + * + * @param params - The parameters for deleting a File Search Store. + */ + async delete(params) { + var _a, _b; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = deleteFileSearchStoreParametersToMldev(params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + await this.apiClient.request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'DELETE', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }); + } + } + async listInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = listFileSearchStoresParametersToMldev(params); + path = formatMap('fileSearchStores', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = listFileSearchStoresResponseFromMldev(apiResponse); + const typedResp = new ListFileSearchStoresResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + async uploadToFileSearchStoreInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = uploadToFileSearchStoreParametersToMldev(params); + path = formatMap('upload/v1beta/{file_search_store_name}:uploadToFileSearchStore', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = uploadToFileSearchStoreResumableResponseFromMldev(apiResponse); + const typedResp = new UploadToFileSearchStoreResumableResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Imports a File from File Service to a FileSearchStore. + * + * This is a long-running operation, see aip.dev/151 + * + * @param params - The parameters for importing a file to a file search store. + * @return ImportFileOperation. + */ + async importFile(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = importFileParametersToMldev(params); + path = formatMap('{file_search_store_name}:importFile', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json(); + }); + return response.then((apiResponse) => { + const resp = importFileOperationFromMldev(apiResponse); + const typedResp = new ImportFileOperation(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +/** + * https://stackoverflow.com/a/2117523 + */ +let uuid4Internal = function () { + const { crypto } = globalThis; + if (crypto === null || crypto === void 0 ? void 0 : crypto.randomUUID) { + uuid4Internal = crypto.randomUUID.bind(crypto); + return crypto.randomUUID(); + } + const u8 = new Uint8Array(1); + const randomByte = crypto ? () => crypto.getRandomValues(u8)[0] : () => (Math.random() * 0xff) & 0xff; + return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, (c) => (+c ^ (randomByte() & (15 >> (+c / 4)))).toString(16)); +}; +const uuid4 = () => uuid4Internal(); + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +function isAbortError(err) { + return (typeof err === 'object' && + err !== null && + // Spec-compliant fetch implementations + (('name' in err && err.name === 'AbortError') || + // Expo fetch + ('message' in err && String(err.message).includes('FetchRequestCanceledException')))); +} +const castToError = (err) => { + if (err instanceof Error) + return err; + if (typeof err === 'object' && err !== null) { + try { + if (Object.prototype.toString.call(err) === '[object Error]') { + // @ts-ignore - not all envs have native support for cause yet + const error = new Error(err.message, err.cause ? { cause: err.cause } : {}); + if (err.stack) + error.stack = err.stack; + // @ts-ignore - not all envs have native support for cause yet + if (err.cause && !error.cause) + error.cause = err.cause; + if (err.name) + error.name = err.name; + return error; + } + } + catch (_a) { } + try { + return new Error(JSON.stringify(err)); + } + catch (_b) { } + } + return new Error(err); +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +class GeminiNextGenAPIClientError extends Error { +} +class APIError extends GeminiNextGenAPIClientError { + constructor(status, error, message, headers) { + super(`${APIError.makeMessage(status, error, message)}`); + this.status = status; + this.headers = headers; + this.error = error; + } + static makeMessage(status, error, message) { + const msg = (error === null || error === void 0 ? void 0 : error.message) ? + typeof error.message === 'string' ? + error.message + : JSON.stringify(error.message) + : error ? JSON.stringify(error) + : message; + if (status && msg) { + return `${status} ${msg}`; + } + if (status) { + return `${status} status code (no body)`; + } + if (msg) { + return msg; + } + return '(no status code or body)'; + } + static generate(status, errorResponse, message, headers) { + if (!status || !headers) { + return new APIConnectionError({ message, cause: castToError(errorResponse) }); + } + const error = errorResponse; + if (status === 400) { + return new BadRequestError(status, error, message, headers); + } + if (status === 401) { + return new AuthenticationError(status, error, message, headers); + } + if (status === 403) { + return new PermissionDeniedError(status, error, message, headers); + } + if (status === 404) { + return new NotFoundError(status, error, message, headers); + } + if (status === 409) { + return new ConflictError(status, error, message, headers); + } + if (status === 422) { + return new UnprocessableEntityError(status, error, message, headers); + } + if (status === 429) { + return new RateLimitError(status, error, message, headers); + } + if (status >= 500) { + return new InternalServerError(status, error, message, headers); + } + return new APIError(status, error, message, headers); + } +} +class APIUserAbortError extends APIError { + constructor({ message } = {}) { + super(undefined, undefined, message || 'Request was aborted.', undefined); + } +} +class APIConnectionError extends APIError { + constructor({ message, cause }) { + super(undefined, undefined, message || 'Connection error.', undefined); + // in some environments the 'cause' property is already declared + // @ts-ignore + if (cause) + this.cause = cause; + } +} +class APIConnectionTimeoutError extends APIConnectionError { + constructor({ message } = {}) { + super({ message: message !== null && message !== void 0 ? message : 'Request timed out.' }); + } +} +class BadRequestError extends APIError { +} +class AuthenticationError extends APIError { +} +class PermissionDeniedError extends APIError { +} +class NotFoundError extends APIError { +} +class ConflictError extends APIError { +} +class UnprocessableEntityError extends APIError { +} +class RateLimitError extends APIError { +} +class InternalServerError extends APIError { +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +// https://url.spec.whatwg.org/#url-scheme-string +const startsWithSchemeRegexp = /^[a-z][a-z0-9+.-]*:/i; +const isAbsoluteURL = (url) => { + return startsWithSchemeRegexp.test(url); +}; +let isArrayInternal = (val) => ((isArrayInternal = Array.isArray), isArrayInternal(val)); +const isArray = isArrayInternal; +let isReadonlyArrayInternal = isArray; +const isReadonlyArray = isReadonlyArrayInternal; +// https://stackoverflow.com/a/34491287 +function isEmptyObj(obj) { + if (!obj) + return true; + for (const _k in obj) + return false; + return true; +} +// https://eslint.org/docs/latest/rules/no-prototype-builtins +function hasOwn(obj, key) { + return Object.prototype.hasOwnProperty.call(obj, key); +} +const validatePositiveInteger = (name, n) => { + if (typeof n !== 'number' || !Number.isInteger(n)) { + throw new GeminiNextGenAPIClientError(`${name} must be an integer`); + } + if (n < 0) { + throw new GeminiNextGenAPIClientError(`${name} must be a positive integer`); + } + return n; +}; +const safeJSON = (text) => { + try { + return JSON.parse(text); + } + catch (err) { + return undefined; + } +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +const sleep$1 = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const VERSION = '0.0.1'; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +/** + * Note this does not detect 'browser'; for that, use getBrowserInfo(). + */ +function getDetectedPlatform() { + if (typeof Deno !== 'undefined' && Deno.build != null) { + return 'deno'; + } + if (typeof EdgeRuntime !== 'undefined') { + return 'edge'; + } + if (Object.prototype.toString.call(typeof globalThis.process !== 'undefined' ? globalThis.process : 0) === '[object process]') { + return 'node'; + } + return 'unknown'; +} +const getPlatformProperties = () => { + var _a, _b, _c, _d, _e; + const detectedPlatform = getDetectedPlatform(); + if (detectedPlatform === 'deno') { + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': VERSION, + 'X-Stainless-OS': normalizePlatform(Deno.build.os), + 'X-Stainless-Arch': normalizeArch(Deno.build.arch), + 'X-Stainless-Runtime': 'deno', + 'X-Stainless-Runtime-Version': typeof Deno.version === 'string' ? Deno.version : (_b = (_a = Deno.version) === null || _a === void 0 ? void 0 : _a.deno) !== null && _b !== void 0 ? _b : 'unknown', + }; + } + if (typeof EdgeRuntime !== 'undefined') { + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': VERSION, + 'X-Stainless-OS': 'Unknown', + 'X-Stainless-Arch': `other:${EdgeRuntime}`, + 'X-Stainless-Runtime': 'edge', + 'X-Stainless-Runtime-Version': globalThis.process.version, + }; + } + // Check if Node.js + if (detectedPlatform === 'node') { + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': VERSION, + 'X-Stainless-OS': normalizePlatform((_c = globalThis.process.platform) !== null && _c !== void 0 ? _c : 'unknown'), + 'X-Stainless-Arch': normalizeArch((_d = globalThis.process.arch) !== null && _d !== void 0 ? _d : 'unknown'), + 'X-Stainless-Runtime': 'node', + 'X-Stainless-Runtime-Version': (_e = globalThis.process.version) !== null && _e !== void 0 ? _e : 'unknown', + }; + } + const browserInfo = getBrowserInfo(); + if (browserInfo) { + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': VERSION, + 'X-Stainless-OS': 'Unknown', + 'X-Stainless-Arch': 'unknown', + 'X-Stainless-Runtime': `browser:${browserInfo.browser}`, + 'X-Stainless-Runtime-Version': browserInfo.version, + }; + } + // TODO add support for Cloudflare workers, etc. + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': VERSION, + 'X-Stainless-OS': 'Unknown', + 'X-Stainless-Arch': 'unknown', + 'X-Stainless-Runtime': 'unknown', + 'X-Stainless-Runtime-Version': 'unknown', + }; +}; +// Note: modified from https://github.com/JS-DevTools/host-environment/blob/b1ab79ecde37db5d6e163c050e54fe7d287d7c92/src/isomorphic.browser.ts +function getBrowserInfo() { + if (typeof navigator === 'undefined' || !navigator) { + return null; + } + // NOTE: The order matters here! + const browserPatterns = [ + { key: 'edge', pattern: /Edge(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'ie', pattern: /MSIE(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'ie', pattern: /Trident(?:.*rv\:(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'chrome', pattern: /Chrome(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'firefox', pattern: /Firefox(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'safari', pattern: /(?:Version\W+(\d+)\.(\d+)(?:\.(\d+))?)?(?:\W+Mobile\S*)?\W+Safari/ }, + ]; + // Find the FIRST matching browser + for (const { key, pattern } of browserPatterns) { + const match = pattern.exec(navigator.userAgent); + if (match) { + const major = match[1] || 0; + const minor = match[2] || 0; + const patch = match[3] || 0; + return { browser: key, version: `${major}.${minor}.${patch}` }; + } + } + return null; +} +const normalizeArch = (arch) => { + // Node docs: + // - https://nodejs.org/api/process.html#processarch + // Deno docs: + // - https://doc.deno.land/deno/stable/~/Deno.build + if (arch === 'x32') + return 'x32'; + if (arch === 'x86_64' || arch === 'x64') + return 'x64'; + if (arch === 'arm') + return 'arm'; + if (arch === 'aarch64' || arch === 'arm64') + return 'arm64'; + if (arch) + return `other:${arch}`; + return 'unknown'; +}; +const normalizePlatform = (platform) => { + // Node platforms: + // - https://nodejs.org/api/process.html#processplatform + // Deno platforms: + // - https://doc.deno.land/deno/stable/~/Deno.build + // - https://github.com/denoland/deno/issues/14799 + platform = platform.toLowerCase(); + // NOTE: this iOS check is untested and may not work + // Node does not work natively on IOS, there is a fork at + // https://github.com/nodejs-mobile/nodejs-mobile + // however it is unknown at the time of writing how to detect if it is running + if (platform.includes('ios')) + return 'iOS'; + if (platform === 'android') + return 'Android'; + if (platform === 'darwin') + return 'MacOS'; + if (platform === 'win32') + return 'Windows'; + if (platform === 'freebsd') + return 'FreeBSD'; + if (platform === 'openbsd') + return 'OpenBSD'; + if (platform === 'linux') + return 'Linux'; + if (platform) + return `Other:${platform}`; + return 'Unknown'; +}; +let _platformHeaders; +const getPlatformHeaders = () => { + return (_platformHeaders !== null && _platformHeaders !== void 0 ? _platformHeaders : (_platformHeaders = getPlatformProperties())); +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function getDefaultFetch() { + if (typeof fetch !== 'undefined') { + return fetch; + } + throw new Error('`fetch` is not defined as a global; Either pass `fetch` to the client, `new GeminiNextGenAPIClient({ fetch })` or polyfill the global, `globalThis.fetch = fetch`'); +} +function makeReadableStream(...args) { + const ReadableStream = globalThis.ReadableStream; + if (typeof ReadableStream === 'undefined') { + // Note: All of the platforms / runtimes we officially support already define + // `ReadableStream` as a global, so this should only ever be hit on unsupported runtimes. + throw new Error('`ReadableStream` is not defined as a global; You will need to polyfill it, `globalThis.ReadableStream = ReadableStream`'); + } + return new ReadableStream(...args); +} +function ReadableStreamFrom(iterable) { + let iter = Symbol.asyncIterator in iterable ? iterable[Symbol.asyncIterator]() : iterable[Symbol.iterator](); + return makeReadableStream({ + start() { }, + async pull(controller) { + const { done, value } = await iter.next(); + if (done) { + controller.close(); + } + else { + controller.enqueue(value); + } + }, + async cancel() { + var _a; + await ((_a = iter.return) === null || _a === void 0 ? void 0 : _a.call(iter)); + }, + }); +} +/** + * Most browsers don't yet have async iterable support for ReadableStream, + * and Node has a very different way of reading bytes from its "ReadableStream". + * + * This polyfill was pulled from https://github.com/MattiasBuelens/web-streams-polyfill/pull/122#issuecomment-1627354490 + */ +function ReadableStreamToAsyncIterable(stream) { + if (stream[Symbol.asyncIterator]) + return stream; + const reader = stream.getReader(); + return { + async next() { + try { + const result = await reader.read(); + if (result === null || result === void 0 ? void 0 : result.done) + reader.releaseLock(); // release lock when stream becomes closed + return result; + } + catch (e) { + reader.releaseLock(); // release lock when stream becomes errored + throw e; + } + }, + async return() { + const cancelPromise = reader.cancel(); + reader.releaseLock(); + await cancelPromise; + return { done: true, value: undefined }; + }, + [Symbol.asyncIterator]() { + return this; + }, + }; +} +/** + * Cancels a ReadableStream we don't need to consume. + * See https://undici.nodejs.org/#/?id=garbage-collection + */ +async function CancelReadableStream(stream) { + var _a, _b; + if (stream === null || typeof stream !== 'object') + return; + if (stream[Symbol.asyncIterator]) { + await ((_b = (_a = stream[Symbol.asyncIterator]()).return) === null || _b === void 0 ? void 0 : _b.call(_a)); + return; + } + const reader = stream.getReader(); + const cancelPromise = reader.cancel(); + reader.releaseLock(); + await cancelPromise; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const FallbackEncoder = ({ headers, body }) => { + return { + bodyHeaders: { + 'content-type': 'application/json', + }, + body: JSON.stringify(body), + }; +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const checkFileSupport = () => { + var _a; + if (typeof File === 'undefined') { + const { process } = globalThis; + const isOldNode = typeof ((_a = process === null || process === void 0 ? void 0 : process.versions) === null || _a === void 0 ? void 0 : _a.node) === 'string' && parseInt(process.versions.node.split('.')) < 20; + throw new Error('`File` is not defined as a global, which is required for file uploads.' + + (isOldNode ? + " Update to Node 20 LTS or newer, or set `globalThis.File` to `import('node:buffer').File`." + : '')); + } +}; +/** + * Construct a `File` instance. This is used to ensure a helpful error is thrown + * for environments that don't define a global `File` yet. + */ +function makeFile(fileBits, fileName, options) { + checkFileSupport(); + return new File(fileBits, fileName !== null && fileName !== void 0 ? fileName : 'unknown_file', options); +} +function getName(value) { + return (((typeof value === 'object' && + value !== null && + (('name' in value && value.name && String(value.name)) || + ('url' in value && value.url && String(value.url)) || + ('filename' in value && value.filename && String(value.filename)) || + ('path' in value && value.path && String(value.path)))) || + '') + .split(/[\\/]/) + .pop() || undefined); +} +const isAsyncIterable = (value) => value != null && typeof value === 'object' && typeof value[Symbol.asyncIterator] === 'function'; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * This check adds the arrayBuffer() method type because it is available and used at runtime + */ +const isBlobLike = (value) => value != null && + typeof value === 'object' && + typeof value.size === 'number' && + typeof value.type === 'string' && + typeof value.text === 'function' && + typeof value.slice === 'function' && + typeof value.arrayBuffer === 'function'; +/** + * This check adds the arrayBuffer() method type because it is available and used at runtime + */ +const isFileLike = (value) => value != null && + typeof value === 'object' && + typeof value.name === 'string' && + typeof value.lastModified === 'number' && + isBlobLike(value); +const isResponseLike = (value) => value != null && + typeof value === 'object' && + typeof value.url === 'string' && + typeof value.blob === 'function'; +/** + * Helper for creating a {@link File} to pass to an SDK upload method from a variety of different data formats + * @param value the raw content of the file. Can be an {@link Uploadable}, BlobLikePart, or AsyncIterable of BlobLikeParts + * @param {string=} name the name of the file. If omitted, toFile will try to determine a file name from bits if possible + * @param {Object=} options additional properties + * @param {string=} options.type the MIME type of the content + * @param {number=} options.lastModified the last modified timestamp + * @returns a {@link File} with the given properties + */ +async function toFile(value, name, options) { + checkFileSupport(); + // If it's a promise, resolve it. + value = await value; + // If we've been given a `File` we don't need to do anything + if (isFileLike(value)) { + if (value instanceof File) { + return value; + } + return makeFile([await value.arrayBuffer()], value.name); + } + if (isResponseLike(value)) { + const blob = await value.blob(); + name || (name = new URL(value.url).pathname.split(/[\\/]/).pop()); + return makeFile(await getBytes(blob), name, options); + } + const parts = await getBytes(value); + name || (name = getName(value)); + if (!(options === null || options === void 0 ? void 0 : options.type)) { + const type = parts.find((part) => typeof part === 'object' && 'type' in part && part.type); + if (typeof type === 'string') { + options = Object.assign(Object.assign({}, options), { type }); + } + } + return makeFile(parts, name, options); +} +async function getBytes(value) { + var _a, e_1, _b, _c; + var _d; + let parts = []; + if (typeof value === 'string' || + ArrayBuffer.isView(value) || // includes Uint8Array, Buffer, etc. + value instanceof ArrayBuffer) { + parts.push(value); + } + else if (isBlobLike(value)) { + parts.push(value instanceof Blob ? value : await value.arrayBuffer()); + } + else if (isAsyncIterable(value) // includes Readable, ReadableStream, etc. + ) { + try { + for (var _e = true, value_1 = __asyncValues(value), value_1_1; value_1_1 = await value_1.next(), _a = value_1_1.done, !_a; _e = true) { + _c = value_1_1.value; + _e = false; + const chunk = _c; + parts.push(...(await getBytes(chunk))); // TODO, consider validating? + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (!_e && !_a && (_b = value_1.return)) await _b.call(value_1); + } + finally { if (e_1) throw e_1.error; } + } + } + else { + const constructor = (_d = value === null || value === void 0 ? void 0 : value.constructor) === null || _d === void 0 ? void 0 : _d.name; + throw new Error(`Unexpected data type: ${typeof value}${constructor ? `; constructor: ${constructor}` : ''}${propsForError(value)}`); + } + return parts; +} +function propsForError(value) { + if (typeof value !== 'object' || value === null) + return ''; + const props = Object.getOwnPropertyNames(value); + return `; props: [${props.map((p) => `"${p}"`).join(', ')}]`; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class APIResource { + constructor(client) { + this._client = client; + } +} +/** + * The key path from the client. For example, a resource accessible as `client.resource.subresource` would + * have a property `static override readonly _key = Object.freeze(['resource', 'subresource'] as const);`. + */ +APIResource._key = []; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Percent-encode everything that isn't safe to have in a path without encoding safe chars. + * + * Taken from https://datatracker.ietf.org/doc/html/rfc3986#section-3.3: + * > unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + * > sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" + * > pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + */ +function encodeURIPath(str) { + return str.replace(/[^A-Za-z0-9\-._~!$&'()*+,;=:@]+/g, encodeURIComponent); +} +const EMPTY = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.create(null)); +const createPathTagFunction = (pathEncoder = encodeURIPath) => (function path(statics, ...params) { + // If there are no params, no processing is needed. + if (statics.length === 1) + return statics[0]; + let postPath = false; + const invalidSegments = []; + const path = statics.reduce((previousValue, currentValue, index) => { + var _a, _b, _c; + if (/[?#]/.test(currentValue)) { + postPath = true; + } + const value = params[index]; + let encoded = (postPath ? encodeURIComponent : pathEncoder)('' + value); + if (index !== params.length && + (value == null || + (typeof value === 'object' && + // handle values from other realms + value.toString === + ((_c = Object.getPrototypeOf((_b = Object.getPrototypeOf((_a = value.hasOwnProperty) !== null && _a !== void 0 ? _a : EMPTY)) !== null && _b !== void 0 ? _b : EMPTY)) === null || _c === void 0 ? void 0 : _c.toString)))) { + encoded = value + ''; + invalidSegments.push({ + start: previousValue.length + currentValue.length, + length: encoded.length, + error: `Value of type ${Object.prototype.toString + .call(value) + .slice(8, -1)} is not a valid path parameter`, + }); + } + return previousValue + currentValue + (index === params.length ? '' : encoded); + }, ''); + const pathOnly = path.split(/[?#]/, 1)[0]; + const invalidSegmentPattern = /(?<=^|\/)(?:\.|%2e){1,2}(?=\/|$)/gi; + let match; + // Find all invalid segments + while ((match = invalidSegmentPattern.exec(pathOnly)) !== null) { + invalidSegments.push({ + start: match.index, + length: match[0].length, + error: `Value "${match[0]}" can\'t be safely passed as a path parameter`, + }); + } + invalidSegments.sort((a, b) => a.start - b.start); + if (invalidSegments.length > 0) { + let lastEnd = 0; + const underline = invalidSegments.reduce((acc, segment) => { + const spaces = ' '.repeat(segment.start - lastEnd); + const arrows = '^'.repeat(segment.length); + lastEnd = segment.start + segment.length; + return acc + spaces + arrows; + }, ''); + throw new GeminiNextGenAPIClientError(`Path parameters result in path with invalid segments:\n${invalidSegments + .map((e) => e.error) + .join('\n')}\n${path}\n${underline}`); + } + return path; +}); +/** + * URI-encodes path params and ensures no unsafe /./ or /../ path segments are introduced. + */ +const path = /* @__PURE__ */ createPathTagFunction(encodeURIPath); + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class BaseInteractions extends APIResource { + create(params, options) { + var _a; + const { api_version = this._client.apiVersion } = params, body = __rest(params, ["api_version"]); + if ('model' in body && 'agent_config' in body) { + throw new GeminiNextGenAPIClientError(`Invalid request: specified \`model\` and \`agent_config\`. If specifying \`model\`, use \`generation_config\`.`); + } + if ('agent' in body && 'generation_config' in body) { + throw new GeminiNextGenAPIClientError(`Invalid request: specified \`agent\` and \`generation_config\`. If specifying \`agent\`, use \`agent_config\`.`); + } + return this._client.post(path `/${api_version}/interactions`, Object.assign(Object.assign({ body }, options), { stream: (_a = params.stream) !== null && _a !== void 0 ? _a : false })); + } + /** + * Deletes the interaction by id. + * + * @example + * ```ts + * const interaction = await client.interactions.delete('id', { + * api_version: 'api_version', + * }); + * ``` + */ + delete(id, params = {}, options) { + const { api_version = this._client.apiVersion } = params !== null && params !== void 0 ? params : {}; + return this._client.delete(path `/${api_version}/interactions/${id}`, options); + } + /** + * Cancels an interaction by id. This only applies to background interactions that are still running. + * + * @example + * ```ts + * const interaction = await client.interactions.cancel('id', { + * api_version: 'api_version', + * }); + * ``` + */ + cancel(id, params = {}, options) { + const { api_version = this._client.apiVersion } = params !== null && params !== void 0 ? params : {}; + return this._client.post(path `/${api_version}/interactions/${id}/cancel`, options); + } + get(id, params = {}, options) { + var _a; + const _b = params !== null && params !== void 0 ? params : {}, { api_version = this._client.apiVersion } = _b, query = __rest(_b, ["api_version"]); + return this._client.get(path `/${api_version}/interactions/${id}`, Object.assign(Object.assign({ query }, options), { stream: (_a = params === null || params === void 0 ? void 0 : params.stream) !== null && _a !== void 0 ? _a : false })); + } +} +BaseInteractions._key = Object.freeze(['interactions']); +class Interactions extends BaseInteractions { +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function concatBytes(buffers) { + let length = 0; + for (const buffer of buffers) { + length += buffer.length; + } + const output = new Uint8Array(length); + let index = 0; + for (const buffer of buffers) { + output.set(buffer, index); + index += buffer.length; + } + return output; +} +let encodeUTF8_; +function encodeUTF8(str) { + let encoder; + return (encodeUTF8_ !== null && encodeUTF8_ !== void 0 ? encodeUTF8_ : ((encoder = new globalThis.TextEncoder()), (encodeUTF8_ = encoder.encode.bind(encoder))))(str); +} +let decodeUTF8_; +function decodeUTF8(bytes) { + let decoder; + return (decodeUTF8_ !== null && decodeUTF8_ !== void 0 ? decodeUTF8_ : ((decoder = new globalThis.TextDecoder()), (decodeUTF8_ = decoder.decode.bind(decoder))))(bytes); +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * A re-implementation of httpx's `LineDecoder` in Python that handles incrementally + * reading lines from text. + * + * https://github.com/encode/httpx/blob/920333ea98118e9cf617f246905d7b202510941c/httpx/_decoders.py#L258 + */ +class LineDecoder { + constructor() { + this.buffer = new Uint8Array(); + this.carriageReturnIndex = null; + } + decode(chunk) { + if (chunk == null) { + return []; + } + const binaryChunk = chunk instanceof ArrayBuffer ? new Uint8Array(chunk) + : typeof chunk === 'string' ? encodeUTF8(chunk) + : chunk; + this.buffer = concatBytes([this.buffer, binaryChunk]); + const lines = []; + let patternIndex; + while ((patternIndex = findNewlineIndex(this.buffer, this.carriageReturnIndex)) != null) { + if (patternIndex.carriage && this.carriageReturnIndex == null) { + // skip until we either get a corresponding `\n`, a new `\r` or nothing + this.carriageReturnIndex = patternIndex.index; + continue; + } + // we got double \r or \rtext\n + if (this.carriageReturnIndex != null && + (patternIndex.index !== this.carriageReturnIndex + 1 || patternIndex.carriage)) { + lines.push(decodeUTF8(this.buffer.subarray(0, this.carriageReturnIndex - 1))); + this.buffer = this.buffer.subarray(this.carriageReturnIndex); + this.carriageReturnIndex = null; + continue; + } + const endIndex = this.carriageReturnIndex !== null ? patternIndex.preceding - 1 : patternIndex.preceding; + const line = decodeUTF8(this.buffer.subarray(0, endIndex)); + lines.push(line); + this.buffer = this.buffer.subarray(patternIndex.index); + this.carriageReturnIndex = null; + } + return lines; + } + flush() { + if (!this.buffer.length) { + return []; + } + return this.decode('\n'); + } +} +// prettier-ignore +LineDecoder.NEWLINE_CHARS = new Set(['\n', '\r']); +LineDecoder.NEWLINE_REGEXP = /\r\n|[\n\r]/g; +/** + * This function searches the buffer for the end patterns, (\r or \n) + * and returns an object with the index preceding the matched newline and the + * index after the newline char. `null` is returned if no new line is found. + * + * ```ts + * findNewLineIndex('abc\ndef') -> { preceding: 2, index: 3 } + * ``` + */ +function findNewlineIndex(buffer, startIndex) { + const newline = 0x0a; // \n + const carriage = 0x0d; // \r + for (let i = startIndex !== null && startIndex !== void 0 ? startIndex : 0; i < buffer.length; i++) { + if (buffer[i] === newline) { + return { preceding: i, index: i + 1, carriage: false }; + } + if (buffer[i] === carriage) { + return { preceding: i, index: i + 1, carriage: true }; + } + } + return null; +} +function findDoubleNewlineIndex(buffer) { + // This function searches the buffer for the end patterns (\r\r, \n\n, \r\n\r\n) + // and returns the index right after the first occurrence of any pattern, + // or -1 if none of the patterns are found. + const newline = 0x0a; // \n + const carriage = 0x0d; // \r + for (let i = 0; i < buffer.length - 1; i++) { + if (buffer[i] === newline && buffer[i + 1] === newline) { + // \n\n + return i + 2; + } + if (buffer[i] === carriage && buffer[i + 1] === carriage) { + // \r\r + return i + 2; + } + if (buffer[i] === carriage && + buffer[i + 1] === newline && + i + 3 < buffer.length && + buffer[i + 2] === carriage && + buffer[i + 3] === newline) { + // \r\n\r\n + return i + 4; + } + } + return -1; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +const levelNumbers = { + off: 0, + error: 200, + warn: 300, + info: 400, + debug: 500, +}; +const parseLogLevel = (maybeLevel, sourceName, client) => { + if (!maybeLevel) { + return undefined; + } + if (hasOwn(levelNumbers, maybeLevel)) { + return maybeLevel; + } + loggerFor(client).warn(`${sourceName} was set to ${JSON.stringify(maybeLevel)}, expected one of ${JSON.stringify(Object.keys(levelNumbers))}`); + return undefined; +}; +function noop() { } +function makeLogFn(fnLevel, logger, logLevel) { + if (!logger || levelNumbers[fnLevel] > levelNumbers[logLevel]) { + return noop; + } + else { + // Don't wrap logger functions, we want the stacktrace intact! + return logger[fnLevel].bind(logger); + } +} +const noopLogger = { + error: noop, + warn: noop, + info: noop, + debug: noop, +}; +let cachedLoggers = /* @__PURE__ */ new WeakMap(); +function loggerFor(client) { + var _a; + const logger = client.logger; + const logLevel = (_a = client.logLevel) !== null && _a !== void 0 ? _a : 'off'; + if (!logger) { + return noopLogger; + } + const cachedLogger = cachedLoggers.get(logger); + if (cachedLogger && cachedLogger[0] === logLevel) { + return cachedLogger[1]; + } + const levelLogger = { + error: makeLogFn('error', logger, logLevel), + warn: makeLogFn('warn', logger, logLevel), + info: makeLogFn('info', logger, logLevel), + debug: makeLogFn('debug', logger, logLevel), + }; + cachedLoggers.set(logger, [logLevel, levelLogger]); + return levelLogger; +} +const formatRequestDetails = (details) => { + if (details.options) { + details.options = Object.assign({}, details.options); + delete details.options['headers']; // redundant + leaks internals + } + if (details.headers) { + details.headers = Object.fromEntries((details.headers instanceof Headers ? [...details.headers] : Object.entries(details.headers)).map(([name, value]) => [ + name, + (name.toLowerCase() === 'x-goog-api-key' || + name.toLowerCase() === 'authorization' || + name.toLowerCase() === 'cookie' || + name.toLowerCase() === 'set-cookie') ? + '***' + : value, + ])); + } + if ('retryOfRequestLogID' in details) { + if (details.retryOfRequestLogID) { + details.retryOf = details.retryOfRequestLogID; + } + delete details.retryOfRequestLogID; + } + return details; +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Stream { + constructor(iterator, controller, client) { + this.iterator = iterator; + this.controller = controller; + this.client = client; + } + static fromSSEResponse(response, controller, client) { + let consumed = false; + const logger = client ? loggerFor(client) : console; + function iterator() { + return __asyncGenerator(this, arguments, function* iterator_1() { + var _a, e_1, _b, _c; + if (consumed) { + throw new GeminiNextGenAPIClientError('Cannot iterate over a consumed stream, use `.tee()` to split the stream.'); + } + consumed = true; + let done = false; + try { + try { + for (var _d = true, _e = __asyncValues(_iterSSEMessages(response, controller)), _f; _f = yield __await(_e.next()), _a = _f.done, !_a; _d = true) { + _c = _f.value; + _d = false; + const sse = _c; + if (done) + continue; + if (sse.data.startsWith('[DONE]')) { + done = true; + continue; + } + else { + try { + // @ts-ignore + yield yield __await(JSON.parse(sse.data)); + } + catch (e) { + logger.error(`Could not parse message into JSON:`, sse.data); + logger.error(`From chunk:`, sse.raw); + throw e; + } + } + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (!_d && !_a && (_b = _e.return)) yield __await(_b.call(_e)); + } + finally { if (e_1) throw e_1.error; } + } + done = true; + } + catch (e) { + // If the user calls `stream.controller.abort()`, we should exit without throwing. + if (isAbortError(e)) + return yield __await(void 0); + throw e; + } + finally { + // If the user `break`s, abort the ongoing request. + if (!done) + controller.abort(); + } + }); + } + return new Stream(iterator, controller, client); + } + /** + * Generates a Stream from a newline-separated ReadableStream + * where each item is a JSON value. + */ + static fromReadableStream(readableStream, controller, client) { + let consumed = false; + function iterLines() { + return __asyncGenerator(this, arguments, function* iterLines_1() { + var _a, e_2, _b, _c; + const lineDecoder = new LineDecoder(); + const iter = ReadableStreamToAsyncIterable(readableStream); + try { + for (var _d = true, iter_1 = __asyncValues(iter), iter_1_1; iter_1_1 = yield __await(iter_1.next()), _a = iter_1_1.done, !_a; _d = true) { + _c = iter_1_1.value; + _d = false; + const chunk = _c; + for (const line of lineDecoder.decode(chunk)) { + yield yield __await(line); + } + } + } + catch (e_2_1) { e_2 = { error: e_2_1 }; } + finally { + try { + if (!_d && !_a && (_b = iter_1.return)) yield __await(_b.call(iter_1)); + } + finally { if (e_2) throw e_2.error; } + } + for (const line of lineDecoder.flush()) { + yield yield __await(line); + } + }); + } + function iterator() { + return __asyncGenerator(this, arguments, function* iterator_2() { + var _a, e_3, _b, _c; + if (consumed) { + throw new GeminiNextGenAPIClientError('Cannot iterate over a consumed stream, use `.tee()` to split the stream.'); + } + consumed = true; + let done = false; + try { + try { + for (var _d = true, _e = __asyncValues(iterLines()), _f; _f = yield __await(_e.next()), _a = _f.done, !_a; _d = true) { + _c = _f.value; + _d = false; + const line = _c; + if (done) + continue; + // @ts-ignore + if (line) + yield yield __await(JSON.parse(line)); + } + } + catch (e_3_1) { e_3 = { error: e_3_1 }; } + finally { + try { + if (!_d && !_a && (_b = _e.return)) yield __await(_b.call(_e)); + } + finally { if (e_3) throw e_3.error; } + } + done = true; + } + catch (e) { + // If the user calls `stream.controller.abort()`, we should exit without throwing. + if (isAbortError(e)) + return yield __await(void 0); + throw e; + } + finally { + // If the user `break`s, abort the ongoing request. + if (!done) + controller.abort(); + } + }); + } + return new Stream(iterator, controller, client); + } + [Symbol.asyncIterator]() { + return this.iterator(); + } + /** + * Splits the stream into two streams which can be + * independently read from at different speeds. + */ + tee() { + const left = []; + const right = []; + const iterator = this.iterator(); + const teeIterator = (queue) => { + return { + next: () => { + if (queue.length === 0) { + const result = iterator.next(); + left.push(result); + right.push(result); + } + return queue.shift(); + }, + }; + }; + return [ + new Stream(() => teeIterator(left), this.controller, this.client), + new Stream(() => teeIterator(right), this.controller, this.client), + ]; + } + /** + * Converts this stream to a newline-separated ReadableStream of + * JSON stringified values in the stream + * which can be turned back into a Stream with `Stream.fromReadableStream()`. + */ + toReadableStream() { + const self = this; + let iter; + return makeReadableStream({ + async start() { + iter = self[Symbol.asyncIterator](); + }, + async pull(ctrl) { + try { + const { value, done } = await iter.next(); + if (done) + return ctrl.close(); + const bytes = encodeUTF8(JSON.stringify(value) + '\n'); + ctrl.enqueue(bytes); + } + catch (err) { + ctrl.error(err); + } + }, + async cancel() { + var _a; + await ((_a = iter.return) === null || _a === void 0 ? void 0 : _a.call(iter)); + }, + }); + } +} +function _iterSSEMessages(response, controller) { + return __asyncGenerator(this, arguments, function* _iterSSEMessages_1() { + var _a, e_4, _b, _c; + if (!response.body) { + controller.abort(); + if (typeof globalThis.navigator !== 'undefined' && + globalThis.navigator.product === 'ReactNative') { + throw new GeminiNextGenAPIClientError(`The default react-native fetch implementation does not support streaming. Please use expo/fetch: https://docs.expo.dev/versions/latest/sdk/expo/#expofetch-api`); + } + throw new GeminiNextGenAPIClientError(`Attempted to iterate over a response with no body`); + } + const sseDecoder = new SSEDecoder(); + const lineDecoder = new LineDecoder(); + const iter = ReadableStreamToAsyncIterable(response.body); + try { + for (var _d = true, _e = __asyncValues(iterSSEChunks(iter)), _f; _f = yield __await(_e.next()), _a = _f.done, !_a; _d = true) { + _c = _f.value; + _d = false; + const sseChunk = _c; + for (const line of lineDecoder.decode(sseChunk)) { + const sse = sseDecoder.decode(line); + if (sse) + yield yield __await(sse); + } + } + } + catch (e_4_1) { e_4 = { error: e_4_1 }; } + finally { + try { + if (!_d && !_a && (_b = _e.return)) yield __await(_b.call(_e)); + } + finally { if (e_4) throw e_4.error; } + } + for (const line of lineDecoder.flush()) { + const sse = sseDecoder.decode(line); + if (sse) + yield yield __await(sse); + } + }); +} +/** + * Given an async iterable iterator, iterates over it and yields full + * SSE chunks, i.e. yields when a double new-line is encountered. + */ +function iterSSEChunks(iterator) { + return __asyncGenerator(this, arguments, function* iterSSEChunks_1() { + var _a, e_5, _b, _c; + let data = new Uint8Array(); + try { + for (var _d = true, iterator_3 = __asyncValues(iterator), iterator_3_1; iterator_3_1 = yield __await(iterator_3.next()), _a = iterator_3_1.done, !_a; _d = true) { + _c = iterator_3_1.value; + _d = false; + const chunk = _c; + if (chunk == null) { + continue; + } + const binaryChunk = chunk instanceof ArrayBuffer ? new Uint8Array(chunk) + : typeof chunk === 'string' ? encodeUTF8(chunk) + : chunk; + let newData = new Uint8Array(data.length + binaryChunk.length); + newData.set(data); + newData.set(binaryChunk, data.length); + data = newData; + let patternIndex; + while ((patternIndex = findDoubleNewlineIndex(data)) !== -1) { + yield yield __await(data.slice(0, patternIndex)); + data = data.slice(patternIndex); + } + } + } + catch (e_5_1) { e_5 = { error: e_5_1 }; } + finally { + try { + if (!_d && !_a && (_b = iterator_3.return)) yield __await(_b.call(iterator_3)); + } + finally { if (e_5) throw e_5.error; } + } + if (data.length > 0) { + yield yield __await(data); + } + }); +} +class SSEDecoder { + constructor() { + this.event = null; + this.data = []; + this.chunks = []; + } + decode(line) { + if (line.endsWith('\r')) { + line = line.substring(0, line.length - 1); + } + if (!line) { + // empty line and we didn't previously encounter any messages + if (!this.event && !this.data.length) + return null; + const sse = { + event: this.event, + data: this.data.join('\n'), + raw: this.chunks, + }; + this.event = null; + this.data = []; + this.chunks = []; + return sse; + } + this.chunks.push(line); + if (line.startsWith(':')) { + return null; + } + let [fieldname, _, value] = partition(line, ':'); + if (value.startsWith(' ')) { + value = value.substring(1); + } + if (fieldname === 'event') { + this.event = value; + } + else if (fieldname === 'data') { + this.data.push(value); + } + return null; + } +} +function partition(str, delimiter) { + const index = str.indexOf(delimiter); + if (index !== -1) { + return [str.substring(0, index), delimiter, str.substring(index + delimiter.length)]; + } + return [str, '', '']; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +async function defaultParseResponse(client, props) { + const { response, requestLogID, retryOfRequestLogID, startTime } = props; + const body = await (async () => { + var _a; + if (props.options.stream) { + loggerFor(client).debug('response', response.status, response.url, response.headers, response.body); + // Note: there is an invariant here that isn't represented in the type system + // that if you set `stream: true` the response type must also be `Stream<T>` + if (props.options.__streamClass) { + return props.options.__streamClass.fromSSEResponse(response, props.controller, client); + } + return Stream.fromSSEResponse(response, props.controller, client); + } + // fetch refuses to read the body when the status code is 204. + if (response.status === 204) { + return null; + } + if (props.options.__binaryResponse) { + return response; + } + const contentType = response.headers.get('content-type'); + const mediaType = (_a = contentType === null || contentType === void 0 ? void 0 : contentType.split(';')[0]) === null || _a === void 0 ? void 0 : _a.trim(); + const isJSON = (mediaType === null || mediaType === void 0 ? void 0 : mediaType.includes('application/json')) || (mediaType === null || mediaType === void 0 ? void 0 : mediaType.endsWith('+json')); + if (isJSON) { + const contentLength = response.headers.get('content-length'); + if (contentLength === '0') { + // if there is no content we can't do anything + return undefined; + } + const json = await response.json(); + return json; + } + const text = await response.text(); + return text; + })(); + loggerFor(client).debug(`[${requestLogID}] response parsed`, formatRequestDetails({ + retryOfRequestLogID, + url: response.url, + status: response.status, + body, + durationMs: Date.now() - startTime, + })); + return body; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * A subclass of `Promise` providing additional helper methods + * for interacting with the SDK. + */ +class APIPromise extends Promise { + constructor(client, responsePromise, parseResponse = defaultParseResponse) { + super((resolve) => { + // this is maybe a bit weird but this has to be a no-op to not implicitly + // parse the response body; instead .then, .catch, .finally are overridden + // to parse the response + resolve(null); + }); + this.responsePromise = responsePromise; + this.parseResponse = parseResponse; + this.client = client; + } + _thenUnwrap(transform) { + return new APIPromise(this.client, this.responsePromise, async (client, props) => transform(await this.parseResponse(client, props), props)); + } + /** + * Gets the raw `Response` instance instead of parsing the response + * data. + * + * If you want to parse the response body but still get the `Response` + * instance, you can use {@link withResponse()}. + * + * 👋 Getting the wrong TypeScript type for `Response`? + * Try setting `"moduleResolution": "NodeNext"` or add `"lib": ["DOM"]` + * to your `tsconfig.json`. + */ + asResponse() { + return this.responsePromise.then((p) => p.response); + } + /** + * Gets the parsed response data and the raw `Response` instance. + * + * If you just want to get the raw `Response` instance without parsing it, + * you can use {@link asResponse()}. + * + * 👋 Getting the wrong TypeScript type for `Response`? + * Try setting `"moduleResolution": "NodeNext"` or add `"lib": ["DOM"]` + * to your `tsconfig.json`. + */ + async withResponse() { + const [data, response] = await Promise.all([this.parse(), this.asResponse()]); + return { data, response }; + } + parse() { + if (!this.parsedPromise) { + this.parsedPromise = this.responsePromise.then((data) => this.parseResponse(this.client, data)); + } + return this.parsedPromise; + } + then(onfulfilled, onrejected) { + return this.parse().then(onfulfilled, onrejected); + } + catch(onrejected) { + return this.parse().catch(onrejected); + } + finally(onfinally) { + return this.parse().finally(onfinally); + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +const brand_privateNullableHeaders = /* @__PURE__ */ Symbol('brand.privateNullableHeaders'); +function* iterateHeaders(headers) { + if (!headers) + return; + if (brand_privateNullableHeaders in headers) { + const { values, nulls } = headers; + yield* values.entries(); + for (const name of nulls) { + yield [name, null]; + } + return; + } + let shouldClear = false; + let iter; + if (headers instanceof Headers) { + iter = headers.entries(); + } + else if (isReadonlyArray(headers)) { + iter = headers; + } + else { + shouldClear = true; + iter = Object.entries(headers !== null && headers !== void 0 ? headers : {}); + } + for (let row of iter) { + const name = row[0]; + if (typeof name !== 'string') + throw new TypeError('expected header name to be a string'); + const values = isReadonlyArray(row[1]) ? row[1] : [row[1]]; + let didClear = false; + for (const value of values) { + if (value === undefined) + continue; + // Objects keys always overwrite older headers, they never append. + // Yield a null to clear the header before adding the new values. + if (shouldClear && !didClear) { + didClear = true; + yield [name, null]; + } + yield [name, value]; + } + } +} +const buildHeaders = (newHeaders) => { + const targetHeaders = new Headers(); + const nullHeaders = new Set(); + for (const headers of newHeaders) { + const seenHeaders = new Set(); + for (const [name, value] of iterateHeaders(headers)) { + const lowerName = name.toLowerCase(); + if (!seenHeaders.has(lowerName)) { + targetHeaders.delete(name); + seenHeaders.add(lowerName); + } + if (value === null) { + targetHeaders.delete(name); + nullHeaders.add(lowerName); + } + else { + targetHeaders.append(name, value); + nullHeaders.delete(lowerName); + } + } + } + return { [brand_privateNullableHeaders]: true, values: targetHeaders, nulls: nullHeaders }; +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +/** + * Read an environment variable. + * + * Trims beginning and trailing whitespace. + * + * Will return undefined if the environment variable doesn't exist or cannot be accessed. + */ +const readEnv = (env) => { + var _a, _b, _c, _d, _e, _f; + if (typeof globalThis.process !== 'undefined') { + return (_c = (_b = (_a = globalThis.process.env) === null || _a === void 0 ? void 0 : _a[env]) === null || _b === void 0 ? void 0 : _b.trim()) !== null && _c !== void 0 ? _c : undefined; + } + if (typeof globalThis.Deno !== 'undefined') { + return (_f = (_e = (_d = globalThis.Deno.env) === null || _d === void 0 ? void 0 : _d.get) === null || _e === void 0 ? void 0 : _e.call(_d, env)) === null || _f === void 0 ? void 0 : _f.trim(); + } + return undefined; +}; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +var _a; +/** + * Base class for Gemini Next Gen API API clients. + */ +class BaseGeminiNextGenAPIClient { + /** + * API Client for interfacing with the Gemini Next Gen API API. + * + * @param {string | null | undefined} [opts.apiKey=process.env['GEMINI_API_KEY'] ?? null] + * @param {string | undefined} [opts.apiVersion=v1beta] + * @param {string} [opts.baseURL=process.env['GEMINI_NEXT_GEN_API_BASE_URL'] ?? https://generativelanguage.googleapis.com] - Override the default base URL for the API. + * @param {number} [opts.timeout=1 minute] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out. + * @param {MergedRequestInit} [opts.fetchOptions] - Additional `RequestInit` options to be passed to `fetch` calls. + * @param {Fetch} [opts.fetch] - Specify a custom `fetch` function implementation. + * @param {number} [opts.maxRetries=2] - The maximum number of times the client will retry a request. + * @param {HeadersLike} opts.defaultHeaders - Default headers to include with every request to the API. + * @param {Record<string, string | undefined>} opts.defaultQuery - Default query parameters to include with every request to the API. + */ + constructor(_b) { + var _c, _d, _e, _f, _g, _h, _j; + var { baseURL = readEnv('GEMINI_NEXT_GEN_API_BASE_URL'), apiKey = (_c = readEnv('GEMINI_API_KEY')) !== null && _c !== void 0 ? _c : null, apiVersion = 'v1beta' } = _b, opts = __rest(_b, ["baseURL", "apiKey", "apiVersion"]); + const options = Object.assign(Object.assign({ apiKey, + apiVersion }, opts), { baseURL: baseURL || `https://generativelanguage.googleapis.com` }); + this.baseURL = options.baseURL; + this.timeout = (_d = options.timeout) !== null && _d !== void 0 ? _d : BaseGeminiNextGenAPIClient.DEFAULT_TIMEOUT /* 1 minute */; + this.logger = (_e = options.logger) !== null && _e !== void 0 ? _e : console; + const defaultLogLevel = 'warn'; + // Set default logLevel early so that we can log a warning in parseLogLevel. + this.logLevel = defaultLogLevel; + this.logLevel = + (_g = (_f = parseLogLevel(options.logLevel, 'ClientOptions.logLevel', this)) !== null && _f !== void 0 ? _f : parseLogLevel(readEnv('GEMINI_NEXT_GEN_API_LOG'), "process.env['GEMINI_NEXT_GEN_API_LOG']", this)) !== null && _g !== void 0 ? _g : defaultLogLevel; + this.fetchOptions = options.fetchOptions; + this.maxRetries = (_h = options.maxRetries) !== null && _h !== void 0 ? _h : 2; + this.fetch = (_j = options.fetch) !== null && _j !== void 0 ? _j : getDefaultFetch(); + this.encoder = FallbackEncoder; + this._options = options; + this.apiKey = apiKey; + this.apiVersion = apiVersion; + this.clientAdapter = options.clientAdapter; + } + /** + * Create a new client instance re-using the same options given to the current client with optional overriding. + */ + withOptions(options) { + const client = new this.constructor(Object.assign(Object.assign(Object.assign({}, this._options), { baseURL: this.baseURL, maxRetries: this.maxRetries, timeout: this.timeout, logger: this.logger, logLevel: this.logLevel, fetch: this.fetch, fetchOptions: this.fetchOptions, apiKey: this.apiKey, apiVersion: this.apiVersion }), options)); + return client; + } + /** + * Check whether the base URL is set to its default. + */ + baseURLOverridden() { + return this.baseURL !== 'https://generativelanguage.googleapis.com'; + } + defaultQuery() { + return this._options.defaultQuery; + } + validateHeaders({ values, nulls }) { + // The headers object handles case insensitivity. + if (values.has('authorization') || values.has('x-goog-api-key')) { + return; + } + if (this.apiKey && values.get('x-goog-api-key')) { + return; + } + if (nulls.has('x-goog-api-key')) { + return; + } + throw new Error('Could not resolve authentication method. Expected the apiKey to be set. Or for the "x-goog-api-key" headers to be explicitly omitted'); + } + async authHeaders(opts) { + const existingHeaders = buildHeaders([opts.headers]); + if (existingHeaders.values.has('authorization') || existingHeaders.values.has('x-goog-api-key')) { + return undefined; + } + if (this.apiKey) { + return buildHeaders([{ 'x-goog-api-key': this.apiKey }]); + } + if (this.clientAdapter.isVertexAI()) { + return buildHeaders([await this.clientAdapter.getAuthHeaders()]); + } + return undefined; + } + /** + * Basic re-implementation of `qs.stringify` for primitive types. + */ + stringifyQuery(query) { + return Object.entries(query) + .filter(([_, value]) => typeof value !== 'undefined') + .map(([key, value]) => { + if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { + return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`; + } + if (value === null) { + return `${encodeURIComponent(key)}=`; + } + throw new GeminiNextGenAPIClientError(`Cannot stringify type ${typeof value}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`); + }) + .join('&'); + } + getUserAgent() { + return `${this.constructor.name}/JS ${VERSION}`; + } + defaultIdempotencyKey() { + return `stainless-node-retry-${uuid4()}`; + } + makeStatusError(status, error, message, headers) { + return APIError.generate(status, error, message, headers); + } + buildURL(path, query, defaultBaseURL) { + const baseURL = (!this.baseURLOverridden() && defaultBaseURL) || this.baseURL; + const url = isAbsoluteURL(path) ? + new URL(path) + : new URL(baseURL + (baseURL.endsWith('/') && path.startsWith('/') ? path.slice(1) : path)); + const defaultQuery = this.defaultQuery(); + if (!isEmptyObj(defaultQuery)) { + query = Object.assign(Object.assign({}, defaultQuery), query); + } + if (typeof query === 'object' && query && !Array.isArray(query)) { + url.search = this.stringifyQuery(query); + } + return url.toString(); + } + /** + * Used as a callback for mutating the given `FinalRequestOptions` object. + + */ + async prepareOptions(options) { + if (this.clientAdapter && + this.clientAdapter.isVertexAI() && + !options.path.startsWith(`/${this.apiVersion}/projects/`)) { + const oldPath = options.path.slice(this.apiVersion.length + 1); + options.path = `/${this.apiVersion}/projects/${this.clientAdapter.getProject()}/locations/${this.clientAdapter.getLocation()}${oldPath}`; + } + } + /** + * Used as a callback for mutating the given `RequestInit` object. + * + * This is useful for cases where you want to add certain headers based off of + * the request properties, e.g. `method` or `url`. + */ + async prepareRequest(request, { url, options }) { } + get(path, opts) { + return this.methodRequest('get', path, opts); + } + post(path, opts) { + return this.methodRequest('post', path, opts); + } + patch(path, opts) { + return this.methodRequest('patch', path, opts); + } + put(path, opts) { + return this.methodRequest('put', path, opts); + } + delete(path, opts) { + return this.methodRequest('delete', path, opts); + } + methodRequest(method, path, opts) { + return this.request(Promise.resolve(opts).then((opts) => { + return Object.assign({ method, path }, opts); + })); + } + request(options, remainingRetries = null) { + return new APIPromise(this, this.makeRequest(options, remainingRetries, undefined)); + } + async makeRequest(optionsInput, retriesRemaining, retryOfRequestLogID) { + var _b, _c, _d; + const options = await optionsInput; + const maxRetries = (_b = options.maxRetries) !== null && _b !== void 0 ? _b : this.maxRetries; + if (retriesRemaining == null) { + retriesRemaining = maxRetries; + } + await this.prepareOptions(options); + const { req, url, timeout } = await this.buildRequest(options, { + retryCount: maxRetries - retriesRemaining, + }); + await this.prepareRequest(req, { url, options }); + /** Not an API request ID, just for correlating local log entries. */ + const requestLogID = 'log_' + ((Math.random() * (1 << 24)) | 0).toString(16).padStart(6, '0'); + const retryLogStr = retryOfRequestLogID === undefined ? '' : `, retryOf: ${retryOfRequestLogID}`; + const startTime = Date.now(); + loggerFor(this).debug(`[${requestLogID}] sending request`, formatRequestDetails({ + retryOfRequestLogID, + method: options.method, + url, + options, + headers: req.headers, + })); + if ((_c = options.signal) === null || _c === void 0 ? void 0 : _c.aborted) { + throw new APIUserAbortError(); + } + const controller = new AbortController(); + const response = await this.fetchWithTimeout(url, req, timeout, controller).catch(castToError); + const headersTime = Date.now(); + if (response instanceof globalThis.Error) { + const retryMessage = `retrying, ${retriesRemaining} attempts remaining`; + if ((_d = options.signal) === null || _d === void 0 ? void 0 : _d.aborted) { + throw new APIUserAbortError(); + } + // detect native connection timeout errors + // deno throws "TypeError: error sending request for url (https://example/): client error (Connect): tcp connect error: Operation timed out (os error 60): Operation timed out (os error 60)" + // undici throws "TypeError: fetch failed" with cause "ConnectTimeoutError: Connect Timeout Error (attempted address: example:443, timeout: 1ms)" + // others do not provide enough information to distinguish timeouts from other connection errors + const isTimeout = isAbortError(response) || + /timed? ?out/i.test(String(response) + ('cause' in response ? String(response.cause) : '')); + if (retriesRemaining) { + loggerFor(this).info(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - ${retryMessage}`); + loggerFor(this).debug(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (${retryMessage})`, formatRequestDetails({ + retryOfRequestLogID, + url, + durationMs: headersTime - startTime, + message: response.message, + })); + return this.retryRequest(options, retriesRemaining, retryOfRequestLogID !== null && retryOfRequestLogID !== void 0 ? retryOfRequestLogID : requestLogID); + } + loggerFor(this).info(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - error; no more retries left`); + loggerFor(this).debug(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (error; no more retries left)`, formatRequestDetails({ + retryOfRequestLogID, + url, + durationMs: headersTime - startTime, + message: response.message, + })); + if (isTimeout) { + throw new APIConnectionTimeoutError(); + } + throw new APIConnectionError({ cause: response }); + } + const responseInfo = `[${requestLogID}${retryLogStr}] ${req.method} ${url} ${response.ok ? 'succeeded' : 'failed'} with status ${response.status} in ${headersTime - startTime}ms`; + if (!response.ok) { + const shouldRetry = await this.shouldRetry(response); + if (retriesRemaining && shouldRetry) { + const retryMessage = `retrying, ${retriesRemaining} attempts remaining`; + // We don't need the body of this response. + await CancelReadableStream(response.body); + loggerFor(this).info(`${responseInfo} - ${retryMessage}`); + loggerFor(this).debug(`[${requestLogID}] response error (${retryMessage})`, formatRequestDetails({ + retryOfRequestLogID, + url: response.url, + status: response.status, + headers: response.headers, + durationMs: headersTime - startTime, + })); + return this.retryRequest(options, retriesRemaining, retryOfRequestLogID !== null && retryOfRequestLogID !== void 0 ? retryOfRequestLogID : requestLogID, response.headers); + } + const retryMessage = shouldRetry ? `error; no more retries left` : `error; not retryable`; + loggerFor(this).info(`${responseInfo} - ${retryMessage}`); + const errText = await response.text().catch((err) => castToError(err).message); + const errJSON = safeJSON(errText); + const errMessage = errJSON ? undefined : errText; + loggerFor(this).debug(`[${requestLogID}] response error (${retryMessage})`, formatRequestDetails({ + retryOfRequestLogID, + url: response.url, + status: response.status, + headers: response.headers, + message: errMessage, + durationMs: Date.now() - startTime, + })); + // @ts-ignore + const err = this.makeStatusError(response.status, errJSON, errMessage, response.headers); + throw err; + } + loggerFor(this).info(responseInfo); + loggerFor(this).debug(`[${requestLogID}] response start`, formatRequestDetails({ + retryOfRequestLogID, + url: response.url, + status: response.status, + headers: response.headers, + durationMs: headersTime - startTime, + })); + return { response, options, controller, requestLogID, retryOfRequestLogID, startTime }; + } + async fetchWithTimeout(url, init, ms, controller) { + const _b = init || {}, { signal, method } = _b, options = __rest(_b, ["signal", "method"]); + const abort = this._makeAbort(controller); + if (signal) + signal.addEventListener('abort', abort, { once: true }); + const timeout = setTimeout(abort, ms); + const isReadableBody = (globalThis.ReadableStream && options.body instanceof globalThis.ReadableStream) || + (typeof options.body === 'object' && options.body !== null && Symbol.asyncIterator in options.body); + const fetchOptions = Object.assign(Object.assign(Object.assign({ signal: controller.signal }, (isReadableBody ? { duplex: 'half' } : {})), { method: 'GET' }), options); + if (method) { + // Custom methods like 'patch' need to be uppercased + // See https://github.com/nodejs/undici/issues/2294 + fetchOptions.method = method.toUpperCase(); + } + try { + // use undefined this binding; fetch errors if bound to something else in browser/cloudflare + return await this.fetch.call(undefined, url, fetchOptions); + } + finally { + clearTimeout(timeout); + } + } + async shouldRetry(response) { + // Note this is not a standard header. + const shouldRetryHeader = response.headers.get('x-should-retry'); + // If the server explicitly says whether or not to retry, obey. + if (shouldRetryHeader === 'true') + return true; + if (shouldRetryHeader === 'false') + return false; + // Retry on request timeouts. + if (response.status === 408) + return true; + // Retry on lock timeouts. + if (response.status === 409) + return true; + // Retry on rate limits. + if (response.status === 429) + return true; + // Retry internal errors. + if (response.status >= 500) + return true; + return false; + } + async retryRequest(options, retriesRemaining, requestLogID, responseHeaders) { + var _b; + let timeoutMillis; + // Note the `retry-after-ms` header may not be standard, but is a good idea and we'd like proactive support for it. + const retryAfterMillisHeader = responseHeaders === null || responseHeaders === void 0 ? void 0 : responseHeaders.get('retry-after-ms'); + if (retryAfterMillisHeader) { + const timeoutMs = parseFloat(retryAfterMillisHeader); + if (!Number.isNaN(timeoutMs)) { + timeoutMillis = timeoutMs; + } + } + // About the Retry-After header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After + const retryAfterHeader = responseHeaders === null || responseHeaders === void 0 ? void 0 : responseHeaders.get('retry-after'); + if (retryAfterHeader && !timeoutMillis) { + const timeoutSeconds = parseFloat(retryAfterHeader); + if (!Number.isNaN(timeoutSeconds)) { + timeoutMillis = timeoutSeconds * 1000; + } + else { + timeoutMillis = Date.parse(retryAfterHeader) - Date.now(); + } + } + // If the API asks us to wait a certain amount of time (and it's a reasonable amount), + // just do what it says, but otherwise calculate a default + if (!(timeoutMillis && 0 <= timeoutMillis && timeoutMillis < 60 * 1000)) { + const maxRetries = (_b = options.maxRetries) !== null && _b !== void 0 ? _b : this.maxRetries; + timeoutMillis = this.calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries); + } + await sleep$1(timeoutMillis); + return this.makeRequest(options, retriesRemaining - 1, requestLogID); + } + calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries) { + const initialRetryDelay = 0.5; + const maxRetryDelay = 8.0; + const numRetries = maxRetries - retriesRemaining; + // Apply exponential backoff, but not more than the max. + const sleepSeconds = Math.min(initialRetryDelay * Math.pow(2, numRetries), maxRetryDelay); + // Apply some jitter, take up to at most 25 percent of the retry time. + const jitter = 1 - Math.random() * 0.25; + return sleepSeconds * jitter * 1000; + } + async buildRequest(inputOptions, { retryCount = 0 } = {}) { + var _b, _c, _d; + const options = Object.assign({}, inputOptions); + const { method, path, query, defaultBaseURL } = options; + const url = this.buildURL(path, query, defaultBaseURL); + if ('timeout' in options) + validatePositiveInteger('timeout', options.timeout); + options.timeout = (_b = options.timeout) !== null && _b !== void 0 ? _b : this.timeout; + const { bodyHeaders, body } = this.buildBody({ options }); + const reqHeaders = await this.buildHeaders({ options: inputOptions, method, bodyHeaders, retryCount }); + const req = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ method, headers: reqHeaders }, (options.signal && { signal: options.signal })), (globalThis.ReadableStream && + body instanceof globalThis.ReadableStream && { duplex: 'half' })), (body && { body })), ((_c = this.fetchOptions) !== null && _c !== void 0 ? _c : {})), ((_d = options.fetchOptions) !== null && _d !== void 0 ? _d : {})); + return { req, url, timeout: options.timeout }; + } + async buildHeaders({ options, method, bodyHeaders, retryCount, }) { + let idempotencyHeaders = {}; + if (this.idempotencyHeader && method !== 'get') { + if (!options.idempotencyKey) + options.idempotencyKey = this.defaultIdempotencyKey(); + idempotencyHeaders[this.idempotencyHeader] = options.idempotencyKey; + } + const authHeaders = await this.authHeaders(options); + let headers = buildHeaders([ + idempotencyHeaders, + Object.assign(Object.assign({ Accept: 'application/json', 'User-Agent': this.getUserAgent(), 'X-Stainless-Retry-Count': String(retryCount) }, (options.timeout ? { 'X-Stainless-Timeout': String(Math.trunc(options.timeout / 1000)) } : {})), getPlatformHeaders()), + this._options.defaultHeaders, + bodyHeaders, + options.headers, + authHeaders, + ]); + this.validateHeaders(headers); + return headers.values; + } + _makeAbort(controller) { + // note: we can't just inline this method inside `fetchWithTimeout()` because then the closure + // would capture all request options, and cause a memory leak. + return () => controller.abort(); + } + buildBody({ options: { body, headers: rawHeaders } }) { + if (!body) { + return { bodyHeaders: undefined, body: undefined }; + } + const headers = buildHeaders([rawHeaders]); + if ( + // Pass raw type verbatim + ArrayBuffer.isView(body) || + body instanceof ArrayBuffer || + body instanceof DataView || + (typeof body === 'string' && + // Preserve legacy string encoding behavior for now + headers.values.has('content-type')) || + // `Blob` is superset of `File` + (globalThis.Blob && body instanceof globalThis.Blob) || + // `FormData` -> `multipart/form-data` + body instanceof FormData || + // `URLSearchParams` -> `application/x-www-form-urlencoded` + body instanceof URLSearchParams || + // Send chunked stream (each chunk has own `length`) + (globalThis.ReadableStream && body instanceof globalThis.ReadableStream)) { + return { bodyHeaders: undefined, body: body }; + } + else if (typeof body === 'object' && + (Symbol.asyncIterator in body || + (Symbol.iterator in body && 'next' in body && typeof body.next === 'function'))) { + return { bodyHeaders: undefined, body: ReadableStreamFrom(body) }; + } + else { + return this.encoder({ body, headers }); + } + } +} +BaseGeminiNextGenAPIClient.DEFAULT_TIMEOUT = 60000; // 1 minute +/** + * API Client for interfacing with the Gemini Next Gen API API. + */ +class GeminiNextGenAPIClient extends BaseGeminiNextGenAPIClient { + constructor() { + super(...arguments); + this.interactions = new Interactions(this); + } +} +_a = GeminiNextGenAPIClient; +GeminiNextGenAPIClient.GeminiNextGenAPIClient = _a; +GeminiNextGenAPIClient.GeminiNextGenAPIClientError = GeminiNextGenAPIClientError; +GeminiNextGenAPIClient.APIError = APIError; +GeminiNextGenAPIClient.APIConnectionError = APIConnectionError; +GeminiNextGenAPIClient.APIConnectionTimeoutError = APIConnectionTimeoutError; +GeminiNextGenAPIClient.APIUserAbortError = APIUserAbortError; +GeminiNextGenAPIClient.NotFoundError = NotFoundError; +GeminiNextGenAPIClient.ConflictError = ConflictError; +GeminiNextGenAPIClient.RateLimitError = RateLimitError; +GeminiNextGenAPIClient.BadRequestError = BadRequestError; +GeminiNextGenAPIClient.AuthenticationError = AuthenticationError; +GeminiNextGenAPIClient.InternalServerError = InternalServerError; +GeminiNextGenAPIClient.PermissionDeniedError = PermissionDeniedError; +GeminiNextGenAPIClient.UnprocessableEntityError = UnprocessableEntityError; +GeminiNextGenAPIClient.toFile = toFile; +GeminiNextGenAPIClient.Interactions = Interactions; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// Code generated by the Google Gen AI SDK generator DO NOT EDIT. +function cancelTuningJobParametersToMldev(fromObject, _rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + return toObject; +} +function cancelTuningJobParametersToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + return toObject; +} +function cancelTuningJobResponseFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function cancelTuningJobResponseFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + return toObject; +} +function createTuningJobConfigToMldev(fromObject, parentObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['validationDataset']) !== undefined) { + throw new Error('validationDataset parameter is not supported in Gemini API.'); + } + const fromTunedModelDisplayName = getValueByPath(fromObject, [ + 'tunedModelDisplayName', + ]); + if (parentObject !== undefined && fromTunedModelDisplayName != null) { + setValueByPath(parentObject, ['displayName'], fromTunedModelDisplayName); + } + if (getValueByPath(fromObject, ['description']) !== undefined) { + throw new Error('description parameter is not supported in Gemini API.'); + } + const fromEpochCount = getValueByPath(fromObject, ['epochCount']); + if (parentObject !== undefined && fromEpochCount != null) { + setValueByPath(parentObject, ['tuningTask', 'hyperparameters', 'epochCount'], fromEpochCount); + } + const fromLearningRateMultiplier = getValueByPath(fromObject, [ + 'learningRateMultiplier', + ]); + if (fromLearningRateMultiplier != null) { + setValueByPath(toObject, ['tuningTask', 'hyperparameters', 'learningRateMultiplier'], fromLearningRateMultiplier); + } + if (getValueByPath(fromObject, ['exportLastCheckpointOnly']) !== + undefined) { + throw new Error('exportLastCheckpointOnly parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['preTunedModelCheckpointId']) !== + undefined) { + throw new Error('preTunedModelCheckpointId parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['adapterSize']) !== undefined) { + throw new Error('adapterSize parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['tuningMode']) !== undefined) { + throw new Error('tuningMode parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['customBaseModel']) !== undefined) { + throw new Error('customBaseModel parameter is not supported in Gemini API.'); + } + const fromBatchSize = getValueByPath(fromObject, ['batchSize']); + if (parentObject !== undefined && fromBatchSize != null) { + setValueByPath(parentObject, ['tuningTask', 'hyperparameters', 'batchSize'], fromBatchSize); + } + const fromLearningRate = getValueByPath(fromObject, ['learningRate']); + if (parentObject !== undefined && fromLearningRate != null) { + setValueByPath(parentObject, ['tuningTask', 'hyperparameters', 'learningRate'], fromLearningRate); + } + if (getValueByPath(fromObject, ['labels']) !== undefined) { + throw new Error('labels parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['beta']) !== undefined) { + throw new Error('beta parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['baseTeacherModel']) !== undefined) { + throw new Error('baseTeacherModel parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['tunedTeacherModelSource']) !== undefined) { + throw new Error('tunedTeacherModelSource parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['sftLossWeightMultiplier']) !== undefined) { + throw new Error('sftLossWeightMultiplier parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['outputUri']) !== undefined) { + throw new Error('outputUri parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['encryptionSpec']) !== undefined) { + throw new Error('encryptionSpec parameter is not supported in Gemini API.'); + } + return toObject; +} +function createTuningJobConfigToVertex(fromObject, parentObject, rootObject) { + const toObject = {}; + let discriminatorValidationDataset = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorValidationDataset === undefined) { + discriminatorValidationDataset = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorValidationDataset === 'SUPERVISED_FINE_TUNING') { + const fromValidationDataset = getValueByPath(fromObject, [ + 'validationDataset', + ]); + if (parentObject !== undefined && fromValidationDataset != null) { + setValueByPath(parentObject, ['supervisedTuningSpec'], tuningValidationDatasetToVertex(fromValidationDataset)); + } + } + else if (discriminatorValidationDataset === 'PREFERENCE_TUNING') { + const fromValidationDataset = getValueByPath(fromObject, [ + 'validationDataset', + ]); + if (parentObject !== undefined && fromValidationDataset != null) { + setValueByPath(parentObject, ['preferenceOptimizationSpec'], tuningValidationDatasetToVertex(fromValidationDataset)); + } + } + else if (discriminatorValidationDataset === 'DISTILLATION') { + const fromValidationDataset = getValueByPath(fromObject, [ + 'validationDataset', + ]); + if (parentObject !== undefined && fromValidationDataset != null) { + setValueByPath(parentObject, ['distillationSpec'], tuningValidationDatasetToVertex(fromValidationDataset)); + } + } + const fromTunedModelDisplayName = getValueByPath(fromObject, [ + 'tunedModelDisplayName', + ]); + if (parentObject !== undefined && fromTunedModelDisplayName != null) { + setValueByPath(parentObject, ['tunedModelDisplayName'], fromTunedModelDisplayName); + } + const fromDescription = getValueByPath(fromObject, ['description']); + if (parentObject !== undefined && fromDescription != null) { + setValueByPath(parentObject, ['description'], fromDescription); + } + let discriminatorEpochCount = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorEpochCount === undefined) { + discriminatorEpochCount = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorEpochCount === 'SUPERVISED_FINE_TUNING') { + const fromEpochCount = getValueByPath(fromObject, ['epochCount']); + if (parentObject !== undefined && fromEpochCount != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'hyperParameters', 'epochCount'], fromEpochCount); + } + } + else if (discriminatorEpochCount === 'PREFERENCE_TUNING') { + const fromEpochCount = getValueByPath(fromObject, ['epochCount']); + if (parentObject !== undefined && fromEpochCount != null) { + setValueByPath(parentObject, ['preferenceOptimizationSpec', 'hyperParameters', 'epochCount'], fromEpochCount); + } + } + else if (discriminatorEpochCount === 'DISTILLATION') { + const fromEpochCount = getValueByPath(fromObject, ['epochCount']); + if (parentObject !== undefined && fromEpochCount != null) { + setValueByPath(parentObject, ['distillationSpec', 'hyperParameters', 'epochCount'], fromEpochCount); + } + } + let discriminatorLearningRateMultiplier = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorLearningRateMultiplier === undefined) { + discriminatorLearningRateMultiplier = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorLearningRateMultiplier === 'SUPERVISED_FINE_TUNING') { + const fromLearningRateMultiplier = getValueByPath(fromObject, [ + 'learningRateMultiplier', + ]); + if (parentObject !== undefined && fromLearningRateMultiplier != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'hyperParameters', 'learningRateMultiplier'], fromLearningRateMultiplier); + } + } + else if (discriminatorLearningRateMultiplier === 'PREFERENCE_TUNING') { + const fromLearningRateMultiplier = getValueByPath(fromObject, [ + 'learningRateMultiplier', + ]); + if (parentObject !== undefined && fromLearningRateMultiplier != null) { + setValueByPath(parentObject, [ + 'preferenceOptimizationSpec', + 'hyperParameters', + 'learningRateMultiplier', + ], fromLearningRateMultiplier); + } + } + else if (discriminatorLearningRateMultiplier === 'DISTILLATION') { + const fromLearningRateMultiplier = getValueByPath(fromObject, [ + 'learningRateMultiplier', + ]); + if (parentObject !== undefined && fromLearningRateMultiplier != null) { + setValueByPath(parentObject, ['distillationSpec', 'hyperParameters', 'learningRateMultiplier'], fromLearningRateMultiplier); + } + } + let discriminatorExportLastCheckpointOnly = getValueByPath(rootObject, ['config', 'method']); + if (discriminatorExportLastCheckpointOnly === undefined) { + discriminatorExportLastCheckpointOnly = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorExportLastCheckpointOnly === 'SUPERVISED_FINE_TUNING') { + const fromExportLastCheckpointOnly = getValueByPath(fromObject, [ + 'exportLastCheckpointOnly', + ]); + if (parentObject !== undefined && fromExportLastCheckpointOnly != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'exportLastCheckpointOnly'], fromExportLastCheckpointOnly); + } + } + else if (discriminatorExportLastCheckpointOnly === 'PREFERENCE_TUNING') { + const fromExportLastCheckpointOnly = getValueByPath(fromObject, [ + 'exportLastCheckpointOnly', + ]); + if (parentObject !== undefined && fromExportLastCheckpointOnly != null) { + setValueByPath(parentObject, ['preferenceOptimizationSpec', 'exportLastCheckpointOnly'], fromExportLastCheckpointOnly); + } + } + else if (discriminatorExportLastCheckpointOnly === 'DISTILLATION') { + const fromExportLastCheckpointOnly = getValueByPath(fromObject, [ + 'exportLastCheckpointOnly', + ]); + if (parentObject !== undefined && fromExportLastCheckpointOnly != null) { + setValueByPath(parentObject, ['distillationSpec', 'exportLastCheckpointOnly'], fromExportLastCheckpointOnly); + } + } + let discriminatorAdapterSize = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorAdapterSize === undefined) { + discriminatorAdapterSize = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorAdapterSize === 'SUPERVISED_FINE_TUNING') { + const fromAdapterSize = getValueByPath(fromObject, ['adapterSize']); + if (parentObject !== undefined && fromAdapterSize != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'hyperParameters', 'adapterSize'], fromAdapterSize); + } + } + else if (discriminatorAdapterSize === 'PREFERENCE_TUNING') { + const fromAdapterSize = getValueByPath(fromObject, ['adapterSize']); + if (parentObject !== undefined && fromAdapterSize != null) { + setValueByPath(parentObject, ['preferenceOptimizationSpec', 'hyperParameters', 'adapterSize'], fromAdapterSize); + } + } + else if (discriminatorAdapterSize === 'DISTILLATION') { + const fromAdapterSize = getValueByPath(fromObject, ['adapterSize']); + if (parentObject !== undefined && fromAdapterSize != null) { + setValueByPath(parentObject, ['distillationSpec', 'hyperParameters', 'adapterSize'], fromAdapterSize); + } + } + let discriminatorTuningMode = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorTuningMode === undefined) { + discriminatorTuningMode = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorTuningMode === 'SUPERVISED_FINE_TUNING') { + const fromTuningMode = getValueByPath(fromObject, ['tuningMode']); + if (parentObject !== undefined && fromTuningMode != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'tuningMode'], fromTuningMode); + } + } + const fromCustomBaseModel = getValueByPath(fromObject, [ + 'customBaseModel', + ]); + if (parentObject !== undefined && fromCustomBaseModel != null) { + setValueByPath(parentObject, ['customBaseModel'], fromCustomBaseModel); + } + let discriminatorBatchSize = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorBatchSize === undefined) { + discriminatorBatchSize = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorBatchSize === 'SUPERVISED_FINE_TUNING') { + const fromBatchSize = getValueByPath(fromObject, ['batchSize']); + if (parentObject !== undefined && fromBatchSize != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'hyperParameters', 'batchSize'], fromBatchSize); + } + } + let discriminatorLearningRate = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorLearningRate === undefined) { + discriminatorLearningRate = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorLearningRate === 'SUPERVISED_FINE_TUNING') { + const fromLearningRate = getValueByPath(fromObject, [ + 'learningRate', + ]); + if (parentObject !== undefined && fromLearningRate != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'hyperParameters', 'learningRate'], fromLearningRate); + } + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (parentObject !== undefined && fromLabels != null) { + setValueByPath(parentObject, ['labels'], fromLabels); + } + const fromBeta = getValueByPath(fromObject, ['beta']); + if (parentObject !== undefined && fromBeta != null) { + setValueByPath(parentObject, ['preferenceOptimizationSpec', 'hyperParameters', 'beta'], fromBeta); + } + const fromBaseTeacherModel = getValueByPath(fromObject, [ + 'baseTeacherModel', + ]); + if (parentObject !== undefined && fromBaseTeacherModel != null) { + setValueByPath(parentObject, ['distillationSpec', 'baseTeacherModel'], fromBaseTeacherModel); + } + const fromTunedTeacherModelSource = getValueByPath(fromObject, [ + 'tunedTeacherModelSource', + ]); + if (parentObject !== undefined && fromTunedTeacherModelSource != null) { + setValueByPath(parentObject, ['distillationSpec', 'tunedTeacherModelSource'], fromTunedTeacherModelSource); + } + const fromSftLossWeightMultiplier = getValueByPath(fromObject, [ + 'sftLossWeightMultiplier', + ]); + if (parentObject !== undefined && fromSftLossWeightMultiplier != null) { + setValueByPath(parentObject, ['distillationSpec', 'hyperParameters', 'sftLossWeightMultiplier'], fromSftLossWeightMultiplier); + } + const fromOutputUri = getValueByPath(fromObject, ['outputUri']); + if (parentObject !== undefined && fromOutputUri != null) { + setValueByPath(parentObject, ['outputUri'], fromOutputUri); + } + const fromEncryptionSpec = getValueByPath(fromObject, [ + 'encryptionSpec', + ]); + if (parentObject !== undefined && fromEncryptionSpec != null) { + setValueByPath(parentObject, ['encryptionSpec'], fromEncryptionSpec); + } + return toObject; +} +function createTuningJobParametersPrivateToMldev(fromObject, rootObject) { + const toObject = {}; + const fromBaseModel = getValueByPath(fromObject, ['baseModel']); + if (fromBaseModel != null) { + setValueByPath(toObject, ['baseModel'], fromBaseModel); + } + const fromPreTunedModel = getValueByPath(fromObject, [ + 'preTunedModel', + ]); + if (fromPreTunedModel != null) { + setValueByPath(toObject, ['preTunedModel'], fromPreTunedModel); + } + const fromTrainingDataset = getValueByPath(fromObject, [ + 'trainingDataset', + ]); + if (fromTrainingDataset != null) { + tuningDatasetToMldev(fromTrainingDataset); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createTuningJobConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function createTuningJobParametersPrivateToVertex(fromObject, rootObject) { + const toObject = {}; + const fromBaseModel = getValueByPath(fromObject, ['baseModel']); + if (fromBaseModel != null) { + setValueByPath(toObject, ['baseModel'], fromBaseModel); + } + const fromPreTunedModel = getValueByPath(fromObject, [ + 'preTunedModel', + ]); + if (fromPreTunedModel != null) { + setValueByPath(toObject, ['preTunedModel'], fromPreTunedModel); + } + const fromTrainingDataset = getValueByPath(fromObject, [ + 'trainingDataset', + ]); + if (fromTrainingDataset != null) { + tuningDatasetToVertex(fromTrainingDataset, toObject, rootObject); + } + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + createTuningJobConfigToVertex(fromConfig, toObject, rootObject); + } + return toObject; +} +function getTuningJobParametersToMldev(fromObject, _rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + return toObject; +} +function getTuningJobParametersToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['_url', 'name'], fromName); + } + return toObject; +} +function listTuningJobsConfigToMldev(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + const fromFilter = getValueByPath(fromObject, ['filter']); + if (parentObject !== undefined && fromFilter != null) { + setValueByPath(parentObject, ['_query', 'filter'], fromFilter); + } + return toObject; +} +function listTuningJobsConfigToVertex(fromObject, parentObject, _rootObject) { + const toObject = {}; + const fromPageSize = getValueByPath(fromObject, ['pageSize']); + if (parentObject !== undefined && fromPageSize != null) { + setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize); + } + const fromPageToken = getValueByPath(fromObject, ['pageToken']); + if (parentObject !== undefined && fromPageToken != null) { + setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken); + } + const fromFilter = getValueByPath(fromObject, ['filter']); + if (parentObject !== undefined && fromFilter != null) { + setValueByPath(parentObject, ['_query', 'filter'], fromFilter); + } + return toObject; +} +function listTuningJobsParametersToMldev(fromObject, rootObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listTuningJobsConfigToMldev(fromConfig, toObject); + } + return toObject; +} +function listTuningJobsParametersToVertex(fromObject, rootObject) { + const toObject = {}; + const fromConfig = getValueByPath(fromObject, ['config']); + if (fromConfig != null) { + listTuningJobsConfigToVertex(fromConfig, toObject); + } + return toObject; +} +function listTuningJobsResponseFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromTuningJobs = getValueByPath(fromObject, ['tunedModels']); + if (fromTuningJobs != null) { + let transformedList = fromTuningJobs; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return tuningJobFromMldev(item); + }); + } + setValueByPath(toObject, ['tuningJobs'], transformedList); + } + return toObject; +} +function listTuningJobsResponseFromVertex(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromNextPageToken = getValueByPath(fromObject, [ + 'nextPageToken', + ]); + if (fromNextPageToken != null) { + setValueByPath(toObject, ['nextPageToken'], fromNextPageToken); + } + const fromTuningJobs = getValueByPath(fromObject, ['tuningJobs']); + if (fromTuningJobs != null) { + let transformedList = fromTuningJobs; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return tuningJobFromVertex(item); + }); + } + setValueByPath(toObject, ['tuningJobs'], transformedList); + } + return toObject; +} +function tunedModelFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromModel = getValueByPath(fromObject, ['name']); + if (fromModel != null) { + setValueByPath(toObject, ['model'], fromModel); + } + const fromEndpoint = getValueByPath(fromObject, ['name']); + if (fromEndpoint != null) { + setValueByPath(toObject, ['endpoint'], fromEndpoint); + } + return toObject; +} +function tuningDatasetToMldev(fromObject, _rootObject) { + const toObject = {}; + if (getValueByPath(fromObject, ['gcsUri']) !== undefined) { + throw new Error('gcsUri parameter is not supported in Gemini API.'); + } + if (getValueByPath(fromObject, ['vertexDatasetResource']) !== undefined) { + throw new Error('vertexDatasetResource parameter is not supported in Gemini API.'); + } + const fromExamples = getValueByPath(fromObject, ['examples']); + if (fromExamples != null) { + let transformedList = fromExamples; + if (Array.isArray(transformedList)) { + transformedList = transformedList.map((item) => { + return item; + }); + } + setValueByPath(toObject, ['examples', 'examples'], transformedList); + } + return toObject; +} +function tuningDatasetToVertex(fromObject, parentObject, rootObject) { + const toObject = {}; + let discriminatorGcsUri = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorGcsUri === undefined) { + discriminatorGcsUri = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorGcsUri === 'SUPERVISED_FINE_TUNING') { + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (parentObject !== undefined && fromGcsUri != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'trainingDatasetUri'], fromGcsUri); + } + } + else if (discriminatorGcsUri === 'PREFERENCE_TUNING') { + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (parentObject !== undefined && fromGcsUri != null) { + setValueByPath(parentObject, ['preferenceOptimizationSpec', 'trainingDatasetUri'], fromGcsUri); + } + } + else if (discriminatorGcsUri === 'DISTILLATION') { + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (parentObject !== undefined && fromGcsUri != null) { + setValueByPath(parentObject, ['distillationSpec', 'promptDatasetUri'], fromGcsUri); + } + } + let discriminatorVertexDatasetResource = getValueByPath(rootObject, [ + 'config', + 'method', + ]); + if (discriminatorVertexDatasetResource === undefined) { + discriminatorVertexDatasetResource = 'SUPERVISED_FINE_TUNING'; + } + if (discriminatorVertexDatasetResource === 'SUPERVISED_FINE_TUNING') { + const fromVertexDatasetResource = getValueByPath(fromObject, [ + 'vertexDatasetResource', + ]); + if (parentObject !== undefined && fromVertexDatasetResource != null) { + setValueByPath(parentObject, ['supervisedTuningSpec', 'trainingDatasetUri'], fromVertexDatasetResource); + } + } + else if (discriminatorVertexDatasetResource === 'PREFERENCE_TUNING') { + const fromVertexDatasetResource = getValueByPath(fromObject, [ + 'vertexDatasetResource', + ]); + if (parentObject !== undefined && fromVertexDatasetResource != null) { + setValueByPath(parentObject, ['preferenceOptimizationSpec', 'trainingDatasetUri'], fromVertexDatasetResource); + } + } + else if (discriminatorVertexDatasetResource === 'DISTILLATION') { + const fromVertexDatasetResource = getValueByPath(fromObject, [ + 'vertexDatasetResource', + ]); + if (parentObject !== undefined && fromVertexDatasetResource != null) { + setValueByPath(parentObject, ['distillationSpec', 'promptDatasetUri'], fromVertexDatasetResource); + } + } + if (getValueByPath(fromObject, ['examples']) !== undefined) { + throw new Error('examples parameter is not supported in Vertex AI.'); + } + return toObject; +} +function tuningJobFromMldev(fromObject, rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromState = getValueByPath(fromObject, ['state']); + if (fromState != null) { + setValueByPath(toObject, ['state'], tTuningJobStatus(fromState)); + } + const fromCreateTime = getValueByPath(fromObject, ['createTime']); + if (fromCreateTime != null) { + setValueByPath(toObject, ['createTime'], fromCreateTime); + } + const fromStartTime = getValueByPath(fromObject, [ + 'tuningTask', + 'startTime', + ]); + if (fromStartTime != null) { + setValueByPath(toObject, ['startTime'], fromStartTime); + } + const fromEndTime = getValueByPath(fromObject, [ + 'tuningTask', + 'completeTime', + ]); + if (fromEndTime != null) { + setValueByPath(toObject, ['endTime'], fromEndTime); + } + const fromUpdateTime = getValueByPath(fromObject, ['updateTime']); + if (fromUpdateTime != null) { + setValueByPath(toObject, ['updateTime'], fromUpdateTime); + } + const fromDescription = getValueByPath(fromObject, ['description']); + if (fromDescription != null) { + setValueByPath(toObject, ['description'], fromDescription); + } + const fromBaseModel = getValueByPath(fromObject, ['baseModel']); + if (fromBaseModel != null) { + setValueByPath(toObject, ['baseModel'], fromBaseModel); + } + const fromTunedModel = getValueByPath(fromObject, ['_self']); + if (fromTunedModel != null) { + setValueByPath(toObject, ['tunedModel'], tunedModelFromMldev(fromTunedModel)); + } + return toObject; +} +function tuningJobFromVertex(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromState = getValueByPath(fromObject, ['state']); + if (fromState != null) { + setValueByPath(toObject, ['state'], tTuningJobStatus(fromState)); + } + const fromCreateTime = getValueByPath(fromObject, ['createTime']); + if (fromCreateTime != null) { + setValueByPath(toObject, ['createTime'], fromCreateTime); + } + const fromStartTime = getValueByPath(fromObject, ['startTime']); + if (fromStartTime != null) { + setValueByPath(toObject, ['startTime'], fromStartTime); + } + const fromEndTime = getValueByPath(fromObject, ['endTime']); + if (fromEndTime != null) { + setValueByPath(toObject, ['endTime'], fromEndTime); + } + const fromUpdateTime = getValueByPath(fromObject, ['updateTime']); + if (fromUpdateTime != null) { + setValueByPath(toObject, ['updateTime'], fromUpdateTime); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + const fromDescription = getValueByPath(fromObject, ['description']); + if (fromDescription != null) { + setValueByPath(toObject, ['description'], fromDescription); + } + const fromBaseModel = getValueByPath(fromObject, ['baseModel']); + if (fromBaseModel != null) { + setValueByPath(toObject, ['baseModel'], fromBaseModel); + } + const fromTunedModel = getValueByPath(fromObject, ['tunedModel']); + if (fromTunedModel != null) { + setValueByPath(toObject, ['tunedModel'], fromTunedModel); + } + const fromPreTunedModel = getValueByPath(fromObject, [ + 'preTunedModel', + ]); + if (fromPreTunedModel != null) { + setValueByPath(toObject, ['preTunedModel'], fromPreTunedModel); + } + const fromSupervisedTuningSpec = getValueByPath(fromObject, [ + 'supervisedTuningSpec', + ]); + if (fromSupervisedTuningSpec != null) { + setValueByPath(toObject, ['supervisedTuningSpec'], fromSupervisedTuningSpec); + } + const fromPreferenceOptimizationSpec = getValueByPath(fromObject, [ + 'preferenceOptimizationSpec', + ]); + if (fromPreferenceOptimizationSpec != null) { + setValueByPath(toObject, ['preferenceOptimizationSpec'], fromPreferenceOptimizationSpec); + } + const fromDistillationSpec = getValueByPath(fromObject, [ + 'distillationSpec', + ]); + if (fromDistillationSpec != null) { + setValueByPath(toObject, ['distillationSpec'], fromDistillationSpec); + } + const fromTuningDataStats = getValueByPath(fromObject, [ + 'tuningDataStats', + ]); + if (fromTuningDataStats != null) { + setValueByPath(toObject, ['tuningDataStats'], fromTuningDataStats); + } + const fromEncryptionSpec = getValueByPath(fromObject, [ + 'encryptionSpec', + ]); + if (fromEncryptionSpec != null) { + setValueByPath(toObject, ['encryptionSpec'], fromEncryptionSpec); + } + const fromPartnerModelTuningSpec = getValueByPath(fromObject, [ + 'partnerModelTuningSpec', + ]); + if (fromPartnerModelTuningSpec != null) { + setValueByPath(toObject, ['partnerModelTuningSpec'], fromPartnerModelTuningSpec); + } + const fromCustomBaseModel = getValueByPath(fromObject, [ + 'customBaseModel', + ]); + if (fromCustomBaseModel != null) { + setValueByPath(toObject, ['customBaseModel'], fromCustomBaseModel); + } + const fromExperiment = getValueByPath(fromObject, ['experiment']); + if (fromExperiment != null) { + setValueByPath(toObject, ['experiment'], fromExperiment); + } + const fromLabels = getValueByPath(fromObject, ['labels']); + if (fromLabels != null) { + setValueByPath(toObject, ['labels'], fromLabels); + } + const fromOutputUri = getValueByPath(fromObject, ['outputUri']); + if (fromOutputUri != null) { + setValueByPath(toObject, ['outputUri'], fromOutputUri); + } + const fromPipelineJob = getValueByPath(fromObject, ['pipelineJob']); + if (fromPipelineJob != null) { + setValueByPath(toObject, ['pipelineJob'], fromPipelineJob); + } + const fromServiceAccount = getValueByPath(fromObject, [ + 'serviceAccount', + ]); + if (fromServiceAccount != null) { + setValueByPath(toObject, ['serviceAccount'], fromServiceAccount); + } + const fromTunedModelDisplayName = getValueByPath(fromObject, [ + 'tunedModelDisplayName', + ]); + if (fromTunedModelDisplayName != null) { + setValueByPath(toObject, ['tunedModelDisplayName'], fromTunedModelDisplayName); + } + const fromVeoTuningSpec = getValueByPath(fromObject, [ + 'veoTuningSpec', + ]); + if (fromVeoTuningSpec != null) { + setValueByPath(toObject, ['veoTuningSpec'], fromVeoTuningSpec); + } + return toObject; +} +function tuningOperationFromMldev(fromObject, _rootObject) { + const toObject = {}; + const fromSdkHttpResponse = getValueByPath(fromObject, [ + 'sdkHttpResponse', + ]); + if (fromSdkHttpResponse != null) { + setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse); + } + const fromName = getValueByPath(fromObject, ['name']); + if (fromName != null) { + setValueByPath(toObject, ['name'], fromName); + } + const fromMetadata = getValueByPath(fromObject, ['metadata']); + if (fromMetadata != null) { + setValueByPath(toObject, ['metadata'], fromMetadata); + } + const fromDone = getValueByPath(fromObject, ['done']); + if (fromDone != null) { + setValueByPath(toObject, ['done'], fromDone); + } + const fromError = getValueByPath(fromObject, ['error']); + if (fromError != null) { + setValueByPath(toObject, ['error'], fromError); + } + return toObject; +} +function tuningValidationDatasetToVertex(fromObject, _rootObject) { + const toObject = {}; + const fromGcsUri = getValueByPath(fromObject, ['gcsUri']); + if (fromGcsUri != null) { + setValueByPath(toObject, ['validationDatasetUri'], fromGcsUri); + } + const fromVertexDatasetResource = getValueByPath(fromObject, [ + 'vertexDatasetResource', + ]); + if (fromVertexDatasetResource != null) { + setValueByPath(toObject, ['validationDatasetUri'], fromVertexDatasetResource); + } + return toObject; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class Tunings extends BaseModule { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + /** + * Lists tuning jobs. + * + * @param params - The parameters for the list request. + * @return - A pager of tuning jobs. + * + * @example + * ```ts + * const tuningJobs = await ai.tunings.list({config: {'pageSize': 2}}); + * for await (const tuningJob of tuningJobs) { + * console.log(tuningJob); + * } + * ``` + */ + this.list = async (params = {}) => { + return new Pager(PagedItem.PAGED_ITEM_TUNING_JOBS, (x) => this.listInternal(x), await this.listInternal(params), params); + }; + /** + * Gets a TuningJob. + * + * @param name - The resource name of the tuning job. + * @return - A TuningJob object. + * + * @experimental - The SDK's tuning implementation is experimental, and may + * change in future versions. + */ + this.get = async (params) => { + return await this.getInternal(params); + }; + /** + * Creates a supervised fine-tuning job. + * + * @param params - The parameters for the tuning job. + * @return - A TuningJob operation. + * + * @experimental - The SDK's tuning implementation is experimental, and may + * change in future versions. + */ + this.tune = async (params) => { + var _a; + if (this.apiClient.isVertexAI()) { + if (params.baseModel.startsWith('projects/')) { + const preTunedModel = { + tunedModelName: params.baseModel, + }; + if ((_a = params.config) === null || _a === void 0 ? void 0 : _a.preTunedModelCheckpointId) { + preTunedModel.checkpointId = params.config.preTunedModelCheckpointId; + } + const paramsPrivate = Object.assign(Object.assign({}, params), { preTunedModel: preTunedModel }); + paramsPrivate.baseModel = undefined; + return await this.tuneInternal(paramsPrivate); + } + else { + const paramsPrivate = Object.assign({}, params); + return await this.tuneInternal(paramsPrivate); + } + } + else { + const paramsPrivate = Object.assign({}, params); + const operation = await this.tuneMldevInternal(paramsPrivate); + let tunedModelName = ''; + if (operation['metadata'] !== undefined && + operation['metadata']['tunedModel'] !== undefined) { + tunedModelName = operation['metadata']['tunedModel']; + } + else if (operation['name'] !== undefined && + operation['name'].includes('/operations/')) { + tunedModelName = operation['name'].split('/operations/')[0]; + } + const tuningJob = { + name: tunedModelName, + state: JobState.JOB_STATE_QUEUED, + }; + return tuningJob; + } + }; + } + async getInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = getTuningJobParametersToVertex(params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = tuningJobFromVertex(apiResponse); + return resp; + }); + } + else { + const body = getTuningJobParametersToMldev(params); + path = formatMap('{name}', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = tuningJobFromMldev(apiResponse); + return resp; + }); + } + } + async listInternal(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = listTuningJobsParametersToVertex(params); + path = formatMap('tuningJobs', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listTuningJobsResponseFromVertex(apiResponse); + const typedResp = new ListTuningJobsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = listTuningJobsParametersToMldev(params); + path = formatMap('tunedModels', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'GET', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = listTuningJobsResponseFromMldev(apiResponse); + const typedResp = new ListTuningJobsResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + /** + * Cancels a tuning job. + * + * @param params - The parameters for the cancel request. + * @return The empty response returned by the API. + * + * @example + * ```ts + * await ai.tunings.cancel({name: '...'}); // The server-generated resource name. + * ``` + */ + async cancel(params) { + var _a, _b, _c, _d; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = cancelTuningJobParametersToVertex(params); + path = formatMap('{name}:cancel', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = cancelTuningJobResponseFromVertex(apiResponse); + const typedResp = new CancelTuningJobResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + else { + const body = cancelTuningJobParametersToMldev(params); + path = formatMap('{name}:cancel', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_c = params.config) === null || _c === void 0 ? void 0 : _c.httpOptions, + abortSignal: (_d = params.config) === null || _d === void 0 ? void 0 : _d.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = cancelTuningJobResponseFromMldev(apiResponse); + const typedResp = new CancelTuningJobResponse(); + Object.assign(typedResp, resp); + return typedResp; + }); + } + } + async tuneInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + const body = createTuningJobParametersPrivateToVertex(params, params); + path = formatMap('tuningJobs', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = tuningJobFromVertex(apiResponse); + return resp; + }); + } + else { + throw new Error('This method is only supported by the Vertex AI.'); + } + } + async tuneMldevInternal(params) { + var _a, _b; + let response; + let path = ''; + let queryParams = {}; + if (this.apiClient.isVertexAI()) { + throw new Error('This method is only supported by the Gemini Developer API.'); + } + else { + const body = createTuningJobParametersPrivateToMldev(params); + path = formatMap('tunedModels', body['_url']); + queryParams = body['_query']; + delete body['_url']; + delete body['_query']; + response = this.apiClient + .request({ + path: path, + queryParams: queryParams, + body: JSON.stringify(body), + httpMethod: 'POST', + httpOptions: (_a = params.config) === null || _a === void 0 ? void 0 : _a.httpOptions, + abortSignal: (_b = params.config) === null || _b === void 0 ? void 0 : _b.abortSignal, + }) + .then((httpResponse) => { + return httpResponse.json().then((jsonResponse) => { + const response = jsonResponse; + response.sdkHttpResponse = { + headers: httpResponse.headers, + }; + return response; + }); + }); + return response.then((apiResponse) => { + const resp = tuningOperationFromMldev(apiResponse); + return resp; + }); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class BrowserDownloader { + async download(_params, _apiClient) { + throw new Error('Download to file is not supported in the browser, please use a browser compliant download like an <a> tag.'); + } +} + +const MAX_CHUNK_SIZE = 1024 * 1024 * 8; // bytes +const MAX_RETRY_COUNT = 3; +const INITIAL_RETRY_DELAY_MS = 1000; +const DELAY_MULTIPLIER = 2; +const X_GOOG_UPLOAD_STATUS_HEADER_FIELD = 'x-goog-upload-status'; +async function uploadBlob(file, uploadUrl, apiClient) { + var _a; + const response = await uploadBlobInternal(file, uploadUrl, apiClient); + const responseJson = (await (response === null || response === void 0 ? void 0 : response.json())); + if (((_a = response === null || response === void 0 ? void 0 : response.headers) === null || _a === void 0 ? void 0 : _a[X_GOOG_UPLOAD_STATUS_HEADER_FIELD]) !== 'final') { + throw new Error('Failed to upload file: Upload status is not finalized.'); + } + return responseJson['file']; +} +async function uploadBlobToFileSearchStore(file, uploadUrl, apiClient) { + var _a; + const response = await uploadBlobInternal(file, uploadUrl, apiClient); + const responseJson = (await (response === null || response === void 0 ? void 0 : response.json())); + if (((_a = response === null || response === void 0 ? void 0 : response.headers) === null || _a === void 0 ? void 0 : _a[X_GOOG_UPLOAD_STATUS_HEADER_FIELD]) !== 'final') { + throw new Error('Failed to upload file: Upload status is not finalized.'); + } + const resp = uploadToFileSearchStoreOperationFromMldev(responseJson); + const typedResp = new UploadToFileSearchStoreOperation(); + Object.assign(typedResp, resp); + return typedResp; +} +async function uploadBlobInternal(file, uploadUrl, apiClient) { + var _a, _b; + let fileSize = 0; + let offset = 0; + let response = new HttpResponse(new Response()); + let uploadCommand = 'upload'; + fileSize = file.size; + while (offset < fileSize) { + const chunkSize = Math.min(MAX_CHUNK_SIZE, fileSize - offset); + const chunk = file.slice(offset, offset + chunkSize); + if (offset + chunkSize >= fileSize) { + uploadCommand += ', finalize'; + } + let retryCount = 0; + let currentDelayMs = INITIAL_RETRY_DELAY_MS; + while (retryCount < MAX_RETRY_COUNT) { + response = await apiClient.request({ + path: '', + body: chunk, + httpMethod: 'POST', + httpOptions: { + apiVersion: '', + baseUrl: uploadUrl, + headers: { + 'X-Goog-Upload-Command': uploadCommand, + 'X-Goog-Upload-Offset': String(offset), + 'Content-Length': String(chunkSize), + }, + }, + }); + if ((_a = response === null || response === void 0 ? void 0 : response.headers) === null || _a === void 0 ? void 0 : _a[X_GOOG_UPLOAD_STATUS_HEADER_FIELD]) { + break; + } + retryCount++; + await sleep(currentDelayMs); + currentDelayMs = currentDelayMs * DELAY_MULTIPLIER; + } + offset += chunkSize; + // The `x-goog-upload-status` header field can be `active`, `final` and + //`cancelled` in resposne. + if (((_b = response === null || response === void 0 ? void 0 : response.headers) === null || _b === void 0 ? void 0 : _b[X_GOOG_UPLOAD_STATUS_HEADER_FIELD]) !== 'active') { + break; + } + // TODO(b/401391430) Investigate why the upload status is not finalized + // even though all content has been uploaded. + if (fileSize <= offset) { + throw new Error('All content has been uploaded, but the upload status is not finalized.'); + } + } + return response; +} +async function getBlobStat(file) { + const fileStat = { size: file.size, type: file.type }; + return fileStat; +} +function sleep(ms) { + return new Promise((resolvePromise) => setTimeout(resolvePromise, ms)); +} + +class BrowserUploader { + async upload(file, uploadUrl, apiClient) { + if (typeof file === 'string') { + throw new Error('File path is not supported in browser uploader.'); + } + return await uploadBlob(file, uploadUrl, apiClient); + } + async uploadToFileSearchStore(file, uploadUrl, apiClient) { + if (typeof file === 'string') { + throw new Error('File path is not supported in browser uploader.'); + } + return await uploadBlobToFileSearchStore(file, uploadUrl, apiClient); + } + async stat(file) { + if (typeof file === 'string') { + throw new Error('File path is not supported in browser uploader.'); + } + else { + return await getBlobStat(file); + } + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +class BrowserWebSocketFactory { + create(url, headers, callbacks) { + return new BrowserWebSocket(url, headers, callbacks); + } +} +class BrowserWebSocket { + constructor(url, headers, callbacks) { + this.url = url; + this.headers = headers; + this.callbacks = callbacks; + } + connect() { + this.ws = new WebSocket(this.url); + this.ws.onopen = this.callbacks.onopen; + this.ws.onerror = this.callbacks.onerror; + this.ws.onclose = this.callbacks.onclose; + this.ws.onmessage = this.callbacks.onmessage; + } + send(message) { + if (this.ws === undefined) { + throw new Error('WebSocket is not connected'); + } + this.ws.send(message); + } + close() { + if (this.ws === undefined) { + throw new Error('WebSocket is not connected'); + } + this.ws.close(); + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const GOOGLE_API_KEY_HEADER = 'x-goog-api-key'; +// TODO(b/395122533): We need a secure client side authentication mechanism. +class WebAuth { + constructor(apiKey) { + this.apiKey = apiKey; + } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async addAuthHeaders(headers, url) { + if (headers.get(GOOGLE_API_KEY_HEADER) !== null) { + return; + } + if (this.apiKey.startsWith('auth_tokens/')) { + throw new Error('Ephemeral tokens are only supported by the live API.'); + } + // Check if API key is empty or null + if (!this.apiKey) { + throw new Error('API key is missing. Please provide a valid API key.'); + } + headers.append(GOOGLE_API_KEY_HEADER, this.apiKey); + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +const LANGUAGE_LABEL_PREFIX = 'gl-node/'; +/** + * The Google GenAI SDK. + * + * @remarks + * Provides access to the GenAI features through either the {@link + * https://cloud.google.com/vertex-ai/docs/reference/rest | Gemini API} or + * the {@link https://cloud.google.com/vertex-ai/docs/reference/rest | Vertex AI + * API}. + * + * The {@link GoogleGenAIOptions.vertexai} value determines which of the API + * services to use. + * + * When using the Gemini API, a {@link GoogleGenAIOptions.apiKey} must also be + * set. When using Vertex AI, currently only {@link GoogleGenAIOptions.apiKey} + * is supported via Express mode. {@link GoogleGenAIOptions.project} and {@link + * GoogleGenAIOptions.location} should not be set. + * + * @example + * Initializing the SDK for using the Gemini API: + * ```ts + * import {GoogleGenAI} from '@google/genai'; + * const ai = new GoogleGenAI({apiKey: 'GEMINI_API_KEY'}); + * ``` + * + * @example + * Initializing the SDK for using the Vertex AI API: + * ```ts + * import {GoogleGenAI} from '@google/genai'; + * const ai = new GoogleGenAI({ + * vertexai: true, + * project: 'PROJECT_ID', + * location: 'PROJECT_LOCATION' + * }); + * ``` + * + */ +class GoogleGenAI { + get interactions() { + var _a; + if (this._interactions !== undefined) { + return this._interactions; + } + console.warn('GoogleGenAI.interactions: Interactions usage is experimental and may change in future versions.'); + const httpOpts = this.httpOptions; + // Unsupported Options Warnings + if (httpOpts === null || httpOpts === void 0 ? void 0 : httpOpts.extraBody) { + console.warn('GoogleGenAI.interactions: Client level httpOptions.extraBody is not supported by the interactions client and will be ignored.'); + } + const nextGenClient = new GeminiNextGenAPIClient({ + baseURL: this.apiClient.getBaseUrl(), + apiKey: this.apiKey, + apiVersion: this.apiClient.getApiVersion(), + clientAdapter: this.apiClient, + defaultHeaders: this.apiClient.getDefaultHeaders(), + timeout: httpOpts === null || httpOpts === void 0 ? void 0 : httpOpts.timeout, + maxRetries: (_a = httpOpts === null || httpOpts === void 0 ? void 0 : httpOpts.retryOptions) === null || _a === void 0 ? void 0 : _a.attempts, + }); + this._interactions = nextGenClient.interactions; + return this._interactions; + } + constructor(options) { + var _a; + if (options.apiKey == null) { + throw new Error('An API Key must be set when running in a browser'); + } + // Web client only supports API key mode for Vertex AI. + if (options.project || options.location) { + throw new Error('Vertex AI project based authentication is not supported on browser runtimes. Please do not provide a project or location.'); + } + this.vertexai = (_a = options.vertexai) !== null && _a !== void 0 ? _a : false; + this.apiKey = options.apiKey; + const baseUrl = getBaseUrl(options.httpOptions, options.vertexai, + /*vertexBaseUrlFromEnv*/ undefined, + /*geminiBaseUrlFromEnv*/ undefined); + if (baseUrl) { + if (options.httpOptions) { + options.httpOptions.baseUrl = baseUrl; + } + else { + options.httpOptions = { baseUrl: baseUrl }; + } + } + this.apiVersion = options.apiVersion; + this.httpOptions = options.httpOptions; + const auth = new WebAuth(this.apiKey); + this.apiClient = new ApiClient({ + auth: auth, + apiVersion: this.apiVersion, + apiKey: this.apiKey, + vertexai: this.vertexai, + httpOptions: this.httpOptions, + userAgentExtra: LANGUAGE_LABEL_PREFIX + 'web', + uploader: new BrowserUploader(), + downloader: new BrowserDownloader(), + }); + this.models = new Models(this.apiClient); + this.live = new Live(this.apiClient, auth, new BrowserWebSocketFactory()); + this.batches = new Batches(this.apiClient); + this.chats = new Chats(this.models, this.apiClient); + this.caches = new Caches(this.apiClient); + this.files = new Files(this.apiClient); + this.operations = new Operations(this.apiClient); + this.authTokens = new Tokens(this.apiClient); + this.tunings = new Tunings(this.apiClient); + this.fileSearchStores = new FileSearchStores(this.apiClient); + } +} + +export { ActivityHandling, AdapterSize, ApiError, ApiSpec, AuthType, Batches, Behavior, BlockedReason, Caches, CancelTuningJobResponse, Chat, Chats, ComputeTokensResponse, ContentReferenceImage, ControlReferenceImage, ControlReferenceType, CountTokensResponse, CreateFileResponse, DeleteCachedContentResponse, DeleteFileResponse, DeleteModelResponse, DocumentState, DynamicRetrievalConfigMode, EditImageResponse, EditMode, EmbedContentResponse, EndSensitivity, Environment, FeatureSelectionPreference, FileSource, FileState, Files, FinishReason, FunctionCallingConfigMode, FunctionResponse, FunctionResponseBlob, FunctionResponseFileData, FunctionResponsePart, FunctionResponseScheduling, GenerateContentResponse, GenerateContentResponsePromptFeedback, GenerateContentResponseUsageMetadata, GenerateImagesResponse, GenerateVideosOperation, GenerateVideosResponse, GoogleGenAI, HarmBlockMethod, HarmBlockThreshold, HarmCategory, HarmProbability, HarmSeverity, HttpElementLocation, HttpResponse, ImagePromptLanguage, ImportFileOperation, ImportFileResponse, InlinedEmbedContentResponse, InlinedResponse, JobState, Language, ListBatchJobsResponse, ListCachedContentsResponse, ListDocumentsResponse, ListFileSearchStoresResponse, ListFilesResponse, ListModelsResponse, ListTuningJobsResponse, Live, LiveClientToolResponse, LiveMusicPlaybackControl, LiveMusicServerMessage, LiveSendToolResponseParameters, LiveServerMessage, MaskReferenceImage, MaskReferenceMode, MediaModality, MediaResolution, Modality, Models, MusicGenerationMode, Operations, Outcome, PagedItem, Pager, PartMediaResolutionLevel, PersonGeneration, PhishBlockThreshold, RawReferenceImage, RecontextImageResponse, RegisterFilesResponse, ReplayResponse, ResourceScope, SafetyFilterLevel, Scale, SegmentImageResponse, SegmentMode, Session, SingleEmbedContentResponse, StartSensitivity, StyleReferenceImage, SubjectReferenceImage, SubjectReferenceType, ThinkingLevel, Tokens, TrafficType, TuningMethod, TuningMode, TuningTask, TurnCompleteReason, TurnCoverage, Type, UploadToFileSearchStoreOperation, UploadToFileSearchStoreResponse, UploadToFileSearchStoreResumableResponse, UpscaleImageResponse, UrlRetrievalStatus, VadSignalType, VideoCompressionQuality, VideoGenerationMaskMode, VideoGenerationReferenceType, VoiceActivityType, createFunctionResponsePartFromBase64, createFunctionResponsePartFromUri, createModelContent, createPartFromBase64, createPartFromCodeExecutionResult, createPartFromExecutableCode, createPartFromFunctionCall, createPartFromFunctionResponse, createPartFromText, createPartFromUri, createUserContent, mcpToTool, setDefaultBaseUrls }; +//# sourceMappingURL=index.mjs.map diff --git a/server/node_modules/@google/genai/dist/web/index.mjs.map b/server/node_modules/@google/genai/dist/web/index.mjs.map new file mode 100644 index 0000000..e416591 --- /dev/null +++ b/server/node_modules/@google/genai/dist/web/index.mjs.map @@ -0,0 +1 @@ +{"version":3,"file":"index.mjs","sources":["../../src/_base_url.ts","../../src/_common.ts","../../src/_base_transformers.ts","../../src/converters/_operations_converters.ts","../../src/types.ts","../../src/_transformers.ts","../../src/converters/_batches_converters.ts","../../src/pagers.ts","../../src/batches.ts","../../src/converters/_caches_converters.ts","../../src/caches.ts","../../src/chats.ts","../../src/errors.ts","../../src/converters/_files_converters.ts","../../src/files.ts","../../src/converters/_live_converters.ts","../../src/converters/_models_converters.ts","../../src/converters/_filesearchstores_converters.ts","../../src/_api_client.ts","../../src/mcp/_mcp.ts","../../src/music.ts","../../src/live.ts","../../src/_afc.ts","../../src/models.ts","../../src/operations.ts","../../src/converters/_tokens_converters.ts","../../src/tokens.ts","../../src/converters/_documents_converters.ts","../../src/documents.ts","../../src/filesearchstores.ts","../../src/interactions/internal/utils/uuid.ts","../../src/interactions/internal/errors.ts","../../src/interactions/core/error.ts","../../src/interactions/internal/utils/values.ts","../../src/interactions/internal/utils/sleep.ts","../../src/interactions/version.ts","../../src/interactions/internal/detect-platform.ts","../../src/interactions/internal/shims.ts","../../src/interactions/internal/request-options.ts","../../src/interactions/internal/uploads.ts","../../src/interactions/internal/to-file.ts","../../src/interactions/core/resource.ts","../../src/interactions/internal/utils/path.ts","../../src/interactions/resources/interactions.ts","../../src/interactions/internal/utils/bytes.ts","../../src/interactions/internal/decoders/line.ts","../../src/interactions/internal/utils/log.ts","../../src/interactions/core/streaming.ts","../../src/interactions/internal/parse.ts","../../src/interactions/core/api-promise.ts","../../src/interactions/internal/headers.ts","../../src/interactions/internal/utils/env.ts","../../src/interactions/client.ts","../../src/converters/_tunings_converters.ts","../../src/tunings.ts","../../src/web/_browser_downloader.ts","../../src/cross/_cross_uploader.ts","../../src/web/_browser_uploader.ts","../../src/web/_browser_websocket.ts","../../src/web/_web_auth.ts","../../src/web/web_client.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {HttpOptions} from './types.js';\n\nlet _defaultBaseGeminiUrl: string | undefined = undefined;\nlet _defaultBaseVertexUrl: string | undefined = undefined;\n\n/**\n * Parameters for setting the base URLs for the Gemini API and Vertex AI API.\n */\nexport interface BaseUrlParameters {\n geminiUrl?: string;\n vertexUrl?: string;\n}\n\n/**\n * Overrides the base URLs for the Gemini API and Vertex AI API.\n *\n * @remarks This function should be called before initializing the SDK. If the\n * base URLs are set after initializing the SDK, the base URLs will not be\n * updated. Base URLs provided in the HttpOptions will also take precedence over\n * URLs set here.\n *\n * @example\n * ```ts\n * import {GoogleGenAI, setDefaultBaseUrls} from '@google/genai';\n * // Override the base URL for the Gemini API.\n * setDefaultBaseUrls({geminiUrl:'https://gemini.google.com'});\n *\n * // Override the base URL for the Vertex AI API.\n * setDefaultBaseUrls({vertexUrl: 'https://vertexai.googleapis.com'});\n *\n * const ai = new GoogleGenAI({apiKey: 'GEMINI_API_KEY'});\n * ```\n */\nexport function setDefaultBaseUrls(baseUrlParams: BaseUrlParameters) {\n _defaultBaseGeminiUrl = baseUrlParams.geminiUrl;\n _defaultBaseVertexUrl = baseUrlParams.vertexUrl;\n}\n\n/**\n * Returns the default base URLs for the Gemini API and Vertex AI API.\n */\nexport function getDefaultBaseUrls(): BaseUrlParameters {\n return {\n geminiUrl: _defaultBaseGeminiUrl,\n vertexUrl: _defaultBaseVertexUrl,\n };\n}\n\n/**\n * Returns the default base URL based on the following priority:\n * 1. Base URLs set via HttpOptions.\n * 2. Base URLs set via the latest call to setDefaultBaseUrls.\n * 3. Base URLs set via environment variables.\n */\nexport function getBaseUrl(\n httpOptions: HttpOptions | undefined,\n vertexai: boolean | undefined,\n vertexBaseUrlFromEnv: string | undefined,\n geminiBaseUrlFromEnv: string | undefined,\n): string | undefined {\n if (!httpOptions?.baseUrl) {\n const defaultBaseUrls = getDefaultBaseUrls();\n if (vertexai) {\n return defaultBaseUrls.vertexUrl ?? vertexBaseUrlFromEnv;\n } else {\n return defaultBaseUrls.geminiUrl ?? geminiBaseUrlFromEnv;\n }\n }\n\n return httpOptions.baseUrl;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nexport class BaseModule {}\n\nexport function formatMap(\n templateString: string,\n valueMap: Record<string, unknown>,\n): string {\n // Use a regular expression to find all placeholders in the template string\n const regex = /\\{([^}]+)\\}/g;\n\n // Replace each placeholder with its corresponding value from the valueMap\n return templateString.replace(regex, (match, key) => {\n if (Object.prototype.hasOwnProperty.call(valueMap, key)) {\n const value = valueMap[key];\n // Convert the value to a string if it's not a string already\n return value !== undefined && value !== null ? String(value) : '';\n } else {\n // Handle missing keys\n throw new Error(`Key '${key}' not found in valueMap.`);\n }\n });\n}\n\nexport function setValueByPath(\n data: Record<string, unknown>,\n keys: string[],\n value: unknown,\n): void {\n for (let i = 0; i < keys.length - 1; i++) {\n const key = keys[i];\n\n if (key.endsWith('[]')) {\n const keyName = key.slice(0, -2);\n if (!(keyName in data)) {\n if (Array.isArray(value)) {\n data[keyName] = Array.from({length: value.length}, () => ({}));\n } else {\n throw new Error(`Value must be a list given an array path ${key}`);\n }\n }\n\n if (Array.isArray(data[keyName])) {\n const arrayData = data[keyName] as Array<unknown>;\n\n if (Array.isArray(value)) {\n for (let j = 0; j < arrayData.length; j++) {\n const entry = arrayData[j] as Record<string, unknown>;\n setValueByPath(entry, keys.slice(i + 1), value[j]);\n }\n } else {\n for (const d of arrayData) {\n setValueByPath(\n d as Record<string, unknown>,\n keys.slice(i + 1),\n value,\n );\n }\n }\n }\n return;\n } else if (key.endsWith('[0]')) {\n const keyName = key.slice(0, -3);\n if (!(keyName in data)) {\n data[keyName] = [{}];\n }\n const arrayData = (data as Record<string, unknown>)[keyName];\n setValueByPath(\n (arrayData as Array<Record<string, unknown>>)[0],\n keys.slice(i + 1),\n value,\n );\n return;\n }\n\n if (!data[key] || typeof data[key] !== 'object') {\n data[key] = {};\n }\n\n data = data[key] as Record<string, unknown>;\n }\n\n const keyToSet = keys[keys.length - 1];\n const existingData = data[keyToSet];\n\n if (existingData !== undefined) {\n if (\n !value ||\n (typeof value === 'object' && Object.keys(value).length === 0)\n ) {\n return;\n }\n\n if (value === existingData) {\n return;\n }\n\n if (\n typeof existingData === 'object' &&\n typeof value === 'object' &&\n existingData !== null &&\n value !== null\n ) {\n Object.assign(existingData, value);\n } else {\n throw new Error(`Cannot set value for an existing key. Key: ${keyToSet}`);\n }\n } else {\n if (\n keyToSet === '_self' &&\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(value)\n ) {\n const valueAsRecord = value as Record<string, unknown>;\n\n Object.assign(data, valueAsRecord);\n } else {\n data[keyToSet] = value;\n }\n }\n}\n\nexport function getValueByPath(\n data: unknown,\n keys: string[],\n defaultValue: unknown = undefined,\n): unknown {\n try {\n if (keys.length === 1 && keys[0] === '_self') {\n return data;\n }\n\n for (let i = 0; i < keys.length; i++) {\n if (typeof data !== 'object' || data === null) {\n return defaultValue;\n }\n\n const key = keys[i];\n if (key.endsWith('[]')) {\n const keyName = key.slice(0, -2);\n if (keyName in data) {\n const arrayData = (data as Record<string, unknown>)[keyName];\n if (!Array.isArray(arrayData)) {\n return defaultValue;\n }\n return arrayData.map((d) =>\n getValueByPath(d, keys.slice(i + 1), defaultValue),\n );\n } else {\n return defaultValue;\n }\n } else {\n data = (data as Record<string, unknown>)[key];\n }\n }\n\n return data;\n } catch (error) {\n if (error instanceof TypeError) {\n return defaultValue;\n }\n throw error;\n }\n}\n\n/**\n * Moves values from source paths to destination paths.\n *\n * Examples:\n * moveValueByPath(\n * {'requests': [{'content': v1}, {'content': v2}]},\n * {'requests[].*': 'requests[].request.*'}\n * )\n * -> {'requests': [{'request': {'content': v1}}, {'request': {'content': v2}}]}\n */\nexport function moveValueByPath(\n data: unknown,\n paths: Record<string, string>,\n): void {\n for (const [sourcePath, destPath] of Object.entries(paths)) {\n const sourceKeys = sourcePath.split('.');\n const destKeys = destPath.split('.');\n\n // Determine keys to exclude from wildcard to avoid cyclic references\n const excludeKeys = new Set<string>();\n let wildcardIdx = -1;\n for (let i = 0; i < sourceKeys.length; i++) {\n if (sourceKeys[i] === '*') {\n wildcardIdx = i;\n break;\n }\n }\n\n if (wildcardIdx !== -1 && destKeys.length > wildcardIdx) {\n // Extract the intermediate key between source and dest paths\n // Example: source=['requests[]', '*'], dest=['requests[]', 'request', '*']\n // We want to exclude 'request'\n for (let i = wildcardIdx; i < destKeys.length; i++) {\n const key = destKeys[i];\n if (key !== '*' && !key.endsWith('[]') && !key.endsWith('[0]')) {\n excludeKeys.add(key);\n }\n }\n }\n\n _moveValueRecursive(data, sourceKeys, destKeys, 0, excludeKeys);\n }\n}\n\n/**\n * Recursively moves values from source path to destination path.\n */\nfunction _moveValueRecursive(\n data: unknown,\n sourceKeys: string[],\n destKeys: string[],\n keyIdx: number,\n excludeKeys: Set<string>,\n): void {\n if (keyIdx >= sourceKeys.length) {\n return;\n }\n\n if (typeof data !== 'object' || data === null) {\n return;\n }\n\n const key = sourceKeys[keyIdx];\n\n if (key.endsWith('[]')) {\n const keyName = key.slice(0, -2);\n const dataRecord = data as Record<string, unknown>;\n if (keyName in dataRecord && Array.isArray(dataRecord[keyName])) {\n for (const item of dataRecord[keyName] as Array<unknown>) {\n _moveValueRecursive(\n item,\n sourceKeys,\n destKeys,\n keyIdx + 1,\n excludeKeys,\n );\n }\n }\n } else if (key === '*') {\n // wildcard - move all fields\n if (typeof data === 'object' && data !== null && !Array.isArray(data)) {\n const dataRecord = data as Record<string, unknown>;\n const keysToMove = Object.keys(dataRecord).filter(\n (k) => !k.startsWith('_') && !excludeKeys.has(k),\n );\n\n const valuesToMove: Record<string, unknown> = {};\n for (const k of keysToMove) {\n valuesToMove[k] = dataRecord[k];\n }\n\n // Set values at destination\n for (const [k, v] of Object.entries(valuesToMove)) {\n const newDestKeys: string[] = [];\n for (const dk of destKeys.slice(keyIdx)) {\n if (dk === '*') {\n newDestKeys.push(k);\n } else {\n newDestKeys.push(dk);\n }\n }\n setValueByPath(dataRecord, newDestKeys, v);\n }\n\n for (const k of keysToMove) {\n delete dataRecord[k];\n }\n }\n } else {\n // Navigate to next level\n const dataRecord = data as Record<string, unknown>;\n if (key in dataRecord) {\n _moveValueRecursive(\n dataRecord[key],\n sourceKeys,\n destKeys,\n keyIdx + 1,\n excludeKeys,\n );\n }\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nexport function tBytes(fromBytes: string | unknown): string {\n if (typeof fromBytes !== 'string') {\n throw new Error('fromImageBytes must be a string');\n }\n // TODO(b/389133914): Remove dummy bytes converter.\n return fromBytes;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport * as t from '../_base_transformers.js';\nimport * as common from '../_common.js';\nimport type * as types from '../types.js';\n\nexport function fetchPredictOperationParametersToMldev(\n fromObject: types.FetchPredictOperationParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['operationName']) !== undefined) {\n throw new Error('operationName parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['resourceName']) !== undefined) {\n throw new Error('resourceName parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['config']) !== undefined) {\n throw new Error('config parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function fetchPredictOperationParametersToVertex(\n fromObject: types.FetchPredictOperationParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromOperationName = common.getValueByPath(fromObject, [\n 'operationName',\n ]);\n if (fromOperationName != null) {\n common.setValueByPath(toObject, ['operationName'], fromOperationName);\n }\n\n const fromResourceName = common.getValueByPath(fromObject, ['resourceName']);\n if (fromResourceName != null) {\n common.setValueByPath(toObject, ['_url', 'resourceName'], fromResourceName);\n }\n\n return toObject;\n}\n\nexport function generateVideosOperationFromMldev(\n fromObject: types.GenerateVideosOperation,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromMetadata = common.getValueByPath(fromObject, ['metadata']);\n if (fromMetadata != null) {\n common.setValueByPath(toObject, ['metadata'], fromMetadata);\n }\n\n const fromDone = common.getValueByPath(fromObject, ['done']);\n if (fromDone != null) {\n common.setValueByPath(toObject, ['done'], fromDone);\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n const fromResponse = common.getValueByPath(fromObject, [\n 'response',\n 'generateVideoResponse',\n ]);\n if (fromResponse != null) {\n common.setValueByPath(\n toObject,\n ['response'],\n generateVideosResponseFromMldev(fromResponse),\n );\n }\n\n return toObject;\n}\n\nexport function generateVideosOperationFromVertex(\n fromObject: types.GenerateVideosOperation,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromMetadata = common.getValueByPath(fromObject, ['metadata']);\n if (fromMetadata != null) {\n common.setValueByPath(toObject, ['metadata'], fromMetadata);\n }\n\n const fromDone = common.getValueByPath(fromObject, ['done']);\n if (fromDone != null) {\n common.setValueByPath(toObject, ['done'], fromDone);\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n const fromResponse = common.getValueByPath(fromObject, ['response']);\n if (fromResponse != null) {\n common.setValueByPath(\n toObject,\n ['response'],\n generateVideosResponseFromVertex(fromResponse),\n );\n }\n\n return toObject;\n}\n\nexport function generateVideosResponseFromMldev(\n fromObject: types.GenerateVideosResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromGeneratedVideos = common.getValueByPath(fromObject, [\n 'generatedSamples',\n ]);\n if (fromGeneratedVideos != null) {\n let transformedList = fromGeneratedVideos;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return generatedVideoFromMldev(item);\n });\n }\n common.setValueByPath(toObject, ['generatedVideos'], transformedList);\n }\n\n const fromRaiMediaFilteredCount = common.getValueByPath(fromObject, [\n 'raiMediaFilteredCount',\n ]);\n if (fromRaiMediaFilteredCount != null) {\n common.setValueByPath(\n toObject,\n ['raiMediaFilteredCount'],\n fromRaiMediaFilteredCount,\n );\n }\n\n const fromRaiMediaFilteredReasons = common.getValueByPath(fromObject, [\n 'raiMediaFilteredReasons',\n ]);\n if (fromRaiMediaFilteredReasons != null) {\n common.setValueByPath(\n toObject,\n ['raiMediaFilteredReasons'],\n fromRaiMediaFilteredReasons,\n );\n }\n\n return toObject;\n}\n\nexport function generateVideosResponseFromVertex(\n fromObject: types.GenerateVideosResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromGeneratedVideos = common.getValueByPath(fromObject, ['videos']);\n if (fromGeneratedVideos != null) {\n let transformedList = fromGeneratedVideos;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return generatedVideoFromVertex(item);\n });\n }\n common.setValueByPath(toObject, ['generatedVideos'], transformedList);\n }\n\n const fromRaiMediaFilteredCount = common.getValueByPath(fromObject, [\n 'raiMediaFilteredCount',\n ]);\n if (fromRaiMediaFilteredCount != null) {\n common.setValueByPath(\n toObject,\n ['raiMediaFilteredCount'],\n fromRaiMediaFilteredCount,\n );\n }\n\n const fromRaiMediaFilteredReasons = common.getValueByPath(fromObject, [\n 'raiMediaFilteredReasons',\n ]);\n if (fromRaiMediaFilteredReasons != null) {\n common.setValueByPath(\n toObject,\n ['raiMediaFilteredReasons'],\n fromRaiMediaFilteredReasons,\n );\n }\n\n return toObject;\n}\n\nexport function generatedVideoFromMldev(\n fromObject: types.GeneratedVideo,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromVideo = common.getValueByPath(fromObject, ['video']);\n if (fromVideo != null) {\n common.setValueByPath(toObject, ['video'], videoFromMldev(fromVideo));\n }\n\n return toObject;\n}\n\nexport function generatedVideoFromVertex(\n fromObject: types.GeneratedVideo,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromVideo = common.getValueByPath(fromObject, ['_self']);\n if (fromVideo != null) {\n common.setValueByPath(toObject, ['video'], videoFromVertex(fromVideo));\n }\n\n return toObject;\n}\n\nexport function getOperationParametersToMldev(\n fromObject: types.GetOperationParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromOperationName = common.getValueByPath(fromObject, [\n 'operationName',\n ]);\n if (fromOperationName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'operationName'],\n fromOperationName,\n );\n }\n\n return toObject;\n}\n\nexport function getOperationParametersToVertex(\n fromObject: types.GetOperationParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromOperationName = common.getValueByPath(fromObject, [\n 'operationName',\n ]);\n if (fromOperationName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'operationName'],\n fromOperationName,\n );\n }\n\n return toObject;\n}\n\nexport function importFileOperationFromMldev(\n fromObject: types.ImportFileOperation,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromMetadata = common.getValueByPath(fromObject, ['metadata']);\n if (fromMetadata != null) {\n common.setValueByPath(toObject, ['metadata'], fromMetadata);\n }\n\n const fromDone = common.getValueByPath(fromObject, ['done']);\n if (fromDone != null) {\n common.setValueByPath(toObject, ['done'], fromDone);\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n const fromResponse = common.getValueByPath(fromObject, ['response']);\n if (fromResponse != null) {\n common.setValueByPath(\n toObject,\n ['response'],\n importFileResponseFromMldev(fromResponse),\n );\n }\n\n return toObject;\n}\n\nexport function importFileResponseFromMldev(\n fromObject: types.ImportFileResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromParent = common.getValueByPath(fromObject, ['parent']);\n if (fromParent != null) {\n common.setValueByPath(toObject, ['parent'], fromParent);\n }\n\n const fromDocumentName = common.getValueByPath(fromObject, ['documentName']);\n if (fromDocumentName != null) {\n common.setValueByPath(toObject, ['documentName'], fromDocumentName);\n }\n\n return toObject;\n}\n\nexport function uploadToFileSearchStoreOperationFromMldev(\n fromObject: types.UploadToFileSearchStoreOperation,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromMetadata = common.getValueByPath(fromObject, ['metadata']);\n if (fromMetadata != null) {\n common.setValueByPath(toObject, ['metadata'], fromMetadata);\n }\n\n const fromDone = common.getValueByPath(fromObject, ['done']);\n if (fromDone != null) {\n common.setValueByPath(toObject, ['done'], fromDone);\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n const fromResponse = common.getValueByPath(fromObject, ['response']);\n if (fromResponse != null) {\n common.setValueByPath(\n toObject,\n ['response'],\n uploadToFileSearchStoreResponseFromMldev(fromResponse),\n );\n }\n\n return toObject;\n}\n\nexport function uploadToFileSearchStoreResponseFromMldev(\n fromObject: types.UploadToFileSearchStoreResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromParent = common.getValueByPath(fromObject, ['parent']);\n if (fromParent != null) {\n common.setValueByPath(toObject, ['parent'], fromParent);\n }\n\n const fromDocumentName = common.getValueByPath(fromObject, ['documentName']);\n if (fromDocumentName != null) {\n common.setValueByPath(toObject, ['documentName'], fromDocumentName);\n }\n\n return toObject;\n}\n\nexport function videoFromMldev(\n fromObject: types.Video,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromUri = common.getValueByPath(fromObject, ['uri']);\n if (fromUri != null) {\n common.setValueByPath(toObject, ['uri'], fromUri);\n }\n\n const fromVideoBytes = common.getValueByPath(fromObject, ['encodedVideo']);\n if (fromVideoBytes != null) {\n common.setValueByPath(toObject, ['videoBytes'], t.tBytes(fromVideoBytes));\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['encoding']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function videoFromVertex(\n fromObject: types.Video,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromUri = common.getValueByPath(fromObject, ['gcsUri']);\n if (fromUri != null) {\n common.setValueByPath(toObject, ['uri'], fromUri);\n }\n\n const fromVideoBytes = common.getValueByPath(fromObject, [\n 'bytesBase64Encoded',\n ]);\n if (fromVideoBytes != null) {\n common.setValueByPath(toObject, ['videoBytes'], t.tBytes(fromVideoBytes));\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport type {ReferenceImageAPIInternal} from './_internal_types.js';\nimport {\n generateVideosOperationFromMldev,\n generateVideosOperationFromVertex,\n importFileOperationFromMldev,\n uploadToFileSearchStoreOperationFromMldev,\n} from './converters/_operations_converters.js';\n\n/** Outcome of the code execution. */\nexport enum Outcome {\n /**\n * Unspecified status. This value should not be used.\n */\n OUTCOME_UNSPECIFIED = 'OUTCOME_UNSPECIFIED',\n /**\n * Code execution completed successfully.\n */\n OUTCOME_OK = 'OUTCOME_OK',\n /**\n * Code execution finished but with a failure. `stderr` should contain the reason.\n */\n OUTCOME_FAILED = 'OUTCOME_FAILED',\n /**\n * Code execution ran for too long, and was cancelled. There may or may not be a partial output present.\n */\n OUTCOME_DEADLINE_EXCEEDED = 'OUTCOME_DEADLINE_EXCEEDED',\n}\n\n/** Programming language of the `code`. */\nexport enum Language {\n /**\n * Unspecified language. This value should not be used.\n */\n LANGUAGE_UNSPECIFIED = 'LANGUAGE_UNSPECIFIED',\n /**\n * Python >= 3.10, with numpy and simpy available.\n */\n PYTHON = 'PYTHON',\n}\n\n/** Specifies how the response should be scheduled in the conversation. */\nexport enum FunctionResponseScheduling {\n /**\n * This value is unused.\n */\n SCHEDULING_UNSPECIFIED = 'SCHEDULING_UNSPECIFIED',\n /**\n * Only add the result to the conversation context, do not interrupt or trigger generation.\n */\n SILENT = 'SILENT',\n /**\n * Add the result to the conversation context, and prompt to generate output without interrupting ongoing generation.\n */\n WHEN_IDLE = 'WHEN_IDLE',\n /**\n * Add the result to the conversation context, interrupt ongoing generation and prompt to generate output.\n */\n INTERRUPT = 'INTERRUPT',\n}\n\n/** The type of the data. */\nexport enum Type {\n /**\n * Not specified, should not be used.\n */\n TYPE_UNSPECIFIED = 'TYPE_UNSPECIFIED',\n /**\n * OpenAPI string type\n */\n STRING = 'STRING',\n /**\n * OpenAPI number type\n */\n NUMBER = 'NUMBER',\n /**\n * OpenAPI integer type\n */\n INTEGER = 'INTEGER',\n /**\n * OpenAPI boolean type\n */\n BOOLEAN = 'BOOLEAN',\n /**\n * OpenAPI array type\n */\n ARRAY = 'ARRAY',\n /**\n * OpenAPI object type\n */\n OBJECT = 'OBJECT',\n /**\n * Null type\n */\n NULL = 'NULL',\n}\n\n/** The API spec that the external API implements. This enum is not supported in Gemini API. */\nexport enum ApiSpec {\n /**\n * Unspecified API spec. This value should not be used.\n */\n API_SPEC_UNSPECIFIED = 'API_SPEC_UNSPECIFIED',\n /**\n * Simple search API spec.\n */\n SIMPLE_SEARCH = 'SIMPLE_SEARCH',\n /**\n * Elastic search API spec.\n */\n ELASTIC_SEARCH = 'ELASTIC_SEARCH',\n}\n\n/** Type of auth scheme. This enum is not supported in Gemini API. */\nexport enum AuthType {\n AUTH_TYPE_UNSPECIFIED = 'AUTH_TYPE_UNSPECIFIED',\n /**\n * No Auth.\n */\n NO_AUTH = 'NO_AUTH',\n /**\n * API Key Auth.\n */\n API_KEY_AUTH = 'API_KEY_AUTH',\n /**\n * HTTP Basic Auth.\n */\n HTTP_BASIC_AUTH = 'HTTP_BASIC_AUTH',\n /**\n * Google Service Account Auth.\n */\n GOOGLE_SERVICE_ACCOUNT_AUTH = 'GOOGLE_SERVICE_ACCOUNT_AUTH',\n /**\n * OAuth auth.\n */\n OAUTH = 'OAUTH',\n /**\n * OpenID Connect (OIDC) Auth.\n */\n OIDC_AUTH = 'OIDC_AUTH',\n}\n\n/** The location of the API key. This enum is not supported in Gemini API. */\nexport enum HttpElementLocation {\n HTTP_IN_UNSPECIFIED = 'HTTP_IN_UNSPECIFIED',\n /**\n * Element is in the HTTP request query.\n */\n HTTP_IN_QUERY = 'HTTP_IN_QUERY',\n /**\n * Element is in the HTTP request header.\n */\n HTTP_IN_HEADER = 'HTTP_IN_HEADER',\n /**\n * Element is in the HTTP request path.\n */\n HTTP_IN_PATH = 'HTTP_IN_PATH',\n /**\n * Element is in the HTTP request body.\n */\n HTTP_IN_BODY = 'HTTP_IN_BODY',\n /**\n * Element is in the HTTP request cookie.\n */\n HTTP_IN_COOKIE = 'HTTP_IN_COOKIE',\n}\n\n/** Sites with confidence level chosen & above this value will be blocked from the search results. This enum is not supported in Gemini API. */\nexport enum PhishBlockThreshold {\n /**\n * Defaults to unspecified.\n */\n PHISH_BLOCK_THRESHOLD_UNSPECIFIED = 'PHISH_BLOCK_THRESHOLD_UNSPECIFIED',\n /**\n * Blocks Low and above confidence URL that is risky.\n */\n BLOCK_LOW_AND_ABOVE = 'BLOCK_LOW_AND_ABOVE',\n /**\n * Blocks Medium and above confidence URL that is risky.\n */\n BLOCK_MEDIUM_AND_ABOVE = 'BLOCK_MEDIUM_AND_ABOVE',\n /**\n * Blocks High and above confidence URL that is risky.\n */\n BLOCK_HIGH_AND_ABOVE = 'BLOCK_HIGH_AND_ABOVE',\n /**\n * Blocks Higher and above confidence URL that is risky.\n */\n BLOCK_HIGHER_AND_ABOVE = 'BLOCK_HIGHER_AND_ABOVE',\n /**\n * Blocks Very high and above confidence URL that is risky.\n */\n BLOCK_VERY_HIGH_AND_ABOVE = 'BLOCK_VERY_HIGH_AND_ABOVE',\n /**\n * Blocks Extremely high confidence URL that is risky.\n */\n BLOCK_ONLY_EXTREMELY_HIGH = 'BLOCK_ONLY_EXTREMELY_HIGH',\n}\n\n/** Specifies the function Behavior. Currently only supported by the BidiGenerateContent method. This enum is not supported in Vertex AI. */\nexport enum Behavior {\n /**\n * This value is unused.\n */\n UNSPECIFIED = 'UNSPECIFIED',\n /**\n * If set, the system will wait to receive the function response before continuing the conversation.\n */\n BLOCKING = 'BLOCKING',\n /**\n * If set, the system will not wait to receive the function response. Instead, it will attempt to handle function responses as they become available while maintaining the conversation between the user and the model.\n */\n NON_BLOCKING = 'NON_BLOCKING',\n}\n\n/** The mode of the predictor to be used in dynamic retrieval. */\nexport enum DynamicRetrievalConfigMode {\n /**\n * Always trigger retrieval.\n */\n MODE_UNSPECIFIED = 'MODE_UNSPECIFIED',\n /**\n * Run retrieval only when system decides it is necessary.\n */\n MODE_DYNAMIC = 'MODE_DYNAMIC',\n}\n\n/** Function calling mode. */\nexport enum FunctionCallingConfigMode {\n /**\n * Unspecified function calling mode. This value should not be used.\n */\n MODE_UNSPECIFIED = 'MODE_UNSPECIFIED',\n /**\n * Default model behavior, model decides to predict either function calls or natural language response.\n */\n AUTO = 'AUTO',\n /**\n * Model is constrained to always predicting function calls only. If \"allowed_function_names\" are set, the predicted function calls will be limited to any one of \"allowed_function_names\", else the predicted function calls will be any one of the provided \"function_declarations\".\n */\n ANY = 'ANY',\n /**\n * Model will not predict any function calls. Model behavior is same as when not passing any function declarations.\n */\n NONE = 'NONE',\n /**\n * Model is constrained to predict either function calls or natural language response. If \"allowed_function_names\" are set, the predicted function calls will be limited to any one of \"allowed_function_names\", else the predicted function calls will be any one of the provided \"function_declarations\".\n */\n VALIDATED = 'VALIDATED',\n}\n\n/** The number of thoughts tokens that the model should generate. */\nexport enum ThinkingLevel {\n /**\n * Unspecified thinking level.\n */\n THINKING_LEVEL_UNSPECIFIED = 'THINKING_LEVEL_UNSPECIFIED',\n /**\n * Low thinking level.\n */\n LOW = 'LOW',\n /**\n * Medium thinking level.\n */\n MEDIUM = 'MEDIUM',\n /**\n * High thinking level.\n */\n HIGH = 'HIGH',\n /**\n * MINIMAL thinking level.\n */\n MINIMAL = 'MINIMAL',\n}\n\n/** Harm category. */\nexport enum HarmCategory {\n /**\n * The harm category is unspecified.\n */\n HARM_CATEGORY_UNSPECIFIED = 'HARM_CATEGORY_UNSPECIFIED',\n /**\n * The harm category is harassment.\n */\n HARM_CATEGORY_HARASSMENT = 'HARM_CATEGORY_HARASSMENT',\n /**\n * The harm category is hate speech.\n */\n HARM_CATEGORY_HATE_SPEECH = 'HARM_CATEGORY_HATE_SPEECH',\n /**\n * The harm category is sexually explicit content.\n */\n HARM_CATEGORY_SEXUALLY_EXPLICIT = 'HARM_CATEGORY_SEXUALLY_EXPLICIT',\n /**\n * The harm category is dangerous content.\n */\n HARM_CATEGORY_DANGEROUS_CONTENT = 'HARM_CATEGORY_DANGEROUS_CONTENT',\n /**\n * Deprecated: Election filter is not longer supported. The harm category is civic integrity.\n */\n HARM_CATEGORY_CIVIC_INTEGRITY = 'HARM_CATEGORY_CIVIC_INTEGRITY',\n /**\n * The harm category is image hate. This enum value is not supported in Gemini API.\n */\n HARM_CATEGORY_IMAGE_HATE = 'HARM_CATEGORY_IMAGE_HATE',\n /**\n * The harm category is image dangerous content. This enum value is not supported in Gemini API.\n */\n HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT = 'HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT',\n /**\n * The harm category is image harassment. This enum value is not supported in Gemini API.\n */\n HARM_CATEGORY_IMAGE_HARASSMENT = 'HARM_CATEGORY_IMAGE_HARASSMENT',\n /**\n * The harm category is image sexually explicit content. This enum value is not supported in Gemini API.\n */\n HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT = 'HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT',\n /**\n * The harm category is for jailbreak prompts. This enum value is not supported in Gemini API.\n */\n HARM_CATEGORY_JAILBREAK = 'HARM_CATEGORY_JAILBREAK',\n}\n\n/** Specify if the threshold is used for probability or severity score. If not specified, the threshold is used for probability score. This enum is not supported in Gemini API. */\nexport enum HarmBlockMethod {\n /**\n * The harm block method is unspecified.\n */\n HARM_BLOCK_METHOD_UNSPECIFIED = 'HARM_BLOCK_METHOD_UNSPECIFIED',\n /**\n * The harm block method uses both probability and severity scores.\n */\n SEVERITY = 'SEVERITY',\n /**\n * The harm block method uses the probability score.\n */\n PROBABILITY = 'PROBABILITY',\n}\n\n/** The harm block threshold. */\nexport enum HarmBlockThreshold {\n /**\n * Unspecified harm block threshold.\n */\n HARM_BLOCK_THRESHOLD_UNSPECIFIED = 'HARM_BLOCK_THRESHOLD_UNSPECIFIED',\n /**\n * Block low threshold and above (i.e. block more).\n */\n BLOCK_LOW_AND_ABOVE = 'BLOCK_LOW_AND_ABOVE',\n /**\n * Block medium threshold and above.\n */\n BLOCK_MEDIUM_AND_ABOVE = 'BLOCK_MEDIUM_AND_ABOVE',\n /**\n * Block only high threshold (i.e. block less).\n */\n BLOCK_ONLY_HIGH = 'BLOCK_ONLY_HIGH',\n /**\n * Block none.\n */\n BLOCK_NONE = 'BLOCK_NONE',\n /**\n * Turn off the safety filter.\n */\n OFF = 'OFF',\n}\n\n/** Output only. The reason why the model stopped generating tokens.\n\nIf empty, the model has not stopped generating the tokens. */\nexport enum FinishReason {\n /**\n * The finish reason is unspecified.\n */\n FINISH_REASON_UNSPECIFIED = 'FINISH_REASON_UNSPECIFIED',\n /**\n * Token generation reached a natural stopping point or a configured stop sequence.\n */\n STOP = 'STOP',\n /**\n * Token generation reached the configured maximum output tokens.\n */\n MAX_TOKENS = 'MAX_TOKENS',\n /**\n * Token generation stopped because the content potentially contains safety violations. NOTE: When streaming, [content][] is empty if content filters blocks the output.\n */\n SAFETY = 'SAFETY',\n /**\n * The token generation stopped because of potential recitation.\n */\n RECITATION = 'RECITATION',\n /**\n * The token generation stopped because of using an unsupported language.\n */\n LANGUAGE = 'LANGUAGE',\n /**\n * All other reasons that stopped the token generation.\n */\n OTHER = 'OTHER',\n /**\n * Token generation stopped because the content contains forbidden terms.\n */\n BLOCKLIST = 'BLOCKLIST',\n /**\n * Token generation stopped for potentially containing prohibited content.\n */\n PROHIBITED_CONTENT = 'PROHIBITED_CONTENT',\n /**\n * Token generation stopped because the content potentially contains Sensitive Personally Identifiable Information (SPII).\n */\n SPII = 'SPII',\n /**\n * The function call generated by the model is invalid.\n */\n MALFORMED_FUNCTION_CALL = 'MALFORMED_FUNCTION_CALL',\n /**\n * Token generation stopped because generated images have safety violations.\n */\n IMAGE_SAFETY = 'IMAGE_SAFETY',\n /**\n * The tool call generated by the model is invalid.\n */\n UNEXPECTED_TOOL_CALL = 'UNEXPECTED_TOOL_CALL',\n /**\n * Image generation stopped because the generated images have prohibited content.\n */\n IMAGE_PROHIBITED_CONTENT = 'IMAGE_PROHIBITED_CONTENT',\n /**\n * The model was expected to generate an image, but none was generated.\n */\n NO_IMAGE = 'NO_IMAGE',\n /**\n * Image generation stopped because the generated image may be a recitation from a source.\n */\n IMAGE_RECITATION = 'IMAGE_RECITATION',\n /**\n * Image generation stopped for a reason not otherwise specified.\n */\n IMAGE_OTHER = 'IMAGE_OTHER',\n}\n\n/** Output only. Harm probability levels in the content. */\nexport enum HarmProbability {\n /**\n * Harm probability unspecified.\n */\n HARM_PROBABILITY_UNSPECIFIED = 'HARM_PROBABILITY_UNSPECIFIED',\n /**\n * Negligible level of harm.\n */\n NEGLIGIBLE = 'NEGLIGIBLE',\n /**\n * Low level of harm.\n */\n LOW = 'LOW',\n /**\n * Medium level of harm.\n */\n MEDIUM = 'MEDIUM',\n /**\n * High level of harm.\n */\n HIGH = 'HIGH',\n}\n\n/** Output only. Harm severity levels in the content. This enum is not supported in Gemini API. */\nexport enum HarmSeverity {\n /**\n * Harm severity unspecified.\n */\n HARM_SEVERITY_UNSPECIFIED = 'HARM_SEVERITY_UNSPECIFIED',\n /**\n * Negligible level of harm severity.\n */\n HARM_SEVERITY_NEGLIGIBLE = 'HARM_SEVERITY_NEGLIGIBLE',\n /**\n * Low level of harm severity.\n */\n HARM_SEVERITY_LOW = 'HARM_SEVERITY_LOW',\n /**\n * Medium level of harm severity.\n */\n HARM_SEVERITY_MEDIUM = 'HARM_SEVERITY_MEDIUM',\n /**\n * High level of harm severity.\n */\n HARM_SEVERITY_HIGH = 'HARM_SEVERITY_HIGH',\n}\n\n/** Status of the url retrieval. */\nexport enum UrlRetrievalStatus {\n /**\n * Default value. This value is unused.\n */\n URL_RETRIEVAL_STATUS_UNSPECIFIED = 'URL_RETRIEVAL_STATUS_UNSPECIFIED',\n /**\n * Url retrieval is successful.\n */\n URL_RETRIEVAL_STATUS_SUCCESS = 'URL_RETRIEVAL_STATUS_SUCCESS',\n /**\n * Url retrieval is failed due to error.\n */\n URL_RETRIEVAL_STATUS_ERROR = 'URL_RETRIEVAL_STATUS_ERROR',\n /**\n * Url retrieval is failed because the content is behind paywall. This enum value is not supported in Vertex AI.\n */\n URL_RETRIEVAL_STATUS_PAYWALL = 'URL_RETRIEVAL_STATUS_PAYWALL',\n /**\n * Url retrieval is failed because the content is unsafe. This enum value is not supported in Vertex AI.\n */\n URL_RETRIEVAL_STATUS_UNSAFE = 'URL_RETRIEVAL_STATUS_UNSAFE',\n}\n\n/** Output only. The reason why the prompt was blocked. */\nexport enum BlockedReason {\n /**\n * The blocked reason is unspecified.\n */\n BLOCKED_REASON_UNSPECIFIED = 'BLOCKED_REASON_UNSPECIFIED',\n /**\n * The prompt was blocked for safety reasons.\n */\n SAFETY = 'SAFETY',\n /**\n * The prompt was blocked for other reasons. For example, it may be due to the prompt's language, or because it contains other harmful content.\n */\n OTHER = 'OTHER',\n /**\n * The prompt was blocked because it contains a term from the terminology blocklist.\n */\n BLOCKLIST = 'BLOCKLIST',\n /**\n * The prompt was blocked because it contains prohibited content.\n */\n PROHIBITED_CONTENT = 'PROHIBITED_CONTENT',\n /**\n * The prompt was blocked because it contains content that is unsafe for image generation.\n */\n IMAGE_SAFETY = 'IMAGE_SAFETY',\n /**\n * The prompt was blocked by Model Armor. This enum value is not supported in Gemini API.\n */\n MODEL_ARMOR = 'MODEL_ARMOR',\n /**\n * The prompt was blocked as a jailbreak attempt. This enum value is not supported in Gemini API.\n */\n JAILBREAK = 'JAILBREAK',\n}\n\n/** Output only. The traffic type for this request. This enum is not supported in Gemini API. */\nexport enum TrafficType {\n /**\n * Unspecified request traffic type.\n */\n TRAFFIC_TYPE_UNSPECIFIED = 'TRAFFIC_TYPE_UNSPECIFIED',\n /**\n * The request was processed using Pay-As-You-Go quota.\n */\n ON_DEMAND = 'ON_DEMAND',\n /**\n * Type for Provisioned Throughput traffic.\n */\n PROVISIONED_THROUGHPUT = 'PROVISIONED_THROUGHPUT',\n}\n\n/** Server content modalities. */\nexport enum Modality {\n /**\n * The modality is unspecified.\n */\n MODALITY_UNSPECIFIED = 'MODALITY_UNSPECIFIED',\n /**\n * Indicates the model should return text\n */\n TEXT = 'TEXT',\n /**\n * Indicates the model should return images.\n */\n IMAGE = 'IMAGE',\n /**\n * Indicates the model should return audio.\n */\n AUDIO = 'AUDIO',\n}\n\n/** The media resolution to use. */\nexport enum MediaResolution {\n /**\n * Media resolution has not been set\n */\n MEDIA_RESOLUTION_UNSPECIFIED = 'MEDIA_RESOLUTION_UNSPECIFIED',\n /**\n * Media resolution set to low (64 tokens).\n */\n MEDIA_RESOLUTION_LOW = 'MEDIA_RESOLUTION_LOW',\n /**\n * Media resolution set to medium (256 tokens).\n */\n MEDIA_RESOLUTION_MEDIUM = 'MEDIA_RESOLUTION_MEDIUM',\n /**\n * Media resolution set to high (zoomed reframing with 256 tokens).\n */\n MEDIA_RESOLUTION_HIGH = 'MEDIA_RESOLUTION_HIGH',\n}\n\n/** Tuning mode. This enum is not supported in Gemini API. */\nexport enum TuningMode {\n /**\n * Tuning mode is unspecified.\n */\n TUNING_MODE_UNSPECIFIED = 'TUNING_MODE_UNSPECIFIED',\n /**\n * Full fine-tuning mode.\n */\n TUNING_MODE_FULL = 'TUNING_MODE_FULL',\n /**\n * PEFT adapter tuning mode.\n */\n TUNING_MODE_PEFT_ADAPTER = 'TUNING_MODE_PEFT_ADAPTER',\n}\n\n/** Adapter size for tuning. This enum is not supported in Gemini API. */\nexport enum AdapterSize {\n /**\n * Adapter size is unspecified.\n */\n ADAPTER_SIZE_UNSPECIFIED = 'ADAPTER_SIZE_UNSPECIFIED',\n /**\n * Adapter size 1.\n */\n ADAPTER_SIZE_ONE = 'ADAPTER_SIZE_ONE',\n /**\n * Adapter size 2.\n */\n ADAPTER_SIZE_TWO = 'ADAPTER_SIZE_TWO',\n /**\n * Adapter size 4.\n */\n ADAPTER_SIZE_FOUR = 'ADAPTER_SIZE_FOUR',\n /**\n * Adapter size 8.\n */\n ADAPTER_SIZE_EIGHT = 'ADAPTER_SIZE_EIGHT',\n /**\n * Adapter size 16.\n */\n ADAPTER_SIZE_SIXTEEN = 'ADAPTER_SIZE_SIXTEEN',\n /**\n * Adapter size 32.\n */\n ADAPTER_SIZE_THIRTY_TWO = 'ADAPTER_SIZE_THIRTY_TWO',\n}\n\n/** Job state. */\nexport enum JobState {\n /**\n * The job state is unspecified.\n */\n JOB_STATE_UNSPECIFIED = 'JOB_STATE_UNSPECIFIED',\n /**\n * The job has been just created or resumed and processing has not yet begun.\n */\n JOB_STATE_QUEUED = 'JOB_STATE_QUEUED',\n /**\n * The service is preparing to run the job.\n */\n JOB_STATE_PENDING = 'JOB_STATE_PENDING',\n /**\n * The job is in progress.\n */\n JOB_STATE_RUNNING = 'JOB_STATE_RUNNING',\n /**\n * The job completed successfully.\n */\n JOB_STATE_SUCCEEDED = 'JOB_STATE_SUCCEEDED',\n /**\n * The job failed.\n */\n JOB_STATE_FAILED = 'JOB_STATE_FAILED',\n /**\n * The job is being cancelled. From this state the job may only go to either `JOB_STATE_SUCCEEDED`, `JOB_STATE_FAILED` or `JOB_STATE_CANCELLED`.\n */\n JOB_STATE_CANCELLING = 'JOB_STATE_CANCELLING',\n /**\n * The job has been cancelled.\n */\n JOB_STATE_CANCELLED = 'JOB_STATE_CANCELLED',\n /**\n * The job has been stopped, and can be resumed.\n */\n JOB_STATE_PAUSED = 'JOB_STATE_PAUSED',\n /**\n * The job has expired.\n */\n JOB_STATE_EXPIRED = 'JOB_STATE_EXPIRED',\n /**\n * The job is being updated. Only jobs in the `JOB_STATE_RUNNING` state can be updated. After updating, the job goes back to the `JOB_STATE_RUNNING` state.\n */\n JOB_STATE_UPDATING = 'JOB_STATE_UPDATING',\n /**\n * The job is partially succeeded, some results may be missing due to errors.\n */\n JOB_STATE_PARTIALLY_SUCCEEDED = 'JOB_STATE_PARTIALLY_SUCCEEDED',\n}\n\n/** The tuning task. Either I2V or T2V. This enum is not supported in Gemini API. */\nexport enum TuningTask {\n /**\n * Default value. This value is unused.\n */\n TUNING_TASK_UNSPECIFIED = 'TUNING_TASK_UNSPECIFIED',\n /**\n * Tuning task for image to video.\n */\n TUNING_TASK_I2V = 'TUNING_TASK_I2V',\n /**\n * Tuning task for text to video.\n */\n TUNING_TASK_T2V = 'TUNING_TASK_T2V',\n /**\n * Tuning task for reference to video.\n */\n TUNING_TASK_R2V = 'TUNING_TASK_R2V',\n}\n\n/** The tokenization quality used for given media. */\nexport enum PartMediaResolutionLevel {\n /**\n * Media resolution has not been set.\n */\n MEDIA_RESOLUTION_UNSPECIFIED = 'MEDIA_RESOLUTION_UNSPECIFIED',\n /**\n * Media resolution set to low.\n */\n MEDIA_RESOLUTION_LOW = 'MEDIA_RESOLUTION_LOW',\n /**\n * Media resolution set to medium.\n */\n MEDIA_RESOLUTION_MEDIUM = 'MEDIA_RESOLUTION_MEDIUM',\n /**\n * Media resolution set to high.\n */\n MEDIA_RESOLUTION_HIGH = 'MEDIA_RESOLUTION_HIGH',\n /**\n * Media resolution set to ultra high.\n */\n MEDIA_RESOLUTION_ULTRA_HIGH = 'MEDIA_RESOLUTION_ULTRA_HIGH',\n}\n\n/** Resource scope. */\nexport enum ResourceScope {\n /**\n * When setting base_url, this value configures resource scope to be the collection.\n The resource name will not include api version, project, or location.\n For example, if base_url is set to \"https://aiplatform.googleapis.com\",\n then the resource name for a Model would be\n \"https://aiplatform.googleapis.com/publishers/google/models/gemini-3-pro-preview\n */\n COLLECTION = 'COLLECTION',\n}\n\n/** Options for feature selection preference. */\nexport enum FeatureSelectionPreference {\n FEATURE_SELECTION_PREFERENCE_UNSPECIFIED = 'FEATURE_SELECTION_PREFERENCE_UNSPECIFIED',\n PRIORITIZE_QUALITY = 'PRIORITIZE_QUALITY',\n BALANCED = 'BALANCED',\n PRIORITIZE_COST = 'PRIORITIZE_COST',\n}\n\n/** The environment being operated. */\nexport enum Environment {\n /**\n * Defaults to browser.\n */\n ENVIRONMENT_UNSPECIFIED = 'ENVIRONMENT_UNSPECIFIED',\n /**\n * Operates in a web browser.\n */\n ENVIRONMENT_BROWSER = 'ENVIRONMENT_BROWSER',\n}\n\n/** Enum that controls the safety filter level for objectionable content. */\nexport enum SafetyFilterLevel {\n BLOCK_LOW_AND_ABOVE = 'BLOCK_LOW_AND_ABOVE',\n BLOCK_MEDIUM_AND_ABOVE = 'BLOCK_MEDIUM_AND_ABOVE',\n BLOCK_ONLY_HIGH = 'BLOCK_ONLY_HIGH',\n BLOCK_NONE = 'BLOCK_NONE',\n}\n\n/** Enum that controls the generation of people. */\nexport enum PersonGeneration {\n /**\n * Block generation of images of people.\n */\n DONT_ALLOW = 'DONT_ALLOW',\n /**\n * Generate images of adults, but not children.\n */\n ALLOW_ADULT = 'ALLOW_ADULT',\n /**\n * Generate images that include adults and children.\n */\n ALLOW_ALL = 'ALLOW_ALL',\n}\n\n/** Enum that specifies the language of the text in the prompt. */\nexport enum ImagePromptLanguage {\n /**\n * Auto-detect the language.\n */\n auto = 'auto',\n /**\n * English\n */\n en = 'en',\n /**\n * Japanese\n */\n ja = 'ja',\n /**\n * Korean\n */\n ko = 'ko',\n /**\n * Hindi\n */\n hi = 'hi',\n /**\n * Chinese\n */\n zh = 'zh',\n /**\n * Portuguese\n */\n pt = 'pt',\n /**\n * Spanish\n */\n es = 'es',\n}\n\n/** Enum representing the mask mode of a mask reference image. */\nexport enum MaskReferenceMode {\n MASK_MODE_DEFAULT = 'MASK_MODE_DEFAULT',\n MASK_MODE_USER_PROVIDED = 'MASK_MODE_USER_PROVIDED',\n MASK_MODE_BACKGROUND = 'MASK_MODE_BACKGROUND',\n MASK_MODE_FOREGROUND = 'MASK_MODE_FOREGROUND',\n MASK_MODE_SEMANTIC = 'MASK_MODE_SEMANTIC',\n}\n\n/** Enum representing the control type of a control reference image. */\nexport enum ControlReferenceType {\n CONTROL_TYPE_DEFAULT = 'CONTROL_TYPE_DEFAULT',\n CONTROL_TYPE_CANNY = 'CONTROL_TYPE_CANNY',\n CONTROL_TYPE_SCRIBBLE = 'CONTROL_TYPE_SCRIBBLE',\n CONTROL_TYPE_FACE_MESH = 'CONTROL_TYPE_FACE_MESH',\n}\n\n/** Enum representing the subject type of a subject reference image. */\nexport enum SubjectReferenceType {\n SUBJECT_TYPE_DEFAULT = 'SUBJECT_TYPE_DEFAULT',\n SUBJECT_TYPE_PERSON = 'SUBJECT_TYPE_PERSON',\n SUBJECT_TYPE_ANIMAL = 'SUBJECT_TYPE_ANIMAL',\n SUBJECT_TYPE_PRODUCT = 'SUBJECT_TYPE_PRODUCT',\n}\n\n/** Enum representing the editing mode. */\nexport enum EditMode {\n EDIT_MODE_DEFAULT = 'EDIT_MODE_DEFAULT',\n EDIT_MODE_INPAINT_REMOVAL = 'EDIT_MODE_INPAINT_REMOVAL',\n EDIT_MODE_INPAINT_INSERTION = 'EDIT_MODE_INPAINT_INSERTION',\n EDIT_MODE_OUTPAINT = 'EDIT_MODE_OUTPAINT',\n EDIT_MODE_CONTROLLED_EDITING = 'EDIT_MODE_CONTROLLED_EDITING',\n EDIT_MODE_STYLE = 'EDIT_MODE_STYLE',\n EDIT_MODE_BGSWAP = 'EDIT_MODE_BGSWAP',\n EDIT_MODE_PRODUCT_IMAGE = 'EDIT_MODE_PRODUCT_IMAGE',\n}\n\n/** Enum that represents the segmentation mode. */\nexport enum SegmentMode {\n FOREGROUND = 'FOREGROUND',\n BACKGROUND = 'BACKGROUND',\n PROMPT = 'PROMPT',\n SEMANTIC = 'SEMANTIC',\n INTERACTIVE = 'INTERACTIVE',\n}\n\n/** Enum for the reference type of a video generation reference image. */\nexport enum VideoGenerationReferenceType {\n /**\n * A reference image that provides assets to the generated video,\n such as the scene, an object, a character, etc.\n */\n ASSET = 'ASSET',\n /**\n * A reference image that provides aesthetics including colors,\n lighting, texture, etc., to be used as the style of the generated video,\n such as 'anime', 'photography', 'origami', etc.\n */\n STYLE = 'STYLE',\n}\n\n/** Enum for the mask mode of a video generation mask. */\nexport enum VideoGenerationMaskMode {\n /**\n * The image mask contains a masked rectangular region which is\n applied on the first frame of the input video. The object described in\n the prompt is inserted into this region and will appear in subsequent\n frames.\n */\n INSERT = 'INSERT',\n /**\n * The image mask is used to determine an object in the\n first video frame to track. This object is removed from the video.\n */\n REMOVE = 'REMOVE',\n /**\n * The image mask is used to determine a region in the\n video. Objects in this region will be removed.\n */\n REMOVE_STATIC = 'REMOVE_STATIC',\n /**\n * The image mask contains a masked rectangular region where\n the input video will go. The remaining area will be generated. Video\n masks are not supported.\n */\n OUTPAINT = 'OUTPAINT',\n}\n\n/** Enum that controls the compression quality of the generated videos. */\nexport enum VideoCompressionQuality {\n /**\n * Optimized video compression quality. This will produce videos\n with a compressed, smaller file size.\n */\n OPTIMIZED = 'OPTIMIZED',\n /**\n * Lossless video compression quality. This will produce videos\n with a larger file size.\n */\n LOSSLESS = 'LOSSLESS',\n}\n\n/** Enum representing the tuning method. */\nexport enum TuningMethod {\n /**\n * Supervised fine tuning.\n */\n SUPERVISED_FINE_TUNING = 'SUPERVISED_FINE_TUNING',\n /**\n * Preference optimization tuning.\n */\n PREFERENCE_TUNING = 'PREFERENCE_TUNING',\n /**\n * Distillation tuning.\n */\n DISTILLATION = 'DISTILLATION',\n}\n\n/** State for the lifecycle of a Document. */\nexport enum DocumentState {\n STATE_UNSPECIFIED = 'STATE_UNSPECIFIED',\n STATE_PENDING = 'STATE_PENDING',\n STATE_ACTIVE = 'STATE_ACTIVE',\n STATE_FAILED = 'STATE_FAILED',\n}\n\n/** State for the lifecycle of a File. */\nexport enum FileState {\n STATE_UNSPECIFIED = 'STATE_UNSPECIFIED',\n PROCESSING = 'PROCESSING',\n ACTIVE = 'ACTIVE',\n FAILED = 'FAILED',\n}\n\n/** Source of the File. */\nexport enum FileSource {\n SOURCE_UNSPECIFIED = 'SOURCE_UNSPECIFIED',\n UPLOADED = 'UPLOADED',\n GENERATED = 'GENERATED',\n REGISTERED = 'REGISTERED',\n}\n\n/** The reason why the turn is complete. */\nexport enum TurnCompleteReason {\n /**\n * Default value. Reason is unspecified.\n */\n TURN_COMPLETE_REASON_UNSPECIFIED = 'TURN_COMPLETE_REASON_UNSPECIFIED',\n /**\n * The function call generated by the model is invalid.\n */\n MALFORMED_FUNCTION_CALL = 'MALFORMED_FUNCTION_CALL',\n /**\n * The response is rejected by the model.\n */\n RESPONSE_REJECTED = 'RESPONSE_REJECTED',\n /**\n * Needs more input from the user.\n */\n NEED_MORE_INPUT = 'NEED_MORE_INPUT',\n}\n\n/** Server content modalities. */\nexport enum MediaModality {\n /**\n * The modality is unspecified.\n */\n MODALITY_UNSPECIFIED = 'MODALITY_UNSPECIFIED',\n /**\n * Plain text.\n */\n TEXT = 'TEXT',\n /**\n * Images.\n */\n IMAGE = 'IMAGE',\n /**\n * Video.\n */\n VIDEO = 'VIDEO',\n /**\n * Audio.\n */\n AUDIO = 'AUDIO',\n /**\n * Document, e.g. PDF.\n */\n DOCUMENT = 'DOCUMENT',\n}\n\n/** The type of the VAD signal. */\nexport enum VadSignalType {\n /**\n * The default is VAD_SIGNAL_TYPE_UNSPECIFIED.\n */\n VAD_SIGNAL_TYPE_UNSPECIFIED = 'VAD_SIGNAL_TYPE_UNSPECIFIED',\n /**\n * Start of sentence signal.\n */\n VAD_SIGNAL_TYPE_SOS = 'VAD_SIGNAL_TYPE_SOS',\n /**\n * End of sentence signal.\n */\n VAD_SIGNAL_TYPE_EOS = 'VAD_SIGNAL_TYPE_EOS',\n}\n\n/** The type of the voice activity signal. */\nexport enum VoiceActivityType {\n /**\n * The default is VOICE_ACTIVITY_TYPE_UNSPECIFIED.\n */\n TYPE_UNSPECIFIED = 'TYPE_UNSPECIFIED',\n /**\n * Start of sentence signal.\n */\n ACTIVITY_START = 'ACTIVITY_START',\n /**\n * End of sentence signal.\n */\n ACTIVITY_END = 'ACTIVITY_END',\n}\n\n/** Start of speech sensitivity. */\nexport enum StartSensitivity {\n /**\n * The default is START_SENSITIVITY_LOW.\n */\n START_SENSITIVITY_UNSPECIFIED = 'START_SENSITIVITY_UNSPECIFIED',\n /**\n * Automatic detection will detect the start of speech more often.\n */\n START_SENSITIVITY_HIGH = 'START_SENSITIVITY_HIGH',\n /**\n * Automatic detection will detect the start of speech less often.\n */\n START_SENSITIVITY_LOW = 'START_SENSITIVITY_LOW',\n}\n\n/** End of speech sensitivity. */\nexport enum EndSensitivity {\n /**\n * The default is END_SENSITIVITY_LOW.\n */\n END_SENSITIVITY_UNSPECIFIED = 'END_SENSITIVITY_UNSPECIFIED',\n /**\n * Automatic detection ends speech more often.\n */\n END_SENSITIVITY_HIGH = 'END_SENSITIVITY_HIGH',\n /**\n * Automatic detection ends speech less often.\n */\n END_SENSITIVITY_LOW = 'END_SENSITIVITY_LOW',\n}\n\n/** The different ways of handling user activity. */\nexport enum ActivityHandling {\n /**\n * If unspecified, the default behavior is `START_OF_ACTIVITY_INTERRUPTS`.\n */\n ACTIVITY_HANDLING_UNSPECIFIED = 'ACTIVITY_HANDLING_UNSPECIFIED',\n /**\n * If true, start of activity will interrupt the model's response (also called \"barge in\"). The model's current response will be cut-off in the moment of the interruption. This is the default behavior.\n */\n START_OF_ACTIVITY_INTERRUPTS = 'START_OF_ACTIVITY_INTERRUPTS',\n /**\n * The model's response will not be interrupted.\n */\n NO_INTERRUPTION = 'NO_INTERRUPTION',\n}\n\n/** Options about which input is included in the user's turn. */\nexport enum TurnCoverage {\n /**\n * If unspecified, the default behavior is `TURN_INCLUDES_ONLY_ACTIVITY`.\n */\n TURN_COVERAGE_UNSPECIFIED = 'TURN_COVERAGE_UNSPECIFIED',\n /**\n * The users turn only includes activity since the last turn, excluding inactivity (e.g. silence on the audio stream). This is the default behavior.\n */\n TURN_INCLUDES_ONLY_ACTIVITY = 'TURN_INCLUDES_ONLY_ACTIVITY',\n /**\n * The users turn includes all realtime input since the last turn, including inactivity (e.g. silence on the audio stream).\n */\n TURN_INCLUDES_ALL_INPUT = 'TURN_INCLUDES_ALL_INPUT',\n}\n\n/** Scale of the generated music. */\nexport enum Scale {\n /**\n * Default value. This value is unused.\n */\n SCALE_UNSPECIFIED = 'SCALE_UNSPECIFIED',\n /**\n * C major or A minor.\n */\n C_MAJOR_A_MINOR = 'C_MAJOR_A_MINOR',\n /**\n * Db major or Bb minor.\n */\n D_FLAT_MAJOR_B_FLAT_MINOR = 'D_FLAT_MAJOR_B_FLAT_MINOR',\n /**\n * D major or B minor.\n */\n D_MAJOR_B_MINOR = 'D_MAJOR_B_MINOR',\n /**\n * Eb major or C minor\n */\n E_FLAT_MAJOR_C_MINOR = 'E_FLAT_MAJOR_C_MINOR',\n /**\n * E major or Db minor.\n */\n E_MAJOR_D_FLAT_MINOR = 'E_MAJOR_D_FLAT_MINOR',\n /**\n * F major or D minor.\n */\n F_MAJOR_D_MINOR = 'F_MAJOR_D_MINOR',\n /**\n * Gb major or Eb minor.\n */\n G_FLAT_MAJOR_E_FLAT_MINOR = 'G_FLAT_MAJOR_E_FLAT_MINOR',\n /**\n * G major or E minor.\n */\n G_MAJOR_E_MINOR = 'G_MAJOR_E_MINOR',\n /**\n * Ab major or F minor.\n */\n A_FLAT_MAJOR_F_MINOR = 'A_FLAT_MAJOR_F_MINOR',\n /**\n * A major or Gb minor.\n */\n A_MAJOR_G_FLAT_MINOR = 'A_MAJOR_G_FLAT_MINOR',\n /**\n * Bb major or G minor.\n */\n B_FLAT_MAJOR_G_MINOR = 'B_FLAT_MAJOR_G_MINOR',\n /**\n * B major or Ab minor.\n */\n B_MAJOR_A_FLAT_MINOR = 'B_MAJOR_A_FLAT_MINOR',\n}\n\n/** The mode of music generation. */\nexport enum MusicGenerationMode {\n /**\n * Rely on the server default generation mode.\n */\n MUSIC_GENERATION_MODE_UNSPECIFIED = 'MUSIC_GENERATION_MODE_UNSPECIFIED',\n /**\n * Steer text prompts to regions of latent space with higher quality\n music.\n */\n QUALITY = 'QUALITY',\n /**\n * Steer text prompts to regions of latent space with a larger\n diversity of music.\n */\n DIVERSITY = 'DIVERSITY',\n /**\n * Steer text prompts to regions of latent space more likely to\n generate music with vocals.\n */\n VOCALIZATION = 'VOCALIZATION',\n}\n\n/** The playback control signal to apply to the music generation. */\nexport enum LiveMusicPlaybackControl {\n /**\n * This value is unused.\n */\n PLAYBACK_CONTROL_UNSPECIFIED = 'PLAYBACK_CONTROL_UNSPECIFIED',\n /**\n * Start generating the music.\n */\n PLAY = 'PLAY',\n /**\n * Hold the music generation. Use PLAY to resume from the current position.\n */\n PAUSE = 'PAUSE',\n /**\n * Stop the music generation and reset the context (prompts retained).\n Use PLAY to restart the music generation.\n */\n STOP = 'STOP',\n /**\n * Reset the context of the music generation without stopping it.\n Retains the current prompts and config.\n */\n RESET_CONTEXT = 'RESET_CONTEXT',\n}\n\n/** Media resolution for the input media. */\nexport declare interface PartMediaResolution {\n /** The tokenization quality used for given media.\n */\n level?: PartMediaResolutionLevel;\n /** Specifies the required sequence length for media tokenization.\n */\n numTokens?: number;\n}\n\n/** Result of executing the [ExecutableCode]. Only generated when using the [CodeExecution] tool, and always follows a `part` containing the [ExecutableCode]. */\nexport declare interface CodeExecutionResult {\n /** Required. Outcome of the code execution. */\n outcome?: Outcome;\n /** Optional. Contains stdout when code execution is successful, stderr or other description otherwise. */\n output?: string;\n}\n\n/** Code generated by the model that is meant to be executed, and the result returned to the model. Generated when using the [CodeExecution] tool, in which the code will be automatically executed, and a corresponding [CodeExecutionResult] will also be generated. */\nexport declare interface ExecutableCode {\n /** Required. The code to be executed. */\n code?: string;\n /** Required. Programming language of the `code`. */\n language?: Language;\n}\n\n/** URI based data. */\nexport declare interface FileData {\n /** Optional. Display name of the file data. Used to provide a label or filename to distinguish file datas. This field is only returned in PromptMessage for prompt management. It is currently used in the Gemini GenerateContent calls only when server side tools (code_execution, google_search, and url_context) are enabled. This field is not supported in Gemini API. */\n displayName?: string;\n /** Required. URI. */\n fileUri?: string;\n /** Required. The IANA standard MIME type of the source data. */\n mimeType?: string;\n}\n\n/** Partial argument value of the function call. This data type is not supported in Gemini API. */\nexport declare interface PartialArg {\n /** Optional. Represents a null value. */\n nullValue?: 'NULL_VALUE';\n /** Optional. Represents a double value. */\n numberValue?: number;\n /** Optional. Represents a string value. */\n stringValue?: string;\n /** Optional. Represents a boolean value. */\n boolValue?: boolean;\n /** Required. A JSON Path (RFC 9535) to the argument being streamed. https://datatracker.ietf.org/doc/html/rfc9535. e.g. \"$.foo.bar[0].data\". */\n jsonPath?: string;\n /** Optional. Whether this is not the last part of the same json_path. If true, another PartialArg message for the current json_path is expected to follow. */\n willContinue?: boolean;\n}\n\n/** A function call. */\nexport declare interface FunctionCall {\n /** The unique id of the function call. If populated, the client to execute the\n `function_call` and return the response with the matching `id`. */\n id?: string;\n /** Optional. The function parameters and values in JSON object format. See [FunctionDeclaration.parameters] for parameter details. */\n args?: Record<string, unknown>;\n /** Optional. The name of the function to call. Matches [FunctionDeclaration.name]. */\n name?: string;\n /** Optional. The partial argument value of the function call. If provided, represents the arguments/fields that are streamed incrementally. This field is not supported in Gemini API. */\n partialArgs?: PartialArg[];\n /** Optional. Whether this is the last part of the FunctionCall. If true, another partial message for the current FunctionCall is expected to follow. This field is not supported in Gemini API. */\n willContinue?: boolean;\n}\n\n/** Raw media bytes for function response.\n\nText should not be sent as raw bytes, use the FunctionResponse.response\nfield. */\nexport class FunctionResponseBlob {\n /** Required. The IANA standard MIME type of the source data. */\n mimeType?: string;\n /** Required. Inline media bytes.\n * @remarks Encoded as base64 string. */\n data?: string;\n /** Optional. Display name of the blob.\n Used to provide a label or filename to distinguish blobs. */\n displayName?: string;\n}\n\n/** URI based data for function response. */\nexport class FunctionResponseFileData {\n /** Required. URI. */\n fileUri?: string;\n /** Required. The IANA standard MIME type of the source data. */\n mimeType?: string;\n /** Optional. Display name of the file.\n Used to provide a label or filename to distinguish files. */\n displayName?: string;\n}\n\n/** A datatype containing media that is part of a `FunctionResponse` message.\n\nA `FunctionResponsePart` consists of data which has an associated datatype. A\n`FunctionResponsePart` can only contain one of the accepted types in\n`FunctionResponsePart.data`.\n\nA `FunctionResponsePart` must have a fixed IANA MIME type identifying the\ntype and subtype of the media if the `inline_data` field is filled with raw\nbytes. */\nexport class FunctionResponsePart {\n /** Optional. Inline media bytes. */\n inlineData?: FunctionResponseBlob;\n /** Optional. URI based data. */\n fileData?: FunctionResponseFileData;\n}\n/**\n * Creates a `FunctionResponsePart` object from a `base64` encoded `string`.\n */\nexport function createFunctionResponsePartFromBase64(\n data: string,\n mimeType: string,\n): FunctionResponsePart {\n return {\n inlineData: {\n data: data,\n mimeType: mimeType,\n },\n };\n}\n/**\n * Creates a `FunctionResponsePart` object from a `URI` string.\n */\nexport function createFunctionResponsePartFromUri(\n uri: string,\n mimeType: string,\n): FunctionResponsePart {\n return {\n fileData: {\n fileUri: uri,\n mimeType: mimeType,\n },\n };\n}\n\n/** A function response. */\nexport class FunctionResponse {\n /** Signals that function call continues, and more responses will be returned, turning the function call into a generator. Is only applicable to NON_BLOCKING function calls (see FunctionDeclaration.behavior for details), ignored otherwise. If false, the default, future responses will not be considered. Is only applicable to NON_BLOCKING function calls, is ignored otherwise. If set to false, future responses will not be considered. It is allowed to return empty `response` with `will_continue=False` to signal that the function call is finished. */\n willContinue?: boolean;\n /** Specifies how the response should be scheduled in the conversation. Only applicable to NON_BLOCKING function calls, is ignored otherwise. Defaults to WHEN_IDLE. */\n scheduling?: FunctionResponseScheduling;\n /** List of parts that constitute a function response. Each part may\n have a different IANA MIME type. */\n parts?: FunctionResponsePart[];\n /** Optional. The id of the function call this response is for. Populated by the client to match the corresponding function call `id`. */\n id?: string;\n /** Required. The name of the function to call. Matches [FunctionDeclaration.name] and [FunctionCall.name]. */\n name?: string;\n /** Required. The function response in JSON object format. Use \"output\" key to specify function output and \"error\" key to specify error details (if any). If \"output\" and \"error\" keys are not specified, then whole \"response\" is treated as function output. */\n response?: Record<string, unknown>;\n}\n\n/** Content blob. */\nexport declare interface Blob {\n /** Required. Raw bytes.\n * @remarks Encoded as base64 string. */\n data?: string;\n /** Optional. Display name of the blob. Used to provide a label or filename to distinguish blobs. This field is only returned in PromptMessage for prompt management. It is currently used in the Gemini GenerateContent calls only when server side tools (code_execution, google_search, and url_context) are enabled. This field is not supported in Gemini API. */\n displayName?: string;\n /** Required. The IANA standard MIME type of the source data. */\n mimeType?: string;\n}\n\n/** Metadata describes the input video content. */\nexport declare interface VideoMetadata {\n /** Optional. The end offset of the video. */\n endOffset?: string;\n /** Optional. The frame rate of the video sent to the model. If not specified, the default value will be 1.0. The fps range is (0.0, 24.0]. */\n fps?: number;\n /** Optional. The start offset of the video. */\n startOffset?: string;\n}\n\n/** A datatype containing media content.\n\nExactly one field within a Part should be set, representing the specific type\nof content being conveyed. Using multiple fields within the same `Part`\ninstance is considered invalid. */\nexport declare interface Part {\n /** Media resolution for the input media.\n */\n mediaResolution?: PartMediaResolution;\n /** Optional. Result of executing the [ExecutableCode]. */\n codeExecutionResult?: CodeExecutionResult;\n /** Optional. Code generated by the model that is meant to be executed. */\n executableCode?: ExecutableCode;\n /** Optional. URI based data. */\n fileData?: FileData;\n /** Optional. A predicted [FunctionCall] returned from the model that contains a string representing the [FunctionDeclaration.name] with the parameters and their values. */\n functionCall?: FunctionCall;\n /** Optional. The result output of a [FunctionCall] that contains a string representing the [FunctionDeclaration.name] and a structured JSON object containing any output from the function call. It is used as context to the model. */\n functionResponse?: FunctionResponse;\n /** Optional. Inlined bytes data. */\n inlineData?: Blob;\n /** Optional. Text part (can be code). */\n text?: string;\n /** Optional. Indicates if the part is thought from the model. */\n thought?: boolean;\n /** Optional. An opaque signature for the thought so it can be reused in subsequent requests.\n * @remarks Encoded as base64 string. */\n thoughtSignature?: string;\n /** Optional. Video metadata. The metadata should only be specified while the video data is presented in inline_data or file_data. */\n videoMetadata?: VideoMetadata;\n}\n/**\n * Creates a `Part` object from a `URI` string.\n */\nexport function createPartFromUri(\n uri: string,\n mimeType: string,\n mediaResolution?: PartMediaResolutionLevel,\n): Part {\n return {\n fileData: {\n fileUri: uri,\n mimeType: mimeType,\n },\n ...(mediaResolution && {mediaResolution: {level: mediaResolution}}),\n };\n}\n/**\n * Creates a `Part` object from a `text` string.\n */\nexport function createPartFromText(text: string): Part {\n return {\n text: text,\n };\n}\n/**\n * Creates a `Part` object from a `FunctionCall` object.\n */\nexport function createPartFromFunctionCall(\n name: string,\n args: Record<string, unknown>,\n): Part {\n return {\n functionCall: {\n name: name,\n args: args,\n },\n };\n}\n/**\n * Creates a `Part` object from a `FunctionResponse` object.\n */\nexport function createPartFromFunctionResponse(\n id: string,\n name: string,\n response: Record<string, unknown>,\n parts: FunctionResponsePart[] = [],\n): Part {\n return {\n functionResponse: {\n id: id,\n name: name,\n response: response,\n ...(parts.length > 0 && {parts}),\n },\n };\n}\n/**\n * Creates a `Part` object from a `base64` encoded `string`.\n */\nexport function createPartFromBase64(\n data: string,\n mimeType: string,\n mediaResolution?: PartMediaResolutionLevel,\n): Part {\n return {\n inlineData: {\n data: data,\n mimeType: mimeType,\n },\n ...(mediaResolution && {mediaResolution: {level: mediaResolution}}),\n };\n}\n/**\n * Creates a `Part` object from the `outcome` and `output` of a `CodeExecutionResult` object.\n */\nexport function createPartFromCodeExecutionResult(\n outcome: Outcome,\n output: string,\n): Part {\n return {\n codeExecutionResult: {\n outcome: outcome,\n output: output,\n },\n };\n}\n/**\n * Creates a `Part` object from the `code` and `language` of an `ExecutableCode` object.\n */\nexport function createPartFromExecutableCode(\n code: string,\n language: Language,\n): Part {\n return {\n executableCode: {\n code: code,\n language: language,\n },\n };\n}\n\n/** Contains the multi-part content of a message. */\nexport declare interface Content {\n /** List of parts that constitute a single message. Each part may have\n a different IANA MIME type. */\n parts?: Part[];\n /** Optional. The producer of the content. Must be either 'user' or 'model'. Useful to set for multi-turn conversations, otherwise can be left blank or unset. */\n role?: string;\n}\nfunction _isPart(obj: unknown): obj is Part {\n if (typeof obj === 'object' && obj !== null) {\n return (\n 'fileData' in obj ||\n 'text' in obj ||\n 'functionCall' in obj ||\n 'functionResponse' in obj ||\n 'inlineData' in obj ||\n 'videoMetadata' in obj ||\n 'codeExecutionResult' in obj ||\n 'executableCode' in obj\n );\n }\n return false;\n}\nfunction _toParts(partOrString: PartListUnion | string): Part[] {\n const parts: Part[] = [];\n if (typeof partOrString === 'string') {\n parts.push(createPartFromText(partOrString));\n } else if (_isPart(partOrString)) {\n parts.push(partOrString);\n } else if (Array.isArray(partOrString)) {\n if (partOrString.length === 0) {\n throw new Error('partOrString cannot be an empty array');\n }\n for (const part of partOrString) {\n if (typeof part === 'string') {\n parts.push(createPartFromText(part));\n } else if (_isPart(part)) {\n parts.push(part);\n } else {\n throw new Error('element in PartUnion must be a Part object or string');\n }\n }\n } else {\n throw new Error('partOrString must be a Part object, string, or array');\n }\n return parts;\n}\n/**\n * Creates a `Content` object with a user role from a `PartListUnion` object or `string`.\n */\nexport function createUserContent(\n partOrString: PartListUnion | string,\n): Content {\n return {\n role: 'user',\n parts: _toParts(partOrString),\n };\n}\n\n/**\n * Creates a `Content` object with a model role from a `PartListUnion` object or `string`.\n */\nexport function createModelContent(\n partOrString: PartListUnion | string,\n): Content {\n return {\n role: 'model',\n parts: _toParts(partOrString),\n };\n}\n/** HTTP retry options to be used in each of the requests. */\nexport declare interface HttpRetryOptions {\n /** Maximum number of attempts, including the original request.\n If 0 or 1, it means no retries. If not specified, default to 5. */\n attempts?: number;\n}\n\n/** HTTP options to be used in each of the requests. */\nexport declare interface HttpOptions {\n /** The base URL for the AI platform service endpoint. */\n baseUrl?: string;\n /** The resource scope used to constructing the resource name when base_url is set */\n baseUrlResourceScope?: ResourceScope;\n /** Specifies the version of the API to use. */\n apiVersion?: string;\n /** Additional HTTP headers to be sent with the request. */\n headers?: Record<string, string>;\n /** Timeout for the request in milliseconds. */\n timeout?: number;\n /** Extra parameters to add to the request body.\n The structure must match the backend API's request structure.\n - VertexAI backend API docs: https://cloud.google.com/vertex-ai/docs/reference/rest\n - GeminiAPI backend API docs: https://ai.google.dev/api/rest */\n extraBody?: Record<string, unknown>;\n /** HTTP retry options for the request. */\n retryOptions?: HttpRetryOptions;\n}\n\n/** Schema is used to define the format of input/output data.\n\nRepresents a select subset of an [OpenAPI 3.0 schema\nobject](https://spec.openapis.org/oas/v3.0.3#schema-object). More fields may\nbe added in the future as needed. */\nexport declare interface Schema {\n /** Optional. The value should be validated against any (one or more) of the subschemas in the list. */\n anyOf?: Schema[];\n /** Optional. Default value of the data. */\n default?: unknown;\n /** Optional. The description of the data. */\n description?: string;\n /** Optional. Possible values of the element of primitive type with enum format. Examples: 1. We can define direction as : {type:STRING, format:enum, enum:[\"EAST\", NORTH\", \"SOUTH\", \"WEST\"]} 2. We can define apartment number as : {type:INTEGER, format:enum, enum:[\"101\", \"201\", \"301\"]} */\n enum?: string[];\n /** Optional. Example of the object. Will only populated when the object is the root. */\n example?: unknown;\n /** Optional. The format of the data. Supported formats: for NUMBER type: \"float\", \"double\" for INTEGER type: \"int32\", \"int64\" for STRING type: \"email\", \"byte\", etc */\n format?: string;\n /** Optional. SCHEMA FIELDS FOR TYPE ARRAY Schema of the elements of Type.ARRAY. */\n items?: Schema;\n /** Optional. Maximum number of the elements for Type.ARRAY. */\n maxItems?: string;\n /** Optional. Maximum length of the Type.STRING */\n maxLength?: string;\n /** Optional. Maximum number of the properties for Type.OBJECT. */\n maxProperties?: string;\n /** Optional. Maximum value of the Type.INTEGER and Type.NUMBER */\n maximum?: number;\n /** Optional. Minimum number of the elements for Type.ARRAY. */\n minItems?: string;\n /** Optional. SCHEMA FIELDS FOR TYPE STRING Minimum length of the Type.STRING */\n minLength?: string;\n /** Optional. Minimum number of the properties for Type.OBJECT. */\n minProperties?: string;\n /** Optional. SCHEMA FIELDS FOR TYPE INTEGER and NUMBER Minimum value of the Type.INTEGER and Type.NUMBER */\n minimum?: number;\n /** Optional. Indicates if the value may be null. */\n nullable?: boolean;\n /** Optional. Pattern of the Type.STRING to restrict a string to a regular expression. */\n pattern?: string;\n /** Optional. SCHEMA FIELDS FOR TYPE OBJECT Properties of Type.OBJECT. */\n properties?: Record<string, Schema>;\n /** Optional. The order of the properties. Not a standard field in open api spec. Only used to support the order of the properties. */\n propertyOrdering?: string[];\n /** Optional. Required properties of Type.OBJECT. */\n required?: string[];\n /** Optional. The title of the Schema. */\n title?: string;\n /** Optional. The type of the data. */\n type?: Type;\n}\n\n/** Config for model selection. */\nexport declare interface ModelSelectionConfig {\n /** Options for feature selection preference. */\n featureSelectionPreference?: FeatureSelectionPreference;\n}\n\n/** Tool to support computer use. */\nexport declare interface ComputerUse {\n /** Required. The environment being operated. */\n environment?: Environment;\n /** By default, predefined functions are included in the final model call.\n Some of them can be explicitly excluded from being automatically included.\n This can serve two purposes:\n 1. Using a more restricted / different action space.\n 2. Improving the definitions / instructions of predefined functions. */\n excludedPredefinedFunctions?: string[];\n}\n\n/** Tool to retrieve knowledge from the File Search Stores. */\nexport declare interface FileSearch {\n /** The names of the file_search_stores to retrieve from.\n Example: `fileSearchStores/my-file-search-store-123` */\n fileSearchStoreNames?: string[];\n /** The number of file search retrieval chunks to retrieve. */\n topK?: number;\n /** Metadata filter to apply to the file search retrieval documents. See https://google.aip.dev/160 for the syntax of the filter expression. */\n metadataFilter?: string;\n}\n\n/** The API secret. This data type is not supported in Gemini API. */\nexport declare interface ApiAuthApiKeyConfig {\n /** Required. The SecretManager secret version resource name storing API key. e.g. projects/{project}/secrets/{secret}/versions/{version} */\n apiKeySecretVersion?: string;\n /** The API key string. Either this or `api_key_secret_version` must be set. */\n apiKeyString?: string;\n}\n\n/** The generic reusable api auth config. Deprecated. Please use AuthConfig (google/cloud/aiplatform/master/auth.proto) instead. This data type is not supported in Gemini API. */\nexport declare interface ApiAuth {\n /** The API secret. */\n apiKeyConfig?: ApiAuthApiKeyConfig;\n}\n\n/** Config for authentication with API key. This data type is not supported in Gemini API. */\nexport declare interface ApiKeyConfig {\n /** Optional. The name of the SecretManager secret version resource storing the API key. Format: `projects/{project}/secrets/{secrete}/versions/{version}` - If both `api_key_secret` and `api_key_string` are specified, this field takes precedence over `api_key_string`. - If specified, the `secretmanager.versions.access` permission should be granted to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents) on the specified resource. */\n apiKeySecret?: string;\n /** Optional. The API key to be used in the request directly. */\n apiKeyString?: string;\n /** Optional. The location of the API key. */\n httpElementLocation?: HttpElementLocation;\n /** Optional. The parameter name of the API key. E.g. If the API request is \"https://example.com/act?api_key=\", \"api_key\" would be the parameter name. */\n name?: string;\n}\n\n/** Config for Google Service Account Authentication. This data type is not supported in Gemini API. */\nexport declare interface AuthConfigGoogleServiceAccountConfig {\n /** Optional. The service account that the extension execution service runs as. - If the service account is specified, the `iam.serviceAccounts.getAccessToken` permission should be granted to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents) on the specified service account. - If not specified, the Vertex AI Extension Service Agent will be used to execute the Extension. */\n serviceAccount?: string;\n}\n\n/** Config for HTTP Basic Authentication. This data type is not supported in Gemini API. */\nexport declare interface AuthConfigHttpBasicAuthConfig {\n /** Required. The name of the SecretManager secret version resource storing the base64 encoded credentials. Format: `projects/{project}/secrets/{secrete}/versions/{version}` - If specified, the `secretmanager.versions.access` permission should be granted to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents) on the specified resource. */\n credentialSecret?: string;\n}\n\n/** Config for user oauth. This data type is not supported in Gemini API. */\nexport declare interface AuthConfigOauthConfig {\n /** Access token for extension endpoint. Only used to propagate token from [[ExecuteExtensionRequest.runtime_auth_config]] at request time. */\n accessToken?: string;\n /** The service account used to generate access tokens for executing the Extension. - If the service account is specified, the `iam.serviceAccounts.getAccessToken` permission should be granted to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents) on the provided service account. */\n serviceAccount?: string;\n}\n\n/** Config for user OIDC auth. This data type is not supported in Gemini API. */\nexport declare interface AuthConfigOidcConfig {\n /** OpenID Connect formatted ID token for extension endpoint. Only used to propagate token from [[ExecuteExtensionRequest.runtime_auth_config]] at request time. */\n idToken?: string;\n /** The service account used to generate an OpenID Connect (OIDC)-compatible JWT token signed by the Google OIDC Provider (accounts.google.com) for extension endpoint (https://cloud.google.com/iam/docs/create-short-lived-credentials-direct#sa-credentials-oidc). - The audience for the token will be set to the URL in the server url defined in the OpenApi spec. - If the service account is provided, the service account should grant `iam.serviceAccounts.getOpenIdToken` permission to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents). */\n serviceAccount?: string;\n}\n\n/** Auth configuration to run the extension. This data type is not supported in Gemini API. */\nexport declare interface AuthConfig {\n /** Config for API key auth. */\n apiKeyConfig?: ApiKeyConfig;\n /** Type of auth scheme. */\n authType?: AuthType;\n /** Config for Google Service Account auth. */\n googleServiceAccountConfig?: AuthConfigGoogleServiceAccountConfig;\n /** Config for HTTP Basic auth. */\n httpBasicAuthConfig?: AuthConfigHttpBasicAuthConfig;\n /** Config for user oauth. */\n oauthConfig?: AuthConfigOauthConfig;\n /** Config for user OIDC auth. */\n oidcConfig?: AuthConfigOidcConfig;\n}\n\n/** The search parameters to use for the ELASTIC_SEARCH spec. This data type is not supported in Gemini API. */\nexport declare interface ExternalApiElasticSearchParams {\n /** The ElasticSearch index to use. */\n index?: string;\n /** Optional. Number of hits (chunks) to request. When specified, it is passed to Elasticsearch as the `num_hits` param. */\n numHits?: number;\n /** The ElasticSearch search template to use. */\n searchTemplate?: string;\n}\n\n/** The search parameters to use for SIMPLE_SEARCH spec. This data type is not supported in Gemini API. */\nexport declare interface ExternalApiSimpleSearchParams {}\n\n/** Retrieve from data source powered by external API for grounding. The external API is not owned by Google, but need to follow the pre-defined API spec. This data type is not supported in Gemini API. */\nexport declare interface ExternalApi {\n /** The authentication config to access the API. Deprecated. Please use auth_config instead. */\n apiAuth?: ApiAuth;\n /** The API spec that the external API implements. */\n apiSpec?: ApiSpec;\n /** The authentication config to access the API. */\n authConfig?: AuthConfig;\n /** Parameters for the elastic search API. */\n elasticSearchParams?: ExternalApiElasticSearchParams;\n /** The endpoint of the external API. The system will call the API at this endpoint to retrieve the data for grounding. Example: https://acme.com:443/search */\n endpoint?: string;\n /** Parameters for the simple search API. */\n simpleSearchParams?: ExternalApiSimpleSearchParams;\n}\n\n/** Define data stores within engine to filter on in a search call and configurations for those data stores. For more information, see https://cloud.google.com/generative-ai-app-builder/docs/reference/rpc/google.cloud.discoveryengine.v1#datastorespec. This data type is not supported in Gemini API. */\nexport declare interface VertexAISearchDataStoreSpec {\n /** Full resource name of DataStore, such as Format: `projects/{project}/locations/{location}/collections/{collection}/dataStores/{dataStore}` */\n dataStore?: string;\n /** Optional. Filter specification to filter documents in the data store specified by data_store field. For more information on filtering, see [Filtering](https://cloud.google.com/generative-ai-app-builder/docs/filter-search-metadata) */\n filter?: string;\n}\n\n/** Retrieve from Vertex AI Search datastore or engine for grounding. datastore and engine are mutually exclusive. See https://cloud.google.com/products/agent-builder. This data type is not supported in Gemini API. */\nexport declare interface VertexAISearch {\n /** Specifications that define the specific DataStores to be searched, along with configurations for those data stores. This is only considered for Engines with multiple data stores. It should only be set if engine is used. */\n dataStoreSpecs?: VertexAISearchDataStoreSpec[];\n /** Optional. Fully-qualified Vertex AI Search data store resource ID. Format: `projects/{project}/locations/{location}/collections/{collection}/dataStores/{dataStore}` */\n datastore?: string;\n /** Optional. Fully-qualified Vertex AI Search engine resource ID. Format: `projects/{project}/locations/{location}/collections/{collection}/engines/{engine}` */\n engine?: string;\n /** Optional. Filter strings to be passed to the search API. */\n filter?: string;\n /** Optional. Number of search results to return per query. The default value is 10. The maximumm allowed value is 10. */\n maxResults?: number;\n}\n\n/** The definition of the Rag resource. This data type is not supported in Gemini API. */\nexport declare interface VertexRagStoreRagResource {\n /** Optional. RagCorpora resource name. Format: `projects/{project}/locations/{location}/ragCorpora/{rag_corpus}` */\n ragCorpus?: string;\n /** Optional. rag_file_id. The files should be in the same rag_corpus set in rag_corpus field. */\n ragFileIds?: string[];\n}\n\n/** Config for filters. This data type is not supported in Gemini API. */\nexport declare interface RagRetrievalConfigFilter {\n /** Optional. String for metadata filtering. */\n metadataFilter?: string;\n /** Optional. Only returns contexts with vector distance smaller than the threshold. */\n vectorDistanceThreshold?: number;\n /** Optional. Only returns contexts with vector similarity larger than the threshold. */\n vectorSimilarityThreshold?: number;\n}\n\n/** Config for Hybrid Search. This data type is not supported in Gemini API. */\nexport declare interface RagRetrievalConfigHybridSearch {\n /** Optional. Alpha value controls the weight between dense and sparse vector search results. The range is [0, 1], while 0 means sparse vector search only and 1 means dense vector search only. The default value is 0.5 which balances sparse and dense vector search equally. */\n alpha?: number;\n}\n\n/** Config for LlmRanker. This data type is not supported in Gemini API. */\nexport declare interface RagRetrievalConfigRankingLlmRanker {\n /** Optional. The model name used for ranking. See [Supported models](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference#supported-models). */\n modelName?: string;\n}\n\n/** Config for Rank Service. This data type is not supported in Gemini API. */\nexport declare interface RagRetrievalConfigRankingRankService {\n /** Optional. The model name of the rank service. Format: `semantic-ranker-512@latest` */\n modelName?: string;\n}\n\n/** Config for ranking and reranking. This data type is not supported in Gemini API. */\nexport declare interface RagRetrievalConfigRanking {\n /** Optional. Config for LlmRanker. */\n llmRanker?: RagRetrievalConfigRankingLlmRanker;\n /** Optional. Config for Rank Service. */\n rankService?: RagRetrievalConfigRankingRankService;\n}\n\n/** Specifies the context retrieval config. This data type is not supported in Gemini API. */\nexport declare interface RagRetrievalConfig {\n /** Optional. Config for filters. */\n filter?: RagRetrievalConfigFilter;\n /** Optional. Config for Hybrid Search. */\n hybridSearch?: RagRetrievalConfigHybridSearch;\n /** Optional. Config for ranking and reranking. */\n ranking?: RagRetrievalConfigRanking;\n /** Optional. The number of contexts to retrieve. */\n topK?: number;\n}\n\n/** Retrieve from Vertex RAG Store for grounding. This data type is not supported in Gemini API. */\nexport declare interface VertexRagStore {\n /** Optional. Deprecated. Please use rag_resources instead. */\n ragCorpora?: string[];\n /** Optional. The representation of the rag source. It can be used to specify corpus only or ragfiles. Currently only support one corpus or multiple files from one corpus. In the future we may open up multiple corpora support. */\n ragResources?: VertexRagStoreRagResource[];\n /** Optional. The retrieval config for the Rag query. */\n ragRetrievalConfig?: RagRetrievalConfig;\n /** Optional. Number of top k results to return from the selected corpora. */\n similarityTopK?: number;\n /** Optional. Currently only supported for Gemini Multimodal Live API. In Gemini Multimodal Live API, if `store_context` bool is specified, Gemini will leverage it to automatically memorize the interactions between the client and Gemini, and retrieve context when needed to augment the response generation for users' ongoing and future interactions. */\n storeContext?: boolean;\n /** Optional. Only return results with vector distance smaller than the threshold. */\n vectorDistanceThreshold?: number;\n}\n\n/** Defines a retrieval tool that model can call to access external knowledge. This data type is not supported in Gemini API. */\nexport declare interface Retrieval {\n /** Optional. Deprecated. This option is no longer supported. */\n disableAttribution?: boolean;\n /** Use data source powered by external API for grounding. */\n externalApi?: ExternalApi;\n /** Set to use data source powered by Vertex AI Search. */\n vertexAiSearch?: VertexAISearch;\n /** Set to use data source powered by Vertex RAG store. User data is uploaded via the VertexRagDataService. */\n vertexRagStore?: VertexRagStore;\n}\n\n/** Tool that executes code generated by the model, and automatically returns the result to the model. See also [ExecutableCode]and [CodeExecutionResult] which are input and output to this tool. This data type is not supported in Gemini API. */\nexport declare interface ToolCodeExecution {}\n\n/** Tool to search public web data, powered by Vertex AI Search and Sec4 compliance. This data type is not supported in Gemini API. */\nexport declare interface EnterpriseWebSearch {\n /** Optional. List of domains to be excluded from the search results. The default limit is 2000 domains. */\n excludeDomains?: string[];\n /** Optional. Sites with confidence level chosen & above this value will be blocked from the search results. */\n blockingConfidence?: PhishBlockThreshold;\n}\n\n/** Structured representation of a function declaration as defined by the [OpenAPI 3.0 specification](https://spec.openapis.org/oas/v3.0.3). Included in this declaration are the function name, description, parameters and response type. This FunctionDeclaration is a representation of a block of code that can be used as a `Tool` by the model and executed by the client. */\nexport declare interface FunctionDeclaration {\n /** Optional. Description and purpose of the function. Model uses it to decide how and whether to call the function. */\n description?: string;\n /** Required. The name of the function to call. Must start with a letter or an underscore. Must be a-z, A-Z, 0-9, or contain underscores, dots and dashes, with a maximum length of 64. */\n name?: string;\n /** Optional. Describes the parameters to this function in JSON Schema Object format. Reflects the Open API 3.03 Parameter Object. string Key: the name of the parameter. Parameter names are case sensitive. Schema Value: the Schema defining the type used for the parameter. For function with no parameters, this can be left unset. Parameter names must start with a letter or an underscore and must only contain chars a-z, A-Z, 0-9, or underscores with a maximum length of 64. Example with 1 required and 1 optional parameter: type: OBJECT properties: param1: type: STRING param2: type: INTEGER required: - param1 */\n parameters?: Schema;\n /** Optional. Describes the parameters to the function in JSON Schema format. The schema must describe an object where the properties are the parameters to the function. For example: ``` { \"type\": \"object\", \"properties\": { \"name\": { \"type\": \"string\" }, \"age\": { \"type\": \"integer\" } }, \"additionalProperties\": false, \"required\": [\"name\", \"age\"], \"propertyOrdering\": [\"name\", \"age\"] } ``` This field is mutually exclusive with `parameters`. */\n parametersJsonSchema?: unknown;\n /** Optional. Describes the output from this function in JSON Schema format. Reflects the Open API 3.03 Response Object. The Schema defines the type used for the response value of the function. */\n response?: Schema;\n /** Optional. Describes the output from this function in JSON Schema format. The value specified by the schema is the response value of the function. This field is mutually exclusive with `response`. */\n responseJsonSchema?: unknown;\n /** Optional. Specifies the function Behavior. Currently only supported by the BidiGenerateContent method. This field is not supported in Vertex AI. */\n behavior?: Behavior;\n}\n\n/** Tool to retrieve public maps data for grounding, powered by Google. */\nexport declare interface GoogleMaps {\n /** The authentication config to access the API. Only API key is supported. This field is not supported in Gemini API. */\n authConfig?: AuthConfig;\n /** Optional. If true, include the widget context token in the response. */\n enableWidget?: boolean;\n}\n\n/** Represents a time interval, encoded as a Timestamp start (inclusive) and a Timestamp end (exclusive). The start must be less than or equal to the end. When the start equals the end, the interval is empty (matches no time). When both start and end are unspecified, the interval matches any time. */\nexport declare interface Interval {\n /** Optional. Exclusive end of the interval. If specified, a Timestamp matching this interval will have to be before the end. */\n endTime?: string;\n /** Optional. Inclusive start of the interval. If specified, a Timestamp matching this interval will have to be the same or after the start. */\n startTime?: string;\n}\n\n/** GoogleSearch tool type. Tool to support Google Search in Model. Powered by Google. */\nexport declare interface GoogleSearch {\n /** Optional. List of domains to be excluded from the search results. The default limit is 2000 domains. Example: [\"amazon.com\", \"facebook.com\"]. This field is not supported in Gemini API. */\n excludeDomains?: string[];\n /** Optional. Sites with confidence level chosen & above this value will be blocked from the search results. This field is not supported in Gemini API. */\n blockingConfidence?: PhishBlockThreshold;\n /** Optional. Filter search results to a specific time range. If customers set a start time, they must set an end time (and vice versa). This field is not supported in Vertex AI. */\n timeRangeFilter?: Interval;\n}\n\n/** Describes the options to customize dynamic retrieval. */\nexport declare interface DynamicRetrievalConfig {\n /** Optional. The threshold to be used in dynamic retrieval. If not set, a system default value is used. */\n dynamicThreshold?: number;\n /** The mode of the predictor to be used in dynamic retrieval. */\n mode?: DynamicRetrievalConfigMode;\n}\n\n/** Tool to retrieve public web data for grounding, powered by Google. */\nexport declare interface GoogleSearchRetrieval {\n /** Specifies the dynamic retrieval configuration for the given source. */\n dynamicRetrievalConfig?: DynamicRetrievalConfig;\n}\n\n/** Tool to support URL context. */\nexport declare interface UrlContext {}\n\n/** Tool details of a tool that the model may use to generate a response. */\nexport declare interface Tool {\n /** Optional. Retrieval tool type. System will always execute the provided retrieval tool(s) to get external knowledge to answer the prompt. Retrieval results are presented to the model for generation. This field is not supported in Gemini API. */\n retrieval?: Retrieval;\n /** Optional. Tool to support the model interacting directly with the\n computer. If enabled, it automatically populates computer-use specific\n Function Declarations. */\n computerUse?: ComputerUse;\n /** Optional. Tool to retrieve knowledge from the File Search Stores. */\n fileSearch?: FileSearch;\n /** Optional. CodeExecution tool type. Enables the model to execute code as part of generation. */\n codeExecution?: ToolCodeExecution;\n /** Optional. Tool to support searching public web data, powered by Vertex AI Search and Sec4 compliance. This field is not supported in Gemini API. */\n enterpriseWebSearch?: EnterpriseWebSearch;\n /** Optional. Function tool type. One or more function declarations to be passed to the model along with the current user query. Model may decide to call a subset of these functions by populating FunctionCall in the response. User should provide a FunctionResponse for each function call in the next turn. Based on the function responses, Model will generate the final response back to the user. Maximum 512 function declarations can be provided. */\n functionDeclarations?: FunctionDeclaration[];\n /** Optional. GoogleMaps tool type. Tool to support Google Maps in Model. */\n googleMaps?: GoogleMaps;\n /** Optional. GoogleSearch tool type. Tool to support Google Search in Model. Powered by Google. */\n googleSearch?: GoogleSearch;\n /** Optional. Specialized retrieval tool that is powered by Google Search. */\n googleSearchRetrieval?: GoogleSearchRetrieval;\n /** Optional. Tool to support URL context retrieval. */\n urlContext?: UrlContext;\n}\n\n/** An object that represents a latitude/longitude pair.\n\nThis is expressed as a pair of doubles to represent degrees latitude and\ndegrees longitude. Unless specified otherwise, this object must conform to the\n<a href=\"https://en.wikipedia.org/wiki/World_Geodetic_System#1984_version\">\nWGS84 standard</a>. Values must be within normalized ranges. */\nexport declare interface LatLng {\n /** The latitude in degrees. It must be in the range [-90.0, +90.0]. */\n latitude?: number;\n /** The longitude in degrees. It must be in the range [-180.0, +180.0] */\n longitude?: number;\n}\n\n/** Retrieval config.\n */\nexport declare interface RetrievalConfig {\n /** Optional. The location of the user. */\n latLng?: LatLng;\n /** The language code of the user. */\n languageCode?: string;\n}\n\n/** Function calling config. */\nexport declare interface FunctionCallingConfig {\n /** Optional. Function names to call. Only set when the Mode is ANY. Function names should match [FunctionDeclaration.name]. With mode set to ANY, model will predict a function call from the set of function names provided. */\n allowedFunctionNames?: string[];\n /** Optional. Function calling mode. */\n mode?: FunctionCallingConfigMode;\n /** Optional. When set to true, arguments of a single function call will be streamed out in multiple parts/contents/responses. Partial parameter results will be returned in the [FunctionCall.partial_args] field. This field is not supported in Gemini API. */\n streamFunctionCallArguments?: boolean;\n}\n\n/** Tool config.\n\nThis config is shared for all tools provided in the request. */\nexport declare interface ToolConfig {\n /** Optional. Retrieval config. */\n retrievalConfig?: RetrievalConfig;\n /** Optional. Function calling config. */\n functionCallingConfig?: FunctionCallingConfig;\n}\n\n/** ReplicatedVoiceConfig is used to configure replicated voice. */\nexport declare interface ReplicatedVoiceConfig {\n /** The mime type of the replicated voice.\n */\n mimeType?: string;\n /** The sample audio of the replicated voice.\n \n * @remarks Encoded as base64 string. */\n voiceSampleAudio?: string;\n}\n\n/** The configuration for the prebuilt speaker to use. */\nexport declare interface PrebuiltVoiceConfig {\n /** The name of the preset voice to use. */\n voiceName?: string;\n}\n\nexport declare interface VoiceConfig {\n /** If true, the model will use a replicated voice for the response. */\n replicatedVoiceConfig?: ReplicatedVoiceConfig;\n /** The configuration for the prebuilt voice to use. */\n prebuiltVoiceConfig?: PrebuiltVoiceConfig;\n}\n\n/** Configuration for a single speaker in a multi speaker setup. */\nexport declare interface SpeakerVoiceConfig {\n /** Required. The name of the speaker. This should be the same as the speaker name used in the prompt. */\n speaker?: string;\n /** Required. The configuration for the voice of this speaker. */\n voiceConfig?: VoiceConfig;\n}\n\n/** Configuration for a multi-speaker text-to-speech request. */\nexport declare interface MultiSpeakerVoiceConfig {\n /** Required. A list of configurations for the voices of the speakers. Exactly two speaker voice configurations must be provided. */\n speakerVoiceConfigs?: SpeakerVoiceConfig[];\n}\n\nexport declare interface SpeechConfig {\n /** Configuration for the voice of the response. */\n voiceConfig?: VoiceConfig;\n /** Optional. Language code (ISO 639. e.g. en-US) for the speech synthesization. */\n languageCode?: string;\n /** The configuration for a multi-speaker text-to-speech request. This field is mutually exclusive with `voice_config`. */\n multiSpeakerVoiceConfig?: MultiSpeakerVoiceConfig;\n}\n\n/** The configuration for automatic function calling. */\nexport declare interface AutomaticFunctionCallingConfig {\n /** Whether to disable automatic function calling.\n If not set or set to False, will enable automatic function calling.\n If set to True, will disable automatic function calling.\n */\n disable?: boolean;\n /** If automatic function calling is enabled,\n maximum number of remote calls for automatic function calling.\n This number should be a positive integer.\n If not set, SDK will set maximum number of remote calls to 10.\n */\n maximumRemoteCalls?: number;\n /** If automatic function calling is enabled,\n whether to ignore call history to the response.\n If not set, SDK will set ignore_call_history to false,\n and will append the call history to\n GenerateContentResponse.automatic_function_calling_history.\n */\n ignoreCallHistory?: boolean;\n}\n\n/** The thinking features configuration. */\nexport declare interface ThinkingConfig {\n /** Indicates whether to include thoughts in the response. If true, thoughts are returned only if the model supports thought and thoughts are available.\n */\n includeThoughts?: boolean;\n /** Indicates the thinking budget in tokens. 0 is DISABLED. -1 is AUTOMATIC. The default values and allowed ranges are model dependent.\n */\n thinkingBudget?: number;\n /** Optional. The number of thoughts tokens that the model should generate. */\n thinkingLevel?: ThinkingLevel;\n}\n\n/** The image generation configuration to be used in GenerateContentConfig. */\nexport declare interface ImageConfig {\n /** Aspect ratio of the generated images. Supported values are\n \"1:1\", \"2:3\", \"3:2\", \"3:4\", \"4:3\", \"9:16\", \"16:9\", and \"21:9\". */\n aspectRatio?: string;\n /** Optional. Specifies the size of generated images. Supported\n values are `1K`, `2K`, `4K`. If not specified, the model will use default\n value `1K`. */\n imageSize?: string;\n /** Controls the generation of people. Supported values are:\n ALLOW_ALL, ALLOW_ADULT, ALLOW_NONE. */\n personGeneration?: string;\n /** MIME type of the generated image. This field is not\n supported in Gemini API. */\n outputMimeType?: string;\n /** Compression quality of the generated image (for\n ``image/jpeg`` only). This field is not supported in Gemini API. */\n outputCompressionQuality?: number;\n}\n\n/** When automated routing is specified, the routing will be determined by the pretrained routing model and customer provided model routing preference. This data type is not supported in Gemini API. */\nexport declare interface GenerationConfigRoutingConfigAutoRoutingMode {\n /** The model routing preference. */\n modelRoutingPreference?:\n | 'UNKNOWN'\n | 'PRIORITIZE_QUALITY'\n | 'BALANCED'\n | 'PRIORITIZE_COST';\n}\n\n/** When manual routing is set, the specified model will be used directly. This data type is not supported in Gemini API. */\nexport declare interface GenerationConfigRoutingConfigManualRoutingMode {\n /** The model name to use. Only the public LLM models are accepted. See [Supported models](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference#supported-models). */\n modelName?: string;\n}\n\n/** The configuration for routing the request to a specific model. This data type is not supported in Gemini API. */\nexport declare interface GenerationConfigRoutingConfig {\n /** Automated routing. */\n autoMode?: GenerationConfigRoutingConfigAutoRoutingMode;\n /** Manual routing. */\n manualMode?: GenerationConfigRoutingConfigManualRoutingMode;\n}\n\n/** Safety settings. */\nexport declare interface SafetySetting {\n /** Required. Harm category. */\n category?: HarmCategory;\n /** Optional. Specify if the threshold is used for probability or severity score. If not specified, the threshold is used for probability score. This field is not supported in Gemini API. */\n method?: HarmBlockMethod;\n /** Required. The harm block threshold. */\n threshold?: HarmBlockThreshold;\n}\n\n/** Configuration for Model Armor integrations of prompt and responses. This data type is not supported in Gemini API. */\nexport declare interface ModelArmorConfig {\n /** Optional. The name of the Model Armor template to use for prompt sanitization. */\n promptTemplateName?: string;\n /** Optional. The name of the Model Armor template to use for response sanitization. */\n responseTemplateName?: string;\n}\n\n/** Optional model configuration parameters.\n\nFor more information, see `Content generation parameters\n<https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/content-generation-parameters>`_. */\nexport declare interface GenerateContentConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** Instructions for the model to steer it toward better performance.\n For example, \"Answer as concisely as possible\" or \"Don't use technical\n terms in your response\".\n */\n systemInstruction?: ContentUnion;\n /** Value that controls the degree of randomness in token selection.\n Lower temperatures are good for prompts that require a less open-ended or\n creative response, while higher temperatures can lead to more diverse or\n creative results.\n */\n temperature?: number;\n /** Tokens are selected from the most to least probable until the sum\n of their probabilities equals this value. Use a lower value for less\n random responses and a higher value for more random responses.\n */\n topP?: number;\n /** For each token selection step, the ``top_k`` tokens with the\n highest probabilities are sampled. Then tokens are further filtered based\n on ``top_p`` with the final token selected using temperature sampling. Use\n a lower number for less random responses and a higher number for more\n random responses.\n */\n topK?: number;\n /** Number of response variations to return.\n */\n candidateCount?: number;\n /** Maximum number of tokens that can be generated in the response.\n */\n maxOutputTokens?: number;\n /** List of strings that tells the model to stop generating text if one\n of the strings is encountered in the response.\n */\n stopSequences?: string[];\n /** Whether to return the log probabilities of the tokens that were\n chosen by the model at each step.\n */\n responseLogprobs?: boolean;\n /** Number of top candidate tokens to return the log probabilities for\n at each generation step.\n */\n logprobs?: number;\n /** Positive values penalize tokens that already appear in the\n generated text, increasing the probability of generating more diverse\n content.\n */\n presencePenalty?: number;\n /** Positive values penalize tokens that repeatedly appear in the\n generated text, increasing the probability of generating more diverse\n content.\n */\n frequencyPenalty?: number;\n /** When ``seed`` is fixed to a specific number, the model makes a best\n effort to provide the same response for repeated requests. By default, a\n random number is used.\n */\n seed?: number;\n /** Output response mimetype of the generated candidate text.\n Supported mimetype:\n - `text/plain`: (default) Text output.\n - `application/json`: JSON response in the candidates.\n The model needs to be prompted to output the appropriate response type,\n otherwise the behavior is undefined.\n This is a preview feature.\n */\n responseMimeType?: string;\n /** The `Schema` object allows the definition of input and output data types.\n These types can be objects, but also primitives and arrays.\n Represents a select subset of an [OpenAPI 3.0 schema\n object](https://spec.openapis.org/oas/v3.0.3#schema).\n If set, a compatible response_mime_type must also be set.\n Compatible mimetypes: `application/json`: Schema for JSON response.\n\n If `response_schema` doesn't process your schema correctly, try using\n `response_json_schema` instead.\n */\n responseSchema?: SchemaUnion;\n /** Optional. Output schema of the generated response.\n This is an alternative to `response_schema` that accepts [JSON\n Schema](https://json-schema.org/). If set, `response_schema` must be\n omitted, but `response_mime_type` is required. While the full JSON Schema\n may be sent, not all features are supported. Specifically, only the\n following properties are supported: - `$id` - `$defs` - `$ref` - `$anchor`\n - `type` - `format` - `title` - `description` - `enum` (for strings and\n numbers) - `items` - `prefixItems` - `minItems` - `maxItems` - `minimum` -\n `maximum` - `anyOf` - `oneOf` (interpreted the same as `anyOf`) -\n `properties` - `additionalProperties` - `required` The non-standard\n `propertyOrdering` property may also be set. Cyclic references are\n unrolled to a limited degree and, as such, may only be used within\n non-required properties. (Nullable properties are not sufficient.) If\n `$ref` is set on a sub-schema, no other properties, except for than those\n starting as a `$`, may be set. */\n responseJsonSchema?: unknown;\n /** Configuration for model router requests.\n */\n routingConfig?: GenerationConfigRoutingConfig;\n /** Configuration for model selection.\n */\n modelSelectionConfig?: ModelSelectionConfig;\n /** Safety settings in the request to block unsafe content in the\n response.\n */\n safetySettings?: SafetySetting[];\n /** Code that enables the system to interact with external systems to\n perform an action outside of the knowledge and scope of the model.\n */\n tools?: ToolListUnion;\n /** Associates model output to a specific function call.\n */\n toolConfig?: ToolConfig;\n /** Labels with user-defined metadata to break down billed charges. */\n labels?: Record<string, string>;\n /** Resource name of a context cache that can be used in subsequent\n requests.\n */\n cachedContent?: string;\n /** The requested modalities of the response. Represents the set of\n modalities that the model can return.\n */\n responseModalities?: string[];\n /** If specified, the media resolution specified will be used.\n */\n mediaResolution?: MediaResolution;\n /** The speech generation configuration.\n */\n speechConfig?: SpeechConfigUnion;\n /** If enabled, audio timestamp will be included in the request to the\n model.\n */\n audioTimestamp?: boolean;\n /** The configuration for automatic function calling.\n */\n automaticFunctionCalling?: AutomaticFunctionCallingConfig;\n /** The thinking features configuration.\n */\n thinkingConfig?: ThinkingConfig;\n /** The image generation configuration.\n */\n imageConfig?: ImageConfig;\n /** Enables enhanced civic answers. It may not be available for all\n models. This field is not supported in Vertex AI.\n */\n enableEnhancedCivicAnswers?: boolean;\n /** Settings for prompt and response sanitization using the Model Armor\n service. If supplied, safety_settings must not be supplied.\n */\n modelArmorConfig?: ModelArmorConfig;\n}\n\n/** Config for models.generate_content parameters. */\nexport declare interface GenerateContentParameters {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model: string;\n /** Content of the request.\n */\n contents: ContentListUnion;\n /** Configuration that contains optional model parameters.\n */\n config?: GenerateContentConfig;\n}\n\n/** A wrapper class for the http response. */\nexport class HttpResponse {\n /** Used to retain the processed HTTP headers in the response. */\n headers?: Record<string, string>;\n /**\n * The original http response.\n */\n responseInternal: Response;\n\n constructor(response: Response) {\n // Process the headers.\n const headers: Record<string, string> = {};\n for (const pair of response.headers.entries()) {\n headers[pair[0]] = pair[1];\n }\n this.headers = headers;\n\n // Keep the original response.\n this.responseInternal = response;\n }\n\n json(): Promise<unknown> {\n return this.responseInternal.json();\n }\n}\n\n/** Callbacks for the live API. */\nexport interface LiveCallbacks {\n /**\n * Called when the websocket connection is established.\n */\n onopen?: (() => void) | null;\n /**\n * Called when a message is received from the server.\n */\n onmessage: (e: LiveServerMessage) => void;\n /**\n * Called when an error occurs.\n */\n onerror?: ((e: ErrorEvent) => void) | null;\n /**\n * Called when the websocket connection is closed.\n */\n onclose?: ((e: CloseEvent) => void) | null;\n}\n\n/** Represents a whole or partial calendar date, such as a birthday. The time of day and time zone are either specified elsewhere or are insignificant. The date is relative to the Gregorian Calendar. This can represent one of the following: * A full date, with non-zero year, month, and day values. * A month and day, with a zero year (for example, an anniversary). * A year on its own, with a zero month and a zero day. * A year and month, with a zero day (for example, a credit card expiration date). Related types: * google.type.TimeOfDay * google.type.DateTime * google.protobuf.Timestamp. This data type is not supported in Gemini API. */\nexport declare interface GoogleTypeDate {\n /** Day of a month. Must be from 1 to 31 and valid for the year and month, or 0 to specify a year by itself or a year and month where the day isn't significant. */\n day?: number;\n /** Month of a year. Must be from 1 to 12, or 0 to specify a year without a month and day. */\n month?: number;\n /** Year of the date. Must be from 1 to 9999, or 0 to specify a date without a year. */\n year?: number;\n}\n\n/** Source attributions for content. This data type is not supported in Gemini API. */\nexport declare interface Citation {\n /** Output only. End index into the content. */\n endIndex?: number;\n /** Output only. License of the attribution. */\n license?: string;\n /** Output only. Publication date of the attribution. */\n publicationDate?: GoogleTypeDate;\n /** Output only. Start index into the content. */\n startIndex?: number;\n /** Output only. Title of the attribution. */\n title?: string;\n /** Output only. Url reference of the attribution. */\n uri?: string;\n}\n\n/** Citation information when the model quotes another source. */\nexport declare interface CitationMetadata {\n /** Contains citation information when the model directly quotes, at\n length, from another source. Can include traditional websites and code\n repositories.\n */\n citations?: Citation[];\n}\n\n/** Author attribution for a photo or review. This data type is not supported in Gemini API. */\nexport declare interface GroundingChunkMapsPlaceAnswerSourcesAuthorAttribution {\n /** Name of the author of the Photo or Review. */\n displayName?: string;\n /** Profile photo URI of the author of the Photo or Review. */\n photoUri?: string;\n /** URI of the author of the Photo or Review. */\n uri?: string;\n}\n\n/** Encapsulates a review snippet. This data type is not supported in Gemini API. */\nexport declare interface GroundingChunkMapsPlaceAnswerSourcesReviewSnippet {\n /** This review's author. */\n authorAttribution?: GroundingChunkMapsPlaceAnswerSourcesAuthorAttribution;\n /** A link where users can flag a problem with the review. */\n flagContentUri?: string;\n /** A link to show the review on Google Maps. */\n googleMapsUri?: string;\n /** A string of formatted recent time, expressing the review time relative to the current time in a form appropriate for the language and country. */\n relativePublishTimeDescription?: string;\n /** A reference representing this place review which may be used to look up this place review again. */\n review?: string;\n /** Id of the review referencing the place. */\n reviewId?: string;\n /** Title of the review. */\n title?: string;\n}\n\n/** Sources used to generate the place answer. This data type is not supported in Gemini API. */\nexport declare interface GroundingChunkMapsPlaceAnswerSources {\n /** A link where users can flag a problem with the generated answer. */\n flagContentUri?: string;\n /** Snippets of reviews that are used to generate the answer. */\n reviewSnippets?: GroundingChunkMapsPlaceAnswerSourcesReviewSnippet[];\n}\n\n/** Chunk from Google Maps. This data type is not supported in Gemini API. */\nexport declare interface GroundingChunkMaps {\n /** Sources used to generate the place answer. This includes review snippets and photos that were used to generate the answer, as well as uris to flag content. */\n placeAnswerSources?: GroundingChunkMapsPlaceAnswerSources;\n /** This Place's resource name, in `places/{place_id}` format. Can be used to look up the Place. */\n placeId?: string;\n /** Text of the place answer. */\n text?: string;\n /** Title of the place. */\n title?: string;\n /** URI reference of the place. */\n uri?: string;\n}\n\n/** Represents where the chunk starts and ends in the document. This data type is not supported in Gemini API. */\nexport declare interface RagChunkPageSpan {\n /** Page where chunk starts in the document. Inclusive. 1-indexed. */\n firstPage?: number;\n /** Page where chunk ends in the document. Inclusive. 1-indexed. */\n lastPage?: number;\n}\n\n/** A RagChunk includes the content of a chunk of a RagFile, and associated metadata. This data type is not supported in Gemini API. */\nexport declare interface RagChunk {\n /** If populated, represents where the chunk starts and ends in the document. */\n pageSpan?: RagChunkPageSpan;\n /** The content of the chunk. */\n text?: string;\n}\n\n/** Chunk from context retrieved by the retrieval tools. This data type is not supported in Gemini API. */\nexport declare interface GroundingChunkRetrievedContext {\n /** Output only. The full document name for the referenced Vertex AI Search document. */\n documentName?: string;\n /** Additional context for the RAG retrieval result. This is only populated when using the RAG retrieval tool. */\n ragChunk?: RagChunk;\n /** Text of the attribution. */\n text?: string;\n /** Title of the attribution. */\n title?: string;\n /** URI reference of the attribution. */\n uri?: string;\n}\n\n/** Chunk from the web. */\nexport declare interface GroundingChunkWeb {\n /** Domain of the (original) URI. This field is not supported in Gemini API. */\n domain?: string;\n /** Title of the chunk. */\n title?: string;\n /** URI reference of the chunk. */\n uri?: string;\n}\n\n/** Grounding chunk. */\nexport declare interface GroundingChunk {\n /** Grounding chunk from Google Maps. This field is not supported in Gemini API. */\n maps?: GroundingChunkMaps;\n /** Grounding chunk from context retrieved by the retrieval tools. This field is not supported in Gemini API. */\n retrievedContext?: GroundingChunkRetrievedContext;\n /** Grounding chunk from the web. */\n web?: GroundingChunkWeb;\n}\n\n/** Segment of the content. */\nexport declare interface Segment {\n /** Output only. End index in the given Part, measured in bytes. Offset from the start of the Part, exclusive, starting at zero. */\n endIndex?: number;\n /** Output only. The index of a Part object within its parent Content object. */\n partIndex?: number;\n /** Output only. Start index in the given Part, measured in bytes. Offset from the start of the Part, inclusive, starting at zero. */\n startIndex?: number;\n /** Output only. The text corresponding to the segment from the response. */\n text?: string;\n}\n\n/** Grounding support. */\nexport declare interface GroundingSupport {\n /** Confidence score of the support references. Ranges from 0 to 1. 1 is the most confident. For Gemini 2.0 and before, this list must have the same size as the grounding_chunk_indices. For Gemini 2.5 and after, this list will be empty and should be ignored. */\n confidenceScores?: number[];\n /** A list of indices (into 'grounding_chunk') specifying the citations associated with the claim. For instance [1,3,4] means that grounding_chunk[1], grounding_chunk[3], grounding_chunk[4] are the retrieved content attributed to the claim. */\n groundingChunkIndices?: number[];\n /** Segment of the content this support belongs to. */\n segment?: Segment;\n}\n\n/** Metadata related to retrieval in the grounding flow. */\nexport declare interface RetrievalMetadata {\n /** Optional. Score indicating how likely information from Google Search could help answer the prompt. The score is in the range `[0, 1]`, where 0 is the least likely and 1 is the most likely. This score is only populated when Google Search grounding and dynamic retrieval is enabled. It will be compared to the threshold to determine whether to trigger Google Search. */\n googleSearchDynamicRetrievalScore?: number;\n}\n\n/** Google search entry point. */\nexport declare interface SearchEntryPoint {\n /** Optional. Web content snippet that can be embedded in a web page or an app webview. */\n renderedContent?: string;\n /** Optional. Base64 encoded JSON representing array of tuple.\n * @remarks Encoded as base64 string. */\n sdkBlob?: string;\n}\n\n/** Source content flagging uri for a place or review. This is currently populated only for Google Maps grounding. This data type is not supported in Gemini API. */\nexport declare interface GroundingMetadataSourceFlaggingUri {\n /** A link where users can flag a problem with the source (place or review). */\n flagContentUri?: string;\n /** Id of the place or review. */\n sourceId?: string;\n}\n\n/** Metadata returned to client when grounding is enabled. */\nexport declare interface GroundingMetadata {\n /** Optional. Output only. Resource name of the Google Maps widget context token to be used with the PlacesContextElement widget to render contextual data. This is populated only for Google Maps grounding. This field is not supported in Gemini API. */\n googleMapsWidgetContextToken?: string;\n /** List of supporting references retrieved from specified grounding source. */\n groundingChunks?: GroundingChunk[];\n /** Optional. List of grounding support. */\n groundingSupports?: GroundingSupport[];\n /** Optional. Output only. Retrieval metadata. */\n retrievalMetadata?: RetrievalMetadata;\n /** Optional. Queries executed by the retrieval tools. This field is not supported in Gemini API. */\n retrievalQueries?: string[];\n /** Optional. Google search entry for the following-up web searches. */\n searchEntryPoint?: SearchEntryPoint;\n /** Optional. Output only. List of source flagging uris. This is currently populated only for Google Maps grounding. This field is not supported in Gemini API. */\n sourceFlaggingUris?: GroundingMetadataSourceFlaggingUri[];\n /** Optional. Web search queries for the following-up web search. */\n webSearchQueries?: string[];\n}\n\n/** Candidate for the logprobs token and score. */\nexport declare interface LogprobsResultCandidate {\n /** The candidate's log probability. */\n logProbability?: number;\n /** The candidate's token string value. */\n token?: string;\n /** The candidate's token id value. */\n tokenId?: number;\n}\n\n/** Candidates with top log probabilities at each decoding step. */\nexport declare interface LogprobsResultTopCandidates {\n /** Sorted by log probability in descending order. */\n candidates?: LogprobsResultCandidate[];\n}\n\n/** Logprobs Result */\nexport declare interface LogprobsResult {\n /** Length = total number of decoding steps. The chosen candidates may or may not be in top_candidates. */\n chosenCandidates?: LogprobsResultCandidate[];\n /** Length = total number of decoding steps. */\n topCandidates?: LogprobsResultTopCandidates[];\n}\n\n/** Safety rating corresponding to the generated content. */\nexport declare interface SafetyRating {\n /** Output only. Indicates whether the content was filtered out because of this rating. */\n blocked?: boolean;\n /** Output only. Harm category. */\n category?: HarmCategory;\n /** Output only. The overwritten threshold for the safety category of Gemini 2.0 image out. If minors are detected in the output image, the threshold of each safety category will be overwritten if user sets a lower threshold. This field is not supported in Gemini API. */\n overwrittenThreshold?: HarmBlockThreshold;\n /** Output only. Harm probability levels in the content. */\n probability?: HarmProbability;\n /** Output only. Harm probability score. This field is not supported in Gemini API. */\n probabilityScore?: number;\n /** Output only. Harm severity levels in the content. This field is not supported in Gemini API. */\n severity?: HarmSeverity;\n /** Output only. Harm severity score. This field is not supported in Gemini API. */\n severityScore?: number;\n}\n\n/** Context of the a single url retrieval. */\nexport declare interface UrlMetadata {\n /** Retrieved url by the tool. */\n retrievedUrl?: string;\n /** Status of the url retrieval. */\n urlRetrievalStatus?: UrlRetrievalStatus;\n}\n\n/** Metadata related to url context retrieval tool. */\nexport declare interface UrlContextMetadata {\n /** Output only. List of url context. */\n urlMetadata?: UrlMetadata[];\n}\n\n/** A response candidate generated from the model. */\nexport declare interface Candidate {\n /** Contains the multi-part content of the response.\n */\n content?: Content;\n /** Source attribution of the generated content.\n */\n citationMetadata?: CitationMetadata;\n /** Describes the reason the model stopped generating tokens.\n */\n finishMessage?: string;\n /** Number of tokens for this candidate.\n */\n tokenCount?: number;\n /** The reason why the model stopped generating tokens.\n If empty, the model has not stopped generating the tokens.\n */\n finishReason?: FinishReason;\n /** Output only. Average log probability score of the candidate. */\n avgLogprobs?: number;\n /** Output only. Metadata specifies sources used to ground generated content. */\n groundingMetadata?: GroundingMetadata;\n /** Output only. Index of the candidate. */\n index?: number;\n /** Output only. Log-likelihood scores for the response tokens and top tokens */\n logprobsResult?: LogprobsResult;\n /** Output only. List of ratings for the safety of a response candidate. There is at most one rating per category. */\n safetyRatings?: SafetyRating[];\n /** Output only. Metadata related to url context retrieval tool. */\n urlContextMetadata?: UrlContextMetadata;\n}\n\n/** Content filter results for a prompt sent in the request. Note: This is sent only in the first stream chunk and only if no candidates were generated due to content violations. */\nexport class GenerateContentResponsePromptFeedback {\n /** Output only. The reason why the prompt was blocked. */\n blockReason?: BlockedReason;\n /** Output only. A readable message that explains the reason why the prompt was blocked. This field is not supported in Gemini API. */\n blockReasonMessage?: string;\n /** Output only. A list of safety ratings for the prompt. There is one rating per category. */\n safetyRatings?: SafetyRating[];\n}\n\n/** Represents token counting info for a single modality. */\nexport declare interface ModalityTokenCount {\n /** The modality associated with this token count. */\n modality?: MediaModality;\n /** Number of tokens. */\n tokenCount?: number;\n}\n\n/** Usage metadata about the content generation request and response. This message provides a detailed breakdown of token usage and other relevant metrics. This data type is not supported in Gemini API. */\nexport class GenerateContentResponseUsageMetadata {\n /** Output only. A detailed breakdown of the token count for each modality in the cached content. */\n cacheTokensDetails?: ModalityTokenCount[];\n /** Output only. The number of tokens in the cached content that was used for this request. */\n cachedContentTokenCount?: number;\n /** The total number of tokens in the generated candidates. */\n candidatesTokenCount?: number;\n /** Output only. A detailed breakdown of the token count for each modality in the generated candidates. */\n candidatesTokensDetails?: ModalityTokenCount[];\n /** The total number of tokens in the prompt. This includes any text, images, or other media provided in the request. When `cached_content` is set, this also includes the number of tokens in the cached content. */\n promptTokenCount?: number;\n /** Output only. A detailed breakdown of the token count for each modality in the prompt. */\n promptTokensDetails?: ModalityTokenCount[];\n /** Output only. The number of tokens that were part of the model's generated \"thoughts\" output, if applicable. */\n thoughtsTokenCount?: number;\n /** Output only. The number of tokens in the results from tool executions, which are provided back to the model as input, if applicable. */\n toolUsePromptTokenCount?: number;\n /** Output only. A detailed breakdown by modality of the token counts from the results of tool executions, which are provided back to the model as input. */\n toolUsePromptTokensDetails?: ModalityTokenCount[];\n /** The total number of tokens for the entire request. This is the sum of `prompt_token_count`, `candidates_token_count`, `tool_use_prompt_token_count`, and `thoughts_token_count`. */\n totalTokenCount?: number;\n /** Output only. The traffic type for this request. */\n trafficType?: TrafficType;\n}\n\n/** Response message for PredictionService.GenerateContent. */\nexport class GenerateContentResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** Response variations returned by the model.\n */\n candidates?: Candidate[];\n /** Timestamp when the request is made to the server.\n */\n createTime?: string;\n /** The history of automatic function calling.\n */\n automaticFunctionCallingHistory?: Content[];\n /** Output only. The model version used to generate the response. */\n modelVersion?: string;\n /** Output only. Content filter results for a prompt sent in the request. Note: Sent only in the first stream chunk. Only happens when no candidates were generated due to content violations. */\n promptFeedback?: GenerateContentResponsePromptFeedback;\n /** Output only. response_id is used to identify each response. It is the encoding of the event_id. */\n responseId?: string;\n /** Usage metadata about the response(s). */\n usageMetadata?: GenerateContentResponseUsageMetadata;\n /**\n * Returns the concatenation of all text parts from the first candidate in the response.\n *\n * @remarks\n * If there are multiple candidates in the response, the text from the first\n * one will be returned.\n * If there are non-text parts in the response, the concatenation of all text\n * parts will be returned, and a warning will be logged.\n * If there are thought parts in the response, the concatenation of all text\n * parts excluding the thought parts will be returned.\n *\n * @example\n * ```ts\n * const response = await ai.models.generateContent({\n * model: 'gemini-2.0-flash',\n * contents:\n * 'Why is the sky blue?',\n * });\n *\n * console.debug(response.text);\n * ```\n */\n get text(): string | undefined {\n if (this.candidates?.[0]?.content?.parts?.length === 0) {\n return undefined;\n }\n if (this.candidates && this.candidates.length > 1) {\n console.warn(\n 'there are multiple candidates in the response, returning text from the first one.',\n );\n }\n let text = '';\n let anyTextPartText = false;\n const nonTextParts = [];\n for (const part of this.candidates?.[0]?.content?.parts ?? []) {\n for (const [fieldName, fieldValue] of Object.entries(part)) {\n if (\n fieldName !== 'text' &&\n fieldName !== 'thought' &&\n fieldName !== 'thoughtSignature' &&\n (fieldValue !== null || fieldValue !== undefined)\n ) {\n nonTextParts.push(fieldName);\n }\n }\n if (typeof part.text === 'string') {\n if (typeof part.thought === 'boolean' && part.thought) {\n continue;\n }\n anyTextPartText = true;\n text += part.text;\n }\n }\n if (nonTextParts.length > 0) {\n console.warn(\n `there are non-text parts ${nonTextParts} in the response, returning concatenation of all text parts. Please refer to the non text parts for a full response from model.`,\n );\n }\n // part.text === '' is different from part.text is null\n return anyTextPartText ? text : undefined;\n }\n\n /**\n * Returns the concatenation of all inline data parts from the first candidate\n * in the response.\n *\n * @remarks\n * If there are multiple candidates in the response, the inline data from the\n * first one will be returned. If there are non-inline data parts in the\n * response, the concatenation of all inline data parts will be returned, and\n * a warning will be logged.\n */\n get data(): string | undefined {\n if (this.candidates?.[0]?.content?.parts?.length === 0) {\n return undefined;\n }\n if (this.candidates && this.candidates.length > 1) {\n console.warn(\n 'there are multiple candidates in the response, returning data from the first one.',\n );\n }\n let data = '';\n const nonDataParts = [];\n for (const part of this.candidates?.[0]?.content?.parts ?? []) {\n for (const [fieldName, fieldValue] of Object.entries(part)) {\n if (\n fieldName !== 'inlineData' &&\n (fieldValue !== null || fieldValue !== undefined)\n ) {\n nonDataParts.push(fieldName);\n }\n }\n if (part.inlineData && typeof part.inlineData.data === 'string') {\n data += atob(part.inlineData.data);\n }\n }\n if (nonDataParts.length > 0) {\n console.warn(\n `there are non-data parts ${nonDataParts} in the response, returning concatenation of all data parts. Please refer to the non data parts for a full response from model.`,\n );\n }\n return data.length > 0 ? btoa(data) : undefined;\n }\n\n /**\n * Returns the function calls from the first candidate in the response.\n *\n * @remarks\n * If there are multiple candidates in the response, the function calls from\n * the first one will be returned.\n * If there are no function calls in the response, undefined will be returned.\n *\n * @example\n * ```ts\n * const controlLightFunctionDeclaration: FunctionDeclaration = {\n * name: 'controlLight',\n * parameters: {\n * type: Type.OBJECT,\n * description: 'Set the brightness and color temperature of a room light.',\n * properties: {\n * brightness: {\n * type: Type.NUMBER,\n * description:\n * 'Light level from 0 to 100. Zero is off and 100 is full brightness.',\n * },\n * colorTemperature: {\n * type: Type.STRING,\n * description:\n * 'Color temperature of the light fixture which can be `daylight`, `cool` or `warm`.',\n * },\n * },\n * required: ['brightness', 'colorTemperature'],\n * };\n * const response = await ai.models.generateContent({\n * model: 'gemini-2.0-flash',\n * contents: 'Dim the lights so the room feels cozy and warm.',\n * config: {\n * tools: [{functionDeclarations: [controlLightFunctionDeclaration]}],\n * toolConfig: {\n * functionCallingConfig: {\n * mode: FunctionCallingConfigMode.ANY,\n * allowedFunctionNames: ['controlLight'],\n * },\n * },\n * },\n * });\n * console.debug(JSON.stringify(response.functionCalls));\n * ```\n */\n get functionCalls(): FunctionCall[] | undefined {\n if (this.candidates?.[0]?.content?.parts?.length === 0) {\n return undefined;\n }\n if (this.candidates && this.candidates.length > 1) {\n console.warn(\n 'there are multiple candidates in the response, returning function calls from the first one.',\n );\n }\n const functionCalls = this.candidates?.[0]?.content?.parts\n ?.filter((part) => part.functionCall)\n .map((part) => part.functionCall)\n .filter(\n (functionCall): functionCall is FunctionCall =>\n functionCall !== undefined,\n );\n if (functionCalls?.length === 0) {\n return undefined;\n }\n return functionCalls;\n }\n /**\n * Returns the first executable code from the first candidate in the response.\n *\n * @remarks\n * If there are multiple candidates in the response, the executable code from\n * the first one will be returned.\n * If there are no executable code in the response, undefined will be\n * returned.\n *\n * @example\n * ```ts\n * const response = await ai.models.generateContent({\n * model: 'gemini-2.0-flash',\n * contents:\n * 'What is the sum of the first 50 prime numbers? Generate and run code for the calculation, and make sure you get all 50.'\n * config: {\n * tools: [{codeExecution: {}}],\n * },\n * });\n *\n * console.debug(response.executableCode);\n * ```\n */\n get executableCode(): string | undefined {\n if (this.candidates?.[0]?.content?.parts?.length === 0) {\n return undefined;\n }\n if (this.candidates && this.candidates.length > 1) {\n console.warn(\n 'there are multiple candidates in the response, returning executable code from the first one.',\n );\n }\n const executableCode = this.candidates?.[0]?.content?.parts\n ?.filter((part) => part.executableCode)\n .map((part) => part.executableCode)\n .filter(\n (executableCode): executableCode is ExecutableCode =>\n executableCode !== undefined,\n );\n if (executableCode?.length === 0) {\n return undefined;\n }\n\n return executableCode?.[0]?.code;\n }\n /**\n * Returns the first code execution result from the first candidate in the response.\n *\n * @remarks\n * If there are multiple candidates in the response, the code execution result from\n * the first one will be returned.\n * If there are no code execution result in the response, undefined will be returned.\n *\n * @example\n * ```ts\n * const response = await ai.models.generateContent({\n * model: 'gemini-2.0-flash',\n * contents:\n * 'What is the sum of the first 50 prime numbers? Generate and run code for the calculation, and make sure you get all 50.'\n * config: {\n * tools: [{codeExecution: {}}],\n * },\n * });\n *\n * console.debug(response.codeExecutionResult);\n * ```\n */\n get codeExecutionResult(): string | undefined {\n if (this.candidates?.[0]?.content?.parts?.length === 0) {\n return undefined;\n }\n if (this.candidates && this.candidates.length > 1) {\n console.warn(\n 'there are multiple candidates in the response, returning code execution result from the first one.',\n );\n }\n const codeExecutionResult = this.candidates?.[0]?.content?.parts\n ?.filter((part) => part.codeExecutionResult)\n .map((part) => part.codeExecutionResult)\n .filter(\n (codeExecutionResult): codeExecutionResult is CodeExecutionResult =>\n codeExecutionResult !== undefined,\n );\n if (codeExecutionResult?.length === 0) {\n return undefined;\n }\n return codeExecutionResult?.[0]?.output;\n }\n}\n\nexport type ReferenceImage =\n | RawReferenceImage\n | MaskReferenceImage\n | ControlReferenceImage\n | StyleReferenceImage\n | SubjectReferenceImage\n | ContentReferenceImage;\n\n/** Parameters for the request to edit an image. */\nexport declare interface EditImageParameters {\n /** The model to use. */\n model: string;\n /** A text description of the edit to apply to the image. */\n prompt: string;\n /** The reference images for Imagen 3 editing. */\n referenceImages: ReferenceImage[];\n /** Configuration for editing. */\n config?: EditImageConfig;\n}\n\n/** Optional parameters for the embed_content method. */\nexport declare interface EmbedContentConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** Type of task for which the embedding will be used.\n */\n taskType?: string;\n /** Title for the text. Only applicable when TaskType is\n `RETRIEVAL_DOCUMENT`.\n */\n title?: string;\n /** Reduced dimension for the output embedding. If set,\n excessive values in the output embedding are truncated from the end.\n Supported by newer models since 2024 only. You cannot set this value if\n using the earlier model (`models/embedding-001`).\n */\n outputDimensionality?: number;\n /** Vertex API only. The MIME type of the input.\n */\n mimeType?: string;\n /** Vertex API only. Whether to silently truncate inputs longer than\n the max sequence length. If this option is set to false, oversized inputs\n will lead to an INVALID_ARGUMENT error, similar to other text APIs.\n */\n autoTruncate?: boolean;\n}\n\n/** Parameters for the embed_content method. */\nexport declare interface EmbedContentParameters {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model: string;\n /** The content to embed. Only the `parts.text` fields will be counted.\n */\n contents: ContentListUnion;\n /** Configuration that contains optional parameters.\n */\n config?: EmbedContentConfig;\n}\n\n/** Statistics of the input text associated with the result of content embedding. */\nexport declare interface ContentEmbeddingStatistics {\n /** Vertex API only. If the input text was truncated due to having\n a length longer than the allowed maximum input.\n */\n truncated?: boolean;\n /** Vertex API only. Number of tokens of the input text.\n */\n tokenCount?: number;\n}\n\n/** The embedding generated from an input content. */\nexport declare interface ContentEmbedding {\n /** A list of floats representing an embedding.\n */\n values?: number[];\n /** Vertex API only. Statistics of the input text associated with this\n embedding.\n */\n statistics?: ContentEmbeddingStatistics;\n}\n\n/** Request-level metadata for the Vertex Embed Content API. */\nexport declare interface EmbedContentMetadata {\n /** Vertex API only. The total number of billable characters included\n in the request.\n */\n billableCharacterCount?: number;\n}\n\n/** Response for the embed_content method. */\nexport class EmbedContentResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** The embeddings for each request, in the same order as provided in\n the batch request.\n */\n embeddings?: ContentEmbedding[];\n /** Vertex API only. Metadata about the request.\n */\n metadata?: EmbedContentMetadata;\n}\n\n/** The config for generating an images. */\nexport declare interface GenerateImagesConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** Cloud Storage URI used to store the generated images. */\n outputGcsUri?: string;\n /** Description of what to discourage in the generated images. */\n negativePrompt?: string;\n /** Number of images to generate. */\n numberOfImages?: number;\n /** Aspect ratio of the generated images. Supported values are\n \"1:1\", \"3:4\", \"4:3\", \"9:16\", and \"16:9\". */\n aspectRatio?: string;\n /** Controls how much the model adheres to the text prompt. Large\n values increase output and prompt alignment, but may compromise image\n quality. */\n guidanceScale?: number;\n /** Random seed for image generation. This is not available when\n ``add_watermark`` is set to true. */\n seed?: number;\n /** Filter level for safety filtering. */\n safetyFilterLevel?: SafetyFilterLevel;\n /** Allows generation of people by the model. */\n personGeneration?: PersonGeneration;\n /** Whether to report the safety scores of each generated image and\n the positive prompt in the response. */\n includeSafetyAttributes?: boolean;\n /** Whether to include the Responsible AI filter reason if the image\n is filtered out of the response. */\n includeRaiReason?: boolean;\n /** Language of the text in the prompt. */\n language?: ImagePromptLanguage;\n /** MIME type of the generated image. */\n outputMimeType?: string;\n /** Compression quality of the generated image (for ``image/jpeg``\n only). */\n outputCompressionQuality?: number;\n /** Whether to add a watermark to the generated images. */\n addWatermark?: boolean;\n /** User specified labels to track billing usage. */\n labels?: Record<string, string>;\n /** The size of the largest dimension of the generated image.\n Supported sizes are 1K and 2K (not supported for Imagen 3 models). */\n imageSize?: string;\n /** Whether to use the prompt rewriting logic. */\n enhancePrompt?: boolean;\n}\n\n/** The parameters for generating images. */\nexport declare interface GenerateImagesParameters {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model: string;\n /** Text prompt that typically describes the images to output.\n */\n prompt: string;\n /** Configuration for generating images.\n */\n config?: GenerateImagesConfig;\n}\n\n/** An image. */\nexport declare interface Image {\n /** The Cloud Storage URI of the image. ``Image`` can contain a value\n for this field or the ``image_bytes`` field but not both. */\n gcsUri?: string;\n /** The image bytes data. ``Image`` can contain a value for this field\n or the ``gcs_uri`` field but not both.\n * @remarks Encoded as base64 string. */\n imageBytes?: string;\n /** The MIME type of the image. */\n mimeType?: string;\n}\n\n/** Safety attributes of a GeneratedImage or the user-provided prompt. */\nexport declare interface SafetyAttributes {\n /** List of RAI categories. */\n categories?: string[];\n /** List of scores of each categories. */\n scores?: number[];\n /** Internal use only. */\n contentType?: string;\n}\n\n/** An output image. */\nexport declare interface GeneratedImage {\n /** The output image data. */\n image?: Image;\n /** Responsible AI filter reason if the image is filtered out of the\n response. */\n raiFilteredReason?: string;\n /** Safety attributes of the image. Lists of RAI categories and their\n scores of each content. */\n safetyAttributes?: SafetyAttributes;\n /** The rewritten prompt used for the image generation if the prompt\n enhancer is enabled. */\n enhancedPrompt?: string;\n}\n\n/** The output images response. */\nexport class GenerateImagesResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** List of generated images. */\n generatedImages?: GeneratedImage[];\n /** Safety attributes of the positive prompt. Only populated if\n ``include_safety_attributes`` is set to True. */\n positivePromptSafetyAttributes?: SafetyAttributes;\n}\n\n/** Configuration for a Mask reference image. */\nexport declare interface MaskReferenceConfig {\n /** Prompts the model to generate a mask instead of you needing to\n provide one (unless MASK_MODE_USER_PROVIDED is used). */\n maskMode?: MaskReferenceMode;\n /** A list of up to 5 class ids to use for semantic segmentation.\n Automatically creates an image mask based on specific objects. */\n segmentationClasses?: number[];\n /** Dilation percentage of the mask provided.\n Float between 0 and 1. */\n maskDilation?: number;\n}\n\n/** Configuration for a Control reference image. */\nexport declare interface ControlReferenceConfig {\n /** The type of control reference image to use. */\n controlType?: ControlReferenceType;\n /** Defaults to False. When set to True, the control image will be\n computed by the model based on the control type. When set to False,\n the control image must be provided by the user. */\n enableControlImageComputation?: boolean;\n}\n\n/** Configuration for a Style reference image. */\nexport declare interface StyleReferenceConfig {\n /** A text description of the style to use for the generated image. */\n styleDescription?: string;\n}\n\n/** Configuration for a Subject reference image. */\nexport declare interface SubjectReferenceConfig {\n /** The subject type of a subject reference image. */\n subjectType?: SubjectReferenceType;\n /** Subject description for the image. */\n subjectDescription?: string;\n}\n\n/** Configuration for editing an image. */\nexport declare interface EditImageConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** Cloud Storage URI used to store the generated images. */\n outputGcsUri?: string;\n /** Description of what to discourage in the generated images. */\n negativePrompt?: string;\n /** Number of images to generate. */\n numberOfImages?: number;\n /** Aspect ratio of the generated images. Supported values are\n \"1:1\", \"3:4\", \"4:3\", \"9:16\", and \"16:9\". */\n aspectRatio?: string;\n /** Controls how much the model adheres to the text prompt. Large\n values increase output and prompt alignment, but may compromise image\n quality. */\n guidanceScale?: number;\n /** Random seed for image generation. This is not available when\n ``add_watermark`` is set to true. */\n seed?: number;\n /** Filter level for safety filtering. */\n safetyFilterLevel?: SafetyFilterLevel;\n /** Allows generation of people by the model. */\n personGeneration?: PersonGeneration;\n /** Whether to report the safety scores of each generated image and\n the positive prompt in the response. */\n includeSafetyAttributes?: boolean;\n /** Whether to include the Responsible AI filter reason if the image\n is filtered out of the response. */\n includeRaiReason?: boolean;\n /** Language of the text in the prompt. */\n language?: ImagePromptLanguage;\n /** MIME type of the generated image. */\n outputMimeType?: string;\n /** Compression quality of the generated image (for ``image/jpeg``\n only). */\n outputCompressionQuality?: number;\n /** Whether to add a watermark to the generated images. */\n addWatermark?: boolean;\n /** User specified labels to track billing usage. */\n labels?: Record<string, string>;\n /** Describes the editing mode for the request. */\n editMode?: EditMode;\n /** The number of sampling steps. A higher value has better image\n quality, while a lower value has better latency. */\n baseSteps?: number;\n}\n\n/** Response for the request to edit an image. */\nexport class EditImageResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** Generated images. */\n generatedImages?: GeneratedImage[];\n}\n\nexport class UpscaleImageResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** Generated images. */\n generatedImages?: GeneratedImage[];\n}\n\n/** An image of the product. */\nexport declare interface ProductImage {\n /** An image of the product to be recontextualized. */\n productImage?: Image;\n}\n\n/** A set of source input(s) for image recontextualization. */\nexport declare interface RecontextImageSource {\n /** A text prompt for guiding the model during image\n recontextualization. Not supported for Virtual Try-On. */\n prompt?: string;\n /** Image of the person or subject who will be wearing the\n product(s). */\n personImage?: Image;\n /** A list of product images. */\n productImages?: ProductImage[];\n}\n\n/** Configuration for recontextualizing an image. */\nexport declare interface RecontextImageConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** Number of images to generate. */\n numberOfImages?: number;\n /** The number of sampling steps. A higher value has better image\n quality, while a lower value has better latency. */\n baseSteps?: number;\n /** Cloud Storage URI used to store the generated images. */\n outputGcsUri?: string;\n /** Random seed for image generation. */\n seed?: number;\n /** Filter level for safety filtering. */\n safetyFilterLevel?: SafetyFilterLevel;\n /** Whether allow to generate person images, and restrict to specific\n ages. */\n personGeneration?: PersonGeneration;\n /** Whether to add a SynthID watermark to the generated images. */\n addWatermark?: boolean;\n /** MIME type of the generated image. */\n outputMimeType?: string;\n /** Compression quality of the generated image (for ``image/jpeg``\n only). */\n outputCompressionQuality?: number;\n /** Whether to use the prompt rewriting logic. */\n enhancePrompt?: boolean;\n /** User specified labels to track billing usage. */\n labels?: Record<string, string>;\n}\n\n/** The parameters for recontextualizing an image. */\nexport declare interface RecontextImageParameters {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model: string;\n /** A set of source input(s) for image recontextualization. */\n source: RecontextImageSource;\n /** Configuration for image recontextualization. */\n config?: RecontextImageConfig;\n}\n\n/** The output images response. */\nexport class RecontextImageResponse {\n /** List of generated images. */\n generatedImages?: GeneratedImage[];\n}\n\n/** An image mask representing a brush scribble. */\nexport declare interface ScribbleImage {\n /** The brush scribble to guide segmentation. Valid for the interactive mode. */\n image?: Image;\n}\n\n/** A set of source input(s) for image segmentation. */\nexport declare interface SegmentImageSource {\n /** A text prompt for guiding the model during image segmentation.\n Required for prompt mode and semantic mode, disallowed for other modes. */\n prompt?: string;\n /** The image to be segmented. */\n image?: Image;\n /** The brush scribble to guide segmentation.\n Required for the interactive mode, disallowed for other modes. */\n scribbleImage?: ScribbleImage;\n}\n\n/** Configuration for segmenting an image. */\nexport declare interface SegmentImageConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** The segmentation mode to use. */\n mode?: SegmentMode;\n /** The maximum number of predictions to return up to, by top\n confidence score. */\n maxPredictions?: number;\n /** The confidence score threshold for the detections as a decimal\n value. Only predictions with a confidence score higher than this\n threshold will be returned. */\n confidenceThreshold?: number;\n /** A decimal value representing how much dilation to apply to the\n masks. 0 for no dilation. 1.0 means the masked area covers the whole\n image. */\n maskDilation?: number;\n /** The binary color threshold to apply to the masks. The threshold\n can be set to a decimal value between 0 and 255 non-inclusive.\n Set to -1 for no binary color thresholding. */\n binaryColorThreshold?: number;\n /** User specified labels to track billing usage. */\n labels?: Record<string, string>;\n}\n\n/** The parameters for segmenting an image. */\nexport declare interface SegmentImageParameters {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model: string;\n /** A set of source input(s) for image segmentation. */\n source: SegmentImageSource;\n /** Configuration for image segmentation. */\n config?: SegmentImageConfig;\n}\n\n/** An entity representing the segmented area. */\nexport declare interface EntityLabel {\n /** The label of the segmented entity. */\n label?: string;\n /** The confidence score of the detected label. */\n score?: number;\n}\n\n/** A generated image mask. */\nexport declare interface GeneratedImageMask {\n /** The generated image mask. */\n mask?: Image;\n /** The detected entities on the segmented area. */\n labels?: EntityLabel[];\n}\n\n/** The output images response. */\nexport class SegmentImageResponse {\n /** List of generated image masks.\n */\n generatedMasks?: GeneratedImageMask[];\n}\n\n/** Optional parameters for models.get method. */\nexport declare interface GetModelConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\nexport declare interface GetModelParameters {\n model: string;\n /** Optional parameters for the request. */\n config?: GetModelConfig;\n}\n\n/** An endpoint where you deploy models. */\nexport declare interface Endpoint {\n /** Resource name of the endpoint. */\n name?: string;\n /** ID of the model that's deployed to the endpoint. */\n deployedModelId?: string;\n}\n\n/** A tuned machine learning model. */\nexport declare interface TunedModelInfo {\n /** ID of the base model that you want to tune. */\n baseModel?: string;\n /** Date and time when the base model was created. */\n createTime?: string;\n /** Date and time when the base model was last updated. */\n updateTime?: string;\n}\n\n/** Describes the machine learning model version checkpoint. */\nexport declare interface Checkpoint {\n /** The ID of the checkpoint.\n */\n checkpointId?: string;\n /** The epoch of the checkpoint.\n */\n epoch?: string;\n /** The step of the checkpoint.\n */\n step?: string;\n}\n\n/** A trained machine learning model. */\nexport declare interface Model {\n /** Resource name of the model. */\n name?: string;\n /** Display name of the model. */\n displayName?: string;\n /** Description of the model. */\n description?: string;\n /** Version ID of the model. A new version is committed when a new\n model version is uploaded or trained under an existing model ID. The\n version ID is an auto-incrementing decimal number in string\n representation. */\n version?: string;\n /** List of deployed models created from this base model. Note that a\n model could have been deployed to endpoints in different locations. */\n endpoints?: Endpoint[];\n /** Labels with user-defined metadata to organize your models. */\n labels?: Record<string, string>;\n /** Information about the tuned model from the base model. */\n tunedModelInfo?: TunedModelInfo;\n /** The maximum number of input tokens that the model can handle. */\n inputTokenLimit?: number;\n /** The maximum number of output tokens that the model can generate. */\n outputTokenLimit?: number;\n /** List of actions that are supported by the model. */\n supportedActions?: string[];\n /** The default checkpoint id of a model version.\n */\n defaultCheckpointId?: string;\n /** The checkpoints of the model. */\n checkpoints?: Checkpoint[];\n /** Temperature value used for sampling set when the dataset was saved.\n This value is used to tune the degree of randomness. */\n temperature?: number;\n /** The maximum temperature value used for sampling set when the\n dataset was saved. This value is used to tune the degree of randomness. */\n maxTemperature?: number;\n /** Optional. Specifies the nucleus sampling threshold. The model\n considers only the smallest set of tokens whose cumulative probability is\n at least `top_p`. This helps generate more diverse and less repetitive\n responses. For example, a `top_p` of 0.9 means the model considers tokens\n until the cumulative probability of the tokens to select from reaches 0.9.\n It's recommended to adjust either temperature or `top_p`, but not both. */\n topP?: number;\n /** Optional. Specifies the top-k sampling threshold. The model\n considers only the top k most probable tokens for the next token. This can\n be useful for generating more coherent and less random text. For example,\n a `top_k` of 40 means the model will choose the next word from the 40 most\n likely words. */\n topK?: number;\n /** Whether the model supports thinking features. If true, thoughts are\n returned only if the model supports thought and thoughts are available. */\n thinking?: boolean;\n}\n\nexport declare interface ListModelsConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n pageSize?: number;\n pageToken?: string;\n filter?: string;\n /** Set true to list base models, false to list tuned models. */\n queryBase?: boolean;\n}\n\nexport declare interface ListModelsParameters {\n config?: ListModelsConfig;\n}\n\nexport class ListModelsResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n nextPageToken?: string;\n models?: Model[];\n}\n\n/** Configuration for updating a tuned model. */\nexport declare interface UpdateModelConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n displayName?: string;\n description?: string;\n defaultCheckpointId?: string;\n}\n\n/** Configuration for updating a tuned model. */\nexport declare interface UpdateModelParameters {\n model: string;\n config?: UpdateModelConfig;\n}\n\n/** Configuration for deleting a tuned model. */\nexport declare interface DeleteModelConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for deleting a tuned model. */\nexport declare interface DeleteModelParameters {\n model: string;\n /** Optional parameters for the request. */\n config?: DeleteModelConfig;\n}\n\nexport class DeleteModelResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n}\n\n/** Generation config. */\nexport declare interface GenerationConfig {\n /** Optional. Config for model selection. */\n modelSelectionConfig?: ModelSelectionConfig;\n /** Output schema of the generated response. This is an alternative to\n `response_schema` that accepts [JSON Schema](https://json-schema.org/).\n */\n responseJsonSchema?: unknown;\n /** Optional. If enabled, audio timestamp will be included in the request to the model. This field is not supported in Gemini API. */\n audioTimestamp?: boolean;\n /** Optional. Number of candidates to generate. */\n candidateCount?: number;\n /** Optional. If enabled, the model will detect emotions and adapt its responses accordingly. This field is not supported in Gemini API. */\n enableAffectiveDialog?: boolean;\n /** Optional. Frequency penalties. */\n frequencyPenalty?: number;\n /** Optional. Logit probabilities. */\n logprobs?: number;\n /** Optional. The maximum number of output tokens to generate per message. */\n maxOutputTokens?: number;\n /** Optional. If specified, the media resolution specified will be used. */\n mediaResolution?: MediaResolution;\n /** Optional. Positive penalties. */\n presencePenalty?: number;\n /** Optional. If true, export the logprobs results in response. */\n responseLogprobs?: boolean;\n /** Optional. Output response mimetype of the generated candidate text. Supported mimetype: - `text/plain`: (default) Text output. - `application/json`: JSON response in the candidates. The model needs to be prompted to output the appropriate response type, otherwise the behavior is undefined. This is a preview feature. */\n responseMimeType?: string;\n /** Optional. The modalities of the response. */\n responseModalities?: Modality[];\n /** Optional. The `Schema` object allows the definition of input and output data types. These types can be objects, but also primitives and arrays. Represents a select subset of an [OpenAPI 3.0 schema object](https://spec.openapis.org/oas/v3.0.3#schema). If set, a compatible response_mime_type must also be set. Compatible mimetypes: `application/json`: Schema for JSON response. */\n responseSchema?: Schema;\n /** Optional. Routing configuration. This field is not supported in Gemini API. */\n routingConfig?: GenerationConfigRoutingConfig;\n /** Optional. Seed. */\n seed?: number;\n /** Optional. The speech generation config. */\n speechConfig?: SpeechConfig;\n /** Optional. Stop sequences. */\n stopSequences?: string[];\n /** Optional. Controls the randomness of predictions. */\n temperature?: number;\n /** Optional. Config for thinking features. An error will be returned if this field is set for models that don't support thinking. */\n thinkingConfig?: ThinkingConfig;\n /** Optional. If specified, top-k sampling will be used. */\n topK?: number;\n /** Optional. If specified, nucleus sampling will be used. */\n topP?: number;\n /** Optional. Enables enhanced civic answers. It may not be available for all models. This field is not supported in Vertex AI. */\n enableEnhancedCivicAnswers?: boolean;\n}\n\n/** Config for the count_tokens method. */\nexport declare interface CountTokensConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** Instructions for the model to steer it toward better performance.\n */\n systemInstruction?: ContentUnion;\n /** Code that enables the system to interact with external systems to\n perform an action outside of the knowledge and scope of the model.\n */\n tools?: Tool[];\n /** Configuration that the model uses to generate the response. Not\n supported by the Gemini Developer API.\n */\n generationConfig?: GenerationConfig;\n}\n\n/** Parameters for counting tokens. */\nexport declare interface CountTokensParameters {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model: string;\n /** Input content. */\n contents: ContentListUnion;\n /** Configuration for counting tokens. */\n config?: CountTokensConfig;\n}\n\n/** Response for counting tokens. */\nexport class CountTokensResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** Total number of tokens. */\n totalTokens?: number;\n /** Number of tokens in the cached part of the prompt (the cached content). */\n cachedContentTokenCount?: number;\n}\n\n/** Optional parameters for computing tokens. */\nexport declare interface ComputeTokensConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for computing tokens. */\nexport declare interface ComputeTokensParameters {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model: string;\n /** Input content. */\n contents: ContentListUnion;\n /** Optional parameters for the request.\n */\n config?: ComputeTokensConfig;\n}\n\n/** Tokens info with a list of tokens and the corresponding list of token ids. */\nexport declare interface TokensInfo {\n /** Optional fields for the role from the corresponding Content. */\n role?: string;\n /** A list of token ids from the input. */\n tokenIds?: string[];\n /** A list of tokens from the input.\n * @remarks Encoded as base64 string. */\n tokens?: string[];\n}\n\n/** Response for computing tokens. */\nexport class ComputeTokensResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** Lists of tokens info from the input. A ComputeTokensRequest could have multiple instances with a prompt in each instance. We also need to return lists of tokens info for the request with multiple instances. */\n tokensInfo?: TokensInfo[];\n}\n\n/** A generated video. */\nexport declare interface Video {\n /** Path to another storage. */\n uri?: string;\n /** Video bytes.\n * @remarks Encoded as base64 string. */\n videoBytes?: string;\n /** Video encoding, for example ``video/mp4``. */\n mimeType?: string;\n}\n\n/** A set of source input(s) for video generation. */\nexport declare interface GenerateVideosSource {\n /** The text prompt for generating the videos.\n Optional if image or video is provided. */\n prompt?: string;\n /** The input image for generating the videos.\n Optional if prompt is provided. Not allowed if video is provided. */\n image?: Image;\n /** The input video for video extension use cases.\n Optional if prompt is provided. Not allowed if image is provided. */\n video?: Video;\n}\n\n/** A reference image for video generation. */\nexport declare interface VideoGenerationReferenceImage {\n /** The reference image. */\n image?: Image;\n /** The type of the reference image, which defines how the reference\n image will be used to generate the video. */\n referenceType?: VideoGenerationReferenceType;\n}\n\n/** A mask for video generation. */\nexport declare interface VideoGenerationMask {\n /** The image mask to use for generating videos. */\n image?: Image;\n /** Describes how the mask will be used. Inpainting masks must\n match the aspect ratio of the input video. Outpainting masks can be\n either 9:16 or 16:9. */\n maskMode?: VideoGenerationMaskMode;\n}\n\n/** Configuration for generating videos. */\nexport declare interface GenerateVideosConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** Number of output videos. */\n numberOfVideos?: number;\n /** The gcs bucket where to save the generated videos. */\n outputGcsUri?: string;\n /** Frames per second for video generation. */\n fps?: number;\n /** Duration of the clip for video generation in seconds. */\n durationSeconds?: number;\n /** The RNG seed. If RNG seed is exactly same for each request with\n unchanged inputs, the prediction results will be consistent. Otherwise,\n a random RNG seed will be used each time to produce a different\n result. */\n seed?: number;\n /** The aspect ratio for the generated video. 16:9 (landscape) and\n 9:16 (portrait) are supported. */\n aspectRatio?: string;\n /** The resolution for the generated video. 720p and 1080p are\n supported. */\n resolution?: string;\n /** Whether allow to generate person videos, and restrict to specific\n ages. Supported values are: dont_allow, allow_adult. */\n personGeneration?: string;\n /** The pubsub topic where to publish the video generation\n progress. */\n pubsubTopic?: string;\n /** Explicitly state what should not be included in the generated\n videos. */\n negativePrompt?: string;\n /** Whether to use the prompt rewriting logic. */\n enhancePrompt?: boolean;\n /** Whether to generate audio along with the video. */\n generateAudio?: boolean;\n /** Image to use as the last frame of generated videos.\n Only supported for image to video use cases. */\n lastFrame?: Image;\n /** The images to use as the references to generate the videos.\n If this field is provided, the text prompt field must also be provided.\n The image, video, or last_frame field are not supported. Each image must\n be associated with a type. Veo 2 supports up to 3 asset images *or* 1\n style image. */\n referenceImages?: VideoGenerationReferenceImage[];\n /** The mask to use for generating videos. */\n mask?: VideoGenerationMask;\n /** Compression quality of the generated videos. */\n compressionQuality?: VideoCompressionQuality;\n}\n\n/** Class that represents the parameters for generating videos. */\nexport declare interface GenerateVideosParameters {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model: string;\n /** The text prompt for generating the videos.\n Optional if image or video is provided. */\n prompt?: string;\n /** The input image for generating the videos.\n Optional if prompt is provided. Not allowed if video is provided. */\n image?: Image;\n /** The input video for video extension use cases.\n Optional if prompt is provided. Not allowed if image is provided. */\n video?: Video;\n /** A set of source input(s) for video generation. */\n source?: GenerateVideosSource;\n /** Configuration for generating videos. */\n config?: GenerateVideosConfig;\n}\n\n/** A generated video. */\nexport declare interface GeneratedVideo {\n /** The output video */\n video?: Video;\n}\n\n/** Response with generated videos. */\nexport class GenerateVideosResponse {\n /** List of the generated videos */\n generatedVideos?: GeneratedVideo[];\n /** Returns if any videos were filtered due to RAI policies. */\n raiMediaFilteredCount?: number;\n /** Returns rai failure reasons if any. */\n raiMediaFilteredReasons?: string[];\n}\n\n/** A long-running operation. */\nexport declare interface Operation<T> {\n /** The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`. */\n name?: string;\n /** Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata. Any method that returns a long-running operation should document the metadata type, if any. */\n metadata?: Record<string, unknown>;\n /** If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available. */\n done?: boolean;\n /** The error result of the operation in case of failure or cancellation. */\n error?: Record<string, unknown>;\n /** The response if the operation is successful. */\n response?: T;\n /**\n * Instantiates an Operation of the same type as the one being called with the fields set from the API response.\n * @internal\n */\n _fromAPIResponse({\n apiResponse,\n _isVertexAI,\n }: OperationFromAPIResponseParameters): Operation<T>;\n}\n\n/** A video generation operation. */\nexport class GenerateVideosOperation\n implements Operation<GenerateVideosResponse>\n{\n /** The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`. */\n name?: string;\n /** Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata. Any method that returns a long-running operation should document the metadata type, if any. */\n metadata?: Record<string, unknown>;\n /** If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available. */\n done?: boolean;\n /** The error result of the operation in case of failure or cancellation. */\n error?: Record<string, unknown>;\n /** The generated videos. */\n response?: GenerateVideosResponse;\n\n /**\n * Instantiates an Operation of the same type as the one being called with the fields set from the API response.\n * @internal\n */\n _fromAPIResponse({\n apiResponse,\n _isVertexAI,\n }: OperationFromAPIResponseParameters): Operation<GenerateVideosResponse> {\n const operation = new GenerateVideosOperation();\n let response;\n const op = apiResponse as unknown as GenerateVideosOperation;\n\n if (_isVertexAI) {\n response = generateVideosOperationFromVertex(op);\n } else {\n response = generateVideosOperationFromMldev(op);\n }\n Object.assign(operation, response);\n return operation;\n }\n /** The full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n}\n\n/** Optional parameters for tunings.get method. */\nexport declare interface GetTuningJobConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for the get method. */\nexport declare interface GetTuningJobParameters {\n name: string;\n /** Optional parameters for the request. */\n config?: GetTuningJobConfig;\n}\n\n/** TunedModelCheckpoint for the Tuned Model of a Tuning Job. */\nexport declare interface TunedModelCheckpoint {\n /** The ID of the checkpoint.\n */\n checkpointId?: string;\n /** The epoch of the checkpoint.\n */\n epoch?: string;\n /** The step of the checkpoint.\n */\n step?: string;\n /** The Endpoint resource name that the checkpoint is deployed to.\n Format: `projects/{project}/locations/{location}/endpoints/{endpoint}`.\n */\n endpoint?: string;\n}\n\n/** TunedModel for the Tuned Model of a Tuning Job. */\nexport declare interface TunedModel {\n /** Output only. The resource name of the TunedModel.\n Format: `projects/{project}/locations/{location}/models/{model}@{version_id}`\n When tuning from a base model, the version_id will be 1.\n For continuous tuning, the version id will be incremented by 1 from the\n last version id in the parent model. E.g., `projects/{project}/locations/{location}/models/{model}@{last_version_id + 1}`\n */\n model?: string;\n /** Output only. A resource name of an Endpoint.\n Format: `projects/{project}/locations/{location}/endpoints/{endpoint}`.\n */\n endpoint?: string;\n /** The checkpoints associated with this TunedModel.\n This field is only populated for tuning jobs that enable intermediate\n checkpoints. */\n checkpoints?: TunedModelCheckpoint[];\n}\n\n/** Hyperparameters for SFT. This data type is not supported in Gemini API. */\nexport declare interface SupervisedHyperParameters {\n /** Optional. Adapter size for tuning. */\n adapterSize?: AdapterSize;\n /** Optional. Batch size for tuning. This feature is only available for open source models. */\n batchSize?: string;\n /** Optional. Number of complete passes the model makes over the entire training dataset during training. */\n epochCount?: string;\n /** Optional. Learning rate for tuning. Mutually exclusive with `learning_rate_multiplier`. This feature is only available for open source models. */\n learningRate?: number;\n /** Optional. Multiplier for adjusting the default learning rate. Mutually exclusive with `learning_rate`. This feature is only available for 1P models. */\n learningRateMultiplier?: number;\n}\n\n/** Supervised tuning spec for tuning. */\nexport declare interface SupervisedTuningSpec {\n /** Optional. If set to true, disable intermediate checkpoints for SFT and only the last checkpoint will be exported. Otherwise, enable intermediate checkpoints for SFT. Default is false. */\n exportLastCheckpointOnly?: boolean;\n /** Optional. Hyperparameters for SFT. */\n hyperParameters?: SupervisedHyperParameters;\n /** Required. Training dataset used for tuning. The dataset can be specified as either a Cloud Storage path to a JSONL file or as the resource name of a Vertex Multimodal Dataset. */\n trainingDatasetUri?: string;\n /** Tuning mode. */\n tuningMode?: TuningMode;\n /** Optional. Validation dataset used for tuning. The dataset can be specified as either a Cloud Storage path to a JSONL file or as the resource name of a Vertex Multimodal Dataset. */\n validationDatasetUri?: string;\n}\n\n/** Hyperparameters for Preference Optimization. This data type is not supported in Gemini API. */\nexport declare interface PreferenceOptimizationHyperParameters {\n /** Optional. Adapter size for preference optimization. */\n adapterSize?: AdapterSize;\n /** Optional. Weight for KL Divergence regularization. */\n beta?: number;\n /** Optional. Number of complete passes the model makes over the entire training dataset during training. */\n epochCount?: string;\n /** Optional. Multiplier for adjusting the default learning rate. */\n learningRateMultiplier?: number;\n}\n\n/** Preference optimization tuning spec for tuning. */\nexport declare interface PreferenceOptimizationSpec {\n /** Optional. If set to true, disable intermediate checkpoints for Preference Optimization and only the last checkpoint will be exported. Otherwise, enable intermediate checkpoints for Preference Optimization. Default is false. */\n exportLastCheckpointOnly?: boolean;\n /** Optional. Hyperparameters for Preference Optimization. */\n hyperParameters?: PreferenceOptimizationHyperParameters;\n /** Required. Cloud Storage path to file containing training dataset for preference optimization tuning. The dataset must be formatted as a JSONL file. */\n trainingDatasetUri?: string;\n /** Optional. Cloud Storage path to file containing validation dataset for preference optimization tuning. The dataset must be formatted as a JSONL file. */\n validationDatasetUri?: string;\n}\n\n/** Hyperparameters for Distillation. This data type is not supported in Gemini API. */\nexport declare interface DistillationHyperParameters {\n /** Optional. Adapter size for distillation. */\n adapterSize?: AdapterSize;\n /** Optional. Number of complete passes the model makes over the entire training dataset during training. */\n epochCount?: string;\n /** Optional. Multiplier for adjusting the default learning rate. */\n learningRateMultiplier?: number;\n}\n\n/** Distillation tuning spec for tuning. */\nexport declare interface DistillationSpec {\n /** The GCS URI of the prompt dataset to use during distillation. */\n promptDatasetUri?: string;\n /** The base teacher model that is being distilled. See [Supported models](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/tuning#supported_models). */\n baseTeacherModel?: string;\n /** Optional. Hyperparameters for Distillation. */\n hyperParameters?: DistillationHyperParameters;\n /** Deprecated. A path in a Cloud Storage bucket, which will be treated as the root output directory of the distillation pipeline. It is used by the system to generate the paths of output artifacts. */\n pipelineRootDirectory?: string;\n /** The student model that is being tuned, e.g., \"google/gemma-2b-1.1-it\". Deprecated. Use base_model instead. */\n studentModel?: string;\n /** Deprecated. Cloud Storage path to file containing training dataset for tuning. The dataset must be formatted as a JSONL file. */\n trainingDatasetUri?: string;\n /** The resource name of the Tuned teacher model. Format: `projects/{project}/locations/{location}/models/{model}`. */\n tunedTeacherModelSource?: string;\n /** Optional. Cloud Storage path to file containing validation dataset for tuning. The dataset must be formatted as a JSONL file. */\n validationDatasetUri?: string;\n}\n\n/** The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors). This data type is not supported in Gemini API. */\nexport declare interface GoogleRpcStatus {\n /** The status code, which should be an enum value of google.rpc.Code. */\n code?: number;\n /** A list of messages that carry the error details. There is a common set of message types for APIs to use. */\n details?: Record<string, unknown>[];\n /** A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the google.rpc.Status.details field, or localized by the client. */\n message?: string;\n}\n\n/** A pre-tuned model for continuous tuning. This data type is not supported in Gemini API. */\nexport declare interface PreTunedModel {\n /** Output only. The name of the base model this PreTunedModel was tuned from. */\n baseModel?: string;\n /** Optional. The source checkpoint id. If not specified, the default checkpoint will be used. */\n checkpointId?: string;\n /** The resource name of the Model. E.g., a model resource name with a specified version id or alias: `projects/{project}/locations/{location}/models/{model}@{version_id}` `projects/{project}/locations/{location}/models/{model}@{alias}` Or, omit the version id to use the default version: `projects/{project}/locations/{location}/models/{model}` */\n tunedModelName?: string;\n}\n\n/** Dataset bucket used to create a histogram for the distribution given a population of values. This data type is not supported in Gemini API. */\nexport declare interface DatasetDistributionDistributionBucket {\n /** Output only. Number of values in the bucket. */\n count?: string;\n /** Output only. Left bound of the bucket. */\n left?: number;\n /** Output only. Right bound of the bucket. */\n right?: number;\n}\n\n/** Distribution computed over a tuning dataset. This data type is not supported in Gemini API. */\nexport declare interface DatasetDistribution {\n /** Output only. Defines the histogram bucket. */\n buckets?: DatasetDistributionDistributionBucket[];\n /** Output only. The maximum of the population values. */\n max?: number;\n /** Output only. The arithmetic mean of the values in the population. */\n mean?: number;\n /** Output only. The median of the values in the population. */\n median?: number;\n /** Output only. The minimum of the population values. */\n min?: number;\n /** Output only. The 5th percentile of the values in the population. */\n p5?: number;\n /** Output only. The 95th percentile of the values in the population. */\n p95?: number;\n /** Output only. Sum of a given population of values. */\n sum?: number;\n}\n\n/** Statistics computed over a tuning dataset. This data type is not supported in Gemini API. */\nexport declare interface DatasetStats {\n /** Output only. Number of billable characters in the tuning dataset. */\n totalBillableCharacterCount?: string;\n /** Output only. Number of tuning characters in the tuning dataset. */\n totalTuningCharacterCount?: string;\n /** Output only. Number of examples in the tuning dataset. */\n tuningDatasetExampleCount?: string;\n /** Output only. Number of tuning steps for this Tuning Job. */\n tuningStepCount?: string;\n /** Output only. Sample user messages in the training dataset uri. */\n userDatasetExamples?: Content[];\n /** Output only. Dataset distributions for the user input tokens. */\n userInputTokenDistribution?: DatasetDistribution;\n /** Output only. Dataset distributions for the messages per example. */\n userMessagePerExampleDistribution?: DatasetDistribution;\n /** Output only. Dataset distributions for the user output tokens. */\n userOutputTokenDistribution?: DatasetDistribution;\n}\n\n/** Statistics computed for datasets used for distillation. This data type is not supported in Gemini API. */\nexport declare interface DistillationDataStats {\n /** Output only. Statistics computed for the training dataset. */\n trainingDatasetStats?: DatasetStats;\n}\n\n/** Completion and its preference score. This data type is not supported in Gemini API. */\nexport declare interface GeminiPreferenceExampleCompletion {\n /** Single turn completion for the given prompt. */\n completion?: Content;\n /** The score for the given completion. */\n score?: number;\n}\n\n/** Input example for preference optimization. This data type is not supported in Gemini API. */\nexport declare interface GeminiPreferenceExample {\n /** List of completions for a given prompt. */\n completions?: GeminiPreferenceExampleCompletion[];\n /** Multi-turn contents that represents the Prompt. */\n contents?: Content[];\n}\n\n/** Statistics computed for datasets used for preference optimization. This data type is not supported in Gemini API. */\nexport declare interface PreferenceOptimizationDataStats {\n /** Output only. Dataset distributions for scores variance per example. */\n scoreVariancePerExampleDistribution?: DatasetDistribution;\n /** Output only. Dataset distributions for scores. */\n scoresDistribution?: DatasetDistribution;\n /** Output only. Number of billable tokens in the tuning dataset. */\n totalBillableTokenCount?: string;\n /** Output only. Number of examples in the tuning dataset. */\n tuningDatasetExampleCount?: string;\n /** Output only. Number of tuning steps for this Tuning Job. */\n tuningStepCount?: string;\n /** Output only. Sample user examples in the training dataset. */\n userDatasetExamples?: GeminiPreferenceExample[];\n /** Output only. Dataset distributions for the user input tokens. */\n userInputTokenDistribution?: DatasetDistribution;\n /** Output only. Dataset distributions for the user output tokens. */\n userOutputTokenDistribution?: DatasetDistribution;\n}\n\n/** Dataset bucket used to create a histogram for the distribution given a population of values. This data type is not supported in Gemini API. */\nexport declare interface SupervisedTuningDatasetDistributionDatasetBucket {\n /** Output only. Number of values in the bucket. */\n count?: number;\n /** Output only. Left bound of the bucket. */\n left?: number;\n /** Output only. Right bound of the bucket. */\n right?: number;\n}\n\n/** Dataset distribution for Supervised Tuning. This data type is not supported in Gemini API. */\nexport declare interface SupervisedTuningDatasetDistribution {\n /** Output only. Sum of a given population of values that are billable. */\n billableSum?: string;\n /** Output only. Defines the histogram bucket. */\n buckets?: SupervisedTuningDatasetDistributionDatasetBucket[];\n /** Output only. The maximum of the population values. */\n max?: number;\n /** Output only. The arithmetic mean of the values in the population. */\n mean?: number;\n /** Output only. The median of the values in the population. */\n median?: number;\n /** Output only. The minimum of the population values. */\n min?: number;\n /** Output only. The 5th percentile of the values in the population. */\n p5?: number;\n /** Output only. The 95th percentile of the values in the population. */\n p95?: number;\n /** Output only. Sum of a given population of values. */\n sum?: string;\n}\n\n/** Tuning data statistics for Supervised Tuning. This data type is not supported in Gemini API. */\nexport declare interface SupervisedTuningDataStats {\n /** Output only. For each index in `truncated_example_indices`, the user-facing reason why the example was dropped. */\n droppedExampleReasons?: string[];\n /** Output only. Number of billable characters in the tuning dataset. */\n totalBillableCharacterCount?: string;\n /** Output only. Number of billable tokens in the tuning dataset. */\n totalBillableTokenCount?: string;\n /** Output only. The number of examples in the dataset that have been dropped. An example can be dropped for reasons including: too many tokens, contains an invalid image, contains too many images, etc. */\n totalTruncatedExampleCount?: string;\n /** Output only. Number of tuning characters in the tuning dataset. */\n totalTuningCharacterCount?: string;\n /** Output only. A partial sample of the indices (starting from 1) of the dropped examples. */\n truncatedExampleIndices?: string[];\n /** Output only. Number of examples in the tuning dataset. */\n tuningDatasetExampleCount?: string;\n /** Output only. Number of tuning steps for this Tuning Job. */\n tuningStepCount?: string;\n /** Output only. Sample user messages in the training dataset uri. */\n userDatasetExamples?: Content[];\n /** Output only. Dataset distributions for the user input tokens. */\n userInputTokenDistribution?: SupervisedTuningDatasetDistribution;\n /** Output only. Dataset distributions for the messages per example. */\n userMessagePerExampleDistribution?: SupervisedTuningDatasetDistribution;\n /** Output only. Dataset distributions for the user output tokens. */\n userOutputTokenDistribution?: SupervisedTuningDatasetDistribution;\n}\n\n/** The tuning data statistic values for TuningJob. This data type is not supported in Gemini API. */\nexport declare interface TuningDataStats {\n /** Output only. Statistics for distillation. */\n distillationDataStats?: DistillationDataStats;\n /** Output only. Statistics for preference optimization. */\n preferenceOptimizationDataStats?: PreferenceOptimizationDataStats;\n /** The SFT Tuning data stats. */\n supervisedTuningDataStats?: SupervisedTuningDataStats;\n}\n\n/** Represents a customer-managed encryption key spec that can be applied to a top-level resource. This data type is not supported in Gemini API. */\nexport declare interface EncryptionSpec {\n /** Required. The Cloud KMS resource identifier of the customer managed encryption key used to protect a resource. Has the form: `projects/my-project/locations/my-region/keyRings/my-kr/cryptoKeys/my-key`. The key needs to be in the same region as where the compute resource is created. */\n kmsKeyName?: string;\n}\n\n/** Tuning spec for Partner models. This data type is not supported in Gemini API. */\nexport declare interface PartnerModelTuningSpec {\n /** Hyperparameters for tuning. The accepted hyper_parameters and their valid range of values will differ depending on the base model. */\n hyperParameters?: Record<string, unknown>;\n /** Required. Cloud Storage path to file containing training dataset for tuning. The dataset must be formatted as a JSONL file. */\n trainingDatasetUri?: string;\n /** Optional. Cloud Storage path to file containing validation dataset for tuning. The dataset must be formatted as a JSONL file. */\n validationDatasetUri?: string;\n}\n\n/** Hyperparameters for Veo. This data type is not supported in Gemini API. */\nexport declare interface VeoHyperParameters {\n /** Optional. Number of complete passes the model makes over the entire training dataset during training. */\n epochCount?: string;\n /** Optional. Multiplier for adjusting the default learning rate. */\n learningRateMultiplier?: number;\n /** Optional. The tuning task. Either I2V or T2V. */\n tuningTask?: TuningTask;\n}\n\n/** Tuning Spec for Veo Model Tuning. This data type is not supported in Gemini API. */\nexport declare interface VeoTuningSpec {\n /** Optional. Hyperparameters for Veo. */\n hyperParameters?: VeoHyperParameters;\n /** Required. Training dataset used for tuning. The dataset can be specified as either a Cloud Storage path to a JSONL file or as the resource name of a Vertex Multimodal Dataset. */\n trainingDatasetUri?: string;\n /** Optional. Validation dataset used for tuning. The dataset can be specified as either a Cloud Storage path to a JSONL file or as the resource name of a Vertex Multimodal Dataset. */\n validationDatasetUri?: string;\n}\n\n/** A tuning job. */\nexport declare interface TuningJob {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** Output only. Identifier. Resource name of a TuningJob. Format: `projects/{project}/locations/{location}/tuningJobs/{tuning_job}` */\n name?: string;\n /** Output only. The detailed state of the job. */\n state?: JobState;\n /** Output only. Time when the TuningJob was created. */\n createTime?: string;\n /** Output only. Time when the TuningJob for the first time entered the `JOB_STATE_RUNNING` state. */\n startTime?: string;\n /** Output only. Time when the TuningJob entered any of the following JobStates: `JOB_STATE_SUCCEEDED`, `JOB_STATE_FAILED`, `JOB_STATE_CANCELLED`, `JOB_STATE_EXPIRED`. */\n endTime?: string;\n /** Output only. Time when the TuningJob was most recently updated. */\n updateTime?: string;\n /** Output only. Only populated when job's state is `JOB_STATE_FAILED` or `JOB_STATE_CANCELLED`. */\n error?: GoogleRpcStatus;\n /** Optional. The description of the TuningJob. */\n description?: string;\n /** The base model that is being tuned. See [Supported models](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/tuning#supported_models). */\n baseModel?: string;\n /** Output only. The tuned model resources associated with this TuningJob. */\n tunedModel?: TunedModel;\n /** The pre-tuned model for continuous tuning. */\n preTunedModel?: PreTunedModel;\n /** Tuning Spec for Supervised Fine Tuning. */\n supervisedTuningSpec?: SupervisedTuningSpec;\n /** Tuning Spec for Preference Optimization. */\n preferenceOptimizationSpec?: PreferenceOptimizationSpec;\n /** Tuning Spec for Distillation. */\n distillationSpec?: DistillationSpec;\n /** Output only. The tuning data statistics associated with this TuningJob. */\n tuningDataStats?: TuningDataStats;\n /** Customer-managed encryption key options for a TuningJob. If this is set, then all resources created by the TuningJob will be encrypted with the provided encryption key. */\n encryptionSpec?: EncryptionSpec;\n /** Tuning Spec for open sourced and third party Partner models. */\n partnerModelTuningSpec?: PartnerModelTuningSpec;\n /** Optional. The user-provided path to custom model weights. Set this field to tune a custom model. The path must be a Cloud Storage directory that contains the model weights in .safetensors format along with associated model metadata files. If this field is set, the base_model field must still be set to indicate which base model the custom model is derived from. This feature is only available for open source models. */\n customBaseModel?: string;\n /** Output only. The Experiment associated with this TuningJob. */\n experiment?: string;\n /** Optional. The labels with user-defined metadata to organize TuningJob and generated resources such as Model and Endpoint. Label keys and values can be no longer than 64 characters (Unicode codepoints), can only contain lowercase letters, numeric characters, underscores and dashes. International characters are allowed. See https://goo.gl/xmQnxf for more information and examples of labels. */\n labels?: Record<string, string>;\n /** Optional. Cloud Storage path to the directory where tuning job outputs are written to. This field is only available and required for open source models. */\n outputUri?: string;\n /** Output only. The resource name of the PipelineJob associated with the TuningJob. Format: `projects/{project}/locations/{location}/pipelineJobs/{pipeline_job}`. */\n pipelineJob?: string;\n /** The service account that the tuningJob workload runs as. If not specified, the Vertex AI Secure Fine-Tuned Service Agent in the project will be used. See https://cloud.google.com/iam/docs/service-agents#vertex-ai-secure-fine-tuning-service-agent Users starting the pipeline must have the `iam.serviceAccounts.actAs` permission on this service account. */\n serviceAccount?: string;\n /** Optional. The display name of the TunedModel. The name can be up to 128 characters long and can consist of any UTF-8 characters. For continuous tuning, tuned_model_display_name will by default use the same display name as the pre-tuned model. If a new display name is provided, the tuning job will create a new model instead of a new version. */\n tunedModelDisplayName?: string;\n /** Tuning Spec for Veo Tuning. */\n veoTuningSpec?: VeoTuningSpec;\n}\n\n/** Configuration for the list tuning jobs method. */\nexport declare interface ListTuningJobsConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n pageSize?: number;\n pageToken?: string;\n filter?: string;\n}\n\n/** Parameters for the list tuning jobs method. */\nexport declare interface ListTuningJobsParameters {\n config?: ListTuningJobsConfig;\n}\n\n/** Response for the list tuning jobs method. */\nexport class ListTuningJobsResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** A token to retrieve the next page of results. Pass to ListTuningJobsRequest.page_token to obtain that page. */\n nextPageToken?: string;\n /** List of TuningJobs in the requested page. */\n tuningJobs?: TuningJob[];\n}\n\n/** Optional parameters for tunings.cancel method. */\nexport declare interface CancelTuningJobConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for the cancel method. */\nexport declare interface CancelTuningJobParameters {\n /** The resource name of the tuning job. */\n name: string;\n /** Optional parameters for the request. */\n config?: CancelTuningJobConfig;\n}\n\n/** Empty response for tunings.cancel method. */\nexport class CancelTuningJobResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n}\n\n/** A single example for tuning. This data type is not supported in Vertex AI. */\nexport declare interface TuningExample {\n /** Required. The expected model output. */\n output?: string;\n /** Optional. Text model input. */\n textInput?: string;\n}\n\n/** Supervised fine-tuning training dataset. */\nexport declare interface TuningDataset {\n /** GCS URI of the file containing training dataset in JSONL format. */\n gcsUri?: string;\n /** The resource name of the Vertex Multimodal Dataset that is used as training dataset. Example: 'projects/my-project-id-or-number/locations/my-location/datasets/my-dataset-id'. */\n vertexDatasetResource?: string;\n /** Inline examples with simple input/output text. */\n examples?: TuningExample[];\n}\n\nexport declare interface TuningValidationDataset {\n /** GCS URI of the file containing validation dataset in JSONL format. */\n gcsUri?: string;\n /** The resource name of the Vertex Multimodal Dataset that is used as validation dataset. Example: 'projects/my-project-id-or-number/locations/my-location/datasets/my-dataset-id'. */\n vertexDatasetResource?: string;\n}\n\n/** Fine-tuning job creation request - optional fields. */\nexport declare interface CreateTuningJobConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** The method to use for tuning (SUPERVISED_FINE_TUNING or PREFERENCE_TUNING or DISTILLATION). If not set, the default method (SFT) will be used. */\n method?: TuningMethod;\n /** Validation dataset for tuning. The dataset must be formatted as a JSONL file. */\n validationDataset?: TuningValidationDataset;\n /** The display name of the tuned Model. The name can be up to 128 characters long and can consist of any UTF-8 characters. */\n tunedModelDisplayName?: string;\n /** The description of the TuningJob */\n description?: string;\n /** Number of complete passes the model makes over the entire training dataset during training. */\n epochCount?: number;\n /** Multiplier for adjusting the default learning rate. 1P models only. Mutually exclusive with learning_rate. */\n learningRateMultiplier?: number;\n /** If set to true, disable intermediate checkpoints and only the last checkpoint will be exported. Otherwise, enable intermediate checkpoints. */\n exportLastCheckpointOnly?: boolean;\n /** The optional checkpoint id of the pre-tuned model to use for tuning, if applicable. */\n preTunedModelCheckpointId?: string;\n /** Adapter size for tuning. */\n adapterSize?: AdapterSize;\n /** Tuning mode for SFT tuning. */\n tuningMode?: TuningMode;\n /** Custom base model for tuning. This is only supported for OSS models in Vertex. */\n customBaseModel?: string;\n /** The batch size hyperparameter for tuning. This is only supported for OSS models in Vertex. */\n batchSize?: number;\n /** The learning rate for tuning. OSS models only. Mutually exclusive with learning_rate_multiplier. */\n learningRate?: number;\n /** Optional. The labels with user-defined metadata to organize TuningJob and generated resources such as Model and Endpoint. Label keys and values can be no longer than 64 characters (Unicode codepoints), can only contain lowercase letters, numeric characters, underscores and dashes. International characters are allowed. See https://goo.gl/xmQnxf for more information and examples of labels. */\n labels?: Record<string, string>;\n /** Weight for KL Divergence regularization, Preference Optimization tuning only. */\n beta?: number;\n /** The base teacher model that is being distilled. Distillation only. */\n baseTeacherModel?: string;\n /** The resource name of the Tuned teacher model. Distillation only. */\n tunedTeacherModelSource?: string;\n /** Multiplier for adjusting the weight of the SFT loss. Distillation only. */\n sftLossWeightMultiplier?: number;\n /** The Google Cloud Storage location where the tuning job outputs are written. */\n outputUri?: string;\n /** The encryption spec of the tuning job. Customer-managed encryption key options for a TuningJob. If this is set, then all resources created by the TuningJob will be encrypted with provided encryption key. */\n encryptionSpec?: EncryptionSpec;\n}\n\n/** Fine-tuning job creation parameters - optional fields. */\nexport declare interface CreateTuningJobParametersPrivate {\n /** The base model that is being tuned, e.g., \"gemini-2.5-flash\". */\n baseModel?: string;\n /** The PreTunedModel that is being tuned. */\n preTunedModel?: PreTunedModel;\n /** Cloud Storage path to file containing training dataset for tuning. The dataset must be formatted as a JSONL file. */\n trainingDataset: TuningDataset;\n /** Configuration for the tuning job. */\n config?: CreateTuningJobConfig;\n}\n\n/** A long-running operation. */\nexport declare interface TuningOperation {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`. */\n name?: string;\n /** Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata. Any method that returns a long-running operation should document the metadata type, if any. */\n metadata?: Record<string, unknown>;\n /** If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available. */\n done?: boolean;\n /** The error result of the operation in case of failure or cancellation. */\n error?: Record<string, unknown>;\n}\n\n/** Optional configuration for cached content creation. */\nexport declare interface CreateCachedContentConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** The TTL for this resource. The expiration time is computed: now + TTL. It is a duration string, with up to nine fractional digits, terminated by 's'. Example: \"3.5s\". */\n ttl?: string;\n /** Timestamp of when this resource is considered expired. Uses RFC 3339 format, Example: 2014-10-02T15:01:23Z. */\n expireTime?: string;\n /** The user-generated meaningful display name of the cached content.\n */\n displayName?: string;\n /** The content to cache.\n */\n contents?: ContentListUnion;\n /** Developer set system instruction.\n */\n systemInstruction?: ContentUnion;\n /** A list of `Tools` the model may use to generate the next response.\n */\n tools?: Tool[];\n /** Configuration for the tools to use. This config is shared for all tools.\n */\n toolConfig?: ToolConfig;\n /** The Cloud KMS resource identifier of the customer managed\n encryption key used to protect a resource.\n The key needs to be in the same region as where the compute resource is\n created. See\n https://cloud.google.com/vertex-ai/docs/general/cmek for more\n details. If this is set, then all created CachedContent objects\n will be encrypted with the provided encryption key.\n Allowed formats: projects/{project}/locations/{location}/keyRings/{key_ring}/cryptoKeys/{crypto_key}\n */\n kmsKeyName?: string;\n}\n\n/** Parameters for caches.create method. */\nexport declare interface CreateCachedContentParameters {\n /** ID of the model to use. Example: gemini-2.0-flash */\n model: string;\n /** Configuration that contains optional parameters.\n */\n config?: CreateCachedContentConfig;\n}\n\n/** Metadata on the usage of the cached content. */\nexport declare interface CachedContentUsageMetadata {\n /** Duration of audio in seconds. This field is not supported in Gemini API. */\n audioDurationSeconds?: number;\n /** Number of images. This field is not supported in Gemini API. */\n imageCount?: number;\n /** Number of text characters. This field is not supported in Gemini API. */\n textCount?: number;\n /** Total number of tokens that the cached content consumes. */\n totalTokenCount?: number;\n /** Duration of video in seconds. This field is not supported in Gemini API. */\n videoDurationSeconds?: number;\n}\n\n/** A resource used in LLM queries for users to explicitly specify what to cache. */\nexport declare interface CachedContent {\n /** The server-generated resource name of the cached content. */\n name?: string;\n /** The user-generated meaningful display name of the cached content. */\n displayName?: string;\n /** The name of the publisher model to use for cached content. */\n model?: string;\n /** Creation time of the cache entry. */\n createTime?: string;\n /** When the cache entry was last updated in UTC time. */\n updateTime?: string;\n /** Expiration time of the cached content. */\n expireTime?: string;\n /** Metadata on the usage of the cached content. */\n usageMetadata?: CachedContentUsageMetadata;\n}\n\n/** Optional parameters for caches.get method. */\nexport declare interface GetCachedContentConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for caches.get method. */\nexport declare interface GetCachedContentParameters {\n /** The server-generated resource name of the cached content.\n */\n name: string;\n /** Optional parameters for the request.\n */\n config?: GetCachedContentConfig;\n}\n\n/** Optional parameters for caches.delete method. */\nexport declare interface DeleteCachedContentConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for caches.delete method. */\nexport declare interface DeleteCachedContentParameters {\n /** The server-generated resource name of the cached content.\n */\n name: string;\n /** Optional parameters for the request.\n */\n config?: DeleteCachedContentConfig;\n}\n\n/** Empty response for caches.delete method. */\nexport class DeleteCachedContentResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n}\n\n/** Optional parameters for caches.update method. */\nexport declare interface UpdateCachedContentConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** The TTL for this resource. The expiration time is computed: now + TTL. It is a duration string, with up to nine fractional digits, terminated by 's'. Example: \"3.5s\". */\n ttl?: string;\n /** Timestamp of when this resource is considered expired. Uses RFC 3339 format, Example: 2014-10-02T15:01:23Z. */\n expireTime?: string;\n}\n\nexport declare interface UpdateCachedContentParameters {\n /** The server-generated resource name of the cached content.\n */\n name: string;\n /** Configuration that contains optional parameters.\n */\n config?: UpdateCachedContentConfig;\n}\n\n/** Config for caches.list method. */\nexport declare interface ListCachedContentsConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n pageSize?: number;\n pageToken?: string;\n}\n\n/** Parameters for caches.list method. */\nexport declare interface ListCachedContentsParameters {\n /** Configuration that contains optional parameters.\n */\n config?: ListCachedContentsConfig;\n}\n\nexport class ListCachedContentsResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n nextPageToken?: string;\n /** List of cached contents.\n */\n cachedContents?: CachedContent[];\n}\n\n/** Optional Config. */\nexport declare interface GetDocumentConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for documents.get. */\nexport declare interface GetDocumentParameters {\n /** The resource name of the Document.\n Example: fileSearchStores/file-search-store-foo/documents/documents-bar */\n name: string;\n /** Optional parameters for the request. */\n config?: GetDocumentConfig;\n}\n\n/** User provided string values assigned to a single metadata key. This data type is not supported in Vertex AI. */\nexport declare interface StringList {\n /** The string values of the metadata to store. */\n values?: string[];\n}\n\n/** User provided metadata stored as key-value pairs. This data type is not supported in Vertex AI. */\nexport declare interface CustomMetadata {\n /** Required. The key of the metadata to store. */\n key?: string;\n /** The numeric value of the metadata to store. */\n numericValue?: number;\n /** The StringList value of the metadata to store. */\n stringListValue?: StringList;\n /** The string value of the metadata to store. */\n stringValue?: string;\n}\n\n/** A Document is a collection of Chunks. */\nexport declare interface Document {\n /** The resource name of the Document.\n Example: fileSearchStores/file-search-store-foo/documents/documents-bar */\n name?: string;\n /** The human-readable display name for the Document. */\n displayName?: string;\n /** The current state of the Document. */\n state?: DocumentState;\n /** The size of the Document in bytes. */\n sizeBytes?: string;\n /** The MIME type of the Document. */\n mimeType?: string;\n /** Output only. The Timestamp of when the `Document` was created. */\n createTime?: string;\n /** Optional. User provided custom metadata stored as key-value pairs used for querying. A `Document` can have a maximum of 20 `CustomMetadata`. */\n customMetadata?: CustomMetadata[];\n /** Output only. The Timestamp of when the `Document` was last updated. */\n updateTime?: string;\n}\n\n/** Config for optional parameters. */\nexport declare interface DeleteDocumentConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** If set to true, any `Chunk`s and objects related to this `Document` will\n also be deleted.\n */\n force?: boolean;\n}\n\n/** Config for documents.delete parameters. */\nexport declare interface DeleteDocumentParameters {\n /** The resource name of the Document.\n Example: fileSearchStores/file-search-store-foo/documents/documents-bar */\n name: string;\n /** Optional parameters for the request. */\n config?: DeleteDocumentConfig;\n}\n\n/** Config for optional parameters. */\nexport declare interface ListDocumentsConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n pageSize?: number;\n pageToken?: string;\n}\n\n/** Config for documents.list parameters. */\nexport declare interface ListDocumentsParameters {\n /** The resource name of the FileSearchStores. Example: `fileSearchStore/file-search-store-foo` */\n parent: string;\n config?: ListDocumentsConfig;\n}\n\n/** Config for documents.list return value. */\nexport class ListDocumentsResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** A token, which can be sent as `page_token` to retrieve the next page. If this field is omitted, there are no more pages. */\n nextPageToken?: string;\n /** The returned `Document`s. */\n documents?: Document[];\n}\n\n/** Optional parameters for creating a file search store. */\nexport declare interface CreateFileSearchStoreConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** The human-readable display name for the file search store.\n */\n displayName?: string;\n}\n\n/** Config for file_search_stores.create parameters. */\nexport declare interface CreateFileSearchStoreParameters {\n /** Optional parameters for creating a file search store.\n */\n config?: CreateFileSearchStoreConfig;\n}\n\n/** A collection of Documents. */\nexport declare interface FileSearchStore {\n /** The resource name of the FileSearchStore. Example: `fileSearchStores/my-file-search-store-123` */\n name?: string;\n /** The human-readable display name for the FileSearchStore. */\n displayName?: string;\n /** The Timestamp of when the FileSearchStore was created. */\n createTime?: string;\n /** The Timestamp of when the FileSearchStore was last updated. */\n updateTime?: string;\n /** The number of documents in the FileSearchStore that are active and ready for retrieval. */\n activeDocumentsCount?: string;\n /** The number of documents in the FileSearchStore that are being processed. */\n pendingDocumentsCount?: string;\n /** The number of documents in the FileSearchStore that have failed processing. */\n failedDocumentsCount?: string;\n /** The size of raw bytes ingested into the FileSearchStore. This is the\n total size of all the documents in the FileSearchStore. */\n sizeBytes?: string;\n}\n\n/** Optional parameters for getting a FileSearchStore. */\nexport declare interface GetFileSearchStoreConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Config for file_search_stores.get parameters. */\nexport declare interface GetFileSearchStoreParameters {\n /** The resource name of the FileSearchStore. Example: `fileSearchStores/my-file-search-store-123` */\n name: string;\n /** Optional parameters for the request. */\n config?: GetFileSearchStoreConfig;\n}\n\n/** Optional parameters for deleting a FileSearchStore. */\nexport declare interface DeleteFileSearchStoreConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** If set to true, any Documents and objects related to this FileSearchStore will also be deleted.\n If false (the default), a FAILED_PRECONDITION error will be returned if\n the FileSearchStore contains any Documents.\n */\n force?: boolean;\n}\n\n/** Config for file_search_stores.delete parameters. */\nexport declare interface DeleteFileSearchStoreParameters {\n /** The resource name of the FileSearchStore. Example: `fileSearchStores/my-file-search-store-123` */\n name: string;\n /** Optional parameters for the request. */\n config?: DeleteFileSearchStoreConfig;\n}\n\n/** Optional parameters for listing FileSearchStore. */\nexport declare interface ListFileSearchStoresConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n pageSize?: number;\n pageToken?: string;\n}\n\n/** Config for file_search_stores.list parameters. */\nexport declare interface ListFileSearchStoresParameters {\n /** Optional parameters for the list request. */\n config?: ListFileSearchStoresConfig;\n}\n\n/** Config for file_search_stores.list return value. */\nexport class ListFileSearchStoresResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n nextPageToken?: string;\n /** The returned file search stores. */\n fileSearchStores?: FileSearchStore[];\n}\n\n/** Configuration for a white space chunking algorithm. */\nexport declare interface WhiteSpaceConfig {\n /** Maximum number of tokens per chunk. */\n maxTokensPerChunk?: number;\n /** Maximum number of overlapping tokens between two adjacent chunks. */\n maxOverlapTokens?: number;\n}\n\n/** Config for telling the service how to chunk the file. */\nexport declare interface ChunkingConfig {\n /** White space chunking configuration. */\n whiteSpaceConfig?: WhiteSpaceConfig;\n}\n\n/** Optional parameters for uploading a file to a FileSearchStore. */\nexport declare interface UploadToFileSearchStoreConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** MIME type of the file to be uploaded. If not provided, it will be inferred from the file extension. */\n mimeType?: string;\n /** Display name of the created document. */\n displayName?: string;\n /** User provided custom metadata stored as key-value pairs used for querying. */\n customMetadata?: CustomMetadata[];\n /** Config for telling the service how to chunk the file. */\n chunkingConfig?: ChunkingConfig;\n}\n\n/** Generates the parameters for the private _upload_to_file_search_store method. */\nexport declare interface UploadToFileSearchStoreParameters {\n /** The resource name of the FileSearchStore. Example: `fileSearchStores/my-file-search-store-123` */\n fileSearchStoreName: string;\n /** Used to override the default configuration. */\n config?: UploadToFileSearchStoreConfig;\n}\n\n/** Response for the resumable upload method. */\nexport class UploadToFileSearchStoreResumableResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n}\n\n/** Optional parameters for importing a file. */\nexport declare interface ImportFileConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** User provided custom metadata stored as key-value pairs used for querying. */\n customMetadata?: CustomMetadata[];\n /** Config for telling the service how to chunk the file. */\n chunkingConfig?: ChunkingConfig;\n}\n\n/** Config for file_search_stores.import_file parameters. */\nexport declare interface ImportFileParameters {\n /** The resource name of the FileSearchStore. Example: `fileSearchStores/my-file-search-store-123` */\n fileSearchStoreName: string;\n /** The name of the File API File to import. Example: `files/abc-123` */\n fileName: string;\n /** Optional parameters for the request. */\n config?: ImportFileConfig;\n}\n\n/** Response for ImportFile to import a File API file with a file search store. */\nexport class ImportFileResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** The name of the FileSearchStore containing Documents. */\n parent?: string;\n /** The identifier for the Document imported. */\n documentName?: string;\n}\n\n/** Long-running operation for importing a file to a FileSearchStore. */\nexport class ImportFileOperation implements Operation<ImportFileResponse> {\n /** The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`. */\n name?: string;\n /** Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata. Any method that returns a long-running operation should document the metadata type, if any. */\n metadata?: Record<string, unknown>;\n /** If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available. */\n done?: boolean;\n /** The error result of the operation in case of failure or cancellation. */\n error?: Record<string, unknown>;\n /** The result of the ImportFile operation, available when the operation is done. */\n response?: ImportFileResponse;\n\n /**\n * Instantiates an Operation of the same type as the one being called with the fields set from the API response.\n * @internal\n */\n _fromAPIResponse({\n apiResponse,\n _isVertexAI,\n }: OperationFromAPIResponseParameters): Operation<ImportFileResponse> {\n const operation = new ImportFileOperation();\n\n const op = apiResponse as unknown as ImportFileOperation;\n const response = importFileOperationFromMldev(op);\n Object.assign(operation, response);\n return operation;\n }\n /** The full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n}\n\nexport /** Used to override the default configuration. */\ndeclare interface ListFilesConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n pageSize?: number;\n pageToken?: string;\n}\n\n/** Generates the parameters for the list method. */\nexport declare interface ListFilesParameters {\n /** Used to override the default configuration. */\n config?: ListFilesConfig;\n}\n\n/** Status of a File that uses a common error model. */\nexport declare interface FileStatus {\n /** A list of messages that carry the error details. There is a common set of message types for APIs to use. */\n details?: Record<string, unknown>[];\n /** A list of messages that carry the error details. There is a common set of message types for APIs to use. */\n message?: string;\n /** The status code. 0 for OK, 1 for CANCELLED */\n code?: number;\n}\n\n/** A file uploaded to the API. */\nexport declare interface File {\n /** The `File` resource name. The ID (name excluding the \"files/\" prefix) can contain up to 40 characters that are lowercase alphanumeric or dashes (-). The ID cannot start or end with a dash. If the name is empty on create, a unique name will be generated. Example: `files/123-456` */\n name?: string;\n /** Optional. The human-readable display name for the `File`. The display name must be no more than 512 characters in length, including spaces. Example: 'Welcome Image' */\n displayName?: string;\n /** Output only. MIME type of the file. */\n mimeType?: string;\n /** Output only. Size of the file in bytes. */\n sizeBytes?: string;\n /** Output only. The timestamp of when the `File` was created. */\n createTime?: string;\n /** Output only. The timestamp of when the `File` will be deleted. Only set if the `File` is scheduled to expire. */\n expirationTime?: string;\n /** Output only. The timestamp of when the `File` was last updated. */\n updateTime?: string;\n /** Output only. SHA-256 hash of the uploaded bytes. The hash value is encoded in base64 format. */\n sha256Hash?: string;\n /** Output only. The URI of the `File`. */\n uri?: string;\n /** Output only. The URI of the `File`, only set for downloadable (generated) files. */\n downloadUri?: string;\n /** Output only. Processing state of the File. */\n state?: FileState;\n /** Output only. The source of the `File`. */\n source?: FileSource;\n /** Output only. Metadata for a video. */\n videoMetadata?: Record<string, unknown>;\n /** Output only. Error status if File processing failed. */\n error?: FileStatus;\n}\n\n/** Response for the list files method. */\nexport class ListFilesResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** A token that can be sent as a `page_token` into a subsequent `ListFiles` call. */\n nextPageToken?: string;\n /** The list of `File`s. */\n files?: File[];\n}\n\n/** Used to override the default configuration. */\nexport declare interface CreateFileConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Generates the parameters for the private _create method. */\nexport declare interface CreateFileParameters {\n /** The file to be uploaded.\n mime_type: (Required) The MIME type of the file. Must be provided.\n name: (Optional) The name of the file in the destination (e.g.\n 'files/sample-image').\n display_name: (Optional) The display name of the file.\n */\n file: File;\n /** Used to override the default configuration. */\n config?: CreateFileConfig;\n}\n\n/** Response for the create file method. */\nexport class CreateFileResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n}\n\n/** Used to override the default configuration. */\nexport declare interface GetFileConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Generates the parameters for the get method. */\nexport declare interface GetFileParameters {\n /** The name identifier for the file to retrieve. */\n name: string;\n /** Used to override the default configuration. */\n config?: GetFileConfig;\n}\n\n/** Used to override the default configuration. */\nexport declare interface DeleteFileConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Generates the parameters for the get method. */\nexport declare interface DeleteFileParameters {\n /** The name identifier for the file to be deleted. */\n name: string;\n /** Used to override the default configuration. */\n config?: DeleteFileConfig;\n}\n\n/** Response for the delete file method. */\nexport class DeleteFileResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n}\n\n/** Used to override the default configuration. */\nexport declare interface RegisterFilesConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for the private _Register method. */\nexport declare interface InternalRegisterFilesParameters {\n /** The Google Cloud Storage URIs to register. Example: `gs://bucket/object`. */\n uris: string[];\n /** Used to override the default configuration. */\n config?: RegisterFilesConfig;\n}\n\n/** Response for the _register file method. */\nexport class RegisterFilesResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** The registered files. */\n files?: File[];\n}\n\n/** Config for inlined request. */\nexport declare interface InlinedRequest {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model?: string;\n /** Content of the request.\n */\n contents?: ContentListUnion;\n /** The metadata to be associated with the request. */\n metadata?: Record<string, string>;\n /** Configuration that contains optional model parameters.\n */\n config?: GenerateContentConfig;\n}\n\n/** Config for `src` parameter. */\nexport declare interface BatchJobSource {\n /** Storage format of the input files. Must be one of:\n 'jsonl', 'bigquery'.\n */\n format?: string;\n /** The Google Cloud Storage URIs to input files.\n */\n gcsUri?: string[];\n /** The BigQuery URI to input table.\n */\n bigqueryUri?: string;\n /** The Gemini Developer API's file resource name of the input data\n (e.g. \"files/12345\").\n */\n fileName?: string;\n /** The Gemini Developer API's inlined input data to run batch job.\n */\n inlinedRequests?: InlinedRequest[];\n}\n\n/** Job error. */\nexport declare interface JobError {\n /** A list of messages that carry the error details. There is a common set of message types for APIs to use. */\n details?: string[];\n /** The status code. */\n code?: number;\n /** A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the `details` field. */\n message?: string;\n}\n\n/** Config for `inlined_responses` parameter. */\nexport class InlinedResponse {\n /** The response to the request.\n */\n response?: GenerateContentResponse;\n /** The metadata to be associated with the request. */\n metadata?: Record<string, string>;\n /** The error encountered while processing the request.\n */\n error?: JobError;\n}\n\n/** Config for `response` parameter. */\nexport class SingleEmbedContentResponse {\n /** The response to the request.\n */\n embedding?: ContentEmbedding;\n /** The error encountered while processing the request.\n */\n tokenCount?: string;\n}\n\n/** Config for `inlined_embedding_responses` parameter. */\nexport class InlinedEmbedContentResponse {\n /** The response to the request.\n */\n response?: SingleEmbedContentResponse;\n /** The error encountered while processing the request.\n */\n error?: JobError;\n}\n\n/** Config for `des` parameter. */\nexport declare interface BatchJobDestination {\n /** Storage format of the output files. Must be one of:\n 'jsonl', 'bigquery'.\n */\n format?: string;\n /** The Google Cloud Storage URI to the output file.\n */\n gcsUri?: string;\n /** The BigQuery URI to the output table.\n */\n bigqueryUri?: string;\n /** The Gemini Developer API's file resource name of the output data\n (e.g. \"files/12345\"). The file will be a JSONL file with a single response\n per line. The responses will be GenerateContentResponse messages formatted\n as JSON. The responses will be written in the same order as the input\n requests.\n */\n fileName?: string;\n /** The responses to the requests in the batch. Returned when the batch was\n built using inlined requests. The responses will be in the same order as\n the input requests.\n */\n inlinedResponses?: InlinedResponse[];\n /** The responses to the requests in the batch. Returned when the batch was\n built using inlined requests. The responses will be in the same order as\n the input requests.\n */\n inlinedEmbedContentResponses?: InlinedEmbedContentResponse[];\n}\n\n/** Config for optional parameters. */\nexport declare interface CreateBatchJobConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** The user-defined name of this BatchJob.\n */\n displayName?: string;\n /** GCS or BigQuery URI prefix for the output predictions. Example:\n \"gs://path/to/output/data\" or \"bq://projectId.bqDatasetId.bqTableId\".\n */\n dest?: BatchJobDestinationUnion;\n}\n\n/** Config for batches.create parameters. */\nexport declare interface CreateBatchJobParameters {\n /** The name of the model to produces the predictions via the BatchJob.\n */\n model?: string;\n /** GCS URI(-s) or BigQuery URI to your input data to run batch job.\n Example: \"gs://path/to/input/data\" or \"bq://projectId.bqDatasetId.bqTableId\".\n */\n src: BatchJobSourceUnion;\n /** Optional parameters for creating a BatchJob.\n */\n config?: CreateBatchJobConfig;\n}\n\n/** Success and error statistics of processing multiple entities (for example, DataItems or structured data rows) in batch. This data type is not supported in Gemini API. */\nexport declare interface CompletionStats {\n /** Output only. The number of entities for which any error was encountered. */\n failedCount?: string;\n /** Output only. In cases when enough errors are encountered a job, pipeline, or operation may be failed as a whole. Below is the number of entities for which the processing had not been finished (either in successful or failed state). Set to -1 if the number is unknown (for example, the operation failed before the total entity number could be collected). */\n incompleteCount?: string;\n /** Output only. The number of entities that had been processed successfully. */\n successfulCount?: string;\n /** Output only. The number of the successful forecast points that are generated by the forecasting model. This is ONLY used by the forecasting batch prediction. */\n successfulForecastPointCount?: string;\n}\n\n/** Config for batches.create return value. */\nexport declare interface BatchJob {\n /** The resource name of the BatchJob. Output only.\".\n */\n name?: string;\n /** The display name of the BatchJob.\n */\n displayName?: string;\n /** The state of the BatchJob.\n */\n state?: JobState;\n /** Output only. Only populated when the job's state is JOB_STATE_FAILED or JOB_STATE_CANCELLED. */\n error?: JobError;\n /** The time when the BatchJob was created.\n */\n createTime?: string;\n /** Output only. Time when the Job for the first time entered the `JOB_STATE_RUNNING` state. */\n startTime?: string;\n /** The time when the BatchJob was completed. This field is for Vertex AI only.\n */\n endTime?: string;\n /** The time when the BatchJob was last updated.\n */\n updateTime?: string;\n /** The name of the model that produces the predictions via the BatchJob.\n */\n model?: string;\n /** Configuration for the input data. This field is for Vertex AI only.\n */\n src?: BatchJobSource;\n /** Configuration for the output data.\n */\n dest?: BatchJobDestination;\n /** Statistics on completed and failed prediction instances. This field is for Vertex AI only.\n */\n completionStats?: CompletionStats;\n}\n\n/** Parameters for the embed_content method. */\nexport declare interface EmbedContentBatch {\n /** The content to embed. Only the `parts.text` fields will be counted.\n */\n contents?: ContentListUnion;\n /** Configuration that contains optional parameters.\n */\n config?: EmbedContentConfig;\n}\n\nexport declare interface EmbeddingsBatchJobSource {\n /** The Gemini Developer API's file resource name of the input data\n (e.g. \"files/12345\").\n */\n fileName?: string;\n /** The Gemini Developer API's inlined input data to run batch job.\n */\n inlinedRequests?: EmbedContentBatch;\n}\n\n/** Config for optional parameters. */\nexport declare interface CreateEmbeddingsBatchJobConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** The user-defined name of this BatchJob.\n */\n displayName?: string;\n}\n\n/** Config for batches.create parameters. */\nexport declare interface CreateEmbeddingsBatchJobParameters {\n /** The name of the model to produces the predictions via the BatchJob.\n */\n model?: string;\n /** input data to run batch job\".\n */\n src: EmbeddingsBatchJobSource;\n /** Optional parameters for creating a BatchJob.\n */\n config?: CreateEmbeddingsBatchJobConfig;\n}\n\n/** Optional parameters. */\nexport declare interface GetBatchJobConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Config for batches.get parameters. */\nexport declare interface GetBatchJobParameters {\n /** A fully-qualified BatchJob resource name or ID.\n Example: \"projects/.../locations/.../batchPredictionJobs/456\"\n or \"456\" when project and location are initialized in the client.\n */\n name: string;\n /** Optional parameters for the request. */\n config?: GetBatchJobConfig;\n}\n\n/** Optional parameters. */\nexport declare interface CancelBatchJobConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Config for batches.cancel parameters. */\nexport declare interface CancelBatchJobParameters {\n /** A fully-qualified BatchJob resource name or ID.\n Example: \"projects/.../locations/.../batchPredictionJobs/456\"\n or \"456\" when project and location are initialized in the client.\n */\n name: string;\n /** Optional parameters for the request. */\n config?: CancelBatchJobConfig;\n}\n\n/** Config for optional parameters. */\nexport declare interface ListBatchJobsConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n pageSize?: number;\n pageToken?: string;\n filter?: string;\n}\n\n/** Config for batches.list parameters. */\nexport declare interface ListBatchJobsParameters {\n config?: ListBatchJobsConfig;\n}\n\n/** Config for batches.list return value. */\nexport class ListBatchJobsResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n nextPageToken?: string;\n batchJobs?: BatchJob[];\n}\n\n/** Optional parameters for models.get method. */\nexport declare interface DeleteBatchJobConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Config for batches.delete parameters. */\nexport declare interface DeleteBatchJobParameters {\n /** A fully-qualified BatchJob resource name or ID.\n Example: \"projects/.../locations/.../batchPredictionJobs/456\"\n or \"456\" when project and location are initialized in the client.\n */\n name: string;\n /** Optional parameters for the request. */\n config?: DeleteBatchJobConfig;\n}\n\n/** The return value of delete operation. */\nexport declare interface DeleteResourceJob {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n name?: string;\n done?: boolean;\n error?: JobError;\n}\n\nexport declare interface GetOperationConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for the GET method. */\nexport declare interface GetOperationParameters {\n /** The server-assigned name for the operation. */\n operationName: string;\n /** Used to override the default configuration. */\n config?: GetOperationConfig;\n}\n\nexport declare interface FetchPredictOperationConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters for the fetchPredictOperation method. */\nexport declare interface FetchPredictOperationParameters {\n /** The server-assigned name for the operation. */\n operationName: string;\n resourceName: string;\n /** Used to override the default configuration. */\n config?: FetchPredictOperationConfig;\n}\n\nexport declare interface TestTableItem {\n /** The name of the test. This is used to derive the replay id. */\n name?: string;\n /** The parameters to the test. Use pydantic models. */\n parameters?: Record<string, unknown>;\n /** Expects an exception for MLDev matching the string. */\n exceptionIfMldev?: string;\n /** Expects an exception for Vertex matching the string. */\n exceptionIfVertex?: string;\n /** Use if you don't want to use the default replay id which is derived from the test name. */\n overrideReplayId?: string;\n /** True if the parameters contain an unsupported union type. This test will be skipped for languages that do not support the union type. */\n hasUnion?: boolean;\n /** When set to a reason string, this test will be skipped in the API mode. Use this flag for tests that can not be reproduced with the real API. E.g. a test that deletes a resource. */\n skipInApiMode?: string;\n /** Keys to ignore when comparing the request and response. This is useful for tests that are not deterministic. */\n ignoreKeys?: string[];\n}\n\nexport declare interface TestTableFile {\n comment?: string;\n testMethod?: string;\n parameterNames?: string[];\n testTable?: TestTableItem[];\n}\n\n/** Represents a single request in a replay. */\nexport declare interface ReplayRequest {\n method?: string;\n url?: string;\n headers?: Record<string, string>;\n bodySegments?: Record<string, unknown>[];\n}\n\n/** Represents a single response in a replay. */\nexport class ReplayResponse {\n statusCode?: number;\n headers?: Record<string, string>;\n bodySegments?: Record<string, unknown>[];\n sdkResponseSegments?: Record<string, unknown>[];\n}\n\n/** Represents a single interaction, request and response in a replay. */\nexport declare interface ReplayInteraction {\n request?: ReplayRequest;\n response?: ReplayResponse;\n}\n\n/** Represents a recorded session. */\nexport declare interface ReplayFile {\n replayId?: string;\n interactions?: ReplayInteraction[];\n}\n\n/** Used to override the default configuration. */\nexport declare interface UploadFileConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** The name of the file in the destination (e.g., 'files/sample-image'. If not provided one will be generated. */\n name?: string;\n /** mime_type: The MIME type of the file. If not provided, it will be inferred from the file extension. */\n mimeType?: string;\n /** Optional display name of the file. */\n displayName?: string;\n}\n\n/** Used to override the default configuration. */\nexport declare interface DownloadFileConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Parameters used to download a file. */\nexport declare interface DownloadFileParameters {\n /** The file to download. It can be a file name, a file object or a generated video. */\n file: DownloadableFileUnion;\n /** Location where the file should be downloaded to. */\n downloadPath: string;\n /** Configuration to for the download operation. */\n config?: DownloadFileConfig;\n}\n\n/** Configuration for upscaling an image.\n\nFor more information on this configuration, refer to\nthe `Imagen API reference documentation\n<https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/imagen-api>`_. */\nexport declare interface UpscaleImageConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** Cloud Storage URI used to store the generated images. */\n outputGcsUri?: string;\n /** Filter level for safety filtering. */\n safetyFilterLevel?: SafetyFilterLevel;\n /** Allows generation of people by the model. */\n personGeneration?: PersonGeneration;\n /** Whether to include a reason for filtered-out images in the\n response. */\n includeRaiReason?: boolean;\n /** The image format that the output should be saved as. */\n outputMimeType?: string;\n /** The level of compression. Only applicable if the\n ``output_mime_type`` is ``image/jpeg``. */\n outputCompressionQuality?: number;\n /** Whether to add an image enhancing step before upscaling.\n It is expected to suppress the noise and JPEG compression artifacts\n from the input image. */\n enhanceInputImage?: boolean;\n /** With a higher image preservation factor, the original image\n pixels are more respected. With a lower image preservation factor, the\n output image will have be more different from the input image, but\n with finer details and less noise. */\n imagePreservationFactor?: number;\n /** User specified labels to track billing usage. */\n labels?: Record<string, string>;\n}\n\n/** User-facing config UpscaleImageParameters. */\nexport declare interface UpscaleImageParameters {\n /** The model to use. */\n model: string;\n /** The input image to upscale. */\n image: Image;\n /** The factor to upscale the image (x2 or x4). */\n upscaleFactor: string;\n /** Configuration for upscaling. */\n config?: UpscaleImageConfig;\n}\n\n/** A raw reference image.\n\nA raw reference image represents the base image to edit, provided by the user.\nIt can optionally be provided in addition to a mask reference image or\na style reference image. */\nexport class RawReferenceImage {\n /** The reference image for the editing operation. */\n referenceImage?: Image;\n /** The id of the reference image. */\n referenceId?: number;\n /** The type of the reference image. Only set by the SDK. */\n referenceType?: string;\n /** Internal method to convert to ReferenceImageAPIInternal. */\n toReferenceImageAPI(): ReferenceImageAPIInternal {\n const referenceImageAPI = {\n referenceType: 'REFERENCE_TYPE_RAW',\n referenceImage: this.referenceImage,\n referenceId: this.referenceId,\n };\n return referenceImageAPI;\n }\n}\n\n/** A mask reference image.\n\nThis encapsulates either a mask image provided by the user and configs for\nthe user provided mask, or only config parameters for the model to generate\na mask.\n\nA mask image is an image whose non-zero values indicate where to edit the base\nimage. If the user provides a mask image, the mask must be in the same\ndimensions as the raw image. */\nexport class MaskReferenceImage {\n /** The reference image for the editing operation. */\n referenceImage?: Image;\n /** The id of the reference image. */\n referenceId?: number;\n /** The type of the reference image. Only set by the SDK. */\n referenceType?: string;\n /** Configuration for the mask reference image. */\n config?: MaskReferenceConfig;\n /** Internal method to convert to ReferenceImageAPIInternal. */\n toReferenceImageAPI(): ReferenceImageAPIInternal {\n const referenceImageAPI = {\n referenceType: 'REFERENCE_TYPE_MASK',\n referenceImage: this.referenceImage,\n referenceId: this.referenceId,\n maskImageConfig: this.config,\n };\n return referenceImageAPI;\n }\n}\n\n/** A control reference image.\n\nThe image of the control reference image is either a control image provided\nby the user, or a regular image which the backend will use to generate a\ncontrol image of. In the case of the latter, the\nenable_control_image_computation field in the config should be set to True.\n\nA control image is an image that represents a sketch image of areas for the\nmodel to fill in based on the prompt. */\nexport class ControlReferenceImage {\n /** The reference image for the editing operation. */\n referenceImage?: Image;\n /** The id of the reference image. */\n referenceId?: number;\n /** The type of the reference image. Only set by the SDK. */\n referenceType?: string;\n /** Configuration for the control reference image. */\n config?: ControlReferenceConfig;\n /** Internal method to convert to ReferenceImageAPIInternal. */\n toReferenceImageAPI(): ReferenceImageAPIInternal {\n const referenceImageAPI = {\n referenceType: 'REFERENCE_TYPE_CONTROL',\n referenceImage: this.referenceImage,\n referenceId: this.referenceId,\n controlImageConfig: this.config,\n };\n return referenceImageAPI;\n }\n}\n\n/** A style reference image.\n\nThis encapsulates a style reference image provided by the user, and\nadditionally optional config parameters for the style reference image.\n\nA raw reference image can also be provided as a destination for the style to\nbe applied to. */\nexport class StyleReferenceImage {\n /** The reference image for the editing operation. */\n referenceImage?: Image;\n /** The id of the reference image. */\n referenceId?: number;\n /** The type of the reference image. Only set by the SDK. */\n referenceType?: string;\n /** Configuration for the style reference image. */\n config?: StyleReferenceConfig;\n /** Internal method to convert to ReferenceImageAPIInternal. */\n toReferenceImageAPI(): ReferenceImageAPIInternal {\n const referenceImageAPI = {\n referenceType: 'REFERENCE_TYPE_STYLE',\n referenceImage: this.referenceImage,\n referenceId: this.referenceId,\n styleImageConfig: this.config,\n };\n return referenceImageAPI;\n }\n}\n\n/** A subject reference image.\n\nThis encapsulates a subject reference image provided by the user, and\nadditionally optional config parameters for the subject reference image.\n\nA raw reference image can also be provided as a destination for the subject to\nbe applied to. */\nexport class SubjectReferenceImage {\n /** The reference image for the editing operation. */\n referenceImage?: Image;\n /** The id of the reference image. */\n referenceId?: number;\n /** The type of the reference image. Only set by the SDK. */\n referenceType?: string;\n /** Configuration for the subject reference image. */\n config?: SubjectReferenceConfig;\n /* Internal method to convert to ReferenceImageAPIInternal. */\n toReferenceImageAPI(): ReferenceImageAPIInternal {\n const referenceImageAPI = {\n referenceType: 'REFERENCE_TYPE_SUBJECT',\n referenceImage: this.referenceImage,\n referenceId: this.referenceId,\n subjectImageConfig: this.config,\n };\n return referenceImageAPI;\n }\n}\n\n/** A content reference image.\n\nA content reference image represents a subject to reference (ex. person,\nproduct, animal) provided by the user. It can optionally be provided in\naddition to a style reference image (ex. background, style reference). */\nexport class ContentReferenceImage {\n /** The reference image for the editing operation. */\n referenceImage?: Image;\n /** The id of the reference image. */\n referenceId?: number;\n /** The type of the reference image. Only set by the SDK. */\n referenceType?: string;\n /** Internal method to convert to ReferenceImageAPIInternal. */\n toReferenceImageAPI(): ReferenceImageAPIInternal {\n const referenceImageAPI = {\n referenceType: 'REFERENCE_TYPE_CONTENT',\n referenceImage: this.referenceImage,\n referenceId: this.referenceId,\n };\n return referenceImageAPI;\n }\n}\n\n/** Sent in response to a `LiveGenerateContentSetup` message from the client. */\nexport declare interface LiveServerSetupComplete {\n /** The session id of the live session. */\n sessionId?: string;\n}\n\n/** Audio transcription in Server Conent. */\nexport declare interface Transcription {\n /** Transcription text.\n */\n text?: string;\n /** The bool indicates the end of the transcription.\n */\n finished?: boolean;\n}\n\n/** Incremental server update generated by the model in response to client messages.\n\nContent is generated as quickly as possible, and not in real time. Clients\nmay choose to buffer and play it out in real time. */\nexport declare interface LiveServerContent {\n /** The content that the model has generated as part of the current conversation with the user. */\n modelTurn?: Content;\n /** If true, indicates that the model is done generating. Generation will only start in response to additional client messages. Can be set alongside `content`, indicating that the `content` is the last in the turn. */\n turnComplete?: boolean;\n /** If true, indicates that a client message has interrupted current model generation. If the client is playing out the content in realtime, this is a good signal to stop and empty the current queue. */\n interrupted?: boolean;\n /** Metadata returned to client when grounding is enabled. */\n groundingMetadata?: GroundingMetadata;\n /** If true, indicates that the model is done generating. When model is\n interrupted while generating there will be no generation_complete message\n in interrupted turn, it will go through interrupted > turn_complete.\n When model assumes realtime playback there will be delay between\n generation_complete and turn_complete that is caused by model\n waiting for playback to finish. If true, indicates that the model\n has finished generating all content. This is a signal to the client\n that it can stop sending messages. */\n generationComplete?: boolean;\n /** Input transcription. The transcription is independent to the model\n turn which means it doesn’t imply any ordering between transcription and\n model turn. */\n inputTranscription?: Transcription;\n /** Output transcription. The transcription is independent to the model\n turn which means it doesn’t imply any ordering between transcription and\n model turn.\n */\n outputTranscription?: Transcription;\n /** Metadata related to url context retrieval tool. */\n urlContextMetadata?: UrlContextMetadata;\n /** Reason for the turn is complete. */\n turnCompleteReason?: TurnCompleteReason;\n /** If true, indicates that the model is not generating content because\n it is waiting for more input from the user, e.g. because it expects the\n user to continue talking. */\n waitingForInput?: boolean;\n}\n\n/** Request for the client to execute the `function_calls` and return the responses with the matching `id`s. */\nexport declare interface LiveServerToolCall {\n /** The function call to be executed. */\n functionCalls?: FunctionCall[];\n}\n\n/** Notification for the client that a previously issued `ToolCallMessage` with the specified `id`s should have been not executed and should be cancelled.\n\nIf there were side-effects to those tool calls, clients may attempt to undo\nthe tool calls. This message occurs only in cases where the clients interrupt\nserver turns. */\nexport declare interface LiveServerToolCallCancellation {\n /** The ids of the tool calls to be cancelled. */\n ids?: string[];\n}\n\n/** Usage metadata about response(s). */\nexport declare interface UsageMetadata {\n /** Number of tokens in the prompt. When `cached_content` is set, this is still the total effective prompt size meaning this includes the number of tokens in the cached content. */\n promptTokenCount?: number;\n /** Number of tokens in the cached part of the prompt (the cached content). */\n cachedContentTokenCount?: number;\n /** Total number of tokens across all the generated response candidates. */\n responseTokenCount?: number;\n /** Number of tokens present in tool-use prompt(s). */\n toolUsePromptTokenCount?: number;\n /** Number of tokens of thoughts for thinking models. */\n thoughtsTokenCount?: number;\n /** Total token count for prompt, response candidates, and tool-use prompts(if present). */\n totalTokenCount?: number;\n /** List of modalities that were processed in the request input. */\n promptTokensDetails?: ModalityTokenCount[];\n /** List of modalities that were processed in the cache input. */\n cacheTokensDetails?: ModalityTokenCount[];\n /** List of modalities that were returned in the response. */\n responseTokensDetails?: ModalityTokenCount[];\n /** List of modalities that were processed in the tool-use prompt. */\n toolUsePromptTokensDetails?: ModalityTokenCount[];\n /** Traffic type. This shows whether a request consumes Pay-As-You-Go\n or Provisioned Throughput quota. */\n trafficType?: TrafficType;\n}\n\n/** Server will not be able to service client soon. */\nexport declare interface LiveServerGoAway {\n /** The remaining time before the connection will be terminated as ABORTED. The minimal time returned here is specified differently together with the rate limits for a given model. */\n timeLeft?: string;\n}\n\n/** Update of the session resumption state.\n\nOnly sent if `session_resumption` was set in the connection config. */\nexport declare interface LiveServerSessionResumptionUpdate {\n /** New handle that represents state that can be resumed. Empty if `resumable`=false. */\n newHandle?: string;\n /** True if session can be resumed at this point. It might be not possible to resume session at some points. In that case we send update empty new_handle and resumable=false. Example of such case could be model executing function calls or just generating. Resuming session (using previous session token) in such state will result in some data loss. */\n resumable?: boolean;\n /** Index of last message sent by client that is included in state represented by this SessionResumptionToken. Only sent when `SessionResumptionConfig.transparent` is set.\n\nPresence of this index allows users to transparently reconnect and avoid issue of losing some part of realtime audio input/video. If client wishes to temporarily disconnect (for example as result of receiving GoAway) they can do it without losing state by buffering messages sent since last `SessionResmumptionTokenUpdate`. This field will enable them to limit buffering (avoid keeping all requests in RAM).\n\nNote: This should not be used for when resuming a session at some time later -- in those cases partial audio and video frames arelikely not needed. */\n lastConsumedClientMessageIndex?: string;\n}\n\nexport declare interface VoiceActivityDetectionSignal {\n /** The type of the VAD signal. */\n vadSignalType?: VadSignalType;\n}\n\n/** Voice activity signal. */\nexport declare interface VoiceActivity {\n /** The type of the voice activity signal. */\n voiceActivityType?: VoiceActivityType;\n}\n\n/** Response message for API call. */\nexport class LiveServerMessage {\n /** Sent in response to a `LiveClientSetup` message from the client. */\n setupComplete?: LiveServerSetupComplete;\n /** Content generated by the model in response to client messages. */\n serverContent?: LiveServerContent;\n /** Request for the client to execute the `function_calls` and return the responses with the matching `id`s. */\n toolCall?: LiveServerToolCall;\n /** Notification for the client that a previously issued `ToolCallMessage` with the specified `id`s should have been not executed and should be cancelled. */\n toolCallCancellation?: LiveServerToolCallCancellation;\n /** Usage metadata about model response(s). */\n usageMetadata?: UsageMetadata;\n /** Server will disconnect soon. */\n goAway?: LiveServerGoAway;\n /** Update of the session resumption state. */\n sessionResumptionUpdate?: LiveServerSessionResumptionUpdate;\n /** Voice activity detection signal. Allowlisted only. */\n voiceActivityDetectionSignal?: VoiceActivityDetectionSignal;\n /** Voice activity signal. */\n voiceActivity?: VoiceActivity;\n /**\n * Returns the concatenation of all text parts from the server content if present.\n *\n * @remarks\n * If there are non-text parts in the response, the concatenation of all text\n * parts will be returned, and a warning will be logged.\n */\n get text(): string | undefined {\n let text = '';\n let anyTextPartFound = false;\n const nonTextParts = [];\n for (const part of this.serverContent?.modelTurn?.parts ?? []) {\n for (const [fieldName, fieldValue] of Object.entries(part)) {\n if (\n fieldName !== 'text' &&\n fieldName !== 'thought' &&\n fieldValue !== null\n ) {\n nonTextParts.push(fieldName);\n }\n }\n if (typeof part.text === 'string') {\n if (typeof part.thought === 'boolean' && part.thought) {\n continue;\n }\n anyTextPartFound = true;\n text += part.text;\n }\n }\n if (nonTextParts.length > 0) {\n console.warn(\n `there are non-text parts ${nonTextParts} in the response, returning concatenation of all text parts. Please refer to the non text parts for a full response from model.`,\n );\n }\n // part.text === '' is different from part.text is null\n return anyTextPartFound ? text : undefined;\n }\n\n /**\n * Returns the concatenation of all inline data parts from the server content if present.\n *\n * @remarks\n * If there are non-inline data parts in the\n * response, the concatenation of all inline data parts will be returned, and\n * a warning will be logged.\n */\n get data(): string | undefined {\n let data = '';\n const nonDataParts = [];\n for (const part of this.serverContent?.modelTurn?.parts ?? []) {\n for (const [fieldName, fieldValue] of Object.entries(part)) {\n if (fieldName !== 'inlineData' && fieldValue !== null) {\n nonDataParts.push(fieldName);\n }\n }\n if (part.inlineData && typeof part.inlineData.data === 'string') {\n data += atob(part.inlineData.data);\n }\n }\n if (nonDataParts.length > 0) {\n console.warn(\n `there are non-data parts ${nonDataParts} in the response, returning concatenation of all data parts. Please refer to the non data parts for a full response from model.`,\n );\n }\n return data.length > 0 ? btoa(data) : undefined;\n }\n}\n\n/** Parameters of the fromAPIResponse method of the Operation class. */\nexport declare interface OperationFromAPIResponseParameters {\n /** The API response to be converted to an Operation. */\n apiResponse: Record<string, unknown>;\n /** Whether the API response is from Vertex AI. */\n _isVertexAI: boolean;\n}\n\n/**\n * Config for thinking feature.\n *\n * @deprecated This interface will be deprecated. Please use `ThinkingConfig` instead.\n */\nexport declare interface GenerationConfigThinkingConfig\n extends ThinkingConfig {}\n\n/** Generates the parameters for the private registerFiles method. */\nexport declare interface RegisterFilesParameters {\n /**\n * The authentication object.\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n auth?: any;\n /**\n * The Google Cloud Storage URIs to register. Example: `gs://bucket/object`.\n */\n uris: string[];\n /** Used to override the default configuration. */\n config?: RegisterFilesConfig;\n}\n\n/** Configures automatic detection of activity. */\nexport declare interface AutomaticActivityDetection {\n /** If enabled, detected voice and text input count as activity. If disabled, the client must send activity signals. */\n disabled?: boolean;\n /** Determines how likely speech is to be detected. */\n startOfSpeechSensitivity?: StartSensitivity;\n /** Determines how likely detected speech is ended. */\n endOfSpeechSensitivity?: EndSensitivity;\n /** The required duration of detected speech before start-of-speech is committed. The lower this value the more sensitive the start-of-speech detection is and the shorter speech can be recognized. However, this also increases the probability of false positives. */\n prefixPaddingMs?: number;\n /** The required duration of detected non-speech (e.g. silence) before end-of-speech is committed. The larger this value, the longer speech gaps can be without interrupting the user's activity but this will increase the model's latency. */\n silenceDurationMs?: number;\n}\n\n/** Marks the end of user activity.\n\nThis can only be sent if automatic (i.e. server-side) activity detection is\ndisabled. */\nexport declare interface RealtimeInputConfig {\n /** If not set, automatic activity detection is enabled by default. If automatic voice detection is disabled, the client must send activity signals. */\n automaticActivityDetection?: AutomaticActivityDetection;\n /** Defines what effect activity has. */\n activityHandling?: ActivityHandling;\n /** Defines which input is included in the user's turn. */\n turnCoverage?: TurnCoverage;\n}\n\n/** Configuration of session resumption mechanism.\n\nIncluded in `LiveConnectConfig.session_resumption`. If included server\nwill send `LiveServerSessionResumptionUpdate` messages. */\nexport declare interface SessionResumptionConfig {\n /** Session resumption handle of previous session (session to restore).\n\nIf not present new session will be started. */\n handle?: string;\n /** If set the server will send `last_consumed_client_message_index` in the `session_resumption_update` messages to allow for transparent reconnections. */\n transparent?: boolean;\n}\n\n/** Context window will be truncated by keeping only suffix of it.\n\nContext window will always be cut at start of USER role turn. System\ninstructions and `BidiGenerateContentSetup.prefix_turns` will not be\nsubject to the sliding window mechanism, they will always stay at the\nbeginning of context window. */\nexport declare interface SlidingWindow {\n /** Session reduction target -- how many tokens we should keep. Window shortening operation has some latency costs, so we should avoid running it on every turn. Should be < trigger_tokens. If not set, trigger_tokens/2 is assumed. */\n targetTokens?: string;\n}\n\n/** Enables context window compression -- mechanism managing model context window so it does not exceed given length. */\nexport declare interface ContextWindowCompressionConfig {\n /** Number of tokens (before running turn) that triggers context window compression mechanism. */\n triggerTokens?: string;\n /** Sliding window compression mechanism. */\n slidingWindow?: SlidingWindow;\n}\n\n/** The audio transcription configuration in Setup. */\nexport declare interface AudioTranscriptionConfig {}\n\n/** Config for proactivity features. */\nexport declare interface ProactivityConfig {\n /** If enabled, the model can reject responding to the last prompt. For\n example, this allows the model to ignore out of context speech or to stay\n silent if the user did not make a request, yet. */\n proactiveAudio?: boolean;\n}\n\n/** Message contains configuration that will apply for the duration of the streaming session. */\nexport declare interface LiveClientSetup {\n /** \n The fully qualified name of the publisher model or tuned model endpoint to\n use.\n */\n model?: string;\n /** The generation configuration for the session.\n Note: only a subset of fields are supported.\n */\n generationConfig?: GenerationConfig;\n /** The user provided system instructions for the model.\n Note: only text should be used in parts and content in each part will be\n in a separate paragraph. */\n systemInstruction?: ContentUnion;\n /** A list of `Tools` the model may use to generate the next response.\n\n A `Tool` is a piece of code that enables the system to interact with\n external systems to perform an action, or set of actions, outside of\n knowledge and scope of the model. */\n tools?: ToolListUnion;\n /** Configures the realtime input behavior in BidiGenerateContent. */\n realtimeInputConfig?: RealtimeInputConfig;\n /** Configures session resumption mechanism.\n\n If included server will send SessionResumptionUpdate messages. */\n sessionResumption?: SessionResumptionConfig;\n /** Configures context window compression mechanism.\n\n If included, server will compress context window to fit into given length. */\n contextWindowCompression?: ContextWindowCompressionConfig;\n /** The transcription of the input aligns with the input audio language.\n */\n inputAudioTranscription?: AudioTranscriptionConfig;\n /** The transcription of the output aligns with the language code\n specified for the output audio.\n */\n outputAudioTranscription?: AudioTranscriptionConfig;\n /** Configures the proactivity of the model. This allows the model to respond proactively to\n the input and to ignore irrelevant input. */\n proactivity?: ProactivityConfig;\n /** Configures the explicit VAD signal. If enabled, the client will send\n vad_signal to indicate the start and end of speech. This allows the server\n to process the audio more efficiently. */\n explicitVadSignal?: boolean;\n}\n\n/** Incremental update of the current conversation delivered from the client.\n\nAll the content here will unconditionally be appended to the conversation\nhistory and used as part of the prompt to the model to generate content.\n\nA message here will interrupt any current model generation. */\nexport declare interface LiveClientContent {\n /** The content appended to the current conversation with the model.\n\n For single-turn queries, this is a single instance. For multi-turn\n queries, this is a repeated field that contains conversation history and\n latest request.\n */\n turns?: Content[];\n /** If true, indicates that the server content generation should start with\n the currently accumulated prompt. Otherwise, the server will await\n additional messages before starting generation. */\n turnComplete?: boolean;\n}\n\n/** Marks the start of user activity.\n\nThis can only be sent if automatic (i.e. server-side) activity detection is\ndisabled. */\nexport declare interface ActivityStart {}\n\n/** Marks the end of user activity.\n\nThis can only be sent if automatic (i.e. server-side) activity detection is\ndisabled. */\nexport declare interface ActivityEnd {}\n\n/** User input that is sent in real time.\n\nThis is different from `LiveClientContent` in a few ways:\n\n - Can be sent continuously without interruption to model generation.\n - If there is a need to mix data interleaved across the\n `LiveClientContent` and the `LiveClientRealtimeInput`, server attempts to\n optimize for best response, but there are no guarantees.\n - End of turn is not explicitly specified, but is rather derived from user\n activity (for example, end of speech).\n - Even before the end of turn, the data is processed incrementally\n to optimize for a fast start of the response from the model.\n - Is always assumed to be the user's input (cannot be used to populate\n conversation history). */\nexport declare interface LiveClientRealtimeInput {\n /** Inlined bytes data for media input. */\n mediaChunks?: Blob[];\n /** The realtime audio input stream. */\n audio?: Blob;\n /** \nIndicates that the audio stream has ended, e.g. because the microphone was\nturned off.\n\nThis should only be sent when automatic activity detection is enabled\n(which is the default).\n\nThe client can reopen the stream by sending an audio message.\n */\n audioStreamEnd?: boolean;\n /** The realtime video input stream. */\n video?: Blob;\n /** The realtime text input stream. */\n text?: string;\n /** Marks the start of user activity. */\n activityStart?: ActivityStart;\n /** Marks the end of user activity. */\n activityEnd?: ActivityEnd;\n}\n\n/** Client generated response to a `ToolCall` received from the server.\n\nIndividual `FunctionResponse` objects are matched to the respective\n`FunctionCall` objects by the `id` field.\n\nNote that in the unary and server-streaming GenerateContent APIs function\ncalling happens by exchanging the `Content` parts, while in the bidi\nGenerateContent APIs function calling happens over this dedicated set of\nmessages. */\nexport class LiveClientToolResponse {\n /** The response to the function calls. */\n functionResponses?: FunctionResponse[];\n}\n\n/** Parameters for sending realtime input to the live API. */\nexport declare interface LiveSendRealtimeInputParameters {\n /** Realtime input to send to the session. */\n media?: BlobImageUnion;\n /** The realtime audio input stream. */\n audio?: Blob;\n /** \nIndicates that the audio stream has ended, e.g. because the microphone was\nturned off.\n\nThis should only be sent when automatic activity detection is enabled\n(which is the default).\n\nThe client can reopen the stream by sending an audio message.\n */\n audioStreamEnd?: boolean;\n /** The realtime video input stream. */\n video?: BlobImageUnion;\n /** The realtime text input stream. */\n text?: string;\n /** Marks the start of user activity. */\n activityStart?: ActivityStart;\n /** Marks the end of user activity. */\n activityEnd?: ActivityEnd;\n}\n\n/** Messages sent by the client in the API call. */\nexport declare interface LiveClientMessage {\n /** Message to be sent by the system when connecting to the API. SDK users should not send this message. */\n setup?: LiveClientSetup;\n /** Incremental update of the current conversation delivered from the client. */\n clientContent?: LiveClientContent;\n /** User input that is sent in real time. */\n realtimeInput?: LiveClientRealtimeInput;\n /** Response to a `ToolCallMessage` received from the server. */\n toolResponse?: LiveClientToolResponse;\n}\n\n/** Session config for the API connection. */\nexport declare interface LiveConnectConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** The generation configuration for the session. */\n generationConfig?: GenerationConfig;\n /** The requested modalities of the response. Represents the set of\n modalities that the model can return. Defaults to AUDIO if not specified.\n */\n responseModalities?: Modality[];\n /** Value that controls the degree of randomness in token selection.\n Lower temperatures are good for prompts that require a less open-ended or\n creative response, while higher temperatures can lead to more diverse or\n creative results.\n */\n temperature?: number;\n /** Tokens are selected from the most to least probable until the sum\n of their probabilities equals this value. Use a lower value for less\n random responses and a higher value for more random responses.\n */\n topP?: number;\n /** For each token selection step, the ``top_k`` tokens with the\n highest probabilities are sampled. Then tokens are further filtered based\n on ``top_p`` with the final token selected using temperature sampling. Use\n a lower number for less random responses and a higher number for more\n random responses.\n */\n topK?: number;\n /** Maximum number of tokens that can be generated in the response.\n */\n maxOutputTokens?: number;\n /** If specified, the media resolution specified will be used.\n */\n mediaResolution?: MediaResolution;\n /** When ``seed`` is fixed to a specific number, the model makes a best\n effort to provide the same response for repeated requests. By default, a\n random number is used.\n */\n seed?: number;\n /** The speech generation configuration.\n */\n speechConfig?: SpeechConfig;\n /** Config for thinking features.\n An error will be returned if this field is set for models that don't\n support thinking.\n */\n thinkingConfig?: ThinkingConfig;\n /** If enabled, the model will detect emotions and adapt its responses accordingly. */\n enableAffectiveDialog?: boolean;\n /** The user provided system instructions for the model.\n Note: only text should be used in parts and content in each part will be\n in a separate paragraph. */\n systemInstruction?: ContentUnion;\n /** A list of `Tools` the model may use to generate the next response.\n\n A `Tool` is a piece of code that enables the system to interact with\n external systems to perform an action, or set of actions, outside of\n knowledge and scope of the model. */\n tools?: ToolListUnion;\n /** Configures session resumption mechanism.\n\nIf included the server will send SessionResumptionUpdate messages. */\n sessionResumption?: SessionResumptionConfig;\n /** The transcription of the input aligns with the input audio language.\n */\n inputAudioTranscription?: AudioTranscriptionConfig;\n /** The transcription of the output aligns with the language code\n specified for the output audio.\n */\n outputAudioTranscription?: AudioTranscriptionConfig;\n /** Configures the realtime input behavior in BidiGenerateContent. */\n realtimeInputConfig?: RealtimeInputConfig;\n /** Configures context window compression mechanism.\n\n If included, server will compress context window to fit into given length. */\n contextWindowCompression?: ContextWindowCompressionConfig;\n /** Configures the proactivity of the model. This allows the model to respond proactively to\n the input and to ignore irrelevant input. */\n proactivity?: ProactivityConfig;\n /** Configures the explicit VAD signal. If enabled, the client will send\n vad_signal to indicate the start and end of speech. This allows the server\n to process the audio more efficiently. */\n explicitVadSignal?: boolean;\n}\n\n/** Parameters for connecting to the live API. */\nexport declare interface LiveConnectParameters {\n /** ID of the model to use. For a list of models, see `Google models\n <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */\n model: string;\n /** callbacks */\n callbacks: LiveCallbacks;\n /** Optional configuration parameters for the request.\n */\n config?: LiveConnectConfig;\n}\n\n/** Parameters for initializing a new chat session.\n\nThese parameters are used when creating a chat session with the\n`chats.create()` method. */\nexport declare interface CreateChatParameters {\n /** The name of the model to use for the chat session.\n\n For example: 'gemini-2.0-flash', 'gemini-2.0-flash-lite', etc. See Gemini API\n docs to find the available models.\n */\n model: string;\n /** Config for the entire chat session.\n\n This config applies to all requests within the session\n unless overridden by a per-request `config` in `SendMessageParameters`.\n */\n config?: GenerateContentConfig;\n /** The initial conversation history for the chat session.\n\n This allows you to start the chat with a pre-existing history. The history\n must be a list of `Content` alternating between 'user' and 'model' roles.\n It should start with a 'user' message.\n */\n history?: Content[];\n}\n\n/** Parameters for sending a message within a chat session.\n\nThese parameters are used with the `chat.sendMessage()` method. */\nexport declare interface SendMessageParameters {\n /** The message to send to the model.\n\n The SDK will combine all parts into a single 'user' content to send to\n the model.\n */\n message: PartListUnion;\n /** Config for this specific request.\n\n Please note that the per-request config does not change the chat level\n config, nor inherit from it. If you intend to use some values from the\n chat's default config, you must explicitly copy them into this per-request\n config.\n */\n config?: GenerateContentConfig;\n}\n\n/** Parameters for sending client content to the live API. */\nexport declare interface LiveSendClientContentParameters {\n /** Client content to send to the session. */\n turns?: ContentListUnion;\n /** If true, indicates that the server content generation should start with\n the currently accumulated prompt. Otherwise, the server will await\n additional messages before starting generation. */\n turnComplete?: boolean;\n}\n\n/** Parameters for sending tool responses to the live API. */\nexport class LiveSendToolResponseParameters {\n /** Tool responses to send to the session. */\n functionResponses: FunctionResponse[] | FunctionResponse = [];\n}\n\n/** Message to be sent by the system when connecting to the API. */\nexport declare interface LiveMusicClientSetup {\n /** The model's resource name. Format: `models/{model}`. */\n model?: string;\n}\n\n/** Maps a prompt to a relative weight to steer music generation. */\nexport declare interface WeightedPrompt {\n /** Text prompt. */\n text?: string;\n /** Weight of the prompt. The weight is used to control the relative\n importance of the prompt. Higher weights are more important than lower\n weights.\n\n Weight must not be 0. Weights of all weighted_prompts in this\n LiveMusicClientContent message will be normalized. */\n weight?: number;\n}\n\n/** User input to start or steer the music. */\nexport declare interface LiveMusicClientContent {\n /** Weighted prompts as the model input. */\n weightedPrompts?: WeightedPrompt[];\n}\n\n/** Configuration for music generation. */\nexport declare interface LiveMusicGenerationConfig {\n /** Controls the variance in audio generation. Higher values produce\n higher variance. Range is [0.0, 3.0]. */\n temperature?: number;\n /** Controls how the model selects tokens for output. Samples the topK\n tokens with the highest probabilities. Range is [1, 1000]. */\n topK?: number;\n /** Seeds audio generation. If not set, the request uses a randomly\n generated seed. */\n seed?: number;\n /** Controls how closely the model follows prompts.\n Higher guidance follows more closely, but will make transitions more\n abrupt. Range is [0.0, 6.0]. */\n guidance?: number;\n /** Beats per minute. Range is [60, 200]. */\n bpm?: number;\n /** Density of sounds. Range is [0.0, 1.0]. */\n density?: number;\n /** Brightness of the music. Range is [0.0, 1.0]. */\n brightness?: number;\n /** Scale of the generated music. */\n scale?: Scale;\n /** Whether the audio output should contain bass. */\n muteBass?: boolean;\n /** Whether the audio output should contain drums. */\n muteDrums?: boolean;\n /** Whether the audio output should contain only bass and drums. */\n onlyBassAndDrums?: boolean;\n /** The mode of music generation. Default mode is QUALITY. */\n musicGenerationMode?: MusicGenerationMode;\n}\n\n/** Messages sent by the client in the LiveMusicClientMessage call. */\nexport declare interface LiveMusicClientMessage {\n /** Message to be sent in the first (and only in the first) `LiveMusicClientMessage`.\n Clients should wait for a `LiveMusicSetupComplete` message before\n sending any additional messages. */\n setup?: LiveMusicClientSetup;\n /** User input to influence music generation. */\n clientContent?: LiveMusicClientContent;\n /** Configuration for music generation. */\n musicGenerationConfig?: LiveMusicGenerationConfig;\n /** Playback control signal for the music generation. */\n playbackControl?: LiveMusicPlaybackControl;\n}\n\n/** Sent in response to a `LiveMusicClientSetup` message from the client. */\nexport declare interface LiveMusicServerSetupComplete {}\n\n/** Prompts and config used for generating this audio chunk. */\nexport declare interface LiveMusicSourceMetadata {\n /** Weighted prompts for generating this audio chunk. */\n clientContent?: LiveMusicClientContent;\n /** Music generation config for generating this audio chunk. */\n musicGenerationConfig?: LiveMusicGenerationConfig;\n}\n\n/** Representation of an audio chunk. */\nexport declare interface AudioChunk {\n /** Raw bytes of audio data.\n * @remarks Encoded as base64 string. */\n data?: string;\n /** MIME type of the audio chunk. */\n mimeType?: string;\n /** Prompts and config used for generating this audio chunk. */\n sourceMetadata?: LiveMusicSourceMetadata;\n}\n\n/** Server update generated by the model in response to client messages.\n\nContent is generated as quickly as possible, and not in real time.\nClients may choose to buffer and play it out in real time. */\nexport declare interface LiveMusicServerContent {\n /** The audio chunks that the model has generated. */\n audioChunks?: AudioChunk[];\n}\n\n/** A prompt that was filtered with the reason. */\nexport declare interface LiveMusicFilteredPrompt {\n /** The text prompt that was filtered. */\n text?: string;\n /** The reason the prompt was filtered. */\n filteredReason?: string;\n}\n\n/** Response message for the LiveMusicClientMessage call. */\nexport class LiveMusicServerMessage {\n /** Message sent in response to a `LiveMusicClientSetup` message from the client.\n Clients should wait for this message before sending any additional messages. */\n setupComplete?: LiveMusicServerSetupComplete;\n /** Content generated by the model in response to client messages. */\n serverContent?: LiveMusicServerContent;\n /** A prompt that was filtered with the reason. */\n filteredPrompt?: LiveMusicFilteredPrompt;\n /**\n * Returns the first audio chunk from the server content, if present.\n *\n * @remarks\n * If there are no audio chunks in the response, undefined will be returned.\n */\n get audioChunk(): AudioChunk | undefined {\n if (\n this.serverContent &&\n this.serverContent.audioChunks &&\n this.serverContent.audioChunks.length > 0\n ) {\n return this.serverContent.audioChunks[0];\n }\n return undefined;\n }\n}\n\n/** Callbacks for the realtime music API. */\nexport interface LiveMusicCallbacks {\n /**\n * Called when a message is received from the server.\n */\n onmessage: (e: LiveMusicServerMessage) => void;\n /**\n * Called when an error occurs.\n */\n onerror?: ((e: ErrorEvent) => void) | null;\n /**\n * Called when the websocket connection is closed.\n */\n onclose?: ((e: CloseEvent) => void) | null;\n}\n\n/** Parameters for the upload file method. */\nexport interface UploadFileParameters {\n /** The string path to the file to be uploaded or a Blob object. */\n file: string | globalThis.Blob;\n /** Configuration that contains optional parameters. */\n config?: UploadFileConfig;\n}\n\n/** Parameters for the upload file to file search store method. */\nexport interface UploadToFileSearchStoreParameters {\n /** The name of the file search store to upload. */\n fileSearchStoreName: string;\n /** The string path to the file to be uploaded or a Blob object. */\n file: string | globalThis.Blob;\n /** Configuration that contains optional parameters. */\n config?: UploadToFileSearchStoreConfig;\n}\n\n/**\n * CallableTool is an invokable tool that can be executed with external\n * application (e.g., via Model Context Protocol) or local functions with\n * function calling.\n */\nexport interface CallableTool {\n /**\n * Returns tool that can be called by Gemini.\n */\n tool(): Promise<Tool>;\n /**\n * Executes the callable tool with the given function call arguments and\n * returns the response parts from the tool execution.\n */\n callTool(functionCalls: FunctionCall[]): Promise<Part[]>;\n}\n\n/**\n * CallableToolConfig is the configuration for a callable tool.\n */\nexport interface CallableToolConfig {\n /**\n * Specifies the model's behavior after invoking this tool.\n */\n behavior?: Behavior;\n /**\n * Timeout for remote calls in milliseconds. Note this timeout applies only to\n * tool remote calls, and not making HTTP requests to the API. */\n timeout?: number;\n}\n\n/** Parameters for connecting to the live API. */\nexport declare interface LiveMusicConnectParameters {\n /** The model's resource name. */\n model: string;\n /** Callbacks invoked on server events. */\n callbacks: LiveMusicCallbacks;\n}\n\n/** Parameters for setting config for the live music API. */\nexport declare interface LiveMusicSetConfigParameters {\n /** Configuration for music generation. */\n musicGenerationConfig: LiveMusicGenerationConfig;\n}\n\n/** Parameters for setting weighted prompts for the live music API. */\nexport declare interface LiveMusicSetWeightedPromptsParameters {\n /** A map of text prompts to weights to use for the generation request. */\n weightedPrompts: WeightedPrompt[];\n}\n\n/** Config for auth_tokens.create parameters. */\nexport declare interface AuthToken {\n /** The name of the auth token. */\n name?: string;\n}\n\n/** Config for LiveConnectConstraints for Auth Token creation. */\nexport declare interface LiveConnectConstraints {\n /** ID of the model to configure in the ephemeral token for Live API.\n For a list of models, see `Gemini models\n <https://ai.google.dev/gemini-api/docs/models>`. */\n model?: string;\n /** Configuration specific to Live API connections created using this token. */\n config?: LiveConnectConfig;\n}\n\n/** Optional parameters. */\nexport declare interface CreateAuthTokenConfig {\n /** Used to override HTTP request options. */\n httpOptions?: HttpOptions;\n /** Abort signal which can be used to cancel the request.\n\n NOTE: AbortSignal is a client-only operation. Using it to cancel an\n operation will not cancel the request in the service. You will still\n be charged usage for any applicable operations.\n */\n abortSignal?: AbortSignal;\n /** An optional time after which, when using the resulting token,\n messages in Live API sessions will be rejected. (Gemini may\n preemptively close the session after this time.)\n\n If not set then this defaults to 30 minutes in the future. If set, this\n value must be less than 20 hours in the future. */\n expireTime?: string;\n /** The time after which new Live API sessions using the token\n resulting from this request will be rejected.\n\n If not set this defaults to 60 seconds in the future. If set, this value\n must be less than 20 hours in the future. */\n newSessionExpireTime?: string;\n /** The number of times the token can be used. If this value is zero\n then no limit is applied. Default is 1. Resuming a Live API session does\n not count as a use. */\n uses?: number;\n /** Configuration specific to Live API connections created using this token. */\n liveConnectConstraints?: LiveConnectConstraints;\n /** Additional fields to lock in the effective LiveConnectParameters. */\n lockAdditionalFields?: string[];\n}\n\n/** Config for auth_tokens.create parameters. */\nexport declare interface CreateAuthTokenParameters {\n /** Optional parameters for the request. */\n config?: CreateAuthTokenConfig;\n}\n\n/** Parameters for the get method of the operations module. */\nexport declare interface OperationGetParameters<T, U extends Operation<T>> {\n /** Used to override the default configuration. */\n config?: GetOperationConfig;\n /** The operation to be retrieved. */\n operation: U;\n}\n\n/** Local tokenizer count tokens result. */\nexport declare interface CountTokensResult {\n /** The total number of tokens. */\n totalTokens?: number;\n}\n\n/** Local tokenizer compute tokens result. */\nexport declare interface ComputeTokensResult {\n /** Lists of tokens info from the input. */\n tokensInfo?: TokensInfo[];\n}\n\n/** Fine-tuning job creation parameters - optional fields. */\nexport declare interface CreateTuningJobParameters {\n /** The base model that is being tuned, e.g., \"gemini-2.5-flash\". */\n baseModel: string;\n /** Cloud Storage path to file containing training dataset for tuning. The dataset must be formatted as a JSONL file. */\n trainingDataset: TuningDataset;\n /** Configuration for the tuning job. */\n config?: CreateTuningJobConfig;\n}\n\n/** The response when long-running operation for uploading a file to a FileSearchStore complete. */\nexport class UploadToFileSearchStoreResponse {\n /** Used to retain the full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n /** The name of the FileSearchStore containing Documents. */\n parent?: string;\n /** The identifier for the Document imported. */\n documentName?: string;\n}\n\n/** Long-running operation for uploading a file to a FileSearchStore. */\nexport class UploadToFileSearchStoreOperation\n implements Operation<UploadToFileSearchStoreResponse>\n{\n /** The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`. */\n name?: string;\n /** Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata. Any method that returns a long-running operation should document the metadata type, if any. */\n metadata?: Record<string, unknown>;\n /** If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available. */\n done?: boolean;\n /** The error result of the operation in case of failure or cancellation. */\n error?: Record<string, unknown>;\n /** The result of the UploadToFileSearchStore operation, available when the operation is done. */\n response?: UploadToFileSearchStoreResponse;\n\n /**\n * Instantiates an Operation of the same type as the one being called with the fields set from the API response.\n * @internal\n */\n _fromAPIResponse({\n apiResponse,\n _isVertexAI,\n }: OperationFromAPIResponseParameters): Operation<UploadToFileSearchStoreResponse> {\n const operation = new UploadToFileSearchStoreOperation();\n\n const op = apiResponse as unknown as UploadToFileSearchStoreOperation;\n const response = uploadToFileSearchStoreOperationFromMldev(op);\n Object.assign(operation, response);\n return operation;\n }\n /** The full HTTP response. */\n sdkHttpResponse?: HttpResponse;\n}\n\nexport type BlobImageUnion = Blob;\n\nexport type PartUnion = Part | string;\n\nexport type PartListUnion = PartUnion[] | PartUnion;\n\nexport type ContentUnion = Content | PartUnion[] | PartUnion;\n\nexport type ContentListUnion = Content | Content[] | PartUnion | PartUnion[];\n\nexport type SchemaUnion = Schema | unknown;\n\nexport type SpeechConfigUnion = SpeechConfig | string;\n\nexport type ToolUnion = Tool | CallableTool;\n\nexport type ToolListUnion = ToolUnion[];\n\nexport type DownloadableFileUnion = string | File | GeneratedVideo | Video;\n\nexport type BatchJobSourceUnion = BatchJobSource | InlinedRequest[] | string;\n\nexport type BatchJobDestinationUnion = BatchJobDestination | string;\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type {Tool as McpTool} from '@modelcontextprotocol/sdk/types';\n\nimport {ApiClient} from './_api_client.js';\nimport * as baseTransformers from './_base_transformers.js';\nimport * as types from './types.js';\n\nexport function tModel(apiClient: ApiClient, model: string | unknown): string {\n if (!model || typeof model !== 'string') {\n throw new Error('model is required and must be a string');\n }\n if (model.includes('..') || model.includes('?') || model.includes('&')) {\n throw new Error('invalid model parameter');\n }\n\n if (apiClient.isVertexAI()) {\n if (\n model.startsWith('publishers/') ||\n model.startsWith('projects/') ||\n model.startsWith('models/')\n ) {\n return model;\n } else if (model.indexOf('/') >= 0) {\n const parts = model.split('/', 2);\n return `publishers/${parts[0]}/models/${parts[1]}`;\n } else {\n return `publishers/google/models/${model}`;\n }\n } else {\n if (model.startsWith('models/') || model.startsWith('tunedModels/')) {\n return model;\n } else {\n return `models/${model}`;\n }\n }\n}\n\nexport function tCachesModel(\n apiClient: ApiClient,\n model: string | unknown,\n): string {\n const transformedModel = tModel(apiClient, model as string);\n if (!transformedModel) {\n return '';\n }\n\n if (transformedModel.startsWith('publishers/') && apiClient.isVertexAI()) {\n // vertex caches only support model name start with projects.\n return `projects/${apiClient.getProject()}/locations/${apiClient.getLocation()}/${transformedModel}`;\n } else if (transformedModel.startsWith('models/') && apiClient.isVertexAI()) {\n return `projects/${apiClient.getProject()}/locations/${apiClient.getLocation()}/publishers/google/${transformedModel}`;\n } else {\n return transformedModel;\n }\n}\n\nexport function tBlobs(\n blobs: types.BlobImageUnion | types.BlobImageUnion[],\n): types.Blob[] {\n if (Array.isArray(blobs)) {\n return blobs.map((blob) => tBlob(blob));\n } else {\n return [tBlob(blobs)];\n }\n}\n\nexport function tBlob(blob: types.BlobImageUnion): types.Blob {\n if (typeof blob === 'object' && blob !== null) {\n return blob;\n }\n\n throw new Error(\n `Could not parse input as Blob. Unsupported blob type: ${typeof blob}`,\n );\n}\n\nexport function tImageBlob(blob: types.BlobImageUnion): types.Blob {\n const transformedBlob = tBlob(blob);\n if (\n transformedBlob.mimeType &&\n transformedBlob.mimeType.startsWith('image/')\n ) {\n return transformedBlob;\n }\n throw new Error(`Unsupported mime type: ${transformedBlob.mimeType!}`);\n}\n\nexport function tAudioBlob(blob: types.Blob): types.Blob {\n const transformedBlob = tBlob(blob);\n if (\n transformedBlob.mimeType &&\n transformedBlob.mimeType.startsWith('audio/')\n ) {\n return transformedBlob;\n }\n throw new Error(`Unsupported mime type: ${transformedBlob.mimeType!}`);\n}\n\nexport function tPart(origin?: types.PartUnion | null): types.Part {\n if (origin === null || origin === undefined) {\n throw new Error('PartUnion is required');\n }\n if (typeof origin === 'object') {\n return origin;\n }\n if (typeof origin === 'string') {\n return {text: origin};\n }\n throw new Error(`Unsupported part type: ${typeof origin}`);\n}\n\nexport function tParts(origin?: types.PartListUnion | null): types.Part[] {\n if (\n origin === null ||\n origin === undefined ||\n (Array.isArray(origin) && origin.length === 0)\n ) {\n throw new Error('PartListUnion is required');\n }\n if (Array.isArray(origin)) {\n return origin.map((item) => tPart(item as types.PartUnion)!);\n }\n return [tPart(origin)!];\n}\n\nfunction _isContent(origin: unknown): boolean {\n return (\n origin !== null &&\n origin !== undefined &&\n typeof origin === 'object' &&\n 'parts' in origin &&\n Array.isArray(origin.parts)\n );\n}\n\nfunction _isFunctionCallPart(origin: unknown): boolean {\n return (\n origin !== null &&\n origin !== undefined &&\n typeof origin === 'object' &&\n 'functionCall' in origin\n );\n}\n\nfunction _isFunctionResponsePart(origin: unknown): boolean {\n return (\n origin !== null &&\n origin !== undefined &&\n typeof origin === 'object' &&\n 'functionResponse' in origin\n );\n}\n\nexport function tContent(origin?: types.ContentUnion): types.Content {\n if (origin === null || origin === undefined) {\n throw new Error('ContentUnion is required');\n }\n if (_isContent(origin)) {\n // _isContent is a utility function that checks if the\n // origin is a Content.\n return origin as types.Content;\n }\n\n return {\n role: 'user',\n parts: tParts(origin as types.PartListUnion)!,\n };\n}\n\nexport function tContentsForEmbed(\n apiClient: ApiClient,\n origin: types.ContentListUnion,\n): types.ContentUnion[] {\n if (!origin) {\n return [];\n }\n if (apiClient.isVertexAI() && Array.isArray(origin)) {\n return origin.flatMap((item) => {\n const content = tContent(item as types.ContentUnion);\n if (\n content.parts &&\n content.parts.length > 0 &&\n content.parts[0].text !== undefined\n ) {\n return [content.parts[0].text];\n }\n return [];\n });\n } else if (apiClient.isVertexAI()) {\n const content = tContent(origin as types.ContentUnion);\n if (\n content.parts &&\n content.parts.length > 0 &&\n content.parts[0].text !== undefined\n ) {\n return [content.parts[0].text];\n }\n return [];\n }\n if (Array.isArray(origin)) {\n return origin.map((item) => tContent(item as types.ContentUnion)!);\n }\n return [tContent(origin as types.ContentUnion)!];\n}\n\nexport function tContents(origin?: types.ContentListUnion): types.Content[] {\n if (\n origin === null ||\n origin === undefined ||\n (Array.isArray(origin) && origin.length === 0)\n ) {\n throw new Error('contents are required');\n }\n if (!Array.isArray(origin)) {\n // If it's not an array, it's a single content or a single PartUnion.\n if (_isFunctionCallPart(origin) || _isFunctionResponsePart(origin)) {\n throw new Error(\n 'To specify functionCall or functionResponse parts, please wrap them in a Content object, specifying the role for them',\n );\n }\n return [tContent(origin as types.ContentUnion)];\n }\n\n const result: types.Content[] = [];\n const accumulatedParts: types.PartUnion[] = [];\n const isContentArray = _isContent(origin[0]);\n\n for (const item of origin) {\n const isContent = _isContent(item);\n\n if (isContent != isContentArray) {\n throw new Error(\n 'Mixing Content and Parts is not supported, please group the parts into a the appropriate Content objects and specify the roles for them',\n );\n }\n\n if (isContent) {\n // `isContent` contains the result of _isContent, which is a utility\n // function that checks if the item is a Content.\n result.push(item as types.Content);\n } else if (_isFunctionCallPart(item) || _isFunctionResponsePart(item)) {\n throw new Error(\n 'To specify functionCall or functionResponse parts, please wrap them, and any other parts, in Content objects as appropriate, specifying the role for them',\n );\n } else {\n accumulatedParts.push(item as types.PartUnion);\n }\n }\n\n if (!isContentArray) {\n result.push({role: 'user', parts: tParts(accumulatedParts)});\n }\n return result;\n}\n\n/*\nTransform the type field from an array of types to an array of anyOf fields.\nExample:\n {type: ['STRING', 'NUMBER']}\nwill be transformed to\n {anyOf: [{type: 'STRING'}, {type: 'NUMBER'}]}\n*/\nfunction flattenTypeArrayToAnyOf(\n typeList: string[],\n resultingSchema: types.Schema,\n) {\n if (typeList.includes('null')) {\n resultingSchema['nullable'] = true;\n }\n const listWithoutNull = typeList.filter((type) => type !== 'null');\n\n if (listWithoutNull.length === 1) {\n resultingSchema['type'] = Object.values(types.Type).includes(\n listWithoutNull[0].toUpperCase() as types.Type,\n )\n ? (listWithoutNull[0].toUpperCase() as types.Type)\n : types.Type.TYPE_UNSPECIFIED;\n } else {\n resultingSchema['anyOf'] = [];\n for (const i of listWithoutNull) {\n resultingSchema['anyOf'].push({\n 'type': Object.values(types.Type).includes(\n i.toUpperCase() as types.Type,\n )\n ? (i.toUpperCase() as types.Type)\n : types.Type.TYPE_UNSPECIFIED,\n });\n }\n }\n}\n\nexport function processJsonSchema(\n _jsonSchema: types.Schema | Record<string, unknown>,\n): types.Schema {\n const genAISchema: types.Schema = {};\n const schemaFieldNames = ['items'];\n const listSchemaFieldNames = ['anyOf'];\n const dictSchemaFieldNames = ['properties'];\n\n if (_jsonSchema['type'] && _jsonSchema['anyOf']) {\n throw new Error('type and anyOf cannot be both populated.');\n }\n\n /*\n This is to handle the nullable array or object. The _jsonSchema will\n be in the format of {anyOf: [{type: 'null'}, {type: 'object'}]}. The\n logic is to check if anyOf has 2 elements and one of the element is null,\n if so, the anyOf field is unnecessary, so we need to get rid of the anyOf\n field and make the schema nullable. Then use the other element as the new\n _jsonSchema for processing. This is because the backend doesn't have a null\n type.\n This has to be checked before we process any other fields.\n For example:\n const objectNullable = z.object({\n nullableArray: z.array(z.string()).nullable(),\n });\n Will have the raw _jsonSchema as:\n {\n type: 'OBJECT',\n properties: {\n nullableArray: {\n anyOf: [\n {type: 'null'},\n {\n type: 'array',\n items: {type: 'string'},\n },\n ],\n }\n },\n required: [ 'nullableArray' ],\n }\n Will result in following schema compatible with Gemini API:\n {\n type: 'OBJECT',\n properties: {\n nullableArray: {\n nullable: true,\n type: 'ARRAY',\n items: {type: 'string'},\n }\n },\n required: [ 'nullableArray' ],\n }\n */\n const incomingAnyOf = _jsonSchema['anyOf'] as Record<string, unknown>[];\n if (incomingAnyOf != null && incomingAnyOf.length == 2) {\n if (incomingAnyOf[0]!['type'] === 'null') {\n genAISchema['nullable'] = true;\n _jsonSchema = incomingAnyOf![1];\n } else if (incomingAnyOf[1]!['type'] === 'null') {\n genAISchema['nullable'] = true;\n _jsonSchema = incomingAnyOf![0];\n }\n }\n\n if (_jsonSchema['type'] instanceof Array) {\n flattenTypeArrayToAnyOf(_jsonSchema['type'], genAISchema);\n }\n\n for (const [fieldName, fieldValue] of Object.entries(_jsonSchema)) {\n // Skip if the fieldvalue is undefined or null.\n if (fieldValue == null) {\n continue;\n }\n\n if (fieldName == 'type') {\n if (fieldValue === 'null') {\n throw new Error(\n 'type: null can not be the only possible type for the field.',\n );\n }\n if (fieldValue instanceof Array) {\n // we have already handled the type field with array of types in the\n // beginning of this function.\n continue;\n }\n genAISchema['type'] = Object.values(types.Type).includes(\n fieldValue.toUpperCase() as types.Type,\n )\n ? fieldValue.toUpperCase()\n : types.Type.TYPE_UNSPECIFIED;\n } else if (schemaFieldNames.includes(fieldName)) {\n (genAISchema as Record<string, unknown>)[fieldName] =\n processJsonSchema(fieldValue);\n } else if (listSchemaFieldNames.includes(fieldName)) {\n const listSchemaFieldValue: Array<types.Schema> = [];\n for (const item of fieldValue) {\n if (item['type'] == 'null') {\n genAISchema['nullable'] = true;\n continue;\n }\n listSchemaFieldValue.push(\n processJsonSchema(item as Record<string, unknown>),\n );\n }\n (genAISchema as Record<string, unknown>)[fieldName] =\n listSchemaFieldValue;\n } else if (dictSchemaFieldNames.includes(fieldName)) {\n const dictSchemaFieldValue: Record<string, types.Schema> = {};\n for (const [key, value] of Object.entries(\n fieldValue as Record<string, unknown>,\n )) {\n dictSchemaFieldValue[key] = processJsonSchema(\n value as Record<string, unknown>,\n );\n }\n (genAISchema as Record<string, unknown>)[fieldName] =\n dictSchemaFieldValue;\n } else {\n // additionalProperties is not included in JSONSchema, skipping it.\n if (fieldName === 'additionalProperties') {\n continue;\n }\n (genAISchema as Record<string, unknown>)[fieldName] = fieldValue;\n }\n }\n return genAISchema;\n}\n\n// we take the unknown in the schema field because we want enable user to pass\n// the output of major schema declaration tools without casting. Tools such as\n// zodToJsonSchema, typebox, zodToJsonSchema function can return JsonSchema7Type\n// or object, see details in\n// https://github.com/StefanTerdell/zod-to-json-schema/blob/70525efe555cd226691e093d171370a3b10921d1/src/zodToJsonSchema.ts#L7\n// typebox can return unknown, see details in\n// https://github.com/sinclairzx81/typebox/blob/5a5431439f7d5ca6b494d0d18fbfd7b1a356d67c/src/type/create/type.ts#L35\n// Note: proper json schemas with the $schema field set never arrive to this\n// transformer. Schemas with $schema are routed to the equivalent API json\n// schema field.\nexport function tSchema(schema: types.Schema | unknown): types.Schema {\n return processJsonSchema(schema as types.Schema);\n}\n\nexport function tSpeechConfig(\n speechConfig: types.SpeechConfigUnion,\n): types.SpeechConfig {\n if (typeof speechConfig === 'object') {\n return speechConfig;\n } else if (typeof speechConfig === 'string') {\n return {\n voiceConfig: {\n prebuiltVoiceConfig: {\n voiceName: speechConfig,\n },\n },\n };\n } else {\n throw new Error(`Unsupported speechConfig type: ${typeof speechConfig}`);\n }\n}\n\nexport function tLiveSpeechConfig(\n speechConfig: types.SpeechConfig | object,\n): types.SpeechConfig {\n if ('multiSpeakerVoiceConfig' in speechConfig) {\n throw new Error(\n 'multiSpeakerVoiceConfig is not supported in the live API.',\n );\n }\n return speechConfig;\n}\n\nexport function tTool(tool: types.Tool): types.Tool {\n if (tool.functionDeclarations) {\n for (const functionDeclaration of tool.functionDeclarations) {\n if (functionDeclaration.parameters) {\n if (!Object.keys(functionDeclaration.parameters).includes('$schema')) {\n functionDeclaration.parameters = processJsonSchema(\n functionDeclaration.parameters,\n );\n } else {\n if (!functionDeclaration.parametersJsonSchema) {\n functionDeclaration.parametersJsonSchema =\n functionDeclaration.parameters;\n delete functionDeclaration.parameters;\n }\n }\n }\n if (functionDeclaration.response) {\n if (!Object.keys(functionDeclaration.response).includes('$schema')) {\n functionDeclaration.response = processJsonSchema(\n functionDeclaration.response,\n );\n } else {\n if (!functionDeclaration.responseJsonSchema) {\n functionDeclaration.responseJsonSchema =\n functionDeclaration.response;\n delete functionDeclaration.response;\n }\n }\n }\n }\n }\n return tool;\n}\n\nexport function tTools(tools: types.ToolListUnion | unknown): types.Tool[] {\n // Check if the incoming type is defined.\n if (tools === undefined || tools === null) {\n throw new Error('tools is required');\n }\n if (!Array.isArray(tools)) {\n throw new Error('tools is required and must be an array of Tools');\n }\n const result: types.Tool[] = [];\n for (const tool of tools) {\n result.push(tool as types.Tool);\n }\n return result;\n}\n\n/**\n * Prepends resource name with project, location, resource_prefix if needed.\n *\n * @param client The API client.\n * @param resourceName The resource name.\n * @param resourcePrefix The resource prefix.\n * @param splitsAfterPrefix The number of splits after the prefix.\n * @returns The completed resource name.\n *\n * Examples:\n *\n * ```\n * resource_name = '123'\n * resource_prefix = 'cachedContents'\n * splits_after_prefix = 1\n * client.vertexai = True\n * client.project = 'bar'\n * client.location = 'us-west1'\n * _resource_name(client, resource_name, resource_prefix, splits_after_prefix)\n * returns: 'projects/bar/locations/us-west1/cachedContents/123'\n * ```\n *\n * ```\n * resource_name = 'projects/foo/locations/us-central1/cachedContents/123'\n * resource_prefix = 'cachedContents'\n * splits_after_prefix = 1\n * client.vertexai = True\n * client.project = 'bar'\n * client.location = 'us-west1'\n * _resource_name(client, resource_name, resource_prefix, splits_after_prefix)\n * returns: 'projects/foo/locations/us-central1/cachedContents/123'\n * ```\n *\n * ```\n * resource_name = '123'\n * resource_prefix = 'cachedContents'\n * splits_after_prefix = 1\n * client.vertexai = False\n * _resource_name(client, resource_name, resource_prefix, splits_after_prefix)\n * returns 'cachedContents/123'\n * ```\n *\n * ```\n * resource_name = 'some/wrong/cachedContents/resource/name/123'\n * resource_prefix = 'cachedContents'\n * splits_after_prefix = 1\n * client.vertexai = False\n * # client.vertexai = True\n * _resource_name(client, resource_name, resource_prefix, splits_after_prefix)\n * -> 'some/wrong/resource/name/123'\n * ```\n */\nfunction resourceName(\n client: ApiClient,\n resourceName: string,\n resourcePrefix: string,\n splitsAfterPrefix: number = 1,\n): string {\n const shouldAppendPrefix =\n !resourceName.startsWith(`${resourcePrefix}/`) &&\n resourceName.split('/').length === splitsAfterPrefix;\n if (client.isVertexAI()) {\n if (resourceName.startsWith('projects/')) {\n return resourceName;\n } else if (resourceName.startsWith('locations/')) {\n return `projects/${client.getProject()}/${resourceName}`;\n } else if (resourceName.startsWith(`${resourcePrefix}/`)) {\n return `projects/${client.getProject()}/locations/${client.getLocation()}/${resourceName}`;\n } else if (shouldAppendPrefix) {\n return `projects/${client.getProject()}/locations/${client.getLocation()}/${resourcePrefix}/${resourceName}`;\n } else {\n return resourceName;\n }\n }\n if (shouldAppendPrefix) {\n return `${resourcePrefix}/${resourceName}`;\n }\n return resourceName;\n}\n\nexport function tCachedContentName(\n apiClient: ApiClient,\n name: string | unknown,\n): string {\n if (typeof name !== 'string') {\n throw new Error('name must be a string');\n }\n return resourceName(apiClient, name, 'cachedContents');\n}\n\nexport function tTuningJobStatus(status: string | unknown): string {\n switch (status) {\n case 'STATE_UNSPECIFIED':\n return 'JOB_STATE_UNSPECIFIED';\n case 'CREATING':\n return 'JOB_STATE_RUNNING';\n case 'ACTIVE':\n return 'JOB_STATE_SUCCEEDED';\n case 'FAILED':\n return 'JOB_STATE_FAILED';\n default:\n return status as string;\n }\n}\n\nexport function tBytes(fromImageBytes: string | unknown): string {\n return baseTransformers.tBytes(fromImageBytes);\n}\n\nfunction _isFile(origin: unknown): boolean {\n return (\n origin !== null &&\n origin !== undefined &&\n typeof origin === 'object' &&\n 'name' in origin\n );\n}\n\nexport function isGeneratedVideo(origin: unknown): boolean {\n return (\n origin !== null &&\n origin !== undefined &&\n typeof origin === 'object' &&\n 'video' in origin\n );\n}\n\nexport function isVideo(origin: unknown): boolean {\n return (\n origin !== null &&\n origin !== undefined &&\n typeof origin === 'object' &&\n 'uri' in origin\n );\n}\n\nexport function tFileName(\n fromName: string | types.File | types.GeneratedVideo | types.Video,\n): string | undefined {\n let name: string | undefined;\n\n if (_isFile(fromName)) {\n name = (fromName as types.File).name;\n }\n if (isVideo(fromName)) {\n name = (fromName as types.Video).uri;\n if (name === undefined) {\n return undefined;\n }\n }\n if (isGeneratedVideo(fromName)) {\n name = (fromName as types.GeneratedVideo).video?.uri;\n if (name === undefined) {\n return undefined;\n }\n }\n if (typeof fromName === 'string') {\n name = fromName;\n }\n\n if (name === undefined) {\n throw new Error('Could not extract file name from the provided input.');\n }\n\n if (name.startsWith('https://')) {\n const suffix = name.split('files/')[1];\n const match = suffix.match(/[a-z0-9]+/);\n if (match === null) {\n throw new Error(`Could not extract file name from URI ${name}`);\n }\n name = match[0];\n } else if (name.startsWith('files/')) {\n name = name.split('files/')[1];\n }\n return name;\n}\n\nexport function tModelsUrl(\n apiClient: ApiClient,\n baseModels: boolean | unknown,\n): string {\n let res: string;\n if (apiClient.isVertexAI()) {\n res = baseModels ? 'publishers/google/models' : 'models';\n } else {\n res = baseModels ? 'models' : 'tunedModels';\n }\n return res;\n}\n\nexport function tExtractModels(response: unknown): Record<string, unknown>[] {\n for (const key of ['models', 'tunedModels', 'publisherModels']) {\n if (hasField(response, key)) {\n return (response as Record<string, unknown>)[key] as Record<\n string,\n unknown\n >[];\n }\n }\n return [];\n}\n\nfunction hasField(data: unknown, fieldName: string): boolean {\n return data !== null && typeof data === 'object' && fieldName in data;\n}\n\nexport function mcpToGeminiTool(\n mcpTool: McpTool,\n config: types.CallableToolConfig = {},\n): types.Tool {\n const mcpToolSchema = mcpTool as Record<string, unknown>;\n const functionDeclaration: Record<string, unknown> = {\n name: mcpToolSchema['name'],\n description: mcpToolSchema['description'],\n parametersJsonSchema: mcpToolSchema['inputSchema'],\n };\n if (mcpToolSchema['outputSchema']) {\n functionDeclaration['responseJsonSchema'] = mcpToolSchema['outputSchema'];\n }\n if (config.behavior) {\n functionDeclaration['behavior'] = config.behavior;\n }\n\n const geminiTool = {\n functionDeclarations: [\n functionDeclaration as unknown as types.FunctionDeclaration,\n ],\n };\n\n return geminiTool;\n}\n\n/**\n * Converts a list of MCP tools to a single Gemini tool with a list of function\n * declarations.\n */\nexport function mcpToolsToGeminiTool(\n mcpTools: McpTool[],\n config: types.CallableToolConfig = {},\n): types.Tool {\n const functionDeclarations: types.FunctionDeclaration[] = [];\n const toolNames = new Set<string>();\n for (const mcpTool of mcpTools) {\n const mcpToolName = mcpTool.name as string;\n if (toolNames.has(mcpToolName)) {\n throw new Error(\n `Duplicate function name ${\n mcpToolName\n } found in MCP tools. Please ensure function names are unique.`,\n );\n }\n toolNames.add(mcpToolName);\n const geminiTool = mcpToGeminiTool(mcpTool, config);\n if (geminiTool.functionDeclarations) {\n functionDeclarations.push(...geminiTool.functionDeclarations);\n }\n }\n\n return {functionDeclarations: functionDeclarations};\n}\n\n// Transforms a source input into a BatchJobSource object with validation.\nexport function tBatchJobSource(\n client: ApiClient,\n src: string | types.InlinedRequest[] | types.BatchJobSource,\n): types.BatchJobSource {\n let sourceObj: types.BatchJobSource;\n\n if (typeof src === 'string') {\n if (client.isVertexAI()) {\n if (src.startsWith('gs://')) {\n sourceObj = {format: 'jsonl', gcsUri: [src]};\n } else if (src.startsWith('bq://')) {\n sourceObj = {format: 'bigquery', bigqueryUri: src};\n } else {\n throw new Error(`Unsupported string source for Vertex AI: ${src}`);\n }\n } else {\n // MLDEV\n if (src.startsWith('files/')) {\n sourceObj = {fileName: src}; // Default to fileName for string input\n } else {\n throw new Error(`Unsupported string source for Gemini API: ${src}`);\n }\n }\n } else if (Array.isArray(src)) {\n if (client.isVertexAI()) {\n throw new Error('InlinedRequest[] is not supported in Vertex AI.');\n }\n sourceObj = {inlinedRequests: src};\n } else {\n // It's already a BatchJobSource object\n sourceObj = src;\n }\n\n // Validation logic\n const vertexSourcesCount = [sourceObj.gcsUri, sourceObj.bigqueryUri].filter(\n Boolean,\n ).length;\n\n const mldevSourcesCount = [\n sourceObj.inlinedRequests,\n sourceObj.fileName,\n ].filter(Boolean).length;\n\n if (client.isVertexAI()) {\n if (mldevSourcesCount > 0 || vertexSourcesCount !== 1) {\n throw new Error(\n 'Exactly one of `gcsUri` or `bigqueryUri` must be set for Vertex AI.',\n );\n }\n } else {\n // MLDEV\n if (vertexSourcesCount > 0 || mldevSourcesCount !== 1) {\n throw new Error(\n 'Exactly one of `inlinedRequests`, `fileName`, ' +\n 'must be set for Gemini API.',\n );\n }\n }\n\n return sourceObj;\n}\n\nexport function tEmbeddingBatchJobSource(\n client: ApiClient,\n src: types.EmbeddingsBatchJobSource,\n): types.EmbeddingsBatchJobSource {\n if (client.isVertexAI()) {\n throw new Error('Embedding batch jobs are not supported in Vertex AI.');\n }\n\n const sourceObj: types.EmbeddingsBatchJobSource = {...src};\n\n const mldevSources =\n Number(!!sourceObj.inlinedRequests) + Number(!!sourceObj.fileName);\n\n if (mldevSources !== 1) {\n throw new Error(\n 'Exactly one of `inlinedRequests` or `fileName` must be set for Embedding Batch Jobs in the Gemini API.',\n );\n }\n return sourceObj;\n}\n\nexport function tBatchJobDestination(\n dest: string | types.BatchJobDestination,\n): types.BatchJobDestination {\n if (typeof dest !== 'string') {\n return dest as types.BatchJobDestination;\n }\n const destString = dest as string;\n if (destString.startsWith('gs://')) {\n return {\n format: 'jsonl',\n gcsUri: destString,\n };\n } else if (destString.startsWith('bq://')) {\n return {\n format: 'bigquery',\n bigqueryUri: destString,\n };\n } else {\n throw new Error(`Unsupported destination: ${destString}`);\n }\n}\n\nexport function tRecvBatchJobDestination(\n dest: unknown,\n): types.BatchJobDestination {\n // Ensure dest is a non-null object before proceeding.\n if (typeof dest !== 'object' || dest === null) {\n // If the input is not an object, it cannot be a valid BatchJobDestination\n // based on the operations performed. Return it cast, or handle as an error.\n // Casting an empty object might be a safe default.\n return {} as types.BatchJobDestination;\n }\n\n // Cast to Record<string, unknown> to allow string property access.\n const obj = dest as Record<string, unknown>;\n\n // Safely access nested properties.\n const inlineResponsesVal = obj['inlinedResponses'];\n if (typeof inlineResponsesVal !== 'object' || inlineResponsesVal === null) {\n return dest as types.BatchJobDestination;\n }\n const inlineResponsesObj = inlineResponsesVal as Record<string, unknown>;\n\n const responsesArray = inlineResponsesObj['inlinedResponses'];\n if (!Array.isArray(responsesArray) || responsesArray.length === 0) {\n return dest as types.BatchJobDestination;\n }\n\n // Check if any response has the 'embedding' property.\n let hasEmbedding = false;\n for (const responseItem of responsesArray) {\n if (typeof responseItem !== 'object' || responseItem === null) {\n continue;\n }\n const responseItemObj = responseItem as Record<string, unknown>;\n\n const responseVal = responseItemObj['response'];\n if (typeof responseVal !== 'object' || responseVal === null) {\n continue;\n }\n const responseObj = responseVal as Record<string, unknown>;\n\n // Check for the existence of the 'embedding' key.\n if (responseObj['embedding'] !== undefined) {\n hasEmbedding = true;\n break;\n }\n }\n\n // Perform the transformation if an embedding was found.\n if (hasEmbedding) {\n obj['inlinedEmbedContentResponses'] = obj['inlinedResponses'];\n delete obj['inlinedResponses'];\n }\n\n // Cast the (potentially) modified object to the target type.\n return dest as types.BatchJobDestination;\n}\n\nexport function tBatchJobName(apiClient: ApiClient, name: unknown): string {\n const nameString = name as string;\n if (!apiClient.isVertexAI()) {\n const mldevPattern = /batches\\/[^/]+$/;\n\n if (mldevPattern.test(nameString)) {\n return nameString.split('/').pop() as string;\n } else {\n throw new Error(`Invalid batch job name: ${nameString}.`);\n }\n }\n\n const vertexPattern =\n /^projects\\/[^/]+\\/locations\\/[^/]+\\/batchPredictionJobs\\/[^/]+$/;\n\n if (vertexPattern.test(nameString)) {\n return nameString.split('/').pop() as string;\n } else if (/^\\d+$/.test(nameString)) {\n return nameString;\n } else {\n throw new Error(`Invalid batch job name: ${nameString}.`);\n }\n}\n\nexport function tJobState(state: unknown): string {\n const stateString = state as string;\n if (stateString === 'BATCH_STATE_UNSPECIFIED') {\n return 'JOB_STATE_UNSPECIFIED';\n } else if (stateString === 'BATCH_STATE_PENDING') {\n return 'JOB_STATE_PENDING';\n } else if (stateString === 'BATCH_STATE_RUNNING') {\n return 'JOB_STATE_RUNNING';\n } else if (stateString === 'BATCH_STATE_SUCCEEDED') {\n return 'JOB_STATE_SUCCEEDED';\n } else if (stateString === 'BATCH_STATE_FAILED') {\n return 'JOB_STATE_FAILED';\n } else if (stateString === 'BATCH_STATE_CANCELLED') {\n return 'JOB_STATE_CANCELLED';\n } else if (stateString === 'BATCH_STATE_EXPIRED') {\n return 'JOB_STATE_EXPIRED';\n } else {\n return stateString;\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport {ApiClient} from '../_api_client.js';\nimport * as common from '../_common.js';\nimport * as t from '../_transformers.js';\nimport type * as types from '../types.js';\n\nexport function batchJobDestinationFromMldev(\n fromObject: types.BatchJobDestination,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromFileName = common.getValueByPath(fromObject, ['responsesFile']);\n if (fromFileName != null) {\n common.setValueByPath(toObject, ['fileName'], fromFileName);\n }\n\n const fromInlinedResponses = common.getValueByPath(fromObject, [\n 'inlinedResponses',\n 'inlinedResponses',\n ]);\n if (fromInlinedResponses != null) {\n let transformedList = fromInlinedResponses;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return inlinedResponseFromMldev(item);\n });\n }\n common.setValueByPath(toObject, ['inlinedResponses'], transformedList);\n }\n\n const fromInlinedEmbedContentResponses = common.getValueByPath(fromObject, [\n 'inlinedEmbedContentResponses',\n 'inlinedResponses',\n ]);\n if (fromInlinedEmbedContentResponses != null) {\n let transformedList = fromInlinedEmbedContentResponses;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(\n toObject,\n ['inlinedEmbedContentResponses'],\n transformedList,\n );\n }\n\n return toObject;\n}\n\nexport function batchJobDestinationFromVertex(\n fromObject: types.BatchJobDestination,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromFormat = common.getValueByPath(fromObject, ['predictionsFormat']);\n if (fromFormat != null) {\n common.setValueByPath(toObject, ['format'], fromFormat);\n }\n\n const fromGcsUri = common.getValueByPath(fromObject, [\n 'gcsDestination',\n 'outputUriPrefix',\n ]);\n if (fromGcsUri != null) {\n common.setValueByPath(toObject, ['gcsUri'], fromGcsUri);\n }\n\n const fromBigqueryUri = common.getValueByPath(fromObject, [\n 'bigqueryDestination',\n 'outputUri',\n ]);\n if (fromBigqueryUri != null) {\n common.setValueByPath(toObject, ['bigqueryUri'], fromBigqueryUri);\n }\n\n return toObject;\n}\n\nexport function batchJobDestinationToVertex(\n fromObject: types.BatchJobDestination,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromFormat = common.getValueByPath(fromObject, ['format']);\n if (fromFormat != null) {\n common.setValueByPath(toObject, ['predictionsFormat'], fromFormat);\n }\n\n const fromGcsUri = common.getValueByPath(fromObject, ['gcsUri']);\n if (fromGcsUri != null) {\n common.setValueByPath(\n toObject,\n ['gcsDestination', 'outputUriPrefix'],\n fromGcsUri,\n );\n }\n\n const fromBigqueryUri = common.getValueByPath(fromObject, ['bigqueryUri']);\n if (fromBigqueryUri != null) {\n common.setValueByPath(\n toObject,\n ['bigqueryDestination', 'outputUri'],\n fromBigqueryUri,\n );\n }\n\n if (common.getValueByPath(fromObject, ['fileName']) !== undefined) {\n throw new Error('fileName parameter is not supported in Vertex AI.');\n }\n\n if (common.getValueByPath(fromObject, ['inlinedResponses']) !== undefined) {\n throw new Error(\n 'inlinedResponses parameter is not supported in Vertex AI.',\n );\n }\n\n if (\n common.getValueByPath(fromObject, ['inlinedEmbedContentResponses']) !==\n undefined\n ) {\n throw new Error(\n 'inlinedEmbedContentResponses parameter is not supported in Vertex AI.',\n );\n }\n\n return toObject;\n}\n\nexport function batchJobFromMldev(\n fromObject: types.BatchJob,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromDisplayName = common.getValueByPath(fromObject, [\n 'metadata',\n 'displayName',\n ]);\n if (fromDisplayName != null) {\n common.setValueByPath(toObject, ['displayName'], fromDisplayName);\n }\n\n const fromState = common.getValueByPath(fromObject, ['metadata', 'state']);\n if (fromState != null) {\n common.setValueByPath(toObject, ['state'], t.tJobState(fromState));\n }\n\n const fromCreateTime = common.getValueByPath(fromObject, [\n 'metadata',\n 'createTime',\n ]);\n if (fromCreateTime != null) {\n common.setValueByPath(toObject, ['createTime'], fromCreateTime);\n }\n\n const fromEndTime = common.getValueByPath(fromObject, [\n 'metadata',\n 'endTime',\n ]);\n if (fromEndTime != null) {\n common.setValueByPath(toObject, ['endTime'], fromEndTime);\n }\n\n const fromUpdateTime = common.getValueByPath(fromObject, [\n 'metadata',\n 'updateTime',\n ]);\n if (fromUpdateTime != null) {\n common.setValueByPath(toObject, ['updateTime'], fromUpdateTime);\n }\n\n const fromModel = common.getValueByPath(fromObject, ['metadata', 'model']);\n if (fromModel != null) {\n common.setValueByPath(toObject, ['model'], fromModel);\n }\n\n const fromDest = common.getValueByPath(fromObject, ['metadata', 'output']);\n if (fromDest != null) {\n common.setValueByPath(\n toObject,\n ['dest'],\n batchJobDestinationFromMldev(t.tRecvBatchJobDestination(fromDest)),\n );\n }\n\n return toObject;\n}\n\nexport function batchJobFromVertex(\n fromObject: types.BatchJob,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromDisplayName = common.getValueByPath(fromObject, ['displayName']);\n if (fromDisplayName != null) {\n common.setValueByPath(toObject, ['displayName'], fromDisplayName);\n }\n\n const fromState = common.getValueByPath(fromObject, ['state']);\n if (fromState != null) {\n common.setValueByPath(toObject, ['state'], t.tJobState(fromState));\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n const fromCreateTime = common.getValueByPath(fromObject, ['createTime']);\n if (fromCreateTime != null) {\n common.setValueByPath(toObject, ['createTime'], fromCreateTime);\n }\n\n const fromStartTime = common.getValueByPath(fromObject, ['startTime']);\n if (fromStartTime != null) {\n common.setValueByPath(toObject, ['startTime'], fromStartTime);\n }\n\n const fromEndTime = common.getValueByPath(fromObject, ['endTime']);\n if (fromEndTime != null) {\n common.setValueByPath(toObject, ['endTime'], fromEndTime);\n }\n\n const fromUpdateTime = common.getValueByPath(fromObject, ['updateTime']);\n if (fromUpdateTime != null) {\n common.setValueByPath(toObject, ['updateTime'], fromUpdateTime);\n }\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(toObject, ['model'], fromModel);\n }\n\n const fromSrc = common.getValueByPath(fromObject, ['inputConfig']);\n if (fromSrc != null) {\n common.setValueByPath(toObject, ['src'], batchJobSourceFromVertex(fromSrc));\n }\n\n const fromDest = common.getValueByPath(fromObject, ['outputConfig']);\n if (fromDest != null) {\n common.setValueByPath(\n toObject,\n ['dest'],\n batchJobDestinationFromVertex(t.tRecvBatchJobDestination(fromDest)),\n );\n }\n\n const fromCompletionStats = common.getValueByPath(fromObject, [\n 'completionStats',\n ]);\n if (fromCompletionStats != null) {\n common.setValueByPath(toObject, ['completionStats'], fromCompletionStats);\n }\n\n return toObject;\n}\n\nexport function batchJobSourceFromVertex(\n fromObject: types.BatchJobSource,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromFormat = common.getValueByPath(fromObject, ['instancesFormat']);\n if (fromFormat != null) {\n common.setValueByPath(toObject, ['format'], fromFormat);\n }\n\n const fromGcsUri = common.getValueByPath(fromObject, ['gcsSource', 'uris']);\n if (fromGcsUri != null) {\n common.setValueByPath(toObject, ['gcsUri'], fromGcsUri);\n }\n\n const fromBigqueryUri = common.getValueByPath(fromObject, [\n 'bigquerySource',\n 'inputUri',\n ]);\n if (fromBigqueryUri != null) {\n common.setValueByPath(toObject, ['bigqueryUri'], fromBigqueryUri);\n }\n\n return toObject;\n}\n\nexport function batchJobSourceToMldev(\n apiClient: ApiClient,\n fromObject: types.BatchJobSource,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['format']) !== undefined) {\n throw new Error('format parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['gcsUri']) !== undefined) {\n throw new Error('gcsUri parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['bigqueryUri']) !== undefined) {\n throw new Error('bigqueryUri parameter is not supported in Gemini API.');\n }\n\n const fromFileName = common.getValueByPath(fromObject, ['fileName']);\n if (fromFileName != null) {\n common.setValueByPath(toObject, ['fileName'], fromFileName);\n }\n\n const fromInlinedRequests = common.getValueByPath(fromObject, [\n 'inlinedRequests',\n ]);\n if (fromInlinedRequests != null) {\n let transformedList = fromInlinedRequests;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return inlinedRequestToMldev(apiClient, item);\n });\n }\n common.setValueByPath(toObject, ['requests', 'requests'], transformedList);\n }\n\n return toObject;\n}\n\nexport function batchJobSourceToVertex(\n fromObject: types.BatchJobSource,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromFormat = common.getValueByPath(fromObject, ['format']);\n if (fromFormat != null) {\n common.setValueByPath(toObject, ['instancesFormat'], fromFormat);\n }\n\n const fromGcsUri = common.getValueByPath(fromObject, ['gcsUri']);\n if (fromGcsUri != null) {\n common.setValueByPath(toObject, ['gcsSource', 'uris'], fromGcsUri);\n }\n\n const fromBigqueryUri = common.getValueByPath(fromObject, ['bigqueryUri']);\n if (fromBigqueryUri != null) {\n common.setValueByPath(\n toObject,\n ['bigquerySource', 'inputUri'],\n fromBigqueryUri,\n );\n }\n\n if (common.getValueByPath(fromObject, ['fileName']) !== undefined) {\n throw new Error('fileName parameter is not supported in Vertex AI.');\n }\n\n if (common.getValueByPath(fromObject, ['inlinedRequests']) !== undefined) {\n throw new Error('inlinedRequests parameter is not supported in Vertex AI.');\n }\n\n return toObject;\n}\n\nexport function blobToMldev(fromObject: types.Blob): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromData = common.getValueByPath(fromObject, ['data']);\n if (fromData != null) {\n common.setValueByPath(toObject, ['data'], fromData);\n }\n\n if (common.getValueByPath(fromObject, ['displayName']) !== undefined) {\n throw new Error('displayName parameter is not supported in Gemini API.');\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function cancelBatchJobParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.CancelBatchJobParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tBatchJobName(apiClient, fromName),\n );\n }\n\n return toObject;\n}\n\nexport function cancelBatchJobParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.CancelBatchJobParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tBatchJobName(apiClient, fromName),\n );\n }\n\n return toObject;\n}\n\nexport function candidateFromMldev(\n fromObject: types.Candidate,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromContent = common.getValueByPath(fromObject, ['content']);\n if (fromContent != null) {\n common.setValueByPath(toObject, ['content'], fromContent);\n }\n\n const fromCitationMetadata = common.getValueByPath(fromObject, [\n 'citationMetadata',\n ]);\n if (fromCitationMetadata != null) {\n common.setValueByPath(\n toObject,\n ['citationMetadata'],\n citationMetadataFromMldev(fromCitationMetadata),\n );\n }\n\n const fromTokenCount = common.getValueByPath(fromObject, ['tokenCount']);\n if (fromTokenCount != null) {\n common.setValueByPath(toObject, ['tokenCount'], fromTokenCount);\n }\n\n const fromFinishReason = common.getValueByPath(fromObject, ['finishReason']);\n if (fromFinishReason != null) {\n common.setValueByPath(toObject, ['finishReason'], fromFinishReason);\n }\n\n const fromAvgLogprobs = common.getValueByPath(fromObject, ['avgLogprobs']);\n if (fromAvgLogprobs != null) {\n common.setValueByPath(toObject, ['avgLogprobs'], fromAvgLogprobs);\n }\n\n const fromGroundingMetadata = common.getValueByPath(fromObject, [\n 'groundingMetadata',\n ]);\n if (fromGroundingMetadata != null) {\n common.setValueByPath(\n toObject,\n ['groundingMetadata'],\n fromGroundingMetadata,\n );\n }\n\n const fromIndex = common.getValueByPath(fromObject, ['index']);\n if (fromIndex != null) {\n common.setValueByPath(toObject, ['index'], fromIndex);\n }\n\n const fromLogprobsResult = common.getValueByPath(fromObject, [\n 'logprobsResult',\n ]);\n if (fromLogprobsResult != null) {\n common.setValueByPath(toObject, ['logprobsResult'], fromLogprobsResult);\n }\n\n const fromSafetyRatings = common.getValueByPath(fromObject, [\n 'safetyRatings',\n ]);\n if (fromSafetyRatings != null) {\n let transformedList = fromSafetyRatings;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['safetyRatings'], transformedList);\n }\n\n const fromUrlContextMetadata = common.getValueByPath(fromObject, [\n 'urlContextMetadata',\n ]);\n if (fromUrlContextMetadata != null) {\n common.setValueByPath(\n toObject,\n ['urlContextMetadata'],\n fromUrlContextMetadata,\n );\n }\n\n return toObject;\n}\n\nexport function citationMetadataFromMldev(\n fromObject: types.CitationMetadata,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromCitations = common.getValueByPath(fromObject, ['citationSources']);\n if (fromCitations != null) {\n let transformedList = fromCitations;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['citations'], transformedList);\n }\n\n return toObject;\n}\n\nexport function contentToMldev(\n fromObject: types.Content,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromParts = common.getValueByPath(fromObject, ['parts']);\n if (fromParts != null) {\n let transformedList = fromParts;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return partToMldev(item);\n });\n }\n common.setValueByPath(toObject, ['parts'], transformedList);\n }\n\n const fromRole = common.getValueByPath(fromObject, ['role']);\n if (fromRole != null) {\n common.setValueByPath(toObject, ['role'], fromRole);\n }\n\n return toObject;\n}\n\nexport function createBatchJobConfigToMldev(\n fromObject: types.CreateBatchJobConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromDisplayName = common.getValueByPath(fromObject, ['displayName']);\n if (parentObject !== undefined && fromDisplayName != null) {\n common.setValueByPath(\n parentObject,\n ['batch', 'displayName'],\n fromDisplayName,\n );\n }\n\n if (common.getValueByPath(fromObject, ['dest']) !== undefined) {\n throw new Error('dest parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function createBatchJobConfigToVertex(\n fromObject: types.CreateBatchJobConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromDisplayName = common.getValueByPath(fromObject, ['displayName']);\n if (parentObject !== undefined && fromDisplayName != null) {\n common.setValueByPath(parentObject, ['displayName'], fromDisplayName);\n }\n\n const fromDest = common.getValueByPath(fromObject, ['dest']);\n if (parentObject !== undefined && fromDest != null) {\n common.setValueByPath(\n parentObject,\n ['outputConfig'],\n batchJobDestinationToVertex(t.tBatchJobDestination(fromDest)),\n );\n }\n\n return toObject;\n}\n\nexport function createBatchJobParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.CreateBatchJobParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromSrc = common.getValueByPath(fromObject, ['src']);\n if (fromSrc != null) {\n common.setValueByPath(\n toObject,\n ['batch', 'inputConfig'],\n batchJobSourceToMldev(apiClient, t.tBatchJobSource(apiClient, fromSrc)),\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n createBatchJobConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function createBatchJobParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.CreateBatchJobParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(toObject, ['model'], t.tModel(apiClient, fromModel));\n }\n\n const fromSrc = common.getValueByPath(fromObject, ['src']);\n if (fromSrc != null) {\n common.setValueByPath(\n toObject,\n ['inputConfig'],\n batchJobSourceToVertex(t.tBatchJobSource(apiClient, fromSrc)),\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n createBatchJobConfigToVertex(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function createEmbeddingsBatchJobConfigToMldev(\n fromObject: types.CreateEmbeddingsBatchJobConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromDisplayName = common.getValueByPath(fromObject, ['displayName']);\n if (parentObject !== undefined && fromDisplayName != null) {\n common.setValueByPath(\n parentObject,\n ['batch', 'displayName'],\n fromDisplayName,\n );\n }\n\n return toObject;\n}\n\nexport function createEmbeddingsBatchJobParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.CreateEmbeddingsBatchJobParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromSrc = common.getValueByPath(fromObject, ['src']);\n if (fromSrc != null) {\n common.setValueByPath(\n toObject,\n ['batch', 'inputConfig'],\n embeddingsBatchJobSourceToMldev(apiClient, fromSrc),\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n createEmbeddingsBatchJobConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function deleteBatchJobParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.DeleteBatchJobParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tBatchJobName(apiClient, fromName),\n );\n }\n\n return toObject;\n}\n\nexport function deleteBatchJobParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.DeleteBatchJobParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tBatchJobName(apiClient, fromName),\n );\n }\n\n return toObject;\n}\n\nexport function deleteResourceJobFromMldev(\n fromObject: types.DeleteResourceJob,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromDone = common.getValueByPath(fromObject, ['done']);\n if (fromDone != null) {\n common.setValueByPath(toObject, ['done'], fromDone);\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n return toObject;\n}\n\nexport function deleteResourceJobFromVertex(\n fromObject: types.DeleteResourceJob,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromDone = common.getValueByPath(fromObject, ['done']);\n if (fromDone != null) {\n common.setValueByPath(toObject, ['done'], fromDone);\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n return toObject;\n}\n\nexport function embedContentBatchToMldev(\n apiClient: ApiClient,\n fromObject: types.EmbedContentBatch,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromContents = common.getValueByPath(fromObject, ['contents']);\n if (fromContents != null) {\n let transformedList = t.tContentsForEmbed(apiClient, fromContents);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(\n toObject,\n ['requests[]', 'request', 'content'],\n transformedList,\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n common.setValueByPath(\n toObject,\n ['_self'],\n embedContentConfigToMldev(fromConfig, toObject),\n );\n common.moveValueByPath(toObject, {'requests[].*': 'requests[].request.*'});\n }\n\n return toObject;\n}\n\nexport function embedContentConfigToMldev(\n fromObject: types.EmbedContentConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromTaskType = common.getValueByPath(fromObject, ['taskType']);\n if (parentObject !== undefined && fromTaskType != null) {\n common.setValueByPath(\n parentObject,\n ['requests[]', 'taskType'],\n fromTaskType,\n );\n }\n\n const fromTitle = common.getValueByPath(fromObject, ['title']);\n if (parentObject !== undefined && fromTitle != null) {\n common.setValueByPath(parentObject, ['requests[]', 'title'], fromTitle);\n }\n\n const fromOutputDimensionality = common.getValueByPath(fromObject, [\n 'outputDimensionality',\n ]);\n if (parentObject !== undefined && fromOutputDimensionality != null) {\n common.setValueByPath(\n parentObject,\n ['requests[]', 'outputDimensionality'],\n fromOutputDimensionality,\n );\n }\n\n if (common.getValueByPath(fromObject, ['mimeType']) !== undefined) {\n throw new Error('mimeType parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['autoTruncate']) !== undefined) {\n throw new Error('autoTruncate parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function embeddingsBatchJobSourceToMldev(\n apiClient: ApiClient,\n fromObject: types.EmbeddingsBatchJobSource,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromFileName = common.getValueByPath(fromObject, ['fileName']);\n if (fromFileName != null) {\n common.setValueByPath(toObject, ['file_name'], fromFileName);\n }\n\n const fromInlinedRequests = common.getValueByPath(fromObject, [\n 'inlinedRequests',\n ]);\n if (fromInlinedRequests != null) {\n common.setValueByPath(\n toObject,\n ['requests'],\n embedContentBatchToMldev(apiClient, fromInlinedRequests),\n );\n }\n\n return toObject;\n}\n\nexport function fileDataToMldev(\n fromObject: types.FileData,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['displayName']) !== undefined) {\n throw new Error('displayName parameter is not supported in Gemini API.');\n }\n\n const fromFileUri = common.getValueByPath(fromObject, ['fileUri']);\n if (fromFileUri != null) {\n common.setValueByPath(toObject, ['fileUri'], fromFileUri);\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function functionCallToMldev(\n fromObject: types.FunctionCall,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromId = common.getValueByPath(fromObject, ['id']);\n if (fromId != null) {\n common.setValueByPath(toObject, ['id'], fromId);\n }\n\n const fromArgs = common.getValueByPath(fromObject, ['args']);\n if (fromArgs != null) {\n common.setValueByPath(toObject, ['args'], fromArgs);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n if (common.getValueByPath(fromObject, ['partialArgs']) !== undefined) {\n throw new Error('partialArgs parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['willContinue']) !== undefined) {\n throw new Error('willContinue parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function functionCallingConfigToMldev(\n fromObject: types.FunctionCallingConfig,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromAllowedFunctionNames = common.getValueByPath(fromObject, [\n 'allowedFunctionNames',\n ]);\n if (fromAllowedFunctionNames != null) {\n common.setValueByPath(\n toObject,\n ['allowedFunctionNames'],\n fromAllowedFunctionNames,\n );\n }\n\n const fromMode = common.getValueByPath(fromObject, ['mode']);\n if (fromMode != null) {\n common.setValueByPath(toObject, ['mode'], fromMode);\n }\n\n if (\n common.getValueByPath(fromObject, ['streamFunctionCallArguments']) !==\n undefined\n ) {\n throw new Error(\n 'streamFunctionCallArguments parameter is not supported in Gemini API.',\n );\n }\n\n return toObject;\n}\n\nexport function generateContentConfigToMldev(\n apiClient: ApiClient,\n fromObject: types.GenerateContentConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSystemInstruction = common.getValueByPath(fromObject, [\n 'systemInstruction',\n ]);\n if (parentObject !== undefined && fromSystemInstruction != null) {\n common.setValueByPath(\n parentObject,\n ['systemInstruction'],\n contentToMldev(t.tContent(fromSystemInstruction)),\n );\n }\n\n const fromTemperature = common.getValueByPath(fromObject, ['temperature']);\n if (fromTemperature != null) {\n common.setValueByPath(toObject, ['temperature'], fromTemperature);\n }\n\n const fromTopP = common.getValueByPath(fromObject, ['topP']);\n if (fromTopP != null) {\n common.setValueByPath(toObject, ['topP'], fromTopP);\n }\n\n const fromTopK = common.getValueByPath(fromObject, ['topK']);\n if (fromTopK != null) {\n common.setValueByPath(toObject, ['topK'], fromTopK);\n }\n\n const fromCandidateCount = common.getValueByPath(fromObject, [\n 'candidateCount',\n ]);\n if (fromCandidateCount != null) {\n common.setValueByPath(toObject, ['candidateCount'], fromCandidateCount);\n }\n\n const fromMaxOutputTokens = common.getValueByPath(fromObject, [\n 'maxOutputTokens',\n ]);\n if (fromMaxOutputTokens != null) {\n common.setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens);\n }\n\n const fromStopSequences = common.getValueByPath(fromObject, [\n 'stopSequences',\n ]);\n if (fromStopSequences != null) {\n common.setValueByPath(toObject, ['stopSequences'], fromStopSequences);\n }\n\n const fromResponseLogprobs = common.getValueByPath(fromObject, [\n 'responseLogprobs',\n ]);\n if (fromResponseLogprobs != null) {\n common.setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs);\n }\n\n const fromLogprobs = common.getValueByPath(fromObject, ['logprobs']);\n if (fromLogprobs != null) {\n common.setValueByPath(toObject, ['logprobs'], fromLogprobs);\n }\n\n const fromPresencePenalty = common.getValueByPath(fromObject, [\n 'presencePenalty',\n ]);\n if (fromPresencePenalty != null) {\n common.setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty);\n }\n\n const fromFrequencyPenalty = common.getValueByPath(fromObject, [\n 'frequencyPenalty',\n ]);\n if (fromFrequencyPenalty != null) {\n common.setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty);\n }\n\n const fromSeed = common.getValueByPath(fromObject, ['seed']);\n if (fromSeed != null) {\n common.setValueByPath(toObject, ['seed'], fromSeed);\n }\n\n const fromResponseMimeType = common.getValueByPath(fromObject, [\n 'responseMimeType',\n ]);\n if (fromResponseMimeType != null) {\n common.setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType);\n }\n\n const fromResponseSchema = common.getValueByPath(fromObject, [\n 'responseSchema',\n ]);\n if (fromResponseSchema != null) {\n common.setValueByPath(\n toObject,\n ['responseSchema'],\n t.tSchema(fromResponseSchema),\n );\n }\n\n const fromResponseJsonSchema = common.getValueByPath(fromObject, [\n 'responseJsonSchema',\n ]);\n if (fromResponseJsonSchema != null) {\n common.setValueByPath(\n toObject,\n ['responseJsonSchema'],\n fromResponseJsonSchema,\n );\n }\n\n if (common.getValueByPath(fromObject, ['routingConfig']) !== undefined) {\n throw new Error('routingConfig parameter is not supported in Gemini API.');\n }\n\n if (\n common.getValueByPath(fromObject, ['modelSelectionConfig']) !== undefined\n ) {\n throw new Error(\n 'modelSelectionConfig parameter is not supported in Gemini API.',\n );\n }\n\n const fromSafetySettings = common.getValueByPath(fromObject, [\n 'safetySettings',\n ]);\n if (parentObject !== undefined && fromSafetySettings != null) {\n let transformedList = fromSafetySettings;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return safetySettingToMldev(item);\n });\n }\n common.setValueByPath(parentObject, ['safetySettings'], transformedList);\n }\n\n const fromTools = common.getValueByPath(fromObject, ['tools']);\n if (parentObject !== undefined && fromTools != null) {\n let transformedList = t.tTools(fromTools);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return toolToMldev(t.tTool(item));\n });\n }\n common.setValueByPath(parentObject, ['tools'], transformedList);\n }\n\n const fromToolConfig = common.getValueByPath(fromObject, ['toolConfig']);\n if (parentObject !== undefined && fromToolConfig != null) {\n common.setValueByPath(\n parentObject,\n ['toolConfig'],\n toolConfigToMldev(fromToolConfig),\n );\n }\n\n if (common.getValueByPath(fromObject, ['labels']) !== undefined) {\n throw new Error('labels parameter is not supported in Gemini API.');\n }\n\n const fromCachedContent = common.getValueByPath(fromObject, [\n 'cachedContent',\n ]);\n if (parentObject !== undefined && fromCachedContent != null) {\n common.setValueByPath(\n parentObject,\n ['cachedContent'],\n t.tCachedContentName(apiClient, fromCachedContent),\n );\n }\n\n const fromResponseModalities = common.getValueByPath(fromObject, [\n 'responseModalities',\n ]);\n if (fromResponseModalities != null) {\n common.setValueByPath(\n toObject,\n ['responseModalities'],\n fromResponseModalities,\n );\n }\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (fromMediaResolution != null) {\n common.setValueByPath(toObject, ['mediaResolution'], fromMediaResolution);\n }\n\n const fromSpeechConfig = common.getValueByPath(fromObject, ['speechConfig']);\n if (fromSpeechConfig != null) {\n common.setValueByPath(\n toObject,\n ['speechConfig'],\n t.tSpeechConfig(fromSpeechConfig),\n );\n }\n\n if (common.getValueByPath(fromObject, ['audioTimestamp']) !== undefined) {\n throw new Error('audioTimestamp parameter is not supported in Gemini API.');\n }\n\n const fromThinkingConfig = common.getValueByPath(fromObject, [\n 'thinkingConfig',\n ]);\n if (fromThinkingConfig != null) {\n common.setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig);\n }\n\n const fromImageConfig = common.getValueByPath(fromObject, ['imageConfig']);\n if (fromImageConfig != null) {\n common.setValueByPath(\n toObject,\n ['imageConfig'],\n imageConfigToMldev(fromImageConfig),\n );\n }\n\n const fromEnableEnhancedCivicAnswers = common.getValueByPath(fromObject, [\n 'enableEnhancedCivicAnswers',\n ]);\n if (fromEnableEnhancedCivicAnswers != null) {\n common.setValueByPath(\n toObject,\n ['enableEnhancedCivicAnswers'],\n fromEnableEnhancedCivicAnswers,\n );\n }\n\n if (common.getValueByPath(fromObject, ['modelArmorConfig']) !== undefined) {\n throw new Error(\n 'modelArmorConfig parameter is not supported in Gemini API.',\n );\n }\n\n return toObject;\n}\n\nexport function generateContentResponseFromMldev(\n fromObject: types.GenerateContentResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromCandidates = common.getValueByPath(fromObject, ['candidates']);\n if (fromCandidates != null) {\n let transformedList = fromCandidates;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return candidateFromMldev(item);\n });\n }\n common.setValueByPath(toObject, ['candidates'], transformedList);\n }\n\n const fromModelVersion = common.getValueByPath(fromObject, ['modelVersion']);\n if (fromModelVersion != null) {\n common.setValueByPath(toObject, ['modelVersion'], fromModelVersion);\n }\n\n const fromPromptFeedback = common.getValueByPath(fromObject, [\n 'promptFeedback',\n ]);\n if (fromPromptFeedback != null) {\n common.setValueByPath(toObject, ['promptFeedback'], fromPromptFeedback);\n }\n\n const fromResponseId = common.getValueByPath(fromObject, ['responseId']);\n if (fromResponseId != null) {\n common.setValueByPath(toObject, ['responseId'], fromResponseId);\n }\n\n const fromUsageMetadata = common.getValueByPath(fromObject, [\n 'usageMetadata',\n ]);\n if (fromUsageMetadata != null) {\n common.setValueByPath(toObject, ['usageMetadata'], fromUsageMetadata);\n }\n\n return toObject;\n}\n\nexport function getBatchJobParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.GetBatchJobParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tBatchJobName(apiClient, fromName),\n );\n }\n\n return toObject;\n}\n\nexport function getBatchJobParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.GetBatchJobParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tBatchJobName(apiClient, fromName),\n );\n }\n\n return toObject;\n}\n\nexport function googleMapsToMldev(\n fromObject: types.GoogleMaps,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['authConfig']) !== undefined) {\n throw new Error('authConfig parameter is not supported in Gemini API.');\n }\n\n const fromEnableWidget = common.getValueByPath(fromObject, ['enableWidget']);\n if (fromEnableWidget != null) {\n common.setValueByPath(toObject, ['enableWidget'], fromEnableWidget);\n }\n\n return toObject;\n}\n\nexport function googleSearchToMldev(\n fromObject: types.GoogleSearch,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['excludeDomains']) !== undefined) {\n throw new Error('excludeDomains parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['blockingConfidence']) !== undefined) {\n throw new Error(\n 'blockingConfidence parameter is not supported in Gemini API.',\n );\n }\n\n const fromTimeRangeFilter = common.getValueByPath(fromObject, [\n 'timeRangeFilter',\n ]);\n if (fromTimeRangeFilter != null) {\n common.setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter);\n }\n\n return toObject;\n}\n\nexport function imageConfigToMldev(\n fromObject: types.ImageConfig,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromAspectRatio = common.getValueByPath(fromObject, ['aspectRatio']);\n if (fromAspectRatio != null) {\n common.setValueByPath(toObject, ['aspectRatio'], fromAspectRatio);\n }\n\n const fromImageSize = common.getValueByPath(fromObject, ['imageSize']);\n if (fromImageSize != null) {\n common.setValueByPath(toObject, ['imageSize'], fromImageSize);\n }\n\n if (common.getValueByPath(fromObject, ['personGeneration']) !== undefined) {\n throw new Error(\n 'personGeneration parameter is not supported in Gemini API.',\n );\n }\n\n if (common.getValueByPath(fromObject, ['outputMimeType']) !== undefined) {\n throw new Error('outputMimeType parameter is not supported in Gemini API.');\n }\n\n if (\n common.getValueByPath(fromObject, ['outputCompressionQuality']) !==\n undefined\n ) {\n throw new Error(\n 'outputCompressionQuality parameter is not supported in Gemini API.',\n );\n }\n\n return toObject;\n}\n\nexport function inlinedRequestToMldev(\n apiClient: ApiClient,\n fromObject: types.InlinedRequest,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['request', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromContents = common.getValueByPath(fromObject, ['contents']);\n if (fromContents != null) {\n let transformedList = t.tContents(fromContents);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return contentToMldev(item);\n });\n }\n common.setValueByPath(toObject, ['request', 'contents'], transformedList);\n }\n\n const fromMetadata = common.getValueByPath(fromObject, ['metadata']);\n if (fromMetadata != null) {\n common.setValueByPath(toObject, ['metadata'], fromMetadata);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n common.setValueByPath(\n toObject,\n ['request', 'generationConfig'],\n generateContentConfigToMldev(\n apiClient,\n fromConfig,\n common.getValueByPath(toObject, ['request'], {}) as Record<\n string,\n unknown\n >,\n ),\n );\n }\n\n return toObject;\n}\n\nexport function inlinedResponseFromMldev(\n fromObject: types.InlinedResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromResponse = common.getValueByPath(fromObject, ['response']);\n if (fromResponse != null) {\n common.setValueByPath(\n toObject,\n ['response'],\n generateContentResponseFromMldev(\n fromResponse as types.GenerateContentResponse,\n ),\n );\n }\n\n const fromMetadata = common.getValueByPath(fromObject, ['metadata']);\n if (fromMetadata != null) {\n common.setValueByPath(toObject, ['metadata'], fromMetadata);\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n return toObject;\n}\n\nexport function listBatchJobsConfigToMldev(\n fromObject: types.ListBatchJobsConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPageSize = common.getValueByPath(fromObject, ['pageSize']);\n if (parentObject !== undefined && fromPageSize != null) {\n common.setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize);\n }\n\n const fromPageToken = common.getValueByPath(fromObject, ['pageToken']);\n if (parentObject !== undefined && fromPageToken != null) {\n common.setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken);\n }\n\n if (common.getValueByPath(fromObject, ['filter']) !== undefined) {\n throw new Error('filter parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function listBatchJobsConfigToVertex(\n fromObject: types.ListBatchJobsConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPageSize = common.getValueByPath(fromObject, ['pageSize']);\n if (parentObject !== undefined && fromPageSize != null) {\n common.setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize);\n }\n\n const fromPageToken = common.getValueByPath(fromObject, ['pageToken']);\n if (parentObject !== undefined && fromPageToken != null) {\n common.setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken);\n }\n\n const fromFilter = common.getValueByPath(fromObject, ['filter']);\n if (parentObject !== undefined && fromFilter != null) {\n common.setValueByPath(parentObject, ['_query', 'filter'], fromFilter);\n }\n\n return toObject;\n}\n\nexport function listBatchJobsParametersToMldev(\n fromObject: types.ListBatchJobsParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n listBatchJobsConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function listBatchJobsParametersToVertex(\n fromObject: types.ListBatchJobsParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n listBatchJobsConfigToVertex(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function listBatchJobsResponseFromMldev(\n fromObject: types.ListBatchJobsResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromNextPageToken = common.getValueByPath(fromObject, [\n 'nextPageToken',\n ]);\n if (fromNextPageToken != null) {\n common.setValueByPath(toObject, ['nextPageToken'], fromNextPageToken);\n }\n\n const fromBatchJobs = common.getValueByPath(fromObject, ['operations']);\n if (fromBatchJobs != null) {\n let transformedList = fromBatchJobs;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return batchJobFromMldev(item);\n });\n }\n common.setValueByPath(toObject, ['batchJobs'], transformedList);\n }\n\n return toObject;\n}\n\nexport function listBatchJobsResponseFromVertex(\n fromObject: types.ListBatchJobsResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromNextPageToken = common.getValueByPath(fromObject, [\n 'nextPageToken',\n ]);\n if (fromNextPageToken != null) {\n common.setValueByPath(toObject, ['nextPageToken'], fromNextPageToken);\n }\n\n const fromBatchJobs = common.getValueByPath(fromObject, [\n 'batchPredictionJobs',\n ]);\n if (fromBatchJobs != null) {\n let transformedList = fromBatchJobs;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return batchJobFromVertex(item);\n });\n }\n common.setValueByPath(toObject, ['batchJobs'], transformedList);\n }\n\n return toObject;\n}\n\nexport function partToMldev(fromObject: types.Part): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (fromMediaResolution != null) {\n common.setValueByPath(toObject, ['mediaResolution'], fromMediaResolution);\n }\n\n const fromCodeExecutionResult = common.getValueByPath(fromObject, [\n 'codeExecutionResult',\n ]);\n if (fromCodeExecutionResult != null) {\n common.setValueByPath(\n toObject,\n ['codeExecutionResult'],\n fromCodeExecutionResult,\n );\n }\n\n const fromExecutableCode = common.getValueByPath(fromObject, [\n 'executableCode',\n ]);\n if (fromExecutableCode != null) {\n common.setValueByPath(toObject, ['executableCode'], fromExecutableCode);\n }\n\n const fromFileData = common.getValueByPath(fromObject, ['fileData']);\n if (fromFileData != null) {\n common.setValueByPath(\n toObject,\n ['fileData'],\n fileDataToMldev(fromFileData),\n );\n }\n\n const fromFunctionCall = common.getValueByPath(fromObject, ['functionCall']);\n if (fromFunctionCall != null) {\n common.setValueByPath(\n toObject,\n ['functionCall'],\n functionCallToMldev(fromFunctionCall),\n );\n }\n\n const fromFunctionResponse = common.getValueByPath(fromObject, [\n 'functionResponse',\n ]);\n if (fromFunctionResponse != null) {\n common.setValueByPath(toObject, ['functionResponse'], fromFunctionResponse);\n }\n\n const fromInlineData = common.getValueByPath(fromObject, ['inlineData']);\n if (fromInlineData != null) {\n common.setValueByPath(\n toObject,\n ['inlineData'],\n blobToMldev(fromInlineData),\n );\n }\n\n const fromText = common.getValueByPath(fromObject, ['text']);\n if (fromText != null) {\n common.setValueByPath(toObject, ['text'], fromText);\n }\n\n const fromThought = common.getValueByPath(fromObject, ['thought']);\n if (fromThought != null) {\n common.setValueByPath(toObject, ['thought'], fromThought);\n }\n\n const fromThoughtSignature = common.getValueByPath(fromObject, [\n 'thoughtSignature',\n ]);\n if (fromThoughtSignature != null) {\n common.setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature);\n }\n\n const fromVideoMetadata = common.getValueByPath(fromObject, [\n 'videoMetadata',\n ]);\n if (fromVideoMetadata != null) {\n common.setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata);\n }\n\n return toObject;\n}\n\nexport function safetySettingToMldev(\n fromObject: types.SafetySetting,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromCategory = common.getValueByPath(fromObject, ['category']);\n if (fromCategory != null) {\n common.setValueByPath(toObject, ['category'], fromCategory);\n }\n\n if (common.getValueByPath(fromObject, ['method']) !== undefined) {\n throw new Error('method parameter is not supported in Gemini API.');\n }\n\n const fromThreshold = common.getValueByPath(fromObject, ['threshold']);\n if (fromThreshold != null) {\n common.setValueByPath(toObject, ['threshold'], fromThreshold);\n }\n\n return toObject;\n}\n\nexport function toolConfigToMldev(\n fromObject: types.ToolConfig,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromRetrievalConfig = common.getValueByPath(fromObject, [\n 'retrievalConfig',\n ]);\n if (fromRetrievalConfig != null) {\n common.setValueByPath(toObject, ['retrievalConfig'], fromRetrievalConfig);\n }\n\n const fromFunctionCallingConfig = common.getValueByPath(fromObject, [\n 'functionCallingConfig',\n ]);\n if (fromFunctionCallingConfig != null) {\n common.setValueByPath(\n toObject,\n ['functionCallingConfig'],\n functionCallingConfigToMldev(fromFunctionCallingConfig),\n );\n }\n\n return toObject;\n}\n\nexport function toolToMldev(fromObject: types.Tool): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['retrieval']) !== undefined) {\n throw new Error('retrieval parameter is not supported in Gemini API.');\n }\n\n const fromComputerUse = common.getValueByPath(fromObject, ['computerUse']);\n if (fromComputerUse != null) {\n common.setValueByPath(toObject, ['computerUse'], fromComputerUse);\n }\n\n const fromFileSearch = common.getValueByPath(fromObject, ['fileSearch']);\n if (fromFileSearch != null) {\n common.setValueByPath(toObject, ['fileSearch'], fromFileSearch);\n }\n\n const fromCodeExecution = common.getValueByPath(fromObject, [\n 'codeExecution',\n ]);\n if (fromCodeExecution != null) {\n common.setValueByPath(toObject, ['codeExecution'], fromCodeExecution);\n }\n\n if (\n common.getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined\n ) {\n throw new Error(\n 'enterpriseWebSearch parameter is not supported in Gemini API.',\n );\n }\n\n const fromFunctionDeclarations = common.getValueByPath(fromObject, [\n 'functionDeclarations',\n ]);\n if (fromFunctionDeclarations != null) {\n let transformedList = fromFunctionDeclarations;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['functionDeclarations'], transformedList);\n }\n\n const fromGoogleMaps = common.getValueByPath(fromObject, ['googleMaps']);\n if (fromGoogleMaps != null) {\n common.setValueByPath(\n toObject,\n ['googleMaps'],\n googleMapsToMldev(fromGoogleMaps),\n );\n }\n\n const fromGoogleSearch = common.getValueByPath(fromObject, ['googleSearch']);\n if (fromGoogleSearch != null) {\n common.setValueByPath(\n toObject,\n ['googleSearch'],\n googleSearchToMldev(fromGoogleSearch),\n );\n }\n\n const fromGoogleSearchRetrieval = common.getValueByPath(fromObject, [\n 'googleSearchRetrieval',\n ]);\n if (fromGoogleSearchRetrieval != null) {\n common.setValueByPath(\n toObject,\n ['googleSearchRetrieval'],\n fromGoogleSearchRetrieval,\n );\n }\n\n const fromUrlContext = common.getValueByPath(fromObject, ['urlContext']);\n if (fromUrlContext != null) {\n common.setValueByPath(toObject, ['urlContext'], fromUrlContext);\n }\n\n return toObject;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Pagers for the GenAI List APIs.\n */\n\nimport * as types from '../src/types';\n\nexport enum PagedItem {\n PAGED_ITEM_BATCH_JOBS = 'batchJobs',\n PAGED_ITEM_MODELS = 'models',\n PAGED_ITEM_TUNING_JOBS = 'tuningJobs',\n PAGED_ITEM_FILES = 'files',\n PAGED_ITEM_CACHED_CONTENTS = 'cachedContents',\n PAGED_ITEM_FILE_SEARCH_STORES = 'fileSearchStores',\n PAGED_ITEM_DOCUMENTS = 'documents',\n}\n\nexport interface PagedItemConfig {\n parent?: string;\n config?: {\n pageToken?: string;\n pageSize?: number;\n };\n}\n\ninterface PagedItemResponse<T> {\n nextPageToken?: string;\n sdkHttpResponse?: types.HttpResponse;\n batchJobs?: T[];\n models?: T[];\n tuningJobs?: T[];\n files?: T[];\n cachedContents?: T[];\n fileSearchStores?: T[];\n documents?: T[];\n}\n\n/**\n * Pager class for iterating through paginated results.\n */\nexport class Pager<T> implements AsyncIterable<T> {\n private nameInternal!: PagedItem;\n private pageInternal: T[] = [];\n private paramsInternal: PagedItemConfig = {};\n private pageInternalSize!: number;\n private sdkHttpResponseInternal?: types.HttpResponse;\n protected requestInternal!: (\n params: PagedItemConfig,\n ) => Promise<PagedItemResponse<T>>;\n protected idxInternal!: number;\n\n constructor(\n name: PagedItem,\n request: (params: PagedItemConfig) => Promise<PagedItemResponse<T>>,\n response: PagedItemResponse<T>,\n params: PagedItemConfig,\n ) {\n this.requestInternal = request;\n this.init(name, response, params);\n }\n\n private init(\n name: PagedItem,\n response: PagedItemResponse<T>,\n params: PagedItemConfig,\n ) {\n this.nameInternal = name;\n this.pageInternal = response[this.nameInternal] || [];\n\n this.sdkHttpResponseInternal = response?.sdkHttpResponse;\n this.idxInternal = 0;\n let requestParams: PagedItemConfig = {config: {}};\n if (!params || Object.keys(params).length === 0) {\n requestParams = {config: {}};\n } else if (typeof params === 'object') {\n requestParams = {...params};\n } else {\n requestParams = params;\n }\n if (requestParams['config']) {\n requestParams['config']['pageToken'] = response['nextPageToken'];\n }\n this.paramsInternal = requestParams;\n this.pageInternalSize =\n requestParams['config']?.['pageSize'] ?? this.pageInternal.length;\n }\n\n private initNextPage(response: PagedItemResponse<T>): void {\n this.init(this.nameInternal, response, this.paramsInternal);\n }\n\n /**\n * Returns the current page, which is a list of items.\n *\n * @remarks\n * The first page is retrieved when the pager is created. The returned list of\n * items could be a subset of the entire list.\n */\n get page(): T[] {\n return this.pageInternal;\n }\n\n /**\n * Returns the type of paged item (for example, ``batch_jobs``).\n */\n get name(): PagedItem {\n return this.nameInternal;\n }\n\n /**\n * Returns the length of the page fetched each time by this pager.\n *\n * @remarks\n * The number of items in the page is less than or equal to the page length.\n */\n get pageSize(): number {\n return this.pageInternalSize;\n }\n\n /**\n * Returns the headers of the API response.\n */\n get sdkHttpResponse(): types.HttpResponse | undefined {\n return this.sdkHttpResponseInternal;\n }\n\n /**\n * Returns the parameters when making the API request for the next page.\n *\n * @remarks\n * Parameters contain a set of optional configs that can be\n * used to customize the API request. For example, the `pageToken` parameter\n * contains the token to request the next page.\n */\n get params(): PagedItemConfig {\n return this.paramsInternal;\n }\n\n /**\n * Returns the total number of items in the current page.\n */\n get pageLength(): number {\n return this.pageInternal.length;\n }\n\n /**\n * Returns the item at the given index.\n */\n getItem(index: number): T {\n return this.pageInternal[index];\n }\n\n /**\n * Returns an async iterator that support iterating through all items\n * retrieved from the API.\n *\n * @remarks\n * The iterator will automatically fetch the next page if there are more items\n * to fetch from the API.\n *\n * @example\n *\n * ```ts\n * const pager = await ai.files.list({config: {pageSize: 10}});\n * for await (const file of pager) {\n * console.log(file.name);\n * }\n * ```\n */\n [Symbol.asyncIterator](): AsyncIterator<T> {\n return {\n next: async () => {\n if (this.idxInternal >= this.pageLength) {\n if (this.hasNextPage()) {\n await this.nextPage();\n } else {\n return {value: undefined, done: true};\n }\n }\n const item = this.getItem(this.idxInternal);\n this.idxInternal += 1;\n return {value: item, done: false};\n },\n return: async () => {\n return {value: undefined, done: true};\n },\n };\n }\n\n /**\n * Fetches the next page of items. This makes a new API request.\n *\n * @throws {Error} If there are no more pages to fetch.\n *\n * @example\n *\n * ```ts\n * const pager = await ai.files.list({config: {pageSize: 10}});\n * let page = pager.page;\n * while (true) {\n * for (const file of page) {\n * console.log(file.name);\n * }\n * if (!pager.hasNextPage()) {\n * break;\n * }\n * page = await pager.nextPage();\n * }\n * ```\n */\n async nextPage(): Promise<T[]> {\n if (!this.hasNextPage()) {\n throw new Error('No more pages to fetch.');\n }\n const response = await this.requestInternal(this.params);\n this.initNextPage(response);\n return this.page;\n }\n\n /**\n * Returns true if there are more pages to fetch from the API.\n */\n hasNextPage(): boolean {\n if (this.params['config']?.['pageToken'] !== undefined) {\n return true;\n }\n return false;\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport {ApiClient} from './_api_client.js';\nimport * as common from './_common.js';\nimport {BaseModule} from './_common.js';\nimport * as converters from './converters/_batches_converters.js';\nimport {PagedItem, Pager} from './pagers.js';\nimport * as types from './types.js';\n\nexport class Batches extends BaseModule {\n constructor(private readonly apiClient: ApiClient) {\n super();\n }\n\n /**\n * Lists batch jobs.\n *\n * @param params - The parameters for the list request.\n * @return - A pager of batch jobs.\n *\n * @example\n * ```ts\n * const batchJobs = await ai.batches.list({config: {'pageSize': 2}});\n * for await (const batchJob of batchJobs) {\n * console.log(batchJob);\n * }\n * ```\n */\n list = async (\n params: types.ListBatchJobsParameters = {},\n ): Promise<Pager<types.BatchJob>> => {\n return new Pager<types.BatchJob>(\n PagedItem.PAGED_ITEM_BATCH_JOBS,\n (x: types.ListBatchJobsParameters) => this.listInternal(x),\n await this.listInternal(params),\n params,\n );\n };\n\n /**\n * Create batch job.\n *\n * @param params - The parameters for create batch job request.\n * @return The created batch job.\n *\n * @example\n * ```ts\n * const response = await ai.batches.create({\n * model: 'gemini-2.0-flash',\n * src: {gcsUri: 'gs://bucket/path/to/file.jsonl', format: 'jsonl'},\n * config: {\n * dest: {gcsUri: 'gs://bucket/path/output/directory', format: 'jsonl'},\n * }\n * });\n * console.log(response);\n * ```\n */\n create = async (\n params: types.CreateBatchJobParameters,\n ): Promise<types.BatchJob> => {\n if (this.apiClient.isVertexAI()) {\n // Format destination if not provided\n // Cast params.src as Vertex AI path does not handle InlinedRequest[]\n params.config = this.formatDestination(\n params.src as string | types.BatchJobSource,\n params.config,\n );\n }\n return this.createInternal(params);\n };\n\n /**\n * **Experimental** Creates an embedding batch job.\n *\n * @param params - The parameters for create embedding batch job request.\n * @return The created batch job.\n *\n * @example\n * ```ts\n * const response = await ai.batches.createEmbeddings({\n * model: 'text-embedding-004',\n * src: {fileName: 'files/my_embedding_input'},\n * });\n * console.log(response);\n * ```\n */\n createEmbeddings = async (\n params: types.CreateEmbeddingsBatchJobParameters,\n ): Promise<types.BatchJob> => {\n console.warn(\n 'batches.createEmbeddings() is experimental and may change without notice.',\n );\n\n if (this.apiClient.isVertexAI()) {\n throw new Error('Vertex AI does not support batches.createEmbeddings.');\n }\n\n return this.createEmbeddingsInternal(params);\n };\n\n // Helper function to handle inlined generate content requests\n private createInlinedGenerateContentRequest(\n params: types.CreateBatchJobParameters,\n ): {path: string; body: Record<string, unknown>} {\n const body = converters.createBatchJobParametersToMldev(\n this.apiClient, // Use instance apiClient\n params,\n );\n\n const urlParams = body['_url'] as Record<string, unknown>;\n const path = common.formatMap('{model}:batchGenerateContent', urlParams);\n\n const batch = body['batch'] as {[key: string]: unknown};\n const inputConfig = batch['inputConfig'] as {[key: string]: unknown};\n const requestsWrapper = inputConfig['requests'] as {\n [key: string]: unknown;\n };\n const requests = requestsWrapper['requests'] as Array<{\n [key: string]: unknown;\n }>;\n const newRequests = [];\n\n for (const request of requests) {\n const requestDict = {...request}; // Clone\n if (requestDict['systemInstruction']) {\n const systemInstructionValue = requestDict['systemInstruction'];\n delete requestDict['systemInstruction'];\n const requestContent = requestDict['request'] as {\n [key: string]: unknown;\n };\n requestContent['systemInstruction'] = systemInstructionValue;\n requestDict['request'] = requestContent;\n }\n newRequests.push(requestDict);\n }\n requestsWrapper['requests'] = newRequests;\n\n delete body['config'];\n delete body['_url'];\n delete body['_query'];\n\n return {path, body};\n }\n\n // Helper function to get the first GCS URI\n private getGcsUri(src: string | types.BatchJobSource): string | undefined {\n if (typeof src === 'string') {\n return src.startsWith('gs://') ? src : undefined;\n }\n if (!Array.isArray(src) && src.gcsUri && src.gcsUri.length > 0) {\n return src.gcsUri[0];\n }\n return undefined;\n }\n\n // Helper function to get the BigQuery URI\n private getBigqueryUri(\n src: string | types.BatchJobSource,\n ): string | undefined {\n if (typeof src === 'string') {\n return src.startsWith('bq://') ? src : undefined;\n }\n if (!Array.isArray(src)) {\n return src.bigqueryUri;\n }\n return undefined;\n }\n\n // Function to format the destination configuration for Vertex AI\n private formatDestination(\n src: string | types.BatchJobSource,\n config?: types.CreateBatchJobConfig,\n ): types.CreateBatchJobConfig {\n const newConfig = config ? {...config} : {};\n\n const timestampStr = Date.now().toString();\n\n if (!newConfig.displayName) {\n newConfig.displayName = `genaiBatchJob_${timestampStr}`;\n }\n\n if (newConfig.dest === undefined) {\n const gcsUri = this.getGcsUri(src);\n const bigqueryUri = this.getBigqueryUri(src);\n\n if (gcsUri) {\n if (gcsUri.endsWith('.jsonl')) {\n // For .jsonl files, remove suffix and add /dest\n newConfig.dest = `${gcsUri.slice(0, -6)}/dest`;\n } else {\n // Fallback for other GCS URIs\n newConfig.dest = `${gcsUri}_dest_${timestampStr}`;\n }\n } else if (bigqueryUri) {\n newConfig.dest = `${bigqueryUri}_dest_${timestampStr}`;\n } else {\n throw new Error(\n 'Unsupported source for Vertex AI: No GCS or BigQuery URI found.',\n );\n }\n }\n return newConfig;\n }\n\n /**\n * Internal method to create batch job.\n *\n * @param params - The parameters for create batch job request.\n * @return The created batch job.\n *\n */\n private async createInternal(\n params: types.CreateBatchJobParameters,\n ): Promise<types.BatchJob> {\n let response: Promise<types.BatchJob>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.createBatchJobParametersToVertex(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n 'batchPredictionJobs',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.BatchJob>;\n\n return response.then((apiResponse) => {\n const resp = converters.batchJobFromVertex(apiResponse);\n\n return resp as types.BatchJob;\n });\n } else {\n const body = converters.createBatchJobParametersToMldev(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n '{model}:batchGenerateContent',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.BatchJob>;\n\n return response.then((apiResponse) => {\n const resp = converters.batchJobFromMldev(apiResponse);\n\n return resp as types.BatchJob;\n });\n }\n }\n\n /**\n * Internal method to create batch job.\n *\n * @param params - The parameters for create batch job request.\n * @return The created batch job.\n *\n */\n private async createEmbeddingsInternal(\n params: types.CreateEmbeddingsBatchJobParameters,\n ): Promise<types.BatchJob> {\n let response: Promise<types.BatchJob>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.createEmbeddingsBatchJobParametersToMldev(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n '{model}:asyncBatchEmbedContent',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.BatchJob>;\n\n return response.then((apiResponse) => {\n const resp = converters.batchJobFromMldev(apiResponse);\n\n return resp as types.BatchJob;\n });\n }\n }\n\n /**\n * Gets batch job configurations.\n *\n * @param params - The parameters for the get request.\n * @return The batch job.\n *\n * @example\n * ```ts\n * await ai.batches.get({name: '...'}); // The server-generated resource name.\n * ```\n */\n async get(params: types.GetBatchJobParameters): Promise<types.BatchJob> {\n let response: Promise<types.BatchJob>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.getBatchJobParametersToVertex(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n 'batchPredictionJobs/{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.BatchJob>;\n\n return response.then((apiResponse) => {\n const resp = converters.batchJobFromVertex(apiResponse);\n\n return resp as types.BatchJob;\n });\n } else {\n const body = converters.getBatchJobParametersToMldev(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n 'batches/{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.BatchJob>;\n\n return response.then((apiResponse) => {\n const resp = converters.batchJobFromMldev(apiResponse);\n\n return resp as types.BatchJob;\n });\n }\n }\n\n /**\n * Cancels a batch job.\n *\n * @param params - The parameters for the cancel request.\n * @return The empty response returned by the API.\n *\n * @example\n * ```ts\n * await ai.batches.cancel({name: '...'}); // The server-generated resource name.\n * ```\n */\n async cancel(params: types.CancelBatchJobParameters): Promise<void> {\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.cancelBatchJobParametersToVertex(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n 'batchPredictionJobs/{name}:cancel',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n await this.apiClient.request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n });\n } else {\n const body = converters.cancelBatchJobParametersToMldev(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n 'batches/{name}:cancel',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n await this.apiClient.request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n });\n }\n }\n\n private async listInternal(\n params: types.ListBatchJobsParameters,\n ): Promise<types.ListBatchJobsResponse> {\n let response: Promise<types.ListBatchJobsResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.listBatchJobsParametersToVertex(params);\n path = common.formatMap(\n 'batchPredictionJobs',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.ListBatchJobsResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.ListBatchJobsResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.listBatchJobsResponseFromVertex(apiResponse);\n const typedResp = new types.ListBatchJobsResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n const body = converters.listBatchJobsParametersToMldev(params);\n path = common.formatMap(\n 'batches',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.ListBatchJobsResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.ListBatchJobsResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.listBatchJobsResponseFromMldev(apiResponse);\n const typedResp = new types.ListBatchJobsResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n /**\n * Deletes a batch job.\n *\n * @param params - The parameters for the delete request.\n * @return The empty response returned by the API.\n *\n * @example\n * ```ts\n * await ai.batches.delete({name: '...'}); // The server-generated resource name.\n * ```\n */\n async delete(\n params: types.DeleteBatchJobParameters,\n ): Promise<types.DeleteResourceJob> {\n let response: Promise<types.DeleteResourceJob>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.deleteBatchJobParametersToVertex(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n 'batchPredictionJobs/{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'DELETE',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.DeleteResourceJob;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.DeleteResourceJob>;\n\n return response.then((apiResponse) => {\n const resp = converters.deleteResourceJobFromVertex(apiResponse);\n\n return resp as types.DeleteResourceJob;\n });\n } else {\n const body = converters.deleteBatchJobParametersToMldev(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n 'batches/{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'DELETE',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.DeleteResourceJob;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.DeleteResourceJob>;\n\n return response.then((apiResponse) => {\n const resp = converters.deleteResourceJobFromMldev(apiResponse);\n\n return resp as types.DeleteResourceJob;\n });\n }\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport {ApiClient} from '../_api_client.js';\nimport * as common from '../_common.js';\nimport * as t from '../_transformers.js';\nimport type * as types from '../types.js';\n\nexport function blobToMldev(fromObject: types.Blob): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromData = common.getValueByPath(fromObject, ['data']);\n if (fromData != null) {\n common.setValueByPath(toObject, ['data'], fromData);\n }\n\n if (common.getValueByPath(fromObject, ['displayName']) !== undefined) {\n throw new Error('displayName parameter is not supported in Gemini API.');\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function contentToMldev(\n fromObject: types.Content,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromParts = common.getValueByPath(fromObject, ['parts']);\n if (fromParts != null) {\n let transformedList = fromParts;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return partToMldev(item);\n });\n }\n common.setValueByPath(toObject, ['parts'], transformedList);\n }\n\n const fromRole = common.getValueByPath(fromObject, ['role']);\n if (fromRole != null) {\n common.setValueByPath(toObject, ['role'], fromRole);\n }\n\n return toObject;\n}\n\nexport function createCachedContentConfigToMldev(\n fromObject: types.CreateCachedContentConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromTtl = common.getValueByPath(fromObject, ['ttl']);\n if (parentObject !== undefined && fromTtl != null) {\n common.setValueByPath(parentObject, ['ttl'], fromTtl);\n }\n\n const fromExpireTime = common.getValueByPath(fromObject, ['expireTime']);\n if (parentObject !== undefined && fromExpireTime != null) {\n common.setValueByPath(parentObject, ['expireTime'], fromExpireTime);\n }\n\n const fromDisplayName = common.getValueByPath(fromObject, ['displayName']);\n if (parentObject !== undefined && fromDisplayName != null) {\n common.setValueByPath(parentObject, ['displayName'], fromDisplayName);\n }\n\n const fromContents = common.getValueByPath(fromObject, ['contents']);\n if (parentObject !== undefined && fromContents != null) {\n let transformedList = t.tContents(fromContents);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return contentToMldev(item);\n });\n }\n common.setValueByPath(parentObject, ['contents'], transformedList);\n }\n\n const fromSystemInstruction = common.getValueByPath(fromObject, [\n 'systemInstruction',\n ]);\n if (parentObject !== undefined && fromSystemInstruction != null) {\n common.setValueByPath(\n parentObject,\n ['systemInstruction'],\n contentToMldev(t.tContent(fromSystemInstruction)),\n );\n }\n\n const fromTools = common.getValueByPath(fromObject, ['tools']);\n if (parentObject !== undefined && fromTools != null) {\n let transformedList = fromTools;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return toolToMldev(item);\n });\n }\n common.setValueByPath(parentObject, ['tools'], transformedList);\n }\n\n const fromToolConfig = common.getValueByPath(fromObject, ['toolConfig']);\n if (parentObject !== undefined && fromToolConfig != null) {\n common.setValueByPath(\n parentObject,\n ['toolConfig'],\n toolConfigToMldev(fromToolConfig),\n );\n }\n\n if (common.getValueByPath(fromObject, ['kmsKeyName']) !== undefined) {\n throw new Error('kmsKeyName parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function createCachedContentConfigToVertex(\n fromObject: types.CreateCachedContentConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromTtl = common.getValueByPath(fromObject, ['ttl']);\n if (parentObject !== undefined && fromTtl != null) {\n common.setValueByPath(parentObject, ['ttl'], fromTtl);\n }\n\n const fromExpireTime = common.getValueByPath(fromObject, ['expireTime']);\n if (parentObject !== undefined && fromExpireTime != null) {\n common.setValueByPath(parentObject, ['expireTime'], fromExpireTime);\n }\n\n const fromDisplayName = common.getValueByPath(fromObject, ['displayName']);\n if (parentObject !== undefined && fromDisplayName != null) {\n common.setValueByPath(parentObject, ['displayName'], fromDisplayName);\n }\n\n const fromContents = common.getValueByPath(fromObject, ['contents']);\n if (parentObject !== undefined && fromContents != null) {\n let transformedList = t.tContents(fromContents);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(parentObject, ['contents'], transformedList);\n }\n\n const fromSystemInstruction = common.getValueByPath(fromObject, [\n 'systemInstruction',\n ]);\n if (parentObject !== undefined && fromSystemInstruction != null) {\n common.setValueByPath(\n parentObject,\n ['systemInstruction'],\n t.tContent(fromSystemInstruction),\n );\n }\n\n const fromTools = common.getValueByPath(fromObject, ['tools']);\n if (parentObject !== undefined && fromTools != null) {\n let transformedList = fromTools;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return toolToVertex(item);\n });\n }\n common.setValueByPath(parentObject, ['tools'], transformedList);\n }\n\n const fromToolConfig = common.getValueByPath(fromObject, ['toolConfig']);\n if (parentObject !== undefined && fromToolConfig != null) {\n common.setValueByPath(parentObject, ['toolConfig'], fromToolConfig);\n }\n\n const fromKmsKeyName = common.getValueByPath(fromObject, ['kmsKeyName']);\n if (parentObject !== undefined && fromKmsKeyName != null) {\n common.setValueByPath(\n parentObject,\n ['encryption_spec', 'kmsKeyName'],\n fromKmsKeyName,\n );\n }\n\n return toObject;\n}\n\nexport function createCachedContentParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.CreateCachedContentParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['model'],\n t.tCachesModel(apiClient, fromModel),\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n createCachedContentConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function createCachedContentParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.CreateCachedContentParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['model'],\n t.tCachesModel(apiClient, fromModel),\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n createCachedContentConfigToVertex(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function deleteCachedContentParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.DeleteCachedContentParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tCachedContentName(apiClient, fromName),\n );\n }\n\n return toObject;\n}\n\nexport function deleteCachedContentParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.DeleteCachedContentParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tCachedContentName(apiClient, fromName),\n );\n }\n\n return toObject;\n}\n\nexport function deleteCachedContentResponseFromMldev(\n fromObject: types.DeleteCachedContentResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n return toObject;\n}\n\nexport function deleteCachedContentResponseFromVertex(\n fromObject: types.DeleteCachedContentResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n return toObject;\n}\n\nexport function fileDataToMldev(\n fromObject: types.FileData,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['displayName']) !== undefined) {\n throw new Error('displayName parameter is not supported in Gemini API.');\n }\n\n const fromFileUri = common.getValueByPath(fromObject, ['fileUri']);\n if (fromFileUri != null) {\n common.setValueByPath(toObject, ['fileUri'], fromFileUri);\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function functionCallToMldev(\n fromObject: types.FunctionCall,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromId = common.getValueByPath(fromObject, ['id']);\n if (fromId != null) {\n common.setValueByPath(toObject, ['id'], fromId);\n }\n\n const fromArgs = common.getValueByPath(fromObject, ['args']);\n if (fromArgs != null) {\n common.setValueByPath(toObject, ['args'], fromArgs);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n if (common.getValueByPath(fromObject, ['partialArgs']) !== undefined) {\n throw new Error('partialArgs parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['willContinue']) !== undefined) {\n throw new Error('willContinue parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function functionCallingConfigToMldev(\n fromObject: types.FunctionCallingConfig,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromAllowedFunctionNames = common.getValueByPath(fromObject, [\n 'allowedFunctionNames',\n ]);\n if (fromAllowedFunctionNames != null) {\n common.setValueByPath(\n toObject,\n ['allowedFunctionNames'],\n fromAllowedFunctionNames,\n );\n }\n\n const fromMode = common.getValueByPath(fromObject, ['mode']);\n if (fromMode != null) {\n common.setValueByPath(toObject, ['mode'], fromMode);\n }\n\n if (\n common.getValueByPath(fromObject, ['streamFunctionCallArguments']) !==\n undefined\n ) {\n throw new Error(\n 'streamFunctionCallArguments parameter is not supported in Gemini API.',\n );\n }\n\n return toObject;\n}\n\nexport function functionDeclarationToVertex(\n fromObject: types.FunctionDeclaration,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromDescription = common.getValueByPath(fromObject, ['description']);\n if (fromDescription != null) {\n common.setValueByPath(toObject, ['description'], fromDescription);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromParameters = common.getValueByPath(fromObject, ['parameters']);\n if (fromParameters != null) {\n common.setValueByPath(toObject, ['parameters'], fromParameters);\n }\n\n const fromParametersJsonSchema = common.getValueByPath(fromObject, [\n 'parametersJsonSchema',\n ]);\n if (fromParametersJsonSchema != null) {\n common.setValueByPath(\n toObject,\n ['parametersJsonSchema'],\n fromParametersJsonSchema,\n );\n }\n\n const fromResponse = common.getValueByPath(fromObject, ['response']);\n if (fromResponse != null) {\n common.setValueByPath(toObject, ['response'], fromResponse);\n }\n\n const fromResponseJsonSchema = common.getValueByPath(fromObject, [\n 'responseJsonSchema',\n ]);\n if (fromResponseJsonSchema != null) {\n common.setValueByPath(\n toObject,\n ['responseJsonSchema'],\n fromResponseJsonSchema,\n );\n }\n\n if (common.getValueByPath(fromObject, ['behavior']) !== undefined) {\n throw new Error('behavior parameter is not supported in Vertex AI.');\n }\n\n return toObject;\n}\n\nexport function getCachedContentParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.GetCachedContentParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tCachedContentName(apiClient, fromName),\n );\n }\n\n return toObject;\n}\n\nexport function getCachedContentParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.GetCachedContentParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tCachedContentName(apiClient, fromName),\n );\n }\n\n return toObject;\n}\n\nexport function googleMapsToMldev(\n fromObject: types.GoogleMaps,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['authConfig']) !== undefined) {\n throw new Error('authConfig parameter is not supported in Gemini API.');\n }\n\n const fromEnableWidget = common.getValueByPath(fromObject, ['enableWidget']);\n if (fromEnableWidget != null) {\n common.setValueByPath(toObject, ['enableWidget'], fromEnableWidget);\n }\n\n return toObject;\n}\n\nexport function googleSearchToMldev(\n fromObject: types.GoogleSearch,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['excludeDomains']) !== undefined) {\n throw new Error('excludeDomains parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['blockingConfidence']) !== undefined) {\n throw new Error(\n 'blockingConfidence parameter is not supported in Gemini API.',\n );\n }\n\n const fromTimeRangeFilter = common.getValueByPath(fromObject, [\n 'timeRangeFilter',\n ]);\n if (fromTimeRangeFilter != null) {\n common.setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter);\n }\n\n return toObject;\n}\n\nexport function listCachedContentsConfigToMldev(\n fromObject: types.ListCachedContentsConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPageSize = common.getValueByPath(fromObject, ['pageSize']);\n if (parentObject !== undefined && fromPageSize != null) {\n common.setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize);\n }\n\n const fromPageToken = common.getValueByPath(fromObject, ['pageToken']);\n if (parentObject !== undefined && fromPageToken != null) {\n common.setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken);\n }\n\n return toObject;\n}\n\nexport function listCachedContentsConfigToVertex(\n fromObject: types.ListCachedContentsConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPageSize = common.getValueByPath(fromObject, ['pageSize']);\n if (parentObject !== undefined && fromPageSize != null) {\n common.setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize);\n }\n\n const fromPageToken = common.getValueByPath(fromObject, ['pageToken']);\n if (parentObject !== undefined && fromPageToken != null) {\n common.setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken);\n }\n\n return toObject;\n}\n\nexport function listCachedContentsParametersToMldev(\n fromObject: types.ListCachedContentsParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n listCachedContentsConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function listCachedContentsParametersToVertex(\n fromObject: types.ListCachedContentsParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n listCachedContentsConfigToVertex(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function listCachedContentsResponseFromMldev(\n fromObject: types.ListCachedContentsResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromNextPageToken = common.getValueByPath(fromObject, [\n 'nextPageToken',\n ]);\n if (fromNextPageToken != null) {\n common.setValueByPath(toObject, ['nextPageToken'], fromNextPageToken);\n }\n\n const fromCachedContents = common.getValueByPath(fromObject, [\n 'cachedContents',\n ]);\n if (fromCachedContents != null) {\n let transformedList = fromCachedContents;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['cachedContents'], transformedList);\n }\n\n return toObject;\n}\n\nexport function listCachedContentsResponseFromVertex(\n fromObject: types.ListCachedContentsResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromNextPageToken = common.getValueByPath(fromObject, [\n 'nextPageToken',\n ]);\n if (fromNextPageToken != null) {\n common.setValueByPath(toObject, ['nextPageToken'], fromNextPageToken);\n }\n\n const fromCachedContents = common.getValueByPath(fromObject, [\n 'cachedContents',\n ]);\n if (fromCachedContents != null) {\n let transformedList = fromCachedContents;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['cachedContents'], transformedList);\n }\n\n return toObject;\n}\n\nexport function partToMldev(fromObject: types.Part): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (fromMediaResolution != null) {\n common.setValueByPath(toObject, ['mediaResolution'], fromMediaResolution);\n }\n\n const fromCodeExecutionResult = common.getValueByPath(fromObject, [\n 'codeExecutionResult',\n ]);\n if (fromCodeExecutionResult != null) {\n common.setValueByPath(\n toObject,\n ['codeExecutionResult'],\n fromCodeExecutionResult,\n );\n }\n\n const fromExecutableCode = common.getValueByPath(fromObject, [\n 'executableCode',\n ]);\n if (fromExecutableCode != null) {\n common.setValueByPath(toObject, ['executableCode'], fromExecutableCode);\n }\n\n const fromFileData = common.getValueByPath(fromObject, ['fileData']);\n if (fromFileData != null) {\n common.setValueByPath(\n toObject,\n ['fileData'],\n fileDataToMldev(fromFileData),\n );\n }\n\n const fromFunctionCall = common.getValueByPath(fromObject, ['functionCall']);\n if (fromFunctionCall != null) {\n common.setValueByPath(\n toObject,\n ['functionCall'],\n functionCallToMldev(fromFunctionCall),\n );\n }\n\n const fromFunctionResponse = common.getValueByPath(fromObject, [\n 'functionResponse',\n ]);\n if (fromFunctionResponse != null) {\n common.setValueByPath(toObject, ['functionResponse'], fromFunctionResponse);\n }\n\n const fromInlineData = common.getValueByPath(fromObject, ['inlineData']);\n if (fromInlineData != null) {\n common.setValueByPath(\n toObject,\n ['inlineData'],\n blobToMldev(fromInlineData),\n );\n }\n\n const fromText = common.getValueByPath(fromObject, ['text']);\n if (fromText != null) {\n common.setValueByPath(toObject, ['text'], fromText);\n }\n\n const fromThought = common.getValueByPath(fromObject, ['thought']);\n if (fromThought != null) {\n common.setValueByPath(toObject, ['thought'], fromThought);\n }\n\n const fromThoughtSignature = common.getValueByPath(fromObject, [\n 'thoughtSignature',\n ]);\n if (fromThoughtSignature != null) {\n common.setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature);\n }\n\n const fromVideoMetadata = common.getValueByPath(fromObject, [\n 'videoMetadata',\n ]);\n if (fromVideoMetadata != null) {\n common.setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata);\n }\n\n return toObject;\n}\n\nexport function toolConfigToMldev(\n fromObject: types.ToolConfig,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromRetrievalConfig = common.getValueByPath(fromObject, [\n 'retrievalConfig',\n ]);\n if (fromRetrievalConfig != null) {\n common.setValueByPath(toObject, ['retrievalConfig'], fromRetrievalConfig);\n }\n\n const fromFunctionCallingConfig = common.getValueByPath(fromObject, [\n 'functionCallingConfig',\n ]);\n if (fromFunctionCallingConfig != null) {\n common.setValueByPath(\n toObject,\n ['functionCallingConfig'],\n functionCallingConfigToMldev(fromFunctionCallingConfig),\n );\n }\n\n return toObject;\n}\n\nexport function toolToMldev(fromObject: types.Tool): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['retrieval']) !== undefined) {\n throw new Error('retrieval parameter is not supported in Gemini API.');\n }\n\n const fromComputerUse = common.getValueByPath(fromObject, ['computerUse']);\n if (fromComputerUse != null) {\n common.setValueByPath(toObject, ['computerUse'], fromComputerUse);\n }\n\n const fromFileSearch = common.getValueByPath(fromObject, ['fileSearch']);\n if (fromFileSearch != null) {\n common.setValueByPath(toObject, ['fileSearch'], fromFileSearch);\n }\n\n const fromCodeExecution = common.getValueByPath(fromObject, [\n 'codeExecution',\n ]);\n if (fromCodeExecution != null) {\n common.setValueByPath(toObject, ['codeExecution'], fromCodeExecution);\n }\n\n if (\n common.getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined\n ) {\n throw new Error(\n 'enterpriseWebSearch parameter is not supported in Gemini API.',\n );\n }\n\n const fromFunctionDeclarations = common.getValueByPath(fromObject, [\n 'functionDeclarations',\n ]);\n if (fromFunctionDeclarations != null) {\n let transformedList = fromFunctionDeclarations;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['functionDeclarations'], transformedList);\n }\n\n const fromGoogleMaps = common.getValueByPath(fromObject, ['googleMaps']);\n if (fromGoogleMaps != null) {\n common.setValueByPath(\n toObject,\n ['googleMaps'],\n googleMapsToMldev(fromGoogleMaps),\n );\n }\n\n const fromGoogleSearch = common.getValueByPath(fromObject, ['googleSearch']);\n if (fromGoogleSearch != null) {\n common.setValueByPath(\n toObject,\n ['googleSearch'],\n googleSearchToMldev(fromGoogleSearch),\n );\n }\n\n const fromGoogleSearchRetrieval = common.getValueByPath(fromObject, [\n 'googleSearchRetrieval',\n ]);\n if (fromGoogleSearchRetrieval != null) {\n common.setValueByPath(\n toObject,\n ['googleSearchRetrieval'],\n fromGoogleSearchRetrieval,\n );\n }\n\n const fromUrlContext = common.getValueByPath(fromObject, ['urlContext']);\n if (fromUrlContext != null) {\n common.setValueByPath(toObject, ['urlContext'], fromUrlContext);\n }\n\n return toObject;\n}\n\nexport function toolToVertex(fromObject: types.Tool): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromRetrieval = common.getValueByPath(fromObject, ['retrieval']);\n if (fromRetrieval != null) {\n common.setValueByPath(toObject, ['retrieval'], fromRetrieval);\n }\n\n const fromComputerUse = common.getValueByPath(fromObject, ['computerUse']);\n if (fromComputerUse != null) {\n common.setValueByPath(toObject, ['computerUse'], fromComputerUse);\n }\n\n if (common.getValueByPath(fromObject, ['fileSearch']) !== undefined) {\n throw new Error('fileSearch parameter is not supported in Vertex AI.');\n }\n\n const fromCodeExecution = common.getValueByPath(fromObject, [\n 'codeExecution',\n ]);\n if (fromCodeExecution != null) {\n common.setValueByPath(toObject, ['codeExecution'], fromCodeExecution);\n }\n\n const fromEnterpriseWebSearch = common.getValueByPath(fromObject, [\n 'enterpriseWebSearch',\n ]);\n if (fromEnterpriseWebSearch != null) {\n common.setValueByPath(\n toObject,\n ['enterpriseWebSearch'],\n fromEnterpriseWebSearch,\n );\n }\n\n const fromFunctionDeclarations = common.getValueByPath(fromObject, [\n 'functionDeclarations',\n ]);\n if (fromFunctionDeclarations != null) {\n let transformedList = fromFunctionDeclarations;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return functionDeclarationToVertex(item);\n });\n }\n common.setValueByPath(toObject, ['functionDeclarations'], transformedList);\n }\n\n const fromGoogleMaps = common.getValueByPath(fromObject, ['googleMaps']);\n if (fromGoogleMaps != null) {\n common.setValueByPath(toObject, ['googleMaps'], fromGoogleMaps);\n }\n\n const fromGoogleSearch = common.getValueByPath(fromObject, ['googleSearch']);\n if (fromGoogleSearch != null) {\n common.setValueByPath(toObject, ['googleSearch'], fromGoogleSearch);\n }\n\n const fromGoogleSearchRetrieval = common.getValueByPath(fromObject, [\n 'googleSearchRetrieval',\n ]);\n if (fromGoogleSearchRetrieval != null) {\n common.setValueByPath(\n toObject,\n ['googleSearchRetrieval'],\n fromGoogleSearchRetrieval,\n );\n }\n\n const fromUrlContext = common.getValueByPath(fromObject, ['urlContext']);\n if (fromUrlContext != null) {\n common.setValueByPath(toObject, ['urlContext'], fromUrlContext);\n }\n\n return toObject;\n}\n\nexport function updateCachedContentConfigToMldev(\n fromObject: types.UpdateCachedContentConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromTtl = common.getValueByPath(fromObject, ['ttl']);\n if (parentObject !== undefined && fromTtl != null) {\n common.setValueByPath(parentObject, ['ttl'], fromTtl);\n }\n\n const fromExpireTime = common.getValueByPath(fromObject, ['expireTime']);\n if (parentObject !== undefined && fromExpireTime != null) {\n common.setValueByPath(parentObject, ['expireTime'], fromExpireTime);\n }\n\n return toObject;\n}\n\nexport function updateCachedContentConfigToVertex(\n fromObject: types.UpdateCachedContentConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromTtl = common.getValueByPath(fromObject, ['ttl']);\n if (parentObject !== undefined && fromTtl != null) {\n common.setValueByPath(parentObject, ['ttl'], fromTtl);\n }\n\n const fromExpireTime = common.getValueByPath(fromObject, ['expireTime']);\n if (parentObject !== undefined && fromExpireTime != null) {\n common.setValueByPath(parentObject, ['expireTime'], fromExpireTime);\n }\n\n return toObject;\n}\n\nexport function updateCachedContentParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.UpdateCachedContentParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tCachedContentName(apiClient, fromName),\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n updateCachedContentConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function updateCachedContentParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.UpdateCachedContentParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tCachedContentName(apiClient, fromName),\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n updateCachedContentConfigToVertex(fromConfig, toObject);\n }\n\n return toObject;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport {ApiClient} from './_api_client.js';\nimport * as common from './_common.js';\nimport {BaseModule} from './_common.js';\nimport * as converters from './converters/_caches_converters.js';\nimport {PagedItem, Pager} from './pagers.js';\nimport * as types from './types.js';\n\nexport class Caches extends BaseModule {\n constructor(private readonly apiClient: ApiClient) {\n super();\n }\n\n /**\n * Lists cached contents.\n *\n * @param params - The parameters for the list request.\n * @return - A pager of cached contents.\n *\n * @example\n * ```ts\n * const cachedContents = await ai.caches.list({config: {'pageSize': 2}});\n * for await (const cachedContent of cachedContents) {\n * console.log(cachedContent);\n * }\n * ```\n */\n list = async (\n params: types.ListCachedContentsParameters = {},\n ): Promise<Pager<types.CachedContent>> => {\n return new Pager<types.CachedContent>(\n PagedItem.PAGED_ITEM_CACHED_CONTENTS,\n (x: types.ListCachedContentsParameters) => this.listInternal(x),\n await this.listInternal(params),\n params,\n );\n };\n\n /**\n * Creates a cached contents resource.\n *\n * @remarks\n * Context caching is only supported for specific models. See [Gemini\n * Developer API reference](https://ai.google.dev/gemini-api/docs/caching?lang=node/context-cac)\n * and [Vertex AI reference](https://cloud.google.com/vertex-ai/generative-ai/docs/context-cache/context-cache-overview#supported_models)\n * for more information.\n *\n * @param params - The parameters for the create request.\n * @return The created cached content.\n *\n * @example\n * ```ts\n * const contents = ...; // Initialize the content to cache.\n * const response = await ai.caches.create({\n * model: 'gemini-2.0-flash-001',\n * config: {\n * 'contents': contents,\n * 'displayName': 'test cache',\n * 'systemInstruction': 'What is the sum of the two pdfs?',\n * 'ttl': '86400s',\n * }\n * });\n * ```\n */\n async create(\n params: types.CreateCachedContentParameters,\n ): Promise<types.CachedContent> {\n let response: Promise<types.CachedContent>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.createCachedContentParametersToVertex(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n 'cachedContents',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.CachedContent>;\n\n return response.then((resp) => {\n return resp as types.CachedContent;\n });\n } else {\n const body = converters.createCachedContentParametersToMldev(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n 'cachedContents',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.CachedContent>;\n\n return response.then((resp) => {\n return resp as types.CachedContent;\n });\n }\n }\n\n /**\n * Gets cached content configurations.\n *\n * @param params - The parameters for the get request.\n * @return The cached content.\n *\n * @example\n * ```ts\n * await ai.caches.get({name: '...'}); // The server-generated resource name.\n * ```\n */\n async get(\n params: types.GetCachedContentParameters,\n ): Promise<types.CachedContent> {\n let response: Promise<types.CachedContent>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.getCachedContentParametersToVertex(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.CachedContent>;\n\n return response.then((resp) => {\n return resp as types.CachedContent;\n });\n } else {\n const body = converters.getCachedContentParametersToMldev(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.CachedContent>;\n\n return response.then((resp) => {\n return resp as types.CachedContent;\n });\n }\n }\n\n /**\n * Deletes cached content.\n *\n * @param params - The parameters for the delete request.\n * @return The empty response returned by the API.\n *\n * @example\n * ```ts\n * await ai.caches.delete({name: '...'}); // The server-generated resource name.\n * ```\n */\n async delete(\n params: types.DeleteCachedContentParameters,\n ): Promise<types.DeleteCachedContentResponse> {\n let response: Promise<types.DeleteCachedContentResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.deleteCachedContentParametersToVertex(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'DELETE',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.DeleteCachedContentResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.DeleteCachedContentResponse>;\n\n return response.then((apiResponse) => {\n const resp =\n converters.deleteCachedContentResponseFromVertex(apiResponse);\n const typedResp = new types.DeleteCachedContentResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n const body = converters.deleteCachedContentParametersToMldev(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'DELETE',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.DeleteCachedContentResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.DeleteCachedContentResponse>;\n\n return response.then((apiResponse) => {\n const resp =\n converters.deleteCachedContentResponseFromMldev(apiResponse);\n const typedResp = new types.DeleteCachedContentResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n /**\n * Updates cached content configurations.\n *\n * @param params - The parameters for the update request.\n * @return The updated cached content.\n *\n * @example\n * ```ts\n * const response = await ai.caches.update({\n * name: '...', // The server-generated resource name.\n * config: {'ttl': '7600s'}\n * });\n * ```\n */\n async update(\n params: types.UpdateCachedContentParameters,\n ): Promise<types.CachedContent> {\n let response: Promise<types.CachedContent>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.updateCachedContentParametersToVertex(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'PATCH',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.CachedContent>;\n\n return response.then((resp) => {\n return resp as types.CachedContent;\n });\n } else {\n const body = converters.updateCachedContentParametersToMldev(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'PATCH',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.CachedContent>;\n\n return response.then((resp) => {\n return resp as types.CachedContent;\n });\n }\n }\n\n private async listInternal(\n params: types.ListCachedContentsParameters,\n ): Promise<types.ListCachedContentsResponse> {\n let response: Promise<types.ListCachedContentsResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.listCachedContentsParametersToVertex(params);\n path = common.formatMap(\n 'cachedContents',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.ListCachedContentsResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.ListCachedContentsResponse>;\n\n return response.then((apiResponse) => {\n const resp =\n converters.listCachedContentsResponseFromVertex(apiResponse);\n const typedResp = new types.ListCachedContentsResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n const body = converters.listCachedContentsParametersToMldev(params);\n path = common.formatMap(\n 'cachedContents',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.ListCachedContentsResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.ListCachedContentsResponse>;\n\n return response.then((apiResponse) => {\n const resp =\n converters.listCachedContentsResponseFromMldev(apiResponse);\n const typedResp = new types.ListCachedContentsResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {ApiClient} from './_api_client.js';\nimport * as t from './_transformers.js';\nimport {Models} from './models.js';\nimport * as types from './types.js';\n\n/**\n * Returns true if the response is valid, false otherwise.\n */\nfunction isValidResponse(response: types.GenerateContentResponse): boolean {\n if (response.candidates == undefined || response.candidates.length === 0) {\n return false;\n }\n const content = response.candidates[0]?.content;\n if (content === undefined) {\n return false;\n }\n return isValidContent(content);\n}\n\nfunction isValidContent(content: types.Content): boolean {\n if (content.parts === undefined || content.parts.length === 0) {\n return false;\n }\n for (const part of content.parts) {\n if (part === undefined || Object.keys(part).length === 0) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * Validates the history contains the correct roles.\n *\n * @throws Error if the history does not start with a user turn.\n * @throws Error if the history contains an invalid role.\n */\nfunction validateHistory(history: types.Content[]) {\n // Empty history is valid.\n if (history.length === 0) {\n return;\n }\n for (const content of history) {\n if (content.role !== 'user' && content.role !== 'model') {\n throw new Error(`Role must be user or model, but got ${content.role}.`);\n }\n }\n}\n\n/**\n * Extracts the curated (valid) history from a comprehensive history.\n *\n * @remarks\n * The model may sometimes generate invalid or empty contents(e.g., due to safty\n * filters or recitation). Extracting valid turns from the history\n * ensures that subsequent requests could be accpeted by the model.\n */\nfunction extractCuratedHistory(\n comprehensiveHistory: types.Content[],\n): types.Content[] {\n if (comprehensiveHistory === undefined || comprehensiveHistory.length === 0) {\n return [];\n }\n const curatedHistory: types.Content[] = [];\n const length = comprehensiveHistory.length;\n let i = 0;\n while (i < length) {\n if (comprehensiveHistory[i].role === 'user') {\n curatedHistory.push(comprehensiveHistory[i]);\n i++;\n } else {\n const modelOutput: types.Content[] = [];\n let isValid = true;\n while (i < length && comprehensiveHistory[i].role === 'model') {\n modelOutput.push(comprehensiveHistory[i]);\n if (isValid && !isValidContent(comprehensiveHistory[i])) {\n isValid = false;\n }\n i++;\n }\n if (isValid) {\n curatedHistory.push(...modelOutput);\n } else {\n // Remove the last user input when model content is invalid.\n curatedHistory.pop();\n }\n }\n }\n return curatedHistory;\n}\n\n/**\n * A utility class to create a chat session.\n */\nexport class Chats {\n private readonly modelsModule: Models;\n private readonly apiClient: ApiClient;\n\n constructor(modelsModule: Models, apiClient: ApiClient) {\n this.modelsModule = modelsModule;\n this.apiClient = apiClient;\n }\n\n /**\n * Creates a new chat session.\n *\n * @remarks\n * The config in the params will be used for all requests within the chat\n * session unless overridden by a per-request `config` in\n * @see {@link types.SendMessageParameters#config}.\n *\n * @param params - Parameters for creating a chat session.\n * @returns A new chat session.\n *\n * @example\n * ```ts\n * const chat = ai.chats.create({\n * model: 'gemini-2.0-flash'\n * config: {\n * temperature: 0.5,\n * maxOutputTokens: 1024,\n * }\n * });\n * ```\n */\n create(params: types.CreateChatParameters) {\n return new Chat(\n this.apiClient,\n this.modelsModule,\n params.model,\n params.config,\n // Deep copy the history to avoid mutating the history outside of the\n // chat session.\n structuredClone(params.history),\n );\n }\n}\n\n/**\n * Chat session that enables sending messages to the model with previous\n * conversation context.\n *\n * @remarks\n * The session maintains all the turns between user and model.\n */\nexport class Chat {\n // A promise to represent the current state of the message being sent to the\n // model.\n private sendPromise: Promise<void> = Promise.resolve();\n\n constructor(\n private readonly apiClient: ApiClient,\n private readonly modelsModule: Models,\n private readonly model: string,\n private readonly config: types.GenerateContentConfig = {},\n private history: types.Content[] = [],\n ) {\n validateHistory(history);\n }\n\n /**\n * Sends a message to the model and returns the response.\n *\n * @remarks\n * This method will wait for the previous message to be processed before\n * sending the next message.\n *\n * @see {@link Chat#sendMessageStream} for streaming method.\n * @param params - parameters for sending messages within a chat session.\n * @returns The model's response.\n *\n * @example\n * ```ts\n * const chat = ai.chats.create({model: 'gemini-2.0-flash'});\n * const response = await chat.sendMessage({\n * message: 'Why is the sky blue?'\n * });\n * console.log(response.text);\n * ```\n */\n async sendMessage(\n params: types.SendMessageParameters,\n ): Promise<types.GenerateContentResponse> {\n await this.sendPromise;\n const inputContent = t.tContent(params.message);\n const responsePromise = this.modelsModule.generateContent({\n model: this.model,\n contents: this.getHistory(true).concat(inputContent),\n config: params.config ?? this.config,\n });\n this.sendPromise = (async () => {\n const response = await responsePromise;\n const outputContent = response.candidates?.[0]?.content;\n\n // Because the AFC input contains the entire curated chat history in\n // addition to the new user input, we need to truncate the AFC history\n // to deduplicate the existing chat history.\n const fullAutomaticFunctionCallingHistory =\n response.automaticFunctionCallingHistory;\n const index = this.getHistory(true).length;\n\n let automaticFunctionCallingHistory: types.Content[] = [];\n if (fullAutomaticFunctionCallingHistory != null) {\n automaticFunctionCallingHistory =\n fullAutomaticFunctionCallingHistory.slice(index) ?? [];\n }\n\n const modelOutput = outputContent ? [outputContent] : [];\n this.recordHistory(\n inputContent,\n modelOutput,\n automaticFunctionCallingHistory,\n );\n return;\n })();\n await this.sendPromise.catch(() => {\n // Resets sendPromise to avoid subsequent calls failing\n this.sendPromise = Promise.resolve();\n });\n return responsePromise;\n }\n\n /**\n * Sends a message to the model and returns the response in chunks.\n *\n * @remarks\n * This method will wait for the previous message to be processed before\n * sending the next message.\n *\n * @see {@link Chat#sendMessage} for non-streaming method.\n * @param params - parameters for sending the message.\n * @return The model's response.\n *\n * @example\n * ```ts\n * const chat = ai.chats.create({model: 'gemini-2.0-flash'});\n * const response = await chat.sendMessageStream({\n * message: 'Why is the sky blue?'\n * });\n * for await (const chunk of response) {\n * console.log(chunk.text);\n * }\n * ```\n */\n async sendMessageStream(\n params: types.SendMessageParameters,\n ): Promise<AsyncGenerator<types.GenerateContentResponse>> {\n await this.sendPromise;\n const inputContent = t.tContent(params.message);\n const streamResponse = this.modelsModule.generateContentStream({\n model: this.model,\n contents: this.getHistory(true).concat(inputContent),\n config: params.config ?? this.config,\n });\n // Resolve the internal tracking of send completion promise - `sendPromise`\n // for both success and failure response. The actual failure is still\n // propagated by the `await streamResponse`.\n this.sendPromise = streamResponse\n .then(() => undefined)\n .catch(() => undefined);\n const response = await streamResponse;\n const result = this.processStreamResponse(response, inputContent);\n return result;\n }\n\n /**\n * Returns the chat history.\n *\n * @remarks\n * The history is a list of contents alternating between user and model.\n *\n * There are two types of history:\n * - The `curated history` contains only the valid turns between user and\n * model, which will be included in the subsequent requests sent to the model.\n * - The `comprehensive history` contains all turns, including invalid or\n * empty model outputs, providing a complete record of the history.\n *\n * The history is updated after receiving the response from the model,\n * for streaming response, it means receiving the last chunk of the response.\n *\n * The `comprehensive history` is returned by default. To get the `curated\n * history`, set the `curated` parameter to `true`.\n *\n * @param curated - whether to return the curated history or the comprehensive\n * history.\n * @return History contents alternating between user and model for the entire\n * chat session.\n */\n getHistory(curated: boolean = false): types.Content[] {\n const history = curated\n ? extractCuratedHistory(this.history)\n : this.history;\n // Deep copy the history to avoid mutating the history outside of the\n // chat session.\n return structuredClone(history);\n }\n\n private async *processStreamResponse(\n streamResponse: AsyncGenerator<types.GenerateContentResponse>,\n inputContent: types.Content,\n ) {\n const outputContent: types.Content[] = [];\n for await (const chunk of streamResponse) {\n if (isValidResponse(chunk)) {\n const content = chunk.candidates?.[0]?.content;\n if (content !== undefined) {\n outputContent.push(content);\n }\n }\n yield chunk;\n }\n this.recordHistory(inputContent, outputContent);\n }\n\n private recordHistory(\n userInput: types.Content,\n modelOutput: types.Content[],\n automaticFunctionCallingHistory?: types.Content[],\n ) {\n let outputContents: types.Content[] = [];\n if (\n modelOutput.length > 0 &&\n modelOutput.every((content) => content.role !== undefined)\n ) {\n outputContents = modelOutput;\n } else {\n // Appends an empty content when model returns empty response, so that the\n // history is always alternating between user and model.\n outputContents.push({\n role: 'model',\n parts: [],\n } as types.Content);\n }\n if (\n automaticFunctionCallingHistory &&\n automaticFunctionCallingHistory.length > 0\n ) {\n this.history.push(\n ...extractCuratedHistory(automaticFunctionCallingHistory!),\n );\n } else {\n this.history.push(userInput);\n }\n this.history.push(...outputContents);\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Details for errors from calling the API.\n */\nexport interface ApiErrorInfo {\n /** The error message. */\n message: string;\n /** The HTTP status code. */\n status: number;\n}\n\n/**\n * API errors raised by the GenAI API.\n */\nexport class ApiError extends Error {\n /** HTTP status code */\n status: number;\n\n constructor(options: ApiErrorInfo) {\n super(options.message);\n this.name = 'ApiError';\n this.status = options.status;\n Object.setPrototypeOf(this, ApiError.prototype);\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport * as common from '../_common.js';\nimport * as t from '../_transformers.js';\nimport type * as types from '../types.js';\n\nexport function createFileParametersToMldev(\n fromObject: types.CreateFileParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromFile = common.getValueByPath(fromObject, ['file']);\n if (fromFile != null) {\n common.setValueByPath(toObject, ['file'], fromFile);\n }\n\n return toObject;\n}\n\nexport function createFileResponseFromMldev(\n fromObject: types.CreateFileResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n return toObject;\n}\n\nexport function deleteFileParametersToMldev(\n fromObject: types.DeleteFileParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['_url', 'file'], t.tFileName(fromName));\n }\n\n return toObject;\n}\n\nexport function deleteFileResponseFromMldev(\n fromObject: types.DeleteFileResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n return toObject;\n}\n\nexport function getFileParametersToMldev(\n fromObject: types.GetFileParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['_url', 'file'], t.tFileName(fromName));\n }\n\n return toObject;\n}\n\nexport function internalRegisterFilesParametersToMldev(\n fromObject: types.InternalRegisterFilesParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromUris = common.getValueByPath(fromObject, ['uris']);\n if (fromUris != null) {\n common.setValueByPath(toObject, ['uris'], fromUris);\n }\n\n return toObject;\n}\n\nexport function listFilesConfigToMldev(\n fromObject: types.ListFilesConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPageSize = common.getValueByPath(fromObject, ['pageSize']);\n if (parentObject !== undefined && fromPageSize != null) {\n common.setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize);\n }\n\n const fromPageToken = common.getValueByPath(fromObject, ['pageToken']);\n if (parentObject !== undefined && fromPageToken != null) {\n common.setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken);\n }\n\n return toObject;\n}\n\nexport function listFilesParametersToMldev(\n fromObject: types.ListFilesParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n listFilesConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function listFilesResponseFromMldev(\n fromObject: types.ListFilesResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromNextPageToken = common.getValueByPath(fromObject, [\n 'nextPageToken',\n ]);\n if (fromNextPageToken != null) {\n common.setValueByPath(toObject, ['nextPageToken'], fromNextPageToken);\n }\n\n const fromFiles = common.getValueByPath(fromObject, ['files']);\n if (fromFiles != null) {\n let transformedList = fromFiles;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['files'], transformedList);\n }\n\n return toObject;\n}\n\nexport function registerFilesResponseFromMldev(\n fromObject: types.RegisterFilesResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromFiles = common.getValueByPath(fromObject, ['files']);\n if (fromFiles != null) {\n let transformedList = fromFiles;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['files'], transformedList);\n }\n\n return toObject;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport {ApiClient} from './_api_client.js';\nimport * as common from './_common.js';\nimport {BaseModule} from './_common.js';\nimport * as converters from './converters/_files_converters.js';\nimport {PagedItem, Pager} from './pagers.js';\nimport * as types from './types.js';\n\nexport class Files extends BaseModule {\n constructor(private readonly apiClient: ApiClient) {\n super();\n }\n\n /**\n * Lists files.\n *\n * @param params - The parameters for the list request.\n * @return - A pager of files.\n *\n * @example\n * ```ts\n * const files = await ai.files.list({config: {'pageSize': 2}});\n * for await (const file of files) {\n * console.log(file);\n * }\n * ```\n */\n list = async (\n params: types.ListFilesParameters = {},\n ): Promise<Pager<types.File>> => {\n return new Pager<types.File>(\n PagedItem.PAGED_ITEM_FILES,\n (x: types.ListFilesParameters) => this.listInternal(x),\n await this.listInternal(params),\n params,\n );\n };\n\n /**\n * Uploads a file asynchronously to the Gemini API.\n * This method is not available in Vertex AI.\n * Supported upload sources:\n * - Node.js: File path (string) or Blob object.\n * - Browser: Blob object (e.g., File).\n *\n * @remarks\n * The `mimeType` can be specified in the `config` parameter. If omitted:\n * - For file path (string) inputs, the `mimeType` will be inferred from the\n * file extension.\n * - For Blob object inputs, the `mimeType` will be set to the Blob's `type`\n * property.\n * Somex eamples for file extension to mimeType mapping:\n * .txt -> text/plain\n * .json -> application/json\n * .jpg -> image/jpeg\n * .png -> image/png\n * .mp3 -> audio/mpeg\n * .mp4 -> video/mp4\n *\n * This section can contain multiple paragraphs and code examples.\n *\n * @param params - Optional parameters specified in the\n * `types.UploadFileParameters` interface.\n * @see {@link types.UploadFileParameters#config} for the optional\n * config in the parameters.\n * @return A promise that resolves to a `types.File` object.\n * @throws An error if called on a Vertex AI client.\n * @throws An error if the `mimeType` is not provided and can not be inferred,\n * the `mimeType` can be provided in the `params.config` parameter.\n * @throws An error occurs if a suitable upload location cannot be established.\n *\n * @example\n * The following code uploads a file to Gemini API.\n *\n * ```ts\n * const file = await ai.files.upload({file: 'file.txt', config: {\n * mimeType: 'text/plain',\n * }});\n * console.log(file.name);\n * ```\n */\n async upload(params: types.UploadFileParameters): Promise<types.File> {\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'Vertex AI does not support uploading files. You can share files through a GCS bucket.',\n );\n }\n\n return this.apiClient\n .uploadFile(params.file, params.config)\n .then((resp) => {\n return resp as types.File;\n });\n }\n\n /**\n * Downloads a remotely stored file asynchronously to a location specified in\n * the `params` object. This method only works on Node environment, to\n * download files in the browser, use a browser compliant method like an <a>\n * tag.\n *\n * @param params - The parameters for the download request.\n *\n * @example\n * The following code downloads an example file named \"files/mehozpxf877d\" as\n * \"file.txt\".\n *\n * ```ts\n * await ai.files.download({file: file.name, downloadPath: 'file.txt'});\n * ```\n */\n\n async download(params: types.DownloadFileParameters): Promise<void> {\n await this.apiClient.downloadFile(params);\n }\n\n /**\n * Registers Google Cloud Storage files for use with the API.\n * This method is only available in Node.js environments.\n */\n async registerFiles(\n params: types.RegisterFilesParameters,\n ): Promise<types.RegisterFilesResponse> {\n void params;\n throw new Error('registerFiles is only supported in Node.js environments.');\n }\n\n protected async _registerFiles(\n params: types.InternalRegisterFilesParameters,\n ): Promise<types.RegisterFilesResponse> {\n return this.registerFilesInternal(params);\n }\n\n private async listInternal(\n params: types.ListFilesParameters,\n ): Promise<types.ListFilesResponse> {\n let response: Promise<types.ListFilesResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.listFilesParametersToMldev(params);\n path = common.formatMap('files', body['_url'] as Record<string, unknown>);\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.ListFilesResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.ListFilesResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.listFilesResponseFromMldev(apiResponse);\n const typedResp = new types.ListFilesResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n private async createInternal(\n params: types.CreateFileParameters,\n ): Promise<types.CreateFileResponse> {\n let response: Promise<types.CreateFileResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.createFileParametersToMldev(params);\n path = common.formatMap(\n 'upload/v1beta/files',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.CreateFileResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.createFileResponseFromMldev(apiResponse);\n const typedResp = new types.CreateFileResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n /**\n * Retrieves the file information from the service.\n *\n * @param params - The parameters for the get request\n * @return The Promise that resolves to the types.File object requested.\n *\n * @example\n * ```ts\n * const config: GetFileParameters = {\n * name: fileName,\n * };\n * file = await ai.files.get(config);\n * console.log(file.name);\n * ```\n */\n async get(params: types.GetFileParameters): Promise<types.File> {\n let response: Promise<types.File>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.getFileParametersToMldev(params);\n path = common.formatMap(\n 'files/{file}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.File>;\n\n return response.then((resp) => {\n return resp as types.File;\n });\n }\n }\n\n /**\n * Deletes a remotely stored file.\n *\n * @param params - The parameters for the delete request.\n * @return The DeleteFileResponse, the response for the delete method.\n *\n * @example\n * The following code deletes an example file named \"files/mehozpxf877d\".\n *\n * ```ts\n * await ai.files.delete({name: file.name});\n * ```\n */\n async delete(\n params: types.DeleteFileParameters,\n ): Promise<types.DeleteFileResponse> {\n let response: Promise<types.DeleteFileResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.deleteFileParametersToMldev(params);\n path = common.formatMap(\n 'files/{file}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'DELETE',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.DeleteFileResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.DeleteFileResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.deleteFileResponseFromMldev(apiResponse);\n const typedResp = new types.DeleteFileResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n private async registerFilesInternal(\n params: types.InternalRegisterFilesParameters,\n ): Promise<types.RegisterFilesResponse> {\n let response: Promise<types.RegisterFilesResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.internalRegisterFilesParametersToMldev(params);\n path = common.formatMap(\n 'files:register',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.RegisterFilesResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.registerFilesResponseFromMldev(apiResponse);\n const typedResp = new types.RegisterFilesResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport {ApiClient} from '../_api_client.js';\nimport * as common from '../_common.js';\nimport * as t from '../_transformers.js';\nimport type * as types from '../types.js';\n\nexport function blobToMldev(fromObject: types.Blob): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromData = common.getValueByPath(fromObject, ['data']);\n if (fromData != null) {\n common.setValueByPath(toObject, ['data'], fromData);\n }\n\n if (common.getValueByPath(fromObject, ['displayName']) !== undefined) {\n throw new Error('displayName parameter is not supported in Gemini API.');\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function contentToMldev(\n fromObject: types.Content,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromParts = common.getValueByPath(fromObject, ['parts']);\n if (fromParts != null) {\n let transformedList = fromParts;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return partToMldev(item);\n });\n }\n common.setValueByPath(toObject, ['parts'], transformedList);\n }\n\n const fromRole = common.getValueByPath(fromObject, ['role']);\n if (fromRole != null) {\n common.setValueByPath(toObject, ['role'], fromRole);\n }\n\n return toObject;\n}\n\nexport function fileDataToMldev(\n fromObject: types.FileData,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['displayName']) !== undefined) {\n throw new Error('displayName parameter is not supported in Gemini API.');\n }\n\n const fromFileUri = common.getValueByPath(fromObject, ['fileUri']);\n if (fromFileUri != null) {\n common.setValueByPath(toObject, ['fileUri'], fromFileUri);\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function functionCallToMldev(\n fromObject: types.FunctionCall,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromId = common.getValueByPath(fromObject, ['id']);\n if (fromId != null) {\n common.setValueByPath(toObject, ['id'], fromId);\n }\n\n const fromArgs = common.getValueByPath(fromObject, ['args']);\n if (fromArgs != null) {\n common.setValueByPath(toObject, ['args'], fromArgs);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n if (common.getValueByPath(fromObject, ['partialArgs']) !== undefined) {\n throw new Error('partialArgs parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['willContinue']) !== undefined) {\n throw new Error('willContinue parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function functionDeclarationToVertex(\n fromObject: types.FunctionDeclaration,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromDescription = common.getValueByPath(fromObject, ['description']);\n if (fromDescription != null) {\n common.setValueByPath(toObject, ['description'], fromDescription);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromParameters = common.getValueByPath(fromObject, ['parameters']);\n if (fromParameters != null) {\n common.setValueByPath(toObject, ['parameters'], fromParameters);\n }\n\n const fromParametersJsonSchema = common.getValueByPath(fromObject, [\n 'parametersJsonSchema',\n ]);\n if (fromParametersJsonSchema != null) {\n common.setValueByPath(\n toObject,\n ['parametersJsonSchema'],\n fromParametersJsonSchema,\n );\n }\n\n const fromResponse = common.getValueByPath(fromObject, ['response']);\n if (fromResponse != null) {\n common.setValueByPath(toObject, ['response'], fromResponse);\n }\n\n const fromResponseJsonSchema = common.getValueByPath(fromObject, [\n 'responseJsonSchema',\n ]);\n if (fromResponseJsonSchema != null) {\n common.setValueByPath(\n toObject,\n ['responseJsonSchema'],\n fromResponseJsonSchema,\n );\n }\n\n if (common.getValueByPath(fromObject, ['behavior']) !== undefined) {\n throw new Error('behavior parameter is not supported in Vertex AI.');\n }\n\n return toObject;\n}\n\nexport function generationConfigToVertex(\n fromObject: types.GenerationConfig,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModelSelectionConfig = common.getValueByPath(fromObject, [\n 'modelSelectionConfig',\n ]);\n if (fromModelSelectionConfig != null) {\n common.setValueByPath(toObject, ['modelConfig'], fromModelSelectionConfig);\n }\n\n const fromResponseJsonSchema = common.getValueByPath(fromObject, [\n 'responseJsonSchema',\n ]);\n if (fromResponseJsonSchema != null) {\n common.setValueByPath(\n toObject,\n ['responseJsonSchema'],\n fromResponseJsonSchema,\n );\n }\n\n const fromAudioTimestamp = common.getValueByPath(fromObject, [\n 'audioTimestamp',\n ]);\n if (fromAudioTimestamp != null) {\n common.setValueByPath(toObject, ['audioTimestamp'], fromAudioTimestamp);\n }\n\n const fromCandidateCount = common.getValueByPath(fromObject, [\n 'candidateCount',\n ]);\n if (fromCandidateCount != null) {\n common.setValueByPath(toObject, ['candidateCount'], fromCandidateCount);\n }\n\n const fromEnableAffectiveDialog = common.getValueByPath(fromObject, [\n 'enableAffectiveDialog',\n ]);\n if (fromEnableAffectiveDialog != null) {\n common.setValueByPath(\n toObject,\n ['enableAffectiveDialog'],\n fromEnableAffectiveDialog,\n );\n }\n\n const fromFrequencyPenalty = common.getValueByPath(fromObject, [\n 'frequencyPenalty',\n ]);\n if (fromFrequencyPenalty != null) {\n common.setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty);\n }\n\n const fromLogprobs = common.getValueByPath(fromObject, ['logprobs']);\n if (fromLogprobs != null) {\n common.setValueByPath(toObject, ['logprobs'], fromLogprobs);\n }\n\n const fromMaxOutputTokens = common.getValueByPath(fromObject, [\n 'maxOutputTokens',\n ]);\n if (fromMaxOutputTokens != null) {\n common.setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens);\n }\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (fromMediaResolution != null) {\n common.setValueByPath(toObject, ['mediaResolution'], fromMediaResolution);\n }\n\n const fromPresencePenalty = common.getValueByPath(fromObject, [\n 'presencePenalty',\n ]);\n if (fromPresencePenalty != null) {\n common.setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty);\n }\n\n const fromResponseLogprobs = common.getValueByPath(fromObject, [\n 'responseLogprobs',\n ]);\n if (fromResponseLogprobs != null) {\n common.setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs);\n }\n\n const fromResponseMimeType = common.getValueByPath(fromObject, [\n 'responseMimeType',\n ]);\n if (fromResponseMimeType != null) {\n common.setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType);\n }\n\n const fromResponseModalities = common.getValueByPath(fromObject, [\n 'responseModalities',\n ]);\n if (fromResponseModalities != null) {\n common.setValueByPath(\n toObject,\n ['responseModalities'],\n fromResponseModalities,\n );\n }\n\n const fromResponseSchema = common.getValueByPath(fromObject, [\n 'responseSchema',\n ]);\n if (fromResponseSchema != null) {\n common.setValueByPath(toObject, ['responseSchema'], fromResponseSchema);\n }\n\n const fromRoutingConfig = common.getValueByPath(fromObject, [\n 'routingConfig',\n ]);\n if (fromRoutingConfig != null) {\n common.setValueByPath(toObject, ['routingConfig'], fromRoutingConfig);\n }\n\n const fromSeed = common.getValueByPath(fromObject, ['seed']);\n if (fromSeed != null) {\n common.setValueByPath(toObject, ['seed'], fromSeed);\n }\n\n const fromSpeechConfig = common.getValueByPath(fromObject, ['speechConfig']);\n if (fromSpeechConfig != null) {\n common.setValueByPath(toObject, ['speechConfig'], fromSpeechConfig);\n }\n\n const fromStopSequences = common.getValueByPath(fromObject, [\n 'stopSequences',\n ]);\n if (fromStopSequences != null) {\n common.setValueByPath(toObject, ['stopSequences'], fromStopSequences);\n }\n\n const fromTemperature = common.getValueByPath(fromObject, ['temperature']);\n if (fromTemperature != null) {\n common.setValueByPath(toObject, ['temperature'], fromTemperature);\n }\n\n const fromThinkingConfig = common.getValueByPath(fromObject, [\n 'thinkingConfig',\n ]);\n if (fromThinkingConfig != null) {\n common.setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig);\n }\n\n const fromTopK = common.getValueByPath(fromObject, ['topK']);\n if (fromTopK != null) {\n common.setValueByPath(toObject, ['topK'], fromTopK);\n }\n\n const fromTopP = common.getValueByPath(fromObject, ['topP']);\n if (fromTopP != null) {\n common.setValueByPath(toObject, ['topP'], fromTopP);\n }\n\n if (\n common.getValueByPath(fromObject, ['enableEnhancedCivicAnswers']) !==\n undefined\n ) {\n throw new Error(\n 'enableEnhancedCivicAnswers parameter is not supported in Vertex AI.',\n );\n }\n\n return toObject;\n}\n\nexport function googleMapsToMldev(\n fromObject: types.GoogleMaps,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['authConfig']) !== undefined) {\n throw new Error('authConfig parameter is not supported in Gemini API.');\n }\n\n const fromEnableWidget = common.getValueByPath(fromObject, ['enableWidget']);\n if (fromEnableWidget != null) {\n common.setValueByPath(toObject, ['enableWidget'], fromEnableWidget);\n }\n\n return toObject;\n}\n\nexport function googleSearchToMldev(\n fromObject: types.GoogleSearch,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['excludeDomains']) !== undefined) {\n throw new Error('excludeDomains parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['blockingConfidence']) !== undefined) {\n throw new Error(\n 'blockingConfidence parameter is not supported in Gemini API.',\n );\n }\n\n const fromTimeRangeFilter = common.getValueByPath(fromObject, [\n 'timeRangeFilter',\n ]);\n if (fromTimeRangeFilter != null) {\n common.setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter);\n }\n\n return toObject;\n}\n\nexport function liveClientContentToMldev(\n fromObject: types.LiveClientContent,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromTurns = common.getValueByPath(fromObject, ['turns']);\n if (fromTurns != null) {\n let transformedList = fromTurns;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return contentToMldev(item);\n });\n }\n common.setValueByPath(toObject, ['turns'], transformedList);\n }\n\n const fromTurnComplete = common.getValueByPath(fromObject, ['turnComplete']);\n if (fromTurnComplete != null) {\n common.setValueByPath(toObject, ['turnComplete'], fromTurnComplete);\n }\n\n return toObject;\n}\n\nexport function liveClientMessageToMldev(\n fromObject: types.LiveClientMessage,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSetup = common.getValueByPath(fromObject, ['setup']);\n if (fromSetup != null) {\n common.setValueByPath(\n toObject,\n ['setup'],\n liveClientSetupToMldev(fromSetup),\n );\n }\n\n const fromClientContent = common.getValueByPath(fromObject, [\n 'clientContent',\n ]);\n if (fromClientContent != null) {\n common.setValueByPath(\n toObject,\n ['clientContent'],\n liveClientContentToMldev(fromClientContent),\n );\n }\n\n const fromRealtimeInput = common.getValueByPath(fromObject, [\n 'realtimeInput',\n ]);\n if (fromRealtimeInput != null) {\n common.setValueByPath(\n toObject,\n ['realtimeInput'],\n liveClientRealtimeInputToMldev(fromRealtimeInput),\n );\n }\n\n const fromToolResponse = common.getValueByPath(fromObject, ['toolResponse']);\n if (fromToolResponse != null) {\n common.setValueByPath(toObject, ['toolResponse'], fromToolResponse);\n }\n\n return toObject;\n}\n\nexport function liveClientMessageToVertex(\n fromObject: types.LiveClientMessage,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSetup = common.getValueByPath(fromObject, ['setup']);\n if (fromSetup != null) {\n common.setValueByPath(\n toObject,\n ['setup'],\n liveClientSetupToVertex(fromSetup),\n );\n }\n\n const fromClientContent = common.getValueByPath(fromObject, [\n 'clientContent',\n ]);\n if (fromClientContent != null) {\n common.setValueByPath(toObject, ['clientContent'], fromClientContent);\n }\n\n const fromRealtimeInput = common.getValueByPath(fromObject, [\n 'realtimeInput',\n ]);\n if (fromRealtimeInput != null) {\n common.setValueByPath(\n toObject,\n ['realtimeInput'],\n liveClientRealtimeInputToVertex(fromRealtimeInput),\n );\n }\n\n const fromToolResponse = common.getValueByPath(fromObject, ['toolResponse']);\n if (fromToolResponse != null) {\n common.setValueByPath(toObject, ['toolResponse'], fromToolResponse);\n }\n\n return toObject;\n}\n\nexport function liveClientRealtimeInputToMldev(\n fromObject: types.LiveClientRealtimeInput,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMediaChunks = common.getValueByPath(fromObject, ['mediaChunks']);\n if (fromMediaChunks != null) {\n let transformedList = fromMediaChunks;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return blobToMldev(item);\n });\n }\n common.setValueByPath(toObject, ['mediaChunks'], transformedList);\n }\n\n const fromAudio = common.getValueByPath(fromObject, ['audio']);\n if (fromAudio != null) {\n common.setValueByPath(toObject, ['audio'], blobToMldev(fromAudio));\n }\n\n const fromAudioStreamEnd = common.getValueByPath(fromObject, [\n 'audioStreamEnd',\n ]);\n if (fromAudioStreamEnd != null) {\n common.setValueByPath(toObject, ['audioStreamEnd'], fromAudioStreamEnd);\n }\n\n const fromVideo = common.getValueByPath(fromObject, ['video']);\n if (fromVideo != null) {\n common.setValueByPath(toObject, ['video'], blobToMldev(fromVideo));\n }\n\n const fromText = common.getValueByPath(fromObject, ['text']);\n if (fromText != null) {\n common.setValueByPath(toObject, ['text'], fromText);\n }\n\n const fromActivityStart = common.getValueByPath(fromObject, [\n 'activityStart',\n ]);\n if (fromActivityStart != null) {\n common.setValueByPath(toObject, ['activityStart'], fromActivityStart);\n }\n\n const fromActivityEnd = common.getValueByPath(fromObject, ['activityEnd']);\n if (fromActivityEnd != null) {\n common.setValueByPath(toObject, ['activityEnd'], fromActivityEnd);\n }\n\n return toObject;\n}\n\nexport function liveClientRealtimeInputToVertex(\n fromObject: types.LiveClientRealtimeInput,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMediaChunks = common.getValueByPath(fromObject, ['mediaChunks']);\n if (fromMediaChunks != null) {\n let transformedList = fromMediaChunks;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['mediaChunks'], transformedList);\n }\n\n const fromAudio = common.getValueByPath(fromObject, ['audio']);\n if (fromAudio != null) {\n common.setValueByPath(toObject, ['audio'], fromAudio);\n }\n\n if (common.getValueByPath(fromObject, ['audioStreamEnd']) !== undefined) {\n throw new Error('audioStreamEnd parameter is not supported in Vertex AI.');\n }\n\n const fromVideo = common.getValueByPath(fromObject, ['video']);\n if (fromVideo != null) {\n common.setValueByPath(toObject, ['video'], fromVideo);\n }\n\n const fromText = common.getValueByPath(fromObject, ['text']);\n if (fromText != null) {\n common.setValueByPath(toObject, ['text'], fromText);\n }\n\n const fromActivityStart = common.getValueByPath(fromObject, [\n 'activityStart',\n ]);\n if (fromActivityStart != null) {\n common.setValueByPath(toObject, ['activityStart'], fromActivityStart);\n }\n\n const fromActivityEnd = common.getValueByPath(fromObject, ['activityEnd']);\n if (fromActivityEnd != null) {\n common.setValueByPath(toObject, ['activityEnd'], fromActivityEnd);\n }\n\n return toObject;\n}\n\nexport function liveClientSetupToMldev(\n fromObject: types.LiveClientSetup,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(toObject, ['model'], fromModel);\n }\n\n const fromGenerationConfig = common.getValueByPath(fromObject, [\n 'generationConfig',\n ]);\n if (fromGenerationConfig != null) {\n common.setValueByPath(toObject, ['generationConfig'], fromGenerationConfig);\n }\n\n const fromSystemInstruction = common.getValueByPath(fromObject, [\n 'systemInstruction',\n ]);\n if (fromSystemInstruction != null) {\n common.setValueByPath(\n toObject,\n ['systemInstruction'],\n contentToMldev(t.tContent(fromSystemInstruction)),\n );\n }\n\n const fromTools = common.getValueByPath(fromObject, ['tools']);\n if (fromTools != null) {\n let transformedList = t.tTools(fromTools);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return toolToMldev(t.tTool(item));\n });\n }\n common.setValueByPath(toObject, ['tools'], transformedList);\n }\n\n const fromRealtimeInputConfig = common.getValueByPath(fromObject, [\n 'realtimeInputConfig',\n ]);\n if (fromRealtimeInputConfig != null) {\n common.setValueByPath(\n toObject,\n ['realtimeInputConfig'],\n fromRealtimeInputConfig,\n );\n }\n\n const fromSessionResumption = common.getValueByPath(fromObject, [\n 'sessionResumption',\n ]);\n if (fromSessionResumption != null) {\n common.setValueByPath(\n toObject,\n ['sessionResumption'],\n sessionResumptionConfigToMldev(fromSessionResumption),\n );\n }\n\n const fromContextWindowCompression = common.getValueByPath(fromObject, [\n 'contextWindowCompression',\n ]);\n if (fromContextWindowCompression != null) {\n common.setValueByPath(\n toObject,\n ['contextWindowCompression'],\n fromContextWindowCompression,\n );\n }\n\n const fromInputAudioTranscription = common.getValueByPath(fromObject, [\n 'inputAudioTranscription',\n ]);\n if (fromInputAudioTranscription != null) {\n common.setValueByPath(\n toObject,\n ['inputAudioTranscription'],\n fromInputAudioTranscription,\n );\n }\n\n const fromOutputAudioTranscription = common.getValueByPath(fromObject, [\n 'outputAudioTranscription',\n ]);\n if (fromOutputAudioTranscription != null) {\n common.setValueByPath(\n toObject,\n ['outputAudioTranscription'],\n fromOutputAudioTranscription,\n );\n }\n\n const fromProactivity = common.getValueByPath(fromObject, ['proactivity']);\n if (fromProactivity != null) {\n common.setValueByPath(toObject, ['proactivity'], fromProactivity);\n }\n\n if (common.getValueByPath(fromObject, ['explicitVadSignal']) !== undefined) {\n throw new Error(\n 'explicitVadSignal parameter is not supported in Gemini API.',\n );\n }\n\n return toObject;\n}\n\nexport function liveClientSetupToVertex(\n fromObject: types.LiveClientSetup,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(toObject, ['model'], fromModel);\n }\n\n const fromGenerationConfig = common.getValueByPath(fromObject, [\n 'generationConfig',\n ]);\n if (fromGenerationConfig != null) {\n common.setValueByPath(\n toObject,\n ['generationConfig'],\n generationConfigToVertex(fromGenerationConfig),\n );\n }\n\n const fromSystemInstruction = common.getValueByPath(fromObject, [\n 'systemInstruction',\n ]);\n if (fromSystemInstruction != null) {\n common.setValueByPath(\n toObject,\n ['systemInstruction'],\n t.tContent(fromSystemInstruction),\n );\n }\n\n const fromTools = common.getValueByPath(fromObject, ['tools']);\n if (fromTools != null) {\n let transformedList = t.tTools(fromTools);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return toolToVertex(t.tTool(item));\n });\n }\n common.setValueByPath(toObject, ['tools'], transformedList);\n }\n\n const fromRealtimeInputConfig = common.getValueByPath(fromObject, [\n 'realtimeInputConfig',\n ]);\n if (fromRealtimeInputConfig != null) {\n common.setValueByPath(\n toObject,\n ['realtimeInputConfig'],\n fromRealtimeInputConfig,\n );\n }\n\n const fromSessionResumption = common.getValueByPath(fromObject, [\n 'sessionResumption',\n ]);\n if (fromSessionResumption != null) {\n common.setValueByPath(\n toObject,\n ['sessionResumption'],\n fromSessionResumption,\n );\n }\n\n const fromContextWindowCompression = common.getValueByPath(fromObject, [\n 'contextWindowCompression',\n ]);\n if (fromContextWindowCompression != null) {\n common.setValueByPath(\n toObject,\n ['contextWindowCompression'],\n fromContextWindowCompression,\n );\n }\n\n const fromInputAudioTranscription = common.getValueByPath(fromObject, [\n 'inputAudioTranscription',\n ]);\n if (fromInputAudioTranscription != null) {\n common.setValueByPath(\n toObject,\n ['inputAudioTranscription'],\n fromInputAudioTranscription,\n );\n }\n\n const fromOutputAudioTranscription = common.getValueByPath(fromObject, [\n 'outputAudioTranscription',\n ]);\n if (fromOutputAudioTranscription != null) {\n common.setValueByPath(\n toObject,\n ['outputAudioTranscription'],\n fromOutputAudioTranscription,\n );\n }\n\n const fromProactivity = common.getValueByPath(fromObject, ['proactivity']);\n if (fromProactivity != null) {\n common.setValueByPath(toObject, ['proactivity'], fromProactivity);\n }\n\n const fromExplicitVadSignal = common.getValueByPath(fromObject, [\n 'explicitVadSignal',\n ]);\n if (fromExplicitVadSignal != null) {\n common.setValueByPath(\n toObject,\n ['explicitVadSignal'],\n fromExplicitVadSignal,\n );\n }\n\n return toObject;\n}\n\nexport function liveConnectConfigToMldev(\n fromObject: types.LiveConnectConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromGenerationConfig = common.getValueByPath(fromObject, [\n 'generationConfig',\n ]);\n if (parentObject !== undefined && fromGenerationConfig != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig'],\n fromGenerationConfig,\n );\n }\n\n const fromResponseModalities = common.getValueByPath(fromObject, [\n 'responseModalities',\n ]);\n if (parentObject !== undefined && fromResponseModalities != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'responseModalities'],\n fromResponseModalities,\n );\n }\n\n const fromTemperature = common.getValueByPath(fromObject, ['temperature']);\n if (parentObject !== undefined && fromTemperature != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'temperature'],\n fromTemperature,\n );\n }\n\n const fromTopP = common.getValueByPath(fromObject, ['topP']);\n if (parentObject !== undefined && fromTopP != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'topP'],\n fromTopP,\n );\n }\n\n const fromTopK = common.getValueByPath(fromObject, ['topK']);\n if (parentObject !== undefined && fromTopK != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'topK'],\n fromTopK,\n );\n }\n\n const fromMaxOutputTokens = common.getValueByPath(fromObject, [\n 'maxOutputTokens',\n ]);\n if (parentObject !== undefined && fromMaxOutputTokens != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'maxOutputTokens'],\n fromMaxOutputTokens,\n );\n }\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (parentObject !== undefined && fromMediaResolution != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'mediaResolution'],\n fromMediaResolution,\n );\n }\n\n const fromSeed = common.getValueByPath(fromObject, ['seed']);\n if (parentObject !== undefined && fromSeed != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'seed'],\n fromSeed,\n );\n }\n\n const fromSpeechConfig = common.getValueByPath(fromObject, ['speechConfig']);\n if (parentObject !== undefined && fromSpeechConfig != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'speechConfig'],\n t.tLiveSpeechConfig(fromSpeechConfig),\n );\n }\n\n const fromThinkingConfig = common.getValueByPath(fromObject, [\n 'thinkingConfig',\n ]);\n if (parentObject !== undefined && fromThinkingConfig != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'thinkingConfig'],\n fromThinkingConfig,\n );\n }\n\n const fromEnableAffectiveDialog = common.getValueByPath(fromObject, [\n 'enableAffectiveDialog',\n ]);\n if (parentObject !== undefined && fromEnableAffectiveDialog != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'enableAffectiveDialog'],\n fromEnableAffectiveDialog,\n );\n }\n\n const fromSystemInstruction = common.getValueByPath(fromObject, [\n 'systemInstruction',\n ]);\n if (parentObject !== undefined && fromSystemInstruction != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'systemInstruction'],\n contentToMldev(t.tContent(fromSystemInstruction)),\n );\n }\n\n const fromTools = common.getValueByPath(fromObject, ['tools']);\n if (parentObject !== undefined && fromTools != null) {\n let transformedList = t.tTools(fromTools);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return toolToMldev(t.tTool(item));\n });\n }\n common.setValueByPath(parentObject, ['setup', 'tools'], transformedList);\n }\n\n const fromSessionResumption = common.getValueByPath(fromObject, [\n 'sessionResumption',\n ]);\n if (parentObject !== undefined && fromSessionResumption != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'sessionResumption'],\n sessionResumptionConfigToMldev(fromSessionResumption),\n );\n }\n\n const fromInputAudioTranscription = common.getValueByPath(fromObject, [\n 'inputAudioTranscription',\n ]);\n if (parentObject !== undefined && fromInputAudioTranscription != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'inputAudioTranscription'],\n fromInputAudioTranscription,\n );\n }\n\n const fromOutputAudioTranscription = common.getValueByPath(fromObject, [\n 'outputAudioTranscription',\n ]);\n if (parentObject !== undefined && fromOutputAudioTranscription != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'outputAudioTranscription'],\n fromOutputAudioTranscription,\n );\n }\n\n const fromRealtimeInputConfig = common.getValueByPath(fromObject, [\n 'realtimeInputConfig',\n ]);\n if (parentObject !== undefined && fromRealtimeInputConfig != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'realtimeInputConfig'],\n fromRealtimeInputConfig,\n );\n }\n\n const fromContextWindowCompression = common.getValueByPath(fromObject, [\n 'contextWindowCompression',\n ]);\n if (parentObject !== undefined && fromContextWindowCompression != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'contextWindowCompression'],\n fromContextWindowCompression,\n );\n }\n\n const fromProactivity = common.getValueByPath(fromObject, ['proactivity']);\n if (parentObject !== undefined && fromProactivity != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'proactivity'],\n fromProactivity,\n );\n }\n\n if (common.getValueByPath(fromObject, ['explicitVadSignal']) !== undefined) {\n throw new Error(\n 'explicitVadSignal parameter is not supported in Gemini API.',\n );\n }\n\n return toObject;\n}\n\nexport function liveConnectConfigToVertex(\n fromObject: types.LiveConnectConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromGenerationConfig = common.getValueByPath(fromObject, [\n 'generationConfig',\n ]);\n if (parentObject !== undefined && fromGenerationConfig != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig'],\n generationConfigToVertex(fromGenerationConfig),\n );\n }\n\n const fromResponseModalities = common.getValueByPath(fromObject, [\n 'responseModalities',\n ]);\n if (parentObject !== undefined && fromResponseModalities != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'responseModalities'],\n fromResponseModalities,\n );\n }\n\n const fromTemperature = common.getValueByPath(fromObject, ['temperature']);\n if (parentObject !== undefined && fromTemperature != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'temperature'],\n fromTemperature,\n );\n }\n\n const fromTopP = common.getValueByPath(fromObject, ['topP']);\n if (parentObject !== undefined && fromTopP != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'topP'],\n fromTopP,\n );\n }\n\n const fromTopK = common.getValueByPath(fromObject, ['topK']);\n if (parentObject !== undefined && fromTopK != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'topK'],\n fromTopK,\n );\n }\n\n const fromMaxOutputTokens = common.getValueByPath(fromObject, [\n 'maxOutputTokens',\n ]);\n if (parentObject !== undefined && fromMaxOutputTokens != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'maxOutputTokens'],\n fromMaxOutputTokens,\n );\n }\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (parentObject !== undefined && fromMediaResolution != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'mediaResolution'],\n fromMediaResolution,\n );\n }\n\n const fromSeed = common.getValueByPath(fromObject, ['seed']);\n if (parentObject !== undefined && fromSeed != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'seed'],\n fromSeed,\n );\n }\n\n const fromSpeechConfig = common.getValueByPath(fromObject, ['speechConfig']);\n if (parentObject !== undefined && fromSpeechConfig != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'speechConfig'],\n t.tLiveSpeechConfig(fromSpeechConfig),\n );\n }\n\n const fromThinkingConfig = common.getValueByPath(fromObject, [\n 'thinkingConfig',\n ]);\n if (parentObject !== undefined && fromThinkingConfig != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'thinkingConfig'],\n fromThinkingConfig,\n );\n }\n\n const fromEnableAffectiveDialog = common.getValueByPath(fromObject, [\n 'enableAffectiveDialog',\n ]);\n if (parentObject !== undefined && fromEnableAffectiveDialog != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'enableAffectiveDialog'],\n fromEnableAffectiveDialog,\n );\n }\n\n const fromSystemInstruction = common.getValueByPath(fromObject, [\n 'systemInstruction',\n ]);\n if (parentObject !== undefined && fromSystemInstruction != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'systemInstruction'],\n t.tContent(fromSystemInstruction),\n );\n }\n\n const fromTools = common.getValueByPath(fromObject, ['tools']);\n if (parentObject !== undefined && fromTools != null) {\n let transformedList = t.tTools(fromTools);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return toolToVertex(t.tTool(item));\n });\n }\n common.setValueByPath(parentObject, ['setup', 'tools'], transformedList);\n }\n\n const fromSessionResumption = common.getValueByPath(fromObject, [\n 'sessionResumption',\n ]);\n if (parentObject !== undefined && fromSessionResumption != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'sessionResumption'],\n fromSessionResumption,\n );\n }\n\n const fromInputAudioTranscription = common.getValueByPath(fromObject, [\n 'inputAudioTranscription',\n ]);\n if (parentObject !== undefined && fromInputAudioTranscription != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'inputAudioTranscription'],\n fromInputAudioTranscription,\n );\n }\n\n const fromOutputAudioTranscription = common.getValueByPath(fromObject, [\n 'outputAudioTranscription',\n ]);\n if (parentObject !== undefined && fromOutputAudioTranscription != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'outputAudioTranscription'],\n fromOutputAudioTranscription,\n );\n }\n\n const fromRealtimeInputConfig = common.getValueByPath(fromObject, [\n 'realtimeInputConfig',\n ]);\n if (parentObject !== undefined && fromRealtimeInputConfig != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'realtimeInputConfig'],\n fromRealtimeInputConfig,\n );\n }\n\n const fromContextWindowCompression = common.getValueByPath(fromObject, [\n 'contextWindowCompression',\n ]);\n if (parentObject !== undefined && fromContextWindowCompression != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'contextWindowCompression'],\n fromContextWindowCompression,\n );\n }\n\n const fromProactivity = common.getValueByPath(fromObject, ['proactivity']);\n if (parentObject !== undefined && fromProactivity != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'proactivity'],\n fromProactivity,\n );\n }\n\n const fromExplicitVadSignal = common.getValueByPath(fromObject, [\n 'explicitVadSignal',\n ]);\n if (parentObject !== undefined && fromExplicitVadSignal != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'explicitVadSignal'],\n fromExplicitVadSignal,\n );\n }\n\n return toObject;\n}\n\nexport function liveConnectParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.LiveConnectParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['setup', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n common.setValueByPath(\n toObject,\n ['config'],\n liveConnectConfigToMldev(fromConfig, toObject),\n );\n }\n\n return toObject;\n}\n\nexport function liveConnectParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.LiveConnectParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['setup', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n common.setValueByPath(\n toObject,\n ['config'],\n liveConnectConfigToVertex(fromConfig, toObject),\n );\n }\n\n return toObject;\n}\n\nexport function liveMusicClientMessageToVertex(\n fromObject: types.LiveMusicClientMessage,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['setup']) !== undefined) {\n throw new Error('setup parameter is not supported in Vertex AI.');\n }\n\n if (common.getValueByPath(fromObject, ['clientContent']) !== undefined) {\n throw new Error('clientContent parameter is not supported in Vertex AI.');\n }\n\n if (\n common.getValueByPath(fromObject, ['musicGenerationConfig']) !== undefined\n ) {\n throw new Error(\n 'musicGenerationConfig parameter is not supported in Vertex AI.',\n );\n }\n\n if (common.getValueByPath(fromObject, ['playbackControl']) !== undefined) {\n throw new Error('playbackControl parameter is not supported in Vertex AI.');\n }\n\n return toObject;\n}\n\nexport function liveMusicConnectParametersToMldev(\n fromObject: types.LiveMusicConnectParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(toObject, ['setup', 'model'], fromModel);\n }\n\n const fromCallbacks = common.getValueByPath(fromObject, ['callbacks']);\n if (fromCallbacks != null) {\n common.setValueByPath(toObject, ['callbacks'], fromCallbacks);\n }\n\n return toObject;\n}\n\nexport function liveMusicConnectParametersToVertex(\n fromObject: types.LiveMusicConnectParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['model']) !== undefined) {\n throw new Error('model parameter is not supported in Vertex AI.');\n }\n\n if (common.getValueByPath(fromObject, ['callbacks']) !== undefined) {\n throw new Error('callbacks parameter is not supported in Vertex AI.');\n }\n\n return toObject;\n}\n\nexport function liveMusicSetConfigParametersToMldev(\n fromObject: types.LiveMusicSetConfigParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMusicGenerationConfig = common.getValueByPath(fromObject, [\n 'musicGenerationConfig',\n ]);\n if (fromMusicGenerationConfig != null) {\n common.setValueByPath(\n toObject,\n ['musicGenerationConfig'],\n fromMusicGenerationConfig,\n );\n }\n\n return toObject;\n}\n\nexport function liveMusicSetConfigParametersToVertex(\n fromObject: types.LiveMusicSetConfigParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (\n common.getValueByPath(fromObject, ['musicGenerationConfig']) !== undefined\n ) {\n throw new Error(\n 'musicGenerationConfig parameter is not supported in Vertex AI.',\n );\n }\n\n return toObject;\n}\n\nexport function liveMusicSetWeightedPromptsParametersToMldev(\n fromObject: types.LiveMusicSetWeightedPromptsParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromWeightedPrompts = common.getValueByPath(fromObject, [\n 'weightedPrompts',\n ]);\n if (fromWeightedPrompts != null) {\n let transformedList = fromWeightedPrompts;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['weightedPrompts'], transformedList);\n }\n\n return toObject;\n}\n\nexport function liveMusicSetWeightedPromptsParametersToVertex(\n fromObject: types.LiveMusicSetWeightedPromptsParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['weightedPrompts']) !== undefined) {\n throw new Error('weightedPrompts parameter is not supported in Vertex AI.');\n }\n\n return toObject;\n}\n\nexport function liveSendRealtimeInputParametersToMldev(\n fromObject: types.LiveSendRealtimeInputParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMedia = common.getValueByPath(fromObject, ['media']);\n if (fromMedia != null) {\n let transformedList = t.tBlobs(fromMedia);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return blobToMldev(item);\n });\n }\n common.setValueByPath(toObject, ['mediaChunks'], transformedList);\n }\n\n const fromAudio = common.getValueByPath(fromObject, ['audio']);\n if (fromAudio != null) {\n common.setValueByPath(\n toObject,\n ['audio'],\n blobToMldev(t.tAudioBlob(fromAudio)),\n );\n }\n\n const fromAudioStreamEnd = common.getValueByPath(fromObject, [\n 'audioStreamEnd',\n ]);\n if (fromAudioStreamEnd != null) {\n common.setValueByPath(toObject, ['audioStreamEnd'], fromAudioStreamEnd);\n }\n\n const fromVideo = common.getValueByPath(fromObject, ['video']);\n if (fromVideo != null) {\n common.setValueByPath(\n toObject,\n ['video'],\n blobToMldev(t.tImageBlob(fromVideo)),\n );\n }\n\n const fromText = common.getValueByPath(fromObject, ['text']);\n if (fromText != null) {\n common.setValueByPath(toObject, ['text'], fromText);\n }\n\n const fromActivityStart = common.getValueByPath(fromObject, [\n 'activityStart',\n ]);\n if (fromActivityStart != null) {\n common.setValueByPath(toObject, ['activityStart'], fromActivityStart);\n }\n\n const fromActivityEnd = common.getValueByPath(fromObject, ['activityEnd']);\n if (fromActivityEnd != null) {\n common.setValueByPath(toObject, ['activityEnd'], fromActivityEnd);\n }\n\n return toObject;\n}\n\nexport function liveSendRealtimeInputParametersToVertex(\n fromObject: types.LiveSendRealtimeInputParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMedia = common.getValueByPath(fromObject, ['media']);\n if (fromMedia != null) {\n let transformedList = t.tBlobs(fromMedia);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['mediaChunks'], transformedList);\n }\n\n const fromAudio = common.getValueByPath(fromObject, ['audio']);\n if (fromAudio != null) {\n common.setValueByPath(toObject, ['audio'], t.tAudioBlob(fromAudio));\n }\n\n const fromAudioStreamEnd = common.getValueByPath(fromObject, [\n 'audioStreamEnd',\n ]);\n if (fromAudioStreamEnd != null) {\n common.setValueByPath(toObject, ['audioStreamEnd'], fromAudioStreamEnd);\n }\n\n const fromVideo = common.getValueByPath(fromObject, ['video']);\n if (fromVideo != null) {\n common.setValueByPath(toObject, ['video'], t.tImageBlob(fromVideo));\n }\n\n const fromText = common.getValueByPath(fromObject, ['text']);\n if (fromText != null) {\n common.setValueByPath(toObject, ['text'], fromText);\n }\n\n const fromActivityStart = common.getValueByPath(fromObject, [\n 'activityStart',\n ]);\n if (fromActivityStart != null) {\n common.setValueByPath(toObject, ['activityStart'], fromActivityStart);\n }\n\n const fromActivityEnd = common.getValueByPath(fromObject, ['activityEnd']);\n if (fromActivityEnd != null) {\n common.setValueByPath(toObject, ['activityEnd'], fromActivityEnd);\n }\n\n return toObject;\n}\n\nexport function liveServerMessageFromMldev(\n fromObject: types.LiveServerMessage,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSetupComplete = common.getValueByPath(fromObject, [\n 'setupComplete',\n ]);\n if (fromSetupComplete != null) {\n common.setValueByPath(toObject, ['setupComplete'], fromSetupComplete);\n }\n\n const fromServerContent = common.getValueByPath(fromObject, [\n 'serverContent',\n ]);\n if (fromServerContent != null) {\n common.setValueByPath(toObject, ['serverContent'], fromServerContent);\n }\n\n const fromToolCall = common.getValueByPath(fromObject, ['toolCall']);\n if (fromToolCall != null) {\n common.setValueByPath(toObject, ['toolCall'], fromToolCall);\n }\n\n const fromToolCallCancellation = common.getValueByPath(fromObject, [\n 'toolCallCancellation',\n ]);\n if (fromToolCallCancellation != null) {\n common.setValueByPath(\n toObject,\n ['toolCallCancellation'],\n fromToolCallCancellation,\n );\n }\n\n const fromUsageMetadata = common.getValueByPath(fromObject, [\n 'usageMetadata',\n ]);\n if (fromUsageMetadata != null) {\n common.setValueByPath(toObject, ['usageMetadata'], fromUsageMetadata);\n }\n\n const fromGoAway = common.getValueByPath(fromObject, ['goAway']);\n if (fromGoAway != null) {\n common.setValueByPath(toObject, ['goAway'], fromGoAway);\n }\n\n const fromSessionResumptionUpdate = common.getValueByPath(fromObject, [\n 'sessionResumptionUpdate',\n ]);\n if (fromSessionResumptionUpdate != null) {\n common.setValueByPath(\n toObject,\n ['sessionResumptionUpdate'],\n fromSessionResumptionUpdate,\n );\n }\n\n const fromVoiceActivityDetectionSignal = common.getValueByPath(fromObject, [\n 'voiceActivityDetectionSignal',\n ]);\n if (fromVoiceActivityDetectionSignal != null) {\n common.setValueByPath(\n toObject,\n ['voiceActivityDetectionSignal'],\n fromVoiceActivityDetectionSignal,\n );\n }\n\n const fromVoiceActivity = common.getValueByPath(fromObject, [\n 'voiceActivity',\n ]);\n if (fromVoiceActivity != null) {\n common.setValueByPath(\n toObject,\n ['voiceActivity'],\n voiceActivityFromMldev(fromVoiceActivity),\n );\n }\n\n return toObject;\n}\n\nexport function liveServerMessageFromVertex(\n fromObject: types.LiveServerMessage,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSetupComplete = common.getValueByPath(fromObject, [\n 'setupComplete',\n ]);\n if (fromSetupComplete != null) {\n common.setValueByPath(toObject, ['setupComplete'], fromSetupComplete);\n }\n\n const fromServerContent = common.getValueByPath(fromObject, [\n 'serverContent',\n ]);\n if (fromServerContent != null) {\n common.setValueByPath(toObject, ['serverContent'], fromServerContent);\n }\n\n const fromToolCall = common.getValueByPath(fromObject, ['toolCall']);\n if (fromToolCall != null) {\n common.setValueByPath(toObject, ['toolCall'], fromToolCall);\n }\n\n const fromToolCallCancellation = common.getValueByPath(fromObject, [\n 'toolCallCancellation',\n ]);\n if (fromToolCallCancellation != null) {\n common.setValueByPath(\n toObject,\n ['toolCallCancellation'],\n fromToolCallCancellation,\n );\n }\n\n const fromUsageMetadata = common.getValueByPath(fromObject, [\n 'usageMetadata',\n ]);\n if (fromUsageMetadata != null) {\n common.setValueByPath(\n toObject,\n ['usageMetadata'],\n usageMetadataFromVertex(fromUsageMetadata),\n );\n }\n\n const fromGoAway = common.getValueByPath(fromObject, ['goAway']);\n if (fromGoAway != null) {\n common.setValueByPath(toObject, ['goAway'], fromGoAway);\n }\n\n const fromSessionResumptionUpdate = common.getValueByPath(fromObject, [\n 'sessionResumptionUpdate',\n ]);\n if (fromSessionResumptionUpdate != null) {\n common.setValueByPath(\n toObject,\n ['sessionResumptionUpdate'],\n fromSessionResumptionUpdate,\n );\n }\n\n const fromVoiceActivityDetectionSignal = common.getValueByPath(fromObject, [\n 'voiceActivityDetectionSignal',\n ]);\n if (fromVoiceActivityDetectionSignal != null) {\n common.setValueByPath(\n toObject,\n ['voiceActivityDetectionSignal'],\n fromVoiceActivityDetectionSignal,\n );\n }\n\n const fromVoiceActivity = common.getValueByPath(fromObject, [\n 'voiceActivity',\n ]);\n if (fromVoiceActivity != null) {\n common.setValueByPath(\n toObject,\n ['voiceActivity'],\n voiceActivityFromVertex(fromVoiceActivity),\n );\n }\n\n return toObject;\n}\n\nexport function partToMldev(fromObject: types.Part): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (fromMediaResolution != null) {\n common.setValueByPath(toObject, ['mediaResolution'], fromMediaResolution);\n }\n\n const fromCodeExecutionResult = common.getValueByPath(fromObject, [\n 'codeExecutionResult',\n ]);\n if (fromCodeExecutionResult != null) {\n common.setValueByPath(\n toObject,\n ['codeExecutionResult'],\n fromCodeExecutionResult,\n );\n }\n\n const fromExecutableCode = common.getValueByPath(fromObject, [\n 'executableCode',\n ]);\n if (fromExecutableCode != null) {\n common.setValueByPath(toObject, ['executableCode'], fromExecutableCode);\n }\n\n const fromFileData = common.getValueByPath(fromObject, ['fileData']);\n if (fromFileData != null) {\n common.setValueByPath(\n toObject,\n ['fileData'],\n fileDataToMldev(fromFileData),\n );\n }\n\n const fromFunctionCall = common.getValueByPath(fromObject, ['functionCall']);\n if (fromFunctionCall != null) {\n common.setValueByPath(\n toObject,\n ['functionCall'],\n functionCallToMldev(fromFunctionCall),\n );\n }\n\n const fromFunctionResponse = common.getValueByPath(fromObject, [\n 'functionResponse',\n ]);\n if (fromFunctionResponse != null) {\n common.setValueByPath(toObject, ['functionResponse'], fromFunctionResponse);\n }\n\n const fromInlineData = common.getValueByPath(fromObject, ['inlineData']);\n if (fromInlineData != null) {\n common.setValueByPath(\n toObject,\n ['inlineData'],\n blobToMldev(fromInlineData),\n );\n }\n\n const fromText = common.getValueByPath(fromObject, ['text']);\n if (fromText != null) {\n common.setValueByPath(toObject, ['text'], fromText);\n }\n\n const fromThought = common.getValueByPath(fromObject, ['thought']);\n if (fromThought != null) {\n common.setValueByPath(toObject, ['thought'], fromThought);\n }\n\n const fromThoughtSignature = common.getValueByPath(fromObject, [\n 'thoughtSignature',\n ]);\n if (fromThoughtSignature != null) {\n common.setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature);\n }\n\n const fromVideoMetadata = common.getValueByPath(fromObject, [\n 'videoMetadata',\n ]);\n if (fromVideoMetadata != null) {\n common.setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata);\n }\n\n return toObject;\n}\n\nexport function sessionResumptionConfigToMldev(\n fromObject: types.SessionResumptionConfig,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromHandle = common.getValueByPath(fromObject, ['handle']);\n if (fromHandle != null) {\n common.setValueByPath(toObject, ['handle'], fromHandle);\n }\n\n if (common.getValueByPath(fromObject, ['transparent']) !== undefined) {\n throw new Error('transparent parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function toolToMldev(fromObject: types.Tool): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['retrieval']) !== undefined) {\n throw new Error('retrieval parameter is not supported in Gemini API.');\n }\n\n const fromComputerUse = common.getValueByPath(fromObject, ['computerUse']);\n if (fromComputerUse != null) {\n common.setValueByPath(toObject, ['computerUse'], fromComputerUse);\n }\n\n const fromFileSearch = common.getValueByPath(fromObject, ['fileSearch']);\n if (fromFileSearch != null) {\n common.setValueByPath(toObject, ['fileSearch'], fromFileSearch);\n }\n\n const fromCodeExecution = common.getValueByPath(fromObject, [\n 'codeExecution',\n ]);\n if (fromCodeExecution != null) {\n common.setValueByPath(toObject, ['codeExecution'], fromCodeExecution);\n }\n\n if (\n common.getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined\n ) {\n throw new Error(\n 'enterpriseWebSearch parameter is not supported in Gemini API.',\n );\n }\n\n const fromFunctionDeclarations = common.getValueByPath(fromObject, [\n 'functionDeclarations',\n ]);\n if (fromFunctionDeclarations != null) {\n let transformedList = fromFunctionDeclarations;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['functionDeclarations'], transformedList);\n }\n\n const fromGoogleMaps = common.getValueByPath(fromObject, ['googleMaps']);\n if (fromGoogleMaps != null) {\n common.setValueByPath(\n toObject,\n ['googleMaps'],\n googleMapsToMldev(fromGoogleMaps),\n );\n }\n\n const fromGoogleSearch = common.getValueByPath(fromObject, ['googleSearch']);\n if (fromGoogleSearch != null) {\n common.setValueByPath(\n toObject,\n ['googleSearch'],\n googleSearchToMldev(fromGoogleSearch),\n );\n }\n\n const fromGoogleSearchRetrieval = common.getValueByPath(fromObject, [\n 'googleSearchRetrieval',\n ]);\n if (fromGoogleSearchRetrieval != null) {\n common.setValueByPath(\n toObject,\n ['googleSearchRetrieval'],\n fromGoogleSearchRetrieval,\n );\n }\n\n const fromUrlContext = common.getValueByPath(fromObject, ['urlContext']);\n if (fromUrlContext != null) {\n common.setValueByPath(toObject, ['urlContext'], fromUrlContext);\n }\n\n return toObject;\n}\n\nexport function toolToVertex(fromObject: types.Tool): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromRetrieval = common.getValueByPath(fromObject, ['retrieval']);\n if (fromRetrieval != null) {\n common.setValueByPath(toObject, ['retrieval'], fromRetrieval);\n }\n\n const fromComputerUse = common.getValueByPath(fromObject, ['computerUse']);\n if (fromComputerUse != null) {\n common.setValueByPath(toObject, ['computerUse'], fromComputerUse);\n }\n\n if (common.getValueByPath(fromObject, ['fileSearch']) !== undefined) {\n throw new Error('fileSearch parameter is not supported in Vertex AI.');\n }\n\n const fromCodeExecution = common.getValueByPath(fromObject, [\n 'codeExecution',\n ]);\n if (fromCodeExecution != null) {\n common.setValueByPath(toObject, ['codeExecution'], fromCodeExecution);\n }\n\n const fromEnterpriseWebSearch = common.getValueByPath(fromObject, [\n 'enterpriseWebSearch',\n ]);\n if (fromEnterpriseWebSearch != null) {\n common.setValueByPath(\n toObject,\n ['enterpriseWebSearch'],\n fromEnterpriseWebSearch,\n );\n }\n\n const fromFunctionDeclarations = common.getValueByPath(fromObject, [\n 'functionDeclarations',\n ]);\n if (fromFunctionDeclarations != null) {\n let transformedList = fromFunctionDeclarations;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return functionDeclarationToVertex(item);\n });\n }\n common.setValueByPath(toObject, ['functionDeclarations'], transformedList);\n }\n\n const fromGoogleMaps = common.getValueByPath(fromObject, ['googleMaps']);\n if (fromGoogleMaps != null) {\n common.setValueByPath(toObject, ['googleMaps'], fromGoogleMaps);\n }\n\n const fromGoogleSearch = common.getValueByPath(fromObject, ['googleSearch']);\n if (fromGoogleSearch != null) {\n common.setValueByPath(toObject, ['googleSearch'], fromGoogleSearch);\n }\n\n const fromGoogleSearchRetrieval = common.getValueByPath(fromObject, [\n 'googleSearchRetrieval',\n ]);\n if (fromGoogleSearchRetrieval != null) {\n common.setValueByPath(\n toObject,\n ['googleSearchRetrieval'],\n fromGoogleSearchRetrieval,\n );\n }\n\n const fromUrlContext = common.getValueByPath(fromObject, ['urlContext']);\n if (fromUrlContext != null) {\n common.setValueByPath(toObject, ['urlContext'], fromUrlContext);\n }\n\n return toObject;\n}\n\nexport function usageMetadataFromVertex(\n fromObject: types.UsageMetadata,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPromptTokenCount = common.getValueByPath(fromObject, [\n 'promptTokenCount',\n ]);\n if (fromPromptTokenCount != null) {\n common.setValueByPath(toObject, ['promptTokenCount'], fromPromptTokenCount);\n }\n\n const fromCachedContentTokenCount = common.getValueByPath(fromObject, [\n 'cachedContentTokenCount',\n ]);\n if (fromCachedContentTokenCount != null) {\n common.setValueByPath(\n toObject,\n ['cachedContentTokenCount'],\n fromCachedContentTokenCount,\n );\n }\n\n const fromResponseTokenCount = common.getValueByPath(fromObject, [\n 'candidatesTokenCount',\n ]);\n if (fromResponseTokenCount != null) {\n common.setValueByPath(\n toObject,\n ['responseTokenCount'],\n fromResponseTokenCount,\n );\n }\n\n const fromToolUsePromptTokenCount = common.getValueByPath(fromObject, [\n 'toolUsePromptTokenCount',\n ]);\n if (fromToolUsePromptTokenCount != null) {\n common.setValueByPath(\n toObject,\n ['toolUsePromptTokenCount'],\n fromToolUsePromptTokenCount,\n );\n }\n\n const fromThoughtsTokenCount = common.getValueByPath(fromObject, [\n 'thoughtsTokenCount',\n ]);\n if (fromThoughtsTokenCount != null) {\n common.setValueByPath(\n toObject,\n ['thoughtsTokenCount'],\n fromThoughtsTokenCount,\n );\n }\n\n const fromTotalTokenCount = common.getValueByPath(fromObject, [\n 'totalTokenCount',\n ]);\n if (fromTotalTokenCount != null) {\n common.setValueByPath(toObject, ['totalTokenCount'], fromTotalTokenCount);\n }\n\n const fromPromptTokensDetails = common.getValueByPath(fromObject, [\n 'promptTokensDetails',\n ]);\n if (fromPromptTokensDetails != null) {\n let transformedList = fromPromptTokensDetails;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['promptTokensDetails'], transformedList);\n }\n\n const fromCacheTokensDetails = common.getValueByPath(fromObject, [\n 'cacheTokensDetails',\n ]);\n if (fromCacheTokensDetails != null) {\n let transformedList = fromCacheTokensDetails;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['cacheTokensDetails'], transformedList);\n }\n\n const fromResponseTokensDetails = common.getValueByPath(fromObject, [\n 'candidatesTokensDetails',\n ]);\n if (fromResponseTokensDetails != null) {\n let transformedList = fromResponseTokensDetails;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['responseTokensDetails'], transformedList);\n }\n\n const fromToolUsePromptTokensDetails = common.getValueByPath(fromObject, [\n 'toolUsePromptTokensDetails',\n ]);\n if (fromToolUsePromptTokensDetails != null) {\n let transformedList = fromToolUsePromptTokensDetails;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(\n toObject,\n ['toolUsePromptTokensDetails'],\n transformedList,\n );\n }\n\n const fromTrafficType = common.getValueByPath(fromObject, ['trafficType']);\n if (fromTrafficType != null) {\n common.setValueByPath(toObject, ['trafficType'], fromTrafficType);\n }\n\n return toObject;\n}\n\nexport function voiceActivityFromMldev(\n fromObject: types.VoiceActivity,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromVoiceActivityType = common.getValueByPath(fromObject, ['type']);\n if (fromVoiceActivityType != null) {\n common.setValueByPath(\n toObject,\n ['voiceActivityType'],\n fromVoiceActivityType,\n );\n }\n\n return toObject;\n}\n\nexport function voiceActivityFromVertex(\n fromObject: types.VoiceActivity,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromVoiceActivityType = common.getValueByPath(fromObject, ['type']);\n if (fromVoiceActivityType != null) {\n common.setValueByPath(\n toObject,\n ['voiceActivityType'],\n fromVoiceActivityType,\n );\n }\n\n return toObject;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport {ApiClient} from '../_api_client.js';\nimport * as common from '../_common.js';\nimport type * as _internal_types from '../_internal_types.js';\nimport * as t from '../_transformers.js';\nimport type * as types from '../types.js';\n\nexport function blobToMldev(\n fromObject: types.Blob,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromData = common.getValueByPath(fromObject, ['data']);\n if (fromData != null) {\n common.setValueByPath(toObject, ['data'], fromData);\n }\n\n if (common.getValueByPath(fromObject, ['displayName']) !== undefined) {\n throw new Error('displayName parameter is not supported in Gemini API.');\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function candidateFromMldev(\n fromObject: types.Candidate,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromContent = common.getValueByPath(fromObject, ['content']);\n if (fromContent != null) {\n common.setValueByPath(toObject, ['content'], fromContent);\n }\n\n const fromCitationMetadata = common.getValueByPath(fromObject, [\n 'citationMetadata',\n ]);\n if (fromCitationMetadata != null) {\n common.setValueByPath(\n toObject,\n ['citationMetadata'],\n citationMetadataFromMldev(fromCitationMetadata, rootObject),\n );\n }\n\n const fromTokenCount = common.getValueByPath(fromObject, ['tokenCount']);\n if (fromTokenCount != null) {\n common.setValueByPath(toObject, ['tokenCount'], fromTokenCount);\n }\n\n const fromFinishReason = common.getValueByPath(fromObject, ['finishReason']);\n if (fromFinishReason != null) {\n common.setValueByPath(toObject, ['finishReason'], fromFinishReason);\n }\n\n const fromAvgLogprobs = common.getValueByPath(fromObject, ['avgLogprobs']);\n if (fromAvgLogprobs != null) {\n common.setValueByPath(toObject, ['avgLogprobs'], fromAvgLogprobs);\n }\n\n const fromGroundingMetadata = common.getValueByPath(fromObject, [\n 'groundingMetadata',\n ]);\n if (fromGroundingMetadata != null) {\n common.setValueByPath(\n toObject,\n ['groundingMetadata'],\n fromGroundingMetadata,\n );\n }\n\n const fromIndex = common.getValueByPath(fromObject, ['index']);\n if (fromIndex != null) {\n common.setValueByPath(toObject, ['index'], fromIndex);\n }\n\n const fromLogprobsResult = common.getValueByPath(fromObject, [\n 'logprobsResult',\n ]);\n if (fromLogprobsResult != null) {\n common.setValueByPath(toObject, ['logprobsResult'], fromLogprobsResult);\n }\n\n const fromSafetyRatings = common.getValueByPath(fromObject, [\n 'safetyRatings',\n ]);\n if (fromSafetyRatings != null) {\n let transformedList = fromSafetyRatings;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['safetyRatings'], transformedList);\n }\n\n const fromUrlContextMetadata = common.getValueByPath(fromObject, [\n 'urlContextMetadata',\n ]);\n if (fromUrlContextMetadata != null) {\n common.setValueByPath(\n toObject,\n ['urlContextMetadata'],\n fromUrlContextMetadata,\n );\n }\n\n return toObject;\n}\n\nexport function citationMetadataFromMldev(\n fromObject: types.CitationMetadata,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromCitations = common.getValueByPath(fromObject, ['citationSources']);\n if (fromCitations != null) {\n let transformedList = fromCitations;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['citations'], transformedList);\n }\n\n return toObject;\n}\n\nexport function computeTokensParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.ComputeTokensParameters,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromContents = common.getValueByPath(fromObject, ['contents']);\n if (fromContents != null) {\n let transformedList = t.tContents(fromContents);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['contents'], transformedList);\n }\n\n return toObject;\n}\n\nexport function computeTokensResponseFromVertex(\n fromObject: types.ComputeTokensResponse,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromTokensInfo = common.getValueByPath(fromObject, ['tokensInfo']);\n if (fromTokensInfo != null) {\n let transformedList = fromTokensInfo;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['tokensInfo'], transformedList);\n }\n\n return toObject;\n}\n\nexport function contentEmbeddingFromVertex(\n fromObject: types.ContentEmbedding,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromValues = common.getValueByPath(fromObject, ['values']);\n if (fromValues != null) {\n common.setValueByPath(toObject, ['values'], fromValues);\n }\n\n const fromStatistics = common.getValueByPath(fromObject, ['statistics']);\n if (fromStatistics != null) {\n common.setValueByPath(\n toObject,\n ['statistics'],\n contentEmbeddingStatisticsFromVertex(fromStatistics, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function contentEmbeddingStatisticsFromVertex(\n fromObject: types.ContentEmbeddingStatistics,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromTruncated = common.getValueByPath(fromObject, ['truncated']);\n if (fromTruncated != null) {\n common.setValueByPath(toObject, ['truncated'], fromTruncated);\n }\n\n const fromTokenCount = common.getValueByPath(fromObject, ['token_count']);\n if (fromTokenCount != null) {\n common.setValueByPath(toObject, ['tokenCount'], fromTokenCount);\n }\n\n return toObject;\n}\n\nexport function contentToMldev(\n fromObject: types.Content,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromParts = common.getValueByPath(fromObject, ['parts']);\n if (fromParts != null) {\n let transformedList = fromParts;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return partToMldev(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['parts'], transformedList);\n }\n\n const fromRole = common.getValueByPath(fromObject, ['role']);\n if (fromRole != null) {\n common.setValueByPath(toObject, ['role'], fromRole);\n }\n\n return toObject;\n}\n\nexport function controlReferenceConfigToVertex(\n fromObject: types.ControlReferenceConfig,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromControlType = common.getValueByPath(fromObject, ['controlType']);\n if (fromControlType != null) {\n common.setValueByPath(toObject, ['controlType'], fromControlType);\n }\n\n const fromEnableControlImageComputation = common.getValueByPath(fromObject, [\n 'enableControlImageComputation',\n ]);\n if (fromEnableControlImageComputation != null) {\n common.setValueByPath(\n toObject,\n ['computeControl'],\n fromEnableControlImageComputation,\n );\n }\n\n return toObject;\n}\n\nexport function countTokensConfigToMldev(\n fromObject: types.CountTokensConfig,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['systemInstruction']) !== undefined) {\n throw new Error(\n 'systemInstruction parameter is not supported in Gemini API.',\n );\n }\n\n if (common.getValueByPath(fromObject, ['tools']) !== undefined) {\n throw new Error('tools parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['generationConfig']) !== undefined) {\n throw new Error(\n 'generationConfig parameter is not supported in Gemini API.',\n );\n }\n\n return toObject;\n}\n\nexport function countTokensConfigToVertex(\n fromObject: types.CountTokensConfig,\n parentObject: Record<string, unknown>,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSystemInstruction = common.getValueByPath(fromObject, [\n 'systemInstruction',\n ]);\n if (parentObject !== undefined && fromSystemInstruction != null) {\n common.setValueByPath(\n parentObject,\n ['systemInstruction'],\n t.tContent(fromSystemInstruction),\n );\n }\n\n const fromTools = common.getValueByPath(fromObject, ['tools']);\n if (parentObject !== undefined && fromTools != null) {\n let transformedList = fromTools;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return toolToVertex(item, rootObject);\n });\n }\n common.setValueByPath(parentObject, ['tools'], transformedList);\n }\n\n const fromGenerationConfig = common.getValueByPath(fromObject, [\n 'generationConfig',\n ]);\n if (parentObject !== undefined && fromGenerationConfig != null) {\n common.setValueByPath(\n parentObject,\n ['generationConfig'],\n generationConfigToVertex(fromGenerationConfig, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function countTokensParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.CountTokensParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromContents = common.getValueByPath(fromObject, ['contents']);\n if (fromContents != null) {\n let transformedList = t.tContents(fromContents);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return contentToMldev(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['contents'], transformedList);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n countTokensConfigToMldev(fromConfig, rootObject);\n }\n\n return toObject;\n}\n\nexport function countTokensParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.CountTokensParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromContents = common.getValueByPath(fromObject, ['contents']);\n if (fromContents != null) {\n let transformedList = t.tContents(fromContents);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['contents'], transformedList);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n countTokensConfigToVertex(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function countTokensResponseFromMldev(\n fromObject: types.CountTokensResponse,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromTotalTokens = common.getValueByPath(fromObject, ['totalTokens']);\n if (fromTotalTokens != null) {\n common.setValueByPath(toObject, ['totalTokens'], fromTotalTokens);\n }\n\n const fromCachedContentTokenCount = common.getValueByPath(fromObject, [\n 'cachedContentTokenCount',\n ]);\n if (fromCachedContentTokenCount != null) {\n common.setValueByPath(\n toObject,\n ['cachedContentTokenCount'],\n fromCachedContentTokenCount,\n );\n }\n\n return toObject;\n}\n\nexport function countTokensResponseFromVertex(\n fromObject: types.CountTokensResponse,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromTotalTokens = common.getValueByPath(fromObject, ['totalTokens']);\n if (fromTotalTokens != null) {\n common.setValueByPath(toObject, ['totalTokens'], fromTotalTokens);\n }\n\n return toObject;\n}\n\nexport function deleteModelParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.DeleteModelParameters,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n return toObject;\n}\n\nexport function deleteModelParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.DeleteModelParameters,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n return toObject;\n}\n\nexport function deleteModelResponseFromMldev(\n fromObject: types.DeleteModelResponse,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n return toObject;\n}\n\nexport function deleteModelResponseFromVertex(\n fromObject: types.DeleteModelResponse,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n return toObject;\n}\n\nexport function editImageConfigToVertex(\n fromObject: types.EditImageConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromOutputGcsUri = common.getValueByPath(fromObject, ['outputGcsUri']);\n if (parentObject !== undefined && fromOutputGcsUri != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'storageUri'],\n fromOutputGcsUri,\n );\n }\n\n const fromNegativePrompt = common.getValueByPath(fromObject, [\n 'negativePrompt',\n ]);\n if (parentObject !== undefined && fromNegativePrompt != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'negativePrompt'],\n fromNegativePrompt,\n );\n }\n\n const fromNumberOfImages = common.getValueByPath(fromObject, [\n 'numberOfImages',\n ]);\n if (parentObject !== undefined && fromNumberOfImages != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'sampleCount'],\n fromNumberOfImages,\n );\n }\n\n const fromAspectRatio = common.getValueByPath(fromObject, ['aspectRatio']);\n if (parentObject !== undefined && fromAspectRatio != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'aspectRatio'],\n fromAspectRatio,\n );\n }\n\n const fromGuidanceScale = common.getValueByPath(fromObject, [\n 'guidanceScale',\n ]);\n if (parentObject !== undefined && fromGuidanceScale != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'guidanceScale'],\n fromGuidanceScale,\n );\n }\n\n const fromSeed = common.getValueByPath(fromObject, ['seed']);\n if (parentObject !== undefined && fromSeed != null) {\n common.setValueByPath(parentObject, ['parameters', 'seed'], fromSeed);\n }\n\n const fromSafetyFilterLevel = common.getValueByPath(fromObject, [\n 'safetyFilterLevel',\n ]);\n if (parentObject !== undefined && fromSafetyFilterLevel != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'safetySetting'],\n fromSafetyFilterLevel,\n );\n }\n\n const fromPersonGeneration = common.getValueByPath(fromObject, [\n 'personGeneration',\n ]);\n if (parentObject !== undefined && fromPersonGeneration != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'personGeneration'],\n fromPersonGeneration,\n );\n }\n\n const fromIncludeSafetyAttributes = common.getValueByPath(fromObject, [\n 'includeSafetyAttributes',\n ]);\n if (parentObject !== undefined && fromIncludeSafetyAttributes != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'includeSafetyAttributes'],\n fromIncludeSafetyAttributes,\n );\n }\n\n const fromIncludeRaiReason = common.getValueByPath(fromObject, [\n 'includeRaiReason',\n ]);\n if (parentObject !== undefined && fromIncludeRaiReason != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'includeRaiReason'],\n fromIncludeRaiReason,\n );\n }\n\n const fromLanguage = common.getValueByPath(fromObject, ['language']);\n if (parentObject !== undefined && fromLanguage != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'language'],\n fromLanguage,\n );\n }\n\n const fromOutputMimeType = common.getValueByPath(fromObject, [\n 'outputMimeType',\n ]);\n if (parentObject !== undefined && fromOutputMimeType != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'outputOptions', 'mimeType'],\n fromOutputMimeType,\n );\n }\n\n const fromOutputCompressionQuality = common.getValueByPath(fromObject, [\n 'outputCompressionQuality',\n ]);\n if (parentObject !== undefined && fromOutputCompressionQuality != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'outputOptions', 'compressionQuality'],\n fromOutputCompressionQuality,\n );\n }\n\n const fromAddWatermark = common.getValueByPath(fromObject, ['addWatermark']);\n if (parentObject !== undefined && fromAddWatermark != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'addWatermark'],\n fromAddWatermark,\n );\n }\n\n const fromLabels = common.getValueByPath(fromObject, ['labels']);\n if (parentObject !== undefined && fromLabels != null) {\n common.setValueByPath(parentObject, ['labels'], fromLabels);\n }\n\n const fromEditMode = common.getValueByPath(fromObject, ['editMode']);\n if (parentObject !== undefined && fromEditMode != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'editMode'],\n fromEditMode,\n );\n }\n\n const fromBaseSteps = common.getValueByPath(fromObject, ['baseSteps']);\n if (parentObject !== undefined && fromBaseSteps != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'editConfig', 'baseSteps'],\n fromBaseSteps,\n );\n }\n\n return toObject;\n}\n\nexport function editImageParametersInternalToVertex(\n apiClient: ApiClient,\n fromObject: _internal_types.EditImageParametersInternal,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromPrompt = common.getValueByPath(fromObject, ['prompt']);\n if (fromPrompt != null) {\n common.setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt);\n }\n\n const fromReferenceImages = common.getValueByPath(fromObject, [\n 'referenceImages',\n ]);\n if (fromReferenceImages != null) {\n let transformedList = fromReferenceImages;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return referenceImageAPIInternalToVertex(item, rootObject);\n });\n }\n common.setValueByPath(\n toObject,\n ['instances[0]', 'referenceImages'],\n transformedList,\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n editImageConfigToVertex(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function editImageResponseFromVertex(\n fromObject: types.EditImageResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromGeneratedImages = common.getValueByPath(fromObject, [\n 'predictions',\n ]);\n if (fromGeneratedImages != null) {\n let transformedList = fromGeneratedImages;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return generatedImageFromVertex(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['generatedImages'], transformedList);\n }\n\n return toObject;\n}\n\nexport function embedContentConfigToMldev(\n fromObject: types.EmbedContentConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromTaskType = common.getValueByPath(fromObject, ['taskType']);\n if (parentObject !== undefined && fromTaskType != null) {\n common.setValueByPath(\n parentObject,\n ['requests[]', 'taskType'],\n fromTaskType,\n );\n }\n\n const fromTitle = common.getValueByPath(fromObject, ['title']);\n if (parentObject !== undefined && fromTitle != null) {\n common.setValueByPath(parentObject, ['requests[]', 'title'], fromTitle);\n }\n\n const fromOutputDimensionality = common.getValueByPath(fromObject, [\n 'outputDimensionality',\n ]);\n if (parentObject !== undefined && fromOutputDimensionality != null) {\n common.setValueByPath(\n parentObject,\n ['requests[]', 'outputDimensionality'],\n fromOutputDimensionality,\n );\n }\n\n if (common.getValueByPath(fromObject, ['mimeType']) !== undefined) {\n throw new Error('mimeType parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['autoTruncate']) !== undefined) {\n throw new Error('autoTruncate parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function embedContentConfigToVertex(\n fromObject: types.EmbedContentConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromTaskType = common.getValueByPath(fromObject, ['taskType']);\n if (parentObject !== undefined && fromTaskType != null) {\n common.setValueByPath(\n parentObject,\n ['instances[]', 'task_type'],\n fromTaskType,\n );\n }\n\n const fromTitle = common.getValueByPath(fromObject, ['title']);\n if (parentObject !== undefined && fromTitle != null) {\n common.setValueByPath(parentObject, ['instances[]', 'title'], fromTitle);\n }\n\n const fromOutputDimensionality = common.getValueByPath(fromObject, [\n 'outputDimensionality',\n ]);\n if (parentObject !== undefined && fromOutputDimensionality != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'outputDimensionality'],\n fromOutputDimensionality,\n );\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (parentObject !== undefined && fromMimeType != null) {\n common.setValueByPath(\n parentObject,\n ['instances[]', 'mimeType'],\n fromMimeType,\n );\n }\n\n const fromAutoTruncate = common.getValueByPath(fromObject, ['autoTruncate']);\n if (parentObject !== undefined && fromAutoTruncate != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'autoTruncate'],\n fromAutoTruncate,\n );\n }\n\n return toObject;\n}\n\nexport function embedContentParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.EmbedContentParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromContents = common.getValueByPath(fromObject, ['contents']);\n if (fromContents != null) {\n let transformedList = t.tContentsForEmbed(apiClient, fromContents);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['requests[]', 'content'], transformedList);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n embedContentConfigToMldev(fromConfig, toObject, rootObject);\n }\n\n const fromModelForEmbedContent = common.getValueByPath(fromObject, ['model']);\n if (fromModelForEmbedContent !== undefined) {\n common.setValueByPath(\n toObject,\n ['requests[]', 'model'],\n t.tModel(apiClient, fromModelForEmbedContent),\n );\n }\n\n return toObject;\n}\n\nexport function embedContentParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.EmbedContentParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromContents = common.getValueByPath(fromObject, ['contents']);\n if (fromContents != null) {\n let transformedList = t.tContentsForEmbed(apiClient, fromContents);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(\n toObject,\n ['instances[]', 'content'],\n transformedList,\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n embedContentConfigToVertex(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function embedContentResponseFromMldev(\n fromObject: types.EmbedContentResponse,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromEmbeddings = common.getValueByPath(fromObject, ['embeddings']);\n if (fromEmbeddings != null) {\n let transformedList = fromEmbeddings;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['embeddings'], transformedList);\n }\n\n const fromMetadata = common.getValueByPath(fromObject, ['metadata']);\n if (fromMetadata != null) {\n common.setValueByPath(toObject, ['metadata'], fromMetadata);\n }\n\n return toObject;\n}\n\nexport function embedContentResponseFromVertex(\n fromObject: types.EmbedContentResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromEmbeddings = common.getValueByPath(fromObject, [\n 'predictions[]',\n 'embeddings',\n ]);\n if (fromEmbeddings != null) {\n let transformedList = fromEmbeddings;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return contentEmbeddingFromVertex(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['embeddings'], transformedList);\n }\n\n const fromMetadata = common.getValueByPath(fromObject, ['metadata']);\n if (fromMetadata != null) {\n common.setValueByPath(toObject, ['metadata'], fromMetadata);\n }\n\n return toObject;\n}\n\nexport function endpointFromVertex(\n fromObject: types.Endpoint,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['endpoint']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromDeployedModelId = common.getValueByPath(fromObject, [\n 'deployedModelId',\n ]);\n if (fromDeployedModelId != null) {\n common.setValueByPath(toObject, ['deployedModelId'], fromDeployedModelId);\n }\n\n return toObject;\n}\n\nexport function fileDataToMldev(\n fromObject: types.FileData,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['displayName']) !== undefined) {\n throw new Error('displayName parameter is not supported in Gemini API.');\n }\n\n const fromFileUri = common.getValueByPath(fromObject, ['fileUri']);\n if (fromFileUri != null) {\n common.setValueByPath(toObject, ['fileUri'], fromFileUri);\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function functionCallToMldev(\n fromObject: types.FunctionCall,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromId = common.getValueByPath(fromObject, ['id']);\n if (fromId != null) {\n common.setValueByPath(toObject, ['id'], fromId);\n }\n\n const fromArgs = common.getValueByPath(fromObject, ['args']);\n if (fromArgs != null) {\n common.setValueByPath(toObject, ['args'], fromArgs);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n if (common.getValueByPath(fromObject, ['partialArgs']) !== undefined) {\n throw new Error('partialArgs parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['willContinue']) !== undefined) {\n throw new Error('willContinue parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function functionCallingConfigToMldev(\n fromObject: types.FunctionCallingConfig,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromAllowedFunctionNames = common.getValueByPath(fromObject, [\n 'allowedFunctionNames',\n ]);\n if (fromAllowedFunctionNames != null) {\n common.setValueByPath(\n toObject,\n ['allowedFunctionNames'],\n fromAllowedFunctionNames,\n );\n }\n\n const fromMode = common.getValueByPath(fromObject, ['mode']);\n if (fromMode != null) {\n common.setValueByPath(toObject, ['mode'], fromMode);\n }\n\n if (\n common.getValueByPath(fromObject, ['streamFunctionCallArguments']) !==\n undefined\n ) {\n throw new Error(\n 'streamFunctionCallArguments parameter is not supported in Gemini API.',\n );\n }\n\n return toObject;\n}\n\nexport function functionDeclarationToVertex(\n fromObject: types.FunctionDeclaration,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromDescription = common.getValueByPath(fromObject, ['description']);\n if (fromDescription != null) {\n common.setValueByPath(toObject, ['description'], fromDescription);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromParameters = common.getValueByPath(fromObject, ['parameters']);\n if (fromParameters != null) {\n common.setValueByPath(toObject, ['parameters'], fromParameters);\n }\n\n const fromParametersJsonSchema = common.getValueByPath(fromObject, [\n 'parametersJsonSchema',\n ]);\n if (fromParametersJsonSchema != null) {\n common.setValueByPath(\n toObject,\n ['parametersJsonSchema'],\n fromParametersJsonSchema,\n );\n }\n\n const fromResponse = common.getValueByPath(fromObject, ['response']);\n if (fromResponse != null) {\n common.setValueByPath(toObject, ['response'], fromResponse);\n }\n\n const fromResponseJsonSchema = common.getValueByPath(fromObject, [\n 'responseJsonSchema',\n ]);\n if (fromResponseJsonSchema != null) {\n common.setValueByPath(\n toObject,\n ['responseJsonSchema'],\n fromResponseJsonSchema,\n );\n }\n\n if (common.getValueByPath(fromObject, ['behavior']) !== undefined) {\n throw new Error('behavior parameter is not supported in Vertex AI.');\n }\n\n return toObject;\n}\n\nexport function generateContentConfigToMldev(\n apiClient: ApiClient,\n fromObject: types.GenerateContentConfig,\n parentObject: Record<string, unknown>,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSystemInstruction = common.getValueByPath(fromObject, [\n 'systemInstruction',\n ]);\n if (parentObject !== undefined && fromSystemInstruction != null) {\n common.setValueByPath(\n parentObject,\n ['systemInstruction'],\n contentToMldev(t.tContent(fromSystemInstruction), rootObject),\n );\n }\n\n const fromTemperature = common.getValueByPath(fromObject, ['temperature']);\n if (fromTemperature != null) {\n common.setValueByPath(toObject, ['temperature'], fromTemperature);\n }\n\n const fromTopP = common.getValueByPath(fromObject, ['topP']);\n if (fromTopP != null) {\n common.setValueByPath(toObject, ['topP'], fromTopP);\n }\n\n const fromTopK = common.getValueByPath(fromObject, ['topK']);\n if (fromTopK != null) {\n common.setValueByPath(toObject, ['topK'], fromTopK);\n }\n\n const fromCandidateCount = common.getValueByPath(fromObject, [\n 'candidateCount',\n ]);\n if (fromCandidateCount != null) {\n common.setValueByPath(toObject, ['candidateCount'], fromCandidateCount);\n }\n\n const fromMaxOutputTokens = common.getValueByPath(fromObject, [\n 'maxOutputTokens',\n ]);\n if (fromMaxOutputTokens != null) {\n common.setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens);\n }\n\n const fromStopSequences = common.getValueByPath(fromObject, [\n 'stopSequences',\n ]);\n if (fromStopSequences != null) {\n common.setValueByPath(toObject, ['stopSequences'], fromStopSequences);\n }\n\n const fromResponseLogprobs = common.getValueByPath(fromObject, [\n 'responseLogprobs',\n ]);\n if (fromResponseLogprobs != null) {\n common.setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs);\n }\n\n const fromLogprobs = common.getValueByPath(fromObject, ['logprobs']);\n if (fromLogprobs != null) {\n common.setValueByPath(toObject, ['logprobs'], fromLogprobs);\n }\n\n const fromPresencePenalty = common.getValueByPath(fromObject, [\n 'presencePenalty',\n ]);\n if (fromPresencePenalty != null) {\n common.setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty);\n }\n\n const fromFrequencyPenalty = common.getValueByPath(fromObject, [\n 'frequencyPenalty',\n ]);\n if (fromFrequencyPenalty != null) {\n common.setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty);\n }\n\n const fromSeed = common.getValueByPath(fromObject, ['seed']);\n if (fromSeed != null) {\n common.setValueByPath(toObject, ['seed'], fromSeed);\n }\n\n const fromResponseMimeType = common.getValueByPath(fromObject, [\n 'responseMimeType',\n ]);\n if (fromResponseMimeType != null) {\n common.setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType);\n }\n\n const fromResponseSchema = common.getValueByPath(fromObject, [\n 'responseSchema',\n ]);\n if (fromResponseSchema != null) {\n common.setValueByPath(\n toObject,\n ['responseSchema'],\n t.tSchema(fromResponseSchema),\n );\n }\n\n const fromResponseJsonSchema = common.getValueByPath(fromObject, [\n 'responseJsonSchema',\n ]);\n if (fromResponseJsonSchema != null) {\n common.setValueByPath(\n toObject,\n ['responseJsonSchema'],\n fromResponseJsonSchema,\n );\n }\n\n if (common.getValueByPath(fromObject, ['routingConfig']) !== undefined) {\n throw new Error('routingConfig parameter is not supported in Gemini API.');\n }\n\n if (\n common.getValueByPath(fromObject, ['modelSelectionConfig']) !== undefined\n ) {\n throw new Error(\n 'modelSelectionConfig parameter is not supported in Gemini API.',\n );\n }\n\n const fromSafetySettings = common.getValueByPath(fromObject, [\n 'safetySettings',\n ]);\n if (parentObject !== undefined && fromSafetySettings != null) {\n let transformedList = fromSafetySettings;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return safetySettingToMldev(item, rootObject);\n });\n }\n common.setValueByPath(parentObject, ['safetySettings'], transformedList);\n }\n\n const fromTools = common.getValueByPath(fromObject, ['tools']);\n if (parentObject !== undefined && fromTools != null) {\n let transformedList = t.tTools(fromTools);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return toolToMldev(t.tTool(item), rootObject);\n });\n }\n common.setValueByPath(parentObject, ['tools'], transformedList);\n }\n\n const fromToolConfig = common.getValueByPath(fromObject, ['toolConfig']);\n if (parentObject !== undefined && fromToolConfig != null) {\n common.setValueByPath(\n parentObject,\n ['toolConfig'],\n toolConfigToMldev(fromToolConfig, rootObject),\n );\n }\n\n if (common.getValueByPath(fromObject, ['labels']) !== undefined) {\n throw new Error('labels parameter is not supported in Gemini API.');\n }\n\n const fromCachedContent = common.getValueByPath(fromObject, [\n 'cachedContent',\n ]);\n if (parentObject !== undefined && fromCachedContent != null) {\n common.setValueByPath(\n parentObject,\n ['cachedContent'],\n t.tCachedContentName(apiClient, fromCachedContent),\n );\n }\n\n const fromResponseModalities = common.getValueByPath(fromObject, [\n 'responseModalities',\n ]);\n if (fromResponseModalities != null) {\n common.setValueByPath(\n toObject,\n ['responseModalities'],\n fromResponseModalities,\n );\n }\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (fromMediaResolution != null) {\n common.setValueByPath(toObject, ['mediaResolution'], fromMediaResolution);\n }\n\n const fromSpeechConfig = common.getValueByPath(fromObject, ['speechConfig']);\n if (fromSpeechConfig != null) {\n common.setValueByPath(\n toObject,\n ['speechConfig'],\n t.tSpeechConfig(fromSpeechConfig),\n );\n }\n\n if (common.getValueByPath(fromObject, ['audioTimestamp']) !== undefined) {\n throw new Error('audioTimestamp parameter is not supported in Gemini API.');\n }\n\n const fromThinkingConfig = common.getValueByPath(fromObject, [\n 'thinkingConfig',\n ]);\n if (fromThinkingConfig != null) {\n common.setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig);\n }\n\n const fromImageConfig = common.getValueByPath(fromObject, ['imageConfig']);\n if (fromImageConfig != null) {\n common.setValueByPath(\n toObject,\n ['imageConfig'],\n imageConfigToMldev(fromImageConfig, rootObject),\n );\n }\n\n const fromEnableEnhancedCivicAnswers = common.getValueByPath(fromObject, [\n 'enableEnhancedCivicAnswers',\n ]);\n if (fromEnableEnhancedCivicAnswers != null) {\n common.setValueByPath(\n toObject,\n ['enableEnhancedCivicAnswers'],\n fromEnableEnhancedCivicAnswers,\n );\n }\n\n if (common.getValueByPath(fromObject, ['modelArmorConfig']) !== undefined) {\n throw new Error(\n 'modelArmorConfig parameter is not supported in Gemini API.',\n );\n }\n\n return toObject;\n}\n\nexport function generateContentConfigToVertex(\n apiClient: ApiClient,\n fromObject: types.GenerateContentConfig,\n parentObject: Record<string, unknown>,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSystemInstruction = common.getValueByPath(fromObject, [\n 'systemInstruction',\n ]);\n if (parentObject !== undefined && fromSystemInstruction != null) {\n common.setValueByPath(\n parentObject,\n ['systemInstruction'],\n t.tContent(fromSystemInstruction),\n );\n }\n\n const fromTemperature = common.getValueByPath(fromObject, ['temperature']);\n if (fromTemperature != null) {\n common.setValueByPath(toObject, ['temperature'], fromTemperature);\n }\n\n const fromTopP = common.getValueByPath(fromObject, ['topP']);\n if (fromTopP != null) {\n common.setValueByPath(toObject, ['topP'], fromTopP);\n }\n\n const fromTopK = common.getValueByPath(fromObject, ['topK']);\n if (fromTopK != null) {\n common.setValueByPath(toObject, ['topK'], fromTopK);\n }\n\n const fromCandidateCount = common.getValueByPath(fromObject, [\n 'candidateCount',\n ]);\n if (fromCandidateCount != null) {\n common.setValueByPath(toObject, ['candidateCount'], fromCandidateCount);\n }\n\n const fromMaxOutputTokens = common.getValueByPath(fromObject, [\n 'maxOutputTokens',\n ]);\n if (fromMaxOutputTokens != null) {\n common.setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens);\n }\n\n const fromStopSequences = common.getValueByPath(fromObject, [\n 'stopSequences',\n ]);\n if (fromStopSequences != null) {\n common.setValueByPath(toObject, ['stopSequences'], fromStopSequences);\n }\n\n const fromResponseLogprobs = common.getValueByPath(fromObject, [\n 'responseLogprobs',\n ]);\n if (fromResponseLogprobs != null) {\n common.setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs);\n }\n\n const fromLogprobs = common.getValueByPath(fromObject, ['logprobs']);\n if (fromLogprobs != null) {\n common.setValueByPath(toObject, ['logprobs'], fromLogprobs);\n }\n\n const fromPresencePenalty = common.getValueByPath(fromObject, [\n 'presencePenalty',\n ]);\n if (fromPresencePenalty != null) {\n common.setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty);\n }\n\n const fromFrequencyPenalty = common.getValueByPath(fromObject, [\n 'frequencyPenalty',\n ]);\n if (fromFrequencyPenalty != null) {\n common.setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty);\n }\n\n const fromSeed = common.getValueByPath(fromObject, ['seed']);\n if (fromSeed != null) {\n common.setValueByPath(toObject, ['seed'], fromSeed);\n }\n\n const fromResponseMimeType = common.getValueByPath(fromObject, [\n 'responseMimeType',\n ]);\n if (fromResponseMimeType != null) {\n common.setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType);\n }\n\n const fromResponseSchema = common.getValueByPath(fromObject, [\n 'responseSchema',\n ]);\n if (fromResponseSchema != null) {\n common.setValueByPath(\n toObject,\n ['responseSchema'],\n t.tSchema(fromResponseSchema),\n );\n }\n\n const fromResponseJsonSchema = common.getValueByPath(fromObject, [\n 'responseJsonSchema',\n ]);\n if (fromResponseJsonSchema != null) {\n common.setValueByPath(\n toObject,\n ['responseJsonSchema'],\n fromResponseJsonSchema,\n );\n }\n\n const fromRoutingConfig = common.getValueByPath(fromObject, [\n 'routingConfig',\n ]);\n if (fromRoutingConfig != null) {\n common.setValueByPath(toObject, ['routingConfig'], fromRoutingConfig);\n }\n\n const fromModelSelectionConfig = common.getValueByPath(fromObject, [\n 'modelSelectionConfig',\n ]);\n if (fromModelSelectionConfig != null) {\n common.setValueByPath(toObject, ['modelConfig'], fromModelSelectionConfig);\n }\n\n const fromSafetySettings = common.getValueByPath(fromObject, [\n 'safetySettings',\n ]);\n if (parentObject !== undefined && fromSafetySettings != null) {\n let transformedList = fromSafetySettings;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(parentObject, ['safetySettings'], transformedList);\n }\n\n const fromTools = common.getValueByPath(fromObject, ['tools']);\n if (parentObject !== undefined && fromTools != null) {\n let transformedList = t.tTools(fromTools);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return toolToVertex(t.tTool(item), rootObject);\n });\n }\n common.setValueByPath(parentObject, ['tools'], transformedList);\n }\n\n const fromToolConfig = common.getValueByPath(fromObject, ['toolConfig']);\n if (parentObject !== undefined && fromToolConfig != null) {\n common.setValueByPath(parentObject, ['toolConfig'], fromToolConfig);\n }\n\n const fromLabels = common.getValueByPath(fromObject, ['labels']);\n if (parentObject !== undefined && fromLabels != null) {\n common.setValueByPath(parentObject, ['labels'], fromLabels);\n }\n\n const fromCachedContent = common.getValueByPath(fromObject, [\n 'cachedContent',\n ]);\n if (parentObject !== undefined && fromCachedContent != null) {\n common.setValueByPath(\n parentObject,\n ['cachedContent'],\n t.tCachedContentName(apiClient, fromCachedContent),\n );\n }\n\n const fromResponseModalities = common.getValueByPath(fromObject, [\n 'responseModalities',\n ]);\n if (fromResponseModalities != null) {\n common.setValueByPath(\n toObject,\n ['responseModalities'],\n fromResponseModalities,\n );\n }\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (fromMediaResolution != null) {\n common.setValueByPath(toObject, ['mediaResolution'], fromMediaResolution);\n }\n\n const fromSpeechConfig = common.getValueByPath(fromObject, ['speechConfig']);\n if (fromSpeechConfig != null) {\n common.setValueByPath(\n toObject,\n ['speechConfig'],\n t.tSpeechConfig(fromSpeechConfig),\n );\n }\n\n const fromAudioTimestamp = common.getValueByPath(fromObject, [\n 'audioTimestamp',\n ]);\n if (fromAudioTimestamp != null) {\n common.setValueByPath(toObject, ['audioTimestamp'], fromAudioTimestamp);\n }\n\n const fromThinkingConfig = common.getValueByPath(fromObject, [\n 'thinkingConfig',\n ]);\n if (fromThinkingConfig != null) {\n common.setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig);\n }\n\n const fromImageConfig = common.getValueByPath(fromObject, ['imageConfig']);\n if (fromImageConfig != null) {\n common.setValueByPath(\n toObject,\n ['imageConfig'],\n imageConfigToVertex(fromImageConfig, rootObject),\n );\n }\n\n if (\n common.getValueByPath(fromObject, ['enableEnhancedCivicAnswers']) !==\n undefined\n ) {\n throw new Error(\n 'enableEnhancedCivicAnswers parameter is not supported in Vertex AI.',\n );\n }\n\n const fromModelArmorConfig = common.getValueByPath(fromObject, [\n 'modelArmorConfig',\n ]);\n if (parentObject !== undefined && fromModelArmorConfig != null) {\n common.setValueByPath(\n parentObject,\n ['modelArmorConfig'],\n fromModelArmorConfig,\n );\n }\n\n return toObject;\n}\n\nexport function generateContentParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.GenerateContentParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromContents = common.getValueByPath(fromObject, ['contents']);\n if (fromContents != null) {\n let transformedList = t.tContents(fromContents);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return contentToMldev(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['contents'], transformedList);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n common.setValueByPath(\n toObject,\n ['generationConfig'],\n generateContentConfigToMldev(apiClient, fromConfig, toObject, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function generateContentParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.GenerateContentParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromContents = common.getValueByPath(fromObject, ['contents']);\n if (fromContents != null) {\n let transformedList = t.tContents(fromContents);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['contents'], transformedList);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n common.setValueByPath(\n toObject,\n ['generationConfig'],\n generateContentConfigToVertex(\n apiClient,\n fromConfig,\n toObject,\n rootObject,\n ),\n );\n }\n\n return toObject;\n}\n\nexport function generateContentResponseFromMldev(\n fromObject: types.GenerateContentResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromCandidates = common.getValueByPath(fromObject, ['candidates']);\n if (fromCandidates != null) {\n let transformedList = fromCandidates;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return candidateFromMldev(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['candidates'], transformedList);\n }\n\n const fromModelVersion = common.getValueByPath(fromObject, ['modelVersion']);\n if (fromModelVersion != null) {\n common.setValueByPath(toObject, ['modelVersion'], fromModelVersion);\n }\n\n const fromPromptFeedback = common.getValueByPath(fromObject, [\n 'promptFeedback',\n ]);\n if (fromPromptFeedback != null) {\n common.setValueByPath(toObject, ['promptFeedback'], fromPromptFeedback);\n }\n\n const fromResponseId = common.getValueByPath(fromObject, ['responseId']);\n if (fromResponseId != null) {\n common.setValueByPath(toObject, ['responseId'], fromResponseId);\n }\n\n const fromUsageMetadata = common.getValueByPath(fromObject, [\n 'usageMetadata',\n ]);\n if (fromUsageMetadata != null) {\n common.setValueByPath(toObject, ['usageMetadata'], fromUsageMetadata);\n }\n\n return toObject;\n}\n\nexport function generateContentResponseFromVertex(\n fromObject: types.GenerateContentResponse,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromCandidates = common.getValueByPath(fromObject, ['candidates']);\n if (fromCandidates != null) {\n let transformedList = fromCandidates;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['candidates'], transformedList);\n }\n\n const fromCreateTime = common.getValueByPath(fromObject, ['createTime']);\n if (fromCreateTime != null) {\n common.setValueByPath(toObject, ['createTime'], fromCreateTime);\n }\n\n const fromModelVersion = common.getValueByPath(fromObject, ['modelVersion']);\n if (fromModelVersion != null) {\n common.setValueByPath(toObject, ['modelVersion'], fromModelVersion);\n }\n\n const fromPromptFeedback = common.getValueByPath(fromObject, [\n 'promptFeedback',\n ]);\n if (fromPromptFeedback != null) {\n common.setValueByPath(toObject, ['promptFeedback'], fromPromptFeedback);\n }\n\n const fromResponseId = common.getValueByPath(fromObject, ['responseId']);\n if (fromResponseId != null) {\n common.setValueByPath(toObject, ['responseId'], fromResponseId);\n }\n\n const fromUsageMetadata = common.getValueByPath(fromObject, [\n 'usageMetadata',\n ]);\n if (fromUsageMetadata != null) {\n common.setValueByPath(toObject, ['usageMetadata'], fromUsageMetadata);\n }\n\n return toObject;\n}\n\nexport function generateImagesConfigToMldev(\n fromObject: types.GenerateImagesConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['outputGcsUri']) !== undefined) {\n throw new Error('outputGcsUri parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['negativePrompt']) !== undefined) {\n throw new Error('negativePrompt parameter is not supported in Gemini API.');\n }\n\n const fromNumberOfImages = common.getValueByPath(fromObject, [\n 'numberOfImages',\n ]);\n if (parentObject !== undefined && fromNumberOfImages != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'sampleCount'],\n fromNumberOfImages,\n );\n }\n\n const fromAspectRatio = common.getValueByPath(fromObject, ['aspectRatio']);\n if (parentObject !== undefined && fromAspectRatio != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'aspectRatio'],\n fromAspectRatio,\n );\n }\n\n const fromGuidanceScale = common.getValueByPath(fromObject, [\n 'guidanceScale',\n ]);\n if (parentObject !== undefined && fromGuidanceScale != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'guidanceScale'],\n fromGuidanceScale,\n );\n }\n\n if (common.getValueByPath(fromObject, ['seed']) !== undefined) {\n throw new Error('seed parameter is not supported in Gemini API.');\n }\n\n const fromSafetyFilterLevel = common.getValueByPath(fromObject, [\n 'safetyFilterLevel',\n ]);\n if (parentObject !== undefined && fromSafetyFilterLevel != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'safetySetting'],\n fromSafetyFilterLevel,\n );\n }\n\n const fromPersonGeneration = common.getValueByPath(fromObject, [\n 'personGeneration',\n ]);\n if (parentObject !== undefined && fromPersonGeneration != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'personGeneration'],\n fromPersonGeneration,\n );\n }\n\n const fromIncludeSafetyAttributes = common.getValueByPath(fromObject, [\n 'includeSafetyAttributes',\n ]);\n if (parentObject !== undefined && fromIncludeSafetyAttributes != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'includeSafetyAttributes'],\n fromIncludeSafetyAttributes,\n );\n }\n\n const fromIncludeRaiReason = common.getValueByPath(fromObject, [\n 'includeRaiReason',\n ]);\n if (parentObject !== undefined && fromIncludeRaiReason != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'includeRaiReason'],\n fromIncludeRaiReason,\n );\n }\n\n const fromLanguage = common.getValueByPath(fromObject, ['language']);\n if (parentObject !== undefined && fromLanguage != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'language'],\n fromLanguage,\n );\n }\n\n const fromOutputMimeType = common.getValueByPath(fromObject, [\n 'outputMimeType',\n ]);\n if (parentObject !== undefined && fromOutputMimeType != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'outputOptions', 'mimeType'],\n fromOutputMimeType,\n );\n }\n\n const fromOutputCompressionQuality = common.getValueByPath(fromObject, [\n 'outputCompressionQuality',\n ]);\n if (parentObject !== undefined && fromOutputCompressionQuality != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'outputOptions', 'compressionQuality'],\n fromOutputCompressionQuality,\n );\n }\n\n if (common.getValueByPath(fromObject, ['addWatermark']) !== undefined) {\n throw new Error('addWatermark parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['labels']) !== undefined) {\n throw new Error('labels parameter is not supported in Gemini API.');\n }\n\n const fromImageSize = common.getValueByPath(fromObject, ['imageSize']);\n if (parentObject !== undefined && fromImageSize != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'sampleImageSize'],\n fromImageSize,\n );\n }\n\n if (common.getValueByPath(fromObject, ['enhancePrompt']) !== undefined) {\n throw new Error('enhancePrompt parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function generateImagesConfigToVertex(\n fromObject: types.GenerateImagesConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromOutputGcsUri = common.getValueByPath(fromObject, ['outputGcsUri']);\n if (parentObject !== undefined && fromOutputGcsUri != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'storageUri'],\n fromOutputGcsUri,\n );\n }\n\n const fromNegativePrompt = common.getValueByPath(fromObject, [\n 'negativePrompt',\n ]);\n if (parentObject !== undefined && fromNegativePrompt != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'negativePrompt'],\n fromNegativePrompt,\n );\n }\n\n const fromNumberOfImages = common.getValueByPath(fromObject, [\n 'numberOfImages',\n ]);\n if (parentObject !== undefined && fromNumberOfImages != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'sampleCount'],\n fromNumberOfImages,\n );\n }\n\n const fromAspectRatio = common.getValueByPath(fromObject, ['aspectRatio']);\n if (parentObject !== undefined && fromAspectRatio != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'aspectRatio'],\n fromAspectRatio,\n );\n }\n\n const fromGuidanceScale = common.getValueByPath(fromObject, [\n 'guidanceScale',\n ]);\n if (parentObject !== undefined && fromGuidanceScale != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'guidanceScale'],\n fromGuidanceScale,\n );\n }\n\n const fromSeed = common.getValueByPath(fromObject, ['seed']);\n if (parentObject !== undefined && fromSeed != null) {\n common.setValueByPath(parentObject, ['parameters', 'seed'], fromSeed);\n }\n\n const fromSafetyFilterLevel = common.getValueByPath(fromObject, [\n 'safetyFilterLevel',\n ]);\n if (parentObject !== undefined && fromSafetyFilterLevel != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'safetySetting'],\n fromSafetyFilterLevel,\n );\n }\n\n const fromPersonGeneration = common.getValueByPath(fromObject, [\n 'personGeneration',\n ]);\n if (parentObject !== undefined && fromPersonGeneration != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'personGeneration'],\n fromPersonGeneration,\n );\n }\n\n const fromIncludeSafetyAttributes = common.getValueByPath(fromObject, [\n 'includeSafetyAttributes',\n ]);\n if (parentObject !== undefined && fromIncludeSafetyAttributes != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'includeSafetyAttributes'],\n fromIncludeSafetyAttributes,\n );\n }\n\n const fromIncludeRaiReason = common.getValueByPath(fromObject, [\n 'includeRaiReason',\n ]);\n if (parentObject !== undefined && fromIncludeRaiReason != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'includeRaiReason'],\n fromIncludeRaiReason,\n );\n }\n\n const fromLanguage = common.getValueByPath(fromObject, ['language']);\n if (parentObject !== undefined && fromLanguage != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'language'],\n fromLanguage,\n );\n }\n\n const fromOutputMimeType = common.getValueByPath(fromObject, [\n 'outputMimeType',\n ]);\n if (parentObject !== undefined && fromOutputMimeType != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'outputOptions', 'mimeType'],\n fromOutputMimeType,\n );\n }\n\n const fromOutputCompressionQuality = common.getValueByPath(fromObject, [\n 'outputCompressionQuality',\n ]);\n if (parentObject !== undefined && fromOutputCompressionQuality != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'outputOptions', 'compressionQuality'],\n fromOutputCompressionQuality,\n );\n }\n\n const fromAddWatermark = common.getValueByPath(fromObject, ['addWatermark']);\n if (parentObject !== undefined && fromAddWatermark != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'addWatermark'],\n fromAddWatermark,\n );\n }\n\n const fromLabels = common.getValueByPath(fromObject, ['labels']);\n if (parentObject !== undefined && fromLabels != null) {\n common.setValueByPath(parentObject, ['labels'], fromLabels);\n }\n\n const fromImageSize = common.getValueByPath(fromObject, ['imageSize']);\n if (parentObject !== undefined && fromImageSize != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'sampleImageSize'],\n fromImageSize,\n );\n }\n\n const fromEnhancePrompt = common.getValueByPath(fromObject, [\n 'enhancePrompt',\n ]);\n if (parentObject !== undefined && fromEnhancePrompt != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'enhancePrompt'],\n fromEnhancePrompt,\n );\n }\n\n return toObject;\n}\n\nexport function generateImagesParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.GenerateImagesParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromPrompt = common.getValueByPath(fromObject, ['prompt']);\n if (fromPrompt != null) {\n common.setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n generateImagesConfigToMldev(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function generateImagesParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.GenerateImagesParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromPrompt = common.getValueByPath(fromObject, ['prompt']);\n if (fromPrompt != null) {\n common.setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n generateImagesConfigToVertex(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function generateImagesResponseFromMldev(\n fromObject: types.GenerateImagesResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromGeneratedImages = common.getValueByPath(fromObject, [\n 'predictions',\n ]);\n if (fromGeneratedImages != null) {\n let transformedList = fromGeneratedImages;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return generatedImageFromMldev(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['generatedImages'], transformedList);\n }\n\n const fromPositivePromptSafetyAttributes = common.getValueByPath(fromObject, [\n 'positivePromptSafetyAttributes',\n ]);\n if (fromPositivePromptSafetyAttributes != null) {\n common.setValueByPath(\n toObject,\n ['positivePromptSafetyAttributes'],\n safetyAttributesFromMldev(fromPositivePromptSafetyAttributes, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function generateImagesResponseFromVertex(\n fromObject: types.GenerateImagesResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromGeneratedImages = common.getValueByPath(fromObject, [\n 'predictions',\n ]);\n if (fromGeneratedImages != null) {\n let transformedList = fromGeneratedImages;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return generatedImageFromVertex(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['generatedImages'], transformedList);\n }\n\n const fromPositivePromptSafetyAttributes = common.getValueByPath(fromObject, [\n 'positivePromptSafetyAttributes',\n ]);\n if (fromPositivePromptSafetyAttributes != null) {\n common.setValueByPath(\n toObject,\n ['positivePromptSafetyAttributes'],\n safetyAttributesFromVertex(\n fromPositivePromptSafetyAttributes,\n rootObject,\n ),\n );\n }\n\n return toObject;\n}\n\nexport function generateVideosConfigToMldev(\n fromObject: types.GenerateVideosConfig,\n parentObject: Record<string, unknown>,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromNumberOfVideos = common.getValueByPath(fromObject, [\n 'numberOfVideos',\n ]);\n if (parentObject !== undefined && fromNumberOfVideos != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'sampleCount'],\n fromNumberOfVideos,\n );\n }\n\n if (common.getValueByPath(fromObject, ['outputGcsUri']) !== undefined) {\n throw new Error('outputGcsUri parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['fps']) !== undefined) {\n throw new Error('fps parameter is not supported in Gemini API.');\n }\n\n const fromDurationSeconds = common.getValueByPath(fromObject, [\n 'durationSeconds',\n ]);\n if (parentObject !== undefined && fromDurationSeconds != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'durationSeconds'],\n fromDurationSeconds,\n );\n }\n\n if (common.getValueByPath(fromObject, ['seed']) !== undefined) {\n throw new Error('seed parameter is not supported in Gemini API.');\n }\n\n const fromAspectRatio = common.getValueByPath(fromObject, ['aspectRatio']);\n if (parentObject !== undefined && fromAspectRatio != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'aspectRatio'],\n fromAspectRatio,\n );\n }\n\n const fromResolution = common.getValueByPath(fromObject, ['resolution']);\n if (parentObject !== undefined && fromResolution != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'resolution'],\n fromResolution,\n );\n }\n\n const fromPersonGeneration = common.getValueByPath(fromObject, [\n 'personGeneration',\n ]);\n if (parentObject !== undefined && fromPersonGeneration != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'personGeneration'],\n fromPersonGeneration,\n );\n }\n\n if (common.getValueByPath(fromObject, ['pubsubTopic']) !== undefined) {\n throw new Error('pubsubTopic parameter is not supported in Gemini API.');\n }\n\n const fromNegativePrompt = common.getValueByPath(fromObject, [\n 'negativePrompt',\n ]);\n if (parentObject !== undefined && fromNegativePrompt != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'negativePrompt'],\n fromNegativePrompt,\n );\n }\n\n const fromEnhancePrompt = common.getValueByPath(fromObject, [\n 'enhancePrompt',\n ]);\n if (parentObject !== undefined && fromEnhancePrompt != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'enhancePrompt'],\n fromEnhancePrompt,\n );\n }\n\n if (common.getValueByPath(fromObject, ['generateAudio']) !== undefined) {\n throw new Error('generateAudio parameter is not supported in Gemini API.');\n }\n\n const fromLastFrame = common.getValueByPath(fromObject, ['lastFrame']);\n if (parentObject !== undefined && fromLastFrame != null) {\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'lastFrame'],\n imageToMldev(fromLastFrame, rootObject),\n );\n }\n\n const fromReferenceImages = common.getValueByPath(fromObject, [\n 'referenceImages',\n ]);\n if (parentObject !== undefined && fromReferenceImages != null) {\n let transformedList = fromReferenceImages;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return videoGenerationReferenceImageToMldev(item, rootObject);\n });\n }\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'referenceImages'],\n transformedList,\n );\n }\n\n if (common.getValueByPath(fromObject, ['mask']) !== undefined) {\n throw new Error('mask parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['compressionQuality']) !== undefined) {\n throw new Error(\n 'compressionQuality parameter is not supported in Gemini API.',\n );\n }\n\n return toObject;\n}\n\nexport function generateVideosConfigToVertex(\n fromObject: types.GenerateVideosConfig,\n parentObject: Record<string, unknown>,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromNumberOfVideos = common.getValueByPath(fromObject, [\n 'numberOfVideos',\n ]);\n if (parentObject !== undefined && fromNumberOfVideos != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'sampleCount'],\n fromNumberOfVideos,\n );\n }\n\n const fromOutputGcsUri = common.getValueByPath(fromObject, ['outputGcsUri']);\n if (parentObject !== undefined && fromOutputGcsUri != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'storageUri'],\n fromOutputGcsUri,\n );\n }\n\n const fromFps = common.getValueByPath(fromObject, ['fps']);\n if (parentObject !== undefined && fromFps != null) {\n common.setValueByPath(parentObject, ['parameters', 'fps'], fromFps);\n }\n\n const fromDurationSeconds = common.getValueByPath(fromObject, [\n 'durationSeconds',\n ]);\n if (parentObject !== undefined && fromDurationSeconds != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'durationSeconds'],\n fromDurationSeconds,\n );\n }\n\n const fromSeed = common.getValueByPath(fromObject, ['seed']);\n if (parentObject !== undefined && fromSeed != null) {\n common.setValueByPath(parentObject, ['parameters', 'seed'], fromSeed);\n }\n\n const fromAspectRatio = common.getValueByPath(fromObject, ['aspectRatio']);\n if (parentObject !== undefined && fromAspectRatio != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'aspectRatio'],\n fromAspectRatio,\n );\n }\n\n const fromResolution = common.getValueByPath(fromObject, ['resolution']);\n if (parentObject !== undefined && fromResolution != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'resolution'],\n fromResolution,\n );\n }\n\n const fromPersonGeneration = common.getValueByPath(fromObject, [\n 'personGeneration',\n ]);\n if (parentObject !== undefined && fromPersonGeneration != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'personGeneration'],\n fromPersonGeneration,\n );\n }\n\n const fromPubsubTopic = common.getValueByPath(fromObject, ['pubsubTopic']);\n if (parentObject !== undefined && fromPubsubTopic != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'pubsubTopic'],\n fromPubsubTopic,\n );\n }\n\n const fromNegativePrompt = common.getValueByPath(fromObject, [\n 'negativePrompt',\n ]);\n if (parentObject !== undefined && fromNegativePrompt != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'negativePrompt'],\n fromNegativePrompt,\n );\n }\n\n const fromEnhancePrompt = common.getValueByPath(fromObject, [\n 'enhancePrompt',\n ]);\n if (parentObject !== undefined && fromEnhancePrompt != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'enhancePrompt'],\n fromEnhancePrompt,\n );\n }\n\n const fromGenerateAudio = common.getValueByPath(fromObject, [\n 'generateAudio',\n ]);\n if (parentObject !== undefined && fromGenerateAudio != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'generateAudio'],\n fromGenerateAudio,\n );\n }\n\n const fromLastFrame = common.getValueByPath(fromObject, ['lastFrame']);\n if (parentObject !== undefined && fromLastFrame != null) {\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'lastFrame'],\n imageToVertex(fromLastFrame, rootObject),\n );\n }\n\n const fromReferenceImages = common.getValueByPath(fromObject, [\n 'referenceImages',\n ]);\n if (parentObject !== undefined && fromReferenceImages != null) {\n let transformedList = fromReferenceImages;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return videoGenerationReferenceImageToVertex(item, rootObject);\n });\n }\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'referenceImages'],\n transformedList,\n );\n }\n\n const fromMask = common.getValueByPath(fromObject, ['mask']);\n if (parentObject !== undefined && fromMask != null) {\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'mask'],\n videoGenerationMaskToVertex(fromMask, rootObject),\n );\n }\n\n const fromCompressionQuality = common.getValueByPath(fromObject, [\n 'compressionQuality',\n ]);\n if (parentObject !== undefined && fromCompressionQuality != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'compressionQuality'],\n fromCompressionQuality,\n );\n }\n\n return toObject;\n}\n\nexport function generateVideosOperationFromMldev(\n fromObject: types.GenerateVideosOperation,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromMetadata = common.getValueByPath(fromObject, ['metadata']);\n if (fromMetadata != null) {\n common.setValueByPath(toObject, ['metadata'], fromMetadata);\n }\n\n const fromDone = common.getValueByPath(fromObject, ['done']);\n if (fromDone != null) {\n common.setValueByPath(toObject, ['done'], fromDone);\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n const fromResponse = common.getValueByPath(fromObject, [\n 'response',\n 'generateVideoResponse',\n ]);\n if (fromResponse != null) {\n common.setValueByPath(\n toObject,\n ['response'],\n generateVideosResponseFromMldev(fromResponse, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function generateVideosOperationFromVertex(\n fromObject: types.GenerateVideosOperation,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromMetadata = common.getValueByPath(fromObject, ['metadata']);\n if (fromMetadata != null) {\n common.setValueByPath(toObject, ['metadata'], fromMetadata);\n }\n\n const fromDone = common.getValueByPath(fromObject, ['done']);\n if (fromDone != null) {\n common.setValueByPath(toObject, ['done'], fromDone);\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n const fromResponse = common.getValueByPath(fromObject, ['response']);\n if (fromResponse != null) {\n common.setValueByPath(\n toObject,\n ['response'],\n generateVideosResponseFromVertex(fromResponse, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function generateVideosParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.GenerateVideosParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromPrompt = common.getValueByPath(fromObject, ['prompt']);\n if (fromPrompt != null) {\n common.setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt);\n }\n\n const fromImage = common.getValueByPath(fromObject, ['image']);\n if (fromImage != null) {\n common.setValueByPath(\n toObject,\n ['instances[0]', 'image'],\n imageToMldev(fromImage, rootObject),\n );\n }\n\n const fromVideo = common.getValueByPath(fromObject, ['video']);\n if (fromVideo != null) {\n common.setValueByPath(\n toObject,\n ['instances[0]', 'video'],\n videoToMldev(fromVideo, rootObject),\n );\n }\n\n const fromSource = common.getValueByPath(fromObject, ['source']);\n if (fromSource != null) {\n generateVideosSourceToMldev(fromSource, toObject, rootObject);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n generateVideosConfigToMldev(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function generateVideosParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.GenerateVideosParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromPrompt = common.getValueByPath(fromObject, ['prompt']);\n if (fromPrompt != null) {\n common.setValueByPath(toObject, ['instances[0]', 'prompt'], fromPrompt);\n }\n\n const fromImage = common.getValueByPath(fromObject, ['image']);\n if (fromImage != null) {\n common.setValueByPath(\n toObject,\n ['instances[0]', 'image'],\n imageToVertex(fromImage, rootObject),\n );\n }\n\n const fromVideo = common.getValueByPath(fromObject, ['video']);\n if (fromVideo != null) {\n common.setValueByPath(\n toObject,\n ['instances[0]', 'video'],\n videoToVertex(fromVideo, rootObject),\n );\n }\n\n const fromSource = common.getValueByPath(fromObject, ['source']);\n if (fromSource != null) {\n generateVideosSourceToVertex(fromSource, toObject, rootObject);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n generateVideosConfigToVertex(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function generateVideosResponseFromMldev(\n fromObject: types.GenerateVideosResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromGeneratedVideos = common.getValueByPath(fromObject, [\n 'generatedSamples',\n ]);\n if (fromGeneratedVideos != null) {\n let transformedList = fromGeneratedVideos;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return generatedVideoFromMldev(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['generatedVideos'], transformedList);\n }\n\n const fromRaiMediaFilteredCount = common.getValueByPath(fromObject, [\n 'raiMediaFilteredCount',\n ]);\n if (fromRaiMediaFilteredCount != null) {\n common.setValueByPath(\n toObject,\n ['raiMediaFilteredCount'],\n fromRaiMediaFilteredCount,\n );\n }\n\n const fromRaiMediaFilteredReasons = common.getValueByPath(fromObject, [\n 'raiMediaFilteredReasons',\n ]);\n if (fromRaiMediaFilteredReasons != null) {\n common.setValueByPath(\n toObject,\n ['raiMediaFilteredReasons'],\n fromRaiMediaFilteredReasons,\n );\n }\n\n return toObject;\n}\n\nexport function generateVideosResponseFromVertex(\n fromObject: types.GenerateVideosResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromGeneratedVideos = common.getValueByPath(fromObject, ['videos']);\n if (fromGeneratedVideos != null) {\n let transformedList = fromGeneratedVideos;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return generatedVideoFromVertex(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['generatedVideos'], transformedList);\n }\n\n const fromRaiMediaFilteredCount = common.getValueByPath(fromObject, [\n 'raiMediaFilteredCount',\n ]);\n if (fromRaiMediaFilteredCount != null) {\n common.setValueByPath(\n toObject,\n ['raiMediaFilteredCount'],\n fromRaiMediaFilteredCount,\n );\n }\n\n const fromRaiMediaFilteredReasons = common.getValueByPath(fromObject, [\n 'raiMediaFilteredReasons',\n ]);\n if (fromRaiMediaFilteredReasons != null) {\n common.setValueByPath(\n toObject,\n ['raiMediaFilteredReasons'],\n fromRaiMediaFilteredReasons,\n );\n }\n\n return toObject;\n}\n\nexport function generateVideosSourceToMldev(\n fromObject: types.GenerateVideosSource,\n parentObject: Record<string, unknown>,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPrompt = common.getValueByPath(fromObject, ['prompt']);\n if (parentObject !== undefined && fromPrompt != null) {\n common.setValueByPath(parentObject, ['instances[0]', 'prompt'], fromPrompt);\n }\n\n const fromImage = common.getValueByPath(fromObject, ['image']);\n if (parentObject !== undefined && fromImage != null) {\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'image'],\n imageToMldev(fromImage, rootObject),\n );\n }\n\n const fromVideo = common.getValueByPath(fromObject, ['video']);\n if (parentObject !== undefined && fromVideo != null) {\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'video'],\n videoToMldev(fromVideo, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function generateVideosSourceToVertex(\n fromObject: types.GenerateVideosSource,\n parentObject: Record<string, unknown>,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPrompt = common.getValueByPath(fromObject, ['prompt']);\n if (parentObject !== undefined && fromPrompt != null) {\n common.setValueByPath(parentObject, ['instances[0]', 'prompt'], fromPrompt);\n }\n\n const fromImage = common.getValueByPath(fromObject, ['image']);\n if (parentObject !== undefined && fromImage != null) {\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'image'],\n imageToVertex(fromImage, rootObject),\n );\n }\n\n const fromVideo = common.getValueByPath(fromObject, ['video']);\n if (parentObject !== undefined && fromVideo != null) {\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'video'],\n videoToVertex(fromVideo, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function generatedImageFromMldev(\n fromObject: types.GeneratedImage,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromImage = common.getValueByPath(fromObject, ['_self']);\n if (fromImage != null) {\n common.setValueByPath(\n toObject,\n ['image'],\n imageFromMldev(fromImage, rootObject),\n );\n }\n\n const fromRaiFilteredReason = common.getValueByPath(fromObject, [\n 'raiFilteredReason',\n ]);\n if (fromRaiFilteredReason != null) {\n common.setValueByPath(\n toObject,\n ['raiFilteredReason'],\n fromRaiFilteredReason,\n );\n }\n\n const fromSafetyAttributes = common.getValueByPath(fromObject, ['_self']);\n if (fromSafetyAttributes != null) {\n common.setValueByPath(\n toObject,\n ['safetyAttributes'],\n safetyAttributesFromMldev(fromSafetyAttributes, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function generatedImageFromVertex(\n fromObject: types.GeneratedImage,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromImage = common.getValueByPath(fromObject, ['_self']);\n if (fromImage != null) {\n common.setValueByPath(\n toObject,\n ['image'],\n imageFromVertex(fromImage, rootObject),\n );\n }\n\n const fromRaiFilteredReason = common.getValueByPath(fromObject, [\n 'raiFilteredReason',\n ]);\n if (fromRaiFilteredReason != null) {\n common.setValueByPath(\n toObject,\n ['raiFilteredReason'],\n fromRaiFilteredReason,\n );\n }\n\n const fromSafetyAttributes = common.getValueByPath(fromObject, ['_self']);\n if (fromSafetyAttributes != null) {\n common.setValueByPath(\n toObject,\n ['safetyAttributes'],\n safetyAttributesFromVertex(fromSafetyAttributes, rootObject),\n );\n }\n\n const fromEnhancedPrompt = common.getValueByPath(fromObject, ['prompt']);\n if (fromEnhancedPrompt != null) {\n common.setValueByPath(toObject, ['enhancedPrompt'], fromEnhancedPrompt);\n }\n\n return toObject;\n}\n\nexport function generatedImageMaskFromVertex(\n fromObject: types.GeneratedImageMask,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMask = common.getValueByPath(fromObject, ['_self']);\n if (fromMask != null) {\n common.setValueByPath(\n toObject,\n ['mask'],\n imageFromVertex(fromMask, rootObject),\n );\n }\n\n const fromLabels = common.getValueByPath(fromObject, ['labels']);\n if (fromLabels != null) {\n let transformedList = fromLabels;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['labels'], transformedList);\n }\n\n return toObject;\n}\n\nexport function generatedVideoFromMldev(\n fromObject: types.GeneratedVideo,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromVideo = common.getValueByPath(fromObject, ['video']);\n if (fromVideo != null) {\n common.setValueByPath(\n toObject,\n ['video'],\n videoFromMldev(fromVideo, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function generatedVideoFromVertex(\n fromObject: types.GeneratedVideo,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromVideo = common.getValueByPath(fromObject, ['_self']);\n if (fromVideo != null) {\n common.setValueByPath(\n toObject,\n ['video'],\n videoFromVertex(fromVideo, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function generationConfigToVertex(\n fromObject: types.GenerationConfig,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModelSelectionConfig = common.getValueByPath(fromObject, [\n 'modelSelectionConfig',\n ]);\n if (fromModelSelectionConfig != null) {\n common.setValueByPath(toObject, ['modelConfig'], fromModelSelectionConfig);\n }\n\n const fromResponseJsonSchema = common.getValueByPath(fromObject, [\n 'responseJsonSchema',\n ]);\n if (fromResponseJsonSchema != null) {\n common.setValueByPath(\n toObject,\n ['responseJsonSchema'],\n fromResponseJsonSchema,\n );\n }\n\n const fromAudioTimestamp = common.getValueByPath(fromObject, [\n 'audioTimestamp',\n ]);\n if (fromAudioTimestamp != null) {\n common.setValueByPath(toObject, ['audioTimestamp'], fromAudioTimestamp);\n }\n\n const fromCandidateCount = common.getValueByPath(fromObject, [\n 'candidateCount',\n ]);\n if (fromCandidateCount != null) {\n common.setValueByPath(toObject, ['candidateCount'], fromCandidateCount);\n }\n\n const fromEnableAffectiveDialog = common.getValueByPath(fromObject, [\n 'enableAffectiveDialog',\n ]);\n if (fromEnableAffectiveDialog != null) {\n common.setValueByPath(\n toObject,\n ['enableAffectiveDialog'],\n fromEnableAffectiveDialog,\n );\n }\n\n const fromFrequencyPenalty = common.getValueByPath(fromObject, [\n 'frequencyPenalty',\n ]);\n if (fromFrequencyPenalty != null) {\n common.setValueByPath(toObject, ['frequencyPenalty'], fromFrequencyPenalty);\n }\n\n const fromLogprobs = common.getValueByPath(fromObject, ['logprobs']);\n if (fromLogprobs != null) {\n common.setValueByPath(toObject, ['logprobs'], fromLogprobs);\n }\n\n const fromMaxOutputTokens = common.getValueByPath(fromObject, [\n 'maxOutputTokens',\n ]);\n if (fromMaxOutputTokens != null) {\n common.setValueByPath(toObject, ['maxOutputTokens'], fromMaxOutputTokens);\n }\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (fromMediaResolution != null) {\n common.setValueByPath(toObject, ['mediaResolution'], fromMediaResolution);\n }\n\n const fromPresencePenalty = common.getValueByPath(fromObject, [\n 'presencePenalty',\n ]);\n if (fromPresencePenalty != null) {\n common.setValueByPath(toObject, ['presencePenalty'], fromPresencePenalty);\n }\n\n const fromResponseLogprobs = common.getValueByPath(fromObject, [\n 'responseLogprobs',\n ]);\n if (fromResponseLogprobs != null) {\n common.setValueByPath(toObject, ['responseLogprobs'], fromResponseLogprobs);\n }\n\n const fromResponseMimeType = common.getValueByPath(fromObject, [\n 'responseMimeType',\n ]);\n if (fromResponseMimeType != null) {\n common.setValueByPath(toObject, ['responseMimeType'], fromResponseMimeType);\n }\n\n const fromResponseModalities = common.getValueByPath(fromObject, [\n 'responseModalities',\n ]);\n if (fromResponseModalities != null) {\n common.setValueByPath(\n toObject,\n ['responseModalities'],\n fromResponseModalities,\n );\n }\n\n const fromResponseSchema = common.getValueByPath(fromObject, [\n 'responseSchema',\n ]);\n if (fromResponseSchema != null) {\n common.setValueByPath(toObject, ['responseSchema'], fromResponseSchema);\n }\n\n const fromRoutingConfig = common.getValueByPath(fromObject, [\n 'routingConfig',\n ]);\n if (fromRoutingConfig != null) {\n common.setValueByPath(toObject, ['routingConfig'], fromRoutingConfig);\n }\n\n const fromSeed = common.getValueByPath(fromObject, ['seed']);\n if (fromSeed != null) {\n common.setValueByPath(toObject, ['seed'], fromSeed);\n }\n\n const fromSpeechConfig = common.getValueByPath(fromObject, ['speechConfig']);\n if (fromSpeechConfig != null) {\n common.setValueByPath(toObject, ['speechConfig'], fromSpeechConfig);\n }\n\n const fromStopSequences = common.getValueByPath(fromObject, [\n 'stopSequences',\n ]);\n if (fromStopSequences != null) {\n common.setValueByPath(toObject, ['stopSequences'], fromStopSequences);\n }\n\n const fromTemperature = common.getValueByPath(fromObject, ['temperature']);\n if (fromTemperature != null) {\n common.setValueByPath(toObject, ['temperature'], fromTemperature);\n }\n\n const fromThinkingConfig = common.getValueByPath(fromObject, [\n 'thinkingConfig',\n ]);\n if (fromThinkingConfig != null) {\n common.setValueByPath(toObject, ['thinkingConfig'], fromThinkingConfig);\n }\n\n const fromTopK = common.getValueByPath(fromObject, ['topK']);\n if (fromTopK != null) {\n common.setValueByPath(toObject, ['topK'], fromTopK);\n }\n\n const fromTopP = common.getValueByPath(fromObject, ['topP']);\n if (fromTopP != null) {\n common.setValueByPath(toObject, ['topP'], fromTopP);\n }\n\n if (\n common.getValueByPath(fromObject, ['enableEnhancedCivicAnswers']) !==\n undefined\n ) {\n throw new Error(\n 'enableEnhancedCivicAnswers parameter is not supported in Vertex AI.',\n );\n }\n\n return toObject;\n}\n\nexport function getModelParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.GetModelParameters,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n return toObject;\n}\n\nexport function getModelParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.GetModelParameters,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n return toObject;\n}\n\nexport function googleMapsToMldev(\n fromObject: types.GoogleMaps,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['authConfig']) !== undefined) {\n throw new Error('authConfig parameter is not supported in Gemini API.');\n }\n\n const fromEnableWidget = common.getValueByPath(fromObject, ['enableWidget']);\n if (fromEnableWidget != null) {\n common.setValueByPath(toObject, ['enableWidget'], fromEnableWidget);\n }\n\n return toObject;\n}\n\nexport function googleSearchToMldev(\n fromObject: types.GoogleSearch,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['excludeDomains']) !== undefined) {\n throw new Error('excludeDomains parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['blockingConfidence']) !== undefined) {\n throw new Error(\n 'blockingConfidence parameter is not supported in Gemini API.',\n );\n }\n\n const fromTimeRangeFilter = common.getValueByPath(fromObject, [\n 'timeRangeFilter',\n ]);\n if (fromTimeRangeFilter != null) {\n common.setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter);\n }\n\n return toObject;\n}\n\nexport function imageConfigToMldev(\n fromObject: types.ImageConfig,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromAspectRatio = common.getValueByPath(fromObject, ['aspectRatio']);\n if (fromAspectRatio != null) {\n common.setValueByPath(toObject, ['aspectRatio'], fromAspectRatio);\n }\n\n const fromImageSize = common.getValueByPath(fromObject, ['imageSize']);\n if (fromImageSize != null) {\n common.setValueByPath(toObject, ['imageSize'], fromImageSize);\n }\n\n if (common.getValueByPath(fromObject, ['personGeneration']) !== undefined) {\n throw new Error(\n 'personGeneration parameter is not supported in Gemini API.',\n );\n }\n\n if (common.getValueByPath(fromObject, ['outputMimeType']) !== undefined) {\n throw new Error('outputMimeType parameter is not supported in Gemini API.');\n }\n\n if (\n common.getValueByPath(fromObject, ['outputCompressionQuality']) !==\n undefined\n ) {\n throw new Error(\n 'outputCompressionQuality parameter is not supported in Gemini API.',\n );\n }\n\n return toObject;\n}\n\nexport function imageConfigToVertex(\n fromObject: types.ImageConfig,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromAspectRatio = common.getValueByPath(fromObject, ['aspectRatio']);\n if (fromAspectRatio != null) {\n common.setValueByPath(toObject, ['aspectRatio'], fromAspectRatio);\n }\n\n const fromImageSize = common.getValueByPath(fromObject, ['imageSize']);\n if (fromImageSize != null) {\n common.setValueByPath(toObject, ['imageSize'], fromImageSize);\n }\n\n const fromPersonGeneration = common.getValueByPath(fromObject, [\n 'personGeneration',\n ]);\n if (fromPersonGeneration != null) {\n common.setValueByPath(toObject, ['personGeneration'], fromPersonGeneration);\n }\n\n const fromOutputMimeType = common.getValueByPath(fromObject, [\n 'outputMimeType',\n ]);\n if (fromOutputMimeType != null) {\n common.setValueByPath(\n toObject,\n ['imageOutputOptions', 'mimeType'],\n fromOutputMimeType,\n );\n }\n\n const fromOutputCompressionQuality = common.getValueByPath(fromObject, [\n 'outputCompressionQuality',\n ]);\n if (fromOutputCompressionQuality != null) {\n common.setValueByPath(\n toObject,\n ['imageOutputOptions', 'compressionQuality'],\n fromOutputCompressionQuality,\n );\n }\n\n return toObject;\n}\n\nexport function imageFromMldev(\n fromObject: types.Image,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromImageBytes = common.getValueByPath(fromObject, [\n 'bytesBase64Encoded',\n ]);\n if (fromImageBytes != null) {\n common.setValueByPath(toObject, ['imageBytes'], t.tBytes(fromImageBytes));\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function imageFromVertex(\n fromObject: types.Image,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromGcsUri = common.getValueByPath(fromObject, ['gcsUri']);\n if (fromGcsUri != null) {\n common.setValueByPath(toObject, ['gcsUri'], fromGcsUri);\n }\n\n const fromImageBytes = common.getValueByPath(fromObject, [\n 'bytesBase64Encoded',\n ]);\n if (fromImageBytes != null) {\n common.setValueByPath(toObject, ['imageBytes'], t.tBytes(fromImageBytes));\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function imageToMldev(\n fromObject: types.Image,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['gcsUri']) !== undefined) {\n throw new Error('gcsUri parameter is not supported in Gemini API.');\n }\n\n const fromImageBytes = common.getValueByPath(fromObject, ['imageBytes']);\n if (fromImageBytes != null) {\n common.setValueByPath(\n toObject,\n ['bytesBase64Encoded'],\n t.tBytes(fromImageBytes),\n );\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function imageToVertex(\n fromObject: types.Image,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromGcsUri = common.getValueByPath(fromObject, ['gcsUri']);\n if (fromGcsUri != null) {\n common.setValueByPath(toObject, ['gcsUri'], fromGcsUri);\n }\n\n const fromImageBytes = common.getValueByPath(fromObject, ['imageBytes']);\n if (fromImageBytes != null) {\n common.setValueByPath(\n toObject,\n ['bytesBase64Encoded'],\n t.tBytes(fromImageBytes),\n );\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function listModelsConfigToMldev(\n apiClient: ApiClient,\n fromObject: types.ListModelsConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPageSize = common.getValueByPath(fromObject, ['pageSize']);\n if (parentObject !== undefined && fromPageSize != null) {\n common.setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize);\n }\n\n const fromPageToken = common.getValueByPath(fromObject, ['pageToken']);\n if (parentObject !== undefined && fromPageToken != null) {\n common.setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken);\n }\n\n const fromFilter = common.getValueByPath(fromObject, ['filter']);\n if (parentObject !== undefined && fromFilter != null) {\n common.setValueByPath(parentObject, ['_query', 'filter'], fromFilter);\n }\n\n const fromQueryBase = common.getValueByPath(fromObject, ['queryBase']);\n if (parentObject !== undefined && fromQueryBase != null) {\n common.setValueByPath(\n parentObject,\n ['_url', 'models_url'],\n t.tModelsUrl(apiClient, fromQueryBase),\n );\n }\n\n return toObject;\n}\n\nexport function listModelsConfigToVertex(\n apiClient: ApiClient,\n fromObject: types.ListModelsConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPageSize = common.getValueByPath(fromObject, ['pageSize']);\n if (parentObject !== undefined && fromPageSize != null) {\n common.setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize);\n }\n\n const fromPageToken = common.getValueByPath(fromObject, ['pageToken']);\n if (parentObject !== undefined && fromPageToken != null) {\n common.setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken);\n }\n\n const fromFilter = common.getValueByPath(fromObject, ['filter']);\n if (parentObject !== undefined && fromFilter != null) {\n common.setValueByPath(parentObject, ['_query', 'filter'], fromFilter);\n }\n\n const fromQueryBase = common.getValueByPath(fromObject, ['queryBase']);\n if (parentObject !== undefined && fromQueryBase != null) {\n common.setValueByPath(\n parentObject,\n ['_url', 'models_url'],\n t.tModelsUrl(apiClient, fromQueryBase),\n );\n }\n\n return toObject;\n}\n\nexport function listModelsParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.ListModelsParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n listModelsConfigToMldev(apiClient, fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function listModelsParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.ListModelsParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n listModelsConfigToVertex(apiClient, fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function listModelsResponseFromMldev(\n fromObject: types.ListModelsResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromNextPageToken = common.getValueByPath(fromObject, [\n 'nextPageToken',\n ]);\n if (fromNextPageToken != null) {\n common.setValueByPath(toObject, ['nextPageToken'], fromNextPageToken);\n }\n\n const fromModels = common.getValueByPath(fromObject, ['_self']);\n if (fromModels != null) {\n let transformedList = t.tExtractModels(fromModels);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return modelFromMldev(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['models'], transformedList);\n }\n\n return toObject;\n}\n\nexport function listModelsResponseFromVertex(\n fromObject: types.ListModelsResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromNextPageToken = common.getValueByPath(fromObject, [\n 'nextPageToken',\n ]);\n if (fromNextPageToken != null) {\n common.setValueByPath(toObject, ['nextPageToken'], fromNextPageToken);\n }\n\n const fromModels = common.getValueByPath(fromObject, ['_self']);\n if (fromModels != null) {\n let transformedList = t.tExtractModels(fromModels);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return modelFromVertex(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['models'], transformedList);\n }\n\n return toObject;\n}\n\nexport function maskReferenceConfigToVertex(\n fromObject: types.MaskReferenceConfig,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMaskMode = common.getValueByPath(fromObject, ['maskMode']);\n if (fromMaskMode != null) {\n common.setValueByPath(toObject, ['maskMode'], fromMaskMode);\n }\n\n const fromSegmentationClasses = common.getValueByPath(fromObject, [\n 'segmentationClasses',\n ]);\n if (fromSegmentationClasses != null) {\n common.setValueByPath(toObject, ['maskClasses'], fromSegmentationClasses);\n }\n\n const fromMaskDilation = common.getValueByPath(fromObject, ['maskDilation']);\n if (fromMaskDilation != null) {\n common.setValueByPath(toObject, ['dilation'], fromMaskDilation);\n }\n\n return toObject;\n}\n\nexport function modelFromMldev(\n fromObject: types.Model,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromDisplayName = common.getValueByPath(fromObject, ['displayName']);\n if (fromDisplayName != null) {\n common.setValueByPath(toObject, ['displayName'], fromDisplayName);\n }\n\n const fromDescription = common.getValueByPath(fromObject, ['description']);\n if (fromDescription != null) {\n common.setValueByPath(toObject, ['description'], fromDescription);\n }\n\n const fromVersion = common.getValueByPath(fromObject, ['version']);\n if (fromVersion != null) {\n common.setValueByPath(toObject, ['version'], fromVersion);\n }\n\n const fromTunedModelInfo = common.getValueByPath(fromObject, ['_self']);\n if (fromTunedModelInfo != null) {\n common.setValueByPath(\n toObject,\n ['tunedModelInfo'],\n tunedModelInfoFromMldev(fromTunedModelInfo, rootObject),\n );\n }\n\n const fromInputTokenLimit = common.getValueByPath(fromObject, [\n 'inputTokenLimit',\n ]);\n if (fromInputTokenLimit != null) {\n common.setValueByPath(toObject, ['inputTokenLimit'], fromInputTokenLimit);\n }\n\n const fromOutputTokenLimit = common.getValueByPath(fromObject, [\n 'outputTokenLimit',\n ]);\n if (fromOutputTokenLimit != null) {\n common.setValueByPath(toObject, ['outputTokenLimit'], fromOutputTokenLimit);\n }\n\n const fromSupportedActions = common.getValueByPath(fromObject, [\n 'supportedGenerationMethods',\n ]);\n if (fromSupportedActions != null) {\n common.setValueByPath(toObject, ['supportedActions'], fromSupportedActions);\n }\n\n const fromTemperature = common.getValueByPath(fromObject, ['temperature']);\n if (fromTemperature != null) {\n common.setValueByPath(toObject, ['temperature'], fromTemperature);\n }\n\n const fromMaxTemperature = common.getValueByPath(fromObject, [\n 'maxTemperature',\n ]);\n if (fromMaxTemperature != null) {\n common.setValueByPath(toObject, ['maxTemperature'], fromMaxTemperature);\n }\n\n const fromTopP = common.getValueByPath(fromObject, ['topP']);\n if (fromTopP != null) {\n common.setValueByPath(toObject, ['topP'], fromTopP);\n }\n\n const fromTopK = common.getValueByPath(fromObject, ['topK']);\n if (fromTopK != null) {\n common.setValueByPath(toObject, ['topK'], fromTopK);\n }\n\n const fromThinking = common.getValueByPath(fromObject, ['thinking']);\n if (fromThinking != null) {\n common.setValueByPath(toObject, ['thinking'], fromThinking);\n }\n\n return toObject;\n}\n\nexport function modelFromVertex(\n fromObject: types.Model,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromDisplayName = common.getValueByPath(fromObject, ['displayName']);\n if (fromDisplayName != null) {\n common.setValueByPath(toObject, ['displayName'], fromDisplayName);\n }\n\n const fromDescription = common.getValueByPath(fromObject, ['description']);\n if (fromDescription != null) {\n common.setValueByPath(toObject, ['description'], fromDescription);\n }\n\n const fromVersion = common.getValueByPath(fromObject, ['versionId']);\n if (fromVersion != null) {\n common.setValueByPath(toObject, ['version'], fromVersion);\n }\n\n const fromEndpoints = common.getValueByPath(fromObject, ['deployedModels']);\n if (fromEndpoints != null) {\n let transformedList = fromEndpoints;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return endpointFromVertex(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['endpoints'], transformedList);\n }\n\n const fromLabels = common.getValueByPath(fromObject, ['labels']);\n if (fromLabels != null) {\n common.setValueByPath(toObject, ['labels'], fromLabels);\n }\n\n const fromTunedModelInfo = common.getValueByPath(fromObject, ['_self']);\n if (fromTunedModelInfo != null) {\n common.setValueByPath(\n toObject,\n ['tunedModelInfo'],\n tunedModelInfoFromVertex(fromTunedModelInfo, rootObject),\n );\n }\n\n const fromDefaultCheckpointId = common.getValueByPath(fromObject, [\n 'defaultCheckpointId',\n ]);\n if (fromDefaultCheckpointId != null) {\n common.setValueByPath(\n toObject,\n ['defaultCheckpointId'],\n fromDefaultCheckpointId,\n );\n }\n\n const fromCheckpoints = common.getValueByPath(fromObject, ['checkpoints']);\n if (fromCheckpoints != null) {\n let transformedList = fromCheckpoints;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['checkpoints'], transformedList);\n }\n\n return toObject;\n}\n\nexport function partToMldev(\n fromObject: types.Part,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (fromMediaResolution != null) {\n common.setValueByPath(toObject, ['mediaResolution'], fromMediaResolution);\n }\n\n const fromCodeExecutionResult = common.getValueByPath(fromObject, [\n 'codeExecutionResult',\n ]);\n if (fromCodeExecutionResult != null) {\n common.setValueByPath(\n toObject,\n ['codeExecutionResult'],\n fromCodeExecutionResult,\n );\n }\n\n const fromExecutableCode = common.getValueByPath(fromObject, [\n 'executableCode',\n ]);\n if (fromExecutableCode != null) {\n common.setValueByPath(toObject, ['executableCode'], fromExecutableCode);\n }\n\n const fromFileData = common.getValueByPath(fromObject, ['fileData']);\n if (fromFileData != null) {\n common.setValueByPath(\n toObject,\n ['fileData'],\n fileDataToMldev(fromFileData, rootObject),\n );\n }\n\n const fromFunctionCall = common.getValueByPath(fromObject, ['functionCall']);\n if (fromFunctionCall != null) {\n common.setValueByPath(\n toObject,\n ['functionCall'],\n functionCallToMldev(fromFunctionCall, rootObject),\n );\n }\n\n const fromFunctionResponse = common.getValueByPath(fromObject, [\n 'functionResponse',\n ]);\n if (fromFunctionResponse != null) {\n common.setValueByPath(toObject, ['functionResponse'], fromFunctionResponse);\n }\n\n const fromInlineData = common.getValueByPath(fromObject, ['inlineData']);\n if (fromInlineData != null) {\n common.setValueByPath(\n toObject,\n ['inlineData'],\n blobToMldev(fromInlineData, rootObject),\n );\n }\n\n const fromText = common.getValueByPath(fromObject, ['text']);\n if (fromText != null) {\n common.setValueByPath(toObject, ['text'], fromText);\n }\n\n const fromThought = common.getValueByPath(fromObject, ['thought']);\n if (fromThought != null) {\n common.setValueByPath(toObject, ['thought'], fromThought);\n }\n\n const fromThoughtSignature = common.getValueByPath(fromObject, [\n 'thoughtSignature',\n ]);\n if (fromThoughtSignature != null) {\n common.setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature);\n }\n\n const fromVideoMetadata = common.getValueByPath(fromObject, [\n 'videoMetadata',\n ]);\n if (fromVideoMetadata != null) {\n common.setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata);\n }\n\n return toObject;\n}\n\nexport function productImageToVertex(\n fromObject: types.ProductImage,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromProductImage = common.getValueByPath(fromObject, ['productImage']);\n if (fromProductImage != null) {\n common.setValueByPath(\n toObject,\n ['image'],\n imageToVertex(fromProductImage, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function recontextImageConfigToVertex(\n fromObject: types.RecontextImageConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromNumberOfImages = common.getValueByPath(fromObject, [\n 'numberOfImages',\n ]);\n if (parentObject !== undefined && fromNumberOfImages != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'sampleCount'],\n fromNumberOfImages,\n );\n }\n\n const fromBaseSteps = common.getValueByPath(fromObject, ['baseSteps']);\n if (parentObject !== undefined && fromBaseSteps != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'baseSteps'],\n fromBaseSteps,\n );\n }\n\n const fromOutputGcsUri = common.getValueByPath(fromObject, ['outputGcsUri']);\n if (parentObject !== undefined && fromOutputGcsUri != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'storageUri'],\n fromOutputGcsUri,\n );\n }\n\n const fromSeed = common.getValueByPath(fromObject, ['seed']);\n if (parentObject !== undefined && fromSeed != null) {\n common.setValueByPath(parentObject, ['parameters', 'seed'], fromSeed);\n }\n\n const fromSafetyFilterLevel = common.getValueByPath(fromObject, [\n 'safetyFilterLevel',\n ]);\n if (parentObject !== undefined && fromSafetyFilterLevel != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'safetySetting'],\n fromSafetyFilterLevel,\n );\n }\n\n const fromPersonGeneration = common.getValueByPath(fromObject, [\n 'personGeneration',\n ]);\n if (parentObject !== undefined && fromPersonGeneration != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'personGeneration'],\n fromPersonGeneration,\n );\n }\n\n const fromAddWatermark = common.getValueByPath(fromObject, ['addWatermark']);\n if (parentObject !== undefined && fromAddWatermark != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'addWatermark'],\n fromAddWatermark,\n );\n }\n\n const fromOutputMimeType = common.getValueByPath(fromObject, [\n 'outputMimeType',\n ]);\n if (parentObject !== undefined && fromOutputMimeType != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'outputOptions', 'mimeType'],\n fromOutputMimeType,\n );\n }\n\n const fromOutputCompressionQuality = common.getValueByPath(fromObject, [\n 'outputCompressionQuality',\n ]);\n if (parentObject !== undefined && fromOutputCompressionQuality != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'outputOptions', 'compressionQuality'],\n fromOutputCompressionQuality,\n );\n }\n\n const fromEnhancePrompt = common.getValueByPath(fromObject, [\n 'enhancePrompt',\n ]);\n if (parentObject !== undefined && fromEnhancePrompt != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'enhancePrompt'],\n fromEnhancePrompt,\n );\n }\n\n const fromLabels = common.getValueByPath(fromObject, ['labels']);\n if (parentObject !== undefined && fromLabels != null) {\n common.setValueByPath(parentObject, ['labels'], fromLabels);\n }\n\n return toObject;\n}\n\nexport function recontextImageParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.RecontextImageParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromSource = common.getValueByPath(fromObject, ['source']);\n if (fromSource != null) {\n recontextImageSourceToVertex(fromSource, toObject, rootObject);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n recontextImageConfigToVertex(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function recontextImageResponseFromVertex(\n fromObject: types.RecontextImageResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromGeneratedImages = common.getValueByPath(fromObject, [\n 'predictions',\n ]);\n if (fromGeneratedImages != null) {\n let transformedList = fromGeneratedImages;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return generatedImageFromVertex(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['generatedImages'], transformedList);\n }\n\n return toObject;\n}\n\nexport function recontextImageSourceToVertex(\n fromObject: types.RecontextImageSource,\n parentObject: Record<string, unknown>,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPrompt = common.getValueByPath(fromObject, ['prompt']);\n if (parentObject !== undefined && fromPrompt != null) {\n common.setValueByPath(parentObject, ['instances[0]', 'prompt'], fromPrompt);\n }\n\n const fromPersonImage = common.getValueByPath(fromObject, ['personImage']);\n if (parentObject !== undefined && fromPersonImage != null) {\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'personImage', 'image'],\n imageToVertex(fromPersonImage, rootObject),\n );\n }\n\n const fromProductImages = common.getValueByPath(fromObject, [\n 'productImages',\n ]);\n if (parentObject !== undefined && fromProductImages != null) {\n let transformedList = fromProductImages;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return productImageToVertex(item, rootObject);\n });\n }\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'productImages'],\n transformedList,\n );\n }\n\n return toObject;\n}\n\nexport function referenceImageAPIInternalToVertex(\n fromObject: _internal_types.ReferenceImageAPIInternal,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromReferenceImage = common.getValueByPath(fromObject, [\n 'referenceImage',\n ]);\n if (fromReferenceImage != null) {\n common.setValueByPath(\n toObject,\n ['referenceImage'],\n imageToVertex(fromReferenceImage, rootObject),\n );\n }\n\n const fromReferenceId = common.getValueByPath(fromObject, ['referenceId']);\n if (fromReferenceId != null) {\n common.setValueByPath(toObject, ['referenceId'], fromReferenceId);\n }\n\n const fromReferenceType = common.getValueByPath(fromObject, [\n 'referenceType',\n ]);\n if (fromReferenceType != null) {\n common.setValueByPath(toObject, ['referenceType'], fromReferenceType);\n }\n\n const fromMaskImageConfig = common.getValueByPath(fromObject, [\n 'maskImageConfig',\n ]);\n if (fromMaskImageConfig != null) {\n common.setValueByPath(\n toObject,\n ['maskImageConfig'],\n maskReferenceConfigToVertex(fromMaskImageConfig, rootObject),\n );\n }\n\n const fromControlImageConfig = common.getValueByPath(fromObject, [\n 'controlImageConfig',\n ]);\n if (fromControlImageConfig != null) {\n common.setValueByPath(\n toObject,\n ['controlImageConfig'],\n controlReferenceConfigToVertex(fromControlImageConfig, rootObject),\n );\n }\n\n const fromStyleImageConfig = common.getValueByPath(fromObject, [\n 'styleImageConfig',\n ]);\n if (fromStyleImageConfig != null) {\n common.setValueByPath(toObject, ['styleImageConfig'], fromStyleImageConfig);\n }\n\n const fromSubjectImageConfig = common.getValueByPath(fromObject, [\n 'subjectImageConfig',\n ]);\n if (fromSubjectImageConfig != null) {\n common.setValueByPath(\n toObject,\n ['subjectImageConfig'],\n fromSubjectImageConfig,\n );\n }\n\n return toObject;\n}\n\nexport function safetyAttributesFromMldev(\n fromObject: types.SafetyAttributes,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromCategories = common.getValueByPath(fromObject, [\n 'safetyAttributes',\n 'categories',\n ]);\n if (fromCategories != null) {\n common.setValueByPath(toObject, ['categories'], fromCategories);\n }\n\n const fromScores = common.getValueByPath(fromObject, [\n 'safetyAttributes',\n 'scores',\n ]);\n if (fromScores != null) {\n common.setValueByPath(toObject, ['scores'], fromScores);\n }\n\n const fromContentType = common.getValueByPath(fromObject, ['contentType']);\n if (fromContentType != null) {\n common.setValueByPath(toObject, ['contentType'], fromContentType);\n }\n\n return toObject;\n}\n\nexport function safetyAttributesFromVertex(\n fromObject: types.SafetyAttributes,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromCategories = common.getValueByPath(fromObject, [\n 'safetyAttributes',\n 'categories',\n ]);\n if (fromCategories != null) {\n common.setValueByPath(toObject, ['categories'], fromCategories);\n }\n\n const fromScores = common.getValueByPath(fromObject, [\n 'safetyAttributes',\n 'scores',\n ]);\n if (fromScores != null) {\n common.setValueByPath(toObject, ['scores'], fromScores);\n }\n\n const fromContentType = common.getValueByPath(fromObject, ['contentType']);\n if (fromContentType != null) {\n common.setValueByPath(toObject, ['contentType'], fromContentType);\n }\n\n return toObject;\n}\n\nexport function safetySettingToMldev(\n fromObject: types.SafetySetting,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromCategory = common.getValueByPath(fromObject, ['category']);\n if (fromCategory != null) {\n common.setValueByPath(toObject, ['category'], fromCategory);\n }\n\n if (common.getValueByPath(fromObject, ['method']) !== undefined) {\n throw new Error('method parameter is not supported in Gemini API.');\n }\n\n const fromThreshold = common.getValueByPath(fromObject, ['threshold']);\n if (fromThreshold != null) {\n common.setValueByPath(toObject, ['threshold'], fromThreshold);\n }\n\n return toObject;\n}\n\nexport function scribbleImageToVertex(\n fromObject: types.ScribbleImage,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromImage = common.getValueByPath(fromObject, ['image']);\n if (fromImage != null) {\n common.setValueByPath(\n toObject,\n ['image'],\n imageToVertex(fromImage, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function segmentImageConfigToVertex(\n fromObject: types.SegmentImageConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMode = common.getValueByPath(fromObject, ['mode']);\n if (parentObject !== undefined && fromMode != null) {\n common.setValueByPath(parentObject, ['parameters', 'mode'], fromMode);\n }\n\n const fromMaxPredictions = common.getValueByPath(fromObject, [\n 'maxPredictions',\n ]);\n if (parentObject !== undefined && fromMaxPredictions != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'maxPredictions'],\n fromMaxPredictions,\n );\n }\n\n const fromConfidenceThreshold = common.getValueByPath(fromObject, [\n 'confidenceThreshold',\n ]);\n if (parentObject !== undefined && fromConfidenceThreshold != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'confidenceThreshold'],\n fromConfidenceThreshold,\n );\n }\n\n const fromMaskDilation = common.getValueByPath(fromObject, ['maskDilation']);\n if (parentObject !== undefined && fromMaskDilation != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'maskDilation'],\n fromMaskDilation,\n );\n }\n\n const fromBinaryColorThreshold = common.getValueByPath(fromObject, [\n 'binaryColorThreshold',\n ]);\n if (parentObject !== undefined && fromBinaryColorThreshold != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'binaryColorThreshold'],\n fromBinaryColorThreshold,\n );\n }\n\n const fromLabels = common.getValueByPath(fromObject, ['labels']);\n if (parentObject !== undefined && fromLabels != null) {\n common.setValueByPath(parentObject, ['labels'], fromLabels);\n }\n\n return toObject;\n}\n\nexport function segmentImageParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.SegmentImageParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromSource = common.getValueByPath(fromObject, ['source']);\n if (fromSource != null) {\n segmentImageSourceToVertex(fromSource, toObject, rootObject);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n segmentImageConfigToVertex(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function segmentImageResponseFromVertex(\n fromObject: types.SegmentImageResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromGeneratedMasks = common.getValueByPath(fromObject, ['predictions']);\n if (fromGeneratedMasks != null) {\n let transformedList = fromGeneratedMasks;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return generatedImageMaskFromVertex(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['generatedMasks'], transformedList);\n }\n\n return toObject;\n}\n\nexport function segmentImageSourceToVertex(\n fromObject: types.SegmentImageSource,\n parentObject: Record<string, unknown>,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPrompt = common.getValueByPath(fromObject, ['prompt']);\n if (parentObject !== undefined && fromPrompt != null) {\n common.setValueByPath(parentObject, ['instances[0]', 'prompt'], fromPrompt);\n }\n\n const fromImage = common.getValueByPath(fromObject, ['image']);\n if (parentObject !== undefined && fromImage != null) {\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'image'],\n imageToVertex(fromImage, rootObject),\n );\n }\n\n const fromScribbleImage = common.getValueByPath(fromObject, [\n 'scribbleImage',\n ]);\n if (parentObject !== undefined && fromScribbleImage != null) {\n common.setValueByPath(\n parentObject,\n ['instances[0]', 'scribble'],\n scribbleImageToVertex(fromScribbleImage, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function toolConfigToMldev(\n fromObject: types.ToolConfig,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromRetrievalConfig = common.getValueByPath(fromObject, [\n 'retrievalConfig',\n ]);\n if (fromRetrievalConfig != null) {\n common.setValueByPath(toObject, ['retrievalConfig'], fromRetrievalConfig);\n }\n\n const fromFunctionCallingConfig = common.getValueByPath(fromObject, [\n 'functionCallingConfig',\n ]);\n if (fromFunctionCallingConfig != null) {\n common.setValueByPath(\n toObject,\n ['functionCallingConfig'],\n functionCallingConfigToMldev(fromFunctionCallingConfig, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function toolToMldev(\n fromObject: types.Tool,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['retrieval']) !== undefined) {\n throw new Error('retrieval parameter is not supported in Gemini API.');\n }\n\n const fromComputerUse = common.getValueByPath(fromObject, ['computerUse']);\n if (fromComputerUse != null) {\n common.setValueByPath(toObject, ['computerUse'], fromComputerUse);\n }\n\n const fromFileSearch = common.getValueByPath(fromObject, ['fileSearch']);\n if (fromFileSearch != null) {\n common.setValueByPath(toObject, ['fileSearch'], fromFileSearch);\n }\n\n const fromCodeExecution = common.getValueByPath(fromObject, [\n 'codeExecution',\n ]);\n if (fromCodeExecution != null) {\n common.setValueByPath(toObject, ['codeExecution'], fromCodeExecution);\n }\n\n if (\n common.getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined\n ) {\n throw new Error(\n 'enterpriseWebSearch parameter is not supported in Gemini API.',\n );\n }\n\n const fromFunctionDeclarations = common.getValueByPath(fromObject, [\n 'functionDeclarations',\n ]);\n if (fromFunctionDeclarations != null) {\n let transformedList = fromFunctionDeclarations;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['functionDeclarations'], transformedList);\n }\n\n const fromGoogleMaps = common.getValueByPath(fromObject, ['googleMaps']);\n if (fromGoogleMaps != null) {\n common.setValueByPath(\n toObject,\n ['googleMaps'],\n googleMapsToMldev(fromGoogleMaps, rootObject),\n );\n }\n\n const fromGoogleSearch = common.getValueByPath(fromObject, ['googleSearch']);\n if (fromGoogleSearch != null) {\n common.setValueByPath(\n toObject,\n ['googleSearch'],\n googleSearchToMldev(fromGoogleSearch, rootObject),\n );\n }\n\n const fromGoogleSearchRetrieval = common.getValueByPath(fromObject, [\n 'googleSearchRetrieval',\n ]);\n if (fromGoogleSearchRetrieval != null) {\n common.setValueByPath(\n toObject,\n ['googleSearchRetrieval'],\n fromGoogleSearchRetrieval,\n );\n }\n\n const fromUrlContext = common.getValueByPath(fromObject, ['urlContext']);\n if (fromUrlContext != null) {\n common.setValueByPath(toObject, ['urlContext'], fromUrlContext);\n }\n\n return toObject;\n}\n\nexport function toolToVertex(\n fromObject: types.Tool,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromRetrieval = common.getValueByPath(fromObject, ['retrieval']);\n if (fromRetrieval != null) {\n common.setValueByPath(toObject, ['retrieval'], fromRetrieval);\n }\n\n const fromComputerUse = common.getValueByPath(fromObject, ['computerUse']);\n if (fromComputerUse != null) {\n common.setValueByPath(toObject, ['computerUse'], fromComputerUse);\n }\n\n if (common.getValueByPath(fromObject, ['fileSearch']) !== undefined) {\n throw new Error('fileSearch parameter is not supported in Vertex AI.');\n }\n\n const fromCodeExecution = common.getValueByPath(fromObject, [\n 'codeExecution',\n ]);\n if (fromCodeExecution != null) {\n common.setValueByPath(toObject, ['codeExecution'], fromCodeExecution);\n }\n\n const fromEnterpriseWebSearch = common.getValueByPath(fromObject, [\n 'enterpriseWebSearch',\n ]);\n if (fromEnterpriseWebSearch != null) {\n common.setValueByPath(\n toObject,\n ['enterpriseWebSearch'],\n fromEnterpriseWebSearch,\n );\n }\n\n const fromFunctionDeclarations = common.getValueByPath(fromObject, [\n 'functionDeclarations',\n ]);\n if (fromFunctionDeclarations != null) {\n let transformedList = fromFunctionDeclarations;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return functionDeclarationToVertex(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['functionDeclarations'], transformedList);\n }\n\n const fromGoogleMaps = common.getValueByPath(fromObject, ['googleMaps']);\n if (fromGoogleMaps != null) {\n common.setValueByPath(toObject, ['googleMaps'], fromGoogleMaps);\n }\n\n const fromGoogleSearch = common.getValueByPath(fromObject, ['googleSearch']);\n if (fromGoogleSearch != null) {\n common.setValueByPath(toObject, ['googleSearch'], fromGoogleSearch);\n }\n\n const fromGoogleSearchRetrieval = common.getValueByPath(fromObject, [\n 'googleSearchRetrieval',\n ]);\n if (fromGoogleSearchRetrieval != null) {\n common.setValueByPath(\n toObject,\n ['googleSearchRetrieval'],\n fromGoogleSearchRetrieval,\n );\n }\n\n const fromUrlContext = common.getValueByPath(fromObject, ['urlContext']);\n if (fromUrlContext != null) {\n common.setValueByPath(toObject, ['urlContext'], fromUrlContext);\n }\n\n return toObject;\n}\n\nexport function tunedModelInfoFromMldev(\n fromObject: types.TunedModelInfo,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromBaseModel = common.getValueByPath(fromObject, ['baseModel']);\n if (fromBaseModel != null) {\n common.setValueByPath(toObject, ['baseModel'], fromBaseModel);\n }\n\n const fromCreateTime = common.getValueByPath(fromObject, ['createTime']);\n if (fromCreateTime != null) {\n common.setValueByPath(toObject, ['createTime'], fromCreateTime);\n }\n\n const fromUpdateTime = common.getValueByPath(fromObject, ['updateTime']);\n if (fromUpdateTime != null) {\n common.setValueByPath(toObject, ['updateTime'], fromUpdateTime);\n }\n\n return toObject;\n}\n\nexport function tunedModelInfoFromVertex(\n fromObject: types.TunedModelInfo,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromBaseModel = common.getValueByPath(fromObject, [\n 'labels',\n 'google-vertex-llm-tuning-base-model-id',\n ]);\n if (fromBaseModel != null) {\n common.setValueByPath(toObject, ['baseModel'], fromBaseModel);\n }\n\n const fromCreateTime = common.getValueByPath(fromObject, ['createTime']);\n if (fromCreateTime != null) {\n common.setValueByPath(toObject, ['createTime'], fromCreateTime);\n }\n\n const fromUpdateTime = common.getValueByPath(fromObject, ['updateTime']);\n if (fromUpdateTime != null) {\n common.setValueByPath(toObject, ['updateTime'], fromUpdateTime);\n }\n\n return toObject;\n}\n\nexport function updateModelConfigToMldev(\n fromObject: types.UpdateModelConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromDisplayName = common.getValueByPath(fromObject, ['displayName']);\n if (parentObject !== undefined && fromDisplayName != null) {\n common.setValueByPath(parentObject, ['displayName'], fromDisplayName);\n }\n\n const fromDescription = common.getValueByPath(fromObject, ['description']);\n if (parentObject !== undefined && fromDescription != null) {\n common.setValueByPath(parentObject, ['description'], fromDescription);\n }\n\n const fromDefaultCheckpointId = common.getValueByPath(fromObject, [\n 'defaultCheckpointId',\n ]);\n if (parentObject !== undefined && fromDefaultCheckpointId != null) {\n common.setValueByPath(\n parentObject,\n ['defaultCheckpointId'],\n fromDefaultCheckpointId,\n );\n }\n\n return toObject;\n}\n\nexport function updateModelConfigToVertex(\n fromObject: types.UpdateModelConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromDisplayName = common.getValueByPath(fromObject, ['displayName']);\n if (parentObject !== undefined && fromDisplayName != null) {\n common.setValueByPath(parentObject, ['displayName'], fromDisplayName);\n }\n\n const fromDescription = common.getValueByPath(fromObject, ['description']);\n if (parentObject !== undefined && fromDescription != null) {\n common.setValueByPath(parentObject, ['description'], fromDescription);\n }\n\n const fromDefaultCheckpointId = common.getValueByPath(fromObject, [\n 'defaultCheckpointId',\n ]);\n if (parentObject !== undefined && fromDefaultCheckpointId != null) {\n common.setValueByPath(\n parentObject,\n ['defaultCheckpointId'],\n fromDefaultCheckpointId,\n );\n }\n\n return toObject;\n}\n\nexport function updateModelParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.UpdateModelParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'name'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n updateModelConfigToMldev(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function updateModelParametersToVertex(\n apiClient: ApiClient,\n fromObject: types.UpdateModelParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n updateModelConfigToVertex(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function upscaleImageAPIConfigInternalToVertex(\n fromObject: _internal_types.UpscaleImageAPIConfigInternal,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromOutputGcsUri = common.getValueByPath(fromObject, ['outputGcsUri']);\n if (parentObject !== undefined && fromOutputGcsUri != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'storageUri'],\n fromOutputGcsUri,\n );\n }\n\n const fromSafetyFilterLevel = common.getValueByPath(fromObject, [\n 'safetyFilterLevel',\n ]);\n if (parentObject !== undefined && fromSafetyFilterLevel != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'safetySetting'],\n fromSafetyFilterLevel,\n );\n }\n\n const fromPersonGeneration = common.getValueByPath(fromObject, [\n 'personGeneration',\n ]);\n if (parentObject !== undefined && fromPersonGeneration != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'personGeneration'],\n fromPersonGeneration,\n );\n }\n\n const fromIncludeRaiReason = common.getValueByPath(fromObject, [\n 'includeRaiReason',\n ]);\n if (parentObject !== undefined && fromIncludeRaiReason != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'includeRaiReason'],\n fromIncludeRaiReason,\n );\n }\n\n const fromOutputMimeType = common.getValueByPath(fromObject, [\n 'outputMimeType',\n ]);\n if (parentObject !== undefined && fromOutputMimeType != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'outputOptions', 'mimeType'],\n fromOutputMimeType,\n );\n }\n\n const fromOutputCompressionQuality = common.getValueByPath(fromObject, [\n 'outputCompressionQuality',\n ]);\n if (parentObject !== undefined && fromOutputCompressionQuality != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'outputOptions', 'compressionQuality'],\n fromOutputCompressionQuality,\n );\n }\n\n const fromEnhanceInputImage = common.getValueByPath(fromObject, [\n 'enhanceInputImage',\n ]);\n if (parentObject !== undefined && fromEnhanceInputImage != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'upscaleConfig', 'enhanceInputImage'],\n fromEnhanceInputImage,\n );\n }\n\n const fromImagePreservationFactor = common.getValueByPath(fromObject, [\n 'imagePreservationFactor',\n ]);\n if (parentObject !== undefined && fromImagePreservationFactor != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'upscaleConfig', 'imagePreservationFactor'],\n fromImagePreservationFactor,\n );\n }\n\n const fromLabels = common.getValueByPath(fromObject, ['labels']);\n if (parentObject !== undefined && fromLabels != null) {\n common.setValueByPath(parentObject, ['labels'], fromLabels);\n }\n\n const fromNumberOfImages = common.getValueByPath(fromObject, [\n 'numberOfImages',\n ]);\n if (parentObject !== undefined && fromNumberOfImages != null) {\n common.setValueByPath(\n parentObject,\n ['parameters', 'sampleCount'],\n fromNumberOfImages,\n );\n }\n\n const fromMode = common.getValueByPath(fromObject, ['mode']);\n if (parentObject !== undefined && fromMode != null) {\n common.setValueByPath(parentObject, ['parameters', 'mode'], fromMode);\n }\n\n return toObject;\n}\n\nexport function upscaleImageAPIParametersInternalToVertex(\n apiClient: ApiClient,\n fromObject: _internal_types.UpscaleImageAPIParametersInternal,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromImage = common.getValueByPath(fromObject, ['image']);\n if (fromImage != null) {\n common.setValueByPath(\n toObject,\n ['instances[0]', 'image'],\n imageToVertex(fromImage, rootObject),\n );\n }\n\n const fromUpscaleFactor = common.getValueByPath(fromObject, [\n 'upscaleFactor',\n ]);\n if (fromUpscaleFactor != null) {\n common.setValueByPath(\n toObject,\n ['parameters', 'upscaleConfig', 'upscaleFactor'],\n fromUpscaleFactor,\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n upscaleImageAPIConfigInternalToVertex(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function upscaleImageResponseFromVertex(\n fromObject: types.UpscaleImageResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromGeneratedImages = common.getValueByPath(fromObject, [\n 'predictions',\n ]);\n if (fromGeneratedImages != null) {\n let transformedList = fromGeneratedImages;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return generatedImageFromVertex(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['generatedImages'], transformedList);\n }\n\n return toObject;\n}\n\nexport function videoFromMldev(\n fromObject: types.Video,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromUri = common.getValueByPath(fromObject, ['uri']);\n if (fromUri != null) {\n common.setValueByPath(toObject, ['uri'], fromUri);\n }\n\n const fromVideoBytes = common.getValueByPath(fromObject, ['encodedVideo']);\n if (fromVideoBytes != null) {\n common.setValueByPath(toObject, ['videoBytes'], t.tBytes(fromVideoBytes));\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['encoding']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function videoFromVertex(\n fromObject: types.Video,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromUri = common.getValueByPath(fromObject, ['gcsUri']);\n if (fromUri != null) {\n common.setValueByPath(toObject, ['uri'], fromUri);\n }\n\n const fromVideoBytes = common.getValueByPath(fromObject, [\n 'bytesBase64Encoded',\n ]);\n if (fromVideoBytes != null) {\n common.setValueByPath(toObject, ['videoBytes'], t.tBytes(fromVideoBytes));\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function videoGenerationMaskToVertex(\n fromObject: types.VideoGenerationMask,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromImage = common.getValueByPath(fromObject, ['image']);\n if (fromImage != null) {\n common.setValueByPath(\n toObject,\n ['_self'],\n imageToVertex(fromImage, rootObject),\n );\n }\n\n const fromMaskMode = common.getValueByPath(fromObject, ['maskMode']);\n if (fromMaskMode != null) {\n common.setValueByPath(toObject, ['maskMode'], fromMaskMode);\n }\n\n return toObject;\n}\n\nexport function videoGenerationReferenceImageToMldev(\n fromObject: types.VideoGenerationReferenceImage,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromImage = common.getValueByPath(fromObject, ['image']);\n if (fromImage != null) {\n common.setValueByPath(\n toObject,\n ['image'],\n imageToMldev(fromImage, rootObject),\n );\n }\n\n const fromReferenceType = common.getValueByPath(fromObject, [\n 'referenceType',\n ]);\n if (fromReferenceType != null) {\n common.setValueByPath(toObject, ['referenceType'], fromReferenceType);\n }\n\n return toObject;\n}\n\nexport function videoGenerationReferenceImageToVertex(\n fromObject: types.VideoGenerationReferenceImage,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromImage = common.getValueByPath(fromObject, ['image']);\n if (fromImage != null) {\n common.setValueByPath(\n toObject,\n ['image'],\n imageToVertex(fromImage, rootObject),\n );\n }\n\n const fromReferenceType = common.getValueByPath(fromObject, [\n 'referenceType',\n ]);\n if (fromReferenceType != null) {\n common.setValueByPath(toObject, ['referenceType'], fromReferenceType);\n }\n\n return toObject;\n}\n\nexport function videoToMldev(\n fromObject: types.Video,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromUri = common.getValueByPath(fromObject, ['uri']);\n if (fromUri != null) {\n common.setValueByPath(toObject, ['uri'], fromUri);\n }\n\n const fromVideoBytes = common.getValueByPath(fromObject, ['videoBytes']);\n if (fromVideoBytes != null) {\n common.setValueByPath(toObject, ['encodedVideo'], t.tBytes(fromVideoBytes));\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['encoding'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function videoToVertex(\n fromObject: types.Video,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromUri = common.getValueByPath(fromObject, ['uri']);\n if (fromUri != null) {\n common.setValueByPath(toObject, ['gcsUri'], fromUri);\n }\n\n const fromVideoBytes = common.getValueByPath(fromObject, ['videoBytes']);\n if (fromVideoBytes != null) {\n common.setValueByPath(\n toObject,\n ['bytesBase64Encoded'],\n t.tBytes(fromVideoBytes),\n );\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport * as common from '../_common.js';\nimport type * as types from '../types.js';\n\nexport function createFileSearchStoreConfigToMldev(\n fromObject: types.CreateFileSearchStoreConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromDisplayName = common.getValueByPath(fromObject, ['displayName']);\n if (parentObject !== undefined && fromDisplayName != null) {\n common.setValueByPath(parentObject, ['displayName'], fromDisplayName);\n }\n\n return toObject;\n}\n\nexport function createFileSearchStoreParametersToMldev(\n fromObject: types.CreateFileSearchStoreParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n createFileSearchStoreConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function deleteFileSearchStoreConfigToMldev(\n fromObject: types.DeleteFileSearchStoreConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromForce = common.getValueByPath(fromObject, ['force']);\n if (parentObject !== undefined && fromForce != null) {\n common.setValueByPath(parentObject, ['_query', 'force'], fromForce);\n }\n\n return toObject;\n}\n\nexport function deleteFileSearchStoreParametersToMldev(\n fromObject: types.DeleteFileSearchStoreParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['_url', 'name'], fromName);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n deleteFileSearchStoreConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function getFileSearchStoreParametersToMldev(\n fromObject: types.GetFileSearchStoreParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['_url', 'name'], fromName);\n }\n\n return toObject;\n}\n\nexport function importFileConfigToMldev(\n fromObject: types.ImportFileConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromCustomMetadata = common.getValueByPath(fromObject, [\n 'customMetadata',\n ]);\n if (parentObject !== undefined && fromCustomMetadata != null) {\n let transformedList = fromCustomMetadata;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(parentObject, ['customMetadata'], transformedList);\n }\n\n const fromChunkingConfig = common.getValueByPath(fromObject, [\n 'chunkingConfig',\n ]);\n if (parentObject !== undefined && fromChunkingConfig != null) {\n common.setValueByPath(parentObject, ['chunkingConfig'], fromChunkingConfig);\n }\n\n return toObject;\n}\n\nexport function importFileOperationFromMldev(\n fromObject: types.ImportFileOperation,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromMetadata = common.getValueByPath(fromObject, ['metadata']);\n if (fromMetadata != null) {\n common.setValueByPath(toObject, ['metadata'], fromMetadata);\n }\n\n const fromDone = common.getValueByPath(fromObject, ['done']);\n if (fromDone != null) {\n common.setValueByPath(toObject, ['done'], fromDone);\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n const fromResponse = common.getValueByPath(fromObject, ['response']);\n if (fromResponse != null) {\n common.setValueByPath(\n toObject,\n ['response'],\n importFileResponseFromMldev(fromResponse),\n );\n }\n\n return toObject;\n}\n\nexport function importFileParametersToMldev(\n fromObject: types.ImportFileParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromFileSearchStoreName = common.getValueByPath(fromObject, [\n 'fileSearchStoreName',\n ]);\n if (fromFileSearchStoreName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'file_search_store_name'],\n fromFileSearchStoreName,\n );\n }\n\n const fromFileName = common.getValueByPath(fromObject, ['fileName']);\n if (fromFileName != null) {\n common.setValueByPath(toObject, ['fileName'], fromFileName);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n importFileConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function importFileResponseFromMldev(\n fromObject: types.ImportFileResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromParent = common.getValueByPath(fromObject, ['parent']);\n if (fromParent != null) {\n common.setValueByPath(toObject, ['parent'], fromParent);\n }\n\n const fromDocumentName = common.getValueByPath(fromObject, ['documentName']);\n if (fromDocumentName != null) {\n common.setValueByPath(toObject, ['documentName'], fromDocumentName);\n }\n\n return toObject;\n}\n\nexport function listFileSearchStoresConfigToMldev(\n fromObject: types.ListFileSearchStoresConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPageSize = common.getValueByPath(fromObject, ['pageSize']);\n if (parentObject !== undefined && fromPageSize != null) {\n common.setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize);\n }\n\n const fromPageToken = common.getValueByPath(fromObject, ['pageToken']);\n if (parentObject !== undefined && fromPageToken != null) {\n common.setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken);\n }\n\n return toObject;\n}\n\nexport function listFileSearchStoresParametersToMldev(\n fromObject: types.ListFileSearchStoresParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n listFileSearchStoresConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function listFileSearchStoresResponseFromMldev(\n fromObject: types.ListFileSearchStoresResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromNextPageToken = common.getValueByPath(fromObject, [\n 'nextPageToken',\n ]);\n if (fromNextPageToken != null) {\n common.setValueByPath(toObject, ['nextPageToken'], fromNextPageToken);\n }\n\n const fromFileSearchStores = common.getValueByPath(fromObject, [\n 'fileSearchStores',\n ]);\n if (fromFileSearchStores != null) {\n let transformedList = fromFileSearchStores;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['fileSearchStores'], transformedList);\n }\n\n return toObject;\n}\n\nexport function uploadToFileSearchStoreConfigToMldev(\n fromObject: types.UploadToFileSearchStoreConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (parentObject !== undefined && fromMimeType != null) {\n common.setValueByPath(parentObject, ['mimeType'], fromMimeType);\n }\n\n const fromDisplayName = common.getValueByPath(fromObject, ['displayName']);\n if (parentObject !== undefined && fromDisplayName != null) {\n common.setValueByPath(parentObject, ['displayName'], fromDisplayName);\n }\n\n const fromCustomMetadata = common.getValueByPath(fromObject, [\n 'customMetadata',\n ]);\n if (parentObject !== undefined && fromCustomMetadata != null) {\n let transformedList = fromCustomMetadata;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(parentObject, ['customMetadata'], transformedList);\n }\n\n const fromChunkingConfig = common.getValueByPath(fromObject, [\n 'chunkingConfig',\n ]);\n if (parentObject !== undefined && fromChunkingConfig != null) {\n common.setValueByPath(parentObject, ['chunkingConfig'], fromChunkingConfig);\n }\n\n return toObject;\n}\n\nexport function uploadToFileSearchStoreParametersToMldev(\n fromObject: types.UploadToFileSearchStoreParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromFileSearchStoreName = common.getValueByPath(fromObject, [\n 'fileSearchStoreName',\n ]);\n if (fromFileSearchStoreName != null) {\n common.setValueByPath(\n toObject,\n ['_url', 'file_search_store_name'],\n fromFileSearchStoreName,\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n uploadToFileSearchStoreConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function uploadToFileSearchStoreResumableResponseFromMldev(\n fromObject: types.UploadToFileSearchStoreResumableResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n return toObject;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport pRetry, {AbortError} from 'p-retry';\nimport {Auth} from './_auth.js';\nimport * as common from './_common.js';\nimport {Downloader} from './_downloader.js';\nimport {Uploader} from './_uploader.js';\nimport {uploadToFileSearchStoreConfigToMldev} from './converters/_filesearchstores_converters.js';\nimport {ApiError} from './errors.js';\nimport {GeminiNextGenAPIClientAdapter} from './interactions/client-adapter.js';\nimport * as types from './types.js';\n\nconst CONTENT_TYPE_HEADER = 'Content-Type';\nconst SERVER_TIMEOUT_HEADER = 'X-Server-Timeout';\nconst USER_AGENT_HEADER = 'User-Agent';\nexport const GOOGLE_API_CLIENT_HEADER = 'x-goog-api-client';\nexport const SDK_VERSION = '1.41.0'; // x-release-please-version\nconst LIBRARY_LABEL = `google-genai-sdk/${SDK_VERSION}`;\nconst VERTEX_AI_API_DEFAULT_VERSION = 'v1beta1';\nconst GOOGLE_AI_API_DEFAULT_VERSION = 'v1beta';\n\n// Default retry options.\n// The config is based on https://cloud.google.com/storage/docs/retry-strategy.\nconst DEFAULT_RETRY_ATTEMPTS = 5; // Including the initial call\n// LINT.IfChange\nconst DEFAULT_RETRY_HTTP_STATUS_CODES = [\n 408, // Request timeout\n 429, // Too many requests\n 500, // Internal server error\n 502, // Bad gateway\n 503, // Service unavailable\n 504, // Gateway timeout\n];\n// LINT.ThenChange(//depot/google3/third_party/py/google/genai/_api_client.py)\n\n/**\n * Options for initializing the ApiClient. The ApiClient uses the parameters\n * for authentication purposes as well as to infer if SDK should send the\n * request to Vertex AI or Gemini API.\n */\nexport interface ApiClientInitOptions {\n /**\n * The object used for adding authentication headers to API requests.\n */\n auth: Auth;\n /**\n * The uploader to use for uploading files. This field is required for\n * creating a client, will be set through the Node_client or Web_client.\n */\n uploader: Uploader;\n /**\n * Optional. The downloader to use for downloading files. This field is\n * required for creating a client, will be set through the Node_client or\n * Web_client.\n */\n downloader: Downloader;\n /**\n * Optional. The Google Cloud project ID for Vertex AI users.\n * It is not the numeric project name.\n * If not provided, SDK will try to resolve it from runtime environment.\n */\n project?: string;\n /**\n * Optional. The Google Cloud project location for Vertex AI users.\n * If not provided, SDK will try to resolve it from runtime environment.\n */\n location?: string;\n /**\n * The API Key. This is required for Gemini API users.\n */\n apiKey?: string;\n /**\n * Optional. Set to true if you intend to call Vertex AI endpoints.\n * If unset, default SDK behavior is to call Gemini API.\n */\n vertexai?: boolean;\n /**\n * Optional. The API version for the endpoint.\n * If unset, SDK will choose a default api version.\n */\n apiVersion?: string;\n /**\n * Optional. A set of customizable configuration for HTTP requests.\n */\n httpOptions?: types.HttpOptions;\n /**\n * Optional. An extra string to append at the end of the User-Agent header.\n *\n * This can be used to e.g specify the runtime and its version.\n */\n userAgentExtra?: string;\n}\n\n/**\n * Represents the necessary information to send a request to an API endpoint.\n * This interface defines the structure for constructing and executing HTTP\n * requests.\n */\nexport interface HttpRequest {\n /**\n * URL path from the modules, this path is appended to the base API URL to\n * form the complete request URL.\n *\n * If you wish to set full URL, use httpOptions.baseUrl instead. Example to\n * set full URL in the request:\n *\n * const request: HttpRequest = {\n * path: '',\n * httpOptions: {\n * baseUrl: 'https://<custom-full-url>',\n * apiVersion: '',\n * },\n * httpMethod: 'GET',\n * };\n *\n * The result URL will be: https://<custom-full-url>\n *\n */\n path: string;\n /**\n * Optional query parameters to be appended to the request URL.\n */\n queryParams?: Record<string, string>;\n /**\n * Optional request body in json string or Blob format, GET request doesn't\n * need a request body.\n */\n body?: string | Blob;\n /**\n * The HTTP method to be used for the request.\n */\n httpMethod: 'GET' | 'POST' | 'PATCH' | 'DELETE';\n /**\n * Optional set of customizable configuration for HTTP requests.\n */\n httpOptions?: types.HttpOptions;\n /**\n * Optional abort signal which can be used to cancel the request.\n */\n abortSignal?: AbortSignal;\n}\n\n/**\n * The ApiClient class is used to send requests to the Gemini API or Vertex AI\n * endpoints.\n */\nexport class ApiClient implements GeminiNextGenAPIClientAdapter {\n readonly clientOptions: ApiClientInitOptions;\n private readonly customBaseUrl?: string;\n constructor(opts: ApiClientInitOptions) {\n this.clientOptions = {\n ...opts,\n };\n\n this.customBaseUrl = opts.httpOptions?.baseUrl;\n\n if (this.clientOptions.vertexai) {\n if (this.clientOptions.project && this.clientOptions.location) {\n this.clientOptions.apiKey = undefined;\n } else if (this.clientOptions.apiKey) {\n this.clientOptions.project = undefined;\n this.clientOptions.location = undefined;\n }\n }\n\n const initHttpOptions: types.HttpOptions = {};\n\n if (this.clientOptions.vertexai) {\n if (\n !this.clientOptions.location &&\n !this.clientOptions.apiKey &&\n !this.customBaseUrl\n ) {\n this.clientOptions.location = 'global';\n }\n\n const hasSufficientAuth =\n (this.clientOptions.project && this.clientOptions.location) ||\n this.clientOptions.apiKey;\n\n if (!hasSufficientAuth && !this.customBaseUrl) {\n throw new Error(\n 'Authentication is not set up. Please provide either a project and location, or an API key, or a custom base URL.',\n );\n }\n\n const hasConstructorAuth =\n (opts.project && opts.location) || !!opts.apiKey;\n\n if (this.customBaseUrl && !hasConstructorAuth) {\n initHttpOptions.baseUrl = this.customBaseUrl;\n this.clientOptions.project = undefined;\n this.clientOptions.location = undefined;\n } else if (\n this.clientOptions.apiKey ||\n this.clientOptions.location === 'global'\n ) {\n // Vertex Express or global endpoint case.\n initHttpOptions.baseUrl = 'https://aiplatform.googleapis.com/';\n } else if (this.clientOptions.project && this.clientOptions.location) {\n initHttpOptions.baseUrl = `https://${this.clientOptions.location}-aiplatform.googleapis.com/`;\n }\n\n initHttpOptions.apiVersion =\n this.clientOptions.apiVersion ?? VERTEX_AI_API_DEFAULT_VERSION;\n } else {\n // Gemini API\n if (!this.clientOptions.apiKey) {\n throw new ApiError({\n message: 'API key must be set when using the Gemini API.',\n status: 403,\n });\n }\n initHttpOptions.apiVersion =\n this.clientOptions.apiVersion ?? GOOGLE_AI_API_DEFAULT_VERSION;\n initHttpOptions.baseUrl = `https://generativelanguage.googleapis.com/`;\n }\n\n initHttpOptions.headers = this.getDefaultHeaders();\n\n this.clientOptions.httpOptions = initHttpOptions;\n\n if (opts.httpOptions) {\n this.clientOptions.httpOptions = this.patchHttpOptions(\n initHttpOptions,\n opts.httpOptions,\n );\n }\n }\n\n isVertexAI(): boolean {\n return this.clientOptions.vertexai ?? false;\n }\n\n getProject() {\n return this.clientOptions.project;\n }\n\n getLocation() {\n return this.clientOptions.location;\n }\n\n getCustomBaseUrl(): string | undefined {\n return this.customBaseUrl;\n }\n\n async getAuthHeaders(): Promise<Headers> {\n const headers = new Headers();\n await this.clientOptions.auth.addAuthHeaders(headers);\n return headers;\n }\n\n getApiVersion() {\n if (\n this.clientOptions.httpOptions &&\n this.clientOptions.httpOptions.apiVersion !== undefined\n ) {\n return this.clientOptions.httpOptions.apiVersion;\n }\n throw new Error('API version is not set.');\n }\n\n getBaseUrl() {\n if (\n this.clientOptions.httpOptions &&\n this.clientOptions.httpOptions.baseUrl !== undefined\n ) {\n return this.clientOptions.httpOptions.baseUrl;\n }\n throw new Error('Base URL is not set.');\n }\n\n getRequestUrl() {\n return this.getRequestUrlInternal(this.clientOptions.httpOptions);\n }\n\n getHeaders() {\n if (\n this.clientOptions.httpOptions &&\n this.clientOptions.httpOptions.headers !== undefined\n ) {\n return this.clientOptions.httpOptions.headers;\n } else {\n throw new Error('Headers are not set.');\n }\n }\n\n private getRequestUrlInternal(httpOptions?: types.HttpOptions) {\n if (\n !httpOptions ||\n httpOptions.baseUrl === undefined ||\n httpOptions.apiVersion === undefined\n ) {\n throw new Error('HTTP options are not correctly set.');\n }\n const baseUrl = httpOptions.baseUrl.endsWith('/')\n ? httpOptions.baseUrl.slice(0, -1)\n : httpOptions.baseUrl;\n const urlElement: Array<string> = [baseUrl];\n if (httpOptions.apiVersion && httpOptions.apiVersion !== '') {\n urlElement.push(httpOptions.apiVersion);\n }\n return urlElement.join('/');\n }\n\n getBaseResourcePath() {\n return `projects/${this.clientOptions.project}/locations/${\n this.clientOptions.location\n }`;\n }\n\n getApiKey() {\n return this.clientOptions.apiKey;\n }\n\n getWebsocketBaseUrl() {\n const baseUrl = this.getBaseUrl();\n const urlParts = new URL(baseUrl);\n urlParts.protocol = urlParts.protocol == 'http:' ? 'ws' : 'wss';\n return urlParts.toString();\n }\n\n setBaseUrl(url: string) {\n if (this.clientOptions.httpOptions) {\n this.clientOptions.httpOptions.baseUrl = url;\n } else {\n throw new Error('HTTP options are not correctly set.');\n }\n }\n\n private constructUrl(\n path: string,\n httpOptions: types.HttpOptions,\n prependProjectLocation: boolean,\n ): URL {\n const urlElement: Array<string> = [this.getRequestUrlInternal(httpOptions)];\n if (prependProjectLocation) {\n urlElement.push(this.getBaseResourcePath());\n }\n if (path !== '') {\n urlElement.push(path);\n }\n const url = new URL(`${urlElement.join('/')}`);\n\n return url;\n }\n\n private shouldPrependVertexProjectPath(\n request: HttpRequest,\n httpOptions: types.HttpOptions,\n ): boolean {\n if (\n httpOptions.baseUrl &&\n httpOptions.baseUrlResourceScope === types.ResourceScope.COLLECTION\n ) {\n return false;\n }\n if (this.clientOptions.apiKey) {\n return false;\n }\n if (!this.clientOptions.vertexai) {\n return false;\n }\n if (request.path.startsWith('projects/')) {\n // Assume the path already starts with\n // `projects/<project>/location/<location>`.\n return false;\n }\n if (\n request.httpMethod === 'GET' &&\n request.path.startsWith('publishers/google/models')\n ) {\n // These paths are used by Vertex's models.get and models.list\n // calls. For base models Vertex does not accept a project/location\n // prefix (for tuned model the prefix is required).\n return false;\n }\n return true;\n }\n\n async request(request: HttpRequest): Promise<types.HttpResponse> {\n let patchedHttpOptions = this.clientOptions.httpOptions!;\n if (request.httpOptions) {\n patchedHttpOptions = this.patchHttpOptions(\n this.clientOptions.httpOptions!,\n request.httpOptions,\n );\n }\n\n const prependProjectLocation = this.shouldPrependVertexProjectPath(\n request,\n patchedHttpOptions,\n );\n const url = this.constructUrl(\n request.path,\n patchedHttpOptions,\n prependProjectLocation,\n );\n if (request.queryParams) {\n for (const [key, value] of Object.entries(request.queryParams)) {\n url.searchParams.append(key, String(value));\n }\n }\n let requestInit: RequestInit = {};\n if (request.httpMethod === 'GET') {\n if (request.body && request.body !== '{}') {\n throw new Error(\n 'Request body should be empty for GET request, but got non empty request body',\n );\n }\n } else {\n requestInit.body = request.body;\n }\n requestInit = await this.includeExtraHttpOptionsToRequestInit(\n requestInit,\n patchedHttpOptions,\n url.toString(),\n request.abortSignal,\n );\n return this.unaryApiCall(url, requestInit, request.httpMethod);\n }\n\n private patchHttpOptions(\n baseHttpOptions: types.HttpOptions,\n requestHttpOptions: types.HttpOptions,\n ): types.HttpOptions {\n const patchedHttpOptions = JSON.parse(\n JSON.stringify(baseHttpOptions),\n ) as types.HttpOptions;\n\n for (const [key, value] of Object.entries(requestHttpOptions)) {\n // Records compile to objects.\n if (typeof value === 'object') {\n // @ts-expect-error TS2345TS7053: Element implicitly has an 'any' type\n // because expression of type 'string' can't be used to index type\n // 'HttpOptions'.\n patchedHttpOptions[key] = {...patchedHttpOptions[key], ...value};\n } else if (value !== undefined) {\n // @ts-expect-error TS2345TS7053: Element implicitly has an 'any' type\n // because expression of type 'string' can't be used to index type\n // 'HttpOptions'.\n patchedHttpOptions[key] = value;\n }\n }\n return patchedHttpOptions;\n }\n\n async requestStream(\n request: HttpRequest,\n ): Promise<AsyncGenerator<types.HttpResponse>> {\n let patchedHttpOptions = this.clientOptions.httpOptions!;\n if (request.httpOptions) {\n patchedHttpOptions = this.patchHttpOptions(\n this.clientOptions.httpOptions!,\n request.httpOptions,\n );\n }\n\n const prependProjectLocation = this.shouldPrependVertexProjectPath(\n request,\n patchedHttpOptions,\n );\n const url = this.constructUrl(\n request.path,\n patchedHttpOptions,\n prependProjectLocation,\n );\n if (!url.searchParams.has('alt') || url.searchParams.get('alt') !== 'sse') {\n url.searchParams.set('alt', 'sse');\n }\n let requestInit: RequestInit = {};\n requestInit.body = request.body;\n requestInit = await this.includeExtraHttpOptionsToRequestInit(\n requestInit,\n patchedHttpOptions,\n url.toString(),\n request.abortSignal,\n );\n return this.streamApiCall(url, requestInit, request.httpMethod);\n }\n\n private async includeExtraHttpOptionsToRequestInit(\n requestInit: RequestInit,\n httpOptions: types.HttpOptions,\n url: string,\n abortSignal?: AbortSignal,\n ): Promise<RequestInit> {\n if ((httpOptions && httpOptions.timeout) || abortSignal) {\n const abortController = new AbortController();\n const signal = abortController.signal;\n if (httpOptions.timeout && httpOptions?.timeout > 0) {\n const timeoutHandle = setTimeout(\n () => abortController.abort(),\n httpOptions.timeout,\n );\n if (\n timeoutHandle &&\n typeof (timeoutHandle as unknown as NodeJS.Timeout).unref ===\n 'function'\n ) {\n // call unref to prevent nodejs process from hanging, see\n // https://nodejs.org/api/timers.html#timeoutunref\n timeoutHandle.unref();\n }\n }\n if (abortSignal) {\n abortSignal.addEventListener('abort', () => {\n abortController.abort();\n });\n }\n requestInit.signal = signal;\n }\n if (httpOptions && httpOptions.extraBody !== null) {\n includeExtraBodyToRequestInit(\n requestInit,\n httpOptions.extraBody as Record<string, unknown>,\n );\n }\n requestInit.headers = await this.getHeadersInternal(httpOptions, url);\n return requestInit;\n }\n\n private async unaryApiCall(\n url: URL,\n requestInit: RequestInit,\n httpMethod: 'GET' | 'POST' | 'PATCH' | 'DELETE',\n ): Promise<types.HttpResponse> {\n return this.apiCall(url.toString(), {\n ...requestInit,\n method: httpMethod,\n })\n .then(async (response) => {\n await throwErrorIfNotOK(response);\n return new types.HttpResponse(response);\n })\n .catch((e) => {\n if (e instanceof Error) {\n throw e;\n } else {\n throw new Error(JSON.stringify(e));\n }\n });\n }\n\n private async streamApiCall(\n url: URL,\n requestInit: RequestInit,\n httpMethod: 'GET' | 'POST' | 'PATCH' | 'DELETE',\n ): Promise<AsyncGenerator<types.HttpResponse>> {\n return this.apiCall(url.toString(), {\n ...requestInit,\n method: httpMethod,\n })\n .then(async (response) => {\n await throwErrorIfNotOK(response);\n return this.processStreamResponse(response);\n })\n .catch((e) => {\n if (e instanceof Error) {\n throw e;\n } else {\n throw new Error(JSON.stringify(e));\n }\n });\n }\n\n async *processStreamResponse(\n response: Response,\n ): AsyncGenerator<types.HttpResponse> {\n const reader = response?.body?.getReader();\n const decoder = new TextDecoder('utf-8');\n if (!reader) {\n throw new Error('Response body is empty');\n }\n\n try {\n let buffer = '';\n const dataPrefix = 'data:';\n const delimiters = ['\\n\\n', '\\r\\r', '\\r\\n\\r\\n'];\n\n while (true) {\n const {done, value} = await reader.read();\n if (done) {\n if (buffer.trim().length > 0) {\n throw new Error('Incomplete JSON segment at the end');\n }\n break;\n }\n const chunkString = decoder.decode(value, {stream: true});\n\n // Parse and throw an error if the chunk contains an error.\n try {\n const chunkJson = JSON.parse(chunkString) as Record<string, unknown>;\n if ('error' in chunkJson) {\n const errorJson = JSON.parse(\n JSON.stringify(chunkJson['error']),\n ) as Record<string, unknown>;\n const status = errorJson['status'] as string;\n const code = errorJson['code'] as number;\n const errorMessage = `got status: ${status}. ${JSON.stringify(\n chunkJson,\n )}`;\n if (code >= 400 && code < 600) {\n const apiError = new ApiError({\n message: errorMessage,\n status: code,\n });\n throw apiError;\n }\n }\n } catch (e: unknown) {\n const error = e as Error;\n if (error.name === 'ApiError') {\n throw e;\n }\n }\n buffer += chunkString;\n\n let delimiterIndex = -1;\n let delimiterLength = 0;\n\n while (true) {\n delimiterIndex = -1;\n delimiterLength = 0;\n\n for (const delimiter of delimiters) {\n const index = buffer.indexOf(delimiter);\n if (\n index !== -1 &&\n (delimiterIndex === -1 || index < delimiterIndex)\n ) {\n delimiterIndex = index;\n delimiterLength = delimiter.length;\n }\n }\n\n if (delimiterIndex === -1) {\n break; // No complete event in buffer\n }\n\n const eventString = buffer.substring(0, delimiterIndex);\n buffer = buffer.substring(delimiterIndex + delimiterLength);\n\n const trimmedEvent = eventString.trim();\n\n if (trimmedEvent.startsWith(dataPrefix)) {\n const processedChunkString = trimmedEvent\n .substring(dataPrefix.length)\n .trim();\n try {\n const partialResponse = new Response(processedChunkString, {\n headers: response?.headers,\n status: response?.status,\n statusText: response?.statusText,\n });\n yield new types.HttpResponse(partialResponse);\n } catch (e) {\n throw new Error(\n `exception parsing stream chunk ${processedChunkString}. ${e}`,\n );\n }\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n }\n private async apiCall(\n url: string,\n requestInit: RequestInit,\n ): Promise<Response> {\n if (\n !this.clientOptions.httpOptions ||\n !this.clientOptions.httpOptions.retryOptions\n ) {\n return fetch(url, requestInit);\n }\n\n const retryOptions = this.clientOptions.httpOptions.retryOptions;\n const runFetch = async () => {\n const response = await fetch(url, requestInit);\n\n if (response.ok) {\n return response;\n }\n\n if (DEFAULT_RETRY_HTTP_STATUS_CODES.includes(response.status)) {\n throw new Error(`Retryable HTTP Error: ${response.statusText}`);\n }\n\n throw new AbortError(\n `Non-retryable exception ${response.statusText} sending request`,\n );\n };\n\n return pRetry(runFetch, {\n // Retry attempts is one less than the number of total attempts.\n retries: (retryOptions.attempts ?? DEFAULT_RETRY_ATTEMPTS) - 1,\n });\n }\n\n getDefaultHeaders(): Record<string, string> {\n const headers: Record<string, string> = {};\n\n const versionHeaderValue =\n LIBRARY_LABEL + ' ' + this.clientOptions.userAgentExtra;\n\n headers[USER_AGENT_HEADER] = versionHeaderValue;\n headers[GOOGLE_API_CLIENT_HEADER] = versionHeaderValue;\n headers[CONTENT_TYPE_HEADER] = 'application/json';\n\n return headers;\n }\n\n private async getHeadersInternal(\n httpOptions: types.HttpOptions | undefined,\n url: string,\n ): Promise<Headers> {\n const headers = new Headers();\n if (httpOptions && httpOptions.headers) {\n for (const [key, value] of Object.entries(httpOptions.headers)) {\n headers.append(key, value);\n }\n // Append a timeout header if it is set, note that the timeout option is\n // in milliseconds but the header is in seconds.\n if (httpOptions.timeout && httpOptions.timeout > 0) {\n headers.append(\n SERVER_TIMEOUT_HEADER,\n String(Math.ceil(httpOptions.timeout / 1000)),\n );\n }\n }\n await this.clientOptions.auth.addAuthHeaders(headers, url);\n return headers;\n }\n\n private getFileName(file: string | Blob): string {\n let fileName: string = '';\n if (typeof file === 'string') {\n fileName = file.replace(/[/\\\\]+$/, '');\n fileName = fileName.split(/[/\\\\]/).pop() ?? '';\n }\n return fileName;\n }\n\n /**\n * Uploads a file asynchronously using Gemini API only, this is not supported\n * in Vertex AI.\n *\n * @param file The string path to the file to be uploaded or a Blob object.\n * @param config Optional parameters specified in the `UploadFileConfig`\n * interface. @see {@link types.UploadFileConfig}\n * @return A promise that resolves to a `File` object.\n * @throws An error if called on a Vertex AI client.\n * @throws An error if the `mimeType` is not provided and can not be inferred,\n */\n async uploadFile(\n file: string | Blob,\n config?: types.UploadFileConfig,\n ): Promise<types.File> {\n const fileToUpload: types.File = {};\n if (config != null) {\n fileToUpload.mimeType = config.mimeType;\n fileToUpload.name = config.name;\n fileToUpload.displayName = config.displayName;\n }\n\n if (fileToUpload.name && !fileToUpload.name.startsWith('files/')) {\n fileToUpload.name = `files/${fileToUpload.name}`;\n }\n\n const uploader = this.clientOptions.uploader;\n const fileStat = await uploader.stat(file);\n fileToUpload.sizeBytes = String(fileStat.size);\n const mimeType = config?.mimeType ?? fileStat.type;\n if (mimeType === undefined || mimeType === '') {\n throw new Error(\n 'Can not determine mimeType. Please provide mimeType in the config.',\n );\n }\n fileToUpload.mimeType = mimeType;\n const body: Record<string, unknown> = {\n file: fileToUpload,\n };\n const fileName = this.getFileName(file);\n const path = common.formatMap(\n 'upload/v1beta/files',\n body['_url'] as Record<string, unknown>,\n );\n const uploadUrl = await this.fetchUploadUrl(\n path,\n fileToUpload.sizeBytes,\n fileToUpload.mimeType,\n fileName,\n body,\n config?.httpOptions,\n );\n return uploader.upload(file, uploadUrl, this);\n }\n\n /**\n * Uploads a file to a given file search store asynchronously using Gemini API only, this is not supported\n * in Vertex AI.\n *\n * @param fileSearchStoreName The name of the file search store to upload the file to.\n * @param file The string path to the file to be uploaded or a Blob object.\n * @param config Optional parameters specified in the `UploadFileConfig`\n * interface. @see {@link UploadFileConfig}\n * @return A promise that resolves to a `File` object.\n * @throws An error if called on a Vertex AI client.\n * @throws An error if the `mimeType` is not provided and can not be inferred,\n */\n async uploadFileToFileSearchStore(\n fileSearchStoreName: string,\n file: string | Blob,\n config?: types.UploadToFileSearchStoreConfig,\n ): Promise<types.UploadToFileSearchStoreOperation> {\n const uploader = this.clientOptions.uploader;\n const fileStat = await uploader.stat(file);\n const sizeBytes = String(fileStat.size);\n const mimeType = config?.mimeType ?? fileStat.type;\n if (mimeType === undefined || mimeType === '') {\n throw new Error(\n 'Can not determine mimeType. Please provide mimeType in the config.',\n );\n }\n const path = `upload/v1beta/${fileSearchStoreName}:uploadToFileSearchStore`;\n const fileName = this.getFileName(file);\n const body: Record<string, unknown> = {};\n if (config != null) {\n uploadToFileSearchStoreConfigToMldev(config, body);\n }\n const uploadUrl = await this.fetchUploadUrl(\n path,\n sizeBytes,\n mimeType,\n fileName,\n body,\n config?.httpOptions,\n );\n return uploader.uploadToFileSearchStore(file, uploadUrl, this);\n }\n\n /**\n * Downloads a file asynchronously to the specified path.\n *\n * @params params - The parameters for the download request, see {@link\n * types.DownloadFileParameters}\n */\n async downloadFile(params: types.DownloadFileParameters): Promise<void> {\n const downloader = this.clientOptions.downloader;\n await downloader.download(params, this);\n }\n\n private async fetchUploadUrl(\n path: string,\n sizeBytes: string,\n mimeType: string,\n fileName: string,\n body: Record<string, unknown>,\n configHttpOptions?: types.HttpOptions,\n ): Promise<string> {\n let httpOptions: types.HttpOptions = {};\n if (configHttpOptions) {\n httpOptions = configHttpOptions;\n } else {\n httpOptions = {\n apiVersion: '', // api-version is set in the path.\n headers: {\n 'Content-Type': 'application/json',\n 'X-Goog-Upload-Protocol': 'resumable',\n 'X-Goog-Upload-Command': 'start',\n 'X-Goog-Upload-Header-Content-Length': `${sizeBytes}`,\n 'X-Goog-Upload-Header-Content-Type': `${mimeType}`,\n ...(fileName ? {'X-Goog-Upload-File-Name': fileName} : {}),\n },\n };\n }\n\n const httpResponse = await this.request({\n path,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions,\n });\n\n if (!httpResponse || !httpResponse?.headers) {\n throw new Error(\n 'Server did not return an HttpResponse or the returned HttpResponse did not have headers.',\n );\n }\n\n const uploadUrl: string | undefined =\n httpResponse?.headers?.['x-goog-upload-url'];\n if (uploadUrl === undefined) {\n throw new Error(\n 'Failed to get upload url. Server did not return the x-google-upload-url in the headers',\n );\n }\n return uploadUrl;\n }\n}\n\nasync function throwErrorIfNotOK(response: Response | undefined) {\n if (response === undefined) {\n throw new Error('response is undefined');\n }\n if (!response.ok) {\n const status: number = response.status;\n let errorBody: Record<string, unknown>;\n if (response.headers.get('content-type')?.includes('application/json')) {\n errorBody = await response.json();\n } else {\n errorBody = {\n error: {\n message: await response.text(),\n code: response.status,\n status: response.statusText,\n },\n };\n }\n const errorMessage = JSON.stringify(errorBody);\n if (status >= 400 && status < 600) {\n const apiError = new ApiError({\n message: errorMessage,\n status: status,\n });\n throw apiError;\n }\n throw new Error(errorMessage);\n }\n}\n\n/**\n * Recursively updates the `requestInit.body` with values from an `extraBody` object.\n *\n * If `requestInit.body` is a string, it's assumed to be JSON and will be parsed.\n * The `extraBody` is then deeply merged into this parsed object.\n * If `requestInit.body` is a Blob, `extraBody` will be ignored, and a warning logged,\n * as merging structured data into an opaque Blob is not supported.\n *\n * The function does not enforce that updated values from `extraBody` have the\n * same type as existing values in `requestInit.body`. Type mismatches during\n * the merge will result in a warning, but the value from `extraBody` will overwrite\n * the original. `extraBody` users are responsible for ensuring `extraBody` has the correct structure.\n *\n * @param requestInit The RequestInit object whose body will be updated.\n * @param extraBody The object containing updates to be merged into `requestInit.body`.\n */\nexport function includeExtraBodyToRequestInit(\n requestInit: RequestInit,\n extraBody: Record<string, unknown>,\n) {\n if (!extraBody || Object.keys(extraBody).length === 0) {\n return;\n }\n\n if (requestInit.body instanceof Blob) {\n console.warn(\n 'includeExtraBodyToRequestInit: extraBody provided but current request body is a Blob. extraBody will be ignored as merging is not supported for Blob bodies.',\n );\n return;\n }\n\n let currentBodyObject: Record<string, unknown> = {};\n\n // If adding new type to HttpRequest.body, please check the code below to\n // see if we need to update the logic.\n if (typeof requestInit.body === 'string' && requestInit.body.length > 0) {\n try {\n const parsedBody = JSON.parse(requestInit.body);\n if (\n typeof parsedBody === 'object' &&\n parsedBody !== null &&\n !Array.isArray(parsedBody)\n ) {\n currentBodyObject = parsedBody as Record<string, unknown>;\n } else {\n console.warn(\n 'includeExtraBodyToRequestInit: Original request body is valid JSON but not a non-array object. Skip applying extraBody to the request body.',\n );\n return;\n }\n /* eslint-disable-next-line @typescript-eslint/no-unused-vars */\n } catch (e) {\n console.warn(\n 'includeExtraBodyToRequestInit: Original request body is not valid JSON. Skip applying extraBody to the request body.',\n );\n return;\n }\n }\n\n function deepMerge(\n target: Record<string, unknown>,\n source: Record<string, unknown>,\n ): Record<string, unknown> {\n const output = {...target};\n for (const key in source) {\n if (Object.prototype.hasOwnProperty.call(source, key)) {\n const sourceValue = source[key];\n const targetValue = output[key];\n if (\n sourceValue &&\n typeof sourceValue === 'object' &&\n !Array.isArray(sourceValue) &&\n targetValue &&\n typeof targetValue === 'object' &&\n !Array.isArray(targetValue)\n ) {\n output[key] = deepMerge(\n targetValue as Record<string, unknown>,\n sourceValue as Record<string, unknown>,\n );\n } else {\n if (\n targetValue &&\n sourceValue &&\n typeof targetValue !== typeof sourceValue\n ) {\n console.warn(\n `includeExtraBodyToRequestInit:deepMerge: Type mismatch for key \"${key}\". Original type: ${typeof targetValue}, New type: ${typeof sourceValue}. Overwriting.`,\n );\n }\n output[key] = sourceValue;\n }\n }\n }\n return output;\n }\n\n const mergedBody = deepMerge(currentBodyObject, extraBody);\n requestInit.body = JSON.stringify(mergedBody);\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type {Client as McpClient} from '@modelcontextprotocol/sdk/client/index.js';\nimport type {Tool as McpTool} from '@modelcontextprotocol/sdk/types.js';\n\nimport {GOOGLE_API_CLIENT_HEADER} from '../_api_client.js';\nimport {mcpToolsToGeminiTool} from '../_transformers.js';\nimport {\n CallableTool,\n CallableToolConfig,\n FunctionCall,\n Part,\n Tool,\n ToolListUnion,\n} from '../types.js';\n\n// TODO: b/416041229 - Determine how to retrieve the MCP package version.\nexport const MCP_LABEL = 'mcp_used/unknown';\n\n// Whether MCP tool usage is detected from mcpToTool. This is used for\n// telemetry.\nlet hasMcpToolUsageFromMcpToTool = false;\n\n// Checks whether the list of tools contains any MCP tools.\nexport function hasMcpToolUsage(tools: ToolListUnion): boolean {\n for (const tool of tools) {\n if (isMcpCallableTool(tool)) {\n return true;\n }\n if (typeof tool === 'object' && 'inputSchema' in tool) {\n return true;\n }\n }\n\n return hasMcpToolUsageFromMcpToTool;\n}\n\n// Sets the MCP version label in the Google API client header.\nexport function setMcpUsageHeader(headers: Record<string, string>) {\n const existingHeader = headers[GOOGLE_API_CLIENT_HEADER] ?? '';\n headers[GOOGLE_API_CLIENT_HEADER] = (\n existingHeader + ` ${MCP_LABEL}`\n ).trimStart();\n}\n\n// Returns true if the object is a MCP CallableTool, otherwise false.\nfunction isMcpCallableTool(object: unknown): boolean {\n return (\n object !== null &&\n typeof object === 'object' &&\n object instanceof McpCallableTool\n );\n}\n\n// List all tools from the MCP client.\nasync function* listAllTools(\n mcpClient: McpClient,\n maxTools: number = 100,\n): AsyncGenerator<McpTool> {\n let cursor: string | undefined = undefined;\n let numTools = 0;\n while (numTools < maxTools) {\n const t = await mcpClient.listTools({cursor});\n for (const tool of t.tools) {\n yield tool;\n numTools++;\n }\n if (!t.nextCursor) {\n break;\n }\n cursor = t.nextCursor;\n }\n}\n\n/**\n * McpCallableTool can be used for model inference and invoking MCP clients with\n * given function call arguments.\n *\n * @experimental Built-in MCP support is an experimental feature, may change in future\n * versions.\n */\nexport class McpCallableTool implements CallableTool {\n private readonly mcpClients;\n private mcpTools: McpTool[] = [];\n private functionNameToMcpClient: Record<string, McpClient> = {};\n private readonly config: CallableToolConfig;\n\n private constructor(\n mcpClients: McpClient[] = [],\n config: CallableToolConfig,\n ) {\n this.mcpClients = mcpClients;\n this.config = config;\n }\n\n /**\n * Creates a McpCallableTool.\n */\n public static create(\n mcpClients: McpClient[],\n config: CallableToolConfig,\n ): McpCallableTool {\n return new McpCallableTool(mcpClients, config);\n }\n\n /**\n * Validates the function names are not duplicate and initialize the function\n * name to MCP client mapping.\n *\n * @throws {Error} if the MCP tools from the MCP clients have duplicate tool\n * names.\n */\n async initialize() {\n if (this.mcpTools.length > 0) {\n return;\n }\n\n const functionMap: Record<string, McpClient> = {};\n const mcpTools: McpTool[] = [];\n for (const mcpClient of this.mcpClients) {\n for await (const mcpTool of listAllTools(mcpClient)) {\n mcpTools.push(mcpTool);\n const mcpToolName = mcpTool.name as string;\n if (functionMap[mcpToolName]) {\n throw new Error(\n `Duplicate function name ${\n mcpToolName\n } found in MCP tools. Please ensure function names are unique.`,\n );\n }\n functionMap[mcpToolName] = mcpClient;\n }\n }\n this.mcpTools = mcpTools;\n this.functionNameToMcpClient = functionMap;\n }\n\n public async tool(): Promise<Tool> {\n await this.initialize();\n return mcpToolsToGeminiTool(this.mcpTools, this.config);\n }\n\n public async callTool(functionCalls: FunctionCall[]): Promise<Part[]> {\n await this.initialize();\n const functionCallResponseParts: Part[] = [];\n for (const functionCall of functionCalls) {\n if (functionCall.name! in this.functionNameToMcpClient) {\n const mcpClient = this.functionNameToMcpClient[functionCall.name!];\n let requestOptions = undefined;\n // TODO: b/424238654 - Add support for finer grained timeout control.\n if (this.config.timeout) {\n requestOptions = {\n timeout: this.config.timeout,\n };\n }\n const callToolResponse = await mcpClient.callTool(\n {\n name: functionCall.name!,\n arguments: functionCall.args,\n },\n // Set the result schema to undefined to allow MCP to rely on the\n // default schema.\n undefined,\n requestOptions,\n );\n functionCallResponseParts.push({\n functionResponse: {\n name: functionCall.name,\n response: callToolResponse.isError\n ? {error: callToolResponse}\n : (callToolResponse as Record<string, unknown>),\n },\n });\n }\n }\n return functionCallResponseParts;\n }\n}\n\nfunction isMcpClient(client: unknown): client is McpClient {\n return (\n client !== null &&\n typeof client === 'object' &&\n 'listTools' in client &&\n typeof client.listTools === 'function'\n );\n}\n\n/**\n * Creates a McpCallableTool from MCP clients and an optional config.\n *\n * The callable tool can invoke the MCP clients with given function call\n * arguments. (often for automatic function calling).\n * Use the config to modify tool parameters such as behavior.\n *\n * @experimental Built-in MCP support is an experimental feature, may change in future\n * versions.\n */\nexport function mcpToTool(\n ...args: [...McpClient[], CallableToolConfig | McpClient]\n): CallableTool {\n // Set MCP usage for telemetry.\n hasMcpToolUsageFromMcpToTool = true;\n if (args.length === 0) {\n throw new Error('No MCP clients provided');\n }\n const maybeConfig = args[args.length - 1];\n if (isMcpClient(maybeConfig)) {\n return McpCallableTool.create(args as McpClient[], {});\n }\n return McpCallableTool.create(\n args.slice(0, args.length - 1) as McpClient[],\n maybeConfig,\n );\n}\n\n/**\n * Sets the MCP tool usage flag from calling mcpToTool. This is used for\n * telemetry.\n */\nexport function setMcpToolUsageFromMcpToTool(mcpToolUsage: boolean) {\n hasMcpToolUsageFromMcpToTool = mcpToolUsage;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Live music client.\n *\n * @experimental\n */\n\nimport {ApiClient} from './_api_client.js';\nimport {Auth} from './_auth.js';\nimport * as t from './_transformers.js';\nimport {WebSocket, WebSocketCallbacks, WebSocketFactory} from './_websocket.js';\nimport * as converters from './converters/_live_converters.js';\nimport * as types from './types.js';\n\n/**\n * Handles incoming messages from the WebSocket.\n *\n * @remarks\n * This function is responsible for parsing incoming messages, transforming them\n * into LiveMusicServerMessage, and then calling the onmessage callback.\n * Note that the first message which is received from the server is a\n * setupComplete message.\n *\n * @param apiClient The ApiClient instance.\n * @param onmessage The user-provided onmessage callback (if any).\n * @param event The MessageEvent from the WebSocket.\n */\nasync function handleWebSocketMessage(\n apiClient: ApiClient,\n onmessage: (msg: types.LiveMusicServerMessage) => void,\n event: MessageEvent,\n): Promise<void> {\n const serverMessage: types.LiveMusicServerMessage =\n new types.LiveMusicServerMessage();\n let data: types.LiveMusicServerMessage;\n if (event.data instanceof Blob) {\n data = JSON.parse(await event.data.text()) as types.LiveMusicServerMessage;\n } else {\n data = JSON.parse(event.data) as types.LiveMusicServerMessage;\n }\n Object.assign(serverMessage, data);\n onmessage(serverMessage);\n}\n\n/**\n LiveMusic class encapsulates the configuration for live music\n generation via Lyria Live models.\n\n @experimental\n */\nexport class LiveMusic {\n constructor(\n private readonly apiClient: ApiClient,\n private readonly auth: Auth,\n private readonly webSocketFactory: WebSocketFactory,\n ) {}\n\n /**\n Establishes a connection to the specified model and returns a\n LiveMusicSession object representing that connection.\n\n @experimental\n\n @remarks\n\n @param params - The parameters for establishing a connection to the model.\n @return A live session.\n\n @example\n ```ts\n let model = 'models/lyria-realtime-exp';\n const session = await ai.live.music.connect({\n model: model,\n callbacks: {\n onmessage: (e: MessageEvent) => {\n console.log('Received message from the server: %s\\n', debug(e.data));\n },\n onerror: (e: ErrorEvent) => {\n console.log('Error occurred: %s\\n', debug(e.error));\n },\n onclose: (e: CloseEvent) => {\n console.log('Connection closed.');\n },\n },\n });\n ```\n */\n async connect(\n params: types.LiveMusicConnectParameters,\n ): Promise<LiveMusicSession> {\n if (this.apiClient.isVertexAI()) {\n throw new Error('Live music is not supported for Vertex AI.');\n }\n console.warn(\n 'Live music generation is experimental and may change in future versions.',\n );\n\n const websocketBaseUrl = this.apiClient.getWebsocketBaseUrl();\n const apiVersion = this.apiClient.getApiVersion();\n const headers = mapToHeaders(this.apiClient.getDefaultHeaders());\n const apiKey = this.apiClient.getApiKey();\n const url = `${websocketBaseUrl}/ws/google.ai.generativelanguage.${\n apiVersion\n }.GenerativeService.BidiGenerateMusic?key=${apiKey}`;\n\n let onopenResolve: (value: unknown) => void = () => {};\n const onopenPromise = new Promise((resolve: (value: unknown) => void) => {\n onopenResolve = resolve;\n });\n\n const callbacks: types.LiveMusicCallbacks = params.callbacks;\n\n const onopenAwaitedCallback = function () {\n onopenResolve({});\n };\n\n const apiClient = this.apiClient;\n const websocketCallbacks: WebSocketCallbacks = {\n onopen: onopenAwaitedCallback,\n onmessage: (event: MessageEvent) => {\n void handleWebSocketMessage(apiClient, callbacks.onmessage, event);\n },\n onerror:\n callbacks?.onerror ??\n function (e: ErrorEvent) {\n void e;\n },\n onclose:\n callbacks?.onclose ??\n function (e: CloseEvent) {\n void e;\n },\n };\n\n const conn = this.webSocketFactory.create(\n url,\n headersToMap(headers),\n websocketCallbacks,\n );\n conn.connect();\n // Wait for the websocket to open before sending requests.\n await onopenPromise;\n\n const model = t.tModel(this.apiClient, params.model);\n const setup = {model};\n const clientMessage = {setup};\n conn.send(JSON.stringify(clientMessage));\n\n return new LiveMusicSession(conn, this.apiClient);\n }\n}\n\n/**\n Represents a connection to the API.\n\n @experimental\n */\nexport class LiveMusicSession {\n constructor(\n readonly conn: WebSocket,\n private readonly apiClient: ApiClient,\n ) {}\n\n /**\n Sets inputs to steer music generation. Updates the session's current\n weighted prompts.\n\n @param params - Contains one property, `weightedPrompts`.\n\n - `weightedPrompts` to send to the model; weights are normalized to\n sum to 1.0.\n\n @experimental\n */\n async setWeightedPrompts(\n params: types.LiveMusicSetWeightedPromptsParameters,\n ) {\n if (\n !params.weightedPrompts ||\n Object.keys(params.weightedPrompts).length === 0\n ) {\n throw new Error(\n 'Weighted prompts must be set and contain at least one entry.',\n );\n }\n const clientContent =\n converters.liveMusicSetWeightedPromptsParametersToMldev(params);\n this.conn.send(JSON.stringify({clientContent}));\n }\n\n /**\n Sets a configuration to the model. Updates the session's current\n music generation config.\n\n @param params - Contains one property, `musicGenerationConfig`.\n\n - `musicGenerationConfig` to set in the model. Passing an empty or\n undefined config to the model will reset the config to defaults.\n\n @experimental\n */\n async setMusicGenerationConfig(params: types.LiveMusicSetConfigParameters) {\n if (!params.musicGenerationConfig) {\n params.musicGenerationConfig = {};\n }\n const setConfigParameters =\n converters.liveMusicSetConfigParametersToMldev(params);\n this.conn.send(JSON.stringify(setConfigParameters));\n }\n\n private sendPlaybackControl(playbackControl: types.LiveMusicPlaybackControl) {\n const clientMessage = {playbackControl};\n this.conn.send(JSON.stringify(clientMessage));\n }\n\n /**\n * Start the music stream.\n *\n * @experimental\n */\n play() {\n this.sendPlaybackControl(types.LiveMusicPlaybackControl.PLAY);\n }\n\n /**\n * Temporarily halt the music stream. Use `play` to resume from the current\n * position.\n *\n * @experimental\n */\n pause() {\n this.sendPlaybackControl(types.LiveMusicPlaybackControl.PAUSE);\n }\n\n /**\n * Stop the music stream and reset the state. Retains the current prompts\n * and config.\n *\n * @experimental\n */\n stop() {\n this.sendPlaybackControl(types.LiveMusicPlaybackControl.STOP);\n }\n\n /**\n * Resets the context of the music generation without stopping it.\n * Retains the current prompts and config.\n *\n * @experimental\n */\n resetContext() {\n this.sendPlaybackControl(types.LiveMusicPlaybackControl.RESET_CONTEXT);\n }\n\n /**\n Terminates the WebSocket connection.\n\n @experimental\n */\n close() {\n this.conn.close();\n }\n}\n\n// Converts an headers object to a \"map\" object as expected by the WebSocket\n// constructor. We use this as the Auth interface works with Headers objects\n// while the WebSocket constructor takes a map.\nfunction headersToMap(headers: Headers): Record<string, string> {\n const headerMap: Record<string, string> = {};\n headers.forEach((value, key) => {\n headerMap[key] = value;\n });\n return headerMap;\n}\n\n// Converts a \"map\" object to a headers object. We use this as the Auth\n// interface works with Headers objects while the API client default headers\n// returns a map.\nfunction mapToHeaders(map: Record<string, string>): Headers {\n const headers = new Headers();\n for (const [key, value] of Object.entries(map)) {\n headers.append(key, value);\n }\n return headers;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Live client.\n *\n * @experimental\n */\n\nimport {ApiClient} from './_api_client.js';\nimport {Auth} from './_auth.js';\nimport * as t from './_transformers.js';\nimport {WebSocket, WebSocketCallbacks, WebSocketFactory} from './_websocket.js';\nimport * as converters from './converters/_live_converters.js';\nimport {contentToMldev} from './converters/_models_converters.js';\nimport {hasMcpToolUsage, setMcpUsageHeader} from './mcp/_mcp.js';\nimport {LiveMusic} from './music.js';\nimport * as types from './types.js';\n\nconst FUNCTION_RESPONSE_REQUIRES_ID =\n 'FunctionResponse request must have an `id` field from the response of a ToolCall.FunctionalCalls in Google AI.';\n\n/**\n * Handles incoming messages from the WebSocket.\n *\n * @remarks\n * This function is responsible for parsing incoming messages, transforming them\n * into LiveServerMessages, and then calling the onmessage callback. Note that\n * the first message which is received from the server is a setupComplete\n * message.\n *\n * @param apiClient The ApiClient instance.\n * @param onmessage The user-provided onmessage callback (if any).\n * @param event The MessageEvent from the WebSocket.\n */\nasync function handleWebSocketMessage(\n apiClient: ApiClient,\n onmessage: (msg: types.LiveServerMessage) => void,\n event: MessageEvent,\n): Promise<void> {\n const serverMessage: types.LiveServerMessage = new types.LiveServerMessage();\n let jsonData: string;\n if (event.data instanceof Blob) {\n jsonData = await event.data.text();\n } else if (event.data instanceof ArrayBuffer) {\n jsonData = new TextDecoder().decode(event.data);\n } else {\n jsonData = event.data;\n }\n\n const data = JSON.parse(jsonData) as types.LiveServerMessage;\n\n if (apiClient.isVertexAI()) {\n const resp = converters.liveServerMessageFromVertex(data);\n Object.assign(serverMessage, resp);\n } else {\n const resp = data;\n Object.assign(serverMessage, resp);\n }\n\n onmessage(serverMessage);\n}\n\n/**\n Live class encapsulates the configuration for live interaction with the\n Generative Language API. It embeds ApiClient for general API settings.\n\n @experimental\n */\nexport class Live {\n public readonly music: LiveMusic;\n\n constructor(\n private readonly apiClient: ApiClient,\n private readonly auth: Auth,\n private readonly webSocketFactory: WebSocketFactory,\n ) {\n this.music = new LiveMusic(\n this.apiClient,\n this.auth,\n this.webSocketFactory,\n );\n }\n\n /**\n Establishes a connection to the specified model with the given\n configuration and returns a Session object representing that connection.\n\n @experimental Built-in MCP support is an experimental feature, may change in\n future versions.\n\n @remarks\n\n @param params - The parameters for establishing a connection to the model.\n @return A live session.\n\n @example\n ```ts\n let model: string;\n if (GOOGLE_GENAI_USE_VERTEXAI) {\n model = 'gemini-2.0-flash-live-preview-04-09';\n } else {\n model = 'gemini-live-2.5-flash-preview';\n }\n const session = await ai.live.connect({\n model: model,\n config: {\n responseModalities: [Modality.AUDIO],\n },\n callbacks: {\n onopen: () => {\n console.log('Connected to the socket.');\n },\n onmessage: (e: MessageEvent) => {\n console.log('Received message from the server: %s\\n', debug(e.data));\n },\n onerror: (e: ErrorEvent) => {\n console.log('Error occurred: %s\\n', debug(e.error));\n },\n onclose: (e: CloseEvent) => {\n console.log('Connection closed.');\n },\n },\n });\n ```\n */\n async connect(params: types.LiveConnectParameters): Promise<Session> {\n // TODO: b/404946746 - Support per request HTTP options.\n if (params.config && params.config.httpOptions) {\n throw new Error(\n 'The Live module does not support httpOptions at request-level in' +\n ' LiveConnectConfig yet. Please use the client-level httpOptions' +\n ' configuration instead.',\n );\n }\n const websocketBaseUrl = this.apiClient.getWebsocketBaseUrl();\n const apiVersion = this.apiClient.getApiVersion();\n let url: string;\n const clientHeaders = this.apiClient.getHeaders();\n if (\n params.config &&\n params.config.tools &&\n hasMcpToolUsage(params.config.tools)\n ) {\n setMcpUsageHeader(clientHeaders);\n }\n const headers = mapToHeaders(clientHeaders);\n if (this.apiClient.isVertexAI()) {\n const project = this.apiClient.getProject();\n const location = this.apiClient.getLocation();\n const apiKey = this.apiClient.getApiKey();\n const hasStandardAuth = (!!project && !!location) || !!apiKey;\n\n if (this.apiClient.getCustomBaseUrl() && !hasStandardAuth) {\n // Custom base URL without standard auth (e.g., proxy).\n url = websocketBaseUrl;\n // Auth headers are assumed to be in `clientHeaders` from httpOptions.\n } else {\n url = `${websocketBaseUrl}/ws/google.cloud.aiplatform.${apiVersion}.LlmBidiService/BidiGenerateContent`;\n await this.auth.addAuthHeaders(headers, url);\n }\n } else {\n const apiKey = this.apiClient.getApiKey();\n\n let method = 'BidiGenerateContent';\n let keyName = 'key';\n if (apiKey?.startsWith('auth_tokens/')) {\n console.warn(\n 'Warning: Ephemeral token support is experimental and may change in future versions.',\n );\n if (apiVersion !== 'v1alpha') {\n console.warn(\n \"Warning: The SDK's ephemeral token support is in v1alpha only. Please use const ai = new GoogleGenAI({apiKey: token.name, httpOptions: { apiVersion: 'v1alpha' }}); before session connection.\",\n );\n }\n method = 'BidiGenerateContentConstrained';\n keyName = 'access_token';\n }\n\n url = `${websocketBaseUrl}/ws/google.ai.generativelanguage.${\n apiVersion\n }.GenerativeService.${method}?${keyName}=${apiKey}`;\n }\n\n let onopenResolve: (value: unknown) => void = () => {};\n const onopenPromise = new Promise((resolve: (value: unknown) => void) => {\n onopenResolve = resolve;\n });\n\n const callbacks: types.LiveCallbacks = params.callbacks;\n\n const onopenAwaitedCallback = function () {\n callbacks?.onopen?.();\n onopenResolve({});\n };\n\n const apiClient = this.apiClient;\n\n const websocketCallbacks: WebSocketCallbacks = {\n onopen: onopenAwaitedCallback,\n onmessage: (event: MessageEvent) => {\n void handleWebSocketMessage(apiClient, callbacks.onmessage, event);\n },\n onerror:\n callbacks?.onerror ??\n function (e: ErrorEvent) {\n void e;\n },\n onclose:\n callbacks?.onclose ??\n function (e: CloseEvent) {\n void e;\n },\n };\n\n const conn = this.webSocketFactory.create(\n url,\n headersToMap(headers),\n websocketCallbacks,\n );\n conn.connect();\n // Wait for the websocket to open before sending requests.\n await onopenPromise;\n\n let transformedModel = t.tModel(this.apiClient, params.model);\n if (\n this.apiClient.isVertexAI() &&\n transformedModel.startsWith('publishers/')\n ) {\n const project = this.apiClient.getProject();\n const location = this.apiClient.getLocation();\n if (project && location) {\n transformedModel =\n `projects/${project}/locations/${location}/` + transformedModel;\n }\n }\n\n let clientMessage: Record<string, unknown> = {};\n\n if (\n this.apiClient.isVertexAI() &&\n params.config?.responseModalities === undefined\n ) {\n // Set default to AUDIO to align with MLDev API.\n if (params.config === undefined) {\n params.config = {responseModalities: [types.Modality.AUDIO]};\n } else {\n params.config.responseModalities = [types.Modality.AUDIO];\n }\n }\n if (params.config?.generationConfig) {\n // Raise deprecation warning for generationConfig.\n console.warn(\n 'Setting `LiveConnectConfig.generation_config` is deprecated, please set the fields on `LiveConnectConfig` directly. This will become an error in a future version (not before Q3 2025).',\n );\n }\n const inputTools = params.config?.tools ?? [];\n const convertedTools: types.Tool[] = [];\n for (const tool of inputTools) {\n if (this.isCallableTool(tool)) {\n const callableTool = tool as types.CallableTool;\n convertedTools.push(await callableTool.tool());\n } else {\n convertedTools.push(tool as types.Tool);\n }\n }\n if (convertedTools.length > 0) {\n params.config!.tools = convertedTools;\n }\n const liveConnectParameters: types.LiveConnectParameters = {\n model: transformedModel,\n config: params.config,\n callbacks: params.callbacks,\n };\n if (this.apiClient.isVertexAI()) {\n clientMessage = converters.liveConnectParametersToVertex(\n this.apiClient,\n liveConnectParameters,\n );\n } else {\n clientMessage = converters.liveConnectParametersToMldev(\n this.apiClient,\n liveConnectParameters,\n );\n }\n delete clientMessage['config'];\n conn.send(JSON.stringify(clientMessage));\n return new Session(conn, this.apiClient);\n }\n\n // TODO: b/416041229 - Abstract this method to a common place.\n private isCallableTool(tool: types.ToolUnion): boolean {\n return 'callTool' in tool && typeof tool.callTool === 'function';\n }\n}\n\nconst defaultLiveSendClientContentParamerters: types.LiveSendClientContentParameters =\n {\n turnComplete: true,\n };\n\n/**\n Represents a connection to the API.\n\n @experimental\n */\nexport class Session {\n constructor(\n readonly conn: WebSocket,\n private readonly apiClient: ApiClient,\n ) {}\n\n private tLiveClientContent(\n apiClient: ApiClient,\n params: types.LiveSendClientContentParameters,\n ): types.LiveClientMessage {\n if (params.turns !== null && params.turns !== undefined) {\n let contents: types.Content[] = [];\n try {\n contents = t.tContents(params.turns as types.ContentListUnion);\n if (!apiClient.isVertexAI()) {\n contents = contents.map((item) => contentToMldev(item));\n }\n } catch {\n throw new Error(\n `Failed to parse client content \"turns\", type: '${typeof params.turns}'`,\n );\n }\n return {\n clientContent: {turns: contents, turnComplete: params.turnComplete},\n };\n }\n\n return {\n clientContent: {turnComplete: params.turnComplete},\n };\n }\n\n private tLiveClienttToolResponse(\n apiClient: ApiClient,\n params: types.LiveSendToolResponseParameters,\n ): types.LiveClientMessage {\n let functionResponses: types.FunctionResponse[] = [];\n\n if (params.functionResponses == null) {\n throw new Error('functionResponses is required.');\n }\n\n if (!Array.isArray(params.functionResponses)) {\n functionResponses = [params.functionResponses];\n } else {\n functionResponses = params.functionResponses;\n }\n\n if (functionResponses.length === 0) {\n throw new Error('functionResponses is required.');\n }\n\n for (const functionResponse of functionResponses) {\n if (\n typeof functionResponse !== 'object' ||\n functionResponse === null ||\n !('name' in functionResponse) ||\n !('response' in functionResponse)\n ) {\n throw new Error(\n `Could not parse function response, type '${typeof functionResponse}'.`,\n );\n }\n if (!apiClient.isVertexAI() && !('id' in functionResponse)) {\n throw new Error(FUNCTION_RESPONSE_REQUIRES_ID);\n }\n }\n\n const clientMessage: types.LiveClientMessage = {\n toolResponse: {functionResponses: functionResponses},\n };\n return clientMessage;\n }\n\n /**\n Send a message over the established connection.\n\n @param params - Contains two **optional** properties, `turns` and\n `turnComplete`.\n\n - `turns` will be converted to a `Content[]`\n - `turnComplete: true` [default] indicates that you are done sending\n content and expect a response. If `turnComplete: false`, the server\n will wait for additional messages before starting generation.\n\n @experimental\n\n @remarks\n There are two ways to send messages to the live API:\n `sendClientContent` and `sendRealtimeInput`.\n\n `sendClientContent` messages are added to the model context **in order**.\n Having a conversation using `sendClientContent` messages is roughly\n equivalent to using the `Chat.sendMessageStream`, except that the state of\n the `chat` history is stored on the API server instead of locally.\n\n Because of `sendClientContent`'s order guarantee, the model cannot respons\n as quickly to `sendClientContent` messages as to `sendRealtimeInput`\n messages. This makes the biggest difference when sending objects that have\n significant preprocessing time (typically images).\n\n The `sendClientContent` message sends a `Content[]`\n which has more options than the `Blob` sent by `sendRealtimeInput`.\n\n So the main use-cases for `sendClientContent` over `sendRealtimeInput` are:\n\n - Sending anything that can't be represented as a `Blob` (text,\n `sendClientContent({turns=\"Hello?\"}`)).\n - Managing turns when not using audio input and voice activity detection.\n (`sendClientContent({turnComplete:true})` or the short form\n `sendClientContent()`)\n - Prefilling a conversation context\n ```\n sendClientContent({\n turns: [\n Content({role:user, parts:...}),\n Content({role:user, parts:...}),\n ...\n ]\n })\n ```\n @experimental\n */\n sendClientContent(params: types.LiveSendClientContentParameters) {\n params = {\n ...defaultLiveSendClientContentParamerters,\n ...params,\n };\n\n const clientMessage: types.LiveClientMessage = this.tLiveClientContent(\n this.apiClient,\n params,\n );\n this.conn.send(JSON.stringify(clientMessage));\n }\n\n /**\n Send a realtime message over the established connection.\n\n @param params - Contains one property, `media`.\n\n - `media` will be converted to a `Blob`\n\n @experimental\n\n @remarks\n Use `sendRealtimeInput` for realtime audio chunks and video frames (images).\n\n With `sendRealtimeInput` the api will respond to audio automatically\n based on voice activity detection (VAD).\n\n `sendRealtimeInput` is optimized for responsivness at the expense of\n deterministic ordering guarantees. Audio and video tokens are to the\n context when they become available.\n\n Note: The Call signature expects a `Blob` object, but only a subset\n of audio and image mimetypes are allowed.\n */\n sendRealtimeInput(params: types.LiveSendRealtimeInputParameters) {\n let clientMessage: types.LiveClientMessage = {};\n\n if (this.apiClient.isVertexAI()) {\n clientMessage = {\n 'realtimeInput':\n converters.liveSendRealtimeInputParametersToVertex(params),\n };\n } else {\n clientMessage = {\n 'realtimeInput':\n converters.liveSendRealtimeInputParametersToMldev(params),\n };\n }\n this.conn.send(JSON.stringify(clientMessage));\n }\n\n /**\n Send a function response message over the established connection.\n\n @param params - Contains property `functionResponses`.\n\n - `functionResponses` will be converted to a `functionResponses[]`\n\n @remarks\n Use `sendFunctionResponse` to reply to `LiveServerToolCall` from the server.\n\n Use {@link types.LiveConnectConfig#tools} to configure the callable functions.\n\n @experimental\n */\n sendToolResponse(params: types.LiveSendToolResponseParameters) {\n if (params.functionResponses == null) {\n throw new Error('Tool response parameters are required.');\n }\n\n const clientMessage: types.LiveClientMessage =\n this.tLiveClienttToolResponse(this.apiClient, params);\n this.conn.send(JSON.stringify(clientMessage));\n }\n\n /**\n Terminates the WebSocket connection.\n\n @experimental\n\n @example\n ```ts\n let model: string;\n if (GOOGLE_GENAI_USE_VERTEXAI) {\n model = 'gemini-2.0-flash-live-preview-04-09';\n } else {\n model = 'gemini-live-2.5-flash-preview';\n }\n const session = await ai.live.connect({\n model: model,\n config: {\n responseModalities: [Modality.AUDIO],\n }\n });\n\n session.close();\n ```\n */\n close() {\n this.conn.close();\n }\n}\n\n// Converts an headers object to a \"map\" object as expected by the WebSocket\n// constructor. We use this as the Auth interface works with Headers objects\n// while the WebSocket constructor takes a map.\nfunction headersToMap(headers: Headers): Record<string, string> {\n const headerMap: Record<string, string> = {};\n headers.forEach((value, key) => {\n headerMap[key] = value;\n });\n return headerMap;\n}\n\n// Converts a \"map\" object to a headers object. We use this as the Auth\n// interface works with Headers objects while the API client default headers\n// returns a map.\nfunction mapToHeaders(map: Record<string, string>): Headers {\n const headers = new Headers();\n for (const [key, value] of Object.entries(map)) {\n headers.append(key, value);\n }\n return headers;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport * as types from './types.js';\n\nexport const DEFAULT_MAX_REMOTE_CALLS = 10;\n\n/** Returns whether automatic function calling is disabled. */\nexport function shouldDisableAfc(\n config: types.GenerateContentConfig | undefined,\n): boolean {\n if (config?.automaticFunctionCalling?.disable) {\n return true;\n }\n\n let callableToolsPresent = false;\n for (const tool of config?.tools ?? []) {\n if (isCallableTool(tool)) {\n callableToolsPresent = true;\n break;\n }\n }\n if (!callableToolsPresent) {\n return true;\n }\n\n const maxCalls = config?.automaticFunctionCalling?.maximumRemoteCalls;\n if (\n (maxCalls && (maxCalls < 0 || !Number.isInteger(maxCalls))) ||\n maxCalls == 0\n ) {\n console.warn(\n 'Invalid maximumRemoteCalls value provided for automatic function calling. Disabled automatic function calling. Please provide a valid integer value greater than 0. maximumRemoteCalls provided:',\n maxCalls,\n );\n return true;\n }\n return false;\n}\n\nexport function isCallableTool(tool: types.ToolUnion): boolean {\n return 'callTool' in tool && typeof tool.callTool === 'function';\n}\n\n// Checks whether the list of tools contains any CallableTools. Will return true\n// if there is at least one CallableTool.\nexport function hasCallableTools(\n params: types.GenerateContentParameters,\n): boolean {\n return params.config?.tools?.some((tool) => isCallableTool(tool)) ?? false;\n}\n\n/**\n * Returns the indexes of the tools that are not compatible with AFC.\n */\nexport function findAfcIncompatibleToolIndexes(\n params?: types.GenerateContentParameters,\n): number[] {\n // Use number[] for an array of numbers in TypeScript\n const afcIncompatibleToolIndexes: number[] = [];\n if (!params?.config?.tools) {\n return afcIncompatibleToolIndexes;\n }\n params.config.tools.forEach((tool, index) => {\n if (isCallableTool(tool)) {\n return;\n }\n const geminiTool = tool as types.Tool;\n if (\n geminiTool.functionDeclarations &&\n geminiTool.functionDeclarations.length > 0\n ) {\n afcIncompatibleToolIndexes.push(index);\n }\n });\n\n return afcIncompatibleToolIndexes;\n}\n\n/**\n * Returns whether to append automatic function calling history to the\n * response.\n */\nexport function shouldAppendAfcHistory(\n config: types.GenerateContentConfig | undefined,\n): boolean {\n return !config?.automaticFunctionCalling?.ignoreCallHistory;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport * as afc from './_afc.js';\nimport {ApiClient} from './_api_client.js';\nimport * as common from './_common.js';\nimport {BaseModule} from './_common.js';\nimport * as _internal_types from './_internal_types.js';\nimport {tContents} from './_transformers.js';\nimport * as converters from './converters/_models_converters.js';\nimport * as mcp from './mcp/_mcp.js';\nimport {PagedItem, Pager} from './pagers.js';\nimport * as types from './types.js';\n\nexport class Models extends BaseModule {\n constructor(private readonly apiClient: ApiClient) {\n super();\n }\n\n /**\n * Makes an API request to generate content with a given model.\n *\n * For the `model` parameter, supported formats for Vertex AI API include:\n * - The Gemini model ID, for example: 'gemini-2.0-flash'\n * - The full resource name starts with 'projects/', for example:\n * 'projects/my-project-id/locations/us-central1/publishers/google/models/gemini-2.0-flash'\n * - The partial resource name with 'publishers/', for example:\n * 'publishers/google/models/gemini-2.0-flash' or\n * 'publishers/meta/models/llama-3.1-405b-instruct-maas'\n * - `/` separated publisher and model name, for example:\n * 'google/gemini-2.0-flash' or 'meta/llama-3.1-405b-instruct-maas'\n *\n * For the `model` parameter, supported formats for Gemini API include:\n * - The Gemini model ID, for example: 'gemini-2.0-flash'\n * - The model name starts with 'models/', for example:\n * 'models/gemini-2.0-flash'\n * - For tuned models, the model name starts with 'tunedModels/',\n * for example:\n * 'tunedModels/1234567890123456789'\n *\n * Some models support multimodal input and output.\n *\n * @param params - The parameters for generating content.\n * @return The response from generating content.\n *\n * @example\n * ```ts\n * const response = await ai.models.generateContent({\n * model: 'gemini-2.0-flash',\n * contents: 'why is the sky blue?',\n * config: {\n * candidateCount: 2,\n * }\n * });\n * console.log(response);\n * ```\n */\n generateContent = async (\n params: types.GenerateContentParameters,\n ): Promise<types.GenerateContentResponse> => {\n const transformedParams = await this.processParamsMaybeAddMcpUsage(params);\n this.maybeMoveToResponseJsonSchem(params);\n if (!afc.hasCallableTools(params) || afc.shouldDisableAfc(params.config)) {\n return await this.generateContentInternal(transformedParams);\n }\n\n const incompatibleToolIndexes = afc.findAfcIncompatibleToolIndexes(params);\n if (incompatibleToolIndexes.length > 0) {\n const formattedIndexes = incompatibleToolIndexes\n .map((index: number) => `tools[${index}]`)\n .join(', ');\n throw new Error(\n `Automatic function calling with CallableTools (or MCP objects) and basic FunctionDeclarations is not yet supported. Incompatible tools found at ${formattedIndexes}.`,\n );\n }\n\n let response: types.GenerateContentResponse;\n let functionResponseContent: types.Content;\n const automaticFunctionCallingHistory: types.Content[] = tContents(\n transformedParams.contents,\n );\n const maxRemoteCalls =\n transformedParams.config?.automaticFunctionCalling?.maximumRemoteCalls ??\n afc.DEFAULT_MAX_REMOTE_CALLS;\n let remoteCalls = 0;\n while (remoteCalls < maxRemoteCalls) {\n response = await this.generateContentInternal(transformedParams);\n if (!response.functionCalls || response.functionCalls!.length === 0) {\n break;\n }\n\n const responseContent: types.Content = response.candidates![0].content!;\n const functionResponseParts: types.Part[] = [];\n for (const tool of params.config?.tools ?? []) {\n if (afc.isCallableTool(tool)) {\n const callableTool = tool as types.CallableTool;\n const parts = await callableTool.callTool(response.functionCalls!);\n functionResponseParts.push(...parts);\n }\n }\n\n remoteCalls++;\n\n functionResponseContent = {\n role: 'user',\n parts: functionResponseParts,\n };\n\n transformedParams.contents = tContents(transformedParams.contents);\n (transformedParams.contents as types.Content[]).push(responseContent);\n (transformedParams.contents as types.Content[]).push(\n functionResponseContent,\n );\n\n if (afc.shouldAppendAfcHistory(transformedParams.config)) {\n automaticFunctionCallingHistory.push(responseContent);\n automaticFunctionCallingHistory.push(functionResponseContent);\n }\n }\n if (afc.shouldAppendAfcHistory(transformedParams.config)) {\n response!.automaticFunctionCallingHistory =\n automaticFunctionCallingHistory;\n }\n return response!;\n };\n\n /**\n * This logic is needed for GenerateContentConfig only.\n * Previously we made GenerateContentConfig.responseSchema field to accept\n * unknown. Since v1.9.0, we switch to use backend JSON schema support.\n * To maintain backward compatibility, we move the data that was treated as\n * JSON schema from the responseSchema field to the responseJsonSchema field.\n */\n private maybeMoveToResponseJsonSchem(\n params: types.GenerateContentParameters,\n ): void {\n if (params.config && params.config.responseSchema) {\n if (!params.config.responseJsonSchema) {\n if (Object.keys(params.config.responseSchema).includes('$schema')) {\n params.config.responseJsonSchema = params.config.responseSchema;\n delete params.config.responseSchema;\n }\n }\n }\n return;\n }\n\n /**\n * Makes an API request to generate content with a given model and yields the\n * response in chunks.\n *\n * For the `model` parameter, supported formats for Vertex AI API include:\n * - The Gemini model ID, for example: 'gemini-2.0-flash'\n * - The full resource name starts with 'projects/', for example:\n * 'projects/my-project-id/locations/us-central1/publishers/google/models/gemini-2.0-flash'\n * - The partial resource name with 'publishers/', for example:\n * 'publishers/google/models/gemini-2.0-flash' or\n * 'publishers/meta/models/llama-3.1-405b-instruct-maas'\n * - `/` separated publisher and model name, for example:\n * 'google/gemini-2.0-flash' or 'meta/llama-3.1-405b-instruct-maas'\n *\n * For the `model` parameter, supported formats for Gemini API include:\n * - The Gemini model ID, for example: 'gemini-2.0-flash'\n * - The model name starts with 'models/', for example:\n * 'models/gemini-2.0-flash'\n * - For tuned models, the model name starts with 'tunedModels/',\n * for example:\n * 'tunedModels/1234567890123456789'\n *\n * Some models support multimodal input and output.\n *\n * @param params - The parameters for generating content with streaming response.\n * @return The response from generating content.\n *\n * @example\n * ```ts\n * const response = await ai.models.generateContentStream({\n * model: 'gemini-2.0-flash',\n * contents: 'why is the sky blue?',\n * config: {\n * maxOutputTokens: 200,\n * }\n * });\n * for await (const chunk of response) {\n * console.log(chunk);\n * }\n * ```\n */\n generateContentStream = async (\n params: types.GenerateContentParameters,\n ): Promise<AsyncGenerator<types.GenerateContentResponse>> => {\n this.maybeMoveToResponseJsonSchem(params);\n if (afc.shouldDisableAfc(params.config)) {\n const transformedParams =\n await this.processParamsMaybeAddMcpUsage(params);\n return await this.generateContentStreamInternal(transformedParams);\n }\n const incompatibleToolIndexes = afc.findAfcIncompatibleToolIndexes(params);\n if (incompatibleToolIndexes.length > 0) {\n const formattedIndexes = incompatibleToolIndexes\n .map((index: number) => `tools[${index}]`)\n .join(', ');\n throw new Error(\n `Incompatible tools found at ${formattedIndexes}. Automatic function calling with CallableTools (or MCP objects) and basic FunctionDeclarations\" is not yet supported.`,\n );\n }\n\n // With tool compatibility confirmed, validate that the configuration are\n // compatible with each other and raise an error if invalid.\n const streamFunctionCall =\n params?.config?.toolConfig?.functionCallingConfig\n ?.streamFunctionCallArguments;\n const disableAfc = params?.config?.automaticFunctionCalling?.disable;\n\n if (streamFunctionCall && !disableAfc) {\n throw new Error(\n \"Running in streaming mode with 'streamFunctionCallArguments' enabled, \" +\n 'this feature is not compatible with automatic function calling (AFC). ' +\n \"Please set 'config.automaticFunctionCalling.disable' to true to disable AFC \" +\n \"or leave 'config.toolConfig.functionCallingConfig.streamFunctionCallArguments' \" +\n 'to be undefined or set to false to disable streaming function call arguments feature.',\n );\n }\n\n return await this.processAfcStream(params);\n };\n\n /**\n * Transforms the CallableTools in the parameters to be simply Tools, it\n * copies the params into a new object and replaces the tools, it does not\n * modify the original params. Also sets the MCP usage header if there are\n * MCP tools in the parameters.\n */\n private async processParamsMaybeAddMcpUsage(\n params: types.GenerateContentParameters,\n ): Promise<types.GenerateContentParameters> {\n const tools = params.config?.tools;\n if (!tools) {\n return params;\n }\n const transformedTools = await Promise.all(\n tools.map(async (tool) => {\n if (afc.isCallableTool(tool)) {\n const callableTool = tool as types.CallableTool;\n return await callableTool.tool();\n }\n return tool;\n }),\n );\n const newParams: types.GenerateContentParameters = {\n model: params.model,\n contents: params.contents,\n config: {\n ...params.config,\n tools: transformedTools,\n },\n };\n newParams.config!.tools = transformedTools;\n\n if (\n params.config &&\n params.config.tools &&\n mcp.hasMcpToolUsage(params.config.tools)\n ) {\n const headers = params.config.httpOptions?.headers ?? {};\n let newHeaders = {...headers};\n if (Object.keys(newHeaders).length === 0) {\n newHeaders = this.apiClient.getDefaultHeaders();\n }\n mcp.setMcpUsageHeader(newHeaders);\n newParams.config!.httpOptions = {\n ...params.config.httpOptions,\n headers: newHeaders,\n };\n }\n return newParams;\n }\n\n private async initAfcToolsMap(\n params: types.GenerateContentParameters,\n ): Promise<Map<string, types.CallableTool>> {\n const afcTools: Map<string, types.CallableTool> = new Map();\n for (const tool of params.config?.tools ?? []) {\n if (afc.isCallableTool(tool)) {\n const callableTool = tool as types.CallableTool;\n const toolDeclaration = await callableTool.tool();\n for (const declaration of toolDeclaration.functionDeclarations ?? []) {\n if (!declaration.name) {\n throw new Error('Function declaration name is required.');\n }\n if (afcTools.has(declaration.name)) {\n throw new Error(\n `Duplicate tool declaration name: ${declaration.name}`,\n );\n }\n afcTools.set(declaration.name, callableTool);\n }\n }\n }\n return afcTools;\n }\n\n private async processAfcStream(\n params: types.GenerateContentParameters,\n ): Promise<AsyncGenerator<types.GenerateContentResponse>> {\n const maxRemoteCalls =\n params.config?.automaticFunctionCalling?.maximumRemoteCalls ??\n afc.DEFAULT_MAX_REMOTE_CALLS;\n let wereFunctionsCalled = false;\n let remoteCallCount = 0;\n const afcToolsMap = await this.initAfcToolsMap(params);\n return (async function* (\n models: Models,\n afcTools: Map<string, types.CallableTool>,\n params: types.GenerateContentParameters,\n ) {\n while (remoteCallCount < maxRemoteCalls) {\n if (wereFunctionsCalled) {\n remoteCallCount++;\n wereFunctionsCalled = false;\n }\n const transformedParams =\n await models.processParamsMaybeAddMcpUsage(params);\n const response =\n await models.generateContentStreamInternal(transformedParams);\n\n const functionResponses: types.Part[] = [];\n const responseContents: types.Content[] = [];\n\n for await (const chunk of response) {\n yield chunk;\n if (chunk.candidates && chunk.candidates[0]?.content) {\n responseContents.push(chunk.candidates[0].content);\n for (const part of chunk.candidates[0].content.parts ?? []) {\n if (remoteCallCount < maxRemoteCalls && part.functionCall) {\n if (!part.functionCall.name) {\n throw new Error(\n 'Function call name was not returned by the model.',\n );\n }\n if (!afcTools.has(part.functionCall.name)) {\n throw new Error(\n `Automatic function calling was requested, but not all the tools the model used implement the CallableTool interface. Available tools: ${afcTools.keys()}, mising tool: ${\n part.functionCall.name\n }`,\n );\n } else {\n const responseParts = await afcTools\n .get(part.functionCall.name)!\n .callTool([part.functionCall]);\n functionResponses.push(...responseParts);\n }\n }\n }\n }\n }\n\n if (functionResponses.length > 0) {\n wereFunctionsCalled = true;\n const typedResponseChunk = new types.GenerateContentResponse();\n typedResponseChunk.candidates = [\n {\n content: {\n role: 'user',\n parts: functionResponses,\n },\n },\n ];\n\n yield typedResponseChunk;\n\n const newContents: types.Content[] = [];\n newContents.push(...responseContents);\n newContents.push({\n role: 'user',\n parts: functionResponses,\n });\n const updatedContents = tContents(params.contents).concat(\n newContents,\n );\n\n params.contents = updatedContents;\n } else {\n break;\n }\n }\n })(this, afcToolsMap, params);\n }\n\n /**\n * Generates an image based on a text description and configuration.\n *\n * @param params - The parameters for generating images.\n * @return The response from the API.\n *\n * @example\n * ```ts\n * const response = await client.models.generateImages({\n * model: 'imagen-4.0-generate-001',\n * prompt: 'Robot holding a red skateboard',\n * config: {\n * numberOfImages: 1,\n * includeRaiReason: true,\n * },\n * });\n * console.log(response?.generatedImages?.[0]?.image?.imageBytes);\n * ```\n */\n generateImages = async (\n params: types.GenerateImagesParameters,\n ): Promise<types.GenerateImagesResponse> => {\n return await this.generateImagesInternal(params).then((apiResponse) => {\n let positivePromptSafetyAttributes;\n const generatedImages = [];\n\n if (apiResponse?.generatedImages) {\n for (const generatedImage of apiResponse.generatedImages) {\n if (\n generatedImage &&\n generatedImage?.safetyAttributes &&\n generatedImage?.safetyAttributes?.contentType === 'Positive Prompt'\n ) {\n positivePromptSafetyAttributes = generatedImage?.safetyAttributes;\n } else {\n generatedImages.push(generatedImage);\n }\n }\n }\n let response: types.GenerateImagesResponse;\n\n if (positivePromptSafetyAttributes) {\n response = {\n generatedImages: generatedImages,\n positivePromptSafetyAttributes: positivePromptSafetyAttributes,\n sdkHttpResponse: apiResponse.sdkHttpResponse,\n };\n } else {\n response = {\n generatedImages: generatedImages,\n sdkHttpResponse: apiResponse.sdkHttpResponse,\n };\n }\n return response;\n });\n };\n\n list = async (\n params?: types.ListModelsParameters,\n ): Promise<Pager<types.Model>> => {\n const defaultConfig: types.ListModelsConfig = {\n queryBase: true,\n };\n const actualConfig: types.ListModelsConfig = {\n ...defaultConfig,\n ...params?.config,\n };\n const actualParams: types.ListModelsParameters = {\n config: actualConfig,\n };\n\n if (this.apiClient.isVertexAI()) {\n if (!actualParams.config!.queryBase) {\n if (actualParams.config?.filter) {\n throw new Error(\n 'Filtering tuned models list for Vertex AI is not currently supported',\n );\n } else {\n actualParams.config!.filter = 'labels.tune-type:*';\n }\n }\n }\n\n return new Pager<types.Model>(\n PagedItem.PAGED_ITEM_MODELS,\n (x: types.ListModelsParameters) => this.listInternal(x),\n await this.listInternal(actualParams),\n actualParams,\n );\n };\n\n /**\n * Edits an image based on a prompt, list of reference images, and configuration.\n *\n * @param params - The parameters for editing an image.\n * @return The response from the API.\n *\n * @example\n * ```ts\n * const response = await client.models.editImage({\n * model: 'imagen-3.0-capability-001',\n * prompt: 'Generate an image containing a mug with the product logo [1] visible on the side of the mug.',\n * referenceImages: [subjectReferenceImage]\n * config: {\n * numberOfImages: 1,\n * includeRaiReason: true,\n * },\n * });\n * console.log(response?.generatedImages?.[0]?.image?.imageBytes);\n * ```\n */\n editImage = async (\n params: types.EditImageParameters,\n ): Promise<types.EditImageResponse> => {\n const paramsInternal: _internal_types.EditImageParametersInternal = {\n model: params.model,\n prompt: params.prompt,\n referenceImages: [],\n config: params.config,\n };\n if (params.referenceImages) {\n if (params.referenceImages) {\n paramsInternal.referenceImages = params.referenceImages.map((img) =>\n img.toReferenceImageAPI(),\n );\n }\n }\n return await this.editImageInternal(paramsInternal);\n };\n\n /**\n * Upscales an image based on an image, upscale factor, and configuration.\n * Only supported in Vertex AI currently.\n *\n * @param params - The parameters for upscaling an image.\n * @return The response from the API.\n *\n * @example\n * ```ts\n * const response = await client.models.upscaleImage({\n * model: 'imagen-4.0-upscale-preview',\n * image: image,\n * upscaleFactor: 'x2',\n * config: {\n * includeRaiReason: true,\n * },\n * });\n * console.log(response?.generatedImages?.[0]?.image?.imageBytes);\n * ```\n */\n upscaleImage = async (\n params: types.UpscaleImageParameters,\n ): Promise<types.UpscaleImageResponse> => {\n let apiConfig: _internal_types.UpscaleImageAPIConfigInternal = {\n numberOfImages: 1,\n mode: 'upscale',\n };\n\n if (params.config) {\n apiConfig = {...apiConfig, ...params.config};\n }\n\n const apiParams: _internal_types.UpscaleImageAPIParametersInternal = {\n model: params.model,\n image: params.image,\n upscaleFactor: params.upscaleFactor,\n config: apiConfig,\n };\n return await this.upscaleImageInternal(apiParams);\n };\n\n /**\n * Generates videos based on a text description and configuration.\n *\n * @param params - The parameters for generating videos.\n * @return A Promise<GenerateVideosOperation> which allows you to track the progress and eventually retrieve the generated videos using the operations.get method.\n *\n * @example\n * ```ts\n * const operation = await ai.models.generateVideos({\n * model: 'veo-2.0-generate-001',\n * source: {\n * prompt: 'A neon hologram of a cat driving at top speed',\n * },\n * config: {\n * numberOfVideos: 1\n * });\n *\n * while (!operation.done) {\n * await new Promise(resolve => setTimeout(resolve, 10000));\n * operation = await ai.operations.getVideosOperation({operation: operation});\n * }\n *\n * console.log(operation.response?.generatedVideos?.[0]?.video?.uri);\n * ```\n */\n\n generateVideos = async (\n params: types.GenerateVideosParameters,\n ): Promise<types.GenerateVideosOperation> => {\n if ((params.prompt || params.image || params.video) && params.source) {\n throw new Error(\n 'Source and prompt/image/video are mutually exclusive. Please only use source.',\n );\n }\n // Gemini API does not support video bytes.\n if (!this.apiClient.isVertexAI()) {\n if (params.video?.uri && params.video?.videoBytes) {\n params.video = {\n uri: params.video.uri,\n mimeType: params.video.mimeType,\n };\n } else if (\n params.source?.video?.uri &&\n params.source?.video?.videoBytes\n ) {\n params.source.video = {\n uri: params.source.video.uri,\n mimeType: params.source.video.mimeType,\n };\n }\n }\n return await this.generateVideosInternal(params);\n };\n\n private async generateContentInternal(\n params: types.GenerateContentParameters,\n ): Promise<types.GenerateContentResponse> {\n let response: Promise<types.GenerateContentResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.generateContentParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:generateContent',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.GenerateContentResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.GenerateContentResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.generateContentResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.GenerateContentResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n const body = converters.generateContentParametersToMldev(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:generateContent',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.GenerateContentResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.GenerateContentResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.generateContentResponseFromMldev(\n apiResponse,\n params,\n );\n const typedResp = new types.GenerateContentResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n private async generateContentStreamInternal(\n params: types.GenerateContentParameters,\n ): Promise<AsyncGenerator<types.GenerateContentResponse>> {\n let response: Promise<AsyncGenerator<types.HttpResponse>>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.generateContentParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:streamGenerateContent?alt=sse',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n const apiClient = this.apiClient;\n response = apiClient.requestStream({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n }) as Promise<AsyncGenerator<types.HttpResponse>>;\n\n return response.then(async function* (\n apiResponse: AsyncGenerator<types.HttpResponse>,\n ) {\n for await (const chunk of apiResponse) {\n const resp = converters.generateContentResponseFromVertex(\n (await chunk.json()) as types.GenerateContentResponse,\n params,\n );\n\n resp['sdkHttpResponse'] = {\n headers: chunk.headers,\n } as types.HttpResponse;\n\n const typedResp = new types.GenerateContentResponse();\n Object.assign(typedResp, resp);\n yield typedResp;\n }\n });\n } else {\n const body = converters.generateContentParametersToMldev(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:streamGenerateContent?alt=sse',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n const apiClient = this.apiClient;\n response = apiClient.requestStream({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n }) as Promise<AsyncGenerator<types.HttpResponse>>;\n\n return response.then(async function* (\n apiResponse: AsyncGenerator<types.HttpResponse>,\n ) {\n for await (const chunk of apiResponse) {\n const resp = converters.generateContentResponseFromMldev(\n (await chunk.json()) as types.GenerateContentResponse,\n params,\n );\n\n resp['sdkHttpResponse'] = {\n headers: chunk.headers,\n } as types.HttpResponse;\n\n const typedResp = new types.GenerateContentResponse();\n Object.assign(typedResp, resp);\n yield typedResp;\n }\n });\n }\n }\n\n /**\n * Calculates embeddings for the given contents. Only text is supported.\n *\n * @param params - The parameters for embedding contents.\n * @return The response from the API.\n *\n * @example\n * ```ts\n * const response = await ai.models.embedContent({\n * model: 'text-embedding-004',\n * contents: [\n * 'What is your name?',\n * 'What is your favorite color?',\n * ],\n * config: {\n * outputDimensionality: 64,\n * },\n * });\n * console.log(response);\n * ```\n */\n async embedContent(\n params: types.EmbedContentParameters,\n ): Promise<types.EmbedContentResponse> {\n let response: Promise<types.EmbedContentResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.embedContentParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:predict',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.EmbedContentResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.EmbedContentResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.embedContentResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.EmbedContentResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n const body = converters.embedContentParametersToMldev(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:batchEmbedContents',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.EmbedContentResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.EmbedContentResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.embedContentResponseFromMldev(\n apiResponse,\n params,\n );\n const typedResp = new types.EmbedContentResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n /**\n * Private method for generating images.\n */\n private async generateImagesInternal(\n params: types.GenerateImagesParameters,\n ): Promise<types.GenerateImagesResponse> {\n let response: Promise<types.GenerateImagesResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.generateImagesParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:predict',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.GenerateImagesResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.GenerateImagesResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.generateImagesResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.GenerateImagesResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n const body = converters.generateImagesParametersToMldev(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:predict',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.GenerateImagesResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.GenerateImagesResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.generateImagesResponseFromMldev(\n apiResponse,\n params,\n );\n const typedResp = new types.GenerateImagesResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n /**\n * Private method for editing an image.\n */\n private async editImageInternal(\n params: _internal_types.EditImageParametersInternal,\n ): Promise<types.EditImageResponse> {\n let response: Promise<types.EditImageResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.editImageParametersInternalToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:predict',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.EditImageResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.EditImageResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.editImageResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.EditImageResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n throw new Error('This method is only supported by the Vertex AI.');\n }\n }\n\n /**\n * Private method for upscaling an image.\n */\n private async upscaleImageInternal(\n params: _internal_types.UpscaleImageAPIParametersInternal,\n ): Promise<types.UpscaleImageResponse> {\n let response: Promise<types.UpscaleImageResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.upscaleImageAPIParametersInternalToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:predict',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.UpscaleImageResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.UpscaleImageResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.upscaleImageResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.UpscaleImageResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n throw new Error('This method is only supported by the Vertex AI.');\n }\n }\n\n /**\n * Recontextualizes an image.\n *\n * There are two types of recontextualization currently supported:\n * 1) Imagen Product Recontext - Generate images of products in new scenes\n * and contexts.\n * 2) Virtual Try-On: Generate images of persons modeling fashion products.\n *\n * @param params - The parameters for recontextualizing an image.\n * @return The response from the API.\n *\n * @example\n * ```ts\n * const response1 = await ai.models.recontextImage({\n * model: 'imagen-product-recontext-preview-06-30',\n * source: {\n * prompt: 'In a modern kitchen setting.',\n * productImages: [productImage],\n * },\n * config: {\n * numberOfImages: 1,\n * },\n * });\n * console.log(response1?.generatedImages?.[0]?.image?.imageBytes);\n *\n * const response2 = await ai.models.recontextImage({\n * model: 'virtual-try-on-001',\n * source: {\n * personImage: personImage,\n * productImages: [productImage],\n * },\n * config: {\n * numberOfImages: 1,\n * },\n * });\n * console.log(response2?.generatedImages?.[0]?.image?.imageBytes);\n * ```\n */\n async recontextImage(\n params: types.RecontextImageParameters,\n ): Promise<types.RecontextImageResponse> {\n let response: Promise<types.RecontextImageResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.recontextImageParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:predict',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.RecontextImageResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.recontextImageResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.RecontextImageResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n throw new Error('This method is only supported by the Vertex AI.');\n }\n }\n\n /**\n * Segments an image, creating a mask of a specified area.\n *\n * @param params - The parameters for segmenting an image.\n * @return The response from the API.\n *\n * @example\n * ```ts\n * const response = await ai.models.segmentImage({\n * model: 'image-segmentation-001',\n * source: {\n * image: image,\n * },\n * config: {\n * mode: 'foreground',\n * },\n * });\n * console.log(response?.generatedMasks?.[0]?.mask?.imageBytes);\n * ```\n */\n async segmentImage(\n params: types.SegmentImageParameters,\n ): Promise<types.SegmentImageResponse> {\n let response: Promise<types.SegmentImageResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.segmentImageParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:predict',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.SegmentImageResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.segmentImageResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.SegmentImageResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n throw new Error('This method is only supported by the Vertex AI.');\n }\n }\n\n /**\n * Fetches information about a model by name.\n *\n * @example\n * ```ts\n * const modelInfo = await ai.models.get({model: 'gemini-2.0-flash'});\n * ```\n */\n async get(params: types.GetModelParameters): Promise<types.Model> {\n let response: Promise<types.Model>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.getModelParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.Model>;\n\n return response.then((apiResponse) => {\n const resp = converters.modelFromVertex(apiResponse, params);\n\n return resp as types.Model;\n });\n } else {\n const body = converters.getModelParametersToMldev(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.Model>;\n\n return response.then((apiResponse) => {\n const resp = converters.modelFromMldev(apiResponse, params);\n\n return resp as types.Model;\n });\n }\n }\n\n private async listInternal(\n params: types.ListModelsParameters,\n ): Promise<types.ListModelsResponse> {\n let response: Promise<types.ListModelsResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.listModelsParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{models_url}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.ListModelsResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.ListModelsResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.listModelsResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.ListModelsResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n const body = converters.listModelsParametersToMldev(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{models_url}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.ListModelsResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.ListModelsResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.listModelsResponseFromMldev(\n apiResponse,\n params,\n );\n const typedResp = new types.ListModelsResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n /**\n * Updates a tuned model by its name.\n *\n * @param params - The parameters for updating the model.\n * @return The response from the API.\n *\n * @example\n * ```ts\n * const response = await ai.models.update({\n * model: 'tuned-model-name',\n * config: {\n * displayName: 'New display name',\n * description: 'New description',\n * },\n * });\n * ```\n */\n async update(params: types.UpdateModelParameters): Promise<types.Model> {\n let response: Promise<types.Model>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.updateModelParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'PATCH',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.Model>;\n\n return response.then((apiResponse) => {\n const resp = converters.modelFromVertex(apiResponse, params);\n\n return resp as types.Model;\n });\n } else {\n const body = converters.updateModelParametersToMldev(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'PATCH',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.Model>;\n\n return response.then((apiResponse) => {\n const resp = converters.modelFromMldev(apiResponse, params);\n\n return resp as types.Model;\n });\n }\n }\n\n /**\n * Deletes a tuned model by its name.\n *\n * @param params - The parameters for deleting the model.\n * @return The response from the API.\n *\n * @example\n * ```ts\n * const response = await ai.models.delete({model: 'tuned-model-name'});\n * ```\n */\n async delete(\n params: types.DeleteModelParameters,\n ): Promise<types.DeleteModelResponse> {\n let response: Promise<types.DeleteModelResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.deleteModelParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'DELETE',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.DeleteModelResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.DeleteModelResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.deleteModelResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.DeleteModelResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n const body = converters.deleteModelParametersToMldev(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'DELETE',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.DeleteModelResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.DeleteModelResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.deleteModelResponseFromMldev(\n apiResponse,\n params,\n );\n const typedResp = new types.DeleteModelResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n /**\n * Counts the number of tokens in the given contents. Multimodal input is\n * supported for Gemini models.\n *\n * @param params - The parameters for counting tokens.\n * @return The response from the API.\n *\n * @example\n * ```ts\n * const response = await ai.models.countTokens({\n * model: 'gemini-2.0-flash',\n * contents: 'The quick brown fox jumps over the lazy dog.'\n * });\n * console.log(response);\n * ```\n */\n async countTokens(\n params: types.CountTokensParameters,\n ): Promise<types.CountTokensResponse> {\n let response: Promise<types.CountTokensResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.countTokensParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:countTokens',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.CountTokensResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.CountTokensResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.countTokensResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.CountTokensResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n const body = converters.countTokensParametersToMldev(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:countTokens',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.CountTokensResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.CountTokensResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.countTokensResponseFromMldev(\n apiResponse,\n params,\n );\n const typedResp = new types.CountTokensResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n /**\n * Given a list of contents, returns a corresponding TokensInfo containing\n * the list of tokens and list of token ids.\n *\n * This method is not supported by the Gemini Developer API.\n *\n * @param params - The parameters for computing tokens.\n * @return The response from the API.\n *\n * @example\n * ```ts\n * const response = await ai.models.computeTokens({\n * model: 'gemini-2.0-flash',\n * contents: 'What is your name?'\n * });\n * console.log(response);\n * ```\n */\n async computeTokens(\n params: types.ComputeTokensParameters,\n ): Promise<types.ComputeTokensResponse> {\n let response: Promise<types.ComputeTokensResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.computeTokensParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:computeTokens',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.ComputeTokensResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.ComputeTokensResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.computeTokensResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.ComputeTokensResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n throw new Error('This method is only supported by the Vertex AI.');\n }\n }\n\n /**\n * Private method for generating videos.\n */\n private async generateVideosInternal(\n params: types.GenerateVideosParameters,\n ): Promise<types.GenerateVideosOperation> {\n let response: Promise<types.GenerateVideosOperation>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.generateVideosParametersToVertex(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:predictLongRunning',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.GenerateVideosOperation>;\n\n return response.then((apiResponse) => {\n const resp = converters.generateVideosOperationFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.GenerateVideosOperation();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n const body = converters.generateVideosParametersToMldev(\n this.apiClient,\n params,\n params,\n );\n path = common.formatMap(\n '{model}:predictLongRunning',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.GenerateVideosOperation>;\n\n return response.then((apiResponse) => {\n const resp = converters.generateVideosOperationFromMldev(\n apiResponse,\n params,\n );\n const typedResp = new types.GenerateVideosOperation();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport {ApiClient} from './_api_client.js';\nimport * as common from './_common.js';\nimport {BaseModule} from './_common.js';\nimport * as converters from './converters/_operations_converters.js';\nimport * as types from './types.js';\n\nexport class Operations extends BaseModule {\n constructor(private readonly apiClient: ApiClient) {\n super();\n }\n\n /**\n * Gets the status of a long-running operation.\n *\n * @param parameters The parameters for the get operation request.\n * @return The updated Operation object, with the latest status or result.\n */\n async getVideosOperation(\n parameters: types.OperationGetParameters<\n types.GenerateVideosResponse,\n types.GenerateVideosOperation\n >,\n ): Promise<types.GenerateVideosOperation> {\n const operation = parameters.operation;\n const config = parameters.config;\n\n if (operation.name === undefined || operation.name === '') {\n throw new Error('Operation name is required.');\n }\n\n if (this.apiClient.isVertexAI()) {\n const resourceName = operation.name.split('/operations/')[0];\n let httpOptions: types.HttpOptions | undefined = undefined;\n\n if (config && 'httpOptions' in config) {\n httpOptions = config.httpOptions;\n }\n\n const rawOperation = await this.fetchPredictVideosOperationInternal({\n operationName: operation.name,\n resourceName: resourceName,\n config: {httpOptions: httpOptions},\n });\n\n return operation._fromAPIResponse({\n apiResponse: rawOperation,\n _isVertexAI: true,\n });\n } else {\n const rawOperation = await this.getVideosOperationInternal({\n operationName: operation.name,\n config: config,\n });\n return operation._fromAPIResponse({\n apiResponse: rawOperation,\n _isVertexAI: false,\n });\n }\n }\n\n /**\n * Gets the status of a long-running operation.\n *\n * @param parameters The parameters for the get operation request.\n * @return The updated Operation object, with the latest status or result.\n */\n async get<T, U extends types.Operation<T>>(\n parameters: types.OperationGetParameters<T, U>,\n ): Promise<types.Operation<T>> {\n const operation = parameters.operation;\n const config = parameters.config;\n\n if (operation.name === undefined || operation.name === '') {\n throw new Error('Operation name is required.');\n }\n\n if (this.apiClient.isVertexAI()) {\n const resourceName = operation.name.split('/operations/')[0];\n let httpOptions: types.HttpOptions | undefined = undefined;\n\n if (config && 'httpOptions' in config) {\n httpOptions = config.httpOptions;\n }\n\n const rawOperation = await this.fetchPredictVideosOperationInternal({\n operationName: operation.name,\n resourceName: resourceName,\n config: {httpOptions: httpOptions},\n });\n\n return operation._fromAPIResponse({\n apiResponse: rawOperation,\n _isVertexAI: true,\n });\n } else {\n const rawOperation = await this.getVideosOperationInternal({\n operationName: operation.name,\n config: config,\n });\n return operation._fromAPIResponse({\n apiResponse: rawOperation,\n _isVertexAI: false,\n });\n }\n }\n\n private async getVideosOperationInternal(\n params: types.GetOperationParameters,\n ): Promise<Record<string, unknown>> {\n let response: Promise<Record<string, unknown>>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.getOperationParametersToVertex(params);\n path = common.formatMap(\n '{operationName}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<Record<string, unknown>>;\n\n return response;\n } else {\n const body = converters.getOperationParametersToMldev(params);\n path = common.formatMap(\n '{operationName}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<Record<string, unknown>>;\n\n return response;\n }\n }\n\n private async fetchPredictVideosOperationInternal(\n params: types.FetchPredictOperationParameters,\n ): Promise<Record<string, unknown>> {\n let response: Promise<Record<string, unknown>>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.fetchPredictOperationParametersToVertex(params);\n path = common.formatMap(\n '{resourceName}:fetchPredictOperation',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<Record<string, unknown>>;\n\n return response;\n } else {\n throw new Error('This method is only supported by the Vertex AI.');\n }\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport {ApiClient} from '../_api_client.js';\nimport * as common from '../_common.js';\nimport * as t from '../_transformers.js';\nimport type * as types from '../types.js';\n\nexport function blobToMldev(fromObject: types.Blob): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromData = common.getValueByPath(fromObject, ['data']);\n if (fromData != null) {\n common.setValueByPath(toObject, ['data'], fromData);\n }\n\n if (common.getValueByPath(fromObject, ['displayName']) !== undefined) {\n throw new Error('displayName parameter is not supported in Gemini API.');\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function contentToMldev(\n fromObject: types.Content,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromParts = common.getValueByPath(fromObject, ['parts']);\n if (fromParts != null) {\n let transformedList = fromParts;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return partToMldev(item);\n });\n }\n common.setValueByPath(toObject, ['parts'], transformedList);\n }\n\n const fromRole = common.getValueByPath(fromObject, ['role']);\n if (fromRole != null) {\n common.setValueByPath(toObject, ['role'], fromRole);\n }\n\n return toObject;\n}\n\nexport function createAuthTokenConfigToMldev(\n apiClient: ApiClient,\n fromObject: types.CreateAuthTokenConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromExpireTime = common.getValueByPath(fromObject, ['expireTime']);\n if (parentObject !== undefined && fromExpireTime != null) {\n common.setValueByPath(parentObject, ['expireTime'], fromExpireTime);\n }\n\n const fromNewSessionExpireTime = common.getValueByPath(fromObject, [\n 'newSessionExpireTime',\n ]);\n if (parentObject !== undefined && fromNewSessionExpireTime != null) {\n common.setValueByPath(\n parentObject,\n ['newSessionExpireTime'],\n fromNewSessionExpireTime,\n );\n }\n\n const fromUses = common.getValueByPath(fromObject, ['uses']);\n if (parentObject !== undefined && fromUses != null) {\n common.setValueByPath(parentObject, ['uses'], fromUses);\n }\n\n const fromLiveConnectConstraints = common.getValueByPath(fromObject, [\n 'liveConnectConstraints',\n ]);\n if (parentObject !== undefined && fromLiveConnectConstraints != null) {\n common.setValueByPath(\n parentObject,\n ['bidiGenerateContentSetup'],\n liveConnectConstraintsToMldev(apiClient, fromLiveConnectConstraints),\n );\n }\n\n const fromLockAdditionalFields = common.getValueByPath(fromObject, [\n 'lockAdditionalFields',\n ]);\n if (parentObject !== undefined && fromLockAdditionalFields != null) {\n common.setValueByPath(\n parentObject,\n ['fieldMask'],\n fromLockAdditionalFields,\n );\n }\n\n return toObject;\n}\n\nexport function createAuthTokenParametersToMldev(\n apiClient: ApiClient,\n fromObject: types.CreateAuthTokenParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n common.setValueByPath(\n toObject,\n ['config'],\n createAuthTokenConfigToMldev(apiClient, fromConfig, toObject),\n );\n }\n\n return toObject;\n}\n\nexport function createAuthTokenParametersToVertex(\n fromObject: types.CreateAuthTokenParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['config']) !== undefined) {\n throw new Error('config parameter is not supported in Vertex AI.');\n }\n\n return toObject;\n}\n\nexport function fileDataToMldev(\n fromObject: types.FileData,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['displayName']) !== undefined) {\n throw new Error('displayName parameter is not supported in Gemini API.');\n }\n\n const fromFileUri = common.getValueByPath(fromObject, ['fileUri']);\n if (fromFileUri != null) {\n common.setValueByPath(toObject, ['fileUri'], fromFileUri);\n }\n\n const fromMimeType = common.getValueByPath(fromObject, ['mimeType']);\n if (fromMimeType != null) {\n common.setValueByPath(toObject, ['mimeType'], fromMimeType);\n }\n\n return toObject;\n}\n\nexport function functionCallToMldev(\n fromObject: types.FunctionCall,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromId = common.getValueByPath(fromObject, ['id']);\n if (fromId != null) {\n common.setValueByPath(toObject, ['id'], fromId);\n }\n\n const fromArgs = common.getValueByPath(fromObject, ['args']);\n if (fromArgs != null) {\n common.setValueByPath(toObject, ['args'], fromArgs);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n if (common.getValueByPath(fromObject, ['partialArgs']) !== undefined) {\n throw new Error('partialArgs parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['willContinue']) !== undefined) {\n throw new Error('willContinue parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function googleMapsToMldev(\n fromObject: types.GoogleMaps,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['authConfig']) !== undefined) {\n throw new Error('authConfig parameter is not supported in Gemini API.');\n }\n\n const fromEnableWidget = common.getValueByPath(fromObject, ['enableWidget']);\n if (fromEnableWidget != null) {\n common.setValueByPath(toObject, ['enableWidget'], fromEnableWidget);\n }\n\n return toObject;\n}\n\nexport function googleSearchToMldev(\n fromObject: types.GoogleSearch,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['excludeDomains']) !== undefined) {\n throw new Error('excludeDomains parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['blockingConfidence']) !== undefined) {\n throw new Error(\n 'blockingConfidence parameter is not supported in Gemini API.',\n );\n }\n\n const fromTimeRangeFilter = common.getValueByPath(fromObject, [\n 'timeRangeFilter',\n ]);\n if (fromTimeRangeFilter != null) {\n common.setValueByPath(toObject, ['timeRangeFilter'], fromTimeRangeFilter);\n }\n\n return toObject;\n}\n\nexport function liveConnectConfigToMldev(\n fromObject: types.LiveConnectConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromGenerationConfig = common.getValueByPath(fromObject, [\n 'generationConfig',\n ]);\n if (parentObject !== undefined && fromGenerationConfig != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig'],\n fromGenerationConfig,\n );\n }\n\n const fromResponseModalities = common.getValueByPath(fromObject, [\n 'responseModalities',\n ]);\n if (parentObject !== undefined && fromResponseModalities != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'responseModalities'],\n fromResponseModalities,\n );\n }\n\n const fromTemperature = common.getValueByPath(fromObject, ['temperature']);\n if (parentObject !== undefined && fromTemperature != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'temperature'],\n fromTemperature,\n );\n }\n\n const fromTopP = common.getValueByPath(fromObject, ['topP']);\n if (parentObject !== undefined && fromTopP != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'topP'],\n fromTopP,\n );\n }\n\n const fromTopK = common.getValueByPath(fromObject, ['topK']);\n if (parentObject !== undefined && fromTopK != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'topK'],\n fromTopK,\n );\n }\n\n const fromMaxOutputTokens = common.getValueByPath(fromObject, [\n 'maxOutputTokens',\n ]);\n if (parentObject !== undefined && fromMaxOutputTokens != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'maxOutputTokens'],\n fromMaxOutputTokens,\n );\n }\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (parentObject !== undefined && fromMediaResolution != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'mediaResolution'],\n fromMediaResolution,\n );\n }\n\n const fromSeed = common.getValueByPath(fromObject, ['seed']);\n if (parentObject !== undefined && fromSeed != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'seed'],\n fromSeed,\n );\n }\n\n const fromSpeechConfig = common.getValueByPath(fromObject, ['speechConfig']);\n if (parentObject !== undefined && fromSpeechConfig != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'speechConfig'],\n t.tLiveSpeechConfig(fromSpeechConfig),\n );\n }\n\n const fromThinkingConfig = common.getValueByPath(fromObject, [\n 'thinkingConfig',\n ]);\n if (parentObject !== undefined && fromThinkingConfig != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'thinkingConfig'],\n fromThinkingConfig,\n );\n }\n\n const fromEnableAffectiveDialog = common.getValueByPath(fromObject, [\n 'enableAffectiveDialog',\n ]);\n if (parentObject !== undefined && fromEnableAffectiveDialog != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'generationConfig', 'enableAffectiveDialog'],\n fromEnableAffectiveDialog,\n );\n }\n\n const fromSystemInstruction = common.getValueByPath(fromObject, [\n 'systemInstruction',\n ]);\n if (parentObject !== undefined && fromSystemInstruction != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'systemInstruction'],\n contentToMldev(t.tContent(fromSystemInstruction)),\n );\n }\n\n const fromTools = common.getValueByPath(fromObject, ['tools']);\n if (parentObject !== undefined && fromTools != null) {\n let transformedList = t.tTools(fromTools);\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return toolToMldev(t.tTool(item));\n });\n }\n common.setValueByPath(parentObject, ['setup', 'tools'], transformedList);\n }\n\n const fromSessionResumption = common.getValueByPath(fromObject, [\n 'sessionResumption',\n ]);\n if (parentObject !== undefined && fromSessionResumption != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'sessionResumption'],\n sessionResumptionConfigToMldev(fromSessionResumption),\n );\n }\n\n const fromInputAudioTranscription = common.getValueByPath(fromObject, [\n 'inputAudioTranscription',\n ]);\n if (parentObject !== undefined && fromInputAudioTranscription != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'inputAudioTranscription'],\n fromInputAudioTranscription,\n );\n }\n\n const fromOutputAudioTranscription = common.getValueByPath(fromObject, [\n 'outputAudioTranscription',\n ]);\n if (parentObject !== undefined && fromOutputAudioTranscription != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'outputAudioTranscription'],\n fromOutputAudioTranscription,\n );\n }\n\n const fromRealtimeInputConfig = common.getValueByPath(fromObject, [\n 'realtimeInputConfig',\n ]);\n if (parentObject !== undefined && fromRealtimeInputConfig != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'realtimeInputConfig'],\n fromRealtimeInputConfig,\n );\n }\n\n const fromContextWindowCompression = common.getValueByPath(fromObject, [\n 'contextWindowCompression',\n ]);\n if (parentObject !== undefined && fromContextWindowCompression != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'contextWindowCompression'],\n fromContextWindowCompression,\n );\n }\n\n const fromProactivity = common.getValueByPath(fromObject, ['proactivity']);\n if (parentObject !== undefined && fromProactivity != null) {\n common.setValueByPath(\n parentObject,\n ['setup', 'proactivity'],\n fromProactivity,\n );\n }\n\n if (common.getValueByPath(fromObject, ['explicitVadSignal']) !== undefined) {\n throw new Error(\n 'explicitVadSignal parameter is not supported in Gemini API.',\n );\n }\n\n return toObject;\n}\n\nexport function liveConnectConstraintsToMldev(\n apiClient: ApiClient,\n fromObject: types.LiveConnectConstraints,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['model']);\n if (fromModel != null) {\n common.setValueByPath(\n toObject,\n ['setup', 'model'],\n t.tModel(apiClient, fromModel),\n );\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n common.setValueByPath(\n toObject,\n ['config'],\n liveConnectConfigToMldev(fromConfig, toObject),\n );\n }\n\n return toObject;\n}\n\nexport function partToMldev(fromObject: types.Part): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromMediaResolution = common.getValueByPath(fromObject, [\n 'mediaResolution',\n ]);\n if (fromMediaResolution != null) {\n common.setValueByPath(toObject, ['mediaResolution'], fromMediaResolution);\n }\n\n const fromCodeExecutionResult = common.getValueByPath(fromObject, [\n 'codeExecutionResult',\n ]);\n if (fromCodeExecutionResult != null) {\n common.setValueByPath(\n toObject,\n ['codeExecutionResult'],\n fromCodeExecutionResult,\n );\n }\n\n const fromExecutableCode = common.getValueByPath(fromObject, [\n 'executableCode',\n ]);\n if (fromExecutableCode != null) {\n common.setValueByPath(toObject, ['executableCode'], fromExecutableCode);\n }\n\n const fromFileData = common.getValueByPath(fromObject, ['fileData']);\n if (fromFileData != null) {\n common.setValueByPath(\n toObject,\n ['fileData'],\n fileDataToMldev(fromFileData),\n );\n }\n\n const fromFunctionCall = common.getValueByPath(fromObject, ['functionCall']);\n if (fromFunctionCall != null) {\n common.setValueByPath(\n toObject,\n ['functionCall'],\n functionCallToMldev(fromFunctionCall),\n );\n }\n\n const fromFunctionResponse = common.getValueByPath(fromObject, [\n 'functionResponse',\n ]);\n if (fromFunctionResponse != null) {\n common.setValueByPath(toObject, ['functionResponse'], fromFunctionResponse);\n }\n\n const fromInlineData = common.getValueByPath(fromObject, ['inlineData']);\n if (fromInlineData != null) {\n common.setValueByPath(\n toObject,\n ['inlineData'],\n blobToMldev(fromInlineData),\n );\n }\n\n const fromText = common.getValueByPath(fromObject, ['text']);\n if (fromText != null) {\n common.setValueByPath(toObject, ['text'], fromText);\n }\n\n const fromThought = common.getValueByPath(fromObject, ['thought']);\n if (fromThought != null) {\n common.setValueByPath(toObject, ['thought'], fromThought);\n }\n\n const fromThoughtSignature = common.getValueByPath(fromObject, [\n 'thoughtSignature',\n ]);\n if (fromThoughtSignature != null) {\n common.setValueByPath(toObject, ['thoughtSignature'], fromThoughtSignature);\n }\n\n const fromVideoMetadata = common.getValueByPath(fromObject, [\n 'videoMetadata',\n ]);\n if (fromVideoMetadata != null) {\n common.setValueByPath(toObject, ['videoMetadata'], fromVideoMetadata);\n }\n\n return toObject;\n}\n\nexport function sessionResumptionConfigToMldev(\n fromObject: types.SessionResumptionConfig,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromHandle = common.getValueByPath(fromObject, ['handle']);\n if (fromHandle != null) {\n common.setValueByPath(toObject, ['handle'], fromHandle);\n }\n\n if (common.getValueByPath(fromObject, ['transparent']) !== undefined) {\n throw new Error('transparent parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function toolToMldev(fromObject: types.Tool): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['retrieval']) !== undefined) {\n throw new Error('retrieval parameter is not supported in Gemini API.');\n }\n\n const fromComputerUse = common.getValueByPath(fromObject, ['computerUse']);\n if (fromComputerUse != null) {\n common.setValueByPath(toObject, ['computerUse'], fromComputerUse);\n }\n\n const fromFileSearch = common.getValueByPath(fromObject, ['fileSearch']);\n if (fromFileSearch != null) {\n common.setValueByPath(toObject, ['fileSearch'], fromFileSearch);\n }\n\n const fromCodeExecution = common.getValueByPath(fromObject, [\n 'codeExecution',\n ]);\n if (fromCodeExecution != null) {\n common.setValueByPath(toObject, ['codeExecution'], fromCodeExecution);\n }\n\n if (\n common.getValueByPath(fromObject, ['enterpriseWebSearch']) !== undefined\n ) {\n throw new Error(\n 'enterpriseWebSearch parameter is not supported in Gemini API.',\n );\n }\n\n const fromFunctionDeclarations = common.getValueByPath(fromObject, [\n 'functionDeclarations',\n ]);\n if (fromFunctionDeclarations != null) {\n let transformedList = fromFunctionDeclarations;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['functionDeclarations'], transformedList);\n }\n\n const fromGoogleMaps = common.getValueByPath(fromObject, ['googleMaps']);\n if (fromGoogleMaps != null) {\n common.setValueByPath(\n toObject,\n ['googleMaps'],\n googleMapsToMldev(fromGoogleMaps),\n );\n }\n\n const fromGoogleSearch = common.getValueByPath(fromObject, ['googleSearch']);\n if (fromGoogleSearch != null) {\n common.setValueByPath(\n toObject,\n ['googleSearch'],\n googleSearchToMldev(fromGoogleSearch),\n );\n }\n\n const fromGoogleSearchRetrieval = common.getValueByPath(fromObject, [\n 'googleSearchRetrieval',\n ]);\n if (fromGoogleSearchRetrieval != null) {\n common.setValueByPath(\n toObject,\n ['googleSearchRetrieval'],\n fromGoogleSearchRetrieval,\n );\n }\n\n const fromUrlContext = common.getValueByPath(fromObject, ['urlContext']);\n if (fromUrlContext != null) {\n common.setValueByPath(toObject, ['urlContext'], fromUrlContext);\n }\n\n return toObject;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {ApiClient} from './_api_client.js';\nimport * as common from './_common.js';\nimport {BaseModule} from './_common.js';\nimport * as converters from './converters/_tokens_converters.js';\nimport * as types from './types.js';\n\n/**\n * Returns a comma-separated list of field masks from a given object.\n *\n * @param setup The object to extract field masks from.\n * @return A comma-separated list of field masks.\n */\nfunction getFieldMasks(setup: Record<string, unknown>): string {\n const fields: string[] = [];\n\n for (const key in setup) {\n if (Object.prototype.hasOwnProperty.call(setup, key)) {\n const value = setup[key];\n // 2nd layer, recursively get field masks see TODO(b/418290100)\n if (\n typeof value === 'object' &&\n value != null &&\n Object.keys(value).length > 0\n ) {\n const field = Object.keys(value).map((kk) => `${key}.${kk}`);\n fields.push(...field);\n } else {\n fields.push(key); // 1st layer\n }\n }\n }\n\n return fields.join(',');\n}\n\n/**\n * Converts bidiGenerateContentSetup.\n * @param requestDict - The request dictionary.\n * @param config - The configuration object.\n * @return - The modified request dictionary.\n */\nfunction convertBidiSetupToTokenSetup(\n requestDict: Record<string, unknown>,\n config?: {lockAdditionalFields?: string[]},\n): Record<string, unknown> {\n // Convert bidiGenerateContentSetup from bidiGenerateContentSetup.setup.\n let setupForMaskGeneration: Record<string, unknown> | null = null;\n const bidiGenerateContentSetupValue = requestDict['bidiGenerateContentSetup'];\n if (\n typeof bidiGenerateContentSetupValue === 'object' &&\n bidiGenerateContentSetupValue !== null &&\n 'setup' in bidiGenerateContentSetupValue\n ) {\n // Now we know bidiGenerateContentSetupValue is an object and has a 'setup'\n // property.\n const innerSetup = (bidiGenerateContentSetupValue as {setup: unknown})\n .setup;\n\n if (typeof innerSetup === 'object' && innerSetup !== null) {\n // Valid inner setup found.\n requestDict['bidiGenerateContentSetup'] = innerSetup;\n setupForMaskGeneration = innerSetup as Record<string, unknown>;\n } else {\n // `bidiGenerateContentSetupValue.setup` is not a valid object; treat as\n // if bidiGenerateContentSetup is invalid.\n delete requestDict['bidiGenerateContentSetup'];\n }\n } else if (bidiGenerateContentSetupValue !== undefined) {\n // `bidiGenerateContentSetup` exists but not in the expected\n // shape {setup: {...}}; treat as invalid.\n delete requestDict['bidiGenerateContentSetup'];\n }\n\n const preExistingFieldMask = requestDict['fieldMask'];\n // Handle mask generation setup.\n if (setupForMaskGeneration) {\n const generatedMaskFromBidi = getFieldMasks(setupForMaskGeneration);\n\n if (\n Array.isArray(config?.lockAdditionalFields) &&\n config?.lockAdditionalFields.length === 0\n ) {\n // Case 1: lockAdditionalFields is an empty array. Lock only fields from\n // bidi setup.\n if (generatedMaskFromBidi) {\n // Only assign if mask is not empty\n requestDict['fieldMask'] = generatedMaskFromBidi;\n } else {\n delete requestDict['fieldMask']; // If mask is empty, effectively no\n // specific fields locked by bidi\n }\n } else if (\n config?.lockAdditionalFields &&\n config.lockAdditionalFields.length > 0 &&\n preExistingFieldMask !== null &&\n Array.isArray(preExistingFieldMask) &&\n preExistingFieldMask.length > 0\n ) {\n // Case 2: Lock fields from bidi setup + additional fields\n // (preExistingFieldMask).\n\n const generationConfigFields = [\n 'temperature',\n 'topK',\n 'topP',\n 'maxOutputTokens',\n 'responseModalities',\n 'seed',\n 'speechConfig',\n ];\n\n let mappedFieldsFromPreExisting: string[] = [];\n if (preExistingFieldMask.length > 0) {\n mappedFieldsFromPreExisting = preExistingFieldMask.map((field) => {\n if (generationConfigFields.includes(field)) {\n return `generationConfig.${field}`;\n }\n return field; // Keep original field name if not in\n // generationConfigFields\n });\n }\n\n const finalMaskParts: string[] = [];\n if (generatedMaskFromBidi) {\n finalMaskParts.push(generatedMaskFromBidi);\n }\n if (mappedFieldsFromPreExisting.length > 0) {\n finalMaskParts.push(...mappedFieldsFromPreExisting);\n }\n\n if (finalMaskParts.length > 0) {\n requestDict['fieldMask'] = finalMaskParts.join(',');\n } else {\n // If no fields from bidi and no valid additional fields from\n // pre-existing mask.\n delete requestDict['fieldMask'];\n }\n } else {\n // Case 3: \"Lock all fields\" (meaning, don't send a field_mask, let server\n // defaults apply or all are mutable). This is hit if:\n // - `config.lockAdditionalFields` is undefined.\n // - `config.lockAdditionalFields` is non-empty, BUT\n // `preExistingFieldMask` is null, not a string, or an empty string.\n delete requestDict['fieldMask'];\n }\n } else {\n // No valid `bidiGenerateContentSetup` was found or extracted.\n // \"Lock additional null fields if any\".\n if (\n preExistingFieldMask !== null &&\n Array.isArray(preExistingFieldMask) &&\n preExistingFieldMask.length > 0\n ) {\n // If there's a pre-existing field mask, it's a string, and it's not\n // empty, then we should lock all fields.\n requestDict['fieldMask'] = preExistingFieldMask.join(',');\n } else {\n delete requestDict['fieldMask'];\n }\n }\n\n return requestDict;\n}\n\nexport class Tokens extends BaseModule {\n constructor(private readonly apiClient: ApiClient) {\n super();\n }\n /**\n * Creates an ephemeral auth token resource.\n *\n * @experimental\n *\n * @remarks\n * Ephemeral auth tokens is only supported in the Gemini Developer API.\n * It can be used for the session connection to the Live constrained API.\n * Support in v1alpha only.\n *\n * @param params - The parameters for the create request.\n * @return The created auth token.\n *\n * @example\n * ```ts\n * const ai = new GoogleGenAI({\n * apiKey: token.name,\n * httpOptions: { apiVersion: 'v1alpha' } // Support in v1alpha only.\n * });\n *\n * // Case 1: If LiveEphemeralParameters is unset, unlock LiveConnectConfig\n * // when using the token in Live API sessions. Each session connection can\n * // use a different configuration.\n * const config: CreateAuthTokenConfig = {\n * uses: 3,\n * expireTime: '2025-05-01T00:00:00Z',\n * }\n * const token = await ai.tokens.create(config);\n *\n * // Case 2: If LiveEphemeralParameters is set, lock all fields in\n * // LiveConnectConfig when using the token in Live API sessions. For\n * // example, changing `outputAudioTranscription` in the Live API\n * // connection will be ignored by the API.\n * const config: CreateAuthTokenConfig =\n * uses: 3,\n * expireTime: '2025-05-01T00:00:00Z',\n * LiveEphemeralParameters: {\n * model: 'gemini-2.0-flash-001',\n * config: {\n * 'responseModalities': ['AUDIO'],\n * 'systemInstruction': 'Always answer in English.',\n * }\n * }\n * }\n * const token = await ai.tokens.create(config);\n *\n * // Case 3: If LiveEphemeralParameters is set and lockAdditionalFields is\n * // set, lock LiveConnectConfig with set and additional fields (e.g.\n * // responseModalities, systemInstruction, temperature in this example) when\n * // using the token in Live API sessions.\n * const config: CreateAuthTokenConfig =\n * uses: 3,\n * expireTime: '2025-05-01T00:00:00Z',\n * LiveEphemeralParameters: {\n * model: 'gemini-2.0-flash-001',\n * config: {\n * 'responseModalities': ['AUDIO'],\n * 'systemInstruction': 'Always answer in English.',\n * }\n * },\n * lockAdditionalFields: ['temperature'],\n * }\n * const token = await ai.tokens.create(config);\n *\n * // Case 4: If LiveEphemeralParameters is set and lockAdditionalFields is\n * // empty array, lock LiveConnectConfig with set fields (e.g.\n * // responseModalities, systemInstruction in this example) when using the\n * // token in Live API sessions.\n * const config: CreateAuthTokenConfig =\n * uses: 3,\n * expireTime: '2025-05-01T00:00:00Z',\n * LiveEphemeralParameters: {\n * model: 'gemini-2.0-flash-001',\n * config: {\n * 'responseModalities': ['AUDIO'],\n * 'systemInstruction': 'Always answer in English.',\n * }\n * },\n * lockAdditionalFields: [],\n * }\n * const token = await ai.tokens.create(config);\n * ```\n */\n\n async create(\n params: types.CreateAuthTokenParameters,\n ): Promise<types.AuthToken> {\n let response: Promise<types.AuthToken>;\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'The client.tokens.create method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.createAuthTokenParametersToMldev(\n this.apiClient,\n params,\n );\n path = common.formatMap(\n 'auth_tokens',\n body['_url'] as Record<string, unknown>,\n );\n\n queryParams = body['_query'] as Record<string, string>;\n delete body['config'];\n delete body['_url'];\n delete body['_query'];\n\n const transformedBody = convertBidiSetupToTokenSetup(body, params.config);\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(transformedBody),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.AuthToken>;\n\n return response.then((resp) => {\n return resp as types.AuthToken;\n });\n }\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport * as common from '../_common.js';\nimport type * as types from '../types.js';\n\nexport function deleteDocumentConfigToMldev(\n fromObject: types.DeleteDocumentConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromForce = common.getValueByPath(fromObject, ['force']);\n if (parentObject !== undefined && fromForce != null) {\n common.setValueByPath(parentObject, ['_query', 'force'], fromForce);\n }\n\n return toObject;\n}\n\nexport function deleteDocumentParametersToMldev(\n fromObject: types.DeleteDocumentParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['_url', 'name'], fromName);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n deleteDocumentConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function getDocumentParametersToMldev(\n fromObject: types.GetDocumentParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['_url', 'name'], fromName);\n }\n\n return toObject;\n}\n\nexport function listDocumentsConfigToMldev(\n fromObject: types.ListDocumentsConfig,\n parentObject: Record<string, unknown>,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPageSize = common.getValueByPath(fromObject, ['pageSize']);\n if (parentObject !== undefined && fromPageSize != null) {\n common.setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize);\n }\n\n const fromPageToken = common.getValueByPath(fromObject, ['pageToken']);\n if (parentObject !== undefined && fromPageToken != null) {\n common.setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken);\n }\n\n return toObject;\n}\n\nexport function listDocumentsParametersToMldev(\n fromObject: types.ListDocumentsParameters,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromParent = common.getValueByPath(fromObject, ['parent']);\n if (fromParent != null) {\n common.setValueByPath(toObject, ['_url', 'parent'], fromParent);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n listDocumentsConfigToMldev(fromConfig, toObject);\n }\n\n return toObject;\n}\n\nexport function listDocumentsResponseFromMldev(\n fromObject: types.ListDocumentsResponse,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromNextPageToken = common.getValueByPath(fromObject, [\n 'nextPageToken',\n ]);\n if (fromNextPageToken != null) {\n common.setValueByPath(toObject, ['nextPageToken'], fromNextPageToken);\n }\n\n const fromDocuments = common.getValueByPath(fromObject, ['documents']);\n if (fromDocuments != null) {\n let transformedList = fromDocuments;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['documents'], transformedList);\n }\n\n return toObject;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport {ApiClient} from './_api_client.js';\nimport * as common from './_common.js';\nimport {BaseModule} from './_common.js';\nimport * as converters from './converters/_documents_converters.js';\nimport {PagedItem, PagedItemConfig, Pager} from './pagers.js';\nimport * as types from './types.js';\n\nexport class Documents extends BaseModule {\n constructor(private readonly apiClient: ApiClient) {\n super();\n }\n\n /**\n * Lists documents.\n *\n * @param params - The parameters for the list request.\n * @return - A pager of documents.\n *\n * @example\n * ```ts\n * const documents = await ai.documents.list({parent:'rag_store_name', config: {'pageSize': 2}});\n * for await (const document of documents) {\n * console.log(document);\n * }\n * ```\n */\n\n list = async (\n params: types.ListDocumentsParameters,\n ): Promise<Pager<types.Document>> => {\n return new Pager<types.Document>(\n PagedItem.PAGED_ITEM_DOCUMENTS,\n (x: PagedItemConfig) =>\n this.listInternal({parent: params.parent, config: x.config}),\n await this.listInternal(params),\n params,\n );\n };\n\n /**\n * Gets a Document.\n *\n * @param params - The parameters for getting a document.\n * @return Document.\n */\n\n async get(params: types.GetDocumentParameters): Promise<types.Document> {\n let response: Promise<types.Document>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.getDocumentParametersToMldev(params);\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.Document>;\n\n return response.then((resp) => {\n return resp as types.Document;\n });\n }\n }\n\n /**\n * Deletes a Document.\n *\n * @param params - The parameters for deleting a document.\n */\n\n async delete(params: types.DeleteDocumentParameters): Promise<void> {\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.deleteDocumentParametersToMldev(params);\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n await this.apiClient.request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'DELETE',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n });\n }\n }\n\n private async listInternal(\n params: types.ListDocumentsParameters,\n ): Promise<types.ListDocumentsResponse> {\n let response: Promise<types.ListDocumentsResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.listDocumentsParametersToMldev(params);\n path = common.formatMap(\n '{parent}/documents',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.ListDocumentsResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.listDocumentsResponseFromMldev(apiResponse);\n const typedResp = new types.ListDocumentsResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport {ApiClient} from './_api_client.js';\nimport * as common from './_common.js';\nimport {BaseModule} from './_common.js';\nimport * as converters from './converters/_filesearchstores_converters.js';\nimport {Documents} from './documents.js';\nimport {PagedItem, Pager} from './pagers.js';\nimport * as types from './types.js';\n\nexport class FileSearchStores extends BaseModule {\n constructor(\n private readonly apiClient: ApiClient,\n public readonly documents: Documents = new Documents(apiClient),\n ) {\n super();\n }\n\n /**\n * Lists file search stores.\n *\n * @param params - The parameters for the list request.\n * @return - A pager of file search stores.\n *\n * @example\n * ```ts\n * const fileSearchStores = await ai.fileSearchStores.list({config: {'pageSize': 2}});\n * for await (const fileSearchStore of fileSearchStores) {\n * console.log(fileSearchStore);\n * }\n * ```\n */\n\n list = async (\n params: types.ListFileSearchStoresParameters = {},\n ): Promise<Pager<types.FileSearchStore>> => {\n return new Pager<types.FileSearchStore>(\n PagedItem.PAGED_ITEM_FILE_SEARCH_STORES,\n (x: types.ListFileSearchStoresParameters) => this.listInternal(x),\n await this.listInternal(params),\n params,\n );\n };\n\n /**\n * Uploads a file asynchronously to a given File Search Store.\n * This method is not available in Vertex AI.\n * Supported upload sources:\n * - Node.js: File path (string) or Blob object.\n * - Browser: Blob object (e.g., File).\n *\n * @remarks\n * The `mimeType` can be specified in the `config` parameter. If omitted:\n * - For file path (string) inputs, the `mimeType` will be inferred from the\n * file extension.\n * - For Blob object inputs, the `mimeType` will be set to the Blob's `type`\n * property.\n *\n * This section can contain multiple paragraphs and code examples.\n *\n * @param params - Optional parameters specified in the\n * `types.UploadToFileSearchStoreParameters` interface.\n * @see {@link types.UploadToFileSearchStoreParameters#config} for the optional\n * config in the parameters.\n * @return A promise that resolves to a long running operation.\n * @throws An error if called on a Vertex AI client.\n * @throws An error if the `mimeType` is not provided and can not be inferred,\n * the `mimeType` can be provided in the `params.config` parameter.\n * @throws An error occurs if a suitable upload location cannot be established.\n *\n * @example\n * The following code uploads a file to a given file search store.\n *\n * ```ts\n * const operation = await ai.fileSearchStores.upload({fileSearchStoreName: 'fileSearchStores/foo-bar', file: 'file.txt', config: {\n * mimeType: 'text/plain',\n * }});\n * console.log(operation.name);\n * ```\n */\n async uploadToFileSearchStore(\n params: types.UploadToFileSearchStoreParameters,\n ): Promise<types.UploadToFileSearchStoreOperation> {\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'Vertex AI does not support uploading files to a file search store.',\n );\n }\n\n return this.apiClient.uploadFileToFileSearchStore(\n params.fileSearchStoreName,\n params.file,\n params.config,\n );\n }\n\n /**\n * Creates a File Search Store.\n *\n * @param params - The parameters for creating a File Search Store.\n * @return FileSearchStore.\n */\n\n async create(\n params: types.CreateFileSearchStoreParameters,\n ): Promise<types.FileSearchStore> {\n let response: Promise<types.FileSearchStore>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.createFileSearchStoreParametersToMldev(params);\n path = common.formatMap(\n 'fileSearchStores',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.FileSearchStore>;\n\n return response.then((resp) => {\n return resp as types.FileSearchStore;\n });\n }\n }\n\n /**\n * Gets a File Search Store.\n *\n * @param params - The parameters for getting a File Search Store.\n * @return FileSearchStore.\n */\n\n async get(\n params: types.GetFileSearchStoreParameters,\n ): Promise<types.FileSearchStore> {\n let response: Promise<types.FileSearchStore>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.getFileSearchStoreParametersToMldev(params);\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.FileSearchStore>;\n\n return response.then((resp) => {\n return resp as types.FileSearchStore;\n });\n }\n }\n\n /**\n * Deletes a File Search Store.\n *\n * @param params - The parameters for deleting a File Search Store.\n */\n\n async delete(params: types.DeleteFileSearchStoreParameters): Promise<void> {\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.deleteFileSearchStoreParametersToMldev(params);\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n await this.apiClient.request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'DELETE',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n });\n }\n }\n\n private async listInternal(\n params: types.ListFileSearchStoresParameters,\n ): Promise<types.ListFileSearchStoresResponse> {\n let response: Promise<types.ListFileSearchStoresResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.listFileSearchStoresParametersToMldev(params);\n path = common.formatMap(\n 'fileSearchStores',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.ListFileSearchStoresResponse>;\n\n return response.then((apiResponse) => {\n const resp =\n converters.listFileSearchStoresResponseFromMldev(apiResponse);\n const typedResp = new types.ListFileSearchStoresResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n private async uploadToFileSearchStoreInternal(\n params: types.UploadToFileSearchStoreParameters,\n ): Promise<types.UploadToFileSearchStoreResumableResponse> {\n let response: Promise<types.UploadToFileSearchStoreResumableResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.uploadToFileSearchStoreParametersToMldev(params);\n path = common.formatMap(\n 'upload/v1beta/{file_search_store_name}:uploadToFileSearchStore',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.UploadToFileSearchStoreResumableResponse>;\n\n return response.then((apiResponse) => {\n const resp =\n converters.uploadToFileSearchStoreResumableResponseFromMldev(\n apiResponse,\n );\n const typedResp = new types.UploadToFileSearchStoreResumableResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n /**\n * Imports a File from File Service to a FileSearchStore.\n *\n * This is a long-running operation, see aip.dev/151\n *\n * @param params - The parameters for importing a file to a file search store.\n * @return ImportFileOperation.\n */\n\n async importFile(\n params: types.ImportFileParameters,\n ): Promise<types.ImportFileOperation> {\n let response: Promise<types.ImportFileOperation>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.importFileParametersToMldev(params);\n path = common.formatMap(\n '{file_search_store_name}:importFile',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json();\n }) as Promise<types.ImportFileOperation>;\n\n return response.then((apiResponse) => {\n const resp = converters.importFileOperationFromMldev(apiResponse);\n const typedResp = new types.ImportFileOperation();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\n/**\n * https://stackoverflow.com/a/2117523\n */\nlet uuid4Internal = function (): string {\n const { crypto } = globalThis as any;\n if (crypto?.randomUUID) {\n uuid4Internal = crypto.randomUUID.bind(crypto);\n return crypto.randomUUID();\n }\n const u8 = new Uint8Array(1);\n const randomByte = crypto ? () => crypto.getRandomValues(u8)[0]! : () => (Math.random() * 0xff) & 0xff;\n return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, (c) =>\n (+c ^ (randomByte() & (15 >> (+c / 4)))).toString(16),\n );\n};\n\nexport const uuid4 = (): string => uuid4Internal();\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nexport function isAbortError(err: unknown) {\n return (\n typeof err === 'object' &&\n err !== null &&\n // Spec-compliant fetch implementations\n (('name' in err && (err as any).name === 'AbortError') ||\n // Expo fetch\n ('message' in err && String((err as any).message).includes('FetchRequestCanceledException')))\n );\n}\n\nexport const castToError = (err: any): Error => {\n if (err instanceof Error) return err;\n if (typeof err === 'object' && err !== null) {\n try {\n if (Object.prototype.toString.call(err) === '[object Error]') {\n // @ts-ignore - not all envs have native support for cause yet\n const error = new Error(err.message, err.cause ? { cause: err.cause } : {});\n if (err.stack) error.stack = err.stack;\n // @ts-ignore - not all envs have native support for cause yet\n if (err.cause && !error.cause) error.cause = err.cause;\n if (err.name) error.name = err.name;\n return error;\n }\n } catch {}\n try {\n return new Error(JSON.stringify(err));\n } catch {}\n }\n return new Error(err);\n};\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nimport { castToError } from '../internal/errors.js';\n\nexport class GeminiNextGenAPIClientError extends Error {}\n\nexport class APIError<\n TStatus extends number | undefined = number | undefined,\n THeaders extends Headers | undefined = Headers | undefined,\n TError extends Object | undefined = Object | undefined,\n> extends GeminiNextGenAPIClientError {\n /** HTTP status for the response that caused the error */\n readonly status: TStatus;\n /** HTTP headers for the response that caused the error */\n readonly headers: THeaders;\n /** JSON body of the response that caused the error */\n readonly error: TError;\n\n constructor(status: TStatus, error: TError, message: string | undefined, headers: THeaders) {\n super(`${APIError.makeMessage(status, error, message)}`);\n this.status = status;\n this.headers = headers;\n this.error = error;\n }\n\n private static makeMessage(status: number | undefined, error: any, message: string | undefined) {\n const msg =\n error?.message ?\n typeof error.message === 'string' ?\n error.message\n : JSON.stringify(error.message)\n : error ? JSON.stringify(error)\n : message;\n\n if (status && msg) {\n return `${status} ${msg}`;\n }\n if (status) {\n return `${status} status code (no body)`;\n }\n if (msg) {\n return msg;\n }\n return '(no status code or body)';\n }\n\n static generate(\n status: number | undefined,\n errorResponse: Object | undefined,\n message: string | undefined,\n headers: Headers | undefined,\n ): APIError {\n if (!status || !headers) {\n return new APIConnectionError({ message, cause: castToError(errorResponse) });\n }\n\n const error = errorResponse as Record<string, any>;\n\n if (status === 400) {\n return new BadRequestError(status, error, message, headers);\n }\n\n if (status === 401) {\n return new AuthenticationError(status, error, message, headers);\n }\n\n if (status === 403) {\n return new PermissionDeniedError(status, error, message, headers);\n }\n\n if (status === 404) {\n return new NotFoundError(status, error, message, headers);\n }\n\n if (status === 409) {\n return new ConflictError(status, error, message, headers);\n }\n\n if (status === 422) {\n return new UnprocessableEntityError(status, error, message, headers);\n }\n\n if (status === 429) {\n return new RateLimitError(status, error, message, headers);\n }\n\n if (status >= 500) {\n return new InternalServerError(status, error, message, headers);\n }\n\n return new APIError(status, error, message, headers);\n }\n}\n\nexport class APIUserAbortError extends APIError<undefined, undefined, undefined> {\n constructor({ message }: { message?: string } = {}) {\n super(undefined, undefined, message || 'Request was aborted.', undefined);\n }\n}\n\nexport class APIConnectionError extends APIError<undefined, undefined, undefined> {\n constructor({ message, cause }: { message?: string | undefined; cause?: Error | undefined }) {\n super(undefined, undefined, message || 'Connection error.', undefined);\n // in some environments the 'cause' property is already declared\n // @ts-ignore\n if (cause) this.cause = cause;\n }\n}\n\nexport class APIConnectionTimeoutError extends APIConnectionError {\n constructor({ message }: { message?: string } = {}) {\n super({ message: message ?? 'Request timed out.' });\n }\n}\n\nexport class BadRequestError extends APIError<400, Headers> {}\n\nexport class AuthenticationError extends APIError<401, Headers> {}\n\nexport class PermissionDeniedError extends APIError<403, Headers> {}\n\nexport class NotFoundError extends APIError<404, Headers> {}\n\nexport class ConflictError extends APIError<409, Headers> {}\n\nexport class UnprocessableEntityError extends APIError<422, Headers> {}\n\nexport class RateLimitError extends APIError<429, Headers> {}\n\nexport class InternalServerError extends APIError<number, Headers> {}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nimport { GeminiNextGenAPIClientError } from '../../core/error.js';\n\n// https://url.spec.whatwg.org/#url-scheme-string\nconst startsWithSchemeRegexp = /^[a-z][a-z0-9+.-]*:/i;\n\nexport const isAbsoluteURL = (url: string): boolean => {\n return startsWithSchemeRegexp.test(url);\n};\n\nlet isArrayInternal = (val: unknown): val is unknown[] => (\n (isArrayInternal = Array.isArray), isArrayInternal(val)\n);\nexport const isArray = isArrayInternal;\nlet isReadonlyArrayInternal = isArray as (val: unknown) => val is readonly unknown[];\nexport const isReadonlyArray = isReadonlyArrayInternal;\n\n/** Returns an object if the given value isn't an object, otherwise returns as-is */\nexport function maybeObj(x: unknown): object {\n if (typeof x !== 'object') {\n return {};\n }\n\n return x ?? {};\n}\n\n// https://stackoverflow.com/a/34491287\nexport function isEmptyObj(obj: Object | null | undefined): boolean {\n if (!obj) return true;\n for (const _k in obj) return false;\n return true;\n}\n\n// https://eslint.org/docs/latest/rules/no-prototype-builtins\nexport function hasOwn<T extends object = object>(obj: T, key: PropertyKey): key is keyof T {\n return Object.prototype.hasOwnProperty.call(obj, key);\n}\n\nexport function isObj(obj: unknown): obj is Record<string, unknown> {\n return obj != null && typeof obj === 'object' && !Array.isArray(obj);\n}\n\nexport const ensurePresent = <T>(value: T | null | undefined): T => {\n if (value == null) {\n throw new GeminiNextGenAPIClientError(`Expected a value to be given but received ${value} instead.`);\n }\n\n return value;\n};\n\nexport const validatePositiveInteger = (name: string, n: unknown): number => {\n if (typeof n !== 'number' || !Number.isInteger(n)) {\n throw new GeminiNextGenAPIClientError(`${name} must be an integer`);\n }\n if (n < 0) {\n throw new GeminiNextGenAPIClientError(`${name} must be a positive integer`);\n }\n return n;\n};\n\nexport const coerceInteger = (value: unknown): number => {\n if (typeof value === 'number') return Math.round(value);\n if (typeof value === 'string') return parseInt(value, 10);\n\n throw new GeminiNextGenAPIClientError(`Could not coerce ${value} (type: ${typeof value}) into a number`);\n};\n\nexport const coerceFloat = (value: unknown): number => {\n if (typeof value === 'number') return value;\n if (typeof value === 'string') return parseFloat(value);\n\n throw new GeminiNextGenAPIClientError(`Could not coerce ${value} (type: ${typeof value}) into a number`);\n};\n\nexport const coerceBoolean = (value: unknown): boolean => {\n if (typeof value === 'boolean') return value;\n if (typeof value === 'string') return value === 'true';\n return Boolean(value);\n};\n\nexport const maybeCoerceInteger = (value: unknown): number | undefined => {\n if (value == null) {\n return undefined;\n }\n return coerceInteger(value);\n};\n\nexport const maybeCoerceFloat = (value: unknown): number | undefined => {\n if (value == null) {\n return undefined;\n }\n return coerceFloat(value);\n};\n\nexport const maybeCoerceBoolean = (value: unknown): boolean | undefined => {\n if (value == null) {\n return undefined;\n }\n return coerceBoolean(value);\n};\n\nexport const safeJSON = (text: string) => {\n try {\n return JSON.parse(text);\n } catch (err) {\n return undefined;\n }\n};\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nexport const sleep = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms));\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nexport const VERSION = '0.0.1';\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nimport { VERSION } from '../version.js';\n\nexport const isRunningInBrowser = () => {\n return (\n // @ts-ignore\n (typeof window !== 'undefined' &&\n // @ts-ignore\n typeof window.document !== 'undefined' && typeof navigator !== 'undefined')\n );\n};\n\ntype DetectedPlatform = 'deno' | 'node' | 'edge' | 'unknown';\n\n/**\n * Note this does not detect 'browser'; for that, use getBrowserInfo().\n */\nfunction getDetectedPlatform(): DetectedPlatform {\n if (typeof Deno !== 'undefined' && Deno.build != null) {\n return 'deno';\n }\n if (typeof EdgeRuntime !== 'undefined') {\n return 'edge';\n }\n if (\n Object.prototype.toString.call(\n typeof (globalThis as any).process !== 'undefined' ? (globalThis as any).process : 0,\n ) === '[object process]'\n ) {\n return 'node';\n }\n return 'unknown';\n}\n\ndeclare const Deno: any;\ndeclare const EdgeRuntime: any;\ntype Arch = 'x32' | 'x64' | 'arm' | 'arm64' | `other:${string}` | 'unknown';\ntype PlatformName =\n | 'MacOS'\n | 'Linux'\n | 'Windows'\n | 'FreeBSD'\n | 'OpenBSD'\n | 'iOS'\n | 'Android'\n | `Other:${string}`\n | 'Unknown';\ntype Browser = 'ie' | 'edge' | 'chrome' | 'firefox' | 'safari';\ntype PlatformProperties = {\n 'X-Stainless-Lang': 'js';\n 'X-Stainless-Package-Version': string;\n 'X-Stainless-OS': PlatformName;\n 'X-Stainless-Arch': Arch;\n 'X-Stainless-Runtime': 'node' | 'deno' | 'edge' | `browser:${Browser}` | 'unknown';\n 'X-Stainless-Runtime-Version': string;\n};\nconst getPlatformProperties = (): PlatformProperties => {\n const detectedPlatform = getDetectedPlatform();\n if (detectedPlatform === 'deno') {\n return {\n 'X-Stainless-Lang': 'js',\n 'X-Stainless-Package-Version': VERSION,\n 'X-Stainless-OS': normalizePlatform(Deno.build.os),\n 'X-Stainless-Arch': normalizeArch(Deno.build.arch),\n 'X-Stainless-Runtime': 'deno',\n 'X-Stainless-Runtime-Version':\n typeof Deno.version === 'string' ? Deno.version : Deno.version?.deno ?? 'unknown',\n };\n }\n if (typeof EdgeRuntime !== 'undefined') {\n return {\n 'X-Stainless-Lang': 'js',\n 'X-Stainless-Package-Version': VERSION,\n 'X-Stainless-OS': 'Unknown',\n 'X-Stainless-Arch': `other:${EdgeRuntime}`,\n 'X-Stainless-Runtime': 'edge',\n 'X-Stainless-Runtime-Version': (globalThis as any).process.version,\n };\n }\n // Check if Node.js\n if (detectedPlatform === 'node') {\n return {\n 'X-Stainless-Lang': 'js',\n 'X-Stainless-Package-Version': VERSION,\n 'X-Stainless-OS': normalizePlatform((globalThis as any).process.platform ?? 'unknown'),\n 'X-Stainless-Arch': normalizeArch((globalThis as any).process.arch ?? 'unknown'),\n 'X-Stainless-Runtime': 'node',\n 'X-Stainless-Runtime-Version': (globalThis as any).process.version ?? 'unknown',\n };\n }\n\n const browserInfo = getBrowserInfo();\n if (browserInfo) {\n return {\n 'X-Stainless-Lang': 'js',\n 'X-Stainless-Package-Version': VERSION,\n 'X-Stainless-OS': 'Unknown',\n 'X-Stainless-Arch': 'unknown',\n 'X-Stainless-Runtime': `browser:${browserInfo.browser}`,\n 'X-Stainless-Runtime-Version': browserInfo.version,\n };\n }\n\n // TODO add support for Cloudflare workers, etc.\n return {\n 'X-Stainless-Lang': 'js',\n 'X-Stainless-Package-Version': VERSION,\n 'X-Stainless-OS': 'Unknown',\n 'X-Stainless-Arch': 'unknown',\n 'X-Stainless-Runtime': 'unknown',\n 'X-Stainless-Runtime-Version': 'unknown',\n };\n};\n\ntype BrowserInfo = {\n browser: Browser;\n version: string;\n};\n\ndeclare const navigator: { userAgent: string } | undefined;\n\n// Note: modified from https://github.com/JS-DevTools/host-environment/blob/b1ab79ecde37db5d6e163c050e54fe7d287d7c92/src/isomorphic.browser.ts\nfunction getBrowserInfo(): BrowserInfo | null {\n if (typeof navigator === 'undefined' || !navigator) {\n return null;\n }\n\n // NOTE: The order matters here!\n const browserPatterns = [\n { key: 'edge' as const, pattern: /Edge(?:\\W+(\\d+)\\.(\\d+)(?:\\.(\\d+))?)?/ },\n { key: 'ie' as const, pattern: /MSIE(?:\\W+(\\d+)\\.(\\d+)(?:\\.(\\d+))?)?/ },\n { key: 'ie' as const, pattern: /Trident(?:.*rv\\:(\\d+)\\.(\\d+)(?:\\.(\\d+))?)?/ },\n { key: 'chrome' as const, pattern: /Chrome(?:\\W+(\\d+)\\.(\\d+)(?:\\.(\\d+))?)?/ },\n { key: 'firefox' as const, pattern: /Firefox(?:\\W+(\\d+)\\.(\\d+)(?:\\.(\\d+))?)?/ },\n { key: 'safari' as const, pattern: /(?:Version\\W+(\\d+)\\.(\\d+)(?:\\.(\\d+))?)?(?:\\W+Mobile\\S*)?\\W+Safari/ },\n ];\n\n // Find the FIRST matching browser\n for (const { key, pattern } of browserPatterns) {\n const match = pattern.exec(navigator.userAgent);\n if (match) {\n const major = match[1] || 0;\n const minor = match[2] || 0;\n const patch = match[3] || 0;\n\n return { browser: key, version: `${major}.${minor}.${patch}` };\n }\n }\n\n return null;\n}\n\nconst normalizeArch = (arch: string): Arch => {\n // Node docs:\n // - https://nodejs.org/api/process.html#processarch\n // Deno docs:\n // - https://doc.deno.land/deno/stable/~/Deno.build\n if (arch === 'x32') return 'x32';\n if (arch === 'x86_64' || arch === 'x64') return 'x64';\n if (arch === 'arm') return 'arm';\n if (arch === 'aarch64' || arch === 'arm64') return 'arm64';\n if (arch) return `other:${arch}`;\n return 'unknown';\n};\n\nconst normalizePlatform = (platform: string): PlatformName => {\n // Node platforms:\n // - https://nodejs.org/api/process.html#processplatform\n // Deno platforms:\n // - https://doc.deno.land/deno/stable/~/Deno.build\n // - https://github.com/denoland/deno/issues/14799\n\n platform = platform.toLowerCase();\n\n // NOTE: this iOS check is untested and may not work\n // Node does not work natively on IOS, there is a fork at\n // https://github.com/nodejs-mobile/nodejs-mobile\n // however it is unknown at the time of writing how to detect if it is running\n if (platform.includes('ios')) return 'iOS';\n if (platform === 'android') return 'Android';\n if (platform === 'darwin') return 'MacOS';\n if (platform === 'win32') return 'Windows';\n if (platform === 'freebsd') return 'FreeBSD';\n if (platform === 'openbsd') return 'OpenBSD';\n if (platform === 'linux') return 'Linux';\n if (platform) return `Other:${platform}`;\n return 'Unknown';\n};\n\nlet _platformHeaders: PlatformProperties;\nexport const getPlatformHeaders = () => {\n return (_platformHeaders ??= getPlatformProperties());\n};\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\n/**\n * This module provides internal shims and utility functions for environments where certain Node.js or global types may not be available.\n *\n * These are used to ensure we can provide a consistent behaviour between different JavaScript environments and good error\n * messages in cases where an environment isn't fully supported.\n */\n\nimport type { Fetch } from './builtin-types.js';\nimport type { ReadableStream } from './shim-types.js';\n\nexport function getDefaultFetch(): Fetch {\n if (typeof fetch !== 'undefined') {\n return fetch as any;\n }\n\n throw new Error(\n '`fetch` is not defined as a global; Either pass `fetch` to the client, `new GeminiNextGenAPIClient({ fetch })` or polyfill the global, `globalThis.fetch = fetch`',\n );\n}\n\ntype ReadableStreamArgs = ConstructorParameters<typeof ReadableStream>;\n\nexport function makeReadableStream(...args: ReadableStreamArgs): ReadableStream {\n const ReadableStream = (globalThis as any).ReadableStream;\n if (typeof ReadableStream === 'undefined') {\n // Note: All of the platforms / runtimes we officially support already define\n // `ReadableStream` as a global, so this should only ever be hit on unsupported runtimes.\n throw new Error(\n '`ReadableStream` is not defined as a global; You will need to polyfill it, `globalThis.ReadableStream = ReadableStream`',\n );\n }\n\n return new ReadableStream(...args);\n}\n\nexport function ReadableStreamFrom<T>(iterable: Iterable<T> | AsyncIterable<T>): ReadableStream<T> {\n let iter: AsyncIterator<T> | Iterator<T> =\n Symbol.asyncIterator in iterable ? iterable[Symbol.asyncIterator]() : iterable[Symbol.iterator]();\n\n return makeReadableStream({\n start() {},\n async pull(controller: any) {\n const { done, value } = await iter.next();\n if (done) {\n controller.close();\n } else {\n controller.enqueue(value);\n }\n },\n async cancel() {\n await iter.return?.();\n },\n });\n}\n\n/**\n * Most browsers don't yet have async iterable support for ReadableStream,\n * and Node has a very different way of reading bytes from its \"ReadableStream\".\n *\n * This polyfill was pulled from https://github.com/MattiasBuelens/web-streams-polyfill/pull/122#issuecomment-1627354490\n */\nexport function ReadableStreamToAsyncIterable<T>(stream: any): AsyncIterableIterator<T> {\n if (stream[Symbol.asyncIterator]) return stream;\n\n const reader = stream.getReader();\n return {\n async next() {\n try {\n const result = await reader.read();\n if (result?.done) reader.releaseLock(); // release lock when stream becomes closed\n return result;\n } catch (e) {\n reader.releaseLock(); // release lock when stream becomes errored\n throw e;\n }\n },\n async return() {\n const cancelPromise = reader.cancel();\n reader.releaseLock();\n await cancelPromise;\n return { done: true, value: undefined };\n },\n [Symbol.asyncIterator]() {\n return this;\n },\n };\n}\n\n/**\n * Cancels a ReadableStream we don't need to consume.\n * See https://undici.nodejs.org/#/?id=garbage-collection\n */\nexport async function CancelReadableStream(stream: any): Promise<void> {\n if (stream === null || typeof stream !== 'object') return;\n\n if (stream[Symbol.asyncIterator]) {\n await stream[Symbol.asyncIterator]().return?.();\n return;\n }\n\n const reader = stream.getReader();\n const cancelPromise = reader.cancel();\n reader.releaseLock();\n await cancelPromise;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nimport { NullableHeaders } from './headers.js';\n\nimport type { BodyInit } from './builtin-types.js';\nimport { Stream } from '../core/streaming.js';\nimport type { HTTPMethod, MergedRequestInit } from './types.js';\nimport { type HeadersLike } from './headers.js';\n\nexport type FinalRequestOptions = RequestOptions & { method: HTTPMethod; path: string };\n\nexport type RequestOptions = {\n /**\n * The HTTP method for the request (e.g., 'get', 'post', 'put', 'delete').\n */\n method?: HTTPMethod;\n\n /**\n * The URL path for the request.\n *\n * @example \"/v1/foo\"\n */\n path?: string;\n\n /**\n * Query parameters to include in the request URL.\n */\n query?: object | undefined | null;\n\n /**\n * The request body. Can be a string, JSON object, FormData, or other supported types.\n */\n body?: unknown;\n\n /**\n * HTTP headers to include with the request. Can be a Headers object, plain object, or array of tuples.\n */\n headers?: HeadersLike;\n\n /**\n * The maximum number of times that the client will retry a request in case of a\n * temporary failure, like a network error or a 5XX error from the server.\n *\n * @default 2\n */\n maxRetries?: number;\n\n stream?: boolean | undefined;\n\n /**\n * The maximum amount of time (in milliseconds) that the client should wait for a response\n * from the server before timing out a single request.\n *\n * @unit milliseconds\n */\n timeout?: number;\n\n /**\n * Additional `RequestInit` options to be passed to the underlying `fetch` call.\n * These options will be merged with the client's default fetch options.\n */\n fetchOptions?: MergedRequestInit;\n\n /**\n * An AbortSignal that can be used to cancel the request.\n */\n signal?: AbortSignal | undefined | null;\n\n /**\n * A unique key for this request to enable idempotency.\n */\n idempotencyKey?: string;\n\n /**\n * Override the default base URL for this specific request.\n */\n defaultBaseURL?: string | undefined;\n\n __binaryResponse?: boolean | undefined;\n __streamClass?: typeof Stream;\n};\n\nexport type EncodedContent = { bodyHeaders: HeadersLike; body: BodyInit };\nexport type RequestEncoder = (request: { headers: NullableHeaders; body: unknown }) => EncodedContent;\n\nexport const FallbackEncoder: RequestEncoder = ({ headers, body }) => {\n return {\n bodyHeaders: {\n 'content-type': 'application/json',\n },\n body: JSON.stringify(body),\n };\n};\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { type RequestOptions } from './request-options.js';\nimport type { FilePropertyBag, Fetch } from './builtin-types.js';\nimport type { BaseGeminiNextGenAPIClient } from '../client.js';\nimport { ReadableStreamFrom } from './shims.js';\n\nexport type BlobPart = string | ArrayBuffer | ArrayBufferView | Blob | DataView;\ntype FsReadStream = AsyncIterable<Uint8Array> & { path: string | { toString(): string } };\n\n// https://github.com/oven-sh/bun/issues/5980\ninterface BunFile extends Blob {\n readonly name?: string | undefined;\n}\n\nexport const checkFileSupport = () => {\n if (typeof File === 'undefined') {\n const { process } = globalThis as any;\n const isOldNode =\n typeof process?.versions?.node === 'string' && parseInt(process.versions.node.split('.')) < 20;\n throw new Error(\n '`File` is not defined as a global, which is required for file uploads.' +\n (isOldNode ?\n \" Update to Node 20 LTS or newer, or set `globalThis.File` to `import('node:buffer').File`.\"\n : ''),\n );\n }\n};\n\n/**\n * Typically, this is a native \"File\" class.\n *\n * We provide the {@link toFile} utility to convert a variety of objects\n * into the File class.\n *\n * For convenience, you can also pass a fetch Response, or in Node,\n * the result of fs.createReadStream().\n */\nexport type Uploadable = File | Response | FsReadStream | BunFile;\n\n/**\n * Construct a `File` instance. This is used to ensure a helpful error is thrown\n * for environments that don't define a global `File` yet.\n */\nexport function makeFile(\n fileBits: BlobPart[],\n fileName: string | undefined,\n options?: FilePropertyBag,\n): File {\n checkFileSupport();\n return new File(fileBits as any, fileName ?? 'unknown_file', options);\n}\n\nexport function getName(value: any): string | undefined {\n return ((\n (typeof value === 'object' &&\n value !== null &&\n (('name' in value && value.name && String(value.name)) ||\n ('url' in value && value.url && String(value.url)) ||\n ('filename' in value && value.filename && String(value.filename)) ||\n ('path' in value && value.path && String(value.path)))) ||\n ''\n )\n .split(/[\\\\/]/)\n .pop() || undefined);\n}\n\nexport const isAsyncIterable = (value: any): value is AsyncIterable<any> =>\n value != null && typeof value === 'object' && typeof value[Symbol.asyncIterator] === 'function';\n\n/**\n * Returns a multipart/form-data request if any part of the given request body contains a File / Blob value.\n * Otherwise returns the request as is.\n */\nexport const maybeMultipartFormRequestOptions = async (\n opts: RequestOptions,\n fetch: BaseGeminiNextGenAPIClient | Fetch,\n): Promise<RequestOptions> => {\n if (!hasUploadableValue(opts.body)) return opts;\n\n return { ...opts, body: await createForm(opts.body, fetch) };\n};\n\ntype MultipartFormRequestOptions = Omit<RequestOptions, 'body'> & { body: unknown };\n\nexport const multipartFormRequestOptions = async (\n opts: MultipartFormRequestOptions,\n fetch: BaseGeminiNextGenAPIClient | Fetch,\n): Promise<RequestOptions> => {\n return { ...opts, body: await createForm(opts.body, fetch) };\n};\n\nconst supportsFormDataMap = /* @__PURE__ */ new WeakMap<Fetch, Promise<boolean>>();\n\n/**\n * node-fetch doesn't support the global FormData object in recent node versions. Instead of sending\n * properly-encoded form data, it just stringifies the object, resulting in a request body of \"[object FormData]\".\n * This function detects if the fetch function provided supports the global FormData object to avoid\n * confusing error messages later on.\n */\nfunction supportsFormData(fetchObject: BaseGeminiNextGenAPIClient | Fetch): Promise<boolean> {\n const fetch: Fetch = typeof fetchObject === 'function' ? fetchObject : (fetchObject as any).fetch;\n const cached = supportsFormDataMap.get(fetch);\n if (cached) return cached;\n const promise = (async () => {\n try {\n const FetchResponse = (\n 'Response' in fetch ?\n fetch.Response\n : (await fetch('data:,')).constructor) as typeof Response;\n const data = new FormData();\n if (data.toString() === (await new FetchResponse(data).text())) {\n return false;\n }\n return true;\n } catch {\n // avoid false negatives\n return true;\n }\n })();\n supportsFormDataMap.set(fetch, promise);\n return promise;\n}\n\nexport const createForm = async <T = Record<string, unknown>>(\n body: T | undefined,\n fetch: BaseGeminiNextGenAPIClient | Fetch,\n): Promise<FormData> => {\n if (!(await supportsFormData(fetch))) {\n throw new TypeError(\n 'The provided fetch function does not support file uploads with the current global FormData class.',\n );\n }\n const form = new FormData();\n await Promise.all(Object.entries(body || {}).map(([key, value]) => addFormValue(form, key, value)));\n return form;\n};\n\n// We check for Blob not File because Bun.File doesn't inherit from File,\n// but they both inherit from Blob and have a `name` property at runtime.\nconst isNamedBlob = (value: unknown): value is Blob => value instanceof Blob && 'name' in value;\n\nconst isUploadable = (value: unknown) =>\n typeof value === 'object' &&\n value !== null &&\n (value instanceof Response || isAsyncIterable(value) || isNamedBlob(value));\n\nconst hasUploadableValue = (value: unknown): boolean => {\n if (isUploadable(value)) return true;\n if (Array.isArray(value)) return value.some(hasUploadableValue);\n if (value && typeof value === 'object') {\n for (const k in value) {\n if (hasUploadableValue((value as any)[k])) return true;\n }\n }\n return false;\n};\n\nconst addFormValue = async (form: FormData, key: string, value: unknown): Promise<void> => {\n if (value === undefined) return;\n if (value == null) {\n throw new TypeError(\n `Received null for \"${key}\"; to pass null in FormData, you must use the string 'null'`,\n );\n }\n\n // TODO: make nested formats configurable\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {\n form.append(key, String(value));\n } else if (value instanceof Response) {\n form.append(key, makeFile([await value.blob()], getName(value)));\n } else if (isAsyncIterable(value)) {\n form.append(key, makeFile([await new Response(ReadableStreamFrom(value)).blob()], getName(value)));\n } else if (isNamedBlob(value)) {\n form.append(key, value, getName(value));\n } else if (Array.isArray(value)) {\n await Promise.all(value.map((entry) => addFormValue(form, key + '[]', entry)));\n } else if (typeof value === 'object') {\n await Promise.all(\n Object.entries(value).map(([name, prop]) => addFormValue(form, `${key}[${name}]`, prop)),\n );\n } else {\n throw new TypeError(\n `Invalid value given to form, expected a string, number, boolean, object, Array, File or Blob but got ${value} instead`,\n );\n }\n};\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { BlobPart, getName, makeFile, isAsyncIterable } from './uploads.js';\nimport type { FilePropertyBag } from './builtin-types.js';\nimport { checkFileSupport } from './uploads.js';\n\nexport type BlobLikePart = string | ArrayBuffer | ArrayBufferView | BlobLike | DataView;\n\n/**\n * Intended to match DOM Blob, node-fetch Blob, node:buffer Blob, etc.\n * Don't add arrayBuffer here, node-fetch doesn't have it\n */\nexport interface BlobLike {\n /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/size) */\n readonly size: number;\n /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/type) */\n readonly type: string;\n /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/text) */\n text(): Promise<string>;\n /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/slice) */\n slice(start?: number, end?: number): BlobLike;\n}\n\n/**\n * This check adds the arrayBuffer() method type because it is available and used at runtime\n */\nconst isBlobLike = (value: any): value is BlobLike & { arrayBuffer(): Promise<ArrayBuffer> } =>\n value != null &&\n typeof value === 'object' &&\n typeof value.size === 'number' &&\n typeof value.type === 'string' &&\n typeof value.text === 'function' &&\n typeof value.slice === 'function' &&\n typeof value.arrayBuffer === 'function';\n\n/**\n * Intended to match DOM File, node:buffer File, undici File, etc.\n */\ninterface FileLike extends BlobLike {\n /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/File/lastModified) */\n readonly lastModified: number;\n /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/File/name) */\n readonly name?: string | undefined;\n}\n\n/**\n * This check adds the arrayBuffer() method type because it is available and used at runtime\n */\nconst isFileLike = (value: any): value is FileLike & { arrayBuffer(): Promise<ArrayBuffer> } =>\n value != null &&\n typeof value === 'object' &&\n typeof value.name === 'string' &&\n typeof value.lastModified === 'number' &&\n isBlobLike(value);\n\n/**\n * Intended to match DOM Response, node-fetch Response, undici Response, etc.\n */\nexport interface ResponseLike {\n url: string;\n blob(): Promise<BlobLike>;\n}\n\nconst isResponseLike = (value: any): value is ResponseLike =>\n value != null &&\n typeof value === 'object' &&\n typeof value.url === 'string' &&\n typeof value.blob === 'function';\n\nexport type ToFileInput =\n | FileLike\n | ResponseLike\n | Exclude<BlobLikePart, string>\n | AsyncIterable<BlobLikePart>;\n\n/**\n * Helper for creating a {@link File} to pass to an SDK upload method from a variety of different data formats\n * @param value the raw content of the file. Can be an {@link Uploadable}, BlobLikePart, or AsyncIterable of BlobLikeParts\n * @param {string=} name the name of the file. If omitted, toFile will try to determine a file name from bits if possible\n * @param {Object=} options additional properties\n * @param {string=} options.type the MIME type of the content\n * @param {number=} options.lastModified the last modified timestamp\n * @returns a {@link File} with the given properties\n */\nexport async function toFile(\n value: ToFileInput | PromiseLike<ToFileInput>,\n name?: string | null | undefined,\n options?: FilePropertyBag | undefined,\n): Promise<File> {\n checkFileSupport();\n\n // If it's a promise, resolve it.\n value = await value;\n\n // If we've been given a `File` we don't need to do anything\n if (isFileLike(value)) {\n if (value instanceof File) {\n return value;\n }\n return makeFile([await value.arrayBuffer()], value.name);\n }\n\n if (isResponseLike(value)) {\n const blob = await value.blob();\n name ||= new URL(value.url).pathname.split(/[\\\\/]/).pop();\n\n return makeFile(await getBytes(blob), name, options);\n }\n\n const parts = await getBytes(value);\n\n name ||= getName(value);\n\n if (!options?.type) {\n const type = parts.find((part) => typeof part === 'object' && 'type' in part && part.type);\n if (typeof type === 'string') {\n options = { ...options, type };\n }\n }\n\n return makeFile(parts, name, options);\n}\n\nasync function getBytes(value: BlobLikePart | AsyncIterable<BlobLikePart>): Promise<Array<BlobPart>> {\n let parts: Array<BlobPart> = [];\n if (\n typeof value === 'string' ||\n ArrayBuffer.isView(value) || // includes Uint8Array, Buffer, etc.\n value instanceof ArrayBuffer\n ) {\n parts.push(value);\n } else if (isBlobLike(value)) {\n parts.push(value instanceof Blob ? value : await value.arrayBuffer());\n } else if (\n isAsyncIterable(value) // includes Readable, ReadableStream, etc.\n ) {\n for await (const chunk of value) {\n parts.push(...(await getBytes(chunk as BlobLikePart))); // TODO, consider validating?\n }\n } else {\n const constructor = value?.constructor?.name;\n throw new Error(\n `Unexpected data type: ${typeof value}${\n constructor ? `; constructor: ${constructor}` : ''\n }${propsForError(value)}`,\n );\n }\n\n return parts;\n}\n\nfunction propsForError(value: unknown): string {\n if (typeof value !== 'object' || value === null) return '';\n const props = Object.getOwnPropertyNames(value);\n return `; props: [${props.map((p) => `\"${p}\"`).join(', ')}]`;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nimport { BaseGeminiNextGenAPIClient } from '../client.js';\n\nexport abstract class APIResource {\n /**\n * The key path from the client. For example, a resource accessible as `client.resource.subresource` would\n * have a property `static override readonly _key = Object.freeze(['resource', 'subresource'] as const);`.\n */\n static readonly _key: readonly string[] = [];\n protected _client: BaseGeminiNextGenAPIClient;\n\n constructor(client: BaseGeminiNextGenAPIClient) {\n this._client = client;\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { GeminiNextGenAPIClientError } from '../../core/error.js';\n\n/**\n * Percent-encode everything that isn't safe to have in a path without encoding safe chars.\n *\n * Taken from https://datatracker.ietf.org/doc/html/rfc3986#section-3.3:\n * > unreserved = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n * > sub-delims = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\" / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n * > pchar = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n */\nexport function encodeURIPath(str: string) {\n return str.replace(/[^A-Za-z0-9\\-._~!$&'()*+,;=:@]+/g, encodeURIComponent);\n}\n\nconst EMPTY = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.create(null));\n\nexport const createPathTagFunction = (pathEncoder = encodeURIPath) =>\n (function path(statics: readonly string[], ...params: readonly unknown[]): string {\n // If there are no params, no processing is needed.\n if (statics.length === 1) return statics[0]!;\n\n let postPath = false;\n const invalidSegments = [];\n const path = statics.reduce((previousValue, currentValue, index) => {\n if (/[?#]/.test(currentValue)) {\n postPath = true;\n }\n const value = params[index];\n let encoded = (postPath ? encodeURIComponent : pathEncoder)('' + value);\n if (\n index !== params.length &&\n (value == null ||\n (typeof value === 'object' &&\n // handle values from other realms\n value.toString ===\n Object.getPrototypeOf(Object.getPrototypeOf((value as any).hasOwnProperty ?? EMPTY) ?? EMPTY)\n ?.toString))\n ) {\n encoded = value + '';\n invalidSegments.push({\n start: previousValue.length + currentValue.length,\n length: encoded.length,\n error: `Value of type ${Object.prototype.toString\n .call(value)\n .slice(8, -1)} is not a valid path parameter`,\n });\n }\n return previousValue + currentValue + (index === params.length ? '' : encoded);\n }, '');\n\n const pathOnly = path.split(/[?#]/, 1)[0]!;\n const invalidSegmentPattern = /(?<=^|\\/)(?:\\.|%2e){1,2}(?=\\/|$)/gi;\n let match;\n\n // Find all invalid segments\n while ((match = invalidSegmentPattern.exec(pathOnly)) !== null) {\n invalidSegments.push({\n start: match.index,\n length: match[0].length,\n error: `Value \"${match[0]}\" can\\'t be safely passed as a path parameter`,\n });\n }\n\n invalidSegments.sort((a, b) => a.start - b.start);\n\n if (invalidSegments.length > 0) {\n let lastEnd = 0;\n const underline = invalidSegments.reduce((acc, segment) => {\n const spaces = ' '.repeat(segment.start - lastEnd);\n const arrows = '^'.repeat(segment.length);\n lastEnd = segment.start + segment.length;\n return acc + spaces + arrows;\n }, '');\n\n throw new GeminiNextGenAPIClientError(\n `Path parameters result in path with invalid segments:\\n${invalidSegments\n .map((e) => e.error)\n .join('\\n')}\\n${path}\\n${underline}`,\n );\n }\n\n return path;\n });\n\n/**\n * URI-encodes path params and ensures no unsafe /./ or /../ path segments are introduced.\n */\nexport const path = /* @__PURE__ */ createPathTagFunction(encodeURIPath);\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nimport { APIResource } from '../core/resource.js';\nimport * as Errors from '../core/error.js';\nimport * as InteractionsAPI from './interactions.js';\nimport { APIPromise } from '../core/api-promise.js';\nimport { Stream } from '../core/streaming.js';\nimport { RequestOptions } from '../internal/request-options.js';\nimport { path } from '../internal/utils/path.js';\n\nexport class BaseInteractions extends APIResource {\n static override readonly _key: readonly ['interactions'] = Object.freeze(['interactions'] as const);\n\n /**\n * Creates a new interaction.\n *\n * @example\n * ```ts\n * const interaction = await client.interactions.create({\n * api_version: 'api_version',\n * input: 'string',\n * model: 'gemini-2.5-flash',\n * });\n * ```\n */\n create(params: CreateModelInteractionParamsNonStreaming, options?: RequestOptions): APIPromise<Interaction>;\n create(\n params: CreateModelInteractionParamsStreaming,\n options?: RequestOptions,\n ): APIPromise<Stream<InteractionSSEEvent>>;\n create(params: CreateAgentInteractionParamsNonStreaming, options?: RequestOptions): APIPromise<Interaction>;\n create(\n params: CreateAgentInteractionParamsStreaming,\n options?: RequestOptions,\n ): APIPromise<Stream<InteractionSSEEvent>>;\n create(\n params: BaseCreateModelInteractionParams | BaseCreateAgentInteractionParams,\n options?: RequestOptions,\n ): APIPromise<Stream<InteractionSSEEvent> | Interaction>;\n create(\n params: InteractionCreateParams,\n options?: RequestOptions,\n ): APIPromise<Interaction> | APIPromise<Stream<InteractionSSEEvent>> {\n const { api_version = this._client.apiVersion, ...body } = params;\n if ('model' in body && 'agent_config' in body) {\n throw new Errors.GeminiNextGenAPIClientError(\n `Invalid request: specified \\`model\\` and \\`agent_config\\`. If specifying \\`model\\`, use \\`generation_config\\`.`,\n );\n }\n if ('agent' in body && 'generation_config' in body) {\n throw new Errors.GeminiNextGenAPIClientError(\n `Invalid request: specified \\`agent\\` and \\`generation_config\\`. If specifying \\`agent\\`, use \\`agent_config\\`.`,\n );\n }\n return this._client.post(path`/${api_version}/interactions`, {\n body,\n ...options,\n stream: params.stream ?? false,\n }) as APIPromise<Interaction> | APIPromise<Stream<InteractionSSEEvent>>;\n }\n\n /**\n * Deletes the interaction by id.\n *\n * @example\n * ```ts\n * const interaction = await client.interactions.delete('id', {\n * api_version: 'api_version',\n * });\n * ```\n */\n delete(\n id: string,\n params: InteractionDeleteParams | null | undefined = {},\n options?: RequestOptions,\n ): APIPromise<unknown> {\n const { api_version = this._client.apiVersion } = params ?? {};\n return this._client.delete(path`/${api_version}/interactions/${id}`, options);\n }\n\n /**\n * Cancels an interaction by id. This only applies to background interactions that are still running.\n *\n * @example\n * ```ts\n * const interaction = await client.interactions.cancel('id', {\n * api_version: 'api_version',\n * });\n * ```\n */\n cancel(\n id: string,\n params: InteractionCancelParams | null | undefined = {},\n options?: RequestOptions,\n ): APIPromise<Interaction> {\n const { api_version = this._client.apiVersion } = params ?? {};\n return this._client.post(path`/${api_version}/interactions/${id}/cancel`, options);\n }\n\n /**\n * Retrieves the full details of a single interaction based on its `Interaction.id`.\n *\n * @example\n * ```ts\n * const interaction = await client.interactions.get('id', {\n * api_version: 'api_version',\n * });\n * ```\n */\n get(\n id: string,\n params?: InteractionGetParamsNonStreaming,\n options?: RequestOptions,\n ): APIPromise<Interaction>;\n get(\n id: string,\n params: InteractionGetParamsStreaming,\n options?: RequestOptions,\n ): APIPromise<Stream<InteractionSSEEvent>>;\n get(\n id: string,\n params?: InteractionGetParamsBase | undefined,\n options?: RequestOptions,\n ): APIPromise<Stream<InteractionSSEEvent> | Interaction>;\n get(\n id: string,\n params: InteractionGetParams | undefined = {},\n options?: RequestOptions,\n ): APIPromise<Interaction> | APIPromise<Stream<InteractionSSEEvent>> {\n const { api_version = this._client.apiVersion, ...query } = params ?? {};\n return this._client.get(path`/${api_version}/interactions/${id}`, {\n query,\n ...options,\n stream: params?.stream ?? false,\n }) as APIPromise<Interaction> | APIPromise<Stream<InteractionSSEEvent>>;\n }\n}\nexport class Interactions extends BaseInteractions {}\n\n/**\n * The configuration for allowed tools.\n */\nexport interface AllowedTools {\n /**\n * The mode of the tool choice.\n */\n mode?: ToolChoiceType;\n\n /**\n * The names of the allowed tools.\n */\n tools?: Array<string>;\n}\n\n/**\n * Citation information for model-generated content.\n */\nexport interface Annotation {\n /**\n * End of the attributed segment, exclusive.\n */\n end_index?: number;\n\n /**\n * Source attributed for a portion of the text. Could be a URL, title, or\n * other identifier.\n */\n source?: string;\n\n /**\n * Start of segment of the response that is attributed to this source.\n *\n * Index indicates the start of the segment, measured in bytes.\n */\n start_index?: number;\n}\n\n/**\n * An audio content block.\n */\nexport interface AudioContent {\n type: 'audio';\n\n /**\n * The audio content.\n */\n data?: string;\n\n /**\n * The mime type of the audio.\n */\n mime_type?: AudioMimeType;\n\n /**\n * The URI of the audio.\n */\n uri?: string;\n}\n\n/**\n * The mime type of the audio.\n */\nexport type AudioMimeType =\n | 'audio/wav'\n | 'audio/mp3'\n | 'audio/aiff'\n | 'audio/aac'\n | 'audio/ogg'\n | 'audio/flac'\n | (string & {});\n\n/**\n * The arguments to pass to the code execution.\n */\nexport interface CodeExecutionCallArguments {\n /**\n * The code to be executed.\n */\n code?: string;\n\n /**\n * Programming language of the `code`.\n */\n language?: 'python';\n}\n\n/**\n * Code execution content.\n */\nexport interface CodeExecutionCallContent {\n type: 'code_execution_call';\n\n /**\n * A unique ID for this specific tool call.\n */\n id?: string;\n\n /**\n * The arguments to pass to the code execution.\n */\n arguments?: CodeExecutionCallArguments;\n}\n\n/**\n * Code execution result content.\n */\nexport interface CodeExecutionResultContent {\n type: 'code_execution_result';\n\n /**\n * ID to match the ID from the code execution call block.\n */\n call_id?: string;\n\n /**\n * Whether the code execution resulted in an error.\n */\n is_error?: boolean;\n\n /**\n * The output of the code execution.\n */\n result?: string;\n\n /**\n * A signature hash for backend validation.\n */\n signature?: string;\n}\n\n/**\n * The content of the response.\n */\nexport type Content =\n | TextContent\n | ImageContent\n | AudioContent\n | DocumentContent\n | VideoContent\n | ThoughtContent\n | FunctionCallContent\n | FunctionResultContent\n | CodeExecutionCallContent\n | CodeExecutionResultContent\n | URLContextCallContent\n | URLContextResultContent\n | GoogleSearchCallContent\n | GoogleSearchResultContent\n | MCPServerToolCallContent\n | MCPServerToolResultContent\n | FileSearchCallContent\n | FileSearchResultContent;\n\nexport interface ContentDelta {\n delta?:\n | ContentDelta.TextDelta\n | ContentDelta.ImageDelta\n | ContentDelta.AudioDelta\n | ContentDelta.DocumentDelta\n | ContentDelta.VideoDelta\n | ContentDelta.ThoughtSummaryDelta\n | ContentDelta.ThoughtSignatureDelta\n | ContentDelta.FunctionCallDelta\n | ContentDelta.FunctionResultDelta\n | ContentDelta.CodeExecutionCallDelta\n | ContentDelta.CodeExecutionResultDelta\n | ContentDelta.URLContextCallDelta\n | ContentDelta.URLContextResultDelta\n | ContentDelta.GoogleSearchCallDelta\n | ContentDelta.GoogleSearchResultDelta\n | ContentDelta.MCPServerToolCallDelta\n | ContentDelta.MCPServerToolResultDelta\n | ContentDelta.FileSearchCallDelta\n | ContentDelta.FileSearchResultDelta;\n\n /**\n * The event_id token to be used to resume the interaction stream, from this event.\n */\n event_id?: string;\n\n event_type?: 'content.delta';\n\n index?: number;\n}\n\nexport namespace ContentDelta {\n export interface TextDelta {\n type: 'text';\n\n /**\n * Citation information for model-generated content.\n */\n annotations?: Array<InteractionsAPI.Annotation>;\n\n text?: string;\n }\n\n export interface ImageDelta {\n type: 'image';\n\n data?: string;\n\n /**\n * The mime type of the image.\n */\n mime_type?: InteractionsAPI.ImageMimeType;\n\n /**\n * The resolution of the media.\n */\n resolution?: 'low' | 'medium' | 'high' | 'ultra_high';\n\n uri?: string;\n }\n\n export interface AudioDelta {\n type: 'audio';\n\n data?: string;\n\n /**\n * The mime type of the audio.\n */\n mime_type?: InteractionsAPI.AudioMimeType;\n\n uri?: string;\n }\n\n export interface DocumentDelta {\n type: 'document';\n\n data?: string;\n\n /**\n * The mime type of the document.\n */\n mime_type?: InteractionsAPI.DocumentMimeType;\n\n uri?: string;\n }\n\n export interface VideoDelta {\n type: 'video';\n\n data?: string;\n\n /**\n * The mime type of the video.\n */\n mime_type?: InteractionsAPI.VideoMimeType;\n\n /**\n * The resolution of the media.\n */\n resolution?: 'low' | 'medium' | 'high' | 'ultra_high';\n\n uri?: string;\n }\n\n export interface ThoughtSummaryDelta {\n type: 'thought_summary';\n\n /**\n * A text content block.\n */\n content?: InteractionsAPI.TextContent | InteractionsAPI.ImageContent;\n }\n\n export interface ThoughtSignatureDelta {\n type: 'thought_signature';\n\n /**\n * Signature to match the backend source to be part of the generation.\n */\n signature?: string;\n }\n\n export interface FunctionCallDelta {\n type: 'function_call';\n\n /**\n * A unique ID for this specific tool call.\n */\n id?: string;\n\n arguments?: { [key: string]: unknown };\n\n name?: string;\n }\n\n export interface FunctionResultDelta {\n type: 'function_result';\n\n /**\n * ID to match the ID from the function call block.\n */\n call_id?: string;\n\n is_error?: boolean;\n\n name?: string;\n\n /**\n * Tool call result delta.\n */\n result?: FunctionResultDelta.Items | unknown | string;\n }\n\n export namespace FunctionResultDelta {\n export interface Items {\n items?: Array<InteractionsAPI.TextContent | InteractionsAPI.ImageContent>;\n }\n }\n\n export interface CodeExecutionCallDelta {\n type: 'code_execution_call';\n\n /**\n * A unique ID for this specific tool call.\n */\n id?: string;\n\n /**\n * The arguments to pass to the code execution.\n */\n arguments?: InteractionsAPI.CodeExecutionCallArguments;\n }\n\n export interface CodeExecutionResultDelta {\n type: 'code_execution_result';\n\n /**\n * ID to match the ID from the function call block.\n */\n call_id?: string;\n\n is_error?: boolean;\n\n result?: string;\n\n signature?: string;\n }\n\n export interface URLContextCallDelta {\n type: 'url_context_call';\n\n /**\n * A unique ID for this specific tool call.\n */\n id?: string;\n\n /**\n * The arguments to pass to the URL context.\n */\n arguments?: InteractionsAPI.URLContextCallArguments;\n }\n\n export interface URLContextResultDelta {\n type: 'url_context_result';\n\n /**\n * ID to match the ID from the function call block.\n */\n call_id?: string;\n\n is_error?: boolean;\n\n result?: Array<InteractionsAPI.URLContextResult>;\n\n signature?: string;\n }\n\n export interface GoogleSearchCallDelta {\n type: 'google_search_call';\n\n /**\n * A unique ID for this specific tool call.\n */\n id?: string;\n\n /**\n * The arguments to pass to Google Search.\n */\n arguments?: InteractionsAPI.GoogleSearchCallArguments;\n }\n\n export interface GoogleSearchResultDelta {\n type: 'google_search_result';\n\n /**\n * ID to match the ID from the function call block.\n */\n call_id?: string;\n\n is_error?: boolean;\n\n result?: Array<InteractionsAPI.GoogleSearchResult>;\n\n signature?: string;\n }\n\n export interface MCPServerToolCallDelta {\n type: 'mcp_server_tool_call';\n\n /**\n * A unique ID for this specific tool call.\n */\n id?: string;\n\n arguments?: { [key: string]: unknown };\n\n name?: string;\n\n server_name?: string;\n }\n\n export interface MCPServerToolResultDelta {\n type: 'mcp_server_tool_result';\n\n /**\n * ID to match the ID from the function call block.\n */\n call_id?: string;\n\n name?: string;\n\n /**\n * Tool call result delta.\n */\n result?: MCPServerToolResultDelta.Items | unknown | string;\n\n server_name?: string;\n }\n\n export namespace MCPServerToolResultDelta {\n export interface Items {\n items?: Array<InteractionsAPI.TextContent | InteractionsAPI.ImageContent>;\n }\n }\n\n export interface FileSearchCallDelta {\n type: 'file_search_call';\n\n /**\n * A unique ID for this specific tool call.\n */\n id?: string;\n }\n\n export interface FileSearchResultDelta {\n type: 'file_search_result';\n\n result?: Array<FileSearchResultDelta.Result>;\n }\n\n export namespace FileSearchResultDelta {\n /**\n * The result of the File Search.\n */\n export interface Result {\n /**\n * The name of the file search store.\n */\n file_search_store?: string;\n\n /**\n * The text of the search result.\n */\n text?: string;\n\n /**\n * The title of the search result.\n */\n title?: string;\n }\n }\n}\n\nexport interface ContentStart {\n /**\n * The content of the response.\n */\n content?: Content;\n\n /**\n * The event_id token to be used to resume the interaction stream, from this event.\n */\n event_id?: string;\n\n event_type?: 'content.start';\n\n index?: number;\n}\n\nexport interface ContentStop {\n /**\n * The event_id token to be used to resume the interaction stream, from this event.\n */\n event_id?: string;\n\n event_type?: 'content.stop';\n\n index?: number;\n}\n\n/**\n * Configuration for the Deep Research agent.\n */\nexport interface DeepResearchAgentConfig {\n /**\n * Whether to include thought summaries in the response.\n */\n thinking_summaries?: 'auto' | 'none';\n\n type?: 'deep-research';\n}\n\n/**\n * A document content block.\n */\nexport interface DocumentContent {\n type: 'document';\n\n /**\n * The document content.\n */\n data?: string;\n\n /**\n * The mime type of the document.\n */\n mime_type?: DocumentMimeType;\n\n /**\n * The URI of the document.\n */\n uri?: string;\n}\n\n/**\n * The mime type of the document.\n */\nexport type DocumentMimeType = (string & {}) | 'application/pdf';\n\n/**\n * Configuration for dynamic agents.\n */\nexport interface DynamicAgentConfig {\n type?: 'dynamic';\n\n [k: string]: unknown;\n}\n\nexport interface ErrorEvent {\n /**\n * Error message from an interaction.\n */\n error?: ErrorEvent.Error;\n\n /**\n * The event_id token to be used to resume the interaction stream, from this event.\n */\n event_id?: string;\n\n event_type?: 'error';\n}\n\nexport namespace ErrorEvent {\n /**\n * Error message from an interaction.\n */\n export interface Error {\n /**\n * A URI that identifies the error type.\n */\n code?: string;\n\n /**\n * A human-readable error message.\n */\n message?: string;\n }\n}\n\n/**\n * File Search content.\n */\nexport interface FileSearchCallContent {\n type: 'file_search_call';\n\n /**\n * A unique ID for this specific tool call.\n */\n id?: string;\n}\n\n/**\n * File Search result content.\n */\nexport interface FileSearchResultContent {\n type: 'file_search_result';\n\n /**\n * The results of the File Search.\n */\n result?: Array<FileSearchResultContent.Result>;\n}\n\nexport namespace FileSearchResultContent {\n /**\n * The result of the File Search.\n */\n export interface Result {\n /**\n * The name of the file search store.\n */\n file_search_store?: string;\n\n /**\n * The text of the search result.\n */\n text?: string;\n\n /**\n * The title of the search result.\n */\n title?: string;\n }\n}\n\n/**\n * A tool that can be used by the model.\n */\nexport interface Function {\n type: 'function';\n\n /**\n * A description of the function.\n */\n description?: string;\n\n /**\n * The name of the function.\n */\n name?: string;\n\n /**\n * The JSON Schema for the function's parameters.\n */\n parameters?: unknown;\n}\n\n/**\n * A function tool call content block.\n */\nexport interface FunctionCallContent {\n /**\n * A unique ID for this specific tool call.\n */\n id: string;\n\n /**\n * The arguments to pass to the function.\n */\n arguments: { [key: string]: unknown };\n\n /**\n * The name of the tool to call.\n */\n name: string;\n\n type: 'function_call';\n}\n\n/**\n * A function tool result content block.\n */\nexport interface FunctionResultContent {\n /**\n * ID to match the ID from the function call block.\n */\n call_id: string;\n\n /**\n * The result of the tool call.\n */\n result: FunctionResultContent.Items | unknown | string;\n\n type: 'function_result';\n\n /**\n * Whether the tool call resulted in an error.\n */\n is_error?: boolean;\n\n /**\n * The name of the tool that was called.\n */\n name?: string;\n}\n\nexport namespace FunctionResultContent {\n export interface Items {\n items?: Array<InteractionsAPI.TextContent | InteractionsAPI.ImageContent>;\n }\n}\n\n/**\n * Configuration parameters for model interactions.\n */\nexport interface GenerationConfig {\n /**\n * Configuration for image interaction.\n */\n image_config?: ImageConfig;\n\n /**\n * The maximum number of tokens to include in the response.\n */\n max_output_tokens?: number;\n\n /**\n * Seed used in decoding for reproducibility.\n */\n seed?: number;\n\n /**\n * Configuration for speech interaction.\n */\n speech_config?: Array<SpeechConfig>;\n\n /**\n * A list of character sequences that will stop output interaction.\n */\n stop_sequences?: Array<string>;\n\n /**\n * Controls the randomness of the output.\n */\n temperature?: number;\n\n /**\n * The level of thought tokens that the model should generate.\n */\n thinking_level?: ThinkingLevel;\n\n /**\n * Whether to include thought summaries in the response.\n */\n thinking_summaries?: 'auto' | 'none';\n\n /**\n * The tool choice for the interaction.\n */\n tool_choice?: ToolChoice;\n\n /**\n * The maximum cumulative probability of tokens to consider when sampling.\n */\n top_p?: number;\n}\n\n/**\n * The arguments to pass to Google Search.\n */\nexport interface GoogleSearchCallArguments {\n /**\n * Web search queries for the following-up web search.\n */\n queries?: Array<string>;\n}\n\n/**\n * Google Search content.\n */\nexport interface GoogleSearchCallContent {\n type: 'google_search_call';\n\n /**\n * A unique ID for this specific tool call.\n */\n id?: string;\n\n /**\n * The arguments to pass to Google Search.\n */\n arguments?: GoogleSearchCallArguments;\n}\n\n/**\n * The result of the Google Search.\n */\nexport interface GoogleSearchResult {\n /**\n * Web content snippet that can be embedded in a web page or an app webview.\n */\n rendered_content?: string;\n\n /**\n * Title of the search result.\n */\n title?: string;\n\n /**\n * URI reference of the search result.\n */\n url?: string;\n}\n\n/**\n * Google Search result content.\n */\nexport interface GoogleSearchResultContent {\n type: 'google_search_result';\n\n /**\n * ID to match the ID from the google search call block.\n */\n call_id?: string;\n\n /**\n * Whether the Google Search resulted in an error.\n */\n is_error?: boolean;\n\n /**\n * The results of the Google Search.\n */\n result?: Array<GoogleSearchResult>;\n\n /**\n * The signature of the Google Search result.\n */\n signature?: string;\n}\n\n/**\n * The configuration for image interaction.\n */\nexport interface ImageConfig {\n aspect_ratio?: '1:1' | '2:3' | '3:2' | '3:4' | '4:3' | '4:5' | '5:4' | '9:16' | '16:9' | '21:9';\n\n image_size?: '1K' | '2K' | '4K';\n}\n\n/**\n * An image content block.\n */\nexport interface ImageContent {\n type: 'image';\n\n /**\n * The image content.\n */\n data?: string;\n\n /**\n * The mime type of the image.\n */\n mime_type?: ImageMimeType;\n\n /**\n * The resolution of the media.\n */\n resolution?: 'low' | 'medium' | 'high' | 'ultra_high';\n\n /**\n * The URI of the image.\n */\n uri?: string;\n}\n\n/**\n * The mime type of the image.\n */\nexport type ImageMimeType =\n | 'image/png'\n | 'image/jpeg'\n | 'image/webp'\n | 'image/heic'\n | 'image/heif'\n | (string & {});\n\n/**\n * The Interaction resource.\n */\nexport interface Interaction {\n /**\n * Output only. A unique identifier for the interaction completion.\n */\n id: string;\n\n /**\n * Output only. The status of the interaction.\n */\n status: 'in_progress' | 'requires_action' | 'completed' | 'failed' | 'cancelled' | 'incomplete';\n\n /**\n * The name of the `Agent` used for generating the interaction.\n */\n agent?: (string & {}) | 'deep-research-pro-preview-12-2025';\n\n /**\n * Output only. The time at which the response was created in ISO 8601 format\n * (YYYY-MM-DDThh:mm:ssZ).\n */\n created?: string;\n\n /**\n * The name of the `Model` used for generating the interaction.\n */\n model?: Model;\n\n /**\n * Output only. Responses from the model.\n */\n outputs?: Array<Content>;\n\n /**\n * The ID of the previous interaction, if any.\n */\n previous_interaction_id?: string;\n\n /**\n * Output only. The role of the interaction.\n */\n role?: string;\n\n /**\n * Output only. The time at which the response was last updated in ISO 8601 format\n * (YYYY-MM-DDThh:mm:ssZ).\n */\n updated?: string;\n\n /**\n * Output only. Statistics on the interaction request's token usage.\n */\n usage?: Usage;\n}\n\nexport interface InteractionCompleteEvent {\n /**\n * The event_id token to be used to resume the interaction stream, from this event.\n */\n event_id?: string;\n\n event_type?: 'interaction.complete';\n\n /**\n * The Interaction resource.\n */\n interaction?: Interaction;\n}\n\nexport type InteractionSSEEvent =\n | InteractionStartEvent\n | InteractionCompleteEvent\n | InteractionStatusUpdate\n | ContentStart\n | ContentDelta\n | ContentStop\n | ErrorEvent;\n\nexport interface InteractionStartEvent {\n /**\n * The event_id token to be used to resume the interaction stream, from this event.\n */\n event_id?: string;\n\n event_type?: 'interaction.start';\n\n /**\n * The Interaction resource.\n */\n interaction?: Interaction;\n}\n\nexport interface InteractionStatusUpdate {\n /**\n * The event_id token to be used to resume the interaction stream, from this event.\n */\n event_id?: string;\n\n event_type?: 'interaction.status_update';\n\n interaction_id?: string;\n\n status?: 'in_progress' | 'requires_action' | 'completed' | 'failed' | 'cancelled' | 'incomplete';\n}\n\n/**\n * MCPServer tool call content.\n */\nexport interface MCPServerToolCallContent {\n /**\n * A unique ID for this specific tool call.\n */\n id: string;\n\n /**\n * The JSON object of arguments for the function.\n */\n arguments: { [key: string]: unknown };\n\n /**\n * The name of the tool which was called.\n */\n name: string;\n\n /**\n * The name of the used MCP server.\n */\n server_name: string;\n\n type: 'mcp_server_tool_call';\n}\n\n/**\n * MCPServer tool result content.\n */\nexport interface MCPServerToolResultContent {\n /**\n * ID to match the ID from the MCP server tool call block.\n */\n call_id: string;\n\n /**\n * The result of the tool call.\n */\n result: MCPServerToolResultContent.Items | unknown | string;\n\n type: 'mcp_server_tool_result';\n\n /**\n * Name of the tool which is called for this specific tool call.\n */\n name?: string;\n\n /**\n * The name of the used MCP server.\n */\n server_name?: string;\n}\n\nexport namespace MCPServerToolResultContent {\n export interface Items {\n items?: Array<InteractionsAPI.TextContent | InteractionsAPI.ImageContent>;\n }\n}\n\n/**\n * The model that will complete your prompt.\\n\\nSee [models](https://ai.google.dev/gemini-api/docs/models) for additional details.\n */\nexport type Model =\n | 'gemini-2.5-flash'\n | 'gemini-2.5-flash-image'\n | 'gemini-2.5-flash-lite'\n | 'gemini-2.5-flash-lite-preview-09-2025'\n | 'gemini-2.5-flash-native-audio-preview-12-2025'\n | 'gemini-2.5-flash-preview-09-2025'\n | 'gemini-2.5-flash-preview-tts'\n | 'gemini-2.5-pro'\n | 'gemini-2.5-pro-preview-tts'\n | 'gemini-3-flash-preview'\n | 'gemini-3-pro-image-preview'\n | 'gemini-3-pro-preview'\n | (string & {});\n\n/**\n * The configuration for speech interaction.\n */\nexport interface SpeechConfig {\n /**\n * The language of the speech.\n */\n language?: string;\n\n /**\n * The speaker's name, it should match the speaker name given in the prompt.\n */\n speaker?: string;\n\n /**\n * The voice of the speaker.\n */\n voice?: string;\n}\n\n/**\n * A text content block.\n */\nexport interface TextContent {\n type: 'text';\n\n /**\n * Citation information for model-generated content.\n */\n annotations?: Array<Annotation>;\n\n /**\n * The text content.\n */\n text?: string;\n}\n\nexport type ThinkingLevel = 'minimal' | 'low' | 'medium' | 'high';\n\n/**\n * A thought content block.\n */\nexport interface ThoughtContent {\n type: 'thought';\n\n /**\n * Signature to match the backend source to be part of the generation.\n */\n signature?: string;\n\n /**\n * A summary of the thought.\n */\n summary?: Array<TextContent | ImageContent>;\n}\n\n/**\n * A tool that can be used by the model.\n */\nexport type Tool =\n | Function\n | Tool.GoogleSearch\n | Tool.CodeExecution\n | Tool.URLContext\n | Tool.ComputerUse\n | Tool.MCPServer\n | Tool.FileSearch;\n\nexport namespace Tool {\n /**\n * A tool that can be used by the model to search Google.\n */\n export interface GoogleSearch {\n type: 'google_search';\n }\n\n /**\n * A tool that can be used by the model to execute code.\n */\n export interface CodeExecution {\n type: 'code_execution';\n }\n\n /**\n * A tool that can be used by the model to fetch URL context.\n */\n export interface URLContext {\n type: 'url_context';\n }\n\n /**\n * A tool that can be used by the model to interact with the computer.\n */\n export interface ComputerUse {\n type: 'computer_use';\n\n /**\n * The environment being operated.\n */\n environment?: 'browser';\n\n /**\n * The list of predefined functions that are excluded from the model call.\n */\n excludedPredefinedFunctions?: Array<string>;\n }\n\n /**\n * A MCPServer is a server that can be called by the model to perform actions.\n */\n export interface MCPServer {\n type: 'mcp_server';\n\n /**\n * The allowed tools.\n */\n allowed_tools?: Array<InteractionsAPI.AllowedTools>;\n\n /**\n * Optional: Fields for authentication headers, timeouts, etc., if needed.\n */\n headers?: { [key: string]: string };\n\n /**\n * The name of the MCPServer.\n */\n name?: string;\n\n /**\n * The full URL for the MCPServer endpoint.\n * Example: \"https://api.example.com/mcp\"\n */\n url?: string;\n }\n\n /**\n * A tool that can be used by the model to search files.\n */\n export interface FileSearch {\n type: 'file_search';\n\n /**\n * The file search store names to search.\n */\n file_search_store_names?: Array<string>;\n\n /**\n * Metadata filter to apply to the semantic retrieval documents and chunks.\n */\n metadata_filter?: string;\n\n /**\n * The number of semantic retrieval chunks to retrieve.\n */\n top_k?: number;\n }\n}\n\n/**\n * The configuration for tool choice.\n */\nexport type ToolChoice = ToolChoiceType | ToolChoiceConfig;\n\nexport interface ToolChoiceConfig {\n /**\n * The configuration for allowed tools.\n */\n allowed_tools?: AllowedTools;\n}\n\nexport type ToolChoiceType = 'auto' | 'any' | 'none' | 'validated';\n\nexport interface Turn {\n /**\n * The content of the turn.\n */\n content?: string | Array<Content>;\n\n /**\n * The originator of this turn. Must be user for input or model for\n * model output.\n */\n role?: string;\n}\n\n/**\n * The arguments to pass to the URL context.\n */\nexport interface URLContextCallArguments {\n /**\n * The URLs to fetch.\n */\n urls?: Array<string>;\n}\n\n/**\n * URL context content.\n */\nexport interface URLContextCallContent {\n type: 'url_context_call';\n\n /**\n * A unique ID for this specific tool call.\n */\n id?: string;\n\n /**\n * The arguments to pass to the URL context.\n */\n arguments?: URLContextCallArguments;\n}\n\n/**\n * The result of the URL context.\n */\nexport interface URLContextResult {\n /**\n * The status of the URL retrieval.\n */\n status?: 'success' | 'error' | 'paywall' | 'unsafe';\n\n /**\n * The URL that was fetched.\n */\n url?: string;\n}\n\n/**\n * URL context result content.\n */\nexport interface URLContextResultContent {\n type: 'url_context_result';\n\n /**\n * ID to match the ID from the url context call block.\n */\n call_id?: string;\n\n /**\n * Whether the URL context resulted in an error.\n */\n is_error?: boolean;\n\n /**\n * The results of the URL context.\n */\n result?: Array<URLContextResult>;\n\n /**\n * The signature of the URL context result.\n */\n signature?: string;\n}\n\n/**\n * Statistics on the interaction request's token usage.\n */\nexport interface Usage {\n /**\n * A breakdown of cached token usage by modality.\n */\n cached_tokens_by_modality?: Array<Usage.CachedTokensByModality>;\n\n /**\n * A breakdown of input token usage by modality.\n */\n input_tokens_by_modality?: Array<Usage.InputTokensByModality>;\n\n /**\n * A breakdown of output token usage by modality.\n */\n output_tokens_by_modality?: Array<Usage.OutputTokensByModality>;\n\n /**\n * A breakdown of tool-use token usage by modality.\n */\n tool_use_tokens_by_modality?: Array<Usage.ToolUseTokensByModality>;\n\n /**\n * Number of tokens in the cached part of the prompt (the cached content).\n */\n total_cached_tokens?: number;\n\n /**\n * Number of tokens in the prompt (context).\n */\n total_input_tokens?: number;\n\n /**\n * Total number of tokens across all the generated responses.\n */\n total_output_tokens?: number;\n\n /**\n * Number of tokens of thoughts for thinking models.\n */\n total_thought_tokens?: number;\n\n /**\n * Total token count for the interaction request (prompt + responses + other\n * internal tokens).\n */\n total_tokens?: number;\n\n /**\n * Number of tokens present in tool-use prompt(s).\n */\n total_tool_use_tokens?: number;\n}\n\nexport namespace Usage {\n /**\n * The token count for a single response modality.\n */\n export interface CachedTokensByModality {\n /**\n * The modality associated with the token count.\n */\n modality?: 'text' | 'image' | 'audio';\n\n /**\n * Number of tokens for the modality.\n */\n tokens?: number;\n }\n\n /**\n * The token count for a single response modality.\n */\n export interface InputTokensByModality {\n /**\n * The modality associated with the token count.\n */\n modality?: 'text' | 'image' | 'audio';\n\n /**\n * Number of tokens for the modality.\n */\n tokens?: number;\n }\n\n /**\n * The token count for a single response modality.\n */\n export interface OutputTokensByModality {\n /**\n * The modality associated with the token count.\n */\n modality?: 'text' | 'image' | 'audio';\n\n /**\n * Number of tokens for the modality.\n */\n tokens?: number;\n }\n\n /**\n * The token count for a single response modality.\n */\n export interface ToolUseTokensByModality {\n /**\n * The modality associated with the token count.\n */\n modality?: 'text' | 'image' | 'audio';\n\n /**\n * Number of tokens for the modality.\n */\n tokens?: number;\n }\n}\n\n/**\n * A video content block.\n */\nexport interface VideoContent {\n type: 'video';\n\n /**\n * The video content.\n */\n data?: string;\n\n /**\n * The mime type of the video.\n */\n mime_type?: VideoMimeType;\n\n /**\n * The resolution of the media.\n */\n resolution?: 'low' | 'medium' | 'high' | 'ultra_high';\n\n /**\n * The URI of the video.\n */\n uri?: string;\n}\n\n/**\n * The mime type of the video.\n */\nexport type VideoMimeType =\n | 'video/mp4'\n | 'video/mpeg'\n | 'video/mov'\n | 'video/avi'\n | 'video/x-flv'\n | 'video/mpg'\n | 'video/webm'\n | 'video/wmv'\n | 'video/3gpp'\n | (string & {});\n\nexport type InteractionDeleteResponse = unknown;\n\nexport type InteractionCreateParams =\n | CreateModelInteractionParamsNonStreaming\n | CreateModelInteractionParamsStreaming\n | CreateAgentInteractionParamsNonStreaming\n | CreateAgentInteractionParamsStreaming;\n\nexport interface BaseCreateModelInteractionParams {\n /**\n * Path param: Which version of the API to use.\n */\n api_version?: string;\n\n /**\n * Body param: The inputs for the interaction.\n */\n input:\n | string\n | Array<Content>\n | Array<Turn>\n | TextContent\n | ImageContent\n | AudioContent\n | DocumentContent\n | VideoContent\n | ThoughtContent\n | FunctionCallContent\n | FunctionResultContent\n | CodeExecutionCallContent\n | CodeExecutionResultContent\n | URLContextCallContent\n | URLContextResultContent\n | GoogleSearchCallContent\n | GoogleSearchResultContent\n | MCPServerToolCallContent\n | MCPServerToolResultContent\n | FileSearchCallContent\n | FileSearchResultContent;\n\n /**\n * Body param: The name of the `Model` used for generating the interaction.\n */\n model: Model;\n\n /**\n * Body param: Input only. Whether to run the model interaction in the background.\n */\n background?: boolean;\n\n /**\n * Body param: Input only. Configuration parameters for the model interaction.\n */\n generation_config?: GenerationConfig;\n\n /**\n * Body param: The ID of the previous interaction, if any.\n */\n previous_interaction_id?: string;\n\n /**\n * Body param: Enforces that the generated response is a JSON object that complies with\n * the JSON schema specified in this field.\n */\n response_format?: unknown;\n\n /**\n * Body param: The mime type of the response. This is required if response_format is set.\n */\n response_mime_type?: string;\n\n /**\n * Body param: The requested modalities of the response (TEXT, IMAGE, AUDIO).\n */\n response_modalities?: Array<'text' | 'image' | 'audio'>;\n\n /**\n * Body param: Input only. Whether to store the response and request for later retrieval.\n */\n store?: boolean;\n\n /**\n * Body param: Input only. Whether the interaction will be streamed.\n */\n stream?: boolean;\n\n /**\n * Body param: System instruction for the interaction.\n */\n system_instruction?: string;\n\n /**\n * Body param: A list of tool declarations the model may call during interaction.\n */\n tools?: Array<Tool>;\n}\n\nexport interface BaseCreateAgentInteractionParams {\n /**\n * Path param: Which version of the API to use.\n */\n api_version?: string;\n\n /**\n * Body param: The name of the `Agent` used for generating the interaction.\n */\n agent: (string & {}) | 'deep-research-pro-preview-12-2025';\n\n /**\n * Body param: The inputs for the interaction.\n */\n input:\n | string\n | Array<Content>\n | Array<Turn>\n | TextContent\n | ImageContent\n | AudioContent\n | DocumentContent\n | VideoContent\n | ThoughtContent\n | FunctionCallContent\n | FunctionResultContent\n | CodeExecutionCallContent\n | CodeExecutionResultContent\n | URLContextCallContent\n | URLContextResultContent\n | GoogleSearchCallContent\n | GoogleSearchResultContent\n | MCPServerToolCallContent\n | MCPServerToolResultContent\n | FileSearchCallContent\n | FileSearchResultContent;\n\n /**\n * Body param: Configuration for the agent.\n */\n agent_config?: DynamicAgentConfig | DeepResearchAgentConfig;\n\n /**\n * Body param: Input only. Whether to run the model interaction in the background.\n */\n background?: boolean;\n\n /**\n * Body param: The ID of the previous interaction, if any.\n */\n previous_interaction_id?: string;\n\n /**\n * Body param: Enforces that the generated response is a JSON object that complies with\n * the JSON schema specified in this field.\n */\n response_format?: unknown;\n\n /**\n * Body param: The mime type of the response. This is required if response_format is set.\n */\n response_mime_type?: string;\n\n /**\n * Body param: The requested modalities of the response (TEXT, IMAGE, AUDIO).\n */\n response_modalities?: Array<'text' | 'image' | 'audio'>;\n\n /**\n * Body param: Input only. Whether to store the response and request for later retrieval.\n */\n store?: boolean;\n\n /**\n * Body param: Input only. Whether the interaction will be streamed.\n */\n stream?: boolean;\n\n /**\n * Body param: System instruction for the interaction.\n */\n system_instruction?: string;\n\n /**\n * Body param: A list of tool declarations the model may call during interaction.\n */\n tools?: Array<Tool>;\n}\n\nexport interface CreateModelInteractionParamsNonStreaming extends BaseCreateModelInteractionParams {\n /**\n * Body param: Input only. Whether the interaction will be streamed.\n */\n stream?: false;\n}\n\nexport interface CreateModelInteractionParamsStreaming extends BaseCreateModelInteractionParams {\n /**\n * Body param: Input only. Whether the interaction will be streamed.\n */\n stream: true;\n}\n\nexport interface CreateAgentInteractionParamsNonStreaming extends BaseCreateAgentInteractionParams {\n /**\n * Body param: Input only. Whether the interaction will be streamed.\n */\n stream?: false;\n}\n\nexport interface CreateAgentInteractionParamsStreaming extends BaseCreateAgentInteractionParams {\n /**\n * Body param: Input only. Whether the interaction will be streamed.\n */\n stream: true;\n}\n\nexport interface InteractionDeleteParams {\n /**\n * Which version of the API to use.\n */\n api_version?: string;\n}\n\nexport interface InteractionCancelParams {\n /**\n * Which version of the API to use.\n */\n api_version?: string;\n}\n\nexport type InteractionGetParams = InteractionGetParamsNonStreaming | InteractionGetParamsStreaming;\n\nexport interface InteractionGetParamsBase {\n /**\n * Path param: Which version of the API to use.\n */\n api_version?: string;\n\n /**\n * Query param: If set to true, includes the input in the response.\n */\n include_input?: boolean;\n\n /**\n * Query param: Optional. If set, resumes the interaction stream from the next chunk after the event marked by the event id. Can only be used if `stream` is true.\n */\n last_event_id?: string;\n\n /**\n * Query param: If set to true, the generated content will be streamed incrementally.\n */\n stream?: boolean;\n}\n\nexport namespace InteractionGetParams {\n export type InteractionGetParamsNonStreaming = InteractionsAPI.InteractionGetParamsNonStreaming;\n export type InteractionGetParamsStreaming = InteractionsAPI.InteractionGetParamsStreaming;\n}\n\nexport interface InteractionGetParamsNonStreaming extends InteractionGetParamsBase {\n /**\n * Query param: If set to true, the generated content will be streamed incrementally.\n */\n stream?: false;\n}\n\nexport interface InteractionGetParamsStreaming extends InteractionGetParamsBase {\n /**\n * Query param: If set to true, the generated content will be streamed incrementally.\n */\n stream: true;\n}\n\nexport declare namespace Interactions {\n export {\n type AllowedTools as AllowedTools,\n type Annotation as Annotation,\n type AudioContent as AudioContent,\n type AudioMimeType as AudioMimeType,\n type CodeExecutionCallArguments as CodeExecutionCallArguments,\n type CodeExecutionCallContent as CodeExecutionCallContent,\n type CodeExecutionResultContent as CodeExecutionResultContent,\n type Content as Content,\n type ContentDelta as ContentDelta,\n type ContentStart as ContentStart,\n type ContentStop as ContentStop,\n type DeepResearchAgentConfig as DeepResearchAgentConfig,\n type DocumentContent as DocumentContent,\n type DocumentMimeType as DocumentMimeType,\n type DynamicAgentConfig as DynamicAgentConfig,\n type ErrorEvent as ErrorEvent,\n type FileSearchCallContent as FileSearchCallContent,\n type FileSearchResultContent as FileSearchResultContent,\n type Function as Function,\n type FunctionCallContent as FunctionCallContent,\n type FunctionResultContent as FunctionResultContent,\n type GenerationConfig as GenerationConfig,\n type GoogleSearchCallArguments as GoogleSearchCallArguments,\n type GoogleSearchCallContent as GoogleSearchCallContent,\n type GoogleSearchResult as GoogleSearchResult,\n type GoogleSearchResultContent as GoogleSearchResultContent,\n type ImageConfig as ImageConfig,\n type ImageContent as ImageContent,\n type ImageMimeType as ImageMimeType,\n type Interaction as Interaction,\n type InteractionCompleteEvent as InteractionCompleteEvent,\n type InteractionSSEEvent as InteractionSSEEvent,\n type InteractionStartEvent as InteractionStartEvent,\n type InteractionStatusUpdate as InteractionStatusUpdate,\n type MCPServerToolCallContent as MCPServerToolCallContent,\n type MCPServerToolResultContent as MCPServerToolResultContent,\n type Model as Model,\n type SpeechConfig as SpeechConfig,\n type TextContent as TextContent,\n type ThinkingLevel as ThinkingLevel,\n type ThoughtContent as ThoughtContent,\n type Tool as Tool,\n type ToolChoice as ToolChoice,\n type ToolChoiceConfig as ToolChoiceConfig,\n type ToolChoiceType as ToolChoiceType,\n type Turn as Turn,\n type URLContextCallArguments as URLContextCallArguments,\n type URLContextCallContent as URLContextCallContent,\n type URLContextResult as URLContextResult,\n type URLContextResultContent as URLContextResultContent,\n type Usage as Usage,\n type VideoContent as VideoContent,\n type VideoMimeType as VideoMimeType,\n type InteractionDeleteResponse as InteractionDeleteResponse,\n type InteractionCreateParams as InteractionCreateParams,\n type CreateModelInteractionParamsNonStreaming as CreateModelInteractionParamsNonStreaming,\n type CreateModelInteractionParamsStreaming as CreateModelInteractionParamsStreaming,\n type CreateAgentInteractionParamsNonStreaming as CreateAgentInteractionParamsNonStreaming,\n type CreateAgentInteractionParamsStreaming as CreateAgentInteractionParamsStreaming,\n type InteractionDeleteParams as InteractionDeleteParams,\n type InteractionCancelParams as InteractionCancelParams,\n type InteractionGetParams as InteractionGetParams,\n type InteractionGetParamsNonStreaming as InteractionGetParamsNonStreaming,\n type InteractionGetParamsStreaming as InteractionGetParamsStreaming,\n };\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nexport function concatBytes(buffers: Uint8Array[]): Uint8Array {\n let length = 0;\n for (const buffer of buffers) {\n length += buffer.length;\n }\n const output = new Uint8Array(length);\n let index = 0;\n for (const buffer of buffers) {\n output.set(buffer, index);\n index += buffer.length;\n }\n\n return output;\n}\n\nlet encodeUTF8_: (str: string) => Uint8Array;\nexport function encodeUTF8(str: string) {\n let encoder;\n return (\n encodeUTF8_ ??\n ((encoder = new (globalThis as any).TextEncoder()), (encodeUTF8_ = encoder.encode.bind(encoder)))\n )(str);\n}\n\nlet decodeUTF8_: (bytes: Uint8Array) => string;\nexport function decodeUTF8(bytes: Uint8Array) {\n let decoder;\n return (\n decodeUTF8_ ??\n ((decoder = new (globalThis as any).TextDecoder()), (decodeUTF8_ = decoder.decode.bind(decoder)))\n )(bytes);\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { concatBytes, decodeUTF8, encodeUTF8 } from '../utils/bytes.js';\n\nexport type Bytes = string | ArrayBuffer | Uint8Array | null | undefined;\n\n/**\n * A re-implementation of httpx's `LineDecoder` in Python that handles incrementally\n * reading lines from text.\n *\n * https://github.com/encode/httpx/blob/920333ea98118e9cf617f246905d7b202510941c/httpx/_decoders.py#L258\n */\nexport class LineDecoder {\n // prettier-ignore\n static NEWLINE_CHARS = new Set(['\\n', '\\r']);\n static NEWLINE_REGEXP = /\\r\\n|[\\n\\r]/g;\n\n private buffer: Uint8Array;\n private carriageReturnIndex: number | null;\n\n constructor() {\n this.buffer = new Uint8Array();\n this.carriageReturnIndex = null;\n }\n\n decode(chunk: Bytes): string[] {\n if (chunk == null) {\n return [];\n }\n\n const binaryChunk =\n chunk instanceof ArrayBuffer ? new Uint8Array(chunk)\n : typeof chunk === 'string' ? encodeUTF8(chunk)\n : chunk;\n\n this.buffer = concatBytes([this.buffer, binaryChunk]);\n\n const lines: string[] = [];\n let patternIndex;\n while ((patternIndex = findNewlineIndex(this.buffer, this.carriageReturnIndex)) != null) {\n if (patternIndex.carriage && this.carriageReturnIndex == null) {\n // skip until we either get a corresponding `\\n`, a new `\\r` or nothing\n this.carriageReturnIndex = patternIndex.index;\n continue;\n }\n\n // we got double \\r or \\rtext\\n\n if (\n this.carriageReturnIndex != null &&\n (patternIndex.index !== this.carriageReturnIndex + 1 || patternIndex.carriage)\n ) {\n lines.push(decodeUTF8(this.buffer.subarray(0, this.carriageReturnIndex - 1)));\n this.buffer = this.buffer.subarray(this.carriageReturnIndex);\n this.carriageReturnIndex = null;\n continue;\n }\n\n const endIndex =\n this.carriageReturnIndex !== null ? patternIndex.preceding - 1 : patternIndex.preceding;\n\n const line = decodeUTF8(this.buffer.subarray(0, endIndex));\n lines.push(line);\n\n this.buffer = this.buffer.subarray(patternIndex.index);\n this.carriageReturnIndex = null;\n }\n\n return lines;\n }\n\n flush(): string[] {\n if (!this.buffer.length) {\n return [];\n }\n return this.decode('\\n');\n }\n}\n\n/**\n * This function searches the buffer for the end patterns, (\\r or \\n)\n * and returns an object with the index preceding the matched newline and the\n * index after the newline char. `null` is returned if no new line is found.\n *\n * ```ts\n * findNewLineIndex('abc\\ndef') -> { preceding: 2, index: 3 }\n * ```\n */\nfunction findNewlineIndex(\n buffer: Uint8Array,\n startIndex: number | null,\n): { preceding: number; index: number; carriage: boolean } | null {\n const newline = 0x0a; // \\n\n const carriage = 0x0d; // \\r\n\n for (let i = startIndex ?? 0; i < buffer.length; i++) {\n if (buffer[i] === newline) {\n return { preceding: i, index: i + 1, carriage: false };\n }\n\n if (buffer[i] === carriage) {\n return { preceding: i, index: i + 1, carriage: true };\n }\n }\n\n return null;\n}\n\nexport function findDoubleNewlineIndex(buffer: Uint8Array): number {\n // This function searches the buffer for the end patterns (\\r\\r, \\n\\n, \\r\\n\\r\\n)\n // and returns the index right after the first occurrence of any pattern,\n // or -1 if none of the patterns are found.\n const newline = 0x0a; // \\n\n const carriage = 0x0d; // \\r\n\n for (let i = 0; i < buffer.length - 1; i++) {\n if (buffer[i] === newline && buffer[i + 1] === newline) {\n // \\n\\n\n return i + 2;\n }\n if (buffer[i] === carriage && buffer[i + 1] === carriage) {\n // \\r\\r\n return i + 2;\n }\n if (\n buffer[i] === carriage &&\n buffer[i + 1] === newline &&\n i + 3 < buffer.length &&\n buffer[i + 2] === carriage &&\n buffer[i + 3] === newline\n ) {\n // \\r\\n\\r\\n\n return i + 4;\n }\n }\n\n return -1;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nimport { hasOwn } from './values.js';\nimport { type BaseGeminiNextGenAPIClient } from '../../client.js';\nimport { RequestOptions } from '../request-options.js';\n\ntype LogFn = (message: string, ...rest: unknown[]) => void;\nexport type Logger = {\n error: LogFn;\n warn: LogFn;\n info: LogFn;\n debug: LogFn;\n};\nexport type LogLevel = 'off' | 'error' | 'warn' | 'info' | 'debug';\n\nconst levelNumbers = {\n off: 0,\n error: 200,\n warn: 300,\n info: 400,\n debug: 500,\n};\n\nexport const parseLogLevel = (\n maybeLevel: string | undefined,\n sourceName: string,\n client: BaseGeminiNextGenAPIClient,\n): LogLevel | undefined => {\n if (!maybeLevel) {\n return undefined;\n }\n if (hasOwn(levelNumbers, maybeLevel)) {\n return maybeLevel;\n }\n loggerFor(client).warn(\n `${sourceName} was set to ${JSON.stringify(maybeLevel)}, expected one of ${JSON.stringify(\n Object.keys(levelNumbers),\n )}`,\n );\n return undefined;\n};\n\nfunction noop() {}\n\nfunction makeLogFn(fnLevel: keyof Logger, logger: Logger | undefined, logLevel: LogLevel) {\n if (!logger || levelNumbers[fnLevel] > levelNumbers[logLevel]) {\n return noop;\n } else {\n // Don't wrap logger functions, we want the stacktrace intact!\n return logger[fnLevel].bind(logger);\n }\n}\n\nconst noopLogger = {\n error: noop,\n warn: noop,\n info: noop,\n debug: noop,\n};\n\nlet cachedLoggers = /* @__PURE__ */ new WeakMap<Logger, [LogLevel, Logger]>();\n\nexport function loggerFor(client: BaseGeminiNextGenAPIClient): Logger {\n const logger = client.logger;\n const logLevel = client.logLevel ?? 'off';\n if (!logger) {\n return noopLogger;\n }\n\n const cachedLogger = cachedLoggers.get(logger);\n if (cachedLogger && cachedLogger[0] === logLevel) {\n return cachedLogger[1];\n }\n\n const levelLogger = {\n error: makeLogFn('error', logger, logLevel),\n warn: makeLogFn('warn', logger, logLevel),\n info: makeLogFn('info', logger, logLevel),\n debug: makeLogFn('debug', logger, logLevel),\n };\n\n cachedLoggers.set(logger, [logLevel, levelLogger]);\n\n return levelLogger;\n}\n\nexport const formatRequestDetails = (details: {\n options?: RequestOptions | undefined;\n headers?: Headers | Record<string, string> | undefined;\n retryOfRequestLogID?: string | undefined;\n retryOf?: string | undefined;\n url?: string | undefined;\n status?: number | undefined;\n method?: string | undefined;\n durationMs?: number | undefined;\n message?: unknown;\n body?: unknown;\n}) => {\n if (details.options) {\n details.options = { ...details.options };\n delete details.options['headers']; // redundant + leaks internals\n }\n if (details.headers) {\n details.headers = Object.fromEntries(\n (details.headers instanceof Headers ? [...details.headers] : Object.entries(details.headers)).map(\n ([name, value]) => [\n name,\n (\n name.toLowerCase() === 'x-goog-api-key' ||\n name.toLowerCase() === 'authorization' ||\n name.toLowerCase() === 'cookie' ||\n name.toLowerCase() === 'set-cookie'\n ) ?\n '***'\n : value,\n ],\n ),\n );\n }\n if ('retryOfRequestLogID' in details) {\n if (details.retryOfRequestLogID) {\n details.retryOf = details.retryOfRequestLogID;\n }\n delete details.retryOfRequestLogID;\n }\n return details;\n};\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { GeminiNextGenAPIClientError } from './error.js';\nimport { type ReadableStream } from '../internal/shim-types.js';\nimport { makeReadableStream } from '../internal/shims.js';\nimport { findDoubleNewlineIndex, LineDecoder } from '../internal/decoders/line.js';\nimport { ReadableStreamToAsyncIterable } from '../internal/shims.js';\nimport { isAbortError } from '../internal/errors.js';\nimport { encodeUTF8 } from '../internal/utils/bytes.js';\nimport { loggerFor } from '../internal/utils/log.js';\nimport type { BaseGeminiNextGenAPIClient } from '../client.js';\n\ntype Bytes = string | ArrayBuffer | Uint8Array | null | undefined;\n\nexport type ServerSentEvent = {\n event: string | null;\n data: string;\n raw: string[];\n};\n\nexport class Stream<Item> implements AsyncIterable<Item> {\n controller: AbortController;\n private client: BaseGeminiNextGenAPIClient | undefined;\n\n constructor(\n private iterator: () => AsyncIterator<Item>,\n controller: AbortController,\n client?: BaseGeminiNextGenAPIClient,\n ) {\n this.controller = controller;\n this.client = client;\n }\n\n static fromSSEResponse<Item>(\n response: Response,\n controller: AbortController,\n client?: BaseGeminiNextGenAPIClient,\n ): Stream<Item> {\n let consumed = false;\n const logger = client ? loggerFor(client) : console;\n\n async function* iterator(): AsyncIterator<Item, any, undefined> {\n if (consumed) {\n throw new GeminiNextGenAPIClientError(\n 'Cannot iterate over a consumed stream, use `.tee()` to split the stream.',\n );\n }\n consumed = true;\n let done = false;\n try {\n for await (const sse of _iterSSEMessages(response, controller)) {\n if (done) continue;\n\n if (sse.data.startsWith('[DONE]')) {\n done = true;\n continue;\n } else {\n try {\n // @ts-ignore\n yield JSON.parse(sse.data);\n } catch (e) {\n logger.error(`Could not parse message into JSON:`, sse.data);\n logger.error(`From chunk:`, sse.raw);\n throw e;\n }\n }\n }\n done = true;\n } catch (e) {\n // If the user calls `stream.controller.abort()`, we should exit without throwing.\n if (isAbortError(e)) return;\n throw e;\n } finally {\n // If the user `break`s, abort the ongoing request.\n if (!done) controller.abort();\n }\n }\n\n return new Stream(iterator, controller, client);\n }\n\n /**\n * Generates a Stream from a newline-separated ReadableStream\n * where each item is a JSON value.\n */\n static fromReadableStream<Item>(\n readableStream: ReadableStream,\n controller: AbortController,\n client?: BaseGeminiNextGenAPIClient,\n ): Stream<Item> {\n let consumed = false;\n\n async function* iterLines(): AsyncGenerator<string, void, unknown> {\n const lineDecoder = new LineDecoder();\n\n const iter = ReadableStreamToAsyncIterable<Bytes>(readableStream);\n for await (const chunk of iter) {\n for (const line of lineDecoder.decode(chunk)) {\n yield line;\n }\n }\n\n for (const line of lineDecoder.flush()) {\n yield line;\n }\n }\n\n async function* iterator(): AsyncIterator<Item, any, undefined> {\n if (consumed) {\n throw new GeminiNextGenAPIClientError(\n 'Cannot iterate over a consumed stream, use `.tee()` to split the stream.',\n );\n }\n consumed = true;\n let done = false;\n try {\n for await (const line of iterLines()) {\n if (done) continue;\n // @ts-ignore\n if (line) yield JSON.parse(line);\n }\n done = true;\n } catch (e) {\n // If the user calls `stream.controller.abort()`, we should exit without throwing.\n if (isAbortError(e)) return;\n throw e;\n } finally {\n // If the user `break`s, abort the ongoing request.\n if (!done) controller.abort();\n }\n }\n\n return new Stream(iterator, controller, client);\n }\n\n [Symbol.asyncIterator](): AsyncIterator<Item> {\n return this.iterator();\n }\n\n /**\n * Splits the stream into two streams which can be\n * independently read from at different speeds.\n */\n tee(): [Stream<Item>, Stream<Item>] {\n const left: Array<Promise<IteratorResult<Item>>> = [];\n const right: Array<Promise<IteratorResult<Item>>> = [];\n const iterator = this.iterator();\n\n const teeIterator = (queue: Array<Promise<IteratorResult<Item>>>): AsyncIterator<Item> => {\n return {\n next: () => {\n if (queue.length === 0) {\n const result = iterator.next();\n left.push(result);\n right.push(result);\n }\n return queue.shift()!;\n },\n };\n };\n\n return [\n new Stream(() => teeIterator(left), this.controller, this.client),\n new Stream(() => teeIterator(right), this.controller, this.client),\n ];\n }\n\n /**\n * Converts this stream to a newline-separated ReadableStream of\n * JSON stringified values in the stream\n * which can be turned back into a Stream with `Stream.fromReadableStream()`.\n */\n toReadableStream(): ReadableStream {\n const self = this;\n let iter: AsyncIterator<Item>;\n\n return makeReadableStream({\n async start() {\n iter = self[Symbol.asyncIterator]();\n },\n async pull(ctrl: any) {\n try {\n const { value, done } = await iter.next();\n if (done) return ctrl.close();\n\n const bytes = encodeUTF8(JSON.stringify(value) + '\\n');\n\n ctrl.enqueue(bytes);\n } catch (err) {\n ctrl.error(err);\n }\n },\n async cancel() {\n await iter.return?.();\n },\n });\n }\n}\n\nexport async function* _iterSSEMessages(\n response: Response,\n controller: AbortController,\n): AsyncGenerator<ServerSentEvent, void, unknown> {\n if (!response.body) {\n controller.abort();\n if (\n typeof (globalThis as any).navigator !== 'undefined' &&\n (globalThis as any).navigator.product === 'ReactNative'\n ) {\n throw new GeminiNextGenAPIClientError(\n `The default react-native fetch implementation does not support streaming. Please use expo/fetch: https://docs.expo.dev/versions/latest/sdk/expo/#expofetch-api`,\n );\n }\n throw new GeminiNextGenAPIClientError(`Attempted to iterate over a response with no body`);\n }\n\n const sseDecoder = new SSEDecoder();\n const lineDecoder = new LineDecoder();\n\n const iter = ReadableStreamToAsyncIterable<Bytes>(response.body);\n for await (const sseChunk of iterSSEChunks(iter)) {\n for (const line of lineDecoder.decode(sseChunk)) {\n const sse = sseDecoder.decode(line);\n if (sse) yield sse;\n }\n }\n\n for (const line of lineDecoder.flush()) {\n const sse = sseDecoder.decode(line);\n if (sse) yield sse;\n }\n}\n\n/**\n * Given an async iterable iterator, iterates over it and yields full\n * SSE chunks, i.e. yields when a double new-line is encountered.\n */\nasync function* iterSSEChunks(iterator: AsyncIterableIterator<Bytes>): AsyncGenerator<Uint8Array> {\n let data = new Uint8Array();\n\n for await (const chunk of iterator) {\n if (chunk == null) {\n continue;\n }\n\n const binaryChunk =\n chunk instanceof ArrayBuffer ? new Uint8Array(chunk)\n : typeof chunk === 'string' ? encodeUTF8(chunk)\n : chunk;\n\n let newData = new Uint8Array(data.length + binaryChunk.length);\n newData.set(data);\n newData.set(binaryChunk, data.length);\n data = newData;\n\n let patternIndex;\n while ((patternIndex = findDoubleNewlineIndex(data)) !== -1) {\n yield data.slice(0, patternIndex);\n data = data.slice(patternIndex);\n }\n }\n\n if (data.length > 0) {\n yield data;\n }\n}\n\nclass SSEDecoder {\n private data: string[];\n private event: string | null;\n private chunks: string[];\n\n constructor() {\n this.event = null;\n this.data = [];\n this.chunks = [];\n }\n\n decode(line: string) {\n if (line.endsWith('\\r')) {\n line = line.substring(0, line.length - 1);\n }\n\n if (!line) {\n // empty line and we didn't previously encounter any messages\n if (!this.event && !this.data.length) return null;\n\n const sse: ServerSentEvent = {\n event: this.event,\n data: this.data.join('\\n'),\n raw: this.chunks,\n };\n\n this.event = null;\n this.data = [];\n this.chunks = [];\n\n return sse;\n }\n\n this.chunks.push(line);\n\n if (line.startsWith(':')) {\n return null;\n }\n\n let [fieldname, _, value] = partition(line, ':');\n\n if (value.startsWith(' ')) {\n value = value.substring(1);\n }\n\n if (fieldname === 'event') {\n this.event = value;\n } else if (fieldname === 'data') {\n this.data.push(value);\n }\n\n return null;\n }\n}\n\nfunction partition(str: string, delimiter: string): [string, string, string] {\n const index = str.indexOf(delimiter);\n if (index !== -1) {\n return [str.substring(0, index), delimiter, str.substring(index + delimiter.length)];\n }\n\n return [str, '', ''];\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nimport type { FinalRequestOptions } from './request-options.js';\nimport { Stream } from '../core/streaming.js';\nimport { type BaseGeminiNextGenAPIClient } from '../client.js';\nimport { formatRequestDetails, loggerFor } from './utils/log.js';\n\nexport type APIResponseProps = {\n response: Response;\n options: FinalRequestOptions;\n controller: AbortController;\n requestLogID: string;\n retryOfRequestLogID: string | undefined;\n startTime: number;\n};\n\nexport async function defaultParseResponse<T>(\n client: BaseGeminiNextGenAPIClient,\n props: APIResponseProps,\n): Promise<T> {\n const { response, requestLogID, retryOfRequestLogID, startTime } = props;\n const body = await (async () => {\n if (props.options.stream) {\n loggerFor(client).debug('response', response.status, response.url, response.headers, response.body);\n\n // Note: there is an invariant here that isn't represented in the type system\n // that if you set `stream: true` the response type must also be `Stream<T>`\n\n if (props.options.__streamClass) {\n return props.options.__streamClass.fromSSEResponse(response, props.controller, client) as any;\n }\n\n return Stream.fromSSEResponse(response, props.controller, client) as any;\n }\n\n // fetch refuses to read the body when the status code is 204.\n if (response.status === 204) {\n return null as T;\n }\n\n if (props.options.__binaryResponse) {\n return response as unknown as T;\n }\n\n const contentType = response.headers.get('content-type');\n const mediaType = contentType?.split(';')[0]?.trim();\n const isJSON = mediaType?.includes('application/json') || mediaType?.endsWith('+json');\n if (isJSON) {\n const contentLength = response.headers.get('content-length');\n if (contentLength === '0') {\n // if there is no content we can't do anything\n return undefined as T;\n }\n\n const json = await response.json();\n return json as T;\n }\n\n const text = await response.text();\n return text as unknown as T;\n })();\n loggerFor(client).debug(\n `[${requestLogID}] response parsed`,\n formatRequestDetails({\n retryOfRequestLogID,\n url: response.url,\n status: response.status,\n body,\n durationMs: Date.now() - startTime,\n }),\n );\n return body;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nimport { type BaseGeminiNextGenAPIClient } from '../client.js';\n\nimport { type PromiseOrValue } from '../internal/types.js';\nimport { APIResponseProps, defaultParseResponse } from '../internal/parse.js';\n\n/**\n * A subclass of `Promise` providing additional helper methods\n * for interacting with the SDK.\n */\nexport class APIPromise<T> extends Promise<T> {\n private parsedPromise: Promise<T> | undefined;\n private client: BaseGeminiNextGenAPIClient;\n\n constructor(\n client: BaseGeminiNextGenAPIClient,\n private responsePromise: Promise<APIResponseProps>,\n private parseResponse: (\n client: BaseGeminiNextGenAPIClient,\n props: APIResponseProps,\n ) => PromiseOrValue<T> = defaultParseResponse,\n ) {\n super((resolve) => {\n // this is maybe a bit weird but this has to be a no-op to not implicitly\n // parse the response body; instead .then, .catch, .finally are overridden\n // to parse the response\n resolve(null as any);\n });\n this.client = client;\n }\n\n _thenUnwrap<U>(transform: (data: T, props: APIResponseProps) => U): APIPromise<U> {\n return new APIPromise(this.client, this.responsePromise, async (client, props) =>\n transform(await this.parseResponse(client, props), props),\n );\n }\n\n /**\n * Gets the raw `Response` instance instead of parsing the response\n * data.\n *\n * If you want to parse the response body but still get the `Response`\n * instance, you can use {@link withResponse()}.\n *\n * 👋 Getting the wrong TypeScript type for `Response`?\n * Try setting `\"moduleResolution\": \"NodeNext\"` or add `\"lib\": [\"DOM\"]`\n * to your `tsconfig.json`.\n */\n asResponse(): Promise<Response> {\n return this.responsePromise.then((p) => p.response);\n }\n\n /**\n * Gets the parsed response data and the raw `Response` instance.\n *\n * If you just want to get the raw `Response` instance without parsing it,\n * you can use {@link asResponse()}.\n *\n * 👋 Getting the wrong TypeScript type for `Response`?\n * Try setting `\"moduleResolution\": \"NodeNext\"` or add `\"lib\": [\"DOM\"]`\n * to your `tsconfig.json`.\n */\n async withResponse(): Promise<{ data: T; response: Response }> {\n const [data, response] = await Promise.all([this.parse(), this.asResponse()]);\n return { data, response };\n }\n\n private parse(): Promise<T> {\n if (!this.parsedPromise) {\n this.parsedPromise = this.responsePromise.then((data) => this.parseResponse(this.client, data));\n }\n return this.parsedPromise;\n }\n\n override then<TResult1 = T, TResult2 = never>(\n onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null,\n onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null,\n ): Promise<TResult1 | TResult2> {\n return this.parse().then(onfulfilled, onrejected);\n }\n\n override catch<TResult = never>(\n onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null,\n ): Promise<T | TResult> {\n return this.parse().catch(onrejected);\n }\n\n override finally(onfinally?: (() => void) | undefined | null): Promise<T> {\n return this.parse().finally(onfinally);\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nimport { isReadonlyArray } from './utils/values.js';\n\ntype HeaderValue = string | undefined | null;\nexport type HeadersLike =\n | Headers\n | readonly HeaderValue[][]\n | Record<string, HeaderValue | readonly HeaderValue[]>\n | undefined\n | null\n | NullableHeaders;\n\nconst brand_privateNullableHeaders = /* @__PURE__ */ Symbol('brand.privateNullableHeaders');\n\n/**\n * @internal\n * Users can pass explicit nulls to unset default headers. When we parse them\n * into a standard headers type we need to preserve that information.\n */\nexport type NullableHeaders = {\n /** Brand check, prevent users from creating a NullableHeaders. */\n [brand_privateNullableHeaders]: true;\n /** Parsed headers. */\n values: Headers;\n /** Set of lowercase header names explicitly set to null. */\n nulls: Set<string>;\n};\n\nfunction* iterateHeaders(headers: HeadersLike): IterableIterator<readonly [string, string | null]> {\n if (!headers) return;\n\n if (brand_privateNullableHeaders in headers) {\n const { values, nulls } = headers;\n yield* values.entries();\n for (const name of nulls) {\n yield [name, null];\n }\n return;\n }\n\n let shouldClear = false;\n let iter: Iterable<readonly (HeaderValue | readonly HeaderValue[])[]>;\n if (headers instanceof Headers) {\n iter = headers.entries();\n } else if (isReadonlyArray(headers)) {\n iter = headers;\n } else {\n shouldClear = true;\n iter = Object.entries(headers ?? {});\n }\n for (let row of iter) {\n const name = row[0];\n if (typeof name !== 'string') throw new TypeError('expected header name to be a string');\n const values = isReadonlyArray(row[1]) ? row[1] : [row[1]];\n let didClear = false;\n for (const value of values) {\n if (value === undefined) continue;\n\n // Objects keys always overwrite older headers, they never append.\n // Yield a null to clear the header before adding the new values.\n if (shouldClear && !didClear) {\n didClear = true;\n yield [name, null];\n }\n yield [name, value];\n }\n }\n}\n\nexport const buildHeaders = (newHeaders: HeadersLike[]): NullableHeaders => {\n const targetHeaders = new Headers();\n const nullHeaders = new Set<string>();\n for (const headers of newHeaders) {\n const seenHeaders = new Set<string>();\n for (const [name, value] of iterateHeaders(headers)) {\n const lowerName = name.toLowerCase();\n if (!seenHeaders.has(lowerName)) {\n targetHeaders.delete(name);\n seenHeaders.add(lowerName);\n }\n if (value === null) {\n targetHeaders.delete(name);\n nullHeaders.add(lowerName);\n } else {\n targetHeaders.append(name, value);\n nullHeaders.delete(lowerName);\n }\n }\n }\n return { [brand_privateNullableHeaders]: true, values: targetHeaders, nulls: nullHeaders };\n};\n\nexport const isEmptyHeaders = (headers: HeadersLike) => {\n for (const _ of iterateHeaders(headers)) return false;\n return true;\n};\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\n/**\n * Read an environment variable.\n *\n * Trims beginning and trailing whitespace.\n *\n * Will return undefined if the environment variable doesn't exist or cannot be accessed.\n */\nexport const readEnv = (env: string): string | undefined => {\n if (typeof (globalThis as any).process !== 'undefined') {\n return (globalThis as any).process.env?.[env]?.trim() ?? undefined;\n }\n if (typeof (globalThis as any).Deno !== 'undefined') {\n return (globalThis as any).Deno.env?.get?.(env)?.trim();\n }\n return undefined;\n};\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nimport type { RequestInit, RequestInfo, BodyInit } from './internal/builtin-types.js';\nimport type { HTTPMethod, PromiseOrValue, MergedRequestInit, FinalizedRequestInit } from './internal/types.js';\nimport { uuid4 } from './internal/utils/uuid.js';\nimport { validatePositiveInteger, isAbsoluteURL, safeJSON } from './internal/utils/values.js';\nimport { sleep } from './internal/utils/sleep.js';\nexport type { Logger, LogLevel } from './internal/utils/log.js';\nimport { castToError, isAbortError } from './internal/errors.js';\nimport type { APIResponseProps } from './internal/parse.js';\nimport { getPlatformHeaders } from './internal/detect-platform.js';\nimport * as Shims from './internal/shims.js';\nimport * as Opts from './internal/request-options.js';\nimport { VERSION } from './version.js';\nimport * as Errors from './core/error.js';\nimport * as Uploads from './core/uploads.js';\nimport * as API from './resources/index.js';\nimport { APIPromise } from './core/api-promise.js';\nimport {\n AllowedTools,\n Annotation,\n AudioContent,\n AudioMimeType,\n CodeExecutionCallArguments,\n CodeExecutionCallContent,\n CodeExecutionResultContent,\n Content,\n ContentDelta,\n ContentStart,\n ContentStop,\n CreateAgentInteractionParamsNonStreaming,\n CreateAgentInteractionParamsStreaming,\n CreateModelInteractionParamsNonStreaming,\n CreateModelInteractionParamsStreaming,\n DeepResearchAgentConfig,\n DocumentContent,\n DocumentMimeType,\n DynamicAgentConfig,\n ErrorEvent,\n FileSearchCallContent,\n FileSearchResultContent,\n Function,\n FunctionCallContent,\n FunctionResultContent,\n GenerationConfig,\n GoogleSearchCallArguments,\n GoogleSearchCallContent,\n GoogleSearchResult,\n GoogleSearchResultContent,\n ImageConfig,\n ImageContent,\n ImageMimeType,\n Interaction,\n InteractionCancelParams,\n InteractionCompleteEvent,\n InteractionCreateParams,\n InteractionDeleteParams,\n InteractionDeleteResponse,\n InteractionGetParams,\n InteractionGetParamsNonStreaming,\n InteractionGetParamsStreaming,\n InteractionSSEEvent,\n InteractionStartEvent,\n InteractionStatusUpdate,\n Interactions,\n MCPServerToolCallContent,\n MCPServerToolResultContent,\n Model,\n SpeechConfig,\n TextContent,\n ThinkingLevel,\n ThoughtContent,\n Tool,\n ToolChoice,\n ToolChoiceConfig,\n ToolChoiceType,\n Turn,\n URLContextCallArguments,\n URLContextCallContent,\n URLContextResult,\n URLContextResultContent,\n Usage,\n VideoContent,\n VideoMimeType,\n} from './resources/interactions.js';\nimport { type Fetch } from './internal/builtin-types.js';\nimport { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers.js';\nimport { FinalRequestOptions, RequestOptions } from './internal/request-options.js';\nimport { readEnv } from './internal/utils/env.js';\nimport {\n type LogLevel,\n type Logger,\n formatRequestDetails,\n loggerFor,\n parseLogLevel,\n} from './internal/utils/log.js';\nimport { isEmptyObj } from './internal/utils/values.js';\nimport { GeminiNextGenAPIClientAdapter } from './client-adapter.js';\n\nexport interface ClientOptions {\n /**\n * Defaults to process.env['GEMINI_API_KEY'].\n */\n apiKey?: string | null | undefined;\n\n apiVersion?: string | undefined;\n\n /**\n * Override the default base URL for the API, e.g., \"https://api.example.com/v2/\"\n *\n * Defaults to process.env['GEMINI_NEXT_GEN_API_BASE_URL'].\n */\n baseURL?: string | null | undefined;\n\n /**\n * The maximum amount of time (in milliseconds) that the client should wait for a response\n * from the server before timing out a single request.\n *\n * Note that request timeouts are retried by default, so in a worst-case scenario you may wait\n * much longer than this timeout before the promise succeeds or fails.\n *\n * @unit milliseconds\n */\n timeout?: number | undefined;\n /**\n * Additional `RequestInit` options to be passed to `fetch` calls.\n * Properties will be overridden by per-request `fetchOptions`.\n */\n fetchOptions?: MergedRequestInit | undefined;\n\n /**\n * Specify a custom `fetch` function implementation.\n *\n * If not provided, we expect that `fetch` is defined globally.\n */\n fetch?: Fetch | undefined;\n\n /**\n * The maximum number of times that the client will retry a request in case of a\n * temporary failure, like a network error or a 5XX error from the server.\n *\n * @default 2\n */\n maxRetries?: number | undefined;\n\n /**\n * Default headers to include with every request to the API.\n *\n * These can be removed in individual requests by explicitly setting the\n * header to `null` in request options.\n */\n defaultHeaders?: HeadersLike | undefined;\n\n /**\n * Default query parameters to include with every request to the API.\n *\n * These can be removed in individual requests by explicitly setting the\n * param to `undefined` in request options.\n */\n defaultQuery?: Record<string, string | undefined> | undefined;\n\n /**\n * Set the log level.\n *\n * Defaults to process.env['GEMINI_NEXT_GEN_API_LOG'] or 'warn' if it isn't set.\n */\n logLevel?: LogLevel | undefined;\n\n /**\n * Set the logger.\n *\n * Defaults to globalThis.console.\n */\n logger?: Logger | undefined;\n\n /**\n * The adapter to the parent API client instance (for accessing auth, project, location)\n */\n clientAdapter: GeminiNextGenAPIClientAdapter;\n}\n\n/**\n * Base class for Gemini Next Gen API API clients.\n */\nexport class BaseGeminiNextGenAPIClient {\n apiKey: string | null;\n apiVersion: string;\n\n baseURL: string;\n maxRetries: number;\n timeout: number;\n logger: Logger;\n logLevel: LogLevel | undefined;\n fetchOptions: MergedRequestInit | undefined;\n\n private fetch: Fetch;\n private encoder: Opts.RequestEncoder;\n protected idempotencyHeader?: string;\n private _options: ClientOptions;\n private clientAdapter: GeminiNextGenAPIClientAdapter;\n\n /**\n * API Client for interfacing with the Gemini Next Gen API API.\n *\n * @param {string | null | undefined} [opts.apiKey=process.env['GEMINI_API_KEY'] ?? null]\n * @param {string | undefined} [opts.apiVersion=v1beta]\n * @param {string} [opts.baseURL=process.env['GEMINI_NEXT_GEN_API_BASE_URL'] ?? https://generativelanguage.googleapis.com] - Override the default base URL for the API.\n * @param {number} [opts.timeout=1 minute] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out.\n * @param {MergedRequestInit} [opts.fetchOptions] - Additional `RequestInit` options to be passed to `fetch` calls.\n * @param {Fetch} [opts.fetch] - Specify a custom `fetch` function implementation.\n * @param {number} [opts.maxRetries=2] - The maximum number of times the client will retry a request.\n * @param {HeadersLike} opts.defaultHeaders - Default headers to include with every request to the API.\n * @param {Record<string, string | undefined>} opts.defaultQuery - Default query parameters to include with every request to the API.\n */\n constructor({\n baseURL = readEnv('GEMINI_NEXT_GEN_API_BASE_URL'),\n apiKey = readEnv('GEMINI_API_KEY') ?? null,\n apiVersion = 'v1beta',\n ...opts\n }: ClientOptions) {\n const options: ClientOptions = {\n apiKey,\n apiVersion,\n ...opts,\n baseURL: baseURL || `https://generativelanguage.googleapis.com`,\n };\n\n this.baseURL = options.baseURL!;\n this.timeout = options.timeout ?? BaseGeminiNextGenAPIClient.DEFAULT_TIMEOUT /* 1 minute */;\n this.logger = options.logger ?? console;\n const defaultLogLevel = 'warn';\n // Set default logLevel early so that we can log a warning in parseLogLevel.\n this.logLevel = defaultLogLevel;\n this.logLevel =\n parseLogLevel(options.logLevel, 'ClientOptions.logLevel', this) ??\n parseLogLevel(readEnv('GEMINI_NEXT_GEN_API_LOG'), \"process.env['GEMINI_NEXT_GEN_API_LOG']\", this) ??\n defaultLogLevel;\n this.fetchOptions = options.fetchOptions;\n this.maxRetries = options.maxRetries ?? 2;\n this.fetch = options.fetch ?? Shims.getDefaultFetch();\n this.encoder = Opts.FallbackEncoder;\n\n this._options = options;\n\n this.apiKey = apiKey;\n this.apiVersion = apiVersion;\n this.clientAdapter = options.clientAdapter;\n }\n\n /**\n * Create a new client instance re-using the same options given to the current client with optional overriding.\n */\n withOptions(options: Partial<ClientOptions>): this {\n const client = new (this.constructor as any as new (props: ClientOptions) => typeof this)({\n ...this._options,\n baseURL: this.baseURL,\n maxRetries: this.maxRetries,\n timeout: this.timeout,\n logger: this.logger,\n logLevel: this.logLevel,\n fetch: this.fetch,\n fetchOptions: this.fetchOptions,\n apiKey: this.apiKey,\n apiVersion: this.apiVersion,\n ...options,\n });\n return client;\n }\n\n /**\n * Check whether the base URL is set to its default.\n */\n private baseURLOverridden() {\n return this.baseURL !== 'https://generativelanguage.googleapis.com';\n }\n\n protected defaultQuery(): Record<string, string | undefined> | undefined {\n return this._options.defaultQuery;\n }\n\n protected validateHeaders({ values, nulls }: NullableHeaders) {\n // The headers object handles case insensitivity.\n if (values.has('authorization') || values.has('x-goog-api-key')) {\n return;\n }\n if (this.apiKey && values.get('x-goog-api-key')) {\n return;\n }\n if (nulls.has('x-goog-api-key')) {\n return;\n }\n\n throw new Error(\n 'Could not resolve authentication method. Expected the apiKey to be set. Or for the \"x-goog-api-key\" headers to be explicitly omitted',\n );\n }\n\n protected async authHeaders(opts: FinalRequestOptions): Promise<NullableHeaders | undefined> {\n const existingHeaders = buildHeaders([opts.headers]);\n\n if (existingHeaders.values.has('authorization') || existingHeaders.values.has('x-goog-api-key')) {\n return undefined;\n }\n\n if (this.apiKey) {\n return buildHeaders([{ 'x-goog-api-key': this.apiKey }]);\n }\n\n if (this.clientAdapter.isVertexAI()) {\n return buildHeaders([await this.clientAdapter.getAuthHeaders()]);\n }\n\n return undefined;\n }\n\n /**\n * Basic re-implementation of `qs.stringify` for primitive types.\n */\n protected stringifyQuery(query: Record<string, unknown>): string {\n return Object.entries(query)\n .filter(([_, value]) => typeof value !== 'undefined')\n .map(([key, value]) => {\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {\n return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;\n }\n if (value === null) {\n return `${encodeURIComponent(key)}=`;\n }\n throw new Errors.GeminiNextGenAPIClientError(\n `Cannot stringify type ${typeof value}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`,\n );\n })\n .join('&');\n }\n\n private getUserAgent(): string {\n return `${this.constructor.name}/JS ${VERSION}`;\n }\n\n protected defaultIdempotencyKey(): string {\n return `stainless-node-retry-${uuid4()}`;\n }\n\n protected makeStatusError(\n status: number,\n error: Object,\n message: string | undefined,\n headers: Headers,\n ): Errors.APIError {\n return Errors.APIError.generate(status, error, message, headers);\n }\n\n buildURL(\n path: string,\n query: Record<string, unknown> | null | undefined,\n defaultBaseURL?: string | undefined,\n ): string {\n const baseURL = (!this.baseURLOverridden() && defaultBaseURL) || this.baseURL;\n const url =\n isAbsoluteURL(path) ?\n new URL(path)\n : new URL(baseURL + (baseURL.endsWith('/') && path.startsWith('/') ? path.slice(1) : path));\n\n const defaultQuery = this.defaultQuery();\n if (!isEmptyObj(defaultQuery)) {\n query = { ...defaultQuery, ...query };\n }\n\n if (typeof query === 'object' && query && !Array.isArray(query)) {\n url.search = this.stringifyQuery(query as Record<string, unknown>);\n }\n\n return url.toString();\n }\n\n /**\n * Used as a callback for mutating the given `FinalRequestOptions` object.\n\n */\n protected async prepareOptions(options: FinalRequestOptions): Promise<void> {\n if (\n this.clientAdapter &&\n this.clientAdapter.isVertexAI() &&\n !options.path.startsWith(`/${this.apiVersion}/projects/`)\n ) {\n const oldPath = options.path.slice(this.apiVersion.length + 1);\n options.path = `/${\n this.apiVersion\n }/projects/${this.clientAdapter.getProject()}/locations/${this.clientAdapter.getLocation()}${oldPath}`;\n }\n }\n\n /**\n * Used as a callback for mutating the given `RequestInit` object.\n *\n * This is useful for cases where you want to add certain headers based off of\n * the request properties, e.g. `method` or `url`.\n */\n protected async prepareRequest(\n request: RequestInit,\n { url, options }: { url: string; options: FinalRequestOptions },\n ): Promise<void> {}\n\n get<Rsp>(path: string, opts?: PromiseOrValue<RequestOptions>): APIPromise<Rsp> {\n return this.methodRequest('get', path, opts);\n }\n\n post<Rsp>(path: string, opts?: PromiseOrValue<RequestOptions>): APIPromise<Rsp> {\n return this.methodRequest('post', path, opts);\n }\n\n patch<Rsp>(path: string, opts?: PromiseOrValue<RequestOptions>): APIPromise<Rsp> {\n return this.methodRequest('patch', path, opts);\n }\n\n put<Rsp>(path: string, opts?: PromiseOrValue<RequestOptions>): APIPromise<Rsp> {\n return this.methodRequest('put', path, opts);\n }\n\n delete<Rsp>(path: string, opts?: PromiseOrValue<RequestOptions>): APIPromise<Rsp> {\n return this.methodRequest('delete', path, opts);\n }\n\n private methodRequest<Rsp>(\n method: HTTPMethod,\n path: string,\n opts?: PromiseOrValue<RequestOptions>,\n ): APIPromise<Rsp> {\n return this.request(\n Promise.resolve(opts).then((opts) => {\n return { method, path, ...opts };\n }),\n );\n }\n\n request<Rsp>(\n options: PromiseOrValue<FinalRequestOptions>,\n remainingRetries: number | null = null,\n ): APIPromise<Rsp> {\n return new APIPromise(this, this.makeRequest(options, remainingRetries, undefined));\n }\n\n private async makeRequest(\n optionsInput: PromiseOrValue<FinalRequestOptions>,\n retriesRemaining: number | null,\n retryOfRequestLogID: string | undefined,\n ): Promise<APIResponseProps> {\n const options = await optionsInput;\n const maxRetries = options.maxRetries ?? this.maxRetries;\n if (retriesRemaining == null) {\n retriesRemaining = maxRetries;\n }\n\n await this.prepareOptions(options);\n\n const { req, url, timeout } = await this.buildRequest(options, {\n retryCount: maxRetries - retriesRemaining,\n });\n\n await this.prepareRequest(req, { url, options });\n\n /** Not an API request ID, just for correlating local log entries. */\n const requestLogID = 'log_' + ((Math.random() * (1 << 24)) | 0).toString(16).padStart(6, '0');\n const retryLogStr = retryOfRequestLogID === undefined ? '' : `, retryOf: ${retryOfRequestLogID}`;\n const startTime = Date.now();\n\n loggerFor(this).debug(\n `[${requestLogID}] sending request`,\n formatRequestDetails({\n retryOfRequestLogID,\n method: options.method,\n url,\n options,\n headers: req.headers,\n }),\n );\n\n if (options.signal?.aborted) {\n throw new Errors.APIUserAbortError();\n }\n\n const controller = new AbortController();\n const response = await this.fetchWithTimeout(url, req, timeout, controller).catch(castToError);\n const headersTime = Date.now();\n\n if (response instanceof globalThis.Error) {\n const retryMessage = `retrying, ${retriesRemaining} attempts remaining`;\n if (options.signal?.aborted) {\n throw new Errors.APIUserAbortError();\n }\n // detect native connection timeout errors\n // deno throws \"TypeError: error sending request for url (https://example/): client error (Connect): tcp connect error: Operation timed out (os error 60): Operation timed out (os error 60)\"\n // undici throws \"TypeError: fetch failed\" with cause \"ConnectTimeoutError: Connect Timeout Error (attempted address: example:443, timeout: 1ms)\"\n // others do not provide enough information to distinguish timeouts from other connection errors\n const isTimeout =\n isAbortError(response) ||\n /timed? ?out/i.test(String(response) + ('cause' in response ? String(response.cause) : ''));\n if (retriesRemaining) {\n loggerFor(this).info(\n `[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - ${retryMessage}`,\n );\n loggerFor(this).debug(\n `[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (${retryMessage})`,\n formatRequestDetails({\n retryOfRequestLogID,\n url,\n durationMs: headersTime - startTime,\n message: response.message,\n }),\n );\n return this.retryRequest(options, retriesRemaining, retryOfRequestLogID ?? requestLogID);\n }\n loggerFor(this).info(\n `[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - error; no more retries left`,\n );\n loggerFor(this).debug(\n `[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (error; no more retries left)`,\n formatRequestDetails({\n retryOfRequestLogID,\n url,\n durationMs: headersTime - startTime,\n message: response.message,\n }),\n );\n if (isTimeout) {\n throw new Errors.APIConnectionTimeoutError();\n }\n throw new Errors.APIConnectionError({ cause: response });\n }\n\n const responseInfo = `[${requestLogID}${retryLogStr}] ${req.method} ${url} ${\n response.ok ? 'succeeded' : 'failed'\n } with status ${response.status} in ${headersTime - startTime}ms`;\n\n if (!response.ok) {\n const shouldRetry = await this.shouldRetry(response);\n if (retriesRemaining && shouldRetry) {\n const retryMessage = `retrying, ${retriesRemaining} attempts remaining`;\n\n // We don't need the body of this response.\n await Shims.CancelReadableStream(response.body);\n loggerFor(this).info(`${responseInfo} - ${retryMessage}`);\n loggerFor(this).debug(\n `[${requestLogID}] response error (${retryMessage})`,\n formatRequestDetails({\n retryOfRequestLogID,\n url: response.url,\n status: response.status,\n headers: response.headers,\n durationMs: headersTime - startTime,\n }),\n );\n return this.retryRequest(\n options,\n retriesRemaining,\n retryOfRequestLogID ?? requestLogID,\n response.headers,\n );\n }\n\n const retryMessage = shouldRetry ? `error; no more retries left` : `error; not retryable`;\n\n loggerFor(this).info(`${responseInfo} - ${retryMessage}`);\n\n const errText = await response.text().catch((err: any) => castToError(err).message);\n const errJSON = safeJSON(errText);\n const errMessage = errJSON ? undefined : errText;\n\n loggerFor(this).debug(\n `[${requestLogID}] response error (${retryMessage})`,\n formatRequestDetails({\n retryOfRequestLogID,\n url: response.url,\n status: response.status,\n headers: response.headers,\n message: errMessage,\n durationMs: Date.now() - startTime,\n }),\n );\n // @ts-ignore\n const err = this.makeStatusError(response.status, errJSON, errMessage, response.headers);\n throw err;\n }\n\n loggerFor(this).info(responseInfo);\n loggerFor(this).debug(\n `[${requestLogID}] response start`,\n formatRequestDetails({\n retryOfRequestLogID,\n url: response.url,\n status: response.status,\n headers: response.headers,\n durationMs: headersTime - startTime,\n }),\n );\n\n return { response, options, controller, requestLogID, retryOfRequestLogID, startTime };\n }\n\n async fetchWithTimeout(\n url: RequestInfo,\n init: RequestInit | undefined,\n ms: number,\n controller: AbortController,\n ): Promise<Response> {\n const { signal, method, ...options } = init || {};\n const abort = this._makeAbort(controller);\n if (signal) signal.addEventListener('abort', abort, { once: true });\n\n const timeout = setTimeout(abort, ms);\n\n const isReadableBody =\n ((globalThis as any).ReadableStream && options.body instanceof (globalThis as any).ReadableStream) ||\n (typeof options.body === 'object' && options.body !== null && Symbol.asyncIterator in options.body);\n\n const fetchOptions: RequestInit = {\n signal: controller.signal as any,\n ...(isReadableBody ? { duplex: 'half' } : {}),\n method: 'GET',\n ...options,\n };\n if (method) {\n // Custom methods like 'patch' need to be uppercased\n // See https://github.com/nodejs/undici/issues/2294\n fetchOptions.method = method.toUpperCase();\n }\n\n try {\n // use undefined this binding; fetch errors if bound to something else in browser/cloudflare\n return await this.fetch.call(undefined, url, fetchOptions);\n } finally {\n clearTimeout(timeout);\n }\n }\n\n private async shouldRetry(response: Response): Promise<boolean> {\n // Note this is not a standard header.\n const shouldRetryHeader = response.headers.get('x-should-retry');\n\n // If the server explicitly says whether or not to retry, obey.\n if (shouldRetryHeader === 'true') return true;\n if (shouldRetryHeader === 'false') return false;\n\n // Retry on request timeouts.\n if (response.status === 408) return true;\n\n // Retry on lock timeouts.\n if (response.status === 409) return true;\n\n // Retry on rate limits.\n if (response.status === 429) return true;\n\n // Retry internal errors.\n if (response.status >= 500) return true;\n\n return false;\n }\n\n private async retryRequest(\n options: FinalRequestOptions,\n retriesRemaining: number,\n requestLogID: string,\n responseHeaders?: Headers | undefined,\n ): Promise<APIResponseProps> {\n let timeoutMillis: number | undefined;\n\n // Note the `retry-after-ms` header may not be standard, but is a good idea and we'd like proactive support for it.\n const retryAfterMillisHeader = responseHeaders?.get('retry-after-ms');\n if (retryAfterMillisHeader) {\n const timeoutMs = parseFloat(retryAfterMillisHeader);\n if (!Number.isNaN(timeoutMs)) {\n timeoutMillis = timeoutMs;\n }\n }\n\n // About the Retry-After header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After\n const retryAfterHeader = responseHeaders?.get('retry-after');\n if (retryAfterHeader && !timeoutMillis) {\n const timeoutSeconds = parseFloat(retryAfterHeader);\n if (!Number.isNaN(timeoutSeconds)) {\n timeoutMillis = timeoutSeconds * 1000;\n } else {\n timeoutMillis = Date.parse(retryAfterHeader) - Date.now();\n }\n }\n\n // If the API asks us to wait a certain amount of time (and it's a reasonable amount),\n // just do what it says, but otherwise calculate a default\n if (!(timeoutMillis && 0 <= timeoutMillis && timeoutMillis < 60 * 1000)) {\n const maxRetries = options.maxRetries ?? this.maxRetries;\n timeoutMillis = this.calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries);\n }\n await sleep(timeoutMillis);\n\n return this.makeRequest(options, retriesRemaining - 1, requestLogID);\n }\n\n private calculateDefaultRetryTimeoutMillis(retriesRemaining: number, maxRetries: number): number {\n const initialRetryDelay = 0.5;\n const maxRetryDelay = 8.0;\n\n const numRetries = maxRetries - retriesRemaining;\n\n // Apply exponential backoff, but not more than the max.\n const sleepSeconds = Math.min(initialRetryDelay * Math.pow(2, numRetries), maxRetryDelay);\n\n // Apply some jitter, take up to at most 25 percent of the retry time.\n const jitter = 1 - Math.random() * 0.25;\n\n return sleepSeconds * jitter * 1000;\n }\n\n async buildRequest(\n inputOptions: FinalRequestOptions,\n { retryCount = 0 }: { retryCount?: number } = {},\n ): Promise<{ req: FinalizedRequestInit; url: string; timeout: number }> {\n const options = { ...inputOptions };\n const { method, path, query, defaultBaseURL } = options;\n\n const url = this.buildURL(path!, query as Record<string, unknown>, defaultBaseURL);\n if ('timeout' in options) validatePositiveInteger('timeout', options.timeout);\n options.timeout = options.timeout ?? this.timeout;\n const { bodyHeaders, body } = this.buildBody({ options });\n const reqHeaders = await this.buildHeaders({ options: inputOptions, method, bodyHeaders, retryCount });\n\n const req: FinalizedRequestInit = {\n method,\n headers: reqHeaders,\n ...(options.signal && { signal: options.signal }),\n ...((globalThis as any).ReadableStream &&\n body instanceof (globalThis as any).ReadableStream && { duplex: 'half' }),\n ...(body && { body }),\n ...((this.fetchOptions as any) ?? {}),\n ...((options.fetchOptions as any) ?? {}),\n };\n\n return { req, url, timeout: options.timeout };\n }\n\n private async buildHeaders({\n options,\n method,\n bodyHeaders,\n retryCount,\n }: {\n options: FinalRequestOptions;\n method: HTTPMethod;\n bodyHeaders: HeadersLike;\n retryCount: number;\n }): Promise<Headers> {\n let idempotencyHeaders: HeadersLike = {};\n if (this.idempotencyHeader && method !== 'get') {\n if (!options.idempotencyKey) options.idempotencyKey = this.defaultIdempotencyKey();\n idempotencyHeaders[this.idempotencyHeader] = options.idempotencyKey;\n }\n\n const authHeaders = await this.authHeaders(options);\n\n let headers = buildHeaders([\n idempotencyHeaders,\n {\n Accept: 'application/json',\n 'User-Agent': this.getUserAgent(),\n 'X-Stainless-Retry-Count': String(retryCount),\n ...(options.timeout ? { 'X-Stainless-Timeout': String(Math.trunc(options.timeout / 1000)) } : {}),\n ...getPlatformHeaders(),\n },\n this._options.defaultHeaders,\n bodyHeaders,\n options.headers,\n authHeaders,\n ]);\n\n this.validateHeaders(headers);\n\n return headers.values;\n }\n\n private _makeAbort(controller: AbortController) {\n // note: we can't just inline this method inside `fetchWithTimeout()` because then the closure\n // would capture all request options, and cause a memory leak.\n return () => controller.abort();\n }\n\n private buildBody({ options: { body, headers: rawHeaders } }: { options: FinalRequestOptions }): {\n bodyHeaders: HeadersLike;\n body: BodyInit | undefined;\n } {\n if (!body) {\n return { bodyHeaders: undefined, body: undefined };\n }\n const headers = buildHeaders([rawHeaders]);\n if (\n // Pass raw type verbatim\n ArrayBuffer.isView(body) ||\n body instanceof ArrayBuffer ||\n body instanceof DataView ||\n (typeof body === 'string' &&\n // Preserve legacy string encoding behavior for now\n headers.values.has('content-type')) ||\n // `Blob` is superset of `File`\n ((globalThis as any).Blob && body instanceof (globalThis as any).Blob) ||\n // `FormData` -> `multipart/form-data`\n body instanceof FormData ||\n // `URLSearchParams` -> `application/x-www-form-urlencoded`\n body instanceof URLSearchParams ||\n // Send chunked stream (each chunk has own `length`)\n ((globalThis as any).ReadableStream && body instanceof (globalThis as any).ReadableStream)\n ) {\n return { bodyHeaders: undefined, body: body as BodyInit };\n } else if (\n typeof body === 'object' &&\n (Symbol.asyncIterator in body ||\n (Symbol.iterator in body && 'next' in body && typeof body.next === 'function'))\n ) {\n return { bodyHeaders: undefined, body: Shims.ReadableStreamFrom(body as AsyncIterable<Uint8Array>) };\n } else {\n return this.encoder({ body, headers });\n }\n }\n\n static DEFAULT_TIMEOUT = 60000; // 1 minute\n}\n\n/**\n * API Client for interfacing with the Gemini Next Gen API API.\n */\nexport class GeminiNextGenAPIClient extends BaseGeminiNextGenAPIClient {\n static GeminiNextGenAPIClient = this;\n\n static GeminiNextGenAPIClientError = Errors.GeminiNextGenAPIClientError;\n static APIError = Errors.APIError;\n static APIConnectionError = Errors.APIConnectionError;\n static APIConnectionTimeoutError = Errors.APIConnectionTimeoutError;\n static APIUserAbortError = Errors.APIUserAbortError;\n static NotFoundError = Errors.NotFoundError;\n static ConflictError = Errors.ConflictError;\n static RateLimitError = Errors.RateLimitError;\n static BadRequestError = Errors.BadRequestError;\n static AuthenticationError = Errors.AuthenticationError;\n static InternalServerError = Errors.InternalServerError;\n static PermissionDeniedError = Errors.PermissionDeniedError;\n static UnprocessableEntityError = Errors.UnprocessableEntityError;\n\n static toFile = Uploads.toFile;\n\n interactions: API.Interactions = new API.Interactions(this);\n}\n\nGeminiNextGenAPIClient.Interactions = Interactions;\n\nexport declare namespace GeminiNextGenAPIClient {\n export type RequestOptions = Opts.RequestOptions;\n\n export {\n Interactions as Interactions,\n type AllowedTools as AllowedTools,\n type Annotation as Annotation,\n type AudioContent as AudioContent,\n type AudioMimeType as AudioMimeType,\n type CodeExecutionCallArguments as CodeExecutionCallArguments,\n type CodeExecutionCallContent as CodeExecutionCallContent,\n type CodeExecutionResultContent as CodeExecutionResultContent,\n type Content as Content,\n type ContentDelta as ContentDelta,\n type ContentStart as ContentStart,\n type ContentStop as ContentStop,\n type DeepResearchAgentConfig as DeepResearchAgentConfig,\n type DocumentContent as DocumentContent,\n type DocumentMimeType as DocumentMimeType,\n type DynamicAgentConfig as DynamicAgentConfig,\n type ErrorEvent as ErrorEvent,\n type FileSearchCallContent as FileSearchCallContent,\n type FileSearchResultContent as FileSearchResultContent,\n type Function as Function,\n type FunctionCallContent as FunctionCallContent,\n type FunctionResultContent as FunctionResultContent,\n type GenerationConfig as GenerationConfig,\n type GoogleSearchCallArguments as GoogleSearchCallArguments,\n type GoogleSearchCallContent as GoogleSearchCallContent,\n type GoogleSearchResult as GoogleSearchResult,\n type GoogleSearchResultContent as GoogleSearchResultContent,\n type ImageConfig as ImageConfig,\n type ImageContent as ImageContent,\n type ImageMimeType as ImageMimeType,\n type Interaction as Interaction,\n type InteractionCompleteEvent as InteractionCompleteEvent,\n type InteractionSSEEvent as InteractionSSEEvent,\n type InteractionStartEvent as InteractionStartEvent,\n type InteractionStatusUpdate as InteractionStatusUpdate,\n type MCPServerToolCallContent as MCPServerToolCallContent,\n type MCPServerToolResultContent as MCPServerToolResultContent,\n type Model as Model,\n type SpeechConfig as SpeechConfig,\n type TextContent as TextContent,\n type ThinkingLevel as ThinkingLevel,\n type ThoughtContent as ThoughtContent,\n type Tool as Tool,\n type ToolChoice as ToolChoice,\n type ToolChoiceConfig as ToolChoiceConfig,\n type ToolChoiceType as ToolChoiceType,\n type Turn as Turn,\n type URLContextCallArguments as URLContextCallArguments,\n type URLContextCallContent as URLContextCallContent,\n type URLContextResult as URLContextResult,\n type URLContextResultContent as URLContextResultContent,\n type Usage as Usage,\n type VideoContent as VideoContent,\n type VideoMimeType as VideoMimeType,\n type InteractionDeleteResponse as InteractionDeleteResponse,\n type InteractionCreateParams as InteractionCreateParams,\n type CreateModelInteractionParamsNonStreaming as CreateModelInteractionParamsNonStreaming,\n type CreateModelInteractionParamsStreaming as CreateModelInteractionParamsStreaming,\n type CreateAgentInteractionParamsNonStreaming as CreateAgentInteractionParamsNonStreaming,\n type CreateAgentInteractionParamsStreaming as CreateAgentInteractionParamsStreaming,\n type InteractionDeleteParams as InteractionDeleteParams,\n type InteractionCancelParams as InteractionCancelParams,\n type InteractionGetParams as InteractionGetParams,\n type InteractionGetParamsNonStreaming as InteractionGetParamsNonStreaming,\n type InteractionGetParamsStreaming as InteractionGetParamsStreaming,\n };\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport * as common from '../_common.js';\nimport * as t from '../_transformers.js';\nimport type * as types from '../types.js';\n\nexport function cancelTuningJobParametersToMldev(\n fromObject: types.CancelTuningJobParameters,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['_url', 'name'], fromName);\n }\n\n return toObject;\n}\n\nexport function cancelTuningJobParametersToVertex(\n fromObject: types.CancelTuningJobParameters,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['_url', 'name'], fromName);\n }\n\n return toObject;\n}\n\nexport function cancelTuningJobResponseFromMldev(\n fromObject: types.CancelTuningJobResponse,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n return toObject;\n}\n\nexport function cancelTuningJobResponseFromVertex(\n fromObject: types.CancelTuningJobResponse,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n return toObject;\n}\n\nexport function createTuningJobConfigToMldev(\n fromObject: types.CreateTuningJobConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['validationDataset']) !== undefined) {\n throw new Error(\n 'validationDataset parameter is not supported in Gemini API.',\n );\n }\n\n const fromTunedModelDisplayName = common.getValueByPath(fromObject, [\n 'tunedModelDisplayName',\n ]);\n if (parentObject !== undefined && fromTunedModelDisplayName != null) {\n common.setValueByPath(\n parentObject,\n ['displayName'],\n fromTunedModelDisplayName,\n );\n }\n\n if (common.getValueByPath(fromObject, ['description']) !== undefined) {\n throw new Error('description parameter is not supported in Gemini API.');\n }\n\n const fromEpochCount = common.getValueByPath(fromObject, ['epochCount']);\n if (parentObject !== undefined && fromEpochCount != null) {\n common.setValueByPath(\n parentObject,\n ['tuningTask', 'hyperparameters', 'epochCount'],\n fromEpochCount,\n );\n }\n\n const fromLearningRateMultiplier = common.getValueByPath(fromObject, [\n 'learningRateMultiplier',\n ]);\n if (fromLearningRateMultiplier != null) {\n common.setValueByPath(\n toObject,\n ['tuningTask', 'hyperparameters', 'learningRateMultiplier'],\n fromLearningRateMultiplier,\n );\n }\n\n if (\n common.getValueByPath(fromObject, ['exportLastCheckpointOnly']) !==\n undefined\n ) {\n throw new Error(\n 'exportLastCheckpointOnly parameter is not supported in Gemini API.',\n );\n }\n\n if (\n common.getValueByPath(fromObject, ['preTunedModelCheckpointId']) !==\n undefined\n ) {\n throw new Error(\n 'preTunedModelCheckpointId parameter is not supported in Gemini API.',\n );\n }\n\n if (common.getValueByPath(fromObject, ['adapterSize']) !== undefined) {\n throw new Error('adapterSize parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['tuningMode']) !== undefined) {\n throw new Error('tuningMode parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['customBaseModel']) !== undefined) {\n throw new Error(\n 'customBaseModel parameter is not supported in Gemini API.',\n );\n }\n\n const fromBatchSize = common.getValueByPath(fromObject, ['batchSize']);\n if (parentObject !== undefined && fromBatchSize != null) {\n common.setValueByPath(\n parentObject,\n ['tuningTask', 'hyperparameters', 'batchSize'],\n fromBatchSize,\n );\n }\n\n const fromLearningRate = common.getValueByPath(fromObject, ['learningRate']);\n if (parentObject !== undefined && fromLearningRate != null) {\n common.setValueByPath(\n parentObject,\n ['tuningTask', 'hyperparameters', 'learningRate'],\n fromLearningRate,\n );\n }\n\n if (common.getValueByPath(fromObject, ['labels']) !== undefined) {\n throw new Error('labels parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['beta']) !== undefined) {\n throw new Error('beta parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['baseTeacherModel']) !== undefined) {\n throw new Error(\n 'baseTeacherModel parameter is not supported in Gemini API.',\n );\n }\n\n if (\n common.getValueByPath(fromObject, ['tunedTeacherModelSource']) !== undefined\n ) {\n throw new Error(\n 'tunedTeacherModelSource parameter is not supported in Gemini API.',\n );\n }\n\n if (\n common.getValueByPath(fromObject, ['sftLossWeightMultiplier']) !== undefined\n ) {\n throw new Error(\n 'sftLossWeightMultiplier parameter is not supported in Gemini API.',\n );\n }\n\n if (common.getValueByPath(fromObject, ['outputUri']) !== undefined) {\n throw new Error('outputUri parameter is not supported in Gemini API.');\n }\n\n if (common.getValueByPath(fromObject, ['encryptionSpec']) !== undefined) {\n throw new Error('encryptionSpec parameter is not supported in Gemini API.');\n }\n\n return toObject;\n}\n\nexport function createTuningJobConfigToVertex(\n fromObject: types.CreateTuningJobConfig,\n parentObject: Record<string, unknown>,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n let discriminatorValidationDataset = common.getValueByPath(rootObject, [\n 'config',\n 'method',\n ]);\n if (discriminatorValidationDataset === undefined) {\n discriminatorValidationDataset = 'SUPERVISED_FINE_TUNING';\n }\n if (discriminatorValidationDataset === 'SUPERVISED_FINE_TUNING') {\n const fromValidationDataset = common.getValueByPath(fromObject, [\n 'validationDataset',\n ]);\n if (parentObject !== undefined && fromValidationDataset != null) {\n common.setValueByPath(\n parentObject,\n ['supervisedTuningSpec'],\n tuningValidationDatasetToVertex(fromValidationDataset, rootObject),\n );\n }\n } else if (discriminatorValidationDataset === 'PREFERENCE_TUNING') {\n const fromValidationDataset = common.getValueByPath(fromObject, [\n 'validationDataset',\n ]);\n if (parentObject !== undefined && fromValidationDataset != null) {\n common.setValueByPath(\n parentObject,\n ['preferenceOptimizationSpec'],\n tuningValidationDatasetToVertex(fromValidationDataset, rootObject),\n );\n }\n } else if (discriminatorValidationDataset === 'DISTILLATION') {\n const fromValidationDataset = common.getValueByPath(fromObject, [\n 'validationDataset',\n ]);\n if (parentObject !== undefined && fromValidationDataset != null) {\n common.setValueByPath(\n parentObject,\n ['distillationSpec'],\n tuningValidationDatasetToVertex(fromValidationDataset, rootObject),\n );\n }\n }\n\n const fromTunedModelDisplayName = common.getValueByPath(fromObject, [\n 'tunedModelDisplayName',\n ]);\n if (parentObject !== undefined && fromTunedModelDisplayName != null) {\n common.setValueByPath(\n parentObject,\n ['tunedModelDisplayName'],\n fromTunedModelDisplayName,\n );\n }\n\n const fromDescription = common.getValueByPath(fromObject, ['description']);\n if (parentObject !== undefined && fromDescription != null) {\n common.setValueByPath(parentObject, ['description'], fromDescription);\n }\n\n let discriminatorEpochCount = common.getValueByPath(rootObject, [\n 'config',\n 'method',\n ]);\n if (discriminatorEpochCount === undefined) {\n discriminatorEpochCount = 'SUPERVISED_FINE_TUNING';\n }\n if (discriminatorEpochCount === 'SUPERVISED_FINE_TUNING') {\n const fromEpochCount = common.getValueByPath(fromObject, ['epochCount']);\n if (parentObject !== undefined && fromEpochCount != null) {\n common.setValueByPath(\n parentObject,\n ['supervisedTuningSpec', 'hyperParameters', 'epochCount'],\n fromEpochCount,\n );\n }\n } else if (discriminatorEpochCount === 'PREFERENCE_TUNING') {\n const fromEpochCount = common.getValueByPath(fromObject, ['epochCount']);\n if (parentObject !== undefined && fromEpochCount != null) {\n common.setValueByPath(\n parentObject,\n ['preferenceOptimizationSpec', 'hyperParameters', 'epochCount'],\n fromEpochCount,\n );\n }\n } else if (discriminatorEpochCount === 'DISTILLATION') {\n const fromEpochCount = common.getValueByPath(fromObject, ['epochCount']);\n if (parentObject !== undefined && fromEpochCount != null) {\n common.setValueByPath(\n parentObject,\n ['distillationSpec', 'hyperParameters', 'epochCount'],\n fromEpochCount,\n );\n }\n }\n\n let discriminatorLearningRateMultiplier = common.getValueByPath(rootObject, [\n 'config',\n 'method',\n ]);\n if (discriminatorLearningRateMultiplier === undefined) {\n discriminatorLearningRateMultiplier = 'SUPERVISED_FINE_TUNING';\n }\n if (discriminatorLearningRateMultiplier === 'SUPERVISED_FINE_TUNING') {\n const fromLearningRateMultiplier = common.getValueByPath(fromObject, [\n 'learningRateMultiplier',\n ]);\n if (parentObject !== undefined && fromLearningRateMultiplier != null) {\n common.setValueByPath(\n parentObject,\n ['supervisedTuningSpec', 'hyperParameters', 'learningRateMultiplier'],\n fromLearningRateMultiplier,\n );\n }\n } else if (discriminatorLearningRateMultiplier === 'PREFERENCE_TUNING') {\n const fromLearningRateMultiplier = common.getValueByPath(fromObject, [\n 'learningRateMultiplier',\n ]);\n if (parentObject !== undefined && fromLearningRateMultiplier != null) {\n common.setValueByPath(\n parentObject,\n [\n 'preferenceOptimizationSpec',\n 'hyperParameters',\n 'learningRateMultiplier',\n ],\n fromLearningRateMultiplier,\n );\n }\n } else if (discriminatorLearningRateMultiplier === 'DISTILLATION') {\n const fromLearningRateMultiplier = common.getValueByPath(fromObject, [\n 'learningRateMultiplier',\n ]);\n if (parentObject !== undefined && fromLearningRateMultiplier != null) {\n common.setValueByPath(\n parentObject,\n ['distillationSpec', 'hyperParameters', 'learningRateMultiplier'],\n fromLearningRateMultiplier,\n );\n }\n }\n\n let discriminatorExportLastCheckpointOnly = common.getValueByPath(\n rootObject,\n ['config', 'method'],\n );\n if (discriminatorExportLastCheckpointOnly === undefined) {\n discriminatorExportLastCheckpointOnly = 'SUPERVISED_FINE_TUNING';\n }\n if (discriminatorExportLastCheckpointOnly === 'SUPERVISED_FINE_TUNING') {\n const fromExportLastCheckpointOnly = common.getValueByPath(fromObject, [\n 'exportLastCheckpointOnly',\n ]);\n if (parentObject !== undefined && fromExportLastCheckpointOnly != null) {\n common.setValueByPath(\n parentObject,\n ['supervisedTuningSpec', 'exportLastCheckpointOnly'],\n fromExportLastCheckpointOnly,\n );\n }\n } else if (discriminatorExportLastCheckpointOnly === 'PREFERENCE_TUNING') {\n const fromExportLastCheckpointOnly = common.getValueByPath(fromObject, [\n 'exportLastCheckpointOnly',\n ]);\n if (parentObject !== undefined && fromExportLastCheckpointOnly != null) {\n common.setValueByPath(\n parentObject,\n ['preferenceOptimizationSpec', 'exportLastCheckpointOnly'],\n fromExportLastCheckpointOnly,\n );\n }\n } else if (discriminatorExportLastCheckpointOnly === 'DISTILLATION') {\n const fromExportLastCheckpointOnly = common.getValueByPath(fromObject, [\n 'exportLastCheckpointOnly',\n ]);\n if (parentObject !== undefined && fromExportLastCheckpointOnly != null) {\n common.setValueByPath(\n parentObject,\n ['distillationSpec', 'exportLastCheckpointOnly'],\n fromExportLastCheckpointOnly,\n );\n }\n }\n\n let discriminatorAdapterSize = common.getValueByPath(rootObject, [\n 'config',\n 'method',\n ]);\n if (discriminatorAdapterSize === undefined) {\n discriminatorAdapterSize = 'SUPERVISED_FINE_TUNING';\n }\n if (discriminatorAdapterSize === 'SUPERVISED_FINE_TUNING') {\n const fromAdapterSize = common.getValueByPath(fromObject, ['adapterSize']);\n if (parentObject !== undefined && fromAdapterSize != null) {\n common.setValueByPath(\n parentObject,\n ['supervisedTuningSpec', 'hyperParameters', 'adapterSize'],\n fromAdapterSize,\n );\n }\n } else if (discriminatorAdapterSize === 'PREFERENCE_TUNING') {\n const fromAdapterSize = common.getValueByPath(fromObject, ['adapterSize']);\n if (parentObject !== undefined && fromAdapterSize != null) {\n common.setValueByPath(\n parentObject,\n ['preferenceOptimizationSpec', 'hyperParameters', 'adapterSize'],\n fromAdapterSize,\n );\n }\n } else if (discriminatorAdapterSize === 'DISTILLATION') {\n const fromAdapterSize = common.getValueByPath(fromObject, ['adapterSize']);\n if (parentObject !== undefined && fromAdapterSize != null) {\n common.setValueByPath(\n parentObject,\n ['distillationSpec', 'hyperParameters', 'adapterSize'],\n fromAdapterSize,\n );\n }\n }\n\n let discriminatorTuningMode = common.getValueByPath(rootObject, [\n 'config',\n 'method',\n ]);\n if (discriminatorTuningMode === undefined) {\n discriminatorTuningMode = 'SUPERVISED_FINE_TUNING';\n }\n if (discriminatorTuningMode === 'SUPERVISED_FINE_TUNING') {\n const fromTuningMode = common.getValueByPath(fromObject, ['tuningMode']);\n if (parentObject !== undefined && fromTuningMode != null) {\n common.setValueByPath(\n parentObject,\n ['supervisedTuningSpec', 'tuningMode'],\n fromTuningMode,\n );\n }\n }\n\n const fromCustomBaseModel = common.getValueByPath(fromObject, [\n 'customBaseModel',\n ]);\n if (parentObject !== undefined && fromCustomBaseModel != null) {\n common.setValueByPath(\n parentObject,\n ['customBaseModel'],\n fromCustomBaseModel,\n );\n }\n\n let discriminatorBatchSize = common.getValueByPath(rootObject, [\n 'config',\n 'method',\n ]);\n if (discriminatorBatchSize === undefined) {\n discriminatorBatchSize = 'SUPERVISED_FINE_TUNING';\n }\n if (discriminatorBatchSize === 'SUPERVISED_FINE_TUNING') {\n const fromBatchSize = common.getValueByPath(fromObject, ['batchSize']);\n if (parentObject !== undefined && fromBatchSize != null) {\n common.setValueByPath(\n parentObject,\n ['supervisedTuningSpec', 'hyperParameters', 'batchSize'],\n fromBatchSize,\n );\n }\n }\n\n let discriminatorLearningRate = common.getValueByPath(rootObject, [\n 'config',\n 'method',\n ]);\n if (discriminatorLearningRate === undefined) {\n discriminatorLearningRate = 'SUPERVISED_FINE_TUNING';\n }\n if (discriminatorLearningRate === 'SUPERVISED_FINE_TUNING') {\n const fromLearningRate = common.getValueByPath(fromObject, [\n 'learningRate',\n ]);\n if (parentObject !== undefined && fromLearningRate != null) {\n common.setValueByPath(\n parentObject,\n ['supervisedTuningSpec', 'hyperParameters', 'learningRate'],\n fromLearningRate,\n );\n }\n }\n\n const fromLabels = common.getValueByPath(fromObject, ['labels']);\n if (parentObject !== undefined && fromLabels != null) {\n common.setValueByPath(parentObject, ['labels'], fromLabels);\n }\n\n const fromBeta = common.getValueByPath(fromObject, ['beta']);\n if (parentObject !== undefined && fromBeta != null) {\n common.setValueByPath(\n parentObject,\n ['preferenceOptimizationSpec', 'hyperParameters', 'beta'],\n fromBeta,\n );\n }\n\n const fromBaseTeacherModel = common.getValueByPath(fromObject, [\n 'baseTeacherModel',\n ]);\n if (parentObject !== undefined && fromBaseTeacherModel != null) {\n common.setValueByPath(\n parentObject,\n ['distillationSpec', 'baseTeacherModel'],\n fromBaseTeacherModel,\n );\n }\n\n const fromTunedTeacherModelSource = common.getValueByPath(fromObject, [\n 'tunedTeacherModelSource',\n ]);\n if (parentObject !== undefined && fromTunedTeacherModelSource != null) {\n common.setValueByPath(\n parentObject,\n ['distillationSpec', 'tunedTeacherModelSource'],\n fromTunedTeacherModelSource,\n );\n }\n\n const fromSftLossWeightMultiplier = common.getValueByPath(fromObject, [\n 'sftLossWeightMultiplier',\n ]);\n if (parentObject !== undefined && fromSftLossWeightMultiplier != null) {\n common.setValueByPath(\n parentObject,\n ['distillationSpec', 'hyperParameters', 'sftLossWeightMultiplier'],\n fromSftLossWeightMultiplier,\n );\n }\n\n const fromOutputUri = common.getValueByPath(fromObject, ['outputUri']);\n if (parentObject !== undefined && fromOutputUri != null) {\n common.setValueByPath(parentObject, ['outputUri'], fromOutputUri);\n }\n\n const fromEncryptionSpec = common.getValueByPath(fromObject, [\n 'encryptionSpec',\n ]);\n if (parentObject !== undefined && fromEncryptionSpec != null) {\n common.setValueByPath(parentObject, ['encryptionSpec'], fromEncryptionSpec);\n }\n\n return toObject;\n}\n\nexport function createTuningJobParametersPrivateToMldev(\n fromObject: types.CreateTuningJobParametersPrivate,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromBaseModel = common.getValueByPath(fromObject, ['baseModel']);\n if (fromBaseModel != null) {\n common.setValueByPath(toObject, ['baseModel'], fromBaseModel);\n }\n\n const fromPreTunedModel = common.getValueByPath(fromObject, [\n 'preTunedModel',\n ]);\n if (fromPreTunedModel != null) {\n common.setValueByPath(toObject, ['preTunedModel'], fromPreTunedModel);\n }\n\n const fromTrainingDataset = common.getValueByPath(fromObject, [\n 'trainingDataset',\n ]);\n if (fromTrainingDataset != null) {\n tuningDatasetToMldev(fromTrainingDataset, rootObject);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n createTuningJobConfigToMldev(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function createTuningJobParametersPrivateToVertex(\n fromObject: types.CreateTuningJobParametersPrivate,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromBaseModel = common.getValueByPath(fromObject, ['baseModel']);\n if (fromBaseModel != null) {\n common.setValueByPath(toObject, ['baseModel'], fromBaseModel);\n }\n\n const fromPreTunedModel = common.getValueByPath(fromObject, [\n 'preTunedModel',\n ]);\n if (fromPreTunedModel != null) {\n common.setValueByPath(toObject, ['preTunedModel'], fromPreTunedModel);\n }\n\n const fromTrainingDataset = common.getValueByPath(fromObject, [\n 'trainingDataset',\n ]);\n if (fromTrainingDataset != null) {\n tuningDatasetToVertex(fromTrainingDataset, toObject, rootObject);\n }\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n createTuningJobConfigToVertex(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function getTuningJobParametersToMldev(\n fromObject: types.GetTuningJobParameters,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['_url', 'name'], fromName);\n }\n\n return toObject;\n}\n\nexport function getTuningJobParametersToVertex(\n fromObject: types.GetTuningJobParameters,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['_url', 'name'], fromName);\n }\n\n return toObject;\n}\n\nexport function listTuningJobsConfigToMldev(\n fromObject: types.ListTuningJobsConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPageSize = common.getValueByPath(fromObject, ['pageSize']);\n if (parentObject !== undefined && fromPageSize != null) {\n common.setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize);\n }\n\n const fromPageToken = common.getValueByPath(fromObject, ['pageToken']);\n if (parentObject !== undefined && fromPageToken != null) {\n common.setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken);\n }\n\n const fromFilter = common.getValueByPath(fromObject, ['filter']);\n if (parentObject !== undefined && fromFilter != null) {\n common.setValueByPath(parentObject, ['_query', 'filter'], fromFilter);\n }\n\n return toObject;\n}\n\nexport function listTuningJobsConfigToVertex(\n fromObject: types.ListTuningJobsConfig,\n parentObject: Record<string, unknown>,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromPageSize = common.getValueByPath(fromObject, ['pageSize']);\n if (parentObject !== undefined && fromPageSize != null) {\n common.setValueByPath(parentObject, ['_query', 'pageSize'], fromPageSize);\n }\n\n const fromPageToken = common.getValueByPath(fromObject, ['pageToken']);\n if (parentObject !== undefined && fromPageToken != null) {\n common.setValueByPath(parentObject, ['_query', 'pageToken'], fromPageToken);\n }\n\n const fromFilter = common.getValueByPath(fromObject, ['filter']);\n if (parentObject !== undefined && fromFilter != null) {\n common.setValueByPath(parentObject, ['_query', 'filter'], fromFilter);\n }\n\n return toObject;\n}\n\nexport function listTuningJobsParametersToMldev(\n fromObject: types.ListTuningJobsParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n listTuningJobsConfigToMldev(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function listTuningJobsParametersToVertex(\n fromObject: types.ListTuningJobsParameters,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromConfig = common.getValueByPath(fromObject, ['config']);\n if (fromConfig != null) {\n listTuningJobsConfigToVertex(fromConfig, toObject, rootObject);\n }\n\n return toObject;\n}\n\nexport function listTuningJobsResponseFromMldev(\n fromObject: types.ListTuningJobsResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromNextPageToken = common.getValueByPath(fromObject, [\n 'nextPageToken',\n ]);\n if (fromNextPageToken != null) {\n common.setValueByPath(toObject, ['nextPageToken'], fromNextPageToken);\n }\n\n const fromTuningJobs = common.getValueByPath(fromObject, ['tunedModels']);\n if (fromTuningJobs != null) {\n let transformedList = fromTuningJobs;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return tuningJobFromMldev(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['tuningJobs'], transformedList);\n }\n\n return toObject;\n}\n\nexport function listTuningJobsResponseFromVertex(\n fromObject: types.ListTuningJobsResponse,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromNextPageToken = common.getValueByPath(fromObject, [\n 'nextPageToken',\n ]);\n if (fromNextPageToken != null) {\n common.setValueByPath(toObject, ['nextPageToken'], fromNextPageToken);\n }\n\n const fromTuningJobs = common.getValueByPath(fromObject, ['tuningJobs']);\n if (fromTuningJobs != null) {\n let transformedList = fromTuningJobs;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return tuningJobFromVertex(item, rootObject);\n });\n }\n common.setValueByPath(toObject, ['tuningJobs'], transformedList);\n }\n\n return toObject;\n}\n\nexport function tunedModelFromMldev(\n fromObject: types.TunedModel,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromModel = common.getValueByPath(fromObject, ['name']);\n if (fromModel != null) {\n common.setValueByPath(toObject, ['model'], fromModel);\n }\n\n const fromEndpoint = common.getValueByPath(fromObject, ['name']);\n if (fromEndpoint != null) {\n common.setValueByPath(toObject, ['endpoint'], fromEndpoint);\n }\n\n return toObject;\n}\n\nexport function tuningDatasetToMldev(\n fromObject: types.TuningDataset,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n if (common.getValueByPath(fromObject, ['gcsUri']) !== undefined) {\n throw new Error('gcsUri parameter is not supported in Gemini API.');\n }\n\n if (\n common.getValueByPath(fromObject, ['vertexDatasetResource']) !== undefined\n ) {\n throw new Error(\n 'vertexDatasetResource parameter is not supported in Gemini API.',\n );\n }\n\n const fromExamples = common.getValueByPath(fromObject, ['examples']);\n if (fromExamples != null) {\n let transformedList = fromExamples;\n if (Array.isArray(transformedList)) {\n transformedList = transformedList.map((item) => {\n return item;\n });\n }\n common.setValueByPath(toObject, ['examples', 'examples'], transformedList);\n }\n\n return toObject;\n}\n\nexport function tuningDatasetToVertex(\n fromObject: types.TuningDataset,\n parentObject: Record<string, unknown>,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n let discriminatorGcsUri = common.getValueByPath(rootObject, [\n 'config',\n 'method',\n ]);\n if (discriminatorGcsUri === undefined) {\n discriminatorGcsUri = 'SUPERVISED_FINE_TUNING';\n }\n if (discriminatorGcsUri === 'SUPERVISED_FINE_TUNING') {\n const fromGcsUri = common.getValueByPath(fromObject, ['gcsUri']);\n if (parentObject !== undefined && fromGcsUri != null) {\n common.setValueByPath(\n parentObject,\n ['supervisedTuningSpec', 'trainingDatasetUri'],\n fromGcsUri,\n );\n }\n } else if (discriminatorGcsUri === 'PREFERENCE_TUNING') {\n const fromGcsUri = common.getValueByPath(fromObject, ['gcsUri']);\n if (parentObject !== undefined && fromGcsUri != null) {\n common.setValueByPath(\n parentObject,\n ['preferenceOptimizationSpec', 'trainingDatasetUri'],\n fromGcsUri,\n );\n }\n } else if (discriminatorGcsUri === 'DISTILLATION') {\n const fromGcsUri = common.getValueByPath(fromObject, ['gcsUri']);\n if (parentObject !== undefined && fromGcsUri != null) {\n common.setValueByPath(\n parentObject,\n ['distillationSpec', 'promptDatasetUri'],\n fromGcsUri,\n );\n }\n }\n\n let discriminatorVertexDatasetResource = common.getValueByPath(rootObject, [\n 'config',\n 'method',\n ]);\n if (discriminatorVertexDatasetResource === undefined) {\n discriminatorVertexDatasetResource = 'SUPERVISED_FINE_TUNING';\n }\n if (discriminatorVertexDatasetResource === 'SUPERVISED_FINE_TUNING') {\n const fromVertexDatasetResource = common.getValueByPath(fromObject, [\n 'vertexDatasetResource',\n ]);\n if (parentObject !== undefined && fromVertexDatasetResource != null) {\n common.setValueByPath(\n parentObject,\n ['supervisedTuningSpec', 'trainingDatasetUri'],\n fromVertexDatasetResource,\n );\n }\n } else if (discriminatorVertexDatasetResource === 'PREFERENCE_TUNING') {\n const fromVertexDatasetResource = common.getValueByPath(fromObject, [\n 'vertexDatasetResource',\n ]);\n if (parentObject !== undefined && fromVertexDatasetResource != null) {\n common.setValueByPath(\n parentObject,\n ['preferenceOptimizationSpec', 'trainingDatasetUri'],\n fromVertexDatasetResource,\n );\n }\n } else if (discriminatorVertexDatasetResource === 'DISTILLATION') {\n const fromVertexDatasetResource = common.getValueByPath(fromObject, [\n 'vertexDatasetResource',\n ]);\n if (parentObject !== undefined && fromVertexDatasetResource != null) {\n common.setValueByPath(\n parentObject,\n ['distillationSpec', 'promptDatasetUri'],\n fromVertexDatasetResource,\n );\n }\n }\n if (common.getValueByPath(fromObject, ['examples']) !== undefined) {\n throw new Error('examples parameter is not supported in Vertex AI.');\n }\n\n return toObject;\n}\n\nexport function tuningJobFromMldev(\n fromObject: types.TuningJob,\n rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromState = common.getValueByPath(fromObject, ['state']);\n if (fromState != null) {\n common.setValueByPath(toObject, ['state'], t.tTuningJobStatus(fromState));\n }\n\n const fromCreateTime = common.getValueByPath(fromObject, ['createTime']);\n if (fromCreateTime != null) {\n common.setValueByPath(toObject, ['createTime'], fromCreateTime);\n }\n\n const fromStartTime = common.getValueByPath(fromObject, [\n 'tuningTask',\n 'startTime',\n ]);\n if (fromStartTime != null) {\n common.setValueByPath(toObject, ['startTime'], fromStartTime);\n }\n\n const fromEndTime = common.getValueByPath(fromObject, [\n 'tuningTask',\n 'completeTime',\n ]);\n if (fromEndTime != null) {\n common.setValueByPath(toObject, ['endTime'], fromEndTime);\n }\n\n const fromUpdateTime = common.getValueByPath(fromObject, ['updateTime']);\n if (fromUpdateTime != null) {\n common.setValueByPath(toObject, ['updateTime'], fromUpdateTime);\n }\n\n const fromDescription = common.getValueByPath(fromObject, ['description']);\n if (fromDescription != null) {\n common.setValueByPath(toObject, ['description'], fromDescription);\n }\n\n const fromBaseModel = common.getValueByPath(fromObject, ['baseModel']);\n if (fromBaseModel != null) {\n common.setValueByPath(toObject, ['baseModel'], fromBaseModel);\n }\n\n const fromTunedModel = common.getValueByPath(fromObject, ['_self']);\n if (fromTunedModel != null) {\n common.setValueByPath(\n toObject,\n ['tunedModel'],\n tunedModelFromMldev(fromTunedModel, rootObject),\n );\n }\n\n return toObject;\n}\n\nexport function tuningJobFromVertex(\n fromObject: types.TuningJob,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromState = common.getValueByPath(fromObject, ['state']);\n if (fromState != null) {\n common.setValueByPath(toObject, ['state'], t.tTuningJobStatus(fromState));\n }\n\n const fromCreateTime = common.getValueByPath(fromObject, ['createTime']);\n if (fromCreateTime != null) {\n common.setValueByPath(toObject, ['createTime'], fromCreateTime);\n }\n\n const fromStartTime = common.getValueByPath(fromObject, ['startTime']);\n if (fromStartTime != null) {\n common.setValueByPath(toObject, ['startTime'], fromStartTime);\n }\n\n const fromEndTime = common.getValueByPath(fromObject, ['endTime']);\n if (fromEndTime != null) {\n common.setValueByPath(toObject, ['endTime'], fromEndTime);\n }\n\n const fromUpdateTime = common.getValueByPath(fromObject, ['updateTime']);\n if (fromUpdateTime != null) {\n common.setValueByPath(toObject, ['updateTime'], fromUpdateTime);\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n const fromDescription = common.getValueByPath(fromObject, ['description']);\n if (fromDescription != null) {\n common.setValueByPath(toObject, ['description'], fromDescription);\n }\n\n const fromBaseModel = common.getValueByPath(fromObject, ['baseModel']);\n if (fromBaseModel != null) {\n common.setValueByPath(toObject, ['baseModel'], fromBaseModel);\n }\n\n const fromTunedModel = common.getValueByPath(fromObject, ['tunedModel']);\n if (fromTunedModel != null) {\n common.setValueByPath(toObject, ['tunedModel'], fromTunedModel);\n }\n\n const fromPreTunedModel = common.getValueByPath(fromObject, [\n 'preTunedModel',\n ]);\n if (fromPreTunedModel != null) {\n common.setValueByPath(toObject, ['preTunedModel'], fromPreTunedModel);\n }\n\n const fromSupervisedTuningSpec = common.getValueByPath(fromObject, [\n 'supervisedTuningSpec',\n ]);\n if (fromSupervisedTuningSpec != null) {\n common.setValueByPath(\n toObject,\n ['supervisedTuningSpec'],\n fromSupervisedTuningSpec,\n );\n }\n\n const fromPreferenceOptimizationSpec = common.getValueByPath(fromObject, [\n 'preferenceOptimizationSpec',\n ]);\n if (fromPreferenceOptimizationSpec != null) {\n common.setValueByPath(\n toObject,\n ['preferenceOptimizationSpec'],\n fromPreferenceOptimizationSpec,\n );\n }\n\n const fromDistillationSpec = common.getValueByPath(fromObject, [\n 'distillationSpec',\n ]);\n if (fromDistillationSpec != null) {\n common.setValueByPath(toObject, ['distillationSpec'], fromDistillationSpec);\n }\n\n const fromTuningDataStats = common.getValueByPath(fromObject, [\n 'tuningDataStats',\n ]);\n if (fromTuningDataStats != null) {\n common.setValueByPath(toObject, ['tuningDataStats'], fromTuningDataStats);\n }\n\n const fromEncryptionSpec = common.getValueByPath(fromObject, [\n 'encryptionSpec',\n ]);\n if (fromEncryptionSpec != null) {\n common.setValueByPath(toObject, ['encryptionSpec'], fromEncryptionSpec);\n }\n\n const fromPartnerModelTuningSpec = common.getValueByPath(fromObject, [\n 'partnerModelTuningSpec',\n ]);\n if (fromPartnerModelTuningSpec != null) {\n common.setValueByPath(\n toObject,\n ['partnerModelTuningSpec'],\n fromPartnerModelTuningSpec,\n );\n }\n\n const fromCustomBaseModel = common.getValueByPath(fromObject, [\n 'customBaseModel',\n ]);\n if (fromCustomBaseModel != null) {\n common.setValueByPath(toObject, ['customBaseModel'], fromCustomBaseModel);\n }\n\n const fromExperiment = common.getValueByPath(fromObject, ['experiment']);\n if (fromExperiment != null) {\n common.setValueByPath(toObject, ['experiment'], fromExperiment);\n }\n\n const fromLabels = common.getValueByPath(fromObject, ['labels']);\n if (fromLabels != null) {\n common.setValueByPath(toObject, ['labels'], fromLabels);\n }\n\n const fromOutputUri = common.getValueByPath(fromObject, ['outputUri']);\n if (fromOutputUri != null) {\n common.setValueByPath(toObject, ['outputUri'], fromOutputUri);\n }\n\n const fromPipelineJob = common.getValueByPath(fromObject, ['pipelineJob']);\n if (fromPipelineJob != null) {\n common.setValueByPath(toObject, ['pipelineJob'], fromPipelineJob);\n }\n\n const fromServiceAccount = common.getValueByPath(fromObject, [\n 'serviceAccount',\n ]);\n if (fromServiceAccount != null) {\n common.setValueByPath(toObject, ['serviceAccount'], fromServiceAccount);\n }\n\n const fromTunedModelDisplayName = common.getValueByPath(fromObject, [\n 'tunedModelDisplayName',\n ]);\n if (fromTunedModelDisplayName != null) {\n common.setValueByPath(\n toObject,\n ['tunedModelDisplayName'],\n fromTunedModelDisplayName,\n );\n }\n\n const fromVeoTuningSpec = common.getValueByPath(fromObject, [\n 'veoTuningSpec',\n ]);\n if (fromVeoTuningSpec != null) {\n common.setValueByPath(toObject, ['veoTuningSpec'], fromVeoTuningSpec);\n }\n\n return toObject;\n}\n\nexport function tuningOperationFromMldev(\n fromObject: types.TuningOperation,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromSdkHttpResponse = common.getValueByPath(fromObject, [\n 'sdkHttpResponse',\n ]);\n if (fromSdkHttpResponse != null) {\n common.setValueByPath(toObject, ['sdkHttpResponse'], fromSdkHttpResponse);\n }\n\n const fromName = common.getValueByPath(fromObject, ['name']);\n if (fromName != null) {\n common.setValueByPath(toObject, ['name'], fromName);\n }\n\n const fromMetadata = common.getValueByPath(fromObject, ['metadata']);\n if (fromMetadata != null) {\n common.setValueByPath(toObject, ['metadata'], fromMetadata);\n }\n\n const fromDone = common.getValueByPath(fromObject, ['done']);\n if (fromDone != null) {\n common.setValueByPath(toObject, ['done'], fromDone);\n }\n\n const fromError = common.getValueByPath(fromObject, ['error']);\n if (fromError != null) {\n common.setValueByPath(toObject, ['error'], fromError);\n }\n\n return toObject;\n}\n\nexport function tuningValidationDatasetToVertex(\n fromObject: types.TuningValidationDataset,\n _rootObject?: unknown,\n): Record<string, unknown> {\n const toObject: Record<string, unknown> = {};\n\n const fromGcsUri = common.getValueByPath(fromObject, ['gcsUri']);\n if (fromGcsUri != null) {\n common.setValueByPath(toObject, ['validationDatasetUri'], fromGcsUri);\n }\n\n const fromVertexDatasetResource = common.getValueByPath(fromObject, [\n 'vertexDatasetResource',\n ]);\n if (fromVertexDatasetResource != null) {\n common.setValueByPath(\n toObject,\n ['validationDatasetUri'],\n fromVertexDatasetResource,\n );\n }\n\n return toObject;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Code generated by the Google Gen AI SDK generator DO NOT EDIT.\n\nimport {ApiClient} from './_api_client.js';\nimport * as common from './_common.js';\nimport {BaseModule} from './_common.js';\nimport * as converters from './converters/_tunings_converters.js';\nimport {PagedItem, Pager} from './pagers.js';\nimport * as types from './types.js';\n\nexport class Tunings extends BaseModule {\n constructor(private readonly apiClient: ApiClient) {\n super();\n }\n\n /**\n * Lists tuning jobs.\n *\n * @param params - The parameters for the list request.\n * @return - A pager of tuning jobs.\n *\n * @example\n * ```ts\n * const tuningJobs = await ai.tunings.list({config: {'pageSize': 2}});\n * for await (const tuningJob of tuningJobs) {\n * console.log(tuningJob);\n * }\n * ```\n */\n list = async (\n params: types.ListTuningJobsParameters = {},\n ): Promise<Pager<types.TuningJob>> => {\n return new Pager<types.TuningJob>(\n PagedItem.PAGED_ITEM_TUNING_JOBS,\n (x: types.ListTuningJobsParameters) => this.listInternal(x),\n await this.listInternal(params),\n params,\n );\n };\n\n /**\n * Gets a TuningJob.\n *\n * @param name - The resource name of the tuning job.\n * @return - A TuningJob object.\n *\n * @experimental - The SDK's tuning implementation is experimental, and may\n * change in future versions.\n */\n get = async (\n params: types.GetTuningJobParameters,\n ): Promise<types.TuningJob> => {\n return await this.getInternal(params);\n };\n\n /**\n * Creates a supervised fine-tuning job.\n *\n * @param params - The parameters for the tuning job.\n * @return - A TuningJob operation.\n *\n * @experimental - The SDK's tuning implementation is experimental, and may\n * change in future versions.\n */\n tune = async (\n params: types.CreateTuningJobParameters,\n ): Promise<types.TuningJob> => {\n if (this.apiClient.isVertexAI()) {\n if (params.baseModel.startsWith('projects/')) {\n const preTunedModel: types.PreTunedModel = {\n tunedModelName: params.baseModel,\n };\n if (params.config?.preTunedModelCheckpointId) {\n preTunedModel.checkpointId = params.config.preTunedModelCheckpointId;\n }\n const paramsPrivate: types.CreateTuningJobParametersPrivate = {\n ...params,\n preTunedModel: preTunedModel,\n };\n paramsPrivate.baseModel = undefined;\n return await this.tuneInternal(paramsPrivate);\n } else {\n const paramsPrivate: types.CreateTuningJobParametersPrivate = {\n ...params,\n };\n return await this.tuneInternal(paramsPrivate);\n }\n } else {\n const paramsPrivate: types.CreateTuningJobParametersPrivate = {\n ...params,\n };\n const operation = await this.tuneMldevInternal(paramsPrivate);\n let tunedModelName = '';\n if (\n operation['metadata'] !== undefined &&\n operation['metadata']['tunedModel'] !== undefined\n ) {\n tunedModelName = operation['metadata']['tunedModel'] as string;\n } else if (\n operation['name'] !== undefined &&\n operation['name'].includes('/operations/')\n ) {\n tunedModelName = operation['name'].split('/operations/')[0];\n }\n const tuningJob: types.TuningJob = {\n name: tunedModelName,\n state: types.JobState.JOB_STATE_QUEUED,\n };\n\n return tuningJob;\n }\n };\n\n private async getInternal(\n params: types.GetTuningJobParameters,\n ): Promise<types.TuningJob> {\n let response: Promise<types.TuningJob>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.getTuningJobParametersToVertex(params, params);\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.TuningJob;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.TuningJob>;\n\n return response.then((apiResponse) => {\n const resp = converters.tuningJobFromVertex(apiResponse, params);\n\n return resp as types.TuningJob;\n });\n } else {\n const body = converters.getTuningJobParametersToMldev(params, params);\n path = common.formatMap(\n '{name}',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.TuningJob;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.TuningJob>;\n\n return response.then((apiResponse) => {\n const resp = converters.tuningJobFromMldev(apiResponse, params);\n\n return resp as types.TuningJob;\n });\n }\n }\n\n private async listInternal(\n params: types.ListTuningJobsParameters,\n ): Promise<types.ListTuningJobsResponse> {\n let response: Promise<types.ListTuningJobsResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.listTuningJobsParametersToVertex(params, params);\n path = common.formatMap(\n 'tuningJobs',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.ListTuningJobsResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.ListTuningJobsResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.listTuningJobsResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.ListTuningJobsResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n const body = converters.listTuningJobsParametersToMldev(params, params);\n path = common.formatMap(\n 'tunedModels',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'GET',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.ListTuningJobsResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.ListTuningJobsResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.listTuningJobsResponseFromMldev(\n apiResponse,\n params,\n );\n const typedResp = new types.ListTuningJobsResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n /**\n * Cancels a tuning job.\n *\n * @param params - The parameters for the cancel request.\n * @return The empty response returned by the API.\n *\n * @example\n * ```ts\n * await ai.tunings.cancel({name: '...'}); // The server-generated resource name.\n * ```\n */\n async cancel(\n params: types.CancelTuningJobParameters,\n ): Promise<types.CancelTuningJobResponse> {\n let response: Promise<types.CancelTuningJobResponse>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.cancelTuningJobParametersToVertex(params, params);\n path = common.formatMap(\n '{name}:cancel',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.CancelTuningJobResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.CancelTuningJobResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.cancelTuningJobResponseFromVertex(\n apiResponse,\n params,\n );\n const typedResp = new types.CancelTuningJobResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n } else {\n const body = converters.cancelTuningJobParametersToMldev(params, params);\n path = common.formatMap(\n '{name}:cancel',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.CancelTuningJobResponse;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.CancelTuningJobResponse>;\n\n return response.then((apiResponse) => {\n const resp = converters.cancelTuningJobResponseFromMldev(\n apiResponse,\n params,\n );\n const typedResp = new types.CancelTuningJobResponse();\n Object.assign(typedResp, resp);\n return typedResp;\n });\n }\n }\n\n private async tuneInternal(\n params: types.CreateTuningJobParametersPrivate,\n ): Promise<types.TuningJob> {\n let response: Promise<types.TuningJob>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n const body = converters.createTuningJobParametersPrivateToVertex(\n params,\n params,\n );\n path = common.formatMap(\n 'tuningJobs',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.TuningJob;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.TuningJob>;\n\n return response.then((apiResponse) => {\n const resp = converters.tuningJobFromVertex(apiResponse, params);\n\n return resp as types.TuningJob;\n });\n } else {\n throw new Error('This method is only supported by the Vertex AI.');\n }\n }\n\n private async tuneMldevInternal(\n params: types.CreateTuningJobParametersPrivate,\n ): Promise<types.TuningOperation> {\n let response: Promise<types.TuningOperation>;\n\n let path: string = '';\n let queryParams: Record<string, string> = {};\n if (this.apiClient.isVertexAI()) {\n throw new Error(\n 'This method is only supported by the Gemini Developer API.',\n );\n } else {\n const body = converters.createTuningJobParametersPrivateToMldev(\n params,\n params,\n );\n path = common.formatMap(\n 'tunedModels',\n body['_url'] as Record<string, unknown>,\n );\n queryParams = body['_query'] as Record<string, string>;\n delete body['_url'];\n delete body['_query'];\n\n response = this.apiClient\n .request({\n path: path,\n queryParams: queryParams,\n body: JSON.stringify(body),\n httpMethod: 'POST',\n httpOptions: params.config?.httpOptions,\n abortSignal: params.config?.abortSignal,\n })\n .then((httpResponse) => {\n return httpResponse.json().then((jsonResponse) => {\n const response = jsonResponse as types.TuningOperation;\n response.sdkHttpResponse = {\n headers: httpResponse.headers,\n } as types.HttpResponse;\n return response;\n });\n }) as Promise<types.TuningOperation>;\n\n return response.then((apiResponse) => {\n const resp = converters.tuningOperationFromMldev(apiResponse, params);\n\n return resp as types.TuningOperation;\n });\n }\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {ApiClient} from '../_api_client.js';\nimport {Downloader} from '../_downloader.js';\nimport {DownloadFileParameters} from '../types.js';\n\nexport class BrowserDownloader implements Downloader {\n async download(\n _params: DownloadFileParameters,\n _apiClient: ApiClient,\n ): Promise<void> {\n throw new Error(\n 'Download to file is not supported in the browser, please use a browser compliant download like an <a> tag.',\n );\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {ApiClient} from '../_api_client.js';\nimport {FileStat, Uploader} from '../_uploader.js';\nimport * as _converters from '../converters/_operations_converters.js';\nimport {\n File,\n HttpResponse,\n UploadToFileSearchStoreOperation,\n} from '../types.js';\nimport {crossError} from './_cross_error.js';\n\nexport const MAX_CHUNK_SIZE = 1024 * 1024 * 8; // bytes\nexport const MAX_RETRY_COUNT = 3;\nexport const INITIAL_RETRY_DELAY_MS = 1000;\nexport const DELAY_MULTIPLIER = 2;\nexport const X_GOOG_UPLOAD_STATUS_HEADER_FIELD = 'x-goog-upload-status';\n\nexport class CrossUploader implements Uploader {\n async upload(\n file: string | Blob,\n uploadUrl: string,\n apiClient: ApiClient,\n ): Promise<File> {\n if (typeof file === 'string') {\n throw crossError();\n } else {\n return uploadBlob(file, uploadUrl, apiClient);\n }\n }\n\n async uploadToFileSearchStore(\n file: string | Blob,\n uploadUrl: string,\n apiClient: ApiClient,\n ): Promise<UploadToFileSearchStoreOperation> {\n if (typeof file === 'string') {\n throw crossError();\n } else {\n return uploadBlobToFileSearchStore(file, uploadUrl, apiClient);\n }\n }\n\n async stat(file: string | Blob): Promise<FileStat> {\n if (typeof file === 'string') {\n throw crossError();\n } else {\n return getBlobStat(file);\n }\n }\n}\n\nexport async function uploadBlob(\n file: Blob,\n uploadUrl: string,\n apiClient: ApiClient,\n): Promise<File> {\n const response = await uploadBlobInternal(file, uploadUrl, apiClient);\n const responseJson = (await response?.json()) as Record<\n string,\n File | unknown\n >;\n if (response?.headers?.[X_GOOG_UPLOAD_STATUS_HEADER_FIELD] !== 'final') {\n throw new Error('Failed to upload file: Upload status is not finalized.');\n }\n return responseJson['file'] as File;\n}\n\nexport async function uploadBlobToFileSearchStore(\n file: Blob,\n uploadUrl: string,\n apiClient: ApiClient,\n): Promise<UploadToFileSearchStoreOperation> {\n const response = await uploadBlobInternal(file, uploadUrl, apiClient);\n const responseJson =\n (await response?.json()) as UploadToFileSearchStoreOperation;\n if (response?.headers?.[X_GOOG_UPLOAD_STATUS_HEADER_FIELD] !== 'final') {\n throw new Error('Failed to upload file: Upload status is not finalized.');\n }\n const resp =\n _converters.uploadToFileSearchStoreOperationFromMldev(responseJson);\n const typedResp = new UploadToFileSearchStoreOperation();\n Object.assign(typedResp, resp);\n return typedResp;\n}\n\nasync function uploadBlobInternal(\n file: Blob,\n uploadUrl: string,\n apiClient: ApiClient,\n): Promise<HttpResponse> {\n let fileSize = 0;\n let offset = 0;\n let response: HttpResponse = new HttpResponse(new Response());\n let uploadCommand = 'upload';\n fileSize = file.size;\n while (offset < fileSize) {\n const chunkSize = Math.min(MAX_CHUNK_SIZE, fileSize - offset);\n const chunk = file.slice(offset, offset + chunkSize);\n if (offset + chunkSize >= fileSize) {\n uploadCommand += ', finalize';\n }\n let retryCount = 0;\n let currentDelayMs = INITIAL_RETRY_DELAY_MS;\n while (retryCount < MAX_RETRY_COUNT) {\n response = await apiClient.request({\n path: '',\n body: chunk,\n httpMethod: 'POST',\n httpOptions: {\n apiVersion: '',\n baseUrl: uploadUrl,\n headers: {\n 'X-Goog-Upload-Command': uploadCommand,\n 'X-Goog-Upload-Offset': String(offset),\n 'Content-Length': String(chunkSize),\n },\n },\n });\n if (response?.headers?.[X_GOOG_UPLOAD_STATUS_HEADER_FIELD]) {\n break;\n }\n retryCount++;\n await sleep(currentDelayMs);\n currentDelayMs = currentDelayMs * DELAY_MULTIPLIER;\n }\n offset += chunkSize;\n // The `x-goog-upload-status` header field can be `active`, `final` and\n //`cancelled` in resposne.\n if (response?.headers?.[X_GOOG_UPLOAD_STATUS_HEADER_FIELD] !== 'active') {\n break;\n }\n // TODO(b/401391430) Investigate why the upload status is not finalized\n // even though all content has been uploaded.\n if (fileSize <= offset) {\n throw new Error(\n 'All content has been uploaded, but the upload status is not finalized.',\n );\n }\n }\n\n return response;\n}\n\nexport async function getBlobStat(file: Blob): Promise<FileStat> {\n const fileStat: FileStat = {size: file.size, type: file.type};\n return fileStat;\n}\n\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolvePromise) => setTimeout(resolvePromise, ms));\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {ApiClient} from '../_api_client.js';\nimport {FileStat, Uploader} from '../_uploader.js';\nimport {\n getBlobStat,\n uploadBlob,\n uploadBlobToFileSearchStore,\n} from '../cross/_cross_uploader.js';\nimport {File, UploadToFileSearchStoreOperation} from '../types.js';\n\nexport class BrowserUploader implements Uploader {\n async upload(\n file: string | Blob,\n uploadUrl: string,\n apiClient: ApiClient,\n ): Promise<File> {\n if (typeof file === 'string') {\n throw new Error('File path is not supported in browser uploader.');\n }\n\n return await uploadBlob(file, uploadUrl, apiClient);\n }\n\n async uploadToFileSearchStore(\n file: string | Blob,\n uploadUrl: string,\n apiClient: ApiClient,\n ): Promise<UploadToFileSearchStoreOperation> {\n if (typeof file === 'string') {\n throw new Error('File path is not supported in browser uploader.');\n }\n\n return await uploadBlobToFileSearchStore(file, uploadUrl, apiClient);\n }\n\n async stat(file: string | Blob): Promise<FileStat> {\n if (typeof file === 'string') {\n throw new Error('File path is not supported in browser uploader.');\n } else {\n return await getBlobStat(file);\n }\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {\n WebSocketCallbacks,\n WebSocketFactory,\n WebSocket as Ws,\n} from '../_websocket.js';\n\nexport class BrowserWebSocketFactory implements WebSocketFactory {\n create(\n url: string,\n headers: Record<string, string>,\n callbacks: WebSocketCallbacks,\n ): Ws {\n return new BrowserWebSocket(url, headers, callbacks);\n }\n}\n\nexport class BrowserWebSocket implements Ws {\n private ws?: WebSocket;\n\n constructor(\n private readonly url: string,\n private readonly headers: Record<string, string>,\n private readonly callbacks: WebSocketCallbacks,\n ) {}\n\n connect(): void {\n this.ws = new WebSocket(this.url);\n\n this.ws.onopen = this.callbacks.onopen;\n this.ws.onerror = this.callbacks.onerror;\n this.ws.onclose = this.callbacks.onclose;\n this.ws.onmessage = this.callbacks.onmessage;\n }\n\n send(message: string) {\n if (this.ws === undefined) {\n throw new Error('WebSocket is not connected');\n }\n\n this.ws.send(message);\n }\n\n close() {\n if (this.ws === undefined) {\n throw new Error('WebSocket is not connected');\n }\n\n this.ws.close();\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {Auth} from '../_auth.js';\n\nexport const GOOGLE_API_KEY_HEADER = 'x-goog-api-key';\n// TODO(b/395122533): We need a secure client side authentication mechanism.\nexport class WebAuth implements Auth {\n constructor(private readonly apiKey: string) {}\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n async addAuthHeaders(headers: Headers, url?: string): Promise<void> {\n if (headers.get(GOOGLE_API_KEY_HEADER) !== null) {\n return;\n }\n\n if (this.apiKey.startsWith('auth_tokens/')) {\n throw new Error('Ephemeral tokens are only supported by the live API.');\n }\n\n // Check if API key is empty or null\n if (!this.apiKey) {\n throw new Error('API key is missing. Please provide a valid API key.');\n }\n headers.append(GOOGLE_API_KEY_HEADER, this.apiKey);\n }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {ApiClient} from '../_api_client.js';\nimport {getBaseUrl} from '../_base_url.js';\nimport {Batches} from '../batches.js';\nimport {Caches} from '../caches.js';\nimport {Chats} from '../chats.js';\nimport {GoogleGenAIOptions} from '../client.js';\nimport {Files} from '../files.js';\nimport {FileSearchStores} from '../filesearchstores.js';\nimport GeminiNextGenAPI from '../interactions/index.js';\nimport {Interactions as GeminiNextGenInteractions} from '../interactions/resources/interactions.js';\nimport {Live} from '../live.js';\nimport {Models} from '../models.js';\nimport {Operations} from '../operations.js';\nimport {Tokens} from '../tokens.js';\nimport {Tunings} from '../tunings.js';\nimport {HttpOptions} from '../types.js';\n\nimport {BrowserDownloader} from './_browser_downloader.js';\nimport {BrowserUploader} from './_browser_uploader.js';\nimport {BrowserWebSocketFactory} from './_browser_websocket.js';\nimport {WebAuth} from './_web_auth.js';\n\nconst LANGUAGE_LABEL_PREFIX = 'gl-node/';\n\n/**\n * The Google GenAI SDK.\n *\n * @remarks\n * Provides access to the GenAI features through either the {@link\n * https://cloud.google.com/vertex-ai/docs/reference/rest | Gemini API} or\n * the {@link https://cloud.google.com/vertex-ai/docs/reference/rest | Vertex AI\n * API}.\n *\n * The {@link GoogleGenAIOptions.vertexai} value determines which of the API\n * services to use.\n *\n * When using the Gemini API, a {@link GoogleGenAIOptions.apiKey} must also be\n * set. When using Vertex AI, currently only {@link GoogleGenAIOptions.apiKey}\n * is supported via Express mode. {@link GoogleGenAIOptions.project} and {@link\n * GoogleGenAIOptions.location} should not be set.\n *\n * @example\n * Initializing the SDK for using the Gemini API:\n * ```ts\n * import {GoogleGenAI} from '@google/genai';\n * const ai = new GoogleGenAI({apiKey: 'GEMINI_API_KEY'});\n * ```\n *\n * @example\n * Initializing the SDK for using the Vertex AI API:\n * ```ts\n * import {GoogleGenAI} from '@google/genai';\n * const ai = new GoogleGenAI({\n * vertexai: true,\n * project: 'PROJECT_ID',\n * location: 'PROJECT_LOCATION'\n * });\n * ```\n *\n */\nexport class GoogleGenAI {\n protected readonly apiClient: ApiClient;\n private readonly apiKey?: string;\n public readonly vertexai: boolean;\n private readonly apiVersion?: string;\n private readonly httpOptions?: HttpOptions;\n readonly models: Models;\n readonly live: Live;\n readonly batches: Batches;\n readonly chats: Chats;\n readonly caches: Caches;\n readonly files: Files;\n readonly operations: Operations;\n readonly authTokens: Tokens;\n readonly tunings: Tunings;\n readonly fileSearchStores: FileSearchStores;\n private _interactions: GeminiNextGenInteractions | undefined;\n get interactions(): GeminiNextGenInteractions {\n if (this._interactions !== undefined) {\n return this._interactions;\n }\n\n console.warn(\n 'GoogleGenAI.interactions: Interactions usage is experimental and may change in future versions.',\n );\n\n const httpOpts = this.httpOptions;\n\n // Unsupported Options Warnings\n if (httpOpts?.extraBody) {\n console.warn(\n 'GoogleGenAI.interactions: Client level httpOptions.extraBody is not supported by the interactions client and will be ignored.',\n );\n }\n\n const nextGenClient = new GeminiNextGenAPI({\n baseURL: this.apiClient.getBaseUrl(),\n apiKey: this.apiKey,\n apiVersion: this.apiClient.getApiVersion(),\n clientAdapter: this.apiClient,\n defaultHeaders: this.apiClient.getDefaultHeaders(),\n timeout: httpOpts?.timeout,\n maxRetries: httpOpts?.retryOptions?.attempts,\n });\n this._interactions = nextGenClient.interactions;\n\n return this._interactions;\n }\n constructor(options: GoogleGenAIOptions) {\n if (options.apiKey == null) {\n throw new Error('An API Key must be set when running in a browser');\n }\n // Web client only supports API key mode for Vertex AI.\n if (options.project || options.location) {\n throw new Error(\n 'Vertex AI project based authentication is not supported on browser runtimes. Please do not provide a project or location.',\n );\n }\n this.vertexai = options.vertexai ?? false;\n\n this.apiKey = options.apiKey;\n\n const baseUrl = getBaseUrl(\n options.httpOptions,\n options.vertexai,\n /*vertexBaseUrlFromEnv*/ undefined,\n /*geminiBaseUrlFromEnv*/ undefined,\n );\n if (baseUrl) {\n if (options.httpOptions) {\n options.httpOptions.baseUrl = baseUrl;\n } else {\n options.httpOptions = {baseUrl: baseUrl};\n }\n }\n\n this.apiVersion = options.apiVersion;\n this.httpOptions = options.httpOptions;\n const auth = new WebAuth(this.apiKey);\n this.apiClient = new ApiClient({\n auth: auth,\n apiVersion: this.apiVersion,\n apiKey: this.apiKey,\n vertexai: this.vertexai,\n httpOptions: this.httpOptions,\n userAgentExtra: LANGUAGE_LABEL_PREFIX + 'web',\n uploader: new BrowserUploader(),\n downloader: new BrowserDownloader(),\n });\n this.models = new Models(this.apiClient);\n this.live = new Live(this.apiClient, auth, new BrowserWebSocketFactory());\n this.batches = new Batches(this.apiClient);\n this.chats = new Chats(this.models, this.apiClient);\n this.caches = new Caches(this.apiClient);\n this.files = new Files(this.apiClient);\n this.operations = new Operations(this.apiClient);\n this.authTokens = new Tokens(this.apiClient);\n this.tunings = new Tunings(this.apiClient);\n this.fileSearchStores = new FileSearchStores(this.apiClient);\n }\n}\n"],"names":["tBytes","common.getValueByPath","common.setValueByPath","generateVideosOperationFromMldev","generateVideosResponseFromMldev","generateVideosOperationFromVertex","generateVideosResponseFromVertex","generatedVideoFromMldev","generatedVideoFromVertex","videoFromMldev","videoFromVertex","importFileOperationFromMldev","importFileResponseFromMldev","t.tBytes","types.Type","baseTransformers.tBytes","t.tJobState","t.tRecvBatchJobDestination","blobToMldev","t.tBatchJobName","candidateFromMldev","citationMetadataFromMldev","contentToMldev","partToMldev","t.tBatchJobDestination","t.tModel","t.tBatchJobSource","t.tContentsForEmbed","embedContentConfigToMldev","common.moveValueByPath","fileDataToMldev","functionCallToMldev","functionCallingConfigToMldev","generateContentConfigToMldev","t.tContent","t.tSchema","safetySettingToMldev","t.tTools","toolToMldev","t.tTool","toolConfigToMldev","t.tCachedContentName","t.tSpeechConfig","imageConfigToMldev","generateContentResponseFromMldev","googleMapsToMldev","googleSearchToMldev","t.tContents","converters.createBatchJobParametersToMldev","common.formatMap","converters.createBatchJobParametersToVertex","converters.batchJobFromVertex","converters.batchJobFromMldev","converters.createEmbeddingsBatchJobParametersToMldev","converters.getBatchJobParametersToVertex","converters.getBatchJobParametersToMldev","converters.cancelBatchJobParametersToVertex","converters.cancelBatchJobParametersToMldev","converters.listBatchJobsParametersToVertex","converters.listBatchJobsResponseFromVertex","types.ListBatchJobsResponse","converters.listBatchJobsParametersToMldev","converters.listBatchJobsResponseFromMldev","converters.deleteBatchJobParametersToVertex","converters.deleteResourceJobFromVertex","converters.deleteBatchJobParametersToMldev","converters.deleteResourceJobFromMldev","toolToVertex","t.tCachesModel","functionDeclarationToVertex","converters.createCachedContentParametersToVertex","converters.createCachedContentParametersToMldev","converters.getCachedContentParametersToVertex","converters.getCachedContentParametersToMldev","converters.deleteCachedContentParametersToVertex","converters.deleteCachedContentResponseFromVertex","types.DeleteCachedContentResponse","converters.deleteCachedContentParametersToMldev","converters.deleteCachedContentResponseFromMldev","converters.updateCachedContentParametersToVertex","converters.updateCachedContentParametersToMldev","converters.listCachedContentsParametersToVertex","converters.listCachedContentsResponseFromVertex","types.ListCachedContentsResponse","converters.listCachedContentsParametersToMldev","converters.listCachedContentsResponseFromMldev","t.tFileName","converters.listFilesParametersToMldev","converters.listFilesResponseFromMldev","types.ListFilesResponse","converters.createFileParametersToMldev","converters.createFileResponseFromMldev","types.CreateFileResponse","converters.getFileParametersToMldev","converters.deleteFileParametersToMldev","converters.deleteFileResponseFromMldev","types.DeleteFileResponse","converters.internalRegisterFilesParametersToMldev","converters.registerFilesResponseFromMldev","types.RegisterFilesResponse","generationConfigToVertex","liveConnectConfigToMldev","t.tLiveSpeechConfig","sessionResumptionConfigToMldev","t.tBlobs","t.tAudioBlob","t.tImageBlob","t.tModelsUrl","t.tExtractModels","types.ResourceScope","types.HttpResponse","handleWebSocketMessage","types.LiveMusicServerMessage","mapToHeaders","headersToMap","converters.liveMusicSetWeightedPromptsParametersToMldev","converters.liveMusicSetConfigParametersToMldev","types.LiveMusicPlaybackControl","types.LiveServerMessage","converters.liveServerMessageFromVertex","types.Modality","converters.liveConnectParametersToVertex","converters.liveConnectParametersToMldev","converters.liveSendRealtimeInputParametersToVertex","converters.liveSendRealtimeInputParametersToMldev","afc.hasCallableTools","afc.shouldDisableAfc","afc.findAfcIncompatibleToolIndexes","afc.DEFAULT_MAX_REMOTE_CALLS","afc.isCallableTool","afc.shouldAppendAfcHistory","mcp.hasMcpToolUsage","mcp.setMcpUsageHeader","types.GenerateContentResponse","converters.generateContentParametersToVertex","converters.generateContentResponseFromVertex","converters.generateContentParametersToMldev","converters.generateContentResponseFromMldev","converters.embedContentParametersToVertex","converters.embedContentResponseFromVertex","types.EmbedContentResponse","converters.embedContentParametersToMldev","converters.embedContentResponseFromMldev","converters.generateImagesParametersToVertex","converters.generateImagesResponseFromVertex","types.GenerateImagesResponse","converters.generateImagesParametersToMldev","converters.generateImagesResponseFromMldev","converters.editImageParametersInternalToVertex","converters.editImageResponseFromVertex","types.EditImageResponse","converters.upscaleImageAPIParametersInternalToVertex","converters.upscaleImageResponseFromVertex","types.UpscaleImageResponse","converters.recontextImageParametersToVertex","converters.recontextImageResponseFromVertex","types.RecontextImageResponse","converters.segmentImageParametersToVertex","converters.segmentImageResponseFromVertex","types.SegmentImageResponse","converters.getModelParametersToVertex","converters.modelFromVertex","converters.getModelParametersToMldev","converters.modelFromMldev","converters.listModelsParametersToVertex","converters.listModelsResponseFromVertex","types.ListModelsResponse","converters.listModelsParametersToMldev","converters.listModelsResponseFromMldev","converters.updateModelParametersToVertex","converters.updateModelParametersToMldev","converters.deleteModelParametersToVertex","converters.deleteModelResponseFromVertex","types.DeleteModelResponse","converters.deleteModelParametersToMldev","converters.deleteModelResponseFromMldev","converters.countTokensParametersToVertex","converters.countTokensResponseFromVertex","types.CountTokensResponse","converters.countTokensParametersToMldev","converters.countTokensResponseFromMldev","converters.computeTokensParametersToVertex","converters.computeTokensResponseFromVertex","types.ComputeTokensResponse","converters.generateVideosParametersToVertex","converters.generateVideosOperationFromVertex","types.GenerateVideosOperation","converters.generateVideosParametersToMldev","converters.generateVideosOperationFromMldev","converters.getOperationParametersToVertex","converters.getOperationParametersToMldev","converters.fetchPredictOperationParametersToVertex","converters.createAuthTokenParametersToMldev","converters.getDocumentParametersToMldev","converters.deleteDocumentParametersToMldev","converters.listDocumentsParametersToMldev","converters.listDocumentsResponseFromMldev","types.ListDocumentsResponse","converters.createFileSearchStoreParametersToMldev","converters.getFileSearchStoreParametersToMldev","converters.deleteFileSearchStoreParametersToMldev","converters.listFileSearchStoresParametersToMldev","converters.listFileSearchStoresResponseFromMldev","types.ListFileSearchStoresResponse","converters.uploadToFileSearchStoreParametersToMldev","converters.uploadToFileSearchStoreResumableResponseFromMldev","types.UploadToFileSearchStoreResumableResponse","converters.importFileParametersToMldev","converters.importFileOperationFromMldev","types.ImportFileOperation","sleep","Errors.GeminiNextGenAPIClientError","Shims.getDefaultFetch","Opts.FallbackEncoder","Errors.APIError","Errors.APIUserAbortError","Errors.APIConnectionTimeoutError","Errors.APIConnectionError","Shims.CancelReadableStream","Shims.ReadableStreamFrom","API.Interactions","Errors.NotFoundError","Errors.ConflictError","Errors.RateLimitError","Errors.BadRequestError","Errors.AuthenticationError","Errors.InternalServerError","Errors.PermissionDeniedError","Errors.UnprocessableEntityError","Uploads.toFile","t.tTuningJobStatus","types.JobState","converters.getTuningJobParametersToVertex","converters.tuningJobFromVertex","converters.getTuningJobParametersToMldev","converters.tuningJobFromMldev","converters.listTuningJobsParametersToVertex","converters.listTuningJobsResponseFromVertex","types.ListTuningJobsResponse","converters.listTuningJobsParametersToMldev","converters.listTuningJobsResponseFromMldev","converters.cancelTuningJobParametersToVertex","converters.cancelTuningJobResponseFromVertex","types.CancelTuningJobResponse","converters.cancelTuningJobParametersToMldev","converters.cancelTuningJobResponseFromMldev","converters.createTuningJobParametersPrivateToVertex","converters.createTuningJobParametersPrivateToMldev","converters.tuningOperationFromMldev","_converters.uploadToFileSearchStoreOperationFromMldev","GeminiNextGenAPI"],"mappings":"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"} \ No newline at end of file diff --git a/server/node_modules/@google/genai/dist/web/web.d.ts b/server/node_modules/@google/genai/dist/web/web.d.ts new file mode 100644 index 0000000..8dfb78b --- /dev/null +++ b/server/node_modules/@google/genai/dist/web/web.d.ts @@ -0,0 +1,11249 @@ +/// <reference types="node" /> + +import type { Client } from '@modelcontextprotocol/sdk/client/index.js'; +import { GoogleAuthOptions } from 'google-auth-library'; +import { ReadableStream as ReadableStream_2 } from 'stream/web'; + +/** Marks the end of user activity. + + This can only be sent if automatic (i.e. server-side) activity detection is + disabled. */ +export declare interface ActivityEnd { +} + +/** The different ways of handling user activity. */ +export declare enum ActivityHandling { + /** + * If unspecified, the default behavior is `START_OF_ACTIVITY_INTERRUPTS`. + */ + ACTIVITY_HANDLING_UNSPECIFIED = "ACTIVITY_HANDLING_UNSPECIFIED", + /** + * If true, start of activity will interrupt the model's response (also called "barge in"). The model's current response will be cut-off in the moment of the interruption. This is the default behavior. + */ + START_OF_ACTIVITY_INTERRUPTS = "START_OF_ACTIVITY_INTERRUPTS", + /** + * The model's response will not be interrupted. + */ + NO_INTERRUPTION = "NO_INTERRUPTION" +} + +/** Marks the start of user activity. + + This can only be sent if automatic (i.e. server-side) activity detection is + disabled. */ +export declare interface ActivityStart { +} + +/** Adapter size for tuning. This enum is not supported in Gemini API. */ +export declare enum AdapterSize { + /** + * Adapter size is unspecified. + */ + ADAPTER_SIZE_UNSPECIFIED = "ADAPTER_SIZE_UNSPECIFIED", + /** + * Adapter size 1. + */ + ADAPTER_SIZE_ONE = "ADAPTER_SIZE_ONE", + /** + * Adapter size 2. + */ + ADAPTER_SIZE_TWO = "ADAPTER_SIZE_TWO", + /** + * Adapter size 4. + */ + ADAPTER_SIZE_FOUR = "ADAPTER_SIZE_FOUR", + /** + * Adapter size 8. + */ + ADAPTER_SIZE_EIGHT = "ADAPTER_SIZE_EIGHT", + /** + * Adapter size 16. + */ + ADAPTER_SIZE_SIXTEEN = "ADAPTER_SIZE_SIXTEEN", + /** + * Adapter size 32. + */ + ADAPTER_SIZE_THIRTY_TWO = "ADAPTER_SIZE_THIRTY_TWO" +} + +/** + * The configuration for allowed tools. + */ +declare interface AllowedTools { + /** + * The mode of the tool choice. + */ + mode?: ToolChoiceType; + /** + * The names of the allowed tools. + */ + tools?: Array<string>; +} + +/** + * Citation information for model-generated content. + */ +declare interface Annotation { + /** + * End of the attributed segment, exclusive. + */ + end_index?: number; + /** + * Source attributed for a portion of the text. Could be a URL, title, or + * other identifier. + */ + source?: string; + /** + * Start of segment of the response that is attributed to this source. + * + * Index indicates the start of the segment, measured in bytes. + */ + start_index?: number; +} + +/** The generic reusable api auth config. Deprecated. Please use AuthConfig (google/cloud/aiplatform/master/auth.proto) instead. This data type is not supported in Gemini API. */ +export declare interface ApiAuth { + /** The API secret. */ + apiKeyConfig?: ApiAuthApiKeyConfig; +} + +/** The API secret. This data type is not supported in Gemini API. */ +export declare interface ApiAuthApiKeyConfig { + /** Required. The SecretManager secret version resource name storing API key. e.g. projects/{project}/secrets/{secret}/versions/{version} */ + apiKeySecretVersion?: string; + /** The API key string. Either this or `api_key_secret_version` must be set. */ + apiKeyString?: string; +} + +/** + * The ApiClient class is used to send requests to the Gemini API or Vertex AI + * endpoints. + */ +declare class ApiClient implements GeminiNextGenAPIClientAdapter { + readonly clientOptions: ApiClientInitOptions; + private readonly customBaseUrl?; + constructor(opts: ApiClientInitOptions); + isVertexAI(): boolean; + getProject(): string | undefined; + getLocation(): string | undefined; + getCustomBaseUrl(): string | undefined; + getAuthHeaders(): Promise<Headers>; + getApiVersion(): string; + getBaseUrl(): string; + getRequestUrl(): string; + getHeaders(): Record<string, string>; + private getRequestUrlInternal; + getBaseResourcePath(): string; + getApiKey(): string | undefined; + getWebsocketBaseUrl(): string; + setBaseUrl(url: string): void; + private constructUrl; + private shouldPrependVertexProjectPath; + request(request: HttpRequest): Promise<types.HttpResponse>; + private patchHttpOptions; + requestStream(request: HttpRequest): Promise<AsyncGenerator<types.HttpResponse>>; + private includeExtraHttpOptionsToRequestInit; + private unaryApiCall; + private streamApiCall; + processStreamResponse(response: Response): AsyncGenerator<types.HttpResponse>; + private apiCall; + getDefaultHeaders(): Record<string, string>; + private getHeadersInternal; + private getFileName; + /** + * Uploads a file asynchronously using Gemini API only, this is not supported + * in Vertex AI. + * + * @param file The string path to the file to be uploaded or a Blob object. + * @param config Optional parameters specified in the `UploadFileConfig` + * interface. @see {@link types.UploadFileConfig} + * @return A promise that resolves to a `File` object. + * @throws An error if called on a Vertex AI client. + * @throws An error if the `mimeType` is not provided and can not be inferred, + */ + uploadFile(file: string | Blob, config?: types.UploadFileConfig): Promise<types.File>; + /** + * Uploads a file to a given file search store asynchronously using Gemini API only, this is not supported + * in Vertex AI. + * + * @param fileSearchStoreName The name of the file search store to upload the file to. + * @param file The string path to the file to be uploaded or a Blob object. + * @param config Optional parameters specified in the `UploadFileConfig` + * interface. @see {@link UploadFileConfig} + * @return A promise that resolves to a `File` object. + * @throws An error if called on a Vertex AI client. + * @throws An error if the `mimeType` is not provided and can not be inferred, + */ + uploadFileToFileSearchStore(fileSearchStoreName: string, file: string | Blob, config?: types.UploadToFileSearchStoreConfig): Promise<types.UploadToFileSearchStoreOperation>; + /** + * Downloads a file asynchronously to the specified path. + * + * @params params - The parameters for the download request, see {@link + * types.DownloadFileParameters} + */ + downloadFile(params: types.DownloadFileParameters): Promise<void>; + private fetchUploadUrl; +} + +/** + * Options for initializing the ApiClient. The ApiClient uses the parameters + * for authentication purposes as well as to infer if SDK should send the + * request to Vertex AI or Gemini API. + */ +declare interface ApiClientInitOptions { + /** + * The object used for adding authentication headers to API requests. + */ + auth: Auth; + /** + * The uploader to use for uploading files. This field is required for + * creating a client, will be set through the Node_client or Web_client. + */ + uploader: Uploader; + /** + * Optional. The downloader to use for downloading files. This field is + * required for creating a client, will be set through the Node_client or + * Web_client. + */ + downloader: Downloader; + /** + * Optional. The Google Cloud project ID for Vertex AI users. + * It is not the numeric project name. + * If not provided, SDK will try to resolve it from runtime environment. + */ + project?: string; + /** + * Optional. The Google Cloud project location for Vertex AI users. + * If not provided, SDK will try to resolve it from runtime environment. + */ + location?: string; + /** + * The API Key. This is required for Gemini API users. + */ + apiKey?: string; + /** + * Optional. Set to true if you intend to call Vertex AI endpoints. + * If unset, default SDK behavior is to call Gemini API. + */ + vertexai?: boolean; + /** + * Optional. The API version for the endpoint. + * If unset, SDK will choose a default api version. + */ + apiVersion?: string; + /** + * Optional. A set of customizable configuration for HTTP requests. + */ + httpOptions?: types.HttpOptions; + /** + * Optional. An extra string to append at the end of the User-Agent header. + * + * This can be used to e.g specify the runtime and its version. + */ + userAgentExtra?: string; +} + +declare class APIConnectionError extends APIError<undefined, undefined, undefined> { + constructor({ message, cause }: { + message?: string | undefined; + cause?: Error | undefined; + }); +} + +declare class APIConnectionTimeoutError extends APIConnectionError { + constructor({ message }?: { + message?: string; + }); +} + +declare class APIError<TStatus extends number | undefined = number | undefined, THeaders extends Headers | undefined = Headers | undefined, TError extends Object | undefined = Object | undefined> extends GeminiNextGenAPIClientError { + /** HTTP status for the response that caused the error */ + readonly status: TStatus; + /** HTTP headers for the response that caused the error */ + readonly headers: THeaders; + /** JSON body of the response that caused the error */ + readonly error: TError; + constructor(status: TStatus, error: TError, message: string | undefined, headers: THeaders); + private static makeMessage; + static generate(status: number | undefined, errorResponse: Object | undefined, message: string | undefined, headers: Headers | undefined): APIError; +} + +/** + * API errors raised by the GenAI API. + */ +export declare class ApiError extends Error { + /** HTTP status code */ + status: number; + constructor(options: ApiErrorInfo); +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * Details for errors from calling the API. + */ +export declare interface ApiErrorInfo { + /** The error message. */ + message: string; + /** The HTTP status code. */ + status: number; +} + +/** Config for authentication with API key. This data type is not supported in Gemini API. */ +export declare interface ApiKeyConfig { + /** Optional. The name of the SecretManager secret version resource storing the API key. Format: `projects/{project}/secrets/{secrete}/versions/{version}` - If both `api_key_secret` and `api_key_string` are specified, this field takes precedence over `api_key_string`. - If specified, the `secretmanager.versions.access` permission should be granted to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents) on the specified resource. */ + apiKeySecret?: string; + /** Optional. The API key to be used in the request directly. */ + apiKeyString?: string; + /** Optional. The location of the API key. */ + httpElementLocation?: HttpElementLocation; + /** Optional. The parameter name of the API key. E.g. If the API request is "https://example.com/act?api_key=", "api_key" would be the parameter name. */ + name?: string; +} + +/** + * A subclass of `Promise` providing additional helper methods + * for interacting with the SDK. + */ +declare class APIPromise<T> extends Promise<T> { + private responsePromise; + private parseResponse; + private parsedPromise; + private client; + constructor(client: BaseGeminiNextGenAPIClient, responsePromise: Promise<APIResponseProps>, parseResponse?: (client: BaseGeminiNextGenAPIClient, props: APIResponseProps) => PromiseOrValue<T>); + _thenUnwrap<U>(transform: (data: T, props: APIResponseProps) => U): APIPromise<U>; + /** + * Gets the raw `Response` instance instead of parsing the response + * data. + * + * If you want to parse the response body but still get the `Response` + * instance, you can use {@link withResponse()}. + * + * 👋 Getting the wrong TypeScript type for `Response`? + * Try setting `"moduleResolution": "NodeNext"` or add `"lib": ["DOM"]` + * to your `tsconfig.json`. + */ + asResponse(): Promise<Response>; + /** + * Gets the parsed response data and the raw `Response` instance. + * + * If you just want to get the raw `Response` instance without parsing it, + * you can use {@link asResponse()}. + * + * 👋 Getting the wrong TypeScript type for `Response`? + * Try setting `"moduleResolution": "NodeNext"` or add `"lib": ["DOM"]` + * to your `tsconfig.json`. + */ + withResponse(): Promise<{ + data: T; + response: Response; + }>; + private parse; + then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>; + catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): Promise<T | TResult>; + finally(onfinally?: (() => void) | undefined | null): Promise<T>; +} + +declare abstract class APIResource { + /** + * The key path from the client. For example, a resource accessible as `client.resource.subresource` would + * have a property `static override readonly _key = Object.freeze(['resource', 'subresource'] as const);`. + */ + static readonly _key: readonly string[]; + protected _client: BaseGeminiNextGenAPIClient; + constructor(client: BaseGeminiNextGenAPIClient); +} + +declare type APIResponseProps = { + response: Response; + options: FinalRequestOptions; + controller: AbortController; + requestLogID: string; + retryOfRequestLogID: string | undefined; + startTime: number; +}; + +/** The API spec that the external API implements. This enum is not supported in Gemini API. */ +export declare enum ApiSpec { + /** + * Unspecified API spec. This value should not be used. + */ + API_SPEC_UNSPECIFIED = "API_SPEC_UNSPECIFIED", + /** + * Simple search API spec. + */ + SIMPLE_SEARCH = "SIMPLE_SEARCH", + /** + * Elastic search API spec. + */ + ELASTIC_SEARCH = "ELASTIC_SEARCH" +} + +declare class APIUserAbortError extends APIError<undefined, undefined, undefined> { + constructor({ message }?: { + message?: string; + }); +} + +/** Representation of an audio chunk. */ +export declare interface AudioChunk { + /** Raw bytes of audio data. + * @remarks Encoded as base64 string. */ + data?: string; + /** MIME type of the audio chunk. */ + mimeType?: string; + /** Prompts and config used for generating this audio chunk. */ + sourceMetadata?: LiveMusicSourceMetadata; +} + +/** + * An audio content block. + */ +declare interface AudioContent { + type: 'audio'; + /** + * The audio content. + */ + data?: string; + /** + * The mime type of the audio. + */ + mime_type?: AudioMimeType; + /** + * The URI of the audio. + */ + uri?: string; +} + +/** + * The mime type of the audio. + */ +declare type AudioMimeType = 'audio/wav' | 'audio/mp3' | 'audio/aiff' | 'audio/aac' | 'audio/ogg' | 'audio/flac' | (string & {}); + +/** The audio transcription configuration in Setup. */ +export declare interface AudioTranscriptionConfig { +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * The Auth interface is used to authenticate with the API service. + */ +declare interface Auth { + /** + * Sets the headers needed to authenticate with the API service. + * + * @param headers - The Headers object that will be updated with the authentication headers. + * @param url - The URL of the request. + */ + addAuthHeaders(headers: Headers, url?: string): Promise<void>; +} + +/** Auth configuration to run the extension. This data type is not supported in Gemini API. */ +export declare interface AuthConfig { + /** Config for API key auth. */ + apiKeyConfig?: ApiKeyConfig; + /** Type of auth scheme. */ + authType?: AuthType; + /** Config for Google Service Account auth. */ + googleServiceAccountConfig?: AuthConfigGoogleServiceAccountConfig; + /** Config for HTTP Basic auth. */ + httpBasicAuthConfig?: AuthConfigHttpBasicAuthConfig; + /** Config for user oauth. */ + oauthConfig?: AuthConfigOauthConfig; + /** Config for user OIDC auth. */ + oidcConfig?: AuthConfigOidcConfig; +} + +/** Config for Google Service Account Authentication. This data type is not supported in Gemini API. */ +export declare interface AuthConfigGoogleServiceAccountConfig { + /** Optional. The service account that the extension execution service runs as. - If the service account is specified, the `iam.serviceAccounts.getAccessToken` permission should be granted to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents) on the specified service account. - If not specified, the Vertex AI Extension Service Agent will be used to execute the Extension. */ + serviceAccount?: string; +} + +/** Config for HTTP Basic Authentication. This data type is not supported in Gemini API. */ +export declare interface AuthConfigHttpBasicAuthConfig { + /** Required. The name of the SecretManager secret version resource storing the base64 encoded credentials. Format: `projects/{project}/secrets/{secrete}/versions/{version}` - If specified, the `secretmanager.versions.access` permission should be granted to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents) on the specified resource. */ + credentialSecret?: string; +} + +/** Config for user oauth. This data type is not supported in Gemini API. */ +export declare interface AuthConfigOauthConfig { + /** Access token for extension endpoint. Only used to propagate token from [[ExecuteExtensionRequest.runtime_auth_config]] at request time. */ + accessToken?: string; + /** The service account used to generate access tokens for executing the Extension. - If the service account is specified, the `iam.serviceAccounts.getAccessToken` permission should be granted to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents) on the provided service account. */ + serviceAccount?: string; +} + +/** Config for user OIDC auth. This data type is not supported in Gemini API. */ +export declare interface AuthConfigOidcConfig { + /** OpenID Connect formatted ID token for extension endpoint. Only used to propagate token from [[ExecuteExtensionRequest.runtime_auth_config]] at request time. */ + idToken?: string; + /** The service account used to generate an OpenID Connect (OIDC)-compatible JWT token signed by the Google OIDC Provider (accounts.google.com) for extension endpoint (https://cloud.google.com/iam/docs/create-short-lived-credentials-direct#sa-credentials-oidc). - The audience for the token will be set to the URL in the server url defined in the OpenApi spec. - If the service account is provided, the service account should grant `iam.serviceAccounts.getOpenIdToken` permission to Vertex AI Extension Service Agent (https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents). */ + serviceAccount?: string; +} + +declare class AuthenticationError extends APIError<401, Headers> { +} + +/** Config for auth_tokens.create parameters. */ +export declare interface AuthToken { + /** The name of the auth token. */ + name?: string; +} + +/** Type of auth scheme. This enum is not supported in Gemini API. */ +export declare enum AuthType { + AUTH_TYPE_UNSPECIFIED = "AUTH_TYPE_UNSPECIFIED", + /** + * No Auth. + */ + NO_AUTH = "NO_AUTH", + /** + * API Key Auth. + */ + API_KEY_AUTH = "API_KEY_AUTH", + /** + * HTTP Basic Auth. + */ + HTTP_BASIC_AUTH = "HTTP_BASIC_AUTH", + /** + * Google Service Account Auth. + */ + GOOGLE_SERVICE_ACCOUNT_AUTH = "GOOGLE_SERVICE_ACCOUNT_AUTH", + /** + * OAuth auth. + */ + OAUTH = "OAUTH", + /** + * OpenID Connect (OIDC) Auth. + */ + OIDC_AUTH = "OIDC_AUTH" +} + +/** Configures automatic detection of activity. */ +export declare interface AutomaticActivityDetection { + /** If enabled, detected voice and text input count as activity. If disabled, the client must send activity signals. */ + disabled?: boolean; + /** Determines how likely speech is to be detected. */ + startOfSpeechSensitivity?: StartSensitivity; + /** Determines how likely detected speech is ended. */ + endOfSpeechSensitivity?: EndSensitivity; + /** The required duration of detected speech before start-of-speech is committed. The lower this value the more sensitive the start-of-speech detection is and the shorter speech can be recognized. However, this also increases the probability of false positives. */ + prefixPaddingMs?: number; + /** The required duration of detected non-speech (e.g. silence) before end-of-speech is committed. The larger this value, the longer speech gaps can be without interrupting the user's activity but this will increase the model's latency. */ + silenceDurationMs?: number; +} + +/** The configuration for automatic function calling. */ +export declare interface AutomaticFunctionCallingConfig { + /** Whether to disable automatic function calling. + If not set or set to False, will enable automatic function calling. + If set to True, will disable automatic function calling. + */ + disable?: boolean; + /** If automatic function calling is enabled, + maximum number of remote calls for automatic function calling. + This number should be a positive integer. + If not set, SDK will set maximum number of remote calls to 10. + */ + maximumRemoteCalls?: number; + /** If automatic function calling is enabled, + whether to ignore call history to the response. + If not set, SDK will set ignore_call_history to false, + and will append the call history to + GenerateContentResponse.automatic_function_calling_history. + */ + ignoreCallHistory?: boolean; +} + +declare class BadRequestError extends APIError<400, Headers> { +} + +declare interface BaseCreateAgentInteractionParams { + /** + * Path param: Which version of the API to use. + */ + api_version?: string; + /** + * Body param: The name of the `Agent` used for generating the interaction. + */ + agent: (string & {}) | 'deep-research-pro-preview-12-2025'; + /** + * Body param: The inputs for the interaction. + */ + input: string | Array<Content_2> | Array<Turn> | TextContent | ImageContent | AudioContent | DocumentContent | VideoContent | ThoughtContent | FunctionCallContent | FunctionResultContent | CodeExecutionCallContent | CodeExecutionResultContent | URLContextCallContent | URLContextResultContent | GoogleSearchCallContent | GoogleSearchResultContent | MCPServerToolCallContent | MCPServerToolResultContent | FileSearchCallContent | FileSearchResultContent; + /** + * Body param: Configuration for the agent. + */ + agent_config?: DynamicAgentConfig | DeepResearchAgentConfig; + /** + * Body param: Input only. Whether to run the model interaction in the background. + */ + background?: boolean; + /** + * Body param: The ID of the previous interaction, if any. + */ + previous_interaction_id?: string; + /** + * Body param: Enforces that the generated response is a JSON object that complies with + * the JSON schema specified in this field. + */ + response_format?: unknown; + /** + * Body param: The mime type of the response. This is required if response_format is set. + */ + response_mime_type?: string; + /** + * Body param: The requested modalities of the response (TEXT, IMAGE, AUDIO). + */ + response_modalities?: Array<'text' | 'image' | 'audio'>; + /** + * Body param: Input only. Whether to store the response and request for later retrieval. + */ + store?: boolean; + /** + * Body param: Input only. Whether the interaction will be streamed. + */ + stream?: boolean; + /** + * Body param: System instruction for the interaction. + */ + system_instruction?: string; + /** + * Body param: A list of tool declarations the model may call during interaction. + */ + tools?: Array<Tool_2>; +} + +declare interface BaseCreateModelInteractionParams { + /** + * Path param: Which version of the API to use. + */ + api_version?: string; + /** + * Body param: The inputs for the interaction. + */ + input: string | Array<Content_2> | Array<Turn> | TextContent | ImageContent | AudioContent | DocumentContent | VideoContent | ThoughtContent | FunctionCallContent | FunctionResultContent | CodeExecutionCallContent | CodeExecutionResultContent | URLContextCallContent | URLContextResultContent | GoogleSearchCallContent | GoogleSearchResultContent | MCPServerToolCallContent | MCPServerToolResultContent | FileSearchCallContent | FileSearchResultContent; + /** + * Body param: The name of the `Model` used for generating the interaction. + */ + model: Model_2; + /** + * Body param: Input only. Whether to run the model interaction in the background. + */ + background?: boolean; + /** + * Body param: Input only. Configuration parameters for the model interaction. + */ + generation_config?: GenerationConfig_2; + /** + * Body param: The ID of the previous interaction, if any. + */ + previous_interaction_id?: string; + /** + * Body param: Enforces that the generated response is a JSON object that complies with + * the JSON schema specified in this field. + */ + response_format?: unknown; + /** + * Body param: The mime type of the response. This is required if response_format is set. + */ + response_mime_type?: string; + /** + * Body param: The requested modalities of the response (TEXT, IMAGE, AUDIO). + */ + response_modalities?: Array<'text' | 'image' | 'audio'>; + /** + * Body param: Input only. Whether to store the response and request for later retrieval. + */ + store?: boolean; + /** + * Body param: Input only. Whether the interaction will be streamed. + */ + stream?: boolean; + /** + * Body param: System instruction for the interaction. + */ + system_instruction?: string; + /** + * Body param: A list of tool declarations the model may call during interaction. + */ + tools?: Array<Tool_2>; +} + +/** + * Base class for Gemini Next Gen API API clients. + */ +declare class BaseGeminiNextGenAPIClient { + apiKey: string | null; + apiVersion: string; + baseURL: string; + maxRetries: number; + timeout: number; + logger: Logger; + logLevel: LogLevel | undefined; + fetchOptions: MergedRequestInit | undefined; + private fetch; + private encoder; + protected idempotencyHeader?: string; + private _options; + private clientAdapter; + /** + * API Client for interfacing with the Gemini Next Gen API API. + * + * @param {string | null | undefined} [opts.apiKey=process.env['GEMINI_API_KEY'] ?? null] + * @param {string | undefined} [opts.apiVersion=v1beta] + * @param {string} [opts.baseURL=process.env['GEMINI_NEXT_GEN_API_BASE_URL'] ?? https://generativelanguage.googleapis.com] - Override the default base URL for the API. + * @param {number} [opts.timeout=1 minute] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out. + * @param {MergedRequestInit} [opts.fetchOptions] - Additional `RequestInit` options to be passed to `fetch` calls. + * @param {Fetch} [opts.fetch] - Specify a custom `fetch` function implementation. + * @param {number} [opts.maxRetries=2] - The maximum number of times the client will retry a request. + * @param {HeadersLike} opts.defaultHeaders - Default headers to include with every request to the API. + * @param {Record<string, string | undefined>} opts.defaultQuery - Default query parameters to include with every request to the API. + */ + constructor({ baseURL, apiKey, apiVersion, ...opts }: ClientOptions); + /** + * Create a new client instance re-using the same options given to the current client with optional overriding. + */ + withOptions(options: Partial<ClientOptions>): this; + /** + * Check whether the base URL is set to its default. + */ + private baseURLOverridden; + protected defaultQuery(): Record<string, string | undefined> | undefined; + protected validateHeaders({ values, nulls }: NullableHeaders): void; + protected authHeaders(opts: FinalRequestOptions): Promise<NullableHeaders | undefined>; + /** + * Basic re-implementation of `qs.stringify` for primitive types. + */ + protected stringifyQuery(query: Record<string, unknown>): string; + private getUserAgent; + protected defaultIdempotencyKey(): string; + protected makeStatusError(status: number, error: Object, message: string | undefined, headers: Headers): Errors.APIError; + buildURL(path: string, query: Record<string, unknown> | null | undefined, defaultBaseURL?: string | undefined): string; + /** + * Used as a callback for mutating the given `FinalRequestOptions` object. + + */ + protected prepareOptions(options: FinalRequestOptions): Promise<void>; + /** + * Used as a callback for mutating the given `RequestInit` object. + * + * This is useful for cases where you want to add certain headers based off of + * the request properties, e.g. `method` or `url`. + */ + protected prepareRequest(request: _RequestInit, { url, options }: { + url: string; + options: FinalRequestOptions; + }): Promise<void>; + get<Rsp>(path: string, opts?: PromiseOrValue<RequestOptions>): APIPromise<Rsp>; + post<Rsp>(path: string, opts?: PromiseOrValue<RequestOptions>): APIPromise<Rsp>; + patch<Rsp>(path: string, opts?: PromiseOrValue<RequestOptions>): APIPromise<Rsp>; + put<Rsp>(path: string, opts?: PromiseOrValue<RequestOptions>): APIPromise<Rsp>; + delete<Rsp>(path: string, opts?: PromiseOrValue<RequestOptions>): APIPromise<Rsp>; + private methodRequest; + request<Rsp>(options: PromiseOrValue<FinalRequestOptions>, remainingRetries?: number | null): APIPromise<Rsp>; + private makeRequest; + fetchWithTimeout(url: _RequestInfo, init: _RequestInit | undefined, ms: number, controller: AbortController): Promise<Response>; + private shouldRetry; + private retryRequest; + private calculateDefaultRetryTimeoutMillis; + buildRequest(inputOptions: FinalRequestOptions, { retryCount }?: { + retryCount?: number; + }): Promise<{ + req: FinalizedRequestInit; + url: string; + timeout: number; + }>; + private buildHeaders; + private _makeAbort; + private buildBody; + static DEFAULT_TIMEOUT: number; +} + +declare class BaseInteractions extends APIResource { + static readonly _key: readonly ['interactions']; + /** + * Creates a new interaction. + * + * @example + * ```ts + * const interaction = await client.interactions.create({ + * api_version: 'api_version', + * input: 'string', + * model: 'gemini-2.5-flash', + * }); + * ``` + */ + create(params: CreateModelInteractionParamsNonStreaming, options?: RequestOptions): APIPromise<Interaction>; + create(params: CreateModelInteractionParamsStreaming, options?: RequestOptions): APIPromise<Stream<InteractionSSEEvent>>; + create(params: CreateAgentInteractionParamsNonStreaming, options?: RequestOptions): APIPromise<Interaction>; + create(params: CreateAgentInteractionParamsStreaming, options?: RequestOptions): APIPromise<Stream<InteractionSSEEvent>>; + create(params: BaseCreateModelInteractionParams | BaseCreateAgentInteractionParams, options?: RequestOptions): APIPromise<Stream<InteractionSSEEvent> | Interaction>; + /** + * Deletes the interaction by id. + * + * @example + * ```ts + * const interaction = await client.interactions.delete('id', { + * api_version: 'api_version', + * }); + * ``` + */ + delete(id: string, params?: InteractionDeleteParams | null | undefined, options?: RequestOptions): APIPromise<unknown>; + /** + * Cancels an interaction by id. This only applies to background interactions that are still running. + * + * @example + * ```ts + * const interaction = await client.interactions.cancel('id', { + * api_version: 'api_version', + * }); + * ``` + */ + cancel(id: string, params?: InteractionCancelParams | null | undefined, options?: RequestOptions): APIPromise<Interaction>; + /** + * Retrieves the full details of a single interaction based on its `Interaction.id`. + * + * @example + * ```ts + * const interaction = await client.interactions.get('id', { + * api_version: 'api_version', + * }); + * ``` + */ + get(id: string, params?: InteractionGetParamsNonStreaming, options?: RequestOptions): APIPromise<Interaction>; + get(id: string, params: InteractionGetParamsStreaming, options?: RequestOptions): APIPromise<Stream<InteractionSSEEvent>>; + get(id: string, params?: InteractionGetParamsBase | undefined, options?: RequestOptions): APIPromise<Stream<InteractionSSEEvent> | Interaction>; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +declare class BaseModule { +} + +/** + * Parameters for setting the base URLs for the Gemini API and Vertex AI API. + */ +export declare interface BaseUrlParameters { + geminiUrl?: string; + vertexUrl?: string; +} + +export declare class Batches extends BaseModule { + private readonly apiClient; + constructor(apiClient: ApiClient); + /** + * Lists batch jobs. + * + * @param params - The parameters for the list request. + * @return - A pager of batch jobs. + * + * @example + * ```ts + * const batchJobs = await ai.batches.list({config: {'pageSize': 2}}); + * for await (const batchJob of batchJobs) { + * console.log(batchJob); + * } + * ``` + */ + list: (params?: types.ListBatchJobsParameters) => Promise<Pager<types.BatchJob>>; + /** + * Create batch job. + * + * @param params - The parameters for create batch job request. + * @return The created batch job. + * + * @example + * ```ts + * const response = await ai.batches.create({ + * model: 'gemini-2.0-flash', + * src: {gcsUri: 'gs://bucket/path/to/file.jsonl', format: 'jsonl'}, + * config: { + * dest: {gcsUri: 'gs://bucket/path/output/directory', format: 'jsonl'}, + * } + * }); + * console.log(response); + * ``` + */ + create: (params: types.CreateBatchJobParameters) => Promise<types.BatchJob>; + /** + * **Experimental** Creates an embedding batch job. + * + * @param params - The parameters for create embedding batch job request. + * @return The created batch job. + * + * @example + * ```ts + * const response = await ai.batches.createEmbeddings({ + * model: 'text-embedding-004', + * src: {fileName: 'files/my_embedding_input'}, + * }); + * console.log(response); + * ``` + */ + createEmbeddings: (params: types.CreateEmbeddingsBatchJobParameters) => Promise<types.BatchJob>; + private createInlinedGenerateContentRequest; + private getGcsUri; + private getBigqueryUri; + private formatDestination; + /** + * Internal method to create batch job. + * + * @param params - The parameters for create batch job request. + * @return The created batch job. + * + */ + private createInternal; + /** + * Internal method to create batch job. + * + * @param params - The parameters for create batch job request. + * @return The created batch job. + * + */ + private createEmbeddingsInternal; + /** + * Gets batch job configurations. + * + * @param params - The parameters for the get request. + * @return The batch job. + * + * @example + * ```ts + * await ai.batches.get({name: '...'}); // The server-generated resource name. + * ``` + */ + get(params: types.GetBatchJobParameters): Promise<types.BatchJob>; + /** + * Cancels a batch job. + * + * @param params - The parameters for the cancel request. + * @return The empty response returned by the API. + * + * @example + * ```ts + * await ai.batches.cancel({name: '...'}); // The server-generated resource name. + * ``` + */ + cancel(params: types.CancelBatchJobParameters): Promise<void>; + private listInternal; + /** + * Deletes a batch job. + * + * @param params - The parameters for the delete request. + * @return The empty response returned by the API. + * + * @example + * ```ts + * await ai.batches.delete({name: '...'}); // The server-generated resource name. + * ``` + */ + delete(params: types.DeleteBatchJobParameters): Promise<types.DeleteResourceJob>; +} + +/** Config for batches.create return value. */ +export declare interface BatchJob { + /** The resource name of the BatchJob. Output only.". + */ + name?: string; + /** The display name of the BatchJob. + */ + displayName?: string; + /** The state of the BatchJob. + */ + state?: JobState; + /** Output only. Only populated when the job's state is JOB_STATE_FAILED or JOB_STATE_CANCELLED. */ + error?: JobError; + /** The time when the BatchJob was created. + */ + createTime?: string; + /** Output only. Time when the Job for the first time entered the `JOB_STATE_RUNNING` state. */ + startTime?: string; + /** The time when the BatchJob was completed. This field is for Vertex AI only. + */ + endTime?: string; + /** The time when the BatchJob was last updated. + */ + updateTime?: string; + /** The name of the model that produces the predictions via the BatchJob. + */ + model?: string; + /** Configuration for the input data. This field is for Vertex AI only. + */ + src?: BatchJobSource; + /** Configuration for the output data. + */ + dest?: BatchJobDestination; + /** Statistics on completed and failed prediction instances. This field is for Vertex AI only. + */ + completionStats?: CompletionStats; +} + +/** Config for `des` parameter. */ +export declare interface BatchJobDestination { + /** Storage format of the output files. Must be one of: + 'jsonl', 'bigquery'. + */ + format?: string; + /** The Google Cloud Storage URI to the output file. + */ + gcsUri?: string; + /** The BigQuery URI to the output table. + */ + bigqueryUri?: string; + /** The Gemini Developer API's file resource name of the output data + (e.g. "files/12345"). The file will be a JSONL file with a single response + per line. The responses will be GenerateContentResponse messages formatted + as JSON. The responses will be written in the same order as the input + requests. + */ + fileName?: string; + /** The responses to the requests in the batch. Returned when the batch was + built using inlined requests. The responses will be in the same order as + the input requests. + */ + inlinedResponses?: InlinedResponse[]; + /** The responses to the requests in the batch. Returned when the batch was + built using inlined requests. The responses will be in the same order as + the input requests. + */ + inlinedEmbedContentResponses?: InlinedEmbedContentResponse[]; +} + +export declare type BatchJobDestinationUnion = BatchJobDestination | string; + +/** Config for `src` parameter. */ +export declare interface BatchJobSource { + /** Storage format of the input files. Must be one of: + 'jsonl', 'bigquery'. + */ + format?: string; + /** The Google Cloud Storage URIs to input files. + */ + gcsUri?: string[]; + /** The BigQuery URI to input table. + */ + bigqueryUri?: string; + /** The Gemini Developer API's file resource name of the input data + (e.g. "files/12345"). + */ + fileName?: string; + /** The Gemini Developer API's inlined input data to run batch job. + */ + inlinedRequests?: InlinedRequest[]; +} + +export declare type BatchJobSourceUnion = BatchJobSource | InlinedRequest[] | string; + +/** Specifies the function Behavior. Currently only supported by the BidiGenerateContent method. This enum is not supported in Vertex AI. */ +export declare enum Behavior { + /** + * This value is unused. + */ + UNSPECIFIED = "UNSPECIFIED", + /** + * If set, the system will wait to receive the function response before continuing the conversation. + */ + BLOCKING = "BLOCKING", + /** + * If set, the system will not wait to receive the function response. Instead, it will attempt to handle function responses as they become available while maintaining the conversation between the user and the model. + */ + NON_BLOCKING = "NON_BLOCKING" +} + +/** Content blob. */ +declare interface Blob_2 { + /** Required. Raw bytes. + * @remarks Encoded as base64 string. */ + data?: string; + /** Optional. Display name of the blob. Used to provide a label or filename to distinguish blobs. This field is only returned in PromptMessage for prompt management. It is currently used in the Gemini GenerateContent calls only when server side tools (code_execution, google_search, and url_context) are enabled. This field is not supported in Gemini API. */ + displayName?: string; + /** Required. The IANA standard MIME type of the source data. */ + mimeType?: string; +} +export { Blob_2 as Blob } + +export declare type BlobImageUnion = Blob_2; + +/** Output only. The reason why the prompt was blocked. */ +export declare enum BlockedReason { + /** + * The blocked reason is unspecified. + */ + BLOCKED_REASON_UNSPECIFIED = "BLOCKED_REASON_UNSPECIFIED", + /** + * The prompt was blocked for safety reasons. + */ + SAFETY = "SAFETY", + /** + * The prompt was blocked for other reasons. For example, it may be due to the prompt's language, or because it contains other harmful content. + */ + OTHER = "OTHER", + /** + * The prompt was blocked because it contains a term from the terminology blocklist. + */ + BLOCKLIST = "BLOCKLIST", + /** + * The prompt was blocked because it contains prohibited content. + */ + PROHIBITED_CONTENT = "PROHIBITED_CONTENT", + /** + * The prompt was blocked because it contains content that is unsafe for image generation. + */ + IMAGE_SAFETY = "IMAGE_SAFETY", + /** + * The prompt was blocked by Model Armor. This enum value is not supported in Gemini API. + */ + MODEL_ARMOR = "MODEL_ARMOR", + /** + * The prompt was blocked as a jailbreak attempt. This enum value is not supported in Gemini API. + */ + JAILBREAK = "JAILBREAK" +} + +declare const brand_privateNullableHeaders: unique symbol; + +/** @ts-ignore For users with \@types/bun */ +declare type BunRequestInit = globalThis.FetchRequestInit; + +/** A resource used in LLM queries for users to explicitly specify what to cache. */ +export declare interface CachedContent { + /** The server-generated resource name of the cached content. */ + name?: string; + /** The user-generated meaningful display name of the cached content. */ + displayName?: string; + /** The name of the publisher model to use for cached content. */ + model?: string; + /** Creation time of the cache entry. */ + createTime?: string; + /** When the cache entry was last updated in UTC time. */ + updateTime?: string; + /** Expiration time of the cached content. */ + expireTime?: string; + /** Metadata on the usage of the cached content. */ + usageMetadata?: CachedContentUsageMetadata; +} + +/** Metadata on the usage of the cached content. */ +export declare interface CachedContentUsageMetadata { + /** Duration of audio in seconds. This field is not supported in Gemini API. */ + audioDurationSeconds?: number; + /** Number of images. This field is not supported in Gemini API. */ + imageCount?: number; + /** Number of text characters. This field is not supported in Gemini API. */ + textCount?: number; + /** Total number of tokens that the cached content consumes. */ + totalTokenCount?: number; + /** Duration of video in seconds. This field is not supported in Gemini API. */ + videoDurationSeconds?: number; +} + +export declare class Caches extends BaseModule { + private readonly apiClient; + constructor(apiClient: ApiClient); + /** + * Lists cached contents. + * + * @param params - The parameters for the list request. + * @return - A pager of cached contents. + * + * @example + * ```ts + * const cachedContents = await ai.caches.list({config: {'pageSize': 2}}); + * for await (const cachedContent of cachedContents) { + * console.log(cachedContent); + * } + * ``` + */ + list: (params?: types.ListCachedContentsParameters) => Promise<Pager<types.CachedContent>>; + /** + * Creates a cached contents resource. + * + * @remarks + * Context caching is only supported for specific models. See [Gemini + * Developer API reference](https://ai.google.dev/gemini-api/docs/caching?lang=node/context-cac) + * and [Vertex AI reference](https://cloud.google.com/vertex-ai/generative-ai/docs/context-cache/context-cache-overview#supported_models) + * for more information. + * + * @param params - The parameters for the create request. + * @return The created cached content. + * + * @example + * ```ts + * const contents = ...; // Initialize the content to cache. + * const response = await ai.caches.create({ + * model: 'gemini-2.0-flash-001', + * config: { + * 'contents': contents, + * 'displayName': 'test cache', + * 'systemInstruction': 'What is the sum of the two pdfs?', + * 'ttl': '86400s', + * } + * }); + * ``` + */ + create(params: types.CreateCachedContentParameters): Promise<types.CachedContent>; + /** + * Gets cached content configurations. + * + * @param params - The parameters for the get request. + * @return The cached content. + * + * @example + * ```ts + * await ai.caches.get({name: '...'}); // The server-generated resource name. + * ``` + */ + get(params: types.GetCachedContentParameters): Promise<types.CachedContent>; + /** + * Deletes cached content. + * + * @param params - The parameters for the delete request. + * @return The empty response returned by the API. + * + * @example + * ```ts + * await ai.caches.delete({name: '...'}); // The server-generated resource name. + * ``` + */ + delete(params: types.DeleteCachedContentParameters): Promise<types.DeleteCachedContentResponse>; + /** + * Updates cached content configurations. + * + * @param params - The parameters for the update request. + * @return The updated cached content. + * + * @example + * ```ts + * const response = await ai.caches.update({ + * name: '...', // The server-generated resource name. + * config: {'ttl': '7600s'} + * }); + * ``` + */ + update(params: types.UpdateCachedContentParameters): Promise<types.CachedContent>; + private listInternal; +} + +/** + * CallableTool is an invokable tool that can be executed with external + * application (e.g., via Model Context Protocol) or local functions with + * function calling. + */ +export declare interface CallableTool { + /** + * Returns tool that can be called by Gemini. + */ + tool(): Promise<Tool>; + /** + * Executes the callable tool with the given function call arguments and + * returns the response parts from the tool execution. + */ + callTool(functionCalls: FunctionCall[]): Promise<Part[]>; +} + +/** + * CallableToolConfig is the configuration for a callable tool. + */ +export declare interface CallableToolConfig { + /** + * Specifies the model's behavior after invoking this tool. + */ + behavior?: Behavior; + /** + * Timeout for remote calls in milliseconds. Note this timeout applies only to + * tool remote calls, and not making HTTP requests to the API. */ + timeout?: number; +} + +/** Optional parameters. */ +export declare interface CancelBatchJobConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Config for batches.cancel parameters. */ +export declare interface CancelBatchJobParameters { + /** A fully-qualified BatchJob resource name or ID. + Example: "projects/.../locations/.../batchPredictionJobs/456" + or "456" when project and location are initialized in the client. + */ + name: string; + /** Optional parameters for the request. */ + config?: CancelBatchJobConfig; +} + +/** Optional parameters for tunings.cancel method. */ +export declare interface CancelTuningJobConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Parameters for the cancel method. */ +export declare interface CancelTuningJobParameters { + /** The resource name of the tuning job. */ + name: string; + /** Optional parameters for the request. */ + config?: CancelTuningJobConfig; +} + +/** Empty response for tunings.cancel method. */ +export declare class CancelTuningJobResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; +} + +/** A response candidate generated from the model. */ +export declare interface Candidate { + /** Contains the multi-part content of the response. + */ + content?: Content; + /** Source attribution of the generated content. + */ + citationMetadata?: CitationMetadata; + /** Describes the reason the model stopped generating tokens. + */ + finishMessage?: string; + /** Number of tokens for this candidate. + */ + tokenCount?: number; + /** The reason why the model stopped generating tokens. + If empty, the model has not stopped generating the tokens. + */ + finishReason?: FinishReason; + /** Output only. Average log probability score of the candidate. */ + avgLogprobs?: number; + /** Output only. Metadata specifies sources used to ground generated content. */ + groundingMetadata?: GroundingMetadata; + /** Output only. Index of the candidate. */ + index?: number; + /** Output only. Log-likelihood scores for the response tokens and top tokens */ + logprobsResult?: LogprobsResult; + /** Output only. List of ratings for the safety of a response candidate. There is at most one rating per category. */ + safetyRatings?: SafetyRating[]; + /** Output only. Metadata related to url context retrieval tool. */ + urlContextMetadata?: UrlContextMetadata; +} + +/** + * Chat session that enables sending messages to the model with previous + * conversation context. + * + * @remarks + * The session maintains all the turns between user and model. + */ +export declare class Chat { + private readonly apiClient; + private readonly modelsModule; + private readonly model; + private readonly config; + private history; + private sendPromise; + constructor(apiClient: ApiClient, modelsModule: Models, model: string, config?: types.GenerateContentConfig, history?: types.Content[]); + /** + * Sends a message to the model and returns the response. + * + * @remarks + * This method will wait for the previous message to be processed before + * sending the next message. + * + * @see {@link Chat#sendMessageStream} for streaming method. + * @param params - parameters for sending messages within a chat session. + * @returns The model's response. + * + * @example + * ```ts + * const chat = ai.chats.create({model: 'gemini-2.0-flash'}); + * const response = await chat.sendMessage({ + * message: 'Why is the sky blue?' + * }); + * console.log(response.text); + * ``` + */ + sendMessage(params: types.SendMessageParameters): Promise<types.GenerateContentResponse>; + /** + * Sends a message to the model and returns the response in chunks. + * + * @remarks + * This method will wait for the previous message to be processed before + * sending the next message. + * + * @see {@link Chat#sendMessage} for non-streaming method. + * @param params - parameters for sending the message. + * @return The model's response. + * + * @example + * ```ts + * const chat = ai.chats.create({model: 'gemini-2.0-flash'}); + * const response = await chat.sendMessageStream({ + * message: 'Why is the sky blue?' + * }); + * for await (const chunk of response) { + * console.log(chunk.text); + * } + * ``` + */ + sendMessageStream(params: types.SendMessageParameters): Promise<AsyncGenerator<types.GenerateContentResponse>>; + /** + * Returns the chat history. + * + * @remarks + * The history is a list of contents alternating between user and model. + * + * There are two types of history: + * - The `curated history` contains only the valid turns between user and + * model, which will be included in the subsequent requests sent to the model. + * - The `comprehensive history` contains all turns, including invalid or + * empty model outputs, providing a complete record of the history. + * + * The history is updated after receiving the response from the model, + * for streaming response, it means receiving the last chunk of the response. + * + * The `comprehensive history` is returned by default. To get the `curated + * history`, set the `curated` parameter to `true`. + * + * @param curated - whether to return the curated history or the comprehensive + * history. + * @return History contents alternating between user and model for the entire + * chat session. + */ + getHistory(curated?: boolean): types.Content[]; + private processStreamResponse; + private recordHistory; +} + +/** + * A utility class to create a chat session. + */ +export declare class Chats { + private readonly modelsModule; + private readonly apiClient; + constructor(modelsModule: Models, apiClient: ApiClient); + /** + * Creates a new chat session. + * + * @remarks + * The config in the params will be used for all requests within the chat + * session unless overridden by a per-request `config` in + * @see {@link types.SendMessageParameters#config}. + * + * @param params - Parameters for creating a chat session. + * @returns A new chat session. + * + * @example + * ```ts + * const chat = ai.chats.create({ + * model: 'gemini-2.0-flash' + * config: { + * temperature: 0.5, + * maxOutputTokens: 1024, + * } + * }); + * ``` + */ + create(params: types.CreateChatParameters): Chat; +} + +/** Describes the machine learning model version checkpoint. */ +export declare interface Checkpoint { + /** The ID of the checkpoint. + */ + checkpointId?: string; + /** The epoch of the checkpoint. + */ + epoch?: string; + /** The step of the checkpoint. + */ + step?: string; +} + +/** Config for telling the service how to chunk the file. */ +export declare interface ChunkingConfig { + /** White space chunking configuration. */ + whiteSpaceConfig?: WhiteSpaceConfig; +} + +/** Source attributions for content. This data type is not supported in Gemini API. */ +export declare interface Citation { + /** Output only. End index into the content. */ + endIndex?: number; + /** Output only. License of the attribution. */ + license?: string; + /** Output only. Publication date of the attribution. */ + publicationDate?: GoogleTypeDate; + /** Output only. Start index into the content. */ + startIndex?: number; + /** Output only. Title of the attribution. */ + title?: string; + /** Output only. Url reference of the attribution. */ + uri?: string; +} + +/** Citation information when the model quotes another source. */ +export declare interface CitationMetadata { + /** Contains citation information when the model directly quotes, at + length, from another source. Can include traditional websites and code + repositories. + */ + citations?: Citation[]; +} + +declare interface ClientOptions { + /** + * Defaults to process.env['GEMINI_API_KEY']. + */ + apiKey?: string | null | undefined; + apiVersion?: string | undefined; + /** + * Override the default base URL for the API, e.g., "https://api.example.com/v2/" + * + * Defaults to process.env['GEMINI_NEXT_GEN_API_BASE_URL']. + */ + baseURL?: string | null | undefined; + /** + * The maximum amount of time (in milliseconds) that the client should wait for a response + * from the server before timing out a single request. + * + * Note that request timeouts are retried by default, so in a worst-case scenario you may wait + * much longer than this timeout before the promise succeeds or fails. + * + * @unit milliseconds + */ + timeout?: number | undefined; + /** + * Additional `RequestInit` options to be passed to `fetch` calls. + * Properties will be overridden by per-request `fetchOptions`. + */ + fetchOptions?: MergedRequestInit | undefined; + /** + * Specify a custom `fetch` function implementation. + * + * If not provided, we expect that `fetch` is defined globally. + */ + fetch?: Fetch | undefined; + /** + * The maximum number of times that the client will retry a request in case of a + * temporary failure, like a network error or a 5XX error from the server. + * + * @default 2 + */ + maxRetries?: number | undefined; + /** + * Default headers to include with every request to the API. + * + * These can be removed in individual requests by explicitly setting the + * header to `null` in request options. + */ + defaultHeaders?: HeadersLike | undefined; + /** + * Default query parameters to include with every request to the API. + * + * These can be removed in individual requests by explicitly setting the + * param to `undefined` in request options. + */ + defaultQuery?: Record<string, string | undefined> | undefined; + /** + * Set the log level. + * + * Defaults to process.env['GEMINI_NEXT_GEN_API_LOG'] or 'warn' if it isn't set. + */ + logLevel?: LogLevel | undefined; + /** + * Set the logger. + * + * Defaults to globalThis.console. + */ + logger?: Logger | undefined; + /** + * The adapter to the parent API client instance (for accessing auth, project, location) + */ + clientAdapter: GeminiNextGenAPIClientAdapter; +} + +/** + * The arguments to pass to the code execution. + */ +declare interface CodeExecutionCallArguments { + /** + * The code to be executed. + */ + code?: string; + /** + * Programming language of the `code`. + */ + language?: 'python'; +} + +/** + * Code execution content. + */ +declare interface CodeExecutionCallContent { + type: 'code_execution_call'; + /** + * A unique ID for this specific tool call. + */ + id?: string; + /** + * The arguments to pass to the code execution. + */ + arguments?: CodeExecutionCallArguments; +} + +/** Result of executing the [ExecutableCode]. Only generated when using the [CodeExecution] tool, and always follows a `part` containing the [ExecutableCode]. */ +export declare interface CodeExecutionResult { + /** Required. Outcome of the code execution. */ + outcome?: Outcome; + /** Optional. Contains stdout when code execution is successful, stderr or other description otherwise. */ + output?: string; +} + +/** + * Code execution result content. + */ +declare interface CodeExecutionResultContent { + type: 'code_execution_result'; + /** + * ID to match the ID from the code execution call block. + */ + call_id?: string; + /** + * Whether the code execution resulted in an error. + */ + is_error?: boolean; + /** + * The output of the code execution. + */ + result?: string; + /** + * A signature hash for backend validation. + */ + signature?: string; +} + +/** Success and error statistics of processing multiple entities (for example, DataItems or structured data rows) in batch. This data type is not supported in Gemini API. */ +export declare interface CompletionStats { + /** Output only. The number of entities for which any error was encountered. */ + failedCount?: string; + /** Output only. In cases when enough errors are encountered a job, pipeline, or operation may be failed as a whole. Below is the number of entities for which the processing had not been finished (either in successful or failed state). Set to -1 if the number is unknown (for example, the operation failed before the total entity number could be collected). */ + incompleteCount?: string; + /** Output only. The number of entities that had been processed successfully. */ + successfulCount?: string; + /** Output only. The number of the successful forecast points that are generated by the forecasting model. This is ONLY used by the forecasting batch prediction. */ + successfulForecastPointCount?: string; +} + +/** Tool to support computer use. */ +export declare interface ComputerUse { + /** Required. The environment being operated. */ + environment?: Environment; + /** By default, predefined functions are included in the final model call. + Some of them can be explicitly excluded from being automatically included. + This can serve two purposes: + 1. Using a more restricted / different action space. + 2. Improving the definitions / instructions of predefined functions. */ + excludedPredefinedFunctions?: string[]; +} + +/** Optional parameters for computing tokens. */ +export declare interface ComputeTokensConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Parameters for computing tokens. */ +export declare interface ComputeTokensParameters { + /** ID of the model to use. For a list of models, see `Google models + <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */ + model: string; + /** Input content. */ + contents: ContentListUnion; + /** Optional parameters for the request. + */ + config?: ComputeTokensConfig; +} + +/** Response for computing tokens. */ +export declare class ComputeTokensResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** Lists of tokens info from the input. A ComputeTokensRequest could have multiple instances with a prompt in each instance. We also need to return lists of tokens info for the request with multiple instances. */ + tokensInfo?: TokensInfo[]; +} + +/** Local tokenizer compute tokens result. */ +export declare interface ComputeTokensResult { + /** Lists of tokens info from the input. */ + tokensInfo?: TokensInfo[]; +} + +declare type _ConditionalNodeReadableStream<R = any> = typeof globalThis extends { + ReadableStream: any; +} ? never : _NodeReadableStream<R>; + +declare class ConflictError extends APIError<409, Headers> { +} + +/** Contains the multi-part content of a message. */ +export declare interface Content { + /** List of parts that constitute a single message. Each part may have + a different IANA MIME type. */ + parts?: Part[]; + /** Optional. The producer of the content. Must be either 'user' or 'model'. Useful to set for multi-turn conversations, otherwise can be left blank or unset. */ + role?: string; +} + +/** + * The content of the response. + */ +declare type Content_2 = TextContent | ImageContent | AudioContent | DocumentContent | VideoContent | ThoughtContent | FunctionCallContent | FunctionResultContent | CodeExecutionCallContent | CodeExecutionResultContent | URLContextCallContent | URLContextResultContent | GoogleSearchCallContent | GoogleSearchResultContent | MCPServerToolCallContent | MCPServerToolResultContent | FileSearchCallContent | FileSearchResultContent; + +declare interface ContentDelta { + delta?: ContentDelta.TextDelta | ContentDelta.ImageDelta | ContentDelta.AudioDelta | ContentDelta.DocumentDelta | ContentDelta.VideoDelta | ContentDelta.ThoughtSummaryDelta | ContentDelta.ThoughtSignatureDelta | ContentDelta.FunctionCallDelta | ContentDelta.FunctionResultDelta | ContentDelta.CodeExecutionCallDelta | ContentDelta.CodeExecutionResultDelta | ContentDelta.URLContextCallDelta | ContentDelta.URLContextResultDelta | ContentDelta.GoogleSearchCallDelta | ContentDelta.GoogleSearchResultDelta | ContentDelta.MCPServerToolCallDelta | ContentDelta.MCPServerToolResultDelta | ContentDelta.FileSearchCallDelta | ContentDelta.FileSearchResultDelta; + /** + * The event_id token to be used to resume the interaction stream, from this event. + */ + event_id?: string; + event_type?: 'content.delta'; + index?: number; +} + +declare namespace ContentDelta { + interface TextDelta { + type: 'text'; + /** + * Citation information for model-generated content. + */ + annotations?: Array<InteractionsAPI.Annotation>; + text?: string; + } + interface ImageDelta { + type: 'image'; + data?: string; + /** + * The mime type of the image. + */ + mime_type?: InteractionsAPI.ImageMimeType; + /** + * The resolution of the media. + */ + resolution?: 'low' | 'medium' | 'high' | 'ultra_high'; + uri?: string; + } + interface AudioDelta { + type: 'audio'; + data?: string; + /** + * The mime type of the audio. + */ + mime_type?: InteractionsAPI.AudioMimeType; + uri?: string; + } + interface DocumentDelta { + type: 'document'; + data?: string; + /** + * The mime type of the document. + */ + mime_type?: InteractionsAPI.DocumentMimeType; + uri?: string; + } + interface VideoDelta { + type: 'video'; + data?: string; + /** + * The mime type of the video. + */ + mime_type?: InteractionsAPI.VideoMimeType; + /** + * The resolution of the media. + */ + resolution?: 'low' | 'medium' | 'high' | 'ultra_high'; + uri?: string; + } + interface ThoughtSummaryDelta { + type: 'thought_summary'; + /** + * A text content block. + */ + content?: InteractionsAPI.TextContent | InteractionsAPI.ImageContent; + } + interface ThoughtSignatureDelta { + type: 'thought_signature'; + /** + * Signature to match the backend source to be part of the generation. + */ + signature?: string; + } + interface FunctionCallDelta { + type: 'function_call'; + /** + * A unique ID for this specific tool call. + */ + id?: string; + arguments?: { + [key: string]: unknown; + }; + name?: string; + } + interface FunctionResultDelta { + type: 'function_result'; + /** + * ID to match the ID from the function call block. + */ + call_id?: string; + is_error?: boolean; + name?: string; + /** + * Tool call result delta. + */ + result?: FunctionResultDelta.Items | unknown | string; + } + namespace FunctionResultDelta { + interface Items { + items?: Array<InteractionsAPI.TextContent | InteractionsAPI.ImageContent>; + } + } + interface CodeExecutionCallDelta { + type: 'code_execution_call'; + /** + * A unique ID for this specific tool call. + */ + id?: string; + /** + * The arguments to pass to the code execution. + */ + arguments?: InteractionsAPI.CodeExecutionCallArguments; + } + interface CodeExecutionResultDelta { + type: 'code_execution_result'; + /** + * ID to match the ID from the function call block. + */ + call_id?: string; + is_error?: boolean; + result?: string; + signature?: string; + } + interface URLContextCallDelta { + type: 'url_context_call'; + /** + * A unique ID for this specific tool call. + */ + id?: string; + /** + * The arguments to pass to the URL context. + */ + arguments?: InteractionsAPI.URLContextCallArguments; + } + interface URLContextResultDelta { + type: 'url_context_result'; + /** + * ID to match the ID from the function call block. + */ + call_id?: string; + is_error?: boolean; + result?: Array<InteractionsAPI.URLContextResult>; + signature?: string; + } + interface GoogleSearchCallDelta { + type: 'google_search_call'; + /** + * A unique ID for this specific tool call. + */ + id?: string; + /** + * The arguments to pass to Google Search. + */ + arguments?: InteractionsAPI.GoogleSearchCallArguments; + } + interface GoogleSearchResultDelta { + type: 'google_search_result'; + /** + * ID to match the ID from the function call block. + */ + call_id?: string; + is_error?: boolean; + result?: Array<InteractionsAPI.GoogleSearchResult>; + signature?: string; + } + interface MCPServerToolCallDelta { + type: 'mcp_server_tool_call'; + /** + * A unique ID for this specific tool call. + */ + id?: string; + arguments?: { + [key: string]: unknown; + }; + name?: string; + server_name?: string; + } + interface MCPServerToolResultDelta { + type: 'mcp_server_tool_result'; + /** + * ID to match the ID from the function call block. + */ + call_id?: string; + name?: string; + /** + * Tool call result delta. + */ + result?: MCPServerToolResultDelta.Items | unknown | string; + server_name?: string; + } + namespace MCPServerToolResultDelta { + interface Items { + items?: Array<InteractionsAPI.TextContent | InteractionsAPI.ImageContent>; + } + } + interface FileSearchCallDelta { + type: 'file_search_call'; + /** + * A unique ID for this specific tool call. + */ + id?: string; + } + interface FileSearchResultDelta { + type: 'file_search_result'; + result?: Array<FileSearchResultDelta.Result>; + } + namespace FileSearchResultDelta { + /** + * The result of the File Search. + */ + interface Result { + /** + * The name of the file search store. + */ + file_search_store?: string; + /** + * The text of the search result. + */ + text?: string; + /** + * The title of the search result. + */ + title?: string; + } + } +} + +/** The embedding generated from an input content. */ +export declare interface ContentEmbedding { + /** A list of floats representing an embedding. + */ + values?: number[]; + /** Vertex API only. Statistics of the input text associated with this + embedding. + */ + statistics?: ContentEmbeddingStatistics; +} + +/** Statistics of the input text associated with the result of content embedding. */ +export declare interface ContentEmbeddingStatistics { + /** Vertex API only. If the input text was truncated due to having + a length longer than the allowed maximum input. + */ + truncated?: boolean; + /** Vertex API only. Number of tokens of the input text. + */ + tokenCount?: number; +} + +export declare type ContentListUnion = Content | Content[] | PartUnion | PartUnion[]; + +/** A content reference image. + + A content reference image represents a subject to reference (ex. person, + product, animal) provided by the user. It can optionally be provided in + addition to a style reference image (ex. background, style reference). */ +export declare class ContentReferenceImage { + /** The reference image for the editing operation. */ + referenceImage?: Image_2; + /** The id of the reference image. */ + referenceId?: number; + /** The type of the reference image. Only set by the SDK. */ + referenceType?: string; + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI(): ReferenceImageAPIInternal; +} + +declare interface ContentStart { + /** + * The content of the response. + */ + content?: Content_2; + /** + * The event_id token to be used to resume the interaction stream, from this event. + */ + event_id?: string; + event_type?: 'content.start'; + index?: number; +} + +declare interface ContentStop { + /** + * The event_id token to be used to resume the interaction stream, from this event. + */ + event_id?: string; + event_type?: 'content.stop'; + index?: number; +} + +export declare type ContentUnion = Content | PartUnion[] | PartUnion; + +/** Enables context window compression -- mechanism managing model context window so it does not exceed given length. */ +export declare interface ContextWindowCompressionConfig { + /** Number of tokens (before running turn) that triggers context window compression mechanism. */ + triggerTokens?: string; + /** Sliding window compression mechanism. */ + slidingWindow?: SlidingWindow; +} + +/** Configuration for a Control reference image. */ +export declare interface ControlReferenceConfig { + /** The type of control reference image to use. */ + controlType?: ControlReferenceType; + /** Defaults to False. When set to True, the control image will be + computed by the model based on the control type. When set to False, + the control image must be provided by the user. */ + enableControlImageComputation?: boolean; +} + +/** A control reference image. + + The image of the control reference image is either a control image provided + by the user, or a regular image which the backend will use to generate a + control image of. In the case of the latter, the + enable_control_image_computation field in the config should be set to True. + + A control image is an image that represents a sketch image of areas for the + model to fill in based on the prompt. */ +export declare class ControlReferenceImage { + /** The reference image for the editing operation. */ + referenceImage?: Image_2; + /** The id of the reference image. */ + referenceId?: number; + /** The type of the reference image. Only set by the SDK. */ + referenceType?: string; + /** Configuration for the control reference image. */ + config?: ControlReferenceConfig; + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI(): ReferenceImageAPIInternal; +} + +/** Enum representing the control type of a control reference image. */ +export declare enum ControlReferenceType { + CONTROL_TYPE_DEFAULT = "CONTROL_TYPE_DEFAULT", + CONTROL_TYPE_CANNY = "CONTROL_TYPE_CANNY", + CONTROL_TYPE_SCRIBBLE = "CONTROL_TYPE_SCRIBBLE", + CONTROL_TYPE_FACE_MESH = "CONTROL_TYPE_FACE_MESH" +} + +/** Config for the count_tokens method. */ +export declare interface CountTokensConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** Instructions for the model to steer it toward better performance. + */ + systemInstruction?: ContentUnion; + /** Code that enables the system to interact with external systems to + perform an action outside of the knowledge and scope of the model. + */ + tools?: Tool[]; + /** Configuration that the model uses to generate the response. Not + supported by the Gemini Developer API. + */ + generationConfig?: GenerationConfig; +} + +/** Parameters for counting tokens. */ +export declare interface CountTokensParameters { + /** ID of the model to use. For a list of models, see `Google models + <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */ + model: string; + /** Input content. */ + contents: ContentListUnion; + /** Configuration for counting tokens. */ + config?: CountTokensConfig; +} + +/** Response for counting tokens. */ +export declare class CountTokensResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** Total number of tokens. */ + totalTokens?: number; + /** Number of tokens in the cached part of the prompt (the cached content). */ + cachedContentTokenCount?: number; +} + +/** Local tokenizer count tokens result. */ +export declare interface CountTokensResult { + /** The total number of tokens. */ + totalTokens?: number; +} + +declare interface CreateAgentInteractionParamsNonStreaming extends BaseCreateAgentInteractionParams { + /** + * Body param: Input only. Whether the interaction will be streamed. + */ + stream?: false; +} + +declare interface CreateAgentInteractionParamsStreaming extends BaseCreateAgentInteractionParams { + /** + * Body param: Input only. Whether the interaction will be streamed. + */ + stream: true; +} + +/** Optional parameters. */ +export declare interface CreateAuthTokenConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** An optional time after which, when using the resulting token, + messages in Live API sessions will be rejected. (Gemini may + preemptively close the session after this time.) + + If not set then this defaults to 30 minutes in the future. If set, this + value must be less than 20 hours in the future. */ + expireTime?: string; + /** The time after which new Live API sessions using the token + resulting from this request will be rejected. + + If not set this defaults to 60 seconds in the future. If set, this value + must be less than 20 hours in the future. */ + newSessionExpireTime?: string; + /** The number of times the token can be used. If this value is zero + then no limit is applied. Default is 1. Resuming a Live API session does + not count as a use. */ + uses?: number; + /** Configuration specific to Live API connections created using this token. */ + liveConnectConstraints?: LiveConnectConstraints; + /** Additional fields to lock in the effective LiveConnectParameters. */ + lockAdditionalFields?: string[]; +} + +/** Config for auth_tokens.create parameters. */ +export declare interface CreateAuthTokenParameters { + /** Optional parameters for the request. */ + config?: CreateAuthTokenConfig; +} + +/** Config for optional parameters. */ +export declare interface CreateBatchJobConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** The user-defined name of this BatchJob. + */ + displayName?: string; + /** GCS or BigQuery URI prefix for the output predictions. Example: + "gs://path/to/output/data" or "bq://projectId.bqDatasetId.bqTableId". + */ + dest?: BatchJobDestinationUnion; +} + +/** Config for batches.create parameters. */ +export declare interface CreateBatchJobParameters { + /** The name of the model to produces the predictions via the BatchJob. + */ + model?: string; + /** GCS URI(-s) or BigQuery URI to your input data to run batch job. + Example: "gs://path/to/input/data" or "bq://projectId.bqDatasetId.bqTableId". + */ + src: BatchJobSourceUnion; + /** Optional parameters for creating a BatchJob. + */ + config?: CreateBatchJobConfig; +} + +/** Optional configuration for cached content creation. */ +export declare interface CreateCachedContentConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** The TTL for this resource. The expiration time is computed: now + TTL. It is a duration string, with up to nine fractional digits, terminated by 's'. Example: "3.5s". */ + ttl?: string; + /** Timestamp of when this resource is considered expired. Uses RFC 3339 format, Example: 2014-10-02T15:01:23Z. */ + expireTime?: string; + /** The user-generated meaningful display name of the cached content. + */ + displayName?: string; + /** The content to cache. + */ + contents?: ContentListUnion; + /** Developer set system instruction. + */ + systemInstruction?: ContentUnion; + /** A list of `Tools` the model may use to generate the next response. + */ + tools?: Tool[]; + /** Configuration for the tools to use. This config is shared for all tools. + */ + toolConfig?: ToolConfig; + /** The Cloud KMS resource identifier of the customer managed + encryption key used to protect a resource. + The key needs to be in the same region as where the compute resource is + created. See + https://cloud.google.com/vertex-ai/docs/general/cmek for more + details. If this is set, then all created CachedContent objects + will be encrypted with the provided encryption key. + Allowed formats: projects/{project}/locations/{location}/keyRings/{key_ring}/cryptoKeys/{crypto_key} + */ + kmsKeyName?: string; +} + +/** Parameters for caches.create method. */ +export declare interface CreateCachedContentParameters { + /** ID of the model to use. Example: gemini-2.0-flash */ + model: string; + /** Configuration that contains optional parameters. + */ + config?: CreateCachedContentConfig; +} + +/** Parameters for initializing a new chat session. + + These parameters are used when creating a chat session with the + `chats.create()` method. */ +export declare interface CreateChatParameters { + /** The name of the model to use for the chat session. + + For example: 'gemini-2.0-flash', 'gemini-2.0-flash-lite', etc. See Gemini API + docs to find the available models. + */ + model: string; + /** Config for the entire chat session. + + This config applies to all requests within the session + unless overridden by a per-request `config` in `SendMessageParameters`. + */ + config?: GenerateContentConfig; + /** The initial conversation history for the chat session. + + This allows you to start the chat with a pre-existing history. The history + must be a list of `Content` alternating between 'user' and 'model' roles. + It should start with a 'user' message. + */ + history?: Content[]; +} + +/** Config for optional parameters. */ +export declare interface CreateEmbeddingsBatchJobConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** The user-defined name of this BatchJob. + */ + displayName?: string; +} + +/** Config for batches.create parameters. */ +export declare interface CreateEmbeddingsBatchJobParameters { + /** The name of the model to produces the predictions via the BatchJob. + */ + model?: string; + /** input data to run batch job". + */ + src: EmbeddingsBatchJobSource; + /** Optional parameters for creating a BatchJob. + */ + config?: CreateEmbeddingsBatchJobConfig; +} + +/** Used to override the default configuration. */ +export declare interface CreateFileConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Generates the parameters for the private _create method. */ +export declare interface CreateFileParameters { + /** The file to be uploaded. + mime_type: (Required) The MIME type of the file. Must be provided. + name: (Optional) The name of the file in the destination (e.g. + 'files/sample-image'). + display_name: (Optional) The display name of the file. + */ + file: File_2; + /** Used to override the default configuration. */ + config?: CreateFileConfig; +} + +/** Response for the create file method. */ +export declare class CreateFileResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; +} + +/** Optional parameters for creating a file search store. */ +export declare interface CreateFileSearchStoreConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** The human-readable display name for the file search store. + */ + displayName?: string; +} + +/** Config for file_search_stores.create parameters. */ +export declare interface CreateFileSearchStoreParameters { + /** Optional parameters for creating a file search store. + */ + config?: CreateFileSearchStoreConfig; +} + +/** + * Creates a `FunctionResponsePart` object from a `base64` encoded `string`. + */ +export declare function createFunctionResponsePartFromBase64(data: string, mimeType: string): FunctionResponsePart; + +/** + * Creates a `FunctionResponsePart` object from a `URI` string. + */ +export declare function createFunctionResponsePartFromUri(uri: string, mimeType: string): FunctionResponsePart; + +/** + * Creates a `Content` object with a model role from a `PartListUnion` object or `string`. + */ +export declare function createModelContent(partOrString: PartListUnion | string): Content; + +declare interface CreateModelInteractionParamsNonStreaming extends BaseCreateModelInteractionParams { + /** + * Body param: Input only. Whether the interaction will be streamed. + */ + stream?: false; +} + +declare interface CreateModelInteractionParamsStreaming extends BaseCreateModelInteractionParams { + /** + * Body param: Input only. Whether the interaction will be streamed. + */ + stream: true; +} + +/** + * Creates a `Part` object from a `base64` encoded `string`. + */ +export declare function createPartFromBase64(data: string, mimeType: string, mediaResolution?: PartMediaResolutionLevel): Part; + +/** + * Creates a `Part` object from the `outcome` and `output` of a `CodeExecutionResult` object. + */ +export declare function createPartFromCodeExecutionResult(outcome: Outcome, output: string): Part; + +/** + * Creates a `Part` object from the `code` and `language` of an `ExecutableCode` object. + */ +export declare function createPartFromExecutableCode(code: string, language: Language): Part; + +/** + * Creates a `Part` object from a `FunctionCall` object. + */ +export declare function createPartFromFunctionCall(name: string, args: Record<string, unknown>): Part; + +/** + * Creates a `Part` object from a `FunctionResponse` object. + */ +export declare function createPartFromFunctionResponse(id: string, name: string, response: Record<string, unknown>, parts?: FunctionResponsePart[]): Part; + +/** + * Creates a `Part` object from a `text` string. + */ +export declare function createPartFromText(text: string): Part; + +/** + * Creates a `Part` object from a `URI` string. + */ +export declare function createPartFromUri(uri: string, mimeType: string, mediaResolution?: PartMediaResolutionLevel): Part; + +/** Fine-tuning job creation request - optional fields. */ +export declare interface CreateTuningJobConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** The method to use for tuning (SUPERVISED_FINE_TUNING or PREFERENCE_TUNING or DISTILLATION). If not set, the default method (SFT) will be used. */ + method?: TuningMethod; + /** Validation dataset for tuning. The dataset must be formatted as a JSONL file. */ + validationDataset?: TuningValidationDataset; + /** The display name of the tuned Model. The name can be up to 128 characters long and can consist of any UTF-8 characters. */ + tunedModelDisplayName?: string; + /** The description of the TuningJob */ + description?: string; + /** Number of complete passes the model makes over the entire training dataset during training. */ + epochCount?: number; + /** Multiplier for adjusting the default learning rate. 1P models only. Mutually exclusive with learning_rate. */ + learningRateMultiplier?: number; + /** If set to true, disable intermediate checkpoints and only the last checkpoint will be exported. Otherwise, enable intermediate checkpoints. */ + exportLastCheckpointOnly?: boolean; + /** The optional checkpoint id of the pre-tuned model to use for tuning, if applicable. */ + preTunedModelCheckpointId?: string; + /** Adapter size for tuning. */ + adapterSize?: AdapterSize; + /** Tuning mode for SFT tuning. */ + tuningMode?: TuningMode; + /** Custom base model for tuning. This is only supported for OSS models in Vertex. */ + customBaseModel?: string; + /** The batch size hyperparameter for tuning. This is only supported for OSS models in Vertex. */ + batchSize?: number; + /** The learning rate for tuning. OSS models only. Mutually exclusive with learning_rate_multiplier. */ + learningRate?: number; + /** Optional. The labels with user-defined metadata to organize TuningJob and generated resources such as Model and Endpoint. Label keys and values can be no longer than 64 characters (Unicode codepoints), can only contain lowercase letters, numeric characters, underscores and dashes. International characters are allowed. See https://goo.gl/xmQnxf for more information and examples of labels. */ + labels?: Record<string, string>; + /** Weight for KL Divergence regularization, Preference Optimization tuning only. */ + beta?: number; + /** The base teacher model that is being distilled. Distillation only. */ + baseTeacherModel?: string; + /** The resource name of the Tuned teacher model. Distillation only. */ + tunedTeacherModelSource?: string; + /** Multiplier for adjusting the weight of the SFT loss. Distillation only. */ + sftLossWeightMultiplier?: number; + /** The Google Cloud Storage location where the tuning job outputs are written. */ + outputUri?: string; + /** The encryption spec of the tuning job. Customer-managed encryption key options for a TuningJob. If this is set, then all resources created by the TuningJob will be encrypted with provided encryption key. */ + encryptionSpec?: EncryptionSpec; +} + +/** Fine-tuning job creation parameters - optional fields. */ +export declare interface CreateTuningJobParameters { + /** The base model that is being tuned, e.g., "gemini-2.5-flash". */ + baseModel: string; + /** Cloud Storage path to file containing training dataset for tuning. The dataset must be formatted as a JSONL file. */ + trainingDataset: TuningDataset; + /** Configuration for the tuning job. */ + config?: CreateTuningJobConfig; +} + +/** Fine-tuning job creation parameters - optional fields. */ +export declare interface CreateTuningJobParametersPrivate { + /** The base model that is being tuned, e.g., "gemini-2.5-flash". */ + baseModel?: string; + /** The PreTunedModel that is being tuned. */ + preTunedModel?: PreTunedModel; + /** Cloud Storage path to file containing training dataset for tuning. The dataset must be formatted as a JSONL file. */ + trainingDataset: TuningDataset; + /** Configuration for the tuning job. */ + config?: CreateTuningJobConfig; +} + +/** + * Creates a `Content` object with a user role from a `PartListUnion` object or `string`. + */ +export declare function createUserContent(partOrString: PartListUnion | string): Content; + +/** User provided metadata stored as key-value pairs. This data type is not supported in Vertex AI. */ +export declare interface CustomMetadata { + /** Required. The key of the metadata to store. */ + key?: string; + /** The numeric value of the metadata to store. */ + numericValue?: number; + /** The StringList value of the metadata to store. */ + stringListValue?: StringList; + /** The string value of the metadata to store. */ + stringValue?: string; +} + +/** Distribution computed over a tuning dataset. This data type is not supported in Gemini API. */ +export declare interface DatasetDistribution { + /** Output only. Defines the histogram bucket. */ + buckets?: DatasetDistributionDistributionBucket[]; + /** Output only. The maximum of the population values. */ + max?: number; + /** Output only. The arithmetic mean of the values in the population. */ + mean?: number; + /** Output only. The median of the values in the population. */ + median?: number; + /** Output only. The minimum of the population values. */ + min?: number; + /** Output only. The 5th percentile of the values in the population. */ + p5?: number; + /** Output only. The 95th percentile of the values in the population. */ + p95?: number; + /** Output only. Sum of a given population of values. */ + sum?: number; +} + +/** Dataset bucket used to create a histogram for the distribution given a population of values. This data type is not supported in Gemini API. */ +export declare interface DatasetDistributionDistributionBucket { + /** Output only. Number of values in the bucket. */ + count?: string; + /** Output only. Left bound of the bucket. */ + left?: number; + /** Output only. Right bound of the bucket. */ + right?: number; +} + +/** Statistics computed over a tuning dataset. This data type is not supported in Gemini API. */ +export declare interface DatasetStats { + /** Output only. Number of billable characters in the tuning dataset. */ + totalBillableCharacterCount?: string; + /** Output only. Number of tuning characters in the tuning dataset. */ + totalTuningCharacterCount?: string; + /** Output only. Number of examples in the tuning dataset. */ + tuningDatasetExampleCount?: string; + /** Output only. Number of tuning steps for this Tuning Job. */ + tuningStepCount?: string; + /** Output only. Sample user messages in the training dataset uri. */ + userDatasetExamples?: Content[]; + /** Output only. Dataset distributions for the user input tokens. */ + userInputTokenDistribution?: DatasetDistribution; + /** Output only. Dataset distributions for the messages per example. */ + userMessagePerExampleDistribution?: DatasetDistribution; + /** Output only. Dataset distributions for the user output tokens. */ + userOutputTokenDistribution?: DatasetDistribution; +} + +/** + * Configuration for the Deep Research agent. + */ +declare interface DeepResearchAgentConfig { + /** + * Whether to include thought summaries in the response. + */ + thinking_summaries?: 'auto' | 'none'; + type?: 'deep-research'; +} + +/** Optional parameters for models.get method. */ +export declare interface DeleteBatchJobConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Config for batches.delete parameters. */ +export declare interface DeleteBatchJobParameters { + /** A fully-qualified BatchJob resource name or ID. + Example: "projects/.../locations/.../batchPredictionJobs/456" + or "456" when project and location are initialized in the client. + */ + name: string; + /** Optional parameters for the request. */ + config?: DeleteBatchJobConfig; +} + +/** Optional parameters for caches.delete method. */ +export declare interface DeleteCachedContentConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Parameters for caches.delete method. */ +export declare interface DeleteCachedContentParameters { + /** The server-generated resource name of the cached content. + */ + name: string; + /** Optional parameters for the request. + */ + config?: DeleteCachedContentConfig; +} + +/** Empty response for caches.delete method. */ +export declare class DeleteCachedContentResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; +} + +/** Config for optional parameters. */ +export declare interface DeleteDocumentConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** If set to true, any `Chunk`s and objects related to this `Document` will + also be deleted. + */ + force?: boolean; +} + +/** Config for documents.delete parameters. */ +export declare interface DeleteDocumentParameters { + /** The resource name of the Document. + Example: fileSearchStores/file-search-store-foo/documents/documents-bar */ + name: string; + /** Optional parameters for the request. */ + config?: DeleteDocumentConfig; +} + +/** Used to override the default configuration. */ +export declare interface DeleteFileConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Generates the parameters for the get method. */ +export declare interface DeleteFileParameters { + /** The name identifier for the file to be deleted. */ + name: string; + /** Used to override the default configuration. */ + config?: DeleteFileConfig; +} + +/** Response for the delete file method. */ +export declare class DeleteFileResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; +} + +/** Optional parameters for deleting a FileSearchStore. */ +export declare interface DeleteFileSearchStoreConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** If set to true, any Documents and objects related to this FileSearchStore will also be deleted. + If false (the default), a FAILED_PRECONDITION error will be returned if + the FileSearchStore contains any Documents. + */ + force?: boolean; +} + +/** Config for file_search_stores.delete parameters. */ +export declare interface DeleteFileSearchStoreParameters { + /** The resource name of the FileSearchStore. Example: `fileSearchStores/my-file-search-store-123` */ + name: string; + /** Optional parameters for the request. */ + config?: DeleteFileSearchStoreConfig; +} + +/** Configuration for deleting a tuned model. */ +export declare interface DeleteModelConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Parameters for deleting a tuned model. */ +export declare interface DeleteModelParameters { + model: string; + /** Optional parameters for the request. */ + config?: DeleteModelConfig; +} + +export declare class DeleteModelResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; +} + +/** The return value of delete operation. */ +export declare interface DeleteResourceJob { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + name?: string; + done?: boolean; + error?: JobError; +} + +/** Statistics computed for datasets used for distillation. This data type is not supported in Gemini API. */ +export declare interface DistillationDataStats { + /** Output only. Statistics computed for the training dataset. */ + trainingDatasetStats?: DatasetStats; +} + +/** Hyperparameters for Distillation. This data type is not supported in Gemini API. */ +export declare interface DistillationHyperParameters { + /** Optional. Adapter size for distillation. */ + adapterSize?: AdapterSize; + /** Optional. Number of complete passes the model makes over the entire training dataset during training. */ + epochCount?: string; + /** Optional. Multiplier for adjusting the default learning rate. */ + learningRateMultiplier?: number; +} + +/** Distillation tuning spec for tuning. */ +export declare interface DistillationSpec { + /** The GCS URI of the prompt dataset to use during distillation. */ + promptDatasetUri?: string; + /** The base teacher model that is being distilled. See [Supported models](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/tuning#supported_models). */ + baseTeacherModel?: string; + /** Optional. Hyperparameters for Distillation. */ + hyperParameters?: DistillationHyperParameters; + /** Deprecated. A path in a Cloud Storage bucket, which will be treated as the root output directory of the distillation pipeline. It is used by the system to generate the paths of output artifacts. */ + pipelineRootDirectory?: string; + /** The student model that is being tuned, e.g., "google/gemma-2b-1.1-it". Deprecated. Use base_model instead. */ + studentModel?: string; + /** Deprecated. Cloud Storage path to file containing training dataset for tuning. The dataset must be formatted as a JSONL file. */ + trainingDatasetUri?: string; + /** The resource name of the Tuned teacher model. Format: `projects/{project}/locations/{location}/models/{model}`. */ + tunedTeacherModelSource?: string; + /** Optional. Cloud Storage path to file containing validation dataset for tuning. The dataset must be formatted as a JSONL file. */ + validationDatasetUri?: string; +} + +/** A Document is a collection of Chunks. */ +declare interface Document_2 { + /** The resource name of the Document. + Example: fileSearchStores/file-search-store-foo/documents/documents-bar */ + name?: string; + /** The human-readable display name for the Document. */ + displayName?: string; + /** The current state of the Document. */ + state?: DocumentState; + /** The size of the Document in bytes. */ + sizeBytes?: string; + /** The MIME type of the Document. */ + mimeType?: string; + /** Output only. The Timestamp of when the `Document` was created. */ + createTime?: string; + /** Optional. User provided custom metadata stored as key-value pairs used for querying. A `Document` can have a maximum of 20 `CustomMetadata`. */ + customMetadata?: CustomMetadata[]; + /** Output only. The Timestamp of when the `Document` was last updated. */ + updateTime?: string; +} +export { Document_2 as Document } + +/** + * A document content block. + */ +declare interface DocumentContent { + type: 'document'; + /** + * The document content. + */ + data?: string; + /** + * The mime type of the document. + */ + mime_type?: DocumentMimeType; + /** + * The URI of the document. + */ + uri?: string; +} + +/** + * The mime type of the document. + */ +declare type DocumentMimeType = (string & {}) | 'application/pdf'; + +declare class Documents extends BaseModule { + private readonly apiClient; + constructor(apiClient: ApiClient); + /** + * Lists documents. + * + * @param params - The parameters for the list request. + * @return - A pager of documents. + * + * @example + * ```ts + * const documents = await ai.documents.list({parent:'rag_store_name', config: {'pageSize': 2}}); + * for await (const document of documents) { + * console.log(document); + * } + * ``` + */ + list: (params: types.ListDocumentsParameters) => Promise<Pager<types.Document>>; + /** + * Gets a Document. + * + * @param params - The parameters for getting a document. + * @return Document. + */ + get(params: types.GetDocumentParameters): Promise<types.Document>; + /** + * Deletes a Document. + * + * @param params - The parameters for deleting a document. + */ + delete(params: types.DeleteDocumentParameters): Promise<void>; + private listInternal; +} + +/** State for the lifecycle of a Document. */ +export declare enum DocumentState { + STATE_UNSPECIFIED = "STATE_UNSPECIFIED", + STATE_PENDING = "STATE_PENDING", + STATE_ACTIVE = "STATE_ACTIVE", + STATE_FAILED = "STATE_FAILED" +} + +/** @ts-ignore */ +declare type _DOMReadableStream<R = any> = globalThis.ReadableStream<R>; + +export declare type DownloadableFileUnion = string | File_2 | GeneratedVideo | Video; + +declare interface Downloader { + /** + * Downloads a file to the given location. + * + * @param params The parameters for downloading the file. + * @param apiClient The ApiClient to use for uploading. + * @return A Promises that resolves when the download is complete. + */ + download(params: DownloadFileParameters, apiClient: ApiClient): Promise<void>; +} + +/** Used to override the default configuration. */ +export declare interface DownloadFileConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Parameters used to download a file. */ +export declare interface DownloadFileParameters { + /** The file to download. It can be a file name, a file object or a generated video. */ + file: DownloadableFileUnion; + /** Location where the file should be downloaded to. */ + downloadPath: string; + /** Configuration to for the download operation. */ + config?: DownloadFileConfig; +} + +/** + * Configuration for dynamic agents. + */ +declare interface DynamicAgentConfig { + type?: 'dynamic'; + [k: string]: unknown; +} + +/** Describes the options to customize dynamic retrieval. */ +export declare interface DynamicRetrievalConfig { + /** Optional. The threshold to be used in dynamic retrieval. If not set, a system default value is used. */ + dynamicThreshold?: number; + /** The mode of the predictor to be used in dynamic retrieval. */ + mode?: DynamicRetrievalConfigMode; +} + +/** The mode of the predictor to be used in dynamic retrieval. */ +export declare enum DynamicRetrievalConfigMode { + /** + * Always trigger retrieval. + */ + MODE_UNSPECIFIED = "MODE_UNSPECIFIED", + /** + * Run retrieval only when system decides it is necessary. + */ + MODE_DYNAMIC = "MODE_DYNAMIC" +} + +/** Configuration for editing an image. */ +export declare interface EditImageConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** Cloud Storage URI used to store the generated images. */ + outputGcsUri?: string; + /** Description of what to discourage in the generated images. */ + negativePrompt?: string; + /** Number of images to generate. */ + numberOfImages?: number; + /** Aspect ratio of the generated images. Supported values are + "1:1", "3:4", "4:3", "9:16", and "16:9". */ + aspectRatio?: string; + /** Controls how much the model adheres to the text prompt. Large + values increase output and prompt alignment, but may compromise image + quality. */ + guidanceScale?: number; + /** Random seed for image generation. This is not available when + ``add_watermark`` is set to true. */ + seed?: number; + /** Filter level for safety filtering. */ + safetyFilterLevel?: SafetyFilterLevel; + /** Allows generation of people by the model. */ + personGeneration?: PersonGeneration; + /** Whether to report the safety scores of each generated image and + the positive prompt in the response. */ + includeSafetyAttributes?: boolean; + /** Whether to include the Responsible AI filter reason if the image + is filtered out of the response. */ + includeRaiReason?: boolean; + /** Language of the text in the prompt. */ + language?: ImagePromptLanguage; + /** MIME type of the generated image. */ + outputMimeType?: string; + /** Compression quality of the generated image (for ``image/jpeg`` + only). */ + outputCompressionQuality?: number; + /** Whether to add a watermark to the generated images. */ + addWatermark?: boolean; + /** User specified labels to track billing usage. */ + labels?: Record<string, string>; + /** Describes the editing mode for the request. */ + editMode?: EditMode; + /** The number of sampling steps. A higher value has better image + quality, while a lower value has better latency. */ + baseSteps?: number; +} + +/** Parameters for the request to edit an image. */ +export declare interface EditImageParameters { + /** The model to use. */ + model: string; + /** A text description of the edit to apply to the image. */ + prompt: string; + /** The reference images for Imagen 3 editing. */ + referenceImages: ReferenceImage[]; + /** Configuration for editing. */ + config?: EditImageConfig; +} + +/** Response for the request to edit an image. */ +export declare class EditImageResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** Generated images. */ + generatedImages?: GeneratedImage[]; +} + +/** Enum representing the editing mode. */ +export declare enum EditMode { + EDIT_MODE_DEFAULT = "EDIT_MODE_DEFAULT", + EDIT_MODE_INPAINT_REMOVAL = "EDIT_MODE_INPAINT_REMOVAL", + EDIT_MODE_INPAINT_INSERTION = "EDIT_MODE_INPAINT_INSERTION", + EDIT_MODE_OUTPAINT = "EDIT_MODE_OUTPAINT", + EDIT_MODE_CONTROLLED_EDITING = "EDIT_MODE_CONTROLLED_EDITING", + EDIT_MODE_STYLE = "EDIT_MODE_STYLE", + EDIT_MODE_BGSWAP = "EDIT_MODE_BGSWAP", + EDIT_MODE_PRODUCT_IMAGE = "EDIT_MODE_PRODUCT_IMAGE" +} + +/** Parameters for the embed_content method. */ +export declare interface EmbedContentBatch { + /** The content to embed. Only the `parts.text` fields will be counted. + */ + contents?: ContentListUnion; + /** Configuration that contains optional parameters. + */ + config?: EmbedContentConfig; +} + +/** Optional parameters for the embed_content method. */ +export declare interface EmbedContentConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** Type of task for which the embedding will be used. + */ + taskType?: string; + /** Title for the text. Only applicable when TaskType is + `RETRIEVAL_DOCUMENT`. + */ + title?: string; + /** Reduced dimension for the output embedding. If set, + excessive values in the output embedding are truncated from the end. + Supported by newer models since 2024 only. You cannot set this value if + using the earlier model (`models/embedding-001`). + */ + outputDimensionality?: number; + /** Vertex API only. The MIME type of the input. + */ + mimeType?: string; + /** Vertex API only. Whether to silently truncate inputs longer than + the max sequence length. If this option is set to false, oversized inputs + will lead to an INVALID_ARGUMENT error, similar to other text APIs. + */ + autoTruncate?: boolean; +} + +/** Request-level metadata for the Vertex Embed Content API. */ +export declare interface EmbedContentMetadata { + /** Vertex API only. The total number of billable characters included + in the request. + */ + billableCharacterCount?: number; +} + +/** Parameters for the embed_content method. */ +export declare interface EmbedContentParameters { + /** ID of the model to use. For a list of models, see `Google models + <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */ + model: string; + /** The content to embed. Only the `parts.text` fields will be counted. + */ + contents: ContentListUnion; + /** Configuration that contains optional parameters. + */ + config?: EmbedContentConfig; +} + +/** Response for the embed_content method. */ +export declare class EmbedContentResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** The embeddings for each request, in the same order as provided in + the batch request. + */ + embeddings?: ContentEmbedding[]; + /** Vertex API only. Metadata about the request. + */ + metadata?: EmbedContentMetadata; +} + +export declare interface EmbeddingsBatchJobSource { + /** The Gemini Developer API's file resource name of the input data + (e.g. "files/12345"). + */ + fileName?: string; + /** The Gemini Developer API's inlined input data to run batch job. + */ + inlinedRequests?: EmbedContentBatch; +} + +/** Represents a customer-managed encryption key spec that can be applied to a top-level resource. This data type is not supported in Gemini API. */ +export declare interface EncryptionSpec { + /** Required. The Cloud KMS resource identifier of the customer managed encryption key used to protect a resource. Has the form: `projects/my-project/locations/my-region/keyRings/my-kr/cryptoKeys/my-key`. The key needs to be in the same region as where the compute resource is created. */ + kmsKeyName?: string; +} + +/** An endpoint where you deploy models. */ +export declare interface Endpoint { + /** Resource name of the endpoint. */ + name?: string; + /** ID of the model that's deployed to the endpoint. */ + deployedModelId?: string; +} + +/** End of speech sensitivity. */ +export declare enum EndSensitivity { + /** + * The default is END_SENSITIVITY_LOW. + */ + END_SENSITIVITY_UNSPECIFIED = "END_SENSITIVITY_UNSPECIFIED", + /** + * Automatic detection ends speech more often. + */ + END_SENSITIVITY_HIGH = "END_SENSITIVITY_HIGH", + /** + * Automatic detection ends speech less often. + */ + END_SENSITIVITY_LOW = "END_SENSITIVITY_LOW" +} + +/** Tool to search public web data, powered by Vertex AI Search and Sec4 compliance. This data type is not supported in Gemini API. */ +export declare interface EnterpriseWebSearch { + /** Optional. List of domains to be excluded from the search results. The default limit is 2000 domains. */ + excludeDomains?: string[]; + /** Optional. Sites with confidence level chosen & above this value will be blocked from the search results. */ + blockingConfidence?: PhishBlockThreshold; +} + +/** An entity representing the segmented area. */ +export declare interface EntityLabel { + /** The label of the segmented entity. */ + label?: string; + /** The confidence score of the detected label. */ + score?: number; +} + +/** The environment being operated. */ +export declare enum Environment { + /** + * Defaults to browser. + */ + ENVIRONMENT_UNSPECIFIED = "ENVIRONMENT_UNSPECIFIED", + /** + * Operates in a web browser. + */ + ENVIRONMENT_BROWSER = "ENVIRONMENT_BROWSER" +} + +declare interface ErrorEvent_2 { + /** + * Error message from an interaction. + */ + error?: ErrorEvent_2.Error; + /** + * The event_id token to be used to resume the interaction stream, from this event. + */ + event_id?: string; + event_type?: 'error'; +} + +declare namespace ErrorEvent_2 { + /** + * Error message from an interaction. + */ + interface Error { + /** + * A URI that identifies the error type. + */ + code?: string; + /** + * A human-readable error message. + */ + message?: string; + } +} + +declare namespace Errors { + export { + GeminiNextGenAPIClientError, + APIError, + APIUserAbortError, + APIConnectionError, + APIConnectionTimeoutError, + BadRequestError, + AuthenticationError, + PermissionDeniedError, + NotFoundError, + ConflictError, + UnprocessableEntityError, + RateLimitError, + InternalServerError + } +} + +/** Code generated by the model that is meant to be executed, and the result returned to the model. Generated when using the [CodeExecution] tool, in which the code will be automatically executed, and a corresponding [CodeExecutionResult] will also be generated. */ +export declare interface ExecutableCode { + /** Required. The code to be executed. */ + code?: string; + /** Required. Programming language of the `code`. */ + language?: Language; +} + +/** Retrieve from data source powered by external API for grounding. The external API is not owned by Google, but need to follow the pre-defined API spec. This data type is not supported in Gemini API. */ +export declare interface ExternalApi { + /** The authentication config to access the API. Deprecated. Please use auth_config instead. */ + apiAuth?: ApiAuth; + /** The API spec that the external API implements. */ + apiSpec?: ApiSpec; + /** The authentication config to access the API. */ + authConfig?: AuthConfig; + /** Parameters for the elastic search API. */ + elasticSearchParams?: ExternalApiElasticSearchParams; + /** The endpoint of the external API. The system will call the API at this endpoint to retrieve the data for grounding. Example: https://acme.com:443/search */ + endpoint?: string; + /** Parameters for the simple search API. */ + simpleSearchParams?: ExternalApiSimpleSearchParams; +} + +/** The search parameters to use for the ELASTIC_SEARCH spec. This data type is not supported in Gemini API. */ +export declare interface ExternalApiElasticSearchParams { + /** The ElasticSearch index to use. */ + index?: string; + /** Optional. Number of hits (chunks) to request. When specified, it is passed to Elasticsearch as the `num_hits` param. */ + numHits?: number; + /** The ElasticSearch search template to use. */ + searchTemplate?: string; +} + +/** The search parameters to use for SIMPLE_SEARCH spec. This data type is not supported in Gemini API. */ +export declare interface ExternalApiSimpleSearchParams { +} + +/** Options for feature selection preference. */ +export declare enum FeatureSelectionPreference { + FEATURE_SELECTION_PREFERENCE_UNSPECIFIED = "FEATURE_SELECTION_PREFERENCE_UNSPECIFIED", + PRIORITIZE_QUALITY = "PRIORITIZE_QUALITY", + BALANCED = "BALANCED", + PRIORITIZE_COST = "PRIORITIZE_COST" +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +declare type Fetch = (input: string | URL | Request, init?: RequestInit) => Promise<Response>; + +export declare interface FetchPredictOperationConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Parameters for the fetchPredictOperation method. */ +export declare interface FetchPredictOperationParameters { + /** The server-assigned name for the operation. */ + operationName: string; + resourceName: string; + /** Used to override the default configuration. */ + config?: FetchPredictOperationConfig; +} + +/** @ts-ignore For users who use Deno */ +declare type FetchRequestInit = NonNullable<OverloadedParameters<typeof fetch>[1]>; + +/** A file uploaded to the API. */ +declare interface File_2 { + /** The `File` resource name. The ID (name excluding the "files/" prefix) can contain up to 40 characters that are lowercase alphanumeric or dashes (-). The ID cannot start or end with a dash. If the name is empty on create, a unique name will be generated. Example: `files/123-456` */ + name?: string; + /** Optional. The human-readable display name for the `File`. The display name must be no more than 512 characters in length, including spaces. Example: 'Welcome Image' */ + displayName?: string; + /** Output only. MIME type of the file. */ + mimeType?: string; + /** Output only. Size of the file in bytes. */ + sizeBytes?: string; + /** Output only. The timestamp of when the `File` was created. */ + createTime?: string; + /** Output only. The timestamp of when the `File` will be deleted. Only set if the `File` is scheduled to expire. */ + expirationTime?: string; + /** Output only. The timestamp of when the `File` was last updated. */ + updateTime?: string; + /** Output only. SHA-256 hash of the uploaded bytes. The hash value is encoded in base64 format. */ + sha256Hash?: string; + /** Output only. The URI of the `File`. */ + uri?: string; + /** Output only. The URI of the `File`, only set for downloadable (generated) files. */ + downloadUri?: string; + /** Output only. Processing state of the File. */ + state?: FileState; + /** Output only. The source of the `File`. */ + source?: FileSource; + /** Output only. Metadata for a video. */ + videoMetadata?: Record<string, unknown>; + /** Output only. Error status if File processing failed. */ + error?: FileStatus; +} +export { File_2 as File } + +/** URI based data. */ +export declare interface FileData { + /** Optional. Display name of the file data. Used to provide a label or filename to distinguish file datas. This field is only returned in PromptMessage for prompt management. It is currently used in the Gemini GenerateContent calls only when server side tools (code_execution, google_search, and url_context) are enabled. This field is not supported in Gemini API. */ + displayName?: string; + /** Required. URI. */ + fileUri?: string; + /** Required. The IANA standard MIME type of the source data. */ + mimeType?: string; +} + +export declare class Files extends BaseModule { + private readonly apiClient; + constructor(apiClient: ApiClient); + /** + * Lists files. + * + * @param params - The parameters for the list request. + * @return - A pager of files. + * + * @example + * ```ts + * const files = await ai.files.list({config: {'pageSize': 2}}); + * for await (const file of files) { + * console.log(file); + * } + * ``` + */ + list: (params?: types.ListFilesParameters) => Promise<Pager<types.File>>; + /** + * Uploads a file asynchronously to the Gemini API. + * This method is not available in Vertex AI. + * Supported upload sources: + * - Node.js: File path (string) or Blob object. + * - Browser: Blob object (e.g., File). + * + * @remarks + * The `mimeType` can be specified in the `config` parameter. If omitted: + * - For file path (string) inputs, the `mimeType` will be inferred from the + * file extension. + * - For Blob object inputs, the `mimeType` will be set to the Blob's `type` + * property. + * Somex eamples for file extension to mimeType mapping: + * .txt -> text/plain + * .json -> application/json + * .jpg -> image/jpeg + * .png -> image/png + * .mp3 -> audio/mpeg + * .mp4 -> video/mp4 + * + * This section can contain multiple paragraphs and code examples. + * + * @param params - Optional parameters specified in the + * `types.UploadFileParameters` interface. + * @see {@link types.UploadFileParameters#config} for the optional + * config in the parameters. + * @return A promise that resolves to a `types.File` object. + * @throws An error if called on a Vertex AI client. + * @throws An error if the `mimeType` is not provided and can not be inferred, + * the `mimeType` can be provided in the `params.config` parameter. + * @throws An error occurs if a suitable upload location cannot be established. + * + * @example + * The following code uploads a file to Gemini API. + * + * ```ts + * const file = await ai.files.upload({file: 'file.txt', config: { + * mimeType: 'text/plain', + * }}); + * console.log(file.name); + * ``` + */ + upload(params: types.UploadFileParameters): Promise<types.File>; + /** + * Downloads a remotely stored file asynchronously to a location specified in + * the `params` object. This method only works on Node environment, to + * download files in the browser, use a browser compliant method like an <a> + * tag. + * + * @param params - The parameters for the download request. + * + * @example + * The following code downloads an example file named "files/mehozpxf877d" as + * "file.txt". + * + * ```ts + * await ai.files.download({file: file.name, downloadPath: 'file.txt'}); + * ``` + */ + download(params: types.DownloadFileParameters): Promise<void>; + /** + * Registers Google Cloud Storage files for use with the API. + * This method is only available in Node.js environments. + */ + registerFiles(params: types.RegisterFilesParameters): Promise<types.RegisterFilesResponse>; + protected _registerFiles(params: types.InternalRegisterFilesParameters): Promise<types.RegisterFilesResponse>; + private listInternal; + private createInternal; + /** + * Retrieves the file information from the service. + * + * @param params - The parameters for the get request + * @return The Promise that resolves to the types.File object requested. + * + * @example + * ```ts + * const config: GetFileParameters = { + * name: fileName, + * }; + * file = await ai.files.get(config); + * console.log(file.name); + * ``` + */ + get(params: types.GetFileParameters): Promise<types.File>; + /** + * Deletes a remotely stored file. + * + * @param params - The parameters for the delete request. + * @return The DeleteFileResponse, the response for the delete method. + * + * @example + * The following code deletes an example file named "files/mehozpxf877d". + * + * ```ts + * await ai.files.delete({name: file.name}); + * ``` + */ + delete(params: types.DeleteFileParameters): Promise<types.DeleteFileResponse>; + private registerFilesInternal; +} + +/** Tool to retrieve knowledge from the File Search Stores. */ +export declare interface FileSearch { + /** The names of the file_search_stores to retrieve from. + Example: `fileSearchStores/my-file-search-store-123` */ + fileSearchStoreNames?: string[]; + /** The number of file search retrieval chunks to retrieve. */ + topK?: number; + /** Metadata filter to apply to the file search retrieval documents. See https://google.aip.dev/160 for the syntax of the filter expression. */ + metadataFilter?: string; +} + +/** + * File Search content. + */ +declare interface FileSearchCallContent { + type: 'file_search_call'; + /** + * A unique ID for this specific tool call. + */ + id?: string; +} + +/** + * File Search result content. + */ +declare interface FileSearchResultContent { + type: 'file_search_result'; + /** + * The results of the File Search. + */ + result?: Array<FileSearchResultContent.Result>; +} + +declare namespace FileSearchResultContent { + /** + * The result of the File Search. + */ + interface Result { + /** + * The name of the file search store. + */ + file_search_store?: string; + /** + * The text of the search result. + */ + text?: string; + /** + * The title of the search result. + */ + title?: string; + } +} + +/** A collection of Documents. */ +export declare interface FileSearchStore { + /** The resource name of the FileSearchStore. Example: `fileSearchStores/my-file-search-store-123` */ + name?: string; + /** The human-readable display name for the FileSearchStore. */ + displayName?: string; + /** The Timestamp of when the FileSearchStore was created. */ + createTime?: string; + /** The Timestamp of when the FileSearchStore was last updated. */ + updateTime?: string; + /** The number of documents in the FileSearchStore that are active and ready for retrieval. */ + activeDocumentsCount?: string; + /** The number of documents in the FileSearchStore that are being processed. */ + pendingDocumentsCount?: string; + /** The number of documents in the FileSearchStore that have failed processing. */ + failedDocumentsCount?: string; + /** The size of raw bytes ingested into the FileSearchStore. This is the + total size of all the documents in the FileSearchStore. */ + sizeBytes?: string; +} + +declare class FileSearchStores extends BaseModule { + private readonly apiClient; + readonly documents: Documents; + constructor(apiClient: ApiClient, documents?: Documents); + /** + * Lists file search stores. + * + * @param params - The parameters for the list request. + * @return - A pager of file search stores. + * + * @example + * ```ts + * const fileSearchStores = await ai.fileSearchStores.list({config: {'pageSize': 2}}); + * for await (const fileSearchStore of fileSearchStores) { + * console.log(fileSearchStore); + * } + * ``` + */ + list: (params?: types.ListFileSearchStoresParameters) => Promise<Pager<types.FileSearchStore>>; + /** + * Uploads a file asynchronously to a given File Search Store. + * This method is not available in Vertex AI. + * Supported upload sources: + * - Node.js: File path (string) or Blob object. + * - Browser: Blob object (e.g., File). + * + * @remarks + * The `mimeType` can be specified in the `config` parameter. If omitted: + * - For file path (string) inputs, the `mimeType` will be inferred from the + * file extension. + * - For Blob object inputs, the `mimeType` will be set to the Blob's `type` + * property. + * + * This section can contain multiple paragraphs and code examples. + * + * @param params - Optional parameters specified in the + * `types.UploadToFileSearchStoreParameters` interface. + * @see {@link types.UploadToFileSearchStoreParameters#config} for the optional + * config in the parameters. + * @return A promise that resolves to a long running operation. + * @throws An error if called on a Vertex AI client. + * @throws An error if the `mimeType` is not provided and can not be inferred, + * the `mimeType` can be provided in the `params.config` parameter. + * @throws An error occurs if a suitable upload location cannot be established. + * + * @example + * The following code uploads a file to a given file search store. + * + * ```ts + * const operation = await ai.fileSearchStores.upload({fileSearchStoreName: 'fileSearchStores/foo-bar', file: 'file.txt', config: { + * mimeType: 'text/plain', + * }}); + * console.log(operation.name); + * ``` + */ + uploadToFileSearchStore(params: types.UploadToFileSearchStoreParameters): Promise<types.UploadToFileSearchStoreOperation>; + /** + * Creates a File Search Store. + * + * @param params - The parameters for creating a File Search Store. + * @return FileSearchStore. + */ + create(params: types.CreateFileSearchStoreParameters): Promise<types.FileSearchStore>; + /** + * Gets a File Search Store. + * + * @param params - The parameters for getting a File Search Store. + * @return FileSearchStore. + */ + get(params: types.GetFileSearchStoreParameters): Promise<types.FileSearchStore>; + /** + * Deletes a File Search Store. + * + * @param params - The parameters for deleting a File Search Store. + */ + delete(params: types.DeleteFileSearchStoreParameters): Promise<void>; + private listInternal; + private uploadToFileSearchStoreInternal; + /** + * Imports a File from File Service to a FileSearchStore. + * + * This is a long-running operation, see aip.dev/151 + * + * @param params - The parameters for importing a file to a file search store. + * @return ImportFileOperation. + */ + importFile(params: types.ImportFileParameters): Promise<types.ImportFileOperation>; +} + +/** Source of the File. */ +export declare enum FileSource { + SOURCE_UNSPECIFIED = "SOURCE_UNSPECIFIED", + UPLOADED = "UPLOADED", + GENERATED = "GENERATED", + REGISTERED = "REGISTERED" +} + +/** + * Represents the size and mimeType of a file. The information is used to + * request the upload URL from the https://generativelanguage.googleapis.com/upload/v1beta/files endpoint. + * This interface defines the structure for constructing and executing HTTP + * requests. + */ +declare interface FileStat { + /** + * The size of the file in bytes. + */ + size: number; + /** + * The MIME type of the file. + */ + type: string | undefined; +} + +/** State for the lifecycle of a File. */ +export declare enum FileState { + STATE_UNSPECIFIED = "STATE_UNSPECIFIED", + PROCESSING = "PROCESSING", + ACTIVE = "ACTIVE", + FAILED = "FAILED" +} + +/** Status of a File that uses a common error model. */ +export declare interface FileStatus { + /** A list of messages that carry the error details. There is a common set of message types for APIs to use. */ + details?: Record<string, unknown>[]; + /** A list of messages that carry the error details. There is a common set of message types for APIs to use. */ + message?: string; + /** The status code. 0 for OK, 1 for CANCELLED */ + code?: number; +} + +declare type FinalizedRequestInit = RequestInit & { + headers: Headers; +}; + +declare type FinalRequestOptions = RequestOptions & { + method: HTTPMethod; + path: string; +}; + +/** Output only. The reason why the model stopped generating tokens. + + If empty, the model has not stopped generating the tokens. */ +export declare enum FinishReason { + /** + * The finish reason is unspecified. + */ + FINISH_REASON_UNSPECIFIED = "FINISH_REASON_UNSPECIFIED", + /** + * Token generation reached a natural stopping point or a configured stop sequence. + */ + STOP = "STOP", + /** + * Token generation reached the configured maximum output tokens. + */ + MAX_TOKENS = "MAX_TOKENS", + /** + * Token generation stopped because the content potentially contains safety violations. NOTE: When streaming, [content][] is empty if content filters blocks the output. + */ + SAFETY = "SAFETY", + /** + * The token generation stopped because of potential recitation. + */ + RECITATION = "RECITATION", + /** + * The token generation stopped because of using an unsupported language. + */ + LANGUAGE = "LANGUAGE", + /** + * All other reasons that stopped the token generation. + */ + OTHER = "OTHER", + /** + * Token generation stopped because the content contains forbidden terms. + */ + BLOCKLIST = "BLOCKLIST", + /** + * Token generation stopped for potentially containing prohibited content. + */ + PROHIBITED_CONTENT = "PROHIBITED_CONTENT", + /** + * Token generation stopped because the content potentially contains Sensitive Personally Identifiable Information (SPII). + */ + SPII = "SPII", + /** + * The function call generated by the model is invalid. + */ + MALFORMED_FUNCTION_CALL = "MALFORMED_FUNCTION_CALL", + /** + * Token generation stopped because generated images have safety violations. + */ + IMAGE_SAFETY = "IMAGE_SAFETY", + /** + * The tool call generated by the model is invalid. + */ + UNEXPECTED_TOOL_CALL = "UNEXPECTED_TOOL_CALL", + /** + * Image generation stopped because the generated images have prohibited content. + */ + IMAGE_PROHIBITED_CONTENT = "IMAGE_PROHIBITED_CONTENT", + /** + * The model was expected to generate an image, but none was generated. + */ + NO_IMAGE = "NO_IMAGE", + /** + * Image generation stopped because the generated image may be a recitation from a source. + */ + IMAGE_RECITATION = "IMAGE_RECITATION", + /** + * Image generation stopped for a reason not otherwise specified. + */ + IMAGE_OTHER = "IMAGE_OTHER" +} + +/** + * A tool that can be used by the model. + */ +declare interface Function_2 { + type: 'function'; + /** + * A description of the function. + */ + description?: string; + /** + * The name of the function. + */ + name?: string; + /** + * The JSON Schema for the function's parameters. + */ + parameters?: unknown; +} + +/** A function call. */ +export declare interface FunctionCall { + /** The unique id of the function call. If populated, the client to execute the + `function_call` and return the response with the matching `id`. */ + id?: string; + /** Optional. The function parameters and values in JSON object format. See [FunctionDeclaration.parameters] for parameter details. */ + args?: Record<string, unknown>; + /** Optional. The name of the function to call. Matches [FunctionDeclaration.name]. */ + name?: string; + /** Optional. The partial argument value of the function call. If provided, represents the arguments/fields that are streamed incrementally. This field is not supported in Gemini API. */ + partialArgs?: PartialArg[]; + /** Optional. Whether this is the last part of the FunctionCall. If true, another partial message for the current FunctionCall is expected to follow. This field is not supported in Gemini API. */ + willContinue?: boolean; +} + +/** + * A function tool call content block. + */ +declare interface FunctionCallContent { + /** + * A unique ID for this specific tool call. + */ + id: string; + /** + * The arguments to pass to the function. + */ + arguments: { + [key: string]: unknown; + }; + /** + * The name of the tool to call. + */ + name: string; + type: 'function_call'; +} + +/** Function calling config. */ +export declare interface FunctionCallingConfig { + /** Optional. Function names to call. Only set when the Mode is ANY. Function names should match [FunctionDeclaration.name]. With mode set to ANY, model will predict a function call from the set of function names provided. */ + allowedFunctionNames?: string[]; + /** Optional. Function calling mode. */ + mode?: FunctionCallingConfigMode; + /** Optional. When set to true, arguments of a single function call will be streamed out in multiple parts/contents/responses. Partial parameter results will be returned in the [FunctionCall.partial_args] field. This field is not supported in Gemini API. */ + streamFunctionCallArguments?: boolean; +} + +/** Function calling mode. */ +export declare enum FunctionCallingConfigMode { + /** + * Unspecified function calling mode. This value should not be used. + */ + MODE_UNSPECIFIED = "MODE_UNSPECIFIED", + /** + * Default model behavior, model decides to predict either function calls or natural language response. + */ + AUTO = "AUTO", + /** + * Model is constrained to always predicting function calls only. If "allowed_function_names" are set, the predicted function calls will be limited to any one of "allowed_function_names", else the predicted function calls will be any one of the provided "function_declarations". + */ + ANY = "ANY", + /** + * Model will not predict any function calls. Model behavior is same as when not passing any function declarations. + */ + NONE = "NONE", + /** + * Model is constrained to predict either function calls or natural language response. If "allowed_function_names" are set, the predicted function calls will be limited to any one of "allowed_function_names", else the predicted function calls will be any one of the provided "function_declarations". + */ + VALIDATED = "VALIDATED" +} + +/** Structured representation of a function declaration as defined by the [OpenAPI 3.0 specification](https://spec.openapis.org/oas/v3.0.3). Included in this declaration are the function name, description, parameters and response type. This FunctionDeclaration is a representation of a block of code that can be used as a `Tool` by the model and executed by the client. */ +export declare interface FunctionDeclaration { + /** Optional. Description and purpose of the function. Model uses it to decide how and whether to call the function. */ + description?: string; + /** Required. The name of the function to call. Must start with a letter or an underscore. Must be a-z, A-Z, 0-9, or contain underscores, dots and dashes, with a maximum length of 64. */ + name?: string; + /** Optional. Describes the parameters to this function in JSON Schema Object format. Reflects the Open API 3.03 Parameter Object. string Key: the name of the parameter. Parameter names are case sensitive. Schema Value: the Schema defining the type used for the parameter. For function with no parameters, this can be left unset. Parameter names must start with a letter or an underscore and must only contain chars a-z, A-Z, 0-9, or underscores with a maximum length of 64. Example with 1 required and 1 optional parameter: type: OBJECT properties: param1: type: STRING param2: type: INTEGER required: - param1 */ + parameters?: Schema; + /** Optional. Describes the parameters to the function in JSON Schema format. The schema must describe an object where the properties are the parameters to the function. For example: ``` { "type": "object", "properties": { "name": { "type": "string" }, "age": { "type": "integer" } }, "additionalProperties": false, "required": ["name", "age"], "propertyOrdering": ["name", "age"] } ``` This field is mutually exclusive with `parameters`. */ + parametersJsonSchema?: unknown; + /** Optional. Describes the output from this function in JSON Schema format. Reflects the Open API 3.03 Response Object. The Schema defines the type used for the response value of the function. */ + response?: Schema; + /** Optional. Describes the output from this function in JSON Schema format. The value specified by the schema is the response value of the function. This field is mutually exclusive with `response`. */ + responseJsonSchema?: unknown; + /** Optional. Specifies the function Behavior. Currently only supported by the BidiGenerateContent method. This field is not supported in Vertex AI. */ + behavior?: Behavior; +} + +/** A function response. */ +export declare class FunctionResponse { + /** Signals that function call continues, and more responses will be returned, turning the function call into a generator. Is only applicable to NON_BLOCKING function calls (see FunctionDeclaration.behavior for details), ignored otherwise. If false, the default, future responses will not be considered. Is only applicable to NON_BLOCKING function calls, is ignored otherwise. If set to false, future responses will not be considered. It is allowed to return empty `response` with `will_continue=False` to signal that the function call is finished. */ + willContinue?: boolean; + /** Specifies how the response should be scheduled in the conversation. Only applicable to NON_BLOCKING function calls, is ignored otherwise. Defaults to WHEN_IDLE. */ + scheduling?: FunctionResponseScheduling; + /** List of parts that constitute a function response. Each part may + have a different IANA MIME type. */ + parts?: FunctionResponsePart[]; + /** Optional. The id of the function call this response is for. Populated by the client to match the corresponding function call `id`. */ + id?: string; + /** Required. The name of the function to call. Matches [FunctionDeclaration.name] and [FunctionCall.name]. */ + name?: string; + /** Required. The function response in JSON object format. Use "output" key to specify function output and "error" key to specify error details (if any). If "output" and "error" keys are not specified, then whole "response" is treated as function output. */ + response?: Record<string, unknown>; +} + +/** Raw media bytes for function response. + + Text should not be sent as raw bytes, use the FunctionResponse.response + field. */ +export declare class FunctionResponseBlob { + /** Required. The IANA standard MIME type of the source data. */ + mimeType?: string; + /** Required. Inline media bytes. + * @remarks Encoded as base64 string. */ + data?: string; + /** Optional. Display name of the blob. + Used to provide a label or filename to distinguish blobs. */ + displayName?: string; +} + +/** URI based data for function response. */ +export declare class FunctionResponseFileData { + /** Required. URI. */ + fileUri?: string; + /** Required. The IANA standard MIME type of the source data. */ + mimeType?: string; + /** Optional. Display name of the file. + Used to provide a label or filename to distinguish files. */ + displayName?: string; +} + +/** A datatype containing media that is part of a `FunctionResponse` message. + + A `FunctionResponsePart` consists of data which has an associated datatype. A + `FunctionResponsePart` can only contain one of the accepted types in + `FunctionResponsePart.data`. + + A `FunctionResponsePart` must have a fixed IANA MIME type identifying the + type and subtype of the media if the `inline_data` field is filled with raw + bytes. */ +export declare class FunctionResponsePart { + /** Optional. Inline media bytes. */ + inlineData?: FunctionResponseBlob; + /** Optional. URI based data. */ + fileData?: FunctionResponseFileData; +} + +/** Specifies how the response should be scheduled in the conversation. */ +export declare enum FunctionResponseScheduling { + /** + * This value is unused. + */ + SCHEDULING_UNSPECIFIED = "SCHEDULING_UNSPECIFIED", + /** + * Only add the result to the conversation context, do not interrupt or trigger generation. + */ + SILENT = "SILENT", + /** + * Add the result to the conversation context, and prompt to generate output without interrupting ongoing generation. + */ + WHEN_IDLE = "WHEN_IDLE", + /** + * Add the result to the conversation context, interrupt ongoing generation and prompt to generate output. + */ + INTERRUPT = "INTERRUPT" +} + +/** + * A function tool result content block. + */ +declare interface FunctionResultContent { + /** + * ID to match the ID from the function call block. + */ + call_id: string; + /** + * The result of the tool call. + */ + result: FunctionResultContent.Items | unknown | string; + type: 'function_result'; + /** + * Whether the tool call resulted in an error. + */ + is_error?: boolean; + /** + * The name of the tool that was called. + */ + name?: string; +} + +declare namespace FunctionResultContent { + interface Items { + items?: Array<InteractionsAPI.TextContent | InteractionsAPI.ImageContent>; + } +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +declare interface GeminiNextGenAPIClientAdapter { + isVertexAI: () => boolean; + getProject: () => string | undefined; + getLocation: () => string | undefined; + getAuthHeaders: () => Headers | Promise<Headers>; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +declare class GeminiNextGenAPIClientError extends Error { +} + +/** Input example for preference optimization. This data type is not supported in Gemini API. */ +export declare interface GeminiPreferenceExample { + /** List of completions for a given prompt. */ + completions?: GeminiPreferenceExampleCompletion[]; + /** Multi-turn contents that represents the Prompt. */ + contents?: Content[]; +} + +/** Completion and its preference score. This data type is not supported in Gemini API. */ +export declare interface GeminiPreferenceExampleCompletion { + /** Single turn completion for the given prompt. */ + completion?: Content; + /** The score for the given completion. */ + score?: number; +} + +/** Optional model configuration parameters. + + For more information, see `Content generation parameters + <https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/content-generation-parameters>`_. */ +export declare interface GenerateContentConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** Instructions for the model to steer it toward better performance. + For example, "Answer as concisely as possible" or "Don't use technical + terms in your response". + */ + systemInstruction?: ContentUnion; + /** Value that controls the degree of randomness in token selection. + Lower temperatures are good for prompts that require a less open-ended or + creative response, while higher temperatures can lead to more diverse or + creative results. + */ + temperature?: number; + /** Tokens are selected from the most to least probable until the sum + of their probabilities equals this value. Use a lower value for less + random responses and a higher value for more random responses. + */ + topP?: number; + /** For each token selection step, the ``top_k`` tokens with the + highest probabilities are sampled. Then tokens are further filtered based + on ``top_p`` with the final token selected using temperature sampling. Use + a lower number for less random responses and a higher number for more + random responses. + */ + topK?: number; + /** Number of response variations to return. + */ + candidateCount?: number; + /** Maximum number of tokens that can be generated in the response. + */ + maxOutputTokens?: number; + /** List of strings that tells the model to stop generating text if one + of the strings is encountered in the response. + */ + stopSequences?: string[]; + /** Whether to return the log probabilities of the tokens that were + chosen by the model at each step. + */ + responseLogprobs?: boolean; + /** Number of top candidate tokens to return the log probabilities for + at each generation step. + */ + logprobs?: number; + /** Positive values penalize tokens that already appear in the + generated text, increasing the probability of generating more diverse + content. + */ + presencePenalty?: number; + /** Positive values penalize tokens that repeatedly appear in the + generated text, increasing the probability of generating more diverse + content. + */ + frequencyPenalty?: number; + /** When ``seed`` is fixed to a specific number, the model makes a best + effort to provide the same response for repeated requests. By default, a + random number is used. + */ + seed?: number; + /** Output response mimetype of the generated candidate text. + Supported mimetype: + - `text/plain`: (default) Text output. + - `application/json`: JSON response in the candidates. + The model needs to be prompted to output the appropriate response type, + otherwise the behavior is undefined. + This is a preview feature. + */ + responseMimeType?: string; + /** The `Schema` object allows the definition of input and output data types. + These types can be objects, but also primitives and arrays. + Represents a select subset of an [OpenAPI 3.0 schema + object](https://spec.openapis.org/oas/v3.0.3#schema). + If set, a compatible response_mime_type must also be set. + Compatible mimetypes: `application/json`: Schema for JSON response. + + If `response_schema` doesn't process your schema correctly, try using + `response_json_schema` instead. + */ + responseSchema?: SchemaUnion; + /** Optional. Output schema of the generated response. + This is an alternative to `response_schema` that accepts [JSON + Schema](https://json-schema.org/). If set, `response_schema` must be + omitted, but `response_mime_type` is required. While the full JSON Schema + may be sent, not all features are supported. Specifically, only the + following properties are supported: - `$id` - `$defs` - `$ref` - `$anchor` + - `type` - `format` - `title` - `description` - `enum` (for strings and + numbers) - `items` - `prefixItems` - `minItems` - `maxItems` - `minimum` - + `maximum` - `anyOf` - `oneOf` (interpreted the same as `anyOf`) - + `properties` - `additionalProperties` - `required` The non-standard + `propertyOrdering` property may also be set. Cyclic references are + unrolled to a limited degree and, as such, may only be used within + non-required properties. (Nullable properties are not sufficient.) If + `$ref` is set on a sub-schema, no other properties, except for than those + starting as a `$`, may be set. */ + responseJsonSchema?: unknown; + /** Configuration for model router requests. + */ + routingConfig?: GenerationConfigRoutingConfig; + /** Configuration for model selection. + */ + modelSelectionConfig?: ModelSelectionConfig; + /** Safety settings in the request to block unsafe content in the + response. + */ + safetySettings?: SafetySetting[]; + /** Code that enables the system to interact with external systems to + perform an action outside of the knowledge and scope of the model. + */ + tools?: ToolListUnion; + /** Associates model output to a specific function call. + */ + toolConfig?: ToolConfig; + /** Labels with user-defined metadata to break down billed charges. */ + labels?: Record<string, string>; + /** Resource name of a context cache that can be used in subsequent + requests. + */ + cachedContent?: string; + /** The requested modalities of the response. Represents the set of + modalities that the model can return. + */ + responseModalities?: string[]; + /** If specified, the media resolution specified will be used. + */ + mediaResolution?: MediaResolution; + /** The speech generation configuration. + */ + speechConfig?: SpeechConfigUnion; + /** If enabled, audio timestamp will be included in the request to the + model. + */ + audioTimestamp?: boolean; + /** The configuration for automatic function calling. + */ + automaticFunctionCalling?: AutomaticFunctionCallingConfig; + /** The thinking features configuration. + */ + thinkingConfig?: ThinkingConfig; + /** The image generation configuration. + */ + imageConfig?: ImageConfig; + /** Enables enhanced civic answers. It may not be available for all + models. This field is not supported in Vertex AI. + */ + enableEnhancedCivicAnswers?: boolean; + /** Settings for prompt and response sanitization using the Model Armor + service. If supplied, safety_settings must not be supplied. + */ + modelArmorConfig?: ModelArmorConfig; +} + +/** Config for models.generate_content parameters. */ +export declare interface GenerateContentParameters { + /** ID of the model to use. For a list of models, see `Google models + <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */ + model: string; + /** Content of the request. + */ + contents: ContentListUnion; + /** Configuration that contains optional model parameters. + */ + config?: GenerateContentConfig; +} + +/** Response message for PredictionService.GenerateContent. */ +export declare class GenerateContentResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** Response variations returned by the model. + */ + candidates?: Candidate[]; + /** Timestamp when the request is made to the server. + */ + createTime?: string; + /** The history of automatic function calling. + */ + automaticFunctionCallingHistory?: Content[]; + /** Output only. The model version used to generate the response. */ + modelVersion?: string; + /** Output only. Content filter results for a prompt sent in the request. Note: Sent only in the first stream chunk. Only happens when no candidates were generated due to content violations. */ + promptFeedback?: GenerateContentResponsePromptFeedback; + /** Output only. response_id is used to identify each response. It is the encoding of the event_id. */ + responseId?: string; + /** Usage metadata about the response(s). */ + usageMetadata?: GenerateContentResponseUsageMetadata; + /** + * Returns the concatenation of all text parts from the first candidate in the response. + * + * @remarks + * If there are multiple candidates in the response, the text from the first + * one will be returned. + * If there are non-text parts in the response, the concatenation of all text + * parts will be returned, and a warning will be logged. + * If there are thought parts in the response, the concatenation of all text + * parts excluding the thought parts will be returned. + * + * @example + * ```ts + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: + * 'Why is the sky blue?', + * }); + * + * console.debug(response.text); + * ``` + */ + get text(): string | undefined; + /** + * Returns the concatenation of all inline data parts from the first candidate + * in the response. + * + * @remarks + * If there are multiple candidates in the response, the inline data from the + * first one will be returned. If there are non-inline data parts in the + * response, the concatenation of all inline data parts will be returned, and + * a warning will be logged. + */ + get data(): string | undefined; + /** + * Returns the function calls from the first candidate in the response. + * + * @remarks + * If there are multiple candidates in the response, the function calls from + * the first one will be returned. + * If there are no function calls in the response, undefined will be returned. + * + * @example + * ```ts + * const controlLightFunctionDeclaration: FunctionDeclaration = { + * name: 'controlLight', + * parameters: { + * type: Type.OBJECT, + * description: 'Set the brightness and color temperature of a room light.', + * properties: { + * brightness: { + * type: Type.NUMBER, + * description: + * 'Light level from 0 to 100. Zero is off and 100 is full brightness.', + * }, + * colorTemperature: { + * type: Type.STRING, + * description: + * 'Color temperature of the light fixture which can be `daylight`, `cool` or `warm`.', + * }, + * }, + * required: ['brightness', 'colorTemperature'], + * }; + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: 'Dim the lights so the room feels cozy and warm.', + * config: { + * tools: [{functionDeclarations: [controlLightFunctionDeclaration]}], + * toolConfig: { + * functionCallingConfig: { + * mode: FunctionCallingConfigMode.ANY, + * allowedFunctionNames: ['controlLight'], + * }, + * }, + * }, + * }); + * console.debug(JSON.stringify(response.functionCalls)); + * ``` + */ + get functionCalls(): FunctionCall[] | undefined; + /** + * Returns the first executable code from the first candidate in the response. + * + * @remarks + * If there are multiple candidates in the response, the executable code from + * the first one will be returned. + * If there are no executable code in the response, undefined will be + * returned. + * + * @example + * ```ts + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: + * 'What is the sum of the first 50 prime numbers? Generate and run code for the calculation, and make sure you get all 50.' + * config: { + * tools: [{codeExecution: {}}], + * }, + * }); + * + * console.debug(response.executableCode); + * ``` + */ + get executableCode(): string | undefined; + /** + * Returns the first code execution result from the first candidate in the response. + * + * @remarks + * If there are multiple candidates in the response, the code execution result from + * the first one will be returned. + * If there are no code execution result in the response, undefined will be returned. + * + * @example + * ```ts + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: + * 'What is the sum of the first 50 prime numbers? Generate and run code for the calculation, and make sure you get all 50.' + * config: { + * tools: [{codeExecution: {}}], + * }, + * }); + * + * console.debug(response.codeExecutionResult); + * ``` + */ + get codeExecutionResult(): string | undefined; +} + +/** Content filter results for a prompt sent in the request. Note: This is sent only in the first stream chunk and only if no candidates were generated due to content violations. */ +export declare class GenerateContentResponsePromptFeedback { + /** Output only. The reason why the prompt was blocked. */ + blockReason?: BlockedReason; + /** Output only. A readable message that explains the reason why the prompt was blocked. This field is not supported in Gemini API. */ + blockReasonMessage?: string; + /** Output only. A list of safety ratings for the prompt. There is one rating per category. */ + safetyRatings?: SafetyRating[]; +} + +/** Usage metadata about the content generation request and response. This message provides a detailed breakdown of token usage and other relevant metrics. This data type is not supported in Gemini API. */ +export declare class GenerateContentResponseUsageMetadata { + /** Output only. A detailed breakdown of the token count for each modality in the cached content. */ + cacheTokensDetails?: ModalityTokenCount[]; + /** Output only. The number of tokens in the cached content that was used for this request. */ + cachedContentTokenCount?: number; + /** The total number of tokens in the generated candidates. */ + candidatesTokenCount?: number; + /** Output only. A detailed breakdown of the token count for each modality in the generated candidates. */ + candidatesTokensDetails?: ModalityTokenCount[]; + /** The total number of tokens in the prompt. This includes any text, images, or other media provided in the request. When `cached_content` is set, this also includes the number of tokens in the cached content. */ + promptTokenCount?: number; + /** Output only. A detailed breakdown of the token count for each modality in the prompt. */ + promptTokensDetails?: ModalityTokenCount[]; + /** Output only. The number of tokens that were part of the model's generated "thoughts" output, if applicable. */ + thoughtsTokenCount?: number; + /** Output only. The number of tokens in the results from tool executions, which are provided back to the model as input, if applicable. */ + toolUsePromptTokenCount?: number; + /** Output only. A detailed breakdown by modality of the token counts from the results of tool executions, which are provided back to the model as input. */ + toolUsePromptTokensDetails?: ModalityTokenCount[]; + /** The total number of tokens for the entire request. This is the sum of `prompt_token_count`, `candidates_token_count`, `tool_use_prompt_token_count`, and `thoughts_token_count`. */ + totalTokenCount?: number; + /** Output only. The traffic type for this request. */ + trafficType?: TrafficType; +} + +/** An output image. */ +export declare interface GeneratedImage { + /** The output image data. */ + image?: Image_2; + /** Responsible AI filter reason if the image is filtered out of the + response. */ + raiFilteredReason?: string; + /** Safety attributes of the image. Lists of RAI categories and their + scores of each content. */ + safetyAttributes?: SafetyAttributes; + /** The rewritten prompt used for the image generation if the prompt + enhancer is enabled. */ + enhancedPrompt?: string; +} + +/** A generated image mask. */ +export declare interface GeneratedImageMask { + /** The generated image mask. */ + mask?: Image_2; + /** The detected entities on the segmented area. */ + labels?: EntityLabel[]; +} + +/** A generated video. */ +export declare interface GeneratedVideo { + /** The output video */ + video?: Video; +} + +/** The config for generating an images. */ +export declare interface GenerateImagesConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** Cloud Storage URI used to store the generated images. */ + outputGcsUri?: string; + /** Description of what to discourage in the generated images. */ + negativePrompt?: string; + /** Number of images to generate. */ + numberOfImages?: number; + /** Aspect ratio of the generated images. Supported values are + "1:1", "3:4", "4:3", "9:16", and "16:9". */ + aspectRatio?: string; + /** Controls how much the model adheres to the text prompt. Large + values increase output and prompt alignment, but may compromise image + quality. */ + guidanceScale?: number; + /** Random seed for image generation. This is not available when + ``add_watermark`` is set to true. */ + seed?: number; + /** Filter level for safety filtering. */ + safetyFilterLevel?: SafetyFilterLevel; + /** Allows generation of people by the model. */ + personGeneration?: PersonGeneration; + /** Whether to report the safety scores of each generated image and + the positive prompt in the response. */ + includeSafetyAttributes?: boolean; + /** Whether to include the Responsible AI filter reason if the image + is filtered out of the response. */ + includeRaiReason?: boolean; + /** Language of the text in the prompt. */ + language?: ImagePromptLanguage; + /** MIME type of the generated image. */ + outputMimeType?: string; + /** Compression quality of the generated image (for ``image/jpeg`` + only). */ + outputCompressionQuality?: number; + /** Whether to add a watermark to the generated images. */ + addWatermark?: boolean; + /** User specified labels to track billing usage. */ + labels?: Record<string, string>; + /** The size of the largest dimension of the generated image. + Supported sizes are 1K and 2K (not supported for Imagen 3 models). */ + imageSize?: string; + /** Whether to use the prompt rewriting logic. */ + enhancePrompt?: boolean; +} + +/** The parameters for generating images. */ +export declare interface GenerateImagesParameters { + /** ID of the model to use. For a list of models, see `Google models + <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */ + model: string; + /** Text prompt that typically describes the images to output. + */ + prompt: string; + /** Configuration for generating images. + */ + config?: GenerateImagesConfig; +} + +/** The output images response. */ +export declare class GenerateImagesResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** List of generated images. */ + generatedImages?: GeneratedImage[]; + /** Safety attributes of the positive prompt. Only populated if + ``include_safety_attributes`` is set to True. */ + positivePromptSafetyAttributes?: SafetyAttributes; +} + +/** Configuration for generating videos. */ +export declare interface GenerateVideosConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** Number of output videos. */ + numberOfVideos?: number; + /** The gcs bucket where to save the generated videos. */ + outputGcsUri?: string; + /** Frames per second for video generation. */ + fps?: number; + /** Duration of the clip for video generation in seconds. */ + durationSeconds?: number; + /** The RNG seed. If RNG seed is exactly same for each request with + unchanged inputs, the prediction results will be consistent. Otherwise, + a random RNG seed will be used each time to produce a different + result. */ + seed?: number; + /** The aspect ratio for the generated video. 16:9 (landscape) and + 9:16 (portrait) are supported. */ + aspectRatio?: string; + /** The resolution for the generated video. 720p and 1080p are + supported. */ + resolution?: string; + /** Whether allow to generate person videos, and restrict to specific + ages. Supported values are: dont_allow, allow_adult. */ + personGeneration?: string; + /** The pubsub topic where to publish the video generation + progress. */ + pubsubTopic?: string; + /** Explicitly state what should not be included in the generated + videos. */ + negativePrompt?: string; + /** Whether to use the prompt rewriting logic. */ + enhancePrompt?: boolean; + /** Whether to generate audio along with the video. */ + generateAudio?: boolean; + /** Image to use as the last frame of generated videos. + Only supported for image to video use cases. */ + lastFrame?: Image_2; + /** The images to use as the references to generate the videos. + If this field is provided, the text prompt field must also be provided. + The image, video, or last_frame field are not supported. Each image must + be associated with a type. Veo 2 supports up to 3 asset images *or* 1 + style image. */ + referenceImages?: VideoGenerationReferenceImage[]; + /** The mask to use for generating videos. */ + mask?: VideoGenerationMask; + /** Compression quality of the generated videos. */ + compressionQuality?: VideoCompressionQuality; +} + +/** A video generation operation. */ +export declare class GenerateVideosOperation implements Operation<GenerateVideosResponse> { + /** The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`. */ + name?: string; + /** Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata. Any method that returns a long-running operation should document the metadata type, if any. */ + metadata?: Record<string, unknown>; + /** If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available. */ + done?: boolean; + /** The error result of the operation in case of failure or cancellation. */ + error?: Record<string, unknown>; + /** The generated videos. */ + response?: GenerateVideosResponse; + /** + * Instantiates an Operation of the same type as the one being called with the fields set from the API response. + * @internal + */ + _fromAPIResponse({ apiResponse, _isVertexAI, }: OperationFromAPIResponseParameters): Operation<GenerateVideosResponse>; + /** The full HTTP response. */ + sdkHttpResponse?: HttpResponse; +} + +/** Class that represents the parameters for generating videos. */ +export declare interface GenerateVideosParameters { + /** ID of the model to use. For a list of models, see `Google models + <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */ + model: string; + /** The text prompt for generating the videos. + Optional if image or video is provided. */ + prompt?: string; + /** The input image for generating the videos. + Optional if prompt is provided. Not allowed if video is provided. */ + image?: Image_2; + /** The input video for video extension use cases. + Optional if prompt is provided. Not allowed if image is provided. */ + video?: Video; + /** A set of source input(s) for video generation. */ + source?: GenerateVideosSource; + /** Configuration for generating videos. */ + config?: GenerateVideosConfig; +} + +/** Response with generated videos. */ +export declare class GenerateVideosResponse { + /** List of the generated videos */ + generatedVideos?: GeneratedVideo[]; + /** Returns if any videos were filtered due to RAI policies. */ + raiMediaFilteredCount?: number; + /** Returns rai failure reasons if any. */ + raiMediaFilteredReasons?: string[]; +} + +/** A set of source input(s) for video generation. */ +export declare interface GenerateVideosSource { + /** The text prompt for generating the videos. + Optional if image or video is provided. */ + prompt?: string; + /** The input image for generating the videos. + Optional if prompt is provided. Not allowed if video is provided. */ + image?: Image_2; + /** The input video for video extension use cases. + Optional if prompt is provided. Not allowed if image is provided. */ + video?: Video; +} + +/** Generation config. */ +export declare interface GenerationConfig { + /** Optional. Config for model selection. */ + modelSelectionConfig?: ModelSelectionConfig; + /** Output schema of the generated response. This is an alternative to + `response_schema` that accepts [JSON Schema](https://json-schema.org/). + */ + responseJsonSchema?: unknown; + /** Optional. If enabled, audio timestamp will be included in the request to the model. This field is not supported in Gemini API. */ + audioTimestamp?: boolean; + /** Optional. Number of candidates to generate. */ + candidateCount?: number; + /** Optional. If enabled, the model will detect emotions and adapt its responses accordingly. This field is not supported in Gemini API. */ + enableAffectiveDialog?: boolean; + /** Optional. Frequency penalties. */ + frequencyPenalty?: number; + /** Optional. Logit probabilities. */ + logprobs?: number; + /** Optional. The maximum number of output tokens to generate per message. */ + maxOutputTokens?: number; + /** Optional. If specified, the media resolution specified will be used. */ + mediaResolution?: MediaResolution; + /** Optional. Positive penalties. */ + presencePenalty?: number; + /** Optional. If true, export the logprobs results in response. */ + responseLogprobs?: boolean; + /** Optional. Output response mimetype of the generated candidate text. Supported mimetype: - `text/plain`: (default) Text output. - `application/json`: JSON response in the candidates. The model needs to be prompted to output the appropriate response type, otherwise the behavior is undefined. This is a preview feature. */ + responseMimeType?: string; + /** Optional. The modalities of the response. */ + responseModalities?: Modality[]; + /** Optional. The `Schema` object allows the definition of input and output data types. These types can be objects, but also primitives and arrays. Represents a select subset of an [OpenAPI 3.0 schema object](https://spec.openapis.org/oas/v3.0.3#schema). If set, a compatible response_mime_type must also be set. Compatible mimetypes: `application/json`: Schema for JSON response. */ + responseSchema?: Schema; + /** Optional. Routing configuration. This field is not supported in Gemini API. */ + routingConfig?: GenerationConfigRoutingConfig; + /** Optional. Seed. */ + seed?: number; + /** Optional. The speech generation config. */ + speechConfig?: SpeechConfig; + /** Optional. Stop sequences. */ + stopSequences?: string[]; + /** Optional. Controls the randomness of predictions. */ + temperature?: number; + /** Optional. Config for thinking features. An error will be returned if this field is set for models that don't support thinking. */ + thinkingConfig?: ThinkingConfig; + /** Optional. If specified, top-k sampling will be used. */ + topK?: number; + /** Optional. If specified, nucleus sampling will be used. */ + topP?: number; + /** Optional. Enables enhanced civic answers. It may not be available for all models. This field is not supported in Vertex AI. */ + enableEnhancedCivicAnswers?: boolean; +} + +/** + * Configuration parameters for model interactions. + */ +declare interface GenerationConfig_2 { + /** + * Configuration for image interaction. + */ + image_config?: ImageConfig_2; + /** + * The maximum number of tokens to include in the response. + */ + max_output_tokens?: number; + /** + * Seed used in decoding for reproducibility. + */ + seed?: number; + /** + * Configuration for speech interaction. + */ + speech_config?: Array<SpeechConfig_2>; + /** + * A list of character sequences that will stop output interaction. + */ + stop_sequences?: Array<string>; + /** + * Controls the randomness of the output. + */ + temperature?: number; + /** + * The level of thought tokens that the model should generate. + */ + thinking_level?: ThinkingLevel_2; + /** + * Whether to include thought summaries in the response. + */ + thinking_summaries?: 'auto' | 'none'; + /** + * The tool choice for the interaction. + */ + tool_choice?: ToolChoice; + /** + * The maximum cumulative probability of tokens to consider when sampling. + */ + top_p?: number; +} + +/** The configuration for routing the request to a specific model. This data type is not supported in Gemini API. */ +export declare interface GenerationConfigRoutingConfig { + /** Automated routing. */ + autoMode?: GenerationConfigRoutingConfigAutoRoutingMode; + /** Manual routing. */ + manualMode?: GenerationConfigRoutingConfigManualRoutingMode; +} + +/** When automated routing is specified, the routing will be determined by the pretrained routing model and customer provided model routing preference. This data type is not supported in Gemini API. */ +export declare interface GenerationConfigRoutingConfigAutoRoutingMode { + /** The model routing preference. */ + modelRoutingPreference?: 'UNKNOWN' | 'PRIORITIZE_QUALITY' | 'BALANCED' | 'PRIORITIZE_COST'; +} + +/** When manual routing is set, the specified model will be used directly. This data type is not supported in Gemini API. */ +export declare interface GenerationConfigRoutingConfigManualRoutingMode { + /** The model name to use. Only the public LLM models are accepted. See [Supported models](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference#supported-models). */ + modelName?: string; +} + +/** + * Config for thinking feature. + * + * @deprecated This interface will be deprecated. Please use `ThinkingConfig` instead. + */ +export declare interface GenerationConfigThinkingConfig extends ThinkingConfig { +} + +/** Optional parameters. */ +export declare interface GetBatchJobConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Config for batches.get parameters. */ +export declare interface GetBatchJobParameters { + /** A fully-qualified BatchJob resource name or ID. + Example: "projects/.../locations/.../batchPredictionJobs/456" + or "456" when project and location are initialized in the client. + */ + name: string; + /** Optional parameters for the request. */ + config?: GetBatchJobConfig; +} + +/** Optional parameters for caches.get method. */ +export declare interface GetCachedContentConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Parameters for caches.get method. */ +export declare interface GetCachedContentParameters { + /** The server-generated resource name of the cached content. + */ + name: string; + /** Optional parameters for the request. + */ + config?: GetCachedContentConfig; +} + +/** Optional Config. */ +export declare interface GetDocumentConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Parameters for documents.get. */ +export declare interface GetDocumentParameters { + /** The resource name of the Document. + Example: fileSearchStores/file-search-store-foo/documents/documents-bar */ + name: string; + /** Optional parameters for the request. */ + config?: GetDocumentConfig; +} + +/** Used to override the default configuration. */ +export declare interface GetFileConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Generates the parameters for the get method. */ +export declare interface GetFileParameters { + /** The name identifier for the file to retrieve. */ + name: string; + /** Used to override the default configuration. */ + config?: GetFileConfig; +} + +/** Optional parameters for getting a FileSearchStore. */ +export declare interface GetFileSearchStoreConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Config for file_search_stores.get parameters. */ +export declare interface GetFileSearchStoreParameters { + /** The resource name of the FileSearchStore. Example: `fileSearchStores/my-file-search-store-123` */ + name: string; + /** Optional parameters for the request. */ + config?: GetFileSearchStoreConfig; +} + +/** Optional parameters for models.get method. */ +export declare interface GetModelConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +export declare interface GetModelParameters { + model: string; + /** Optional parameters for the request. */ + config?: GetModelConfig; +} + +export declare interface GetOperationConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Parameters for the GET method. */ +export declare interface GetOperationParameters { + /** The server-assigned name for the operation. */ + operationName: string; + /** Used to override the default configuration. */ + config?: GetOperationConfig; +} + +/** Optional parameters for tunings.get method. */ +export declare interface GetTuningJobConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Parameters for the get method. */ +export declare interface GetTuningJobParameters { + name: string; + /** Optional parameters for the request. */ + config?: GetTuningJobConfig; +} + +/** + * The Google GenAI SDK. + * + * @remarks + * Provides access to the GenAI features through either the {@link + * https://cloud.google.com/vertex-ai/docs/reference/rest | Gemini API} or + * the {@link https://cloud.google.com/vertex-ai/docs/reference/rest | Vertex AI + * API}. + * + * The {@link GoogleGenAIOptions.vertexai} value determines which of the API + * services to use. + * + * When using the Gemini API, a {@link GoogleGenAIOptions.apiKey} must also be + * set. When using Vertex AI, currently only {@link GoogleGenAIOptions.apiKey} + * is supported via Express mode. {@link GoogleGenAIOptions.project} and {@link + * GoogleGenAIOptions.location} should not be set. + * + * @example + * Initializing the SDK for using the Gemini API: + * ```ts + * import {GoogleGenAI} from '@google/genai'; + * const ai = new GoogleGenAI({apiKey: 'GEMINI_API_KEY'}); + * ``` + * + * @example + * Initializing the SDK for using the Vertex AI API: + * ```ts + * import {GoogleGenAI} from '@google/genai'; + * const ai = new GoogleGenAI({ + * vertexai: true, + * project: 'PROJECT_ID', + * location: 'PROJECT_LOCATION' + * }); + * ``` + * + */ +export declare class GoogleGenAI { + protected readonly apiClient: ApiClient; + private readonly apiKey?; + readonly vertexai: boolean; + private readonly apiVersion?; + private readonly httpOptions?; + readonly models: Models; + readonly live: Live; + readonly batches: Batches; + readonly chats: Chats; + readonly caches: Caches; + readonly files: Files; + readonly operations: Operations; + readonly authTokens: Tokens; + readonly tunings: Tunings; + readonly fileSearchStores: FileSearchStores; + private _interactions; + get interactions(): Interactions; + constructor(options: GoogleGenAIOptions); +} + +/** + * Google Gen AI SDK's configuration options. + * + * See {@link GoogleGenAI} for usage samples. + */ +export declare interface GoogleGenAIOptions { + /** + * Optional. Determines whether to use the Vertex AI or the Gemini API. + * + * @remarks + * When true, the {@link https://cloud.google.com/vertex-ai/docs/reference/rest | Vertex AI API} will used. + * When false, the {@link https://ai.google.dev/api | Gemini API} will be used. + * + * If unset, default SDK behavior is to use the Gemini API service. + */ + vertexai?: boolean; + /** + * Optional. The Google Cloud project ID for Vertex AI clients. + * + * Find your project ID: https://cloud.google.com/resource-manager/docs/creating-managing-projects#identifying_projects + * + * @remarks + * Only supported on Node runtimes, ignored on browser runtimes. + */ + project?: string; + /** + * Optional. The Google Cloud project {@link https://cloud.google.com/vertex-ai/generative-ai/docs/learn/locations | location} for Vertex AI clients. + * + * @remarks + * Only supported on Node runtimes, ignored on browser runtimes. + * + */ + location?: string; + /** + * The API Key, required for Gemini API clients. + * + * @remarks + * Required on browser runtimes. + */ + apiKey?: string; + /** + * Optional. The API version to use. + * + * @remarks + * If unset, the default API version will be used. + */ + apiVersion?: string; + /** + * Optional. Authentication options defined by the by google-auth-library for Vertex AI clients. + * + * @remarks + * @see {@link https://github.com/googleapis/google-auth-library-nodejs/blob/v9.15.0/src/auth/googleauth.ts | GoogleAuthOptions interface in google-auth-library-nodejs}. + * + * Only supported on Node runtimes, ignored on browser runtimes. + * + */ + googleAuthOptions?: GoogleAuthOptions; + /** + * Optional. A set of customizable configuration for HTTP requests. + */ + httpOptions?: HttpOptions; +} + +/** Tool to retrieve public maps data for grounding, powered by Google. */ +export declare interface GoogleMaps { + /** The authentication config to access the API. Only API key is supported. This field is not supported in Gemini API. */ + authConfig?: AuthConfig; + /** Optional. If true, include the widget context token in the response. */ + enableWidget?: boolean; +} + +/** The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors). This data type is not supported in Gemini API. */ +export declare interface GoogleRpcStatus { + /** The status code, which should be an enum value of google.rpc.Code. */ + code?: number; + /** A list of messages that carry the error details. There is a common set of message types for APIs to use. */ + details?: Record<string, unknown>[]; + /** A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the google.rpc.Status.details field, or localized by the client. */ + message?: string; +} + +/** GoogleSearch tool type. Tool to support Google Search in Model. Powered by Google. */ +export declare interface GoogleSearch { + /** Optional. List of domains to be excluded from the search results. The default limit is 2000 domains. Example: ["amazon.com", "facebook.com"]. This field is not supported in Gemini API. */ + excludeDomains?: string[]; + /** Optional. Sites with confidence level chosen & above this value will be blocked from the search results. This field is not supported in Gemini API. */ + blockingConfidence?: PhishBlockThreshold; + /** Optional. Filter search results to a specific time range. If customers set a start time, they must set an end time (and vice versa). This field is not supported in Vertex AI. */ + timeRangeFilter?: Interval; +} + +/** + * The arguments to pass to Google Search. + */ +declare interface GoogleSearchCallArguments { + /** + * Web search queries for the following-up web search. + */ + queries?: Array<string>; +} + +/** + * Google Search content. + */ +declare interface GoogleSearchCallContent { + type: 'google_search_call'; + /** + * A unique ID for this specific tool call. + */ + id?: string; + /** + * The arguments to pass to Google Search. + */ + arguments?: GoogleSearchCallArguments; +} + +/** + * The result of the Google Search. + */ +declare interface GoogleSearchResult { + /** + * Web content snippet that can be embedded in a web page or an app webview. + */ + rendered_content?: string; + /** + * Title of the search result. + */ + title?: string; + /** + * URI reference of the search result. + */ + url?: string; +} + +/** + * Google Search result content. + */ +declare interface GoogleSearchResultContent { + type: 'google_search_result'; + /** + * ID to match the ID from the google search call block. + */ + call_id?: string; + /** + * Whether the Google Search resulted in an error. + */ + is_error?: boolean; + /** + * The results of the Google Search. + */ + result?: Array<GoogleSearchResult>; + /** + * The signature of the Google Search result. + */ + signature?: string; +} + +/** Tool to retrieve public web data for grounding, powered by Google. */ +export declare interface GoogleSearchRetrieval { + /** Specifies the dynamic retrieval configuration for the given source. */ + dynamicRetrievalConfig?: DynamicRetrievalConfig; +} + +/** Represents a whole or partial calendar date, such as a birthday. The time of day and time zone are either specified elsewhere or are insignificant. The date is relative to the Gregorian Calendar. This can represent one of the following: * A full date, with non-zero year, month, and day values. * A month and day, with a zero year (for example, an anniversary). * A year on its own, with a zero month and a zero day. * A year and month, with a zero day (for example, a credit card expiration date). Related types: * google.type.TimeOfDay * google.type.DateTime * google.protobuf.Timestamp. This data type is not supported in Gemini API. */ +export declare interface GoogleTypeDate { + /** Day of a month. Must be from 1 to 31 and valid for the year and month, or 0 to specify a year by itself or a year and month where the day isn't significant. */ + day?: number; + /** Month of a year. Must be from 1 to 12, or 0 to specify a year without a month and day. */ + month?: number; + /** Year of the date. Must be from 1 to 9999, or 0 to specify a date without a year. */ + year?: number; +} + +/** Grounding chunk. */ +export declare interface GroundingChunk { + /** Grounding chunk from Google Maps. This field is not supported in Gemini API. */ + maps?: GroundingChunkMaps; + /** Grounding chunk from context retrieved by the retrieval tools. This field is not supported in Gemini API. */ + retrievedContext?: GroundingChunkRetrievedContext; + /** Grounding chunk from the web. */ + web?: GroundingChunkWeb; +} + +/** Chunk from Google Maps. This data type is not supported in Gemini API. */ +export declare interface GroundingChunkMaps { + /** Sources used to generate the place answer. This includes review snippets and photos that were used to generate the answer, as well as uris to flag content. */ + placeAnswerSources?: GroundingChunkMapsPlaceAnswerSources; + /** This Place's resource name, in `places/{place_id}` format. Can be used to look up the Place. */ + placeId?: string; + /** Text of the place answer. */ + text?: string; + /** Title of the place. */ + title?: string; + /** URI reference of the place. */ + uri?: string; +} + +/** Sources used to generate the place answer. This data type is not supported in Gemini API. */ +export declare interface GroundingChunkMapsPlaceAnswerSources { + /** A link where users can flag a problem with the generated answer. */ + flagContentUri?: string; + /** Snippets of reviews that are used to generate the answer. */ + reviewSnippets?: GroundingChunkMapsPlaceAnswerSourcesReviewSnippet[]; +} + +/** Author attribution for a photo or review. This data type is not supported in Gemini API. */ +export declare interface GroundingChunkMapsPlaceAnswerSourcesAuthorAttribution { + /** Name of the author of the Photo or Review. */ + displayName?: string; + /** Profile photo URI of the author of the Photo or Review. */ + photoUri?: string; + /** URI of the author of the Photo or Review. */ + uri?: string; +} + +/** Encapsulates a review snippet. This data type is not supported in Gemini API. */ +export declare interface GroundingChunkMapsPlaceAnswerSourcesReviewSnippet { + /** This review's author. */ + authorAttribution?: GroundingChunkMapsPlaceAnswerSourcesAuthorAttribution; + /** A link where users can flag a problem with the review. */ + flagContentUri?: string; + /** A link to show the review on Google Maps. */ + googleMapsUri?: string; + /** A string of formatted recent time, expressing the review time relative to the current time in a form appropriate for the language and country. */ + relativePublishTimeDescription?: string; + /** A reference representing this place review which may be used to look up this place review again. */ + review?: string; + /** Id of the review referencing the place. */ + reviewId?: string; + /** Title of the review. */ + title?: string; +} + +/** Chunk from context retrieved by the retrieval tools. This data type is not supported in Gemini API. */ +export declare interface GroundingChunkRetrievedContext { + /** Output only. The full document name for the referenced Vertex AI Search document. */ + documentName?: string; + /** Additional context for the RAG retrieval result. This is only populated when using the RAG retrieval tool. */ + ragChunk?: RagChunk; + /** Text of the attribution. */ + text?: string; + /** Title of the attribution. */ + title?: string; + /** URI reference of the attribution. */ + uri?: string; +} + +/** Chunk from the web. */ +export declare interface GroundingChunkWeb { + /** Domain of the (original) URI. This field is not supported in Gemini API. */ + domain?: string; + /** Title of the chunk. */ + title?: string; + /** URI reference of the chunk. */ + uri?: string; +} + +/** Metadata returned to client when grounding is enabled. */ +export declare interface GroundingMetadata { + /** Optional. Output only. Resource name of the Google Maps widget context token to be used with the PlacesContextElement widget to render contextual data. This is populated only for Google Maps grounding. This field is not supported in Gemini API. */ + googleMapsWidgetContextToken?: string; + /** List of supporting references retrieved from specified grounding source. */ + groundingChunks?: GroundingChunk[]; + /** Optional. List of grounding support. */ + groundingSupports?: GroundingSupport[]; + /** Optional. Output only. Retrieval metadata. */ + retrievalMetadata?: RetrievalMetadata; + /** Optional. Queries executed by the retrieval tools. This field is not supported in Gemini API. */ + retrievalQueries?: string[]; + /** Optional. Google search entry for the following-up web searches. */ + searchEntryPoint?: SearchEntryPoint; + /** Optional. Output only. List of source flagging uris. This is currently populated only for Google Maps grounding. This field is not supported in Gemini API. */ + sourceFlaggingUris?: GroundingMetadataSourceFlaggingUri[]; + /** Optional. Web search queries for the following-up web search. */ + webSearchQueries?: string[]; +} + +/** Source content flagging uri for a place or review. This is currently populated only for Google Maps grounding. This data type is not supported in Gemini API. */ +export declare interface GroundingMetadataSourceFlaggingUri { + /** A link where users can flag a problem with the source (place or review). */ + flagContentUri?: string; + /** Id of the place or review. */ + sourceId?: string; +} + +/** Grounding support. */ +export declare interface GroundingSupport { + /** Confidence score of the support references. Ranges from 0 to 1. 1 is the most confident. For Gemini 2.0 and before, this list must have the same size as the grounding_chunk_indices. For Gemini 2.5 and after, this list will be empty and should be ignored. */ + confidenceScores?: number[]; + /** A list of indices (into 'grounding_chunk') specifying the citations associated with the claim. For instance [1,3,4] means that grounding_chunk[1], grounding_chunk[3], grounding_chunk[4] are the retrieved content attributed to the claim. */ + groundingChunkIndices?: number[]; + /** Segment of the content this support belongs to. */ + segment?: Segment; +} + +/** Specify if the threshold is used for probability or severity score. If not specified, the threshold is used for probability score. This enum is not supported in Gemini API. */ +export declare enum HarmBlockMethod { + /** + * The harm block method is unspecified. + */ + HARM_BLOCK_METHOD_UNSPECIFIED = "HARM_BLOCK_METHOD_UNSPECIFIED", + /** + * The harm block method uses both probability and severity scores. + */ + SEVERITY = "SEVERITY", + /** + * The harm block method uses the probability score. + */ + PROBABILITY = "PROBABILITY" +} + +/** The harm block threshold. */ +export declare enum HarmBlockThreshold { + /** + * Unspecified harm block threshold. + */ + HARM_BLOCK_THRESHOLD_UNSPECIFIED = "HARM_BLOCK_THRESHOLD_UNSPECIFIED", + /** + * Block low threshold and above (i.e. block more). + */ + BLOCK_LOW_AND_ABOVE = "BLOCK_LOW_AND_ABOVE", + /** + * Block medium threshold and above. + */ + BLOCK_MEDIUM_AND_ABOVE = "BLOCK_MEDIUM_AND_ABOVE", + /** + * Block only high threshold (i.e. block less). + */ + BLOCK_ONLY_HIGH = "BLOCK_ONLY_HIGH", + /** + * Block none. + */ + BLOCK_NONE = "BLOCK_NONE", + /** + * Turn off the safety filter. + */ + OFF = "OFF" +} + +/** Harm category. */ +export declare enum HarmCategory { + /** + * The harm category is unspecified. + */ + HARM_CATEGORY_UNSPECIFIED = "HARM_CATEGORY_UNSPECIFIED", + /** + * The harm category is harassment. + */ + HARM_CATEGORY_HARASSMENT = "HARM_CATEGORY_HARASSMENT", + /** + * The harm category is hate speech. + */ + HARM_CATEGORY_HATE_SPEECH = "HARM_CATEGORY_HATE_SPEECH", + /** + * The harm category is sexually explicit content. + */ + HARM_CATEGORY_SEXUALLY_EXPLICIT = "HARM_CATEGORY_SEXUALLY_EXPLICIT", + /** + * The harm category is dangerous content. + */ + HARM_CATEGORY_DANGEROUS_CONTENT = "HARM_CATEGORY_DANGEROUS_CONTENT", + /** + * Deprecated: Election filter is not longer supported. The harm category is civic integrity. + */ + HARM_CATEGORY_CIVIC_INTEGRITY = "HARM_CATEGORY_CIVIC_INTEGRITY", + /** + * The harm category is image hate. This enum value is not supported in Gemini API. + */ + HARM_CATEGORY_IMAGE_HATE = "HARM_CATEGORY_IMAGE_HATE", + /** + * The harm category is image dangerous content. This enum value is not supported in Gemini API. + */ + HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT = "HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT", + /** + * The harm category is image harassment. This enum value is not supported in Gemini API. + */ + HARM_CATEGORY_IMAGE_HARASSMENT = "HARM_CATEGORY_IMAGE_HARASSMENT", + /** + * The harm category is image sexually explicit content. This enum value is not supported in Gemini API. + */ + HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT = "HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT", + /** + * The harm category is for jailbreak prompts. This enum value is not supported in Gemini API. + */ + HARM_CATEGORY_JAILBREAK = "HARM_CATEGORY_JAILBREAK" +} + +/** Output only. Harm probability levels in the content. */ +export declare enum HarmProbability { + /** + * Harm probability unspecified. + */ + HARM_PROBABILITY_UNSPECIFIED = "HARM_PROBABILITY_UNSPECIFIED", + /** + * Negligible level of harm. + */ + NEGLIGIBLE = "NEGLIGIBLE", + /** + * Low level of harm. + */ + LOW = "LOW", + /** + * Medium level of harm. + */ + MEDIUM = "MEDIUM", + /** + * High level of harm. + */ + HIGH = "HIGH" +} + +/** Output only. Harm severity levels in the content. This enum is not supported in Gemini API. */ +export declare enum HarmSeverity { + /** + * Harm severity unspecified. + */ + HARM_SEVERITY_UNSPECIFIED = "HARM_SEVERITY_UNSPECIFIED", + /** + * Negligible level of harm severity. + */ + HARM_SEVERITY_NEGLIGIBLE = "HARM_SEVERITY_NEGLIGIBLE", + /** + * Low level of harm severity. + */ + HARM_SEVERITY_LOW = "HARM_SEVERITY_LOW", + /** + * Medium level of harm severity. + */ + HARM_SEVERITY_MEDIUM = "HARM_SEVERITY_MEDIUM", + /** + * High level of harm severity. + */ + HARM_SEVERITY_HIGH = "HARM_SEVERITY_HIGH" +} + +declare type HeadersLike = Headers | readonly HeaderValue[][] | Record<string, HeaderValue | readonly HeaderValue[]> | undefined | null | NullableHeaders; + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +declare type HeaderValue = string | undefined | null; + +/** The location of the API key. This enum is not supported in Gemini API. */ +export declare enum HttpElementLocation { + HTTP_IN_UNSPECIFIED = "HTTP_IN_UNSPECIFIED", + /** + * Element is in the HTTP request query. + */ + HTTP_IN_QUERY = "HTTP_IN_QUERY", + /** + * Element is in the HTTP request header. + */ + HTTP_IN_HEADER = "HTTP_IN_HEADER", + /** + * Element is in the HTTP request path. + */ + HTTP_IN_PATH = "HTTP_IN_PATH", + /** + * Element is in the HTTP request body. + */ + HTTP_IN_BODY = "HTTP_IN_BODY", + /** + * Element is in the HTTP request cookie. + */ + HTTP_IN_COOKIE = "HTTP_IN_COOKIE" +} + +declare type HTTPMethod = 'get' | 'post' | 'put' | 'patch' | 'delete'; + +/** HTTP options to be used in each of the requests. */ +export declare interface HttpOptions { + /** The base URL for the AI platform service endpoint. */ + baseUrl?: string; + /** The resource scope used to constructing the resource name when base_url is set */ + baseUrlResourceScope?: ResourceScope; + /** Specifies the version of the API to use. */ + apiVersion?: string; + /** Additional HTTP headers to be sent with the request. */ + headers?: Record<string, string>; + /** Timeout for the request in milliseconds. */ + timeout?: number; + /** Extra parameters to add to the request body. + The structure must match the backend API's request structure. + - VertexAI backend API docs: https://cloud.google.com/vertex-ai/docs/reference/rest + - GeminiAPI backend API docs: https://ai.google.dev/api/rest */ + extraBody?: Record<string, unknown>; + /** HTTP retry options for the request. */ + retryOptions?: HttpRetryOptions; +} + +/** + * Represents the necessary information to send a request to an API endpoint. + * This interface defines the structure for constructing and executing HTTP + * requests. + */ +declare interface HttpRequest { + /** + * URL path from the modules, this path is appended to the base API URL to + * form the complete request URL. + * + * If you wish to set full URL, use httpOptions.baseUrl instead. Example to + * set full URL in the request: + * + * const request: HttpRequest = { + * path: '', + * httpOptions: { + * baseUrl: 'https://<custom-full-url>', + * apiVersion: '', + * }, + * httpMethod: 'GET', + * }; + * + * The result URL will be: https://<custom-full-url> + * + */ + path: string; + /** + * Optional query parameters to be appended to the request URL. + */ + queryParams?: Record<string, string>; + /** + * Optional request body in json string or Blob format, GET request doesn't + * need a request body. + */ + body?: string | Blob; + /** + * The HTTP method to be used for the request. + */ + httpMethod: 'GET' | 'POST' | 'PATCH' | 'DELETE'; + /** + * Optional set of customizable configuration for HTTP requests. + */ + httpOptions?: types.HttpOptions; + /** + * Optional abort signal which can be used to cancel the request. + */ + abortSignal?: AbortSignal; +} + +/** A wrapper class for the http response. */ +export declare class HttpResponse { + /** Used to retain the processed HTTP headers in the response. */ + headers?: Record<string, string>; + /** + * The original http response. + */ + responseInternal: Response; + constructor(response: Response); + json(): Promise<unknown>; +} + +/** HTTP retry options to be used in each of the requests. */ +export declare interface HttpRetryOptions { + /** Maximum number of attempts, including the original request. + If 0 or 1, it means no retries. If not specified, default to 5. */ + attempts?: number; +} + +/** An image. */ +declare interface Image_2 { + /** The Cloud Storage URI of the image. ``Image`` can contain a value + for this field or the ``image_bytes`` field but not both. */ + gcsUri?: string; + /** The image bytes data. ``Image`` can contain a value for this field + or the ``gcs_uri`` field but not both. + * @remarks Encoded as base64 string. */ + imageBytes?: string; + /** The MIME type of the image. */ + mimeType?: string; +} +export { Image_2 as Image } + +/** The image generation configuration to be used in GenerateContentConfig. */ +export declare interface ImageConfig { + /** Aspect ratio of the generated images. Supported values are + "1:1", "2:3", "3:2", "3:4", "4:3", "9:16", "16:9", and "21:9". */ + aspectRatio?: string; + /** Optional. Specifies the size of generated images. Supported + values are `1K`, `2K`, `4K`. If not specified, the model will use default + value `1K`. */ + imageSize?: string; + /** Controls the generation of people. Supported values are: + ALLOW_ALL, ALLOW_ADULT, ALLOW_NONE. */ + personGeneration?: string; + /** MIME type of the generated image. This field is not + supported in Gemini API. */ + outputMimeType?: string; + /** Compression quality of the generated image (for + ``image/jpeg`` only). This field is not supported in Gemini API. */ + outputCompressionQuality?: number; +} + +/** + * The configuration for image interaction. + */ +declare interface ImageConfig_2 { + aspect_ratio?: '1:1' | '2:3' | '3:2' | '3:4' | '4:3' | '4:5' | '5:4' | '9:16' | '16:9' | '21:9'; + image_size?: '1K' | '2K' | '4K'; +} + +/** + * An image content block. + */ +declare interface ImageContent { + type: 'image'; + /** + * The image content. + */ + data?: string; + /** + * The mime type of the image. + */ + mime_type?: ImageMimeType; + /** + * The resolution of the media. + */ + resolution?: 'low' | 'medium' | 'high' | 'ultra_high'; + /** + * The URI of the image. + */ + uri?: string; +} + +/** + * The mime type of the image. + */ +declare type ImageMimeType = 'image/png' | 'image/jpeg' | 'image/webp' | 'image/heic' | 'image/heif' | (string & {}); + +/** Enum that specifies the language of the text in the prompt. */ +export declare enum ImagePromptLanguage { + /** + * Auto-detect the language. + */ + auto = "auto", + /** + * English + */ + en = "en", + /** + * Japanese + */ + ja = "ja", + /** + * Korean + */ + ko = "ko", + /** + * Hindi + */ + hi = "hi", + /** + * Chinese + */ + zh = "zh", + /** + * Portuguese + */ + pt = "pt", + /** + * Spanish + */ + es = "es" +} + +/** Optional parameters for importing a file. */ +export declare interface ImportFileConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** User provided custom metadata stored as key-value pairs used for querying. */ + customMetadata?: CustomMetadata[]; + /** Config for telling the service how to chunk the file. */ + chunkingConfig?: ChunkingConfig; +} + +/** Long-running operation for importing a file to a FileSearchStore. */ +export declare class ImportFileOperation implements Operation<ImportFileResponse> { + /** The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`. */ + name?: string; + /** Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata. Any method that returns a long-running operation should document the metadata type, if any. */ + metadata?: Record<string, unknown>; + /** If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available. */ + done?: boolean; + /** The error result of the operation in case of failure or cancellation. */ + error?: Record<string, unknown>; + /** The result of the ImportFile operation, available when the operation is done. */ + response?: ImportFileResponse; + /** + * Instantiates an Operation of the same type as the one being called with the fields set from the API response. + * @internal + */ + _fromAPIResponse({ apiResponse, _isVertexAI, }: OperationFromAPIResponseParameters): Operation<ImportFileResponse>; + /** The full HTTP response. */ + sdkHttpResponse?: HttpResponse; +} + +/** Config for file_search_stores.import_file parameters. */ +export declare interface ImportFileParameters { + /** The resource name of the FileSearchStore. Example: `fileSearchStores/my-file-search-store-123` */ + fileSearchStoreName: string; + /** The name of the File API File to import. Example: `files/abc-123` */ + fileName: string; + /** Optional parameters for the request. */ + config?: ImportFileConfig; +} + +/** Response for ImportFile to import a File API file with a file search store. */ +export declare class ImportFileResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** The name of the FileSearchStore containing Documents. */ + parent?: string; + /** The identifier for the Document imported. */ + documentName?: string; +} + +/** Config for `inlined_embedding_responses` parameter. */ +export declare class InlinedEmbedContentResponse { + /** The response to the request. + */ + response?: SingleEmbedContentResponse; + /** The error encountered while processing the request. + */ + error?: JobError; +} + +/** Config for inlined request. */ +export declare interface InlinedRequest { + /** ID of the model to use. For a list of models, see `Google models + <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */ + model?: string; + /** Content of the request. + */ + contents?: ContentListUnion; + /** The metadata to be associated with the request. */ + metadata?: Record<string, string>; + /** Configuration that contains optional model parameters. + */ + config?: GenerateContentConfig; +} + +/** Config for `inlined_responses` parameter. */ +export declare class InlinedResponse { + /** The response to the request. + */ + response?: GenerateContentResponse; + /** The metadata to be associated with the request. */ + metadata?: Record<string, string>; + /** The error encountered while processing the request. + */ + error?: JobError; +} + +/** + * The Interaction resource. + */ +declare interface Interaction { + /** + * Output only. A unique identifier for the interaction completion. + */ + id: string; + /** + * Output only. The status of the interaction. + */ + status: 'in_progress' | 'requires_action' | 'completed' | 'failed' | 'cancelled' | 'incomplete'; + /** + * The name of the `Agent` used for generating the interaction. + */ + agent?: (string & {}) | 'deep-research-pro-preview-12-2025'; + /** + * Output only. The time at which the response was created in ISO 8601 format + * (YYYY-MM-DDThh:mm:ssZ). + */ + created?: string; + /** + * The name of the `Model` used for generating the interaction. + */ + model?: Model_2; + /** + * Output only. Responses from the model. + */ + outputs?: Array<Content_2>; + /** + * The ID of the previous interaction, if any. + */ + previous_interaction_id?: string; + /** + * Output only. The role of the interaction. + */ + role?: string; + /** + * Output only. The time at which the response was last updated in ISO 8601 format + * (YYYY-MM-DDThh:mm:ssZ). + */ + updated?: string; + /** + * Output only. Statistics on the interaction request's token usage. + */ + usage?: Usage; +} + +declare interface InteractionCancelParams { + /** + * Which version of the API to use. + */ + api_version?: string; +} + +declare interface InteractionCompleteEvent { + /** + * The event_id token to be used to resume the interaction stream, from this event. + */ + event_id?: string; + event_type?: 'interaction.complete'; + /** + * The Interaction resource. + */ + interaction?: Interaction; +} + +declare type InteractionCreateParams = CreateModelInteractionParamsNonStreaming | CreateModelInteractionParamsStreaming | CreateAgentInteractionParamsNonStreaming | CreateAgentInteractionParamsStreaming; + +declare interface InteractionDeleteParams { + /** + * Which version of the API to use. + */ + api_version?: string; +} + +declare type InteractionDeleteResponse = unknown; + +declare type InteractionGetParams = InteractionGetParamsNonStreaming | InteractionGetParamsStreaming; + +declare namespace InteractionGetParams { + type InteractionGetParamsNonStreaming = InteractionsAPI.InteractionGetParamsNonStreaming; + type InteractionGetParamsStreaming = InteractionsAPI.InteractionGetParamsStreaming; +} + +declare interface InteractionGetParamsBase { + /** + * Path param: Which version of the API to use. + */ + api_version?: string; + /** + * Query param: If set to true, includes the input in the response. + */ + include_input?: boolean; + /** + * Query param: Optional. If set, resumes the interaction stream from the next chunk after the event marked by the event id. Can only be used if `stream` is true. + */ + last_event_id?: string; + /** + * Query param: If set to true, the generated content will be streamed incrementally. + */ + stream?: boolean; +} + +declare interface InteractionGetParamsNonStreaming extends InteractionGetParamsBase { + /** + * Query param: If set to true, the generated content will be streamed incrementally. + */ + stream?: false; +} + +declare interface InteractionGetParamsStreaming extends InteractionGetParamsBase { + /** + * Query param: If set to true, the generated content will be streamed incrementally. + */ + stream: true; +} + +export declare class Interactions extends BaseInteractions { +} + +export declare namespace Interactions { + export { type AllowedTools as AllowedTools, type Annotation as Annotation, type AudioContent as AudioContent, type AudioMimeType as AudioMimeType, type CodeExecutionCallArguments as CodeExecutionCallArguments, type CodeExecutionCallContent as CodeExecutionCallContent, type CodeExecutionResultContent as CodeExecutionResultContent, type Content_2 as Content, type ContentDelta as ContentDelta, type ContentStart as ContentStart, type ContentStop as ContentStop, type DeepResearchAgentConfig as DeepResearchAgentConfig, type DocumentContent as DocumentContent, type DocumentMimeType as DocumentMimeType, type DynamicAgentConfig as DynamicAgentConfig, type ErrorEvent_2 as ErrorEvent, type FileSearchCallContent as FileSearchCallContent, type FileSearchResultContent as FileSearchResultContent, type Function_2 as Function, type FunctionCallContent as FunctionCallContent, type FunctionResultContent as FunctionResultContent, type GenerationConfig_2 as GenerationConfig, type GoogleSearchCallArguments as GoogleSearchCallArguments, type GoogleSearchCallContent as GoogleSearchCallContent, type GoogleSearchResult as GoogleSearchResult, type GoogleSearchResultContent as GoogleSearchResultContent, type ImageConfig_2 as ImageConfig, type ImageContent as ImageContent, type ImageMimeType as ImageMimeType, type Interaction as Interaction, type InteractionCompleteEvent as InteractionCompleteEvent, type InteractionSSEEvent as InteractionSSEEvent, type InteractionStartEvent as InteractionStartEvent, type InteractionStatusUpdate as InteractionStatusUpdate, type MCPServerToolCallContent as MCPServerToolCallContent, type MCPServerToolResultContent as MCPServerToolResultContent, type Model_2 as Model, type SpeechConfig_2 as SpeechConfig, type TextContent as TextContent, type ThinkingLevel_2 as ThinkingLevel, type ThoughtContent as ThoughtContent, type Tool_2 as Tool, type ToolChoice as ToolChoice, type ToolChoiceConfig as ToolChoiceConfig, type ToolChoiceType as ToolChoiceType, type Turn as Turn, type URLContextCallArguments as URLContextCallArguments, type URLContextCallContent as URLContextCallContent, type URLContextResult as URLContextResult, type URLContextResultContent as URLContextResultContent, type Usage as Usage, type VideoContent as VideoContent, type VideoMimeType as VideoMimeType, type InteractionDeleteResponse as InteractionDeleteResponse, type InteractionCreateParams as InteractionCreateParams, type CreateModelInteractionParamsNonStreaming as CreateModelInteractionParamsNonStreaming, type CreateModelInteractionParamsStreaming as CreateModelInteractionParamsStreaming, type CreateAgentInteractionParamsNonStreaming as CreateAgentInteractionParamsNonStreaming, type CreateAgentInteractionParamsStreaming as CreateAgentInteractionParamsStreaming, type InteractionDeleteParams as InteractionDeleteParams, type InteractionCancelParams as InteractionCancelParams, type InteractionGetParams as InteractionGetParams, type InteractionGetParamsNonStreaming as InteractionGetParamsNonStreaming, type InteractionGetParamsStreaming as InteractionGetParamsStreaming, }; +} + +declare namespace InteractionsAPI { + export { + BaseInteractions, + Interactions, + AllowedTools, + Annotation, + AudioContent, + AudioMimeType, + CodeExecutionCallArguments, + CodeExecutionCallContent, + CodeExecutionResultContent, + Content_2 as Content, + ContentDelta, + ContentStart, + ContentStop, + DeepResearchAgentConfig, + DocumentContent, + DocumentMimeType, + DynamicAgentConfig, + ErrorEvent_2 as ErrorEvent, + FileSearchCallContent, + FileSearchResultContent, + Function_2 as Function, + FunctionCallContent, + FunctionResultContent, + GenerationConfig_2 as GenerationConfig, + GoogleSearchCallArguments, + GoogleSearchCallContent, + GoogleSearchResult, + GoogleSearchResultContent, + ImageConfig_2 as ImageConfig, + ImageContent, + ImageMimeType, + Interaction, + InteractionCompleteEvent, + InteractionSSEEvent, + InteractionStartEvent, + InteractionStatusUpdate, + MCPServerToolCallContent, + MCPServerToolResultContent, + Model_2 as Model, + SpeechConfig_2 as SpeechConfig, + TextContent, + ThinkingLevel_2 as ThinkingLevel, + ThoughtContent, + Tool_2 as Tool, + ToolChoice, + ToolChoiceConfig, + ToolChoiceType, + Turn, + URLContextCallArguments, + URLContextCallContent, + URLContextResult, + URLContextResultContent, + Usage, + VideoContent, + VideoMimeType, + InteractionDeleteResponse, + InteractionCreateParams, + BaseCreateModelInteractionParams, + BaseCreateAgentInteractionParams, + CreateModelInteractionParamsNonStreaming, + CreateModelInteractionParamsStreaming, + CreateAgentInteractionParamsNonStreaming, + CreateAgentInteractionParamsStreaming, + InteractionDeleteParams, + InteractionCancelParams, + InteractionGetParams, + InteractionGetParamsBase, + InteractionGetParamsNonStreaming, + InteractionGetParamsStreaming + } +} + +declare type InteractionSSEEvent = InteractionStartEvent | InteractionCompleteEvent | InteractionStatusUpdate | ContentStart | ContentDelta | ContentStop | ErrorEvent_2; + +declare interface InteractionStartEvent { + /** + * The event_id token to be used to resume the interaction stream, from this event. + */ + event_id?: string; + event_type?: 'interaction.start'; + /** + * The Interaction resource. + */ + interaction?: Interaction; +} + +declare interface InteractionStatusUpdate { + /** + * The event_id token to be used to resume the interaction stream, from this event. + */ + event_id?: string; + event_type?: 'interaction.status_update'; + interaction_id?: string; + status?: 'in_progress' | 'requires_action' | 'completed' | 'failed' | 'cancelled' | 'incomplete'; +} + +/** Parameters for the private _Register method. */ +export declare interface InternalRegisterFilesParameters { + /** The Google Cloud Storage URIs to register. Example: `gs://bucket/object`. */ + uris: string[]; + /** Used to override the default configuration. */ + config?: RegisterFilesConfig; +} + +declare class InternalServerError extends APIError<number, Headers> { +} + +/** Represents a time interval, encoded as a Timestamp start (inclusive) and a Timestamp end (exclusive). The start must be less than or equal to the end. When the start equals the end, the interval is empty (matches no time). When both start and end are unspecified, the interval matches any time. */ +export declare interface Interval { + /** Optional. Exclusive end of the interval. If specified, a Timestamp matching this interval will have to be before the end. */ + endTime?: string; + /** Optional. Inclusive start of the interval. If specified, a Timestamp matching this interval will have to be the same or after the start. */ + startTime?: string; +} + +/** Job error. */ +export declare interface JobError { + /** A list of messages that carry the error details. There is a common set of message types for APIs to use. */ + details?: string[]; + /** The status code. */ + code?: number; + /** A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the `details` field. */ + message?: string; +} + +/** Job state. */ +export declare enum JobState { + /** + * The job state is unspecified. + */ + JOB_STATE_UNSPECIFIED = "JOB_STATE_UNSPECIFIED", + /** + * The job has been just created or resumed and processing has not yet begun. + */ + JOB_STATE_QUEUED = "JOB_STATE_QUEUED", + /** + * The service is preparing to run the job. + */ + JOB_STATE_PENDING = "JOB_STATE_PENDING", + /** + * The job is in progress. + */ + JOB_STATE_RUNNING = "JOB_STATE_RUNNING", + /** + * The job completed successfully. + */ + JOB_STATE_SUCCEEDED = "JOB_STATE_SUCCEEDED", + /** + * The job failed. + */ + JOB_STATE_FAILED = "JOB_STATE_FAILED", + /** + * The job is being cancelled. From this state the job may only go to either `JOB_STATE_SUCCEEDED`, `JOB_STATE_FAILED` or `JOB_STATE_CANCELLED`. + */ + JOB_STATE_CANCELLING = "JOB_STATE_CANCELLING", + /** + * The job has been cancelled. + */ + JOB_STATE_CANCELLED = "JOB_STATE_CANCELLED", + /** + * The job has been stopped, and can be resumed. + */ + JOB_STATE_PAUSED = "JOB_STATE_PAUSED", + /** + * The job has expired. + */ + JOB_STATE_EXPIRED = "JOB_STATE_EXPIRED", + /** + * The job is being updated. Only jobs in the `JOB_STATE_RUNNING` state can be updated. After updating, the job goes back to the `JOB_STATE_RUNNING` state. + */ + JOB_STATE_UPDATING = "JOB_STATE_UPDATING", + /** + * The job is partially succeeded, some results may be missing due to errors. + */ + JOB_STATE_PARTIALLY_SUCCEEDED = "JOB_STATE_PARTIALLY_SUCCEEDED" +} + +/** Programming language of the `code`. */ +export declare enum Language { + /** + * Unspecified language. This value should not be used. + */ + LANGUAGE_UNSPECIFIED = "LANGUAGE_UNSPECIFIED", + /** + * Python >= 3.10, with numpy and simpy available. + */ + PYTHON = "PYTHON" +} + +/** An object that represents a latitude/longitude pair. + + This is expressed as a pair of doubles to represent degrees latitude and + degrees longitude. Unless specified otherwise, this object must conform to the + <a href="https://en.wikipedia.org/wiki/World_Geodetic_System#1984_version"> + WGS84 standard</a>. Values must be within normalized ranges. */ +export declare interface LatLng { + /** The latitude in degrees. It must be in the range [-90.0, +90.0]. */ + latitude?: number; + /** The longitude in degrees. It must be in the range [-180.0, +180.0] */ + longitude?: number; +} + +/** Config for optional parameters. */ +export declare interface ListBatchJobsConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + pageSize?: number; + pageToken?: string; + filter?: string; +} + +/** Config for batches.list parameters. */ +export declare interface ListBatchJobsParameters { + config?: ListBatchJobsConfig; +} + +/** Config for batches.list return value. */ +export declare class ListBatchJobsResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + nextPageToken?: string; + batchJobs?: BatchJob[]; +} + +/** Config for caches.list method. */ +export declare interface ListCachedContentsConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + pageSize?: number; + pageToken?: string; +} + +/** Parameters for caches.list method. */ +export declare interface ListCachedContentsParameters { + /** Configuration that contains optional parameters. + */ + config?: ListCachedContentsConfig; +} + +export declare class ListCachedContentsResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + nextPageToken?: string; + /** List of cached contents. + */ + cachedContents?: CachedContent[]; +} + +/** Config for optional parameters. */ +export declare interface ListDocumentsConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + pageSize?: number; + pageToken?: string; +} + +/** Config for documents.list parameters. */ +export declare interface ListDocumentsParameters { + /** The resource name of the FileSearchStores. Example: `fileSearchStore/file-search-store-foo` */ + parent: string; + config?: ListDocumentsConfig; +} + +/** Config for documents.list return value. */ +export declare class ListDocumentsResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** A token, which can be sent as `page_token` to retrieve the next page. If this field is omitted, there are no more pages. */ + nextPageToken?: string; + /** The returned `Document`s. */ + documents?: Document_2[]; +} + +export declare interface ListFilesConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + pageSize?: number; + pageToken?: string; +} + +/** Optional parameters for listing FileSearchStore. */ +export declare interface ListFileSearchStoresConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + pageSize?: number; + pageToken?: string; +} + +/** Config for file_search_stores.list parameters. */ +export declare interface ListFileSearchStoresParameters { + /** Optional parameters for the list request. */ + config?: ListFileSearchStoresConfig; +} + +/** Config for file_search_stores.list return value. */ +export declare class ListFileSearchStoresResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + nextPageToken?: string; + /** The returned file search stores. */ + fileSearchStores?: FileSearchStore[]; +} + +/** Generates the parameters for the list method. */ +export declare interface ListFilesParameters { + /** Used to override the default configuration. */ + config?: ListFilesConfig; +} + +/** Response for the list files method. */ +export declare class ListFilesResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** A token that can be sent as a `page_token` into a subsequent `ListFiles` call. */ + nextPageToken?: string; + /** The list of `File`s. */ + files?: File_2[]; +} + +export declare interface ListModelsConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + pageSize?: number; + pageToken?: string; + filter?: string; + /** Set true to list base models, false to list tuned models. */ + queryBase?: boolean; +} + +export declare interface ListModelsParameters { + config?: ListModelsConfig; +} + +export declare class ListModelsResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + nextPageToken?: string; + models?: Model[]; +} + +/** Configuration for the list tuning jobs method. */ +export declare interface ListTuningJobsConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + pageSize?: number; + pageToken?: string; + filter?: string; +} + +/** Parameters for the list tuning jobs method. */ +export declare interface ListTuningJobsParameters { + config?: ListTuningJobsConfig; +} + +/** Response for the list tuning jobs method. */ +export declare class ListTuningJobsResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** A token to retrieve the next page of results. Pass to ListTuningJobsRequest.page_token to obtain that page. */ + nextPageToken?: string; + /** List of TuningJobs in the requested page. */ + tuningJobs?: TuningJob[]; +} + +/** + Live class encapsulates the configuration for live interaction with the + Generative Language API. It embeds ApiClient for general API settings. + + @experimental + */ +export declare class Live { + private readonly apiClient; + private readonly auth; + private readonly webSocketFactory; + readonly music: LiveMusic; + constructor(apiClient: ApiClient, auth: Auth, webSocketFactory: WebSocketFactory); + /** + Establishes a connection to the specified model with the given + configuration and returns a Session object representing that connection. + + @experimental Built-in MCP support is an experimental feature, may change in + future versions. + + @remarks + + @param params - The parameters for establishing a connection to the model. + @return A live session. + + @example + ```ts + let model: string; + if (GOOGLE_GENAI_USE_VERTEXAI) { + model = 'gemini-2.0-flash-live-preview-04-09'; + } else { + model = 'gemini-live-2.5-flash-preview'; + } + const session = await ai.live.connect({ + model: model, + config: { + responseModalities: [Modality.AUDIO], + }, + callbacks: { + onopen: () => { + console.log('Connected to the socket.'); + }, + onmessage: (e: MessageEvent) => { + console.log('Received message from the server: %s\n', debug(e.data)); + }, + onerror: (e: ErrorEvent) => { + console.log('Error occurred: %s\n', debug(e.error)); + }, + onclose: (e: CloseEvent) => { + console.log('Connection closed.'); + }, + }, + }); + ``` + */ + connect(params: types.LiveConnectParameters): Promise<Session>; + private isCallableTool; +} + +/** Callbacks for the live API. */ +export declare interface LiveCallbacks { + /** + * Called when the websocket connection is established. + */ + onopen?: (() => void) | null; + /** + * Called when a message is received from the server. + */ + onmessage: (e: LiveServerMessage) => void; + /** + * Called when an error occurs. + */ + onerror?: ((e: ErrorEvent) => void) | null; + /** + * Called when the websocket connection is closed. + */ + onclose?: ((e: CloseEvent) => void) | null; +} + +/** Incremental update of the current conversation delivered from the client. + + All the content here will unconditionally be appended to the conversation + history and used as part of the prompt to the model to generate content. + + A message here will interrupt any current model generation. */ +export declare interface LiveClientContent { + /** The content appended to the current conversation with the model. + + For single-turn queries, this is a single instance. For multi-turn + queries, this is a repeated field that contains conversation history and + latest request. + */ + turns?: Content[]; + /** If true, indicates that the server content generation should start with + the currently accumulated prompt. Otherwise, the server will await + additional messages before starting generation. */ + turnComplete?: boolean; +} + +/** Messages sent by the client in the API call. */ +export declare interface LiveClientMessage { + /** Message to be sent by the system when connecting to the API. SDK users should not send this message. */ + setup?: LiveClientSetup; + /** Incremental update of the current conversation delivered from the client. */ + clientContent?: LiveClientContent; + /** User input that is sent in real time. */ + realtimeInput?: LiveClientRealtimeInput; + /** Response to a `ToolCallMessage` received from the server. */ + toolResponse?: LiveClientToolResponse; +} + +/** User input that is sent in real time. + + This is different from `LiveClientContent` in a few ways: + + - Can be sent continuously without interruption to model generation. + - If there is a need to mix data interleaved across the + `LiveClientContent` and the `LiveClientRealtimeInput`, server attempts to + optimize for best response, but there are no guarantees. + - End of turn is not explicitly specified, but is rather derived from user + activity (for example, end of speech). + - Even before the end of turn, the data is processed incrementally + to optimize for a fast start of the response from the model. + - Is always assumed to be the user's input (cannot be used to populate + conversation history). */ +export declare interface LiveClientRealtimeInput { + /** Inlined bytes data for media input. */ + mediaChunks?: Blob_2[]; + /** The realtime audio input stream. */ + audio?: Blob_2; + /** + Indicates that the audio stream has ended, e.g. because the microphone was + turned off. + + This should only be sent when automatic activity detection is enabled + (which is the default). + + The client can reopen the stream by sending an audio message. + */ + audioStreamEnd?: boolean; + /** The realtime video input stream. */ + video?: Blob_2; + /** The realtime text input stream. */ + text?: string; + /** Marks the start of user activity. */ + activityStart?: ActivityStart; + /** Marks the end of user activity. */ + activityEnd?: ActivityEnd; +} + +/** Message contains configuration that will apply for the duration of the streaming session. */ +export declare interface LiveClientSetup { + /** + The fully qualified name of the publisher model or tuned model endpoint to + use. + */ + model?: string; + /** The generation configuration for the session. + Note: only a subset of fields are supported. + */ + generationConfig?: GenerationConfig; + /** The user provided system instructions for the model. + Note: only text should be used in parts and content in each part will be + in a separate paragraph. */ + systemInstruction?: ContentUnion; + /** A list of `Tools` the model may use to generate the next response. + + A `Tool` is a piece of code that enables the system to interact with + external systems to perform an action, or set of actions, outside of + knowledge and scope of the model. */ + tools?: ToolListUnion; + /** Configures the realtime input behavior in BidiGenerateContent. */ + realtimeInputConfig?: RealtimeInputConfig; + /** Configures session resumption mechanism. + + If included server will send SessionResumptionUpdate messages. */ + sessionResumption?: SessionResumptionConfig; + /** Configures context window compression mechanism. + + If included, server will compress context window to fit into given length. */ + contextWindowCompression?: ContextWindowCompressionConfig; + /** The transcription of the input aligns with the input audio language. + */ + inputAudioTranscription?: AudioTranscriptionConfig; + /** The transcription of the output aligns with the language code + specified for the output audio. + */ + outputAudioTranscription?: AudioTranscriptionConfig; + /** Configures the proactivity of the model. This allows the model to respond proactively to + the input and to ignore irrelevant input. */ + proactivity?: ProactivityConfig; + /** Configures the explicit VAD signal. If enabled, the client will send + vad_signal to indicate the start and end of speech. This allows the server + to process the audio more efficiently. */ + explicitVadSignal?: boolean; +} + +/** Client generated response to a `ToolCall` received from the server. + + Individual `FunctionResponse` objects are matched to the respective + `FunctionCall` objects by the `id` field. + + Note that in the unary and server-streaming GenerateContent APIs function + calling happens by exchanging the `Content` parts, while in the bidi + GenerateContent APIs function calling happens over this dedicated set of + messages. */ +export declare class LiveClientToolResponse { + /** The response to the function calls. */ + functionResponses?: FunctionResponse[]; +} + +/** Session config for the API connection. */ +export declare interface LiveConnectConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** The generation configuration for the session. */ + generationConfig?: GenerationConfig; + /** The requested modalities of the response. Represents the set of + modalities that the model can return. Defaults to AUDIO if not specified. + */ + responseModalities?: Modality[]; + /** Value that controls the degree of randomness in token selection. + Lower temperatures are good for prompts that require a less open-ended or + creative response, while higher temperatures can lead to more diverse or + creative results. + */ + temperature?: number; + /** Tokens are selected from the most to least probable until the sum + of their probabilities equals this value. Use a lower value for less + random responses and a higher value for more random responses. + */ + topP?: number; + /** For each token selection step, the ``top_k`` tokens with the + highest probabilities are sampled. Then tokens are further filtered based + on ``top_p`` with the final token selected using temperature sampling. Use + a lower number for less random responses and a higher number for more + random responses. + */ + topK?: number; + /** Maximum number of tokens that can be generated in the response. + */ + maxOutputTokens?: number; + /** If specified, the media resolution specified will be used. + */ + mediaResolution?: MediaResolution; + /** When ``seed`` is fixed to a specific number, the model makes a best + effort to provide the same response for repeated requests. By default, a + random number is used. + */ + seed?: number; + /** The speech generation configuration. + */ + speechConfig?: SpeechConfig; + /** Config for thinking features. + An error will be returned if this field is set for models that don't + support thinking. + */ + thinkingConfig?: ThinkingConfig; + /** If enabled, the model will detect emotions and adapt its responses accordingly. */ + enableAffectiveDialog?: boolean; + /** The user provided system instructions for the model. + Note: only text should be used in parts and content in each part will be + in a separate paragraph. */ + systemInstruction?: ContentUnion; + /** A list of `Tools` the model may use to generate the next response. + + A `Tool` is a piece of code that enables the system to interact with + external systems to perform an action, or set of actions, outside of + knowledge and scope of the model. */ + tools?: ToolListUnion; + /** Configures session resumption mechanism. + + If included the server will send SessionResumptionUpdate messages. */ + sessionResumption?: SessionResumptionConfig; + /** The transcription of the input aligns with the input audio language. + */ + inputAudioTranscription?: AudioTranscriptionConfig; + /** The transcription of the output aligns with the language code + specified for the output audio. + */ + outputAudioTranscription?: AudioTranscriptionConfig; + /** Configures the realtime input behavior in BidiGenerateContent. */ + realtimeInputConfig?: RealtimeInputConfig; + /** Configures context window compression mechanism. + + If included, server will compress context window to fit into given length. */ + contextWindowCompression?: ContextWindowCompressionConfig; + /** Configures the proactivity of the model. This allows the model to respond proactively to + the input and to ignore irrelevant input. */ + proactivity?: ProactivityConfig; + /** Configures the explicit VAD signal. If enabled, the client will send + vad_signal to indicate the start and end of speech. This allows the server + to process the audio more efficiently. */ + explicitVadSignal?: boolean; +} + +/** Config for LiveConnectConstraints for Auth Token creation. */ +export declare interface LiveConnectConstraints { + /** ID of the model to configure in the ephemeral token for Live API. + For a list of models, see `Gemini models + <https://ai.google.dev/gemini-api/docs/models>`. */ + model?: string; + /** Configuration specific to Live API connections created using this token. */ + config?: LiveConnectConfig; +} + +/** Parameters for connecting to the live API. */ +export declare interface LiveConnectParameters { + /** ID of the model to use. For a list of models, see `Google models + <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */ + model: string; + /** callbacks */ + callbacks: LiveCallbacks; + /** Optional configuration parameters for the request. + */ + config?: LiveConnectConfig; +} + +/** + LiveMusic class encapsulates the configuration for live music + generation via Lyria Live models. + + @experimental + */ +declare class LiveMusic { + private readonly apiClient; + private readonly auth; + private readonly webSocketFactory; + constructor(apiClient: ApiClient, auth: Auth, webSocketFactory: WebSocketFactory); + /** + Establishes a connection to the specified model and returns a + LiveMusicSession object representing that connection. + + @experimental + + @remarks + + @param params - The parameters for establishing a connection to the model. + @return A live session. + + @example + ```ts + let model = 'models/lyria-realtime-exp'; + const session = await ai.live.music.connect({ + model: model, + callbacks: { + onmessage: (e: MessageEvent) => { + console.log('Received message from the server: %s\n', debug(e.data)); + }, + onerror: (e: ErrorEvent) => { + console.log('Error occurred: %s\n', debug(e.error)); + }, + onclose: (e: CloseEvent) => { + console.log('Connection closed.'); + }, + }, + }); + ``` + */ + connect(params: types.LiveMusicConnectParameters): Promise<LiveMusicSession>; +} + +/** Callbacks for the realtime music API. */ +export declare interface LiveMusicCallbacks { + /** + * Called when a message is received from the server. + */ + onmessage: (e: LiveMusicServerMessage) => void; + /** + * Called when an error occurs. + */ + onerror?: ((e: ErrorEvent) => void) | null; + /** + * Called when the websocket connection is closed. + */ + onclose?: ((e: CloseEvent) => void) | null; +} + +/** User input to start or steer the music. */ +export declare interface LiveMusicClientContent { + /** Weighted prompts as the model input. */ + weightedPrompts?: WeightedPrompt[]; +} + +/** Messages sent by the client in the LiveMusicClientMessage call. */ +export declare interface LiveMusicClientMessage { + /** Message to be sent in the first (and only in the first) `LiveMusicClientMessage`. + Clients should wait for a `LiveMusicSetupComplete` message before + sending any additional messages. */ + setup?: LiveMusicClientSetup; + /** User input to influence music generation. */ + clientContent?: LiveMusicClientContent; + /** Configuration for music generation. */ + musicGenerationConfig?: LiveMusicGenerationConfig; + /** Playback control signal for the music generation. */ + playbackControl?: LiveMusicPlaybackControl; +} + +/** Message to be sent by the system when connecting to the API. */ +export declare interface LiveMusicClientSetup { + /** The model's resource name. Format: `models/{model}`. */ + model?: string; +} + +/** Parameters for connecting to the live API. */ +export declare interface LiveMusicConnectParameters { + /** The model's resource name. */ + model: string; + /** Callbacks invoked on server events. */ + callbacks: LiveMusicCallbacks; +} + +/** A prompt that was filtered with the reason. */ +export declare interface LiveMusicFilteredPrompt { + /** The text prompt that was filtered. */ + text?: string; + /** The reason the prompt was filtered. */ + filteredReason?: string; +} + +/** Configuration for music generation. */ +export declare interface LiveMusicGenerationConfig { + /** Controls the variance in audio generation. Higher values produce + higher variance. Range is [0.0, 3.0]. */ + temperature?: number; + /** Controls how the model selects tokens for output. Samples the topK + tokens with the highest probabilities. Range is [1, 1000]. */ + topK?: number; + /** Seeds audio generation. If not set, the request uses a randomly + generated seed. */ + seed?: number; + /** Controls how closely the model follows prompts. + Higher guidance follows more closely, but will make transitions more + abrupt. Range is [0.0, 6.0]. */ + guidance?: number; + /** Beats per minute. Range is [60, 200]. */ + bpm?: number; + /** Density of sounds. Range is [0.0, 1.0]. */ + density?: number; + /** Brightness of the music. Range is [0.0, 1.0]. */ + brightness?: number; + /** Scale of the generated music. */ + scale?: Scale; + /** Whether the audio output should contain bass. */ + muteBass?: boolean; + /** Whether the audio output should contain drums. */ + muteDrums?: boolean; + /** Whether the audio output should contain only bass and drums. */ + onlyBassAndDrums?: boolean; + /** The mode of music generation. Default mode is QUALITY. */ + musicGenerationMode?: MusicGenerationMode; +} + +/** The playback control signal to apply to the music generation. */ +export declare enum LiveMusicPlaybackControl { + /** + * This value is unused. + */ + PLAYBACK_CONTROL_UNSPECIFIED = "PLAYBACK_CONTROL_UNSPECIFIED", + /** + * Start generating the music. + */ + PLAY = "PLAY", + /** + * Hold the music generation. Use PLAY to resume from the current position. + */ + PAUSE = "PAUSE", + /** + * Stop the music generation and reset the context (prompts retained). + Use PLAY to restart the music generation. + */ + STOP = "STOP", + /** + * Reset the context of the music generation without stopping it. + Retains the current prompts and config. + */ + RESET_CONTEXT = "RESET_CONTEXT" +} + +/** Server update generated by the model in response to client messages. + + Content is generated as quickly as possible, and not in real time. + Clients may choose to buffer and play it out in real time. */ +export declare interface LiveMusicServerContent { + /** The audio chunks that the model has generated. */ + audioChunks?: AudioChunk[]; +} + +/** Response message for the LiveMusicClientMessage call. */ +export declare class LiveMusicServerMessage { + /** Message sent in response to a `LiveMusicClientSetup` message from the client. + Clients should wait for this message before sending any additional messages. */ + setupComplete?: LiveMusicServerSetupComplete; + /** Content generated by the model in response to client messages. */ + serverContent?: LiveMusicServerContent; + /** A prompt that was filtered with the reason. */ + filteredPrompt?: LiveMusicFilteredPrompt; + /** + * Returns the first audio chunk from the server content, if present. + * + * @remarks + * If there are no audio chunks in the response, undefined will be returned. + */ + get audioChunk(): AudioChunk | undefined; +} + +/** Sent in response to a `LiveMusicClientSetup` message from the client. */ +export declare interface LiveMusicServerSetupComplete { +} + +/** + Represents a connection to the API. + + @experimental + */ +export declare class LiveMusicSession { + readonly conn: WebSocket_2; + private readonly apiClient; + constructor(conn: WebSocket_2, apiClient: ApiClient); + /** + Sets inputs to steer music generation. Updates the session's current + weighted prompts. + + @param params - Contains one property, `weightedPrompts`. + + - `weightedPrompts` to send to the model; weights are normalized to + sum to 1.0. + + @experimental + */ + setWeightedPrompts(params: types.LiveMusicSetWeightedPromptsParameters): Promise<void>; + /** + Sets a configuration to the model. Updates the session's current + music generation config. + + @param params - Contains one property, `musicGenerationConfig`. + + - `musicGenerationConfig` to set in the model. Passing an empty or + undefined config to the model will reset the config to defaults. + + @experimental + */ + setMusicGenerationConfig(params: types.LiveMusicSetConfigParameters): Promise<void>; + private sendPlaybackControl; + /** + * Start the music stream. + * + * @experimental + */ + play(): void; + /** + * Temporarily halt the music stream. Use `play` to resume from the current + * position. + * + * @experimental + */ + pause(): void; + /** + * Stop the music stream and reset the state. Retains the current prompts + * and config. + * + * @experimental + */ + stop(): void; + /** + * Resets the context of the music generation without stopping it. + * Retains the current prompts and config. + * + * @experimental + */ + resetContext(): void; + /** + Terminates the WebSocket connection. + + @experimental + */ + close(): void; +} + +/** Parameters for setting config for the live music API. */ +export declare interface LiveMusicSetConfigParameters { + /** Configuration for music generation. */ + musicGenerationConfig: LiveMusicGenerationConfig; +} + +/** Parameters for setting weighted prompts for the live music API. */ +export declare interface LiveMusicSetWeightedPromptsParameters { + /** A map of text prompts to weights to use for the generation request. */ + weightedPrompts: WeightedPrompt[]; +} + +/** Prompts and config used for generating this audio chunk. */ +export declare interface LiveMusicSourceMetadata { + /** Weighted prompts for generating this audio chunk. */ + clientContent?: LiveMusicClientContent; + /** Music generation config for generating this audio chunk. */ + musicGenerationConfig?: LiveMusicGenerationConfig; +} + +/** Parameters for sending client content to the live API. */ +export declare interface LiveSendClientContentParameters { + /** Client content to send to the session. */ + turns?: ContentListUnion; + /** If true, indicates that the server content generation should start with + the currently accumulated prompt. Otherwise, the server will await + additional messages before starting generation. */ + turnComplete?: boolean; +} + +/** Parameters for sending realtime input to the live API. */ +export declare interface LiveSendRealtimeInputParameters { + /** Realtime input to send to the session. */ + media?: BlobImageUnion; + /** The realtime audio input stream. */ + audio?: Blob_2; + /** + Indicates that the audio stream has ended, e.g. because the microphone was + turned off. + + This should only be sent when automatic activity detection is enabled + (which is the default). + + The client can reopen the stream by sending an audio message. + */ + audioStreamEnd?: boolean; + /** The realtime video input stream. */ + video?: BlobImageUnion; + /** The realtime text input stream. */ + text?: string; + /** Marks the start of user activity. */ + activityStart?: ActivityStart; + /** Marks the end of user activity. */ + activityEnd?: ActivityEnd; +} + +/** Parameters for sending tool responses to the live API. */ +export declare class LiveSendToolResponseParameters { + /** Tool responses to send to the session. */ + functionResponses: FunctionResponse[] | FunctionResponse; +} + +/** Incremental server update generated by the model in response to client messages. + + Content is generated as quickly as possible, and not in real time. Clients + may choose to buffer and play it out in real time. */ +export declare interface LiveServerContent { + /** The content that the model has generated as part of the current conversation with the user. */ + modelTurn?: Content; + /** If true, indicates that the model is done generating. Generation will only start in response to additional client messages. Can be set alongside `content`, indicating that the `content` is the last in the turn. */ + turnComplete?: boolean; + /** If true, indicates that a client message has interrupted current model generation. If the client is playing out the content in realtime, this is a good signal to stop and empty the current queue. */ + interrupted?: boolean; + /** Metadata returned to client when grounding is enabled. */ + groundingMetadata?: GroundingMetadata; + /** If true, indicates that the model is done generating. When model is + interrupted while generating there will be no generation_complete message + in interrupted turn, it will go through interrupted > turn_complete. + When model assumes realtime playback there will be delay between + generation_complete and turn_complete that is caused by model + waiting for playback to finish. If true, indicates that the model + has finished generating all content. This is a signal to the client + that it can stop sending messages. */ + generationComplete?: boolean; + /** Input transcription. The transcription is independent to the model + turn which means it doesn’t imply any ordering between transcription and + model turn. */ + inputTranscription?: Transcription; + /** Output transcription. The transcription is independent to the model + turn which means it doesn’t imply any ordering between transcription and + model turn. + */ + outputTranscription?: Transcription; + /** Metadata related to url context retrieval tool. */ + urlContextMetadata?: UrlContextMetadata; + /** Reason for the turn is complete. */ + turnCompleteReason?: TurnCompleteReason; + /** If true, indicates that the model is not generating content because + it is waiting for more input from the user, e.g. because it expects the + user to continue talking. */ + waitingForInput?: boolean; +} + +/** Server will not be able to service client soon. */ +export declare interface LiveServerGoAway { + /** The remaining time before the connection will be terminated as ABORTED. The minimal time returned here is specified differently together with the rate limits for a given model. */ + timeLeft?: string; +} + +/** Response message for API call. */ +export declare class LiveServerMessage { + /** Sent in response to a `LiveClientSetup` message from the client. */ + setupComplete?: LiveServerSetupComplete; + /** Content generated by the model in response to client messages. */ + serverContent?: LiveServerContent; + /** Request for the client to execute the `function_calls` and return the responses with the matching `id`s. */ + toolCall?: LiveServerToolCall; + /** Notification for the client that a previously issued `ToolCallMessage` with the specified `id`s should have been not executed and should be cancelled. */ + toolCallCancellation?: LiveServerToolCallCancellation; + /** Usage metadata about model response(s). */ + usageMetadata?: UsageMetadata; + /** Server will disconnect soon. */ + goAway?: LiveServerGoAway; + /** Update of the session resumption state. */ + sessionResumptionUpdate?: LiveServerSessionResumptionUpdate; + /** Voice activity detection signal. Allowlisted only. */ + voiceActivityDetectionSignal?: VoiceActivityDetectionSignal; + /** Voice activity signal. */ + voiceActivity?: VoiceActivity; + /** + * Returns the concatenation of all text parts from the server content if present. + * + * @remarks + * If there are non-text parts in the response, the concatenation of all text + * parts will be returned, and a warning will be logged. + */ + get text(): string | undefined; + /** + * Returns the concatenation of all inline data parts from the server content if present. + * + * @remarks + * If there are non-inline data parts in the + * response, the concatenation of all inline data parts will be returned, and + * a warning will be logged. + */ + get data(): string | undefined; +} + +/** Update of the session resumption state. + + Only sent if `session_resumption` was set in the connection config. */ +export declare interface LiveServerSessionResumptionUpdate { + /** New handle that represents state that can be resumed. Empty if `resumable`=false. */ + newHandle?: string; + /** True if session can be resumed at this point. It might be not possible to resume session at some points. In that case we send update empty new_handle and resumable=false. Example of such case could be model executing function calls or just generating. Resuming session (using previous session token) in such state will result in some data loss. */ + resumable?: boolean; + /** Index of last message sent by client that is included in state represented by this SessionResumptionToken. Only sent when `SessionResumptionConfig.transparent` is set. + + Presence of this index allows users to transparently reconnect and avoid issue of losing some part of realtime audio input/video. If client wishes to temporarily disconnect (for example as result of receiving GoAway) they can do it without losing state by buffering messages sent since last `SessionResmumptionTokenUpdate`. This field will enable them to limit buffering (avoid keeping all requests in RAM). + + Note: This should not be used for when resuming a session at some time later -- in those cases partial audio and video frames arelikely not needed. */ + lastConsumedClientMessageIndex?: string; +} + +/** Sent in response to a `LiveGenerateContentSetup` message from the client. */ +export declare interface LiveServerSetupComplete { + /** The session id of the live session. */ + sessionId?: string; +} + +/** Request for the client to execute the `function_calls` and return the responses with the matching `id`s. */ +export declare interface LiveServerToolCall { + /** The function call to be executed. */ + functionCalls?: FunctionCall[]; +} + +/** Notification for the client that a previously issued `ToolCallMessage` with the specified `id`s should have been not executed and should be cancelled. + + If there were side-effects to those tool calls, clients may attempt to undo + the tool calls. This message occurs only in cases where the clients interrupt + server turns. */ +export declare interface LiveServerToolCallCancellation { + /** The ids of the tool calls to be cancelled. */ + ids?: string[]; +} + +declare type LogFn = (message: string, ...rest: unknown[]) => void; + +declare type Logger = { + error: LogFn; + warn: LogFn; + info: LogFn; + debug: LogFn; +}; + +declare type LogLevel = 'off' | 'error' | 'warn' | 'info' | 'debug'; + +/** Logprobs Result */ +export declare interface LogprobsResult { + /** Length = total number of decoding steps. The chosen candidates may or may not be in top_candidates. */ + chosenCandidates?: LogprobsResultCandidate[]; + /** Length = total number of decoding steps. */ + topCandidates?: LogprobsResultTopCandidates[]; +} + +/** Candidate for the logprobs token and score. */ +export declare interface LogprobsResultCandidate { + /** The candidate's log probability. */ + logProbability?: number; + /** The candidate's token string value. */ + token?: string; + /** The candidate's token id value. */ + tokenId?: number; +} + +/** Candidates with top log probabilities at each decoding step. */ +export declare interface LogprobsResultTopCandidates { + /** Sorted by log probability in descending order. */ + candidates?: LogprobsResultCandidate[]; +} + +/** Configuration for a Mask reference image. */ +export declare interface MaskReferenceConfig { + /** Prompts the model to generate a mask instead of you needing to + provide one (unless MASK_MODE_USER_PROVIDED is used). */ + maskMode?: MaskReferenceMode; + /** A list of up to 5 class ids to use for semantic segmentation. + Automatically creates an image mask based on specific objects. */ + segmentationClasses?: number[]; + /** Dilation percentage of the mask provided. + Float between 0 and 1. */ + maskDilation?: number; +} + +/** A mask reference image. + + This encapsulates either a mask image provided by the user and configs for + the user provided mask, or only config parameters for the model to generate + a mask. + + A mask image is an image whose non-zero values indicate where to edit the base + image. If the user provides a mask image, the mask must be in the same + dimensions as the raw image. */ +export declare class MaskReferenceImage { + /** The reference image for the editing operation. */ + referenceImage?: Image_2; + /** The id of the reference image. */ + referenceId?: number; + /** The type of the reference image. Only set by the SDK. */ + referenceType?: string; + /** Configuration for the mask reference image. */ + config?: MaskReferenceConfig; + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI(): ReferenceImageAPIInternal; +} + +/** Enum representing the mask mode of a mask reference image. */ +export declare enum MaskReferenceMode { + MASK_MODE_DEFAULT = "MASK_MODE_DEFAULT", + MASK_MODE_USER_PROVIDED = "MASK_MODE_USER_PROVIDED", + MASK_MODE_BACKGROUND = "MASK_MODE_BACKGROUND", + MASK_MODE_FOREGROUND = "MASK_MODE_FOREGROUND", + MASK_MODE_SEMANTIC = "MASK_MODE_SEMANTIC" +} + +/** + * MCPServer tool call content. + */ +declare interface MCPServerToolCallContent { + /** + * A unique ID for this specific tool call. + */ + id: string; + /** + * The JSON object of arguments for the function. + */ + arguments: { + [key: string]: unknown; + }; + /** + * The name of the tool which was called. + */ + name: string; + /** + * The name of the used MCP server. + */ + server_name: string; + type: 'mcp_server_tool_call'; +} + +/** + * MCPServer tool result content. + */ +declare interface MCPServerToolResultContent { + /** + * ID to match the ID from the MCP server tool call block. + */ + call_id: string; + /** + * The result of the tool call. + */ + result: MCPServerToolResultContent.Items | unknown | string; + type: 'mcp_server_tool_result'; + /** + * Name of the tool which is called for this specific tool call. + */ + name?: string; + /** + * The name of the used MCP server. + */ + server_name?: string; +} + +declare namespace MCPServerToolResultContent { + interface Items { + items?: Array<InteractionsAPI.TextContent | InteractionsAPI.ImageContent>; + } +} + +/** + * Creates a McpCallableTool from MCP clients and an optional config. + * + * The callable tool can invoke the MCP clients with given function call + * arguments. (often for automatic function calling). + * Use the config to modify tool parameters such as behavior. + * + * @experimental Built-in MCP support is an experimental feature, may change in future + * versions. + */ +export declare function mcpToTool(...args: [...Client[], CallableToolConfig | Client]): CallableTool; + +/** Server content modalities. */ +export declare enum MediaModality { + /** + * The modality is unspecified. + */ + MODALITY_UNSPECIFIED = "MODALITY_UNSPECIFIED", + /** + * Plain text. + */ + TEXT = "TEXT", + /** + * Images. + */ + IMAGE = "IMAGE", + /** + * Video. + */ + VIDEO = "VIDEO", + /** + * Audio. + */ + AUDIO = "AUDIO", + /** + * Document, e.g. PDF. + */ + DOCUMENT = "DOCUMENT" +} + +/** The media resolution to use. */ +export declare enum MediaResolution { + /** + * Media resolution has not been set + */ + MEDIA_RESOLUTION_UNSPECIFIED = "MEDIA_RESOLUTION_UNSPECIFIED", + /** + * Media resolution set to low (64 tokens). + */ + MEDIA_RESOLUTION_LOW = "MEDIA_RESOLUTION_LOW", + /** + * Media resolution set to medium (256 tokens). + */ + MEDIA_RESOLUTION_MEDIUM = "MEDIA_RESOLUTION_MEDIUM", + /** + * Media resolution set to high (zoomed reframing with 256 tokens). + */ + MEDIA_RESOLUTION_HIGH = "MEDIA_RESOLUTION_HIGH" +} + +/** + * This type contains `RequestInit` options that may be available on the current runtime, + * including per-platform extensions like `dispatcher`, `agent`, `client`, etc. + */ +declare type MergedRequestInit = RequestInits & +/** We don't include these in the types as they'll be overridden for every request. */ +Partial<Record<'body' | 'headers' | 'method' | 'signal', never>>; + +/** Server content modalities. */ +export declare enum Modality { + /** + * The modality is unspecified. + */ + MODALITY_UNSPECIFIED = "MODALITY_UNSPECIFIED", + /** + * Indicates the model should return text + */ + TEXT = "TEXT", + /** + * Indicates the model should return images. + */ + IMAGE = "IMAGE", + /** + * Indicates the model should return audio. + */ + AUDIO = "AUDIO" +} + +/** Represents token counting info for a single modality. */ +export declare interface ModalityTokenCount { + /** The modality associated with this token count. */ + modality?: MediaModality; + /** Number of tokens. */ + tokenCount?: number; +} + +/** A trained machine learning model. */ +export declare interface Model { + /** Resource name of the model. */ + name?: string; + /** Display name of the model. */ + displayName?: string; + /** Description of the model. */ + description?: string; + /** Version ID of the model. A new version is committed when a new + model version is uploaded or trained under an existing model ID. The + version ID is an auto-incrementing decimal number in string + representation. */ + version?: string; + /** List of deployed models created from this base model. Note that a + model could have been deployed to endpoints in different locations. */ + endpoints?: Endpoint[]; + /** Labels with user-defined metadata to organize your models. */ + labels?: Record<string, string>; + /** Information about the tuned model from the base model. */ + tunedModelInfo?: TunedModelInfo; + /** The maximum number of input tokens that the model can handle. */ + inputTokenLimit?: number; + /** The maximum number of output tokens that the model can generate. */ + outputTokenLimit?: number; + /** List of actions that are supported by the model. */ + supportedActions?: string[]; + /** The default checkpoint id of a model version. + */ + defaultCheckpointId?: string; + /** The checkpoints of the model. */ + checkpoints?: Checkpoint[]; + /** Temperature value used for sampling set when the dataset was saved. + This value is used to tune the degree of randomness. */ + temperature?: number; + /** The maximum temperature value used for sampling set when the + dataset was saved. This value is used to tune the degree of randomness. */ + maxTemperature?: number; + /** Optional. Specifies the nucleus sampling threshold. The model + considers only the smallest set of tokens whose cumulative probability is + at least `top_p`. This helps generate more diverse and less repetitive + responses. For example, a `top_p` of 0.9 means the model considers tokens + until the cumulative probability of the tokens to select from reaches 0.9. + It's recommended to adjust either temperature or `top_p`, but not both. */ + topP?: number; + /** Optional. Specifies the top-k sampling threshold. The model + considers only the top k most probable tokens for the next token. This can + be useful for generating more coherent and less random text. For example, + a `top_k` of 40 means the model will choose the next word from the 40 most + likely words. */ + topK?: number; + /** Whether the model supports thinking features. If true, thoughts are + returned only if the model supports thought and thoughts are available. */ + thinking?: boolean; +} + +/** + * The model that will complete your prompt.\n\nSee [models](https://ai.google.dev/gemini-api/docs/models) for additional details. + */ +declare type Model_2 = 'gemini-2.5-flash' | 'gemini-2.5-flash-image' | 'gemini-2.5-flash-lite' | 'gemini-2.5-flash-lite-preview-09-2025' | 'gemini-2.5-flash-native-audio-preview-12-2025' | 'gemini-2.5-flash-preview-09-2025' | 'gemini-2.5-flash-preview-tts' | 'gemini-2.5-pro' | 'gemini-2.5-pro-preview-tts' | 'gemini-3-flash-preview' | 'gemini-3-pro-image-preview' | 'gemini-3-pro-preview' | (string & {}); + +/** Configuration for Model Armor integrations of prompt and responses. This data type is not supported in Gemini API. */ +export declare interface ModelArmorConfig { + /** Optional. The name of the Model Armor template to use for prompt sanitization. */ + promptTemplateName?: string; + /** Optional. The name of the Model Armor template to use for response sanitization. */ + responseTemplateName?: string; +} + +export declare class Models extends BaseModule { + private readonly apiClient; + constructor(apiClient: ApiClient); + /** + * Makes an API request to generate content with a given model. + * + * For the `model` parameter, supported formats for Vertex AI API include: + * - The Gemini model ID, for example: 'gemini-2.0-flash' + * - The full resource name starts with 'projects/', for example: + * 'projects/my-project-id/locations/us-central1/publishers/google/models/gemini-2.0-flash' + * - The partial resource name with 'publishers/', for example: + * 'publishers/google/models/gemini-2.0-flash' or + * 'publishers/meta/models/llama-3.1-405b-instruct-maas' + * - `/` separated publisher and model name, for example: + * 'google/gemini-2.0-flash' or 'meta/llama-3.1-405b-instruct-maas' + * + * For the `model` parameter, supported formats for Gemini API include: + * - The Gemini model ID, for example: 'gemini-2.0-flash' + * - The model name starts with 'models/', for example: + * 'models/gemini-2.0-flash' + * - For tuned models, the model name starts with 'tunedModels/', + * for example: + * 'tunedModels/1234567890123456789' + * + * Some models support multimodal input and output. + * + * @param params - The parameters for generating content. + * @return The response from generating content. + * + * @example + * ```ts + * const response = await ai.models.generateContent({ + * model: 'gemini-2.0-flash', + * contents: 'why is the sky blue?', + * config: { + * candidateCount: 2, + * } + * }); + * console.log(response); + * ``` + */ + generateContent: (params: types.GenerateContentParameters) => Promise<types.GenerateContentResponse>; + /** + * This logic is needed for GenerateContentConfig only. + * Previously we made GenerateContentConfig.responseSchema field to accept + * unknown. Since v1.9.0, we switch to use backend JSON schema support. + * To maintain backward compatibility, we move the data that was treated as + * JSON schema from the responseSchema field to the responseJsonSchema field. + */ + private maybeMoveToResponseJsonSchem; + /** + * Makes an API request to generate content with a given model and yields the + * response in chunks. + * + * For the `model` parameter, supported formats for Vertex AI API include: + * - The Gemini model ID, for example: 'gemini-2.0-flash' + * - The full resource name starts with 'projects/', for example: + * 'projects/my-project-id/locations/us-central1/publishers/google/models/gemini-2.0-flash' + * - The partial resource name with 'publishers/', for example: + * 'publishers/google/models/gemini-2.0-flash' or + * 'publishers/meta/models/llama-3.1-405b-instruct-maas' + * - `/` separated publisher and model name, for example: + * 'google/gemini-2.0-flash' or 'meta/llama-3.1-405b-instruct-maas' + * + * For the `model` parameter, supported formats for Gemini API include: + * - The Gemini model ID, for example: 'gemini-2.0-flash' + * - The model name starts with 'models/', for example: + * 'models/gemini-2.0-flash' + * - For tuned models, the model name starts with 'tunedModels/', + * for example: + * 'tunedModels/1234567890123456789' + * + * Some models support multimodal input and output. + * + * @param params - The parameters for generating content with streaming response. + * @return The response from generating content. + * + * @example + * ```ts + * const response = await ai.models.generateContentStream({ + * model: 'gemini-2.0-flash', + * contents: 'why is the sky blue?', + * config: { + * maxOutputTokens: 200, + * } + * }); + * for await (const chunk of response) { + * console.log(chunk); + * } + * ``` + */ + generateContentStream: (params: types.GenerateContentParameters) => Promise<AsyncGenerator<types.GenerateContentResponse>>; + /** + * Transforms the CallableTools in the parameters to be simply Tools, it + * copies the params into a new object and replaces the tools, it does not + * modify the original params. Also sets the MCP usage header if there are + * MCP tools in the parameters. + */ + private processParamsMaybeAddMcpUsage; + private initAfcToolsMap; + private processAfcStream; + /** + * Generates an image based on a text description and configuration. + * + * @param params - The parameters for generating images. + * @return The response from the API. + * + * @example + * ```ts + * const response = await client.models.generateImages({ + * model: 'imagen-4.0-generate-001', + * prompt: 'Robot holding a red skateboard', + * config: { + * numberOfImages: 1, + * includeRaiReason: true, + * }, + * }); + * console.log(response?.generatedImages?.[0]?.image?.imageBytes); + * ``` + */ + generateImages: (params: types.GenerateImagesParameters) => Promise<types.GenerateImagesResponse>; + list: (params?: types.ListModelsParameters) => Promise<Pager<types.Model>>; + /** + * Edits an image based on a prompt, list of reference images, and configuration. + * + * @param params - The parameters for editing an image. + * @return The response from the API. + * + * @example + * ```ts + * const response = await client.models.editImage({ + * model: 'imagen-3.0-capability-001', + * prompt: 'Generate an image containing a mug with the product logo [1] visible on the side of the mug.', + * referenceImages: [subjectReferenceImage] + * config: { + * numberOfImages: 1, + * includeRaiReason: true, + * }, + * }); + * console.log(response?.generatedImages?.[0]?.image?.imageBytes); + * ``` + */ + editImage: (params: types.EditImageParameters) => Promise<types.EditImageResponse>; + /** + * Upscales an image based on an image, upscale factor, and configuration. + * Only supported in Vertex AI currently. + * + * @param params - The parameters for upscaling an image. + * @return The response from the API. + * + * @example + * ```ts + * const response = await client.models.upscaleImage({ + * model: 'imagen-4.0-upscale-preview', + * image: image, + * upscaleFactor: 'x2', + * config: { + * includeRaiReason: true, + * }, + * }); + * console.log(response?.generatedImages?.[0]?.image?.imageBytes); + * ``` + */ + upscaleImage: (params: types.UpscaleImageParameters) => Promise<types.UpscaleImageResponse>; + /** + * Generates videos based on a text description and configuration. + * + * @param params - The parameters for generating videos. + * @return A Promise<GenerateVideosOperation> which allows you to track the progress and eventually retrieve the generated videos using the operations.get method. + * + * @example + * ```ts + * const operation = await ai.models.generateVideos({ + * model: 'veo-2.0-generate-001', + * source: { + * prompt: 'A neon hologram of a cat driving at top speed', + * }, + * config: { + * numberOfVideos: 1 + * }); + * + * while (!operation.done) { + * await new Promise(resolve => setTimeout(resolve, 10000)); + * operation = await ai.operations.getVideosOperation({operation: operation}); + * } + * + * console.log(operation.response?.generatedVideos?.[0]?.video?.uri); + * ``` + */ + generateVideos: (params: types.GenerateVideosParameters) => Promise<types.GenerateVideosOperation>; + private generateContentInternal; + private generateContentStreamInternal; + /** + * Calculates embeddings for the given contents. Only text is supported. + * + * @param params - The parameters for embedding contents. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.embedContent({ + * model: 'text-embedding-004', + * contents: [ + * 'What is your name?', + * 'What is your favorite color?', + * ], + * config: { + * outputDimensionality: 64, + * }, + * }); + * console.log(response); + * ``` + */ + embedContent(params: types.EmbedContentParameters): Promise<types.EmbedContentResponse>; + /** + * Private method for generating images. + */ + private generateImagesInternal; + /** + * Private method for editing an image. + */ + private editImageInternal; + /** + * Private method for upscaling an image. + */ + private upscaleImageInternal; + /** + * Recontextualizes an image. + * + * There are two types of recontextualization currently supported: + * 1) Imagen Product Recontext - Generate images of products in new scenes + * and contexts. + * 2) Virtual Try-On: Generate images of persons modeling fashion products. + * + * @param params - The parameters for recontextualizing an image. + * @return The response from the API. + * + * @example + * ```ts + * const response1 = await ai.models.recontextImage({ + * model: 'imagen-product-recontext-preview-06-30', + * source: { + * prompt: 'In a modern kitchen setting.', + * productImages: [productImage], + * }, + * config: { + * numberOfImages: 1, + * }, + * }); + * console.log(response1?.generatedImages?.[0]?.image?.imageBytes); + * + * const response2 = await ai.models.recontextImage({ + * model: 'virtual-try-on-001', + * source: { + * personImage: personImage, + * productImages: [productImage], + * }, + * config: { + * numberOfImages: 1, + * }, + * }); + * console.log(response2?.generatedImages?.[0]?.image?.imageBytes); + * ``` + */ + recontextImage(params: types.RecontextImageParameters): Promise<types.RecontextImageResponse>; + /** + * Segments an image, creating a mask of a specified area. + * + * @param params - The parameters for segmenting an image. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.segmentImage({ + * model: 'image-segmentation-001', + * source: { + * image: image, + * }, + * config: { + * mode: 'foreground', + * }, + * }); + * console.log(response?.generatedMasks?.[0]?.mask?.imageBytes); + * ``` + */ + segmentImage(params: types.SegmentImageParameters): Promise<types.SegmentImageResponse>; + /** + * Fetches information about a model by name. + * + * @example + * ```ts + * const modelInfo = await ai.models.get({model: 'gemini-2.0-flash'}); + * ``` + */ + get(params: types.GetModelParameters): Promise<types.Model>; + private listInternal; + /** + * Updates a tuned model by its name. + * + * @param params - The parameters for updating the model. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.update({ + * model: 'tuned-model-name', + * config: { + * displayName: 'New display name', + * description: 'New description', + * }, + * }); + * ``` + */ + update(params: types.UpdateModelParameters): Promise<types.Model>; + /** + * Deletes a tuned model by its name. + * + * @param params - The parameters for deleting the model. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.delete({model: 'tuned-model-name'}); + * ``` + */ + delete(params: types.DeleteModelParameters): Promise<types.DeleteModelResponse>; + /** + * Counts the number of tokens in the given contents. Multimodal input is + * supported for Gemini models. + * + * @param params - The parameters for counting tokens. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.countTokens({ + * model: 'gemini-2.0-flash', + * contents: 'The quick brown fox jumps over the lazy dog.' + * }); + * console.log(response); + * ``` + */ + countTokens(params: types.CountTokensParameters): Promise<types.CountTokensResponse>; + /** + * Given a list of contents, returns a corresponding TokensInfo containing + * the list of tokens and list of token ids. + * + * This method is not supported by the Gemini Developer API. + * + * @param params - The parameters for computing tokens. + * @return The response from the API. + * + * @example + * ```ts + * const response = await ai.models.computeTokens({ + * model: 'gemini-2.0-flash', + * contents: 'What is your name?' + * }); + * console.log(response); + * ``` + */ + computeTokens(params: types.ComputeTokensParameters): Promise<types.ComputeTokensResponse>; + /** + * Private method for generating videos. + */ + private generateVideosInternal; +} + +/** Config for model selection. */ +export declare interface ModelSelectionConfig { + /** Options for feature selection preference. */ + featureSelectionPreference?: FeatureSelectionPreference; +} + +/** Configuration for a multi-speaker text-to-speech request. */ +export declare interface MultiSpeakerVoiceConfig { + /** Required. A list of configurations for the voices of the speakers. Exactly two speaker voice configurations must be provided. */ + speakerVoiceConfigs?: SpeakerVoiceConfig[]; +} + +/** The mode of music generation. */ +export declare enum MusicGenerationMode { + /** + * Rely on the server default generation mode. + */ + MUSIC_GENERATION_MODE_UNSPECIFIED = "MUSIC_GENERATION_MODE_UNSPECIFIED", + /** + * Steer text prompts to regions of latent space with higher quality + music. + */ + QUALITY = "QUALITY", + /** + * Steer text prompts to regions of latent space with a larger + diversity of music. + */ + DIVERSITY = "DIVERSITY", + /** + * Steer text prompts to regions of latent space more likely to + generate music with vocals. + */ + VOCALIZATION = "VOCALIZATION" +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +/// <reference types="node" /> +/** + * Shims for types that we can't always rely on being available globally. + * + * Note: these only exist at the type-level, there is no corresponding runtime + * version for any of these symbols. + */ +declare type NeverToAny<T> = T extends never ? any : T; + +/** @ts-ignore For users with node-fetch@2 */ +declare type NodeFetch2RequestInit = NotAny<import('../node_modules/@types/node-fetch/index.d.ts').RequestInit> | NotAny<import('../../node_modules/@types/node-fetch/index.d.ts').RequestInit> | NotAny<import('../../../node_modules/@types/node-fetch/index.d.ts').RequestInit> | NotAny<import('../../../../node_modules/@types/node-fetch/index.d.ts').RequestInit> | NotAny<import('../../../../../node_modules/@types/node-fetch/index.d.ts').RequestInit> | NotAny<import('../../../../../../node_modules/@types/node-fetch/index.d.ts').RequestInit> | NotAny<import('../../../../../../../node_modules/@types/node-fetch/index.d.ts').RequestInit> | NotAny<import('../../../../../../../../node_modules/@types/node-fetch/index.d.ts').RequestInit> | NotAny<import('../../../../../../../../../node_modules/@types/node-fetch/index.d.ts').RequestInit> | NotAny<import('../../../../../../../../../../node_modules/@types/node-fetch/index.d.ts').RequestInit>; + +/** @ts-ignore For users with node-fetch@3, doesn't need file extension because types are at ./@types/index.d.ts */ +declare type NodeFetch3RequestInit = NotAny<import('../node_modules/node-fetch').RequestInit> | NotAny<import('../../node_modules/node-fetch').RequestInit> | NotAny<import('../../../node_modules/node-fetch').RequestInit> | NotAny<import('../../../../node_modules/node-fetch').RequestInit> | NotAny<import('../../../../../node_modules/node-fetch').RequestInit> | NotAny<import('../../../../../../node_modules/node-fetch').RequestInit> | NotAny<import('../../../../../../../node_modules/node-fetch').RequestInit> | NotAny<import('../../../../../../../../node_modules/node-fetch').RequestInit> | NotAny<import('../../../../../../../../../node_modules/node-fetch').RequestInit> | NotAny<import('../../../../../../../../../../node_modules/node-fetch').RequestInit>; + +/** @ts-ignore */ +declare type _NodeReadableStream<R = any> = ReadableStream_2<R>; + +declare type NotAny<T> = [0] extends [1 & T] ? never : T; + +declare class NotFoundError extends APIError<404, Headers> { +} + +/** + * @internal + * Users can pass explicit nulls to unset default headers. When we parse them + * into a standard headers type we need to preserve that information. + */ +declare type NullableHeaders = { + /** Brand check, prevent users from creating a NullableHeaders. */ + [brand_privateNullableHeaders]: true; + /** Parsed headers. */ + values: Headers; + /** Set of lowercase header names explicitly set to null. */ + nulls: Set<string>; +}; + +/** A long-running operation. */ +export declare interface Operation<T> { + /** The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`. */ + name?: string; + /** Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata. Any method that returns a long-running operation should document the metadata type, if any. */ + metadata?: Record<string, unknown>; + /** If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available. */ + done?: boolean; + /** The error result of the operation in case of failure or cancellation. */ + error?: Record<string, unknown>; + /** The response if the operation is successful. */ + response?: T; + /** + * Instantiates an Operation of the same type as the one being called with the fields set from the API response. + * @internal + */ + _fromAPIResponse({ apiResponse, _isVertexAI, }: OperationFromAPIResponseParameters): Operation<T>; +} + +/** Parameters of the fromAPIResponse method of the Operation class. */ +export declare interface OperationFromAPIResponseParameters { + /** The API response to be converted to an Operation. */ + apiResponse: Record<string, unknown>; + /** Whether the API response is from Vertex AI. */ + _isVertexAI: boolean; +} + +/** Parameters for the get method of the operations module. */ +export declare interface OperationGetParameters<T, U extends Operation<T>> { + /** Used to override the default configuration. */ + config?: GetOperationConfig; + /** The operation to be retrieved. */ + operation: U; +} + +export declare class Operations extends BaseModule { + private readonly apiClient; + constructor(apiClient: ApiClient); + /** + * Gets the status of a long-running operation. + * + * @param parameters The parameters for the get operation request. + * @return The updated Operation object, with the latest status or result. + */ + getVideosOperation(parameters: types.OperationGetParameters<types.GenerateVideosResponse, types.GenerateVideosOperation>): Promise<types.GenerateVideosOperation>; + /** + * Gets the status of a long-running operation. + * + * @param parameters The parameters for the get operation request. + * @return The updated Operation object, with the latest status or result. + */ + get<T, U extends types.Operation<T>>(parameters: types.OperationGetParameters<T, U>): Promise<types.Operation<T>>; + private getVideosOperationInternal; + private fetchPredictVideosOperationInternal; +} + +/** Outcome of the code execution. */ +export declare enum Outcome { + /** + * Unspecified status. This value should not be used. + */ + OUTCOME_UNSPECIFIED = "OUTCOME_UNSPECIFIED", + /** + * Code execution completed successfully. + */ + OUTCOME_OK = "OUTCOME_OK", + /** + * Code execution finished but with a failure. `stderr` should contain the reason. + */ + OUTCOME_FAILED = "OUTCOME_FAILED", + /** + * Code execution ran for too long, and was cancelled. There may or may not be a partial output present. + */ + OUTCOME_DEADLINE_EXCEEDED = "OUTCOME_DEADLINE_EXCEEDED" +} + +/** + * Some environments overload the global fetch function, and Parameters<T> only gets the last signature. + */ +declare type OverloadedParameters<T> = T extends ({ + (...args: infer A): unknown; + (...args: infer B): unknown; + (...args: infer C): unknown; + (...args: infer D): unknown; +}) ? A | B | C | D : T extends ({ + (...args: infer A): unknown; + (...args: infer B): unknown; + (...args: infer C): unknown; +}) ? A | B | C : T extends ({ + (...args: infer A): unknown; + (...args: infer B): unknown; +}) ? A | B : T extends (...args: infer A) => unknown ? A : never; + +export declare enum PagedItem { + PAGED_ITEM_BATCH_JOBS = "batchJobs", + PAGED_ITEM_MODELS = "models", + PAGED_ITEM_TUNING_JOBS = "tuningJobs", + PAGED_ITEM_FILES = "files", + PAGED_ITEM_CACHED_CONTENTS = "cachedContents", + PAGED_ITEM_FILE_SEARCH_STORES = "fileSearchStores", + PAGED_ITEM_DOCUMENTS = "documents" +} + +declare interface PagedItemConfig { + parent?: string; + config?: { + pageToken?: string; + pageSize?: number; + }; +} + +declare interface PagedItemResponse<T> { + nextPageToken?: string; + sdkHttpResponse?: types.HttpResponse; + batchJobs?: T[]; + models?: T[]; + tuningJobs?: T[]; + files?: T[]; + cachedContents?: T[]; + fileSearchStores?: T[]; + documents?: T[]; +} + +/** + * Pager class for iterating through paginated results. + */ +export declare class Pager<T> implements AsyncIterable<T> { + private nameInternal; + private pageInternal; + private paramsInternal; + private pageInternalSize; + private sdkHttpResponseInternal?; + protected requestInternal: (params: PagedItemConfig) => Promise<PagedItemResponse<T>>; + protected idxInternal: number; + constructor(name: PagedItem, request: (params: PagedItemConfig) => Promise<PagedItemResponse<T>>, response: PagedItemResponse<T>, params: PagedItemConfig); + private init; + private initNextPage; + /** + * Returns the current page, which is a list of items. + * + * @remarks + * The first page is retrieved when the pager is created. The returned list of + * items could be a subset of the entire list. + */ + get page(): T[]; + /** + * Returns the type of paged item (for example, ``batch_jobs``). + */ + get name(): PagedItem; + /** + * Returns the length of the page fetched each time by this pager. + * + * @remarks + * The number of items in the page is less than or equal to the page length. + */ + get pageSize(): number; + /** + * Returns the headers of the API response. + */ + get sdkHttpResponse(): types.HttpResponse | undefined; + /** + * Returns the parameters when making the API request for the next page. + * + * @remarks + * Parameters contain a set of optional configs that can be + * used to customize the API request. For example, the `pageToken` parameter + * contains the token to request the next page. + */ + get params(): PagedItemConfig; + /** + * Returns the total number of items in the current page. + */ + get pageLength(): number; + /** + * Returns the item at the given index. + */ + getItem(index: number): T; + /** + * Returns an async iterator that support iterating through all items + * retrieved from the API. + * + * @remarks + * The iterator will automatically fetch the next page if there are more items + * to fetch from the API. + * + * @example + * + * ```ts + * const pager = await ai.files.list({config: {pageSize: 10}}); + * for await (const file of pager) { + * console.log(file.name); + * } + * ``` + */ + [Symbol.asyncIterator](): AsyncIterator<T>; + /** + * Fetches the next page of items. This makes a new API request. + * + * @throws {Error} If there are no more pages to fetch. + * + * @example + * + * ```ts + * const pager = await ai.files.list({config: {pageSize: 10}}); + * let page = pager.page; + * while (true) { + * for (const file of page) { + * console.log(file.name); + * } + * if (!pager.hasNextPage()) { + * break; + * } + * page = await pager.nextPage(); + * } + * ``` + */ + nextPage(): Promise<T[]>; + /** + * Returns true if there are more pages to fetch from the API. + */ + hasNextPage(): boolean; +} + +/** A datatype containing media content. + + Exactly one field within a Part should be set, representing the specific type + of content being conveyed. Using multiple fields within the same `Part` + instance is considered invalid. */ +export declare interface Part { + /** Media resolution for the input media. + */ + mediaResolution?: PartMediaResolution; + /** Optional. Result of executing the [ExecutableCode]. */ + codeExecutionResult?: CodeExecutionResult; + /** Optional. Code generated by the model that is meant to be executed. */ + executableCode?: ExecutableCode; + /** Optional. URI based data. */ + fileData?: FileData; + /** Optional. A predicted [FunctionCall] returned from the model that contains a string representing the [FunctionDeclaration.name] with the parameters and their values. */ + functionCall?: FunctionCall; + /** Optional. The result output of a [FunctionCall] that contains a string representing the [FunctionDeclaration.name] and a structured JSON object containing any output from the function call. It is used as context to the model. */ + functionResponse?: FunctionResponse; + /** Optional. Inlined bytes data. */ + inlineData?: Blob_2; + /** Optional. Text part (can be code). */ + text?: string; + /** Optional. Indicates if the part is thought from the model. */ + thought?: boolean; + /** Optional. An opaque signature for the thought so it can be reused in subsequent requests. + * @remarks Encoded as base64 string. */ + thoughtSignature?: string; + /** Optional. Video metadata. The metadata should only be specified while the video data is presented in inline_data or file_data. */ + videoMetadata?: VideoMetadata; +} + +/** Partial argument value of the function call. This data type is not supported in Gemini API. */ +export declare interface PartialArg { + /** Optional. Represents a null value. */ + nullValue?: 'NULL_VALUE'; + /** Optional. Represents a double value. */ + numberValue?: number; + /** Optional. Represents a string value. */ + stringValue?: string; + /** Optional. Represents a boolean value. */ + boolValue?: boolean; + /** Required. A JSON Path (RFC 9535) to the argument being streamed. https://datatracker.ietf.org/doc/html/rfc9535. e.g. "$.foo.bar[0].data". */ + jsonPath?: string; + /** Optional. Whether this is not the last part of the same json_path. If true, another PartialArg message for the current json_path is expected to follow. */ + willContinue?: boolean; +} + +export declare type PartListUnion = PartUnion[] | PartUnion; + +/** Media resolution for the input media. */ +export declare interface PartMediaResolution { + /** The tokenization quality used for given media. + */ + level?: PartMediaResolutionLevel; + /** Specifies the required sequence length for media tokenization. + */ + numTokens?: number; +} + +/** The tokenization quality used for given media. */ +export declare enum PartMediaResolutionLevel { + /** + * Media resolution has not been set. + */ + MEDIA_RESOLUTION_UNSPECIFIED = "MEDIA_RESOLUTION_UNSPECIFIED", + /** + * Media resolution set to low. + */ + MEDIA_RESOLUTION_LOW = "MEDIA_RESOLUTION_LOW", + /** + * Media resolution set to medium. + */ + MEDIA_RESOLUTION_MEDIUM = "MEDIA_RESOLUTION_MEDIUM", + /** + * Media resolution set to high. + */ + MEDIA_RESOLUTION_HIGH = "MEDIA_RESOLUTION_HIGH", + /** + * Media resolution set to ultra high. + */ + MEDIA_RESOLUTION_ULTRA_HIGH = "MEDIA_RESOLUTION_ULTRA_HIGH" +} + +/** Tuning spec for Partner models. This data type is not supported in Gemini API. */ +export declare interface PartnerModelTuningSpec { + /** Hyperparameters for tuning. The accepted hyper_parameters and their valid range of values will differ depending on the base model. */ + hyperParameters?: Record<string, unknown>; + /** Required. Cloud Storage path to file containing training dataset for tuning. The dataset must be formatted as a JSONL file. */ + trainingDatasetUri?: string; + /** Optional. Cloud Storage path to file containing validation dataset for tuning. The dataset must be formatted as a JSONL file. */ + validationDatasetUri?: string; +} + +export declare type PartUnion = Part | string; + +declare class PermissionDeniedError extends APIError<403, Headers> { +} + +/** Enum that controls the generation of people. */ +export declare enum PersonGeneration { + /** + * Block generation of images of people. + */ + DONT_ALLOW = "DONT_ALLOW", + /** + * Generate images of adults, but not children. + */ + ALLOW_ADULT = "ALLOW_ADULT", + /** + * Generate images that include adults and children. + */ + ALLOW_ALL = "ALLOW_ALL" +} + +/** Sites with confidence level chosen & above this value will be blocked from the search results. This enum is not supported in Gemini API. */ +export declare enum PhishBlockThreshold { + /** + * Defaults to unspecified. + */ + PHISH_BLOCK_THRESHOLD_UNSPECIFIED = "PHISH_BLOCK_THRESHOLD_UNSPECIFIED", + /** + * Blocks Low and above confidence URL that is risky. + */ + BLOCK_LOW_AND_ABOVE = "BLOCK_LOW_AND_ABOVE", + /** + * Blocks Medium and above confidence URL that is risky. + */ + BLOCK_MEDIUM_AND_ABOVE = "BLOCK_MEDIUM_AND_ABOVE", + /** + * Blocks High and above confidence URL that is risky. + */ + BLOCK_HIGH_AND_ABOVE = "BLOCK_HIGH_AND_ABOVE", + /** + * Blocks Higher and above confidence URL that is risky. + */ + BLOCK_HIGHER_AND_ABOVE = "BLOCK_HIGHER_AND_ABOVE", + /** + * Blocks Very high and above confidence URL that is risky. + */ + BLOCK_VERY_HIGH_AND_ABOVE = "BLOCK_VERY_HIGH_AND_ABOVE", + /** + * Blocks Extremely high confidence URL that is risky. + */ + BLOCK_ONLY_EXTREMELY_HIGH = "BLOCK_ONLY_EXTREMELY_HIGH" +} + +/** The configuration for the prebuilt speaker to use. */ +export declare interface PrebuiltVoiceConfig { + /** The name of the preset voice to use. */ + voiceName?: string; +} + +/** Statistics computed for datasets used for preference optimization. This data type is not supported in Gemini API. */ +export declare interface PreferenceOptimizationDataStats { + /** Output only. Dataset distributions for scores variance per example. */ + scoreVariancePerExampleDistribution?: DatasetDistribution; + /** Output only. Dataset distributions for scores. */ + scoresDistribution?: DatasetDistribution; + /** Output only. Number of billable tokens in the tuning dataset. */ + totalBillableTokenCount?: string; + /** Output only. Number of examples in the tuning dataset. */ + tuningDatasetExampleCount?: string; + /** Output only. Number of tuning steps for this Tuning Job. */ + tuningStepCount?: string; + /** Output only. Sample user examples in the training dataset. */ + userDatasetExamples?: GeminiPreferenceExample[]; + /** Output only. Dataset distributions for the user input tokens. */ + userInputTokenDistribution?: DatasetDistribution; + /** Output only. Dataset distributions for the user output tokens. */ + userOutputTokenDistribution?: DatasetDistribution; +} + +/** Hyperparameters for Preference Optimization. This data type is not supported in Gemini API. */ +export declare interface PreferenceOptimizationHyperParameters { + /** Optional. Adapter size for preference optimization. */ + adapterSize?: AdapterSize; + /** Optional. Weight for KL Divergence regularization. */ + beta?: number; + /** Optional. Number of complete passes the model makes over the entire training dataset during training. */ + epochCount?: string; + /** Optional. Multiplier for adjusting the default learning rate. */ + learningRateMultiplier?: number; +} + +/** Preference optimization tuning spec for tuning. */ +export declare interface PreferenceOptimizationSpec { + /** Optional. If set to true, disable intermediate checkpoints for Preference Optimization and only the last checkpoint will be exported. Otherwise, enable intermediate checkpoints for Preference Optimization. Default is false. */ + exportLastCheckpointOnly?: boolean; + /** Optional. Hyperparameters for Preference Optimization. */ + hyperParameters?: PreferenceOptimizationHyperParameters; + /** Required. Cloud Storage path to file containing training dataset for preference optimization tuning. The dataset must be formatted as a JSONL file. */ + trainingDatasetUri?: string; + /** Optional. Cloud Storage path to file containing validation dataset for preference optimization tuning. The dataset must be formatted as a JSONL file. */ + validationDatasetUri?: string; +} + +/** A pre-tuned model for continuous tuning. This data type is not supported in Gemini API. */ +export declare interface PreTunedModel { + /** Output only. The name of the base model this PreTunedModel was tuned from. */ + baseModel?: string; + /** Optional. The source checkpoint id. If not specified, the default checkpoint will be used. */ + checkpointId?: string; + /** The resource name of the Model. E.g., a model resource name with a specified version id or alias: `projects/{project}/locations/{location}/models/{model}@{version_id}` `projects/{project}/locations/{location}/models/{model}@{alias}` Or, omit the version id to use the default version: `projects/{project}/locations/{location}/models/{model}` */ + tunedModelName?: string; +} + +/** Config for proactivity features. */ +export declare interface ProactivityConfig { + /** If enabled, the model can reject responding to the last prompt. For + example, this allows the model to ignore out of context speech or to stay + silent if the user did not make a request, yet. */ + proactiveAudio?: boolean; +} + +/** An image of the product. */ +export declare interface ProductImage { + /** An image of the product to be recontextualized. */ + productImage?: Image_2; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +declare type PromiseOrValue<T> = T | Promise<T>; + +/** A RagChunk includes the content of a chunk of a RagFile, and associated metadata. This data type is not supported in Gemini API. */ +export declare interface RagChunk { + /** If populated, represents where the chunk starts and ends in the document. */ + pageSpan?: RagChunkPageSpan; + /** The content of the chunk. */ + text?: string; +} + +/** Represents where the chunk starts and ends in the document. This data type is not supported in Gemini API. */ +export declare interface RagChunkPageSpan { + /** Page where chunk starts in the document. Inclusive. 1-indexed. */ + firstPage?: number; + /** Page where chunk ends in the document. Inclusive. 1-indexed. */ + lastPage?: number; +} + +/** Specifies the context retrieval config. This data type is not supported in Gemini API. */ +export declare interface RagRetrievalConfig { + /** Optional. Config for filters. */ + filter?: RagRetrievalConfigFilter; + /** Optional. Config for Hybrid Search. */ + hybridSearch?: RagRetrievalConfigHybridSearch; + /** Optional. Config for ranking and reranking. */ + ranking?: RagRetrievalConfigRanking; + /** Optional. The number of contexts to retrieve. */ + topK?: number; +} + +/** Config for filters. This data type is not supported in Gemini API. */ +export declare interface RagRetrievalConfigFilter { + /** Optional. String for metadata filtering. */ + metadataFilter?: string; + /** Optional. Only returns contexts with vector distance smaller than the threshold. */ + vectorDistanceThreshold?: number; + /** Optional. Only returns contexts with vector similarity larger than the threshold. */ + vectorSimilarityThreshold?: number; +} + +/** Config for Hybrid Search. This data type is not supported in Gemini API. */ +export declare interface RagRetrievalConfigHybridSearch { + /** Optional. Alpha value controls the weight between dense and sparse vector search results. The range is [0, 1], while 0 means sparse vector search only and 1 means dense vector search only. The default value is 0.5 which balances sparse and dense vector search equally. */ + alpha?: number; +} + +/** Config for ranking and reranking. This data type is not supported in Gemini API. */ +export declare interface RagRetrievalConfigRanking { + /** Optional. Config for LlmRanker. */ + llmRanker?: RagRetrievalConfigRankingLlmRanker; + /** Optional. Config for Rank Service. */ + rankService?: RagRetrievalConfigRankingRankService; +} + +/** Config for LlmRanker. This data type is not supported in Gemini API. */ +export declare interface RagRetrievalConfigRankingLlmRanker { + /** Optional. The model name used for ranking. See [Supported models](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference#supported-models). */ + modelName?: string; +} + +/** Config for Rank Service. This data type is not supported in Gemini API. */ +export declare interface RagRetrievalConfigRankingRankService { + /** Optional. The model name of the rank service. Format: `semantic-ranker-512@latest` */ + modelName?: string; +} + +declare class RateLimitError extends APIError<429, Headers> { +} + +/** A raw reference image. + + A raw reference image represents the base image to edit, provided by the user. + It can optionally be provided in addition to a mask reference image or + a style reference image. */ +export declare class RawReferenceImage { + /** The reference image for the editing operation. */ + referenceImage?: Image_2; + /** The id of the reference image. */ + referenceId?: number; + /** The type of the reference image. Only set by the SDK. */ + referenceType?: string; + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI(): ReferenceImageAPIInternal; +} + +declare type _ReadableStream_2<R = any> = NeverToAny<([0] extends [1 & _DOMReadableStream<R>] ? never : _DOMReadableStream<R>) | ([0] extends [1 & _ConditionalNodeReadableStream<R>] ? never : _ConditionalNodeReadableStream<R>)>; + +/** Marks the end of user activity. + + This can only be sent if automatic (i.e. server-side) activity detection is + disabled. */ +export declare interface RealtimeInputConfig { + /** If not set, automatic activity detection is enabled by default. If automatic voice detection is disabled, the client must send activity signals. */ + automaticActivityDetection?: AutomaticActivityDetection; + /** Defines what effect activity has. */ + activityHandling?: ActivityHandling; + /** Defines which input is included in the user's turn. */ + turnCoverage?: TurnCoverage; +} + +/** Configuration for recontextualizing an image. */ +export declare interface RecontextImageConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** Number of images to generate. */ + numberOfImages?: number; + /** The number of sampling steps. A higher value has better image + quality, while a lower value has better latency. */ + baseSteps?: number; + /** Cloud Storage URI used to store the generated images. */ + outputGcsUri?: string; + /** Random seed for image generation. */ + seed?: number; + /** Filter level for safety filtering. */ + safetyFilterLevel?: SafetyFilterLevel; + /** Whether allow to generate person images, and restrict to specific + ages. */ + personGeneration?: PersonGeneration; + /** Whether to add a SynthID watermark to the generated images. */ + addWatermark?: boolean; + /** MIME type of the generated image. */ + outputMimeType?: string; + /** Compression quality of the generated image (for ``image/jpeg`` + only). */ + outputCompressionQuality?: number; + /** Whether to use the prompt rewriting logic. */ + enhancePrompt?: boolean; + /** User specified labels to track billing usage. */ + labels?: Record<string, string>; +} + +/** The parameters for recontextualizing an image. */ +export declare interface RecontextImageParameters { + /** ID of the model to use. For a list of models, see `Google models + <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */ + model: string; + /** A set of source input(s) for image recontextualization. */ + source: RecontextImageSource; + /** Configuration for image recontextualization. */ + config?: RecontextImageConfig; +} + +/** The output images response. */ +export declare class RecontextImageResponse { + /** List of generated images. */ + generatedImages?: GeneratedImage[]; +} + +/** A set of source input(s) for image recontextualization. */ +export declare interface RecontextImageSource { + /** A text prompt for guiding the model during image + recontextualization. Not supported for Virtual Try-On. */ + prompt?: string; + /** Image of the person or subject who will be wearing the + product(s). */ + personImage?: Image_2; + /** A list of product images. */ + productImages?: ProductImage[]; +} + +export declare type ReferenceImage = RawReferenceImage | MaskReferenceImage | ControlReferenceImage | StyleReferenceImage | SubjectReferenceImage | ContentReferenceImage; + +/** Private class that represents a Reference image that is sent to API. */ +declare interface ReferenceImageAPIInternal { + /** The reference image for the editing operation. */ + referenceImage?: types.Image; + /** The id of the reference image. */ + referenceId?: number; + /** The type of the reference image. Only set by the SDK. */ + referenceType?: string; + /** Configuration for the mask reference image. */ + maskImageConfig?: types.MaskReferenceConfig; + /** Configuration for the control reference image. */ + controlImageConfig?: types.ControlReferenceConfig; + /** Configuration for the style reference image. */ + styleImageConfig?: types.StyleReferenceConfig; + /** Configuration for the subject reference image. */ + subjectImageConfig?: types.SubjectReferenceConfig; +} + +/** Used to override the default configuration. */ +export declare interface RegisterFilesConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; +} + +/** Generates the parameters for the private registerFiles method. */ +export declare interface RegisterFilesParameters { + /** + * The authentication object. + */ + auth?: any; + /** + * The Google Cloud Storage URIs to register. Example: `gs://bucket/object`. + */ + uris: string[]; + /** Used to override the default configuration. */ + config?: RegisterFilesConfig; +} + +/** Response for the _register file method. */ +export declare class RegisterFilesResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** The registered files. */ + files?: File_2[]; +} + +/** Represents a recorded session. */ +export declare interface ReplayFile { + replayId?: string; + interactions?: ReplayInteraction[]; +} + +/** Represents a single interaction, request and response in a replay. */ +export declare interface ReplayInteraction { + request?: ReplayRequest; + response?: ReplayResponse; +} + +/** Represents a single request in a replay. */ +export declare interface ReplayRequest { + method?: string; + url?: string; + headers?: Record<string, string>; + bodySegments?: Record<string, unknown>[]; +} + +/** Represents a single response in a replay. */ +export declare class ReplayResponse { + statusCode?: number; + headers?: Record<string, string>; + bodySegments?: Record<string, unknown>[]; + sdkResponseSegments?: Record<string, unknown>[]; +} + +/** ReplicatedVoiceConfig is used to configure replicated voice. */ +export declare interface ReplicatedVoiceConfig { + /** The mime type of the replicated voice. + */ + mimeType?: string; + /** The sample audio of the replicated voice. + + * @remarks Encoded as base64 string. */ + voiceSampleAudio?: string; +} + +/** + * The type for the first argument to `fetch`. + * + * https://developer.mozilla.org/docs/Web/API/Window/fetch#resource + */ +declare type _RequestInfo = Request | URL | string; + +/** + * An alias to the builtin `RequestInit` type so we can + * easily alias it in import statements if there are name clashes. + * + * https://developer.mozilla.org/docs/Web/API/RequestInit + */ +declare type _RequestInit = RequestInit; + +declare type RequestInits = NotAny<UndiciTypesRequestInit> | NotAny<UndiciRequestInit> | NotAny<BunRequestInit> | NotAny<NodeFetch2RequestInit> | NotAny<NodeFetch3RequestInit> | NotAny<RequestInit> | NotAny<FetchRequestInit>; + +declare type RequestOptions = { + /** + * The HTTP method for the request (e.g., 'get', 'post', 'put', 'delete'). + */ + method?: HTTPMethod; + /** + * The URL path for the request. + * + * @example "/v1/foo" + */ + path?: string; + /** + * Query parameters to include in the request URL. + */ + query?: object | undefined | null; + /** + * The request body. Can be a string, JSON object, FormData, or other supported types. + */ + body?: unknown; + /** + * HTTP headers to include with the request. Can be a Headers object, plain object, or array of tuples. + */ + headers?: HeadersLike; + /** + * The maximum number of times that the client will retry a request in case of a + * temporary failure, like a network error or a 5XX error from the server. + * + * @default 2 + */ + maxRetries?: number; + stream?: boolean | undefined; + /** + * The maximum amount of time (in milliseconds) that the client should wait for a response + * from the server before timing out a single request. + * + * @unit milliseconds + */ + timeout?: number; + /** + * Additional `RequestInit` options to be passed to the underlying `fetch` call. + * These options will be merged with the client's default fetch options. + */ + fetchOptions?: MergedRequestInit; + /** + * An AbortSignal that can be used to cancel the request. + */ + signal?: AbortSignal | undefined | null; + /** + * A unique key for this request to enable idempotency. + */ + idempotencyKey?: string; + /** + * Override the default base URL for this specific request. + */ + defaultBaseURL?: string | undefined; + __binaryResponse?: boolean | undefined; + __streamClass?: typeof Stream; +}; + +/** Resource scope. */ +export declare enum ResourceScope { + /** + * When setting base_url, this value configures resource scope to be the collection. + The resource name will not include api version, project, or location. + For example, if base_url is set to "https://aiplatform.googleapis.com", + then the resource name for a Model would be + "https://aiplatform.googleapis.com/publishers/google/models/gemini-3-pro-preview + */ + COLLECTION = "COLLECTION" +} + +/** Defines a retrieval tool that model can call to access external knowledge. This data type is not supported in Gemini API. */ +export declare interface Retrieval { + /** Optional. Deprecated. This option is no longer supported. */ + disableAttribution?: boolean; + /** Use data source powered by external API for grounding. */ + externalApi?: ExternalApi; + /** Set to use data source powered by Vertex AI Search. */ + vertexAiSearch?: VertexAISearch; + /** Set to use data source powered by Vertex RAG store. User data is uploaded via the VertexRagDataService. */ + vertexRagStore?: VertexRagStore; +} + +/** Retrieval config. + */ +export declare interface RetrievalConfig { + /** Optional. The location of the user. */ + latLng?: LatLng; + /** The language code of the user. */ + languageCode?: string; +} + +/** Metadata related to retrieval in the grounding flow. */ +export declare interface RetrievalMetadata { + /** Optional. Score indicating how likely information from Google Search could help answer the prompt. The score is in the range `[0, 1]`, where 0 is the least likely and 1 is the most likely. This score is only populated when Google Search grounding and dynamic retrieval is enabled. It will be compared to the threshold to determine whether to trigger Google Search. */ + googleSearchDynamicRetrievalScore?: number; +} + +/** Safety attributes of a GeneratedImage or the user-provided prompt. */ +export declare interface SafetyAttributes { + /** List of RAI categories. */ + categories?: string[]; + /** List of scores of each categories. */ + scores?: number[]; + /** Internal use only. */ + contentType?: string; +} + +/** Enum that controls the safety filter level for objectionable content. */ +export declare enum SafetyFilterLevel { + BLOCK_LOW_AND_ABOVE = "BLOCK_LOW_AND_ABOVE", + BLOCK_MEDIUM_AND_ABOVE = "BLOCK_MEDIUM_AND_ABOVE", + BLOCK_ONLY_HIGH = "BLOCK_ONLY_HIGH", + BLOCK_NONE = "BLOCK_NONE" +} + +/** Safety rating corresponding to the generated content. */ +export declare interface SafetyRating { + /** Output only. Indicates whether the content was filtered out because of this rating. */ + blocked?: boolean; + /** Output only. Harm category. */ + category?: HarmCategory; + /** Output only. The overwritten threshold for the safety category of Gemini 2.0 image out. If minors are detected in the output image, the threshold of each safety category will be overwritten if user sets a lower threshold. This field is not supported in Gemini API. */ + overwrittenThreshold?: HarmBlockThreshold; + /** Output only. Harm probability levels in the content. */ + probability?: HarmProbability; + /** Output only. Harm probability score. This field is not supported in Gemini API. */ + probabilityScore?: number; + /** Output only. Harm severity levels in the content. This field is not supported in Gemini API. */ + severity?: HarmSeverity; + /** Output only. Harm severity score. This field is not supported in Gemini API. */ + severityScore?: number; +} + +/** Safety settings. */ +export declare interface SafetySetting { + /** Required. Harm category. */ + category?: HarmCategory; + /** Optional. Specify if the threshold is used for probability or severity score. If not specified, the threshold is used for probability score. This field is not supported in Gemini API. */ + method?: HarmBlockMethod; + /** Required. The harm block threshold. */ + threshold?: HarmBlockThreshold; +} + +/** Scale of the generated music. */ +export declare enum Scale { + /** + * Default value. This value is unused. + */ + SCALE_UNSPECIFIED = "SCALE_UNSPECIFIED", + /** + * C major or A minor. + */ + C_MAJOR_A_MINOR = "C_MAJOR_A_MINOR", + /** + * Db major or Bb minor. + */ + D_FLAT_MAJOR_B_FLAT_MINOR = "D_FLAT_MAJOR_B_FLAT_MINOR", + /** + * D major or B minor. + */ + D_MAJOR_B_MINOR = "D_MAJOR_B_MINOR", + /** + * Eb major or C minor + */ + E_FLAT_MAJOR_C_MINOR = "E_FLAT_MAJOR_C_MINOR", + /** + * E major or Db minor. + */ + E_MAJOR_D_FLAT_MINOR = "E_MAJOR_D_FLAT_MINOR", + /** + * F major or D minor. + */ + F_MAJOR_D_MINOR = "F_MAJOR_D_MINOR", + /** + * Gb major or Eb minor. + */ + G_FLAT_MAJOR_E_FLAT_MINOR = "G_FLAT_MAJOR_E_FLAT_MINOR", + /** + * G major or E minor. + */ + G_MAJOR_E_MINOR = "G_MAJOR_E_MINOR", + /** + * Ab major or F minor. + */ + A_FLAT_MAJOR_F_MINOR = "A_FLAT_MAJOR_F_MINOR", + /** + * A major or Gb minor. + */ + A_MAJOR_G_FLAT_MINOR = "A_MAJOR_G_FLAT_MINOR", + /** + * Bb major or G minor. + */ + B_FLAT_MAJOR_G_MINOR = "B_FLAT_MAJOR_G_MINOR", + /** + * B major or Ab minor. + */ + B_MAJOR_A_FLAT_MINOR = "B_MAJOR_A_FLAT_MINOR" +} + +/** Schema is used to define the format of input/output data. + + Represents a select subset of an [OpenAPI 3.0 schema + object](https://spec.openapis.org/oas/v3.0.3#schema-object). More fields may + be added in the future as needed. */ +export declare interface Schema { + /** Optional. The value should be validated against any (one or more) of the subschemas in the list. */ + anyOf?: Schema[]; + /** Optional. Default value of the data. */ + default?: unknown; + /** Optional. The description of the data. */ + description?: string; + /** Optional. Possible values of the element of primitive type with enum format. Examples: 1. We can define direction as : {type:STRING, format:enum, enum:["EAST", NORTH", "SOUTH", "WEST"]} 2. We can define apartment number as : {type:INTEGER, format:enum, enum:["101", "201", "301"]} */ + enum?: string[]; + /** Optional. Example of the object. Will only populated when the object is the root. */ + example?: unknown; + /** Optional. The format of the data. Supported formats: for NUMBER type: "float", "double" for INTEGER type: "int32", "int64" for STRING type: "email", "byte", etc */ + format?: string; + /** Optional. SCHEMA FIELDS FOR TYPE ARRAY Schema of the elements of Type.ARRAY. */ + items?: Schema; + /** Optional. Maximum number of the elements for Type.ARRAY. */ + maxItems?: string; + /** Optional. Maximum length of the Type.STRING */ + maxLength?: string; + /** Optional. Maximum number of the properties for Type.OBJECT. */ + maxProperties?: string; + /** Optional. Maximum value of the Type.INTEGER and Type.NUMBER */ + maximum?: number; + /** Optional. Minimum number of the elements for Type.ARRAY. */ + minItems?: string; + /** Optional. SCHEMA FIELDS FOR TYPE STRING Minimum length of the Type.STRING */ + minLength?: string; + /** Optional. Minimum number of the properties for Type.OBJECT. */ + minProperties?: string; + /** Optional. SCHEMA FIELDS FOR TYPE INTEGER and NUMBER Minimum value of the Type.INTEGER and Type.NUMBER */ + minimum?: number; + /** Optional. Indicates if the value may be null. */ + nullable?: boolean; + /** Optional. Pattern of the Type.STRING to restrict a string to a regular expression. */ + pattern?: string; + /** Optional. SCHEMA FIELDS FOR TYPE OBJECT Properties of Type.OBJECT. */ + properties?: Record<string, Schema>; + /** Optional. The order of the properties. Not a standard field in open api spec. Only used to support the order of the properties. */ + propertyOrdering?: string[]; + /** Optional. Required properties of Type.OBJECT. */ + required?: string[]; + /** Optional. The title of the Schema. */ + title?: string; + /** Optional. The type of the data. */ + type?: Type; +} + +export declare type SchemaUnion = Schema | unknown; + +/** An image mask representing a brush scribble. */ +export declare interface ScribbleImage { + /** The brush scribble to guide segmentation. Valid for the interactive mode. */ + image?: Image_2; +} + +/** Google search entry point. */ +export declare interface SearchEntryPoint { + /** Optional. Web content snippet that can be embedded in a web page or an app webview. */ + renderedContent?: string; + /** Optional. Base64 encoded JSON representing array of tuple. + * @remarks Encoded as base64 string. */ + sdkBlob?: string; +} + +/** Segment of the content. */ +export declare interface Segment { + /** Output only. End index in the given Part, measured in bytes. Offset from the start of the Part, exclusive, starting at zero. */ + endIndex?: number; + /** Output only. The index of a Part object within its parent Content object. */ + partIndex?: number; + /** Output only. Start index in the given Part, measured in bytes. Offset from the start of the Part, inclusive, starting at zero. */ + startIndex?: number; + /** Output only. The text corresponding to the segment from the response. */ + text?: string; +} + +/** Configuration for segmenting an image. */ +export declare interface SegmentImageConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** The segmentation mode to use. */ + mode?: SegmentMode; + /** The maximum number of predictions to return up to, by top + confidence score. */ + maxPredictions?: number; + /** The confidence score threshold for the detections as a decimal + value. Only predictions with a confidence score higher than this + threshold will be returned. */ + confidenceThreshold?: number; + /** A decimal value representing how much dilation to apply to the + masks. 0 for no dilation. 1.0 means the masked area covers the whole + image. */ + maskDilation?: number; + /** The binary color threshold to apply to the masks. The threshold + can be set to a decimal value between 0 and 255 non-inclusive. + Set to -1 for no binary color thresholding. */ + binaryColorThreshold?: number; + /** User specified labels to track billing usage. */ + labels?: Record<string, string>; +} + +/** The parameters for segmenting an image. */ +export declare interface SegmentImageParameters { + /** ID of the model to use. For a list of models, see `Google models + <https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models>`_. */ + model: string; + /** A set of source input(s) for image segmentation. */ + source: SegmentImageSource; + /** Configuration for image segmentation. */ + config?: SegmentImageConfig; +} + +/** The output images response. */ +export declare class SegmentImageResponse { + /** List of generated image masks. + */ + generatedMasks?: GeneratedImageMask[]; +} + +/** A set of source input(s) for image segmentation. */ +export declare interface SegmentImageSource { + /** A text prompt for guiding the model during image segmentation. + Required for prompt mode and semantic mode, disallowed for other modes. */ + prompt?: string; + /** The image to be segmented. */ + image?: Image_2; + /** The brush scribble to guide segmentation. + Required for the interactive mode, disallowed for other modes. */ + scribbleImage?: ScribbleImage; +} + +/** Enum that represents the segmentation mode. */ +export declare enum SegmentMode { + FOREGROUND = "FOREGROUND", + BACKGROUND = "BACKGROUND", + PROMPT = "PROMPT", + SEMANTIC = "SEMANTIC", + INTERACTIVE = "INTERACTIVE" +} + +/** Parameters for sending a message within a chat session. + + These parameters are used with the `chat.sendMessage()` method. */ +export declare interface SendMessageParameters { + /** The message to send to the model. + + The SDK will combine all parts into a single 'user' content to send to + the model. + */ + message: PartListUnion; + /** Config for this specific request. + + Please note that the per-request config does not change the chat level + config, nor inherit from it. If you intend to use some values from the + chat's default config, you must explicitly copy them into this per-request + config. + */ + config?: GenerateContentConfig; +} + +/** + Represents a connection to the API. + + @experimental + */ +export declare class Session { + readonly conn: WebSocket_2; + private readonly apiClient; + constructor(conn: WebSocket_2, apiClient: ApiClient); + private tLiveClientContent; + private tLiveClienttToolResponse; + /** + Send a message over the established connection. + + @param params - Contains two **optional** properties, `turns` and + `turnComplete`. + + - `turns` will be converted to a `Content[]` + - `turnComplete: true` [default] indicates that you are done sending + content and expect a response. If `turnComplete: false`, the server + will wait for additional messages before starting generation. + + @experimental + + @remarks + There are two ways to send messages to the live API: + `sendClientContent` and `sendRealtimeInput`. + + `sendClientContent` messages are added to the model context **in order**. + Having a conversation using `sendClientContent` messages is roughly + equivalent to using the `Chat.sendMessageStream`, except that the state of + the `chat` history is stored on the API server instead of locally. + + Because of `sendClientContent`'s order guarantee, the model cannot respons + as quickly to `sendClientContent` messages as to `sendRealtimeInput` + messages. This makes the biggest difference when sending objects that have + significant preprocessing time (typically images). + + The `sendClientContent` message sends a `Content[]` + which has more options than the `Blob` sent by `sendRealtimeInput`. + + So the main use-cases for `sendClientContent` over `sendRealtimeInput` are: + + - Sending anything that can't be represented as a `Blob` (text, + `sendClientContent({turns="Hello?"}`)). + - Managing turns when not using audio input and voice activity detection. + (`sendClientContent({turnComplete:true})` or the short form + `sendClientContent()`) + - Prefilling a conversation context + ``` + sendClientContent({ + turns: [ + Content({role:user, parts:...}), + Content({role:user, parts:...}), + ... + ] + }) + ``` + @experimental + */ + sendClientContent(params: types.LiveSendClientContentParameters): void; + /** + Send a realtime message over the established connection. + + @param params - Contains one property, `media`. + + - `media` will be converted to a `Blob` + + @experimental + + @remarks + Use `sendRealtimeInput` for realtime audio chunks and video frames (images). + + With `sendRealtimeInput` the api will respond to audio automatically + based on voice activity detection (VAD). + + `sendRealtimeInput` is optimized for responsivness at the expense of + deterministic ordering guarantees. Audio and video tokens are to the + context when they become available. + + Note: The Call signature expects a `Blob` object, but only a subset + of audio and image mimetypes are allowed. + */ + sendRealtimeInput(params: types.LiveSendRealtimeInputParameters): void; + /** + Send a function response message over the established connection. + + @param params - Contains property `functionResponses`. + + - `functionResponses` will be converted to a `functionResponses[]` + + @remarks + Use `sendFunctionResponse` to reply to `LiveServerToolCall` from the server. + + Use {@link types.LiveConnectConfig#tools} to configure the callable functions. + + @experimental + */ + sendToolResponse(params: types.LiveSendToolResponseParameters): void; + /** + Terminates the WebSocket connection. + + @experimental + + @example + ```ts + let model: string; + if (GOOGLE_GENAI_USE_VERTEXAI) { + model = 'gemini-2.0-flash-live-preview-04-09'; + } else { + model = 'gemini-live-2.5-flash-preview'; + } + const session = await ai.live.connect({ + model: model, + config: { + responseModalities: [Modality.AUDIO], + } + }); + + session.close(); + ``` + */ + close(): void; +} + +/** Configuration of session resumption mechanism. + + Included in `LiveConnectConfig.session_resumption`. If included server + will send `LiveServerSessionResumptionUpdate` messages. */ +export declare interface SessionResumptionConfig { + /** Session resumption handle of previous session (session to restore). + + If not present new session will be started. */ + handle?: string; + /** If set the server will send `last_consumed_client_message_index` in the `session_resumption_update` messages to allow for transparent reconnections. */ + transparent?: boolean; +} + +/** + * Overrides the base URLs for the Gemini API and Vertex AI API. + * + * @remarks This function should be called before initializing the SDK. If the + * base URLs are set after initializing the SDK, the base URLs will not be + * updated. Base URLs provided in the HttpOptions will also take precedence over + * URLs set here. + * + * @example + * ```ts + * import {GoogleGenAI, setDefaultBaseUrls} from '@google/genai'; + * // Override the base URL for the Gemini API. + * setDefaultBaseUrls({geminiUrl:'https://gemini.google.com'}); + * + * // Override the base URL for the Vertex AI API. + * setDefaultBaseUrls({vertexUrl: 'https://vertexai.googleapis.com'}); + * + * const ai = new GoogleGenAI({apiKey: 'GEMINI_API_KEY'}); + * ``` + */ +export declare function setDefaultBaseUrls(baseUrlParams: BaseUrlParameters): void; + +/** Config for `response` parameter. */ +export declare class SingleEmbedContentResponse { + /** The response to the request. + */ + embedding?: ContentEmbedding; + /** The error encountered while processing the request. + */ + tokenCount?: string; +} + +/** Context window will be truncated by keeping only suffix of it. + + Context window will always be cut at start of USER role turn. System + instructions and `BidiGenerateContentSetup.prefix_turns` will not be + subject to the sliding window mechanism, they will always stay at the + beginning of context window. */ +export declare interface SlidingWindow { + /** Session reduction target -- how many tokens we should keep. Window shortening operation has some latency costs, so we should avoid running it on every turn. Should be < trigger_tokens. If not set, trigger_tokens/2 is assumed. */ + targetTokens?: string; +} + +/** Configuration for a single speaker in a multi speaker setup. */ +export declare interface SpeakerVoiceConfig { + /** Required. The name of the speaker. This should be the same as the speaker name used in the prompt. */ + speaker?: string; + /** Required. The configuration for the voice of this speaker. */ + voiceConfig?: VoiceConfig; +} + +export declare interface SpeechConfig { + /** Configuration for the voice of the response. */ + voiceConfig?: VoiceConfig; + /** Optional. Language code (ISO 639. e.g. en-US) for the speech synthesization. */ + languageCode?: string; + /** The configuration for a multi-speaker text-to-speech request. This field is mutually exclusive with `voice_config`. */ + multiSpeakerVoiceConfig?: MultiSpeakerVoiceConfig; +} + +/** + * The configuration for speech interaction. + */ +declare interface SpeechConfig_2 { + /** + * The language of the speech. + */ + language?: string; + /** + * The speaker's name, it should match the speaker name given in the prompt. + */ + speaker?: string; + /** + * The voice of the speaker. + */ + voice?: string; +} + +export declare type SpeechConfigUnion = SpeechConfig | string; + +/** Start of speech sensitivity. */ +export declare enum StartSensitivity { + /** + * The default is START_SENSITIVITY_LOW. + */ + START_SENSITIVITY_UNSPECIFIED = "START_SENSITIVITY_UNSPECIFIED", + /** + * Automatic detection will detect the start of speech more often. + */ + START_SENSITIVITY_HIGH = "START_SENSITIVITY_HIGH", + /** + * Automatic detection will detect the start of speech less often. + */ + START_SENSITIVITY_LOW = "START_SENSITIVITY_LOW" +} + +declare class Stream<Item> implements AsyncIterable<Item> { + private iterator; + controller: AbortController; + private client; + constructor(iterator: () => AsyncIterator<Item>, controller: AbortController, client?: BaseGeminiNextGenAPIClient); + static fromSSEResponse<Item>(response: Response, controller: AbortController, client?: BaseGeminiNextGenAPIClient): Stream<Item>; + /** + * Generates a Stream from a newline-separated ReadableStream + * where each item is a JSON value. + */ + static fromReadableStream<Item>(readableStream: _ReadableStream_2, controller: AbortController, client?: BaseGeminiNextGenAPIClient): Stream<Item>; + [Symbol.asyncIterator](): AsyncIterator<Item>; + /** + * Splits the stream into two streams which can be + * independently read from at different speeds. + */ + tee(): [Stream<Item>, Stream<Item>]; + /** + * Converts this stream to a newline-separated ReadableStream of + * JSON stringified values in the stream + * which can be turned back into a Stream with `Stream.fromReadableStream()`. + */ + toReadableStream(): _ReadableStream_2; +} + +/** User provided string values assigned to a single metadata key. This data type is not supported in Vertex AI. */ +export declare interface StringList { + /** The string values of the metadata to store. */ + values?: string[]; +} + +/** Configuration for a Style reference image. */ +export declare interface StyleReferenceConfig { + /** A text description of the style to use for the generated image. */ + styleDescription?: string; +} + +/** A style reference image. + + This encapsulates a style reference image provided by the user, and + additionally optional config parameters for the style reference image. + + A raw reference image can also be provided as a destination for the style to + be applied to. */ +export declare class StyleReferenceImage { + /** The reference image for the editing operation. */ + referenceImage?: Image_2; + /** The id of the reference image. */ + referenceId?: number; + /** The type of the reference image. Only set by the SDK. */ + referenceType?: string; + /** Configuration for the style reference image. */ + config?: StyleReferenceConfig; + /** Internal method to convert to ReferenceImageAPIInternal. */ + toReferenceImageAPI(): ReferenceImageAPIInternal; +} + +/** Configuration for a Subject reference image. */ +export declare interface SubjectReferenceConfig { + /** The subject type of a subject reference image. */ + subjectType?: SubjectReferenceType; + /** Subject description for the image. */ + subjectDescription?: string; +} + +/** A subject reference image. + + This encapsulates a subject reference image provided by the user, and + additionally optional config parameters for the subject reference image. + + A raw reference image can also be provided as a destination for the subject to + be applied to. */ +export declare class SubjectReferenceImage { + /** The reference image for the editing operation. */ + referenceImage?: Image_2; + /** The id of the reference image. */ + referenceId?: number; + /** The type of the reference image. Only set by the SDK. */ + referenceType?: string; + /** Configuration for the subject reference image. */ + config?: SubjectReferenceConfig; + toReferenceImageAPI(): ReferenceImageAPIInternal; +} + +/** Enum representing the subject type of a subject reference image. */ +export declare enum SubjectReferenceType { + SUBJECT_TYPE_DEFAULT = "SUBJECT_TYPE_DEFAULT", + SUBJECT_TYPE_PERSON = "SUBJECT_TYPE_PERSON", + SUBJECT_TYPE_ANIMAL = "SUBJECT_TYPE_ANIMAL", + SUBJECT_TYPE_PRODUCT = "SUBJECT_TYPE_PRODUCT" +} + +/** Hyperparameters for SFT. This data type is not supported in Gemini API. */ +export declare interface SupervisedHyperParameters { + /** Optional. Adapter size for tuning. */ + adapterSize?: AdapterSize; + /** Optional. Batch size for tuning. This feature is only available for open source models. */ + batchSize?: string; + /** Optional. Number of complete passes the model makes over the entire training dataset during training. */ + epochCount?: string; + /** Optional. Learning rate for tuning. Mutually exclusive with `learning_rate_multiplier`. This feature is only available for open source models. */ + learningRate?: number; + /** Optional. Multiplier for adjusting the default learning rate. Mutually exclusive with `learning_rate`. This feature is only available for 1P models. */ + learningRateMultiplier?: number; +} + +/** Dataset distribution for Supervised Tuning. This data type is not supported in Gemini API. */ +export declare interface SupervisedTuningDatasetDistribution { + /** Output only. Sum of a given population of values that are billable. */ + billableSum?: string; + /** Output only. Defines the histogram bucket. */ + buckets?: SupervisedTuningDatasetDistributionDatasetBucket[]; + /** Output only. The maximum of the population values. */ + max?: number; + /** Output only. The arithmetic mean of the values in the population. */ + mean?: number; + /** Output only. The median of the values in the population. */ + median?: number; + /** Output only. The minimum of the population values. */ + min?: number; + /** Output only. The 5th percentile of the values in the population. */ + p5?: number; + /** Output only. The 95th percentile of the values in the population. */ + p95?: number; + /** Output only. Sum of a given population of values. */ + sum?: string; +} + +/** Dataset bucket used to create a histogram for the distribution given a population of values. This data type is not supported in Gemini API. */ +export declare interface SupervisedTuningDatasetDistributionDatasetBucket { + /** Output only. Number of values in the bucket. */ + count?: number; + /** Output only. Left bound of the bucket. */ + left?: number; + /** Output only. Right bound of the bucket. */ + right?: number; +} + +/** Tuning data statistics for Supervised Tuning. This data type is not supported in Gemini API. */ +export declare interface SupervisedTuningDataStats { + /** Output only. For each index in `truncated_example_indices`, the user-facing reason why the example was dropped. */ + droppedExampleReasons?: string[]; + /** Output only. Number of billable characters in the tuning dataset. */ + totalBillableCharacterCount?: string; + /** Output only. Number of billable tokens in the tuning dataset. */ + totalBillableTokenCount?: string; + /** Output only. The number of examples in the dataset that have been dropped. An example can be dropped for reasons including: too many tokens, contains an invalid image, contains too many images, etc. */ + totalTruncatedExampleCount?: string; + /** Output only. Number of tuning characters in the tuning dataset. */ + totalTuningCharacterCount?: string; + /** Output only. A partial sample of the indices (starting from 1) of the dropped examples. */ + truncatedExampleIndices?: string[]; + /** Output only. Number of examples in the tuning dataset. */ + tuningDatasetExampleCount?: string; + /** Output only. Number of tuning steps for this Tuning Job. */ + tuningStepCount?: string; + /** Output only. Sample user messages in the training dataset uri. */ + userDatasetExamples?: Content[]; + /** Output only. Dataset distributions for the user input tokens. */ + userInputTokenDistribution?: SupervisedTuningDatasetDistribution; + /** Output only. Dataset distributions for the messages per example. */ + userMessagePerExampleDistribution?: SupervisedTuningDatasetDistribution; + /** Output only. Dataset distributions for the user output tokens. */ + userOutputTokenDistribution?: SupervisedTuningDatasetDistribution; +} + +/** Supervised tuning spec for tuning. */ +export declare interface SupervisedTuningSpec { + /** Optional. If set to true, disable intermediate checkpoints for SFT and only the last checkpoint will be exported. Otherwise, enable intermediate checkpoints for SFT. Default is false. */ + exportLastCheckpointOnly?: boolean; + /** Optional. Hyperparameters for SFT. */ + hyperParameters?: SupervisedHyperParameters; + /** Required. Training dataset used for tuning. The dataset can be specified as either a Cloud Storage path to a JSONL file or as the resource name of a Vertex Multimodal Dataset. */ + trainingDatasetUri?: string; + /** Tuning mode. */ + tuningMode?: TuningMode; + /** Optional. Validation dataset used for tuning. The dataset can be specified as either a Cloud Storage path to a JSONL file or as the resource name of a Vertex Multimodal Dataset. */ + validationDatasetUri?: string; +} + +export declare interface TestTableFile { + comment?: string; + testMethod?: string; + parameterNames?: string[]; + testTable?: TestTableItem[]; +} + +export declare interface TestTableItem { + /** The name of the test. This is used to derive the replay id. */ + name?: string; + /** The parameters to the test. Use pydantic models. */ + parameters?: Record<string, unknown>; + /** Expects an exception for MLDev matching the string. */ + exceptionIfMldev?: string; + /** Expects an exception for Vertex matching the string. */ + exceptionIfVertex?: string; + /** Use if you don't want to use the default replay id which is derived from the test name. */ + overrideReplayId?: string; + /** True if the parameters contain an unsupported union type. This test will be skipped for languages that do not support the union type. */ + hasUnion?: boolean; + /** When set to a reason string, this test will be skipped in the API mode. Use this flag for tests that can not be reproduced with the real API. E.g. a test that deletes a resource. */ + skipInApiMode?: string; + /** Keys to ignore when comparing the request and response. This is useful for tests that are not deterministic. */ + ignoreKeys?: string[]; +} + +/** + * A text content block. + */ +declare interface TextContent { + type: 'text'; + /** + * Citation information for model-generated content. + */ + annotations?: Array<Annotation>; + /** + * The text content. + */ + text?: string; +} + +/** The thinking features configuration. */ +export declare interface ThinkingConfig { + /** Indicates whether to include thoughts in the response. If true, thoughts are returned only if the model supports thought and thoughts are available. + */ + includeThoughts?: boolean; + /** Indicates the thinking budget in tokens. 0 is DISABLED. -1 is AUTOMATIC. The default values and allowed ranges are model dependent. + */ + thinkingBudget?: number; + /** Optional. The number of thoughts tokens that the model should generate. */ + thinkingLevel?: ThinkingLevel; +} + +/** The number of thoughts tokens that the model should generate. */ +export declare enum ThinkingLevel { + /** + * Unspecified thinking level. + */ + THINKING_LEVEL_UNSPECIFIED = "THINKING_LEVEL_UNSPECIFIED", + /** + * Low thinking level. + */ + LOW = "LOW", + /** + * Medium thinking level. + */ + MEDIUM = "MEDIUM", + /** + * High thinking level. + */ + HIGH = "HIGH", + /** + * MINIMAL thinking level. + */ + MINIMAL = "MINIMAL" +} + +declare type ThinkingLevel_2 = 'minimal' | 'low' | 'medium' | 'high'; + +/** + * A thought content block. + */ +declare interface ThoughtContent { + type: 'thought'; + /** + * Signature to match the backend source to be part of the generation. + */ + signature?: string; + /** + * A summary of the thought. + */ + summary?: Array<TextContent | ImageContent>; +} + +export declare class Tokens extends BaseModule { + private readonly apiClient; + constructor(apiClient: ApiClient); + /** + * Creates an ephemeral auth token resource. + * + * @experimental + * + * @remarks + * Ephemeral auth tokens is only supported in the Gemini Developer API. + * It can be used for the session connection to the Live constrained API. + * Support in v1alpha only. + * + * @param params - The parameters for the create request. + * @return The created auth token. + * + * @example + * ```ts + * const ai = new GoogleGenAI({ + * apiKey: token.name, + * httpOptions: { apiVersion: 'v1alpha' } // Support in v1alpha only. + * }); + * + * // Case 1: If LiveEphemeralParameters is unset, unlock LiveConnectConfig + * // when using the token in Live API sessions. Each session connection can + * // use a different configuration. + * const config: CreateAuthTokenConfig = { + * uses: 3, + * expireTime: '2025-05-01T00:00:00Z', + * } + * const token = await ai.tokens.create(config); + * + * // Case 2: If LiveEphemeralParameters is set, lock all fields in + * // LiveConnectConfig when using the token in Live API sessions. For + * // example, changing `outputAudioTranscription` in the Live API + * // connection will be ignored by the API. + * const config: CreateAuthTokenConfig = + * uses: 3, + * expireTime: '2025-05-01T00:00:00Z', + * LiveEphemeralParameters: { + * model: 'gemini-2.0-flash-001', + * config: { + * 'responseModalities': ['AUDIO'], + * 'systemInstruction': 'Always answer in English.', + * } + * } + * } + * const token = await ai.tokens.create(config); + * + * // Case 3: If LiveEphemeralParameters is set and lockAdditionalFields is + * // set, lock LiveConnectConfig with set and additional fields (e.g. + * // responseModalities, systemInstruction, temperature in this example) when + * // using the token in Live API sessions. + * const config: CreateAuthTokenConfig = + * uses: 3, + * expireTime: '2025-05-01T00:00:00Z', + * LiveEphemeralParameters: { + * model: 'gemini-2.0-flash-001', + * config: { + * 'responseModalities': ['AUDIO'], + * 'systemInstruction': 'Always answer in English.', + * } + * }, + * lockAdditionalFields: ['temperature'], + * } + * const token = await ai.tokens.create(config); + * + * // Case 4: If LiveEphemeralParameters is set and lockAdditionalFields is + * // empty array, lock LiveConnectConfig with set fields (e.g. + * // responseModalities, systemInstruction in this example) when using the + * // token in Live API sessions. + * const config: CreateAuthTokenConfig = + * uses: 3, + * expireTime: '2025-05-01T00:00:00Z', + * LiveEphemeralParameters: { + * model: 'gemini-2.0-flash-001', + * config: { + * 'responseModalities': ['AUDIO'], + * 'systemInstruction': 'Always answer in English.', + * } + * }, + * lockAdditionalFields: [], + * } + * const token = await ai.tokens.create(config); + * ``` + */ + create(params: types.CreateAuthTokenParameters): Promise<types.AuthToken>; +} + +/** Tokens info with a list of tokens and the corresponding list of token ids. */ +export declare interface TokensInfo { + /** Optional fields for the role from the corresponding Content. */ + role?: string; + /** A list of token ids from the input. */ + tokenIds?: string[]; + /** A list of tokens from the input. + * @remarks Encoded as base64 string. */ + tokens?: string[]; +} + +/** Tool details of a tool that the model may use to generate a response. */ +export declare interface Tool { + /** Optional. Retrieval tool type. System will always execute the provided retrieval tool(s) to get external knowledge to answer the prompt. Retrieval results are presented to the model for generation. This field is not supported in Gemini API. */ + retrieval?: Retrieval; + /** Optional. Tool to support the model interacting directly with the + computer. If enabled, it automatically populates computer-use specific + Function Declarations. */ + computerUse?: ComputerUse; + /** Optional. Tool to retrieve knowledge from the File Search Stores. */ + fileSearch?: FileSearch; + /** Optional. CodeExecution tool type. Enables the model to execute code as part of generation. */ + codeExecution?: ToolCodeExecution; + /** Optional. Tool to support searching public web data, powered by Vertex AI Search and Sec4 compliance. This field is not supported in Gemini API. */ + enterpriseWebSearch?: EnterpriseWebSearch; + /** Optional. Function tool type. One or more function declarations to be passed to the model along with the current user query. Model may decide to call a subset of these functions by populating FunctionCall in the response. User should provide a FunctionResponse for each function call in the next turn. Based on the function responses, Model will generate the final response back to the user. Maximum 512 function declarations can be provided. */ + functionDeclarations?: FunctionDeclaration[]; + /** Optional. GoogleMaps tool type. Tool to support Google Maps in Model. */ + googleMaps?: GoogleMaps; + /** Optional. GoogleSearch tool type. Tool to support Google Search in Model. Powered by Google. */ + googleSearch?: GoogleSearch; + /** Optional. Specialized retrieval tool that is powered by Google Search. */ + googleSearchRetrieval?: GoogleSearchRetrieval; + /** Optional. Tool to support URL context retrieval. */ + urlContext?: UrlContext; +} + +/** + * A tool that can be used by the model. + */ +declare type Tool_2 = Function_2 | Tool_2.GoogleSearch | Tool_2.CodeExecution | Tool_2.URLContext | Tool_2.ComputerUse | Tool_2.MCPServer | Tool_2.FileSearch; + +declare namespace Tool_2 { + /** + * A tool that can be used by the model to search Google. + */ + interface GoogleSearch { + type: 'google_search'; + } + /** + * A tool that can be used by the model to execute code. + */ + interface CodeExecution { + type: 'code_execution'; + } + /** + * A tool that can be used by the model to fetch URL context. + */ + interface URLContext { + type: 'url_context'; + } + /** + * A tool that can be used by the model to interact with the computer. + */ + interface ComputerUse { + type: 'computer_use'; + /** + * The environment being operated. + */ + environment?: 'browser'; + /** + * The list of predefined functions that are excluded from the model call. + */ + excludedPredefinedFunctions?: Array<string>; + } + /** + * A MCPServer is a server that can be called by the model to perform actions. + */ + interface MCPServer { + type: 'mcp_server'; + /** + * The allowed tools. + */ + allowed_tools?: Array<InteractionsAPI.AllowedTools>; + /** + * Optional: Fields for authentication headers, timeouts, etc., if needed. + */ + headers?: { + [key: string]: string; + }; + /** + * The name of the MCPServer. + */ + name?: string; + /** + * The full URL for the MCPServer endpoint. + * Example: "https://api.example.com/mcp" + */ + url?: string; + } + /** + * A tool that can be used by the model to search files. + */ + interface FileSearch { + type: 'file_search'; + /** + * The file search store names to search. + */ + file_search_store_names?: Array<string>; + /** + * Metadata filter to apply to the semantic retrieval documents and chunks. + */ + metadata_filter?: string; + /** + * The number of semantic retrieval chunks to retrieve. + */ + top_k?: number; + } +} + +/** + * The configuration for tool choice. + */ +declare type ToolChoice = ToolChoiceType | ToolChoiceConfig; + +declare interface ToolChoiceConfig { + /** + * The configuration for allowed tools. + */ + allowed_tools?: AllowedTools; +} + +declare type ToolChoiceType = 'auto' | 'any' | 'none' | 'validated'; + +/** Tool that executes code generated by the model, and automatically returns the result to the model. See also [ExecutableCode]and [CodeExecutionResult] which are input and output to this tool. This data type is not supported in Gemini API. */ +export declare interface ToolCodeExecution { +} + +/** Tool config. + + This config is shared for all tools provided in the request. */ +export declare interface ToolConfig { + /** Optional. Retrieval config. */ + retrievalConfig?: RetrievalConfig; + /** Optional. Function calling config. */ + functionCallingConfig?: FunctionCallingConfig; +} + +export declare type ToolListUnion = ToolUnion[]; + +export declare type ToolUnion = Tool | CallableTool; + +/** Output only. The traffic type for this request. This enum is not supported in Gemini API. */ +export declare enum TrafficType { + /** + * Unspecified request traffic type. + */ + TRAFFIC_TYPE_UNSPECIFIED = "TRAFFIC_TYPE_UNSPECIFIED", + /** + * The request was processed using Pay-As-You-Go quota. + */ + ON_DEMAND = "ON_DEMAND", + /** + * Type for Provisioned Throughput traffic. + */ + PROVISIONED_THROUGHPUT = "PROVISIONED_THROUGHPUT" +} + +/** Audio transcription in Server Conent. */ +export declare interface Transcription { + /** Transcription text. + */ + text?: string; + /** The bool indicates the end of the transcription. + */ + finished?: boolean; +} + +/** TunedModel for the Tuned Model of a Tuning Job. */ +export declare interface TunedModel { + /** Output only. The resource name of the TunedModel. + Format: `projects/{project}/locations/{location}/models/{model}@{version_id}` + When tuning from a base model, the version_id will be 1. + For continuous tuning, the version id will be incremented by 1 from the + last version id in the parent model. E.g., `projects/{project}/locations/{location}/models/{model}@{last_version_id + 1}` + */ + model?: string; + /** Output only. A resource name of an Endpoint. + Format: `projects/{project}/locations/{location}/endpoints/{endpoint}`. + */ + endpoint?: string; + /** The checkpoints associated with this TunedModel. + This field is only populated for tuning jobs that enable intermediate + checkpoints. */ + checkpoints?: TunedModelCheckpoint[]; +} + +/** TunedModelCheckpoint for the Tuned Model of a Tuning Job. */ +export declare interface TunedModelCheckpoint { + /** The ID of the checkpoint. + */ + checkpointId?: string; + /** The epoch of the checkpoint. + */ + epoch?: string; + /** The step of the checkpoint. + */ + step?: string; + /** The Endpoint resource name that the checkpoint is deployed to. + Format: `projects/{project}/locations/{location}/endpoints/{endpoint}`. + */ + endpoint?: string; +} + +/** A tuned machine learning model. */ +export declare interface TunedModelInfo { + /** ID of the base model that you want to tune. */ + baseModel?: string; + /** Date and time when the base model was created. */ + createTime?: string; + /** Date and time when the base model was last updated. */ + updateTime?: string; +} + +/** Supervised fine-tuning training dataset. */ +export declare interface TuningDataset { + /** GCS URI of the file containing training dataset in JSONL format. */ + gcsUri?: string; + /** The resource name of the Vertex Multimodal Dataset that is used as training dataset. Example: 'projects/my-project-id-or-number/locations/my-location/datasets/my-dataset-id'. */ + vertexDatasetResource?: string; + /** Inline examples with simple input/output text. */ + examples?: TuningExample[]; +} + +/** The tuning data statistic values for TuningJob. This data type is not supported in Gemini API. */ +export declare interface TuningDataStats { + /** Output only. Statistics for distillation. */ + distillationDataStats?: DistillationDataStats; + /** Output only. Statistics for preference optimization. */ + preferenceOptimizationDataStats?: PreferenceOptimizationDataStats; + /** The SFT Tuning data stats. */ + supervisedTuningDataStats?: SupervisedTuningDataStats; +} + +/** A single example for tuning. This data type is not supported in Vertex AI. */ +export declare interface TuningExample { + /** Required. The expected model output. */ + output?: string; + /** Optional. Text model input. */ + textInput?: string; +} + +/** A tuning job. */ +export declare interface TuningJob { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** Output only. Identifier. Resource name of a TuningJob. Format: `projects/{project}/locations/{location}/tuningJobs/{tuning_job}` */ + name?: string; + /** Output only. The detailed state of the job. */ + state?: JobState; + /** Output only. Time when the TuningJob was created. */ + createTime?: string; + /** Output only. Time when the TuningJob for the first time entered the `JOB_STATE_RUNNING` state. */ + startTime?: string; + /** Output only. Time when the TuningJob entered any of the following JobStates: `JOB_STATE_SUCCEEDED`, `JOB_STATE_FAILED`, `JOB_STATE_CANCELLED`, `JOB_STATE_EXPIRED`. */ + endTime?: string; + /** Output only. Time when the TuningJob was most recently updated. */ + updateTime?: string; + /** Output only. Only populated when job's state is `JOB_STATE_FAILED` or `JOB_STATE_CANCELLED`. */ + error?: GoogleRpcStatus; + /** Optional. The description of the TuningJob. */ + description?: string; + /** The base model that is being tuned. See [Supported models](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/tuning#supported_models). */ + baseModel?: string; + /** Output only. The tuned model resources associated with this TuningJob. */ + tunedModel?: TunedModel; + /** The pre-tuned model for continuous tuning. */ + preTunedModel?: PreTunedModel; + /** Tuning Spec for Supervised Fine Tuning. */ + supervisedTuningSpec?: SupervisedTuningSpec; + /** Tuning Spec for Preference Optimization. */ + preferenceOptimizationSpec?: PreferenceOptimizationSpec; + /** Tuning Spec for Distillation. */ + distillationSpec?: DistillationSpec; + /** Output only. The tuning data statistics associated with this TuningJob. */ + tuningDataStats?: TuningDataStats; + /** Customer-managed encryption key options for a TuningJob. If this is set, then all resources created by the TuningJob will be encrypted with the provided encryption key. */ + encryptionSpec?: EncryptionSpec; + /** Tuning Spec for open sourced and third party Partner models. */ + partnerModelTuningSpec?: PartnerModelTuningSpec; + /** Optional. The user-provided path to custom model weights. Set this field to tune a custom model. The path must be a Cloud Storage directory that contains the model weights in .safetensors format along with associated model metadata files. If this field is set, the base_model field must still be set to indicate which base model the custom model is derived from. This feature is only available for open source models. */ + customBaseModel?: string; + /** Output only. The Experiment associated with this TuningJob. */ + experiment?: string; + /** Optional. The labels with user-defined metadata to organize TuningJob and generated resources such as Model and Endpoint. Label keys and values can be no longer than 64 characters (Unicode codepoints), can only contain lowercase letters, numeric characters, underscores and dashes. International characters are allowed. See https://goo.gl/xmQnxf for more information and examples of labels. */ + labels?: Record<string, string>; + /** Optional. Cloud Storage path to the directory where tuning job outputs are written to. This field is only available and required for open source models. */ + outputUri?: string; + /** Output only. The resource name of the PipelineJob associated with the TuningJob. Format: `projects/{project}/locations/{location}/pipelineJobs/{pipeline_job}`. */ + pipelineJob?: string; + /** The service account that the tuningJob workload runs as. If not specified, the Vertex AI Secure Fine-Tuned Service Agent in the project will be used. See https://cloud.google.com/iam/docs/service-agents#vertex-ai-secure-fine-tuning-service-agent Users starting the pipeline must have the `iam.serviceAccounts.actAs` permission on this service account. */ + serviceAccount?: string; + /** Optional. The display name of the TunedModel. The name can be up to 128 characters long and can consist of any UTF-8 characters. For continuous tuning, tuned_model_display_name will by default use the same display name as the pre-tuned model. If a new display name is provided, the tuning job will create a new model instead of a new version. */ + tunedModelDisplayName?: string; + /** Tuning Spec for Veo Tuning. */ + veoTuningSpec?: VeoTuningSpec; +} + +/** Enum representing the tuning method. */ +export declare enum TuningMethod { + /** + * Supervised fine tuning. + */ + SUPERVISED_FINE_TUNING = "SUPERVISED_FINE_TUNING", + /** + * Preference optimization tuning. + */ + PREFERENCE_TUNING = "PREFERENCE_TUNING", + /** + * Distillation tuning. + */ + DISTILLATION = "DISTILLATION" +} + +/** Tuning mode. This enum is not supported in Gemini API. */ +export declare enum TuningMode { + /** + * Tuning mode is unspecified. + */ + TUNING_MODE_UNSPECIFIED = "TUNING_MODE_UNSPECIFIED", + /** + * Full fine-tuning mode. + */ + TUNING_MODE_FULL = "TUNING_MODE_FULL", + /** + * PEFT adapter tuning mode. + */ + TUNING_MODE_PEFT_ADAPTER = "TUNING_MODE_PEFT_ADAPTER" +} + +/** A long-running operation. */ +export declare interface TuningOperation { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`. */ + name?: string; + /** Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata. Any method that returns a long-running operation should document the metadata type, if any. */ + metadata?: Record<string, unknown>; + /** If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available. */ + done?: boolean; + /** The error result of the operation in case of failure or cancellation. */ + error?: Record<string, unknown>; +} + +declare class Tunings extends BaseModule { + private readonly apiClient; + constructor(apiClient: ApiClient); + /** + * Lists tuning jobs. + * + * @param params - The parameters for the list request. + * @return - A pager of tuning jobs. + * + * @example + * ```ts + * const tuningJobs = await ai.tunings.list({config: {'pageSize': 2}}); + * for await (const tuningJob of tuningJobs) { + * console.log(tuningJob); + * } + * ``` + */ + list: (params?: types.ListTuningJobsParameters) => Promise<Pager<types.TuningJob>>; + /** + * Gets a TuningJob. + * + * @param name - The resource name of the tuning job. + * @return - A TuningJob object. + * + * @experimental - The SDK's tuning implementation is experimental, and may + * change in future versions. + */ + get: (params: types.GetTuningJobParameters) => Promise<types.TuningJob>; + /** + * Creates a supervised fine-tuning job. + * + * @param params - The parameters for the tuning job. + * @return - A TuningJob operation. + * + * @experimental - The SDK's tuning implementation is experimental, and may + * change in future versions. + */ + tune: (params: types.CreateTuningJobParameters) => Promise<types.TuningJob>; + private getInternal; + private listInternal; + /** + * Cancels a tuning job. + * + * @param params - The parameters for the cancel request. + * @return The empty response returned by the API. + * + * @example + * ```ts + * await ai.tunings.cancel({name: '...'}); // The server-generated resource name. + * ``` + */ + cancel(params: types.CancelTuningJobParameters): Promise<types.CancelTuningJobResponse>; + private tuneInternal; + private tuneMldevInternal; +} + +/** The tuning task. Either I2V or T2V. This enum is not supported in Gemini API. */ +export declare enum TuningTask { + /** + * Default value. This value is unused. + */ + TUNING_TASK_UNSPECIFIED = "TUNING_TASK_UNSPECIFIED", + /** + * Tuning task for image to video. + */ + TUNING_TASK_I2V = "TUNING_TASK_I2V", + /** + * Tuning task for text to video. + */ + TUNING_TASK_T2V = "TUNING_TASK_T2V", + /** + * Tuning task for reference to video. + */ + TUNING_TASK_R2V = "TUNING_TASK_R2V" +} + +export declare interface TuningValidationDataset { + /** GCS URI of the file containing validation dataset in JSONL format. */ + gcsUri?: string; + /** The resource name of the Vertex Multimodal Dataset that is used as validation dataset. Example: 'projects/my-project-id-or-number/locations/my-location/datasets/my-dataset-id'. */ + vertexDatasetResource?: string; +} + +declare interface Turn { + /** + * The content of the turn. + */ + content?: string | Array<Content_2>; + /** + * The originator of this turn. Must be user for input or model for + * model output. + */ + role?: string; +} + +/** The reason why the turn is complete. */ +export declare enum TurnCompleteReason { + /** + * Default value. Reason is unspecified. + */ + TURN_COMPLETE_REASON_UNSPECIFIED = "TURN_COMPLETE_REASON_UNSPECIFIED", + /** + * The function call generated by the model is invalid. + */ + MALFORMED_FUNCTION_CALL = "MALFORMED_FUNCTION_CALL", + /** + * The response is rejected by the model. + */ + RESPONSE_REJECTED = "RESPONSE_REJECTED", + /** + * Needs more input from the user. + */ + NEED_MORE_INPUT = "NEED_MORE_INPUT" +} + +/** Options about which input is included in the user's turn. */ +export declare enum TurnCoverage { + /** + * If unspecified, the default behavior is `TURN_INCLUDES_ONLY_ACTIVITY`. + */ + TURN_COVERAGE_UNSPECIFIED = "TURN_COVERAGE_UNSPECIFIED", + /** + * The users turn only includes activity since the last turn, excluding inactivity (e.g. silence on the audio stream). This is the default behavior. + */ + TURN_INCLUDES_ONLY_ACTIVITY = "TURN_INCLUDES_ONLY_ACTIVITY", + /** + * The users turn includes all realtime input since the last turn, including inactivity (e.g. silence on the audio stream). + */ + TURN_INCLUDES_ALL_INPUT = "TURN_INCLUDES_ALL_INPUT" +} + +/** The type of the data. */ +export declare enum Type { + /** + * Not specified, should not be used. + */ + TYPE_UNSPECIFIED = "TYPE_UNSPECIFIED", + /** + * OpenAPI string type + */ + STRING = "STRING", + /** + * OpenAPI number type + */ + NUMBER = "NUMBER", + /** + * OpenAPI integer type + */ + INTEGER = "INTEGER", + /** + * OpenAPI boolean type + */ + BOOLEAN = "BOOLEAN", + /** + * OpenAPI array type + */ + ARRAY = "ARRAY", + /** + * OpenAPI object type + */ + OBJECT = "OBJECT", + /** + * Null type + */ + NULL = "NULL" +} + +declare namespace types { + export { + createFunctionResponsePartFromBase64, + createFunctionResponsePartFromUri, + createPartFromUri, + createPartFromText, + createPartFromFunctionCall, + createPartFromFunctionResponse, + createPartFromBase64, + createPartFromCodeExecutionResult, + createPartFromExecutableCode, + createUserContent, + createModelContent, + Outcome, + Language, + FunctionResponseScheduling, + Type, + ApiSpec, + AuthType, + HttpElementLocation, + PhishBlockThreshold, + Behavior, + DynamicRetrievalConfigMode, + FunctionCallingConfigMode, + ThinkingLevel, + HarmCategory, + HarmBlockMethod, + HarmBlockThreshold, + FinishReason, + HarmProbability, + HarmSeverity, + UrlRetrievalStatus, + BlockedReason, + TrafficType, + Modality, + MediaResolution, + TuningMode, + AdapterSize, + JobState, + TuningTask, + PartMediaResolutionLevel, + ResourceScope, + FeatureSelectionPreference, + Environment, + SafetyFilterLevel, + PersonGeneration, + ImagePromptLanguage, + MaskReferenceMode, + ControlReferenceType, + SubjectReferenceType, + EditMode, + SegmentMode, + VideoGenerationReferenceType, + VideoGenerationMaskMode, + VideoCompressionQuality, + TuningMethod, + DocumentState, + FileState, + FileSource, + TurnCompleteReason, + MediaModality, + VadSignalType, + VoiceActivityType, + StartSensitivity, + EndSensitivity, + ActivityHandling, + TurnCoverage, + Scale, + MusicGenerationMode, + LiveMusicPlaybackControl, + PartMediaResolution, + CodeExecutionResult, + ExecutableCode, + FileData, + PartialArg, + FunctionCall, + FunctionResponseBlob, + FunctionResponseFileData, + FunctionResponsePart, + FunctionResponse, + Blob_2 as Blob, + VideoMetadata, + Part, + Content, + HttpRetryOptions, + HttpOptions, + Schema, + ModelSelectionConfig, + ComputerUse, + FileSearch, + ApiAuthApiKeyConfig, + ApiAuth, + ApiKeyConfig, + AuthConfigGoogleServiceAccountConfig, + AuthConfigHttpBasicAuthConfig, + AuthConfigOauthConfig, + AuthConfigOidcConfig, + AuthConfig, + ExternalApiElasticSearchParams, + ExternalApiSimpleSearchParams, + ExternalApi, + VertexAISearchDataStoreSpec, + VertexAISearch, + VertexRagStoreRagResource, + RagRetrievalConfigFilter, + RagRetrievalConfigHybridSearch, + RagRetrievalConfigRankingLlmRanker, + RagRetrievalConfigRankingRankService, + RagRetrievalConfigRanking, + RagRetrievalConfig, + VertexRagStore, + Retrieval, + ToolCodeExecution, + EnterpriseWebSearch, + FunctionDeclaration, + GoogleMaps, + Interval, + GoogleSearch, + DynamicRetrievalConfig, + GoogleSearchRetrieval, + UrlContext, + Tool, + LatLng, + RetrievalConfig, + FunctionCallingConfig, + ToolConfig, + ReplicatedVoiceConfig, + PrebuiltVoiceConfig, + VoiceConfig, + SpeakerVoiceConfig, + MultiSpeakerVoiceConfig, + SpeechConfig, + AutomaticFunctionCallingConfig, + ThinkingConfig, + ImageConfig, + GenerationConfigRoutingConfigAutoRoutingMode, + GenerationConfigRoutingConfigManualRoutingMode, + GenerationConfigRoutingConfig, + SafetySetting, + ModelArmorConfig, + GenerateContentConfig, + GenerateContentParameters, + HttpResponse, + LiveCallbacks, + GoogleTypeDate, + Citation, + CitationMetadata, + GroundingChunkMapsPlaceAnswerSourcesAuthorAttribution, + GroundingChunkMapsPlaceAnswerSourcesReviewSnippet, + GroundingChunkMapsPlaceAnswerSources, + GroundingChunkMaps, + RagChunkPageSpan, + RagChunk, + GroundingChunkRetrievedContext, + GroundingChunkWeb, + GroundingChunk, + Segment, + GroundingSupport, + RetrievalMetadata, + SearchEntryPoint, + GroundingMetadataSourceFlaggingUri, + GroundingMetadata, + LogprobsResultCandidate, + LogprobsResultTopCandidates, + LogprobsResult, + SafetyRating, + UrlMetadata, + UrlContextMetadata, + Candidate, + GenerateContentResponsePromptFeedback, + ModalityTokenCount, + GenerateContentResponseUsageMetadata, + GenerateContentResponse, + ReferenceImage, + EditImageParameters, + EmbedContentConfig, + EmbedContentParameters, + ContentEmbeddingStatistics, + ContentEmbedding, + EmbedContentMetadata, + EmbedContentResponse, + GenerateImagesConfig, + GenerateImagesParameters, + Image_2 as Image, + SafetyAttributes, + GeneratedImage, + GenerateImagesResponse, + MaskReferenceConfig, + ControlReferenceConfig, + StyleReferenceConfig, + SubjectReferenceConfig, + EditImageConfig, + EditImageResponse, + UpscaleImageResponse, + ProductImage, + RecontextImageSource, + RecontextImageConfig, + RecontextImageParameters, + RecontextImageResponse, + ScribbleImage, + SegmentImageSource, + SegmentImageConfig, + SegmentImageParameters, + EntityLabel, + GeneratedImageMask, + SegmentImageResponse, + GetModelConfig, + GetModelParameters, + Endpoint, + TunedModelInfo, + Checkpoint, + Model, + ListModelsConfig, + ListModelsParameters, + ListModelsResponse, + UpdateModelConfig, + UpdateModelParameters, + DeleteModelConfig, + DeleteModelParameters, + DeleteModelResponse, + GenerationConfig, + CountTokensConfig, + CountTokensParameters, + CountTokensResponse, + ComputeTokensConfig, + ComputeTokensParameters, + TokensInfo, + ComputeTokensResponse, + Video, + GenerateVideosSource, + VideoGenerationReferenceImage, + VideoGenerationMask, + GenerateVideosConfig, + GenerateVideosParameters, + GeneratedVideo, + GenerateVideosResponse, + Operation, + GenerateVideosOperation, + GetTuningJobConfig, + GetTuningJobParameters, + TunedModelCheckpoint, + TunedModel, + SupervisedHyperParameters, + SupervisedTuningSpec, + PreferenceOptimizationHyperParameters, + PreferenceOptimizationSpec, + DistillationHyperParameters, + DistillationSpec, + GoogleRpcStatus, + PreTunedModel, + DatasetDistributionDistributionBucket, + DatasetDistribution, + DatasetStats, + DistillationDataStats, + GeminiPreferenceExampleCompletion, + GeminiPreferenceExample, + PreferenceOptimizationDataStats, + SupervisedTuningDatasetDistributionDatasetBucket, + SupervisedTuningDatasetDistribution, + SupervisedTuningDataStats, + TuningDataStats, + EncryptionSpec, + PartnerModelTuningSpec, + VeoHyperParameters, + VeoTuningSpec, + TuningJob, + ListTuningJobsConfig, + ListTuningJobsParameters, + ListTuningJobsResponse, + CancelTuningJobConfig, + CancelTuningJobParameters, + CancelTuningJobResponse, + TuningExample, + TuningDataset, + TuningValidationDataset, + CreateTuningJobConfig, + CreateTuningJobParametersPrivate, + TuningOperation, + CreateCachedContentConfig, + CreateCachedContentParameters, + CachedContentUsageMetadata, + CachedContent, + GetCachedContentConfig, + GetCachedContentParameters, + DeleteCachedContentConfig, + DeleteCachedContentParameters, + DeleteCachedContentResponse, + UpdateCachedContentConfig, + UpdateCachedContentParameters, + ListCachedContentsConfig, + ListCachedContentsParameters, + ListCachedContentsResponse, + GetDocumentConfig, + GetDocumentParameters, + StringList, + CustomMetadata, + Document_2 as Document, + DeleteDocumentConfig, + DeleteDocumentParameters, + ListDocumentsConfig, + ListDocumentsParameters, + ListDocumentsResponse, + CreateFileSearchStoreConfig, + CreateFileSearchStoreParameters, + FileSearchStore, + GetFileSearchStoreConfig, + GetFileSearchStoreParameters, + DeleteFileSearchStoreConfig, + DeleteFileSearchStoreParameters, + ListFileSearchStoresConfig, + ListFileSearchStoresParameters, + ListFileSearchStoresResponse, + WhiteSpaceConfig, + ChunkingConfig, + UploadToFileSearchStoreConfig, + UploadToFileSearchStoreParameters, + UploadToFileSearchStoreResumableResponse, + ImportFileConfig, + ImportFileParameters, + ImportFileResponse, + ImportFileOperation, + ListFilesConfig, + ListFilesParameters, + FileStatus, + File_2 as File, + ListFilesResponse, + CreateFileConfig, + CreateFileParameters, + CreateFileResponse, + GetFileConfig, + GetFileParameters, + DeleteFileConfig, + DeleteFileParameters, + DeleteFileResponse, + RegisterFilesConfig, + InternalRegisterFilesParameters, + RegisterFilesResponse, + InlinedRequest, + BatchJobSource, + JobError, + InlinedResponse, + SingleEmbedContentResponse, + InlinedEmbedContentResponse, + BatchJobDestination, + CreateBatchJobConfig, + CreateBatchJobParameters, + CompletionStats, + BatchJob, + EmbedContentBatch, + EmbeddingsBatchJobSource, + CreateEmbeddingsBatchJobConfig, + CreateEmbeddingsBatchJobParameters, + GetBatchJobConfig, + GetBatchJobParameters, + CancelBatchJobConfig, + CancelBatchJobParameters, + ListBatchJobsConfig, + ListBatchJobsParameters, + ListBatchJobsResponse, + DeleteBatchJobConfig, + DeleteBatchJobParameters, + DeleteResourceJob, + GetOperationConfig, + GetOperationParameters, + FetchPredictOperationConfig, + FetchPredictOperationParameters, + TestTableItem, + TestTableFile, + ReplayRequest, + ReplayResponse, + ReplayInteraction, + ReplayFile, + UploadFileConfig, + DownloadFileConfig, + DownloadFileParameters, + UpscaleImageConfig, + UpscaleImageParameters, + RawReferenceImage, + MaskReferenceImage, + ControlReferenceImage, + StyleReferenceImage, + SubjectReferenceImage, + ContentReferenceImage, + LiveServerSetupComplete, + Transcription, + LiveServerContent, + LiveServerToolCall, + LiveServerToolCallCancellation, + UsageMetadata, + LiveServerGoAway, + LiveServerSessionResumptionUpdate, + VoiceActivityDetectionSignal, + VoiceActivity, + LiveServerMessage, + OperationFromAPIResponseParameters, + GenerationConfigThinkingConfig, + RegisterFilesParameters, + AutomaticActivityDetection, + RealtimeInputConfig, + SessionResumptionConfig, + SlidingWindow, + ContextWindowCompressionConfig, + AudioTranscriptionConfig, + ProactivityConfig, + LiveClientSetup, + LiveClientContent, + ActivityStart, + ActivityEnd, + LiveClientRealtimeInput, + LiveClientToolResponse, + LiveSendRealtimeInputParameters, + LiveClientMessage, + LiveConnectConfig, + LiveConnectParameters, + CreateChatParameters, + SendMessageParameters, + LiveSendClientContentParameters, + LiveSendToolResponseParameters, + LiveMusicClientSetup, + WeightedPrompt, + LiveMusicClientContent, + LiveMusicGenerationConfig, + LiveMusicClientMessage, + LiveMusicServerSetupComplete, + LiveMusicSourceMetadata, + AudioChunk, + LiveMusicServerContent, + LiveMusicFilteredPrompt, + LiveMusicServerMessage, + LiveMusicCallbacks, + UploadFileParameters, + CallableTool, + CallableToolConfig, + LiveMusicConnectParameters, + LiveMusicSetConfigParameters, + LiveMusicSetWeightedPromptsParameters, + AuthToken, + LiveConnectConstraints, + CreateAuthTokenConfig, + CreateAuthTokenParameters, + OperationGetParameters, + CountTokensResult, + ComputeTokensResult, + CreateTuningJobParameters, + UploadToFileSearchStoreResponse, + UploadToFileSearchStoreOperation, + BlobImageUnion, + PartUnion, + PartListUnion, + ContentUnion, + ContentListUnion, + SchemaUnion, + SpeechConfigUnion, + ToolUnion, + ToolListUnion, + DownloadableFileUnion, + BatchJobSourceUnion, + BatchJobDestinationUnion + } +} + +/** @ts-ignore For users with undici */ +declare type UndiciRequestInit = NotAny<import('../node_modules/undici/index.d.ts').RequestInit> | NotAny<import('../../node_modules/undici/index.d.ts').RequestInit> | NotAny<import('../../../node_modules/undici/index.d.ts').RequestInit> | NotAny<import('../../../../node_modules/undici/index.d.ts').RequestInit> | NotAny<import('../../../../../node_modules/undici/index.d.ts').RequestInit> | NotAny<import('../../../../../../node_modules/undici/index.d.ts').RequestInit> | NotAny<import('../../../../../../../node_modules/undici/index.d.ts').RequestInit> | NotAny<import('../../../../../../../../node_modules/undici/index.d.ts').RequestInit> | NotAny<import('../../../../../../../../../node_modules/undici/index.d.ts').RequestInit> | NotAny<import('../../../../../../../../../../node_modules/undici/index.d.ts').RequestInit>; + +/** + * These imports attempt to get types from a parent package's dependencies. + * Unresolved bare specifiers can trigger [automatic type acquisition][1] in some projects, which + * would cause typescript to show types not present at runtime. To avoid this, we import + * directly from parent node_modules folders. + * + * We need to check multiple levels because we don't know what directory structure we'll be in. + * For example, pnpm generates directories like this: + * ``` + * node_modules + * ├── .pnpm + * │ └── pkg@1.0.0 + * │ └── node_modules + * │ └── pkg + * │ └── internal + * │ └── types.d.ts + * ├── pkg -> .pnpm/pkg@1.0.0/node_modules/pkg + * └── undici + * ``` + * + * [1]: https://www.typescriptlang.org/tsconfig/#typeAcquisition + */ +/** @ts-ignore For users with \@types/node */ +declare type UndiciTypesRequestInit = NotAny<import('../node_modules/undici-types/index.d.ts').RequestInit> | NotAny<import('../../node_modules/undici-types/index.d.ts').RequestInit> | NotAny<import('../../../node_modules/undici-types/index.d.ts').RequestInit> | NotAny<import('../../../../node_modules/undici-types/index.d.ts').RequestInit> | NotAny<import('../../../../../node_modules/undici-types/index.d.ts').RequestInit> | NotAny<import('../../../../../../node_modules/undici-types/index.d.ts').RequestInit> | NotAny<import('../../../../../../../node_modules/undici-types/index.d.ts').RequestInit> | NotAny<import('../../../../../../../../node_modules/undici-types/index.d.ts').RequestInit> | NotAny<import('../../../../../../../../../node_modules/undici-types/index.d.ts').RequestInit> | NotAny<import('../../../../../../../../../../node_modules/undici-types/index.d.ts').RequestInit>; + +declare class UnprocessableEntityError extends APIError<422, Headers> { +} + +/** Optional parameters for caches.update method. */ +export declare interface UpdateCachedContentConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** The TTL for this resource. The expiration time is computed: now + TTL. It is a duration string, with up to nine fractional digits, terminated by 's'. Example: "3.5s". */ + ttl?: string; + /** Timestamp of when this resource is considered expired. Uses RFC 3339 format, Example: 2014-10-02T15:01:23Z. */ + expireTime?: string; +} + +export declare interface UpdateCachedContentParameters { + /** The server-generated resource name of the cached content. + */ + name: string; + /** Configuration that contains optional parameters. + */ + config?: UpdateCachedContentConfig; +} + +/** Configuration for updating a tuned model. */ +export declare interface UpdateModelConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + displayName?: string; + description?: string; + defaultCheckpointId?: string; +} + +/** Configuration for updating a tuned model. */ +export declare interface UpdateModelParameters { + model: string; + config?: UpdateModelConfig; +} + +declare interface Uploader { + /** + * Uploads a file to the given upload url. + * + * @param file The file to upload. file is in string type or a Blob. + * @param uploadUrl The upload URL as a string is where the file will be + * uploaded to. The uploadUrl must be a url that was returned by the + * https://generativelanguage.googleapis.com/upload/v1beta/files endpoint + * @param apiClient The ApiClient to use for uploading. + * @return A Promise that resolves to types.File. + */ + upload(file: string | Blob, uploadUrl: string, apiClient: ApiClient): Promise<File_2>; + /** + * Uploads a file to file search store via the given upload url. + * + * @param file The file to upload. file is in string type or a Blob. + * @param uploadUrl The upload URL as a string is where the file will be + * uploaded to. The uploadUrl must be a url that was returned by the + * https://generativelanguage.googleapis.com/upload/v1beta/{file_search_store_name}:uploadToFileSearchStore endpoint + * @param apiClient The ApiClient to use for uploading. + * @return A Promise that resolves to types.UploadToFileSearchStoreOperation. + */ + uploadToFileSearchStore(file: string | Blob, uploadUrl: string, apiClient: ApiClient): Promise<UploadToFileSearchStoreOperation>; + /** + * Returns the file's mimeType and the size of a given file. If the file is a + * string path, the file type is determined by the file extension. If the + * file's type cannot be determined, the type will be set to undefined. + * + * @param file The file to get the stat for. Can be a string path or a Blob. + * @return A Promise that resolves to the file stat of the given file. + */ + stat(file: string | Blob): Promise<FileStat>; +} + +/** Used to override the default configuration. */ +export declare interface UploadFileConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** The name of the file in the destination (e.g., 'files/sample-image'. If not provided one will be generated. */ + name?: string; + /** mime_type: The MIME type of the file. If not provided, it will be inferred from the file extension. */ + mimeType?: string; + /** Optional display name of the file. */ + displayName?: string; +} + +/** Parameters for the upload file method. */ +export declare interface UploadFileParameters { + /** The string path to the file to be uploaded or a Blob object. */ + file: string | globalThis.Blob; + /** Configuration that contains optional parameters. */ + config?: UploadFileConfig; +} + +/** Optional parameters for uploading a file to a FileSearchStore. */ +export declare interface UploadToFileSearchStoreConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** MIME type of the file to be uploaded. If not provided, it will be inferred from the file extension. */ + mimeType?: string; + /** Display name of the created document. */ + displayName?: string; + /** User provided custom metadata stored as key-value pairs used for querying. */ + customMetadata?: CustomMetadata[]; + /** Config for telling the service how to chunk the file. */ + chunkingConfig?: ChunkingConfig; +} + +/** Long-running operation for uploading a file to a FileSearchStore. */ +export declare class UploadToFileSearchStoreOperation implements Operation<UploadToFileSearchStoreResponse> { + /** The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`. */ + name?: string; + /** Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata. Any method that returns a long-running operation should document the metadata type, if any. */ + metadata?: Record<string, unknown>; + /** If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available. */ + done?: boolean; + /** The error result of the operation in case of failure or cancellation. */ + error?: Record<string, unknown>; + /** The result of the UploadToFileSearchStore operation, available when the operation is done. */ + response?: UploadToFileSearchStoreResponse; + /** + * Instantiates an Operation of the same type as the one being called with the fields set from the API response. + * @internal + */ + _fromAPIResponse({ apiResponse, _isVertexAI, }: OperationFromAPIResponseParameters): Operation<UploadToFileSearchStoreResponse>; + /** The full HTTP response. */ + sdkHttpResponse?: HttpResponse; +} + +/** Generates the parameters for the private _upload_to_file_search_store method. */ +export declare interface UploadToFileSearchStoreParameters { + /** The resource name of the FileSearchStore. Example: `fileSearchStores/my-file-search-store-123` */ + fileSearchStoreName: string; + /** Used to override the default configuration. */ + config?: UploadToFileSearchStoreConfig; +} + +/** Parameters for the upload file to file search store method. */ +export declare interface UploadToFileSearchStoreParameters { + /** The name of the file search store to upload. */ + fileSearchStoreName: string; + /** The string path to the file to be uploaded or a Blob object. */ + file: string | globalThis.Blob; + /** Configuration that contains optional parameters. */ + config?: UploadToFileSearchStoreConfig; +} + +/** The response when long-running operation for uploading a file to a FileSearchStore complete. */ +export declare class UploadToFileSearchStoreResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** The name of the FileSearchStore containing Documents. */ + parent?: string; + /** The identifier for the Document imported. */ + documentName?: string; +} + +/** Response for the resumable upload method. */ +export declare class UploadToFileSearchStoreResumableResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; +} + +/** Configuration for upscaling an image. + + For more information on this configuration, refer to + the `Imagen API reference documentation + <https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/imagen-api>`_. */ +export declare interface UpscaleImageConfig { + /** Used to override HTTP request options. */ + httpOptions?: HttpOptions; + /** Abort signal which can be used to cancel the request. + + NOTE: AbortSignal is a client-only operation. Using it to cancel an + operation will not cancel the request in the service. You will still + be charged usage for any applicable operations. + */ + abortSignal?: AbortSignal; + /** Cloud Storage URI used to store the generated images. */ + outputGcsUri?: string; + /** Filter level for safety filtering. */ + safetyFilterLevel?: SafetyFilterLevel; + /** Allows generation of people by the model. */ + personGeneration?: PersonGeneration; + /** Whether to include a reason for filtered-out images in the + response. */ + includeRaiReason?: boolean; + /** The image format that the output should be saved as. */ + outputMimeType?: string; + /** The level of compression. Only applicable if the + ``output_mime_type`` is ``image/jpeg``. */ + outputCompressionQuality?: number; + /** Whether to add an image enhancing step before upscaling. + It is expected to suppress the noise and JPEG compression artifacts + from the input image. */ + enhanceInputImage?: boolean; + /** With a higher image preservation factor, the original image + pixels are more respected. With a lower image preservation factor, the + output image will have be more different from the input image, but + with finer details and less noise. */ + imagePreservationFactor?: number; + /** User specified labels to track billing usage. */ + labels?: Record<string, string>; +} + +/** User-facing config UpscaleImageParameters. */ +export declare interface UpscaleImageParameters { + /** The model to use. */ + model: string; + /** The input image to upscale. */ + image: Image_2; + /** The factor to upscale the image (x2 or x4). */ + upscaleFactor: string; + /** Configuration for upscaling. */ + config?: UpscaleImageConfig; +} + +export declare class UpscaleImageResponse { + /** Used to retain the full HTTP response. */ + sdkHttpResponse?: HttpResponse; + /** Generated images. */ + generatedImages?: GeneratedImage[]; +} + +/** Tool to support URL context. */ +export declare interface UrlContext { +} + +/** + * The arguments to pass to the URL context. + */ +declare interface URLContextCallArguments { + /** + * The URLs to fetch. + */ + urls?: Array<string>; +} + +/** + * URL context content. + */ +declare interface URLContextCallContent { + type: 'url_context_call'; + /** + * A unique ID for this specific tool call. + */ + id?: string; + /** + * The arguments to pass to the URL context. + */ + arguments?: URLContextCallArguments; +} + +/** Metadata related to url context retrieval tool. */ +export declare interface UrlContextMetadata { + /** Output only. List of url context. */ + urlMetadata?: UrlMetadata[]; +} + +/** + * The result of the URL context. + */ +declare interface URLContextResult { + /** + * The status of the URL retrieval. + */ + status?: 'success' | 'error' | 'paywall' | 'unsafe'; + /** + * The URL that was fetched. + */ + url?: string; +} + +/** + * URL context result content. + */ +declare interface URLContextResultContent { + type: 'url_context_result'; + /** + * ID to match the ID from the url context call block. + */ + call_id?: string; + /** + * Whether the URL context resulted in an error. + */ + is_error?: boolean; + /** + * The results of the URL context. + */ + result?: Array<URLContextResult>; + /** + * The signature of the URL context result. + */ + signature?: string; +} + +/** Context of the a single url retrieval. */ +export declare interface UrlMetadata { + /** Retrieved url by the tool. */ + retrievedUrl?: string; + /** Status of the url retrieval. */ + urlRetrievalStatus?: UrlRetrievalStatus; +} + +/** Status of the url retrieval. */ +export declare enum UrlRetrievalStatus { + /** + * Default value. This value is unused. + */ + URL_RETRIEVAL_STATUS_UNSPECIFIED = "URL_RETRIEVAL_STATUS_UNSPECIFIED", + /** + * Url retrieval is successful. + */ + URL_RETRIEVAL_STATUS_SUCCESS = "URL_RETRIEVAL_STATUS_SUCCESS", + /** + * Url retrieval is failed due to error. + */ + URL_RETRIEVAL_STATUS_ERROR = "URL_RETRIEVAL_STATUS_ERROR", + /** + * Url retrieval is failed because the content is behind paywall. This enum value is not supported in Vertex AI. + */ + URL_RETRIEVAL_STATUS_PAYWALL = "URL_RETRIEVAL_STATUS_PAYWALL", + /** + * Url retrieval is failed because the content is unsafe. This enum value is not supported in Vertex AI. + */ + URL_RETRIEVAL_STATUS_UNSAFE = "URL_RETRIEVAL_STATUS_UNSAFE" +} + +/** + * Statistics on the interaction request's token usage. + */ +declare interface Usage { + /** + * A breakdown of cached token usage by modality. + */ + cached_tokens_by_modality?: Array<Usage.CachedTokensByModality>; + /** + * A breakdown of input token usage by modality. + */ + input_tokens_by_modality?: Array<Usage.InputTokensByModality>; + /** + * A breakdown of output token usage by modality. + */ + output_tokens_by_modality?: Array<Usage.OutputTokensByModality>; + /** + * A breakdown of tool-use token usage by modality. + */ + tool_use_tokens_by_modality?: Array<Usage.ToolUseTokensByModality>; + /** + * Number of tokens in the cached part of the prompt (the cached content). + */ + total_cached_tokens?: number; + /** + * Number of tokens in the prompt (context). + */ + total_input_tokens?: number; + /** + * Total number of tokens across all the generated responses. + */ + total_output_tokens?: number; + /** + * Number of tokens of thoughts for thinking models. + */ + total_thought_tokens?: number; + /** + * Total token count for the interaction request (prompt + responses + other + * internal tokens). + */ + total_tokens?: number; + /** + * Number of tokens present in tool-use prompt(s). + */ + total_tool_use_tokens?: number; +} + +declare namespace Usage { + /** + * The token count for a single response modality. + */ + interface CachedTokensByModality { + /** + * The modality associated with the token count. + */ + modality?: 'text' | 'image' | 'audio'; + /** + * Number of tokens for the modality. + */ + tokens?: number; + } + /** + * The token count for a single response modality. + */ + interface InputTokensByModality { + /** + * The modality associated with the token count. + */ + modality?: 'text' | 'image' | 'audio'; + /** + * Number of tokens for the modality. + */ + tokens?: number; + } + /** + * The token count for a single response modality. + */ + interface OutputTokensByModality { + /** + * The modality associated with the token count. + */ + modality?: 'text' | 'image' | 'audio'; + /** + * Number of tokens for the modality. + */ + tokens?: number; + } + /** + * The token count for a single response modality. + */ + interface ToolUseTokensByModality { + /** + * The modality associated with the token count. + */ + modality?: 'text' | 'image' | 'audio'; + /** + * Number of tokens for the modality. + */ + tokens?: number; + } +} + +/** Usage metadata about response(s). */ +export declare interface UsageMetadata { + /** Number of tokens in the prompt. When `cached_content` is set, this is still the total effective prompt size meaning this includes the number of tokens in the cached content. */ + promptTokenCount?: number; + /** Number of tokens in the cached part of the prompt (the cached content). */ + cachedContentTokenCount?: number; + /** Total number of tokens across all the generated response candidates. */ + responseTokenCount?: number; + /** Number of tokens present in tool-use prompt(s). */ + toolUsePromptTokenCount?: number; + /** Number of tokens of thoughts for thinking models. */ + thoughtsTokenCount?: number; + /** Total token count for prompt, response candidates, and tool-use prompts(if present). */ + totalTokenCount?: number; + /** List of modalities that were processed in the request input. */ + promptTokensDetails?: ModalityTokenCount[]; + /** List of modalities that were processed in the cache input. */ + cacheTokensDetails?: ModalityTokenCount[]; + /** List of modalities that were returned in the response. */ + responseTokensDetails?: ModalityTokenCount[]; + /** List of modalities that were processed in the tool-use prompt. */ + toolUsePromptTokensDetails?: ModalityTokenCount[]; + /** Traffic type. This shows whether a request consumes Pay-As-You-Go + or Provisioned Throughput quota. */ + trafficType?: TrafficType; +} + +/** The type of the VAD signal. */ +export declare enum VadSignalType { + /** + * The default is VAD_SIGNAL_TYPE_UNSPECIFIED. + */ + VAD_SIGNAL_TYPE_UNSPECIFIED = "VAD_SIGNAL_TYPE_UNSPECIFIED", + /** + * Start of sentence signal. + */ + VAD_SIGNAL_TYPE_SOS = "VAD_SIGNAL_TYPE_SOS", + /** + * End of sentence signal. + */ + VAD_SIGNAL_TYPE_EOS = "VAD_SIGNAL_TYPE_EOS" +} + +/** Hyperparameters for Veo. This data type is not supported in Gemini API. */ +export declare interface VeoHyperParameters { + /** Optional. Number of complete passes the model makes over the entire training dataset during training. */ + epochCount?: string; + /** Optional. Multiplier for adjusting the default learning rate. */ + learningRateMultiplier?: number; + /** Optional. The tuning task. Either I2V or T2V. */ + tuningTask?: TuningTask; +} + +/** Tuning Spec for Veo Model Tuning. This data type is not supported in Gemini API. */ +export declare interface VeoTuningSpec { + /** Optional. Hyperparameters for Veo. */ + hyperParameters?: VeoHyperParameters; + /** Required. Training dataset used for tuning. The dataset can be specified as either a Cloud Storage path to a JSONL file or as the resource name of a Vertex Multimodal Dataset. */ + trainingDatasetUri?: string; + /** Optional. Validation dataset used for tuning. The dataset can be specified as either a Cloud Storage path to a JSONL file or as the resource name of a Vertex Multimodal Dataset. */ + validationDatasetUri?: string; +} + +/** Retrieve from Vertex AI Search datastore or engine for grounding. datastore and engine are mutually exclusive. See https://cloud.google.com/products/agent-builder. This data type is not supported in Gemini API. */ +export declare interface VertexAISearch { + /** Specifications that define the specific DataStores to be searched, along with configurations for those data stores. This is only considered for Engines with multiple data stores. It should only be set if engine is used. */ + dataStoreSpecs?: VertexAISearchDataStoreSpec[]; + /** Optional. Fully-qualified Vertex AI Search data store resource ID. Format: `projects/{project}/locations/{location}/collections/{collection}/dataStores/{dataStore}` */ + datastore?: string; + /** Optional. Fully-qualified Vertex AI Search engine resource ID. Format: `projects/{project}/locations/{location}/collections/{collection}/engines/{engine}` */ + engine?: string; + /** Optional. Filter strings to be passed to the search API. */ + filter?: string; + /** Optional. Number of search results to return per query. The default value is 10. The maximumm allowed value is 10. */ + maxResults?: number; +} + +/** Define data stores within engine to filter on in a search call and configurations for those data stores. For more information, see https://cloud.google.com/generative-ai-app-builder/docs/reference/rpc/google.cloud.discoveryengine.v1#datastorespec. This data type is not supported in Gemini API. */ +export declare interface VertexAISearchDataStoreSpec { + /** Full resource name of DataStore, such as Format: `projects/{project}/locations/{location}/collections/{collection}/dataStores/{dataStore}` */ + dataStore?: string; + /** Optional. Filter specification to filter documents in the data store specified by data_store field. For more information on filtering, see [Filtering](https://cloud.google.com/generative-ai-app-builder/docs/filter-search-metadata) */ + filter?: string; +} + +/** Retrieve from Vertex RAG Store for grounding. This data type is not supported in Gemini API. */ +export declare interface VertexRagStore { + /** Optional. Deprecated. Please use rag_resources instead. */ + ragCorpora?: string[]; + /** Optional. The representation of the rag source. It can be used to specify corpus only or ragfiles. Currently only support one corpus or multiple files from one corpus. In the future we may open up multiple corpora support. */ + ragResources?: VertexRagStoreRagResource[]; + /** Optional. The retrieval config for the Rag query. */ + ragRetrievalConfig?: RagRetrievalConfig; + /** Optional. Number of top k results to return from the selected corpora. */ + similarityTopK?: number; + /** Optional. Currently only supported for Gemini Multimodal Live API. In Gemini Multimodal Live API, if `store_context` bool is specified, Gemini will leverage it to automatically memorize the interactions between the client and Gemini, and retrieve context when needed to augment the response generation for users' ongoing and future interactions. */ + storeContext?: boolean; + /** Optional. Only return results with vector distance smaller than the threshold. */ + vectorDistanceThreshold?: number; +} + +/** The definition of the Rag resource. This data type is not supported in Gemini API. */ +export declare interface VertexRagStoreRagResource { + /** Optional. RagCorpora resource name. Format: `projects/{project}/locations/{location}/ragCorpora/{rag_corpus}` */ + ragCorpus?: string; + /** Optional. rag_file_id. The files should be in the same rag_corpus set in rag_corpus field. */ + ragFileIds?: string[]; +} + +/** A generated video. */ +export declare interface Video { + /** Path to another storage. */ + uri?: string; + /** Video bytes. + * @remarks Encoded as base64 string. */ + videoBytes?: string; + /** Video encoding, for example ``video/mp4``. */ + mimeType?: string; +} + +/** Enum that controls the compression quality of the generated videos. */ +export declare enum VideoCompressionQuality { + /** + * Optimized video compression quality. This will produce videos + with a compressed, smaller file size. + */ + OPTIMIZED = "OPTIMIZED", + /** + * Lossless video compression quality. This will produce videos + with a larger file size. + */ + LOSSLESS = "LOSSLESS" +} + +/** + * A video content block. + */ +declare interface VideoContent { + type: 'video'; + /** + * The video content. + */ + data?: string; + /** + * The mime type of the video. + */ + mime_type?: VideoMimeType; + /** + * The resolution of the media. + */ + resolution?: 'low' | 'medium' | 'high' | 'ultra_high'; + /** + * The URI of the video. + */ + uri?: string; +} + +/** A mask for video generation. */ +export declare interface VideoGenerationMask { + /** The image mask to use for generating videos. */ + image?: Image_2; + /** Describes how the mask will be used. Inpainting masks must + match the aspect ratio of the input video. Outpainting masks can be + either 9:16 or 16:9. */ + maskMode?: VideoGenerationMaskMode; +} + +/** Enum for the mask mode of a video generation mask. */ +export declare enum VideoGenerationMaskMode { + /** + * The image mask contains a masked rectangular region which is + applied on the first frame of the input video. The object described in + the prompt is inserted into this region and will appear in subsequent + frames. + */ + INSERT = "INSERT", + /** + * The image mask is used to determine an object in the + first video frame to track. This object is removed from the video. + */ + REMOVE = "REMOVE", + /** + * The image mask is used to determine a region in the + video. Objects in this region will be removed. + */ + REMOVE_STATIC = "REMOVE_STATIC", + /** + * The image mask contains a masked rectangular region where + the input video will go. The remaining area will be generated. Video + masks are not supported. + */ + OUTPAINT = "OUTPAINT" +} + +/** A reference image for video generation. */ +export declare interface VideoGenerationReferenceImage { + /** The reference image. */ + image?: Image_2; + /** The type of the reference image, which defines how the reference + image will be used to generate the video. */ + referenceType?: VideoGenerationReferenceType; +} + +/** Enum for the reference type of a video generation reference image. */ +export declare enum VideoGenerationReferenceType { + /** + * A reference image that provides assets to the generated video, + such as the scene, an object, a character, etc. + */ + ASSET = "ASSET", + /** + * A reference image that provides aesthetics including colors, + lighting, texture, etc., to be used as the style of the generated video, + such as 'anime', 'photography', 'origami', etc. + */ + STYLE = "STYLE" +} + +/** Metadata describes the input video content. */ +export declare interface VideoMetadata { + /** Optional. The end offset of the video. */ + endOffset?: string; + /** Optional. The frame rate of the video sent to the model. If not specified, the default value will be 1.0. The fps range is (0.0, 24.0]. */ + fps?: number; + /** Optional. The start offset of the video. */ + startOffset?: string; +} + +/** + * The mime type of the video. + */ +declare type VideoMimeType = 'video/mp4' | 'video/mpeg' | 'video/mov' | 'video/avi' | 'video/x-flv' | 'video/mpg' | 'video/webm' | 'video/wmv' | 'video/3gpp' | (string & {}); + +/** Voice activity signal. */ +export declare interface VoiceActivity { + /** The type of the voice activity signal. */ + voiceActivityType?: VoiceActivityType; +} + +export declare interface VoiceActivityDetectionSignal { + /** The type of the VAD signal. */ + vadSignalType?: VadSignalType; +} + +/** The type of the voice activity signal. */ +export declare enum VoiceActivityType { + /** + * The default is VOICE_ACTIVITY_TYPE_UNSPECIFIED. + */ + TYPE_UNSPECIFIED = "TYPE_UNSPECIFIED", + /** + * Start of sentence signal. + */ + ACTIVITY_START = "ACTIVITY_START", + /** + * End of sentence signal. + */ + ACTIVITY_END = "ACTIVITY_END" +} + +export declare interface VoiceConfig { + /** If true, the model will use a replicated voice for the response. */ + replicatedVoiceConfig?: ReplicatedVoiceConfig; + /** The configuration for the prebuilt voice to use. */ + prebuiltVoiceConfig?: PrebuiltVoiceConfig; +} + +declare interface WebSocket_2 { + /** + * Connects the socket to the server. + */ + connect(): void; + /** + * Sends a message to the server. + */ + send(message: string): void; + /** + * Closes the socket connection. + */ + close(): void; +} + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +declare interface WebSocketCallbacks { + onopen: () => void; + onerror: (e: any) => void; + onmessage: (e: any) => void; + onclose: (e: any) => void; +} + +declare interface WebSocketFactory { + /** + * Returns a new WebSocket instance. + */ + create(url: string, headers: Record<string, string>, callbacks: WebSocketCallbacks): WebSocket_2; +} + +/** Maps a prompt to a relative weight to steer music generation. */ +export declare interface WeightedPrompt { + /** Text prompt. */ + text?: string; + /** Weight of the prompt. The weight is used to control the relative + importance of the prompt. Higher weights are more important than lower + weights. + + Weight must not be 0. Weights of all weighted_prompts in this + LiveMusicClientContent message will be normalized. */ + weight?: number; +} + +/** Configuration for a white space chunking algorithm. */ +export declare interface WhiteSpaceConfig { + /** Maximum number of tokens per chunk. */ + maxTokensPerChunk?: number; + /** Maximum number of overlapping tokens between two adjacent chunks. */ + maxOverlapTokens?: number; +} + +export { } diff --git a/server/node_modules/@google/genai/node/package.json b/server/node_modules/@google/genai/node/package.json new file mode 100644 index 0000000..7666aff --- /dev/null +++ b/server/node_modules/@google/genai/node/package.json @@ -0,0 +1,4 @@ +{ + "name": "@google/genai/node", + "main": "../dist/node/index.js" +} diff --git a/server/node_modules/@google/genai/package.json b/server/node_modules/@google/genai/package.json new file mode 100644 index 0000000..58ad4ae --- /dev/null +++ b/server/node_modules/@google/genai/package.json @@ -0,0 +1,167 @@ +{ + "name": "@google/genai", + "version": "1.41.0", + "description": "", + "type": "module", + "main": "dist/node/index.mjs", + "module": "dist/web/index.mjs", + "browser": "dist/web/index.mjs", + "typings": "dist/genai.d.ts", + "exports": { + ".": { + "browser": { + "types": "./dist/web/web.d.ts", + "import": "./dist/web/index.mjs", + "default": "./dist/web/index.mjs" + }, + "node": { + "types": "./dist/node/node.d.ts", + "import": "./dist/node/index.mjs", + "require": "./dist/node/index.cjs", + "default": "./dist/node/index.mjs" + }, + "types": "./dist/genai.d.ts", + "import": "./dist/index.mjs", + "require": "./dist/index.cjs", + "default": "./dist/index.mjs" + }, + "./web": { + "types": "./dist/web/web.d.ts", + "import": "./dist/web/index.mjs", + "default": "./dist/web/index.mjs" + }, + "./node": { + "types": "./dist/node/node.d.ts", + "import": "./dist/node/index.mjs", + "default": "./dist/node/index.mjs" + }, + "./tokenizer": { + "node": { + "types": "./dist/tokenizer/node.d.ts", + "import": "./dist/tokenizer/node.mjs", + "require": "./dist/tokenizer/node.cjs", + "default": "./dist/tokenizer/node.mjs" + }, + "types": "./dist/tokenizer/node.d.ts", + "import": "./dist/tokenizer/node.mjs", + "require": "./dist/tokenizer/node.cjs", + "default": "./dist/tokenizer/node.mjs" + }, + "./tokenizer/node": { + "types": "./dist/tokenizer/node.d.ts", + "import": "./dist/tokenizer/node.mjs", + "require": "./dist/tokenizer/node.cjs", + "default": "./dist/tokenizer/node.mjs" + } + }, + "scripts": { + "prepare": "node scripts/prepare.js", + "build": "patch-package && rollup -c && npm-run-all --parallel api-extractor:dev:* && node scripts/ignore_missing_mcp_dep.js", + "build-prod": "patch-package && rollup -c && npm-run-all --parallel api-extractor:prod:* && node scripts/ignore_missing_mcp_dep.js", + "api-extractor:dev:main": "api-extractor run --local --verbose", + "api-extractor:dev:node": "api-extractor run -c api-extractor.node.json --local --verbose", + "api-extractor:dev:web": "api-extractor run -c api-extractor.web.json --local --verbose", + "api-extractor:dev:tokenizer-node": "api-extractor run -c api-extractor.tokenizer-node.json --local --verbose", + "api-extractor:prod:main": "api-extractor run --verbose", + "api-extractor:prod:node": "api-extractor run -c api-extractor.node.json --verbose", + "api-extractor:prod:web": "api-extractor run -c api-extractor.web.json --verbose", + "api-extractor:prod:tokenizer-node": "api-extractor run -c api-extractor.tokenizer-node.json --verbose", + "unit-test": "tsc && cp src/cross/sentencepiece/sentencepiece_model.pb.js dist/src/cross/sentencepiece/ && jasmine dist/test/unit/**/*_test.js dist/test/unit/**/**/*_test.js dist/test/unit/*_test.js", + "system-test": "tsc && jasmine dist/test/system/**/*_test.js", + "test-server-tests": "tsc && GOOGLE_CLOUD_PROJECT=googcloudproj GOOGLE_CLOUD_LOCATION=googcloudloc jasmine dist/test/system/node/*_test.js -- --test-server", + "test-server-tests:record": "tsc && jasmine --fail-fast dist/test/system/node/*_test.js -- --test-server --record", + "docs": "typedoc && node --loader ts-node/esm scripts/add_docsite_license_headers.ts", + "pages-main": "node --loader ts-node/esm scripts/generate_pages.ts main", + "pages-release": "node --loader ts-node/esm scripts/generate_pages.ts release", + "format": "prettier '**/*.ts' '**/*.mjs' '**/*.json' --write", + "lint": "eslint '**/*.ts'", + "lint-fix": "eslint --fix '**/*.ts'", + "coverage-report": "./test/generate_report.sh", + "generate-proto": "pbjs -t static-module -w es6 -o src/cross/sentencepiece/sentencepiece_model.pb.js src/cross/sentencepiece/sentencepiece_model.proto && pbts -o src/cross/sentencepiece/sentencepiece_model.pb.d.ts src/cross/sentencepiece/sentencepiece_model.pb.js && sed -i.bak 's/import \\* as \\$protobuf from \"protobufjs\\/minimal\"/import \\$protobuf from \"protobufjs\\/minimal.js\"/' src/cross/sentencepiece/sentencepiece_model.pb.js && rm src/cross/sentencepiece/sentencepiece_model.pb.js.bak" + }, + "engines": { + "node": ">=20.0.0" + }, + "overrides": { + "tmp": "^0.2.4" + }, + "files": [ + "dist/genai.d.ts", + "dist/index.mjs", + "dist/index.cjs", + "dist/index.mjs.map", + "dist/node/index.mjs", + "dist/node/index.cjs", + "dist/node/index.mjs.map", + "dist/node/node.d.ts", + "dist/web/index.mjs", + "dist/web/index.mjs.map", + "dist/web/web.d.ts", + "dist/tokenizer/node.mjs", + "dist/tokenizer/node.cjs", + "dist/tokenizer/node.mjs.map", + "dist/tokenizer/node.d.ts", + "node/package.json", + "web/package.json" + ], + "devDependencies": { + "@cfworker/json-schema": "^4.1.1", + "@eslint/js": "9.20.0", + "@microsoft/api-extractor": "^7.52.9", + "@modelcontextprotocol/sdk": "^1.25.2", + "@rollup/plugin-json": "^6.1.0", + "@types/jasmine": "^5.1.2", + "@types/node": "^20.9.0", + "@types/node-fetch": "^2.6.13", + "@types/unist": "^3.0.3", + "@types/ws": "^8.5.14", + "c8": "^10.1.3", + "eslint": "8.57.0", + "gts": "^5.2.0", + "jasmine": "^5.5.0", + "jasmine-reporters": "^2.4.0", + "node-fetch": "^3.3.2", + "npm-run-all": "^4.1.5", + "nyc": "^17.1.0", + "patch-package": "^8.0.1", + "prettier": "3.3.3", + "prettier-plugin-organize-imports": "^4.1.0", + "protobufjs-cli": "^1.1.3", + "rollup-plugin-typescript2": "^0.36.0", + "test-server-sdk": "^0.2.9", + "ts-node": "^10.9.2", + "tslib": "^2.8.1", + "tsx": "^4.19.4", + "typedoc": "^0.27.0", + "typescript": "~5.4.0", + "typescript-eslint": "8.24.1", + "undici": "^7.16.0", + "undici-types": "^7.16.0", + "zod": "^3.25.0", + "zod-to-json-schema": "^3.25.0" + }, + "dependencies": { + "google-auth-library": "^10.3.0", + "p-retry": "^7.1.1", + "protobufjs": "^7.5.4", + "ws": "^8.18.0" + }, + "peerDependencies": { + "@modelcontextprotocol/sdk": "^1.25.2" + }, + "peerDependenciesMeta": { + "@modelcontextprotocol/sdk": { + "optional": true + } + }, + "repository": { + "type": "git", + "url": "https://github.com/googleapis/js-genai.git" + }, + "bugs": { + "url": "https://github.com/googleapis/js-genai/issues" + }, + "homepage": "https://github.com/googleapis/js-genai#readme", + "author": "", + "license": "Apache-2.0" +} diff --git a/server/node_modules/@google/genai/web/package.json b/server/node_modules/@google/genai/web/package.json new file mode 100644 index 0000000..606dd1f --- /dev/null +++ b/server/node_modules/@google/genai/web/package.json @@ -0,0 +1,4 @@ +{ + "name": "@google/genai/web", + "module": "../dist/web/index.mjs" +} diff --git a/server/node_modules/@isaacs/cliui/LICENSE.txt b/server/node_modules/@isaacs/cliui/LICENSE.txt new file mode 100644 index 0000000..c7e2747 --- /dev/null +++ b/server/node_modules/@isaacs/cliui/LICENSE.txt @@ -0,0 +1,14 @@ +Copyright (c) 2015, Contributors + +Permission to use, copy, modify, and/or distribute this software +for any purpose with or without fee is hereby granted, provided +that the above copyright notice and this permission notice +appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE +LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES +OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/server/node_modules/@isaacs/cliui/README.md b/server/node_modules/@isaacs/cliui/README.md new file mode 100644 index 0000000..4880642 --- /dev/null +++ b/server/node_modules/@isaacs/cliui/README.md @@ -0,0 +1,143 @@ +# @isaacs/cliui + +Temporary fork of [cliui](http://npm.im/cliui). + +![ci](https://github.com/yargs/cliui/workflows/ci/badge.svg) +[![NPM version](https://img.shields.io/npm/v/cliui.svg)](https://www.npmjs.com/package/cliui) +[![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg)](https://conventionalcommits.org) +![nycrc config on GitHub](https://img.shields.io/nycrc/yargs/cliui) + +easily create complex multi-column command-line-interfaces. + +## Example + +```js +const ui = require('cliui')() + +ui.div('Usage: $0 [command] [options]') + +ui.div({ + text: 'Options:', + padding: [2, 0, 1, 0] +}) + +ui.div( + { + text: "-f, --file", + width: 20, + padding: [0, 4, 0, 4] + }, + { + text: "the file to load." + + chalk.green("(if this description is long it wraps).") + , + width: 20 + }, + { + text: chalk.red("[required]"), + align: 'right' + } +) + +console.log(ui.toString()) +``` + +## Deno/ESM Support + +As of `v7` `cliui` supports [Deno](https://github.com/denoland/deno) and +[ESM](https://nodejs.org/api/esm.html#esm_ecmascript_modules): + +```typescript +import cliui from "https://deno.land/x/cliui/deno.ts"; + +const ui = cliui({}) + +ui.div('Usage: $0 [command] [options]') + +ui.div({ + text: 'Options:', + padding: [2, 0, 1, 0] +}) + +ui.div({ + text: "-f, --file", + width: 20, + padding: [0, 4, 0, 4] +}) + +console.log(ui.toString()) +``` + +<img width="500" src="screenshot.png"> + +## Layout DSL + +cliui exposes a simple layout DSL: + +If you create a single `ui.div`, passing a string rather than an +object: + +* `\n`: characters will be interpreted as new rows. +* `\t`: characters will be interpreted as new columns. +* `\s`: characters will be interpreted as padding. + +**as an example...** + +```js +var ui = require('./')({ + width: 60 +}) + +ui.div( + 'Usage: node ./bin/foo.js\n' + + ' <regex>\t provide a regex\n' + + ' <glob>\t provide a glob\t [required]' +) + +console.log(ui.toString()) +``` + +**will output:** + +```shell +Usage: node ./bin/foo.js + <regex> provide a regex + <glob> provide a glob [required] +``` + +## Methods + +```js +cliui = require('cliui') +``` + +### cliui({width: integer}) + +Specify the maximum width of the UI being generated. +If no width is provided, cliui will try to get the current window's width and use it, and if that doesn't work, width will be set to `80`. + +### cliui({wrap: boolean}) + +Enable or disable the wrapping of text in a column. + +### cliui.div(column, column, column) + +Create a row with any number of columns, a column +can either be a string, or an object with the following +options: + +* **text:** some text to place in the column. +* **width:** the width of a column. +* **align:** alignment, `right` or `center`. +* **padding:** `[top, right, bottom, left]`. +* **border:** should a border be placed around the div? + +### cliui.span(column, column, column) + +Similar to `div`, except the next row will be appended without +a new line being created. + +### cliui.resetOutput() + +Resets the UI elements of the current cliui instance, maintaining the values +set for `width` and `wrap`. diff --git a/server/node_modules/@isaacs/cliui/build/index.cjs b/server/node_modules/@isaacs/cliui/build/index.cjs new file mode 100644 index 0000000..aca2b85 --- /dev/null +++ b/server/node_modules/@isaacs/cliui/build/index.cjs @@ -0,0 +1,317 @@ +'use strict'; + +const align = { + right: alignRight, + center: alignCenter +}; +const top = 0; +const right = 1; +const bottom = 2; +const left = 3; +class UI { + constructor(opts) { + var _a; + this.width = opts.width; + /* c8 ignore start */ + this.wrap = (_a = opts.wrap) !== null && _a !== void 0 ? _a : true; + /* c8 ignore stop */ + this.rows = []; + } + span(...args) { + const cols = this.div(...args); + cols.span = true; + } + resetOutput() { + this.rows = []; + } + div(...args) { + if (args.length === 0) { + this.div(''); + } + if (this.wrap && this.shouldApplyLayoutDSL(...args) && typeof args[0] === 'string') { + return this.applyLayoutDSL(args[0]); + } + const cols = args.map(arg => { + if (typeof arg === 'string') { + return this.colFromString(arg); + } + return arg; + }); + this.rows.push(cols); + return cols; + } + shouldApplyLayoutDSL(...args) { + return args.length === 1 && typeof args[0] === 'string' && + /[\t\n]/.test(args[0]); + } + applyLayoutDSL(str) { + const rows = str.split('\n').map(row => row.split('\t')); + let leftColumnWidth = 0; + // simple heuristic for layout, make sure the + // second column lines up along the left-hand. + // don't allow the first column to take up more + // than 50% of the screen. + rows.forEach(columns => { + if (columns.length > 1 && mixin.stringWidth(columns[0]) > leftColumnWidth) { + leftColumnWidth = Math.min(Math.floor(this.width * 0.5), mixin.stringWidth(columns[0])); + } + }); + // generate a table: + // replacing ' ' with padding calculations. + // using the algorithmically generated width. + rows.forEach(columns => { + this.div(...columns.map((r, i) => { + return { + text: r.trim(), + padding: this.measurePadding(r), + width: (i === 0 && columns.length > 1) ? leftColumnWidth : undefined + }; + })); + }); + return this.rows[this.rows.length - 1]; + } + colFromString(text) { + return { + text, + padding: this.measurePadding(text) + }; + } + measurePadding(str) { + // measure padding without ansi escape codes + const noAnsi = mixin.stripAnsi(str); + return [0, noAnsi.match(/\s*$/)[0].length, 0, noAnsi.match(/^\s*/)[0].length]; + } + toString() { + const lines = []; + this.rows.forEach(row => { + this.rowToString(row, lines); + }); + // don't display any lines with the + // hidden flag set. + return lines + .filter(line => !line.hidden) + .map(line => line.text) + .join('\n'); + } + rowToString(row, lines) { + this.rasterize(row).forEach((rrow, r) => { + let str = ''; + rrow.forEach((col, c) => { + const { width } = row[c]; // the width with padding. + const wrapWidth = this.negatePadding(row[c]); // the width without padding. + let ts = col; // temporary string used during alignment/padding. + if (wrapWidth > mixin.stringWidth(col)) { + ts += ' '.repeat(wrapWidth - mixin.stringWidth(col)); + } + // align the string within its column. + if (row[c].align && row[c].align !== 'left' && this.wrap) { + const fn = align[row[c].align]; + ts = fn(ts, wrapWidth); + if (mixin.stringWidth(ts) < wrapWidth) { + /* c8 ignore start */ + const w = width || 0; + /* c8 ignore stop */ + ts += ' '.repeat(w - mixin.stringWidth(ts) - 1); + } + } + // apply border and padding to string. + const padding = row[c].padding || [0, 0, 0, 0]; + if (padding[left]) { + str += ' '.repeat(padding[left]); + } + str += addBorder(row[c], ts, '| '); + str += ts; + str += addBorder(row[c], ts, ' |'); + if (padding[right]) { + str += ' '.repeat(padding[right]); + } + // if prior row is span, try to render the + // current row on the prior line. + if (r === 0 && lines.length > 0) { + str = this.renderInline(str, lines[lines.length - 1]); + } + }); + // remove trailing whitespace. + lines.push({ + text: str.replace(/ +$/, ''), + span: row.span + }); + }); + return lines; + } + // if the full 'source' can render in + // the target line, do so. + renderInline(source, previousLine) { + const match = source.match(/^ */); + /* c8 ignore start */ + const leadingWhitespace = match ? match[0].length : 0; + /* c8 ignore stop */ + const target = previousLine.text; + const targetTextWidth = mixin.stringWidth(target.trimEnd()); + if (!previousLine.span) { + return source; + } + // if we're not applying wrapping logic, + // just always append to the span. + if (!this.wrap) { + previousLine.hidden = true; + return target + source; + } + if (leadingWhitespace < targetTextWidth) { + return source; + } + previousLine.hidden = true; + return target.trimEnd() + ' '.repeat(leadingWhitespace - targetTextWidth) + source.trimStart(); + } + rasterize(row) { + const rrows = []; + const widths = this.columnWidths(row); + let wrapped; + // word wrap all columns, and create + // a data-structure that is easy to rasterize. + row.forEach((col, c) => { + // leave room for left and right padding. + col.width = widths[c]; + if (this.wrap) { + wrapped = mixin.wrap(col.text, this.negatePadding(col), { hard: true }).split('\n'); + } + else { + wrapped = col.text.split('\n'); + } + if (col.border) { + wrapped.unshift('.' + '-'.repeat(this.negatePadding(col) + 2) + '.'); + wrapped.push("'" + '-'.repeat(this.negatePadding(col) + 2) + "'"); + } + // add top and bottom padding. + if (col.padding) { + wrapped.unshift(...new Array(col.padding[top] || 0).fill('')); + wrapped.push(...new Array(col.padding[bottom] || 0).fill('')); + } + wrapped.forEach((str, r) => { + if (!rrows[r]) { + rrows.push([]); + } + const rrow = rrows[r]; + for (let i = 0; i < c; i++) { + if (rrow[i] === undefined) { + rrow.push(''); + } + } + rrow.push(str); + }); + }); + return rrows; + } + negatePadding(col) { + /* c8 ignore start */ + let wrapWidth = col.width || 0; + /* c8 ignore stop */ + if (col.padding) { + wrapWidth -= (col.padding[left] || 0) + (col.padding[right] || 0); + } + if (col.border) { + wrapWidth -= 4; + } + return wrapWidth; + } + columnWidths(row) { + if (!this.wrap) { + return row.map(col => { + return col.width || mixin.stringWidth(col.text); + }); + } + let unset = row.length; + let remainingWidth = this.width; + // column widths can be set in config. + const widths = row.map(col => { + if (col.width) { + unset--; + remainingWidth -= col.width; + return col.width; + } + return undefined; + }); + // any unset widths should be calculated. + /* c8 ignore start */ + const unsetWidth = unset ? Math.floor(remainingWidth / unset) : 0; + /* c8 ignore stop */ + return widths.map((w, i) => { + if (w === undefined) { + return Math.max(unsetWidth, _minWidth(row[i])); + } + return w; + }); + } +} +function addBorder(col, ts, style) { + if (col.border) { + if (/[.']-+[.']/.test(ts)) { + return ''; + } + if (ts.trim().length !== 0) { + return style; + } + return ' '; + } + return ''; +} +// calculates the minimum width of +// a column, based on padding preferences. +function _minWidth(col) { + const padding = col.padding || []; + const minWidth = 1 + (padding[left] || 0) + (padding[right] || 0); + if (col.border) { + return minWidth + 4; + } + return minWidth; +} +function getWindowWidth() { + /* c8 ignore start */ + if (typeof process === 'object' && process.stdout && process.stdout.columns) { + return process.stdout.columns; + } + return 80; +} +/* c8 ignore stop */ +function alignRight(str, width) { + str = str.trim(); + const strWidth = mixin.stringWidth(str); + if (strWidth < width) { + return ' '.repeat(width - strWidth) + str; + } + return str; +} +function alignCenter(str, width) { + str = str.trim(); + const strWidth = mixin.stringWidth(str); + /* c8 ignore start */ + if (strWidth >= width) { + return str; + } + /* c8 ignore stop */ + return ' '.repeat((width - strWidth) >> 1) + str; +} +let mixin; +function cliui(opts, _mixin) { + mixin = _mixin; + return new UI({ + /* c8 ignore start */ + width: (opts === null || opts === void 0 ? void 0 : opts.width) || getWindowWidth(), + wrap: opts === null || opts === void 0 ? void 0 : opts.wrap + /* c8 ignore stop */ + }); +} + +// Bootstrap cliui with CommonJS dependencies: +const stringWidth = require('string-width-cjs'); +const stripAnsi = require('strip-ansi-cjs'); +const wrap = require('wrap-ansi-cjs'); +function ui(opts) { + return cliui(opts, { + stringWidth, + stripAnsi, + wrap + }); +} + +module.exports = ui; diff --git a/server/node_modules/@isaacs/cliui/build/index.d.cts b/server/node_modules/@isaacs/cliui/build/index.d.cts new file mode 100644 index 0000000..4567f94 --- /dev/null +++ b/server/node_modules/@isaacs/cliui/build/index.d.cts @@ -0,0 +1,43 @@ +interface UIOptions { + width: number; + wrap?: boolean; + rows?: string[]; +} +interface Column { + text: string; + width?: number; + align?: "right" | "left" | "center"; + padding: number[]; + border?: boolean; +} +interface ColumnArray extends Array<Column> { + span: boolean; +} +interface Line { + hidden?: boolean; + text: string; + span?: boolean; +} +declare class UI { + width: number; + wrap: boolean; + rows: ColumnArray[]; + constructor(opts: UIOptions); + span(...args: ColumnArray): void; + resetOutput(): void; + div(...args: (Column | string)[]): ColumnArray; + private shouldApplyLayoutDSL; + private applyLayoutDSL; + private colFromString; + private measurePadding; + toString(): string; + rowToString(row: ColumnArray, lines: Line[]): Line[]; + // if the full 'source' can render in + // the target line, do so. + private renderInline; + private rasterize; + private negatePadding; + private columnWidths; +} +declare function ui(opts: UIOptions): UI; +export { ui as default }; diff --git a/server/node_modules/@isaacs/cliui/build/lib/index.js b/server/node_modules/@isaacs/cliui/build/lib/index.js new file mode 100644 index 0000000..587b5ec --- /dev/null +++ b/server/node_modules/@isaacs/cliui/build/lib/index.js @@ -0,0 +1,302 @@ +'use strict'; +const align = { + right: alignRight, + center: alignCenter +}; +const top = 0; +const right = 1; +const bottom = 2; +const left = 3; +export class UI { + constructor(opts) { + var _a; + this.width = opts.width; + /* c8 ignore start */ + this.wrap = (_a = opts.wrap) !== null && _a !== void 0 ? _a : true; + /* c8 ignore stop */ + this.rows = []; + } + span(...args) { + const cols = this.div(...args); + cols.span = true; + } + resetOutput() { + this.rows = []; + } + div(...args) { + if (args.length === 0) { + this.div(''); + } + if (this.wrap && this.shouldApplyLayoutDSL(...args) && typeof args[0] === 'string') { + return this.applyLayoutDSL(args[0]); + } + const cols = args.map(arg => { + if (typeof arg === 'string') { + return this.colFromString(arg); + } + return arg; + }); + this.rows.push(cols); + return cols; + } + shouldApplyLayoutDSL(...args) { + return args.length === 1 && typeof args[0] === 'string' && + /[\t\n]/.test(args[0]); + } + applyLayoutDSL(str) { + const rows = str.split('\n').map(row => row.split('\t')); + let leftColumnWidth = 0; + // simple heuristic for layout, make sure the + // second column lines up along the left-hand. + // don't allow the first column to take up more + // than 50% of the screen. + rows.forEach(columns => { + if (columns.length > 1 && mixin.stringWidth(columns[0]) > leftColumnWidth) { + leftColumnWidth = Math.min(Math.floor(this.width * 0.5), mixin.stringWidth(columns[0])); + } + }); + // generate a table: + // replacing ' ' with padding calculations. + // using the algorithmically generated width. + rows.forEach(columns => { + this.div(...columns.map((r, i) => { + return { + text: r.trim(), + padding: this.measurePadding(r), + width: (i === 0 && columns.length > 1) ? leftColumnWidth : undefined + }; + })); + }); + return this.rows[this.rows.length - 1]; + } + colFromString(text) { + return { + text, + padding: this.measurePadding(text) + }; + } + measurePadding(str) { + // measure padding without ansi escape codes + const noAnsi = mixin.stripAnsi(str); + return [0, noAnsi.match(/\s*$/)[0].length, 0, noAnsi.match(/^\s*/)[0].length]; + } + toString() { + const lines = []; + this.rows.forEach(row => { + this.rowToString(row, lines); + }); + // don't display any lines with the + // hidden flag set. + return lines + .filter(line => !line.hidden) + .map(line => line.text) + .join('\n'); + } + rowToString(row, lines) { + this.rasterize(row).forEach((rrow, r) => { + let str = ''; + rrow.forEach((col, c) => { + const { width } = row[c]; // the width with padding. + const wrapWidth = this.negatePadding(row[c]); // the width without padding. + let ts = col; // temporary string used during alignment/padding. + if (wrapWidth > mixin.stringWidth(col)) { + ts += ' '.repeat(wrapWidth - mixin.stringWidth(col)); + } + // align the string within its column. + if (row[c].align && row[c].align !== 'left' && this.wrap) { + const fn = align[row[c].align]; + ts = fn(ts, wrapWidth); + if (mixin.stringWidth(ts) < wrapWidth) { + /* c8 ignore start */ + const w = width || 0; + /* c8 ignore stop */ + ts += ' '.repeat(w - mixin.stringWidth(ts) - 1); + } + } + // apply border and padding to string. + const padding = row[c].padding || [0, 0, 0, 0]; + if (padding[left]) { + str += ' '.repeat(padding[left]); + } + str += addBorder(row[c], ts, '| '); + str += ts; + str += addBorder(row[c], ts, ' |'); + if (padding[right]) { + str += ' '.repeat(padding[right]); + } + // if prior row is span, try to render the + // current row on the prior line. + if (r === 0 && lines.length > 0) { + str = this.renderInline(str, lines[lines.length - 1]); + } + }); + // remove trailing whitespace. + lines.push({ + text: str.replace(/ +$/, ''), + span: row.span + }); + }); + return lines; + } + // if the full 'source' can render in + // the target line, do so. + renderInline(source, previousLine) { + const match = source.match(/^ */); + /* c8 ignore start */ + const leadingWhitespace = match ? match[0].length : 0; + /* c8 ignore stop */ + const target = previousLine.text; + const targetTextWidth = mixin.stringWidth(target.trimEnd()); + if (!previousLine.span) { + return source; + } + // if we're not applying wrapping logic, + // just always append to the span. + if (!this.wrap) { + previousLine.hidden = true; + return target + source; + } + if (leadingWhitespace < targetTextWidth) { + return source; + } + previousLine.hidden = true; + return target.trimEnd() + ' '.repeat(leadingWhitespace - targetTextWidth) + source.trimStart(); + } + rasterize(row) { + const rrows = []; + const widths = this.columnWidths(row); + let wrapped; + // word wrap all columns, and create + // a data-structure that is easy to rasterize. + row.forEach((col, c) => { + // leave room for left and right padding. + col.width = widths[c]; + if (this.wrap) { + wrapped = mixin.wrap(col.text, this.negatePadding(col), { hard: true }).split('\n'); + } + else { + wrapped = col.text.split('\n'); + } + if (col.border) { + wrapped.unshift('.' + '-'.repeat(this.negatePadding(col) + 2) + '.'); + wrapped.push("'" + '-'.repeat(this.negatePadding(col) + 2) + "'"); + } + // add top and bottom padding. + if (col.padding) { + wrapped.unshift(...new Array(col.padding[top] || 0).fill('')); + wrapped.push(...new Array(col.padding[bottom] || 0).fill('')); + } + wrapped.forEach((str, r) => { + if (!rrows[r]) { + rrows.push([]); + } + const rrow = rrows[r]; + for (let i = 0; i < c; i++) { + if (rrow[i] === undefined) { + rrow.push(''); + } + } + rrow.push(str); + }); + }); + return rrows; + } + negatePadding(col) { + /* c8 ignore start */ + let wrapWidth = col.width || 0; + /* c8 ignore stop */ + if (col.padding) { + wrapWidth -= (col.padding[left] || 0) + (col.padding[right] || 0); + } + if (col.border) { + wrapWidth -= 4; + } + return wrapWidth; + } + columnWidths(row) { + if (!this.wrap) { + return row.map(col => { + return col.width || mixin.stringWidth(col.text); + }); + } + let unset = row.length; + let remainingWidth = this.width; + // column widths can be set in config. + const widths = row.map(col => { + if (col.width) { + unset--; + remainingWidth -= col.width; + return col.width; + } + return undefined; + }); + // any unset widths should be calculated. + /* c8 ignore start */ + const unsetWidth = unset ? Math.floor(remainingWidth / unset) : 0; + /* c8 ignore stop */ + return widths.map((w, i) => { + if (w === undefined) { + return Math.max(unsetWidth, _minWidth(row[i])); + } + return w; + }); + } +} +function addBorder(col, ts, style) { + if (col.border) { + if (/[.']-+[.']/.test(ts)) { + return ''; + } + if (ts.trim().length !== 0) { + return style; + } + return ' '; + } + return ''; +} +// calculates the minimum width of +// a column, based on padding preferences. +function _minWidth(col) { + const padding = col.padding || []; + const minWidth = 1 + (padding[left] || 0) + (padding[right] || 0); + if (col.border) { + return minWidth + 4; + } + return minWidth; +} +function getWindowWidth() { + /* c8 ignore start */ + if (typeof process === 'object' && process.stdout && process.stdout.columns) { + return process.stdout.columns; + } + return 80; +} +/* c8 ignore stop */ +function alignRight(str, width) { + str = str.trim(); + const strWidth = mixin.stringWidth(str); + if (strWidth < width) { + return ' '.repeat(width - strWidth) + str; + } + return str; +} +function alignCenter(str, width) { + str = str.trim(); + const strWidth = mixin.stringWidth(str); + /* c8 ignore start */ + if (strWidth >= width) { + return str; + } + /* c8 ignore stop */ + return ' '.repeat((width - strWidth) >> 1) + str; +} +let mixin; +export function cliui(opts, _mixin) { + mixin = _mixin; + return new UI({ + /* c8 ignore start */ + width: (opts === null || opts === void 0 ? void 0 : opts.width) || getWindowWidth(), + wrap: opts === null || opts === void 0 ? void 0 : opts.wrap + /* c8 ignore stop */ + }); +} diff --git a/server/node_modules/@isaacs/cliui/index.mjs b/server/node_modules/@isaacs/cliui/index.mjs new file mode 100644 index 0000000..5177519 --- /dev/null +++ b/server/node_modules/@isaacs/cliui/index.mjs @@ -0,0 +1,14 @@ +// Bootstrap cliui with ESM dependencies: +import { cliui } from './build/lib/index.js' + +import stringWidth from 'string-width' +import stripAnsi from 'strip-ansi' +import wrap from 'wrap-ansi' + +export default function ui (opts) { + return cliui(opts, { + stringWidth, + stripAnsi, + wrap + }) +} diff --git a/server/node_modules/@isaacs/cliui/package.json b/server/node_modules/@isaacs/cliui/package.json new file mode 100644 index 0000000..7a95253 --- /dev/null +++ b/server/node_modules/@isaacs/cliui/package.json @@ -0,0 +1,86 @@ +{ + "name": "@isaacs/cliui", + "version": "8.0.2", + "description": "easily create complex multi-column command-line-interfaces", + "main": "build/index.cjs", + "exports": { + ".": [ + { + "import": "./index.mjs", + "require": "./build/index.cjs" + }, + "./build/index.cjs" + ] + }, + "type": "module", + "module": "./index.mjs", + "scripts": { + "check": "standardx '**/*.ts' && standardx '**/*.js' && standardx '**/*.cjs'", + "fix": "standardx --fix '**/*.ts' && standardx --fix '**/*.js' && standardx --fix '**/*.cjs'", + "pretest": "rimraf build && tsc -p tsconfig.test.json && cross-env NODE_ENV=test npm run build:cjs", + "test": "c8 mocha ./test/*.cjs", + "test:esm": "c8 mocha ./test/**/*.mjs", + "postest": "check", + "coverage": "c8 report --check-coverage", + "precompile": "rimraf build", + "compile": "tsc", + "postcompile": "npm run build:cjs", + "build:cjs": "rollup -c", + "prepare": "npm run compile" + }, + "repository": "yargs/cliui", + "standard": { + "ignore": [ + "**/example/**" + ], + "globals": [ + "it" + ] + }, + "keywords": [ + "cli", + "command-line", + "layout", + "design", + "console", + "wrap", + "table" + ], + "author": "Ben Coe <ben@npmjs.com>", + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "devDependencies": { + "@types/node": "^14.0.27", + "@typescript-eslint/eslint-plugin": "^4.0.0", + "@typescript-eslint/parser": "^4.0.0", + "c8": "^7.3.0", + "chai": "^4.2.0", + "chalk": "^4.1.0", + "cross-env": "^7.0.2", + "eslint": "^7.6.0", + "eslint-plugin-import": "^2.22.0", + "eslint-plugin-node": "^11.1.0", + "gts": "^3.0.0", + "mocha": "^10.0.0", + "rimraf": "^3.0.2", + "rollup": "^2.23.1", + "rollup-plugin-ts": "^3.0.2", + "standardx": "^7.0.0", + "typescript": "^4.0.0" + }, + "files": [ + "build", + "index.mjs", + "!*.d.ts" + ], + "engines": { + "node": ">=12" + } +} diff --git a/server/node_modules/@pkgjs/parseargs/.editorconfig b/server/node_modules/@pkgjs/parseargs/.editorconfig new file mode 100644 index 0000000..b140163 --- /dev/null +++ b/server/node_modules/@pkgjs/parseargs/.editorconfig @@ -0,0 +1,14 @@ +# EditorConfig is awesome: http://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Copied from Node.js to ease compatibility in PR. +[*] +charset = utf-8 +end_of_line = lf +indent_size = 2 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true +quote_type = single diff --git a/server/node_modules/@pkgjs/parseargs/CHANGELOG.md b/server/node_modules/@pkgjs/parseargs/CHANGELOG.md new file mode 100644 index 0000000..2adc7d3 --- /dev/null +++ b/server/node_modules/@pkgjs/parseargs/CHANGELOG.md @@ -0,0 +1,147 @@ +# Changelog + +## [0.11.0](https://github.com/pkgjs/parseargs/compare/v0.10.0...v0.11.0) (2022-10-08) + + +### Features + +* add `default` option parameter ([#142](https://github.com/pkgjs/parseargs/issues/142)) ([cd20847](https://github.com/pkgjs/parseargs/commit/cd20847a00b2f556aa9c085ac83b942c60868ec1)) + +## [0.10.0](https://github.com/pkgjs/parseargs/compare/v0.9.1...v0.10.0) (2022-07-21) + + +### Features + +* add parsed meta-data to returned properties ([#129](https://github.com/pkgjs/parseargs/issues/129)) ([91bfb4d](https://github.com/pkgjs/parseargs/commit/91bfb4d3f7b6937efab1b27c91c45d1205f1497e)) + +## [0.9.1](https://github.com/pkgjs/parseargs/compare/v0.9.0...v0.9.1) (2022-06-20) + + +### Bug Fixes + +* **runtime:** support node 14+ ([#135](https://github.com/pkgjs/parseargs/issues/135)) ([6a1c5a6](https://github.com/pkgjs/parseargs/commit/6a1c5a6f7cadf2f035e004027e2742e3c4ce554b)) + +## [0.9.0](https://github.com/pkgjs/parseargs/compare/v0.8.0...v0.9.0) (2022-05-23) + + +### ⚠ BREAKING CHANGES + +* drop handling of electron arguments (#121) + +### Code Refactoring + +* drop handling of electron arguments ([#121](https://github.com/pkgjs/parseargs/issues/121)) ([a2ffd53](https://github.com/pkgjs/parseargs/commit/a2ffd537c244a062371522b955acb45a404fc9f2)) + +## [0.8.0](https://github.com/pkgjs/parseargs/compare/v0.7.1...v0.8.0) (2022-05-16) + + +### ⚠ BREAKING CHANGES + +* switch type:string option arguments to greedy, but with error for suspect cases in strict mode (#88) +* positionals now opt-in when strict:true (#116) +* create result.values with null prototype (#111) + +### Features + +* create result.values with null prototype ([#111](https://github.com/pkgjs/parseargs/issues/111)) ([9d539c3](https://github.com/pkgjs/parseargs/commit/9d539c3d57f269c160e74e0656ad4fa84ff92ec2)) +* positionals now opt-in when strict:true ([#116](https://github.com/pkgjs/parseargs/issues/116)) ([3643338](https://github.com/pkgjs/parseargs/commit/364333826b746e8a7dc5505b4b22fd19ac51df3b)) +* switch type:string option arguments to greedy, but with error for suspect cases in strict mode ([#88](https://github.com/pkgjs/parseargs/issues/88)) ([c2b5e72](https://github.com/pkgjs/parseargs/commit/c2b5e72161991dfdc535909f1327cc9b970fe7e8)) + +### [0.7.1](https://github.com/pkgjs/parseargs/compare/v0.7.0...v0.7.1) (2022-04-15) + + +### Bug Fixes + +* resist pollution ([#106](https://github.com/pkgjs/parseargs/issues/106)) ([ecf2dec](https://github.com/pkgjs/parseargs/commit/ecf2dece0a9f2a76d789384d5d71c68ffe64022a)) + +## [0.7.0](https://github.com/pkgjs/parseargs/compare/v0.6.0...v0.7.0) (2022-04-13) + + +### Features + +* Add strict mode to parser ([#74](https://github.com/pkgjs/parseargs/issues/74)) ([8267d02](https://github.com/pkgjs/parseargs/commit/8267d02083a87b8b8a71fcce08348d1e031ea91c)) + +## [0.6.0](https://github.com/pkgjs/parseargs/compare/v0.5.0...v0.6.0) (2022-04-11) + + +### ⚠ BREAKING CHANGES + +* rework results to remove redundant `flags` property and store value true for boolean options (#83) +* switch to existing ERR_INVALID_ARG_VALUE (#97) + +### Code Refactoring + +* rework results to remove redundant `flags` property and store value true for boolean options ([#83](https://github.com/pkgjs/parseargs/issues/83)) ([be153db](https://github.com/pkgjs/parseargs/commit/be153dbed1d488cb7b6e27df92f601ba7337713d)) +* switch to existing ERR_INVALID_ARG_VALUE ([#97](https://github.com/pkgjs/parseargs/issues/97)) ([084a23f](https://github.com/pkgjs/parseargs/commit/084a23f9fde2da030b159edb1c2385f24579ce40)) + +## [0.5.0](https://github.com/pkgjs/parseargs/compare/v0.4.0...v0.5.0) (2022-04-10) + + +### ⚠ BREAKING CHANGES + +* Require type to be specified for each supplied option (#95) + +### Features + +* Require type to be specified for each supplied option ([#95](https://github.com/pkgjs/parseargs/issues/95)) ([02cd018](https://github.com/pkgjs/parseargs/commit/02cd01885b8aaa59f2db8308f2d4479e64340068)) + +## [0.4.0](https://github.com/pkgjs/parseargs/compare/v0.3.0...v0.4.0) (2022-03-12) + + +### ⚠ BREAKING CHANGES + +* parsing, revisit short option groups, add support for combined short and value (#75) +* restructure configuration to take options bag (#63) + +### Code Refactoring + +* parsing, revisit short option groups, add support for combined short and value ([#75](https://github.com/pkgjs/parseargs/issues/75)) ([a92600f](https://github.com/pkgjs/parseargs/commit/a92600fa6c214508ab1e016fa55879a314f541af)) +* restructure configuration to take options bag ([#63](https://github.com/pkgjs/parseargs/issues/63)) ([b412095](https://github.com/pkgjs/parseargs/commit/b4120957d90e809ee8b607b06e747d3e6a6b213e)) + +## [0.3.0](https://github.com/pkgjs/parseargs/compare/v0.2.0...v0.3.0) (2022-02-06) + + +### Features + +* **parser:** support short-option groups ([#59](https://github.com/pkgjs/parseargs/issues/59)) ([882067b](https://github.com/pkgjs/parseargs/commit/882067bc2d7cbc6b796f8e5a079a99bc99d4e6ba)) + +## [0.2.0](https://github.com/pkgjs/parseargs/compare/v0.1.1...v0.2.0) (2022-02-05) + + +### Features + +* basic support for shorts ([#50](https://github.com/pkgjs/parseargs/issues/50)) ([a2f36d7](https://github.com/pkgjs/parseargs/commit/a2f36d7da4145af1c92f76806b7fe2baf6beeceb)) + + +### Bug Fixes + +* always store value for a=b ([#43](https://github.com/pkgjs/parseargs/issues/43)) ([a85e8dc](https://github.com/pkgjs/parseargs/commit/a85e8dc06379fd2696ee195cc625de8fac6aee42)) +* support single dash as positional ([#49](https://github.com/pkgjs/parseargs/issues/49)) ([d795bf8](https://github.com/pkgjs/parseargs/commit/d795bf877d068fd67aec381f30b30b63f97109ad)) + +### [0.1.1](https://github.com/pkgjs/parseargs/compare/v0.1.0...v0.1.1) (2022-01-25) + + +### Bug Fixes + +* only use arrays in results for multiples ([#42](https://github.com/pkgjs/parseargs/issues/42)) ([c357584](https://github.com/pkgjs/parseargs/commit/c357584847912506319ed34a0840080116f4fd65)) + +## 0.1.0 (2022-01-22) + + +### Features + +* expand scenarios covered by default arguments for environments ([#20](https://github.com/pkgjs/parseargs/issues/20)) ([582ada7](https://github.com/pkgjs/parseargs/commit/582ada7be0eca3a73d6e0bd016e7ace43449fa4c)) +* update readme and include contributing guidelines ([8edd6fc](https://github.com/pkgjs/parseargs/commit/8edd6fc863cd705f6fac732724159ebe8065a2b0)) + + +### Bug Fixes + +* do not strip excess leading dashes on long option names ([#21](https://github.com/pkgjs/parseargs/issues/21)) ([f848590](https://github.com/pkgjs/parseargs/commit/f848590ebf3249ed5979ff47e003fa6e1a8ec5c0)) +* name & readme ([3f057c1](https://github.com/pkgjs/parseargs/commit/3f057c1b158a1bdbe878c64b57460c58e56e465f)) +* package.json values ([9bac300](https://github.com/pkgjs/parseargs/commit/9bac300e00cd76c77076bf9e75e44f8929512da9)) +* update readme name ([957d8d9](https://github.com/pkgjs/parseargs/commit/957d8d96e1dcb48297c0a14345d44c0123b2883e)) + + +### Build System + +* first release as minor ([421c6e2](https://github.com/pkgjs/parseargs/commit/421c6e2569a8668ad14fac5a5af5be60479a7571)) diff --git a/server/node_modules/@pkgjs/parseargs/LICENSE b/server/node_modules/@pkgjs/parseargs/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/server/node_modules/@pkgjs/parseargs/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/server/node_modules/@pkgjs/parseargs/README.md b/server/node_modules/@pkgjs/parseargs/README.md new file mode 100644 index 0000000..0a04192 --- /dev/null +++ b/server/node_modules/@pkgjs/parseargs/README.md @@ -0,0 +1,413 @@ +<!-- omit in toc --> +# parseArgs + +[![Coverage][coverage-image]][coverage-url] + +Polyfill of `util.parseArgs()` + +## `util.parseArgs([config])` + +<!-- YAML +added: v18.3.0 +changes: + - version: REPLACEME + pr-url: https://github.com/nodejs/node/pull/43459 + description: add support for returning detailed parse information + using `tokens` in input `config` and returned properties. +--> + +> Stability: 1 - Experimental + +* `config` {Object} Used to provide arguments for parsing and to configure + the parser. `config` supports the following properties: + * `args` {string\[]} array of argument strings. **Default:** `process.argv` + with `execPath` and `filename` removed. + * `options` {Object} Used to describe arguments known to the parser. + Keys of `options` are the long names of options and values are an + {Object} accepting the following properties: + * `type` {string} Type of argument, which must be either `boolean` or `string`. + * `multiple` {boolean} Whether this option can be provided multiple + times. If `true`, all values will be collected in an array. If + `false`, values for the option are last-wins. **Default:** `false`. + * `short` {string} A single character alias for the option. + * `default` {string | boolean | string\[] | boolean\[]} The default option + value when it is not set by args. It must be of the same type as the + the `type` property. When `multiple` is `true`, it must be an array. + * `strict` {boolean} Should an error be thrown when unknown arguments + are encountered, or when arguments are passed that do not match the + `type` configured in `options`. + **Default:** `true`. + * `allowPositionals` {boolean} Whether this command accepts positional + arguments. + **Default:** `false` if `strict` is `true`, otherwise `true`. + * `tokens` {boolean} Return the parsed tokens. This is useful for extending + the built-in behavior, from adding additional checks through to reprocessing + the tokens in different ways. + **Default:** `false`. + +* Returns: {Object} The parsed command line arguments: + * `values` {Object} A mapping of parsed option names with their {string} + or {boolean} values. + * `positionals` {string\[]} Positional arguments. + * `tokens` {Object\[] | undefined} See [parseArgs tokens](#parseargs-tokens) + section. Only returned if `config` includes `tokens: true`. + +Provides a higher level API for command-line argument parsing than interacting +with `process.argv` directly. Takes a specification for the expected arguments +and returns a structured object with the parsed options and positionals. + +```mjs +import { parseArgs } from 'node:util'; +const args = ['-f', '--bar', 'b']; +const options = { + foo: { + type: 'boolean', + short: 'f' + }, + bar: { + type: 'string' + } +}; +const { + values, + positionals +} = parseArgs({ args, options }); +console.log(values, positionals); +// Prints: [Object: null prototype] { foo: true, bar: 'b' } [] +``` + +```cjs +const { parseArgs } = require('node:util'); +const args = ['-f', '--bar', 'b']; +const options = { + foo: { + type: 'boolean', + short: 'f' + }, + bar: { + type: 'string' + } +}; +const { + values, + positionals +} = parseArgs({ args, options }); +console.log(values, positionals); +// Prints: [Object: null prototype] { foo: true, bar: 'b' } [] +``` + +`util.parseArgs` is experimental and behavior may change. Join the +conversation in [pkgjs/parseargs][] to contribute to the design. + +### `parseArgs` `tokens` + +Detailed parse information is available for adding custom behaviours by +specifying `tokens: true` in the configuration. +The returned tokens have properties describing: + +* all tokens + * `kind` {string} One of 'option', 'positional', or 'option-terminator'. + * `index` {number} Index of element in `args` containing token. So the + source argument for a token is `args[token.index]`. +* option tokens + * `name` {string} Long name of option. + * `rawName` {string} How option used in args, like `-f` of `--foo`. + * `value` {string | undefined} Option value specified in args. + Undefined for boolean options. + * `inlineValue` {boolean | undefined} Whether option value specified inline, + like `--foo=bar`. +* positional tokens + * `value` {string} The value of the positional argument in args (i.e. `args[index]`). +* option-terminator token + +The returned tokens are in the order encountered in the input args. Options +that appear more than once in args produce a token for each use. Short option +groups like `-xy` expand to a token for each option. So `-xxx` produces +three tokens. + +For example to use the returned tokens to add support for a negated option +like `--no-color`, the tokens can be reprocessed to change the value stored +for the negated option. + +```mjs +import { parseArgs } from 'node:util'; + +const options = { + 'color': { type: 'boolean' }, + 'no-color': { type: 'boolean' }, + 'logfile': { type: 'string' }, + 'no-logfile': { type: 'boolean' }, +}; +const { values, tokens } = parseArgs({ options, tokens: true }); + +// Reprocess the option tokens and overwrite the returned values. +tokens + .filter((token) => token.kind === 'option') + .forEach((token) => { + if (token.name.startsWith('no-')) { + // Store foo:false for --no-foo + const positiveName = token.name.slice(3); + values[positiveName] = false; + delete values[token.name]; + } else { + // Resave value so last one wins if both --foo and --no-foo. + values[token.name] = token.value ?? true; + } + }); + +const color = values.color; +const logfile = values.logfile ?? 'default.log'; + +console.log({ logfile, color }); +``` + +```cjs +const { parseArgs } = require('node:util'); + +const options = { + 'color': { type: 'boolean' }, + 'no-color': { type: 'boolean' }, + 'logfile': { type: 'string' }, + 'no-logfile': { type: 'boolean' }, +}; +const { values, tokens } = parseArgs({ options, tokens: true }); + +// Reprocess the option tokens and overwrite the returned values. +tokens + .filter((token) => token.kind === 'option') + .forEach((token) => { + if (token.name.startsWith('no-')) { + // Store foo:false for --no-foo + const positiveName = token.name.slice(3); + values[positiveName] = false; + delete values[token.name]; + } else { + // Resave value so last one wins if both --foo and --no-foo. + values[token.name] = token.value ?? true; + } + }); + +const color = values.color; +const logfile = values.logfile ?? 'default.log'; + +console.log({ logfile, color }); +``` + +Example usage showing negated options, and when an option is used +multiple ways then last one wins. + +```console +$ node negate.js +{ logfile: 'default.log', color: undefined } +$ node negate.js --no-logfile --no-color +{ logfile: false, color: false } +$ node negate.js --logfile=test.log --color +{ logfile: 'test.log', color: true } +$ node negate.js --no-logfile --logfile=test.log --color --no-color +{ logfile: 'test.log', color: false } +``` + +----- + +<!-- omit in toc --> +## Table of Contents +- [`util.parseArgs([config])`](#utilparseargsconfig) +- [Scope](#scope) +- [Version Matchups](#version-matchups) +- [🚀 Getting Started](#-getting-started) +- [🙌 Contributing](#-contributing) +- [💡 `process.mainArgs` Proposal](#-processmainargs-proposal) + - [Implementation:](#implementation) +- [📃 Examples](#-examples) +- [F.A.Qs](#faqs) +- [Links & Resources](#links--resources) + +----- + +## Scope + +It is already possible to build great arg parsing modules on top of what Node.js provides; the prickly API is abstracted away by these modules. Thus, process.parseArgs() is not necessarily intended for library authors; it is intended for developers of simple CLI tools, ad-hoc scripts, deployed Node.js applications, and learning materials. + +It is exceedingly difficult to provide an API which would both be friendly to these Node.js users while being extensible enough for libraries to build upon. We chose to prioritize these use cases because these are currently not well-served by Node.js' API. + +---- + +## Version Matchups + +| Node.js | @pkgjs/parseArgs | +| -- | -- | +| [v18.3.0](https://nodejs.org/docs/latest-v18.x/api/util.html#utilparseargsconfig) | [v0.9.1](https://github.com/pkgjs/parseargs/tree/v0.9.1#utilparseargsconfig) | +| [v16.17.0](https://nodejs.org/dist/latest-v16.x/docs/api/util.html#utilparseargsconfig), [v18.7.0](https://nodejs.org/docs/latest-v18.x/api/util.html#utilparseargsconfig) | [0.10.0](https://github.com/pkgjs/parseargs/tree/v0.10.0#utilparseargsconfig) | + +---- + +## 🚀 Getting Started + +1. **Install dependencies.** + + ```bash + npm install + ``` + +2. **Open the index.js file and start editing!** + +3. **Test your code by calling parseArgs through our test file** + + ```bash + npm test + ``` + +---- + +## 🙌 Contributing + +Any person who wants to contribute to the initiative is welcome! Please first read the [Contributing Guide](CONTRIBUTING.md) + +Additionally, reading the [`Examples w/ Output`](#-examples-w-output) section of this document will be the best way to familiarize yourself with the target expected behavior for parseArgs() once it is fully implemented. + +This package was implemented using [tape](https://www.npmjs.com/package/tape) as its test harness. + +---- + +## 💡 `process.mainArgs` Proposal + +> Note: This can be moved forward independently of the `util.parseArgs()` proposal/work. + +### Implementation: + +```javascript +process.mainArgs = process.argv.slice(process._exec ? 1 : 2) +``` + +---- + +## 📃 Examples + +```js +const { parseArgs } = require('@pkgjs/parseargs'); +``` + +```js +const { parseArgs } = require('@pkgjs/parseargs'); +// specify the options that may be used +const options = { + foo: { type: 'string'}, + bar: { type: 'boolean' }, +}; +const args = ['--foo=a', '--bar']; +const { values, positionals } = parseArgs({ args, options }); +// values = { foo: 'a', bar: true } +// positionals = [] +``` + +```js +const { parseArgs } = require('@pkgjs/parseargs'); +// type:string & multiple +const options = { + foo: { + type: 'string', + multiple: true, + }, +}; +const args = ['--foo=a', '--foo', 'b']; +const { values, positionals } = parseArgs({ args, options }); +// values = { foo: [ 'a', 'b' ] } +// positionals = [] +``` + +```js +const { parseArgs } = require('@pkgjs/parseargs'); +// shorts +const options = { + foo: { + short: 'f', + type: 'boolean' + }, +}; +const args = ['-f', 'b']; +const { values, positionals } = parseArgs({ args, options, allowPositionals: true }); +// values = { foo: true } +// positionals = ['b'] +``` + +```js +const { parseArgs } = require('@pkgjs/parseargs'); +// unconfigured +const options = {}; +const args = ['-f', '--foo=a', '--bar', 'b']; +const { values, positionals } = parseArgs({ strict: false, args, options, allowPositionals: true }); +// values = { f: true, foo: 'a', bar: true } +// positionals = ['b'] +``` + +---- + +## F.A.Qs + +- Is `cmd --foo=bar baz` the same as `cmd baz --foo=bar`? + - yes +- Does the parser execute a function? + - no +- Does the parser execute one of several functions, depending on input? + - no +- Can subcommands take options that are distinct from the main command? + - no +- Does it output generated help when no options match? + - no +- Does it generated short usage? Like: `usage: ls [-ABCFGHLOPRSTUWabcdefghiklmnopqrstuwx1] [file ...]` + - no (no usage/help at all) +- Does the user provide the long usage text? For each option? For the whole command? + - no +- Do subcommands (if implemented) have their own usage output? + - no +- Does usage print if the user runs `cmd --help`? + - no +- Does it set `process.exitCode`? + - no +- Does usage print to stderr or stdout? + - N/A +- Does it check types? (Say, specify that an option is a boolean, number, etc.) + - no +- Can an option have more than one type? (string or false, for example) + - no +- Can the user define a type? (Say, `type: path` to call `path.resolve()` on the argument.) + - no +- Does a `--foo=0o22` mean 0, 22, 18, or "0o22"? + - `"0o22"` +- Does it coerce types? + - no +- Does `--no-foo` coerce to `--foo=false`? For all options? Only boolean options? + - no, it sets `{values:{'no-foo': true}}` +- Is `--foo` the same as `--foo=true`? Only for known booleans? Only at the end? + - no, they are not the same. There is no special handling of `true` as a value so it is just another string. +- Does it read environment variables? Ie, is `FOO=1 cmd` the same as `cmd --foo=1`? + - no +- Do unknown arguments raise an error? Are they parsed? Are they treated as positional arguments? + - no, they are parsed, not treated as positionals +- Does `--` signal the end of options? + - yes +- Is `--` included as a positional? + - no +- Is `program -- foo` the same as `program foo`? + - yes, both store `{positionals:['foo']}` +- Does the API specify whether a `--` was present/relevant? + - no +- Is `-bar` the same as `--bar`? + - no, `-bar` is a short option or options, with expansion logic that follows the + [Utility Syntax Guidelines in POSIX.1-2017](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html). `-bar` expands to `-b`, `-a`, `-r`. +- Is `---foo` the same as `--foo`? + - no + - the first is a long option named `'-foo'` + - the second is a long option named `'foo'` +- Is `-` a positional? ie, `bash some-test.sh | tap -` + - yes + +## Links & Resources + +* [Initial Tooling Issue](https://github.com/nodejs/tooling/issues/19) +* [Initial Proposal](https://github.com/nodejs/node/pull/35015) +* [parseArgs Proposal](https://github.com/nodejs/node/pull/42675) + +[coverage-image]: https://img.shields.io/nycrc/pkgjs/parseargs +[coverage-url]: https://github.com/pkgjs/parseargs/blob/main/.nycrc +[pkgjs/parseargs]: https://github.com/pkgjs/parseargs diff --git a/server/node_modules/@pkgjs/parseargs/examples/is-default-value.js b/server/node_modules/@pkgjs/parseargs/examples/is-default-value.js new file mode 100644 index 0000000..0a67972 --- /dev/null +++ b/server/node_modules/@pkgjs/parseargs/examples/is-default-value.js @@ -0,0 +1,25 @@ +'use strict'; + +// This example shows how to understand if a default value is used or not. + +// 1. const { parseArgs } = require('node:util'); // from node +// 2. const { parseArgs } = require('@pkgjs/parseargs'); // from package +const { parseArgs } = require('..'); // in repo + +const options = { + file: { short: 'f', type: 'string', default: 'FOO' }, +}; + +const { values, tokens } = parseArgs({ options, tokens: true }); + +const isFileDefault = !tokens.some((token) => token.kind === 'option' && + token.name === 'file' +); + +console.log(values); +console.log(`Is the file option [${values.file}] the default value? ${isFileDefault}`); + +// Try the following: +// node is-default-value.js +// node is-default-value.js -f FILE +// node is-default-value.js --file FILE diff --git a/server/node_modules/@pkgjs/parseargs/examples/limit-long-syntax.js b/server/node_modules/@pkgjs/parseargs/examples/limit-long-syntax.js new file mode 100644 index 0000000..943e643 --- /dev/null +++ b/server/node_modules/@pkgjs/parseargs/examples/limit-long-syntax.js @@ -0,0 +1,35 @@ +'use strict'; + +// This is an example of using tokens to add a custom behaviour. +// +// Require the use of `=` for long options and values by blocking +// the use of space separated values. +// So allow `--foo=bar`, and not allow `--foo bar`. +// +// Note: this is not a common behaviour, most CLIs allow both forms. + +// 1. const { parseArgs } = require('node:util'); // from node +// 2. const { parseArgs } = require('@pkgjs/parseargs'); // from package +const { parseArgs } = require('..'); // in repo + +const options = { + file: { short: 'f', type: 'string' }, + log: { type: 'string' }, +}; + +const { values, tokens } = parseArgs({ options, tokens: true }); + +const badToken = tokens.find((token) => token.kind === 'option' && + token.value != null && + token.rawName.startsWith('--') && + !token.inlineValue +); +if (badToken) { + throw new Error(`Option value for '${badToken.rawName}' must be inline, like '${badToken.rawName}=VALUE'`); +} + +console.log(values); + +// Try the following: +// node limit-long-syntax.js -f FILE --log=LOG +// node limit-long-syntax.js --file FILE diff --git a/server/node_modules/@pkgjs/parseargs/examples/negate.js b/server/node_modules/@pkgjs/parseargs/examples/negate.js new file mode 100644 index 0000000..b663469 --- /dev/null +++ b/server/node_modules/@pkgjs/parseargs/examples/negate.js @@ -0,0 +1,43 @@ +'use strict'; + +// This example is used in the documentation. + +// How might I add my own support for --no-foo? + +// 1. const { parseArgs } = require('node:util'); // from node +// 2. const { parseArgs } = require('@pkgjs/parseargs'); // from package +const { parseArgs } = require('..'); // in repo + +const options = { + 'color': { type: 'boolean' }, + 'no-color': { type: 'boolean' }, + 'logfile': { type: 'string' }, + 'no-logfile': { type: 'boolean' }, +}; +const { values, tokens } = parseArgs({ options, tokens: true }); + +// Reprocess the option tokens and overwrite the returned values. +tokens + .filter((token) => token.kind === 'option') + .forEach((token) => { + if (token.name.startsWith('no-')) { + // Store foo:false for --no-foo + const positiveName = token.name.slice(3); + values[positiveName] = false; + delete values[token.name]; + } else { + // Resave value so last one wins if both --foo and --no-foo. + values[token.name] = token.value ?? true; + } + }); + +const color = values.color; +const logfile = values.logfile ?? 'default.log'; + +console.log({ logfile, color }); + +// Try the following: +// node negate.js +// node negate.js --no-logfile --no-color +// negate.js --logfile=test.log --color +// node negate.js --no-logfile --logfile=test.log --color --no-color diff --git a/server/node_modules/@pkgjs/parseargs/examples/no-repeated-options.js b/server/node_modules/@pkgjs/parseargs/examples/no-repeated-options.js new file mode 100644 index 0000000..0c32468 --- /dev/null +++ b/server/node_modules/@pkgjs/parseargs/examples/no-repeated-options.js @@ -0,0 +1,31 @@ +'use strict'; + +// This is an example of using tokens to add a custom behaviour. +// +// Throw an error if an option is used more than once. + +// 1. const { parseArgs } = require('node:util'); // from node +// 2. const { parseArgs } = require('@pkgjs/parseargs'); // from package +const { parseArgs } = require('..'); // in repo + +const options = { + ding: { type: 'boolean', short: 'd' }, + beep: { type: 'boolean', short: 'b' } +}; +const { values, tokens } = parseArgs({ options, tokens: true }); + +const seenBefore = new Set(); +tokens.forEach((token) => { + if (token.kind !== 'option') return; + if (seenBefore.has(token.name)) { + throw new Error(`option '${token.name}' used multiple times`); + } + seenBefore.add(token.name); +}); + +console.log(values); + +// Try the following: +// node no-repeated-options --ding --beep +// node no-repeated-options --beep -b +// node no-repeated-options -ddd diff --git a/server/node_modules/@pkgjs/parseargs/examples/ordered-options.mjs b/server/node_modules/@pkgjs/parseargs/examples/ordered-options.mjs new file mode 100644 index 0000000..8ab7367 --- /dev/null +++ b/server/node_modules/@pkgjs/parseargs/examples/ordered-options.mjs @@ -0,0 +1,41 @@ +// This is an example of using tokens to add a custom behaviour. +// +// This adds a option order check so that --some-unstable-option +// may only be used after --enable-experimental-options +// +// Note: this is not a common behaviour, the order of different options +// does not usually matter. + +import { parseArgs } from '../index.js'; + +function findTokenIndex(tokens, target) { + return tokens.findIndex((token) => token.kind === 'option' && + token.name === target + ); +} + +const experimentalName = 'enable-experimental-options'; +const unstableName = 'some-unstable-option'; + +const options = { + [experimentalName]: { type: 'boolean' }, + [unstableName]: { type: 'boolean' }, +}; + +const { values, tokens } = parseArgs({ options, tokens: true }); + +const experimentalIndex = findTokenIndex(tokens, experimentalName); +const unstableIndex = findTokenIndex(tokens, unstableName); +if (unstableIndex !== -1 && + ((experimentalIndex === -1) || (unstableIndex < experimentalIndex))) { + throw new Error(`'--${experimentalName}' must be specified before '--${unstableName}'`); +} + +console.log(values); + +/* eslint-disable max-len */ +// Try the following: +// node ordered-options.mjs +// node ordered-options.mjs --some-unstable-option +// node ordered-options.mjs --some-unstable-option --enable-experimental-options +// node ordered-options.mjs --enable-experimental-options --some-unstable-option diff --git a/server/node_modules/@pkgjs/parseargs/examples/simple-hard-coded.js b/server/node_modules/@pkgjs/parseargs/examples/simple-hard-coded.js new file mode 100644 index 0000000..eff04c2 --- /dev/null +++ b/server/node_modules/@pkgjs/parseargs/examples/simple-hard-coded.js @@ -0,0 +1,26 @@ +'use strict'; + +// This example is used in the documentation. + +// 1. const { parseArgs } = require('node:util'); // from node +// 2. const { parseArgs } = require('@pkgjs/parseargs'); // from package +const { parseArgs } = require('..'); // in repo + +const args = ['-f', '--bar', 'b']; +const options = { + foo: { + type: 'boolean', + short: 'f' + }, + bar: { + type: 'string' + } +}; +const { + values, + positionals +} = parseArgs({ args, options }); +console.log(values, positionals); + +// Try the following: +// node simple-hard-coded.js diff --git a/server/node_modules/@pkgjs/parseargs/index.js b/server/node_modules/@pkgjs/parseargs/index.js new file mode 100644 index 0000000..b1004c7 --- /dev/null +++ b/server/node_modules/@pkgjs/parseargs/index.js @@ -0,0 +1,396 @@ +'use strict'; + +const { + ArrayPrototypeForEach, + ArrayPrototypeIncludes, + ArrayPrototypeMap, + ArrayPrototypePush, + ArrayPrototypePushApply, + ArrayPrototypeShift, + ArrayPrototypeSlice, + ArrayPrototypeUnshiftApply, + ObjectEntries, + ObjectPrototypeHasOwnProperty: ObjectHasOwn, + StringPrototypeCharAt, + StringPrototypeIndexOf, + StringPrototypeSlice, + StringPrototypeStartsWith, +} = require('./internal/primordials'); + +const { + validateArray, + validateBoolean, + validateBooleanArray, + validateObject, + validateString, + validateStringArray, + validateUnion, +} = require('./internal/validators'); + +const { + kEmptyObject, +} = require('./internal/util'); + +const { + findLongOptionForShort, + isLoneLongOption, + isLoneShortOption, + isLongOptionAndValue, + isOptionValue, + isOptionLikeValue, + isShortOptionAndValue, + isShortOptionGroup, + useDefaultValueOption, + objectGetOwn, + optionsGetOwn, +} = require('./utils'); + +const { + codes: { + ERR_INVALID_ARG_VALUE, + ERR_PARSE_ARGS_INVALID_OPTION_VALUE, + ERR_PARSE_ARGS_UNKNOWN_OPTION, + ERR_PARSE_ARGS_UNEXPECTED_POSITIONAL, + }, +} = require('./internal/errors'); + +function getMainArgs() { + // Work out where to slice process.argv for user supplied arguments. + + // Check node options for scenarios where user CLI args follow executable. + const execArgv = process.execArgv; + if (ArrayPrototypeIncludes(execArgv, '-e') || + ArrayPrototypeIncludes(execArgv, '--eval') || + ArrayPrototypeIncludes(execArgv, '-p') || + ArrayPrototypeIncludes(execArgv, '--print')) { + return ArrayPrototypeSlice(process.argv, 1); + } + + // Normally first two arguments are executable and script, then CLI arguments + return ArrayPrototypeSlice(process.argv, 2); +} + +/** + * In strict mode, throw for possible usage errors like --foo --bar + * + * @param {object} token - from tokens as available from parseArgs + */ +function checkOptionLikeValue(token) { + if (!token.inlineValue && isOptionLikeValue(token.value)) { + // Only show short example if user used short option. + const example = StringPrototypeStartsWith(token.rawName, '--') ? + `'${token.rawName}=-XYZ'` : + `'--${token.name}=-XYZ' or '${token.rawName}-XYZ'`; + const errorMessage = `Option '${token.rawName}' argument is ambiguous. +Did you forget to specify the option argument for '${token.rawName}'? +To specify an option argument starting with a dash use ${example}.`; + throw new ERR_PARSE_ARGS_INVALID_OPTION_VALUE(errorMessage); + } +} + +/** + * In strict mode, throw for usage errors. + * + * @param {object} config - from config passed to parseArgs + * @param {object} token - from tokens as available from parseArgs + */ +function checkOptionUsage(config, token) { + if (!ObjectHasOwn(config.options, token.name)) { + throw new ERR_PARSE_ARGS_UNKNOWN_OPTION( + token.rawName, config.allowPositionals); + } + + const short = optionsGetOwn(config.options, token.name, 'short'); + const shortAndLong = `${short ? `-${short}, ` : ''}--${token.name}`; + const type = optionsGetOwn(config.options, token.name, 'type'); + if (type === 'string' && typeof token.value !== 'string') { + throw new ERR_PARSE_ARGS_INVALID_OPTION_VALUE(`Option '${shortAndLong} <value>' argument missing`); + } + // (Idiomatic test for undefined||null, expecting undefined.) + if (type === 'boolean' && token.value != null) { + throw new ERR_PARSE_ARGS_INVALID_OPTION_VALUE(`Option '${shortAndLong}' does not take an argument`); + } +} + + +/** + * Store the option value in `values`. + * + * @param {string} longOption - long option name e.g. 'foo' + * @param {string|undefined} optionValue - value from user args + * @param {object} options - option configs, from parseArgs({ options }) + * @param {object} values - option values returned in `values` by parseArgs + */ +function storeOption(longOption, optionValue, options, values) { + if (longOption === '__proto__') { + return; // No. Just no. + } + + // We store based on the option value rather than option type, + // preserving the users intent for author to deal with. + const newValue = optionValue ?? true; + if (optionsGetOwn(options, longOption, 'multiple')) { + // Always store value in array, including for boolean. + // values[longOption] starts out not present, + // first value is added as new array [newValue], + // subsequent values are pushed to existing array. + // (note: values has null prototype, so simpler usage) + if (values[longOption]) { + ArrayPrototypePush(values[longOption], newValue); + } else { + values[longOption] = [newValue]; + } + } else { + values[longOption] = newValue; + } +} + +/** + * Store the default option value in `values`. + * + * @param {string} longOption - long option name e.g. 'foo' + * @param {string + * | boolean + * | string[] + * | boolean[]} optionValue - default value from option config + * @param {object} values - option values returned in `values` by parseArgs + */ +function storeDefaultOption(longOption, optionValue, values) { + if (longOption === '__proto__') { + return; // No. Just no. + } + + values[longOption] = optionValue; +} + +/** + * Process args and turn into identified tokens: + * - option (along with value, if any) + * - positional + * - option-terminator + * + * @param {string[]} args - from parseArgs({ args }) or mainArgs + * @param {object} options - option configs, from parseArgs({ options }) + */ +function argsToTokens(args, options) { + const tokens = []; + let index = -1; + let groupCount = 0; + + const remainingArgs = ArrayPrototypeSlice(args); + while (remainingArgs.length > 0) { + const arg = ArrayPrototypeShift(remainingArgs); + const nextArg = remainingArgs[0]; + if (groupCount > 0) + groupCount--; + else + index++; + + // Check if `arg` is an options terminator. + // Guideline 10 in https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html + if (arg === '--') { + // Everything after a bare '--' is considered a positional argument. + ArrayPrototypePush(tokens, { kind: 'option-terminator', index }); + ArrayPrototypePushApply( + tokens, ArrayPrototypeMap(remainingArgs, (arg) => { + return { kind: 'positional', index: ++index, value: arg }; + }) + ); + break; // Finished processing args, leave while loop. + } + + if (isLoneShortOption(arg)) { + // e.g. '-f' + const shortOption = StringPrototypeCharAt(arg, 1); + const longOption = findLongOptionForShort(shortOption, options); + let value; + let inlineValue; + if (optionsGetOwn(options, longOption, 'type') === 'string' && + isOptionValue(nextArg)) { + // e.g. '-f', 'bar' + value = ArrayPrototypeShift(remainingArgs); + inlineValue = false; + } + ArrayPrototypePush( + tokens, + { kind: 'option', name: longOption, rawName: arg, + index, value, inlineValue }); + if (value != null) ++index; + continue; + } + + if (isShortOptionGroup(arg, options)) { + // Expand -fXzy to -f -X -z -y + const expanded = []; + for (let index = 1; index < arg.length; index++) { + const shortOption = StringPrototypeCharAt(arg, index); + const longOption = findLongOptionForShort(shortOption, options); + if (optionsGetOwn(options, longOption, 'type') !== 'string' || + index === arg.length - 1) { + // Boolean option, or last short in group. Well formed. + ArrayPrototypePush(expanded, `-${shortOption}`); + } else { + // String option in middle. Yuck. + // Expand -abfFILE to -a -b -fFILE + ArrayPrototypePush(expanded, `-${StringPrototypeSlice(arg, index)}`); + break; // finished short group + } + } + ArrayPrototypeUnshiftApply(remainingArgs, expanded); + groupCount = expanded.length; + continue; + } + + if (isShortOptionAndValue(arg, options)) { + // e.g. -fFILE + const shortOption = StringPrototypeCharAt(arg, 1); + const longOption = findLongOptionForShort(shortOption, options); + const value = StringPrototypeSlice(arg, 2); + ArrayPrototypePush( + tokens, + { kind: 'option', name: longOption, rawName: `-${shortOption}`, + index, value, inlineValue: true }); + continue; + } + + if (isLoneLongOption(arg)) { + // e.g. '--foo' + const longOption = StringPrototypeSlice(arg, 2); + let value; + let inlineValue; + if (optionsGetOwn(options, longOption, 'type') === 'string' && + isOptionValue(nextArg)) { + // e.g. '--foo', 'bar' + value = ArrayPrototypeShift(remainingArgs); + inlineValue = false; + } + ArrayPrototypePush( + tokens, + { kind: 'option', name: longOption, rawName: arg, + index, value, inlineValue }); + if (value != null) ++index; + continue; + } + + if (isLongOptionAndValue(arg)) { + // e.g. --foo=bar + const equalIndex = StringPrototypeIndexOf(arg, '='); + const longOption = StringPrototypeSlice(arg, 2, equalIndex); + const value = StringPrototypeSlice(arg, equalIndex + 1); + ArrayPrototypePush( + tokens, + { kind: 'option', name: longOption, rawName: `--${longOption}`, + index, value, inlineValue: true }); + continue; + } + + ArrayPrototypePush(tokens, { kind: 'positional', index, value: arg }); + } + + return tokens; +} + +const parseArgs = (config = kEmptyObject) => { + const args = objectGetOwn(config, 'args') ?? getMainArgs(); + const strict = objectGetOwn(config, 'strict') ?? true; + const allowPositionals = objectGetOwn(config, 'allowPositionals') ?? !strict; + const returnTokens = objectGetOwn(config, 'tokens') ?? false; + const options = objectGetOwn(config, 'options') ?? { __proto__: null }; + // Bundle these up for passing to strict-mode checks. + const parseConfig = { args, strict, options, allowPositionals }; + + // Validate input configuration. + validateArray(args, 'args'); + validateBoolean(strict, 'strict'); + validateBoolean(allowPositionals, 'allowPositionals'); + validateBoolean(returnTokens, 'tokens'); + validateObject(options, 'options'); + ArrayPrototypeForEach( + ObjectEntries(options), + ({ 0: longOption, 1: optionConfig }) => { + validateObject(optionConfig, `options.${longOption}`); + + // type is required + const optionType = objectGetOwn(optionConfig, 'type'); + validateUnion(optionType, `options.${longOption}.type`, ['string', 'boolean']); + + if (ObjectHasOwn(optionConfig, 'short')) { + const shortOption = optionConfig.short; + validateString(shortOption, `options.${longOption}.short`); + if (shortOption.length !== 1) { + throw new ERR_INVALID_ARG_VALUE( + `options.${longOption}.short`, + shortOption, + 'must be a single character' + ); + } + } + + const multipleOption = objectGetOwn(optionConfig, 'multiple'); + if (ObjectHasOwn(optionConfig, 'multiple')) { + validateBoolean(multipleOption, `options.${longOption}.multiple`); + } + + const defaultValue = objectGetOwn(optionConfig, 'default'); + if (defaultValue !== undefined) { + let validator; + switch (optionType) { + case 'string': + validator = multipleOption ? validateStringArray : validateString; + break; + + case 'boolean': + validator = multipleOption ? validateBooleanArray : validateBoolean; + break; + } + validator(defaultValue, `options.${longOption}.default`); + } + } + ); + + // Phase 1: identify tokens + const tokens = argsToTokens(args, options); + + // Phase 2: process tokens into parsed option values and positionals + const result = { + values: { __proto__: null }, + positionals: [], + }; + if (returnTokens) { + result.tokens = tokens; + } + ArrayPrototypeForEach(tokens, (token) => { + if (token.kind === 'option') { + if (strict) { + checkOptionUsage(parseConfig, token); + checkOptionLikeValue(token); + } + storeOption(token.name, token.value, options, result.values); + } else if (token.kind === 'positional') { + if (!allowPositionals) { + throw new ERR_PARSE_ARGS_UNEXPECTED_POSITIONAL(token.value); + } + ArrayPrototypePush(result.positionals, token.value); + } + }); + + // Phase 3: fill in default values for missing args + ArrayPrototypeForEach(ObjectEntries(options), ({ 0: longOption, + 1: optionConfig }) => { + const mustSetDefault = useDefaultValueOption(longOption, + optionConfig, + result.values); + if (mustSetDefault) { + storeDefaultOption(longOption, + objectGetOwn(optionConfig, 'default'), + result.values); + } + }); + + + return result; +}; + +module.exports = { + parseArgs, +}; diff --git a/server/node_modules/@pkgjs/parseargs/internal/errors.js b/server/node_modules/@pkgjs/parseargs/internal/errors.js new file mode 100644 index 0000000..e1b237b --- /dev/null +++ b/server/node_modules/@pkgjs/parseargs/internal/errors.js @@ -0,0 +1,47 @@ +'use strict'; + +class ERR_INVALID_ARG_TYPE extends TypeError { + constructor(name, expected, actual) { + super(`${name} must be ${expected} got ${actual}`); + this.code = 'ERR_INVALID_ARG_TYPE'; + } +} + +class ERR_INVALID_ARG_VALUE extends TypeError { + constructor(arg1, arg2, expected) { + super(`The property ${arg1} ${expected}. Received '${arg2}'`); + this.code = 'ERR_INVALID_ARG_VALUE'; + } +} + +class ERR_PARSE_ARGS_INVALID_OPTION_VALUE extends Error { + constructor(message) { + super(message); + this.code = 'ERR_PARSE_ARGS_INVALID_OPTION_VALUE'; + } +} + +class ERR_PARSE_ARGS_UNKNOWN_OPTION extends Error { + constructor(option, allowPositionals) { + const suggestDashDash = allowPositionals ? `. To specify a positional argument starting with a '-', place it at the end of the command after '--', as in '-- ${JSON.stringify(option)}` : ''; + super(`Unknown option '${option}'${suggestDashDash}`); + this.code = 'ERR_PARSE_ARGS_UNKNOWN_OPTION'; + } +} + +class ERR_PARSE_ARGS_UNEXPECTED_POSITIONAL extends Error { + constructor(positional) { + super(`Unexpected argument '${positional}'. This command does not take positional arguments`); + this.code = 'ERR_PARSE_ARGS_UNEXPECTED_POSITIONAL'; + } +} + +module.exports = { + codes: { + ERR_INVALID_ARG_TYPE, + ERR_INVALID_ARG_VALUE, + ERR_PARSE_ARGS_INVALID_OPTION_VALUE, + ERR_PARSE_ARGS_UNKNOWN_OPTION, + ERR_PARSE_ARGS_UNEXPECTED_POSITIONAL, + } +}; diff --git a/server/node_modules/@pkgjs/parseargs/internal/primordials.js b/server/node_modules/@pkgjs/parseargs/internal/primordials.js new file mode 100644 index 0000000..63e23ab --- /dev/null +++ b/server/node_modules/@pkgjs/parseargs/internal/primordials.js @@ -0,0 +1,393 @@ +/* +This file is copied from https://github.com/nodejs/node/blob/v14.19.3/lib/internal/per_context/primordials.js +under the following license: + +Copyright Node.js contributors. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +*/ + +'use strict'; + +/* eslint-disable node-core/prefer-primordials */ + +// This file subclasses and stores the JS builtins that come from the VM +// so that Node.js's builtin modules do not need to later look these up from +// the global proxy, which can be mutated by users. + +// Use of primordials have sometimes a dramatic impact on performance, please +// benchmark all changes made in performance-sensitive areas of the codebase. +// See: https://github.com/nodejs/node/pull/38248 + +const primordials = {}; + +const { + defineProperty: ReflectDefineProperty, + getOwnPropertyDescriptor: ReflectGetOwnPropertyDescriptor, + ownKeys: ReflectOwnKeys, +} = Reflect; + +// `uncurryThis` is equivalent to `func => Function.prototype.call.bind(func)`. +// It is using `bind.bind(call)` to avoid using `Function.prototype.bind` +// and `Function.prototype.call` after it may have been mutated by users. +const { apply, bind, call } = Function.prototype; +const uncurryThis = bind.bind(call); +primordials.uncurryThis = uncurryThis; + +// `applyBind` is equivalent to `func => Function.prototype.apply.bind(func)`. +// It is using `bind.bind(apply)` to avoid using `Function.prototype.bind` +// and `Function.prototype.apply` after it may have been mutated by users. +const applyBind = bind.bind(apply); +primordials.applyBind = applyBind; + +// Methods that accept a variable number of arguments, and thus it's useful to +// also create `${prefix}${key}Apply`, which uses `Function.prototype.apply`, +// instead of `Function.prototype.call`, and thus doesn't require iterator +// destructuring. +const varargsMethods = [ + // 'ArrayPrototypeConcat' is omitted, because it performs the spread + // on its own for arrays and array-likes with a truthy + // @@isConcatSpreadable symbol property. + 'ArrayOf', + 'ArrayPrototypePush', + 'ArrayPrototypeUnshift', + // 'FunctionPrototypeCall' is omitted, since there's 'ReflectApply' + // and 'FunctionPrototypeApply'. + 'MathHypot', + 'MathMax', + 'MathMin', + 'StringPrototypeConcat', + 'TypedArrayOf', +]; + +function getNewKey(key) { + return typeof key === 'symbol' ? + `Symbol${key.description[7].toUpperCase()}${key.description.slice(8)}` : + `${key[0].toUpperCase()}${key.slice(1)}`; +} + +function copyAccessor(dest, prefix, key, { enumerable, get, set }) { + ReflectDefineProperty(dest, `${prefix}Get${key}`, { + value: uncurryThis(get), + enumerable + }); + if (set !== undefined) { + ReflectDefineProperty(dest, `${prefix}Set${key}`, { + value: uncurryThis(set), + enumerable + }); + } +} + +function copyPropsRenamed(src, dest, prefix) { + for (const key of ReflectOwnKeys(src)) { + const newKey = getNewKey(key); + const desc = ReflectGetOwnPropertyDescriptor(src, key); + if ('get' in desc) { + copyAccessor(dest, prefix, newKey, desc); + } else { + const name = `${prefix}${newKey}`; + ReflectDefineProperty(dest, name, desc); + if (varargsMethods.includes(name)) { + ReflectDefineProperty(dest, `${name}Apply`, { + // `src` is bound as the `this` so that the static `this` points + // to the object it was defined on, + // e.g.: `ArrayOfApply` gets a `this` of `Array`: + value: applyBind(desc.value, src), + }); + } + } + } +} + +function copyPropsRenamedBound(src, dest, prefix) { + for (const key of ReflectOwnKeys(src)) { + const newKey = getNewKey(key); + const desc = ReflectGetOwnPropertyDescriptor(src, key); + if ('get' in desc) { + copyAccessor(dest, prefix, newKey, desc); + } else { + const { value } = desc; + if (typeof value === 'function') { + desc.value = value.bind(src); + } + + const name = `${prefix}${newKey}`; + ReflectDefineProperty(dest, name, desc); + if (varargsMethods.includes(name)) { + ReflectDefineProperty(dest, `${name}Apply`, { + value: applyBind(value, src), + }); + } + } + } +} + +function copyPrototype(src, dest, prefix) { + for (const key of ReflectOwnKeys(src)) { + const newKey = getNewKey(key); + const desc = ReflectGetOwnPropertyDescriptor(src, key); + if ('get' in desc) { + copyAccessor(dest, prefix, newKey, desc); + } else { + const { value } = desc; + if (typeof value === 'function') { + desc.value = uncurryThis(value); + } + + const name = `${prefix}${newKey}`; + ReflectDefineProperty(dest, name, desc); + if (varargsMethods.includes(name)) { + ReflectDefineProperty(dest, `${name}Apply`, { + value: applyBind(value), + }); + } + } + } +} + +// Create copies of configurable value properties of the global object +[ + 'Proxy', + 'globalThis', +].forEach((name) => { + // eslint-disable-next-line no-restricted-globals + primordials[name] = globalThis[name]; +}); + +// Create copies of URI handling functions +[ + decodeURI, + decodeURIComponent, + encodeURI, + encodeURIComponent, +].forEach((fn) => { + primordials[fn.name] = fn; +}); + +// Create copies of the namespace objects +[ + 'JSON', + 'Math', + 'Proxy', + 'Reflect', +].forEach((name) => { + // eslint-disable-next-line no-restricted-globals + copyPropsRenamed(global[name], primordials, name); +}); + +// Create copies of intrinsic objects +[ + 'Array', + 'ArrayBuffer', + 'BigInt', + 'BigInt64Array', + 'BigUint64Array', + 'Boolean', + 'DataView', + 'Date', + 'Error', + 'EvalError', + 'Float32Array', + 'Float64Array', + 'Function', + 'Int16Array', + 'Int32Array', + 'Int8Array', + 'Map', + 'Number', + 'Object', + 'RangeError', + 'ReferenceError', + 'RegExp', + 'Set', + 'String', + 'Symbol', + 'SyntaxError', + 'TypeError', + 'URIError', + 'Uint16Array', + 'Uint32Array', + 'Uint8Array', + 'Uint8ClampedArray', + 'WeakMap', + 'WeakSet', +].forEach((name) => { + // eslint-disable-next-line no-restricted-globals + const original = global[name]; + primordials[name] = original; + copyPropsRenamed(original, primordials, name); + copyPrototype(original.prototype, primordials, `${name}Prototype`); +}); + +// Create copies of intrinsic objects that require a valid `this` to call +// static methods. +// Refs: https://www.ecma-international.org/ecma-262/#sec-promise.all +[ + 'Promise', +].forEach((name) => { + // eslint-disable-next-line no-restricted-globals + const original = global[name]; + primordials[name] = original; + copyPropsRenamedBound(original, primordials, name); + copyPrototype(original.prototype, primordials, `${name}Prototype`); +}); + +// Create copies of abstract intrinsic objects that are not directly exposed +// on the global object. +// Refs: https://tc39.es/ecma262/#sec-%typedarray%-intrinsic-object +[ + { name: 'TypedArray', original: Reflect.getPrototypeOf(Uint8Array) }, + { name: 'ArrayIterator', original: { + prototype: Reflect.getPrototypeOf(Array.prototype[Symbol.iterator]()), + } }, + { name: 'StringIterator', original: { + prototype: Reflect.getPrototypeOf(String.prototype[Symbol.iterator]()), + } }, +].forEach(({ name, original }) => { + primordials[name] = original; + // The static %TypedArray% methods require a valid `this`, but can't be bound, + // as they need a subclass constructor as the receiver: + copyPrototype(original, primordials, name); + copyPrototype(original.prototype, primordials, `${name}Prototype`); +}); + +/* eslint-enable node-core/prefer-primordials */ + +const { + ArrayPrototypeForEach, + FunctionPrototypeCall, + Map, + ObjectFreeze, + ObjectSetPrototypeOf, + Set, + SymbolIterator, + WeakMap, + WeakSet, +} = primordials; + +// Because these functions are used by `makeSafe`, which is exposed +// on the `primordials` object, it's important to use const references +// to the primordials that they use: +const createSafeIterator = (factory, next) => { + class SafeIterator { + constructor(iterable) { + this._iterator = factory(iterable); + } + next() { + return next(this._iterator); + } + [SymbolIterator]() { + return this; + } + } + ObjectSetPrototypeOf(SafeIterator.prototype, null); + ObjectFreeze(SafeIterator.prototype); + ObjectFreeze(SafeIterator); + return SafeIterator; +}; + +primordials.SafeArrayIterator = createSafeIterator( + primordials.ArrayPrototypeSymbolIterator, + primordials.ArrayIteratorPrototypeNext +); +primordials.SafeStringIterator = createSafeIterator( + primordials.StringPrototypeSymbolIterator, + primordials.StringIteratorPrototypeNext +); + +const copyProps = (src, dest) => { + ArrayPrototypeForEach(ReflectOwnKeys(src), (key) => { + if (!ReflectGetOwnPropertyDescriptor(dest, key)) { + ReflectDefineProperty( + dest, + key, + ReflectGetOwnPropertyDescriptor(src, key)); + } + }); +}; + +const makeSafe = (unsafe, safe) => { + if (SymbolIterator in unsafe.prototype) { + const dummy = new unsafe(); + let next; // We can reuse the same `next` method. + + ArrayPrototypeForEach(ReflectOwnKeys(unsafe.prototype), (key) => { + if (!ReflectGetOwnPropertyDescriptor(safe.prototype, key)) { + const desc = ReflectGetOwnPropertyDescriptor(unsafe.prototype, key); + if ( + typeof desc.value === 'function' && + desc.value.length === 0 && + SymbolIterator in (FunctionPrototypeCall(desc.value, dummy) ?? {}) + ) { + const createIterator = uncurryThis(desc.value); + next = next ?? uncurryThis(createIterator(dummy).next); + const SafeIterator = createSafeIterator(createIterator, next); + desc.value = function() { + return new SafeIterator(this); + }; + } + ReflectDefineProperty(safe.prototype, key, desc); + } + }); + } else { + copyProps(unsafe.prototype, safe.prototype); + } + copyProps(unsafe, safe); + + ObjectSetPrototypeOf(safe.prototype, null); + ObjectFreeze(safe.prototype); + ObjectFreeze(safe); + return safe; +}; +primordials.makeSafe = makeSafe; + +// Subclass the constructors because we need to use their prototype +// methods later. +// Defining the `constructor` is necessary here to avoid the default +// constructor which uses the user-mutable `%ArrayIteratorPrototype%.next`. +primordials.SafeMap = makeSafe( + Map, + class SafeMap extends Map { + constructor(i) { super(i); } // eslint-disable-line no-useless-constructor + } +); +primordials.SafeWeakMap = makeSafe( + WeakMap, + class SafeWeakMap extends WeakMap { + constructor(i) { super(i); } // eslint-disable-line no-useless-constructor + } +); +primordials.SafeSet = makeSafe( + Set, + class SafeSet extends Set { + constructor(i) { super(i); } // eslint-disable-line no-useless-constructor + } +); +primordials.SafeWeakSet = makeSafe( + WeakSet, + class SafeWeakSet extends WeakSet { + constructor(i) { super(i); } // eslint-disable-line no-useless-constructor + } +); + +ObjectSetPrototypeOf(primordials, null); +ObjectFreeze(primordials); + +module.exports = primordials; diff --git a/server/node_modules/@pkgjs/parseargs/internal/util.js b/server/node_modules/@pkgjs/parseargs/internal/util.js new file mode 100644 index 0000000..b9b8fe5 --- /dev/null +++ b/server/node_modules/@pkgjs/parseargs/internal/util.js @@ -0,0 +1,14 @@ +'use strict'; + +// This is a placeholder for util.js in node.js land. + +const { + ObjectCreate, + ObjectFreeze, +} = require('./primordials'); + +const kEmptyObject = ObjectFreeze(ObjectCreate(null)); + +module.exports = { + kEmptyObject, +}; diff --git a/server/node_modules/@pkgjs/parseargs/internal/validators.js b/server/node_modules/@pkgjs/parseargs/internal/validators.js new file mode 100644 index 0000000..b5ac4fb --- /dev/null +++ b/server/node_modules/@pkgjs/parseargs/internal/validators.js @@ -0,0 +1,89 @@ +'use strict'; + +// This file is a proxy of the original file located at: +// https://github.com/nodejs/node/blob/main/lib/internal/validators.js +// Every addition or modification to this file must be evaluated +// during the PR review. + +const { + ArrayIsArray, + ArrayPrototypeIncludes, + ArrayPrototypeJoin, +} = require('./primordials'); + +const { + codes: { + ERR_INVALID_ARG_TYPE + } +} = require('./errors'); + +function validateString(value, name) { + if (typeof value !== 'string') { + throw new ERR_INVALID_ARG_TYPE(name, 'String', value); + } +} + +function validateUnion(value, name, union) { + if (!ArrayPrototypeIncludes(union, value)) { + throw new ERR_INVALID_ARG_TYPE(name, `('${ArrayPrototypeJoin(union, '|')}')`, value); + } +} + +function validateBoolean(value, name) { + if (typeof value !== 'boolean') { + throw new ERR_INVALID_ARG_TYPE(name, 'Boolean', value); + } +} + +function validateArray(value, name) { + if (!ArrayIsArray(value)) { + throw new ERR_INVALID_ARG_TYPE(name, 'Array', value); + } +} + +function validateStringArray(value, name) { + validateArray(value, name); + for (let i = 0; i < value.length; i++) { + validateString(value[i], `${name}[${i}]`); + } +} + +function validateBooleanArray(value, name) { + validateArray(value, name); + for (let i = 0; i < value.length; i++) { + validateBoolean(value[i], `${name}[${i}]`); + } +} + +/** + * @param {unknown} value + * @param {string} name + * @param {{ + * allowArray?: boolean, + * allowFunction?: boolean, + * nullable?: boolean + * }} [options] + */ +function validateObject(value, name, options) { + const useDefaultOptions = options == null; + const allowArray = useDefaultOptions ? false : options.allowArray; + const allowFunction = useDefaultOptions ? false : options.allowFunction; + const nullable = useDefaultOptions ? false : options.nullable; + if ((!nullable && value === null) || + (!allowArray && ArrayIsArray(value)) || + (typeof value !== 'object' && ( + !allowFunction || typeof value !== 'function' + ))) { + throw new ERR_INVALID_ARG_TYPE(name, 'Object', value); + } +} + +module.exports = { + validateArray, + validateObject, + validateString, + validateStringArray, + validateUnion, + validateBoolean, + validateBooleanArray, +}; diff --git a/server/node_modules/@pkgjs/parseargs/package.json b/server/node_modules/@pkgjs/parseargs/package.json new file mode 100644 index 0000000..0bcc05c --- /dev/null +++ b/server/node_modules/@pkgjs/parseargs/package.json @@ -0,0 +1,36 @@ +{ + "name": "@pkgjs/parseargs", + "version": "0.11.0", + "description": "Polyfill of future proposal for `util.parseArgs()`", + "engines": { + "node": ">=14" + }, + "main": "index.js", + "exports": { + ".": "./index.js", + "./package.json": "./package.json" + }, + "scripts": { + "coverage": "c8 --check-coverage tape 'test/*.js'", + "test": "c8 tape 'test/*.js'", + "posttest": "eslint .", + "fix": "npm run posttest -- --fix" + }, + "repository": { + "type": "git", + "url": "git@github.com:pkgjs/parseargs.git" + }, + "keywords": [], + "author": "", + "license": "MIT", + "bugs": { + "url": "https://github.com/pkgjs/parseargs/issues" + }, + "homepage": "https://github.com/pkgjs/parseargs#readme", + "devDependencies": { + "c8": "^7.10.0", + "eslint": "^8.2.0", + "eslint-plugin-node-core": "iansu/eslint-plugin-node-core", + "tape": "^5.2.2" + } +} diff --git a/server/node_modules/@pkgjs/parseargs/utils.js b/server/node_modules/@pkgjs/parseargs/utils.js new file mode 100644 index 0000000..d7f420a --- /dev/null +++ b/server/node_modules/@pkgjs/parseargs/utils.js @@ -0,0 +1,198 @@ +'use strict'; + +const { + ArrayPrototypeFind, + ObjectEntries, + ObjectPrototypeHasOwnProperty: ObjectHasOwn, + StringPrototypeCharAt, + StringPrototypeIncludes, + StringPrototypeStartsWith, +} = require('./internal/primordials'); + +const { + validateObject, +} = require('./internal/validators'); + +// These are internal utilities to make the parsing logic easier to read, and +// add lots of detail for the curious. They are in a separate file to allow +// unit testing, although that is not essential (this could be rolled into +// main file and just tested implicitly via API). +// +// These routines are for internal use, not for export to client. + +/** + * Return the named property, but only if it is an own property. + */ +function objectGetOwn(obj, prop) { + if (ObjectHasOwn(obj, prop)) + return obj[prop]; +} + +/** + * Return the named options property, but only if it is an own property. + */ +function optionsGetOwn(options, longOption, prop) { + if (ObjectHasOwn(options, longOption)) + return objectGetOwn(options[longOption], prop); +} + +/** + * Determines if the argument may be used as an option value. + * @example + * isOptionValue('V') // returns true + * isOptionValue('-v') // returns true (greedy) + * isOptionValue('--foo') // returns true (greedy) + * isOptionValue(undefined) // returns false + */ +function isOptionValue(value) { + if (value == null) return false; + + // Open Group Utility Conventions are that an option-argument + // is the argument after the option, and may start with a dash. + return true; // greedy! +} + +/** + * Detect whether there is possible confusion and user may have omitted + * the option argument, like `--port --verbose` when `port` of type:string. + * In strict mode we throw errors if value is option-like. + */ +function isOptionLikeValue(value) { + if (value == null) return false; + + return value.length > 1 && StringPrototypeCharAt(value, 0) === '-'; +} + +/** + * Determines if `arg` is just a short option. + * @example '-f' + */ +function isLoneShortOption(arg) { + return arg.length === 2 && + StringPrototypeCharAt(arg, 0) === '-' && + StringPrototypeCharAt(arg, 1) !== '-'; +} + +/** + * Determines if `arg` is a lone long option. + * @example + * isLoneLongOption('a') // returns false + * isLoneLongOption('-a') // returns false + * isLoneLongOption('--foo') // returns true + * isLoneLongOption('--foo=bar') // returns false + */ +function isLoneLongOption(arg) { + return arg.length > 2 && + StringPrototypeStartsWith(arg, '--') && + !StringPrototypeIncludes(arg, '=', 3); +} + +/** + * Determines if `arg` is a long option and value in the same argument. + * @example + * isLongOptionAndValue('--foo') // returns false + * isLongOptionAndValue('--foo=bar') // returns true + */ +function isLongOptionAndValue(arg) { + return arg.length > 2 && + StringPrototypeStartsWith(arg, '--') && + StringPrototypeIncludes(arg, '=', 3); +} + +/** + * Determines if `arg` is a short option group. + * + * See Guideline 5 of the [Open Group Utility Conventions](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html). + * One or more options without option-arguments, followed by at most one + * option that takes an option-argument, should be accepted when grouped + * behind one '-' delimiter. + * @example + * isShortOptionGroup('-a', {}) // returns false + * isShortOptionGroup('-ab', {}) // returns true + * // -fb is an option and a value, not a short option group + * isShortOptionGroup('-fb', { + * options: { f: { type: 'string' } } + * }) // returns false + * isShortOptionGroup('-bf', { + * options: { f: { type: 'string' } } + * }) // returns true + * // -bfb is an edge case, return true and caller sorts it out + * isShortOptionGroup('-bfb', { + * options: { f: { type: 'string' } } + * }) // returns true + */ +function isShortOptionGroup(arg, options) { + if (arg.length <= 2) return false; + if (StringPrototypeCharAt(arg, 0) !== '-') return false; + if (StringPrototypeCharAt(arg, 1) === '-') return false; + + const firstShort = StringPrototypeCharAt(arg, 1); + const longOption = findLongOptionForShort(firstShort, options); + return optionsGetOwn(options, longOption, 'type') !== 'string'; +} + +/** + * Determine if arg is a short string option followed by its value. + * @example + * isShortOptionAndValue('-a', {}); // returns false + * isShortOptionAndValue('-ab', {}); // returns false + * isShortOptionAndValue('-fFILE', { + * options: { foo: { short: 'f', type: 'string' }} + * }) // returns true + */ +function isShortOptionAndValue(arg, options) { + validateObject(options, 'options'); + + if (arg.length <= 2) return false; + if (StringPrototypeCharAt(arg, 0) !== '-') return false; + if (StringPrototypeCharAt(arg, 1) === '-') return false; + + const shortOption = StringPrototypeCharAt(arg, 1); + const longOption = findLongOptionForShort(shortOption, options); + return optionsGetOwn(options, longOption, 'type') === 'string'; +} + +/** + * Find the long option associated with a short option. Looks for a configured + * `short` and returns the short option itself if a long option is not found. + * @example + * findLongOptionForShort('a', {}) // returns 'a' + * findLongOptionForShort('b', { + * options: { bar: { short: 'b' } } + * }) // returns 'bar' + */ +function findLongOptionForShort(shortOption, options) { + validateObject(options, 'options'); + const longOptionEntry = ArrayPrototypeFind( + ObjectEntries(options), + ({ 1: optionConfig }) => objectGetOwn(optionConfig, 'short') === shortOption + ); + return longOptionEntry?.[0] ?? shortOption; +} + +/** + * Check if the given option includes a default value + * and that option has not been set by the input args. + * + * @param {string} longOption - long option name e.g. 'foo' + * @param {object} optionConfig - the option configuration properties + * @param {object} values - option values returned in `values` by parseArgs + */ +function useDefaultValueOption(longOption, optionConfig, values) { + return objectGetOwn(optionConfig, 'default') !== undefined && + values[longOption] === undefined; +} + +module.exports = { + findLongOptionForShort, + isLoneLongOption, + isLoneShortOption, + isLongOptionAndValue, + isOptionValue, + isOptionLikeValue, + isShortOptionAndValue, + isShortOptionGroup, + useDefaultValueOption, + objectGetOwn, + optionsGetOwn, +}; diff --git a/server/node_modules/@protobufjs/aspromise/LICENSE b/server/node_modules/@protobufjs/aspromise/LICENSE new file mode 100644 index 0000000..2a2d560 --- /dev/null +++ b/server/node_modules/@protobufjs/aspromise/LICENSE @@ -0,0 +1,26 @@ +Copyright (c) 2016, Daniel Wirtz All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +* Neither the name of its author, nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/server/node_modules/@protobufjs/aspromise/README.md b/server/node_modules/@protobufjs/aspromise/README.md new file mode 100644 index 0000000..7227096 --- /dev/null +++ b/server/node_modules/@protobufjs/aspromise/README.md @@ -0,0 +1,13 @@ +@protobufjs/aspromise +===================== +[![npm](https://img.shields.io/npm/v/@protobufjs/aspromise.svg)](https://www.npmjs.com/package/@protobufjs/aspromise) + +Returns a promise from a node-style callback function. + +API +--- + +* **asPromise(fn: `function`, ctx: `Object`, ...params: `*`): `Promise<*>`**<br /> + Returns a promise from a node-style callback function. + +**License:** [BSD 3-Clause License](https://opensource.org/licenses/BSD-3-Clause) diff --git a/server/node_modules/@protobufjs/aspromise/index.d.ts b/server/node_modules/@protobufjs/aspromise/index.d.ts new file mode 100644 index 0000000..afbd89a --- /dev/null +++ b/server/node_modules/@protobufjs/aspromise/index.d.ts @@ -0,0 +1,13 @@ +export = asPromise; + +type asPromiseCallback = (error: Error | null, ...params: any[]) => {}; + +/** + * Returns a promise from a node-style callback function. + * @memberof util + * @param {asPromiseCallback} fn Function to call + * @param {*} ctx Function context + * @param {...*} params Function arguments + * @returns {Promise<*>} Promisified function + */ +declare function asPromise(fn: asPromiseCallback, ctx: any, ...params: any[]): Promise<any>; diff --git a/server/node_modules/@protobufjs/aspromise/index.js b/server/node_modules/@protobufjs/aspromise/index.js new file mode 100644 index 0000000..b10f826 --- /dev/null +++ b/server/node_modules/@protobufjs/aspromise/index.js @@ -0,0 +1,52 @@ +"use strict"; +module.exports = asPromise; + +/** + * Callback as used by {@link util.asPromise}. + * @typedef asPromiseCallback + * @type {function} + * @param {Error|null} error Error, if any + * @param {...*} params Additional arguments + * @returns {undefined} + */ + +/** + * Returns a promise from a node-style callback function. + * @memberof util + * @param {asPromiseCallback} fn Function to call + * @param {*} ctx Function context + * @param {...*} params Function arguments + * @returns {Promise<*>} Promisified function + */ +function asPromise(fn, ctx/*, varargs */) { + var params = new Array(arguments.length - 1), + offset = 0, + index = 2, + pending = true; + while (index < arguments.length) + params[offset++] = arguments[index++]; + return new Promise(function executor(resolve, reject) { + params[offset] = function callback(err/*, varargs */) { + if (pending) { + pending = false; + if (err) + reject(err); + else { + var params = new Array(arguments.length - 1), + offset = 0; + while (offset < params.length) + params[offset++] = arguments[offset]; + resolve.apply(null, params); + } + } + }; + try { + fn.apply(ctx || null, params); + } catch (err) { + if (pending) { + pending = false; + reject(err); + } + } + }); +} diff --git a/server/node_modules/@protobufjs/aspromise/package.json b/server/node_modules/@protobufjs/aspromise/package.json new file mode 100644 index 0000000..2d7e503 --- /dev/null +++ b/server/node_modules/@protobufjs/aspromise/package.json @@ -0,0 +1,21 @@ +{ + "name": "@protobufjs/aspromise", + "description": "Returns a promise from a node-style callback function.", + "version": "1.1.2", + "author": "Daniel Wirtz <dcode+protobufjs@dcode.io>", + "repository": { + "type": "git", + "url": "https://github.com/dcodeIO/protobuf.js.git" + }, + "license": "BSD-3-Clause", + "main": "index.js", + "types": "index.d.ts", + "devDependencies": { + "istanbul": "^0.4.5", + "tape": "^4.6.3" + }, + "scripts": { + "test": "tape tests/*.js", + "coverage": "istanbul cover node_modules/tape/bin/tape tests/*.js" + } +} \ No newline at end of file diff --git a/server/node_modules/@protobufjs/aspromise/tests/index.js b/server/node_modules/@protobufjs/aspromise/tests/index.js new file mode 100644 index 0000000..6d8d24c --- /dev/null +++ b/server/node_modules/@protobufjs/aspromise/tests/index.js @@ -0,0 +1,130 @@ +var tape = require("tape"); + +var asPromise = require(".."); + +tape.test("aspromise", function(test) { + + test.test(this.name + " - resolve", function(test) { + + function fn(arg1, arg2, callback) { + test.equal(this, ctx, "function should be called with this = ctx"); + test.equal(arg1, 1, "function should be called with arg1 = 1"); + test.equal(arg2, 2, "function should be called with arg2 = 2"); + callback(null, arg2); + } + + var ctx = {}; + + var promise = asPromise(fn, ctx, 1, 2); + promise.then(function(arg2) { + test.equal(arg2, 2, "promise should be resolved with arg2 = 2"); + test.end(); + }).catch(function(err) { + test.fail("promise should not be rejected (" + err + ")"); + }); + }); + + test.test(this.name + " - reject", function(test) { + + function fn(arg1, arg2, callback) { + test.equal(this, ctx, "function should be called with this = ctx"); + test.equal(arg1, 1, "function should be called with arg1 = 1"); + test.equal(arg2, 2, "function should be called with arg2 = 2"); + callback(arg1); + } + + var ctx = {}; + + var promise = asPromise(fn, ctx, 1, 2); + promise.then(function() { + test.fail("promise should not be resolved"); + }).catch(function(err) { + test.equal(err, 1, "promise should be rejected with err = 1"); + test.end(); + }); + }); + + test.test(this.name + " - resolve twice", function(test) { + + function fn(arg1, arg2, callback) { + test.equal(this, ctx, "function should be called with this = ctx"); + test.equal(arg1, 1, "function should be called with arg1 = 1"); + test.equal(arg2, 2, "function should be called with arg2 = 2"); + callback(null, arg2); + callback(null, arg1); + } + + var ctx = {}; + var count = 0; + + var promise = asPromise(fn, ctx, 1, 2); + promise.then(function(arg2) { + test.equal(arg2, 2, "promise should be resolved with arg2 = 2"); + if (++count > 1) + test.fail("promise should not be resolved twice"); + test.end(); + }).catch(function(err) { + test.fail("promise should not be rejected (" + err + ")"); + }); + }); + + test.test(this.name + " - reject twice", function(test) { + + function fn(arg1, arg2, callback) { + test.equal(this, ctx, "function should be called with this = ctx"); + test.equal(arg1, 1, "function should be called with arg1 = 1"); + test.equal(arg2, 2, "function should be called with arg2 = 2"); + callback(arg1); + callback(arg2); + } + + var ctx = {}; + var count = 0; + + var promise = asPromise(fn, ctx, 1, 2); + promise.then(function() { + test.fail("promise should not be resolved"); + }).catch(function(err) { + test.equal(err, 1, "promise should be rejected with err = 1"); + if (++count > 1) + test.fail("promise should not be rejected twice"); + test.end(); + }); + }); + + test.test(this.name + " - reject error", function(test) { + + function fn(callback) { + test.ok(arguments.length === 1 && typeof callback === "function", "function should be called with just a callback"); + throw 3; + } + + var promise = asPromise(fn, null); + promise.then(function() { + test.fail("promise should not be resolved"); + }).catch(function(err) { + test.equal(err, 3, "promise should be rejected with err = 3"); + test.end(); + }); + }); + + test.test(this.name + " - reject and error", function(test) { + + function fn(callback) { + callback(3); + throw 4; + } + + var count = 0; + + var promise = asPromise(fn, null); + promise.then(function() { + test.fail("promise should not be resolved"); + }).catch(function(err) { + test.equal(err, 3, "promise should be rejected with err = 3"); + if (++count > 1) + test.fail("promise should not be rejected twice"); + test.end(); + }); + }); +}); diff --git a/server/node_modules/@protobufjs/base64/LICENSE b/server/node_modules/@protobufjs/base64/LICENSE new file mode 100644 index 0000000..2a2d560 --- /dev/null +++ b/server/node_modules/@protobufjs/base64/LICENSE @@ -0,0 +1,26 @@ +Copyright (c) 2016, Daniel Wirtz All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +* Neither the name of its author, nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/server/node_modules/@protobufjs/base64/README.md b/server/node_modules/@protobufjs/base64/README.md new file mode 100644 index 0000000..0e2eb33 --- /dev/null +++ b/server/node_modules/@protobufjs/base64/README.md @@ -0,0 +1,19 @@ +@protobufjs/base64 +================== +[![npm](https://img.shields.io/npm/v/@protobufjs/base64.svg)](https://www.npmjs.com/package/@protobufjs/base64) + +A minimal base64 implementation for number arrays. + +API +--- + +* **base64.length(string: `string`): `number`**<br /> + Calculates the byte length of a base64 encoded string. + +* **base64.encode(buffer: `Uint8Array`, start: `number`, end: `number`): `string`**<br /> + Encodes a buffer to a base64 encoded string. + +* **base64.decode(string: `string`, buffer: `Uint8Array`, offset: `number`): `number`**<br /> + Decodes a base64 encoded string to a buffer. + +**License:** [BSD 3-Clause License](https://opensource.org/licenses/BSD-3-Clause) diff --git a/server/node_modules/@protobufjs/base64/index.d.ts b/server/node_modules/@protobufjs/base64/index.d.ts new file mode 100644 index 0000000..16fd7db --- /dev/null +++ b/server/node_modules/@protobufjs/base64/index.d.ts @@ -0,0 +1,32 @@ +/** + * Calculates the byte length of a base64 encoded string. + * @param {string} string Base64 encoded string + * @returns {number} Byte length + */ +export function length(string: string): number; + +/** + * Encodes a buffer to a base64 encoded string. + * @param {Uint8Array} buffer Source buffer + * @param {number} start Source start + * @param {number} end Source end + * @returns {string} Base64 encoded string + */ +export function encode(buffer: Uint8Array, start: number, end: number): string; + +/** + * Decodes a base64 encoded string to a buffer. + * @param {string} string Source string + * @param {Uint8Array} buffer Destination buffer + * @param {number} offset Destination offset + * @returns {number} Number of bytes written + * @throws {Error} If encoding is invalid + */ +export function decode(string: string, buffer: Uint8Array, offset: number): number; + +/** + * Tests if the specified string appears to be base64 encoded. + * @param {string} string String to test + * @returns {boolean} `true` if it appears to be base64 encoded, otherwise false + */ +export function test(string: string): boolean; diff --git a/server/node_modules/@protobufjs/base64/index.js b/server/node_modules/@protobufjs/base64/index.js new file mode 100644 index 0000000..26d5443 --- /dev/null +++ b/server/node_modules/@protobufjs/base64/index.js @@ -0,0 +1,139 @@ +"use strict"; + +/** + * A minimal base64 implementation for number arrays. + * @memberof util + * @namespace + */ +var base64 = exports; + +/** + * Calculates the byte length of a base64 encoded string. + * @param {string} string Base64 encoded string + * @returns {number} Byte length + */ +base64.length = function length(string) { + var p = string.length; + if (!p) + return 0; + var n = 0; + while (--p % 4 > 1 && string.charAt(p) === "=") + ++n; + return Math.ceil(string.length * 3) / 4 - n; +}; + +// Base64 encoding table +var b64 = new Array(64); + +// Base64 decoding table +var s64 = new Array(123); + +// 65..90, 97..122, 48..57, 43, 47 +for (var i = 0; i < 64;) + s64[b64[i] = i < 26 ? i + 65 : i < 52 ? i + 71 : i < 62 ? i - 4 : i - 59 | 43] = i++; + +/** + * Encodes a buffer to a base64 encoded string. + * @param {Uint8Array} buffer Source buffer + * @param {number} start Source start + * @param {number} end Source end + * @returns {string} Base64 encoded string + */ +base64.encode = function encode(buffer, start, end) { + var parts = null, + chunk = []; + var i = 0, // output index + j = 0, // goto index + t; // temporary + while (start < end) { + var b = buffer[start++]; + switch (j) { + case 0: + chunk[i++] = b64[b >> 2]; + t = (b & 3) << 4; + j = 1; + break; + case 1: + chunk[i++] = b64[t | b >> 4]; + t = (b & 15) << 2; + j = 2; + break; + case 2: + chunk[i++] = b64[t | b >> 6]; + chunk[i++] = b64[b & 63]; + j = 0; + break; + } + if (i > 8191) { + (parts || (parts = [])).push(String.fromCharCode.apply(String, chunk)); + i = 0; + } + } + if (j) { + chunk[i++] = b64[t]; + chunk[i++] = 61; + if (j === 1) + chunk[i++] = 61; + } + if (parts) { + if (i) + parts.push(String.fromCharCode.apply(String, chunk.slice(0, i))); + return parts.join(""); + } + return String.fromCharCode.apply(String, chunk.slice(0, i)); +}; + +var invalidEncoding = "invalid encoding"; + +/** + * Decodes a base64 encoded string to a buffer. + * @param {string} string Source string + * @param {Uint8Array} buffer Destination buffer + * @param {number} offset Destination offset + * @returns {number} Number of bytes written + * @throws {Error} If encoding is invalid + */ +base64.decode = function decode(string, buffer, offset) { + var start = offset; + var j = 0, // goto index + t; // temporary + for (var i = 0; i < string.length;) { + var c = string.charCodeAt(i++); + if (c === 61 && j > 1) + break; + if ((c = s64[c]) === undefined) + throw Error(invalidEncoding); + switch (j) { + case 0: + t = c; + j = 1; + break; + case 1: + buffer[offset++] = t << 2 | (c & 48) >> 4; + t = c; + j = 2; + break; + case 2: + buffer[offset++] = (t & 15) << 4 | (c & 60) >> 2; + t = c; + j = 3; + break; + case 3: + buffer[offset++] = (t & 3) << 6 | c; + j = 0; + break; + } + } + if (j === 1) + throw Error(invalidEncoding); + return offset - start; +}; + +/** + * Tests if the specified string appears to be base64 encoded. + * @param {string} string String to test + * @returns {boolean} `true` if probably base64 encoded, otherwise false + */ +base64.test = function test(string) { + return /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(string); +}; diff --git a/server/node_modules/@protobufjs/base64/package.json b/server/node_modules/@protobufjs/base64/package.json new file mode 100644 index 0000000..46e71d4 --- /dev/null +++ b/server/node_modules/@protobufjs/base64/package.json @@ -0,0 +1,21 @@ +{ + "name": "@protobufjs/base64", + "description": "A minimal base64 implementation for number arrays.", + "version": "1.1.2", + "author": "Daniel Wirtz <dcode+protobufjs@dcode.io>", + "repository": { + "type": "git", + "url": "https://github.com/dcodeIO/protobuf.js.git" + }, + "license": "BSD-3-Clause", + "main": "index.js", + "types": "index.d.ts", + "devDependencies": { + "istanbul": "^0.4.5", + "tape": "^4.6.3" + }, + "scripts": { + "test": "tape tests/*.js", + "coverage": "istanbul cover node_modules/tape/bin/tape tests/*.js" + } +} \ No newline at end of file diff --git a/server/node_modules/@protobufjs/base64/tests/index.js b/server/node_modules/@protobufjs/base64/tests/index.js new file mode 100644 index 0000000..89828f2 --- /dev/null +++ b/server/node_modules/@protobufjs/base64/tests/index.js @@ -0,0 +1,46 @@ +var tape = require("tape"); + +var base64 = require(".."); + +var strings = { + "": "", + "a": "YQ==", + "ab": "YWI=", + "abcdefg": "YWJjZGVmZw==", + "abcdefgh": "YWJjZGVmZ2g=", + "abcdefghi": "YWJjZGVmZ2hp" +}; + +tape.test("base64", function(test) { + + Object.keys(strings).forEach(function(str) { + var enc = strings[str]; + + test.equal(base64.test(enc), true, "should detect '" + enc + "' to be base64 encoded"); + + var len = base64.length(enc); + test.equal(len, str.length, "should calculate '" + enc + "' as " + str.length + " bytes"); + + var buf = new Array(len); + var len2 = base64.decode(enc, buf, 0); + test.equal(len2, len, "should decode '" + enc + "' to " + len + " bytes"); + + test.equal(String.fromCharCode.apply(String, buf), str, "should decode '" + enc + "' to '" + str + "'"); + + var enc2 = base64.encode(buf, 0, buf.length); + test.equal(enc2, enc, "should encode '" + str + "' to '" + enc + "'"); + + }); + + test.throws(function() { + var buf = new Array(10); + base64.decode("YQ!", buf, 0); + }, Error, "should throw if encoding is invalid"); + + test.throws(function() { + var buf = new Array(10); + base64.decode("Y", buf, 0); + }, Error, "should throw if string is truncated"); + + test.end(); +}); diff --git a/server/node_modules/@protobufjs/codegen/LICENSE b/server/node_modules/@protobufjs/codegen/LICENSE new file mode 100644 index 0000000..2a2d560 --- /dev/null +++ b/server/node_modules/@protobufjs/codegen/LICENSE @@ -0,0 +1,26 @@ +Copyright (c) 2016, Daniel Wirtz All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +* Neither the name of its author, nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/server/node_modules/@protobufjs/codegen/README.md b/server/node_modules/@protobufjs/codegen/README.md new file mode 100644 index 0000000..0169338 --- /dev/null +++ b/server/node_modules/@protobufjs/codegen/README.md @@ -0,0 +1,49 @@ +@protobufjs/codegen +=================== +[![npm](https://img.shields.io/npm/v/@protobufjs/codegen.svg)](https://www.npmjs.com/package/@protobufjs/codegen) + +A minimalistic code generation utility. + +API +--- + +* **codegen([functionParams: `string[]`], [functionName: string]): `Codegen`**<br /> + Begins generating a function. + +* **codegen.verbose = `false`**<br /> + When set to true, codegen will log generated code to console. Useful for debugging. + +Invoking **codegen** returns an appender function that appends code to the function's body and returns itself: + +* **Codegen(formatString: `string`, [...formatParams: `any`]): Codegen**<br /> + Appends code to the function's body. The format string can contain placeholders specifying the types of inserted format parameters: + + * `%d`: Number (integer or floating point value) + * `%f`: Floating point value + * `%i`: Integer value + * `%j`: JSON.stringify'ed value + * `%s`: String value + * `%%`: Percent sign<br /> + +* **Codegen([scope: `Object.<string,*>`]): `Function`**<br /> + Finishes the function and returns it. + +* **Codegen.toString([functionNameOverride: `string`]): `string`**<br /> + Returns the function as a string. + +Example +------- + +```js +var codegen = require("@protobufjs/codegen"); + +var add = codegen(["a", "b"], "add") // A function with parameters "a" and "b" named "add" + ("// awesome comment") // adds the line to the function's body + ("return a + b - c + %d", 1) // replaces %d with 1 and adds the line to the body + ({ c: 1 }); // adds "c" with a value of 1 to the function's scope + +console.log(add.toString()); // function add(a, b) { return a + b - c + 1 } +console.log(add(1, 2)); // calculates 1 + 2 - 1 + 1 = 3 +``` + +**License:** [BSD 3-Clause License](https://opensource.org/licenses/BSD-3-Clause) diff --git a/server/node_modules/@protobufjs/codegen/index.d.ts b/server/node_modules/@protobufjs/codegen/index.d.ts new file mode 100644 index 0000000..f7fb921 --- /dev/null +++ b/server/node_modules/@protobufjs/codegen/index.d.ts @@ -0,0 +1,31 @@ +export = codegen; + +/** + * Appends code to the function's body. + * @param [formatStringOrScope] Format string or, to finish the function, an object of additional scope variables, if any + * @param [formatParams] Format parameters + * @returns Itself or the generated function if finished + * @throws {Error} If format parameter counts do not match + */ +type Codegen = (formatStringOrScope?: (string|{ [k: string]: any }), ...formatParams: any[]) => (Codegen|Function); + +/** + * Begins generating a function. + * @param functionParams Function parameter names + * @param [functionName] Function name if not anonymous + * @returns Appender that appends code to the function's body + */ +declare function codegen(functionParams: string[], functionName?: string): Codegen; + +/** + * Begins generating a function. + * @param [functionName] Function name if not anonymous + * @returns Appender that appends code to the function's body + */ +declare function codegen(functionName?: string): Codegen; + +declare namespace codegen { + + /** When set to `true`, codegen will log generated code to console. Useful for debugging. */ + let verbose: boolean; +} diff --git a/server/node_modules/@protobufjs/codegen/index.js b/server/node_modules/@protobufjs/codegen/index.js new file mode 100644 index 0000000..de73f80 --- /dev/null +++ b/server/node_modules/@protobufjs/codegen/index.js @@ -0,0 +1,99 @@ +"use strict"; +module.exports = codegen; + +/** + * Begins generating a function. + * @memberof util + * @param {string[]} functionParams Function parameter names + * @param {string} [functionName] Function name if not anonymous + * @returns {Codegen} Appender that appends code to the function's body + */ +function codegen(functionParams, functionName) { + + /* istanbul ignore if */ + if (typeof functionParams === "string") { + functionName = functionParams; + functionParams = undefined; + } + + var body = []; + + /** + * Appends code to the function's body or finishes generation. + * @typedef Codegen + * @type {function} + * @param {string|Object.<string,*>} [formatStringOrScope] Format string or, to finish the function, an object of additional scope variables, if any + * @param {...*} [formatParams] Format parameters + * @returns {Codegen|Function} Itself or the generated function if finished + * @throws {Error} If format parameter counts do not match + */ + + function Codegen(formatStringOrScope) { + // note that explicit array handling below makes this ~50% faster + + // finish the function + if (typeof formatStringOrScope !== "string") { + var source = toString(); + if (codegen.verbose) + console.log("codegen: " + source); // eslint-disable-line no-console + source = "return " + source; + if (formatStringOrScope) { + var scopeKeys = Object.keys(formatStringOrScope), + scopeParams = new Array(scopeKeys.length + 1), + scopeValues = new Array(scopeKeys.length), + scopeOffset = 0; + while (scopeOffset < scopeKeys.length) { + scopeParams[scopeOffset] = scopeKeys[scopeOffset]; + scopeValues[scopeOffset] = formatStringOrScope[scopeKeys[scopeOffset++]]; + } + scopeParams[scopeOffset] = source; + return Function.apply(null, scopeParams).apply(null, scopeValues); // eslint-disable-line no-new-func + } + return Function(source)(); // eslint-disable-line no-new-func + } + + // otherwise append to body + var formatParams = new Array(arguments.length - 1), + formatOffset = 0; + while (formatOffset < formatParams.length) + formatParams[formatOffset] = arguments[++formatOffset]; + formatOffset = 0; + formatStringOrScope = formatStringOrScope.replace(/%([%dfijs])/g, function replace($0, $1) { + var value = formatParams[formatOffset++]; + switch ($1) { + case "d": case "f": return String(Number(value)); + case "i": return String(Math.floor(value)); + case "j": return JSON.stringify(value); + case "s": return String(value); + } + return "%"; + }); + if (formatOffset !== formatParams.length) + throw Error("parameter count mismatch"); + body.push(formatStringOrScope); + return Codegen; + } + + function toString(functionNameOverride) { + return "function " + (functionNameOverride || functionName || "") + "(" + (functionParams && functionParams.join(",") || "") + "){\n " + body.join("\n ") + "\n}"; + } + + Codegen.toString = toString; + return Codegen; +} + +/** + * Begins generating a function. + * @memberof util + * @function codegen + * @param {string} [functionName] Function name if not anonymous + * @returns {Codegen} Appender that appends code to the function's body + * @variation 2 + */ + +/** + * When set to `true`, codegen will log generated code to console. Useful for debugging. + * @name util.codegen.verbose + * @type {boolean} + */ +codegen.verbose = false; diff --git a/server/node_modules/@protobufjs/codegen/package.json b/server/node_modules/@protobufjs/codegen/package.json new file mode 100644 index 0000000..92f2c4c --- /dev/null +++ b/server/node_modules/@protobufjs/codegen/package.json @@ -0,0 +1,13 @@ +{ + "name": "@protobufjs/codegen", + "description": "A minimalistic code generation utility.", + "version": "2.0.4", + "author": "Daniel Wirtz <dcode+protobufjs@dcode.io>", + "repository": { + "type": "git", + "url": "https://github.com/dcodeIO/protobuf.js.git" + }, + "license": "BSD-3-Clause", + "main": "index.js", + "types": "index.d.ts" +} \ No newline at end of file diff --git a/server/node_modules/@protobufjs/codegen/tests/index.js b/server/node_modules/@protobufjs/codegen/tests/index.js new file mode 100644 index 0000000..f3a3db1 --- /dev/null +++ b/server/node_modules/@protobufjs/codegen/tests/index.js @@ -0,0 +1,13 @@ +var codegen = require(".."); + +// new require("benchmark").Suite().add("add", function() { + +var add = codegen(["a", "b"], "add") + ("// awesome comment") + ("return a + b - c + %d", 1) + ({ c: 1 }); + +if (add(1, 2) !== 3) + throw Error("failed"); + +// }).on("cycle", function(event) { process.stdout.write(String(event.target) + "\n"); }).run(); diff --git a/server/node_modules/@protobufjs/eventemitter/LICENSE b/server/node_modules/@protobufjs/eventemitter/LICENSE new file mode 100644 index 0000000..2a2d560 --- /dev/null +++ b/server/node_modules/@protobufjs/eventemitter/LICENSE @@ -0,0 +1,26 @@ +Copyright (c) 2016, Daniel Wirtz All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +* Neither the name of its author, nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/server/node_modules/@protobufjs/eventemitter/README.md b/server/node_modules/@protobufjs/eventemitter/README.md new file mode 100644 index 0000000..998d315 --- /dev/null +++ b/server/node_modules/@protobufjs/eventemitter/README.md @@ -0,0 +1,22 @@ +@protobufjs/eventemitter +======================== +[![npm](https://img.shields.io/npm/v/@protobufjs/eventemitter.svg)](https://www.npmjs.com/package/@protobufjs/eventemitter) + +A minimal event emitter. + +API +--- + +* **new EventEmitter()**<br /> + Constructs a new event emitter instance. + +* **EventEmitter#on(evt: `string`, fn: `function`, [ctx: `Object`]): `EventEmitter`**<br /> + Registers an event listener. + +* **EventEmitter#off([evt: `string`], [fn: `function`]): `EventEmitter`**<br /> + Removes an event listener or any matching listeners if arguments are omitted. + +* **EventEmitter#emit(evt: `string`, ...args: `*`): `EventEmitter`**<br /> + Emits an event by calling its listeners with the specified arguments. + +**License:** [BSD 3-Clause License](https://opensource.org/licenses/BSD-3-Clause) diff --git a/server/node_modules/@protobufjs/eventemitter/index.d.ts b/server/node_modules/@protobufjs/eventemitter/index.d.ts new file mode 100644 index 0000000..4615963 --- /dev/null +++ b/server/node_modules/@protobufjs/eventemitter/index.d.ts @@ -0,0 +1,43 @@ +export = EventEmitter; + +/** + * Constructs a new event emitter instance. + * @classdesc A minimal event emitter. + * @memberof util + * @constructor + */ +declare class EventEmitter { + + /** + * Constructs a new event emitter instance. + * @classdesc A minimal event emitter. + * @memberof util + * @constructor + */ + constructor(); + + /** + * Registers an event listener. + * @param {string} evt Event name + * @param {function} fn Listener + * @param {*} [ctx] Listener context + * @returns {util.EventEmitter} `this` + */ + on(evt: string, fn: () => any, ctx?: any): EventEmitter; + + /** + * Removes an event listener or any matching listeners if arguments are omitted. + * @param {string} [evt] Event name. Removes all listeners if omitted. + * @param {function} [fn] Listener to remove. Removes all listeners of `evt` if omitted. + * @returns {util.EventEmitter} `this` + */ + off(evt?: string, fn?: () => any): EventEmitter; + + /** + * Emits an event by calling its listeners with the specified arguments. + * @param {string} evt Event name + * @param {...*} args Arguments + * @returns {util.EventEmitter} `this` + */ + emit(evt: string, ...args: any[]): EventEmitter; +} diff --git a/server/node_modules/@protobufjs/eventemitter/index.js b/server/node_modules/@protobufjs/eventemitter/index.js new file mode 100644 index 0000000..76ce938 --- /dev/null +++ b/server/node_modules/@protobufjs/eventemitter/index.js @@ -0,0 +1,76 @@ +"use strict"; +module.exports = EventEmitter; + +/** + * Constructs a new event emitter instance. + * @classdesc A minimal event emitter. + * @memberof util + * @constructor + */ +function EventEmitter() { + + /** + * Registered listeners. + * @type {Object.<string,*>} + * @private + */ + this._listeners = {}; +} + +/** + * Registers an event listener. + * @param {string} evt Event name + * @param {function} fn Listener + * @param {*} [ctx] Listener context + * @returns {util.EventEmitter} `this` + */ +EventEmitter.prototype.on = function on(evt, fn, ctx) { + (this._listeners[evt] || (this._listeners[evt] = [])).push({ + fn : fn, + ctx : ctx || this + }); + return this; +}; + +/** + * Removes an event listener or any matching listeners if arguments are omitted. + * @param {string} [evt] Event name. Removes all listeners if omitted. + * @param {function} [fn] Listener to remove. Removes all listeners of `evt` if omitted. + * @returns {util.EventEmitter} `this` + */ +EventEmitter.prototype.off = function off(evt, fn) { + if (evt === undefined) + this._listeners = {}; + else { + if (fn === undefined) + this._listeners[evt] = []; + else { + var listeners = this._listeners[evt]; + for (var i = 0; i < listeners.length;) + if (listeners[i].fn === fn) + listeners.splice(i, 1); + else + ++i; + } + } + return this; +}; + +/** + * Emits an event by calling its listeners with the specified arguments. + * @param {string} evt Event name + * @param {...*} args Arguments + * @returns {util.EventEmitter} `this` + */ +EventEmitter.prototype.emit = function emit(evt) { + var listeners = this._listeners[evt]; + if (listeners) { + var args = [], + i = 1; + for (; i < arguments.length;) + args.push(arguments[i++]); + for (i = 0; i < listeners.length;) + listeners[i].fn.apply(listeners[i++].ctx, args); + } + return this; +}; diff --git a/server/node_modules/@protobufjs/eventemitter/package.json b/server/node_modules/@protobufjs/eventemitter/package.json new file mode 100644 index 0000000..1d565e6 --- /dev/null +++ b/server/node_modules/@protobufjs/eventemitter/package.json @@ -0,0 +1,21 @@ +{ + "name": "@protobufjs/eventemitter", + "description": "A minimal event emitter.", + "version": "1.1.0", + "author": "Daniel Wirtz <dcode+protobufjs@dcode.io>", + "repository": { + "type": "git", + "url": "https://github.com/dcodeIO/protobuf.js.git" + }, + "license": "BSD-3-Clause", + "main": "index.js", + "types": "index.d.ts", + "devDependencies": { + "istanbul": "^0.4.5", + "tape": "^4.6.3" + }, + "scripts": { + "test": "tape tests/*.js", + "coverage": "istanbul cover node_modules/tape/bin/tape tests/*.js" + } +} \ No newline at end of file diff --git a/server/node_modules/@protobufjs/eventemitter/tests/index.js b/server/node_modules/@protobufjs/eventemitter/tests/index.js new file mode 100644 index 0000000..aeee277 --- /dev/null +++ b/server/node_modules/@protobufjs/eventemitter/tests/index.js @@ -0,0 +1,47 @@ +var tape = require("tape"); + +var EventEmitter = require(".."); + +tape.test("eventemitter", function(test) { + + var ee = new EventEmitter(); + var fn; + var ctx = {}; + + test.doesNotThrow(function() { + ee.emit("a", 1); + ee.off(); + ee.off("a"); + ee.off("a", function() {}); + }, "should not throw if no listeners are registered"); + + test.equal(ee.on("a", function(arg1) { + test.equal(this, ctx, "should be called with this = ctx"); + test.equal(arg1, 1, "should be called with arg1 = 1"); + }, ctx), ee, "should return itself when registering events"); + ee.emit("a", 1); + + ee.off("a"); + test.same(ee._listeners, { a: [] }, "should remove all listeners of the respective event when calling off(evt)"); + + ee.off(); + test.same(ee._listeners, {}, "should remove all listeners when just calling off()"); + + ee.on("a", fn = function(arg1) { + test.equal(this, ctx, "should be called with this = ctx"); + test.equal(arg1, 1, "should be called with arg1 = 1"); + }, ctx).emit("a", 1); + + ee.off("a", fn); + test.same(ee._listeners, { a: [] }, "should remove the exact listener when calling off(evt, fn)"); + + ee.on("a", function() { + test.equal(this, ee, "should be called with this = ee"); + }).emit("a"); + + test.doesNotThrow(function() { + ee.off("a", fn); + }, "should not throw if no such listener is found"); + + test.end(); +}); diff --git a/server/node_modules/@protobufjs/fetch/LICENSE b/server/node_modules/@protobufjs/fetch/LICENSE new file mode 100644 index 0000000..2a2d560 --- /dev/null +++ b/server/node_modules/@protobufjs/fetch/LICENSE @@ -0,0 +1,26 @@ +Copyright (c) 2016, Daniel Wirtz All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +* Neither the name of its author, nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/server/node_modules/@protobufjs/fetch/README.md b/server/node_modules/@protobufjs/fetch/README.md new file mode 100644 index 0000000..11088a0 --- /dev/null +++ b/server/node_modules/@protobufjs/fetch/README.md @@ -0,0 +1,13 @@ +@protobufjs/fetch +================= +[![npm](https://img.shields.io/npm/v/@protobufjs/fetch.svg)](https://www.npmjs.com/package/@protobufjs/fetch) + +Fetches the contents of a file accross node and browsers. + +API +--- + +* **fetch(path: `string`, [options: { binary: boolean } ], [callback: `function(error: ?Error, [contents: string])`]): `Promise<string|Uint8Array>|undefined`** + Fetches the contents of a file. + +**License:** [BSD 3-Clause License](https://opensource.org/licenses/BSD-3-Clause) diff --git a/server/node_modules/@protobufjs/fetch/index.d.ts b/server/node_modules/@protobufjs/fetch/index.d.ts new file mode 100644 index 0000000..77cf9f3 --- /dev/null +++ b/server/node_modules/@protobufjs/fetch/index.d.ts @@ -0,0 +1,56 @@ +export = fetch; + +/** + * Node-style callback as used by {@link util.fetch}. + * @typedef FetchCallback + * @type {function} + * @param {?Error} error Error, if any, otherwise `null` + * @param {string} [contents] File contents, if there hasn't been an error + * @returns {undefined} + */ +type FetchCallback = (error: Error, contents?: string) => void; + +/** + * Options as used by {@link util.fetch}. + * @typedef FetchOptions + * @type {Object} + * @property {boolean} [binary=false] Whether expecting a binary response + * @property {boolean} [xhr=false] If `true`, forces the use of XMLHttpRequest + */ + +interface FetchOptions { + binary?: boolean; + xhr?: boolean +} + +/** + * Fetches the contents of a file. + * @memberof util + * @param {string} filename File path or url + * @param {FetchOptions} options Fetch options + * @param {FetchCallback} callback Callback function + * @returns {undefined} + */ +declare function fetch(filename: string, options: FetchOptions, callback: FetchCallback): void; + +/** + * Fetches the contents of a file. + * @name util.fetch + * @function + * @param {string} path File path or url + * @param {FetchCallback} callback Callback function + * @returns {undefined} + * @variation 2 + */ +declare function fetch(path: string, callback: FetchCallback): void; + +/** + * Fetches the contents of a file. + * @name util.fetch + * @function + * @param {string} path File path or url + * @param {FetchOptions} [options] Fetch options + * @returns {Promise<string|Uint8Array>} Promise + * @variation 3 + */ +declare function fetch(path: string, options?: FetchOptions): Promise<(string|Uint8Array)>; diff --git a/server/node_modules/@protobufjs/fetch/index.js b/server/node_modules/@protobufjs/fetch/index.js new file mode 100644 index 0000000..f2766f5 --- /dev/null +++ b/server/node_modules/@protobufjs/fetch/index.js @@ -0,0 +1,115 @@ +"use strict"; +module.exports = fetch; + +var asPromise = require("@protobufjs/aspromise"), + inquire = require("@protobufjs/inquire"); + +var fs = inquire("fs"); + +/** + * Node-style callback as used by {@link util.fetch}. + * @typedef FetchCallback + * @type {function} + * @param {?Error} error Error, if any, otherwise `null` + * @param {string} [contents] File contents, if there hasn't been an error + * @returns {undefined} + */ + +/** + * Options as used by {@link util.fetch}. + * @typedef FetchOptions + * @type {Object} + * @property {boolean} [binary=false] Whether expecting a binary response + * @property {boolean} [xhr=false] If `true`, forces the use of XMLHttpRequest + */ + +/** + * Fetches the contents of a file. + * @memberof util + * @param {string} filename File path or url + * @param {FetchOptions} options Fetch options + * @param {FetchCallback} callback Callback function + * @returns {undefined} + */ +function fetch(filename, options, callback) { + if (typeof options === "function") { + callback = options; + options = {}; + } else if (!options) + options = {}; + + if (!callback) + return asPromise(fetch, this, filename, options); // eslint-disable-line no-invalid-this + + // if a node-like filesystem is present, try it first but fall back to XHR if nothing is found. + if (!options.xhr && fs && fs.readFile) + return fs.readFile(filename, function fetchReadFileCallback(err, contents) { + return err && typeof XMLHttpRequest !== "undefined" + ? fetch.xhr(filename, options, callback) + : err + ? callback(err) + : callback(null, options.binary ? contents : contents.toString("utf8")); + }); + + // use the XHR version otherwise. + return fetch.xhr(filename, options, callback); +} + +/** + * Fetches the contents of a file. + * @name util.fetch + * @function + * @param {string} path File path or url + * @param {FetchCallback} callback Callback function + * @returns {undefined} + * @variation 2 + */ + +/** + * Fetches the contents of a file. + * @name util.fetch + * @function + * @param {string} path File path or url + * @param {FetchOptions} [options] Fetch options + * @returns {Promise<string|Uint8Array>} Promise + * @variation 3 + */ + +/**/ +fetch.xhr = function fetch_xhr(filename, options, callback) { + var xhr = new XMLHttpRequest(); + xhr.onreadystatechange /* works everywhere */ = function fetchOnReadyStateChange() { + + if (xhr.readyState !== 4) + return undefined; + + // local cors security errors return status 0 / empty string, too. afaik this cannot be + // reliably distinguished from an actually empty file for security reasons. feel free + // to send a pull request if you are aware of a solution. + if (xhr.status !== 0 && xhr.status !== 200) + return callback(Error("status " + xhr.status)); + + // if binary data is expected, make sure that some sort of array is returned, even if + // ArrayBuffers are not supported. the binary string fallback, however, is unsafe. + if (options.binary) { + var buffer = xhr.response; + if (!buffer) { + buffer = []; + for (var i = 0; i < xhr.responseText.length; ++i) + buffer.push(xhr.responseText.charCodeAt(i) & 255); + } + return callback(null, typeof Uint8Array !== "undefined" ? new Uint8Array(buffer) : buffer); + } + return callback(null, xhr.responseText); + }; + + if (options.binary) { + // ref: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Sending_and_Receiving_Binary_Data#Receiving_binary_data_in_older_browsers + if ("overrideMimeType" in xhr) + xhr.overrideMimeType("text/plain; charset=x-user-defined"); + xhr.responseType = "arraybuffer"; + } + + xhr.open("GET", filename); + xhr.send(); +}; diff --git a/server/node_modules/@protobufjs/fetch/package.json b/server/node_modules/@protobufjs/fetch/package.json new file mode 100644 index 0000000..10096ea --- /dev/null +++ b/server/node_modules/@protobufjs/fetch/package.json @@ -0,0 +1,25 @@ +{ + "name": "@protobufjs/fetch", + "description": "Fetches the contents of a file accross node and browsers.", + "version": "1.1.0", + "author": "Daniel Wirtz <dcode+protobufjs@dcode.io>", + "repository": { + "type": "git", + "url": "https://github.com/dcodeIO/protobuf.js.git" + }, + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + }, + "license": "BSD-3-Clause", + "main": "index.js", + "types": "index.d.ts", + "devDependencies": { + "istanbul": "^0.4.5", + "tape": "^4.6.3" + }, + "scripts": { + "test": "tape tests/*.js", + "coverage": "istanbul cover node_modules/tape/bin/tape tests/*.js" + } +} \ No newline at end of file diff --git a/server/node_modules/@protobufjs/fetch/tests/index.js b/server/node_modules/@protobufjs/fetch/tests/index.js new file mode 100644 index 0000000..3cb0dae --- /dev/null +++ b/server/node_modules/@protobufjs/fetch/tests/index.js @@ -0,0 +1,16 @@ +var tape = require("tape"); + +var fetch = require(".."); + +tape.test("fetch", function(test) { + + if (typeof Promise !== "undefined") { + var promise = fetch("NOTFOUND"); + promise.catch(function() {}); + test.ok(promise instanceof Promise, "should return a promise if callback has been omitted"); + } + + // TODO - some way to test this properly? + + test.end(); +}); diff --git a/server/node_modules/@protobufjs/float/LICENSE b/server/node_modules/@protobufjs/float/LICENSE new file mode 100644 index 0000000..2a2d560 --- /dev/null +++ b/server/node_modules/@protobufjs/float/LICENSE @@ -0,0 +1,26 @@ +Copyright (c) 2016, Daniel Wirtz All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +* Neither the name of its author, nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/server/node_modules/@protobufjs/float/README.md b/server/node_modules/@protobufjs/float/README.md new file mode 100644 index 0000000..8947bae --- /dev/null +++ b/server/node_modules/@protobufjs/float/README.md @@ -0,0 +1,102 @@ +@protobufjs/float +================= +[![npm](https://img.shields.io/npm/v/@protobufjs/float.svg)](https://www.npmjs.com/package/@protobufjs/float) + +Reads / writes floats / doubles from / to buffers in both modern and ancient browsers. Fast. + +API +--- + +* **writeFloatLE(val: `number`, buf: `Uint8Array`, pos: `number`)**<br /> + Writes a 32 bit float to a buffer using little endian byte order. + +* **writeFloatBE(val: `number`, buf: `Uint8Array`, pos: `number`)**<br /> + Writes a 32 bit float to a buffer using big endian byte order. + +* **readFloatLE(buf: `Uint8Array`, pos: `number`): `number`**<br /> + Reads a 32 bit float from a buffer using little endian byte order. + +* **readFloatBE(buf: `Uint8Array`, pos: `number`): `number`**<br /> + Reads a 32 bit float from a buffer using big endian byte order. + +* **writeDoubleLE(val: `number`, buf: `Uint8Array`, pos: `number`)**<br /> + Writes a 64 bit double to a buffer using little endian byte order. + +* **writeDoubleBE(val: `number`, buf: `Uint8Array`, pos: `number`)**<br /> + Writes a 64 bit double to a buffer using big endian byte order. + +* **readDoubleLE(buf: `Uint8Array`, pos: `number`): `number`**<br /> + Reads a 64 bit double from a buffer using little endian byte order. + +* **readDoubleBE(buf: `Uint8Array`, pos: `number`): `number`**<br /> + Reads a 64 bit double from a buffer using big endian byte order. + +Performance +----------- +There is a simple benchmark included comparing raw read/write performance of this library (float), float's fallback for old browsers, the [ieee754](https://www.npmjs.com/package/ieee754) module and node's [buffer](https://nodejs.org/api/buffer.html). On an i7-2600k running node 6.9.1 it yields: + +``` +benchmarking writeFloat performance ... + +float x 42,741,625 ops/sec ±1.75% (81 runs sampled) +float (fallback) x 11,272,532 ops/sec ±1.12% (85 runs sampled) +ieee754 x 8,653,337 ops/sec ±1.18% (84 runs sampled) +buffer x 12,412,414 ops/sec ±1.41% (83 runs sampled) +buffer (noAssert) x 13,471,149 ops/sec ±1.09% (84 runs sampled) + + float was fastest + float (fallback) was 73.5% slower + ieee754 was 79.6% slower + buffer was 70.9% slower + buffer (noAssert) was 68.3% slower + +benchmarking readFloat performance ... + +float x 44,382,729 ops/sec ±1.70% (84 runs sampled) +float (fallback) x 20,925,938 ops/sec ±0.86% (87 runs sampled) +ieee754 x 17,189,009 ops/sec ±1.01% (87 runs sampled) +buffer x 10,518,437 ops/sec ±1.04% (83 runs sampled) +buffer (noAssert) x 11,031,636 ops/sec ±1.15% (87 runs sampled) + + float was fastest + float (fallback) was 52.5% slower + ieee754 was 61.0% slower + buffer was 76.1% slower + buffer (noAssert) was 75.0% slower + +benchmarking writeDouble performance ... + +float x 38,624,906 ops/sec ±0.93% (83 runs sampled) +float (fallback) x 10,457,811 ops/sec ±1.54% (85 runs sampled) +ieee754 x 7,681,130 ops/sec ±1.11% (83 runs sampled) +buffer x 12,657,876 ops/sec ±1.03% (83 runs sampled) +buffer (noAssert) x 13,372,795 ops/sec ±0.84% (85 runs sampled) + + float was fastest + float (fallback) was 73.1% slower + ieee754 was 80.1% slower + buffer was 67.3% slower + buffer (noAssert) was 65.3% slower + +benchmarking readDouble performance ... + +float x 40,527,888 ops/sec ±1.05% (84 runs sampled) +float (fallback) x 18,696,480 ops/sec ±0.84% (86 runs sampled) +ieee754 x 14,074,028 ops/sec ±1.04% (87 runs sampled) +buffer x 10,092,367 ops/sec ±1.15% (84 runs sampled) +buffer (noAssert) x 10,623,793 ops/sec ±0.96% (84 runs sampled) + + float was fastest + float (fallback) was 53.8% slower + ieee754 was 65.3% slower + buffer was 75.1% slower + buffer (noAssert) was 73.8% slower +``` + +To run it yourself: + +``` +$> npm run bench +``` + +**License:** [BSD 3-Clause License](https://opensource.org/licenses/BSD-3-Clause) diff --git a/server/node_modules/@protobufjs/float/bench/index.js b/server/node_modules/@protobufjs/float/bench/index.js new file mode 100644 index 0000000..1b3c4b8 --- /dev/null +++ b/server/node_modules/@protobufjs/float/bench/index.js @@ -0,0 +1,87 @@ +"use strict"; + +var float = require(".."), + ieee754 = require("ieee754"), + newSuite = require("./suite"); + +var F32 = Float32Array; +var F64 = Float64Array; +delete global.Float32Array; +delete global.Float64Array; +var floatFallback = float({}); +global.Float32Array = F32; +global.Float64Array = F64; + +var buf = new Buffer(8); + +newSuite("writeFloat") +.add("float", function() { + float.writeFloatLE(0.1, buf, 0); +}) +.add("float (fallback)", function() { + floatFallback.writeFloatLE(0.1, buf, 0); +}) +.add("ieee754", function() { + ieee754.write(buf, 0.1, 0, true, 23, 4); +}) +.add("buffer", function() { + buf.writeFloatLE(0.1, 0); +}) +.add("buffer (noAssert)", function() { + buf.writeFloatLE(0.1, 0, true); +}) +.run(); + +newSuite("readFloat") +.add("float", function() { + float.readFloatLE(buf, 0); +}) +.add("float (fallback)", function() { + floatFallback.readFloatLE(buf, 0); +}) +.add("ieee754", function() { + ieee754.read(buf, 0, true, 23, 4); +}) +.add("buffer", function() { + buf.readFloatLE(0); +}) +.add("buffer (noAssert)", function() { + buf.readFloatLE(0, true); +}) +.run(); + +newSuite("writeDouble") +.add("float", function() { + float.writeDoubleLE(0.1, buf, 0); +}) +.add("float (fallback)", function() { + floatFallback.writeDoubleLE(0.1, buf, 0); +}) +.add("ieee754", function() { + ieee754.write(buf, 0.1, 0, true, 52, 8); +}) +.add("buffer", function() { + buf.writeDoubleLE(0.1, 0); +}) +.add("buffer (noAssert)", function() { + buf.writeDoubleLE(0.1, 0, true); +}) +.run(); + +newSuite("readDouble") +.add("float", function() { + float.readDoubleLE(buf, 0); +}) +.add("float (fallback)", function() { + floatFallback.readDoubleLE(buf, 0); +}) +.add("ieee754", function() { + ieee754.read(buf, 0, true, 52, 8); +}) +.add("buffer", function() { + buf.readDoubleLE(0); +}) +.add("buffer (noAssert)", function() { + buf.readDoubleLE(0, true); +}) +.run(); diff --git a/server/node_modules/@protobufjs/float/bench/suite.js b/server/node_modules/@protobufjs/float/bench/suite.js new file mode 100644 index 0000000..3820579 --- /dev/null +++ b/server/node_modules/@protobufjs/float/bench/suite.js @@ -0,0 +1,46 @@ +"use strict"; +module.exports = newSuite; + +var benchmark = require("benchmark"), + chalk = require("chalk"); + +var padSize = 27; + +function newSuite(name) { + var benches = []; + return new benchmark.Suite(name) + .on("add", function(event) { + benches.push(event.target); + }) + .on("start", function() { + process.stdout.write("benchmarking " + name + " performance ...\n\n"); + }) + .on("cycle", function(event) { + process.stdout.write(String(event.target) + "\n"); + }) + .on("complete", function() { + if (benches.length > 1) { + var fastest = this.filter("fastest"), // eslint-disable-line no-invalid-this + fastestHz = getHz(fastest[0]); + process.stdout.write("\n" + chalk.white(pad(fastest[0].name, padSize)) + " was " + chalk.green("fastest") + "\n"); + benches.forEach(function(bench) { + if (fastest.indexOf(bench) === 0) + return; + var hz = hz = getHz(bench); + var percent = (1 - hz / fastestHz) * 100; + process.stdout.write(chalk.white(pad(bench.name, padSize)) + " was " + chalk.red(percent.toFixed(1) + "% slower") + "\n"); + }); + } + process.stdout.write("\n"); + }); +} + +function getHz(bench) { + return 1 / (bench.stats.mean + bench.stats.moe); +} + +function pad(str, len, l) { + while (str.length < len) + str = l ? str + " " : " " + str; + return str; +} diff --git a/server/node_modules/@protobufjs/float/index.d.ts b/server/node_modules/@protobufjs/float/index.d.ts new file mode 100644 index 0000000..ab05de3 --- /dev/null +++ b/server/node_modules/@protobufjs/float/index.d.ts @@ -0,0 +1,83 @@ +/** + * Writes a 32 bit float to a buffer using little endian byte order. + * @name writeFloatLE + * @function + * @param {number} val Value to write + * @param {Uint8Array} buf Target buffer + * @param {number} pos Target buffer offset + * @returns {undefined} + */ +export function writeFloatLE(val: number, buf: Uint8Array, pos: number): void; + +/** + * Writes a 32 bit float to a buffer using big endian byte order. + * @name writeFloatBE + * @function + * @param {number} val Value to write + * @param {Uint8Array} buf Target buffer + * @param {number} pos Target buffer offset + * @returns {undefined} + */ +export function writeFloatBE(val: number, buf: Uint8Array, pos: number): void; + +/** + * Reads a 32 bit float from a buffer using little endian byte order. + * @name readFloatLE + * @function + * @param {Uint8Array} buf Source buffer + * @param {number} pos Source buffer offset + * @returns {number} Value read + */ +export function readFloatLE(buf: Uint8Array, pos: number): number; + +/** + * Reads a 32 bit float from a buffer using big endian byte order. + * @name readFloatBE + * @function + * @param {Uint8Array} buf Source buffer + * @param {number} pos Source buffer offset + * @returns {number} Value read + */ +export function readFloatBE(buf: Uint8Array, pos: number): number; + +/** + * Writes a 64 bit double to a buffer using little endian byte order. + * @name writeDoubleLE + * @function + * @param {number} val Value to write + * @param {Uint8Array} buf Target buffer + * @param {number} pos Target buffer offset + * @returns {undefined} + */ +export function writeDoubleLE(val: number, buf: Uint8Array, pos: number): void; + +/** + * Writes a 64 bit double to a buffer using big endian byte order. + * @name writeDoubleBE + * @function + * @param {number} val Value to write + * @param {Uint8Array} buf Target buffer + * @param {number} pos Target buffer offset + * @returns {undefined} + */ +export function writeDoubleBE(val: number, buf: Uint8Array, pos: number): void; + +/** + * Reads a 64 bit double from a buffer using little endian byte order. + * @name readDoubleLE + * @function + * @param {Uint8Array} buf Source buffer + * @param {number} pos Source buffer offset + * @returns {number} Value read + */ +export function readDoubleLE(buf: Uint8Array, pos: number): number; + +/** + * Reads a 64 bit double from a buffer using big endian byte order. + * @name readDoubleBE + * @function + * @param {Uint8Array} buf Source buffer + * @param {number} pos Source buffer offset + * @returns {number} Value read + */ +export function readDoubleBE(buf: Uint8Array, pos: number): number; diff --git a/server/node_modules/@protobufjs/float/index.js b/server/node_modules/@protobufjs/float/index.js new file mode 100644 index 0000000..706d096 --- /dev/null +++ b/server/node_modules/@protobufjs/float/index.js @@ -0,0 +1,335 @@ +"use strict"; + +module.exports = factory(factory); + +/** + * Reads / writes floats / doubles from / to buffers. + * @name util.float + * @namespace + */ + +/** + * Writes a 32 bit float to a buffer using little endian byte order. + * @name util.float.writeFloatLE + * @function + * @param {number} val Value to write + * @param {Uint8Array} buf Target buffer + * @param {number} pos Target buffer offset + * @returns {undefined} + */ + +/** + * Writes a 32 bit float to a buffer using big endian byte order. + * @name util.float.writeFloatBE + * @function + * @param {number} val Value to write + * @param {Uint8Array} buf Target buffer + * @param {number} pos Target buffer offset + * @returns {undefined} + */ + +/** + * Reads a 32 bit float from a buffer using little endian byte order. + * @name util.float.readFloatLE + * @function + * @param {Uint8Array} buf Source buffer + * @param {number} pos Source buffer offset + * @returns {number} Value read + */ + +/** + * Reads a 32 bit float from a buffer using big endian byte order. + * @name util.float.readFloatBE + * @function + * @param {Uint8Array} buf Source buffer + * @param {number} pos Source buffer offset + * @returns {number} Value read + */ + +/** + * Writes a 64 bit double to a buffer using little endian byte order. + * @name util.float.writeDoubleLE + * @function + * @param {number} val Value to write + * @param {Uint8Array} buf Target buffer + * @param {number} pos Target buffer offset + * @returns {undefined} + */ + +/** + * Writes a 64 bit double to a buffer using big endian byte order. + * @name util.float.writeDoubleBE + * @function + * @param {number} val Value to write + * @param {Uint8Array} buf Target buffer + * @param {number} pos Target buffer offset + * @returns {undefined} + */ + +/** + * Reads a 64 bit double from a buffer using little endian byte order. + * @name util.float.readDoubleLE + * @function + * @param {Uint8Array} buf Source buffer + * @param {number} pos Source buffer offset + * @returns {number} Value read + */ + +/** + * Reads a 64 bit double from a buffer using big endian byte order. + * @name util.float.readDoubleBE + * @function + * @param {Uint8Array} buf Source buffer + * @param {number} pos Source buffer offset + * @returns {number} Value read + */ + +// Factory function for the purpose of node-based testing in modified global environments +function factory(exports) { + + // float: typed array + if (typeof Float32Array !== "undefined") (function() { + + var f32 = new Float32Array([ -0 ]), + f8b = new Uint8Array(f32.buffer), + le = f8b[3] === 128; + + function writeFloat_f32_cpy(val, buf, pos) { + f32[0] = val; + buf[pos ] = f8b[0]; + buf[pos + 1] = f8b[1]; + buf[pos + 2] = f8b[2]; + buf[pos + 3] = f8b[3]; + } + + function writeFloat_f32_rev(val, buf, pos) { + f32[0] = val; + buf[pos ] = f8b[3]; + buf[pos + 1] = f8b[2]; + buf[pos + 2] = f8b[1]; + buf[pos + 3] = f8b[0]; + } + + /* istanbul ignore next */ + exports.writeFloatLE = le ? writeFloat_f32_cpy : writeFloat_f32_rev; + /* istanbul ignore next */ + exports.writeFloatBE = le ? writeFloat_f32_rev : writeFloat_f32_cpy; + + function readFloat_f32_cpy(buf, pos) { + f8b[0] = buf[pos ]; + f8b[1] = buf[pos + 1]; + f8b[2] = buf[pos + 2]; + f8b[3] = buf[pos + 3]; + return f32[0]; + } + + function readFloat_f32_rev(buf, pos) { + f8b[3] = buf[pos ]; + f8b[2] = buf[pos + 1]; + f8b[1] = buf[pos + 2]; + f8b[0] = buf[pos + 3]; + return f32[0]; + } + + /* istanbul ignore next */ + exports.readFloatLE = le ? readFloat_f32_cpy : readFloat_f32_rev; + /* istanbul ignore next */ + exports.readFloatBE = le ? readFloat_f32_rev : readFloat_f32_cpy; + + // float: ieee754 + })(); else (function() { + + function writeFloat_ieee754(writeUint, val, buf, pos) { + var sign = val < 0 ? 1 : 0; + if (sign) + val = -val; + if (val === 0) + writeUint(1 / val > 0 ? /* positive */ 0 : /* negative 0 */ 2147483648, buf, pos); + else if (isNaN(val)) + writeUint(2143289344, buf, pos); + else if (val > 3.4028234663852886e+38) // +-Infinity + writeUint((sign << 31 | 2139095040) >>> 0, buf, pos); + else if (val < 1.1754943508222875e-38) // denormal + writeUint((sign << 31 | Math.round(val / 1.401298464324817e-45)) >>> 0, buf, pos); + else { + var exponent = Math.floor(Math.log(val) / Math.LN2), + mantissa = Math.round(val * Math.pow(2, -exponent) * 8388608) & 8388607; + writeUint((sign << 31 | exponent + 127 << 23 | mantissa) >>> 0, buf, pos); + } + } + + exports.writeFloatLE = writeFloat_ieee754.bind(null, writeUintLE); + exports.writeFloatBE = writeFloat_ieee754.bind(null, writeUintBE); + + function readFloat_ieee754(readUint, buf, pos) { + var uint = readUint(buf, pos), + sign = (uint >> 31) * 2 + 1, + exponent = uint >>> 23 & 255, + mantissa = uint & 8388607; + return exponent === 255 + ? mantissa + ? NaN + : sign * Infinity + : exponent === 0 // denormal + ? sign * 1.401298464324817e-45 * mantissa + : sign * Math.pow(2, exponent - 150) * (mantissa + 8388608); + } + + exports.readFloatLE = readFloat_ieee754.bind(null, readUintLE); + exports.readFloatBE = readFloat_ieee754.bind(null, readUintBE); + + })(); + + // double: typed array + if (typeof Float64Array !== "undefined") (function() { + + var f64 = new Float64Array([-0]), + f8b = new Uint8Array(f64.buffer), + le = f8b[7] === 128; + + function writeDouble_f64_cpy(val, buf, pos) { + f64[0] = val; + buf[pos ] = f8b[0]; + buf[pos + 1] = f8b[1]; + buf[pos + 2] = f8b[2]; + buf[pos + 3] = f8b[3]; + buf[pos + 4] = f8b[4]; + buf[pos + 5] = f8b[5]; + buf[pos + 6] = f8b[6]; + buf[pos + 7] = f8b[7]; + } + + function writeDouble_f64_rev(val, buf, pos) { + f64[0] = val; + buf[pos ] = f8b[7]; + buf[pos + 1] = f8b[6]; + buf[pos + 2] = f8b[5]; + buf[pos + 3] = f8b[4]; + buf[pos + 4] = f8b[3]; + buf[pos + 5] = f8b[2]; + buf[pos + 6] = f8b[1]; + buf[pos + 7] = f8b[0]; + } + + /* istanbul ignore next */ + exports.writeDoubleLE = le ? writeDouble_f64_cpy : writeDouble_f64_rev; + /* istanbul ignore next */ + exports.writeDoubleBE = le ? writeDouble_f64_rev : writeDouble_f64_cpy; + + function readDouble_f64_cpy(buf, pos) { + f8b[0] = buf[pos ]; + f8b[1] = buf[pos + 1]; + f8b[2] = buf[pos + 2]; + f8b[3] = buf[pos + 3]; + f8b[4] = buf[pos + 4]; + f8b[5] = buf[pos + 5]; + f8b[6] = buf[pos + 6]; + f8b[7] = buf[pos + 7]; + return f64[0]; + } + + function readDouble_f64_rev(buf, pos) { + f8b[7] = buf[pos ]; + f8b[6] = buf[pos + 1]; + f8b[5] = buf[pos + 2]; + f8b[4] = buf[pos + 3]; + f8b[3] = buf[pos + 4]; + f8b[2] = buf[pos + 5]; + f8b[1] = buf[pos + 6]; + f8b[0] = buf[pos + 7]; + return f64[0]; + } + + /* istanbul ignore next */ + exports.readDoubleLE = le ? readDouble_f64_cpy : readDouble_f64_rev; + /* istanbul ignore next */ + exports.readDoubleBE = le ? readDouble_f64_rev : readDouble_f64_cpy; + + // double: ieee754 + })(); else (function() { + + function writeDouble_ieee754(writeUint, off0, off1, val, buf, pos) { + var sign = val < 0 ? 1 : 0; + if (sign) + val = -val; + if (val === 0) { + writeUint(0, buf, pos + off0); + writeUint(1 / val > 0 ? /* positive */ 0 : /* negative 0 */ 2147483648, buf, pos + off1); + } else if (isNaN(val)) { + writeUint(0, buf, pos + off0); + writeUint(2146959360, buf, pos + off1); + } else if (val > 1.7976931348623157e+308) { // +-Infinity + writeUint(0, buf, pos + off0); + writeUint((sign << 31 | 2146435072) >>> 0, buf, pos + off1); + } else { + var mantissa; + if (val < 2.2250738585072014e-308) { // denormal + mantissa = val / 5e-324; + writeUint(mantissa >>> 0, buf, pos + off0); + writeUint((sign << 31 | mantissa / 4294967296) >>> 0, buf, pos + off1); + } else { + var exponent = Math.floor(Math.log(val) / Math.LN2); + if (exponent === 1024) + exponent = 1023; + mantissa = val * Math.pow(2, -exponent); + writeUint(mantissa * 4503599627370496 >>> 0, buf, pos + off0); + writeUint((sign << 31 | exponent + 1023 << 20 | mantissa * 1048576 & 1048575) >>> 0, buf, pos + off1); + } + } + } + + exports.writeDoubleLE = writeDouble_ieee754.bind(null, writeUintLE, 0, 4); + exports.writeDoubleBE = writeDouble_ieee754.bind(null, writeUintBE, 4, 0); + + function readDouble_ieee754(readUint, off0, off1, buf, pos) { + var lo = readUint(buf, pos + off0), + hi = readUint(buf, pos + off1); + var sign = (hi >> 31) * 2 + 1, + exponent = hi >>> 20 & 2047, + mantissa = 4294967296 * (hi & 1048575) + lo; + return exponent === 2047 + ? mantissa + ? NaN + : sign * Infinity + : exponent === 0 // denormal + ? sign * 5e-324 * mantissa + : sign * Math.pow(2, exponent - 1075) * (mantissa + 4503599627370496); + } + + exports.readDoubleLE = readDouble_ieee754.bind(null, readUintLE, 0, 4); + exports.readDoubleBE = readDouble_ieee754.bind(null, readUintBE, 4, 0); + + })(); + + return exports; +} + +// uint helpers + +function writeUintLE(val, buf, pos) { + buf[pos ] = val & 255; + buf[pos + 1] = val >>> 8 & 255; + buf[pos + 2] = val >>> 16 & 255; + buf[pos + 3] = val >>> 24; +} + +function writeUintBE(val, buf, pos) { + buf[pos ] = val >>> 24; + buf[pos + 1] = val >>> 16 & 255; + buf[pos + 2] = val >>> 8 & 255; + buf[pos + 3] = val & 255; +} + +function readUintLE(buf, pos) { + return (buf[pos ] + | buf[pos + 1] << 8 + | buf[pos + 2] << 16 + | buf[pos + 3] << 24) >>> 0; +} + +function readUintBE(buf, pos) { + return (buf[pos ] << 24 + | buf[pos + 1] << 16 + | buf[pos + 2] << 8 + | buf[pos + 3]) >>> 0; +} diff --git a/server/node_modules/@protobufjs/float/package.json b/server/node_modules/@protobufjs/float/package.json new file mode 100644 index 0000000..b3072f1 --- /dev/null +++ b/server/node_modules/@protobufjs/float/package.json @@ -0,0 +1,26 @@ +{ + "name": "@protobufjs/float", + "description": "Reads / writes floats / doubles from / to buffers in both modern and ancient browsers.", + "version": "1.0.2", + "author": "Daniel Wirtz <dcode+protobufjs@dcode.io>", + "repository": { + "type": "git", + "url": "https://github.com/dcodeIO/protobuf.js.git" + }, + "dependencies": {}, + "license": "BSD-3-Clause", + "main": "index.js", + "types": "index.d.ts", + "devDependencies": { + "benchmark": "^2.1.4", + "chalk": "^1.1.3", + "ieee754": "^1.1.8", + "istanbul": "^0.4.5", + "tape": "^4.6.3" + }, + "scripts": { + "test": "tape tests/*.js", + "coverage": "istanbul cover node_modules/tape/bin/tape tests/*.js", + "bench": "node bench" + } +} \ No newline at end of file diff --git a/server/node_modules/@protobufjs/float/tests/index.js b/server/node_modules/@protobufjs/float/tests/index.js new file mode 100644 index 0000000..324e85c --- /dev/null +++ b/server/node_modules/@protobufjs/float/tests/index.js @@ -0,0 +1,100 @@ +var tape = require("tape"); + +var float = require(".."); + +tape.test("float", function(test) { + + // default + test.test(test.name + " - typed array", function(test) { + runTest(float, test); + }); + + // ieee754 + test.test(test.name + " - fallback", function(test) { + var F32 = global.Float32Array, + F64 = global.Float64Array; + delete global.Float32Array; + delete global.Float64Array; + runTest(float({}), test); + global.Float32Array = F32; + global.Float64Array = F64; + }); +}); + +function runTest(float, test) { + + var common = [ + 0, + -0, + Infinity, + -Infinity, + 0.125, + 1024.5, + -4096.5, + NaN + ]; + + test.test(test.name + " - using 32 bits", function(test) { + common.concat([ + 3.4028234663852886e+38, + 1.1754943508222875e-38, + 1.1754946310819804e-39 + ]) + .forEach(function(value) { + var strval = value === 0 && 1 / value < 0 ? "-0" : value.toString(); + test.ok( + checkValue(value, 4, float.readFloatLE, float.writeFloatLE, Buffer.prototype.writeFloatLE), + "should write and read back " + strval + " (32 bit LE)" + ); + test.ok( + checkValue(value, 4, float.readFloatBE, float.writeFloatBE, Buffer.prototype.writeFloatBE), + "should write and read back " + strval + " (32 bit BE)" + ); + }); + test.end(); + }); + + test.test(test.name + " - using 64 bits", function(test) { + common.concat([ + 1.7976931348623157e+308, + 2.2250738585072014e-308, + 2.2250738585072014e-309 + ]) + .forEach(function(value) { + var strval = value === 0 && 1 / value < 0 ? "-0" : value.toString(); + test.ok( + checkValue(value, 8, float.readDoubleLE, float.writeDoubleLE, Buffer.prototype.writeDoubleLE), + "should write and read back " + strval + " (64 bit LE)" + ); + test.ok( + checkValue(value, 8, float.readDoubleBE, float.writeDoubleBE, Buffer.prototype.writeDoubleBE), + "should write and read back " + strval + " (64 bit BE)" + ); + }); + test.end(); + }); + + test.end(); +} + +function checkValue(value, size, read, write, write_comp) { + var buffer = new Buffer(size); + write(value, buffer, 0); + var value_comp = read(buffer, 0); + var strval = value === 0 && 1 / value < 0 ? "-0" : value.toString(); + if (value !== value) { + if (value_comp === value_comp) + return false; + } else if (value_comp !== value) + return false; + + var buffer_comp = new Buffer(size); + write_comp.call(buffer_comp, value, 0); + for (var i = 0; i < size; ++i) + if (buffer[i] !== buffer_comp[i]) { + console.error(">", buffer, buffer_comp); + return false; + } + + return true; +} \ No newline at end of file diff --git a/server/node_modules/@protobufjs/inquire/.npmignore b/server/node_modules/@protobufjs/inquire/.npmignore new file mode 100644 index 0000000..ce75de4 --- /dev/null +++ b/server/node_modules/@protobufjs/inquire/.npmignore @@ -0,0 +1,3 @@ +npm-debug.* +node_modules/ +coverage/ diff --git a/server/node_modules/@protobufjs/inquire/LICENSE b/server/node_modules/@protobufjs/inquire/LICENSE new file mode 100644 index 0000000..2a2d560 --- /dev/null +++ b/server/node_modules/@protobufjs/inquire/LICENSE @@ -0,0 +1,26 @@ +Copyright (c) 2016, Daniel Wirtz All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +* Neither the name of its author, nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/server/node_modules/@protobufjs/inquire/README.md b/server/node_modules/@protobufjs/inquire/README.md new file mode 100644 index 0000000..22f9968 --- /dev/null +++ b/server/node_modules/@protobufjs/inquire/README.md @@ -0,0 +1,13 @@ +@protobufjs/inquire +=================== +[![npm](https://img.shields.io/npm/v/@protobufjs/inquire.svg)](https://www.npmjs.com/package/@protobufjs/inquire) + +Requires a module only if available and hides the require call from bundlers. + +API +--- + +* **inquire(moduleName: `string`): `?Object`**<br /> + Requires a module only if available. + +**License:** [BSD 3-Clause License](https://opensource.org/licenses/BSD-3-Clause) diff --git a/server/node_modules/@protobufjs/inquire/index.d.ts b/server/node_modules/@protobufjs/inquire/index.d.ts new file mode 100644 index 0000000..6f9825b --- /dev/null +++ b/server/node_modules/@protobufjs/inquire/index.d.ts @@ -0,0 +1,9 @@ +export = inquire; + +/** + * Requires a module only if available. + * @memberof util + * @param {string} moduleName Module to require + * @returns {?Object} Required module if available and not empty, otherwise `null` + */ +declare function inquire(moduleName: string): Object; diff --git a/server/node_modules/@protobufjs/inquire/index.js b/server/node_modules/@protobufjs/inquire/index.js new file mode 100644 index 0000000..33778b5 --- /dev/null +++ b/server/node_modules/@protobufjs/inquire/index.js @@ -0,0 +1,17 @@ +"use strict"; +module.exports = inquire; + +/** + * Requires a module only if available. + * @memberof util + * @param {string} moduleName Module to require + * @returns {?Object} Required module if available and not empty, otherwise `null` + */ +function inquire(moduleName) { + try { + var mod = eval("quire".replace(/^/,"re"))(moduleName); // eslint-disable-line no-eval + if (mod && (mod.length || Object.keys(mod).length)) + return mod; + } catch (e) {} // eslint-disable-line no-empty + return null; +} diff --git a/server/node_modules/@protobufjs/inquire/package.json b/server/node_modules/@protobufjs/inquire/package.json new file mode 100644 index 0000000..f4b33db --- /dev/null +++ b/server/node_modules/@protobufjs/inquire/package.json @@ -0,0 +1,21 @@ +{ + "name": "@protobufjs/inquire", + "description": "Requires a module only if available and hides the require call from bundlers.", + "version": "1.1.0", + "author": "Daniel Wirtz <dcode+protobufjs@dcode.io>", + "repository": { + "type": "git", + "url": "https://github.com/dcodeIO/protobuf.js.git" + }, + "license": "BSD-3-Clause", + "main": "index.js", + "types": "index.d.ts", + "devDependencies": { + "istanbul": "^0.4.5", + "tape": "^4.6.3" + }, + "scripts": { + "test": "tape tests/*.js", + "coverage": "istanbul cover node_modules/tape/bin/tape tests/*.js" + } +} \ No newline at end of file diff --git a/server/node_modules/@protobufjs/inquire/tests/data/array.js b/server/node_modules/@protobufjs/inquire/tests/data/array.js new file mode 100644 index 0000000..96627c3 --- /dev/null +++ b/server/node_modules/@protobufjs/inquire/tests/data/array.js @@ -0,0 +1 @@ +module.exports = [1]; diff --git a/server/node_modules/@protobufjs/inquire/tests/data/emptyArray.js b/server/node_modules/@protobufjs/inquire/tests/data/emptyArray.js new file mode 100644 index 0000000..0630c8f --- /dev/null +++ b/server/node_modules/@protobufjs/inquire/tests/data/emptyArray.js @@ -0,0 +1 @@ +module.exports = []; diff --git a/server/node_modules/@protobufjs/inquire/tests/data/emptyObject.js b/server/node_modules/@protobufjs/inquire/tests/data/emptyObject.js new file mode 100644 index 0000000..0369aa4 --- /dev/null +++ b/server/node_modules/@protobufjs/inquire/tests/data/emptyObject.js @@ -0,0 +1 @@ +module.exports = {}; diff --git a/server/node_modules/@protobufjs/inquire/tests/data/object.js b/server/node_modules/@protobufjs/inquire/tests/data/object.js new file mode 100644 index 0000000..3226d44 --- /dev/null +++ b/server/node_modules/@protobufjs/inquire/tests/data/object.js @@ -0,0 +1 @@ +module.exports = { a: 1 }; diff --git a/server/node_modules/@protobufjs/inquire/tests/index.js b/server/node_modules/@protobufjs/inquire/tests/index.js new file mode 100644 index 0000000..7d6496f --- /dev/null +++ b/server/node_modules/@protobufjs/inquire/tests/index.js @@ -0,0 +1,20 @@ +var tape = require("tape"); + +var inquire = require(".."); + +tape.test("inquire", function(test) { + + test.equal(inquire("buffer").Buffer, Buffer, "should be able to require \"buffer\""); + + test.equal(inquire("%invalid"), null, "should not be able to require \"%invalid\""); + + test.equal(inquire("./tests/data/emptyObject"), null, "should return null when requiring a module exporting an empty object"); + + test.equal(inquire("./tests/data/emptyArray"), null, "should return null when requiring a module exporting an empty array"); + + test.same(inquire("./tests/data/object"), { a: 1 }, "should return the object if a non-empty object"); + + test.same(inquire("./tests/data/array"), [ 1 ], "should return the module if a non-empty array"); + + test.end(); +}); diff --git a/server/node_modules/@protobufjs/path/LICENSE b/server/node_modules/@protobufjs/path/LICENSE new file mode 100644 index 0000000..2a2d560 --- /dev/null +++ b/server/node_modules/@protobufjs/path/LICENSE @@ -0,0 +1,26 @@ +Copyright (c) 2016, Daniel Wirtz All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +* Neither the name of its author, nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/server/node_modules/@protobufjs/path/README.md b/server/node_modules/@protobufjs/path/README.md new file mode 100644 index 0000000..0e8e6bc --- /dev/null +++ b/server/node_modules/@protobufjs/path/README.md @@ -0,0 +1,19 @@ +@protobufjs/path +================ +[![npm](https://img.shields.io/npm/v/@protobufjs/path.svg)](https://www.npmjs.com/package/@protobufjs/path) + +A minimal path module to resolve Unix, Windows and URL paths alike. + +API +--- + +* **path.isAbsolute(path: `string`): `boolean`**<br /> + Tests if the specified path is absolute. + +* **path.normalize(path: `string`): `string`**<br /> + Normalizes the specified path. + +* **path.resolve(originPath: `string`, includePath: `string`, [alreadyNormalized=false: `boolean`]): `string`**<br /> + Resolves the specified include path against the specified origin path. + +**License:** [BSD 3-Clause License](https://opensource.org/licenses/BSD-3-Clause) diff --git a/server/node_modules/@protobufjs/path/index.d.ts b/server/node_modules/@protobufjs/path/index.d.ts new file mode 100644 index 0000000..567c3dc --- /dev/null +++ b/server/node_modules/@protobufjs/path/index.d.ts @@ -0,0 +1,22 @@ +/** + * Tests if the specified path is absolute. + * @param {string} path Path to test + * @returns {boolean} `true` if path is absolute + */ +export function isAbsolute(path: string): boolean; + +/** + * Normalizes the specified path. + * @param {string} path Path to normalize + * @returns {string} Normalized path + */ +export function normalize(path: string): string; + +/** + * Resolves the specified include path against the specified origin path. + * @param {string} originPath Path to the origin file + * @param {string} includePath Include path relative to origin path + * @param {boolean} [alreadyNormalized=false] `true` if both paths are already known to be normalized + * @returns {string} Path to the include file + */ +export function resolve(originPath: string, includePath: string, alreadyNormalized?: boolean): string; diff --git a/server/node_modules/@protobufjs/path/index.js b/server/node_modules/@protobufjs/path/index.js new file mode 100644 index 0000000..1ea7b17 --- /dev/null +++ b/server/node_modules/@protobufjs/path/index.js @@ -0,0 +1,65 @@ +"use strict"; + +/** + * A minimal path module to resolve Unix, Windows and URL paths alike. + * @memberof util + * @namespace + */ +var path = exports; + +var isAbsolute = +/** + * Tests if the specified path is absolute. + * @param {string} path Path to test + * @returns {boolean} `true` if path is absolute + */ +path.isAbsolute = function isAbsolute(path) { + return /^(?:\/|\w+:)/.test(path); +}; + +var normalize = +/** + * Normalizes the specified path. + * @param {string} path Path to normalize + * @returns {string} Normalized path + */ +path.normalize = function normalize(path) { + path = path.replace(/\\/g, "/") + .replace(/\/{2,}/g, "/"); + var parts = path.split("/"), + absolute = isAbsolute(path), + prefix = ""; + if (absolute) + prefix = parts.shift() + "/"; + for (var i = 0; i < parts.length;) { + if (parts[i] === "..") { + if (i > 0 && parts[i - 1] !== "..") + parts.splice(--i, 2); + else if (absolute) + parts.splice(i, 1); + else + ++i; + } else if (parts[i] === ".") + parts.splice(i, 1); + else + ++i; + } + return prefix + parts.join("/"); +}; + +/** + * Resolves the specified include path against the specified origin path. + * @param {string} originPath Path to the origin file + * @param {string} includePath Include path relative to origin path + * @param {boolean} [alreadyNormalized=false] `true` if both paths are already known to be normalized + * @returns {string} Path to the include file + */ +path.resolve = function resolve(originPath, includePath, alreadyNormalized) { + if (!alreadyNormalized) + includePath = normalize(includePath); + if (isAbsolute(includePath)) + return includePath; + if (!alreadyNormalized) + originPath = normalize(originPath); + return (originPath = originPath.replace(/(?:\/|^)[^/]+$/, "")).length ? normalize(originPath + "/" + includePath) : includePath; +}; diff --git a/server/node_modules/@protobufjs/path/package.json b/server/node_modules/@protobufjs/path/package.json new file mode 100644 index 0000000..ae0808a --- /dev/null +++ b/server/node_modules/@protobufjs/path/package.json @@ -0,0 +1,21 @@ +{ + "name": "@protobufjs/path", + "description": "A minimal path module to resolve Unix, Windows and URL paths alike.", + "version": "1.1.2", + "author": "Daniel Wirtz <dcode+protobufjs@dcode.io>", + "repository": { + "type": "git", + "url": "https://github.com/dcodeIO/protobuf.js.git" + }, + "license": "BSD-3-Clause", + "main": "index.js", + "types": "index.d.ts", + "devDependencies": { + "istanbul": "^0.4.5", + "tape": "^4.6.3" + }, + "scripts": { + "test": "tape tests/*.js", + "coverage": "istanbul cover node_modules/tape/bin/tape tests/*.js" + } +} \ No newline at end of file diff --git a/server/node_modules/@protobufjs/path/tests/index.js b/server/node_modules/@protobufjs/path/tests/index.js new file mode 100644 index 0000000..927736e --- /dev/null +++ b/server/node_modules/@protobufjs/path/tests/index.js @@ -0,0 +1,60 @@ +var tape = require("tape"); + +var path = require(".."); + +tape.test("path", function(test) { + + test.ok(path.isAbsolute("X:\\some\\path\\file.js"), "should identify absolute windows paths"); + test.ok(path.isAbsolute("/some/path/file.js"), "should identify absolute unix paths"); + + test.notOk(path.isAbsolute("some\\path\\file.js"), "should identify relative windows paths"); + test.notOk(path.isAbsolute("some/path/file.js"), "should identify relative unix paths"); + + var paths = [ + { + actual: "X:\\some\\..\\.\\path\\\\file.js", + normal: "X:/path/file.js", + resolve: { + origin: "X:/path/origin.js", + expected: "X:/path/file.js" + } + }, { + actual: "some\\..\\.\\path\\\\file.js", + normal: "path/file.js", + resolve: { + origin: "X:/path/origin.js", + expected: "X:/path/path/file.js" + } + }, { + actual: "/some/.././path//file.js", + normal: "/path/file.js", + resolve: { + origin: "/path/origin.js", + expected: "/path/file.js" + } + }, { + actual: "some/.././path//file.js", + normal: "path/file.js", + resolve: { + origin: "", + expected: "path/file.js" + } + }, { + actual: ".././path//file.js", + normal: "../path/file.js" + }, { + actual: "/.././path//file.js", + normal: "/path/file.js" + } + ]; + + paths.forEach(function(p) { + test.equal(path.normalize(p.actual), p.normal, "should normalize " + p.actual); + if (p.resolve) { + test.equal(path.resolve(p.resolve.origin, p.actual), p.resolve.expected, "should resolve " + p.actual); + test.equal(path.resolve(p.resolve.origin, p.normal, true), p.resolve.expected, "should resolve " + p.normal + " (already normalized)"); + } + }); + + test.end(); +}); diff --git a/server/node_modules/@protobufjs/pool/.npmignore b/server/node_modules/@protobufjs/pool/.npmignore new file mode 100644 index 0000000..ce75de4 --- /dev/null +++ b/server/node_modules/@protobufjs/pool/.npmignore @@ -0,0 +1,3 @@ +npm-debug.* +node_modules/ +coverage/ diff --git a/server/node_modules/@protobufjs/pool/LICENSE b/server/node_modules/@protobufjs/pool/LICENSE new file mode 100644 index 0000000..2a2d560 --- /dev/null +++ b/server/node_modules/@protobufjs/pool/LICENSE @@ -0,0 +1,26 @@ +Copyright (c) 2016, Daniel Wirtz All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +* Neither the name of its author, nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/server/node_modules/@protobufjs/pool/README.md b/server/node_modules/@protobufjs/pool/README.md new file mode 100644 index 0000000..3955ae0 --- /dev/null +++ b/server/node_modules/@protobufjs/pool/README.md @@ -0,0 +1,13 @@ +@protobufjs/pool +================ +[![npm](https://img.shields.io/npm/v/@protobufjs/pool.svg)](https://www.npmjs.com/package/@protobufjs/pool) + +A general purpose buffer pool. + +API +--- + +* **pool(alloc: `function(size: number): Uint8Array`, slice: `function(this: Uint8Array, start: number, end: number): Uint8Array`, [size=8192: `number`]): `function(size: number): Uint8Array`**<br /> + Creates a pooled allocator. + +**License:** [BSD 3-Clause License](https://opensource.org/licenses/BSD-3-Clause) diff --git a/server/node_modules/@protobufjs/pool/index.d.ts b/server/node_modules/@protobufjs/pool/index.d.ts new file mode 100644 index 0000000..465559c --- /dev/null +++ b/server/node_modules/@protobufjs/pool/index.d.ts @@ -0,0 +1,32 @@ +export = pool; + +/** + * An allocator as used by {@link util.pool}. + * @typedef PoolAllocator + * @type {function} + * @param {number} size Buffer size + * @returns {Uint8Array} Buffer + */ +type PoolAllocator = (size: number) => Uint8Array; + +/** + * A slicer as used by {@link util.pool}. + * @typedef PoolSlicer + * @type {function} + * @param {number} start Start offset + * @param {number} end End offset + * @returns {Uint8Array} Buffer slice + * @this {Uint8Array} + */ +type PoolSlicer = (this: Uint8Array, start: number, end: number) => Uint8Array; + +/** + * A general purpose buffer pool. + * @memberof util + * @function + * @param {PoolAllocator} alloc Allocator + * @param {PoolSlicer} slice Slicer + * @param {number} [size=8192] Slab size + * @returns {PoolAllocator} Pooled allocator + */ +declare function pool(alloc: PoolAllocator, slice: PoolSlicer, size?: number): PoolAllocator; diff --git a/server/node_modules/@protobufjs/pool/index.js b/server/node_modules/@protobufjs/pool/index.js new file mode 100644 index 0000000..9556f5a --- /dev/null +++ b/server/node_modules/@protobufjs/pool/index.js @@ -0,0 +1,48 @@ +"use strict"; +module.exports = pool; + +/** + * An allocator as used by {@link util.pool}. + * @typedef PoolAllocator + * @type {function} + * @param {number} size Buffer size + * @returns {Uint8Array} Buffer + */ + +/** + * A slicer as used by {@link util.pool}. + * @typedef PoolSlicer + * @type {function} + * @param {number} start Start offset + * @param {number} end End offset + * @returns {Uint8Array} Buffer slice + * @this {Uint8Array} + */ + +/** + * A general purpose buffer pool. + * @memberof util + * @function + * @param {PoolAllocator} alloc Allocator + * @param {PoolSlicer} slice Slicer + * @param {number} [size=8192] Slab size + * @returns {PoolAllocator} Pooled allocator + */ +function pool(alloc, slice, size) { + var SIZE = size || 8192; + var MAX = SIZE >>> 1; + var slab = null; + var offset = SIZE; + return function pool_alloc(size) { + if (size < 1 || size > MAX) + return alloc(size); + if (offset + size > SIZE) { + slab = alloc(SIZE); + offset = 0; + } + var buf = slice.call(slab, offset, offset += size); + if (offset & 7) // align to 32 bit + offset = (offset | 7) + 1; + return buf; + }; +} diff --git a/server/node_modules/@protobufjs/pool/package.json b/server/node_modules/@protobufjs/pool/package.json new file mode 100644 index 0000000..f025e03 --- /dev/null +++ b/server/node_modules/@protobufjs/pool/package.json @@ -0,0 +1,21 @@ +{ + "name": "@protobufjs/pool", + "description": "A general purpose buffer pool.", + "version": "1.1.0", + "author": "Daniel Wirtz <dcode+protobufjs@dcode.io>", + "repository": { + "type": "git", + "url": "https://github.com/dcodeIO/protobuf.js.git" + }, + "license": "BSD-3-Clause", + "main": "index.js", + "types": "index.d.ts", + "devDependencies": { + "istanbul": "^0.4.5", + "tape": "^4.6.3" + }, + "scripts": { + "test": "tape tests/*.js", + "coverage": "istanbul cover node_modules/tape/bin/tape tests/*.js" + } +} diff --git a/server/node_modules/@protobufjs/pool/tests/index.js b/server/node_modules/@protobufjs/pool/tests/index.js new file mode 100644 index 0000000..dc488b8 --- /dev/null +++ b/server/node_modules/@protobufjs/pool/tests/index.js @@ -0,0 +1,33 @@ +var tape = require("tape"); + +var pool = require(".."); + +if (typeof Uint8Array !== "undefined") +tape.test("pool", function(test) { + + var alloc = pool(function(size) { return new Uint8Array(size); }, Uint8Array.prototype.subarray); + + var buf1 = alloc(0); + test.equal(buf1.length, 0, "should allocate a buffer of size 0"); + + var buf2 = alloc(1); + test.equal(buf2.length, 1, "should allocate a buffer of size 1 (initializes slab)"); + + test.notEqual(buf2.buffer, buf1.buffer, "should not reference the same backing buffer if previous buffer had size 0"); + test.equal(buf2.byteOffset, 0, "should allocate at byteOffset 0 when using a new slab"); + + buf1 = alloc(1); + test.equal(buf1.buffer, buf2.buffer, "should reference the same backing buffer when allocating a chunk fitting into the slab"); + test.equal(buf1.byteOffset, 8, "should align slices to 32 bit and this allocate at byteOffset 8"); + + var buf3 = alloc(4097); + test.notEqual(buf3.buffer, buf2.buffer, "should not reference the same backing buffer when allocating a buffer larger than half the backing buffer's size"); + + buf2 = alloc(4096); + test.equal(buf2.buffer, buf1.buffer, "should reference the same backing buffer when allocating a buffer smaller or equal than half the backing buffer's size"); + + buf1 = alloc(4096); + test.notEqual(buf1.buffer, buf2.buffer, "should not reference the same backing buffer when the slab is exhausted (initializes new slab)"); + + test.end(); +}); \ No newline at end of file diff --git a/server/node_modules/@protobufjs/utf8/.npmignore b/server/node_modules/@protobufjs/utf8/.npmignore new file mode 100644 index 0000000..ce75de4 --- /dev/null +++ b/server/node_modules/@protobufjs/utf8/.npmignore @@ -0,0 +1,3 @@ +npm-debug.* +node_modules/ +coverage/ diff --git a/server/node_modules/@protobufjs/utf8/LICENSE b/server/node_modules/@protobufjs/utf8/LICENSE new file mode 100644 index 0000000..2a2d560 --- /dev/null +++ b/server/node_modules/@protobufjs/utf8/LICENSE @@ -0,0 +1,26 @@ +Copyright (c) 2016, Daniel Wirtz All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +* Neither the name of its author, nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/server/node_modules/@protobufjs/utf8/README.md b/server/node_modules/@protobufjs/utf8/README.md new file mode 100644 index 0000000..3696289 --- /dev/null +++ b/server/node_modules/@protobufjs/utf8/README.md @@ -0,0 +1,20 @@ +@protobufjs/utf8 +================ +[![npm](https://img.shields.io/npm/v/@protobufjs/utf8.svg)](https://www.npmjs.com/package/@protobufjs/utf8) + +A minimal UTF8 implementation for number arrays. + +API +--- + +* **utf8.length(string: `string`): `number`**<br /> + Calculates the UTF8 byte length of a string. + +* **utf8.read(buffer: `Uint8Array`, start: `number`, end: `number`): `string`**<br /> + Reads UTF8 bytes as a string. + +* **utf8.write(string: `string`, buffer: `Uint8Array`, offset: `number`): `number`**<br /> + Writes a string as UTF8 bytes. + + +**License:** [BSD 3-Clause License](https://opensource.org/licenses/BSD-3-Clause) diff --git a/server/node_modules/@protobufjs/utf8/index.d.ts b/server/node_modules/@protobufjs/utf8/index.d.ts new file mode 100644 index 0000000..010888c --- /dev/null +++ b/server/node_modules/@protobufjs/utf8/index.d.ts @@ -0,0 +1,24 @@ +/** + * Calculates the UTF8 byte length of a string. + * @param {string} string String + * @returns {number} Byte length + */ +export function length(string: string): number; + +/** + * Reads UTF8 bytes as a string. + * @param {Uint8Array} buffer Source buffer + * @param {number} start Source start + * @param {number} end Source end + * @returns {string} String read + */ +export function read(buffer: Uint8Array, start: number, end: number): string; + +/** + * Writes a string as UTF8 bytes. + * @param {string} string Source string + * @param {Uint8Array} buffer Destination buffer + * @param {number} offset Destination offset + * @returns {number} Bytes written + */ +export function write(string: string, buffer: Uint8Array, offset: number): number; diff --git a/server/node_modules/@protobufjs/utf8/index.js b/server/node_modules/@protobufjs/utf8/index.js new file mode 100644 index 0000000..e4ff8df --- /dev/null +++ b/server/node_modules/@protobufjs/utf8/index.js @@ -0,0 +1,105 @@ +"use strict"; + +/** + * A minimal UTF8 implementation for number arrays. + * @memberof util + * @namespace + */ +var utf8 = exports; + +/** + * Calculates the UTF8 byte length of a string. + * @param {string} string String + * @returns {number} Byte length + */ +utf8.length = function utf8_length(string) { + var len = 0, + c = 0; + for (var i = 0; i < string.length; ++i) { + c = string.charCodeAt(i); + if (c < 128) + len += 1; + else if (c < 2048) + len += 2; + else if ((c & 0xFC00) === 0xD800 && (string.charCodeAt(i + 1) & 0xFC00) === 0xDC00) { + ++i; + len += 4; + } else + len += 3; + } + return len; +}; + +/** + * Reads UTF8 bytes as a string. + * @param {Uint8Array} buffer Source buffer + * @param {number} start Source start + * @param {number} end Source end + * @returns {string} String read + */ +utf8.read = function utf8_read(buffer, start, end) { + var len = end - start; + if (len < 1) + return ""; + var parts = null, + chunk = [], + i = 0, // char offset + t; // temporary + while (start < end) { + t = buffer[start++]; + if (t < 128) + chunk[i++] = t; + else if (t > 191 && t < 224) + chunk[i++] = (t & 31) << 6 | buffer[start++] & 63; + else if (t > 239 && t < 365) { + t = ((t & 7) << 18 | (buffer[start++] & 63) << 12 | (buffer[start++] & 63) << 6 | buffer[start++] & 63) - 0x10000; + chunk[i++] = 0xD800 + (t >> 10); + chunk[i++] = 0xDC00 + (t & 1023); + } else + chunk[i++] = (t & 15) << 12 | (buffer[start++] & 63) << 6 | buffer[start++] & 63; + if (i > 8191) { + (parts || (parts = [])).push(String.fromCharCode.apply(String, chunk)); + i = 0; + } + } + if (parts) { + if (i) + parts.push(String.fromCharCode.apply(String, chunk.slice(0, i))); + return parts.join(""); + } + return String.fromCharCode.apply(String, chunk.slice(0, i)); +}; + +/** + * Writes a string as UTF8 bytes. + * @param {string} string Source string + * @param {Uint8Array} buffer Destination buffer + * @param {number} offset Destination offset + * @returns {number} Bytes written + */ +utf8.write = function utf8_write(string, buffer, offset) { + var start = offset, + c1, // character 1 + c2; // character 2 + for (var i = 0; i < string.length; ++i) { + c1 = string.charCodeAt(i); + if (c1 < 128) { + buffer[offset++] = c1; + } else if (c1 < 2048) { + buffer[offset++] = c1 >> 6 | 192; + buffer[offset++] = c1 & 63 | 128; + } else if ((c1 & 0xFC00) === 0xD800 && ((c2 = string.charCodeAt(i + 1)) & 0xFC00) === 0xDC00) { + c1 = 0x10000 + ((c1 & 0x03FF) << 10) + (c2 & 0x03FF); + ++i; + buffer[offset++] = c1 >> 18 | 240; + buffer[offset++] = c1 >> 12 & 63 | 128; + buffer[offset++] = c1 >> 6 & 63 | 128; + buffer[offset++] = c1 & 63 | 128; + } else { + buffer[offset++] = c1 >> 12 | 224; + buffer[offset++] = c1 >> 6 & 63 | 128; + buffer[offset++] = c1 & 63 | 128; + } + } + return offset - start; +}; diff --git a/server/node_modules/@protobufjs/utf8/package.json b/server/node_modules/@protobufjs/utf8/package.json new file mode 100644 index 0000000..80881c5 --- /dev/null +++ b/server/node_modules/@protobufjs/utf8/package.json @@ -0,0 +1,21 @@ +{ + "name": "@protobufjs/utf8", + "description": "A minimal UTF8 implementation for number arrays.", + "version": "1.1.0", + "author": "Daniel Wirtz <dcode+protobufjs@dcode.io>", + "repository": { + "type": "git", + "url": "https://github.com/dcodeIO/protobuf.js.git" + }, + "license": "BSD-3-Clause", + "main": "index.js", + "types": "index.d.ts", + "devDependencies": { + "istanbul": "^0.4.5", + "tape": "^4.6.3" + }, + "scripts": { + "test": "tape tests/*.js", + "coverage": "istanbul cover node_modules/tape/bin/tape tests/*.js" + } +} diff --git a/server/node_modules/@protobufjs/utf8/tests/data/utf8.txt b/server/node_modules/@protobufjs/utf8/tests/data/utf8.txt new file mode 100644 index 0000000..580b4c4 --- /dev/null +++ b/server/node_modules/@protobufjs/utf8/tests/data/utf8.txt @@ -0,0 +1,216 @@ +UTF-8 encoded sample plain-text file +‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +Markus Kuhn [ˈmaʳkʊs kuːn] <http://www.cl.cam.ac.uk/~mgk25/> — 2002-07-25 CC BY + + +The ASCII compatible UTF-8 encoding used in this plain-text file +is defined in Unicode, ISO 10646-1, and RFC 2279. + + +Using Unicode/UTF-8, you can write in emails and source code things such as + +Mathematics and sciences: + + ∮ E⋅da = Q, n → ∞, ∑ f(i) = ∏ g(i), ⎧⎡⎛┌─────┐⎞⎤⎫ + ⎪⎢⎜│a²+b³ ⎟⎥⎪ + ∀x∈ℝ: ⌈x⌉ = −⌊−x⌋, α ∧ ¬β = ¬(¬α ∨ β), ⎪⎢⎜│───── ⎟⎥⎪ + ⎪⎢⎜⎷ c₈ ⎟⎥⎪ + ℕ ⊆ ℕ₀ ⊂ ℤ ⊂ ℚ ⊂ ℝ ⊂ ℂ, ⎨⎢⎜ ⎟⎥⎬ + ⎪⎢⎜ ∞ ⎟⎥⎪ + ⊥ < a ≠ b ≡ c ≤ d ≪ ⊤ ⇒ (⟦A⟧ ⇔ ⟪B⟫), ⎪⎢⎜ ⎲ ⎟⎥⎪ + ⎪⎢⎜ ⎳aⁱ-bⁱ⎟⎥⎪ + 2H₂ + O₂ ⇌ 2H₂O, R = 4.7 kΩ, ⌀ 200 mm ⎩⎣⎝i=1 ⎠⎦⎭ + +Linguistics and dictionaries: + + ði ıntəˈnæʃənəl fəˈnɛtık əsoʊsiˈeıʃn + Y [ˈʏpsilɔn], Yen [jɛn], Yoga [ˈjoːgɑ] + +APL: + + ((V⍳V)=⍳⍴V)/V←,V ⌷←⍳→⍴∆∇⊃‾⍎⍕⌈ + +Nicer typography in plain text files: + + ╔══════════════════════════════════════════╗ + ║ ║ + ║ • ‘single’ and “double” quotes ║ + ║ ║ + ║ • Curly apostrophes: “We’ve been here” ║ + ║ ║ + ║ • Latin-1 apostrophe and accents: '´` ║ + ║ ║ + ║ • ‚deutsche‘ „Anführungszeichen“ ║ + ║ ║ + ║ • †, ‡, ‰, •, 3–4, —, −5/+5, ™, … ║ + ║ ║ + ║ • ASCII safety test: 1lI|, 0OD, 8B ║ + ║ ╭─────────╮ ║ + ║ • the euro symbol: │ 14.95 € │ ║ + ║ ╰─────────╯ ║ + ╚══════════════════════════════════════════╝ + +Combining characters: + + STARGΛ̊TE SG-1, a = v̇ = r̈, a⃑ ⊥ b⃑ + +Greek (in Polytonic): + + The Greek anthem: + + Σὲ γνωρίζω ἀπὸ τὴν κόψη + τοῦ σπαθιοῦ τὴν τρομερή, + σὲ γνωρίζω ἀπὸ τὴν ὄψη + ποὺ μὲ βία μετράει τὴ γῆ. + + ᾿Απ᾿ τὰ κόκκαλα βγαλμένη + τῶν ῾Ελλήνων τὰ ἱερά + καὶ σὰν πρῶτα ἀνδρειωμένη + χαῖρε, ὦ χαῖρε, ᾿Ελευθεριά! + + From a speech of Demosthenes in the 4th century BC: + + Οὐχὶ ταὐτὰ παρίσταταί μοι γιγνώσκειν, ὦ ἄνδρες ᾿Αθηναῖοι, + ὅταν τ᾿ εἰς τὰ πράγματα ἀποβλέψω καὶ ὅταν πρὸς τοὺς + λόγους οὓς ἀκούω· τοὺς μὲν γὰρ λόγους περὶ τοῦ + τιμωρήσασθαι Φίλιππον ὁρῶ γιγνομένους, τὰ δὲ πράγματ᾿ + εἰς τοῦτο προήκοντα, ὥσθ᾿ ὅπως μὴ πεισόμεθ᾿ αὐτοὶ + πρότερον κακῶς σκέψασθαι δέον. οὐδέν οὖν ἄλλο μοι δοκοῦσιν + οἱ τὰ τοιαῦτα λέγοντες ἢ τὴν ὑπόθεσιν, περὶ ἧς βουλεύεσθαι, + οὐχὶ τὴν οὖσαν παριστάντες ὑμῖν ἁμαρτάνειν. ἐγὼ δέ, ὅτι μέν + ποτ᾿ ἐξῆν τῇ πόλει καὶ τὰ αὑτῆς ἔχειν ἀσφαλῶς καὶ Φίλιππον + τιμωρήσασθαι, καὶ μάλ᾿ ἀκριβῶς οἶδα· ἐπ᾿ ἐμοῦ γάρ, οὐ πάλαι + γέγονεν ταῦτ᾿ ἀμφότερα· νῦν μέντοι πέπεισμαι τοῦθ᾿ ἱκανὸν + προλαβεῖν ἡμῖν εἶναι τὴν πρώτην, ὅπως τοὺς συμμάχους + σώσομεν. ἐὰν γὰρ τοῦτο βεβαίως ὑπάρξῃ, τότε καὶ περὶ τοῦ + τίνα τιμωρήσεταί τις καὶ ὃν τρόπον ἐξέσται σκοπεῖν· πρὶν δὲ + τὴν ἀρχὴν ὀρθῶς ὑποθέσθαι, μάταιον ἡγοῦμαι περὶ τῆς + τελευτῆς ὁντινοῦν ποιεῖσθαι λόγον. + + Δημοσθένους, Γ´ ᾿Ολυνθιακὸς + +Georgian: + + From a Unicode conference invitation: + + გთხოვთ ახლავე გაიაროთ რეგისტრაცია Unicode-ის მეათე საერთაშორისო + კონფერენციაზე დასასწრებად, რომელიც გაიმართება 10-12 მარტს, + ქ. მაინცში, გერმანიაში. კონფერენცია შეჰკრებს ერთად მსოფლიოს + ექსპერტებს ისეთ დარგებში როგორიცაა ინტერნეტი და Unicode-ი, + ინტერნაციონალიზაცია და ლოკალიზაცია, Unicode-ის გამოყენება + ოპერაციულ სისტემებსა, და გამოყენებით პროგრამებში, შრიფტებში, + ტექსტების დამუშავებასა და მრავალენოვან კომპიუტერულ სისტემებში. + +Russian: + + From a Unicode conference invitation: + + Зарегистрируйтесь сейчас на Десятую Международную Конференцию по + Unicode, которая состоится 10-12 марта 1997 года в Майнце в Германии. + Конференция соберет широкий круг экспертов по вопросам глобального + Интернета и Unicode, локализации и интернационализации, воплощению и + применению Unicode в различных операционных системах и программных + приложениях, шрифтах, верстке и многоязычных компьютерных системах. + +Thai (UCS Level 2): + + Excerpt from a poetry on The Romance of The Three Kingdoms (a Chinese + classic 'San Gua'): + + [----------------------------|------------------------] + ๏ แผ่นดินฮั่นเสื่อมโทรมแสนสังเวช พระปกเกศกองบู๊กู้ขึ้นใหม่ + สิบสองกษัตริย์ก่อนหน้าแลถัดไป สององค์ไซร้โง่เขลาเบาปัญญา + ทรงนับถือขันทีเป็นที่พึ่ง บ้านเมืองจึงวิปริตเป็นนักหนา + โฮจิ๋นเรียกทัพทั่วหัวเมืองมา หมายจะฆ่ามดชั่วตัวสำคัญ + เหมือนขับไสไล่เสือจากเคหา รับหมาป่าเข้ามาเลยอาสัญ + ฝ่ายอ้องอุ้นยุแยกให้แตกกัน ใช้สาวนั้นเป็นชนวนชื่นชวนใจ + พลันลิฉุยกุยกีกลับก่อเหตุ ช่างอาเพศจริงหนาฟ้าร้องไห้ + ต้องรบราฆ่าฟันจนบรรลัย ฤๅหาใครค้ำชูกู้บรรลังก์ ฯ + + (The above is a two-column text. If combining characters are handled + correctly, the lines of the second column should be aligned with the + | character above.) + +Ethiopian: + + Proverbs in the Amharic language: + + ሰማይ አይታረስ ንጉሥ አይከሰስ። + ብላ ካለኝ እንደአባቴ በቆመጠኝ። + ጌጥ ያለቤቱ ቁምጥና ነው። + ደሀ በሕልሙ ቅቤ ባይጠጣ ንጣት በገደለው። + የአፍ ወለምታ በቅቤ አይታሽም። + አይጥ በበላ ዳዋ ተመታ። + ሲተረጉሙ ይደረግሙ። + ቀስ በቀስ፥ ዕንቁላል በእግሩ ይሄዳል። + ድር ቢያብር አንበሳ ያስር። + ሰው እንደቤቱ እንጅ እንደ ጉረቤቱ አይተዳደርም። + እግዜር የከፈተውን ጉሮሮ ሳይዘጋው አይድርም። + የጎረቤት ሌባ፥ ቢያዩት ይስቅ ባያዩት ያጠልቅ። + ሥራ ከመፍታት ልጄን ላፋታት። + ዓባይ ማደሪያ የለው፥ ግንድ ይዞ ይዞራል። + የእስላም አገሩ መካ የአሞራ አገሩ ዋርካ። + ተንጋሎ ቢተፉ ተመልሶ ባፉ። + ወዳጅህ ማር ቢሆን ጨርስህ አትላሰው። + እግርህን በፍራሽህ ልክ ዘርጋ። + +Runes: + + ᚻᛖ ᚳᚹᚫᚦ ᚦᚫᛏ ᚻᛖ ᛒᚢᛞᛖ ᚩᚾ ᚦᚫᛗ ᛚᚪᚾᛞᛖ ᚾᚩᚱᚦᚹᛖᚪᚱᛞᚢᛗ ᚹᛁᚦ ᚦᚪ ᚹᛖᛥᚫ + + (Old English, which transcribed into Latin reads 'He cwaeth that he + bude thaem lande northweardum with tha Westsae.' and means 'He said + that he lived in the northern land near the Western Sea.') + +Braille: + + ⡌⠁⠧⠑ ⠼⠁⠒ ⡍⠜⠇⠑⠹⠰⠎ ⡣⠕⠌ + + ⡍⠜⠇⠑⠹ ⠺⠁⠎ ⠙⠑⠁⠙⠒ ⠞⠕ ⠃⠑⠛⠔ ⠺⠊⠹⠲ ⡹⠻⠑ ⠊⠎ ⠝⠕ ⠙⠳⠃⠞ + ⠱⠁⠞⠑⠧⠻ ⠁⠃⠳⠞ ⠹⠁⠞⠲ ⡹⠑ ⠗⠑⠛⠊⠌⠻ ⠕⠋ ⠙⠊⠎ ⠃⠥⠗⠊⠁⠇ ⠺⠁⠎ + ⠎⠊⠛⠝⠫ ⠃⠹ ⠹⠑ ⠊⠇⠻⠛⠹⠍⠁⠝⠂ ⠹⠑ ⠊⠇⠻⠅⠂ ⠹⠑ ⠥⠝⠙⠻⠞⠁⠅⠻⠂ + ⠁⠝⠙ ⠹⠑ ⠡⠊⠑⠋ ⠍⠳⠗⠝⠻⠲ ⡎⠊⠗⠕⠕⠛⠑ ⠎⠊⠛⠝⠫ ⠊⠞⠲ ⡁⠝⠙ + ⡎⠊⠗⠕⠕⠛⠑⠰⠎ ⠝⠁⠍⠑ ⠺⠁⠎ ⠛⠕⠕⠙ ⠥⠏⠕⠝ ⠰⡡⠁⠝⠛⠑⠂ ⠋⠕⠗ ⠁⠝⠹⠹⠔⠛ ⠙⠑ + ⠡⠕⠎⠑ ⠞⠕ ⠏⠥⠞ ⠙⠊⠎ ⠙⠁⠝⠙ ⠞⠕⠲ + + ⡕⠇⠙ ⡍⠜⠇⠑⠹ ⠺⠁⠎ ⠁⠎ ⠙⠑⠁⠙ ⠁⠎ ⠁ ⠙⠕⠕⠗⠤⠝⠁⠊⠇⠲ + + ⡍⠔⠙⠖ ⡊ ⠙⠕⠝⠰⠞ ⠍⠑⠁⠝ ⠞⠕ ⠎⠁⠹ ⠹⠁⠞ ⡊ ⠅⠝⠪⠂ ⠕⠋ ⠍⠹ + ⠪⠝ ⠅⠝⠪⠇⠫⠛⠑⠂ ⠱⠁⠞ ⠹⠻⠑ ⠊⠎ ⠏⠜⠞⠊⠊⠥⠇⠜⠇⠹ ⠙⠑⠁⠙ ⠁⠃⠳⠞ + ⠁ ⠙⠕⠕⠗⠤⠝⠁⠊⠇⠲ ⡊ ⠍⠊⠣⠞ ⠙⠁⠧⠑ ⠃⠑⠲ ⠔⠊⠇⠔⠫⠂ ⠍⠹⠎⠑⠇⠋⠂ ⠞⠕ + ⠗⠑⠛⠜⠙ ⠁ ⠊⠕⠋⠋⠔⠤⠝⠁⠊⠇ ⠁⠎ ⠹⠑ ⠙⠑⠁⠙⠑⠌ ⠏⠊⠑⠊⠑ ⠕⠋ ⠊⠗⠕⠝⠍⠕⠝⠛⠻⠹ + ⠔ ⠹⠑ ⠞⠗⠁⠙⠑⠲ ⡃⠥⠞ ⠹⠑ ⠺⠊⠎⠙⠕⠍ ⠕⠋ ⠳⠗ ⠁⠝⠊⠑⠌⠕⠗⠎ + ⠊⠎ ⠔ ⠹⠑ ⠎⠊⠍⠊⠇⠑⠆ ⠁⠝⠙ ⠍⠹ ⠥⠝⠙⠁⠇⠇⠪⠫ ⠙⠁⠝⠙⠎ + ⠩⠁⠇⠇ ⠝⠕⠞ ⠙⠊⠌⠥⠗⠃ ⠊⠞⠂ ⠕⠗ ⠹⠑ ⡊⠳⠝⠞⠗⠹⠰⠎ ⠙⠕⠝⠑ ⠋⠕⠗⠲ ⡹⠳ + ⠺⠊⠇⠇ ⠹⠻⠑⠋⠕⠗⠑ ⠏⠻⠍⠊⠞ ⠍⠑ ⠞⠕ ⠗⠑⠏⠑⠁⠞⠂ ⠑⠍⠏⠙⠁⠞⠊⠊⠁⠇⠇⠹⠂ ⠹⠁⠞ + ⡍⠜⠇⠑⠹ ⠺⠁⠎ ⠁⠎ ⠙⠑⠁⠙ ⠁⠎ ⠁ ⠙⠕⠕⠗⠤⠝⠁⠊⠇⠲ + + (The first couple of paragraphs of "A Christmas Carol" by Dickens) + +Compact font selection example text: + + ABCDEFGHIJKLMNOPQRSTUVWXYZ /0123456789 + abcdefghijklmnopqrstuvwxyz £©µÀÆÖÞßéöÿ + –—‘“”„†•…‰™œŠŸž€ ΑΒΓΔΩαβγδω АБВГДабвгд + ∀∂∈ℝ∧∪≡∞ ↑↗↨↻⇣ ┐┼╔╘░►☺♀ fi�⑀₂ἠḂӥẄɐː⍎אԱა + +Greetings in various languages: + + Hello world, Καλημέρα κόσμε, コンニチハ + +Box drawing alignment tests: █ + ▉ + ╔══╦══╗ ┌──┬──┐ ╭──┬──╮ ╭──┬──╮ ┏━━┳━━┓ ┎┒┏┑ ╷ ╻ ┏┯┓ ┌┰┐ ▊ ╱╲╱╲╳╳╳ + ║┌─╨─┐║ │╔═╧═╗│ │╒═╪═╕│ │╓─╁─╖│ ┃┌─╂─┐┃ ┗╃╄┙ ╶┼╴╺╋╸┠┼┨ ┝╋┥ ▋ ╲╱╲╱╳╳╳ + ║│╲ ╱│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╿ │┃ ┍╅╆┓ ╵ ╹ ┗┷┛ └┸┘ ▌ ╱╲╱╲╳╳╳ + ╠╡ ╳ ╞╣ ├╢ ╟┤ ├┼─┼─┼┤ ├╫─╂─╫┤ ┣┿╾┼╼┿┫ ┕┛┖┚ ┌┄┄┐ ╎ ┏┅┅┓ ┋ ▍ ╲╱╲╱╳╳╳ + ║│╱ ╲│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╽ │┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▎ + ║└─╥─┘║ │╚═╤═╝│ │╘═╪═╛│ │╙─╀─╜│ ┃└─╂─┘┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▏ + ╚══╩══╝ └──┴──┘ ╰──┴──╯ ╰──┴──╯ ┗━━┻━━┛ ▗▄▖▛▀▜ └╌╌┘ ╎ ┗╍╍┛ ┋ ▁▂▃▄▅▆▇█ + ▝▀▘▙▄▟ + +Surrogates: + +𠜎 𠜱 𠝹 𠱓 𠱸 𠲖 𠳏 𠳕 𠴕 𠵼 𠵿 𠸎 𠸏 𠹷 𠺝 𠺢 𠻗 𠻹 𠻺 𠼭 𠼮 𠽌 𠾴 𠾼 𠿪 𡁜 𡁯 𡁵 𡁶 𡁻 𡃁 +𡃉 𡇙 𢃇 𢞵 𢫕 𢭃 𢯊 𢱑 𢱕 𢳂 𢴈 𢵌 𢵧 𢺳 𣲷 𤓓 𤶸 𤷪 𥄫 𦉘 𦟌 𦧲 𦧺 𧨾 𨅝 𨈇 𨋢 𨳊 𨳍 𨳒 𩶘 diff --git a/server/node_modules/@protobufjs/utf8/tests/index.js b/server/node_modules/@protobufjs/utf8/tests/index.js new file mode 100644 index 0000000..222cd8a --- /dev/null +++ b/server/node_modules/@protobufjs/utf8/tests/index.js @@ -0,0 +1,57 @@ +var tape = require("tape"); + +var utf8 = require(".."); + +var data = require("fs").readFileSync(require.resolve("./data/utf8.txt")), + dataStr = data.toString("utf8"); + +tape.test("utf8", function(test) { + + test.test(test.name + " - length", function(test) { + test.equal(utf8.length(""), 0, "should return a byte length of zero for an empty string"); + + test.equal(utf8.length(dataStr), Buffer.byteLength(dataStr), "should return the same byte length as node buffers"); + + test.end(); + }); + + test.test(test.name + " - read", function(test) { + var comp = utf8.read([], 0, 0); + test.equal(comp, "", "should decode an empty buffer to an empty string"); + + comp = utf8.read(data, 0, data.length); + test.equal(comp, data.toString("utf8"), "should decode to the same byte data as node buffers"); + + var longData = Buffer.concat([data, data, data, data]); + comp = utf8.read(longData, 0, longData.length); + test.equal(comp, longData.toString("utf8"), "should decode to the same byte data as node buffers (long)"); + + var chunkData = new Buffer(data.toString("utf8").substring(0, 8192)); + comp = utf8.read(chunkData, 0, chunkData.length); + test.equal(comp, chunkData.toString("utf8"), "should decode to the same byte data as node buffers (chunk size)"); + + test.end(); + }); + + test.test(test.name + " - write", function(test) { + var buf = new Buffer(0); + test.equal(utf8.write("", buf, 0), 0, "should encode an empty string to an empty buffer"); + + var len = utf8.length(dataStr); + buf = new Buffer(len); + test.equal(utf8.write(dataStr, buf, 0), len, "should encode to exactly " + len + " bytes"); + + test.equal(buf.length, data.length, "should encode to a buffer length equal to that of node buffers"); + + for (var i = 0; i < buf.length; ++i) { + if (buf[i] !== data[i]) { + test.fail("should encode to the same buffer data as node buffers (offset " + i + ")"); + return; + } + } + test.pass("should encode to the same buffer data as node buffers"); + + test.end(); + }); + +}); diff --git a/server/node_modules/@types/node/LICENSE b/server/node_modules/@types/node/LICENSE new file mode 100644 index 0000000..9e841e7 --- /dev/null +++ b/server/node_modules/@types/node/LICENSE @@ -0,0 +1,21 @@ + MIT License + + Copyright (c) Microsoft Corporation. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE diff --git a/server/node_modules/@types/node/README.md b/server/node_modules/@types/node/README.md new file mode 100644 index 0000000..969cbd4 --- /dev/null +++ b/server/node_modules/@types/node/README.md @@ -0,0 +1,15 @@ +# Installation +> `npm install --save @types/node` + +# Summary +This package contains type definitions for node (https://nodejs.org/). + +# Details +Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node. + +### Additional Details + * Last updated: Tue, 10 Feb 2026 14:48:58 GMT + * Dependencies: [undici-types](https://npmjs.com/package/undici-types) + +# Credits +These definitions were written by [Microsoft TypeScript](https://github.com/Microsoft), [Alberto Schiabel](https://github.com/jkomyno), [Andrew Makarov](https://github.com/r3nya), [Benjamin Toueg](https://github.com/btoueg), [David Junger](https://github.com/touffy), [Mohsen Azimi](https://github.com/mohsen1), [Nikita Galkin](https://github.com/galkin), [Sebastian Silbermann](https://github.com/eps1lon), [Wilco Bakker](https://github.com/WilcoBakker), [Marcin Kopacz](https://github.com/chyzwar), [Trivikram Kamat](https://github.com/trivikr), [Junxiao Shi](https://github.com/yoursunny), [Ilia Baryshnikov](https://github.com/qwelias), [ExE Boss](https://github.com/ExE-Boss), [Piotr Błażejewicz](https://github.com/peterblazejewicz), [Anna Henningsen](https://github.com/addaleax), [Victor Perin](https://github.com/victorperin), [NodeJS Contributors](https://github.com/NodeJS), [Linus Unnebäck](https://github.com/LinusU), [wafuwafu13](https://github.com/wafuwafu13), [Matteo Collina](https://github.com/mcollina), [Dmitry Semigradsky](https://github.com/Semigradsky), [René](https://github.com/Renegade334), and [Yagiz Nizipli](https://github.com/anonrig). diff --git a/server/node_modules/@types/node/assert.d.ts b/server/node_modules/@types/node/assert.d.ts new file mode 100644 index 0000000..ef4d852 --- /dev/null +++ b/server/node_modules/@types/node/assert.d.ts @@ -0,0 +1,955 @@ +/** + * The `node:assert` module provides a set of assertion functions for verifying + * invariants. + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/assert.js) + */ +declare module "node:assert" { + import strict = require("node:assert/strict"); + /** + * An alias of {@link assert.ok}. + * @since v0.5.9 + * @param value The input that is checked for being truthy. + */ + function assert(value: unknown, message?: string | Error): asserts value; + const kOptions: unique symbol; + namespace assert { + type AssertMethodNames = + | "deepEqual" + | "deepStrictEqual" + | "doesNotMatch" + | "doesNotReject" + | "doesNotThrow" + | "equal" + | "fail" + | "ifError" + | "match" + | "notDeepEqual" + | "notDeepStrictEqual" + | "notEqual" + | "notStrictEqual" + | "ok" + | "partialDeepStrictEqual" + | "rejects" + | "strictEqual" + | "throws"; + interface AssertOptions { + /** + * If set to `'full'`, shows the full diff in assertion errors. + * @default 'simple' + */ + diff?: "simple" | "full" | undefined; + /** + * If set to `true`, non-strict methods behave like their + * corresponding strict methods. + * @default true + */ + strict?: boolean | undefined; + /** + * If set to `true`, skips prototype and constructor + * comparison in deep equality checks. + * @since v24.9.0 + * @default false + */ + skipPrototype?: boolean | undefined; + } + interface Assert extends Pick<typeof assert, AssertMethodNames> { + readonly [kOptions]: AssertOptions & { strict: false }; + } + interface AssertStrict extends Pick<typeof strict, AssertMethodNames> { + readonly [kOptions]: AssertOptions & { strict: true }; + } + /** + * The `Assert` class allows creating independent assertion instances with custom options. + * @since v24.6.0 + */ + var Assert: { + /** + * Creates a new assertion instance. The `diff` option controls the verbosity of diffs in assertion error messages. + * + * ```js + * const { Assert } = require('node:assert'); + * const assertInstance = new Assert({ diff: 'full' }); + * assertInstance.deepStrictEqual({ a: 1 }, { a: 2 }); + * // Shows a full diff in the error message. + * ``` + * + * **Important**: When destructuring assertion methods from an `Assert` instance, + * the methods lose their connection to the instance's configuration options (such + * as `diff`, `strict`, and `skipPrototype` settings). + * The destructured methods will fall back to default behavior instead. + * + * ```js + * const myAssert = new Assert({ diff: 'full' }); + * + * // This works as expected - uses 'full' diff + * myAssert.strictEqual({ a: 1 }, { b: { c: 1 } }); + * + * // This loses the 'full' diff setting - falls back to default 'simple' diff + * const { strictEqual } = myAssert; + * strictEqual({ a: 1 }, { b: { c: 1 } }); + * ``` + * + * The `skipPrototype` option affects all deep equality methods: + * + * ```js + * class Foo { + * constructor(a) { + * this.a = a; + * } + * } + * + * class Bar { + * constructor(a) { + * this.a = a; + * } + * } + * + * const foo = new Foo(1); + * const bar = new Bar(1); + * + * // Default behavior - fails due to different constructors + * const assert1 = new Assert(); + * assert1.deepStrictEqual(foo, bar); // AssertionError + * + * // Skip prototype comparison - passes if properties are equal + * const assert2 = new Assert({ skipPrototype: true }); + * assert2.deepStrictEqual(foo, bar); // OK + * ``` + * + * When destructured, methods lose access to the instance's `this` context and revert to default assertion behavior + * (diff: 'simple', non-strict mode). + * To maintain custom options when using destructured methods, avoid + * destructuring and call methods directly on the instance. + * @since v24.6.0 + */ + new( + options?: AssertOptions & { strict?: true | undefined }, + ): AssertStrict; + new( + options: AssertOptions, + ): Assert; + }; + interface AssertionErrorOptions { + /** + * If provided, the error message is set to this value. + */ + message?: string | undefined; + /** + * The `actual` property on the error instance. + */ + actual?: unknown; + /** + * The `expected` property on the error instance. + */ + expected?: unknown; + /** + * The `operator` property on the error instance. + */ + operator?: string | undefined; + /** + * If provided, the generated stack trace omits frames before this function. + */ + stackStartFn?: Function | undefined; + /** + * If set to `'full'`, shows the full diff in assertion errors. + * @default 'simple' + */ + diff?: "simple" | "full" | undefined; + } + /** + * Indicates the failure of an assertion. All errors thrown by the `node:assert` module will be instances of the `AssertionError` class. + */ + class AssertionError extends Error { + constructor(options: AssertionErrorOptions); + /** + * Set to the `actual` argument for methods such as {@link assert.strictEqual()}. + */ + actual: unknown; + /** + * Set to the `expected` argument for methods such as {@link assert.strictEqual()}. + */ + expected: unknown; + /** + * Indicates if the message was auto-generated (`true`) or not. + */ + generatedMessage: boolean; + /** + * Value is always `ERR_ASSERTION` to show that the error is an assertion error. + */ + code: "ERR_ASSERTION"; + /** + * Set to the passed in operator value. + */ + operator: string; + } + type AssertPredicate = RegExp | (new() => object) | ((thrown: unknown) => boolean) | object | Error; + /** + * Throws an `AssertionError` with the provided error message or a default + * error message. If the `message` parameter is an instance of an `Error` then + * it will be thrown instead of the `AssertionError`. + * + * ```js + * import assert from 'node:assert/strict'; + * + * assert.fail(); + * // AssertionError [ERR_ASSERTION]: Failed + * + * assert.fail('boom'); + * // AssertionError [ERR_ASSERTION]: boom + * + * assert.fail(new TypeError('need array')); + * // TypeError: need array + * ``` + * @since v0.1.21 + * @param [message='Failed'] + */ + function fail(message?: string | Error): never; + /** + * Tests if `value` is truthy. It is equivalent to `assert.equal(!!value, true, message)`. + * + * If `value` is not truthy, an `AssertionError` is thrown with a `message` property set equal to the value of the `message` parameter. If the `message` parameter is `undefined`, a default + * error message is assigned. If the `message` parameter is an instance of an `Error` then it will be thrown instead of the `AssertionError`. + * If no arguments are passed in at all `message` will be set to the string:`` 'No value argument passed to `assert.ok()`' ``. + * + * Be aware that in the `repl` the error message will be different to the one + * thrown in a file! See below for further details. + * + * ```js + * import assert from 'node:assert/strict'; + * + * assert.ok(true); + * // OK + * assert.ok(1); + * // OK + * + * assert.ok(); + * // AssertionError: No value argument passed to `assert.ok()` + * + * assert.ok(false, 'it\'s false'); + * // AssertionError: it's false + * + * // In the repl: + * assert.ok(typeof 123 === 'string'); + * // AssertionError: false == true + * + * // In a file (e.g. test.js): + * assert.ok(typeof 123 === 'string'); + * // AssertionError: The expression evaluated to a falsy value: + * // + * // assert.ok(typeof 123 === 'string') + * + * assert.ok(false); + * // AssertionError: The expression evaluated to a falsy value: + * // + * // assert.ok(false) + * + * assert.ok(0); + * // AssertionError: The expression evaluated to a falsy value: + * // + * // assert.ok(0) + * ``` + * + * ```js + * import assert from 'node:assert/strict'; + * + * // Using `assert()` works the same: + * assert(0); + * // AssertionError: The expression evaluated to a falsy value: + * // + * // assert(0) + * ``` + * @since v0.1.21 + */ + function ok(value: unknown, message?: string | Error): asserts value; + /** + * **Strict assertion mode** + * + * An alias of {@link strictEqual}. + * + * **Legacy assertion mode** + * + * > Stability: 3 - Legacy: Use {@link strictEqual} instead. + * + * Tests shallow, coercive equality between the `actual` and `expected` parameters + * using the [`==` operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Equality). `NaN` is specially handled + * and treated as being identical if both sides are `NaN`. + * + * ```js + * import assert from 'node:assert'; + * + * assert.equal(1, 1); + * // OK, 1 == 1 + * assert.equal(1, '1'); + * // OK, 1 == '1' + * assert.equal(NaN, NaN); + * // OK + * + * assert.equal(1, 2); + * // AssertionError: 1 == 2 + * assert.equal({ a: { b: 1 } }, { a: { b: 1 } }); + * // AssertionError: { a: { b: 1 } } == { a: { b: 1 } } + * ``` + * + * If the values are not equal, an `AssertionError` is thrown with a `message` property set equal to the value of the `message` parameter. If the `message` parameter is undefined, a default + * error message is assigned. If the `message` parameter is an instance of an `Error` then it will be thrown instead of the `AssertionError`. + * @since v0.1.21 + */ + function equal(actual: unknown, expected: unknown, message?: string | Error): void; + /** + * **Strict assertion mode** + * + * An alias of {@link notStrictEqual}. + * + * **Legacy assertion mode** + * + * > Stability: 3 - Legacy: Use {@link notStrictEqual} instead. + * + * Tests shallow, coercive inequality with the [`!=` operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Inequality). `NaN` is + * specially handled and treated as being identical if both sides are `NaN`. + * + * ```js + * import assert from 'node:assert'; + * + * assert.notEqual(1, 2); + * // OK + * + * assert.notEqual(1, 1); + * // AssertionError: 1 != 1 + * + * assert.notEqual(1, '1'); + * // AssertionError: 1 != '1' + * ``` + * + * If the values are equal, an `AssertionError` is thrown with a `message` property set equal to the value of the `message` parameter. If the `message` parameter is undefined, a default error + * message is assigned. If the `message` parameter is an instance of an `Error` then it will be thrown instead of the `AssertionError`. + * @since v0.1.21 + */ + function notEqual(actual: unknown, expected: unknown, message?: string | Error): void; + /** + * **Strict assertion mode** + * + * An alias of {@link deepStrictEqual}. + * + * **Legacy assertion mode** + * + * > Stability: 3 - Legacy: Use {@link deepStrictEqual} instead. + * + * Tests for deep equality between the `actual` and `expected` parameters. Consider + * using {@link deepStrictEqual} instead. {@link deepEqual} can have + * surprising results. + * + * _Deep equality_ means that the enumerable "own" properties of child objects + * are also recursively evaluated by the following rules. + * @since v0.1.21 + */ + function deepEqual(actual: unknown, expected: unknown, message?: string | Error): void; + /** + * **Strict assertion mode** + * + * An alias of {@link notDeepStrictEqual}. + * + * **Legacy assertion mode** + * + * > Stability: 3 - Legacy: Use {@link notDeepStrictEqual} instead. + * + * Tests for any deep inequality. Opposite of {@link deepEqual}. + * + * ```js + * import assert from 'node:assert'; + * + * const obj1 = { + * a: { + * b: 1, + * }, + * }; + * const obj2 = { + * a: { + * b: 2, + * }, + * }; + * const obj3 = { + * a: { + * b: 1, + * }, + * }; + * const obj4 = { __proto__: obj1 }; + * + * assert.notDeepEqual(obj1, obj1); + * // AssertionError: { a: { b: 1 } } notDeepEqual { a: { b: 1 } } + * + * assert.notDeepEqual(obj1, obj2); + * // OK + * + * assert.notDeepEqual(obj1, obj3); + * // AssertionError: { a: { b: 1 } } notDeepEqual { a: { b: 1 } } + * + * assert.notDeepEqual(obj1, obj4); + * // OK + * ``` + * + * If the values are deeply equal, an `AssertionError` is thrown with a `message` property set equal to the value of the `message` parameter. If the `message` parameter is undefined, a default + * error message is assigned. If the `message` parameter is an instance of an `Error` then it will be thrown + * instead of the `AssertionError`. + * @since v0.1.21 + */ + function notDeepEqual(actual: unknown, expected: unknown, message?: string | Error): void; + /** + * Tests strict equality between the `actual` and `expected` parameters as + * determined by [`Object.is()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is). + * + * ```js + * import assert from 'node:assert/strict'; + * + * assert.strictEqual(1, 2); + * // AssertionError [ERR_ASSERTION]: Expected inputs to be strictly equal: + * // + * // 1 !== 2 + * + * assert.strictEqual(1, 1); + * // OK + * + * assert.strictEqual('Hello foobar', 'Hello World!'); + * // AssertionError [ERR_ASSERTION]: Expected inputs to be strictly equal: + * // + actual - expected + * // + * // + 'Hello foobar' + * // - 'Hello World!' + * // ^ + * + * const apples = 1; + * const oranges = 2; + * assert.strictEqual(apples, oranges, `apples ${apples} !== oranges ${oranges}`); + * // AssertionError [ERR_ASSERTION]: apples 1 !== oranges 2 + * + * assert.strictEqual(1, '1', new TypeError('Inputs are not identical')); + * // TypeError: Inputs are not identical + * ``` + * + * If the values are not strictly equal, an `AssertionError` is thrown with a `message` property set equal to the value of the `message` parameter. If the `message` parameter is undefined, a + * default error message is assigned. If the `message` parameter is an instance of an `Error` then it will be thrown + * instead of the `AssertionError`. + * @since v0.1.21 + */ + function strictEqual<T>(actual: unknown, expected: T, message?: string | Error): asserts actual is T; + /** + * Tests strict inequality between the `actual` and `expected` parameters as + * determined by [`Object.is()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is). + * + * ```js + * import assert from 'node:assert/strict'; + * + * assert.notStrictEqual(1, 2); + * // OK + * + * assert.notStrictEqual(1, 1); + * // AssertionError [ERR_ASSERTION]: Expected "actual" to be strictly unequal to: + * // + * // 1 + * + * assert.notStrictEqual(1, '1'); + * // OK + * ``` + * + * If the values are strictly equal, an `AssertionError` is thrown with a `message` property set equal to the value of the `message` parameter. If the `message` parameter is undefined, a + * default error message is assigned. If the `message` parameter is an instance of an `Error` then it will be thrown + * instead of the `AssertionError`. + * @since v0.1.21 + */ + function notStrictEqual(actual: unknown, expected: unknown, message?: string | Error): void; + /** + * Tests for deep equality between the `actual` and `expected` parameters. + * "Deep" equality means that the enumerable "own" properties of child objects + * are recursively evaluated also by the following rules. + * @since v1.2.0 + */ + function deepStrictEqual<T>(actual: unknown, expected: T, message?: string | Error): asserts actual is T; + /** + * Tests for deep strict inequality. Opposite of {@link deepStrictEqual}. + * + * ```js + * import assert from 'node:assert/strict'; + * + * assert.notDeepStrictEqual({ a: 1 }, { a: '1' }); + * // OK + * ``` + * + * If the values are deeply and strictly equal, an `AssertionError` is thrown + * with a `message` property set equal to the value of the `message` parameter. If + * the `message` parameter is undefined, a default error message is assigned. If + * the `message` parameter is an instance of an `Error` then it will be thrown + * instead of the `AssertionError`. + * @since v1.2.0 + */ + function notDeepStrictEqual(actual: unknown, expected: unknown, message?: string | Error): void; + /** + * Expects the function `fn` to throw an error. + * + * If specified, `error` can be a [`Class`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes), + * [`RegExp`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions), a validation function, + * a validation object where each property will be tested for strict deep equality, + * or an instance of error where each property will be tested for strict deep + * equality including the non-enumerable `message` and `name` properties. When + * using an object, it is also possible to use a regular expression, when + * validating against a string property. See below for examples. + * + * If specified, `message` will be appended to the message provided by the `AssertionError` if the `fn` call fails to throw or in case the error validation + * fails. + * + * Custom validation object/error instance: + * + * ```js + * import assert from 'node:assert/strict'; + * + * const err = new TypeError('Wrong value'); + * err.code = 404; + * err.foo = 'bar'; + * err.info = { + * nested: true, + * baz: 'text', + * }; + * err.reg = /abc/i; + * + * assert.throws( + * () => { + * throw err; + * }, + * { + * name: 'TypeError', + * message: 'Wrong value', + * info: { + * nested: true, + * baz: 'text', + * }, + * // Only properties on the validation object will be tested for. + * // Using nested objects requires all properties to be present. Otherwise + * // the validation is going to fail. + * }, + * ); + * + * // Using regular expressions to validate error properties: + * assert.throws( + * () => { + * throw err; + * }, + * { + * // The `name` and `message` properties are strings and using regular + * // expressions on those will match against the string. If they fail, an + * // error is thrown. + * name: /^TypeError$/, + * message: /Wrong/, + * foo: 'bar', + * info: { + * nested: true, + * // It is not possible to use regular expressions for nested properties! + * baz: 'text', + * }, + * // The `reg` property contains a regular expression and only if the + * // validation object contains an identical regular expression, it is going + * // to pass. + * reg: /abc/i, + * }, + * ); + * + * // Fails due to the different `message` and `name` properties: + * assert.throws( + * () => { + * const otherErr = new Error('Not found'); + * // Copy all enumerable properties from `err` to `otherErr`. + * for (const [key, value] of Object.entries(err)) { + * otherErr[key] = value; + * } + * throw otherErr; + * }, + * // The error's `message` and `name` properties will also be checked when using + * // an error as validation object. + * err, + * ); + * ``` + * + * Validate instanceof using constructor: + * + * ```js + * import assert from 'node:assert/strict'; + * + * assert.throws( + * () => { + * throw new Error('Wrong value'); + * }, + * Error, + * ); + * ``` + * + * Validate error message using [`RegExp`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions): + * + * Using a regular expression runs `.toString` on the error object, and will + * therefore also include the error name. + * + * ```js + * import assert from 'node:assert/strict'; + * + * assert.throws( + * () => { + * throw new Error('Wrong value'); + * }, + * /^Error: Wrong value$/, + * ); + * ``` + * + * Custom error validation: + * + * The function must return `true` to indicate all internal validations passed. + * It will otherwise fail with an `AssertionError`. + * + * ```js + * import assert from 'node:assert/strict'; + * + * assert.throws( + * () => { + * throw new Error('Wrong value'); + * }, + * (err) => { + * assert(err instanceof Error); + * assert(/value/.test(err)); + * // Avoid returning anything from validation functions besides `true`. + * // Otherwise, it's not clear what part of the validation failed. Instead, + * // throw an error about the specific validation that failed (as done in this + * // example) and add as much helpful debugging information to that error as + * // possible. + * return true; + * }, + * 'unexpected error', + * ); + * ``` + * + * `error` cannot be a string. If a string is provided as the second + * argument, then `error` is assumed to be omitted and the string will be used for `message` instead. This can lead to easy-to-miss mistakes. Using the same + * message as the thrown error message is going to result in an `ERR_AMBIGUOUS_ARGUMENT` error. Please read the example below carefully if using + * a string as the second argument gets considered: + * + * ```js + * import assert from 'node:assert/strict'; + * + * function throwingFirst() { + * throw new Error('First'); + * } + * + * function throwingSecond() { + * throw new Error('Second'); + * } + * + * function notThrowing() {} + * + * // The second argument is a string and the input function threw an Error. + * // The first case will not throw as it does not match for the error message + * // thrown by the input function! + * assert.throws(throwingFirst, 'Second'); + * // In the next example the message has no benefit over the message from the + * // error and since it is not clear if the user intended to actually match + * // against the error message, Node.js throws an `ERR_AMBIGUOUS_ARGUMENT` error. + * assert.throws(throwingSecond, 'Second'); + * // TypeError [ERR_AMBIGUOUS_ARGUMENT] + * + * // The string is only used (as message) in case the function does not throw: + * assert.throws(notThrowing, 'Second'); + * // AssertionError [ERR_ASSERTION]: Missing expected exception: Second + * + * // If it was intended to match for the error message do this instead: + * // It does not throw because the error messages match. + * assert.throws(throwingSecond, /Second$/); + * + * // If the error message does not match, an AssertionError is thrown. + * assert.throws(throwingFirst, /Second$/); + * // AssertionError [ERR_ASSERTION] + * ``` + * + * Due to the confusing error-prone notation, avoid a string as the second + * argument. + * @since v0.1.21 + */ + function throws(block: () => unknown, message?: string | Error): void; + function throws(block: () => unknown, error: AssertPredicate, message?: string | Error): void; + /** + * Asserts that the function `fn` does not throw an error. + * + * Using `assert.doesNotThrow()` is actually not useful because there + * is no benefit in catching an error and then rethrowing it. Instead, consider + * adding a comment next to the specific code path that should not throw and keep + * error messages as expressive as possible. + * + * When `assert.doesNotThrow()` is called, it will immediately call the `fn` function. + * + * If an error is thrown and it is the same type as that specified by the `error` parameter, then an `AssertionError` is thrown. If the error is of a + * different type, or if the `error` parameter is undefined, the error is + * propagated back to the caller. + * + * If specified, `error` can be a [`Class`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes), + * [`RegExp`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions), or a validation + * function. See {@link throws} for more details. + * + * The following, for instance, will throw the `TypeError` because there is no + * matching error type in the assertion: + * + * ```js + * import assert from 'node:assert/strict'; + * + * assert.doesNotThrow( + * () => { + * throw new TypeError('Wrong value'); + * }, + * SyntaxError, + * ); + * ``` + * + * However, the following will result in an `AssertionError` with the message + * 'Got unwanted exception...': + * + * ```js + * import assert from 'node:assert/strict'; + * + * assert.doesNotThrow( + * () => { + * throw new TypeError('Wrong value'); + * }, + * TypeError, + * ); + * ``` + * + * If an `AssertionError` is thrown and a value is provided for the `message` parameter, the value of `message` will be appended to the `AssertionError` message: + * + * ```js + * import assert from 'node:assert/strict'; + * + * assert.doesNotThrow( + * () => { + * throw new TypeError('Wrong value'); + * }, + * /Wrong value/, + * 'Whoops', + * ); + * // Throws: AssertionError: Got unwanted exception: Whoops + * ``` + * @since v0.1.21 + */ + function doesNotThrow(block: () => unknown, message?: string | Error): void; + function doesNotThrow(block: () => unknown, error: AssertPredicate, message?: string | Error): void; + /** + * Throws `value` if `value` is not `undefined` or `null`. This is useful when + * testing the `error` argument in callbacks. The stack trace contains all frames + * from the error passed to `ifError()` including the potential new frames for `ifError()` itself. + * + * ```js + * import assert from 'node:assert/strict'; + * + * assert.ifError(null); + * // OK + * assert.ifError(0); + * // AssertionError [ERR_ASSERTION]: ifError got unwanted exception: 0 + * assert.ifError('error'); + * // AssertionError [ERR_ASSERTION]: ifError got unwanted exception: 'error' + * assert.ifError(new Error()); + * // AssertionError [ERR_ASSERTION]: ifError got unwanted exception: Error + * + * // Create some random error frames. + * let err; + * (function errorFrame() { + * err = new Error('test error'); + * })(); + * + * (function ifErrorFrame() { + * assert.ifError(err); + * })(); + * // AssertionError [ERR_ASSERTION]: ifError got unwanted exception: test error + * // at ifErrorFrame + * // at errorFrame + * ``` + * @since v0.1.97 + */ + function ifError(value: unknown): asserts value is null | undefined; + /** + * Awaits the `asyncFn` promise or, if `asyncFn` is a function, immediately + * calls the function and awaits the returned promise to complete. It will then + * check that the promise is rejected. + * + * If `asyncFn` is a function and it throws an error synchronously, `assert.rejects()` will return a rejected `Promise` with that error. If the + * function does not return a promise, `assert.rejects()` will return a rejected `Promise` with an [ERR_INVALID_RETURN_VALUE](https://nodejs.org/docs/latest-v25.x/api/errors.html#err_invalid_return_value) + * error. In both cases the error handler is skipped. + * + * Besides the async nature to await the completion behaves identically to {@link throws}. + * + * If specified, `error` can be a [`Class`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes), + * [`RegExp`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions), a validation function, + * an object where each property will be tested for, or an instance of error where + * each property will be tested for including the non-enumerable `message` and `name` properties. + * + * If specified, `message` will be the message provided by the `{@link AssertionError}` if the `asyncFn` fails to reject. + * + * ```js + * import assert from 'node:assert/strict'; + * + * await assert.rejects( + * async () => { + * throw new TypeError('Wrong value'); + * }, + * { + * name: 'TypeError', + * message: 'Wrong value', + * }, + * ); + * ``` + * + * ```js + * import assert from 'node:assert/strict'; + * + * await assert.rejects( + * async () => { + * throw new TypeError('Wrong value'); + * }, + * (err) => { + * assert.strictEqual(err.name, 'TypeError'); + * assert.strictEqual(err.message, 'Wrong value'); + * return true; + * }, + * ); + * ``` + * + * ```js + * import assert from 'node:assert/strict'; + * + * assert.rejects( + * Promise.reject(new Error('Wrong value')), + * Error, + * ).then(() => { + * // ... + * }); + * ``` + * + * `error` cannot be a string. If a string is provided as the second argument, then `error` is assumed to + * be omitted and the string will be used for `message` instead. This can lead to easy-to-miss mistakes. Please read the + * example in {@link throws} carefully if using a string as the second argument gets considered. + * @since v10.0.0 + */ + function rejects(block: (() => Promise<unknown>) | Promise<unknown>, message?: string | Error): Promise<void>; + function rejects( + block: (() => Promise<unknown>) | Promise<unknown>, + error: AssertPredicate, + message?: string | Error, + ): Promise<void>; + /** + * Awaits the `asyncFn` promise or, if `asyncFn` is a function, immediately + * calls the function and awaits the returned promise to complete. It will then + * check that the promise is not rejected. + * + * If `asyncFn` is a function and it throws an error synchronously, `assert.doesNotReject()` will return a rejected `Promise` with that error. If + * the function does not return a promise, `assert.doesNotReject()` will return a + * rejected `Promise` with an [ERR_INVALID_RETURN_VALUE](https://nodejs.org/docs/latest-v25.x/api/errors.html#err_invalid_return_value) error. In both cases + * the error handler is skipped. + * + * Using `assert.doesNotReject()` is actually not useful because there is little + * benefit in catching a rejection and then rejecting it again. Instead, consider + * adding a comment next to the specific code path that should not reject and keep + * error messages as expressive as possible. + * + * If specified, `error` can be a [`Class`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes), + * [`RegExp`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions), or a validation + * function. See {@link throws} for more details. + * + * Besides the async nature to await the completion behaves identically to {@link doesNotThrow}. + * + * ```js + * import assert from 'node:assert/strict'; + * + * await assert.doesNotReject( + * async () => { + * throw new TypeError('Wrong value'); + * }, + * SyntaxError, + * ); + * ``` + * + * ```js + * import assert from 'node:assert/strict'; + * + * assert.doesNotReject(Promise.reject(new TypeError('Wrong value'))) + * .then(() => { + * // ... + * }); + * ``` + * @since v10.0.0 + */ + function doesNotReject( + block: (() => Promise<unknown>) | Promise<unknown>, + message?: string | Error, + ): Promise<void>; + function doesNotReject( + block: (() => Promise<unknown>) | Promise<unknown>, + error: AssertPredicate, + message?: string | Error, + ): Promise<void>; + /** + * Expects the `string` input to match the regular expression. + * + * ```js + * import assert from 'node:assert/strict'; + * + * assert.match('I will fail', /pass/); + * // AssertionError [ERR_ASSERTION]: The input did not match the regular ... + * + * assert.match(123, /pass/); + * // AssertionError [ERR_ASSERTION]: The "string" argument must be of type string. + * + * assert.match('I will pass', /pass/); + * // OK + * ``` + * + * If the values do not match, or if the `string` argument is of another type than `string`, an `{@link AssertionError}` is thrown with a `message` property set equal + * to the value of the `message` parameter. If the `message` parameter is + * undefined, a default error message is assigned. If the `message` parameter is an + * instance of an [Error](https://nodejs.org/docs/latest-v25.x/api/errors.html#class-error) then it will be thrown instead of the `{@link AssertionError}`. + * @since v13.6.0, v12.16.0 + */ + function match(value: string, regExp: RegExp, message?: string | Error): void; + /** + * Expects the `string` input not to match the regular expression. + * + * ```js + * import assert from 'node:assert/strict'; + * + * assert.doesNotMatch('I will fail', /fail/); + * // AssertionError [ERR_ASSERTION]: The input was expected to not match the ... + * + * assert.doesNotMatch(123, /pass/); + * // AssertionError [ERR_ASSERTION]: The "string" argument must be of type string. + * + * assert.doesNotMatch('I will pass', /different/); + * // OK + * ``` + * + * If the values do match, or if the `string` argument is of another type than `string`, an `{@link AssertionError}` is thrown with a `message` property set equal + * to the value of the `message` parameter. If the `message` parameter is + * undefined, a default error message is assigned. If the `message` parameter is an + * instance of an [Error](https://nodejs.org/docs/latest-v25.x/api/errors.html#class-error) then it will be thrown instead of the `{@link AssertionError}`. + * @since v13.6.0, v12.16.0 + */ + function doesNotMatch(value: string, regExp: RegExp, message?: string | Error): void; + /** + * Tests for partial deep equality between the `actual` and `expected` parameters. + * "Deep" equality means that the enumerable "own" properties of child objects + * are recursively evaluated also by the following rules. "Partial" equality means + * that only properties that exist on the `expected` parameter are going to be + * compared. + * + * This method always passes the same test cases as `assert.deepStrictEqual()`, + * behaving as a super set of it. + * @since v22.13.0 + */ + function partialDeepStrictEqual(actual: unknown, expected: unknown, message?: string | Error): void; + } + namespace assert { + export { strict }; + } + export = assert; +} +declare module "assert" { + import assert = require("node:assert"); + export = assert; +} diff --git a/server/node_modules/@types/node/assert/strict.d.ts b/server/node_modules/@types/node/assert/strict.d.ts new file mode 100644 index 0000000..51bb352 --- /dev/null +++ b/server/node_modules/@types/node/assert/strict.d.ts @@ -0,0 +1,105 @@ +/** + * In strict assertion mode, non-strict methods behave like their corresponding + * strict methods. For example, `assert.deepEqual()` will behave like + * `assert.deepStrictEqual()`. + * + * In strict assertion mode, error messages for objects display a diff. In legacy + * assertion mode, error messages for objects display the objects, often truncated. + * + * To use strict assertion mode: + * + * ```js + * import { strict as assert } from 'node:assert'; + * ``` + * + * ```js + * import assert from 'node:assert/strict'; + * ``` + * + * Example error diff: + * + * ```js + * import { strict as assert } from 'node:assert'; + * + * assert.deepEqual([[[1, 2, 3]], 4, 5], [[[1, 2, '3']], 4, 5]); + * // AssertionError: Expected inputs to be strictly deep-equal: + * // + actual - expected ... Lines skipped + * // + * // [ + * // [ + * // ... + * // 2, + * // + 3 + * // - '3' + * // ], + * // ... + * // 5 + * // ] + * ``` + * + * To deactivate the colors, use the `NO_COLOR` or `NODE_DISABLE_COLORS` + * environment variables. This will also deactivate the colors in the REPL. For + * more on color support in terminal environments, read the tty + * [`getColorDepth()`](https://nodejs.org/docs/latest-v25.x/api/tty.html#writestreamgetcolordepthenv) documentation. + * @since v15.0.0 + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/assert/strict.js) + */ +declare module "node:assert/strict" { + import { + Assert, + AssertionError, + AssertionErrorOptions, + AssertOptions, + AssertPredicate, + AssertStrict, + deepStrictEqual, + doesNotMatch, + doesNotReject, + doesNotThrow, + fail, + ifError, + match, + notDeepStrictEqual, + notStrictEqual, + ok, + partialDeepStrictEqual, + rejects, + strictEqual, + throws, + } from "node:assert"; + function strict(value: unknown, message?: string | Error): asserts value; + namespace strict { + export { + Assert, + AssertionError, + AssertionErrorOptions, + AssertOptions, + AssertPredicate, + AssertStrict, + deepStrictEqual, + deepStrictEqual as deepEqual, + doesNotMatch, + doesNotReject, + doesNotThrow, + fail, + ifError, + match, + notDeepStrictEqual, + notDeepStrictEqual as notDeepEqual, + notStrictEqual, + notStrictEqual as notEqual, + ok, + partialDeepStrictEqual, + rejects, + strict, + strictEqual, + strictEqual as equal, + throws, + }; + } + export = strict; +} +declare module "assert/strict" { + import strict = require("node:assert/strict"); + export = strict; +} diff --git a/server/node_modules/@types/node/async_hooks.d.ts b/server/node_modules/@types/node/async_hooks.d.ts new file mode 100644 index 0000000..aa692c1 --- /dev/null +++ b/server/node_modules/@types/node/async_hooks.d.ts @@ -0,0 +1,623 @@ +/** + * We strongly discourage the use of the `async_hooks` API. + * Other APIs that can cover most of its use cases include: + * + * * [`AsyncLocalStorage`](https://nodejs.org/docs/latest-v25.x/api/async_context.html#class-asynclocalstorage) tracks async context + * * [`process.getActiveResourcesInfo()`](https://nodejs.org/docs/latest-v25.x/api/process.html#processgetactiveresourcesinfo) tracks active resources + * + * The `node:async_hooks` module provides an API to track asynchronous resources. + * It can be accessed using: + * + * ```js + * import async_hooks from 'node:async_hooks'; + * ``` + * @experimental + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/async_hooks.js) + */ +declare module "node:async_hooks" { + /** + * ```js + * import { executionAsyncId } from 'node:async_hooks'; + * import fs from 'node:fs'; + * + * console.log(executionAsyncId()); // 1 - bootstrap + * const path = '.'; + * fs.open(path, 'r', (err, fd) => { + * console.log(executionAsyncId()); // 6 - open() + * }); + * ``` + * + * The ID returned from `executionAsyncId()` is related to execution timing, not + * causality (which is covered by `triggerAsyncId()`): + * + * ```js + * const server = net.createServer((conn) => { + * // Returns the ID of the server, not of the new connection, because the + * // callback runs in the execution scope of the server's MakeCallback(). + * async_hooks.executionAsyncId(); + * + * }).listen(port, () => { + * // Returns the ID of a TickObject (process.nextTick()) because all + * // callbacks passed to .listen() are wrapped in a nextTick(). + * async_hooks.executionAsyncId(); + * }); + * ``` + * + * Promise contexts may not get precise `executionAsyncIds` by default. + * See the section on [promise execution tracking](https://nodejs.org/docs/latest-v25.x/api/async_hooks.html#promise-execution-tracking). + * @since v8.1.0 + * @return The `asyncId` of the current execution context. Useful to track when something calls. + */ + function executionAsyncId(): number; + /** + * Resource objects returned by `executionAsyncResource()` are most often internal + * Node.js handle objects with undocumented APIs. Using any functions or properties + * on the object is likely to crash your application and should be avoided. + * + * Using `executionAsyncResource()` in the top-level execution context will + * return an empty object as there is no handle or request object to use, + * but having an object representing the top-level can be helpful. + * + * ```js + * import { open } from 'node:fs'; + * import { executionAsyncId, executionAsyncResource } from 'node:async_hooks'; + * + * console.log(executionAsyncId(), executionAsyncResource()); // 1 {} + * open(new URL(import.meta.url), 'r', (err, fd) => { + * console.log(executionAsyncId(), executionAsyncResource()); // 7 FSReqWrap + * }); + * ``` + * + * This can be used to implement continuation local storage without the + * use of a tracking `Map` to store the metadata: + * + * ```js + * import { createServer } from 'node:http'; + * import { + * executionAsyncId, + * executionAsyncResource, + * createHook, + * } from 'node:async_hooks'; + * const sym = Symbol('state'); // Private symbol to avoid pollution + * + * createHook({ + * init(asyncId, type, triggerAsyncId, resource) { + * const cr = executionAsyncResource(); + * if (cr) { + * resource[sym] = cr[sym]; + * } + * }, + * }).enable(); + * + * const server = createServer((req, res) => { + * executionAsyncResource()[sym] = { state: req.url }; + * setTimeout(function() { + * res.end(JSON.stringify(executionAsyncResource()[sym])); + * }, 100); + * }).listen(3000); + * ``` + * @since v13.9.0, v12.17.0 + * @return The resource representing the current execution. Useful to store data within the resource. + */ + function executionAsyncResource(): object; + /** + * ```js + * const server = net.createServer((conn) => { + * // The resource that caused (or triggered) this callback to be called + * // was that of the new connection. Thus the return value of triggerAsyncId() + * // is the asyncId of "conn". + * async_hooks.triggerAsyncId(); + * + * }).listen(port, () => { + * // Even though all callbacks passed to .listen() are wrapped in a nextTick() + * // the callback itself exists because the call to the server's .listen() + * // was made. So the return value would be the ID of the server. + * async_hooks.triggerAsyncId(); + * }); + * ``` + * + * Promise contexts may not get valid `triggerAsyncId`s by default. See + * the section on [promise execution tracking](https://nodejs.org/docs/latest-v25.x/api/async_hooks.html#promise-execution-tracking). + * @return The ID of the resource responsible for calling the callback that is currently being executed. + */ + function triggerAsyncId(): number; + interface HookCallbacks { + /** + * Called when a class is constructed that has the possibility to emit an asynchronous event. + * @param asyncId A unique ID for the async resource + * @param type The type of the async resource + * @param triggerAsyncId The unique ID of the async resource in whose execution context this async resource was created + * @param resource Reference to the resource representing the async operation, needs to be released during destroy + */ + init?(asyncId: number, type: string, triggerAsyncId: number, resource: object): void; + /** + * When an asynchronous operation is initiated or completes a callback is called to notify the user. + * The before callback is called just before said callback is executed. + * @param asyncId the unique identifier assigned to the resource about to execute the callback. + */ + before?(asyncId: number): void; + /** + * Called immediately after the callback specified in `before` is completed. + * + * If an uncaught exception occurs during execution of the callback, then `after` will run after the `'uncaughtException'` event is emitted or a `domain`'s handler runs. + * @param asyncId the unique identifier assigned to the resource which has executed the callback. + */ + after?(asyncId: number): void; + /** + * Called when a promise has resolve() called. This may not be in the same execution id + * as the promise itself. + * @param asyncId the unique id for the promise that was resolve()d. + */ + promiseResolve?(asyncId: number): void; + /** + * Called after the resource corresponding to asyncId is destroyed + * @param asyncId a unique ID for the async resource + */ + destroy?(asyncId: number): void; + } + interface AsyncHook { + /** + * Enable the callbacks for a given AsyncHook instance. If no callbacks are provided enabling is a noop. + */ + enable(): this; + /** + * Disable the callbacks for a given AsyncHook instance from the global pool of AsyncHook callbacks to be executed. Once a hook has been disabled it will not be called again until enabled. + */ + disable(): this; + } + /** + * Registers functions to be called for different lifetime events of each async + * operation. + * + * The callbacks `init()`/`before()`/`after()`/`destroy()` are called for the + * respective asynchronous event during a resource's lifetime. + * + * All callbacks are optional. For example, if only resource cleanup needs to + * be tracked, then only the `destroy` callback needs to be passed. The + * specifics of all functions that can be passed to `callbacks` is in the `Hook Callbacks` section. + * + * ```js + * import { createHook } from 'node:async_hooks'; + * + * const asyncHook = createHook({ + * init(asyncId, type, triggerAsyncId, resource) { }, + * destroy(asyncId) { }, + * }); + * ``` + * + * The callbacks will be inherited via the prototype chain: + * + * ```js + * class MyAsyncCallbacks { + * init(asyncId, type, triggerAsyncId, resource) { } + * destroy(asyncId) {} + * } + * + * class MyAddedCallbacks extends MyAsyncCallbacks { + * before(asyncId) { } + * after(asyncId) { } + * } + * + * const asyncHook = async_hooks.createHook(new MyAddedCallbacks()); + * ``` + * + * Because promises are asynchronous resources whose lifecycle is tracked + * via the async hooks mechanism, the `init()`, `before()`, `after()`, and`destroy()` callbacks _must not_ be async functions that return promises. + * @since v8.1.0 + * @param callbacks The `Hook Callbacks` to register + * @return Instance used for disabling and enabling hooks + */ + function createHook(callbacks: HookCallbacks): AsyncHook; + interface AsyncResourceOptions { + /** + * The ID of the execution context that created this async event. + * @default executionAsyncId() + */ + triggerAsyncId?: number | undefined; + /** + * Disables automatic `emitDestroy` when the object is garbage collected. + * This usually does not need to be set (even if `emitDestroy` is called + * manually), unless the resource's `asyncId` is retrieved and the + * sensitive API's `emitDestroy` is called with it. + * @default false + */ + requireManualDestroy?: boolean | undefined; + } + /** + * The class `AsyncResource` is designed to be extended by the embedder's async + * resources. Using this, users can easily trigger the lifetime events of their + * own resources. + * + * The `init` hook will trigger when an `AsyncResource` is instantiated. + * + * The following is an overview of the `AsyncResource` API. + * + * ```js + * import { AsyncResource, executionAsyncId } from 'node:async_hooks'; + * + * // AsyncResource() is meant to be extended. Instantiating a + * // new AsyncResource() also triggers init. If triggerAsyncId is omitted then + * // async_hook.executionAsyncId() is used. + * const asyncResource = new AsyncResource( + * type, { triggerAsyncId: executionAsyncId(), requireManualDestroy: false }, + * ); + * + * // Run a function in the execution context of the resource. This will + * // * establish the context of the resource + * // * trigger the AsyncHooks before callbacks + * // * call the provided function `fn` with the supplied arguments + * // * trigger the AsyncHooks after callbacks + * // * restore the original execution context + * asyncResource.runInAsyncScope(fn, thisArg, ...args); + * + * // Call AsyncHooks destroy callbacks. + * asyncResource.emitDestroy(); + * + * // Return the unique ID assigned to the AsyncResource instance. + * asyncResource.asyncId(); + * + * // Return the trigger ID for the AsyncResource instance. + * asyncResource.triggerAsyncId(); + * ``` + */ + class AsyncResource { + /** + * AsyncResource() is meant to be extended. Instantiating a + * new AsyncResource() also triggers init. If triggerAsyncId is omitted then + * async_hook.executionAsyncId() is used. + * @param type The type of async event. + * @param triggerAsyncId The ID of the execution context that created + * this async event (default: `executionAsyncId()`), or an + * AsyncResourceOptions object (since v9.3.0) + */ + constructor(type: string, triggerAsyncId?: number | AsyncResourceOptions); + /** + * Binds the given function to the current execution context. + * @since v14.8.0, v12.19.0 + * @param fn The function to bind to the current execution context. + * @param type An optional name to associate with the underlying `AsyncResource`. + */ + static bind<Func extends (this: ThisArg, ...args: any[]) => any, ThisArg>( + fn: Func, + type?: string, + thisArg?: ThisArg, + ): Func; + /** + * Binds the given function to execute to this `AsyncResource`'s scope. + * @since v14.8.0, v12.19.0 + * @param fn The function to bind to the current `AsyncResource`. + */ + bind<Func extends (...args: any[]) => any>(fn: Func): Func; + /** + * Call the provided function with the provided arguments in the execution context + * of the async resource. This will establish the context, trigger the AsyncHooks + * before callbacks, call the function, trigger the AsyncHooks after callbacks, and + * then restore the original execution context. + * @since v9.6.0 + * @param fn The function to call in the execution context of this async resource. + * @param thisArg The receiver to be used for the function call. + * @param args Optional arguments to pass to the function. + */ + runInAsyncScope<This, Result>( + fn: (this: This, ...args: any[]) => Result, + thisArg?: This, + ...args: any[] + ): Result; + /** + * Call all `destroy` hooks. This should only ever be called once. An error will + * be thrown if it is called more than once. This **must** be manually called. If + * the resource is left to be collected by the GC then the `destroy` hooks will + * never be called. + * @return A reference to `asyncResource`. + */ + emitDestroy(): this; + /** + * @return The unique `asyncId` assigned to the resource. + */ + asyncId(): number; + /** + * @return The same `triggerAsyncId` that is passed to the `AsyncResource` constructor. + */ + triggerAsyncId(): number; + } + interface AsyncLocalStorageOptions { + /** + * The default value to be used when no store is provided. + */ + defaultValue?: any; + /** + * A name for the `AsyncLocalStorage` value. + */ + name?: string | undefined; + } + /** + * This class creates stores that stay coherent through asynchronous operations. + * + * While you can create your own implementation on top of the `node:async_hooks` module, `AsyncLocalStorage` should be preferred as it is a performant and memory + * safe implementation that involves significant optimizations that are non-obvious + * to implement. + * + * The following example uses `AsyncLocalStorage` to build a simple logger + * that assigns IDs to incoming HTTP requests and includes them in messages + * logged within each request. + * + * ```js + * import http from 'node:http'; + * import { AsyncLocalStorage } from 'node:async_hooks'; + * + * const asyncLocalStorage = new AsyncLocalStorage(); + * + * function logWithId(msg) { + * const id = asyncLocalStorage.getStore(); + * console.log(`${id !== undefined ? id : '-'}:`, msg); + * } + * + * let idSeq = 0; + * http.createServer((req, res) => { + * asyncLocalStorage.run(idSeq++, () => { + * logWithId('start'); + * // Imagine any chain of async operations here + * setImmediate(() => { + * logWithId('finish'); + * res.end(); + * }); + * }); + * }).listen(8080); + * + * http.get('http://localhost:8080'); + * http.get('http://localhost:8080'); + * // Prints: + * // 0: start + * // 0: finish + * // 1: start + * // 1: finish + * ``` + * + * Each instance of `AsyncLocalStorage` maintains an independent storage context. + * Multiple instances can safely exist simultaneously without risk of interfering + * with each other's data. + * @since v13.10.0, v12.17.0 + */ + class AsyncLocalStorage<T> { + /** + * Creates a new instance of `AsyncLocalStorage`. Store is only provided within a + * `run()` call or after an `enterWith()` call. + */ + constructor(options?: AsyncLocalStorageOptions); + /** + * Binds the given function to the current execution context. + * @since v19.8.0 + * @param fn The function to bind to the current execution context. + * @return A new function that calls `fn` within the captured execution context. + */ + static bind<Func extends (...args: any[]) => any>(fn: Func): Func; + /** + * Captures the current execution context and returns a function that accepts a + * function as an argument. Whenever the returned function is called, it + * calls the function passed to it within the captured context. + * + * ```js + * const asyncLocalStorage = new AsyncLocalStorage(); + * const runInAsyncScope = asyncLocalStorage.run(123, () => AsyncLocalStorage.snapshot()); + * const result = asyncLocalStorage.run(321, () => runInAsyncScope(() => asyncLocalStorage.getStore())); + * console.log(result); // returns 123 + * ``` + * + * AsyncLocalStorage.snapshot() can replace the use of AsyncResource for simple + * async context tracking purposes, for example: + * + * ```js + * class Foo { + * #runInAsyncScope = AsyncLocalStorage.snapshot(); + * + * get() { return this.#runInAsyncScope(() => asyncLocalStorage.getStore()); } + * } + * + * const foo = asyncLocalStorage.run(123, () => new Foo()); + * console.log(asyncLocalStorage.run(321, () => foo.get())); // returns 123 + * ``` + * @since v19.8.0 + * @return A new function with the signature `(fn: (...args) : R, ...args) : R`. + */ + static snapshot(): <R, TArgs extends any[]>(fn: (...args: TArgs) => R, ...args: TArgs) => R; + /** + * Disables the instance of `AsyncLocalStorage`. All subsequent calls + * to `asyncLocalStorage.getStore()` will return `undefined` until `asyncLocalStorage.run()` or `asyncLocalStorage.enterWith()` is called again. + * + * When calling `asyncLocalStorage.disable()`, all current contexts linked to the + * instance will be exited. + * + * Calling `asyncLocalStorage.disable()` is required before the `asyncLocalStorage` can be garbage collected. This does not apply to stores + * provided by the `asyncLocalStorage`, as those objects are garbage collected + * along with the corresponding async resources. + * + * Use this method when the `asyncLocalStorage` is not in use anymore + * in the current process. + * @since v13.10.0, v12.17.0 + * @experimental + */ + disable(): void; + /** + * Returns the current store. + * If called outside of an asynchronous context initialized by + * calling `asyncLocalStorage.run()` or `asyncLocalStorage.enterWith()`, it + * returns `undefined`. + * @since v13.10.0, v12.17.0 + */ + getStore(): T | undefined; + /** + * The name of the `AsyncLocalStorage` instance if provided. + * @since v24.0.0 + */ + readonly name: string; + /** + * Runs a function synchronously within a context and returns its + * return value. The store is not accessible outside of the callback function. + * The store is accessible to any asynchronous operations created within the + * callback. + * + * The optional `args` are passed to the callback function. + * + * If the callback function throws an error, the error is thrown by `run()` too. + * The stacktrace is not impacted by this call and the context is exited. + * + * Example: + * + * ```js + * const store = { id: 2 }; + * try { + * asyncLocalStorage.run(store, () => { + * asyncLocalStorage.getStore(); // Returns the store object + * setTimeout(() => { + * asyncLocalStorage.getStore(); // Returns the store object + * }, 200); + * throw new Error(); + * }); + * } catch (e) { + * asyncLocalStorage.getStore(); // Returns undefined + * // The error will be caught here + * } + * ``` + * @since v13.10.0, v12.17.0 + */ + run<R>(store: T, callback: () => R): R; + run<R, TArgs extends any[]>(store: T, callback: (...args: TArgs) => R, ...args: TArgs): R; + /** + * Runs a function synchronously outside of a context and returns its + * return value. The store is not accessible within the callback function or + * the asynchronous operations created within the callback. Any `getStore()` call done within the callback function will always return `undefined`. + * + * The optional `args` are passed to the callback function. + * + * If the callback function throws an error, the error is thrown by `exit()` too. + * The stacktrace is not impacted by this call and the context is re-entered. + * + * Example: + * + * ```js + * // Within a call to run + * try { + * asyncLocalStorage.getStore(); // Returns the store object or value + * asyncLocalStorage.exit(() => { + * asyncLocalStorage.getStore(); // Returns undefined + * throw new Error(); + * }); + * } catch (e) { + * asyncLocalStorage.getStore(); // Returns the same object or value + * // The error will be caught here + * } + * ``` + * @since v13.10.0, v12.17.0 + * @experimental + */ + exit<R, TArgs extends any[]>(callback: (...args: TArgs) => R, ...args: TArgs): R; + /** + * Transitions into the context for the remainder of the current + * synchronous execution and then persists the store through any following + * asynchronous calls. + * + * Example: + * + * ```js + * const store = { id: 1 }; + * // Replaces previous store with the given store object + * asyncLocalStorage.enterWith(store); + * asyncLocalStorage.getStore(); // Returns the store object + * someAsyncOperation(() => { + * asyncLocalStorage.getStore(); // Returns the same object + * }); + * ``` + * + * This transition will continue for the _entire_ synchronous execution. + * This means that if, for example, the context is entered within an event + * handler subsequent event handlers will also run within that context unless + * specifically bound to another context with an `AsyncResource`. That is why `run()` should be preferred over `enterWith()` unless there are strong reasons + * to use the latter method. + * + * ```js + * const store = { id: 1 }; + * + * emitter.on('my-event', () => { + * asyncLocalStorage.enterWith(store); + * }); + * emitter.on('my-event', () => { + * asyncLocalStorage.getStore(); // Returns the same object + * }); + * + * asyncLocalStorage.getStore(); // Returns undefined + * emitter.emit('my-event'); + * asyncLocalStorage.getStore(); // Returns the same object + * ``` + * @since v13.11.0, v12.17.0 + * @experimental + */ + enterWith(store: T): void; + } + /** + * @since v17.2.0, v16.14.0 + * @return A map of provider types to the corresponding numeric id. + * This map contains all the event types that might be emitted by the `async_hooks.init()` event. + */ + namespace asyncWrapProviders { + const NONE: number; + const DIRHANDLE: number; + const DNSCHANNEL: number; + const ELDHISTOGRAM: number; + const FILEHANDLE: number; + const FILEHANDLECLOSEREQ: number; + const FIXEDSIZEBLOBCOPY: number; + const FSEVENTWRAP: number; + const FSREQCALLBACK: number; + const FSREQPROMISE: number; + const GETADDRINFOREQWRAP: number; + const GETNAMEINFOREQWRAP: number; + const HEAPSNAPSHOT: number; + const HTTP2SESSION: number; + const HTTP2STREAM: number; + const HTTP2PING: number; + const HTTP2SETTINGS: number; + const HTTPINCOMINGMESSAGE: number; + const HTTPCLIENTREQUEST: number; + const JSSTREAM: number; + const JSUDPWRAP: number; + const MESSAGEPORT: number; + const PIPECONNECTWRAP: number; + const PIPESERVERWRAP: number; + const PIPEWRAP: number; + const PROCESSWRAP: number; + const PROMISE: number; + const QUERYWRAP: number; + const SHUTDOWNWRAP: number; + const SIGNALWRAP: number; + const STATWATCHER: number; + const STREAMPIPE: number; + const TCPCONNECTWRAP: number; + const TCPSERVERWRAP: number; + const TCPWRAP: number; + const TTYWRAP: number; + const UDPSENDWRAP: number; + const UDPWRAP: number; + const SIGINTWATCHDOG: number; + const WORKER: number; + const WORKERHEAPSNAPSHOT: number; + const WRITEWRAP: number; + const ZLIB: number; + const CHECKPRIMEREQUEST: number; + const PBKDF2REQUEST: number; + const KEYPAIRGENREQUEST: number; + const KEYGENREQUEST: number; + const KEYEXPORTREQUEST: number; + const CIPHERREQUEST: number; + const DERIVEBITSREQUEST: number; + const HASHREQUEST: number; + const RANDOMBYTESREQUEST: number; + const RANDOMPRIMEREQUEST: number; + const SCRYPTREQUEST: number; + const SIGNREQUEST: number; + const TLSWRAP: number; + const VERIFYREQUEST: number; + } +} +declare module "async_hooks" { + export * from "node:async_hooks"; +} diff --git a/server/node_modules/@types/node/buffer.buffer.d.ts b/server/node_modules/@types/node/buffer.buffer.d.ts new file mode 100644 index 0000000..a3c2304 --- /dev/null +++ b/server/node_modules/@types/node/buffer.buffer.d.ts @@ -0,0 +1,466 @@ +declare module "node:buffer" { + type ImplicitArrayBuffer<T extends WithImplicitCoercion<ArrayBufferLike>> = T extends + { valueOf(): infer V extends ArrayBufferLike } ? V : T; + global { + interface BufferConstructor { + // see buffer.d.ts for implementation shared with all TypeScript versions + + /** + * Allocates a new buffer containing the given {str}. + * + * @param str String to store in buffer. + * @param encoding encoding to use, optional. Default is 'utf8' + * @deprecated since v10.0.0 - Use `Buffer.from(string[, encoding])` instead. + */ + new(str: string, encoding?: BufferEncoding): Buffer<ArrayBuffer>; + /** + * Allocates a new buffer of {size} octets. + * + * @param size count of octets to allocate. + * @deprecated since v10.0.0 - Use `Buffer.alloc()` instead (also see `Buffer.allocUnsafe()`). + */ + new(size: number): Buffer<ArrayBuffer>; + /** + * Allocates a new buffer containing the given {array} of octets. + * + * @param array The octets to store. + * @deprecated since v10.0.0 - Use `Buffer.from(array)` instead. + */ + new(array: ArrayLike<number>): Buffer<ArrayBuffer>; + /** + * Produces a Buffer backed by the same allocated memory as + * the given {ArrayBuffer}/{SharedArrayBuffer}. + * + * @param arrayBuffer The ArrayBuffer with which to share memory. + * @deprecated since v10.0.0 - Use `Buffer.from(arrayBuffer[, byteOffset[, length]])` instead. + */ + new<TArrayBuffer extends ArrayBufferLike = ArrayBuffer>(arrayBuffer: TArrayBuffer): Buffer<TArrayBuffer>; + /** + * Allocates a new `Buffer` using an `array` of bytes in the range `0` – `255`. + * Array entries outside that range will be truncated to fit into it. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * // Creates a new Buffer containing the UTF-8 bytes of the string 'buffer'. + * const buf = Buffer.from([0x62, 0x75, 0x66, 0x66, 0x65, 0x72]); + * ``` + * + * If `array` is an `Array`-like object (that is, one with a `length` property of + * type `number`), it is treated as if it is an array, unless it is a `Buffer` or + * a `Uint8Array`. This means all other `TypedArray` variants get treated as an + * `Array`. To create a `Buffer` from the bytes backing a `TypedArray`, use + * `Buffer.copyBytesFrom()`. + * + * A `TypeError` will be thrown if `array` is not an `Array` or another type + * appropriate for `Buffer.from()` variants. + * + * `Buffer.from(array)` and `Buffer.from(string)` may also use the internal + * `Buffer` pool like `Buffer.allocUnsafe()` does. + * @since v5.10.0 + */ + from(array: WithImplicitCoercion<ArrayLike<number>>): Buffer<ArrayBuffer>; + /** + * This creates a view of the `ArrayBuffer` without copying the underlying + * memory. For example, when passed a reference to the `.buffer` property of a + * `TypedArray` instance, the newly created `Buffer` will share the same + * allocated memory as the `TypedArray`'s underlying `ArrayBuffer`. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const arr = new Uint16Array(2); + * + * arr[0] = 5000; + * arr[1] = 4000; + * + * // Shares memory with `arr`. + * const buf = Buffer.from(arr.buffer); + * + * console.log(buf); + * // Prints: <Buffer 88 13 a0 0f> + * + * // Changing the original Uint16Array changes the Buffer also. + * arr[1] = 6000; + * + * console.log(buf); + * // Prints: <Buffer 88 13 70 17> + * ``` + * + * The optional `byteOffset` and `length` arguments specify a memory range within + * the `arrayBuffer` that will be shared by the `Buffer`. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const ab = new ArrayBuffer(10); + * const buf = Buffer.from(ab, 0, 2); + * + * console.log(buf.length); + * // Prints: 2 + * ``` + * + * A `TypeError` will be thrown if `arrayBuffer` is not an `ArrayBuffer` or a + * `SharedArrayBuffer` or another type appropriate for `Buffer.from()` + * variants. + * + * It is important to remember that a backing `ArrayBuffer` can cover a range + * of memory that extends beyond the bounds of a `TypedArray` view. A new + * `Buffer` created using the `buffer` property of a `TypedArray` may extend + * beyond the range of the `TypedArray`: + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const arrA = Uint8Array.from([0x63, 0x64, 0x65, 0x66]); // 4 elements + * const arrB = new Uint8Array(arrA.buffer, 1, 2); // 2 elements + * console.log(arrA.buffer === arrB.buffer); // true + * + * const buf = Buffer.from(arrB.buffer); + * console.log(buf); + * // Prints: <Buffer 63 64 65 66> + * ``` + * @since v5.10.0 + * @param arrayBuffer An `ArrayBuffer`, `SharedArrayBuffer`, for example the + * `.buffer` property of a `TypedArray`. + * @param byteOffset Index of first byte to expose. **Default:** `0`. + * @param length Number of bytes to expose. **Default:** + * `arrayBuffer.byteLength - byteOffset`. + */ + from<TArrayBuffer extends WithImplicitCoercion<ArrayBufferLike>>( + arrayBuffer: TArrayBuffer, + byteOffset?: number, + length?: number, + ): Buffer<ImplicitArrayBuffer<TArrayBuffer>>; + /** + * Creates a new `Buffer` containing `string`. The `encoding` parameter identifies + * the character encoding to be used when converting `string` into bytes. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf1 = Buffer.from('this is a tést'); + * const buf2 = Buffer.from('7468697320697320612074c3a97374', 'hex'); + * + * console.log(buf1.toString()); + * // Prints: this is a tést + * console.log(buf2.toString()); + * // Prints: this is a tést + * console.log(buf1.toString('latin1')); + * // Prints: this is a tést + * ``` + * + * A `TypeError` will be thrown if `string` is not a string or another type + * appropriate for `Buffer.from()` variants. + * + * `Buffer.from(string)` may also use the internal `Buffer` pool like + * `Buffer.allocUnsafe()` does. + * @since v5.10.0 + * @param string A string to encode. + * @param encoding The encoding of `string`. **Default:** `'utf8'`. + */ + from(string: WithImplicitCoercion<string>, encoding?: BufferEncoding): Buffer<ArrayBuffer>; + from(arrayOrString: WithImplicitCoercion<ArrayLike<number> | string>): Buffer<ArrayBuffer>; + /** + * Creates a new Buffer using the passed {data} + * @param values to create a new Buffer + */ + of(...items: number[]): Buffer<ArrayBuffer>; + /** + * Returns a new `Buffer` which is the result of concatenating all the `Buffer` instances in the `list` together. + * + * If the list has no items, or if the `totalLength` is 0, then a new zero-length `Buffer` is returned. + * + * If `totalLength` is not provided, it is calculated from the `Buffer` instances + * in `list` by adding their lengths. + * + * If `totalLength` is provided, it is coerced to an unsigned integer. If the + * combined length of the `Buffer`s in `list` exceeds `totalLength`, the result is + * truncated to `totalLength`. If the combined length of the `Buffer`s in `list` is + * less than `totalLength`, the remaining space is filled with zeros. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * // Create a single `Buffer` from a list of three `Buffer` instances. + * + * const buf1 = Buffer.alloc(10); + * const buf2 = Buffer.alloc(14); + * const buf3 = Buffer.alloc(18); + * const totalLength = buf1.length + buf2.length + buf3.length; + * + * console.log(totalLength); + * // Prints: 42 + * + * const bufA = Buffer.concat([buf1, buf2, buf3], totalLength); + * + * console.log(bufA); + * // Prints: <Buffer 00 00 00 00 ...> + * console.log(bufA.length); + * // Prints: 42 + * ``` + * + * `Buffer.concat()` may also use the internal `Buffer` pool like `Buffer.allocUnsafe()` does. + * @since v0.7.11 + * @param list List of `Buffer` or {@link Uint8Array} instances to concatenate. + * @param totalLength Total length of the `Buffer` instances in `list` when concatenated. + */ + concat(list: readonly Uint8Array[], totalLength?: number): Buffer<ArrayBuffer>; + /** + * Copies the underlying memory of `view` into a new `Buffer`. + * + * ```js + * const u16 = new Uint16Array([0, 0xffff]); + * const buf = Buffer.copyBytesFrom(u16, 1, 1); + * u16[1] = 0; + * console.log(buf.length); // 2 + * console.log(buf[0]); // 255 + * console.log(buf[1]); // 255 + * ``` + * @since v19.8.0 + * @param view The {TypedArray} to copy. + * @param [offset=0] The starting offset within `view`. + * @param [length=view.length - offset] The number of elements from `view` to copy. + */ + copyBytesFrom(view: NodeJS.TypedArray, offset?: number, length?: number): Buffer<ArrayBuffer>; + /** + * Allocates a new `Buffer` of `size` bytes. If `fill` is `undefined`, the`Buffer` will be zero-filled. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.alloc(5); + * + * console.log(buf); + * // Prints: <Buffer 00 00 00 00 00> + * ``` + * + * If `size` is larger than {@link constants.MAX_LENGTH} or smaller than 0, `ERR_OUT_OF_RANGE` is thrown. + * + * If `fill` is specified, the allocated `Buffer` will be initialized by calling `buf.fill(fill)`. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.alloc(5, 'a'); + * + * console.log(buf); + * // Prints: <Buffer 61 61 61 61 61> + * ``` + * + * If both `fill` and `encoding` are specified, the allocated `Buffer` will be + * initialized by calling `buf.fill(fill, encoding)`. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.alloc(11, 'aGVsbG8gd29ybGQ=', 'base64'); + * + * console.log(buf); + * // Prints: <Buffer 68 65 6c 6c 6f 20 77 6f 72 6c 64> + * ``` + * + * Calling `Buffer.alloc()` can be measurably slower than the alternative `Buffer.allocUnsafe()` but ensures that the newly created `Buffer` instance + * contents will never contain sensitive data from previous allocations, including + * data that might not have been allocated for `Buffer`s. + * + * A `TypeError` will be thrown if `size` is not a number. + * @since v5.10.0 + * @param size The desired length of the new `Buffer`. + * @param [fill=0] A value to pre-fill the new `Buffer` with. + * @param [encoding='utf8'] If `fill` is a string, this is its encoding. + */ + alloc(size: number, fill?: string | Uint8Array | number, encoding?: BufferEncoding): Buffer<ArrayBuffer>; + /** + * Allocates a new `Buffer` of `size` bytes. If `size` is larger than {@link constants.MAX_LENGTH} or smaller than 0, `ERR_OUT_OF_RANGE` is thrown. + * + * The underlying memory for `Buffer` instances created in this way is _not_ + * _initialized_. The contents of the newly created `Buffer` are unknown and _may contain sensitive data_. Use `Buffer.alloc()` instead to initialize`Buffer` instances with zeroes. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.allocUnsafe(10); + * + * console.log(buf); + * // Prints (contents may vary): <Buffer a0 8b 28 3f 01 00 00 00 50 32> + * + * buf.fill(0); + * + * console.log(buf); + * // Prints: <Buffer 00 00 00 00 00 00 00 00 00 00> + * ``` + * + * A `TypeError` will be thrown if `size` is not a number. + * + * The `Buffer` module pre-allocates an internal `Buffer` instance of + * size `Buffer.poolSize` that is used as a pool for the fast allocation of new `Buffer` instances created using `Buffer.allocUnsafe()`, `Buffer.from(array)`, + * and `Buffer.concat()` only when `size` is less than `Buffer.poolSize >>> 1` (floor of `Buffer.poolSize` divided by two). + * + * Use of this pre-allocated internal memory pool is a key difference between + * calling `Buffer.alloc(size, fill)` vs. `Buffer.allocUnsafe(size).fill(fill)`. + * Specifically, `Buffer.alloc(size, fill)` will _never_ use the internal `Buffer`pool, while `Buffer.allocUnsafe(size).fill(fill)`_will_ use the internal`Buffer` pool if `size` is less + * than or equal to half `Buffer.poolSize`. The + * difference is subtle but can be important when an application requires the + * additional performance that `Buffer.allocUnsafe()` provides. + * @since v5.10.0 + * @param size The desired length of the new `Buffer`. + */ + allocUnsafe(size: number): Buffer<ArrayBuffer>; + /** + * Allocates a new `Buffer` of `size` bytes. If `size` is larger than {@link constants.MAX_LENGTH} or smaller than 0, `ERR_OUT_OF_RANGE` is thrown. A zero-length `Buffer` is created if + * `size` is 0. + * + * The underlying memory for `Buffer` instances created in this way is _not_ + * _initialized_. The contents of the newly created `Buffer` are unknown and _may contain sensitive data_. Use `buf.fill(0)` to initialize + * such `Buffer` instances with zeroes. + * + * When using `Buffer.allocUnsafe()` to allocate new `Buffer` instances, + * allocations under 4 KiB are sliced from a single pre-allocated `Buffer`. This + * allows applications to avoid the garbage collection overhead of creating many + * individually allocated `Buffer` instances. This approach improves both + * performance and memory usage by eliminating the need to track and clean up as + * many individual `ArrayBuffer` objects. + * + * However, in the case where a developer may need to retain a small chunk of + * memory from a pool for an indeterminate amount of time, it may be appropriate + * to create an un-pooled `Buffer` instance using `Buffer.allocUnsafeSlow()` and + * then copying out the relevant bits. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * // Need to keep around a few small chunks of memory. + * const store = []; + * + * socket.on('readable', () => { + * let data; + * while (null !== (data = readable.read())) { + * // Allocate for retained data. + * const sb = Buffer.allocUnsafeSlow(10); + * + * // Copy the data into the new allocation. + * data.copy(sb, 0, 0, 10); + * + * store.push(sb); + * } + * }); + * ``` + * + * A `TypeError` will be thrown if `size` is not a number. + * @since v5.12.0 + * @param size The desired length of the new `Buffer`. + */ + allocUnsafeSlow(size: number): Buffer<ArrayBuffer>; + } + interface Buffer<TArrayBuffer extends ArrayBufferLike = ArrayBufferLike> extends Uint8Array<TArrayBuffer> { + // see buffer.d.ts for implementation shared with all TypeScript versions + + /** + * Returns a new `Buffer` that references the same memory as the original, but + * offset and cropped by the `start` and `end` indices. + * + * This method is not compatible with the `Uint8Array.prototype.slice()`, + * which is a superclass of `Buffer`. To copy the slice, use`Uint8Array.prototype.slice()`. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.from('buffer'); + * + * const copiedBuf = Uint8Array.prototype.slice.call(buf); + * copiedBuf[0]++; + * console.log(copiedBuf.toString()); + * // Prints: cuffer + * + * console.log(buf.toString()); + * // Prints: buffer + * + * // With buf.slice(), the original buffer is modified. + * const notReallyCopiedBuf = buf.slice(); + * notReallyCopiedBuf[0]++; + * console.log(notReallyCopiedBuf.toString()); + * // Prints: cuffer + * console.log(buf.toString()); + * // Also prints: cuffer (!) + * ``` + * @since v0.3.0 + * @deprecated Use `subarray` instead. + * @param [start=0] Where the new `Buffer` will start. + * @param [end=buf.length] Where the new `Buffer` will end (not inclusive). + */ + slice(start?: number, end?: number): Buffer<ArrayBuffer>; + /** + * Returns a new `Buffer` that references the same memory as the original, but + * offset and cropped by the `start` and `end` indices. + * + * Specifying `end` greater than `buf.length` will return the same result as + * that of `end` equal to `buf.length`. + * + * This method is inherited from [`TypedArray.prototype.subarray()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/subarray). + * + * Modifying the new `Buffer` slice will modify the memory in the original `Buffer`because the allocated memory of the two objects overlap. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * // Create a `Buffer` with the ASCII alphabet, take a slice, and modify one byte + * // from the original `Buffer`. + * + * const buf1 = Buffer.allocUnsafe(26); + * + * for (let i = 0; i < 26; i++) { + * // 97 is the decimal ASCII value for 'a'. + * buf1[i] = i + 97; + * } + * + * const buf2 = buf1.subarray(0, 3); + * + * console.log(buf2.toString('ascii', 0, buf2.length)); + * // Prints: abc + * + * buf1[0] = 33; + * + * console.log(buf2.toString('ascii', 0, buf2.length)); + * // Prints: !bc + * ``` + * + * Specifying negative indexes causes the slice to be generated relative to the + * end of `buf` rather than the beginning. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.from('buffer'); + * + * console.log(buf.subarray(-6, -1).toString()); + * // Prints: buffe + * // (Equivalent to buf.subarray(0, 5).) + * + * console.log(buf.subarray(-6, -2).toString()); + * // Prints: buff + * // (Equivalent to buf.subarray(0, 4).) + * + * console.log(buf.subarray(-5, -2).toString()); + * // Prints: uff + * // (Equivalent to buf.subarray(1, 4).) + * ``` + * @since v3.0.0 + * @param [start=0] Where the new `Buffer` will start. + * @param [end=buf.length] Where the new `Buffer` will end (not inclusive). + */ + subarray(start?: number, end?: number): Buffer<TArrayBuffer>; + } + // TODO: remove globals in future version + /** + * @deprecated This is intended for internal use, and will be removed once `@types/node` no longer supports + * TypeScript versions earlier than 5.7. + */ + type NonSharedBuffer = Buffer<ArrayBuffer>; + /** + * @deprecated This is intended for internal use, and will be removed once `@types/node` no longer supports + * TypeScript versions earlier than 5.7. + */ + type AllowSharedBuffer = Buffer<ArrayBufferLike>; + } +} diff --git a/server/node_modules/@types/node/buffer.d.ts b/server/node_modules/@types/node/buffer.d.ts new file mode 100644 index 0000000..bb0f004 --- /dev/null +++ b/server/node_modules/@types/node/buffer.d.ts @@ -0,0 +1,1810 @@ +/** + * `Buffer` objects are used to represent a fixed-length sequence of bytes. Many + * Node.js APIs support `Buffer`s. + * + * The `Buffer` class is a subclass of JavaScript's [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) class and + * extends it with methods that cover additional use cases. Node.js APIs accept + * plain [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) s wherever `Buffer`s are supported as well. + * + * While the `Buffer` class is available within the global scope, it is still + * recommended to explicitly reference it via an import or require statement. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * // Creates a zero-filled Buffer of length 10. + * const buf1 = Buffer.alloc(10); + * + * // Creates a Buffer of length 10, + * // filled with bytes which all have the value `1`. + * const buf2 = Buffer.alloc(10, 1); + * + * // Creates an uninitialized buffer of length 10. + * // This is faster than calling Buffer.alloc() but the returned + * // Buffer instance might contain old data that needs to be + * // overwritten using fill(), write(), or other functions that fill the Buffer's + * // contents. + * const buf3 = Buffer.allocUnsafe(10); + * + * // Creates a Buffer containing the bytes [1, 2, 3]. + * const buf4 = Buffer.from([1, 2, 3]); + * + * // Creates a Buffer containing the bytes [1, 1, 1, 1] – the entries + * // are all truncated using `(value & 255)` to fit into the range 0–255. + * const buf5 = Buffer.from([257, 257.5, -255, '1']); + * + * // Creates a Buffer containing the UTF-8-encoded bytes for the string 'tést': + * // [0x74, 0xc3, 0xa9, 0x73, 0x74] (in hexadecimal notation) + * // [116, 195, 169, 115, 116] (in decimal notation) + * const buf6 = Buffer.from('tést'); + * + * // Creates a Buffer containing the Latin-1 bytes [0x74, 0xe9, 0x73, 0x74]. + * const buf7 = Buffer.from('tést', 'latin1'); + * ``` + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/buffer.js) + */ +declare module "node:buffer" { + import { ReadableStream } from "node:stream/web"; + /** + * This function returns `true` if `input` contains only valid UTF-8-encoded data, + * including the case in which `input` is empty. + * + * Throws if the `input` is a detached array buffer. + * @since v19.4.0, v18.14.0 + * @param input The input to validate. + */ + export function isUtf8(input: ArrayBuffer | NodeJS.TypedArray): boolean; + /** + * This function returns `true` if `input` contains only valid ASCII-encoded data, + * including the case in which `input` is empty. + * + * Throws if the `input` is a detached array buffer. + * @since v19.6.0, v18.15.0 + * @param input The input to validate. + */ + export function isAscii(input: ArrayBuffer | NodeJS.TypedArray): boolean; + export let INSPECT_MAX_BYTES: number; + export const kMaxLength: number; + export const kStringMaxLength: number; + export const constants: { + MAX_LENGTH: number; + MAX_STRING_LENGTH: number; + }; + export type TranscodeEncoding = + | "ascii" + | "utf8" + | "utf-8" + | "utf16le" + | "utf-16le" + | "ucs2" + | "ucs-2" + | "latin1" + | "binary"; + /** + * Re-encodes the given `Buffer` or `Uint8Array` instance from one character + * encoding to another. Returns a new `Buffer` instance. + * + * Throws if the `fromEnc` or `toEnc` specify invalid character encodings or if + * conversion from `fromEnc` to `toEnc` is not permitted. + * + * Encodings supported by `buffer.transcode()` are: `'ascii'`, `'utf8'`, `'utf16le'`, `'ucs2'`, `'latin1'`, and `'binary'`. + * + * The transcoding process will use substitution characters if a given byte + * sequence cannot be adequately represented in the target encoding. For instance: + * + * ```js + * import { Buffer, transcode } from 'node:buffer'; + * + * const newBuf = transcode(Buffer.from('€'), 'utf8', 'ascii'); + * console.log(newBuf.toString('ascii')); + * // Prints: '?' + * ``` + * + * Because the Euro (`€`) sign is not representable in US-ASCII, it is replaced + * with `?` in the transcoded `Buffer`. + * @since v7.1.0 + * @param source A `Buffer` or `Uint8Array` instance. + * @param fromEnc The current encoding. + * @param toEnc To target encoding. + */ + export function transcode( + source: Uint8Array, + fromEnc: TranscodeEncoding, + toEnc: TranscodeEncoding, + ): NonSharedBuffer; + /** + * Resolves a `'blob:nodedata:...'` an associated `Blob` object registered using + * a prior call to `URL.createObjectURL()`. + * @since v16.7.0 + * @param id A `'blob:nodedata:...` URL string returned by a prior call to `URL.createObjectURL()`. + */ + export function resolveObjectURL(id: string): Blob | undefined; + export { type AllowSharedBuffer, Buffer, type NonSharedBuffer }; + /** @deprecated This alias will be removed in a future version. Use the canonical `BlobPropertyBag` instead. */ + // TODO: remove in future major + export interface BlobOptions extends BlobPropertyBag {} + /** @deprecated This alias will be removed in a future version. Use the canonical `FilePropertyBag` instead. */ + export interface FileOptions extends FilePropertyBag {} + export type WithImplicitCoercion<T> = + | T + | { valueOf(): T } + | (T extends string ? { [Symbol.toPrimitive](hint: "string"): T } : never); + global { + namespace NodeJS { + export { BufferEncoding }; + } + // Buffer class + type BufferEncoding = + | "ascii" + | "utf8" + | "utf-8" + | "utf16le" + | "utf-16le" + | "ucs2" + | "ucs-2" + | "base64" + | "base64url" + | "latin1" + | "binary" + | "hex"; + /** + * Raw data is stored in instances of the Buffer class. + * A Buffer is similar to an array of integers but corresponds to a raw memory allocation outside the V8 heap. A Buffer cannot be resized. + * Valid string encodings: 'ascii'|'utf8'|'utf16le'|'ucs2'(alias of 'utf16le')|'base64'|'base64url'|'binary'(deprecated)|'hex' + */ + interface BufferConstructor { + // see buffer.buffer.d.ts for implementation specific to TypeScript 5.7 and later + // see ts5.6/buffer.buffer.d.ts for implementation specific to TypeScript 5.6 and earlier + + /** + * Returns `true` if `obj` is a `Buffer`, `false` otherwise. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * Buffer.isBuffer(Buffer.alloc(10)); // true + * Buffer.isBuffer(Buffer.from('foo')); // true + * Buffer.isBuffer('a string'); // false + * Buffer.isBuffer([]); // false + * Buffer.isBuffer(new Uint8Array(1024)); // false + * ``` + * @since v0.1.101 + */ + isBuffer(obj: any): obj is Buffer; + /** + * Returns `true` if `encoding` is the name of a supported character encoding, + * or `false` otherwise. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * console.log(Buffer.isEncoding('utf8')); + * // Prints: true + * + * console.log(Buffer.isEncoding('hex')); + * // Prints: true + * + * console.log(Buffer.isEncoding('utf/8')); + * // Prints: false + * + * console.log(Buffer.isEncoding('')); + * // Prints: false + * ``` + * @since v0.9.1 + * @param encoding A character encoding name to check. + */ + isEncoding(encoding: string): encoding is BufferEncoding; + /** + * Returns the byte length of a string when encoded using `encoding`. + * This is not the same as [`String.prototype.length`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/length), which does not account + * for the encoding that is used to convert the string into bytes. + * + * For `'base64'`, `'base64url'`, and `'hex'`, this function assumes valid input. + * For strings that contain non-base64/hex-encoded data (e.g. whitespace), the + * return value might be greater than the length of a `Buffer` created from the + * string. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const str = '\u00bd + \u00bc = \u00be'; + * + * console.log(`${str}: ${str.length} characters, ` + + * `${Buffer.byteLength(str, 'utf8')} bytes`); + * // Prints: ½ + ¼ = ¾: 9 characters, 12 bytes + * ``` + * + * When `string` is a + * `Buffer`/[`DataView`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView)/[`TypedArray`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/- + * Reference/Global_Objects/TypedArray)/[`ArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer)/[`SharedArrayBuffer`](https://develop- + * er.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer), the byte length as reported by `.byteLength`is returned. + * @since v0.1.90 + * @param string A value to calculate the length of. + * @param [encoding='utf8'] If `string` is a string, this is its encoding. + * @return The number of bytes contained within `string`. + */ + byteLength( + string: string | NodeJS.ArrayBufferView | ArrayBufferLike, + encoding?: BufferEncoding, + ): number; + /** + * Compares `buf1` to `buf2`, typically for the purpose of sorting arrays of `Buffer` instances. This is equivalent to calling `buf1.compare(buf2)`. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf1 = Buffer.from('1234'); + * const buf2 = Buffer.from('0123'); + * const arr = [buf1, buf2]; + * + * console.log(arr.sort(Buffer.compare)); + * // Prints: [ <Buffer 30 31 32 33>, <Buffer 31 32 33 34> ] + * // (This result is equal to: [buf2, buf1].) + * ``` + * @since v0.11.13 + * @return Either `-1`, `0`, or `1`, depending on the result of the comparison. See `compare` for details. + */ + compare(buf1: Uint8Array, buf2: Uint8Array): -1 | 0 | 1; + /** + * This is the size (in bytes) of pre-allocated internal `Buffer` instances used + * for pooling. This value may be modified. + * @since v0.11.3 + */ + poolSize: number; + } + interface Buffer { + // see buffer.buffer.d.ts for implementation specific to TypeScript 5.7 and later + // see ts5.6/buffer.buffer.d.ts for implementation specific to TypeScript 5.6 and earlier + + /** + * Writes `string` to `buf` at `offset` according to the character encoding in`encoding`. The `length` parameter is the number of bytes to write. If `buf` did + * not contain enough space to fit the entire string, only part of `string` will be + * written. However, partially encoded characters will not be written. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.alloc(256); + * + * const len = buf.write('\u00bd + \u00bc = \u00be', 0); + * + * console.log(`${len} bytes: ${buf.toString('utf8', 0, len)}`); + * // Prints: 12 bytes: ½ + ¼ = ¾ + * + * const buffer = Buffer.alloc(10); + * + * const length = buffer.write('abcd', 8); + * + * console.log(`${length} bytes: ${buffer.toString('utf8', 8, 10)}`); + * // Prints: 2 bytes : ab + * ``` + * @since v0.1.90 + * @param string String to write to `buf`. + * @param [offset=0] Number of bytes to skip before starting to write `string`. + * @param [length=buf.length - offset] Maximum number of bytes to write (written bytes will not exceed `buf.length - offset`). + * @param [encoding='utf8'] The character encoding of `string`. + * @return Number of bytes written. + */ + write(string: string, encoding?: BufferEncoding): number; + write(string: string, offset: number, encoding?: BufferEncoding): number; + write(string: string, offset: number, length: number, encoding?: BufferEncoding): number; + /** + * Decodes `buf` to a string according to the specified character encoding in`encoding`. `start` and `end` may be passed to decode only a subset of `buf`. + * + * If `encoding` is `'utf8'` and a byte sequence in the input is not valid UTF-8, + * then each invalid byte is replaced with the replacement character `U+FFFD`. + * + * The maximum length of a string instance (in UTF-16 code units) is available + * as {@link constants.MAX_STRING_LENGTH}. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf1 = Buffer.allocUnsafe(26); + * + * for (let i = 0; i < 26; i++) { + * // 97 is the decimal ASCII value for 'a'. + * buf1[i] = i + 97; + * } + * + * console.log(buf1.toString('utf8')); + * // Prints: abcdefghijklmnopqrstuvwxyz + * console.log(buf1.toString('utf8', 0, 5)); + * // Prints: abcde + * + * const buf2 = Buffer.from('tést'); + * + * console.log(buf2.toString('hex')); + * // Prints: 74c3a97374 + * console.log(buf2.toString('utf8', 0, 3)); + * // Prints: té + * console.log(buf2.toString(undefined, 0, 3)); + * // Prints: té + * ``` + * @since v0.1.90 + * @param [encoding='utf8'] The character encoding to use. + * @param [start=0] The byte offset to start decoding at. + * @param [end=buf.length] The byte offset to stop decoding at (not inclusive). + */ + toString(encoding?: BufferEncoding, start?: number, end?: number): string; + /** + * Returns a JSON representation of `buf`. [`JSON.stringify()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) implicitly calls + * this function when stringifying a `Buffer` instance. + * + * `Buffer.from()` accepts objects in the format returned from this method. + * In particular, `Buffer.from(buf.toJSON())` works like `Buffer.from(buf)`. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5]); + * const json = JSON.stringify(buf); + * + * console.log(json); + * // Prints: {"type":"Buffer","data":[1,2,3,4,5]} + * + * const copy = JSON.parse(json, (key, value) => { + * return value && value.type === 'Buffer' ? + * Buffer.from(value) : + * value; + * }); + * + * console.log(copy); + * // Prints: <Buffer 01 02 03 04 05> + * ``` + * @since v0.9.2 + */ + toJSON(): { + type: "Buffer"; + data: number[]; + }; + /** + * Returns `true` if both `buf` and `otherBuffer` have exactly the same bytes,`false` otherwise. Equivalent to `buf.compare(otherBuffer) === 0`. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf1 = Buffer.from('ABC'); + * const buf2 = Buffer.from('414243', 'hex'); + * const buf3 = Buffer.from('ABCD'); + * + * console.log(buf1.equals(buf2)); + * // Prints: true + * console.log(buf1.equals(buf3)); + * // Prints: false + * ``` + * @since v0.11.13 + * @param otherBuffer A `Buffer` or {@link Uint8Array} with which to compare `buf`. + */ + equals(otherBuffer: Uint8Array): boolean; + /** + * Compares `buf` with `target` and returns a number indicating whether `buf`comes before, after, or is the same as `target` in sort order. + * Comparison is based on the actual sequence of bytes in each `Buffer`. + * + * * `0` is returned if `target` is the same as `buf` + * * `1` is returned if `target` should come _before_`buf` when sorted. + * * `-1` is returned if `target` should come _after_`buf` when sorted. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf1 = Buffer.from('ABC'); + * const buf2 = Buffer.from('BCD'); + * const buf3 = Buffer.from('ABCD'); + * + * console.log(buf1.compare(buf1)); + * // Prints: 0 + * console.log(buf1.compare(buf2)); + * // Prints: -1 + * console.log(buf1.compare(buf3)); + * // Prints: -1 + * console.log(buf2.compare(buf1)); + * // Prints: 1 + * console.log(buf2.compare(buf3)); + * // Prints: 1 + * console.log([buf1, buf2, buf3].sort(Buffer.compare)); + * // Prints: [ <Buffer 41 42 43>, <Buffer 41 42 43 44>, <Buffer 42 43 44> ] + * // (This result is equal to: [buf1, buf3, buf2].) + * ``` + * + * The optional `targetStart`, `targetEnd`, `sourceStart`, and `sourceEnd` arguments can be used to limit the comparison to specific ranges within `target` and `buf` respectively. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf1 = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8, 9]); + * const buf2 = Buffer.from([5, 6, 7, 8, 9, 1, 2, 3, 4]); + * + * console.log(buf1.compare(buf2, 5, 9, 0, 4)); + * // Prints: 0 + * console.log(buf1.compare(buf2, 0, 6, 4)); + * // Prints: -1 + * console.log(buf1.compare(buf2, 5, 6, 5)); + * // Prints: 1 + * ``` + * + * `ERR_OUT_OF_RANGE` is thrown if `targetStart < 0`, `sourceStart < 0`, `targetEnd > target.byteLength`, or `sourceEnd > source.byteLength`. + * @since v0.11.13 + * @param target A `Buffer` or {@link Uint8Array} with which to compare `buf`. + * @param [targetStart=0] The offset within `target` at which to begin comparison. + * @param [targetEnd=target.length] The offset within `target` at which to end comparison (not inclusive). + * @param [sourceStart=0] The offset within `buf` at which to begin comparison. + * @param [sourceEnd=buf.length] The offset within `buf` at which to end comparison (not inclusive). + */ + compare( + target: Uint8Array, + targetStart?: number, + targetEnd?: number, + sourceStart?: number, + sourceEnd?: number, + ): -1 | 0 | 1; + /** + * Copies data from a region of `buf` to a region in `target`, even if the `target`memory region overlaps with `buf`. + * + * [`TypedArray.prototype.set()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set) performs the same operation, and is available + * for all TypedArrays, including Node.js `Buffer`s, although it takes + * different function arguments. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * // Create two `Buffer` instances. + * const buf1 = Buffer.allocUnsafe(26); + * const buf2 = Buffer.allocUnsafe(26).fill('!'); + * + * for (let i = 0; i < 26; i++) { + * // 97 is the decimal ASCII value for 'a'. + * buf1[i] = i + 97; + * } + * + * // Copy `buf1` bytes 16 through 19 into `buf2` starting at byte 8 of `buf2`. + * buf1.copy(buf2, 8, 16, 20); + * // This is equivalent to: + * // buf2.set(buf1.subarray(16, 20), 8); + * + * console.log(buf2.toString('ascii', 0, 25)); + * // Prints: !!!!!!!!qrst!!!!!!!!!!!!! + * ``` + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * // Create a `Buffer` and copy data from one region to an overlapping region + * // within the same `Buffer`. + * + * const buf = Buffer.allocUnsafe(26); + * + * for (let i = 0; i < 26; i++) { + * // 97 is the decimal ASCII value for 'a'. + * buf[i] = i + 97; + * } + * + * buf.copy(buf, 0, 4, 10); + * + * console.log(buf.toString()); + * // Prints: efghijghijklmnopqrstuvwxyz + * ``` + * @since v0.1.90 + * @param target A `Buffer` or {@link Uint8Array} to copy into. + * @param [targetStart=0] The offset within `target` at which to begin writing. + * @param [sourceStart=0] The offset within `buf` from which to begin copying. + * @param [sourceEnd=buf.length] The offset within `buf` at which to stop copying (not inclusive). + * @return The number of bytes copied. + */ + copy(target: Uint8Array, targetStart?: number, sourceStart?: number, sourceEnd?: number): number; + /** + * Writes `value` to `buf` at the specified `offset` as big-endian. + * + * `value` is interpreted and written as a two's complement signed integer. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.allocUnsafe(8); + * + * buf.writeBigInt64BE(0x0102030405060708n, 0); + * + * console.log(buf); + * // Prints: <Buffer 01 02 03 04 05 06 07 08> + * ``` + * @since v12.0.0, v10.20.0 + * @param value Number to be written to `buf`. + * @param [offset=0] Number of bytes to skip before starting to write. Must satisfy: `0 <= offset <= buf.length - 8`. + * @return `offset` plus the number of bytes written. + */ + writeBigInt64BE(value: bigint, offset?: number): number; + /** + * Writes `value` to `buf` at the specified `offset` as little-endian. + * + * `value` is interpreted and written as a two's complement signed integer. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.allocUnsafe(8); + * + * buf.writeBigInt64LE(0x0102030405060708n, 0); + * + * console.log(buf); + * // Prints: <Buffer 08 07 06 05 04 03 02 01> + * ``` + * @since v12.0.0, v10.20.0 + * @param value Number to be written to `buf`. + * @param [offset=0] Number of bytes to skip before starting to write. Must satisfy: `0 <= offset <= buf.length - 8`. + * @return `offset` plus the number of bytes written. + */ + writeBigInt64LE(value: bigint, offset?: number): number; + /** + * Writes `value` to `buf` at the specified `offset` as big-endian. + * + * This function is also available under the `writeBigUint64BE` alias. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.allocUnsafe(8); + * + * buf.writeBigUInt64BE(0xdecafafecacefaden, 0); + * + * console.log(buf); + * // Prints: <Buffer de ca fa fe ca ce fa de> + * ``` + * @since v12.0.0, v10.20.0 + * @param value Number to be written to `buf`. + * @param [offset=0] Number of bytes to skip before starting to write. Must satisfy: `0 <= offset <= buf.length - 8`. + * @return `offset` plus the number of bytes written. + */ + writeBigUInt64BE(value: bigint, offset?: number): number; + /** + * @alias Buffer.writeBigUInt64BE + * @since v14.10.0, v12.19.0 + */ + writeBigUint64BE(value: bigint, offset?: number): number; + /** + * Writes `value` to `buf` at the specified `offset` as little-endian + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.allocUnsafe(8); + * + * buf.writeBigUInt64LE(0xdecafafecacefaden, 0); + * + * console.log(buf); + * // Prints: <Buffer de fa ce ca fe fa ca de> + * ``` + * + * This function is also available under the `writeBigUint64LE` alias. + * @since v12.0.0, v10.20.0 + * @param value Number to be written to `buf`. + * @param [offset=0] Number of bytes to skip before starting to write. Must satisfy: `0 <= offset <= buf.length - 8`. + * @return `offset` plus the number of bytes written. + */ + writeBigUInt64LE(value: bigint, offset?: number): number; + /** + * @alias Buffer.writeBigUInt64LE + * @since v14.10.0, v12.19.0 + */ + writeBigUint64LE(value: bigint, offset?: number): number; + /** + * Writes `byteLength` bytes of `value` to `buf` at the specified `offset`as little-endian. Supports up to 48 bits of accuracy. Behavior is undefined + * when `value` is anything other than an unsigned integer. + * + * This function is also available under the `writeUintLE` alias. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.allocUnsafe(6); + * + * buf.writeUIntLE(0x1234567890ab, 0, 6); + * + * console.log(buf); + * // Prints: <Buffer ab 90 78 56 34 12> + * ``` + * @since v0.5.5 + * @param value Number to be written to `buf`. + * @param offset Number of bytes to skip before starting to write. Must satisfy `0 <= offset <= buf.length - byteLength`. + * @param byteLength Number of bytes to write. Must satisfy `0 < byteLength <= 6`. + * @return `offset` plus the number of bytes written. + */ + writeUIntLE(value: number, offset: number, byteLength: number): number; + /** + * @alias Buffer.writeUIntLE + * @since v14.9.0, v12.19.0 + */ + writeUintLE(value: number, offset: number, byteLength: number): number; + /** + * Writes `byteLength` bytes of `value` to `buf` at the specified `offset`as big-endian. Supports up to 48 bits of accuracy. Behavior is undefined + * when `value` is anything other than an unsigned integer. + * + * This function is also available under the `writeUintBE` alias. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.allocUnsafe(6); + * + * buf.writeUIntBE(0x1234567890ab, 0, 6); + * + * console.log(buf); + * // Prints: <Buffer 12 34 56 78 90 ab> + * ``` + * @since v0.5.5 + * @param value Number to be written to `buf`. + * @param offset Number of bytes to skip before starting to write. Must satisfy `0 <= offset <= buf.length - byteLength`. + * @param byteLength Number of bytes to write. Must satisfy `0 < byteLength <= 6`. + * @return `offset` plus the number of bytes written. + */ + writeUIntBE(value: number, offset: number, byteLength: number): number; + /** + * @alias Buffer.writeUIntBE + * @since v14.9.0, v12.19.0 + */ + writeUintBE(value: number, offset: number, byteLength: number): number; + /** + * Writes `byteLength` bytes of `value` to `buf` at the specified `offset`as little-endian. Supports up to 48 bits of accuracy. Behavior is undefined + * when `value` is anything other than a signed integer. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.allocUnsafe(6); + * + * buf.writeIntLE(0x1234567890ab, 0, 6); + * + * console.log(buf); + * // Prints: <Buffer ab 90 78 56 34 12> + * ``` + * @since v0.11.15 + * @param value Number to be written to `buf`. + * @param offset Number of bytes to skip before starting to write. Must satisfy `0 <= offset <= buf.length - byteLength`. + * @param byteLength Number of bytes to write. Must satisfy `0 < byteLength <= 6`. + * @return `offset` plus the number of bytes written. + */ + writeIntLE(value: number, offset: number, byteLength: number): number; + /** + * Writes `byteLength` bytes of `value` to `buf` at the specified `offset`as big-endian. Supports up to 48 bits of accuracy. Behavior is undefined when`value` is anything other than a + * signed integer. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.allocUnsafe(6); + * + * buf.writeIntBE(0x1234567890ab, 0, 6); + * + * console.log(buf); + * // Prints: <Buffer 12 34 56 78 90 ab> + * ``` + * @since v0.11.15 + * @param value Number to be written to `buf`. + * @param offset Number of bytes to skip before starting to write. Must satisfy `0 <= offset <= buf.length - byteLength`. + * @param byteLength Number of bytes to write. Must satisfy `0 < byteLength <= 6`. + * @return `offset` plus the number of bytes written. + */ + writeIntBE(value: number, offset: number, byteLength: number): number; + /** + * Reads an unsigned, big-endian 64-bit integer from `buf` at the specified`offset`. + * + * This function is also available under the `readBigUint64BE` alias. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.from([0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff]); + * + * console.log(buf.readBigUInt64BE(0)); + * // Prints: 4294967295n + * ``` + * @since v12.0.0, v10.20.0 + * @param [offset=0] Number of bytes to skip before starting to read. Must satisfy: `0 <= offset <= buf.length - 8`. + */ + readBigUInt64BE(offset?: number): bigint; + /** + * @alias Buffer.readBigUInt64BE + * @since v14.10.0, v12.19.0 + */ + readBigUint64BE(offset?: number): bigint; + /** + * Reads an unsigned, little-endian 64-bit integer from `buf` at the specified`offset`. + * + * This function is also available under the `readBigUint64LE` alias. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.from([0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff]); + * + * console.log(buf.readBigUInt64LE(0)); + * // Prints: 18446744069414584320n + * ``` + * @since v12.0.0, v10.20.0 + * @param [offset=0] Number of bytes to skip before starting to read. Must satisfy: `0 <= offset <= buf.length - 8`. + */ + readBigUInt64LE(offset?: number): bigint; + /** + * @alias Buffer.readBigUInt64LE + * @since v14.10.0, v12.19.0 + */ + readBigUint64LE(offset?: number): bigint; + /** + * Reads a signed, big-endian 64-bit integer from `buf` at the specified `offset`. + * + * Integers read from a `Buffer` are interpreted as two's complement signed + * values. + * @since v12.0.0, v10.20.0 + * @param [offset=0] Number of bytes to skip before starting to read. Must satisfy: `0 <= offset <= buf.length - 8`. + */ + readBigInt64BE(offset?: number): bigint; + /** + * Reads a signed, little-endian 64-bit integer from `buf` at the specified`offset`. + * + * Integers read from a `Buffer` are interpreted as two's complement signed + * values. + * @since v12.0.0, v10.20.0 + * @param [offset=0] Number of bytes to skip before starting to read. Must satisfy: `0 <= offset <= buf.length - 8`. + */ + readBigInt64LE(offset?: number): bigint; + /** + * Reads `byteLength` number of bytes from `buf` at the specified `offset` and interprets the result as an unsigned, little-endian integer supporting + * up to 48 bits of accuracy. + * + * This function is also available under the `readUintLE` alias. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.from([0x12, 0x34, 0x56, 0x78, 0x90, 0xab]); + * + * console.log(buf.readUIntLE(0, 6).toString(16)); + * // Prints: ab9078563412 + * ``` + * @since v0.11.15 + * @param offset Number of bytes to skip before starting to read. Must satisfy `0 <= offset <= buf.length - byteLength`. + * @param byteLength Number of bytes to read. Must satisfy `0 < byteLength <= 6`. + */ + readUIntLE(offset: number, byteLength: number): number; + /** + * @alias Buffer.readUIntLE + * @since v14.9.0, v12.19.0 + */ + readUintLE(offset: number, byteLength: number): number; + /** + * Reads `byteLength` number of bytes from `buf` at the specified `offset` and interprets the result as an unsigned big-endian integer supporting + * up to 48 bits of accuracy. + * + * This function is also available under the `readUintBE` alias. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.from([0x12, 0x34, 0x56, 0x78, 0x90, 0xab]); + * + * console.log(buf.readUIntBE(0, 6).toString(16)); + * // Prints: 1234567890ab + * console.log(buf.readUIntBE(1, 6).toString(16)); + * // Throws ERR_OUT_OF_RANGE. + * ``` + * @since v0.11.15 + * @param offset Number of bytes to skip before starting to read. Must satisfy `0 <= offset <= buf.length - byteLength`. + * @param byteLength Number of bytes to read. Must satisfy `0 < byteLength <= 6`. + */ + readUIntBE(offset: number, byteLength: number): number; + /** + * @alias Buffer.readUIntBE + * @since v14.9.0, v12.19.0 + */ + readUintBE(offset: number, byteLength: number): number; + /** + * Reads `byteLength` number of bytes from `buf` at the specified `offset` and interprets the result as a little-endian, two's complement signed value + * supporting up to 48 bits of accuracy. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.from([0x12, 0x34, 0x56, 0x78, 0x90, 0xab]); + * + * console.log(buf.readIntLE(0, 6).toString(16)); + * // Prints: -546f87a9cbee + * ``` + * @since v0.11.15 + * @param offset Number of bytes to skip before starting to read. Must satisfy `0 <= offset <= buf.length - byteLength`. + * @param byteLength Number of bytes to read. Must satisfy `0 < byteLength <= 6`. + */ + readIntLE(offset: number, byteLength: number): number; + /** + * Reads `byteLength` number of bytes from `buf` at the specified `offset` and interprets the result as a big-endian, two's complement signed value + * supporting up to 48 bits of accuracy. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.from([0x12, 0x34, 0x56, 0x78, 0x90, 0xab]); + * + * console.log(buf.readIntBE(0, 6).toString(16)); + * // Prints: 1234567890ab + * console.log(buf.readIntBE(1, 6).toString(16)); + * // Throws ERR_OUT_OF_RANGE. + * console.log(buf.readIntBE(1, 0).toString(16)); + * // Throws ERR_OUT_OF_RANGE. + * ``` + * @since v0.11.15 + * @param offset Number of bytes to skip before starting to read. Must satisfy `0 <= offset <= buf.length - byteLength`. + * @param byteLength Number of bytes to read. Must satisfy `0 < byteLength <= 6`. + */ + readIntBE(offset: number, byteLength: number): number; + /** + * Reads an unsigned 8-bit integer from `buf` at the specified `offset`. + * + * This function is also available under the `readUint8` alias. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.from([1, -2]); + * + * console.log(buf.readUInt8(0)); + * // Prints: 1 + * console.log(buf.readUInt8(1)); + * // Prints: 254 + * console.log(buf.readUInt8(2)); + * // Throws ERR_OUT_OF_RANGE. + * ``` + * @since v0.5.0 + * @param [offset=0] Number of bytes to skip before starting to read. Must satisfy `0 <= offset <= buf.length - 1`. + */ + readUInt8(offset?: number): number; + /** + * @alias Buffer.readUInt8 + * @since v14.9.0, v12.19.0 + */ + readUint8(offset?: number): number; + /** + * Reads an unsigned, little-endian 16-bit integer from `buf` at the specified `offset`. + * + * This function is also available under the `readUint16LE` alias. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.from([0x12, 0x34, 0x56]); + * + * console.log(buf.readUInt16LE(0).toString(16)); + * // Prints: 3412 + * console.log(buf.readUInt16LE(1).toString(16)); + * // Prints: 5634 + * console.log(buf.readUInt16LE(2).toString(16)); + * // Throws ERR_OUT_OF_RANGE. + * ``` + * @since v0.5.5 + * @param [offset=0] Number of bytes to skip before starting to read. Must satisfy `0 <= offset <= buf.length - 2`. + */ + readUInt16LE(offset?: number): number; + /** + * @alias Buffer.readUInt16LE + * @since v14.9.0, v12.19.0 + */ + readUint16LE(offset?: number): number; + /** + * Reads an unsigned, big-endian 16-bit integer from `buf` at the specified`offset`. + * + * This function is also available under the `readUint16BE` alias. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.from([0x12, 0x34, 0x56]); + * + * console.log(buf.readUInt16BE(0).toString(16)); + * // Prints: 1234 + * console.log(buf.readUInt16BE(1).toString(16)); + * // Prints: 3456 + * ``` + * @since v0.5.5 + * @param [offset=0] Number of bytes to skip before starting to read. Must satisfy `0 <= offset <= buf.length - 2`. + */ + readUInt16BE(offset?: number): number; + /** + * @alias Buffer.readUInt16BE + * @since v14.9.0, v12.19.0 + */ + readUint16BE(offset?: number): number; + /** + * Reads an unsigned, little-endian 32-bit integer from `buf` at the specified`offset`. + * + * This function is also available under the `readUint32LE` alias. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.from([0x12, 0x34, 0x56, 0x78]); + * + * console.log(buf.readUInt32LE(0).toString(16)); + * // Prints: 78563412 + * console.log(buf.readUInt32LE(1).toString(16)); + * // Throws ERR_OUT_OF_RANGE. + * ``` + * @since v0.5.5 + * @param [offset=0] Number of bytes to skip before starting to read. Must satisfy `0 <= offset <= buf.length - 4`. + */ + readUInt32LE(offset?: number): number; + /** + * @alias Buffer.readUInt32LE + * @since v14.9.0, v12.19.0 + */ + readUint32LE(offset?: number): number; + /** + * Reads an unsigned, big-endian 32-bit integer from `buf` at the specified`offset`. + * + * This function is also available under the `readUint32BE` alias. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.from([0x12, 0x34, 0x56, 0x78]); + * + * console.log(buf.readUInt32BE(0).toString(16)); + * // Prints: 12345678 + * ``` + * @since v0.5.5 + * @param [offset=0] Number of bytes to skip before starting to read. Must satisfy `0 <= offset <= buf.length - 4`. + */ + readUInt32BE(offset?: number): number; + /** + * @alias Buffer.readUInt32BE + * @since v14.9.0, v12.19.0 + */ + readUint32BE(offset?: number): number; + /** + * Reads a signed 8-bit integer from `buf` at the specified `offset`. + * + * Integers read from a `Buffer` are interpreted as two's complement signed values. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.from([-1, 5]); + * + * console.log(buf.readInt8(0)); + * // Prints: -1 + * console.log(buf.readInt8(1)); + * // Prints: 5 + * console.log(buf.readInt8(2)); + * // Throws ERR_OUT_OF_RANGE. + * ``` + * @since v0.5.0 + * @param [offset=0] Number of bytes to skip before starting to read. Must satisfy `0 <= offset <= buf.length - 1`. + */ + readInt8(offset?: number): number; + /** + * Reads a signed, little-endian 16-bit integer from `buf` at the specified`offset`. + * + * Integers read from a `Buffer` are interpreted as two's complement signed values. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.from([0, 5]); + * + * console.log(buf.readInt16LE(0)); + * // Prints: 1280 + * console.log(buf.readInt16LE(1)); + * // Throws ERR_OUT_OF_RANGE. + * ``` + * @since v0.5.5 + * @param [offset=0] Number of bytes to skip before starting to read. Must satisfy `0 <= offset <= buf.length - 2`. + */ + readInt16LE(offset?: number): number; + /** + * Reads a signed, big-endian 16-bit integer from `buf` at the specified `offset`. + * + * Integers read from a `Buffer` are interpreted as two's complement signed values. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.from([0, 5]); + * + * console.log(buf.readInt16BE(0)); + * // Prints: 5 + * ``` + * @since v0.5.5 + * @param [offset=0] Number of bytes to skip before starting to read. Must satisfy `0 <= offset <= buf.length - 2`. + */ + readInt16BE(offset?: number): number; + /** + * Reads a signed, little-endian 32-bit integer from `buf` at the specified`offset`. + * + * Integers read from a `Buffer` are interpreted as two's complement signed values. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.from([0, 0, 0, 5]); + * + * console.log(buf.readInt32LE(0)); + * // Prints: 83886080 + * console.log(buf.readInt32LE(1)); + * // Throws ERR_OUT_OF_RANGE. + * ``` + * @since v0.5.5 + * @param [offset=0] Number of bytes to skip before starting to read. Must satisfy `0 <= offset <= buf.length - 4`. + */ + readInt32LE(offset?: number): number; + /** + * Reads a signed, big-endian 32-bit integer from `buf` at the specified `offset`. + * + * Integers read from a `Buffer` are interpreted as two's complement signed values. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.from([0, 0, 0, 5]); + * + * console.log(buf.readInt32BE(0)); + * // Prints: 5 + * ``` + * @since v0.5.5 + * @param [offset=0] Number of bytes to skip before starting to read. Must satisfy `0 <= offset <= buf.length - 4`. + */ + readInt32BE(offset?: number): number; + /** + * Reads a 32-bit, little-endian float from `buf` at the specified `offset`. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.from([1, 2, 3, 4]); + * + * console.log(buf.readFloatLE(0)); + * // Prints: 1.539989614439558e-36 + * console.log(buf.readFloatLE(1)); + * // Throws ERR_OUT_OF_RANGE. + * ``` + * @since v0.11.15 + * @param [offset=0] Number of bytes to skip before starting to read. Must satisfy `0 <= offset <= buf.length - 4`. + */ + readFloatLE(offset?: number): number; + /** + * Reads a 32-bit, big-endian float from `buf` at the specified `offset`. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.from([1, 2, 3, 4]); + * + * console.log(buf.readFloatBE(0)); + * // Prints: 2.387939260590663e-38 + * ``` + * @since v0.11.15 + * @param [offset=0] Number of bytes to skip before starting to read. Must satisfy `0 <= offset <= buf.length - 4`. + */ + readFloatBE(offset?: number): number; + /** + * Reads a 64-bit, little-endian double from `buf` at the specified `offset`. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]); + * + * console.log(buf.readDoubleLE(0)); + * // Prints: 5.447603722011605e-270 + * console.log(buf.readDoubleLE(1)); + * // Throws ERR_OUT_OF_RANGE. + * ``` + * @since v0.11.15 + * @param [offset=0] Number of bytes to skip before starting to read. Must satisfy `0 <= offset <= buf.length - 8`. + */ + readDoubleLE(offset?: number): number; + /** + * Reads a 64-bit, big-endian double from `buf` at the specified `offset`. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]); + * + * console.log(buf.readDoubleBE(0)); + * // Prints: 8.20788039913184e-304 + * ``` + * @since v0.11.15 + * @param [offset=0] Number of bytes to skip before starting to read. Must satisfy `0 <= offset <= buf.length - 8`. + */ + readDoubleBE(offset?: number): number; + reverse(): this; + /** + * Interprets `buf` as an array of unsigned 16-bit integers and swaps the + * byte order _in-place_. Throws `ERR_INVALID_BUFFER_SIZE` if `buf.length` is not a multiple of 2. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf1 = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8]); + * + * console.log(buf1); + * // Prints: <Buffer 01 02 03 04 05 06 07 08> + * + * buf1.swap16(); + * + * console.log(buf1); + * // Prints: <Buffer 02 01 04 03 06 05 08 07> + * + * const buf2 = Buffer.from([0x1, 0x2, 0x3]); + * + * buf2.swap16(); + * // Throws ERR_INVALID_BUFFER_SIZE. + * ``` + * + * One convenient use of `buf.swap16()` is to perform a fast in-place conversion + * between UTF-16 little-endian and UTF-16 big-endian: + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.from('This is little-endian UTF-16', 'utf16le'); + * buf.swap16(); // Convert to big-endian UTF-16 text. + * ``` + * @since v5.10.0 + * @return A reference to `buf`. + */ + swap16(): this; + /** + * Interprets `buf` as an array of unsigned 32-bit integers and swaps the + * byte order _in-place_. Throws `ERR_INVALID_BUFFER_SIZE` if `buf.length` is not a multiple of 4. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf1 = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8]); + * + * console.log(buf1); + * // Prints: <Buffer 01 02 03 04 05 06 07 08> + * + * buf1.swap32(); + * + * console.log(buf1); + * // Prints: <Buffer 04 03 02 01 08 07 06 05> + * + * const buf2 = Buffer.from([0x1, 0x2, 0x3]); + * + * buf2.swap32(); + * // Throws ERR_INVALID_BUFFER_SIZE. + * ``` + * @since v5.10.0 + * @return A reference to `buf`. + */ + swap32(): this; + /** + * Interprets `buf` as an array of 64-bit numbers and swaps byte order _in-place_. + * Throws `ERR_INVALID_BUFFER_SIZE` if `buf.length` is not a multiple of 8. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf1 = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8]); + * + * console.log(buf1); + * // Prints: <Buffer 01 02 03 04 05 06 07 08> + * + * buf1.swap64(); + * + * console.log(buf1); + * // Prints: <Buffer 08 07 06 05 04 03 02 01> + * + * const buf2 = Buffer.from([0x1, 0x2, 0x3]); + * + * buf2.swap64(); + * // Throws ERR_INVALID_BUFFER_SIZE. + * ``` + * @since v6.3.0 + * @return A reference to `buf`. + */ + swap64(): this; + /** + * Writes `value` to `buf` at the specified `offset`. `value` must be a + * valid unsigned 8-bit integer. Behavior is undefined when `value` is anything + * other than an unsigned 8-bit integer. + * + * This function is also available under the `writeUint8` alias. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.allocUnsafe(4); + * + * buf.writeUInt8(0x3, 0); + * buf.writeUInt8(0x4, 1); + * buf.writeUInt8(0x23, 2); + * buf.writeUInt8(0x42, 3); + * + * console.log(buf); + * // Prints: <Buffer 03 04 23 42> + * ``` + * @since v0.5.0 + * @param value Number to be written to `buf`. + * @param [offset=0] Number of bytes to skip before starting to write. Must satisfy `0 <= offset <= buf.length - 1`. + * @return `offset` plus the number of bytes written. + */ + writeUInt8(value: number, offset?: number): number; + /** + * @alias Buffer.writeUInt8 + * @since v14.9.0, v12.19.0 + */ + writeUint8(value: number, offset?: number): number; + /** + * Writes `value` to `buf` at the specified `offset` as little-endian. The `value` must be a valid unsigned 16-bit integer. Behavior is undefined when `value` is + * anything other than an unsigned 16-bit integer. + * + * This function is also available under the `writeUint16LE` alias. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.allocUnsafe(4); + * + * buf.writeUInt16LE(0xdead, 0); + * buf.writeUInt16LE(0xbeef, 2); + * + * console.log(buf); + * // Prints: <Buffer ad de ef be> + * ``` + * @since v0.5.5 + * @param value Number to be written to `buf`. + * @param [offset=0] Number of bytes to skip before starting to write. Must satisfy `0 <= offset <= buf.length - 2`. + * @return `offset` plus the number of bytes written. + */ + writeUInt16LE(value: number, offset?: number): number; + /** + * @alias Buffer.writeUInt16LE + * @since v14.9.0, v12.19.0 + */ + writeUint16LE(value: number, offset?: number): number; + /** + * Writes `value` to `buf` at the specified `offset` as big-endian. The `value` must be a valid unsigned 16-bit integer. Behavior is undefined when `value`is anything other than an + * unsigned 16-bit integer. + * + * This function is also available under the `writeUint16BE` alias. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.allocUnsafe(4); + * + * buf.writeUInt16BE(0xdead, 0); + * buf.writeUInt16BE(0xbeef, 2); + * + * console.log(buf); + * // Prints: <Buffer de ad be ef> + * ``` + * @since v0.5.5 + * @param value Number to be written to `buf`. + * @param [offset=0] Number of bytes to skip before starting to write. Must satisfy `0 <= offset <= buf.length - 2`. + * @return `offset` plus the number of bytes written. + */ + writeUInt16BE(value: number, offset?: number): number; + /** + * @alias Buffer.writeUInt16BE + * @since v14.9.0, v12.19.0 + */ + writeUint16BE(value: number, offset?: number): number; + /** + * Writes `value` to `buf` at the specified `offset` as little-endian. The `value` must be a valid unsigned 32-bit integer. Behavior is undefined when `value` is + * anything other than an unsigned 32-bit integer. + * + * This function is also available under the `writeUint32LE` alias. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.allocUnsafe(4); + * + * buf.writeUInt32LE(0xfeedface, 0); + * + * console.log(buf); + * // Prints: <Buffer ce fa ed fe> + * ``` + * @since v0.5.5 + * @param value Number to be written to `buf`. + * @param [offset=0] Number of bytes to skip before starting to write. Must satisfy `0 <= offset <= buf.length - 4`. + * @return `offset` plus the number of bytes written. + */ + writeUInt32LE(value: number, offset?: number): number; + /** + * @alias Buffer.writeUInt32LE + * @since v14.9.0, v12.19.0 + */ + writeUint32LE(value: number, offset?: number): number; + /** + * Writes `value` to `buf` at the specified `offset` as big-endian. The `value` must be a valid unsigned 32-bit integer. Behavior is undefined when `value`is anything other than an + * unsigned 32-bit integer. + * + * This function is also available under the `writeUint32BE` alias. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.allocUnsafe(4); + * + * buf.writeUInt32BE(0xfeedface, 0); + * + * console.log(buf); + * // Prints: <Buffer fe ed fa ce> + * ``` + * @since v0.5.5 + * @param value Number to be written to `buf`. + * @param [offset=0] Number of bytes to skip before starting to write. Must satisfy `0 <= offset <= buf.length - 4`. + * @return `offset` plus the number of bytes written. + */ + writeUInt32BE(value: number, offset?: number): number; + /** + * @alias Buffer.writeUInt32BE + * @since v14.9.0, v12.19.0 + */ + writeUint32BE(value: number, offset?: number): number; + /** + * Writes `value` to `buf` at the specified `offset`. `value` must be a valid + * signed 8-bit integer. Behavior is undefined when `value` is anything other than + * a signed 8-bit integer. + * + * `value` is interpreted and written as a two's complement signed integer. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.allocUnsafe(2); + * + * buf.writeInt8(2, 0); + * buf.writeInt8(-2, 1); + * + * console.log(buf); + * // Prints: <Buffer 02 fe> + * ``` + * @since v0.5.0 + * @param value Number to be written to `buf`. + * @param [offset=0] Number of bytes to skip before starting to write. Must satisfy `0 <= offset <= buf.length - 1`. + * @return `offset` plus the number of bytes written. + */ + writeInt8(value: number, offset?: number): number; + /** + * Writes `value` to `buf` at the specified `offset` as little-endian. The `value` must be a valid signed 16-bit integer. Behavior is undefined when `value` is + * anything other than a signed 16-bit integer. + * + * The `value` is interpreted and written as a two's complement signed integer. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.allocUnsafe(2); + * + * buf.writeInt16LE(0x0304, 0); + * + * console.log(buf); + * // Prints: <Buffer 04 03> + * ``` + * @since v0.5.5 + * @param value Number to be written to `buf`. + * @param [offset=0] Number of bytes to skip before starting to write. Must satisfy `0 <= offset <= buf.length - 2`. + * @return `offset` plus the number of bytes written. + */ + writeInt16LE(value: number, offset?: number): number; + /** + * Writes `value` to `buf` at the specified `offset` as big-endian. The `value` must be a valid signed 16-bit integer. Behavior is undefined when `value` is + * anything other than a signed 16-bit integer. + * + * The `value` is interpreted and written as a two's complement signed integer. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.allocUnsafe(2); + * + * buf.writeInt16BE(0x0102, 0); + * + * console.log(buf); + * // Prints: <Buffer 01 02> + * ``` + * @since v0.5.5 + * @param value Number to be written to `buf`. + * @param [offset=0] Number of bytes to skip before starting to write. Must satisfy `0 <= offset <= buf.length - 2`. + * @return `offset` plus the number of bytes written. + */ + writeInt16BE(value: number, offset?: number): number; + /** + * Writes `value` to `buf` at the specified `offset` as little-endian. The `value` must be a valid signed 32-bit integer. Behavior is undefined when `value` is + * anything other than a signed 32-bit integer. + * + * The `value` is interpreted and written as a two's complement signed integer. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.allocUnsafe(4); + * + * buf.writeInt32LE(0x05060708, 0); + * + * console.log(buf); + * // Prints: <Buffer 08 07 06 05> + * ``` + * @since v0.5.5 + * @param value Number to be written to `buf`. + * @param [offset=0] Number of bytes to skip before starting to write. Must satisfy `0 <= offset <= buf.length - 4`. + * @return `offset` plus the number of bytes written. + */ + writeInt32LE(value: number, offset?: number): number; + /** + * Writes `value` to `buf` at the specified `offset` as big-endian. The `value` must be a valid signed 32-bit integer. Behavior is undefined when `value` is + * anything other than a signed 32-bit integer. + * + * The `value` is interpreted and written as a two's complement signed integer. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.allocUnsafe(4); + * + * buf.writeInt32BE(0x01020304, 0); + * + * console.log(buf); + * // Prints: <Buffer 01 02 03 04> + * ``` + * @since v0.5.5 + * @param value Number to be written to `buf`. + * @param [offset=0] Number of bytes to skip before starting to write. Must satisfy `0 <= offset <= buf.length - 4`. + * @return `offset` plus the number of bytes written. + */ + writeInt32BE(value: number, offset?: number): number; + /** + * Writes `value` to `buf` at the specified `offset` as little-endian. Behavior is + * undefined when `value` is anything other than a JavaScript number. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.allocUnsafe(4); + * + * buf.writeFloatLE(0xcafebabe, 0); + * + * console.log(buf); + * // Prints: <Buffer bb fe 4a 4f> + * ``` + * @since v0.11.15 + * @param value Number to be written to `buf`. + * @param [offset=0] Number of bytes to skip before starting to write. Must satisfy `0 <= offset <= buf.length - 4`. + * @return `offset` plus the number of bytes written. + */ + writeFloatLE(value: number, offset?: number): number; + /** + * Writes `value` to `buf` at the specified `offset` as big-endian. Behavior is + * undefined when `value` is anything other than a JavaScript number. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.allocUnsafe(4); + * + * buf.writeFloatBE(0xcafebabe, 0); + * + * console.log(buf); + * // Prints: <Buffer 4f 4a fe bb> + * ``` + * @since v0.11.15 + * @param value Number to be written to `buf`. + * @param [offset=0] Number of bytes to skip before starting to write. Must satisfy `0 <= offset <= buf.length - 4`. + * @return `offset` plus the number of bytes written. + */ + writeFloatBE(value: number, offset?: number): number; + /** + * Writes `value` to `buf` at the specified `offset` as little-endian. The `value` must be a JavaScript number. Behavior is undefined when `value` is anything + * other than a JavaScript number. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.allocUnsafe(8); + * + * buf.writeDoubleLE(123.456, 0); + * + * console.log(buf); + * // Prints: <Buffer 77 be 9f 1a 2f dd 5e 40> + * ``` + * @since v0.11.15 + * @param value Number to be written to `buf`. + * @param [offset=0] Number of bytes to skip before starting to write. Must satisfy `0 <= offset <= buf.length - 8`. + * @return `offset` plus the number of bytes written. + */ + writeDoubleLE(value: number, offset?: number): number; + /** + * Writes `value` to `buf` at the specified `offset` as big-endian. The `value` must be a JavaScript number. Behavior is undefined when `value` is anything + * other than a JavaScript number. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.allocUnsafe(8); + * + * buf.writeDoubleBE(123.456, 0); + * + * console.log(buf); + * // Prints: <Buffer 40 5e dd 2f 1a 9f be 77> + * ``` + * @since v0.11.15 + * @param value Number to be written to `buf`. + * @param [offset=0] Number of bytes to skip before starting to write. Must satisfy `0 <= offset <= buf.length - 8`. + * @return `offset` plus the number of bytes written. + */ + writeDoubleBE(value: number, offset?: number): number; + /** + * Fills `buf` with the specified `value`. If the `offset` and `end` are not given, + * the entire `buf` will be filled: + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * // Fill a `Buffer` with the ASCII character 'h'. + * + * const b = Buffer.allocUnsafe(50).fill('h'); + * + * console.log(b.toString()); + * // Prints: hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh + * + * // Fill a buffer with empty string + * const c = Buffer.allocUnsafe(5).fill(''); + * + * console.log(c.fill('')); + * // Prints: <Buffer 00 00 00 00 00> + * ``` + * + * `value` is coerced to a `uint32` value if it is not a string, `Buffer`, or + * integer. If the resulting integer is greater than `255` (decimal), `buf` will be + * filled with `value & 255`. + * + * If the final write of a `fill()` operation falls on a multi-byte character, + * then only the bytes of that character that fit into `buf` are written: + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * // Fill a `Buffer` with character that takes up two bytes in UTF-8. + * + * console.log(Buffer.allocUnsafe(5).fill('\u0222')); + * // Prints: <Buffer c8 a2 c8 a2 c8> + * ``` + * + * If `value` contains invalid characters, it is truncated; if no valid + * fill data remains, an exception is thrown: + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.allocUnsafe(5); + * + * console.log(buf.fill('a')); + * // Prints: <Buffer 61 61 61 61 61> + * console.log(buf.fill('aazz', 'hex')); + * // Prints: <Buffer aa aa aa aa aa> + * console.log(buf.fill('zz', 'hex')); + * // Throws an exception. + * ``` + * @since v0.5.0 + * @param value The value with which to fill `buf`. Empty value (string, Uint8Array, Buffer) is coerced to `0`. + * @param [offset=0] Number of bytes to skip before starting to fill `buf`. + * @param [end=buf.length] Where to stop filling `buf` (not inclusive). + * @param [encoding='utf8'] The encoding for `value` if `value` is a string. + * @return A reference to `buf`. + */ + fill(value: string | Uint8Array | number, offset?: number, end?: number, encoding?: BufferEncoding): this; + fill(value: string | Uint8Array | number, offset: number, encoding: BufferEncoding): this; + fill(value: string | Uint8Array | number, encoding: BufferEncoding): this; + /** + * If `value` is: + * + * * a string, `value` is interpreted according to the character encoding in `encoding`. + * * a `Buffer` or [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array), `value` will be used in its entirety. + * To compare a partial `Buffer`, use `buf.subarray`. + * * a number, `value` will be interpreted as an unsigned 8-bit integer + * value between `0` and `255`. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.from('this is a buffer'); + * + * console.log(buf.indexOf('this')); + * // Prints: 0 + * console.log(buf.indexOf('is')); + * // Prints: 2 + * console.log(buf.indexOf(Buffer.from('a buffer'))); + * // Prints: 8 + * console.log(buf.indexOf(97)); + * // Prints: 8 (97 is the decimal ASCII value for 'a') + * console.log(buf.indexOf(Buffer.from('a buffer example'))); + * // Prints: -1 + * console.log(buf.indexOf(Buffer.from('a buffer example').slice(0, 8))); + * // Prints: 8 + * + * const utf16Buffer = Buffer.from('\u039a\u0391\u03a3\u03a3\u0395', 'utf16le'); + * + * console.log(utf16Buffer.indexOf('\u03a3', 0, 'utf16le')); + * // Prints: 4 + * console.log(utf16Buffer.indexOf('\u03a3', -4, 'utf16le')); + * // Prints: 6 + * ``` + * + * If `value` is not a string, number, or `Buffer`, this method will throw a `TypeError`. If `value` is a number, it will be coerced to a valid byte value, + * an integer between 0 and 255. + * + * If `byteOffset` is not a number, it will be coerced to a number. If the result + * of coercion is `NaN` or `0`, then the entire buffer will be searched. This + * behavior matches [`String.prototype.indexOf()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf). + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const b = Buffer.from('abcdef'); + * + * // Passing a value that's a number, but not a valid byte. + * // Prints: 2, equivalent to searching for 99 or 'c'. + * console.log(b.indexOf(99.9)); + * console.log(b.indexOf(256 + 99)); + * + * // Passing a byteOffset that coerces to NaN or 0. + * // Prints: 1, searching the whole buffer. + * console.log(b.indexOf('b', undefined)); + * console.log(b.indexOf('b', {})); + * console.log(b.indexOf('b', null)); + * console.log(b.indexOf('b', [])); + * ``` + * + * If `value` is an empty string or empty `Buffer` and `byteOffset` is less + * than `buf.length`, `byteOffset` will be returned. If `value` is empty and`byteOffset` is at least `buf.length`, `buf.length` will be returned. + * @since v1.5.0 + * @param value What to search for. + * @param [byteOffset=0] Where to begin searching in `buf`. If negative, then offset is calculated from the end of `buf`. + * @param [encoding='utf8'] If `value` is a string, this is the encoding used to determine the binary representation of the string that will be searched for in `buf`. + * @return The index of the first occurrence of `value` in `buf`, or `-1` if `buf` does not contain `value`. + */ + indexOf(value: string | number | Uint8Array, byteOffset?: number, encoding?: BufferEncoding): number; + indexOf(value: string | number | Uint8Array, encoding: BufferEncoding): number; + /** + * Identical to `buf.indexOf()`, except the last occurrence of `value` is found + * rather than the first occurrence. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.from('this buffer is a buffer'); + * + * console.log(buf.lastIndexOf('this')); + * // Prints: 0 + * console.log(buf.lastIndexOf('buffer')); + * // Prints: 17 + * console.log(buf.lastIndexOf(Buffer.from('buffer'))); + * // Prints: 17 + * console.log(buf.lastIndexOf(97)); + * // Prints: 15 (97 is the decimal ASCII value for 'a') + * console.log(buf.lastIndexOf(Buffer.from('yolo'))); + * // Prints: -1 + * console.log(buf.lastIndexOf('buffer', 5)); + * // Prints: 5 + * console.log(buf.lastIndexOf('buffer', 4)); + * // Prints: -1 + * + * const utf16Buffer = Buffer.from('\u039a\u0391\u03a3\u03a3\u0395', 'utf16le'); + * + * console.log(utf16Buffer.lastIndexOf('\u03a3', undefined, 'utf16le')); + * // Prints: 6 + * console.log(utf16Buffer.lastIndexOf('\u03a3', -5, 'utf16le')); + * // Prints: 4 + * ``` + * + * If `value` is not a string, number, or `Buffer`, this method will throw a `TypeError`. If `value` is a number, it will be coerced to a valid byte value, + * an integer between 0 and 255. + * + * If `byteOffset` is not a number, it will be coerced to a number. Any arguments + * that coerce to `NaN`, like `{}` or `undefined`, will search the whole buffer. + * This behavior matches [`String.prototype.lastIndexOf()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/lastIndexOf). + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const b = Buffer.from('abcdef'); + * + * // Passing a value that's a number, but not a valid byte. + * // Prints: 2, equivalent to searching for 99 or 'c'. + * console.log(b.lastIndexOf(99.9)); + * console.log(b.lastIndexOf(256 + 99)); + * + * // Passing a byteOffset that coerces to NaN. + * // Prints: 1, searching the whole buffer. + * console.log(b.lastIndexOf('b', undefined)); + * console.log(b.lastIndexOf('b', {})); + * + * // Passing a byteOffset that coerces to 0. + * // Prints: -1, equivalent to passing 0. + * console.log(b.lastIndexOf('b', null)); + * console.log(b.lastIndexOf('b', [])); + * ``` + * + * If `value` is an empty string or empty `Buffer`, `byteOffset` will be returned. + * @since v6.0.0 + * @param value What to search for. + * @param [byteOffset=buf.length - 1] Where to begin searching in `buf`. If negative, then offset is calculated from the end of `buf`. + * @param [encoding='utf8'] If `value` is a string, this is the encoding used to determine the binary representation of the string that will be searched for in `buf`. + * @return The index of the last occurrence of `value` in `buf`, or `-1` if `buf` does not contain `value`. + */ + lastIndexOf(value: string | number | Uint8Array, byteOffset?: number, encoding?: BufferEncoding): number; + lastIndexOf(value: string | number | Uint8Array, encoding: BufferEncoding): number; + /** + * Equivalent to `buf.indexOf() !== -1`. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.from('this is a buffer'); + * + * console.log(buf.includes('this')); + * // Prints: true + * console.log(buf.includes('is')); + * // Prints: true + * console.log(buf.includes(Buffer.from('a buffer'))); + * // Prints: true + * console.log(buf.includes(97)); + * // Prints: true (97 is the decimal ASCII value for 'a') + * console.log(buf.includes(Buffer.from('a buffer example'))); + * // Prints: false + * console.log(buf.includes(Buffer.from('a buffer example').slice(0, 8))); + * // Prints: true + * console.log(buf.includes('this', 4)); + * // Prints: false + * ``` + * @since v5.3.0 + * @param value What to search for. + * @param [byteOffset=0] Where to begin searching in `buf`. If negative, then offset is calculated from the end of `buf`. + * @param [encoding='utf8'] If `value` is a string, this is its encoding. + * @return `true` if `value` was found in `buf`, `false` otherwise. + */ + includes(value: string | number | Buffer, byteOffset?: number, encoding?: BufferEncoding): boolean; + includes(value: string | number | Buffer, encoding: BufferEncoding): boolean; + } + var Buffer: BufferConstructor; + } + // #region web types + export type BlobPart = NodeJS.BufferSource | Blob | string; + export interface BlobPropertyBag { + endings?: "native" | "transparent"; + type?: string; + } + export interface FilePropertyBag extends BlobPropertyBag { + lastModified?: number; + } + export interface Blob { + readonly size: number; + readonly type: string; + arrayBuffer(): Promise<ArrayBuffer>; + bytes(): Promise<NodeJS.NonSharedUint8Array>; + slice(start?: number, end?: number, contentType?: string): Blob; + stream(): ReadableStream<NodeJS.NonSharedUint8Array>; + text(): Promise<string>; + } + export var Blob: { + prototype: Blob; + new(blobParts?: BlobPart[], options?: BlobPropertyBag): Blob; + }; + export interface File extends Blob { + readonly lastModified: number; + readonly name: string; + readonly webkitRelativePath: string; + } + export var File: { + prototype: File; + new(fileBits: BlobPart[], fileName: string, options?: FilePropertyBag): File; + }; + export import atob = globalThis.atob; + export import btoa = globalThis.btoa; + // #endregion +} +declare module "buffer" { + export * from "node:buffer"; +} diff --git a/server/node_modules/@types/node/child_process.d.ts b/server/node_modules/@types/node/child_process.d.ts new file mode 100644 index 0000000..f081809 --- /dev/null +++ b/server/node_modules/@types/node/child_process.d.ts @@ -0,0 +1,1428 @@ +/** + * The `node:child_process` module provides the ability to spawn subprocesses in + * a manner that is similar, but not identical, to [`popen(3)`](http://man7.org/linux/man-pages/man3/popen.3.html). This capability + * is primarily provided by the {@link spawn} function: + * + * ```js + * import { spawn } from 'node:child_process'; + * import { once } from 'node:events'; + * const ls = spawn('ls', ['-lh', '/usr']); + * + * ls.stdout.on('data', (data) => { + * console.log(`stdout: ${data}`); + * }); + * + * ls.stderr.on('data', (data) => { + * console.error(`stderr: ${data}`); + * }); + * + * const [code] = await once(ls, 'close'); + * console.log(`child process exited with code ${code}`); + * ``` + * + * By default, pipes for `stdin`, `stdout`, and `stderr` are established between + * the parent Node.js process and the spawned subprocess. These pipes have + * limited (and platform-specific) capacity. If the subprocess writes to + * stdout in excess of that limit without the output being captured, the + * subprocess blocks, waiting for the pipe buffer to accept more data. This is + * identical to the behavior of pipes in the shell. Use the `{ stdio: 'ignore' }` option if the output will not be consumed. + * + * The command lookup is performed using the `options.env.PATH` environment + * variable if `env` is in the `options` object. Otherwise, `process.env.PATH` is + * used. If `options.env` is set without `PATH`, lookup on Unix is performed + * on a default search path search of `/usr/bin:/bin` (see your operating system's + * manual for execvpe/execvp), on Windows the current processes environment + * variable `PATH` is used. + * + * On Windows, environment variables are case-insensitive. Node.js + * lexicographically sorts the `env` keys and uses the first one that + * case-insensitively matches. Only first (in lexicographic order) entry will be + * passed to the subprocess. This might lead to issues on Windows when passing + * objects to the `env` option that have multiple variants of the same key, such as `PATH` and `Path`. + * + * The {@link spawn} method spawns the child process asynchronously, + * without blocking the Node.js event loop. The {@link spawnSync} function provides equivalent functionality in a synchronous manner that blocks + * the event loop until the spawned process either exits or is terminated. + * + * For convenience, the `node:child_process` module provides a handful of + * synchronous and asynchronous alternatives to {@link spawn} and {@link spawnSync}. Each of these alternatives are implemented on + * top of {@link spawn} or {@link spawnSync}. + * + * * {@link exec}: spawns a shell and runs a command within that + * shell, passing the `stdout` and `stderr` to a callback function when + * complete. + * * {@link execFile}: similar to {@link exec} except + * that it spawns the command directly without first spawning a shell by + * default. + * * {@link fork}: spawns a new Node.js process and invokes a + * specified module with an IPC communication channel established that allows + * sending messages between parent and child. + * * {@link execSync}: a synchronous version of {@link exec} that will block the Node.js event loop. + * * {@link execFileSync}: a synchronous version of {@link execFile} that will block the Node.js event loop. + * + * For certain use cases, such as automating shell scripts, the `synchronous counterparts` may be more convenient. In many cases, however, + * the synchronous methods can have significant impact on performance due to + * stalling the event loop while spawned processes complete. + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/child_process.js) + */ +declare module "node:child_process" { + import { NonSharedBuffer } from "node:buffer"; + import * as dgram from "node:dgram"; + import { Abortable, EventEmitter, InternalEventEmitter } from "node:events"; + import * as net from "node:net"; + import { Readable, Stream, Writable } from "node:stream"; + import { URL } from "node:url"; + type Serializable = string | object | number | boolean | bigint; + type SendHandle = net.Socket | net.Server | dgram.Socket | undefined; + interface ChildProcessEventMap { + "close": [code: number | null, signal: NodeJS.Signals | null]; + "disconnect": []; + "error": [err: Error]; + "exit": [code: number | null, signal: NodeJS.Signals | null]; + "message": [message: Serializable, sendHandle: SendHandle]; + "spawn": []; + } + /** + * Instances of the `ChildProcess` represent spawned child processes. + * + * Instances of `ChildProcess` are not intended to be created directly. Rather, + * use the {@link spawn}, {@link exec},{@link execFile}, or {@link fork} methods to create + * instances of `ChildProcess`. + * @since v2.2.0 + */ + class ChildProcess implements EventEmitter { + /** + * A `Writable Stream` that represents the child process's `stdin`. + * + * If a child process waits to read all of its input, the child will not continue + * until this stream has been closed via `end()`. + * + * If the child was spawned with `stdio[0]` set to anything other than `'pipe'`, + * then this will be `null`. + * + * `subprocess.stdin` is an alias for `subprocess.stdio[0]`. Both properties will + * refer to the same value. + * + * The `subprocess.stdin` property can be `null` or `undefined` if the child process could not be successfully spawned. + * @since v0.1.90 + */ + stdin: Writable | null; + /** + * A `Readable Stream` that represents the child process's `stdout`. + * + * If the child was spawned with `stdio[1]` set to anything other than `'pipe'`, + * then this will be `null`. + * + * `subprocess.stdout` is an alias for `subprocess.stdio[1]`. Both properties will + * refer to the same value. + * + * ```js + * import { spawn } from 'node:child_process'; + * + * const subprocess = spawn('ls'); + * + * subprocess.stdout.on('data', (data) => { + * console.log(`Received chunk ${data}`); + * }); + * ``` + * + * The `subprocess.stdout` property can be `null` or `undefined` if the child process could not be successfully spawned. + * @since v0.1.90 + */ + stdout: Readable | null; + /** + * A `Readable Stream` that represents the child process's `stderr`. + * + * If the child was spawned with `stdio[2]` set to anything other than `'pipe'`, + * then this will be `null`. + * + * `subprocess.stderr` is an alias for `subprocess.stdio[2]`. Both properties will + * refer to the same value. + * + * The `subprocess.stderr` property can be `null` or `undefined` if the child process could not be successfully spawned. + * @since v0.1.90 + */ + stderr: Readable | null; + /** + * The `subprocess.channel` property is a reference to the child's IPC channel. If + * no IPC channel exists, this property is `undefined`. + * @since v7.1.0 + */ + readonly channel?: Control | null; + /** + * A sparse array of pipes to the child process, corresponding with positions in + * the `stdio` option passed to {@link spawn} that have been set + * to the value `'pipe'`. `subprocess.stdio[0]`, `subprocess.stdio[1]`, and `subprocess.stdio[2]` are also available as `subprocess.stdin`, `subprocess.stdout`, and `subprocess.stderr`, + * respectively. + * + * In the following example, only the child's fd `1` (stdout) is configured as a + * pipe, so only the parent's `subprocess.stdio[1]` is a stream, all other values + * in the array are `null`. + * + * ```js + * import assert from 'node:assert'; + * import fs from 'node:fs'; + * import child_process from 'node:child_process'; + * + * const subprocess = child_process.spawn('ls', { + * stdio: [ + * 0, // Use parent's stdin for child. + * 'pipe', // Pipe child's stdout to parent. + * fs.openSync('err.out', 'w'), // Direct child's stderr to a file. + * ], + * }); + * + * assert.strictEqual(subprocess.stdio[0], null); + * assert.strictEqual(subprocess.stdio[0], subprocess.stdin); + * + * assert(subprocess.stdout); + * assert.strictEqual(subprocess.stdio[1], subprocess.stdout); + * + * assert.strictEqual(subprocess.stdio[2], null); + * assert.strictEqual(subprocess.stdio[2], subprocess.stderr); + * ``` + * + * The `subprocess.stdio` property can be `undefined` if the child process could + * not be successfully spawned. + * @since v0.7.10 + */ + readonly stdio: [ + Writable | null, + // stdin + Readable | null, + // stdout + Readable | null, + // stderr + Readable | Writable | null | undefined, + // extra + Readable | Writable | null | undefined, // extra + ]; + /** + * The `subprocess.killed` property indicates whether the child process + * successfully received a signal from `subprocess.kill()`. The `killed` property + * does not indicate that the child process has been terminated. + * @since v0.5.10 + */ + readonly killed: boolean; + /** + * Returns the process identifier (PID) of the child process. If the child process + * fails to spawn due to errors, then the value is `undefined` and `error` is + * emitted. + * + * ```js + * import { spawn } from 'node:child_process'; + * const grep = spawn('grep', ['ssh']); + * + * console.log(`Spawned child pid: ${grep.pid}`); + * grep.stdin.end(); + * ``` + * @since v0.1.90 + */ + readonly pid?: number | undefined; + /** + * The `subprocess.connected` property indicates whether it is still possible to + * send and receive messages from a child process. When `subprocess.connected` is `false`, it is no longer possible to send or receive messages. + * @since v0.7.2 + */ + readonly connected: boolean; + /** + * The `subprocess.exitCode` property indicates the exit code of the child process. + * If the child process is still running, the field will be `null`. + */ + readonly exitCode: number | null; + /** + * The `subprocess.signalCode` property indicates the signal received by + * the child process if any, else `null`. + */ + readonly signalCode: NodeJS.Signals | null; + /** + * The `subprocess.spawnargs` property represents the full list of command-line + * arguments the child process was launched with. + */ + readonly spawnargs: string[]; + /** + * The `subprocess.spawnfile` property indicates the executable file name of + * the child process that is launched. + * + * For {@link fork}, its value will be equal to `process.execPath`. + * For {@link spawn}, its value will be the name of + * the executable file. + * For {@link exec}, its value will be the name of the shell + * in which the child process is launched. + */ + readonly spawnfile: string; + /** + * The `subprocess.kill()` method sends a signal to the child process. If no + * argument is given, the process will be sent the `'SIGTERM'` signal. See [`signal(7)`](http://man7.org/linux/man-pages/man7/signal.7.html) for a list of available signals. This function + * returns `true` if [`kill(2)`](http://man7.org/linux/man-pages/man2/kill.2.html) succeeds, and `false` otherwise. + * + * ```js + * import { spawn } from 'node:child_process'; + * const grep = spawn('grep', ['ssh']); + * + * grep.on('close', (code, signal) => { + * console.log( + * `child process terminated due to receipt of signal ${signal}`); + * }); + * + * // Send SIGHUP to process. + * grep.kill('SIGHUP'); + * ``` + * + * The `ChildProcess` object may emit an `'error'` event if the signal + * cannot be delivered. Sending a signal to a child process that has already exited + * is not an error but may have unforeseen consequences. Specifically, if the + * process identifier (PID) has been reassigned to another process, the signal will + * be delivered to that process instead which can have unexpected results. + * + * While the function is called `kill`, the signal delivered to the child process + * may not actually terminate the process. + * + * See [`kill(2)`](http://man7.org/linux/man-pages/man2/kill.2.html) for reference. + * + * On Windows, where POSIX signals do not exist, the `signal` argument will be + * ignored, and the process will be killed forcefully and abruptly (similar to `'SIGKILL'`). + * See `Signal Events` for more details. + * + * On Linux, child processes of child processes will not be terminated + * when attempting to kill their parent. This is likely to happen when running a + * new process in a shell or with the use of the `shell` option of `ChildProcess`: + * + * ```js + * 'use strict'; + * import { spawn } from 'node:child_process'; + * + * const subprocess = spawn( + * 'sh', + * [ + * '-c', + * `node -e "setInterval(() => { + * console.log(process.pid, 'is alive') + * }, 500);"`, + * ], { + * stdio: ['inherit', 'inherit', 'inherit'], + * }, + * ); + * + * setTimeout(() => { + * subprocess.kill(); // Does not terminate the Node.js process in the shell. + * }, 2000); + * ``` + * @since v0.1.90 + */ + kill(signal?: NodeJS.Signals | number): boolean; + /** + * Calls {@link ChildProcess.kill} with `'SIGTERM'`. + * @since v20.5.0 + */ + [Symbol.dispose](): void; + /** + * When an IPC channel has been established between the parent and child ( + * i.e. when using {@link fork}), the `subprocess.send()` method can + * be used to send messages to the child process. When the child process is a + * Node.js instance, these messages can be received via the `'message'` event. + * + * The message goes through serialization and parsing. The resulting + * message might not be the same as what is originally sent. + * + * For example, in the parent script: + * + * ```js + * import cp from 'node:child_process'; + * const n = cp.fork(`${__dirname}/sub.js`); + * + * n.on('message', (m) => { + * console.log('PARENT got message:', m); + * }); + * + * // Causes the child to print: CHILD got message: { hello: 'world' } + * n.send({ hello: 'world' }); + * ``` + * + * And then the child script, `'sub.js'` might look like this: + * + * ```js + * process.on('message', (m) => { + * console.log('CHILD got message:', m); + * }); + * + * // Causes the parent to print: PARENT got message: { foo: 'bar', baz: null } + * process.send({ foo: 'bar', baz: NaN }); + * ``` + * + * Child Node.js processes will have a `process.send()` method of their own + * that allows the child to send messages back to the parent. + * + * There is a special case when sending a `{cmd: 'NODE_foo'}` message. Messages + * containing a `NODE_` prefix in the `cmd` property are reserved for use within + * Node.js core and will not be emitted in the child's `'message'` event. Rather, such messages are emitted using the `'internalMessage'` event and are consumed internally by Node.js. + * Applications should avoid using such messages or listening for `'internalMessage'` events as it is subject to change without notice. + * + * The optional `sendHandle` argument that may be passed to `subprocess.send()` is + * for passing a TCP server or socket object to the child process. The child will + * receive the object as the second argument passed to the callback function + * registered on the `'message'` event. Any data that is received and buffered in + * the socket will not be sent to the child. Sending IPC sockets is not supported on Windows. + * + * The optional `callback` is a function that is invoked after the message is + * sent but before the child may have received it. The function is called with a + * single argument: `null` on success, or an `Error` object on failure. + * + * If no `callback` function is provided and the message cannot be sent, an `'error'` event will be emitted by the `ChildProcess` object. This can + * happen, for instance, when the child process has already exited. + * + * `subprocess.send()` will return `false` if the channel has closed or when the + * backlog of unsent messages exceeds a threshold that makes it unwise to send + * more. Otherwise, the method returns `true`. The `callback` function can be + * used to implement flow control. + * + * #### Example: sending a server object + * + * The `sendHandle` argument can be used, for instance, to pass the handle of + * a TCP server object to the child process as illustrated in the example below: + * + * ```js + * import { createServer } from 'node:net'; + * import { fork } from 'node:child_process'; + * const subprocess = fork('subprocess.js'); + * + * // Open up the server object and send the handle. + * const server = createServer(); + * server.on('connection', (socket) => { + * socket.end('handled by parent'); + * }); + * server.listen(1337, () => { + * subprocess.send('server', server); + * }); + * ``` + * + * The child would then receive the server object as: + * + * ```js + * process.on('message', (m, server) => { + * if (m === 'server') { + * server.on('connection', (socket) => { + * socket.end('handled by child'); + * }); + * } + * }); + * ``` + * + * Once the server is now shared between the parent and child, some connections + * can be handled by the parent and some by the child. + * + * While the example above uses a server created using the `node:net` module, `node:dgram` module servers use exactly the same workflow with the exceptions of + * listening on a `'message'` event instead of `'connection'` and using `server.bind()` instead of `server.listen()`. This is, however, only + * supported on Unix platforms. + * + * #### Example: sending a socket object + * + * Similarly, the `sendHandler` argument can be used to pass the handle of a + * socket to the child process. The example below spawns two children that each + * handle connections with "normal" or "special" priority: + * + * ```js + * import { createServer } from 'node:net'; + * import { fork } from 'node:child_process'; + * const normal = fork('subprocess.js', ['normal']); + * const special = fork('subprocess.js', ['special']); + * + * // Open up the server and send sockets to child. Use pauseOnConnect to prevent + * // the sockets from being read before they are sent to the child process. + * const server = createServer({ pauseOnConnect: true }); + * server.on('connection', (socket) => { + * + * // If this is special priority... + * if (socket.remoteAddress === '74.125.127.100') { + * special.send('socket', socket); + * return; + * } + * // This is normal priority. + * normal.send('socket', socket); + * }); + * server.listen(1337); + * ``` + * + * The `subprocess.js` would receive the socket handle as the second argument + * passed to the event callback function: + * + * ```js + * process.on('message', (m, socket) => { + * if (m === 'socket') { + * if (socket) { + * // Check that the client socket exists. + * // It is possible for the socket to be closed between the time it is + * // sent and the time it is received in the child process. + * socket.end(`Request handled with ${process.argv[2]} priority`); + * } + * } + * }); + * ``` + * + * Do not use `.maxConnections` on a socket that has been passed to a subprocess. + * The parent cannot track when the socket is destroyed. + * + * Any `'message'` handlers in the subprocess should verify that `socket` exists, + * as the connection may have been closed during the time it takes to send the + * connection to the child. + * @since v0.5.9 + * @param sendHandle `undefined`, or a [`net.Socket`](https://nodejs.org/docs/latest-v25.x/api/net.html#class-netsocket), [`net.Server`](https://nodejs.org/docs/latest-v25.x/api/net.html#class-netserver), or [`dgram.Socket`](https://nodejs.org/docs/latest-v25.x/api/dgram.html#class-dgramsocket) object. + * @param options The `options` argument, if present, is an object used to parameterize the sending of certain types of handles. `options` supports the following properties: + */ + send(message: Serializable, callback?: (error: Error | null) => void): boolean; + send(message: Serializable, sendHandle?: SendHandle, callback?: (error: Error | null) => void): boolean; + send( + message: Serializable, + sendHandle?: SendHandle, + options?: MessageOptions, + callback?: (error: Error | null) => void, + ): boolean; + /** + * Closes the IPC channel between parent and child, allowing the child to exit + * gracefully once there are no other connections keeping it alive. After calling + * this method the `subprocess.connected` and `process.connected` properties in + * both the parent and child (respectively) will be set to `false`, and it will be + * no longer possible to pass messages between the processes. + * + * The `'disconnect'` event will be emitted when there are no messages in the + * process of being received. This will most often be triggered immediately after + * calling `subprocess.disconnect()`. + * + * When the child process is a Node.js instance (e.g. spawned using {@link fork}), the `process.disconnect()` method can be invoked + * within the child process to close the IPC channel as well. + * @since v0.7.2 + */ + disconnect(): void; + /** + * By default, the parent will wait for the detached child to exit. To prevent the + * parent from waiting for a given `subprocess` to exit, use the `subprocess.unref()` method. Doing so will cause the parent's event loop to not + * include the child in its reference count, allowing the parent to exit + * independently of the child, unless there is an established IPC channel between + * the child and the parent. + * + * ```js + * import { spawn } from 'node:child_process'; + * + * const subprocess = spawn(process.argv[0], ['child_program.js'], { + * detached: true, + * stdio: 'ignore', + * }); + * + * subprocess.unref(); + * ``` + * @since v0.7.10 + */ + unref(): void; + /** + * Calling `subprocess.ref()` after making a call to `subprocess.unref()` will + * restore the removed reference count for the child process, forcing the parent + * to wait for the child to exit before exiting itself. + * + * ```js + * import { spawn } from 'node:child_process'; + * + * const subprocess = spawn(process.argv[0], ['child_program.js'], { + * detached: true, + * stdio: 'ignore', + * }); + * + * subprocess.unref(); + * subprocess.ref(); + * ``` + * @since v0.7.10 + */ + ref(): void; + } + interface ChildProcess extends InternalEventEmitter<ChildProcessEventMap> {} + // return this object when stdio option is undefined or not specified + interface ChildProcessWithoutNullStreams extends ChildProcess { + stdin: Writable; + stdout: Readable; + stderr: Readable; + readonly stdio: [ + Writable, + Readable, + Readable, + // stderr + Readable | Writable | null | undefined, + // extra, no modification + Readable | Writable | null | undefined, // extra, no modification + ]; + } + // return this object when stdio option is a tuple of 3 + interface ChildProcessByStdio<I extends null | Writable, O extends null | Readable, E extends null | Readable> + extends ChildProcess + { + stdin: I; + stdout: O; + stderr: E; + readonly stdio: [ + I, + O, + E, + Readable | Writable | null | undefined, + // extra, no modification + Readable | Writable | null | undefined, // extra, no modification + ]; + } + interface Control extends EventEmitter { + ref(): void; + unref(): void; + } + interface MessageOptions { + keepOpen?: boolean | undefined; + } + type IOType = "overlapped" | "pipe" | "ignore" | "inherit"; + type StdioOptions = IOType | Array<IOType | "ipc" | Stream | number | null | undefined>; + type SerializationType = "json" | "advanced"; + interface MessagingOptions extends Abortable { + /** + * Specify the kind of serialization used for sending messages between processes. + * @default 'json' + */ + serialization?: SerializationType | undefined; + /** + * The signal value to be used when the spawned process will be killed by the abort signal. + * @default 'SIGTERM' + */ + killSignal?: NodeJS.Signals | number | undefined; + /** + * In milliseconds the maximum amount of time the process is allowed to run. + */ + timeout?: number | undefined; + } + interface ProcessEnvOptions { + uid?: number | undefined; + gid?: number | undefined; + cwd?: string | URL | undefined; + env?: NodeJS.ProcessEnv | undefined; + } + interface CommonOptions extends ProcessEnvOptions { + /** + * @default false + */ + windowsHide?: boolean | undefined; + /** + * @default 0 + */ + timeout?: number | undefined; + } + interface CommonSpawnOptions extends CommonOptions, MessagingOptions, Abortable { + argv0?: string | undefined; + /** + * Can be set to 'pipe', 'inherit', 'overlapped', or 'ignore', or an array of these strings. + * If passed as an array, the first element is used for `stdin`, the second for + * `stdout`, and the third for `stderr`. A fourth element can be used to + * specify the `stdio` behavior beyond the standard streams. See + * {@link ChildProcess.stdio} for more information. + * + * @default 'pipe' + */ + stdio?: StdioOptions | undefined; + shell?: boolean | string | undefined; + windowsVerbatimArguments?: boolean | undefined; + } + interface SpawnOptions extends CommonSpawnOptions { + detached?: boolean | undefined; + } + interface SpawnOptionsWithoutStdio extends SpawnOptions { + stdio?: StdioPipeNamed | StdioPipe[] | undefined; + } + type StdioNull = "inherit" | "ignore" | Stream; + type StdioPipeNamed = "pipe" | "overlapped"; + type StdioPipe = undefined | null | StdioPipeNamed; + interface SpawnOptionsWithStdioTuple< + Stdin extends StdioNull | StdioPipe, + Stdout extends StdioNull | StdioPipe, + Stderr extends StdioNull | StdioPipe, + > extends SpawnOptions { + stdio: [Stdin, Stdout, Stderr]; + } + /** + * The `child_process.spawn()` method spawns a new process using the given `command`, with command-line arguments in `args`. If omitted, `args` defaults + * to an empty array. + * + * **If the `shell` option is enabled, do not pass unsanitized user input to this** + * **function. Any input containing shell metacharacters may be used to trigger** + * **arbitrary command execution.** + * + * A third argument may be used to specify additional options, with these defaults: + * + * ```js + * const defaults = { + * cwd: undefined, + * env: process.env, + * }; + * ``` + * + * Use `cwd` to specify the working directory from which the process is spawned. + * If not given, the default is to inherit the current working directory. If given, + * but the path does not exist, the child process emits an `ENOENT` error + * and exits immediately. `ENOENT` is also emitted when the command + * does not exist. + * + * Use `env` to specify environment variables that will be visible to the new + * process, the default is `process.env`. + * + * `undefined` values in `env` will be ignored. + * + * Example of running `ls -lh /usr`, capturing `stdout`, `stderr`, and the + * exit code: + * + * ```js + * import { spawn } from 'node:child_process'; + * import { once } from 'node:events'; + * const ls = spawn('ls', ['-lh', '/usr']); + * + * ls.stdout.on('data', (data) => { + * console.log(`stdout: ${data}`); + * }); + * + * ls.stderr.on('data', (data) => { + * console.error(`stderr: ${data}`); + * }); + * + * const [code] = await once(ls, 'close'); + * console.log(`child process exited with code ${code}`); + * ``` + * + * Example: A very elaborate way to run `ps ax | grep ssh` + * + * ```js + * import { spawn } from 'node:child_process'; + * const ps = spawn('ps', ['ax']); + * const grep = spawn('grep', ['ssh']); + * + * ps.stdout.on('data', (data) => { + * grep.stdin.write(data); + * }); + * + * ps.stderr.on('data', (data) => { + * console.error(`ps stderr: ${data}`); + * }); + * + * ps.on('close', (code) => { + * if (code !== 0) { + * console.log(`ps process exited with code ${code}`); + * } + * grep.stdin.end(); + * }); + * + * grep.stdout.on('data', (data) => { + * console.log(data.toString()); + * }); + * + * grep.stderr.on('data', (data) => { + * console.error(`grep stderr: ${data}`); + * }); + * + * grep.on('close', (code) => { + * if (code !== 0) { + * console.log(`grep process exited with code ${code}`); + * } + * }); + * ``` + * + * Example of checking for failed `spawn`: + * + * ```js + * import { spawn } from 'node:child_process'; + * const subprocess = spawn('bad_command'); + * + * subprocess.on('error', (err) => { + * console.error('Failed to start subprocess.'); + * }); + * ``` + * + * Certain platforms (macOS, Linux) will use the value of `argv[0]` for the process + * title while others (Windows, SunOS) will use `command`. + * + * Node.js overwrites `argv[0]` with `process.execPath` on startup, so `process.argv[0]` in a Node.js child process will not match the `argv0` parameter passed to `spawn` from the parent. Retrieve + * it with the `process.argv0` property instead. + * + * If the `signal` option is enabled, calling `.abort()` on the corresponding `AbortController` is similar to calling `.kill()` on the child process except + * the error passed to the callback will be an `AbortError`: + * + * ```js + * import { spawn } from 'node:child_process'; + * const controller = new AbortController(); + * const { signal } = controller; + * const grep = spawn('grep', ['ssh'], { signal }); + * grep.on('error', (err) => { + * // This will be called with err being an AbortError if the controller aborts + * }); + * controller.abort(); // Stops the child process + * ``` + * @since v0.1.90 + * @param command The command to run. + * @param args List of string arguments. + */ + function spawn(command: string, options?: SpawnOptionsWithoutStdio): ChildProcessWithoutNullStreams; + function spawn( + command: string, + options: SpawnOptionsWithStdioTuple<StdioPipe, StdioPipe, StdioPipe>, + ): ChildProcessByStdio<Writable, Readable, Readable>; + function spawn( + command: string, + options: SpawnOptionsWithStdioTuple<StdioPipe, StdioPipe, StdioNull>, + ): ChildProcessByStdio<Writable, Readable, null>; + function spawn( + command: string, + options: SpawnOptionsWithStdioTuple<StdioPipe, StdioNull, StdioPipe>, + ): ChildProcessByStdio<Writable, null, Readable>; + function spawn( + command: string, + options: SpawnOptionsWithStdioTuple<StdioNull, StdioPipe, StdioPipe>, + ): ChildProcessByStdio<null, Readable, Readable>; + function spawn( + command: string, + options: SpawnOptionsWithStdioTuple<StdioPipe, StdioNull, StdioNull>, + ): ChildProcessByStdio<Writable, null, null>; + function spawn( + command: string, + options: SpawnOptionsWithStdioTuple<StdioNull, StdioPipe, StdioNull>, + ): ChildProcessByStdio<null, Readable, null>; + function spawn( + command: string, + options: SpawnOptionsWithStdioTuple<StdioNull, StdioNull, StdioPipe>, + ): ChildProcessByStdio<null, null, Readable>; + function spawn( + command: string, + options: SpawnOptionsWithStdioTuple<StdioNull, StdioNull, StdioNull>, + ): ChildProcessByStdio<null, null, null>; + function spawn(command: string, options: SpawnOptions): ChildProcess; + // overloads of spawn with 'args' + function spawn( + command: string, + args?: readonly string[], + options?: SpawnOptionsWithoutStdio, + ): ChildProcessWithoutNullStreams; + function spawn( + command: string, + args: readonly string[], + options: SpawnOptionsWithStdioTuple<StdioPipe, StdioPipe, StdioPipe>, + ): ChildProcessByStdio<Writable, Readable, Readable>; + function spawn( + command: string, + args: readonly string[], + options: SpawnOptionsWithStdioTuple<StdioPipe, StdioPipe, StdioNull>, + ): ChildProcessByStdio<Writable, Readable, null>; + function spawn( + command: string, + args: readonly string[], + options: SpawnOptionsWithStdioTuple<StdioPipe, StdioNull, StdioPipe>, + ): ChildProcessByStdio<Writable, null, Readable>; + function spawn( + command: string, + args: readonly string[], + options: SpawnOptionsWithStdioTuple<StdioNull, StdioPipe, StdioPipe>, + ): ChildProcessByStdio<null, Readable, Readable>; + function spawn( + command: string, + args: readonly string[], + options: SpawnOptionsWithStdioTuple<StdioPipe, StdioNull, StdioNull>, + ): ChildProcessByStdio<Writable, null, null>; + function spawn( + command: string, + args: readonly string[], + options: SpawnOptionsWithStdioTuple<StdioNull, StdioPipe, StdioNull>, + ): ChildProcessByStdio<null, Readable, null>; + function spawn( + command: string, + args: readonly string[], + options: SpawnOptionsWithStdioTuple<StdioNull, StdioNull, StdioPipe>, + ): ChildProcessByStdio<null, null, Readable>; + function spawn( + command: string, + args: readonly string[], + options: SpawnOptionsWithStdioTuple<StdioNull, StdioNull, StdioNull>, + ): ChildProcessByStdio<null, null, null>; + function spawn(command: string, args: readonly string[], options: SpawnOptions): ChildProcess; + interface ExecOptions extends CommonOptions { + shell?: string | undefined; + signal?: AbortSignal | undefined; + maxBuffer?: number | undefined; + killSignal?: NodeJS.Signals | number | undefined; + encoding?: string | null | undefined; + } + interface ExecOptionsWithStringEncoding extends ExecOptions { + encoding?: BufferEncoding | undefined; + } + interface ExecOptionsWithBufferEncoding extends ExecOptions { + encoding: "buffer" | null; // specify `null`. + } + // TODO: Just Plain Wrong™ (see also nodejs/node#57392) + interface ExecException extends Error { + cmd?: string; + killed?: boolean; + code?: number; + signal?: NodeJS.Signals; + stdout?: string; + stderr?: string; + } + /** + * Spawns a shell then executes the `command` within that shell, buffering any + * generated output. The `command` string passed to the exec function is processed + * directly by the shell and special characters (vary based on [shell](https://en.wikipedia.org/wiki/List_of_command-line_interpreters)) + * need to be dealt with accordingly: + * + * ```js + * import { exec } from 'node:child_process'; + * + * exec('"/path/to/test file/test.sh" arg1 arg2'); + * // Double quotes are used so that the space in the path is not interpreted as + * // a delimiter of multiple arguments. + * + * exec('echo "The \\$HOME variable is $HOME"'); + * // The $HOME variable is escaped in the first instance, but not in the second. + * ``` + * + * **Never pass unsanitized user input to this function. Any input containing shell** + * **metacharacters may be used to trigger arbitrary command execution.** + * + * If a `callback` function is provided, it is called with the arguments `(error, stdout, stderr)`. On success, `error` will be `null`. On error, `error` will be an instance of `Error`. The + * `error.code` property will be + * the exit code of the process. By convention, any exit code other than `0` indicates an error. `error.signal` will be the signal that terminated the + * process. + * + * The `stdout` and `stderr` arguments passed to the callback will contain the + * stdout and stderr output of the child process. By default, Node.js will decode + * the output as UTF-8 and pass strings to the callback. The `encoding` option + * can be used to specify the character encoding used to decode the stdout and + * stderr output. If `encoding` is `'buffer'`, or an unrecognized character + * encoding, `Buffer` objects will be passed to the callback instead. + * + * ```js + * import { exec } from 'node:child_process'; + * exec('cat *.js missing_file | wc -l', (error, stdout, stderr) => { + * if (error) { + * console.error(`exec error: ${error}`); + * return; + * } + * console.log(`stdout: ${stdout}`); + * console.error(`stderr: ${stderr}`); + * }); + * ``` + * + * If `timeout` is greater than `0`, the parent will send the signal + * identified by the `killSignal` property (the default is `'SIGTERM'`) if the + * child runs longer than `timeout` milliseconds. + * + * Unlike the [`exec(3)`](http://man7.org/linux/man-pages/man3/exec.3.html) POSIX system call, `child_process.exec()` does not replace + * the existing process and uses a shell to execute the command. + * + * If this method is invoked as its `util.promisify()` ed version, it returns + * a `Promise` for an `Object` with `stdout` and `stderr` properties. The returned `ChildProcess` instance is attached to the `Promise` as a `child` property. In + * case of an error (including any error resulting in an exit code other than 0), a + * rejected promise is returned, with the same `error` object given in the + * callback, but with two additional properties `stdout` and `stderr`. + * + * ```js + * import util from 'node:util'; + * import child_process from 'node:child_process'; + * const exec = util.promisify(child_process.exec); + * + * async function lsExample() { + * const { stdout, stderr } = await exec('ls'); + * console.log('stdout:', stdout); + * console.error('stderr:', stderr); + * } + * lsExample(); + * ``` + * + * If the `signal` option is enabled, calling `.abort()` on the corresponding `AbortController` is similar to calling `.kill()` on the child process except + * the error passed to the callback will be an `AbortError`: + * + * ```js + * import { exec } from 'node:child_process'; + * const controller = new AbortController(); + * const { signal } = controller; + * const child = exec('grep ssh', { signal }, (error) => { + * console.error(error); // an AbortError + * }); + * controller.abort(); + * ``` + * @since v0.1.90 + * @param command The command to run, with space-separated arguments. + * @param callback called with the output when process terminates. + */ + function exec( + command: string, + callback?: (error: ExecException | null, stdout: string, stderr: string) => void, + ): ChildProcess; + // `options` with `"buffer"` or `null` for `encoding` means stdout/stderr are definitely `Buffer`. + function exec( + command: string, + options: ExecOptionsWithBufferEncoding, + callback?: (error: ExecException | null, stdout: NonSharedBuffer, stderr: NonSharedBuffer) => void, + ): ChildProcess; + // `options` with well-known or absent `encoding` means stdout/stderr are definitely `string`. + function exec( + command: string, + options: ExecOptionsWithStringEncoding, + callback?: (error: ExecException | null, stdout: string, stderr: string) => void, + ): ChildProcess; + // fallback if nothing else matches. Worst case is always `string | Buffer`. + function exec( + command: string, + options: ExecOptions | undefined | null, + callback?: ( + error: ExecException | null, + stdout: string | NonSharedBuffer, + stderr: string | NonSharedBuffer, + ) => void, + ): ChildProcess; + interface PromiseWithChild<T> extends Promise<T> { + child: ChildProcess; + } + namespace exec { + function __promisify__(command: string): PromiseWithChild<{ + stdout: string; + stderr: string; + }>; + function __promisify__( + command: string, + options: ExecOptionsWithBufferEncoding, + ): PromiseWithChild<{ + stdout: NonSharedBuffer; + stderr: NonSharedBuffer; + }>; + function __promisify__( + command: string, + options: ExecOptionsWithStringEncoding, + ): PromiseWithChild<{ + stdout: string; + stderr: string; + }>; + function __promisify__( + command: string, + options: ExecOptions | undefined | null, + ): PromiseWithChild<{ + stdout: string | NonSharedBuffer; + stderr: string | NonSharedBuffer; + }>; + } + interface ExecFileOptions extends CommonOptions, Abortable { + maxBuffer?: number | undefined; + killSignal?: NodeJS.Signals | number | undefined; + windowsVerbatimArguments?: boolean | undefined; + shell?: boolean | string | undefined; + signal?: AbortSignal | undefined; + encoding?: string | null | undefined; + } + interface ExecFileOptionsWithStringEncoding extends ExecFileOptions { + encoding?: BufferEncoding | undefined; + } + interface ExecFileOptionsWithBufferEncoding extends ExecFileOptions { + encoding: "buffer" | null; + } + /** @deprecated Use `ExecFileOptions` instead. */ + interface ExecFileOptionsWithOtherEncoding extends ExecFileOptions {} + // TODO: execFile exceptions can take many forms... this accurately describes none of them + type ExecFileException = + & Omit<ExecException, "code"> + & Omit<NodeJS.ErrnoException, "code"> + & { code?: string | number | null }; + /** + * The `child_process.execFile()` function is similar to {@link exec} except that it does not spawn a shell by default. Rather, the specified + * executable `file` is spawned directly as a new process making it slightly more + * efficient than {@link exec}. + * + * The same options as {@link exec} are supported. Since a shell is + * not spawned, behaviors such as I/O redirection and file globbing are not + * supported. + * + * ```js + * import { execFile } from 'node:child_process'; + * const child = execFile('node', ['--version'], (error, stdout, stderr) => { + * if (error) { + * throw error; + * } + * console.log(stdout); + * }); + * ``` + * + * The `stdout` and `stderr` arguments passed to the callback will contain the + * stdout and stderr output of the child process. By default, Node.js will decode + * the output as UTF-8 and pass strings to the callback. The `encoding` option + * can be used to specify the character encoding used to decode the stdout and + * stderr output. If `encoding` is `'buffer'`, or an unrecognized character + * encoding, `Buffer` objects will be passed to the callback instead. + * + * If this method is invoked as its `util.promisify()` ed version, it returns + * a `Promise` for an `Object` with `stdout` and `stderr` properties. The returned `ChildProcess` instance is attached to the `Promise` as a `child` property. In + * case of an error (including any error resulting in an exit code other than 0), a + * rejected promise is returned, with the same `error` object given in the + * callback, but with two additional properties `stdout` and `stderr`. + * + * ```js + * import util from 'node:util'; + * import child_process from 'node:child_process'; + * const execFile = util.promisify(child_process.execFile); + * async function getVersion() { + * const { stdout } = await execFile('node', ['--version']); + * console.log(stdout); + * } + * getVersion(); + * ``` + * + * **If the `shell` option is enabled, do not pass unsanitized user input to this** + * **function. Any input containing shell metacharacters may be used to trigger** + * **arbitrary command execution.** + * + * If the `signal` option is enabled, calling `.abort()` on the corresponding `AbortController` is similar to calling `.kill()` on the child process except + * the error passed to the callback will be an `AbortError`: + * + * ```js + * import { execFile } from 'node:child_process'; + * const controller = new AbortController(); + * const { signal } = controller; + * const child = execFile('node', ['--version'], { signal }, (error) => { + * console.error(error); // an AbortError + * }); + * controller.abort(); + * ``` + * @since v0.1.91 + * @param file The name or path of the executable file to run. + * @param args List of string arguments. + * @param callback Called with the output when process terminates. + */ + // no `options` definitely means stdout/stderr are `string`. + function execFile( + file: string, + callback?: (error: ExecFileException | null, stdout: string, stderr: string) => void, + ): ChildProcess; + function execFile( + file: string, + args: readonly string[] | undefined | null, + callback?: (error: ExecFileException | null, stdout: string, stderr: string) => void, + ): ChildProcess; + // `options` with `"buffer"` or `null` for `encoding` means stdout/stderr are definitely `Buffer`. + function execFile( + file: string, + options: ExecFileOptionsWithBufferEncoding, + callback?: (error: ExecFileException | null, stdout: NonSharedBuffer, stderr: NonSharedBuffer) => void, + ): ChildProcess; + function execFile( + file: string, + args: readonly string[] | undefined | null, + options: ExecFileOptionsWithBufferEncoding, + callback?: (error: ExecFileException | null, stdout: NonSharedBuffer, stderr: NonSharedBuffer) => void, + ): ChildProcess; + // `options` with well-known or absent `encoding` means stdout/stderr are definitely `string`. + function execFile( + file: string, + options: ExecFileOptionsWithStringEncoding, + callback?: (error: ExecFileException | null, stdout: string, stderr: string) => void, + ): ChildProcess; + function execFile( + file: string, + args: readonly string[] | undefined | null, + options: ExecFileOptionsWithStringEncoding, + callback?: (error: ExecFileException | null, stdout: string, stderr: string) => void, + ): ChildProcess; + // fallback if nothing else matches. Worst case is always `string | Buffer`. + function execFile( + file: string, + options: ExecFileOptions | undefined | null, + callback: + | (( + error: ExecFileException | null, + stdout: string | NonSharedBuffer, + stderr: string | NonSharedBuffer, + ) => void) + | undefined + | null, + ): ChildProcess; + function execFile( + file: string, + args: readonly string[] | undefined | null, + options: ExecFileOptions | undefined | null, + callback: + | (( + error: ExecFileException | null, + stdout: string | NonSharedBuffer, + stderr: string | NonSharedBuffer, + ) => void) + | undefined + | null, + ): ChildProcess; + namespace execFile { + function __promisify__(file: string): PromiseWithChild<{ + stdout: string; + stderr: string; + }>; + function __promisify__( + file: string, + args: readonly string[] | undefined | null, + ): PromiseWithChild<{ + stdout: string; + stderr: string; + }>; + function __promisify__( + file: string, + options: ExecFileOptionsWithBufferEncoding, + ): PromiseWithChild<{ + stdout: NonSharedBuffer; + stderr: NonSharedBuffer; + }>; + function __promisify__( + file: string, + args: readonly string[] | undefined | null, + options: ExecFileOptionsWithBufferEncoding, + ): PromiseWithChild<{ + stdout: NonSharedBuffer; + stderr: NonSharedBuffer; + }>; + function __promisify__( + file: string, + options: ExecFileOptionsWithStringEncoding, + ): PromiseWithChild<{ + stdout: string; + stderr: string; + }>; + function __promisify__( + file: string, + args: readonly string[] | undefined | null, + options: ExecFileOptionsWithStringEncoding, + ): PromiseWithChild<{ + stdout: string; + stderr: string; + }>; + function __promisify__( + file: string, + options: ExecFileOptions | undefined | null, + ): PromiseWithChild<{ + stdout: string | NonSharedBuffer; + stderr: string | NonSharedBuffer; + }>; + function __promisify__( + file: string, + args: readonly string[] | undefined | null, + options: ExecFileOptions | undefined | null, + ): PromiseWithChild<{ + stdout: string | NonSharedBuffer; + stderr: string | NonSharedBuffer; + }>; + } + interface ForkOptions extends ProcessEnvOptions, MessagingOptions, Abortable { + execPath?: string | undefined; + execArgv?: string[] | undefined; + silent?: boolean | undefined; + /** + * Can be set to 'pipe', 'inherit', 'overlapped', or 'ignore', or an array of these strings. + * If passed as an array, the first element is used for `stdin`, the second for + * `stdout`, and the third for `stderr`. A fourth element can be used to + * specify the `stdio` behavior beyond the standard streams. See + * {@link ChildProcess.stdio} for more information. + * + * @default 'pipe' + */ + stdio?: StdioOptions | undefined; + detached?: boolean | undefined; + windowsVerbatimArguments?: boolean | undefined; + } + /** + * The `child_process.fork()` method is a special case of {@link spawn} used specifically to spawn new Node.js processes. + * Like {@link spawn}, a `ChildProcess` object is returned. The + * returned `ChildProcess` will have an additional communication channel + * built-in that allows messages to be passed back and forth between the parent and + * child. See `subprocess.send()` for details. + * + * Keep in mind that spawned Node.js child processes are + * independent of the parent with exception of the IPC communication channel + * that is established between the two. Each process has its own memory, with + * their own V8 instances. Because of the additional resource allocations + * required, spawning a large number of child Node.js processes is not + * recommended. + * + * By default, `child_process.fork()` will spawn new Node.js instances using the `process.execPath` of the parent process. The `execPath` property in the `options` object allows for an alternative + * execution path to be used. + * + * Node.js processes launched with a custom `execPath` will communicate with the + * parent process using the file descriptor (fd) identified using the + * environment variable `NODE_CHANNEL_FD` on the child process. + * + * Unlike the [`fork(2)`](http://man7.org/linux/man-pages/man2/fork.2.html) POSIX system call, `child_process.fork()` does not clone the + * current process. + * + * The `shell` option available in {@link spawn} is not supported by `child_process.fork()` and will be ignored if set. + * + * If the `signal` option is enabled, calling `.abort()` on the corresponding `AbortController` is similar to calling `.kill()` on the child process except + * the error passed to the callback will be an `AbortError`: + * + * ```js + * if (process.argv[2] === 'child') { + * setTimeout(() => { + * console.log(`Hello from ${process.argv[2]}!`); + * }, 1_000); + * } else { + * import { fork } from 'node:child_process'; + * const controller = new AbortController(); + * const { signal } = controller; + * const child = fork(__filename, ['child'], { signal }); + * child.on('error', (err) => { + * // This will be called with err being an AbortError if the controller aborts + * }); + * controller.abort(); // Stops the child process + * } + * ``` + * @since v0.5.0 + * @param modulePath The module to run in the child. + * @param args List of string arguments. + */ + function fork(modulePath: string | URL, options?: ForkOptions): ChildProcess; + function fork(modulePath: string | URL, args?: readonly string[], options?: ForkOptions): ChildProcess; + interface SpawnSyncOptions extends CommonSpawnOptions { + input?: string | NodeJS.ArrayBufferView | undefined; + maxBuffer?: number | undefined; + encoding?: BufferEncoding | "buffer" | null | undefined; + } + interface SpawnSyncOptionsWithStringEncoding extends SpawnSyncOptions { + encoding: BufferEncoding; + } + interface SpawnSyncOptionsWithBufferEncoding extends SpawnSyncOptions { + encoding?: "buffer" | null | undefined; + } + interface SpawnSyncReturns<T> { + pid: number; + output: Array<T | null>; + stdout: T; + stderr: T; + status: number | null; + signal: NodeJS.Signals | null; + error?: Error; + } + /** + * The `child_process.spawnSync()` method is generally identical to {@link spawn} with the exception that the function will not return + * until the child process has fully closed. When a timeout has been encountered + * and `killSignal` is sent, the method won't return until the process has + * completely exited. If the process intercepts and handles the `SIGTERM` signal + * and doesn't exit, the parent process will wait until the child process has + * exited. + * + * **If the `shell` option is enabled, do not pass unsanitized user input to this** + * **function. Any input containing shell metacharacters may be used to trigger** + * **arbitrary command execution.** + * @since v0.11.12 + * @param command The command to run. + * @param args List of string arguments. + */ + function spawnSync(command: string): SpawnSyncReturns<NonSharedBuffer>; + function spawnSync(command: string, options: SpawnSyncOptionsWithStringEncoding): SpawnSyncReturns<string>; + function spawnSync(command: string, options: SpawnSyncOptionsWithBufferEncoding): SpawnSyncReturns<NonSharedBuffer>; + function spawnSync(command: string, options?: SpawnSyncOptions): SpawnSyncReturns<string | NonSharedBuffer>; + function spawnSync(command: string, args: readonly string[]): SpawnSyncReturns<NonSharedBuffer>; + function spawnSync( + command: string, + args: readonly string[], + options: SpawnSyncOptionsWithStringEncoding, + ): SpawnSyncReturns<string>; + function spawnSync( + command: string, + args: readonly string[], + options: SpawnSyncOptionsWithBufferEncoding, + ): SpawnSyncReturns<NonSharedBuffer>; + function spawnSync( + command: string, + args?: readonly string[], + options?: SpawnSyncOptions, + ): SpawnSyncReturns<string | NonSharedBuffer>; + interface CommonExecOptions extends CommonOptions { + input?: string | NodeJS.ArrayBufferView | undefined; + /** + * Can be set to 'pipe', 'inherit, or 'ignore', or an array of these strings. + * If passed as an array, the first element is used for `stdin`, the second for + * `stdout`, and the third for `stderr`. A fourth element can be used to + * specify the `stdio` behavior beyond the standard streams. See + * {@link ChildProcess.stdio} for more information. + * + * @default 'pipe' + */ + stdio?: StdioOptions | undefined; + killSignal?: NodeJS.Signals | number | undefined; + maxBuffer?: number | undefined; + encoding?: BufferEncoding | "buffer" | null | undefined; + } + interface ExecSyncOptions extends CommonExecOptions { + shell?: string | undefined; + } + interface ExecSyncOptionsWithStringEncoding extends ExecSyncOptions { + encoding: BufferEncoding; + } + interface ExecSyncOptionsWithBufferEncoding extends ExecSyncOptions { + encoding?: "buffer" | null | undefined; + } + /** + * The `child_process.execSync()` method is generally identical to {@link exec} with the exception that the method will not return + * until the child process has fully closed. When a timeout has been encountered + * and `killSignal` is sent, the method won't return until the process has + * completely exited. If the child process intercepts and handles the `SIGTERM` signal and doesn't exit, the parent process will wait until the child process + * has exited. + * + * If the process times out or has a non-zero exit code, this method will throw. + * The `Error` object will contain the entire result from {@link spawnSync}. + * + * **Never pass unsanitized user input to this function. Any input containing shell** + * **metacharacters may be used to trigger arbitrary command execution.** + * @since v0.11.12 + * @param command The command to run. + * @return The stdout from the command. + */ + function execSync(command: string): NonSharedBuffer; + function execSync(command: string, options: ExecSyncOptionsWithStringEncoding): string; + function execSync(command: string, options: ExecSyncOptionsWithBufferEncoding): NonSharedBuffer; + function execSync(command: string, options?: ExecSyncOptions): string | NonSharedBuffer; + interface ExecFileSyncOptions extends CommonExecOptions { + shell?: boolean | string | undefined; + } + interface ExecFileSyncOptionsWithStringEncoding extends ExecFileSyncOptions { + encoding: BufferEncoding; + } + interface ExecFileSyncOptionsWithBufferEncoding extends ExecFileSyncOptions { + encoding?: "buffer" | null | undefined; // specify `null`. + } + /** + * The `child_process.execFileSync()` method is generally identical to {@link execFile} with the exception that the method will not + * return until the child process has fully closed. When a timeout has been + * encountered and `killSignal` is sent, the method won't return until the process + * has completely exited. + * + * If the child process intercepts and handles the `SIGTERM` signal and + * does not exit, the parent process will still wait until the child process has + * exited. + * + * If the process times out or has a non-zero exit code, this method will throw an `Error` that will include the full result of the underlying {@link spawnSync}. + * + * **If the `shell` option is enabled, do not pass unsanitized user input to this** + * **function. Any input containing shell metacharacters may be used to trigger** + * **arbitrary command execution.** + * @since v0.11.12 + * @param file The name or path of the executable file to run. + * @param args List of string arguments. + * @return The stdout from the command. + */ + function execFileSync(file: string): NonSharedBuffer; + function execFileSync(file: string, options: ExecFileSyncOptionsWithStringEncoding): string; + function execFileSync(file: string, options: ExecFileSyncOptionsWithBufferEncoding): NonSharedBuffer; + function execFileSync(file: string, options?: ExecFileSyncOptions): string | NonSharedBuffer; + function execFileSync(file: string, args: readonly string[]): NonSharedBuffer; + function execFileSync( + file: string, + args: readonly string[], + options: ExecFileSyncOptionsWithStringEncoding, + ): string; + function execFileSync( + file: string, + args: readonly string[], + options: ExecFileSyncOptionsWithBufferEncoding, + ): NonSharedBuffer; + function execFileSync( + file: string, + args?: readonly string[], + options?: ExecFileSyncOptions, + ): string | NonSharedBuffer; +} +declare module "child_process" { + export * from "node:child_process"; +} diff --git a/server/node_modules/@types/node/cluster.d.ts b/server/node_modules/@types/node/cluster.d.ts new file mode 100644 index 0000000..4e5efbf --- /dev/null +++ b/server/node_modules/@types/node/cluster.d.ts @@ -0,0 +1,486 @@ +/** + * Clusters of Node.js processes can be used to run multiple instances of Node.js + * that can distribute workloads among their application threads. When process isolation + * is not needed, use the [`worker_threads`](https://nodejs.org/docs/latest-v25.x/api/worker_threads.html) + * module instead, which allows running multiple application threads within a single Node.js instance. + * + * The cluster module allows easy creation of child processes that all share + * server ports. + * + * ```js + * import cluster from 'node:cluster'; + * import http from 'node:http'; + * import { availableParallelism } from 'node:os'; + * import process from 'node:process'; + * + * const numCPUs = availableParallelism(); + * + * if (cluster.isPrimary) { + * console.log(`Primary ${process.pid} is running`); + * + * // Fork workers. + * for (let i = 0; i < numCPUs; i++) { + * cluster.fork(); + * } + * + * cluster.on('exit', (worker, code, signal) => { + * console.log(`worker ${worker.process.pid} died`); + * }); + * } else { + * // Workers can share any TCP connection + * // In this case it is an HTTP server + * http.createServer((req, res) => { + * res.writeHead(200); + * res.end('hello world\n'); + * }).listen(8000); + * + * console.log(`Worker ${process.pid} started`); + * } + * ``` + * + * Running Node.js will now share port 8000 between the workers: + * + * ```console + * $ node server.js + * Primary 3596 is running + * Worker 4324 started + * Worker 4520 started + * Worker 6056 started + * Worker 5644 started + * ``` + * + * On Windows, it is not yet possible to set up a named pipe server in a worker. + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/cluster.js) + */ +declare module "node:cluster" { + import * as child_process from "node:child_process"; + import { EventEmitter, InternalEventEmitter } from "node:events"; + class Worker implements EventEmitter { + constructor(options?: cluster.WorkerOptions); + /** + * Each new worker is given its own unique id, this id is stored in the `id`. + * + * While a worker is alive, this is the key that indexes it in `cluster.workers`. + * @since v0.8.0 + */ + id: number; + /** + * All workers are created using [`child_process.fork()`](https://nodejs.org/docs/latest-v25.x/api/child_process.html#child_processforkmodulepath-args-options), the returned object + * from this function is stored as `.process`. In a worker, the global `process` is stored. + * + * See: [Child Process module](https://nodejs.org/docs/latest-v25.x/api/child_process.html#child_processforkmodulepath-args-options). + * + * Workers will call `process.exit(0)` if the `'disconnect'` event occurs + * on `process` and `.exitedAfterDisconnect` is not `true`. This protects against + * accidental disconnection. + * @since v0.7.0 + */ + process: child_process.ChildProcess; + /** + * Send a message to a worker or primary, optionally with a handle. + * + * In the primary, this sends a message to a specific worker. It is identical to [`ChildProcess.send()`](https://nodejs.org/docs/latest-v25.x/api/child_process.html#subprocesssendmessage-sendhandle-options-callback). + * + * In a worker, this sends a message to the primary. It is identical to `process.send()`. + * + * This example will echo back all messages from the primary: + * + * ```js + * if (cluster.isPrimary) { + * const worker = cluster.fork(); + * worker.send('hi there'); + * + * } else if (cluster.isWorker) { + * process.on('message', (msg) => { + * process.send(msg); + * }); + * } + * ``` + * @since v0.7.0 + * @param options The `options` argument, if present, is an object used to parameterize the sending of certain types of handles. + */ + send(message: child_process.Serializable, callback?: (error: Error | null) => void): boolean; + send( + message: child_process.Serializable, + sendHandle: child_process.SendHandle, + callback?: (error: Error | null) => void, + ): boolean; + send( + message: child_process.Serializable, + sendHandle: child_process.SendHandle, + options?: child_process.MessageOptions, + callback?: (error: Error | null) => void, + ): boolean; + /** + * This function will kill the worker. In the primary worker, it does this by + * disconnecting the `worker.process`, and once disconnected, killing with `signal`. In the worker, it does it by killing the process with `signal`. + * + * The `kill()` function kills the worker process without waiting for a graceful + * disconnect, it has the same behavior as `worker.process.kill()`. + * + * This method is aliased as `worker.destroy()` for backwards compatibility. + * + * In a worker, `process.kill()` exists, but it is not this function; + * it is [`kill()`](https://nodejs.org/docs/latest-v25.x/api/process.html#processkillpid-signal). + * @since v0.9.12 + * @param [signal='SIGTERM'] Name of the kill signal to send to the worker process. + */ + kill(signal?: string): void; + destroy(signal?: string): void; + /** + * In a worker, this function will close all servers, wait for the `'close'` event + * on those servers, and then disconnect the IPC channel. + * + * In the primary, an internal message is sent to the worker causing it to call `.disconnect()` on itself. + * + * Causes `.exitedAfterDisconnect` to be set. + * + * After a server is closed, it will no longer accept new connections, + * but connections may be accepted by any other listening worker. Existing + * connections will be allowed to close as usual. When no more connections exist, + * see `server.close()`, the IPC channel to the worker will close allowing it + * to die gracefully. + * + * The above applies _only_ to server connections, client connections are not + * automatically closed by workers, and disconnect does not wait for them to close + * before exiting. + * + * In a worker, `process.disconnect` exists, but it is not this function; + * it is `disconnect()`. + * + * Because long living server connections may block workers from disconnecting, it + * may be useful to send a message, so application specific actions may be taken to + * close them. It also may be useful to implement a timeout, killing a worker if + * the `'disconnect'` event has not been emitted after some time. + * + * ```js + * import net from 'node:net'; + * + * if (cluster.isPrimary) { + * const worker = cluster.fork(); + * let timeout; + * + * worker.on('listening', (address) => { + * worker.send('shutdown'); + * worker.disconnect(); + * timeout = setTimeout(() => { + * worker.kill(); + * }, 2000); + * }); + * + * worker.on('disconnect', () => { + * clearTimeout(timeout); + * }); + * + * } else if (cluster.isWorker) { + * const server = net.createServer((socket) => { + * // Connections never end + * }); + * + * server.listen(8000); + * + * process.on('message', (msg) => { + * if (msg === 'shutdown') { + * // Initiate graceful close of any connections to server + * } + * }); + * } + * ``` + * @since v0.7.7 + * @return A reference to `worker`. + */ + disconnect(): this; + /** + * This function returns `true` if the worker is connected to its primary via its + * IPC channel, `false` otherwise. A worker is connected to its primary after it + * has been created. It is disconnected after the `'disconnect'` event is emitted. + * @since v0.11.14 + */ + isConnected(): boolean; + /** + * This function returns `true` if the worker's process has terminated (either + * because of exiting or being signaled). Otherwise, it returns `false`. + * + * ```js + * import cluster from 'node:cluster'; + * import http from 'node:http'; + * import { availableParallelism } from 'node:os'; + * import process from 'node:process'; + * + * const numCPUs = availableParallelism(); + * + * if (cluster.isPrimary) { + * console.log(`Primary ${process.pid} is running`); + * + * // Fork workers. + * for (let i = 0; i < numCPUs; i++) { + * cluster.fork(); + * } + * + * cluster.on('fork', (worker) => { + * console.log('worker is dead:', worker.isDead()); + * }); + * + * cluster.on('exit', (worker, code, signal) => { + * console.log('worker is dead:', worker.isDead()); + * }); + * } else { + * // Workers can share any TCP connection. In this case, it is an HTTP server. + * http.createServer((req, res) => { + * res.writeHead(200); + * res.end(`Current process\n ${process.pid}`); + * process.kill(process.pid); + * }).listen(8000); + * } + * ``` + * @since v0.11.14 + */ + isDead(): boolean; + /** + * This property is `true` if the worker exited due to `.disconnect()`. + * If the worker exited any other way, it is `false`. If the + * worker has not exited, it is `undefined`. + * + * The boolean `worker.exitedAfterDisconnect` allows distinguishing between + * voluntary and accidental exit, the primary may choose not to respawn a worker + * based on this value. + * + * ```js + * cluster.on('exit', (worker, code, signal) => { + * if (worker.exitedAfterDisconnect === true) { + * console.log('Oh, it was just voluntary – no need to worry'); + * } + * }); + * + * // kill worker + * worker.kill(); + * ``` + * @since v6.0.0 + */ + exitedAfterDisconnect: boolean; + } + interface Worker extends InternalEventEmitter<cluster.WorkerEventMap> {} + type _Worker = Worker; + namespace cluster { + interface Worker extends _Worker {} + interface WorkerOptions { + id?: number | undefined; + process?: child_process.ChildProcess | undefined; + state?: string | undefined; + } + interface WorkerEventMap { + "disconnect": []; + "error": [error: Error]; + "exit": [code: number, signal: string]; + "listening": [address: Address]; + "message": [message: any, handle: child_process.SendHandle]; + "online": []; + } + interface ClusterSettings { + /** + * List of string arguments passed to the Node.js executable. + * @default process.execArgv + */ + execArgv?: string[] | undefined; + /** + * File path to worker file. + * @default process.argv[1] + */ + exec?: string | undefined; + /** + * String arguments passed to worker. + * @default process.argv.slice(2) + */ + args?: readonly string[] | undefined; + /** + * Whether or not to send output to parent's stdio. + * @default false + */ + silent?: boolean | undefined; + /** + * Configures the stdio of forked processes. Because the cluster module relies on IPC to function, this configuration must + * contain an `'ipc'` entry. When this option is provided, it overrides `silent`. See [`child_prcess.spawn()`](https://nodejs.org/docs/latest-v25.x/api/child_process.html#child_processspawncommand-args-options)'s + * [`stdio`](https://nodejs.org/docs/latest-v25.x/api/child_process.html#optionsstdio). + */ + stdio?: any[] | undefined; + /** + * Sets the user identity of the process. (See [`setuid(2)`](https://man7.org/linux/man-pages/man2/setuid.2.html).) + */ + uid?: number | undefined; + /** + * Sets the group identity of the process. (See [`setgid(2)`](https://man7.org/linux/man-pages/man2/setgid.2.html).) + */ + gid?: number | undefined; + /** + * Sets inspector port of worker. This can be a number, or a function that takes no arguments and returns a number. + * By default each worker gets its own port, incremented from the primary's `process.debugPort`. + */ + inspectPort?: number | (() => number) | undefined; + /** + * Specify the kind of serialization used for sending messages between processes. Possible values are `'json'` and `'advanced'`. + * See [Advanced serialization for `child_process`](https://nodejs.org/docs/latest-v25.x/api/child_process.html#advanced-serialization) for more details. + * @default false + */ + serialization?: "json" | "advanced" | undefined; + /** + * Current working directory of the worker process. + * @default undefined (inherits from parent process) + */ + cwd?: string | undefined; + /** + * Hide the forked processes console window that would normally be created on Windows systems. + * @default false + */ + windowsHide?: boolean | undefined; + } + interface Address { + address: string; + port: number; + /** + * The `addressType` is one of: + * + * * `4` (TCPv4) + * * `6` (TCPv6) + * * `-1` (Unix domain socket) + * * `'udp4'` or `'udp6'` (UDPv4 or UDPv6) + */ + addressType: 4 | 6 | -1 | "udp4" | "udp6"; + } + interface ClusterEventMap { + "disconnect": [worker: Worker]; + "exit": [worker: Worker, code: number, signal: string]; + "fork": [worker: Worker]; + "listening": [worker: Worker, address: Address]; + "message": [worker: Worker, message: any, handle: child_process.SendHandle]; + "online": [worker: Worker]; + "setup": [settings: ClusterSettings]; + } + interface Cluster extends InternalEventEmitter<ClusterEventMap> { + /** + * A `Worker` object contains all public information and method about a worker. + * In the primary it can be obtained using `cluster.workers`. In a worker + * it can be obtained using `cluster.worker`. + * @since v0.7.0 + */ + Worker: typeof Worker; + disconnect(callback?: () => void): void; + /** + * Spawn a new worker process. + * + * This can only be called from the primary process. + * @param env Key/value pairs to add to worker process environment. + * @since v0.6.0 + */ + fork(env?: any): Worker; + /** @deprecated since v16.0.0 - use isPrimary. */ + readonly isMaster: boolean; + /** + * True if the process is a primary. This is determined by the `process.env.NODE_UNIQUE_ID`. If `process.env.NODE_UNIQUE_ID` + * is undefined, then `isPrimary` is `true`. + * @since v16.0.0 + */ + readonly isPrimary: boolean; + /** + * True if the process is not a primary (it is the negation of `cluster.isPrimary`). + * @since v0.6.0 + */ + readonly isWorker: boolean; + /** + * The scheduling policy, either `cluster.SCHED_RR` for round-robin or `cluster.SCHED_NONE` to leave it to the operating system. This is a + * global setting and effectively frozen once either the first worker is spawned, or [`.setupPrimary()`](https://nodejs.org/docs/latest-v25.x/api/cluster.html#clustersetupprimarysettings) + * is called, whichever comes first. + * + * `SCHED_RR` is the default on all operating systems except Windows. Windows will change to `SCHED_RR` once libuv is able to effectively distribute + * IOCP handles without incurring a large performance hit. + * + * `cluster.schedulingPolicy` can also be set through the `NODE_CLUSTER_SCHED_POLICY` environment variable. Valid values are `'rr'` and `'none'`. + * @since v0.11.2 + */ + schedulingPolicy: number; + /** + * After calling [`.setupPrimary()`](https://nodejs.org/docs/latest-v25.x/api/cluster.html#clustersetupprimarysettings) + * (or [`.fork()`](https://nodejs.org/docs/latest-v25.x/api/cluster.html#clusterforkenv)) this settings object will contain + * the settings, including the default values. + * + * This object is not intended to be changed or set manually. + * @since v0.7.1 + */ + readonly settings: ClusterSettings; + /** @deprecated since v16.0.0 - use [`.setupPrimary()`](https://nodejs.org/docs/latest-v25.x/api/cluster.html#clustersetupprimarysettings) instead. */ + setupMaster(settings?: ClusterSettings): void; + /** + * `setupPrimary` is used to change the default 'fork' behavior. Once called, the settings will be present in `cluster.settings`. + * + * Any settings changes only affect future calls to [`.fork()`](https://nodejs.org/docs/latest-v25.x/api/cluster.html#clusterforkenv) + * and have no effect on workers that are already running. + * + * The only attribute of a worker that cannot be set via `.setupPrimary()` is the `env` passed to + * [`.fork()`](https://nodejs.org/docs/latest-v25.x/api/cluster.html#clusterforkenv). + * + * The defaults above apply to the first call only; the defaults for later calls are the current values at the time of + * `cluster.setupPrimary()` is called. + * + * ```js + * import cluster from 'node:cluster'; + * + * cluster.setupPrimary({ + * exec: 'worker.js', + * args: ['--use', 'https'], + * silent: true, + * }); + * cluster.fork(); // https worker + * cluster.setupPrimary({ + * exec: 'worker.js', + * args: ['--use', 'http'], + * }); + * cluster.fork(); // http worker + * ``` + * + * This can only be called from the primary process. + * @since v16.0.0 + */ + setupPrimary(settings?: ClusterSettings): void; + /** + * A reference to the current worker object. Not available in the primary process. + * + * ```js + * import cluster from 'node:cluster'; + * + * if (cluster.isPrimary) { + * console.log('I am primary'); + * cluster.fork(); + * cluster.fork(); + * } else if (cluster.isWorker) { + * console.log(`I am worker #${cluster.worker.id}`); + * } + * ``` + * @since v0.7.0 + */ + readonly worker?: Worker; + /** + * A hash that stores the active worker objects, keyed by `id` field. This makes it easy to loop through all the workers. It is only available in the primary process. + * + * A worker is removed from `cluster.workers` after the worker has disconnected _and_ exited. The order between these two events cannot be determined in advance. However, it + * is guaranteed that the removal from the `cluster.workers` list happens before the last `'disconnect'` or `'exit'` event is emitted. + * + * ```js + * import cluster from 'node:cluster'; + * + * for (const worker of Object.values(cluster.workers)) { + * worker.send('big announcement to all workers'); + * } + * ``` + * @since v0.7.0 + */ + readonly workers?: NodeJS.Dict<Worker>; + readonly SCHED_NONE: number; + readonly SCHED_RR: number; + } + } + var cluster: cluster.Cluster; + export = cluster; +} +declare module "cluster" { + import cluster = require("node:cluster"); + export = cluster; +} diff --git a/server/node_modules/@types/node/compatibility/iterators.d.ts b/server/node_modules/@types/node/compatibility/iterators.d.ts new file mode 100644 index 0000000..156e785 --- /dev/null +++ b/server/node_modules/@types/node/compatibility/iterators.d.ts @@ -0,0 +1,21 @@ +// Backwards-compatible iterator interfaces, augmented with iterator helper methods by lib.esnext.iterator in TypeScript 5.6. +// The IterableIterator interface does not contain these methods, which creates assignability issues in places where IteratorObjects +// are expected (eg. DOM-compatible APIs) if lib.esnext.iterator is loaded. +// Also ensures that iterators returned by the Node API, which inherit from Iterator.prototype, correctly expose the iterator helper methods +// if lib.esnext.iterator is loaded. +// TODO: remove once this package no longer supports TS 5.5, and replace NodeJS.BuiltinIteratorReturn with BuiltinIteratorReturn. + +// Placeholders for TS <5.6 +interface IteratorObject<T, TReturn, TNext> {} +interface AsyncIteratorObject<T, TReturn, TNext> {} + +declare namespace NodeJS { + // Populate iterator methods for TS <5.6 + interface Iterator<T, TReturn, TNext> extends globalThis.Iterator<T, TReturn, TNext> {} + interface AsyncIterator<T, TReturn, TNext> extends globalThis.AsyncIterator<T, TReturn, TNext> {} + + // Polyfill for TS 5.6's instrinsic BuiltinIteratorReturn type, required for DOM-compatible iterators + type BuiltinIteratorReturn = ReturnType<any[][typeof Symbol.iterator]> extends + globalThis.Iterator<any, infer TReturn> ? TReturn + : any; +} diff --git a/server/node_modules/@types/node/console.d.ts b/server/node_modules/@types/node/console.d.ts new file mode 100644 index 0000000..3943442 --- /dev/null +++ b/server/node_modules/@types/node/console.d.ts @@ -0,0 +1,151 @@ +/** + * The `node:console` module provides a simple debugging console that is similar to + * the JavaScript console mechanism provided by web browsers. + * + * The module exports two specific components: + * + * * A `Console` class with methods such as `console.log()`, `console.error()`, and `console.warn()` that can be used to write to any Node.js stream. + * * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v25.x/api/process.html#processstdout) and + * [`process.stderr`](https://nodejs.org/docs/latest-v25.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. + * + * _**Warning**_: The global console object's methods are neither consistently + * synchronous like the browser APIs they resemble, nor are they consistently + * asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v25.x/api/process.html#a-note-on-process-io) for + * more information. + * + * Example using the global `console`: + * + * ```js + * console.log('hello world'); + * // Prints: hello world, to stdout + * console.log('hello %s', 'world'); + * // Prints: hello world, to stdout + * console.error(new Error('Whoops, something bad happened')); + * // Prints error message and stack trace to stderr: + * // Error: Whoops, something bad happened + * // at [eval]:5:15 + * // at Script.runInThisContext (node:vm:132:18) + * // at Object.runInThisContext (node:vm:309:38) + * // at node:internal/process/execution:77:19 + * // at [eval]-wrapper:6:22 + * // at evalScript (node:internal/process/execution:76:60) + * // at node:internal/main/eval_string:23:3 + * + * const name = 'Will Robinson'; + * console.warn(`Danger ${name}! Danger!`); + * // Prints: Danger Will Robinson! Danger!, to stderr + * ``` + * + * Example using the `Console` class: + * + * ```js + * const out = getStreamSomehow(); + * const err = getStreamSomehow(); + * const myConsole = new console.Console(out, err); + * + * myConsole.log('hello world'); + * // Prints: hello world, to out + * myConsole.log('hello %s', 'world'); + * // Prints: hello world, to out + * myConsole.error(new Error('Whoops, something bad happened')); + * // Prints: [Error: Whoops, something bad happened], to err + * + * const name = 'Will Robinson'; + * myConsole.warn(`Danger ${name}! Danger!`); + * // Prints: Danger Will Robinson! Danger!, to err + * ``` + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/console.js) + */ +declare module "node:console" { + import { InspectOptions } from "node:util"; + namespace console { + interface ConsoleOptions { + stdout: NodeJS.WritableStream; + stderr?: NodeJS.WritableStream | undefined; + /** + * Ignore errors when writing to the underlying streams. + * @default true + */ + ignoreErrors?: boolean | undefined; + /** + * Set color support for this `Console` instance. Setting to true enables coloring while inspecting + * values. Setting to `false` disables coloring while inspecting values. Setting to `'auto'` makes color + * support depend on the value of the `isTTY` property and the value returned by `getColorDepth()` on the + * respective stream. This option can not be used, if `inspectOptions.colors` is set as well. + * @default 'auto' + */ + colorMode?: boolean | "auto" | undefined; + /** + * Specifies options that are passed along to + * [`util.inspect()`](https://nodejs.org/docs/latest-v25.x/api/util.html#utilinspectobject-options). + */ + inspectOptions?: InspectOptions | ReadonlyMap<NodeJS.WritableStream, InspectOptions> | undefined; + /** + * Set group indentation. + * @default 2 + */ + groupIndentation?: number | undefined; + } + interface Console { + readonly Console: { + prototype: Console; + new(stdout: NodeJS.WritableStream, stderr?: NodeJS.WritableStream, ignoreErrors?: boolean): Console; + new(options: ConsoleOptions): Console; + }; + assert(condition?: unknown, ...data: any[]): void; + clear(): void; + count(label?: string): void; + countReset(label?: string): void; + debug(...data: any[]): void; + dir(item?: any, options?: InspectOptions): void; + dirxml(...data: any[]): void; + error(...data: any[]): void; + group(...data: any[]): void; + groupCollapsed(...data: any[]): void; + groupEnd(): void; + info(...data: any[]): void; + log(...data: any[]): void; + table(tabularData?: any, properties?: string[]): void; + time(label?: string): void; + timeEnd(label?: string): void; + timeLog(label?: string, ...data: any[]): void; + trace(...data: any[]): void; + warn(...data: any[]): void; + /** + * This method does not display anything unless used in the inspector. The `console.profile()` + * method starts a JavaScript CPU profile with an optional label until {@link profileEnd} + * is called. The profile is then added to the Profile panel of the inspector. + * + * ```js + * console.profile('MyLabel'); + * // Some code + * console.profileEnd('MyLabel'); + * // Adds the profile 'MyLabel' to the Profiles panel of the inspector. + * ``` + * @since v8.0.0 + */ + profile(label?: string): void; + /** + * This method does not display anything unless used in the inspector. Stops the current + * JavaScript CPU profiling session if one has been started and prints the report to the + * Profiles panel of the inspector. See {@link profile} for an example. + * + * If this method is called without a label, the most recently started profile is stopped. + * @since v8.0.0 + */ + profileEnd(label?: string): void; + /** + * This method does not display anything unless used in the inspector. The `console.timeStamp()` + * method adds an event with the label `'label'` to the Timeline panel of the inspector. + * @since v8.0.0 + */ + timeStamp(label?: string): void; + } + } + var console: console.Console; + export = console; +} +declare module "console" { + import console = require("node:console"); + export = console; +} diff --git a/server/node_modules/@types/node/constants.d.ts b/server/node_modules/@types/node/constants.d.ts new file mode 100644 index 0000000..c24ad98 --- /dev/null +++ b/server/node_modules/@types/node/constants.d.ts @@ -0,0 +1,20 @@ +/** + * @deprecated The `node:constants` module is deprecated. When requiring access to constants + * relevant to specific Node.js builtin modules, developers should instead refer + * to the `constants` property exposed by the relevant module. For instance, + * `require('node:fs').constants` and `require('node:os').constants`. + */ +declare module "node:constants" { + const constants: + & typeof import("node:os").constants.dlopen + & typeof import("node:os").constants.errno + & typeof import("node:os").constants.priority + & typeof import("node:os").constants.signals + & typeof import("node:fs").constants + & typeof import("node:crypto").constants; + export = constants; +} +declare module "constants" { + import constants = require("node:constants"); + export = constants; +} diff --git a/server/node_modules/@types/node/crypto.d.ts b/server/node_modules/@types/node/crypto.d.ts new file mode 100644 index 0000000..15b46ce --- /dev/null +++ b/server/node_modules/@types/node/crypto.d.ts @@ -0,0 +1,4065 @@ +/** + * The `node:crypto` module provides cryptographic functionality that includes a + * set of wrappers for OpenSSL's hash, HMAC, cipher, decipher, sign, and verify + * functions. + * + * ```js + * const { createHmac } = await import('node:crypto'); + * + * const secret = 'abcdefg'; + * const hash = createHmac('sha256', secret) + * .update('I love cupcakes') + * .digest('hex'); + * console.log(hash); + * // Prints: + * // c0fa1bc00531bd78ef38c628449c5102aeabd49b5dc3a2a516ea6ea959d6658e + * ``` + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/crypto.js) + */ +declare module "node:crypto" { + import { NonSharedBuffer } from "node:buffer"; + import * as stream from "node:stream"; + import { PeerCertificate } from "node:tls"; + /** + * SPKAC is a Certificate Signing Request mechanism originally implemented by + * Netscape and was specified formally as part of HTML5's `keygen` element. + * + * `<keygen>` is deprecated since [HTML 5.2](https://www.w3.org/TR/html52/changes.html#features-removed) and new projects + * should not use this element anymore. + * + * The `node:crypto` module provides the `Certificate` class for working with SPKAC + * data. The most common usage is handling output generated by the HTML5 `<keygen>` element. Node.js uses [OpenSSL's SPKAC + * implementation](https://www.openssl.org/docs/man3.0/man1/openssl-spkac.html) internally. + * @since v0.11.8 + */ + class Certificate { + /** + * ```js + * const { Certificate } = await import('node:crypto'); + * const spkac = getSpkacSomehow(); + * const challenge = Certificate.exportChallenge(spkac); + * console.log(challenge.toString('utf8')); + * // Prints: the challenge as a UTF8 string + * ``` + * @since v9.0.0 + * @param encoding The `encoding` of the `spkac` string. + * @return The challenge component of the `spkac` data structure, which includes a public key and a challenge. + */ + static exportChallenge(spkac: BinaryLike): NonSharedBuffer; + /** + * ```js + * const { Certificate } = await import('node:crypto'); + * const spkac = getSpkacSomehow(); + * const publicKey = Certificate.exportPublicKey(spkac); + * console.log(publicKey); + * // Prints: the public key as <Buffer ...> + * ``` + * @since v9.0.0 + * @param encoding The `encoding` of the `spkac` string. + * @return The public key component of the `spkac` data structure, which includes a public key and a challenge. + */ + static exportPublicKey(spkac: BinaryLike, encoding?: string): NonSharedBuffer; + /** + * ```js + * import { Buffer } from 'node:buffer'; + * const { Certificate } = await import('node:crypto'); + * + * const spkac = getSpkacSomehow(); + * console.log(Certificate.verifySpkac(Buffer.from(spkac))); + * // Prints: true or false + * ``` + * @since v9.0.0 + * @param encoding The `encoding` of the `spkac` string. + * @return `true` if the given `spkac` data structure is valid, `false` otherwise. + */ + static verifySpkac(spkac: NodeJS.ArrayBufferView): boolean; + /** + * @deprecated + * @param spkac + * @returns The challenge component of the `spkac` data structure, + * which includes a public key and a challenge. + */ + exportChallenge(spkac: BinaryLike): NonSharedBuffer; + /** + * @deprecated + * @param spkac + * @param encoding The encoding of the spkac string. + * @returns The public key component of the `spkac` data structure, + * which includes a public key and a challenge. + */ + exportPublicKey(spkac: BinaryLike, encoding?: string): NonSharedBuffer; + /** + * @deprecated + * @param spkac + * @returns `true` if the given `spkac` data structure is valid, + * `false` otherwise. + */ + verifySpkac(spkac: NodeJS.ArrayBufferView): boolean; + } + namespace constants { + // https://nodejs.org/dist/latest-v25.x/docs/api/crypto.html#crypto-constants + const OPENSSL_VERSION_NUMBER: number; + /** Applies multiple bug workarounds within OpenSSL. See https://www.openssl.org/docs/man1.0.2/ssl/SSL_CTX_set_options.html for detail. */ + const SSL_OP_ALL: number; + /** Instructs OpenSSL to allow a non-[EC]DHE-based key exchange mode for TLS v1.3 */ + const SSL_OP_ALLOW_NO_DHE_KEX: number; + /** Allows legacy insecure renegotiation between OpenSSL and unpatched clients or servers. See https://www.openssl.org/docs/man1.0.2/ssl/SSL_CTX_set_options.html. */ + const SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION: number; + /** Attempts to use the server's preferences instead of the client's when selecting a cipher. See https://www.openssl.org/docs/man1.0.2/ssl/SSL_CTX_set_options.html. */ + const SSL_OP_CIPHER_SERVER_PREFERENCE: number; + /** Instructs OpenSSL to use Cisco's version identifier of DTLS_BAD_VER. */ + const SSL_OP_CISCO_ANYCONNECT: number; + /** Instructs OpenSSL to turn on cookie exchange. */ + const SSL_OP_COOKIE_EXCHANGE: number; + /** Instructs OpenSSL to add server-hello extension from an early version of the cryptopro draft. */ + const SSL_OP_CRYPTOPRO_TLSEXT_BUG: number; + /** Instructs OpenSSL to disable a SSL 3.0/TLS 1.0 vulnerability workaround added in OpenSSL 0.9.6d. */ + const SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS: number; + /** Allows initial connection to servers that do not support RI. */ + const SSL_OP_LEGACY_SERVER_CONNECT: number; + /** Instructs OpenSSL to disable support for SSL/TLS compression. */ + const SSL_OP_NO_COMPRESSION: number; + /** Instructs OpenSSL to disable encrypt-then-MAC. */ + const SSL_OP_NO_ENCRYPT_THEN_MAC: number; + const SSL_OP_NO_QUERY_MTU: number; + /** Instructs OpenSSL to disable renegotiation. */ + const SSL_OP_NO_RENEGOTIATION: number; + /** Instructs OpenSSL to always start a new session when performing renegotiation. */ + const SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION: number; + /** Instructs OpenSSL to turn off SSL v2 */ + const SSL_OP_NO_SSLv2: number; + /** Instructs OpenSSL to turn off SSL v3 */ + const SSL_OP_NO_SSLv3: number; + /** Instructs OpenSSL to disable use of RFC4507bis tickets. */ + const SSL_OP_NO_TICKET: number; + /** Instructs OpenSSL to turn off TLS v1 */ + const SSL_OP_NO_TLSv1: number; + /** Instructs OpenSSL to turn off TLS v1.1 */ + const SSL_OP_NO_TLSv1_1: number; + /** Instructs OpenSSL to turn off TLS v1.2 */ + const SSL_OP_NO_TLSv1_2: number; + /** Instructs OpenSSL to turn off TLS v1.3 */ + const SSL_OP_NO_TLSv1_3: number; + /** Instructs OpenSSL server to prioritize ChaCha20-Poly1305 when the client does. This option has no effect if `SSL_OP_CIPHER_SERVER_PREFERENCE` is not enabled. */ + const SSL_OP_PRIORITIZE_CHACHA: number; + /** Instructs OpenSSL to disable version rollback attack detection. */ + const SSL_OP_TLS_ROLLBACK_BUG: number; + const ENGINE_METHOD_RSA: number; + const ENGINE_METHOD_DSA: number; + const ENGINE_METHOD_DH: number; + const ENGINE_METHOD_RAND: number; + const ENGINE_METHOD_EC: number; + const ENGINE_METHOD_CIPHERS: number; + const ENGINE_METHOD_DIGESTS: number; + const ENGINE_METHOD_PKEY_METHS: number; + const ENGINE_METHOD_PKEY_ASN1_METHS: number; + const ENGINE_METHOD_ALL: number; + const ENGINE_METHOD_NONE: number; + const DH_CHECK_P_NOT_SAFE_PRIME: number; + const DH_CHECK_P_NOT_PRIME: number; + const DH_UNABLE_TO_CHECK_GENERATOR: number; + const DH_NOT_SUITABLE_GENERATOR: number; + const RSA_PKCS1_PADDING: number; + const RSA_SSLV23_PADDING: number; + const RSA_NO_PADDING: number; + const RSA_PKCS1_OAEP_PADDING: number; + const RSA_X931_PADDING: number; + const RSA_PKCS1_PSS_PADDING: number; + /** Sets the salt length for RSA_PKCS1_PSS_PADDING to the digest size when signing or verifying. */ + const RSA_PSS_SALTLEN_DIGEST: number; + /** Sets the salt length for RSA_PKCS1_PSS_PADDING to the maximum permissible value when signing data. */ + const RSA_PSS_SALTLEN_MAX_SIGN: number; + /** Causes the salt length for RSA_PKCS1_PSS_PADDING to be determined automatically when verifying a signature. */ + const RSA_PSS_SALTLEN_AUTO: number; + const POINT_CONVERSION_COMPRESSED: number; + const POINT_CONVERSION_UNCOMPRESSED: number; + const POINT_CONVERSION_HYBRID: number; + /** Specifies the built-in default cipher list used by Node.js (colon-separated values). */ + const defaultCoreCipherList: string; + /** Specifies the active default cipher list used by the current Node.js process (colon-separated values). */ + const defaultCipherList: string; + } + interface HashOptions extends stream.TransformOptions { + /** + * For XOF hash functions such as `shake256`, the + * outputLength option can be used to specify the desired output length in bytes. + */ + outputLength?: number | undefined; + } + /** @deprecated since v10.0.0 */ + const fips: boolean; + /** + * Creates and returns a `Hash` object that can be used to generate hash digests + * using the given `algorithm`. Optional `options` argument controls stream + * behavior. For XOF hash functions such as `'shake256'`, the `outputLength` option + * can be used to specify the desired output length in bytes. + * + * The `algorithm` is dependent on the available algorithms supported by the + * version of OpenSSL on the platform. Examples are `'sha256'`, `'sha512'`, etc. + * On recent releases of OpenSSL, `openssl list -digest-algorithms` will + * display the available digest algorithms. + * + * Example: generating the sha256 sum of a file + * + * ```js + * import { + * createReadStream, + * } from 'node:fs'; + * import { argv } from 'node:process'; + * const { + * createHash, + * } = await import('node:crypto'); + * + * const filename = argv[2]; + * + * const hash = createHash('sha256'); + * + * const input = createReadStream(filename); + * input.on('readable', () => { + * // Only one element is going to be produced by the + * // hash stream. + * const data = input.read(); + * if (data) + * hash.update(data); + * else { + * console.log(`${hash.digest('hex')} ${filename}`); + * } + * }); + * ``` + * @since v0.1.92 + * @param options `stream.transform` options + */ + function createHash(algorithm: string, options?: HashOptions): Hash; + /** + * Creates and returns an `Hmac` object that uses the given `algorithm` and `key`. + * Optional `options` argument controls stream behavior. + * + * The `algorithm` is dependent on the available algorithms supported by the + * version of OpenSSL on the platform. Examples are `'sha256'`, `'sha512'`, etc. + * On recent releases of OpenSSL, `openssl list -digest-algorithms` will + * display the available digest algorithms. + * + * The `key` is the HMAC key used to generate the cryptographic HMAC hash. If it is + * a `KeyObject`, its type must be `secret`. If it is a string, please consider `caveats when using strings as inputs to cryptographic APIs`. If it was + * obtained from a cryptographically secure source of entropy, such as {@link randomBytes} or {@link generateKey}, its length should not + * exceed the block size of `algorithm` (e.g., 512 bits for SHA-256). + * + * Example: generating the sha256 HMAC of a file + * + * ```js + * import { + * createReadStream, + * } from 'node:fs'; + * import { argv } from 'node:process'; + * const { + * createHmac, + * } = await import('node:crypto'); + * + * const filename = argv[2]; + * + * const hmac = createHmac('sha256', 'a secret'); + * + * const input = createReadStream(filename); + * input.on('readable', () => { + * // Only one element is going to be produced by the + * // hash stream. + * const data = input.read(); + * if (data) + * hmac.update(data); + * else { + * console.log(`${hmac.digest('hex')} ${filename}`); + * } + * }); + * ``` + * @since v0.1.94 + * @param options `stream.transform` options + */ + function createHmac(algorithm: string, key: BinaryLike | KeyObject, options?: stream.TransformOptions): Hmac; + // https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings + type BinaryToTextEncoding = "base64" | "base64url" | "hex" | "binary"; + type CharacterEncoding = "utf8" | "utf-8" | "utf16le" | "utf-16le" | "latin1"; + type LegacyCharacterEncoding = "ascii" | "binary" | "ucs2" | "ucs-2"; + type Encoding = BinaryToTextEncoding | CharacterEncoding | LegacyCharacterEncoding; + type ECDHKeyFormat = "compressed" | "uncompressed" | "hybrid"; + /** + * The `Hash` class is a utility for creating hash digests of data. It can be + * used in one of two ways: + * + * * As a `stream` that is both readable and writable, where data is written + * to produce a computed hash digest on the readable side, or + * * Using the `hash.update()` and `hash.digest()` methods to produce the + * computed hash. + * + * The {@link createHash} method is used to create `Hash` instances. `Hash`objects are not to be created directly using the `new` keyword. + * + * Example: Using `Hash` objects as streams: + * + * ```js + * const { + * createHash, + * } = await import('node:crypto'); + * + * const hash = createHash('sha256'); + * + * hash.on('readable', () => { + * // Only one element is going to be produced by the + * // hash stream. + * const data = hash.read(); + * if (data) { + * console.log(data.toString('hex')); + * // Prints: + * // 6a2da20943931e9834fc12cfe5bb47bbd9ae43489a30726962b576f4e3993e50 + * } + * }); + * + * hash.write('some data to hash'); + * hash.end(); + * ``` + * + * Example: Using `Hash` and piped streams: + * + * ```js + * import { createReadStream } from 'node:fs'; + * import { stdout } from 'node:process'; + * const { createHash } = await import('node:crypto'); + * + * const hash = createHash('sha256'); + * + * const input = createReadStream('test.js'); + * input.pipe(hash).setEncoding('hex').pipe(stdout); + * ``` + * + * Example: Using the `hash.update()` and `hash.digest()` methods: + * + * ```js + * const { + * createHash, + * } = await import('node:crypto'); + * + * const hash = createHash('sha256'); + * + * hash.update('some data to hash'); + * console.log(hash.digest('hex')); + * // Prints: + * // 6a2da20943931e9834fc12cfe5bb47bbd9ae43489a30726962b576f4e3993e50 + * ``` + * @since v0.1.92 + */ + class Hash extends stream.Transform { + private constructor(); + /** + * Creates a new `Hash` object that contains a deep copy of the internal state + * of the current `Hash` object. + * + * The optional `options` argument controls stream behavior. For XOF hash + * functions such as `'shake256'`, the `outputLength` option can be used to + * specify the desired output length in bytes. + * + * An error is thrown when an attempt is made to copy the `Hash` object after + * its `hash.digest()` method has been called. + * + * ```js + * // Calculate a rolling hash. + * const { + * createHash, + * } = await import('node:crypto'); + * + * const hash = createHash('sha256'); + * + * hash.update('one'); + * console.log(hash.copy().digest('hex')); + * + * hash.update('two'); + * console.log(hash.copy().digest('hex')); + * + * hash.update('three'); + * console.log(hash.copy().digest('hex')); + * + * // Etc. + * ``` + * @since v13.1.0 + * @param options `stream.transform` options + */ + copy(options?: HashOptions): Hash; + /** + * Updates the hash content with the given `data`, the encoding of which + * is given in `inputEncoding`. + * If `encoding` is not provided, and the `data` is a string, an + * encoding of `'utf8'` is enforced. If `data` is a `Buffer`, `TypedArray`, or`DataView`, then `inputEncoding` is ignored. + * + * This can be called many times with new data as it is streamed. + * @since v0.1.92 + * @param inputEncoding The `encoding` of the `data` string. + */ + update(data: BinaryLike): Hash; + update(data: string, inputEncoding: Encoding): Hash; + /** + * Calculates the digest of all of the data passed to be hashed (using the `hash.update()` method). + * If `encoding` is provided a string will be returned; otherwise + * a `Buffer` is returned. + * + * The `Hash` object can not be used again after `hash.digest()` method has been + * called. Multiple calls will cause an error to be thrown. + * @since v0.1.92 + * @param encoding The `encoding` of the return value. + */ + digest(): NonSharedBuffer; + digest(encoding: BinaryToTextEncoding): string; + } + /** + * The `Hmac` class is a utility for creating cryptographic HMAC digests. It can + * be used in one of two ways: + * + * * As a `stream` that is both readable and writable, where data is written + * to produce a computed HMAC digest on the readable side, or + * * Using the `hmac.update()` and `hmac.digest()` methods to produce the + * computed HMAC digest. + * + * The {@link createHmac} method is used to create `Hmac` instances. `Hmac`objects are not to be created directly using the `new` keyword. + * + * Example: Using `Hmac` objects as streams: + * + * ```js + * const { + * createHmac, + * } = await import('node:crypto'); + * + * const hmac = createHmac('sha256', 'a secret'); + * + * hmac.on('readable', () => { + * // Only one element is going to be produced by the + * // hash stream. + * const data = hmac.read(); + * if (data) { + * console.log(data.toString('hex')); + * // Prints: + * // 7fd04df92f636fd450bc841c9418e5825c17f33ad9c87c518115a45971f7f77e + * } + * }); + * + * hmac.write('some data to hash'); + * hmac.end(); + * ``` + * + * Example: Using `Hmac` and piped streams: + * + * ```js + * import { createReadStream } from 'node:fs'; + * import { stdout } from 'node:process'; + * const { + * createHmac, + * } = await import('node:crypto'); + * + * const hmac = createHmac('sha256', 'a secret'); + * + * const input = createReadStream('test.js'); + * input.pipe(hmac).pipe(stdout); + * ``` + * + * Example: Using the `hmac.update()` and `hmac.digest()` methods: + * + * ```js + * const { + * createHmac, + * } = await import('node:crypto'); + * + * const hmac = createHmac('sha256', 'a secret'); + * + * hmac.update('some data to hash'); + * console.log(hmac.digest('hex')); + * // Prints: + * // 7fd04df92f636fd450bc841c9418e5825c17f33ad9c87c518115a45971f7f77e + * ``` + * @since v0.1.94 + */ + class Hmac extends stream.Transform { + private constructor(); + /** + * Updates the `Hmac` content with the given `data`, the encoding of which + * is given in `inputEncoding`. + * If `encoding` is not provided, and the `data` is a string, an + * encoding of `'utf8'` is enforced. If `data` is a `Buffer`, `TypedArray`, or`DataView`, then `inputEncoding` is ignored. + * + * This can be called many times with new data as it is streamed. + * @since v0.1.94 + * @param inputEncoding The `encoding` of the `data` string. + */ + update(data: BinaryLike): Hmac; + update(data: string, inputEncoding: Encoding): Hmac; + /** + * Calculates the HMAC digest of all of the data passed using `hmac.update()`. + * If `encoding` is + * provided a string is returned; otherwise a `Buffer` is returned; + * + * The `Hmac` object can not be used again after `hmac.digest()` has been + * called. Multiple calls to `hmac.digest()` will result in an error being thrown. + * @since v0.1.94 + * @param encoding The `encoding` of the return value. + */ + digest(): NonSharedBuffer; + digest(encoding: BinaryToTextEncoding): string; + } + type KeyFormat = "pem" | "der" | "jwk"; + type KeyObjectType = "secret" | "public" | "private"; + type PublicKeyExportType = "pkcs1" | "spki"; + type PrivateKeyExportType = "pkcs1" | "pkcs8" | "sec1"; + type KeyExportOptions = + | SymmetricKeyExportOptions + | PublicKeyExportOptions + | PrivateKeyExportOptions + | JwkKeyExportOptions; + interface SymmetricKeyExportOptions { + format?: "buffer" | undefined; + } + interface PublicKeyExportOptions<T extends PublicKeyExportType = PublicKeyExportType> { + type: T; + format: Exclude<KeyFormat, "jwk">; + } + interface PrivateKeyExportOptions<T extends PrivateKeyExportType = PrivateKeyExportType> { + type: T; + format: Exclude<KeyFormat, "jwk">; + cipher?: string | undefined; + passphrase?: string | Buffer | undefined; + } + interface JwkKeyExportOptions { + format: "jwk"; + } + interface KeyPairExportOptions< + TPublic extends PublicKeyExportType = PublicKeyExportType, + TPrivate extends PrivateKeyExportType = PrivateKeyExportType, + > { + publicKeyEncoding?: PublicKeyExportOptions<TPublic> | JwkKeyExportOptions | undefined; + privateKeyEncoding?: PrivateKeyExportOptions<TPrivate> | JwkKeyExportOptions | undefined; + } + type KeyExportResult<T, Default> = T extends { format: infer F extends KeyFormat } + ? { der: NonSharedBuffer; jwk: webcrypto.JsonWebKey; pem: string }[F] + : Default; + interface KeyPairExportResult<T extends KeyPairExportOptions> { + publicKey: KeyExportResult<T["publicKeyEncoding"], KeyObject>; + privateKey: KeyExportResult<T["privateKeyEncoding"], KeyObject>; + } + type KeyPairExportCallback<T extends KeyPairExportOptions> = ( + err: Error | null, + publicKey: KeyExportResult<T["publicKeyEncoding"], KeyObject>, + privateKey: KeyExportResult<T["privateKeyEncoding"], KeyObject>, + ) => void; + type MLDSAKeyType = `ml-dsa-${44 | 65 | 87}`; + type MLKEMKeyType = `ml-kem-${1024 | 512 | 768}`; + type SLHDSAKeyType = `slh-dsa-${"sha2" | "shake"}-${128 | 192 | 256}${"f" | "s"}`; + type AsymmetricKeyType = + | "dh" + | "dsa" + | "ec" + | "ed25519" + | "ed448" + | MLDSAKeyType + | MLKEMKeyType + | "rsa-pss" + | "rsa" + | SLHDSAKeyType + | "x25519" + | "x448"; + interface AsymmetricKeyDetails { + /** + * Key size in bits (RSA, DSA). + */ + modulusLength?: number; + /** + * Public exponent (RSA). + */ + publicExponent?: bigint; + /** + * Name of the message digest (RSA-PSS). + */ + hashAlgorithm?: string; + /** + * Name of the message digest used by MGF1 (RSA-PSS). + */ + mgf1HashAlgorithm?: string; + /** + * Minimal salt length in bytes (RSA-PSS). + */ + saltLength?: number; + /** + * Size of q in bits (DSA). + */ + divisorLength?: number; + /** + * Name of the curve (EC). + */ + namedCurve?: string; + } + /** + * Node.js uses a `KeyObject` class to represent a symmetric or asymmetric key, + * and each kind of key exposes different functions. The {@link createSecretKey}, {@link createPublicKey} and {@link createPrivateKey} methods are used to create `KeyObject`instances. `KeyObject` + * objects are not to be created directly using the `new`keyword. + * + * Most applications should consider using the new `KeyObject` API instead of + * passing keys as strings or `Buffer`s due to improved security features. + * + * `KeyObject` instances can be passed to other threads via `postMessage()`. + * The receiver obtains a cloned `KeyObject`, and the `KeyObject` does not need to + * be listed in the `transferList` argument. + * @since v11.6.0 + */ + class KeyObject { + private constructor(); + /** + * Example: Converting a `CryptoKey` instance to a `KeyObject`: + * + * ```js + * const { KeyObject } = await import('node:crypto'); + * const { subtle } = globalThis.crypto; + * + * const key = await subtle.generateKey({ + * name: 'HMAC', + * hash: 'SHA-256', + * length: 256, + * }, true, ['sign', 'verify']); + * + * const keyObject = KeyObject.from(key); + * console.log(keyObject.symmetricKeySize); + * // Prints: 32 (symmetric key size in bytes) + * ``` + * @since v15.0.0 + */ + static from(key: webcrypto.CryptoKey): KeyObject; + /** + * For asymmetric keys, this property represents the type of the key. See the + * supported [asymmetric key types](https://nodejs.org/docs/latest-v25.x/api/crypto.html#asymmetric-key-types). + * + * This property is `undefined` for unrecognized `KeyObject` types and symmetric + * keys. + * @since v11.6.0 + */ + asymmetricKeyType?: AsymmetricKeyType; + /** + * This property exists only on asymmetric keys. Depending on the type of the key, + * this object contains information about the key. None of the information obtained + * through this property can be used to uniquely identify a key or to compromise + * the security of the key. + * + * For RSA-PSS keys, if the key material contains a `RSASSA-PSS-params` sequence, + * the `hashAlgorithm`, `mgf1HashAlgorithm`, and `saltLength` properties will be + * set. + * + * Other key details might be exposed via this API using additional attributes. + * @since v15.7.0 + */ + asymmetricKeyDetails?: AsymmetricKeyDetails; + /** + * For symmetric keys, the following encoding options can be used: + * + * For public keys, the following encoding options can be used: + * + * For private keys, the following encoding options can be used: + * + * The result type depends on the selected encoding format, when PEM the + * result is a string, when DER it will be a buffer containing the data + * encoded as DER, when [JWK](https://tools.ietf.org/html/rfc7517) it will be an object. + * + * When [JWK](https://tools.ietf.org/html/rfc7517) encoding format was selected, all other encoding options are + * ignored. + * + * PKCS#1, SEC1, and PKCS#8 type keys can be encrypted by using a combination of + * the `cipher` and `format` options. The PKCS#8 `type` can be used with any`format` to encrypt any key algorithm (RSA, EC, or DH) by specifying a`cipher`. PKCS#1 and SEC1 can only be + * encrypted by specifying a `cipher`when the PEM `format` is used. For maximum compatibility, use PKCS#8 for + * encrypted private keys. Since PKCS#8 defines its own + * encryption mechanism, PEM-level encryption is not supported when encrypting + * a PKCS#8 key. See [RFC 5208](https://www.rfc-editor.org/rfc/rfc5208.txt) for PKCS#8 encryption and [RFC 1421](https://www.rfc-editor.org/rfc/rfc1421.txt) for + * PKCS#1 and SEC1 encryption. + * @since v11.6.0 + */ + export<T extends KeyExportOptions = {}>(options?: T): KeyExportResult<T, NonSharedBuffer>; + /** + * Returns `true` or `false` depending on whether the keys have exactly the same + * type, value, and parameters. This method is not [constant time](https://en.wikipedia.org/wiki/Timing_attack). + * @since v17.7.0, v16.15.0 + * @param otherKeyObject A `KeyObject` with which to compare `keyObject`. + */ + equals(otherKeyObject: KeyObject): boolean; + /** + * For secret keys, this property represents the size of the key in bytes. This + * property is `undefined` for asymmetric keys. + * @since v11.6.0 + */ + symmetricKeySize?: number; + /** + * Converts a `KeyObject` instance to a `CryptoKey`. + * @since 22.10.0 + */ + toCryptoKey( + algorithm: + | webcrypto.AlgorithmIdentifier + | webcrypto.RsaHashedImportParams + | webcrypto.EcKeyImportParams + | webcrypto.HmacImportParams, + extractable: boolean, + keyUsages: readonly webcrypto.KeyUsage[], + ): webcrypto.CryptoKey; + /** + * Depending on the type of this `KeyObject`, this property is either`'secret'` for secret (symmetric) keys, `'public'` for public (asymmetric) keys + * or `'private'` for private (asymmetric) keys. + * @since v11.6.0 + */ + type: KeyObjectType; + } + type CipherCCMTypes = "aes-128-ccm" | "aes-192-ccm" | "aes-256-ccm"; + type CipherGCMTypes = "aes-128-gcm" | "aes-192-gcm" | "aes-256-gcm"; + type CipherOCBTypes = "aes-128-ocb" | "aes-192-ocb" | "aes-256-ocb"; + type CipherChaCha20Poly1305Types = "chacha20-poly1305"; + type BinaryLike = string | NodeJS.ArrayBufferView; + type CipherKey = BinaryLike | KeyObject; + interface CipherCCMOptions extends stream.TransformOptions { + authTagLength: number; + } + interface CipherGCMOptions extends stream.TransformOptions { + authTagLength?: number | undefined; + } + interface CipherOCBOptions extends stream.TransformOptions { + authTagLength: number; + } + interface CipherChaCha20Poly1305Options extends stream.TransformOptions { + /** @default 16 */ + authTagLength?: number | undefined; + } + /** + * Creates and returns a `Cipher` object, with the given `algorithm`, `key` and + * initialization vector (`iv`). + * + * The `options` argument controls stream behavior and is optional except when a + * cipher in CCM or OCB mode (e.g. `'aes-128-ccm'`) is used. In that case, the`authTagLength` option is required and specifies the length of the + * authentication tag in bytes, see `CCM mode`. In GCM mode, the `authTagLength`option is not required but can be used to set the length of the authentication + * tag that will be returned by `getAuthTag()` and defaults to 16 bytes. + * For `chacha20-poly1305`, the `authTagLength` option defaults to 16 bytes. + * + * The `algorithm` is dependent on OpenSSL, examples are `'aes192'`, etc. On + * recent OpenSSL releases, `openssl list -cipher-algorithms` will + * display the available cipher algorithms. + * + * The `key` is the raw key used by the `algorithm` and `iv` is an [initialization vector](https://en.wikipedia.org/wiki/Initialization_vector). Both arguments must be `'utf8'` encoded + * strings,`Buffers`, `TypedArray`, or `DataView`s. The `key` may optionally be + * a `KeyObject` of type `secret`. If the cipher does not need + * an initialization vector, `iv` may be `null`. + * + * When passing strings for `key` or `iv`, please consider `caveats when using strings as inputs to cryptographic APIs`. + * + * Initialization vectors should be unpredictable and unique; ideally, they will be + * cryptographically random. They do not have to be secret: IVs are typically just + * added to ciphertext messages unencrypted. It may sound contradictory that + * something has to be unpredictable and unique, but does not have to be secret; + * remember that an attacker must not be able to predict ahead of time what a + * given IV will be. + * @since v0.1.94 + * @param options `stream.transform` options + */ + function createCipheriv( + algorithm: CipherCCMTypes, + key: CipherKey, + iv: BinaryLike, + options: CipherCCMOptions, + ): CipherCCM; + function createCipheriv( + algorithm: CipherOCBTypes, + key: CipherKey, + iv: BinaryLike, + options: CipherOCBOptions, + ): CipherOCB; + function createCipheriv( + algorithm: CipherGCMTypes, + key: CipherKey, + iv: BinaryLike, + options?: CipherGCMOptions, + ): CipherGCM; + function createCipheriv( + algorithm: CipherChaCha20Poly1305Types, + key: CipherKey, + iv: BinaryLike, + options?: CipherChaCha20Poly1305Options, + ): CipherChaCha20Poly1305; + function createCipheriv( + algorithm: string, + key: CipherKey, + iv: BinaryLike | null, + options?: stream.TransformOptions, + ): Cipheriv; + /** + * Instances of the `Cipheriv` class are used to encrypt data. The class can be + * used in one of two ways: + * + * * As a `stream` that is both readable and writable, where plain unencrypted + * data is written to produce encrypted data on the readable side, or + * * Using the `cipher.update()` and `cipher.final()` methods to produce + * the encrypted data. + * + * The {@link createCipheriv} method is + * used to create `Cipheriv` instances. `Cipheriv` objects are not to be created + * directly using the `new` keyword. + * + * Example: Using `Cipheriv` objects as streams: + * + * ```js + * const { + * scrypt, + * randomFill, + * createCipheriv, + * } = await import('node:crypto'); + * + * const algorithm = 'aes-192-cbc'; + * const password = 'Password used to generate key'; + * + * // First, we'll generate the key. The key length is dependent on the algorithm. + * // In this case for aes192, it is 24 bytes (192 bits). + * scrypt(password, 'salt', 24, (err, key) => { + * if (err) throw err; + * // Then, we'll generate a random initialization vector + * randomFill(new Uint8Array(16), (err, iv) => { + * if (err) throw err; + * + * // Once we have the key and iv, we can create and use the cipher... + * const cipher = createCipheriv(algorithm, key, iv); + * + * let encrypted = ''; + * cipher.setEncoding('hex'); + * + * cipher.on('data', (chunk) => encrypted += chunk); + * cipher.on('end', () => console.log(encrypted)); + * + * cipher.write('some clear text data'); + * cipher.end(); + * }); + * }); + * ``` + * + * Example: Using `Cipheriv` and piped streams: + * + * ```js + * import { + * createReadStream, + * createWriteStream, + * } from 'node:fs'; + * + * import { + * pipeline, + * } from 'node:stream'; + * + * const { + * scrypt, + * randomFill, + * createCipheriv, + * } = await import('node:crypto'); + * + * const algorithm = 'aes-192-cbc'; + * const password = 'Password used to generate key'; + * + * // First, we'll generate the key. The key length is dependent on the algorithm. + * // In this case for aes192, it is 24 bytes (192 bits). + * scrypt(password, 'salt', 24, (err, key) => { + * if (err) throw err; + * // Then, we'll generate a random initialization vector + * randomFill(new Uint8Array(16), (err, iv) => { + * if (err) throw err; + * + * const cipher = createCipheriv(algorithm, key, iv); + * + * const input = createReadStream('test.js'); + * const output = createWriteStream('test.enc'); + * + * pipeline(input, cipher, output, (err) => { + * if (err) throw err; + * }); + * }); + * }); + * ``` + * + * Example: Using the `cipher.update()` and `cipher.final()` methods: + * + * ```js + * const { + * scrypt, + * randomFill, + * createCipheriv, + * } = await import('node:crypto'); + * + * const algorithm = 'aes-192-cbc'; + * const password = 'Password used to generate key'; + * + * // First, we'll generate the key. The key length is dependent on the algorithm. + * // In this case for aes192, it is 24 bytes (192 bits). + * scrypt(password, 'salt', 24, (err, key) => { + * if (err) throw err; + * // Then, we'll generate a random initialization vector + * randomFill(new Uint8Array(16), (err, iv) => { + * if (err) throw err; + * + * const cipher = createCipheriv(algorithm, key, iv); + * + * let encrypted = cipher.update('some clear text data', 'utf8', 'hex'); + * encrypted += cipher.final('hex'); + * console.log(encrypted); + * }); + * }); + * ``` + * @since v0.1.94 + */ + class Cipheriv extends stream.Transform { + private constructor(); + /** + * Updates the cipher with `data`. If the `inputEncoding` argument is given, + * the `data`argument is a string using the specified encoding. If the `inputEncoding`argument is not given, `data` must be a `Buffer`, `TypedArray`, or `DataView`. If `data` is a `Buffer`, + * `TypedArray`, or `DataView`, then `inputEncoding` is ignored. + * + * The `outputEncoding` specifies the output format of the enciphered + * data. If the `outputEncoding`is specified, a string using the specified encoding is returned. If no`outputEncoding` is provided, a `Buffer` is returned. + * + * The `cipher.update()` method can be called multiple times with new data until `cipher.final()` is called. Calling `cipher.update()` after `cipher.final()` will result in an error being + * thrown. + * @since v0.1.94 + * @param inputEncoding The `encoding` of the data. + * @param outputEncoding The `encoding` of the return value. + */ + update(data: BinaryLike): NonSharedBuffer; + update(data: string, inputEncoding: Encoding): NonSharedBuffer; + update(data: NodeJS.ArrayBufferView, inputEncoding: undefined, outputEncoding: Encoding): string; + update(data: string, inputEncoding: Encoding | undefined, outputEncoding: Encoding): string; + /** + * Once the `cipher.final()` method has been called, the `Cipheriv` object can no + * longer be used to encrypt data. Attempts to call `cipher.final()` more than + * once will result in an error being thrown. + * @since v0.1.94 + * @param outputEncoding The `encoding` of the return value. + * @return Any remaining enciphered contents. If `outputEncoding` is specified, a string is returned. If an `outputEncoding` is not provided, a {@link Buffer} is returned. + */ + final(): NonSharedBuffer; + final(outputEncoding: BufferEncoding): string; + /** + * When using block encryption algorithms, the `Cipheriv` class will automatically + * add padding to the input data to the appropriate block size. To disable the + * default padding call `cipher.setAutoPadding(false)`. + * + * When `autoPadding` is `false`, the length of the entire input data must be a + * multiple of the cipher's block size or `cipher.final()` will throw an error. + * Disabling automatic padding is useful for non-standard padding, for instance + * using `0x0` instead of PKCS padding. + * + * The `cipher.setAutoPadding()` method must be called before `cipher.final()`. + * @since v0.7.1 + * @param [autoPadding=true] + * @return for method chaining. + */ + setAutoPadding(autoPadding?: boolean): this; + } + interface CipherCCM extends Cipheriv { + setAAD( + buffer: NodeJS.ArrayBufferView, + options: { + plaintextLength: number; + }, + ): this; + getAuthTag(): NonSharedBuffer; + } + interface CipherGCM extends Cipheriv { + setAAD( + buffer: NodeJS.ArrayBufferView, + options?: { + plaintextLength: number; + }, + ): this; + getAuthTag(): NonSharedBuffer; + } + interface CipherOCB extends Cipheriv { + setAAD( + buffer: NodeJS.ArrayBufferView, + options?: { + plaintextLength: number; + }, + ): this; + getAuthTag(): NonSharedBuffer; + } + interface CipherChaCha20Poly1305 extends Cipheriv { + setAAD( + buffer: NodeJS.ArrayBufferView, + options: { + plaintextLength: number; + }, + ): this; + getAuthTag(): NonSharedBuffer; + } + /** + * Creates and returns a `Decipheriv` object that uses the given `algorithm`, `key` and initialization vector (`iv`). + * + * The `options` argument controls stream behavior and is optional except when a + * cipher in CCM or OCB mode (e.g. `'aes-128-ccm'`) is used. In that case, the `authTagLength` option is required and specifies the length of the + * authentication tag in bytes, see `CCM mode`. In GCM mode, the `authTagLength` option is not required but can be used to restrict accepted authentication tags + * to those with the specified length. + * For `chacha20-poly1305`, the `authTagLength` option defaults to 16 bytes. + * + * The `algorithm` is dependent on OpenSSL, examples are `'aes192'`, etc. On + * recent OpenSSL releases, `openssl list -cipher-algorithms` will + * display the available cipher algorithms. + * + * The `key` is the raw key used by the `algorithm` and `iv` is an [initialization vector](https://en.wikipedia.org/wiki/Initialization_vector). Both arguments must be `'utf8'` encoded + * strings,`Buffers`, `TypedArray`, or `DataView`s. The `key` may optionally be + * a `KeyObject` of type `secret`. If the cipher does not need + * an initialization vector, `iv` may be `null`. + * + * When passing strings for `key` or `iv`, please consider `caveats when using strings as inputs to cryptographic APIs`. + * + * Initialization vectors should be unpredictable and unique; ideally, they will be + * cryptographically random. They do not have to be secret: IVs are typically just + * added to ciphertext messages unencrypted. It may sound contradictory that + * something has to be unpredictable and unique, but does not have to be secret; + * remember that an attacker must not be able to predict ahead of time what a given + * IV will be. + * @since v0.1.94 + * @param options `stream.transform` options + */ + function createDecipheriv( + algorithm: CipherCCMTypes, + key: CipherKey, + iv: BinaryLike, + options: CipherCCMOptions, + ): DecipherCCM; + function createDecipheriv( + algorithm: CipherOCBTypes, + key: CipherKey, + iv: BinaryLike, + options: CipherOCBOptions, + ): DecipherOCB; + function createDecipheriv( + algorithm: CipherGCMTypes, + key: CipherKey, + iv: BinaryLike, + options?: CipherGCMOptions, + ): DecipherGCM; + function createDecipheriv( + algorithm: CipherChaCha20Poly1305Types, + key: CipherKey, + iv: BinaryLike, + options?: CipherChaCha20Poly1305Options, + ): DecipherChaCha20Poly1305; + function createDecipheriv( + algorithm: string, + key: CipherKey, + iv: BinaryLike | null, + options?: stream.TransformOptions, + ): Decipheriv; + /** + * Instances of the `Decipheriv` class are used to decrypt data. The class can be + * used in one of two ways: + * + * * As a `stream` that is both readable and writable, where plain encrypted + * data is written to produce unencrypted data on the readable side, or + * * Using the `decipher.update()` and `decipher.final()` methods to + * produce the unencrypted data. + * + * The {@link createDecipheriv} method is + * used to create `Decipheriv` instances. `Decipheriv` objects are not to be created + * directly using the `new` keyword. + * + * Example: Using `Decipheriv` objects as streams: + * + * ```js + * import { Buffer } from 'node:buffer'; + * const { + * scryptSync, + * createDecipheriv, + * } = await import('node:crypto'); + * + * const algorithm = 'aes-192-cbc'; + * const password = 'Password used to generate key'; + * // Key length is dependent on the algorithm. In this case for aes192, it is + * // 24 bytes (192 bits). + * // Use the async `crypto.scrypt()` instead. + * const key = scryptSync(password, 'salt', 24); + * // The IV is usually passed along with the ciphertext. + * const iv = Buffer.alloc(16, 0); // Initialization vector. + * + * const decipher = createDecipheriv(algorithm, key, iv); + * + * let decrypted = ''; + * decipher.on('readable', () => { + * let chunk; + * while (null !== (chunk = decipher.read())) { + * decrypted += chunk.toString('utf8'); + * } + * }); + * decipher.on('end', () => { + * console.log(decrypted); + * // Prints: some clear text data + * }); + * + * // Encrypted with same algorithm, key and iv. + * const encrypted = + * 'e5f79c5915c02171eec6b212d5520d44480993d7d622a7c4c2da32f6efda0ffa'; + * decipher.write(encrypted, 'hex'); + * decipher.end(); + * ``` + * + * Example: Using `Decipheriv` and piped streams: + * + * ```js + * import { + * createReadStream, + * createWriteStream, + * } from 'node:fs'; + * import { Buffer } from 'node:buffer'; + * const { + * scryptSync, + * createDecipheriv, + * } = await import('node:crypto'); + * + * const algorithm = 'aes-192-cbc'; + * const password = 'Password used to generate key'; + * // Use the async `crypto.scrypt()` instead. + * const key = scryptSync(password, 'salt', 24); + * // The IV is usually passed along with the ciphertext. + * const iv = Buffer.alloc(16, 0); // Initialization vector. + * + * const decipher = createDecipheriv(algorithm, key, iv); + * + * const input = createReadStream('test.enc'); + * const output = createWriteStream('test.js'); + * + * input.pipe(decipher).pipe(output); + * ``` + * + * Example: Using the `decipher.update()` and `decipher.final()` methods: + * + * ```js + * import { Buffer } from 'node:buffer'; + * const { + * scryptSync, + * createDecipheriv, + * } = await import('node:crypto'); + * + * const algorithm = 'aes-192-cbc'; + * const password = 'Password used to generate key'; + * // Use the async `crypto.scrypt()` instead. + * const key = scryptSync(password, 'salt', 24); + * // The IV is usually passed along with the ciphertext. + * const iv = Buffer.alloc(16, 0); // Initialization vector. + * + * const decipher = createDecipheriv(algorithm, key, iv); + * + * // Encrypted using same algorithm, key and iv. + * const encrypted = + * 'e5f79c5915c02171eec6b212d5520d44480993d7d622a7c4c2da32f6efda0ffa'; + * let decrypted = decipher.update(encrypted, 'hex', 'utf8'); + * decrypted += decipher.final('utf8'); + * console.log(decrypted); + * // Prints: some clear text data + * ``` + * @since v0.1.94 + */ + class Decipheriv extends stream.Transform { + private constructor(); + /** + * Updates the decipher with `data`. If the `inputEncoding` argument is given, + * the `data` argument is a string using the specified encoding. If the `inputEncoding` argument is not given, `data` must be a `Buffer`. If `data` is a `Buffer` then `inputEncoding` is + * ignored. + * + * The `outputEncoding` specifies the output format of the enciphered + * data. If the `outputEncoding` is specified, a string using the specified encoding is returned. If no `outputEncoding` is provided, a `Buffer` is returned. + * + * The `decipher.update()` method can be called multiple times with new data until `decipher.final()` is called. Calling `decipher.update()` after `decipher.final()` will result in an error + * being thrown. + * @since v0.1.94 + * @param inputEncoding The `encoding` of the `data` string. + * @param outputEncoding The `encoding` of the return value. + */ + update(data: NodeJS.ArrayBufferView): NonSharedBuffer; + update(data: string, inputEncoding: Encoding): NonSharedBuffer; + update(data: NodeJS.ArrayBufferView, inputEncoding: undefined, outputEncoding: Encoding): string; + update(data: string, inputEncoding: Encoding | undefined, outputEncoding: Encoding): string; + /** + * Once the `decipher.final()` method has been called, the `Decipheriv` object can + * no longer be used to decrypt data. Attempts to call `decipher.final()` more + * than once will result in an error being thrown. + * @since v0.1.94 + * @param outputEncoding The `encoding` of the return value. + * @return Any remaining deciphered contents. If `outputEncoding` is specified, a string is returned. If an `outputEncoding` is not provided, a {@link Buffer} is returned. + */ + final(): NonSharedBuffer; + final(outputEncoding: BufferEncoding): string; + /** + * When data has been encrypted without standard block padding, calling `decipher.setAutoPadding(false)` will disable automatic padding to prevent `decipher.final()` from checking for and + * removing padding. + * + * Turning auto padding off will only work if the input data's length is a + * multiple of the ciphers block size. + * + * The `decipher.setAutoPadding()` method must be called before `decipher.final()`. + * @since v0.7.1 + * @param [autoPadding=true] + * @return for method chaining. + */ + setAutoPadding(auto_padding?: boolean): this; + } + interface DecipherCCM extends Decipheriv { + setAuthTag(buffer: NodeJS.ArrayBufferView): this; + setAAD( + buffer: NodeJS.ArrayBufferView, + options: { + plaintextLength: number; + }, + ): this; + } + interface DecipherGCM extends Decipheriv { + setAuthTag(buffer: NodeJS.ArrayBufferView): this; + setAAD( + buffer: NodeJS.ArrayBufferView, + options?: { + plaintextLength: number; + }, + ): this; + } + interface DecipherOCB extends Decipheriv { + setAuthTag(buffer: NodeJS.ArrayBufferView): this; + setAAD( + buffer: NodeJS.ArrayBufferView, + options?: { + plaintextLength: number; + }, + ): this; + } + interface DecipherChaCha20Poly1305 extends Decipheriv { + setAuthTag(buffer: NodeJS.ArrayBufferView): this; + setAAD( + buffer: NodeJS.ArrayBufferView, + options: { + plaintextLength: number; + }, + ): this; + } + interface PrivateKeyInput { + key: string | Buffer; + format?: KeyFormat | undefined; + type?: PrivateKeyExportType | undefined; + passphrase?: string | Buffer | undefined; + encoding?: string | undefined; + } + interface PublicKeyInput { + key: string | Buffer; + format?: KeyFormat | undefined; + type?: PublicKeyExportType | undefined; + encoding?: string | undefined; + } + /** + * Asynchronously generates a new random secret key of the given `length`. The `type` will determine which validations will be performed on the `length`. + * + * ```js + * const { + * generateKey, + * } = await import('node:crypto'); + * + * generateKey('hmac', { length: 512 }, (err, key) => { + * if (err) throw err; + * console.log(key.export().toString('hex')); // 46e..........620 + * }); + * ``` + * + * The size of a generated HMAC key should not exceed the block size of the + * underlying hash function. See {@link createHmac} for more information. + * @since v15.0.0 + * @param type The intended use of the generated secret key. Currently accepted values are `'hmac'` and `'aes'`. + */ + function generateKey( + type: "hmac" | "aes", + options: { + length: number; + }, + callback: (err: Error | null, key: KeyObject) => void, + ): void; + /** + * Synchronously generates a new random secret key of the given `length`. The `type` will determine which validations will be performed on the `length`. + * + * ```js + * const { + * generateKeySync, + * } = await import('node:crypto'); + * + * const key = generateKeySync('hmac', { length: 512 }); + * console.log(key.export().toString('hex')); // e89..........41e + * ``` + * + * The size of a generated HMAC key should not exceed the block size of the + * underlying hash function. See {@link createHmac} for more information. + * @since v15.0.0 + * @param type The intended use of the generated secret key. Currently accepted values are `'hmac'` and `'aes'`. + */ + function generateKeySync( + type: "hmac" | "aes", + options: { + length: number; + }, + ): KeyObject; + interface JsonWebKeyInput { + key: webcrypto.JsonWebKey; + format: "jwk"; + } + /** + * Creates and returns a new key object containing a private key. If `key` is a + * string or `Buffer`, `format` is assumed to be `'pem'`; otherwise, `key` must be an object with the properties described above. + * + * If the private key is encrypted, a `passphrase` must be specified. The length + * of the passphrase is limited to 1024 bytes. + * @since v11.6.0 + */ + function createPrivateKey(key: PrivateKeyInput | string | Buffer | JsonWebKeyInput): KeyObject; + /** + * Creates and returns a new key object containing a public key. If `key` is a + * string or `Buffer`, `format` is assumed to be `'pem'`; if `key` is a `KeyObject` with type `'private'`, the public key is derived from the given private key; + * otherwise, `key` must be an object with the properties described above. + * + * If the format is `'pem'`, the `'key'` may also be an X.509 certificate. + * + * Because public keys can be derived from private keys, a private key may be + * passed instead of a public key. In that case, this function behaves as if {@link createPrivateKey} had been called, except that the type of the + * returned `KeyObject` will be `'public'` and that the private key cannot be + * extracted from the returned `KeyObject`. Similarly, if a `KeyObject` with type `'private'` is given, a new `KeyObject` with type `'public'` will be returned + * and it will be impossible to extract the private key from the returned object. + * @since v11.6.0 + */ + function createPublicKey(key: PublicKeyInput | string | Buffer | KeyObject | JsonWebKeyInput): KeyObject; + /** + * Creates and returns a new key object containing a secret key for symmetric + * encryption or `Hmac`. + * @since v11.6.0 + * @param encoding The string encoding when `key` is a string. + */ + function createSecretKey(key: NodeJS.ArrayBufferView): KeyObject; + function createSecretKey(key: string, encoding: BufferEncoding): KeyObject; + /** + * Creates and returns a `Sign` object that uses the given `algorithm`. Use {@link getHashes} to obtain the names of the available digest algorithms. + * Optional `options` argument controls the `stream.Writable` behavior. + * + * In some cases, a `Sign` instance can be created using the name of a signature + * algorithm, such as `'RSA-SHA256'`, instead of a digest algorithm. This will use + * the corresponding digest algorithm. This does not work for all signature + * algorithms, such as `'ecdsa-with-SHA256'`, so it is best to always use digest + * algorithm names. + * @since v0.1.92 + * @param options `stream.Writable` options + */ + // TODO: signing algorithm type + function createSign(algorithm: string, options?: stream.WritableOptions): Sign; + type DSAEncoding = "der" | "ieee-p1363"; + interface SigningOptions { + /** + * @see crypto.constants.RSA_PKCS1_PADDING + */ + padding?: number | undefined; + saltLength?: number | undefined; + dsaEncoding?: DSAEncoding | undefined; + context?: ArrayBuffer | NodeJS.ArrayBufferView | undefined; + } + interface SignPrivateKeyInput extends PrivateKeyInput, SigningOptions {} + interface SignKeyObjectInput extends SigningOptions { + key: KeyObject; + } + interface SignJsonWebKeyInput extends JsonWebKeyInput, SigningOptions {} + interface VerifyPublicKeyInput extends PublicKeyInput, SigningOptions {} + interface VerifyKeyObjectInput extends SigningOptions { + key: KeyObject; + } + interface VerifyJsonWebKeyInput extends JsonWebKeyInput, SigningOptions {} + type KeyLike = string | Buffer | KeyObject; + /** + * The `Sign` class is a utility for generating signatures. It can be used in one + * of two ways: + * + * * As a writable `stream`, where data to be signed is written and the `sign.sign()` method is used to generate and return the signature, or + * * Using the `sign.update()` and `sign.sign()` methods to produce the + * signature. + * + * The {@link createSign} method is used to create `Sign` instances. The + * argument is the string name of the hash function to use. `Sign` objects are not + * to be created directly using the `new` keyword. + * + * Example: Using `Sign` and `Verify` objects as streams: + * + * ```js + * const { + * generateKeyPairSync, + * createSign, + * createVerify, + * } = await import('node:crypto'); + * + * const { privateKey, publicKey } = generateKeyPairSync('ec', { + * namedCurve: 'sect239k1', + * }); + * + * const sign = createSign('SHA256'); + * sign.write('some data to sign'); + * sign.end(); + * const signature = sign.sign(privateKey, 'hex'); + * + * const verify = createVerify('SHA256'); + * verify.write('some data to sign'); + * verify.end(); + * console.log(verify.verify(publicKey, signature, 'hex')); + * // Prints: true + * ``` + * + * Example: Using the `sign.update()` and `verify.update()` methods: + * + * ```js + * const { + * generateKeyPairSync, + * createSign, + * createVerify, + * } = await import('node:crypto'); + * + * const { privateKey, publicKey } = generateKeyPairSync('rsa', { + * modulusLength: 2048, + * }); + * + * const sign = createSign('SHA256'); + * sign.update('some data to sign'); + * sign.end(); + * const signature = sign.sign(privateKey); + * + * const verify = createVerify('SHA256'); + * verify.update('some data to sign'); + * verify.end(); + * console.log(verify.verify(publicKey, signature)); + * // Prints: true + * ``` + * @since v0.1.92 + */ + class Sign extends stream.Writable { + private constructor(); + /** + * Updates the `Sign` content with the given `data`, the encoding of which + * is given in `inputEncoding`. + * If `encoding` is not provided, and the `data` is a string, an + * encoding of `'utf8'` is enforced. If `data` is a `Buffer`, `TypedArray`, or`DataView`, then `inputEncoding` is ignored. + * + * This can be called many times with new data as it is streamed. + * @since v0.1.92 + * @param inputEncoding The `encoding` of the `data` string. + */ + update(data: BinaryLike): this; + update(data: string, inputEncoding: Encoding): this; + /** + * Calculates the signature on all the data passed through using either `sign.update()` or `sign.write()`. + * + * If `privateKey` is not a `KeyObject`, this function behaves as if `privateKey` had been passed to {@link createPrivateKey}. If it is an + * object, the following additional properties can be passed: + * + * If `outputEncoding` is provided a string is returned; otherwise a `Buffer` is returned. + * + * The `Sign` object can not be again used after `sign.sign()` method has been + * called. Multiple calls to `sign.sign()` will result in an error being thrown. + * @since v0.1.92 + */ + sign(privateKey: KeyLike | SignKeyObjectInput | SignPrivateKeyInput | SignJsonWebKeyInput): NonSharedBuffer; + sign( + privateKey: KeyLike | SignKeyObjectInput | SignPrivateKeyInput | SignJsonWebKeyInput, + outputFormat: BinaryToTextEncoding, + ): string; + } + /** + * Creates and returns a `Verify` object that uses the given algorithm. + * Use {@link getHashes} to obtain an array of names of the available + * signing algorithms. Optional `options` argument controls the `stream.Writable` behavior. + * + * In some cases, a `Verify` instance can be created using the name of a signature + * algorithm, such as `'RSA-SHA256'`, instead of a digest algorithm. This will use + * the corresponding digest algorithm. This does not work for all signature + * algorithms, such as `'ecdsa-with-SHA256'`, so it is best to always use digest + * algorithm names. + * @since v0.1.92 + * @param options `stream.Writable` options + */ + function createVerify(algorithm: string, options?: stream.WritableOptions): Verify; + /** + * The `Verify` class is a utility for verifying signatures. It can be used in one + * of two ways: + * + * * As a writable `stream` where written data is used to validate against the + * supplied signature, or + * * Using the `verify.update()` and `verify.verify()` methods to verify + * the signature. + * + * The {@link createVerify} method is used to create `Verify` instances. `Verify` objects are not to be created directly using the `new` keyword. + * + * See `Sign` for examples. + * @since v0.1.92 + */ + class Verify extends stream.Writable { + private constructor(); + /** + * Updates the `Verify` content with the given `data`, the encoding of which + * is given in `inputEncoding`. + * If `inputEncoding` is not provided, and the `data` is a string, an + * encoding of `'utf8'` is enforced. If `data` is a `Buffer`, `TypedArray`, or `DataView`, then `inputEncoding` is ignored. + * + * This can be called many times with new data as it is streamed. + * @since v0.1.92 + * @param inputEncoding The `encoding` of the `data` string. + */ + update(data: BinaryLike): Verify; + update(data: string, inputEncoding: Encoding): Verify; + /** + * Verifies the provided data using the given `object` and `signature`. + * + * If `object` is not a `KeyObject`, this function behaves as if `object` had been passed to {@link createPublicKey}. If it is an + * object, the following additional properties can be passed: + * + * The `signature` argument is the previously calculated signature for the data, in + * the `signatureEncoding`. + * If a `signatureEncoding` is specified, the `signature` is expected to be a + * string; otherwise `signature` is expected to be a `Buffer`, `TypedArray`, or `DataView`. + * + * The `verify` object can not be used again after `verify.verify()` has been + * called. Multiple calls to `verify.verify()` will result in an error being + * thrown. + * + * Because public keys can be derived from private keys, a private key may + * be passed instead of a public key. + * @since v0.1.92 + */ + verify( + object: KeyLike | VerifyKeyObjectInput | VerifyPublicKeyInput | VerifyJsonWebKeyInput, + signature: NodeJS.ArrayBufferView, + ): boolean; + verify( + object: KeyLike | VerifyKeyObjectInput | VerifyPublicKeyInput | VerifyJsonWebKeyInput, + signature: string, + signature_format?: BinaryToTextEncoding, + ): boolean; + } + /** + * Creates a `DiffieHellman` key exchange object using the supplied `prime` and an + * optional specific `generator`. + * + * The `generator` argument can be a number, string, or `Buffer`. If `generator` is not specified, the value `2` is used. + * + * If `primeEncoding` is specified, `prime` is expected to be a string; otherwise + * a `Buffer`, `TypedArray`, or `DataView` is expected. + * + * If `generatorEncoding` is specified, `generator` is expected to be a string; + * otherwise a number, `Buffer`, `TypedArray`, or `DataView` is expected. + * @since v0.11.12 + * @param primeEncoding The `encoding` of the `prime` string. + * @param [generator=2] + * @param generatorEncoding The `encoding` of the `generator` string. + */ + function createDiffieHellman(primeLength: number, generator?: number): DiffieHellman; + function createDiffieHellman( + prime: ArrayBuffer | NodeJS.ArrayBufferView, + generator?: number | ArrayBuffer | NodeJS.ArrayBufferView, + ): DiffieHellman; + function createDiffieHellman( + prime: ArrayBuffer | NodeJS.ArrayBufferView, + generator: string, + generatorEncoding: BinaryToTextEncoding, + ): DiffieHellman; + function createDiffieHellman( + prime: string, + primeEncoding: BinaryToTextEncoding, + generator?: number | ArrayBuffer | NodeJS.ArrayBufferView, + ): DiffieHellman; + function createDiffieHellman( + prime: string, + primeEncoding: BinaryToTextEncoding, + generator: string, + generatorEncoding: BinaryToTextEncoding, + ): DiffieHellman; + /** + * The `DiffieHellman` class is a utility for creating Diffie-Hellman key + * exchanges. + * + * Instances of the `DiffieHellman` class can be created using the {@link createDiffieHellman} function. + * + * ```js + * import assert from 'node:assert'; + * + * const { + * createDiffieHellman, + * } = await import('node:crypto'); + * + * // Generate Alice's keys... + * const alice = createDiffieHellman(2048); + * const aliceKey = alice.generateKeys(); + * + * // Generate Bob's keys... + * const bob = createDiffieHellman(alice.getPrime(), alice.getGenerator()); + * const bobKey = bob.generateKeys(); + * + * // Exchange and generate the secret... + * const aliceSecret = alice.computeSecret(bobKey); + * const bobSecret = bob.computeSecret(aliceKey); + * + * // OK + * assert.strictEqual(aliceSecret.toString('hex'), bobSecret.toString('hex')); + * ``` + * @since v0.5.0 + */ + class DiffieHellman { + private constructor(); + /** + * Generates private and public Diffie-Hellman key values unless they have been + * generated or computed already, and returns + * the public key in the specified `encoding`. This key should be + * transferred to the other party. + * If `encoding` is provided a string is returned; otherwise a `Buffer` is returned. + * + * This function is a thin wrapper around [`DH_generate_key()`](https://www.openssl.org/docs/man3.0/man3/DH_generate_key.html). In particular, + * once a private key has been generated or set, calling this function only updates + * the public key but does not generate a new private key. + * @since v0.5.0 + * @param encoding The `encoding` of the return value. + */ + generateKeys(): NonSharedBuffer; + generateKeys(encoding: BinaryToTextEncoding): string; + /** + * Computes the shared secret using `otherPublicKey` as the other + * party's public key and returns the computed shared secret. The supplied + * key is interpreted using the specified `inputEncoding`, and secret is + * encoded using specified `outputEncoding`. + * If the `inputEncoding` is not + * provided, `otherPublicKey` is expected to be a `Buffer`, `TypedArray`, or `DataView`. + * + * If `outputEncoding` is given a string is returned; otherwise, a `Buffer` is returned. + * @since v0.5.0 + * @param inputEncoding The `encoding` of an `otherPublicKey` string. + * @param outputEncoding The `encoding` of the return value. + */ + computeSecret( + otherPublicKey: NodeJS.ArrayBufferView, + inputEncoding?: null, + outputEncoding?: null, + ): NonSharedBuffer; + computeSecret( + otherPublicKey: string, + inputEncoding: BinaryToTextEncoding, + outputEncoding?: null, + ): NonSharedBuffer; + computeSecret( + otherPublicKey: NodeJS.ArrayBufferView, + inputEncoding: null, + outputEncoding: BinaryToTextEncoding, + ): string; + computeSecret( + otherPublicKey: string, + inputEncoding: BinaryToTextEncoding, + outputEncoding: BinaryToTextEncoding, + ): string; + /** + * Returns the Diffie-Hellman prime in the specified `encoding`. + * If `encoding` is provided a string is + * returned; otherwise a `Buffer` is returned. + * @since v0.5.0 + * @param encoding The `encoding` of the return value. + */ + getPrime(): NonSharedBuffer; + getPrime(encoding: BinaryToTextEncoding): string; + /** + * Returns the Diffie-Hellman generator in the specified `encoding`. + * If `encoding` is provided a string is + * returned; otherwise a `Buffer` is returned. + * @since v0.5.0 + * @param encoding The `encoding` of the return value. + */ + getGenerator(): NonSharedBuffer; + getGenerator(encoding: BinaryToTextEncoding): string; + /** + * Returns the Diffie-Hellman public key in the specified `encoding`. + * If `encoding` is provided a + * string is returned; otherwise a `Buffer` is returned. + * @since v0.5.0 + * @param encoding The `encoding` of the return value. + */ + getPublicKey(): NonSharedBuffer; + getPublicKey(encoding: BinaryToTextEncoding): string; + /** + * Returns the Diffie-Hellman private key in the specified `encoding`. + * If `encoding` is provided a + * string is returned; otherwise a `Buffer` is returned. + * @since v0.5.0 + * @param encoding The `encoding` of the return value. + */ + getPrivateKey(): NonSharedBuffer; + getPrivateKey(encoding: BinaryToTextEncoding): string; + /** + * Sets the Diffie-Hellman public key. If the `encoding` argument is provided, `publicKey` is expected + * to be a string. If no `encoding` is provided, `publicKey` is expected + * to be a `Buffer`, `TypedArray`, or `DataView`. + * @since v0.5.0 + * @param encoding The `encoding` of the `publicKey` string. + */ + setPublicKey(publicKey: NodeJS.ArrayBufferView): void; + setPublicKey(publicKey: string, encoding: BufferEncoding): void; + /** + * Sets the Diffie-Hellman private key. If the `encoding` argument is provided,`privateKey` is expected + * to be a string. If no `encoding` is provided, `privateKey` is expected + * to be a `Buffer`, `TypedArray`, or `DataView`. + * + * This function does not automatically compute the associated public key. Either `diffieHellman.setPublicKey()` or `diffieHellman.generateKeys()` can be + * used to manually provide the public key or to automatically derive it. + * @since v0.5.0 + * @param encoding The `encoding` of the `privateKey` string. + */ + setPrivateKey(privateKey: NodeJS.ArrayBufferView): void; + setPrivateKey(privateKey: string, encoding: BufferEncoding): void; + /** + * A bit field containing any warnings and/or errors resulting from a check + * performed during initialization of the `DiffieHellman` object. + * + * The following values are valid for this property (as defined in `node:constants` module): + * + * * `DH_CHECK_P_NOT_SAFE_PRIME` + * * `DH_CHECK_P_NOT_PRIME` + * * `DH_UNABLE_TO_CHECK_GENERATOR` + * * `DH_NOT_SUITABLE_GENERATOR` + * @since v0.11.12 + */ + verifyError: number; + } + /** + * The `DiffieHellmanGroup` class takes a well-known modp group as its argument. + * It works the same as `DiffieHellman`, except that it does not allow changing its keys after creation. + * In other words, it does not implement `setPublicKey()` or `setPrivateKey()` methods. + * + * ```js + * const { createDiffieHellmanGroup } = await import('node:crypto'); + * const dh = createDiffieHellmanGroup('modp1'); + * ``` + * The name (e.g. `'modp1'`) is taken from [RFC 2412](https://www.rfc-editor.org/rfc/rfc2412.txt) (modp1 and 2) and [RFC 3526](https://www.rfc-editor.org/rfc/rfc3526.txt): + * ```bash + * $ perl -ne 'print "$1\n" if /"(modp\d+)"/' src/node_crypto_groups.h + * modp1 # 768 bits + * modp2 # 1024 bits + * modp5 # 1536 bits + * modp14 # 2048 bits + * modp15 # etc. + * modp16 + * modp17 + * modp18 + * ``` + * @since v0.7.5 + */ + const DiffieHellmanGroup: DiffieHellmanGroupConstructor; + interface DiffieHellmanGroupConstructor { + new(name: string): DiffieHellmanGroup; + (name: string): DiffieHellmanGroup; + readonly prototype: DiffieHellmanGroup; + } + type DiffieHellmanGroup = Omit<DiffieHellman, "setPublicKey" | "setPrivateKey">; + /** + * Creates a predefined `DiffieHellmanGroup` key exchange object. The + * supported groups are listed in the documentation for `DiffieHellmanGroup`. + * + * The returned object mimics the interface of objects created by {@link createDiffieHellman}, but will not allow changing + * the keys (with `diffieHellman.setPublicKey()`, for example). The + * advantage of using this method is that the parties do not have to + * generate nor exchange a group modulus beforehand, saving both processor + * and communication time. + * + * Example (obtaining a shared secret): + * + * ```js + * const { + * getDiffieHellman, + * } = await import('node:crypto'); + * const alice = getDiffieHellman('modp14'); + * const bob = getDiffieHellman('modp14'); + * + * alice.generateKeys(); + * bob.generateKeys(); + * + * const aliceSecret = alice.computeSecret(bob.getPublicKey(), null, 'hex'); + * const bobSecret = bob.computeSecret(alice.getPublicKey(), null, 'hex'); + * + * // aliceSecret and bobSecret should be the same + * console.log(aliceSecret === bobSecret); + * ``` + * @since v0.7.5 + */ + function getDiffieHellman(groupName: string): DiffieHellmanGroup; + /** + * An alias for {@link getDiffieHellman} + * @since v0.9.3 + */ + function createDiffieHellmanGroup(name: string): DiffieHellmanGroup; + /** + * Provides an asynchronous Password-Based Key Derivation Function 2 (PBKDF2) + * implementation. A selected HMAC digest algorithm specified by `digest` is + * applied to derive a key of the requested byte length (`keylen`) from the `password`, `salt` and `iterations`. + * + * The supplied `callback` function is called with two arguments: `err` and `derivedKey`. If an error occurs while deriving the key, `err` will be set; + * otherwise `err` will be `null`. By default, the successfully generated `derivedKey` will be passed to the callback as a `Buffer`. An error will be + * thrown if any of the input arguments specify invalid values or types. + * + * The `iterations` argument must be a number set as high as possible. The + * higher the number of iterations, the more secure the derived key will be, + * but will take a longer amount of time to complete. + * + * The `salt` should be as unique as possible. It is recommended that a salt is + * random and at least 16 bytes long. See [NIST SP 800-132](https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-132.pdf) for details. + * + * When passing strings for `password` or `salt`, please consider `caveats when using strings as inputs to cryptographic APIs`. + * + * ```js + * const { + * pbkdf2, + * } = await import('node:crypto'); + * + * pbkdf2('secret', 'salt', 100000, 64, 'sha512', (err, derivedKey) => { + * if (err) throw err; + * console.log(derivedKey.toString('hex')); // '3745e48...08d59ae' + * }); + * ``` + * + * An array of supported digest functions can be retrieved using {@link getHashes}. + * + * This API uses libuv's threadpool, which can have surprising and + * negative performance implications for some applications; see the `UV_THREADPOOL_SIZE` documentation for more information. + * @since v0.5.5 + */ + function pbkdf2( + password: BinaryLike, + salt: BinaryLike, + iterations: number, + keylen: number, + digest: string, + callback: (err: Error | null, derivedKey: NonSharedBuffer) => void, + ): void; + /** + * Provides a synchronous Password-Based Key Derivation Function 2 (PBKDF2) + * implementation. A selected HMAC digest algorithm specified by `digest` is + * applied to derive a key of the requested byte length (`keylen`) from the `password`, `salt` and `iterations`. + * + * If an error occurs an `Error` will be thrown, otherwise the derived key will be + * returned as a `Buffer`. + * + * The `iterations` argument must be a number set as high as possible. The + * higher the number of iterations, the more secure the derived key will be, + * but will take a longer amount of time to complete. + * + * The `salt` should be as unique as possible. It is recommended that a salt is + * random and at least 16 bytes long. See [NIST SP 800-132](https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-132.pdf) for details. + * + * When passing strings for `password` or `salt`, please consider `caveats when using strings as inputs to cryptographic APIs`. + * + * ```js + * const { + * pbkdf2Sync, + * } = await import('node:crypto'); + * + * const key = pbkdf2Sync('secret', 'salt', 100000, 64, 'sha512'); + * console.log(key.toString('hex')); // '3745e48...08d59ae' + * ``` + * + * An array of supported digest functions can be retrieved using {@link getHashes}. + * @since v0.9.3 + */ + function pbkdf2Sync( + password: BinaryLike, + salt: BinaryLike, + iterations: number, + keylen: number, + digest: string, + ): NonSharedBuffer; + /** + * Generates cryptographically strong pseudorandom data. The `size` argument + * is a number indicating the number of bytes to generate. + * + * If a `callback` function is provided, the bytes are generated asynchronously + * and the `callback` function is invoked with two arguments: `err` and `buf`. + * If an error occurs, `err` will be an `Error` object; otherwise it is `null`. The `buf` argument is a `Buffer` containing the generated bytes. + * + * ```js + * // Asynchronous + * const { + * randomBytes, + * } = await import('node:crypto'); + * + * randomBytes(256, (err, buf) => { + * if (err) throw err; + * console.log(`${buf.length} bytes of random data: ${buf.toString('hex')}`); + * }); + * ``` + * + * If the `callback` function is not provided, the random bytes are generated + * synchronously and returned as a `Buffer`. An error will be thrown if + * there is a problem generating the bytes. + * + * ```js + * // Synchronous + * const { + * randomBytes, + * } = await import('node:crypto'); + * + * const buf = randomBytes(256); + * console.log( + * `${buf.length} bytes of random data: ${buf.toString('hex')}`); + * ``` + * + * The `crypto.randomBytes()` method will not complete until there is + * sufficient entropy available. + * This should normally never take longer than a few milliseconds. The only time + * when generating the random bytes may conceivably block for a longer period of + * time is right after boot, when the whole system is still low on entropy. + * + * This API uses libuv's threadpool, which can have surprising and + * negative performance implications for some applications; see the `UV_THREADPOOL_SIZE` documentation for more information. + * + * The asynchronous version of `crypto.randomBytes()` is carried out in a single + * threadpool request. To minimize threadpool task length variation, partition + * large `randomBytes` requests when doing so as part of fulfilling a client + * request. + * @since v0.5.8 + * @param size The number of bytes to generate. The `size` must not be larger than `2**31 - 1`. + * @return if the `callback` function is not provided. + */ + function randomBytes(size: number): NonSharedBuffer; + function randomBytes(size: number, callback: (err: Error | null, buf: NonSharedBuffer) => void): void; + function pseudoRandomBytes(size: number): NonSharedBuffer; + function pseudoRandomBytes(size: number, callback: (err: Error | null, buf: NonSharedBuffer) => void): void; + /** + * Return a random integer `n` such that `min <= n < max`. This + * implementation avoids [modulo bias](https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#Modulo_bias). + * + * The range (`max - min`) must be less than 2**48. `min` and `max` must + * be [safe integers](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isSafeInteger). + * + * If the `callback` function is not provided, the random integer is + * generated synchronously. + * + * ```js + * // Asynchronous + * const { + * randomInt, + * } = await import('node:crypto'); + * + * randomInt(3, (err, n) => { + * if (err) throw err; + * console.log(`Random number chosen from (0, 1, 2): ${n}`); + * }); + * ``` + * + * ```js + * // Synchronous + * const { + * randomInt, + * } = await import('node:crypto'); + * + * const n = randomInt(3); + * console.log(`Random number chosen from (0, 1, 2): ${n}`); + * ``` + * + * ```js + * // With `min` argument + * const { + * randomInt, + * } = await import('node:crypto'); + * + * const n = randomInt(1, 7); + * console.log(`The dice rolled: ${n}`); + * ``` + * @since v14.10.0, v12.19.0 + * @param [min=0] Start of random range (inclusive). + * @param max End of random range (exclusive). + * @param callback `function(err, n) {}`. + */ + function randomInt(max: number): number; + function randomInt(min: number, max: number): number; + function randomInt(max: number, callback: (err: Error | null, value: number) => void): void; + function randomInt(min: number, max: number, callback: (err: Error | null, value: number) => void): void; + /** + * Synchronous version of {@link randomFill}. + * + * ```js + * import { Buffer } from 'node:buffer'; + * const { randomFillSync } = await import('node:crypto'); + * + * const buf = Buffer.alloc(10); + * console.log(randomFillSync(buf).toString('hex')); + * + * randomFillSync(buf, 5); + * console.log(buf.toString('hex')); + * + * // The above is equivalent to the following: + * randomFillSync(buf, 5, 5); + * console.log(buf.toString('hex')); + * ``` + * + * Any `ArrayBuffer`, `TypedArray` or `DataView` instance may be passed as`buffer`. + * + * ```js + * import { Buffer } from 'node:buffer'; + * const { randomFillSync } = await import('node:crypto'); + * + * const a = new Uint32Array(10); + * console.log(Buffer.from(randomFillSync(a).buffer, + * a.byteOffset, a.byteLength).toString('hex')); + * + * const b = new DataView(new ArrayBuffer(10)); + * console.log(Buffer.from(randomFillSync(b).buffer, + * b.byteOffset, b.byteLength).toString('hex')); + * + * const c = new ArrayBuffer(10); + * console.log(Buffer.from(randomFillSync(c)).toString('hex')); + * ``` + * @since v7.10.0, v6.13.0 + * @param buffer Must be supplied. The size of the provided `buffer` must not be larger than `2**31 - 1`. + * @param [offset=0] + * @param [size=buffer.length - offset] + * @return The object passed as `buffer` argument. + */ + function randomFillSync<T extends NodeJS.ArrayBufferView>(buffer: T, offset?: number, size?: number): T; + /** + * This function is similar to {@link randomBytes} but requires the first + * argument to be a `Buffer` that will be filled. It also + * requires that a callback is passed in. + * + * If the `callback` function is not provided, an error will be thrown. + * + * ```js + * import { Buffer } from 'node:buffer'; + * const { randomFill } = await import('node:crypto'); + * + * const buf = Buffer.alloc(10); + * randomFill(buf, (err, buf) => { + * if (err) throw err; + * console.log(buf.toString('hex')); + * }); + * + * randomFill(buf, 5, (err, buf) => { + * if (err) throw err; + * console.log(buf.toString('hex')); + * }); + * + * // The above is equivalent to the following: + * randomFill(buf, 5, 5, (err, buf) => { + * if (err) throw err; + * console.log(buf.toString('hex')); + * }); + * ``` + * + * Any `ArrayBuffer`, `TypedArray`, or `DataView` instance may be passed as `buffer`. + * + * While this includes instances of `Float32Array` and `Float64Array`, this + * function should not be used to generate random floating-point numbers. The + * result may contain `+Infinity`, `-Infinity`, and `NaN`, and even if the array + * contains finite numbers only, they are not drawn from a uniform random + * distribution and have no meaningful lower or upper bounds. + * + * ```js + * import { Buffer } from 'node:buffer'; + * const { randomFill } = await import('node:crypto'); + * + * const a = new Uint32Array(10); + * randomFill(a, (err, buf) => { + * if (err) throw err; + * console.log(Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength) + * .toString('hex')); + * }); + * + * const b = new DataView(new ArrayBuffer(10)); + * randomFill(b, (err, buf) => { + * if (err) throw err; + * console.log(Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength) + * .toString('hex')); + * }); + * + * const c = new ArrayBuffer(10); + * randomFill(c, (err, buf) => { + * if (err) throw err; + * console.log(Buffer.from(buf).toString('hex')); + * }); + * ``` + * + * This API uses libuv's threadpool, which can have surprising and + * negative performance implications for some applications; see the `UV_THREADPOOL_SIZE` documentation for more information. + * + * The asynchronous version of `crypto.randomFill()` is carried out in a single + * threadpool request. To minimize threadpool task length variation, partition + * large `randomFill` requests when doing so as part of fulfilling a client + * request. + * @since v7.10.0, v6.13.0 + * @param buffer Must be supplied. The size of the provided `buffer` must not be larger than `2**31 - 1`. + * @param [offset=0] + * @param [size=buffer.length - offset] + * @param callback `function(err, buf) {}`. + */ + function randomFill<T extends NodeJS.ArrayBufferView>( + buffer: T, + callback: (err: Error | null, buf: T) => void, + ): void; + function randomFill<T extends NodeJS.ArrayBufferView>( + buffer: T, + offset: number, + callback: (err: Error | null, buf: T) => void, + ): void; + function randomFill<T extends NodeJS.ArrayBufferView>( + buffer: T, + offset: number, + size: number, + callback: (err: Error | null, buf: T) => void, + ): void; + interface ScryptOptions { + cost?: number | undefined; + blockSize?: number | undefined; + parallelization?: number | undefined; + N?: number | undefined; + r?: number | undefined; + p?: number | undefined; + maxmem?: number | undefined; + } + /** + * Provides an asynchronous [scrypt](https://en.wikipedia.org/wiki/Scrypt) implementation. Scrypt is a password-based + * key derivation function that is designed to be expensive computationally and + * memory-wise in order to make brute-force attacks unrewarding. + * + * The `salt` should be as unique as possible. It is recommended that a salt is + * random and at least 16 bytes long. See [NIST SP 800-132](https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-132.pdf) for details. + * + * When passing strings for `password` or `salt`, please consider `caveats when using strings as inputs to cryptographic APIs`. + * + * The `callback` function is called with two arguments: `err` and `derivedKey`. `err` is an exception object when key derivation fails, otherwise `err` is `null`. `derivedKey` is passed to the + * callback as a `Buffer`. + * + * An exception is thrown when any of the input arguments specify invalid values + * or types. + * + * ```js + * const { + * scrypt, + * } = await import('node:crypto'); + * + * // Using the factory defaults. + * scrypt('password', 'salt', 64, (err, derivedKey) => { + * if (err) throw err; + * console.log(derivedKey.toString('hex')); // '3745e48...08d59ae' + * }); + * // Using a custom N parameter. Must be a power of two. + * scrypt('password', 'salt', 64, { N: 1024 }, (err, derivedKey) => { + * if (err) throw err; + * console.log(derivedKey.toString('hex')); // '3745e48...aa39b34' + * }); + * ``` + * @since v10.5.0 + */ + function scrypt( + password: BinaryLike, + salt: BinaryLike, + keylen: number, + callback: (err: Error | null, derivedKey: NonSharedBuffer) => void, + ): void; + function scrypt( + password: BinaryLike, + salt: BinaryLike, + keylen: number, + options: ScryptOptions, + callback: (err: Error | null, derivedKey: NonSharedBuffer) => void, + ): void; + /** + * Provides a synchronous [scrypt](https://en.wikipedia.org/wiki/Scrypt) implementation. Scrypt is a password-based + * key derivation function that is designed to be expensive computationally and + * memory-wise in order to make brute-force attacks unrewarding. + * + * The `salt` should be as unique as possible. It is recommended that a salt is + * random and at least 16 bytes long. See [NIST SP 800-132](https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-132.pdf) for details. + * + * When passing strings for `password` or `salt`, please consider `caveats when using strings as inputs to cryptographic APIs`. + * + * An exception is thrown when key derivation fails, otherwise the derived key is + * returned as a `Buffer`. + * + * An exception is thrown when any of the input arguments specify invalid values + * or types. + * + * ```js + * const { + * scryptSync, + * } = await import('node:crypto'); + * // Using the factory defaults. + * + * const key1 = scryptSync('password', 'salt', 64); + * console.log(key1.toString('hex')); // '3745e48...08d59ae' + * // Using a custom N parameter. Must be a power of two. + * const key2 = scryptSync('password', 'salt', 64, { N: 1024 }); + * console.log(key2.toString('hex')); // '3745e48...aa39b34' + * ``` + * @since v10.5.0 + */ + function scryptSync( + password: BinaryLike, + salt: BinaryLike, + keylen: number, + options?: ScryptOptions, + ): NonSharedBuffer; + interface RsaPublicKey { + key: KeyLike; + padding?: number | undefined; + } + interface RsaPrivateKey { + key: KeyLike; + passphrase?: string | undefined; + /** + * @default 'sha1' + */ + oaepHash?: string | undefined; + oaepLabel?: NodeJS.TypedArray | undefined; + padding?: number | undefined; + } + /** + * Encrypts the content of `buffer` with `key` and returns a new `Buffer` with encrypted content. The returned data can be decrypted using + * the corresponding private key, for example using {@link privateDecrypt}. + * + * If `key` is not a `KeyObject`, this function behaves as if `key` had been passed to {@link createPublicKey}. If it is an + * object, the `padding` property can be passed. Otherwise, this function uses `RSA_PKCS1_OAEP_PADDING`. + * + * Because RSA public keys can be derived from private keys, a private key may + * be passed instead of a public key. + * @since v0.11.14 + */ + function publicEncrypt( + key: RsaPublicKey | RsaPrivateKey | KeyLike, + buffer: NodeJS.ArrayBufferView | string, + ): NonSharedBuffer; + /** + * Decrypts `buffer` with `key`.`buffer` was previously encrypted using + * the corresponding private key, for example using {@link privateEncrypt}. + * + * If `key` is not a `KeyObject`, this function behaves as if `key` had been passed to {@link createPublicKey}. If it is an + * object, the `padding` property can be passed. Otherwise, this function uses `RSA_PKCS1_PADDING`. + * + * Because RSA public keys can be derived from private keys, a private key may + * be passed instead of a public key. + * @since v1.1.0 + */ + function publicDecrypt( + key: RsaPublicKey | RsaPrivateKey | KeyLike, + buffer: NodeJS.ArrayBufferView | string, + ): NonSharedBuffer; + /** + * Decrypts `buffer` with `privateKey`. `buffer` was previously encrypted using + * the corresponding public key, for example using {@link publicEncrypt}. + * + * If `privateKey` is not a `KeyObject`, this function behaves as if `privateKey` had been passed to {@link createPrivateKey}. If it is an + * object, the `padding` property can be passed. Otherwise, this function uses `RSA_PKCS1_OAEP_PADDING`. + * @since v0.11.14 + */ + function privateDecrypt( + privateKey: RsaPrivateKey | KeyLike, + buffer: NodeJS.ArrayBufferView | string, + ): NonSharedBuffer; + /** + * Encrypts `buffer` with `privateKey`. The returned data can be decrypted using + * the corresponding public key, for example using {@link publicDecrypt}. + * + * If `privateKey` is not a `KeyObject`, this function behaves as if `privateKey` had been passed to {@link createPrivateKey}. If it is an + * object, the `padding` property can be passed. Otherwise, this function uses `RSA_PKCS1_PADDING`. + * @since v1.1.0 + */ + function privateEncrypt( + privateKey: RsaPrivateKey | KeyLike, + buffer: NodeJS.ArrayBufferView | string, + ): NonSharedBuffer; + /** + * ```js + * const { + * getCiphers, + * } = await import('node:crypto'); + * + * console.log(getCiphers()); // ['aes-128-cbc', 'aes-128-ccm', ...] + * ``` + * @since v0.9.3 + * @return An array with the names of the supported cipher algorithms. + */ + function getCiphers(): string[]; + /** + * ```js + * const { + * getCurves, + * } = await import('node:crypto'); + * + * console.log(getCurves()); // ['Oakley-EC2N-3', 'Oakley-EC2N-4', ...] + * ``` + * @since v2.3.0 + * @return An array with the names of the supported elliptic curves. + */ + function getCurves(): string[]; + /** + * @since v10.0.0 + * @return `1` if and only if a FIPS compliant crypto provider is currently in use, `0` otherwise. A future semver-major release may change the return type of this API to a {boolean}. + */ + function getFips(): 1 | 0; + /** + * Enables the FIPS compliant crypto provider in a FIPS-enabled Node.js build. + * Throws an error if FIPS mode is not available. + * @since v10.0.0 + * @param bool `true` to enable FIPS mode. + */ + function setFips(bool: boolean): void; + /** + * ```js + * const { + * getHashes, + * } = await import('node:crypto'); + * + * console.log(getHashes()); // ['DSA', 'DSA-SHA', 'DSA-SHA1', ...] + * ``` + * @since v0.9.3 + * @return An array of the names of the supported hash algorithms, such as `'RSA-SHA256'`. Hash algorithms are also called "digest" algorithms. + */ + function getHashes(): string[]; + /** + * The `ECDH` class is a utility for creating Elliptic Curve Diffie-Hellman (ECDH) + * key exchanges. + * + * Instances of the `ECDH` class can be created using the {@link createECDH} function. + * + * ```js + * import assert from 'node:assert'; + * + * const { + * createECDH, + * } = await import('node:crypto'); + * + * // Generate Alice's keys... + * const alice = createECDH('secp521r1'); + * const aliceKey = alice.generateKeys(); + * + * // Generate Bob's keys... + * const bob = createECDH('secp521r1'); + * const bobKey = bob.generateKeys(); + * + * // Exchange and generate the secret... + * const aliceSecret = alice.computeSecret(bobKey); + * const bobSecret = bob.computeSecret(aliceKey); + * + * assert.strictEqual(aliceSecret.toString('hex'), bobSecret.toString('hex')); + * // OK + * ``` + * @since v0.11.14 + */ + class ECDH { + private constructor(); + /** + * Converts the EC Diffie-Hellman public key specified by `key` and `curve` to the + * format specified by `format`. The `format` argument specifies point encoding + * and can be `'compressed'`, `'uncompressed'` or `'hybrid'`. The supplied key is + * interpreted using the specified `inputEncoding`, and the returned key is encoded + * using the specified `outputEncoding`. + * + * Use {@link getCurves} to obtain a list of available curve names. + * On recent OpenSSL releases, `openssl ecparam -list_curves` will also display + * the name and description of each available elliptic curve. + * + * If `format` is not specified the point will be returned in `'uncompressed'` format. + * + * If the `inputEncoding` is not provided, `key` is expected to be a `Buffer`, `TypedArray`, or `DataView`. + * + * Example (uncompressing a key): + * + * ```js + * const { + * createECDH, + * ECDH, + * } = await import('node:crypto'); + * + * const ecdh = createECDH('secp256k1'); + * ecdh.generateKeys(); + * + * const compressedKey = ecdh.getPublicKey('hex', 'compressed'); + * + * const uncompressedKey = ECDH.convertKey(compressedKey, + * 'secp256k1', + * 'hex', + * 'hex', + * 'uncompressed'); + * + * // The converted key and the uncompressed public key should be the same + * console.log(uncompressedKey === ecdh.getPublicKey('hex')); + * ``` + * @since v10.0.0 + * @param inputEncoding The `encoding` of the `key` string. + * @param outputEncoding The `encoding` of the return value. + * @param [format='uncompressed'] + */ + static convertKey( + key: BinaryLike, + curve: string, + inputEncoding?: BinaryToTextEncoding, + outputEncoding?: "latin1" | "hex" | "base64" | "base64url", + format?: "uncompressed" | "compressed" | "hybrid", + ): NonSharedBuffer | string; + /** + * Generates private and public EC Diffie-Hellman key values, and returns + * the public key in the specified `format` and `encoding`. This key should be + * transferred to the other party. + * + * The `format` argument specifies point encoding and can be `'compressed'` or `'uncompressed'`. If `format` is not specified, the point will be returned in`'uncompressed'` format. + * + * If `encoding` is provided a string is returned; otherwise a `Buffer` is returned. + * @since v0.11.14 + * @param encoding The `encoding` of the return value. + * @param [format='uncompressed'] + */ + generateKeys(): NonSharedBuffer; + generateKeys(encoding: BinaryToTextEncoding, format?: ECDHKeyFormat): string; + /** + * Computes the shared secret using `otherPublicKey` as the other + * party's public key and returns the computed shared secret. The supplied + * key is interpreted using specified `inputEncoding`, and the returned secret + * is encoded using the specified `outputEncoding`. + * If the `inputEncoding` is not + * provided, `otherPublicKey` is expected to be a `Buffer`, `TypedArray`, or `DataView`. + * + * If `outputEncoding` is given a string will be returned; otherwise a `Buffer` is returned. + * + * `ecdh.computeSecret` will throw an`ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY` error when `otherPublicKey` lies outside of the elliptic curve. Since `otherPublicKey` is + * usually supplied from a remote user over an insecure network, + * be sure to handle this exception accordingly. + * @since v0.11.14 + * @param inputEncoding The `encoding` of the `otherPublicKey` string. + * @param outputEncoding The `encoding` of the return value. + */ + computeSecret(otherPublicKey: NodeJS.ArrayBufferView): NonSharedBuffer; + computeSecret(otherPublicKey: string, inputEncoding: BinaryToTextEncoding): NonSharedBuffer; + computeSecret(otherPublicKey: NodeJS.ArrayBufferView, outputEncoding: BinaryToTextEncoding): string; + computeSecret( + otherPublicKey: string, + inputEncoding: BinaryToTextEncoding, + outputEncoding: BinaryToTextEncoding, + ): string; + /** + * If `encoding` is specified, a string is returned; otherwise a `Buffer` is + * returned. + * @since v0.11.14 + * @param encoding The `encoding` of the return value. + * @return The EC Diffie-Hellman in the specified `encoding`. + */ + getPrivateKey(): NonSharedBuffer; + getPrivateKey(encoding: BinaryToTextEncoding): string; + /** + * The `format` argument specifies point encoding and can be `'compressed'` or `'uncompressed'`. If `format` is not specified the point will be returned in`'uncompressed'` format. + * + * If `encoding` is specified, a string is returned; otherwise a `Buffer` is + * returned. + * @since v0.11.14 + * @param encoding The `encoding` of the return value. + * @param [format='uncompressed'] + * @return The EC Diffie-Hellman public key in the specified `encoding` and `format`. + */ + getPublicKey(encoding?: null, format?: ECDHKeyFormat): NonSharedBuffer; + getPublicKey(encoding: BinaryToTextEncoding, format?: ECDHKeyFormat): string; + /** + * Sets the EC Diffie-Hellman private key. + * If `encoding` is provided, `privateKey` is expected + * to be a string; otherwise `privateKey` is expected to be a `Buffer`, `TypedArray`, or `DataView`. + * + * If `privateKey` is not valid for the curve specified when the `ECDH` object was + * created, an error is thrown. Upon setting the private key, the associated + * public point (key) is also generated and set in the `ECDH` object. + * @since v0.11.14 + * @param encoding The `encoding` of the `privateKey` string. + */ + setPrivateKey(privateKey: NodeJS.ArrayBufferView): void; + setPrivateKey(privateKey: string, encoding: BinaryToTextEncoding): void; + } + /** + * Creates an Elliptic Curve Diffie-Hellman (`ECDH`) key exchange object using a + * predefined curve specified by the `curveName` string. Use {@link getCurves} to obtain a list of available curve names. On recent + * OpenSSL releases, `openssl ecparam -list_curves` will also display the name + * and description of each available elliptic curve. + * @since v0.11.14 + */ + function createECDH(curveName: string): ECDH; + /** + * This function compares the underlying bytes that represent the given `ArrayBuffer`, `TypedArray`, or `DataView` instances using a constant-time + * algorithm. + * + * This function does not leak timing information that + * would allow an attacker to guess one of the values. This is suitable for + * comparing HMAC digests or secret values like authentication cookies or [capability urls](https://www.w3.org/TR/capability-urls/). + * + * `a` and `b` must both be `Buffer`s, `TypedArray`s, or `DataView`s, and they + * must have the same byte length. An error is thrown if `a` and `b` have + * different byte lengths. + * + * If at least one of `a` and `b` is a `TypedArray` with more than one byte per + * entry, such as `Uint16Array`, the result will be computed using the platform + * byte order. + * + * **When both of the inputs are `Float32Array`s or `Float64Array`s, this function might return unexpected results due to IEEE 754** + * **encoding of floating-point numbers. In particular, neither `x === y` nor `Object.is(x, y)` implies that the byte representations of two floating-point** + * **numbers `x` and `y` are equal.** + * + * Use of `crypto.timingSafeEqual` does not guarantee that the _surrounding_ code + * is timing-safe. Care should be taken to ensure that the surrounding code does + * not introduce timing vulnerabilities. + * @since v6.6.0 + */ + function timingSafeEqual(a: NodeJS.ArrayBufferView, b: NodeJS.ArrayBufferView): boolean; + interface DHKeyPairOptions extends KeyPairExportOptions<"spki", "pkcs8"> { + /** + * The prime parameter + */ + prime?: Buffer | undefined; + /** + * Prime length in bits + */ + primeLength?: number | undefined; + /** + * Custom generator + * @default 2 + */ + generator?: number | undefined; + /** + * Diffie-Hellman group name + * @see {@link getDiffieHellman} + */ + groupName?: string | undefined; + } + interface DSAKeyPairOptions extends KeyPairExportOptions<"spki", "pkcs8"> { + /** + * Key size in bits + */ + modulusLength: number; + /** + * Size of q in bits + */ + divisorLength: number; + } + interface ECKeyPairOptions extends KeyPairExportOptions<"spki", "pkcs8" | "sec1"> { + /** + * Name of the curve to use + */ + namedCurve: string; + /** + * Must be `'named'` or `'explicit'` + * @default 'named' + */ + paramEncoding?: "explicit" | "named" | undefined; + } + interface ED25519KeyPairOptions extends KeyPairExportOptions<"spki", "pkcs8"> {} + interface ED448KeyPairOptions extends KeyPairExportOptions<"spki", "pkcs8"> {} + interface MLDSAKeyPairOptions extends KeyPairExportOptions<"spki", "pkcs8"> {} + interface MLKEMKeyPairOptions extends KeyPairExportOptions<"spki", "pkcs8"> {} + interface RSAPSSKeyPairOptions extends KeyPairExportOptions<"spki", "pkcs8"> { + /** + * Key size in bits + */ + modulusLength: number; + /** + * Public exponent + * @default 0x10001 + */ + publicExponent?: number | undefined; + /** + * Name of the message digest + */ + hashAlgorithm?: string | undefined; + /** + * Name of the message digest used by MGF1 + */ + mgf1HashAlgorithm?: string | undefined; + /** + * Minimal salt length in bytes + */ + saltLength?: string | undefined; + } + interface RSAKeyPairOptions extends KeyPairExportOptions<"pkcs1" | "spki", "pkcs1" | "pkcs8"> { + /** + * Key size in bits + */ + modulusLength: number; + /** + * Public exponent + * @default 0x10001 + */ + publicExponent?: number | undefined; + } + interface SLHDSAKeyPairOptions extends KeyPairExportOptions<"spki", "pkcs8"> {} + interface X25519KeyPairOptions extends KeyPairExportOptions<"spki", "pkcs8"> {} + interface X448KeyPairOptions extends KeyPairExportOptions<"spki", "pkcs8"> {} + /** + * Generates a new asymmetric key pair of the given `type`. See the + * supported [asymmetric key types](https://nodejs.org/docs/latest-v25.x/api/crypto.html#asymmetric-key-types). + * + * If a `publicKeyEncoding` or `privateKeyEncoding` was specified, this function + * behaves as if `keyObject.export()` had been called on its result. Otherwise, + * the respective part of the key is returned as a `KeyObject`. + * + * When encoding public keys, it is recommended to use `'spki'`. When encoding + * private keys, it is recommended to use `'pkcs8'` with a strong passphrase, + * and to keep the passphrase confidential. + * + * ```js + * const { + * generateKeyPairSync, + * } = await import('node:crypto'); + * + * const { + * publicKey, + * privateKey, + * } = generateKeyPairSync('rsa', { + * modulusLength: 4096, + * publicKeyEncoding: { + * type: 'spki', + * format: 'pem', + * }, + * privateKeyEncoding: { + * type: 'pkcs8', + * format: 'pem', + * cipher: 'aes-256-cbc', + * passphrase: 'top secret', + * }, + * }); + * ``` + * + * The return value `{ publicKey, privateKey }` represents the generated key pair. + * When PEM encoding was selected, the respective key will be a string, otherwise + * it will be a buffer containing the data encoded as DER. + * @since v10.12.0 + * @param type The asymmetric key type to generate. See the + * supported [asymmetric key types](https://nodejs.org/docs/latest-v25.x/api/crypto.html#asymmetric-key-types). + */ + function generateKeyPairSync<T extends DHKeyPairOptions>( + type: "dh", + options: T, + ): KeyPairExportResult<T>; + function generateKeyPairSync<T extends DSAKeyPairOptions>( + type: "dsa", + options: T, + ): KeyPairExportResult<T>; + function generateKeyPairSync<T extends ECKeyPairOptions>( + type: "ec", + options: T, + ): KeyPairExportResult<T>; + function generateKeyPairSync<T extends ED25519KeyPairOptions = {}>( + type: "ed25519", + options?: T, + ): KeyPairExportResult<T>; + function generateKeyPairSync<T extends ED448KeyPairOptions = {}>( + type: "ed448", + options?: T, + ): KeyPairExportResult<T>; + function generateKeyPairSync<T extends MLDSAKeyPairOptions = {}>( + type: MLDSAKeyType, + options?: T, + ): KeyPairExportResult<T>; + function generateKeyPairSync<T extends MLKEMKeyPairOptions = {}>( + type: MLKEMKeyType, + options?: T, + ): KeyPairExportResult<T>; + function generateKeyPairSync<T extends RSAPSSKeyPairOptions>( + type: "rsa-pss", + options: T, + ): KeyPairExportResult<T>; + function generateKeyPairSync<T extends RSAKeyPairOptions>( + type: "rsa", + options: T, + ): KeyPairExportResult<T>; + function generateKeyPairSync<T extends SLHDSAKeyPairOptions = {}>( + type: SLHDSAKeyType, + options?: T, + ): KeyPairExportResult<T>; + function generateKeyPairSync<T extends X25519KeyPairOptions = {}>( + type: "x25519", + options?: T, + ): KeyPairExportResult<T>; + function generateKeyPairSync<T extends X448KeyPairOptions = {}>( + type: "x448", + options?: T, + ): KeyPairExportResult<T>; + /** + * Generates a new asymmetric key pair of the given `type`. See the + * supported [asymmetric key types](https://nodejs.org/docs/latest-v25.x/api/crypto.html#asymmetric-key-types). + * + * If a `publicKeyEncoding` or `privateKeyEncoding` was specified, this function + * behaves as if `keyObject.export()` had been called on its result. Otherwise, + * the respective part of the key is returned as a `KeyObject`. + * + * It is recommended to encode public keys as `'spki'` and private keys as `'pkcs8'` with encryption for long-term storage: + * + * ```js + * const { + * generateKeyPair, + * } = await import('node:crypto'); + * + * generateKeyPair('rsa', { + * modulusLength: 4096, + * publicKeyEncoding: { + * type: 'spki', + * format: 'pem', + * }, + * privateKeyEncoding: { + * type: 'pkcs8', + * format: 'pem', + * cipher: 'aes-256-cbc', + * passphrase: 'top secret', + * }, + * }, (err, publicKey, privateKey) => { + * // Handle errors and use the generated key pair. + * }); + * ``` + * + * On completion, `callback` will be called with `err` set to `undefined` and `publicKey` / `privateKey` representing the generated key pair. + * + * If this method is invoked as its `util.promisify()` ed version, it returns + * a `Promise` for an `Object` with `publicKey` and `privateKey` properties. + * @since v10.12.0 + * @param type The asymmetric key type to generate. See the + * supported [asymmetric key types](https://nodejs.org/docs/latest-v25.x/api/crypto.html#asymmetric-key-types). + */ + function generateKeyPair<T extends DHKeyPairOptions>( + type: "dh", + options: T, + callback: KeyPairExportCallback<T>, + ): void; + function generateKeyPair<T extends DSAKeyPairOptions>( + type: "dsa", + options: T, + callback: KeyPairExportCallback<T>, + ): void; + function generateKeyPair<T extends ECKeyPairOptions>( + type: "ec", + options: T, + callback: KeyPairExportCallback<T>, + ): void; + function generateKeyPair<T extends ED25519KeyPairOptions = {}>( + type: "ed25519", + options: T | undefined, + callback: KeyPairExportCallback<T>, + ): void; + function generateKeyPair<T extends ED448KeyPairOptions = {}>( + type: "ed448", + options: T | undefined, + callback: KeyPairExportCallback<T>, + ): void; + function generateKeyPair<T extends MLDSAKeyPairOptions = {}>( + type: MLDSAKeyType, + options: T | undefined, + callback: KeyPairExportCallback<T>, + ): void; + function generateKeyPair<T extends MLKEMKeyPairOptions = {}>( + type: MLKEMKeyType, + options: T | undefined, + callback: KeyPairExportCallback<T>, + ): void; + function generateKeyPair<T extends RSAPSSKeyPairOptions>( + type: "rsa-pss", + options: T, + callback: KeyPairExportCallback<T>, + ): void; + function generateKeyPair<T extends RSAKeyPairOptions>( + type: "rsa", + options: T, + callback: KeyPairExportCallback<T>, + ): void; + function generateKeyPair<T extends SLHDSAKeyPairOptions = {}>( + type: SLHDSAKeyType, + options: T | undefined, + callback: KeyPairExportCallback<T>, + ): void; + function generateKeyPair<T extends X25519KeyPairOptions = {}>( + type: "x25519", + options: T | undefined, + callback: KeyPairExportCallback<T>, + ): void; + function generateKeyPair<T extends X448KeyPairOptions = {}>( + type: "x448", + options: T | undefined, + callback: KeyPairExportCallback<T>, + ): void; + namespace generateKeyPair { + function __promisify__<T extends DHKeyPairOptions>( + type: "dh", + options: T, + ): Promise<KeyPairExportResult<T>>; + function __promisify__<T extends DSAKeyPairOptions>( + type: "dsa", + options: T, + ): Promise<KeyPairExportResult<T>>; + function __promisify__<T extends ECKeyPairOptions>( + type: "ec", + options: T, + ): Promise<KeyPairExportResult<T>>; + function __promisify__<T extends ED25519KeyPairOptions = {}>( + type: "ed25519", + options?: T, + ): Promise<KeyPairExportResult<T>>; + function __promisify__<T extends ED448KeyPairOptions = {}>( + type: "ed448", + options?: T, + ): Promise<KeyPairExportResult<T>>; + function __promisify__<T extends MLDSAKeyPairOptions = {}>( + type: MLDSAKeyType, + options?: T, + ): Promise<KeyPairExportResult<T>>; + function __promisify__<T extends MLKEMKeyPairOptions = {}>( + type: MLKEMKeyType, + options?: T, + ): Promise<KeyPairExportResult<T>>; + function __promisify__<T extends RSAPSSKeyPairOptions>( + type: "rsa-pss", + options: T, + ): Promise<KeyPairExportResult<T>>; + function __promisify__<T extends RSAKeyPairOptions>( + type: "rsa", + options: T, + ): Promise<KeyPairExportResult<T>>; + function __promisify__<T extends SLHDSAKeyPairOptions = {}>( + type: SLHDSAKeyType, + options?: T, + ): Promise<KeyPairExportResult<T>>; + function __promisify__<T extends X25519KeyPairOptions = {}>( + type: "x25519", + options?: T, + ): Promise<KeyPairExportResult<T>>; + function __promisify__<T extends X448KeyPairOptions = {}>( + type: "x448", + options?: T, + ): Promise<KeyPairExportResult<T>>; + } + /** + * Calculates and returns the signature for `data` using the given private key and + * algorithm. If `algorithm` is `null` or `undefined`, then the algorithm is + * dependent upon the key type. + * + * `algorithm` is required to be `null` or `undefined` for Ed25519, Ed448, and + * ML-DSA. + * + * If `key` is not a `KeyObject`, this function behaves as if `key` had been + * passed to {@link createPrivateKey}. If it is an object, the following + * additional properties can be passed: + * + * If the `callback` function is provided this function uses libuv's threadpool. + * @since v12.0.0 + */ + function sign( + algorithm: string | null | undefined, + data: NodeJS.ArrayBufferView, + key: KeyLike | SignKeyObjectInput | SignPrivateKeyInput | SignJsonWebKeyInput, + ): NonSharedBuffer; + function sign( + algorithm: string | null | undefined, + data: NodeJS.ArrayBufferView, + key: KeyLike | SignKeyObjectInput | SignPrivateKeyInput | SignJsonWebKeyInput, + callback: (error: Error | null, data: NonSharedBuffer) => void, + ): void; + /** + * Verifies the given signature for `data` using the given key and algorithm. If + * `algorithm` is `null` or `undefined`, then the algorithm is dependent upon the + * key type. + * + * `algorithm` is required to be `null` or `undefined` for Ed25519, Ed448, and + * ML-DSA. + * + * If `key` is not a `KeyObject`, this function behaves as if `key` had been + * passed to {@link createPublicKey}. If it is an object, the following + * additional properties can be passed: + * + * The `signature` argument is the previously calculated signature for the `data`. + * + * Because public keys can be derived from private keys, a private key or a public + * key may be passed for `key`. + * + * If the `callback` function is provided this function uses libuv's threadpool. + * @since v12.0.0 + */ + function verify( + algorithm: string | null | undefined, + data: NodeJS.ArrayBufferView, + key: KeyLike | VerifyKeyObjectInput | VerifyPublicKeyInput | VerifyJsonWebKeyInput, + signature: NodeJS.ArrayBufferView, + ): boolean; + function verify( + algorithm: string | null | undefined, + data: NodeJS.ArrayBufferView, + key: KeyLike | VerifyKeyObjectInput | VerifyPublicKeyInput | VerifyJsonWebKeyInput, + signature: NodeJS.ArrayBufferView, + callback: (error: Error | null, result: boolean) => void, + ): void; + /** + * Key decapsulation using a KEM algorithm with a private key. + * + * Supported key types and their KEM algorithms are: + * + * * `'rsa'` RSA Secret Value Encapsulation + * * `'ec'` DHKEM(P-256, HKDF-SHA256), DHKEM(P-384, HKDF-SHA256), DHKEM(P-521, HKDF-SHA256) + * * `'x25519'` DHKEM(X25519, HKDF-SHA256) + * * `'x448'` DHKEM(X448, HKDF-SHA512) + * * `'ml-kem-512'` ML-KEM + * * `'ml-kem-768'` ML-KEM + * * `'ml-kem-1024'` ML-KEM + * + * If `key` is not a {@link KeyObject}, this function behaves as if `key` had been + * passed to `crypto.createPrivateKey()`. + * + * If the `callback` function is provided this function uses libuv's threadpool. + * @since v24.7.0 + */ + function decapsulate( + key: KeyLike | PrivateKeyInput | JsonWebKeyInput, + ciphertext: ArrayBuffer | NodeJS.ArrayBufferView, + ): NonSharedBuffer; + function decapsulate( + key: KeyLike | PrivateKeyInput | JsonWebKeyInput, + ciphertext: ArrayBuffer | NodeJS.ArrayBufferView, + callback: (err: Error, sharedKey: NonSharedBuffer) => void, + ): void; + /** + * Computes the Diffie-Hellman shared secret based on a `privateKey` and a `publicKey`. + * Both keys must have the same `asymmetricKeyType` and must support either the DH or + * ECDH operation. + * + * If the `callback` function is provided this function uses libuv's threadpool. + * @since v13.9.0, v12.17.0 + */ + function diffieHellman(options: { privateKey: KeyObject; publicKey: KeyObject }): NonSharedBuffer; + function diffieHellman( + options: { privateKey: KeyObject; publicKey: KeyObject }, + callback: (err: Error | null, secret: NonSharedBuffer) => void, + ): void; + /** + * Key encapsulation using a KEM algorithm with a public key. + * + * Supported key types and their KEM algorithms are: + * + * * `'rsa'` RSA Secret Value Encapsulation + * * `'ec'` DHKEM(P-256, HKDF-SHA256), DHKEM(P-384, HKDF-SHA256), DHKEM(P-521, HKDF-SHA256) + * * `'x25519'` DHKEM(X25519, HKDF-SHA256) + * * `'x448'` DHKEM(X448, HKDF-SHA512) + * * `'ml-kem-512'` ML-KEM + * * `'ml-kem-768'` ML-KEM + * * `'ml-kem-1024'` ML-KEM + * + * If `key` is not a {@link KeyObject}, this function behaves as if `key` had been + * passed to `crypto.createPublicKey()`. + * + * If the `callback` function is provided this function uses libuv's threadpool. + * @since v24.7.0 + */ + function encapsulate( + key: KeyLike | PublicKeyInput | JsonWebKeyInput, + ): { sharedKey: NonSharedBuffer; ciphertext: NonSharedBuffer }; + function encapsulate( + key: KeyLike | PublicKeyInput | JsonWebKeyInput, + callback: (err: Error, result: { sharedKey: NonSharedBuffer; ciphertext: NonSharedBuffer }) => void, + ): void; + interface OneShotDigestOptions { + /** + * Encoding used to encode the returned digest. + * @default 'hex' + */ + outputEncoding?: BinaryToTextEncoding | "buffer" | undefined; + /** + * For XOF hash functions such as 'shake256', the outputLength option + * can be used to specify the desired output length in bytes. + */ + outputLength?: number | undefined; + } + interface OneShotDigestOptionsWithStringEncoding extends OneShotDigestOptions { + outputEncoding?: BinaryToTextEncoding | undefined; + } + interface OneShotDigestOptionsWithBufferEncoding extends OneShotDigestOptions { + outputEncoding: "buffer"; + } + /** + * A utility for creating one-shot hash digests of data. It can be faster than + * the object-based `crypto.createHash()` when hashing a smaller amount of data + * (<= 5MB) that's readily available. If the data can be big or if it is streamed, + * it's still recommended to use `crypto.createHash()` instead. + * + * The `algorithm` is dependent on the available algorithms supported by the + * version of OpenSSL on the platform. Examples are `'sha256'`, `'sha512'`, etc. + * On recent releases of OpenSSL, `openssl list -digest-algorithms` will + * display the available digest algorithms. + * + * If `options` is a string, then it specifies the `outputEncoding`. + * + * Example: + * + * ```js + * import crypto from 'node:crypto'; + * import { Buffer } from 'node:buffer'; + * + * // Hashing a string and return the result as a hex-encoded string. + * const string = 'Node.js'; + * // 10b3493287f831e81a438811a1ffba01f8cec4b7 + * console.log(crypto.hash('sha1', string)); + * + * // Encode a base64-encoded string into a Buffer, hash it and return + * // the result as a buffer. + * const base64 = 'Tm9kZS5qcw=='; + * // <Buffer 10 b3 49 32 87 f8 31 e8 1a 43 88 11 a1 ff ba 01 f8 ce c4 b7> + * console.log(crypto.hash('sha1', Buffer.from(base64, 'base64'), 'buffer')); + * ``` + * @since v21.7.0, v20.12.0 + * @param data When `data` is a string, it will be encoded as UTF-8 before being hashed. If a different + * input encoding is desired for a string input, user could encode the string + * into a `TypedArray` using either `TextEncoder` or `Buffer.from()` and passing + * the encoded `TypedArray` into this API instead. + */ + function hash( + algorithm: string, + data: BinaryLike, + options?: OneShotDigestOptionsWithStringEncoding | BinaryToTextEncoding, + ): string; + function hash( + algorithm: string, + data: BinaryLike, + options: OneShotDigestOptionsWithBufferEncoding | "buffer", + ): NonSharedBuffer; + function hash( + algorithm: string, + data: BinaryLike, + options: OneShotDigestOptions | BinaryToTextEncoding | "buffer", + ): string | NonSharedBuffer; + type CipherMode = "cbc" | "ccm" | "cfb" | "ctr" | "ecb" | "gcm" | "ocb" | "ofb" | "stream" | "wrap" | "xts"; + interface CipherInfoOptions { + /** + * A test key length. + */ + keyLength?: number | undefined; + /** + * A test IV length. + */ + ivLength?: number | undefined; + } + interface CipherInfo { + /** + * The name of the cipher. + */ + name: string; + /** + * The nid of the cipher. + */ + nid: number; + /** + * The block size of the cipher in bytes. + * This property is omitted when mode is 'stream'. + */ + blockSize?: number | undefined; + /** + * The expected or default initialization vector length in bytes. + * This property is omitted if the cipher does not use an initialization vector. + */ + ivLength?: number | undefined; + /** + * The expected or default key length in bytes. + */ + keyLength: number; + /** + * The cipher mode. + */ + mode: CipherMode; + } + /** + * Returns information about a given cipher. + * + * Some ciphers accept variable length keys and initialization vectors. By default, + * the `crypto.getCipherInfo()` method will return the default values for these + * ciphers. To test if a given key length or iv length is acceptable for given + * cipher, use the `keyLength` and `ivLength` options. If the given values are + * unacceptable, `undefined` will be returned. + * @since v15.0.0 + * @param nameOrNid The name or nid of the cipher to query. + */ + function getCipherInfo(nameOrNid: string | number, options?: CipherInfoOptions): CipherInfo | undefined; + /** + * HKDF is a simple key derivation function defined in RFC 5869\. The given `ikm`, `salt` and `info` are used with the `digest` to derive a key of `keylen` bytes. + * + * The supplied `callback` function is called with two arguments: `err` and `derivedKey`. If an errors occurs while deriving the key, `err` will be set; + * otherwise `err` will be `null`. The successfully generated `derivedKey` will + * be passed to the callback as an [ArrayBuffer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer). An error will be thrown if any + * of the input arguments specify invalid values or types. + * + * ```js + * import { Buffer } from 'node:buffer'; + * const { + * hkdf, + * } = await import('node:crypto'); + * + * hkdf('sha512', 'key', 'salt', 'info', 64, (err, derivedKey) => { + * if (err) throw err; + * console.log(Buffer.from(derivedKey).toString('hex')); // '24156e2...5391653' + * }); + * ``` + * @since v15.0.0 + * @param digest The digest algorithm to use. + * @param ikm The input keying material. Must be provided but can be zero-length. + * @param salt The salt value. Must be provided but can be zero-length. + * @param info Additional info value. Must be provided but can be zero-length, and cannot be more than 1024 bytes. + * @param keylen The length of the key to generate. Must be greater than 0. The maximum allowable value is `255` times the number of bytes produced by the selected digest function (e.g. `sha512` + * generates 64-byte hashes, making the maximum HKDF output 16320 bytes). + */ + function hkdf( + digest: string, + irm: BinaryLike | KeyObject, + salt: BinaryLike, + info: BinaryLike, + keylen: number, + callback: (err: Error | null, derivedKey: ArrayBuffer) => void, + ): void; + /** + * Provides a synchronous HKDF key derivation function as defined in RFC 5869\. The + * given `ikm`, `salt` and `info` are used with the `digest` to derive a key of `keylen` bytes. + * + * The successfully generated `derivedKey` will be returned as an [ArrayBuffer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer). + * + * An error will be thrown if any of the input arguments specify invalid values or + * types, or if the derived key cannot be generated. + * + * ```js + * import { Buffer } from 'node:buffer'; + * const { + * hkdfSync, + * } = await import('node:crypto'); + * + * const derivedKey = hkdfSync('sha512', 'key', 'salt', 'info', 64); + * console.log(Buffer.from(derivedKey).toString('hex')); // '24156e2...5391653' + * ``` + * @since v15.0.0 + * @param digest The digest algorithm to use. + * @param ikm The input keying material. Must be provided but can be zero-length. + * @param salt The salt value. Must be provided but can be zero-length. + * @param info Additional info value. Must be provided but can be zero-length, and cannot be more than 1024 bytes. + * @param keylen The length of the key to generate. Must be greater than 0. The maximum allowable value is `255` times the number of bytes produced by the selected digest function (e.g. `sha512` + * generates 64-byte hashes, making the maximum HKDF output 16320 bytes). + */ + function hkdfSync( + digest: string, + ikm: BinaryLike | KeyObject, + salt: BinaryLike, + info: BinaryLike, + keylen: number, + ): ArrayBuffer; + interface SecureHeapUsage { + /** + * The total allocated secure heap size as specified using the `--secure-heap=n` command-line flag. + */ + total: number; + /** + * The minimum allocation from the secure heap as specified using the `--secure-heap-min` command-line flag. + */ + min: number; + /** + * The total number of bytes currently allocated from the secure heap. + */ + used: number; + /** + * The calculated ratio of `used` to `total` allocated bytes. + */ + utilization: number; + } + /** + * @since v15.6.0 + */ + function secureHeapUsed(): SecureHeapUsage; + interface RandomUUIDOptions { + /** + * By default, to improve performance, + * Node.js will pre-emptively generate and persistently cache enough + * random data to generate up to 128 random UUIDs. To generate a UUID + * without using the cache, set `disableEntropyCache` to `true`. + * + * @default `false` + */ + disableEntropyCache?: boolean | undefined; + } + type UUID = `${string}-${string}-${string}-${string}-${string}`; + /** + * Generates a random [RFC 4122](https://www.rfc-editor.org/rfc/rfc4122.txt) version 4 UUID. The UUID is generated using a + * cryptographic pseudorandom number generator. + * @since v15.6.0, v14.17.0 + */ + function randomUUID(options?: RandomUUIDOptions): UUID; + interface X509CheckOptions { + /** + * @default 'always' + */ + subject?: "always" | "default" | "never" | undefined; + /** + * @default true + */ + wildcards?: boolean | undefined; + /** + * @default true + */ + partialWildcards?: boolean | undefined; + /** + * @default false + */ + multiLabelWildcards?: boolean | undefined; + /** + * @default false + */ + singleLabelSubdomains?: boolean | undefined; + } + /** + * Encapsulates an X509 certificate and provides read-only access to + * its information. + * + * ```js + * const { X509Certificate } = await import('node:crypto'); + * + * const x509 = new X509Certificate('{... pem encoded cert ...}'); + * + * console.log(x509.subject); + * ``` + * @since v15.6.0 + */ + class X509Certificate { + /** + * Will be \`true\` if this is a Certificate Authority (CA) certificate. + * @since v15.6.0 + */ + readonly ca: boolean; + /** + * The SHA-1 fingerprint of this certificate. + * + * Because SHA-1 is cryptographically broken and because the security of SHA-1 is + * significantly worse than that of algorithms that are commonly used to sign + * certificates, consider using `x509.fingerprint256` instead. + * @since v15.6.0 + */ + readonly fingerprint: string; + /** + * The SHA-256 fingerprint of this certificate. + * @since v15.6.0 + */ + readonly fingerprint256: string; + /** + * The SHA-512 fingerprint of this certificate. + * + * Because computing the SHA-256 fingerprint is usually faster and because it is + * only half the size of the SHA-512 fingerprint, `x509.fingerprint256` may be + * a better choice. While SHA-512 presumably provides a higher level of security in + * general, the security of SHA-256 matches that of most algorithms that are + * commonly used to sign certificates. + * @since v17.2.0, v16.14.0 + */ + readonly fingerprint512: string; + /** + * The complete subject of this certificate. + * @since v15.6.0 + */ + readonly subject: string; + /** + * The subject alternative name specified for this certificate. + * + * This is a comma-separated list of subject alternative names. Each entry begins + * with a string identifying the kind of the subject alternative name followed by + * a colon and the value associated with the entry. + * + * Earlier versions of Node.js incorrectly assumed that it is safe to split this + * property at the two-character sequence `', '` (see [CVE-2021-44532](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-44532)). However, + * both malicious and legitimate certificates can contain subject alternative names + * that include this sequence when represented as a string. + * + * After the prefix denoting the type of the entry, the remainder of each entry + * might be enclosed in quotes to indicate that the value is a JSON string literal. + * For backward compatibility, Node.js only uses JSON string literals within this + * property when necessary to avoid ambiguity. Third-party code should be prepared + * to handle both possible entry formats. + * @since v15.6.0 + */ + readonly subjectAltName: string | undefined; + /** + * A textual representation of the certificate's authority information access + * extension. + * + * This is a line feed separated list of access descriptions. Each line begins with + * the access method and the kind of the access location, followed by a colon and + * the value associated with the access location. + * + * After the prefix denoting the access method and the kind of the access location, + * the remainder of each line might be enclosed in quotes to indicate that the + * value is a JSON string literal. For backward compatibility, Node.js only uses + * JSON string literals within this property when necessary to avoid ambiguity. + * Third-party code should be prepared to handle both possible entry formats. + * @since v15.6.0 + */ + readonly infoAccess: string | undefined; + /** + * An array detailing the key usages for this certificate. + * @since v15.6.0 + */ + readonly keyUsage: string[]; + /** + * The issuer identification included in this certificate. + * @since v15.6.0 + */ + readonly issuer: string; + /** + * The issuer certificate or `undefined` if the issuer certificate is not + * available. + * @since v15.9.0 + */ + readonly issuerCertificate: X509Certificate | undefined; + /** + * The public key `KeyObject` for this certificate. + * @since v15.6.0 + */ + readonly publicKey: KeyObject; + /** + * A `Buffer` containing the DER encoding of this certificate. + * @since v15.6.0 + */ + readonly raw: NonSharedBuffer; + /** + * The serial number of this certificate. + * + * Serial numbers are assigned by certificate authorities and do not uniquely + * identify certificates. Consider using `x509.fingerprint256` as a unique + * identifier instead. + * @since v15.6.0 + */ + readonly serialNumber: string; + /** + * The algorithm used to sign the certificate or `undefined` if the signature algorithm is unknown by OpenSSL. + * @since v24.9.0 + */ + readonly signatureAlgorithm: string | undefined; + /** + * The OID of the algorithm used to sign the certificate. + * @since v24.9.0 + */ + readonly signatureAlgorithmOid: string; + /** + * The date/time from which this certificate is considered valid. + * @since v15.6.0 + */ + readonly validFrom: string; + /** + * The date/time from which this certificate is valid, encapsulated in a `Date` object. + * @since v22.10.0 + */ + readonly validFromDate: Date; + /** + * The date/time until which this certificate is considered valid. + * @since v15.6.0 + */ + readonly validTo: string; + /** + * The date/time until which this certificate is valid, encapsulated in a `Date` object. + * @since v22.10.0 + */ + readonly validToDate: Date; + constructor(buffer: BinaryLike); + /** + * Checks whether the certificate matches the given email address. + * + * If the `'subject'` option is undefined or set to `'default'`, the certificate + * subject is only considered if the subject alternative name extension either does + * not exist or does not contain any email addresses. + * + * If the `'subject'` option is set to `'always'` and if the subject alternative + * name extension either does not exist or does not contain a matching email + * address, the certificate subject is considered. + * + * If the `'subject'` option is set to `'never'`, the certificate subject is never + * considered, even if the certificate contains no subject alternative names. + * @since v15.6.0 + * @return Returns `email` if the certificate matches, `undefined` if it does not. + */ + checkEmail(email: string, options?: Pick<X509CheckOptions, "subject">): string | undefined; + /** + * Checks whether the certificate matches the given host name. + * + * If the certificate matches the given host name, the matching subject name is + * returned. The returned name might be an exact match (e.g., `foo.example.com`) + * or it might contain wildcards (e.g., `*.example.com`). Because host name + * comparisons are case-insensitive, the returned subject name might also differ + * from the given `name` in capitalization. + * + * If the `'subject'` option is undefined or set to `'default'`, the certificate + * subject is only considered if the subject alternative name extension either does + * not exist or does not contain any DNS names. This behavior is consistent with [RFC 2818](https://www.rfc-editor.org/rfc/rfc2818.txt) ("HTTP Over TLS"). + * + * If the `'subject'` option is set to `'always'` and if the subject alternative + * name extension either does not exist or does not contain a matching DNS name, + * the certificate subject is considered. + * + * If the `'subject'` option is set to `'never'`, the certificate subject is never + * considered, even if the certificate contains no subject alternative names. + * @since v15.6.0 + * @return Returns a subject name that matches `name`, or `undefined` if no subject name matches `name`. + */ + checkHost(name: string, options?: X509CheckOptions): string | undefined; + /** + * Checks whether the certificate matches the given IP address (IPv4 or IPv6). + * + * Only [RFC 5280](https://www.rfc-editor.org/rfc/rfc5280.txt) `iPAddress` subject alternative names are considered, and they + * must match the given `ip` address exactly. Other subject alternative names as + * well as the subject field of the certificate are ignored. + * @since v15.6.0 + * @return Returns `ip` if the certificate matches, `undefined` if it does not. + */ + checkIP(ip: string): string | undefined; + /** + * Checks whether this certificate was potentially issued by the given `otherCert` + * by comparing the certificate metadata. + * + * This is useful for pruning a list of possible issuer certificates which have been + * selected using a more rudimentary filtering routine, i.e. just based on subject + * and issuer names. + * + * Finally, to verify that this certificate's signature was produced by a private key + * corresponding to `otherCert`'s public key use `x509.verify(publicKey)` + * with `otherCert`'s public key represented as a `KeyObject` + * like so + * + * ```js + * if (!x509.verify(otherCert.publicKey)) { + * throw new Error('otherCert did not issue x509'); + * } + * ``` + * @since v15.6.0 + */ + checkIssued(otherCert: X509Certificate): boolean; + /** + * Checks whether the public key for this certificate is consistent with + * the given private key. + * @since v15.6.0 + * @param privateKey A private key. + */ + checkPrivateKey(privateKey: KeyObject): boolean; + /** + * There is no standard JSON encoding for X509 certificates. The`toJSON()` method returns a string containing the PEM encoded + * certificate. + * @since v15.6.0 + */ + toJSON(): string; + /** + * Returns information about this certificate using the legacy `certificate object` encoding. + * @since v15.6.0 + */ + toLegacyObject(): PeerCertificate; + /** + * Returns the PEM-encoded certificate. + * @since v15.6.0 + */ + toString(): string; + /** + * Verifies that this certificate was signed by the given public key. + * Does not perform any other validation checks on the certificate. + * @since v15.6.0 + * @param publicKey A public key. + */ + verify(publicKey: KeyObject): boolean; + } + type LargeNumberLike = NodeJS.ArrayBufferView | SharedArrayBuffer | ArrayBuffer | bigint; + interface GeneratePrimeOptions { + add?: LargeNumberLike | undefined; + rem?: LargeNumberLike | undefined; + /** + * @default false + */ + safe?: boolean | undefined; + bigint?: boolean | undefined; + } + interface GeneratePrimeOptionsBigInt extends GeneratePrimeOptions { + bigint: true; + } + interface GeneratePrimeOptionsArrayBuffer extends GeneratePrimeOptions { + bigint?: false | undefined; + } + /** + * Generates a pseudorandom prime of `size` bits. + * + * If `options.safe` is `true`, the prime will be a safe prime -- that is, `(prime - 1) / 2` will also be a prime. + * + * The `options.add` and `options.rem` parameters can be used to enforce additional + * requirements, e.g., for Diffie-Hellman: + * + * * If `options.add` and `options.rem` are both set, the prime will satisfy the + * condition that `prime % add = rem`. + * * If only `options.add` is set and `options.safe` is not `true`, the prime will + * satisfy the condition that `prime % add = 1`. + * * If only `options.add` is set and `options.safe` is set to `true`, the prime + * will instead satisfy the condition that `prime % add = 3`. This is necessary + * because `prime % add = 1` for `options.add > 2` would contradict the condition + * enforced by `options.safe`. + * * `options.rem` is ignored if `options.add` is not given. + * + * Both `options.add` and `options.rem` must be encoded as big-endian sequences + * if given as an `ArrayBuffer`, `SharedArrayBuffer`, `TypedArray`, `Buffer`, or `DataView`. + * + * By default, the prime is encoded as a big-endian sequence of octets + * in an [ArrayBuffer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer). If the `bigint` option is `true`, then a + * [bigint](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) is provided. + * @since v15.8.0 + * @param size The size (in bits) of the prime to generate. + */ + function generatePrime(size: number, callback: (err: Error | null, prime: ArrayBuffer) => void): void; + function generatePrime( + size: number, + options: GeneratePrimeOptionsBigInt, + callback: (err: Error | null, prime: bigint) => void, + ): void; + function generatePrime( + size: number, + options: GeneratePrimeOptionsArrayBuffer, + callback: (err: Error | null, prime: ArrayBuffer) => void, + ): void; + function generatePrime( + size: number, + options: GeneratePrimeOptions, + callback: (err: Error | null, prime: ArrayBuffer | bigint) => void, + ): void; + /** + * Generates a pseudorandom prime of `size` bits. + * + * If `options.safe` is `true`, the prime will be a safe prime -- that is, `(prime - 1) / 2` will also be a prime. + * + * The `options.add` and `options.rem` parameters can be used to enforce additional + * requirements, e.g., for Diffie-Hellman: + * + * * If `options.add` and `options.rem` are both set, the prime will satisfy the + * condition that `prime % add = rem`. + * * If only `options.add` is set and `options.safe` is not `true`, the prime will + * satisfy the condition that `prime % add = 1`. + * * If only `options.add` is set and `options.safe` is set to `true`, the prime + * will instead satisfy the condition that `prime % add = 3`. This is necessary + * because `prime % add = 1` for `options.add > 2` would contradict the condition + * enforced by `options.safe`. + * * `options.rem` is ignored if `options.add` is not given. + * + * Both `options.add` and `options.rem` must be encoded as big-endian sequences + * if given as an `ArrayBuffer`, `SharedArrayBuffer`, `TypedArray`, `Buffer`, or `DataView`. + * + * By default, the prime is encoded as a big-endian sequence of octets + * in an [ArrayBuffer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer). If the `bigint` option is `true`, then a + * [bigint](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) is provided. + * @since v15.8.0 + * @param size The size (in bits) of the prime to generate. + */ + function generatePrimeSync(size: number): ArrayBuffer; + function generatePrimeSync(size: number, options: GeneratePrimeOptionsBigInt): bigint; + function generatePrimeSync(size: number, options: GeneratePrimeOptionsArrayBuffer): ArrayBuffer; + function generatePrimeSync(size: number, options: GeneratePrimeOptions): ArrayBuffer | bigint; + interface CheckPrimeOptions { + /** + * The number of Miller-Rabin probabilistic primality iterations to perform. + * When the value is 0 (zero), a number of checks is used that yields a false positive rate of at most `2**-64` for random input. + * Care must be used when selecting a number of checks. + * Refer to the OpenSSL documentation for the BN_is_prime_ex function nchecks options for more details. + * + * @default 0 + */ + checks?: number | undefined; + } + /** + * Checks the primality of the `candidate`. + * @since v15.8.0 + * @param candidate A possible prime encoded as a sequence of big endian octets of arbitrary length. + */ + function checkPrime(value: LargeNumberLike, callback: (err: Error | null, result: boolean) => void): void; + function checkPrime( + value: LargeNumberLike, + options: CheckPrimeOptions, + callback: (err: Error | null, result: boolean) => void, + ): void; + /** + * Checks the primality of the `candidate`. + * @since v15.8.0 + * @param candidate A possible prime encoded as a sequence of big endian octets of arbitrary length. + * @return `true` if the candidate is a prime with an error probability less than `0.25 ** options.checks`. + */ + function checkPrimeSync(candidate: LargeNumberLike, options?: CheckPrimeOptions): boolean; + /** + * Load and set the `engine` for some or all OpenSSL functions (selected by flags). + * + * `engine` could be either an id or a path to the engine's shared library. + * + * The optional `flags` argument uses `ENGINE_METHOD_ALL` by default. The `flags` is a bit field taking one of or a mix of the following flags (defined in `crypto.constants`): + * + * * `crypto.constants.ENGINE_METHOD_RSA` + * * `crypto.constants.ENGINE_METHOD_DSA` + * * `crypto.constants.ENGINE_METHOD_DH` + * * `crypto.constants.ENGINE_METHOD_RAND` + * * `crypto.constants.ENGINE_METHOD_EC` + * * `crypto.constants.ENGINE_METHOD_CIPHERS` + * * `crypto.constants.ENGINE_METHOD_DIGESTS` + * * `crypto.constants.ENGINE_METHOD_PKEY_METHS` + * * `crypto.constants.ENGINE_METHOD_PKEY_ASN1_METHS` + * * `crypto.constants.ENGINE_METHOD_ALL` + * * `crypto.constants.ENGINE_METHOD_NONE` + * @since v0.11.11 + * @param flags + */ + function setEngine(engine: string, flags?: number): void; + /** + * A convenient alias for {@link webcrypto.getRandomValues}. This + * implementation is not compliant with the Web Crypto spec, to write + * web-compatible code use {@link webcrypto.getRandomValues} instead. + * @since v17.4.0 + * @return Returns `typedArray`. + */ + function getRandomValues< + T extends Exclude< + NodeJS.NonSharedTypedArray, + NodeJS.NonSharedFloat16Array | NodeJS.NonSharedFloat32Array | NodeJS.NonSharedFloat64Array + >, + >(typedArray: T): T; + type Argon2Algorithm = "argon2d" | "argon2i" | "argon2id"; + interface Argon2Parameters { + /** + * REQUIRED, this is the password for password hashing applications of Argon2. + */ + message: string | ArrayBuffer | NodeJS.ArrayBufferView; + /** + * REQUIRED, must be at least 8 bytes long. This is the salt for password hashing applications of Argon2. + */ + nonce: string | ArrayBuffer | NodeJS.ArrayBufferView; + /** + * REQUIRED, degree of parallelism determines how many computational chains (lanes) + * can be run. Must be greater than 1 and less than `2**24-1`. + */ + parallelism: number; + /** + * REQUIRED, the length of the key to generate. Must be greater than 4 and + * less than `2**32-1`. + */ + tagLength: number; + /** + * REQUIRED, memory cost in 1KiB blocks. Must be greater than + * `8 * parallelism` and less than `2**32-1`. The actual number of blocks is rounded + * down to the nearest multiple of `4 * parallelism`. + */ + memory: number; + /** + * REQUIRED, number of passes (iterations). Must be greater than 1 and less + * than `2**32-1`. + */ + passes: number; + /** + * OPTIONAL, Random additional input, + * similar to the salt, that should **NOT** be stored with the derived key. This is known as pepper in + * password hashing applications. If used, must have a length not greater than `2**32-1` bytes. + */ + secret?: string | ArrayBuffer | NodeJS.ArrayBufferView | undefined; + /** + * OPTIONAL, Additional data to + * be added to the hash, functionally equivalent to salt or secret, but meant for + * non-random data. If used, must have a length not greater than `2**32-1` bytes. + */ + associatedData?: string | ArrayBuffer | NodeJS.ArrayBufferView | undefined; + } + /** + * Provides an asynchronous [Argon2](https://www.rfc-editor.org/rfc/rfc9106.html) implementation. Argon2 is a password-based + * key derivation function that is designed to be expensive computationally and + * memory-wise in order to make brute-force attacks unrewarding. + * + * The `nonce` should be as unique as possible. It is recommended that a nonce is + * random and at least 16 bytes long. See [NIST SP 800-132](https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-132.pdf) for details. + * + * When passing strings for `message`, `nonce`, `secret` or `associatedData`, please + * consider [caveats when using strings as inputs to cryptographic APIs](https://nodejs.org/docs/latest-v25.x/api/crypto.html#using-strings-as-inputs-to-cryptographic-apis). + * + * The `callback` function is called with two arguments: `err` and `derivedKey`. + * `err` is an exception object when key derivation fails, otherwise `err` is + * `null`. `derivedKey` is passed to the callback as a `Buffer`. + * + * An exception is thrown when any of the input arguments specify invalid values + * or types. + * + * ```js + * const { argon2, randomBytes } = await import('node:crypto'); + * + * const parameters = { + * message: 'password', + * nonce: randomBytes(16), + * parallelism: 4, + * tagLength: 64, + * memory: 65536, + * passes: 3, + * }; + * + * argon2('argon2id', parameters, (err, derivedKey) => { + * if (err) throw err; + * console.log(derivedKey.toString('hex')); // 'af91dad...9520f15' + * }); + * ``` + * @since v24.7.0 + * @param algorithm Variant of Argon2, one of `"argon2d"`, `"argon2i"` or `"argon2id"`. + * @experimental + */ + function argon2( + algorithm: Argon2Algorithm, + parameters: Argon2Parameters, + callback: (err: Error | null, derivedKey: NonSharedBuffer) => void, + ): void; + /** + * Provides a synchronous [Argon2][] implementation. Argon2 is a password-based + * key derivation function that is designed to be expensive computationally and + * memory-wise in order to make brute-force attacks unrewarding. + * + * The `nonce` should be as unique as possible. It is recommended that a nonce is + * random and at least 16 bytes long. See [NIST SP 800-132](https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-132.pdf) for details. + * + * When passing strings for `message`, `nonce`, `secret` or `associatedData`, please + * consider [caveats when using strings as inputs to cryptographic APIs](https://nodejs.org/docs/latest-v25.x/api/crypto.html#using-strings-as-inputs-to-cryptographic-apis). + * + * An exception is thrown when key derivation fails, otherwise the derived key is + * returned as a `Buffer`. + * + * An exception is thrown when any of the input arguments specify invalid values + * or types. + * + * ```js + * const { argon2Sync, randomBytes } = await import('node:crypto'); + * + * const parameters = { + * message: 'password', + * nonce: randomBytes(16), + * parallelism: 4, + * tagLength: 64, + * memory: 65536, + * passes: 3, + * }; + * + * const derivedKey = argon2Sync('argon2id', parameters); + * console.log(derivedKey.toString('hex')); // 'af91dad...9520f15' + * ``` + * @since v24.7.0 + * @experimental + */ + function argon2Sync(algorithm: Argon2Algorithm, parameters: Argon2Parameters): NonSharedBuffer; + /** + * A convenient alias for `crypto.webcrypto.subtle`. + * @since v17.4.0 + */ + const subtle: webcrypto.SubtleCrypto; + /** + * An implementation of the Web Crypto API standard. + * + * See the {@link https://nodejs.org/docs/latest/api/webcrypto.html Web Crypto API documentation} for details. + * @since v15.0.0 + */ + const webcrypto: webcrypto.Crypto; + namespace webcrypto { + type AlgorithmIdentifier = Algorithm | string; + type BigInteger = NodeJS.NonSharedUint8Array; + type KeyFormat = "jwk" | "pkcs8" | "raw" | "raw-public" | "raw-secret" | "raw-seed" | "spki"; + type KeyType = "private" | "public" | "secret"; + type KeyUsage = + | "decapsulateBits" + | "decapsulateKey" + | "decrypt" + | "deriveBits" + | "deriveKey" + | "encapsulateBits" + | "encapsulateKey" + | "encrypt" + | "sign" + | "unwrapKey" + | "verify" + | "wrapKey"; + type HashAlgorithmIdentifier = AlgorithmIdentifier; + type NamedCurve = string; + interface AeadParams extends Algorithm { + additionalData?: NodeJS.BufferSource; + iv: NodeJS.BufferSource; + tagLength: number; + } + interface AesCbcParams extends Algorithm { + iv: NodeJS.BufferSource; + } + interface AesCtrParams extends Algorithm { + counter: NodeJS.BufferSource; + length: number; + } + interface AesDerivedKeyParams extends Algorithm { + length: number; + } + interface AesKeyAlgorithm extends KeyAlgorithm { + length: number; + } + interface AesKeyGenParams extends Algorithm { + length: number; + } + interface Algorithm { + name: string; + } + interface Argon2Params extends Algorithm { + associatedData?: NodeJS.BufferSource; + memory: number; + nonce: NodeJS.BufferSource; + parallelism: number; + passes: number; + secretValue?: NodeJS.BufferSource; + version?: number; + } + interface CShakeParams extends Algorithm { + customization?: NodeJS.BufferSource; + functionName?: NodeJS.BufferSource; + length: number; + } + interface ContextParams extends Algorithm { + context?: NodeJS.BufferSource; + } + interface EcKeyAlgorithm extends KeyAlgorithm { + namedCurve: NamedCurve; + } + interface EcKeyGenParams extends Algorithm { + namedCurve: NamedCurve; + } + interface EcKeyImportParams extends Algorithm { + namedCurve: NamedCurve; + } + interface EcdhKeyDeriveParams extends Algorithm { + public: CryptoKey; + } + interface EcdsaParams extends Algorithm { + hash: HashAlgorithmIdentifier; + } + interface HkdfParams extends Algorithm { + hash: HashAlgorithmIdentifier; + info: NodeJS.BufferSource; + salt: NodeJS.BufferSource; + } + interface HmacImportParams extends Algorithm { + hash: HashAlgorithmIdentifier; + length?: number; + } + interface HmacKeyAlgorithm extends KeyAlgorithm { + hash: KeyAlgorithm; + length: number; + } + interface HmacKeyGenParams extends Algorithm { + hash: HashAlgorithmIdentifier; + length?: number; + } + interface JsonWebKey { + alg?: string; + crv?: string; + d?: string; + dp?: string; + dq?: string; + e?: string; + ext?: boolean; + k?: string; + key_ops?: string[]; + kty?: string; + n?: string; + oth?: RsaOtherPrimesInfo[]; + p?: string; + q?: string; + qi?: string; + use?: string; + x?: string; + y?: string; + } + interface KeyAlgorithm { + name: string; + } + interface KmacImportParams extends Algorithm { + length?: number; + } + interface KmacKeyAlgorithm extends KeyAlgorithm { + length: number; + } + interface KmacKeyGenParams extends Algorithm { + length?: number; + } + interface KmacParams extends Algorithm { + customization?: NodeJS.BufferSource; + length: number; + } + interface Pbkdf2Params extends Algorithm { + hash: HashAlgorithmIdentifier; + iterations: number; + salt: NodeJS.BufferSource; + } + interface RsaHashedImportParams extends Algorithm { + hash: HashAlgorithmIdentifier; + } + interface RsaHashedKeyAlgorithm extends RsaKeyAlgorithm { + hash: KeyAlgorithm; + } + interface RsaHashedKeyGenParams extends RsaKeyGenParams { + hash: HashAlgorithmIdentifier; + } + interface RsaKeyAlgorithm extends KeyAlgorithm { + modulusLength: number; + publicExponent: BigInteger; + } + interface RsaKeyGenParams extends Algorithm { + modulusLength: number; + publicExponent: BigInteger; + } + interface RsaOaepParams extends Algorithm { + label?: NodeJS.BufferSource; + } + interface RsaOtherPrimesInfo { + d?: string; + r?: string; + t?: string; + } + interface RsaPssParams extends Algorithm { + saltLength: number; + } + interface Crypto { + readonly subtle: SubtleCrypto; + getRandomValues< + T extends Exclude< + NodeJS.NonSharedTypedArray, + NodeJS.NonSharedFloat16Array | NodeJS.NonSharedFloat32Array | NodeJS.NonSharedFloat64Array + >, + >( + typedArray: T, + ): T; + randomUUID(): UUID; + } + interface CryptoKey { + readonly algorithm: KeyAlgorithm; + readonly extractable: boolean; + readonly type: KeyType; + readonly usages: KeyUsage[]; + } + interface CryptoKeyPair { + privateKey: CryptoKey; + publicKey: CryptoKey; + } + interface EncapsulatedBits { + sharedKey: ArrayBuffer; + ciphertext: ArrayBuffer; + } + interface EncapsulatedKey { + sharedKey: CryptoKey; + ciphertext: ArrayBuffer; + } + interface SubtleCrypto { + decapsulateBits( + decapsulationAlgorithm: AlgorithmIdentifier, + decapsulationKey: CryptoKey, + ciphertext: NodeJS.BufferSource, + ): Promise<ArrayBuffer>; + decapsulateKey( + decapsulationAlgorithm: AlgorithmIdentifier, + decapsulationKey: CryptoKey, + ciphertext: NodeJS.BufferSource, + sharedKeyAlgorithm: AlgorithmIdentifier | HmacImportParams | AesDerivedKeyParams | KmacImportParams, + extractable: boolean, + usages: KeyUsage[], + ): Promise<CryptoKey>; + decrypt( + algorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AeadParams, + key: CryptoKey, + data: NodeJS.BufferSource, + ): Promise<ArrayBuffer>; + deriveBits( + algorithm: AlgorithmIdentifier | EcdhKeyDeriveParams | HkdfParams | Pbkdf2Params | Argon2Params, + baseKey: CryptoKey, + length?: number | null, + ): Promise<ArrayBuffer>; + deriveKey( + algorithm: AlgorithmIdentifier | EcdhKeyDeriveParams | HkdfParams | Pbkdf2Params | Argon2Params, + baseKey: CryptoKey, + derivedKeyType: AlgorithmIdentifier | AesDerivedKeyParams | HmacImportParams | KmacImportParams, + extractable: boolean, + keyUsages: readonly KeyUsage[], + ): Promise<CryptoKey>; + digest(algorithm: AlgorithmIdentifier | CShakeParams, data: NodeJS.BufferSource): Promise<ArrayBuffer>; + encapsulateBits( + encapsulationAlgorithm: AlgorithmIdentifier, + encapsulationKey: CryptoKey, + ): Promise<EncapsulatedBits>; + encapsulateKey( + encapsulationAlgorithm: AlgorithmIdentifier, + encapsulationKey: CryptoKey, + sharedKeyAlgorithm: AlgorithmIdentifier | AesDerivedKeyParams | HmacImportParams | KmacImportParams, + extractable: boolean, + usages: KeyUsage[], + ): Promise<EncapsulatedKey>; + encrypt( + algorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AeadParams, + key: CryptoKey, + data: NodeJS.BufferSource, + ): Promise<ArrayBuffer>; + exportKey(format: "jwk", key: CryptoKey): Promise<JsonWebKey>; + exportKey(format: Exclude<KeyFormat, "jwk">, key: CryptoKey): Promise<ArrayBuffer>; + exportKey(format: KeyFormat, key: CryptoKey): Promise<ArrayBuffer | JsonWebKey>; + generateKey( + algorithm: RsaHashedKeyGenParams | EcKeyGenParams, + extractable: boolean, + keyUsages: KeyUsage[], + ): Promise<CryptoKeyPair>; + generateKey( + algorithm: AesKeyGenParams | HmacKeyGenParams | Pbkdf2Params | KmacKeyGenParams, + extractable: boolean, + keyUsages: KeyUsage[], + ): Promise<CryptoKey>; + generateKey( + algorithm: AlgorithmIdentifier, + extractable: boolean, + keyUsages: KeyUsage[], + ): Promise<CryptoKeyPair | CryptoKey>; + getPublicKey(key: CryptoKey, keyUsages: KeyUsage[]): Promise<CryptoKey>; + importKey( + format: "jwk", + keyData: JsonWebKey, + algorithm: + | AlgorithmIdentifier + | RsaHashedImportParams + | EcKeyImportParams + | HmacImportParams + | AesKeyAlgorithm + | KmacImportParams, + extractable: boolean, + keyUsages: KeyUsage[], + ): Promise<CryptoKey>; + importKey( + format: Exclude<KeyFormat, "jwk">, + keyData: NodeJS.BufferSource, + algorithm: + | AlgorithmIdentifier + | RsaHashedImportParams + | EcKeyImportParams + | HmacImportParams + | AesKeyAlgorithm + | KmacImportParams, + extractable: boolean, + keyUsages: KeyUsage[], + ): Promise<CryptoKey>; + sign( + algorithm: AlgorithmIdentifier | RsaPssParams | EcdsaParams | ContextParams | KmacParams, + key: CryptoKey, + data: NodeJS.BufferSource, + ): Promise<ArrayBuffer>; + unwrapKey( + format: KeyFormat, + wrappedKey: NodeJS.BufferSource, + unwrappingKey: CryptoKey, + unwrapAlgorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AeadParams, + unwrappedKeyAlgorithm: + | AlgorithmIdentifier + | RsaHashedImportParams + | EcKeyImportParams + | HmacImportParams + | AesKeyAlgorithm + | KmacImportParams, + extractable: boolean, + keyUsages: KeyUsage[], + ): Promise<CryptoKey>; + verify( + algorithm: AlgorithmIdentifier | RsaPssParams | EcdsaParams | ContextParams | KmacParams, + key: CryptoKey, + signature: NodeJS.BufferSource, + data: NodeJS.BufferSource, + ): Promise<boolean>; + wrapKey( + format: KeyFormat, + key: CryptoKey, + wrappingKey: CryptoKey, + wrapAlgorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AeadParams, + ): Promise<ArrayBuffer>; + } + } +} +declare module "crypto" { + export * from "node:crypto"; +} diff --git a/server/node_modules/@types/node/dgram.d.ts b/server/node_modules/@types/node/dgram.d.ts new file mode 100644 index 0000000..3672e08 --- /dev/null +++ b/server/node_modules/@types/node/dgram.d.ts @@ -0,0 +1,564 @@ +/** + * The `node:dgram` module provides an implementation of UDP datagram sockets. + * + * ```js + * import dgram from 'node:dgram'; + * + * const server = dgram.createSocket('udp4'); + * + * server.on('error', (err) => { + * console.error(`server error:\n${err.stack}`); + * server.close(); + * }); + * + * server.on('message', (msg, rinfo) => { + * console.log(`server got: ${msg} from ${rinfo.address}:${rinfo.port}`); + * }); + * + * server.on('listening', () => { + * const address = server.address(); + * console.log(`server listening ${address.address}:${address.port}`); + * }); + * + * server.bind(41234); + * // Prints: server listening 0.0.0.0:41234 + * ``` + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/dgram.js) + */ +declare module "node:dgram" { + import { NonSharedBuffer } from "node:buffer"; + import * as dns from "node:dns"; + import { Abortable, EventEmitter, InternalEventEmitter } from "node:events"; + import { AddressInfo, BlockList } from "node:net"; + interface RemoteInfo { + address: string; + family: "IPv4" | "IPv6"; + port: number; + size: number; + } + interface BindOptions { + port?: number | undefined; + address?: string | undefined; + exclusive?: boolean | undefined; + fd?: number | undefined; + } + type SocketType = "udp4" | "udp6"; + interface SocketOptions extends Abortable { + type: SocketType; + reuseAddr?: boolean | undefined; + reusePort?: boolean | undefined; + /** + * @default false + */ + ipv6Only?: boolean | undefined; + recvBufferSize?: number | undefined; + sendBufferSize?: number | undefined; + lookup?: + | (( + hostname: string, + options: dns.LookupOneOptions, + callback: (err: NodeJS.ErrnoException | null, address: string, family: number) => void, + ) => void) + | undefined; + receiveBlockList?: BlockList | undefined; + sendBlockList?: BlockList | undefined; + } + /** + * Creates a `dgram.Socket` object. Once the socket is created, calling `socket.bind()` will instruct the socket to begin listening for datagram + * messages. When `address` and `port` are not passed to `socket.bind()` the + * method will bind the socket to the "all interfaces" address on a random port + * (it does the right thing for both `udp4` and `udp6` sockets). The bound address + * and port can be retrieved using `socket.address().address` and `socket.address().port`. + * + * If the `signal` option is enabled, calling `.abort()` on the corresponding `AbortController` is similar to calling `.close()` on the socket: + * + * ```js + * const controller = new AbortController(); + * const { signal } = controller; + * const server = dgram.createSocket({ type: 'udp4', signal }); + * server.on('message', (msg, rinfo) => { + * console.log(`server got: ${msg} from ${rinfo.address}:${rinfo.port}`); + * }); + * // Later, when you want to close the server. + * controller.abort(); + * ``` + * @since v0.11.13 + * @param options Available options are: + * @param callback Attached as a listener for `'message'` events. Optional. + */ + function createSocket(type: SocketType, callback?: (msg: NonSharedBuffer, rinfo: RemoteInfo) => void): Socket; + function createSocket(options: SocketOptions, callback?: (msg: NonSharedBuffer, rinfo: RemoteInfo) => void): Socket; + interface SocketEventMap { + "close": []; + "connect": []; + "error": [err: Error]; + "listening": []; + "message": [msg: NonSharedBuffer, rinfo: RemoteInfo]; + } + /** + * Encapsulates the datagram functionality. + * + * New instances of `dgram.Socket` are created using {@link createSocket}. + * The `new` keyword is not to be used to create `dgram.Socket` instances. + * @since v0.1.99 + */ + class Socket implements EventEmitter { + /** + * Tells the kernel to join a multicast group at the given `multicastAddress` and `multicastInterface` using the `IP_ADD_MEMBERSHIP` socket option. If the `multicastInterface` argument is not + * specified, the operating system will choose + * one interface and will add membership to it. To add membership to every + * available interface, call `addMembership` multiple times, once per interface. + * + * When called on an unbound socket, this method will implicitly bind to a random + * port, listening on all interfaces. + * + * When sharing a UDP socket across multiple `cluster` workers, the`socket.addMembership()` function must be called only once or an`EADDRINUSE` error will occur: + * + * ```js + * import cluster from 'node:cluster'; + * import dgram from 'node:dgram'; + * + * if (cluster.isPrimary) { + * cluster.fork(); // Works ok. + * cluster.fork(); // Fails with EADDRINUSE. + * } else { + * const s = dgram.createSocket('udp4'); + * s.bind(1234, () => { + * s.addMembership('224.0.0.114'); + * }); + * } + * ``` + * @since v0.6.9 + */ + addMembership(multicastAddress: string, multicastInterface?: string): void; + /** + * Returns an object containing the address information for a socket. + * For UDP sockets, this object will contain `address`, `family`, and `port` properties. + * + * This method throws `EBADF` if called on an unbound socket. + * @since v0.1.99 + */ + address(): AddressInfo; + /** + * For UDP sockets, causes the `dgram.Socket` to listen for datagram + * messages on a named `port` and optional `address`. If `port` is not + * specified or is `0`, the operating system will attempt to bind to a + * random port. If `address` is not specified, the operating system will + * attempt to listen on all addresses. Once binding is complete, a `'listening'` event is emitted and the optional `callback` function is + * called. + * + * Specifying both a `'listening'` event listener and passing a `callback` to the `socket.bind()` method is not harmful but not very + * useful. + * + * A bound datagram socket keeps the Node.js process running to receive + * datagram messages. + * + * If binding fails, an `'error'` event is generated. In rare case (e.g. + * attempting to bind with a closed socket), an `Error` may be thrown. + * + * Example of a UDP server listening on port 41234: + * + * ```js + * import dgram from 'node:dgram'; + * + * const server = dgram.createSocket('udp4'); + * + * server.on('error', (err) => { + * console.error(`server error:\n${err.stack}`); + * server.close(); + * }); + * + * server.on('message', (msg, rinfo) => { + * console.log(`server got: ${msg} from ${rinfo.address}:${rinfo.port}`); + * }); + * + * server.on('listening', () => { + * const address = server.address(); + * console.log(`server listening ${address.address}:${address.port}`); + * }); + * + * server.bind(41234); + * // Prints: server listening 0.0.0.0:41234 + * ``` + * @since v0.1.99 + * @param callback with no parameters. Called when binding is complete. + */ + bind(port?: number, address?: string, callback?: () => void): this; + bind(port?: number, callback?: () => void): this; + bind(callback?: () => void): this; + bind(options: BindOptions, callback?: () => void): this; + /** + * Close the underlying socket and stop listening for data on it. If a callback is + * provided, it is added as a listener for the `'close'` event. + * @since v0.1.99 + * @param callback Called when the socket has been closed. + */ + close(callback?: () => void): this; + /** + * Associates the `dgram.Socket` to a remote address and port. Every + * message sent by this handle is automatically sent to that destination. Also, + * the socket will only receive messages from that remote peer. + * Trying to call `connect()` on an already connected socket will result + * in an `ERR_SOCKET_DGRAM_IS_CONNECTED` exception. If `address` is not + * provided, `'127.0.0.1'` (for `udp4` sockets) or `'::1'` (for `udp6` sockets) + * will be used by default. Once the connection is complete, a `'connect'` event + * is emitted and the optional `callback` function is called. In case of failure, + * the `callback` is called or, failing this, an `'error'` event is emitted. + * @since v12.0.0 + * @param callback Called when the connection is completed or on error. + */ + connect(port: number, address?: string, callback?: () => void): void; + connect(port: number, callback: () => void): void; + /** + * A synchronous function that disassociates a connected `dgram.Socket` from + * its remote address. Trying to call `disconnect()` on an unbound or already + * disconnected socket will result in an `ERR_SOCKET_DGRAM_NOT_CONNECTED` exception. + * @since v12.0.0 + */ + disconnect(): void; + /** + * Instructs the kernel to leave a multicast group at `multicastAddress` using the `IP_DROP_MEMBERSHIP` socket option. This method is automatically called by the + * kernel when the socket is closed or the process terminates, so most apps will + * never have reason to call this. + * + * If `multicastInterface` is not specified, the operating system will attempt to + * drop membership on all valid interfaces. + * @since v0.6.9 + */ + dropMembership(multicastAddress: string, multicastInterface?: string): void; + /** + * This method throws `ERR_SOCKET_BUFFER_SIZE` if called on an unbound socket. + * @since v8.7.0 + * @return the `SO_RCVBUF` socket receive buffer size in bytes. + */ + getRecvBufferSize(): number; + /** + * This method throws `ERR_SOCKET_BUFFER_SIZE` if called on an unbound socket. + * @since v8.7.0 + * @return the `SO_SNDBUF` socket send buffer size in bytes. + */ + getSendBufferSize(): number; + /** + * @since v18.8.0, v16.19.0 + * @return Number of bytes queued for sending. + */ + getSendQueueSize(): number; + /** + * @since v18.8.0, v16.19.0 + * @return Number of send requests currently in the queue awaiting to be processed. + */ + getSendQueueCount(): number; + /** + * By default, binding a socket will cause it to block the Node.js process from + * exiting as long as the socket is open. The `socket.unref()` method can be used + * to exclude the socket from the reference counting that keeps the Node.js + * process active. The `socket.ref()` method adds the socket back to the reference + * counting and restores the default behavior. + * + * Calling `socket.ref()` multiples times will have no additional effect. + * + * The `socket.ref()` method returns a reference to the socket so calls can be + * chained. + * @since v0.9.1 + */ + ref(): this; + /** + * Returns an object containing the `address`, `family`, and `port` of the remote + * endpoint. This method throws an `ERR_SOCKET_DGRAM_NOT_CONNECTED` exception + * if the socket is not connected. + * @since v12.0.0 + */ + remoteAddress(): AddressInfo; + /** + * Broadcasts a datagram on the socket. + * For connectionless sockets, the destination `port` and `address` must be + * specified. Connected sockets, on the other hand, will use their associated + * remote endpoint, so the `port` and `address` arguments must not be set. + * + * The `msg` argument contains the message to be sent. + * Depending on its type, different behavior can apply. If `msg` is a `Buffer`, + * any `TypedArray` or a `DataView`, + * the `offset` and `length` specify the offset within the `Buffer` where the + * message begins and the number of bytes in the message, respectively. + * If `msg` is a `String`, then it is automatically converted to a `Buffer` with `'utf8'` encoding. With messages that + * contain multi-byte characters, `offset` and `length` will be calculated with + * respect to `byte length` and not the character position. + * If `msg` is an array, `offset` and `length` must not be specified. + * + * The `address` argument is a string. If the value of `address` is a host name, + * DNS will be used to resolve the address of the host. If `address` is not + * provided or otherwise nullish, `'127.0.0.1'` (for `udp4` sockets) or `'::1'` (for `udp6` sockets) will be used by default. + * + * If the socket has not been previously bound with a call to `bind`, the socket + * is assigned a random port number and is bound to the "all interfaces" address + * (`'0.0.0.0'` for `udp4` sockets, `'::0'` for `udp6` sockets.) + * + * An optional `callback` function may be specified to as a way of reporting + * DNS errors or for determining when it is safe to reuse the `buf` object. + * DNS lookups delay the time to send for at least one tick of the + * Node.js event loop. + * + * The only way to know for sure that the datagram has been sent is by using a `callback`. If an error occurs and a `callback` is given, the error will be + * passed as the first argument to the `callback`. If a `callback` is not given, + * the error is emitted as an `'error'` event on the `socket` object. + * + * Offset and length are optional but both _must_ be set if either are used. + * They are supported only when the first argument is a `Buffer`, a `TypedArray`, + * or a `DataView`. + * + * This method throws `ERR_SOCKET_BAD_PORT` if called on an unbound socket. + * + * Example of sending a UDP packet to a port on `localhost`; + * + * ```js + * import dgram from 'node:dgram'; + * import { Buffer } from 'node:buffer'; + * + * const message = Buffer.from('Some bytes'); + * const client = dgram.createSocket('udp4'); + * client.send(message, 41234, 'localhost', (err) => { + * client.close(); + * }); + * ``` + * + * Example of sending a UDP packet composed of multiple buffers to a port on`127.0.0.1`; + * + * ```js + * import dgram from 'node:dgram'; + * import { Buffer } from 'node:buffer'; + * + * const buf1 = Buffer.from('Some '); + * const buf2 = Buffer.from('bytes'); + * const client = dgram.createSocket('udp4'); + * client.send([buf1, buf2], 41234, (err) => { + * client.close(); + * }); + * ``` + * + * Sending multiple buffers might be faster or slower depending on the + * application and operating system. Run benchmarks to + * determine the optimal strategy on a case-by-case basis. Generally speaking, + * however, sending multiple buffers is faster. + * + * Example of sending a UDP packet using a socket connected to a port on `localhost`: + * + * ```js + * import dgram from 'node:dgram'; + * import { Buffer } from 'node:buffer'; + * + * const message = Buffer.from('Some bytes'); + * const client = dgram.createSocket('udp4'); + * client.connect(41234, 'localhost', (err) => { + * client.send(message, (err) => { + * client.close(); + * }); + * }); + * ``` + * @since v0.1.99 + * @param msg Message to be sent. + * @param offset Offset in the buffer where the message starts. + * @param length Number of bytes in the message. + * @param port Destination port. + * @param address Destination host name or IP address. + * @param callback Called when the message has been sent. + */ + send( + msg: string | NodeJS.ArrayBufferView | readonly any[], + port?: number, + address?: string, + callback?: (error: Error | null, bytes: number) => void, + ): void; + send( + msg: string | NodeJS.ArrayBufferView | readonly any[], + port?: number, + callback?: (error: Error | null, bytes: number) => void, + ): void; + send( + msg: string | NodeJS.ArrayBufferView | readonly any[], + callback?: (error: Error | null, bytes: number) => void, + ): void; + send( + msg: string | NodeJS.ArrayBufferView, + offset: number, + length: number, + port?: number, + address?: string, + callback?: (error: Error | null, bytes: number) => void, + ): void; + send( + msg: string | NodeJS.ArrayBufferView, + offset: number, + length: number, + port?: number, + callback?: (error: Error | null, bytes: number) => void, + ): void; + send( + msg: string | NodeJS.ArrayBufferView, + offset: number, + length: number, + callback?: (error: Error | null, bytes: number) => void, + ): void; + /** + * Sets or clears the `SO_BROADCAST` socket option. When set to `true`, UDP + * packets may be sent to a local interface's broadcast address. + * + * This method throws `EBADF` if called on an unbound socket. + * @since v0.6.9 + */ + setBroadcast(flag: boolean): void; + /** + * _All references to scope in this section are referring to [IPv6 Zone Indices](https://en.wikipedia.org/wiki/IPv6_address#Scoped_literal_IPv6_addresses), which are defined by [RFC + * 4007](https://tools.ietf.org/html/rfc4007). In string form, an IP_ + * _with a scope index is written as `'IP%scope'` where scope is an interface name_ + * _or interface number._ + * + * Sets the default outgoing multicast interface of the socket to a chosen + * interface or back to system interface selection. The `multicastInterface` must + * be a valid string representation of an IP from the socket's family. + * + * For IPv4 sockets, this should be the IP configured for the desired physical + * interface. All packets sent to multicast on the socket will be sent on the + * interface determined by the most recent successful use of this call. + * + * For IPv6 sockets, `multicastInterface` should include a scope to indicate the + * interface as in the examples that follow. In IPv6, individual `send` calls can + * also use explicit scope in addresses, so only packets sent to a multicast + * address without specifying an explicit scope are affected by the most recent + * successful use of this call. + * + * This method throws `EBADF` if called on an unbound socket. + * + * #### Example: IPv6 outgoing multicast interface + * + * On most systems, where scope format uses the interface name: + * + * ```js + * const socket = dgram.createSocket('udp6'); + * + * socket.bind(1234, () => { + * socket.setMulticastInterface('::%eth1'); + * }); + * ``` + * + * On Windows, where scope format uses an interface number: + * + * ```js + * const socket = dgram.createSocket('udp6'); + * + * socket.bind(1234, () => { + * socket.setMulticastInterface('::%2'); + * }); + * ``` + * + * #### Example: IPv4 outgoing multicast interface + * + * All systems use an IP of the host on the desired physical interface: + * + * ```js + * const socket = dgram.createSocket('udp4'); + * + * socket.bind(1234, () => { + * socket.setMulticastInterface('10.0.0.2'); + * }); + * ``` + * @since v8.6.0 + */ + setMulticastInterface(multicastInterface: string): void; + /** + * Sets or clears the `IP_MULTICAST_LOOP` socket option. When set to `true`, + * multicast packets will also be received on the local interface. + * + * This method throws `EBADF` if called on an unbound socket. + * @since v0.3.8 + */ + setMulticastLoopback(flag: boolean): boolean; + /** + * Sets the `IP_MULTICAST_TTL` socket option. While TTL generally stands for + * "Time to Live", in this context it specifies the number of IP hops that a + * packet is allowed to travel through, specifically for multicast traffic. Each + * router or gateway that forwards a packet decrements the TTL. If the TTL is + * decremented to 0 by a router, it will not be forwarded. + * + * The `ttl` argument may be between 0 and 255\. The default on most systems is `1`. + * + * This method throws `EBADF` if called on an unbound socket. + * @since v0.3.8 + */ + setMulticastTTL(ttl: number): number; + /** + * Sets the `SO_RCVBUF` socket option. Sets the maximum socket receive buffer + * in bytes. + * + * This method throws `ERR_SOCKET_BUFFER_SIZE` if called on an unbound socket. + * @since v8.7.0 + */ + setRecvBufferSize(size: number): void; + /** + * Sets the `SO_SNDBUF` socket option. Sets the maximum socket send buffer + * in bytes. + * + * This method throws `ERR_SOCKET_BUFFER_SIZE` if called on an unbound socket. + * @since v8.7.0 + */ + setSendBufferSize(size: number): void; + /** + * Sets the `IP_TTL` socket option. While TTL generally stands for "Time to Live", + * in this context it specifies the number of IP hops that a packet is allowed to + * travel through. Each router or gateway that forwards a packet decrements the + * TTL. If the TTL is decremented to 0 by a router, it will not be forwarded. + * Changing TTL values is typically done for network probes or when multicasting. + * + * The `ttl` argument may be between 1 and 255\. The default on most systems + * is 64. + * + * This method throws `EBADF` if called on an unbound socket. + * @since v0.1.101 + */ + setTTL(ttl: number): number; + /** + * By default, binding a socket will cause it to block the Node.js process from + * exiting as long as the socket is open. The `socket.unref()` method can be used + * to exclude the socket from the reference counting that keeps the Node.js + * process active, allowing the process to exit even if the socket is still + * listening. + * + * Calling `socket.unref()` multiple times will have no additional effect. + * + * The `socket.unref()` method returns a reference to the socket so calls can be + * chained. + * @since v0.9.1 + */ + unref(): this; + /** + * Tells the kernel to join a source-specific multicast channel at the given `sourceAddress` and `groupAddress`, using the `multicastInterface` with the `IP_ADD_SOURCE_MEMBERSHIP` socket + * option. If the `multicastInterface` argument + * is not specified, the operating system will choose one interface and will add + * membership to it. To add membership to every available interface, call `socket.addSourceSpecificMembership()` multiple times, once per interface. + * + * When called on an unbound socket, this method will implicitly bind to a random + * port, listening on all interfaces. + * @since v13.1.0, v12.16.0 + */ + addSourceSpecificMembership(sourceAddress: string, groupAddress: string, multicastInterface?: string): void; + /** + * Instructs the kernel to leave a source-specific multicast channel at the given `sourceAddress` and `groupAddress` using the `IP_DROP_SOURCE_MEMBERSHIP` socket option. This method is + * automatically called by the kernel when the + * socket is closed or the process terminates, so most apps will never have + * reason to call this. + * + * If `multicastInterface` is not specified, the operating system will attempt to + * drop membership on all valid interfaces. + * @since v13.1.0, v12.16.0 + */ + dropSourceSpecificMembership(sourceAddress: string, groupAddress: string, multicastInterface?: string): void; + /** + * Calls `socket.close()` and returns a promise that fulfills when the socket has closed. + * @since v20.5.0 + */ + [Symbol.asyncDispose](): Promise<void>; + } + interface Socket extends InternalEventEmitter<SocketEventMap> {} +} +declare module "dgram" { + export * from "node:dgram"; +} diff --git a/server/node_modules/@types/node/diagnostics_channel.d.ts b/server/node_modules/@types/node/diagnostics_channel.d.ts new file mode 100644 index 0000000..206592b --- /dev/null +++ b/server/node_modules/@types/node/diagnostics_channel.d.ts @@ -0,0 +1,576 @@ +/** + * The `node:diagnostics_channel` module provides an API to create named channels + * to report arbitrary message data for diagnostics purposes. + * + * It can be accessed using: + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * ``` + * + * It is intended that a module writer wanting to report diagnostics messages + * will create one or many top-level channels to report messages through. + * Channels may also be acquired at runtime but it is not encouraged + * due to the additional overhead of doing so. Channels may be exported for + * convenience, but as long as the name is known it can be acquired anywhere. + * + * If you intend for your module to produce diagnostics data for others to + * consume it is recommended that you include documentation of what named + * channels are used along with the shape of the message data. Channel names + * should generally include the module name to avoid collisions with data from + * other modules. + * @since v15.1.0, v14.17.0 + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/diagnostics_channel.js) + */ +declare module "node:diagnostics_channel" { + import { AsyncLocalStorage } from "node:async_hooks"; + /** + * Check if there are active subscribers to the named channel. This is helpful if + * the message you want to send might be expensive to prepare. + * + * This API is optional but helpful when trying to publish messages from very + * performance-sensitive code. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * if (diagnostics_channel.hasSubscribers('my-channel')) { + * // There are subscribers, prepare and publish message + * } + * ``` + * @since v15.1.0, v14.17.0 + * @param name The channel name + * @return If there are active subscribers + */ + function hasSubscribers(name: string | symbol): boolean; + /** + * This is the primary entry-point for anyone wanting to publish to a named + * channel. It produces a channel object which is optimized to reduce overhead at + * publish time as much as possible. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * const channel = diagnostics_channel.channel('my-channel'); + * ``` + * @since v15.1.0, v14.17.0 + * @param name The channel name + * @return The named channel object + */ + function channel(name: string | symbol): Channel; + type ChannelListener = (message: unknown, name: string | symbol) => void; + /** + * Register a message handler to subscribe to this channel. This message handler + * will be run synchronously whenever a message is published to the channel. Any + * errors thrown in the message handler will trigger an `'uncaughtException'`. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * diagnostics_channel.subscribe('my-channel', (message, name) => { + * // Received data + * }); + * ``` + * @since v18.7.0, v16.17.0 + * @param name The channel name + * @param onMessage The handler to receive channel messages + */ + function subscribe(name: string | symbol, onMessage: ChannelListener): void; + /** + * Remove a message handler previously registered to this channel with {@link subscribe}. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * function onMessage(message, name) { + * // Received data + * } + * + * diagnostics_channel.subscribe('my-channel', onMessage); + * + * diagnostics_channel.unsubscribe('my-channel', onMessage); + * ``` + * @since v18.7.0, v16.17.0 + * @param name The channel name + * @param onMessage The previous subscribed handler to remove + * @return `true` if the handler was found, `false` otherwise. + */ + function unsubscribe(name: string | symbol, onMessage: ChannelListener): boolean; + /** + * Creates a `TracingChannel` wrapper for the given `TracingChannel Channels`. If a name is given, the corresponding tracing + * channels will be created in the form of `tracing:${name}:${eventType}` where `eventType` corresponds to the types of `TracingChannel Channels`. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * const channelsByName = diagnostics_channel.tracingChannel('my-channel'); + * + * // or... + * + * const channelsByCollection = diagnostics_channel.tracingChannel({ + * start: diagnostics_channel.channel('tracing:my-channel:start'), + * end: diagnostics_channel.channel('tracing:my-channel:end'), + * asyncStart: diagnostics_channel.channel('tracing:my-channel:asyncStart'), + * asyncEnd: diagnostics_channel.channel('tracing:my-channel:asyncEnd'), + * error: diagnostics_channel.channel('tracing:my-channel:error'), + * }); + * ``` + * @since v19.9.0 + * @experimental + * @param nameOrChannels Channel name or object containing all the `TracingChannel Channels` + * @return Collection of channels to trace with + */ + function tracingChannel< + StoreType = unknown, + ContextType extends object = StoreType extends object ? StoreType : object, + >( + nameOrChannels: string | TracingChannelCollection<StoreType, ContextType>, + ): TracingChannel<StoreType, ContextType>; + /** + * The class `Channel` represents an individual named channel within the data + * pipeline. It is used to track subscribers and to publish messages when there + * are subscribers present. It exists as a separate object to avoid channel + * lookups at publish time, enabling very fast publish speeds and allowing + * for heavy use while incurring very minimal cost. Channels are created with {@link channel}, constructing a channel directly + * with `new Channel(name)` is not supported. + * @since v15.1.0, v14.17.0 + */ + class Channel<StoreType = unknown, ContextType = StoreType> { + readonly name: string | symbol; + /** + * Check if there are active subscribers to this channel. This is helpful if + * the message you want to send might be expensive to prepare. + * + * This API is optional but helpful when trying to publish messages from very + * performance-sensitive code. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * const channel = diagnostics_channel.channel('my-channel'); + * + * if (channel.hasSubscribers) { + * // There are subscribers, prepare and publish message + * } + * ``` + * @since v15.1.0, v14.17.0 + */ + readonly hasSubscribers: boolean; + private constructor(name: string | symbol); + /** + * Publish a message to any subscribers to the channel. This will trigger + * message handlers synchronously so they will execute within the same context. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * const channel = diagnostics_channel.channel('my-channel'); + * + * channel.publish({ + * some: 'message', + * }); + * ``` + * @since v15.1.0, v14.17.0 + * @param message The message to send to the channel subscribers + */ + publish(message: unknown): void; + /** + * Register a message handler to subscribe to this channel. This message handler + * will be run synchronously whenever a message is published to the channel. Any + * errors thrown in the message handler will trigger an `'uncaughtException'`. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * const channel = diagnostics_channel.channel('my-channel'); + * + * channel.subscribe((message, name) => { + * // Received data + * }); + * ``` + * @since v15.1.0, v14.17.0 + * @param onMessage The handler to receive channel messages + */ + subscribe(onMessage: ChannelListener): void; + /** + * Remove a message handler previously registered to this channel with `channel.subscribe(onMessage)`. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * const channel = diagnostics_channel.channel('my-channel'); + * + * function onMessage(message, name) { + * // Received data + * } + * + * channel.subscribe(onMessage); + * + * channel.unsubscribe(onMessage); + * ``` + * @since v15.1.0, v14.17.0 + * @param onMessage The previous subscribed handler to remove + * @return `true` if the handler was found, `false` otherwise. + */ + unsubscribe(onMessage: ChannelListener): void; + /** + * When `channel.runStores(context, ...)` is called, the given context data + * will be applied to any store bound to the channel. If the store has already been + * bound the previous `transform` function will be replaced with the new one. + * The `transform` function may be omitted to set the given context data as the + * context directly. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * import { AsyncLocalStorage } from 'node:async_hooks'; + * + * const store = new AsyncLocalStorage(); + * + * const channel = diagnostics_channel.channel('my-channel'); + * + * channel.bindStore(store, (data) => { + * return { data }; + * }); + * ``` + * @since v19.9.0 + * @experimental + * @param store The store to which to bind the context data + * @param transform Transform context data before setting the store context + */ + bindStore(store: AsyncLocalStorage<StoreType>, transform?: (context: ContextType) => StoreType): void; + /** + * Remove a message handler previously registered to this channel with `channel.bindStore(store)`. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * import { AsyncLocalStorage } from 'node:async_hooks'; + * + * const store = new AsyncLocalStorage(); + * + * const channel = diagnostics_channel.channel('my-channel'); + * + * channel.bindStore(store); + * channel.unbindStore(store); + * ``` + * @since v19.9.0 + * @experimental + * @param store The store to unbind from the channel. + * @return `true` if the store was found, `false` otherwise. + */ + unbindStore(store: AsyncLocalStorage<StoreType>): boolean; + /** + * Applies the given data to any AsyncLocalStorage instances bound to the channel + * for the duration of the given function, then publishes to the channel within + * the scope of that data is applied to the stores. + * + * If a transform function was given to `channel.bindStore(store)` it will be + * applied to transform the message data before it becomes the context value for + * the store. The prior storage context is accessible from within the transform + * function in cases where context linking is required. + * + * The context applied to the store should be accessible in any async code which + * continues from execution which began during the given function, however + * there are some situations in which `context loss` may occur. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * import { AsyncLocalStorage } from 'node:async_hooks'; + * + * const store = new AsyncLocalStorage(); + * + * const channel = diagnostics_channel.channel('my-channel'); + * + * channel.bindStore(store, (message) => { + * const parent = store.getStore(); + * return new Span(message, parent); + * }); + * channel.runStores({ some: 'message' }, () => { + * store.getStore(); // Span({ some: 'message' }) + * }); + * ``` + * @since v19.9.0 + * @experimental + * @param context Message to send to subscribers and bind to stores + * @param fn Handler to run within the entered storage context + * @param thisArg The receiver to be used for the function call. + * @param args Optional arguments to pass to the function. + */ + runStores<ThisArg = any, Args extends any[] = any[], Result = any>( + context: ContextType, + fn: (this: ThisArg, ...args: Args) => Result, + thisArg?: ThisArg, + ...args: Args + ): Result; + } + interface TracingChannelSubscribers<ContextType extends object> { + start: (message: ContextType) => void; + end: ( + message: ContextType & { + error?: unknown; + result?: unknown; + }, + ) => void; + asyncStart: ( + message: ContextType & { + error?: unknown; + result?: unknown; + }, + ) => void; + asyncEnd: ( + message: ContextType & { + error?: unknown; + result?: unknown; + }, + ) => void; + error: ( + message: ContextType & { + error: unknown; + }, + ) => void; + } + interface TracingChannelCollection<StoreType = unknown, ContextType = StoreType> { + start: Channel<StoreType, ContextType>; + end: Channel<StoreType, ContextType>; + asyncStart: Channel<StoreType, ContextType>; + asyncEnd: Channel<StoreType, ContextType>; + error: Channel<StoreType, ContextType>; + } + /** + * The class `TracingChannel` is a collection of `TracingChannel Channels` which + * together express a single traceable action. It is used to formalize and + * simplify the process of producing events for tracing application flow. {@link tracingChannel} is used to construct a `TracingChannel`. As with `Channel` it is recommended to create and reuse a + * single `TracingChannel` at the top-level of the file rather than creating them + * dynamically. + * @since v19.9.0 + * @experimental + */ + class TracingChannel<StoreType = unknown, ContextType extends object = {}> implements TracingChannelCollection { + start: Channel<StoreType, ContextType>; + end: Channel<StoreType, ContextType>; + asyncStart: Channel<StoreType, ContextType>; + asyncEnd: Channel<StoreType, ContextType>; + error: Channel<StoreType, ContextType>; + /** + * Helper to subscribe a collection of functions to the corresponding channels. + * This is the same as calling `channel.subscribe(onMessage)` on each channel + * individually. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * const channels = diagnostics_channel.tracingChannel('my-channel'); + * + * channels.subscribe({ + * start(message) { + * // Handle start message + * }, + * end(message) { + * // Handle end message + * }, + * asyncStart(message) { + * // Handle asyncStart message + * }, + * asyncEnd(message) { + * // Handle asyncEnd message + * }, + * error(message) { + * // Handle error message + * }, + * }); + * ``` + * @since v19.9.0 + * @experimental + * @param subscribers Set of `TracingChannel Channels` subscribers + */ + subscribe(subscribers: TracingChannelSubscribers<ContextType>): void; + /** + * Helper to unsubscribe a collection of functions from the corresponding channels. + * This is the same as calling `channel.unsubscribe(onMessage)` on each channel + * individually. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * const channels = diagnostics_channel.tracingChannel('my-channel'); + * + * channels.unsubscribe({ + * start(message) { + * // Handle start message + * }, + * end(message) { + * // Handle end message + * }, + * asyncStart(message) { + * // Handle asyncStart message + * }, + * asyncEnd(message) { + * // Handle asyncEnd message + * }, + * error(message) { + * // Handle error message + * }, + * }); + * ``` + * @since v19.9.0 + * @experimental + * @param subscribers Set of `TracingChannel Channels` subscribers + * @return `true` if all handlers were successfully unsubscribed, and `false` otherwise. + */ + unsubscribe(subscribers: TracingChannelSubscribers<ContextType>): void; + /** + * Trace a synchronous function call. This will always produce a `start event` and `end event` around the execution and may produce an `error event` if the given function throws an error. + * This will run the given function using `channel.runStores(context, ...)` on the `start` channel which ensures all + * events should have any bound stores set to match this trace context. + * + * To ensure only correct trace graphs are formed, events will only be published if subscribers are present prior to starting the trace. Subscriptions + * which are added after the trace begins will not receive future events from that trace, only future traces will be seen. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * const channels = diagnostics_channel.tracingChannel('my-channel'); + * + * channels.traceSync(() => { + * // Do something + * }, { + * some: 'thing', + * }); + * ``` + * @since v19.9.0 + * @experimental + * @param fn Function to wrap a trace around + * @param context Shared object to correlate events through + * @param thisArg The receiver to be used for the function call + * @param args Optional arguments to pass to the function + * @return The return value of the given function + */ + traceSync<ThisArg = any, Args extends any[] = any[], Result = any>( + fn: (this: ThisArg, ...args: Args) => Result, + context?: ContextType, + thisArg?: ThisArg, + ...args: Args + ): Result; + /** + * Trace a promise-returning function call. This will always produce a `start event` and `end event` around the synchronous portion of the + * function execution, and will produce an `asyncStart event` and `asyncEnd event` when a promise continuation is reached. It may also + * produce an `error event` if the given function throws an error or the + * returned promise rejects. This will run the given function using `channel.runStores(context, ...)` on the `start` channel which ensures all + * events should have any bound stores set to match this trace context. + * + * To ensure only correct trace graphs are formed, events will only be published if subscribers are present prior to starting the trace. Subscriptions + * which are added after the trace begins will not receive future events from that trace, only future traces will be seen. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * const channels = diagnostics_channel.tracingChannel('my-channel'); + * + * channels.tracePromise(async () => { + * // Do something + * }, { + * some: 'thing', + * }); + * ``` + * @since v19.9.0 + * @experimental + * @param fn Promise-returning function to wrap a trace around + * @param context Shared object to correlate trace events through + * @param thisArg The receiver to be used for the function call + * @param args Optional arguments to pass to the function + * @return Chained from promise returned by the given function + */ + tracePromise<ThisArg = any, Args extends any[] = any[], Result = any>( + fn: (this: ThisArg, ...args: Args) => Promise<Result>, + context?: ContextType, + thisArg?: ThisArg, + ...args: Args + ): Promise<Result>; + /** + * Trace a callback-receiving function call. This will always produce a `start event` and `end event` around the synchronous portion of the + * function execution, and will produce a `asyncStart event` and `asyncEnd event` around the callback execution. It may also produce an `error event` if the given function throws an error or + * the returned + * promise rejects. This will run the given function using `channel.runStores(context, ...)` on the `start` channel which ensures all + * events should have any bound stores set to match this trace context. + * + * The `position` will be -1 by default to indicate the final argument should + * be used as the callback. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * + * const channels = diagnostics_channel.tracingChannel('my-channel'); + * + * channels.traceCallback((arg1, callback) => { + * // Do something + * callback(null, 'result'); + * }, 1, { + * some: 'thing', + * }, thisArg, arg1, callback); + * ``` + * + * The callback will also be run with `channel.runStores(context, ...)` which + * enables context loss recovery in some cases. + * + * To ensure only correct trace graphs are formed, events will only be published if subscribers are present prior to starting the trace. Subscriptions + * which are added after the trace begins will not receive future events from that trace, only future traces will be seen. + * + * ```js + * import diagnostics_channel from 'node:diagnostics_channel'; + * import { AsyncLocalStorage } from 'node:async_hooks'; + * + * const channels = diagnostics_channel.tracingChannel('my-channel'); + * const myStore = new AsyncLocalStorage(); + * + * // The start channel sets the initial store data to something + * // and stores that store data value on the trace context object + * channels.start.bindStore(myStore, (data) => { + * const span = new Span(data); + * data.span = span; + * return span; + * }); + * + * // Then asyncStart can restore from that data it stored previously + * channels.asyncStart.bindStore(myStore, (data) => { + * return data.span; + * }); + * ``` + * @since v19.9.0 + * @experimental + * @param fn callback using function to wrap a trace around + * @param position Zero-indexed argument position of expected callback + * @param context Shared object to correlate trace events through + * @param thisArg The receiver to be used for the function call + * @param args Optional arguments to pass to the function + * @return The return value of the given function + */ + traceCallback<ThisArg = any, Args extends any[] = any[], Result = any>( + fn: (this: ThisArg, ...args: Args) => Result, + position?: number, + context?: ContextType, + thisArg?: ThisArg, + ...args: Args + ): Result; + /** + * `true` if any of the individual channels has a subscriber, `false` if not. + * + * This is a helper method available on a {@link TracingChannel} instance to check + * if any of the [TracingChannel Channels](https://nodejs.org/api/diagnostics_channel.html#tracingchannel-channels) have subscribers. + * A `true` is returned if any of them have at least one subscriber, a `false` is returned otherwise. + * + * ```js + * const diagnostics_channel = require('node:diagnostics_channel'); + * + * const channels = diagnostics_channel.tracingChannel('my-channel'); + * + * if (channels.hasSubscribers) { + * // Do something + * } + * ``` + * @since v22.0.0, v20.13.0 + */ + readonly hasSubscribers: boolean; + } +} +declare module "diagnostics_channel" { + export * from "node:diagnostics_channel"; +} diff --git a/server/node_modules/@types/node/dns.d.ts b/server/node_modules/@types/node/dns.d.ts new file mode 100644 index 0000000..80a2272 --- /dev/null +++ b/server/node_modules/@types/node/dns.d.ts @@ -0,0 +1,922 @@ +/** + * The `node:dns` module enables name resolution. For example, use it to look up IP + * addresses of host names. + * + * Although named for the [Domain Name System (DNS)](https://en.wikipedia.org/wiki/Domain_Name_System), it does not always use the + * DNS protocol for lookups. {@link lookup} uses the operating system + * facilities to perform name resolution. It may not need to perform any network + * communication. To perform name resolution the way other applications on the same + * system do, use {@link lookup}. + * + * ```js + * import dns from 'node:dns'; + * + * dns.lookup('example.org', (err, address, family) => { + * console.log('address: %j family: IPv%s', address, family); + * }); + * // address: "93.184.216.34" family: IPv4 + * ``` + * + * All other functions in the `node:dns` module connect to an actual DNS server to + * perform name resolution. They will always use the network to perform DNS + * queries. These functions do not use the same set of configuration files used by {@link lookup} (e.g. `/etc/hosts`). Use these functions to always perform + * DNS queries, bypassing other name-resolution facilities. + * + * ```js + * import dns from 'node:dns'; + * + * dns.resolve4('archive.org', (err, addresses) => { + * if (err) throw err; + * + * console.log(`addresses: ${JSON.stringify(addresses)}`); + * + * addresses.forEach((a) => { + * dns.reverse(a, (err, hostnames) => { + * if (err) { + * throw err; + * } + * console.log(`reverse for ${a}: ${JSON.stringify(hostnames)}`); + * }); + * }); + * }); + * ``` + * + * See the [Implementation considerations section](https://nodejs.org/docs/latest-v25.x/api/dns.html#implementation-considerations) for more information. + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/dns.js) + */ +declare module "node:dns" { + // Supported getaddrinfo flags. + /** + * Limits returned address types to the types of non-loopback addresses configured on the system. For example, IPv4 addresses are + * only returned if the current system has at least one IPv4 address configured. + */ + const ADDRCONFIG: number; + /** + * If the IPv6 family was specified, but no IPv6 addresses were found, then return IPv4 mapped IPv6 addresses. It is not supported + * on some operating systems (e.g. FreeBSD 10.1). + */ + const V4MAPPED: number; + /** + * If `dns.V4MAPPED` is specified, return resolved IPv6 addresses as + * well as IPv4 mapped IPv6 addresses. + */ + const ALL: number; + interface LookupOptions { + /** + * The record family. Must be `4`, `6`, or `0`. For backward compatibility reasons, `'IPv4'` and `'IPv6'` are interpreted + * as `4` and `6` respectively. The value 0 indicates that either an IPv4 or IPv6 address is returned. If the value `0` is used + * with `{ all: true } (see below)`, both IPv4 and IPv6 addresses are returned. + * @default 0 + */ + family?: number | "IPv4" | "IPv6" | undefined; + /** + * One or more [supported `getaddrinfo`](https://nodejs.org/docs/latest-v25.x/api/dns.html#supported-getaddrinfo-flags) flags. Multiple flags may be + * passed by bitwise `OR`ing their values. + */ + hints?: number | undefined; + /** + * When `true`, the callback returns all resolved addresses in an array. Otherwise, returns a single address. + * @default false + */ + all?: boolean | undefined; + /** + * When `verbatim`, the resolved addresses are return unsorted. When `ipv4first`, the resolved addresses are sorted + * by placing IPv4 addresses before IPv6 addresses. When `ipv6first`, the resolved addresses are sorted by placing IPv6 + * addresses before IPv4 addresses. Default value is configurable using + * {@link setDefaultResultOrder} or [`--dns-result-order`](https://nodejs.org/docs/latest-v25.x/api/cli.html#--dns-result-orderorder). + * @default `verbatim` (addresses are not reordered) + * @since v22.1.0 + */ + order?: "ipv4first" | "ipv6first" | "verbatim" | undefined; + /** + * When `true`, the callback receives IPv4 and IPv6 addresses in the order the DNS resolver returned them. When `false`, IPv4 + * addresses are placed before IPv6 addresses. This option will be deprecated in favor of `order`. When both are specified, + * `order` has higher precedence. New code should only use `order`. Default value is configurable using {@link setDefaultResultOrder} + * @default true (addresses are not reordered) + * @deprecated Please use `order` option + */ + verbatim?: boolean | undefined; + } + interface LookupOneOptions extends LookupOptions { + all?: false | undefined; + } + interface LookupAllOptions extends LookupOptions { + all: true; + } + interface LookupAddress { + /** + * A string representation of an IPv4 or IPv6 address. + */ + address: string; + /** + * `4` or `6`, denoting the family of `address`, or `0` if the address is not an IPv4 or IPv6 address. `0` is a likely indicator of a + * bug in the name resolution service used by the operating system. + */ + family: number; + } + /** + * Resolves a host name (e.g. `'nodejs.org'`) into the first found A (IPv4) or + * AAAA (IPv6) record. All `option` properties are optional. If `options` is an + * integer, then it must be `4` or `6` – if `options` is `0` or not provided, then + * IPv4 and IPv6 addresses are both returned if found. + * + * With the `all` option set to `true`, the arguments for `callback` change to `(err, addresses)`, with `addresses` being an array of objects with the + * properties `address` and `family`. + * + * On error, `err` is an `Error` object, where `err.code` is the error code. + * Keep in mind that `err.code` will be set to `'ENOTFOUND'` not only when + * the host name does not exist but also when the lookup fails in other ways + * such as no available file descriptors. + * + * `dns.lookup()` does not necessarily have anything to do with the DNS protocol. + * The implementation uses an operating system facility that can associate names + * with addresses and vice versa. This implementation can have subtle but + * important consequences on the behavior of any Node.js program. Please take some + * time to consult the [Implementation considerations section](https://nodejs.org/docs/latest-v25.x/api/dns.html#implementation-considerations) + * before using `dns.lookup()`. + * + * Example usage: + * + * ```js + * import dns from 'node:dns'; + * const options = { + * family: 6, + * hints: dns.ADDRCONFIG | dns.V4MAPPED, + * }; + * dns.lookup('example.com', options, (err, address, family) => + * console.log('address: %j family: IPv%s', address, family)); + * // address: "2606:2800:220:1:248:1893:25c8:1946" family: IPv6 + * + * // When options.all is true, the result will be an Array. + * options.all = true; + * dns.lookup('example.com', options, (err, addresses) => + * console.log('addresses: %j', addresses)); + * // addresses: [{"address":"2606:2800:220:1:248:1893:25c8:1946","family":6}] + * ``` + * + * If this method is invoked as its [util.promisify()](https://nodejs.org/docs/latest-v25.x/api/util.html#utilpromisifyoriginal) ed + * version, and `all` is not set to `true`, it returns a `Promise` for an `Object` with `address` and `family` properties. + * @since v0.1.90 + */ + function lookup( + hostname: string, + family: number, + callback: (err: NodeJS.ErrnoException | null, address: string, family: number) => void, + ): void; + function lookup( + hostname: string, + options: LookupOneOptions, + callback: (err: NodeJS.ErrnoException | null, address: string, family: number) => void, + ): void; + function lookup( + hostname: string, + options: LookupAllOptions, + callback: (err: NodeJS.ErrnoException | null, addresses: LookupAddress[]) => void, + ): void; + function lookup( + hostname: string, + options: LookupOptions, + callback: (err: NodeJS.ErrnoException | null, address: string | LookupAddress[], family: number) => void, + ): void; + function lookup( + hostname: string, + callback: (err: NodeJS.ErrnoException | null, address: string, family: number) => void, + ): void; + namespace lookup { + function __promisify__(hostname: string, options: LookupAllOptions): Promise<LookupAddress[]>; + function __promisify__(hostname: string, options?: LookupOneOptions | number): Promise<LookupAddress>; + function __promisify__(hostname: string, options: LookupOptions): Promise<LookupAddress | LookupAddress[]>; + } + /** + * Resolves the given `address` and `port` into a host name and service using + * the operating system's underlying `getnameinfo` implementation. + * + * If `address` is not a valid IP address, a `TypeError` will be thrown. + * The `port` will be coerced to a number. If it is not a legal port, a `TypeError` will be thrown. + * + * On an error, `err` is an [`Error`](https://nodejs.org/docs/latest-v25.x/api/errors.html#class-error) object, + * where `err.code` is the error code. + * + * ```js + * import dns from 'node:dns'; + * dns.lookupService('127.0.0.1', 22, (err, hostname, service) => { + * console.log(hostname, service); + * // Prints: localhost ssh + * }); + * ``` + * + * If this method is invoked as its [util.promisify()](https://nodejs.org/docs/latest-v25.x/api/util.html#utilpromisifyoriginal) ed + * version, it returns a `Promise` for an `Object` with `hostname` and `service` properties. + * @since v0.11.14 + */ + function lookupService( + address: string, + port: number, + callback: (err: NodeJS.ErrnoException | null, hostname: string, service: string) => void, + ): void; + namespace lookupService { + function __promisify__( + address: string, + port: number, + ): Promise<{ + hostname: string; + service: string; + }>; + } + interface ResolveOptions { + ttl: boolean; + } + interface ResolveWithTtlOptions extends ResolveOptions { + ttl: true; + } + interface RecordWithTtl { + address: string; + ttl: number; + } + interface AnyARecord extends RecordWithTtl { + type: "A"; + } + interface AnyAaaaRecord extends RecordWithTtl { + type: "AAAA"; + } + interface CaaRecord { + critical: number; + issue?: string | undefined; + issuewild?: string | undefined; + iodef?: string | undefined; + contactemail?: string | undefined; + contactphone?: string | undefined; + } + interface AnyCaaRecord extends CaaRecord { + type: "CAA"; + } + interface MxRecord { + priority: number; + exchange: string; + } + interface AnyMxRecord extends MxRecord { + type: "MX"; + } + interface NaptrRecord { + flags: string; + service: string; + regexp: string; + replacement: string; + order: number; + preference: number; + } + interface AnyNaptrRecord extends NaptrRecord { + type: "NAPTR"; + } + interface SoaRecord { + nsname: string; + hostmaster: string; + serial: number; + refresh: number; + retry: number; + expire: number; + minttl: number; + } + interface AnySoaRecord extends SoaRecord { + type: "SOA"; + } + interface SrvRecord { + priority: number; + weight: number; + port: number; + name: string; + } + interface AnySrvRecord extends SrvRecord { + type: "SRV"; + } + interface TlsaRecord { + certUsage: number; + selector: number; + match: number; + data: ArrayBuffer; + } + interface AnyTlsaRecord extends TlsaRecord { + type: "TLSA"; + } + interface AnyTxtRecord { + type: "TXT"; + entries: string[]; + } + interface AnyNsRecord { + type: "NS"; + value: string; + } + interface AnyPtrRecord { + type: "PTR"; + value: string; + } + interface AnyCnameRecord { + type: "CNAME"; + value: string; + } + type AnyRecord = + | AnyARecord + | AnyAaaaRecord + | AnyCaaRecord + | AnyCnameRecord + | AnyMxRecord + | AnyNaptrRecord + | AnyNsRecord + | AnyPtrRecord + | AnySoaRecord + | AnySrvRecord + | AnyTlsaRecord + | AnyTxtRecord; + /** + * Uses the DNS protocol to resolve a host name (e.g. `'nodejs.org'`) into an array + * of the resource records. The `callback` function has arguments `(err, records)`. When successful, `records` will be an array of resource + * records. The type and structure of individual results varies based on `rrtype`: + * + * <omitted> + * + * On error, `err` is an [`Error`](https://nodejs.org/docs/latest-v25.x/api/errors.html#class-error) object, + * where `err.code` is one of the `DNS error codes`. + * @since v0.1.27 + * @param hostname Host name to resolve. + * @param [rrtype='A'] Resource record type. + */ + function resolve( + hostname: string, + callback: (err: NodeJS.ErrnoException | null, addresses: string[]) => void, + ): void; + function resolve( + hostname: string, + rrtype: "A" | "AAAA" | "CNAME" | "NS" | "PTR", + callback: (err: NodeJS.ErrnoException | null, addresses: string[]) => void, + ): void; + function resolve( + hostname: string, + rrtype: "ANY", + callback: (err: NodeJS.ErrnoException | null, addresses: AnyRecord[]) => void, + ): void; + function resolve( + hostname: string, + rrtype: "CAA", + callback: (err: NodeJS.ErrnoException | null, address: CaaRecord[]) => void, + ): void; + function resolve( + hostname: string, + rrtype: "MX", + callback: (err: NodeJS.ErrnoException | null, addresses: MxRecord[]) => void, + ): void; + function resolve( + hostname: string, + rrtype: "NAPTR", + callback: (err: NodeJS.ErrnoException | null, addresses: NaptrRecord[]) => void, + ): void; + function resolve( + hostname: string, + rrtype: "SOA", + callback: (err: NodeJS.ErrnoException | null, addresses: SoaRecord) => void, + ): void; + function resolve( + hostname: string, + rrtype: "SRV", + callback: (err: NodeJS.ErrnoException | null, addresses: SrvRecord[]) => void, + ): void; + function resolve( + hostname: string, + rrtype: "TLSA", + callback: (err: NodeJS.ErrnoException | null, addresses: TlsaRecord[]) => void, + ): void; + function resolve( + hostname: string, + rrtype: "TXT", + callback: (err: NodeJS.ErrnoException | null, addresses: string[][]) => void, + ): void; + function resolve( + hostname: string, + rrtype: string, + callback: ( + err: NodeJS.ErrnoException | null, + addresses: + | string[] + | CaaRecord[] + | MxRecord[] + | NaptrRecord[] + | SoaRecord + | SrvRecord[] + | TlsaRecord[] + | string[][] + | AnyRecord[], + ) => void, + ): void; + namespace resolve { + function __promisify__(hostname: string, rrtype?: "A" | "AAAA" | "CNAME" | "NS" | "PTR"): Promise<string[]>; + function __promisify__(hostname: string, rrtype: "ANY"): Promise<AnyRecord[]>; + function __promisify__(hostname: string, rrtype: "CAA"): Promise<CaaRecord[]>; + function __promisify__(hostname: string, rrtype: "MX"): Promise<MxRecord[]>; + function __promisify__(hostname: string, rrtype: "NAPTR"): Promise<NaptrRecord[]>; + function __promisify__(hostname: string, rrtype: "SOA"): Promise<SoaRecord>; + function __promisify__(hostname: string, rrtype: "SRV"): Promise<SrvRecord[]>; + function __promisify__(hostname: string, rrtype: "TLSA"): Promise<TlsaRecord[]>; + function __promisify__(hostname: string, rrtype: "TXT"): Promise<string[][]>; + function __promisify__( + hostname: string, + rrtype: string, + ): Promise< + | string[] + | CaaRecord[] + | MxRecord[] + | NaptrRecord[] + | SoaRecord + | SrvRecord[] + | TlsaRecord[] + | string[][] + | AnyRecord[] + >; + } + /** + * Uses the DNS protocol to resolve a IPv4 addresses (`A` records) for the `hostname`. The `addresses` argument passed to the `callback` function + * will contain an array of IPv4 addresses (e.g.`['74.125.79.104', '74.125.79.105', '74.125.79.106']`). + * @since v0.1.16 + * @param hostname Host name to resolve. + */ + function resolve4( + hostname: string, + callback: (err: NodeJS.ErrnoException | null, addresses: string[]) => void, + ): void; + function resolve4( + hostname: string, + options: ResolveWithTtlOptions, + callback: (err: NodeJS.ErrnoException | null, addresses: RecordWithTtl[]) => void, + ): void; + function resolve4( + hostname: string, + options: ResolveOptions, + callback: (err: NodeJS.ErrnoException | null, addresses: string[] | RecordWithTtl[]) => void, + ): void; + namespace resolve4 { + function __promisify__(hostname: string): Promise<string[]>; + function __promisify__(hostname: string, options: ResolveWithTtlOptions): Promise<RecordWithTtl[]>; + function __promisify__(hostname: string, options?: ResolveOptions): Promise<string[] | RecordWithTtl[]>; + } + /** + * Uses the DNS protocol to resolve IPv6 addresses (`AAAA` records) for the `hostname`. The `addresses` argument passed to the `callback` function + * will contain an array of IPv6 addresses. + * @since v0.1.16 + * @param hostname Host name to resolve. + */ + function resolve6( + hostname: string, + callback: (err: NodeJS.ErrnoException | null, addresses: string[]) => void, + ): void; + function resolve6( + hostname: string, + options: ResolveWithTtlOptions, + callback: (err: NodeJS.ErrnoException | null, addresses: RecordWithTtl[]) => void, + ): void; + function resolve6( + hostname: string, + options: ResolveOptions, + callback: (err: NodeJS.ErrnoException | null, addresses: string[] | RecordWithTtl[]) => void, + ): void; + namespace resolve6 { + function __promisify__(hostname: string): Promise<string[]>; + function __promisify__(hostname: string, options: ResolveWithTtlOptions): Promise<RecordWithTtl[]>; + function __promisify__(hostname: string, options?: ResolveOptions): Promise<string[] | RecordWithTtl[]>; + } + /** + * Uses the DNS protocol to resolve `CNAME` records for the `hostname`. The `addresses` argument passed to the `callback` function + * will contain an array of canonical name records available for the `hostname` (e.g. `['bar.example.com']`). + * @since v0.3.2 + */ + function resolveCname( + hostname: string, + callback: (err: NodeJS.ErrnoException | null, addresses: string[]) => void, + ): void; + namespace resolveCname { + function __promisify__(hostname: string): Promise<string[]>; + } + /** + * Uses the DNS protocol to resolve `CAA` records for the `hostname`. The `addresses` argument passed to the `callback` function + * will contain an array of certification authority authorization records + * available for the `hostname` (e.g. `[{critical: 0, iodef: 'mailto:pki@example.com'}, {critical: 128, issue: 'pki.example.com'}]`). + * @since v15.0.0, v14.17.0 + */ + function resolveCaa( + hostname: string, + callback: (err: NodeJS.ErrnoException | null, records: CaaRecord[]) => void, + ): void; + namespace resolveCaa { + function __promisify__(hostname: string): Promise<CaaRecord[]>; + } + /** + * Uses the DNS protocol to resolve mail exchange records (`MX` records) for the `hostname`. The `addresses` argument passed to the `callback` function will + * contain an array of objects containing both a `priority` and `exchange` property (e.g. `[{priority: 10, exchange: 'mx.example.com'}, ...]`). + * @since v0.1.27 + */ + function resolveMx( + hostname: string, + callback: (err: NodeJS.ErrnoException | null, addresses: MxRecord[]) => void, + ): void; + namespace resolveMx { + function __promisify__(hostname: string): Promise<MxRecord[]>; + } + /** + * Uses the DNS protocol to resolve regular expression-based records (`NAPTR` records) for the `hostname`. The `addresses` argument passed to the `callback` function will contain an array of + * objects with the following properties: + * + * * `flags` + * * `service` + * * `regexp` + * * `replacement` + * * `order` + * * `preference` + * + * ```js + * { + * flags: 's', + * service: 'SIP+D2U', + * regexp: '', + * replacement: '_sip._udp.example.com', + * order: 30, + * preference: 100 + * } + * ``` + * @since v0.9.12 + */ + function resolveNaptr( + hostname: string, + callback: (err: NodeJS.ErrnoException | null, addresses: NaptrRecord[]) => void, + ): void; + namespace resolveNaptr { + function __promisify__(hostname: string): Promise<NaptrRecord[]>; + } + /** + * Uses the DNS protocol to resolve name server records (`NS` records) for the `hostname`. The `addresses` argument passed to the `callback` function will + * contain an array of name server records available for `hostname` (e.g. `['ns1.example.com', 'ns2.example.com']`). + * @since v0.1.90 + */ + function resolveNs( + hostname: string, + callback: (err: NodeJS.ErrnoException | null, addresses: string[]) => void, + ): void; + namespace resolveNs { + function __promisify__(hostname: string): Promise<string[]>; + } + /** + * Uses the DNS protocol to resolve pointer records (`PTR` records) for the `hostname`. The `addresses` argument passed to the `callback` function will + * be an array of strings containing the reply records. + * @since v6.0.0 + */ + function resolvePtr( + hostname: string, + callback: (err: NodeJS.ErrnoException | null, addresses: string[]) => void, + ): void; + namespace resolvePtr { + function __promisify__(hostname: string): Promise<string[]>; + } + /** + * Uses the DNS protocol to resolve a start of authority record (`SOA` record) for + * the `hostname`. The `address` argument passed to the `callback` function will + * be an object with the following properties: + * + * * `nsname` + * * `hostmaster` + * * `serial` + * * `refresh` + * * `retry` + * * `expire` + * * `minttl` + * + * ```js + * { + * nsname: 'ns.example.com', + * hostmaster: 'root.example.com', + * serial: 2013101809, + * refresh: 10000, + * retry: 2400, + * expire: 604800, + * minttl: 3600 + * } + * ``` + * @since v0.11.10 + */ + function resolveSoa( + hostname: string, + callback: (err: NodeJS.ErrnoException | null, address: SoaRecord) => void, + ): void; + namespace resolveSoa { + function __promisify__(hostname: string): Promise<SoaRecord>; + } + /** + * Uses the DNS protocol to resolve service records (`SRV` records) for the `hostname`. The `addresses` argument passed to the `callback` function will + * be an array of objects with the following properties: + * + * * `priority` + * * `weight` + * * `port` + * * `name` + * + * ```js + * { + * priority: 10, + * weight: 5, + * port: 21223, + * name: 'service.example.com' + * } + * ``` + * @since v0.1.27 + */ + function resolveSrv( + hostname: string, + callback: (err: NodeJS.ErrnoException | null, addresses: SrvRecord[]) => void, + ): void; + namespace resolveSrv { + function __promisify__(hostname: string): Promise<SrvRecord[]>; + } + /** + * Uses the DNS protocol to resolve certificate associations (`TLSA` records) for + * the `hostname`. The `records` argument passed to the `callback` function is an + * array of objects with these properties: + * + * * `certUsage` + * * `selector` + * * `match` + * * `data` + * + * ```js + * { + * certUsage: 3, + * selector: 1, + * match: 1, + * data: [ArrayBuffer] + * } + * ``` + * @since v23.9.0, v22.15.0 + */ + function resolveTlsa( + hostname: string, + callback: (err: NodeJS.ErrnoException | null, addresses: TlsaRecord[]) => void, + ): void; + namespace resolveTlsa { + function __promisify__(hostname: string): Promise<TlsaRecord[]>; + } + /** + * Uses the DNS protocol to resolve text queries (`TXT` records) for the `hostname`. The `records` argument passed to the `callback` function is a + * two-dimensional array of the text records available for `hostname` (e.g.`[ ['v=spf1 ip4:0.0.0.0 ', '~all' ] ]`). Each sub-array contains TXT chunks of + * one record. Depending on the use case, these could be either joined together or + * treated separately. + * @since v0.1.27 + */ + function resolveTxt( + hostname: string, + callback: (err: NodeJS.ErrnoException | null, addresses: string[][]) => void, + ): void; + namespace resolveTxt { + function __promisify__(hostname: string): Promise<string[][]>; + } + /** + * Uses the DNS protocol to resolve all records (also known as `ANY` or `*` query). + * The `ret` argument passed to the `callback` function will be an array containing + * various types of records. Each object has a property `type` that indicates the + * type of the current record. And depending on the `type`, additional properties + * will be present on the object: + * + * <omitted> + * + * Here is an example of the `ret` object passed to the callback: + * + * ```js + * [ { type: 'A', address: '127.0.0.1', ttl: 299 }, + * { type: 'CNAME', value: 'example.com' }, + * { type: 'MX', exchange: 'alt4.aspmx.l.example.com', priority: 50 }, + * { type: 'NS', value: 'ns1.example.com' }, + * { type: 'TXT', entries: [ 'v=spf1 include:_spf.example.com ~all' ] }, + * { type: 'SOA', + * nsname: 'ns1.example.com', + * hostmaster: 'admin.example.com', + * serial: 156696742, + * refresh: 900, + * retry: 900, + * expire: 1800, + * minttl: 60 } ] + * ``` + * + * DNS server operators may choose not to respond to `ANY` queries. It may be better to call individual methods like {@link resolve4}, {@link resolveMx}, and so on. For more details, see + * [RFC 8482](https://tools.ietf.org/html/rfc8482). + */ + function resolveAny( + hostname: string, + callback: (err: NodeJS.ErrnoException | null, addresses: AnyRecord[]) => void, + ): void; + namespace resolveAny { + function __promisify__(hostname: string): Promise<AnyRecord[]>; + } + /** + * Performs a reverse DNS query that resolves an IPv4 or IPv6 address to an + * array of host names. + * + * On error, `err` is an [`Error`](https://nodejs.org/docs/latest-v25.x/api/errors.html#class-error) object, where `err.code` is + * one of the [DNS error codes](https://nodejs.org/docs/latest-v25.x/api/dns.html#error-codes). + * @since v0.1.16 + */ + function reverse( + ip: string, + callback: (err: NodeJS.ErrnoException | null, hostnames: string[]) => void, + ): void; + /** + * Get the default value for `order` in {@link lookup} and [`dnsPromises.lookup()`](https://nodejs.org/docs/latest-v25.x/api/dns.html#dnspromiseslookuphostname-options). + * The value could be: + * + * * `ipv4first`: for `order` defaulting to `ipv4first`. + * * `ipv6first`: for `order` defaulting to `ipv6first`. + * * `verbatim`: for `order` defaulting to `verbatim`. + * @since v18.17.0 + */ + function getDefaultResultOrder(): "ipv4first" | "ipv6first" | "verbatim"; + /** + * Sets the IP address and port of servers to be used when performing DNS + * resolution. The `servers` argument is an array of [RFC 5952](https://tools.ietf.org/html/rfc5952#section-6) formatted + * addresses. If the port is the IANA default DNS port (53) it can be omitted. + * + * ```js + * dns.setServers([ + * '4.4.4.4', + * '[2001:4860:4860::8888]', + * '4.4.4.4:1053', + * '[2001:4860:4860::8888]:1053', + * ]); + * ``` + * + * An error will be thrown if an invalid address is provided. + * + * The `dns.setServers()` method must not be called while a DNS query is in + * progress. + * + * The {@link setServers} method affects only {@link resolve}, `dns.resolve*()` and {@link reverse} (and specifically _not_ {@link lookup}). + * + * This method works much like [resolve.conf](https://man7.org/linux/man-pages/man5/resolv.conf.5.html). + * That is, if attempting to resolve with the first server provided results in a `NOTFOUND` error, the `resolve()` method will _not_ attempt to resolve with + * subsequent servers provided. Fallback DNS servers will only be used if the + * earlier ones time out or result in some other error. + * @since v0.11.3 + * @param servers array of [RFC 5952](https://datatracker.ietf.org/doc/html/rfc5952#section-6) formatted addresses + */ + function setServers(servers: readonly string[]): void; + /** + * Returns an array of IP address strings, formatted according to [RFC 5952](https://tools.ietf.org/html/rfc5952#section-6), + * that are currently configured for DNS resolution. A string will include a port + * section if a custom port is used. + * + * ```js + * [ + * '4.4.4.4', + * '2001:4860:4860::8888', + * '4.4.4.4:1053', + * '[2001:4860:4860::8888]:1053', + * ] + * ``` + * @since v0.11.3 + */ + function getServers(): string[]; + /** + * Set the default value of `order` in {@link lookup} and [`dnsPromises.lookup()`](https://nodejs.org/docs/latest-v25.x/api/dns.html#dnspromiseslookuphostname-options). + * The value could be: + * + * * `ipv4first`: sets default `order` to `ipv4first`. + * * `ipv6first`: sets default `order` to `ipv6first`. + * * `verbatim`: sets default `order` to `verbatim`. + * + * The default is `verbatim` and {@link setDefaultResultOrder} have higher + * priority than [`--dns-result-order`](https://nodejs.org/docs/latest-v25.x/api/cli.html#--dns-result-orderorder). When using + * [worker threads](https://nodejs.org/docs/latest-v25.x/api/worker_threads.html), {@link setDefaultResultOrder} from the main + * thread won't affect the default dns orders in workers. + * @since v16.4.0, v14.18.0 + * @param order must be `'ipv4first'`, `'ipv6first'` or `'verbatim'`. + */ + function setDefaultResultOrder(order: "ipv4first" | "ipv6first" | "verbatim"): void; + // Error codes + const NODATA: "ENODATA"; + const FORMERR: "EFORMERR"; + const SERVFAIL: "ESERVFAIL"; + const NOTFOUND: "ENOTFOUND"; + const NOTIMP: "ENOTIMP"; + const REFUSED: "EREFUSED"; + const BADQUERY: "EBADQUERY"; + const BADNAME: "EBADNAME"; + const BADFAMILY: "EBADFAMILY"; + const BADRESP: "EBADRESP"; + const CONNREFUSED: "ECONNREFUSED"; + const TIMEOUT: "ETIMEOUT"; + const EOF: "EOF"; + const FILE: "EFILE"; + const NOMEM: "ENOMEM"; + const DESTRUCTION: "EDESTRUCTION"; + const BADSTR: "EBADSTR"; + const BADFLAGS: "EBADFLAGS"; + const NONAME: "ENONAME"; + const BADHINTS: "EBADHINTS"; + const NOTINITIALIZED: "ENOTINITIALIZED"; + const LOADIPHLPAPI: "ELOADIPHLPAPI"; + const ADDRGETNETWORKPARAMS: "EADDRGETNETWORKPARAMS"; + const CANCELLED: "ECANCELLED"; + interface ResolverOptions { + /** + * Query timeout in milliseconds, or `-1` to use the default timeout. + */ + timeout?: number | undefined; + /** + * The number of tries the resolver will try contacting each name server before giving up. + * @default 4 + */ + tries?: number | undefined; + /** + * The max retry timeout, in milliseconds. + * @default 0 + */ + maxTimeout?: number | undefined; + } + /** + * An independent resolver for DNS requests. + * + * Creating a new resolver uses the default server settings. Setting + * the servers used for a resolver using [`resolver.setServers()`](https://nodejs.org/docs/latest-v25.x/api/dns.html#dnssetserversservers) does not affect + * other resolvers: + * + * ```js + * import { Resolver } from 'node:dns'; + * const resolver = new Resolver(); + * resolver.setServers(['4.4.4.4']); + * + * // This request will use the server at 4.4.4.4, independent of global settings. + * resolver.resolve4('example.org', (err, addresses) => { + * // ... + * }); + * ``` + * + * The following methods from the `node:dns` module are available: + * + * * `resolver.getServers()` + * * `resolver.resolve()` + * * `resolver.resolve4()` + * * `resolver.resolve6()` + * * `resolver.resolveAny()` + * * `resolver.resolveCaa()` + * * `resolver.resolveCname()` + * * `resolver.resolveMx()` + * * `resolver.resolveNaptr()` + * * `resolver.resolveNs()` + * * `resolver.resolvePtr()` + * * `resolver.resolveSoa()` + * * `resolver.resolveSrv()` + * * `resolver.resolveTxt()` + * * `resolver.reverse()` + * * `resolver.setServers()` + * @since v8.3.0 + */ + class Resolver { + constructor(options?: ResolverOptions); + /** + * Cancel all outstanding DNS queries made by this resolver. The corresponding + * callbacks will be called with an error with code `ECANCELLED`. + * @since v8.3.0 + */ + cancel(): void; + getServers: typeof getServers; + resolve: typeof resolve; + resolve4: typeof resolve4; + resolve6: typeof resolve6; + resolveAny: typeof resolveAny; + resolveCaa: typeof resolveCaa; + resolveCname: typeof resolveCname; + resolveMx: typeof resolveMx; + resolveNaptr: typeof resolveNaptr; + resolveNs: typeof resolveNs; + resolvePtr: typeof resolvePtr; + resolveSoa: typeof resolveSoa; + resolveSrv: typeof resolveSrv; + resolveTlsa: typeof resolveTlsa; + resolveTxt: typeof resolveTxt; + reverse: typeof reverse; + /** + * The resolver instance will send its requests from the specified IP address. + * This allows programs to specify outbound interfaces when used on multi-homed + * systems. + * + * If a v4 or v6 address is not specified, it is set to the default and the + * operating system will choose a local address automatically. + * + * The resolver will use the v4 local address when making requests to IPv4 DNS + * servers, and the v6 local address when making requests to IPv6 DNS servers. + * The `rrtype` of resolution requests has no impact on the local address used. + * @since v15.1.0, v14.17.0 + * @param [ipv4='0.0.0.0'] A string representation of an IPv4 address. + * @param [ipv6='::0'] A string representation of an IPv6 address. + */ + setLocalAddress(ipv4?: string, ipv6?: string): void; + setServers: typeof setServers; + } +} +declare module "node:dns" { + export * as promises from "node:dns/promises"; +} +declare module "dns" { + export * from "node:dns"; +} diff --git a/server/node_modules/@types/node/dns/promises.d.ts b/server/node_modules/@types/node/dns/promises.d.ts new file mode 100644 index 0000000..8d5f989 --- /dev/null +++ b/server/node_modules/@types/node/dns/promises.d.ts @@ -0,0 +1,503 @@ +/** + * The `dns.promises` API provides an alternative set of asynchronous DNS methods + * that return `Promise` objects rather than using callbacks. The API is accessible + * via `import { promises as dnsPromises } from 'node:dns'` or `import dnsPromises from 'node:dns/promises'`. + * @since v10.6.0 + */ +declare module "node:dns/promises" { + import { + AnyRecord, + CaaRecord, + LookupAddress, + LookupAllOptions, + LookupOneOptions, + LookupOptions, + MxRecord, + NaptrRecord, + RecordWithTtl, + ResolveOptions, + ResolverOptions, + ResolveWithTtlOptions, + SoaRecord, + SrvRecord, + TlsaRecord, + } from "node:dns"; + /** + * Returns an array of IP address strings, formatted according to [RFC 5952](https://tools.ietf.org/html/rfc5952#section-6), + * that are currently configured for DNS resolution. A string will include a port + * section if a custom port is used. + * + * ```js + * [ + * '4.4.4.4', + * '2001:4860:4860::8888', + * '4.4.4.4:1053', + * '[2001:4860:4860::8888]:1053', + * ] + * ``` + * @since v10.6.0 + */ + function getServers(): string[]; + /** + * Resolves a host name (e.g. `'nodejs.org'`) into the first found A (IPv4) or + * AAAA (IPv6) record. All `option` properties are optional. If `options` is an + * integer, then it must be `4` or `6` – if `options` is not provided, then IPv4 + * and IPv6 addresses are both returned if found. + * + * With the `all` option set to `true`, the `Promise` is resolved with `addresses` being an array of objects with the properties `address` and `family`. + * + * On error, the `Promise` is rejected with an [`Error`](https://nodejs.org/docs/latest-v20.x/api/errors.html#class-error) object, where `err.code` is the error code. + * Keep in mind that `err.code` will be set to `'ENOTFOUND'` not only when + * the host name does not exist but also when the lookup fails in other ways + * such as no available file descriptors. + * + * [`dnsPromises.lookup()`](https://nodejs.org/docs/latest-v20.x/api/dns.html#dnspromiseslookuphostname-options) does not necessarily have anything to do with the DNS + * protocol. The implementation uses an operating system facility that can + * associate names with addresses and vice versa. This implementation can have + * subtle but important consequences on the behavior of any Node.js program. Please + * take some time to consult the [Implementation considerations section](https://nodejs.org/docs/latest-v20.x/api/dns.html#implementation-considerations) before + * using `dnsPromises.lookup()`. + * + * Example usage: + * + * ```js + * import dns from 'node:dns'; + * const dnsPromises = dns.promises; + * const options = { + * family: 6, + * hints: dns.ADDRCONFIG | dns.V4MAPPED, + * }; + * + * dnsPromises.lookup('example.com', options).then((result) => { + * console.log('address: %j family: IPv%s', result.address, result.family); + * // address: "2606:2800:220:1:248:1893:25c8:1946" family: IPv6 + * }); + * + * // When options.all is true, the result will be an Array. + * options.all = true; + * dnsPromises.lookup('example.com', options).then((result) => { + * console.log('addresses: %j', result); + * // addresses: [{"address":"2606:2800:220:1:248:1893:25c8:1946","family":6}] + * }); + * ``` + * @since v10.6.0 + */ + function lookup(hostname: string, family: number): Promise<LookupAddress>; + function lookup(hostname: string, options: LookupOneOptions): Promise<LookupAddress>; + function lookup(hostname: string, options: LookupAllOptions): Promise<LookupAddress[]>; + function lookup(hostname: string, options: LookupOptions): Promise<LookupAddress | LookupAddress[]>; + function lookup(hostname: string): Promise<LookupAddress>; + /** + * Resolves the given `address` and `port` into a host name and service using + * the operating system's underlying `getnameinfo` implementation. + * + * If `address` is not a valid IP address, a `TypeError` will be thrown. + * The `port` will be coerced to a number. If it is not a legal port, a `TypeError` will be thrown. + * + * On error, the `Promise` is rejected with an [`Error`](https://nodejs.org/docs/latest-v20.x/api/errors.html#class-error) object, where `err.code` is the error code. + * + * ```js + * import dnsPromises from 'node:dns'; + * dnsPromises.lookupService('127.0.0.1', 22).then((result) => { + * console.log(result.hostname, result.service); + * // Prints: localhost ssh + * }); + * ``` + * @since v10.6.0 + */ + function lookupService( + address: string, + port: number, + ): Promise<{ + hostname: string; + service: string; + }>; + /** + * Uses the DNS protocol to resolve a host name (e.g. `'nodejs.org'`) into an array + * of the resource records. When successful, the `Promise` is resolved with an + * array of resource records. The type and structure of individual results vary + * based on `rrtype`: + * + * <omitted> + * + * On error, the `Promise` is rejected with an [`Error`](https://nodejs.org/docs/latest-v20.x/api/errors.html#class-error) object, where `err.code` + * is one of the [DNS error codes](https://nodejs.org/docs/latest-v20.x/api/dns.html#error-codes). + * @since v10.6.0 + * @param hostname Host name to resolve. + * @param [rrtype='A'] Resource record type. + */ + function resolve(hostname: string): Promise<string[]>; + function resolve(hostname: string, rrtype: "A" | "AAAA" | "CNAME" | "NS" | "PTR"): Promise<string[]>; + function resolve(hostname: string, rrtype: "ANY"): Promise<AnyRecord[]>; + function resolve(hostname: string, rrtype: "CAA"): Promise<CaaRecord[]>; + function resolve(hostname: string, rrtype: "MX"): Promise<MxRecord[]>; + function resolve(hostname: string, rrtype: "NAPTR"): Promise<NaptrRecord[]>; + function resolve(hostname: string, rrtype: "SOA"): Promise<SoaRecord>; + function resolve(hostname: string, rrtype: "SRV"): Promise<SrvRecord[]>; + function resolve(hostname: string, rrtype: "TLSA"): Promise<TlsaRecord[]>; + function resolve(hostname: string, rrtype: "TXT"): Promise<string[][]>; + function resolve(hostname: string, rrtype: string): Promise< + | string[] + | CaaRecord[] + | MxRecord[] + | NaptrRecord[] + | SoaRecord + | SrvRecord[] + | TlsaRecord[] + | string[][] + | AnyRecord[] + >; + /** + * Uses the DNS protocol to resolve IPv4 addresses (`A` records) for the `hostname`. On success, the `Promise` is resolved with an array of IPv4 + * addresses (e.g. `['74.125.79.104', '74.125.79.105', '74.125.79.106']`). + * @since v10.6.0 + * @param hostname Host name to resolve. + */ + function resolve4(hostname: string): Promise<string[]>; + function resolve4(hostname: string, options: ResolveWithTtlOptions): Promise<RecordWithTtl[]>; + function resolve4(hostname: string, options: ResolveOptions): Promise<string[] | RecordWithTtl[]>; + /** + * Uses the DNS protocol to resolve IPv6 addresses (`AAAA` records) for the `hostname`. On success, the `Promise` is resolved with an array of IPv6 + * addresses. + * @since v10.6.0 + * @param hostname Host name to resolve. + */ + function resolve6(hostname: string): Promise<string[]>; + function resolve6(hostname: string, options: ResolveWithTtlOptions): Promise<RecordWithTtl[]>; + function resolve6(hostname: string, options: ResolveOptions): Promise<string[] | RecordWithTtl[]>; + /** + * Uses the DNS protocol to resolve all records (also known as `ANY` or `*` query). + * On success, the `Promise` is resolved with an array containing various types of + * records. Each object has a property `type` that indicates the type of the + * current record. And depending on the `type`, additional properties will be + * present on the object: + * + * <omitted> + * + * Here is an example of the result object: + * + * ```js + * [ { type: 'A', address: '127.0.0.1', ttl: 299 }, + * { type: 'CNAME', value: 'example.com' }, + * { type: 'MX', exchange: 'alt4.aspmx.l.example.com', priority: 50 }, + * { type: 'NS', value: 'ns1.example.com' }, + * { type: 'TXT', entries: [ 'v=spf1 include:_spf.example.com ~all' ] }, + * { type: 'SOA', + * nsname: 'ns1.example.com', + * hostmaster: 'admin.example.com', + * serial: 156696742, + * refresh: 900, + * retry: 900, + * expire: 1800, + * minttl: 60 } ] + * ``` + * @since v10.6.0 + */ + function resolveAny(hostname: string): Promise<AnyRecord[]>; + /** + * Uses the DNS protocol to resolve `CAA` records for the `hostname`. On success, + * the `Promise` is resolved with an array of objects containing available + * certification authority authorization records available for the `hostname` (e.g. `[{critical: 0, iodef: 'mailto:pki@example.com'},{critical: 128, issue: 'pki.example.com'}]`). + * @since v15.0.0, v14.17.0 + */ + function resolveCaa(hostname: string): Promise<CaaRecord[]>; + /** + * Uses the DNS protocol to resolve `CNAME` records for the `hostname`. On success, + * the `Promise` is resolved with an array of canonical name records available for + * the `hostname` (e.g. `['bar.example.com']`). + * @since v10.6.0 + */ + function resolveCname(hostname: string): Promise<string[]>; + /** + * Uses the DNS protocol to resolve mail exchange records (`MX` records) for the `hostname`. On success, the `Promise` is resolved with an array of objects + * containing both a `priority` and `exchange` property (e.g.`[{priority: 10, exchange: 'mx.example.com'}, ...]`). + * @since v10.6.0 + */ + function resolveMx(hostname: string): Promise<MxRecord[]>; + /** + * Uses the DNS protocol to resolve regular expression-based records (`NAPTR` records) for the `hostname`. On success, the `Promise` is resolved with an array + * of objects with the following properties: + * + * * `flags` + * * `service` + * * `regexp` + * * `replacement` + * * `order` + * * `preference` + * + * ```js + * { + * flags: 's', + * service: 'SIP+D2U', + * regexp: '', + * replacement: '_sip._udp.example.com', + * order: 30, + * preference: 100 + * } + * ``` + * @since v10.6.0 + */ + function resolveNaptr(hostname: string): Promise<NaptrRecord[]>; + /** + * Uses the DNS protocol to resolve name server records (`NS` records) for the `hostname`. On success, the `Promise` is resolved with an array of name server + * records available for `hostname` (e.g.`['ns1.example.com', 'ns2.example.com']`). + * @since v10.6.0 + */ + function resolveNs(hostname: string): Promise<string[]>; + /** + * Uses the DNS protocol to resolve pointer records (`PTR` records) for the `hostname`. On success, the `Promise` is resolved with an array of strings + * containing the reply records. + * @since v10.6.0 + */ + function resolvePtr(hostname: string): Promise<string[]>; + /** + * Uses the DNS protocol to resolve a start of authority record (`SOA` record) for + * the `hostname`. On success, the `Promise` is resolved with an object with the + * following properties: + * + * * `nsname` + * * `hostmaster` + * * `serial` + * * `refresh` + * * `retry` + * * `expire` + * * `minttl` + * + * ```js + * { + * nsname: 'ns.example.com', + * hostmaster: 'root.example.com', + * serial: 2013101809, + * refresh: 10000, + * retry: 2400, + * expire: 604800, + * minttl: 3600 + * } + * ``` + * @since v10.6.0 + */ + function resolveSoa(hostname: string): Promise<SoaRecord>; + /** + * Uses the DNS protocol to resolve service records (`SRV` records) for the `hostname`. On success, the `Promise` is resolved with an array of objects with + * the following properties: + * + * * `priority` + * * `weight` + * * `port` + * * `name` + * + * ```js + * { + * priority: 10, + * weight: 5, + * port: 21223, + * name: 'service.example.com' + * } + * ``` + * @since v10.6.0 + */ + function resolveSrv(hostname: string): Promise<SrvRecord[]>; + /** + * Uses the DNS protocol to resolve certificate associations (`TLSA` records) for + * the `hostname`. On success, the `Promise` is resolved with an array of objectsAdd commentMore actions + * with these properties: + * + * * `certUsage` + * * `selector` + * * `match` + * * `data` + * + * ```js + * { + * certUsage: 3, + * selector: 1, + * match: 1, + * data: [ArrayBuffer] + * } + * ``` + * @since v23.9.0, v22.15.0 + */ + function resolveTlsa(hostname: string): Promise<TlsaRecord[]>; + /** + * Uses the DNS protocol to resolve text queries (`TXT` records) for the `hostname`. On success, the `Promise` is resolved with a two-dimensional array + * of the text records available for `hostname` (e.g.`[ ['v=spf1 ip4:0.0.0.0 ', '~all' ] ]`). Each sub-array contains TXT chunks of + * one record. Depending on the use case, these could be either joined together or + * treated separately. + * @since v10.6.0 + */ + function resolveTxt(hostname: string): Promise<string[][]>; + /** + * Performs a reverse DNS query that resolves an IPv4 or IPv6 address to an + * array of host names. + * + * On error, the `Promise` is rejected with an [`Error`](https://nodejs.org/docs/latest-v20.x/api/errors.html#class-error) object, where `err.code` + * is one of the [DNS error codes](https://nodejs.org/docs/latest-v20.x/api/dns.html#error-codes). + * @since v10.6.0 + */ + function reverse(ip: string): Promise<string[]>; + /** + * Get the default value for `verbatim` in {@link lookup} and [dnsPromises.lookup()](https://nodejs.org/docs/latest-v20.x/api/dns.html#dnspromiseslookuphostname-options). + * The value could be: + * + * * `ipv4first`: for `verbatim` defaulting to `false`. + * * `verbatim`: for `verbatim` defaulting to `true`. + * @since v20.1.0 + */ + function getDefaultResultOrder(): "ipv4first" | "verbatim"; + /** + * Sets the IP address and port of servers to be used when performing DNS + * resolution. The `servers` argument is an array of [RFC 5952](https://tools.ietf.org/html/rfc5952#section-6) formatted + * addresses. If the port is the IANA default DNS port (53) it can be omitted. + * + * ```js + * dnsPromises.setServers([ + * '4.4.4.4', + * '[2001:4860:4860::8888]', + * '4.4.4.4:1053', + * '[2001:4860:4860::8888]:1053', + * ]); + * ``` + * + * An error will be thrown if an invalid address is provided. + * + * The `dnsPromises.setServers()` method must not be called while a DNS query is in + * progress. + * + * This method works much like [resolve.conf](https://man7.org/linux/man-pages/man5/resolv.conf.5.html). + * That is, if attempting to resolve with the first server provided results in a `NOTFOUND` error, the `resolve()` method will _not_ attempt to resolve with + * subsequent servers provided. Fallback DNS servers will only be used if the + * earlier ones time out or result in some other error. + * @since v10.6.0 + * @param servers array of `RFC 5952` formatted addresses + */ + function setServers(servers: readonly string[]): void; + /** + * Set the default value of `order` in `dns.lookup()` and `{@link lookup}`. The value could be: + * + * * `ipv4first`: sets default `order` to `ipv4first`. + * * `ipv6first`: sets default `order` to `ipv6first`. + * * `verbatim`: sets default `order` to `verbatim`. + * + * The default is `verbatim` and [dnsPromises.setDefaultResultOrder()](https://nodejs.org/docs/latest-v20.x/api/dns.html#dnspromisessetdefaultresultorderorder) + * have higher priority than [`--dns-result-order`](https://nodejs.org/docs/latest-v20.x/api/cli.html#--dns-result-orderorder). + * When using [worker threads](https://nodejs.org/docs/latest-v20.x/api/worker_threads.html), [`dnsPromises.setDefaultResultOrder()`](https://nodejs.org/docs/latest-v20.x/api/dns.html#dnspromisessetdefaultresultorderorder) + * from the main thread won't affect the default dns orders in workers. + * @since v16.4.0, v14.18.0 + * @param order must be `'ipv4first'`, `'ipv6first'` or `'verbatim'`. + */ + function setDefaultResultOrder(order: "ipv4first" | "ipv6first" | "verbatim"): void; + // Error codes + const NODATA: "ENODATA"; + const FORMERR: "EFORMERR"; + const SERVFAIL: "ESERVFAIL"; + const NOTFOUND: "ENOTFOUND"; + const NOTIMP: "ENOTIMP"; + const REFUSED: "EREFUSED"; + const BADQUERY: "EBADQUERY"; + const BADNAME: "EBADNAME"; + const BADFAMILY: "EBADFAMILY"; + const BADRESP: "EBADRESP"; + const CONNREFUSED: "ECONNREFUSED"; + const TIMEOUT: "ETIMEOUT"; + const EOF: "EOF"; + const FILE: "EFILE"; + const NOMEM: "ENOMEM"; + const DESTRUCTION: "EDESTRUCTION"; + const BADSTR: "EBADSTR"; + const BADFLAGS: "EBADFLAGS"; + const NONAME: "ENONAME"; + const BADHINTS: "EBADHINTS"; + const NOTINITIALIZED: "ENOTINITIALIZED"; + const LOADIPHLPAPI: "ELOADIPHLPAPI"; + const ADDRGETNETWORKPARAMS: "EADDRGETNETWORKPARAMS"; + const CANCELLED: "ECANCELLED"; + + /** + * An independent resolver for DNS requests. + * + * Creating a new resolver uses the default server settings. Setting + * the servers used for a resolver using [`resolver.setServers()`](https://nodejs.org/docs/latest-v20.x/api/dns.html#dnspromisessetserversservers) does not affect + * other resolvers: + * + * ```js + * import { promises } from 'node:dns'; + * const resolver = new promises.Resolver(); + * resolver.setServers(['4.4.4.4']); + * + * // This request will use the server at 4.4.4.4, independent of global settings. + * resolver.resolve4('example.org').then((addresses) => { + * // ... + * }); + * + * // Alternatively, the same code can be written using async-await style. + * (async function() { + * const addresses = await resolver.resolve4('example.org'); + * })(); + * ``` + * + * The following methods from the `dnsPromises` API are available: + * + * * `resolver.getServers()` + * * `resolver.resolve()` + * * `resolver.resolve4()` + * * `resolver.resolve6()` + * * `resolver.resolveAny()` + * * `resolver.resolveCaa()` + * * `resolver.resolveCname()` + * * `resolver.resolveMx()` + * * `resolver.resolveNaptr()` + * * `resolver.resolveNs()` + * * `resolver.resolvePtr()` + * * `resolver.resolveSoa()` + * * `resolver.resolveSrv()` + * * `resolver.resolveTxt()` + * * `resolver.reverse()` + * * `resolver.setServers()` + * @since v10.6.0 + */ + class Resolver { + constructor(options?: ResolverOptions); + /** + * Cancel all outstanding DNS queries made by this resolver. The corresponding + * callbacks will be called with an error with code `ECANCELLED`. + * @since v8.3.0 + */ + cancel(): void; + getServers: typeof getServers; + resolve: typeof resolve; + resolve4: typeof resolve4; + resolve6: typeof resolve6; + resolveAny: typeof resolveAny; + resolveCaa: typeof resolveCaa; + resolveCname: typeof resolveCname; + resolveMx: typeof resolveMx; + resolveNaptr: typeof resolveNaptr; + resolveNs: typeof resolveNs; + resolvePtr: typeof resolvePtr; + resolveSoa: typeof resolveSoa; + resolveSrv: typeof resolveSrv; + resolveTlsa: typeof resolveTlsa; + resolveTxt: typeof resolveTxt; + reverse: typeof reverse; + /** + * The resolver instance will send its requests from the specified IP address. + * This allows programs to specify outbound interfaces when used on multi-homed + * systems. + * + * If a v4 or v6 address is not specified, it is set to the default and the + * operating system will choose a local address automatically. + * + * The resolver will use the v4 local address when making requests to IPv4 DNS + * servers, and the v6 local address when making requests to IPv6 DNS servers. + * The `rrtype` of resolution requests has no impact on the local address used. + * @since v15.1.0, v14.17.0 + * @param [ipv4='0.0.0.0'] A string representation of an IPv4 address. + * @param [ipv6='::0'] A string representation of an IPv6 address. + */ + setLocalAddress(ipv4?: string, ipv6?: string): void; + setServers: typeof setServers; + } +} +declare module "dns/promises" { + export * from "node:dns/promises"; +} diff --git a/server/node_modules/@types/node/domain.d.ts b/server/node_modules/@types/node/domain.d.ts new file mode 100644 index 0000000..24a0981 --- /dev/null +++ b/server/node_modules/@types/node/domain.d.ts @@ -0,0 +1,166 @@ +/** + * **This module is pending deprecation.** Once a replacement API has been + * finalized, this module will be fully deprecated. Most developers should + * **not** have cause to use this module. Users who absolutely must have + * the functionality that domains provide may rely on it for the time being + * but should expect to have to migrate to a different solution + * in the future. + * + * Domains provide a way to handle multiple different IO operations as a + * single group. If any of the event emitters or callbacks registered to a + * domain emit an `'error'` event, or throw an error, then the domain object + * will be notified, rather than losing the context of the error in the `process.on('uncaughtException')` handler, or causing the program to + * exit immediately with an error code. + * @deprecated Since v1.4.2 - Deprecated + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/domain.js) + */ +declare module "node:domain" { + import { EventEmitter } from "node:events"; + /** + * The `Domain` class encapsulates the functionality of routing errors and + * uncaught exceptions to the active `Domain` object. + * + * To handle the errors that it catches, listen to its `'error'` event. + */ + class Domain extends EventEmitter { + /** + * An array of event emitters that have been explicitly added to the domain. + */ + members: EventEmitter[]; + /** + * The `enter()` method is plumbing used by the `run()`, `bind()`, and `intercept()` methods to set the active domain. It sets `domain.active` and `process.domain` to the domain, and implicitly + * pushes the domain onto the domain + * stack managed by the domain module (see {@link exit} for details on the + * domain stack). The call to `enter()` delimits the beginning of a chain of + * asynchronous calls and I/O operations bound to a domain. + * + * Calling `enter()` changes only the active domain, and does not alter the domain + * itself. `enter()` and `exit()` can be called an arbitrary number of times on a + * single domain. + */ + enter(): void; + /** + * The `exit()` method exits the current domain, popping it off the domain stack. + * Any time execution is going to switch to the context of a different chain of + * asynchronous calls, it's important to ensure that the current domain is exited. + * The call to `exit()` delimits either the end of or an interruption to the chain + * of asynchronous calls and I/O operations bound to a domain. + * + * If there are multiple, nested domains bound to the current execution context, `exit()` will exit any domains nested within this domain. + * + * Calling `exit()` changes only the active domain, and does not alter the domain + * itself. `enter()` and `exit()` can be called an arbitrary number of times on a + * single domain. + */ + exit(): void; + /** + * Run the supplied function in the context of the domain, implicitly + * binding all event emitters, timers, and low-level requests that are + * created in that context. Optionally, arguments can be passed to + * the function. + * + * This is the most basic way to use a domain. + * + * ```js + * import domain from 'node:domain'; + * import fs from 'node:fs'; + * const d = domain.create(); + * d.on('error', (er) => { + * console.error('Caught error!', er); + * }); + * d.run(() => { + * process.nextTick(() => { + * setTimeout(() => { // Simulating some various async stuff + * fs.open('non-existent file', 'r', (er, fd) => { + * if (er) throw er; + * // proceed... + * }); + * }, 100); + * }); + * }); + * ``` + * + * In this example, the `d.on('error')` handler will be triggered, rather + * than crashing the program. + */ + run<T>(fn: (...args: any[]) => T, ...args: any[]): T; + /** + * Explicitly adds an emitter to the domain. If any event handlers called by + * the emitter throw an error, or if the emitter emits an `'error'` event, it + * will be routed to the domain's `'error'` event, just like with implicit + * binding. + * + * If the `EventEmitter` was already bound to a domain, it is removed from that + * one, and bound to this one instead. + * @param emitter emitter to be added to the domain + */ + add(emitter: EventEmitter): void; + /** + * The opposite of {@link add}. Removes domain handling from the + * specified emitter. + * @param emitter emitter to be removed from the domain + */ + remove(emitter: EventEmitter): void; + /** + * The returned function will be a wrapper around the supplied callback + * function. When the returned function is called, any errors that are + * thrown will be routed to the domain's `'error'` event. + * + * ```js + * const d = domain.create(); + * + * function readSomeFile(filename, cb) { + * fs.readFile(filename, 'utf8', d.bind((er, data) => { + * // If this throws, it will also be passed to the domain. + * return cb(er, data ? JSON.parse(data) : null); + * })); + * } + * + * d.on('error', (er) => { + * // An error occurred somewhere. If we throw it now, it will crash the program + * // with the normal line number and stack message. + * }); + * ``` + * @param callback The callback function + * @return The bound function + */ + bind<T extends Function>(callback: T): T; + /** + * This method is almost identical to {@link bind}. However, in + * addition to catching thrown errors, it will also intercept `Error` objects sent as the first argument to the function. + * + * In this way, the common `if (err) return callback(err);` pattern can be replaced + * with a single error handler in a single place. + * + * ```js + * const d = domain.create(); + * + * function readSomeFile(filename, cb) { + * fs.readFile(filename, 'utf8', d.intercept((data) => { + * // Note, the first argument is never passed to the + * // callback since it is assumed to be the 'Error' argument + * // and thus intercepted by the domain. + * + * // If this throws, it will also be passed to the domain + * // so the error-handling logic can be moved to the 'error' + * // event on the domain instead of being repeated throughout + * // the program. + * return cb(null, JSON.parse(data)); + * })); + * } + * + * d.on('error', (er) => { + * // An error occurred somewhere. If we throw it now, it will crash the program + * // with the normal line number and stack message. + * }); + * ``` + * @param callback The callback function + * @return The intercepted function + */ + intercept<T extends Function>(callback: T): T; + } + function create(): Domain; +} +declare module "domain" { + export * from "node:domain"; +} diff --git a/server/node_modules/@types/node/events.d.ts b/server/node_modules/@types/node/events.d.ts new file mode 100644 index 0000000..4ed0f65 --- /dev/null +++ b/server/node_modules/@types/node/events.d.ts @@ -0,0 +1,1054 @@ +/** + * Much of the Node.js core API is built around an idiomatic asynchronous + * event-driven architecture in which certain kinds of objects (called "emitters") + * emit named events that cause `Function` objects ("listeners") to be called. + * + * For instance: a `net.Server` object emits an event each time a peer + * connects to it; a `fs.ReadStream` emits an event when the file is opened; + * a `stream` emits an event whenever data is available to be read. + * + * All objects that emit events are instances of the `EventEmitter` class. These + * objects expose an `eventEmitter.on()` function that allows one or more + * functions to be attached to named events emitted by the object. Typically, + * event names are camel-cased strings but any valid JavaScript property key + * can be used. + * + * When the `EventEmitter` object emits an event, all of the functions attached + * to that specific event are called _synchronously_. Any values returned by the + * called listeners are _ignored_ and discarded. + * + * The following example shows a simple `EventEmitter` instance with a single + * listener. The `eventEmitter.on()` method is used to register listeners, while + * the `eventEmitter.emit()` method is used to trigger the event. + * + * ```js + * import { EventEmitter } from 'node:events'; + * + * class MyEmitter extends EventEmitter {} + * + * const myEmitter = new MyEmitter(); + * myEmitter.on('event', () => { + * console.log('an event occurred!'); + * }); + * myEmitter.emit('event'); + * ``` + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/events.js) + */ +declare module "node:events" { + import { AsyncResource, AsyncResourceOptions } from "node:async_hooks"; + // #region Event map helpers + type EventMap<T> = Record<keyof T, any[]>; + type IfEventMap<Events extends EventMap<Events>, True, False> = {} extends Events ? False : True; + type Args<Events extends EventMap<Events>, EventName extends string | symbol> = IfEventMap< + Events, + EventName extends keyof Events ? Events[EventName] + : EventName extends keyof EventEmitterEventMap ? EventEmitterEventMap[EventName] + : any[], + any[] + >; + type EventNames<Events extends EventMap<Events>, EventName extends string | symbol> = IfEventMap< + Events, + EventName | (keyof Events & (string | symbol)) | keyof EventEmitterEventMap, + string | symbol + >; + type Listener<Events extends EventMap<Events>, EventName extends string | symbol> = IfEventMap< + Events, + ( + ...args: EventName extends keyof Events ? Events[EventName] + : EventName extends keyof EventEmitterEventMap ? EventEmitterEventMap[EventName] + : any[] + ) => void, + (...args: any[]) => void + >; + interface EventEmitterEventMap { + newListener: [eventName: string | symbol, listener: (...args: any[]) => void]; + removeListener: [eventName: string | symbol, listener: (...args: any[]) => void]; + } + // #endregion + interface EventEmitterOptions { + /** + * It enables + * [automatic capturing of promise rejection](https://nodejs.org/docs/latest-v25.x/api/events.html#capture-rejections-of-promises). + * @default false + */ + captureRejections?: boolean | undefined; + } + /** + * The `EventEmitter` class is defined and exposed by the `node:events` module: + * + * ```js + * import { EventEmitter } from 'node:events'; + * ``` + * + * All `EventEmitter`s emit the event `'newListener'` when new listeners are + * added and `'removeListener'` when existing listeners are removed. + * + * It supports the following option: + * @since v0.1.26 + */ + class EventEmitter<T extends EventMap<T> = any> { + constructor(options?: EventEmitterOptions); + } + interface EventEmitter<T extends EventMap<T> = any> extends NodeJS.EventEmitter<T> {} + global { + namespace NodeJS { + interface EventEmitter<T extends EventMap<T> = any> { + /** + * The `Symbol.for('nodejs.rejection')` method is called in case a + * promise rejection happens when emitting an event and + * `captureRejections` is enabled on the emitter. + * It is possible to use `events.captureRejectionSymbol` in + * place of `Symbol.for('nodejs.rejection')`. + * + * ```js + * import { EventEmitter, captureRejectionSymbol } from 'node:events'; + * + * class MyClass extends EventEmitter { + * constructor() { + * super({ captureRejections: true }); + * } + * + * [captureRejectionSymbol](err, event, ...args) { + * console.log('rejection happened for', event, 'with', err, ...args); + * this.destroy(err); + * } + * + * destroy(err) { + * // Tear the resource down here. + * } + * } + * ``` + * @since v13.4.0, v12.16.0 + */ + [EventEmitter.captureRejectionSymbol]?(error: Error, event: string | symbol, ...args: any[]): void; + /** + * Alias for `emitter.on(eventName, listener)`. + * @since v0.1.26 + */ + addListener<E extends string | symbol>(eventName: EventNames<T, E>, listener: Listener<T, E>): this; + /** + * Synchronously calls each of the listeners registered for the event named + * `eventName`, in the order they were registered, passing the supplied arguments + * to each. + * + * Returns `true` if the event had listeners, `false` otherwise. + * + * ```js + * import { EventEmitter } from 'node:events'; + * const myEmitter = new EventEmitter(); + * + * // First listener + * myEmitter.on('event', function firstListener() { + * console.log('Helloooo! first listener'); + * }); + * // Second listener + * myEmitter.on('event', function secondListener(arg1, arg2) { + * console.log(`event with parameters ${arg1}, ${arg2} in second listener`); + * }); + * // Third listener + * myEmitter.on('event', function thirdListener(...args) { + * const parameters = args.join(', '); + * console.log(`event with parameters ${parameters} in third listener`); + * }); + * + * console.log(myEmitter.listeners('event')); + * + * myEmitter.emit('event', 1, 2, 3, 4, 5); + * + * // Prints: + * // [ + * // [Function: firstListener], + * // [Function: secondListener], + * // [Function: thirdListener] + * // ] + * // Helloooo! first listener + * // event with parameters 1, 2 in second listener + * // event with parameters 1, 2, 3, 4, 5 in third listener + * ``` + * @since v0.1.26 + */ + emit<E extends string | symbol>(eventName: EventNames<T, E>, ...args: Args<T, E>): boolean; + /** + * Returns an array listing the events for which the emitter has registered + * listeners. + * + * ```js + * import { EventEmitter } from 'node:events'; + * + * const myEE = new EventEmitter(); + * myEE.on('foo', () => {}); + * myEE.on('bar', () => {}); + * + * const sym = Symbol('symbol'); + * myEE.on(sym, () => {}); + * + * console.log(myEE.eventNames()); + * // Prints: [ 'foo', 'bar', Symbol(symbol) ] + * ``` + * @since v6.0.0 + */ + eventNames(): (string | symbol)[]; + /** + * Returns the current max listener value for the `EventEmitter` which is either + * set by `emitter.setMaxListeners(n)` or defaults to + * `events.defaultMaxListeners`. + * @since v1.0.0 + */ + getMaxListeners(): number; + /** + * Returns the number of listeners listening for the event named `eventName`. + * If `listener` is provided, it will return how many times the listener is found + * in the list of the listeners of the event. + * @since v3.2.0 + * @param eventName The name of the event being listened for + * @param listener The event handler function + */ + listenerCount<E extends string | symbol>( + eventName: EventNames<T, E>, + listener?: Listener<T, E>, + ): number; + /** + * Returns a copy of the array of listeners for the event named `eventName`. + * + * ```js + * server.on('connection', (stream) => { + * console.log('someone connected!'); + * }); + * console.log(util.inspect(server.listeners('connection'))); + * // Prints: [ [Function] ] + * ``` + * @since v0.1.26 + */ + listeners<E extends string | symbol>(eventName: EventNames<T, E>): Listener<T, E>[]; + /** + * Alias for `emitter.removeListener()`. + * @since v10.0.0 + */ + off<E extends string | symbol>(eventName: EventNames<T, E>, listener: Listener<T, E>): this; + /** + * Adds the `listener` function to the end of the listeners array for the + * event named `eventName`. No checks are made to see if the `listener` has + * already been added. Multiple calls passing the same combination of `eventName` + * and `listener` will result in the `listener` being added, and called, multiple + * times. + * + * ```js + * server.on('connection', (stream) => { + * console.log('someone connected!'); + * }); + * ``` + * + * Returns a reference to the `EventEmitter`, so that calls can be chained. + * + * By default, event listeners are invoked in the order they are added. The + * `emitter.prependListener()` method can be used as an alternative to add the + * event listener to the beginning of the listeners array. + * + * ```js + * import { EventEmitter } from 'node:events'; + * const myEE = new EventEmitter(); + * myEE.on('foo', () => console.log('a')); + * myEE.prependListener('foo', () => console.log('b')); + * myEE.emit('foo'); + * // Prints: + * // b + * // a + * ``` + * @since v0.1.101 + * @param eventName The name of the event. + * @param listener The callback function + */ + on<E extends string | symbol>(eventName: EventNames<T, E>, listener: Listener<T, E>): this; + /** + * Adds a **one-time** `listener` function for the event named `eventName`. The + * next time `eventName` is triggered, this listener is removed and then invoked. + * + * ```js + * server.once('connection', (stream) => { + * console.log('Ah, we have our first user!'); + * }); + * ``` + * + * Returns a reference to the `EventEmitter`, so that calls can be chained. + * + * By default, event listeners are invoked in the order they are added. The + * `emitter.prependOnceListener()` method can be used as an alternative to add the + * event listener to the beginning of the listeners array. + * + * ```js + * import { EventEmitter } from 'node:events'; + * const myEE = new EventEmitter(); + * myEE.once('foo', () => console.log('a')); + * myEE.prependOnceListener('foo', () => console.log('b')); + * myEE.emit('foo'); + * // Prints: + * // b + * // a + * ``` + * @since v0.3.0 + * @param eventName The name of the event. + * @param listener The callback function + */ + once<E extends string | symbol>(eventName: EventNames<T, E>, listener: Listener<T, E>): this; + /** + * Adds the `listener` function to the _beginning_ of the listeners array for the + * event named `eventName`. No checks are made to see if the `listener` has + * already been added. Multiple calls passing the same combination of `eventName` + * and `listener` will result in the `listener` being added, and called, multiple + * times. + * + * ```js + * server.prependListener('connection', (stream) => { + * console.log('someone connected!'); + * }); + * ``` + * + * Returns a reference to the `EventEmitter`, so that calls can be chained. + * @since v6.0.0 + * @param eventName The name of the event. + * @param listener The callback function + */ + prependListener<E extends string | symbol>(eventName: EventNames<T, E>, listener: Listener<T, E>): this; + /** + * Adds a **one-time** `listener` function for the event named `eventName` to the + * _beginning_ of the listeners array. The next time `eventName` is triggered, this + * listener is removed, and then invoked. + * + * ```js + * server.prependOnceListener('connection', (stream) => { + * console.log('Ah, we have our first user!'); + * }); + * ``` + * + * Returns a reference to the `EventEmitter`, so that calls can be chained. + * @since v6.0.0 + * @param eventName The name of the event. + * @param listener The callback function + */ + prependOnceListener<E extends string | symbol>( + eventName: EventNames<T, E>, + listener: Listener<T, E>, + ): this; + /** + * Returns a copy of the array of listeners for the event named `eventName`, + * including any wrappers (such as those created by `.once()`). + * + * ```js + * import { EventEmitter } from 'node:events'; + * const emitter = new EventEmitter(); + * emitter.once('log', () => console.log('log once')); + * + * // Returns a new Array with a function `onceWrapper` which has a property + * // `listener` which contains the original listener bound above + * const listeners = emitter.rawListeners('log'); + * const logFnWrapper = listeners[0]; + * + * // Logs "log once" to the console and does not unbind the `once` event + * logFnWrapper.listener(); + * + * // Logs "log once" to the console and removes the listener + * logFnWrapper(); + * + * emitter.on('log', () => console.log('log persistently')); + * // Will return a new Array with a single function bound by `.on()` above + * const newListeners = emitter.rawListeners('log'); + * + * // Logs "log persistently" twice + * newListeners[0](); + * emitter.emit('log'); + * ``` + * @since v9.4.0 + */ + rawListeners<E extends string | symbol>(eventName: EventNames<T, E>): Listener<T, E>[]; + /** + * Removes all listeners, or those of the specified `eventName`. + * + * It is bad practice to remove listeners added elsewhere in the code, + * particularly when the `EventEmitter` instance was created by some other + * component or module (e.g. sockets or file streams). + * + * Returns a reference to the `EventEmitter`, so that calls can be chained. + * @since v0.1.26 + */ + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + removeAllListeners<E extends string | symbol>(eventName?: EventNames<T, E>): this; + /** + * Removes the specified `listener` from the listener array for the event named + * `eventName`. + * + * ```js + * const callback = (stream) => { + * console.log('someone connected!'); + * }; + * server.on('connection', callback); + * // ... + * server.removeListener('connection', callback); + * ``` + * + * `removeListener()` will remove, at most, one instance of a listener from the + * listener array. If any single listener has been added multiple times to the + * listener array for the specified `eventName`, then `removeListener()` must be + * called multiple times to remove each instance. + * + * Once an event is emitted, all listeners attached to it at the + * time of emitting are called in order. This implies that any + * `removeListener()` or `removeAllListeners()` calls _after_ emitting and + * _before_ the last listener finishes execution will not remove them from + * `emit()` in progress. Subsequent events behave as expected. + * + * ```js + * import { EventEmitter } from 'node:events'; + * class MyEmitter extends EventEmitter {} + * const myEmitter = new MyEmitter(); + * + * const callbackA = () => { + * console.log('A'); + * myEmitter.removeListener('event', callbackB); + * }; + * + * const callbackB = () => { + * console.log('B'); + * }; + * + * myEmitter.on('event', callbackA); + * + * myEmitter.on('event', callbackB); + * + * // callbackA removes listener callbackB but it will still be called. + * // Internal listener array at time of emit [callbackA, callbackB] + * myEmitter.emit('event'); + * // Prints: + * // A + * // B + * + * // callbackB is now removed. + * // Internal listener array [callbackA] + * myEmitter.emit('event'); + * // Prints: + * // A + * ``` + * + * Because listeners are managed using an internal array, calling this will + * change the position indexes of any listener registered _after_ the listener + * being removed. This will not impact the order in which listeners are called, + * but it means that any copies of the listener array as returned by + * the `emitter.listeners()` method will need to be recreated. + * + * When a single function has been added as a handler multiple times for a single + * event (as in the example below), `removeListener()` will remove the most + * recently added instance. In the example the `once('ping')` + * listener is removed: + * + * ```js + * import { EventEmitter } from 'node:events'; + * const ee = new EventEmitter(); + * + * function pong() { + * console.log('pong'); + * } + * + * ee.on('ping', pong); + * ee.once('ping', pong); + * ee.removeListener('ping', pong); + * + * ee.emit('ping'); + * ee.emit('ping'); + * ``` + * + * Returns a reference to the `EventEmitter`, so that calls can be chained. + * @since v0.1.26 + */ + removeListener<E extends string | symbol>(eventName: EventNames<T, E>, listener: Listener<T, E>): this; + /** + * By default `EventEmitter`s will print a warning if more than `10` listeners are + * added for a particular event. This is a useful default that helps finding + * memory leaks. The `emitter.setMaxListeners()` method allows the limit to be + * modified for this specific `EventEmitter` instance. The value can be set to + * `Infinity` (or `0`) to indicate an unlimited number of listeners. + * + * Returns a reference to the `EventEmitter`, so that calls can be chained. + * @since v0.3.5 + */ + setMaxListeners(n: number): this; + } + } + } + namespace EventEmitter { + export { EventEmitter, EventEmitterEventMap, EventEmitterOptions }; + } + namespace EventEmitter { + interface Abortable { + signal?: AbortSignal | undefined; + } + /** + * See how to write a custom [rejection handler](https://nodejs.org/docs/latest-v25.x/api/events.html#emittersymbolfornodejsrejectionerr-eventname-args). + * @since v13.4.0, v12.16.0 + */ + const captureRejectionSymbol: unique symbol; + /** + * Change the default `captureRejections` option on all new `EventEmitter` objects. + * @since v13.4.0, v12.16.0 + */ + let captureRejections: boolean; + /** + * By default, a maximum of `10` listeners can be registered for any single + * event. This limit can be changed for individual `EventEmitter` instances + * using the `emitter.setMaxListeners(n)` method. To change the default + * for _all_ `EventEmitter` instances, the `events.defaultMaxListeners` + * property can be used. If this value is not a positive number, a `RangeError` + * is thrown. + * + * Take caution when setting the `events.defaultMaxListeners` because the + * change affects _all_ `EventEmitter` instances, including those created before + * the change is made. However, calling `emitter.setMaxListeners(n)` still has + * precedence over `events.defaultMaxListeners`. + * + * This is not a hard limit. The `EventEmitter` instance will allow + * more listeners to be added but will output a trace warning to stderr indicating + * that a "possible EventEmitter memory leak" has been detected. For any single + * `EventEmitter`, the `emitter.getMaxListeners()` and `emitter.setMaxListeners()` + * methods can be used to temporarily avoid this warning: + * + * `defaultMaxListeners` has no effect on `AbortSignal` instances. While it is + * still possible to use `emitter.setMaxListeners(n)` to set a warning limit + * for individual `AbortSignal` instances, per default `AbortSignal` instances will not warn. + * + * ```js + * import { EventEmitter } from 'node:events'; + * const emitter = new EventEmitter(); + * emitter.setMaxListeners(emitter.getMaxListeners() + 1); + * emitter.once('event', () => { + * // do stuff + * emitter.setMaxListeners(Math.max(emitter.getMaxListeners() - 1, 0)); + * }); + * ``` + * + * The `--trace-warnings` command-line flag can be used to display the + * stack trace for such warnings. + * + * The emitted warning can be inspected with `process.on('warning')` and will + * have the additional `emitter`, `type`, and `count` properties, referring to + * the event emitter instance, the event's name and the number of attached + * listeners, respectively. + * Its `name` property is set to `'MaxListenersExceededWarning'`. + * @since v0.11.2 + */ + let defaultMaxListeners: number; + /** + * This symbol shall be used to install a listener for only monitoring `'error'` + * events. Listeners installed using this symbol are called before the regular + * `'error'` listeners are called. + * + * Installing a listener using this symbol does not change the behavior once an + * `'error'` event is emitted. Therefore, the process will still crash if no + * regular `'error'` listener is installed. + * @since v13.6.0, v12.17.0 + */ + const errorMonitor: unique symbol; + /** + * Listens once to the `abort` event on the provided `signal`. + * + * Listening to the `abort` event on abort signals is unsafe and may + * lead to resource leaks since another third party with the signal can + * call `e.stopImmediatePropagation()`. Unfortunately Node.js cannot change + * this since it would violate the web standard. Additionally, the original + * API makes it easy to forget to remove listeners. + * + * This API allows safely using `AbortSignal`s in Node.js APIs by solving these + * two issues by listening to the event such that `stopImmediatePropagation` does + * not prevent the listener from running. + * + * Returns a disposable so that it may be unsubscribed from more easily. + * + * ```js + * import { addAbortListener } from 'node:events'; + * + * function example(signal) { + * let disposable; + * try { + * signal.addEventListener('abort', (e) => e.stopImmediatePropagation()); + * disposable = addAbortListener(signal, (e) => { + * // Do something when signal is aborted. + * }); + * } finally { + * disposable?.[Symbol.dispose](); + * } + * } + * ``` + * @since v20.5.0 + * @return Disposable that removes the `abort` listener. + */ + function addAbortListener(signal: AbortSignal, resource: (event: Event) => void): Disposable; + /** + * Returns a copy of the array of listeners for the event named `eventName`. + * + * For `EventEmitter`s this behaves exactly the same as calling `.listeners` on + * the emitter. + * + * For `EventTarget`s this is the only way to get the event listeners for the + * event target. This is useful for debugging and diagnostic purposes. + * + * ```js + * import { getEventListeners, EventEmitter } from 'node:events'; + * + * { + * const ee = new EventEmitter(); + * const listener = () => console.log('Events are fun'); + * ee.on('foo', listener); + * console.log(getEventListeners(ee, 'foo')); // [ [Function: listener] ] + * } + * { + * const et = new EventTarget(); + * const listener = () => console.log('Events are fun'); + * et.addEventListener('foo', listener); + * console.log(getEventListeners(et, 'foo')); // [ [Function: listener] ] + * } + * ``` + * @since v15.2.0, v14.17.0 + */ + function getEventListeners(emitter: EventEmitter, name: string | symbol): ((...args: any[]) => void)[]; + function getEventListeners(emitter: EventTarget, name: string): ((...args: any[]) => void)[]; + /** + * Returns the currently set max amount of listeners. + * + * For `EventEmitter`s this behaves exactly the same as calling `.getMaxListeners` on + * the emitter. + * + * For `EventTarget`s this is the only way to get the max event listeners for the + * event target. If the number of event handlers on a single EventTarget exceeds + * the max set, the EventTarget will print a warning. + * + * ```js + * import { getMaxListeners, setMaxListeners, EventEmitter } from 'node:events'; + * + * { + * const ee = new EventEmitter(); + * console.log(getMaxListeners(ee)); // 10 + * setMaxListeners(11, ee); + * console.log(getMaxListeners(ee)); // 11 + * } + * { + * const et = new EventTarget(); + * console.log(getMaxListeners(et)); // 10 + * setMaxListeners(11, et); + * console.log(getMaxListeners(et)); // 11 + * } + * ``` + * @since v19.9.0 + */ + function getMaxListeners(emitter: EventEmitter | EventTarget): number; + /** + * A class method that returns the number of listeners for the given `eventName` + * registered on the given `emitter`. + * + * ```js + * import { EventEmitter, listenerCount } from 'node:events'; + * + * const myEmitter = new EventEmitter(); + * myEmitter.on('event', () => {}); + * myEmitter.on('event', () => {}); + * console.log(listenerCount(myEmitter, 'event')); + * // Prints: 2 + * ``` + * @since v0.9.12 + * @deprecated Use `emitter.listenerCount()` instead. + * @param emitter The emitter to query + * @param eventName The event name + */ + function listenerCount(emitter: EventEmitter, eventName: string | symbol): number; + interface OnOptions extends Abortable { + /** + * Names of events that will end the iteration. + */ + close?: readonly string[] | undefined; + /** + * The high watermark. The emitter is paused every time the size of events + * being buffered is higher than it. Supported only on emitters implementing + * `pause()` and `resume()` methods. + * @default Number.MAX_SAFE_INTEGER + */ + highWaterMark?: number | undefined; + /** + * The low watermark. The emitter is resumed every time the size of events + * being buffered is lower than it. Supported only on emitters implementing + * `pause()` and `resume()` methods. + * @default 1 + */ + lowWaterMark?: number | undefined; + } + /** + * ```js + * import { on, EventEmitter } from 'node:events'; + * import process from 'node:process'; + * + * const ee = new EventEmitter(); + * + * // Emit later on + * process.nextTick(() => { + * ee.emit('foo', 'bar'); + * ee.emit('foo', 42); + * }); + * + * for await (const event of on(ee, 'foo')) { + * // The execution of this inner block is synchronous and it + * // processes one event at a time (even with await). Do not use + * // if concurrent execution is required. + * console.log(event); // prints ['bar'] [42] + * } + * // Unreachable here + * ``` + * + * Returns an `AsyncIterator` that iterates `eventName` events. It will throw + * if the `EventEmitter` emits `'error'`. It removes all listeners when + * exiting the loop. The `value` returned by each iteration is an array + * composed of the emitted event arguments. + * + * An `AbortSignal` can be used to cancel waiting on events: + * + * ```js + * import { on, EventEmitter } from 'node:events'; + * import process from 'node:process'; + * + * const ac = new AbortController(); + * + * (async () => { + * const ee = new EventEmitter(); + * + * // Emit later on + * process.nextTick(() => { + * ee.emit('foo', 'bar'); + * ee.emit('foo', 42); + * }); + * + * for await (const event of on(ee, 'foo', { signal: ac.signal })) { + * // The execution of this inner block is synchronous and it + * // processes one event at a time (even with await). Do not use + * // if concurrent execution is required. + * console.log(event); // prints ['bar'] [42] + * } + * // Unreachable here + * })(); + * + * process.nextTick(() => ac.abort()); + * ``` + * @since v13.6.0, v12.16.0 + * @returns `AsyncIterator` that iterates `eventName` events emitted by the `emitter` + */ + function on( + emitter: EventEmitter, + eventName: string | symbol, + options?: OnOptions, + ): NodeJS.AsyncIterator<any[]>; + function on( + emitter: EventTarget, + eventName: string, + options?: OnOptions, + ): NodeJS.AsyncIterator<any[]>; + interface OnceOptions extends Abortable {} + /** + * Creates a `Promise` that is fulfilled when the `EventEmitter` emits the given + * event or that is rejected if the `EventEmitter` emits `'error'` while waiting. + * The `Promise` will resolve with an array of all the arguments emitted to the + * given event. + * + * This method is intentionally generic and works with the web platform + * [EventTarget][WHATWG-EventTarget] interface, which has no special + * `'error'` event semantics and does not listen to the `'error'` event. + * + * ```js + * import { once, EventEmitter } from 'node:events'; + * import process from 'node:process'; + * + * const ee = new EventEmitter(); + * + * process.nextTick(() => { + * ee.emit('myevent', 42); + * }); + * + * const [value] = await once(ee, 'myevent'); + * console.log(value); + * + * const err = new Error('kaboom'); + * process.nextTick(() => { + * ee.emit('error', err); + * }); + * + * try { + * await once(ee, 'myevent'); + * } catch (err) { + * console.error('error happened', err); + * } + * ``` + * + * The special handling of the `'error'` event is only used when `events.once()` + * is used to wait for another event. If `events.once()` is used to wait for the + * '`error'` event itself, then it is treated as any other kind of event without + * special handling: + * + * ```js + * import { EventEmitter, once } from 'node:events'; + * + * const ee = new EventEmitter(); + * + * once(ee, 'error') + * .then(([err]) => console.log('ok', err.message)) + * .catch((err) => console.error('error', err.message)); + * + * ee.emit('error', new Error('boom')); + * + * // Prints: ok boom + * ``` + * + * An `AbortSignal` can be used to cancel waiting for the event: + * + * ```js + * import { EventEmitter, once } from 'node:events'; + * + * const ee = new EventEmitter(); + * const ac = new AbortController(); + * + * async function foo(emitter, event, signal) { + * try { + * await once(emitter, event, { signal }); + * console.log('event emitted!'); + * } catch (error) { + * if (error.name === 'AbortError') { + * console.error('Waiting for the event was canceled!'); + * } else { + * console.error('There was an error', error.message); + * } + * } + * } + * + * foo(ee, 'foo', ac.signal); + * ac.abort(); // Prints: Waiting for the event was canceled! + * ``` + * @since v11.13.0, v10.16.0 + */ + function once( + emitter: EventEmitter, + eventName: string | symbol, + options?: OnceOptions, + ): Promise<any[]>; + function once(emitter: EventTarget, eventName: string, options?: OnceOptions): Promise<any[]>; + /** + * ```js + * import { setMaxListeners, EventEmitter } from 'node:events'; + * + * const target = new EventTarget(); + * const emitter = new EventEmitter(); + * + * setMaxListeners(5, target, emitter); + * ``` + * @since v15.4.0 + * @param n A non-negative number. The maximum number of listeners per `EventTarget` event. + * @param eventTargets Zero or more `EventTarget` + * or `EventEmitter` instances. If none are specified, `n` is set as the default + * max for all newly created `EventTarget` and `EventEmitter` objects. + * objects. + */ + function setMaxListeners(n: number, ...eventTargets: ReadonlyArray<EventEmitter | EventTarget>): void; + /** + * This is the interface from which event-emitting Node.js APIs inherit in the types package. + * **It is not intended for consumer use.** + * + * It provides event-mapped definitions similar to EventEmitter, except that its signatures + * are deliberately permissive: they provide type _hinting_, but not rigid type-checking, + * for compatibility reasons. + * + * Classes that inherit directly from EventEmitter in JavaScript can inherit directly from + * this interface in the type definitions. Classes that are more than one inheritance level + * away from EventEmitter (eg. `net.Socket` > `stream.Duplex` > `EventEmitter`) must instead + * copy these method definitions into the derived class. Search "#region InternalEventEmitter" + * for examples. + * @internal + */ + interface InternalEventEmitter<T extends EventMap<T>> extends EventEmitter { + addListener<E extends keyof T>(eventName: E, listener: (...args: T[E]) => void): this; + addListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + emit<E extends keyof T>(eventName: E, ...args: T[E]): boolean; + emit(eventName: string | symbol, ...args: any[]): boolean; + listenerCount<E extends keyof T>(eventName: E, listener?: (...args: T[E]) => void): number; + listenerCount(eventName: string | symbol, listener?: (...args: any[]) => void): number; + listeners<E extends keyof T>(eventName: E): ((...args: T[E]) => void)[]; + listeners(eventName: string | symbol): ((...args: any[]) => void)[]; + off<E extends keyof T>(eventName: E, listener: (...args: T[E]) => void): this; + off(eventName: string | symbol, listener: (...args: any[]) => void): this; + on<E extends keyof T>(eventName: E, listener: (...args: T[E]) => void): this; + on(eventName: string | symbol, listener: (...args: any[]) => void): this; + once<E extends keyof T>(eventName: E, listener: (...args: T[E]) => void): this; + once(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependListener<E extends keyof T>(eventName: E, listener: (...args: T[E]) => void): this; + prependListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependOnceListener<E extends keyof T>(eventName: E, listener: (...args: T[E]) => void): this; + prependOnceListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + rawListeners<E extends keyof T>(eventName: E): ((...args: T[E]) => void)[]; + rawListeners(eventName: string | symbol): ((...args: any[]) => void)[]; + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + removeAllListeners<E extends keyof T>(eventName?: E): this; + removeAllListeners(eventName?: string | symbol): this; + removeListener<E extends keyof T>(eventName: E, listener: (...args: T[E]) => void): this; + removeListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + } + interface EventEmitterReferencingAsyncResource extends AsyncResource { + readonly eventEmitter: EventEmitterAsyncResource; + } + interface EventEmitterAsyncResourceOptions extends AsyncResourceOptions, EventEmitterOptions { + /** + * The type of async event. + * @default new.target.name + */ + name?: string | undefined; + } + /** + * Integrates `EventEmitter` with `AsyncResource` for `EventEmitter`s that + * require manual async tracking. Specifically, all events emitted by instances + * of `events.EventEmitterAsyncResource` will run within its [async context](https://nodejs.org/docs/latest-v25.x/api/async_context.html). + * + * ```js + * import { EventEmitterAsyncResource, EventEmitter } from 'node:events'; + * import { notStrictEqual, strictEqual } from 'node:assert'; + * import { executionAsyncId, triggerAsyncId } from 'node:async_hooks'; + * + * // Async tracking tooling will identify this as 'Q'. + * const ee1 = new EventEmitterAsyncResource({ name: 'Q' }); + * + * // 'foo' listeners will run in the EventEmitters async context. + * ee1.on('foo', () => { + * strictEqual(executionAsyncId(), ee1.asyncId); + * strictEqual(triggerAsyncId(), ee1.triggerAsyncId); + * }); + * + * const ee2 = new EventEmitter(); + * + * // 'foo' listeners on ordinary EventEmitters that do not track async + * // context, however, run in the same async context as the emit(). + * ee2.on('foo', () => { + * notStrictEqual(executionAsyncId(), ee2.asyncId); + * notStrictEqual(triggerAsyncId(), ee2.triggerAsyncId); + * }); + * + * Promise.resolve().then(() => { + * ee1.emit('foo'); + * ee2.emit('foo'); + * }); + * ``` + * + * The `EventEmitterAsyncResource` class has the same methods and takes the + * same options as `EventEmitter` and `AsyncResource` themselves. + * @since v17.4.0, v16.14.0 + */ + class EventEmitterAsyncResource extends EventEmitter { + constructor(options?: EventEmitterAsyncResourceOptions); + /** + * The unique `asyncId` assigned to the resource. + */ + readonly asyncId: number; + /** + * The returned `AsyncResource` object has an additional `eventEmitter` property + * that provides a reference to this `EventEmitterAsyncResource`. + */ + readonly asyncResource: EventEmitterReferencingAsyncResource; + /** + * Call all `destroy` hooks. This should only ever be called once. An error will + * be thrown if it is called more than once. This **must** be manually called. If + * the resource is left to be collected by the GC then the `destroy` hooks will + * never be called. + */ + emitDestroy(): void; + /** + * The same `triggerAsyncId` that is passed to the + * `AsyncResource` constructor. + */ + readonly triggerAsyncId: number; + } + /** + * The `NodeEventTarget` is a Node.js-specific extension to `EventTarget` + * that emulates a subset of the `EventEmitter` API. + * @since v14.5.0 + */ + interface NodeEventTarget extends EventTarget { + /** + * Node.js-specific extension to the `EventTarget` class that emulates the + * equivalent `EventEmitter` API. The only difference between `addListener()` and + * `addEventListener()` is that `addListener()` will return a reference to the + * `EventTarget`. + * @since v14.5.0 + */ + addListener(type: string, listener: (arg: any) => void): this; + /** + * Node.js-specific extension to the `EventTarget` class that dispatches the + * `arg` to the list of handlers for `type`. + * @since v15.2.0 + * @returns `true` if event listeners registered for the `type` exist, + * otherwise `false`. + */ + emit(type: string, arg: any): boolean; + /** + * Node.js-specific extension to the `EventTarget` class that returns an array + * of event `type` names for which event listeners are registered. + * @since 14.5.0 + */ + eventNames(): string[]; + /** + * Node.js-specific extension to the `EventTarget` class that returns the number + * of event listeners registered for the `type`. + * @since v14.5.0 + */ + listenerCount(type: string): number; + /** + * Node.js-specific extension to the `EventTarget` class that sets the number + * of max event listeners as `n`. + * @since v14.5.0 + */ + setMaxListeners(n: number): void; + /** + * Node.js-specific extension to the `EventTarget` class that returns the number + * of max event listeners. + * @since v14.5.0 + */ + getMaxListeners(): number; + /** + * Node.js-specific alias for `eventTarget.removeEventListener()`. + * @since v14.5.0 + */ + off(type: string, listener: (arg: any) => void, options?: EventListenerOptions): this; + /** + * Node.js-specific alias for `eventTarget.addEventListener()`. + * @since v14.5.0 + */ + on(type: string, listener: (arg: any) => void): this; + /** + * Node.js-specific extension to the `EventTarget` class that adds a `once` + * listener for the given event `type`. This is equivalent to calling `on` + * with the `once` option set to `true`. + * @since v14.5.0 + */ + once(type: string, listener: (arg: any) => void): this; + /** + * Node.js-specific extension to the `EventTarget` class. If `type` is specified, + * removes all registered listeners for `type`, otherwise removes all registered + * listeners. + * @since v14.5.0 + */ + removeAllListeners(type?: string): this; + /** + * Node.js-specific extension to the `EventTarget` class that removes the + * `listener` for the given `type`. The only difference between `removeListener()` + * and `removeEventListener()` is that `removeListener()` will return a reference + * to the `EventTarget`. + * @since v14.5.0 + */ + removeListener(type: string, listener: (arg: any) => void, options?: EventListenerOptions): this; + } + /** @internal */ + type InternalEventTargetEventProperties<T> = { + [K in keyof T & string as `on${K}`]: ((ev: T[K]) => void) | null; + }; + } + export = EventEmitter; +} +declare module "events" { + import events = require("node:events"); + export = events; +} diff --git a/server/node_modules/@types/node/fs.d.ts b/server/node_modules/@types/node/fs.d.ts new file mode 100644 index 0000000..63af06d --- /dev/null +++ b/server/node_modules/@types/node/fs.d.ts @@ -0,0 +1,4676 @@ +/** + * The `node:fs` module enables interacting with the file system in a + * way modeled on standard POSIX functions. + * + * To use the promise-based APIs: + * + * ```js + * import * as fs from 'node:fs/promises'; + * ``` + * + * To use the callback and sync APIs: + * + * ```js + * import * as fs from 'node:fs'; + * ``` + * + * All file system operations have synchronous, callback, and promise-based + * forms, and are accessible using both CommonJS syntax and ES6 Modules (ESM). + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/fs.js) + */ +declare module "node:fs" { + import { NonSharedBuffer } from "node:buffer"; + import { Abortable, EventEmitter, InternalEventEmitter } from "node:events"; + import { FileHandle } from "node:fs/promises"; + import * as stream from "node:stream"; + import { URL } from "node:url"; + /** + * Valid types for path values in "fs". + */ + type PathLike = string | Buffer | URL; + type PathOrFileDescriptor = PathLike | number; + type TimeLike = string | number | Date; + type NoParamCallback = (err: NodeJS.ErrnoException | null) => void; + type BufferEncodingOption = + | "buffer" + | { + encoding: "buffer"; + }; + interface ObjectEncodingOptions { + encoding?: BufferEncoding | null | undefined; + } + type EncodingOption = ObjectEncodingOptions | BufferEncoding | undefined | null; + type OpenMode = number | string; + type Mode = number | string; + interface StatsBase<T> { + isFile(): boolean; + isDirectory(): boolean; + isBlockDevice(): boolean; + isCharacterDevice(): boolean; + isSymbolicLink(): boolean; + isFIFO(): boolean; + isSocket(): boolean; + dev: T; + ino: T; + mode: T; + nlink: T; + uid: T; + gid: T; + rdev: T; + size: T; + blksize: T; + blocks: T; + atimeMs: T; + mtimeMs: T; + ctimeMs: T; + birthtimeMs: T; + atime: Date; + mtime: Date; + ctime: Date; + birthtime: Date; + } + interface Stats extends StatsBase<number> {} + /** + * A `fs.Stats` object provides information about a file. + * + * Objects returned from {@link stat}, {@link lstat}, {@link fstat}, and + * their synchronous counterparts are of this type. + * If `bigint` in the `options` passed to those methods is true, the numeric values + * will be `bigint` instead of `number`, and the object will contain additional + * nanosecond-precision properties suffixed with `Ns`. `Stat` objects are not to be created directly using the `new` keyword. + * + * ```console + * Stats { + * dev: 2114, + * ino: 48064969, + * mode: 33188, + * nlink: 1, + * uid: 85, + * gid: 100, + * rdev: 0, + * size: 527, + * blksize: 4096, + * blocks: 8, + * atimeMs: 1318289051000.1, + * mtimeMs: 1318289051000.1, + * ctimeMs: 1318289051000.1, + * birthtimeMs: 1318289051000.1, + * atime: Mon, 10 Oct 2011 23:24:11 GMT, + * mtime: Mon, 10 Oct 2011 23:24:11 GMT, + * ctime: Mon, 10 Oct 2011 23:24:11 GMT, + * birthtime: Mon, 10 Oct 2011 23:24:11 GMT } + * ``` + * + * `bigint` version: + * + * ```console + * BigIntStats { + * dev: 2114n, + * ino: 48064969n, + * mode: 33188n, + * nlink: 1n, + * uid: 85n, + * gid: 100n, + * rdev: 0n, + * size: 527n, + * blksize: 4096n, + * blocks: 8n, + * atimeMs: 1318289051000n, + * mtimeMs: 1318289051000n, + * ctimeMs: 1318289051000n, + * birthtimeMs: 1318289051000n, + * atimeNs: 1318289051000000000n, + * mtimeNs: 1318289051000000000n, + * ctimeNs: 1318289051000000000n, + * birthtimeNs: 1318289051000000000n, + * atime: Mon, 10 Oct 2011 23:24:11 GMT, + * mtime: Mon, 10 Oct 2011 23:24:11 GMT, + * ctime: Mon, 10 Oct 2011 23:24:11 GMT, + * birthtime: Mon, 10 Oct 2011 23:24:11 GMT } + * ``` + * @since v0.1.21 + */ + class Stats { + private constructor(); + } + interface StatsFsBase<T> { + /** Type of file system. */ + type: T; + /** Optimal transfer block size. */ + bsize: T; + /** Total data blocks in file system. */ + blocks: T; + /** Free blocks in file system. */ + bfree: T; + /** Available blocks for unprivileged users */ + bavail: T; + /** Total file nodes in file system. */ + files: T; + /** Free file nodes in file system. */ + ffree: T; + } + interface StatsFs extends StatsFsBase<number> {} + /** + * Provides information about a mounted file system. + * + * Objects returned from {@link statfs} and its synchronous counterpart are of + * this type. If `bigint` in the `options` passed to those methods is `true`, the + * numeric values will be `bigint` instead of `number`. + * + * ```console + * StatFs { + * type: 1397114950, + * bsize: 4096, + * blocks: 121938943, + * bfree: 61058895, + * bavail: 61058895, + * files: 999, + * ffree: 1000000 + * } + * ``` + * + * `bigint` version: + * + * ```console + * StatFs { + * type: 1397114950n, + * bsize: 4096n, + * blocks: 121938943n, + * bfree: 61058895n, + * bavail: 61058895n, + * files: 999n, + * ffree: 1000000n + * } + * ``` + * @since v19.6.0, v18.15.0 + */ + class StatsFs {} + interface BigIntStatsFs extends StatsFsBase<bigint> {} + interface StatFsOptions { + bigint?: boolean | undefined; + } + /** + * A representation of a directory entry, which can be a file or a subdirectory + * within the directory, as returned by reading from an `fs.Dir`. The + * directory entry is a combination of the file name and file type pairs. + * + * Additionally, when {@link readdir} or {@link readdirSync} is called with + * the `withFileTypes` option set to `true`, the resulting array is filled with `fs.Dirent` objects, rather than strings or `Buffer` s. + * @since v10.10.0 + */ + class Dirent<Name extends string | Buffer = string> { + /** + * Returns `true` if the `fs.Dirent` object describes a regular file. + * @since v10.10.0 + */ + isFile(): boolean; + /** + * Returns `true` if the `fs.Dirent` object describes a file system + * directory. + * @since v10.10.0 + */ + isDirectory(): boolean; + /** + * Returns `true` if the `fs.Dirent` object describes a block device. + * @since v10.10.0 + */ + isBlockDevice(): boolean; + /** + * Returns `true` if the `fs.Dirent` object describes a character device. + * @since v10.10.0 + */ + isCharacterDevice(): boolean; + /** + * Returns `true` if the `fs.Dirent` object describes a symbolic link. + * @since v10.10.0 + */ + isSymbolicLink(): boolean; + /** + * Returns `true` if the `fs.Dirent` object describes a first-in-first-out + * (FIFO) pipe. + * @since v10.10.0 + */ + isFIFO(): boolean; + /** + * Returns `true` if the `fs.Dirent` object describes a socket. + * @since v10.10.0 + */ + isSocket(): boolean; + /** + * The file name that this `fs.Dirent` object refers to. The type of this + * value is determined by the `options.encoding` passed to {@link readdir} or {@link readdirSync}. + * @since v10.10.0 + */ + name: Name; + /** + * The path to the parent directory of the file this `fs.Dirent` object refers to. + * @since v20.12.0, v18.20.0 + */ + parentPath: string; + } + /** + * A class representing a directory stream. + * + * Created by {@link opendir}, {@link opendirSync}, or `fsPromises.opendir()`. + * + * ```js + * import { opendir } from 'node:fs/promises'; + * + * try { + * const dir = await opendir('./'); + * for await (const dirent of dir) + * console.log(dirent.name); + * } catch (err) { + * console.error(err); + * } + * ``` + * + * When using the async iterator, the `fs.Dir` object will be automatically + * closed after the iterator exits. + * @since v12.12.0 + */ + class Dir implements AsyncIterable<Dirent> { + /** + * The read-only path of this directory as was provided to {@link opendir},{@link opendirSync}, or `fsPromises.opendir()`. + * @since v12.12.0 + */ + readonly path: string; + /** + * Asynchronously iterates over the directory via `readdir(3)` until all entries have been read. + */ + [Symbol.asyncIterator](): NodeJS.AsyncIterator<Dirent>; + /** + * Asynchronously close the directory's underlying resource handle. + * Subsequent reads will result in errors. + * + * A promise is returned that will be fulfilled after the resource has been + * closed. + * @since v12.12.0 + */ + close(): Promise<void>; + close(cb: NoParamCallback): void; + /** + * Synchronously close the directory's underlying resource handle. + * Subsequent reads will result in errors. + * @since v12.12.0 + */ + closeSync(): void; + /** + * Asynchronously read the next directory entry via [`readdir(3)`](http://man7.org/linux/man-pages/man3/readdir.3.html) as an `fs.Dirent`. + * + * A promise is returned that will be fulfilled with an `fs.Dirent`, or `null` if there are no more directory entries to read. + * + * Directory entries returned by this function are in no particular order as + * provided by the operating system's underlying directory mechanisms. + * Entries added or removed while iterating over the directory might not be + * included in the iteration results. + * @since v12.12.0 + * @return containing {fs.Dirent|null} + */ + read(): Promise<Dirent | null>; + read(cb: (err: NodeJS.ErrnoException | null, dirEnt: Dirent | null) => void): void; + /** + * Synchronously read the next directory entry as an `fs.Dirent`. See the + * POSIX [`readdir(3)`](http://man7.org/linux/man-pages/man3/readdir.3.html) documentation for more detail. + * + * If there are no more directory entries to read, `null` will be returned. + * + * Directory entries returned by this function are in no particular order as + * provided by the operating system's underlying directory mechanisms. + * Entries added or removed while iterating over the directory might not be + * included in the iteration results. + * @since v12.12.0 + */ + readSync(): Dirent | null; + /** + * Calls `dir.close()` if the directory handle is open, and returns a promise that + * fulfills when disposal is complete. + * @since v24.1.0 + */ + [Symbol.asyncDispose](): Promise<void>; + /** + * Calls `dir.closeSync()` if the directory handle is open, and returns + * `undefined`. + * @since v24.1.0 + */ + [Symbol.dispose](): void; + } + /** + * Class: fs.StatWatcher + * @since v14.3.0, v12.20.0 + * Extends `EventEmitter` + * A successful call to {@link watchFile} method will return a new fs.StatWatcher object. + */ + interface StatWatcher extends EventEmitter { + /** + * When called, requests that the Node.js event loop _not_ exit so long as the `fs.StatWatcher` is active. Calling `watcher.ref()` multiple times will have + * no effect. + * + * By default, all `fs.StatWatcher` objects are "ref'ed", making it normally + * unnecessary to call `watcher.ref()` unless `watcher.unref()` had been + * called previously. + * @since v14.3.0, v12.20.0 + */ + ref(): this; + /** + * When called, the active `fs.StatWatcher` object will not require the Node.js + * event loop to remain active. If there is no other activity keeping the + * event loop running, the process may exit before the `fs.StatWatcher` object's + * callback is invoked. Calling `watcher.unref()` multiple times will have + * no effect. + * @since v14.3.0, v12.20.0 + */ + unref(): this; + } + interface FSWatcherEventMap { + "change": [eventType: string, filename: string | NonSharedBuffer]; + "close": []; + "error": [error: Error]; + } + interface FSWatcher extends InternalEventEmitter<FSWatcherEventMap> { + /** + * Stop watching for changes on the given `fs.FSWatcher`. Once stopped, the `fs.FSWatcher` object is no longer usable. + * @since v0.5.8 + */ + close(): void; + /** + * When called, requests that the Node.js event loop _not_ exit so long as the `fs.FSWatcher` is active. Calling `watcher.ref()` multiple times will have + * no effect. + * + * By default, all `fs.FSWatcher` objects are "ref'ed", making it normally + * unnecessary to call `watcher.ref()` unless `watcher.unref()` had been + * called previously. + * @since v14.3.0, v12.20.0 + */ + ref(): this; + /** + * When called, the active `fs.FSWatcher` object will not require the Node.js + * event loop to remain active. If there is no other activity keeping the + * event loop running, the process may exit before the `fs.FSWatcher` object's + * callback is invoked. Calling `watcher.unref()` multiple times will have + * no effect. + * @since v14.3.0, v12.20.0 + */ + unref(): this; + } + interface ReadStreamEventMap extends stream.ReadableEventMap { + "close": []; + "data": [chunk: string | NonSharedBuffer]; + "open": [fd: number]; + "ready": []; + } + /** + * Instances of `fs.ReadStream` are created and returned using the {@link createReadStream} function. + * @since v0.1.93 + */ + class ReadStream extends stream.Readable { + close(callback?: (err?: NodeJS.ErrnoException | null) => void): void; + /** + * The number of bytes that have been read so far. + * @since v6.4.0 + */ + bytesRead: number; + /** + * The path to the file the stream is reading from as specified in the first + * argument to `fs.createReadStream()`. If `path` is passed as a string, then`readStream.path` will be a string. If `path` is passed as a `Buffer`, then`readStream.path` will be a + * `Buffer`. If `fd` is specified, then`readStream.path` will be `undefined`. + * @since v0.1.93 + */ + path: string | Buffer; + /** + * This property is `true` if the underlying file has not been opened yet, + * i.e. before the `'ready'` event is emitted. + * @since v11.2.0, v10.16.0 + */ + pending: boolean; + // #region InternalEventEmitter + addListener<E extends keyof ReadStreamEventMap>( + eventName: E, + listener: (...args: ReadStreamEventMap[E]) => void, + ): this; + addListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + emit<E extends keyof ReadStreamEventMap>(eventName: E, ...args: ReadStreamEventMap[E]): boolean; + emit(eventName: string | symbol, ...args: any[]): boolean; + listenerCount<E extends keyof ReadStreamEventMap>( + eventName: E, + listener?: (...args: ReadStreamEventMap[E]) => void, + ): number; + listenerCount(eventName: string | symbol, listener?: (...args: any[]) => void): number; + listeners<E extends keyof ReadStreamEventMap>(eventName: E): ((...args: ReadStreamEventMap[E]) => void)[]; + listeners(eventName: string | symbol): ((...args: any[]) => void)[]; + off<E extends keyof ReadStreamEventMap>(eventName: E, listener: (...args: ReadStreamEventMap[E]) => void): this; + off(eventName: string | symbol, listener: (...args: any[]) => void): this; + on<E extends keyof ReadStreamEventMap>(eventName: E, listener: (...args: ReadStreamEventMap[E]) => void): this; + on(eventName: string | symbol, listener: (...args: any[]) => void): this; + once<E extends keyof ReadStreamEventMap>( + eventName: E, + listener: (...args: ReadStreamEventMap[E]) => void, + ): this; + once(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependListener<E extends keyof ReadStreamEventMap>( + eventName: E, + listener: (...args: ReadStreamEventMap[E]) => void, + ): this; + prependListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependOnceListener<E extends keyof ReadStreamEventMap>( + eventName: E, + listener: (...args: ReadStreamEventMap[E]) => void, + ): this; + prependOnceListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + rawListeners<E extends keyof ReadStreamEventMap>(eventName: E): ((...args: ReadStreamEventMap[E]) => void)[]; + rawListeners(eventName: string | symbol): ((...args: any[]) => void)[]; + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + removeAllListeners<E extends keyof ReadStreamEventMap>(eventName?: E): this; + removeAllListeners(eventName?: string | symbol): this; + removeListener<E extends keyof ReadStreamEventMap>( + eventName: E, + listener: (...args: ReadStreamEventMap[E]) => void, + ): this; + removeListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + // #endregion + } + interface Utf8StreamOptions { + /** + * Appends writes to dest file instead of truncating it. + * @default true + */ + append?: boolean | undefined; + /** + * Which type of data you can send to the write + * function, supported values are `'utf8'` or `'buffer'`. + * @default 'utf8' + */ + contentMode?: "utf8" | "buffer" | undefined; + /** + * A path to a file to be written to (mode controlled by the + * append option). + */ + dest?: string | undefined; + /** + * A file descriptor, something that is returned by `fs.open()` + * or `fs.openSync()`. + */ + fd?: number | undefined; + /** + * An object that has the same API as the `fs` module, useful + * for mocking, testing, or customizing the behavior of the stream. + */ + fs?: object | undefined; + /** + * Perform a `fs.fsyncSync()` every time a write is + * completed. + */ + fsync?: boolean | undefined; + /** + * The maximum length of the internal buffer. If a write + * operation would cause the buffer to exceed `maxLength`, the data written is + * dropped and a drop event is emitted with the dropped data + */ + maxLength?: number | undefined; + /** + * The maximum number of bytes that can be written; + * @default 16384 + */ + maxWrite?: number | undefined; + /** + * The minimum length of the internal buffer that is + * required to be full before flushing. + */ + minLength?: number | undefined; + /** + * Ensure directory for `dest` file exists when true. + * @default false + */ + mkdir?: boolean | undefined; + /** + * Specify the creating file mode (see `fs.open()`). + */ + mode?: number | string | undefined; + /** + * Calls flush every `periodicFlush` milliseconds. + */ + periodicFlush?: number | undefined; + /** + * A function that will be called when `write()`, + * `writeSync()`, or `flushSync()` encounters an `EAGAIN` or `EBUSY` error. + * If the return value is `true` the operation will be retried, otherwise it + * will bubble the error. The `err` is the error that caused this function to + * be called, `writeBufferLen` is the length of the buffer that was written, + * and `remainingBufferLen` is the length of the remaining buffer that the + * stream did not try to write. + */ + retryEAGAIN?: ((err: Error | null, writeBufferLen: number, remainingBufferLen: number) => boolean) | undefined; + /** + * Perform writes synchronously. + */ + sync?: boolean | undefined; + } + interface Utf8StreamEventMap { + "close": []; + "drain": []; + "drop": [data: string | Buffer]; + "error": [error: Error]; + "finish": []; + "ready": []; + "write": [n: number]; + } + /** + * An optimized UTF-8 stream writer that allows for flushing all the internal + * buffering on demand. It handles `EAGAIN` errors correctly, allowing for + * customization, for example, by dropping content if the disk is busy. + * @since v24.6.0 + * @experimental + */ + class Utf8Stream implements EventEmitter { + constructor(options: Utf8StreamOptions); + /** + * Whether the stream is appending to the file or truncating it. + */ + readonly append: boolean; + /** + * The type of data that can be written to the stream. Supported + * values are `'utf8'` or `'buffer'`. + * @default 'utf8' + */ + readonly contentMode: "utf8" | "buffer"; + /** + * Close the stream immediately, without flushing the internal buffer. + */ + destroy(): void; + /** + * Close the stream gracefully, flushing the internal buffer before closing. + */ + end(): void; + /** + * The file descriptor that is being written to. + */ + readonly fd: number; + /** + * The file that is being written to. + */ + readonly file: string; + /** + * Writes the current buffer to the file if a write was not in progress. Do + * nothing if `minLength` is zero or if it is already writing. + */ + flush(callback: (err: Error | null) => void): void; + /** + * Flushes the buffered data synchronously. This is a costly operation. + */ + flushSync(): void; + /** + * Whether the stream is performing a `fs.fsyncSync()` after every + * write operation. + */ + readonly fsync: boolean; + /** + * The maximum length of the internal buffer. If a write + * operation would cause the buffer to exceed `maxLength`, the data written is + * dropped and a drop event is emitted with the dropped data. + */ + readonly maxLength: number; + /** + * The minimum length of the internal buffer that is required to be + * full before flushing. + */ + readonly minLength: number; + /** + * Whether the stream should ensure that the directory for the + * `dest` file exists. If `true`, it will create the directory if it does not + * exist. + * @default false + */ + readonly mkdir: boolean; + /** + * The mode of the file that is being written to. + */ + readonly mode: number | string; + /** + * The number of milliseconds between flushes. If set to `0`, no + * periodic flushes will be performed. + */ + readonly periodicFlush: number; + /** + * Reopen the file in place, useful for log rotation. + * @param file A path to a file to be written to (mode + * controlled by the append option). + */ + reopen(file: PathLike): void; + /** + * Whether the stream is writing synchronously or asynchronously. + */ + readonly sync: boolean; + /** + * When the `options.contentMode` is set to `'utf8'` when the stream is created, + * the `data` argument must be a string. If the `contentMode` is set to `'buffer'`, + * the `data` argument must be a `Buffer`. + * @param data The data to write. + */ + write(data: string | Buffer): boolean; + /** + * Whether the stream is currently writing data to the file. + */ + readonly writing: boolean; + /** + * Calls `utf8Stream.destroy()`. + */ + [Symbol.dispose](): void; + } + interface Utf8Stream extends InternalEventEmitter<Utf8StreamEventMap> {} + interface WriteStreamEventMap extends stream.WritableEventMap { + "close": []; + "open": [fd: number]; + "ready": []; + } + /** + * Instances of `fs.WriteStream` are created and returned using the {@link createWriteStream} function. + * @since v0.1.93 + */ + class WriteStream extends stream.Writable { + /** + * Closes `writeStream`. Optionally accepts a + * callback that will be executed once the `writeStream`is closed. + * @since v0.9.4 + */ + close(callback?: (err?: NodeJS.ErrnoException | null) => void): void; + /** + * The number of bytes written so far. Does not include data that is still queued + * for writing. + * @since v0.4.7 + */ + bytesWritten: number; + /** + * The path to the file the stream is writing to as specified in the first + * argument to {@link createWriteStream}. If `path` is passed as a string, then`writeStream.path` will be a string. If `path` is passed as a `Buffer`, then`writeStream.path` will be a + * `Buffer`. + * @since v0.1.93 + */ + path: string | Buffer; + /** + * This property is `true` if the underlying file has not been opened yet, + * i.e. before the `'ready'` event is emitted. + * @since v11.2.0 + */ + pending: boolean; + // #region InternalEventEmitter + addListener<E extends keyof WriteStreamEventMap>( + eventName: E, + listener: (...args: WriteStreamEventMap[E]) => void, + ): this; + addListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + emit<E extends keyof WriteStreamEventMap>(eventName: E, ...args: WriteStreamEventMap[E]): boolean; + emit(eventName: string | symbol, ...args: any[]): boolean; + listenerCount<E extends keyof WriteStreamEventMap>( + eventName: E, + listener?: (...args: WriteStreamEventMap[E]) => void, + ): number; + listenerCount(eventName: string | symbol, listener?: (...args: any[]) => void): number; + listeners<E extends keyof WriteStreamEventMap>(eventName: E): ((...args: WriteStreamEventMap[E]) => void)[]; + listeners(eventName: string | symbol): ((...args: any[]) => void)[]; + off<E extends keyof WriteStreamEventMap>( + eventName: E, + listener: (...args: WriteStreamEventMap[E]) => void, + ): this; + off(eventName: string | symbol, listener: (...args: any[]) => void): this; + on<E extends keyof WriteStreamEventMap>( + eventName: E, + listener: (...args: WriteStreamEventMap[E]) => void, + ): this; + on(eventName: string | symbol, listener: (...args: any[]) => void): this; + once<E extends keyof WriteStreamEventMap>( + eventName: E, + listener: (...args: WriteStreamEventMap[E]) => void, + ): this; + once(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependListener<E extends keyof WriteStreamEventMap>( + eventName: E, + listener: (...args: WriteStreamEventMap[E]) => void, + ): this; + prependListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependOnceListener<E extends keyof WriteStreamEventMap>( + eventName: E, + listener: (...args: WriteStreamEventMap[E]) => void, + ): this; + prependOnceListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + rawListeners<E extends keyof WriteStreamEventMap>(eventName: E): ((...args: WriteStreamEventMap[E]) => void)[]; + rawListeners(eventName: string | symbol): ((...args: any[]) => void)[]; + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + removeAllListeners<E extends keyof WriteStreamEventMap>(eventName?: E): this; + removeAllListeners(eventName?: string | symbol): this; + removeListener<E extends keyof WriteStreamEventMap>( + eventName: E, + listener: (...args: WriteStreamEventMap[E]) => void, + ): this; + removeListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + // #endregion + } + /** + * Asynchronously rename file at `oldPath` to the pathname provided + * as `newPath`. In the case that `newPath` already exists, it will + * be overwritten. If there is a directory at `newPath`, an error will + * be raised instead. No arguments other than a possible exception are + * given to the completion callback. + * + * See also: [`rename(2)`](http://man7.org/linux/man-pages/man2/rename.2.html). + * + * ```js + * import { rename } from 'node:fs'; + * + * rename('oldFile.txt', 'newFile.txt', (err) => { + * if (err) throw err; + * console.log('Rename complete!'); + * }); + * ``` + * @since v0.0.2 + */ + function rename(oldPath: PathLike, newPath: PathLike, callback: NoParamCallback): void; + namespace rename { + /** + * Asynchronous rename(2) - Change the name or location of a file or directory. + * @param oldPath A path to a file. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + * @param newPath A path to a file. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + */ + function __promisify__(oldPath: PathLike, newPath: PathLike): Promise<void>; + } + /** + * Renames the file from `oldPath` to `newPath`. Returns `undefined`. + * + * See the POSIX [`rename(2)`](http://man7.org/linux/man-pages/man2/rename.2.html) documentation for more details. + * @since v0.1.21 + */ + function renameSync(oldPath: PathLike, newPath: PathLike): void; + /** + * Truncates the file. No arguments other than a possible exception are + * given to the completion callback. A file descriptor can also be passed as the + * first argument. In this case, `fs.ftruncate()` is called. + * + * ```js + * import { truncate } from 'node:fs'; + * // Assuming that 'path/file.txt' is a regular file. + * truncate('path/file.txt', (err) => { + * if (err) throw err; + * console.log('path/file.txt was truncated'); + * }); + * ``` + * + * Passing a file descriptor is deprecated and may result in an error being thrown + * in the future. + * + * See the POSIX [`truncate(2)`](http://man7.org/linux/man-pages/man2/truncate.2.html) documentation for more details. + * @since v0.8.6 + * @param [len=0] + */ + function truncate(path: PathLike, len: number | undefined, callback: NoParamCallback): void; + /** + * Asynchronous truncate(2) - Truncate a file to a specified length. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + function truncate(path: PathLike, callback: NoParamCallback): void; + namespace truncate { + /** + * Asynchronous truncate(2) - Truncate a file to a specified length. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param len If not specified, defaults to `0`. + */ + function __promisify__(path: PathLike, len?: number): Promise<void>; + } + /** + * Truncates the file. Returns `undefined`. A file descriptor can also be + * passed as the first argument. In this case, `fs.ftruncateSync()` is called. + * + * Passing a file descriptor is deprecated and may result in an error being thrown + * in the future. + * @since v0.8.6 + * @param [len=0] + */ + function truncateSync(path: PathLike, len?: number): void; + /** + * Truncates the file descriptor. No arguments other than a possible exception are + * given to the completion callback. + * + * See the POSIX [`ftruncate(2)`](http://man7.org/linux/man-pages/man2/ftruncate.2.html) documentation for more detail. + * + * If the file referred to by the file descriptor was larger than `len` bytes, only + * the first `len` bytes will be retained in the file. + * + * For example, the following program retains only the first four bytes of the + * file: + * + * ```js + * import { open, close, ftruncate } from 'node:fs'; + * + * function closeFd(fd) { + * close(fd, (err) => { + * if (err) throw err; + * }); + * } + * + * open('temp.txt', 'r+', (err, fd) => { + * if (err) throw err; + * + * try { + * ftruncate(fd, 4, (err) => { + * closeFd(fd); + * if (err) throw err; + * }); + * } catch (err) { + * closeFd(fd); + * if (err) throw err; + * } + * }); + * ``` + * + * If the file previously was shorter than `len` bytes, it is extended, and the + * extended part is filled with null bytes (`'\0'`): + * + * If `len` is negative then `0` will be used. + * @since v0.8.6 + * @param [len=0] + */ + function ftruncate(fd: number, len: number | undefined, callback: NoParamCallback): void; + /** + * Asynchronous ftruncate(2) - Truncate a file to a specified length. + * @param fd A file descriptor. + */ + function ftruncate(fd: number, callback: NoParamCallback): void; + namespace ftruncate { + /** + * Asynchronous ftruncate(2) - Truncate a file to a specified length. + * @param fd A file descriptor. + * @param len If not specified, defaults to `0`. + */ + function __promisify__(fd: number, len?: number): Promise<void>; + } + /** + * Truncates the file descriptor. Returns `undefined`. + * + * For detailed information, see the documentation of the asynchronous version of + * this API: {@link ftruncate}. + * @since v0.8.6 + * @param [len=0] + */ + function ftruncateSync(fd: number, len?: number): void; + /** + * Asynchronously changes owner and group of a file. No arguments other than a + * possible exception are given to the completion callback. + * + * See the POSIX [`chown(2)`](http://man7.org/linux/man-pages/man2/chown.2.html) documentation for more detail. + * @since v0.1.97 + */ + function chown(path: PathLike, uid: number, gid: number, callback: NoParamCallback): void; + namespace chown { + /** + * Asynchronous chown(2) - Change ownership of a file. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + function __promisify__(path: PathLike, uid: number, gid: number): Promise<void>; + } + /** + * Synchronously changes owner and group of a file. Returns `undefined`. + * This is the synchronous version of {@link chown}. + * + * See the POSIX [`chown(2)`](http://man7.org/linux/man-pages/man2/chown.2.html) documentation for more detail. + * @since v0.1.97 + */ + function chownSync(path: PathLike, uid: number, gid: number): void; + /** + * Sets the owner of the file. No arguments other than a possible exception are + * given to the completion callback. + * + * See the POSIX [`fchown(2)`](http://man7.org/linux/man-pages/man2/fchown.2.html) documentation for more detail. + * @since v0.4.7 + */ + function fchown(fd: number, uid: number, gid: number, callback: NoParamCallback): void; + namespace fchown { + /** + * Asynchronous fchown(2) - Change ownership of a file. + * @param fd A file descriptor. + */ + function __promisify__(fd: number, uid: number, gid: number): Promise<void>; + } + /** + * Sets the owner of the file. Returns `undefined`. + * + * See the POSIX [`fchown(2)`](http://man7.org/linux/man-pages/man2/fchown.2.html) documentation for more detail. + * @since v0.4.7 + * @param uid The file's new owner's user id. + * @param gid The file's new group's group id. + */ + function fchownSync(fd: number, uid: number, gid: number): void; + /** + * Set the owner of the symbolic link. No arguments other than a possible + * exception are given to the completion callback. + * + * See the POSIX [`lchown(2)`](http://man7.org/linux/man-pages/man2/lchown.2.html) documentation for more detail. + */ + function lchown(path: PathLike, uid: number, gid: number, callback: NoParamCallback): void; + namespace lchown { + /** + * Asynchronous lchown(2) - Change ownership of a file. Does not dereference symbolic links. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + function __promisify__(path: PathLike, uid: number, gid: number): Promise<void>; + } + /** + * Set the owner for the path. Returns `undefined`. + * + * See the POSIX [`lchown(2)`](http://man7.org/linux/man-pages/man2/lchown.2.html) documentation for more details. + * @param uid The file's new owner's user id. + * @param gid The file's new group's group id. + */ + function lchownSync(path: PathLike, uid: number, gid: number): void; + /** + * Changes the access and modification times of a file in the same way as {@link utimes}, with the difference that if the path refers to a symbolic + * link, then the link is not dereferenced: instead, the timestamps of the + * symbolic link itself are changed. + * + * No arguments other than a possible exception are given to the completion + * callback. + * @since v14.5.0, v12.19.0 + */ + function lutimes(path: PathLike, atime: TimeLike, mtime: TimeLike, callback: NoParamCallback): void; + namespace lutimes { + /** + * Changes the access and modification times of a file in the same way as `fsPromises.utimes()`, + * with the difference that if the path refers to a symbolic link, then the link is not + * dereferenced: instead, the timestamps of the symbolic link itself are changed. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param atime The last access time. If a string is provided, it will be coerced to number. + * @param mtime The last modified time. If a string is provided, it will be coerced to number. + */ + function __promisify__(path: PathLike, atime: TimeLike, mtime: TimeLike): Promise<void>; + } + /** + * Change the file system timestamps of the symbolic link referenced by `path`. + * Returns `undefined`, or throws an exception when parameters are incorrect or + * the operation fails. This is the synchronous version of {@link lutimes}. + * @since v14.5.0, v12.19.0 + */ + function lutimesSync(path: PathLike, atime: TimeLike, mtime: TimeLike): void; + /** + * Asynchronously changes the permissions of a file. No arguments other than a + * possible exception are given to the completion callback. + * + * See the POSIX [`chmod(2)`](http://man7.org/linux/man-pages/man2/chmod.2.html) documentation for more detail. + * + * ```js + * import { chmod } from 'node:fs'; + * + * chmod('my_file.txt', 0o775, (err) => { + * if (err) throw err; + * console.log('The permissions for file "my_file.txt" have been changed!'); + * }); + * ``` + * @since v0.1.30 + */ + function chmod(path: PathLike, mode: Mode, callback: NoParamCallback): void; + namespace chmod { + /** + * Asynchronous chmod(2) - Change permissions of a file. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param mode A file mode. If a string is passed, it is parsed as an octal integer. + */ + function __promisify__(path: PathLike, mode: Mode): Promise<void>; + } + /** + * For detailed information, see the documentation of the asynchronous version of + * this API: {@link chmod}. + * + * See the POSIX [`chmod(2)`](http://man7.org/linux/man-pages/man2/chmod.2.html) documentation for more detail. + * @since v0.6.7 + */ + function chmodSync(path: PathLike, mode: Mode): void; + /** + * Sets the permissions on the file. No arguments other than a possible exception + * are given to the completion callback. + * + * See the POSIX [`fchmod(2)`](http://man7.org/linux/man-pages/man2/fchmod.2.html) documentation for more detail. + * @since v0.4.7 + */ + function fchmod(fd: number, mode: Mode, callback: NoParamCallback): void; + namespace fchmod { + /** + * Asynchronous fchmod(2) - Change permissions of a file. + * @param fd A file descriptor. + * @param mode A file mode. If a string is passed, it is parsed as an octal integer. + */ + function __promisify__(fd: number, mode: Mode): Promise<void>; + } + /** + * Sets the permissions on the file. Returns `undefined`. + * + * See the POSIX [`fchmod(2)`](http://man7.org/linux/man-pages/man2/fchmod.2.html) documentation for more detail. + * @since v0.4.7 + */ + function fchmodSync(fd: number, mode: Mode): void; + /** + * Changes the permissions on a symbolic link. No arguments other than a possible + * exception are given to the completion callback. + * + * This method is only implemented on macOS. + * + * See the POSIX [`lchmod(2)`](https://www.freebsd.org/cgi/man.cgi?query=lchmod&sektion=2) documentation for more detail. + * @deprecated Since v0.4.7 + */ + function lchmod(path: PathLike, mode: Mode, callback: NoParamCallback): void; + /** @deprecated */ + namespace lchmod { + /** + * Asynchronous lchmod(2) - Change permissions of a file. Does not dereference symbolic links. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param mode A file mode. If a string is passed, it is parsed as an octal integer. + */ + function __promisify__(path: PathLike, mode: Mode): Promise<void>; + } + /** + * Changes the permissions on a symbolic link. Returns `undefined`. + * + * This method is only implemented on macOS. + * + * See the POSIX [`lchmod(2)`](https://www.freebsd.org/cgi/man.cgi?query=lchmod&sektion=2) documentation for more detail. + * @deprecated Since v0.4.7 + */ + function lchmodSync(path: PathLike, mode: Mode): void; + /** + * Asynchronous [`stat(2)`](http://man7.org/linux/man-pages/man2/stat.2.html). The callback gets two arguments `(err, stats)` where`stats` is an `fs.Stats` object. + * + * In case of an error, the `err.code` will be one of `Common System Errors`. + * + * {@link stat} follows symbolic links. Use {@link lstat} to look at the + * links themselves. + * + * Using `fs.stat()` to check for the existence of a file before calling`fs.open()`, `fs.readFile()`, or `fs.writeFile()` is not recommended. + * Instead, user code should open/read/write the file directly and handle the + * error raised if the file is not available. + * + * To check if a file exists without manipulating it afterwards, {@link access} is recommended. + * + * For example, given the following directory structure: + * + * ```text + * - txtDir + * -- file.txt + * - app.js + * ``` + * + * The next program will check for the stats of the given paths: + * + * ```js + * import { stat } from 'node:fs'; + * + * const pathsToCheck = ['./txtDir', './txtDir/file.txt']; + * + * for (let i = 0; i < pathsToCheck.length; i++) { + * stat(pathsToCheck[i], (err, stats) => { + * console.log(stats.isDirectory()); + * console.log(stats); + * }); + * } + * ``` + * + * The resulting output will resemble: + * + * ```console + * true + * Stats { + * dev: 16777220, + * mode: 16877, + * nlink: 3, + * uid: 501, + * gid: 20, + * rdev: 0, + * blksize: 4096, + * ino: 14214262, + * size: 96, + * blocks: 0, + * atimeMs: 1561174653071.963, + * mtimeMs: 1561174614583.3518, + * ctimeMs: 1561174626623.5366, + * birthtimeMs: 1561174126937.2893, + * atime: 2019-06-22T03:37:33.072Z, + * mtime: 2019-06-22T03:36:54.583Z, + * ctime: 2019-06-22T03:37:06.624Z, + * birthtime: 2019-06-22T03:28:46.937Z + * } + * false + * Stats { + * dev: 16777220, + * mode: 33188, + * nlink: 1, + * uid: 501, + * gid: 20, + * rdev: 0, + * blksize: 4096, + * ino: 14214074, + * size: 8, + * blocks: 8, + * atimeMs: 1561174616618.8555, + * mtimeMs: 1561174614584, + * ctimeMs: 1561174614583.8145, + * birthtimeMs: 1561174007710.7478, + * atime: 2019-06-22T03:36:56.619Z, + * mtime: 2019-06-22T03:36:54.584Z, + * ctime: 2019-06-22T03:36:54.584Z, + * birthtime: 2019-06-22T03:26:47.711Z + * } + * ``` + * @since v0.0.2 + */ + function stat(path: PathLike, callback: (err: NodeJS.ErrnoException | null, stats: Stats) => void): void; + function stat( + path: PathLike, + options: + | (StatOptions & { + bigint?: false | undefined; + }) + | undefined, + callback: (err: NodeJS.ErrnoException | null, stats: Stats) => void, + ): void; + function stat( + path: PathLike, + options: StatOptions & { + bigint: true; + }, + callback: (err: NodeJS.ErrnoException | null, stats: BigIntStats) => void, + ): void; + function stat( + path: PathLike, + options: StatOptions | undefined, + callback: (err: NodeJS.ErrnoException | null, stats: Stats | BigIntStats) => void, + ): void; + namespace stat { + /** + * Asynchronous stat(2) - Get file status. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + function __promisify__( + path: PathLike, + options?: StatOptions & { + bigint?: false | undefined; + }, + ): Promise<Stats>; + function __promisify__( + path: PathLike, + options: StatOptions & { + bigint: true; + }, + ): Promise<BigIntStats>; + function __promisify__(path: PathLike, options?: StatOptions): Promise<Stats | BigIntStats>; + } + interface StatSyncFn extends Function { + (path: PathLike, options?: undefined): Stats; + ( + path: PathLike, + options?: StatSyncOptions & { + bigint?: false | undefined; + throwIfNoEntry: false; + }, + ): Stats | undefined; + ( + path: PathLike, + options: StatSyncOptions & { + bigint: true; + throwIfNoEntry: false; + }, + ): BigIntStats | undefined; + ( + path: PathLike, + options?: StatSyncOptions & { + bigint?: false | undefined; + }, + ): Stats; + ( + path: PathLike, + options: StatSyncOptions & { + bigint: true; + }, + ): BigIntStats; + ( + path: PathLike, + options: StatSyncOptions & { + bigint: boolean; + throwIfNoEntry?: false | undefined; + }, + ): Stats | BigIntStats; + (path: PathLike, options?: StatSyncOptions): Stats | BigIntStats | undefined; + } + /** + * Synchronous stat(2) - Get file status. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + const statSync: StatSyncFn; + /** + * Invokes the callback with the `fs.Stats` for the file descriptor. + * + * See the POSIX [`fstat(2)`](http://man7.org/linux/man-pages/man2/fstat.2.html) documentation for more detail. + * @since v0.1.95 + */ + function fstat(fd: number, callback: (err: NodeJS.ErrnoException | null, stats: Stats) => void): void; + function fstat( + fd: number, + options: + | (StatOptions & { + bigint?: false | undefined; + }) + | undefined, + callback: (err: NodeJS.ErrnoException | null, stats: Stats) => void, + ): void; + function fstat( + fd: number, + options: StatOptions & { + bigint: true; + }, + callback: (err: NodeJS.ErrnoException | null, stats: BigIntStats) => void, + ): void; + function fstat( + fd: number, + options: StatOptions | undefined, + callback: (err: NodeJS.ErrnoException | null, stats: Stats | BigIntStats) => void, + ): void; + namespace fstat { + /** + * Asynchronous fstat(2) - Get file status. + * @param fd A file descriptor. + */ + function __promisify__( + fd: number, + options?: StatOptions & { + bigint?: false | undefined; + }, + ): Promise<Stats>; + function __promisify__( + fd: number, + options: StatOptions & { + bigint: true; + }, + ): Promise<BigIntStats>; + function __promisify__(fd: number, options?: StatOptions): Promise<Stats | BigIntStats>; + } + /** + * Retrieves the `fs.Stats` for the file descriptor. + * + * See the POSIX [`fstat(2)`](http://man7.org/linux/man-pages/man2/fstat.2.html) documentation for more detail. + * @since v0.1.95 + */ + function fstatSync( + fd: number, + options?: StatOptions & { + bigint?: false | undefined; + }, + ): Stats; + function fstatSync( + fd: number, + options: StatOptions & { + bigint: true; + }, + ): BigIntStats; + function fstatSync(fd: number, options?: StatOptions): Stats | BigIntStats; + /** + * Retrieves the `fs.Stats` for the symbolic link referred to by the path. + * The callback gets two arguments `(err, stats)` where `stats` is a `fs.Stats` object. `lstat()` is identical to `stat()`, except that if `path` is a symbolic + * link, then the link itself is stat-ed, not the file that it refers to. + * + * See the POSIX [`lstat(2)`](http://man7.org/linux/man-pages/man2/lstat.2.html) documentation for more details. + * @since v0.1.30 + */ + function lstat(path: PathLike, callback: (err: NodeJS.ErrnoException | null, stats: Stats) => void): void; + function lstat( + path: PathLike, + options: + | (StatOptions & { + bigint?: false | undefined; + }) + | undefined, + callback: (err: NodeJS.ErrnoException | null, stats: Stats) => void, + ): void; + function lstat( + path: PathLike, + options: StatOptions & { + bigint: true; + }, + callback: (err: NodeJS.ErrnoException | null, stats: BigIntStats) => void, + ): void; + function lstat( + path: PathLike, + options: StatOptions | undefined, + callback: (err: NodeJS.ErrnoException | null, stats: Stats | BigIntStats) => void, + ): void; + namespace lstat { + /** + * Asynchronous lstat(2) - Get file status. Does not dereference symbolic links. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + function __promisify__( + path: PathLike, + options?: StatOptions & { + bigint?: false | undefined; + }, + ): Promise<Stats>; + function __promisify__( + path: PathLike, + options: StatOptions & { + bigint: true; + }, + ): Promise<BigIntStats>; + function __promisify__(path: PathLike, options?: StatOptions): Promise<Stats | BigIntStats>; + } + /** + * Asynchronous [`statfs(2)`](http://man7.org/linux/man-pages/man2/statfs.2.html). Returns information about the mounted file system which + * contains `path`. The callback gets two arguments `(err, stats)` where `stats`is an `fs.StatFs` object. + * + * In case of an error, the `err.code` will be one of `Common System Errors`. + * @since v19.6.0, v18.15.0 + * @param path A path to an existing file or directory on the file system to be queried. + */ + function statfs(path: PathLike, callback: (err: NodeJS.ErrnoException | null, stats: StatsFs) => void): void; + function statfs( + path: PathLike, + options: + | (StatFsOptions & { + bigint?: false | undefined; + }) + | undefined, + callback: (err: NodeJS.ErrnoException | null, stats: StatsFs) => void, + ): void; + function statfs( + path: PathLike, + options: StatFsOptions & { + bigint: true; + }, + callback: (err: NodeJS.ErrnoException | null, stats: BigIntStatsFs) => void, + ): void; + function statfs( + path: PathLike, + options: StatFsOptions | undefined, + callback: (err: NodeJS.ErrnoException | null, stats: StatsFs | BigIntStatsFs) => void, + ): void; + namespace statfs { + /** + * Asynchronous statfs(2) - Returns information about the mounted file system which contains path. The callback gets two arguments (err, stats) where stats is an <fs.StatFs> object. + * @param path A path to an existing file or directory on the file system to be queried. + */ + function __promisify__( + path: PathLike, + options?: StatFsOptions & { + bigint?: false | undefined; + }, + ): Promise<StatsFs>; + function __promisify__( + path: PathLike, + options: StatFsOptions & { + bigint: true; + }, + ): Promise<BigIntStatsFs>; + function __promisify__(path: PathLike, options?: StatFsOptions): Promise<StatsFs | BigIntStatsFs>; + } + /** + * Synchronous [`statfs(2)`](http://man7.org/linux/man-pages/man2/statfs.2.html). Returns information about the mounted file system which + * contains `path`. + * + * In case of an error, the `err.code` will be one of `Common System Errors`. + * @since v19.6.0, v18.15.0 + * @param path A path to an existing file or directory on the file system to be queried. + */ + function statfsSync( + path: PathLike, + options?: StatFsOptions & { + bigint?: false | undefined; + }, + ): StatsFs; + function statfsSync( + path: PathLike, + options: StatFsOptions & { + bigint: true; + }, + ): BigIntStatsFs; + function statfsSync(path: PathLike, options?: StatFsOptions): StatsFs | BigIntStatsFs; + /** + * Synchronous lstat(2) - Get file status. Does not dereference symbolic links. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + const lstatSync: StatSyncFn; + /** + * Creates a new link from the `existingPath` to the `newPath`. See the POSIX [`link(2)`](http://man7.org/linux/man-pages/man2/link.2.html) documentation for more detail. No arguments other than + * a possible + * exception are given to the completion callback. + * @since v0.1.31 + */ + function link(existingPath: PathLike, newPath: PathLike, callback: NoParamCallback): void; + namespace link { + /** + * Asynchronous link(2) - Create a new link (also known as a hard link) to an existing file. + * @param existingPath A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param newPath A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + function __promisify__(existingPath: PathLike, newPath: PathLike): Promise<void>; + } + /** + * Creates a new link from the `existingPath` to the `newPath`. See the POSIX [`link(2)`](http://man7.org/linux/man-pages/man2/link.2.html) documentation for more detail. Returns `undefined`. + * @since v0.1.31 + */ + function linkSync(existingPath: PathLike, newPath: PathLike): void; + /** + * Creates the link called `path` pointing to `target`. No arguments other than a + * possible exception are given to the completion callback. + * + * See the POSIX [`symlink(2)`](http://man7.org/linux/man-pages/man2/symlink.2.html) documentation for more details. + * + * The `type` argument is only available on Windows and ignored on other platforms. + * It can be set to `'dir'`, `'file'`, or `'junction'`. If the `type` argument is + * not a string, Node.js will autodetect `target` type and use `'file'` or `'dir'`. + * If the `target` does not exist, `'file'` will be used. Windows junction points + * require the destination path to be absolute. When using `'junction'`, the`target` argument will automatically be normalized to absolute path. Junction + * points on NTFS volumes can only point to directories. + * + * Relative targets are relative to the link's parent directory. + * + * ```js + * import { symlink } from 'node:fs'; + * + * symlink('./mew', './mewtwo', callback); + * ``` + * + * The above example creates a symbolic link `mewtwo` which points to `mew` in the + * same directory: + * + * ```bash + * $ tree . + * . + * ├── mew + * └── mewtwo -> ./mew + * ``` + * @since v0.1.31 + * @param [type='null'] + */ + function symlink( + target: PathLike, + path: PathLike, + type: symlink.Type | undefined | null, + callback: NoParamCallback, + ): void; + /** + * Asynchronous symlink(2) - Create a new symbolic link to an existing file. + * @param target A path to an existing file. If a URL is provided, it must use the `file:` protocol. + * @param path A path to the new symlink. If a URL is provided, it must use the `file:` protocol. + */ + function symlink(target: PathLike, path: PathLike, callback: NoParamCallback): void; + namespace symlink { + /** + * Asynchronous symlink(2) - Create a new symbolic link to an existing file. + * @param target A path to an existing file. If a URL is provided, it must use the `file:` protocol. + * @param path A path to the new symlink. If a URL is provided, it must use the `file:` protocol. + * @param type May be set to `'dir'`, `'file'`, or `'junction'` (default is `'file'`) and is only available on Windows (ignored on other platforms). + * When using `'junction'`, the `target` argument will automatically be normalized to an absolute path. + */ + function __promisify__(target: PathLike, path: PathLike, type?: string | null): Promise<void>; + type Type = "dir" | "file" | "junction"; + } + /** + * Returns `undefined`. + * + * For detailed information, see the documentation of the asynchronous version of + * this API: {@link symlink}. + * @since v0.1.31 + * @param [type='null'] + */ + function symlinkSync(target: PathLike, path: PathLike, type?: symlink.Type | null): void; + /** + * Reads the contents of the symbolic link referred to by `path`. The callback gets + * two arguments `(err, linkString)`. + * + * See the POSIX [`readlink(2)`](http://man7.org/linux/man-pages/man2/readlink.2.html) documentation for more details. + * + * The optional `options` argument can be a string specifying an encoding, or an + * object with an `encoding` property specifying the character encoding to use for + * the link path passed to the callback. If the `encoding` is set to `'buffer'`, + * the link path returned will be passed as a `Buffer` object. + * @since v0.1.31 + */ + function readlink( + path: PathLike, + options: EncodingOption, + callback: (err: NodeJS.ErrnoException | null, linkString: string) => void, + ): void; + /** + * Asynchronous readlink(2) - read value of a symbolic link. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function readlink( + path: PathLike, + options: BufferEncodingOption, + callback: (err: NodeJS.ErrnoException | null, linkString: NonSharedBuffer) => void, + ): void; + /** + * Asynchronous readlink(2) - read value of a symbolic link. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function readlink( + path: PathLike, + options: EncodingOption, + callback: (err: NodeJS.ErrnoException | null, linkString: string | NonSharedBuffer) => void, + ): void; + /** + * Asynchronous readlink(2) - read value of a symbolic link. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + function readlink( + path: PathLike, + callback: (err: NodeJS.ErrnoException | null, linkString: string) => void, + ): void; + namespace readlink { + /** + * Asynchronous readlink(2) - read value of a symbolic link. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function __promisify__(path: PathLike, options?: EncodingOption): Promise<string>; + /** + * Asynchronous readlink(2) - read value of a symbolic link. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function __promisify__(path: PathLike, options: BufferEncodingOption): Promise<NonSharedBuffer>; + /** + * Asynchronous readlink(2) - read value of a symbolic link. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function __promisify__(path: PathLike, options?: EncodingOption): Promise<string | NonSharedBuffer>; + } + /** + * Returns the symbolic link's string value. + * + * See the POSIX [`readlink(2)`](http://man7.org/linux/man-pages/man2/readlink.2.html) documentation for more details. + * + * The optional `options` argument can be a string specifying an encoding, or an + * object with an `encoding` property specifying the character encoding to use for + * the link path returned. If the `encoding` is set to `'buffer'`, + * the link path returned will be passed as a `Buffer` object. + * @since v0.1.31 + */ + function readlinkSync(path: PathLike, options?: EncodingOption): string; + /** + * Synchronous readlink(2) - read value of a symbolic link. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function readlinkSync(path: PathLike, options: BufferEncodingOption): NonSharedBuffer; + /** + * Synchronous readlink(2) - read value of a symbolic link. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function readlinkSync(path: PathLike, options?: EncodingOption): string | NonSharedBuffer; + /** + * Asynchronously computes the canonical pathname by resolving `.`, `..`, and + * symbolic links. + * + * A canonical pathname is not necessarily unique. Hard links and bind mounts can + * expose a file system entity through many pathnames. + * + * This function behaves like [`realpath(3)`](http://man7.org/linux/man-pages/man3/realpath.3.html), with some exceptions: + * + * 1. No case conversion is performed on case-insensitive file systems. + * 2. The maximum number of symbolic links is platform-independent and generally + * (much) higher than what the native [`realpath(3)`](http://man7.org/linux/man-pages/man3/realpath.3.html) implementation supports. + * + * The `callback` gets two arguments `(err, resolvedPath)`. May use `process.cwd` to resolve relative paths. + * + * Only paths that can be converted to UTF8 strings are supported. + * + * The optional `options` argument can be a string specifying an encoding, or an + * object with an `encoding` property specifying the character encoding to use for + * the path passed to the callback. If the `encoding` is set to `'buffer'`, + * the path returned will be passed as a `Buffer` object. + * + * If `path` resolves to a socket or a pipe, the function will return a system + * dependent name for that object. + * @since v0.1.31 + */ + function realpath( + path: PathLike, + options: EncodingOption, + callback: (err: NodeJS.ErrnoException | null, resolvedPath: string) => void, + ): void; + /** + * Asynchronous realpath(3) - return the canonicalized absolute pathname. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function realpath( + path: PathLike, + options: BufferEncodingOption, + callback: (err: NodeJS.ErrnoException | null, resolvedPath: NonSharedBuffer) => void, + ): void; + /** + * Asynchronous realpath(3) - return the canonicalized absolute pathname. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function realpath( + path: PathLike, + options: EncodingOption, + callback: (err: NodeJS.ErrnoException | null, resolvedPath: string | NonSharedBuffer) => void, + ): void; + /** + * Asynchronous realpath(3) - return the canonicalized absolute pathname. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + function realpath( + path: PathLike, + callback: (err: NodeJS.ErrnoException | null, resolvedPath: string) => void, + ): void; + namespace realpath { + /** + * Asynchronous realpath(3) - return the canonicalized absolute pathname. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function __promisify__(path: PathLike, options?: EncodingOption): Promise<string>; + /** + * Asynchronous realpath(3) - return the canonicalized absolute pathname. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function __promisify__(path: PathLike, options: BufferEncodingOption): Promise<NonSharedBuffer>; + /** + * Asynchronous realpath(3) - return the canonicalized absolute pathname. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function __promisify__(path: PathLike, options?: EncodingOption): Promise<string | NonSharedBuffer>; + /** + * Asynchronous [`realpath(3)`](http://man7.org/linux/man-pages/man3/realpath.3.html). + * + * The `callback` gets two arguments `(err, resolvedPath)`. + * + * Only paths that can be converted to UTF8 strings are supported. + * + * The optional `options` argument can be a string specifying an encoding, or an + * object with an `encoding` property specifying the character encoding to use for + * the path passed to the callback. If the `encoding` is set to `'buffer'`, + * the path returned will be passed as a `Buffer` object. + * + * On Linux, when Node.js is linked against musl libc, the procfs file system must + * be mounted on `/proc` in order for this function to work. Glibc does not have + * this restriction. + * @since v9.2.0 + */ + function native( + path: PathLike, + options: EncodingOption, + callback: (err: NodeJS.ErrnoException | null, resolvedPath: string) => void, + ): void; + function native( + path: PathLike, + options: BufferEncodingOption, + callback: (err: NodeJS.ErrnoException | null, resolvedPath: NonSharedBuffer) => void, + ): void; + function native( + path: PathLike, + options: EncodingOption, + callback: (err: NodeJS.ErrnoException | null, resolvedPath: string | NonSharedBuffer) => void, + ): void; + function native( + path: PathLike, + callback: (err: NodeJS.ErrnoException | null, resolvedPath: string) => void, + ): void; + } + /** + * Returns the resolved pathname. + * + * For detailed information, see the documentation of the asynchronous version of + * this API: {@link realpath}. + * @since v0.1.31 + */ + function realpathSync(path: PathLike, options?: EncodingOption): string; + /** + * Synchronous realpath(3) - return the canonicalized absolute pathname. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function realpathSync(path: PathLike, options: BufferEncodingOption): NonSharedBuffer; + /** + * Synchronous realpath(3) - return the canonicalized absolute pathname. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function realpathSync(path: PathLike, options?: EncodingOption): string | NonSharedBuffer; + namespace realpathSync { + function native(path: PathLike, options?: EncodingOption): string; + function native(path: PathLike, options: BufferEncodingOption): NonSharedBuffer; + function native(path: PathLike, options?: EncodingOption): string | NonSharedBuffer; + } + /** + * Asynchronously removes a file or symbolic link. No arguments other than a + * possible exception are given to the completion callback. + * + * ```js + * import { unlink } from 'node:fs'; + * // Assuming that 'path/file.txt' is a regular file. + * unlink('path/file.txt', (err) => { + * if (err) throw err; + * console.log('path/file.txt was deleted'); + * }); + * ``` + * + * `fs.unlink()` will not work on a directory, empty or otherwise. To remove a + * directory, use {@link rmdir}. + * + * See the POSIX [`unlink(2)`](http://man7.org/linux/man-pages/man2/unlink.2.html) documentation for more details. + * @since v0.0.2 + */ + function unlink(path: PathLike, callback: NoParamCallback): void; + namespace unlink { + /** + * Asynchronous unlink(2) - delete a name and possibly the file it refers to. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + function __promisify__(path: PathLike): Promise<void>; + } + /** + * Synchronous [`unlink(2)`](http://man7.org/linux/man-pages/man2/unlink.2.html). Returns `undefined`. + * @since v0.1.21 + */ + function unlinkSync(path: PathLike): void; + /** @deprecated `rmdir()` no longer provides any options. This interface will be removed in a future version. */ + // TODO: remove in future major + interface RmDirOptions {} + /** + * Asynchronous [`rmdir(2)`](http://man7.org/linux/man-pages/man2/rmdir.2.html). No arguments other than a possible exception are given + * to the completion callback. + * + * Using `fs.rmdir()` on a file (not a directory) results in an `ENOENT` error on + * Windows and an `ENOTDIR` error on POSIX. + * + * To get a behavior similar to the `rm -rf` Unix command, use {@link rm} with options `{ recursive: true, force: true }`. + * @since v0.0.2 + */ + function rmdir(path: PathLike, callback: NoParamCallback): void; + namespace rmdir { + /** + * Asynchronous rmdir(2) - delete a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + function __promisify__(path: PathLike): Promise<void>; + } + /** + * Synchronous [`rmdir(2)`](http://man7.org/linux/man-pages/man2/rmdir.2.html). Returns `undefined`. + * + * Using `fs.rmdirSync()` on a file (not a directory) results in an `ENOENT` error + * on Windows and an `ENOTDIR` error on POSIX. + * + * To get a behavior similar to the `rm -rf` Unix command, use {@link rmSync} with options `{ recursive: true, force: true }`. + * @since v0.1.21 + */ + function rmdirSync(path: PathLike): void; + interface RmOptions { + /** + * When `true`, exceptions will be ignored if `path` does not exist. + * @default false + */ + force?: boolean | undefined; + /** + * If an `EBUSY`, `EMFILE`, `ENFILE`, `ENOTEMPTY`, or + * `EPERM` error is encountered, Node.js will retry the operation with a linear + * backoff wait of `retryDelay` ms longer on each try. This option represents the + * number of retries. This option is ignored if the `recursive` option is not + * `true`. + * @default 0 + */ + maxRetries?: number | undefined; + /** + * If `true`, perform a recursive directory removal. In + * recursive mode, operations are retried on failure. + * @default false + */ + recursive?: boolean | undefined; + /** + * The amount of time in milliseconds to wait between retries. + * This option is ignored if the `recursive` option is not `true`. + * @default 100 + */ + retryDelay?: number | undefined; + } + /** + * Asynchronously removes files and directories (modeled on the standard POSIX `rm` utility). No arguments other than a possible exception are given to the + * completion callback. + * @since v14.14.0 + */ + function rm(path: PathLike, callback: NoParamCallback): void; + function rm(path: PathLike, options: RmOptions, callback: NoParamCallback): void; + namespace rm { + /** + * Asynchronously removes files and directories (modeled on the standard POSIX `rm` utility). + */ + function __promisify__(path: PathLike, options?: RmOptions): Promise<void>; + } + /** + * Synchronously removes files and directories (modeled on the standard POSIX `rm` utility). Returns `undefined`. + * @since v14.14.0 + */ + function rmSync(path: PathLike, options?: RmOptions): void; + interface MakeDirectoryOptions { + /** + * Indicates whether parent folders should be created. + * If a folder was created, the path to the first created folder will be returned. + * @default false + */ + recursive?: boolean | undefined; + /** + * A file mode. If a string is passed, it is parsed as an octal integer. If not specified + * @default 0o777 + */ + mode?: Mode | undefined; + } + /** + * Asynchronously creates a directory. + * + * The callback is given a possible exception and, if `recursive` is `true`, the + * first directory path created, `(err[, path])`.`path` can still be `undefined` when `recursive` is `true`, if no directory was + * created (for instance, if it was previously created). + * + * The optional `options` argument can be an integer specifying `mode` (permission + * and sticky bits), or an object with a `mode` property and a `recursive` property indicating whether parent directories should be created. Calling `fs.mkdir()` when `path` is a directory that + * exists results in an error only + * when `recursive` is false. If `recursive` is false and the directory exists, + * an `EEXIST` error occurs. + * + * ```js + * import { mkdir } from 'node:fs'; + * + * // Create ./tmp/a/apple, regardless of whether ./tmp and ./tmp/a exist. + * mkdir('./tmp/a/apple', { recursive: true }, (err) => { + * if (err) throw err; + * }); + * ``` + * + * On Windows, using `fs.mkdir()` on the root directory even with recursion will + * result in an error: + * + * ```js + * import { mkdir } from 'node:fs'; + * + * mkdir('/', { recursive: true }, (err) => { + * // => [Error: EPERM: operation not permitted, mkdir 'C:\'] + * }); + * ``` + * + * See the POSIX [`mkdir(2)`](http://man7.org/linux/man-pages/man2/mkdir.2.html) documentation for more details. + * @since v0.1.8 + */ + function mkdir( + path: PathLike, + options: MakeDirectoryOptions & { + recursive: true; + }, + callback: (err: NodeJS.ErrnoException | null, path?: string) => void, + ): void; + /** + * Asynchronous mkdir(2) - create a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders + * should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`. + */ + function mkdir( + path: PathLike, + options: + | Mode + | (MakeDirectoryOptions & { + recursive?: false | undefined; + }) + | null + | undefined, + callback: NoParamCallback, + ): void; + /** + * Asynchronous mkdir(2) - create a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders + * should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`. + */ + function mkdir( + path: PathLike, + options: Mode | MakeDirectoryOptions | null | undefined, + callback: (err: NodeJS.ErrnoException | null, path?: string) => void, + ): void; + /** + * Asynchronous mkdir(2) - create a directory with a mode of `0o777`. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + function mkdir(path: PathLike, callback: NoParamCallback): void; + namespace mkdir { + /** + * Asynchronous mkdir(2) - create a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders + * should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`. + */ + function __promisify__( + path: PathLike, + options: MakeDirectoryOptions & { + recursive: true; + }, + ): Promise<string | undefined>; + /** + * Asynchronous mkdir(2) - create a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders + * should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`. + */ + function __promisify__( + path: PathLike, + options?: + | Mode + | (MakeDirectoryOptions & { + recursive?: false | undefined; + }) + | null, + ): Promise<void>; + /** + * Asynchronous mkdir(2) - create a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders + * should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`. + */ + function __promisify__( + path: PathLike, + options?: Mode | MakeDirectoryOptions | null, + ): Promise<string | undefined>; + } + /** + * Synchronously creates a directory. Returns `undefined`, or if `recursive` is `true`, the first directory path created. + * This is the synchronous version of {@link mkdir}. + * + * See the POSIX [`mkdir(2)`](http://man7.org/linux/man-pages/man2/mkdir.2.html) documentation for more details. + * @since v0.1.21 + */ + function mkdirSync( + path: PathLike, + options: MakeDirectoryOptions & { + recursive: true; + }, + ): string | undefined; + /** + * Synchronous mkdir(2) - create a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders + * should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`. + */ + function mkdirSync( + path: PathLike, + options?: + | Mode + | (MakeDirectoryOptions & { + recursive?: false | undefined; + }) + | null, + ): void; + /** + * Synchronous mkdir(2) - create a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders + * should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`. + */ + function mkdirSync(path: PathLike, options?: Mode | MakeDirectoryOptions | null): string | undefined; + /** + * Creates a unique temporary directory. + * + * Generates six random characters to be appended behind a required `prefix` to create a unique temporary directory. Due to platform + * inconsistencies, avoid trailing `X` characters in `prefix`. Some platforms, + * notably the BSDs, can return more than six random characters, and replace + * trailing `X` characters in `prefix` with random characters. + * + * The created directory path is passed as a string to the callback's second + * parameter. + * + * The optional `options` argument can be a string specifying an encoding, or an + * object with an `encoding` property specifying the character encoding to use. + * + * ```js + * import { mkdtemp } from 'node:fs'; + * import { join } from 'node:path'; + * import { tmpdir } from 'node:os'; + * + * mkdtemp(join(tmpdir(), 'foo-'), (err, directory) => { + * if (err) throw err; + * console.log(directory); + * // Prints: /tmp/foo-itXde2 or C:\Users\...\AppData\Local\Temp\foo-itXde2 + * }); + * ``` + * + * The `fs.mkdtemp()` method will append the six randomly selected characters + * directly to the `prefix` string. For instance, given a directory `/tmp`, if the + * intention is to create a temporary directory _within_`/tmp`, the `prefix`must end with a trailing platform-specific path separator + * (`import { sep } from 'node:path'`). + * + * ```js + * import { tmpdir } from 'node:os'; + * import { mkdtemp } from 'node:fs'; + * + * // The parent directory for the new temporary directory + * const tmpDir = tmpdir(); + * + * // This method is *INCORRECT*: + * mkdtemp(tmpDir, (err, directory) => { + * if (err) throw err; + * console.log(directory); + * // Will print something similar to `/tmpabc123`. + * // A new temporary directory is created at the file system root + * // rather than *within* the /tmp directory. + * }); + * + * // This method is *CORRECT*: + * import { sep } from 'node:path'; + * mkdtemp(`${tmpDir}${sep}`, (err, directory) => { + * if (err) throw err; + * console.log(directory); + * // Will print something similar to `/tmp/abc123`. + * // A new temporary directory is created within + * // the /tmp directory. + * }); + * ``` + * @since v5.10.0 + */ + function mkdtemp( + prefix: string, + options: EncodingOption, + callback: (err: NodeJS.ErrnoException | null, folder: string) => void, + ): void; + /** + * Asynchronously creates a unique temporary directory. + * Generates six random characters to be appended behind a required prefix to create a unique temporary directory. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function mkdtemp( + prefix: string, + options: BufferEncodingOption, + callback: (err: NodeJS.ErrnoException | null, folder: NonSharedBuffer) => void, + ): void; + /** + * Asynchronously creates a unique temporary directory. + * Generates six random characters to be appended behind a required prefix to create a unique temporary directory. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function mkdtemp( + prefix: string, + options: EncodingOption, + callback: (err: NodeJS.ErrnoException | null, folder: string | NonSharedBuffer) => void, + ): void; + /** + * Asynchronously creates a unique temporary directory. + * Generates six random characters to be appended behind a required prefix to create a unique temporary directory. + */ + function mkdtemp( + prefix: string, + callback: (err: NodeJS.ErrnoException | null, folder: string) => void, + ): void; + namespace mkdtemp { + /** + * Asynchronously creates a unique temporary directory. + * Generates six random characters to be appended behind a required prefix to create a unique temporary directory. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function __promisify__(prefix: string, options?: EncodingOption): Promise<string>; + /** + * Asynchronously creates a unique temporary directory. + * Generates six random characters to be appended behind a required prefix to create a unique temporary directory. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function __promisify__(prefix: string, options: BufferEncodingOption): Promise<NonSharedBuffer>; + /** + * Asynchronously creates a unique temporary directory. + * Generates six random characters to be appended behind a required prefix to create a unique temporary directory. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function __promisify__(prefix: string, options?: EncodingOption): Promise<string | NonSharedBuffer>; + } + /** + * Returns the created directory path. + * + * For detailed information, see the documentation of the asynchronous version of + * this API: {@link mkdtemp}. + * + * The optional `options` argument can be a string specifying an encoding, or an + * object with an `encoding` property specifying the character encoding to use. + * @since v5.10.0 + */ + function mkdtempSync(prefix: string, options?: EncodingOption): string; + /** + * Synchronously creates a unique temporary directory. + * Generates six random characters to be appended behind a required prefix to create a unique temporary directory. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function mkdtempSync(prefix: string, options: BufferEncodingOption): NonSharedBuffer; + /** + * Synchronously creates a unique temporary directory. + * Generates six random characters to be appended behind a required prefix to create a unique temporary directory. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function mkdtempSync(prefix: string, options?: EncodingOption): string | NonSharedBuffer; + interface DisposableTempDir extends Disposable { + /** + * The path of the created directory. + */ + path: string; + /** + * A function which removes the created directory. + */ + remove(): void; + /** + * The same as `remove`. + */ + [Symbol.dispose](): void; + } + /** + * Returns a disposable object whose `path` property holds the created directory + * path. When the object is disposed, the directory and its contents will be + * removed if it still exists. If the directory cannot be deleted, disposal will + * throw an error. The object has a `remove()` method which will perform the same + * task. + * + * <!-- TODO: link MDN docs for disposables once https://github.com/mdn/content/pull/38027 lands --> + * + * For detailed information, see the documentation of `fs.mkdtemp()`. + * + * There is no callback-based version of this API because it is designed for use + * with the `using` syntax. + * + * The optional `options` argument can be a string specifying an encoding, or an + * object with an `encoding` property specifying the character encoding to use. + * @since v24.4.0 + */ + function mkdtempDisposableSync(prefix: string, options?: EncodingOption): DisposableTempDir; + /** + * Reads the contents of a directory. The callback gets two arguments `(err, files)` where `files` is an array of the names of the files in the directory excluding `'.'` and `'..'`. + * + * See the POSIX [`readdir(3)`](http://man7.org/linux/man-pages/man3/readdir.3.html) documentation for more details. + * + * The optional `options` argument can be a string specifying an encoding, or an + * object with an `encoding` property specifying the character encoding to use for + * the filenames passed to the callback. If the `encoding` is set to `'buffer'`, + * the filenames returned will be passed as `Buffer` objects. + * + * If `options.withFileTypes` is set to `true`, the `files` array will contain `fs.Dirent` objects. + * @since v0.1.8 + */ + function readdir( + path: PathLike, + options: + | { + encoding: BufferEncoding | null; + withFileTypes?: false | undefined; + recursive?: boolean | undefined; + } + | BufferEncoding + | undefined + | null, + callback: (err: NodeJS.ErrnoException | null, files: string[]) => void, + ): void; + /** + * Asynchronous readdir(3) - read a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function readdir( + path: PathLike, + options: + | { + encoding: "buffer"; + withFileTypes?: false | undefined; + recursive?: boolean | undefined; + } + | "buffer", + callback: (err: NodeJS.ErrnoException | null, files: NonSharedBuffer[]) => void, + ): void; + /** + * Asynchronous readdir(3) - read a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function readdir( + path: PathLike, + options: + | (ObjectEncodingOptions & { + withFileTypes?: false | undefined; + recursive?: boolean | undefined; + }) + | BufferEncoding + | undefined + | null, + callback: (err: NodeJS.ErrnoException | null, files: string[] | NonSharedBuffer[]) => void, + ): void; + /** + * Asynchronous readdir(3) - read a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + function readdir( + path: PathLike, + callback: (err: NodeJS.ErrnoException | null, files: string[]) => void, + ): void; + /** + * Asynchronous readdir(3) - read a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options If called with `withFileTypes: true` the result data will be an array of Dirent. + */ + function readdir( + path: PathLike, + options: ObjectEncodingOptions & { + withFileTypes: true; + recursive?: boolean | undefined; + }, + callback: (err: NodeJS.ErrnoException | null, files: Dirent[]) => void, + ): void; + /** + * Asynchronous readdir(3) - read a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options Must include `withFileTypes: true` and `encoding: 'buffer'`. + */ + function readdir( + path: PathLike, + options: { + encoding: "buffer"; + withFileTypes: true; + recursive?: boolean | undefined; + }, + callback: (err: NodeJS.ErrnoException | null, files: Dirent<NonSharedBuffer>[]) => void, + ): void; + namespace readdir { + /** + * Asynchronous readdir(3) - read a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function __promisify__( + path: PathLike, + options?: + | { + encoding: BufferEncoding | null; + withFileTypes?: false | undefined; + recursive?: boolean | undefined; + } + | BufferEncoding + | null, + ): Promise<string[]>; + /** + * Asynchronous readdir(3) - read a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function __promisify__( + path: PathLike, + options: + | "buffer" + | { + encoding: "buffer"; + withFileTypes?: false | undefined; + recursive?: boolean | undefined; + }, + ): Promise<NonSharedBuffer[]>; + /** + * Asynchronous readdir(3) - read a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function __promisify__( + path: PathLike, + options?: + | (ObjectEncodingOptions & { + withFileTypes?: false | undefined; + recursive?: boolean | undefined; + }) + | BufferEncoding + | null, + ): Promise<string[] | NonSharedBuffer[]>; + /** + * Asynchronous readdir(3) - read a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options If called with `withFileTypes: true` the result data will be an array of Dirent + */ + function __promisify__( + path: PathLike, + options: ObjectEncodingOptions & { + withFileTypes: true; + recursive?: boolean | undefined; + }, + ): Promise<Dirent[]>; + /** + * Asynchronous readdir(3) - read a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options Must include `withFileTypes: true` and `encoding: 'buffer'`. + */ + function __promisify__( + path: PathLike, + options: { + encoding: "buffer"; + withFileTypes: true; + recursive?: boolean | undefined; + }, + ): Promise<Dirent<NonSharedBuffer>[]>; + } + /** + * Reads the contents of the directory. + * + * See the POSIX [`readdir(3)`](http://man7.org/linux/man-pages/man3/readdir.3.html) documentation for more details. + * + * The optional `options` argument can be a string specifying an encoding, or an + * object with an `encoding` property specifying the character encoding to use for + * the filenames returned. If the `encoding` is set to `'buffer'`, + * the filenames returned will be passed as `Buffer` objects. + * + * If `options.withFileTypes` is set to `true`, the result will contain `fs.Dirent` objects. + * @since v0.1.21 + */ + function readdirSync( + path: PathLike, + options?: + | { + encoding: BufferEncoding | null; + withFileTypes?: false | undefined; + recursive?: boolean | undefined; + } + | BufferEncoding + | null, + ): string[]; + /** + * Synchronous readdir(3) - read a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function readdirSync( + path: PathLike, + options: + | { + encoding: "buffer"; + withFileTypes?: false | undefined; + recursive?: boolean | undefined; + } + | "buffer", + ): NonSharedBuffer[]; + /** + * Synchronous readdir(3) - read a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function readdirSync( + path: PathLike, + options?: + | (ObjectEncodingOptions & { + withFileTypes?: false | undefined; + recursive?: boolean | undefined; + }) + | BufferEncoding + | null, + ): string[] | NonSharedBuffer[]; + /** + * Synchronous readdir(3) - read a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options If called with `withFileTypes: true` the result data will be an array of Dirent. + */ + function readdirSync( + path: PathLike, + options: ObjectEncodingOptions & { + withFileTypes: true; + recursive?: boolean | undefined; + }, + ): Dirent[]; + /** + * Synchronous readdir(3) - read a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options Must include `withFileTypes: true` and `encoding: 'buffer'`. + */ + function readdirSync( + path: PathLike, + options: { + encoding: "buffer"; + withFileTypes: true; + recursive?: boolean | undefined; + }, + ): Dirent<NonSharedBuffer>[]; + /** + * Closes the file descriptor. No arguments other than a possible exception are + * given to the completion callback. + * + * Calling `fs.close()` on any file descriptor (`fd`) that is currently in use + * through any other `fs` operation may lead to undefined behavior. + * + * See the POSIX [`close(2)`](http://man7.org/linux/man-pages/man2/close.2.html) documentation for more detail. + * @since v0.0.2 + */ + function close(fd: number, callback?: NoParamCallback): void; + namespace close { + /** + * Asynchronous close(2) - close a file descriptor. + * @param fd A file descriptor. + */ + function __promisify__(fd: number): Promise<void>; + } + /** + * Closes the file descriptor. Returns `undefined`. + * + * Calling `fs.closeSync()` on any file descriptor (`fd`) that is currently in use + * through any other `fs` operation may lead to undefined behavior. + * + * See the POSIX [`close(2)`](http://man7.org/linux/man-pages/man2/close.2.html) documentation for more detail. + * @since v0.1.21 + */ + function closeSync(fd: number): void; + /** + * Asynchronous file open. See the POSIX [`open(2)`](http://man7.org/linux/man-pages/man2/open.2.html) documentation for more details. + * + * `mode` sets the file mode (permission and sticky bits), but only if the file was + * created. On Windows, only the write permission can be manipulated; see {@link chmod}. + * + * The callback gets two arguments `(err, fd)`. + * + * Some characters (`< > : " / \ | ? *`) are reserved under Windows as documented + * by [Naming Files, Paths, and Namespaces](https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file). Under NTFS, if the filename contains + * a colon, Node.js will open a file system stream, as described by [this MSDN page](https://docs.microsoft.com/en-us/windows/desktop/FileIO/using-streams). + * + * Functions based on `fs.open()` exhibit this behavior as well:`fs.writeFile()`, `fs.readFile()`, etc. + * @since v0.0.2 + * @param [flags='r'] See `support of file system `flags``. + * @param [mode=0o666] + */ + function open( + path: PathLike, + flags: OpenMode | undefined, + mode: Mode | undefined | null, + callback: (err: NodeJS.ErrnoException | null, fd: number) => void, + ): void; + /** + * Asynchronous open(2) - open and possibly create a file. If the file is created, its mode will be `0o666`. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param [flags='r'] See `support of file system `flags``. + */ + function open( + path: PathLike, + flags: OpenMode | undefined, + callback: (err: NodeJS.ErrnoException | null, fd: number) => void, + ): void; + /** + * Asynchronous open(2) - open and possibly create a file. If the file is created, its mode will be `0o666`. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + */ + function open(path: PathLike, callback: (err: NodeJS.ErrnoException | null, fd: number) => void): void; + namespace open { + /** + * Asynchronous open(2) - open and possibly create a file. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param mode A file mode. If a string is passed, it is parsed as an octal integer. If not supplied, defaults to `0o666`. + */ + function __promisify__(path: PathLike, flags: OpenMode, mode?: Mode | null): Promise<number>; + } + /** + * Returns an integer representing the file descriptor. + * + * For detailed information, see the documentation of the asynchronous version of + * this API: {@link open}. + * @since v0.1.21 + * @param [flags='r'] + * @param [mode=0o666] + */ + function openSync(path: PathLike, flags: OpenMode, mode?: Mode | null): number; + /** + * Change the file system timestamps of the object referenced by `path`. + * + * The `atime` and `mtime` arguments follow these rules: + * + * * Values can be either numbers representing Unix epoch time in seconds, `Date`s, or a numeric string like `'123456789.0'`. + * * If the value can not be converted to a number, or is `NaN`, `Infinity`, or `-Infinity`, an `Error` will be thrown. + * @since v0.4.2 + */ + function utimes(path: PathLike, atime: TimeLike, mtime: TimeLike, callback: NoParamCallback): void; + namespace utimes { + /** + * Asynchronously change file timestamps of the file referenced by the supplied path. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param atime The last access time. If a string is provided, it will be coerced to number. + * @param mtime The last modified time. If a string is provided, it will be coerced to number. + */ + function __promisify__(path: PathLike, atime: TimeLike, mtime: TimeLike): Promise<void>; + } + /** + * Returns `undefined`. + * + * For detailed information, see the documentation of the asynchronous version of + * this API: {@link utimes}. + * @since v0.4.2 + */ + function utimesSync(path: PathLike, atime: TimeLike, mtime: TimeLike): void; + /** + * Change the file system timestamps of the object referenced by the supplied file + * descriptor. See {@link utimes}. + * @since v0.4.2 + */ + function futimes(fd: number, atime: TimeLike, mtime: TimeLike, callback: NoParamCallback): void; + namespace futimes { + /** + * Asynchronously change file timestamps of the file referenced by the supplied file descriptor. + * @param fd A file descriptor. + * @param atime The last access time. If a string is provided, it will be coerced to number. + * @param mtime The last modified time. If a string is provided, it will be coerced to number. + */ + function __promisify__(fd: number, atime: TimeLike, mtime: TimeLike): Promise<void>; + } + /** + * Synchronous version of {@link futimes}. Returns `undefined`. + * @since v0.4.2 + */ + function futimesSync(fd: number, atime: TimeLike, mtime: TimeLike): void; + /** + * Request that all data for the open file descriptor is flushed to the storage + * device. The specific implementation is operating system and device specific. + * Refer to the POSIX [`fsync(2)`](http://man7.org/linux/man-pages/man2/fsync.2.html) documentation for more detail. No arguments other + * than a possible exception are given to the completion callback. + * @since v0.1.96 + */ + function fsync(fd: number, callback: NoParamCallback): void; + namespace fsync { + /** + * Asynchronous fsync(2) - synchronize a file's in-core state with the underlying storage device. + * @param fd A file descriptor. + */ + function __promisify__(fd: number): Promise<void>; + } + /** + * Request that all data for the open file descriptor is flushed to the storage + * device. The specific implementation is operating system and device specific. + * Refer to the POSIX [`fsync(2)`](http://man7.org/linux/man-pages/man2/fsync.2.html) documentation for more detail. Returns `undefined`. + * @since v0.1.96 + */ + function fsyncSync(fd: number): void; + interface WriteOptions { + /** + * @default 0 + */ + offset?: number | undefined; + /** + * @default `buffer.byteLength - offset` + */ + length?: number | undefined; + /** + * @default null + */ + position?: number | null | undefined; + } + /** + * Write `buffer` to the file specified by `fd`. + * + * `offset` determines the part of the buffer to be written, and `length` is + * an integer specifying the number of bytes to write. + * + * `position` refers to the offset from the beginning of the file where this data + * should be written. If `typeof position !== 'number'`, the data will be written + * at the current position. See [`pwrite(2)`](http://man7.org/linux/man-pages/man2/pwrite.2.html). + * + * The callback will be given three arguments `(err, bytesWritten, buffer)` where `bytesWritten` specifies how many _bytes_ were written from `buffer`. + * + * If this method is invoked as its `util.promisify()` ed version, it returns + * a promise for an `Object` with `bytesWritten` and `buffer` properties. + * + * It is unsafe to use `fs.write()` multiple times on the same file without waiting + * for the callback. For this scenario, {@link createWriteStream} is + * recommended. + * + * On Linux, positional writes don't work when the file is opened in append mode. + * The kernel ignores the position argument and always appends the data to + * the end of the file. + * @since v0.0.2 + * @param [offset=0] + * @param [length=buffer.byteLength - offset] + * @param [position='null'] + */ + function write<TBuffer extends NodeJS.ArrayBufferView>( + fd: number, + buffer: TBuffer, + offset: number | undefined | null, + length: number | undefined | null, + position: number | undefined | null, + callback: (err: NodeJS.ErrnoException | null, written: number, buffer: TBuffer) => void, + ): void; + /** + * Asynchronously writes `buffer` to the file referenced by the supplied file descriptor. + * @param fd A file descriptor. + * @param offset The part of the buffer to be written. If not supplied, defaults to `0`. + * @param length The number of bytes to write. If not supplied, defaults to `buffer.length - offset`. + */ + function write<TBuffer extends NodeJS.ArrayBufferView>( + fd: number, + buffer: TBuffer, + offset: number | undefined | null, + length: number | undefined | null, + callback: (err: NodeJS.ErrnoException | null, written: number, buffer: TBuffer) => void, + ): void; + /** + * Asynchronously writes `buffer` to the file referenced by the supplied file descriptor. + * @param fd A file descriptor. + * @param offset The part of the buffer to be written. If not supplied, defaults to `0`. + */ + function write<TBuffer extends NodeJS.ArrayBufferView>( + fd: number, + buffer: TBuffer, + offset: number | undefined | null, + callback: (err: NodeJS.ErrnoException | null, written: number, buffer: TBuffer) => void, + ): void; + /** + * Asynchronously writes `buffer` to the file referenced by the supplied file descriptor. + * @param fd A file descriptor. + */ + function write<TBuffer extends NodeJS.ArrayBufferView>( + fd: number, + buffer: TBuffer, + callback: (err: NodeJS.ErrnoException | null, written: number, buffer: TBuffer) => void, + ): void; + /** + * Asynchronously writes `buffer` to the file referenced by the supplied file descriptor. + * @param fd A file descriptor. + * @param options An object with the following properties: + * * `offset` The part of the buffer to be written. If not supplied, defaults to `0`. + * * `length` The number of bytes to write. If not supplied, defaults to `buffer.length - offset`. + * * `position` The offset from the beginning of the file where this data should be written. If not supplied, defaults to the current position. + */ + function write<TBuffer extends NodeJS.ArrayBufferView>( + fd: number, + buffer: TBuffer, + options: WriteOptions, + callback: (err: NodeJS.ErrnoException | null, written: number, buffer: TBuffer) => void, + ): void; + /** + * Asynchronously writes `string` to the file referenced by the supplied file descriptor. + * @param fd A file descriptor. + * @param string A string to write. + * @param position The offset from the beginning of the file where this data should be written. If not supplied, defaults to the current position. + * @param encoding The expected string encoding. + */ + function write( + fd: number, + string: string, + position: number | undefined | null, + encoding: BufferEncoding | undefined | null, + callback: (err: NodeJS.ErrnoException | null, written: number, str: string) => void, + ): void; + /** + * Asynchronously writes `string` to the file referenced by the supplied file descriptor. + * @param fd A file descriptor. + * @param string A string to write. + * @param position The offset from the beginning of the file where this data should be written. If not supplied, defaults to the current position. + */ + function write( + fd: number, + string: string, + position: number | undefined | null, + callback: (err: NodeJS.ErrnoException | null, written: number, str: string) => void, + ): void; + /** + * Asynchronously writes `string` to the file referenced by the supplied file descriptor. + * @param fd A file descriptor. + * @param string A string to write. + */ + function write( + fd: number, + string: string, + callback: (err: NodeJS.ErrnoException | null, written: number, str: string) => void, + ): void; + namespace write { + /** + * Asynchronously writes `buffer` to the file referenced by the supplied file descriptor. + * @param fd A file descriptor. + * @param offset The part of the buffer to be written. If not supplied, defaults to `0`. + * @param length The number of bytes to write. If not supplied, defaults to `buffer.length - offset`. + * @param position The offset from the beginning of the file where this data should be written. If not supplied, defaults to the current position. + */ + function __promisify__<TBuffer extends NodeJS.ArrayBufferView>( + fd: number, + buffer?: TBuffer, + offset?: number, + length?: number, + position?: number | null, + ): Promise<{ + bytesWritten: number; + buffer: TBuffer; + }>; + /** + * Asynchronously writes `buffer` to the file referenced by the supplied file descriptor. + * @param fd A file descriptor. + * @param options An object with the following properties: + * * `offset` The part of the buffer to be written. If not supplied, defaults to `0`. + * * `length` The number of bytes to write. If not supplied, defaults to `buffer.length - offset`. + * * `position` The offset from the beginning of the file where this data should be written. If not supplied, defaults to the current position. + */ + function __promisify__<TBuffer extends NodeJS.ArrayBufferView>( + fd: number, + buffer?: TBuffer, + options?: WriteOptions, + ): Promise<{ + bytesWritten: number; + buffer: TBuffer; + }>; + /** + * Asynchronously writes `string` to the file referenced by the supplied file descriptor. + * @param fd A file descriptor. + * @param string A string to write. + * @param position The offset from the beginning of the file where this data should be written. If not supplied, defaults to the current position. + * @param encoding The expected string encoding. + */ + function __promisify__( + fd: number, + string: string, + position?: number | null, + encoding?: BufferEncoding | null, + ): Promise<{ + bytesWritten: number; + buffer: string; + }>; + } + /** + * For detailed information, see the documentation of the asynchronous version of + * this API: {@link write}. + * @since v0.1.21 + * @param [offset=0] + * @param [length=buffer.byteLength - offset] + * @param [position='null'] + * @return The number of bytes written. + */ + function writeSync( + fd: number, + buffer: NodeJS.ArrayBufferView, + offset?: number | null, + length?: number | null, + position?: number | null, + ): number; + /** + * Synchronously writes `string` to the file referenced by the supplied file descriptor, returning the number of bytes written. + * @param fd A file descriptor. + * @param string A string to write. + * @param position The offset from the beginning of the file where this data should be written. If not supplied, defaults to the current position. + * @param encoding The expected string encoding. + */ + function writeSync( + fd: number, + string: string, + position?: number | null, + encoding?: BufferEncoding | null, + ): number; + type ReadPosition = number | bigint; + interface ReadOptions { + /** + * @default 0 + */ + offset?: number | undefined; + /** + * @default `length of buffer` + */ + length?: number | undefined; + /** + * @default null + */ + position?: ReadPosition | null | undefined; + } + interface ReadOptionsWithBuffer<T extends NodeJS.ArrayBufferView> extends ReadOptions { + buffer?: T | undefined; + } + /** @deprecated Use `ReadOptions` instead. */ + // TODO: remove in future major + interface ReadSyncOptions extends ReadOptions {} + /** @deprecated Use `ReadOptionsWithBuffer` instead. */ + // TODO: remove in future major + interface ReadAsyncOptions<T extends NodeJS.ArrayBufferView> extends ReadOptionsWithBuffer<T> {} + /** + * Read data from the file specified by `fd`. + * + * The callback is given the three arguments, `(err, bytesRead, buffer)`. + * + * If the file is not modified concurrently, the end-of-file is reached when the + * number of bytes read is zero. + * + * If this method is invoked as its `util.promisify()` ed version, it returns + * a promise for an `Object` with `bytesRead` and `buffer` properties. + * @since v0.0.2 + * @param buffer The buffer that the data will be written to. + * @param offset The position in `buffer` to write the data to. + * @param length The number of bytes to read. + * @param position Specifies where to begin reading from in the file. If `position` is `null` or `-1 `, data will be read from the current file position, and the file position will be updated. If + * `position` is an integer, the file position will be unchanged. + */ + function read<TBuffer extends NodeJS.ArrayBufferView>( + fd: number, + buffer: TBuffer, + offset: number, + length: number, + position: ReadPosition | null, + callback: (err: NodeJS.ErrnoException | null, bytesRead: number, buffer: TBuffer) => void, + ): void; + /** + * Similar to the above `fs.read` function, this version takes an optional `options` object. + * If not otherwise specified in an `options` object, + * `buffer` defaults to `Buffer.alloc(16384)`, + * `offset` defaults to `0`, + * `length` defaults to `buffer.byteLength`, `- offset` as of Node 17.6.0 + * `position` defaults to `null` + * @since v12.17.0, 13.11.0 + */ + function read<TBuffer extends NodeJS.ArrayBufferView = NonSharedBuffer>( + fd: number, + options: ReadOptionsWithBuffer<TBuffer>, + callback: (err: NodeJS.ErrnoException | null, bytesRead: number, buffer: TBuffer) => void, + ): void; + function read<TBuffer extends NodeJS.ArrayBufferView>( + fd: number, + buffer: TBuffer, + options: ReadOptions, + callback: (err: NodeJS.ErrnoException | null, bytesRead: number, buffer: TBuffer) => void, + ): void; + function read<TBuffer extends NodeJS.ArrayBufferView>( + fd: number, + buffer: TBuffer, + callback: (err: NodeJS.ErrnoException | null, bytesRead: number, buffer: TBuffer) => void, + ): void; + function read( + fd: number, + callback: (err: NodeJS.ErrnoException | null, bytesRead: number, buffer: NonSharedBuffer) => void, + ): void; + namespace read { + /** + * @param fd A file descriptor. + * @param buffer The buffer that the data will be written to. + * @param offset The offset in the buffer at which to start writing. + * @param length The number of bytes to read. + * @param position The offset from the beginning of the file from which data should be read. If `null`, data will be read from the current position. + */ + function __promisify__<TBuffer extends NodeJS.ArrayBufferView>( + fd: number, + buffer: TBuffer, + offset: number, + length: number, + position: ReadPosition | null, + ): Promise<{ + bytesRead: number; + buffer: TBuffer; + }>; + function __promisify__<TBuffer extends NodeJS.ArrayBufferView = NonSharedBuffer>( + fd: number, + options: ReadOptionsWithBuffer<TBuffer>, + ): Promise<{ + bytesRead: number; + buffer: TBuffer; + }>; + function __promisify__(fd: number): Promise<{ + bytesRead: number; + buffer: NonSharedBuffer; + }>; + } + /** + * Returns the number of `bytesRead`. + * + * For detailed information, see the documentation of the asynchronous version of + * this API: {@link read}. + * @since v0.1.21 + * @param [position='null'] + */ + function readSync( + fd: number, + buffer: NodeJS.ArrayBufferView, + offset: number, + length: number, + position: ReadPosition | null, + ): number; + /** + * Similar to the above `fs.readSync` function, this version takes an optional `options` object. + * If no `options` object is specified, it will default with the above values. + */ + function readSync(fd: number, buffer: NodeJS.ArrayBufferView, opts?: ReadOptions): number; + /** + * Asynchronously reads the entire contents of a file. + * + * ```js + * import { readFile } from 'node:fs'; + * + * readFile('/etc/passwd', (err, data) => { + * if (err) throw err; + * console.log(data); + * }); + * ``` + * + * The callback is passed two arguments `(err, data)`, where `data` is the + * contents of the file. + * + * If no encoding is specified, then the raw buffer is returned. + * + * If `options` is a string, then it specifies the encoding: + * + * ```js + * import { readFile } from 'node:fs'; + * + * readFile('/etc/passwd', 'utf8', callback); + * ``` + * + * When the path is a directory, the behavior of `fs.readFile()` and {@link readFileSync} is platform-specific. On macOS, Linux, and Windows, an + * error will be returned. On FreeBSD, a representation of the directory's contents + * will be returned. + * + * ```js + * import { readFile } from 'node:fs'; + * + * // macOS, Linux, and Windows + * readFile('<directory>', (err, data) => { + * // => [Error: EISDIR: illegal operation on a directory, read <directory>] + * }); + * + * // FreeBSD + * readFile('<directory>', (err, data) => { + * // => null, <data> + * }); + * ``` + * + * It is possible to abort an ongoing request using an `AbortSignal`. If a + * request is aborted the callback is called with an `AbortError`: + * + * ```js + * import { readFile } from 'node:fs'; + * + * const controller = new AbortController(); + * const signal = controller.signal; + * readFile(fileInfo[0].name, { signal }, (err, buf) => { + * // ... + * }); + * // When you want to abort the request + * controller.abort(); + * ``` + * + * The `fs.readFile()` function buffers the entire file. To minimize memory costs, + * when possible prefer streaming via `fs.createReadStream()`. + * + * Aborting an ongoing request does not abort individual operating + * system requests but rather the internal buffering `fs.readFile` performs. + * @since v0.1.29 + * @param path filename or file descriptor + */ + function readFile( + path: PathOrFileDescriptor, + options: + | ({ + encoding?: null | undefined; + flag?: string | undefined; + } & Abortable) + | undefined + | null, + callback: (err: NodeJS.ErrnoException | null, data: NonSharedBuffer) => void, + ): void; + /** + * Asynchronously reads the entire contents of a file. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * If a file descriptor is provided, the underlying file will _not_ be closed automatically. + * @param options Either the encoding for the result, or an object that contains the encoding and an optional flag. + * If a flag is not provided, it defaults to `'r'`. + */ + function readFile( + path: PathOrFileDescriptor, + options: + | ({ + encoding: BufferEncoding; + flag?: string | undefined; + } & Abortable) + | BufferEncoding, + callback: (err: NodeJS.ErrnoException | null, data: string) => void, + ): void; + /** + * Asynchronously reads the entire contents of a file. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * If a file descriptor is provided, the underlying file will _not_ be closed automatically. + * @param options Either the encoding for the result, or an object that contains the encoding and an optional flag. + * If a flag is not provided, it defaults to `'r'`. + */ + function readFile( + path: PathOrFileDescriptor, + options: + | (ObjectEncodingOptions & { + flag?: string | undefined; + } & Abortable) + | BufferEncoding + | undefined + | null, + callback: (err: NodeJS.ErrnoException | null, data: string | NonSharedBuffer) => void, + ): void; + /** + * Asynchronously reads the entire contents of a file. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * If a file descriptor is provided, the underlying file will _not_ be closed automatically. + */ + function readFile( + path: PathOrFileDescriptor, + callback: (err: NodeJS.ErrnoException | null, data: NonSharedBuffer) => void, + ): void; + namespace readFile { + /** + * Asynchronously reads the entire contents of a file. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * If a file descriptor is provided, the underlying file will _not_ be closed automatically. + * @param options An object that may contain an optional flag. + * If a flag is not provided, it defaults to `'r'`. + */ + function __promisify__( + path: PathOrFileDescriptor, + options?: { + encoding?: null | undefined; + flag?: string | undefined; + } | null, + ): Promise<NonSharedBuffer>; + /** + * Asynchronously reads the entire contents of a file. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + * If a file descriptor is provided, the underlying file will _not_ be closed automatically. + * @param options Either the encoding for the result, or an object that contains the encoding and an optional flag. + * If a flag is not provided, it defaults to `'r'`. + */ + function __promisify__( + path: PathOrFileDescriptor, + options: + | { + encoding: BufferEncoding; + flag?: string | undefined; + } + | BufferEncoding, + ): Promise<string>; + /** + * Asynchronously reads the entire contents of a file. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + * If a file descriptor is provided, the underlying file will _not_ be closed automatically. + * @param options Either the encoding for the result, or an object that contains the encoding and an optional flag. + * If a flag is not provided, it defaults to `'r'`. + */ + function __promisify__( + path: PathOrFileDescriptor, + options?: + | (ObjectEncodingOptions & { + flag?: string | undefined; + }) + | BufferEncoding + | null, + ): Promise<string | NonSharedBuffer>; + } + /** + * Returns the contents of the `path`. + * + * For detailed information, see the documentation of the asynchronous version of + * this API: {@link readFile}. + * + * If the `encoding` option is specified then this function returns a + * string. Otherwise it returns a buffer. + * + * Similar to {@link readFile}, when the path is a directory, the behavior of `fs.readFileSync()` is platform-specific. + * + * ```js + * import { readFileSync } from 'node:fs'; + * + * // macOS, Linux, and Windows + * readFileSync('<directory>'); + * // => [Error: EISDIR: illegal operation on a directory, read <directory>] + * + * // FreeBSD + * readFileSync('<directory>'); // => <data> + * ``` + * @since v0.1.8 + * @param path filename or file descriptor + */ + function readFileSync( + path: PathOrFileDescriptor, + options?: { + encoding?: null | undefined; + flag?: string | undefined; + } | null, + ): NonSharedBuffer; + /** + * Synchronously reads the entire contents of a file. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * If a file descriptor is provided, the underlying file will _not_ be closed automatically. + * @param options Either the encoding for the result, or an object that contains the encoding and an optional flag. + * If a flag is not provided, it defaults to `'r'`. + */ + function readFileSync( + path: PathOrFileDescriptor, + options: + | { + encoding: BufferEncoding; + flag?: string | undefined; + } + | BufferEncoding, + ): string; + /** + * Synchronously reads the entire contents of a file. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * If a file descriptor is provided, the underlying file will _not_ be closed automatically. + * @param options Either the encoding for the result, or an object that contains the encoding and an optional flag. + * If a flag is not provided, it defaults to `'r'`. + */ + function readFileSync( + path: PathOrFileDescriptor, + options?: + | (ObjectEncodingOptions & { + flag?: string | undefined; + }) + | BufferEncoding + | null, + ): string | NonSharedBuffer; + type WriteFileOptions = + | ( + & ObjectEncodingOptions + & Abortable + & { + mode?: Mode | undefined; + flag?: string | undefined; + flush?: boolean | undefined; + } + ) + | BufferEncoding + | null; + /** + * When `file` is a filename, asynchronously writes data to the file, replacing the + * file if it already exists. `data` can be a string or a buffer. + * + * When `file` is a file descriptor, the behavior is similar to calling `fs.write()` directly (which is recommended). See the notes below on using + * a file descriptor. + * + * The `encoding` option is ignored if `data` is a buffer. + * + * The `mode` option only affects the newly created file. See {@link open} for more details. + * + * ```js + * import { writeFile } from 'node:fs'; + * import { Buffer } from 'node:buffer'; + * + * const data = new Uint8Array(Buffer.from('Hello Node.js')); + * writeFile('message.txt', data, (err) => { + * if (err) throw err; + * console.log('The file has been saved!'); + * }); + * ``` + * + * If `options` is a string, then it specifies the encoding: + * + * ```js + * import { writeFile } from 'node:fs'; + * + * writeFile('message.txt', 'Hello Node.js', 'utf8', callback); + * ``` + * + * It is unsafe to use `fs.writeFile()` multiple times on the same file without + * waiting for the callback. For this scenario, {@link createWriteStream} is + * recommended. + * + * Similarly to `fs.readFile` \- `fs.writeFile` is a convenience method that + * performs multiple `write` calls internally to write the buffer passed to it. + * For performance sensitive code consider using {@link createWriteStream}. + * + * It is possible to use an `AbortSignal` to cancel an `fs.writeFile()`. + * Cancelation is "best effort", and some amount of data is likely still + * to be written. + * + * ```js + * import { writeFile } from 'node:fs'; + * import { Buffer } from 'node:buffer'; + * + * const controller = new AbortController(); + * const { signal } = controller; + * const data = new Uint8Array(Buffer.from('Hello Node.js')); + * writeFile('message.txt', data, { signal }, (err) => { + * // When a request is aborted - the callback is called with an AbortError + * }); + * // When the request should be aborted + * controller.abort(); + * ``` + * + * Aborting an ongoing request does not abort individual operating + * system requests but rather the internal buffering `fs.writeFile` performs. + * @since v0.1.29 + * @param file filename or file descriptor + */ + function writeFile( + file: PathOrFileDescriptor, + data: string | NodeJS.ArrayBufferView, + options: WriteFileOptions, + callback: NoParamCallback, + ): void; + /** + * Asynchronously writes data to a file, replacing the file if it already exists. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * If a file descriptor is provided, the underlying file will _not_ be closed automatically. + * @param data The data to write. If something other than a Buffer or Uint8Array is provided, the value is coerced to a string. + */ + function writeFile( + path: PathOrFileDescriptor, + data: string | NodeJS.ArrayBufferView, + callback: NoParamCallback, + ): void; + namespace writeFile { + /** + * Asynchronously writes data to a file, replacing the file if it already exists. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + * If a file descriptor is provided, the underlying file will _not_ be closed automatically. + * @param data The data to write. If something other than a Buffer or Uint8Array is provided, the value is coerced to a string. + * @param options Either the encoding for the file, or an object optionally specifying the encoding, file mode, and flag. + * If `encoding` is not supplied, the default of `'utf8'` is used. + * If `mode` is not supplied, the default of `0o666` is used. + * If `mode` is a string, it is parsed as an octal integer. + * If `flag` is not supplied, the default of `'w'` is used. + */ + function __promisify__( + path: PathOrFileDescriptor, + data: string | NodeJS.ArrayBufferView, + options?: WriteFileOptions, + ): Promise<void>; + } + /** + * Returns `undefined`. + * + * The `mode` option only affects the newly created file. See {@link open} for more details. + * + * For detailed information, see the documentation of the asynchronous version of + * this API: {@link writeFile}. + * @since v0.1.29 + * @param file filename or file descriptor + */ + function writeFileSync( + file: PathOrFileDescriptor, + data: string | NodeJS.ArrayBufferView, + options?: WriteFileOptions, + ): void; + /** + * Asynchronously append data to a file, creating the file if it does not yet + * exist. `data` can be a string or a `Buffer`. + * + * The `mode` option only affects the newly created file. See {@link open} for more details. + * + * ```js + * import { appendFile } from 'node:fs'; + * + * appendFile('message.txt', 'data to append', (err) => { + * if (err) throw err; + * console.log('The "data to append" was appended to file!'); + * }); + * ``` + * + * If `options` is a string, then it specifies the encoding: + * + * ```js + * import { appendFile } from 'node:fs'; + * + * appendFile('message.txt', 'data to append', 'utf8', callback); + * ``` + * + * The `path` may be specified as a numeric file descriptor that has been opened + * for appending (using `fs.open()` or `fs.openSync()`). The file descriptor will + * not be closed automatically. + * + * ```js + * import { open, close, appendFile } from 'node:fs'; + * + * function closeFd(fd) { + * close(fd, (err) => { + * if (err) throw err; + * }); + * } + * + * open('message.txt', 'a', (err, fd) => { + * if (err) throw err; + * + * try { + * appendFile(fd, 'data to append', 'utf8', (err) => { + * closeFd(fd); + * if (err) throw err; + * }); + * } catch (err) { + * closeFd(fd); + * throw err; + * } + * }); + * ``` + * @since v0.6.7 + * @param path filename or file descriptor + */ + function appendFile( + path: PathOrFileDescriptor, + data: string | Uint8Array, + options: WriteFileOptions, + callback: NoParamCallback, + ): void; + /** + * Asynchronously append data to a file, creating the file if it does not exist. + * @param file A path to a file. If a URL is provided, it must use the `file:` protocol. + * If a file descriptor is provided, the underlying file will _not_ be closed automatically. + * @param data The data to write. If something other than a Buffer or Uint8Array is provided, the value is coerced to a string. + */ + function appendFile(file: PathOrFileDescriptor, data: string | Uint8Array, callback: NoParamCallback): void; + namespace appendFile { + /** + * Asynchronously append data to a file, creating the file if it does not exist. + * @param file A path to a file. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + * If a file descriptor is provided, the underlying file will _not_ be closed automatically. + * @param data The data to write. If something other than a Buffer or Uint8Array is provided, the value is coerced to a string. + * @param options Either the encoding for the file, or an object optionally specifying the encoding, file mode, and flag. + * If `encoding` is not supplied, the default of `'utf8'` is used. + * If `mode` is not supplied, the default of `0o666` is used. + * If `mode` is a string, it is parsed as an octal integer. + * If `flag` is not supplied, the default of `'a'` is used. + */ + function __promisify__( + file: PathOrFileDescriptor, + data: string | Uint8Array, + options?: WriteFileOptions, + ): Promise<void>; + } + /** + * Synchronously append data to a file, creating the file if it does not yet + * exist. `data` can be a string or a `Buffer`. + * + * The `mode` option only affects the newly created file. See {@link open} for more details. + * + * ```js + * import { appendFileSync } from 'node:fs'; + * + * try { + * appendFileSync('message.txt', 'data to append'); + * console.log('The "data to append" was appended to file!'); + * } catch (err) { + * // Handle the error + * } + * ``` + * + * If `options` is a string, then it specifies the encoding: + * + * ```js + * import { appendFileSync } from 'node:fs'; + * + * appendFileSync('message.txt', 'data to append', 'utf8'); + * ``` + * + * The `path` may be specified as a numeric file descriptor that has been opened + * for appending (using `fs.open()` or `fs.openSync()`). The file descriptor will + * not be closed automatically. + * + * ```js + * import { openSync, closeSync, appendFileSync } from 'node:fs'; + * + * let fd; + * + * try { + * fd = openSync('message.txt', 'a'); + * appendFileSync(fd, 'data to append', 'utf8'); + * } catch (err) { + * // Handle the error + * } finally { + * if (fd !== undefined) + * closeSync(fd); + * } + * ``` + * @since v0.6.7 + * @param path filename or file descriptor + */ + function appendFileSync( + path: PathOrFileDescriptor, + data: string | Uint8Array, + options?: WriteFileOptions, + ): void; + /** + * Watch for changes on `filename`. The callback `listener` will be called each + * time the file is accessed. + * + * The `options` argument may be omitted. If provided, it should be an object. The `options` object may contain a boolean named `persistent` that indicates + * whether the process should continue to run as long as files are being watched. + * The `options` object may specify an `interval` property indicating how often the + * target should be polled in milliseconds. + * + * The `listener` gets two arguments the current stat object and the previous + * stat object: + * + * ```js + * import { watchFile } from 'node:fs'; + * + * watchFile('message.text', (curr, prev) => { + * console.log(`the current mtime is: ${curr.mtime}`); + * console.log(`the previous mtime was: ${prev.mtime}`); + * }); + * ``` + * + * These stat objects are instances of `fs.Stat`. If the `bigint` option is `true`, + * the numeric values in these objects are specified as `BigInt`s. + * + * To be notified when the file was modified, not just accessed, it is necessary + * to compare `curr.mtimeMs` and `prev.mtimeMs`. + * + * When an `fs.watchFile` operation results in an `ENOENT` error, it + * will invoke the listener once, with all the fields zeroed (or, for dates, the + * Unix Epoch). If the file is created later on, the listener will be called + * again, with the latest stat objects. This is a change in functionality since + * v0.10. + * + * Using {@link watch} is more efficient than `fs.watchFile` and `fs.unwatchFile`. `fs.watch` should be used instead of `fs.watchFile` and `fs.unwatchFile` when possible. + * + * When a file being watched by `fs.watchFile()` disappears and reappears, + * then the contents of `previous` in the second callback event (the file's + * reappearance) will be the same as the contents of `previous` in the first + * callback event (its disappearance). + * + * This happens when: + * + * * the file is deleted, followed by a restore + * * the file is renamed and then renamed a second time back to its original name + * @since v0.1.31 + */ + interface WatchFileOptions { + bigint?: boolean | undefined; + persistent?: boolean | undefined; + interval?: number | undefined; + } + /** + * Watch for changes on `filename`. The callback `listener` will be called each + * time the file is accessed. + * + * The `options` argument may be omitted. If provided, it should be an object. The `options` object may contain a boolean named `persistent` that indicates + * whether the process should continue to run as long as files are being watched. + * The `options` object may specify an `interval` property indicating how often the + * target should be polled in milliseconds. + * + * The `listener` gets two arguments the current stat object and the previous + * stat object: + * + * ```js + * import { watchFile } from 'node:fs'; + * + * watchFile('message.text', (curr, prev) => { + * console.log(`the current mtime is: ${curr.mtime}`); + * console.log(`the previous mtime was: ${prev.mtime}`); + * }); + * ``` + * + * These stat objects are instances of `fs.Stat`. If the `bigint` option is `true`, + * the numeric values in these objects are specified as `BigInt`s. + * + * To be notified when the file was modified, not just accessed, it is necessary + * to compare `curr.mtimeMs` and `prev.mtimeMs`. + * + * When an `fs.watchFile` operation results in an `ENOENT` error, it + * will invoke the listener once, with all the fields zeroed (or, for dates, the + * Unix Epoch). If the file is created later on, the listener will be called + * again, with the latest stat objects. This is a change in functionality since + * v0.10. + * + * Using {@link watch} is more efficient than `fs.watchFile` and `fs.unwatchFile`. `fs.watch` should be used instead of `fs.watchFile` and `fs.unwatchFile` when possible. + * + * When a file being watched by `fs.watchFile()` disappears and reappears, + * then the contents of `previous` in the second callback event (the file's + * reappearance) will be the same as the contents of `previous` in the first + * callback event (its disappearance). + * + * This happens when: + * + * * the file is deleted, followed by a restore + * * the file is renamed and then renamed a second time back to its original name + * @since v0.1.31 + */ + function watchFile( + filename: PathLike, + options: + | (WatchFileOptions & { + bigint?: false | undefined; + }) + | undefined, + listener: StatsListener, + ): StatWatcher; + function watchFile( + filename: PathLike, + options: + | (WatchFileOptions & { + bigint: true; + }) + | undefined, + listener: BigIntStatsListener, + ): StatWatcher; + /** + * Watch for changes on `filename`. The callback `listener` will be called each time the file is accessed. + * @param filename A path to a file or directory. If a URL is provided, it must use the `file:` protocol. + */ + function watchFile(filename: PathLike, listener: StatsListener): StatWatcher; + /** + * Stop watching for changes on `filename`. If `listener` is specified, only that + * particular listener is removed. Otherwise, _all_ listeners are removed, + * effectively stopping watching of `filename`. + * + * Calling `fs.unwatchFile()` with a filename that is not being watched is a + * no-op, not an error. + * + * Using {@link watch} is more efficient than `fs.watchFile()` and `fs.unwatchFile()`. `fs.watch()` should be used instead of `fs.watchFile()` and `fs.unwatchFile()` when possible. + * @since v0.1.31 + * @param listener Optional, a listener previously attached using `fs.watchFile()` + */ + function unwatchFile(filename: PathLike, listener?: StatsListener): void; + function unwatchFile(filename: PathLike, listener?: BigIntStatsListener): void; + interface WatchOptions extends Abortable { + encoding?: BufferEncoding | "buffer" | undefined; + persistent?: boolean | undefined; + recursive?: boolean | undefined; + } + interface WatchOptionsWithBufferEncoding extends WatchOptions { + encoding: "buffer"; + } + interface WatchOptionsWithStringEncoding extends WatchOptions { + encoding?: BufferEncoding | undefined; + } + type WatchEventType = "rename" | "change"; + type WatchListener<T> = (event: WatchEventType, filename: T | null) => void; + type StatsListener = (curr: Stats, prev: Stats) => void; + type BigIntStatsListener = (curr: BigIntStats, prev: BigIntStats) => void; + /** + * Watch for changes on `filename`, where `filename` is either a file or a + * directory. + * + * The second argument is optional. If `options` is provided as a string, it + * specifies the `encoding`. Otherwise `options` should be passed as an object. + * + * The listener callback gets two arguments `(eventType, filename)`. `eventType`is either `'rename'` or `'change'`, and `filename` is the name of the file + * which triggered the event. + * + * On most platforms, `'rename'` is emitted whenever a filename appears or + * disappears in the directory. + * + * The listener callback is attached to the `'change'` event fired by `fs.FSWatcher`, but it is not the same thing as the `'change'` value of `eventType`. + * + * If a `signal` is passed, aborting the corresponding AbortController will close + * the returned `fs.FSWatcher`. + * @since v0.5.10 + * @param listener + */ + function watch( + filename: PathLike, + options?: WatchOptionsWithStringEncoding | BufferEncoding | null, + listener?: WatchListener<string>, + ): FSWatcher; + function watch( + filename: PathLike, + options: WatchOptionsWithBufferEncoding | "buffer", + listener: WatchListener<NonSharedBuffer>, + ): FSWatcher; + function watch( + filename: PathLike, + options: WatchOptions | BufferEncoding | "buffer" | null, + listener: WatchListener<string | NonSharedBuffer>, + ): FSWatcher; + function watch(filename: PathLike, listener: WatchListener<string>): FSWatcher; + /** + * Test whether or not the given path exists by checking with the file system. + * Then call the `callback` argument with either true or false: + * + * ```js + * import { exists } from 'node:fs'; + * + * exists('/etc/passwd', (e) => { + * console.log(e ? 'it exists' : 'no passwd!'); + * }); + * ``` + * + * **The parameters for this callback are not consistent with other Node.js** + * **callbacks.** Normally, the first parameter to a Node.js callback is an `err` parameter, optionally followed by other parameters. The `fs.exists()` callback + * has only one boolean parameter. This is one reason `fs.access()` is recommended + * instead of `fs.exists()`. + * + * Using `fs.exists()` to check for the existence of a file before calling `fs.open()`, `fs.readFile()`, or `fs.writeFile()` is not recommended. Doing + * so introduces a race condition, since other processes may change the file's + * state between the two calls. Instead, user code should open/read/write the + * file directly and handle the error raised if the file does not exist. + * + * **write (NOT RECOMMENDED)** + * + * ```js + * import { exists, open, close } from 'node:fs'; + * + * exists('myfile', (e) => { + * if (e) { + * console.error('myfile already exists'); + * } else { + * open('myfile', 'wx', (err, fd) => { + * if (err) throw err; + * + * try { + * writeMyData(fd); + * } finally { + * close(fd, (err) => { + * if (err) throw err; + * }); + * } + * }); + * } + * }); + * ``` + * + * **write (RECOMMENDED)** + * + * ```js + * import { open, close } from 'node:fs'; + * open('myfile', 'wx', (err, fd) => { + * if (err) { + * if (err.code === 'EEXIST') { + * console.error('myfile already exists'); + * return; + * } + * + * throw err; + * } + * + * try { + * writeMyData(fd); + * } finally { + * close(fd, (err) => { + * if (err) throw err; + * }); + * } + * }); + * ``` + * + * **read (NOT RECOMMENDED)** + * + * ```js + * import { open, close, exists } from 'node:fs'; + * + * exists('myfile', (e) => { + * if (e) { + * open('myfile', 'r', (err, fd) => { + * if (err) throw err; + * + * try { + * readMyData(fd); + * } finally { + * close(fd, (err) => { + * if (err) throw err; + * }); + * } + * }); + * } else { + * console.error('myfile does not exist'); + * } + * }); + * ``` + * + * **read (RECOMMENDED)** + * + * ```js + * import { open, close } from 'node:fs'; + * + * open('myfile', 'r', (err, fd) => { + * if (err) { + * if (err.code === 'ENOENT') { + * console.error('myfile does not exist'); + * return; + * } + * + * throw err; + * } + * + * try { + * readMyData(fd); + * } finally { + * close(fd, (err) => { + * if (err) throw err; + * }); + * } + * }); + * ``` + * + * The "not recommended" examples above check for existence and then use the + * file; the "recommended" examples are better because they use the file directly + * and handle the error, if any. + * + * In general, check for the existence of a file only if the file won't be + * used directly, for example when its existence is a signal from another + * process. + * @since v0.0.2 + * @deprecated Since v1.0.0 - Use {@link stat} or {@link access} instead. + */ + function exists(path: PathLike, callback: (exists: boolean) => void): void; + /** @deprecated */ + namespace exists { + /** + * @param path A path to a file or directory. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + */ + function __promisify__(path: PathLike): Promise<boolean>; + } + /** + * Returns `true` if the path exists, `false` otherwise. + * + * For detailed information, see the documentation of the asynchronous version of + * this API: {@link exists}. + * + * `fs.exists()` is deprecated, but `fs.existsSync()` is not. The `callback` parameter to `fs.exists()` accepts parameters that are inconsistent with other + * Node.js callbacks. `fs.existsSync()` does not use a callback. + * + * ```js + * import { existsSync } from 'node:fs'; + * + * if (existsSync('/etc/passwd')) + * console.log('The path exists.'); + * ``` + * @since v0.1.21 + */ + function existsSync(path: PathLike): boolean; + namespace constants { + // File Access Constants + /** Constant for fs.access(). File is visible to the calling process. */ + const F_OK: number; + /** Constant for fs.access(). File can be read by the calling process. */ + const R_OK: number; + /** Constant for fs.access(). File can be written by the calling process. */ + const W_OK: number; + /** Constant for fs.access(). File can be executed by the calling process. */ + const X_OK: number; + // File Copy Constants + /** Constant for fs.copyFile. Flag indicating the destination file should not be overwritten if it already exists. */ + const COPYFILE_EXCL: number; + /** + * Constant for fs.copyFile. copy operation will attempt to create a copy-on-write reflink. + * If the underlying platform does not support copy-on-write, then a fallback copy mechanism is used. + */ + const COPYFILE_FICLONE: number; + /** + * Constant for fs.copyFile. Copy operation will attempt to create a copy-on-write reflink. + * If the underlying platform does not support copy-on-write, then the operation will fail with an error. + */ + const COPYFILE_FICLONE_FORCE: number; + // File Open Constants + /** Constant for fs.open(). Flag indicating to open a file for read-only access. */ + const O_RDONLY: number; + /** Constant for fs.open(). Flag indicating to open a file for write-only access. */ + const O_WRONLY: number; + /** Constant for fs.open(). Flag indicating to open a file for read-write access. */ + const O_RDWR: number; + /** Constant for fs.open(). Flag indicating to create the file if it does not already exist. */ + const O_CREAT: number; + /** Constant for fs.open(). Flag indicating that opening a file should fail if the O_CREAT flag is set and the file already exists. */ + const O_EXCL: number; + /** + * Constant for fs.open(). Flag indicating that if path identifies a terminal device, + * opening the path shall not cause that terminal to become the controlling terminal for the process + * (if the process does not already have one). + */ + const O_NOCTTY: number; + /** Constant for fs.open(). Flag indicating that if the file exists and is a regular file, and the file is opened successfully for write access, its length shall be truncated to zero. */ + const O_TRUNC: number; + /** Constant for fs.open(). Flag indicating that data will be appended to the end of the file. */ + const O_APPEND: number; + /** Constant for fs.open(). Flag indicating that the open should fail if the path is not a directory. */ + const O_DIRECTORY: number; + /** + * constant for fs.open(). + * Flag indicating reading accesses to the file system will no longer result in + * an update to the atime information associated with the file. + * This flag is available on Linux operating systems only. + */ + const O_NOATIME: number; + /** Constant for fs.open(). Flag indicating that the open should fail if the path is a symbolic link. */ + const O_NOFOLLOW: number; + /** Constant for fs.open(). Flag indicating that the file is opened for synchronous I/O. */ + const O_SYNC: number; + /** Constant for fs.open(). Flag indicating that the file is opened for synchronous I/O with write operations waiting for data integrity. */ + const O_DSYNC: number; + /** Constant for fs.open(). Flag indicating to open the symbolic link itself rather than the resource it is pointing to. */ + const O_SYMLINK: number; + /** Constant for fs.open(). When set, an attempt will be made to minimize caching effects of file I/O. */ + const O_DIRECT: number; + /** Constant for fs.open(). Flag indicating to open the file in nonblocking mode when possible. */ + const O_NONBLOCK: number; + // File Type Constants + /** Constant for fs.Stats mode property for determining a file's type. Bit mask used to extract the file type code. */ + const S_IFMT: number; + /** Constant for fs.Stats mode property for determining a file's type. File type constant for a regular file. */ + const S_IFREG: number; + /** Constant for fs.Stats mode property for determining a file's type. File type constant for a directory. */ + const S_IFDIR: number; + /** Constant for fs.Stats mode property for determining a file's type. File type constant for a character-oriented device file. */ + const S_IFCHR: number; + /** Constant for fs.Stats mode property for determining a file's type. File type constant for a block-oriented device file. */ + const S_IFBLK: number; + /** Constant for fs.Stats mode property for determining a file's type. File type constant for a FIFO/pipe. */ + const S_IFIFO: number; + /** Constant for fs.Stats mode property for determining a file's type. File type constant for a symbolic link. */ + const S_IFLNK: number; + /** Constant for fs.Stats mode property for determining a file's type. File type constant for a socket. */ + const S_IFSOCK: number; + // File Mode Constants + /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating readable, writable and executable by owner. */ + const S_IRWXU: number; + /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating readable by owner. */ + const S_IRUSR: number; + /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating writable by owner. */ + const S_IWUSR: number; + /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating executable by owner. */ + const S_IXUSR: number; + /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating readable, writable and executable by group. */ + const S_IRWXG: number; + /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating readable by group. */ + const S_IRGRP: number; + /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating writable by group. */ + const S_IWGRP: number; + /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating executable by group. */ + const S_IXGRP: number; + /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating readable, writable and executable by others. */ + const S_IRWXO: number; + /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating readable by others. */ + const S_IROTH: number; + /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating writable by others. */ + const S_IWOTH: number; + /** Constant for fs.Stats mode property for determining access permissions for a file. File mode indicating executable by others. */ + const S_IXOTH: number; + /** + * When set, a memory file mapping is used to access the file. This flag + * is available on Windows operating systems only. On other operating systems, + * this flag is ignored. + */ + const UV_FS_O_FILEMAP: number; + } + /** + * Tests a user's permissions for the file or directory specified by `path`. + * The `mode` argument is an optional integer that specifies the accessibility + * checks to be performed. `mode` should be either the value `fs.constants.F_OK` or a mask consisting of the bitwise OR of any of `fs.constants.R_OK`, `fs.constants.W_OK`, and `fs.constants.X_OK` + * (e.g.`fs.constants.W_OK | fs.constants.R_OK`). Check `File access constants` for + * possible values of `mode`. + * + * The final argument, `callback`, is a callback function that is invoked with + * a possible error argument. If any of the accessibility checks fail, the error + * argument will be an `Error` object. The following examples check if `package.json` exists, and if it is readable or writable. + * + * ```js + * import { access, constants } from 'node:fs'; + * + * const file = 'package.json'; + * + * // Check if the file exists in the current directory. + * access(file, constants.F_OK, (err) => { + * console.log(`${file} ${err ? 'does not exist' : 'exists'}`); + * }); + * + * // Check if the file is readable. + * access(file, constants.R_OK, (err) => { + * console.log(`${file} ${err ? 'is not readable' : 'is readable'}`); + * }); + * + * // Check if the file is writable. + * access(file, constants.W_OK, (err) => { + * console.log(`${file} ${err ? 'is not writable' : 'is writable'}`); + * }); + * + * // Check if the file is readable and writable. + * access(file, constants.R_OK | constants.W_OK, (err) => { + * console.log(`${file} ${err ? 'is not' : 'is'} readable and writable`); + * }); + * ``` + * + * Do not use `fs.access()` to check for the accessibility of a file before calling `fs.open()`, `fs.readFile()`, or `fs.writeFile()`. Doing + * so introduces a race condition, since other processes may change the file's + * state between the two calls. Instead, user code should open/read/write the + * file directly and handle the error raised if the file is not accessible. + * + * **write (NOT RECOMMENDED)** + * + * ```js + * import { access, open, close } from 'node:fs'; + * + * access('myfile', (err) => { + * if (!err) { + * console.error('myfile already exists'); + * return; + * } + * + * open('myfile', 'wx', (err, fd) => { + * if (err) throw err; + * + * try { + * writeMyData(fd); + * } finally { + * close(fd, (err) => { + * if (err) throw err; + * }); + * } + * }); + * }); + * ``` + * + * **write (RECOMMENDED)** + * + * ```js + * import { open, close } from 'node:fs'; + * + * open('myfile', 'wx', (err, fd) => { + * if (err) { + * if (err.code === 'EEXIST') { + * console.error('myfile already exists'); + * return; + * } + * + * throw err; + * } + * + * try { + * writeMyData(fd); + * } finally { + * close(fd, (err) => { + * if (err) throw err; + * }); + * } + * }); + * ``` + * + * **read (NOT RECOMMENDED)** + * + * ```js + * import { access, open, close } from 'node:fs'; + * access('myfile', (err) => { + * if (err) { + * if (err.code === 'ENOENT') { + * console.error('myfile does not exist'); + * return; + * } + * + * throw err; + * } + * + * open('myfile', 'r', (err, fd) => { + * if (err) throw err; + * + * try { + * readMyData(fd); + * } finally { + * close(fd, (err) => { + * if (err) throw err; + * }); + * } + * }); + * }); + * ``` + * + * **read (RECOMMENDED)** + * + * ```js + * import { open, close } from 'node:fs'; + * + * open('myfile', 'r', (err, fd) => { + * if (err) { + * if (err.code === 'ENOENT') { + * console.error('myfile does not exist'); + * return; + * } + * + * throw err; + * } + * + * try { + * readMyData(fd); + * } finally { + * close(fd, (err) => { + * if (err) throw err; + * }); + * } + * }); + * ``` + * + * The "not recommended" examples above check for accessibility and then use the + * file; the "recommended" examples are better because they use the file directly + * and handle the error, if any. + * + * In general, check for the accessibility of a file only if the file will not be + * used directly, for example when its accessibility is a signal from another + * process. + * + * On Windows, access-control policies (ACLs) on a directory may limit access to + * a file or directory. The `fs.access()` function, however, does not check the + * ACL and therefore may report that a path is accessible even if the ACL restricts + * the user from reading or writing to it. + * @since v0.11.15 + * @param [mode=fs.constants.F_OK] + */ + function access(path: PathLike, mode: number | undefined, callback: NoParamCallback): void; + /** + * Asynchronously tests a user's permissions for the file specified by path. + * @param path A path to a file or directory. If a URL is provided, it must use the `file:` protocol. + */ + function access(path: PathLike, callback: NoParamCallback): void; + namespace access { + /** + * Asynchronously tests a user's permissions for the file specified by path. + * @param path A path to a file or directory. If a URL is provided, it must use the `file:` protocol. + * URL support is _experimental_. + */ + function __promisify__(path: PathLike, mode?: number): Promise<void>; + } + /** + * Synchronously tests a user's permissions for the file or directory specified + * by `path`. The `mode` argument is an optional integer that specifies the + * accessibility checks to be performed. `mode` should be either the value `fs.constants.F_OK` or a mask consisting of the bitwise OR of any of `fs.constants.R_OK`, `fs.constants.W_OK`, and + * `fs.constants.X_OK` (e.g.`fs.constants.W_OK | fs.constants.R_OK`). Check `File access constants` for + * possible values of `mode`. + * + * If any of the accessibility checks fail, an `Error` will be thrown. Otherwise, + * the method will return `undefined`. + * + * ```js + * import { accessSync, constants } from 'node:fs'; + * + * try { + * accessSync('etc/passwd', constants.R_OK | constants.W_OK); + * console.log('can read/write'); + * } catch (err) { + * console.error('no access!'); + * } + * ``` + * @since v0.11.15 + * @param [mode=fs.constants.F_OK] + */ + function accessSync(path: PathLike, mode?: number): void; + interface StreamOptions { + flags?: string | undefined; + encoding?: BufferEncoding | undefined; + fd?: number | FileHandle | undefined; + mode?: number | undefined; + autoClose?: boolean | undefined; + emitClose?: boolean | undefined; + start?: number | undefined; + signal?: AbortSignal | null | undefined; + highWaterMark?: number | undefined; + } + interface FSImplementation { + open?: (...args: any[]) => any; + close?: (...args: any[]) => any; + } + interface CreateReadStreamFSImplementation extends FSImplementation { + read: (...args: any[]) => any; + } + interface CreateWriteStreamFSImplementation extends FSImplementation { + write: (...args: any[]) => any; + writev?: (...args: any[]) => any; + } + interface ReadStreamOptions extends StreamOptions { + fs?: CreateReadStreamFSImplementation | null | undefined; + end?: number | undefined; + } + interface WriteStreamOptions extends StreamOptions { + fs?: CreateWriteStreamFSImplementation | null | undefined; + flush?: boolean | undefined; + } + /** + * `options` can include `start` and `end` values to read a range of bytes from + * the file instead of the entire file. Both `start` and `end` are inclusive and + * start counting at 0, allowed values are in the + * \[0, [`Number.MAX_SAFE_INTEGER`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER)\] range. If `fd` is specified and `start` is + * omitted or `undefined`, `fs.createReadStream()` reads sequentially from the + * current file position. The `encoding` can be any one of those accepted by `Buffer`. + * + * If `fd` is specified, `ReadStream` will ignore the `path` argument and will use + * the specified file descriptor. This means that no `'open'` event will be + * emitted. `fd` should be blocking; non-blocking `fd`s should be passed to `net.Socket`. + * + * If `fd` points to a character device that only supports blocking reads + * (such as keyboard or sound card), read operations do not finish until data is + * available. This can prevent the process from exiting and the stream from + * closing naturally. + * + * By default, the stream will emit a `'close'` event after it has been + * destroyed. Set the `emitClose` option to `false` to change this behavior. + * + * By providing the `fs` option, it is possible to override the corresponding `fs` implementations for `open`, `read`, and `close`. When providing the `fs` option, + * an override for `read` is required. If no `fd` is provided, an override for `open` is also required. If `autoClose` is `true`, an override for `close` is + * also required. + * + * ```js + * import { createReadStream } from 'node:fs'; + * + * // Create a stream from some character device. + * const stream = createReadStream('/dev/input/event0'); + * setTimeout(() => { + * stream.close(); // This may not close the stream. + * // Artificially marking end-of-stream, as if the underlying resource had + * // indicated end-of-file by itself, allows the stream to close. + * // This does not cancel pending read operations, and if there is such an + * // operation, the process may still not be able to exit successfully + * // until it finishes. + * stream.push(null); + * stream.read(0); + * }, 100); + * ``` + * + * If `autoClose` is false, then the file descriptor won't be closed, even if + * there's an error. It is the application's responsibility to close it and make + * sure there's no file descriptor leak. If `autoClose` is set to true (default + * behavior), on `'error'` or `'end'` the file descriptor will be closed + * automatically. + * + * `mode` sets the file mode (permission and sticky bits), but only if the + * file was created. + * + * An example to read the last 10 bytes of a file which is 100 bytes long: + * + * ```js + * import { createReadStream } from 'node:fs'; + * + * createReadStream('sample.txt', { start: 90, end: 99 }); + * ``` + * + * If `options` is a string, then it specifies the encoding. + * @since v0.1.31 + */ + function createReadStream(path: PathLike, options?: BufferEncoding | ReadStreamOptions): ReadStream; + /** + * `options` may also include a `start` option to allow writing data at some + * position past the beginning of the file, allowed values are in the + * \[0, [`Number.MAX_SAFE_INTEGER`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER)\] range. Modifying a file rather than + * replacing it may require the `flags` option to be set to `r+` rather than the + * default `w`. The `encoding` can be any one of those accepted by `Buffer`. + * + * If `autoClose` is set to true (default behavior) on `'error'` or `'finish'` the file descriptor will be closed automatically. If `autoClose` is false, + * then the file descriptor won't be closed, even if there's an error. + * It is the application's responsibility to close it and make sure there's no + * file descriptor leak. + * + * By default, the stream will emit a `'close'` event after it has been + * destroyed. Set the `emitClose` option to `false` to change this behavior. + * + * By providing the `fs` option it is possible to override the corresponding `fs` implementations for `open`, `write`, `writev`, and `close`. Overriding `write()` without `writev()` can reduce + * performance as some optimizations (`_writev()`) + * will be disabled. When providing the `fs` option, overrides for at least one of `write` and `writev` are required. If no `fd` option is supplied, an override + * for `open` is also required. If `autoClose` is `true`, an override for `close` is also required. + * + * Like `fs.ReadStream`, if `fd` is specified, `fs.WriteStream` will ignore the `path` argument and will use the specified file descriptor. This means that no `'open'` event will be + * emitted. `fd` should be blocking; non-blocking `fd`s + * should be passed to `net.Socket`. + * + * If `options` is a string, then it specifies the encoding. + * @since v0.1.31 + */ + function createWriteStream(path: PathLike, options?: BufferEncoding | WriteStreamOptions): WriteStream; + /** + * Forces all currently queued I/O operations associated with the file to the + * operating system's synchronized I/O completion state. Refer to the POSIX [`fdatasync(2)`](http://man7.org/linux/man-pages/man2/fdatasync.2.html) documentation for details. No arguments other + * than a possible + * exception are given to the completion callback. + * @since v0.1.96 + */ + function fdatasync(fd: number, callback: NoParamCallback): void; + namespace fdatasync { + /** + * Asynchronous fdatasync(2) - synchronize a file's in-core state with storage device. + * @param fd A file descriptor. + */ + function __promisify__(fd: number): Promise<void>; + } + /** + * Forces all currently queued I/O operations associated with the file to the + * operating system's synchronized I/O completion state. Refer to the POSIX [`fdatasync(2)`](http://man7.org/linux/man-pages/man2/fdatasync.2.html) documentation for details. Returns `undefined`. + * @since v0.1.96 + */ + function fdatasyncSync(fd: number): void; + /** + * Asynchronously copies `src` to `dest`. By default, `dest` is overwritten if it + * already exists. No arguments other than a possible exception are given to the + * callback function. Node.js makes no guarantees about the atomicity of the copy + * operation. If an error occurs after the destination file has been opened for + * writing, Node.js will attempt to remove the destination. + * + * `mode` is an optional integer that specifies the behavior + * of the copy operation. It is possible to create a mask consisting of the bitwise + * OR of two or more values (e.g.`fs.constants.COPYFILE_EXCL | fs.constants.COPYFILE_FICLONE`). + * + * * `fs.constants.COPYFILE_EXCL`: The copy operation will fail if `dest` already + * exists. + * * `fs.constants.COPYFILE_FICLONE`: The copy operation will attempt to create a + * copy-on-write reflink. If the platform does not support copy-on-write, then a + * fallback copy mechanism is used. + * * `fs.constants.COPYFILE_FICLONE_FORCE`: The copy operation will attempt to + * create a copy-on-write reflink. If the platform does not support + * copy-on-write, then the operation will fail. + * + * ```js + * import { copyFile, constants } from 'node:fs'; + * + * function callback(err) { + * if (err) throw err; + * console.log('source.txt was copied to destination.txt'); + * } + * + * // destination.txt will be created or overwritten by default. + * copyFile('source.txt', 'destination.txt', callback); + * + * // By using COPYFILE_EXCL, the operation will fail if destination.txt exists. + * copyFile('source.txt', 'destination.txt', constants.COPYFILE_EXCL, callback); + * ``` + * @since v8.5.0 + * @param src source filename to copy + * @param dest destination filename of the copy operation + * @param [mode=0] modifiers for copy operation. + */ + function copyFile(src: PathLike, dest: PathLike, callback: NoParamCallback): void; + function copyFile(src: PathLike, dest: PathLike, mode: number, callback: NoParamCallback): void; + namespace copyFile { + function __promisify__(src: PathLike, dst: PathLike, mode?: number): Promise<void>; + } + /** + * Synchronously copies `src` to `dest`. By default, `dest` is overwritten if it + * already exists. Returns `undefined`. Node.js makes no guarantees about the + * atomicity of the copy operation. If an error occurs after the destination file + * has been opened for writing, Node.js will attempt to remove the destination. + * + * `mode` is an optional integer that specifies the behavior + * of the copy operation. It is possible to create a mask consisting of the bitwise + * OR of two or more values (e.g.`fs.constants.COPYFILE_EXCL | fs.constants.COPYFILE_FICLONE`). + * + * * `fs.constants.COPYFILE_EXCL`: The copy operation will fail if `dest` already + * exists. + * * `fs.constants.COPYFILE_FICLONE`: The copy operation will attempt to create a + * copy-on-write reflink. If the platform does not support copy-on-write, then a + * fallback copy mechanism is used. + * * `fs.constants.COPYFILE_FICLONE_FORCE`: The copy operation will attempt to + * create a copy-on-write reflink. If the platform does not support + * copy-on-write, then the operation will fail. + * + * ```js + * import { copyFileSync, constants } from 'node:fs'; + * + * // destination.txt will be created or overwritten by default. + * copyFileSync('source.txt', 'destination.txt'); + * console.log('source.txt was copied to destination.txt'); + * + * // By using COPYFILE_EXCL, the operation will fail if destination.txt exists. + * copyFileSync('source.txt', 'destination.txt', constants.COPYFILE_EXCL); + * ``` + * @since v8.5.0 + * @param src source filename to copy + * @param dest destination filename of the copy operation + * @param [mode=0] modifiers for copy operation. + */ + function copyFileSync(src: PathLike, dest: PathLike, mode?: number): void; + /** + * Write an array of `ArrayBufferView`s to the file specified by `fd` using `writev()`. + * + * `position` is the offset from the beginning of the file where this data + * should be written. If `typeof position !== 'number'`, the data will be written + * at the current position. + * + * The callback will be given three arguments: `err`, `bytesWritten`, and `buffers`. `bytesWritten` is how many bytes were written from `buffers`. + * + * If this method is `util.promisify()` ed, it returns a promise for an `Object` with `bytesWritten` and `buffers` properties. + * + * It is unsafe to use `fs.writev()` multiple times on the same file without + * waiting for the callback. For this scenario, use {@link createWriteStream}. + * + * On Linux, positional writes don't work when the file is opened in append mode. + * The kernel ignores the position argument and always appends the data to + * the end of the file. + * @since v12.9.0 + * @param [position='null'] + */ + function writev<TBuffers extends readonly NodeJS.ArrayBufferView[]>( + fd: number, + buffers: TBuffers, + cb: (err: NodeJS.ErrnoException | null, bytesWritten: number, buffers: TBuffers) => void, + ): void; + function writev<TBuffers extends readonly NodeJS.ArrayBufferView[]>( + fd: number, + buffers: TBuffers, + position: number | null, + cb: (err: NodeJS.ErrnoException | null, bytesWritten: number, buffers: TBuffers) => void, + ): void; + // Providing a default type parameter doesn't provide true BC for userland consumers, but at least suppresses TS2314 + // TODO: remove default in future major version + interface WriteVResult<T extends readonly NodeJS.ArrayBufferView[] = NodeJS.ArrayBufferView[]> { + bytesWritten: number; + buffers: T; + } + namespace writev { + function __promisify__<TBuffers extends readonly NodeJS.ArrayBufferView[]>( + fd: number, + buffers: TBuffers, + position?: number, + ): Promise<WriteVResult<TBuffers>>; + } + /** + * For detailed information, see the documentation of the asynchronous version of + * this API: {@link writev}. + * @since v12.9.0 + * @param [position='null'] + * @return The number of bytes written. + */ + function writevSync(fd: number, buffers: readonly NodeJS.ArrayBufferView[], position?: number): number; + /** + * Read from a file specified by `fd` and write to an array of `ArrayBufferView`s + * using `readv()`. + * + * `position` is the offset from the beginning of the file from where data + * should be read. If `typeof position !== 'number'`, the data will be read + * from the current position. + * + * The callback will be given three arguments: `err`, `bytesRead`, and `buffers`. `bytesRead` is how many bytes were read from the file. + * + * If this method is invoked as its `util.promisify()` ed version, it returns + * a promise for an `Object` with `bytesRead` and `buffers` properties. + * @since v13.13.0, v12.17.0 + * @param [position='null'] + */ + function readv<TBuffers extends readonly NodeJS.ArrayBufferView[]>( + fd: number, + buffers: TBuffers, + cb: (err: NodeJS.ErrnoException | null, bytesRead: number, buffers: TBuffers) => void, + ): void; + function readv<TBuffers extends readonly NodeJS.ArrayBufferView[]>( + fd: number, + buffers: TBuffers, + position: number | null, + cb: (err: NodeJS.ErrnoException | null, bytesRead: number, buffers: TBuffers) => void, + ): void; + // Providing a default type parameter doesn't provide true BC for userland consumers, but at least suppresses TS2314 + // TODO: remove default in future major version + interface ReadVResult<T extends readonly NodeJS.ArrayBufferView[] = NodeJS.ArrayBufferView[]> { + bytesRead: number; + buffers: T; + } + namespace readv { + function __promisify__<TBuffers extends readonly NodeJS.ArrayBufferView[]>( + fd: number, + buffers: TBuffers, + position?: number, + ): Promise<ReadVResult<TBuffers>>; + } + /** + * For detailed information, see the documentation of the asynchronous version of + * this API: {@link readv}. + * @since v13.13.0, v12.17.0 + * @param [position='null'] + * @return The number of bytes read. + */ + function readvSync(fd: number, buffers: readonly NodeJS.ArrayBufferView[], position?: number): number; + + interface OpenAsBlobOptions { + /** + * An optional mime type for the blob. + * + * @default 'undefined' + */ + type?: string | undefined; + } + + /** + * Returns a `Blob` whose data is backed by the given file. + * + * The file must not be modified after the `Blob` is created. Any modifications + * will cause reading the `Blob` data to fail with a `DOMException` error. + * Synchronous stat operations on the file when the `Blob` is created, and before + * each read in order to detect whether the file data has been modified on disk. + * + * ```js + * import { openAsBlob } from 'node:fs'; + * + * const blob = await openAsBlob('the.file.txt'); + * const ab = await blob.arrayBuffer(); + * blob.stream(); + * ``` + * @since v19.8.0 + */ + function openAsBlob(path: PathLike, options?: OpenAsBlobOptions): Promise<Blob>; + + interface OpenDirOptions { + /** + * @default 'utf8' + */ + encoding?: BufferEncoding | undefined; + /** + * Number of directory entries that are buffered + * internally when reading from the directory. Higher values lead to better + * performance but higher memory usage. + * @default 32 + */ + bufferSize?: number | undefined; + /** + * @default false + */ + recursive?: boolean | undefined; + } + /** + * Synchronously open a directory. See [`opendir(3)`](http://man7.org/linux/man-pages/man3/opendir.3.html). + * + * Creates an `fs.Dir`, which contains all further functions for reading from + * and cleaning up the directory. + * + * The `encoding` option sets the encoding for the `path` while opening the + * directory and subsequent read operations. + * @since v12.12.0 + */ + function opendirSync(path: PathLike, options?: OpenDirOptions): Dir; + /** + * Asynchronously open a directory. See the POSIX [`opendir(3)`](http://man7.org/linux/man-pages/man3/opendir.3.html) documentation for + * more details. + * + * Creates an `fs.Dir`, which contains all further functions for reading from + * and cleaning up the directory. + * + * The `encoding` option sets the encoding for the `path` while opening the + * directory and subsequent read operations. + * @since v12.12.0 + */ + function opendir(path: PathLike, cb: (err: NodeJS.ErrnoException | null, dir: Dir) => void): void; + function opendir( + path: PathLike, + options: OpenDirOptions, + cb: (err: NodeJS.ErrnoException | null, dir: Dir) => void, + ): void; + namespace opendir { + function __promisify__(path: PathLike, options?: OpenDirOptions): Promise<Dir>; + } + interface BigIntStats extends StatsBase<bigint> { + atimeNs: bigint; + mtimeNs: bigint; + ctimeNs: bigint; + birthtimeNs: bigint; + } + interface BigIntOptions { + bigint: true; + } + interface StatOptions { + bigint?: boolean | undefined; + } + interface StatSyncOptions extends StatOptions { + throwIfNoEntry?: boolean | undefined; + } + interface CopyOptionsBase { + /** + * Dereference symlinks + * @default false + */ + dereference?: boolean | undefined; + /** + * When `force` is `false`, and the destination + * exists, throw an error. + * @default false + */ + errorOnExist?: boolean | undefined; + /** + * Overwrite existing file or directory. _The copy + * operation will ignore errors if you set this to false and the destination + * exists. Use the `errorOnExist` option to change this behavior. + * @default true + */ + force?: boolean | undefined; + /** + * Modifiers for copy operation. See `mode` flag of {@link copyFileSync()} + */ + mode?: number | undefined; + /** + * When `true` timestamps from `src` will + * be preserved. + * @default false + */ + preserveTimestamps?: boolean | undefined; + /** + * Copy directories recursively. + * @default false + */ + recursive?: boolean | undefined; + /** + * When true, path resolution for symlinks will be skipped + * @default false + */ + verbatimSymlinks?: boolean | undefined; + } + interface CopyOptions extends CopyOptionsBase { + /** + * Function to filter copied files/directories. Return + * `true` to copy the item, `false` to ignore it. + */ + filter?: ((source: string, destination: string) => boolean | Promise<boolean>) | undefined; + } + interface CopySyncOptions extends CopyOptionsBase { + /** + * Function to filter copied files/directories. Return + * `true` to copy the item, `false` to ignore it. + */ + filter?: ((source: string, destination: string) => boolean) | undefined; + } + /** + * Asynchronously copies the entire directory structure from `src` to `dest`, + * including subdirectories and files. + * + * When copying a directory to another directory, globs are not supported and + * behavior is similar to `cp dir1/ dir2/`. + * @since v16.7.0 + * @experimental + * @param src source path to copy. + * @param dest destination path to copy to. + */ + function cp( + source: string | URL, + destination: string | URL, + callback: (err: NodeJS.ErrnoException | null) => void, + ): void; + function cp( + source: string | URL, + destination: string | URL, + opts: CopyOptions, + callback: (err: NodeJS.ErrnoException | null) => void, + ): void; + /** + * Synchronously copies the entire directory structure from `src` to `dest`, + * including subdirectories and files. + * + * When copying a directory to another directory, globs are not supported and + * behavior is similar to `cp dir1/ dir2/`. + * @since v16.7.0 + * @experimental + * @param src source path to copy. + * @param dest destination path to copy to. + */ + function cpSync(source: string | URL, destination: string | URL, opts?: CopySyncOptions): void; + + // TODO: collapse + interface _GlobOptions<T extends Dirent | string> { + /** + * Current working directory. + * @default process.cwd() + */ + cwd?: string | URL | undefined; + /** + * `true` if the glob should return paths as `Dirent`s, `false` otherwise. + * @default false + * @since v22.2.0 + */ + withFileTypes?: boolean | undefined; + /** + * Function to filter out files/directories or a + * list of glob patterns to be excluded. If a function is provided, return + * `true` to exclude the item, `false` to include it. + * If a string array is provided, each string should be a glob pattern that + * specifies paths to exclude. Note: Negation patterns (e.g., '!foo.js') are + * not supported. + * @default undefined + */ + exclude?: ((fileName: T) => boolean) | readonly string[] | undefined; + } + interface GlobOptions extends _GlobOptions<Dirent | string> {} + interface GlobOptionsWithFileTypes extends _GlobOptions<Dirent> { + withFileTypes: true; + } + interface GlobOptionsWithoutFileTypes extends _GlobOptions<string> { + withFileTypes?: false | undefined; + } + + /** + * Retrieves the files matching the specified pattern. + * + * ```js + * import { glob } from 'node:fs'; + * + * glob('*.js', (err, matches) => { + * if (err) throw err; + * console.log(matches); + * }); + * ``` + * @since v22.0.0 + */ + function glob( + pattern: string | readonly string[], + callback: (err: NodeJS.ErrnoException | null, matches: string[]) => void, + ): void; + function glob( + pattern: string | readonly string[], + options: GlobOptionsWithFileTypes, + callback: ( + err: NodeJS.ErrnoException | null, + matches: Dirent[], + ) => void, + ): void; + function glob( + pattern: string | readonly string[], + options: GlobOptionsWithoutFileTypes, + callback: ( + err: NodeJS.ErrnoException | null, + matches: string[], + ) => void, + ): void; + function glob( + pattern: string | readonly string[], + options: GlobOptions, + callback: ( + err: NodeJS.ErrnoException | null, + matches: Dirent[] | string[], + ) => void, + ): void; + /** + * ```js + * import { globSync } from 'node:fs'; + * + * console.log(globSync('*.js')); + * ``` + * @since v22.0.0 + * @returns paths of files that match the pattern. + */ + function globSync(pattern: string | readonly string[]): string[]; + function globSync( + pattern: string | readonly string[], + options: GlobOptionsWithFileTypes, + ): Dirent[]; + function globSync( + pattern: string | readonly string[], + options: GlobOptionsWithoutFileTypes, + ): string[]; + function globSync( + pattern: string | readonly string[], + options: GlobOptions, + ): Dirent[] | string[]; +} +declare module "node:fs" { + export * as promises from "node:fs/promises"; +} +declare module "fs" { + export * from "node:fs"; +} diff --git a/server/node_modules/@types/node/fs/promises.d.ts b/server/node_modules/@types/node/fs/promises.d.ts new file mode 100644 index 0000000..e4d249d --- /dev/null +++ b/server/node_modules/@types/node/fs/promises.d.ts @@ -0,0 +1,1329 @@ +/** + * The `fs/promises` API provides asynchronous file system methods that return + * promises. + * + * The promise APIs use the underlying Node.js threadpool to perform file + * system operations off the event loop thread. These operations are not + * synchronized or threadsafe. Care must be taken when performing multiple + * concurrent modifications on the same file or data corruption may occur. + * @since v10.0.0 + */ +declare module "node:fs/promises" { + import { NonSharedBuffer } from "node:buffer"; + import { Abortable } from "node:events"; + import { Interface as ReadlineInterface } from "node:readline"; + import { + BigIntStats, + BigIntStatsFs, + BufferEncodingOption, + constants as fsConstants, + CopyOptions, + Dir, + Dirent, + EncodingOption, + GlobOptions, + GlobOptionsWithFileTypes, + GlobOptionsWithoutFileTypes, + MakeDirectoryOptions, + Mode, + ObjectEncodingOptions, + OpenDirOptions, + OpenMode, + PathLike, + ReadOptions, + ReadOptionsWithBuffer, + ReadPosition, + ReadStream, + ReadVResult, + RmOptions, + StatFsOptions, + StatOptions, + Stats, + StatsFs, + TimeLike, + WatchEventType, + WatchOptions as _WatchOptions, + WriteStream, + WriteVResult, + } from "node:fs"; + import { Stream } from "node:stream"; + import { ReadableStream } from "node:stream/web"; + interface FileChangeInfo<T extends string | Buffer> { + eventType: WatchEventType; + filename: T | null; + } + interface FlagAndOpenMode { + mode?: Mode | undefined; + flag?: OpenMode | undefined; + } + interface FileReadResult<T extends NodeJS.ArrayBufferView> { + bytesRead: number; + buffer: T; + } + /** @deprecated This interface will be removed in a future version. Use `import { ReadOptionsWithBuffer } from "node:fs"` instead. */ + interface FileReadOptions<T extends NodeJS.ArrayBufferView = Buffer> { + /** + * @default `Buffer.alloc(0xffff)` + */ + buffer?: T; + /** + * @default 0 + */ + offset?: number | null; + /** + * @default `buffer.byteLength` + */ + length?: number | null; + position?: ReadPosition | null; + } + interface CreateReadStreamOptions extends Abortable { + encoding?: BufferEncoding | null | undefined; + autoClose?: boolean | undefined; + emitClose?: boolean | undefined; + start?: number | undefined; + end?: number | undefined; + highWaterMark?: number | undefined; + } + interface CreateWriteStreamOptions { + encoding?: BufferEncoding | null | undefined; + autoClose?: boolean | undefined; + emitClose?: boolean | undefined; + start?: number | undefined; + highWaterMark?: number | undefined; + flush?: boolean | undefined; + } + interface ReadableWebStreamOptions { + autoClose?: boolean | undefined; + } + // TODO: Add `EventEmitter` close + interface FileHandle { + /** + * The numeric file descriptor managed by the {FileHandle} object. + * @since v10.0.0 + */ + readonly fd: number; + /** + * Alias of `filehandle.writeFile()`. + * + * When operating on file handles, the mode cannot be changed from what it was set + * to with `fsPromises.open()`. Therefore, this is equivalent to `filehandle.writeFile()`. + * @since v10.0.0 + * @return Fulfills with `undefined` upon success. + */ + appendFile( + data: string | Uint8Array, + options?: + | (ObjectEncodingOptions & Abortable) + | BufferEncoding + | null, + ): Promise<void>; + /** + * Changes the ownership of the file. A wrapper for [`chown(2)`](http://man7.org/linux/man-pages/man2/chown.2.html). + * @since v10.0.0 + * @param uid The file's new owner's user id. + * @param gid The file's new group's group id. + * @return Fulfills with `undefined` upon success. + */ + chown(uid: number, gid: number): Promise<void>; + /** + * Modifies the permissions on the file. See [`chmod(2)`](http://man7.org/linux/man-pages/man2/chmod.2.html). + * @since v10.0.0 + * @param mode the file mode bit mask. + * @return Fulfills with `undefined` upon success. + */ + chmod(mode: Mode): Promise<void>; + /** + * Unlike the 16 KiB default `highWaterMark` for a `stream.Readable`, the stream + * returned by this method has a default `highWaterMark` of 64 KiB. + * + * `options` can include `start` and `end` values to read a range of bytes from + * the file instead of the entire file. Both `start` and `end` are inclusive and + * start counting at 0, allowed values are in the + * \[0, [`Number.MAX_SAFE_INTEGER`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER)\] range. If `start` is + * omitted or `undefined`, `filehandle.createReadStream()` reads sequentially from + * the current file position. The `encoding` can be any one of those accepted by `Buffer`. + * + * If the `FileHandle` points to a character device that only supports blocking + * reads (such as keyboard or sound card), read operations do not finish until data + * is available. This can prevent the process from exiting and the stream from + * closing naturally. + * + * By default, the stream will emit a `'close'` event after it has been + * destroyed. Set the `emitClose` option to `false` to change this behavior. + * + * ```js + * import { open } from 'node:fs/promises'; + * + * const fd = await open('/dev/input/event0'); + * // Create a stream from some character device. + * const stream = fd.createReadStream(); + * setTimeout(() => { + * stream.close(); // This may not close the stream. + * // Artificially marking end-of-stream, as if the underlying resource had + * // indicated end-of-file by itself, allows the stream to close. + * // This does not cancel pending read operations, and if there is such an + * // operation, the process may still not be able to exit successfully + * // until it finishes. + * stream.push(null); + * stream.read(0); + * }, 100); + * ``` + * + * If `autoClose` is false, then the file descriptor won't be closed, even if + * there's an error. It is the application's responsibility to close it and make + * sure there's no file descriptor leak. If `autoClose` is set to true (default + * behavior), on `'error'` or `'end'` the file descriptor will be closed + * automatically. + * + * An example to read the last 10 bytes of a file which is 100 bytes long: + * + * ```js + * import { open } from 'node:fs/promises'; + * + * const fd = await open('sample.txt'); + * fd.createReadStream({ start: 90, end: 99 }); + * ``` + * @since v16.11.0 + */ + createReadStream(options?: CreateReadStreamOptions): ReadStream; + /** + * `options` may also include a `start` option to allow writing data at some + * position past the beginning of the file, allowed values are in the + * \[0, [`Number.MAX_SAFE_INTEGER`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER)\] range. Modifying a file rather than + * replacing it may require the `flags` `open` option to be set to `r+` rather than + * the default `r`. The `encoding` can be any one of those accepted by `Buffer`. + * + * If `autoClose` is set to true (default behavior) on `'error'` or `'finish'` the file descriptor will be closed automatically. If `autoClose` is false, + * then the file descriptor won't be closed, even if there's an error. + * It is the application's responsibility to close it and make sure there's no + * file descriptor leak. + * + * By default, the stream will emit a `'close'` event after it has been + * destroyed. Set the `emitClose` option to `false` to change this behavior. + * @since v16.11.0 + */ + createWriteStream(options?: CreateWriteStreamOptions): WriteStream; + /** + * Forces all currently queued I/O operations associated with the file to the + * operating system's synchronized I/O completion state. Refer to the POSIX [`fdatasync(2)`](http://man7.org/linux/man-pages/man2/fdatasync.2.html) documentation for details. + * + * Unlike `filehandle.sync` this method does not flush modified metadata. + * @since v10.0.0 + * @return Fulfills with `undefined` upon success. + */ + datasync(): Promise<void>; + /** + * Request that all data for the open file descriptor is flushed to the storage + * device. The specific implementation is operating system and device specific. + * Refer to the POSIX [`fsync(2)`](http://man7.org/linux/man-pages/man2/fsync.2.html) documentation for more detail. + * @since v10.0.0 + * @return Fulfills with `undefined` upon success. + */ + sync(): Promise<void>; + /** + * Reads data from the file and stores that in the given buffer. + * + * If the file is not modified concurrently, the end-of-file is reached when the + * number of bytes read is zero. + * @since v10.0.0 + * @param buffer A buffer that will be filled with the file data read. + * @param offset The location in the buffer at which to start filling. + * @param length The number of bytes to read. + * @param position The location where to begin reading data from the file. If `null`, data will be read from the current file position, and the position will be updated. If `position` is an + * integer, the current file position will remain unchanged. + * @return Fulfills upon success with an object with two properties: + */ + read<T extends NodeJS.ArrayBufferView>( + buffer: T, + offset?: number | null, + length?: number | null, + position?: ReadPosition | null, + ): Promise<FileReadResult<T>>; + read<T extends NodeJS.ArrayBufferView>( + buffer: T, + options?: ReadOptions, + ): Promise<FileReadResult<T>>; + read<T extends NodeJS.ArrayBufferView = NonSharedBuffer>( + options?: ReadOptionsWithBuffer<T>, + ): Promise<FileReadResult<T>>; + /** + * Returns a byte-oriented `ReadableStream` that may be used to read the file's + * contents. + * + * An error will be thrown if this method is called more than once or is called + * after the `FileHandle` is closed or closing. + * + * ```js + * import { + * open, + * } from 'node:fs/promises'; + * + * const file = await open('./some/file/to/read'); + * + * for await (const chunk of file.readableWebStream()) + * console.log(chunk); + * + * await file.close(); + * ``` + * + * While the `ReadableStream` will read the file to completion, it will not + * close the `FileHandle` automatically. User code must still call the`fileHandle.close()` method. + * @since v17.0.0 + */ + readableWebStream(options?: ReadableWebStreamOptions): ReadableStream; + /** + * Asynchronously reads the entire contents of a file. + * + * If `options` is a string, then it specifies the `encoding`. + * + * The `FileHandle` has to support reading. + * + * If one or more `filehandle.read()` calls are made on a file handle and then a `filehandle.readFile()` call is made, the data will be read from the current + * position till the end of the file. It doesn't always read from the beginning + * of the file. + * @since v10.0.0 + * @return Fulfills upon a successful read with the contents of the file. If no encoding is specified (using `options.encoding`), the data is returned as a {Buffer} object. Otherwise, the + * data will be a string. + */ + readFile( + options?: + | ({ encoding?: null | undefined } & Abortable) + | null, + ): Promise<NonSharedBuffer>; + /** + * Asynchronously reads the entire contents of a file. The underlying file will _not_ be closed automatically. + * The `FileHandle` must have been opened for reading. + */ + readFile( + options: + | ({ encoding: BufferEncoding } & Abortable) + | BufferEncoding, + ): Promise<string>; + /** + * Asynchronously reads the entire contents of a file. The underlying file will _not_ be closed automatically. + * The `FileHandle` must have been opened for reading. + */ + readFile( + options?: + | (ObjectEncodingOptions & Abortable) + | BufferEncoding + | null, + ): Promise<string | NonSharedBuffer>; + /** + * Convenience method to create a `readline` interface and stream over the file. + * See `filehandle.createReadStream()` for the options. + * + * ```js + * import { open } from 'node:fs/promises'; + * + * const file = await open('./some/file/to/read'); + * + * for await (const line of file.readLines()) { + * console.log(line); + * } + * ``` + * @since v18.11.0 + */ + readLines(options?: CreateReadStreamOptions): ReadlineInterface; + /** + * @since v10.0.0 + * @return Fulfills with an {fs.Stats} for the file. + */ + stat( + opts?: StatOptions & { + bigint?: false | undefined; + }, + ): Promise<Stats>; + stat( + opts: StatOptions & { + bigint: true; + }, + ): Promise<BigIntStats>; + stat(opts?: StatOptions): Promise<Stats | BigIntStats>; + /** + * Truncates the file. + * + * If the file was larger than `len` bytes, only the first `len` bytes will be + * retained in the file. + * + * The following example retains only the first four bytes of the file: + * + * ```js + * import { open } from 'node:fs/promises'; + * + * let filehandle = null; + * try { + * filehandle = await open('temp.txt', 'r+'); + * await filehandle.truncate(4); + * } finally { + * await filehandle?.close(); + * } + * ``` + * + * If the file previously was shorter than `len` bytes, it is extended, and the + * extended part is filled with null bytes (`'\0'`): + * + * If `len` is negative then `0` will be used. + * @since v10.0.0 + * @param [len=0] + * @return Fulfills with `undefined` upon success. + */ + truncate(len?: number): Promise<void>; + /** + * Change the file system timestamps of the object referenced by the `FileHandle` then fulfills the promise with no arguments upon success. + * @since v10.0.0 + */ + utimes(atime: TimeLike, mtime: TimeLike): Promise<void>; + /** + * Asynchronously writes data to a file, replacing the file if it already exists. `data` can be a string, a buffer, an + * [AsyncIterable](https://tc39.github.io/ecma262/#sec-asynciterable-interface), or an + * [Iterable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#The_iterable_protocol) object. + * The promise is fulfilled with no arguments upon success. + * + * If `options` is a string, then it specifies the `encoding`. + * + * The `FileHandle` has to support writing. + * + * It is unsafe to use `filehandle.writeFile()` multiple times on the same file + * without waiting for the promise to be fulfilled (or rejected). + * + * If one or more `filehandle.write()` calls are made on a file handle and then a`filehandle.writeFile()` call is made, the data will be written from the + * current position till the end of the file. It doesn't always write from the + * beginning of the file. + * @since v10.0.0 + */ + writeFile( + data: string | Uint8Array, + options?: + | (ObjectEncodingOptions & Abortable) + | BufferEncoding + | null, + ): Promise<void>; + /** + * Write `buffer` to the file. + * + * The promise is fulfilled with an object containing two properties: + * + * It is unsafe to use `filehandle.write()` multiple times on the same file + * without waiting for the promise to be fulfilled (or rejected). For this + * scenario, use `filehandle.createWriteStream()`. + * + * On Linux, positional writes do not work when the file is opened in append mode. + * The kernel ignores the position argument and always appends the data to + * the end of the file. + * @since v10.0.0 + * @param offset The start position from within `buffer` where the data to write begins. + * @param [length=buffer.byteLength - offset] The number of bytes from `buffer` to write. + * @param [position='null'] The offset from the beginning of the file where the data from `buffer` should be written. If `position` is not a `number`, the data will be written at the current + * position. See the POSIX pwrite(2) documentation for more detail. + */ + write<TBuffer extends NodeJS.ArrayBufferView>( + buffer: TBuffer, + offset?: number | null, + length?: number | null, + position?: number | null, + ): Promise<{ + bytesWritten: number; + buffer: TBuffer; + }>; + write<TBuffer extends Uint8Array>( + buffer: TBuffer, + options?: { offset?: number; length?: number; position?: number }, + ): Promise<{ + bytesWritten: number; + buffer: TBuffer; + }>; + write( + data: string, + position?: number | null, + encoding?: BufferEncoding | null, + ): Promise<{ + bytesWritten: number; + buffer: string; + }>; + /** + * Write an array of [ArrayBufferView](https://developer.mozilla.org/en-US/docs/Web/API/ArrayBufferView) s to the file. + * + * The promise is fulfilled with an object containing a two properties: + * + * It is unsafe to call `writev()` multiple times on the same file without waiting + * for the promise to be fulfilled (or rejected). + * + * On Linux, positional writes don't work when the file is opened in append mode. + * The kernel ignores the position argument and always appends the data to + * the end of the file. + * @since v12.9.0 + * @param [position='null'] The offset from the beginning of the file where the data from `buffers` should be written. If `position` is not a `number`, the data will be written at the current + * position. + */ + writev<TBuffers extends readonly NodeJS.ArrayBufferView[]>( + buffers: TBuffers, + position?: number, + ): Promise<WriteVResult<TBuffers>>; + /** + * Read from a file and write to an array of [ArrayBufferView](https://developer.mozilla.org/en-US/docs/Web/API/ArrayBufferView) s + * @since v13.13.0, v12.17.0 + * @param [position='null'] The offset from the beginning of the file where the data should be read from. If `position` is not a `number`, the data will be read from the current position. + * @return Fulfills upon success an object containing two properties: + */ + readv<TBuffers extends readonly NodeJS.ArrayBufferView[]>( + buffers: TBuffers, + position?: number, + ): Promise<ReadVResult<TBuffers>>; + /** + * Closes the file handle after waiting for any pending operation on the handle to + * complete. + * + * ```js + * import { open } from 'node:fs/promises'; + * + * let filehandle; + * try { + * filehandle = await open('thefile.txt', 'r'); + * } finally { + * await filehandle?.close(); + * } + * ``` + * @since v10.0.0 + * @return Fulfills with `undefined` upon success. + */ + close(): Promise<void>; + /** + * Calls `filehandle.close()` and returns a promise that fulfills when the + * filehandle is closed. + * @since v20.4.0, v18.8.0 + */ + [Symbol.asyncDispose](): Promise<void>; + } + const constants: typeof fsConstants; + /** + * Tests a user's permissions for the file or directory specified by `path`. + * The `mode` argument is an optional integer that specifies the accessibility + * checks to be performed. `mode` should be either the value `fs.constants.F_OK` or a mask consisting of the bitwise OR of any of `fs.constants.R_OK`, `fs.constants.W_OK`, and `fs.constants.X_OK` + * (e.g.`fs.constants.W_OK | fs.constants.R_OK`). Check `File access constants` for + * possible values of `mode`. + * + * If the accessibility check is successful, the promise is fulfilled with no + * value. If any of the accessibility checks fail, the promise is rejected + * with an [Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) object. The following example checks if the file`/etc/passwd` can be read and + * written by the current process. + * + * ```js + * import { access, constants } from 'node:fs/promises'; + * + * try { + * await access('/etc/passwd', constants.R_OK | constants.W_OK); + * console.log('can access'); + * } catch { + * console.error('cannot access'); + * } + * ``` + * + * Using `fsPromises.access()` to check for the accessibility of a file before + * calling `fsPromises.open()` is not recommended. Doing so introduces a race + * condition, since other processes may change the file's state between the two + * calls. Instead, user code should open/read/write the file directly and handle + * the error raised if the file is not accessible. + * @since v10.0.0 + * @param [mode=fs.constants.F_OK] + * @return Fulfills with `undefined` upon success. + */ + function access(path: PathLike, mode?: number): Promise<void>; + /** + * Asynchronously copies `src` to `dest`. By default, `dest` is overwritten if it + * already exists. + * + * No guarantees are made about the atomicity of the copy operation. If an + * error occurs after the destination file has been opened for writing, an attempt + * will be made to remove the destination. + * + * ```js + * import { copyFile, constants } from 'node:fs/promises'; + * + * try { + * await copyFile('source.txt', 'destination.txt'); + * console.log('source.txt was copied to destination.txt'); + * } catch { + * console.error('The file could not be copied'); + * } + * + * // By using COPYFILE_EXCL, the operation will fail if destination.txt exists. + * try { + * await copyFile('source.txt', 'destination.txt', constants.COPYFILE_EXCL); + * console.log('source.txt was copied to destination.txt'); + * } catch { + * console.error('The file could not be copied'); + * } + * ``` + * @since v10.0.0 + * @param src source filename to copy + * @param dest destination filename of the copy operation + * @param [mode=0] Optional modifiers that specify the behavior of the copy operation. It is possible to create a mask consisting of the bitwise OR of two or more values (e.g. + * `fs.constants.COPYFILE_EXCL | fs.constants.COPYFILE_FICLONE`) + * @return Fulfills with `undefined` upon success. + */ + function copyFile(src: PathLike, dest: PathLike, mode?: number): Promise<void>; + /** + * Opens a `FileHandle`. + * + * Refer to the POSIX [`open(2)`](http://man7.org/linux/man-pages/man2/open.2.html) documentation for more detail. + * + * Some characters (`< > : " / \ | ? *`) are reserved under Windows as documented + * by [Naming Files, Paths, and Namespaces](https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file). Under NTFS, if the filename contains + * a colon, Node.js will open a file system stream, as described by [this MSDN page](https://docs.microsoft.com/en-us/windows/desktop/FileIO/using-streams). + * @since v10.0.0 + * @param [flags='r'] See `support of file system `flags``. + * @param [mode=0o666] Sets the file mode (permission and sticky bits) if the file is created. + * @return Fulfills with a {FileHandle} object. + */ + function open(path: PathLike, flags?: string | number, mode?: Mode): Promise<FileHandle>; + /** + * Renames `oldPath` to `newPath`. + * @since v10.0.0 + * @return Fulfills with `undefined` upon success. + */ + function rename(oldPath: PathLike, newPath: PathLike): Promise<void>; + /** + * Truncates (shortens or extends the length) of the content at `path` to `len` bytes. + * @since v10.0.0 + * @param [len=0] + * @return Fulfills with `undefined` upon success. + */ + function truncate(path: PathLike, len?: number): Promise<void>; + /** + * Removes the directory identified by `path`. + * + * Using `fsPromises.rmdir()` on a file (not a directory) results in the + * promise being rejected with an `ENOENT` error on Windows and an `ENOTDIR` error on POSIX. + * + * To get a behavior similar to the `rm -rf` Unix command, use `fsPromises.rm()` with options `{ recursive: true, force: true }`. + * @since v10.0.0 + * @return Fulfills with `undefined` upon success. + */ + function rmdir(path: PathLike): Promise<void>; + /** + * Removes files and directories (modeled on the standard POSIX `rm` utility). + * @since v14.14.0 + * @return Fulfills with `undefined` upon success. + */ + function rm(path: PathLike, options?: RmOptions): Promise<void>; + /** + * Asynchronously creates a directory. + * + * The optional `options` argument can be an integer specifying `mode` (permission + * and sticky bits), or an object with a `mode` property and a `recursive` property indicating whether parent directories should be created. Calling `fsPromises.mkdir()` when `path` is a directory + * that exists results in a + * rejection only when `recursive` is false. + * + * ```js + * import { mkdir } from 'node:fs/promises'; + * + * try { + * const projectFolder = new URL('./test/project/', import.meta.url); + * const createDir = await mkdir(projectFolder, { recursive: true }); + * + * console.log(`created ${createDir}`); + * } catch (err) { + * console.error(err.message); + * } + * ``` + * @since v10.0.0 + * @return Upon success, fulfills with `undefined` if `recursive` is `false`, or the first directory path created if `recursive` is `true`. + */ + function mkdir( + path: PathLike, + options: MakeDirectoryOptions & { + recursive: true; + }, + ): Promise<string | undefined>; + /** + * Asynchronous mkdir(2) - create a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders + * should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`. + */ + function mkdir( + path: PathLike, + options?: + | Mode + | (MakeDirectoryOptions & { + recursive?: false | undefined; + }) + | null, + ): Promise<void>; + /** + * Asynchronous mkdir(2) - create a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders + * should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`. + */ + function mkdir(path: PathLike, options?: Mode | MakeDirectoryOptions | null): Promise<string | undefined>; + /** + * Reads the contents of a directory. + * + * The optional `options` argument can be a string specifying an encoding, or an + * object with an `encoding` property specifying the character encoding to use for + * the filenames. If the `encoding` is set to `'buffer'`, the filenames returned + * will be passed as `Buffer` objects. + * + * If `options.withFileTypes` is set to `true`, the returned array will contain `fs.Dirent` objects. + * + * ```js + * import { readdir } from 'node:fs/promises'; + * + * try { + * const files = await readdir(path); + * for (const file of files) + * console.log(file); + * } catch (err) { + * console.error(err); + * } + * ``` + * @since v10.0.0 + * @return Fulfills with an array of the names of the files in the directory excluding `'.'` and `'..'`. + */ + function readdir( + path: PathLike, + options?: + | (ObjectEncodingOptions & { + withFileTypes?: false | undefined; + recursive?: boolean | undefined; + }) + | BufferEncoding + | null, + ): Promise<string[]>; + /** + * Asynchronous readdir(3) - read a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function readdir( + path: PathLike, + options: + | { + encoding: "buffer"; + withFileTypes?: false | undefined; + recursive?: boolean | undefined; + } + | "buffer", + ): Promise<NonSharedBuffer[]>; + /** + * Asynchronous readdir(3) - read a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function readdir( + path: PathLike, + options?: + | (ObjectEncodingOptions & { + withFileTypes?: false | undefined; + recursive?: boolean | undefined; + }) + | BufferEncoding + | null, + ): Promise<string[] | NonSharedBuffer[]>; + /** + * Asynchronous readdir(3) - read a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options If called with `withFileTypes: true` the result data will be an array of Dirent. + */ + function readdir( + path: PathLike, + options: ObjectEncodingOptions & { + withFileTypes: true; + recursive?: boolean | undefined; + }, + ): Promise<Dirent[]>; + /** + * Asynchronous readdir(3) - read a directory. + * @param path A path to a directory. If a URL is provided, it must use the `file:` protocol. + * @param options Must include `withFileTypes: true` and `encoding: 'buffer'`. + */ + function readdir( + path: PathLike, + options: { + encoding: "buffer"; + withFileTypes: true; + recursive?: boolean | undefined; + }, + ): Promise<Dirent<NonSharedBuffer>[]>; + /** + * Reads the contents of the symbolic link referred to by `path`. See the POSIX [`readlink(2)`](http://man7.org/linux/man-pages/man2/readlink.2.html) documentation for more detail. The promise is + * fulfilled with the`linkString` upon success. + * + * The optional `options` argument can be a string specifying an encoding, or an + * object with an `encoding` property specifying the character encoding to use for + * the link path returned. If the `encoding` is set to `'buffer'`, the link path + * returned will be passed as a `Buffer` object. + * @since v10.0.0 + * @return Fulfills with the `linkString` upon success. + */ + function readlink(path: PathLike, options?: ObjectEncodingOptions | BufferEncoding | null): Promise<string>; + /** + * Asynchronous readlink(2) - read value of a symbolic link. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function readlink(path: PathLike, options: BufferEncodingOption): Promise<NonSharedBuffer>; + /** + * Asynchronous readlink(2) - read value of a symbolic link. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function readlink( + path: PathLike, + options?: ObjectEncodingOptions | string | null, + ): Promise<string | NonSharedBuffer>; + /** + * Creates a symbolic link. + * + * The `type` argument is only used on Windows platforms and can be one of `'dir'`, `'file'`, or `'junction'`. If the `type` argument is not a string, Node.js will + * autodetect `target` type and use `'file'` or `'dir'`. If the `target` does not + * exist, `'file'` will be used. Windows junction points require the destination + * path to be absolute. When using `'junction'`, the `target` argument will + * automatically be normalized to absolute path. Junction points on NTFS volumes + * can only point to directories. + * @since v10.0.0 + * @param [type='null'] + * @return Fulfills with `undefined` upon success. + */ + function symlink(target: PathLike, path: PathLike, type?: string | null): Promise<void>; + /** + * Equivalent to `fsPromises.stat()` unless `path` refers to a symbolic link, + * in which case the link itself is stat-ed, not the file that it refers to. + * Refer to the POSIX [`lstat(2)`](http://man7.org/linux/man-pages/man2/lstat.2.html) document for more detail. + * @since v10.0.0 + * @return Fulfills with the {fs.Stats} object for the given symbolic link `path`. + */ + function lstat( + path: PathLike, + opts?: StatOptions & { + bigint?: false | undefined; + }, + ): Promise<Stats>; + function lstat( + path: PathLike, + opts: StatOptions & { + bigint: true; + }, + ): Promise<BigIntStats>; + function lstat(path: PathLike, opts?: StatOptions): Promise<Stats | BigIntStats>; + /** + * @since v10.0.0 + * @return Fulfills with the {fs.Stats} object for the given `path`. + */ + function stat( + path: PathLike, + opts?: StatOptions & { + bigint?: false | undefined; + }, + ): Promise<Stats>; + function stat( + path: PathLike, + opts: StatOptions & { + bigint: true; + }, + ): Promise<BigIntStats>; + function stat(path: PathLike, opts?: StatOptions): Promise<Stats | BigIntStats>; + /** + * @since v19.6.0, v18.15.0 + * @return Fulfills with the {fs.StatFs} object for the given `path`. + */ + function statfs( + path: PathLike, + opts?: StatFsOptions & { + bigint?: false | undefined; + }, + ): Promise<StatsFs>; + function statfs( + path: PathLike, + opts: StatFsOptions & { + bigint: true; + }, + ): Promise<BigIntStatsFs>; + function statfs(path: PathLike, opts?: StatFsOptions): Promise<StatsFs | BigIntStatsFs>; + /** + * Creates a new link from the `existingPath` to the `newPath`. See the POSIX [`link(2)`](http://man7.org/linux/man-pages/man2/link.2.html) documentation for more detail. + * @since v10.0.0 + * @return Fulfills with `undefined` upon success. + */ + function link(existingPath: PathLike, newPath: PathLike): Promise<void>; + /** + * If `path` refers to a symbolic link, then the link is removed without affecting + * the file or directory to which that link refers. If the `path` refers to a file + * path that is not a symbolic link, the file is deleted. See the POSIX [`unlink(2)`](http://man7.org/linux/man-pages/man2/unlink.2.html) documentation for more detail. + * @since v10.0.0 + * @return Fulfills with `undefined` upon success. + */ + function unlink(path: PathLike): Promise<void>; + /** + * Changes the permissions of a file. + * @since v10.0.0 + * @return Fulfills with `undefined` upon success. + */ + function chmod(path: PathLike, mode: Mode): Promise<void>; + /** + * Changes the permissions on a symbolic link. + * + * This method is only implemented on macOS. + * @deprecated Since v10.0.0 + * @return Fulfills with `undefined` upon success. + */ + function lchmod(path: PathLike, mode: Mode): Promise<void>; + /** + * Changes the ownership on a symbolic link. + * @since v10.0.0 + * @return Fulfills with `undefined` upon success. + */ + function lchown(path: PathLike, uid: number, gid: number): Promise<void>; + /** + * Changes the access and modification times of a file in the same way as `fsPromises.utimes()`, with the difference that if the path refers to a + * symbolic link, then the link is not dereferenced: instead, the timestamps of + * the symbolic link itself are changed. + * @since v14.5.0, v12.19.0 + * @return Fulfills with `undefined` upon success. + */ + function lutimes(path: PathLike, atime: TimeLike, mtime: TimeLike): Promise<void>; + /** + * Changes the ownership of a file. + * @since v10.0.0 + * @return Fulfills with `undefined` upon success. + */ + function chown(path: PathLike, uid: number, gid: number): Promise<void>; + /** + * Change the file system timestamps of the object referenced by `path`. + * + * The `atime` and `mtime` arguments follow these rules: + * + * * Values can be either numbers representing Unix epoch time, `Date`s, or a + * numeric string like `'123456789.0'`. + * * If the value can not be converted to a number, or is `NaN`, `Infinity`, or `-Infinity`, an `Error` will be thrown. + * @since v10.0.0 + * @return Fulfills with `undefined` upon success. + */ + function utimes(path: PathLike, atime: TimeLike, mtime: TimeLike): Promise<void>; + /** + * Determines the actual location of `path` using the same semantics as the `fs.realpath.native()` function. + * + * Only paths that can be converted to UTF8 strings are supported. + * + * The optional `options` argument can be a string specifying an encoding, or an + * object with an `encoding` property specifying the character encoding to use for + * the path. If the `encoding` is set to `'buffer'`, the path returned will be + * passed as a `Buffer` object. + * + * On Linux, when Node.js is linked against musl libc, the procfs file system must + * be mounted on `/proc` in order for this function to work. Glibc does not have + * this restriction. + * @since v10.0.0 + * @return Fulfills with the resolved path upon success. + */ + function realpath(path: PathLike, options?: ObjectEncodingOptions | BufferEncoding | null): Promise<string>; + /** + * Asynchronous realpath(3) - return the canonicalized absolute pathname. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function realpath(path: PathLike, options: BufferEncodingOption): Promise<NonSharedBuffer>; + /** + * Asynchronous realpath(3) - return the canonicalized absolute pathname. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function realpath( + path: PathLike, + options?: ObjectEncodingOptions | BufferEncoding | null, + ): Promise<string | NonSharedBuffer>; + /** + * Creates a unique temporary directory. A unique directory name is generated by + * appending six random characters to the end of the provided `prefix`. Due to + * platform inconsistencies, avoid trailing `X` characters in `prefix`. Some + * platforms, notably the BSDs, can return more than six random characters, and + * replace trailing `X` characters in `prefix` with random characters. + * + * The optional `options` argument can be a string specifying an encoding, or an + * object with an `encoding` property specifying the character encoding to use. + * + * ```js + * import { mkdtemp } from 'node:fs/promises'; + * import { join } from 'node:path'; + * import { tmpdir } from 'node:os'; + * + * try { + * await mkdtemp(join(tmpdir(), 'foo-')); + * } catch (err) { + * console.error(err); + * } + * ``` + * + * The `fsPromises.mkdtemp()` method will append the six randomly selected + * characters directly to the `prefix` string. For instance, given a directory `/tmp`, if the intention is to create a temporary directory _within_ `/tmp`, the `prefix` must end with a trailing + * platform-specific path separator + * (`import { sep } from 'node:path'`). + * @since v10.0.0 + * @return Fulfills with a string containing the file system path of the newly created temporary directory. + */ + function mkdtemp(prefix: string, options?: ObjectEncodingOptions | BufferEncoding | null): Promise<string>; + /** + * Asynchronously creates a unique temporary directory. + * Generates six random characters to be appended behind a required `prefix` to create a unique temporary directory. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function mkdtemp(prefix: string, options: BufferEncodingOption): Promise<NonSharedBuffer>; + /** + * Asynchronously creates a unique temporary directory. + * Generates six random characters to be appended behind a required `prefix` to create a unique temporary directory. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used. + */ + function mkdtemp( + prefix: string, + options?: ObjectEncodingOptions | BufferEncoding | null, + ): Promise<string | NonSharedBuffer>; + interface DisposableTempDir extends AsyncDisposable { + /** + * The path of the created directory. + */ + path: string; + /** + * A function which removes the created directory. + */ + remove(): Promise<void>; + /** + * The same as `remove`. + */ + [Symbol.asyncDispose](): Promise<void>; + } + /** + * The resulting Promise holds an async-disposable object whose `path` property + * holds the created directory path. When the object is disposed, the directory + * and its contents will be removed asynchronously if it still exists. If the + * directory cannot be deleted, disposal will throw an error. The object has an + * async `remove()` method which will perform the same task. + * + * Both this function and the disposal function on the resulting object are + * async, so it should be used with `await` + `await using` as in + * `await using dir = await fsPromises.mkdtempDisposable('prefix')`. + * + * <!-- TODO: link MDN docs for disposables once https://github.com/mdn/content/pull/38027 lands --> + * + * For detailed information, see the documentation of `fsPromises.mkdtemp()`. + * + * The optional `options` argument can be a string specifying an encoding, or an + * object with an `encoding` property specifying the character encoding to use. + * @since v24.4.0 + */ + function mkdtempDisposable(prefix: PathLike, options?: EncodingOption): Promise<DisposableTempDir>; + /** + * Asynchronously writes data to a file, replacing the file if it already exists. `data` can be a string, a buffer, an + * [AsyncIterable](https://tc39.github.io/ecma262/#sec-asynciterable-interface), or an + * [Iterable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#The_iterable_protocol) object. + * + * The `encoding` option is ignored if `data` is a buffer. + * + * If `options` is a string, then it specifies the encoding. + * + * The `mode` option only affects the newly created file. See `fs.open()` for more details. + * + * Any specified `FileHandle` has to support writing. + * + * It is unsafe to use `fsPromises.writeFile()` multiple times on the same file + * without waiting for the promise to be settled. + * + * Similarly to `fsPromises.readFile` \- `fsPromises.writeFile` is a convenience + * method that performs multiple `write` calls internally to write the buffer + * passed to it. For performance sensitive code consider using `fs.createWriteStream()` or `filehandle.createWriteStream()`. + * + * It is possible to use an `AbortSignal` to cancel an `fsPromises.writeFile()`. + * Cancelation is "best effort", and some amount of data is likely still + * to be written. + * + * ```js + * import { writeFile } from 'node:fs/promises'; + * import { Buffer } from 'node:buffer'; + * + * try { + * const controller = new AbortController(); + * const { signal } = controller; + * const data = new Uint8Array(Buffer.from('Hello Node.js')); + * const promise = writeFile('message.txt', data, { signal }); + * + * // Abort the request before the promise settles. + * controller.abort(); + * + * await promise; + * } catch (err) { + * // When a request is aborted - err is an AbortError + * console.error(err); + * } + * ``` + * + * Aborting an ongoing request does not abort individual operating + * system requests but rather the internal buffering `fs.writeFile` performs. + * @since v10.0.0 + * @param file filename or `FileHandle` + * @return Fulfills with `undefined` upon success. + */ + function writeFile( + file: PathLike | FileHandle, + data: + | string + | NodeJS.ArrayBufferView + | Iterable<string | NodeJS.ArrayBufferView> + | AsyncIterable<string | NodeJS.ArrayBufferView> + | Stream, + options?: + | (ObjectEncodingOptions & { + mode?: Mode | undefined; + flag?: OpenMode | undefined; + /** + * If all data is successfully written to the file, and `flush` + * is `true`, `filehandle.sync()` is used to flush the data. + * @default false + */ + flush?: boolean | undefined; + } & Abortable) + | BufferEncoding + | null, + ): Promise<void>; + /** + * Asynchronously append data to a file, creating the file if it does not yet + * exist. `data` can be a string or a `Buffer`. + * + * If `options` is a string, then it specifies the `encoding`. + * + * The `mode` option only affects the newly created file. See `fs.open()` for more details. + * + * The `path` may be specified as a `FileHandle` that has been opened + * for appending (using `fsPromises.open()`). + * @since v10.0.0 + * @param path filename or {FileHandle} + * @return Fulfills with `undefined` upon success. + */ + function appendFile( + path: PathLike | FileHandle, + data: string | Uint8Array, + options?: (ObjectEncodingOptions & FlagAndOpenMode & { flush?: boolean | undefined }) | BufferEncoding | null, + ): Promise<void>; + /** + * Asynchronously reads the entire contents of a file. + * + * If no encoding is specified (using `options.encoding`), the data is returned + * as a `Buffer` object. Otherwise, the data will be a string. + * + * If `options` is a string, then it specifies the encoding. + * + * When the `path` is a directory, the behavior of `fsPromises.readFile()` is + * platform-specific. On macOS, Linux, and Windows, the promise will be rejected + * with an error. On FreeBSD, a representation of the directory's contents will be + * returned. + * + * An example of reading a `package.json` file located in the same directory of the + * running code: + * + * ```js + * import { readFile } from 'node:fs/promises'; + * try { + * const filePath = new URL('./package.json', import.meta.url); + * const contents = await readFile(filePath, { encoding: 'utf8' }); + * console.log(contents); + * } catch (err) { + * console.error(err.message); + * } + * ``` + * + * It is possible to abort an ongoing `readFile` using an `AbortSignal`. If a + * request is aborted the promise returned is rejected with an `AbortError`: + * + * ```js + * import { readFile } from 'node:fs/promises'; + * + * try { + * const controller = new AbortController(); + * const { signal } = controller; + * const promise = readFile(fileName, { signal }); + * + * // Abort the request before the promise settles. + * controller.abort(); + * + * await promise; + * } catch (err) { + * // When a request is aborted - err is an AbortError + * console.error(err); + * } + * ``` + * + * Aborting an ongoing request does not abort individual operating + * system requests but rather the internal buffering `fs.readFile` performs. + * + * Any specified `FileHandle` has to support reading. + * @since v10.0.0 + * @param path filename or `FileHandle` + * @return Fulfills with the contents of the file. + */ + function readFile( + path: PathLike | FileHandle, + options?: + | ({ + encoding?: null | undefined; + flag?: OpenMode | undefined; + } & Abortable) + | null, + ): Promise<NonSharedBuffer>; + /** + * Asynchronously reads the entire contents of a file. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * If a `FileHandle` is provided, the underlying file will _not_ be closed automatically. + * @param options An object that may contain an optional flag. + * If a flag is not provided, it defaults to `'r'`. + */ + function readFile( + path: PathLike | FileHandle, + options: + | ({ + encoding: BufferEncoding; + flag?: OpenMode | undefined; + } & Abortable) + | BufferEncoding, + ): Promise<string>; + /** + * Asynchronously reads the entire contents of a file. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * If a `FileHandle` is provided, the underlying file will _not_ be closed automatically. + * @param options An object that may contain an optional flag. + * If a flag is not provided, it defaults to `'r'`. + */ + function readFile( + path: PathLike | FileHandle, + options?: + | ( + & ObjectEncodingOptions + & Abortable + & { + flag?: OpenMode | undefined; + } + ) + | BufferEncoding + | null, + ): Promise<string | NonSharedBuffer>; + /** + * Asynchronously open a directory for iterative scanning. See the POSIX [`opendir(3)`](http://man7.org/linux/man-pages/man3/opendir.3.html) documentation for more detail. + * + * Creates an `fs.Dir`, which contains all further functions for reading from + * and cleaning up the directory. + * + * The `encoding` option sets the encoding for the `path` while opening the + * directory and subsequent read operations. + * + * Example using async iteration: + * + * ```js + * import { opendir } from 'node:fs/promises'; + * + * try { + * const dir = await opendir('./'); + * for await (const dirent of dir) + * console.log(dirent.name); + * } catch (err) { + * console.error(err); + * } + * ``` + * + * When using the async iterator, the `fs.Dir` object will be automatically + * closed after the iterator exits. + * @since v12.12.0 + * @return Fulfills with an {fs.Dir}. + */ + function opendir(path: PathLike, options?: OpenDirOptions): Promise<Dir>; + interface WatchOptions extends _WatchOptions { + maxQueue?: number | undefined; + overflow?: "ignore" | "throw" | undefined; + } + interface WatchOptionsWithBufferEncoding extends WatchOptions { + encoding: "buffer"; + } + interface WatchOptionsWithStringEncoding extends WatchOptions { + encoding?: BufferEncoding | undefined; + } + /** + * Returns an async iterator that watches for changes on `filename`, where `filename`is either a file or a directory. + * + * ```js + * import { watch } from 'node:fs/promises'; + * + * const ac = new AbortController(); + * const { signal } = ac; + * setTimeout(() => ac.abort(), 10000); + * + * (async () => { + * try { + * const watcher = watch(__filename, { signal }); + * for await (const event of watcher) + * console.log(event); + * } catch (err) { + * if (err.name === 'AbortError') + * return; + * throw err; + * } + * })(); + * ``` + * + * On most platforms, `'rename'` is emitted whenever a filename appears or + * disappears in the directory. + * + * All the `caveats` for `fs.watch()` also apply to `fsPromises.watch()`. + * @since v15.9.0, v14.18.0 + * @return of objects with the properties: + */ + function watch( + filename: PathLike, + options?: WatchOptionsWithStringEncoding | BufferEncoding, + ): NodeJS.AsyncIterator<FileChangeInfo<string>>; + function watch( + filename: PathLike, + options: WatchOptionsWithBufferEncoding | "buffer", + ): NodeJS.AsyncIterator<FileChangeInfo<NonSharedBuffer>>; + function watch( + filename: PathLike, + options: WatchOptions | BufferEncoding | "buffer", + ): NodeJS.AsyncIterator<FileChangeInfo<string | NonSharedBuffer>>; + /** + * Asynchronously copies the entire directory structure from `src` to `dest`, + * including subdirectories and files. + * + * When copying a directory to another directory, globs are not supported and + * behavior is similar to `cp dir1/ dir2/`. + * @since v16.7.0 + * @experimental + * @param src source path to copy. + * @param dest destination path to copy to. + * @return Fulfills with `undefined` upon success. + */ + function cp(source: string | URL, destination: string | URL, opts?: CopyOptions): Promise<void>; + /** + * ```js + * import { glob } from 'node:fs/promises'; + * + * for await (const entry of glob('*.js')) + * console.log(entry); + * ``` + * @since v22.0.0 + * @returns An AsyncIterator that yields the paths of files + * that match the pattern. + */ + function glob(pattern: string | readonly string[]): NodeJS.AsyncIterator<string>; + function glob( + pattern: string | readonly string[], + options: GlobOptionsWithFileTypes, + ): NodeJS.AsyncIterator<Dirent>; + function glob( + pattern: string | readonly string[], + options: GlobOptionsWithoutFileTypes, + ): NodeJS.AsyncIterator<string>; + function glob( + pattern: string | readonly string[], + options: GlobOptions, + ): NodeJS.AsyncIterator<Dirent | string>; +} +declare module "fs/promises" { + export * from "node:fs/promises"; +} diff --git a/server/node_modules/@types/node/globals.d.ts b/server/node_modules/@types/node/globals.d.ts new file mode 100644 index 0000000..36e7f90 --- /dev/null +++ b/server/node_modules/@types/node/globals.d.ts @@ -0,0 +1,150 @@ +declare var global: typeof globalThis; + +declare var process: NodeJS.Process; + +interface ErrorConstructor { + /** + * Creates a `.stack` property on `targetObject`, which when accessed returns + * a string representing the location in the code at which + * `Error.captureStackTrace()` was called. + * + * ```js + * const myObject = {}; + * Error.captureStackTrace(myObject); + * myObject.stack; // Similar to `new Error().stack` + * ``` + * + * The first line of the trace will be prefixed with + * `${myObject.name}: ${myObject.message}`. + * + * The optional `constructorOpt` argument accepts a function. If given, all frames + * above `constructorOpt`, including `constructorOpt`, will be omitted from the + * generated stack trace. + * + * The `constructorOpt` argument is useful for hiding implementation + * details of error generation from the user. For instance: + * + * ```js + * function a() { + * b(); + * } + * + * function b() { + * c(); + * } + * + * function c() { + * // Create an error without stack trace to avoid calculating the stack trace twice. + * const { stackTraceLimit } = Error; + * Error.stackTraceLimit = 0; + * const error = new Error(); + * Error.stackTraceLimit = stackTraceLimit; + * + * // Capture the stack trace above function b + * Error.captureStackTrace(error, b); // Neither function c, nor b is included in the stack trace + * throw error; + * } + * + * a(); + * ``` + */ + captureStackTrace(targetObject: object, constructorOpt?: Function): void; + /** + * @see https://v8.dev/docs/stack-trace-api#customizing-stack-traces + */ + prepareStackTrace(err: Error, stackTraces: NodeJS.CallSite[]): any; + /** + * The `Error.stackTraceLimit` property specifies the number of stack frames + * collected by a stack trace (whether generated by `new Error().stack` or + * `Error.captureStackTrace(obj)`). + * + * The default value is `10` but may be set to any valid JavaScript number. Changes + * will affect any stack trace captured _after_ the value has been changed. + * + * If set to a non-number value, or set to a negative number, stack traces will + * not capture any frames. + */ + stackTraceLimit: number; +} + +/** + * Enable this API with the `--expose-gc` CLI flag. + */ +declare var gc: NodeJS.GCFunction | undefined; + +declare namespace NodeJS { + interface CallSite { + getColumnNumber(): number | null; + getEnclosingColumnNumber(): number | null; + getEnclosingLineNumber(): number | null; + getEvalOrigin(): string | undefined; + getFileName(): string | null; + getFunction(): Function | undefined; + getFunctionName(): string | null; + getLineNumber(): number | null; + getMethodName(): string | null; + getPosition(): number; + getPromiseIndex(): number | null; + getScriptHash(): string; + getScriptNameOrSourceURL(): string | null; + getThis(): unknown; + getTypeName(): string | null; + isAsync(): boolean; + isConstructor(): boolean; + isEval(): boolean; + isNative(): boolean; + isPromiseAll(): boolean; + isToplevel(): boolean; + } + + interface ErrnoException extends Error { + errno?: number | undefined; + code?: string | undefined; + path?: string | undefined; + syscall?: string | undefined; + } + + interface RefCounted { + ref(): this; + unref(): this; + } + + interface Dict<T> { + [key: string]: T | undefined; + } + + interface ReadOnlyDict<T> { + readonly [key: string]: T | undefined; + } + + type PartialOptions<T> = { [K in keyof T]?: T[K] | undefined }; + + interface GCFunction { + (minor?: boolean): void; + (options: NodeJS.GCOptions & { execution: "async" }): Promise<void>; + (options: NodeJS.GCOptions): void; + } + + interface GCOptions { + execution?: "sync" | "async" | undefined; + flavor?: "regular" | "last-resort" | undefined; + type?: "major-snapshot" | "major" | "minor" | undefined; + filename?: string | undefined; + } + + /** An iterable iterator returned by the Node.js API. */ + interface Iterator<T, TReturn = undefined, TNext = any> extends IteratorObject<T, TReturn, TNext> { + [Symbol.iterator](): NodeJS.Iterator<T, TReturn, TNext>; + } + + /** An async iterable iterator returned by the Node.js API. */ + interface AsyncIterator<T, TReturn = undefined, TNext = any> extends AsyncIteratorObject<T, TReturn, TNext> { + [Symbol.asyncIterator](): NodeJS.AsyncIterator<T, TReturn, TNext>; + } + + /** The [`BufferSource`](https://webidl.spec.whatwg.org/#BufferSource) type from the Web IDL specification. */ + type BufferSource = NonSharedArrayBufferView | ArrayBuffer; + + /** The [`AllowSharedBufferSource`](https://webidl.spec.whatwg.org/#AllowSharedBufferSource) type from the Web IDL specification. */ + type AllowSharedBufferSource = ArrayBufferView | ArrayBufferLike; +} diff --git a/server/node_modules/@types/node/globals.typedarray.d.ts b/server/node_modules/@types/node/globals.typedarray.d.ts new file mode 100644 index 0000000..e69dd0c --- /dev/null +++ b/server/node_modules/@types/node/globals.typedarray.d.ts @@ -0,0 +1,101 @@ +export {}; // Make this a module + +declare global { + namespace NodeJS { + type TypedArray<TArrayBuffer extends ArrayBufferLike = ArrayBufferLike> = + | Uint8Array<TArrayBuffer> + | Uint8ClampedArray<TArrayBuffer> + | Uint16Array<TArrayBuffer> + | Uint32Array<TArrayBuffer> + | Int8Array<TArrayBuffer> + | Int16Array<TArrayBuffer> + | Int32Array<TArrayBuffer> + | BigUint64Array<TArrayBuffer> + | BigInt64Array<TArrayBuffer> + | Float16Array<TArrayBuffer> + | Float32Array<TArrayBuffer> + | Float64Array<TArrayBuffer>; + type ArrayBufferView<TArrayBuffer extends ArrayBufferLike = ArrayBufferLike> = + | TypedArray<TArrayBuffer> + | DataView<TArrayBuffer>; + + // The following aliases are required to allow use of non-shared ArrayBufferViews in @types/node + // while maintaining compatibility with TS <=5.6. + // TODO: remove once @types/node no longer supports TS 5.6, and replace with native types. + /** + * @deprecated This is intended for internal use, and will be removed once `@types/node` no longer supports + * TypeScript versions earlier than 5.7. + */ + type NonSharedUint8Array = Uint8Array<ArrayBuffer>; + /** + * @deprecated This is intended for internal use, and will be removed once `@types/node` no longer supports + * TypeScript versions earlier than 5.7. + */ + type NonSharedUint8ClampedArray = Uint8ClampedArray<ArrayBuffer>; + /** + * @deprecated This is intended for internal use, and will be removed once `@types/node` no longer supports + * TypeScript versions earlier than 5.7. + */ + type NonSharedUint16Array = Uint16Array<ArrayBuffer>; + /** + * @deprecated This is intended for internal use, and will be removed once `@types/node` no longer supports + * TypeScript versions earlier than 5.7. + */ + type NonSharedUint32Array = Uint32Array<ArrayBuffer>; + /** + * @deprecated This is intended for internal use, and will be removed once `@types/node` no longer supports + * TypeScript versions earlier than 5.7. + */ + type NonSharedInt8Array = Int8Array<ArrayBuffer>; + /** + * @deprecated This is intended for internal use, and will be removed once `@types/node` no longer supports + * TypeScript versions earlier than 5.7. + */ + type NonSharedInt16Array = Int16Array<ArrayBuffer>; + /** + * @deprecated This is intended for internal use, and will be removed once `@types/node` no longer supports + * TypeScript versions earlier than 5.7. + */ + type NonSharedInt32Array = Int32Array<ArrayBuffer>; + /** + * @deprecated This is intended for internal use, and will be removed once `@types/node` no longer supports + * TypeScript versions earlier than 5.7. + */ + type NonSharedBigUint64Array = BigUint64Array<ArrayBuffer>; + /** + * @deprecated This is intended for internal use, and will be removed once `@types/node` no longer supports + * TypeScript versions earlier than 5.7. + */ + type NonSharedBigInt64Array = BigInt64Array<ArrayBuffer>; + /** + * @deprecated This is intended for internal use, and will be removed once `@types/node` no longer supports + * TypeScript versions earlier than 5.7. + */ + type NonSharedFloat16Array = Float16Array<ArrayBuffer>; + /** + * @deprecated This is intended for internal use, and will be removed once `@types/node` no longer supports + * TypeScript versions earlier than 5.7. + */ + type NonSharedFloat32Array = Float32Array<ArrayBuffer>; + /** + * @deprecated This is intended for internal use, and will be removed once `@types/node` no longer supports + * TypeScript versions earlier than 5.7. + */ + type NonSharedFloat64Array = Float64Array<ArrayBuffer>; + /** + * @deprecated This is intended for internal use, and will be removed once `@types/node` no longer supports + * TypeScript versions earlier than 5.7. + */ + type NonSharedDataView = DataView<ArrayBuffer>; + /** + * @deprecated This is intended for internal use, and will be removed once `@types/node` no longer supports + * TypeScript versions earlier than 5.7. + */ + type NonSharedTypedArray = TypedArray<ArrayBuffer>; + /** + * @deprecated This is intended for internal use, and will be removed once `@types/node` no longer supports + * TypeScript versions earlier than 5.7. + */ + type NonSharedArrayBufferView = ArrayBufferView<ArrayBuffer>; + } +} diff --git a/server/node_modules/@types/node/http.d.ts b/server/node_modules/@types/node/http.d.ts new file mode 100644 index 0000000..4ba1922 --- /dev/null +++ b/server/node_modules/@types/node/http.d.ts @@ -0,0 +1,2167 @@ +/** + * To use the HTTP server and client one must import the `node:http` module. + * + * The HTTP interfaces in Node.js are designed to support many features + * of the protocol which have been traditionally difficult to use. + * In particular, large, possibly chunk-encoded, messages. The interface is + * careful to never buffer entire requests or responses, so the + * user is able to stream data. + * + * HTTP message headers are represented by an object like this: + * + * ```json + * { "content-length": "123", + * "content-type": "text/plain", + * "connection": "keep-alive", + * "host": "example.com", + * "accept": "*" } + * ``` + * + * Keys are lowercased. Values are not modified. + * + * In order to support the full spectrum of possible HTTP applications, the Node.js + * HTTP API is very low-level. It deals with stream handling and message + * parsing only. It parses a message into headers and body but it does not + * parse the actual headers or the body. + * + * See `message.headers` for details on how duplicate headers are handled. + * + * The raw headers as they were received are retained in the `rawHeaders` property, which is an array of `[key, value, key2, value2, ...]`. For + * example, the previous message header object might have a `rawHeaders` list like the following: + * + * ```js + * [ 'ConTent-Length', '123456', + * 'content-LENGTH', '123', + * 'content-type', 'text/plain', + * 'CONNECTION', 'keep-alive', + * 'Host', 'example.com', + * 'accepT', '*' ] + * ``` + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/http.js) + */ +declare module "node:http" { + import { NonSharedBuffer } from "node:buffer"; + import { LookupOptions } from "node:dns"; + import { EventEmitter } from "node:events"; + import * as net from "node:net"; + import * as stream from "node:stream"; + import { URL } from "node:url"; + // incoming headers will never contain number + interface IncomingHttpHeaders extends NodeJS.Dict<string | string[]> { + accept?: string | undefined; + "accept-encoding"?: string | undefined; + "accept-language"?: string | undefined; + "accept-patch"?: string | undefined; + "accept-ranges"?: string | undefined; + "access-control-allow-credentials"?: string | undefined; + "access-control-allow-headers"?: string | undefined; + "access-control-allow-methods"?: string | undefined; + "access-control-allow-origin"?: string | undefined; + "access-control-expose-headers"?: string | undefined; + "access-control-max-age"?: string | undefined; + "access-control-request-headers"?: string | undefined; + "access-control-request-method"?: string | undefined; + age?: string | undefined; + allow?: string | undefined; + "alt-svc"?: string | undefined; + authorization?: string | undefined; + "cache-control"?: string | undefined; + connection?: string | undefined; + "content-disposition"?: string | undefined; + "content-encoding"?: string | undefined; + "content-language"?: string | undefined; + "content-length"?: string | undefined; + "content-location"?: string | undefined; + "content-range"?: string | undefined; + "content-type"?: string | undefined; + cookie?: string | undefined; + date?: string | undefined; + etag?: string | undefined; + expect?: string | undefined; + expires?: string | undefined; + forwarded?: string | undefined; + from?: string | undefined; + host?: string | undefined; + "if-match"?: string | undefined; + "if-modified-since"?: string | undefined; + "if-none-match"?: string | undefined; + "if-unmodified-since"?: string | undefined; + "last-modified"?: string | undefined; + location?: string | undefined; + origin?: string | undefined; + pragma?: string | undefined; + "proxy-authenticate"?: string | undefined; + "proxy-authorization"?: string | undefined; + "public-key-pins"?: string | undefined; + range?: string | undefined; + referer?: string | undefined; + "retry-after"?: string | undefined; + "sec-fetch-site"?: string | undefined; + "sec-fetch-mode"?: string | undefined; + "sec-fetch-user"?: string | undefined; + "sec-fetch-dest"?: string | undefined; + "sec-websocket-accept"?: string | undefined; + "sec-websocket-extensions"?: string | undefined; + "sec-websocket-key"?: string | undefined; + "sec-websocket-protocol"?: string | undefined; + "sec-websocket-version"?: string | undefined; + "set-cookie"?: string[] | undefined; + "strict-transport-security"?: string | undefined; + tk?: string | undefined; + trailer?: string | undefined; + "transfer-encoding"?: string | undefined; + upgrade?: string | undefined; + "user-agent"?: string | undefined; + vary?: string | undefined; + via?: string | undefined; + warning?: string | undefined; + "www-authenticate"?: string | undefined; + } + // outgoing headers allows numbers (as they are converted internally to strings) + type OutgoingHttpHeader = number | string | string[]; + interface OutgoingHttpHeaders extends NodeJS.Dict<OutgoingHttpHeader> { + accept?: string | string[] | undefined; + "accept-charset"?: string | string[] | undefined; + "accept-encoding"?: string | string[] | undefined; + "accept-language"?: string | string[] | undefined; + "accept-ranges"?: string | undefined; + "access-control-allow-credentials"?: string | undefined; + "access-control-allow-headers"?: string | undefined; + "access-control-allow-methods"?: string | undefined; + "access-control-allow-origin"?: string | undefined; + "access-control-expose-headers"?: string | undefined; + "access-control-max-age"?: string | undefined; + "access-control-request-headers"?: string | undefined; + "access-control-request-method"?: string | undefined; + age?: string | undefined; + allow?: string | undefined; + authorization?: string | undefined; + "cache-control"?: string | undefined; + "cdn-cache-control"?: string | undefined; + connection?: string | string[] | undefined; + "content-disposition"?: string | undefined; + "content-encoding"?: string | undefined; + "content-language"?: string | undefined; + "content-length"?: string | number | undefined; + "content-location"?: string | undefined; + "content-range"?: string | undefined; + "content-security-policy"?: string | undefined; + "content-security-policy-report-only"?: string | undefined; + "content-type"?: string | undefined; + cookie?: string | string[] | undefined; + dav?: string | string[] | undefined; + dnt?: string | undefined; + date?: string | undefined; + etag?: string | undefined; + expect?: string | undefined; + expires?: string | undefined; + forwarded?: string | undefined; + from?: string | undefined; + host?: string | undefined; + "if-match"?: string | undefined; + "if-modified-since"?: string | undefined; + "if-none-match"?: string | undefined; + "if-range"?: string | undefined; + "if-unmodified-since"?: string | undefined; + "last-modified"?: string | undefined; + link?: string | string[] | undefined; + location?: string | undefined; + "max-forwards"?: string | undefined; + origin?: string | undefined; + pragma?: string | string[] | undefined; + "proxy-authenticate"?: string | string[] | undefined; + "proxy-authorization"?: string | undefined; + "public-key-pins"?: string | undefined; + "public-key-pins-report-only"?: string | undefined; + range?: string | undefined; + referer?: string | undefined; + "referrer-policy"?: string | undefined; + refresh?: string | undefined; + "retry-after"?: string | undefined; + "sec-websocket-accept"?: string | undefined; + "sec-websocket-extensions"?: string | string[] | undefined; + "sec-websocket-key"?: string | undefined; + "sec-websocket-protocol"?: string | string[] | undefined; + "sec-websocket-version"?: string | undefined; + server?: string | undefined; + "set-cookie"?: string | string[] | undefined; + "strict-transport-security"?: string | undefined; + te?: string | undefined; + trailer?: string | undefined; + "transfer-encoding"?: string | undefined; + "user-agent"?: string | undefined; + upgrade?: string | undefined; + "upgrade-insecure-requests"?: string | undefined; + vary?: string | undefined; + via?: string | string[] | undefined; + warning?: string | undefined; + "www-authenticate"?: string | string[] | undefined; + "x-content-type-options"?: string | undefined; + "x-dns-prefetch-control"?: string | undefined; + "x-frame-options"?: string | undefined; + "x-xss-protection"?: string | undefined; + } + interface ClientRequestArgs extends Pick<LookupOptions, "hints"> { + _defaultAgent?: Agent | undefined; + agent?: Agent | boolean | undefined; + auth?: string | null | undefined; + createConnection?: + | (( + options: ClientRequestArgs, + oncreate: (err: Error | null, socket: stream.Duplex) => void, + ) => stream.Duplex | null | undefined) + | undefined; + defaultPort?: number | string | undefined; + family?: number | undefined; + headers?: OutgoingHttpHeaders | readonly string[] | undefined; + host?: string | null | undefined; + hostname?: string | null | undefined; + insecureHTTPParser?: boolean | undefined; + localAddress?: string | undefined; + localPort?: number | undefined; + lookup?: net.LookupFunction | undefined; + /** + * @default 16384 + */ + maxHeaderSize?: number | undefined; + method?: string | undefined; + path?: string | null | undefined; + port?: number | string | null | undefined; + protocol?: string | null | undefined; + setDefaultHeaders?: boolean | undefined; + setHost?: boolean | undefined; + signal?: AbortSignal | undefined; + socketPath?: string | undefined; + timeout?: number | undefined; + uniqueHeaders?: Array<string | string[]> | undefined; + joinDuplicateHeaders?: boolean | undefined; + } + interface ServerOptions< + Request extends typeof IncomingMessage = typeof IncomingMessage, + Response extends typeof ServerResponse<InstanceType<Request>> = typeof ServerResponse, + > { + /** + * Specifies the `IncomingMessage` class to be used. Useful for extending the original `IncomingMessage`. + */ + IncomingMessage?: Request | undefined; + /** + * Specifies the `ServerResponse` class to be used. Useful for extending the original `ServerResponse`. + */ + ServerResponse?: Response | undefined; + /** + * Sets the timeout value in milliseconds for receiving the entire request from the client. + * @see Server.requestTimeout for more information. + * @default 300000 + * @since v18.0.0 + */ + requestTimeout?: number | undefined; + /** + * It joins the field line values of multiple headers in a request with `, ` instead of discarding the duplicates. + * @default false + * @since v18.14.0 + */ + joinDuplicateHeaders?: boolean | undefined; + /** + * The number of milliseconds of inactivity a server needs to wait for additional incoming data, + * after it has finished writing the last response, before a socket will be destroyed. + * @see Server.keepAliveTimeout for more information. + * @default 5000 + * @since v18.0.0 + */ + keepAliveTimeout?: number | undefined; + /** + * An additional buffer time added to the + * `server.keepAliveTimeout` to extend the internal socket timeout. + * @since 24.6.0 + * @default 1000 + */ + keepAliveTimeoutBuffer?: number | undefined; + /** + * Sets the interval value in milliseconds to check for request and headers timeout in incomplete requests. + * @default 30000 + */ + connectionsCheckingInterval?: number | undefined; + /** + * Sets the timeout value in milliseconds for receiving the complete HTTP headers from the client. + * See {@link Server.headersTimeout} for more information. + * @default 60000 + * @since 18.0.0 + */ + headersTimeout?: number | undefined; + /** + * Optionally overrides all `socket`s' `readableHighWaterMark` and `writableHighWaterMark`. + * This affects `highWaterMark` property of both `IncomingMessage` and `ServerResponse`. + * Default: @see stream.getDefaultHighWaterMark(). + * @since v20.1.0 + */ + highWaterMark?: number | undefined; + /** + * Use an insecure HTTP parser that accepts invalid HTTP headers when `true`. + * Using the insecure parser should be avoided. + * See --insecure-http-parser for more information. + * @default false + */ + insecureHTTPParser?: boolean | undefined; + /** + * Optionally overrides the value of `--max-http-header-size` for requests received by + * this server, i.e. the maximum length of request headers in bytes. + * @default 16384 + * @since v13.3.0 + */ + maxHeaderSize?: number | undefined; + /** + * If set to `true`, it disables the use of Nagle's algorithm immediately after a new incoming connection is received. + * @default true + * @since v16.5.0 + */ + noDelay?: boolean | undefined; + /** + * If set to `true`, it forces the server to respond with a 400 (Bad Request) status code + * to any HTTP/1.1 request message that lacks a Host header (as mandated by the specification). + * @default true + * @since 20.0.0 + */ + requireHostHeader?: boolean | undefined; + /** + * If set to `true`, it enables keep-alive functionality on the socket immediately after a new incoming connection is received, + * similarly on what is done in `socket.setKeepAlive([enable][, initialDelay])`. + * @default false + * @since v16.5.0 + */ + keepAlive?: boolean | undefined; + /** + * If set to a positive number, it sets the initial delay before the first keepalive probe is sent on an idle socket. + * @default 0 + * @since v16.5.0 + */ + keepAliveInitialDelay?: number | undefined; + /** + * A list of response headers that should be sent only once. + * If the header's value is an array, the items will be joined using `; `. + */ + uniqueHeaders?: Array<string | string[]> | undefined; + /** + * A callback which receives an + * incoming request and returns a boolean, to control which upgrade attempts + * should be accepted. Accepted upgrades will fire an `'upgrade'` event (or + * their sockets will be destroyed, if no listener is registered) while + * rejected upgrades will fire a `'request'` event like any non-upgrade + * request. + * @since v24.9.0 + * @default () => server.listenerCount('upgrade') > 0 + */ + shouldUpgradeCallback?: ((request: InstanceType<Request>) => boolean) | undefined; + /** + * If set to `true`, an error is thrown when writing to an HTTP response which does not have a body. + * @default false + * @since v18.17.0, v20.2.0 + */ + rejectNonStandardBodyWrites?: boolean | undefined; + /** + * If set to `true`, requests without `Content-Length` + * or `Transfer-Encoding` headers (indicating no body) will be initialized with an + * already-ended body stream, so they will never emit any stream events + * (like `'data'` or `'end'`). You can use `req.readableEnded` to detect this case. + * @since v25.1.0 + * @default false + */ + optimizeEmptyRequests?: boolean | undefined; + } + type RequestListener< + Request extends typeof IncomingMessage = typeof IncomingMessage, + Response extends typeof ServerResponse<InstanceType<Request>> = typeof ServerResponse, + > = (request: InstanceType<Request>, response: InstanceType<Response> & { req: InstanceType<Request> }) => void; + interface ServerEventMap< + Request extends typeof IncomingMessage = typeof IncomingMessage, + Response extends typeof ServerResponse<InstanceType<Request>> = typeof ServerResponse, + > extends net.ServerEventMap { + "checkContinue": Parameters<RequestListener<Request, Response>>; + "checkExpectation": Parameters<RequestListener<Request, Response>>; + "clientError": [exception: Error, socket: stream.Duplex]; + "connect": [request: InstanceType<Request>, socket: stream.Duplex, head: NonSharedBuffer]; + "connection": [socket: net.Socket]; + "dropRequest": [request: InstanceType<Request>, socket: stream.Duplex]; + "request": Parameters<RequestListener<Request, Response>>; + "upgrade": [req: InstanceType<Request>, socket: stream.Duplex, head: NonSharedBuffer]; + } + /** + * @since v0.1.17 + */ + class Server< + Request extends typeof IncomingMessage = typeof IncomingMessage, + Response extends typeof ServerResponse<InstanceType<Request>> = typeof ServerResponse, + > extends net.Server { + constructor(requestListener?: RequestListener<Request, Response>); + constructor(options: ServerOptions<Request, Response>, requestListener?: RequestListener<Request, Response>); + /** + * Sets the timeout value for sockets, and emits a `'timeout'` event on + * the Server object, passing the socket as an argument, if a timeout + * occurs. + * + * If there is a `'timeout'` event listener on the Server object, then it + * will be called with the timed-out socket as an argument. + * + * By default, the Server does not timeout sockets. However, if a callback + * is assigned to the Server's `'timeout'` event, timeouts must be handled + * explicitly. + * @since v0.9.12 + * @param [msecs=0 (no timeout)] + */ + setTimeout(msecs?: number, callback?: (socket: net.Socket) => void): this; + setTimeout(callback: (socket: net.Socket) => void): this; + /** + * Limits maximum incoming headers count. If set to 0, no limit will be applied. + * @since v0.7.0 + */ + maxHeadersCount: number | null; + /** + * The maximum number of requests socket can handle + * before closing keep alive connection. + * + * A value of `0` will disable the limit. + * + * When the limit is reached it will set the `Connection` header value to `close`, + * but will not actually close the connection, subsequent requests sent + * after the limit is reached will get `503 Service Unavailable` as a response. + * @since v16.10.0 + */ + maxRequestsPerSocket: number | null; + /** + * The number of milliseconds of inactivity before a socket is presumed + * to have timed out. + * + * A value of `0` will disable the timeout behavior on incoming connections. + * + * The socket timeout logic is set up on connection, so changing this + * value only affects new connections to the server, not any existing connections. + * @since v0.9.12 + */ + timeout: number; + /** + * Limit the amount of time the parser will wait to receive the complete HTTP + * headers. + * + * If the timeout expires, the server responds with status 408 without + * forwarding the request to the request listener and then closes the connection. + * + * It must be set to a non-zero value (e.g. 120 seconds) to protect against + * potential Denial-of-Service attacks in case the server is deployed without a + * reverse proxy in front. + * @since v11.3.0, v10.14.0 + */ + headersTimeout: number; + /** + * The number of milliseconds of inactivity a server needs to wait for additional + * incoming data, after it has finished writing the last response, before a socket + * will be destroyed. + * + * This timeout value is combined with the + * `server.keepAliveTimeoutBuffer` option to determine the actual socket + * timeout, calculated as: + * socketTimeout = keepAliveTimeout + keepAliveTimeoutBuffer + * If the server receives new data before the keep-alive timeout has fired, it + * will reset the regular inactivity timeout, i.e., `server.timeout`. + * + * A value of `0` will disable the keep-alive timeout behavior on incoming + * connections. + * A value of `0` makes the HTTP server behave similarly to Node.js versions prior + * to 8.0.0, which did not have a keep-alive timeout. + * + * The socket timeout logic is set up on connection, so changing this value only + * affects new connections to the server, not any existing connections. + * @since v8.0.0 + */ + keepAliveTimeout: number; + /** + * An additional buffer time added to the + * `server.keepAliveTimeout` to extend the internal socket timeout. + * + * This buffer helps reduce connection reset (`ECONNRESET`) errors by increasing + * the socket timeout slightly beyond the advertised keep-alive timeout. + * + * This option applies only to new incoming connections. + * @since v24.6.0 + * @default 1000 + */ + keepAliveTimeoutBuffer: number; + /** + * Sets the timeout value in milliseconds for receiving the entire request from + * the client. + * + * If the timeout expires, the server responds with status 408 without + * forwarding the request to the request listener and then closes the connection. + * + * It must be set to a non-zero value (e.g. 120 seconds) to protect against + * potential Denial-of-Service attacks in case the server is deployed without a + * reverse proxy in front. + * @since v14.11.0 + */ + requestTimeout: number; + /** + * Closes all connections connected to this server. + * @since v18.2.0 + */ + closeAllConnections(): void; + /** + * Closes all connections connected to this server which are not sending a request + * or waiting for a response. + * @since v18.2.0 + */ + closeIdleConnections(): void; + // #region InternalEventEmitter + addListener<E extends keyof ServerEventMap>( + eventName: E, + listener: (...args: ServerEventMap<Request, Response>[E]) => void, + ): this; + addListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + emit<E extends keyof ServerEventMap>(eventName: E, ...args: ServerEventMap<Request, Response>[E]): boolean; + emit(eventName: string | symbol, ...args: any[]): boolean; + listenerCount<E extends keyof ServerEventMap>( + eventName: E, + listener?: (...args: ServerEventMap<Request, Response>[E]) => void, + ): number; + listenerCount(eventName: string | symbol, listener?: (...args: any[]) => void): number; + listeners<E extends keyof ServerEventMap>( + eventName: E, + ): ((...args: ServerEventMap<Request, Response>[E]) => void)[]; + listeners(eventName: string | symbol): ((...args: any[]) => void)[]; + off<E extends keyof ServerEventMap>( + eventName: E, + listener: (...args: ServerEventMap<Request, Response>[E]) => void, + ): this; + off(eventName: string | symbol, listener: (...args: any[]) => void): this; + on<E extends keyof ServerEventMap>( + eventName: E, + listener: (...args: ServerEventMap<Request, Response>[E]) => void, + ): this; + on(eventName: string | symbol, listener: (...args: any[]) => void): this; + once<E extends keyof ServerEventMap>( + eventName: E, + listener: (...args: ServerEventMap<Request, Response>[E]) => void, + ): this; + once(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependListener<E extends keyof ServerEventMap>( + eventName: E, + listener: (...args: ServerEventMap<Request, Response>[E]) => void, + ): this; + prependListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependOnceListener<E extends keyof ServerEventMap>( + eventName: E, + listener: (...args: ServerEventMap<Request, Response>[E]) => void, + ): this; + prependOnceListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + rawListeners<E extends keyof ServerEventMap>( + eventName: E, + ): ((...args: ServerEventMap<Request, Response>[E]) => void)[]; + rawListeners(eventName: string | symbol): ((...args: any[]) => void)[]; + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + removeAllListeners<E extends keyof ServerEventMap>(eventName?: E): this; + removeAllListeners(eventName?: string | symbol): this; + removeListener<E extends keyof ServerEventMap>( + eventName: E, + listener: (...args: ServerEventMap<Request, Response>[E]) => void, + ): this; + removeListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + // #endregion + } + interface OutgoingMessageEventMap extends stream.WritableEventMap { + "prefinish": []; + } + /** + * This class serves as the parent class of {@link ClientRequest} and {@link ServerResponse}. It is an abstract outgoing message from + * the perspective of the participants of an HTTP transaction. + * @since v0.1.17 + */ + class OutgoingMessage<Request extends IncomingMessage = IncomingMessage> extends stream.Writable { + constructor(); + readonly req: Request; + chunkedEncoding: boolean; + shouldKeepAlive: boolean; + useChunkedEncodingByDefault: boolean; + sendDate: boolean; + /** + * @deprecated Use `writableEnded` instead. + */ + finished: boolean; + /** + * Read-only. `true` if the headers were sent, otherwise `false`. + * @since v0.9.3 + */ + readonly headersSent: boolean; + /** + * Alias of `outgoingMessage.socket`. + * @since v0.3.0 + * @deprecated Since v15.12.0,v14.17.1 - Use `socket` instead. + */ + readonly connection: net.Socket | null; + /** + * Reference to the underlying socket. Usually, users will not want to access + * this property. + * + * After calling `outgoingMessage.end()`, this property will be nulled. + * @since v0.3.0 + */ + readonly socket: net.Socket | null; + /** + * Once a socket is associated with the message and is connected, `socket.setTimeout()` will be called with `msecs` as the first parameter. + * @since v0.9.12 + * @param callback Optional function to be called when a timeout occurs. Same as binding to the `timeout` event. + */ + setTimeout(msecs: number, callback?: () => void): this; + /** + * Sets a single header value. If the header already exists in the to-be-sent + * headers, its value will be replaced. Use an array of strings to send multiple + * headers with the same name. + * @since v0.4.0 + * @param name Header name + * @param value Header value + */ + setHeader(name: string, value: number | string | readonly string[]): this; + /** + * Sets multiple header values for implicit headers. headers must be an instance of + * `Headers` or `Map`, if a header already exists in the to-be-sent headers, its + * value will be replaced. + * + * ```js + * const headers = new Headers({ foo: 'bar' }); + * outgoingMessage.setHeaders(headers); + * ``` + * + * or + * + * ```js + * const headers = new Map([['foo', 'bar']]); + * outgoingMessage.setHeaders(headers); + * ``` + * + * When headers have been set with `outgoingMessage.setHeaders()`, they will be + * merged with any headers passed to `response.writeHead()`, with the headers passed + * to `response.writeHead()` given precedence. + * + * ```js + * // Returns content-type = text/plain + * const server = http.createServer((req, res) => { + * const headers = new Headers({ 'Content-Type': 'text/html' }); + * res.setHeaders(headers); + * res.writeHead(200, { 'Content-Type': 'text/plain' }); + * res.end('ok'); + * }); + * ``` + * + * @since v19.6.0, v18.15.0 + * @param name Header name + * @param value Header value + */ + setHeaders(headers: Headers | Map<string, number | string | readonly string[]>): this; + /** + * Append a single header value to the header object. + * + * If the value is an array, this is equivalent to calling this method multiple + * times. + * + * If there were no previous values for the header, this is equivalent to calling `outgoingMessage.setHeader(name, value)`. + * + * Depending of the value of `options.uniqueHeaders` when the client request or the + * server were created, this will end up in the header being sent multiple times or + * a single time with values joined using `; `. + * @since v18.3.0, v16.17.0 + * @param name Header name + * @param value Header value + */ + appendHeader(name: string, value: string | readonly string[]): this; + /** + * Gets the value of the HTTP header with the given name. If that header is not + * set, the returned value will be `undefined`. + * @since v0.4.0 + * @param name Name of header + */ + getHeader(name: string): number | string | string[] | undefined; + /** + * Returns a shallow copy of the current outgoing headers. Since a shallow + * copy is used, array values may be mutated without additional calls to + * various header-related HTTP module methods. The keys of the returned + * object are the header names and the values are the respective header + * values. All header names are lowercase. + * + * The object returned by the `outgoingMessage.getHeaders()` method does + * not prototypically inherit from the JavaScript `Object`. This means that + * typical `Object` methods such as `obj.toString()`, `obj.hasOwnProperty()`, + * and others are not defined and will not work. + * + * ```js + * outgoingMessage.setHeader('Foo', 'bar'); + * outgoingMessage.setHeader('Set-Cookie', ['foo=bar', 'bar=baz']); + * + * const headers = outgoingMessage.getHeaders(); + * // headers === { foo: 'bar', 'set-cookie': ['foo=bar', 'bar=baz'] } + * ``` + * @since v7.7.0 + */ + getHeaders(): OutgoingHttpHeaders; + /** + * Returns an array containing the unique names of the current outgoing headers. + * All names are lowercase. + * @since v7.7.0 + */ + getHeaderNames(): string[]; + /** + * Returns `true` if the header identified by `name` is currently set in the + * outgoing headers. The header name is case-insensitive. + * + * ```js + * const hasContentType = outgoingMessage.hasHeader('content-type'); + * ``` + * @since v7.7.0 + */ + hasHeader(name: string): boolean; + /** + * Removes a header that is queued for implicit sending. + * + * ```js + * outgoingMessage.removeHeader('Content-Encoding'); + * ``` + * @since v0.4.0 + * @param name Header name + */ + removeHeader(name: string): void; + /** + * Adds HTTP trailers (headers but at the end of the message) to the message. + * + * Trailers will **only** be emitted if the message is chunked encoded. If not, + * the trailers will be silently discarded. + * + * HTTP requires the `Trailer` header to be sent to emit trailers, + * with a list of header field names in its value, e.g. + * + * ```js + * message.writeHead(200, { 'Content-Type': 'text/plain', + * 'Trailer': 'Content-MD5' }); + * message.write(fileData); + * message.addTrailers({ 'Content-MD5': '7895bf4b8828b55ceaf47747b4bca667' }); + * message.end(); + * ``` + * + * Attempting to set a header field name or value that contains invalid characters + * will result in a `TypeError` being thrown. + * @since v0.3.0 + */ + addTrailers(headers: OutgoingHttpHeaders | ReadonlyArray<[string, string]>): void; + /** + * Flushes the message headers. + * + * For efficiency reason, Node.js normally buffers the message headers + * until `outgoingMessage.end()` is called or the first chunk of message data + * is written. It then tries to pack the headers and data into a single TCP + * packet. + * + * It is usually desired (it saves a TCP round-trip), but not when the first + * data is not sent until possibly much later. `outgoingMessage.flushHeaders()` bypasses the optimization and kickstarts the message. + * @since v1.6.0 + */ + flushHeaders(): void; + // #region InternalEventEmitter + addListener<E extends keyof OutgoingMessageEventMap>( + eventName: E, + listener: (...args: OutgoingMessageEventMap[E]) => void, + ): this; + addListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + emit<E extends keyof OutgoingMessageEventMap>(eventName: E, ...args: OutgoingMessageEventMap[E]): boolean; + emit(eventName: string | symbol, ...args: any[]): boolean; + listenerCount<E extends keyof OutgoingMessageEventMap>( + eventName: E, + listener?: (...args: OutgoingMessageEventMap[E]) => void, + ): number; + listenerCount(eventName: string | symbol, listener?: (...args: any[]) => void): number; + listeners<E extends keyof OutgoingMessageEventMap>( + eventName: E, + ): ((...args: OutgoingMessageEventMap[E]) => void)[]; + listeners(eventName: string | symbol): ((...args: any[]) => void)[]; + off<E extends keyof OutgoingMessageEventMap>( + eventName: E, + listener: (...args: OutgoingMessageEventMap[E]) => void, + ): this; + off(eventName: string | symbol, listener: (...args: any[]) => void): this; + on<E extends keyof OutgoingMessageEventMap>( + eventName: E, + listener: (...args: OutgoingMessageEventMap[E]) => void, + ): this; + on(eventName: string | symbol, listener: (...args: any[]) => void): this; + once<E extends keyof OutgoingMessageEventMap>( + eventName: E, + listener: (...args: OutgoingMessageEventMap[E]) => void, + ): this; + once(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependListener<E extends keyof OutgoingMessageEventMap>( + eventName: E, + listener: (...args: OutgoingMessageEventMap[E]) => void, + ): this; + prependListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependOnceListener<E extends keyof OutgoingMessageEventMap>( + eventName: E, + listener: (...args: OutgoingMessageEventMap[E]) => void, + ): this; + prependOnceListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + rawListeners<E extends keyof OutgoingMessageEventMap>( + eventName: E, + ): ((...args: OutgoingMessageEventMap[E]) => void)[]; + rawListeners(eventName: string | symbol): ((...args: any[]) => void)[]; + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + removeAllListeners<E extends keyof OutgoingMessageEventMap>(eventName?: E): this; + removeAllListeners(eventName?: string | symbol): this; + removeListener<E extends keyof OutgoingMessageEventMap>( + eventName: E, + listener: (...args: OutgoingMessageEventMap[E]) => void, + ): this; + removeListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + // #endregion + } + /** + * This object is created internally by an HTTP server, not by the user. It is + * passed as the second parameter to the `'request'` event. + * @since v0.1.17 + */ + class ServerResponse<Request extends IncomingMessage = IncomingMessage> extends OutgoingMessage<Request> { + /** + * When using implicit headers (not calling `response.writeHead()` explicitly), + * this property controls the status code that will be sent to the client when + * the headers get flushed. + * + * ```js + * response.statusCode = 404; + * ``` + * + * After response header was sent to the client, this property indicates the + * status code which was sent out. + * @since v0.4.0 + */ + statusCode: number; + /** + * When using implicit headers (not calling `response.writeHead()` explicitly), + * this property controls the status message that will be sent to the client when + * the headers get flushed. If this is left as `undefined` then the standard + * message for the status code will be used. + * + * ```js + * response.statusMessage = 'Not found'; + * ``` + * + * After response header was sent to the client, this property indicates the + * status message which was sent out. + * @since v0.11.8 + */ + statusMessage: string; + /** + * If set to `true`, Node.js will check whether the `Content-Length` header value and the size of the body, in bytes, are equal. + * Mismatching the `Content-Length` header value will result + * in an `Error` being thrown, identified by `code:``'ERR_HTTP_CONTENT_LENGTH_MISMATCH'`. + * @since v18.10.0, v16.18.0 + */ + strictContentLength: boolean; + constructor(req: Request); + assignSocket(socket: net.Socket): void; + detachSocket(socket: net.Socket): void; + /** + * Sends an HTTP/1.1 100 Continue message to the client, indicating that + * the request body should be sent. See the `'checkContinue'` event on `Server`. + * @since v0.3.0 + */ + writeContinue(callback?: () => void): void; + /** + * Sends an HTTP/1.1 103 Early Hints message to the client with a Link header, + * indicating that the user agent can preload/preconnect the linked resources. + * The `hints` is an object containing the values of headers to be sent with + * early hints message. The optional `callback` argument will be called when + * the response message has been written. + * + * **Example** + * + * ```js + * const earlyHintsLink = '</styles.css>; rel=preload; as=style'; + * response.writeEarlyHints({ + * 'link': earlyHintsLink, + * }); + * + * const earlyHintsLinks = [ + * '</styles.css>; rel=preload; as=style', + * '</scripts.js>; rel=preload; as=script', + * ]; + * response.writeEarlyHints({ + * 'link': earlyHintsLinks, + * 'x-trace-id': 'id for diagnostics', + * }); + * + * const earlyHintsCallback = () => console.log('early hints message sent'); + * response.writeEarlyHints({ + * 'link': earlyHintsLinks, + * }, earlyHintsCallback); + * ``` + * @since v18.11.0 + * @param hints An object containing the values of headers + * @param callback Will be called when the response message has been written + */ + writeEarlyHints(hints: Record<string, string | string[]>, callback?: () => void): void; + /** + * Sends a response header to the request. The status code is a 3-digit HTTP + * status code, like `404`. The last argument, `headers`, are the response headers. + * Optionally one can give a human-readable `statusMessage` as the second + * argument. + * + * `headers` may be an `Array` where the keys and values are in the same list. + * It is _not_ a list of tuples. So, the even-numbered offsets are key values, + * and the odd-numbered offsets are the associated values. The array is in the same + * format as `request.rawHeaders`. + * + * Returns a reference to the `ServerResponse`, so that calls can be chained. + * + * ```js + * const body = 'hello world'; + * response + * .writeHead(200, { + * 'Content-Length': Buffer.byteLength(body), + * 'Content-Type': 'text/plain', + * }) + * .end(body); + * ``` + * + * This method must only be called once on a message and it must + * be called before `response.end()` is called. + * + * If `response.write()` or `response.end()` are called before calling + * this, the implicit/mutable headers will be calculated and call this function. + * + * When headers have been set with `response.setHeader()`, they will be merged + * with any headers passed to `response.writeHead()`, with the headers passed + * to `response.writeHead()` given precedence. + * + * If this method is called and `response.setHeader()` has not been called, + * it will directly write the supplied header values onto the network channel + * without caching internally, and the `response.getHeader()` on the header + * will not yield the expected result. If progressive population of headers is + * desired with potential future retrieval and modification, use `response.setHeader()` instead. + * + * ```js + * // Returns content-type = text/plain + * const server = http.createServer((req, res) => { + * res.setHeader('Content-Type', 'text/html'); + * res.setHeader('X-Foo', 'bar'); + * res.writeHead(200, { 'Content-Type': 'text/plain' }); + * res.end('ok'); + * }); + * ``` + * + * `Content-Length` is read in bytes, not characters. Use `Buffer.byteLength()` to determine the length of the body in bytes. Node.js + * will check whether `Content-Length` and the length of the body which has + * been transmitted are equal or not. + * + * Attempting to set a header field name or value that contains invalid characters + * will result in a \[`Error`\]\[\] being thrown. + * @since v0.1.30 + */ + writeHead( + statusCode: number, + statusMessage?: string, + headers?: OutgoingHttpHeaders | OutgoingHttpHeader[], + ): this; + writeHead(statusCode: number, headers?: OutgoingHttpHeaders | OutgoingHttpHeader[]): this; + /** + * Sends a HTTP/1.1 102 Processing message to the client, indicating that + * the request body should be sent. + * @since v10.0.0 + */ + writeProcessing(callback?: () => void): void; + } + interface InformationEvent { + httpVersion: string; + httpVersionMajor: number; + httpVersionMinor: number; + statusCode: number; + statusMessage: string; + headers: IncomingHttpHeaders; + rawHeaders: string[]; + } + interface ClientRequestEventMap extends stream.WritableEventMap { + /** @deprecated Listen for the `'close'` event instead. */ + "abort": []; + "connect": [response: IncomingMessage, socket: net.Socket, head: NonSharedBuffer]; + "continue": []; + "information": [info: InformationEvent]; + "response": [response: IncomingMessage]; + "socket": [socket: net.Socket]; + "timeout": []; + "upgrade": [response: IncomingMessage, socket: net.Socket, head: NonSharedBuffer]; + } + /** + * This object is created internally and returned from {@link request}. It + * represents an _in-progress_ request whose header has already been queued. The + * header is still mutable using the `setHeader(name, value)`, `getHeader(name)`, `removeHeader(name)` API. The actual header will + * be sent along with the first data chunk or when calling `request.end()`. + * + * To get the response, add a listener for `'response'` to the request object. `'response'` will be emitted from the request object when the response + * headers have been received. The `'response'` event is executed with one + * argument which is an instance of {@link IncomingMessage}. + * + * During the `'response'` event, one can add listeners to the + * response object; particularly to listen for the `'data'` event. + * + * If no `'response'` handler is added, then the response will be + * entirely discarded. However, if a `'response'` event handler is added, + * then the data from the response object **must** be consumed, either by + * calling `response.read()` whenever there is a `'readable'` event, or + * by adding a `'data'` handler, or by calling the `.resume()` method. + * Until the data is consumed, the `'end'` event will not fire. Also, until + * the data is read it will consume memory that can eventually lead to a + * 'process out of memory' error. + * + * For backward compatibility, `res` will only emit `'error'` if there is an `'error'` listener registered. + * + * Set `Content-Length` header to limit the response body size. + * If `response.strictContentLength` is set to `true`, mismatching the `Content-Length` header value will result in an `Error` being thrown, + * identified by `code:``'ERR_HTTP_CONTENT_LENGTH_MISMATCH'`. + * + * `Content-Length` value should be in bytes, not characters. Use `Buffer.byteLength()` to determine the length of the body in bytes. + * @since v0.1.17 + */ + class ClientRequest extends OutgoingMessage { + /** + * The `request.aborted` property will be `true` if the request has + * been aborted. + * @since v0.11.14 + * @deprecated Since v17.0.0, v16.12.0 - Check `destroyed` instead. + */ + aborted: boolean; + /** + * The request host. + * @since v14.5.0, v12.19.0 + */ + host: string; + /** + * The request protocol. + * @since v14.5.0, v12.19.0 + */ + protocol: string; + /** + * When sending request through a keep-alive enabled agent, the underlying socket + * might be reused. But if server closes connection at unfortunate time, client + * may run into a 'ECONNRESET' error. + * + * ```js + * import http from 'node:http'; + * const agent = new http.Agent({ keepAlive: true }); + * + * // Server has a 5 seconds keep-alive timeout by default + * http + * .createServer((req, res) => { + * res.write('hello\n'); + * res.end(); + * }) + * .listen(3000); + * + * setInterval(() => { + * // Adapting a keep-alive agent + * http.get('http://localhost:3000', { agent }, (res) => { + * res.on('data', (data) => { + * // Do nothing + * }); + * }); + * }, 5000); // Sending request on 5s interval so it's easy to hit idle timeout + * ``` + * + * By marking a request whether it reused socket or not, we can do + * automatic error retry base on it. + * + * ```js + * import http from 'node:http'; + * const agent = new http.Agent({ keepAlive: true }); + * + * function retriableRequest() { + * const req = http + * .get('http://localhost:3000', { agent }, (res) => { + * // ... + * }) + * .on('error', (err) => { + * // Check if retry is needed + * if (req.reusedSocket && err.code === 'ECONNRESET') { + * retriableRequest(); + * } + * }); + * } + * + * retriableRequest(); + * ``` + * @since v13.0.0, v12.16.0 + */ + reusedSocket: boolean; + /** + * Limits maximum response headers count. If set to 0, no limit will be applied. + */ + maxHeadersCount: number; + constructor(url: string | URL | ClientRequestArgs, cb?: (res: IncomingMessage) => void); + /** + * The request method. + * @since v0.1.97 + */ + method: string; + /** + * The request path. + * @since v0.4.0 + */ + path: string; + /** + * Marks the request as aborting. Calling this will cause remaining data + * in the response to be dropped and the socket to be destroyed. + * @since v0.3.8 + * @deprecated Since v14.1.0,v13.14.0 - Use `destroy` instead. + */ + abort(): void; + onSocket(socket: net.Socket): void; + /** + * Once a socket is assigned to this request and is connected `socket.setTimeout()` will be called. + * @since v0.5.9 + * @param timeout Milliseconds before a request times out. + * @param callback Optional function to be called when a timeout occurs. Same as binding to the `'timeout'` event. + */ + setTimeout(timeout: number, callback?: () => void): this; + /** + * Once a socket is assigned to this request and is connected `socket.setNoDelay()` will be called. + * @since v0.5.9 + */ + setNoDelay(noDelay?: boolean): void; + /** + * Once a socket is assigned to this request and is connected `socket.setKeepAlive()` will be called. + * @since v0.5.9 + */ + setSocketKeepAlive(enable?: boolean, initialDelay?: number): void; + /** + * Returns an array containing the unique names of the current outgoing raw + * headers. Header names are returned with their exact casing being set. + * + * ```js + * request.setHeader('Foo', 'bar'); + * request.setHeader('Set-Cookie', ['foo=bar', 'bar=baz']); + * + * const headerNames = request.getRawHeaderNames(); + * // headerNames === ['Foo', 'Set-Cookie'] + * ``` + * @since v15.13.0, v14.17.0 + */ + getRawHeaderNames(): string[]; + // #region InternalEventEmitter + addListener<E extends keyof ClientRequestEventMap>( + eventName: E, + listener: (...args: ClientRequestEventMap[E]) => void, + ): this; + addListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + emit<E extends keyof ClientRequestEventMap>(eventName: E, ...args: ClientRequestEventMap[E]): boolean; + emit(eventName: string | symbol, ...args: any[]): boolean; + listenerCount<E extends keyof ClientRequestEventMap>( + eventName: E, + listener?: (...args: ClientRequestEventMap[E]) => void, + ): number; + listenerCount(eventName: string | symbol, listener?: (...args: any[]) => void): number; + listeners<E extends keyof ClientRequestEventMap>(eventName: E): ((...args: ClientRequestEventMap[E]) => void)[]; + listeners(eventName: string | symbol): ((...args: any[]) => void)[]; + off<E extends keyof ClientRequestEventMap>( + eventName: E, + listener: (...args: ClientRequestEventMap[E]) => void, + ): this; + off(eventName: string | symbol, listener: (...args: any[]) => void): this; + on<E extends keyof ClientRequestEventMap>( + eventName: E, + listener: (...args: ClientRequestEventMap[E]) => void, + ): this; + on(eventName: string | symbol, listener: (...args: any[]) => void): this; + once<E extends keyof ClientRequestEventMap>( + eventName: E, + listener: (...args: ClientRequestEventMap[E]) => void, + ): this; + once(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependListener<E extends keyof ClientRequestEventMap>( + eventName: E, + listener: (...args: ClientRequestEventMap[E]) => void, + ): this; + prependListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependOnceListener<E extends keyof ClientRequestEventMap>( + eventName: E, + listener: (...args: ClientRequestEventMap[E]) => void, + ): this; + prependOnceListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + rawListeners<E extends keyof ClientRequestEventMap>( + eventName: E, + ): ((...args: ClientRequestEventMap[E]) => void)[]; + rawListeners(eventName: string | symbol): ((...args: any[]) => void)[]; + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + removeAllListeners<E extends keyof ClientRequestEventMap>(eventName?: E): this; + removeAllListeners(eventName?: string | symbol): this; + removeListener<E extends keyof ClientRequestEventMap>( + eventName: E, + listener: (...args: ClientRequestEventMap[E]) => void, + ): this; + removeListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + // #endregion + } + interface IncomingMessageEventMap extends stream.ReadableEventMap { + /** @deprecated Listen for `'close'` event instead. */ + "aborted": []; + } + /** + * An `IncomingMessage` object is created by {@link Server} or {@link ClientRequest} and passed as the first argument to the `'request'` and `'response'` event respectively. It may be used to + * access response + * status, headers, and data. + * + * Different from its `socket` value which is a subclass of `stream.Duplex`, the `IncomingMessage` itself extends `stream.Readable` and is created separately to + * parse and emit the incoming HTTP headers and payload, as the underlying socket + * may be reused multiple times in case of keep-alive. + * @since v0.1.17 + */ + class IncomingMessage extends stream.Readable { + constructor(socket: net.Socket); + /** + * The `message.aborted` property will be `true` if the request has + * been aborted. + * @since v10.1.0 + * @deprecated Since v17.0.0,v16.12.0 - Check `message.destroyed` from <a href="stream.html#class-streamreadable" class="type">stream.Readable</a>. + */ + aborted: boolean; + /** + * In case of server request, the HTTP version sent by the client. In the case of + * client response, the HTTP version of the connected-to server. + * Probably either `'1.1'` or `'1.0'`. + * + * Also `message.httpVersionMajor` is the first integer and `message.httpVersionMinor` is the second. + * @since v0.1.1 + */ + httpVersion: string; + httpVersionMajor: number; + httpVersionMinor: number; + /** + * The `message.complete` property will be `true` if a complete HTTP message has + * been received and successfully parsed. + * + * This property is particularly useful as a means of determining if a client or + * server fully transmitted a message before a connection was terminated: + * + * ```js + * const req = http.request({ + * host: '127.0.0.1', + * port: 8080, + * method: 'POST', + * }, (res) => { + * res.resume(); + * res.on('end', () => { + * if (!res.complete) + * console.error( + * 'The connection was terminated while the message was still being sent'); + * }); + * }); + * ``` + * @since v0.3.0 + */ + complete: boolean; + /** + * Alias for `message.socket`. + * @since v0.1.90 + * @deprecated Since v16.0.0 - Use `socket`. + */ + connection: net.Socket; + /** + * The `net.Socket` object associated with the connection. + * + * With HTTPS support, use `request.socket.getPeerCertificate()` to obtain the + * client's authentication details. + * + * This property is guaranteed to be an instance of the `net.Socket` class, + * a subclass of `stream.Duplex`, unless the user specified a socket + * type other than `net.Socket` or internally nulled. + * @since v0.3.0 + */ + socket: net.Socket; + /** + * The request/response headers object. + * + * Key-value pairs of header names and values. Header names are lower-cased. + * + * ```js + * // Prints something like: + * // + * // { 'user-agent': 'curl/7.22.0', + * // host: '127.0.0.1:8000', + * // accept: '*' } + * console.log(request.headers); + * ``` + * + * Duplicates in raw headers are handled in the following ways, depending on the + * header name: + * + * * Duplicates of `age`, `authorization`, `content-length`, `content-type`, `etag`, `expires`, `from`, `host`, `if-modified-since`, `if-unmodified-since`, `last-modified`, `location`, + * `max-forwards`, `proxy-authorization`, `referer`, `retry-after`, `server`, or `user-agent` are discarded. + * To allow duplicate values of the headers listed above to be joined, + * use the option `joinDuplicateHeaders` in {@link request} and {@link createServer}. See RFC 9110 Section 5.3 for more + * information. + * * `set-cookie` is always an array. Duplicates are added to the array. + * * For duplicate `cookie` headers, the values are joined together with `; `. + * * For all other headers, the values are joined together with `, `. + * @since v0.1.5 + */ + headers: IncomingHttpHeaders; + /** + * Similar to `message.headers`, but there is no join logic and the values are + * always arrays of strings, even for headers received just once. + * + * ```js + * // Prints something like: + * // + * // { 'user-agent': ['curl/7.22.0'], + * // host: ['127.0.0.1:8000'], + * // accept: ['*'] } + * console.log(request.headersDistinct); + * ``` + * @since v18.3.0, v16.17.0 + */ + headersDistinct: NodeJS.Dict<string[]>; + /** + * The raw request/response headers list exactly as they were received. + * + * The keys and values are in the same list. It is _not_ a + * list of tuples. So, the even-numbered offsets are key values, and the + * odd-numbered offsets are the associated values. + * + * Header names are not lowercased, and duplicates are not merged. + * + * ```js + * // Prints something like: + * // + * // [ 'user-agent', + * // 'this is invalid because there can be only one', + * // 'User-Agent', + * // 'curl/7.22.0', + * // 'Host', + * // '127.0.0.1:8000', + * // 'ACCEPT', + * // '*' ] + * console.log(request.rawHeaders); + * ``` + * @since v0.11.6 + */ + rawHeaders: string[]; + /** + * The request/response trailers object. Only populated at the `'end'` event. + * @since v0.3.0 + */ + trailers: NodeJS.Dict<string>; + /** + * Similar to `message.trailers`, but there is no join logic and the values are + * always arrays of strings, even for headers received just once. + * Only populated at the `'end'` event. + * @since v18.3.0, v16.17.0 + */ + trailersDistinct: NodeJS.Dict<string[]>; + /** + * The raw request/response trailer keys and values exactly as they were + * received. Only populated at the `'end'` event. + * @since v0.11.6 + */ + rawTrailers: string[]; + /** + * Calls `message.socket.setTimeout(msecs, callback)`. + * @since v0.5.9 + */ + setTimeout(msecs: number, callback?: () => void): this; + /** + * **Only valid for request obtained from {@link Server}.** + * + * The request method as a string. Read only. Examples: `'GET'`, `'DELETE'`. + * @since v0.1.1 + */ + method?: string | undefined; + /** + * **Only valid for request obtained from {@link Server}.** + * + * Request URL string. This contains only the URL that is present in the actual + * HTTP request. Take the following request: + * + * ```http + * GET /status?name=ryan HTTP/1.1 + * Accept: text/plain + * ``` + * + * To parse the URL into its parts: + * + * ```js + * new URL(`http://${process.env.HOST ?? 'localhost'}${request.url}`); + * ``` + * + * When `request.url` is `'/status?name=ryan'` and `process.env.HOST` is undefined: + * + * ```console + * $ node + * > new URL(`http://${process.env.HOST ?? 'localhost'}${request.url}`); + * URL { + * href: 'http://localhost/status?name=ryan', + * origin: 'http://localhost', + * protocol: 'http:', + * username: '', + * password: '', + * host: 'localhost', + * hostname: 'localhost', + * port: '', + * pathname: '/status', + * search: '?name=ryan', + * searchParams: URLSearchParams { 'name' => 'ryan' }, + * hash: '' + * } + * ``` + * + * Ensure that you set `process.env.HOST` to the server's host name, or consider replacing this part entirely. If using `req.headers.host`, ensure proper + * validation is used, as clients may specify a custom `Host` header. + * @since v0.1.90 + */ + url?: string | undefined; + /** + * **Only valid for response obtained from {@link ClientRequest}.** + * + * The 3-digit HTTP response status code. E.G. `404`. + * @since v0.1.1 + */ + statusCode?: number | undefined; + /** + * **Only valid for response obtained from {@link ClientRequest}.** + * + * The HTTP response status message (reason phrase). E.G. `OK` or `Internal Server Error`. + * @since v0.11.10 + */ + statusMessage?: string | undefined; + /** + * Calls `destroy()` on the socket that received the `IncomingMessage`. If `error` is provided, an `'error'` event is emitted on the socket and `error` is passed + * as an argument to any listeners on the event. + * @since v0.3.0 + */ + destroy(error?: Error): this; + // #region InternalEventEmitter + addListener<E extends keyof IncomingMessageEventMap>( + eventName: E, + listener: (...args: IncomingMessageEventMap[E]) => void, + ): this; + addListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + emit<E extends keyof IncomingMessageEventMap>(eventName: E, ...args: IncomingMessageEventMap[E]): boolean; + emit(eventName: string | symbol, ...args: any[]): boolean; + listenerCount<E extends keyof IncomingMessageEventMap>( + eventName: E, + listener?: (...args: IncomingMessageEventMap[E]) => void, + ): number; + listenerCount(eventName: string | symbol, listener?: (...args: any[]) => void): number; + listeners<E extends keyof IncomingMessageEventMap>( + eventName: E, + ): ((...args: IncomingMessageEventMap[E]) => void)[]; + listeners(eventName: string | symbol): ((...args: any[]) => void)[]; + off<E extends keyof IncomingMessageEventMap>( + eventName: E, + listener: (...args: IncomingMessageEventMap[E]) => void, + ): this; + off(eventName: string | symbol, listener: (...args: any[]) => void): this; + on<E extends keyof IncomingMessageEventMap>( + eventName: E, + listener: (...args: IncomingMessageEventMap[E]) => void, + ): this; + on(eventName: string | symbol, listener: (...args: any[]) => void): this; + once<E extends keyof IncomingMessageEventMap>( + eventName: E, + listener: (...args: IncomingMessageEventMap[E]) => void, + ): this; + once(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependListener<E extends keyof IncomingMessageEventMap>( + eventName: E, + listener: (...args: IncomingMessageEventMap[E]) => void, + ): this; + prependListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependOnceListener<E extends keyof IncomingMessageEventMap>( + eventName: E, + listener: (...args: IncomingMessageEventMap[E]) => void, + ): this; + prependOnceListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + rawListeners<E extends keyof IncomingMessageEventMap>( + eventName: E, + ): ((...args: IncomingMessageEventMap[E]) => void)[]; + rawListeners(eventName: string | symbol): ((...args: any[]) => void)[]; + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + removeAllListeners<E extends keyof IncomingMessageEventMap>(eventName?: E): this; + removeAllListeners(eventName?: string | symbol): this; + removeListener<E extends keyof IncomingMessageEventMap>( + eventName: E, + listener: (...args: IncomingMessageEventMap[E]) => void, + ): this; + removeListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + // #endregion + } + interface ProxyEnv extends NodeJS.ProcessEnv { + HTTP_PROXY?: string | undefined; + HTTPS_PROXY?: string | undefined; + NO_PROXY?: string | undefined; + http_proxy?: string | undefined; + https_proxy?: string | undefined; + no_proxy?: string | undefined; + } + interface AgentOptions extends NodeJS.PartialOptions<net.TcpSocketConnectOpts> { + /** + * Keep sockets around in a pool to be used by other requests in the future. Default = false + */ + keepAlive?: boolean | undefined; + /** + * When using HTTP KeepAlive, how often to send TCP KeepAlive packets over sockets being kept alive. Default = 1000. + * Only relevant if keepAlive is set to true. + */ + keepAliveMsecs?: number | undefined; + /** + * Milliseconds to subtract from + * the server-provided `keep-alive: timeout=...` hint when determining socket + * expiration time. This buffer helps ensure the agent closes the socket + * slightly before the server does, reducing the chance of sending a request + * on a socket that’s about to be closed by the server. + * @since v24.7.0 + * @default 1000 + */ + agentKeepAliveTimeoutBuffer?: number | undefined; + /** + * Maximum number of sockets to allow per host. Default for Node 0.10 is 5, default for Node 0.12 is Infinity + */ + maxSockets?: number | undefined; + /** + * Maximum number of sockets allowed for all hosts in total. Each request will use a new socket until the maximum is reached. Default: Infinity. + */ + maxTotalSockets?: number | undefined; + /** + * Maximum number of sockets to leave open in a free state. Only relevant if keepAlive is set to true. Default = 256. + */ + maxFreeSockets?: number | undefined; + /** + * Socket timeout in milliseconds. This will set the timeout after the socket is connected. + */ + timeout?: number | undefined; + /** + * Scheduling strategy to apply when picking the next free socket to use. + * @default `lifo` + */ + scheduling?: "fifo" | "lifo" | undefined; + /** + * Environment variables for proxy configuration. See + * [Built-in Proxy Support](https://nodejs.org/docs/latest-v25.x/api/http.html#built-in-proxy-support) for details. + * @since v24.5.0 + */ + proxyEnv?: ProxyEnv | undefined; + /** + * Default port to use when the port is not specified in requests. + * @since v24.5.0 + */ + defaultPort?: number | undefined; + /** + * The protocol to use for the agent. + * @since v24.5.0 + */ + protocol?: string | undefined; + } + /** + * An `Agent` is responsible for managing connection persistence + * and reuse for HTTP clients. It maintains a queue of pending requests + * for a given host and port, reusing a single socket connection for each + * until the queue is empty, at which time the socket is either destroyed + * or put into a pool where it is kept to be used again for requests to the + * same host and port. Whether it is destroyed or pooled depends on the `keepAlive` `option`. + * + * Pooled connections have TCP Keep-Alive enabled for them, but servers may + * still close idle connections, in which case they will be removed from the + * pool and a new connection will be made when a new HTTP request is made for + * that host and port. Servers may also refuse to allow multiple requests + * over the same connection, in which case the connection will have to be + * remade for every request and cannot be pooled. The `Agent` will still make + * the requests to that server, but each one will occur over a new connection. + * + * When a connection is closed by the client or the server, it is removed + * from the pool. Any unused sockets in the pool will be unrefed so as not + * to keep the Node.js process running when there are no outstanding requests. + * (see `socket.unref()`). + * + * It is good practice, to `destroy()` an `Agent` instance when it is no + * longer in use, because unused sockets consume OS resources. + * + * Sockets are removed from an agent when the socket emits either + * a `'close'` event or an `'agentRemove'` event. When intending to keep one + * HTTP request open for a long time without keeping it in the agent, something + * like the following may be done: + * + * ```js + * http.get(options, (res) => { + * // Do stuff + * }).on('socket', (socket) => { + * socket.emit('agentRemove'); + * }); + * ``` + * + * An agent may also be used for an individual request. By providing `{agent: false}` as an option to the `http.get()` or `http.request()` functions, a one-time use `Agent` with default options + * will be used + * for the client connection. + * + * `agent:false`: + * + * ```js + * http.get({ + * hostname: 'localhost', + * port: 80, + * path: '/', + * agent: false, // Create a new agent just for this one request + * }, (res) => { + * // Do stuff with response + * }); + * ``` + * + * `options` in [`socket.connect()`](https://nodejs.org/docs/latest-v25.x/api/net.html#socketconnectoptions-connectlistener) are also supported. + * + * To configure any of them, a custom {@link Agent} instance must be created. + * + * ```js + * import http from 'node:http'; + * const keepAliveAgent = new http.Agent({ keepAlive: true }); + * options.agent = keepAliveAgent; + * http.request(options, onResponseCallback) + * ``` + * @since v0.3.4 + */ + class Agent extends EventEmitter { + /** + * By default set to 256. For agents with `keepAlive` enabled, this + * sets the maximum number of sockets that will be left open in the free + * state. + * @since v0.11.7 + */ + maxFreeSockets: number; + /** + * By default set to `Infinity`. Determines how many concurrent sockets the agent + * can have open per origin. Origin is the returned value of `agent.getName()`. + * @since v0.3.6 + */ + maxSockets: number; + /** + * By default set to `Infinity`. Determines how many concurrent sockets the agent + * can have open. Unlike `maxSockets`, this parameter applies across all origins. + * @since v14.5.0, v12.19.0 + */ + maxTotalSockets: number; + /** + * An object which contains arrays of sockets currently awaiting use by + * the agent when `keepAlive` is enabled. Do not modify. + * + * Sockets in the `freeSockets` list will be automatically destroyed and + * removed from the array on `'timeout'`. + * @since v0.11.4 + */ + readonly freeSockets: NodeJS.ReadOnlyDict<net.Socket[]>; + /** + * An object which contains arrays of sockets currently in use by the + * agent. Do not modify. + * @since v0.3.6 + */ + readonly sockets: NodeJS.ReadOnlyDict<net.Socket[]>; + /** + * An object which contains queues of requests that have not yet been assigned to + * sockets. Do not modify. + * @since v0.5.9 + */ + readonly requests: NodeJS.ReadOnlyDict<ClientRequest[]>; + constructor(opts?: AgentOptions); + /** + * Destroy any sockets that are currently in use by the agent. + * + * It is usually not necessary to do this. However, if using an + * agent with `keepAlive` enabled, then it is best to explicitly shut down + * the agent when it is no longer needed. Otherwise, + * sockets might stay open for quite a long time before the server + * terminates them. + * @since v0.11.4 + */ + destroy(): void; + /** + * Produces a socket/stream to be used for HTTP requests. + * + * By default, this function behaves identically to `net.createConnection()`, + * synchronously returning the created socket. The optional `callback` parameter in the + * signature is **not** used by this default implementation. + * + * However, custom agents may override this method to provide greater flexibility, + * for example, to create sockets asynchronously. When overriding `createConnection`: + * + * 1. **Synchronous socket creation**: The overriding method can return the + * socket/stream directly. + * 2. **Asynchronous socket creation**: The overriding method can accept the `callback` + * and pass the created socket/stream to it (e.g., `callback(null, newSocket)`). + * If an error occurs during socket creation, it should be passed as the first + * argument to the `callback` (e.g., `callback(err)`). + * + * The agent will call the provided `createConnection` function with `options` and + * this internal `callback`. The `callback` provided by the agent has a signature + * of `(err, stream)`. + * @since v0.11.4 + * @param options Options containing connection details. Check + * `net.createConnection` for the format of the options. For custom agents, + * this object is passed to the custom `createConnection` function. + * @param callback (Optional, primarily for custom agents) A function to be + * called by a custom `createConnection` implementation when the socket is + * created, especially for asynchronous operations. + * @returns The created socket. This is returned by the default + * implementation or by a custom synchronous `createConnection` implementation. + * If a custom `createConnection` uses the `callback` for asynchronous + * operation, this return value might not be the primary way to obtain the socket. + */ + createConnection( + options: ClientRequestArgs, + callback?: (err: Error | null, stream: stream.Duplex) => void, + ): stream.Duplex | null | undefined; + /** + * Called when `socket` is detached from a request and could be persisted by the`Agent`. Default behavior is to: + * + * ```js + * socket.setKeepAlive(true, this.keepAliveMsecs); + * socket.unref(); + * return true; + * ``` + * + * This method can be overridden by a particular `Agent` subclass. If this + * method returns a falsy value, the socket will be destroyed instead of persisting + * it for use with the next request. + * + * The `socket` argument can be an instance of `net.Socket`, a subclass of `stream.Duplex`. + * @since v8.1.0 + */ + keepSocketAlive(socket: stream.Duplex): void; + /** + * Called when `socket` is attached to `request` after being persisted because of + * the keep-alive options. Default behavior is to: + * + * ```js + * socket.ref(); + * ``` + * + * This method can be overridden by a particular `Agent` subclass. + * + * The `socket` argument can be an instance of `net.Socket`, a subclass of `stream.Duplex`. + * @since v8.1.0 + */ + reuseSocket(socket: stream.Duplex, request: ClientRequest): void; + /** + * Get a unique name for a set of request options, to determine whether a + * connection can be reused. For an HTTP agent, this returns`host:port:localAddress` or `host:port:localAddress:family`. For an HTTPS agent, + * the name includes the CA, cert, ciphers, and other HTTPS/TLS-specific options + * that determine socket reusability. + * @since v0.11.4 + * @param options A set of options providing information for name generation + */ + getName(options?: ClientRequestArgs): string; + } + const METHODS: string[]; + const STATUS_CODES: { + [errorCode: number]: string | undefined; + [errorCode: string]: string | undefined; + }; + /** + * Returns a new instance of {@link Server}. + * + * The `requestListener` is a function which is automatically + * added to the `'request'` event. + * + * ```js + * import http from 'node:http'; + * + * // Create a local server to receive data from + * const server = http.createServer((req, res) => { + * res.writeHead(200, { 'Content-Type': 'application/json' }); + * res.end(JSON.stringify({ + * data: 'Hello World!', + * })); + * }); + * + * server.listen(8000); + * ``` + * + * ```js + * import http from 'node:http'; + * + * // Create a local server to receive data from + * const server = http.createServer(); + * + * // Listen to the request event + * server.on('request', (request, res) => { + * res.writeHead(200, { 'Content-Type': 'application/json' }); + * res.end(JSON.stringify({ + * data: 'Hello World!', + * })); + * }); + * + * server.listen(8000); + * ``` + * @since v0.1.13 + */ + function createServer< + Request extends typeof IncomingMessage = typeof IncomingMessage, + Response extends typeof ServerResponse<InstanceType<Request>> = typeof ServerResponse, + >(requestListener?: RequestListener<Request, Response>): Server<Request, Response>; + function createServer< + Request extends typeof IncomingMessage = typeof IncomingMessage, + Response extends typeof ServerResponse<InstanceType<Request>> = typeof ServerResponse, + >( + options: ServerOptions<Request, Response>, + requestListener?: RequestListener<Request, Response>, + ): Server<Request, Response>; + // although RequestOptions are passed as ClientRequestArgs to ClientRequest directly, + // create interface RequestOptions would make the naming more clear to developers + interface RequestOptions extends ClientRequestArgs {} + /** + * `options` in `socket.connect()` are also supported. + * + * Node.js maintains several connections per server to make HTTP requests. + * This function allows one to transparently issue requests. + * + * `url` can be a string or a `URL` object. If `url` is a + * string, it is automatically parsed with `new URL()`. If it is a `URL` object, it will be automatically converted to an ordinary `options` object. + * + * If both `url` and `options` are specified, the objects are merged, with the `options` properties taking precedence. + * + * The optional `callback` parameter will be added as a one-time listener for + * the `'response'` event. + * + * `http.request()` returns an instance of the {@link ClientRequest} class. The `ClientRequest` instance is a writable stream. If one needs to + * upload a file with a POST request, then write to the `ClientRequest` object. + * + * ```js + * import http from 'node:http'; + * import { Buffer } from 'node:buffer'; + * + * const postData = JSON.stringify({ + * 'msg': 'Hello World!', + * }); + * + * const options = { + * hostname: 'www.google.com', + * port: 80, + * path: '/upload', + * method: 'POST', + * headers: { + * 'Content-Type': 'application/json', + * 'Content-Length': Buffer.byteLength(postData), + * }, + * }; + * + * const req = http.request(options, (res) => { + * console.log(`STATUS: ${res.statusCode}`); + * console.log(`HEADERS: ${JSON.stringify(res.headers)}`); + * res.setEncoding('utf8'); + * res.on('data', (chunk) => { + * console.log(`BODY: ${chunk}`); + * }); + * res.on('end', () => { + * console.log('No more data in response.'); + * }); + * }); + * + * req.on('error', (e) => { + * console.error(`problem with request: ${e.message}`); + * }); + * + * // Write data to request body + * req.write(postData); + * req.end(); + * ``` + * + * In the example `req.end()` was called. With `http.request()` one + * must always call `req.end()` to signify the end of the request - + * even if there is no data being written to the request body. + * + * If any error is encountered during the request (be that with DNS resolution, + * TCP level errors, or actual HTTP parse errors) an `'error'` event is emitted + * on the returned request object. As with all `'error'` events, if no listeners + * are registered the error will be thrown. + * + * There are a few special headers that should be noted. + * + * * Sending a 'Connection: keep-alive' will notify Node.js that the connection to + * the server should be persisted until the next request. + * * Sending a 'Content-Length' header will disable the default chunked encoding. + * * Sending an 'Expect' header will immediately send the request headers. + * Usually, when sending 'Expect: 100-continue', both a timeout and a listener + * for the `'continue'` event should be set. See RFC 2616 Section 8.2.3 for more + * information. + * * Sending an Authorization header will override using the `auth` option + * to compute basic authentication. + * + * Example using a `URL` as `options`: + * + * ```js + * const options = new URL('http://abc:xyz@example.com'); + * + * const req = http.request(options, (res) => { + * // ... + * }); + * ``` + * + * In a successful request, the following events will be emitted in the following + * order: + * + * * `'socket'` + * * `'response'` + * * `'data'` any number of times, on the `res` object + * (`'data'` will not be emitted at all if the response body is empty, for + * instance, in most redirects) + * * `'end'` on the `res` object + * * `'close'` + * + * In the case of a connection error, the following events will be emitted: + * + * * `'socket'` + * * `'error'` + * * `'close'` + * + * In the case of a premature connection close before the response is received, + * the following events will be emitted in the following order: + * + * * `'socket'` + * * `'error'` with an error with message `'Error: socket hang up'` and code `'ECONNRESET'` + * * `'close'` + * + * In the case of a premature connection close after the response is received, + * the following events will be emitted in the following order: + * + * * `'socket'` + * * `'response'` + * * `'data'` any number of times, on the `res` object + * * (connection closed here) + * * `'aborted'` on the `res` object + * * `'close'` + * * `'error'` on the `res` object with an error with message `'Error: aborted'` and code `'ECONNRESET'` + * * `'close'` on the `res` object + * + * If `req.destroy()` is called before a socket is assigned, the following + * events will be emitted in the following order: + * + * * (`req.destroy()` called here) + * * `'error'` with an error with message `'Error: socket hang up'` and code `'ECONNRESET'`, or the error with which `req.destroy()` was called + * * `'close'` + * + * If `req.destroy()` is called before the connection succeeds, the following + * events will be emitted in the following order: + * + * * `'socket'` + * * (`req.destroy()` called here) + * * `'error'` with an error with message `'Error: socket hang up'` and code `'ECONNRESET'`, or the error with which `req.destroy()` was called + * * `'close'` + * + * If `req.destroy()` is called after the response is received, the following + * events will be emitted in the following order: + * + * * `'socket'` + * * `'response'` + * * `'data'` any number of times, on the `res` object + * * (`req.destroy()` called here) + * * `'aborted'` on the `res` object + * * `'close'` + * * `'error'` on the `res` object with an error with message `'Error: aborted'` and code `'ECONNRESET'`, or the error with which `req.destroy()` was called + * * `'close'` on the `res` object + * + * If `req.abort()` is called before a socket is assigned, the following + * events will be emitted in the following order: + * + * * (`req.abort()` called here) + * * `'abort'` + * * `'close'` + * + * If `req.abort()` is called before the connection succeeds, the following + * events will be emitted in the following order: + * + * * `'socket'` + * * (`req.abort()` called here) + * * `'abort'` + * * `'error'` with an error with message `'Error: socket hang up'` and code `'ECONNRESET'` + * * `'close'` + * + * If `req.abort()` is called after the response is received, the following + * events will be emitted in the following order: + * + * * `'socket'` + * * `'response'` + * * `'data'` any number of times, on the `res` object + * * (`req.abort()` called here) + * * `'abort'` + * * `'aborted'` on the `res` object + * * `'error'` on the `res` object with an error with message `'Error: aborted'` and code `'ECONNRESET'`. + * * `'close'` + * * `'close'` on the `res` object + * + * Setting the `timeout` option or using the `setTimeout()` function will + * not abort the request or do anything besides add a `'timeout'` event. + * + * Passing an `AbortSignal` and then calling `abort()` on the corresponding `AbortController` will behave the same way as calling `.destroy()` on the + * request. Specifically, the `'error'` event will be emitted with an error with + * the message `'AbortError: The operation was aborted'`, the code `'ABORT_ERR'` and the `cause`, if one was provided. + * @since v0.3.6 + */ + function request(options: RequestOptions | string | URL, callback?: (res: IncomingMessage) => void): ClientRequest; + function request( + url: string | URL, + options: RequestOptions, + callback?: (res: IncomingMessage) => void, + ): ClientRequest; + /** + * Since most requests are GET requests without bodies, Node.js provides this + * convenience method. The only difference between this method and {@link request} is that it sets the method to GET by default and calls `req.end()` automatically. The callback must take care to + * consume the response + * data for reasons stated in {@link ClientRequest} section. + * + * The `callback` is invoked with a single argument that is an instance of {@link IncomingMessage}. + * + * JSON fetching example: + * + * ```js + * http.get('http://localhost:8000/', (res) => { + * const { statusCode } = res; + * const contentType = res.headers['content-type']; + * + * let error; + * // Any 2xx status code signals a successful response but + * // here we're only checking for 200. + * if (statusCode !== 200) { + * error = new Error('Request Failed.\n' + + * `Status Code: ${statusCode}`); + * } else if (!/^application\/json/.test(contentType)) { + * error = new Error('Invalid content-type.\n' + + * `Expected application/json but received ${contentType}`); + * } + * if (error) { + * console.error(error.message); + * // Consume response data to free up memory + * res.resume(); + * return; + * } + * + * res.setEncoding('utf8'); + * let rawData = ''; + * res.on('data', (chunk) => { rawData += chunk; }); + * res.on('end', () => { + * try { + * const parsedData = JSON.parse(rawData); + * console.log(parsedData); + * } catch (e) { + * console.error(e.message); + * } + * }); + * }).on('error', (e) => { + * console.error(`Got error: ${e.message}`); + * }); + * + * // Create a local server to receive data from + * const server = http.createServer((req, res) => { + * res.writeHead(200, { 'Content-Type': 'application/json' }); + * res.end(JSON.stringify({ + * data: 'Hello World!', + * })); + * }); + * + * server.listen(8000); + * ``` + * @since v0.3.6 + * @param options Accepts the same `options` as {@link request}, with the method set to GET by default. + */ + function get(options: RequestOptions | string | URL, callback?: (res: IncomingMessage) => void): ClientRequest; + function get(url: string | URL, options: RequestOptions, callback?: (res: IncomingMessage) => void): ClientRequest; + /** + * Performs the low-level validations on the provided `name` that are done when `res.setHeader(name, value)` is called. + * + * Passing illegal value as `name` will result in a `TypeError` being thrown, + * identified by `code: 'ERR_INVALID_HTTP_TOKEN'`. + * + * It is not necessary to use this method before passing headers to an HTTP request + * or response. The HTTP module will automatically validate such headers. + * + * Example: + * + * ```js + * import { validateHeaderName } from 'node:http'; + * + * try { + * validateHeaderName(''); + * } catch (err) { + * console.error(err instanceof TypeError); // --> true + * console.error(err.code); // --> 'ERR_INVALID_HTTP_TOKEN' + * console.error(err.message); // --> 'Header name must be a valid HTTP token [""]' + * } + * ``` + * @since v14.3.0 + * @param [label='Header name'] Label for error message. + */ + function validateHeaderName(name: string): void; + /** + * Performs the low-level validations on the provided `value` that are done when `res.setHeader(name, value)` is called. + * + * Passing illegal value as `value` will result in a `TypeError` being thrown. + * + * * Undefined value error is identified by `code: 'ERR_HTTP_INVALID_HEADER_VALUE'`. + * * Invalid value character error is identified by `code: 'ERR_INVALID_CHAR'`. + * + * It is not necessary to use this method before passing headers to an HTTP request + * or response. The HTTP module will automatically validate such headers. + * + * Examples: + * + * ```js + * import { validateHeaderValue } from 'node:http'; + * + * try { + * validateHeaderValue('x-my-header', undefined); + * } catch (err) { + * console.error(err instanceof TypeError); // --> true + * console.error(err.code === 'ERR_HTTP_INVALID_HEADER_VALUE'); // --> true + * console.error(err.message); // --> 'Invalid value "undefined" for header "x-my-header"' + * } + * + * try { + * validateHeaderValue('x-my-header', 'oʊmɪɡə'); + * } catch (err) { + * console.error(err instanceof TypeError); // --> true + * console.error(err.code === 'ERR_INVALID_CHAR'); // --> true + * console.error(err.message); // --> 'Invalid character in header content ["x-my-header"]' + * } + * ``` + * @since v14.3.0 + * @param name Header name + * @param value Header value + */ + function validateHeaderValue(name: string, value: string): void; + /** + * Set the maximum number of idle HTTP parsers. + * @since v18.8.0, v16.18.0 + * @param [max=1000] + */ + function setMaxIdleHTTPParsers(max: number): void; + /** + * Global instance of `Agent` which is used as the default for all HTTP client + * requests. Diverges from a default `Agent` configuration by having `keepAlive` + * enabled and a `timeout` of 5 seconds. + * @since v0.5.9 + */ + let globalAgent: Agent; + /** + * Read-only property specifying the maximum allowed size of HTTP headers in bytes. + * Defaults to 16KB. Configurable using the `--max-http-header-size` CLI option. + */ + const maxHeaderSize: number; + /** + * A browser-compatible implementation of `WebSocket`. + * @since v22.5.0 + */ + const WebSocket: typeof import("undici-types").WebSocket; + /** + * @since v22.5.0 + */ + const CloseEvent: typeof import("undici-types").CloseEvent; + /** + * @since v22.5.0 + */ + const MessageEvent: typeof import("undici-types").MessageEvent; +} +declare module "http" { + export * from "node:http"; +} diff --git a/server/node_modules/@types/node/http2.d.ts b/server/node_modules/@types/node/http2.d.ts new file mode 100644 index 0000000..4130bfe --- /dev/null +++ b/server/node_modules/@types/node/http2.d.ts @@ -0,0 +1,2480 @@ +/** + * The `node:http2` module provides an implementation of the [HTTP/2](https://tools.ietf.org/html/rfc7540) protocol. + * It can be accessed using: + * + * ```js + * import http2 from 'node:http2'; + * ``` + * @since v8.4.0 + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/http2.js) + */ +declare module "node:http2" { + import { NonSharedBuffer } from "node:buffer"; + import { InternalEventEmitter } from "node:events"; + import * as fs from "node:fs"; + import * as net from "node:net"; + import * as stream from "node:stream"; + import * as tls from "node:tls"; + import * as url from "node:url"; + import { + IncomingHttpHeaders as Http1IncomingHttpHeaders, + IncomingMessage, + OutgoingHttpHeaders, + ServerResponse, + } from "node:http"; + interface IncomingHttpStatusHeader { + ":status"?: number | undefined; + } + interface IncomingHttpHeaders extends Http1IncomingHttpHeaders { + ":path"?: string | undefined; + ":method"?: string | undefined; + ":authority"?: string | undefined; + ":scheme"?: string | undefined; + } + // Http2Stream + interface StreamState { + localWindowSize?: number | undefined; + state?: number | undefined; + localClose?: number | undefined; + remoteClose?: number | undefined; + /** @deprecated */ + sumDependencyWeight?: number | undefined; + /** @deprecated */ + weight?: number | undefined; + } + interface ServerStreamResponseOptions { + endStream?: boolean | undefined; + waitForTrailers?: boolean | undefined; + } + interface StatOptions { + offset: number; + length: number; + } + interface ServerStreamFileResponseOptions { + statCheck?: + | ((stats: fs.Stats, headers: OutgoingHttpHeaders, statOptions: StatOptions) => void) + | undefined; + waitForTrailers?: boolean | undefined; + offset?: number | undefined; + length?: number | undefined; + } + interface ServerStreamFileResponseOptionsWithError extends ServerStreamFileResponseOptions { + onError?: ((err: NodeJS.ErrnoException) => void) | undefined; + } + interface Http2StreamEventMap extends stream.DuplexEventMap { + "aborted": []; + "data": [chunk: string | NonSharedBuffer]; + "frameError": [type: number, code: number, id: number]; + "ready": []; + "streamClosed": [code: number]; + "timeout": []; + "trailers": [trailers: IncomingHttpHeaders, flags: number]; + "wantTrailers": []; + } + interface Http2Stream extends stream.Duplex { + /** + * Set to `true` if the `Http2Stream` instance was aborted abnormally. When set, + * the `'aborted'` event will have been emitted. + * @since v8.4.0 + */ + readonly aborted: boolean; + /** + * This property shows the number of characters currently buffered to be written. + * See `net.Socket.bufferSize` for details. + * @since v11.2.0, v10.16.0 + */ + readonly bufferSize: number; + /** + * Set to `true` if the `Http2Stream` instance has been closed. + * @since v9.4.0 + */ + readonly closed: boolean; + /** + * Set to `true` if the `Http2Stream` instance has been destroyed and is no longer + * usable. + * @since v8.4.0 + */ + readonly destroyed: boolean; + /** + * Set to `true` if the `END_STREAM` flag was set in the request or response + * HEADERS frame received, indicating that no additional data should be received + * and the readable side of the `Http2Stream` will be closed. + * @since v10.11.0 + */ + readonly endAfterHeaders: boolean; + /** + * The numeric stream identifier of this `Http2Stream` instance. Set to `undefined` if the stream identifier has not yet been assigned. + * @since v8.4.0 + */ + readonly id?: number | undefined; + /** + * Set to `true` if the `Http2Stream` instance has not yet been assigned a + * numeric stream identifier. + * @since v9.4.0 + */ + readonly pending: boolean; + /** + * Set to the `RST_STREAM` `error code` reported when the `Http2Stream` is + * destroyed after either receiving an `RST_STREAM` frame from the connected peer, + * calling `http2stream.close()`, or `http2stream.destroy()`. Will be `undefined` if the `Http2Stream` has not been closed. + * @since v8.4.0 + */ + readonly rstCode: number; + /** + * An object containing the outbound headers sent for this `Http2Stream`. + * @since v9.5.0 + */ + readonly sentHeaders: OutgoingHttpHeaders; + /** + * An array of objects containing the outbound informational (additional) headers + * sent for this `Http2Stream`. + * @since v9.5.0 + */ + readonly sentInfoHeaders?: OutgoingHttpHeaders[] | undefined; + /** + * An object containing the outbound trailers sent for this `HttpStream`. + * @since v9.5.0 + */ + readonly sentTrailers?: OutgoingHttpHeaders | undefined; + /** + * A reference to the `Http2Session` instance that owns this `Http2Stream`. The + * value will be `undefined` after the `Http2Stream` instance is destroyed. + * @since v8.4.0 + */ + readonly session: Http2Session | undefined; + /** + * Provides miscellaneous information about the current state of the `Http2Stream`. + * + * A current state of this `Http2Stream`. + * @since v8.4.0 + */ + readonly state: StreamState; + /** + * Closes the `Http2Stream` instance by sending an `RST_STREAM` frame to the + * connected HTTP/2 peer. + * @since v8.4.0 + * @param [code=http2.constants.NGHTTP2_NO_ERROR] Unsigned 32-bit integer identifying the error code. + * @param callback An optional function registered to listen for the `'close'` event. + */ + close(code?: number, callback?: () => void): void; + /** + * @deprecated Priority signaling is no longer supported in Node.js. + */ + priority(options: unknown): void; + /** + * ```js + * import http2 from 'node:http2'; + * const client = http2.connect('http://example.org:8000'); + * const { NGHTTP2_CANCEL } = http2.constants; + * const req = client.request({ ':path': '/' }); + * + * // Cancel the stream if there's no activity after 5 seconds + * req.setTimeout(5000, () => req.close(NGHTTP2_CANCEL)); + * ``` + * @since v8.4.0 + */ + setTimeout(msecs: number, callback?: () => void): void; + /** + * Sends a trailing `HEADERS` frame to the connected HTTP/2 peer. This method + * will cause the `Http2Stream` to be immediately closed and must only be + * called after the `'wantTrailers'` event has been emitted. When sending a + * request or sending a response, the `options.waitForTrailers` option must be set + * in order to keep the `Http2Stream` open after the final `DATA` frame so that + * trailers can be sent. + * + * ```js + * import http2 from 'node:http2'; + * const server = http2.createServer(); + * server.on('stream', (stream) => { + * stream.respond(undefined, { waitForTrailers: true }); + * stream.on('wantTrailers', () => { + * stream.sendTrailers({ xyz: 'abc' }); + * }); + * stream.end('Hello World'); + * }); + * ``` + * + * The HTTP/1 specification forbids trailers from containing HTTP/2 pseudo-header + * fields (e.g. `':method'`, `':path'`, etc). + * @since v10.0.0 + */ + sendTrailers(headers: OutgoingHttpHeaders): void; + // #region InternalEventEmitter + addListener<E extends keyof Http2StreamEventMap>( + eventName: E, + listener: (...args: Http2StreamEventMap[E]) => void, + ): this; + addListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + emit<E extends keyof Http2StreamEventMap>(eventName: E, ...args: Http2StreamEventMap[E]): boolean; + emit(eventName: string | symbol, ...args: any[]): boolean; + listenerCount<E extends keyof Http2StreamEventMap>( + eventName: E, + listener?: (...args: Http2StreamEventMap[E]) => void, + ): number; + listenerCount(eventName: string | symbol, listener?: (...args: any[]) => void): number; + listeners<E extends keyof Http2StreamEventMap>(eventName: E): ((...args: Http2StreamEventMap[E]) => void)[]; + listeners(eventName: string | symbol): ((...args: any[]) => void)[]; + off<E extends keyof Http2StreamEventMap>( + eventName: E, + listener: (...args: Http2StreamEventMap[E]) => void, + ): this; + off(eventName: string | symbol, listener: (...args: any[]) => void): this; + on<E extends keyof Http2StreamEventMap>( + eventName: E, + listener: (...args: Http2StreamEventMap[E]) => void, + ): this; + on(eventName: string | symbol, listener: (...args: any[]) => void): this; + once<E extends keyof Http2StreamEventMap>( + eventName: E, + listener: (...args: Http2StreamEventMap[E]) => void, + ): this; + once(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependListener<E extends keyof Http2StreamEventMap>( + eventName: E, + listener: (...args: Http2StreamEventMap[E]) => void, + ): this; + prependListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependOnceListener<E extends keyof Http2StreamEventMap>( + eventName: E, + listener: (...args: Http2StreamEventMap[E]) => void, + ): this; + prependOnceListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + rawListeners<E extends keyof Http2StreamEventMap>(eventName: E): ((...args: Http2StreamEventMap[E]) => void)[]; + rawListeners(eventName: string | symbol): ((...args: any[]) => void)[]; + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + removeAllListeners<E extends keyof Http2StreamEventMap>(eventName?: E): this; + removeAllListeners(eventName?: string | symbol): this; + removeListener<E extends keyof Http2StreamEventMap>( + eventName: E, + listener: (...args: Http2StreamEventMap[E]) => void, + ): this; + removeListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + // #endregion + } + interface ClientHttp2StreamEventMap extends Http2StreamEventMap { + "continue": []; + "headers": [headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number, rawHeaders: string[]]; + "push": [headers: IncomingHttpHeaders, flags: number]; + "response": [headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number, rawHeaders: string[]]; + } + interface ClientHttp2Stream extends Http2Stream { + // #region InternalEventEmitter + addListener<E extends keyof ClientHttp2StreamEventMap>( + eventName: E, + listener: (...args: ClientHttp2StreamEventMap[E]) => void, + ): this; + addListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + emit<E extends keyof ClientHttp2StreamEventMap>(eventName: E, ...args: ClientHttp2StreamEventMap[E]): boolean; + emit(eventName: string | symbol, ...args: any[]): boolean; + listenerCount<E extends keyof ClientHttp2StreamEventMap>( + eventName: E, + listener?: (...args: ClientHttp2StreamEventMap[E]) => void, + ): number; + listenerCount(eventName: string | symbol, listener?: (...args: any[]) => void): number; + listeners<E extends keyof ClientHttp2StreamEventMap>( + eventName: E, + ): ((...args: ClientHttp2StreamEventMap[E]) => void)[]; + listeners(eventName: string | symbol): ((...args: any[]) => void)[]; + off<E extends keyof ClientHttp2StreamEventMap>( + eventName: E, + listener: (...args: ClientHttp2StreamEventMap[E]) => void, + ): this; + off(eventName: string | symbol, listener: (...args: any[]) => void): this; + on<E extends keyof ClientHttp2StreamEventMap>( + eventName: E, + listener: (...args: ClientHttp2StreamEventMap[E]) => void, + ): this; + on(eventName: string | symbol, listener: (...args: any[]) => void): this; + once<E extends keyof ClientHttp2StreamEventMap>( + eventName: E, + listener: (...args: ClientHttp2StreamEventMap[E]) => void, + ): this; + once(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependListener<E extends keyof ClientHttp2StreamEventMap>( + eventName: E, + listener: (...args: ClientHttp2StreamEventMap[E]) => void, + ): this; + prependListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependOnceListener<E extends keyof ClientHttp2StreamEventMap>( + eventName: E, + listener: (...args: ClientHttp2StreamEventMap[E]) => void, + ): this; + prependOnceListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + rawListeners<E extends keyof ClientHttp2StreamEventMap>( + eventName: E, + ): ((...args: ClientHttp2StreamEventMap[E]) => void)[]; + rawListeners(eventName: string | symbol): ((...args: any[]) => void)[]; + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + removeAllListeners<E extends keyof ClientHttp2StreamEventMap>(eventName?: E): this; + removeAllListeners(eventName?: string | symbol): this; + removeListener<E extends keyof ClientHttp2StreamEventMap>( + eventName: E, + listener: (...args: ClientHttp2StreamEventMap[E]) => void, + ): this; + removeListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + // #endregion + } + interface ServerHttp2Stream extends Http2Stream { + /** + * True if headers were sent, false otherwise (read-only). + * @since v8.4.0 + */ + readonly headersSent: boolean; + /** + * Read-only property mapped to the `SETTINGS_ENABLE_PUSH` flag of the remote + * client's most recent `SETTINGS` frame. Will be `true` if the remote peer + * accepts push streams, `false` otherwise. Settings are the same for every `Http2Stream` in the same `Http2Session`. + * @since v8.4.0 + */ + readonly pushAllowed: boolean; + /** + * Sends an additional informational `HEADERS` frame to the connected HTTP/2 peer. + * @since v8.4.0 + */ + additionalHeaders(headers: OutgoingHttpHeaders): void; + /** + * Initiates a push stream. The callback is invoked with the new `Http2Stream` instance created for the push stream passed as the second argument, or an `Error` passed as the first argument. + * + * ```js + * import http2 from 'node:http2'; + * const server = http2.createServer(); + * server.on('stream', (stream) => { + * stream.respond({ ':status': 200 }); + * stream.pushStream({ ':path': '/' }, (err, pushStream, headers) => { + * if (err) throw err; + * pushStream.respond({ ':status': 200 }); + * pushStream.end('some pushed data'); + * }); + * stream.end('some data'); + * }); + * ``` + * + * Setting the weight of a push stream is not allowed in the `HEADERS` frame. Pass + * a `weight` value to `http2stream.priority` with the `silent` option set to `true` to enable server-side bandwidth balancing between concurrent streams. + * + * Calling `http2stream.pushStream()` from within a pushed stream is not permitted + * and will throw an error. + * @since v8.4.0 + * @param callback Callback that is called once the push stream has been initiated. + */ + pushStream( + headers: OutgoingHttpHeaders, + callback?: (err: Error | null, pushStream: ServerHttp2Stream, headers: OutgoingHttpHeaders) => void, + ): void; + pushStream( + headers: OutgoingHttpHeaders, + options?: Pick<ClientSessionRequestOptions, "exclusive" | "parent">, + callback?: (err: Error | null, pushStream: ServerHttp2Stream, headers: OutgoingHttpHeaders) => void, + ): void; + /** + * ```js + * import http2 from 'node:http2'; + * const server = http2.createServer(); + * server.on('stream', (stream) => { + * stream.respond({ ':status': 200 }); + * stream.end('some data'); + * }); + * ``` + * + * Initiates a response. When the `options.waitForTrailers` option is set, the `'wantTrailers'` event + * will be emitted immediately after queuing the last chunk of payload data to be sent. + * The `http2stream.sendTrailers()` method can then be used to send trailing header fields to the peer. + * + * When `options.waitForTrailers` is set, the `Http2Stream` will not automatically + * close when the final `DATA` frame is transmitted. User code must call either `http2stream.sendTrailers()` or `http2stream.close()` to close the `Http2Stream`. + * + * ```js + * import http2 from 'node:http2'; + * const server = http2.createServer(); + * server.on('stream', (stream) => { + * stream.respond({ ':status': 200 }, { waitForTrailers: true }); + * stream.on('wantTrailers', () => { + * stream.sendTrailers({ ABC: 'some value to send' }); + * }); + * stream.end('some data'); + * }); + * ``` + * @since v8.4.0 + */ + respond(headers?: OutgoingHttpHeaders | readonly string[], options?: ServerStreamResponseOptions): void; + /** + * Initiates a response whose data is read from the given file descriptor. No + * validation is performed on the given file descriptor. If an error occurs while + * attempting to read data using the file descriptor, the `Http2Stream` will be + * closed using an `RST_STREAM` frame using the standard `INTERNAL_ERROR` code. + * + * When used, the `Http2Stream` object's `Duplex` interface will be closed + * automatically. + * + * ```js + * import http2 from 'node:http2'; + * import fs from 'node:fs'; + * + * const server = http2.createServer(); + * server.on('stream', (stream) => { + * const fd = fs.openSync('/some/file', 'r'); + * + * const stat = fs.fstatSync(fd); + * const headers = { + * 'content-length': stat.size, + * 'last-modified': stat.mtime.toUTCString(), + * 'content-type': 'text/plain; charset=utf-8', + * }; + * stream.respondWithFD(fd, headers); + * stream.on('close', () => fs.closeSync(fd)); + * }); + * ``` + * + * The optional `options.statCheck` function may be specified to give user code + * an opportunity to set additional content headers based on the `fs.Stat` details + * of the given fd. If the `statCheck` function is provided, the `http2stream.respondWithFD()` method will + * perform an `fs.fstat()` call to collect details on the provided file descriptor. + * + * The `offset` and `length` options may be used to limit the response to a + * specific range subset. This can be used, for instance, to support HTTP Range + * requests. + * + * The file descriptor or `FileHandle` is not closed when the stream is closed, + * so it will need to be closed manually once it is no longer needed. + * Using the same file descriptor concurrently for multiple streams + * is not supported and may result in data loss. Re-using a file descriptor + * after a stream has finished is supported. + * + * When the `options.waitForTrailers` option is set, the `'wantTrailers'` event + * will be emitted immediately after queuing the last chunk of payload data to be + * sent. The `http2stream.sendTrailers()` method can then be used to sent trailing + * header fields to the peer. + * + * When `options.waitForTrailers` is set, the `Http2Stream` will not automatically + * close when the final `DATA` frame is transmitted. User code _must_ call either `http2stream.sendTrailers()` + * or `http2stream.close()` to close the `Http2Stream`. + * + * ```js + * import http2 from 'node:http2'; + * import fs from 'node:fs'; + * + * const server = http2.createServer(); + * server.on('stream', (stream) => { + * const fd = fs.openSync('/some/file', 'r'); + * + * const stat = fs.fstatSync(fd); + * const headers = { + * 'content-length': stat.size, + * 'last-modified': stat.mtime.toUTCString(), + * 'content-type': 'text/plain; charset=utf-8', + * }; + * stream.respondWithFD(fd, headers, { waitForTrailers: true }); + * stream.on('wantTrailers', () => { + * stream.sendTrailers({ ABC: 'some value to send' }); + * }); + * + * stream.on('close', () => fs.closeSync(fd)); + * }); + * ``` + * @since v8.4.0 + * @param fd A readable file descriptor. + */ + respondWithFD( + fd: number | fs.promises.FileHandle, + headers?: OutgoingHttpHeaders, + options?: ServerStreamFileResponseOptions, + ): void; + /** + * Sends a regular file as the response. The `path` must specify a regular file + * or an `'error'` event will be emitted on the `Http2Stream` object. + * + * When used, the `Http2Stream` object's `Duplex` interface will be closed + * automatically. + * + * The optional `options.statCheck` function may be specified to give user code + * an opportunity to set additional content headers based on the `fs.Stat` details + * of the given file: + * + * If an error occurs while attempting to read the file data, the `Http2Stream` will be closed using an + * `RST_STREAM` frame using the standard `INTERNAL_ERROR` code. + * If the `onError` callback is defined, then it will be called. Otherwise, the stream will be destroyed. + * + * Example using a file path: + * + * ```js + * import http2 from 'node:http2'; + * const server = http2.createServer(); + * server.on('stream', (stream) => { + * function statCheck(stat, headers) { + * headers['last-modified'] = stat.mtime.toUTCString(); + * } + * + * function onError(err) { + * // stream.respond() can throw if the stream has been destroyed by + * // the other side. + * try { + * if (err.code === 'ENOENT') { + * stream.respond({ ':status': 404 }); + * } else { + * stream.respond({ ':status': 500 }); + * } + * } catch (err) { + * // Perform actual error handling. + * console.error(err); + * } + * stream.end(); + * } + * + * stream.respondWithFile('/some/file', + * { 'content-type': 'text/plain; charset=utf-8' }, + * { statCheck, onError }); + * }); + * ``` + * + * The `options.statCheck` function may also be used to cancel the send operation + * by returning `false`. For instance, a conditional request may check the stat + * results to determine if the file has been modified to return an appropriate `304` response: + * + * ```js + * import http2 from 'node:http2'; + * const server = http2.createServer(); + * server.on('stream', (stream) => { + * function statCheck(stat, headers) { + * // Check the stat here... + * stream.respond({ ':status': 304 }); + * return false; // Cancel the send operation + * } + * stream.respondWithFile('/some/file', + * { 'content-type': 'text/plain; charset=utf-8' }, + * { statCheck }); + * }); + * ``` + * + * The `content-length` header field will be automatically set. + * + * The `offset` and `length` options may be used to limit the response to a + * specific range subset. This can be used, for instance, to support HTTP Range + * requests. + * + * The `options.onError` function may also be used to handle all the errors + * that could happen before the delivery of the file is initiated. The + * default behavior is to destroy the stream. + * + * When the `options.waitForTrailers` option is set, the `'wantTrailers'` event + * will be emitted immediately after queuing the last chunk of payload data to be + * sent. The `http2stream.sendTrailers()` method can then be used to sent trailing + * header fields to the peer. + * + * When `options.waitForTrailers` is set, the `Http2Stream` will not automatically + * close when the final `DATA` frame is transmitted. User code must call either`http2stream.sendTrailers()` or `http2stream.close()` to close the`Http2Stream`. + * + * ```js + * import http2 from 'node:http2'; + * const server = http2.createServer(); + * server.on('stream', (stream) => { + * stream.respondWithFile('/some/file', + * { 'content-type': 'text/plain; charset=utf-8' }, + * { waitForTrailers: true }); + * stream.on('wantTrailers', () => { + * stream.sendTrailers({ ABC: 'some value to send' }); + * }); + * }); + * ``` + * @since v8.4.0 + */ + respondWithFile( + path: string, + headers?: OutgoingHttpHeaders, + options?: ServerStreamFileResponseOptionsWithError, + ): void; + } + // Http2Session + interface Settings { + headerTableSize?: number | undefined; + enablePush?: boolean | undefined; + initialWindowSize?: number | undefined; + maxFrameSize?: number | undefined; + maxConcurrentStreams?: number | undefined; + maxHeaderListSize?: number | undefined; + enableConnectProtocol?: boolean | undefined; + } + interface ClientSessionRequestOptions { + endStream?: boolean | undefined; + exclusive?: boolean | undefined; + parent?: number | undefined; + waitForTrailers?: boolean | undefined; + signal?: AbortSignal | undefined; + } + interface SessionState { + effectiveLocalWindowSize?: number | undefined; + effectiveRecvDataLength?: number | undefined; + nextStreamID?: number | undefined; + localWindowSize?: number | undefined; + lastProcStreamID?: number | undefined; + remoteWindowSize?: number | undefined; + outboundQueueSize?: number | undefined; + deflateDynamicTableSize?: number | undefined; + inflateDynamicTableSize?: number | undefined; + } + interface Http2SessionEventMap { + "close": []; + "connect": [session: Http2Session, socket: net.Socket | tls.TLSSocket]; + "error": [err: Error]; + "frameError": [type: number, code: number, id: number]; + "goaway": [errorCode: number, lastStreamID: number, opaqueData?: NonSharedBuffer]; + "localSettings": [settings: Settings]; + "ping": [payload: Buffer]; + "remoteSettings": [settings: Settings]; + "stream": [ + stream: Http2Stream, + headers: IncomingHttpHeaders & IncomingHttpStatusHeader, + flags: number, + rawHeaders: string[], + ]; + "timeout": []; + } + interface Http2Session extends InternalEventEmitter<Http2SessionEventMap> { + /** + * Value will be `undefined` if the `Http2Session` is not yet connected to a + * socket, `h2c` if the `Http2Session` is not connected to a `TLSSocket`, or + * will return the value of the connected `TLSSocket`'s own `alpnProtocol` property. + * @since v9.4.0 + */ + readonly alpnProtocol?: string | undefined; + /** + * Will be `true` if this `Http2Session` instance has been closed, otherwise `false`. + * @since v9.4.0 + */ + readonly closed: boolean; + /** + * Will be `true` if this `Http2Session` instance is still connecting, will be set + * to `false` before emitting `connect` event and/or calling the `http2.connect` callback. + * @since v10.0.0 + */ + readonly connecting: boolean; + /** + * Will be `true` if this `Http2Session` instance has been destroyed and must no + * longer be used, otherwise `false`. + * @since v8.4.0 + */ + readonly destroyed: boolean; + /** + * Value is `undefined` if the `Http2Session` session socket has not yet been + * connected, `true` if the `Http2Session` is connected with a `TLSSocket`, + * and `false` if the `Http2Session` is connected to any other kind of socket + * or stream. + * @since v9.4.0 + */ + readonly encrypted?: boolean | undefined; + /** + * A prototype-less object describing the current local settings of this `Http2Session`. + * The local settings are local to _this_`Http2Session` instance. + * @since v8.4.0 + */ + readonly localSettings: Settings; + /** + * If the `Http2Session` is connected to a `TLSSocket`, the `originSet` property + * will return an `Array` of origins for which the `Http2Session` may be + * considered authoritative. + * + * The `originSet` property is only available when using a secure TLS connection. + * @since v9.4.0 + */ + readonly originSet?: string[] | undefined; + /** + * Indicates whether the `Http2Session` is currently waiting for acknowledgment of + * a sent `SETTINGS` frame. Will be `true` after calling the `http2session.settings()` method. + * Will be `false` once all sent `SETTINGS` frames have been acknowledged. + * @since v8.4.0 + */ + readonly pendingSettingsAck: boolean; + /** + * A prototype-less object describing the current remote settings of this`Http2Session`. + * The remote settings are set by the _connected_ HTTP/2 peer. + * @since v8.4.0 + */ + readonly remoteSettings: Settings; + /** + * Returns a `Proxy` object that acts as a `net.Socket` (or `tls.TLSSocket`) but + * limits available methods to ones safe to use with HTTP/2. + * + * `destroy`, `emit`, `end`, `pause`, `read`, `resume`, and `write` will throw + * an error with code `ERR_HTTP2_NO_SOCKET_MANIPULATION`. See `Http2Session and Sockets` for more information. + * + * `setTimeout` method will be called on this `Http2Session`. + * + * All other interactions will be routed directly to the socket. + * @since v8.4.0 + */ + readonly socket: net.Socket | tls.TLSSocket; + /** + * Provides miscellaneous information about the current state of the`Http2Session`. + * + * An object describing the current status of this `Http2Session`. + * @since v8.4.0 + */ + readonly state: SessionState; + /** + * The `http2session.type` will be equal to `http2.constants.NGHTTP2_SESSION_SERVER` if this `Http2Session` instance is a + * server, and `http2.constants.NGHTTP2_SESSION_CLIENT` if the instance is a + * client. + * @since v8.4.0 + */ + readonly type: number; + /** + * Gracefully closes the `Http2Session`, allowing any existing streams to + * complete on their own and preventing new `Http2Stream` instances from being + * created. Once closed, `http2session.destroy()`_might_ be called if there + * are no open `Http2Stream` instances. + * + * If specified, the `callback` function is registered as a handler for the`'close'` event. + * @since v9.4.0 + */ + close(callback?: () => void): void; + /** + * Immediately terminates the `Http2Session` and the associated `net.Socket` or `tls.TLSSocket`. + * + * Once destroyed, the `Http2Session` will emit the `'close'` event. If `error` is not undefined, an `'error'` event will be emitted immediately before the `'close'` event. + * + * If there are any remaining open `Http2Streams` associated with the `Http2Session`, those will also be destroyed. + * @since v8.4.0 + * @param error An `Error` object if the `Http2Session` is being destroyed due to an error. + * @param code The HTTP/2 error code to send in the final `GOAWAY` frame. If unspecified, and `error` is not undefined, the default is `INTERNAL_ERROR`, otherwise defaults to `NO_ERROR`. + */ + destroy(error?: Error, code?: number): void; + /** + * Transmits a `GOAWAY` frame to the connected peer _without_ shutting down the`Http2Session`. + * @since v9.4.0 + * @param code An HTTP/2 error code + * @param lastStreamID The numeric ID of the last processed `Http2Stream` + * @param opaqueData A `TypedArray` or `DataView` instance containing additional data to be carried within the `GOAWAY` frame. + */ + goaway(code?: number, lastStreamID?: number, opaqueData?: NodeJS.ArrayBufferView): void; + /** + * Sends a `PING` frame to the connected HTTP/2 peer. A `callback` function must + * be provided. The method will return `true` if the `PING` was sent, `false` otherwise. + * + * The maximum number of outstanding (unacknowledged) pings is determined by the `maxOutstandingPings` configuration option. The default maximum is 10. + * + * If provided, the `payload` must be a `Buffer`, `TypedArray`, or `DataView` containing 8 bytes of data that will be transmitted with the `PING` and + * returned with the ping acknowledgment. + * + * The callback will be invoked with three arguments: an error argument that will + * be `null` if the `PING` was successfully acknowledged, a `duration` argument + * that reports the number of milliseconds elapsed since the ping was sent and the + * acknowledgment was received, and a `Buffer` containing the 8-byte `PING` payload. + * + * ```js + * session.ping(Buffer.from('abcdefgh'), (err, duration, payload) => { + * if (!err) { + * console.log(`Ping acknowledged in ${duration} milliseconds`); + * console.log(`With payload '${payload.toString()}'`); + * } + * }); + * ``` + * + * If the `payload` argument is not specified, the default payload will be the + * 64-bit timestamp (little endian) marking the start of the `PING` duration. + * @since v8.9.3 + * @param payload Optional ping payload. + */ + ping(callback: (err: Error | null, duration: number, payload: NonSharedBuffer) => void): boolean; + ping( + payload: NodeJS.ArrayBufferView, + callback: (err: Error | null, duration: number, payload: NonSharedBuffer) => void, + ): boolean; + /** + * Calls `ref()` on this `Http2Session` instance's underlying `net.Socket`. + * @since v9.4.0 + */ + ref(): void; + /** + * Sets the local endpoint's window size. + * The `windowSize` is the total window size to set, not + * the delta. + * + * ```js + * import http2 from 'node:http2'; + * + * const server = http2.createServer(); + * const expectedWindowSize = 2 ** 20; + * server.on('connect', (session) => { + * + * // Set local window size to be 2 ** 20 + * session.setLocalWindowSize(expectedWindowSize); + * }); + * ``` + * @since v15.3.0, v14.18.0 + */ + setLocalWindowSize(windowSize: number): void; + /** + * Used to set a callback function that is called when there is no activity on + * the `Http2Session` after `msecs` milliseconds. The given `callback` is + * registered as a listener on the `'timeout'` event. + * @since v8.4.0 + */ + setTimeout(msecs: number, callback?: () => void): void; + /** + * Updates the current local settings for this `Http2Session` and sends a new `SETTINGS` frame to the connected HTTP/2 peer. + * + * Once called, the `http2session.pendingSettingsAck` property will be `true` while the session is waiting for the remote peer to acknowledge the new + * settings. + * + * The new settings will not become effective until the `SETTINGS` acknowledgment + * is received and the `'localSettings'` event is emitted. It is possible to send + * multiple `SETTINGS` frames while acknowledgment is still pending. + * @since v8.4.0 + * @param callback Callback that is called once the session is connected or right away if the session is already connected. + */ + settings( + settings: Settings, + callback?: (err: Error | null, settings: Settings, duration: number) => void, + ): void; + /** + * Calls `unref()` on this `Http2Session`instance's underlying `net.Socket`. + * @since v9.4.0 + */ + unref(): void; + } + interface ClientHttp2SessionEventMap extends Http2SessionEventMap { + "altsvc": [alt: string, origin: string, streamId: number]; + "connect": [session: ClientHttp2Session, socket: net.Socket | tls.TLSSocket]; + "origin": [origins: string[]]; + "stream": [ + stream: ClientHttp2Stream, + headers: IncomingHttpHeaders & IncomingHttpStatusHeader, + flags: number, + rawHeaders: string[], + ]; + } + interface ClientHttp2Session extends Http2Session { + /** + * For HTTP/2 Client `Http2Session` instances only, the `http2session.request()` creates and returns an `Http2Stream` instance that can be used to send an + * HTTP/2 request to the connected server. + * + * When a `ClientHttp2Session` is first created, the socket may not yet be + * connected. if `clienthttp2session.request()` is called during this time, the + * actual request will be deferred until the socket is ready to go. + * If the `session` is closed before the actual request be executed, an `ERR_HTTP2_GOAWAY_SESSION` is thrown. + * + * This method is only available if `http2session.type` is equal to `http2.constants.NGHTTP2_SESSION_CLIENT`. + * + * ```js + * import http2 from 'node:http2'; + * const clientSession = http2.connect('https://localhost:1234'); + * const { + * HTTP2_HEADER_PATH, + * HTTP2_HEADER_STATUS, + * } = http2.constants; + * + * const req = clientSession.request({ [HTTP2_HEADER_PATH]: '/' }); + * req.on('response', (headers) => { + * console.log(headers[HTTP2_HEADER_STATUS]); + * req.on('data', (chunk) => { // .. }); + * req.on('end', () => { // .. }); + * }); + * ``` + * + * When the `options.waitForTrailers` option is set, the `'wantTrailers'` event + * is emitted immediately after queuing the last chunk of payload data to be sent. + * The `http2stream.sendTrailers()` method can then be called to send trailing + * headers to the peer. + * + * When `options.waitForTrailers` is set, the `Http2Stream` will not automatically + * close when the final `DATA` frame is transmitted. User code must call either`http2stream.sendTrailers()` or `http2stream.close()` to close the`Http2Stream`. + * + * When `options.signal` is set with an `AbortSignal` and then `abort` on the + * corresponding `AbortController` is called, the request will emit an `'error'`event with an `AbortError` error. + * + * The `:method` and `:path` pseudo-headers are not specified within `headers`, + * they respectively default to: + * + * * `:method` \= `'GET'` + * * `:path` \= `/` + * @since v8.4.0 + */ + request( + headers?: OutgoingHttpHeaders | readonly string[], + options?: ClientSessionRequestOptions, + ): ClientHttp2Stream; + // #region InternalEventEmitter + addListener<E extends keyof ClientHttp2StreamEventMap>( + eventName: E, + listener: (...args: ClientHttp2StreamEventMap[E]) => void, + ): this; + addListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + emit<E extends keyof ClientHttp2StreamEventMap>(eventName: E, ...args: ClientHttp2StreamEventMap[E]): boolean; + emit(eventName: string | symbol, ...args: any[]): boolean; + listenerCount<E extends keyof ClientHttp2StreamEventMap>( + eventName: E, + listener?: (...args: ClientHttp2StreamEventMap[E]) => void, + ): number; + listenerCount(eventName: string | symbol, listener?: (...args: any[]) => void): number; + listeners<E extends keyof ClientHttp2StreamEventMap>( + eventName: E, + ): ((...args: ClientHttp2StreamEventMap[E]) => void)[]; + listeners(eventName: string | symbol): ((...args: any[]) => void)[]; + off<E extends keyof ClientHttp2StreamEventMap>( + eventName: E, + listener: (...args: ClientHttp2StreamEventMap[E]) => void, + ): this; + off(eventName: string | symbol, listener: (...args: any[]) => void): this; + on<E extends keyof ClientHttp2StreamEventMap>( + eventName: E, + listener: (...args: ClientHttp2StreamEventMap[E]) => void, + ): this; + on(eventName: string | symbol, listener: (...args: any[]) => void): this; + once<E extends keyof ClientHttp2StreamEventMap>( + eventName: E, + listener: (...args: ClientHttp2StreamEventMap[E]) => void, + ): this; + once(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependListener<E extends keyof ClientHttp2StreamEventMap>( + eventName: E, + listener: (...args: ClientHttp2StreamEventMap[E]) => void, + ): this; + prependListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependOnceListener<E extends keyof ClientHttp2StreamEventMap>( + eventName: E, + listener: (...args: ClientHttp2StreamEventMap[E]) => void, + ): this; + prependOnceListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + rawListeners<E extends keyof ClientHttp2StreamEventMap>( + eventName: E, + ): ((...args: ClientHttp2StreamEventMap[E]) => void)[]; + rawListeners(eventName: string | symbol): ((...args: any[]) => void)[]; + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + removeAllListeners<E extends keyof ClientHttp2StreamEventMap>(eventName?: E): this; + removeAllListeners(eventName?: string | symbol): this; + removeListener<E extends keyof ClientHttp2StreamEventMap>( + eventName: E, + listener: (...args: ClientHttp2StreamEventMap[E]) => void, + ): this; + removeListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + // #endregion + } + interface AlternativeServiceOptions { + origin: number | string | url.URL; + } + interface ServerHttp2SessionEventMap< + Http1Request extends typeof IncomingMessage = typeof IncomingMessage, + Http1Response extends typeof ServerResponse<InstanceType<Http1Request>> = typeof ServerResponse, + Http2Request extends typeof Http2ServerRequest = typeof Http2ServerRequest, + Http2Response extends typeof Http2ServerResponse<InstanceType<Http2Request>> = typeof Http2ServerResponse, + > extends Http2SessionEventMap { + "connect": [ + session: ServerHttp2Session<Http1Request, Http1Response, Http2Request, Http2Response>, + socket: net.Socket | tls.TLSSocket, + ]; + "stream": [stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number, rawHeaders: string[]]; + } + interface ServerHttp2Session< + Http1Request extends typeof IncomingMessage = typeof IncomingMessage, + Http1Response extends typeof ServerResponse<InstanceType<Http1Request>> = typeof ServerResponse, + Http2Request extends typeof Http2ServerRequest = typeof Http2ServerRequest, + Http2Response extends typeof Http2ServerResponse<InstanceType<Http2Request>> = typeof Http2ServerResponse, + > extends Http2Session { + readonly server: + | Http2Server<Http1Request, Http1Response, Http2Request, Http2Response> + | Http2SecureServer<Http1Request, Http1Response, Http2Request, Http2Response>; + /** + * Submits an `ALTSVC` frame (as defined by [RFC 7838](https://tools.ietf.org/html/rfc7838)) to the connected client. + * + * ```js + * import http2 from 'node:http2'; + * + * const server = http2.createServer(); + * server.on('session', (session) => { + * // Set altsvc for origin https://example.org:80 + * session.altsvc('h2=":8000"', 'https://example.org:80'); + * }); + * + * server.on('stream', (stream) => { + * // Set altsvc for a specific stream + * stream.session.altsvc('h2=":8000"', stream.id); + * }); + * ``` + * + * Sending an `ALTSVC` frame with a specific stream ID indicates that the alternate + * service is associated with the origin of the given `Http2Stream`. + * + * The `alt` and origin string _must_ contain only ASCII bytes and are + * strictly interpreted as a sequence of ASCII bytes. The special value `'clear'`may be passed to clear any previously set alternative service for a given + * domain. + * + * When a string is passed for the `originOrStream` argument, it will be parsed as + * a URL and the origin will be derived. For instance, the origin for the + * HTTP URL `'https://example.org/foo/bar'` is the ASCII string`'https://example.org'`. An error will be thrown if either the given string + * cannot be parsed as a URL or if a valid origin cannot be derived. + * + * A `URL` object, or any object with an `origin` property, may be passed as`originOrStream`, in which case the value of the `origin` property will be + * used. The value of the `origin` property _must_ be a properly serialized + * ASCII origin. + * @since v9.4.0 + * @param alt A description of the alternative service configuration as defined by `RFC 7838`. + * @param originOrStream Either a URL string specifying the origin (or an `Object` with an `origin` property) or the numeric identifier of an active `Http2Stream` as given by the + * `http2stream.id` property. + */ + altsvc(alt: string, originOrStream: number | string | url.URL | AlternativeServiceOptions): void; + /** + * Submits an `ORIGIN` frame (as defined by [RFC 8336](https://tools.ietf.org/html/rfc8336)) to the connected client + * to advertise the set of origins for which the server is capable of providing + * authoritative responses. + * + * ```js + * import http2 from 'node:http2'; + * const options = getSecureOptionsSomehow(); + * const server = http2.createSecureServer(options); + * server.on('stream', (stream) => { + * stream.respond(); + * stream.end('ok'); + * }); + * server.on('session', (session) => { + * session.origin('https://example.com', 'https://example.org'); + * }); + * ``` + * + * When a string is passed as an `origin`, it will be parsed as a URL and the + * origin will be derived. For instance, the origin for the HTTP URL `'https://example.org/foo/bar'` is the ASCII string` 'https://example.org'`. An error will be thrown if either the given + * string + * cannot be parsed as a URL or if a valid origin cannot be derived. + * + * A `URL` object, or any object with an `origin` property, may be passed as + * an `origin`, in which case the value of the `origin` property will be + * used. The value of the `origin` property _must_ be a properly serialized + * ASCII origin. + * + * Alternatively, the `origins` option may be used when creating a new HTTP/2 + * server using the `http2.createSecureServer()` method: + * + * ```js + * import http2 from 'node:http2'; + * const options = getSecureOptionsSomehow(); + * options.origins = ['https://example.com', 'https://example.org']; + * const server = http2.createSecureServer(options); + * server.on('stream', (stream) => { + * stream.respond(); + * stream.end('ok'); + * }); + * ``` + * @since v10.12.0 + * @param origins One or more URL Strings passed as separate arguments. + */ + origin( + ...origins: Array< + | string + | url.URL + | { + origin: string; + } + > + ): void; + // #region InternalEventEmitter + addListener<E extends keyof ServerHttp2SessionEventMap>( + eventName: E, + listener: ( + ...args: ServerHttp2SessionEventMap<Http1Request, Http1Response, Http2Request, Http2Response>[E] + ) => void, + ): this; + addListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + emit<E extends keyof ServerHttp2SessionEventMap>( + eventName: E, + ...args: ServerHttp2SessionEventMap<Http1Request, Http1Response, Http2Request, Http2Response>[E] + ): boolean; + emit(eventName: string | symbol, ...args: any[]): boolean; + listenerCount<E extends keyof ServerHttp2SessionEventMap>( + eventName: E, + listener?: ( + ...args: ServerHttp2SessionEventMap<Http1Request, Http1Response, Http2Request, Http2Response>[E] + ) => void, + ): number; + listenerCount(eventName: string | symbol, listener?: (...args: any[]) => void): number; + listeners<E extends keyof ServerHttp2SessionEventMap>( + eventName: E, + ): (( + ...args: ServerHttp2SessionEventMap<Http1Request, Http1Response, Http2Request, Http2Response>[E] + ) => void)[]; + listeners(eventName: string | symbol): ((...args: any[]) => void)[]; + off<E extends keyof ServerHttp2SessionEventMap>( + eventName: E, + listener: ( + ...args: ServerHttp2SessionEventMap<Http1Request, Http1Response, Http2Request, Http2Response>[E] + ) => void, + ): this; + off(eventName: string | symbol, listener: (...args: any[]) => void): this; + on<E extends keyof ServerHttp2SessionEventMap>( + eventName: E, + listener: ( + ...args: ServerHttp2SessionEventMap<Http1Request, Http1Response, Http2Request, Http2Response>[E] + ) => void, + ): this; + on(eventName: string | symbol, listener: (...args: any[]) => void): this; + once<E extends keyof ServerHttp2SessionEventMap>( + eventName: E, + listener: ( + ...args: ServerHttp2SessionEventMap<Http1Request, Http1Response, Http2Request, Http2Response>[E] + ) => void, + ): this; + once(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependListener<E extends keyof ServerHttp2SessionEventMap>( + eventName: E, + listener: ( + ...args: ServerHttp2SessionEventMap<Http1Request, Http1Response, Http2Request, Http2Response>[E] + ) => void, + ): this; + prependListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependOnceListener<E extends keyof ServerHttp2SessionEventMap>( + eventName: E, + listener: ( + ...args: ServerHttp2SessionEventMap<Http1Request, Http1Response, Http2Request, Http2Response>[E] + ) => void, + ): this; + prependOnceListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + rawListeners<E extends keyof ServerHttp2SessionEventMap>( + eventName: E, + ): (( + ...args: ServerHttp2SessionEventMap<Http1Request, Http1Response, Http2Request, Http2Response>[E] + ) => void)[]; + rawListeners(eventName: string | symbol): ((...args: any[]) => void)[]; + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + removeAllListeners<E extends keyof ServerHttp2SessionEventMap>(eventName?: E): this; + removeAllListeners(eventName?: string | symbol): this; + removeListener<E extends keyof ServerHttp2SessionEventMap>( + eventName: E, + listener: ( + ...args: ServerHttp2SessionEventMap<Http1Request, Http1Response, Http2Request, Http2Response>[E] + ) => void, + ): this; + removeListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + // #endregion + } + // Http2Server + interface SessionOptions { + /** + * Sets the maximum dynamic table size for deflating header fields. + * @default 4Kib + */ + maxDeflateDynamicTableSize?: number | undefined; + /** + * Sets the maximum number of settings entries per `SETTINGS` frame. + * The minimum value allowed is `1`. + * @default 32 + */ + maxSettings?: number | undefined; + /** + * Sets the maximum memory that the `Http2Session` is permitted to use. + * The value is expressed in terms of number of megabytes, e.g. `1` equal 1 megabyte. + * The minimum value allowed is `1`. + * This is a credit based limit, existing `Http2Stream`s may cause this limit to be exceeded, + * but new `Http2Stream` instances will be rejected while this limit is exceeded. + * The current number of `Http2Stream` sessions, the current memory use of the header compression tables, + * current data queued to be sent, and unacknowledged `PING` and `SETTINGS` frames are all counted towards the current limit. + * @default 10 + */ + maxSessionMemory?: number | undefined; + /** + * Sets the maximum number of header entries. + * This is similar to `server.maxHeadersCount` or `request.maxHeadersCount` in the `node:http` module. + * The minimum value is `1`. + * @default 128 + */ + maxHeaderListPairs?: number | undefined; + /** + * Sets the maximum number of outstanding, unacknowledged pings. + * @default 10 + */ + maxOutstandingPings?: number | undefined; + /** + * Sets the maximum allowed size for a serialized, compressed block of headers. + * Attempts to send headers that exceed this limit will result in + * a `'frameError'` event being emitted and the stream being closed and destroyed. + */ + maxSendHeaderBlockLength?: number | undefined; + /** + * Strategy used for determining the amount of padding to use for `HEADERS` and `DATA` frames. + * @default http2.constants.PADDING_STRATEGY_NONE + */ + paddingStrategy?: number | undefined; + /** + * Sets the maximum number of concurrent streams for the remote peer as if a `SETTINGS` frame had been received. + * Will be overridden if the remote peer sets its own value for `maxConcurrentStreams`. + * @default 100 + */ + peerMaxConcurrentStreams?: number | undefined; + /** + * The initial settings to send to the remote peer upon connection. + */ + settings?: Settings | undefined; + /** + * The array of integer values determines the settings types, + * which are included in the `CustomSettings`-property of the received remoteSettings. + * Please see the `CustomSettings`-property of the `Http2Settings` object for more information, on the allowed setting types. + */ + remoteCustomSettings?: number[] | undefined; + /** + * Specifies a timeout in milliseconds that + * a server should wait when an [`'unknownProtocol'`][] is emitted. If the + * socket has not been destroyed by that time the server will destroy it. + * @default 100000 + */ + unknownProtocolTimeout?: number | undefined; + /** + * If `true`, it turns on strict leading + * and trailing whitespace validation for HTTP/2 header field names and values + * as per [RFC-9113](https://www.rfc-editor.org/rfc/rfc9113.html#section-8.2.1). + * @since v24.2.0 + * @default true + */ + strictFieldWhitespaceValidation?: boolean | undefined; + } + interface ClientSessionOptions extends SessionOptions { + /** + * Sets the maximum number of reserved push streams the client will accept at any given time. + * Once the current number of currently reserved push streams exceeds reaches this limit, + * new push streams sent by the server will be automatically rejected. + * The minimum allowed value is 0. The maximum allowed value is 2<sup>32</sup>-1. + * A negative value sets this option to the maximum allowed value. + * @default 200 + */ + maxReservedRemoteStreams?: number | undefined; + /** + * An optional callback that receives the `URL` instance passed to `connect` and the `options` object, + * and returns any `Duplex` stream that is to be used as the connection for this session. + */ + createConnection?: ((authority: url.URL, option: SessionOptions) => stream.Duplex) | undefined; + /** + * The protocol to connect with, if not set in the `authority`. + * Value may be either `'http:'` or `'https:'`. + * @default 'https:' + */ + protocol?: "http:" | "https:" | undefined; + } + interface ServerSessionOptions< + Http1Request extends typeof IncomingMessage = typeof IncomingMessage, + Http1Response extends typeof ServerResponse<InstanceType<Http1Request>> = typeof ServerResponse, + Http2Request extends typeof Http2ServerRequest = typeof Http2ServerRequest, + Http2Response extends typeof Http2ServerResponse<InstanceType<Http2Request>> = typeof Http2ServerResponse, + > extends SessionOptions { + streamResetBurst?: number | undefined; + streamResetRate?: number | undefined; + Http1IncomingMessage?: Http1Request | undefined; + Http1ServerResponse?: Http1Response | undefined; + Http2ServerRequest?: Http2Request | undefined; + Http2ServerResponse?: Http2Response | undefined; + } + interface SecureClientSessionOptions extends ClientSessionOptions, tls.ConnectionOptions {} + interface SecureServerSessionOptions< + Http1Request extends typeof IncomingMessage = typeof IncomingMessage, + Http1Response extends typeof ServerResponse<InstanceType<Http1Request>> = typeof ServerResponse, + Http2Request extends typeof Http2ServerRequest = typeof Http2ServerRequest, + Http2Response extends typeof Http2ServerResponse<InstanceType<Http2Request>> = typeof Http2ServerResponse, + > extends ServerSessionOptions<Http1Request, Http1Response, Http2Request, Http2Response>, tls.TlsOptions {} + interface ServerOptions< + Http1Request extends typeof IncomingMessage = typeof IncomingMessage, + Http1Response extends typeof ServerResponse<InstanceType<Http1Request>> = typeof ServerResponse, + Http2Request extends typeof Http2ServerRequest = typeof Http2ServerRequest, + Http2Response extends typeof Http2ServerResponse<InstanceType<Http2Request>> = typeof Http2ServerResponse, + > extends ServerSessionOptions<Http1Request, Http1Response, Http2Request, Http2Response> {} + interface SecureServerOptions< + Http1Request extends typeof IncomingMessage = typeof IncomingMessage, + Http1Response extends typeof ServerResponse<InstanceType<Http1Request>> = typeof ServerResponse, + Http2Request extends typeof Http2ServerRequest = typeof Http2ServerRequest, + Http2Response extends typeof Http2ServerResponse<InstanceType<Http2Request>> = typeof Http2ServerResponse, + > extends SecureServerSessionOptions<Http1Request, Http1Response, Http2Request, Http2Response> { + allowHTTP1?: boolean | undefined; + origins?: string[] | undefined; + } + interface Http2ServerCommon { + setTimeout(msec?: number, callback?: () => void): this; + /** + * Throws ERR_HTTP2_INVALID_SETTING_VALUE for invalid settings values. + * Throws ERR_INVALID_ARG_TYPE for invalid settings argument. + */ + updateSettings(settings: Settings): void; + } + interface Http2ServerEventMap< + Http1Request extends typeof IncomingMessage = typeof IncomingMessage, + Http1Response extends typeof ServerResponse<InstanceType<Http1Request>> = typeof ServerResponse, + Http2Request extends typeof Http2ServerRequest = typeof Http2ServerRequest, + Http2Response extends typeof Http2ServerResponse<InstanceType<Http2Request>> = typeof Http2ServerResponse, + > extends net.ServerEventMap, Pick<Http2SessionEventMap, "stream" | "timeout"> { + "checkContinue": [request: InstanceType<Http2Request>, response: InstanceType<Http2Response>]; + "request": [request: InstanceType<Http2Request>, response: InstanceType<Http2Response>]; + "session": [session: ServerHttp2Session<Http1Request, Http1Response, Http2Request, Http2Response>]; + "sessionError": [err: Error]; + } + interface Http2Server< + Http1Request extends typeof IncomingMessage = typeof IncomingMessage, + Http1Response extends typeof ServerResponse<InstanceType<Http1Request>> = typeof ServerResponse, + Http2Request extends typeof Http2ServerRequest = typeof Http2ServerRequest, + Http2Response extends typeof Http2ServerResponse<InstanceType<Http2Request>> = typeof Http2ServerResponse, + > extends net.Server, Http2ServerCommon { + // #region InternalEventEmitter + addListener<E extends keyof Http2ServerEventMap>( + eventName: E, + listener: ( + ...args: Http2ServerEventMap<Http1Request, Http1Response, Http2Request, Http2Response>[E] + ) => void, + ): this; + addListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + emit<E extends keyof Http2ServerEventMap>( + eventName: E, + ...args: Http2ServerEventMap<Http1Request, Http1Response, Http2Request, Http2Response>[E] + ): boolean; + emit(eventName: string | symbol, ...args: any[]): boolean; + listenerCount<E extends keyof Http2ServerEventMap>( + eventName: E, + listener?: ( + ...args: Http2ServerEventMap<Http1Request, Http1Response, Http2Request, Http2Response>[E] + ) => void, + ): number; + listenerCount(eventName: string | symbol, listener?: (...args: any[]) => void): number; + listeners<E extends keyof Http2ServerEventMap>( + eventName: E, + ): ((...args: Http2ServerEventMap<Http1Request, Http1Response, Http2Request, Http2Response>[E]) => void)[]; + listeners(eventName: string | symbol): ((...args: any[]) => void)[]; + off<E extends keyof Http2ServerEventMap>( + eventName: E, + listener: ( + ...args: Http2ServerEventMap<Http1Request, Http1Response, Http2Request, Http2Response>[E] + ) => void, + ): this; + off(eventName: string | symbol, listener: (...args: any[]) => void): this; + on<E extends keyof Http2ServerEventMap>( + eventName: E, + listener: ( + ...args: Http2ServerEventMap<Http1Request, Http1Response, Http2Request, Http2Response>[E] + ) => void, + ): this; + on(eventName: string | symbol, listener: (...args: any[]) => void): this; + once<E extends keyof Http2ServerEventMap>( + eventName: E, + listener: ( + ...args: Http2ServerEventMap<Http1Request, Http1Response, Http2Request, Http2Response>[E] + ) => void, + ): this; + once(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependListener<E extends keyof Http2ServerEventMap>( + eventName: E, + listener: ( + ...args: Http2ServerEventMap<Http1Request, Http1Response, Http2Request, Http2Response>[E] + ) => void, + ): this; + prependListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependOnceListener<E extends keyof Http2ServerEventMap>( + eventName: E, + listener: ( + ...args: Http2ServerEventMap<Http1Request, Http1Response, Http2Request, Http2Response>[E] + ) => void, + ): this; + prependOnceListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + rawListeners<E extends keyof Http2ServerEventMap>( + eventName: E, + ): ((...args: Http2ServerEventMap<Http1Request, Http1Response, Http2Request, Http2Response>[E]) => void)[]; + rawListeners(eventName: string | symbol): ((...args: any[]) => void)[]; + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + removeAllListeners<E extends keyof Http2ServerEventMap>(eventName?: E): this; + removeAllListeners(eventName?: string | symbol): this; + removeListener<E extends keyof Http2ServerEventMap>( + eventName: E, + listener: ( + ...args: Http2ServerEventMap<Http1Request, Http1Response, Http2Request, Http2Response>[E] + ) => void, + ): this; + removeListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + // #endregion + } + interface Http2SecureServerEventMap< + Http1Request extends typeof IncomingMessage = typeof IncomingMessage, + Http1Response extends typeof ServerResponse<InstanceType<Http1Request>> = typeof ServerResponse, + Http2Request extends typeof Http2ServerRequest = typeof Http2ServerRequest, + Http2Response extends typeof Http2ServerResponse<InstanceType<Http2Request>> = typeof Http2ServerResponse, + > extends tls.ServerEventMap, Http2ServerEventMap<Http1Request, Http1Response, Http2Request, Http2Response> { + "unknownProtocol": [socket: tls.TLSSocket]; + } + interface Http2SecureServer< + Http1Request extends typeof IncomingMessage = typeof IncomingMessage, + Http1Response extends typeof ServerResponse<InstanceType<Http1Request>> = typeof ServerResponse, + Http2Request extends typeof Http2ServerRequest = typeof Http2ServerRequest, + Http2Response extends typeof Http2ServerResponse<InstanceType<Http2Request>> = typeof Http2ServerResponse, + > extends tls.Server, Http2ServerCommon { + // #region InternalEventEmitter + addListener<E extends keyof Http2SecureServerEventMap>( + eventName: E, + listener: ( + ...args: Http2SecureServerEventMap<Http1Request, Http1Response, Http2Request, Http2Response>[E] + ) => void, + ): this; + addListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + emit<E extends keyof Http2SecureServerEventMap>( + eventName: E, + ...args: Http2SecureServerEventMap<Http1Request, Http1Response, Http2Request, Http2Response>[E] + ): boolean; + emit(eventName: string | symbol, ...args: any[]): boolean; + listenerCount<E extends keyof Http2SecureServerEventMap>( + eventName: E, + listener?: ( + ...args: Http2SecureServerEventMap<Http1Request, Http1Response, Http2Request, Http2Response>[E] + ) => void, + ): number; + listenerCount(eventName: string | symbol, listener?: (...args: any[]) => void): number; + listeners<E extends keyof Http2SecureServerEventMap>( + eventName: E, + ): (( + ...args: Http2SecureServerEventMap<Http1Request, Http1Response, Http2Request, Http2Response>[E] + ) => void)[]; + listeners(eventName: string | symbol): ((...args: any[]) => void)[]; + off<E extends keyof Http2SecureServerEventMap>( + eventName: E, + listener: ( + ...args: Http2SecureServerEventMap<Http1Request, Http1Response, Http2Request, Http2Response>[E] + ) => void, + ): this; + off(eventName: string | symbol, listener: (...args: any[]) => void): this; + on<E extends keyof Http2SecureServerEventMap>( + eventName: E, + listener: ( + ...args: Http2SecureServerEventMap<Http1Request, Http1Response, Http2Request, Http2Response>[E] + ) => void, + ): this; + on(eventName: string | symbol, listener: (...args: any[]) => void): this; + once<E extends keyof Http2SecureServerEventMap>( + eventName: E, + listener: ( + ...args: Http2SecureServerEventMap<Http1Request, Http1Response, Http2Request, Http2Response>[E] + ) => void, + ): this; + once(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependListener<E extends keyof Http2SecureServerEventMap>( + eventName: E, + listener: ( + ...args: Http2SecureServerEventMap<Http1Request, Http1Response, Http2Request, Http2Response>[E] + ) => void, + ): this; + prependListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependOnceListener<E extends keyof Http2SecureServerEventMap>( + eventName: E, + listener: ( + ...args: Http2SecureServerEventMap<Http1Request, Http1Response, Http2Request, Http2Response>[E] + ) => void, + ): this; + prependOnceListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + rawListeners<E extends keyof Http2SecureServerEventMap>( + eventName: E, + ): (( + ...args: Http2SecureServerEventMap<Http1Request, Http1Response, Http2Request, Http2Response>[E] + ) => void)[]; + rawListeners(eventName: string | symbol): ((...args: any[]) => void)[]; + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + removeAllListeners<E extends keyof Http2SecureServerEventMap>(eventName?: E): this; + removeAllListeners(eventName?: string | symbol): this; + removeListener<E extends keyof Http2SecureServerEventMap>( + eventName: E, + listener: ( + ...args: Http2SecureServerEventMap<Http1Request, Http1Response, Http2Request, Http2Response>[E] + ) => void, + ): this; + removeListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + // #endregion + } + interface Http2ServerRequestEventMap extends stream.ReadableEventMap { + "aborted": [hadError: boolean, code: number]; + "data": [chunk: string | NonSharedBuffer]; + } + /** + * A `Http2ServerRequest` object is created by {@link Server} or {@link SecureServer} and passed as the first argument to the `'request'` event. It may be used to access a request status, + * headers, and + * data. + * @since v8.4.0 + */ + class Http2ServerRequest extends stream.Readable { + constructor( + stream: ServerHttp2Stream, + headers: IncomingHttpHeaders, + options: stream.ReadableOptions, + rawHeaders: readonly string[], + ); + /** + * The `request.aborted` property will be `true` if the request has + * been aborted. + * @since v10.1.0 + */ + readonly aborted: boolean; + /** + * The request authority pseudo header field. Because HTTP/2 allows requests + * to set either `:authority` or `host`, this value is derived from `req.headers[':authority']` if present. Otherwise, it is derived from `req.headers['host']`. + * @since v8.4.0 + */ + readonly authority: string; + /** + * See `request.socket`. + * @since v8.4.0 + * @deprecated Since v13.0.0 - Use `socket`. + */ + readonly connection: net.Socket | tls.TLSSocket; + /** + * The `request.complete` property will be `true` if the request has + * been completed, aborted, or destroyed. + * @since v12.10.0 + */ + readonly complete: boolean; + /** + * The request/response headers object. + * + * Key-value pairs of header names and values. Header names are lower-cased. + * + * ```js + * // Prints something like: + * // + * // { 'user-agent': 'curl/7.22.0', + * // host: '127.0.0.1:8000', + * // accept: '*' } + * console.log(request.headers); + * ``` + * + * See `HTTP/2 Headers Object`. + * + * In HTTP/2, the request path, host name, protocol, and method are represented as + * special headers prefixed with the `:` character (e.g. `':path'`). These special + * headers will be included in the `request.headers` object. Care must be taken not + * to inadvertently modify these special headers or errors may occur. For instance, + * removing all headers from the request will cause errors to occur: + * + * ```js + * removeAllHeaders(request.headers); + * assert(request.url); // Fails because the :path header has been removed + * ``` + * @since v8.4.0 + */ + readonly headers: IncomingHttpHeaders; + /** + * In case of server request, the HTTP version sent by the client. In the case of + * client response, the HTTP version of the connected-to server. Returns `'2.0'`. + * + * Also `message.httpVersionMajor` is the first integer and `message.httpVersionMinor` is the second. + * @since v8.4.0 + */ + readonly httpVersion: string; + readonly httpVersionMinor: number; + readonly httpVersionMajor: number; + /** + * The request method as a string. Read-only. Examples: `'GET'`, `'DELETE'`. + * @since v8.4.0 + */ + readonly method: string; + /** + * The raw request/response headers list exactly as they were received. + * + * The keys and values are in the same list. It is _not_ a + * list of tuples. So, the even-numbered offsets are key values, and the + * odd-numbered offsets are the associated values. + * + * Header names are not lowercased, and duplicates are not merged. + * + * ```js + * // Prints something like: + * // + * // [ 'user-agent', + * // 'this is invalid because there can be only one', + * // 'User-Agent', + * // 'curl/7.22.0', + * // 'Host', + * // '127.0.0.1:8000', + * // 'ACCEPT', + * // '*' ] + * console.log(request.rawHeaders); + * ``` + * @since v8.4.0 + */ + readonly rawHeaders: string[]; + /** + * The raw request/response trailer keys and values exactly as they were + * received. Only populated at the `'end'` event. + * @since v8.4.0 + */ + readonly rawTrailers: string[]; + /** + * The request scheme pseudo header field indicating the scheme + * portion of the target URL. + * @since v8.4.0 + */ + readonly scheme: string; + /** + * Returns a `Proxy` object that acts as a `net.Socket` (or `tls.TLSSocket`) but + * applies getters, setters, and methods based on HTTP/2 logic. + * + * `destroyed`, `readable`, and `writable` properties will be retrieved from and + * set on `request.stream`. + * + * `destroy`, `emit`, `end`, `on` and `once` methods will be called on `request.stream`. + * + * `setTimeout` method will be called on `request.stream.session`. + * + * `pause`, `read`, `resume`, and `write` will throw an error with code `ERR_HTTP2_NO_SOCKET_MANIPULATION`. See `Http2Session and Sockets` for + * more information. + * + * All other interactions will be routed directly to the socket. With TLS support, + * use `request.socket.getPeerCertificate()` to obtain the client's + * authentication details. + * @since v8.4.0 + */ + readonly socket: net.Socket | tls.TLSSocket; + /** + * The `Http2Stream` object backing the request. + * @since v8.4.0 + */ + readonly stream: ServerHttp2Stream; + /** + * The request/response trailers object. Only populated at the `'end'` event. + * @since v8.4.0 + */ + readonly trailers: IncomingHttpHeaders; + /** + * Request URL string. This contains only the URL that is present in the actual + * HTTP request. If the request is: + * + * ```http + * GET /status?name=ryan HTTP/1.1 + * Accept: text/plain + * ``` + * + * Then `request.url` will be: + * + * ```js + * '/status?name=ryan' + * ``` + * + * To parse the url into its parts, `new URL()` can be used: + * + * ```console + * $ node + * > new URL('/status?name=ryan', 'http://example.com') + * URL { + * href: 'http://example.com/status?name=ryan', + * origin: 'http://example.com', + * protocol: 'http:', + * username: '', + * password: '', + * host: 'example.com', + * hostname: 'example.com', + * port: '', + * pathname: '/status', + * search: '?name=ryan', + * searchParams: URLSearchParams { 'name' => 'ryan' }, + * hash: '' + * } + * ``` + * @since v8.4.0 + */ + url: string; + /** + * Sets the `Http2Stream`'s timeout value to `msecs`. If a callback is + * provided, then it is added as a listener on the `'timeout'` event on + * the response object. + * + * If no `'timeout'` listener is added to the request, the response, or + * the server, then `Http2Stream`s are destroyed when they time out. If a + * handler is assigned to the request, the response, or the server's `'timeout'`events, timed out sockets must be handled explicitly. + * @since v8.4.0 + */ + setTimeout(msecs: number, callback?: () => void): void; + read(size?: number): Buffer | string | null; + // #region InternalEventEmitter + addListener<E extends keyof Http2ServerRequestEventMap>( + eventName: E, + listener: (...args: Http2ServerRequestEventMap[E]) => void, + ): this; + addListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + emit<E extends keyof Http2ServerRequestEventMap>(eventName: E, ...args: Http2ServerRequestEventMap[E]): boolean; + emit(eventName: string | symbol, ...args: any[]): boolean; + listenerCount<E extends keyof Http2ServerRequestEventMap>( + eventName: E, + listener?: (...args: Http2ServerRequestEventMap[E]) => void, + ): number; + listenerCount(eventName: string | symbol, listener?: (...args: any[]) => void): number; + listeners<E extends keyof Http2ServerRequestEventMap>( + eventName: E, + ): ((...args: Http2ServerRequestEventMap[E]) => void)[]; + listeners(eventName: string | symbol): ((...args: any[]) => void)[]; + off<E extends keyof Http2ServerRequestEventMap>( + eventName: E, + listener: (...args: Http2ServerRequestEventMap[E]) => void, + ): this; + off(eventName: string | symbol, listener: (...args: any[]) => void): this; + on<E extends keyof Http2ServerRequestEventMap>( + eventName: E, + listener: (...args: Http2ServerRequestEventMap[E]) => void, + ): this; + on(eventName: string | symbol, listener: (...args: any[]) => void): this; + once<E extends keyof Http2ServerRequestEventMap>( + eventName: E, + listener: (...args: Http2ServerRequestEventMap[E]) => void, + ): this; + once(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependListener<E extends keyof Http2ServerRequestEventMap>( + eventName: E, + listener: (...args: Http2ServerRequestEventMap[E]) => void, + ): this; + prependListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependOnceListener<E extends keyof Http2ServerRequestEventMap>( + eventName: E, + listener: (...args: Http2ServerRequestEventMap[E]) => void, + ): this; + prependOnceListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + rawListeners<E extends keyof Http2ServerRequestEventMap>( + eventName: E, + ): ((...args: Http2ServerRequestEventMap[E]) => void)[]; + rawListeners(eventName: string | symbol): ((...args: any[]) => void)[]; + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + removeAllListeners<E extends keyof Http2ServerRequestEventMap>(eventName?: E): this; + removeAllListeners(eventName?: string | symbol): this; + removeListener<E extends keyof Http2ServerRequestEventMap>( + eventName: E, + listener: (...args: Http2ServerRequestEventMap[E]) => void, + ): this; + removeListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + // #endregion + } + /** + * This object is created internally by an HTTP server, not by the user. It is + * passed as the second parameter to the `'request'` event. + * @since v8.4.0 + */ + class Http2ServerResponse<Request extends Http2ServerRequest = Http2ServerRequest> extends stream.Writable { + constructor(stream: ServerHttp2Stream); + /** + * See `response.socket`. + * @since v8.4.0 + * @deprecated Since v13.0.0 - Use `socket`. + */ + readonly connection: net.Socket | tls.TLSSocket; + /** + * Append a single header value to the header object. + * + * If the value is an array, this is equivalent to calling this method multiple times. + * + * If there were no previous values for the header, this is equivalent to calling {@link setHeader}. + * + * Attempting to set a header field name or value that contains invalid characters will result in a + * [TypeError](https://nodejs.org/docs/latest-v25.x/api/errors.html#class-typeerror) being thrown. + * + * ```js + * // Returns headers including "set-cookie: a" and "set-cookie: b" + * const server = http2.createServer((req, res) => { + * res.setHeader('set-cookie', 'a'); + * res.appendHeader('set-cookie', 'b'); + * res.writeHead(200); + * res.end('ok'); + * }); + * ``` + * @since v20.12.0 + */ + appendHeader(name: string, value: string | string[]): void; + /** + * Boolean value that indicates whether the response has completed. Starts + * as `false`. After `response.end()` executes, the value will be `true`. + * @since v8.4.0 + * @deprecated Since v13.4.0,v12.16.0 - Use `writableEnded`. + */ + readonly finished: boolean; + /** + * True if headers were sent, false otherwise (read-only). + * @since v8.4.0 + */ + readonly headersSent: boolean; + /** + * A reference to the original HTTP2 `request` object. + * @since v15.7.0 + */ + readonly req: Request; + /** + * Returns a `Proxy` object that acts as a `net.Socket` (or `tls.TLSSocket`) but + * applies getters, setters, and methods based on HTTP/2 logic. + * + * `destroyed`, `readable`, and `writable` properties will be retrieved from and + * set on `response.stream`. + * + * `destroy`, `emit`, `end`, `on` and `once` methods will be called on `response.stream`. + * + * `setTimeout` method will be called on `response.stream.session`. + * + * `pause`, `read`, `resume`, and `write` will throw an error with code `ERR_HTTP2_NO_SOCKET_MANIPULATION`. See `Http2Session and Sockets` for + * more information. + * + * All other interactions will be routed directly to the socket. + * + * ```js + * import http2 from 'node:http2'; + * const server = http2.createServer((req, res) => { + * const ip = req.socket.remoteAddress; + * const port = req.socket.remotePort; + * res.end(`Your IP address is ${ip} and your source port is ${port}.`); + * }).listen(3000); + * ``` + * @since v8.4.0 + */ + readonly socket: net.Socket | tls.TLSSocket; + /** + * The `Http2Stream` object backing the response. + * @since v8.4.0 + */ + readonly stream: ServerHttp2Stream; + /** + * When true, the Date header will be automatically generated and sent in + * the response if it is not already present in the headers. Defaults to true. + * + * This should only be disabled for testing; HTTP requires the Date header + * in responses. + * @since v8.4.0 + */ + sendDate: boolean; + /** + * When using implicit headers (not calling `response.writeHead()` explicitly), + * this property controls the status code that will be sent to the client when + * the headers get flushed. + * + * ```js + * response.statusCode = 404; + * ``` + * + * After response header was sent to the client, this property indicates the + * status code which was sent out. + * @since v8.4.0 + */ + statusCode: number; + /** + * Status message is not supported by HTTP/2 (RFC 7540 8.1.2.4). It returns + * an empty string. + * @since v8.4.0 + */ + statusMessage: ""; + /** + * This method adds HTTP trailing headers (a header but at the end of the + * message) to the response. + * + * Attempting to set a header field name or value that contains invalid characters + * will result in a `TypeError` being thrown. + * @since v8.4.0 + */ + addTrailers(trailers: OutgoingHttpHeaders): void; + /** + * This method signals to the server that all of the response headers and body + * have been sent; that server should consider this message complete. + * The method, `response.end()`, MUST be called on each response. + * + * If `data` is specified, it is equivalent to calling `response.write(data, encoding)` followed by `response.end(callback)`. + * + * If `callback` is specified, it will be called when the response stream + * is finished. + * @since v8.4.0 + */ + end(callback?: () => void): this; + end(data: string | Uint8Array, callback?: () => void): this; + end(data: string | Uint8Array, encoding: BufferEncoding, callback?: () => void): this; + /** + * Reads out a header that has already been queued but not sent to the client. + * The name is case-insensitive. + * + * ```js + * const contentType = response.getHeader('content-type'); + * ``` + * @since v8.4.0 + */ + getHeader(name: string): string; + /** + * Returns an array containing the unique names of the current outgoing headers. + * All header names are lowercase. + * + * ```js + * response.setHeader('Foo', 'bar'); + * response.setHeader('Set-Cookie', ['foo=bar', 'bar=baz']); + * + * const headerNames = response.getHeaderNames(); + * // headerNames === ['foo', 'set-cookie'] + * ``` + * @since v8.4.0 + */ + getHeaderNames(): string[]; + /** + * Returns a shallow copy of the current outgoing headers. Since a shallow copy + * is used, array values may be mutated without additional calls to various + * header-related http module methods. The keys of the returned object are the + * header names and the values are the respective header values. All header names + * are lowercase. + * + * The object returned by the `response.getHeaders()` method _does not_ prototypically inherit from the JavaScript `Object`. This means that typical `Object` methods such as `obj.toString()`, + * `obj.hasOwnProperty()`, and others + * are not defined and _will not work_. + * + * ```js + * response.setHeader('Foo', 'bar'); + * response.setHeader('Set-Cookie', ['foo=bar', 'bar=baz']); + * + * const headers = response.getHeaders(); + * // headers === { foo: 'bar', 'set-cookie': ['foo=bar', 'bar=baz'] } + * ``` + * @since v8.4.0 + */ + getHeaders(): OutgoingHttpHeaders; + /** + * Returns `true` if the header identified by `name` is currently set in the + * outgoing headers. The header name matching is case-insensitive. + * + * ```js + * const hasContentType = response.hasHeader('content-type'); + * ``` + * @since v8.4.0 + */ + hasHeader(name: string): boolean; + /** + * Removes a header that has been queued for implicit sending. + * + * ```js + * response.removeHeader('Content-Encoding'); + * ``` + * @since v8.4.0 + */ + removeHeader(name: string): void; + /** + * Sets a single header value for implicit headers. If this header already exists + * in the to-be-sent headers, its value will be replaced. Use an array of strings + * here to send multiple headers with the same name. + * + * ```js + * response.setHeader('Content-Type', 'text/html; charset=utf-8'); + * ``` + * + * or + * + * ```js + * response.setHeader('Set-Cookie', ['type=ninja', 'language=javascript']); + * ``` + * + * Attempting to set a header field name or value that contains invalid characters + * will result in a `TypeError` being thrown. + * + * When headers have been set with `response.setHeader()`, they will be merged + * with any headers passed to `response.writeHead()`, with the headers passed + * to `response.writeHead()` given precedence. + * + * ```js + * // Returns content-type = text/plain + * const server = http2.createServer((req, res) => { + * res.setHeader('Content-Type', 'text/html; charset=utf-8'); + * res.setHeader('X-Foo', 'bar'); + * res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' }); + * res.end('ok'); + * }); + * ``` + * @since v8.4.0 + */ + setHeader(name: string, value: number | string | readonly string[]): void; + /** + * Sets the `Http2Stream`'s timeout value to `msecs`. If a callback is + * provided, then it is added as a listener on the `'timeout'` event on + * the response object. + * + * If no `'timeout'` listener is added to the request, the response, or + * the server, then `Http2Stream` s are destroyed when they time out. If a + * handler is assigned to the request, the response, or the server's `'timeout'` events, timed out sockets must be handled explicitly. + * @since v8.4.0 + */ + setTimeout(msecs: number, callback?: () => void): void; + /** + * If this method is called and `response.writeHead()` has not been called, + * it will switch to implicit header mode and flush the implicit headers. + * + * This sends a chunk of the response body. This method may + * be called multiple times to provide successive parts of the body. + * + * In the `node:http` module, the response body is omitted when the + * request is a HEAD request. Similarly, the `204` and `304` responses _must not_ include a message body. + * + * `chunk` can be a string or a buffer. If `chunk` is a string, + * the second parameter specifies how to encode it into a byte stream. + * By default the `encoding` is `'utf8'`. `callback` will be called when this chunk + * of data is flushed. + * + * This is the raw HTTP body and has nothing to do with higher-level multi-part + * body encodings that may be used. + * + * The first time `response.write()` is called, it will send the buffered + * header information and the first chunk of the body to the client. The second + * time `response.write()` is called, Node.js assumes data will be streamed, + * and sends the new data separately. That is, the response is buffered up to the + * first chunk of the body. + * + * Returns `true` if the entire data was flushed successfully to the kernel + * buffer. Returns `false` if all or part of the data was queued in user memory.`'drain'` will be emitted when the buffer is free again. + * @since v8.4.0 + */ + write(chunk: string | Uint8Array, callback?: (err: Error) => void): boolean; + write(chunk: string | Uint8Array, encoding: BufferEncoding, callback?: (err: Error) => void): boolean; + /** + * Sends a status `100 Continue` to the client, indicating that the request body + * should be sent. See the `'checkContinue'` event on `Http2Server` and `Http2SecureServer`. + * @since v8.4.0 + */ + writeContinue(): void; + /** + * Sends a status `103 Early Hints` to the client with a Link header, + * indicating that the user agent can preload/preconnect the linked resources. + * The `hints` is an object containing the values of headers to be sent with + * early hints message. + * + * **Example** + * + * ```js + * const earlyHintsLink = '</styles.css>; rel=preload; as=style'; + * response.writeEarlyHints({ + * 'link': earlyHintsLink, + * }); + * + * const earlyHintsLinks = [ + * '</styles.css>; rel=preload; as=style', + * '</scripts.js>; rel=preload; as=script', + * ]; + * response.writeEarlyHints({ + * 'link': earlyHintsLinks, + * }); + * ``` + * @since v18.11.0 + */ + writeEarlyHints(hints: Record<string, string | string[]>): void; + /** + * Sends a response header to the request. The status code is a 3-digit HTTP + * status code, like `404`. The last argument, `headers`, are the response headers. + * + * Returns a reference to the `Http2ServerResponse`, so that calls can be chained. + * + * For compatibility with `HTTP/1`, a human-readable `statusMessage` may be + * passed as the second argument. However, because the `statusMessage` has no + * meaning within HTTP/2, the argument will have no effect and a process warning + * will be emitted. + * + * ```js + * const body = 'hello world'; + * response.writeHead(200, { + * 'Content-Length': Buffer.byteLength(body), + * 'Content-Type': 'text/plain; charset=utf-8', + * }); + * ``` + * + * `Content-Length` is given in bytes not characters. The`Buffer.byteLength()` API may be used to determine the number of bytes in a + * given encoding. On outbound messages, Node.js does not check if Content-Length + * and the length of the body being transmitted are equal or not. However, when + * receiving messages, Node.js will automatically reject messages when the `Content-Length` does not match the actual payload size. + * + * This method may be called at most one time on a message before `response.end()` is called. + * + * If `response.write()` or `response.end()` are called before calling + * this, the implicit/mutable headers will be calculated and call this function. + * + * When headers have been set with `response.setHeader()`, they will be merged + * with any headers passed to `response.writeHead()`, with the headers passed + * to `response.writeHead()` given precedence. + * + * ```js + * // Returns content-type = text/plain + * const server = http2.createServer((req, res) => { + * res.setHeader('Content-Type', 'text/html; charset=utf-8'); + * res.setHeader('X-Foo', 'bar'); + * res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' }); + * res.end('ok'); + * }); + * ``` + * + * Attempting to set a header field name or value that contains invalid characters + * will result in a `TypeError` being thrown. + * @since v8.4.0 + */ + writeHead(statusCode: number, headers?: OutgoingHttpHeaders | readonly string[]): this; + writeHead(statusCode: number, statusMessage: string, headers?: OutgoingHttpHeaders | readonly string[]): this; + /** + * Call `http2stream.pushStream()` with the given headers, and wrap the + * given `Http2Stream` on a newly created `Http2ServerResponse` as the callback + * parameter if successful. When `Http2ServerRequest` is closed, the callback is + * called with an error `ERR_HTTP2_INVALID_STREAM`. + * @since v8.4.0 + * @param headers An object describing the headers + * @param callback Called once `http2stream.pushStream()` is finished, or either when the attempt to create the pushed `Http2Stream` has failed or has been rejected, or the state of + * `Http2ServerRequest` is closed prior to calling the `http2stream.pushStream()` method + */ + createPushResponse( + headers: OutgoingHttpHeaders, + callback: (err: Error | null, res: Http2ServerResponse) => void, + ): void; + } + namespace constants { + const NGHTTP2_SESSION_SERVER: number; + const NGHTTP2_SESSION_CLIENT: number; + const NGHTTP2_STREAM_STATE_IDLE: number; + const NGHTTP2_STREAM_STATE_OPEN: number; + const NGHTTP2_STREAM_STATE_RESERVED_LOCAL: number; + const NGHTTP2_STREAM_STATE_RESERVED_REMOTE: number; + const NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL: number; + const NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE: number; + const NGHTTP2_STREAM_STATE_CLOSED: number; + const NGHTTP2_NO_ERROR: number; + const NGHTTP2_PROTOCOL_ERROR: number; + const NGHTTP2_INTERNAL_ERROR: number; + const NGHTTP2_FLOW_CONTROL_ERROR: number; + const NGHTTP2_SETTINGS_TIMEOUT: number; + const NGHTTP2_STREAM_CLOSED: number; + const NGHTTP2_FRAME_SIZE_ERROR: number; + const NGHTTP2_REFUSED_STREAM: number; + const NGHTTP2_CANCEL: number; + const NGHTTP2_COMPRESSION_ERROR: number; + const NGHTTP2_CONNECT_ERROR: number; + const NGHTTP2_ENHANCE_YOUR_CALM: number; + const NGHTTP2_INADEQUATE_SECURITY: number; + const NGHTTP2_HTTP_1_1_REQUIRED: number; + const NGHTTP2_ERR_FRAME_SIZE_ERROR: number; + const NGHTTP2_FLAG_NONE: number; + const NGHTTP2_FLAG_END_STREAM: number; + const NGHTTP2_FLAG_END_HEADERS: number; + const NGHTTP2_FLAG_ACK: number; + const NGHTTP2_FLAG_PADDED: number; + const NGHTTP2_FLAG_PRIORITY: number; + const DEFAULT_SETTINGS_HEADER_TABLE_SIZE: number; + const DEFAULT_SETTINGS_ENABLE_PUSH: number; + const DEFAULT_SETTINGS_INITIAL_WINDOW_SIZE: number; + const DEFAULT_SETTINGS_MAX_FRAME_SIZE: number; + const MAX_MAX_FRAME_SIZE: number; + const MIN_MAX_FRAME_SIZE: number; + const MAX_INITIAL_WINDOW_SIZE: number; + const NGHTTP2_DEFAULT_WEIGHT: number; + const NGHTTP2_SETTINGS_HEADER_TABLE_SIZE: number; + const NGHTTP2_SETTINGS_ENABLE_PUSH: number; + const NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS: number; + const NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE: number; + const NGHTTP2_SETTINGS_MAX_FRAME_SIZE: number; + const NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE: number; + const PADDING_STRATEGY_NONE: number; + const PADDING_STRATEGY_MAX: number; + const PADDING_STRATEGY_CALLBACK: number; + const HTTP2_HEADER_STATUS: string; + const HTTP2_HEADER_METHOD: string; + const HTTP2_HEADER_AUTHORITY: string; + const HTTP2_HEADER_SCHEME: string; + const HTTP2_HEADER_PATH: string; + const HTTP2_HEADER_ACCEPT_CHARSET: string; + const HTTP2_HEADER_ACCEPT_ENCODING: string; + const HTTP2_HEADER_ACCEPT_LANGUAGE: string; + const HTTP2_HEADER_ACCEPT_RANGES: string; + const HTTP2_HEADER_ACCEPT: string; + const HTTP2_HEADER_ACCESS_CONTROL_ALLOW_CREDENTIALS: string; + const HTTP2_HEADER_ACCESS_CONTROL_ALLOW_HEADERS: string; + const HTTP2_HEADER_ACCESS_CONTROL_ALLOW_METHODS: string; + const HTTP2_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN: string; + const HTTP2_HEADER_ACCESS_CONTROL_EXPOSE_HEADERS: string; + const HTTP2_HEADER_ACCESS_CONTROL_REQUEST_HEADERS: string; + const HTTP2_HEADER_ACCESS_CONTROL_REQUEST_METHOD: string; + const HTTP2_HEADER_AGE: string; + const HTTP2_HEADER_ALLOW: string; + const HTTP2_HEADER_AUTHORIZATION: string; + const HTTP2_HEADER_CACHE_CONTROL: string; + const HTTP2_HEADER_CONNECTION: string; + const HTTP2_HEADER_CONTENT_DISPOSITION: string; + const HTTP2_HEADER_CONTENT_ENCODING: string; + const HTTP2_HEADER_CONTENT_LANGUAGE: string; + const HTTP2_HEADER_CONTENT_LENGTH: string; + const HTTP2_HEADER_CONTENT_LOCATION: string; + const HTTP2_HEADER_CONTENT_MD5: string; + const HTTP2_HEADER_CONTENT_RANGE: string; + const HTTP2_HEADER_CONTENT_TYPE: string; + const HTTP2_HEADER_COOKIE: string; + const HTTP2_HEADER_DATE: string; + const HTTP2_HEADER_ETAG: string; + const HTTP2_HEADER_EXPECT: string; + const HTTP2_HEADER_EXPIRES: string; + const HTTP2_HEADER_FROM: string; + const HTTP2_HEADER_HOST: string; + const HTTP2_HEADER_IF_MATCH: string; + const HTTP2_HEADER_IF_MODIFIED_SINCE: string; + const HTTP2_HEADER_IF_NONE_MATCH: string; + const HTTP2_HEADER_IF_RANGE: string; + const HTTP2_HEADER_IF_UNMODIFIED_SINCE: string; + const HTTP2_HEADER_LAST_MODIFIED: string; + const HTTP2_HEADER_LINK: string; + const HTTP2_HEADER_LOCATION: string; + const HTTP2_HEADER_MAX_FORWARDS: string; + const HTTP2_HEADER_PREFER: string; + const HTTP2_HEADER_PROXY_AUTHENTICATE: string; + const HTTP2_HEADER_PROXY_AUTHORIZATION: string; + const HTTP2_HEADER_RANGE: string; + const HTTP2_HEADER_REFERER: string; + const HTTP2_HEADER_REFRESH: string; + const HTTP2_HEADER_RETRY_AFTER: string; + const HTTP2_HEADER_SERVER: string; + const HTTP2_HEADER_SET_COOKIE: string; + const HTTP2_HEADER_STRICT_TRANSPORT_SECURITY: string; + const HTTP2_HEADER_TRANSFER_ENCODING: string; + const HTTP2_HEADER_TE: string; + const HTTP2_HEADER_UPGRADE: string; + const HTTP2_HEADER_USER_AGENT: string; + const HTTP2_HEADER_VARY: string; + const HTTP2_HEADER_VIA: string; + const HTTP2_HEADER_WWW_AUTHENTICATE: string; + const HTTP2_HEADER_HTTP2_SETTINGS: string; + const HTTP2_HEADER_KEEP_ALIVE: string; + const HTTP2_HEADER_PROXY_CONNECTION: string; + const HTTP2_METHOD_ACL: string; + const HTTP2_METHOD_BASELINE_CONTROL: string; + const HTTP2_METHOD_BIND: string; + const HTTP2_METHOD_CHECKIN: string; + const HTTP2_METHOD_CHECKOUT: string; + const HTTP2_METHOD_CONNECT: string; + const HTTP2_METHOD_COPY: string; + const HTTP2_METHOD_DELETE: string; + const HTTP2_METHOD_GET: string; + const HTTP2_METHOD_HEAD: string; + const HTTP2_METHOD_LABEL: string; + const HTTP2_METHOD_LINK: string; + const HTTP2_METHOD_LOCK: string; + const HTTP2_METHOD_MERGE: string; + const HTTP2_METHOD_MKACTIVITY: string; + const HTTP2_METHOD_MKCALENDAR: string; + const HTTP2_METHOD_MKCOL: string; + const HTTP2_METHOD_MKREDIRECTREF: string; + const HTTP2_METHOD_MKWORKSPACE: string; + const HTTP2_METHOD_MOVE: string; + const HTTP2_METHOD_OPTIONS: string; + const HTTP2_METHOD_ORDERPATCH: string; + const HTTP2_METHOD_PATCH: string; + const HTTP2_METHOD_POST: string; + const HTTP2_METHOD_PRI: string; + const HTTP2_METHOD_PROPFIND: string; + const HTTP2_METHOD_PROPPATCH: string; + const HTTP2_METHOD_PUT: string; + const HTTP2_METHOD_REBIND: string; + const HTTP2_METHOD_REPORT: string; + const HTTP2_METHOD_SEARCH: string; + const HTTP2_METHOD_TRACE: string; + const HTTP2_METHOD_UNBIND: string; + const HTTP2_METHOD_UNCHECKOUT: string; + const HTTP2_METHOD_UNLINK: string; + const HTTP2_METHOD_UNLOCK: string; + const HTTP2_METHOD_UPDATE: string; + const HTTP2_METHOD_UPDATEREDIRECTREF: string; + const HTTP2_METHOD_VERSION_CONTROL: string; + const HTTP_STATUS_CONTINUE: number; + const HTTP_STATUS_SWITCHING_PROTOCOLS: number; + const HTTP_STATUS_PROCESSING: number; + const HTTP_STATUS_OK: number; + const HTTP_STATUS_CREATED: number; + const HTTP_STATUS_ACCEPTED: number; + const HTTP_STATUS_NON_AUTHORITATIVE_INFORMATION: number; + const HTTP_STATUS_NO_CONTENT: number; + const HTTP_STATUS_RESET_CONTENT: number; + const HTTP_STATUS_PARTIAL_CONTENT: number; + const HTTP_STATUS_MULTI_STATUS: number; + const HTTP_STATUS_ALREADY_REPORTED: number; + const HTTP_STATUS_IM_USED: number; + const HTTP_STATUS_MULTIPLE_CHOICES: number; + const HTTP_STATUS_MOVED_PERMANENTLY: number; + const HTTP_STATUS_FOUND: number; + const HTTP_STATUS_SEE_OTHER: number; + const HTTP_STATUS_NOT_MODIFIED: number; + const HTTP_STATUS_USE_PROXY: number; + const HTTP_STATUS_TEMPORARY_REDIRECT: number; + const HTTP_STATUS_PERMANENT_REDIRECT: number; + const HTTP_STATUS_BAD_REQUEST: number; + const HTTP_STATUS_UNAUTHORIZED: number; + const HTTP_STATUS_PAYMENT_REQUIRED: number; + const HTTP_STATUS_FORBIDDEN: number; + const HTTP_STATUS_NOT_FOUND: number; + const HTTP_STATUS_METHOD_NOT_ALLOWED: number; + const HTTP_STATUS_NOT_ACCEPTABLE: number; + const HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED: number; + const HTTP_STATUS_REQUEST_TIMEOUT: number; + const HTTP_STATUS_CONFLICT: number; + const HTTP_STATUS_GONE: number; + const HTTP_STATUS_LENGTH_REQUIRED: number; + const HTTP_STATUS_PRECONDITION_FAILED: number; + const HTTP_STATUS_PAYLOAD_TOO_LARGE: number; + const HTTP_STATUS_URI_TOO_LONG: number; + const HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE: number; + const HTTP_STATUS_RANGE_NOT_SATISFIABLE: number; + const HTTP_STATUS_EXPECTATION_FAILED: number; + const HTTP_STATUS_TEAPOT: number; + const HTTP_STATUS_MISDIRECTED_REQUEST: number; + const HTTP_STATUS_UNPROCESSABLE_ENTITY: number; + const HTTP_STATUS_LOCKED: number; + const HTTP_STATUS_FAILED_DEPENDENCY: number; + const HTTP_STATUS_UNORDERED_COLLECTION: number; + const HTTP_STATUS_UPGRADE_REQUIRED: number; + const HTTP_STATUS_PRECONDITION_REQUIRED: number; + const HTTP_STATUS_TOO_MANY_REQUESTS: number; + const HTTP_STATUS_REQUEST_HEADER_FIELDS_TOO_LARGE: number; + const HTTP_STATUS_UNAVAILABLE_FOR_LEGAL_REASONS: number; + const HTTP_STATUS_INTERNAL_SERVER_ERROR: number; + const HTTP_STATUS_NOT_IMPLEMENTED: number; + const HTTP_STATUS_BAD_GATEWAY: number; + const HTTP_STATUS_SERVICE_UNAVAILABLE: number; + const HTTP_STATUS_GATEWAY_TIMEOUT: number; + const HTTP_STATUS_HTTP_VERSION_NOT_SUPPORTED: number; + const HTTP_STATUS_VARIANT_ALSO_NEGOTIATES: number; + const HTTP_STATUS_INSUFFICIENT_STORAGE: number; + const HTTP_STATUS_LOOP_DETECTED: number; + const HTTP_STATUS_BANDWIDTH_LIMIT_EXCEEDED: number; + const HTTP_STATUS_NOT_EXTENDED: number; + const HTTP_STATUS_NETWORK_AUTHENTICATION_REQUIRED: number; + } + /** + * This symbol can be set as a property on the HTTP/2 headers object with + * an array value in order to provide a list of headers considered sensitive. + */ + const sensitiveHeaders: symbol; + /** + * Returns an object containing the default settings for an `Http2Session` instance. This method returns a new object instance every time it is called + * so instances returned may be safely modified for use. + * @since v8.4.0 + */ + function getDefaultSettings(): Settings; + /** + * Returns a `Buffer` instance containing serialized representation of the given + * HTTP/2 settings as specified in the [HTTP/2](https://tools.ietf.org/html/rfc7540) specification. This is intended + * for use with the `HTTP2-Settings` header field. + * + * ```js + * import http2 from 'node:http2'; + * + * const packed = http2.getPackedSettings({ enablePush: false }); + * + * console.log(packed.toString('base64')); + * // Prints: AAIAAAAA + * ``` + * @since v8.4.0 + */ + function getPackedSettings(settings: Settings): NonSharedBuffer; + /** + * Returns a `HTTP/2 Settings Object` containing the deserialized settings from + * the given `Buffer` as generated by `http2.getPackedSettings()`. + * @since v8.4.0 + * @param buf The packed settings. + */ + function getUnpackedSettings(buf: Uint8Array): Settings; + /** + * Returns a `net.Server` instance that creates and manages `Http2Session` instances. + * + * Since there are no browsers known that support [unencrypted HTTP/2](https://http2.github.io/faq/#does-http2-require-encryption), the use of {@link createSecureServer} is necessary when + * communicating + * with browser clients. + * + * ```js + * import http2 from 'node:http2'; + * + * // Create an unencrypted HTTP/2 server. + * // Since there are no browsers known that support + * // unencrypted HTTP/2, the use of `http2.createSecureServer()` + * // is necessary when communicating with browser clients. + * const server = http2.createServer(); + * + * server.on('stream', (stream, headers) => { + * stream.respond({ + * 'content-type': 'text/html; charset=utf-8', + * ':status': 200, + * }); + * stream.end('<h1>Hello World</h1>'); + * }); + * + * server.listen(8000); + * ``` + * @since v8.4.0 + * @param onRequestHandler See `Compatibility API` + */ + function createServer( + onRequestHandler?: (request: Http2ServerRequest, response: Http2ServerResponse) => void, + ): Http2Server; + function createServer< + Http1Request extends typeof IncomingMessage = typeof IncomingMessage, + Http1Response extends typeof ServerResponse<InstanceType<Http1Request>> = typeof ServerResponse, + Http2Request extends typeof Http2ServerRequest = typeof Http2ServerRequest, + Http2Response extends typeof Http2ServerResponse<InstanceType<Http2Request>> = typeof Http2ServerResponse, + >( + options: ServerOptions<Http1Request, Http1Response, Http2Request, Http2Response>, + onRequestHandler?: (request: InstanceType<Http2Request>, response: InstanceType<Http2Response>) => void, + ): Http2Server<Http1Request, Http1Response, Http2Request, Http2Response>; + /** + * Returns a `tls.Server` instance that creates and manages `Http2Session` instances. + * + * ```js + * import http2 from 'node:http2'; + * import fs from 'node:fs'; + * + * const options = { + * key: fs.readFileSync('server-key.pem'), + * cert: fs.readFileSync('server-cert.pem'), + * }; + * + * // Create a secure HTTP/2 server + * const server = http2.createSecureServer(options); + * + * server.on('stream', (stream, headers) => { + * stream.respond({ + * 'content-type': 'text/html; charset=utf-8', + * ':status': 200, + * }); + * stream.end('<h1>Hello World</h1>'); + * }); + * + * server.listen(8443); + * ``` + * @since v8.4.0 + * @param onRequestHandler See `Compatibility API` + */ + function createSecureServer( + onRequestHandler?: (request: Http2ServerRequest, response: Http2ServerResponse) => void, + ): Http2SecureServer; + function createSecureServer< + Http1Request extends typeof IncomingMessage = typeof IncomingMessage, + Http1Response extends typeof ServerResponse<InstanceType<Http1Request>> = typeof ServerResponse, + Http2Request extends typeof Http2ServerRequest = typeof Http2ServerRequest, + Http2Response extends typeof Http2ServerResponse<InstanceType<Http2Request>> = typeof Http2ServerResponse, + >( + options: SecureServerOptions<Http1Request, Http1Response, Http2Request, Http2Response>, + onRequestHandler?: (request: InstanceType<Http2Request>, response: InstanceType<Http2Response>) => void, + ): Http2SecureServer<Http1Request, Http1Response, Http2Request, Http2Response>; + /** + * Returns a `ClientHttp2Session` instance. + * + * ```js + * import http2 from 'node:http2'; + * const client = http2.connect('https://localhost:1234'); + * + * // Use the client + * + * client.close(); + * ``` + * @since v8.4.0 + * @param authority The remote HTTP/2 server to connect to. This must be in the form of a minimal, valid URL with the `http://` or `https://` prefix, host name, and IP port (if a non-default port + * is used). Userinfo (user ID and password), path, querystring, and fragment details in the URL will be ignored. + * @param listener Will be registered as a one-time listener of the {@link 'connect'} event. + */ + function connect( + authority: string | url.URL, + listener: (session: ClientHttp2Session, socket: net.Socket | tls.TLSSocket) => void, + ): ClientHttp2Session; + function connect( + authority: string | url.URL, + options?: ClientSessionOptions | SecureClientSessionOptions, + listener?: (session: ClientHttp2Session, socket: net.Socket | tls.TLSSocket) => void, + ): ClientHttp2Session; + /** + * Create an HTTP/2 server session from an existing socket. + * @param socket A Duplex Stream + * @param options Any `{@link createServer}` options can be provided. + * @since v20.12.0 + */ + function performServerHandshake< + Http1Request extends typeof IncomingMessage = typeof IncomingMessage, + Http1Response extends typeof ServerResponse<InstanceType<Http1Request>> = typeof ServerResponse, + Http2Request extends typeof Http2ServerRequest = typeof Http2ServerRequest, + Http2Response extends typeof Http2ServerResponse<InstanceType<Http2Request>> = typeof Http2ServerResponse, + >( + socket: stream.Duplex, + options?: ServerOptions<Http1Request, Http1Response, Http2Request, Http2Response>, + ): ServerHttp2Session<Http1Request, Http1Response, Http2Request, Http2Response>; +} +declare module "node:http2" { + export { OutgoingHttpHeaders } from "node:http"; +} +declare module "http2" { + export * from "node:http2"; +} diff --git a/server/node_modules/@types/node/https.d.ts b/server/node_modules/@types/node/https.d.ts new file mode 100644 index 0000000..6b02569 --- /dev/null +++ b/server/node_modules/@types/node/https.d.ts @@ -0,0 +1,405 @@ +/** + * HTTPS is the HTTP protocol over TLS/SSL. In Node.js this is implemented as a + * separate module. + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/https.js) + */ +declare module "node:https" { + import * as http from "node:http"; + import { Duplex } from "node:stream"; + import * as tls from "node:tls"; + import { URL } from "node:url"; + interface ServerOptions< + Request extends typeof http.IncomingMessage = typeof http.IncomingMessage, + Response extends typeof http.ServerResponse<InstanceType<Request>> = typeof http.ServerResponse, + > extends http.ServerOptions<Request, Response>, tls.TlsOptions {} + interface RequestOptions extends http.RequestOptions, tls.SecureContextOptions { + checkServerIdentity?: + | ((hostname: string, cert: tls.DetailedPeerCertificate) => Error | undefined) + | undefined; + rejectUnauthorized?: boolean | undefined; // Defaults to true + servername?: string | undefined; // SNI TLS Extension + } + interface AgentOptions extends http.AgentOptions, tls.ConnectionOptions { + maxCachedSessions?: number | undefined; + } + /** + * An `Agent` object for HTTPS similar to `http.Agent`. See {@link request} for more information. + * + * Like `http.Agent`, the `createConnection(options[, callback])` method can be overridden + * to customize how TLS connections are established. + * + * > See `agent.createConnection()` for details on overriding this method, + * > including asynchronous socket creation with a callback. + * @since v0.4.5 + */ + class Agent extends http.Agent { + constructor(options?: AgentOptions); + options: AgentOptions; + createConnection( + options: RequestOptions, + callback?: (err: Error | null, stream: Duplex) => void, + ): Duplex | null | undefined; + getName(options?: RequestOptions): string; + } + interface ServerEventMap< + Request extends typeof http.IncomingMessage = typeof http.IncomingMessage, + Response extends typeof http.ServerResponse<InstanceType<Request>> = typeof http.ServerResponse, + > extends http.ServerEventMap<Request, Response>, tls.ServerEventMap {} + /** + * See `http.Server` for more information. + * @since v0.3.4 + */ + class Server< + Request extends typeof http.IncomingMessage = typeof http.IncomingMessage, + Response extends typeof http.ServerResponse<InstanceType<Request>> = typeof http.ServerResponse, + > extends tls.Server { + constructor(requestListener?: http.RequestListener<Request, Response>); + constructor( + options: ServerOptions<Request, Response>, + requestListener?: http.RequestListener<Request, Response>, + ); + /** + * Closes all connections connected to this server. + * @since v18.2.0 + */ + closeAllConnections(): void; + /** + * Closes all connections connected to this server which are not sending a request or waiting for a response. + * @since v18.2.0 + */ + closeIdleConnections(): void; + // #region InternalEventEmitter + addListener<E extends keyof ServerEventMap>( + eventName: E, + listener: (...args: ServerEventMap<Request, Response>[E]) => void, + ): this; + addListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + emit<E extends keyof ServerEventMap>(eventName: E, ...args: ServerEventMap<Request, Response>[E]): boolean; + emit(eventName: string | symbol, ...args: any[]): boolean; + listenerCount<E extends keyof ServerEventMap>( + eventName: E, + listener?: (...args: ServerEventMap<Request, Response>[E]) => void, + ): number; + listenerCount(eventName: string | symbol, listener?: (...args: any[]) => void): number; + listeners<E extends keyof ServerEventMap>( + eventName: E, + ): ((...args: ServerEventMap<Request, Response>[E]) => void)[]; + listeners(eventName: string | symbol): ((...args: any[]) => void)[]; + off<E extends keyof ServerEventMap>( + eventName: E, + listener: (...args: ServerEventMap<Request, Response>[E]) => void, + ): this; + off(eventName: string | symbol, listener: (...args: any[]) => void): this; + on<E extends keyof ServerEventMap>( + eventName: E, + listener: (...args: ServerEventMap<Request, Response>[E]) => void, + ): this; + on(eventName: string | symbol, listener: (...args: any[]) => void): this; + once<E extends keyof ServerEventMap>( + eventName: E, + listener: (...args: ServerEventMap<Request, Response>[E]) => void, + ): this; + once(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependListener<E extends keyof ServerEventMap>( + eventName: E, + listener: (...args: ServerEventMap<Request, Response>[E]) => void, + ): this; + prependListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependOnceListener<E extends keyof ServerEventMap>( + eventName: E, + listener: (...args: ServerEventMap<Request, Response>[E]) => void, + ): this; + prependOnceListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + rawListeners<E extends keyof ServerEventMap>( + eventName: E, + ): ((...args: ServerEventMap<Request, Response>[E]) => void)[]; + rawListeners(eventName: string | symbol): ((...args: any[]) => void)[]; + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + removeAllListeners<E extends keyof ServerEventMap>(eventName?: E): this; + removeAllListeners(eventName?: string | symbol): this; + removeListener<E extends keyof ServerEventMap>( + eventName: E, + listener: (...args: ServerEventMap<Request, Response>[E]) => void, + ): this; + removeListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + // #endregion + } + interface Server< + Request extends typeof http.IncomingMessage = typeof http.IncomingMessage, + Response extends typeof http.ServerResponse<InstanceType<Request>> = typeof http.ServerResponse, + > extends http.Server<Request, Response> {} + /** + * ```js + * // curl -k https://localhost:8000/ + * import https from 'node:https'; + * import fs from 'node:fs'; + * + * const options = { + * key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'), + * cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem'), + * }; + * + * https.createServer(options, (req, res) => { + * res.writeHead(200); + * res.end('hello world\n'); + * }).listen(8000); + * ``` + * + * Or + * + * ```js + * import https from 'node:https'; + * import fs from 'node:fs'; + * + * const options = { + * pfx: fs.readFileSync('test/fixtures/test_cert.pfx'), + * passphrase: 'sample', + * }; + * + * https.createServer(options, (req, res) => { + * res.writeHead(200); + * res.end('hello world\n'); + * }).listen(8000); + * ``` + * @since v0.3.4 + * @param options Accepts `options` from `createServer`, `createSecureContext` and `createServer`. + * @param requestListener A listener to be added to the `'request'` event. + */ + function createServer< + Request extends typeof http.IncomingMessage = typeof http.IncomingMessage, + Response extends typeof http.ServerResponse<InstanceType<Request>> = typeof http.ServerResponse, + >(requestListener?: http.RequestListener<Request, Response>): Server<Request, Response>; + function createServer< + Request extends typeof http.IncomingMessage = typeof http.IncomingMessage, + Response extends typeof http.ServerResponse<InstanceType<Request>> = typeof http.ServerResponse, + >( + options: ServerOptions<Request, Response>, + requestListener?: http.RequestListener<Request, Response>, + ): Server<Request, Response>; + /** + * Makes a request to a secure web server. + * + * The following additional `options` from `tls.connect()` are also accepted: `ca`, `cert`, `ciphers`, `clientCertEngine`, `crl`, `dhparam`, `ecdhCurve`, `honorCipherOrder`, `key`, `passphrase`, + * `pfx`, `rejectUnauthorized`, `secureOptions`, `secureProtocol`, `servername`, `sessionIdContext`, `highWaterMark`. + * + * `options` can be an object, a string, or a `URL` object. If `options` is a + * string, it is automatically parsed with `new URL()`. If it is a `URL` object, it will be automatically converted to an ordinary `options` object. + * + * `https.request()` returns an instance of the `http.ClientRequest` class. The `ClientRequest` instance is a writable stream. If one needs to + * upload a file with a POST request, then write to the `ClientRequest` object. + * + * ```js + * import https from 'node:https'; + * + * const options = { + * hostname: 'encrypted.google.com', + * port: 443, + * path: '/', + * method: 'GET', + * }; + * + * const req = https.request(options, (res) => { + * console.log('statusCode:', res.statusCode); + * console.log('headers:', res.headers); + * + * res.on('data', (d) => { + * process.stdout.write(d); + * }); + * }); + * + * req.on('error', (e) => { + * console.error(e); + * }); + * req.end(); + * ``` + * + * Example using options from `tls.connect()`: + * + * ```js + * const options = { + * hostname: 'encrypted.google.com', + * port: 443, + * path: '/', + * method: 'GET', + * key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'), + * cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem'), + * }; + * options.agent = new https.Agent(options); + * + * const req = https.request(options, (res) => { + * // ... + * }); + * ``` + * + * Alternatively, opt out of connection pooling by not using an `Agent`. + * + * ```js + * const options = { + * hostname: 'encrypted.google.com', + * port: 443, + * path: '/', + * method: 'GET', + * key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'), + * cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem'), + * agent: false, + * }; + * + * const req = https.request(options, (res) => { + * // ... + * }); + * ``` + * + * Example using a `URL` as `options`: + * + * ```js + * const options = new URL('https://abc:xyz@example.com'); + * + * const req = https.request(options, (res) => { + * // ... + * }); + * ``` + * + * Example pinning on certificate fingerprint, or the public key (similar to`pin-sha256`): + * + * ```js + * import tls from 'node:tls'; + * import https from 'node:https'; + * import crypto from 'node:crypto'; + * + * function sha256(s) { + * return crypto.createHash('sha256').update(s).digest('base64'); + * } + * const options = { + * hostname: 'github.com', + * port: 443, + * path: '/', + * method: 'GET', + * checkServerIdentity: function(host, cert) { + * // Make sure the certificate is issued to the host we are connected to + * const err = tls.checkServerIdentity(host, cert); + * if (err) { + * return err; + * } + * + * // Pin the public key, similar to HPKP pin-sha256 pinning + * const pubkey256 = 'pL1+qb9HTMRZJmuC/bB/ZI9d302BYrrqiVuRyW+DGrU='; + * if (sha256(cert.pubkey) !== pubkey256) { + * const msg = 'Certificate verification error: ' + + * `The public key of '${cert.subject.CN}' ` + + * 'does not match our pinned fingerprint'; + * return new Error(msg); + * } + * + * // Pin the exact certificate, rather than the pub key + * const cert256 = '25:FE:39:32:D9:63:8C:8A:FC:A1:9A:29:87:' + + * 'D8:3E:4C:1D:98:DB:71:E4:1A:48:03:98:EA:22:6A:BD:8B:93:16'; + * if (cert.fingerprint256 !== cert256) { + * const msg = 'Certificate verification error: ' + + * `The certificate of '${cert.subject.CN}' ` + + * 'does not match our pinned fingerprint'; + * return new Error(msg); + * } + * + * // This loop is informational only. + * // Print the certificate and public key fingerprints of all certs in the + * // chain. Its common to pin the public key of the issuer on the public + * // internet, while pinning the public key of the service in sensitive + * // environments. + * do { + * console.log('Subject Common Name:', cert.subject.CN); + * console.log(' Certificate SHA256 fingerprint:', cert.fingerprint256); + * + * hash = crypto.createHash('sha256'); + * console.log(' Public key ping-sha256:', sha256(cert.pubkey)); + * + * lastprint256 = cert.fingerprint256; + * cert = cert.issuerCertificate; + * } while (cert.fingerprint256 !== lastprint256); + * + * }, + * }; + * + * options.agent = new https.Agent(options); + * const req = https.request(options, (res) => { + * console.log('All OK. Server matched our pinned cert or public key'); + * console.log('statusCode:', res.statusCode); + * // Print the HPKP values + * console.log('headers:', res.headers['public-key-pins']); + * + * res.on('data', (d) => {}); + * }); + * + * req.on('error', (e) => { + * console.error(e.message); + * }); + * req.end(); + * ``` + * + * Outputs for example: + * + * ```text + * Subject Common Name: github.com + * Certificate SHA256 fingerprint: 25:FE:39:32:D9:63:8C:8A:FC:A1:9A:29:87:D8:3E:4C:1D:98:DB:71:E4:1A:48:03:98:EA:22:6A:BD:8B:93:16 + * Public key ping-sha256: pL1+qb9HTMRZJmuC/bB/ZI9d302BYrrqiVuRyW+DGrU= + * Subject Common Name: DigiCert SHA2 Extended Validation Server CA + * Certificate SHA256 fingerprint: 40:3E:06:2A:26:53:05:91:13:28:5B:AF:80:A0:D4:AE:42:2C:84:8C:9F:78:FA:D0:1F:C9:4B:C5:B8:7F:EF:1A + * Public key ping-sha256: RRM1dGqnDFsCJXBTHky16vi1obOlCgFFn/yOhI/y+ho= + * Subject Common Name: DigiCert High Assurance EV Root CA + * Certificate SHA256 fingerprint: 74:31:E5:F4:C3:C1:CE:46:90:77:4F:0B:61:E0:54:40:88:3B:A9:A0:1E:D0:0B:A6:AB:D7:80:6E:D3:B1:18:CF + * Public key ping-sha256: WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18= + * All OK. Server matched our pinned cert or public key + * statusCode: 200 + * headers: max-age=0; pin-sha256="WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18="; pin-sha256="RRM1dGqnDFsCJXBTHky16vi1obOlCgFFn/yOhI/y+ho="; + * pin-sha256="k2v657xBsOVe1PQRwOsHsw3bsGT2VzIqz5K+59sNQws="; pin-sha256="K87oWBWM9UZfyddvDfoxL+8lpNyoUB2ptGtn0fv6G2Q="; pin-sha256="IQBnNBEiFuhj+8x6X8XLgh01V9Ic5/V3IRQLNFFc7v4="; + * pin-sha256="iie1VXtL7HzAMF+/PVPR9xzT80kQxdZeJ+zduCB3uj0="; pin-sha256="LvRiGEjRqfzurezaWuj8Wie2gyHMrW5Q06LspMnox7A="; includeSubDomains + * ``` + * @since v0.3.6 + * @param options Accepts all `options` from `request`, with some differences in default values: + */ + function request( + options: RequestOptions | string | URL, + callback?: (res: http.IncomingMessage) => void, + ): http.ClientRequest; + function request( + url: string | URL, + options: RequestOptions, + callback?: (res: http.IncomingMessage) => void, + ): http.ClientRequest; + /** + * Like `http.get()` but for HTTPS. + * + * `options` can be an object, a string, or a `URL` object. If `options` is a + * string, it is automatically parsed with `new URL()`. If it is a `URL` object, it will be automatically converted to an ordinary `options` object. + * + * ```js + * import https from 'node:https'; + * + * https.get('https://encrypted.google.com/', (res) => { + * console.log('statusCode:', res.statusCode); + * console.log('headers:', res.headers); + * + * res.on('data', (d) => { + * process.stdout.write(d); + * }); + * + * }).on('error', (e) => { + * console.error(e); + * }); + * ``` + * @since v0.3.6 + * @param options Accepts the same `options` as {@link request}, with the `method` always set to `GET`. + */ + function get( + options: RequestOptions | string | URL, + callback?: (res: http.IncomingMessage) => void, + ): http.ClientRequest; + function get( + url: string | URL, + options: RequestOptions, + callback?: (res: http.IncomingMessage) => void, + ): http.ClientRequest; + let globalAgent: Agent; +} +declare module "https" { + export * from "node:https"; +} diff --git a/server/node_modules/@types/node/index.d.ts b/server/node_modules/@types/node/index.d.ts new file mode 100644 index 0000000..08ab4f0 --- /dev/null +++ b/server/node_modules/@types/node/index.d.ts @@ -0,0 +1,115 @@ +/** + * License for programmatically and manually incorporated + * documentation aka. `JSDoc` from https://github.com/nodejs/node/tree/master/doc + * + * Copyright Node.js contributors. All rights reserved. + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +// NOTE: These definitions support Node.js and TypeScript 5.8+. + +// Reference required TypeScript libraries: +/// <reference lib="es2020" /> +/// <reference lib="esnext.disposable" /> +/// <reference lib="esnext.float16" /> + +// Iterator definitions required for compatibility with TypeScript <5.6: +/// <reference path="compatibility/iterators.d.ts" /> + +// Definitions for Node.js modules specific to TypeScript 5.7+: +/// <reference path="globals.typedarray.d.ts" /> +/// <reference path="buffer.buffer.d.ts" /> + +// Definitions for Node.js modules that are not specific to any version of TypeScript: +/// <reference path="globals.d.ts" /> +/// <reference path="web-globals/abortcontroller.d.ts" /> +/// <reference path="web-globals/blob.d.ts" /> +/// <reference path="web-globals/console.d.ts" /> +/// <reference path="web-globals/crypto.d.ts" /> +/// <reference path="web-globals/domexception.d.ts" /> +/// <reference path="web-globals/encoding.d.ts" /> +/// <reference path="web-globals/events.d.ts" /> +/// <reference path="web-globals/fetch.d.ts" /> +/// <reference path="web-globals/importmeta.d.ts" /> +/// <reference path="web-globals/messaging.d.ts" /> +/// <reference path="web-globals/navigator.d.ts" /> +/// <reference path="web-globals/performance.d.ts" /> +/// <reference path="web-globals/storage.d.ts" /> +/// <reference path="web-globals/streams.d.ts" /> +/// <reference path="web-globals/timers.d.ts" /> +/// <reference path="web-globals/url.d.ts" /> +/// <reference path="assert.d.ts" /> +/// <reference path="assert/strict.d.ts" /> +/// <reference path="async_hooks.d.ts" /> +/// <reference path="buffer.d.ts" /> +/// <reference path="child_process.d.ts" /> +/// <reference path="cluster.d.ts" /> +/// <reference path="console.d.ts" /> +/// <reference path="constants.d.ts" /> +/// <reference path="crypto.d.ts" /> +/// <reference path="dgram.d.ts" /> +/// <reference path="diagnostics_channel.d.ts" /> +/// <reference path="dns.d.ts" /> +/// <reference path="dns/promises.d.ts" /> +/// <reference path="domain.d.ts" /> +/// <reference path="events.d.ts" /> +/// <reference path="fs.d.ts" /> +/// <reference path="fs/promises.d.ts" /> +/// <reference path="http.d.ts" /> +/// <reference path="http2.d.ts" /> +/// <reference path="https.d.ts" /> +/// <reference path="inspector.d.ts" /> +/// <reference path="inspector.generated.d.ts" /> +/// <reference path="inspector/promises.d.ts" /> +/// <reference path="module.d.ts" /> +/// <reference path="net.d.ts" /> +/// <reference path="os.d.ts" /> +/// <reference path="path.d.ts" /> +/// <reference path="path/posix.d.ts" /> +/// <reference path="path/win32.d.ts" /> +/// <reference path="perf_hooks.d.ts" /> +/// <reference path="process.d.ts" /> +/// <reference path="punycode.d.ts" /> +/// <reference path="querystring.d.ts" /> +/// <reference path="quic.d.ts" /> +/// <reference path="readline.d.ts" /> +/// <reference path="readline/promises.d.ts" /> +/// <reference path="repl.d.ts" /> +/// <reference path="sea.d.ts" /> +/// <reference path="sqlite.d.ts" /> +/// <reference path="stream.d.ts" /> +/// <reference path="stream/consumers.d.ts" /> +/// <reference path="stream/promises.d.ts" /> +/// <reference path="stream/web.d.ts" /> +/// <reference path="string_decoder.d.ts" /> +/// <reference path="test.d.ts" /> +/// <reference path="test/reporters.d.ts" /> +/// <reference path="timers.d.ts" /> +/// <reference path="timers/promises.d.ts" /> +/// <reference path="tls.d.ts" /> +/// <reference path="trace_events.d.ts" /> +/// <reference path="tty.d.ts" /> +/// <reference path="url.d.ts" /> +/// <reference path="util.d.ts" /> +/// <reference path="util/types.d.ts" /> +/// <reference path="v8.d.ts" /> +/// <reference path="vm.d.ts" /> +/// <reference path="wasi.d.ts" /> +/// <reference path="worker_threads.d.ts" /> +/// <reference path="zlib.d.ts" /> diff --git a/server/node_modules/@types/node/inspector.d.ts b/server/node_modules/@types/node/inspector.d.ts new file mode 100644 index 0000000..c3a7785 --- /dev/null +++ b/server/node_modules/@types/node/inspector.d.ts @@ -0,0 +1,224 @@ +/** + * The `node:inspector` module provides an API for interacting with the V8 + * inspector. + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/inspector.js) + */ +declare module "node:inspector" { + import { EventEmitter } from "node:events"; + /** + * The `inspector.Session` is used for dispatching messages to the V8 inspector + * back-end and receiving message responses and notifications. + */ + class Session extends EventEmitter { + /** + * Create a new instance of the inspector.Session class. + * The inspector session needs to be connected through `session.connect()` before the messages can be dispatched to the inspector backend. + */ + constructor(); + /** + * Connects a session to the inspector back-end. + */ + connect(): void; + /** + * Connects a session to the inspector back-end. + * An exception will be thrown if this API was not called on a Worker thread. + * @since v12.11.0 + */ + connectToMainThread(): void; + /** + * Immediately close the session. All pending message callbacks will be called with an error. + * `session.connect()` will need to be called to be able to send messages again. + * Reconnected session will lose all inspector state, such as enabled agents or configured breakpoints. + */ + disconnect(): void; + } + /** + * Activate inspector on host and port. Equivalent to `node --inspect=[[host:]port]`, but can be done programmatically after node has + * started. + * + * If wait is `true`, will block until a client has connected to the inspect port + * and flow control has been passed to the debugger client. + * + * See the [security warning](https://nodejs.org/docs/latest-v25.x/api/cli.html#warning-binding-inspector-to-a-public-ipport-combination-is-insecure) + * regarding the `host` parameter usage. + * @param port Port to listen on for inspector connections. Defaults to what was specified on the CLI. + * @param host Host to listen on for inspector connections. Defaults to what was specified on the CLI. + * @param wait Block until a client has connected. Defaults to what was specified on the CLI. + * @returns Disposable that calls `inspector.close()`. + */ + function open(port?: number, host?: string, wait?: boolean): Disposable; + /** + * Deactivate the inspector. Blocks until there are no active connections. + */ + function close(): void; + /** + * Return the URL of the active inspector, or `undefined` if there is none. + * + * ```console + * $ node --inspect -p 'inspector.url()' + * Debugger listening on ws://127.0.0.1:9229/166e272e-7a30-4d09-97ce-f1c012b43c34 + * For help, see: https://nodejs.org/en/docs/inspector + * ws://127.0.0.1:9229/166e272e-7a30-4d09-97ce-f1c012b43c34 + * + * $ node --inspect=localhost:3000 -p 'inspector.url()' + * Debugger listening on ws://localhost:3000/51cf8d0e-3c36-4c59-8efd-54519839e56a + * For help, see: https://nodejs.org/en/docs/inspector + * ws://localhost:3000/51cf8d0e-3c36-4c59-8efd-54519839e56a + * + * $ node -p 'inspector.url()' + * undefined + * ``` + */ + function url(): string | undefined; + /** + * Blocks until a client (existing or connected later) has sent `Runtime.runIfWaitingForDebugger` command. + * + * An exception will be thrown if there is no active inspector. + * @since v12.7.0 + */ + function waitForDebugger(): void; + // These methods are exposed by the V8 inspector console API (inspector/v8-console.h). + // The method signatures differ from those of the Node.js console, and are deliberately + // typed permissively. + interface InspectorConsole { + debug(...data: any[]): void; + error(...data: any[]): void; + info(...data: any[]): void; + log(...data: any[]): void; + warn(...data: any[]): void; + dir(...data: any[]): void; + dirxml(...data: any[]): void; + table(...data: any[]): void; + trace(...data: any[]): void; + group(...data: any[]): void; + groupCollapsed(...data: any[]): void; + groupEnd(...data: any[]): void; + clear(...data: any[]): void; + count(label?: any): void; + countReset(label?: any): void; + assert(value?: any, ...data: any[]): void; + profile(label?: any): void; + profileEnd(label?: any): void; + time(label?: any): void; + timeLog(label?: any): void; + timeStamp(label?: any): void; + } + /** + * An object to send messages to the remote inspector console. + * @since v11.0.0 + */ + const console: InspectorConsole; + // DevTools protocol event broadcast methods + namespace Network { + /** + * This feature is only available with the `--experimental-network-inspection` flag enabled. + * + * Broadcasts the `Network.requestWillBeSent` event to connected frontends. This event indicates that + * the application is about to send an HTTP request. + * @since v22.6.0 + */ + function requestWillBeSent(params: RequestWillBeSentEventDataType): void; + /** + * This feature is only available with the `--experimental-network-inspection` flag enabled. + * + * Broadcasts the `Network.dataReceived` event to connected frontends, or buffers the data if + * `Network.streamResourceContent` command was not invoked for the given request yet. + * + * Also enables `Network.getResponseBody` command to retrieve the response data. + * @since v24.2.0 + */ + function dataReceived(params: DataReceivedEventDataType): void; + /** + * This feature is only available with the `--experimental-network-inspection` flag enabled. + * + * Enables `Network.getRequestPostData` command to retrieve the request data. + * @since v24.3.0 + */ + function dataSent(params: unknown): void; + /** + * This feature is only available with the `--experimental-network-inspection` flag enabled. + * + * Broadcasts the `Network.responseReceived` event to connected frontends. This event indicates that + * HTTP response is available. + * @since v22.6.0 + */ + function responseReceived(params: ResponseReceivedEventDataType): void; + /** + * This feature is only available with the `--experimental-network-inspection` flag enabled. + * + * Broadcasts the `Network.loadingFinished` event to connected frontends. This event indicates that + * HTTP request has finished loading. + * @since v22.6.0 + */ + function loadingFinished(params: LoadingFinishedEventDataType): void; + /** + * This feature is only available with the `--experimental-network-inspection` flag enabled. + * + * Broadcasts the `Network.loadingFailed` event to connected frontends. This event indicates that + * HTTP request has failed to load. + * @since v22.7.0 + */ + function loadingFailed(params: LoadingFailedEventDataType): void; + /** + * This feature is only available with the `--experimental-network-inspection` flag enabled. + * + * Broadcasts the `Network.webSocketCreated` event to connected frontends. This event indicates that + * a WebSocket connection has been initiated. + * @since v24.7.0 + */ + function webSocketCreated(params: WebSocketCreatedEventDataType): void; + /** + * This feature is only available with the `--experimental-network-inspection` flag enabled. + * + * Broadcasts the `Network.webSocketHandshakeResponseReceived` event to connected frontends. + * This event indicates that the WebSocket handshake response has been received. + * @since v24.7.0 + */ + function webSocketHandshakeResponseReceived(params: WebSocketHandshakeResponseReceivedEventDataType): void; + /** + * This feature is only available with the `--experimental-network-inspection` flag enabled. + * + * Broadcasts the `Network.webSocketClosed` event to connected frontends. + * This event indicates that a WebSocket connection has been closed. + * @since v24.7.0 + */ + function webSocketClosed(params: WebSocketClosedEventDataType): void; + } + namespace NetworkResources { + /** + * This feature is only available with the `--experimental-inspector-network-resource` flag enabled. + * + * The inspector.NetworkResources.put method is used to provide a response for a loadNetworkResource + * request issued via the Chrome DevTools Protocol (CDP). + * This is typically triggered when a source map is specified by URL, and a DevTools frontend—such as + * Chrome—requests the resource to retrieve the source map. + * + * This method allows developers to predefine the resource content to be served in response to such CDP requests. + * + * ```js + * const inspector = require('node:inspector'); + * // By preemptively calling put to register the resource, a source map can be resolved when + * // a loadNetworkResource request is made from the frontend. + * async function setNetworkResources() { + * const mapUrl = 'http://localhost:3000/dist/app.js.map'; + * const tsUrl = 'http://localhost:3000/src/app.ts'; + * const distAppJsMap = await fetch(mapUrl).then((res) => res.text()); + * const srcAppTs = await fetch(tsUrl).then((res) => res.text()); + * inspector.NetworkResources.put(mapUrl, distAppJsMap); + * inspector.NetworkResources.put(tsUrl, srcAppTs); + * }; + * setNetworkResources().then(() => { + * require('./dist/app'); + * }); + * ``` + * + * For more details, see the official CDP documentation: [Network.loadNetworkResource](https://chromedevtools.github.io/devtools-protocol/tot/Network/#method-loadNetworkResource) + * @since v24.5.0 + * @experimental + */ + function put(url: string, data: string): void; + } +} +declare module "inspector" { + export * from "node:inspector"; +} diff --git a/server/node_modules/@types/node/inspector.generated.d.ts b/server/node_modules/@types/node/inspector.generated.d.ts new file mode 100644 index 0000000..84c482d --- /dev/null +++ b/server/node_modules/@types/node/inspector.generated.d.ts @@ -0,0 +1,4226 @@ +// These definitions are automatically generated by the generate-inspector script. +// Do not edit this file directly. +// See scripts/generate-inspector/README.md for information on how to update the protocol definitions. +// Changes to the module itself should be added to the generator template (scripts/generate-inspector/inspector.d.ts.template). + +declare module "node:inspector" { + interface InspectorNotification<T> { + method: string; + params: T; + } + namespace Schema { + /** + * Description of the protocol domain. + */ + interface Domain { + /** + * Domain name. + */ + name: string; + /** + * Domain version. + */ + version: string; + } + interface GetDomainsReturnType { + /** + * List of supported domains. + */ + domains: Domain[]; + } + } + namespace Runtime { + /** + * Unique script identifier. + */ + type ScriptId = string; + /** + * Unique object identifier. + */ + type RemoteObjectId = string; + /** + * Primitive value which cannot be JSON-stringified. + */ + type UnserializableValue = string; + /** + * Mirror object referencing original JavaScript object. + */ + interface RemoteObject { + /** + * Object type. + */ + type: string; + /** + * Object subtype hint. Specified for <code>object</code> type values only. + */ + subtype?: string | undefined; + /** + * Object class (constructor) name. Specified for <code>object</code> type values only. + */ + className?: string | undefined; + /** + * Remote object value in case of primitive values or JSON values (if it was requested). + */ + value?: any; + /** + * Primitive value which can not be JSON-stringified does not have <code>value</code>, but gets this property. + */ + unserializableValue?: UnserializableValue | undefined; + /** + * String representation of the object. + */ + description?: string | undefined; + /** + * Unique object identifier (for non-primitive values). + */ + objectId?: RemoteObjectId | undefined; + /** + * Preview containing abbreviated property values. Specified for <code>object</code> type values only. + * @experimental + */ + preview?: ObjectPreview | undefined; + /** + * @experimental + */ + customPreview?: CustomPreview | undefined; + } + /** + * @experimental + */ + interface CustomPreview { + header: string; + hasBody: boolean; + formatterObjectId: RemoteObjectId; + bindRemoteObjectFunctionId: RemoteObjectId; + configObjectId?: RemoteObjectId | undefined; + } + /** + * Object containing abbreviated remote object value. + * @experimental + */ + interface ObjectPreview { + /** + * Object type. + */ + type: string; + /** + * Object subtype hint. Specified for <code>object</code> type values only. + */ + subtype?: string | undefined; + /** + * String representation of the object. + */ + description?: string | undefined; + /** + * True iff some of the properties or entries of the original object did not fit. + */ + overflow: boolean; + /** + * List of the properties. + */ + properties: PropertyPreview[]; + /** + * List of the entries. Specified for <code>map</code> and <code>set</code> subtype values only. + */ + entries?: EntryPreview[] | undefined; + } + /** + * @experimental + */ + interface PropertyPreview { + /** + * Property name. + */ + name: string; + /** + * Object type. Accessor means that the property itself is an accessor property. + */ + type: string; + /** + * User-friendly property value string. + */ + value?: string | undefined; + /** + * Nested value preview. + */ + valuePreview?: ObjectPreview | undefined; + /** + * Object subtype hint. Specified for <code>object</code> type values only. + */ + subtype?: string | undefined; + } + /** + * @experimental + */ + interface EntryPreview { + /** + * Preview of the key. Specified for map-like collection entries. + */ + key?: ObjectPreview | undefined; + /** + * Preview of the value. + */ + value: ObjectPreview; + } + /** + * Object property descriptor. + */ + interface PropertyDescriptor { + /** + * Property name or symbol description. + */ + name: string; + /** + * The value associated with the property. + */ + value?: RemoteObject | undefined; + /** + * True if the value associated with the property may be changed (data descriptors only). + */ + writable?: boolean | undefined; + /** + * A function which serves as a getter for the property, or <code>undefined</code> if there is no getter (accessor descriptors only). + */ + get?: RemoteObject | undefined; + /** + * A function which serves as a setter for the property, or <code>undefined</code> if there is no setter (accessor descriptors only). + */ + set?: RemoteObject | undefined; + /** + * True if the type of this property descriptor may be changed and if the property may be deleted from the corresponding object. + */ + configurable: boolean; + /** + * True if this property shows up during enumeration of the properties on the corresponding object. + */ + enumerable: boolean; + /** + * True if the result was thrown during the evaluation. + */ + wasThrown?: boolean | undefined; + /** + * True if the property is owned for the object. + */ + isOwn?: boolean | undefined; + /** + * Property symbol object, if the property is of the <code>symbol</code> type. + */ + symbol?: RemoteObject | undefined; + } + /** + * Object internal property descriptor. This property isn't normally visible in JavaScript code. + */ + interface InternalPropertyDescriptor { + /** + * Conventional property name. + */ + name: string; + /** + * The value associated with the property. + */ + value?: RemoteObject | undefined; + } + /** + * Represents function call argument. Either remote object id <code>objectId</code>, primitive <code>value</code>, unserializable primitive value or neither of (for undefined) them should be specified. + */ + interface CallArgument { + /** + * Primitive value or serializable javascript object. + */ + value?: any; + /** + * Primitive value which can not be JSON-stringified. + */ + unserializableValue?: UnserializableValue | undefined; + /** + * Remote object handle. + */ + objectId?: RemoteObjectId | undefined; + } + /** + * Id of an execution context. + */ + type ExecutionContextId = number; + /** + * Description of an isolated world. + */ + interface ExecutionContextDescription { + /** + * Unique id of the execution context. It can be used to specify in which execution context script evaluation should be performed. + */ + id: ExecutionContextId; + /** + * Execution context origin. + */ + origin: string; + /** + * Human readable name describing given context. + */ + name: string; + /** + * Embedder-specific auxiliary data. + */ + auxData?: object | undefined; + } + /** + * Detailed information about exception (or error) that was thrown during script compilation or execution. + */ + interface ExceptionDetails { + /** + * Exception id. + */ + exceptionId: number; + /** + * Exception text, which should be used together with exception object when available. + */ + text: string; + /** + * Line number of the exception location (0-based). + */ + lineNumber: number; + /** + * Column number of the exception location (0-based). + */ + columnNumber: number; + /** + * Script ID of the exception location. + */ + scriptId?: ScriptId | undefined; + /** + * URL of the exception location, to be used when the script was not reported. + */ + url?: string | undefined; + /** + * JavaScript stack trace if available. + */ + stackTrace?: StackTrace | undefined; + /** + * Exception object if available. + */ + exception?: RemoteObject | undefined; + /** + * Identifier of the context where exception happened. + */ + executionContextId?: ExecutionContextId | undefined; + } + /** + * Number of milliseconds since epoch. + */ + type Timestamp = number; + /** + * Stack entry for runtime errors and assertions. + */ + interface CallFrame { + /** + * JavaScript function name. + */ + functionName: string; + /** + * JavaScript script id. + */ + scriptId: ScriptId; + /** + * JavaScript script name or url. + */ + url: string; + /** + * JavaScript script line number (0-based). + */ + lineNumber: number; + /** + * JavaScript script column number (0-based). + */ + columnNumber: number; + } + /** + * Call frames for assertions or error messages. + */ + interface StackTrace { + /** + * String label of this stack trace. For async traces this may be a name of the function that initiated the async call. + */ + description?: string | undefined; + /** + * JavaScript function name. + */ + callFrames: CallFrame[]; + /** + * Asynchronous JavaScript stack trace that preceded this stack, if available. + */ + parent?: StackTrace | undefined; + /** + * Asynchronous JavaScript stack trace that preceded this stack, if available. + * @experimental + */ + parentId?: StackTraceId | undefined; + } + /** + * Unique identifier of current debugger. + * @experimental + */ + type UniqueDebuggerId = string; + /** + * If <code>debuggerId</code> is set stack trace comes from another debugger and can be resolved there. This allows to track cross-debugger calls. See <code>Runtime.StackTrace</code> and <code>Debugger.paused</code> for usages. + * @experimental + */ + interface StackTraceId { + id: string; + debuggerId?: UniqueDebuggerId | undefined; + } + interface EvaluateParameterType { + /** + * Expression to evaluate. + */ + expression: string; + /** + * Symbolic group name that can be used to release multiple objects. + */ + objectGroup?: string | undefined; + /** + * Determines whether Command Line API should be available during the evaluation. + */ + includeCommandLineAPI?: boolean | undefined; + /** + * In silent mode exceptions thrown during evaluation are not reported and do not pause execution. Overrides <code>setPauseOnException</code> state. + */ + silent?: boolean | undefined; + /** + * Specifies in which execution context to perform evaluation. If the parameter is omitted the evaluation will be performed in the context of the inspected page. + */ + contextId?: ExecutionContextId | undefined; + /** + * Whether the result is expected to be a JSON object that should be sent by value. + */ + returnByValue?: boolean | undefined; + /** + * Whether preview should be generated for the result. + * @experimental + */ + generatePreview?: boolean | undefined; + /** + * Whether execution should be treated as initiated by user in the UI. + */ + userGesture?: boolean | undefined; + /** + * Whether execution should <code>await</code> for resulting value and return once awaited promise is resolved. + */ + awaitPromise?: boolean | undefined; + } + interface AwaitPromiseParameterType { + /** + * Identifier of the promise. + */ + promiseObjectId: RemoteObjectId; + /** + * Whether the result is expected to be a JSON object that should be sent by value. + */ + returnByValue?: boolean | undefined; + /** + * Whether preview should be generated for the result. + */ + generatePreview?: boolean | undefined; + } + interface CallFunctionOnParameterType { + /** + * Declaration of the function to call. + */ + functionDeclaration: string; + /** + * Identifier of the object to call function on. Either objectId or executionContextId should be specified. + */ + objectId?: RemoteObjectId | undefined; + /** + * Call arguments. All call arguments must belong to the same JavaScript world as the target object. + */ + arguments?: CallArgument[] | undefined; + /** + * In silent mode exceptions thrown during evaluation are not reported and do not pause execution. Overrides <code>setPauseOnException</code> state. + */ + silent?: boolean | undefined; + /** + * Whether the result is expected to be a JSON object which should be sent by value. + */ + returnByValue?: boolean | undefined; + /** + * Whether preview should be generated for the result. + * @experimental + */ + generatePreview?: boolean | undefined; + /** + * Whether execution should be treated as initiated by user in the UI. + */ + userGesture?: boolean | undefined; + /** + * Whether execution should <code>await</code> for resulting value and return once awaited promise is resolved. + */ + awaitPromise?: boolean | undefined; + /** + * Specifies execution context which global object will be used to call function on. Either executionContextId or objectId should be specified. + */ + executionContextId?: ExecutionContextId | undefined; + /** + * Symbolic group name that can be used to release multiple objects. If objectGroup is not specified and objectId is, objectGroup will be inherited from object. + */ + objectGroup?: string | undefined; + } + interface GetPropertiesParameterType { + /** + * Identifier of the object to return properties for. + */ + objectId: RemoteObjectId; + /** + * If true, returns properties belonging only to the element itself, not to its prototype chain. + */ + ownProperties?: boolean | undefined; + /** + * If true, returns accessor properties (with getter/setter) only; internal properties are not returned either. + * @experimental + */ + accessorPropertiesOnly?: boolean | undefined; + /** + * Whether preview should be generated for the results. + * @experimental + */ + generatePreview?: boolean | undefined; + } + interface ReleaseObjectParameterType { + /** + * Identifier of the object to release. + */ + objectId: RemoteObjectId; + } + interface ReleaseObjectGroupParameterType { + /** + * Symbolic object group name. + */ + objectGroup: string; + } + interface SetCustomObjectFormatterEnabledParameterType { + enabled: boolean; + } + interface CompileScriptParameterType { + /** + * Expression to compile. + */ + expression: string; + /** + * Source url to be set for the script. + */ + sourceURL: string; + /** + * Specifies whether the compiled script should be persisted. + */ + persistScript: boolean; + /** + * Specifies in which execution context to perform script run. If the parameter is omitted the evaluation will be performed in the context of the inspected page. + */ + executionContextId?: ExecutionContextId | undefined; + } + interface RunScriptParameterType { + /** + * Id of the script to run. + */ + scriptId: ScriptId; + /** + * Specifies in which execution context to perform script run. If the parameter is omitted the evaluation will be performed in the context of the inspected page. + */ + executionContextId?: ExecutionContextId | undefined; + /** + * Symbolic group name that can be used to release multiple objects. + */ + objectGroup?: string | undefined; + /** + * In silent mode exceptions thrown during evaluation are not reported and do not pause execution. Overrides <code>setPauseOnException</code> state. + */ + silent?: boolean | undefined; + /** + * Determines whether Command Line API should be available during the evaluation. + */ + includeCommandLineAPI?: boolean | undefined; + /** + * Whether the result is expected to be a JSON object which should be sent by value. + */ + returnByValue?: boolean | undefined; + /** + * Whether preview should be generated for the result. + */ + generatePreview?: boolean | undefined; + /** + * Whether execution should <code>await</code> for resulting value and return once awaited promise is resolved. + */ + awaitPromise?: boolean | undefined; + } + interface QueryObjectsParameterType { + /** + * Identifier of the prototype to return objects for. + */ + prototypeObjectId: RemoteObjectId; + } + interface GlobalLexicalScopeNamesParameterType { + /** + * Specifies in which execution context to lookup global scope variables. + */ + executionContextId?: ExecutionContextId | undefined; + } + interface EvaluateReturnType { + /** + * Evaluation result. + */ + result: RemoteObject; + /** + * Exception details. + */ + exceptionDetails?: ExceptionDetails | undefined; + } + interface AwaitPromiseReturnType { + /** + * Promise result. Will contain rejected value if promise was rejected. + */ + result: RemoteObject; + /** + * Exception details if stack strace is available. + */ + exceptionDetails?: ExceptionDetails | undefined; + } + interface CallFunctionOnReturnType { + /** + * Call result. + */ + result: RemoteObject; + /** + * Exception details. + */ + exceptionDetails?: ExceptionDetails | undefined; + } + interface GetPropertiesReturnType { + /** + * Object properties. + */ + result: PropertyDescriptor[]; + /** + * Internal object properties (only of the element itself). + */ + internalProperties?: InternalPropertyDescriptor[] | undefined; + /** + * Exception details. + */ + exceptionDetails?: ExceptionDetails | undefined; + } + interface CompileScriptReturnType { + /** + * Id of the script. + */ + scriptId?: ScriptId | undefined; + /** + * Exception details. + */ + exceptionDetails?: ExceptionDetails | undefined; + } + interface RunScriptReturnType { + /** + * Run result. + */ + result: RemoteObject; + /** + * Exception details. + */ + exceptionDetails?: ExceptionDetails | undefined; + } + interface QueryObjectsReturnType { + /** + * Array with objects. + */ + objects: RemoteObject; + } + interface GlobalLexicalScopeNamesReturnType { + names: string[]; + } + interface ExecutionContextCreatedEventDataType { + /** + * A newly created execution context. + */ + context: ExecutionContextDescription; + } + interface ExecutionContextDestroyedEventDataType { + /** + * Id of the destroyed context + */ + executionContextId: ExecutionContextId; + } + interface ExceptionThrownEventDataType { + /** + * Timestamp of the exception. + */ + timestamp: Timestamp; + exceptionDetails: ExceptionDetails; + } + interface ExceptionRevokedEventDataType { + /** + * Reason describing why exception was revoked. + */ + reason: string; + /** + * The id of revoked exception, as reported in <code>exceptionThrown</code>. + */ + exceptionId: number; + } + interface ConsoleAPICalledEventDataType { + /** + * Type of the call. + */ + type: string; + /** + * Call arguments. + */ + args: RemoteObject[]; + /** + * Identifier of the context where the call was made. + */ + executionContextId: ExecutionContextId; + /** + * Call timestamp. + */ + timestamp: Timestamp; + /** + * Stack trace captured when the call was made. + */ + stackTrace?: StackTrace | undefined; + /** + * Console context descriptor for calls on non-default console context (not console.*): 'anonymous#unique-logger-id' for call on unnamed context, 'name#unique-logger-id' for call on named context. + * @experimental + */ + context?: string | undefined; + } + interface InspectRequestedEventDataType { + object: RemoteObject; + hints: object; + } + } + namespace Debugger { + /** + * Breakpoint identifier. + */ + type BreakpointId = string; + /** + * Call frame identifier. + */ + type CallFrameId = string; + /** + * Location in the source code. + */ + interface Location { + /** + * Script identifier as reported in the <code>Debugger.scriptParsed</code>. + */ + scriptId: Runtime.ScriptId; + /** + * Line number in the script (0-based). + */ + lineNumber: number; + /** + * Column number in the script (0-based). + */ + columnNumber?: number | undefined; + } + /** + * Location in the source code. + * @experimental + */ + interface ScriptPosition { + lineNumber: number; + columnNumber: number; + } + /** + * JavaScript call frame. Array of call frames form the call stack. + */ + interface CallFrame { + /** + * Call frame identifier. This identifier is only valid while the virtual machine is paused. + */ + callFrameId: CallFrameId; + /** + * Name of the JavaScript function called on this call frame. + */ + functionName: string; + /** + * Location in the source code. + */ + functionLocation?: Location | undefined; + /** + * Location in the source code. + */ + location: Location; + /** + * JavaScript script name or url. + */ + url: string; + /** + * Scope chain for this call frame. + */ + scopeChain: Scope[]; + /** + * <code>this</code> object for this call frame. + */ + this: Runtime.RemoteObject; + /** + * The value being returned, if the function is at return point. + */ + returnValue?: Runtime.RemoteObject | undefined; + } + /** + * Scope description. + */ + interface Scope { + /** + * Scope type. + */ + type: string; + /** + * Object representing the scope. For <code>global</code> and <code>with</code> scopes it represents the actual object; for the rest of the scopes, it is artificial transient object enumerating scope variables as its properties. + */ + object: Runtime.RemoteObject; + name?: string | undefined; + /** + * Location in the source code where scope starts + */ + startLocation?: Location | undefined; + /** + * Location in the source code where scope ends + */ + endLocation?: Location | undefined; + } + /** + * Search match for resource. + */ + interface SearchMatch { + /** + * Line number in resource content. + */ + lineNumber: number; + /** + * Line with match content. + */ + lineContent: string; + } + interface BreakLocation { + /** + * Script identifier as reported in the <code>Debugger.scriptParsed</code>. + */ + scriptId: Runtime.ScriptId; + /** + * Line number in the script (0-based). + */ + lineNumber: number; + /** + * Column number in the script (0-based). + */ + columnNumber?: number | undefined; + type?: string | undefined; + } + interface SetBreakpointsActiveParameterType { + /** + * New value for breakpoints active state. + */ + active: boolean; + } + interface SetSkipAllPausesParameterType { + /** + * New value for skip pauses state. + */ + skip: boolean; + } + interface SetBreakpointByUrlParameterType { + /** + * Line number to set breakpoint at. + */ + lineNumber: number; + /** + * URL of the resources to set breakpoint on. + */ + url?: string | undefined; + /** + * Regex pattern for the URLs of the resources to set breakpoints on. Either <code>url</code> or <code>urlRegex</code> must be specified. + */ + urlRegex?: string | undefined; + /** + * Script hash of the resources to set breakpoint on. + */ + scriptHash?: string | undefined; + /** + * Offset in the line to set breakpoint at. + */ + columnNumber?: number | undefined; + /** + * Expression to use as a breakpoint condition. When specified, debugger will only stop on the breakpoint if this expression evaluates to true. + */ + condition?: string | undefined; + } + interface SetBreakpointParameterType { + /** + * Location to set breakpoint in. + */ + location: Location; + /** + * Expression to use as a breakpoint condition. When specified, debugger will only stop on the breakpoint if this expression evaluates to true. + */ + condition?: string | undefined; + } + interface RemoveBreakpointParameterType { + breakpointId: BreakpointId; + } + interface GetPossibleBreakpointsParameterType { + /** + * Start of range to search possible breakpoint locations in. + */ + start: Location; + /** + * End of range to search possible breakpoint locations in (excluding). When not specified, end of scripts is used as end of range. + */ + end?: Location | undefined; + /** + * Only consider locations which are in the same (non-nested) function as start. + */ + restrictToFunction?: boolean | undefined; + } + interface ContinueToLocationParameterType { + /** + * Location to continue to. + */ + location: Location; + targetCallFrames?: string | undefined; + } + interface PauseOnAsyncCallParameterType { + /** + * Debugger will pause when async call with given stack trace is started. + */ + parentStackTraceId: Runtime.StackTraceId; + } + interface StepIntoParameterType { + /** + * Debugger will issue additional Debugger.paused notification if any async task is scheduled before next pause. + * @experimental + */ + breakOnAsyncCall?: boolean | undefined; + } + interface GetStackTraceParameterType { + stackTraceId: Runtime.StackTraceId; + } + interface SearchInContentParameterType { + /** + * Id of the script to search in. + */ + scriptId: Runtime.ScriptId; + /** + * String to search for. + */ + query: string; + /** + * If true, search is case sensitive. + */ + caseSensitive?: boolean | undefined; + /** + * If true, treats string parameter as regex. + */ + isRegex?: boolean | undefined; + } + interface SetScriptSourceParameterType { + /** + * Id of the script to edit. + */ + scriptId: Runtime.ScriptId; + /** + * New content of the script. + */ + scriptSource: string; + /** + * If true the change will not actually be applied. Dry run may be used to get result description without actually modifying the code. + */ + dryRun?: boolean | undefined; + } + interface RestartFrameParameterType { + /** + * Call frame identifier to evaluate on. + */ + callFrameId: CallFrameId; + } + interface GetScriptSourceParameterType { + /** + * Id of the script to get source for. + */ + scriptId: Runtime.ScriptId; + } + interface SetPauseOnExceptionsParameterType { + /** + * Pause on exceptions mode. + */ + state: string; + } + interface EvaluateOnCallFrameParameterType { + /** + * Call frame identifier to evaluate on. + */ + callFrameId: CallFrameId; + /** + * Expression to evaluate. + */ + expression: string; + /** + * String object group name to put result into (allows rapid releasing resulting object handles using <code>releaseObjectGroup</code>). + */ + objectGroup?: string | undefined; + /** + * Specifies whether command line API should be available to the evaluated expression, defaults to false. + */ + includeCommandLineAPI?: boolean | undefined; + /** + * In silent mode exceptions thrown during evaluation are not reported and do not pause execution. Overrides <code>setPauseOnException</code> state. + */ + silent?: boolean | undefined; + /** + * Whether the result is expected to be a JSON object that should be sent by value. + */ + returnByValue?: boolean | undefined; + /** + * Whether preview should be generated for the result. + * @experimental + */ + generatePreview?: boolean | undefined; + /** + * Whether to throw an exception if side effect cannot be ruled out during evaluation. + */ + throwOnSideEffect?: boolean | undefined; + } + interface SetVariableValueParameterType { + /** + * 0-based number of scope as was listed in scope chain. Only 'local', 'closure' and 'catch' scope types are allowed. Other scopes could be manipulated manually. + */ + scopeNumber: number; + /** + * Variable name. + */ + variableName: string; + /** + * New variable value. + */ + newValue: Runtime.CallArgument; + /** + * Id of callframe that holds variable. + */ + callFrameId: CallFrameId; + } + interface SetReturnValueParameterType { + /** + * New return value. + */ + newValue: Runtime.CallArgument; + } + interface SetAsyncCallStackDepthParameterType { + /** + * Maximum depth of async call stacks. Setting to <code>0</code> will effectively disable collecting async call stacks (default). + */ + maxDepth: number; + } + interface SetBlackboxPatternsParameterType { + /** + * Array of regexps that will be used to check script url for blackbox state. + */ + patterns: string[]; + } + interface SetBlackboxedRangesParameterType { + /** + * Id of the script. + */ + scriptId: Runtime.ScriptId; + positions: ScriptPosition[]; + } + interface EnableReturnType { + /** + * Unique identifier of the debugger. + * @experimental + */ + debuggerId: Runtime.UniqueDebuggerId; + } + interface SetBreakpointByUrlReturnType { + /** + * Id of the created breakpoint for further reference. + */ + breakpointId: BreakpointId; + /** + * List of the locations this breakpoint resolved into upon addition. + */ + locations: Location[]; + } + interface SetBreakpointReturnType { + /** + * Id of the created breakpoint for further reference. + */ + breakpointId: BreakpointId; + /** + * Location this breakpoint resolved into. + */ + actualLocation: Location; + } + interface GetPossibleBreakpointsReturnType { + /** + * List of the possible breakpoint locations. + */ + locations: BreakLocation[]; + } + interface GetStackTraceReturnType { + stackTrace: Runtime.StackTrace; + } + interface SearchInContentReturnType { + /** + * List of search matches. + */ + result: SearchMatch[]; + } + interface SetScriptSourceReturnType { + /** + * New stack trace in case editing has happened while VM was stopped. + */ + callFrames?: CallFrame[] | undefined; + /** + * Whether current call stack was modified after applying the changes. + */ + stackChanged?: boolean | undefined; + /** + * Async stack trace, if any. + */ + asyncStackTrace?: Runtime.StackTrace | undefined; + /** + * Async stack trace, if any. + * @experimental + */ + asyncStackTraceId?: Runtime.StackTraceId | undefined; + /** + * Exception details if any. + */ + exceptionDetails?: Runtime.ExceptionDetails | undefined; + } + interface RestartFrameReturnType { + /** + * New stack trace. + */ + callFrames: CallFrame[]; + /** + * Async stack trace, if any. + */ + asyncStackTrace?: Runtime.StackTrace | undefined; + /** + * Async stack trace, if any. + * @experimental + */ + asyncStackTraceId?: Runtime.StackTraceId | undefined; + } + interface GetScriptSourceReturnType { + /** + * Script source. + */ + scriptSource: string; + } + interface EvaluateOnCallFrameReturnType { + /** + * Object wrapper for the evaluation result. + */ + result: Runtime.RemoteObject; + /** + * Exception details. + */ + exceptionDetails?: Runtime.ExceptionDetails | undefined; + } + interface ScriptParsedEventDataType { + /** + * Identifier of the script parsed. + */ + scriptId: Runtime.ScriptId; + /** + * URL or name of the script parsed (if any). + */ + url: string; + /** + * Line offset of the script within the resource with given URL (for script tags). + */ + startLine: number; + /** + * Column offset of the script within the resource with given URL. + */ + startColumn: number; + /** + * Last line of the script. + */ + endLine: number; + /** + * Length of the last line of the script. + */ + endColumn: number; + /** + * Specifies script creation context. + */ + executionContextId: Runtime.ExecutionContextId; + /** + * Content hash of the script. + */ + hash: string; + /** + * Embedder-specific auxiliary data. + */ + executionContextAuxData?: object | undefined; + /** + * True, if this script is generated as a result of the live edit operation. + * @experimental + */ + isLiveEdit?: boolean | undefined; + /** + * URL of source map associated with script (if any). + */ + sourceMapURL?: string | undefined; + /** + * True, if this script has sourceURL. + */ + hasSourceURL?: boolean | undefined; + /** + * True, if this script is ES6 module. + */ + isModule?: boolean | undefined; + /** + * This script length. + */ + length?: number | undefined; + /** + * JavaScript top stack frame of where the script parsed event was triggered if available. + * @experimental + */ + stackTrace?: Runtime.StackTrace | undefined; + } + interface ScriptFailedToParseEventDataType { + /** + * Identifier of the script parsed. + */ + scriptId: Runtime.ScriptId; + /** + * URL or name of the script parsed (if any). + */ + url: string; + /** + * Line offset of the script within the resource with given URL (for script tags). + */ + startLine: number; + /** + * Column offset of the script within the resource with given URL. + */ + startColumn: number; + /** + * Last line of the script. + */ + endLine: number; + /** + * Length of the last line of the script. + */ + endColumn: number; + /** + * Specifies script creation context. + */ + executionContextId: Runtime.ExecutionContextId; + /** + * Content hash of the script. + */ + hash: string; + /** + * Embedder-specific auxiliary data. + */ + executionContextAuxData?: object | undefined; + /** + * URL of source map associated with script (if any). + */ + sourceMapURL?: string | undefined; + /** + * True, if this script has sourceURL. + */ + hasSourceURL?: boolean | undefined; + /** + * True, if this script is ES6 module. + */ + isModule?: boolean | undefined; + /** + * This script length. + */ + length?: number | undefined; + /** + * JavaScript top stack frame of where the script parsed event was triggered if available. + * @experimental + */ + stackTrace?: Runtime.StackTrace | undefined; + } + interface BreakpointResolvedEventDataType { + /** + * Breakpoint unique identifier. + */ + breakpointId: BreakpointId; + /** + * Actual breakpoint location. + */ + location: Location; + } + interface PausedEventDataType { + /** + * Call stack the virtual machine stopped on. + */ + callFrames: CallFrame[]; + /** + * Pause reason. + */ + reason: string; + /** + * Object containing break-specific auxiliary properties. + */ + data?: object | undefined; + /** + * Hit breakpoints IDs + */ + hitBreakpoints?: string[] | undefined; + /** + * Async stack trace, if any. + */ + asyncStackTrace?: Runtime.StackTrace | undefined; + /** + * Async stack trace, if any. + * @experimental + */ + asyncStackTraceId?: Runtime.StackTraceId | undefined; + /** + * Just scheduled async call will have this stack trace as parent stack during async execution. This field is available only after <code>Debugger.stepInto</code> call with <code>breakOnAsynCall</code> flag. + * @experimental + */ + asyncCallStackTraceId?: Runtime.StackTraceId | undefined; + } + } + namespace Console { + /** + * Console message. + */ + interface ConsoleMessage { + /** + * Message source. + */ + source: string; + /** + * Message severity. + */ + level: string; + /** + * Message text. + */ + text: string; + /** + * URL of the message origin. + */ + url?: string | undefined; + /** + * Line number in the resource that generated this message (1-based). + */ + line?: number | undefined; + /** + * Column number in the resource that generated this message (1-based). + */ + column?: number | undefined; + } + interface MessageAddedEventDataType { + /** + * Console message that has been added. + */ + message: ConsoleMessage; + } + } + namespace Profiler { + /** + * Profile node. Holds callsite information, execution statistics and child nodes. + */ + interface ProfileNode { + /** + * Unique id of the node. + */ + id: number; + /** + * Function location. + */ + callFrame: Runtime.CallFrame; + /** + * Number of samples where this node was on top of the call stack. + */ + hitCount?: number | undefined; + /** + * Child node ids. + */ + children?: number[] | undefined; + /** + * The reason of being not optimized. The function may be deoptimized or marked as don't optimize. + */ + deoptReason?: string | undefined; + /** + * An array of source position ticks. + */ + positionTicks?: PositionTickInfo[] | undefined; + } + /** + * Profile. + */ + interface Profile { + /** + * The list of profile nodes. First item is the root node. + */ + nodes: ProfileNode[]; + /** + * Profiling start timestamp in microseconds. + */ + startTime: number; + /** + * Profiling end timestamp in microseconds. + */ + endTime: number; + /** + * Ids of samples top nodes. + */ + samples?: number[] | undefined; + /** + * Time intervals between adjacent samples in microseconds. The first delta is relative to the profile startTime. + */ + timeDeltas?: number[] | undefined; + } + /** + * Specifies a number of samples attributed to a certain source position. + */ + interface PositionTickInfo { + /** + * Source line number (1-based). + */ + line: number; + /** + * Number of samples attributed to the source line. + */ + ticks: number; + } + /** + * Coverage data for a source range. + */ + interface CoverageRange { + /** + * JavaScript script source offset for the range start. + */ + startOffset: number; + /** + * JavaScript script source offset for the range end. + */ + endOffset: number; + /** + * Collected execution count of the source range. + */ + count: number; + } + /** + * Coverage data for a JavaScript function. + */ + interface FunctionCoverage { + /** + * JavaScript function name. + */ + functionName: string; + /** + * Source ranges inside the function with coverage data. + */ + ranges: CoverageRange[]; + /** + * Whether coverage data for this function has block granularity. + */ + isBlockCoverage: boolean; + } + /** + * Coverage data for a JavaScript script. + */ + interface ScriptCoverage { + /** + * JavaScript script id. + */ + scriptId: Runtime.ScriptId; + /** + * JavaScript script name or url. + */ + url: string; + /** + * Functions contained in the script that has coverage data. + */ + functions: FunctionCoverage[]; + } + interface SetSamplingIntervalParameterType { + /** + * New sampling interval in microseconds. + */ + interval: number; + } + interface StartPreciseCoverageParameterType { + /** + * Collect accurate call counts beyond simple 'covered' or 'not covered'. + */ + callCount?: boolean | undefined; + /** + * Collect block-based coverage. + */ + detailed?: boolean | undefined; + } + interface StopReturnType { + /** + * Recorded profile. + */ + profile: Profile; + } + interface TakePreciseCoverageReturnType { + /** + * Coverage data for the current isolate. + */ + result: ScriptCoverage[]; + } + interface GetBestEffortCoverageReturnType { + /** + * Coverage data for the current isolate. + */ + result: ScriptCoverage[]; + } + interface ConsoleProfileStartedEventDataType { + id: string; + /** + * Location of console.profile(). + */ + location: Debugger.Location; + /** + * Profile title passed as an argument to console.profile(). + */ + title?: string | undefined; + } + interface ConsoleProfileFinishedEventDataType { + id: string; + /** + * Location of console.profileEnd(). + */ + location: Debugger.Location; + profile: Profile; + /** + * Profile title passed as an argument to console.profile(). + */ + title?: string | undefined; + } + } + namespace HeapProfiler { + /** + * Heap snapshot object id. + */ + type HeapSnapshotObjectId = string; + /** + * Sampling Heap Profile node. Holds callsite information, allocation statistics and child nodes. + */ + interface SamplingHeapProfileNode { + /** + * Function location. + */ + callFrame: Runtime.CallFrame; + /** + * Allocations size in bytes for the node excluding children. + */ + selfSize: number; + /** + * Child nodes. + */ + children: SamplingHeapProfileNode[]; + } + /** + * Profile. + */ + interface SamplingHeapProfile { + head: SamplingHeapProfileNode; + } + interface StartTrackingHeapObjectsParameterType { + trackAllocations?: boolean | undefined; + } + interface StopTrackingHeapObjectsParameterType { + /** + * If true 'reportHeapSnapshotProgress' events will be generated while snapshot is being taken when the tracking is stopped. + */ + reportProgress?: boolean | undefined; + } + interface TakeHeapSnapshotParameterType { + /** + * If true 'reportHeapSnapshotProgress' events will be generated while snapshot is being taken. + */ + reportProgress?: boolean | undefined; + } + interface GetObjectByHeapObjectIdParameterType { + objectId: HeapSnapshotObjectId; + /** + * Symbolic group name that can be used to release multiple objects. + */ + objectGroup?: string | undefined; + } + interface AddInspectedHeapObjectParameterType { + /** + * Heap snapshot object id to be accessible by means of $x command line API. + */ + heapObjectId: HeapSnapshotObjectId; + } + interface GetHeapObjectIdParameterType { + /** + * Identifier of the object to get heap object id for. + */ + objectId: Runtime.RemoteObjectId; + } + interface StartSamplingParameterType { + /** + * Average sample interval in bytes. Poisson distribution is used for the intervals. The default value is 32768 bytes. + */ + samplingInterval?: number | undefined; + } + interface GetObjectByHeapObjectIdReturnType { + /** + * Evaluation result. + */ + result: Runtime.RemoteObject; + } + interface GetHeapObjectIdReturnType { + /** + * Id of the heap snapshot object corresponding to the passed remote object id. + */ + heapSnapshotObjectId: HeapSnapshotObjectId; + } + interface StopSamplingReturnType { + /** + * Recorded sampling heap profile. + */ + profile: SamplingHeapProfile; + } + interface GetSamplingProfileReturnType { + /** + * Return the sampling profile being collected. + */ + profile: SamplingHeapProfile; + } + interface AddHeapSnapshotChunkEventDataType { + chunk: string; + } + interface ReportHeapSnapshotProgressEventDataType { + done: number; + total: number; + finished?: boolean | undefined; + } + interface LastSeenObjectIdEventDataType { + lastSeenObjectId: number; + timestamp: number; + } + interface HeapStatsUpdateEventDataType { + /** + * An array of triplets. Each triplet describes a fragment. The first integer is the fragment index, the second integer is a total count of objects for the fragment, the third integer is a total size of the objects for the fragment. + */ + statsUpdate: number[]; + } + } + namespace NodeTracing { + interface TraceConfig { + /** + * Controls how the trace buffer stores data. + */ + recordMode?: string | undefined; + /** + * Included category filters. + */ + includedCategories: string[]; + } + interface StartParameterType { + traceConfig: TraceConfig; + } + interface GetCategoriesReturnType { + /** + * A list of supported tracing categories. + */ + categories: string[]; + } + interface DataCollectedEventDataType { + value: object[]; + } + } + namespace NodeWorker { + type WorkerID = string; + /** + * Unique identifier of attached debugging session. + */ + type SessionID = string; + interface WorkerInfo { + workerId: WorkerID; + type: string; + title: string; + url: string; + } + interface SendMessageToWorkerParameterType { + message: string; + /** + * Identifier of the session. + */ + sessionId: SessionID; + } + interface EnableParameterType { + /** + * Whether to new workers should be paused until the frontend sends `Runtime.runIfWaitingForDebugger` + * message to run them. + */ + waitForDebuggerOnStart: boolean; + } + interface DetachParameterType { + sessionId: SessionID; + } + interface AttachedToWorkerEventDataType { + /** + * Identifier assigned to the session used to send/receive messages. + */ + sessionId: SessionID; + workerInfo: WorkerInfo; + waitingForDebugger: boolean; + } + interface DetachedFromWorkerEventDataType { + /** + * Detached session identifier. + */ + sessionId: SessionID; + } + interface ReceivedMessageFromWorkerEventDataType { + /** + * Identifier of a session which sends a message. + */ + sessionId: SessionID; + message: string; + } + } + namespace Network { + /** + * Resource type as it was perceived by the rendering engine. + */ + type ResourceType = string; + /** + * Unique request identifier. + */ + type RequestId = string; + /** + * UTC time in seconds, counted from January 1, 1970. + */ + type TimeSinceEpoch = number; + /** + * Monotonically increasing time in seconds since an arbitrary point in the past. + */ + type MonotonicTime = number; + /** + * Information about the request initiator. + */ + interface Initiator { + /** + * Type of this initiator. + */ + type: string; + /** + * Initiator JavaScript stack trace, set for Script only. + * Requires the Debugger domain to be enabled. + */ + stack?: Runtime.StackTrace | undefined; + /** + * Initiator URL, set for Parser type or for Script type (when script is importing module) or for SignedExchange type. + */ + url?: string | undefined; + /** + * Initiator line number, set for Parser type or for Script type (when script is importing + * module) (0-based). + */ + lineNumber?: number | undefined; + /** + * Initiator column number, set for Parser type or for Script type (when script is importing + * module) (0-based). + */ + columnNumber?: number | undefined; + /** + * Set if another request triggered this request (e.g. preflight). + */ + requestId?: RequestId | undefined; + } + /** + * HTTP request data. + */ + interface Request { + url: string; + method: string; + headers: Headers; + hasPostData: boolean; + } + /** + * HTTP response data. + */ + interface Response { + url: string; + status: number; + statusText: string; + headers: Headers; + mimeType: string; + charset: string; + } + /** + * Request / response headers as keys / values of JSON object. + */ + interface Headers { + } + interface LoadNetworkResourcePageResult { + success: boolean; + stream?: IO.StreamHandle | undefined; + } + /** + * WebSocket response data. + */ + interface WebSocketResponse { + /** + * HTTP response status code. + */ + status: number; + /** + * HTTP response status text. + */ + statusText: string; + /** + * HTTP response headers. + */ + headers: Headers; + } + interface GetRequestPostDataParameterType { + /** + * Identifier of the network request to get content for. + */ + requestId: RequestId; + } + interface GetResponseBodyParameterType { + /** + * Identifier of the network request to get content for. + */ + requestId: RequestId; + } + interface StreamResourceContentParameterType { + /** + * Identifier of the request to stream. + */ + requestId: RequestId; + } + interface LoadNetworkResourceParameterType { + /** + * URL of the resource to get content for. + */ + url: string; + } + interface GetRequestPostDataReturnType { + /** + * Request body string, omitting files from multipart requests + */ + postData: string; + } + interface GetResponseBodyReturnType { + /** + * Response body. + */ + body: string; + /** + * True, if content was sent as base64. + */ + base64Encoded: boolean; + } + interface StreamResourceContentReturnType { + /** + * Data that has been buffered until streaming is enabled. + */ + bufferedData: string; + } + interface LoadNetworkResourceReturnType { + resource: LoadNetworkResourcePageResult; + } + interface RequestWillBeSentEventDataType { + /** + * Request identifier. + */ + requestId: RequestId; + /** + * Request data. + */ + request: Request; + /** + * Request initiator. + */ + initiator: Initiator; + /** + * Timestamp. + */ + timestamp: MonotonicTime; + /** + * Timestamp. + */ + wallTime: TimeSinceEpoch; + } + interface ResponseReceivedEventDataType { + /** + * Request identifier. + */ + requestId: RequestId; + /** + * Timestamp. + */ + timestamp: MonotonicTime; + /** + * Resource type. + */ + type: ResourceType; + /** + * Response data. + */ + response: Response; + } + interface LoadingFailedEventDataType { + /** + * Request identifier. + */ + requestId: RequestId; + /** + * Timestamp. + */ + timestamp: MonotonicTime; + /** + * Resource type. + */ + type: ResourceType; + /** + * Error message. + */ + errorText: string; + } + interface LoadingFinishedEventDataType { + /** + * Request identifier. + */ + requestId: RequestId; + /** + * Timestamp. + */ + timestamp: MonotonicTime; + } + interface DataReceivedEventDataType { + /** + * Request identifier. + */ + requestId: RequestId; + /** + * Timestamp. + */ + timestamp: MonotonicTime; + /** + * Data chunk length. + */ + dataLength: number; + /** + * Actual bytes received (might be less than dataLength for compressed encodings). + */ + encodedDataLength: number; + /** + * Data that was received. + * @experimental + */ + data?: string | undefined; + } + interface WebSocketCreatedEventDataType { + /** + * Request identifier. + */ + requestId: RequestId; + /** + * WebSocket request URL. + */ + url: string; + /** + * Request initiator. + */ + initiator: Initiator; + } + interface WebSocketClosedEventDataType { + /** + * Request identifier. + */ + requestId: RequestId; + /** + * Timestamp. + */ + timestamp: MonotonicTime; + } + interface WebSocketHandshakeResponseReceivedEventDataType { + /** + * Request identifier. + */ + requestId: RequestId; + /** + * Timestamp. + */ + timestamp: MonotonicTime; + /** + * WebSocket response data. + */ + response: WebSocketResponse; + } + } + namespace NodeRuntime { + interface NotifyWhenWaitingForDisconnectParameterType { + enabled: boolean; + } + } + namespace Target { + type SessionID = string; + type TargetID = string; + interface TargetInfo { + targetId: TargetID; + type: string; + title: string; + url: string; + attached: boolean; + canAccessOpener: boolean; + } + interface SetAutoAttachParameterType { + autoAttach: boolean; + waitForDebuggerOnStart: boolean; + } + interface TargetCreatedEventDataType { + targetInfo: TargetInfo; + } + interface AttachedToTargetEventDataType { + sessionId: SessionID; + targetInfo: TargetInfo; + waitingForDebugger: boolean; + } + } + namespace IO { + type StreamHandle = string; + interface ReadParameterType { + /** + * Handle of the stream to read. + */ + handle: StreamHandle; + /** + * Seek to the specified offset before reading (if not specified, proceed with offset + * following the last read). Some types of streams may only support sequential reads. + */ + offset?: number | undefined; + /** + * Maximum number of bytes to read (left upon the agent discretion if not specified). + */ + size?: number | undefined; + } + interface CloseParameterType { + /** + * Handle of the stream to close. + */ + handle: StreamHandle; + } + interface ReadReturnType { + /** + * Data that were read. + */ + data: string; + /** + * Set if the end-of-file condition occurred while reading. + */ + eof: boolean; + } + } + interface Session { + /** + * Posts a message to the inspector back-end. `callback` will be notified when + * a response is received. `callback` is a function that accepts two optional + * arguments: error and message-specific result. + * + * ```js + * session.post('Runtime.evaluate', { expression: '2 + 2' }, + * (error, { result }) => console.log(result)); + * // Output: { type: 'number', value: 4, description: '4' } + * ``` + * + * The latest version of the V8 inspector protocol is published on the + * [Chrome DevTools Protocol Viewer](https://chromedevtools.github.io/devtools-protocol/v8/). + * + * Node.js inspector supports all the Chrome DevTools Protocol domains declared + * by V8. Chrome DevTools Protocol domain provides an interface for interacting + * with one of the runtime agents used to inspect the application state and listen + * to the run-time events. + */ + post(method: string, callback?: (err: Error | null, params?: object) => void): void; + post(method: string, params?: object, callback?: (err: Error | null, params?: object) => void): void; + /** + * Returns supported domains. + */ + post(method: "Schema.getDomains", callback?: (err: Error | null, params: Schema.GetDomainsReturnType) => void): void; + /** + * Evaluates expression on global object. + */ + post(method: "Runtime.evaluate", params?: Runtime.EvaluateParameterType, callback?: (err: Error | null, params: Runtime.EvaluateReturnType) => void): void; + post(method: "Runtime.evaluate", callback?: (err: Error | null, params: Runtime.EvaluateReturnType) => void): void; + /** + * Add handler to promise with given promise object id. + */ + post(method: "Runtime.awaitPromise", params?: Runtime.AwaitPromiseParameterType, callback?: (err: Error | null, params: Runtime.AwaitPromiseReturnType) => void): void; + post(method: "Runtime.awaitPromise", callback?: (err: Error | null, params: Runtime.AwaitPromiseReturnType) => void): void; + /** + * Calls function with given declaration on the given object. Object group of the result is inherited from the target object. + */ + post(method: "Runtime.callFunctionOn", params?: Runtime.CallFunctionOnParameterType, callback?: (err: Error | null, params: Runtime.CallFunctionOnReturnType) => void): void; + post(method: "Runtime.callFunctionOn", callback?: (err: Error | null, params: Runtime.CallFunctionOnReturnType) => void): void; + /** + * Returns properties of a given object. Object group of the result is inherited from the target object. + */ + post(method: "Runtime.getProperties", params?: Runtime.GetPropertiesParameterType, callback?: (err: Error | null, params: Runtime.GetPropertiesReturnType) => void): void; + post(method: "Runtime.getProperties", callback?: (err: Error | null, params: Runtime.GetPropertiesReturnType) => void): void; + /** + * Releases remote object with given id. + */ + post(method: "Runtime.releaseObject", params?: Runtime.ReleaseObjectParameterType, callback?: (err: Error | null) => void): void; + post(method: "Runtime.releaseObject", callback?: (err: Error | null) => void): void; + /** + * Releases all remote objects that belong to a given group. + */ + post(method: "Runtime.releaseObjectGroup", params?: Runtime.ReleaseObjectGroupParameterType, callback?: (err: Error | null) => void): void; + post(method: "Runtime.releaseObjectGroup", callback?: (err: Error | null) => void): void; + /** + * Tells inspected instance to run if it was waiting for debugger to attach. + */ + post(method: "Runtime.runIfWaitingForDebugger", callback?: (err: Error | null) => void): void; + /** + * Enables reporting of execution contexts creation by means of <code>executionContextCreated</code> event. When the reporting gets enabled the event will be sent immediately for each existing execution context. + */ + post(method: "Runtime.enable", callback?: (err: Error | null) => void): void; + /** + * Disables reporting of execution contexts creation. + */ + post(method: "Runtime.disable", callback?: (err: Error | null) => void): void; + /** + * Discards collected exceptions and console API calls. + */ + post(method: "Runtime.discardConsoleEntries", callback?: (err: Error | null) => void): void; + /** + * @experimental + */ + post(method: "Runtime.setCustomObjectFormatterEnabled", params?: Runtime.SetCustomObjectFormatterEnabledParameterType, callback?: (err: Error | null) => void): void; + post(method: "Runtime.setCustomObjectFormatterEnabled", callback?: (err: Error | null) => void): void; + /** + * Compiles expression. + */ + post(method: "Runtime.compileScript", params?: Runtime.CompileScriptParameterType, callback?: (err: Error | null, params: Runtime.CompileScriptReturnType) => void): void; + post(method: "Runtime.compileScript", callback?: (err: Error | null, params: Runtime.CompileScriptReturnType) => void): void; + /** + * Runs script with given id in a given context. + */ + post(method: "Runtime.runScript", params?: Runtime.RunScriptParameterType, callback?: (err: Error | null, params: Runtime.RunScriptReturnType) => void): void; + post(method: "Runtime.runScript", callback?: (err: Error | null, params: Runtime.RunScriptReturnType) => void): void; + post(method: "Runtime.queryObjects", params?: Runtime.QueryObjectsParameterType, callback?: (err: Error | null, params: Runtime.QueryObjectsReturnType) => void): void; + post(method: "Runtime.queryObjects", callback?: (err: Error | null, params: Runtime.QueryObjectsReturnType) => void): void; + /** + * Returns all let, const and class variables from global scope. + */ + post( + method: "Runtime.globalLexicalScopeNames", + params?: Runtime.GlobalLexicalScopeNamesParameterType, + callback?: (err: Error | null, params: Runtime.GlobalLexicalScopeNamesReturnType) => void + ): void; + post(method: "Runtime.globalLexicalScopeNames", callback?: (err: Error | null, params: Runtime.GlobalLexicalScopeNamesReturnType) => void): void; + /** + * Enables debugger for the given page. Clients should not assume that the debugging has been enabled until the result for this command is received. + */ + post(method: "Debugger.enable", callback?: (err: Error | null, params: Debugger.EnableReturnType) => void): void; + /** + * Disables debugger for given page. + */ + post(method: "Debugger.disable", callback?: (err: Error | null) => void): void; + /** + * Activates / deactivates all breakpoints on the page. + */ + post(method: "Debugger.setBreakpointsActive", params?: Debugger.SetBreakpointsActiveParameterType, callback?: (err: Error | null) => void): void; + post(method: "Debugger.setBreakpointsActive", callback?: (err: Error | null) => void): void; + /** + * Makes page not interrupt on any pauses (breakpoint, exception, dom exception etc). + */ + post(method: "Debugger.setSkipAllPauses", params?: Debugger.SetSkipAllPausesParameterType, callback?: (err: Error | null) => void): void; + post(method: "Debugger.setSkipAllPauses", callback?: (err: Error | null) => void): void; + /** + * Sets JavaScript breakpoint at given location specified either by URL or URL regex. Once this command is issued, all existing parsed scripts will have breakpoints resolved and returned in <code>locations</code> property. Further matching script parsing will result in subsequent <code>breakpointResolved</code> events issued. This logical breakpoint will survive page reloads. + */ + post(method: "Debugger.setBreakpointByUrl", params?: Debugger.SetBreakpointByUrlParameterType, callback?: (err: Error | null, params: Debugger.SetBreakpointByUrlReturnType) => void): void; + post(method: "Debugger.setBreakpointByUrl", callback?: (err: Error | null, params: Debugger.SetBreakpointByUrlReturnType) => void): void; + /** + * Sets JavaScript breakpoint at a given location. + */ + post(method: "Debugger.setBreakpoint", params?: Debugger.SetBreakpointParameterType, callback?: (err: Error | null, params: Debugger.SetBreakpointReturnType) => void): void; + post(method: "Debugger.setBreakpoint", callback?: (err: Error | null, params: Debugger.SetBreakpointReturnType) => void): void; + /** + * Removes JavaScript breakpoint. + */ + post(method: "Debugger.removeBreakpoint", params?: Debugger.RemoveBreakpointParameterType, callback?: (err: Error | null) => void): void; + post(method: "Debugger.removeBreakpoint", callback?: (err: Error | null) => void): void; + /** + * Returns possible locations for breakpoint. scriptId in start and end range locations should be the same. + */ + post( + method: "Debugger.getPossibleBreakpoints", + params?: Debugger.GetPossibleBreakpointsParameterType, + callback?: (err: Error | null, params: Debugger.GetPossibleBreakpointsReturnType) => void + ): void; + post(method: "Debugger.getPossibleBreakpoints", callback?: (err: Error | null, params: Debugger.GetPossibleBreakpointsReturnType) => void): void; + /** + * Continues execution until specific location is reached. + */ + post(method: "Debugger.continueToLocation", params?: Debugger.ContinueToLocationParameterType, callback?: (err: Error | null) => void): void; + post(method: "Debugger.continueToLocation", callback?: (err: Error | null) => void): void; + /** + * @experimental + */ + post(method: "Debugger.pauseOnAsyncCall", params?: Debugger.PauseOnAsyncCallParameterType, callback?: (err: Error | null) => void): void; + post(method: "Debugger.pauseOnAsyncCall", callback?: (err: Error | null) => void): void; + /** + * Steps over the statement. + */ + post(method: "Debugger.stepOver", callback?: (err: Error | null) => void): void; + /** + * Steps into the function call. + */ + post(method: "Debugger.stepInto", params?: Debugger.StepIntoParameterType, callback?: (err: Error | null) => void): void; + post(method: "Debugger.stepInto", callback?: (err: Error | null) => void): void; + /** + * Steps out of the function call. + */ + post(method: "Debugger.stepOut", callback?: (err: Error | null) => void): void; + /** + * Stops on the next JavaScript statement. + */ + post(method: "Debugger.pause", callback?: (err: Error | null) => void): void; + /** + * This method is deprecated - use Debugger.stepInto with breakOnAsyncCall and Debugger.pauseOnAsyncTask instead. Steps into next scheduled async task if any is scheduled before next pause. Returns success when async task is actually scheduled, returns error if no task were scheduled or another scheduleStepIntoAsync was called. + * @experimental + */ + post(method: "Debugger.scheduleStepIntoAsync", callback?: (err: Error | null) => void): void; + /** + * Resumes JavaScript execution. + */ + post(method: "Debugger.resume", callback?: (err: Error | null) => void): void; + /** + * Returns stack trace with given <code>stackTraceId</code>. + * @experimental + */ + post(method: "Debugger.getStackTrace", params?: Debugger.GetStackTraceParameterType, callback?: (err: Error | null, params: Debugger.GetStackTraceReturnType) => void): void; + post(method: "Debugger.getStackTrace", callback?: (err: Error | null, params: Debugger.GetStackTraceReturnType) => void): void; + /** + * Searches for given string in script content. + */ + post(method: "Debugger.searchInContent", params?: Debugger.SearchInContentParameterType, callback?: (err: Error | null, params: Debugger.SearchInContentReturnType) => void): void; + post(method: "Debugger.searchInContent", callback?: (err: Error | null, params: Debugger.SearchInContentReturnType) => void): void; + /** + * Edits JavaScript source live. + */ + post(method: "Debugger.setScriptSource", params?: Debugger.SetScriptSourceParameterType, callback?: (err: Error | null, params: Debugger.SetScriptSourceReturnType) => void): void; + post(method: "Debugger.setScriptSource", callback?: (err: Error | null, params: Debugger.SetScriptSourceReturnType) => void): void; + /** + * Restarts particular call frame from the beginning. + */ + post(method: "Debugger.restartFrame", params?: Debugger.RestartFrameParameterType, callback?: (err: Error | null, params: Debugger.RestartFrameReturnType) => void): void; + post(method: "Debugger.restartFrame", callback?: (err: Error | null, params: Debugger.RestartFrameReturnType) => void): void; + /** + * Returns source for the script with given id. + */ + post(method: "Debugger.getScriptSource", params?: Debugger.GetScriptSourceParameterType, callback?: (err: Error | null, params: Debugger.GetScriptSourceReturnType) => void): void; + post(method: "Debugger.getScriptSource", callback?: (err: Error | null, params: Debugger.GetScriptSourceReturnType) => void): void; + /** + * Defines pause on exceptions state. Can be set to stop on all exceptions, uncaught exceptions or no exceptions. Initial pause on exceptions state is <code>none</code>. + */ + post(method: "Debugger.setPauseOnExceptions", params?: Debugger.SetPauseOnExceptionsParameterType, callback?: (err: Error | null) => void): void; + post(method: "Debugger.setPauseOnExceptions", callback?: (err: Error | null) => void): void; + /** + * Evaluates expression on a given call frame. + */ + post(method: "Debugger.evaluateOnCallFrame", params?: Debugger.EvaluateOnCallFrameParameterType, callback?: (err: Error | null, params: Debugger.EvaluateOnCallFrameReturnType) => void): void; + post(method: "Debugger.evaluateOnCallFrame", callback?: (err: Error | null, params: Debugger.EvaluateOnCallFrameReturnType) => void): void; + /** + * Changes value of variable in a callframe. Object-based scopes are not supported and must be mutated manually. + */ + post(method: "Debugger.setVariableValue", params?: Debugger.SetVariableValueParameterType, callback?: (err: Error | null) => void): void; + post(method: "Debugger.setVariableValue", callback?: (err: Error | null) => void): void; + /** + * Changes return value in top frame. Available only at return break position. + * @experimental + */ + post(method: "Debugger.setReturnValue", params?: Debugger.SetReturnValueParameterType, callback?: (err: Error | null) => void): void; + post(method: "Debugger.setReturnValue", callback?: (err: Error | null) => void): void; + /** + * Enables or disables async call stacks tracking. + */ + post(method: "Debugger.setAsyncCallStackDepth", params?: Debugger.SetAsyncCallStackDepthParameterType, callback?: (err: Error | null) => void): void; + post(method: "Debugger.setAsyncCallStackDepth", callback?: (err: Error | null) => void): void; + /** + * Replace previous blackbox patterns with passed ones. Forces backend to skip stepping/pausing in scripts with url matching one of the patterns. VM will try to leave blackboxed script by performing 'step in' several times, finally resorting to 'step out' if unsuccessful. + * @experimental + */ + post(method: "Debugger.setBlackboxPatterns", params?: Debugger.SetBlackboxPatternsParameterType, callback?: (err: Error | null) => void): void; + post(method: "Debugger.setBlackboxPatterns", callback?: (err: Error | null) => void): void; + /** + * Makes backend skip steps in the script in blackboxed ranges. VM will try leave blacklisted scripts by performing 'step in' several times, finally resorting to 'step out' if unsuccessful. Positions array contains positions where blackbox state is changed. First interval isn't blackboxed. Array should be sorted. + * @experimental + */ + post(method: "Debugger.setBlackboxedRanges", params?: Debugger.SetBlackboxedRangesParameterType, callback?: (err: Error | null) => void): void; + post(method: "Debugger.setBlackboxedRanges", callback?: (err: Error | null) => void): void; + /** + * Enables console domain, sends the messages collected so far to the client by means of the <code>messageAdded</code> notification. + */ + post(method: "Console.enable", callback?: (err: Error | null) => void): void; + /** + * Disables console domain, prevents further console messages from being reported to the client. + */ + post(method: "Console.disable", callback?: (err: Error | null) => void): void; + /** + * Does nothing. + */ + post(method: "Console.clearMessages", callback?: (err: Error | null) => void): void; + post(method: "Profiler.enable", callback?: (err: Error | null) => void): void; + post(method: "Profiler.disable", callback?: (err: Error | null) => void): void; + /** + * Changes CPU profiler sampling interval. Must be called before CPU profiles recording started. + */ + post(method: "Profiler.setSamplingInterval", params?: Profiler.SetSamplingIntervalParameterType, callback?: (err: Error | null) => void): void; + post(method: "Profiler.setSamplingInterval", callback?: (err: Error | null) => void): void; + post(method: "Profiler.start", callback?: (err: Error | null) => void): void; + post(method: "Profiler.stop", callback?: (err: Error | null, params: Profiler.StopReturnType) => void): void; + /** + * Enable precise code coverage. Coverage data for JavaScript executed before enabling precise code coverage may be incomplete. Enabling prevents running optimized code and resets execution counters. + */ + post(method: "Profiler.startPreciseCoverage", params?: Profiler.StartPreciseCoverageParameterType, callback?: (err: Error | null) => void): void; + post(method: "Profiler.startPreciseCoverage", callback?: (err: Error | null) => void): void; + /** + * Disable precise code coverage. Disabling releases unnecessary execution count records and allows executing optimized code. + */ + post(method: "Profiler.stopPreciseCoverage", callback?: (err: Error | null) => void): void; + /** + * Collect coverage data for the current isolate, and resets execution counters. Precise code coverage needs to have started. + */ + post(method: "Profiler.takePreciseCoverage", callback?: (err: Error | null, params: Profiler.TakePreciseCoverageReturnType) => void): void; + /** + * Collect coverage data for the current isolate. The coverage data may be incomplete due to garbage collection. + */ + post(method: "Profiler.getBestEffortCoverage", callback?: (err: Error | null, params: Profiler.GetBestEffortCoverageReturnType) => void): void; + post(method: "HeapProfiler.enable", callback?: (err: Error | null) => void): void; + post(method: "HeapProfiler.disable", callback?: (err: Error | null) => void): void; + post(method: "HeapProfiler.startTrackingHeapObjects", params?: HeapProfiler.StartTrackingHeapObjectsParameterType, callback?: (err: Error | null) => void): void; + post(method: "HeapProfiler.startTrackingHeapObjects", callback?: (err: Error | null) => void): void; + post(method: "HeapProfiler.stopTrackingHeapObjects", params?: HeapProfiler.StopTrackingHeapObjectsParameterType, callback?: (err: Error | null) => void): void; + post(method: "HeapProfiler.stopTrackingHeapObjects", callback?: (err: Error | null) => void): void; + post(method: "HeapProfiler.takeHeapSnapshot", params?: HeapProfiler.TakeHeapSnapshotParameterType, callback?: (err: Error | null) => void): void; + post(method: "HeapProfiler.takeHeapSnapshot", callback?: (err: Error | null) => void): void; + post(method: "HeapProfiler.collectGarbage", callback?: (err: Error | null) => void): void; + post( + method: "HeapProfiler.getObjectByHeapObjectId", + params?: HeapProfiler.GetObjectByHeapObjectIdParameterType, + callback?: (err: Error | null, params: HeapProfiler.GetObjectByHeapObjectIdReturnType) => void + ): void; + post(method: "HeapProfiler.getObjectByHeapObjectId", callback?: (err: Error | null, params: HeapProfiler.GetObjectByHeapObjectIdReturnType) => void): void; + /** + * Enables console to refer to the node with given id via $x (see Command Line API for more details $x functions). + */ + post(method: "HeapProfiler.addInspectedHeapObject", params?: HeapProfiler.AddInspectedHeapObjectParameterType, callback?: (err: Error | null) => void): void; + post(method: "HeapProfiler.addInspectedHeapObject", callback?: (err: Error | null) => void): void; + post(method: "HeapProfiler.getHeapObjectId", params?: HeapProfiler.GetHeapObjectIdParameterType, callback?: (err: Error | null, params: HeapProfiler.GetHeapObjectIdReturnType) => void): void; + post(method: "HeapProfiler.getHeapObjectId", callback?: (err: Error | null, params: HeapProfiler.GetHeapObjectIdReturnType) => void): void; + post(method: "HeapProfiler.startSampling", params?: HeapProfiler.StartSamplingParameterType, callback?: (err: Error | null) => void): void; + post(method: "HeapProfiler.startSampling", callback?: (err: Error | null) => void): void; + post(method: "HeapProfiler.stopSampling", callback?: (err: Error | null, params: HeapProfiler.StopSamplingReturnType) => void): void; + post(method: "HeapProfiler.getSamplingProfile", callback?: (err: Error | null, params: HeapProfiler.GetSamplingProfileReturnType) => void): void; + /** + * Gets supported tracing categories. + */ + post(method: "NodeTracing.getCategories", callback?: (err: Error | null, params: NodeTracing.GetCategoriesReturnType) => void): void; + /** + * Start trace events collection. + */ + post(method: "NodeTracing.start", params?: NodeTracing.StartParameterType, callback?: (err: Error | null) => void): void; + post(method: "NodeTracing.start", callback?: (err: Error | null) => void): void; + /** + * Stop trace events collection. Remaining collected events will be sent as a sequence of + * dataCollected events followed by tracingComplete event. + */ + post(method: "NodeTracing.stop", callback?: (err: Error | null) => void): void; + /** + * Sends protocol message over session with given id. + */ + post(method: "NodeWorker.sendMessageToWorker", params?: NodeWorker.SendMessageToWorkerParameterType, callback?: (err: Error | null) => void): void; + post(method: "NodeWorker.sendMessageToWorker", callback?: (err: Error | null) => void): void; + /** + * Instructs the inspector to attach to running workers. Will also attach to new workers + * as they start + */ + post(method: "NodeWorker.enable", params?: NodeWorker.EnableParameterType, callback?: (err: Error | null) => void): void; + post(method: "NodeWorker.enable", callback?: (err: Error | null) => void): void; + /** + * Detaches from all running workers and disables attaching to new workers as they are started. + */ + post(method: "NodeWorker.disable", callback?: (err: Error | null) => void): void; + /** + * Detached from the worker with given sessionId. + */ + post(method: "NodeWorker.detach", params?: NodeWorker.DetachParameterType, callback?: (err: Error | null) => void): void; + post(method: "NodeWorker.detach", callback?: (err: Error | null) => void): void; + /** + * Disables network tracking, prevents network events from being sent to the client. + */ + post(method: "Network.disable", callback?: (err: Error | null) => void): void; + /** + * Enables network tracking, network events will now be delivered to the client. + */ + post(method: "Network.enable", callback?: (err: Error | null) => void): void; + /** + * Returns post data sent with the request. Returns an error when no data was sent with the request. + */ + post(method: "Network.getRequestPostData", params?: Network.GetRequestPostDataParameterType, callback?: (err: Error | null, params: Network.GetRequestPostDataReturnType) => void): void; + post(method: "Network.getRequestPostData", callback?: (err: Error | null, params: Network.GetRequestPostDataReturnType) => void): void; + /** + * Returns content served for the given request. + */ + post(method: "Network.getResponseBody", params?: Network.GetResponseBodyParameterType, callback?: (err: Error | null, params: Network.GetResponseBodyReturnType) => void): void; + post(method: "Network.getResponseBody", callback?: (err: Error | null, params: Network.GetResponseBodyReturnType) => void): void; + /** + * Enables streaming of the response for the given requestId. + * If enabled, the dataReceived event contains the data that was received during streaming. + * @experimental + */ + post( + method: "Network.streamResourceContent", + params?: Network.StreamResourceContentParameterType, + callback?: (err: Error | null, params: Network.StreamResourceContentReturnType) => void + ): void; + post(method: "Network.streamResourceContent", callback?: (err: Error | null, params: Network.StreamResourceContentReturnType) => void): void; + /** + * Fetches the resource and returns the content. + */ + post(method: "Network.loadNetworkResource", params?: Network.LoadNetworkResourceParameterType, callback?: (err: Error | null, params: Network.LoadNetworkResourceReturnType) => void): void; + post(method: "Network.loadNetworkResource", callback?: (err: Error | null, params: Network.LoadNetworkResourceReturnType) => void): void; + /** + * Enable the NodeRuntime events except by `NodeRuntime.waitingForDisconnect`. + */ + post(method: "NodeRuntime.enable", callback?: (err: Error | null) => void): void; + /** + * Disable NodeRuntime events + */ + post(method: "NodeRuntime.disable", callback?: (err: Error | null) => void): void; + /** + * Enable the `NodeRuntime.waitingForDisconnect`. + */ + post(method: "NodeRuntime.notifyWhenWaitingForDisconnect", params?: NodeRuntime.NotifyWhenWaitingForDisconnectParameterType, callback?: (err: Error | null) => void): void; + post(method: "NodeRuntime.notifyWhenWaitingForDisconnect", callback?: (err: Error | null) => void): void; + post(method: "Target.setAutoAttach", params?: Target.SetAutoAttachParameterType, callback?: (err: Error | null) => void): void; + post(method: "Target.setAutoAttach", callback?: (err: Error | null) => void): void; + /** + * Read a chunk of the stream + */ + post(method: "IO.read", params?: IO.ReadParameterType, callback?: (err: Error | null, params: IO.ReadReturnType) => void): void; + post(method: "IO.read", callback?: (err: Error | null, params: IO.ReadReturnType) => void): void; + post(method: "IO.close", params?: IO.CloseParameterType, callback?: (err: Error | null) => void): void; + post(method: "IO.close", callback?: (err: Error | null) => void): void; + addListener(event: string, listener: (...args: any[]) => void): this; + /** + * Emitted when any notification from the V8 Inspector is received. + */ + addListener(event: "inspectorNotification", listener: (message: InspectorNotification<object>) => void): this; + /** + * Issued when new execution context is created. + */ + addListener(event: "Runtime.executionContextCreated", listener: (message: InspectorNotification<Runtime.ExecutionContextCreatedEventDataType>) => void): this; + /** + * Issued when execution context is destroyed. + */ + addListener(event: "Runtime.executionContextDestroyed", listener: (message: InspectorNotification<Runtime.ExecutionContextDestroyedEventDataType>) => void): this; + /** + * Issued when all executionContexts were cleared in browser + */ + addListener(event: "Runtime.executionContextsCleared", listener: () => void): this; + /** + * Issued when exception was thrown and unhandled. + */ + addListener(event: "Runtime.exceptionThrown", listener: (message: InspectorNotification<Runtime.ExceptionThrownEventDataType>) => void): this; + /** + * Issued when unhandled exception was revoked. + */ + addListener(event: "Runtime.exceptionRevoked", listener: (message: InspectorNotification<Runtime.ExceptionRevokedEventDataType>) => void): this; + /** + * Issued when console API was called. + */ + addListener(event: "Runtime.consoleAPICalled", listener: (message: InspectorNotification<Runtime.ConsoleAPICalledEventDataType>) => void): this; + /** + * Issued when object should be inspected (for example, as a result of inspect() command line API call). + */ + addListener(event: "Runtime.inspectRequested", listener: (message: InspectorNotification<Runtime.InspectRequestedEventDataType>) => void): this; + /** + * Fired when virtual machine parses script. This event is also fired for all known and uncollected scripts upon enabling debugger. + */ + addListener(event: "Debugger.scriptParsed", listener: (message: InspectorNotification<Debugger.ScriptParsedEventDataType>) => void): this; + /** + * Fired when virtual machine fails to parse the script. + */ + addListener(event: "Debugger.scriptFailedToParse", listener: (message: InspectorNotification<Debugger.ScriptFailedToParseEventDataType>) => void): this; + /** + * Fired when breakpoint is resolved to an actual script and location. + */ + addListener(event: "Debugger.breakpointResolved", listener: (message: InspectorNotification<Debugger.BreakpointResolvedEventDataType>) => void): this; + /** + * Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria. + */ + addListener(event: "Debugger.paused", listener: (message: InspectorNotification<Debugger.PausedEventDataType>) => void): this; + /** + * Fired when the virtual machine resumed execution. + */ + addListener(event: "Debugger.resumed", listener: () => void): this; + /** + * Issued when new console message is added. + */ + addListener(event: "Console.messageAdded", listener: (message: InspectorNotification<Console.MessageAddedEventDataType>) => void): this; + /** + * Sent when new profile recording is started using console.profile() call. + */ + addListener(event: "Profiler.consoleProfileStarted", listener: (message: InspectorNotification<Profiler.ConsoleProfileStartedEventDataType>) => void): this; + addListener(event: "Profiler.consoleProfileFinished", listener: (message: InspectorNotification<Profiler.ConsoleProfileFinishedEventDataType>) => void): this; + addListener(event: "HeapProfiler.addHeapSnapshotChunk", listener: (message: InspectorNotification<HeapProfiler.AddHeapSnapshotChunkEventDataType>) => void): this; + addListener(event: "HeapProfiler.resetProfiles", listener: () => void): this; + addListener(event: "HeapProfiler.reportHeapSnapshotProgress", listener: (message: InspectorNotification<HeapProfiler.ReportHeapSnapshotProgressEventDataType>) => void): this; + /** + * If heap objects tracking has been started then backend regularly sends a current value for last seen object id and corresponding timestamp. If the were changes in the heap since last event then one or more heapStatsUpdate events will be sent before a new lastSeenObjectId event. + */ + addListener(event: "HeapProfiler.lastSeenObjectId", listener: (message: InspectorNotification<HeapProfiler.LastSeenObjectIdEventDataType>) => void): this; + /** + * If heap objects tracking has been started then backend may send update for one or more fragments + */ + addListener(event: "HeapProfiler.heapStatsUpdate", listener: (message: InspectorNotification<HeapProfiler.HeapStatsUpdateEventDataType>) => void): this; + /** + * Contains an bucket of collected trace events. + */ + addListener(event: "NodeTracing.dataCollected", listener: (message: InspectorNotification<NodeTracing.DataCollectedEventDataType>) => void): this; + /** + * Signals that tracing is stopped and there is no trace buffers pending flush, all data were + * delivered via dataCollected events. + */ + addListener(event: "NodeTracing.tracingComplete", listener: () => void): this; + /** + * Issued when attached to a worker. + */ + addListener(event: "NodeWorker.attachedToWorker", listener: (message: InspectorNotification<NodeWorker.AttachedToWorkerEventDataType>) => void): this; + /** + * Issued when detached from the worker. + */ + addListener(event: "NodeWorker.detachedFromWorker", listener: (message: InspectorNotification<NodeWorker.DetachedFromWorkerEventDataType>) => void): this; + /** + * Notifies about a new protocol message received from the session + * (session ID is provided in attachedToWorker notification). + */ + addListener(event: "NodeWorker.receivedMessageFromWorker", listener: (message: InspectorNotification<NodeWorker.ReceivedMessageFromWorkerEventDataType>) => void): this; + /** + * Fired when page is about to send HTTP request. + */ + addListener(event: "Network.requestWillBeSent", listener: (message: InspectorNotification<Network.RequestWillBeSentEventDataType>) => void): this; + /** + * Fired when HTTP response is available. + */ + addListener(event: "Network.responseReceived", listener: (message: InspectorNotification<Network.ResponseReceivedEventDataType>) => void): this; + addListener(event: "Network.loadingFailed", listener: (message: InspectorNotification<Network.LoadingFailedEventDataType>) => void): this; + addListener(event: "Network.loadingFinished", listener: (message: InspectorNotification<Network.LoadingFinishedEventDataType>) => void): this; + /** + * Fired when data chunk was received over the network. + */ + addListener(event: "Network.dataReceived", listener: (message: InspectorNotification<Network.DataReceivedEventDataType>) => void): this; + /** + * Fired upon WebSocket creation. + */ + addListener(event: "Network.webSocketCreated", listener: (message: InspectorNotification<Network.WebSocketCreatedEventDataType>) => void): this; + /** + * Fired when WebSocket is closed. + */ + addListener(event: "Network.webSocketClosed", listener: (message: InspectorNotification<Network.WebSocketClosedEventDataType>) => void): this; + /** + * Fired when WebSocket handshake response becomes available. + */ + addListener(event: "Network.webSocketHandshakeResponseReceived", listener: (message: InspectorNotification<Network.WebSocketHandshakeResponseReceivedEventDataType>) => void): this; + /** + * This event is fired instead of `Runtime.executionContextDestroyed` when + * enabled. + * It is fired when the Node process finished all code execution and is + * waiting for all frontends to disconnect. + */ + addListener(event: "NodeRuntime.waitingForDisconnect", listener: () => void): this; + /** + * This event is fired when the runtime is waiting for the debugger. For + * example, when inspector.waitingForDebugger is called + */ + addListener(event: "NodeRuntime.waitingForDebugger", listener: () => void): this; + addListener(event: "Target.targetCreated", listener: (message: InspectorNotification<Target.TargetCreatedEventDataType>) => void): this; + addListener(event: "Target.attachedToTarget", listener: (message: InspectorNotification<Target.AttachedToTargetEventDataType>) => void): this; + emit(event: string | symbol, ...args: any[]): boolean; + emit(event: "inspectorNotification", message: InspectorNotification<object>): boolean; + emit(event: "Runtime.executionContextCreated", message: InspectorNotification<Runtime.ExecutionContextCreatedEventDataType>): boolean; + emit(event: "Runtime.executionContextDestroyed", message: InspectorNotification<Runtime.ExecutionContextDestroyedEventDataType>): boolean; + emit(event: "Runtime.executionContextsCleared"): boolean; + emit(event: "Runtime.exceptionThrown", message: InspectorNotification<Runtime.ExceptionThrownEventDataType>): boolean; + emit(event: "Runtime.exceptionRevoked", message: InspectorNotification<Runtime.ExceptionRevokedEventDataType>): boolean; + emit(event: "Runtime.consoleAPICalled", message: InspectorNotification<Runtime.ConsoleAPICalledEventDataType>): boolean; + emit(event: "Runtime.inspectRequested", message: InspectorNotification<Runtime.InspectRequestedEventDataType>): boolean; + emit(event: "Debugger.scriptParsed", message: InspectorNotification<Debugger.ScriptParsedEventDataType>): boolean; + emit(event: "Debugger.scriptFailedToParse", message: InspectorNotification<Debugger.ScriptFailedToParseEventDataType>): boolean; + emit(event: "Debugger.breakpointResolved", message: InspectorNotification<Debugger.BreakpointResolvedEventDataType>): boolean; + emit(event: "Debugger.paused", message: InspectorNotification<Debugger.PausedEventDataType>): boolean; + emit(event: "Debugger.resumed"): boolean; + emit(event: "Console.messageAdded", message: InspectorNotification<Console.MessageAddedEventDataType>): boolean; + emit(event: "Profiler.consoleProfileStarted", message: InspectorNotification<Profiler.ConsoleProfileStartedEventDataType>): boolean; + emit(event: "Profiler.consoleProfileFinished", message: InspectorNotification<Profiler.ConsoleProfileFinishedEventDataType>): boolean; + emit(event: "HeapProfiler.addHeapSnapshotChunk", message: InspectorNotification<HeapProfiler.AddHeapSnapshotChunkEventDataType>): boolean; + emit(event: "HeapProfiler.resetProfiles"): boolean; + emit(event: "HeapProfiler.reportHeapSnapshotProgress", message: InspectorNotification<HeapProfiler.ReportHeapSnapshotProgressEventDataType>): boolean; + emit(event: "HeapProfiler.lastSeenObjectId", message: InspectorNotification<HeapProfiler.LastSeenObjectIdEventDataType>): boolean; + emit(event: "HeapProfiler.heapStatsUpdate", message: InspectorNotification<HeapProfiler.HeapStatsUpdateEventDataType>): boolean; + emit(event: "NodeTracing.dataCollected", message: InspectorNotification<NodeTracing.DataCollectedEventDataType>): boolean; + emit(event: "NodeTracing.tracingComplete"): boolean; + emit(event: "NodeWorker.attachedToWorker", message: InspectorNotification<NodeWorker.AttachedToWorkerEventDataType>): boolean; + emit(event: "NodeWorker.detachedFromWorker", message: InspectorNotification<NodeWorker.DetachedFromWorkerEventDataType>): boolean; + emit(event: "NodeWorker.receivedMessageFromWorker", message: InspectorNotification<NodeWorker.ReceivedMessageFromWorkerEventDataType>): boolean; + emit(event: "Network.requestWillBeSent", message: InspectorNotification<Network.RequestWillBeSentEventDataType>): boolean; + emit(event: "Network.responseReceived", message: InspectorNotification<Network.ResponseReceivedEventDataType>): boolean; + emit(event: "Network.loadingFailed", message: InspectorNotification<Network.LoadingFailedEventDataType>): boolean; + emit(event: "Network.loadingFinished", message: InspectorNotification<Network.LoadingFinishedEventDataType>): boolean; + emit(event: "Network.dataReceived", message: InspectorNotification<Network.DataReceivedEventDataType>): boolean; + emit(event: "Network.webSocketCreated", message: InspectorNotification<Network.WebSocketCreatedEventDataType>): boolean; + emit(event: "Network.webSocketClosed", message: InspectorNotification<Network.WebSocketClosedEventDataType>): boolean; + emit(event: "Network.webSocketHandshakeResponseReceived", message: InspectorNotification<Network.WebSocketHandshakeResponseReceivedEventDataType>): boolean; + emit(event: "NodeRuntime.waitingForDisconnect"): boolean; + emit(event: "NodeRuntime.waitingForDebugger"): boolean; + emit(event: "Target.targetCreated", message: InspectorNotification<Target.TargetCreatedEventDataType>): boolean; + emit(event: "Target.attachedToTarget", message: InspectorNotification<Target.AttachedToTargetEventDataType>): boolean; + on(event: string, listener: (...args: any[]) => void): this; + /** + * Emitted when any notification from the V8 Inspector is received. + */ + on(event: "inspectorNotification", listener: (message: InspectorNotification<object>) => void): this; + /** + * Issued when new execution context is created. + */ + on(event: "Runtime.executionContextCreated", listener: (message: InspectorNotification<Runtime.ExecutionContextCreatedEventDataType>) => void): this; + /** + * Issued when execution context is destroyed. + */ + on(event: "Runtime.executionContextDestroyed", listener: (message: InspectorNotification<Runtime.ExecutionContextDestroyedEventDataType>) => void): this; + /** + * Issued when all executionContexts were cleared in browser + */ + on(event: "Runtime.executionContextsCleared", listener: () => void): this; + /** + * Issued when exception was thrown and unhandled. + */ + on(event: "Runtime.exceptionThrown", listener: (message: InspectorNotification<Runtime.ExceptionThrownEventDataType>) => void): this; + /** + * Issued when unhandled exception was revoked. + */ + on(event: "Runtime.exceptionRevoked", listener: (message: InspectorNotification<Runtime.ExceptionRevokedEventDataType>) => void): this; + /** + * Issued when console API was called. + */ + on(event: "Runtime.consoleAPICalled", listener: (message: InspectorNotification<Runtime.ConsoleAPICalledEventDataType>) => void): this; + /** + * Issued when object should be inspected (for example, as a result of inspect() command line API call). + */ + on(event: "Runtime.inspectRequested", listener: (message: InspectorNotification<Runtime.InspectRequestedEventDataType>) => void): this; + /** + * Fired when virtual machine parses script. This event is also fired for all known and uncollected scripts upon enabling debugger. + */ + on(event: "Debugger.scriptParsed", listener: (message: InspectorNotification<Debugger.ScriptParsedEventDataType>) => void): this; + /** + * Fired when virtual machine fails to parse the script. + */ + on(event: "Debugger.scriptFailedToParse", listener: (message: InspectorNotification<Debugger.ScriptFailedToParseEventDataType>) => void): this; + /** + * Fired when breakpoint is resolved to an actual script and location. + */ + on(event: "Debugger.breakpointResolved", listener: (message: InspectorNotification<Debugger.BreakpointResolvedEventDataType>) => void): this; + /** + * Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria. + */ + on(event: "Debugger.paused", listener: (message: InspectorNotification<Debugger.PausedEventDataType>) => void): this; + /** + * Fired when the virtual machine resumed execution. + */ + on(event: "Debugger.resumed", listener: () => void): this; + /** + * Issued when new console message is added. + */ + on(event: "Console.messageAdded", listener: (message: InspectorNotification<Console.MessageAddedEventDataType>) => void): this; + /** + * Sent when new profile recording is started using console.profile() call. + */ + on(event: "Profiler.consoleProfileStarted", listener: (message: InspectorNotification<Profiler.ConsoleProfileStartedEventDataType>) => void): this; + on(event: "Profiler.consoleProfileFinished", listener: (message: InspectorNotification<Profiler.ConsoleProfileFinishedEventDataType>) => void): this; + on(event: "HeapProfiler.addHeapSnapshotChunk", listener: (message: InspectorNotification<HeapProfiler.AddHeapSnapshotChunkEventDataType>) => void): this; + on(event: "HeapProfiler.resetProfiles", listener: () => void): this; + on(event: "HeapProfiler.reportHeapSnapshotProgress", listener: (message: InspectorNotification<HeapProfiler.ReportHeapSnapshotProgressEventDataType>) => void): this; + /** + * If heap objects tracking has been started then backend regularly sends a current value for last seen object id and corresponding timestamp. If the were changes in the heap since last event then one or more heapStatsUpdate events will be sent before a new lastSeenObjectId event. + */ + on(event: "HeapProfiler.lastSeenObjectId", listener: (message: InspectorNotification<HeapProfiler.LastSeenObjectIdEventDataType>) => void): this; + /** + * If heap objects tracking has been started then backend may send update for one or more fragments + */ + on(event: "HeapProfiler.heapStatsUpdate", listener: (message: InspectorNotification<HeapProfiler.HeapStatsUpdateEventDataType>) => void): this; + /** + * Contains an bucket of collected trace events. + */ + on(event: "NodeTracing.dataCollected", listener: (message: InspectorNotification<NodeTracing.DataCollectedEventDataType>) => void): this; + /** + * Signals that tracing is stopped and there is no trace buffers pending flush, all data were + * delivered via dataCollected events. + */ + on(event: "NodeTracing.tracingComplete", listener: () => void): this; + /** + * Issued when attached to a worker. + */ + on(event: "NodeWorker.attachedToWorker", listener: (message: InspectorNotification<NodeWorker.AttachedToWorkerEventDataType>) => void): this; + /** + * Issued when detached from the worker. + */ + on(event: "NodeWorker.detachedFromWorker", listener: (message: InspectorNotification<NodeWorker.DetachedFromWorkerEventDataType>) => void): this; + /** + * Notifies about a new protocol message received from the session + * (session ID is provided in attachedToWorker notification). + */ + on(event: "NodeWorker.receivedMessageFromWorker", listener: (message: InspectorNotification<NodeWorker.ReceivedMessageFromWorkerEventDataType>) => void): this; + /** + * Fired when page is about to send HTTP request. + */ + on(event: "Network.requestWillBeSent", listener: (message: InspectorNotification<Network.RequestWillBeSentEventDataType>) => void): this; + /** + * Fired when HTTP response is available. + */ + on(event: "Network.responseReceived", listener: (message: InspectorNotification<Network.ResponseReceivedEventDataType>) => void): this; + on(event: "Network.loadingFailed", listener: (message: InspectorNotification<Network.LoadingFailedEventDataType>) => void): this; + on(event: "Network.loadingFinished", listener: (message: InspectorNotification<Network.LoadingFinishedEventDataType>) => void): this; + /** + * Fired when data chunk was received over the network. + */ + on(event: "Network.dataReceived", listener: (message: InspectorNotification<Network.DataReceivedEventDataType>) => void): this; + /** + * Fired upon WebSocket creation. + */ + on(event: "Network.webSocketCreated", listener: (message: InspectorNotification<Network.WebSocketCreatedEventDataType>) => void): this; + /** + * Fired when WebSocket is closed. + */ + on(event: "Network.webSocketClosed", listener: (message: InspectorNotification<Network.WebSocketClosedEventDataType>) => void): this; + /** + * Fired when WebSocket handshake response becomes available. + */ + on(event: "Network.webSocketHandshakeResponseReceived", listener: (message: InspectorNotification<Network.WebSocketHandshakeResponseReceivedEventDataType>) => void): this; + /** + * This event is fired instead of `Runtime.executionContextDestroyed` when + * enabled. + * It is fired when the Node process finished all code execution and is + * waiting for all frontends to disconnect. + */ + on(event: "NodeRuntime.waitingForDisconnect", listener: () => void): this; + /** + * This event is fired when the runtime is waiting for the debugger. For + * example, when inspector.waitingForDebugger is called + */ + on(event: "NodeRuntime.waitingForDebugger", listener: () => void): this; + on(event: "Target.targetCreated", listener: (message: InspectorNotification<Target.TargetCreatedEventDataType>) => void): this; + on(event: "Target.attachedToTarget", listener: (message: InspectorNotification<Target.AttachedToTargetEventDataType>) => void): this; + once(event: string, listener: (...args: any[]) => void): this; + /** + * Emitted when any notification from the V8 Inspector is received. + */ + once(event: "inspectorNotification", listener: (message: InspectorNotification<object>) => void): this; + /** + * Issued when new execution context is created. + */ + once(event: "Runtime.executionContextCreated", listener: (message: InspectorNotification<Runtime.ExecutionContextCreatedEventDataType>) => void): this; + /** + * Issued when execution context is destroyed. + */ + once(event: "Runtime.executionContextDestroyed", listener: (message: InspectorNotification<Runtime.ExecutionContextDestroyedEventDataType>) => void): this; + /** + * Issued when all executionContexts were cleared in browser + */ + once(event: "Runtime.executionContextsCleared", listener: () => void): this; + /** + * Issued when exception was thrown and unhandled. + */ + once(event: "Runtime.exceptionThrown", listener: (message: InspectorNotification<Runtime.ExceptionThrownEventDataType>) => void): this; + /** + * Issued when unhandled exception was revoked. + */ + once(event: "Runtime.exceptionRevoked", listener: (message: InspectorNotification<Runtime.ExceptionRevokedEventDataType>) => void): this; + /** + * Issued when console API was called. + */ + once(event: "Runtime.consoleAPICalled", listener: (message: InspectorNotification<Runtime.ConsoleAPICalledEventDataType>) => void): this; + /** + * Issued when object should be inspected (for example, as a result of inspect() command line API call). + */ + once(event: "Runtime.inspectRequested", listener: (message: InspectorNotification<Runtime.InspectRequestedEventDataType>) => void): this; + /** + * Fired when virtual machine parses script. This event is also fired for all known and uncollected scripts upon enabling debugger. + */ + once(event: "Debugger.scriptParsed", listener: (message: InspectorNotification<Debugger.ScriptParsedEventDataType>) => void): this; + /** + * Fired when virtual machine fails to parse the script. + */ + once(event: "Debugger.scriptFailedToParse", listener: (message: InspectorNotification<Debugger.ScriptFailedToParseEventDataType>) => void): this; + /** + * Fired when breakpoint is resolved to an actual script and location. + */ + once(event: "Debugger.breakpointResolved", listener: (message: InspectorNotification<Debugger.BreakpointResolvedEventDataType>) => void): this; + /** + * Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria. + */ + once(event: "Debugger.paused", listener: (message: InspectorNotification<Debugger.PausedEventDataType>) => void): this; + /** + * Fired when the virtual machine resumed execution. + */ + once(event: "Debugger.resumed", listener: () => void): this; + /** + * Issued when new console message is added. + */ + once(event: "Console.messageAdded", listener: (message: InspectorNotification<Console.MessageAddedEventDataType>) => void): this; + /** + * Sent when new profile recording is started using console.profile() call. + */ + once(event: "Profiler.consoleProfileStarted", listener: (message: InspectorNotification<Profiler.ConsoleProfileStartedEventDataType>) => void): this; + once(event: "Profiler.consoleProfileFinished", listener: (message: InspectorNotification<Profiler.ConsoleProfileFinishedEventDataType>) => void): this; + once(event: "HeapProfiler.addHeapSnapshotChunk", listener: (message: InspectorNotification<HeapProfiler.AddHeapSnapshotChunkEventDataType>) => void): this; + once(event: "HeapProfiler.resetProfiles", listener: () => void): this; + once(event: "HeapProfiler.reportHeapSnapshotProgress", listener: (message: InspectorNotification<HeapProfiler.ReportHeapSnapshotProgressEventDataType>) => void): this; + /** + * If heap objects tracking has been started then backend regularly sends a current value for last seen object id and corresponding timestamp. If the were changes in the heap since last event then one or more heapStatsUpdate events will be sent before a new lastSeenObjectId event. + */ + once(event: "HeapProfiler.lastSeenObjectId", listener: (message: InspectorNotification<HeapProfiler.LastSeenObjectIdEventDataType>) => void): this; + /** + * If heap objects tracking has been started then backend may send update for one or more fragments + */ + once(event: "HeapProfiler.heapStatsUpdate", listener: (message: InspectorNotification<HeapProfiler.HeapStatsUpdateEventDataType>) => void): this; + /** + * Contains an bucket of collected trace events. + */ + once(event: "NodeTracing.dataCollected", listener: (message: InspectorNotification<NodeTracing.DataCollectedEventDataType>) => void): this; + /** + * Signals that tracing is stopped and there is no trace buffers pending flush, all data were + * delivered via dataCollected events. + */ + once(event: "NodeTracing.tracingComplete", listener: () => void): this; + /** + * Issued when attached to a worker. + */ + once(event: "NodeWorker.attachedToWorker", listener: (message: InspectorNotification<NodeWorker.AttachedToWorkerEventDataType>) => void): this; + /** + * Issued when detached from the worker. + */ + once(event: "NodeWorker.detachedFromWorker", listener: (message: InspectorNotification<NodeWorker.DetachedFromWorkerEventDataType>) => void): this; + /** + * Notifies about a new protocol message received from the session + * (session ID is provided in attachedToWorker notification). + */ + once(event: "NodeWorker.receivedMessageFromWorker", listener: (message: InspectorNotification<NodeWorker.ReceivedMessageFromWorkerEventDataType>) => void): this; + /** + * Fired when page is about to send HTTP request. + */ + once(event: "Network.requestWillBeSent", listener: (message: InspectorNotification<Network.RequestWillBeSentEventDataType>) => void): this; + /** + * Fired when HTTP response is available. + */ + once(event: "Network.responseReceived", listener: (message: InspectorNotification<Network.ResponseReceivedEventDataType>) => void): this; + once(event: "Network.loadingFailed", listener: (message: InspectorNotification<Network.LoadingFailedEventDataType>) => void): this; + once(event: "Network.loadingFinished", listener: (message: InspectorNotification<Network.LoadingFinishedEventDataType>) => void): this; + /** + * Fired when data chunk was received over the network. + */ + once(event: "Network.dataReceived", listener: (message: InspectorNotification<Network.DataReceivedEventDataType>) => void): this; + /** + * Fired upon WebSocket creation. + */ + once(event: "Network.webSocketCreated", listener: (message: InspectorNotification<Network.WebSocketCreatedEventDataType>) => void): this; + /** + * Fired when WebSocket is closed. + */ + once(event: "Network.webSocketClosed", listener: (message: InspectorNotification<Network.WebSocketClosedEventDataType>) => void): this; + /** + * Fired when WebSocket handshake response becomes available. + */ + once(event: "Network.webSocketHandshakeResponseReceived", listener: (message: InspectorNotification<Network.WebSocketHandshakeResponseReceivedEventDataType>) => void): this; + /** + * This event is fired instead of `Runtime.executionContextDestroyed` when + * enabled. + * It is fired when the Node process finished all code execution and is + * waiting for all frontends to disconnect. + */ + once(event: "NodeRuntime.waitingForDisconnect", listener: () => void): this; + /** + * This event is fired when the runtime is waiting for the debugger. For + * example, when inspector.waitingForDebugger is called + */ + once(event: "NodeRuntime.waitingForDebugger", listener: () => void): this; + once(event: "Target.targetCreated", listener: (message: InspectorNotification<Target.TargetCreatedEventDataType>) => void): this; + once(event: "Target.attachedToTarget", listener: (message: InspectorNotification<Target.AttachedToTargetEventDataType>) => void): this; + prependListener(event: string, listener: (...args: any[]) => void): this; + /** + * Emitted when any notification from the V8 Inspector is received. + */ + prependListener(event: "inspectorNotification", listener: (message: InspectorNotification<object>) => void): this; + /** + * Issued when new execution context is created. + */ + prependListener(event: "Runtime.executionContextCreated", listener: (message: InspectorNotification<Runtime.ExecutionContextCreatedEventDataType>) => void): this; + /** + * Issued when execution context is destroyed. + */ + prependListener(event: "Runtime.executionContextDestroyed", listener: (message: InspectorNotification<Runtime.ExecutionContextDestroyedEventDataType>) => void): this; + /** + * Issued when all executionContexts were cleared in browser + */ + prependListener(event: "Runtime.executionContextsCleared", listener: () => void): this; + /** + * Issued when exception was thrown and unhandled. + */ + prependListener(event: "Runtime.exceptionThrown", listener: (message: InspectorNotification<Runtime.ExceptionThrownEventDataType>) => void): this; + /** + * Issued when unhandled exception was revoked. + */ + prependListener(event: "Runtime.exceptionRevoked", listener: (message: InspectorNotification<Runtime.ExceptionRevokedEventDataType>) => void): this; + /** + * Issued when console API was called. + */ + prependListener(event: "Runtime.consoleAPICalled", listener: (message: InspectorNotification<Runtime.ConsoleAPICalledEventDataType>) => void): this; + /** + * Issued when object should be inspected (for example, as a result of inspect() command line API call). + */ + prependListener(event: "Runtime.inspectRequested", listener: (message: InspectorNotification<Runtime.InspectRequestedEventDataType>) => void): this; + /** + * Fired when virtual machine parses script. This event is also fired for all known and uncollected scripts upon enabling debugger. + */ + prependListener(event: "Debugger.scriptParsed", listener: (message: InspectorNotification<Debugger.ScriptParsedEventDataType>) => void): this; + /** + * Fired when virtual machine fails to parse the script. + */ + prependListener(event: "Debugger.scriptFailedToParse", listener: (message: InspectorNotification<Debugger.ScriptFailedToParseEventDataType>) => void): this; + /** + * Fired when breakpoint is resolved to an actual script and location. + */ + prependListener(event: "Debugger.breakpointResolved", listener: (message: InspectorNotification<Debugger.BreakpointResolvedEventDataType>) => void): this; + /** + * Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria. + */ + prependListener(event: "Debugger.paused", listener: (message: InspectorNotification<Debugger.PausedEventDataType>) => void): this; + /** + * Fired when the virtual machine resumed execution. + */ + prependListener(event: "Debugger.resumed", listener: () => void): this; + /** + * Issued when new console message is added. + */ + prependListener(event: "Console.messageAdded", listener: (message: InspectorNotification<Console.MessageAddedEventDataType>) => void): this; + /** + * Sent when new profile recording is started using console.profile() call. + */ + prependListener(event: "Profiler.consoleProfileStarted", listener: (message: InspectorNotification<Profiler.ConsoleProfileStartedEventDataType>) => void): this; + prependListener(event: "Profiler.consoleProfileFinished", listener: (message: InspectorNotification<Profiler.ConsoleProfileFinishedEventDataType>) => void): this; + prependListener(event: "HeapProfiler.addHeapSnapshotChunk", listener: (message: InspectorNotification<HeapProfiler.AddHeapSnapshotChunkEventDataType>) => void): this; + prependListener(event: "HeapProfiler.resetProfiles", listener: () => void): this; + prependListener(event: "HeapProfiler.reportHeapSnapshotProgress", listener: (message: InspectorNotification<HeapProfiler.ReportHeapSnapshotProgressEventDataType>) => void): this; + /** + * If heap objects tracking has been started then backend regularly sends a current value for last seen object id and corresponding timestamp. If the were changes in the heap since last event then one or more heapStatsUpdate events will be sent before a new lastSeenObjectId event. + */ + prependListener(event: "HeapProfiler.lastSeenObjectId", listener: (message: InspectorNotification<HeapProfiler.LastSeenObjectIdEventDataType>) => void): this; + /** + * If heap objects tracking has been started then backend may send update for one or more fragments + */ + prependListener(event: "HeapProfiler.heapStatsUpdate", listener: (message: InspectorNotification<HeapProfiler.HeapStatsUpdateEventDataType>) => void): this; + /** + * Contains an bucket of collected trace events. + */ + prependListener(event: "NodeTracing.dataCollected", listener: (message: InspectorNotification<NodeTracing.DataCollectedEventDataType>) => void): this; + /** + * Signals that tracing is stopped and there is no trace buffers pending flush, all data were + * delivered via dataCollected events. + */ + prependListener(event: "NodeTracing.tracingComplete", listener: () => void): this; + /** + * Issued when attached to a worker. + */ + prependListener(event: "NodeWorker.attachedToWorker", listener: (message: InspectorNotification<NodeWorker.AttachedToWorkerEventDataType>) => void): this; + /** + * Issued when detached from the worker. + */ + prependListener(event: "NodeWorker.detachedFromWorker", listener: (message: InspectorNotification<NodeWorker.DetachedFromWorkerEventDataType>) => void): this; + /** + * Notifies about a new protocol message received from the session + * (session ID is provided in attachedToWorker notification). + */ + prependListener(event: "NodeWorker.receivedMessageFromWorker", listener: (message: InspectorNotification<NodeWorker.ReceivedMessageFromWorkerEventDataType>) => void): this; + /** + * Fired when page is about to send HTTP request. + */ + prependListener(event: "Network.requestWillBeSent", listener: (message: InspectorNotification<Network.RequestWillBeSentEventDataType>) => void): this; + /** + * Fired when HTTP response is available. + */ + prependListener(event: "Network.responseReceived", listener: (message: InspectorNotification<Network.ResponseReceivedEventDataType>) => void): this; + prependListener(event: "Network.loadingFailed", listener: (message: InspectorNotification<Network.LoadingFailedEventDataType>) => void): this; + prependListener(event: "Network.loadingFinished", listener: (message: InspectorNotification<Network.LoadingFinishedEventDataType>) => void): this; + /** + * Fired when data chunk was received over the network. + */ + prependListener(event: "Network.dataReceived", listener: (message: InspectorNotification<Network.DataReceivedEventDataType>) => void): this; + /** + * Fired upon WebSocket creation. + */ + prependListener(event: "Network.webSocketCreated", listener: (message: InspectorNotification<Network.WebSocketCreatedEventDataType>) => void): this; + /** + * Fired when WebSocket is closed. + */ + prependListener(event: "Network.webSocketClosed", listener: (message: InspectorNotification<Network.WebSocketClosedEventDataType>) => void): this; + /** + * Fired when WebSocket handshake response becomes available. + */ + prependListener(event: "Network.webSocketHandshakeResponseReceived", listener: (message: InspectorNotification<Network.WebSocketHandshakeResponseReceivedEventDataType>) => void): this; + /** + * This event is fired instead of `Runtime.executionContextDestroyed` when + * enabled. + * It is fired when the Node process finished all code execution and is + * waiting for all frontends to disconnect. + */ + prependListener(event: "NodeRuntime.waitingForDisconnect", listener: () => void): this; + /** + * This event is fired when the runtime is waiting for the debugger. For + * example, when inspector.waitingForDebugger is called + */ + prependListener(event: "NodeRuntime.waitingForDebugger", listener: () => void): this; + prependListener(event: "Target.targetCreated", listener: (message: InspectorNotification<Target.TargetCreatedEventDataType>) => void): this; + prependListener(event: "Target.attachedToTarget", listener: (message: InspectorNotification<Target.AttachedToTargetEventDataType>) => void): this; + prependOnceListener(event: string, listener: (...args: any[]) => void): this; + /** + * Emitted when any notification from the V8 Inspector is received. + */ + prependOnceListener(event: "inspectorNotification", listener: (message: InspectorNotification<object>) => void): this; + /** + * Issued when new execution context is created. + */ + prependOnceListener(event: "Runtime.executionContextCreated", listener: (message: InspectorNotification<Runtime.ExecutionContextCreatedEventDataType>) => void): this; + /** + * Issued when execution context is destroyed. + */ + prependOnceListener(event: "Runtime.executionContextDestroyed", listener: (message: InspectorNotification<Runtime.ExecutionContextDestroyedEventDataType>) => void): this; + /** + * Issued when all executionContexts were cleared in browser + */ + prependOnceListener(event: "Runtime.executionContextsCleared", listener: () => void): this; + /** + * Issued when exception was thrown and unhandled. + */ + prependOnceListener(event: "Runtime.exceptionThrown", listener: (message: InspectorNotification<Runtime.ExceptionThrownEventDataType>) => void): this; + /** + * Issued when unhandled exception was revoked. + */ + prependOnceListener(event: "Runtime.exceptionRevoked", listener: (message: InspectorNotification<Runtime.ExceptionRevokedEventDataType>) => void): this; + /** + * Issued when console API was called. + */ + prependOnceListener(event: "Runtime.consoleAPICalled", listener: (message: InspectorNotification<Runtime.ConsoleAPICalledEventDataType>) => void): this; + /** + * Issued when object should be inspected (for example, as a result of inspect() command line API call). + */ + prependOnceListener(event: "Runtime.inspectRequested", listener: (message: InspectorNotification<Runtime.InspectRequestedEventDataType>) => void): this; + /** + * Fired when virtual machine parses script. This event is also fired for all known and uncollected scripts upon enabling debugger. + */ + prependOnceListener(event: "Debugger.scriptParsed", listener: (message: InspectorNotification<Debugger.ScriptParsedEventDataType>) => void): this; + /** + * Fired when virtual machine fails to parse the script. + */ + prependOnceListener(event: "Debugger.scriptFailedToParse", listener: (message: InspectorNotification<Debugger.ScriptFailedToParseEventDataType>) => void): this; + /** + * Fired when breakpoint is resolved to an actual script and location. + */ + prependOnceListener(event: "Debugger.breakpointResolved", listener: (message: InspectorNotification<Debugger.BreakpointResolvedEventDataType>) => void): this; + /** + * Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria. + */ + prependOnceListener(event: "Debugger.paused", listener: (message: InspectorNotification<Debugger.PausedEventDataType>) => void): this; + /** + * Fired when the virtual machine resumed execution. + */ + prependOnceListener(event: "Debugger.resumed", listener: () => void): this; + /** + * Issued when new console message is added. + */ + prependOnceListener(event: "Console.messageAdded", listener: (message: InspectorNotification<Console.MessageAddedEventDataType>) => void): this; + /** + * Sent when new profile recording is started using console.profile() call. + */ + prependOnceListener(event: "Profiler.consoleProfileStarted", listener: (message: InspectorNotification<Profiler.ConsoleProfileStartedEventDataType>) => void): this; + prependOnceListener(event: "Profiler.consoleProfileFinished", listener: (message: InspectorNotification<Profiler.ConsoleProfileFinishedEventDataType>) => void): this; + prependOnceListener(event: "HeapProfiler.addHeapSnapshotChunk", listener: (message: InspectorNotification<HeapProfiler.AddHeapSnapshotChunkEventDataType>) => void): this; + prependOnceListener(event: "HeapProfiler.resetProfiles", listener: () => void): this; + prependOnceListener(event: "HeapProfiler.reportHeapSnapshotProgress", listener: (message: InspectorNotification<HeapProfiler.ReportHeapSnapshotProgressEventDataType>) => void): this; + /** + * If heap objects tracking has been started then backend regularly sends a current value for last seen object id and corresponding timestamp. If the were changes in the heap since last event then one or more heapStatsUpdate events will be sent before a new lastSeenObjectId event. + */ + prependOnceListener(event: "HeapProfiler.lastSeenObjectId", listener: (message: InspectorNotification<HeapProfiler.LastSeenObjectIdEventDataType>) => void): this; + /** + * If heap objects tracking has been started then backend may send update for one or more fragments + */ + prependOnceListener(event: "HeapProfiler.heapStatsUpdate", listener: (message: InspectorNotification<HeapProfiler.HeapStatsUpdateEventDataType>) => void): this; + /** + * Contains an bucket of collected trace events. + */ + prependOnceListener(event: "NodeTracing.dataCollected", listener: (message: InspectorNotification<NodeTracing.DataCollectedEventDataType>) => void): this; + /** + * Signals that tracing is stopped and there is no trace buffers pending flush, all data were + * delivered via dataCollected events. + */ + prependOnceListener(event: "NodeTracing.tracingComplete", listener: () => void): this; + /** + * Issued when attached to a worker. + */ + prependOnceListener(event: "NodeWorker.attachedToWorker", listener: (message: InspectorNotification<NodeWorker.AttachedToWorkerEventDataType>) => void): this; + /** + * Issued when detached from the worker. + */ + prependOnceListener(event: "NodeWorker.detachedFromWorker", listener: (message: InspectorNotification<NodeWorker.DetachedFromWorkerEventDataType>) => void): this; + /** + * Notifies about a new protocol message received from the session + * (session ID is provided in attachedToWorker notification). + */ + prependOnceListener(event: "NodeWorker.receivedMessageFromWorker", listener: (message: InspectorNotification<NodeWorker.ReceivedMessageFromWorkerEventDataType>) => void): this; + /** + * Fired when page is about to send HTTP request. + */ + prependOnceListener(event: "Network.requestWillBeSent", listener: (message: InspectorNotification<Network.RequestWillBeSentEventDataType>) => void): this; + /** + * Fired when HTTP response is available. + */ + prependOnceListener(event: "Network.responseReceived", listener: (message: InspectorNotification<Network.ResponseReceivedEventDataType>) => void): this; + prependOnceListener(event: "Network.loadingFailed", listener: (message: InspectorNotification<Network.LoadingFailedEventDataType>) => void): this; + prependOnceListener(event: "Network.loadingFinished", listener: (message: InspectorNotification<Network.LoadingFinishedEventDataType>) => void): this; + /** + * Fired when data chunk was received over the network. + */ + prependOnceListener(event: "Network.dataReceived", listener: (message: InspectorNotification<Network.DataReceivedEventDataType>) => void): this; + /** + * Fired upon WebSocket creation. + */ + prependOnceListener(event: "Network.webSocketCreated", listener: (message: InspectorNotification<Network.WebSocketCreatedEventDataType>) => void): this; + /** + * Fired when WebSocket is closed. + */ + prependOnceListener(event: "Network.webSocketClosed", listener: (message: InspectorNotification<Network.WebSocketClosedEventDataType>) => void): this; + /** + * Fired when WebSocket handshake response becomes available. + */ + prependOnceListener(event: "Network.webSocketHandshakeResponseReceived", listener: (message: InspectorNotification<Network.WebSocketHandshakeResponseReceivedEventDataType>) => void): this; + /** + * This event is fired instead of `Runtime.executionContextDestroyed` when + * enabled. + * It is fired when the Node process finished all code execution and is + * waiting for all frontends to disconnect. + */ + prependOnceListener(event: "NodeRuntime.waitingForDisconnect", listener: () => void): this; + /** + * This event is fired when the runtime is waiting for the debugger. For + * example, when inspector.waitingForDebugger is called + */ + prependOnceListener(event: "NodeRuntime.waitingForDebugger", listener: () => void): this; + prependOnceListener(event: "Target.targetCreated", listener: (message: InspectorNotification<Target.TargetCreatedEventDataType>) => void): this; + prependOnceListener(event: "Target.attachedToTarget", listener: (message: InspectorNotification<Target.AttachedToTargetEventDataType>) => void): this; + } +} +declare module "node:inspector/promises" { + export { + Schema, + Runtime, + Debugger, + Console, + Profiler, + HeapProfiler, + NodeTracing, + NodeWorker, + Network, + NodeRuntime, + Target, + IO, + } from 'inspector'; +} +declare module "node:inspector/promises" { + import { + InspectorNotification, + Schema, + Runtime, + Debugger, + Console, + Profiler, + HeapProfiler, + NodeTracing, + NodeWorker, + Network, + NodeRuntime, + Target, + IO, + } from "inspector"; + /** + * The `inspector.Session` is used for dispatching messages to the V8 inspector + * back-end and receiving message responses and notifications. + * @since v19.0.0 + */ + interface Session { + /** + * Posts a message to the inspector back-end. + * + * ```js + * import { Session } from 'node:inspector/promises'; + * try { + * const session = new Session(); + * session.connect(); + * const result = await session.post('Runtime.evaluate', { expression: '2 + 2' }); + * console.log(result); + * } catch (error) { + * console.error(error); + * } + * // Output: { result: { type: 'number', value: 4, description: '4' } } + * ``` + * + * The latest version of the V8 inspector protocol is published on the + * [Chrome DevTools Protocol Viewer](https://chromedevtools.github.io/devtools-protocol/v8/). + * + * Node.js inspector supports all the Chrome DevTools Protocol domains declared + * by V8. Chrome DevTools Protocol domain provides an interface for interacting + * with one of the runtime agents used to inspect the application state and listen + * to the run-time events. + */ + post(method: string, params?: object): Promise<void>; + /** + * Returns supported domains. + */ + post(method: "Schema.getDomains"): Promise<Schema.GetDomainsReturnType>; + /** + * Evaluates expression on global object. + */ + post(method: "Runtime.evaluate", params?: Runtime.EvaluateParameterType): Promise<Runtime.EvaluateReturnType>; + /** + * Add handler to promise with given promise object id. + */ + post(method: "Runtime.awaitPromise", params?: Runtime.AwaitPromiseParameterType): Promise<Runtime.AwaitPromiseReturnType>; + /** + * Calls function with given declaration on the given object. Object group of the result is inherited from the target object. + */ + post(method: "Runtime.callFunctionOn", params?: Runtime.CallFunctionOnParameterType): Promise<Runtime.CallFunctionOnReturnType>; + /** + * Returns properties of a given object. Object group of the result is inherited from the target object. + */ + post(method: "Runtime.getProperties", params?: Runtime.GetPropertiesParameterType): Promise<Runtime.GetPropertiesReturnType>; + /** + * Releases remote object with given id. + */ + post(method: "Runtime.releaseObject", params?: Runtime.ReleaseObjectParameterType): Promise<void>; + /** + * Releases all remote objects that belong to a given group. + */ + post(method: "Runtime.releaseObjectGroup", params?: Runtime.ReleaseObjectGroupParameterType): Promise<void>; + /** + * Tells inspected instance to run if it was waiting for debugger to attach. + */ + post(method: "Runtime.runIfWaitingForDebugger"): Promise<void>; + /** + * Enables reporting of execution contexts creation by means of <code>executionContextCreated</code> event. When the reporting gets enabled the event will be sent immediately for each existing execution context. + */ + post(method: "Runtime.enable"): Promise<void>; + /** + * Disables reporting of execution contexts creation. + */ + post(method: "Runtime.disable"): Promise<void>; + /** + * Discards collected exceptions and console API calls. + */ + post(method: "Runtime.discardConsoleEntries"): Promise<void>; + /** + * @experimental + */ + post(method: "Runtime.setCustomObjectFormatterEnabled", params?: Runtime.SetCustomObjectFormatterEnabledParameterType): Promise<void>; + /** + * Compiles expression. + */ + post(method: "Runtime.compileScript", params?: Runtime.CompileScriptParameterType): Promise<Runtime.CompileScriptReturnType>; + /** + * Runs script with given id in a given context. + */ + post(method: "Runtime.runScript", params?: Runtime.RunScriptParameterType): Promise<Runtime.RunScriptReturnType>; + post(method: "Runtime.queryObjects", params?: Runtime.QueryObjectsParameterType): Promise<Runtime.QueryObjectsReturnType>; + /** + * Returns all let, const and class variables from global scope. + */ + post(method: "Runtime.globalLexicalScopeNames", params?: Runtime.GlobalLexicalScopeNamesParameterType): Promise<Runtime.GlobalLexicalScopeNamesReturnType>; + /** + * Enables debugger for the given page. Clients should not assume that the debugging has been enabled until the result for this command is received. + */ + post(method: "Debugger.enable"): Promise<Debugger.EnableReturnType>; + /** + * Disables debugger for given page. + */ + post(method: "Debugger.disable"): Promise<void>; + /** + * Activates / deactivates all breakpoints on the page. + */ + post(method: "Debugger.setBreakpointsActive", params?: Debugger.SetBreakpointsActiveParameterType): Promise<void>; + /** + * Makes page not interrupt on any pauses (breakpoint, exception, dom exception etc). + */ + post(method: "Debugger.setSkipAllPauses", params?: Debugger.SetSkipAllPausesParameterType): Promise<void>; + /** + * Sets JavaScript breakpoint at given location specified either by URL or URL regex. Once this command is issued, all existing parsed scripts will have breakpoints resolved and returned in <code>locations</code> property. Further matching script parsing will result in subsequent <code>breakpointResolved</code> events issued. This logical breakpoint will survive page reloads. + */ + post(method: "Debugger.setBreakpointByUrl", params?: Debugger.SetBreakpointByUrlParameterType): Promise<Debugger.SetBreakpointByUrlReturnType>; + /** + * Sets JavaScript breakpoint at a given location. + */ + post(method: "Debugger.setBreakpoint", params?: Debugger.SetBreakpointParameterType): Promise<Debugger.SetBreakpointReturnType>; + /** + * Removes JavaScript breakpoint. + */ + post(method: "Debugger.removeBreakpoint", params?: Debugger.RemoveBreakpointParameterType): Promise<void>; + /** + * Returns possible locations for breakpoint. scriptId in start and end range locations should be the same. + */ + post(method: "Debugger.getPossibleBreakpoints", params?: Debugger.GetPossibleBreakpointsParameterType): Promise<Debugger.GetPossibleBreakpointsReturnType>; + /** + * Continues execution until specific location is reached. + */ + post(method: "Debugger.continueToLocation", params?: Debugger.ContinueToLocationParameterType): Promise<void>; + /** + * @experimental + */ + post(method: "Debugger.pauseOnAsyncCall", params?: Debugger.PauseOnAsyncCallParameterType): Promise<void>; + /** + * Steps over the statement. + */ + post(method: "Debugger.stepOver"): Promise<void>; + /** + * Steps into the function call. + */ + post(method: "Debugger.stepInto", params?: Debugger.StepIntoParameterType): Promise<void>; + /** + * Steps out of the function call. + */ + post(method: "Debugger.stepOut"): Promise<void>; + /** + * Stops on the next JavaScript statement. + */ + post(method: "Debugger.pause"): Promise<void>; + /** + * This method is deprecated - use Debugger.stepInto with breakOnAsyncCall and Debugger.pauseOnAsyncTask instead. Steps into next scheduled async task if any is scheduled before next pause. Returns success when async task is actually scheduled, returns error if no task were scheduled or another scheduleStepIntoAsync was called. + * @experimental + */ + post(method: "Debugger.scheduleStepIntoAsync"): Promise<void>; + /** + * Resumes JavaScript execution. + */ + post(method: "Debugger.resume"): Promise<void>; + /** + * Returns stack trace with given <code>stackTraceId</code>. + * @experimental + */ + post(method: "Debugger.getStackTrace", params?: Debugger.GetStackTraceParameterType): Promise<Debugger.GetStackTraceReturnType>; + /** + * Searches for given string in script content. + */ + post(method: "Debugger.searchInContent", params?: Debugger.SearchInContentParameterType): Promise<Debugger.SearchInContentReturnType>; + /** + * Edits JavaScript source live. + */ + post(method: "Debugger.setScriptSource", params?: Debugger.SetScriptSourceParameterType): Promise<Debugger.SetScriptSourceReturnType>; + /** + * Restarts particular call frame from the beginning. + */ + post(method: "Debugger.restartFrame", params?: Debugger.RestartFrameParameterType): Promise<Debugger.RestartFrameReturnType>; + /** + * Returns source for the script with given id. + */ + post(method: "Debugger.getScriptSource", params?: Debugger.GetScriptSourceParameterType): Promise<Debugger.GetScriptSourceReturnType>; + /** + * Defines pause on exceptions state. Can be set to stop on all exceptions, uncaught exceptions or no exceptions. Initial pause on exceptions state is <code>none</code>. + */ + post(method: "Debugger.setPauseOnExceptions", params?: Debugger.SetPauseOnExceptionsParameterType): Promise<void>; + /** + * Evaluates expression on a given call frame. + */ + post(method: "Debugger.evaluateOnCallFrame", params?: Debugger.EvaluateOnCallFrameParameterType): Promise<Debugger.EvaluateOnCallFrameReturnType>; + /** + * Changes value of variable in a callframe. Object-based scopes are not supported and must be mutated manually. + */ + post(method: "Debugger.setVariableValue", params?: Debugger.SetVariableValueParameterType): Promise<void>; + /** + * Changes return value in top frame. Available only at return break position. + * @experimental + */ + post(method: "Debugger.setReturnValue", params?: Debugger.SetReturnValueParameterType): Promise<void>; + /** + * Enables or disables async call stacks tracking. + */ + post(method: "Debugger.setAsyncCallStackDepth", params?: Debugger.SetAsyncCallStackDepthParameterType): Promise<void>; + /** + * Replace previous blackbox patterns with passed ones. Forces backend to skip stepping/pausing in scripts with url matching one of the patterns. VM will try to leave blackboxed script by performing 'step in' several times, finally resorting to 'step out' if unsuccessful. + * @experimental + */ + post(method: "Debugger.setBlackboxPatterns", params?: Debugger.SetBlackboxPatternsParameterType): Promise<void>; + /** + * Makes backend skip steps in the script in blackboxed ranges. VM will try leave blacklisted scripts by performing 'step in' several times, finally resorting to 'step out' if unsuccessful. Positions array contains positions where blackbox state is changed. First interval isn't blackboxed. Array should be sorted. + * @experimental + */ + post(method: "Debugger.setBlackboxedRanges", params?: Debugger.SetBlackboxedRangesParameterType): Promise<void>; + /** + * Enables console domain, sends the messages collected so far to the client by means of the <code>messageAdded</code> notification. + */ + post(method: "Console.enable"): Promise<void>; + /** + * Disables console domain, prevents further console messages from being reported to the client. + */ + post(method: "Console.disable"): Promise<void>; + /** + * Does nothing. + */ + post(method: "Console.clearMessages"): Promise<void>; + post(method: "Profiler.enable"): Promise<void>; + post(method: "Profiler.disable"): Promise<void>; + /** + * Changes CPU profiler sampling interval. Must be called before CPU profiles recording started. + */ + post(method: "Profiler.setSamplingInterval", params?: Profiler.SetSamplingIntervalParameterType): Promise<void>; + post(method: "Profiler.start"): Promise<void>; + post(method: "Profiler.stop"): Promise<Profiler.StopReturnType>; + /** + * Enable precise code coverage. Coverage data for JavaScript executed before enabling precise code coverage may be incomplete. Enabling prevents running optimized code and resets execution counters. + */ + post(method: "Profiler.startPreciseCoverage", params?: Profiler.StartPreciseCoverageParameterType): Promise<void>; + /** + * Disable precise code coverage. Disabling releases unnecessary execution count records and allows executing optimized code. + */ + post(method: "Profiler.stopPreciseCoverage"): Promise<void>; + /** + * Collect coverage data for the current isolate, and resets execution counters. Precise code coverage needs to have started. + */ + post(method: "Profiler.takePreciseCoverage"): Promise<Profiler.TakePreciseCoverageReturnType>; + /** + * Collect coverage data for the current isolate. The coverage data may be incomplete due to garbage collection. + */ + post(method: "Profiler.getBestEffortCoverage"): Promise<Profiler.GetBestEffortCoverageReturnType>; + post(method: "HeapProfiler.enable"): Promise<void>; + post(method: "HeapProfiler.disable"): Promise<void>; + post(method: "HeapProfiler.startTrackingHeapObjects", params?: HeapProfiler.StartTrackingHeapObjectsParameterType): Promise<void>; + post(method: "HeapProfiler.stopTrackingHeapObjects", params?: HeapProfiler.StopTrackingHeapObjectsParameterType): Promise<void>; + post(method: "HeapProfiler.takeHeapSnapshot", params?: HeapProfiler.TakeHeapSnapshotParameterType): Promise<void>; + post(method: "HeapProfiler.collectGarbage"): Promise<void>; + post(method: "HeapProfiler.getObjectByHeapObjectId", params?: HeapProfiler.GetObjectByHeapObjectIdParameterType): Promise<HeapProfiler.GetObjectByHeapObjectIdReturnType>; + /** + * Enables console to refer to the node with given id via $x (see Command Line API for more details $x functions). + */ + post(method: "HeapProfiler.addInspectedHeapObject", params?: HeapProfiler.AddInspectedHeapObjectParameterType): Promise<void>; + post(method: "HeapProfiler.getHeapObjectId", params?: HeapProfiler.GetHeapObjectIdParameterType): Promise<HeapProfiler.GetHeapObjectIdReturnType>; + post(method: "HeapProfiler.startSampling", params?: HeapProfiler.StartSamplingParameterType): Promise<void>; + post(method: "HeapProfiler.stopSampling"): Promise<HeapProfiler.StopSamplingReturnType>; + post(method: "HeapProfiler.getSamplingProfile"): Promise<HeapProfiler.GetSamplingProfileReturnType>; + /** + * Gets supported tracing categories. + */ + post(method: "NodeTracing.getCategories"): Promise<NodeTracing.GetCategoriesReturnType>; + /** + * Start trace events collection. + */ + post(method: "NodeTracing.start", params?: NodeTracing.StartParameterType): Promise<void>; + /** + * Stop trace events collection. Remaining collected events will be sent as a sequence of + * dataCollected events followed by tracingComplete event. + */ + post(method: "NodeTracing.stop"): Promise<void>; + /** + * Sends protocol message over session with given id. + */ + post(method: "NodeWorker.sendMessageToWorker", params?: NodeWorker.SendMessageToWorkerParameterType): Promise<void>; + /** + * Instructs the inspector to attach to running workers. Will also attach to new workers + * as they start + */ + post(method: "NodeWorker.enable", params?: NodeWorker.EnableParameterType): Promise<void>; + /** + * Detaches from all running workers and disables attaching to new workers as they are started. + */ + post(method: "NodeWorker.disable"): Promise<void>; + /** + * Detached from the worker with given sessionId. + */ + post(method: "NodeWorker.detach", params?: NodeWorker.DetachParameterType): Promise<void>; + /** + * Disables network tracking, prevents network events from being sent to the client. + */ + post(method: "Network.disable"): Promise<void>; + /** + * Enables network tracking, network events will now be delivered to the client. + */ + post(method: "Network.enable"): Promise<void>; + /** + * Returns post data sent with the request. Returns an error when no data was sent with the request. + */ + post(method: "Network.getRequestPostData", params?: Network.GetRequestPostDataParameterType): Promise<Network.GetRequestPostDataReturnType>; + /** + * Returns content served for the given request. + */ + post(method: "Network.getResponseBody", params?: Network.GetResponseBodyParameterType): Promise<Network.GetResponseBodyReturnType>; + /** + * Enables streaming of the response for the given requestId. + * If enabled, the dataReceived event contains the data that was received during streaming. + * @experimental + */ + post(method: "Network.streamResourceContent", params?: Network.StreamResourceContentParameterType): Promise<Network.StreamResourceContentReturnType>; + /** + * Fetches the resource and returns the content. + */ + post(method: "Network.loadNetworkResource", params?: Network.LoadNetworkResourceParameterType): Promise<Network.LoadNetworkResourceReturnType>; + /** + * Enable the NodeRuntime events except by `NodeRuntime.waitingForDisconnect`. + */ + post(method: "NodeRuntime.enable"): Promise<void>; + /** + * Disable NodeRuntime events + */ + post(method: "NodeRuntime.disable"): Promise<void>; + /** + * Enable the `NodeRuntime.waitingForDisconnect`. + */ + post(method: "NodeRuntime.notifyWhenWaitingForDisconnect", params?: NodeRuntime.NotifyWhenWaitingForDisconnectParameterType): Promise<void>; + post(method: "Target.setAutoAttach", params?: Target.SetAutoAttachParameterType): Promise<void>; + /** + * Read a chunk of the stream + */ + post(method: "IO.read", params?: IO.ReadParameterType): Promise<IO.ReadReturnType>; + post(method: "IO.close", params?: IO.CloseParameterType): Promise<void>; + addListener(event: string, listener: (...args: any[]) => void): this; + /** + * Emitted when any notification from the V8 Inspector is received. + */ + addListener(event: "inspectorNotification", listener: (message: InspectorNotification<object>) => void): this; + /** + * Issued when new execution context is created. + */ + addListener(event: "Runtime.executionContextCreated", listener: (message: InspectorNotification<Runtime.ExecutionContextCreatedEventDataType>) => void): this; + /** + * Issued when execution context is destroyed. + */ + addListener(event: "Runtime.executionContextDestroyed", listener: (message: InspectorNotification<Runtime.ExecutionContextDestroyedEventDataType>) => void): this; + /** + * Issued when all executionContexts were cleared in browser + */ + addListener(event: "Runtime.executionContextsCleared", listener: () => void): this; + /** + * Issued when exception was thrown and unhandled. + */ + addListener(event: "Runtime.exceptionThrown", listener: (message: InspectorNotification<Runtime.ExceptionThrownEventDataType>) => void): this; + /** + * Issued when unhandled exception was revoked. + */ + addListener(event: "Runtime.exceptionRevoked", listener: (message: InspectorNotification<Runtime.ExceptionRevokedEventDataType>) => void): this; + /** + * Issued when console API was called. + */ + addListener(event: "Runtime.consoleAPICalled", listener: (message: InspectorNotification<Runtime.ConsoleAPICalledEventDataType>) => void): this; + /** + * Issued when object should be inspected (for example, as a result of inspect() command line API call). + */ + addListener(event: "Runtime.inspectRequested", listener: (message: InspectorNotification<Runtime.InspectRequestedEventDataType>) => void): this; + /** + * Fired when virtual machine parses script. This event is also fired for all known and uncollected scripts upon enabling debugger. + */ + addListener(event: "Debugger.scriptParsed", listener: (message: InspectorNotification<Debugger.ScriptParsedEventDataType>) => void): this; + /** + * Fired when virtual machine fails to parse the script. + */ + addListener(event: "Debugger.scriptFailedToParse", listener: (message: InspectorNotification<Debugger.ScriptFailedToParseEventDataType>) => void): this; + /** + * Fired when breakpoint is resolved to an actual script and location. + */ + addListener(event: "Debugger.breakpointResolved", listener: (message: InspectorNotification<Debugger.BreakpointResolvedEventDataType>) => void): this; + /** + * Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria. + */ + addListener(event: "Debugger.paused", listener: (message: InspectorNotification<Debugger.PausedEventDataType>) => void): this; + /** + * Fired when the virtual machine resumed execution. + */ + addListener(event: "Debugger.resumed", listener: () => void): this; + /** + * Issued when new console message is added. + */ + addListener(event: "Console.messageAdded", listener: (message: InspectorNotification<Console.MessageAddedEventDataType>) => void): this; + /** + * Sent when new profile recording is started using console.profile() call. + */ + addListener(event: "Profiler.consoleProfileStarted", listener: (message: InspectorNotification<Profiler.ConsoleProfileStartedEventDataType>) => void): this; + addListener(event: "Profiler.consoleProfileFinished", listener: (message: InspectorNotification<Profiler.ConsoleProfileFinishedEventDataType>) => void): this; + addListener(event: "HeapProfiler.addHeapSnapshotChunk", listener: (message: InspectorNotification<HeapProfiler.AddHeapSnapshotChunkEventDataType>) => void): this; + addListener(event: "HeapProfiler.resetProfiles", listener: () => void): this; + addListener(event: "HeapProfiler.reportHeapSnapshotProgress", listener: (message: InspectorNotification<HeapProfiler.ReportHeapSnapshotProgressEventDataType>) => void): this; + /** + * If heap objects tracking has been started then backend regularly sends a current value for last seen object id and corresponding timestamp. If the were changes in the heap since last event then one or more heapStatsUpdate events will be sent before a new lastSeenObjectId event. + */ + addListener(event: "HeapProfiler.lastSeenObjectId", listener: (message: InspectorNotification<HeapProfiler.LastSeenObjectIdEventDataType>) => void): this; + /** + * If heap objects tracking has been started then backend may send update for one or more fragments + */ + addListener(event: "HeapProfiler.heapStatsUpdate", listener: (message: InspectorNotification<HeapProfiler.HeapStatsUpdateEventDataType>) => void): this; + /** + * Contains an bucket of collected trace events. + */ + addListener(event: "NodeTracing.dataCollected", listener: (message: InspectorNotification<NodeTracing.DataCollectedEventDataType>) => void): this; + /** + * Signals that tracing is stopped and there is no trace buffers pending flush, all data were + * delivered via dataCollected events. + */ + addListener(event: "NodeTracing.tracingComplete", listener: () => void): this; + /** + * Issued when attached to a worker. + */ + addListener(event: "NodeWorker.attachedToWorker", listener: (message: InspectorNotification<NodeWorker.AttachedToWorkerEventDataType>) => void): this; + /** + * Issued when detached from the worker. + */ + addListener(event: "NodeWorker.detachedFromWorker", listener: (message: InspectorNotification<NodeWorker.DetachedFromWorkerEventDataType>) => void): this; + /** + * Notifies about a new protocol message received from the session + * (session ID is provided in attachedToWorker notification). + */ + addListener(event: "NodeWorker.receivedMessageFromWorker", listener: (message: InspectorNotification<NodeWorker.ReceivedMessageFromWorkerEventDataType>) => void): this; + /** + * Fired when page is about to send HTTP request. + */ + addListener(event: "Network.requestWillBeSent", listener: (message: InspectorNotification<Network.RequestWillBeSentEventDataType>) => void): this; + /** + * Fired when HTTP response is available. + */ + addListener(event: "Network.responseReceived", listener: (message: InspectorNotification<Network.ResponseReceivedEventDataType>) => void): this; + addListener(event: "Network.loadingFailed", listener: (message: InspectorNotification<Network.LoadingFailedEventDataType>) => void): this; + addListener(event: "Network.loadingFinished", listener: (message: InspectorNotification<Network.LoadingFinishedEventDataType>) => void): this; + /** + * Fired when data chunk was received over the network. + */ + addListener(event: "Network.dataReceived", listener: (message: InspectorNotification<Network.DataReceivedEventDataType>) => void): this; + /** + * Fired upon WebSocket creation. + */ + addListener(event: "Network.webSocketCreated", listener: (message: InspectorNotification<Network.WebSocketCreatedEventDataType>) => void): this; + /** + * Fired when WebSocket is closed. + */ + addListener(event: "Network.webSocketClosed", listener: (message: InspectorNotification<Network.WebSocketClosedEventDataType>) => void): this; + /** + * Fired when WebSocket handshake response becomes available. + */ + addListener(event: "Network.webSocketHandshakeResponseReceived", listener: (message: InspectorNotification<Network.WebSocketHandshakeResponseReceivedEventDataType>) => void): this; + /** + * This event is fired instead of `Runtime.executionContextDestroyed` when + * enabled. + * It is fired when the Node process finished all code execution and is + * waiting for all frontends to disconnect. + */ + addListener(event: "NodeRuntime.waitingForDisconnect", listener: () => void): this; + /** + * This event is fired when the runtime is waiting for the debugger. For + * example, when inspector.waitingForDebugger is called + */ + addListener(event: "NodeRuntime.waitingForDebugger", listener: () => void): this; + addListener(event: "Target.targetCreated", listener: (message: InspectorNotification<Target.TargetCreatedEventDataType>) => void): this; + addListener(event: "Target.attachedToTarget", listener: (message: InspectorNotification<Target.AttachedToTargetEventDataType>) => void): this; + emit(event: string | symbol, ...args: any[]): boolean; + emit(event: "inspectorNotification", message: InspectorNotification<object>): boolean; + emit(event: "Runtime.executionContextCreated", message: InspectorNotification<Runtime.ExecutionContextCreatedEventDataType>): boolean; + emit(event: "Runtime.executionContextDestroyed", message: InspectorNotification<Runtime.ExecutionContextDestroyedEventDataType>): boolean; + emit(event: "Runtime.executionContextsCleared"): boolean; + emit(event: "Runtime.exceptionThrown", message: InspectorNotification<Runtime.ExceptionThrownEventDataType>): boolean; + emit(event: "Runtime.exceptionRevoked", message: InspectorNotification<Runtime.ExceptionRevokedEventDataType>): boolean; + emit(event: "Runtime.consoleAPICalled", message: InspectorNotification<Runtime.ConsoleAPICalledEventDataType>): boolean; + emit(event: "Runtime.inspectRequested", message: InspectorNotification<Runtime.InspectRequestedEventDataType>): boolean; + emit(event: "Debugger.scriptParsed", message: InspectorNotification<Debugger.ScriptParsedEventDataType>): boolean; + emit(event: "Debugger.scriptFailedToParse", message: InspectorNotification<Debugger.ScriptFailedToParseEventDataType>): boolean; + emit(event: "Debugger.breakpointResolved", message: InspectorNotification<Debugger.BreakpointResolvedEventDataType>): boolean; + emit(event: "Debugger.paused", message: InspectorNotification<Debugger.PausedEventDataType>): boolean; + emit(event: "Debugger.resumed"): boolean; + emit(event: "Console.messageAdded", message: InspectorNotification<Console.MessageAddedEventDataType>): boolean; + emit(event: "Profiler.consoleProfileStarted", message: InspectorNotification<Profiler.ConsoleProfileStartedEventDataType>): boolean; + emit(event: "Profiler.consoleProfileFinished", message: InspectorNotification<Profiler.ConsoleProfileFinishedEventDataType>): boolean; + emit(event: "HeapProfiler.addHeapSnapshotChunk", message: InspectorNotification<HeapProfiler.AddHeapSnapshotChunkEventDataType>): boolean; + emit(event: "HeapProfiler.resetProfiles"): boolean; + emit(event: "HeapProfiler.reportHeapSnapshotProgress", message: InspectorNotification<HeapProfiler.ReportHeapSnapshotProgressEventDataType>): boolean; + emit(event: "HeapProfiler.lastSeenObjectId", message: InspectorNotification<HeapProfiler.LastSeenObjectIdEventDataType>): boolean; + emit(event: "HeapProfiler.heapStatsUpdate", message: InspectorNotification<HeapProfiler.HeapStatsUpdateEventDataType>): boolean; + emit(event: "NodeTracing.dataCollected", message: InspectorNotification<NodeTracing.DataCollectedEventDataType>): boolean; + emit(event: "NodeTracing.tracingComplete"): boolean; + emit(event: "NodeWorker.attachedToWorker", message: InspectorNotification<NodeWorker.AttachedToWorkerEventDataType>): boolean; + emit(event: "NodeWorker.detachedFromWorker", message: InspectorNotification<NodeWorker.DetachedFromWorkerEventDataType>): boolean; + emit(event: "NodeWorker.receivedMessageFromWorker", message: InspectorNotification<NodeWorker.ReceivedMessageFromWorkerEventDataType>): boolean; + emit(event: "Network.requestWillBeSent", message: InspectorNotification<Network.RequestWillBeSentEventDataType>): boolean; + emit(event: "Network.responseReceived", message: InspectorNotification<Network.ResponseReceivedEventDataType>): boolean; + emit(event: "Network.loadingFailed", message: InspectorNotification<Network.LoadingFailedEventDataType>): boolean; + emit(event: "Network.loadingFinished", message: InspectorNotification<Network.LoadingFinishedEventDataType>): boolean; + emit(event: "Network.dataReceived", message: InspectorNotification<Network.DataReceivedEventDataType>): boolean; + emit(event: "Network.webSocketCreated", message: InspectorNotification<Network.WebSocketCreatedEventDataType>): boolean; + emit(event: "Network.webSocketClosed", message: InspectorNotification<Network.WebSocketClosedEventDataType>): boolean; + emit(event: "Network.webSocketHandshakeResponseReceived", message: InspectorNotification<Network.WebSocketHandshakeResponseReceivedEventDataType>): boolean; + emit(event: "NodeRuntime.waitingForDisconnect"): boolean; + emit(event: "NodeRuntime.waitingForDebugger"): boolean; + emit(event: "Target.targetCreated", message: InspectorNotification<Target.TargetCreatedEventDataType>): boolean; + emit(event: "Target.attachedToTarget", message: InspectorNotification<Target.AttachedToTargetEventDataType>): boolean; + on(event: string, listener: (...args: any[]) => void): this; + /** + * Emitted when any notification from the V8 Inspector is received. + */ + on(event: "inspectorNotification", listener: (message: InspectorNotification<object>) => void): this; + /** + * Issued when new execution context is created. + */ + on(event: "Runtime.executionContextCreated", listener: (message: InspectorNotification<Runtime.ExecutionContextCreatedEventDataType>) => void): this; + /** + * Issued when execution context is destroyed. + */ + on(event: "Runtime.executionContextDestroyed", listener: (message: InspectorNotification<Runtime.ExecutionContextDestroyedEventDataType>) => void): this; + /** + * Issued when all executionContexts were cleared in browser + */ + on(event: "Runtime.executionContextsCleared", listener: () => void): this; + /** + * Issued when exception was thrown and unhandled. + */ + on(event: "Runtime.exceptionThrown", listener: (message: InspectorNotification<Runtime.ExceptionThrownEventDataType>) => void): this; + /** + * Issued when unhandled exception was revoked. + */ + on(event: "Runtime.exceptionRevoked", listener: (message: InspectorNotification<Runtime.ExceptionRevokedEventDataType>) => void): this; + /** + * Issued when console API was called. + */ + on(event: "Runtime.consoleAPICalled", listener: (message: InspectorNotification<Runtime.ConsoleAPICalledEventDataType>) => void): this; + /** + * Issued when object should be inspected (for example, as a result of inspect() command line API call). + */ + on(event: "Runtime.inspectRequested", listener: (message: InspectorNotification<Runtime.InspectRequestedEventDataType>) => void): this; + /** + * Fired when virtual machine parses script. This event is also fired for all known and uncollected scripts upon enabling debugger. + */ + on(event: "Debugger.scriptParsed", listener: (message: InspectorNotification<Debugger.ScriptParsedEventDataType>) => void): this; + /** + * Fired when virtual machine fails to parse the script. + */ + on(event: "Debugger.scriptFailedToParse", listener: (message: InspectorNotification<Debugger.ScriptFailedToParseEventDataType>) => void): this; + /** + * Fired when breakpoint is resolved to an actual script and location. + */ + on(event: "Debugger.breakpointResolved", listener: (message: InspectorNotification<Debugger.BreakpointResolvedEventDataType>) => void): this; + /** + * Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria. + */ + on(event: "Debugger.paused", listener: (message: InspectorNotification<Debugger.PausedEventDataType>) => void): this; + /** + * Fired when the virtual machine resumed execution. + */ + on(event: "Debugger.resumed", listener: () => void): this; + /** + * Issued when new console message is added. + */ + on(event: "Console.messageAdded", listener: (message: InspectorNotification<Console.MessageAddedEventDataType>) => void): this; + /** + * Sent when new profile recording is started using console.profile() call. + */ + on(event: "Profiler.consoleProfileStarted", listener: (message: InspectorNotification<Profiler.ConsoleProfileStartedEventDataType>) => void): this; + on(event: "Profiler.consoleProfileFinished", listener: (message: InspectorNotification<Profiler.ConsoleProfileFinishedEventDataType>) => void): this; + on(event: "HeapProfiler.addHeapSnapshotChunk", listener: (message: InspectorNotification<HeapProfiler.AddHeapSnapshotChunkEventDataType>) => void): this; + on(event: "HeapProfiler.resetProfiles", listener: () => void): this; + on(event: "HeapProfiler.reportHeapSnapshotProgress", listener: (message: InspectorNotification<HeapProfiler.ReportHeapSnapshotProgressEventDataType>) => void): this; + /** + * If heap objects tracking has been started then backend regularly sends a current value for last seen object id and corresponding timestamp. If the were changes in the heap since last event then one or more heapStatsUpdate events will be sent before a new lastSeenObjectId event. + */ + on(event: "HeapProfiler.lastSeenObjectId", listener: (message: InspectorNotification<HeapProfiler.LastSeenObjectIdEventDataType>) => void): this; + /** + * If heap objects tracking has been started then backend may send update for one or more fragments + */ + on(event: "HeapProfiler.heapStatsUpdate", listener: (message: InspectorNotification<HeapProfiler.HeapStatsUpdateEventDataType>) => void): this; + /** + * Contains an bucket of collected trace events. + */ + on(event: "NodeTracing.dataCollected", listener: (message: InspectorNotification<NodeTracing.DataCollectedEventDataType>) => void): this; + /** + * Signals that tracing is stopped and there is no trace buffers pending flush, all data were + * delivered via dataCollected events. + */ + on(event: "NodeTracing.tracingComplete", listener: () => void): this; + /** + * Issued when attached to a worker. + */ + on(event: "NodeWorker.attachedToWorker", listener: (message: InspectorNotification<NodeWorker.AttachedToWorkerEventDataType>) => void): this; + /** + * Issued when detached from the worker. + */ + on(event: "NodeWorker.detachedFromWorker", listener: (message: InspectorNotification<NodeWorker.DetachedFromWorkerEventDataType>) => void): this; + /** + * Notifies about a new protocol message received from the session + * (session ID is provided in attachedToWorker notification). + */ + on(event: "NodeWorker.receivedMessageFromWorker", listener: (message: InspectorNotification<NodeWorker.ReceivedMessageFromWorkerEventDataType>) => void): this; + /** + * Fired when page is about to send HTTP request. + */ + on(event: "Network.requestWillBeSent", listener: (message: InspectorNotification<Network.RequestWillBeSentEventDataType>) => void): this; + /** + * Fired when HTTP response is available. + */ + on(event: "Network.responseReceived", listener: (message: InspectorNotification<Network.ResponseReceivedEventDataType>) => void): this; + on(event: "Network.loadingFailed", listener: (message: InspectorNotification<Network.LoadingFailedEventDataType>) => void): this; + on(event: "Network.loadingFinished", listener: (message: InspectorNotification<Network.LoadingFinishedEventDataType>) => void): this; + /** + * Fired when data chunk was received over the network. + */ + on(event: "Network.dataReceived", listener: (message: InspectorNotification<Network.DataReceivedEventDataType>) => void): this; + /** + * Fired upon WebSocket creation. + */ + on(event: "Network.webSocketCreated", listener: (message: InspectorNotification<Network.WebSocketCreatedEventDataType>) => void): this; + /** + * Fired when WebSocket is closed. + */ + on(event: "Network.webSocketClosed", listener: (message: InspectorNotification<Network.WebSocketClosedEventDataType>) => void): this; + /** + * Fired when WebSocket handshake response becomes available. + */ + on(event: "Network.webSocketHandshakeResponseReceived", listener: (message: InspectorNotification<Network.WebSocketHandshakeResponseReceivedEventDataType>) => void): this; + /** + * This event is fired instead of `Runtime.executionContextDestroyed` when + * enabled. + * It is fired when the Node process finished all code execution and is + * waiting for all frontends to disconnect. + */ + on(event: "NodeRuntime.waitingForDisconnect", listener: () => void): this; + /** + * This event is fired when the runtime is waiting for the debugger. For + * example, when inspector.waitingForDebugger is called + */ + on(event: "NodeRuntime.waitingForDebugger", listener: () => void): this; + on(event: "Target.targetCreated", listener: (message: InspectorNotification<Target.TargetCreatedEventDataType>) => void): this; + on(event: "Target.attachedToTarget", listener: (message: InspectorNotification<Target.AttachedToTargetEventDataType>) => void): this; + once(event: string, listener: (...args: any[]) => void): this; + /** + * Emitted when any notification from the V8 Inspector is received. + */ + once(event: "inspectorNotification", listener: (message: InspectorNotification<object>) => void): this; + /** + * Issued when new execution context is created. + */ + once(event: "Runtime.executionContextCreated", listener: (message: InspectorNotification<Runtime.ExecutionContextCreatedEventDataType>) => void): this; + /** + * Issued when execution context is destroyed. + */ + once(event: "Runtime.executionContextDestroyed", listener: (message: InspectorNotification<Runtime.ExecutionContextDestroyedEventDataType>) => void): this; + /** + * Issued when all executionContexts were cleared in browser + */ + once(event: "Runtime.executionContextsCleared", listener: () => void): this; + /** + * Issued when exception was thrown and unhandled. + */ + once(event: "Runtime.exceptionThrown", listener: (message: InspectorNotification<Runtime.ExceptionThrownEventDataType>) => void): this; + /** + * Issued when unhandled exception was revoked. + */ + once(event: "Runtime.exceptionRevoked", listener: (message: InspectorNotification<Runtime.ExceptionRevokedEventDataType>) => void): this; + /** + * Issued when console API was called. + */ + once(event: "Runtime.consoleAPICalled", listener: (message: InspectorNotification<Runtime.ConsoleAPICalledEventDataType>) => void): this; + /** + * Issued when object should be inspected (for example, as a result of inspect() command line API call). + */ + once(event: "Runtime.inspectRequested", listener: (message: InspectorNotification<Runtime.InspectRequestedEventDataType>) => void): this; + /** + * Fired when virtual machine parses script. This event is also fired for all known and uncollected scripts upon enabling debugger. + */ + once(event: "Debugger.scriptParsed", listener: (message: InspectorNotification<Debugger.ScriptParsedEventDataType>) => void): this; + /** + * Fired when virtual machine fails to parse the script. + */ + once(event: "Debugger.scriptFailedToParse", listener: (message: InspectorNotification<Debugger.ScriptFailedToParseEventDataType>) => void): this; + /** + * Fired when breakpoint is resolved to an actual script and location. + */ + once(event: "Debugger.breakpointResolved", listener: (message: InspectorNotification<Debugger.BreakpointResolvedEventDataType>) => void): this; + /** + * Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria. + */ + once(event: "Debugger.paused", listener: (message: InspectorNotification<Debugger.PausedEventDataType>) => void): this; + /** + * Fired when the virtual machine resumed execution. + */ + once(event: "Debugger.resumed", listener: () => void): this; + /** + * Issued when new console message is added. + */ + once(event: "Console.messageAdded", listener: (message: InspectorNotification<Console.MessageAddedEventDataType>) => void): this; + /** + * Sent when new profile recording is started using console.profile() call. + */ + once(event: "Profiler.consoleProfileStarted", listener: (message: InspectorNotification<Profiler.ConsoleProfileStartedEventDataType>) => void): this; + once(event: "Profiler.consoleProfileFinished", listener: (message: InspectorNotification<Profiler.ConsoleProfileFinishedEventDataType>) => void): this; + once(event: "HeapProfiler.addHeapSnapshotChunk", listener: (message: InspectorNotification<HeapProfiler.AddHeapSnapshotChunkEventDataType>) => void): this; + once(event: "HeapProfiler.resetProfiles", listener: () => void): this; + once(event: "HeapProfiler.reportHeapSnapshotProgress", listener: (message: InspectorNotification<HeapProfiler.ReportHeapSnapshotProgressEventDataType>) => void): this; + /** + * If heap objects tracking has been started then backend regularly sends a current value for last seen object id and corresponding timestamp. If the were changes in the heap since last event then one or more heapStatsUpdate events will be sent before a new lastSeenObjectId event. + */ + once(event: "HeapProfiler.lastSeenObjectId", listener: (message: InspectorNotification<HeapProfiler.LastSeenObjectIdEventDataType>) => void): this; + /** + * If heap objects tracking has been started then backend may send update for one or more fragments + */ + once(event: "HeapProfiler.heapStatsUpdate", listener: (message: InspectorNotification<HeapProfiler.HeapStatsUpdateEventDataType>) => void): this; + /** + * Contains an bucket of collected trace events. + */ + once(event: "NodeTracing.dataCollected", listener: (message: InspectorNotification<NodeTracing.DataCollectedEventDataType>) => void): this; + /** + * Signals that tracing is stopped and there is no trace buffers pending flush, all data were + * delivered via dataCollected events. + */ + once(event: "NodeTracing.tracingComplete", listener: () => void): this; + /** + * Issued when attached to a worker. + */ + once(event: "NodeWorker.attachedToWorker", listener: (message: InspectorNotification<NodeWorker.AttachedToWorkerEventDataType>) => void): this; + /** + * Issued when detached from the worker. + */ + once(event: "NodeWorker.detachedFromWorker", listener: (message: InspectorNotification<NodeWorker.DetachedFromWorkerEventDataType>) => void): this; + /** + * Notifies about a new protocol message received from the session + * (session ID is provided in attachedToWorker notification). + */ + once(event: "NodeWorker.receivedMessageFromWorker", listener: (message: InspectorNotification<NodeWorker.ReceivedMessageFromWorkerEventDataType>) => void): this; + /** + * Fired when page is about to send HTTP request. + */ + once(event: "Network.requestWillBeSent", listener: (message: InspectorNotification<Network.RequestWillBeSentEventDataType>) => void): this; + /** + * Fired when HTTP response is available. + */ + once(event: "Network.responseReceived", listener: (message: InspectorNotification<Network.ResponseReceivedEventDataType>) => void): this; + once(event: "Network.loadingFailed", listener: (message: InspectorNotification<Network.LoadingFailedEventDataType>) => void): this; + once(event: "Network.loadingFinished", listener: (message: InspectorNotification<Network.LoadingFinishedEventDataType>) => void): this; + /** + * Fired when data chunk was received over the network. + */ + once(event: "Network.dataReceived", listener: (message: InspectorNotification<Network.DataReceivedEventDataType>) => void): this; + /** + * Fired upon WebSocket creation. + */ + once(event: "Network.webSocketCreated", listener: (message: InspectorNotification<Network.WebSocketCreatedEventDataType>) => void): this; + /** + * Fired when WebSocket is closed. + */ + once(event: "Network.webSocketClosed", listener: (message: InspectorNotification<Network.WebSocketClosedEventDataType>) => void): this; + /** + * Fired when WebSocket handshake response becomes available. + */ + once(event: "Network.webSocketHandshakeResponseReceived", listener: (message: InspectorNotification<Network.WebSocketHandshakeResponseReceivedEventDataType>) => void): this; + /** + * This event is fired instead of `Runtime.executionContextDestroyed` when + * enabled. + * It is fired when the Node process finished all code execution and is + * waiting for all frontends to disconnect. + */ + once(event: "NodeRuntime.waitingForDisconnect", listener: () => void): this; + /** + * This event is fired when the runtime is waiting for the debugger. For + * example, when inspector.waitingForDebugger is called + */ + once(event: "NodeRuntime.waitingForDebugger", listener: () => void): this; + once(event: "Target.targetCreated", listener: (message: InspectorNotification<Target.TargetCreatedEventDataType>) => void): this; + once(event: "Target.attachedToTarget", listener: (message: InspectorNotification<Target.AttachedToTargetEventDataType>) => void): this; + prependListener(event: string, listener: (...args: any[]) => void): this; + /** + * Emitted when any notification from the V8 Inspector is received. + */ + prependListener(event: "inspectorNotification", listener: (message: InspectorNotification<object>) => void): this; + /** + * Issued when new execution context is created. + */ + prependListener(event: "Runtime.executionContextCreated", listener: (message: InspectorNotification<Runtime.ExecutionContextCreatedEventDataType>) => void): this; + /** + * Issued when execution context is destroyed. + */ + prependListener(event: "Runtime.executionContextDestroyed", listener: (message: InspectorNotification<Runtime.ExecutionContextDestroyedEventDataType>) => void): this; + /** + * Issued when all executionContexts were cleared in browser + */ + prependListener(event: "Runtime.executionContextsCleared", listener: () => void): this; + /** + * Issued when exception was thrown and unhandled. + */ + prependListener(event: "Runtime.exceptionThrown", listener: (message: InspectorNotification<Runtime.ExceptionThrownEventDataType>) => void): this; + /** + * Issued when unhandled exception was revoked. + */ + prependListener(event: "Runtime.exceptionRevoked", listener: (message: InspectorNotification<Runtime.ExceptionRevokedEventDataType>) => void): this; + /** + * Issued when console API was called. + */ + prependListener(event: "Runtime.consoleAPICalled", listener: (message: InspectorNotification<Runtime.ConsoleAPICalledEventDataType>) => void): this; + /** + * Issued when object should be inspected (for example, as a result of inspect() command line API call). + */ + prependListener(event: "Runtime.inspectRequested", listener: (message: InspectorNotification<Runtime.InspectRequestedEventDataType>) => void): this; + /** + * Fired when virtual machine parses script. This event is also fired for all known and uncollected scripts upon enabling debugger. + */ + prependListener(event: "Debugger.scriptParsed", listener: (message: InspectorNotification<Debugger.ScriptParsedEventDataType>) => void): this; + /** + * Fired when virtual machine fails to parse the script. + */ + prependListener(event: "Debugger.scriptFailedToParse", listener: (message: InspectorNotification<Debugger.ScriptFailedToParseEventDataType>) => void): this; + /** + * Fired when breakpoint is resolved to an actual script and location. + */ + prependListener(event: "Debugger.breakpointResolved", listener: (message: InspectorNotification<Debugger.BreakpointResolvedEventDataType>) => void): this; + /** + * Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria. + */ + prependListener(event: "Debugger.paused", listener: (message: InspectorNotification<Debugger.PausedEventDataType>) => void): this; + /** + * Fired when the virtual machine resumed execution. + */ + prependListener(event: "Debugger.resumed", listener: () => void): this; + /** + * Issued when new console message is added. + */ + prependListener(event: "Console.messageAdded", listener: (message: InspectorNotification<Console.MessageAddedEventDataType>) => void): this; + /** + * Sent when new profile recording is started using console.profile() call. + */ + prependListener(event: "Profiler.consoleProfileStarted", listener: (message: InspectorNotification<Profiler.ConsoleProfileStartedEventDataType>) => void): this; + prependListener(event: "Profiler.consoleProfileFinished", listener: (message: InspectorNotification<Profiler.ConsoleProfileFinishedEventDataType>) => void): this; + prependListener(event: "HeapProfiler.addHeapSnapshotChunk", listener: (message: InspectorNotification<HeapProfiler.AddHeapSnapshotChunkEventDataType>) => void): this; + prependListener(event: "HeapProfiler.resetProfiles", listener: () => void): this; + prependListener(event: "HeapProfiler.reportHeapSnapshotProgress", listener: (message: InspectorNotification<HeapProfiler.ReportHeapSnapshotProgressEventDataType>) => void): this; + /** + * If heap objects tracking has been started then backend regularly sends a current value for last seen object id and corresponding timestamp. If the were changes in the heap since last event then one or more heapStatsUpdate events will be sent before a new lastSeenObjectId event. + */ + prependListener(event: "HeapProfiler.lastSeenObjectId", listener: (message: InspectorNotification<HeapProfiler.LastSeenObjectIdEventDataType>) => void): this; + /** + * If heap objects tracking has been started then backend may send update for one or more fragments + */ + prependListener(event: "HeapProfiler.heapStatsUpdate", listener: (message: InspectorNotification<HeapProfiler.HeapStatsUpdateEventDataType>) => void): this; + /** + * Contains an bucket of collected trace events. + */ + prependListener(event: "NodeTracing.dataCollected", listener: (message: InspectorNotification<NodeTracing.DataCollectedEventDataType>) => void): this; + /** + * Signals that tracing is stopped and there is no trace buffers pending flush, all data were + * delivered via dataCollected events. + */ + prependListener(event: "NodeTracing.tracingComplete", listener: () => void): this; + /** + * Issued when attached to a worker. + */ + prependListener(event: "NodeWorker.attachedToWorker", listener: (message: InspectorNotification<NodeWorker.AttachedToWorkerEventDataType>) => void): this; + /** + * Issued when detached from the worker. + */ + prependListener(event: "NodeWorker.detachedFromWorker", listener: (message: InspectorNotification<NodeWorker.DetachedFromWorkerEventDataType>) => void): this; + /** + * Notifies about a new protocol message received from the session + * (session ID is provided in attachedToWorker notification). + */ + prependListener(event: "NodeWorker.receivedMessageFromWorker", listener: (message: InspectorNotification<NodeWorker.ReceivedMessageFromWorkerEventDataType>) => void): this; + /** + * Fired when page is about to send HTTP request. + */ + prependListener(event: "Network.requestWillBeSent", listener: (message: InspectorNotification<Network.RequestWillBeSentEventDataType>) => void): this; + /** + * Fired when HTTP response is available. + */ + prependListener(event: "Network.responseReceived", listener: (message: InspectorNotification<Network.ResponseReceivedEventDataType>) => void): this; + prependListener(event: "Network.loadingFailed", listener: (message: InspectorNotification<Network.LoadingFailedEventDataType>) => void): this; + prependListener(event: "Network.loadingFinished", listener: (message: InspectorNotification<Network.LoadingFinishedEventDataType>) => void): this; + /** + * Fired when data chunk was received over the network. + */ + prependListener(event: "Network.dataReceived", listener: (message: InspectorNotification<Network.DataReceivedEventDataType>) => void): this; + /** + * Fired upon WebSocket creation. + */ + prependListener(event: "Network.webSocketCreated", listener: (message: InspectorNotification<Network.WebSocketCreatedEventDataType>) => void): this; + /** + * Fired when WebSocket is closed. + */ + prependListener(event: "Network.webSocketClosed", listener: (message: InspectorNotification<Network.WebSocketClosedEventDataType>) => void): this; + /** + * Fired when WebSocket handshake response becomes available. + */ + prependListener(event: "Network.webSocketHandshakeResponseReceived", listener: (message: InspectorNotification<Network.WebSocketHandshakeResponseReceivedEventDataType>) => void): this; + /** + * This event is fired instead of `Runtime.executionContextDestroyed` when + * enabled. + * It is fired when the Node process finished all code execution and is + * waiting for all frontends to disconnect. + */ + prependListener(event: "NodeRuntime.waitingForDisconnect", listener: () => void): this; + /** + * This event is fired when the runtime is waiting for the debugger. For + * example, when inspector.waitingForDebugger is called + */ + prependListener(event: "NodeRuntime.waitingForDebugger", listener: () => void): this; + prependListener(event: "Target.targetCreated", listener: (message: InspectorNotification<Target.TargetCreatedEventDataType>) => void): this; + prependListener(event: "Target.attachedToTarget", listener: (message: InspectorNotification<Target.AttachedToTargetEventDataType>) => void): this; + prependOnceListener(event: string, listener: (...args: any[]) => void): this; + /** + * Emitted when any notification from the V8 Inspector is received. + */ + prependOnceListener(event: "inspectorNotification", listener: (message: InspectorNotification<object>) => void): this; + /** + * Issued when new execution context is created. + */ + prependOnceListener(event: "Runtime.executionContextCreated", listener: (message: InspectorNotification<Runtime.ExecutionContextCreatedEventDataType>) => void): this; + /** + * Issued when execution context is destroyed. + */ + prependOnceListener(event: "Runtime.executionContextDestroyed", listener: (message: InspectorNotification<Runtime.ExecutionContextDestroyedEventDataType>) => void): this; + /** + * Issued when all executionContexts were cleared in browser + */ + prependOnceListener(event: "Runtime.executionContextsCleared", listener: () => void): this; + /** + * Issued when exception was thrown and unhandled. + */ + prependOnceListener(event: "Runtime.exceptionThrown", listener: (message: InspectorNotification<Runtime.ExceptionThrownEventDataType>) => void): this; + /** + * Issued when unhandled exception was revoked. + */ + prependOnceListener(event: "Runtime.exceptionRevoked", listener: (message: InspectorNotification<Runtime.ExceptionRevokedEventDataType>) => void): this; + /** + * Issued when console API was called. + */ + prependOnceListener(event: "Runtime.consoleAPICalled", listener: (message: InspectorNotification<Runtime.ConsoleAPICalledEventDataType>) => void): this; + /** + * Issued when object should be inspected (for example, as a result of inspect() command line API call). + */ + prependOnceListener(event: "Runtime.inspectRequested", listener: (message: InspectorNotification<Runtime.InspectRequestedEventDataType>) => void): this; + /** + * Fired when virtual machine parses script. This event is also fired for all known and uncollected scripts upon enabling debugger. + */ + prependOnceListener(event: "Debugger.scriptParsed", listener: (message: InspectorNotification<Debugger.ScriptParsedEventDataType>) => void): this; + /** + * Fired when virtual machine fails to parse the script. + */ + prependOnceListener(event: "Debugger.scriptFailedToParse", listener: (message: InspectorNotification<Debugger.ScriptFailedToParseEventDataType>) => void): this; + /** + * Fired when breakpoint is resolved to an actual script and location. + */ + prependOnceListener(event: "Debugger.breakpointResolved", listener: (message: InspectorNotification<Debugger.BreakpointResolvedEventDataType>) => void): this; + /** + * Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria. + */ + prependOnceListener(event: "Debugger.paused", listener: (message: InspectorNotification<Debugger.PausedEventDataType>) => void): this; + /** + * Fired when the virtual machine resumed execution. + */ + prependOnceListener(event: "Debugger.resumed", listener: () => void): this; + /** + * Issued when new console message is added. + */ + prependOnceListener(event: "Console.messageAdded", listener: (message: InspectorNotification<Console.MessageAddedEventDataType>) => void): this; + /** + * Sent when new profile recording is started using console.profile() call. + */ + prependOnceListener(event: "Profiler.consoleProfileStarted", listener: (message: InspectorNotification<Profiler.ConsoleProfileStartedEventDataType>) => void): this; + prependOnceListener(event: "Profiler.consoleProfileFinished", listener: (message: InspectorNotification<Profiler.ConsoleProfileFinishedEventDataType>) => void): this; + prependOnceListener(event: "HeapProfiler.addHeapSnapshotChunk", listener: (message: InspectorNotification<HeapProfiler.AddHeapSnapshotChunkEventDataType>) => void): this; + prependOnceListener(event: "HeapProfiler.resetProfiles", listener: () => void): this; + prependOnceListener(event: "HeapProfiler.reportHeapSnapshotProgress", listener: (message: InspectorNotification<HeapProfiler.ReportHeapSnapshotProgressEventDataType>) => void): this; + /** + * If heap objects tracking has been started then backend regularly sends a current value for last seen object id and corresponding timestamp. If the were changes in the heap since last event then one or more heapStatsUpdate events will be sent before a new lastSeenObjectId event. + */ + prependOnceListener(event: "HeapProfiler.lastSeenObjectId", listener: (message: InspectorNotification<HeapProfiler.LastSeenObjectIdEventDataType>) => void): this; + /** + * If heap objects tracking has been started then backend may send update for one or more fragments + */ + prependOnceListener(event: "HeapProfiler.heapStatsUpdate", listener: (message: InspectorNotification<HeapProfiler.HeapStatsUpdateEventDataType>) => void): this; + /** + * Contains an bucket of collected trace events. + */ + prependOnceListener(event: "NodeTracing.dataCollected", listener: (message: InspectorNotification<NodeTracing.DataCollectedEventDataType>) => void): this; + /** + * Signals that tracing is stopped and there is no trace buffers pending flush, all data were + * delivered via dataCollected events. + */ + prependOnceListener(event: "NodeTracing.tracingComplete", listener: () => void): this; + /** + * Issued when attached to a worker. + */ + prependOnceListener(event: "NodeWorker.attachedToWorker", listener: (message: InspectorNotification<NodeWorker.AttachedToWorkerEventDataType>) => void): this; + /** + * Issued when detached from the worker. + */ + prependOnceListener(event: "NodeWorker.detachedFromWorker", listener: (message: InspectorNotification<NodeWorker.DetachedFromWorkerEventDataType>) => void): this; + /** + * Notifies about a new protocol message received from the session + * (session ID is provided in attachedToWorker notification). + */ + prependOnceListener(event: "NodeWorker.receivedMessageFromWorker", listener: (message: InspectorNotification<NodeWorker.ReceivedMessageFromWorkerEventDataType>) => void): this; + /** + * Fired when page is about to send HTTP request. + */ + prependOnceListener(event: "Network.requestWillBeSent", listener: (message: InspectorNotification<Network.RequestWillBeSentEventDataType>) => void): this; + /** + * Fired when HTTP response is available. + */ + prependOnceListener(event: "Network.responseReceived", listener: (message: InspectorNotification<Network.ResponseReceivedEventDataType>) => void): this; + prependOnceListener(event: "Network.loadingFailed", listener: (message: InspectorNotification<Network.LoadingFailedEventDataType>) => void): this; + prependOnceListener(event: "Network.loadingFinished", listener: (message: InspectorNotification<Network.LoadingFinishedEventDataType>) => void): this; + /** + * Fired when data chunk was received over the network. + */ + prependOnceListener(event: "Network.dataReceived", listener: (message: InspectorNotification<Network.DataReceivedEventDataType>) => void): this; + /** + * Fired upon WebSocket creation. + */ + prependOnceListener(event: "Network.webSocketCreated", listener: (message: InspectorNotification<Network.WebSocketCreatedEventDataType>) => void): this; + /** + * Fired when WebSocket is closed. + */ + prependOnceListener(event: "Network.webSocketClosed", listener: (message: InspectorNotification<Network.WebSocketClosedEventDataType>) => void): this; + /** + * Fired when WebSocket handshake response becomes available. + */ + prependOnceListener(event: "Network.webSocketHandshakeResponseReceived", listener: (message: InspectorNotification<Network.WebSocketHandshakeResponseReceivedEventDataType>) => void): this; + /** + * This event is fired instead of `Runtime.executionContextDestroyed` when + * enabled. + * It is fired when the Node process finished all code execution and is + * waiting for all frontends to disconnect. + */ + prependOnceListener(event: "NodeRuntime.waitingForDisconnect", listener: () => void): this; + /** + * This event is fired when the runtime is waiting for the debugger. For + * example, when inspector.waitingForDebugger is called + */ + prependOnceListener(event: "NodeRuntime.waitingForDebugger", listener: () => void): this; + prependOnceListener(event: "Target.targetCreated", listener: (message: InspectorNotification<Target.TargetCreatedEventDataType>) => void): this; + prependOnceListener(event: "Target.attachedToTarget", listener: (message: InspectorNotification<Target.AttachedToTargetEventDataType>) => void): this; + } +} diff --git a/server/node_modules/@types/node/inspector/promises.d.ts b/server/node_modules/@types/node/inspector/promises.d.ts new file mode 100644 index 0000000..54e1250 --- /dev/null +++ b/server/node_modules/@types/node/inspector/promises.d.ts @@ -0,0 +1,41 @@ +/** + * The `node:inspector/promises` module provides an API for interacting with the V8 + * inspector. + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/inspector/promises.js) + * @since v19.0.0 + */ +declare module "node:inspector/promises" { + import { EventEmitter } from "node:events"; + export { close, console, NetworkResources, open, url, waitForDebugger } from "node:inspector"; + /** + * The `inspector.Session` is used for dispatching messages to the V8 inspector + * back-end and receiving message responses and notifications. + * @since v19.0.0 + */ + export class Session extends EventEmitter { + /** + * Create a new instance of the inspector.Session class. + * The inspector session needs to be connected through `session.connect()` before the messages can be dispatched to the inspector backend. + */ + constructor(); + /** + * Connects a session to the inspector back-end. + */ + connect(): void; + /** + * Connects a session to the inspector back-end. + * An exception will be thrown if this API was not called on a Worker thread. + * @since v12.11.0 + */ + connectToMainThread(): void; + /** + * Immediately close the session. All pending message callbacks will be called with an error. + * `session.connect()` will need to be called to be able to send messages again. + * Reconnected session will lose all inspector state, such as enabled agents or configured breakpoints. + */ + disconnect(): void; + } +} +declare module "inspector/promises" { + export * from "node:inspector/promises"; +} diff --git a/server/node_modules/@types/node/module.d.ts b/server/node_modules/@types/node/module.d.ts new file mode 100644 index 0000000..14c898f --- /dev/null +++ b/server/node_modules/@types/node/module.d.ts @@ -0,0 +1,819 @@ +/** + * @since v0.3.7 + */ +declare module "node:module" { + import { URL } from "node:url"; + class Module { + constructor(id: string, parent?: Module); + } + interface Module extends NodeJS.Module {} + namespace Module { + export { Module }; + } + namespace Module { + /** + * A list of the names of all modules provided by Node.js. Can be used to verify + * if a module is maintained by a third party or not. + * + * Note: the list doesn't contain prefix-only modules like `node:test`. + * @since v9.3.0, v8.10.0, v6.13.0 + */ + const builtinModules: readonly string[]; + /** + * @since v12.2.0 + * @param path Filename to be used to construct the require + * function. Must be a file URL object, file URL string, or absolute path + * string. + */ + function createRequire(path: string | URL): NodeJS.Require; + namespace constants { + /** + * The following constants are returned as the `status` field in the object returned by + * {@link enableCompileCache} to indicate the result of the attempt to enable the + * [module compile cache](https://nodejs.org/docs/latest-v25.x/api/module.html#module-compile-cache). + * @since v22.8.0 + */ + namespace compileCacheStatus { + /** + * Node.js has enabled the compile cache successfully. The directory used to store the + * compile cache will be returned in the `directory` field in the + * returned object. + */ + const ENABLED: number; + /** + * The compile cache has already been enabled before, either by a previous call to + * {@link enableCompileCache}, or by the `NODE_COMPILE_CACHE=dir` + * environment variable. The directory used to store the + * compile cache will be returned in the `directory` field in the + * returned object. + */ + const ALREADY_ENABLED: number; + /** + * Node.js fails to enable the compile cache. This can be caused by the lack of + * permission to use the specified directory, or various kinds of file system errors. + * The detail of the failure will be returned in the `message` field in the + * returned object. + */ + const FAILED: number; + /** + * Node.js cannot enable the compile cache because the environment variable + * `NODE_DISABLE_COMPILE_CACHE=1` has been set. + */ + const DISABLED: number; + } + } + interface EnableCompileCacheOptions { + /** + * Optional. Directory to store the compile cache. If not specified, + * the directory specified by the `NODE_COMPILE_CACHE=dir` environment variable + * will be used if it's set, or `path.join(os.tmpdir(), 'node-compile-cache')` + * otherwise. + * @since v25.0.0 + */ + directory?: string | undefined; + /** + * Optional. If `true`, enables portable compile cache so that + * the cache can be reused even if the project directory is moved. This is a best-effort + * feature. If not specified, it will depend on whether the environment variable + * `NODE_COMPILE_CACHE_PORTABLE=1` is set. + * @since v25.0.0 + */ + portable?: boolean | undefined; + } + interface EnableCompileCacheResult { + /** + * One of the {@link constants.compileCacheStatus} + */ + status: number; + /** + * If Node.js cannot enable the compile cache, this contains + * the error message. Only set if `status` is `module.constants.compileCacheStatus.FAILED`. + */ + message?: string; + /** + * If the compile cache is enabled, this contains the directory + * where the compile cache is stored. Only set if `status` is + * `module.constants.compileCacheStatus.ENABLED` or + * `module.constants.compileCacheStatus.ALREADY_ENABLED`. + */ + directory?: string; + } + /** + * Enable [module compile cache](https://nodejs.org/docs/latest-v25.x/api/module.html#module-compile-cache) + * in the current Node.js instance. + * + * For general use cases, it's recommended to call `module.enableCompileCache()` without + * specifying the `options.directory`, so that the directory can be overridden by the + * `NODE_COMPILE_CACHE` environment variable when necessary. + * + * Since compile cache is supposed to be a optimization that is not mission critical, this + * method is designed to not throw any exception when the compile cache cannot be enabled. + * Instead, it will return an object containing an error message in the `message` field to + * aid debugging. If compile cache is enabled successfully, the `directory` field in the + * returned object contains the path to the directory where the compile cache is stored. The + * `status` field in the returned object would be one of the `module.constants.compileCacheStatus` + * values to indicate the result of the attempt to enable the + * [module compile cache](https://nodejs.org/docs/latest-v25.x/api/module.html#module-compile-cache). + * + * This method only affects the current Node.js instance. To enable it in child worker threads, + * either call this method in child worker threads too, or set the + * `process.env.NODE_COMPILE_CACHE` value to compile cache directory so the behavior can + * be inherited into the child workers. The directory can be obtained either from the + * `directory` field returned by this method, or with {@link getCompileCacheDir}. + * @since v22.8.0 + * @param options Optional. If a string is passed, it is considered to be `options.directory`. + */ + function enableCompileCache(options?: string | EnableCompileCacheOptions): EnableCompileCacheResult; + /** + * Flush the [module compile cache](https://nodejs.org/docs/latest-v25.x/api/module.html#module-compile-cache) + * accumulated from modules already loaded + * in the current Node.js instance to disk. This returns after all the flushing + * file system operations come to an end, no matter they succeed or not. If there + * are any errors, this will fail silently, since compile cache misses should not + * interfere with the actual operation of the application. + * @since v22.10.0 + */ + function flushCompileCache(): void; + /** + * @since v22.8.0 + * @return Path to the [module compile cache](https://nodejs.org/docs/latest-v25.x/api/module.html#module-compile-cache) + * directory if it is enabled, or `undefined` otherwise. + */ + function getCompileCacheDir(): string | undefined; + /** + * ```text + * /path/to/project + * ├ packages/ + * ├ bar/ + * ├ bar.js + * └ package.json // name = '@foo/bar' + * └ qux/ + * ├ node_modules/ + * └ some-package/ + * └ package.json // name = 'some-package' + * ├ qux.js + * └ package.json // name = '@foo/qux' + * ├ main.js + * └ package.json // name = '@foo' + * ``` + * ```js + * // /path/to/project/packages/bar/bar.js + * import { findPackageJSON } from 'node:module'; + * + * findPackageJSON('..', import.meta.url); + * // '/path/to/project/package.json' + * // Same result when passing an absolute specifier instead: + * findPackageJSON(new URL('../', import.meta.url)); + * findPackageJSON(import.meta.resolve('../')); + * + * findPackageJSON('some-package', import.meta.url); + * // '/path/to/project/packages/bar/node_modules/some-package/package.json' + * // When passing an absolute specifier, you might get a different result if the + * // resolved module is inside a subfolder that has nested `package.json`. + * findPackageJSON(import.meta.resolve('some-package')); + * // '/path/to/project/packages/bar/node_modules/some-package/some-subfolder/package.json' + * + * findPackageJSON('@foo/qux', import.meta.url); + * // '/path/to/project/packages/qux/package.json' + * ``` + * @since v22.14.0 + * @param specifier The specifier for the module whose `package.json` to + * retrieve. When passing a _bare specifier_, the `package.json` at the root of + * the package is returned. When passing a _relative specifier_ or an _absolute specifier_, + * the closest parent `package.json` is returned. + * @param base The absolute location (`file:` URL string or FS path) of the + * containing module. For CJS, use `__filename` (not `__dirname`!); for ESM, use + * `import.meta.url`. You do not need to pass it if `specifier` is an _absolute specifier_. + * @returns A path if the `package.json` is found. When `startLocation` + * is a package, the package's root `package.json`; when a relative or unresolved, the closest + * `package.json` to the `startLocation`. + */ + function findPackageJSON(specifier: string | URL, base?: string | URL): string | undefined; + /** + * @since v18.6.0, v16.17.0 + */ + function isBuiltin(moduleName: string): boolean; + interface RegisterOptions<Data> { + /** + * If you want to resolve `specifier` relative to a + * base URL, such as `import.meta.url`, you can pass that URL here. This + * property is ignored if the `parentURL` is supplied as the second argument. + * @default 'data:' + */ + parentURL?: string | URL | undefined; + /** + * Any arbitrary, cloneable JavaScript value to pass into the + * {@link initialize} hook. + */ + data?: Data | undefined; + /** + * [Transferable objects](https://nodejs.org/docs/latest-v25.x/api/worker_threads.html#portpostmessagevalue-transferlist) + * to be passed into the `initialize` hook. + */ + transferList?: any[] | undefined; + } + /* eslint-disable @definitelytyped/no-unnecessary-generics */ + /** + * Register a module that exports hooks that customize Node.js module + * resolution and loading behavior. See + * [Customization hooks](https://nodejs.org/docs/latest-v25.x/api/module.html#customization-hooks). + * + * This feature requires `--allow-worker` if used with the + * [Permission Model](https://nodejs.org/docs/latest-v25.x/api/permissions.html#permission-model). + * @since v20.6.0, v18.19.0 + * @param specifier Customization hooks to be registered; this should be + * the same string that would be passed to `import()`, except that if it is + * relative, it is resolved relative to `parentURL`. + * @param parentURL f you want to resolve `specifier` relative to a base + * URL, such as `import.meta.url`, you can pass that URL here. + */ + function register<Data = any>( + specifier: string | URL, + parentURL?: string | URL, + options?: RegisterOptions<Data>, + ): void; + function register<Data = any>(specifier: string | URL, options?: RegisterOptions<Data>): void; + interface RegisterHooksOptions { + /** + * See [load hook](https://nodejs.org/docs/latest-v25.x/api/module.html#loadurl-context-nextload). + * @default undefined + */ + load?: LoadHookSync | undefined; + /** + * See [resolve hook](https://nodejs.org/docs/latest-v25.x/api/module.html#resolvespecifier-context-nextresolve). + * @default undefined + */ + resolve?: ResolveHookSync | undefined; + } + interface ModuleHooks { + /** + * Deregister the hook instance. + */ + deregister(): void; + } + /** + * Register [hooks](https://nodejs.org/docs/latest-v25.x/api/module.html#customization-hooks) + * that customize Node.js module resolution and loading behavior. + * @since v22.15.0 + * @experimental + */ + function registerHooks(options: RegisterHooksOptions): ModuleHooks; + interface StripTypeScriptTypesOptions { + /** + * Possible values are: + * * `'strip'` Only strip type annotations without performing the transformation of TypeScript features. + * * `'transform'` Strip type annotations and transform TypeScript features to JavaScript. + * @default 'strip' + */ + mode?: "strip" | "transform" | undefined; + /** + * Only when `mode` is `'transform'`, if `true`, a source map + * will be generated for the transformed code. + * @default false + */ + sourceMap?: boolean | undefined; + /** + * Specifies the source url used in the source map. + */ + sourceUrl?: string | undefined; + } + /** + * `module.stripTypeScriptTypes()` removes type annotations from TypeScript code. It + * can be used to strip type annotations from TypeScript code before running it + * with `vm.runInContext()` or `vm.compileFunction()`. + * By default, it will throw an error if the code contains TypeScript features + * that require transformation such as `Enums`, + * see [type-stripping](https://nodejs.org/docs/latest-v25.x/api/typescript.md#type-stripping) for more information. + * When mode is `'transform'`, it also transforms TypeScript features to JavaScript, + * see [transform TypeScript features](https://nodejs.org/docs/latest-v25.x/api/typescript.md#typescript-features) for more information. + * When mode is `'strip'`, source maps are not generated, because locations are preserved. + * If `sourceMap` is provided, when mode is `'strip'`, an error will be thrown. + * + * _WARNING_: The output of this function should not be considered stable across Node.js versions, + * due to changes in the TypeScript parser. + * + * ```js + * import { stripTypeScriptTypes } from 'node:module'; + * const code = 'const a: number = 1;'; + * const strippedCode = stripTypeScriptTypes(code); + * console.log(strippedCode); + * // Prints: const a = 1; + * ``` + * + * If `sourceUrl` is provided, it will be used appended as a comment at the end of the output: + * + * ```js + * import { stripTypeScriptTypes } from 'node:module'; + * const code = 'const a: number = 1;'; + * const strippedCode = stripTypeScriptTypes(code, { mode: 'strip', sourceUrl: 'source.ts' }); + * console.log(strippedCode); + * // Prints: const a = 1\n\n//# sourceURL=source.ts; + * ``` + * + * When `mode` is `'transform'`, the code is transformed to JavaScript: + * + * ```js + * import { stripTypeScriptTypes } from 'node:module'; + * const code = ` + * namespace MathUtil { + * export const add = (a: number, b: number) => a + b; + * }`; + * const strippedCode = stripTypeScriptTypes(code, { mode: 'transform', sourceMap: true }); + * console.log(strippedCode); + * // Prints: + * // var MathUtil; + * // (function(MathUtil) { + * // MathUtil.add = (a, b)=>a + b; + * // })(MathUtil || (MathUtil = {})); + * // # sourceMappingURL=data:application/json;base64, ... + * ``` + * @since v22.13.0 + * @param code The code to strip type annotations from. + * @returns The code with type annotations stripped. + */ + function stripTypeScriptTypes(code: string, options?: StripTypeScriptTypesOptions): string; + /* eslint-enable @definitelytyped/no-unnecessary-generics */ + /** + * The `module.syncBuiltinESMExports()` method updates all the live bindings for + * builtin `ES Modules` to match the properties of the `CommonJS` exports. It + * does not add or remove exported names from the `ES Modules`. + * + * ```js + * import fs from 'node:fs'; + * import assert from 'node:assert'; + * import { syncBuiltinESMExports } from 'node:module'; + * + * fs.readFile = newAPI; + * + * delete fs.readFileSync; + * + * function newAPI() { + * // ... + * } + * + * fs.newAPI = newAPI; + * + * syncBuiltinESMExports(); + * + * import('node:fs').then((esmFS) => { + * // It syncs the existing readFile property with the new value + * assert.strictEqual(esmFS.readFile, newAPI); + * // readFileSync has been deleted from the required fs + * assert.strictEqual('readFileSync' in fs, false); + * // syncBuiltinESMExports() does not remove readFileSync from esmFS + * assert.strictEqual('readFileSync' in esmFS, true); + * // syncBuiltinESMExports() does not add names + * assert.strictEqual(esmFS.newAPI, undefined); + * }); + * ``` + * @since v12.12.0 + */ + function syncBuiltinESMExports(): void; + interface ImportAttributes extends NodeJS.Dict<string> { + type?: string | undefined; + } + type ImportPhase = "source" | "evaluation"; + type ModuleFormat = + | "addon" + | "builtin" + | "commonjs" + | "commonjs-typescript" + | "json" + | "module" + | "module-typescript" + | "wasm"; + type ModuleSource = string | ArrayBuffer | NodeJS.TypedArray; + /** + * The `initialize` hook provides a way to define a custom function that runs in + * the hooks thread when the hooks module is initialized. Initialization happens + * when the hooks module is registered via {@link register}. + * + * This hook can receive data from a {@link register} invocation, including + * ports and other transferable objects. The return value of `initialize` can be a + * `Promise`, in which case it will be awaited before the main application thread + * execution resumes. + */ + type InitializeHook<Data = any> = (data: Data) => void | Promise<void>; + interface ResolveHookContext { + /** + * Export conditions of the relevant `package.json` + */ + conditions: string[]; + /** + * An object whose key-value pairs represent the assertions for the module to import + */ + importAttributes: ImportAttributes; + /** + * The module importing this one, or undefined if this is the Node.js entry point + */ + parentURL: string | undefined; + } + interface ResolveFnOutput { + /** + * A hint to the load hook (it might be ignored); can be an intermediary value. + */ + format?: string | null | undefined; + /** + * The import attributes to use when caching the module (optional; if excluded the input will be used) + */ + importAttributes?: ImportAttributes | undefined; + /** + * A signal that this hook intends to terminate the chain of `resolve` hooks. + * @default false + */ + shortCircuit?: boolean | undefined; + /** + * The absolute URL to which this input resolves + */ + url: string; + } + /** + * The `resolve` hook chain is responsible for telling Node.js where to find and + * how to cache a given `import` statement or expression, or `require` call. It can + * optionally return a format (such as `'module'`) as a hint to the `load` hook. If + * a format is specified, the `load` hook is ultimately responsible for providing + * the final `format` value (and it is free to ignore the hint provided by + * `resolve`); if `resolve` provides a `format`, a custom `load` hook is required + * even if only to pass the value to the Node.js default `load` hook. + */ + type ResolveHook = ( + specifier: string, + context: ResolveHookContext, + nextResolve: ( + specifier: string, + context?: Partial<ResolveHookContext>, + ) => ResolveFnOutput | Promise<ResolveFnOutput>, + ) => ResolveFnOutput | Promise<ResolveFnOutput>; + type ResolveHookSync = ( + specifier: string, + context: ResolveHookContext, + nextResolve: ( + specifier: string, + context?: Partial<ResolveHookContext>, + ) => ResolveFnOutput, + ) => ResolveFnOutput; + interface LoadHookContext { + /** + * Export conditions of the relevant `package.json` + */ + conditions: string[]; + /** + * The format optionally supplied by the `resolve` hook chain (can be an intermediary value). + */ + format: string | null | undefined; + /** + * An object whose key-value pairs represent the assertions for the module to import + */ + importAttributes: ImportAttributes; + } + interface LoadFnOutput { + format: string | null | undefined; + /** + * A signal that this hook intends to terminate the chain of `resolve` hooks. + * @default false + */ + shortCircuit?: boolean | undefined; + /** + * The source for Node.js to evaluate + */ + source?: ModuleSource | undefined; + } + /** + * The `load` hook provides a way to define a custom method of determining how a + * URL should be interpreted, retrieved, and parsed. It is also in charge of + * validating the import attributes. + */ + type LoadHook = ( + url: string, + context: LoadHookContext, + nextLoad: ( + url: string, + context?: Partial<LoadHookContext>, + ) => LoadFnOutput | Promise<LoadFnOutput>, + ) => LoadFnOutput | Promise<LoadFnOutput>; + type LoadHookSync = ( + url: string, + context: LoadHookContext, + nextLoad: ( + url: string, + context?: Partial<LoadHookContext>, + ) => LoadFnOutput, + ) => LoadFnOutput; + interface SourceMapsSupport { + /** + * If the source maps support is enabled + */ + enabled: boolean; + /** + * If the support is enabled for files in `node_modules`. + */ + nodeModules: boolean; + /** + * If the support is enabled for generated code from `eval` or `new Function`. + */ + generatedCode: boolean; + } + /** + * This method returns whether the [Source Map v3](https://tc39.es/ecma426/) support for stack + * traces is enabled. + * @since v23.7.0, v22.14.0 + */ + function getSourceMapsSupport(): SourceMapsSupport; + /** + * `path` is the resolved path for the file for which a corresponding source map + * should be fetched. + * @since v13.7.0, v12.17.0 + * @return Returns `module.SourceMap` if a source map is found, `undefined` otherwise. + */ + function findSourceMap(path: string): SourceMap | undefined; + interface SetSourceMapsSupportOptions { + /** + * If enabling the support for files in `node_modules`. + * @default false + */ + nodeModules?: boolean | undefined; + /** + * If enabling the support for generated code from `eval` or `new Function`. + * @default false + */ + generatedCode?: boolean | undefined; + } + /** + * This function enables or disables the [Source Map v3](https://tc39.es/ecma426/) support for + * stack traces. + * + * It provides same features as launching Node.js process with commandline options + * `--enable-source-maps`, with additional options to alter the support for files + * in `node_modules` or generated codes. + * + * Only source maps in JavaScript files that are loaded after source maps has been + * enabled will be parsed and loaded. Preferably, use the commandline options + * `--enable-source-maps` to avoid losing track of source maps of modules loaded + * before this API call. + * @since v23.7.0, v22.14.0 + */ + function setSourceMapsSupport(enabled: boolean, options?: SetSourceMapsSupportOptions): void; + interface SourceMapConstructorOptions { + /** + * @since v21.0.0, v20.5.0 + */ + lineLengths?: readonly number[] | undefined; + } + interface SourceMapPayload { + file: string; + version: number; + sources: string[]; + sourcesContent: string[]; + names: string[]; + mappings: string; + sourceRoot: string; + } + interface SourceMapping { + generatedLine: number; + generatedColumn: number; + originalSource: string; + originalLine: number; + originalColumn: number; + } + interface SourceOrigin { + /** + * The name of the range in the source map, if one was provided + */ + name: string | undefined; + /** + * The file name of the original source, as reported in the SourceMap + */ + fileName: string; + /** + * The 1-indexed lineNumber of the corresponding call site in the original source + */ + lineNumber: number; + /** + * The 1-indexed columnNumber of the corresponding call site in the original source + */ + columnNumber: number; + } + /** + * @since v13.7.0, v12.17.0 + */ + class SourceMap { + constructor(payload: SourceMapPayload, options?: SourceMapConstructorOptions); + /** + * Getter for the payload used to construct the `SourceMap` instance. + */ + readonly payload: SourceMapPayload; + /** + * Given a line offset and column offset in the generated source + * file, returns an object representing the SourceMap range in the + * original file if found, or an empty object if not. + * + * The object returned contains the following keys: + * + * The returned value represents the raw range as it appears in the + * SourceMap, based on zero-indexed offsets, _not_ 1-indexed line and + * column numbers as they appear in Error messages and CallSite + * objects. + * + * To get the corresponding 1-indexed line and column numbers from a + * lineNumber and columnNumber as they are reported by Error stacks + * and CallSite objects, use `sourceMap.findOrigin(lineNumber, columnNumber)` + * @param lineOffset The zero-indexed line number offset in the generated source + * @param columnOffset The zero-indexed column number offset in the generated source + */ + findEntry(lineOffset: number, columnOffset: number): SourceMapping | {}; + /** + * Given a 1-indexed `lineNumber` and `columnNumber` from a call site in the generated source, + * find the corresponding call site location in the original source. + * + * If the `lineNumber` and `columnNumber` provided are not found in any source map, + * then an empty object is returned. + * @param lineNumber The 1-indexed line number of the call site in the generated source + * @param columnNumber The 1-indexed column number of the call site in the generated source + */ + findOrigin(lineNumber: number, columnNumber: number): SourceOrigin | {}; + } + function runMain(main?: string): void; + function wrap(script: string): string; + } + global { + namespace NodeJS { + interface Module { + /** + * The module objects required for the first time by this one. + * @since v0.1.16 + */ + children: Module[]; + /** + * The `module.exports` object is created by the `Module` system. Sometimes this is + * not acceptable; many want their module to be an instance of some class. To do + * this, assign the desired export object to `module.exports`. + * @since v0.1.16 + */ + exports: any; + /** + * The fully resolved filename of the module. + * @since v0.1.16 + */ + filename: string; + /** + * The identifier for the module. Typically this is the fully resolved + * filename. + * @since v0.1.16 + */ + id: string; + /** + * `true` if the module is running during the Node.js preload + * phase. + * @since v15.4.0, v14.17.0 + */ + isPreloading: boolean; + /** + * Whether or not the module is done loading, or is in the process of + * loading. + * @since v0.1.16 + */ + loaded: boolean; + /** + * The module that first required this one, or `null` if the current module is the + * entry point of the current process, or `undefined` if the module was loaded by + * something that is not a CommonJS module (e.g. REPL or `import`). + * @since v0.1.16 + * @deprecated Please use `require.main` and `module.children` instead. + */ + parent: Module | null | undefined; + /** + * The directory name of the module. This is usually the same as the + * `path.dirname()` of the `module.id`. + * @since v11.14.0 + */ + path: string; + /** + * The search paths for the module. + * @since v0.4.0 + */ + paths: string[]; + /** + * The `module.require()` method provides a way to load a module as if + * `require()` was called from the original module. + * @since v0.5.1 + */ + require(id: string): any; + } + interface Require { + /** + * Used to import modules, `JSON`, and local files. + * @since v0.1.13 + */ + (id: string): any; + /** + * Modules are cached in this object when they are required. By deleting a key + * value from this object, the next `require` will reload the module. + * This does not apply to + * [native addons](https://nodejs.org/docs/latest-v25.x/api/addons.html), + * for which reloading will result in an error. + * @since v0.3.0 + */ + cache: Dict<Module>; + /** + * Instruct `require` on how to handle certain file extensions. + * @since v0.3.0 + * @deprecated + */ + extensions: RequireExtensions; + /** + * The `Module` object representing the entry script loaded when the Node.js + * process launched, or `undefined` if the entry point of the program is not a + * CommonJS module. + * @since v0.1.17 + */ + main: Module | undefined; + /** + * @since v0.3.0 + */ + resolve: RequireResolve; + } + /** @deprecated */ + interface RequireExtensions extends Dict<(module: Module, filename: string) => any> { + ".js": (module: Module, filename: string) => any; + ".json": (module: Module, filename: string) => any; + ".node": (module: Module, filename: string) => any; + } + interface RequireResolveOptions { + /** + * Paths to resolve module location from. If present, these + * paths are used instead of the default resolution paths, with the exception + * of + * [GLOBAL\_FOLDERS](https://nodejs.org/docs/latest-v25.x/api/modules.html#loading-from-the-global-folders) + * like `$HOME/.node_modules`, which are + * always included. Each of these paths is used as a starting point for + * the module resolution algorithm, meaning that the `node_modules` hierarchy + * is checked from this location. + * @since v8.9.0 + */ + paths?: string[] | undefined; + } + interface RequireResolve { + /** + * Use the internal `require()` machinery to look up the location of a module, + * but rather than loading the module, just return the resolved filename. + * + * If the module can not be found, a `MODULE_NOT_FOUND` error is thrown. + * @since v0.3.0 + * @param request The module path to resolve. + */ + (request: string, options?: RequireResolveOptions): string; + /** + * Returns an array containing the paths searched during resolution of `request` or + * `null` if the `request` string references a core module, for example `http` or + * `fs`. + * @since v8.9.0 + * @param request The module path whose lookup paths are being retrieved. + */ + paths(request: string): string[] | null; + } + } + /** + * The directory name of the current module. This is the same as the + * `path.dirname()` of the `__filename`. + * @since v0.1.27 + */ + var __dirname: string; + /** + * The file name of the current module. This is the current module file's absolute + * path with symlinks resolved. + * + * For a main program this is not necessarily the same as the file name used in the + * command line. + * @since v0.0.1 + */ + var __filename: string; + /** + * The `exports` variable is available within a module's file-level scope, and is + * assigned the value of `module.exports` before the module is evaluated. + * @since v0.1.16 + */ + var exports: NodeJS.Module["exports"]; + /** + * A reference to the current module. + * @since v0.1.16 + */ + var module: NodeJS.Module; + /** + * @since v0.1.13 + */ + var require: NodeJS.Require; + // Global-scope aliases for backwards compatibility with @types/node <13.0.x + // TODO: consider removing in a future major version update + /** @deprecated Use `NodeJS.Module` instead. */ + interface NodeModule extends NodeJS.Module {} + /** @deprecated Use `NodeJS.Require` instead. */ + interface NodeRequire extends NodeJS.Require {} + /** @deprecated Use `NodeJS.RequireResolve` instead. */ + interface RequireResolve extends NodeJS.RequireResolve {} + } + export = Module; +} +declare module "module" { + import module = require("node:module"); + export = module; +} diff --git a/server/node_modules/@types/node/net.d.ts b/server/node_modules/@types/node/net.d.ts new file mode 100644 index 0000000..0fcd105 --- /dev/null +++ b/server/node_modules/@types/node/net.d.ts @@ -0,0 +1,933 @@ +/** + * > Stability: 2 - Stable + * + * The `node:net` module provides an asynchronous network API for creating stream-based + * TCP or `IPC` servers ({@link createServer}) and clients + * ({@link createConnection}). + * + * It can be accessed using: + * + * ```js + * import net from 'node:net'; + * ``` + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/net.js) + */ +declare module "node:net" { + import { NonSharedBuffer } from "node:buffer"; + import * as dns from "node:dns"; + import { Abortable, EventEmitter, InternalEventEmitter } from "node:events"; + import * as stream from "node:stream"; + type LookupFunction = ( + hostname: string, + options: dns.LookupOptions, + callback: (err: NodeJS.ErrnoException | null, address: string | dns.LookupAddress[], family?: number) => void, + ) => void; + interface AddressInfo { + address: string; + family: string; + port: number; + } + interface SocketConstructorOpts { + fd?: number | undefined; + allowHalfOpen?: boolean | undefined; + onread?: OnReadOpts | undefined; + readable?: boolean | undefined; + writable?: boolean | undefined; + signal?: AbortSignal | undefined; + } + interface OnReadOpts { + buffer: Uint8Array | (() => Uint8Array); + /** + * This function is called for every chunk of incoming data. + * Two arguments are passed to it: the number of bytes written to `buffer` and a reference to `buffer`. + * Return `false` from this function to implicitly `pause()` the socket. + */ + callback(bytesWritten: number, buffer: Uint8Array): boolean; + } + interface TcpSocketConnectOpts { + port: number; + host?: string | undefined; + localAddress?: string | undefined; + localPort?: number | undefined; + hints?: number | undefined; + family?: number | undefined; + lookup?: LookupFunction | undefined; + noDelay?: boolean | undefined; + keepAlive?: boolean | undefined; + keepAliveInitialDelay?: number | undefined; + /** + * @since v18.13.0 + */ + autoSelectFamily?: boolean | undefined; + /** + * @since v18.13.0 + */ + autoSelectFamilyAttemptTimeout?: number | undefined; + blockList?: BlockList | undefined; + } + interface IpcSocketConnectOpts { + path: string; + } + type SocketConnectOpts = TcpSocketConnectOpts | IpcSocketConnectOpts; + type SocketReadyState = "opening" | "open" | "readOnly" | "writeOnly" | "closed"; + interface SocketEventMap extends Omit<stream.DuplexEventMap, "close"> { + "close": [hadError: boolean]; + "connect": []; + "connectionAttempt": [ip: string, port: number, family: number]; + "connectionAttemptFailed": [ip: string, port: number, family: number, error: Error]; + "connectionAttemptTimeout": [ip: string, port: number, family: number]; + "data": [data: string | NonSharedBuffer]; + "lookup": [err: Error | null, address: string, family: number | null, host: string]; + "ready": []; + "timeout": []; + } + /** + * This class is an abstraction of a TCP socket or a streaming `IPC` endpoint + * (uses named pipes on Windows, and Unix domain sockets otherwise). It is also + * an `EventEmitter`. + * + * A `net.Socket` can be created by the user and used directly to interact with + * a server. For example, it is returned by {@link createConnection}, + * so the user can use it to talk to the server. + * + * It can also be created by Node.js and passed to the user when a connection + * is received. For example, it is passed to the listeners of a `'connection'` event emitted on a {@link Server}, so the user can use + * it to interact with the client. + * @since v0.3.4 + */ + class Socket extends stream.Duplex { + constructor(options?: SocketConstructorOpts); + /** + * Destroys the socket after all data is written. If the `finish` event was already emitted the socket is destroyed immediately. + * If the socket is still writable it implicitly calls `socket.end()`. + * @since v0.3.4 + */ + destroySoon(): void; + /** + * Sends data on the socket. The second parameter specifies the encoding in the + * case of a string. It defaults to UTF8 encoding. + * + * Returns `true` if the entire data was flushed successfully to the kernel + * buffer. Returns `false` if all or part of the data was queued in user memory.`'drain'` will be emitted when the buffer is again free. + * + * The optional `callback` parameter will be executed when the data is finally + * written out, which may not be immediately. + * + * See `Writable` stream `write()` method for more + * information. + * @since v0.1.90 + * @param [encoding='utf8'] Only used when data is `string`. + */ + write(buffer: Uint8Array | string, cb?: (err?: Error | null) => void): boolean; + write(str: Uint8Array | string, encoding?: BufferEncoding, cb?: (err?: Error | null) => void): boolean; + /** + * Initiate a connection on a given socket. + * + * Possible signatures: + * + * * `socket.connect(options[, connectListener])` + * * `socket.connect(path[, connectListener])` for `IPC` connections. + * * `socket.connect(port[, host][, connectListener])` for TCP connections. + * * Returns: `net.Socket` The socket itself. + * + * This function is asynchronous. When the connection is established, the `'connect'` event will be emitted. If there is a problem connecting, + * instead of a `'connect'` event, an `'error'` event will be emitted with + * the error passed to the `'error'` listener. + * The last parameter `connectListener`, if supplied, will be added as a listener + * for the `'connect'` event **once**. + * + * This function should only be used for reconnecting a socket after`'close'` has been emitted or otherwise it may lead to undefined + * behavior. + */ + connect(options: SocketConnectOpts, connectionListener?: () => void): this; + connect(port: number, host: string, connectionListener?: () => void): this; + connect(port: number, connectionListener?: () => void): this; + connect(path: string, connectionListener?: () => void): this; + /** + * Set the encoding for the socket as a `Readable Stream`. See `readable.setEncoding()` for more information. + * @since v0.1.90 + * @return The socket itself. + */ + setEncoding(encoding?: BufferEncoding): this; + /** + * Pauses the reading of data. That is, `'data'` events will not be emitted. + * Useful to throttle back an upload. + * @return The socket itself. + */ + pause(): this; + /** + * Close the TCP connection by sending an RST packet and destroy the stream. + * If this TCP socket is in connecting status, it will send an RST packet and destroy this TCP socket once it is connected. + * Otherwise, it will call `socket.destroy` with an `ERR_SOCKET_CLOSED` Error. + * If this is not a TCP socket (for example, a pipe), calling this method will immediately throw an `ERR_INVALID_HANDLE_TYPE` Error. + * @since v18.3.0, v16.17.0 + */ + resetAndDestroy(): this; + /** + * Resumes reading after a call to `socket.pause()`. + * @return The socket itself. + */ + resume(): this; + /** + * Sets the socket to timeout after `timeout` milliseconds of inactivity on + * the socket. By default `net.Socket` do not have a timeout. + * + * When an idle timeout is triggered the socket will receive a `'timeout'` event but the connection will not be severed. The user must manually call `socket.end()` or `socket.destroy()` to + * end the connection. + * + * ```js + * socket.setTimeout(3000); + * socket.on('timeout', () => { + * console.log('socket timeout'); + * socket.end(); + * }); + * ``` + * + * If `timeout` is 0, then the existing idle timeout is disabled. + * + * The optional `callback` parameter will be added as a one-time listener for the `'timeout'` event. + * @since v0.1.90 + * @return The socket itself. + */ + setTimeout(timeout: number, callback?: () => void): this; + /** + * Enable/disable the use of Nagle's algorithm. + * + * When a TCP connection is created, it will have Nagle's algorithm enabled. + * + * Nagle's algorithm delays data before it is sent via the network. It attempts + * to optimize throughput at the expense of latency. + * + * Passing `true` for `noDelay` or not passing an argument will disable Nagle's + * algorithm for the socket. Passing `false` for `noDelay` will enable Nagle's + * algorithm. + * @since v0.1.90 + * @param [noDelay=true] + * @return The socket itself. + */ + setNoDelay(noDelay?: boolean): this; + /** + * Enable/disable keep-alive functionality, and optionally set the initial + * delay before the first keepalive probe is sent on an idle socket. + * + * Set `initialDelay` (in milliseconds) to set the delay between the last + * data packet received and the first keepalive probe. Setting `0` for`initialDelay` will leave the value unchanged from the default + * (or previous) setting. + * + * Enabling the keep-alive functionality will set the following socket options: + * + * * `SO_KEEPALIVE=1` + * * `TCP_KEEPIDLE=initialDelay` + * * `TCP_KEEPCNT=10` + * * `TCP_KEEPINTVL=1` + * @since v0.1.92 + * @param [enable=false] + * @param [initialDelay=0] + * @return The socket itself. + */ + setKeepAlive(enable?: boolean, initialDelay?: number): this; + /** + * Returns the bound `address`, the address `family` name and `port` of the + * socket as reported by the operating system:`{ port: 12346, family: 'IPv4', address: '127.0.0.1' }` + * @since v0.1.90 + */ + address(): AddressInfo | {}; + /** + * Calling `unref()` on a socket will allow the program to exit if this is the only + * active socket in the event system. If the socket is already `unref`ed calling`unref()` again will have no effect. + * @since v0.9.1 + * @return The socket itself. + */ + unref(): this; + /** + * Opposite of `unref()`, calling `ref()` on a previously `unref`ed socket will _not_ let the program exit if it's the only socket left (the default behavior). + * If the socket is `ref`ed calling `ref` again will have no effect. + * @since v0.9.1 + * @return The socket itself. + */ + ref(): this; + /** + * This property is only present if the family autoselection algorithm is enabled in `socket.connect(options)` + * and it is an array of the addresses that have been attempted. + * + * Each address is a string in the form of `$IP:$PORT`. + * If the connection was successful, then the last address is the one that the socket is currently connected to. + * @since v19.4.0 + */ + readonly autoSelectFamilyAttemptedAddresses: string[]; + /** + * This property shows the number of characters buffered for writing. The buffer + * may contain strings whose length after encoding is not yet known. So this number + * is only an approximation of the number of bytes in the buffer. + * + * `net.Socket` has the property that `socket.write()` always works. This is to + * help users get up and running quickly. The computer cannot always keep up + * with the amount of data that is written to a socket. The network connection + * simply might be too slow. Node.js will internally queue up the data written to a + * socket and send it out over the wire when it is possible. + * + * The consequence of this internal buffering is that memory may grow. + * Users who experience large or growing `bufferSize` should attempt to + * "throttle" the data flows in their program with `socket.pause()` and `socket.resume()`. + * @since v0.3.8 + * @deprecated Since v14.6.0 - Use `writableLength` instead. + */ + readonly bufferSize: number; + /** + * The amount of received bytes. + * @since v0.5.3 + */ + readonly bytesRead: number; + /** + * The amount of bytes sent. + * @since v0.5.3 + */ + readonly bytesWritten: number; + /** + * If `true`, `socket.connect(options[, connectListener])` was + * called and has not yet finished. It will stay `true` until the socket becomes + * connected, then it is set to `false` and the `'connect'` event is emitted. Note + * that the `socket.connect(options[, connectListener])` callback is a listener for the `'connect'` event. + * @since v6.1.0 + */ + readonly connecting: boolean; + /** + * This is `true` if the socket is not connected yet, either because `.connect()`has not yet been called or because it is still in the process of connecting + * (see `socket.connecting`). + * @since v11.2.0, v10.16.0 + */ + readonly pending: boolean; + /** + * See `writable.destroyed` for further details. + */ + readonly destroyed: boolean; + /** + * The string representation of the local IP address the remote client is + * connecting on. For example, in a server listening on `'0.0.0.0'`, if a client + * connects on `'192.168.1.1'`, the value of `socket.localAddress` would be`'192.168.1.1'`. + * @since v0.9.6 + */ + readonly localAddress?: string; + /** + * The numeric representation of the local port. For example, `80` or `21`. + * @since v0.9.6 + */ + readonly localPort?: number; + /** + * The string representation of the local IP family. `'IPv4'` or `'IPv6'`. + * @since v18.8.0, v16.18.0 + */ + readonly localFamily?: string; + /** + * This property represents the state of the connection as a string. + * + * * If the stream is connecting `socket.readyState` is `opening`. + * * If the stream is readable and writable, it is `open`. + * * If the stream is readable and not writable, it is `readOnly`. + * * If the stream is not readable and writable, it is `writeOnly`. + * @since v0.5.0 + */ + readonly readyState: SocketReadyState; + /** + * The string representation of the remote IP address. For example,`'74.125.127.100'` or `'2001:4860:a005::68'`. Value may be `undefined` if + * the socket is destroyed (for example, if the client disconnected). + * @since v0.5.10 + */ + readonly remoteAddress: string | undefined; + /** + * The string representation of the remote IP family. `'IPv4'` or `'IPv6'`. Value may be `undefined` if + * the socket is destroyed (for example, if the client disconnected). + * @since v0.11.14 + */ + readonly remoteFamily: string | undefined; + /** + * The numeric representation of the remote port. For example, `80` or `21`. Value may be `undefined` if + * the socket is destroyed (for example, if the client disconnected). + * @since v0.5.10 + */ + readonly remotePort: number | undefined; + /** + * The socket timeout in milliseconds as set by `socket.setTimeout()`. + * It is `undefined` if a timeout has not been set. + * @since v10.7.0 + */ + readonly timeout?: number; + /** + * Half-closes the socket. i.e., it sends a FIN packet. It is possible the + * server will still send some data. + * + * See `writable.end()` for further details. + * @since v0.1.90 + * @param [encoding='utf8'] Only used when data is `string`. + * @param callback Optional callback for when the socket is finished. + * @return The socket itself. + */ + end(callback?: () => void): this; + end(buffer: Uint8Array | string, callback?: () => void): this; + end(str: Uint8Array | string, encoding?: BufferEncoding, callback?: () => void): this; + // #region InternalEventEmitter + addListener<E extends keyof SocketEventMap>(eventName: E, listener: (...args: SocketEventMap[E]) => void): this; + addListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + emit<E extends keyof SocketEventMap>(eventName: E, ...args: SocketEventMap[E]): boolean; + emit(eventName: string | symbol, ...args: any[]): boolean; + listenerCount<E extends keyof SocketEventMap>( + eventName: E, + listener?: (...args: SocketEventMap[E]) => void, + ): number; + listenerCount(eventName: string | symbol, listener?: (...args: any[]) => void): number; + listeners<E extends keyof SocketEventMap>(eventName: E): ((...args: SocketEventMap[E]) => void)[]; + listeners(eventName: string | symbol): ((...args: any[]) => void)[]; + off<E extends keyof SocketEventMap>(eventName: E, listener: (...args: SocketEventMap[E]) => void): this; + off(eventName: string | symbol, listener: (...args: any[]) => void): this; + on<E extends keyof SocketEventMap>(eventName: E, listener: (...args: SocketEventMap[E]) => void): this; + on(eventName: string | symbol, listener: (...args: any[]) => void): this; + once<E extends keyof SocketEventMap>(eventName: E, listener: (...args: SocketEventMap[E]) => void): this; + once(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependListener<E extends keyof SocketEventMap>( + eventName: E, + listener: (...args: SocketEventMap[E]) => void, + ): this; + prependListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependOnceListener<E extends keyof SocketEventMap>( + eventName: E, + listener: (...args: SocketEventMap[E]) => void, + ): this; + prependOnceListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + rawListeners<E extends keyof SocketEventMap>(eventName: E): ((...args: SocketEventMap[E]) => void)[]; + rawListeners(eventName: string | symbol): ((...args: any[]) => void)[]; + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + removeAllListeners<E extends keyof SocketEventMap>(eventName?: E): this; + removeAllListeners(eventName?: string | symbol): this; + removeListener<E extends keyof SocketEventMap>( + eventName: E, + listener: (...args: SocketEventMap[E]) => void, + ): this; + removeListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + // #endregion + } + interface ListenOptions extends Abortable { + backlog?: number | undefined; + exclusive?: boolean | undefined; + host?: string | undefined; + /** + * @default false + */ + ipv6Only?: boolean | undefined; + reusePort?: boolean | undefined; + path?: string | undefined; + port?: number | undefined; + readableAll?: boolean | undefined; + writableAll?: boolean | undefined; + } + interface ServerOpts { + /** + * Indicates whether half-opened TCP connections are allowed. + * @default false + */ + allowHalfOpen?: boolean | undefined; + /** + * Indicates whether the socket should be paused on incoming connections. + * @default false + */ + pauseOnConnect?: boolean | undefined; + /** + * If set to `true`, it disables the use of Nagle's algorithm immediately after a new incoming connection is received. + * @default false + * @since v16.5.0 + */ + noDelay?: boolean | undefined; + /** + * If set to `true`, it enables keep-alive functionality on the socket immediately after a new incoming connection is received, + * similarly on what is done in `socket.setKeepAlive([enable][, initialDelay])`. + * @default false + * @since v16.5.0 + */ + keepAlive?: boolean | undefined; + /** + * If set to a positive number, it sets the initial delay before the first keepalive probe is sent on an idle socket. + * @default 0 + * @since v16.5.0 + */ + keepAliveInitialDelay?: number | undefined; + /** + * Optionally overrides all `net.Socket`s' `readableHighWaterMark` and `writableHighWaterMark`. + * @default See [stream.getDefaultHighWaterMark()](https://nodejs.org/docs/latest-v25.x/api/stream.html#streamgetdefaulthighwatermarkobjectmode). + * @since v18.17.0, v20.1.0 + */ + highWaterMark?: number | undefined; + /** + * `blockList` can be used for disabling inbound + * access to specific IP addresses, IP ranges, or IP subnets. This does not + * work if the server is behind a reverse proxy, NAT, etc. because the address + * checked against the block list is the address of the proxy, or the one + * specified by the NAT. + * @since v22.13.0 + */ + blockList?: BlockList | undefined; + } + interface DropArgument { + localAddress?: string; + localPort?: number; + localFamily?: string; + remoteAddress?: string; + remotePort?: number; + remoteFamily?: string; + } + interface ServerEventMap { + "close": []; + "connection": [socket: Socket]; + "error": [err: Error]; + "listening": []; + "drop": [data?: DropArgument]; + } + /** + * This class is used to create a TCP or `IPC` server. + * @since v0.1.90 + */ + class Server implements EventEmitter { + constructor(connectionListener?: (socket: Socket) => void); + constructor(options?: ServerOpts, connectionListener?: (socket: Socket) => void); + /** + * Start a server listening for connections. A `net.Server` can be a TCP or + * an `IPC` server depending on what it listens to. + * + * Possible signatures: + * + * * `server.listen(handle[, backlog][, callback])` + * * `server.listen(options[, callback])` + * * `server.listen(path[, backlog][, callback])` for `IPC` servers + * * `server.listen([port[, host[, backlog]]][, callback])` for TCP servers + * + * This function is asynchronous. When the server starts listening, the `'listening'` event will be emitted. The last parameter `callback`will be added as a listener for the `'listening'` + * event. + * + * All `listen()` methods can take a `backlog` parameter to specify the maximum + * length of the queue of pending connections. The actual length will be determined + * by the OS through sysctl settings such as `tcp_max_syn_backlog` and `somaxconn` on Linux. The default value of this parameter is 511 (not 512). + * + * All {@link Socket} are set to `SO_REUSEADDR` (see [`socket(7)`](https://man7.org/linux/man-pages/man7/socket.7.html) for + * details). + * + * The `server.listen()` method can be called again if and only if there was an + * error during the first `server.listen()` call or `server.close()` has been + * called. Otherwise, an `ERR_SERVER_ALREADY_LISTEN` error will be thrown. + * + * One of the most common errors raised when listening is `EADDRINUSE`. + * This happens when another server is already listening on the requested`port`/`path`/`handle`. One way to handle this would be to retry + * after a certain amount of time: + * + * ```js + * server.on('error', (e) => { + * if (e.code === 'EADDRINUSE') { + * console.error('Address in use, retrying...'); + * setTimeout(() => { + * server.close(); + * server.listen(PORT, HOST); + * }, 1000); + * } + * }); + * ``` + */ + listen(port?: number, hostname?: string, backlog?: number, listeningListener?: () => void): this; + listen(port?: number, hostname?: string, listeningListener?: () => void): this; + listen(port?: number, backlog?: number, listeningListener?: () => void): this; + listen(port?: number, listeningListener?: () => void): this; + listen(path: string, backlog?: number, listeningListener?: () => void): this; + listen(path: string, listeningListener?: () => void): this; + listen(options: ListenOptions, listeningListener?: () => void): this; + listen(handle: any, backlog?: number, listeningListener?: () => void): this; + listen(handle: any, listeningListener?: () => void): this; + /** + * Stops the server from accepting new connections and keeps existing + * connections. This function is asynchronous, the server is finally closed + * when all connections are ended and the server emits a `'close'` event. + * The optional `callback` will be called once the `'close'` event occurs. Unlike + * that event, it will be called with an `Error` as its only argument if the server + * was not open when it was closed. + * @since v0.1.90 + * @param callback Called when the server is closed. + */ + close(callback?: (err?: Error) => void): this; + /** + * Returns the bound `address`, the address `family` name, and `port` of the server + * as reported by the operating system if listening on an IP socket + * (useful to find which port was assigned when getting an OS-assigned address):`{ port: 12346, family: 'IPv4', address: '127.0.0.1' }`. + * + * For a server listening on a pipe or Unix domain socket, the name is returned + * as a string. + * + * ```js + * const server = net.createServer((socket) => { + * socket.end('goodbye\n'); + * }).on('error', (err) => { + * // Handle errors here. + * throw err; + * }); + * + * // Grab an arbitrary unused port. + * server.listen(() => { + * console.log('opened server on', server.address()); + * }); + * ``` + * + * `server.address()` returns `null` before the `'listening'` event has been + * emitted or after calling `server.close()`. + * @since v0.1.90 + */ + address(): AddressInfo | string | null; + /** + * Asynchronously get the number of concurrent connections on the server. Works + * when sockets were sent to forks. + * + * Callback should take two arguments `err` and `count`. + * @since v0.9.7 + */ + getConnections(cb: (error: Error | null, count: number) => void): this; + /** + * Opposite of `unref()`, calling `ref()` on a previously `unref`ed server will _not_ let the program exit if it's the only server left (the default behavior). + * If the server is `ref`ed calling `ref()` again will have no effect. + * @since v0.9.1 + */ + ref(): this; + /** + * Calling `unref()` on a server will allow the program to exit if this is the only + * active server in the event system. If the server is already `unref`ed calling`unref()` again will have no effect. + * @since v0.9.1 + */ + unref(): this; + /** + * Set this property to reject connections when the server's connection count gets + * high. + * + * It is not recommended to use this option once a socket has been sent to a child + * with `child_process.fork()`. + * @since v0.2.0 + */ + maxConnections: number; + connections: number; + /** + * Indicates whether or not the server is listening for connections. + * @since v5.7.0 + */ + readonly listening: boolean; + /** + * Calls {@link Server.close()} and returns a promise that fulfills when the server has closed. + * @since v20.5.0 + */ + [Symbol.asyncDispose](): Promise<void>; + } + interface Server extends InternalEventEmitter<ServerEventMap> {} + type IPVersion = "ipv4" | "ipv6"; + /** + * The `BlockList` object can be used with some network APIs to specify rules for + * disabling inbound or outbound access to specific IP addresses, IP ranges, or + * IP subnets. + * @since v15.0.0, v14.18.0 + */ + class BlockList { + /** + * Adds a rule to block the given IP address. + * @since v15.0.0, v14.18.0 + * @param address An IPv4 or IPv6 address. + * @param [type='ipv4'] Either `'ipv4'` or `'ipv6'`. + */ + addAddress(address: string, type?: IPVersion): void; + addAddress(address: SocketAddress): void; + /** + * Adds a rule to block a range of IP addresses from `start` (inclusive) to`end` (inclusive). + * @since v15.0.0, v14.18.0 + * @param start The starting IPv4 or IPv6 address in the range. + * @param end The ending IPv4 or IPv6 address in the range. + * @param [type='ipv4'] Either `'ipv4'` or `'ipv6'`. + */ + addRange(start: string, end: string, type?: IPVersion): void; + addRange(start: SocketAddress, end: SocketAddress): void; + /** + * Adds a rule to block a range of IP addresses specified as a subnet mask. + * @since v15.0.0, v14.18.0 + * @param net The network IPv4 or IPv6 address. + * @param prefix The number of CIDR prefix bits. For IPv4, this must be a value between `0` and `32`. For IPv6, this must be between `0` and `128`. + * @param [type='ipv4'] Either `'ipv4'` or `'ipv6'`. + */ + addSubnet(net: SocketAddress, prefix: number): void; + addSubnet(net: string, prefix: number, type?: IPVersion): void; + /** + * Returns `true` if the given IP address matches any of the rules added to the`BlockList`. + * + * ```js + * const blockList = new net.BlockList(); + * blockList.addAddress('123.123.123.123'); + * blockList.addRange('10.0.0.1', '10.0.0.10'); + * blockList.addSubnet('8592:757c:efae:4e45::', 64, 'ipv6'); + * + * console.log(blockList.check('123.123.123.123')); // Prints: true + * console.log(blockList.check('10.0.0.3')); // Prints: true + * console.log(blockList.check('222.111.111.222')); // Prints: false + * + * // IPv6 notation for IPv4 addresses works: + * console.log(blockList.check('::ffff:7b7b:7b7b', 'ipv6')); // Prints: true + * console.log(blockList.check('::ffff:123.123.123.123', 'ipv6')); // Prints: true + * ``` + * @since v15.0.0, v14.18.0 + * @param address The IP address to check + * @param [type='ipv4'] Either `'ipv4'` or `'ipv6'`. + */ + check(address: SocketAddress): boolean; + check(address: string, type?: IPVersion): boolean; + /** + * The list of rules added to the blocklist. + * @since v15.0.0, v14.18.0 + */ + rules: readonly string[]; + /** + * Returns `true` if the `value` is a `net.BlockList`. + * @since v22.13.0 + * @param value Any JS value + */ + static isBlockList(value: unknown): value is BlockList; + /** + * ```js + * const blockList = new net.BlockList(); + * const data = [ + * 'Subnet: IPv4 192.168.1.0/24', + * 'Address: IPv4 10.0.0.5', + * 'Range: IPv4 192.168.2.1-192.168.2.10', + * 'Range: IPv4 10.0.0.1-10.0.0.10', + * ]; + * blockList.fromJSON(data); + * blockList.fromJSON(JSON.stringify(data)); + * ``` + * @since v24.5.0 + * @experimental + */ + fromJSON(data: string | readonly string[]): void; + /** + * @since v24.5.0 + * @experimental + */ + toJSON(): readonly string[]; + } + interface TcpNetConnectOpts extends TcpSocketConnectOpts, SocketConstructorOpts { + timeout?: number | undefined; + } + interface IpcNetConnectOpts extends IpcSocketConnectOpts, SocketConstructorOpts { + timeout?: number | undefined; + } + type NetConnectOpts = TcpNetConnectOpts | IpcNetConnectOpts; + /** + * Creates a new TCP or `IPC` server. + * + * If `allowHalfOpen` is set to `true`, when the other end of the socket + * signals the end of transmission, the server will only send back the end of + * transmission when `socket.end()` is explicitly called. For example, in the + * context of TCP, when a FIN packed is received, a FIN packed is sent + * back only when `socket.end()` is explicitly called. Until then the + * connection is half-closed (non-readable but still writable). See `'end'` event and [RFC 1122](https://tools.ietf.org/html/rfc1122) (section 4.2.2.13) for more information. + * + * If `pauseOnConnect` is set to `true`, then the socket associated with each + * incoming connection will be paused, and no data will be read from its handle. + * This allows connections to be passed between processes without any data being + * read by the original process. To begin reading data from a paused socket, call `socket.resume()`. + * + * The server can be a TCP server or an `IPC` server, depending on what it `listen()` to. + * + * Here is an example of a TCP echo server which listens for connections + * on port 8124: + * + * ```js + * import net from 'node:net'; + * const server = net.createServer((c) => { + * // 'connection' listener. + * console.log('client connected'); + * c.on('end', () => { + * console.log('client disconnected'); + * }); + * c.write('hello\r\n'); + * c.pipe(c); + * }); + * server.on('error', (err) => { + * throw err; + * }); + * server.listen(8124, () => { + * console.log('server bound'); + * }); + * ``` + * + * Test this by using `telnet`: + * + * ```bash + * telnet localhost 8124 + * ``` + * + * To listen on the socket `/tmp/echo.sock`: + * + * ```js + * server.listen('/tmp/echo.sock', () => { + * console.log('server bound'); + * }); + * ``` + * + * Use `nc` to connect to a Unix domain socket server: + * + * ```bash + * nc -U /tmp/echo.sock + * ``` + * @since v0.5.0 + * @param connectionListener Automatically set as a listener for the {@link 'connection'} event. + */ + function createServer(connectionListener?: (socket: Socket) => void): Server; + function createServer(options?: ServerOpts, connectionListener?: (socket: Socket) => void): Server; + /** + * Aliases to {@link createConnection}. + * + * Possible signatures: + * + * * {@link connect} + * * {@link connect} for `IPC` connections. + * * {@link connect} for TCP connections. + */ + function connect(options: NetConnectOpts, connectionListener?: () => void): Socket; + function connect(port: number, host?: string, connectionListener?: () => void): Socket; + function connect(path: string, connectionListener?: () => void): Socket; + /** + * A factory function, which creates a new {@link Socket}, + * immediately initiates connection with `socket.connect()`, + * then returns the `net.Socket` that starts the connection. + * + * When the connection is established, a `'connect'` event will be emitted + * on the returned socket. The last parameter `connectListener`, if supplied, + * will be added as a listener for the `'connect'` event **once**. + * + * Possible signatures: + * + * * {@link createConnection} + * * {@link createConnection} for `IPC` connections. + * * {@link createConnection} for TCP connections. + * + * The {@link connect} function is an alias to this function. + */ + function createConnection(options: NetConnectOpts, connectionListener?: () => void): Socket; + function createConnection(port: number, host?: string, connectionListener?: () => void): Socket; + function createConnection(path: string, connectionListener?: () => void): Socket; + /** + * Gets the current default value of the `autoSelectFamily` option of `socket.connect(options)`. + * The initial default value is `true`, unless the command line option`--no-network-family-autoselection` is provided. + * @since v19.4.0 + */ + function getDefaultAutoSelectFamily(): boolean; + /** + * Sets the default value of the `autoSelectFamily` option of `socket.connect(options)`. + * @param value The new default value. + * The initial default value is `true`, unless the command line option + * `--no-network-family-autoselection` is provided. + * @since v19.4.0 + */ + function setDefaultAutoSelectFamily(value: boolean): void; + /** + * Gets the current default value of the `autoSelectFamilyAttemptTimeout` option of `socket.connect(options)`. + * The initial default value is `500` or the value specified via the command line option `--network-family-autoselection-attempt-timeout`. + * @returns The current default value of the `autoSelectFamilyAttemptTimeout` option. + * @since v19.8.0, v18.8.0 + */ + function getDefaultAutoSelectFamilyAttemptTimeout(): number; + /** + * Sets the default value of the `autoSelectFamilyAttemptTimeout` option of `socket.connect(options)`. + * @param value The new default value, which must be a positive number. If the number is less than `10`, the value `10` is used instead. The initial default value is `250` or the value specified via the command line + * option `--network-family-autoselection-attempt-timeout`. + * @since v19.8.0, v18.8.0 + */ + function setDefaultAutoSelectFamilyAttemptTimeout(value: number): void; + /** + * Returns `6` if `input` is an IPv6 address. Returns `4` if `input` is an IPv4 + * address in [dot-decimal notation](https://en.wikipedia.org/wiki/Dot-decimal_notation) with no leading zeroes. Otherwise, returns`0`. + * + * ```js + * net.isIP('::1'); // returns 6 + * net.isIP('127.0.0.1'); // returns 4 + * net.isIP('127.000.000.001'); // returns 0 + * net.isIP('127.0.0.1/24'); // returns 0 + * net.isIP('fhqwhgads'); // returns 0 + * ``` + * @since v0.3.0 + */ + function isIP(input: string): number; + /** + * Returns `true` if `input` is an IPv4 address in [dot-decimal notation](https://en.wikipedia.org/wiki/Dot-decimal_notation) with no + * leading zeroes. Otherwise, returns `false`. + * + * ```js + * net.isIPv4('127.0.0.1'); // returns true + * net.isIPv4('127.000.000.001'); // returns false + * net.isIPv4('127.0.0.1/24'); // returns false + * net.isIPv4('fhqwhgads'); // returns false + * ``` + * @since v0.3.0 + */ + function isIPv4(input: string): boolean; + /** + * Returns `true` if `input` is an IPv6 address. Otherwise, returns `false`. + * + * ```js + * net.isIPv6('::1'); // returns true + * net.isIPv6('fhqwhgads'); // returns false + * ``` + * @since v0.3.0 + */ + function isIPv6(input: string): boolean; + interface SocketAddressInitOptions { + /** + * The network address as either an IPv4 or IPv6 string. + * @default 127.0.0.1 + */ + address?: string | undefined; + /** + * @default `'ipv4'` + */ + family?: IPVersion | undefined; + /** + * An IPv6 flow-label used only if `family` is `'ipv6'`. + * @default 0 + */ + flowlabel?: number | undefined; + /** + * An IP port. + * @default 0 + */ + port?: number | undefined; + } + /** + * @since v15.14.0, v14.18.0 + */ + class SocketAddress { + constructor(options: SocketAddressInitOptions); + /** + * Either \`'ipv4'\` or \`'ipv6'\`. + * @since v15.14.0, v14.18.0 + */ + readonly address: string; + /** + * Either \`'ipv4'\` or \`'ipv6'\`. + * @since v15.14.0, v14.18.0 + */ + readonly family: IPVersion; + /** + * @since v15.14.0, v14.18.0 + */ + readonly port: number; + /** + * @since v15.14.0, v14.18.0 + */ + readonly flowlabel: number; + /** + * @since v22.13.0 + * @param input An input string containing an IP address and optional port, + * e.g. `123.1.2.3:1234` or `[1::1]:1234`. + * @returns Returns a `SocketAddress` if parsing was successful. + * Otherwise returns `undefined`. + */ + static parse(input: string): SocketAddress | undefined; + } +} +declare module "net" { + export * from "node:net"; +} diff --git a/server/node_modules/@types/node/os.d.ts b/server/node_modules/@types/node/os.d.ts new file mode 100644 index 0000000..db86e9b --- /dev/null +++ b/server/node_modules/@types/node/os.d.ts @@ -0,0 +1,507 @@ +/** + * The `node:os` module provides operating system-related utility methods and + * properties. It can be accessed using: + * + * ```js + * import os from 'node:os'; + * ``` + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/os.js) + */ +declare module "node:os" { + import { NonSharedBuffer } from "buffer"; + interface CpuInfo { + model: string; + speed: number; + times: { + /** The number of milliseconds the CPU has spent in user mode. */ + user: number; + /** The number of milliseconds the CPU has spent in nice mode. */ + nice: number; + /** The number of milliseconds the CPU has spent in sys mode. */ + sys: number; + /** The number of milliseconds the CPU has spent in idle mode. */ + idle: number; + /** The number of milliseconds the CPU has spent in irq mode. */ + irq: number; + }; + } + interface NetworkInterfaceBase { + address: string; + netmask: string; + mac: string; + internal: boolean; + cidr: string | null; + scopeid?: number; + } + interface NetworkInterfaceInfoIPv4 extends NetworkInterfaceBase { + family: "IPv4"; + } + interface NetworkInterfaceInfoIPv6 extends NetworkInterfaceBase { + family: "IPv6"; + scopeid: number; + } + interface UserInfo<T> { + username: T; + uid: number; + gid: number; + shell: T | null; + homedir: T; + } + type NetworkInterfaceInfo = NetworkInterfaceInfoIPv4 | NetworkInterfaceInfoIPv6; + /** + * Returns the host name of the operating system as a string. + * @since v0.3.3 + */ + function hostname(): string; + /** + * Returns an array containing the 1, 5, and 15 minute load averages. + * + * The load average is a measure of system activity calculated by the operating + * system and expressed as a fractional number. + * + * The load average is a Unix-specific concept. On Windows, the return value is + * always `[0, 0, 0]`. + * @since v0.3.3 + */ + function loadavg(): number[]; + /** + * Returns the system uptime in number of seconds. + * @since v0.3.3 + */ + function uptime(): number; + /** + * Returns the amount of free system memory in bytes as an integer. + * @since v0.3.3 + */ + function freemem(): number; + /** + * Returns the total amount of system memory in bytes as an integer. + * @since v0.3.3 + */ + function totalmem(): number; + /** + * Returns an array of objects containing information about each logical CPU core. + * The array will be empty if no CPU information is available, such as if the `/proc` file system is unavailable. + * + * The properties included on each object include: + * + * ```js + * [ + * { + * model: 'Intel(R) Core(TM) i7 CPU 860 @ 2.80GHz', + * speed: 2926, + * times: { + * user: 252020, + * nice: 0, + * sys: 30340, + * idle: 1070356870, + * irq: 0, + * }, + * }, + * { + * model: 'Intel(R) Core(TM) i7 CPU 860 @ 2.80GHz', + * speed: 2926, + * times: { + * user: 306960, + * nice: 0, + * sys: 26980, + * idle: 1071569080, + * irq: 0, + * }, + * }, + * { + * model: 'Intel(R) Core(TM) i7 CPU 860 @ 2.80GHz', + * speed: 2926, + * times: { + * user: 248450, + * nice: 0, + * sys: 21750, + * idle: 1070919370, + * irq: 0, + * }, + * }, + * { + * model: 'Intel(R) Core(TM) i7 CPU 860 @ 2.80GHz', + * speed: 2926, + * times: { + * user: 256880, + * nice: 0, + * sys: 19430, + * idle: 1070905480, + * irq: 20, + * }, + * }, + * ] + * ``` + * + * `nice` values are POSIX-only. On Windows, the `nice` values of all processors + * are always 0. + * + * `os.cpus().length` should not be used to calculate the amount of parallelism + * available to an application. Use {@link availableParallelism} for this purpose. + * @since v0.3.3 + */ + function cpus(): CpuInfo[]; + /** + * Returns an estimate of the default amount of parallelism a program should use. + * Always returns a value greater than zero. + * + * This function is a small wrapper about libuv's [`uv_available_parallelism()`](https://docs.libuv.org/en/v1.x/misc.html#c.uv_available_parallelism). + * @since v19.4.0, v18.14.0 + */ + function availableParallelism(): number; + /** + * Returns the operating system name as returned by [`uname(3)`](https://linux.die.net/man/3/uname). For example, it + * returns `'Linux'` on Linux, `'Darwin'` on macOS, and `'Windows_NT'` on Windows. + * + * See [https://en.wikipedia.org/wiki/Uname#Examples](https://en.wikipedia.org/wiki/Uname#Examples) for additional information + * about the output of running [`uname(3)`](https://linux.die.net/man/3/uname) on various operating systems. + * @since v0.3.3 + */ + function type(): string; + /** + * Returns the operating system as a string. + * + * On POSIX systems, the operating system release is determined by calling [`uname(3)`](https://linux.die.net/man/3/uname). On Windows, `GetVersionExW()` is used. See + * [https://en.wikipedia.org/wiki/Uname#Examples](https://en.wikipedia.org/wiki/Uname#Examples) for more information. + * @since v0.3.3 + */ + function release(): string; + /** + * Returns an object containing network interfaces that have been assigned a + * network address. + * + * Each key on the returned object identifies a network interface. The associated + * value is an array of objects that each describe an assigned network address. + * + * The properties available on the assigned network address object include: + * + * ```js + * { + * lo: [ + * { + * address: '127.0.0.1', + * netmask: '255.0.0.0', + * family: 'IPv4', + * mac: '00:00:00:00:00:00', + * internal: true, + * cidr: '127.0.0.1/8' + * }, + * { + * address: '::1', + * netmask: 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', + * family: 'IPv6', + * mac: '00:00:00:00:00:00', + * scopeid: 0, + * internal: true, + * cidr: '::1/128' + * } + * ], + * eth0: [ + * { + * address: '192.168.1.108', + * netmask: '255.255.255.0', + * family: 'IPv4', + * mac: '01:02:03:0a:0b:0c', + * internal: false, + * cidr: '192.168.1.108/24' + * }, + * { + * address: 'fe80::a00:27ff:fe4e:66a1', + * netmask: 'ffff:ffff:ffff:ffff::', + * family: 'IPv6', + * mac: '01:02:03:0a:0b:0c', + * scopeid: 1, + * internal: false, + * cidr: 'fe80::a00:27ff:fe4e:66a1/64' + * } + * ] + * } + * ``` + * @since v0.6.0 + */ + function networkInterfaces(): NodeJS.Dict<NetworkInterfaceInfo[]>; + /** + * Returns the string path of the current user's home directory. + * + * On POSIX, it uses the `$HOME` environment variable if defined. Otherwise it + * uses the [effective UID](https://en.wikipedia.org/wiki/User_identifier#Effective_user_ID) to look up the user's home directory. + * + * On Windows, it uses the `USERPROFILE` environment variable if defined. + * Otherwise it uses the path to the profile directory of the current user. + * @since v2.3.0 + */ + function homedir(): string; + interface UserInfoOptions { + encoding?: BufferEncoding | "buffer" | undefined; + } + interface UserInfoOptionsWithBufferEncoding extends UserInfoOptions { + encoding: "buffer"; + } + interface UserInfoOptionsWithStringEncoding extends UserInfoOptions { + encoding?: BufferEncoding | undefined; + } + /** + * Returns information about the currently effective user. On POSIX platforms, + * this is typically a subset of the password file. The returned object includes + * the `username`, `uid`, `gid`, `shell`, and `homedir`. On Windows, the `uid` and `gid` fields are `-1`, and `shell` is `null`. + * + * The value of `homedir` returned by `os.userInfo()` is provided by the operating + * system. This differs from the result of `os.homedir()`, which queries + * environment variables for the home directory before falling back to the + * operating system response. + * + * Throws a [`SystemError`](https://nodejs.org/docs/latest-v25.x/api/errors.html#class-systemerror) if a user has no `username` or `homedir`. + * @since v6.0.0 + */ + function userInfo(options?: UserInfoOptionsWithStringEncoding): UserInfo<string>; + function userInfo(options: UserInfoOptionsWithBufferEncoding): UserInfo<NonSharedBuffer>; + function userInfo(options: UserInfoOptions): UserInfo<string | NonSharedBuffer>; + type SignalConstants = { + [key in NodeJS.Signals]: number; + }; + namespace constants { + const UV_UDP_REUSEADDR: number; + namespace signals {} + const signals: SignalConstants; + namespace errno { + const E2BIG: number; + const EACCES: number; + const EADDRINUSE: number; + const EADDRNOTAVAIL: number; + const EAFNOSUPPORT: number; + const EAGAIN: number; + const EALREADY: number; + const EBADF: number; + const EBADMSG: number; + const EBUSY: number; + const ECANCELED: number; + const ECHILD: number; + const ECONNABORTED: number; + const ECONNREFUSED: number; + const ECONNRESET: number; + const EDEADLK: number; + const EDESTADDRREQ: number; + const EDOM: number; + const EDQUOT: number; + const EEXIST: number; + const EFAULT: number; + const EFBIG: number; + const EHOSTUNREACH: number; + const EIDRM: number; + const EILSEQ: number; + const EINPROGRESS: number; + const EINTR: number; + const EINVAL: number; + const EIO: number; + const EISCONN: number; + const EISDIR: number; + const ELOOP: number; + const EMFILE: number; + const EMLINK: number; + const EMSGSIZE: number; + const EMULTIHOP: number; + const ENAMETOOLONG: number; + const ENETDOWN: number; + const ENETRESET: number; + const ENETUNREACH: number; + const ENFILE: number; + const ENOBUFS: number; + const ENODATA: number; + const ENODEV: number; + const ENOENT: number; + const ENOEXEC: number; + const ENOLCK: number; + const ENOLINK: number; + const ENOMEM: number; + const ENOMSG: number; + const ENOPROTOOPT: number; + const ENOSPC: number; + const ENOSR: number; + const ENOSTR: number; + const ENOSYS: number; + const ENOTCONN: number; + const ENOTDIR: number; + const ENOTEMPTY: number; + const ENOTSOCK: number; + const ENOTSUP: number; + const ENOTTY: number; + const ENXIO: number; + const EOPNOTSUPP: number; + const EOVERFLOW: number; + const EPERM: number; + const EPIPE: number; + const EPROTO: number; + const EPROTONOSUPPORT: number; + const EPROTOTYPE: number; + const ERANGE: number; + const EROFS: number; + const ESPIPE: number; + const ESRCH: number; + const ESTALE: number; + const ETIME: number; + const ETIMEDOUT: number; + const ETXTBSY: number; + const EWOULDBLOCK: number; + const EXDEV: number; + const WSAEINTR: number; + const WSAEBADF: number; + const WSAEACCES: number; + const WSAEFAULT: number; + const WSAEINVAL: number; + const WSAEMFILE: number; + const WSAEWOULDBLOCK: number; + const WSAEINPROGRESS: number; + const WSAEALREADY: number; + const WSAENOTSOCK: number; + const WSAEDESTADDRREQ: number; + const WSAEMSGSIZE: number; + const WSAEPROTOTYPE: number; + const WSAENOPROTOOPT: number; + const WSAEPROTONOSUPPORT: number; + const WSAESOCKTNOSUPPORT: number; + const WSAEOPNOTSUPP: number; + const WSAEPFNOSUPPORT: number; + const WSAEAFNOSUPPORT: number; + const WSAEADDRINUSE: number; + const WSAEADDRNOTAVAIL: number; + const WSAENETDOWN: number; + const WSAENETUNREACH: number; + const WSAENETRESET: number; + const WSAECONNABORTED: number; + const WSAECONNRESET: number; + const WSAENOBUFS: number; + const WSAEISCONN: number; + const WSAENOTCONN: number; + const WSAESHUTDOWN: number; + const WSAETOOMANYREFS: number; + const WSAETIMEDOUT: number; + const WSAECONNREFUSED: number; + const WSAELOOP: number; + const WSAENAMETOOLONG: number; + const WSAEHOSTDOWN: number; + const WSAEHOSTUNREACH: number; + const WSAENOTEMPTY: number; + const WSAEPROCLIM: number; + const WSAEUSERS: number; + const WSAEDQUOT: number; + const WSAESTALE: number; + const WSAEREMOTE: number; + const WSASYSNOTREADY: number; + const WSAVERNOTSUPPORTED: number; + const WSANOTINITIALISED: number; + const WSAEDISCON: number; + const WSAENOMORE: number; + const WSAECANCELLED: number; + const WSAEINVALIDPROCTABLE: number; + const WSAEINVALIDPROVIDER: number; + const WSAEPROVIDERFAILEDINIT: number; + const WSASYSCALLFAILURE: number; + const WSASERVICE_NOT_FOUND: number; + const WSATYPE_NOT_FOUND: number; + const WSA_E_NO_MORE: number; + const WSA_E_CANCELLED: number; + const WSAEREFUSED: number; + } + namespace dlopen { + const RTLD_LAZY: number; + const RTLD_NOW: number; + const RTLD_GLOBAL: number; + const RTLD_LOCAL: number; + const RTLD_DEEPBIND: number; + } + namespace priority { + const PRIORITY_LOW: number; + const PRIORITY_BELOW_NORMAL: number; + const PRIORITY_NORMAL: number; + const PRIORITY_ABOVE_NORMAL: number; + const PRIORITY_HIGH: number; + const PRIORITY_HIGHEST: number; + } + } + const devNull: string; + /** + * The operating system-specific end-of-line marker. + * * `\n` on POSIX + * * `\r\n` on Windows + */ + const EOL: string; + /** + * Returns the operating system CPU architecture for which the Node.js binary was + * compiled. Possible values are `'arm'`, `'arm64'`, `'ia32'`, `'loong64'`, + * `'mips'`, `'mipsel'`, `'ppc64'`, `'riscv64'`, `'s390x'`, and `'x64'`. + * + * The return value is equivalent to [process.arch](https://nodejs.org/docs/latest-v25.x/api/process.html#processarch). + * @since v0.5.0 + */ + function arch(): NodeJS.Architecture; + /** + * Returns a string identifying the kernel version. + * + * On POSIX systems, the operating system release is determined by calling [`uname(3)`](https://linux.die.net/man/3/uname). On Windows, `RtlGetVersion()` is used, and if it is not + * available, `GetVersionExW()` will be used. See [https://en.wikipedia.org/wiki/Uname#Examples](https://en.wikipedia.org/wiki/Uname#Examples) for more information. + * @since v13.11.0, v12.17.0 + */ + function version(): string; + /** + * Returns a string identifying the operating system platform for which + * the Node.js binary was compiled. The value is set at compile time. + * Possible values are `'aix'`, `'darwin'`, `'freebsd'`, `'linux'`, `'openbsd'`, `'sunos'`, and `'win32'`. + * + * The return value is equivalent to `process.platform`. + * + * The value `'android'` may also be returned if Node.js is built on the Android + * operating system. [Android support is experimental](https://github.com/nodejs/node/blob/HEAD/BUILDING.md#androidandroid-based-devices-eg-firefox-os). + * @since v0.5.0 + */ + function platform(): NodeJS.Platform; + /** + * Returns the machine type as a string, such as `arm`, `arm64`, `aarch64`, + * `mips`, `mips64`, `ppc64`, `ppc64le`, `s390x`, `i386`, `i686`, `x86_64`. + * + * On POSIX systems, the machine type is determined by calling [`uname(3)`](https://linux.die.net/man/3/uname). On Windows, `RtlGetVersion()` is used, and if it is not + * available, `GetVersionExW()` will be used. See [https://en.wikipedia.org/wiki/Uname#Examples](https://en.wikipedia.org/wiki/Uname#Examples) for more information. + * @since v18.9.0, v16.18.0 + */ + function machine(): string; + /** + * Returns the operating system's default directory for temporary files as a + * string. + * @since v0.9.9 + */ + function tmpdir(): string; + /** + * Returns a string identifying the endianness of the CPU for which the Node.js + * binary was compiled. + * + * Possible values are `'BE'` for big endian and `'LE'` for little endian. + * @since v0.9.4 + */ + function endianness(): "BE" | "LE"; + /** + * Returns the scheduling priority for the process specified by `pid`. If `pid` is + * not provided or is `0`, the priority of the current process is returned. + * @since v10.10.0 + * @param [pid=0] The process ID to retrieve scheduling priority for. + */ + function getPriority(pid?: number): number; + /** + * Attempts to set the scheduling priority for the process specified by `pid`. If `pid` is not provided or is `0`, the process ID of the current process is used. + * + * The `priority` input must be an integer between `-20` (high priority) and `19` (low priority). Due to differences between Unix priority levels and Windows + * priority classes, `priority` is mapped to one of six priority constants in `os.constants.priority`. When retrieving a process priority level, this range + * mapping may cause the return value to be slightly different on Windows. To avoid + * confusion, set `priority` to one of the priority constants. + * + * On Windows, setting priority to `PRIORITY_HIGHEST` requires elevated user + * privileges. Otherwise the set priority will be silently reduced to `PRIORITY_HIGH`. + * @since v10.10.0 + * @param [pid=0] The process ID to set scheduling priority for. + * @param priority The scheduling priority to assign to the process. + */ + function setPriority(priority: number): void; + function setPriority(pid: number, priority: number): void; +} +declare module "os" { + export * from "node:os"; +} diff --git a/server/node_modules/@types/node/package.json b/server/node_modules/@types/node/package.json new file mode 100644 index 0000000..d346711 --- /dev/null +++ b/server/node_modules/@types/node/package.json @@ -0,0 +1,155 @@ +{ + "name": "@types/node", + "version": "25.2.3", + "description": "TypeScript definitions for node", + "homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node", + "license": "MIT", + "contributors": [ + { + "name": "Microsoft TypeScript", + "githubUsername": "Microsoft", + "url": "https://github.com/Microsoft" + }, + { + "name": "Alberto Schiabel", + "githubUsername": "jkomyno", + "url": "https://github.com/jkomyno" + }, + { + "name": "Andrew Makarov", + "githubUsername": "r3nya", + "url": "https://github.com/r3nya" + }, + { + "name": "Benjamin Toueg", + "githubUsername": "btoueg", + "url": "https://github.com/btoueg" + }, + { + "name": "David Junger", + "githubUsername": "touffy", + "url": "https://github.com/touffy" + }, + { + "name": "Mohsen Azimi", + "githubUsername": "mohsen1", + "url": "https://github.com/mohsen1" + }, + { + "name": "Nikita Galkin", + "githubUsername": "galkin", + "url": "https://github.com/galkin" + }, + { + "name": "Sebastian Silbermann", + "githubUsername": "eps1lon", + "url": "https://github.com/eps1lon" + }, + { + "name": "Wilco Bakker", + "githubUsername": "WilcoBakker", + "url": "https://github.com/WilcoBakker" + }, + { + "name": "Marcin Kopacz", + "githubUsername": "chyzwar", + "url": "https://github.com/chyzwar" + }, + { + "name": "Trivikram Kamat", + "githubUsername": "trivikr", + "url": "https://github.com/trivikr" + }, + { + "name": "Junxiao Shi", + "githubUsername": "yoursunny", + "url": "https://github.com/yoursunny" + }, + { + "name": "Ilia Baryshnikov", + "githubUsername": "qwelias", + "url": "https://github.com/qwelias" + }, + { + "name": "ExE Boss", + "githubUsername": "ExE-Boss", + "url": "https://github.com/ExE-Boss" + }, + { + "name": "Piotr Błażejewicz", + "githubUsername": "peterblazejewicz", + "url": "https://github.com/peterblazejewicz" + }, + { + "name": "Anna Henningsen", + "githubUsername": "addaleax", + "url": "https://github.com/addaleax" + }, + { + "name": "Victor Perin", + "githubUsername": "victorperin", + "url": "https://github.com/victorperin" + }, + { + "name": "NodeJS Contributors", + "githubUsername": "NodeJS", + "url": "https://github.com/NodeJS" + }, + { + "name": "Linus Unnebäck", + "githubUsername": "LinusU", + "url": "https://github.com/LinusU" + }, + { + "name": "wafuwafu13", + "githubUsername": "wafuwafu13", + "url": "https://github.com/wafuwafu13" + }, + { + "name": "Matteo Collina", + "githubUsername": "mcollina", + "url": "https://github.com/mcollina" + }, + { + "name": "Dmitry Semigradsky", + "githubUsername": "Semigradsky", + "url": "https://github.com/Semigradsky" + }, + { + "name": "René", + "githubUsername": "Renegade334", + "url": "https://github.com/Renegade334" + }, + { + "name": "Yagiz Nizipli", + "githubUsername": "anonrig", + "url": "https://github.com/anonrig" + } + ], + "main": "", + "types": "index.d.ts", + "typesVersions": { + "<=5.6": { + "*": [ + "ts5.6/*" + ] + }, + "<=5.7": { + "*": [ + "ts5.7/*" + ] + } + }, + "repository": { + "type": "git", + "url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git", + "directory": "types/node" + }, + "scripts": {}, + "dependencies": { + "undici-types": "~7.16.0" + }, + "peerDependencies": {}, + "typesPublisherContentHash": "8b755d23bb0d24c0d68b2add771cb66e2226b9633549b6f9c190a2a5f9831395", + "typeScriptVersion": "5.2" +} \ No newline at end of file diff --git a/server/node_modules/@types/node/path.d.ts b/server/node_modules/@types/node/path.d.ts new file mode 100644 index 0000000..c0b22f6 --- /dev/null +++ b/server/node_modules/@types/node/path.d.ts @@ -0,0 +1,187 @@ +/** + * The `node:path` module provides utilities for working with file and directory + * paths. It can be accessed using: + * + * ```js + * import path from 'node:path'; + * ``` + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/path.js) + */ +declare module "node:path" { + namespace path { + /** + * A parsed path object generated by path.parse() or consumed by path.format(). + */ + interface ParsedPath { + /** + * The root of the path such as '/' or 'c:\' + */ + root: string; + /** + * The full directory path such as '/home/user/dir' or 'c:\path\dir' + */ + dir: string; + /** + * The file name including extension (if any) such as 'index.html' + */ + base: string; + /** + * The file extension (if any) such as '.html' + */ + ext: string; + /** + * The file name without extension (if any) such as 'index' + */ + name: string; + } + interface FormatInputPathObject { + /** + * The root of the path such as '/' or 'c:\' + */ + root?: string | undefined; + /** + * The full directory path such as '/home/user/dir' or 'c:\path\dir' + */ + dir?: string | undefined; + /** + * The file name including extension (if any) such as 'index.html' + */ + base?: string | undefined; + /** + * The file extension (if any) such as '.html' + */ + ext?: string | undefined; + /** + * The file name without extension (if any) such as 'index' + */ + name?: string | undefined; + } + /** + * Normalize a string path, reducing '..' and '.' parts. + * When multiple slashes are found, they're replaced by a single one; when the path contains a trailing slash, it is preserved. On Windows backslashes are used. If the path is a zero-length string, '.' is returned, representing the current working directory. + * + * @param path string path to normalize. + * @throws {TypeError} if `path` is not a string. + */ + function normalize(path: string): string; + /** + * Join all arguments together and normalize the resulting path. + * + * @param paths paths to join. + * @throws {TypeError} if any of the path segments is not a string. + */ + function join(...paths: string[]): string; + /** + * The right-most parameter is considered {to}. Other parameters are considered an array of {from}. + * + * Starting from leftmost {from} parameter, resolves {to} to an absolute path. + * + * If {to} isn't already absolute, {from} arguments are prepended in right to left order, + * until an absolute path is found. If after using all {from} paths still no absolute path is found, + * the current working directory is used as well. The resulting path is normalized, + * and trailing slashes are removed unless the path gets resolved to the root directory. + * + * @param paths A sequence of paths or path segments. + * @throws {TypeError} if any of the arguments is not a string. + */ + function resolve(...paths: string[]): string; + /** + * The `path.matchesGlob()` method determines if `path` matches the `pattern`. + * @param path The path to glob-match against. + * @param pattern The glob to check the path against. + * @returns Whether or not the `path` matched the `pattern`. + * @throws {TypeError} if `path` or `pattern` are not strings. + * @since v22.5.0 + */ + function matchesGlob(path: string, pattern: string): boolean; + /** + * Determines whether {path} is an absolute path. An absolute path will always resolve to the same location, regardless of the working directory. + * + * If the given {path} is a zero-length string, `false` will be returned. + * + * @param path path to test. + * @throws {TypeError} if `path` is not a string. + */ + function isAbsolute(path: string): boolean; + /** + * Solve the relative path from {from} to {to} based on the current working directory. + * At times we have two absolute paths, and we need to derive the relative path from one to the other. This is actually the reverse transform of path.resolve. + * + * @throws {TypeError} if either `from` or `to` is not a string. + */ + function relative(from: string, to: string): string; + /** + * Return the directory name of a path. Similar to the Unix dirname command. + * + * @param path the path to evaluate. + * @throws {TypeError} if `path` is not a string. + */ + function dirname(path: string): string; + /** + * Return the last portion of a path. Similar to the Unix basename command. + * Often used to extract the file name from a fully qualified path. + * + * @param path the path to evaluate. + * @param suffix optionally, an extension to remove from the result. + * @throws {TypeError} if `path` is not a string or if `ext` is given and is not a string. + */ + function basename(path: string, suffix?: string): string; + /** + * Return the extension of the path, from the last '.' to end of string in the last portion of the path. + * If there is no '.' in the last portion of the path or the first character of it is '.', then it returns an empty string. + * + * @param path the path to evaluate. + * @throws {TypeError} if `path` is not a string. + */ + function extname(path: string): string; + /** + * The platform-specific file separator. '\\' or '/'. + */ + const sep: "\\" | "/"; + /** + * The platform-specific file delimiter. ';' or ':'. + */ + const delimiter: ";" | ":"; + /** + * Returns an object from a path string - the opposite of format(). + * + * @param path path to evaluate. + * @throws {TypeError} if `path` is not a string. + */ + function parse(path: string): ParsedPath; + /** + * Returns a path string from an object - the opposite of parse(). + * + * @param pathObject path to evaluate. + */ + function format(pathObject: FormatInputPathObject): string; + /** + * On Windows systems only, returns an equivalent namespace-prefixed path for the given path. + * If path is not a string, path will be returned without modifications. + * This method is meaningful only on Windows system. + * On POSIX systems, the method is non-operational and always returns path without modifications. + */ + function toNamespacedPath(path: string): string; + } + namespace path { + export { + /** + * The `path.posix` property provides access to POSIX specific implementations of the `path` methods. + * + * The API is accessible via `require('node:path').posix` or `require('node:path/posix')`. + */ + path as posix, + /** + * The `path.win32` property provides access to Windows-specific implementations of the `path` methods. + * + * The API is accessible via `require('node:path').win32` or `require('node:path/win32')`. + */ + path as win32, + }; + } + export = path; +} +declare module "path" { + import path = require("node:path"); + export = path; +} diff --git a/server/node_modules/@types/node/path/posix.d.ts b/server/node_modules/@types/node/path/posix.d.ts new file mode 100644 index 0000000..d60f629 --- /dev/null +++ b/server/node_modules/@types/node/path/posix.d.ts @@ -0,0 +1,8 @@ +declare module "node:path/posix" { + import path = require("node:path"); + export = path.posix; +} +declare module "path/posix" { + import path = require("path"); + export = path.posix; +} diff --git a/server/node_modules/@types/node/path/win32.d.ts b/server/node_modules/@types/node/path/win32.d.ts new file mode 100644 index 0000000..e6aa9fa --- /dev/null +++ b/server/node_modules/@types/node/path/win32.d.ts @@ -0,0 +1,8 @@ +declare module "node:path/win32" { + import path = require("node:path"); + export = path.win32; +} +declare module "path/win32" { + import path = require("path"); + export = path.win32; +} diff --git a/server/node_modules/@types/node/perf_hooks.d.ts b/server/node_modules/@types/node/perf_hooks.d.ts new file mode 100644 index 0000000..4dd0632 --- /dev/null +++ b/server/node_modules/@types/node/perf_hooks.d.ts @@ -0,0 +1,643 @@ +/** + * This module provides an implementation of a subset of the W3C [Web Performance APIs](https://w3c.github.io/perf-timing-primer/) as well as additional APIs for + * Node.js-specific performance measurements. + * + * Node.js supports the following [Web Performance APIs](https://w3c.github.io/perf-timing-primer/): + * + * * [High Resolution Time](https://www.w3.org/TR/hr-time-2) + * * [Performance Timeline](https://w3c.github.io/performance-timeline/) + * * [User Timing](https://www.w3.org/TR/user-timing/) + * * [Resource Timing](https://www.w3.org/TR/resource-timing-2/) + * + * ```js + * import { PerformanceObserver, performance } from 'node:perf_hooks'; + * + * const obs = new PerformanceObserver((items) => { + * console.log(items.getEntries()[0].duration); + * performance.clearMarks(); + * }); + * obs.observe({ type: 'measure' }); + * performance.measure('Start to Now'); + * + * performance.mark('A'); + * doSomeLongRunningProcess(() => { + * performance.measure('A to Now', 'A'); + * + * performance.mark('B'); + * performance.measure('A to B', 'A', 'B'); + * }); + * ``` + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/perf_hooks.js) + */ +declare module "node:perf_hooks" { + import { InternalEventTargetEventProperties } from "node:events"; + // #region web types + type EntryType = + | "dns" // Node.js only + | "function" // Node.js only + | "gc" // Node.js only + | "http2" // Node.js only + | "http" // Node.js only + | "mark" // available on the Web + | "measure" // available on the Web + | "net" // Node.js only + | "node" // Node.js only + | "resource"; // available on the Web + interface ConnectionTimingInfo { + domainLookupStartTime: number; + domainLookupEndTime: number; + connectionStartTime: number; + connectionEndTime: number; + secureConnectionStartTime: number; + ALPNNegotiatedProtocol: string; + } + interface FetchTimingInfo { + startTime: number; + redirectStartTime: number; + redirectEndTime: number; + postRedirectStartTime: number; + finalServiceWorkerStartTime: number; + finalNetworkRequestStartTime: number; + finalNetworkResponseStartTime: number; + endTime: number; + finalConnectionTimingInfo: ConnectionTimingInfo | null; + encodedBodySize: number; + decodedBodySize: number; + } + type PerformanceEntryList = PerformanceEntry[]; + interface PerformanceMarkOptions { + detail?: any; + startTime?: number; + } + interface PerformanceMeasureOptions { + detail?: any; + duration?: number; + end?: string | number; + start?: string | number; + } + interface PerformanceObserverCallback { + (entries: PerformanceObserverEntryList, observer: PerformanceObserver): void; + } + interface PerformanceObserverInit { + buffered?: boolean; + entryTypes?: EntryType[]; + type?: EntryType; + } + // TODO: remove in next major + /** @deprecated Use `TimerifyOptions` instead. */ + interface PerformanceTimerifyOptions extends TimerifyOptions {} + interface PerformanceEventMap { + "resourcetimingbufferfull": Event; + } + interface Performance extends EventTarget, InternalEventTargetEventProperties<PerformanceEventMap> { + readonly nodeTiming: PerformanceNodeTiming; + readonly timeOrigin: number; + clearMarks(markName?: string): void; + clearMeasures(measureName?: string): void; + clearResourceTimings(resourceTimingName?: string): void; + getEntries(): PerformanceEntryList; + getEntriesByName(name: string, type?: EntryType): PerformanceEntryList; + getEntriesByType(type: EntryType): PerformanceEntryList; + mark(markName: string, markOptions?: PerformanceMarkOptions): PerformanceMark; + markResourceTiming( + timingInfo: FetchTimingInfo, + requestedUrl: string, + initiatorType: string, + global: unknown, + cacheMode: string, + bodyInfo: unknown, + responseStatus: number, + deliveryType?: string, + ): PerformanceResourceTiming; + measure(measureName: string, startMark?: string, endMark?: string): PerformanceMeasure; + measure(measureName: string, options: PerformanceMeasureOptions, endMark?: string): PerformanceMeasure; + now(): number; + setResourceTimingBufferSize(maxSize: number): void; + toJSON(): any; + addEventListener<K extends keyof PerformanceEventMap>( + type: K, + listener: (ev: PerformanceEventMap[K]) => void, + options?: AddEventListenerOptions | boolean, + ): void; + addEventListener( + type: string, + listener: EventListener | EventListenerObject, + options?: AddEventListenerOptions | boolean, + ): void; + removeEventListener<K extends keyof PerformanceEventMap>( + type: K, + listener: (ev: PerformanceEventMap[K]) => void, + options?: EventListenerOptions | boolean, + ): void; + removeEventListener( + type: string, + listener: EventListener | EventListenerObject, + options?: EventListenerOptions | boolean, + ): void; + /** + * This is an alias of `perf_hooks.eventLoopUtilization()`. + * + * _This property is an extension by Node.js. It is not available in Web browsers._ + * @since v14.10.0, v12.19.0 + * @param utilization1 The result of a previous call to + * `eventLoopUtilization()`. + * @param utilization2 The result of a previous call to + * `eventLoopUtilization()` prior to `utilization1`. + */ + eventLoopUtilization( + utilization1?: EventLoopUtilization, + utilization2?: EventLoopUtilization, + ): EventLoopUtilization; + /** + * This is an alias of `perf_hooks.timerify()`. + * + * _This property is an extension by Node.js. It is not available in Web browsers._ + * @since v8.5.0 + */ + timerify<T extends (...args: any[]) => any>(fn: T, options?: TimerifyOptions): T; + } + var Performance: { + prototype: Performance; + new(): Performance; + }; + interface PerformanceEntry { + readonly duration: number; + readonly entryType: EntryType; + readonly name: string; + readonly startTime: number; + toJSON(): any; + } + var PerformanceEntry: { + prototype: PerformanceEntry; + new(): PerformanceEntry; + }; + interface PerformanceMark extends PerformanceEntry { + readonly detail: any; + readonly entryType: "mark"; + } + var PerformanceMark: { + prototype: PerformanceMark; + new(markName: string, markOptions?: PerformanceMarkOptions): PerformanceMark; + }; + interface PerformanceMeasure extends PerformanceEntry { + readonly detail: any; + readonly entryType: "measure"; + } + var PerformanceMeasure: { + prototype: PerformanceMeasure; + new(): PerformanceMeasure; + }; + interface PerformanceObserver { + disconnect(): void; + observe(options: PerformanceObserverInit): void; + takeRecords(): PerformanceEntryList; + } + var PerformanceObserver: { + prototype: PerformanceObserver; + new(callback: PerformanceObserverCallback): PerformanceObserver; + readonly supportedEntryTypes: readonly EntryType[]; + }; + interface PerformanceObserverEntryList { + getEntries(): PerformanceEntryList; + getEntriesByName(name: string, type?: EntryType): PerformanceEntryList; + getEntriesByType(type: EntryType): PerformanceEntryList; + } + var PerformanceObserverEntryList: { + prototype: PerformanceObserverEntryList; + new(): PerformanceObserverEntryList; + }; + interface PerformanceResourceTiming extends PerformanceEntry { + readonly connectEnd: number; + readonly connectStart: number; + readonly decodedBodySize: number; + readonly domainLookupEnd: number; + readonly domainLookupStart: number; + readonly encodedBodySize: number; + readonly entryType: "resource"; + readonly fetchStart: number; + readonly initiatorType: string; + readonly nextHopProtocol: string; + readonly redirectEnd: number; + readonly redirectStart: number; + readonly requestStart: number; + readonly responseEnd: number; + readonly responseStart: number; + readonly responseStatus: number; + readonly secureConnectionStart: number; + readonly transferSize: number; + readonly workerStart: number; + toJSON(): any; + } + var PerformanceResourceTiming: { + prototype: PerformanceResourceTiming; + new(): PerformanceResourceTiming; + }; + var performance: Performance; + // #endregion + /** + * _This class is an extension by Node.js. It is not available in Web browsers._ + * + * Provides detailed Node.js timing data. + * + * The constructor of this class is not exposed to users directly. + * @since v19.0.0 + */ + class PerformanceNodeEntry extends PerformanceEntry { + /** + * Additional detail specific to the `entryType`. + * @since v16.0.0 + */ + readonly detail: any; + readonly entryType: "dns" | "function" | "gc" | "http2" | "http" | "net" | "node"; + } + interface UVMetrics { + /** + * Number of event loop iterations. + */ + readonly loopCount: number; + /** + * Number of events that have been processed by the event handler. + */ + readonly events: number; + /** + * Number of events that were waiting to be processed when the event provider was called. + */ + readonly eventsWaiting: number; + } + /** + * _This property is an extension by Node.js. It is not available in Web browsers._ + * + * Provides timing details for Node.js itself. The constructor of this class + * is not exposed to users. + * @since v8.5.0 + */ + interface PerformanceNodeTiming extends PerformanceEntry { + /** + * The high resolution millisecond timestamp at which the Node.js process + * completed bootstrapping. If bootstrapping has not yet finished, the property + * has the value of -1. + * @since v8.5.0 + */ + readonly bootstrapComplete: number; + readonly entryType: "node"; + /** + * The high resolution millisecond timestamp at which the Node.js environment was + * initialized. + * @since v8.5.0 + */ + readonly environment: number; + /** + * The high resolution millisecond timestamp of the amount of time the event loop + * has been idle within the event loop's event provider (e.g. `epoll_wait`). This + * does not take CPU usage into consideration. If the event loop has not yet + * started (e.g., in the first tick of the main script), the property has the + * value of 0. + * @since v14.10.0, v12.19.0 + */ + readonly idleTime: number; + /** + * The high resolution millisecond timestamp at which the Node.js event loop + * exited. If the event loop has not yet exited, the property has the value of -1\. + * It can only have a value of not -1 in a handler of the `'exit'` event. + * @since v8.5.0 + */ + readonly loopExit: number; + /** + * The high resolution millisecond timestamp at which the Node.js event loop + * started. If the event loop has not yet started (e.g., in the first tick of the + * main script), the property has the value of -1. + * @since v8.5.0 + */ + readonly loopStart: number; + /** + * The high resolution millisecond timestamp at which the Node.js process was initialized. + * @since v8.5.0 + */ + readonly nodeStart: number; + /** + * This is a wrapper to the `uv_metrics_info` function. + * It returns the current set of event loop metrics. + * + * It is recommended to use this property inside a function whose execution was + * scheduled using `setImmediate` to avoid collecting metrics before finishing all + * operations scheduled during the current loop iteration. + * @since v22.8.0, v20.18.0 + */ + readonly uvMetricsInfo: UVMetrics; + /** + * The high resolution millisecond timestamp at which the V8 platform was + * initialized. + * @since v8.5.0 + */ + readonly v8Start: number; + } + namespace constants { + const NODE_PERFORMANCE_GC_MAJOR: number; + const NODE_PERFORMANCE_GC_MINOR: number; + const NODE_PERFORMANCE_GC_INCREMENTAL: number; + const NODE_PERFORMANCE_GC_WEAKCB: number; + const NODE_PERFORMANCE_GC_FLAGS_NO: number; + const NODE_PERFORMANCE_GC_FLAGS_CONSTRUCT_RETAINED: number; + const NODE_PERFORMANCE_GC_FLAGS_FORCED: number; + const NODE_PERFORMANCE_GC_FLAGS_SYNCHRONOUS_PHANTOM_PROCESSING: number; + const NODE_PERFORMANCE_GC_FLAGS_ALL_AVAILABLE_GARBAGE: number; + const NODE_PERFORMANCE_GC_FLAGS_ALL_EXTERNAL_MEMORY: number; + const NODE_PERFORMANCE_GC_FLAGS_SCHEDULE_IDLE: number; + } + interface EventLoopMonitorOptions { + /** + * The sampling rate in milliseconds. + * Must be greater than zero. + * @default 10 + */ + resolution?: number | undefined; + } + interface Histogram { + /** + * The number of samples recorded by the histogram. + * @since v17.4.0, v16.14.0 + */ + readonly count: number; + /** + * The number of samples recorded by the histogram. + * v17.4.0, v16.14.0 + */ + readonly countBigInt: bigint; + /** + * The number of times the event loop delay exceeded the maximum 1 hour event + * loop delay threshold. + * @since v11.10.0 + */ + readonly exceeds: number; + /** + * The number of times the event loop delay exceeded the maximum 1 hour event loop delay threshold. + * @since v17.4.0, v16.14.0 + */ + readonly exceedsBigInt: bigint; + /** + * The maximum recorded event loop delay. + * @since v11.10.0 + */ + readonly max: number; + /** + * The maximum recorded event loop delay. + * v17.4.0, v16.14.0 + */ + readonly maxBigInt: number; + /** + * The mean of the recorded event loop delays. + * @since v11.10.0 + */ + readonly mean: number; + /** + * The minimum recorded event loop delay. + * @since v11.10.0 + */ + readonly min: number; + /** + * The minimum recorded event loop delay. + * v17.4.0, v16.14.0 + */ + readonly minBigInt: bigint; + /** + * Returns the value at the given percentile. + * @since v11.10.0 + * @param percentile A percentile value in the range (0, 100]. + */ + percentile(percentile: number): number; + /** + * Returns the value at the given percentile. + * @since v17.4.0, v16.14.0 + * @param percentile A percentile value in the range (0, 100]. + */ + percentileBigInt(percentile: number): bigint; + /** + * Returns a `Map` object detailing the accumulated percentile distribution. + * @since v11.10.0 + */ + readonly percentiles: Map<number, number>; + /** + * Returns a `Map` object detailing the accumulated percentile distribution. + * @since v17.4.0, v16.14.0 + */ + readonly percentilesBigInt: Map<bigint, bigint>; + /** + * Resets the collected histogram data. + * @since v11.10.0 + */ + reset(): void; + /** + * The standard deviation of the recorded event loop delays. + * @since v11.10.0 + */ + readonly stddev: number; + } + interface IntervalHistogram extends Histogram { + /** + * Enables the update interval timer. Returns `true` if the timer was + * started, `false` if it was already started. + * @since v11.10.0 + */ + enable(): boolean; + /** + * Disables the update interval timer. Returns `true` if the timer was + * stopped, `false` if it was already stopped. + * @since v11.10.0 + */ + disable(): boolean; + /** + * Disables the update interval timer when the histogram is disposed. + * + * ```js + * const { monitorEventLoopDelay } = require('node:perf_hooks'); + * { + * using hist = monitorEventLoopDelay({ resolution: 20 }); + * hist.enable(); + * // The histogram will be disabled when the block is exited. + * } + * ``` + * @since v24.2.0 + */ + [Symbol.dispose](): void; + } + interface RecordableHistogram extends Histogram { + /** + * @since v15.9.0, v14.18.0 + * @param val The amount to record in the histogram. + */ + record(val: number | bigint): void; + /** + * Calculates the amount of time (in nanoseconds) that has passed since the + * previous call to `recordDelta()` and records that amount in the histogram. + * @since v15.9.0, v14.18.0 + */ + recordDelta(): void; + /** + * Adds the values from `other` to this histogram. + * @since v17.4.0, v16.14.0 + */ + add(other: RecordableHistogram): void; + } + interface EventLoopUtilization { + idle: number; + active: number; + utilization: number; + } + /** + * The `eventLoopUtilization()` function returns an object that contains the + * cumulative duration of time the event loop has been both idle and active as a + * high resolution milliseconds timer. The `utilization` value is the calculated + * Event Loop Utilization (ELU). + * + * If bootstrapping has not yet finished on the main thread the properties have + * the value of `0`. The ELU is immediately available on [Worker threads](https://nodejs.org/docs/latest-v25.x/api/worker_threads.html#worker-threads) since + * bootstrap happens within the event loop. + * + * Both `utilization1` and `utilization2` are optional parameters. + * + * If `utilization1` is passed, then the delta between the current call's `active` + * and `idle` times, as well as the corresponding `utilization` value are + * calculated and returned (similar to `process.hrtime()`). + * + * If `utilization1` and `utilization2` are both passed, then the delta is + * calculated between the two arguments. This is a convenience option because, + * unlike `process.hrtime()`, calculating the ELU is more complex than a + * single subtraction. + * + * ELU is similar to CPU utilization, except that it only measures event loop + * statistics and not CPU usage. It represents the percentage of time the event + * loop has spent outside the event loop's event provider (e.g. `epoll_wait`). + * No other CPU idle time is taken into consideration. The following is an example + * of how a mostly idle process will have a high ELU. + * + * ```js + * import { eventLoopUtilization } from 'node:perf_hooks'; + * import { spawnSync } from 'node:child_process'; + * + * setImmediate(() => { + * const elu = eventLoopUtilization(); + * spawnSync('sleep', ['5']); + * console.log(eventLoopUtilization(elu).utilization); + * }); + * ``` + * + * Although the CPU is mostly idle while running this script, the value of + * `utilization` is `1`. This is because the call to + * `child_process.spawnSync()` blocks the event loop from proceeding. + * + * Passing in a user-defined object instead of the result of a previous call to + * `eventLoopUtilization()` will lead to undefined behavior. The return values + * are not guaranteed to reflect any correct state of the event loop. + * @since v25.2.0 + * @param utilization1 The result of a previous call to + * `eventLoopUtilization()`. + * @param utilization2 The result of a previous call to + * `eventLoopUtilization()` prior to `utilization1`. + */ + function eventLoopUtilization( + utilization1?: EventLoopUtilization, + utilization2?: EventLoopUtilization, + ): EventLoopUtilization; + /** + * _This property is an extension by Node.js. It is not available in Web browsers._ + * + * Creates an `IntervalHistogram` object that samples and reports the event loop + * delay over time. The delays will be reported in nanoseconds. + * + * Using a timer to detect approximate event loop delay works because the + * execution of timers is tied specifically to the lifecycle of the libuv + * event loop. That is, a delay in the loop will cause a delay in the execution + * of the timer, and those delays are specifically what this API is intended to + * detect. + * + * ```js + * import { monitorEventLoopDelay } from 'node:perf_hooks'; + * const h = monitorEventLoopDelay({ resolution: 20 }); + * h.enable(); + * // Do something. + * h.disable(); + * console.log(h.min); + * console.log(h.max); + * console.log(h.mean); + * console.log(h.stddev); + * console.log(h.percentiles); + * console.log(h.percentile(50)); + * console.log(h.percentile(99)); + * ``` + * @since v11.10.0 + */ + function monitorEventLoopDelay(options?: EventLoopMonitorOptions): IntervalHistogram; + interface TimerifyOptions { + /** + * A histogram object created using + * `perf_hooks.createHistogram()` that will record runtime durations in + * nanoseconds. + */ + histogram?: RecordableHistogram | undefined; + } + /** + * _This property is an extension by Node.js. It is not available in Web browsers._ + * + * Wraps a function within a new function that measures the running time of the + * wrapped function. A `PerformanceObserver` must be subscribed to the `'function'` + * event type in order for the timing details to be accessed. + * + * ```js + * import { timerify, performance, PerformanceObserver } from 'node:perf_hooks'; + * + * function someFunction() { + * console.log('hello world'); + * } + * + * const wrapped = timerify(someFunction); + * + * const obs = new PerformanceObserver((list) => { + * console.log(list.getEntries()[0].duration); + * + * performance.clearMarks(); + * performance.clearMeasures(); + * obs.disconnect(); + * }); + * obs.observe({ entryTypes: ['function'] }); + * + * // A performance timeline entry will be created + * wrapped(); + * ``` + * + * If the wrapped function returns a promise, a finally handler will be attached + * to the promise and the duration will be reported once the finally handler is + * invoked. + * @since v25.2.0 + */ + function timerify<T extends (...args: any[]) => any>(fn: T, options?: TimerifyOptions): T; + interface CreateHistogramOptions { + /** + * The minimum recordable value. Must be an integer value greater than 0. + * @default 1 + */ + lowest?: number | bigint | undefined; + /** + * The maximum recordable value. Must be an integer value greater than min. + * @default Number.MAX_SAFE_INTEGER + */ + highest?: number | bigint | undefined; + /** + * The number of accuracy digits. Must be a number between 1 and 5. + * @default 3 + */ + figures?: number | undefined; + } + /** + * Returns a `RecordableHistogram`. + * @since v15.9.0, v14.18.0 + */ + function createHistogram(options?: CreateHistogramOptions): RecordableHistogram; + // TODO: remove these in a future major + /** @deprecated Use the canonical `PerformanceMarkOptions` instead. */ + interface MarkOptions extends PerformanceMarkOptions {} + /** @deprecated Use the canonical `PerformanceMeasureOptions` instead. */ + interface MeasureOptions extends PerformanceMeasureOptions {} +} +declare module "perf_hooks" { + export * from "node:perf_hooks"; +} diff --git a/server/node_modules/@types/node/process.d.ts b/server/node_modules/@types/node/process.d.ts new file mode 100644 index 0000000..6974c48 --- /dev/null +++ b/server/node_modules/@types/node/process.d.ts @@ -0,0 +1,2161 @@ +declare module "node:process" { + import { Control, MessageOptions, SendHandle } from "node:child_process"; + import { PathLike } from "node:fs"; + import * as tty from "node:tty"; + import { Worker } from "node:worker_threads"; + interface BuiltInModule { + "assert": typeof import("assert"); + "node:assert": typeof import("node:assert"); + "assert/strict": typeof import("assert/strict"); + "node:assert/strict": typeof import("node:assert/strict"); + "async_hooks": typeof import("async_hooks"); + "node:async_hooks": typeof import("node:async_hooks"); + "buffer": typeof import("buffer"); + "node:buffer": typeof import("node:buffer"); + "child_process": typeof import("child_process"); + "node:child_process": typeof import("node:child_process"); + "cluster": typeof import("cluster"); + "node:cluster": typeof import("node:cluster"); + "console": typeof import("console"); + "node:console": typeof import("node:console"); + "constants": typeof import("constants"); + "node:constants": typeof import("node:constants"); + "crypto": typeof import("crypto"); + "node:crypto": typeof import("node:crypto"); + "dgram": typeof import("dgram"); + "node:dgram": typeof import("node:dgram"); + "diagnostics_channel": typeof import("diagnostics_channel"); + "node:diagnostics_channel": typeof import("node:diagnostics_channel"); + "dns": typeof import("dns"); + "node:dns": typeof import("node:dns"); + "dns/promises": typeof import("dns/promises"); + "node:dns/promises": typeof import("node:dns/promises"); + "domain": typeof import("domain"); + "node:domain": typeof import("node:domain"); + "events": typeof import("events"); + "node:events": typeof import("node:events"); + "fs": typeof import("fs"); + "node:fs": typeof import("node:fs"); + "fs/promises": typeof import("fs/promises"); + "node:fs/promises": typeof import("node:fs/promises"); + "http": typeof import("http"); + "node:http": typeof import("node:http"); + "http2": typeof import("http2"); + "node:http2": typeof import("node:http2"); + "https": typeof import("https"); + "node:https": typeof import("node:https"); + "inspector": typeof import("inspector"); + "node:inspector": typeof import("node:inspector"); + "inspector/promises": typeof import("inspector/promises"); + "node:inspector/promises": typeof import("node:inspector/promises"); + "module": typeof import("module"); + "node:module": typeof import("node:module"); + "net": typeof import("net"); + "node:net": typeof import("node:net"); + "os": typeof import("os"); + "node:os": typeof import("node:os"); + "path": typeof import("path"); + "node:path": typeof import("node:path"); + "path/posix": typeof import("path/posix"); + "node:path/posix": typeof import("node:path/posix"); + "path/win32": typeof import("path/win32"); + "node:path/win32": typeof import("node:path/win32"); + "perf_hooks": typeof import("perf_hooks"); + "node:perf_hooks": typeof import("node:perf_hooks"); + "process": typeof import("process"); + "node:process": typeof import("node:process"); + "punycode": typeof import("punycode"); + "node:punycode": typeof import("node:punycode"); + "querystring": typeof import("querystring"); + "node:querystring": typeof import("node:querystring"); + "node:quic": typeof import("node:quic"); + "readline": typeof import("readline"); + "node:readline": typeof import("node:readline"); + "readline/promises": typeof import("readline/promises"); + "node:readline/promises": typeof import("node:readline/promises"); + "repl": typeof import("repl"); + "node:repl": typeof import("node:repl"); + "node:sea": typeof import("node:sea"); + "node:sqlite": typeof import("node:sqlite"); + "stream": typeof import("stream"); + "node:stream": typeof import("node:stream"); + "stream/consumers": typeof import("stream/consumers"); + "node:stream/consumers": typeof import("node:stream/consumers"); + "stream/promises": typeof import("stream/promises"); + "node:stream/promises": typeof import("node:stream/promises"); + "stream/web": typeof import("stream/web"); + "node:stream/web": typeof import("node:stream/web"); + "string_decoder": typeof import("string_decoder"); + "node:string_decoder": typeof import("node:string_decoder"); + "node:test": typeof import("node:test"); + "node:test/reporters": typeof import("node:test/reporters"); + "timers": typeof import("timers"); + "node:timers": typeof import("node:timers"); + "timers/promises": typeof import("timers/promises"); + "node:timers/promises": typeof import("node:timers/promises"); + "tls": typeof import("tls"); + "node:tls": typeof import("node:tls"); + "trace_events": typeof import("trace_events"); + "node:trace_events": typeof import("node:trace_events"); + "tty": typeof import("tty"); + "node:tty": typeof import("node:tty"); + "url": typeof import("url"); + "node:url": typeof import("node:url"); + "util": typeof import("util"); + "node:util": typeof import("node:util"); + "util/types": typeof import("util/types"); + "node:util/types": typeof import("node:util/types"); + "v8": typeof import("v8"); + "node:v8": typeof import("node:v8"); + "vm": typeof import("vm"); + "node:vm": typeof import("node:vm"); + "wasi": typeof import("wasi"); + "node:wasi": typeof import("node:wasi"); + "worker_threads": typeof import("worker_threads"); + "node:worker_threads": typeof import("node:worker_threads"); + "zlib": typeof import("zlib"); + "node:zlib": typeof import("node:zlib"); + } + type SignalsEventMap = { [S in NodeJS.Signals]: [signal: S] }; + interface ProcessEventMap extends SignalsEventMap { + "beforeExit": [code: number]; + "disconnect": []; + "exit": [code: number]; + "message": [ + message: object | boolean | number | string | null, + sendHandle: SendHandle | undefined, + ]; + "rejectionHandled": [promise: Promise<unknown>]; + "uncaughtException": [error: Error, origin: NodeJS.UncaughtExceptionOrigin]; + "uncaughtExceptionMonitor": [error: Error, origin: NodeJS.UncaughtExceptionOrigin]; + "unhandledRejection": [reason: unknown, promise: Promise<unknown>]; + "warning": [warning: Error]; + "worker": [worker: Worker]; + "workerMessage": [value: any, source: number]; + } + global { + var process: NodeJS.Process; + namespace process { + export { ProcessEventMap }; + } + namespace NodeJS { + // this namespace merge is here because these are specifically used + // as the type for process.stdin, process.stdout, and process.stderr. + // they can't live in tty.d.ts because we need to disambiguate the imported name. + interface ReadStream extends tty.ReadStream {} + interface WriteStream extends tty.WriteStream {} + interface MemoryUsageFn { + /** + * The `process.memoryUsage()` method iterate over each page to gather informations about memory + * usage which can be slow depending on the program memory allocations. + */ + (): MemoryUsage; + /** + * method returns an integer representing the Resident Set Size (RSS) in bytes. + */ + rss(): number; + } + interface MemoryUsage { + /** + * Resident Set Size, is the amount of space occupied in the main memory device (that is a subset of the total allocated memory) for the + * process, including all C++ and JavaScript objects and code. + */ + rss: number; + /** + * Refers to V8's memory usage. + */ + heapTotal: number; + /** + * Refers to V8's memory usage. + */ + heapUsed: number; + external: number; + /** + * Refers to memory allocated for `ArrayBuffer`s and `SharedArrayBuffer`s, including all Node.js Buffers. This is also included + * in the external value. When Node.js is used as an embedded library, this value may be `0` because allocations for `ArrayBuffer`s + * may not be tracked in that case. + */ + arrayBuffers: number; + } + interface CpuUsage { + user: number; + system: number; + } + interface ProcessRelease { + name: string; + sourceUrl?: string | undefined; + headersUrl?: string | undefined; + libUrl?: string | undefined; + lts?: string | undefined; + } + interface ProcessFeatures { + /** + * A boolean value that is `true` if the current Node.js build is caching builtin modules. + * @since v12.0.0 + */ + readonly cached_builtins: boolean; + /** + * A boolean value that is `true` if the current Node.js build is a debug build. + * @since v0.5.5 + */ + readonly debug: boolean; + /** + * A boolean value that is `true` if the current Node.js build includes the inspector. + * @since v11.10.0 + */ + readonly inspector: boolean; + /** + * A boolean value that is `true` if the current Node.js build includes support for IPv6. + * + * Since all Node.js builds have IPv6 support, this value is always `true`. + * @since v0.5.3 + * @deprecated This property is always true, and any checks based on it are redundant. + */ + readonly ipv6: boolean; + /** + * A boolean value that is `true` if the current Node.js build supports + * [loading ECMAScript modules using `require()`](https://nodejs.org/docs/latest-v25.x/api/modules.md#loading-ecmascript-modules-using-require). + * @since v22.10.0 + */ + readonly require_module: boolean; + /** + * A boolean value that is `true` if the current Node.js build includes support for TLS. + * @since v0.5.3 + */ + readonly tls: boolean; + /** + * A boolean value that is `true` if the current Node.js build includes support for ALPN in TLS. + * + * In Node.js 11.0.0 and later versions, the OpenSSL dependencies feature unconditional ALPN support. + * This value is therefore identical to that of `process.features.tls`. + * @since v4.8.0 + * @deprecated Use `process.features.tls` instead. + */ + readonly tls_alpn: boolean; + /** + * A boolean value that is `true` if the current Node.js build includes support for OCSP in TLS. + * + * In Node.js 11.0.0 and later versions, the OpenSSL dependencies feature unconditional OCSP support. + * This value is therefore identical to that of `process.features.tls`. + * @since v0.11.13 + * @deprecated Use `process.features.tls` instead. + */ + readonly tls_ocsp: boolean; + /** + * A boolean value that is `true` if the current Node.js build includes support for SNI in TLS. + * + * In Node.js 11.0.0 and later versions, the OpenSSL dependencies feature unconditional SNI support. + * This value is therefore identical to that of `process.features.tls`. + * @since v0.5.3 + * @deprecated Use `process.features.tls` instead. + */ + readonly tls_sni: boolean; + /** + * A value that is `"strip"` by default, + * `"transform"` if Node.js is run with `--experimental-transform-types`, and `false` if + * Node.js is run with `--no-strip-types`. + * @since v22.10.0 + */ + readonly typescript: "strip" | "transform" | false; + /** + * A boolean value that is `true` if the current Node.js build includes support for libuv. + * + * Since it's not possible to build Node.js without libuv, this value is always `true`. + * @since v0.5.3 + * @deprecated This property is always true, and any checks based on it are redundant. + */ + readonly uv: boolean; + } + interface ProcessVersions extends Dict<string> { + http_parser: string; + node: string; + v8: string; + ares: string; + uv: string; + zlib: string; + modules: string; + openssl: string; + } + type Platform = + | "aix" + | "android" + | "darwin" + | "freebsd" + | "haiku" + | "linux" + | "openbsd" + | "sunos" + | "win32" + | "cygwin" + | "netbsd"; + type Architecture = + | "arm" + | "arm64" + | "ia32" + | "loong64" + | "mips" + | "mipsel" + | "ppc64" + | "riscv64" + | "s390x" + | "x64"; + type Signals = + | "SIGABRT" + | "SIGALRM" + | "SIGBUS" + | "SIGCHLD" + | "SIGCONT" + | "SIGFPE" + | "SIGHUP" + | "SIGILL" + | "SIGINT" + | "SIGIO" + | "SIGIOT" + | "SIGKILL" + | "SIGPIPE" + | "SIGPOLL" + | "SIGPROF" + | "SIGPWR" + | "SIGQUIT" + | "SIGSEGV" + | "SIGSTKFLT" + | "SIGSTOP" + | "SIGSYS" + | "SIGTERM" + | "SIGTRAP" + | "SIGTSTP" + | "SIGTTIN" + | "SIGTTOU" + | "SIGUNUSED" + | "SIGURG" + | "SIGUSR1" + | "SIGUSR2" + | "SIGVTALRM" + | "SIGWINCH" + | "SIGXCPU" + | "SIGXFSZ" + | "SIGBREAK" + | "SIGLOST" + | "SIGINFO"; + type UncaughtExceptionOrigin = "uncaughtException" | "unhandledRejection"; + /** + * @deprecated Global listener types will be removed in a future version. + * Callbacks passed directly to `process`'s EventEmitter methods + * have their parameter types inferred automatically. + * + * `process` event types are also available via `ProcessEventMap`: + * + * ```ts + * import type { ProcessEventMap } from 'node:process'; + * const listener = (...args: ProcessEventMap['beforeExit']) => { ... }; + * ``` + */ + type BeforeExitListener = (...args: ProcessEventMap["beforeExit"]) => void; + /** + * @deprecated Global listener types will be removed in a future version. + * Callbacks passed directly to `process`'s EventEmitter methods + * have their parameter types inferred automatically. + * + * `process` event types are also available via `ProcessEventMap`: + * + * ```ts + * import type { ProcessEventMap } from 'node:process'; + * const listener = (...args: ProcessEventMap['disconnect']) => { ... }; + * ``` + */ + type DisconnectListener = (...args: ProcessEventMap["disconnect"]) => void; + /** + * @deprecated Global listener types will be removed in a future version. + * Callbacks passed directly to `process`'s EventEmitter methods + * have their parameter types inferred automatically. + * + * `process` event types are also available via `ProcessEventMap`: + * + * ```ts + * import type { ProcessEventMap } from 'node:process'; + * const listener = (...args: ProcessEventMap['exit']) => { ... }; + * ``` + */ + type ExitListener = (...args: ProcessEventMap["exit"]) => void; + /** + * @deprecated Global listener types will be removed in a future version. + * Callbacks passed directly to `process`'s EventEmitter methods + * have their parameter types inferred automatically. + * + * `process` event types are also available via `ProcessEventMap`: + * + * ```ts + * import type { ProcessEventMap } from 'node:process'; + * const listener = (...args: ProcessEventMap['message']) => { ... }; + * ``` + */ + type MessageListener = (...args: ProcessEventMap["message"]) => void; + /** + * @deprecated Global listener types will be removed in a future version. + * Callbacks passed directly to `process`'s EventEmitter methods + * have their parameter types inferred automatically. + * + * `process` event types are also available via `ProcessEventMap`: + * + * ```ts + * import type { ProcessEventMap } from 'node:process'; + * const listener = (...args: ProcessEventMap['rejectionHandled']) => { ... }; + * ``` + */ + type RejectionHandledListener = (...args: ProcessEventMap["rejectionHandled"]) => void; + /** + * @deprecated Global listener types will be removed in a future version. + * Callbacks passed directly to `process`'s EventEmitter methods + * have their parameter types inferred automatically. + */ + type SignalsListener = (signal: Signals) => void; + /** + * @deprecated Global listener types will be removed in a future version. + * Callbacks passed directly to `process`'s EventEmitter methods + * have their parameter types inferred automatically. + * + * `process` event types are also available via `ProcessEventMap`: + * + * ```ts + * import type { ProcessEventMap } from 'node:process'; + * const listener = (...args: ProcessEventMap['uncaughtException']) => { ... }; + * ``` + */ + type UncaughtExceptionListener = (...args: ProcessEventMap["uncaughtException"]) => void; + /** + * @deprecated Global listener types will be removed in a future version. + * Callbacks passed directly to `process`'s EventEmitter methods + * have their parameter types inferred automatically. + * + * `process` event types are also available via `ProcessEventMap`: + * + * ```ts + * import type { ProcessEventMap } from 'node:process'; + * const listener = (...args: ProcessEventMap['unhandledRejection']) => { ... }; + * ``` + */ + type UnhandledRejectionListener = (...args: ProcessEventMap["unhandledRejection"]) => void; + /** + * @deprecated Global listener types will be removed in a future version. + * Callbacks passed directly to `process`'s EventEmitter methods + * have their parameter types inferred automatically. + * + * `process` event types are also available via `ProcessEventMap`: + * + * ```ts + * import type { ProcessEventMap } from 'node:process'; + * const listener = (...args: ProcessEventMap['warning']) => { ... }; + * ``` + */ + type WarningListener = (...args: ProcessEventMap["warning"]) => void; + /** + * @deprecated Global listener types will be removed in a future version. + * Callbacks passed directly to `process`'s EventEmitter methods + * have their parameter types inferred automatically. + * + * `process` event types are also available via `ProcessEventMap`: + * + * ```ts + * import type { ProcessEventMap } from 'node:process'; + * const listener = (...args: ProcessEventMap['worker']) => { ... }; + * ``` + */ + type WorkerListener = (...args: ProcessEventMap["worker"]) => void; + interface Socket extends ReadWriteStream { + isTTY?: true | undefined; + } + // Alias for compatibility + interface ProcessEnv extends Dict<string> { + /** + * Can be used to change the default timezone at runtime + */ + TZ?: string | undefined; + } + interface HRTime { + /** + * This is the legacy version of {@link process.hrtime.bigint()} + * before bigint was introduced in JavaScript. + * + * The `process.hrtime()` method returns the current high-resolution real time in a `[seconds, nanoseconds]` tuple `Array`, + * where `nanoseconds` is the remaining part of the real time that can't be represented in second precision. + * + * `time` is an optional parameter that must be the result of a previous `process.hrtime()` call to diff with the current time. + * If the parameter passed in is not a tuple `Array`, a TypeError will be thrown. + * Passing in a user-defined array instead of the result of a previous call to `process.hrtime()` will lead to undefined behavior. + * + * These times are relative to an arbitrary time in the past, + * and not related to the time of day and therefore not subject to clock drift. + * The primary use is for measuring performance between intervals: + * ```js + * const { hrtime } = require('node:process'); + * const NS_PER_SEC = 1e9; + * const time = hrtime(); + * // [ 1800216, 25 ] + * + * setTimeout(() => { + * const diff = hrtime(time); + * // [ 1, 552 ] + * + * console.log(`Benchmark took ${diff[0] * NS_PER_SEC + diff[1]} nanoseconds`); + * // Benchmark took 1000000552 nanoseconds + * }, 1000); + * ``` + * @since 0.7.6 + * @legacy Use {@link process.hrtime.bigint()} instead. + * @param time The result of a previous call to `process.hrtime()` + */ + (time?: [number, number]): [number, number]; + /** + * The `bigint` version of the {@link process.hrtime()} method returning the current high-resolution real time in nanoseconds as a `bigint`. + * + * Unlike {@link process.hrtime()}, it does not support an additional time argument since the difference can just be computed directly by subtraction of the two `bigint`s. + * ```js + * import { hrtime } from 'node:process'; + * + * const start = hrtime.bigint(); + * // 191051479007711n + * + * setTimeout(() => { + * const end = hrtime.bigint(); + * // 191052633396993n + * + * console.log(`Benchmark took ${end - start} nanoseconds`); + * // Benchmark took 1154389282 nanoseconds + * }, 1000); + * ``` + * @since v10.7.0 + */ + bigint(): bigint; + } + interface ProcessPermission { + /** + * Verifies that the process is able to access the given scope and reference. + * If no reference is provided, a global scope is assumed, for instance, `process.permission.has('fs.read')` + * will check if the process has ALL file system read permissions. + * + * The reference has a meaning based on the provided scope. For example, the reference when the scope is File System means files and folders. + * + * The available scopes are: + * + * * `fs` - All File System + * * `fs.read` - File System read operations + * * `fs.write` - File System write operations + * * `child` - Child process spawning operations + * * `worker` - Worker thread spawning operation + * + * ```js + * // Check if the process has permission to read the README file + * process.permission.has('fs.read', './README.md'); + * // Check if the process has read permission operations + * process.permission.has('fs.read'); + * ``` + * @since v20.0.0 + */ + has(scope: string, reference?: string): boolean; + } + interface ProcessReport { + /** + * Write reports in a compact format, single-line JSON, more easily consumable by log processing systems + * than the default multi-line format designed for human consumption. + * @since v13.12.0, v12.17.0 + */ + compact: boolean; + /** + * Directory where the report is written. + * The default value is the empty string, indicating that reports are written to the current + * working directory of the Node.js process. + */ + directory: string; + /** + * Filename where the report is written. If set to the empty string, the output filename will be comprised + * of a timestamp, PID, and sequence number. The default value is the empty string. + */ + filename: string; + /** + * Returns a JavaScript Object representation of a diagnostic report for the running process. + * The report's JavaScript stack trace is taken from `err`, if present. + */ + getReport(err?: Error): object; + /** + * If true, a diagnostic report is generated on fatal errors, + * such as out of memory errors or failed C++ assertions. + * @default false + */ + reportOnFatalError: boolean; + /** + * If true, a diagnostic report is generated when the process + * receives the signal specified by process.report.signal. + * @default false + */ + reportOnSignal: boolean; + /** + * If true, a diagnostic report is generated on uncaught exception. + * @default false + */ + reportOnUncaughtException: boolean; + /** + * If true, a diagnostic report is generated without the environment variables. + * @default false + */ + excludeEnv: boolean; + /** + * The signal used to trigger the creation of a diagnostic report. + * @default 'SIGUSR2' + */ + signal: Signals; + /** + * Writes a diagnostic report to a file. If filename is not provided, the default filename + * includes the date, time, PID, and a sequence number. + * The report's JavaScript stack trace is taken from `err`, if present. + * + * If the value of filename is set to `'stdout'` or `'stderr'`, the report is written + * to the stdout or stderr of the process respectively. + * @param fileName Name of the file where the report is written. + * This should be a relative path, that will be appended to the directory specified in + * `process.report.directory`, or the current working directory of the Node.js process, + * if unspecified. + * @param err A custom error used for reporting the JavaScript stack. + * @return Filename of the generated report. + */ + writeReport(fileName?: string, err?: Error): string; + writeReport(err?: Error): string; + } + interface ResourceUsage { + fsRead: number; + fsWrite: number; + involuntaryContextSwitches: number; + ipcReceived: number; + ipcSent: number; + majorPageFault: number; + maxRSS: number; + minorPageFault: number; + sharedMemorySize: number; + signalsCount: number; + swappedOut: number; + systemCPUTime: number; + unsharedDataSize: number; + unsharedStackSize: number; + userCPUTime: number; + voluntaryContextSwitches: number; + } + interface EmitWarningOptions { + /** + * When `warning` is a `string`, `type` is the name to use for the _type_ of warning being emitted. + * + * @default 'Warning' + */ + type?: string | undefined; + /** + * A unique identifier for the warning instance being emitted. + */ + code?: string | undefined; + /** + * When `warning` is a `string`, `ctor` is an optional function used to limit the generated stack trace. + * + * @default process.emitWarning + */ + ctor?: Function | undefined; + /** + * Additional text to include with the error. + */ + detail?: string | undefined; + } + interface ProcessConfig { + readonly target_defaults: { + readonly cflags: any[]; + readonly default_configuration: string; + readonly defines: string[]; + readonly include_dirs: string[]; + readonly libraries: string[]; + }; + readonly variables: { + readonly clang: number; + readonly host_arch: string; + readonly node_install_npm: boolean; + readonly node_install_waf: boolean; + readonly node_prefix: string; + readonly node_shared_openssl: boolean; + readonly node_shared_v8: boolean; + readonly node_shared_zlib: boolean; + readonly node_use_dtrace: boolean; + readonly node_use_etw: boolean; + readonly node_use_openssl: boolean; + readonly target_arch: string; + readonly v8_no_strict_aliasing: number; + readonly v8_use_snapshot: boolean; + readonly visibility: string; + }; + } + interface Process extends EventEmitter { + /** + * The `process.stdout` property returns a stream connected to`stdout` (fd `1`). It is a `net.Socket` (which is a `Duplex` stream) unless fd `1` refers to a file, in which case it is + * a `Writable` stream. + * + * For example, to copy `process.stdin` to `process.stdout`: + * + * ```js + * import { stdin, stdout } from 'node:process'; + * + * stdin.pipe(stdout); + * ``` + * + * `process.stdout` differs from other Node.js streams in important ways. See `note on process I/O` for more information. + */ + stdout: WriteStream & { + fd: 1; + }; + /** + * The `process.stderr` property returns a stream connected to`stderr` (fd `2`). It is a `net.Socket` (which is a `Duplex` stream) unless fd `2` refers to a file, in which case it is + * a `Writable` stream. + * + * `process.stderr` differs from other Node.js streams in important ways. See `note on process I/O` for more information. + */ + stderr: WriteStream & { + fd: 2; + }; + /** + * The `process.stdin` property returns a stream connected to`stdin` (fd `0`). It is a `net.Socket` (which is a `Duplex` stream) unless fd `0` refers to a file, in which case it is + * a `Readable` stream. + * + * For details of how to read from `stdin` see `readable.read()`. + * + * As a `Duplex` stream, `process.stdin` can also be used in "old" mode that + * is compatible with scripts written for Node.js prior to v0.10\. + * For more information see `Stream compatibility`. + * + * In "old" streams mode the `stdin` stream is paused by default, so one + * must call `process.stdin.resume()` to read from it. Note also that calling `process.stdin.resume()` itself would switch stream to "old" mode. + */ + stdin: ReadStream & { + fd: 0; + }; + /** + * The `process.argv` property returns an array containing the command-line + * arguments passed when the Node.js process was launched. The first element will + * be {@link execPath}. See `process.argv0` if access to the original value + * of `argv[0]` is needed. The second element will be the path to the JavaScript + * file being executed. The remaining elements will be any additional command-line + * arguments. + * + * For example, assuming the following script for `process-args.js`: + * + * ```js + * import { argv } from 'node:process'; + * + * // print process.argv + * argv.forEach((val, index) => { + * console.log(`${index}: ${val}`); + * }); + * ``` + * + * Launching the Node.js process as: + * + * ```bash + * node process-args.js one two=three four + * ``` + * + * Would generate the output: + * + * ```text + * 0: /usr/local/bin/node + * 1: /Users/mjr/work/node/process-args.js + * 2: one + * 3: two=three + * 4: four + * ``` + * @since v0.1.27 + */ + argv: string[]; + /** + * The `process.argv0` property stores a read-only copy of the original value of`argv[0]` passed when Node.js starts. + * + * ```console + * $ bash -c 'exec -a customArgv0 ./node' + * > process.argv[0] + * '/Volumes/code/external/node/out/Release/node' + * > process.argv0 + * 'customArgv0' + * ``` + * @since v6.4.0 + */ + argv0: string; + /** + * The `process.execArgv` property returns the set of Node.js-specific command-line + * options passed when the Node.js process was launched. These options do not + * appear in the array returned by the {@link argv} property, and do not + * include the Node.js executable, the name of the script, or any options following + * the script name. These options are useful in order to spawn child processes with + * the same execution environment as the parent. + * + * ```bash + * node --icu-data-dir=./foo --require ./bar.js script.js --version + * ``` + * + * Results in `process.execArgv`: + * + * ```js + * ["--icu-data-dir=./foo", "--require", "./bar.js"] + * ``` + * + * And `process.argv`: + * + * ```js + * ['/usr/local/bin/node', 'script.js', '--version'] + * ``` + * + * Refer to `Worker constructor` for the detailed behavior of worker + * threads with this property. + * @since v0.7.7 + */ + execArgv: string[]; + /** + * The `process.execPath` property returns the absolute pathname of the executable + * that started the Node.js process. Symbolic links, if any, are resolved. + * + * ```js + * '/usr/local/bin/node' + * ``` + * @since v0.1.100 + */ + execPath: string; + /** + * The `process.abort()` method causes the Node.js process to exit immediately and + * generate a core file. + * + * This feature is not available in `Worker` threads. + * @since v0.7.0 + */ + abort(): never; + /** + * The `process.chdir()` method changes the current working directory of the + * Node.js process or throws an exception if doing so fails (for instance, if + * the specified `directory` does not exist). + * + * ```js + * import { chdir, cwd } from 'node:process'; + * + * console.log(`Starting directory: ${cwd()}`); + * try { + * chdir('/tmp'); + * console.log(`New directory: ${cwd()}`); + * } catch (err) { + * console.error(`chdir: ${err}`); + * } + * ``` + * + * This feature is not available in `Worker` threads. + * @since v0.1.17 + */ + chdir(directory: string): void; + /** + * The `process.cwd()` method returns the current working directory of the Node.js + * process. + * + * ```js + * import { cwd } from 'node:process'; + * + * console.log(`Current directory: ${cwd()}`); + * ``` + * @since v0.1.8 + */ + cwd(): string; + /** + * The port used by the Node.js debugger when enabled. + * + * ```js + * import process from 'node:process'; + * + * process.debugPort = 5858; + * ``` + * @since v0.7.2 + */ + debugPort: number; + /** + * The `process.dlopen()` method allows dynamically loading shared objects. It is primarily used by `require()` to load C++ Addons, and + * should not be used directly, except in special cases. In other words, `require()` should be preferred over `process.dlopen()` + * unless there are specific reasons such as custom dlopen flags or loading from ES modules. + * + * The `flags` argument is an integer that allows to specify dlopen behavior. See the `[os.constants.dlopen](https://nodejs.org/docs/latest-v25.x/api/os.html#dlopen-constants)` + * documentation for details. + * + * An important requirement when calling `process.dlopen()` is that the `module` instance must be passed. Functions exported by the C++ Addon + * are then accessible via `module.exports`. + * + * The example below shows how to load a C++ Addon, named `local.node`, that exports a `foo` function. All the symbols are loaded before the call returns, by passing the `RTLD_NOW` constant. + * In this example the constant is assumed to be available. + * + * ```js + * import { dlopen } from 'node:process'; + * import { constants } from 'node:os'; + * import { fileURLToPath } from 'node:url'; + * + * const module = { exports: {} }; + * dlopen(module, fileURLToPath(new URL('local.node', import.meta.url)), + * constants.dlopen.RTLD_NOW); + * module.exports.foo(); + * ``` + */ + dlopen(module: object, filename: string, flags?: number): void; + /** + * The `process.emitWarning()` method can be used to emit custom or application + * specific process warnings. These can be listened for by adding a handler to the `'warning'` event. + * + * ```js + * import { emitWarning } from 'node:process'; + * + * // Emit a warning using a string. + * emitWarning('Something happened!'); + * // Emits: (node: 56338) Warning: Something happened! + * ``` + * + * ```js + * import { emitWarning } from 'node:process'; + * + * // Emit a warning using a string and a type. + * emitWarning('Something Happened!', 'CustomWarning'); + * // Emits: (node:56338) CustomWarning: Something Happened! + * ``` + * + * ```js + * import { emitWarning } from 'node:process'; + * + * emitWarning('Something happened!', 'CustomWarning', 'WARN001'); + * // Emits: (node:56338) [WARN001] CustomWarning: Something happened! + * ```js + * + * In each of the previous examples, an `Error` object is generated internally by `process.emitWarning()` and passed through to the `'warning'` handler. + * + * ```js + * import process from 'node:process'; + * + * process.on('warning', (warning) => { + * console.warn(warning.name); // 'Warning' + * console.warn(warning.message); // 'Something happened!' + * console.warn(warning.code); // 'MY_WARNING' + * console.warn(warning.stack); // Stack trace + * console.warn(warning.detail); // 'This is some additional information' + * }); + * ``` + * + * If `warning` is passed as an `Error` object, it will be passed through to the `'warning'` event handler + * unmodified (and the optional `type`, `code` and `ctor` arguments will be ignored): + * + * ```js + * import { emitWarning } from 'node:process'; + * + * // Emit a warning using an Error object. + * const myWarning = new Error('Something happened!'); + * // Use the Error name property to specify the type name + * myWarning.name = 'CustomWarning'; + * myWarning.code = 'WARN001'; + * + * emitWarning(myWarning); + * // Emits: (node:56338) [WARN001] CustomWarning: Something happened! + * ``` + * + * A `TypeError` is thrown if `warning` is anything other than a string or `Error` object. + * + * While process warnings use `Error` objects, the process warning mechanism is not a replacement for normal error handling mechanisms. + * + * The following additional handling is implemented if the warning `type` is `'DeprecationWarning'`: + * * If the `--throw-deprecation` command-line flag is used, the deprecation warning is thrown as an exception rather than being emitted as an event. + * * If the `--no-deprecation` command-line flag is used, the deprecation warning is suppressed. + * * If the `--trace-deprecation` command-line flag is used, the deprecation warning is printed to `stderr` along with the full stack trace. + * @since v8.0.0 + * @param warning The warning to emit. + */ + emitWarning(warning: string | Error, ctor?: Function): void; + emitWarning(warning: string | Error, type?: string, ctor?: Function): void; + emitWarning(warning: string | Error, type?: string, code?: string, ctor?: Function): void; + emitWarning(warning: string | Error, options?: EmitWarningOptions): void; + /** + * The `process.env` property returns an object containing the user environment. + * See [`environ(7)`](http://man7.org/linux/man-pages/man7/environ.7.html). + * + * An example of this object looks like: + * + * ```js + * { + * TERM: 'xterm-256color', + * SHELL: '/usr/local/bin/bash', + * USER: 'maciej', + * PATH: '~/.bin/:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin', + * PWD: '/Users/maciej', + * EDITOR: 'vim', + * SHLVL: '1', + * HOME: '/Users/maciej', + * LOGNAME: 'maciej', + * _: '/usr/local/bin/node' + * } + * ``` + * + * It is possible to modify this object, but such modifications will not be + * reflected outside the Node.js process, or (unless explicitly requested) + * to other `Worker` threads. + * In other words, the following example would not work: + * + * ```bash + * node -e 'process.env.foo = "bar"' && echo $foo + * ``` + * + * While the following will: + * + * ```js + * import { env } from 'node:process'; + * + * env.foo = 'bar'; + * console.log(env.foo); + * ``` + * + * Assigning a property on `process.env` will implicitly convert the value + * to a string. **This behavior is deprecated.** Future versions of Node.js may + * throw an error when the value is not a string, number, or boolean. + * + * ```js + * import { env } from 'node:process'; + * + * env.test = null; + * console.log(env.test); + * // => 'null' + * env.test = undefined; + * console.log(env.test); + * // => 'undefined' + * ``` + * + * Use `delete` to delete a property from `process.env`. + * + * ```js + * import { env } from 'node:process'; + * + * env.TEST = 1; + * delete env.TEST; + * console.log(env.TEST); + * // => undefined + * ``` + * + * On Windows operating systems, environment variables are case-insensitive. + * + * ```js + * import { env } from 'node:process'; + * + * env.TEST = 1; + * console.log(env.test); + * // => 1 + * ``` + * + * Unless explicitly specified when creating a `Worker` instance, + * each `Worker` thread has its own copy of `process.env`, based on its + * parent thread's `process.env`, or whatever was specified as the `env` option + * to the `Worker` constructor. Changes to `process.env` will not be visible + * across `Worker` threads, and only the main thread can make changes that + * are visible to the operating system or to native add-ons. On Windows, a copy of `process.env` on a `Worker` instance operates in a case-sensitive manner + * unlike the main thread. + * @since v0.1.27 + */ + env: ProcessEnv; + /** + * The `process.exit()` method instructs Node.js to terminate the process + * synchronously with an exit status of `code`. If `code` is omitted, exit uses + * either the 'success' code `0` or the value of `process.exitCode` if it has been + * set. Node.js will not terminate until all the `'exit'` event listeners are + * called. + * + * To exit with a 'failure' code: + * + * ```js + * import { exit } from 'node:process'; + * + * exit(1); + * ``` + * + * The shell that executed Node.js should see the exit code as `1`. + * + * Calling `process.exit()` will force the process to exit as quickly as possible + * even if there are still asynchronous operations pending that have not yet + * completed fully, including I/O operations to `process.stdout` and `process.stderr`. + * + * In most situations, it is not actually necessary to call `process.exit()` explicitly. The Node.js process will exit on its own _if there is no additional_ + * _work pending_ in the event loop. The `process.exitCode` property can be set to + * tell the process which exit code to use when the process exits gracefully. + * + * For instance, the following example illustrates a _misuse_ of the `process.exit()` method that could lead to data printed to stdout being + * truncated and lost: + * + * ```js + * import { exit } from 'node:process'; + * + * // This is an example of what *not* to do: + * if (someConditionNotMet()) { + * printUsageToStdout(); + * exit(1); + * } + * ``` + * + * The reason this is problematic is because writes to `process.stdout` in Node.js + * are sometimes _asynchronous_ and may occur over multiple ticks of the Node.js + * event loop. Calling `process.exit()`, however, forces the process to exit _before_ those additional writes to `stdout` can be performed. + * + * Rather than calling `process.exit()` directly, the code _should_ set the `process.exitCode` and allow the process to exit naturally by avoiding + * scheduling any additional work for the event loop: + * + * ```js + * import process from 'node:process'; + * + * // How to properly set the exit code while letting + * // the process exit gracefully. + * if (someConditionNotMet()) { + * printUsageToStdout(); + * process.exitCode = 1; + * } + * ``` + * + * If it is necessary to terminate the Node.js process due to an error condition, + * throwing an _uncaught_ error and allowing the process to terminate accordingly + * is safer than calling `process.exit()`. + * + * In `Worker` threads, this function stops the current thread rather + * than the current process. + * @since v0.1.13 + * @param [code=0] The exit code. For string type, only integer strings (e.g.,'1') are allowed. + */ + exit(code?: number | string | null): never; + /** + * A number which will be the process exit code, when the process either + * exits gracefully, or is exited via {@link exit} without specifying + * a code. + * + * Specifying a code to {@link exit} will override any + * previous setting of `process.exitCode`. + * @default undefined + * @since v0.11.8 + */ + exitCode: number | string | null | undefined; + finalization: { + /** + * This function registers a callback to be called when the process emits the `exit` event if the `ref` object was not garbage collected. + * If the object `ref` was garbage collected before the `exit` event is emitted, the callback will be removed from the finalization registry, and it will not be called on process exit. + * + * Inside the callback you can release the resources allocated by the `ref` object. + * Be aware that all limitations applied to the `beforeExit` event are also applied to the callback function, + * this means that there is a possibility that the callback will not be called under special circumstances. + * + * The idea of ​​this function is to help you free up resources when the starts process exiting, but also let the object be garbage collected if it is no longer being used. + * @param ref The reference to the resource that is being tracked. + * @param callback The callback function to be called when the resource is finalized. + * @since v22.5.0 + * @experimental + */ + register<T extends object>(ref: T, callback: (ref: T, event: "exit") => void): void; + /** + * This function behaves exactly like the `register`, except that the callback will be called when the process emits the `beforeExit` event if `ref` object was not garbage collected. + * + * Be aware that all limitations applied to the `beforeExit` event are also applied to the callback function, this means that there is a possibility that the callback will not be called under special circumstances. + * @param ref The reference to the resource that is being tracked. + * @param callback The callback function to be called when the resource is finalized. + * @since v22.5.0 + * @experimental + */ + registerBeforeExit<T extends object>(ref: T, callback: (ref: T, event: "beforeExit") => void): void; + /** + * This function remove the register of the object from the finalization registry, so the callback will not be called anymore. + * @param ref The reference to the resource that was registered previously. + * @since v22.5.0 + * @experimental + */ + unregister(ref: object): void; + }; + /** + * The `process.getActiveResourcesInfo()` method returns an array of strings containing + * the types of the active resources that are currently keeping the event loop alive. + * + * ```js + * import { getActiveResourcesInfo } from 'node:process'; + * import { setTimeout } from 'node:timers'; + + * console.log('Before:', getActiveResourcesInfo()); + * setTimeout(() => {}, 1000); + * console.log('After:', getActiveResourcesInfo()); + * // Prints: + * // Before: [ 'TTYWrap', 'TTYWrap', 'TTYWrap' ] + * // After: [ 'TTYWrap', 'TTYWrap', 'TTYWrap', 'Timeout' ] + * ``` + * @since v17.3.0, v16.14.0 + */ + getActiveResourcesInfo(): string[]; + /** + * Provides a way to load built-in modules in a globally available function. + * @param id ID of the built-in module being requested. + */ + getBuiltinModule<ID extends keyof BuiltInModule>(id: ID): BuiltInModule[ID]; + getBuiltinModule(id: string): object | undefined; + /** + * The `process.getgid()` method returns the numerical group identity of the + * process. (See [`getgid(2)`](http://man7.org/linux/man-pages/man2/getgid.2.html).) + * + * ```js + * import process from 'node:process'; + * + * if (process.getgid) { + * console.log(`Current gid: ${process.getgid()}`); + * } + * ``` + * + * This function is only available on POSIX platforms (i.e. not Windows or + * Android). + * @since v0.1.31 + */ + getgid?: () => number; + /** + * The `process.setgid()` method sets the group identity of the process. (See [`setgid(2)`](http://man7.org/linux/man-pages/man2/setgid.2.html).) The `id` can be passed as either a + * numeric ID or a group name + * string. If a group name is specified, this method blocks while resolving the + * associated numeric ID. + * + * ```js + * import process from 'node:process'; + * + * if (process.getgid && process.setgid) { + * console.log(`Current gid: ${process.getgid()}`); + * try { + * process.setgid(501); + * console.log(`New gid: ${process.getgid()}`); + * } catch (err) { + * console.log(`Failed to set gid: ${err}`); + * } + * } + * ``` + * + * This function is only available on POSIX platforms (i.e. not Windows or + * Android). + * This feature is not available in `Worker` threads. + * @since v0.1.31 + * @param id The group name or ID + */ + setgid?: (id: number | string) => void; + /** + * The `process.getuid()` method returns the numeric user identity of the process. + * (See [`getuid(2)`](http://man7.org/linux/man-pages/man2/getuid.2.html).) + * + * ```js + * import process from 'node:process'; + * + * if (process.getuid) { + * console.log(`Current uid: ${process.getuid()}`); + * } + * ``` + * + * This function is only available on POSIX platforms (i.e. not Windows or + * Android). + * @since v0.1.28 + */ + getuid?: () => number; + /** + * The `process.setuid(id)` method sets the user identity of the process. (See [`setuid(2)`](http://man7.org/linux/man-pages/man2/setuid.2.html).) The `id` can be passed as either a + * numeric ID or a username string. + * If a username is specified, the method blocks while resolving the associated + * numeric ID. + * + * ```js + * import process from 'node:process'; + * + * if (process.getuid && process.setuid) { + * console.log(`Current uid: ${process.getuid()}`); + * try { + * process.setuid(501); + * console.log(`New uid: ${process.getuid()}`); + * } catch (err) { + * console.log(`Failed to set uid: ${err}`); + * } + * } + * ``` + * + * This function is only available on POSIX platforms (i.e. not Windows or + * Android). + * This feature is not available in `Worker` threads. + * @since v0.1.28 + */ + setuid?: (id: number | string) => void; + /** + * The `process.geteuid()` method returns the numerical effective user identity of + * the process. (See [`geteuid(2)`](http://man7.org/linux/man-pages/man2/geteuid.2.html).) + * + * ```js + * import process from 'node:process'; + * + * if (process.geteuid) { + * console.log(`Current uid: ${process.geteuid()}`); + * } + * ``` + * + * This function is only available on POSIX platforms (i.e. not Windows or + * Android). + * @since v2.0.0 + */ + geteuid?: () => number; + /** + * The `process.seteuid()` method sets the effective user identity of the process. + * (See [`seteuid(2)`](http://man7.org/linux/man-pages/man2/seteuid.2.html).) The `id` can be passed as either a numeric ID or a username + * string. If a username is specified, the method blocks while resolving the + * associated numeric ID. + * + * ```js + * import process from 'node:process'; + * + * if (process.geteuid && process.seteuid) { + * console.log(`Current uid: ${process.geteuid()}`); + * try { + * process.seteuid(501); + * console.log(`New uid: ${process.geteuid()}`); + * } catch (err) { + * console.log(`Failed to set uid: ${err}`); + * } + * } + * ``` + * + * This function is only available on POSIX platforms (i.e. not Windows or + * Android). + * This feature is not available in `Worker` threads. + * @since v2.0.0 + * @param id A user name or ID + */ + seteuid?: (id: number | string) => void; + /** + * The `process.getegid()` method returns the numerical effective group identity + * of the Node.js process. (See [`getegid(2)`](http://man7.org/linux/man-pages/man2/getegid.2.html).) + * + * ```js + * import process from 'node:process'; + * + * if (process.getegid) { + * console.log(`Current gid: ${process.getegid()}`); + * } + * ``` + * + * This function is only available on POSIX platforms (i.e. not Windows or + * Android). + * @since v2.0.0 + */ + getegid?: () => number; + /** + * The `process.setegid()` method sets the effective group identity of the process. + * (See [`setegid(2)`](http://man7.org/linux/man-pages/man2/setegid.2.html).) The `id` can be passed as either a numeric ID or a group + * name string. If a group name is specified, this method blocks while resolving + * the associated a numeric ID. + * + * ```js + * import process from 'node:process'; + * + * if (process.getegid && process.setegid) { + * console.log(`Current gid: ${process.getegid()}`); + * try { + * process.setegid(501); + * console.log(`New gid: ${process.getegid()}`); + * } catch (err) { + * console.log(`Failed to set gid: ${err}`); + * } + * } + * ``` + * + * This function is only available on POSIX platforms (i.e. not Windows or + * Android). + * This feature is not available in `Worker` threads. + * @since v2.0.0 + * @param id A group name or ID + */ + setegid?: (id: number | string) => void; + /** + * The `process.getgroups()` method returns an array with the supplementary group + * IDs. POSIX leaves it unspecified if the effective group ID is included but + * Node.js ensures it always is. + * + * ```js + * import process from 'node:process'; + * + * if (process.getgroups) { + * console.log(process.getgroups()); // [ 16, 21, 297 ] + * } + * ``` + * + * This function is only available on POSIX platforms (i.e. not Windows or + * Android). + * @since v0.9.4 + */ + getgroups?: () => number[]; + /** + * The `process.setgroups()` method sets the supplementary group IDs for the + * Node.js process. This is a privileged operation that requires the Node.js + * process to have `root` or the `CAP_SETGID` capability. + * + * The `groups` array can contain numeric group IDs, group names, or both. + * + * ```js + * import process from 'node:process'; + * + * if (process.getgroups && process.setgroups) { + * try { + * process.setgroups([501]); + * console.log(process.getgroups()); // new groups + * } catch (err) { + * console.log(`Failed to set groups: ${err}`); + * } + * } + * ``` + * + * This function is only available on POSIX platforms (i.e. not Windows or + * Android). + * This feature is not available in `Worker` threads. + * @since v0.9.4 + */ + setgroups?: (groups: ReadonlyArray<string | number>) => void; + /** + * The `process.setUncaughtExceptionCaptureCallback()` function sets a function + * that will be invoked when an uncaught exception occurs, which will receive the + * exception value itself as its first argument. + * + * If such a function is set, the `'uncaughtException'` event will + * not be emitted. If `--abort-on-uncaught-exception` was passed from the + * command line or set through `v8.setFlagsFromString()`, the process will + * not abort. Actions configured to take place on exceptions such as report + * generations will be affected too + * + * To unset the capture function, `process.setUncaughtExceptionCaptureCallback(null)` may be used. Calling this + * method with a non-`null` argument while another capture function is set will + * throw an error. + * + * Using this function is mutually exclusive with using the deprecated `domain` built-in module. + * @since v9.3.0 + */ + setUncaughtExceptionCaptureCallback(cb: ((err: Error) => void) | null): void; + /** + * Indicates whether a callback has been set using {@link setUncaughtExceptionCaptureCallback}. + * @since v9.3.0 + */ + hasUncaughtExceptionCaptureCallback(): boolean; + /** + * The `process.sourceMapsEnabled` property returns whether the [Source Map v3](https://sourcemaps.info/spec.html) support for stack traces is enabled. + * @since v20.7.0 + * @experimental + */ + readonly sourceMapsEnabled: boolean; + /** + * This function enables or disables the [Source Map v3](https://sourcemaps.info/spec.html) support for + * stack traces. + * + * It provides same features as launching Node.js process with commandline options `--enable-source-maps`. + * + * Only source maps in JavaScript files that are loaded after source maps has been + * enabled will be parsed and loaded. + * @since v16.6.0, v14.18.0 + * @experimental + */ + setSourceMapsEnabled(value: boolean): void; + /** + * The `process.version` property contains the Node.js version string. + * + * ```js + * import { version } from 'node:process'; + * + * console.log(`Version: ${version}`); + * // Version: v14.8.0 + * ``` + * + * To get the version string without the prepended _v_, use`process.versions.node`. + * @since v0.1.3 + */ + readonly version: string; + /** + * The `process.versions` property returns an object listing the version strings of + * Node.js and its dependencies. `process.versions.modules` indicates the current + * ABI version, which is increased whenever a C++ API changes. Node.js will refuse + * to load modules that were compiled against a different module ABI version. + * + * ```js + * import { versions } from 'node:process'; + * + * console.log(versions); + * ``` + * + * Will generate an object similar to: + * + * ```console + * { node: '20.2.0', + * acorn: '8.8.2', + * ada: '2.4.0', + * ares: '1.19.0', + * base64: '0.5.0', + * brotli: '1.0.9', + * cjs_module_lexer: '1.2.2', + * cldr: '43.0', + * icu: '73.1', + * llhttp: '8.1.0', + * modules: '115', + * napi: '8', + * nghttp2: '1.52.0', + * nghttp3: '0.7.0', + * ngtcp2: '0.8.1', + * openssl: '3.0.8+quic', + * simdutf: '3.2.9', + * tz: '2023c', + * undici: '5.22.0', + * unicode: '15.0', + * uv: '1.44.2', + * uvwasi: '0.0.16', + * v8: '11.3.244.8-node.9', + * zlib: '1.2.13' } + * ``` + * @since v0.2.0 + */ + readonly versions: ProcessVersions; + /** + * The `process.config` property returns a frozen `Object` containing the + * JavaScript representation of the configure options used to compile the current + * Node.js executable. This is the same as the `config.gypi` file that was produced + * when running the `./configure` script. + * + * An example of the possible output looks like: + * + * ```js + * { + * target_defaults: + * { cflags: [], + * default_configuration: 'Release', + * defines: [], + * include_dirs: [], + * libraries: [] }, + * variables: + * { + * host_arch: 'x64', + * napi_build_version: 5, + * node_install_npm: 'true', + * node_prefix: '', + * node_shared_cares: 'false', + * node_shared_http_parser: 'false', + * node_shared_libuv: 'false', + * node_shared_zlib: 'false', + * node_use_openssl: 'true', + * node_shared_openssl: 'false', + * strict_aliasing: 'true', + * target_arch: 'x64', + * v8_use_snapshot: 1 + * } + * } + * ``` + * @since v0.7.7 + */ + readonly config: ProcessConfig; + /** + * The `process.kill()` method sends the `signal` to the process identified by`pid`. + * + * Signal names are strings such as `'SIGINT'` or `'SIGHUP'`. See `Signal Events` and [`kill(2)`](http://man7.org/linux/man-pages/man2/kill.2.html) for more information. + * + * This method will throw an error if the target `pid` does not exist. As a special + * case, a signal of `0` can be used to test for the existence of a process. + * Windows platforms will throw an error if the `pid` is used to kill a process + * group. + * + * Even though the name of this function is `process.kill()`, it is really just a + * signal sender, like the `kill` system call. The signal sent may do something + * other than kill the target process. + * + * ```js + * import process, { kill } from 'node:process'; + * + * process.on('SIGHUP', () => { + * console.log('Got SIGHUP signal.'); + * }); + * + * setTimeout(() => { + * console.log('Exiting.'); + * process.exit(0); + * }, 100); + * + * kill(process.pid, 'SIGHUP'); + * ``` + * + * When `SIGUSR1` is received by a Node.js process, Node.js will start the + * debugger. See `Signal Events`. + * @since v0.0.6 + * @param pid A process ID + * @param [signal='SIGTERM'] The signal to send, either as a string or number. + */ + kill(pid: number, signal?: string | number): true; + /** + * Loads the environment configuration from a `.env` file into `process.env`. If + * the file is not found, error will be thrown. + * + * To load a specific .env file by specifying its path, use the following code: + * + * ```js + * import { loadEnvFile } from 'node:process'; + * + * loadEnvFile('./development.env') + * ``` + * @since v20.12.0 + * @param path The path to the .env file + */ + loadEnvFile(path?: PathLike): void; + /** + * The `process.pid` property returns the PID of the process. + * + * ```js + * import { pid } from 'node:process'; + * + * console.log(`This process is pid ${pid}`); + * ``` + * @since v0.1.15 + */ + readonly pid: number; + /** + * The `process.ppid` property returns the PID of the parent of the + * current process. + * + * ```js + * import { ppid } from 'node:process'; + * + * console.log(`The parent process is pid ${ppid}`); + * ``` + * @since v9.2.0, v8.10.0, v6.13.0 + */ + readonly ppid: number; + /** + * The `process.threadCpuUsage()` method returns the user and system CPU time usage of + * the current worker thread, in an object with properties `user` and `system`, whose + * values are microsecond values (millionth of a second). + * + * The result of a previous call to `process.threadCpuUsage()` can be passed as the + * argument to the function, to get a diff reading. + * @since v23.9.0 + * @param previousValue A previous return value from calling + * `process.threadCpuUsage()` + */ + threadCpuUsage(previousValue?: CpuUsage): CpuUsage; + /** + * The `process.title` property returns the current process title (i.e. returns + * the current value of `ps`). Assigning a new value to `process.title` modifies + * the current value of `ps`. + * + * When a new value is assigned, different platforms will impose different maximum + * length restrictions on the title. Usually such restrictions are quite limited. + * For instance, on Linux and macOS, `process.title` is limited to the size of the + * binary name plus the length of the command-line arguments because setting the `process.title` overwrites the `argv` memory of the process. Node.js v0.8 + * allowed for longer process title strings by also overwriting the `environ` memory but that was potentially insecure and confusing in some (rather obscure) + * cases. + * + * Assigning a value to `process.title` might not result in an accurate label + * within process manager applications such as macOS Activity Monitor or Windows + * Services Manager. + * @since v0.1.104 + */ + title: string; + /** + * The operating system CPU architecture for which the Node.js binary was compiled. + * Possible values are: `'arm'`, `'arm64'`, `'ia32'`, `'loong64'`, `'mips'`, + * `'mipsel'`, `'ppc64'`, `'riscv64'`, `'s390x'`, and `'x64'`. + * + * ```js + * import { arch } from 'node:process'; + * + * console.log(`This processor architecture is ${arch}`); + * ``` + * @since v0.5.0 + */ + readonly arch: Architecture; + /** + * The `process.platform` property returns a string identifying the operating + * system platform for which the Node.js binary was compiled. + * + * Currently possible values are: + * + * * `'aix'` + * * `'darwin'` + * * `'freebsd'` + * * `'linux'` + * * `'openbsd'` + * * `'sunos'` + * * `'win32'` + * + * ```js + * import { platform } from 'node:process'; + * + * console.log(`This platform is ${platform}`); + * ``` + * + * The value `'android'` may also be returned if the Node.js is built on the + * Android operating system. However, Android support in Node.js [is experimental](https://github.com/nodejs/node/blob/HEAD/BUILDING.md#androidandroid-based-devices-eg-firefox-os). + * @since v0.1.16 + */ + readonly platform: Platform; + /** + * The `process.mainModule` property provides an alternative way of retrieving `require.main`. The difference is that if the main module changes at + * runtime, `require.main` may still refer to the original main module in + * modules that were required before the change occurred. Generally, it's + * safe to assume that the two refer to the same module. + * + * As with `require.main`, `process.mainModule` will be `undefined` if there + * is no entry script. + * @since v0.1.17 + * @deprecated Since v14.0.0 - Use `main` instead. + */ + mainModule?: Module; + memoryUsage: MemoryUsageFn; + /** + * Gets the amount of memory available to the process (in bytes) based on + * limits imposed by the OS. If there is no such constraint, or the constraint + * is unknown, `0` is returned. + * + * See [`uv_get_constrained_memory`](https://docs.libuv.org/en/v1.x/misc.html#c.uv_get_constrained_memory) for more + * information. + * @since v19.6.0, v18.15.0 + */ + constrainedMemory(): number; + /** + * Gets the amount of free memory that is still available to the process (in bytes). + * See [`uv_get_available_memory`](https://nodejs.org/docs/latest-v25.x/api/process.html#processavailablememory) for more information. + * @since v20.13.0 + */ + availableMemory(): number; + /** + * The `process.cpuUsage()` method returns the user and system CPU time usage of + * the current process, in an object with properties `user` and `system`, whose + * values are microsecond values (millionth of a second). These values measure time + * spent in user and system code respectively, and may end up being greater than + * actual elapsed time if multiple CPU cores are performing work for this process. + * + * The result of a previous call to `process.cpuUsage()` can be passed as the + * argument to the function, to get a diff reading. + * + * ```js + * import { cpuUsage } from 'node:process'; + * + * const startUsage = cpuUsage(); + * // { user: 38579, system: 6986 } + * + * // spin the CPU for 500 milliseconds + * const now = Date.now(); + * while (Date.now() - now < 500); + * + * console.log(cpuUsage(startUsage)); + * // { user: 514883, system: 11226 } + * ``` + * @since v6.1.0 + * @param previousValue A previous return value from calling `process.cpuUsage()` + */ + cpuUsage(previousValue?: CpuUsage): CpuUsage; + /** + * `process.nextTick()` adds `callback` to the "next tick queue". This queue is + * fully drained after the current operation on the JavaScript stack runs to + * completion and before the event loop is allowed to continue. It's possible to + * create an infinite loop if one were to recursively call `process.nextTick()`. + * See the [Event Loop](https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/#process-nexttick) guide for more background. + * + * ```js + * import { nextTick } from 'node:process'; + * + * console.log('start'); + * nextTick(() => { + * console.log('nextTick callback'); + * }); + * console.log('scheduled'); + * // Output: + * // start + * // scheduled + * // nextTick callback + * ``` + * + * This is important when developing APIs in order to give users the opportunity + * to assign event handlers _after_ an object has been constructed but before any + * I/O has occurred: + * + * ```js + * import { nextTick } from 'node:process'; + * + * function MyThing(options) { + * this.setupOptions(options); + * + * nextTick(() => { + * this.startDoingStuff(); + * }); + * } + * + * const thing = new MyThing(); + * thing.getReadyForStuff(); + * + * // thing.startDoingStuff() gets called now, not before. + * ``` + * + * It is very important for APIs to be either 100% synchronous or 100% + * asynchronous. Consider this example: + * + * ```js + * // WARNING! DO NOT USE! BAD UNSAFE HAZARD! + * function maybeSync(arg, cb) { + * if (arg) { + * cb(); + * return; + * } + * + * fs.stat('file', cb); + * } + * ``` + * + * This API is hazardous because in the following case: + * + * ```js + * const maybeTrue = Math.random() > 0.5; + * + * maybeSync(maybeTrue, () => { + * foo(); + * }); + * + * bar(); + * ``` + * + * It is not clear whether `foo()` or `bar()` will be called first. + * + * The following approach is much better: + * + * ```js + * import { nextTick } from 'node:process'; + * + * function definitelyAsync(arg, cb) { + * if (arg) { + * nextTick(cb); + * return; + * } + * + * fs.stat('file', cb); + * } + * ``` + * @since v0.1.26 + * @param args Additional arguments to pass when invoking the `callback` + */ + nextTick(callback: Function, ...args: any[]): void; + /** + * The process.noDeprecation property indicates whether the --no-deprecation flag is set on the current Node.js process. + * See the documentation for the ['warning' event](https://nodejs.org/docs/latest/api/process.html#event-warning) and the [emitWarning()](https://nodejs.org/docs/latest/api/process.html#processemitwarningwarning-type-code-ctor) method for more information about this flag's behavior. + */ + noDeprecation?: boolean; + /** + * This API is available through the [--permission](https://nodejs.org/api/cli.html#--permission) flag. + * + * `process.permission` is an object whose methods are used to manage permissions for the current process. + * Additional documentation is available in the [Permission Model](https://nodejs.org/api/permissions.html#permission-model). + * @since v20.0.0 + */ + permission: ProcessPermission; + /** + * The `process.release` property returns an `Object` containing metadata related + * to the current release, including URLs for the source tarball and headers-only + * tarball. + * + * `process.release` contains the following properties: + * + * ```js + * { + * name: 'node', + * lts: 'Hydrogen', + * sourceUrl: 'https://nodejs.org/download/release/v18.12.0/node-v18.12.0.tar.gz', + * headersUrl: 'https://nodejs.org/download/release/v18.12.0/node-v18.12.0-headers.tar.gz', + * libUrl: 'https://nodejs.org/download/release/v18.12.0/win-x64/node.lib' + * } + * ``` + * + * In custom builds from non-release versions of the source tree, only the `name` property may be present. The additional properties should not be + * relied upon to exist. + * @since v3.0.0 + */ + readonly release: ProcessRelease; + readonly features: ProcessFeatures; + /** + * `process.umask()` returns the Node.js process's file mode creation mask. Child + * processes inherit the mask from the parent process. + * @since v0.1.19 + * @deprecated Calling `process.umask()` with no argument causes the process-wide umask to be written twice. This introduces a race condition between threads, and is a potential + * security vulnerability. There is no safe, cross-platform alternative API. + */ + umask(): number; + /** + * Can only be set if not in worker thread. + */ + umask(mask: string | number): number; + /** + * The `process.uptime()` method returns the number of seconds the current Node.js + * process has been running. + * + * The return value includes fractions of a second. Use `Math.floor()` to get whole + * seconds. + * @since v0.5.0 + */ + uptime(): number; + hrtime: HRTime; + /** + * If the Node.js process was spawned with an IPC channel, the process.channel property is a reference to the IPC channel. + * If no IPC channel exists, this property is undefined. + * @since v7.1.0 + */ + channel?: Control; + /** + * If Node.js is spawned with an IPC channel, the `process.send()` method can be + * used to send messages to the parent process. Messages will be received as a `'message'` event on the parent's `ChildProcess` object. + * + * If Node.js was not spawned with an IPC channel, `process.send` will be `undefined`. + * + * The message goes through serialization and parsing. The resulting message might + * not be the same as what is originally sent. + * @since v0.5.9 + * @param options used to parameterize the sending of certain types of handles. `options` supports the following properties: + */ + send?( + message: any, + sendHandle?: SendHandle, + options?: MessageOptions, + callback?: (error: Error | null) => void, + ): boolean; + send?( + message: any, + sendHandle: SendHandle, + callback?: (error: Error | null) => void, + ): boolean; + send?( + message: any, + callback: (error: Error | null) => void, + ): boolean; + /** + * If the Node.js process is spawned with an IPC channel (see the `Child Process` and `Cluster` documentation), the `process.disconnect()` method will close the + * IPC channel to the parent process, allowing the child process to exit gracefully + * once there are no other connections keeping it alive. + * + * The effect of calling `process.disconnect()` is the same as calling `ChildProcess.disconnect()` from the parent process. + * + * If the Node.js process was not spawned with an IPC channel, `process.disconnect()` will be `undefined`. + * @since v0.7.2 + */ + disconnect?(): void; + /** + * If the Node.js process is spawned with an IPC channel (see the `Child Process` and `Cluster` documentation), the `process.connected` property will return `true` so long as the IPC + * channel is connected and will return `false` after `process.disconnect()` is called. + * + * Once `process.connected` is `false`, it is no longer possible to send messages + * over the IPC channel using `process.send()`. + * @since v0.7.2 + */ + connected: boolean; + /** + * The `process.allowedNodeEnvironmentFlags` property is a special, + * read-only `Set` of flags allowable within the `NODE_OPTIONS` environment variable. + * + * `process.allowedNodeEnvironmentFlags` extends `Set`, but overrides `Set.prototype.has` to recognize several different possible flag + * representations. `process.allowedNodeEnvironmentFlags.has()` will + * return `true` in the following cases: + * + * * Flags may omit leading single (`-`) or double (`--`) dashes; e.g., `inspect-brk` for `--inspect-brk`, or `r` for `-r`. + * * Flags passed through to V8 (as listed in `--v8-options`) may replace + * one or more _non-leading_ dashes for an underscore, or vice-versa; + * e.g., `--perf_basic_prof`, `--perf-basic-prof`, `--perf_basic-prof`, + * etc. + * * Flags may contain one or more equals (`=`) characters; all + * characters after and including the first equals will be ignored; + * e.g., `--stack-trace-limit=100`. + * * Flags _must_ be allowable within `NODE_OPTIONS`. + * + * When iterating over `process.allowedNodeEnvironmentFlags`, flags will + * appear only _once_; each will begin with one or more dashes. Flags + * passed through to V8 will contain underscores instead of non-leading + * dashes: + * + * ```js + * import { allowedNodeEnvironmentFlags } from 'node:process'; + * + * allowedNodeEnvironmentFlags.forEach((flag) => { + * // -r + * // --inspect-brk + * // --abort_on_uncaught_exception + * // ... + * }); + * ``` + * + * The methods `add()`, `clear()`, and `delete()` of`process.allowedNodeEnvironmentFlags` do nothing, and will fail + * silently. + * + * If Node.js was compiled _without_ `NODE_OPTIONS` support (shown in {@link config}), `process.allowedNodeEnvironmentFlags` will + * contain what _would have_ been allowable. + * @since v10.10.0 + */ + allowedNodeEnvironmentFlags: ReadonlySet<string>; + /** + * `process.report` is an object whose methods are used to generate diagnostic reports for the current process. + * Additional documentation is available in the [report documentation](https://nodejs.org/docs/latest-v25.x/api/report.html). + * @since v11.8.0 + */ + report: ProcessReport; + /** + * ```js + * import { resourceUsage } from 'node:process'; + * + * console.log(resourceUsage()); + * /* + * Will output: + * { + * userCPUTime: 82872, + * systemCPUTime: 4143, + * maxRSS: 33164, + * sharedMemorySize: 0, + * unsharedDataSize: 0, + * unsharedStackSize: 0, + * minorPageFault: 2469, + * majorPageFault: 0, + * swappedOut: 0, + * fsRead: 0, + * fsWrite: 8, + * ipcSent: 0, + * ipcReceived: 0, + * signalsCount: 0, + * voluntaryContextSwitches: 79, + * involuntaryContextSwitches: 1 + * } + * + * ``` + * @since v12.6.0 + * @return the resource usage for the current process. All of these values come from the `uv_getrusage` call which returns a [`uv_rusage_t` struct][uv_rusage_t]. + */ + resourceUsage(): ResourceUsage; + /** + * The initial value of `process.throwDeprecation` indicates whether the `--throw-deprecation` flag is set on the current Node.js process. `process.throwDeprecation` + * is mutable, so whether or not deprecation warnings result in errors may be altered at runtime. See the documentation for the 'warning' event and the emitWarning() + * method for more information. + * + * ```bash + * $ node --throw-deprecation -p "process.throwDeprecation" + * true + * $ node -p "process.throwDeprecation" + * undefined + * $ node + * > process.emitWarning('test', 'DeprecationWarning'); + * undefined + * > (node:26598) DeprecationWarning: test + * > process.throwDeprecation = true; + * true + * > process.emitWarning('test', 'DeprecationWarning'); + * Thrown: + * [DeprecationWarning: test] { name: 'DeprecationWarning' } + * ``` + * @since v0.9.12 + */ + throwDeprecation: boolean; + /** + * The `process.traceDeprecation` property indicates whether the `--trace-deprecation` flag is set on the current Node.js process. See the + * documentation for the `'warning' event` and the `emitWarning() method` for more information about this + * flag's behavior. + * @since v0.8.0 + */ + traceDeprecation: boolean; + /** + * An object is "refable" if it implements the Node.js "Refable protocol". + * Specifically, this means that the object implements the `Symbol.for('nodejs.ref')` + * and `Symbol.for('nodejs.unref')` methods. "Ref'd" objects will keep the Node.js + * event loop alive, while "unref'd" objects will not. Historically, this was + * implemented by using `ref()` and `unref()` methods directly on the objects. + * This pattern, however, is being deprecated in favor of the "Refable protocol" + * in order to better support Web Platform API types whose APIs cannot be modified + * to add `ref()` and `unref()` methods but still need to support that behavior. + * @since v22.14.0 + * @experimental + * @param maybeRefable An object that may be "refable". + */ + ref(maybeRefable: any): void; + /** + * An object is "unrefable" if it implements the Node.js "Refable protocol". + * Specifically, this means that the object implements the `Symbol.for('nodejs.ref')` + * and `Symbol.for('nodejs.unref')` methods. "Ref'd" objects will keep the Node.js + * event loop alive, while "unref'd" objects will not. Historically, this was + * implemented by using `ref()` and `unref()` methods directly on the objects. + * This pattern, however, is being deprecated in favor of the "Refable protocol" + * in order to better support Web Platform API types whose APIs cannot be modified + * to add `ref()` and `unref()` methods but still need to support that behavior. + * @since v22.14.0 + * @experimental + * @param maybeRefable An object that may be "unref'd". + */ + unref(maybeRefable: any): void; + /** + * Replaces the current process with a new process. + * + * This is achieved by using the `execve` POSIX function and therefore no memory or other + * resources from the current process are preserved, except for the standard input, + * standard output and standard error file descriptor. + * + * All other resources are discarded by the system when the processes are swapped, without triggering + * any exit or close events and without running any cleanup handler. + * + * This function will never return, unless an error occurred. + * + * This function is not available on Windows or IBM i. + * @since v22.15.0 + * @experimental + * @param file The name or path of the executable file to run. + * @param args List of string arguments. No argument can contain a null-byte (`\u0000`). + * @param env Environment key-value pairs. + * No key or value can contain a null-byte (`\u0000`). + * **Default:** `process.env`. + */ + execve?(file: string, args?: readonly string[], env?: ProcessEnv): never; + // #region InternalEventEmitter + addListener<E extends keyof ProcessEventMap>( + eventName: E, + listener: (...args: ProcessEventMap[E]) => void, + ): this; + addListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + emit<E extends keyof ProcessEventMap>(eventName: E, ...args: ProcessEventMap[E]): boolean; + emit(eventName: string | symbol, ...args: any[]): boolean; + listenerCount<E extends keyof ProcessEventMap>( + eventName: E, + listener?: (...args: ProcessEventMap[E]) => void, + ): number; + listenerCount(eventName: string | symbol, listener?: (...args: any[]) => void): number; + listeners<E extends keyof ProcessEventMap>(eventName: E): ((...args: ProcessEventMap[E]) => void)[]; + listeners(eventName: string | symbol): ((...args: any[]) => void)[]; + off<E extends keyof ProcessEventMap>( + eventName: E, + listener: (...args: ProcessEventMap[E]) => void, + ): this; + off(eventName: string | symbol, listener: (...args: any[]) => void): this; + on<E extends keyof ProcessEventMap>( + eventName: E, + listener: (...args: ProcessEventMap[E]) => void, + ): this; + on(eventName: string | symbol, listener: (...args: any[]) => void): this; + once<E extends keyof ProcessEventMap>( + eventName: E, + listener: (...args: ProcessEventMap[E]) => void, + ): this; + once(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependListener<E extends keyof ProcessEventMap>( + eventName: E, + listener: (...args: ProcessEventMap[E]) => void, + ): this; + prependListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependOnceListener<E extends keyof ProcessEventMap>( + eventName: E, + listener: (...args: ProcessEventMap[E]) => void, + ): this; + prependOnceListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + rawListeners<E extends keyof ProcessEventMap>(eventName: E): ((...args: ProcessEventMap[E]) => void)[]; + rawListeners(eventName: string | symbol): ((...args: any[]) => void)[]; + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + removeAllListeners<E extends keyof ProcessEventMap>(eventName?: E): this; + removeAllListeners(eventName?: string | symbol): this; + removeListener<E extends keyof ProcessEventMap>( + eventName: E, + listener: (...args: ProcessEventMap[E]) => void, + ): this; + removeListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + // #endregion + } + } + } + export = process; +} +declare module "process" { + import process = require("node:process"); + export = process; +} diff --git a/server/node_modules/@types/node/punycode.d.ts b/server/node_modules/@types/node/punycode.d.ts new file mode 100644 index 0000000..d293553 --- /dev/null +++ b/server/node_modules/@types/node/punycode.d.ts @@ -0,0 +1,117 @@ +/** + * **The version of the punycode module bundled in Node.js is being deprecated. **In a future major version of Node.js this module will be removed. Users + * currently depending on the `punycode` module should switch to using the + * userland-provided [Punycode.js](https://github.com/bestiejs/punycode.js) module instead. For punycode-based URL + * encoding, see `url.domainToASCII` or, more generally, the `WHATWG URL API`. + * + * The `punycode` module is a bundled version of the [Punycode.js](https://github.com/bestiejs/punycode.js) module. It + * can be accessed using: + * + * ```js + * import punycode from 'node:punycode'; + * ``` + * + * [Punycode](https://tools.ietf.org/html/rfc3492) is a character encoding scheme defined by RFC 3492 that is + * primarily intended for use in Internationalized Domain Names. Because host + * names in URLs are limited to ASCII characters only, Domain Names that contain + * non-ASCII characters must be converted into ASCII using the Punycode scheme. + * For instance, the Japanese character that translates into the English word, `'example'` is `'例'`. The Internationalized Domain Name, `'例.com'` (equivalent + * to `'example.com'`) is represented by Punycode as the ASCII string `'xn--fsq.com'`. + * + * The `punycode` module provides a simple implementation of the Punycode standard. + * + * The `punycode` module is a third-party dependency used by Node.js and + * made available to developers as a convenience. Fixes or other modifications to + * the module must be directed to the [Punycode.js](https://github.com/bestiejs/punycode.js) project. + * @deprecated + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/punycode.js) + */ +declare module "node:punycode" { + /** + * The `punycode.decode()` method converts a [Punycode](https://tools.ietf.org/html/rfc3492) string of ASCII-only + * characters to the equivalent string of Unicode codepoints. + * + * ```js + * punycode.decode('maana-pta'); // 'mañana' + * punycode.decode('--dqo34k'); // '☃-⌘' + * ``` + * @since v0.5.1 + */ + function decode(string: string): string; + /** + * The `punycode.encode()` method converts a string of Unicode codepoints to a [Punycode](https://tools.ietf.org/html/rfc3492) string of ASCII-only characters. + * + * ```js + * punycode.encode('mañana'); // 'maana-pta' + * punycode.encode('☃-⌘'); // '--dqo34k' + * ``` + * @since v0.5.1 + */ + function encode(string: string): string; + /** + * The `punycode.toUnicode()` method converts a string representing a domain name + * containing [Punycode](https://tools.ietf.org/html/rfc3492) encoded characters into Unicode. Only the [Punycode](https://tools.ietf.org/html/rfc3492) encoded parts of the domain name are be + * converted. + * + * ```js + * // decode domain names + * punycode.toUnicode('xn--maana-pta.com'); // 'mañana.com' + * punycode.toUnicode('xn----dqo34k.com'); // '☃-⌘.com' + * punycode.toUnicode('example.com'); // 'example.com' + * ``` + * @since v0.6.1 + */ + function toUnicode(domain: string): string; + /** + * The `punycode.toASCII()` method converts a Unicode string representing an + * Internationalized Domain Name to [Punycode](https://tools.ietf.org/html/rfc3492). Only the non-ASCII parts of the + * domain name will be converted. Calling `punycode.toASCII()` on a string that + * already only contains ASCII characters will have no effect. + * + * ```js + * // encode domain names + * punycode.toASCII('mañana.com'); // 'xn--maana-pta.com' + * punycode.toASCII('☃-⌘.com'); // 'xn----dqo34k.com' + * punycode.toASCII('example.com'); // 'example.com' + * ``` + * @since v0.6.1 + */ + function toASCII(domain: string): string; + /** + * @deprecated since v7.0.0 + * The version of the punycode module bundled in Node.js is being deprecated. + * In a future major version of Node.js this module will be removed. + * Users currently depending on the punycode module should switch to using + * the userland-provided Punycode.js module instead. + */ + const ucs2: ucs2; + interface ucs2 { + /** + * @deprecated since v7.0.0 + * The version of the punycode module bundled in Node.js is being deprecated. + * In a future major version of Node.js this module will be removed. + * Users currently depending on the punycode module should switch to using + * the userland-provided Punycode.js module instead. + */ + decode(string: string): number[]; + /** + * @deprecated since v7.0.0 + * The version of the punycode module bundled in Node.js is being deprecated. + * In a future major version of Node.js this module will be removed. + * Users currently depending on the punycode module should switch to using + * the userland-provided Punycode.js module instead. + */ + encode(codePoints: readonly number[]): string; + } + /** + * @deprecated since v7.0.0 + * The version of the punycode module bundled in Node.js is being deprecated. + * In a future major version of Node.js this module will be removed. + * Users currently depending on the punycode module should switch to using + * the userland-provided Punycode.js module instead. + */ + const version: string; +} +declare module "punycode" { + export * from "node:punycode"; +} diff --git a/server/node_modules/@types/node/querystring.d.ts b/server/node_modules/@types/node/querystring.d.ts new file mode 100644 index 0000000..dc421bc --- /dev/null +++ b/server/node_modules/@types/node/querystring.d.ts @@ -0,0 +1,152 @@ +/** + * The `node:querystring` module provides utilities for parsing and formatting URL + * query strings. It can be accessed using: + * + * ```js + * import querystring from 'node:querystring'; + * ``` + * + * `querystring` is more performant than `URLSearchParams` but is not a + * standardized API. Use `URLSearchParams` when performance is not critical or + * when compatibility with browser code is desirable. + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/querystring.js) + */ +declare module "node:querystring" { + interface StringifyOptions { + /** + * The function to use when converting URL-unsafe characters to percent-encoding in the query string. + * @default `querystring.escape()` + */ + encodeURIComponent?: ((str: string) => string) | undefined; + } + interface ParseOptions { + /** + * Specifies the maximum number of keys to parse. Specify `0` to remove key counting limitations. + * @default 1000 + */ + maxKeys?: number | undefined; + /** + * The function to use when decoding percent-encoded characters in the query string. + * @default `querystring.unescape()` + */ + decodeURIComponent?: ((str: string) => string) | undefined; + } + interface ParsedUrlQuery extends NodeJS.Dict<string | string[]> {} + interface ParsedUrlQueryInput extends + NodeJS.Dict< + | string + | number + | boolean + | bigint + | ReadonlyArray<string | number | boolean | bigint> + | null + > + {} + /** + * The `querystring.stringify()` method produces a URL query string from a + * given `obj` by iterating through the object's "own properties". + * + * It serializes the following types of values passed in `obj`: [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type) | + * [number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Number_type) | + * [bigint](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) | + * [boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Boolean_type) | + * [string\[\]](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type) | + * [number\[\]](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Number_type) | + * [bigint\[\]](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) | + * [boolean\[\]](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Boolean_type) The numeric values must be finite. Any other input values will be coerced to + * empty strings. + * + * ```js + * querystring.stringify({ foo: 'bar', baz: ['qux', 'quux'], corge: '' }); + * // Returns 'foo=bar&baz=qux&baz=quux&corge=' + * + * querystring.stringify({ foo: 'bar', baz: 'qux' }, ';', ':'); + * // Returns 'foo:bar;baz:qux' + * ``` + * + * By default, characters requiring percent-encoding within the query string will + * be encoded as UTF-8\. If an alternative encoding is required, then an alternative `encodeURIComponent` option will need to be specified: + * + * ```js + * // Assuming gbkEncodeURIComponent function already exists, + * + * querystring.stringify({ w: '中文', foo: 'bar' }, null, null, + * { encodeURIComponent: gbkEncodeURIComponent }); + * ``` + * @since v0.1.25 + * @param obj The object to serialize into a URL query string + * @param [sep='&'] The substring used to delimit key and value pairs in the query string. + * @param [eq='='] . The substring used to delimit keys and values in the query string. + */ + function stringify(obj?: ParsedUrlQueryInput, sep?: string, eq?: string, options?: StringifyOptions): string; + /** + * The `querystring.parse()` method parses a URL query string (`str`) into a + * collection of key and value pairs. + * + * For example, the query string `'foo=bar&abc=xyz&abc=123'` is parsed into: + * + * ```json + * { + * "foo": "bar", + * "abc": ["xyz", "123"] + * } + * ``` + * + * The object returned by the `querystring.parse()` method _does not_ prototypically inherit from the JavaScript `Object`. This means that typical `Object` methods such as `obj.toString()`, + * `obj.hasOwnProperty()`, and others + * are not defined and _will not work_. + * + * By default, percent-encoded characters within the query string will be assumed + * to use UTF-8 encoding. If an alternative character encoding is used, then an + * alternative `decodeURIComponent` option will need to be specified: + * + * ```js + * // Assuming gbkDecodeURIComponent function already exists... + * + * querystring.parse('w=%D6%D0%CE%C4&foo=bar', null, null, + * { decodeURIComponent: gbkDecodeURIComponent }); + * ``` + * @since v0.1.25 + * @param str The URL query string to parse + * @param [sep='&'] The substring used to delimit key and value pairs in the query string. + * @param [eq='='] The substring used to delimit keys and values in the query string. + */ + function parse(str: string, sep?: string, eq?: string, options?: ParseOptions): ParsedUrlQuery; + /** + * The querystring.encode() function is an alias for querystring.stringify(). + */ + const encode: typeof stringify; + /** + * The querystring.decode() function is an alias for querystring.parse(). + */ + const decode: typeof parse; + /** + * The `querystring.escape()` method performs URL percent-encoding on the given `str` in a manner that is optimized for the specific requirements of URL + * query strings. + * + * The `querystring.escape()` method is used by `querystring.stringify()` and is + * generally not expected to be used directly. It is exported primarily to allow + * application code to provide a replacement percent-encoding implementation if + * necessary by assigning `querystring.escape` to an alternative function. + * @since v0.1.25 + */ + function escape(str: string): string; + /** + * The `querystring.unescape()` method performs decoding of URL percent-encoded + * characters on the given `str`. + * + * The `querystring.unescape()` method is used by `querystring.parse()` and is + * generally not expected to be used directly. It is exported primarily to allow + * application code to provide a replacement decoding implementation if + * necessary by assigning `querystring.unescape` to an alternative function. + * + * By default, the `querystring.unescape()` method will attempt to use the + * JavaScript built-in `decodeURIComponent()` method to decode. If that fails, + * a safer equivalent that does not throw on malformed URLs will be used. + * @since v0.1.25 + */ + function unescape(str: string): string; +} +declare module "querystring" { + export * from "node:querystring"; +} diff --git a/server/node_modules/@types/node/quic.d.ts b/server/node_modules/@types/node/quic.d.ts new file mode 100644 index 0000000..9a6fd97 --- /dev/null +++ b/server/node_modules/@types/node/quic.d.ts @@ -0,0 +1,910 @@ +/** + * The 'node:quic' module provides an implementation of the QUIC protocol. + * To access it, start Node.js with the `--experimental-quic` option and: + * + * ```js + * import quic from 'node:quic'; + * ``` + * + * The module is only available under the `node:` scheme. + * @since v23.8.0 + * @experimental + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/quic.js) + */ +declare module "node:quic" { + import { KeyObject, webcrypto } from "node:crypto"; + import { SocketAddress } from "node:net"; + import { ReadableStream } from "node:stream/web"; + /** + * @since v23.8.0 + */ + type OnSessionCallback = (this: QuicEndpoint, session: QuicSession) => void; + /** + * @since v23.8.0 + */ + type OnStreamCallback = (this: QuicSession, stream: QuicStream) => void; + /** + * @since v23.8.0 + */ + type OnDatagramCallback = (this: QuicSession, datagram: Uint8Array, early: boolean) => void; + /** + * @since v23.8.0 + */ + type OnDatagramStatusCallback = (this: QuicSession, id: bigint, status: "lost" | "acknowledged") => void; + /** + * @since v23.8.0 + */ + type OnPathValidationCallback = ( + this: QuicSession, + result: "success" | "failure" | "aborted", + newLocalAddress: SocketAddress, + newRemoteAddress: SocketAddress, + oldLocalAddress: SocketAddress, + oldRemoteAddress: SocketAddress, + preferredAddress: boolean, + ) => void; + /** + * @since v23.8.0 + */ + type OnSessionTicketCallback = (this: QuicSession, ticket: object) => void; + /** + * @since v23.8.0 + */ + type OnVersionNegotiationCallback = ( + this: QuicSession, + version: number, + requestedVersions: number[], + supportedVersions: number[], + ) => void; + /** + * @since v23.8.0 + */ + type OnHandshakeCallback = ( + this: QuicSession, + sni: string, + alpn: string, + cipher: string, + cipherVersion: string, + validationErrorReason: string, + validationErrorCode: number, + earlyDataAccepted: boolean, + ) => void; + /** + * @since v23.8.0 + */ + type OnBlockedCallback = (this: QuicStream) => void; + /** + * @since v23.8.0 + */ + type OnStreamErrorCallback = (this: QuicStream, error: any) => void; + /** + * @since v23.8.0 + */ + interface TransportParams { + /** + * The preferred IPv4 address to advertise. + * @since v23.8.0 + */ + preferredAddressIpv4?: SocketAddress | undefined; + /** + * The preferred IPv6 address to advertise. + * @since v23.8.0 + */ + preferredAddressIpv6?: SocketAddress | undefined; + /** + * @since v23.8.0 + */ + initialMaxStreamDataBidiLocal?: bigint | number | undefined; + /** + * @since v23.8.0 + */ + initialMaxStreamDataBidiRemote?: bigint | number | undefined; + /** + * @since v23.8.0 + */ + initialMaxStreamDataUni?: bigint | number | undefined; + /** + * @since v23.8.0 + */ + initialMaxData?: bigint | number | undefined; + /** + * @since v23.8.0 + */ + initialMaxStreamsBidi?: bigint | number | undefined; + /** + * @since v23.8.0 + */ + initialMaxStreamsUni?: bigint | number | undefined; + /** + * @since v23.8.0 + */ + maxIdleTimeout?: bigint | number | undefined; + /** + * @since v23.8.0 + */ + activeConnectionIDLimit?: bigint | number | undefined; + /** + * @since v23.8.0 + */ + ackDelayExponent?: bigint | number | undefined; + /** + * @since v23.8.0 + */ + maxAckDelay?: bigint | number | undefined; + /** + * @since v23.8.0 + */ + maxDatagramFrameSize?: bigint | number | undefined; + } + /** + * @since v23.8.0 + */ + interface SessionOptions { + /** + * An endpoint to use. + * @since v23.8.0 + */ + endpoint?: EndpointOptions | QuicEndpoint | undefined; + /** + * The ALPN protocol identifier. + * @since v23.8.0 + */ + alpn?: string | undefined; + /** + * The CA certificates to use for sessions. + * @since v23.8.0 + */ + ca?: ArrayBuffer | NodeJS.ArrayBufferView | ReadonlyArray<ArrayBuffer | NodeJS.ArrayBufferView> | undefined; + /** + * Specifies the congestion control algorithm that will be used. + * Must be set to one of either `'reno'`, `'cubic'`, or `'bbr'`. + * + * This is an advanced option that users typically won't have need to specify. + * @since v23.8.0 + */ + cc?: `${constants.cc}` | undefined; + /** + * The TLS certificates to use for sessions. + * @since v23.8.0 + */ + certs?: ArrayBuffer | NodeJS.ArrayBufferView | ReadonlyArray<ArrayBuffer | NodeJS.ArrayBufferView> | undefined; + /** + * The list of supported TLS 1.3 cipher algorithms. + * @since v23.8.0 + */ + ciphers?: string | undefined; + /** + * The CRL to use for sessions. + * @since v23.8.0 + */ + crl?: ArrayBuffer | NodeJS.ArrayBufferView | ReadonlyArray<ArrayBuffer | NodeJS.ArrayBufferView> | undefined; + /** + * The list of support TLS 1.3 cipher groups. + * @since v23.8.0 + */ + groups?: string | undefined; + /** + * True to enable TLS keylogging output. + * @since v23.8.0 + */ + keylog?: boolean | undefined; + /** + * The TLS crypto keys to use for sessions. + * @since v23.8.0 + */ + keys?: KeyObject | webcrypto.CryptoKey | ReadonlyArray<KeyObject | webcrypto.CryptoKey> | undefined; + /** + * Specifies the maximum UDP packet payload size. + * @since v23.8.0 + */ + maxPayloadSize?: bigint | number | undefined; + /** + * Specifies the maximum stream flow-control window size. + * @since v23.8.0 + */ + maxStreamWindow?: bigint | number | undefined; + /** + * Specifies the maximum session flow-control window size. + * @since v23.8.0 + */ + maxWindow?: bigint | number | undefined; + /** + * The minimum QUIC version number to allow. This is an advanced option that users + * typically won't have need to specify. + * @since v23.8.0 + */ + minVersion?: number | undefined; + /** + * When the remote peer advertises a preferred address, this option specifies whether + * to use it or ignore it. + * @since v23.8.0 + */ + preferredAddressPolicy?: "use" | "ignore" | "default" | undefined; + /** + * True if qlog output should be enabled. + * @since v23.8.0 + */ + qlog?: boolean | undefined; + /** + * A session ticket to use for 0RTT session resumption. + * @since v23.8.0 + */ + sessionTicket?: NodeJS.ArrayBufferView | undefined; + /** + * Specifies the maximum number of milliseconds a TLS handshake is permitted to take + * to complete before timing out. + * @since v23.8.0 + */ + handshakeTimeout?: bigint | number | undefined; + /** + * The peer server name to target. + * @since v23.8.0 + */ + sni?: string | undefined; + /** + * True to enable TLS tracing output. + * @since v23.8.0 + */ + tlsTrace?: boolean | undefined; + /** + * The QUIC transport parameters to use for the session. + * @since v23.8.0 + */ + transportParams?: TransportParams | undefined; + /** + * Specifies the maximum number of unacknowledged packets a session should allow. + * @since v23.8.0 + */ + unacknowledgedPacketThreshold?: bigint | number | undefined; + /** + * True to require verification of TLS client certificate. + * @since v23.8.0 + */ + verifyClient?: boolean | undefined; + /** + * True to require private key verification. + * @since v23.8.0 + */ + verifyPrivateKey?: boolean | undefined; + /** + * The QUIC version number to use. This is an advanced option that users typically + * won't have need to specify. + * @since v23.8.0 + */ + version?: number | undefined; + } + /** + * Initiate a new client-side session. + * + * ```js + * import { connect } from 'node:quic'; + * import { Buffer } from 'node:buffer'; + * + * const enc = new TextEncoder(); + * const alpn = 'foo'; + * const client = await connect('123.123.123.123:8888', { alpn }); + * await client.createUnidirectionalStream({ + * body: enc.encode('hello world'), + * }); + * ``` + * + * By default, every call to `connect(...)` will create a new local + * `QuicEndpoint` instance bound to a new random local IP port. To + * specify the exact local address to use, or to multiplex multiple + * QUIC sessions over a single local port, pass the `endpoint` option + * with either a `QuicEndpoint` or `EndpointOptions` as the argument. + * + * ```js + * import { QuicEndpoint, connect } from 'node:quic'; + * + * const endpoint = new QuicEndpoint({ + * address: '127.0.0.1:1234', + * }); + * + * const client = await connect('123.123.123.123:8888', { endpoint }); + * ``` + * @since v23.8.0 + */ + function connect(address: string | SocketAddress, options?: SessionOptions): Promise<QuicSession>; + /** + * Configures the endpoint to listen as a server. When a new session is initiated by + * a remote peer, the given `onsession` callback will be invoked with the created + * session. + * + * ```js + * import { listen } from 'node:quic'; + * + * const endpoint = await listen((session) => { + * // ... handle the session + * }); + * + * // Closing the endpoint allows any sessions open when close is called + * // to complete naturally while preventing new sessions from being + * // initiated. Once all existing sessions have finished, the endpoint + * // will be destroyed. The call returns a promise that is resolved once + * // the endpoint is destroyed. + * await endpoint.close(); + * ``` + * + * By default, every call to `listen(...)` will create a new local + * `QuicEndpoint` instance bound to a new random local IP port. To + * specify the exact local address to use, or to multiplex multiple + * QUIC sessions over a single local port, pass the `endpoint` option + * with either a `QuicEndpoint` or `EndpointOptions` as the argument. + * + * At most, any single `QuicEndpoint` can only be configured to listen as + * a server once. + * @since v23.8.0 + */ + function listen(onsession: OnSessionCallback, options?: SessionOptions): Promise<QuicEndpoint>; + /** + * The endpoint configuration options passed when constructing a new `QuicEndpoint` instance. + * @since v23.8.0 + */ + interface EndpointOptions { + /** + * If not specified the endpoint will bind to IPv4 `localhost` on a random port. + * @since v23.8.0 + */ + address?: SocketAddress | string | undefined; + /** + * The endpoint maintains an internal cache of validated socket addresses as a + * performance optimization. This option sets the maximum number of addresses + * that are cache. This is an advanced option that users typically won't have + * need to specify. + * @since v23.8.0 + */ + addressLRUSize?: bigint | number | undefined; + /** + * When `true`, indicates that the endpoint should bind only to IPv6 addresses. + * @since v23.8.0 + */ + ipv6Only?: boolean | undefined; + /** + * Specifies the maximum number of concurrent sessions allowed per remote peer address. + * @since v23.8.0 + */ + maxConnectionsPerHost?: bigint | number | undefined; + /** + * Specifies the maximum total number of concurrent sessions. + * @since v23.8.0 + */ + maxConnectionsTotal?: bigint | number | undefined; + /** + * Specifies the maximum number of QUIC retry attempts allowed per remote peer address. + * @since v23.8.0 + */ + maxRetries?: bigint | number | undefined; + /** + * Specifies the maximum number of stateless resets that are allowed per remote peer address. + * @since v23.8.0 + */ + maxStatelessResetsPerHost?: bigint | number | undefined; + /** + * Specifies the length of time a QUIC retry token is considered valid. + * @since v23.8.0 + */ + retryTokenExpiration?: bigint | number | undefined; + /** + * Specifies the 16-byte secret used to generate QUIC retry tokens. + * @since v23.8.0 + */ + resetTokenSecret?: NodeJS.ArrayBufferView | undefined; + /** + * Specifies the length of time a QUIC token is considered valid. + * @since v23.8.0 + */ + tokenExpiration?: bigint | number | undefined; + /** + * Specifies the 16-byte secret used to generate QUIC tokens. + * @since v23.8.0 + */ + tokenSecret?: NodeJS.ArrayBufferView | undefined; + /** + * @since v23.8.0 + */ + udpReceiveBufferSize?: number | undefined; + /** + * @since v23.8.0 + */ + udpSendBufferSize?: number | undefined; + /** + * @since v23.8.0 + */ + udpTTL?: number | undefined; + /** + * When `true`, requires that the endpoint validate peer addresses using retry packets + * while establishing a new connection. + * @since v23.8.0 + */ + validateAddress?: boolean | undefined; + } + /** + * A `QuicEndpoint` encapsulates the local UDP-port binding for QUIC. It can be + * used as both a client and a server. + * @since v23.8.0 + */ + class QuicEndpoint implements AsyncDisposable { + constructor(options?: EndpointOptions); + /** + * The local UDP socket address to which the endpoint is bound, if any. + * + * If the endpoint is not currently bound then the value will be `undefined`. Read only. + * @since v23.8.0 + */ + readonly address: SocketAddress | undefined; + /** + * When `endpoint.busy` is set to true, the endpoint will temporarily reject + * new sessions from being created. Read/write. + * + * ```js + * // Mark the endpoint busy. New sessions will be prevented. + * endpoint.busy = true; + * + * // Mark the endpoint free. New session will be allowed. + * endpoint.busy = false; + * ``` + * + * The `busy` property is useful when the endpoint is under heavy load and needs to + * temporarily reject new sessions while it catches up. + * @since v23.8.0 + */ + busy: boolean; + /** + * Gracefully close the endpoint. The endpoint will close and destroy itself when + * all currently open sessions close. Once called, new sessions will be rejected. + * + * Returns a promise that is fulfilled when the endpoint is destroyed. + * @since v23.8.0 + */ + close(): Promise<void>; + /** + * A promise that is fulfilled when the endpoint is destroyed. This will be the same promise that is + * returned by the `endpoint.close()` function. Read only. + * @since v23.8.0 + */ + readonly closed: Promise<void>; + /** + * True if `endpoint.close()` has been called and closing the endpoint has not yet completed. + * Read only. + * @since v23.8.0 + */ + readonly closing: boolean; + /** + * Forcefully closes the endpoint by forcing all open sessions to be immediately + * closed. + * @since v23.8.0 + */ + destroy(error?: any): void; + /** + * True if `endpoint.destroy()` has been called. Read only. + * @since v23.8.0 + */ + readonly destroyed: boolean; + /** + * The statistics collected for an active session. Read only. + * @since v23.8.0 + */ + readonly stats: QuicEndpoint.Stats; + /** + * Calls `endpoint.close()` and returns a promise that fulfills when the + * endpoint has closed. + * @since v23.8.0 + */ + [Symbol.asyncDispose](): Promise<void>; + } + namespace QuicEndpoint { + /** + * A view of the collected statistics for an endpoint. + * @since v23.8.0 + */ + class Stats { + private constructor(); + /** + * A timestamp indicating the moment the endpoint was created. Read only. + * @since v23.8.0 + */ + readonly createdAt: bigint; + /** + * A timestamp indicating the moment the endpoint was destroyed. Read only. + * @since v23.8.0 + */ + readonly destroyedAt: bigint; + /** + * The total number of bytes received by this endpoint. Read only. + * @since v23.8.0 + */ + readonly bytesReceived: bigint; + /** + * The total number of bytes sent by this endpoint. Read only. + * @since v23.8.0 + */ + readonly bytesSent: bigint; + /** + * The total number of QUIC packets successfully received by this endpoint. Read only. + * @since v23.8.0 + */ + readonly packetsReceived: bigint; + /** + * The total number of QUIC packets successfully sent by this endpoint. Read only. + * @since v23.8.0 + */ + readonly packetsSent: bigint; + /** + * The total number of peer-initiated sessions received by this endpoint. Read only. + * @since v23.8.0 + */ + readonly serverSessions: bigint; + /** + * The total number of sessions initiated by this endpoint. Read only. + * @since v23.8.0 + */ + readonly clientSessions: bigint; + /** + * The total number of times an initial packet was rejected due to the + * endpoint being marked busy. Read only. + * @since v23.8.0 + */ + readonly serverBusyCount: bigint; + /** + * The total number of QUIC retry attempts on this endpoint. Read only. + * @since v23.8.0 + */ + readonly retryCount: bigint; + /** + * The total number sessions rejected due to QUIC version mismatch. Read only. + * @since v23.8.0 + */ + readonly versionNegotiationCount: bigint; + /** + * The total number of stateless resets handled by this endpoint. Read only. + * @since v23.8.0 + */ + readonly statelessResetCount: bigint; + /** + * The total number of sessions that were closed before handshake completed. Read only. + * @since v23.8.0 + */ + readonly immediateCloseCount: bigint; + } + } + interface CreateStreamOptions { + body?: ArrayBuffer | NodeJS.ArrayBufferView | Blob | undefined; + sendOrder?: number | undefined; + } + interface SessionPath { + local: SocketAddress; + remote: SocketAddress; + } + /** + * A `QuicSession` represents the local side of a QUIC connection. + * @since v23.8.0 + */ + class QuicSession implements AsyncDisposable { + private constructor(); + /** + * Initiate a graceful close of the session. Existing streams will be allowed + * to complete but no new streams will be opened. Once all streams have closed, + * the session will be destroyed. The returned promise will be fulfilled once + * the session has been destroyed. + * @since v23.8.0 + */ + close(): Promise<void>; + /** + * A promise that is fulfilled once the session is destroyed. + * @since v23.8.0 + */ + readonly closed: Promise<void>; + /** + * Immediately destroy the session. All streams will be destroys and the + * session will be closed. + * @since v23.8.0 + */ + destroy(error?: any): void; + /** + * True if `session.destroy()` has been called. Read only. + * @since v23.8.0 + */ + readonly destroyed: boolean; + /** + * The endpoint that created this session. Read only. + * @since v23.8.0 + */ + readonly endpoint: QuicEndpoint; + /** + * The callback to invoke when a new stream is initiated by a remote peer. Read/write. + * @since v23.8.0 + */ + onstream: OnStreamCallback | undefined; + /** + * The callback to invoke when a new datagram is received from a remote peer. Read/write. + * @since v23.8.0 + */ + ondatagram: OnDatagramCallback | undefined; + /** + * The callback to invoke when the status of a datagram is updated. Read/write. + * @since v23.8.0 + */ + ondatagramstatus: OnDatagramStatusCallback | undefined; + /** + * The callback to invoke when the path validation is updated. Read/write. + * @since v23.8.0 + */ + onpathvalidation: OnPathValidationCallback | undefined; + /** + * The callback to invoke when a new session ticket is received. Read/write. + * @since v23.8.0 + */ + onsessionticket: OnSessionTicketCallback | undefined; + /** + * The callback to invoke when a version negotiation is initiated. Read/write. + * @since v23.8.0 + */ + onversionnegotiation: OnVersionNegotiationCallback | undefined; + /** + * The callback to invoke when the TLS handshake is completed. Read/write. + * @since v23.8.0 + */ + onhandshake: OnHandshakeCallback | undefined; + /** + * Open a new bidirectional stream. If the `body` option is not specified, + * the outgoing stream will be half-closed. + * @since v23.8.0 + */ + createBidirectionalStream(options?: CreateStreamOptions): Promise<QuicStream>; + /** + * Open a new unidirectional stream. If the `body` option is not specified, + * the outgoing stream will be closed. + * @since v23.8.0 + */ + createUnidirectionalStream(options?: CreateStreamOptions): Promise<QuicStream>; + /** + * The local and remote socket addresses associated with the session. Read only. + * @since v23.8.0 + */ + path: SessionPath | undefined; + /** + * Sends an unreliable datagram to the remote peer, returning the datagram ID. + * If the datagram payload is specified as an `ArrayBufferView`, then ownership of + * that view will be transfered to the underlying stream. + * @since v23.8.0 + */ + sendDatagram(datagram: string | NodeJS.ArrayBufferView): bigint; + /** + * Return the current statistics for the session. Read only. + * @since v23.8.0 + */ + readonly stats: QuicSession.Stats; + /** + * Initiate a key update for the session. + * @since v23.8.0 + */ + updateKey(): void; + /** + * Calls `session.close()` and returns a promise that fulfills when the + * session has closed. + * @since v23.8.0 + */ + [Symbol.asyncDispose](): Promise<void>; + } + namespace QuicSession { + /** + * @since v23.8.0 + */ + class Stats { + private constructor(); + /** + * @since v23.8.0 + */ + readonly createdAt: bigint; + /** + * @since v23.8.0 + */ + readonly closingAt: bigint; + /** + * @since v23.8.0 + */ + readonly handshakeCompletedAt: bigint; + /** + * @since v23.8.0 + */ + readonly handshakeConfirmedAt: bigint; + /** + * @since v23.8.0 + */ + readonly bytesReceived: bigint; + /** + * @since v23.8.0 + */ + readonly bytesSent: bigint; + /** + * @since v23.8.0 + */ + readonly bidiInStreamCount: bigint; + /** + * @since v23.8.0 + */ + readonly bidiOutStreamCount: bigint; + /** + * @since v23.8.0 + */ + readonly uniInStreamCount: bigint; + /** + * @since v23.8.0 + */ + readonly uniOutStreamCount: bigint; + /** + * @since v23.8.0 + */ + readonly maxBytesInFlights: bigint; + /** + * @since v23.8.0 + */ + readonly bytesInFlight: bigint; + /** + * @since v23.8.0 + */ + readonly blockCount: bigint; + /** + * @since v23.8.0 + */ + readonly cwnd: bigint; + /** + * @since v23.8.0 + */ + readonly latestRtt: bigint; + /** + * @since v23.8.0 + */ + readonly minRtt: bigint; + /** + * @since v23.8.0 + */ + readonly rttVar: bigint; + /** + * @since v23.8.0 + */ + readonly smoothedRtt: bigint; + /** + * @since v23.8.0 + */ + readonly ssthresh: bigint; + /** + * @since v23.8.0 + */ + readonly datagramsReceived: bigint; + /** + * @since v23.8.0 + */ + readonly datagramsSent: bigint; + /** + * @since v23.8.0 + */ + readonly datagramsAcknowledged: bigint; + /** + * @since v23.8.0 + */ + readonly datagramsLost: bigint; + } + } + /** + * @since v23.8.0 + */ + class QuicStream { + private constructor(); + /** + * A promise that is fulfilled when the stream is fully closed. + * @since v23.8.0 + */ + readonly closed: Promise<void>; + /** + * Immediately and abruptly destroys the stream. + * @since v23.8.0 + */ + destroy(error?: any): void; + /** + * True if `stream.destroy()` has been called. + * @since v23.8.0 + */ + readonly destroyed: boolean; + /** + * The directionality of the stream. Read only. + * @since v23.8.0 + */ + readonly direction: "bidi" | "uni"; + /** + * The stream ID. Read only. + * @since v23.8.0 + */ + readonly id: bigint; + /** + * The callback to invoke when the stream is blocked. Read/write. + * @since v23.8.0 + */ + onblocked: OnBlockedCallback | undefined; + /** + * The callback to invoke when the stream is reset. Read/write. + * @since v23.8.0 + */ + onreset: OnStreamErrorCallback | undefined; + /** + * @since v23.8.0 + */ + readonly readable: ReadableStream<Uint8Array>; + /** + * The session that created this stream. Read only. + * @since v23.8.0 + */ + readonly session: QuicSession; + /** + * The current statistics for the stream. Read only. + * @since v23.8.0 + */ + readonly stats: QuicStream.Stats; + } + namespace QuicStream { + /** + * @since v23.8.0 + */ + class Stats { + private constructor(); + /** + * @since v23.8.0 + */ + readonly ackedAt: bigint; + /** + * @since v23.8.0 + */ + readonly bytesReceived: bigint; + /** + * @since v23.8.0 + */ + readonly bytesSent: bigint; + /** + * @since v23.8.0 + */ + readonly createdAt: bigint; + /** + * @since v23.8.0 + */ + readonly destroyedAt: bigint; + /** + * @since v23.8.0 + */ + readonly finalSize: bigint; + /** + * @since v23.8.0 + */ + readonly isConnected: bigint; + /** + * @since v23.8.0 + */ + readonly maxOffset: bigint; + /** + * @since v23.8.0 + */ + readonly maxOffsetAcknowledged: bigint; + /** + * @since v23.8.0 + */ + readonly maxOffsetReceived: bigint; + /** + * @since v23.8.0 + */ + readonly openedAt: bigint; + /** + * @since v23.8.0 + */ + readonly receivedAt: bigint; + } + } + namespace constants { + enum cc { + RENO = "reno", + CUBIC = "cubic", + BBR = "bbr", + } + const DEFAULT_CIPHERS: string; + const DEFAULT_GROUPS: string; + } +} diff --git a/server/node_modules/@types/node/readline.d.ts b/server/node_modules/@types/node/readline.d.ts new file mode 100644 index 0000000..a47e185 --- /dev/null +++ b/server/node_modules/@types/node/readline.d.ts @@ -0,0 +1,541 @@ +/** + * The `node:readline` module provides an interface for reading data from a [Readable](https://nodejs.org/docs/latest-v25.x/api/stream.html#readable-streams) stream + * (such as [`process.stdin`](https://nodejs.org/docs/latest-v25.x/api/process.html#processstdin)) one line at a time. + * + * To use the promise-based APIs: + * + * ```js + * import * as readline from 'node:readline/promises'; + * ``` + * + * To use the callback and sync APIs: + * + * ```js + * import * as readline from 'node:readline'; + * ``` + * + * The following simple example illustrates the basic use of the `node:readline` module. + * + * ```js + * import * as readline from 'node:readline/promises'; + * import { stdin as input, stdout as output } from 'node:process'; + * + * const rl = readline.createInterface({ input, output }); + * + * const answer = await rl.question('What do you think of Node.js? '); + * + * console.log(`Thank you for your valuable feedback: ${answer}`); + * + * rl.close(); + * ``` + * + * Once this code is invoked, the Node.js application will not terminate until the `readline.Interface` is closed because the interface waits for data to be + * received on the `input` stream. + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/readline.js) + */ +declare module "node:readline" { + import { Abortable, EventEmitter, InternalEventEmitter } from "node:events"; + interface Key { + sequence?: string | undefined; + name?: string | undefined; + ctrl?: boolean | undefined; + meta?: boolean | undefined; + shift?: boolean | undefined; + } + interface InterfaceEventMap { + "close": []; + "history": [history: string[]]; + "line": [input: string]; + "pause": []; + "resume": []; + "SIGCONT": []; + "SIGINT": []; + "SIGTSTP": []; + } + /** + * Instances of the `readline.Interface` class are constructed using the `readline.createInterface()` method. Every instance is associated with a + * single `input` [Readable](https://nodejs.org/docs/latest-v25.x/api/stream.html#readable-streams) stream and a single `output` [Writable](https://nodejs.org/docs/latest-v25.x/api/stream.html#writable-streams) stream. + * The `output` stream is used to print prompts for user input that arrives on, + * and is read from, the `input` stream. + * @since v0.1.104 + */ + class Interface implements EventEmitter, Disposable { + /** + * NOTE: According to the documentation: + * + * > Instances of the `readline.Interface` class are constructed using the + * > `readline.createInterface()` method. + * + * @see https://nodejs.org/dist/latest-v25.x/docs/api/readline.html#class-interfaceconstructor + */ + protected constructor( + input: NodeJS.ReadableStream, + output?: NodeJS.WritableStream, + completer?: Completer | AsyncCompleter, + terminal?: boolean, + ); + /** + * NOTE: According to the documentation: + * + * > Instances of the `readline.Interface` class are constructed using the + * > `readline.createInterface()` method. + * + * @see https://nodejs.org/dist/latest-v25.x/docs/api/readline.html#class-interfaceconstructor + */ + protected constructor(options: ReadLineOptions); + readonly terminal: boolean; + /** + * The current input data being processed by node. + * + * This can be used when collecting input from a TTY stream to retrieve the + * current value that has been processed thus far, prior to the `line` event + * being emitted. Once the `line` event has been emitted, this property will + * be an empty string. + * + * Be aware that modifying the value during the instance runtime may have + * unintended consequences if `rl.cursor` is not also controlled. + * + * **If not using a TTY stream for input, use the `'line'` event.** + * + * One possible use case would be as follows: + * + * ```js + * const values = ['lorem ipsum', 'dolor sit amet']; + * const rl = readline.createInterface(process.stdin); + * const showResults = debounce(() => { + * console.log( + * '\n', + * values.filter((val) => val.startsWith(rl.line)).join(' '), + * ); + * }, 300); + * process.stdin.on('keypress', (c, k) => { + * showResults(); + * }); + * ``` + * @since v0.1.98 + */ + readonly line: string; + /** + * The cursor position relative to `rl.line`. + * + * This will track where the current cursor lands in the input string, when + * reading input from a TTY stream. The position of cursor determines the + * portion of the input string that will be modified as input is processed, + * as well as the column where the terminal caret will be rendered. + * @since v0.1.98 + */ + readonly cursor: number; + /** + * The `rl.getPrompt()` method returns the current prompt used by `rl.prompt()`. + * @since v15.3.0, v14.17.0 + * @return the current prompt string + */ + getPrompt(): string; + /** + * The `rl.setPrompt()` method sets the prompt that will be written to `output` whenever `rl.prompt()` is called. + * @since v0.1.98 + */ + setPrompt(prompt: string): void; + /** + * The `rl.prompt()` method writes the `Interface` instances configured`prompt` to a new line in `output` in order to provide a user with a new + * location at which to provide input. + * + * When called, `rl.prompt()` will resume the `input` stream if it has been + * paused. + * + * If the `Interface` was created with `output` set to `null` or `undefined` the prompt is not written. + * @since v0.1.98 + * @param preserveCursor If `true`, prevents the cursor placement from being reset to `0`. + */ + prompt(preserveCursor?: boolean): void; + /** + * The `rl.question()` method displays the `query` by writing it to the `output`, + * waits for user input to be provided on `input`, then invokes the `callback` function passing the provided input as the first argument. + * + * When called, `rl.question()` will resume the `input` stream if it has been + * paused. + * + * If the `Interface` was created with `output` set to `null` or `undefined` the `query` is not written. + * + * The `callback` function passed to `rl.question()` does not follow the typical + * pattern of accepting an `Error` object or `null` as the first argument. + * The `callback` is called with the provided answer as the only argument. + * + * An error will be thrown if calling `rl.question()` after `rl.close()`. + * + * Example usage: + * + * ```js + * rl.question('What is your favorite food? ', (answer) => { + * console.log(`Oh, so your favorite food is ${answer}`); + * }); + * ``` + * + * Using an `AbortController` to cancel a question. + * + * ```js + * const ac = new AbortController(); + * const signal = ac.signal; + * + * rl.question('What is your favorite food? ', { signal }, (answer) => { + * console.log(`Oh, so your favorite food is ${answer}`); + * }); + * + * signal.addEventListener('abort', () => { + * console.log('The food question timed out'); + * }, { once: true }); + * + * setTimeout(() => ac.abort(), 10000); + * ``` + * @since v0.3.3 + * @param query A statement or query to write to `output`, prepended to the prompt. + * @param callback A callback function that is invoked with the user's input in response to the `query`. + */ + question(query: string, callback: (answer: string) => void): void; + question(query: string, options: Abortable, callback: (answer: string) => void): void; + /** + * The `rl.pause()` method pauses the `input` stream, allowing it to be resumed + * later if necessary. + * + * Calling `rl.pause()` does not immediately pause other events (including `'line'`) from being emitted by the `Interface` instance. + * @since v0.3.4 + */ + pause(): this; + /** + * The `rl.resume()` method resumes the `input` stream if it has been paused. + * @since v0.3.4 + */ + resume(): this; + /** + * The `rl.close()` method closes the `Interface` instance and + * relinquishes control over the `input` and `output` streams. When called, + * the `'close'` event will be emitted. + * + * Calling `rl.close()` does not immediately stop other events (including `'line'`) + * from being emitted by the `Interface` instance. + * @since v0.1.98 + */ + close(): void; + /** + * Alias for `rl.close()`. + * @since v22.15.0 + */ + [Symbol.dispose](): void; + /** + * The `rl.write()` method will write either `data` or a key sequence identified + * by `key` to the `output`. The `key` argument is supported only if `output` is + * a `TTY` text terminal. See `TTY keybindings` for a list of key + * combinations. + * + * If `key` is specified, `data` is ignored. + * + * When called, `rl.write()` will resume the `input` stream if it has been + * paused. + * + * If the `Interface` was created with `output` set to `null` or `undefined` the `data` and `key` are not written. + * + * ```js + * rl.write('Delete this!'); + * // Simulate Ctrl+U to delete the line written previously + * rl.write(null, { ctrl: true, name: 'u' }); + * ``` + * + * The `rl.write()` method will write the data to the `readline` `Interface`'s `input` _as if it were provided by the user_. + * @since v0.1.98 + */ + write(data: string | Buffer, key?: Key): void; + write(data: undefined | null | string | Buffer, key: Key): void; + /** + * Returns the real position of the cursor in relation to the input + * prompt + string. Long input (wrapping) strings, as well as multiple + * line prompts are included in the calculations. + * @since v13.5.0, v12.16.0 + */ + getCursorPos(): CursorPos; + [Symbol.asyncIterator](): NodeJS.AsyncIterator<string>; + } + interface Interface extends InternalEventEmitter<InterfaceEventMap> {} + type ReadLine = Interface; // type forwarded for backwards compatibility + type Completer = (line: string) => CompleterResult; + type AsyncCompleter = ( + line: string, + callback: (err?: null | Error, result?: CompleterResult) => void, + ) => void; + type CompleterResult = [string[], string]; + interface ReadLineOptions { + /** + * The [`Readable`](https://nodejs.org/docs/latest-v25.x/api/stream.html#readable-streams) stream to listen to + */ + input: NodeJS.ReadableStream; + /** + * The [`Writable`](https://nodejs.org/docs/latest-v25.x/api/stream.html#writable-streams) stream to write readline data to. + */ + output?: NodeJS.WritableStream | undefined; + /** + * An optional function used for Tab autocompletion. + */ + completer?: Completer | AsyncCompleter | undefined; + /** + * `true` if the `input` and `output` streams should be treated like a TTY, + * and have ANSI/VT100 escape codes written to it. + * Default: checking `isTTY` on the `output` stream upon instantiation. + */ + terminal?: boolean | undefined; + /** + * Initial list of history lines. + * This option makes sense only if `terminal` is set to `true` by the user or by an internal `output` check, + * otherwise the history caching mechanism is not initialized at all. + * @default [] + */ + history?: string[] | undefined; + /** + * Maximum number of history lines retained. + * To disable the history set this value to `0`. + * This option makes sense only if `terminal` is set to `true` by the user or by an internal `output` check, + * otherwise the history caching mechanism is not initialized at all. + * @default 30 + */ + historySize?: number | undefined; + /** + * If `true`, when a new input line added to the history list duplicates an older one, + * this removes the older line from the list. + * @default false + */ + removeHistoryDuplicates?: boolean | undefined; + /** + * The prompt string to use. + * @default "> " + */ + prompt?: string | undefined; + /** + * If the delay between `\r` and `\n` exceeds `crlfDelay` milliseconds, + * both `\r` and `\n` will be treated as separate end-of-line input. + * `crlfDelay` will be coerced to a number no less than `100`. + * It can be set to `Infinity`, in which case + * `\r` followed by `\n` will always be considered a single newline + * (which may be reasonable for [reading files](https://nodejs.org/docs/latest-v25.x/api/readline.html#example-read-file-stream-line-by-line) with `\r\n` line delimiter). + * @default 100 + */ + crlfDelay?: number | undefined; + /** + * The duration `readline` will wait for a character + * (when reading an ambiguous key sequence in milliseconds + * one that can both form a complete key sequence using the input read so far + * and can take additional input to complete a longer key sequence). + * @default 500 + */ + escapeCodeTimeout?: number | undefined; + /** + * The number of spaces a tab is equal to (minimum 1). + * @default 8 + */ + tabSize?: number | undefined; + /** + * Allows closing the interface using an AbortSignal. + * Aborting the signal will internally call `close` on the interface. + */ + signal?: AbortSignal | undefined; + } + /** + * The `readline.createInterface()` method creates a new `readline.Interface` instance. + * + * ```js + * import readline from 'node:readline'; + * const rl = readline.createInterface({ + * input: process.stdin, + * output: process.stdout, + * }); + * ``` + * + * Once the `readline.Interface` instance is created, the most common case is to + * listen for the `'line'` event: + * + * ```js + * rl.on('line', (line) => { + * console.log(`Received: ${line}`); + * }); + * ``` + * + * If `terminal` is `true` for this instance then the `output` stream will get + * the best compatibility if it defines an `output.columns` property and emits + * a `'resize'` event on the `output` if or when the columns ever change + * (`process.stdout` does this automatically when it is a TTY). + * + * When creating a `readline.Interface` using `stdin` as input, the program + * will not terminate until it receives an [EOF character](https://en.wikipedia.org/wiki/End-of-file#EOF_character). To exit without + * waiting for user input, call `process.stdin.unref()`. + * @since v0.1.98 + */ + function createInterface( + input: NodeJS.ReadableStream, + output?: NodeJS.WritableStream, + completer?: Completer | AsyncCompleter, + terminal?: boolean, + ): Interface; + function createInterface(options: ReadLineOptions): Interface; + /** + * The `readline.emitKeypressEvents()` method causes the given `Readable` stream to begin emitting `'keypress'` events corresponding to received input. + * + * Optionally, `interface` specifies a `readline.Interface` instance for which + * autocompletion is disabled when copy-pasted input is detected. + * + * If the `stream` is a `TTY`, then it must be in raw mode. + * + * This is automatically called by any readline instance on its `input` if the `input` is a terminal. Closing the `readline` instance does not stop + * the `input` from emitting `'keypress'` events. + * + * ```js + * readline.emitKeypressEvents(process.stdin); + * if (process.stdin.isTTY) + * process.stdin.setRawMode(true); + * ``` + * + * ## Example: Tiny CLI + * + * The following example illustrates the use of `readline.Interface` class to + * implement a small command-line interface: + * + * ```js + * import readline from 'node:readline'; + * const rl = readline.createInterface({ + * input: process.stdin, + * output: process.stdout, + * prompt: 'OHAI> ', + * }); + * + * rl.prompt(); + * + * rl.on('line', (line) => { + * switch (line.trim()) { + * case 'hello': + * console.log('world!'); + * break; + * default: + * console.log(`Say what? I might have heard '${line.trim()}'`); + * break; + * } + * rl.prompt(); + * }).on('close', () => { + * console.log('Have a great day!'); + * process.exit(0); + * }); + * ``` + * + * ## Example: Read file stream line-by-Line + * + * A common use case for `readline` is to consume an input file one line at a + * time. The easiest way to do so is leveraging the `fs.ReadStream` API as + * well as a `for await...of` loop: + * + * ```js + * import fs from 'node:fs'; + * import readline from 'node:readline'; + * + * async function processLineByLine() { + * const fileStream = fs.createReadStream('input.txt'); + * + * const rl = readline.createInterface({ + * input: fileStream, + * crlfDelay: Infinity, + * }); + * // Note: we use the crlfDelay option to recognize all instances of CR LF + * // ('\r\n') in input.txt as a single line break. + * + * for await (const line of rl) { + * // Each line in input.txt will be successively available here as `line`. + * console.log(`Line from file: ${line}`); + * } + * } + * + * processLineByLine(); + * ``` + * + * Alternatively, one could use the `'line'` event: + * + * ```js + * import fs from 'node:fs'; + * import readline from 'node:readline'; + * + * const rl = readline.createInterface({ + * input: fs.createReadStream('sample.txt'), + * crlfDelay: Infinity, + * }); + * + * rl.on('line', (line) => { + * console.log(`Line from file: ${line}`); + * }); + * ``` + * + * Currently, `for await...of` loop can be a bit slower. If `async` / `await` flow and speed are both essential, a mixed approach can be applied: + * + * ```js + * import { once } from 'node:events'; + * import { createReadStream } from 'node:fs'; + * import { createInterface } from 'node:readline'; + * + * (async function processLineByLine() { + * try { + * const rl = createInterface({ + * input: createReadStream('big-file.txt'), + * crlfDelay: Infinity, + * }); + * + * rl.on('line', (line) => { + * // Process the line. + * }); + * + * await once(rl, 'close'); + * + * console.log('File processed.'); + * } catch (err) { + * console.error(err); + * } + * })(); + * ``` + * @since v0.7.7 + */ + function emitKeypressEvents(stream: NodeJS.ReadableStream, readlineInterface?: Interface): void; + type Direction = -1 | 0 | 1; + interface CursorPos { + rows: number; + cols: number; + } + /** + * The `readline.clearLine()` method clears current line of given [TTY](https://nodejs.org/docs/latest-v25.x/api/tty.html) stream + * in a specified direction identified by `dir`. + * @since v0.7.7 + * @param callback Invoked once the operation completes. + * @return `false` if `stream` wishes for the calling code to wait for the `'drain'` event to be emitted before continuing to write additional data; otherwise `true`. + */ + function clearLine(stream: NodeJS.WritableStream, dir: Direction, callback?: () => void): boolean; + /** + * The `readline.clearScreenDown()` method clears the given [TTY](https://nodejs.org/docs/latest-v25.x/api/tty.html) stream from + * the current position of the cursor down. + * @since v0.7.7 + * @param callback Invoked once the operation completes. + * @return `false` if `stream` wishes for the calling code to wait for the `'drain'` event to be emitted before continuing to write additional data; otherwise `true`. + */ + function clearScreenDown(stream: NodeJS.WritableStream, callback?: () => void): boolean; + /** + * The `readline.cursorTo()` method moves cursor to the specified position in a + * given [TTY](https://nodejs.org/docs/latest-v25.x/api/tty.html) `stream`. + * @since v0.7.7 + * @param callback Invoked once the operation completes. + * @return `false` if `stream` wishes for the calling code to wait for the `'drain'` event to be emitted before continuing to write additional data; otherwise `true`. + */ + function cursorTo(stream: NodeJS.WritableStream, x: number, y?: number, callback?: () => void): boolean; + /** + * The `readline.moveCursor()` method moves the cursor _relative_ to its current + * position in a given [TTY](https://nodejs.org/docs/latest-v25.x/api/tty.html) `stream`. + * @since v0.7.7 + * @param callback Invoked once the operation completes. + * @return `false` if `stream` wishes for the calling code to wait for the `'drain'` event to be emitted before continuing to write additional data; otherwise `true`. + */ + function moveCursor(stream: NodeJS.WritableStream, dx: number, dy: number, callback?: () => void): boolean; +} +declare module "node:readline" { + export * as promises from "node:readline/promises"; +} +declare module "readline" { + export * from "node:readline"; +} diff --git a/server/node_modules/@types/node/readline/promises.d.ts b/server/node_modules/@types/node/readline/promises.d.ts new file mode 100644 index 0000000..f449e1b --- /dev/null +++ b/server/node_modules/@types/node/readline/promises.d.ts @@ -0,0 +1,161 @@ +/** + * @since v17.0.0 + */ +declare module "node:readline/promises" { + import { Abortable } from "node:events"; + import { + CompleterResult, + Direction, + Interface as _Interface, + ReadLineOptions as _ReadLineOptions, + } from "node:readline"; + /** + * Instances of the `readlinePromises.Interface` class are constructed using the `readlinePromises.createInterface()` method. Every instance is associated with a + * single `input` `Readable` stream and a single `output` `Writable` stream. + * The `output` stream is used to print prompts for user input that arrives on, + * and is read from, the `input` stream. + * @since v17.0.0 + */ + class Interface extends _Interface { + /** + * The `rl.question()` method displays the `query` by writing it to the `output`, + * waits for user input to be provided on `input`, then invokes the `callback` function passing the provided input as the first argument. + * + * When called, `rl.question()` will resume the `input` stream if it has been + * paused. + * + * If the `Interface` was created with `output` set to `null` or `undefined` the `query` is not written. + * + * If the question is called after `rl.close()`, it returns a rejected promise. + * + * Example usage: + * + * ```js + * const answer = await rl.question('What is your favorite food? '); + * console.log(`Oh, so your favorite food is ${answer}`); + * ``` + * + * Using an `AbortSignal` to cancel a question. + * + * ```js + * const signal = AbortSignal.timeout(10_000); + * + * signal.addEventListener('abort', () => { + * console.log('The food question timed out'); + * }, { once: true }); + * + * const answer = await rl.question('What is your favorite food? ', { signal }); + * console.log(`Oh, so your favorite food is ${answer}`); + * ``` + * @since v17.0.0 + * @param query A statement or query to write to `output`, prepended to the prompt. + * @return A promise that is fulfilled with the user's input in response to the `query`. + */ + question(query: string): Promise<string>; + question(query: string, options: Abortable): Promise<string>; + } + /** + * @since v17.0.0 + */ + class Readline { + /** + * @param stream A TTY stream. + */ + constructor( + stream: NodeJS.WritableStream, + options?: { + autoCommit?: boolean | undefined; + }, + ); + /** + * The `rl.clearLine()` method adds to the internal list of pending action an + * action that clears current line of the associated `stream` in a specified + * direction identified by `dir`. + * Call `rl.commit()` to see the effect of this method, unless `autoCommit: true` was passed to the constructor. + * @since v17.0.0 + * @return this + */ + clearLine(dir: Direction): this; + /** + * The `rl.clearScreenDown()` method adds to the internal list of pending action an + * action that clears the associated stream from the current position of the + * cursor down. + * Call `rl.commit()` to see the effect of this method, unless `autoCommit: true` was passed to the constructor. + * @since v17.0.0 + * @return this + */ + clearScreenDown(): this; + /** + * The `rl.commit()` method sends all the pending actions to the associated `stream` and clears the internal list of pending actions. + * @since v17.0.0 + */ + commit(): Promise<void>; + /** + * The `rl.cursorTo()` method adds to the internal list of pending action an action + * that moves cursor to the specified position in the associated `stream`. + * Call `rl.commit()` to see the effect of this method, unless `autoCommit: true` was passed to the constructor. + * @since v17.0.0 + * @return this + */ + cursorTo(x: number, y?: number): this; + /** + * The `rl.moveCursor()` method adds to the internal list of pending action an + * action that moves the cursor _relative_ to its current position in the + * associated `stream`. + * Call `rl.commit()` to see the effect of this method, unless `autoCommit: true` was passed to the constructor. + * @since v17.0.0 + * @return this + */ + moveCursor(dx: number, dy: number): this; + /** + * The `rl.rollback` methods clears the internal list of pending actions without + * sending it to the associated `stream`. + * @since v17.0.0 + * @return this + */ + rollback(): this; + } + type Completer = (line: string) => CompleterResult | Promise<CompleterResult>; + interface ReadLineOptions extends Omit<_ReadLineOptions, "completer"> { + /** + * An optional function used for Tab autocompletion. + */ + completer?: Completer | undefined; + } + /** + * The `readlinePromises.createInterface()` method creates a new `readlinePromises.Interface` instance. + * + * ```js + * import readlinePromises from 'node:readline/promises'; + * const rl = readlinePromises.createInterface({ + * input: process.stdin, + * output: process.stdout, + * }); + * ``` + * + * Once the `readlinePromises.Interface` instance is created, the most common case + * is to listen for the `'line'` event: + * + * ```js + * rl.on('line', (line) => { + * console.log(`Received: ${line}`); + * }); + * ``` + * + * If `terminal` is `true` for this instance then the `output` stream will get + * the best compatibility if it defines an `output.columns` property and emits + * a `'resize'` event on the `output` if or when the columns ever change + * (`process.stdout` does this automatically when it is a TTY). + * @since v17.0.0 + */ + function createInterface( + input: NodeJS.ReadableStream, + output?: NodeJS.WritableStream, + completer?: Completer, + terminal?: boolean, + ): Interface; + function createInterface(options: ReadLineOptions): Interface; +} +declare module "readline/promises" { + export * from "node:readline/promises"; +} diff --git a/server/node_modules/@types/node/repl.d.ts b/server/node_modules/@types/node/repl.d.ts new file mode 100644 index 0000000..2d06294 --- /dev/null +++ b/server/node_modules/@types/node/repl.d.ts @@ -0,0 +1,415 @@ +/** + * The `node:repl` module provides a Read-Eval-Print-Loop (REPL) implementation + * that is available both as a standalone program or includible in other + * applications. It can be accessed using: + * + * ```js + * import repl from 'node:repl'; + * ``` + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/repl.js) + */ +declare module "node:repl" { + import { AsyncCompleter, Completer, Interface, InterfaceEventMap } from "node:readline"; + import { InspectOptions } from "node:util"; + import { Context } from "node:vm"; + interface ReplOptions { + /** + * The input prompt to display. + * @default "> " + */ + prompt?: string | undefined; + /** + * The `Readable` stream from which REPL input will be read. + * @default process.stdin + */ + input?: NodeJS.ReadableStream | undefined; + /** + * The `Writable` stream to which REPL output will be written. + * @default process.stdout + */ + output?: NodeJS.WritableStream | undefined; + /** + * If `true`, specifies that the output should be treated as a TTY terminal, and have + * ANSI/VT100 escape codes written to it. + * Default: checking the value of the `isTTY` property on the output stream upon + * instantiation. + */ + terminal?: boolean | undefined; + /** + * The function to be used when evaluating each given line of input. + * **Default:** an async wrapper for the JavaScript `eval()` function. An `eval` function can + * error with `repl.Recoverable` to indicate the input was incomplete and prompt for + * additional lines. See the [custom evaluation functions](https://nodejs.org/dist/latest-v25.x/docs/api/repl.html#custom-evaluation-functions) + * section for more details. + */ + eval?: REPLEval | undefined; + /** + * Defines if the repl prints output previews or not. + * @default `true` Always `false` in case `terminal` is falsy. + */ + preview?: boolean | undefined; + /** + * If `true`, specifies that the default `writer` function should include ANSI color + * styling to REPL output. If a custom `writer` function is provided then this has no + * effect. + * @default the REPL instance's `terminal` value + */ + useColors?: boolean | undefined; + /** + * If `true`, specifies that the default evaluation function will use the JavaScript + * `global` as the context as opposed to creating a new separate context for the REPL + * instance. The node CLI REPL sets this value to `true`. + * @default false + */ + useGlobal?: boolean | undefined; + /** + * If `true`, specifies that the default writer will not output the return value of a + * command if it evaluates to `undefined`. + * @default false + */ + ignoreUndefined?: boolean | undefined; + /** + * The function to invoke to format the output of each command before writing to `output`. + * @default a wrapper for `util.inspect` + * + * @see https://nodejs.org/dist/latest-v25.x/docs/api/repl.html#repl_customizing_repl_output + */ + writer?: REPLWriter | undefined; + /** + * An optional function used for custom Tab auto completion. + * + * @see https://nodejs.org/dist/latest-v25.x/docs/api/readline.html#readline_use_of_the_completer_function + */ + completer?: Completer | AsyncCompleter | undefined; + /** + * A flag that specifies whether the default evaluator executes all JavaScript commands in + * strict mode or default (sloppy) mode. + * Accepted values are: + * - `repl.REPL_MODE_SLOPPY` - evaluates expressions in sloppy mode. + * - `repl.REPL_MODE_STRICT` - evaluates expressions in strict mode. This is equivalent to + * prefacing every repl statement with `'use strict'`. + */ + replMode?: typeof REPL_MODE_SLOPPY | typeof REPL_MODE_STRICT | undefined; + /** + * Stop evaluating the current piece of code when `SIGINT` is received, i.e. `Ctrl+C` is + * pressed. This cannot be used together with a custom `eval` function. + * @default false + */ + breakEvalOnSigint?: boolean | undefined; + } + type REPLEval = ( + this: REPLServer, + evalCmd: string, + context: Context, + file: string, + cb: (err: Error | null, result: any) => void, + ) => void; + type REPLWriter = (this: REPLServer, obj: any) => string; + /** + * This is the default "writer" value, if none is passed in the REPL options, + * and it can be overridden by custom print functions. + */ + const writer: REPLWriter & { + options: InspectOptions; + }; + type REPLCommandAction = (this: REPLServer, text: string) => void; + interface REPLCommand { + /** + * Help text to be displayed when `.help` is entered. + */ + help?: string | undefined; + /** + * The function to execute, optionally accepting a single string argument. + */ + action: REPLCommandAction; + } + interface REPLServerSetupHistoryOptions { + filePath?: string | undefined; + size?: number | undefined; + removeHistoryDuplicates?: boolean | undefined; + onHistoryFileLoaded?: ((err: Error | null, repl: REPLServer) => void) | undefined; + } + interface REPLServerEventMap extends InterfaceEventMap { + "exit": []; + "reset": [context: Context]; + } + /** + * Instances of `repl.REPLServer` are created using the {@link start} method + * or directly using the JavaScript `new` keyword. + * + * ```js + * import repl from 'node:repl'; + * + * const options = { useColors: true }; + * + * const firstInstance = repl.start(options); + * const secondInstance = new repl.REPLServer(options); + * ``` + * @since v0.1.91 + */ + class REPLServer extends Interface { + /** + * NOTE: According to the documentation: + * + * > Instances of `repl.REPLServer` are created using the `repl.start()` method and + * > _should not_ be created directly using the JavaScript `new` keyword. + * + * `REPLServer` cannot be subclassed due to implementation specifics in NodeJS. + * + * @see https://nodejs.org/dist/latest-v25.x/docs/api/repl.html#repl_class_replserver + */ + private constructor(); + /** + * The `vm.Context` provided to the `eval` function to be used for JavaScript + * evaluation. + */ + readonly context: Context; + /** + * @deprecated since v14.3.0 - Use `input` instead. + */ + readonly inputStream: NodeJS.ReadableStream; + /** + * @deprecated since v14.3.0 - Use `output` instead. + */ + readonly outputStream: NodeJS.WritableStream; + /** + * The `Readable` stream from which REPL input will be read. + */ + readonly input: NodeJS.ReadableStream; + /** + * The `Writable` stream to which REPL output will be written. + */ + readonly output: NodeJS.WritableStream; + /** + * The commands registered via `replServer.defineCommand()`. + */ + readonly commands: NodeJS.ReadOnlyDict<REPLCommand>; + /** + * A value indicating whether the REPL is currently in "editor mode". + * + * @see https://nodejs.org/dist/latest-v25.x/docs/api/repl.html#repl_commands_and_special_keys + */ + readonly editorMode: boolean; + /** + * A value indicating whether the `_` variable has been assigned. + * + * @see https://nodejs.org/dist/latest-v25.x/docs/api/repl.html#repl_assignment_of_the_underscore_variable + */ + readonly underscoreAssigned: boolean; + /** + * The last evaluation result from the REPL (assigned to the `_` variable inside of the REPL). + * + * @see https://nodejs.org/dist/latest-v25.x/docs/api/repl.html#repl_assignment_of_the_underscore_variable + */ + readonly last: any; + /** + * A value indicating whether the `_error` variable has been assigned. + * + * @since v9.8.0 + * @see https://nodejs.org/dist/latest-v25.x/docs/api/repl.html#repl_assignment_of_the_underscore_variable + */ + readonly underscoreErrAssigned: boolean; + /** + * The last error raised inside the REPL (assigned to the `_error` variable inside of the REPL). + * + * @since v9.8.0 + * @see https://nodejs.org/dist/latest-v25.x/docs/api/repl.html#repl_assignment_of_the_underscore_variable + */ + readonly lastError: any; + /** + * Specified in the REPL options, this is the function to be used when evaluating each + * given line of input. If not specified in the REPL options, this is an async wrapper + * for the JavaScript `eval()` function. + */ + readonly eval: REPLEval; + /** + * Specified in the REPL options, this is a value indicating whether the default + * `writer` function should include ANSI color styling to REPL output. + */ + readonly useColors: boolean; + /** + * Specified in the REPL options, this is a value indicating whether the default `eval` + * function will use the JavaScript `global` as the context as opposed to creating a new + * separate context for the REPL instance. + */ + readonly useGlobal: boolean; + /** + * Specified in the REPL options, this is a value indicating whether the default `writer` + * function should output the result of a command if it evaluates to `undefined`. + */ + readonly ignoreUndefined: boolean; + /** + * Specified in the REPL options, this is the function to invoke to format the output of + * each command before writing to `outputStream`. If not specified in the REPL options, + * this will be a wrapper for `util.inspect`. + */ + readonly writer: REPLWriter; + /** + * Specified in the REPL options, this is the function to use for custom Tab auto-completion. + */ + readonly completer: Completer | AsyncCompleter; + /** + * Specified in the REPL options, this is a flag that specifies whether the default `eval` + * function should execute all JavaScript commands in strict mode or default (sloppy) mode. + * Possible values are: + * - `repl.REPL_MODE_SLOPPY` - evaluates expressions in sloppy mode. + * - `repl.REPL_MODE_STRICT` - evaluates expressions in strict mode. This is equivalent to + * prefacing every repl statement with `'use strict'`. + */ + readonly replMode: typeof REPL_MODE_SLOPPY | typeof REPL_MODE_STRICT; + /** + * The `replServer.defineCommand()` method is used to add new `.`\-prefixed commands + * to the REPL instance. Such commands are invoked by typing a `.` followed by the `keyword`. The `cmd` is either a `Function` or an `Object` with the following + * properties: + * + * The following example shows two new commands added to the REPL instance: + * + * ```js + * import repl from 'node:repl'; + * + * const replServer = repl.start({ prompt: '> ' }); + * replServer.defineCommand('sayhello', { + * help: 'Say hello', + * action(name) { + * this.clearBufferedCommand(); + * console.log(`Hello, ${name}!`); + * this.displayPrompt(); + * }, + * }); + * replServer.defineCommand('saybye', function saybye() { + * console.log('Goodbye!'); + * this.close(); + * }); + * ``` + * + * The new commands can then be used from within the REPL instance: + * + * ```console + * > .sayhello Node.js User + * Hello, Node.js User! + * > .saybye + * Goodbye! + * ``` + * @since v0.3.0 + * @param keyword The command keyword (_without_ a leading `.` character). + * @param cmd The function to invoke when the command is processed. + */ + defineCommand(keyword: string, cmd: REPLCommandAction | REPLCommand): void; + /** + * The `replServer.displayPrompt()` method readies the REPL instance for input + * from the user, printing the configured `prompt` to a new line in the `output` and resuming the `input` to accept new input. + * + * When multi-line input is being entered, a pipe `'|'` is printed rather than the + * 'prompt'. + * + * When `preserveCursor` is `true`, the cursor placement will not be reset to `0`. + * + * The `replServer.displayPrompt` method is primarily intended to be called from + * within the action function for commands registered using the `replServer.defineCommand()` method. + * @since v0.1.91 + */ + displayPrompt(preserveCursor?: boolean): void; + /** + * The `replServer.clearBufferedCommand()` method clears any command that has been + * buffered but not yet executed. This method is primarily intended to be + * called from within the action function for commands registered using the `replServer.defineCommand()` method. + * @since v9.0.0 + */ + clearBufferedCommand(): void; + /** + * Initializes a history log file for the REPL instance. When executing the + * Node.js binary and using the command-line REPL, a history file is initialized + * by default. However, this is not the case when creating a REPL + * programmatically. Use this method to initialize a history log file when working + * with REPL instances programmatically. + * @since v11.10.0 + * @param historyPath the path to the history file + * @param callback called when history writes are ready or upon error + */ + setupHistory(historyPath: string, callback: (err: Error | null, repl: this) => void): void; + setupHistory( + historyConfig?: REPLServerSetupHistoryOptions, + callback?: (err: Error | null, repl: this) => void, + ): void; + // #region InternalEventEmitter + addListener<E extends keyof REPLServerEventMap>( + eventName: E, + listener: (...args: REPLServerEventMap[E]) => void, + ): this; + addListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + emit<E extends keyof REPLServerEventMap>(eventName: E, ...args: REPLServerEventMap[E]): boolean; + emit(eventName: string | symbol, ...args: any[]): boolean; + listenerCount<E extends keyof REPLServerEventMap>( + eventName: E, + listener?: (...args: REPLServerEventMap[E]) => void, + ): number; + listenerCount(eventName: string | symbol, listener?: (...args: any[]) => void): number; + listeners<E extends keyof REPLServerEventMap>(eventName: E): ((...args: REPLServerEventMap[E]) => void)[]; + listeners(eventName: string | symbol): ((...args: any[]) => void)[]; + off<E extends keyof REPLServerEventMap>(eventName: E, listener: (...args: REPLServerEventMap[E]) => void): this; + off(eventName: string | symbol, listener: (...args: any[]) => void): this; + on<E extends keyof REPLServerEventMap>(eventName: E, listener: (...args: REPLServerEventMap[E]) => void): this; + on(eventName: string | symbol, listener: (...args: any[]) => void): this; + once<E extends keyof REPLServerEventMap>( + eventName: E, + listener: (...args: REPLServerEventMap[E]) => void, + ): this; + once(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependListener<E extends keyof REPLServerEventMap>( + eventName: E, + listener: (...args: REPLServerEventMap[E]) => void, + ): this; + prependListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependOnceListener<E extends keyof REPLServerEventMap>( + eventName: E, + listener: (...args: REPLServerEventMap[E]) => void, + ): this; + prependOnceListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + rawListeners<E extends keyof REPLServerEventMap>(eventName: E): ((...args: REPLServerEventMap[E]) => void)[]; + rawListeners(eventName: string | symbol): ((...args: any[]) => void)[]; + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + removeAllListeners<E extends keyof REPLServerEventMap>(eventName?: E): this; + removeAllListeners(eventName?: string | symbol): this; + removeListener<E extends keyof REPLServerEventMap>( + eventName: E, + listener: (...args: REPLServerEventMap[E]) => void, + ): this; + removeListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + // #endregion + } + /** + * A flag passed in the REPL options. Evaluates expressions in sloppy mode. + */ + const REPL_MODE_SLOPPY: unique symbol; + /** + * A flag passed in the REPL options. Evaluates expressions in strict mode. + * This is equivalent to prefacing every repl statement with `'use strict'`. + */ + const REPL_MODE_STRICT: unique symbol; + /** + * The `repl.start()` method creates and starts a {@link REPLServer} instance. + * + * If `options` is a string, then it specifies the input prompt: + * + * ```js + * import repl from 'node:repl'; + * + * // a Unix style prompt + * repl.start('$ '); + * ``` + * @since v0.1.91 + */ + function start(options?: string | ReplOptions): REPLServer; + /** + * Indicates a recoverable error that a `REPLServer` can use to support multi-line input. + * + * @see https://nodejs.org/dist/latest-v25.x/docs/api/repl.html#repl_recoverable_errors + */ + class Recoverable extends SyntaxError { + err: Error; + constructor(err: Error); + } +} +declare module "repl" { + export * from "node:repl"; +} diff --git a/server/node_modules/@types/node/sea.d.ts b/server/node_modules/@types/node/sea.d.ts new file mode 100644 index 0000000..2930c82 --- /dev/null +++ b/server/node_modules/@types/node/sea.d.ts @@ -0,0 +1,162 @@ +/** + * This feature allows the distribution of a Node.js application conveniently to a + * system that does not have Node.js installed. + * + * Node.js supports the creation of [single executable applications](https://github.com/nodejs/single-executable) by allowing + * the injection of a blob prepared by Node.js, which can contain a bundled script, + * into the `node` binary. During start up, the program checks if anything has been + * injected. If the blob is found, it executes the script in the blob. Otherwise + * Node.js operates as it normally does. + * + * The single executable application feature currently only supports running a + * single embedded script using the `CommonJS` module system. + * + * Users can create a single executable application from their bundled script + * with the `node` binary itself and any tool which can inject resources into the + * binary. + * + * Here are the steps for creating a single executable application using one such + * tool, [postject](https://github.com/nodejs/postject): + * + * 1. Create a JavaScript file: + * ```bash + * echo 'console.log(`Hello, ${process.argv[2]}!`);' > hello.js + * ``` + * 2. Create a configuration file building a blob that can be injected into the + * single executable application (see `Generating single executable preparation blobs` for details): + * ```bash + * echo '{ "main": "hello.js", "output": "sea-prep.blob" }' > sea-config.json + * ``` + * 3. Generate the blob to be injected: + * ```bash + * node --experimental-sea-config sea-config.json + * ``` + * 4. Create a copy of the `node` executable and name it according to your needs: + * * On systems other than Windows: + * ```bash + * cp $(command -v node) hello + * ``` + * * On Windows: + * ```text + * node -e "require('fs').copyFileSync(process.execPath, 'hello.exe')" + * ``` + * The `.exe` extension is necessary. + * 5. Remove the signature of the binary (macOS and Windows only): + * * On macOS: + * ```bash + * codesign --remove-signature hello + * ``` + * * On Windows (optional): + * [signtool](https://learn.microsoft.com/en-us/windows/win32/seccrypto/signtool) can be used from the installed [Windows SDK](https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/). + * If this step is + * skipped, ignore any signature-related warning from postject. + * ```powershell + * signtool remove /s hello.exe + * ``` + * 6. Inject the blob into the copied binary by running `postject` with + * the following options: + * * `hello` / `hello.exe` \- The name of the copy of the `node` executable + * created in step 4. + * * `NODE_SEA_BLOB` \- The name of the resource / note / section in the binary + * where the contents of the blob will be stored. + * * `sea-prep.blob` \- The name of the blob created in step 1. + * * `--sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2` \- The [fuse](https://www.electronjs.org/docs/latest/tutorial/fuses) used by the Node.js project to detect if a file has been + * injected. + * * `--macho-segment-name NODE_SEA` (only needed on macOS) - The name of the + * segment in the binary where the contents of the blob will be + * stored. + * To summarize, here is the required command for each platform: + * * On Linux: + * ```bash + * npx postject hello NODE_SEA_BLOB sea-prep.blob \ + * --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2 + * ``` + * * On Windows - PowerShell: + * ```powershell + * npx postject hello.exe NODE_SEA_BLOB sea-prep.blob ` + * --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2 + * ``` + * * On Windows - Command Prompt: + * ```text + * npx postject hello.exe NODE_SEA_BLOB sea-prep.blob ^ + * --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2 + * ``` + * * On macOS: + * ```bash + * npx postject hello NODE_SEA_BLOB sea-prep.blob \ + * --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2 \ + * --macho-segment-name NODE_SEA + * ``` + * 7. Sign the binary (macOS and Windows only): + * * On macOS: + * ```bash + * codesign --sign - hello + * ``` + * * On Windows (optional): + * A certificate needs to be present for this to work. However, the unsigned + * binary would still be runnable. + * ```powershell + * signtool sign /fd SHA256 hello.exe + * ``` + * 8. Run the binary: + * * On systems other than Windows + * ```console + * $ ./hello world + * Hello, world! + * ``` + * * On Windows + * ```console + * $ .\hello.exe world + * Hello, world! + * ``` + * @since v19.7.0, v18.16.0 + * @experimental + * @see [source](https://github.com/nodejs/node/blob/v25.x/src/node_sea.cc) + */ +declare module "node:sea" { + type AssetKey = string; + /** + * @since v20.12.0 + * @return Whether this script is running inside a single-executable application. + */ + function isSea(): boolean; + /** + * This method can be used to retrieve the assets configured to be bundled into the + * single-executable application at build time. + * An error is thrown when no matching asset can be found. + * @since v20.12.0 + */ + function getAsset(key: AssetKey): ArrayBuffer; + function getAsset(key: AssetKey, encoding: string): string; + /** + * Similar to `sea.getAsset()`, but returns the result in a [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob). + * An error is thrown when no matching asset can be found. + * @since v20.12.0 + */ + function getAssetAsBlob(key: AssetKey, options?: { + type: string; + }): Blob; + /** + * This method can be used to retrieve the assets configured to be bundled into the + * single-executable application at build time. + * An error is thrown when no matching asset can be found. + * + * Unlike `sea.getRawAsset()` or `sea.getAssetAsBlob()`, this method does not + * return a copy. Instead, it returns the raw asset bundled inside the executable. + * + * For now, users should avoid writing to the returned array buffer. If the + * injected section is not marked as writable or not aligned properly, + * writes to the returned array buffer is likely to result in a crash. + * @since v20.12.0 + */ + function getRawAsset(key: AssetKey): ArrayBuffer; + /** + * This method can be used to retrieve an array of all the keys of assets + * embedded into the single-executable application. + * An error is thrown when not running inside a single-executable application. + * @since v24.8.0 + * @returns An array containing all the keys of the assets + * embedded in the executable. If no assets are embedded, returns an empty array. + */ + function getAssetKeys(): string[]; +} diff --git a/server/node_modules/@types/node/sqlite.d.ts b/server/node_modules/@types/node/sqlite.d.ts new file mode 100644 index 0000000..f6c3452 --- /dev/null +++ b/server/node_modules/@types/node/sqlite.d.ts @@ -0,0 +1,955 @@ +/** + * The `node:sqlite` module facilitates working with SQLite databases. + * To access it: + * + * ```js + * import sqlite from 'node:sqlite'; + * ``` + * + * This module is only available under the `node:` scheme. The following will not + * work: + * + * ```js + * import sqlite from 'sqlite'; + * ``` + * + * The following example shows the basic usage of the `node:sqlite` module to open + * an in-memory database, write data to the database, and then read the data back. + * + * ```js + * import { DatabaseSync } from 'node:sqlite'; + * const database = new DatabaseSync(':memory:'); + * + * // Execute SQL statements from strings. + * database.exec(` + * CREATE TABLE data( + * key INTEGER PRIMARY KEY, + * value TEXT + * ) STRICT + * `); + * // Create a prepared statement to insert data into the database. + * const insert = database.prepare('INSERT INTO data (key, value) VALUES (?, ?)'); + * // Execute the prepared statement with bound values. + * insert.run(1, 'hello'); + * insert.run(2, 'world'); + * // Create a prepared statement to read data from the database. + * const query = database.prepare('SELECT * FROM data ORDER BY key'); + * // Execute the prepared statement and log the result set. + * console.log(query.all()); + * // Prints: [ { key: 1, value: 'hello' }, { key: 2, value: 'world' } ] + * ``` + * @since v22.5.0 + * @experimental + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/sqlite.js) + */ +declare module "node:sqlite" { + import { PathLike } from "node:fs"; + type SQLInputValue = null | number | bigint | string | NodeJS.ArrayBufferView; + type SQLOutputValue = null | number | bigint | string | NodeJS.NonSharedUint8Array; + interface DatabaseSyncOptions { + /** + * If `true`, the database is opened by the constructor. When + * this value is `false`, the database must be opened via the `open()` method. + * @since v22.5.0 + * @default true + */ + open?: boolean | undefined; + /** + * If `true`, foreign key constraints + * are enabled. This is recommended but can be disabled for compatibility with + * legacy database schemas. The enforcement of foreign key constraints can be + * enabled and disabled after opening the database using + * [`PRAGMA foreign_keys`](https://www.sqlite.org/pragma.html#pragma_foreign_keys). + * @since v22.10.0 + * @default true + */ + enableForeignKeyConstraints?: boolean | undefined; + /** + * If `true`, SQLite will accept + * [double-quoted string literals](https://www.sqlite.org/quirks.html#dblquote). + * This is not recommended but can be + * enabled for compatibility with legacy database schemas. + * @since v22.10.0 + * @default false + */ + enableDoubleQuotedStringLiterals?: boolean | undefined; + /** + * If `true`, the database is opened in read-only mode. + * If the database does not exist, opening it will fail. + * @since v22.12.0 + * @default false + */ + readOnly?: boolean | undefined; + /** + * If `true`, the `loadExtension` SQL function + * and the `loadExtension()` method are enabled. + * You can call `enableLoadExtension(false)` later to disable this feature. + * @since v22.13.0 + * @default false + */ + allowExtension?: boolean | undefined; + /** + * The [busy timeout](https://sqlite.org/c3ref/busy_timeout.html) in milliseconds. This is the maximum amount of + * time that SQLite will wait for a database lock to be released before + * returning an error. + * @since v24.0.0 + * @default 0 + */ + timeout?: number | undefined; + /** + * If `true`, integer fields are read as JavaScript `BigInt` values. If `false`, + * integer fields are read as JavaScript numbers. + * @since v24.4.0 + * @default false + */ + readBigInts?: boolean | undefined; + /** + * If `true`, query results are returned as arrays instead of objects. + * @since v24.4.0 + * @default false + */ + returnArrays?: boolean | undefined; + /** + * If `true`, allows binding named parameters without the prefix + * character (e.g., `foo` instead of `:foo`). + * @since v24.4.40 + * @default true + */ + allowBareNamedParameters?: boolean | undefined; + /** + * If `true`, unknown named parameters are ignored when binding. + * If `false`, an exception is thrown for unknown named parameters. + * @since v24.4.40 + * @default false + */ + allowUnknownNamedParameters?: boolean | undefined; + /** + * If `true`, enables the defensive flag. When the defensive flag is enabled, + * language features that allow ordinary SQL to deliberately corrupt the database file are disabled. + * The defensive flag can also be set using `enableDefensive()`. + * @since v25.1.0 + * @default false + */ + defensive?: boolean | undefined; + } + interface CreateSessionOptions { + /** + * A specific table to track changes for. By default, changes to all tables are tracked. + * @since v22.12.0 + */ + table?: string | undefined; + /** + * Name of the database to track. This is useful when multiple databases have been added using + * [`ATTACH DATABASE`](https://www.sqlite.org/lang_attach.html). + * @since v22.12.0 + * @default 'main' + */ + db?: string | undefined; + } + interface ApplyChangesetOptions { + /** + * Skip changes that, when targeted table name is supplied to this function, return a truthy value. + * By default, all changes are attempted. + * @since v22.12.0 + */ + filter?: ((tableName: string) => boolean) | undefined; + /** + * A function that determines how to handle conflicts. The function receives one argument, + * which can be one of the following values: + * + * * `SQLITE_CHANGESET_DATA`: A `DELETE` or `UPDATE` change does not contain the expected "before" values. + * * `SQLITE_CHANGESET_NOTFOUND`: A row matching the primary key of the `DELETE` or `UPDATE` change does not exist. + * * `SQLITE_CHANGESET_CONFLICT`: An `INSERT` change results in a duplicate primary key. + * * `SQLITE_CHANGESET_FOREIGN_KEY`: Applying a change would result in a foreign key violation. + * * `SQLITE_CHANGESET_CONSTRAINT`: Applying a change results in a `UNIQUE`, `CHECK`, or `NOT NULL` constraint + * violation. + * + * The function should return one of the following values: + * + * * `SQLITE_CHANGESET_OMIT`: Omit conflicting changes. + * * `SQLITE_CHANGESET_REPLACE`: Replace existing values with conflicting changes (only valid with + `SQLITE_CHANGESET_DATA` or `SQLITE_CHANGESET_CONFLICT` conflicts). + * * `SQLITE_CHANGESET_ABORT`: Abort on conflict and roll back the database. + * + * When an error is thrown in the conflict handler or when any other value is returned from the handler, + * applying the changeset is aborted and the database is rolled back. + * + * **Default**: A function that returns `SQLITE_CHANGESET_ABORT`. + * @since v22.12.0 + */ + onConflict?: ((conflictType: number) => number) | undefined; + } + interface FunctionOptions { + /** + * If `true`, the [`SQLITE_DETERMINISTIC`](https://www.sqlite.org/c3ref/c_deterministic.html) flag is + * set on the created function. + * @default false + */ + deterministic?: boolean | undefined; + /** + * If `true`, the [`SQLITE_DIRECTONLY`](https://www.sqlite.org/c3ref/c_directonly.html) flag is set on + * the created function. + * @default false + */ + directOnly?: boolean | undefined; + /** + * If `true`, integer arguments to `function` + * are converted to `BigInt`s. If `false`, integer arguments are passed as + * JavaScript numbers. + * @default false + */ + useBigIntArguments?: boolean | undefined; + /** + * If `true`, `function` may be invoked with any number of + * arguments (between zero and + * [`SQLITE_MAX_FUNCTION_ARG`](https://www.sqlite.org/limits.html#max_function_arg)). If `false`, + * `function` must be invoked with exactly `function.length` arguments. + * @default false + */ + varargs?: boolean | undefined; + } + interface AggregateOptions<T extends SQLInputValue = SQLInputValue> extends FunctionOptions { + /** + * The identity value for the aggregation function. This value is used when the aggregation + * function is initialized. When a `Function` is passed the identity will be its return value. + */ + start: T | (() => T); + /** + * The function to call for each row in the aggregation. The + * function receives the current state and the row value. The return value of + * this function should be the new state. + */ + step: (accumulator: T, ...args: SQLOutputValue[]) => T; + /** + * The function to call to get the result of the + * aggregation. The function receives the final state and should return the + * result of the aggregation. + */ + result?: ((accumulator: T) => SQLInputValue) | undefined; + /** + * When this function is provided, the `aggregate` method will work as a window function. + * The function receives the current state and the dropped row value. The return value of this function should be the + * new state. + */ + inverse?: ((accumulator: T, ...args: SQLOutputValue[]) => T) | undefined; + } + /** + * This class represents a single [connection](https://www.sqlite.org/c3ref/sqlite3.html) to a SQLite database. All APIs + * exposed by this class execute synchronously. + * @since v22.5.0 + */ + class DatabaseSync implements Disposable { + /** + * Constructs a new `DatabaseSync` instance. + * @param path The path of the database. + * A SQLite database can be stored in a file or completely [in memory](https://www.sqlite.org/inmemorydb.html). + * To use a file-backed database, the path should be a file path. + * To use an in-memory database, the path should be the special name `':memory:'`. + * @param options Configuration options for the database connection. + */ + constructor(path: PathLike, options?: DatabaseSyncOptions); + /** + * Registers a new aggregate function with the SQLite database. This method is a wrapper around + * [`sqlite3_create_window_function()`](https://www.sqlite.org/c3ref/create_function.html). + * + * When used as a window function, the `result` function will be called multiple times. + * + * ```js + * import { DatabaseSync } from 'node:sqlite'; + * + * const db = new DatabaseSync(':memory:'); + * db.exec(` + * CREATE TABLE t3(x, y); + * INSERT INTO t3 VALUES ('a', 4), + * ('b', 5), + * ('c', 3), + * ('d', 8), + * ('e', 1); + * `); + * + * db.aggregate('sumint', { + * start: 0, + * step: (acc, value) => acc + value, + * }); + * + * db.prepare('SELECT sumint(y) as total FROM t3').get(); // { total: 21 } + * ``` + * @since v24.0.0 + * @param name The name of the SQLite function to create. + * @param options Function configuration settings. + */ + aggregate(name: string, options: AggregateOptions): void; + aggregate<T extends SQLInputValue>(name: string, options: AggregateOptions<T>): void; + /** + * Closes the database connection. An exception is thrown if the database is not + * open. This method is a wrapper around [`sqlite3_close_v2()`](https://www.sqlite.org/c3ref/close.html). + * @since v22.5.0 + */ + close(): void; + /** + * Loads a shared library into the database connection. This method is a wrapper + * around [`sqlite3_load_extension()`](https://www.sqlite.org/c3ref/load_extension.html). It is required to enable the + * `allowExtension` option when constructing the `DatabaseSync` instance. + * @since v22.13.0 + * @param path The path to the shared library to load. + */ + loadExtension(path: string): void; + /** + * Enables or disables the `loadExtension` SQL function, and the `loadExtension()` + * method. When `allowExtension` is `false` when constructing, you cannot enable + * loading extensions for security reasons. + * @since v22.13.0 + * @param allow Whether to allow loading extensions. + */ + enableLoadExtension(allow: boolean): void; + /** + * Enables or disables the defensive flag. When the defensive flag is active, + * language features that allow ordinary SQL to deliberately corrupt the database file are disabled. + * See [`SQLITE_DBCONFIG_DEFENSIVE`](https://www.sqlite.org/c3ref/c_dbconfig_defensive.html#sqlitedbconfigdefensive) in the SQLite documentation for details. + * @since v25.1.0 + * @param active Whether to set the defensive flag. + */ + enableDefensive(active: boolean): void; + /** + * This method is a wrapper around [`sqlite3_db_filename()`](https://sqlite.org/c3ref/db_filename.html) + * @since v24.0.0 + * @param dbName Name of the database. This can be `'main'` (the default primary database) or any other + * database that has been added with [`ATTACH DATABASE`](https://www.sqlite.org/lang_attach.html) **Default:** `'main'`. + * @returns The location of the database file. When using an in-memory database, + * this method returns null. + */ + location(dbName?: string): string | null; + /** + * This method allows one or more SQL statements to be executed without returning + * any results. This method is useful when executing SQL statements read from a + * file. This method is a wrapper around [`sqlite3_exec()`](https://www.sqlite.org/c3ref/exec.html). + * @since v22.5.0 + * @param sql A SQL string to execute. + */ + exec(sql: string): void; + /** + * This method is used to create SQLite user-defined functions. This method is a + * wrapper around [`sqlite3_create_function_v2()`](https://www.sqlite.org/c3ref/create_function.html). + * @since v22.13.0 + * @param name The name of the SQLite function to create. + * @param options Optional configuration settings for the function. + * @param func The JavaScript function to call when the SQLite + * function is invoked. The return value of this function should be a valid + * SQLite data type: see + * [Type conversion between JavaScript and SQLite](https://nodejs.org/docs/latest-v25.x/api/sqlite.html#type-conversion-between-javascript-and-sqlite). + * The result defaults to `NULL` if the return value is `undefined`. + */ + function( + name: string, + options: FunctionOptions, + func: (...args: SQLOutputValue[]) => SQLInputValue, + ): void; + function(name: string, func: (...args: SQLOutputValue[]) => SQLInputValue): void; + /** + * Sets an authorizer callback that SQLite will invoke whenever it attempts to + * access data or modify the database schema through prepared statements. + * This can be used to implement security policies, audit access, or restrict certain operations. + * This method is a wrapper around [`sqlite3_set_authorizer()`](https://sqlite.org/c3ref/set_authorizer.html). + * + * When invoked, the callback receives five arguments: + * + * * `actionCode` {number} The type of operation being performed (e.g., + * `SQLITE_INSERT`, `SQLITE_UPDATE`, `SQLITE_SELECT`). + * * `arg1` {string|null} The first argument (context-dependent, often a table name). + * * `arg2` {string|null} The second argument (context-dependent, often a column name). + * * `dbName` {string|null} The name of the database. + * * `triggerOrView` {string|null} The name of the trigger or view causing the access. + * + * The callback must return one of the following constants: + * + * * `SQLITE_OK` - Allow the operation. + * * `SQLITE_DENY` - Deny the operation (causes an error). + * * `SQLITE_IGNORE` - Ignore the operation (silently skip). + * + * ```js + * import { DatabaseSync, constants } from 'node:sqlite'; + * const db = new DatabaseSync(':memory:'); + * + * // Set up an authorizer that denies all table creation + * db.setAuthorizer((actionCode) => { + * if (actionCode === constants.SQLITE_CREATE_TABLE) { + * return constants.SQLITE_DENY; + * } + * return constants.SQLITE_OK; + * }); + * + * // This will work + * db.prepare('SELECT 1').get(); + * + * // This will throw an error due to authorization denial + * try { + * db.exec('CREATE TABLE blocked (id INTEGER)'); + * } catch (err) { + * console.log('Operation blocked:', err.message); + * } + * ``` + * @since v24.10.0 + * @param callback The authorizer function to set, or `null` to + * clear the current authorizer. + */ + setAuthorizer( + callback: + | (( + actionCode: number, + arg1: string | null, + arg2: string | null, + dbName: string | null, + triggerOrView: string | null, + ) => number) + | null, + ): void; + /** + * Whether the database is currently open or not. + * @since v22.15.0 + */ + readonly isOpen: boolean; + /** + * Whether the database is currently within a transaction. This method + * is a wrapper around [`sqlite3_get_autocommit()`](https://sqlite.org/c3ref/get_autocommit.html). + * @since v24.0.0 + */ + readonly isTransaction: boolean; + /** + * Opens the database specified in the `path` argument of the `DatabaseSync`constructor. This method should only be used when the database is not opened via + * the constructor. An exception is thrown if the database is already open. + * @since v22.5.0 + */ + open(): void; + /** + * Compiles a SQL statement into a [prepared statement](https://www.sqlite.org/c3ref/stmt.html). This method is a wrapper + * around [`sqlite3_prepare_v2()`](https://www.sqlite.org/c3ref/prepare.html). + * @since v22.5.0 + * @param sql A SQL string to compile to a prepared statement. + * @return The prepared statement. + */ + prepare(sql: string): StatementSync; + /** + * Creates a new `SQLTagStore`, which is an LRU (Least Recently Used) cache for + * storing prepared statements. This allows for the efficient reuse of prepared + * statements by tagging them with a unique identifier. + * + * When a tagged SQL literal is executed, the `SQLTagStore` checks if a prepared + * statement for that specific SQL string already exists in the cache. If it does, + * the cached statement is used. If not, a new prepared statement is created, + * executed, and then stored in the cache for future use. This mechanism helps to + * avoid the overhead of repeatedly parsing and preparing the same SQL statements. + * + * ```js + * import { DatabaseSync } from 'node:sqlite'; + * + * const db = new DatabaseSync(':memory:'); + * const sql = db.createSQLTagStore(); + * + * db.exec('CREATE TABLE users (id INT, name TEXT)'); + * + * // Using the 'run' method to insert data. + * // The tagged literal is used to identify the prepared statement. + * sql.run`INSERT INTO users VALUES (1, 'Alice')`; + * sql.run`INSERT INTO users VALUES (2, 'Bob')`; + * + * // Using the 'get' method to retrieve a single row. + * const id = 1; + * const user = sql.get`SELECT * FROM users WHERE id = ${id}`; + * console.log(user); // { id: 1, name: 'Alice' } + * + * // Using the 'all' method to retrieve all rows. + * const allUsers = sql.all`SELECT * FROM users ORDER BY id`; + * console.log(allUsers); + * // [ + * // { id: 1, name: 'Alice' }, + * // { id: 2, name: 'Bob' } + * // ] + * ``` + * @since v24.9.0 + * @returns A new SQL tag store for caching prepared statements. + */ + createTagStore(maxSize?: number): SQLTagStore; + /** + * Creates and attaches a session to the database. This method is a wrapper around + * [`sqlite3session_create()`](https://www.sqlite.org/session/sqlite3session_create.html) and + * [`sqlite3session_attach()`](https://www.sqlite.org/session/sqlite3session_attach.html). + * @param options The configuration options for the session. + * @returns A session handle. + * @since v22.12.0 + */ + createSession(options?: CreateSessionOptions): Session; + /** + * An exception is thrown if the database is not + * open. This method is a wrapper around + * [`sqlite3changeset_apply()`](https://www.sqlite.org/session/sqlite3changeset_apply.html). + * + * ```js + * import { DatabaseSync } from 'node:sqlite'; + * + * const sourceDb = new DatabaseSync(':memory:'); + * const targetDb = new DatabaseSync(':memory:'); + * + * sourceDb.exec('CREATE TABLE data(key INTEGER PRIMARY KEY, value TEXT)'); + * targetDb.exec('CREATE TABLE data(key INTEGER PRIMARY KEY, value TEXT)'); + * + * const session = sourceDb.createSession(); + * + * const insert = sourceDb.prepare('INSERT INTO data (key, value) VALUES (?, ?)'); + * insert.run(1, 'hello'); + * insert.run(2, 'world'); + * + * const changeset = session.changeset(); + * targetDb.applyChangeset(changeset); + * // Now that the changeset has been applied, targetDb contains the same data as sourceDb. + * ``` + * @param changeset A binary changeset or patchset. + * @param options The configuration options for how the changes will be applied. + * @returns Whether the changeset was applied successfully without being aborted. + * @since v22.12.0 + */ + applyChangeset(changeset: Uint8Array, options?: ApplyChangesetOptions): boolean; + /** + * Closes the database connection. If the database connection is already closed + * then this is a no-op. + * @since v22.15.0 + */ + [Symbol.dispose](): void; + } + /** + * @since v22.12.0 + */ + interface Session { + /** + * Retrieves a changeset containing all changes since the changeset was created. Can be called multiple times. + * An exception is thrown if the database or the session is not open. This method is a wrapper around + * [`sqlite3session_changeset()`](https://www.sqlite.org/session/sqlite3session_changeset.html). + * @returns Binary changeset that can be applied to other databases. + * @since v22.12.0 + */ + changeset(): NodeJS.NonSharedUint8Array; + /** + * Similar to the method above, but generates a more compact patchset. See + * [Changesets and Patchsets](https://www.sqlite.org/sessionintro.html#changesets_and_patchsets) + * in the documentation of SQLite. An exception is thrown if the database or the session is not open. This method is a + * wrapper around + * [`sqlite3session_patchset()`](https://www.sqlite.org/session/sqlite3session_patchset.html). + * @returns Binary patchset that can be applied to other databases. + * @since v22.12.0 + */ + patchset(): NodeJS.NonSharedUint8Array; + /** + * Closes the session. An exception is thrown if the database or the session is not open. This method is a + * wrapper around + * [`sqlite3session_delete()`](https://www.sqlite.org/session/sqlite3session_delete.html). + */ + close(): void; + } + /** + * This class represents a single LRU (Least Recently Used) cache for storing + * prepared statements. + * + * Instances of this class are created via the database.createSQLTagStore() method, + * not by using a constructor. The store caches prepared statements based on the + * provided SQL query string. When the same query is seen again, the store + * retrieves the cached statement and safely applies the new values through + * parameter binding, thereby preventing attacks like SQL injection. + * + * The cache has a maxSize that defaults to 1000 statements, but a custom size can + * be provided (e.g., database.createSQLTagStore(100)). All APIs exposed by this + * class execute synchronously. + * @since v24.9.0 + */ + interface SQLTagStore { + /** + * Executes the given SQL query and returns all resulting rows as an array of objects. + * @since v24.9.0 + */ + all( + stringElements: TemplateStringsArray, + ...boundParameters: SQLInputValue[] + ): Record<string, SQLOutputValue>[]; + /** + * Executes the given SQL query and returns the first resulting row as an object. + * @since v24.9.0 + */ + get( + stringElements: TemplateStringsArray, + ...boundParameters: SQLInputValue[] + ): Record<string, SQLOutputValue> | undefined; + /** + * Executes the given SQL query and returns an iterator over the resulting rows. + * @since v24.9.0 + */ + iterate( + stringElements: TemplateStringsArray, + ...boundParameters: SQLInputValue[] + ): NodeJS.Iterator<Record<string, SQLOutputValue>>; + /** + * Executes the given SQL query, which is expected to not return any rows (e.g., INSERT, UPDATE, DELETE). + * @since v24.9.0 + */ + run(stringElements: TemplateStringsArray, ...boundParameters: SQLInputValue[]): StatementResultingChanges; + /** + * A read-only property that returns the number of prepared statements currently in the cache. + * @since v24.9.0 + * @returns The maximum number of prepared statements the cache can hold. + */ + size(): number; + /** + * A read-only property that returns the maximum number of prepared statements the cache can hold. + * @since v24.9.0 + */ + readonly capacity: number; + /** + * A read-only property that returns the `DatabaseSync` object associated with this `SQLTagStore`. + * @since v24.9.0 + */ + readonly db: DatabaseSync; + /** + * Resets the LRU cache, clearing all stored prepared statements. + * @since v24.9.0 + */ + clear(): void; + } + interface StatementColumnMetadata { + /** + * The unaliased name of the column in the origin + * table, or `null` if the column is the result of an expression or subquery. + * This property is the result of [`sqlite3_column_origin_name()`](https://www.sqlite.org/c3ref/column_database_name.html). + */ + column: string | null; + /** + * The unaliased name of the origin database, or + * `null` if the column is the result of an expression or subquery. This + * property is the result of [`sqlite3_column_database_name()`](https://www.sqlite.org/c3ref/column_database_name.html). + */ + database: string | null; + /** + * The name assigned to the column in the result set of a + * `SELECT` statement. This property is the result of + * [`sqlite3_column_name()`](https://www.sqlite.org/c3ref/column_name.html). + */ + name: string; + /** + * The unaliased name of the origin table, or `null` if + * the column is the result of an expression or subquery. This property is the + * result of [`sqlite3_column_table_name()`](https://www.sqlite.org/c3ref/column_database_name.html). + */ + table: string | null; + /** + * The declared data type of the column, or `null` if the + * column is the result of an expression or subquery. This property is the + * result of [`sqlite3_column_decltype()`](https://www.sqlite.org/c3ref/column_decltype.html). + */ + type: string | null; + } + interface StatementResultingChanges { + /** + * The number of rows modified, inserted, or deleted by the most recently completed `INSERT`, `UPDATE`, or `DELETE` statement. + * This field is either a number or a `BigInt` depending on the prepared statement's configuration. + * This property is the result of [`sqlite3_changes64()`](https://www.sqlite.org/c3ref/changes.html). + */ + changes: number | bigint; + /** + * The most recently inserted rowid. + * This field is either a number or a `BigInt` depending on the prepared statement's configuration. + * This property is the result of [`sqlite3_last_insert_rowid()`](https://www.sqlite.org/c3ref/last_insert_rowid.html). + */ + lastInsertRowid: number | bigint; + } + /** + * This class represents a single [prepared statement](https://www.sqlite.org/c3ref/stmt.html). This class cannot be + * instantiated via its constructor. Instead, instances are created via the`database.prepare()` method. All APIs exposed by this class execute + * synchronously. + * + * A prepared statement is an efficient binary representation of the SQL used to + * create it. Prepared statements are parameterizable, and can be invoked multiple + * times with different bound values. Parameters also offer protection against [SQL injection](https://en.wikipedia.org/wiki/SQL_injection) attacks. For these reasons, prepared statements are + * preferred + * over hand-crafted SQL strings when handling user input. + * @since v22.5.0 + */ + class StatementSync { + private constructor(); + /** + * This method executes a prepared statement and returns all results as an array of + * objects. If the prepared statement does not return any results, this method + * returns an empty array. The prepared statement [parameters are bound](https://www.sqlite.org/c3ref/bind_blob.html) using + * the values in `namedParameters` and `anonymousParameters`. + * @since v22.5.0 + * @param namedParameters An optional object used to bind named parameters. The keys of this object are used to configure the mapping. + * @param anonymousParameters Zero or more values to bind to anonymous parameters. + * @return An array of objects. Each object corresponds to a row returned by executing the prepared statement. The keys and values of each object correspond to the column names and values of + * the row. + */ + all(...anonymousParameters: SQLInputValue[]): Record<string, SQLOutputValue>[]; + all( + namedParameters: Record<string, SQLInputValue>, + ...anonymousParameters: SQLInputValue[] + ): Record<string, SQLOutputValue>[]; + /** + * This method is used to retrieve information about the columns returned by the + * prepared statement. + * @since v23.11.0 + * @returns An array of objects. Each object corresponds to a column + * in the prepared statement, and contains the following properties: + */ + columns(): StatementColumnMetadata[]; + /** + * The source SQL text of the prepared statement with parameter + * placeholders replaced by the values that were used during the most recent + * execution of this prepared statement. This property is a wrapper around + * [`sqlite3_expanded_sql()`](https://www.sqlite.org/c3ref/expanded_sql.html). + * @since v22.5.0 + */ + readonly expandedSQL: string; + /** + * This method executes a prepared statement and returns the first result as an + * object. If the prepared statement does not return any results, this method + * returns `undefined`. The prepared statement [parameters are bound](https://www.sqlite.org/c3ref/bind_blob.html) using the + * values in `namedParameters` and `anonymousParameters`. + * @since v22.5.0 + * @param namedParameters An optional object used to bind named parameters. The keys of this object are used to configure the mapping. + * @param anonymousParameters Zero or more values to bind to anonymous parameters. + * @return An object corresponding to the first row returned by executing the prepared statement. The keys and values of the object correspond to the column names and values of the row. If no + * rows were returned from the database then this method returns `undefined`. + */ + get(...anonymousParameters: SQLInputValue[]): Record<string, SQLOutputValue> | undefined; + get( + namedParameters: Record<string, SQLInputValue>, + ...anonymousParameters: SQLInputValue[] + ): Record<string, SQLOutputValue> | undefined; + /** + * This method executes a prepared statement and returns an iterator of + * objects. If the prepared statement does not return any results, this method + * returns an empty iterator. The prepared statement [parameters are bound](https://www.sqlite.org/c3ref/bind_blob.html) using + * the values in `namedParameters` and `anonymousParameters`. + * @since v22.13.0 + * @param namedParameters An optional object used to bind named parameters. + * The keys of this object are used to configure the mapping. + * @param anonymousParameters Zero or more values to bind to anonymous parameters. + * @returns An iterable iterator of objects. Each object corresponds to a row + * returned by executing the prepared statement. The keys and values of each + * object correspond to the column names and values of the row. + */ + iterate(...anonymousParameters: SQLInputValue[]): NodeJS.Iterator<Record<string, SQLOutputValue>>; + iterate( + namedParameters: Record<string, SQLInputValue>, + ...anonymousParameters: SQLInputValue[] + ): NodeJS.Iterator<Record<string, SQLOutputValue>>; + /** + * This method executes a prepared statement and returns an object summarizing the + * resulting changes. The prepared statement [parameters are bound](https://www.sqlite.org/c3ref/bind_blob.html) using the + * values in `namedParameters` and `anonymousParameters`. + * @since v22.5.0 + * @param namedParameters An optional object used to bind named parameters. The keys of this object are used to configure the mapping. + * @param anonymousParameters Zero or more values to bind to anonymous parameters. + */ + run(...anonymousParameters: SQLInputValue[]): StatementResultingChanges; + run( + namedParameters: Record<string, SQLInputValue>, + ...anonymousParameters: SQLInputValue[] + ): StatementResultingChanges; + /** + * The names of SQLite parameters begin with a prefix character. By default,`node:sqlite` requires that this prefix character is present when binding + * parameters. However, with the exception of dollar sign character, these + * prefix characters also require extra quoting when used in object keys. + * + * To improve ergonomics, this method can be used to also allow bare named + * parameters, which do not require the prefix character in JavaScript code. There + * are several caveats to be aware of when enabling bare named parameters: + * + * * The prefix character is still required in SQL. + * * The prefix character is still allowed in JavaScript. In fact, prefixed names + * will have slightly better binding performance. + * * Using ambiguous named parameters, such as `$k` and `@k`, in the same prepared + * statement will result in an exception as it cannot be determined how to bind + * a bare name. + * @since v22.5.0 + * @param enabled Enables or disables support for binding named parameters without the prefix character. + */ + setAllowBareNamedParameters(enabled: boolean): void; + /** + * By default, if an unknown name is encountered while binding parameters, an + * exception is thrown. This method allows unknown named parameters to be ignored. + * @since v22.15.0 + * @param enabled Enables or disables support for unknown named parameters. + */ + setAllowUnknownNamedParameters(enabled: boolean): void; + /** + * When enabled, query results returned by the `all()`, `get()`, and `iterate()` methods will be returned as arrays instead + * of objects. + * @since v24.0.0 + * @param enabled Enables or disables the return of query results as arrays. + */ + setReturnArrays(enabled: boolean): void; + /** + * When reading from the database, SQLite `INTEGER`s are mapped to JavaScript + * numbers by default. However, SQLite `INTEGER`s can store values larger than + * JavaScript numbers are capable of representing. In such cases, this method can + * be used to read `INTEGER` data using JavaScript `BigInt`s. This method has no + * impact on database write operations where numbers and `BigInt`s are both + * supported at all times. + * @since v22.5.0 + * @param enabled Enables or disables the use of `BigInt`s when reading `INTEGER` fields from the database. + */ + setReadBigInts(enabled: boolean): void; + /** + * The source SQL text of the prepared statement. This property is a + * wrapper around [`sqlite3_sql()`](https://www.sqlite.org/c3ref/expanded_sql.html). + * @since v22.5.0 + */ + readonly sourceSQL: string; + } + interface BackupOptions { + /** + * Name of the source database. This can be `'main'` (the default primary database) or any other + * database that have been added with [`ATTACH DATABASE`](https://www.sqlite.org/lang_attach.html) + * @default 'main' + */ + source?: string | undefined; + /** + * Name of the target database. This can be `'main'` (the default primary database) or any other + * database that have been added with [`ATTACH DATABASE`](https://www.sqlite.org/lang_attach.html) + * @default 'main' + */ + target?: string | undefined; + /** + * Number of pages to be transmitted in each batch of the backup. + * @default 100 + */ + rate?: number | undefined; + /** + * An optional callback function that will be called after each backup step. The argument passed + * to this callback is an `Object` with `remainingPages` and `totalPages` properties, describing the current progress + * of the backup operation. + */ + progress?: ((progressInfo: BackupProgressInfo) => void) | undefined; + } + interface BackupProgressInfo { + totalPages: number; + remainingPages: number; + } + /** + * This method makes a database backup. This method abstracts the + * [`sqlite3_backup_init()`](https://www.sqlite.org/c3ref/backup_finish.html#sqlite3backupinit), + * [`sqlite3_backup_step()`](https://www.sqlite.org/c3ref/backup_finish.html#sqlite3backupstep) + * and [`sqlite3_backup_finish()`](https://www.sqlite.org/c3ref/backup_finish.html#sqlite3backupfinish) functions. + * + * The backed-up database can be used normally during the backup process. Mutations coming from the same connection - same + * `DatabaseSync` - object will be reflected in the backup right away. However, mutations from other connections will cause + * the backup process to restart. + * + * ```js + * import { backup, DatabaseSync } from 'node:sqlite'; + * + * const sourceDb = new DatabaseSync('source.db'); + * const totalPagesTransferred = await backup(sourceDb, 'backup.db', { + * rate: 1, // Copy one page at a time. + * progress: ({ totalPages, remainingPages }) => { + * console.log('Backup in progress', { totalPages, remainingPages }); + * }, + * }); + * + * console.log('Backup completed', totalPagesTransferred); + * ``` + * @since v23.8.0 + * @param sourceDb The database to backup. The source database must be open. + * @param path The path where the backup will be created. If the file already exists, + * the contents will be overwritten. + * @param options Optional configuration for the backup. The + * following properties are supported: + * @returns A promise that fulfills with the total number of backed-up pages upon completion, or rejects if an + * error occurs. + */ + function backup(sourceDb: DatabaseSync, path: PathLike, options?: BackupOptions): Promise<number>; + /** + * @since v22.13.0 + */ + namespace constants { + /** + * The conflict handler is invoked with this constant when processing a DELETE or UPDATE change if a row with the required PRIMARY KEY fields is present in the database, but one or more other (non primary-key) fields modified by the update do not contain the expected "before" values. + * @since v22.14.0 + */ + const SQLITE_CHANGESET_DATA: number; + /** + * The conflict handler is invoked with this constant when processing a DELETE or UPDATE change if a row with the required PRIMARY KEY fields is not present in the database. + * @since v22.14.0 + */ + const SQLITE_CHANGESET_NOTFOUND: number; + /** + * This constant is passed to the conflict handler while processing an INSERT change if the operation would result in duplicate primary key values. + * @since v22.14.0 + */ + const SQLITE_CHANGESET_CONFLICT: number; + /** + * If foreign key handling is enabled, and applying a changeset leaves the database in a state containing foreign key violations, the conflict handler is invoked with this constant exactly once before the changeset is committed. If the conflict handler returns `SQLITE_CHANGESET_OMIT`, the changes, including those that caused the foreign key constraint violation, are committed. Or, if it returns `SQLITE_CHANGESET_ABORT`, the changeset is rolled back. + * @since v22.14.0 + */ + const SQLITE_CHANGESET_FOREIGN_KEY: number; + /** + * Conflicting changes are omitted. + * @since v22.12.0 + */ + const SQLITE_CHANGESET_OMIT: number; + /** + * Conflicting changes replace existing values. Note that this value can only be returned when the type of conflict is either `SQLITE_CHANGESET_DATA` or `SQLITE_CHANGESET_CONFLICT`. + * @since v22.12.0 + */ + const SQLITE_CHANGESET_REPLACE: number; + /** + * Abort when a change encounters a conflict and roll back database. + * @since v22.12.0 + */ + const SQLITE_CHANGESET_ABORT: number; + /** + * Deny the operation and cause an error to be returned. + * @since v24.10.0 + */ + const SQLITE_DENY: number; + /** + * Ignore the operation and continue as if it had never been requested. + * @since 24.10.0 + */ + const SQLITE_IGNORE: number; + /** + * Allow the operation to proceed normally. + * @since v24.10.0 + */ + const SQLITE_OK: number; + const SQLITE_CREATE_INDEX: number; + const SQLITE_CREATE_TABLE: number; + const SQLITE_CREATE_TEMP_INDEX: number; + const SQLITE_CREATE_TEMP_TABLE: number; + const SQLITE_CREATE_TEMP_TRIGGER: number; + const SQLITE_CREATE_TEMP_VIEW: number; + const SQLITE_CREATE_TRIGGER: number; + const SQLITE_CREATE_VIEW: number; + const SQLITE_DELETE: number; + const SQLITE_DROP_INDEX: number; + const SQLITE_DROP_TABLE: number; + const SQLITE_DROP_TEMP_INDEX: number; + const SQLITE_DROP_TEMP_TABLE: number; + const SQLITE_DROP_TEMP_TRIGGER: number; + const SQLITE_DROP_TEMP_VIEW: number; + const SQLITE_DROP_TRIGGER: number; + const SQLITE_DROP_VIEW: number; + const SQLITE_INSERT: number; + const SQLITE_PRAGMA: number; + const SQLITE_READ: number; + const SQLITE_SELECT: number; + const SQLITE_TRANSACTION: number; + const SQLITE_UPDATE: number; + const SQLITE_ATTACH: number; + const SQLITE_DETACH: number; + const SQLITE_ALTER_TABLE: number; + const SQLITE_REINDEX: number; + const SQLITE_ANALYZE: number; + const SQLITE_CREATE_VTABLE: number; + const SQLITE_DROP_VTABLE: number; + const SQLITE_FUNCTION: number; + const SQLITE_SAVEPOINT: number; + const SQLITE_COPY: number; + const SQLITE_RECURSIVE: number; + } +} diff --git a/server/node_modules/@types/node/stream.d.ts b/server/node_modules/@types/node/stream.d.ts new file mode 100644 index 0000000..79ad890 --- /dev/null +++ b/server/node_modules/@types/node/stream.d.ts @@ -0,0 +1,1760 @@ +/** + * A stream is an abstract interface for working with streaming data in Node.js. + * The `node:stream` module provides an API for implementing the stream interface. + * + * There are many stream objects provided by Node.js. For instance, a [request to an HTTP server](https://nodejs.org/docs/latest-v25.x/api/http.html#class-httpincomingmessage) + * and [`process.stdout`](https://nodejs.org/docs/latest-v25.x/api/process.html#processstdout) are both stream instances. + * + * Streams can be readable, writable, or both. All streams are instances of [`EventEmitter`](https://nodejs.org/docs/latest-v25.x/api/events.html#class-eventemitter). + * + * To access the `node:stream` module: + * + * ```js + * import stream from 'node:stream'; + * ``` + * + * The `node:stream` module is useful for creating new types of stream instances. + * It is usually not necessary to use the `node:stream` module to consume streams. + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/stream.js) + */ +declare module "node:stream" { + import { Blob } from "node:buffer"; + import { Abortable, EventEmitter } from "node:events"; + import * as promises from "node:stream/promises"; + import * as web from "node:stream/web"; + class Stream extends EventEmitter { + /** + * @since v0.9.4 + */ + pipe<T extends NodeJS.WritableStream>( + destination: T, + options?: Stream.PipeOptions, + ): T; + } + namespace Stream { + export { promises, Stream }; + } + namespace Stream { + interface PipeOptions { + /** + * End the writer when the reader ends. + * @default true + */ + end?: boolean | undefined; + } + interface StreamOptions<T extends Stream> extends Abortable { + emitClose?: boolean | undefined; + highWaterMark?: number | undefined; + objectMode?: boolean | undefined; + construct?: ((this: T, callback: (error?: Error | null) => void) => void) | undefined; + destroy?: ((this: T, error: Error | null, callback: (error?: Error | null) => void) => void) | undefined; + autoDestroy?: boolean | undefined; + } + interface ReadableOptions<T extends Readable = Readable> extends StreamOptions<T> { + encoding?: BufferEncoding | undefined; + read?: ((this: T, size: number) => void) | undefined; + } + interface ReadableIteratorOptions { + /** + * When set to `false`, calling `return` on the async iterator, + * or exiting a `for await...of` iteration using a `break`, + * `return`, or `throw` will not destroy the stream. + * @default true + */ + destroyOnReturn?: boolean | undefined; + } + interface ReadableOperatorOptions extends Abortable { + /** + * The maximum concurrent invocations of `fn` to call + * on the stream at once. + * @default 1 + */ + concurrency?: number | undefined; + /** + * How many items to buffer while waiting for user consumption + * of the output. + * @default concurrency * 2 - 1 + */ + highWaterMark?: number | undefined; + } + /** @deprecated Use `ReadableOperatorOptions` instead. */ + interface ArrayOptions extends ReadableOperatorOptions {} + interface ReadableToWebOptions { + strategy?: web.QueuingStrategy | undefined; + } + interface ReadableEventMap { + "close": []; + "data": [chunk: any]; + "end": []; + "error": [err: Error]; + "pause": []; + "readable": []; + "resume": []; + } + /** + * @since v0.9.4 + */ + class Readable extends Stream implements NodeJS.ReadableStream { + constructor(options?: ReadableOptions); + /** + * A utility method for creating Readable Streams out of iterators. + * @since v12.3.0, v10.17.0 + * @param iterable Object implementing the `Symbol.asyncIterator` or `Symbol.iterator` iterable protocol. Emits an 'error' event if a null value is passed. + * @param options Options provided to `new stream.Readable([options])`. By default, `Readable.from()` will set `options.objectMode` to `true`, unless this is explicitly opted out by setting `options.objectMode` to `false`. + */ + static from(iterable: Iterable<any> | AsyncIterable<any>, options?: ReadableOptions): Readable; + /** + * A utility method for creating a `Readable` from a web `ReadableStream`. + * @since v17.0.0 + */ + static fromWeb( + readableStream: web.ReadableStream, + options?: Pick<ReadableOptions, "encoding" | "highWaterMark" | "objectMode" | "signal">, + ): Readable; + /** + * A utility method for creating a web `ReadableStream` from a `Readable`. + * @since v17.0.0 + */ + static toWeb( + streamReadable: NodeJS.ReadableStream, + options?: ReadableToWebOptions, + ): web.ReadableStream; + /** + * Returns whether the stream has been read from or cancelled. + * @since v16.8.0 + */ + static isDisturbed(stream: NodeJS.ReadableStream | web.ReadableStream): boolean; + /** + * Returns whether the stream was destroyed or errored before emitting `'end'`. + * @since v16.8.0 + */ + readonly readableAborted: boolean; + /** + * Is `true` if it is safe to call {@link read}, which means + * the stream has not been destroyed or emitted `'error'` or `'end'`. + * @since v11.4.0 + */ + readable: boolean; + /** + * Returns whether `'data'` has been emitted. + * @since v16.7.0, v14.18.0 + */ + readonly readableDidRead: boolean; + /** + * Getter for the property `encoding` of a given `Readable` stream. The `encoding` property can be set using the {@link setEncoding} method. + * @since v12.7.0 + */ + readonly readableEncoding: BufferEncoding | null; + /** + * Becomes `true` when [`'end'`](https://nodejs.org/docs/latest-v25.x/api/stream.html#event-end) event is emitted. + * @since v12.9.0 + */ + readonly readableEnded: boolean; + /** + * This property reflects the current state of a `Readable` stream as described + * in the [Three states](https://nodejs.org/docs/latest-v25.x/api/stream.html#three-states) section. + * @since v9.4.0 + */ + readableFlowing: boolean | null; + /** + * Returns the value of `highWaterMark` passed when creating this `Readable`. + * @since v9.3.0 + */ + readonly readableHighWaterMark: number; + /** + * This property contains the number of bytes (or objects) in the queue + * ready to be read. The value provides introspection data regarding + * the status of the `highWaterMark`. + * @since v9.4.0 + */ + readonly readableLength: number; + /** + * Getter for the property `objectMode` of a given `Readable` stream. + * @since v12.3.0 + */ + readonly readableObjectMode: boolean; + /** + * Is `true` after `readable.destroy()` has been called. + * @since v8.0.0 + */ + destroyed: boolean; + /** + * Is `true` after `'close'` has been emitted. + * @since v18.0.0 + */ + readonly closed: boolean; + /** + * Returns error if the stream has been destroyed with an error. + * @since v18.0.0 + */ + readonly errored: Error | null; + _construct?(callback: (error?: Error | null) => void): void; + _read(size: number): void; + /** + * The `readable.read()` method reads data out of the internal buffer and + * returns it. If no data is available to be read, `null` is returned. By default, + * the data is returned as a `Buffer` object unless an encoding has been + * specified using the `readable.setEncoding()` method or the stream is operating + * in object mode. + * + * The optional `size` argument specifies a specific number of bytes to read. If + * `size` bytes are not available to be read, `null` will be returned _unless_ the + * stream has ended, in which case all of the data remaining in the internal buffer + * will be returned. + * + * If the `size` argument is not specified, all of the data contained in the + * internal buffer will be returned. + * + * The `size` argument must be less than or equal to 1 GiB. + * + * The `readable.read()` method should only be called on `Readable` streams + * operating in paused mode. In flowing mode, `readable.read()` is called + * automatically until the internal buffer is fully drained. + * + * ```js + * const readable = getReadableStreamSomehow(); + * + * // 'readable' may be triggered multiple times as data is buffered in + * readable.on('readable', () => { + * let chunk; + * console.log('Stream is readable (new data received in buffer)'); + * // Use a loop to make sure we read all currently available data + * while (null !== (chunk = readable.read())) { + * console.log(`Read ${chunk.length} bytes of data...`); + * } + * }); + * + * // 'end' will be triggered once when there is no more data available + * readable.on('end', () => { + * console.log('Reached end of stream.'); + * }); + * ``` + * + * Each call to `readable.read()` returns a chunk of data, or `null`. The chunks + * are not concatenated. A `while` loop is necessary to consume all data + * currently in the buffer. When reading a large file `.read()` may return `null`, + * having consumed all buffered content so far, but there is still more data to + * come not yet buffered. In this case a new `'readable'` event will be emitted + * when there is more data in the buffer. Finally the `'end'` event will be + * emitted when there is no more data to come. + * + * Therefore to read a file's whole contents from a `readable`, it is necessary + * to collect chunks across multiple `'readable'` events: + * + * ```js + * const chunks = []; + * + * readable.on('readable', () => { + * let chunk; + * while (null !== (chunk = readable.read())) { + * chunks.push(chunk); + * } + * }); + * + * readable.on('end', () => { + * const content = chunks.join(''); + * }); + * ``` + * + * A `Readable` stream in object mode will always return a single item from + * a call to `readable.read(size)`, regardless of the value of the `size` argument. + * + * If the `readable.read()` method returns a chunk of data, a `'data'` event will + * also be emitted. + * + * Calling {@link read} after the `'end'` event has + * been emitted will return `null`. No runtime error will be raised. + * @since v0.9.4 + * @param size Optional argument to specify how much data to read. + */ + read(size?: number): any; + /** + * The `readable.setEncoding()` method sets the character encoding for + * data read from the `Readable` stream. + * + * By default, no encoding is assigned and stream data will be returned as `Buffer` objects. Setting an encoding causes the stream data + * to be returned as strings of the specified encoding rather than as `Buffer` objects. For instance, calling `readable.setEncoding('utf8')` will cause the + * output data to be interpreted as UTF-8 data, and passed as strings. Calling `readable.setEncoding('hex')` will cause the data to be encoded in hexadecimal + * string format. + * + * The `Readable` stream will properly handle multi-byte characters delivered + * through the stream that would otherwise become improperly decoded if simply + * pulled from the stream as `Buffer` objects. + * + * ```js + * const readable = getReadableStreamSomehow(); + * readable.setEncoding('utf8'); + * readable.on('data', (chunk) => { + * assert.equal(typeof chunk, 'string'); + * console.log('Got %d characters of string data:', chunk.length); + * }); + * ``` + * @since v0.9.4 + * @param encoding The encoding to use. + */ + setEncoding(encoding: BufferEncoding): this; + /** + * The `readable.pause()` method will cause a stream in flowing mode to stop + * emitting `'data'` events, switching out of flowing mode. Any data that + * becomes available will remain in the internal buffer. + * + * ```js + * const readable = getReadableStreamSomehow(); + * readable.on('data', (chunk) => { + * console.log(`Received ${chunk.length} bytes of data.`); + * readable.pause(); + * console.log('There will be no additional data for 1 second.'); + * setTimeout(() => { + * console.log('Now data will start flowing again.'); + * readable.resume(); + * }, 1000); + * }); + * ``` + * + * The `readable.pause()` method has no effect if there is a `'readable'` event listener. + * @since v0.9.4 + */ + pause(): this; + /** + * The `readable.resume()` method causes an explicitly paused `Readable` stream to + * resume emitting `'data'` events, switching the stream into flowing mode. + * + * The `readable.resume()` method can be used to fully consume the data from a + * stream without actually processing any of that data: + * + * ```js + * getReadableStreamSomehow() + * .resume() + * .on('end', () => { + * console.log('Reached the end, but did not read anything.'); + * }); + * ``` + * + * The `readable.resume()` method has no effect if there is a `'readable'` event listener. + * @since v0.9.4 + */ + resume(): this; + /** + * The `readable.isPaused()` method returns the current operating state of the `Readable`. + * This is used primarily by the mechanism that underlies the `readable.pipe()` method. + * In most typical cases, there will be no reason to use this method directly. + * + * ```js + * const readable = new stream.Readable(); + * + * readable.isPaused(); // === false + * readable.pause(); + * readable.isPaused(); // === true + * readable.resume(); + * readable.isPaused(); // === false + * ``` + * @since v0.11.14 + */ + isPaused(): boolean; + /** + * The `readable.unpipe()` method detaches a `Writable` stream previously attached + * using the {@link pipe} method. + * + * If the `destination` is not specified, then _all_ pipes are detached. + * + * If the `destination` is specified, but no pipe is set up for it, then + * the method does nothing. + * + * ```js + * import fs from 'node:fs'; + * const readable = getReadableStreamSomehow(); + * const writable = fs.createWriteStream('file.txt'); + * // All the data from readable goes into 'file.txt', + * // but only for the first second. + * readable.pipe(writable); + * setTimeout(() => { + * console.log('Stop writing to file.txt.'); + * readable.unpipe(writable); + * console.log('Manually close the file stream.'); + * writable.end(); + * }, 1000); + * ``` + * @since v0.9.4 + * @param destination Optional specific stream to unpipe + */ + unpipe(destination?: NodeJS.WritableStream): this; + /** + * Passing `chunk` as `null` signals the end of the stream (EOF) and behaves the + * same as `readable.push(null)`, after which no more data can be written. The EOF + * signal is put at the end of the buffer and any buffered data will still be + * flushed. + * + * The `readable.unshift()` method pushes a chunk of data back into the internal + * buffer. This is useful in certain situations where a stream is being consumed by + * code that needs to "un-consume" some amount of data that it has optimistically + * pulled out of the source, so that the data can be passed on to some other party. + * + * The `stream.unshift(chunk)` method cannot be called after the `'end'` event + * has been emitted or a runtime error will be thrown. + * + * Developers using `stream.unshift()` often should consider switching to + * use of a `Transform` stream instead. See the `API for stream implementers` section for more information. + * + * ```js + * // Pull off a header delimited by \n\n. + * // Use unshift() if we get too much. + * // Call the callback with (error, header, stream). + * import { StringDecoder } from 'node:string_decoder'; + * function parseHeader(stream, callback) { + * stream.on('error', callback); + * stream.on('readable', onReadable); + * const decoder = new StringDecoder('utf8'); + * let header = ''; + * function onReadable() { + * let chunk; + * while (null !== (chunk = stream.read())) { + * const str = decoder.write(chunk); + * if (str.includes('\n\n')) { + * // Found the header boundary. + * const split = str.split(/\n\n/); + * header += split.shift(); + * const remaining = split.join('\n\n'); + * const buf = Buffer.from(remaining, 'utf8'); + * stream.removeListener('error', callback); + * // Remove the 'readable' listener before unshifting. + * stream.removeListener('readable', onReadable); + * if (buf.length) + * stream.unshift(buf); + * // Now the body of the message can be read from the stream. + * callback(null, header, stream); + * return; + * } + * // Still reading the header. + * header += str; + * } + * } + * } + * ``` + * + * Unlike {@link push}, `stream.unshift(chunk)` will not + * end the reading process by resetting the internal reading state of the stream. + * This can cause unexpected results if `readable.unshift()` is called during a + * read (i.e. from within a {@link _read} implementation on a + * custom stream). Following the call to `readable.unshift()` with an immediate {@link push} will reset the reading state appropriately, + * however it is best to simply avoid calling `readable.unshift()` while in the + * process of performing a read. + * @since v0.9.11 + * @param chunk Chunk of data to unshift onto the read queue. For streams not operating in object mode, `chunk` must + * be a {string}, {Buffer}, {TypedArray}, {DataView} or `null`. For object mode streams, `chunk` may be any JavaScript value. + * @param encoding Encoding of string chunks. Must be a valid `Buffer` encoding, such as `'utf8'` or `'ascii'`. + */ + unshift(chunk: any, encoding?: BufferEncoding): void; + /** + * Prior to Node.js 0.10, streams did not implement the entire `node:stream` module API as it is currently defined. (See `Compatibility` for more + * information.) + * + * When using an older Node.js library that emits `'data'` events and has a {@link pause} method that is advisory only, the `readable.wrap()` method can be used to create a `Readable` + * stream that uses + * the old stream as its data source. + * + * It will rarely be necessary to use `readable.wrap()` but the method has been + * provided as a convenience for interacting with older Node.js applications and + * libraries. + * + * ```js + * import { OldReader } from './old-api-module.js'; + * import { Readable } from 'node:stream'; + * const oreader = new OldReader(); + * const myReader = new Readable().wrap(oreader); + * + * myReader.on('readable', () => { + * myReader.read(); // etc. + * }); + * ``` + * @since v0.9.4 + * @param stream An "old style" readable stream + */ + wrap(stream: NodeJS.ReadableStream): this; + push(chunk: any, encoding?: BufferEncoding): boolean; + /** + * ```js + * import { Readable } from 'node:stream'; + * + * async function* splitToWords(source) { + * for await (const chunk of source) { + * const words = String(chunk).split(' '); + * + * for (const word of words) { + * yield word; + * } + * } + * } + * + * const wordsStream = Readable.from(['this is', 'compose as operator']).compose(splitToWords); + * const words = await wordsStream.toArray(); + * + * console.log(words); // prints ['this', 'is', 'compose', 'as', 'operator'] + * ``` + * + * See [`stream.compose`](https://nodejs.org/docs/latest-v25.x/api/stream.html#streamcomposestreams) for more information. + * @since v19.1.0, v18.13.0 + * @returns a stream composed with the stream `stream`. + */ + compose( + stream: NodeJS.WritableStream | web.WritableStream | web.TransformStream | ((source: any) => void), + options?: Abortable, + ): Duplex; + /** + * The iterator created by this method gives users the option to cancel the destruction + * of the stream if the `for await...of` loop is exited by `return`, `break`, or `throw`, + * or if the iterator should destroy the stream if the stream emitted an error during iteration. + * @since v16.3.0 + */ + iterator(options?: ReadableIteratorOptions): NodeJS.AsyncIterator<any>; + /** + * This method allows mapping over the stream. The *fn* function will be called for every chunk in the stream. + * If the *fn* function returns a promise - that promise will be `await`ed before being passed to the result stream. + * @since v17.4.0, v16.14.0 + * @param fn a function to map over every chunk in the stream. Async or not. + * @returns a stream mapped with the function *fn*. + */ + map(fn: (data: any, options?: Abortable) => any, options?: ReadableOperatorOptions): Readable; + /** + * This method allows filtering the stream. For each chunk in the stream the *fn* function will be called + * and if it returns a truthy value, the chunk will be passed to the result stream. + * If the *fn* function returns a promise - that promise will be `await`ed. + * @since v17.4.0, v16.14.0 + * @param fn a function to filter chunks from the stream. Async or not. + * @returns a stream filtered with the predicate *fn*. + */ + filter( + fn: (data: any, options?: Abortable) => boolean | Promise<boolean>, + options?: ReadableOperatorOptions, + ): Readable; + /** + * This method allows iterating a stream. For each chunk in the stream the *fn* function will be called. + * If the *fn* function returns a promise - that promise will be `await`ed. + * + * This method is different from `for await...of` loops in that it can optionally process chunks concurrently. + * In addition, a `forEach` iteration can only be stopped by having passed a `signal` option + * and aborting the related AbortController while `for await...of` can be stopped with `break` or `return`. + * In either case the stream will be destroyed. + * + * This method is different from listening to the `'data'` event in that it uses the `readable` event + * in the underlying machinary and can limit the number of concurrent *fn* calls. + * @since v17.5.0 + * @param fn a function to call on each chunk of the stream. Async or not. + * @returns a promise for when the stream has finished. + */ + forEach( + fn: (data: any, options?: Abortable) => void | Promise<void>, + options?: Pick<ReadableOperatorOptions, "concurrency" | "signal">, + ): Promise<void>; + /** + * This method allows easily obtaining the contents of a stream. + * + * As this method reads the entire stream into memory, it negates the benefits of streams. It's intended + * for interoperability and convenience, not as the primary way to consume streams. + * @since v17.5.0 + * @returns a promise containing an array with the contents of the stream. + */ + toArray(options?: Abortable): Promise<any[]>; + /** + * This method is similar to `Array.prototype.some` and calls *fn* on each chunk in the stream + * until the awaited return value is `true` (or any truthy value). Once an *fn* call on a chunk + * `await`ed return value is truthy, the stream is destroyed and the promise is fulfilled with `true`. + * If none of the *fn* calls on the chunks return a truthy value, the promise is fulfilled with `false`. + * @since v17.5.0 + * @param fn a function to call on each chunk of the stream. Async or not. + * @returns a promise evaluating to `true` if *fn* returned a truthy value for at least one of the chunks. + */ + some( + fn: (data: any, options?: Abortable) => boolean | Promise<boolean>, + options?: Pick<ReadableOperatorOptions, "concurrency" | "signal">, + ): Promise<boolean>; + /** + * This method is similar to `Array.prototype.find` and calls *fn* on each chunk in the stream + * to find a chunk with a truthy value for *fn*. Once an *fn* call's awaited return value is truthy, + * the stream is destroyed and the promise is fulfilled with value for which *fn* returned a truthy value. + * If all of the *fn* calls on the chunks return a falsy value, the promise is fulfilled with `undefined`. + * @since v17.5.0 + * @param fn a function to call on each chunk of the stream. Async or not. + * @returns a promise evaluating to the first chunk for which *fn* evaluated with a truthy value, + * or `undefined` if no element was found. + */ + find<T>( + fn: (data: any, options?: Abortable) => data is T, + options?: Pick<ReadableOperatorOptions, "concurrency" | "signal">, + ): Promise<T | undefined>; + find( + fn: (data: any, options?: Abortable) => boolean | Promise<boolean>, + options?: Pick<ReadableOperatorOptions, "concurrency" | "signal">, + ): Promise<any>; + /** + * This method is similar to `Array.prototype.every` and calls *fn* on each chunk in the stream + * to check if all awaited return values are truthy value for *fn*. Once an *fn* call on a chunk + * `await`ed return value is falsy, the stream is destroyed and the promise is fulfilled with `false`. + * If all of the *fn* calls on the chunks return a truthy value, the promise is fulfilled with `true`. + * @since v17.5.0 + * @param fn a function to call on each chunk of the stream. Async or not. + * @returns a promise evaluating to `true` if *fn* returned a truthy value for every one of the chunks. + */ + every( + fn: (data: any, options?: Abortable) => boolean | Promise<boolean>, + options?: Pick<ReadableOperatorOptions, "concurrency" | "signal">, + ): Promise<boolean>; + /** + * This method returns a new stream by applying the given callback to each chunk of the stream + * and then flattening the result. + * + * It is possible to return a stream or another iterable or async iterable from *fn* and the result streams + * will be merged (flattened) into the returned stream. + * @since v17.5.0 + * @param fn a function to map over every chunk in the stream. May be async. May be a stream or generator. + * @returns a stream flat-mapped with the function *fn*. + */ + flatMap( + fn: (data: any, options?: Abortable) => any, + options?: Pick<ReadableOperatorOptions, "concurrency" | "signal">, + ): Readable; + /** + * This method returns a new stream with the first *limit* chunks dropped from the start. + * @since v17.5.0 + * @param limit the number of chunks to drop from the readable. + * @returns a stream with *limit* chunks dropped from the start. + */ + drop(limit: number, options?: Abortable): Readable; + /** + * This method returns a new stream with the first *limit* chunks. + * @since v17.5.0 + * @param limit the number of chunks to take from the readable. + * @returns a stream with *limit* chunks taken. + */ + take(limit: number, options?: Abortable): Readable; + /** + * This method calls *fn* on each chunk of the stream in order, passing it the result from the calculation + * on the previous element. It returns a promise for the final value of the reduction. + * + * If no *initial* value is supplied the first chunk of the stream is used as the initial value. + * If the stream is empty, the promise is rejected with a `TypeError` with the `ERR_INVALID_ARGS` code property. + * + * The reducer function iterates the stream element-by-element which means that there is no *concurrency* parameter + * or parallelism. To perform a reduce concurrently, you can extract the async function to `readable.map` method. + * @since v17.5.0 + * @param fn a reducer function to call over every chunk in the stream. Async or not. + * @param initial the initial value to use in the reduction. + * @returns a promise for the final value of the reduction. + */ + reduce<T>(fn: (previous: any, data: any, options?: Abortable) => T): Promise<T>; + reduce<T>( + fn: (previous: T, data: any, options?: Abortable) => T, + initial: T, + options?: Abortable, + ): Promise<T>; + _destroy(error: Error | null, callback: (error?: Error | null) => void): void; + /** + * Destroy the stream. Optionally emit an `'error'` event, and emit a `'close'` event (unless `emitClose` is set to `false`). After this call, the readable + * stream will release any internal resources and subsequent calls to `push()` will be ignored. + * + * Once `destroy()` has been called any further calls will be a no-op and no + * further errors except from `_destroy()` may be emitted as `'error'`. + * + * Implementors should not override this method, but instead implement `readable._destroy()`. + * @since v8.0.0 + * @param error Error which will be passed as payload in `'error'` event + */ + destroy(error?: Error): this; + /** + * @returns `AsyncIterator` to fully consume the stream. + * @since v10.0.0 + */ + [Symbol.asyncIterator](): NodeJS.AsyncIterator<any>; + /** + * Calls `readable.destroy()` with an `AbortError` and returns + * a promise that fulfills when the stream is finished. + * @since v20.4.0 + */ + [Symbol.asyncDispose](): Promise<void>; + // #region InternalEventEmitter + addListener<E extends keyof ReadableEventMap>( + eventName: E, + listener: (...args: ReadableEventMap[E]) => void, + ): this; + addListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + emit<E extends keyof ReadableEventMap>(eventName: E, ...args: ReadableEventMap[E]): boolean; + emit(eventName: string | symbol, ...args: any[]): boolean; + listenerCount<E extends keyof ReadableEventMap>( + eventName: E, + listener?: (...args: ReadableEventMap[E]) => void, + ): number; + listenerCount(eventName: string | symbol, listener?: (...args: any[]) => void): number; + listeners<E extends keyof ReadableEventMap>(eventName: E): ((...args: ReadableEventMap[E]) => void)[]; + listeners(eventName: string | symbol): ((...args: any[]) => void)[]; + off<E extends keyof ReadableEventMap>(eventName: E, listener: (...args: ReadableEventMap[E]) => void): this; + off(eventName: string | symbol, listener: (...args: any[]) => void): this; + on<E extends keyof ReadableEventMap>(eventName: E, listener: (...args: ReadableEventMap[E]) => void): this; + on(eventName: string | symbol, listener: (...args: any[]) => void): this; + once<E extends keyof ReadableEventMap>( + eventName: E, + listener: (...args: ReadableEventMap[E]) => void, + ): this; + once(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependListener<E extends keyof ReadableEventMap>( + eventName: E, + listener: (...args: ReadableEventMap[E]) => void, + ): this; + prependListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependOnceListener<E extends keyof ReadableEventMap>( + eventName: E, + listener: (...args: ReadableEventMap[E]) => void, + ): this; + prependOnceListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + rawListeners<E extends keyof ReadableEventMap>(eventName: E): ((...args: ReadableEventMap[E]) => void)[]; + rawListeners(eventName: string | symbol): ((...args: any[]) => void)[]; + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + removeAllListeners<E extends keyof ReadableEventMap>(eventName?: E): this; + removeAllListeners(eventName?: string | symbol): this; + removeListener<E extends keyof ReadableEventMap>( + eventName: E, + listener: (...args: ReadableEventMap[E]) => void, + ): this; + removeListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + // #endregion + } + interface WritableOptions<T extends Writable = Writable> extends StreamOptions<T> { + decodeStrings?: boolean | undefined; + defaultEncoding?: BufferEncoding | undefined; + write?: + | (( + this: T, + chunk: any, + encoding: BufferEncoding, + callback: (error?: Error | null) => void, + ) => void) + | undefined; + writev?: + | (( + this: T, + chunks: { + chunk: any; + encoding: BufferEncoding; + }[], + callback: (error?: Error | null) => void, + ) => void) + | undefined; + final?: ((this: T, callback: (error?: Error | null) => void) => void) | undefined; + } + interface WritableEventMap { + "close": []; + "drain": []; + "error": [err: Error]; + "finish": []; + "pipe": [src: Readable]; + "unpipe": [src: Readable]; + } + /** + * @since v0.9.4 + */ + class Writable extends Stream implements NodeJS.WritableStream { + constructor(options?: WritableOptions); + /** + * A utility method for creating a `Writable` from a web `WritableStream`. + * @since v17.0.0 + */ + static fromWeb( + writableStream: web.WritableStream, + options?: Pick<WritableOptions, "decodeStrings" | "highWaterMark" | "objectMode" | "signal">, + ): Writable; + /** + * A utility method for creating a web `WritableStream` from a `Writable`. + * @since v17.0.0 + */ + static toWeb(streamWritable: NodeJS.WritableStream): web.WritableStream; + /** + * Is `true` if it is safe to call `writable.write()`, which means + * the stream has not been destroyed, errored, or ended. + * @since v11.4.0 + */ + writable: boolean; + /** + * Returns whether the stream was destroyed or errored before emitting `'finish'`. + * @since v18.0.0, v16.17.0 + */ + readonly writableAborted: boolean; + /** + * Is `true` after `writable.end()` has been called. This property + * does not indicate whether the data has been flushed, for this use `writable.writableFinished` instead. + * @since v12.9.0 + */ + readonly writableEnded: boolean; + /** + * Is set to `true` immediately before the `'finish'` event is emitted. + * @since v12.6.0 + */ + readonly writableFinished: boolean; + /** + * Return the value of `highWaterMark` passed when creating this `Writable`. + * @since v9.3.0 + */ + readonly writableHighWaterMark: number; + /** + * This property contains the number of bytes (or objects) in the queue + * ready to be written. The value provides introspection data regarding + * the status of the `highWaterMark`. + * @since v9.4.0 + */ + readonly writableLength: number; + /** + * Getter for the property `objectMode` of a given `Writable` stream. + * @since v12.3.0 + */ + readonly writableObjectMode: boolean; + /** + * Number of times `writable.uncork()` needs to be + * called in order to fully uncork the stream. + * @since v13.2.0, v12.16.0 + */ + readonly writableCorked: number; + /** + * Is `true` after `writable.destroy()` has been called. + * @since v8.0.0 + */ + destroyed: boolean; + /** + * Is `true` after `'close'` has been emitted. + * @since v18.0.0 + */ + readonly closed: boolean; + /** + * Returns error if the stream has been destroyed with an error. + * @since v18.0.0 + */ + readonly errored: Error | null; + /** + * Is `true` if the stream's buffer has been full and stream will emit `'drain'`. + * @since v15.2.0, v14.17.0 + */ + readonly writableNeedDrain: boolean; + _write(chunk: any, encoding: BufferEncoding, callback: (error?: Error | null) => void): void; + _writev?( + chunks: { + chunk: any; + encoding: BufferEncoding; + }[], + callback: (error?: Error | null) => void, + ): void; + _construct?(callback: (error?: Error | null) => void): void; + _destroy(error: Error | null, callback: (error?: Error | null) => void): void; + _final(callback: (error?: Error | null) => void): void; + /** + * The `writable.write()` method writes some data to the stream, and calls the + * supplied `callback` once the data has been fully handled. If an error + * occurs, the `callback` will be called with the error as its + * first argument. The `callback` is called asynchronously and before `'error'` is + * emitted. + * + * The return value is `true` if the internal buffer is less than the `highWaterMark` configured when the stream was created after admitting `chunk`. + * If `false` is returned, further attempts to write data to the stream should + * stop until the `'drain'` event is emitted. + * + * While a stream is not draining, calls to `write()` will buffer `chunk`, and + * return false. Once all currently buffered chunks are drained (accepted for + * delivery by the operating system), the `'drain'` event will be emitted. + * Once `write()` returns false, do not write more chunks + * until the `'drain'` event is emitted. While calling `write()` on a stream that + * is not draining is allowed, Node.js will buffer all written chunks until + * maximum memory usage occurs, at which point it will abort unconditionally. + * Even before it aborts, high memory usage will cause poor garbage collector + * performance and high RSS (which is not typically released back to the system, + * even after the memory is no longer required). Since TCP sockets may never + * drain if the remote peer does not read the data, writing a socket that is + * not draining may lead to a remotely exploitable vulnerability. + * + * Writing data while the stream is not draining is particularly + * problematic for a `Transform`, because the `Transform` streams are paused + * by default until they are piped or a `'data'` or `'readable'` event handler + * is added. + * + * If the data to be written can be generated or fetched on demand, it is + * recommended to encapsulate the logic into a `Readable` and use {@link pipe}. However, if calling `write()` is preferred, it is + * possible to respect backpressure and avoid memory issues using the `'drain'` event: + * + * ```js + * function write(data, cb) { + * if (!stream.write(data)) { + * stream.once('drain', cb); + * } else { + * process.nextTick(cb); + * } + * } + * + * // Wait for cb to be called before doing any other write. + * write('hello', () => { + * console.log('Write completed, do more writes now.'); + * }); + * ``` + * + * A `Writable` stream in object mode will always ignore the `encoding` argument. + * @since v0.9.4 + * @param chunk Optional data to write. For streams not operating in object mode, `chunk` must be a {string}, {Buffer}, + * {TypedArray} or {DataView}. For object mode streams, `chunk` may be any JavaScript value other than `null`. + * @param [encoding='utf8'] The encoding, if `chunk` is a string. + * @param callback Callback for when this chunk of data is flushed. + * @return `false` if the stream wishes for the calling code to wait for the `'drain'` event to be emitted before continuing to write additional data; otherwise `true`. + */ + write(chunk: any, callback?: (error: Error | null | undefined) => void): boolean; + write(chunk: any, encoding: BufferEncoding, callback?: (error: Error | null | undefined) => void): boolean; + /** + * The `writable.setDefaultEncoding()` method sets the default `encoding` for a `Writable` stream. + * @since v0.11.15 + * @param encoding The new default encoding + */ + setDefaultEncoding(encoding: BufferEncoding): this; + /** + * Calling the `writable.end()` method signals that no more data will be written + * to the `Writable`. The optional `chunk` and `encoding` arguments allow one + * final additional chunk of data to be written immediately before closing the + * stream. + * + * Calling the {@link write} method after calling {@link end} will raise an error. + * + * ```js + * // Write 'hello, ' and then end with 'world!'. + * import fs from 'node:fs'; + * const file = fs.createWriteStream('example.txt'); + * file.write('hello, '); + * file.end('world!'); + * // Writing more now is not allowed! + * ``` + * @since v0.9.4 + * @param chunk Optional data to write. For streams not operating in object mode, `chunk` must be a {string}, {Buffer}, + * {TypedArray} or {DataView}. For object mode streams, `chunk` may be any JavaScript value other than `null`. + * @param encoding The encoding if `chunk` is a string + * @param callback Callback for when the stream is finished. + */ + end(cb?: () => void): this; + end(chunk: any, cb?: () => void): this; + end(chunk: any, encoding: BufferEncoding, cb?: () => void): this; + /** + * The `writable.cork()` method forces all written data to be buffered in memory. + * The buffered data will be flushed when either the {@link uncork} or {@link end} methods are called. + * + * The primary intent of `writable.cork()` is to accommodate a situation in which + * several small chunks are written to the stream in rapid succession. Instead of + * immediately forwarding them to the underlying destination, `writable.cork()` buffers all the chunks until `writable.uncork()` is called, which will pass them + * all to `writable._writev()`, if present. This prevents a head-of-line blocking + * situation where data is being buffered while waiting for the first small chunk + * to be processed. However, use of `writable.cork()` without implementing `writable._writev()` may have an adverse effect on throughput. + * + * See also: `writable.uncork()`, `writable._writev()`. + * @since v0.11.2 + */ + cork(): void; + /** + * The `writable.uncork()` method flushes all data buffered since {@link cork} was called. + * + * When using `writable.cork()` and `writable.uncork()` to manage the buffering + * of writes to a stream, defer calls to `writable.uncork()` using `process.nextTick()`. Doing so allows batching of all `writable.write()` calls that occur within a given Node.js event + * loop phase. + * + * ```js + * stream.cork(); + * stream.write('some '); + * stream.write('data '); + * process.nextTick(() => stream.uncork()); + * ``` + * + * If the `writable.cork()` method is called multiple times on a stream, the + * same number of calls to `writable.uncork()` must be called to flush the buffered + * data. + * + * ```js + * stream.cork(); + * stream.write('some '); + * stream.cork(); + * stream.write('data '); + * process.nextTick(() => { + * stream.uncork(); + * // The data will not be flushed until uncork() is called a second time. + * stream.uncork(); + * }); + * ``` + * + * See also: `writable.cork()`. + * @since v0.11.2 + */ + uncork(): void; + /** + * Destroy the stream. Optionally emit an `'error'` event, and emit a `'close'` event (unless `emitClose` is set to `false`). After this call, the writable + * stream has ended and subsequent calls to `write()` or `end()` will result in + * an `ERR_STREAM_DESTROYED` error. + * This is a destructive and immediate way to destroy a stream. Previous calls to `write()` may not have drained, and may trigger an `ERR_STREAM_DESTROYED` error. + * Use `end()` instead of destroy if data should flush before close, or wait for + * the `'drain'` event before destroying the stream. + * + * Once `destroy()` has been called any further calls will be a no-op and no + * further errors except from `_destroy()` may be emitted as `'error'`. + * + * Implementors should not override this method, + * but instead implement `writable._destroy()`. + * @since v8.0.0 + * @param error Optional, an error to emit with `'error'` event. + */ + destroy(error?: Error): this; + /** + * Calls `writable.destroy()` with an `AbortError` and returns + * a promise that fulfills when the stream is finished. + * @since v22.4.0, v20.16.0 + */ + [Symbol.asyncDispose](): Promise<void>; + // #region InternalEventEmitter + addListener<E extends keyof WritableEventMap>( + eventName: E, + listener: (...args: WritableEventMap[E]) => void, + ): this; + addListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + emit<E extends keyof WritableEventMap>(eventName: E, ...args: WritableEventMap[E]): boolean; + emit(eventName: string | symbol, ...args: any[]): boolean; + listenerCount<E extends keyof WritableEventMap>( + eventName: E, + listener?: (...args: WritableEventMap[E]) => void, + ): number; + listenerCount(eventName: string | symbol, listener?: (...args: any[]) => void): number; + listeners<E extends keyof WritableEventMap>(eventName: E): ((...args: WritableEventMap[E]) => void)[]; + listeners(eventName: string | symbol): ((...args: any[]) => void)[]; + off<E extends keyof WritableEventMap>(eventName: E, listener: (...args: WritableEventMap[E]) => void): this; + off(eventName: string | symbol, listener: (...args: any[]) => void): this; + on<E extends keyof WritableEventMap>(eventName: E, listener: (...args: WritableEventMap[E]) => void): this; + on(eventName: string | symbol, listener: (...args: any[]) => void): this; + once<E extends keyof WritableEventMap>( + eventName: E, + listener: (...args: WritableEventMap[E]) => void, + ): this; + once(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependListener<E extends keyof WritableEventMap>( + eventName: E, + listener: (...args: WritableEventMap[E]) => void, + ): this; + prependListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependOnceListener<E extends keyof WritableEventMap>( + eventName: E, + listener: (...args: WritableEventMap[E]) => void, + ): this; + prependOnceListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + rawListeners<E extends keyof WritableEventMap>(eventName: E): ((...args: WritableEventMap[E]) => void)[]; + rawListeners(eventName: string | symbol): ((...args: any[]) => void)[]; + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + removeAllListeners<E extends keyof WritableEventMap>(eventName?: E): this; + removeAllListeners(eventName?: string | symbol): this; + removeListener<E extends keyof WritableEventMap>( + eventName: E, + listener: (...args: WritableEventMap[E]) => void, + ): this; + removeListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + // #endregion + } + interface DuplexOptions<T extends Duplex = Duplex> extends ReadableOptions<T>, WritableOptions<T> { + allowHalfOpen?: boolean | undefined; + readableObjectMode?: boolean | undefined; + writableObjectMode?: boolean | undefined; + readableHighWaterMark?: number | undefined; + writableHighWaterMark?: number | undefined; + writableCorked?: number | undefined; + } + interface DuplexEventMap extends ReadableEventMap, WritableEventMap {} + /** + * Duplex streams are streams that implement both the `Readable` and `Writable` interfaces. + * + * Examples of `Duplex` streams include: + * + * * `TCP sockets` + * * `zlib streams` + * * `crypto streams` + * @since v0.9.4 + */ + class Duplex extends Stream implements NodeJS.ReadWriteStream { + constructor(options?: DuplexOptions); + /** + * A utility method for creating duplex streams. + * + * - `Stream` converts writable stream into writable `Duplex` and readable stream + * to `Duplex`. + * - `Blob` converts into readable `Duplex`. + * - `string` converts into readable `Duplex`. + * - `ArrayBuffer` converts into readable `Duplex`. + * - `AsyncIterable` converts into a readable `Duplex`. Cannot yield `null`. + * - `AsyncGeneratorFunction` converts into a readable/writable transform + * `Duplex`. Must take a source `AsyncIterable` as first parameter. Cannot yield + * `null`. + * - `AsyncFunction` converts into a writable `Duplex`. Must return + * either `null` or `undefined` + * - `Object ({ writable, readable })` converts `readable` and + * `writable` into `Stream` and then combines them into `Duplex` where the + * `Duplex` will write to the `writable` and read from the `readable`. + * - `Promise` converts into readable `Duplex`. Value `null` is ignored. + * + * @since v16.8.0 + */ + static from( + src: + | NodeJS.ReadableStream + | NodeJS.WritableStream + | Blob + | string + | Iterable<any> + | AsyncIterable<any> + | ((source: AsyncIterable<any>) => AsyncIterable<any>) + | ((source: AsyncIterable<any>) => Promise<void>) + | Promise<any> + | web.ReadableWritablePair + | web.ReadableStream + | web.WritableStream, + ): Duplex; + /** + * A utility method for creating a web `ReadableStream` and `WritableStream` from a `Duplex`. + * @since v17.0.0 + */ + static toWeb(streamDuplex: NodeJS.ReadWriteStream): web.ReadableWritablePair; + /** + * A utility method for creating a `Duplex` from a web `ReadableStream` and `WritableStream`. + * @since v17.0.0 + */ + static fromWeb( + duplexStream: web.ReadableWritablePair, + options?: Pick< + DuplexOptions, + "allowHalfOpen" | "decodeStrings" | "encoding" | "highWaterMark" | "objectMode" | "signal" + >, + ): Duplex; + /** + * If `false` then the stream will automatically end the writable side when the + * readable side ends. Set initially by the `allowHalfOpen` constructor option, + * which defaults to `true`. + * + * This can be changed manually to change the half-open behavior of an existing + * `Duplex` stream instance, but must be changed before the `'end'` event is emitted. + * @since v0.9.4 + */ + allowHalfOpen: boolean; + // #region InternalEventEmitter + addListener<E extends keyof DuplexEventMap>( + eventName: E, + listener: (...args: DuplexEventMap[E]) => void, + ): this; + addListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + emit<E extends keyof DuplexEventMap>(eventName: E, ...args: DuplexEventMap[E]): boolean; + emit(eventName: string | symbol, ...args: any[]): boolean; + listenerCount<E extends keyof DuplexEventMap>( + eventName: E, + listener?: (...args: DuplexEventMap[E]) => void, + ): number; + listenerCount(eventName: string | symbol, listener?: (...args: any[]) => void): number; + listeners<E extends keyof DuplexEventMap>(eventName: E): ((...args: DuplexEventMap[E]) => void)[]; + listeners(eventName: string | symbol): ((...args: any[]) => void)[]; + off<E extends keyof DuplexEventMap>(eventName: E, listener: (...args: DuplexEventMap[E]) => void): this; + off(eventName: string | symbol, listener: (...args: any[]) => void): this; + on<E extends keyof DuplexEventMap>(eventName: E, listener: (...args: DuplexEventMap[E]) => void): this; + on(eventName: string | symbol, listener: (...args: any[]) => void): this; + once<E extends keyof DuplexEventMap>(eventName: E, listener: (...args: DuplexEventMap[E]) => void): this; + once(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependListener<E extends keyof DuplexEventMap>( + eventName: E, + listener: (...args: DuplexEventMap[E]) => void, + ): this; + prependListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependOnceListener<E extends keyof DuplexEventMap>( + eventName: E, + listener: (...args: DuplexEventMap[E]) => void, + ): this; + prependOnceListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + rawListeners<E extends keyof DuplexEventMap>(eventName: E): ((...args: DuplexEventMap[E]) => void)[]; + rawListeners(eventName: string | symbol): ((...args: any[]) => void)[]; + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + removeAllListeners<E extends keyof DuplexEventMap>(eventName?: E): this; + removeAllListeners(eventName?: string | symbol): this; + removeListener<E extends keyof DuplexEventMap>( + eventName: E, + listener: (...args: DuplexEventMap[E]) => void, + ): this; + removeListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + // #endregion + } + interface Duplex extends Readable, Writable {} + /** + * The utility function `duplexPair` returns an Array with two items, + * each being a `Duplex` stream connected to the other side: + * + * ```js + * const [ sideA, sideB ] = duplexPair(); + * ``` + * + * Whatever is written to one stream is made readable on the other. It provides + * behavior analogous to a network connection, where the data written by the client + * becomes readable by the server, and vice-versa. + * + * The Duplex streams are symmetrical; one or the other may be used without any + * difference in behavior. + * @param options A value to pass to both {@link Duplex} constructors, + * to set options such as buffering. + * @since v22.6.0 + */ + function duplexPair(options?: DuplexOptions): [Duplex, Duplex]; + type TransformCallback = (error?: Error | null, data?: any) => void; + interface TransformOptions<T extends Transform = Transform> extends DuplexOptions<T> { + transform?: + | ((this: T, chunk: any, encoding: BufferEncoding, callback: TransformCallback) => void) + | undefined; + flush?: ((this: T, callback: TransformCallback) => void) | undefined; + } + /** + * Transform streams are `Duplex` streams where the output is in some way + * related to the input. Like all `Duplex` streams, `Transform` streams + * implement both the `Readable` and `Writable` interfaces. + * + * Examples of `Transform` streams include: + * + * * `zlib streams` + * * `crypto streams` + * @since v0.9.4 + */ + class Transform extends Duplex { + constructor(options?: TransformOptions); + _transform(chunk: any, encoding: BufferEncoding, callback: TransformCallback): void; + _flush(callback: TransformCallback): void; + } + /** + * The `stream.PassThrough` class is a trivial implementation of a `Transform` stream that simply passes the input bytes across to the output. Its purpose is + * primarily for examples and testing, but there are some use cases where `stream.PassThrough` is useful as a building block for novel sorts of streams. + */ + class PassThrough extends Transform {} + /** + * A stream to attach a signal to. + * + * Attaches an AbortSignal to a readable or writeable stream. This lets code + * control stream destruction using an `AbortController`. + * + * Calling `abort` on the `AbortController` corresponding to the passed `AbortSignal` will behave the same way as calling `.destroy(new AbortError())` on the + * stream, and `controller.error(new AbortError())` for webstreams. + * + * ```js + * import fs from 'node:fs'; + * + * const controller = new AbortController(); + * const read = addAbortSignal( + * controller.signal, + * fs.createReadStream(('object.json')), + * ); + * // Later, abort the operation closing the stream + * controller.abort(); + * ``` + * + * Or using an `AbortSignal` with a readable stream as an async iterable: + * + * ```js + * const controller = new AbortController(); + * setTimeout(() => controller.abort(), 10_000); // set a timeout + * const stream = addAbortSignal( + * controller.signal, + * fs.createReadStream(('object.json')), + * ); + * (async () => { + * try { + * for await (const chunk of stream) { + * await process(chunk); + * } + * } catch (e) { + * if (e.name === 'AbortError') { + * // The operation was cancelled + * } else { + * throw e; + * } + * } + * })(); + * ``` + * + * Or using an `AbortSignal` with a ReadableStream: + * + * ```js + * const controller = new AbortController(); + * const rs = new ReadableStream({ + * start(controller) { + * controller.enqueue('hello'); + * controller.enqueue('world'); + * controller.close(); + * }, + * }); + * + * addAbortSignal(controller.signal, rs); + * + * finished(rs, (err) => { + * if (err) { + * if (err.name === 'AbortError') { + * // The operation was cancelled + * } + * } + * }); + * + * const reader = rs.getReader(); + * + * reader.read().then(({ value, done }) => { + * console.log(value); // hello + * console.log(done); // false + * controller.abort(); + * }); + * ``` + * @since v15.4.0 + * @param signal A signal representing possible cancellation + * @param stream A stream to attach a signal to. + */ + function addAbortSignal< + T extends NodeJS.ReadableStream | NodeJS.WritableStream | web.ReadableStream | web.WritableStream, + >(signal: AbortSignal, stream: T): T; + /** + * Returns the default highWaterMark used by streams. + * Defaults to `65536` (64 KiB), or `16` for `objectMode`. + * @since v19.9.0 + */ + function getDefaultHighWaterMark(objectMode: boolean): number; + /** + * Sets the default highWaterMark used by streams. + * @since v19.9.0 + * @param value highWaterMark value + */ + function setDefaultHighWaterMark(objectMode: boolean, value: number): void; + interface FinishedOptions extends Abortable { + error?: boolean | undefined; + readable?: boolean | undefined; + writable?: boolean | undefined; + } + /** + * A readable and/or writable stream/webstream. + * + * A function to get notified when a stream is no longer readable, writable + * or has experienced an error or a premature close event. + * + * ```js + * import { finished } from 'node:stream'; + * import fs from 'node:fs'; + * + * const rs = fs.createReadStream('archive.tar'); + * + * finished(rs, (err) => { + * if (err) { + * console.error('Stream failed.', err); + * } else { + * console.log('Stream is done reading.'); + * } + * }); + * + * rs.resume(); // Drain the stream. + * ``` + * + * Especially useful in error handling scenarios where a stream is destroyed + * prematurely (like an aborted HTTP request), and will not emit `'end'` or `'finish'`. + * + * The `finished` API provides [`promise version`](https://nodejs.org/docs/latest-v25.x/api/stream.html#streamfinishedstream-options). + * + * `stream.finished()` leaves dangling event listeners (in particular `'error'`, `'end'`, `'finish'` and `'close'`) after `callback` has been + * invoked. The reason for this is so that unexpected `'error'` events (due to + * incorrect stream implementations) do not cause unexpected crashes. + * If this is unwanted behavior then the returned cleanup function needs to be + * invoked in the callback: + * + * ```js + * const cleanup = finished(rs, (err) => { + * cleanup(); + * // ... + * }); + * ``` + * @since v10.0.0 + * @param stream A readable and/or writable stream. + * @param callback A callback function that takes an optional error argument. + * @returns A cleanup function which removes all registered listeners. + */ + function finished( + stream: NodeJS.ReadableStream | NodeJS.WritableStream | web.ReadableStream | web.WritableStream, + options: FinishedOptions, + callback: (err?: NodeJS.ErrnoException | null) => void, + ): () => void; + function finished( + stream: NodeJS.ReadableStream | NodeJS.WritableStream | web.ReadableStream | web.WritableStream, + callback: (err?: NodeJS.ErrnoException | null) => void, + ): () => void; + namespace finished { + import __promisify__ = promises.finished; + export { __promisify__ }; + } + type PipelineSourceFunction<O> = (options?: Abortable) => Iterable<O> | AsyncIterable<O>; + type PipelineSource<O> = + | NodeJS.ReadableStream + | web.ReadableStream<O> + | web.TransformStream<any, O> + | Iterable<O> + | AsyncIterable<O> + | PipelineSourceFunction<O>; + type PipelineSourceArgument<T> = (T extends (...args: any[]) => infer R ? R : T) extends infer S + ? S extends web.TransformStream<any, infer O> ? web.ReadableStream<O> : S + : never; + type PipelineTransformGenerator<S extends PipelineTransformSource<any>, O> = ( + source: PipelineSourceArgument<S>, + options?: Abortable, + ) => AsyncIterable<O>; + type PipelineTransformStreams<I, O> = + | NodeJS.ReadWriteStream + | web.TransformStream<I, O>; + type PipelineTransform<S extends PipelineTransformSource<any>, O> = S extends + PipelineSource<infer I> | PipelineTransformStreams<any, infer I> | ((...args: any[]) => infer I) + ? PipelineTransformStreams<I, O> | PipelineTransformGenerator<S, O> + : never; + type PipelineTransformSource<O> = PipelineSource<O> | PipelineTransform<any, O>; + type PipelineDestinationFunction<S extends PipelineTransformSource<any>, R> = ( + source: PipelineSourceArgument<S>, + options?: Abortable, + ) => R; + type PipelineDestination<S extends PipelineTransformSource<any>, R> = S extends + PipelineSource<infer I> | PipelineTransform<any, infer I> ? + | NodeJS.WritableStream + | web.WritableStream<I> + | web.TransformStream<I, any> + | PipelineDestinationFunction<S, R> + : never; + type PipelineCallback<S extends PipelineDestination<any, any>> = ( + err: NodeJS.ErrnoException | null, + value: S extends (...args: any[]) => PromiseLike<infer R> ? R : undefined, + ) => void; + type PipelineResult<S extends PipelineDestination<any, any>> = S extends NodeJS.WritableStream ? S : Duplex; + /** + * A module method to pipe between streams and generators forwarding errors and + * properly cleaning up and provide a callback when the pipeline is complete. + * + * ```js + * import { pipeline } from 'node:stream'; + * import fs from 'node:fs'; + * import zlib from 'node:zlib'; + * + * // Use the pipeline API to easily pipe a series of streams + * // together and get notified when the pipeline is fully done. + * + * // A pipeline to gzip a potentially huge tar file efficiently: + * + * pipeline( + * fs.createReadStream('archive.tar'), + * zlib.createGzip(), + * fs.createWriteStream('archive.tar.gz'), + * (err) => { + * if (err) { + * console.error('Pipeline failed.', err); + * } else { + * console.log('Pipeline succeeded.'); + * } + * }, + * ); + * ``` + * + * The `pipeline` API provides a [`promise version`](https://nodejs.org/docs/latest-v25.x/api/stream.html#streampipelinesource-transforms-destination-options). + * + * `stream.pipeline()` will call `stream.destroy(err)` on all streams except: + * + * * `Readable` streams which have emitted `'end'` or `'close'`. + * * `Writable` streams which have emitted `'finish'` or `'close'`. + * + * `stream.pipeline()` leaves dangling event listeners on the streams + * after the `callback` has been invoked. In the case of reuse of streams after + * failure, this can cause event listener leaks and swallowed errors. If the last + * stream is readable, dangling event listeners will be removed so that the last + * stream can be consumed later. + * + * `stream.pipeline()` closes all the streams when an error is raised. + * The `IncomingRequest` usage with `pipeline` could lead to an unexpected behavior + * once it would destroy the socket without sending the expected response. + * See the example below: + * + * ```js + * import fs from 'node:fs'; + * import http from 'node:http'; + * import { pipeline } from 'node:stream'; + * + * const server = http.createServer((req, res) => { + * const fileStream = fs.createReadStream('./fileNotExist.txt'); + * pipeline(fileStream, res, (err) => { + * if (err) { + * console.log(err); // No such file + * // this message can't be sent once `pipeline` already destroyed the socket + * return res.end('error!!!'); + * } + * }); + * }); + * ``` + * @since v10.0.0 + * @param callback Called when the pipeline is fully done. + */ + function pipeline<S extends PipelineSource<any>, D extends PipelineDestination<S, any>>( + source: S, + destination: D, + callback: PipelineCallback<D>, + ): PipelineResult<D>; + function pipeline< + S extends PipelineSource<any>, + T extends PipelineTransform<S, any>, + D extends PipelineDestination<T, any>, + >( + source: S, + transform: T, + destination: D, + callback: PipelineCallback<D>, + ): PipelineResult<D>; + function pipeline< + S extends PipelineSource<any>, + T1 extends PipelineTransform<S, any>, + T2 extends PipelineTransform<T1, any>, + D extends PipelineDestination<T2, any>, + >( + source: S, + transform1: T1, + transform2: T2, + destination: D, + callback: PipelineCallback<D>, + ): PipelineResult<D>; + function pipeline< + S extends PipelineSource<any>, + T1 extends PipelineTransform<S, any>, + T2 extends PipelineTransform<T1, any>, + T3 extends PipelineTransform<T2, any>, + D extends PipelineDestination<T3, any>, + >( + source: S, + transform1: T1, + transform2: T2, + transform3: T3, + destination: D, + callback: PipelineCallback<D>, + ): PipelineResult<D>; + function pipeline< + S extends PipelineSource<any>, + T1 extends PipelineTransform<S, any>, + T2 extends PipelineTransform<T1, any>, + T3 extends PipelineTransform<T2, any>, + T4 extends PipelineTransform<T3, any>, + D extends PipelineDestination<T4, any>, + >( + source: S, + transform1: T1, + transform2: T2, + transform3: T3, + transform4: T4, + destination: D, + callback: PipelineCallback<D>, + ): PipelineResult<D>; + function pipeline( + streams: ReadonlyArray<PipelineSource<any> | PipelineTransform<any, any> | PipelineDestination<any, any>>, + callback: (err: NodeJS.ErrnoException | null) => void, + ): NodeJS.WritableStream; + function pipeline( + ...streams: [ + ...[PipelineSource<any>, ...PipelineTransform<any, any>[], PipelineDestination<any, any>], + callback: ((err: NodeJS.ErrnoException | null) => void), + ] + ): NodeJS.WritableStream; + namespace pipeline { + import __promisify__ = promises.pipeline; + export { __promisify__ }; + } + type ComposeSource<O> = + | NodeJS.ReadableStream + | web.ReadableStream<O> + | Iterable<O> + | AsyncIterable<O> + | (() => AsyncIterable<O>); + type ComposeTransformStreams<I, O> = NodeJS.ReadWriteStream | web.TransformStream<I, O>; + type ComposeTransformGenerator<I, O> = (source: AsyncIterable<I>) => AsyncIterable<O>; + type ComposeTransform<S extends ComposeTransformSource<any>, O> = S extends + ComposeSource<infer I> | ComposeTransformStreams<any, infer I> | ComposeTransformGenerator<any, infer I> + ? ComposeTransformStreams<I, O> | ComposeTransformGenerator<I, O> + : never; + type ComposeTransformSource<O> = ComposeSource<O> | ComposeTransform<any, O>; + type ComposeDestination<S extends ComposeTransformSource<any>> = S extends ComposeTransformSource<infer I> ? + | NodeJS.WritableStream + | web.WritableStream<I> + | web.TransformStream<I, any> + | ((source: AsyncIterable<I>) => void) + : never; + /** + * Combines two or more streams into a `Duplex` stream that writes to the + * first stream and reads from the last. Each provided stream is piped into + * the next, using `stream.pipeline`. If any of the streams error then all + * are destroyed, including the outer `Duplex` stream. + * + * Because `stream.compose` returns a new stream that in turn can (and + * should) be piped into other streams, it enables composition. In contrast, + * when passing streams to `stream.pipeline`, typically the first stream is + * a readable stream and the last a writable stream, forming a closed + * circuit. + * + * If passed a `Function` it must be a factory method taking a `source` + * `Iterable`. + * + * ```js + * import { compose, Transform } from 'node:stream'; + * + * const removeSpaces = new Transform({ + * transform(chunk, encoding, callback) { + * callback(null, String(chunk).replace(' ', '')); + * }, + * }); + * + * async function* toUpper(source) { + * for await (const chunk of source) { + * yield String(chunk).toUpperCase(); + * } + * } + * + * let res = ''; + * for await (const buf of compose(removeSpaces, toUpper).end('hello world')) { + * res += buf; + * } + * + * console.log(res); // prints 'HELLOWORLD' + * ``` + * + * `stream.compose` can be used to convert async iterables, generators and + * functions into streams. + * + * * `AsyncIterable` converts into a readable `Duplex`. Cannot yield + * `null`. + * * `AsyncGeneratorFunction` converts into a readable/writable transform `Duplex`. + * Must take a source `AsyncIterable` as first parameter. Cannot yield + * `null`. + * * `AsyncFunction` converts into a writable `Duplex`. Must return + * either `null` or `undefined`. + * + * ```js + * import { compose } from 'node:stream'; + * import { finished } from 'node:stream/promises'; + * + * // Convert AsyncIterable into readable Duplex. + * const s1 = compose(async function*() { + * yield 'Hello'; + * yield 'World'; + * }()); + * + * // Convert AsyncGenerator into transform Duplex. + * const s2 = compose(async function*(source) { + * for await (const chunk of source) { + * yield String(chunk).toUpperCase(); + * } + * }); + * + * let res = ''; + * + * // Convert AsyncFunction into writable Duplex. + * const s3 = compose(async function(source) { + * for await (const chunk of source) { + * res += chunk; + * } + * }); + * + * await finished(compose(s1, s2, s3)); + * + * console.log(res); // prints 'HELLOWORLD' + * ``` + * + * See [`readable.compose(stream)`](https://nodejs.org/docs/latest-v25.x/api/stream.html#readablecomposestream-options) for `stream.compose` as operator. + * @since v16.9.0 + * @experimental + */ + /* eslint-disable @definitelytyped/no-unnecessary-generics */ + function compose(stream: ComposeSource<any> | ComposeDestination<any>): Duplex; + function compose< + S extends ComposeSource<any> | ComposeTransform<any, any>, + D extends ComposeTransform<S, any> | ComposeDestination<S>, + >( + source: S, + destination: D, + ): Duplex; + function compose< + S extends ComposeSource<any> | ComposeTransform<any, any>, + T extends ComposeTransform<S, any>, + D extends ComposeTransform<T, any> | ComposeDestination<T>, + >(source: S, transform: T, destination: D): Duplex; + function compose< + S extends ComposeSource<any> | ComposeTransform<any, any>, + T1 extends ComposeTransform<S, any>, + T2 extends ComposeTransform<T1, any>, + D extends ComposeTransform<T2, any> | ComposeDestination<T2>, + >(source: S, transform1: T1, transform2: T2, destination: D): Duplex; + function compose< + S extends ComposeSource<any> | ComposeTransform<any, any>, + T1 extends ComposeTransform<S, any>, + T2 extends ComposeTransform<T1, any>, + T3 extends ComposeTransform<T2, any>, + D extends ComposeTransform<T3, any> | ComposeDestination<T3>, + >(source: S, transform1: T1, transform2: T2, transform3: T3, destination: D): Duplex; + function compose< + S extends ComposeSource<any> | ComposeTransform<any, any>, + T1 extends ComposeTransform<S, any>, + T2 extends ComposeTransform<T1, any>, + T3 extends ComposeTransform<T2, any>, + T4 extends ComposeTransform<T3, any>, + D extends ComposeTransform<T4, any> | ComposeDestination<T4>, + >(source: S, transform1: T1, transform2: T2, transform3: T3, transform4: T4, destination: D): Duplex; + function compose( + ...streams: [ + ComposeSource<any>, + ...ComposeTransform<any, any>[], + ComposeDestination<any>, + ] + ): Duplex; + /* eslint-enable @definitelytyped/no-unnecessary-generics */ + /** + * Returns whether the stream has encountered an error. + * @since v17.3.0, v16.14.0 + */ + function isErrored( + stream: NodeJS.ReadableStream | NodeJS.WritableStream | web.ReadableStream | web.WritableStream, + ): boolean; + /** + * Returns whether the stream is readable. + * @since v17.4.0, v16.14.0 + * @returns Only returns `null` if `stream` is not a valid `Readable`, `Duplex` or `ReadableStream`. + */ + function isReadable(stream: NodeJS.ReadableStream | web.ReadableStream): boolean | null; + /** + * Returns whether the stream is writable. + * @since v20.0.0 + * @returns Only returns `null` if `stream` is not a valid `Writable`, `Duplex` or `WritableStream`. + */ + function isWritable(stream: NodeJS.WritableStream | web.WritableStream): boolean | null; + } + global { + namespace NodeJS { + // These interfaces are vestigial, and correspond roughly to the "streams2" interfaces + // from early versions of Node.js, but they are still used widely across the ecosystem. + // Accordingly, they are commonly used as "in-types" for @types/node APIs, so that + // eg. streams returned from older libraries will still be considered valid input to + // functions which accept stream arguments. + // It's not possible to change or remove these without astronomical levels of breakage. + interface ReadableStream extends EventEmitter { + readable: boolean; + read(size?: number): string | Buffer; + setEncoding(encoding: BufferEncoding): this; + pause(): this; + resume(): this; + isPaused(): boolean; + pipe<T extends WritableStream>(destination: T, options?: { end?: boolean | undefined }): T; + unpipe(destination?: WritableStream): this; + unshift(chunk: string | Uint8Array, encoding?: BufferEncoding): void; + wrap(oldStream: ReadableStream): this; + [Symbol.asyncIterator](): AsyncIterableIterator<string | Buffer>; + } + interface WritableStream extends EventEmitter { + writable: boolean; + write(buffer: Uint8Array | string, cb?: (err?: Error | null) => void): boolean; + write(str: string, encoding?: BufferEncoding, cb?: (err?: Error | null) => void): boolean; + end(cb?: () => void): this; + end(data: string | Uint8Array, cb?: () => void): this; + end(str: string, encoding?: BufferEncoding, cb?: () => void): this; + } + interface ReadWriteStream extends ReadableStream, WritableStream {} + } + } + export = Stream; +} +declare module "stream" { + import stream = require("node:stream"); + export = stream; +} diff --git a/server/node_modules/@types/node/stream/consumers.d.ts b/server/node_modules/@types/node/stream/consumers.d.ts new file mode 100644 index 0000000..97f260d --- /dev/null +++ b/server/node_modules/@types/node/stream/consumers.d.ts @@ -0,0 +1,38 @@ +/** + * The utility consumer functions provide common options for consuming + * streams. + * @since v16.7.0 + */ +declare module "node:stream/consumers" { + import { Blob, NonSharedBuffer } from "node:buffer"; + import { ReadableStream } from "node:stream/web"; + /** + * @since v16.7.0 + * @returns Fulfills with an `ArrayBuffer` containing the full contents of the stream. + */ + function arrayBuffer(stream: ReadableStream | NodeJS.ReadableStream | AsyncIterable<any>): Promise<ArrayBuffer>; + /** + * @since v16.7.0 + * @returns Fulfills with a `Blob` containing the full contents of the stream. + */ + function blob(stream: ReadableStream | NodeJS.ReadableStream | AsyncIterable<any>): Promise<Blob>; + /** + * @since v16.7.0 + * @returns Fulfills with a `Buffer` containing the full contents of the stream. + */ + function buffer(stream: ReadableStream | NodeJS.ReadableStream | AsyncIterable<any>): Promise<NonSharedBuffer>; + /** + * @since v16.7.0 + * @returns Fulfills with the contents of the stream parsed as a + * UTF-8 encoded string that is then passed through `JSON.parse()`. + */ + function json(stream: ReadableStream | NodeJS.ReadableStream | AsyncIterable<any>): Promise<unknown>; + /** + * @since v16.7.0 + * @returns Fulfills with the contents of the stream parsed as a UTF-8 encoded string. + */ + function text(stream: ReadableStream | NodeJS.ReadableStream | AsyncIterable<any>): Promise<string>; +} +declare module "stream/consumers" { + export * from "node:stream/consumers"; +} diff --git a/server/node_modules/@types/node/stream/promises.d.ts b/server/node_modules/@types/node/stream/promises.d.ts new file mode 100644 index 0000000..c4bd3ea --- /dev/null +++ b/server/node_modules/@types/node/stream/promises.d.ts @@ -0,0 +1,211 @@ +declare module "node:stream/promises" { + import { Abortable } from "node:events"; + import { + FinishedOptions as _FinishedOptions, + PipelineDestination, + PipelineSource, + PipelineTransform, + } from "node:stream"; + import { ReadableStream, WritableStream } from "node:stream/web"; + interface FinishedOptions extends _FinishedOptions { + /** + * If true, removes the listeners registered by this function before the promise is fulfilled. + * @default false + */ + cleanup?: boolean | undefined; + } + /** + * ```js + * import { finished } from 'node:stream/promises'; + * import { createReadStream } from 'node:fs'; + * + * const rs = createReadStream('archive.tar'); + * + * async function run() { + * await finished(rs); + * console.log('Stream is done reading.'); + * } + * + * run().catch(console.error); + * rs.resume(); // Drain the stream. + * ``` + * + * The `finished` API also provides a [callback version](https://nodejs.org/docs/latest-v25.x/api/stream.html#streamfinishedstream-options-callback). + * + * `stream.finished()` leaves dangling event listeners (in particular + * `'error'`, `'end'`, `'finish'` and `'close'`) after the returned promise is + * resolved or rejected. The reason for this is so that unexpected `'error'` + * events (due to incorrect stream implementations) do not cause unexpected + * crashes. If this is unwanted behavior then `options.cleanup` should be set to + * `true`: + * + * ```js + * await finished(rs, { cleanup: true }); + * ``` + * @since v15.0.0 + * @returns Fulfills when the stream is no longer readable or writable. + */ + function finished( + stream: NodeJS.ReadableStream | NodeJS.WritableStream | ReadableStream | WritableStream, + options?: FinishedOptions, + ): Promise<void>; + interface PipelineOptions extends Abortable { + end?: boolean | undefined; + } + type PipelineResult<S extends PipelineDestination<any, any>> = S extends (...args: any[]) => PromiseLike<infer R> + ? Promise<R> + : Promise<void>; + /** + * ```js + * import { pipeline } from 'node:stream/promises'; + * import { createReadStream, createWriteStream } from 'node:fs'; + * import { createGzip } from 'node:zlib'; + * + * await pipeline( + * createReadStream('archive.tar'), + * createGzip(), + * createWriteStream('archive.tar.gz'), + * ); + * console.log('Pipeline succeeded.'); + * ``` + * + * To use an `AbortSignal`, pass it inside an options object, as the last argument. + * When the signal is aborted, `destroy` will be called on the underlying pipeline, + * with an `AbortError`. + * + * ```js + * import { pipeline } from 'node:stream/promises'; + * import { createReadStream, createWriteStream } from 'node:fs'; + * import { createGzip } from 'node:zlib'; + * + * const ac = new AbortController(); + * const { signal } = ac; + * setImmediate(() => ac.abort()); + * try { + * await pipeline( + * createReadStream('archive.tar'), + * createGzip(), + * createWriteStream('archive.tar.gz'), + * { signal }, + * ); + * } catch (err) { + * console.error(err); // AbortError + * } + * ``` + * + * The `pipeline` API also supports async generators: + * + * ```js + * import { pipeline } from 'node:stream/promises'; + * import { createReadStream, createWriteStream } from 'node:fs'; + * + * await pipeline( + * createReadStream('lowercase.txt'), + * async function* (source, { signal }) { + * source.setEncoding('utf8'); // Work with strings rather than `Buffer`s. + * for await (const chunk of source) { + * yield await processChunk(chunk, { signal }); + * } + * }, + * createWriteStream('uppercase.txt'), + * ); + * console.log('Pipeline succeeded.'); + * ``` + * + * Remember to handle the `signal` argument passed into the async generator. + * Especially in the case where the async generator is the source for the + * pipeline (i.e. first argument) or the pipeline will never complete. + * + * ```js + * import { pipeline } from 'node:stream/promises'; + * import fs from 'node:fs'; + * await pipeline( + * async function* ({ signal }) { + * await someLongRunningfn({ signal }); + * yield 'asd'; + * }, + * fs.createWriteStream('uppercase.txt'), + * ); + * console.log('Pipeline succeeded.'); + * ``` + * + * The `pipeline` API provides [callback version](https://nodejs.org/docs/latest-v25.x/api/stream.html#streampipelinesource-transforms-destination-callback): + * @since v15.0.0 + * @returns Fulfills when the pipeline is complete. + */ + function pipeline<A extends PipelineSource<any>, B extends PipelineDestination<A, any>>( + source: A, + destination: B, + options?: PipelineOptions, + ): PipelineResult<B>; + function pipeline< + A extends PipelineSource<any>, + T1 extends PipelineTransform<A, any>, + B extends PipelineDestination<T1, any>, + >( + source: A, + transform1: T1, + destination: B, + options?: PipelineOptions, + ): PipelineResult<B>; + function pipeline< + A extends PipelineSource<any>, + T1 extends PipelineTransform<A, any>, + T2 extends PipelineTransform<T1, any>, + B extends PipelineDestination<T2, any>, + >( + source: A, + transform1: T1, + transform2: T2, + destination: B, + options?: PipelineOptions, + ): PipelineResult<B>; + function pipeline< + A extends PipelineSource<any>, + T1 extends PipelineTransform<A, any>, + T2 extends PipelineTransform<T1, any>, + T3 extends PipelineTransform<T2, any>, + B extends PipelineDestination<T3, any>, + >( + source: A, + transform1: T1, + transform2: T2, + transform3: T3, + destination: B, + options?: PipelineOptions, + ): PipelineResult<B>; + function pipeline< + A extends PipelineSource<any>, + T1 extends PipelineTransform<A, any>, + T2 extends PipelineTransform<T1, any>, + T3 extends PipelineTransform<T2, any>, + T4 extends PipelineTransform<T3, any>, + B extends PipelineDestination<T4, any>, + >( + source: A, + transform1: T1, + transform2: T2, + transform3: T3, + transform4: T4, + destination: B, + options?: PipelineOptions, + ): PipelineResult<B>; + function pipeline( + streams: readonly [PipelineSource<any>, ...PipelineTransform<any, any>[], PipelineDestination<any, any>], + options?: PipelineOptions, + ): Promise<void>; + function pipeline( + ...streams: [PipelineSource<any>, ...PipelineTransform<any, any>[], PipelineDestination<any, any>] + ): Promise<void>; + function pipeline( + ...streams: [ + PipelineSource<any>, + ...PipelineTransform<any, any>[], + PipelineDestination<any, any>, + options: PipelineOptions, + ] + ): Promise<void>; +} +declare module "stream/promises" { + export * from "node:stream/promises"; +} diff --git a/server/node_modules/@types/node/stream/web.d.ts b/server/node_modules/@types/node/stream/web.d.ts new file mode 100644 index 0000000..32ce406 --- /dev/null +++ b/server/node_modules/@types/node/stream/web.d.ts @@ -0,0 +1,296 @@ +declare module "node:stream/web" { + import { TextDecoderCommon, TextDecoderOptions, TextEncoderCommon } from "node:util"; + type CompressionFormat = "brotli" | "deflate" | "deflate-raw" | "gzip"; + type ReadableStreamController<T> = ReadableStreamDefaultController<T> | ReadableByteStreamController; + type ReadableStreamReader<T> = ReadableStreamDefaultReader<T> | ReadableStreamBYOBReader; + type ReadableStreamReaderMode = "byob"; + type ReadableStreamReadResult<T> = ReadableStreamReadValueResult<T> | ReadableStreamReadDoneResult<T>; + type ReadableStreamType = "bytes"; + interface GenericTransformStream { + readonly readable: ReadableStream; + readonly writable: WritableStream; + } + interface QueuingStrategy<T = any> { + highWaterMark?: number; + size?: QueuingStrategySize<T>; + } + interface QueuingStrategyInit { + highWaterMark: number; + } + interface QueuingStrategySize<T = any> { + (chunk: T): number; + } + interface ReadableStreamBYOBReaderReadOptions { + min?: number; + } + interface ReadableStreamGenericReader { + readonly closed: Promise<void>; + cancel(reason?: any): Promise<void>; + } + interface ReadableStreamGetReaderOptions { + mode?: ReadableStreamReaderMode; + } + interface ReadableStreamIteratorOptions { + preventCancel?: boolean; + } + interface ReadableStreamReadDoneResult<T> { + done: true; + value: T | undefined; + } + interface ReadableStreamReadValueResult<T> { + done: false; + value: T; + } + interface ReadableWritablePair<R = any, W = any> { + readable: ReadableStream<R>; + writable: WritableStream<W>; + } + interface StreamPipeOptions { + preventAbort?: boolean; + preventCancel?: boolean; + preventClose?: boolean; + signal?: AbortSignal; + } + interface Transformer<I = any, O = any> { + flush?: TransformerFlushCallback<O>; + readableType?: undefined; + start?: TransformerStartCallback<O>; + transform?: TransformerTransformCallback<I, O>; + writableType?: undefined; + } + interface TransformerFlushCallback<O> { + (controller: TransformStreamDefaultController<O>): void | PromiseLike<void>; + } + interface TransformerStartCallback<O> { + (controller: TransformStreamDefaultController<O>): any; + } + interface TransformerTransformCallback<I, O> { + (chunk: I, controller: TransformStreamDefaultController<O>): void | PromiseLike<void>; + } + interface UnderlyingByteSource { + autoAllocateChunkSize?: number; + cancel?: UnderlyingSourceCancelCallback; + pull?: (controller: ReadableByteStreamController) => void | PromiseLike<void>; + start?: (controller: ReadableByteStreamController) => any; + type: "bytes"; + } + interface UnderlyingDefaultSource<R = any> { + cancel?: UnderlyingSourceCancelCallback; + pull?: (controller: ReadableStreamDefaultController<R>) => void | PromiseLike<void>; + start?: (controller: ReadableStreamDefaultController<R>) => any; + type?: undefined; + } + interface UnderlyingSink<W = any> { + abort?: UnderlyingSinkAbortCallback; + close?: UnderlyingSinkCloseCallback; + start?: UnderlyingSinkStartCallback; + type?: undefined; + write?: UnderlyingSinkWriteCallback<W>; + } + interface UnderlyingSinkAbortCallback { + (reason?: any): void | PromiseLike<void>; + } + interface UnderlyingSinkCloseCallback { + (): void | PromiseLike<void>; + } + interface UnderlyingSinkStartCallback { + (controller: WritableStreamDefaultController): any; + } + interface UnderlyingSinkWriteCallback<W> { + (chunk: W, controller: WritableStreamDefaultController): void | PromiseLike<void>; + } + interface UnderlyingSource<R = any> { + autoAllocateChunkSize?: number; + cancel?: UnderlyingSourceCancelCallback; + pull?: UnderlyingSourcePullCallback<R>; + start?: UnderlyingSourceStartCallback<R>; + type?: ReadableStreamType; + } + interface UnderlyingSourceCancelCallback { + (reason?: any): void | PromiseLike<void>; + } + interface UnderlyingSourcePullCallback<R> { + (controller: ReadableStreamController<R>): void | PromiseLike<void>; + } + interface UnderlyingSourceStartCallback<R> { + (controller: ReadableStreamController<R>): any; + } + interface ByteLengthQueuingStrategy extends QueuingStrategy<NodeJS.ArrayBufferView> { + readonly highWaterMark: number; + readonly size: QueuingStrategySize<NodeJS.ArrayBufferView>; + } + var ByteLengthQueuingStrategy: { + prototype: ByteLengthQueuingStrategy; + new(init: QueuingStrategyInit): ByteLengthQueuingStrategy; + }; + interface CompressionStream extends GenericTransformStream { + readonly readable: ReadableStream<NodeJS.NonSharedUint8Array>; + readonly writable: WritableStream<NodeJS.BufferSource>; + } + var CompressionStream: { + prototype: CompressionStream; + new(format: CompressionFormat): CompressionStream; + }; + interface CountQueuingStrategy extends QueuingStrategy { + readonly highWaterMark: number; + readonly size: QueuingStrategySize; + } + var CountQueuingStrategy: { + prototype: CountQueuingStrategy; + new(init: QueuingStrategyInit): CountQueuingStrategy; + }; + interface DecompressionStream extends GenericTransformStream { + readonly readable: ReadableStream<NodeJS.NonSharedUint8Array>; + readonly writable: WritableStream<NodeJS.BufferSource>; + } + var DecompressionStream: { + prototype: DecompressionStream; + new(format: CompressionFormat): DecompressionStream; + }; + interface ReadableByteStreamController { + readonly byobRequest: ReadableStreamBYOBRequest | null; + readonly desiredSize: number | null; + close(): void; + enqueue(chunk: NodeJS.NonSharedArrayBufferView): void; + error(e?: any): void; + } + var ReadableByteStreamController: { + prototype: ReadableByteStreamController; + new(): ReadableByteStreamController; + }; + interface ReadableStream<R = any> { + readonly locked: boolean; + cancel(reason?: any): Promise<void>; + getReader(options: { mode: "byob" }): ReadableStreamBYOBReader; + getReader(): ReadableStreamDefaultReader<R>; + getReader(options?: ReadableStreamGetReaderOptions): ReadableStreamReader<R>; + pipeThrough<T>(transform: ReadableWritablePair<T, R>, options?: StreamPipeOptions): ReadableStream<T>; + pipeTo(destination: WritableStream<R>, options?: StreamPipeOptions): Promise<void>; + tee(): [ReadableStream<R>, ReadableStream<R>]; + [Symbol.asyncIterator](options?: ReadableStreamIteratorOptions): ReadableStreamAsyncIterator<R>; + values(options?: ReadableStreamIteratorOptions): ReadableStreamAsyncIterator<R>; + } + var ReadableStream: { + prototype: ReadableStream; + new( + underlyingSource: UnderlyingByteSource, + strategy?: { highWaterMark?: number }, + ): ReadableStream<NodeJS.NonSharedUint8Array>; + new<R = any>(underlyingSource: UnderlyingDefaultSource<R>, strategy?: QueuingStrategy<R>): ReadableStream<R>; + new<R = any>(underlyingSource?: UnderlyingSource<R>, strategy?: QueuingStrategy<R>): ReadableStream<R>; + from<R = any>(iterable: Iterable<R> | AsyncIterable<R>): ReadableStream<R>; + }; + interface ReadableStreamAsyncIterator<T> extends NodeJS.AsyncIterator<T, NodeJS.BuiltinIteratorReturn, unknown> { + [Symbol.asyncIterator](): ReadableStreamAsyncIterator<T>; + } + interface ReadableStreamBYOBReader extends ReadableStreamGenericReader { + read<T extends NodeJS.NonSharedArrayBufferView>( + view: T, + options?: ReadableStreamBYOBReaderReadOptions, + ): Promise<ReadableStreamReadResult<T>>; + releaseLock(): void; + } + var ReadableStreamBYOBReader: { + prototype: ReadableStreamBYOBReader; + new(stream: ReadableStream<NodeJS.NonSharedUint8Array>): ReadableStreamBYOBReader; + }; + interface ReadableStreamBYOBRequest { + readonly view: NodeJS.NonSharedArrayBufferView | null; + respond(bytesWritten: number): void; + respondWithNewView(view: NodeJS.NonSharedArrayBufferView): void; + } + var ReadableStreamBYOBRequest: { + prototype: ReadableStreamBYOBRequest; + new(): ReadableStreamBYOBRequest; + }; + interface ReadableStreamDefaultController<R = any> { + readonly desiredSize: number | null; + close(): void; + enqueue(chunk?: R): void; + error(e?: any): void; + } + var ReadableStreamDefaultController: { + prototype: ReadableStreamDefaultController; + new(): ReadableStreamDefaultController; + }; + interface ReadableStreamDefaultReader<R = any> extends ReadableStreamGenericReader { + read(): Promise<ReadableStreamReadResult<R>>; + releaseLock(): void; + } + var ReadableStreamDefaultReader: { + prototype: ReadableStreamDefaultReader; + new<R = any>(stream: ReadableStream<R>): ReadableStreamDefaultReader<R>; + }; + interface TextDecoderStream extends GenericTransformStream, TextDecoderCommon { + readonly readable: ReadableStream<string>; + readonly writable: WritableStream<NodeJS.BufferSource>; + } + var TextDecoderStream: { + prototype: TextDecoderStream; + new(label?: string, options?: TextDecoderOptions): TextDecoderStream; + }; + interface TextEncoderStream extends GenericTransformStream, TextEncoderCommon { + readonly readable: ReadableStream<NodeJS.NonSharedUint8Array>; + readonly writable: WritableStream<string>; + } + var TextEncoderStream: { + prototype: TextEncoderStream; + new(): TextEncoderStream; + }; + interface TransformStream<I = any, O = any> { + readonly readable: ReadableStream<O>; + readonly writable: WritableStream<I>; + } + var TransformStream: { + prototype: TransformStream; + new<I = any, O = any>( + transformer?: Transformer<I, O>, + writableStrategy?: QueuingStrategy<I>, + readableStrategy?: QueuingStrategy<O>, + ): TransformStream<I, O>; + }; + interface TransformStreamDefaultController<O = any> { + readonly desiredSize: number | null; + enqueue(chunk?: O): void; + error(reason?: any): void; + terminate(): void; + } + var TransformStreamDefaultController: { + prototype: TransformStreamDefaultController; + new(): TransformStreamDefaultController; + }; + interface WritableStream<W = any> { + readonly locked: boolean; + abort(reason?: any): Promise<void>; + close(): Promise<void>; + getWriter(): WritableStreamDefaultWriter<W>; + } + var WritableStream: { + prototype: WritableStream; + new<W = any>(underlyingSink?: UnderlyingSink<W>, strategy?: QueuingStrategy<W>): WritableStream<W>; + }; + interface WritableStreamDefaultController { + readonly signal: AbortSignal; + error(e?: any): void; + } + var WritableStreamDefaultController: { + prototype: WritableStreamDefaultController; + new(): WritableStreamDefaultController; + }; + interface WritableStreamDefaultWriter<W = any> { + readonly closed: Promise<void>; + readonly desiredSize: number | null; + readonly ready: Promise<void>; + abort(reason?: any): Promise<void>; + close(): Promise<void>; + releaseLock(): void; + write(chunk?: W): Promise<void>; + } + var WritableStreamDefaultWriter: { + prototype: WritableStreamDefaultWriter; + new<W = any>(stream: WritableStream<W>): WritableStreamDefaultWriter<W>; + }; +} +declare module "stream/web" { + export * from "node:stream/web"; +} diff --git a/server/node_modules/@types/node/string_decoder.d.ts b/server/node_modules/@types/node/string_decoder.d.ts new file mode 100644 index 0000000..a72c374 --- /dev/null +++ b/server/node_modules/@types/node/string_decoder.d.ts @@ -0,0 +1,67 @@ +/** + * The `node:string_decoder` module provides an API for decoding `Buffer` objects + * into strings in a manner that preserves encoded multi-byte UTF-8 and UTF-16 + * characters. It can be accessed using: + * + * ```js + * import { StringDecoder } from 'node:string_decoder'; + * ``` + * + * The following example shows the basic use of the `StringDecoder` class. + * + * ```js + * import { StringDecoder } from 'node:string_decoder'; + * const decoder = new StringDecoder('utf8'); + * + * const cent = Buffer.from([0xC2, 0xA2]); + * console.log(decoder.write(cent)); // Prints: ¢ + * + * const euro = Buffer.from([0xE2, 0x82, 0xAC]); + * console.log(decoder.write(euro)); // Prints: € + * ``` + * + * When a `Buffer` instance is written to the `StringDecoder` instance, an + * internal buffer is used to ensure that the decoded string does not contain + * any incomplete multibyte characters. These are held in the buffer until the + * next call to `stringDecoder.write()` or until `stringDecoder.end()` is called. + * + * In the following example, the three UTF-8 encoded bytes of the European Euro + * symbol (`€`) are written over three separate operations: + * + * ```js + * import { StringDecoder } from 'node:string_decoder'; + * const decoder = new StringDecoder('utf8'); + * + * decoder.write(Buffer.from([0xE2])); + * decoder.write(Buffer.from([0x82])); + * console.log(decoder.end(Buffer.from([0xAC]))); // Prints: € + * ``` + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/string_decoder.js) + */ +declare module "node:string_decoder" { + class StringDecoder { + constructor(encoding?: BufferEncoding); + /** + * Returns a decoded string, ensuring that any incomplete multibyte characters at + * the end of the `Buffer`, or `TypedArray`, or `DataView` are omitted from the + * returned string and stored in an internal buffer for the next call to `stringDecoder.write()` or `stringDecoder.end()`. + * @since v0.1.99 + * @param buffer The bytes to decode. + */ + write(buffer: string | NodeJS.ArrayBufferView): string; + /** + * Returns any remaining input stored in the internal buffer as a string. Bytes + * representing incomplete UTF-8 and UTF-16 characters will be replaced with + * substitution characters appropriate for the character encoding. + * + * If the `buffer` argument is provided, one final call to `stringDecoder.write()` is performed before returning the remaining input. + * After `end()` is called, the `stringDecoder` object can be reused for new input. + * @since v0.9.3 + * @param buffer The bytes to decode. + */ + end(buffer?: string | NodeJS.ArrayBufferView): string; + } +} +declare module "string_decoder" { + export * from "node:string_decoder"; +} diff --git a/server/node_modules/@types/node/test.d.ts b/server/node_modules/@types/node/test.d.ts new file mode 100644 index 0000000..a3d3b68 --- /dev/null +++ b/server/node_modules/@types/node/test.d.ts @@ -0,0 +1,2240 @@ +/** + * The `node:test` module facilitates the creation of JavaScript tests. + * To access it: + * + * ```js + * import test from 'node:test'; + * ``` + * + * This module is only available under the `node:` scheme. The following will not + * work: + * + * ```js + * import test from 'node:test'; + * ``` + * + * Tests created via the `test` module consist of a single function that is + * processed in one of three ways: + * + * 1. A synchronous function that is considered failing if it throws an exception, + * and is considered passing otherwise. + * 2. A function that returns a `Promise` that is considered failing if the `Promise` rejects, and is considered passing if the `Promise` fulfills. + * 3. A function that receives a callback function. If the callback receives any + * truthy value as its first argument, the test is considered failing. If a + * falsy value is passed as the first argument to the callback, the test is + * considered passing. If the test function receives a callback function and + * also returns a `Promise`, the test will fail. + * + * The following example illustrates how tests are written using the `test` module. + * + * ```js + * test('synchronous passing test', (t) => { + * // This test passes because it does not throw an exception. + * assert.strictEqual(1, 1); + * }); + * + * test('synchronous failing test', (t) => { + * // This test fails because it throws an exception. + * assert.strictEqual(1, 2); + * }); + * + * test('asynchronous passing test', async (t) => { + * // This test passes because the Promise returned by the async + * // function is settled and not rejected. + * assert.strictEqual(1, 1); + * }); + * + * test('asynchronous failing test', async (t) => { + * // This test fails because the Promise returned by the async + * // function is rejected. + * assert.strictEqual(1, 2); + * }); + * + * test('failing test using Promises', (t) => { + * // Promises can be used directly as well. + * return new Promise((resolve, reject) => { + * setImmediate(() => { + * reject(new Error('this will cause the test to fail')); + * }); + * }); + * }); + * + * test('callback passing test', (t, done) => { + * // done() is the callback function. When the setImmediate() runs, it invokes + * // done() with no arguments. + * setImmediate(done); + * }); + * + * test('callback failing test', (t, done) => { + * // When the setImmediate() runs, done() is invoked with an Error object and + * // the test fails. + * setImmediate(() => { + * done(new Error('callback failure')); + * }); + * }); + * ``` + * + * If any tests fail, the process exit code is set to `1`. + * @since v18.0.0, v16.17.0 + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/test.js) + */ +declare module "node:test" { + import { AssertMethodNames } from "node:assert"; + import { Readable, ReadableEventMap } from "node:stream"; + import { TestEvent } from "node:test/reporters"; + import { URL } from "node:url"; + import TestFn = test.TestFn; + import TestOptions = test.TestOptions; + /** + * The `test()` function is the value imported from the `test` module. Each + * invocation of this function results in reporting the test to the `TestsStream`. + * + * The `TestContext` object passed to the `fn` argument can be used to perform + * actions related to the current test. Examples include skipping the test, adding + * additional diagnostic information, or creating subtests. + * + * `test()` returns a `Promise` that fulfills once the test completes. + * if `test()` is called within a suite, it fulfills immediately. + * The return value can usually be discarded for top level tests. + * However, the return value from subtests should be used to prevent the parent + * test from finishing first and cancelling the subtest + * as shown in the following example. + * + * ```js + * test('top level test', async (t) => { + * // The setTimeout() in the following subtest would cause it to outlive its + * // parent test if 'await' is removed on the next line. Once the parent test + * // completes, it will cancel any outstanding subtests. + * await t.test('longer running subtest', async (t) => { + * return new Promise((resolve, reject) => { + * setTimeout(resolve, 1000); + * }); + * }); + * }); + * ``` + * + * The `timeout` option can be used to fail the test if it takes longer than `timeout` milliseconds to complete. However, it is not a reliable mechanism for + * canceling tests because a running test might block the application thread and + * thus prevent the scheduled cancellation. + * @since v18.0.0, v16.17.0 + * @param name The name of the test, which is displayed when reporting test results. + * Defaults to the `name` property of `fn`, or `'<anonymous>'` if `fn` does not have a name. + * @param options Configuration options for the test. + * @param fn The function under test. The first argument to this function is a {@link TestContext} object. + * If the test uses callbacks, the callback function is passed as the second argument. + * @return Fulfilled with `undefined` once the test completes, or immediately if the test runs within a suite. + */ + function test(name?: string, fn?: TestFn): Promise<void>; + function test(name?: string, options?: TestOptions, fn?: TestFn): Promise<void>; + function test(options?: TestOptions, fn?: TestFn): Promise<void>; + function test(fn?: TestFn): Promise<void>; + namespace test { + export { test }; + export { suite as describe, test as it }; + } + namespace test { + /** + * **Note:** `shard` is used to horizontally parallelize test running across + * machines or processes, ideal for large-scale executions across varied + * environments. It's incompatible with `watch` mode, tailored for rapid + * code iteration by automatically rerunning tests on file changes. + * + * ```js + * import { tap } from 'node:test/reporters'; + * import { run } from 'node:test'; + * import process from 'node:process'; + * import path from 'node:path'; + * + * run({ files: [path.resolve('./tests/test.js')] }) + * .compose(tap) + * .pipe(process.stdout); + * ``` + * @since v18.9.0, v16.19.0 + * @param options Configuration options for running tests. + */ + function run(options?: RunOptions): TestsStream; + /** + * The `suite()` function is imported from the `node:test` module. + * @param name The name of the suite, which is displayed when reporting test results. + * Defaults to the `name` property of `fn`, or `'<anonymous>'` if `fn` does not have a name. + * @param options Configuration options for the suite. This supports the same options as {@link test}. + * @param fn The suite function declaring nested tests and suites. The first argument to this function is a {@link SuiteContext} object. + * @return Immediately fulfilled with `undefined`. + * @since v20.13.0 + */ + function suite(name?: string, options?: TestOptions, fn?: SuiteFn): Promise<void>; + function suite(name?: string, fn?: SuiteFn): Promise<void>; + function suite(options?: TestOptions, fn?: SuiteFn): Promise<void>; + function suite(fn?: SuiteFn): Promise<void>; + namespace suite { + /** + * Shorthand for skipping a suite. This is the same as calling {@link suite} with `options.skip` set to `true`. + * @since v20.13.0 + */ + function skip(name?: string, options?: TestOptions, fn?: SuiteFn): Promise<void>; + function skip(name?: string, fn?: SuiteFn): Promise<void>; + function skip(options?: TestOptions, fn?: SuiteFn): Promise<void>; + function skip(fn?: SuiteFn): Promise<void>; + /** + * Shorthand for marking a suite as `TODO`. This is the same as calling {@link suite} with `options.todo` set to `true`. + * @since v20.13.0 + */ + function todo(name?: string, options?: TestOptions, fn?: SuiteFn): Promise<void>; + function todo(name?: string, fn?: SuiteFn): Promise<void>; + function todo(options?: TestOptions, fn?: SuiteFn): Promise<void>; + function todo(fn?: SuiteFn): Promise<void>; + /** + * Shorthand for marking a suite as `only`. This is the same as calling {@link suite} with `options.only` set to `true`. + * @since v20.13.0 + */ + function only(name?: string, options?: TestOptions, fn?: SuiteFn): Promise<void>; + function only(name?: string, fn?: SuiteFn): Promise<void>; + function only(options?: TestOptions, fn?: SuiteFn): Promise<void>; + function only(fn?: SuiteFn): Promise<void>; + } + /** + * Shorthand for skipping a test. This is the same as calling {@link test} with `options.skip` set to `true`. + * @since v20.2.0 + */ + function skip(name?: string, options?: TestOptions, fn?: TestFn): Promise<void>; + function skip(name?: string, fn?: TestFn): Promise<void>; + function skip(options?: TestOptions, fn?: TestFn): Promise<void>; + function skip(fn?: TestFn): Promise<void>; + /** + * Shorthand for marking a test as `TODO`. This is the same as calling {@link test} with `options.todo` set to `true`. + * @since v20.2.0 + */ + function todo(name?: string, options?: TestOptions, fn?: TestFn): Promise<void>; + function todo(name?: string, fn?: TestFn): Promise<void>; + function todo(options?: TestOptions, fn?: TestFn): Promise<void>; + function todo(fn?: TestFn): Promise<void>; + /** + * Shorthand for marking a test as `only`. This is the same as calling {@link test} with `options.only` set to `true`. + * @since v20.2.0 + */ + function only(name?: string, options?: TestOptions, fn?: TestFn): Promise<void>; + function only(name?: string, fn?: TestFn): Promise<void>; + function only(options?: TestOptions, fn?: TestFn): Promise<void>; + function only(fn?: TestFn): Promise<void>; + /** + * The type of a function passed to {@link test}. The first argument to this function is a {@link TestContext} object. + * If the test uses callbacks, the callback function is passed as the second argument. + */ + type TestFn = (t: TestContext, done: (result?: any) => void) => void | Promise<void>; + /** + * The type of a suite test function. The argument to this function is a {@link SuiteContext} object. + */ + type SuiteFn = (s: SuiteContext) => void | Promise<void>; + interface TestShard { + /** + * A positive integer between 1 and `total` that specifies the index of the shard to run. + */ + index: number; + /** + * A positive integer that specifies the total number of shards to split the test files to. + */ + total: number; + } + interface RunOptions { + /** + * If a number is provided, then that many test processes would run in parallel, where each process corresponds to one test file. + * If `true`, it would run `os.availableParallelism() - 1` test files in parallel. If `false`, it would only run one test file at a time. + * @default false + */ + concurrency?: number | boolean | undefined; + /** + * Specifies the current working directory to be used by the test runner. + * Serves as the base path for resolving files according to the + * [test runner execution model](https://nodejs.org/docs/latest-v25.x/api/test.html#test-runner-execution-model). + * @since v23.0.0 + * @default process.cwd() + */ + cwd?: string | undefined; + /** + * An array containing the list of files to run. If omitted, files are run according to the + * [test runner execution model](https://nodejs.org/docs/latest-v25.x/api/test.html#test-runner-execution-model). + */ + files?: readonly string[] | undefined; + /** + * Configures the test runner to exit the process once all known + * tests have finished executing even if the event loop would + * otherwise remain active. + * @default false + */ + forceExit?: boolean | undefined; + /** + * An array containing the list of glob patterns to match test files. + * This option cannot be used together with `files`. If omitted, files are run according to the + * [test runner execution model](https://nodejs.org/docs/latest-v25.x/api/test.html#test-runner-execution-model). + * @since v22.6.0 + */ + globPatterns?: readonly string[] | undefined; + /** + * Sets inspector port of test child process. + * This can be a number, or a function that takes no arguments and returns a + * number. If a nullish value is provided, each process gets its own port, + * incremented from the primary's `process.debugPort`. This option is ignored + * if the `isolation` option is set to `'none'` as no child processes are + * spawned. + * @default undefined + */ + inspectPort?: number | (() => number) | undefined; + /** + * Configures the type of test isolation. If set to + * `'process'`, each test file is run in a separate child process. If set to + * `'none'`, all test files run in the current process. + * @default 'process' + * @since v22.8.0 + */ + isolation?: "process" | "none" | undefined; + /** + * If truthy, the test context will only run tests that have the `only` option set + */ + only?: boolean | undefined; + /** + * A function that accepts the `TestsStream` instance and can be used to setup listeners before any tests are run. + * @default undefined + */ + setup?: ((reporter: TestsStream) => void | Promise<void>) | undefined; + /** + * An array of CLI flags to pass to the `node` executable when + * spawning the subprocesses. This option has no effect when `isolation` is `'none`'. + * @since v22.10.0 + * @default [] + */ + execArgv?: readonly string[] | undefined; + /** + * An array of CLI flags to pass to each test file when spawning the + * subprocesses. This option has no effect when `isolation` is `'none'`. + * @since v22.10.0 + * @default [] + */ + argv?: readonly string[] | undefined; + /** + * Allows aborting an in-progress test execution. + */ + signal?: AbortSignal | undefined; + /** + * If provided, only run tests whose name matches the provided pattern. + * Strings are interpreted as JavaScript regular expressions. + * @default undefined + */ + testNamePatterns?: string | RegExp | ReadonlyArray<string | RegExp> | undefined; + /** + * A String, RegExp or a RegExp Array, that can be used to exclude running tests whose + * name matches the provided pattern. Test name patterns are interpreted as JavaScript + * regular expressions. For each test that is executed, any corresponding test hooks, + * such as `beforeEach()`, are also run. + * @default undefined + * @since v22.1.0 + */ + testSkipPatterns?: string | RegExp | ReadonlyArray<string | RegExp> | undefined; + /** + * The number of milliseconds after which the test execution will fail. + * If unspecified, subtests inherit this value from their parent. + * @default Infinity + */ + timeout?: number | undefined; + /** + * Whether to run in watch mode or not. + * @default false + */ + watch?: boolean | undefined; + /** + * Running tests in a specific shard. + * @default undefined + */ + shard?: TestShard | undefined; + /** + * A file path where the test runner will + * store the state of the tests to allow rerunning only the failed tests on a next run. + * @since v24.7.0 + * @default undefined + */ + rerunFailuresFilePath?: string | undefined; + /** + * enable [code coverage](https://nodejs.org/docs/latest-v25.x/api/test.html#collecting-code-coverage) collection. + * @since v22.10.0 + * @default false + */ + coverage?: boolean | undefined; + /** + * Excludes specific files from code coverage + * using a glob pattern, which can match both absolute and relative file paths. + * This property is only applicable when `coverage` was set to `true`. + * If both `coverageExcludeGlobs` and `coverageIncludeGlobs` are provided, + * files must meet **both** criteria to be included in the coverage report. + * @since v22.10.0 + * @default undefined + */ + coverageExcludeGlobs?: string | readonly string[] | undefined; + /** + * Includes specific files in code coverage + * using a glob pattern, which can match both absolute and relative file paths. + * This property is only applicable when `coverage` was set to `true`. + * If both `coverageExcludeGlobs` and `coverageIncludeGlobs` are provided, + * files must meet **both** criteria to be included in the coverage report. + * @since v22.10.0 + * @default undefined + */ + coverageIncludeGlobs?: string | readonly string[] | undefined; + /** + * Require a minimum percent of covered lines. If code + * coverage does not reach the threshold specified, the process will exit with code `1`. + * @since v22.10.0 + * @default 0 + */ + lineCoverage?: number | undefined; + /** + * Require a minimum percent of covered branches. If code + * coverage does not reach the threshold specified, the process will exit with code `1`. + * @since v22.10.0 + * @default 0 + */ + branchCoverage?: number | undefined; + /** + * Require a minimum percent of covered functions. If code + * coverage does not reach the threshold specified, the process will exit with code `1`. + * @since v22.10.0 + * @default 0 + */ + functionCoverage?: number | undefined; + } + interface TestsStreamEventMap extends ReadableEventMap { + "data": [data: TestEvent]; + "test:coverage": [data: EventData.TestCoverage]; + "test:complete": [data: EventData.TestComplete]; + "test:dequeue": [data: EventData.TestDequeue]; + "test:diagnostic": [data: EventData.TestDiagnostic]; + "test:enqueue": [data: EventData.TestEnqueue]; + "test:fail": [data: EventData.TestFail]; + "test:pass": [data: EventData.TestPass]; + "test:plan": [data: EventData.TestPlan]; + "test:start": [data: EventData.TestStart]; + "test:stderr": [data: EventData.TestStderr]; + "test:stdout": [data: EventData.TestStdout]; + "test:summary": [data: EventData.TestSummary]; + "test:watch:drained": []; + "test:watch:restarted": []; + } + /** + * A successful call to `run()` will return a new `TestsStream` object, streaming a series of events representing the execution of the tests. + * + * Some of the events are guaranteed to be emitted in the same order as the tests are defined, while others are emitted in the order that the tests execute. + * @since v18.9.0, v16.19.0 + */ + interface TestsStream extends Readable { + // #region InternalEventEmitter + addListener<E extends keyof TestsStreamEventMap>( + eventName: E, + listener: (...args: TestsStreamEventMap[E]) => void, + ): this; + addListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + emit<E extends keyof TestsStreamEventMap>(eventName: E, ...args: TestsStreamEventMap[E]): boolean; + emit(eventName: string | symbol, ...args: any[]): boolean; + listenerCount<E extends keyof TestsStreamEventMap>( + eventName: E, + listener?: (...args: TestsStreamEventMap[E]) => void, + ): number; + listenerCount(eventName: string | symbol, listener?: (...args: any[]) => void): number; + listeners<E extends keyof TestsStreamEventMap>(eventName: E): ((...args: TestsStreamEventMap[E]) => void)[]; + listeners(eventName: string | symbol): ((...args: any[]) => void)[]; + off<E extends keyof TestsStreamEventMap>( + eventName: E, + listener: (...args: TestsStreamEventMap[E]) => void, + ): this; + off(eventName: string | symbol, listener: (...args: any[]) => void): this; + on<E extends keyof TestsStreamEventMap>( + eventName: E, + listener: (...args: TestsStreamEventMap[E]) => void, + ): this; + on(eventName: string | symbol, listener: (...args: any[]) => void): this; + once<E extends keyof TestsStreamEventMap>( + eventName: E, + listener: (...args: TestsStreamEventMap[E]) => void, + ): this; + once(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependListener<E extends keyof TestsStreamEventMap>( + eventName: E, + listener: (...args: TestsStreamEventMap[E]) => void, + ): this; + prependListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependOnceListener<E extends keyof TestsStreamEventMap>( + eventName: E, + listener: (...args: TestsStreamEventMap[E]) => void, + ): this; + prependOnceListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + rawListeners<E extends keyof TestsStreamEventMap>( + eventName: E, + ): ((...args: TestsStreamEventMap[E]) => void)[]; + rawListeners(eventName: string | symbol): ((...args: any[]) => void)[]; + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + removeAllListeners<E extends keyof TestsStreamEventMap>(eventName?: E): this; + removeAllListeners(eventName?: string | symbol): this; + removeListener<E extends keyof TestsStreamEventMap>( + eventName: E, + listener: (...args: TestsStreamEventMap[E]) => void, + ): this; + removeListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + // #endregion + } + namespace EventData { + interface Error extends globalThis.Error { + cause: globalThis.Error; + } + interface LocationInfo { + /** + * The column number where the test is defined, or + * `undefined` if the test was run through the REPL. + */ + column?: number; + /** + * The path of the test file, `undefined` if test was run through the REPL. + */ + file?: string; + /** + * The line number where the test is defined, or `undefined` if the test was run through the REPL. + */ + line?: number; + } + interface TestDiagnostic extends LocationInfo { + /** + * The diagnostic message. + */ + message: string; + /** + * The nesting level of the test. + */ + nesting: number; + /** + * The severity level of the diagnostic message. + * Possible values are: + * * `'info'`: Informational messages. + * * `'warn'`: Warnings. + * * `'error'`: Errors. + */ + level: "info" | "warn" | "error"; + } + interface TestCoverage { + /** + * An object containing the coverage report. + */ + summary: { + /** + * An array of coverage reports for individual files. + */ + files: Array<{ + /** + * The absolute path of the file. + */ + path: string; + /** + * The total number of lines. + */ + totalLineCount: number; + /** + * The total number of branches. + */ + totalBranchCount: number; + /** + * The total number of functions. + */ + totalFunctionCount: number; + /** + * The number of covered lines. + */ + coveredLineCount: number; + /** + * The number of covered branches. + */ + coveredBranchCount: number; + /** + * The number of covered functions. + */ + coveredFunctionCount: number; + /** + * The percentage of lines covered. + */ + coveredLinePercent: number; + /** + * The percentage of branches covered. + */ + coveredBranchPercent: number; + /** + * The percentage of functions covered. + */ + coveredFunctionPercent: number; + /** + * An array of functions representing function coverage. + */ + functions: Array<{ + /** + * The name of the function. + */ + name: string; + /** + * The line number where the function is defined. + */ + line: number; + /** + * The number of times the function was called. + */ + count: number; + }>; + /** + * An array of branches representing branch coverage. + */ + branches: Array<{ + /** + * The line number where the branch is defined. + */ + line: number; + /** + * The number of times the branch was taken. + */ + count: number; + }>; + /** + * An array of lines representing line numbers and the number of times they were covered. + */ + lines: Array<{ + /** + * The line number. + */ + line: number; + /** + * The number of times the line was covered. + */ + count: number; + }>; + }>; + /** + * An object containing whether or not the coverage for + * each coverage type. + * @since v22.9.0 + */ + thresholds: { + /** + * The function coverage threshold. + */ + function: number; + /** + * The branch coverage threshold. + */ + branch: number; + /** + * The line coverage threshold. + */ + line: number; + }; + /** + * An object containing a summary of coverage for all files. + */ + totals: { + /** + * The total number of lines. + */ + totalLineCount: number; + /** + * The total number of branches. + */ + totalBranchCount: number; + /** + * The total number of functions. + */ + totalFunctionCount: number; + /** + * The number of covered lines. + */ + coveredLineCount: number; + /** + * The number of covered branches. + */ + coveredBranchCount: number; + /** + * The number of covered functions. + */ + coveredFunctionCount: number; + /** + * The percentage of lines covered. + */ + coveredLinePercent: number; + /** + * The percentage of branches covered. + */ + coveredBranchPercent: number; + /** + * The percentage of functions covered. + */ + coveredFunctionPercent: number; + }; + /** + * The working directory when code coverage began. This + * is useful for displaying relative path names in case + * the tests changed the working directory of the Node.js process. + */ + workingDirectory: string; + }; + /** + * The nesting level of the test. + */ + nesting: number; + } + interface TestComplete extends LocationInfo { + /** + * Additional execution metadata. + */ + details: { + /** + * Whether the test passed or not. + */ + passed: boolean; + /** + * The duration of the test in milliseconds. + */ + duration_ms: number; + /** + * An error wrapping the error thrown by the test if it did not pass. + */ + error?: Error; + /** + * The type of the test, used to denote whether this is a suite. + */ + type?: "suite" | "test"; + }; + /** + * The test name. + */ + name: string; + /** + * The nesting level of the test. + */ + nesting: number; + /** + * The ordinal number of the test. + */ + testNumber: number; + /** + * Present if `context.todo` is called. + */ + todo?: string | boolean; + /** + * Present if `context.skip` is called. + */ + skip?: string | boolean; + } + interface TestDequeue extends LocationInfo { + /** + * The test name. + */ + name: string; + /** + * The nesting level of the test. + */ + nesting: number; + /** + * The test type. Either `'suite'` or `'test'`. + * @since v22.15.0 + */ + type: "suite" | "test"; + } + interface TestEnqueue extends LocationInfo { + /** + * The test name. + */ + name: string; + /** + * The nesting level of the test. + */ + nesting: number; + /** + * The test type. Either `'suite'` or `'test'`. + * @since v22.15.0 + */ + type: "suite" | "test"; + } + interface TestFail extends LocationInfo { + /** + * Additional execution metadata. + */ + details: { + /** + * The duration of the test in milliseconds. + */ + duration_ms: number; + /** + * An error wrapping the error thrown by the test. + */ + error: Error; + /** + * The type of the test, used to denote whether this is a suite. + * @since v20.0.0, v19.9.0, v18.17.0 + */ + type?: "suite" | "test"; + /** + * The attempt number of the test run, + * present only when using the `--test-rerun-failures` flag. + * @since v24.7.0 + */ + attempt?: number; + }; + /** + * The test name. + */ + name: string; + /** + * The nesting level of the test. + */ + nesting: number; + /** + * The ordinal number of the test. + */ + testNumber: number; + /** + * Present if `context.todo` is called. + */ + todo?: string | boolean; + /** + * Present if `context.skip` is called. + */ + skip?: string | boolean; + } + interface TestPass extends LocationInfo { + /** + * Additional execution metadata. + */ + details: { + /** + * The duration of the test in milliseconds. + */ + duration_ms: number; + /** + * The type of the test, used to denote whether this is a suite. + * @since 20.0.0, 19.9.0, 18.17.0 + */ + type?: "suite" | "test"; + /** + * The attempt number of the test run, + * present only when using the `--test-rerun-failures` flag. + * @since v24.7.0 + */ + attempt?: number; + /** + * The attempt number the test passed on, + * present only when using the `--test-rerun-failures` flag. + * @since v24.7.0 + */ + passed_on_attempt?: number; + }; + /** + * The test name. + */ + name: string; + /** + * The nesting level of the test. + */ + nesting: number; + /** + * The ordinal number of the test. + */ + testNumber: number; + /** + * Present if `context.todo` is called. + */ + todo?: string | boolean; + /** + * Present if `context.skip` is called. + */ + skip?: string | boolean; + } + interface TestPlan extends LocationInfo { + /** + * The nesting level of the test. + */ + nesting: number; + /** + * The number of subtests that have ran. + */ + count: number; + } + interface TestStart extends LocationInfo { + /** + * The test name. + */ + name: string; + /** + * The nesting level of the test. + */ + nesting: number; + } + interface TestStderr { + /** + * The path of the test file. + */ + file: string; + /** + * The message written to `stderr`. + */ + message: string; + } + interface TestStdout { + /** + * The path of the test file. + */ + file: string; + /** + * The message written to `stdout`. + */ + message: string; + } + interface TestSummary { + /** + * An object containing the counts of various test results. + */ + counts: { + /** + * The total number of cancelled tests. + */ + cancelled: number; + /** + * The total number of passed tests. + */ + passed: number; + /** + * The total number of skipped tests. + */ + skipped: number; + /** + * The total number of suites run. + */ + suites: number; + /** + * The total number of tests run, excluding suites. + */ + tests: number; + /** + * The total number of TODO tests. + */ + todo: number; + /** + * The total number of top level tests and suites. + */ + topLevel: number; + }; + /** + * The duration of the test run in milliseconds. + */ + duration_ms: number; + /** + * The path of the test file that generated the + * summary. If the summary corresponds to multiple files, this value is + * `undefined`. + */ + file: string | undefined; + /** + * Indicates whether or not the test run is considered + * successful or not. If any error condition occurs, such as a failing test or + * unmet coverage threshold, this value will be set to `false`. + */ + success: boolean; + } + } + /** + * An instance of `TestContext` is passed to each test function in order to + * interact with the test runner. However, the `TestContext` constructor is not + * exposed as part of the API. + * @since v18.0.0, v16.17.0 + */ + interface TestContext { + /** + * An object containing assertion methods bound to the test context. + * The top-level functions from the `node:assert` module are exposed here for the purpose of creating test plans. + * + * **Note:** Some of the functions from `node:assert` contain type assertions. If these are called via the + * TestContext `assert` object, then the context parameter in the test's function signature **must be explicitly typed** + * (ie. the parameter must have a type annotation), otherwise an error will be raised by the TypeScript compiler: + * ```ts + * import { test, type TestContext } from 'node:test'; + * + * // The test function's context parameter must have a type annotation. + * test('example', (t: TestContext) => { + * t.assert.deepStrictEqual(actual, expected); + * }); + * + * // Omitting the type annotation will result in a compilation error. + * test('example', t => { + * t.assert.deepStrictEqual(actual, expected); // Error: 't' needs an explicit type annotation. + * }); + * ``` + * @since v22.2.0, v20.15.0 + */ + readonly assert: TestContextAssert; + readonly attempt: number; + /** + * This function is used to create a hook running before subtest of the current test. + * @param fn The hook function. The first argument to this function is a `TestContext` object. + * If the hook uses callbacks, the callback function is passed as the second argument. + * @param options Configuration options for the hook. + * @since v20.1.0, v18.17.0 + */ + before(fn?: TestContextHookFn, options?: HookOptions): void; + /** + * This function is used to create a hook running before each subtest of the current test. + * @param fn The hook function. The first argument to this function is a `TestContext` object. + * If the hook uses callbacks, the callback function is passed as the second argument. + * @param options Configuration options for the hook. + * @since v18.8.0 + */ + beforeEach(fn?: TestContextHookFn, options?: HookOptions): void; + /** + * This function is used to create a hook that runs after the current test finishes. + * @param fn The hook function. The first argument to this function is a `TestContext` object. + * If the hook uses callbacks, the callback function is passed as the second argument. + * @param options Configuration options for the hook. + * @since v18.13.0 + */ + after(fn?: TestContextHookFn, options?: HookOptions): void; + /** + * This function is used to create a hook running after each subtest of the current test. + * @param fn The hook function. The first argument to this function is a `TestContext` object. + * If the hook uses callbacks, the callback function is passed as the second argument. + * @param options Configuration options for the hook. + * @since v18.8.0 + */ + afterEach(fn?: TestContextHookFn, options?: HookOptions): void; + /** + * This function is used to write diagnostics to the output. Any diagnostic + * information is included at the end of the test's results. This function does + * not return a value. + * + * ```js + * test('top level test', (t) => { + * t.diagnostic('A diagnostic message'); + * }); + * ``` + * @since v18.0.0, v16.17.0 + * @param message Message to be reported. + */ + diagnostic(message: string): void; + /** + * The absolute path of the test file that created the current test. If a test file imports + * additional modules that generate tests, the imported tests will return the path of the root test file. + * @since v22.6.0 + */ + readonly filePath: string | undefined; + /** + * The name of the test and each of its ancestors, separated by `>`. + * @since v22.3.0 + */ + readonly fullName: string; + /** + * The name of the test. + * @since v18.8.0, v16.18.0 + */ + readonly name: string; + /** + * This function is used to set the number of assertions and subtests that are expected to run + * within the test. If the number of assertions and subtests that run does not match the + * expected count, the test will fail. + * + * > Note: To make sure assertions are tracked, `t.assert` must be used instead of `assert` directly. + * + * ```js + * test('top level test', (t) => { + * t.plan(2); + * t.assert.ok('some relevant assertion here'); + * t.test('subtest', () => {}); + * }); + * ``` + * + * When working with asynchronous code, the `plan` function can be used to ensure that the + * correct number of assertions are run: + * + * ```js + * test('planning with streams', (t, done) => { + * function* generate() { + * yield 'a'; + * yield 'b'; + * yield 'c'; + * } + * const expected = ['a', 'b', 'c']; + * t.plan(expected.length); + * const stream = Readable.from(generate()); + * stream.on('data', (chunk) => { + * t.assert.strictEqual(chunk, expected.shift()); + * }); + * + * stream.on('end', () => { + * done(); + * }); + * }); + * ``` + * + * When using the `wait` option, you can control how long the test will wait for the expected assertions. + * For example, setting a maximum wait time ensures that the test will wait for asynchronous assertions + * to complete within the specified timeframe: + * + * ```js + * test('plan with wait: 2000 waits for async assertions', (t) => { + * t.plan(1, { wait: 2000 }); // Waits for up to 2 seconds for the assertion to complete. + * + * const asyncActivity = () => { + * setTimeout(() => { + * * t.assert.ok(true, 'Async assertion completed within the wait time'); + * }, 1000); // Completes after 1 second, within the 2-second wait time. + * }; + * + * asyncActivity(); // The test will pass because the assertion is completed in time. + * }); + * ``` + * + * Note: If a `wait` timeout is specified, it begins counting down only after the test function finishes executing. + * @since v22.2.0 + */ + plan(count: number, options?: TestContextPlanOptions): void; + /** + * If `shouldRunOnlyTests` is truthy, the test context will only run tests that + * have the `only` option set. Otherwise, all tests are run. If Node.js was not + * started with the `--test-only` command-line option, this function is a + * no-op. + * + * ```js + * test('top level test', (t) => { + * // The test context can be set to run subtests with the 'only' option. + * t.runOnly(true); + * return Promise.all([ + * t.test('this subtest is now skipped'), + * t.test('this subtest is run', { only: true }), + * ]); + * }); + * ``` + * @since v18.0.0, v16.17.0 + * @param shouldRunOnlyTests Whether or not to run `only` tests. + */ + runOnly(shouldRunOnlyTests: boolean): void; + /** + * ```js + * test('top level test', async (t) => { + * await fetch('some/uri', { signal: t.signal }); + * }); + * ``` + * @since v18.7.0, v16.17.0 + */ + readonly signal: AbortSignal; + /** + * This function causes the test's output to indicate the test as skipped. If `message` is provided, it is included in the output. Calling `skip()` does + * not terminate execution of the test function. This function does not return a + * value. + * + * ```js + * test('top level test', (t) => { + * // Make sure to return here as well if the test contains additional logic. + * t.skip('this is skipped'); + * }); + * ``` + * @since v18.0.0, v16.17.0 + * @param message Optional skip message. + */ + skip(message?: string): void; + /** + * This function adds a `TODO` directive to the test's output. If `message` is + * provided, it is included in the output. Calling `todo()` does not terminate + * execution of the test function. This function does not return a value. + * + * ```js + * test('top level test', (t) => { + * // This test is marked as `TODO` + * t.todo('this is a todo'); + * }); + * ``` + * @since v18.0.0, v16.17.0 + * @param message Optional `TODO` message. + */ + todo(message?: string): void; + /** + * This function is used to create subtests under the current test. This function behaves in + * the same fashion as the top level {@link test} function. + * @since v18.0.0 + * @param name The name of the test, which is displayed when reporting test results. + * Defaults to the `name` property of `fn`, or `'<anonymous>'` if `fn` does not have a name. + * @param options Configuration options for the test. + * @param fn The function under test. This first argument to this function is a {@link TestContext} object. + * If the test uses callbacks, the callback function is passed as the second argument. + * @returns A {@link Promise} resolved with `undefined` once the test completes. + */ + test: typeof test; + /** + * This method polls a `condition` function until that function either returns + * successfully or the operation times out. + * @since v22.14.0 + * @param condition An assertion function that is invoked + * periodically until it completes successfully or the defined polling timeout + * elapses. Successful completion is defined as not throwing or rejecting. This + * function does not accept any arguments, and is allowed to return any value. + * @param options An optional configuration object for the polling operation. + * @returns Fulfilled with the value returned by `condition`. + */ + waitFor<T>(condition: () => T, options?: TestContextWaitForOptions): Promise<Awaited<T>>; + /** + * Each test provides its own MockTracker instance. + */ + readonly mock: MockTracker; + } + interface TestContextAssert extends Pick<typeof import("assert"), AssertMethodNames> { + /** + * This function serializes `value` and writes it to the file specified by `path`. + * + * ```js + * test('snapshot test with default serialization', (t) => { + * t.assert.fileSnapshot({ value1: 1, value2: 2 }, './snapshots/snapshot.json'); + * }); + * ``` + * + * This function differs from `context.assert.snapshot()` in the following ways: + * + * * The snapshot file path is explicitly provided by the user. + * * Each snapshot file is limited to a single snapshot value. + * * No additional escaping is performed by the test runner. + * + * These differences allow snapshot files to better support features such as syntax + * highlighting. + * @since v22.14.0 + * @param value A value to serialize to a string. If Node.js was started with + * the [`--test-update-snapshots`](https://nodejs.org/docs/latest-v25.x/api/cli.html#--test-update-snapshots) + * flag, the serialized value is written to + * `path`. Otherwise, the serialized value is compared to the contents of the + * existing snapshot file. + * @param path The file where the serialized `value` is written. + * @param options Optional configuration options. + */ + fileSnapshot(value: any, path: string, options?: AssertSnapshotOptions): void; + /** + * This function implements assertions for snapshot testing. + * ```js + * test('snapshot test with default serialization', (t) => { + * t.assert.snapshot({ value1: 1, value2: 2 }); + * }); + * + * test('snapshot test with custom serialization', (t) => { + * t.assert.snapshot({ value3: 3, value4: 4 }, { + * serializers: [(value) => JSON.stringify(value)] + * }); + * }); + * ``` + * @since v22.3.0 + * @param value A value to serialize to a string. If Node.js was started with + * the [`--test-update-snapshots`](https://nodejs.org/docs/latest-v25.x/api/cli.html#--test-update-snapshots) + * flag, the serialized value is written to + * the snapshot file. Otherwise, the serialized value is compared to the + * corresponding value in the existing snapshot file. + */ + snapshot(value: any, options?: AssertSnapshotOptions): void; + /** + * A custom assertion function registered with `assert.register()`. + */ + [name: string]: (...args: any[]) => void; + } + interface AssertSnapshotOptions { + /** + * An array of synchronous functions used to serialize `value` into a string. + * `value` is passed as the only argument to the first serializer function. + * The return value of each serializer is passed as input to the next serializer. + * Once all serializers have run, the resulting value is coerced to a string. + * + * If no serializers are provided, the test runner's default serializers are used. + */ + serializers?: ReadonlyArray<(value: any) => any> | undefined; + } + interface TestContextPlanOptions { + /** + * The wait time for the plan: + * * If `true`, the plan waits indefinitely for all assertions and subtests to run. + * * If `false`, the plan performs an immediate check after the test function completes, + * without waiting for any pending assertions or subtests. + * Any assertions or subtests that complete after this check will not be counted towards the plan. + * * If a number, it specifies the maximum wait time in milliseconds + * before timing out while waiting for expected assertions and subtests to be matched. + * If the timeout is reached, the test will fail. + * @default false + */ + wait?: boolean | number | undefined; + } + interface TestContextWaitForOptions { + /** + * The number of milliseconds to wait after an unsuccessful + * invocation of `condition` before trying again. + * @default 50 + */ + interval?: number | undefined; + /** + * The poll timeout in milliseconds. If `condition` has not + * succeeded by the time this elapses, an error occurs. + * @default 1000 + */ + timeout?: number | undefined; + } + /** + * An instance of `SuiteContext` is passed to each suite function in order to + * interact with the test runner. However, the `SuiteContext` constructor is not + * exposed as part of the API. + * @since v18.7.0, v16.17.0 + */ + interface SuiteContext { + /** + * The absolute path of the test file that created the current suite. If a test file imports + * additional modules that generate suites, the imported suites will return the path of the root test file. + * @since v22.6.0 + */ + readonly filePath: string | undefined; + /** + * The name of the suite. + * @since v18.8.0, v16.18.0 + */ + readonly name: string; + /** + * Can be used to abort test subtasks when the test has been aborted. + * @since v18.7.0, v16.17.0 + */ + readonly signal: AbortSignal; + } + interface TestOptions { + /** + * If a number is provided, then that many tests would run in parallel. + * If truthy, it would run (number of cpu cores - 1) tests in parallel. + * For subtests, it will be `Infinity` tests in parallel. + * If falsy, it would only run one test at a time. + * If unspecified, subtests inherit this value from their parent. + * @default false + */ + concurrency?: number | boolean | undefined; + /** + * If truthy, and the test context is configured to run `only` tests, then this test will be + * run. Otherwise, the test is skipped. + * @default false + */ + only?: boolean | undefined; + /** + * Allows aborting an in-progress test. + * @since v18.8.0 + */ + signal?: AbortSignal | undefined; + /** + * If truthy, the test is skipped. If a string is provided, that string is displayed in the + * test results as the reason for skipping the test. + * @default false + */ + skip?: boolean | string | undefined; + /** + * A number of milliseconds the test will fail after. If unspecified, subtests inherit this + * value from their parent. + * @default Infinity + * @since v18.7.0 + */ + timeout?: number | undefined; + /** + * If truthy, the test marked as `TODO`. If a string is provided, that string is displayed in + * the test results as the reason why the test is `TODO`. + * @default false + */ + todo?: boolean | string | undefined; + /** + * The number of assertions and subtests expected to be run in the test. + * If the number of assertions run in the test does not match the number + * specified in the plan, the test will fail. + * @default undefined + * @since v22.2.0 + */ + plan?: number | undefined; + } + /** + * This function creates a hook that runs before executing a suite. + * + * ```js + * describe('tests', async () => { + * before(() => console.log('about to run some test')); + * it('is a subtest', () => { + * assert.ok('some relevant assertion here'); + * }); + * }); + * ``` + * @since v18.8.0, v16.18.0 + * @param fn The hook function. If the hook uses callbacks, the callback function is passed as the second argument. + * @param options Configuration options for the hook. + */ + function before(fn?: HookFn, options?: HookOptions): void; + /** + * This function creates a hook that runs after executing a suite. + * + * ```js + * describe('tests', async () => { + * after(() => console.log('finished running tests')); + * it('is a subtest', () => { + * assert.ok('some relevant assertion here'); + * }); + * }); + * ``` + * @since v18.8.0, v16.18.0 + * @param fn The hook function. If the hook uses callbacks, the callback function is passed as the second argument. + * @param options Configuration options for the hook. + */ + function after(fn?: HookFn, options?: HookOptions): void; + /** + * This function creates a hook that runs before each test in the current suite. + * + * ```js + * describe('tests', async () => { + * beforeEach(() => console.log('about to run a test')); + * it('is a subtest', () => { + * assert.ok('some relevant assertion here'); + * }); + * }); + * ``` + * @since v18.8.0, v16.18.0 + * @param fn The hook function. If the hook uses callbacks, the callback function is passed as the second argument. + * @param options Configuration options for the hook. + */ + function beforeEach(fn?: HookFn, options?: HookOptions): void; + /** + * This function creates a hook that runs after each test in the current suite. + * The `afterEach()` hook is run even if the test fails. + * + * ```js + * describe('tests', async () => { + * afterEach(() => console.log('finished running a test')); + * it('is a subtest', () => { + * assert.ok('some relevant assertion here'); + * }); + * }); + * ``` + * @since v18.8.0, v16.18.0 + * @param fn The hook function. If the hook uses callbacks, the callback function is passed as the second argument. + * @param options Configuration options for the hook. + */ + function afterEach(fn?: HookFn, options?: HookOptions): void; + /** + * The hook function. The first argument is the context in which the hook is called. + * If the hook uses callbacks, the callback function is passed as the second argument. + */ + type HookFn = (c: TestContext | SuiteContext, done: (result?: any) => void) => any; + /** + * The hook function. The first argument is a `TestContext` object. + * If the hook uses callbacks, the callback function is passed as the second argument. + */ + type TestContextHookFn = (t: TestContext, done: (result?: any) => void) => any; + /** + * Configuration options for hooks. + * @since v18.8.0 + */ + interface HookOptions { + /** + * Allows aborting an in-progress hook. + */ + signal?: AbortSignal | undefined; + /** + * A number of milliseconds the hook will fail after. If unspecified, subtests inherit this + * value from their parent. + * @default Infinity + */ + timeout?: number | undefined; + } + interface MockFunctionOptions { + /** + * The number of times that the mock will use the behavior of `implementation`. + * Once the mock function has been called `times` times, + * it will automatically restore the behavior of `original`. + * This value must be an integer greater than zero. + * @default Infinity + */ + times?: number | undefined; + } + interface MockMethodOptions extends MockFunctionOptions { + /** + * If `true`, `object[methodName]` is treated as a getter. + * This option cannot be used with the `setter` option. + */ + getter?: boolean | undefined; + /** + * If `true`, `object[methodName]` is treated as a setter. + * This option cannot be used with the `getter` option. + */ + setter?: boolean | undefined; + } + type Mock<F extends Function> = F & { + mock: MockFunctionContext<F>; + }; + interface MockModuleOptions { + /** + * If false, each call to `require()` or `import()` generates a new mock module. + * If true, subsequent calls will return the same module mock, and the mock module is inserted into the CommonJS cache. + * @default false + */ + cache?: boolean | undefined; + /** + * The value to use as the mocked module's default export. + * + * If this value is not provided, ESM mocks do not include a default export. + * If the mock is a CommonJS or builtin module, this setting is used as the value of `module.exports`. + * If this value is not provided, CJS and builtin mocks use an empty object as the value of `module.exports`. + */ + defaultExport?: any; + /** + * An object whose keys and values are used to create the named exports of the mock module. + * + * If the mock is a CommonJS or builtin module, these values are copied onto `module.exports`. + * Therefore, if a mock is created with both named exports and a non-object default export, + * the mock will throw an exception when used as a CJS or builtin module. + */ + namedExports?: object | undefined; + } + /** + * The `MockTracker` class is used to manage mocking functionality. The test runner + * module provides a top level `mock` export which is a `MockTracker` instance. + * Each test also provides its own `MockTracker` instance via the test context's `mock` property. + * @since v19.1.0, v18.13.0 + */ + interface MockTracker { + /** + * This function is used to create a mock function. + * + * The following example creates a mock function that increments a counter by one + * on each invocation. The `times` option is used to modify the mock behavior such + * that the first two invocations add two to the counter instead of one. + * + * ```js + * test('mocks a counting function', (t) => { + * let cnt = 0; + * + * function addOne() { + * cnt++; + * return cnt; + * } + * + * function addTwo() { + * cnt += 2; + * return cnt; + * } + * + * const fn = t.mock.fn(addOne, addTwo, { times: 2 }); + * + * assert.strictEqual(fn(), 2); + * assert.strictEqual(fn(), 4); + * assert.strictEqual(fn(), 5); + * assert.strictEqual(fn(), 6); + * }); + * ``` + * @since v19.1.0, v18.13.0 + * @param original An optional function to create a mock on. + * @param implementation An optional function used as the mock implementation for `original`. This is useful for creating mocks that exhibit one behavior for a specified number of calls and + * then restore the behavior of `original`. + * @param options Optional configuration options for the mock function. + * @return The mocked function. The mocked function contains a special `mock` property, which is an instance of {@link MockFunctionContext}, and can be used for inspecting and changing the + * behavior of the mocked function. + */ + fn<F extends Function = (...args: any[]) => undefined>( + original?: F, + options?: MockFunctionOptions, + ): Mock<F>; + fn<F extends Function = (...args: any[]) => undefined, Implementation extends Function = F>( + original?: F, + implementation?: Implementation, + options?: MockFunctionOptions, + ): Mock<F | Implementation>; + /** + * This function is used to create a mock on an existing object method. The + * following example demonstrates how a mock is created on an existing object + * method. + * + * ```js + * test('spies on an object method', (t) => { + * const number = { + * value: 5, + * subtract(a) { + * return this.value - a; + * }, + * }; + * + * t.mock.method(number, 'subtract'); + * assert.strictEqual(number.subtract.mock.calls.length, 0); + * assert.strictEqual(number.subtract(3), 2); + * assert.strictEqual(number.subtract.mock.calls.length, 1); + * + * const call = number.subtract.mock.calls[0]; + * + * assert.deepStrictEqual(call.arguments, [3]); + * assert.strictEqual(call.result, 2); + * assert.strictEqual(call.error, undefined); + * assert.strictEqual(call.target, undefined); + * assert.strictEqual(call.this, number); + * }); + * ``` + * @since v19.1.0, v18.13.0 + * @param object The object whose method is being mocked. + * @param methodName The identifier of the method on `object` to mock. If `object[methodName]` is not a function, an error is thrown. + * @param implementation An optional function used as the mock implementation for `object[methodName]`. + * @param options Optional configuration options for the mock method. + * @return The mocked method. The mocked method contains a special `mock` property, which is an instance of {@link MockFunctionContext}, and can be used for inspecting and changing the + * behavior of the mocked method. + */ + method< + MockedObject extends object, + MethodName extends FunctionPropertyNames<MockedObject>, + >( + object: MockedObject, + methodName: MethodName, + options?: MockFunctionOptions, + ): MockedObject[MethodName] extends Function ? Mock<MockedObject[MethodName]> + : never; + method< + MockedObject extends object, + MethodName extends FunctionPropertyNames<MockedObject>, + Implementation extends Function, + >( + object: MockedObject, + methodName: MethodName, + implementation: Implementation, + options?: MockFunctionOptions, + ): MockedObject[MethodName] extends Function ? Mock<MockedObject[MethodName] | Implementation> + : never; + method<MockedObject extends object>( + object: MockedObject, + methodName: keyof MockedObject, + options: MockMethodOptions, + ): Mock<Function>; + method<MockedObject extends object>( + object: MockedObject, + methodName: keyof MockedObject, + implementation: Function, + options: MockMethodOptions, + ): Mock<Function>; + /** + * This function is syntax sugar for `MockTracker.method` with `options.getter` set to `true`. + * @since v19.3.0, v18.13.0 + */ + getter< + MockedObject extends object, + MethodName extends keyof MockedObject, + >( + object: MockedObject, + methodName: MethodName, + options?: MockFunctionOptions, + ): Mock<() => MockedObject[MethodName]>; + getter< + MockedObject extends object, + MethodName extends keyof MockedObject, + Implementation extends Function, + >( + object: MockedObject, + methodName: MethodName, + implementation?: Implementation, + options?: MockFunctionOptions, + ): Mock<(() => MockedObject[MethodName]) | Implementation>; + /** + * This function is syntax sugar for `MockTracker.method` with `options.setter` set to `true`. + * @since v19.3.0, v18.13.0 + */ + setter< + MockedObject extends object, + MethodName extends keyof MockedObject, + >( + object: MockedObject, + methodName: MethodName, + options?: MockFunctionOptions, + ): Mock<(value: MockedObject[MethodName]) => void>; + setter< + MockedObject extends object, + MethodName extends keyof MockedObject, + Implementation extends Function, + >( + object: MockedObject, + methodName: MethodName, + implementation?: Implementation, + options?: MockFunctionOptions, + ): Mock<((value: MockedObject[MethodName]) => void) | Implementation>; + /** + * This function is used to mock the exports of ECMAScript modules, CommonJS modules, JSON modules, and + * Node.js builtin modules. Any references to the original module prior to mocking are not impacted. In + * order to enable module mocking, Node.js must be started with the + * [`--experimental-test-module-mocks`](https://nodejs.org/docs/latest-v25.x/api/cli.html#--experimental-test-module-mocks) + * command-line flag. + * + * The following example demonstrates how a mock is created for a module. + * + * ```js + * test('mocks a builtin module in both module systems', async (t) => { + * // Create a mock of 'node:readline' with a named export named 'fn', which + * // does not exist in the original 'node:readline' module. + * const mock = t.mock.module('node:readline', { + * namedExports: { fn() { return 42; } }, + * }); + * + * let esmImpl = await import('node:readline'); + * let cjsImpl = require('node:readline'); + * + * // cursorTo() is an export of the original 'node:readline' module. + * assert.strictEqual(esmImpl.cursorTo, undefined); + * assert.strictEqual(cjsImpl.cursorTo, undefined); + * assert.strictEqual(esmImpl.fn(), 42); + * assert.strictEqual(cjsImpl.fn(), 42); + * + * mock.restore(); + * + * // The mock is restored, so the original builtin module is returned. + * esmImpl = await import('node:readline'); + * cjsImpl = require('node:readline'); + * + * assert.strictEqual(typeof esmImpl.cursorTo, 'function'); + * assert.strictEqual(typeof cjsImpl.cursorTo, 'function'); + * assert.strictEqual(esmImpl.fn, undefined); + * assert.strictEqual(cjsImpl.fn, undefined); + * }); + * ``` + * @since v22.3.0 + * @experimental + * @param specifier A string identifying the module to mock. + * @param options Optional configuration options for the mock module. + */ + module(specifier: string | URL, options?: MockModuleOptions): MockModuleContext; + /** + * Creates a mock for a property value on an object. This allows you to track and control access to a specific property, + * including how many times it is read (getter) or written (setter), and to restore the original value after mocking. + * + * ```js + * test('mocks a property value', (t) => { + * const obj = { foo: 42 }; + * const prop = t.mock.property(obj, 'foo', 100); + * + * assert.strictEqual(obj.foo, 100); + * assert.strictEqual(prop.mock.accessCount(), 1); + * assert.strictEqual(prop.mock.accesses[0].type, 'get'); + * assert.strictEqual(prop.mock.accesses[0].value, 100); + * + * obj.foo = 200; + * assert.strictEqual(prop.mock.accessCount(), 2); + * assert.strictEqual(prop.mock.accesses[1].type, 'set'); + * assert.strictEqual(prop.mock.accesses[1].value, 200); + * + * prop.mock.restore(); + * assert.strictEqual(obj.foo, 42); + * }); + * ``` + * @since v24.3.0 + * @param object The object whose value is being mocked. + * @param propertyName The identifier of the property on `object` to mock. + * @param value An optional value used as the mock value + * for `object[propertyName]`. **Default:** The original property value. + * @returns A proxy to the mocked object. The mocked object contains a + * special `mock` property, which is an instance of [`MockPropertyContext`][], and + * can be used for inspecting and changing the behavior of the mocked property. + */ + property< + MockedObject extends object, + PropertyName extends keyof MockedObject, + >( + object: MockedObject, + property: PropertyName, + value?: MockedObject[PropertyName], + ): MockedObject & { mock: MockPropertyContext<MockedObject[PropertyName]> }; + /** + * This function restores the default behavior of all mocks that were previously + * created by this `MockTracker` and disassociates the mocks from the `MockTracker` instance. Once disassociated, the mocks can still be used, but the `MockTracker` instance can no longer be + * used to reset their behavior or + * otherwise interact with them. + * + * After each test completes, this function is called on the test context's `MockTracker`. If the global `MockTracker` is used extensively, calling this + * function manually is recommended. + * @since v19.1.0, v18.13.0 + */ + reset(): void; + /** + * This function restores the default behavior of all mocks that were previously + * created by this `MockTracker`. Unlike `mock.reset()`, `mock.restoreAll()` does + * not disassociate the mocks from the `MockTracker` instance. + * @since v19.1.0, v18.13.0 + */ + restoreAll(): void; + readonly timers: MockTimers; + } + const mock: MockTracker; + interface MockFunctionCall< + F extends Function, + ReturnType = F extends (...args: any) => infer T ? T + : F extends abstract new(...args: any) => infer T ? T + : unknown, + Args = F extends (...args: infer Y) => any ? Y + : F extends abstract new(...args: infer Y) => any ? Y + : unknown[], + > { + /** + * An array of the arguments passed to the mock function. + */ + arguments: Args; + /** + * If the mocked function threw then this property contains the thrown value. + */ + error: unknown | undefined; + /** + * The value returned by the mocked function. + * + * If the mocked function threw, it will be `undefined`. + */ + result: ReturnType | undefined; + /** + * An `Error` object whose stack can be used to determine the callsite of the mocked function invocation. + */ + stack: Error; + /** + * If the mocked function is a constructor, this field contains the class being constructed. + * Otherwise this will be `undefined`. + */ + target: F extends abstract new(...args: any) => any ? F : undefined; + /** + * The mocked function's `this` value. + */ + this: unknown; + } + /** + * The `MockFunctionContext` class is used to inspect or manipulate the behavior of + * mocks created via the `MockTracker` APIs. + * @since v19.1.0, v18.13.0 + */ + interface MockFunctionContext<F extends Function> { + /** + * A getter that returns a copy of the internal array used to track calls to the + * mock. Each entry in the array is an object with the following properties. + * @since v19.1.0, v18.13.0 + */ + readonly calls: MockFunctionCall<F>[]; + /** + * This function returns the number of times that this mock has been invoked. This + * function is more efficient than checking `ctx.calls.length` because `ctx.calls` is a getter that creates a copy of the internal call tracking array. + * @since v19.1.0, v18.13.0 + * @return The number of times that this mock has been invoked. + */ + callCount(): number; + /** + * This function is used to change the behavior of an existing mock. + * + * The following example creates a mock function using `t.mock.fn()`, calls the + * mock function, and then changes the mock implementation to a different function. + * + * ```js + * test('changes a mock behavior', (t) => { + * let cnt = 0; + * + * function addOne() { + * cnt++; + * return cnt; + * } + * + * function addTwo() { + * cnt += 2; + * return cnt; + * } + * + * const fn = t.mock.fn(addOne); + * + * assert.strictEqual(fn(), 1); + * fn.mock.mockImplementation(addTwo); + * assert.strictEqual(fn(), 3); + * assert.strictEqual(fn(), 5); + * }); + * ``` + * @since v19.1.0, v18.13.0 + * @param implementation The function to be used as the mock's new implementation. + */ + mockImplementation(implementation: F): void; + /** + * This function is used to change the behavior of an existing mock for a single + * invocation. Once invocation `onCall` has occurred, the mock will revert to + * whatever behavior it would have used had `mockImplementationOnce()` not been + * called. + * + * The following example creates a mock function using `t.mock.fn()`, calls the + * mock function, changes the mock implementation to a different function for the + * next invocation, and then resumes its previous behavior. + * + * ```js + * test('changes a mock behavior once', (t) => { + * let cnt = 0; + * + * function addOne() { + * cnt++; + * return cnt; + * } + * + * function addTwo() { + * cnt += 2; + * return cnt; + * } + * + * const fn = t.mock.fn(addOne); + * + * assert.strictEqual(fn(), 1); + * fn.mock.mockImplementationOnce(addTwo); + * assert.strictEqual(fn(), 3); + * assert.strictEqual(fn(), 4); + * }); + * ``` + * @since v19.1.0, v18.13.0 + * @param implementation The function to be used as the mock's implementation for the invocation number specified by `onCall`. + * @param onCall The invocation number that will use `implementation`. If the specified invocation has already occurred then an exception is thrown. + */ + mockImplementationOnce(implementation: F, onCall?: number): void; + /** + * Resets the call history of the mock function. + * @since v19.3.0, v18.13.0 + */ + resetCalls(): void; + /** + * Resets the implementation of the mock function to its original behavior. The + * mock can still be used after calling this function. + * @since v19.1.0, v18.13.0 + */ + restore(): void; + } + /** + * @since v22.3.0 + * @experimental + */ + interface MockModuleContext { + /** + * Resets the implementation of the mock module. + * @since v22.3.0 + */ + restore(): void; + } + /** + * @since v24.3.0 + */ + class MockPropertyContext<PropertyType = any> { + /** + * A getter that returns a copy of the internal array used to track accesses (get/set) to + * the mocked property. Each entry in the array is an object with the following properties: + */ + readonly accesses: Array<{ + type: "get" | "set"; + value: PropertyType; + stack: Error; + }>; + /** + * This function returns the number of times that the property was accessed. + * This function is more efficient than checking `ctx.accesses.length` because + * `ctx.accesses` is a getter that creates a copy of the internal access tracking array. + * @returns The number of times that the property was accessed (read or written). + */ + accessCount(): number; + /** + * This function is used to change the value returned by the mocked property getter. + * @param value The new value to be set as the mocked property value. + */ + mockImplementation(value: PropertyType): void; + /** + * This function is used to change the behavior of an existing mock for a single + * invocation. Once invocation `onAccess` has occurred, the mock will revert to + * whatever behavior it would have used had `mockImplementationOnce()` not been + * called. + * + * The following example creates a mock function using `t.mock.property()`, calls the + * mock property, changes the mock implementation to a different value for the + * next invocation, and then resumes its previous behavior. + * + * ```js + * test('changes a mock behavior once', (t) => { + * const obj = { foo: 1 }; + * + * const prop = t.mock.property(obj, 'foo', 5); + * + * assert.strictEqual(obj.foo, 5); + * prop.mock.mockImplementationOnce(25); + * assert.strictEqual(obj.foo, 25); + * assert.strictEqual(obj.foo, 5); + * }); + * ``` + * @param value The value to be used as the mock's + * implementation for the invocation number specified by `onAccess`. + * @param onAccess The invocation number that will use `value`. If + * the specified invocation has already occurred then an exception is thrown. + * **Default:** The number of the next invocation. + */ + mockImplementationOnce(value: PropertyType, onAccess?: number): void; + /** + * Resets the access history of the mocked property. + */ + resetAccesses(): void; + /** + * Resets the implementation of the mock property to its original behavior. The + * mock can still be used after calling this function. + */ + restore(): void; + } + interface MockTimersOptions { + apis: ReadonlyArray<"setInterval" | "setTimeout" | "setImmediate" | "Date">; + now?: number | Date | undefined; + } + /** + * Mocking timers is a technique commonly used in software testing to simulate and + * control the behavior of timers, such as `setInterval` and `setTimeout`, + * without actually waiting for the specified time intervals. + * + * The MockTimers API also allows for mocking of the `Date` constructor and + * `setImmediate`/`clearImmediate` functions. + * + * The `MockTracker` provides a top-level `timers` export + * which is a `MockTimers` instance. + * @since v20.4.0 + */ + interface MockTimers { + /** + * Enables timer mocking for the specified timers. + * + * **Note:** When you enable mocking for a specific timer, its associated + * clear function will also be implicitly mocked. + * + * **Note:** Mocking `Date` will affect the behavior of the mocked timers + * as they use the same internal clock. + * + * Example usage without setting initial time: + * + * ```js + * import { mock } from 'node:test'; + * mock.timers.enable({ apis: ['setInterval', 'Date'], now: 1234 }); + * ``` + * + * The above example enables mocking for the `Date` constructor, `setInterval` timer and + * implicitly mocks the `clearInterval` function. Only the `Date` constructor from `globalThis`, + * `setInterval` and `clearInterval` functions from `node:timers`, `node:timers/promises`, and `globalThis` will be mocked. + * + * Example usage with initial time set + * + * ```js + * import { mock } from 'node:test'; + * mock.timers.enable({ apis: ['Date'], now: 1000 }); + * ``` + * + * Example usage with initial Date object as time set + * + * ```js + * import { mock } from 'node:test'; + * mock.timers.enable({ apis: ['Date'], now: new Date() }); + * ``` + * + * Alternatively, if you call `mock.timers.enable()` without any parameters: + * + * All timers (`'setInterval'`, `'clearInterval'`, `'Date'`, `'setImmediate'`, `'clearImmediate'`, `'setTimeout'`, and `'clearTimeout'`) + * will be mocked. + * + * The `setInterval`, `clearInterval`, `setTimeout`, and `clearTimeout` functions from `node:timers`, `node:timers/promises`, + * and `globalThis` will be mocked. + * The `Date` constructor from `globalThis` will be mocked. + * + * If there is no initial epoch set, the initial date will be based on 0 in the Unix epoch. This is `January 1st, 1970, 00:00:00 UTC`. You can + * set an initial date by passing a now property to the `.enable()` method. This value will be used as the initial date for the mocked Date + * object. It can either be a positive integer, or another Date object. + * @since v20.4.0 + */ + enable(options?: MockTimersOptions): void; + /** + * You can use the `.setTime()` method to manually move the mocked date to another time. This method only accepts a positive integer. + * Note: This method will execute any mocked timers that are in the past from the new time. + * In the below example we are setting a new time for the mocked date. + * ```js + * import assert from 'node:assert'; + * import { test } from 'node:test'; + * test('sets the time of a date object', (context) => { + * // Optionally choose what to mock + * context.mock.timers.enable({ apis: ['Date'], now: 100 }); + * assert.strictEqual(Date.now(), 100); + * // Advance in time will also advance the date + * context.mock.timers.setTime(1000); + * context.mock.timers.tick(200); + * assert.strictEqual(Date.now(), 1200); + * }); + * ``` + */ + setTime(time: number): void; + /** + * This function restores the default behavior of all mocks that were previously + * created by this `MockTimers` instance and disassociates the mocks + * from the `MockTracker` instance. + * + * **Note:** After each test completes, this function is called on + * the test context's `MockTracker`. + * + * ```js + * import { mock } from 'node:test'; + * mock.timers.reset(); + * ``` + * @since v20.4.0 + */ + reset(): void; + /** + * Advances time for all mocked timers. + * + * **Note:** This diverges from how `setTimeout` in Node.js behaves and accepts + * only positive numbers. In Node.js, `setTimeout` with negative numbers is + * only supported for web compatibility reasons. + * + * The following example mocks a `setTimeout` function and + * by using `.tick` advances in + * time triggering all pending timers. + * + * ```js + * import assert from 'node:assert'; + * import { test } from 'node:test'; + * + * test('mocks setTimeout to be executed synchronously without having to actually wait for it', (context) => { + * const fn = context.mock.fn(); + * + * context.mock.timers.enable({ apis: ['setTimeout'] }); + * + * setTimeout(fn, 9999); + * + * assert.strictEqual(fn.mock.callCount(), 0); + * + * // Advance in time + * context.mock.timers.tick(9999); + * + * assert.strictEqual(fn.mock.callCount(), 1); + * }); + * ``` + * + * Alternativelly, the `.tick` function can be called many times + * + * ```js + * import assert from 'node:assert'; + * import { test } from 'node:test'; + * + * test('mocks setTimeout to be executed synchronously without having to actually wait for it', (context) => { + * const fn = context.mock.fn(); + * context.mock.timers.enable({ apis: ['setTimeout'] }); + * const nineSecs = 9000; + * setTimeout(fn, nineSecs); + * + * const twoSeconds = 3000; + * context.mock.timers.tick(twoSeconds); + * context.mock.timers.tick(twoSeconds); + * context.mock.timers.tick(twoSeconds); + * + * assert.strictEqual(fn.mock.callCount(), 1); + * }); + * ``` + * + * Advancing time using `.tick` will also advance the time for any `Date` object + * created after the mock was enabled (if `Date` was also set to be mocked). + * + * ```js + * import assert from 'node:assert'; + * import { test } from 'node:test'; + * + * test('mocks setTimeout to be executed synchronously without having to actually wait for it', (context) => { + * const fn = context.mock.fn(); + * + * context.mock.timers.enable({ apis: ['setTimeout', 'Date'] }); + * setTimeout(fn, 9999); + * + * assert.strictEqual(fn.mock.callCount(), 0); + * assert.strictEqual(Date.now(), 0); + * + * // Advance in time + * context.mock.timers.tick(9999); + * assert.strictEqual(fn.mock.callCount(), 1); + * assert.strictEqual(Date.now(), 9999); + * }); + * ``` + * @since v20.4.0 + */ + tick(milliseconds: number): void; + /** + * Triggers all pending mocked timers immediately. If the `Date` object is also + * mocked, it will also advance the `Date` object to the furthest timer's time. + * + * The example below triggers all pending timers immediately, + * causing them to execute without any delay. + * + * ```js + * import assert from 'node:assert'; + * import { test } from 'node:test'; + * + * test('runAll functions following the given order', (context) => { + * context.mock.timers.enable({ apis: ['setTimeout', 'Date'] }); + * const results = []; + * setTimeout(() => results.push(1), 9999); + * + * // Notice that if both timers have the same timeout, + * // the order of execution is guaranteed + * setTimeout(() => results.push(3), 8888); + * setTimeout(() => results.push(2), 8888); + * + * assert.deepStrictEqual(results, []); + * + * context.mock.timers.runAll(); + * assert.deepStrictEqual(results, [3, 2, 1]); + * // The Date object is also advanced to the furthest timer's time + * assert.strictEqual(Date.now(), 9999); + * }); + * ``` + * + * **Note:** The `runAll()` function is specifically designed for + * triggering timers in the context of timer mocking. + * It does not have any effect on real-time system + * clocks or actual timers outside of the mocking environment. + * @since v20.4.0 + */ + runAll(): void; + /** + * Calls {@link MockTimers.reset()}. + */ + [Symbol.dispose](): void; + } + /** + * An object whose methods are used to configure available assertions on the + * `TestContext` objects in the current process. The methods from `node:assert` + * and snapshot testing functions are available by default. + * + * It is possible to apply the same configuration to all files by placing common + * configuration code in a module + * preloaded with `--require` or `--import`. + * @since v22.14.0 + */ + namespace assert { + /** + * Defines a new assertion function with the provided name and function. If an + * assertion already exists with the same name, it is overwritten. + * @since v22.14.0 + */ + function register(name: string, fn: (this: TestContext, ...args: any[]) => void): void; + } + /** + * @since v22.3.0 + */ + namespace snapshot { + /** + * This function is used to customize the default serialization mechanism used by the test runner. + * + * By default, the test runner performs serialization by calling `JSON.stringify(value, null, 2)` on the provided value. + * `JSON.stringify()` does have limitations regarding circular structures and supported data types. + * If a more robust serialization mechanism is required, this function should be used to specify a list of custom serializers. + * + * Serializers are called in order, with the output of the previous serializer passed as input to the next. + * The final result must be a string value. + * @since v22.3.0 + * @param serializers An array of synchronous functions used as the default serializers for snapshot tests. + */ + function setDefaultSnapshotSerializers(serializers: ReadonlyArray<(value: any) => any>): void; + /** + * This function is used to set a custom resolver for the location of the snapshot file used for snapshot testing. + * By default, the snapshot filename is the same as the entry point filename with `.snapshot` appended. + * @since v22.3.0 + * @param fn A function used to compute the location of the snapshot file. + * The function receives the path of the test file as its only argument. If the + * test is not associated with a file (for example in the REPL), the input is + * undefined. `fn()` must return a string specifying the location of the snapshot file. + */ + function setResolveSnapshotPath(fn: (path: string | undefined) => string): void; + } + } + type FunctionPropertyNames<T> = { + [K in keyof T]: T[K] extends Function ? K : never; + }[keyof T]; + export = test; +} diff --git a/server/node_modules/@types/node/test/reporters.d.ts b/server/node_modules/@types/node/test/reporters.d.ts new file mode 100644 index 0000000..465e80d --- /dev/null +++ b/server/node_modules/@types/node/test/reporters.d.ts @@ -0,0 +1,96 @@ +/** + * The `node:test` module supports passing `--test-reporter` + * flags for the test runner to use a specific reporter. + * + * The following built-reporters are supported: + * + * * `spec` + * The `spec` reporter outputs the test results in a human-readable format. This + * is the default reporter. + * + * * `tap` + * The `tap` reporter outputs the test results in the [TAP](https://testanything.org/) format. + * + * * `dot` + * The `dot` reporter outputs the test results in a compact format, + * where each passing test is represented by a `.`, + * and each failing test is represented by a `X`. + * + * * `junit` + * The junit reporter outputs test results in a jUnit XML format + * + * * `lcov` + * The `lcov` reporter outputs test coverage when used with the + * `--experimental-test-coverage` flag. + * + * The exact output of these reporters is subject to change between versions of + * Node.js, and should not be relied on programmatically. If programmatic access + * to the test runner's output is required, use the events emitted by the + * `TestsStream`. + * + * The reporters are available via the `node:test/reporters` module: + * + * ```js + * import { tap, spec, dot, junit, lcov } from 'node:test/reporters'; + * ``` + * @since v19.9.0, v18.17.0 + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/test/reporters.js) + */ +declare module "node:test/reporters" { + import { Transform, TransformOptions } from "node:stream"; + import { EventData } from "node:test"; + type TestEvent = + | { type: "test:coverage"; data: EventData.TestCoverage } + | { type: "test:complete"; data: EventData.TestComplete } + | { type: "test:dequeue"; data: EventData.TestDequeue } + | { type: "test:diagnostic"; data: EventData.TestDiagnostic } + | { type: "test:enqueue"; data: EventData.TestEnqueue } + | { type: "test:fail"; data: EventData.TestFail } + | { type: "test:pass"; data: EventData.TestPass } + | { type: "test:plan"; data: EventData.TestPlan } + | { type: "test:start"; data: EventData.TestStart } + | { type: "test:stderr"; data: EventData.TestStderr } + | { type: "test:stdout"; data: EventData.TestStdout } + | { type: "test:summary"; data: EventData.TestSummary } + | { type: "test:watch:drained"; data: undefined } + | { type: "test:watch:restarted"; data: undefined }; + interface ReporterConstructorWrapper<T extends new(...args: any[]) => Transform> { + new(...args: ConstructorParameters<T>): InstanceType<T>; + (...args: ConstructorParameters<T>): InstanceType<T>; + } + /** + * The `dot` reporter outputs the test results in a compact format, + * where each passing test is represented by a `.`, + * and each failing test is represented by a `X`. + * @since v20.0.0 + */ + function dot(source: AsyncIterable<TestEvent>): NodeJS.AsyncIterator<string>; + /** + * The `tap` reporter outputs the test results in the [TAP](https://testanything.org/) format. + * @since v20.0.0 + */ + function tap(source: AsyncIterable<TestEvent>): NodeJS.AsyncIterator<string>; + class SpecReporter extends Transform { + constructor(); + } + /** + * The `spec` reporter outputs the test results in a human-readable format. + * @since v20.0.0 + */ + const spec: ReporterConstructorWrapper<typeof SpecReporter>; + /** + * The `junit` reporter outputs test results in a jUnit XML format. + * @since v21.0.0 + */ + function junit(source: AsyncIterable<TestEvent>): NodeJS.AsyncIterator<string>; + class LcovReporter extends Transform { + constructor(options?: Omit<TransformOptions, "writableObjectMode">); + } + /** + * The `lcov` reporter outputs test coverage when used with the + * [`--experimental-test-coverage`](https://nodejs.org/docs/latest-v25.x/api/cli.html#--experimental-test-coverage) flag. + * @since v22.0.0 + */ + const lcov: ReporterConstructorWrapper<typeof LcovReporter>; + export { dot, junit, lcov, spec, tap, TestEvent }; +} diff --git a/server/node_modules/@types/node/timers.d.ts b/server/node_modules/@types/node/timers.d.ts new file mode 100644 index 0000000..00a8cd0 --- /dev/null +++ b/server/node_modules/@types/node/timers.d.ts @@ -0,0 +1,159 @@ +/** + * The `timer` module exposes a global API for scheduling functions to + * be called at some future period of time. Because the timer functions are + * globals, there is no need to import `node:timers` to use the API. + * + * The timer functions within Node.js implement a similar API as the timers API + * provided by Web Browsers but use a different internal implementation that is + * built around the Node.js [Event Loop](https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/#setimmediate-vs-settimeout). + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/timers.js) + */ +declare module "node:timers" { + import { Abortable } from "node:events"; + import * as promises from "node:timers/promises"; + export interface TimerOptions extends Abortable { + /** + * Set to `false` to indicate that the scheduled `Timeout` + * should not require the Node.js event loop to remain active. + * @default true + */ + ref?: boolean | undefined; + } + global { + namespace NodeJS { + /** + * This object is created internally and is returned from `setImmediate()`. It + * can be passed to `clearImmediate()` in order to cancel the scheduled + * actions. + * + * By default, when an immediate is scheduled, the Node.js event loop will continue + * running as long as the immediate is active. The `Immediate` object returned by + * `setImmediate()` exports both `immediate.ref()` and `immediate.unref()` + * functions that can be used to control this default behavior. + */ + interface Immediate extends RefCounted, Disposable { + /** + * If true, the `Immediate` object will keep the Node.js event loop active. + * @since v11.0.0 + */ + hasRef(): boolean; + /** + * When called, requests that the Node.js event loop _not_ exit so long as the + * `Immediate` is active. Calling `immediate.ref()` multiple times will have no + * effect. + * + * By default, all `Immediate` objects are "ref'ed", making it normally unnecessary + * to call `immediate.ref()` unless `immediate.unref()` had been called previously. + * @since v9.7.0 + * @returns a reference to `immediate` + */ + ref(): this; + /** + * When called, the active `Immediate` object will not require the Node.js event + * loop to remain active. If there is no other activity keeping the event loop + * running, the process may exit before the `Immediate` object's callback is + * invoked. Calling `immediate.unref()` multiple times will have no effect. + * @since v9.7.0 + * @returns a reference to `immediate` + */ + unref(): this; + /** + * Cancels the immediate. This is similar to calling `clearImmediate()`. + * @since v20.5.0, v18.18.0 + */ + [Symbol.dispose](): void; + _onImmediate(...args: any[]): void; + } + // Legacy interface used in Node.js v9 and prior + // TODO: remove in a future major version bump + /** @deprecated Use `NodeJS.Timeout` instead. */ + interface Timer extends RefCounted { + hasRef(): boolean; + refresh(): this; + [Symbol.toPrimitive](): number; + } + /** + * This object is created internally and is returned from `setTimeout()` and + * `setInterval()`. It can be passed to either `clearTimeout()` or + * `clearInterval()` in order to cancel the scheduled actions. + * + * By default, when a timer is scheduled using either `setTimeout()` or + * `setInterval()`, the Node.js event loop will continue running as long as the + * timer is active. Each of the `Timeout` objects returned by these functions + * export both `timeout.ref()` and `timeout.unref()` functions that can be used to + * control this default behavior. + */ + interface Timeout extends RefCounted, Disposable, Timer { + /** + * Cancels the timeout. + * @since v0.9.1 + * @legacy Use `clearTimeout()` instead. + * @returns a reference to `timeout` + */ + close(): this; + /** + * If true, the `Timeout` object will keep the Node.js event loop active. + * @since v11.0.0 + */ + hasRef(): boolean; + /** + * When called, requests that the Node.js event loop _not_ exit so long as the + * `Timeout` is active. Calling `timeout.ref()` multiple times will have no effect. + * + * By default, all `Timeout` objects are "ref'ed", making it normally unnecessary + * to call `timeout.ref()` unless `timeout.unref()` had been called previously. + * @since v0.9.1 + * @returns a reference to `timeout` + */ + ref(): this; + /** + * Sets the timer's start time to the current time, and reschedules the timer to + * call its callback at the previously specified duration adjusted to the current + * time. This is useful for refreshing a timer without allocating a new + * JavaScript object. + * + * Using this on a timer that has already called its callback will reactivate the + * timer. + * @since v10.2.0 + * @returns a reference to `timeout` + */ + refresh(): this; + /** + * When called, the active `Timeout` object will not require the Node.js event loop + * to remain active. If there is no other activity keeping the event loop running, + * the process may exit before the `Timeout` object's callback is invoked. Calling + * `timeout.unref()` multiple times will have no effect. + * @since v0.9.1 + * @returns a reference to `timeout` + */ + unref(): this; + /** + * Coerce a `Timeout` to a primitive. The primitive can be used to + * clear the `Timeout`. The primitive can only be used in the + * same thread where the timeout was created. Therefore, to use it + * across `worker_threads` it must first be passed to the correct + * thread. This allows enhanced compatibility with browser + * `setTimeout()` and `setInterval()` implementations. + * @since v14.9.0, v12.19.0 + */ + [Symbol.toPrimitive](): number; + /** + * Cancels the timeout. + * @since v20.5.0, v18.18.0 + */ + [Symbol.dispose](): void; + _onTimeout(...args: any[]): void; + } + } + } + import clearImmediate = globalThis.clearImmediate; + import clearInterval = globalThis.clearInterval; + import clearTimeout = globalThis.clearTimeout; + import setImmediate = globalThis.setImmediate; + import setInterval = globalThis.setInterval; + import setTimeout = globalThis.setTimeout; + export { clearImmediate, clearInterval, clearTimeout, promises, setImmediate, setInterval, setTimeout }; +} +declare module "timers" { + export * from "node:timers"; +} diff --git a/server/node_modules/@types/node/timers/promises.d.ts b/server/node_modules/@types/node/timers/promises.d.ts new file mode 100644 index 0000000..85bc831 --- /dev/null +++ b/server/node_modules/@types/node/timers/promises.d.ts @@ -0,0 +1,108 @@ +/** + * The `timers/promises` API provides an alternative set of timer functions + * that return `Promise` objects. The API is accessible via + * `require('node:timers/promises')`. + * + * ```js + * import { + * setTimeout, + * setImmediate, + * setInterval, + * } from 'node:timers/promises'; + * ``` + * @since v15.0.0 + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/timers/promises.js) + */ +declare module "node:timers/promises" { + import { TimerOptions } from "node:timers"; + /** + * ```js + * import { + * setTimeout, + * } from 'node:timers/promises'; + * + * const res = await setTimeout(100, 'result'); + * + * console.log(res); // Prints 'result' + * ``` + * @since v15.0.0 + * @param delay The number of milliseconds to wait before fulfilling the + * promise. **Default:** `1`. + * @param value A value with which the promise is fulfilled. + */ + function setTimeout<T = void>(delay?: number, value?: T, options?: TimerOptions): Promise<T>; + /** + * ```js + * import { + * setImmediate, + * } from 'node:timers/promises'; + * + * const res = await setImmediate('result'); + * + * console.log(res); // Prints 'result' + * ``` + * @since v15.0.0 + * @param value A value with which the promise is fulfilled. + */ + function setImmediate<T = void>(value?: T, options?: TimerOptions): Promise<T>; + /** + * Returns an async iterator that generates values in an interval of `delay` ms. + * If `ref` is `true`, you need to call `next()` of async iterator explicitly + * or implicitly to keep the event loop alive. + * + * ```js + * import { + * setInterval, + * } from 'node:timers/promises'; + * + * const interval = 100; + * for await (const startTime of setInterval(interval, Date.now())) { + * const now = Date.now(); + * console.log(now); + * if ((now - startTime) > 1000) + * break; + * } + * console.log(Date.now()); + * ``` + * @since v15.9.0 + * @param delay The number of milliseconds to wait between iterations. + * **Default:** `1`. + * @param value A value with which the iterator returns. + */ + function setInterval<T = void>(delay?: number, value?: T, options?: TimerOptions): NodeJS.AsyncIterator<T>; + interface Scheduler { + /** + * An experimental API defined by the [Scheduling APIs](https://github.com/WICG/scheduling-apis) draft specification + * being developed as a standard Web Platform API. + * + * Calling `timersPromises.scheduler.wait(delay, options)` is roughly equivalent + * to calling `timersPromises.setTimeout(delay, undefined, options)` except that + * the `ref` option is not supported. + * + * ```js + * import { scheduler } from 'node:timers/promises'; + * + * await scheduler.wait(1000); // Wait one second before continuing + * ``` + * @since v17.3.0, v16.14.0 + * @experimental + * @param delay The number of milliseconds to wait before resolving the + * promise. + */ + wait(delay: number, options?: { signal?: AbortSignal }): Promise<void>; + /** + * An experimental API defined by the [Scheduling APIs](https://github.com/WICG/scheduling-apis) draft specification + * being developed as a standard Web Platform API. + * + * Calling `timersPromises.scheduler.yield()` is equivalent to calling + * `timersPromises.setImmediate()` with no arguments. + * @since v17.3.0, v16.14.0 + * @experimental + */ + yield(): Promise<void>; + } + const scheduler: Scheduler; +} +declare module "timers/promises" { + export * from "node:timers/promises"; +} diff --git a/server/node_modules/@types/node/tls.d.ts b/server/node_modules/@types/node/tls.d.ts new file mode 100644 index 0000000..5c45f93 --- /dev/null +++ b/server/node_modules/@types/node/tls.d.ts @@ -0,0 +1,1198 @@ +/** + * The `node:tls` module provides an implementation of the Transport Layer Security + * (TLS) and Secure Socket Layer (SSL) protocols that is built on top of OpenSSL. + * The module can be accessed using: + * + * ```js + * import tls from 'node:tls'; + * ``` + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/tls.js) + */ +declare module "node:tls" { + import { NonSharedBuffer } from "node:buffer"; + import { X509Certificate } from "node:crypto"; + import * as net from "node:net"; + import * as stream from "stream"; + const CLIENT_RENEG_LIMIT: number; + const CLIENT_RENEG_WINDOW: number; + interface Certificate { + /** + * Country code. + */ + C: string; + /** + * Street. + */ + ST: string; + /** + * Locality. + */ + L: string; + /** + * Organization. + */ + O: string; + /** + * Organizational unit. + */ + OU: string; + /** + * Common name. + */ + CN: string; + } + interface PeerCertificate { + /** + * `true` if a Certificate Authority (CA), `false` otherwise. + * @since v18.13.0 + */ + ca: boolean; + /** + * The DER encoded X.509 certificate data. + */ + raw: NonSharedBuffer; + /** + * The certificate subject. + */ + subject: Certificate; + /** + * The certificate issuer, described in the same terms as the `subject`. + */ + issuer: Certificate; + /** + * The date-time the certificate is valid from. + */ + valid_from: string; + /** + * The date-time the certificate is valid to. + */ + valid_to: string; + /** + * The certificate serial number, as a hex string. + */ + serialNumber: string; + /** + * The SHA-1 digest of the DER encoded certificate. + * It is returned as a `:` separated hexadecimal string. + */ + fingerprint: string; + /** + * The SHA-256 digest of the DER encoded certificate. + * It is returned as a `:` separated hexadecimal string. + */ + fingerprint256: string; + /** + * The SHA-512 digest of the DER encoded certificate. + * It is returned as a `:` separated hexadecimal string. + */ + fingerprint512: string; + /** + * The extended key usage, a set of OIDs. + */ + ext_key_usage?: string[]; + /** + * A string containing concatenated names for the subject, + * an alternative to the `subject` names. + */ + subjectaltname?: string; + /** + * An array describing the AuthorityInfoAccess, used with OCSP. + */ + infoAccess?: NodeJS.Dict<string[]>; + /** + * For RSA keys: The RSA bit size. + * + * For EC keys: The key size in bits. + */ + bits?: number; + /** + * The RSA exponent, as a string in hexadecimal number notation. + */ + exponent?: string; + /** + * The RSA modulus, as a hexadecimal string. + */ + modulus?: string; + /** + * The public key. + */ + pubkey?: NonSharedBuffer; + /** + * The ASN.1 name of the OID of the elliptic curve. + * Well-known curves are identified by an OID. + * While it is unusual, it is possible that the curve + * is identified by its mathematical properties, + * in which case it will not have an OID. + */ + asn1Curve?: string; + /** + * The NIST name for the elliptic curve, if it has one + * (not all well-known curves have been assigned names by NIST). + */ + nistCurve?: string; + } + interface DetailedPeerCertificate extends PeerCertificate { + /** + * The issuer certificate object. + * For self-signed certificates, this may be a circular reference. + */ + issuerCertificate: DetailedPeerCertificate; + } + interface CipherNameAndProtocol { + /** + * The cipher name. + */ + name: string; + /** + * SSL/TLS protocol version. + */ + version: string; + /** + * IETF name for the cipher suite. + */ + standardName: string; + } + interface EphemeralKeyInfo { + /** + * The supported types are 'DH' and 'ECDH'. + */ + type: string; + /** + * The name property is available only when type is 'ECDH'. + */ + name?: string | undefined; + /** + * The size of parameter of an ephemeral key exchange. + */ + size: number; + } + interface KeyObject { + /** + * Private keys in PEM format. + */ + pem: string | Buffer; + /** + * Optional passphrase. + */ + passphrase?: string | undefined; + } + interface PxfObject { + /** + * PFX or PKCS12 encoded private key and certificate chain. + */ + buf: string | Buffer; + /** + * Optional passphrase. + */ + passphrase?: string | undefined; + } + interface TLSSocketOptions extends SecureContextOptions, CommonConnectionOptions { + /** + * If true the TLS socket will be instantiated in server-mode. + * Defaults to false. + */ + isServer?: boolean | undefined; + /** + * An optional net.Server instance. + */ + server?: net.Server | undefined; + /** + * An optional Buffer instance containing a TLS session. + */ + session?: Buffer | undefined; + /** + * If true, specifies that the OCSP status request extension will be + * added to the client hello and an 'OCSPResponse' event will be + * emitted on the socket before establishing a secure communication + */ + requestOCSP?: boolean | undefined; + } + interface TLSSocketEventMap extends net.SocketEventMap { + "keylog": [line: NonSharedBuffer]; + "OCSPResponse": [response: NonSharedBuffer]; + "secureConnect": []; + "session": [session: NonSharedBuffer]; + } + /** + * Performs transparent encryption of written data and all required TLS + * negotiation. + * + * Instances of `tls.TLSSocket` implement the duplex `Stream` interface. + * + * Methods that return TLS connection metadata (e.g.{@link TLSSocket.getPeerCertificate}) will only return data while the + * connection is open. + * @since v0.11.4 + */ + class TLSSocket extends net.Socket { + /** + * Construct a new tls.TLSSocket object from an existing TCP socket. + */ + constructor(socket: net.Socket | stream.Duplex, options?: TLSSocketOptions); + /** + * This property is `true` if the peer certificate was signed by one of the CAs + * specified when creating the `tls.TLSSocket` instance, otherwise `false`. + * @since v0.11.4 + */ + authorized: boolean; + /** + * Returns the reason why the peer's certificate was not been verified. This + * property is set only when `tlsSocket.authorized === false`. + * @since v0.11.4 + */ + authorizationError: Error; + /** + * Always returns `true`. This may be used to distinguish TLS sockets from regular`net.Socket` instances. + * @since v0.11.4 + */ + encrypted: true; + /** + * String containing the selected ALPN protocol. + * Before a handshake has completed, this value is always null. + * When a handshake is completed but not ALPN protocol was selected, tlsSocket.alpnProtocol equals false. + */ + alpnProtocol: string | false | null; + /** + * String containing the server name requested via SNI (Server Name Indication) TLS extension. + */ + servername: string | false | null; + /** + * Returns an object representing the local certificate. The returned object has + * some properties corresponding to the fields of the certificate. + * + * See {@link TLSSocket.getPeerCertificate} for an example of the certificate + * structure. + * + * If there is no local certificate, an empty object will be returned. If the + * socket has been destroyed, `null` will be returned. + * @since v11.2.0 + */ + getCertificate(): PeerCertificate | object | null; + /** + * Returns an object containing information on the negotiated cipher suite. + * + * For example, a TLSv1.2 protocol with AES256-SHA cipher: + * + * ```json + * { + * "name": "AES256-SHA", + * "standardName": "TLS_RSA_WITH_AES_256_CBC_SHA", + * "version": "SSLv3" + * } + * ``` + * + * See [SSL\_CIPHER\_get\_name](https://www.openssl.org/docs/man1.1.1/man3/SSL_CIPHER_get_name.html) for more information. + * @since v0.11.4 + */ + getCipher(): CipherNameAndProtocol; + /** + * Returns an object representing the type, name, and size of parameter of + * an ephemeral key exchange in `perfect forward secrecy` on a client + * connection. It returns an empty object when the key exchange is not + * ephemeral. As this is only supported on a client socket; `null` is returned + * if called on a server socket. The supported types are `'DH'` and `'ECDH'`. The `name` property is available only when type is `'ECDH'`. + * + * For example: `{ type: 'ECDH', name: 'prime256v1', size: 256 }`. + * @since v5.0.0 + */ + getEphemeralKeyInfo(): EphemeralKeyInfo | object | null; + /** + * As the `Finished` messages are message digests of the complete handshake + * (with a total of 192 bits for TLS 1.0 and more for SSL 3.0), they can + * be used for external authentication procedures when the authentication + * provided by SSL/TLS is not desired or is not enough. + * + * Corresponds to the `SSL_get_finished` routine in OpenSSL and may be used + * to implement the `tls-unique` channel binding from [RFC 5929](https://tools.ietf.org/html/rfc5929). + * @since v9.9.0 + * @return The latest `Finished` message that has been sent to the socket as part of a SSL/TLS handshake, or `undefined` if no `Finished` message has been sent yet. + */ + getFinished(): NonSharedBuffer | undefined; + /** + * Returns an object representing the peer's certificate. If the peer does not + * provide a certificate, an empty object will be returned. If the socket has been + * destroyed, `null` will be returned. + * + * If the full certificate chain was requested, each certificate will include an`issuerCertificate` property containing an object representing its issuer's + * certificate. + * @since v0.11.4 + * @param detailed Include the full certificate chain if `true`, otherwise include just the peer's certificate. + * @return A certificate object. + */ + getPeerCertificate(detailed: true): DetailedPeerCertificate; + getPeerCertificate(detailed?: false): PeerCertificate; + getPeerCertificate(detailed?: boolean): PeerCertificate | DetailedPeerCertificate; + /** + * As the `Finished` messages are message digests of the complete handshake + * (with a total of 192 bits for TLS 1.0 and more for SSL 3.0), they can + * be used for external authentication procedures when the authentication + * provided by SSL/TLS is not desired or is not enough. + * + * Corresponds to the `SSL_get_peer_finished` routine in OpenSSL and may be used + * to implement the `tls-unique` channel binding from [RFC 5929](https://tools.ietf.org/html/rfc5929). + * @since v9.9.0 + * @return The latest `Finished` message that is expected or has actually been received from the socket as part of a SSL/TLS handshake, or `undefined` if there is no `Finished` message so + * far. + */ + getPeerFinished(): NonSharedBuffer | undefined; + /** + * Returns a string containing the negotiated SSL/TLS protocol version of the + * current connection. The value `'unknown'` will be returned for connected + * sockets that have not completed the handshaking process. The value `null` will + * be returned for server sockets or disconnected client sockets. + * + * Protocol versions are: + * + * * `'SSLv3'` + * * `'TLSv1'` + * * `'TLSv1.1'` + * * `'TLSv1.2'` + * * `'TLSv1.3'` + * + * See the OpenSSL [`SSL_get_version`](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_version.html) documentation for more information. + * @since v5.7.0 + */ + getProtocol(): string | null; + /** + * Returns the TLS session data or `undefined` if no session was + * negotiated. On the client, the data can be provided to the `session` option of {@link connect} to resume the connection. On the server, it may be useful + * for debugging. + * + * See `Session Resumption` for more information. + * + * Note: `getSession()` works only for TLSv1.2 and below. For TLSv1.3, applications + * must use the `'session'` event (it also works for TLSv1.2 and below). + * @since v0.11.4 + */ + getSession(): NonSharedBuffer | undefined; + /** + * See [SSL\_get\_shared\_sigalgs](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_shared_sigalgs.html) for more information. + * @since v12.11.0 + * @return List of signature algorithms shared between the server and the client in the order of decreasing preference. + */ + getSharedSigalgs(): string[]; + /** + * For a client, returns the TLS session ticket if one is available, or`undefined`. For a server, always returns `undefined`. + * + * It may be useful for debugging. + * + * See `Session Resumption` for more information. + * @since v0.11.4 + */ + getTLSTicket(): NonSharedBuffer | undefined; + /** + * See `Session Resumption` for more information. + * @since v0.5.6 + * @return `true` if the session was reused, `false` otherwise. + */ + isSessionReused(): boolean; + /** + * The `tlsSocket.renegotiate()` method initiates a TLS renegotiation process. + * Upon completion, the `callback` function will be passed a single argument + * that is either an `Error` (if the request failed) or `null`. + * + * This method can be used to request a peer's certificate after the secure + * connection has been established. + * + * When running as the server, the socket will be destroyed with an error after `handshakeTimeout` timeout. + * + * For TLSv1.3, renegotiation cannot be initiated, it is not supported by the + * protocol. + * @since v0.11.8 + * @param callback If `renegotiate()` returned `true`, callback is attached once to the `'secure'` event. If `renegotiate()` returned `false`, `callback` will be called in the next tick with + * an error, unless the `tlsSocket` has been destroyed, in which case `callback` will not be called at all. + * @return `true` if renegotiation was initiated, `false` otherwise. + */ + renegotiate( + options: { + rejectUnauthorized?: boolean | undefined; + requestCert?: boolean | undefined; + }, + callback: (err: Error | null) => void, + ): undefined | boolean; + /** + * The `tlsSocket.setKeyCert()` method sets the private key and certificate to use for the socket. + * This is mainly useful if you wish to select a server certificate from a TLS server's `ALPNCallback`. + * @since v22.5.0, v20.17.0 + * @param context An object containing at least `key` and `cert` properties from the {@link createSecureContext()} `options`, + * or a TLS context object created with {@link createSecureContext()} itself. + */ + setKeyCert(context: SecureContextOptions | SecureContext): void; + /** + * The `tlsSocket.setMaxSendFragment()` method sets the maximum TLS fragment size. + * Returns `true` if setting the limit succeeded; `false` otherwise. + * + * Smaller fragment sizes decrease the buffering latency on the client: larger + * fragments are buffered by the TLS layer until the entire fragment is received + * and its integrity is verified; large fragments can span multiple roundtrips + * and their processing can be delayed due to packet loss or reordering. However, + * smaller fragments add extra TLS framing bytes and CPU overhead, which may + * decrease overall server throughput. + * @since v0.11.11 + * @param [size=16384] The maximum TLS fragment size. The maximum value is `16384`. + */ + setMaxSendFragment(size: number): boolean; + /** + * Disables TLS renegotiation for this `TLSSocket` instance. Once called, attempts + * to renegotiate will trigger an `'error'` event on the `TLSSocket`. + * @since v8.4.0 + */ + disableRenegotiation(): void; + /** + * When enabled, TLS packet trace information is written to `stderr`. This can be + * used to debug TLS connection problems. + * + * The format of the output is identical to the output of`openssl s_client -trace` or `openssl s_server -trace`. While it is produced by + * OpenSSL's `SSL_trace()` function, the format is undocumented, can change + * without notice, and should not be relied on. + * @since v12.2.0 + */ + enableTrace(): void; + /** + * Returns the peer certificate as an `X509Certificate` object. + * + * If there is no peer certificate, or the socket has been destroyed,`undefined` will be returned. + * @since v15.9.0 + */ + getPeerX509Certificate(): X509Certificate | undefined; + /** + * Returns the local certificate as an `X509Certificate` object. + * + * If there is no local certificate, or the socket has been destroyed,`undefined` will be returned. + * @since v15.9.0 + */ + getX509Certificate(): X509Certificate | undefined; + /** + * Keying material is used for validations to prevent different kind of attacks in + * network protocols, for example in the specifications of IEEE 802.1X. + * + * Example + * + * ```js + * const keyingMaterial = tlsSocket.exportKeyingMaterial( + * 128, + * 'client finished'); + * + * /* + * Example return value of keyingMaterial: + * <Buffer 76 26 af 99 c5 56 8e 42 09 91 ef 9f 93 cb ad 6c 7b 65 f8 53 f1 d8 d9 + * 12 5a 33 b8 b5 25 df 7b 37 9f e0 e2 4f b8 67 83 a3 2f cd 5d 41 42 4c 91 + * 74 ef 2c ... 78 more bytes> + * + * ``` + * + * See the OpenSSL [`SSL_export_keying_material`](https://www.openssl.org/docs/man1.1.1/man3/SSL_export_keying_material.html) documentation for more + * information. + * @since v13.10.0, v12.17.0 + * @param length number of bytes to retrieve from keying material + * @param label an application specific label, typically this will be a value from the [IANA Exporter Label + * Registry](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#exporter-labels). + * @param context Optionally provide a context. + * @return requested bytes of the keying material + */ + exportKeyingMaterial(length: number, label: string, context: Buffer): NonSharedBuffer; + // #region InternalEventEmitter + addListener<E extends keyof TLSSocketEventMap>( + eventName: E, + listener: (...args: TLSSocketEventMap[E]) => void, + ): this; + addListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + emit<E extends keyof TLSSocketEventMap>(eventName: E, ...args: TLSSocketEventMap[E]): boolean; + emit(eventName: string | symbol, ...args: any[]): boolean; + listenerCount<E extends keyof TLSSocketEventMap>( + eventName: E, + listener?: (...args: TLSSocketEventMap[E]) => void, + ): number; + listenerCount(eventName: string | symbol, listener?: (...args: any[]) => void): number; + listeners<E extends keyof TLSSocketEventMap>(eventName: E): ((...args: TLSSocketEventMap[E]) => void)[]; + listeners(eventName: string | symbol): ((...args: any[]) => void)[]; + off<E extends keyof TLSSocketEventMap>(eventName: E, listener: (...args: TLSSocketEventMap[E]) => void): this; + off(eventName: string | symbol, listener: (...args: any[]) => void): this; + on<E extends keyof TLSSocketEventMap>(eventName: E, listener: (...args: TLSSocketEventMap[E]) => void): this; + on(eventName: string | symbol, listener: (...args: any[]) => void): this; + once<E extends keyof TLSSocketEventMap>(eventName: E, listener: (...args: TLSSocketEventMap[E]) => void): this; + once(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependListener<E extends keyof TLSSocketEventMap>( + eventName: E, + listener: (...args: TLSSocketEventMap[E]) => void, + ): this; + prependListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependOnceListener<E extends keyof TLSSocketEventMap>( + eventName: E, + listener: (...args: TLSSocketEventMap[E]) => void, + ): this; + prependOnceListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + rawListeners<E extends keyof TLSSocketEventMap>(eventName: E): ((...args: TLSSocketEventMap[E]) => void)[]; + rawListeners(eventName: string | symbol): ((...args: any[]) => void)[]; + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + removeAllListeners<E extends keyof TLSSocketEventMap>(eventName?: E): this; + removeAllListeners(eventName?: string | symbol): this; + removeListener<E extends keyof TLSSocketEventMap>( + eventName: E, + listener: (...args: TLSSocketEventMap[E]) => void, + ): this; + removeListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + // #endregion + } + interface CommonConnectionOptions { + /** + * An optional TLS context object from tls.createSecureContext() + */ + secureContext?: SecureContext | undefined; + /** + * When enabled, TLS packet trace information is written to `stderr`. This can be + * used to debug TLS connection problems. + * @default false + */ + enableTrace?: boolean | undefined; + /** + * If true the server will request a certificate from clients that + * connect and attempt to verify that certificate. Defaults to + * false. + */ + requestCert?: boolean | undefined; + /** + * An array of strings or a Buffer naming possible ALPN protocols. + * (Protocols should be ordered by their priority.) + */ + ALPNProtocols?: readonly string[] | NodeJS.ArrayBufferView | undefined; + /** + * SNICallback(servername, cb) <Function> A function that will be + * called if the client supports SNI TLS extension. Two arguments + * will be passed when called: servername and cb. SNICallback should + * invoke cb(null, ctx), where ctx is a SecureContext instance. + * (tls.createSecureContext(...) can be used to get a proper + * SecureContext.) If SNICallback wasn't provided the default callback + * with high-level API will be used (see below). + */ + SNICallback?: ((servername: string, cb: (err: Error | null, ctx?: SecureContext) => void) => void) | undefined; + /** + * If true the server will reject any connection which is not + * authorized with the list of supplied CAs. This option only has an + * effect if requestCert is true. + * @default true + */ + rejectUnauthorized?: boolean | undefined; + } + interface TlsOptions extends SecureContextOptions, CommonConnectionOptions, net.ServerOpts { + /** + * Abort the connection if the SSL/TLS handshake does not finish in the + * specified number of milliseconds. A 'tlsClientError' is emitted on + * the tls.Server object whenever a handshake times out. Default: + * 120000 (120 seconds). + */ + handshakeTimeout?: number | undefined; + /** + * The number of seconds after which a TLS session created by the + * server will no longer be resumable. See Session Resumption for more + * information. Default: 300. + */ + sessionTimeout?: number | undefined; + /** + * 48-bytes of cryptographically strong pseudo-random data. + */ + ticketKeys?: Buffer | undefined; + /** + * @param socket + * @param identity identity parameter sent from the client. + * @return pre-shared key that must either be + * a buffer or `null` to stop the negotiation process. Returned PSK must be + * compatible with the selected cipher's digest. + * + * When negotiating TLS-PSK (pre-shared keys), this function is called + * with the identity provided by the client. + * If the return value is `null` the negotiation process will stop and an + * "unknown_psk_identity" alert message will be sent to the other party. + * If the server wishes to hide the fact that the PSK identity was not known, + * the callback must provide some random data as `psk` to make the connection + * fail with "decrypt_error" before negotiation is finished. + * PSK ciphers are disabled by default, and using TLS-PSK thus + * requires explicitly specifying a cipher suite with the `ciphers` option. + * More information can be found in the RFC 4279. + */ + pskCallback?: ((socket: TLSSocket, identity: string) => NodeJS.ArrayBufferView | null) | undefined; + /** + * hint to send to a client to help + * with selecting the identity during TLS-PSK negotiation. Will be ignored + * in TLS 1.3. Upon failing to set pskIdentityHint `tlsClientError` will be + * emitted with `ERR_TLS_PSK_SET_IDENTIY_HINT_FAILED` code. + */ + pskIdentityHint?: string | undefined; + } + interface PSKCallbackNegotation { + psk: NodeJS.ArrayBufferView; + identity: string; + } + interface ConnectionOptions extends SecureContextOptions, CommonConnectionOptions { + host?: string | undefined; + port?: number | undefined; + path?: string | undefined; // Creates unix socket connection to path. If this option is specified, `host` and `port` are ignored. + socket?: stream.Duplex | undefined; // Establish secure connection on a given socket rather than creating a new socket + checkServerIdentity?: typeof checkServerIdentity | undefined; + servername?: string | undefined; // SNI TLS Extension + session?: Buffer | undefined; + minDHSize?: number | undefined; + lookup?: net.LookupFunction | undefined; + timeout?: number | undefined; + /** + * When negotiating TLS-PSK (pre-shared keys), this function is called + * with optional identity `hint` provided by the server or `null` + * in case of TLS 1.3 where `hint` was removed. + * It will be necessary to provide a custom `tls.checkServerIdentity()` + * for the connection as the default one will try to check hostname/IP + * of the server against the certificate but that's not applicable for PSK + * because there won't be a certificate present. + * More information can be found in the RFC 4279. + * + * @param hint message sent from the server to help client + * decide which identity to use during negotiation. + * Always `null` if TLS 1.3 is used. + * @returns Return `null` to stop the negotiation process. `psk` must be + * compatible with the selected cipher's digest. + * `identity` must use UTF-8 encoding. + */ + pskCallback?: ((hint: string | null) => PSKCallbackNegotation | null) | undefined; + } + interface ServerEventMap extends net.ServerEventMap { + "connection": [socket: net.Socket]; + "keylog": [line: NonSharedBuffer, tlsSocket: TLSSocket]; + "newSession": [sessionId: NonSharedBuffer, sessionData: NonSharedBuffer, callback: () => void]; + "OCSPRequest": [ + certificate: NonSharedBuffer, + issuer: NonSharedBuffer, + callback: (err: Error | null, resp: Buffer | null) => void, + ]; + "resumeSession": [sessionId: Buffer, callback: (err: Error | null, sessionData?: Buffer) => void]; + "secureConnection": [tlsSocket: TLSSocket]; + "tlsClientError": [exception: Error, tlsSocket: TLSSocket]; + } + /** + * Accepts encrypted connections using TLS or SSL. + * @since v0.3.2 + */ + class Server extends net.Server { + constructor(secureConnectionListener?: (socket: TLSSocket) => void); + constructor(options: TlsOptions, secureConnectionListener?: (socket: TLSSocket) => void); + /** + * The `server.addContext()` method adds a secure context that will be used if + * the client request's SNI name matches the supplied `hostname` (or wildcard). + * + * When there are multiple matching contexts, the most recently added one is + * used. + * @since v0.5.3 + * @param hostname A SNI host name or wildcard (e.g. `'*'`) + * @param context An object containing any of the possible properties from the {@link createSecureContext} `options` arguments (e.g. `key`, `cert`, `ca`, etc), or a TLS context object created + * with {@link createSecureContext} itself. + */ + addContext(hostname: string, context: SecureContextOptions | SecureContext): void; + /** + * Returns the session ticket keys. + * + * See `Session Resumption` for more information. + * @since v3.0.0 + * @return A 48-byte buffer containing the session ticket keys. + */ + getTicketKeys(): NonSharedBuffer; + /** + * The `server.setSecureContext()` method replaces the secure context of an + * existing server. Existing connections to the server are not interrupted. + * @since v11.0.0 + * @param options An object containing any of the possible properties from the {@link createSecureContext} `options` arguments (e.g. `key`, `cert`, `ca`, etc). + */ + setSecureContext(options: SecureContextOptions): void; + /** + * Sets the session ticket keys. + * + * Changes to the ticket keys are effective only for future server connections. + * Existing or currently pending server connections will use the previous keys. + * + * See `Session Resumption` for more information. + * @since v3.0.0 + * @param keys A 48-byte buffer containing the session ticket keys. + */ + setTicketKeys(keys: Buffer): void; + // #region InternalEventEmitter + addListener<E extends keyof ServerEventMap>(eventName: E, listener: (...args: ServerEventMap[E]) => void): this; + addListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + emit<E extends keyof ServerEventMap>(eventName: E, ...args: ServerEventMap[E]): boolean; + emit(eventName: string | symbol, ...args: any[]): boolean; + listenerCount<E extends keyof ServerEventMap>( + eventName: E, + listener?: (...args: ServerEventMap[E]) => void, + ): number; + listenerCount(eventName: string | symbol, listener?: (...args: any[]) => void): number; + listeners<E extends keyof ServerEventMap>(eventName: E): ((...args: ServerEventMap[E]) => void)[]; + listeners(eventName: string | symbol): ((...args: any[]) => void)[]; + off<E extends keyof ServerEventMap>(eventName: E, listener: (...args: ServerEventMap[E]) => void): this; + off(eventName: string | symbol, listener: (...args: any[]) => void): this; + on<E extends keyof ServerEventMap>(eventName: E, listener: (...args: ServerEventMap[E]) => void): this; + on(eventName: string | symbol, listener: (...args: any[]) => void): this; + once<E extends keyof ServerEventMap>(eventName: E, listener: (...args: ServerEventMap[E]) => void): this; + once(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependListener<E extends keyof ServerEventMap>( + eventName: E, + listener: (...args: ServerEventMap[E]) => void, + ): this; + prependListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependOnceListener<E extends keyof ServerEventMap>( + eventName: E, + listener: (...args: ServerEventMap[E]) => void, + ): this; + prependOnceListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + rawListeners<E extends keyof ServerEventMap>(eventName: E): ((...args: ServerEventMap[E]) => void)[]; + rawListeners(eventName: string | symbol): ((...args: any[]) => void)[]; + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + removeAllListeners<E extends keyof ServerEventMap>(eventName?: E): this; + removeAllListeners(eventName?: string | symbol): this; + removeListener<E extends keyof ServerEventMap>( + eventName: E, + listener: (...args: ServerEventMap[E]) => void, + ): this; + removeListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + // #endregion + } + type SecureVersion = "TLSv1.3" | "TLSv1.2" | "TLSv1.1" | "TLSv1"; + interface SecureContextOptions { + /** + * If set, this will be called when a client opens a connection using the ALPN extension. + * One argument will be passed to the callback: an object containing `servername` and `protocols` fields, + * respectively containing the server name from the SNI extension (if any) and an array of + * ALPN protocol name strings. The callback must return either one of the strings listed in `protocols`, + * which will be returned to the client as the selected ALPN protocol, or `undefined`, + * to reject the connection with a fatal alert. If a string is returned that does not match one of + * the client's ALPN protocols, an error will be thrown. + * This option cannot be used with the `ALPNProtocols` option, and setting both options will throw an error. + */ + ALPNCallback?: ((arg: { servername: string; protocols: string[] }) => string | undefined) | undefined; + /** + * Treat intermediate (non-self-signed) + * certificates in the trust CA certificate list as trusted. + * @since v22.9.0, v20.18.0 + */ + allowPartialTrustChain?: boolean | undefined; + /** + * Optionally override the trusted CA certificates. Default is to trust + * the well-known CAs curated by Mozilla. Mozilla's CAs are completely + * replaced when CAs are explicitly specified using this option. + */ + ca?: string | Buffer | Array<string | Buffer> | undefined; + /** + * Cert chains in PEM format. One cert chain should be provided per + * private key. Each cert chain should consist of the PEM formatted + * certificate for a provided private key, followed by the PEM + * formatted intermediate certificates (if any), in order, and not + * including the root CA (the root CA must be pre-known to the peer, + * see ca). When providing multiple cert chains, they do not have to + * be in the same order as their private keys in key. If the + * intermediate certificates are not provided, the peer will not be + * able to validate the certificate, and the handshake will fail. + */ + cert?: string | Buffer | Array<string | Buffer> | undefined; + /** + * Colon-separated list of supported signature algorithms. The list + * can contain digest algorithms (SHA256, MD5 etc.), public key + * algorithms (RSA-PSS, ECDSA etc.), combination of both (e.g + * 'RSA+SHA384') or TLS v1.3 scheme names (e.g. rsa_pss_pss_sha512). + */ + sigalgs?: string | undefined; + /** + * Cipher suite specification, replacing the default. For more + * information, see modifying the default cipher suite. Permitted + * ciphers can be obtained via tls.getCiphers(). Cipher names must be + * uppercased in order for OpenSSL to accept them. + */ + ciphers?: string | undefined; + /** + * Name of an OpenSSL engine which can provide the client certificate. + * @deprecated + */ + clientCertEngine?: string | undefined; + /** + * PEM formatted CRLs (Certificate Revocation Lists). + */ + crl?: string | Buffer | Array<string | Buffer> | undefined; + /** + * `'auto'` or custom Diffie-Hellman parameters, required for non-ECDHE perfect forward secrecy. + * If omitted or invalid, the parameters are silently discarded and DHE ciphers will not be available. + * ECDHE-based perfect forward secrecy will still be available. + */ + dhparam?: string | Buffer | undefined; + /** + * A string describing a named curve or a colon separated list of curve + * NIDs or names, for example P-521:P-384:P-256, to use for ECDH key + * agreement. Set to auto to select the curve automatically. Use + * crypto.getCurves() to obtain a list of available curve names. On + * recent releases, openssl ecparam -list_curves will also display the + * name and description of each available elliptic curve. Default: + * tls.DEFAULT_ECDH_CURVE. + */ + ecdhCurve?: string | undefined; + /** + * Attempt to use the server's cipher suite preferences instead of the + * client's. When true, causes SSL_OP_CIPHER_SERVER_PREFERENCE to be + * set in secureOptions + */ + honorCipherOrder?: boolean | undefined; + /** + * Private keys in PEM format. PEM allows the option of private keys + * being encrypted. Encrypted keys will be decrypted with + * options.passphrase. Multiple keys using different algorithms can be + * provided either as an array of unencrypted key strings or buffers, + * or an array of objects in the form {pem: <string|buffer>[, + * passphrase: <string>]}. The object form can only occur in an array. + * object.passphrase is optional. Encrypted keys will be decrypted with + * object.passphrase if provided, or options.passphrase if it is not. + */ + key?: string | Buffer | Array<string | Buffer | KeyObject> | undefined; + /** + * Name of an OpenSSL engine to get private key from. Should be used + * together with privateKeyIdentifier. + * @deprecated + */ + privateKeyEngine?: string | undefined; + /** + * Identifier of a private key managed by an OpenSSL engine. Should be + * used together with privateKeyEngine. Should not be set together with + * key, because both options define a private key in different ways. + * @deprecated + */ + privateKeyIdentifier?: string | undefined; + /** + * Optionally set the maximum TLS version to allow. One + * of `'TLSv1.3'`, `'TLSv1.2'`, `'TLSv1.1'`, or `'TLSv1'`. Cannot be specified along with the + * `secureProtocol` option, use one or the other. + * **Default:** `'TLSv1.3'`, unless changed using CLI options. Using + * `--tls-max-v1.2` sets the default to `'TLSv1.2'`. Using `--tls-max-v1.3` sets the default to + * `'TLSv1.3'`. If multiple of the options are provided, the highest maximum is used. + */ + maxVersion?: SecureVersion | undefined; + /** + * Optionally set the minimum TLS version to allow. One + * of `'TLSv1.3'`, `'TLSv1.2'`, `'TLSv1.1'`, or `'TLSv1'`. Cannot be specified along with the + * `secureProtocol` option, use one or the other. It is not recommended to use + * less than TLSv1.2, but it may be required for interoperability. + * **Default:** `'TLSv1.2'`, unless changed using CLI options. Using + * `--tls-v1.0` sets the default to `'TLSv1'`. Using `--tls-v1.1` sets the default to + * `'TLSv1.1'`. Using `--tls-min-v1.3` sets the default to + * 'TLSv1.3'. If multiple of the options are provided, the lowest minimum is used. + */ + minVersion?: SecureVersion | undefined; + /** + * Shared passphrase used for a single private key and/or a PFX. + */ + passphrase?: string | undefined; + /** + * PFX or PKCS12 encoded private key and certificate chain. pfx is an + * alternative to providing key and cert individually. PFX is usually + * encrypted, if it is, passphrase will be used to decrypt it. Multiple + * PFX can be provided either as an array of unencrypted PFX buffers, + * or an array of objects in the form {buf: <string|buffer>[, + * passphrase: <string>]}. The object form can only occur in an array. + * object.passphrase is optional. Encrypted PFX will be decrypted with + * object.passphrase if provided, or options.passphrase if it is not. + */ + pfx?: string | Buffer | Array<string | Buffer | PxfObject> | undefined; + /** + * Optionally affect the OpenSSL protocol behavior, which is not + * usually necessary. This should be used carefully if at all! Value is + * a numeric bitmask of the SSL_OP_* options from OpenSSL Options + */ + secureOptions?: number | undefined; // Value is a numeric bitmask of the `SSL_OP_*` options + /** + * Legacy mechanism to select the TLS protocol version to use, it does + * not support independent control of the minimum and maximum version, + * and does not support limiting the protocol to TLSv1.3. Use + * minVersion and maxVersion instead. The possible values are listed as + * SSL_METHODS, use the function names as strings. For example, use + * 'TLSv1_1_method' to force TLS version 1.1, or 'TLS_method' to allow + * any TLS protocol version up to TLSv1.3. It is not recommended to use + * TLS versions less than 1.2, but it may be required for + * interoperability. Default: none, see minVersion. + */ + secureProtocol?: string | undefined; + /** + * Opaque identifier used by servers to ensure session state is not + * shared between applications. Unused by clients. + */ + sessionIdContext?: string | undefined; + /** + * 48-bytes of cryptographically strong pseudo-random data. + * See Session Resumption for more information. + */ + ticketKeys?: Buffer | undefined; + /** + * The number of seconds after which a TLS session created by the + * server will no longer be resumable. See Session Resumption for more + * information. Default: 300. + */ + sessionTimeout?: number | undefined; + } + interface SecureContext { + context: any; + } + /** + * Verifies the certificate `cert` is issued to `hostname`. + * + * Returns [Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) object, populating it with `reason`, `host`, and `cert` on + * failure. On success, returns [undefined](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Undefined_type). + * + * This function is intended to be used in combination with the`checkServerIdentity` option that can be passed to {@link connect} and as + * such operates on a `certificate object`. For other purposes, consider using `x509.checkHost()` instead. + * + * This function can be overwritten by providing an alternative function as the `options.checkServerIdentity` option that is passed to `tls.connect()`. The + * overwriting function can call `tls.checkServerIdentity()` of course, to augment + * the checks done with additional verification. + * + * This function is only called if the certificate passed all other checks, such as + * being issued by trusted CA (`options.ca`). + * + * Earlier versions of Node.js incorrectly accepted certificates for a given`hostname` if a matching `uniformResourceIdentifier` subject alternative name + * was present (see [CVE-2021-44531](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-44531)). Applications that wish to accept`uniformResourceIdentifier` subject alternative names can use + * a custom `options.checkServerIdentity` function that implements the desired behavior. + * @since v0.8.4 + * @param hostname The host name or IP address to verify the certificate against. + * @param cert A `certificate object` representing the peer's certificate. + */ + function checkServerIdentity(hostname: string, cert: PeerCertificate): Error | undefined; + /** + * Creates a new {@link Server}. The `secureConnectionListener`, if provided, is + * automatically set as a listener for the `'secureConnection'` event. + * + * The `ticketKeys` options is automatically shared between `node:cluster` module + * workers. + * + * The following illustrates a simple echo server: + * + * ```js + * import tls from 'node:tls'; + * import fs from 'node:fs'; + * + * const options = { + * key: fs.readFileSync('server-key.pem'), + * cert: fs.readFileSync('server-cert.pem'), + * + * // This is necessary only if using client certificate authentication. + * requestCert: true, + * + * // This is necessary only if the client uses a self-signed certificate. + * ca: [ fs.readFileSync('client-cert.pem') ], + * }; + * + * const server = tls.createServer(options, (socket) => { + * console.log('server connected', + * socket.authorized ? 'authorized' : 'unauthorized'); + * socket.write('welcome!\n'); + * socket.setEncoding('utf8'); + * socket.pipe(socket); + * }); + * server.listen(8000, () => { + * console.log('server bound'); + * }); + * ``` + * + * The server can be tested by connecting to it using the example client from {@link connect}. + * @since v0.3.2 + */ + function createServer(secureConnectionListener?: (socket: TLSSocket) => void): Server; + function createServer(options: TlsOptions, secureConnectionListener?: (socket: TLSSocket) => void): Server; + /** + * The `callback` function, if specified, will be added as a listener for the `'secureConnect'` event. + * + * `tls.connect()` returns a {@link TLSSocket} object. + * + * Unlike the `https` API, `tls.connect()` does not enable the + * SNI (Server Name Indication) extension by default, which may cause some + * servers to return an incorrect certificate or reject the connection + * altogether. To enable SNI, set the `servername` option in addition + * to `host`. + * + * The following illustrates a client for the echo server example from {@link createServer}: + * + * ```js + * // Assumes an echo server that is listening on port 8000. + * import tls from 'node:tls'; + * import fs from 'node:fs'; + * + * const options = { + * // Necessary only if the server requires client certificate authentication. + * key: fs.readFileSync('client-key.pem'), + * cert: fs.readFileSync('client-cert.pem'), + * + * // Necessary only if the server uses a self-signed certificate. + * ca: [ fs.readFileSync('server-cert.pem') ], + * + * // Necessary only if the server's cert isn't for "localhost". + * checkServerIdentity: () => { return null; }, + * }; + * + * const socket = tls.connect(8000, options, () => { + * console.log('client connected', + * socket.authorized ? 'authorized' : 'unauthorized'); + * process.stdin.pipe(socket); + * process.stdin.resume(); + * }); + * socket.setEncoding('utf8'); + * socket.on('data', (data) => { + * console.log(data); + * }); + * socket.on('end', () => { + * console.log('server ends connection'); + * }); + * ``` + * @since v0.11.3 + */ + function connect(options: ConnectionOptions, secureConnectListener?: () => void): TLSSocket; + function connect( + port: number, + host?: string, + options?: ConnectionOptions, + secureConnectListener?: () => void, + ): TLSSocket; + function connect(port: number, options?: ConnectionOptions, secureConnectListener?: () => void): TLSSocket; + /** + * `{@link createServer}` sets the default value of the `honorCipherOrder` option + * to `true`, other APIs that create secure contexts leave it unset. + * + * `{@link createServer}` uses a 128 bit truncated SHA1 hash value generated + * from `process.argv` as the default value of the `sessionIdContext` option, other + * APIs that create secure contexts have no default value. + * + * The `tls.createSecureContext()` method creates a `SecureContext` object. It is + * usable as an argument to several `tls` APIs, such as `server.addContext()`, + * but has no public methods. The {@link Server} constructor and the {@link createServer} method do not support the `secureContext` option. + * + * A key is _required_ for ciphers that use certificates. Either `key` or `pfx` can be used to provide it. + * + * If the `ca` option is not given, then Node.js will default to using [Mozilla's publicly trusted list of + * CAs](https://hg.mozilla.org/mozilla-central/raw-file/tip/security/nss/lib/ckfw/builtins/certdata.txt). + * + * Custom DHE parameters are discouraged in favor of the new `dhparam: 'auto' `option. When set to `'auto'`, well-known DHE parameters of sufficient strength + * will be selected automatically. Otherwise, if necessary, `openssl dhparam` can + * be used to create custom parameters. The key length must be greater than or + * equal to 1024 bits or else an error will be thrown. Although 1024 bits is + * permissible, use 2048 bits or larger for stronger security. + * @since v0.11.13 + */ + function createSecureContext(options?: SecureContextOptions): SecureContext; + /** + * Returns an array containing the CA certificates from various sources, depending on `type`: + * + * * `"default"`: return the CA certificates that will be used by the Node.js TLS clients by default. + * * When `--use-bundled-ca` is enabled (default), or `--use-openssl-ca` is not enabled, + * this would include CA certificates from the bundled Mozilla CA store. + * * When `--use-system-ca` is enabled, this would also include certificates from the system's + * trusted store. + * * When `NODE_EXTRA_CA_CERTS` is used, this would also include certificates loaded from the specified + * file. + * * `"system"`: return the CA certificates that are loaded from the system's trusted store, according + * to rules set by `--use-system-ca`. This can be used to get the certificates from the system + * when `--use-system-ca` is not enabled. + * * `"bundled"`: return the CA certificates from the bundled Mozilla CA store. This would be the same + * as `tls.rootCertificates`. + * * `"extra"`: return the CA certificates loaded from `NODE_EXTRA_CA_CERTS`. It's an empty array if + * `NODE_EXTRA_CA_CERTS` is not set. + * @since v22.15.0 + * @param type The type of CA certificates that will be returned. Valid values + * are `"default"`, `"system"`, `"bundled"` and `"extra"`. + * **Default:** `"default"`. + * @returns An array of PEM-encoded certificates. The array may contain duplicates + * if the same certificate is repeatedly stored in multiple sources. + */ + function getCACertificates(type?: "default" | "system" | "bundled" | "extra"): string[]; + /** + * Returns an array with the names of the supported TLS ciphers. The names are + * lower-case for historical reasons, but must be uppercased to be used in + * the `ciphers` option of `{@link createSecureContext}`. + * + * Not all supported ciphers are enabled by default. See + * [Modifying the default TLS cipher suite](https://nodejs.org/docs/latest-v25.x/api/tls.html#modifying-the-default-tls-cipher-suite). + * + * Cipher names that start with `'tls_'` are for TLSv1.3, all the others are for + * TLSv1.2 and below. + * + * ```js + * console.log(tls.getCiphers()); // ['aes128-gcm-sha256', 'aes128-sha', ...] + * ``` + * @since v0.10.2 + */ + function getCiphers(): string[]; + /** + * Sets the default CA certificates used by Node.js TLS clients. If the provided + * certificates are parsed successfully, they will become the default CA + * certificate list returned by {@link getCACertificates} and used + * by subsequent TLS connections that don't specify their own CA certificates. + * The certificates will be deduplicated before being set as the default. + * + * This function only affects the current Node.js thread. Previous + * sessions cached by the HTTPS agent won't be affected by this change, so + * this method should be called before any unwanted cachable TLS connections are + * made. + * + * To use system CA certificates as the default: + * + * ```js + * import tls from 'node:tls'; + * tls.setDefaultCACertificates(tls.getCACertificates('system')); + * ``` + * + * This function completely replaces the default CA certificate list. To add additional + * certificates to the existing defaults, get the current certificates and append to them: + * + * ```js + * import tls from 'node:tls'; + * const currentCerts = tls.getCACertificates('default'); + * const additionalCerts = ['-----BEGIN CERTIFICATE-----\n...']; + * tls.setDefaultCACertificates([...currentCerts, ...additionalCerts]); + * ``` + * @since v24.5.0 + * @param certs An array of CA certificates in PEM format. + */ + function setDefaultCACertificates(certs: ReadonlyArray<string | NodeJS.ArrayBufferView>): void; + /** + * The default curve name to use for ECDH key agreement in a tls server. + * The default value is `'auto'`. See `{@link createSecureContext()}` for further + * information. + * @since v0.11.13 + */ + let DEFAULT_ECDH_CURVE: string; + /** + * The default value of the `maxVersion` option of `{@link createSecureContext()}`. + * It can be assigned any of the supported TLS protocol versions, + * `'TLSv1.3'`, `'TLSv1.2'`, `'TLSv1.1'`, or `'TLSv1'`. **Default:** `'TLSv1.3'`, unless + * changed using CLI options. Using `--tls-max-v1.2` sets the default to `'TLSv1.2'`. Using + * `--tls-max-v1.3` sets the default to `'TLSv1.3'`. If multiple of the options + * are provided, the highest maximum is used. + * @since v11.4.0 + */ + let DEFAULT_MAX_VERSION: SecureVersion; + /** + * The default value of the `minVersion` option of `{@link createSecureContext()}`. + * It can be assigned any of the supported TLS protocol versions, + * `'TLSv1.3'`, `'TLSv1.2'`, `'TLSv1.1'`, or `'TLSv1'`. **Default:** `'TLSv1.2'`, unless + * changed using CLI options. Using `--tls-min-v1.0` sets the default to + * `'TLSv1'`. Using `--tls-min-v1.1` sets the default to `'TLSv1.1'`. Using + * `--tls-min-v1.3` sets the default to `'TLSv1.3'`. If multiple of the options + * are provided, the lowest minimum is used. + * @since v11.4.0 + */ + let DEFAULT_MIN_VERSION: SecureVersion; + /** + * The default value of the `ciphers` option of `{@link createSecureContext()}`. + * It can be assigned any of the supported OpenSSL ciphers. + * Defaults to the content of `crypto.constants.defaultCoreCipherList`, unless + * changed using CLI options using `--tls-default-ciphers`. + * @since v19.8.0 + */ + let DEFAULT_CIPHERS: string; + /** + * An immutable array of strings representing the root certificates (in PEM format) + * from the bundled Mozilla CA store as supplied by the current Node.js version. + * + * The bundled CA store, as supplied by Node.js, is a snapshot of Mozilla CA store + * that is fixed at release time. It is identical on all supported platforms. + * @since v12.3.0 + */ + const rootCertificates: readonly string[]; +} +declare module "tls" { + export * from "node:tls"; +} diff --git a/server/node_modules/@types/node/trace_events.d.ts b/server/node_modules/@types/node/trace_events.d.ts new file mode 100644 index 0000000..b2c6b32 --- /dev/null +++ b/server/node_modules/@types/node/trace_events.d.ts @@ -0,0 +1,197 @@ +/** + * The `node:trace_events` module provides a mechanism to centralize tracing information + * generated by V8, Node.js core, and userspace code. + * + * Tracing can be enabled with the `--trace-event-categories` command-line flag + * or by using the `trace_events` module. The `--trace-event-categories` flag + * accepts a list of comma-separated category names. + * + * The available categories are: + * + * * `node`: An empty placeholder. + * * `node.async_hooks`: Enables capture of detailed [`async_hooks`](https://nodejs.org/docs/latest-v25.x/api/async_hooks.html) trace data. + * The [`async_hooks`](https://nodejs.org/docs/latest-v25.x/api/async_hooks.html) events have a unique `asyncId` and a special `triggerId` `triggerAsyncId` property. + * * `node.bootstrap`: Enables capture of Node.js bootstrap milestones. + * * `node.console`: Enables capture of `console.time()` and `console.count()` output. + * * `node.threadpoolwork.sync`: Enables capture of trace data for threadpool synchronous operations, such as `blob`, `zlib`, `crypto` and `node_api`. + * * `node.threadpoolwork.async`: Enables capture of trace data for threadpool asynchronous operations, such as `blob`, `zlib`, `crypto` and `node_api`. + * * `node.dns.native`: Enables capture of trace data for DNS queries. + * * `node.net.native`: Enables capture of trace data for network. + * * `node.environment`: Enables capture of Node.js Environment milestones. + * * `node.fs.sync`: Enables capture of trace data for file system sync methods. + * * `node.fs_dir.sync`: Enables capture of trace data for file system sync directory methods. + * * `node.fs.async`: Enables capture of trace data for file system async methods. + * * `node.fs_dir.async`: Enables capture of trace data for file system async directory methods. + * * `node.perf`: Enables capture of [Performance API](https://nodejs.org/docs/latest-v25.x/api/perf_hooks.html) measurements. + * * `node.perf.usertiming`: Enables capture of only Performance API User Timing + * measures and marks. + * * `node.perf.timerify`: Enables capture of only Performance API timerify + * measurements. + * * `node.promises.rejections`: Enables capture of trace data tracking the number + * of unhandled Promise rejections and handled-after-rejections. + * * `node.vm.script`: Enables capture of trace data for the `node:vm` module's `runInNewContext()`, `runInContext()`, and `runInThisContext()` methods. + * * `v8`: The [V8](https://nodejs.org/docs/latest-v25.x/api/v8.html) events are GC, compiling, and execution related. + * * `node.http`: Enables capture of trace data for http request / response. + * + * By default the `node`, `node.async_hooks`, and `v8` categories are enabled. + * + * ```bash + * node --trace-event-categories v8,node,node.async_hooks server.js + * ``` + * + * Prior versions of Node.js required the use of the `--trace-events-enabled` flag to enable trace events. This requirement has been removed. However, the `--trace-events-enabled` flag _may_ still be + * used and will enable the `node`, `node.async_hooks`, and `v8` trace event categories by default. + * + * ```bash + * node --trace-events-enabled + * + * # is equivalent to + * + * node --trace-event-categories v8,node,node.async_hooks + * ``` + * + * Alternatively, trace events may be enabled using the `node:trace_events` module: + * + * ```js + * import trace_events from 'node:trace_events'; + * const tracing = trace_events.createTracing({ categories: ['node.perf'] }); + * tracing.enable(); // Enable trace event capture for the 'node.perf' category + * + * // do work + * + * tracing.disable(); // Disable trace event capture for the 'node.perf' category + * ``` + * + * Running Node.js with tracing enabled will produce log files that can be opened + * in the [`chrome://tracing`](https://www.chromium.org/developers/how-tos/trace-event-profiling-tool) tab of Chrome. + * + * The logging file is by default called `node_trace.${rotation}.log`, where `${rotation}` is an incrementing log-rotation id. The filepath pattern can + * be specified with `--trace-event-file-pattern` that accepts a template + * string that supports `${rotation}` and `${pid}`: + * + * ```bash + * node --trace-event-categories v8 --trace-event-file-pattern '${pid}-${rotation}.log' server.js + * ``` + * + * To guarantee that the log file is properly generated after signal events like `SIGINT`, `SIGTERM`, or `SIGBREAK`, make sure to have the appropriate handlers + * in your code, such as: + * + * ```js + * process.on('SIGINT', function onSigint() { + * console.info('Received SIGINT.'); + * process.exit(130); // Or applicable exit code depending on OS and signal + * }); + * ``` + * + * The tracing system uses the same time source + * as the one used by `process.hrtime()`. + * However the trace-event timestamps are expressed in microseconds, + * unlike `process.hrtime()` which returns nanoseconds. + * + * The features from this module are not available in [`Worker`](https://nodejs.org/docs/latest-v25.x/api/worker_threads.html#class-worker) threads. + * @experimental + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/trace_events.js) + */ +declare module "node:trace_events" { + /** + * The `Tracing` object is used to enable or disable tracing for sets of + * categories. Instances are created using the + * `trace_events.createTracing()` method. + * + * When created, the `Tracing` object is disabled. Calling the + * `tracing.enable()` method adds the categories to the set of enabled trace + * event categories. Calling `tracing.disable()` will remove the categories + * from the set of enabled trace event categories. + */ + interface Tracing { + /** + * A comma-separated list of the trace event categories covered by this + * `Tracing` object. + * @since v10.0.0 + */ + readonly categories: string; + /** + * Disables this `Tracing` object. + * + * Only trace event categories _not_ covered by other enabled `Tracing` + * objects and _not_ specified by the `--trace-event-categories` flag + * will be disabled. + * + * ```js + * import trace_events from 'node:trace_events'; + * const t1 = trace_events.createTracing({ categories: ['node', 'v8'] }); + * const t2 = trace_events.createTracing({ categories: ['node.perf', 'node'] }); + * t1.enable(); + * t2.enable(); + * + * // Prints 'node,node.perf,v8' + * console.log(trace_events.getEnabledCategories()); + * + * t2.disable(); // Will only disable emission of the 'node.perf' category + * + * // Prints 'node,v8' + * console.log(trace_events.getEnabledCategories()); + * ``` + * @since v10.0.0 + */ + disable(): void; + /** + * Enables this `Tracing` object for the set of categories covered by + * the `Tracing` object. + * @since v10.0.0 + */ + enable(): void; + /** + * `true` only if the `Tracing` object has been enabled. + * @since v10.0.0 + */ + readonly enabled: boolean; + } + interface CreateTracingOptions { + /** + * An array of trace category names. Values included in the array are + * coerced to a string when possible. An error will be thrown if the + * value cannot be coerced. + */ + categories: string[]; + } + /** + * Creates and returns a `Tracing` object for the given set of `categories`. + * + * ```js + * import trace_events from 'node:trace_events'; + * const categories = ['node.perf', 'node.async_hooks']; + * const tracing = trace_events.createTracing({ categories }); + * tracing.enable(); + * // do stuff + * tracing.disable(); + * ``` + * @since v10.0.0 + */ + function createTracing(options: CreateTracingOptions): Tracing; + /** + * Returns a comma-separated list of all currently-enabled trace event + * categories. The current set of enabled trace event categories is determined + * by the _union_ of all currently-enabled `Tracing` objects and any categories + * enabled using the `--trace-event-categories` flag. + * + * Given the file `test.js` below, the command `node --trace-event-categories node.perf test.js` will print `'node.async_hooks,node.perf'` to the console. + * + * ```js + * import trace_events from 'node:trace_events'; + * const t1 = trace_events.createTracing({ categories: ['node.async_hooks'] }); + * const t2 = trace_events.createTracing({ categories: ['node.perf'] }); + * const t3 = trace_events.createTracing({ categories: ['v8'] }); + * + * t1.enable(); + * t2.enable(); + * + * console.log(trace_events.getEnabledCategories()); + * ``` + * @since v10.0.0 + */ + function getEnabledCategories(): string | undefined; +} +declare module "trace_events" { + export * from "node:trace_events"; +} diff --git a/server/node_modules/@types/node/ts5.6/buffer.buffer.d.ts b/server/node_modules/@types/node/ts5.6/buffer.buffer.d.ts new file mode 100644 index 0000000..bd32dc6 --- /dev/null +++ b/server/node_modules/@types/node/ts5.6/buffer.buffer.d.ts @@ -0,0 +1,462 @@ +declare module "node:buffer" { + global { + interface BufferConstructor { + // see ../buffer.d.ts for implementation shared with all TypeScript versions + + /** + * Allocates a new buffer containing the given {str}. + * + * @param str String to store in buffer. + * @param encoding encoding to use, optional. Default is 'utf8' + * @deprecated since v10.0.0 - Use `Buffer.from(string[, encoding])` instead. + */ + new(str: string, encoding?: BufferEncoding): Buffer; + /** + * Allocates a new buffer of {size} octets. + * + * @param size count of octets to allocate. + * @deprecated since v10.0.0 - Use `Buffer.alloc()` instead (also see `Buffer.allocUnsafe()`). + */ + new(size: number): Buffer; + /** + * Allocates a new buffer containing the given {array} of octets. + * + * @param array The octets to store. + * @deprecated since v10.0.0 - Use `Buffer.from(array)` instead. + */ + new(array: ArrayLike<number>): Buffer; + /** + * Produces a Buffer backed by the same allocated memory as + * the given {ArrayBuffer}/{SharedArrayBuffer}. + * + * @param arrayBuffer The ArrayBuffer with which to share memory. + * @deprecated since v10.0.0 - Use `Buffer.from(arrayBuffer[, byteOffset[, length]])` instead. + */ + new(arrayBuffer: ArrayBufferLike): Buffer; + /** + * Allocates a new `Buffer` using an `array` of bytes in the range `0` – `255`. + * Array entries outside that range will be truncated to fit into it. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * // Creates a new Buffer containing the UTF-8 bytes of the string 'buffer'. + * const buf = Buffer.from([0x62, 0x75, 0x66, 0x66, 0x65, 0x72]); + * ``` + * + * If `array` is an `Array`-like object (that is, one with a `length` property of + * type `number`), it is treated as if it is an array, unless it is a `Buffer` or + * a `Uint8Array`. This means all other `TypedArray` variants get treated as an + * `Array`. To create a `Buffer` from the bytes backing a `TypedArray`, use + * `Buffer.copyBytesFrom()`. + * + * A `TypeError` will be thrown if `array` is not an `Array` or another type + * appropriate for `Buffer.from()` variants. + * + * `Buffer.from(array)` and `Buffer.from(string)` may also use the internal + * `Buffer` pool like `Buffer.allocUnsafe()` does. + * @since v5.10.0 + */ + from(array: WithImplicitCoercion<ArrayLike<number>>): Buffer; + /** + * This creates a view of the `ArrayBuffer` without copying the underlying + * memory. For example, when passed a reference to the `.buffer` property of a + * `TypedArray` instance, the newly created `Buffer` will share the same + * allocated memory as the `TypedArray`'s underlying `ArrayBuffer`. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const arr = new Uint16Array(2); + * + * arr[0] = 5000; + * arr[1] = 4000; + * + * // Shares memory with `arr`. + * const buf = Buffer.from(arr.buffer); + * + * console.log(buf); + * // Prints: <Buffer 88 13 a0 0f> + * + * // Changing the original Uint16Array changes the Buffer also. + * arr[1] = 6000; + * + * console.log(buf); + * // Prints: <Buffer 88 13 70 17> + * ``` + * + * The optional `byteOffset` and `length` arguments specify a memory range within + * the `arrayBuffer` that will be shared by the `Buffer`. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const ab = new ArrayBuffer(10); + * const buf = Buffer.from(ab, 0, 2); + * + * console.log(buf.length); + * // Prints: 2 + * ``` + * + * A `TypeError` will be thrown if `arrayBuffer` is not an `ArrayBuffer` or a + * `SharedArrayBuffer` or another type appropriate for `Buffer.from()` + * variants. + * + * It is important to remember that a backing `ArrayBuffer` can cover a range + * of memory that extends beyond the bounds of a `TypedArray` view. A new + * `Buffer` created using the `buffer` property of a `TypedArray` may extend + * beyond the range of the `TypedArray`: + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const arrA = Uint8Array.from([0x63, 0x64, 0x65, 0x66]); // 4 elements + * const arrB = new Uint8Array(arrA.buffer, 1, 2); // 2 elements + * console.log(arrA.buffer === arrB.buffer); // true + * + * const buf = Buffer.from(arrB.buffer); + * console.log(buf); + * // Prints: <Buffer 63 64 65 66> + * ``` + * @since v5.10.0 + * @param arrayBuffer An `ArrayBuffer`, `SharedArrayBuffer`, for example the + * `.buffer` property of a `TypedArray`. + * @param byteOffset Index of first byte to expose. **Default:** `0`. + * @param length Number of bytes to expose. **Default:** + * `arrayBuffer.byteLength - byteOffset`. + */ + from( + arrayBuffer: WithImplicitCoercion<ArrayBufferLike>, + byteOffset?: number, + length?: number, + ): Buffer; + /** + * Creates a new `Buffer` containing `string`. The `encoding` parameter identifies + * the character encoding to be used when converting `string` into bytes. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf1 = Buffer.from('this is a tést'); + * const buf2 = Buffer.from('7468697320697320612074c3a97374', 'hex'); + * + * console.log(buf1.toString()); + * // Prints: this is a tést + * console.log(buf2.toString()); + * // Prints: this is a tést + * console.log(buf1.toString('latin1')); + * // Prints: this is a tést + * ``` + * + * A `TypeError` will be thrown if `string` is not a string or another type + * appropriate for `Buffer.from()` variants. + * + * `Buffer.from(string)` may also use the internal `Buffer` pool like + * `Buffer.allocUnsafe()` does. + * @since v5.10.0 + * @param string A string to encode. + * @param encoding The encoding of `string`. **Default:** `'utf8'`. + */ + from(string: WithImplicitCoercion<string>, encoding?: BufferEncoding): Buffer; + from(arrayOrString: WithImplicitCoercion<ArrayLike<number> | string>): Buffer; + /** + * Creates a new Buffer using the passed {data} + * @param values to create a new Buffer + */ + of(...items: number[]): Buffer; + /** + * Returns a new `Buffer` which is the result of concatenating all the `Buffer` instances in the `list` together. + * + * If the list has no items, or if the `totalLength` is 0, then a new zero-length `Buffer` is returned. + * + * If `totalLength` is not provided, it is calculated from the `Buffer` instances + * in `list` by adding their lengths. + * + * If `totalLength` is provided, it is coerced to an unsigned integer. If the + * combined length of the `Buffer`s in `list` exceeds `totalLength`, the result is + * truncated to `totalLength`. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * // Create a single `Buffer` from a list of three `Buffer` instances. + * + * const buf1 = Buffer.alloc(10); + * const buf2 = Buffer.alloc(14); + * const buf3 = Buffer.alloc(18); + * const totalLength = buf1.length + buf2.length + buf3.length; + * + * console.log(totalLength); + * // Prints: 42 + * + * const bufA = Buffer.concat([buf1, buf2, buf3], totalLength); + * + * console.log(bufA); + * // Prints: <Buffer 00 00 00 00 ...> + * console.log(bufA.length); + * // Prints: 42 + * ``` + * + * `Buffer.concat()` may also use the internal `Buffer` pool like `Buffer.allocUnsafe()` does. + * @since v0.7.11 + * @param list List of `Buffer` or {@link Uint8Array} instances to concatenate. + * @param totalLength Total length of the `Buffer` instances in `list` when concatenated. + */ + concat(list: readonly Uint8Array[], totalLength?: number): Buffer; + /** + * Copies the underlying memory of `view` into a new `Buffer`. + * + * ```js + * const u16 = new Uint16Array([0, 0xffff]); + * const buf = Buffer.copyBytesFrom(u16, 1, 1); + * u16[1] = 0; + * console.log(buf.length); // 2 + * console.log(buf[0]); // 255 + * console.log(buf[1]); // 255 + * ``` + * @since v19.8.0 + * @param view The {TypedArray} to copy. + * @param [offset=0] The starting offset within `view`. + * @param [length=view.length - offset] The number of elements from `view` to copy. + */ + copyBytesFrom(view: NodeJS.TypedArray, offset?: number, length?: number): Buffer; + /** + * Allocates a new `Buffer` of `size` bytes. If `fill` is `undefined`, the`Buffer` will be zero-filled. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.alloc(5); + * + * console.log(buf); + * // Prints: <Buffer 00 00 00 00 00> + * ``` + * + * If `size` is larger than {@link constants.MAX_LENGTH} or smaller than 0, `ERR_OUT_OF_RANGE` is thrown. + * + * If `fill` is specified, the allocated `Buffer` will be initialized by calling `buf.fill(fill)`. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.alloc(5, 'a'); + * + * console.log(buf); + * // Prints: <Buffer 61 61 61 61 61> + * ``` + * + * If both `fill` and `encoding` are specified, the allocated `Buffer` will be + * initialized by calling `buf.fill(fill, encoding)`. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.alloc(11, 'aGVsbG8gd29ybGQ=', 'base64'); + * + * console.log(buf); + * // Prints: <Buffer 68 65 6c 6c 6f 20 77 6f 72 6c 64> + * ``` + * + * Calling `Buffer.alloc()` can be measurably slower than the alternative `Buffer.allocUnsafe()` but ensures that the newly created `Buffer` instance + * contents will never contain sensitive data from previous allocations, including + * data that might not have been allocated for `Buffer`s. + * + * A `TypeError` will be thrown if `size` is not a number. + * @since v5.10.0 + * @param size The desired length of the new `Buffer`. + * @param [fill=0] A value to pre-fill the new `Buffer` with. + * @param [encoding='utf8'] If `fill` is a string, this is its encoding. + */ + alloc(size: number, fill?: string | Uint8Array | number, encoding?: BufferEncoding): Buffer; + /** + * Allocates a new `Buffer` of `size` bytes. If `size` is larger than {@link constants.MAX_LENGTH} or smaller than 0, `ERR_OUT_OF_RANGE` is thrown. + * + * The underlying memory for `Buffer` instances created in this way is _not_ + * _initialized_. The contents of the newly created `Buffer` are unknown and _may contain sensitive data_. Use `Buffer.alloc()` instead to initialize`Buffer` instances with zeroes. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.allocUnsafe(10); + * + * console.log(buf); + * // Prints (contents may vary): <Buffer a0 8b 28 3f 01 00 00 00 50 32> + * + * buf.fill(0); + * + * console.log(buf); + * // Prints: <Buffer 00 00 00 00 00 00 00 00 00 00> + * ``` + * + * A `TypeError` will be thrown if `size` is not a number. + * + * The `Buffer` module pre-allocates an internal `Buffer` instance of + * size `Buffer.poolSize` that is used as a pool for the fast allocation of new `Buffer` instances created using `Buffer.allocUnsafe()`, `Buffer.from(array)`, + * and `Buffer.concat()` only when `size` is less than `Buffer.poolSize >>> 1` (floor of `Buffer.poolSize` divided by two). + * + * Use of this pre-allocated internal memory pool is a key difference between + * calling `Buffer.alloc(size, fill)` vs. `Buffer.allocUnsafe(size).fill(fill)`. + * Specifically, `Buffer.alloc(size, fill)` will _never_ use the internal `Buffer`pool, while `Buffer.allocUnsafe(size).fill(fill)`_will_ use the internal`Buffer` pool if `size` is less + * than or equal to half `Buffer.poolSize`. The + * difference is subtle but can be important when an application requires the + * additional performance that `Buffer.allocUnsafe()` provides. + * @since v5.10.0 + * @param size The desired length of the new `Buffer`. + */ + allocUnsafe(size: number): Buffer; + /** + * Allocates a new `Buffer` of `size` bytes. If `size` is larger than {@link constants.MAX_LENGTH} or smaller than 0, `ERR_OUT_OF_RANGE` is thrown. A zero-length `Buffer` is created if + * `size` is 0. + * + * The underlying memory for `Buffer` instances created in this way is _not_ + * _initialized_. The contents of the newly created `Buffer` are unknown and _may contain sensitive data_. Use `buf.fill(0)` to initialize + * such `Buffer` instances with zeroes. + * + * When using `Buffer.allocUnsafe()` to allocate new `Buffer` instances, + * allocations under 4 KiB are sliced from a single pre-allocated `Buffer`. This + * allows applications to avoid the garbage collection overhead of creating many + * individually allocated `Buffer` instances. This approach improves both + * performance and memory usage by eliminating the need to track and clean up as + * many individual `ArrayBuffer` objects. + * + * However, in the case where a developer may need to retain a small chunk of + * memory from a pool for an indeterminate amount of time, it may be appropriate + * to create an un-pooled `Buffer` instance using `Buffer.allocUnsafeSlow()` and + * then copying out the relevant bits. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * // Need to keep around a few small chunks of memory. + * const store = []; + * + * socket.on('readable', () => { + * let data; + * while (null !== (data = readable.read())) { + * // Allocate for retained data. + * const sb = Buffer.allocUnsafeSlow(10); + * + * // Copy the data into the new allocation. + * data.copy(sb, 0, 0, 10); + * + * store.push(sb); + * } + * }); + * ``` + * + * A `TypeError` will be thrown if `size` is not a number. + * @since v5.12.0 + * @param size The desired length of the new `Buffer`. + */ + allocUnsafeSlow(size: number): Buffer; + } + interface Buffer extends Uint8Array { + // see ../buffer.d.ts for implementation shared with all TypeScript versions + + /** + * Returns a new `Buffer` that references the same memory as the original, but + * offset and cropped by the `start` and `end` indices. + * + * This method is not compatible with the `Uint8Array.prototype.slice()`, + * which is a superclass of `Buffer`. To copy the slice, use`Uint8Array.prototype.slice()`. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.from('buffer'); + * + * const copiedBuf = Uint8Array.prototype.slice.call(buf); + * copiedBuf[0]++; + * console.log(copiedBuf.toString()); + * // Prints: cuffer + * + * console.log(buf.toString()); + * // Prints: buffer + * + * // With buf.slice(), the original buffer is modified. + * const notReallyCopiedBuf = buf.slice(); + * notReallyCopiedBuf[0]++; + * console.log(notReallyCopiedBuf.toString()); + * // Prints: cuffer + * console.log(buf.toString()); + * // Also prints: cuffer (!) + * ``` + * @since v0.3.0 + * @deprecated Use `subarray` instead. + * @param [start=0] Where the new `Buffer` will start. + * @param [end=buf.length] Where the new `Buffer` will end (not inclusive). + */ + slice(start?: number, end?: number): Buffer; + /** + * Returns a new `Buffer` that references the same memory as the original, but + * offset and cropped by the `start` and `end` indices. + * + * Specifying `end` greater than `buf.length` will return the same result as + * that of `end` equal to `buf.length`. + * + * This method is inherited from [`TypedArray.prototype.subarray()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/subarray). + * + * Modifying the new `Buffer` slice will modify the memory in the original `Buffer`because the allocated memory of the two objects overlap. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * // Create a `Buffer` with the ASCII alphabet, take a slice, and modify one byte + * // from the original `Buffer`. + * + * const buf1 = Buffer.allocUnsafe(26); + * + * for (let i = 0; i < 26; i++) { + * // 97 is the decimal ASCII value for 'a'. + * buf1[i] = i + 97; + * } + * + * const buf2 = buf1.subarray(0, 3); + * + * console.log(buf2.toString('ascii', 0, buf2.length)); + * // Prints: abc + * + * buf1[0] = 33; + * + * console.log(buf2.toString('ascii', 0, buf2.length)); + * // Prints: !bc + * ``` + * + * Specifying negative indexes causes the slice to be generated relative to the + * end of `buf` rather than the beginning. + * + * ```js + * import { Buffer } from 'node:buffer'; + * + * const buf = Buffer.from('buffer'); + * + * console.log(buf.subarray(-6, -1).toString()); + * // Prints: buffe + * // (Equivalent to buf.subarray(0, 5).) + * + * console.log(buf.subarray(-6, -2).toString()); + * // Prints: buff + * // (Equivalent to buf.subarray(0, 4).) + * + * console.log(buf.subarray(-5, -2).toString()); + * // Prints: uff + * // (Equivalent to buf.subarray(1, 4).) + * ``` + * @since v3.0.0 + * @param [start=0] Where the new `Buffer` will start. + * @param [end=buf.length] Where the new `Buffer` will end (not inclusive). + */ + subarray(start?: number, end?: number): Buffer; + } + /** + * @deprecated This is intended for internal use, and will be removed once `@types/node` no longer supports + * TypeScript versions earlier than 5.7. + */ + type NonSharedBuffer = Buffer; + /** + * @deprecated This is intended for internal use, and will be removed once `@types/node` no longer supports + * TypeScript versions earlier than 5.7. + */ + type AllowSharedBuffer = Buffer; + } +} diff --git a/server/node_modules/@types/node/ts5.6/compatibility/float16array.d.ts b/server/node_modules/@types/node/ts5.6/compatibility/float16array.d.ts new file mode 100644 index 0000000..f148cc4 --- /dev/null +++ b/server/node_modules/@types/node/ts5.6/compatibility/float16array.d.ts @@ -0,0 +1,71 @@ +// Interface declaration for Float16Array, required in @types/node v24+. +// These definitions are specific to TS <=5.6. + +// This needs all of the "common" properties/methods of the TypedArrays, +// otherwise the type unions `TypedArray` and `ArrayBufferView` will be +// empty objects. +interface Float16Array extends Pick<Float32Array, typeof Symbol.iterator | "entries" | "keys" | "values"> { + readonly BYTES_PER_ELEMENT: number; + readonly buffer: ArrayBufferLike; + readonly byteLength: number; + readonly byteOffset: number; + readonly length: number; + readonly [Symbol.toStringTag]: "Float16Array"; + at(index: number): number | undefined; + copyWithin(target: number, start: number, end?: number): this; + every(predicate: (value: number, index: number, array: Float16Array) => unknown, thisArg?: any): boolean; + fill(value: number, start?: number, end?: number): this; + filter(predicate: (value: number, index: number, array: Float16Array) => any, thisArg?: any): Float16Array; + find(predicate: (value: number, index: number, obj: Float16Array) => boolean, thisArg?: any): number | undefined; + findIndex(predicate: (value: number, index: number, obj: Float16Array) => boolean, thisArg?: any): number; + findLast<S extends number>( + predicate: (value: number, index: number, array: Float16Array) => value is S, + thisArg?: any, + ): S | undefined; + findLast( + predicate: (value: number, index: number, array: Float16Array) => unknown, + thisArg?: any, + ): number | undefined; + findLastIndex(predicate: (value: number, index: number, array: Float16Array) => unknown, thisArg?: any): number; + forEach(callbackfn: (value: number, index: number, array: Float16Array) => void, thisArg?: any): void; + includes(searchElement: number, fromIndex?: number): boolean; + indexOf(searchElement: number, fromIndex?: number): number; + join(separator?: string): string; + lastIndexOf(searchElement: number, fromIndex?: number): number; + map(callbackfn: (value: number, index: number, array: Float16Array) => number, thisArg?: any): Float16Array; + reduce( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float16Array) => number, + ): number; + reduce( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float16Array) => number, + initialValue: number, + ): number; + reduce<U>( + callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Float16Array) => U, + initialValue: U, + ): U; + reduceRight( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float16Array) => number, + ): number; + reduceRight( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float16Array) => number, + initialValue: number, + ): number; + reduceRight<U>( + callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Float16Array) => U, + initialValue: U, + ): U; + reverse(): Float16Array; + set(array: ArrayLike<number>, offset?: number): void; + slice(start?: number, end?: number): Float16Array; + some(predicate: (value: number, index: number, array: Float16Array) => unknown, thisArg?: any): boolean; + sort(compareFn?: (a: number, b: number) => number): this; + subarray(begin?: number, end?: number): Float16Array; + toLocaleString(locales: string | string[], options?: Intl.NumberFormatOptions): string; + toReversed(): Float16Array; + toSorted(compareFn?: (a: number, b: number) => number): Float16Array; + toString(): string; + valueOf(): Float16Array; + with(index: number, value: number): Float16Array; + [index: number]: number; +} diff --git a/server/node_modules/@types/node/ts5.6/globals.typedarray.d.ts b/server/node_modules/@types/node/ts5.6/globals.typedarray.d.ts new file mode 100644 index 0000000..57a1ab4 --- /dev/null +++ b/server/node_modules/@types/node/ts5.6/globals.typedarray.d.ts @@ -0,0 +1,36 @@ +export {}; // Make this a module + +declare global { + namespace NodeJS { + type TypedArray = + | Uint8Array + | Uint8ClampedArray + | Uint16Array + | Uint32Array + | Int8Array + | Int16Array + | Int32Array + | BigUint64Array + | BigInt64Array + | Float16Array + | Float32Array + | Float64Array; + type ArrayBufferView = TypedArray | DataView; + + type NonSharedUint8Array = Uint8Array; + type NonSharedUint8ClampedArray = Uint8ClampedArray; + type NonSharedUint16Array = Uint16Array; + type NonSharedUint32Array = Uint32Array; + type NonSharedInt8Array = Int8Array; + type NonSharedInt16Array = Int16Array; + type NonSharedInt32Array = Int32Array; + type NonSharedBigUint64Array = BigUint64Array; + type NonSharedBigInt64Array = BigInt64Array; + type NonSharedFloat16Array = Float16Array; + type NonSharedFloat32Array = Float32Array; + type NonSharedFloat64Array = Float64Array; + type NonSharedDataView = DataView; + type NonSharedTypedArray = TypedArray; + type NonSharedArrayBufferView = ArrayBufferView; + } +} diff --git a/server/node_modules/@types/node/ts5.6/index.d.ts b/server/node_modules/@types/node/ts5.6/index.d.ts new file mode 100644 index 0000000..a157660 --- /dev/null +++ b/server/node_modules/@types/node/ts5.6/index.d.ts @@ -0,0 +1,117 @@ +/** + * License for programmatically and manually incorporated + * documentation aka. `JSDoc` from https://github.com/nodejs/node/tree/master/doc + * + * Copyright Node.js contributors. All rights reserved. + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +// NOTE: These definitions support Node.js and TypeScript 5.2 through 5.6. + +// Reference required TypeScript libraries: +/// <reference lib="es2020" /> +/// <reference lib="esnext.disposable" /> + +// TypeScript library polyfills required for TypeScript <=5.6: +/// <reference path="./compatibility/float16array.d.ts" /> + +// Iterator definitions required for compatibility with TypeScript <5.6: +/// <reference path="../compatibility/iterators.d.ts" /> + +// Definitions for Node.js modules specific to TypeScript <=5.6: +/// <reference path="./globals.typedarray.d.ts" /> +/// <reference path="./buffer.buffer.d.ts" /> + +// Definitions for Node.js modules that are not specific to any version of TypeScript: +/// <reference path="../globals.d.ts" /> +/// <reference path="../web-globals/abortcontroller.d.ts" /> +/// <reference path="../web-globals/blob.d.ts" /> +/// <reference path="../web-globals/console.d.ts" /> +/// <reference path="../web-globals/crypto.d.ts" /> +/// <reference path="../web-globals/domexception.d.ts" /> +/// <reference path="../web-globals/encoding.d.ts" /> +/// <reference path="../web-globals/events.d.ts" /> +/// <reference path="../web-globals/fetch.d.ts" /> +/// <reference path="../web-globals/importmeta.d.ts" /> +/// <reference path="../web-globals/messaging.d.ts" /> +/// <reference path="../web-globals/navigator.d.ts" /> +/// <reference path="../web-globals/performance.d.ts" /> +/// <reference path="../web-globals/storage.d.ts" /> +/// <reference path="../web-globals/streams.d.ts" /> +/// <reference path="../web-globals/timers.d.ts" /> +/// <reference path="../web-globals/url.d.ts" /> +/// <reference path="../assert.d.ts" /> +/// <reference path="../assert/strict.d.ts" /> +/// <reference path="../async_hooks.d.ts" /> +/// <reference path="../buffer.d.ts" /> +/// <reference path="../child_process.d.ts" /> +/// <reference path="../cluster.d.ts" /> +/// <reference path="../console.d.ts" /> +/// <reference path="../constants.d.ts" /> +/// <reference path="../crypto.d.ts" /> +/// <reference path="../dgram.d.ts" /> +/// <reference path="../diagnostics_channel.d.ts" /> +/// <reference path="../dns.d.ts" /> +/// <reference path="../dns/promises.d.ts" /> +/// <reference path="../domain.d.ts" /> +/// <reference path="../events.d.ts" /> +/// <reference path="../fs.d.ts" /> +/// <reference path="../fs/promises.d.ts" /> +/// <reference path="../http.d.ts" /> +/// <reference path="../http2.d.ts" /> +/// <reference path="../https.d.ts" /> +/// <reference path="../inspector.d.ts" /> +/// <reference path="../inspector.generated.d.ts" /> +/// <reference path="../inspector/promises.d.ts" /> +/// <reference path="../module.d.ts" /> +/// <reference path="../net.d.ts" /> +/// <reference path="../os.d.ts" /> +/// <reference path="../path.d.ts" /> +/// <reference path="../path/posix.d.ts" /> +/// <reference path="../path/win32.d.ts" /> +/// <reference path="../perf_hooks.d.ts" /> +/// <reference path="../process.d.ts" /> +/// <reference path="../punycode.d.ts" /> +/// <reference path="../querystring.d.ts" /> +/// <reference path="../quic.d.ts" /> +/// <reference path="../readline.d.ts" /> +/// <reference path="../readline/promises.d.ts" /> +/// <reference path="../repl.d.ts" /> +/// <reference path="../sea.d.ts" /> +/// <reference path="../sqlite.d.ts" /> +/// <reference path="../stream.d.ts" /> +/// <reference path="../stream/consumers.d.ts" /> +/// <reference path="../stream/promises.d.ts" /> +/// <reference path="../stream/web.d.ts" /> +/// <reference path="../string_decoder.d.ts" /> +/// <reference path="../test.d.ts" /> +/// <reference path="../test/reporters.d.ts" /> +/// <reference path="../timers.d.ts" /> +/// <reference path="../timers/promises.d.ts" /> +/// <reference path="../tls.d.ts" /> +/// <reference path="../trace_events.d.ts" /> +/// <reference path="../tty.d.ts" /> +/// <reference path="../url.d.ts" /> +/// <reference path="../util.d.ts" /> +/// <reference path="../util/types.d.ts" /> +/// <reference path="../v8.d.ts" /> +/// <reference path="../vm.d.ts" /> +/// <reference path="../wasi.d.ts" /> +/// <reference path="../worker_threads.d.ts" /> +/// <reference path="../zlib.d.ts" /> diff --git a/server/node_modules/@types/node/ts5.7/compatibility/float16array.d.ts b/server/node_modules/@types/node/ts5.7/compatibility/float16array.d.ts new file mode 100644 index 0000000..110b1eb --- /dev/null +++ b/server/node_modules/@types/node/ts5.7/compatibility/float16array.d.ts @@ -0,0 +1,72 @@ +// Interface declaration for Float16Array, required in @types/node v24+. +// These definitions are specific to TS 5.7. + +// This needs all of the "common" properties/methods of the TypedArrays, +// otherwise the type unions `TypedArray` and `ArrayBufferView` will be +// empty objects. +interface Float16Array<TArrayBuffer extends ArrayBufferLike = ArrayBufferLike> { + readonly BYTES_PER_ELEMENT: number; + readonly buffer: TArrayBuffer; + readonly byteLength: number; + readonly byteOffset: number; + readonly length: number; + readonly [Symbol.toStringTag]: "Float16Array"; + at(index: number): number | undefined; + copyWithin(target: number, start: number, end?: number): this; + entries(): ArrayIterator<[number, number]>; + every(predicate: (value: number, index: number, array: this) => unknown, thisArg?: any): boolean; + fill(value: number, start?: number, end?: number): this; + filter(predicate: (value: number, index: number, array: this) => any, thisArg?: any): Float16Array<ArrayBuffer>; + find(predicate: (value: number, index: number, obj: this) => boolean, thisArg?: any): number | undefined; + findIndex(predicate: (value: number, index: number, obj: this) => boolean, thisArg?: any): number; + findLast<S extends number>( + predicate: (value: number, index: number, array: this) => value is S, + thisArg?: any, + ): S | undefined; + findLast(predicate: (value: number, index: number, array: this) => unknown, thisArg?: any): number | undefined; + findLastIndex(predicate: (value: number, index: number, array: this) => unknown, thisArg?: any): number; + forEach(callbackfn: (value: number, index: number, array: this) => void, thisArg?: any): void; + includes(searchElement: number, fromIndex?: number): boolean; + indexOf(searchElement: number, fromIndex?: number): number; + join(separator?: string): string; + keys(): ArrayIterator<number>; + lastIndexOf(searchElement: number, fromIndex?: number): number; + map(callbackfn: (value: number, index: number, array: this) => number, thisArg?: any): Float16Array<ArrayBuffer>; + reduce( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: this) => number, + ): number; + reduce( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: this) => number, + initialValue: number, + ): number; + reduce<U>( + callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: this) => U, + initialValue: U, + ): U; + reduceRight( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: this) => number, + ): number; + reduceRight( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: this) => number, + initialValue: number, + ): number; + reduceRight<U>( + callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: this) => U, + initialValue: U, + ): U; + reverse(): this; + set(array: ArrayLike<number>, offset?: number): void; + slice(start?: number, end?: number): Float16Array<ArrayBuffer>; + some(predicate: (value: number, index: number, array: this) => unknown, thisArg?: any): boolean; + sort(compareFn?: (a: number, b: number) => number): this; + subarray(begin?: number, end?: number): Float16Array<TArrayBuffer>; + toLocaleString(locales: string | string[], options?: Intl.NumberFormatOptions): string; + toReversed(): Float16Array<ArrayBuffer>; + toSorted(compareFn?: (a: number, b: number) => number): Float16Array<ArrayBuffer>; + toString(): string; + valueOf(): this; + values(): ArrayIterator<number>; + with(index: number, value: number): Float16Array<ArrayBuffer>; + [Symbol.iterator](): ArrayIterator<number>; + [index: number]: number; +} diff --git a/server/node_modules/@types/node/ts5.7/index.d.ts b/server/node_modules/@types/node/ts5.7/index.d.ts new file mode 100644 index 0000000..32c541b --- /dev/null +++ b/server/node_modules/@types/node/ts5.7/index.d.ts @@ -0,0 +1,117 @@ +/** + * License for programmatically and manually incorporated + * documentation aka. `JSDoc` from https://github.com/nodejs/node/tree/master/doc + * + * Copyright Node.js contributors. All rights reserved. + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +// NOTE: These definitions support Node.js and TypeScript 5.7. + +// Reference required TypeScript libraries: +/// <reference lib="es2020" /> +/// <reference lib="esnext.disposable" /> + +// TypeScript library polyfills required for TypeScript 5.7: +/// <reference path="./compatibility/float16array.d.ts" /> + +// Iterator definitions required for compatibility with TypeScript <5.6: +/// <reference path="../compatibility/iterators.d.ts" /> + +// Definitions for Node.js modules specific to TypeScript 5.7+: +/// <reference path="../globals.typedarray.d.ts" /> +/// <reference path="../buffer.buffer.d.ts" /> + +// Definitions for Node.js modules that are not specific to any version of TypeScript: +/// <reference path="../globals.d.ts" /> +/// <reference path="../web-globals/abortcontroller.d.ts" /> +/// <reference path="../web-globals/blob.d.ts" /> +/// <reference path="../web-globals/console.d.ts" /> +/// <reference path="../web-globals/crypto.d.ts" /> +/// <reference path="../web-globals/domexception.d.ts" /> +/// <reference path="../web-globals/encoding.d.ts" /> +/// <reference path="../web-globals/events.d.ts" /> +/// <reference path="../web-globals/fetch.d.ts" /> +/// <reference path="../web-globals/importmeta.d.ts" /> +/// <reference path="../web-globals/messaging.d.ts" /> +/// <reference path="../web-globals/navigator.d.ts" /> +/// <reference path="../web-globals/performance.d.ts" /> +/// <reference path="../web-globals/storage.d.ts" /> +/// <reference path="../web-globals/streams.d.ts" /> +/// <reference path="../web-globals/timers.d.ts" /> +/// <reference path="../web-globals/url.d.ts" /> +/// <reference path="../assert.d.ts" /> +/// <reference path="../assert/strict.d.ts" /> +/// <reference path="../async_hooks.d.ts" /> +/// <reference path="../buffer.d.ts" /> +/// <reference path="../child_process.d.ts" /> +/// <reference path="../cluster.d.ts" /> +/// <reference path="../console.d.ts" /> +/// <reference path="../constants.d.ts" /> +/// <reference path="../crypto.d.ts" /> +/// <reference path="../dgram.d.ts" /> +/// <reference path="../diagnostics_channel.d.ts" /> +/// <reference path="../dns.d.ts" /> +/// <reference path="../dns/promises.d.ts" /> +/// <reference path="../domain.d.ts" /> +/// <reference path="../events.d.ts" /> +/// <reference path="../fs.d.ts" /> +/// <reference path="../fs/promises.d.ts" /> +/// <reference path="../http.d.ts" /> +/// <reference path="../http2.d.ts" /> +/// <reference path="../https.d.ts" /> +/// <reference path="../inspector.d.ts" /> +/// <reference path="../inspector.generated.d.ts" /> +/// <reference path="../inspector/promises.d.ts" /> +/// <reference path="../module.d.ts" /> +/// <reference path="../net.d.ts" /> +/// <reference path="../os.d.ts" /> +/// <reference path="../path.d.ts" /> +/// <reference path="../path/posix.d.ts" /> +/// <reference path="../path/win32.d.ts" /> +/// <reference path="../perf_hooks.d.ts" /> +/// <reference path="../process.d.ts" /> +/// <reference path="../punycode.d.ts" /> +/// <reference path="../querystring.d.ts" /> +/// <reference path="../quic.d.ts" /> +/// <reference path="../readline.d.ts" /> +/// <reference path="../readline/promises.d.ts" /> +/// <reference path="../repl.d.ts" /> +/// <reference path="../sea.d.ts" /> +/// <reference path="../sqlite.d.ts" /> +/// <reference path="../stream.d.ts" /> +/// <reference path="../stream/consumers.d.ts" /> +/// <reference path="../stream/promises.d.ts" /> +/// <reference path="../stream/web.d.ts" /> +/// <reference path="../string_decoder.d.ts" /> +/// <reference path="../test.d.ts" /> +/// <reference path="../test/reporters.d.ts" /> +/// <reference path="../timers.d.ts" /> +/// <reference path="../timers/promises.d.ts" /> +/// <reference path="../tls.d.ts" /> +/// <reference path="../trace_events.d.ts" /> +/// <reference path="../tty.d.ts" /> +/// <reference path="../url.d.ts" /> +/// <reference path="../util.d.ts" /> +/// <reference path="../util/types.d.ts" /> +/// <reference path="../v8.d.ts" /> +/// <reference path="../vm.d.ts" /> +/// <reference path="../wasi.d.ts" /> +/// <reference path="../worker_threads.d.ts" /> +/// <reference path="../zlib.d.ts" /> diff --git a/server/node_modules/@types/node/tty.d.ts b/server/node_modules/@types/node/tty.d.ts new file mode 100644 index 0000000..9b97a1e --- /dev/null +++ b/server/node_modules/@types/node/tty.d.ts @@ -0,0 +1,250 @@ +/** + * The `node:tty` module provides the `tty.ReadStream` and `tty.WriteStream` classes. In most cases, it will not be necessary or possible to use this module + * directly. However, it can be accessed using: + * + * ```js + * import tty from 'node:tty'; + * ``` + * + * When Node.js detects that it is being run with a text terminal ("TTY") + * attached, `process.stdin` will, by default, be initialized as an instance of `tty.ReadStream` and both `process.stdout` and `process.stderr` will, by + * default, be instances of `tty.WriteStream`. The preferred method of determining + * whether Node.js is being run within a TTY context is to check that the value of + * the `process.stdout.isTTY` property is `true`: + * + * ```console + * $ node -p -e "Boolean(process.stdout.isTTY)" + * true + * $ node -p -e "Boolean(process.stdout.isTTY)" | cat + * false + * ``` + * + * In most cases, there should be little to no reason for an application to + * manually create instances of the `tty.ReadStream` and `tty.WriteStream` classes. + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/tty.js) + */ +declare module "node:tty" { + import * as net from "node:net"; + /** + * The `tty.isatty()` method returns `true` if the given `fd` is associated with + * a TTY and `false` if it is not, including whenever `fd` is not a non-negative + * integer. + * @since v0.5.8 + * @param fd A numeric file descriptor + */ + function isatty(fd: number): boolean; + /** + * Represents the readable side of a TTY. In normal circumstances `process.stdin` will be the only `tty.ReadStream` instance in a Node.js + * process and there should be no reason to create additional instances. + * @since v0.5.8 + */ + class ReadStream extends net.Socket { + constructor(fd: number, options?: net.SocketConstructorOpts); + /** + * A `boolean` that is `true` if the TTY is currently configured to operate as a + * raw device. + * + * This flag is always `false` when a process starts, even if the terminal is + * operating in raw mode. Its value will change with subsequent calls to `setRawMode`. + * @since v0.7.7 + */ + isRaw: boolean; + /** + * Allows configuration of `tty.ReadStream` so that it operates as a raw device. + * + * When in raw mode, input is always available character-by-character, not + * including modifiers. Additionally, all special processing of characters by the + * terminal is disabled, including echoing input + * characters. Ctrl+C will no longer cause a `SIGINT` when + * in this mode. + * @since v0.7.7 + * @param mode If `true`, configures the `tty.ReadStream` to operate as a raw device. If `false`, configures the `tty.ReadStream` to operate in its default mode. The `readStream.isRaw` + * property will be set to the resulting mode. + * @return The read stream instance. + */ + setRawMode(mode: boolean): this; + /** + * A `boolean` that is always `true` for `tty.ReadStream` instances. + * @since v0.5.8 + */ + isTTY: boolean; + } + /** + * -1 - to the left from cursor + * 0 - the entire line + * 1 - to the right from cursor + */ + type Direction = -1 | 0 | 1; + interface WriteStreamEventMap extends net.SocketEventMap { + "resize": []; + } + /** + * Represents the writable side of a TTY. In normal circumstances, `process.stdout` and `process.stderr` will be the only`tty.WriteStream` instances created for a Node.js process and there + * should be no reason to create additional instances. + * @since v0.5.8 + */ + class WriteStream extends net.Socket { + constructor(fd: number); + /** + * `writeStream.clearLine()` clears the current line of this `WriteStream` in a + * direction identified by `dir`. + * @since v0.7.7 + * @param callback Invoked once the operation completes. + * @return `false` if the stream wishes for the calling code to wait for the `'drain'` event to be emitted before continuing to write additional data; otherwise `true`. + */ + clearLine(dir: Direction, callback?: () => void): boolean; + /** + * `writeStream.clearScreenDown()` clears this `WriteStream` from the current + * cursor down. + * @since v0.7.7 + * @param callback Invoked once the operation completes. + * @return `false` if the stream wishes for the calling code to wait for the `'drain'` event to be emitted before continuing to write additional data; otherwise `true`. + */ + clearScreenDown(callback?: () => void): boolean; + /** + * `writeStream.cursorTo()` moves this `WriteStream`'s cursor to the specified + * position. + * @since v0.7.7 + * @param callback Invoked once the operation completes. + * @return `false` if the stream wishes for the calling code to wait for the `'drain'` event to be emitted before continuing to write additional data; otherwise `true`. + */ + cursorTo(x: number, y?: number, callback?: () => void): boolean; + cursorTo(x: number, callback: () => void): boolean; + /** + * `writeStream.moveCursor()` moves this `WriteStream`'s cursor _relative_ to its + * current position. + * @since v0.7.7 + * @param callback Invoked once the operation completes. + * @return `false` if the stream wishes for the calling code to wait for the `'drain'` event to be emitted before continuing to write additional data; otherwise `true`. + */ + moveCursor(dx: number, dy: number, callback?: () => void): boolean; + /** + * Returns: + * + * * `1` for 2, + * * `4` for 16, + * * `8` for 256, + * * `24` for 16,777,216 colors supported. + * + * Use this to determine what colors the terminal supports. Due to the nature of + * colors in terminals it is possible to either have false positives or false + * negatives. It depends on process information and the environment variables that + * may lie about what terminal is used. + * It is possible to pass in an `env` object to simulate the usage of a specific + * terminal. This can be useful to check how specific environment settings behave. + * + * To enforce a specific color support, use one of the below environment settings. + * + * * 2 colors: `FORCE_COLOR = 0` (Disables colors) + * * 16 colors: `FORCE_COLOR = 1` + * * 256 colors: `FORCE_COLOR = 2` + * * 16,777,216 colors: `FORCE_COLOR = 3` + * + * Disabling color support is also possible by using the `NO_COLOR` and `NODE_DISABLE_COLORS` environment variables. + * @since v9.9.0 + * @param [env=process.env] An object containing the environment variables to check. This enables simulating the usage of a specific terminal. + */ + getColorDepth(env?: object): number; + /** + * Returns `true` if the `writeStream` supports at least as many colors as provided + * in `count`. Minimum support is 2 (black and white). + * + * This has the same false positives and negatives as described in `writeStream.getColorDepth()`. + * + * ```js + * process.stdout.hasColors(); + * // Returns true or false depending on if `stdout` supports at least 16 colors. + * process.stdout.hasColors(256); + * // Returns true or false depending on if `stdout` supports at least 256 colors. + * process.stdout.hasColors({ TMUX: '1' }); + * // Returns true. + * process.stdout.hasColors(2 ** 24, { TMUX: '1' }); + * // Returns false (the environment setting pretends to support 2 ** 8 colors). + * ``` + * @since v11.13.0, v10.16.0 + * @param [count=16] The number of colors that are requested (minimum 2). + * @param [env=process.env] An object containing the environment variables to check. This enables simulating the usage of a specific terminal. + */ + hasColors(count?: number): boolean; + hasColors(env?: object): boolean; + hasColors(count: number, env?: object): boolean; + /** + * `writeStream.getWindowSize()` returns the size of the TTY + * corresponding to this `WriteStream`. The array is of the type `[numColumns, numRows]` where `numColumns` and `numRows` represent the number + * of columns and rows in the corresponding TTY. + * @since v0.7.7 + */ + getWindowSize(): [number, number]; + /** + * A `number` specifying the number of columns the TTY currently has. This property + * is updated whenever the `'resize'` event is emitted. + * @since v0.7.7 + */ + columns: number; + /** + * A `number` specifying the number of rows the TTY currently has. This property + * is updated whenever the `'resize'` event is emitted. + * @since v0.7.7 + */ + rows: number; + /** + * A `boolean` that is always `true`. + * @since v0.5.8 + */ + isTTY: boolean; + // #region InternalEventEmitter + addListener<E extends keyof WriteStreamEventMap>( + eventName: E, + listener: (...args: WriteStreamEventMap[E]) => void, + ): this; + addListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + emit<E extends keyof WriteStreamEventMap>(eventName: E, ...args: WriteStreamEventMap[E]): boolean; + emit(eventName: string | symbol, ...args: any[]): boolean; + listenerCount<E extends keyof WriteStreamEventMap>( + eventName: E, + listener?: (...args: WriteStreamEventMap[E]) => void, + ): number; + listenerCount(eventName: string | symbol, listener?: (...args: any[]) => void): number; + listeners<E extends keyof WriteStreamEventMap>(eventName: E): ((...args: WriteStreamEventMap[E]) => void)[]; + listeners(eventName: string | symbol): ((...args: any[]) => void)[]; + off<E extends keyof WriteStreamEventMap>( + eventName: E, + listener: (...args: WriteStreamEventMap[E]) => void, + ): this; + off(eventName: string | symbol, listener: (...args: any[]) => void): this; + on<E extends keyof WriteStreamEventMap>( + eventName: E, + listener: (...args: WriteStreamEventMap[E]) => void, + ): this; + on(eventName: string | symbol, listener: (...args: any[]) => void): this; + once<E extends keyof WriteStreamEventMap>( + eventName: E, + listener: (...args: WriteStreamEventMap[E]) => void, + ): this; + once(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependListener<E extends keyof WriteStreamEventMap>( + eventName: E, + listener: (...args: WriteStreamEventMap[E]) => void, + ): this; + prependListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + prependOnceListener<E extends keyof WriteStreamEventMap>( + eventName: E, + listener: (...args: WriteStreamEventMap[E]) => void, + ): this; + prependOnceListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + rawListeners<E extends keyof WriteStreamEventMap>(eventName: E): ((...args: WriteStreamEventMap[E]) => void)[]; + rawListeners(eventName: string | symbol): ((...args: any[]) => void)[]; + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + removeAllListeners<E extends keyof WriteStreamEventMap>(eventName?: E): this; + removeAllListeners(eventName?: string | symbol): this; + removeListener<E extends keyof WriteStreamEventMap>( + eventName: E, + listener: (...args: WriteStreamEventMap[E]) => void, + ): this; + removeListener(eventName: string | symbol, listener: (...args: any[]) => void): this; + // #endregion + } +} +declare module "tty" { + export * from "node:tty"; +} diff --git a/server/node_modules/@types/node/url.d.ts b/server/node_modules/@types/node/url.d.ts new file mode 100644 index 0000000..6f5b885 --- /dev/null +++ b/server/node_modules/@types/node/url.d.ts @@ -0,0 +1,519 @@ +/** + * The `node:url` module provides utilities for URL resolution and parsing. It can + * be accessed using: + * + * ```js + * import url from 'node:url'; + * ``` + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/url.js) + */ +declare module "node:url" { + import { Blob, NonSharedBuffer } from "node:buffer"; + import { ClientRequestArgs } from "node:http"; + import { ParsedUrlQuery, ParsedUrlQueryInput } from "node:querystring"; + // Input to `url.format` + interface UrlObject { + auth?: string | null | undefined; + hash?: string | null | undefined; + host?: string | null | undefined; + hostname?: string | null | undefined; + href?: string | null | undefined; + pathname?: string | null | undefined; + protocol?: string | null | undefined; + search?: string | null | undefined; + slashes?: boolean | null | undefined; + port?: string | number | null | undefined; + query?: string | null | ParsedUrlQueryInput | undefined; + } + // Output of `url.parse` + interface Url { + auth: string | null; + hash: string | null; + host: string | null; + hostname: string | null; + href: string; + path: string | null; + pathname: string | null; + protocol: string | null; + search: string | null; + slashes: boolean | null; + port: string | null; + query: string | null | ParsedUrlQuery; + } + interface UrlWithParsedQuery extends Url { + query: ParsedUrlQuery; + } + interface UrlWithStringQuery extends Url { + query: string | null; + } + interface FileUrlToPathOptions { + /** + * `true` if the `path` should be return as a windows filepath, `false` for posix, and `undefined` for the system default. + * @default undefined + * @since v22.1.0 + */ + windows?: boolean | undefined; + } + interface PathToFileUrlOptions { + /** + * `true` if the `path` should be return as a windows filepath, `false` for posix, and `undefined` for the system default. + * @default undefined + * @since v22.1.0 + */ + windows?: boolean | undefined; + } + /** + * The `url.parse()` method takes a URL string, parses it, and returns a URL + * object. + * + * A `TypeError` is thrown if `urlString` is not a string. + * + * A `URIError` is thrown if the `auth` property is present but cannot be decoded. + * + * `url.parse()` uses a lenient, non-standard algorithm for parsing URL + * strings. It is prone to security issues such as [host name spoofing](https://hackerone.com/reports/678487) + * and incorrect handling of usernames and passwords. Do not use with untrusted + * input. CVEs are not issued for `url.parse()` vulnerabilities. Use the + * [WHATWG URL](https://nodejs.org/docs/latest-v25.x/api/url.html#the-whatwg-url-api) API instead, for example: + * + * ```js + * function getURL(req) { + * const proto = req.headers['x-forwarded-proto'] || 'https'; + * const host = req.headers['x-forwarded-host'] || req.headers.host || 'example.com'; + * return new URL(req.url || '/', `${proto}://${host}`); + * } + * ``` + * + * The example above assumes well-formed headers are forwarded from a reverse + * proxy to your Node.js server. If you are not using a reverse proxy, you should + * use the example below: + * + * ```js + * function getURL(req) { + * return new URL(req.url || '/', 'https://example.com'); + * } + * ``` + * @since v0.1.25 + * @deprecated Use the WHATWG URL API instead. + * @param urlString The URL string to parse. + * @param parseQueryString If `true`, the `query` property will always + * be set to an object returned by the [`querystring`](https://nodejs.org/docs/latest-v25.x/api/querystring.html) module's `parse()` + * method. If `false`, the `query` property on the returned URL object will be an + * unparsed, undecoded string. **Default:** `false`. + * @param slashesDenoteHost If `true`, the first token after the literal + * string `//` and preceding the next `/` will be interpreted as the `host`. + * For instance, given `//foo/bar`, the result would be + * `{host: 'foo', pathname: '/bar'}` rather than `{pathname: '//foo/bar'}`. + * **Default:** `false`. + */ + function parse( + urlString: string, + parseQueryString?: false, + slashesDenoteHost?: boolean, + ): UrlWithStringQuery; + function parse(urlString: string, parseQueryString: true, slashesDenoteHost?: boolean): UrlWithParsedQuery; + function parse(urlString: string, parseQueryString: boolean, slashesDenoteHost?: boolean): Url; + /** + * The `url.format()` method returns a formatted URL string derived from `urlObject`. + * + * ```js + * import url from 'node:url'; + * url.format({ + * protocol: 'https', + * hostname: 'example.com', + * pathname: '/some/path', + * query: { + * page: 1, + * format: 'json', + * }, + * }); + * + * // => 'https://example.com/some/path?page=1&format=json' + * ``` + * + * If `urlObject` is not an object or a string, `url.format()` will throw a `TypeError`. + * + * The formatting process operates as follows: + * + * * A new empty string `result` is created. + * * If `urlObject.protocol` is a string, it is appended as-is to `result`. + * * Otherwise, if `urlObject.protocol` is not `undefined` and is not a string, an `Error` is thrown. + * * For all string values of `urlObject.protocol` that _do not end_ with an ASCII + * colon (`:`) character, the literal string `:` will be appended to `result`. + * * If either of the following conditions is true, then the literal string `//` will be appended to `result`: + * * `urlObject.slashes` property is true; + * * `urlObject.protocol` begins with `http`, `https`, `ftp`, `gopher`, or `file`; + * * If the value of the `urlObject.auth` property is truthy, and either `urlObject.host` or `urlObject.hostname` are not `undefined`, the value of `urlObject.auth` will be coerced into a string + * and appended to `result` followed by the literal string `@`. + * * If the `urlObject.host` property is `undefined` then: + * * If the `urlObject.hostname` is a string, it is appended to `result`. + * * Otherwise, if `urlObject.hostname` is not `undefined` and is not a string, + * an `Error` is thrown. + * * If the `urlObject.port` property value is truthy, and `urlObject.hostname` is not `undefined`: + * * The literal string `:` is appended to `result`, and + * * The value of `urlObject.port` is coerced to a string and appended to `result`. + * * Otherwise, if the `urlObject.host` property value is truthy, the value of `urlObject.host` is coerced to a string and appended to `result`. + * * If the `urlObject.pathname` property is a string that is not an empty string: + * * If the `urlObject.pathname` _does not start_ with an ASCII forward slash + * (`/`), then the literal string `'/'` is appended to `result`. + * * The value of `urlObject.pathname` is appended to `result`. + * * Otherwise, if `urlObject.pathname` is not `undefined` and is not a string, an `Error` is thrown. + * * If the `urlObject.search` property is `undefined` and if the `urlObject.query`property is an `Object`, the literal string `?` is appended to `result` followed by the output of calling the + * `querystring` module's `stringify()` method passing the value of `urlObject.query`. + * * Otherwise, if `urlObject.search` is a string: + * * If the value of `urlObject.search` _does not start_ with the ASCII question + * mark (`?`) character, the literal string `?` is appended to `result`. + * * The value of `urlObject.search` is appended to `result`. + * * Otherwise, if `urlObject.search` is not `undefined` and is not a string, an `Error` is thrown. + * * If the `urlObject.hash` property is a string: + * * If the value of `urlObject.hash` _does not start_ with the ASCII hash (`#`) + * character, the literal string `#` is appended to `result`. + * * The value of `urlObject.hash` is appended to `result`. + * * Otherwise, if the `urlObject.hash` property is not `undefined` and is not a + * string, an `Error` is thrown. + * * `result` is returned. + * @since v0.1.25 + * @legacy Use the WHATWG URL API instead. + * @param urlObject A URL object (as returned by `url.parse()` or constructed otherwise). If a string, it is converted to an object by passing it to `url.parse()`. + */ + function format(urlObject: URL, options?: URLFormatOptions): string; + /** + * The `url.format()` method returns a formatted URL string derived from `urlObject`. + * + * ```js + * import url from 'node:url'; + * url.format({ + * protocol: 'https', + * hostname: 'example.com', + * pathname: '/some/path', + * query: { + * page: 1, + * format: 'json', + * }, + * }); + * + * // => 'https://example.com/some/path?page=1&format=json' + * ``` + * + * If `urlObject` is not an object or a string, `url.format()` will throw a `TypeError`. + * + * The formatting process operates as follows: + * + * * A new empty string `result` is created. + * * If `urlObject.protocol` is a string, it is appended as-is to `result`. + * * Otherwise, if `urlObject.protocol` is not `undefined` and is not a string, an `Error` is thrown. + * * For all string values of `urlObject.protocol` that _do not end_ with an ASCII + * colon (`:`) character, the literal string `:` will be appended to `result`. + * * If either of the following conditions is true, then the literal string `//` will be appended to `result`: + * * `urlObject.slashes` property is true; + * * `urlObject.protocol` begins with `http`, `https`, `ftp`, `gopher`, or `file`; + * * If the value of the `urlObject.auth` property is truthy, and either `urlObject.host` or `urlObject.hostname` are not `undefined`, the value of `urlObject.auth` will be coerced into a string + * and appended to `result` followed by the literal string `@`. + * * If the `urlObject.host` property is `undefined` then: + * * If the `urlObject.hostname` is a string, it is appended to `result`. + * * Otherwise, if `urlObject.hostname` is not `undefined` and is not a string, + * an `Error` is thrown. + * * If the `urlObject.port` property value is truthy, and `urlObject.hostname` is not `undefined`: + * * The literal string `:` is appended to `result`, and + * * The value of `urlObject.port` is coerced to a string and appended to `result`. + * * Otherwise, if the `urlObject.host` property value is truthy, the value of `urlObject.host` is coerced to a string and appended to `result`. + * * If the `urlObject.pathname` property is a string that is not an empty string: + * * If the `urlObject.pathname` _does not start_ with an ASCII forward slash + * (`/`), then the literal string `'/'` is appended to `result`. + * * The value of `urlObject.pathname` is appended to `result`. + * * Otherwise, if `urlObject.pathname` is not `undefined` and is not a string, an `Error` is thrown. + * * If the `urlObject.search` property is `undefined` and if the `urlObject.query`property is an `Object`, the literal string `?` is appended to `result` followed by the output of calling the + * `querystring` module's `stringify()` method passing the value of `urlObject.query`. + * * Otherwise, if `urlObject.search` is a string: + * * If the value of `urlObject.search` _does not start_ with the ASCII question + * mark (`?`) character, the literal string `?` is appended to `result`. + * * The value of `urlObject.search` is appended to `result`. + * * Otherwise, if `urlObject.search` is not `undefined` and is not a string, an `Error` is thrown. + * * If the `urlObject.hash` property is a string: + * * If the value of `urlObject.hash` _does not start_ with the ASCII hash (`#`) + * character, the literal string `#` is appended to `result`. + * * The value of `urlObject.hash` is appended to `result`. + * * Otherwise, if the `urlObject.hash` property is not `undefined` and is not a + * string, an `Error` is thrown. + * * `result` is returned. + * @since v0.1.25 + * @legacy Use the WHATWG URL API instead. + * @param urlObject A URL object (as returned by `url.parse()` or constructed otherwise). If a string, it is converted to an object by passing it to `url.parse()`. + */ + function format(urlObject: UrlObject | string): string; + /** + * The `url.resolve()` method resolves a target URL relative to a base URL in a + * manner similar to that of a web browser resolving an anchor tag. + * + * ```js + * import url from 'node:url'; + * url.resolve('/one/two/three', 'four'); // '/one/two/four' + * url.resolve('http://example.com/', '/one'); // 'http://example.com/one' + * url.resolve('http://example.com/one', '/two'); // 'http://example.com/two' + * ``` + * + * To achieve the same result using the WHATWG URL API: + * + * ```js + * function resolve(from, to) { + * const resolvedUrl = new URL(to, new URL(from, 'resolve://')); + * if (resolvedUrl.protocol === 'resolve:') { + * // `from` is a relative URL. + * const { pathname, search, hash } = resolvedUrl; + * return pathname + search + hash; + * } + * return resolvedUrl.toString(); + * } + * + * resolve('/one/two/three', 'four'); // '/one/two/four' + * resolve('http://example.com/', '/one'); // 'http://example.com/one' + * resolve('http://example.com/one', '/two'); // 'http://example.com/two' + * ``` + * @since v0.1.25 + * @legacy Use the WHATWG URL API instead. + * @param from The base URL to use if `to` is a relative URL. + * @param to The target URL to resolve. + */ + function resolve(from: string, to: string): string; + /** + * Returns the [Punycode](https://tools.ietf.org/html/rfc5891#section-4.4) ASCII serialization of the `domain`. If `domain` is an + * invalid domain, the empty string is returned. + * + * It performs the inverse operation to {@link domainToUnicode}. + * + * ```js + * import url from 'node:url'; + * + * console.log(url.domainToASCII('español.com')); + * // Prints xn--espaol-zwa.com + * console.log(url.domainToASCII('中文.com')); + * // Prints xn--fiq228c.com + * console.log(url.domainToASCII('xn--iñvalid.com')); + * // Prints an empty string + * ``` + * @since v7.4.0, v6.13.0 + */ + function domainToASCII(domain: string): string; + /** + * Returns the Unicode serialization of the `domain`. If `domain` is an invalid + * domain, the empty string is returned. + * + * It performs the inverse operation to {@link domainToASCII}. + * + * ```js + * import url from 'node:url'; + * + * console.log(url.domainToUnicode('xn--espaol-zwa.com')); + * // Prints español.com + * console.log(url.domainToUnicode('xn--fiq228c.com')); + * // Prints 中文.com + * console.log(url.domainToUnicode('xn--iñvalid.com')); + * // Prints an empty string + * ``` + * @since v7.4.0, v6.13.0 + */ + function domainToUnicode(domain: string): string; + /** + * This function ensures the correct decodings of percent-encoded characters as + * well as ensuring a cross-platform valid absolute path string. + * + * ```js + * import { fileURLToPath } from 'node:url'; + * + * const __filename = fileURLToPath(import.meta.url); + * + * new URL('file:///C:/path/').pathname; // Incorrect: /C:/path/ + * fileURLToPath('file:///C:/path/'); // Correct: C:\path\ (Windows) + * + * new URL('file://nas/foo.txt').pathname; // Incorrect: /foo.txt + * fileURLToPath('file://nas/foo.txt'); // Correct: \\nas\foo.txt (Windows) + * + * new URL('file:///你好.txt').pathname; // Incorrect: /%E4%BD%A0%E5%A5%BD.txt + * fileURLToPath('file:///你好.txt'); // Correct: /你好.txt (POSIX) + * + * new URL('file:///hello world').pathname; // Incorrect: /hello%20world + * fileURLToPath('file:///hello world'); // Correct: /hello world (POSIX) + * ``` + * @since v10.12.0 + * @param url The file URL string or URL object to convert to a path. + * @return The fully-resolved platform-specific Node.js file path. + */ + function fileURLToPath(url: string | URL, options?: FileUrlToPathOptions): string; + /** + * Like `url.fileURLToPath(...)` except that instead of returning a string + * representation of the path, a `Buffer` is returned. This conversion is + * helpful when the input URL contains percent-encoded segments that are + * not valid UTF-8 / Unicode sequences. + * @since v24.3.0 + * @param url The file URL string or URL object to convert to a path. + * @returns The fully-resolved platform-specific Node.js file path + * as a `Buffer`. + */ + function fileURLToPathBuffer(url: string | URL, options?: FileUrlToPathOptions): NonSharedBuffer; + /** + * This function ensures that `path` is resolved absolutely, and that the URL + * control characters are correctly encoded when converting into a File URL. + * + * ```js + * import { pathToFileURL } from 'node:url'; + * + * new URL('/foo#1', 'file:'); // Incorrect: file:///foo#1 + * pathToFileURL('/foo#1'); // Correct: file:///foo%231 (POSIX) + * + * new URL('/some/path%.c', 'file:'); // Incorrect: file:///some/path%.c + * pathToFileURL('/some/path%.c'); // Correct: file:///some/path%25.c (POSIX) + * ``` + * @since v10.12.0 + * @param path The path to convert to a File URL. + * @return The file URL object. + */ + function pathToFileURL(path: string, options?: PathToFileUrlOptions): URL; + /** + * This utility function converts a URL object into an ordinary options object as + * expected by the `http.request()` and `https.request()` APIs. + * + * ```js + * import { urlToHttpOptions } from 'node:url'; + * const myURL = new URL('https://a:b@測試?abc#foo'); + * + * console.log(urlToHttpOptions(myURL)); + * /* + * { + * protocol: 'https:', + * hostname: 'xn--g6w251d', + * hash: '#foo', + * search: '?abc', + * pathname: '/', + * path: '/?abc', + * href: 'https://a:b@xn--g6w251d/?abc#foo', + * auth: 'a:b' + * } + * + * ``` + * @since v15.7.0, v14.18.0 + * @param url The `WHATWG URL` object to convert to an options object. + * @return Options object + */ + function urlToHttpOptions(url: URL): ClientRequestArgs; + interface URLFormatOptions { + /** + * `true` if the serialized URL string should include the username and password, `false` otherwise. + * @default true + */ + auth?: boolean | undefined; + /** + * `true` if the serialized URL string should include the fragment, `false` otherwise. + * @default true + */ + fragment?: boolean | undefined; + /** + * `true` if the serialized URL string should include the search query, `false` otherwise. + * @default true + */ + search?: boolean | undefined; + /** + * `true` if Unicode characters appearing in the host component of the URL string should be encoded directly as opposed to + * being Punycode encoded. + * @default false + */ + unicode?: boolean | undefined; + } + // #region web types + type URLPatternInput = string | URLPatternInit; + interface URLPatternComponentResult { + input: string; + groups: Record<string, string | undefined>; + } + interface URLPatternInit { + protocol?: string; + username?: string; + password?: string; + hostname?: string; + port?: string; + pathname?: string; + search?: string; + hash?: string; + baseURL?: string; + } + interface URLPatternOptions { + ignoreCase?: boolean; + } + interface URLPatternResult { + inputs: URLPatternInput[]; + protocol: URLPatternComponentResult; + username: URLPatternComponentResult; + password: URLPatternComponentResult; + hostname: URLPatternComponentResult; + port: URLPatternComponentResult; + pathname: URLPatternComponentResult; + search: URLPatternComponentResult; + hash: URLPatternComponentResult; + } + interface URL { + hash: string; + host: string; + hostname: string; + href: string; + readonly origin: string; + password: string; + pathname: string; + port: string; + protocol: string; + search: string; + readonly searchParams: URLSearchParams; + username: string; + toJSON(): string; + } + var URL: { + prototype: URL; + new(url: string | URL, base?: string | URL): URL; + canParse(input: string | URL, base?: string | URL): boolean; + createObjectURL(blob: Blob): string; + parse(input: string | URL, base?: string | URL): URL | null; + revokeObjectURL(id: string): void; + }; + interface URLPattern { + readonly hasRegExpGroups: boolean; + readonly hash: string; + readonly hostname: string; + readonly password: string; + readonly pathname: string; + readonly port: string; + readonly protocol: string; + readonly search: string; + readonly username: string; + exec(input?: URLPatternInput, baseURL?: string | URL): URLPatternResult | null; + test(input?: URLPatternInput, baseURL?: string | URL): boolean; + } + var URLPattern: { + prototype: URLPattern; + new(input: URLPatternInput, baseURL: string | URL, options?: URLPatternOptions): URLPattern; + new(input?: URLPatternInput, options?: URLPatternOptions): URLPattern; + }; + interface URLSearchParams { + readonly size: number; + append(name: string, value: string): void; + delete(name: string, value?: string): void; + get(name: string): string | null; + getAll(name: string): string[]; + has(name: string, value?: string): boolean; + set(name: string, value: string): void; + sort(): void; + forEach(callbackfn: (value: string, key: string, parent: URLSearchParams) => void, thisArg?: any): void; + [Symbol.iterator](): URLSearchParamsIterator<[string, string]>; + entries(): URLSearchParamsIterator<[string, string]>; + keys(): URLSearchParamsIterator<string>; + values(): URLSearchParamsIterator<string>; + } + var URLSearchParams: { + prototype: URLSearchParams; + new(init?: string[][] | Record<string, string> | string | URLSearchParams): URLSearchParams; + }; + interface URLSearchParamsIterator<T> extends NodeJS.Iterator<T, NodeJS.BuiltinIteratorReturn, unknown> { + [Symbol.iterator](): URLSearchParamsIterator<T>; + } + // #endregion +} +declare module "url" { + export * from "node:url"; +} diff --git a/server/node_modules/@types/node/util.d.ts b/server/node_modules/@types/node/util.d.ts new file mode 100644 index 0000000..4caf804 --- /dev/null +++ b/server/node_modules/@types/node/util.d.ts @@ -0,0 +1,1662 @@ +/** + * The `node:util` module supports the needs of Node.js internal APIs. Many of the + * utilities are useful for application and module developers as well. To access + * it: + * + * ```js + * import util from 'node:util'; + * ``` + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/util.js) + */ +declare module "node:util" { + export * as types from "node:util/types"; + export type InspectStyle = + | "special" + | "number" + | "bigint" + | "boolean" + | "undefined" + | "null" + | "string" + | "symbol" + | "date" + | "name" + | "regexp" + | "module"; + export interface InspectStyles extends Record<InspectStyle, InspectColor | ((value: string) => string)> { + regexp: { + (value: string): string; + colors: InspectColor[]; + }; + } + export type InspectColorModifier = + | "reset" + | "bold" + | "dim" + | "italic" + | "underline" + | "blink" + | "inverse" + | "hidden" + | "strikethrough" + | "doubleunderline"; + export type InspectColorForeground = + | "black" + | "red" + | "green" + | "yellow" + | "blue" + | "magenta" + | "cyan" + | "white" + | "gray" + | "redBright" + | "greenBright" + | "yellowBright" + | "blueBright" + | "magentaBright" + | "cyanBright" + | "whiteBright"; + export type InspectColorBackground = `bg${Capitalize<InspectColorForeground>}`; + export type InspectColor = InspectColorModifier | InspectColorForeground | InspectColorBackground; + export interface InspectColors extends Record<InspectColor, [number, number]> {} + export interface InspectOptions { + /** + * If `true`, object's non-enumerable symbols and properties are included in the formatted result. + * `WeakMap` and `WeakSet` entries are also included as well as user defined prototype properties (excluding method properties). + * @default false + */ + showHidden?: boolean | undefined; + /** + * Specifies the number of times to recurse while formatting object. + * This is useful for inspecting large objects. + * To recurse up to the maximum call stack size pass `Infinity` or `null`. + * @default 2 + */ + depth?: number | null | undefined; + /** + * If `true`, the output is styled with ANSI color codes. Colors are customizable. + */ + colors?: boolean | undefined; + /** + * If `false`, `[util.inspect.custom](depth, opts, inspect)` functions are not invoked. + * @default true + */ + customInspect?: boolean | undefined; + /** + * If `true`, `Proxy` inspection includes the target and handler objects. + * @default false + */ + showProxy?: boolean | undefined; + /** + * Specifies the maximum number of `Array`, `TypedArray`, `WeakMap`, and `WeakSet` elements + * to include when formatting. Set to `null` or `Infinity` to show all elements. + * Set to `0` or negative to show no elements. + * @default 100 + */ + maxArrayLength?: number | null | undefined; + /** + * Specifies the maximum number of characters to + * include when formatting. Set to `null` or `Infinity` to show all elements. + * Set to `0` or negative to show no characters. + * @default 10000 + */ + maxStringLength?: number | null | undefined; + /** + * The length at which input values are split across multiple lines. + * Set to `Infinity` to format the input as a single line + * (in combination with `compact` set to `true` or any number >= `1`). + * @default 80 + */ + breakLength?: number | undefined; + /** + * Setting this to `false` causes each object key + * to be displayed on a new line. It will also add new lines to text that is + * longer than `breakLength`. If set to a number, the most `n` inner elements + * are united on a single line as long as all properties fit into + * `breakLength`. Short array elements are also grouped together. Note that no + * text will be reduced below 16 characters, no matter the `breakLength` size. + * For more information, see the example below. + * @default true + */ + compact?: boolean | number | undefined; + /** + * If set to `true` or a function, all properties of an object, and `Set` and `Map` + * entries are sorted in the resulting string. + * If set to `true` the default sort is used. + * If set to a function, it is used as a compare function. + */ + sorted?: boolean | ((a: string, b: string) => number) | undefined; + /** + * If set to `true`, getters are going to be + * inspected as well. If set to `'get'` only getters without setter are going + * to be inspected. If set to `'set'` only getters having a corresponding + * setter are going to be inspected. This might cause side effects depending on + * the getter function. + * @default false + */ + getters?: "get" | "set" | boolean | undefined; + /** + * If set to `true`, an underscore is used to separate every three digits in all bigints and numbers. + * @default false + */ + numericSeparator?: boolean | undefined; + } + export interface InspectContext extends Required<InspectOptions> { + stylize(text: string, styleType: InspectStyle): string; + } + import _inspect = inspect; + export interface Inspectable { + [inspect.custom](depth: number, options: InspectContext, inspect: typeof _inspect): any; + } + // TODO: Remove these in a future major + /** @deprecated Use `InspectStyle` instead. */ + export type Style = Exclude<InspectStyle, "name">; + /** @deprecated Use the `Inspectable` interface instead. */ + export type CustomInspectFunction = (depth: number, options: InspectContext) => any; + /** @deprecated Use `InspectContext` instead. */ + export interface InspectOptionsStylized extends InspectContext {} + /** @deprecated Use `InspectColorModifier` instead. */ + export type Modifiers = InspectColorModifier; + /** @deprecated Use `InspectColorForeground` instead. */ + export type ForegroundColors = InspectColorForeground; + /** @deprecated Use `InspectColorBackground` instead. */ + export type BackgroundColors = InspectColorBackground; + export interface CallSiteObject { + /** + * Returns the name of the function associated with this call site. + */ + functionName: string; + /** + * Returns the name of the resource that contains the script for the + * function for this call site. + */ + scriptName: string; + /** + * Returns the unique id of the script, as in Chrome DevTools protocol + * [`Runtime.ScriptId`](https://chromedevtools.github.io/devtools-protocol/1-3/Runtime/#type-ScriptId). + * @since v22.14.0 + */ + scriptId: string; + /** + * Returns the number, 1-based, of the line for the associate function call. + */ + lineNumber: number; + /** + * Returns the 1-based column offset on the line for the associated function call. + */ + columnNumber: number; + } + export type DiffEntry = [operation: -1 | 0 | 1, value: string]; + /** + * `util.diff()` compares two string or array values and returns an array of difference entries. + * It uses the Myers diff algorithm to compute minimal differences, which is the same algorithm + * used internally by assertion error messages. + * + * If the values are equal, an empty array is returned. + * + * ```js + * const { diff } = require('node:util'); + * + * // Comparing strings + * const actualString = '12345678'; + * const expectedString = '12!!5!7!'; + * console.log(diff(actualString, expectedString)); + * // [ + * // [0, '1'], + * // [0, '2'], + * // [1, '3'], + * // [1, '4'], + * // [-1, '!'], + * // [-1, '!'], + * // [0, '5'], + * // [1, '6'], + * // [-1, '!'], + * // [0, '7'], + * // [1, '8'], + * // [-1, '!'], + * // ] + * // Comparing arrays + * const actualArray = ['1', '2', '3']; + * const expectedArray = ['1', '3', '4']; + * console.log(diff(actualArray, expectedArray)); + * // [ + * // [0, '1'], + * // [1, '2'], + * // [0, '3'], + * // [-1, '4'], + * // ] + * // Equal values return empty array + * console.log(diff('same', 'same')); + * // [] + * ``` + * @since v22.15.0 + * @experimental + * @param actual The first value to compare + * @param expected The second value to compare + * @returns An array of difference entries. Each entry is an array with two elements: + * * Index 0: `number` Operation code: `-1` for delete, `0` for no-op/unchanged, `1` for insert + * * Index 1: `string` The value associated with the operation + */ + export function diff(actual: string | readonly string[], expected: string | readonly string[]): DiffEntry[]; + /** + * The `util.format()` method returns a formatted string using the first argument + * as a `printf`-like format string which can contain zero or more format + * specifiers. Each specifier is replaced with the converted value from the + * corresponding argument. Supported specifiers are: + * + * If a specifier does not have a corresponding argument, it is not replaced: + * + * ```js + * util.format('%s:%s', 'foo'); + * // Returns: 'foo:%s' + * ``` + * + * Values that are not part of the format string are formatted using `util.inspect()` if their type is not `string`. + * + * If there are more arguments passed to the `util.format()` method than the + * number of specifiers, the extra arguments are concatenated to the returned + * string, separated by spaces: + * + * ```js + * util.format('%s:%s', 'foo', 'bar', 'baz'); + * // Returns: 'foo:bar baz' + * ``` + * + * If the first argument does not contain a valid format specifier, `util.format()` returns a string that is the concatenation of all arguments separated by spaces: + * + * ```js + * util.format(1, 2, 3); + * // Returns: '1 2 3' + * ``` + * + * If only one argument is passed to `util.format()`, it is returned as it is + * without any formatting: + * + * ```js + * util.format('%% %s'); + * // Returns: '%% %s' + * ``` + * + * `util.format()` is a synchronous method that is intended as a debugging tool. + * Some input values can have a significant performance overhead that can block the + * event loop. Use this function with care and never in a hot code path. + * @since v0.5.3 + * @param format A `printf`-like format string. + */ + export function format(format?: any, ...param: any[]): string; + /** + * This function is identical to {@link format}, except in that it takes + * an `inspectOptions` argument which specifies options that are passed along to {@link inspect}. + * + * ```js + * util.formatWithOptions({ colors: true }, 'See object %O', { foo: 42 }); + * // Returns 'See object { foo: 42 }', where `42` is colored as a number + * // when printed to a terminal. + * ``` + * @since v10.0.0 + */ + export function formatWithOptions(inspectOptions: InspectOptions, format?: any, ...param: any[]): string; + export interface GetCallSitesOptions { + /** + * Reconstruct the original location in the stacktrace from the source-map. + * Enabled by default with the flag `--enable-source-maps`. + */ + sourceMap?: boolean | undefined; + } + /** + * Returns an array of call site objects containing the stack of + * the caller function. + * + * ```js + * import { getCallSites } from 'node:util'; + * + * function exampleFunction() { + * const callSites = getCallSites(); + * + * console.log('Call Sites:'); + * callSites.forEach((callSite, index) => { + * console.log(`CallSite ${index + 1}:`); + * console.log(`Function Name: ${callSite.functionName}`); + * console.log(`Script Name: ${callSite.scriptName}`); + * console.log(`Line Number: ${callSite.lineNumber}`); + * console.log(`Column Number: ${callSite.column}`); + * }); + * // CallSite 1: + * // Function Name: exampleFunction + * // Script Name: /home/example.js + * // Line Number: 5 + * // Column Number: 26 + * + * // CallSite 2: + * // Function Name: anotherFunction + * // Script Name: /home/example.js + * // Line Number: 22 + * // Column Number: 3 + * + * // ... + * } + * + * // A function to simulate another stack layer + * function anotherFunction() { + * exampleFunction(); + * } + * + * anotherFunction(); + * ``` + * + * It is possible to reconstruct the original locations by setting the option `sourceMap` to `true`. + * If the source map is not available, the original location will be the same as the current location. + * When the `--enable-source-maps` flag is enabled, for example when using `--experimental-transform-types`, + * `sourceMap` will be true by default. + * + * ```ts + * import { getCallSites } from 'node:util'; + * + * interface Foo { + * foo: string; + * } + * + * const callSites = getCallSites({ sourceMap: true }); + * + * // With sourceMap: + * // Function Name: '' + * // Script Name: example.js + * // Line Number: 7 + * // Column Number: 26 + * + * // Without sourceMap: + * // Function Name: '' + * // Script Name: example.js + * // Line Number: 2 + * // Column Number: 26 + * ``` + * @param frameCount Number of frames to capture as call site objects. + * **Default:** `10`. Allowable range is between 1 and 200. + * @return An array of call site objects + * @since v22.9.0 + */ + export function getCallSites(frameCount?: number, options?: GetCallSitesOptions): CallSiteObject[]; + export function getCallSites(options: GetCallSitesOptions): CallSiteObject[]; + /** + * Returns the string name for a numeric error code that comes from a Node.js API. + * The mapping between error codes and error names is platform-dependent. + * See `Common System Errors` for the names of common errors. + * + * ```js + * fs.access('file/that/does/not/exist', (err) => { + * const name = util.getSystemErrorName(err.errno); + * console.error(name); // ENOENT + * }); + * ``` + * @since v9.7.0 + */ + export function getSystemErrorName(err: number): string; + /** + * Enable or disable printing a stack trace on `SIGINT`. The API is only available on the main thread. + * @since 24.6.0 + */ + export function setTraceSigInt(enable: boolean): void; + /** + * Returns a Map of all system error codes available from the Node.js API. + * The mapping between error codes and error names is platform-dependent. + * See `Common System Errors` for the names of common errors. + * + * ```js + * fs.access('file/that/does/not/exist', (err) => { + * const errorMap = util.getSystemErrorMap(); + * const name = errorMap.get(err.errno); + * console.error(name); // ENOENT + * }); + * ``` + * @since v16.0.0, v14.17.0 + */ + export function getSystemErrorMap(): Map<number, [string, string]>; + /** + * Returns the string message for a numeric error code that comes from a Node.js + * API. + * The mapping between error codes and string messages is platform-dependent. + * + * ```js + * fs.access('file/that/does/not/exist', (err) => { + * const message = util.getSystemErrorMessage(err.errno); + * console.error(message); // no such file or directory + * }); + * ``` + * @since v22.12.0 + */ + export function getSystemErrorMessage(err: number): string; + /** + * Returns the `string` after replacing any surrogate code points + * (or equivalently, any unpaired surrogate code units) with the + * Unicode "replacement character" U+FFFD. + * @since v16.8.0, v14.18.0 + */ + export function toUSVString(string: string): string; + /** + * Creates and returns an `AbortController` instance whose `AbortSignal` is marked + * as transferable and can be used with `structuredClone()` or `postMessage()`. + * @since v18.11.0 + * @returns A transferable AbortController + */ + export function transferableAbortController(): AbortController; + /** + * Marks the given `AbortSignal` as transferable so that it can be used with`structuredClone()` and `postMessage()`. + * + * ```js + * const signal = transferableAbortSignal(AbortSignal.timeout(100)); + * const channel = new MessageChannel(); + * channel.port2.postMessage(signal, [signal]); + * ``` + * @since v18.11.0 + * @param signal The AbortSignal + * @returns The same AbortSignal + */ + export function transferableAbortSignal(signal: AbortSignal): AbortSignal; + /** + * Listens to abort event on the provided `signal` and returns a promise that resolves when the `signal` is aborted. + * If `resource` is provided, it weakly references the operation's associated object, + * so if `resource` is garbage collected before the `signal` aborts, + * then returned promise shall remain pending. + * This prevents memory leaks in long-running or non-cancelable operations. + * + * ```js + * import { aborted } from 'node:util'; + * + * // Obtain an object with an abortable signal, like a custom resource or operation. + * const dependent = obtainSomethingAbortable(); + * + * // Pass `dependent` as the resource, indicating the promise should only resolve + * // if `dependent` is still in memory when the signal is aborted. + * aborted(dependent.signal, dependent).then(() => { + * // This code runs when `dependent` is aborted. + * console.log('Dependent resource was aborted.'); + * }); + * + * // Simulate an event that triggers the abort. + * dependent.on('event', () => { + * dependent.abort(); // This will cause the `aborted` promise to resolve. + * }); + * ``` + * @since v19.7.0 + * @param resource Any non-null object tied to the abortable operation and held weakly. + * If `resource` is garbage collected before the `signal` aborts, the promise remains pending, + * allowing Node.js to stop tracking it. + * This helps prevent memory leaks in long-running or non-cancelable operations. + */ + export function aborted(signal: AbortSignal, resource: any): Promise<void>; + /** + * The `util.inspect()` method returns a string representation of `object` that is + * intended for debugging. The output of `util.inspect` may change at any time + * and should not be depended upon programmatically. Additional `options` may be + * passed that alter the result. + * `util.inspect()` will use the constructor's name and/or `Symbol.toStringTag` + * property to make an identifiable tag for an inspected value. + * + * ```js + * class Foo { + * get [Symbol.toStringTag]() { + * return 'bar'; + * } + * } + * + * class Bar {} + * + * const baz = Object.create(null, { [Symbol.toStringTag]: { value: 'foo' } }); + * + * util.inspect(new Foo()); // 'Foo [bar] {}' + * util.inspect(new Bar()); // 'Bar {}' + * util.inspect(baz); // '[foo] {}' + * ``` + * + * Circular references point to their anchor by using a reference index: + * + * ```js + * import { inspect } from 'node:util'; + * + * const obj = {}; + * obj.a = [obj]; + * obj.b = {}; + * obj.b.inner = obj.b; + * obj.b.obj = obj; + * + * console.log(inspect(obj)); + * // <ref *1> { + * // a: [ [Circular *1] ], + * // b: <ref *2> { inner: [Circular *2], obj: [Circular *1] } + * // } + * ``` + * + * The following example inspects all properties of the `util` object: + * + * ```js + * import util from 'node:util'; + * + * console.log(util.inspect(util, { showHidden: true, depth: null })); + * ``` + * + * The following example highlights the effect of the `compact` option: + * + * ```js + * import { inspect } from 'node:util'; + * + * const o = { + * a: [1, 2, [[ + * 'Lorem ipsum dolor sit amet,\nconsectetur adipiscing elit, sed do ' + + * 'eiusmod \ntempor incididunt ut labore et dolore magna aliqua.', + * 'test', + * 'foo']], 4], + * b: new Map([['za', 1], ['zb', 'test']]), + * }; + * console.log(inspect(o, { compact: true, depth: 5, breakLength: 80 })); + * + * // { a: + * // [ 1, + * // 2, + * // [ [ 'Lorem ipsum dolor sit amet,\nconsectetur [...]', // A long line + * // 'test', + * // 'foo' ] ], + * // 4 ], + * // b: Map(2) { 'za' => 1, 'zb' => 'test' } } + * + * // Setting `compact` to false or an integer creates more reader friendly output. + * console.log(inspect(o, { compact: false, depth: 5, breakLength: 80 })); + * + * // { + * // a: [ + * // 1, + * // 2, + * // [ + * // [ + * // 'Lorem ipsum dolor sit amet,\n' + + * // 'consectetur adipiscing elit, sed do eiusmod \n' + + * // 'tempor incididunt ut labore et dolore magna aliqua.', + * // 'test', + * // 'foo' + * // ] + * // ], + * // 4 + * // ], + * // b: Map(2) { + * // 'za' => 1, + * // 'zb' => 'test' + * // } + * // } + * + * // Setting `breakLength` to e.g. 150 will print the "Lorem ipsum" text in a + * // single line. + * ``` + * + * The `showHidden` option allows `WeakMap` and `WeakSet` entries to be + * inspected. If there are more entries than `maxArrayLength`, there is no + * guarantee which entries are displayed. That means retrieving the same + * `WeakSet` entries twice may result in different output. Furthermore, entries + * with no remaining strong references may be garbage collected at any time. + * + * ```js + * import { inspect } from 'node:util'; + * + * const obj = { a: 1 }; + * const obj2 = { b: 2 }; + * const weakSet = new WeakSet([obj, obj2]); + * + * console.log(inspect(weakSet, { showHidden: true })); + * // WeakSet { { a: 1 }, { b: 2 } } + * ``` + * + * The `sorted` option ensures that an object's property insertion order does not + * impact the result of `util.inspect()`. + * + * ```js + * import { inspect } from 'node:util'; + * import assert from 'node:assert'; + * + * const o1 = { + * b: [2, 3, 1], + * a: '`a` comes before `b`', + * c: new Set([2, 3, 1]), + * }; + * console.log(inspect(o1, { sorted: true })); + * // { a: '`a` comes before `b`', b: [ 2, 3, 1 ], c: Set(3) { 1, 2, 3 } } + * console.log(inspect(o1, { sorted: (a, b) => b.localeCompare(a) })); + * // { c: Set(3) { 3, 2, 1 }, b: [ 2, 3, 1 ], a: '`a` comes before `b`' } + * + * const o2 = { + * c: new Set([2, 1, 3]), + * a: '`a` comes before `b`', + * b: [2, 3, 1], + * }; + * assert.strict.equal( + * inspect(o1, { sorted: true }), + * inspect(o2, { sorted: true }), + * ); + * ``` + * + * The `numericSeparator` option adds an underscore every three digits to all + * numbers. + * + * ```js + * import { inspect } from 'node:util'; + * + * const thousand = 1000; + * const million = 1000000; + * const bigNumber = 123456789n; + * const bigDecimal = 1234.12345; + * + * console.log(inspect(thousand, { numericSeparator: true })); + * // 1_000 + * console.log(inspect(million, { numericSeparator: true })); + * // 1_000_000 + * console.log(inspect(bigNumber, { numericSeparator: true })); + * // 123_456_789n + * console.log(inspect(bigDecimal, { numericSeparator: true })); + * // 1_234.123_45 + * ``` + * + * `util.inspect()` is a synchronous method intended for debugging. Its maximum + * output length is approximately 128 MiB. Inputs that result in longer output will + * be truncated. + * @since v0.3.0 + * @param object Any JavaScript primitive or `Object`. + * @return The representation of `object`. + */ + export function inspect(object: any, showHidden?: boolean, depth?: number | null, color?: boolean): string; + export function inspect(object: any, options?: InspectOptions): string; + export namespace inspect { + const custom: unique symbol; + let colors: InspectColors; + let styles: InspectStyles; + let defaultOptions: InspectOptions; + let replDefaults: InspectOptions; + } + /** + * Alias for [`Array.isArray()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray). + * + * Returns `true` if the given `object` is an `Array`. Otherwise, returns `false`. + * + * ```js + * import util from 'node:util'; + * + * util.isArray([]); + * // Returns: true + * util.isArray(new Array()); + * // Returns: true + * util.isArray({}); + * // Returns: false + * ``` + * @since v0.6.0 + * @deprecated Since v4.0.0 - Use `isArray` instead. + */ + export function isArray(object: unknown): object is unknown[]; + /** + * Usage of `util.inherits()` is discouraged. Please use the ES6 `class` and + * `extends` keywords to get language level inheritance support. Also note + * that the two styles are [semantically incompatible](https://github.com/nodejs/node/issues/4179). + * + * Inherit the prototype methods from one + * [constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor) into another. The + * prototype of `constructor` will be set to a new object created from + * `superConstructor`. + * + * This mainly adds some input validation on top of + * `Object.setPrototypeOf(constructor.prototype, superConstructor.prototype)`. + * As an additional convenience, `superConstructor` will be accessible + * through the `constructor.super_` property. + * + * ```js + * const util = require('node:util'); + * const EventEmitter = require('node:events'); + * + * function MyStream() { + * EventEmitter.call(this); + * } + * + * util.inherits(MyStream, EventEmitter); + * + * MyStream.prototype.write = function(data) { + * this.emit('data', data); + * }; + * + * const stream = new MyStream(); + * + * console.log(stream instanceof EventEmitter); // true + * console.log(MyStream.super_ === EventEmitter); // true + * + * stream.on('data', (data) => { + * console.log(`Received data: "${data}"`); + * }); + * stream.write('It works!'); // Received data: "It works!" + * ``` + * + * ES6 example using `class` and `extends`: + * + * ```js + * import EventEmitter from 'node:events'; + * + * class MyStream extends EventEmitter { + * write(data) { + * this.emit('data', data); + * } + * } + * + * const stream = new MyStream(); + * + * stream.on('data', (data) => { + * console.log(`Received data: "${data}"`); + * }); + * stream.write('With ES6'); + * ``` + * @since v0.3.0 + * @legacy Use ES2015 class syntax and `extends` keyword instead. + */ + export function inherits(constructor: unknown, superConstructor: unknown): void; + export type DebugLoggerFunction = (msg: string, ...param: unknown[]) => void; + export interface DebugLogger extends DebugLoggerFunction { + /** + * The `util.debuglog().enabled` getter is used to create a test that can be used + * in conditionals based on the existence of the `NODE_DEBUG` environment variable. + * If the `section` name appears within the value of that environment variable, + * then the returned value will be `true`. If not, then the returned value will be + * `false`. + * + * ```js + * import { debuglog } from 'node:util'; + * const enabled = debuglog('foo').enabled; + * if (enabled) { + * console.log('hello from foo [%d]', 123); + * } + * ``` + * + * If this program is run with `NODE_DEBUG=foo` in the environment, then it will + * output something like: + * + * ```console + * hello from foo [123] + * ``` + */ + enabled: boolean; + } + /** + * The `util.debuglog()` method is used to create a function that conditionally + * writes debug messages to `stderr` based on the existence of the `NODE_DEBUG` + * environment variable. If the `section` name appears within the value of that + * environment variable, then the returned function operates similar to + * `console.error()`. If not, then the returned function is a no-op. + * + * ```js + * import { debuglog } from 'node:util'; + * const log = debuglog('foo'); + * + * log('hello from foo [%d]', 123); + * ``` + * + * If this program is run with `NODE_DEBUG=foo` in the environment, then + * it will output something like: + * + * ```console + * FOO 3245: hello from foo [123] + * ``` + * + * where `3245` is the process id. If it is not run with that + * environment variable set, then it will not print anything. + * + * The `section` supports wildcard also: + * + * ```js + * import { debuglog } from 'node:util'; + * const log = debuglog('foo'); + * + * log('hi there, it\'s foo-bar [%d]', 2333); + * ``` + * + * if it is run with `NODE_DEBUG=foo*` in the environment, then it will output + * something like: + * + * ```console + * FOO-BAR 3257: hi there, it's foo-bar [2333] + * ``` + * + * Multiple comma-separated `section` names may be specified in the `NODE_DEBUG` + * environment variable: `NODE_DEBUG=fs,net,tls`. + * + * The optional `callback` argument can be used to replace the logging function + * with a different function that doesn't have any initialization or + * unnecessary wrapping. + * + * ```js + * import { debuglog } from 'node:util'; + * let log = debuglog('internals', (debug) => { + * // Replace with a logging function that optimizes out + * // testing if the section is enabled + * log = debug; + * }); + * ``` + * @since v0.11.3 + * @param section A string identifying the portion of the application for which the `debuglog` function is being created. + * @param callback A callback invoked the first time the logging function is called with a function argument that is a more optimized logging function. + * @return The logging function + */ + export function debuglog(section: string, callback?: (fn: DebugLoggerFunction) => void): DebugLogger; + export { debuglog as debug }; + export interface DeprecateOptions { + /** + * When false do not change the prototype of object + * while emitting the deprecation warning. + * @since v25.2.0 + * @default true + */ + modifyPrototype?: boolean | undefined; + } + /** + * The `util.deprecate()` method wraps `fn` (which may be a function or class) in + * such a way that it is marked as deprecated. + * + * ```js + * import { deprecate } from 'node:util'; + * + * export const obsoleteFunction = deprecate(() => { + * // Do something here. + * }, 'obsoleteFunction() is deprecated. Use newShinyFunction() instead.'); + * ``` + * + * When called, `util.deprecate()` will return a function that will emit a + * `DeprecationWarning` using the `'warning'` event. The warning will + * be emitted and printed to `stderr` the first time the returned function is + * called. After the warning is emitted, the wrapped function is called without + * emitting a warning. + * + * If the same optional `code` is supplied in multiple calls to `util.deprecate()`, + * the warning will be emitted only once for that `code`. + * + * ```js + * import { deprecate } from 'node:util'; + * + * const fn1 = deprecate( + * () => 'a value', + * 'deprecation message', + * 'DEP0001', + * ); + * const fn2 = deprecate( + * () => 'a different value', + * 'other dep message', + * 'DEP0001', + * ); + * fn1(); // Emits a deprecation warning with code DEP0001 + * fn2(); // Does not emit a deprecation warning because it has the same code + * ``` + * + * If either the `--no-deprecation` or `--no-warnings` command-line flags are + * used, or if the `process.noDeprecation` property is set to `true` _prior_ to + * the first deprecation warning, the `util.deprecate()` method does nothing. + * + * If the `--trace-deprecation` or `--trace-warnings` command-line flags are set, + * or the `process.traceDeprecation` property is set to `true`, a warning and a + * stack trace are printed to `stderr` the first time the deprecated function is + * called. + * + * If the `--throw-deprecation` command-line flag is set, or the + * `process.throwDeprecation` property is set to `true`, then an exception will be + * thrown when the deprecated function is called. + * + * The `--throw-deprecation` command-line flag and `process.throwDeprecation` + * property take precedence over `--trace-deprecation` and + * `process.traceDeprecation`. + * @since v0.8.0 + * @param fn The function that is being deprecated. + * @param msg A warning message to display when the deprecated function is invoked. + * @param code A deprecation code. See the `list of deprecated APIs` for a list of codes. + * @return The deprecated function wrapped to emit a warning. + */ + export function deprecate<T extends Function>(fn: T, msg: string, code?: string, options?: DeprecateOptions): T; + export interface IsDeepStrictEqualOptions { + /** + * If `true`, prototype and constructor + * comparison is skipped during deep strict equality check. + * @since v24.9.0 + * @default false + */ + skipPrototype?: boolean | undefined; + } + /** + * Returns `true` if there is deep strict equality between `val1` and `val2`. + * Otherwise, returns `false`. + * + * See `assert.deepStrictEqual()` for more information about deep strict + * equality. + * @since v9.0.0 + */ + export function isDeepStrictEqual(val1: unknown, val2: unknown, options?: IsDeepStrictEqualOptions): boolean; + /** + * Returns `str` with any ANSI escape codes removed. + * + * ```js + * console.log(util.stripVTControlCharacters('\u001B[4mvalue\u001B[0m')); + * // Prints "value" + * ``` + * @since v16.11.0 + */ + export function stripVTControlCharacters(str: string): string; + /** + * Takes an `async` function (or a function that returns a `Promise`) and returns a + * function following the error-first callback style, i.e. taking + * an `(err, value) => ...` callback as the last argument. In the callback, the + * first argument will be the rejection reason (or `null` if the `Promise` + * resolved), and the second argument will be the resolved value. + * + * ```js + * import { callbackify } from 'node:util'; + * + * async function fn() { + * return 'hello world'; + * } + * const callbackFunction = callbackify(fn); + * + * callbackFunction((err, ret) => { + * if (err) throw err; + * console.log(ret); + * }); + * ``` + * + * Will print: + * + * ```text + * hello world + * ``` + * + * The callback is executed asynchronously, and will have a limited stack trace. + * If the callback throws, the process will emit an `'uncaughtException'` + * event, and if not handled will exit. + * + * Since `null` has a special meaning as the first argument to a callback, if a + * wrapped function rejects a `Promise` with a falsy value as a reason, the value + * is wrapped in an `Error` with the original value stored in a field named + * `reason`. + * + * ```js + * function fn() { + * return Promise.reject(null); + * } + * const callbackFunction = util.callbackify(fn); + * + * callbackFunction((err, ret) => { + * // When the Promise was rejected with `null` it is wrapped with an Error and + * // the original value is stored in `reason`. + * err && Object.hasOwn(err, 'reason') && err.reason === null; // true + * }); + * ``` + * @since v8.2.0 + * @param fn An `async` function + * @return a callback style function + */ + export function callbackify(fn: () => Promise<void>): (callback: (err: NodeJS.ErrnoException) => void) => void; + export function callbackify<TResult>( + fn: () => Promise<TResult>, + ): (callback: (err: NodeJS.ErrnoException, result: TResult) => void) => void; + export function callbackify<T1>( + fn: (arg1: T1) => Promise<void>, + ): (arg1: T1, callback: (err: NodeJS.ErrnoException) => void) => void; + export function callbackify<T1, TResult>( + fn: (arg1: T1) => Promise<TResult>, + ): (arg1: T1, callback: (err: NodeJS.ErrnoException, result: TResult) => void) => void; + export function callbackify<T1, T2>( + fn: (arg1: T1, arg2: T2) => Promise<void>, + ): (arg1: T1, arg2: T2, callback: (err: NodeJS.ErrnoException) => void) => void; + export function callbackify<T1, T2, TResult>( + fn: (arg1: T1, arg2: T2) => Promise<TResult>, + ): (arg1: T1, arg2: T2, callback: (err: NodeJS.ErrnoException | null, result: TResult) => void) => void; + export function callbackify<T1, T2, T3>( + fn: (arg1: T1, arg2: T2, arg3: T3) => Promise<void>, + ): (arg1: T1, arg2: T2, arg3: T3, callback: (err: NodeJS.ErrnoException) => void) => void; + export function callbackify<T1, T2, T3, TResult>( + fn: (arg1: T1, arg2: T2, arg3: T3) => Promise<TResult>, + ): (arg1: T1, arg2: T2, arg3: T3, callback: (err: NodeJS.ErrnoException | null, result: TResult) => void) => void; + export function callbackify<T1, T2, T3, T4>( + fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4) => Promise<void>, + ): (arg1: T1, arg2: T2, arg3: T3, arg4: T4, callback: (err: NodeJS.ErrnoException) => void) => void; + export function callbackify<T1, T2, T3, T4, TResult>( + fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4) => Promise<TResult>, + ): ( + arg1: T1, + arg2: T2, + arg3: T3, + arg4: T4, + callback: (err: NodeJS.ErrnoException | null, result: TResult) => void, + ) => void; + export function callbackify<T1, T2, T3, T4, T5>( + fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5) => Promise<void>, + ): (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5, callback: (err: NodeJS.ErrnoException) => void) => void; + export function callbackify<T1, T2, T3, T4, T5, TResult>( + fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5) => Promise<TResult>, + ): ( + arg1: T1, + arg2: T2, + arg3: T3, + arg4: T4, + arg5: T5, + callback: (err: NodeJS.ErrnoException | null, result: TResult) => void, + ) => void; + export function callbackify<T1, T2, T3, T4, T5, T6>( + fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5, arg6: T6) => Promise<void>, + ): ( + arg1: T1, + arg2: T2, + arg3: T3, + arg4: T4, + arg5: T5, + arg6: T6, + callback: (err: NodeJS.ErrnoException) => void, + ) => void; + export function callbackify<T1, T2, T3, T4, T5, T6, TResult>( + fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5, arg6: T6) => Promise<TResult>, + ): ( + arg1: T1, + arg2: T2, + arg3: T3, + arg4: T4, + arg5: T5, + arg6: T6, + callback: (err: NodeJS.ErrnoException | null, result: TResult) => void, + ) => void; + export interface CustomPromisifyLegacy<TCustom extends Function> extends Function { + __promisify__: TCustom; + } + export interface CustomPromisifySymbol<TCustom extends Function> extends Function { + [promisify.custom]: TCustom; + } + export type CustomPromisify<TCustom extends Function> = + | CustomPromisifySymbol<TCustom> + | CustomPromisifyLegacy<TCustom>; + /** + * Takes a function following the common error-first callback style, i.e. taking + * an `(err, value) => ...` callback as the last argument, and returns a version + * that returns promises. + * + * ```js + * import { promisify } from 'node:util'; + * import { stat } from 'node:fs'; + * + * const promisifiedStat = promisify(stat); + * promisifiedStat('.').then((stats) => { + * // Do something with `stats` + * }).catch((error) => { + * // Handle the error. + * }); + * ``` + * + * Or, equivalently using `async function`s: + * + * ```js + * import { promisify } from 'node:util'; + * import { stat } from 'node:fs'; + * + * const promisifiedStat = promisify(stat); + * + * async function callStat() { + * const stats = await promisifiedStat('.'); + * console.log(`This directory is owned by ${stats.uid}`); + * } + * + * callStat(); + * ``` + * + * If there is an `original[util.promisify.custom]` property present, `promisify` + * will return its value, see [Custom promisified functions](https://nodejs.org/docs/latest-v25.x/api/util.html#custom-promisified-functions). + * + * `promisify()` assumes that `original` is a function taking a callback as its + * final argument in all cases. If `original` is not a function, `promisify()` + * will throw an error. If `original` is a function but its last argument is not + * an error-first callback, it will still be passed an error-first + * callback as its last argument. + * + * Using `promisify()` on class methods or other methods that use `this` may not + * work as expected unless handled specially: + * + * ```js + * import { promisify } from 'node:util'; + * + * class Foo { + * constructor() { + * this.a = 42; + * } + * + * bar(callback) { + * callback(null, this.a); + * } + * } + * + * const foo = new Foo(); + * + * const naiveBar = promisify(foo.bar); + * // TypeError: Cannot read properties of undefined (reading 'a') + * // naiveBar().then(a => console.log(a)); + * + * naiveBar.call(foo).then((a) => console.log(a)); // '42' + * + * const bindBar = naiveBar.bind(foo); + * bindBar().then((a) => console.log(a)); // '42' + * ``` + * @since v8.0.0 + */ + export function promisify<TCustom extends Function>(fn: CustomPromisify<TCustom>): TCustom; + export function promisify<TResult>( + fn: (callback: (err: any, result: TResult) => void) => void, + ): () => Promise<TResult>; + export function promisify(fn: (callback: (err?: any) => void) => void): () => Promise<void>; + export function promisify<T1, TResult>( + fn: (arg1: T1, callback: (err: any, result: TResult) => void) => void, + ): (arg1: T1) => Promise<TResult>; + export function promisify<T1>(fn: (arg1: T1, callback: (err?: any) => void) => void): (arg1: T1) => Promise<void>; + export function promisify<T1, T2, TResult>( + fn: (arg1: T1, arg2: T2, callback: (err: any, result: TResult) => void) => void, + ): (arg1: T1, arg2: T2) => Promise<TResult>; + export function promisify<T1, T2>( + fn: (arg1: T1, arg2: T2, callback: (err?: any) => void) => void, + ): (arg1: T1, arg2: T2) => Promise<void>; + export function promisify<T1, T2, T3, TResult>( + fn: (arg1: T1, arg2: T2, arg3: T3, callback: (err: any, result: TResult) => void) => void, + ): (arg1: T1, arg2: T2, arg3: T3) => Promise<TResult>; + export function promisify<T1, T2, T3>( + fn: (arg1: T1, arg2: T2, arg3: T3, callback: (err?: any) => void) => void, + ): (arg1: T1, arg2: T2, arg3: T3) => Promise<void>; + export function promisify<T1, T2, T3, T4, TResult>( + fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, callback: (err: any, result: TResult) => void) => void, + ): (arg1: T1, arg2: T2, arg3: T3, arg4: T4) => Promise<TResult>; + export function promisify<T1, T2, T3, T4>( + fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, callback: (err?: any) => void) => void, + ): (arg1: T1, arg2: T2, arg3: T3, arg4: T4) => Promise<void>; + export function promisify<T1, T2, T3, T4, T5, TResult>( + fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5, callback: (err: any, result: TResult) => void) => void, + ): (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5) => Promise<TResult>; + export function promisify<T1, T2, T3, T4, T5>( + fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5, callback: (err?: any) => void) => void, + ): (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5) => Promise<void>; + export function promisify(fn: Function): Function; + export namespace promisify { + /** + * That can be used to declare custom promisified variants of functions. + */ + const custom: unique symbol; + } + /** + * Stability: 1.1 - Active development + * Given an example `.env` file: + * + * ```js + * import { parseEnv } from 'node:util'; + * + * parseEnv('HELLO=world\nHELLO=oh my\n'); + * // Returns: { HELLO: 'oh my' } + * ``` + * @param content The raw contents of a `.env` file. + * @since v20.12.0 + */ + export function parseEnv(content: string): NodeJS.Dict<string>; + export interface StyleTextOptions { + /** + * When true, `stream` is checked to see if it can handle colors. + * @default true + */ + validateStream?: boolean | undefined; + /** + * A stream that will be validated if it can be colored. + * @default process.stdout + */ + stream?: NodeJS.WritableStream | undefined; + } + /** + * This function returns a formatted text considering the `format` passed + * for printing in a terminal. It is aware of the terminal's capabilities + * and acts according to the configuration set via `NO_COLOR`, + * `NODE_DISABLE_COLORS` and `FORCE_COLOR` environment variables. + * + * ```js + * import { styleText } from 'node:util'; + * import { stderr } from 'node:process'; + * + * const successMessage = styleText('green', 'Success!'); + * console.log(successMessage); + * + * const errorMessage = styleText( + * 'red', + * 'Error! Error!', + * // Validate if process.stderr has TTY + * { stream: stderr }, + * ); + * console.error(errorMessage); + * ``` + * + * `util.inspect.colors` also provides text formats such as `italic`, and + * `underline` and you can combine both: + * + * ```js + * console.log( + * util.styleText(['underline', 'italic'], 'My italic underlined message'), + * ); + * ``` + * + * When passing an array of formats, the order of the format applied + * is left to right so the following style might overwrite the previous one. + * + * ```js + * console.log( + * util.styleText(['red', 'green'], 'text'), // green + * ); + * ``` + * + * The special format value `none` applies no additional styling to the text. + * + * The full list of formats can be found in [modifiers](https://nodejs.org/docs/latest-v25.x/api/util.html#modifiers). + * @param format A text format or an Array of text formats defined in `util.inspect.colors`. + * @param text The text to to be formatted. + * @since v20.12.0 + */ + export function styleText( + format: InspectColor | readonly InspectColor[], + text: string, + options?: StyleTextOptions, + ): string; + /** @deprecated This alias will be removed in a future version. Use the canonical `TextEncoderEncodeIntoResult` instead. */ + // TODO: remove in future major + export interface EncodeIntoResult extends TextEncoderEncodeIntoResult {} + //// parseArgs + /** + * Provides a higher level API for command-line argument parsing than interacting + * with `process.argv` directly. Takes a specification for the expected arguments + * and returns a structured object with the parsed options and positionals. + * + * ```js + * import { parseArgs } from 'node:util'; + * const args = ['-f', '--bar', 'b']; + * const options = { + * foo: { + * type: 'boolean', + * short: 'f', + * }, + * bar: { + * type: 'string', + * }, + * }; + * const { + * values, + * positionals, + * } = parseArgs({ args, options }); + * console.log(values, positionals); + * // Prints: [Object: null prototype] { foo: true, bar: 'b' } [] + * ``` + * @since v18.3.0, v16.17.0 + * @param config Used to provide arguments for parsing and to configure the parser. `config` supports the following properties: + * @return The parsed command line arguments: + */ + export function parseArgs<T extends ParseArgsConfig>(config?: T): ParsedResults<T>; + /** + * Type of argument used in {@link parseArgs}. + */ + export type ParseArgsOptionsType = "boolean" | "string"; + export interface ParseArgsOptionDescriptor { + /** + * Type of argument. + */ + type: ParseArgsOptionsType; + /** + * Whether this option can be provided multiple times. + * If `true`, all values will be collected in an array. + * If `false`, values for the option are last-wins. + * @default false. + */ + multiple?: boolean | undefined; + /** + * A single character alias for the option. + */ + short?: string | undefined; + /** + * The value to assign to + * the option if it does not appear in the arguments to be parsed. The value + * must match the type specified by the `type` property. If `multiple` is + * `true`, it must be an array. No default value is applied when the option + * does appear in the arguments to be parsed, even if the provided value + * is falsy. + * @since v18.11.0 + */ + default?: string | boolean | string[] | boolean[] | undefined; + } + export interface ParseArgsOptionsConfig { + [longOption: string]: ParseArgsOptionDescriptor; + } + export interface ParseArgsConfig { + /** + * Array of argument strings. + */ + args?: readonly string[] | undefined; + /** + * Used to describe arguments known to the parser. + */ + options?: ParseArgsOptionsConfig | undefined; + /** + * Should an error be thrown when unknown arguments are encountered, + * or when arguments are passed that do not match the `type` configured in `options`. + * @default true + */ + strict?: boolean | undefined; + /** + * Whether this command accepts positional arguments. + */ + allowPositionals?: boolean | undefined; + /** + * If `true`, allows explicitly setting boolean options to `false` by prefixing the option name with `--no-`. + * @default false + * @since v22.4.0 + */ + allowNegative?: boolean | undefined; + /** + * Return the parsed tokens. This is useful for extending the built-in behavior, + * from adding additional checks through to reprocessing the tokens in different ways. + * @default false + */ + tokens?: boolean | undefined; + } + /* + IfDefaultsTrue and IfDefaultsFalse are helpers to handle default values for missing boolean properties. + TypeScript does not have exact types for objects: https://github.com/microsoft/TypeScript/issues/12936 + This means it is impossible to distinguish between "field X is definitely not present" and "field X may or may not be present". + But we expect users to generally provide their config inline or `as const`, which means TS will always know whether a given field is present. + So this helper treats "not definitely present" (i.e., not `extends boolean`) as being "definitely not present", i.e. it should have its default value. + This is technically incorrect but is a much nicer UX for the common case. + The IfDefaultsTrue version is for things which default to true; the IfDefaultsFalse version is for things which default to false. + */ + type IfDefaultsTrue<T, IfTrue, IfFalse> = T extends true ? IfTrue + : T extends false ? IfFalse + : IfTrue; + // we put the `extends false` condition first here because `undefined` compares like `any` when `strictNullChecks: false` + type IfDefaultsFalse<T, IfTrue, IfFalse> = T extends false ? IfFalse + : T extends true ? IfTrue + : IfFalse; + type ExtractOptionValue<T extends ParseArgsConfig, O extends ParseArgsOptionDescriptor> = IfDefaultsTrue< + T["strict"], + O["type"] extends "string" ? string : O["type"] extends "boolean" ? boolean : string | boolean, + string | boolean + >; + type ApplyOptionalModifiers<O extends ParseArgsOptionsConfig, V extends Record<keyof O, unknown>> = ( + & { -readonly [LongOption in keyof O]?: V[LongOption] } + & { [LongOption in keyof O as O[LongOption]["default"] extends {} ? LongOption : never]: V[LongOption] } + ) extends infer P ? { [K in keyof P]: P[K] } : never; // resolve intersection to object + type ParsedValues<T extends ParseArgsConfig> = + & IfDefaultsTrue<T["strict"], unknown, { [longOption: string]: undefined | string | boolean }> + & (T["options"] extends ParseArgsOptionsConfig ? ApplyOptionalModifiers< + T["options"], + { + [LongOption in keyof T["options"]]: IfDefaultsFalse< + T["options"][LongOption]["multiple"], + Array<ExtractOptionValue<T, T["options"][LongOption]>>, + ExtractOptionValue<T, T["options"][LongOption]> + >; + } + > + : {}); + type ParsedPositionals<T extends ParseArgsConfig> = IfDefaultsTrue< + T["strict"], + IfDefaultsFalse<T["allowPositionals"], string[], []>, + IfDefaultsTrue<T["allowPositionals"], string[], []> + >; + type PreciseTokenForOptions< + K extends string, + O extends ParseArgsOptionDescriptor, + > = O["type"] extends "string" ? { + kind: "option"; + index: number; + name: K; + rawName: string; + value: string; + inlineValue: boolean; + } + : O["type"] extends "boolean" ? { + kind: "option"; + index: number; + name: K; + rawName: string; + value: undefined; + inlineValue: undefined; + } + : OptionToken & { name: K }; + type TokenForOptions< + T extends ParseArgsConfig, + K extends keyof T["options"] = keyof T["options"], + > = K extends unknown + ? T["options"] extends ParseArgsOptionsConfig ? PreciseTokenForOptions<K & string, T["options"][K]> + : OptionToken + : never; + type ParsedOptionToken<T extends ParseArgsConfig> = IfDefaultsTrue<T["strict"], TokenForOptions<T>, OptionToken>; + type ParsedPositionalToken<T extends ParseArgsConfig> = IfDefaultsTrue< + T["strict"], + IfDefaultsFalse<T["allowPositionals"], { kind: "positional"; index: number; value: string }, never>, + IfDefaultsTrue<T["allowPositionals"], { kind: "positional"; index: number; value: string }, never> + >; + type ParsedTokens<T extends ParseArgsConfig> = Array< + ParsedOptionToken<T> | ParsedPositionalToken<T> | { kind: "option-terminator"; index: number } + >; + type PreciseParsedResults<T extends ParseArgsConfig> = IfDefaultsFalse< + T["tokens"], + { + values: ParsedValues<T>; + positionals: ParsedPositionals<T>; + tokens: ParsedTokens<T>; + }, + { + values: ParsedValues<T>; + positionals: ParsedPositionals<T>; + } + >; + type OptionToken = + | { kind: "option"; index: number; name: string; rawName: string; value: string; inlineValue: boolean } + | { + kind: "option"; + index: number; + name: string; + rawName: string; + value: undefined; + inlineValue: undefined; + }; + type Token = + | OptionToken + | { kind: "positional"; index: number; value: string } + | { kind: "option-terminator"; index: number }; + // If ParseArgsConfig extends T, then the user passed config constructed elsewhere. + // So we can't rely on the `"not definitely present" implies "definitely not present"` assumption mentioned above. + type ParsedResults<T extends ParseArgsConfig> = ParseArgsConfig extends T ? { + values: { + [longOption: string]: undefined | string | boolean | Array<string | boolean>; + }; + positionals: string[]; + tokens?: Token[]; + } + : PreciseParsedResults<T>; + /** + * An implementation of [the MIMEType class](https://bmeck.github.io/node-proposal-mime-api/). + * + * In accordance with browser conventions, all properties of `MIMEType` objects + * are implemented as getters and setters on the class prototype, rather than as + * data properties on the object itself. + * + * A MIME string is a structured string containing multiple meaningful + * components. When parsed, a `MIMEType` object is returned containing + * properties for each of these components. + * @since v19.1.0, v18.13.0 + */ + export class MIMEType { + /** + * Creates a new MIMEType object by parsing the input. + * + * A `TypeError` will be thrown if the `input` is not a valid MIME. + * Note that an effort will be made to coerce the given values into strings. + * @param input The input MIME to parse. + */ + constructor(input: string | { toString: () => string }); + /** + * Gets and sets the type portion of the MIME. + * + * ```js + * import { MIMEType } from 'node:util'; + * + * const myMIME = new MIMEType('text/javascript'); + * console.log(myMIME.type); + * // Prints: text + * myMIME.type = 'application'; + * console.log(myMIME.type); + * // Prints: application + * console.log(String(myMIME)); + * // Prints: application/javascript + * ``` + */ + type: string; + /** + * Gets and sets the subtype portion of the MIME. + * + * ```js + * import { MIMEType } from 'node:util'; + * + * const myMIME = new MIMEType('text/ecmascript'); + * console.log(myMIME.subtype); + * // Prints: ecmascript + * myMIME.subtype = 'javascript'; + * console.log(myMIME.subtype); + * // Prints: javascript + * console.log(String(myMIME)); + * // Prints: text/javascript + * ``` + */ + subtype: string; + /** + * Gets the essence of the MIME. This property is read only. + * Use `mime.type` or `mime.subtype` to alter the MIME. + * + * ```js + * import { MIMEType } from 'node:util'; + * + * const myMIME = new MIMEType('text/javascript;key=value'); + * console.log(myMIME.essence); + * // Prints: text/javascript + * myMIME.type = 'application'; + * console.log(myMIME.essence); + * // Prints: application/javascript + * console.log(String(myMIME)); + * // Prints: application/javascript;key=value + * ``` + */ + readonly essence: string; + /** + * Gets the `MIMEParams` object representing the + * parameters of the MIME. This property is read-only. See `MIMEParams` documentation for details. + */ + readonly params: MIMEParams; + /** + * The `toString()` method on the `MIMEType` object returns the serialized MIME. + * + * Because of the need for standard compliance, this method does not allow users + * to customize the serialization process of the MIME. + */ + toString(): string; + } + /** + * The `MIMEParams` API provides read and write access to the parameters of a `MIMEType`. + * @since v19.1.0, v18.13.0 + */ + export class MIMEParams { + /** + * Remove all name-value pairs whose name is `name`. + */ + delete(name: string): void; + /** + * Returns an iterator over each of the name-value pairs in the parameters. + * Each item of the iterator is a JavaScript `Array`. The first item of the array + * is the `name`, the second item of the array is the `value`. + */ + entries(): NodeJS.Iterator<[name: string, value: string]>; + /** + * Returns the value of the first name-value pair whose name is `name`. If there + * are no such pairs, `null` is returned. + * @return or `null` if there is no name-value pair with the given `name`. + */ + get(name: string): string | null; + /** + * Returns `true` if there is at least one name-value pair whose name is `name`. + */ + has(name: string): boolean; + /** + * Returns an iterator over the names of each name-value pair. + * + * ```js + * import { MIMEType } from 'node:util'; + * + * const { params } = new MIMEType('text/plain;foo=0;bar=1'); + * for (const name of params.keys()) { + * console.log(name); + * } + * // Prints: + * // foo + * // bar + * ``` + */ + keys(): NodeJS.Iterator<string>; + /** + * Sets the value in the `MIMEParams` object associated with `name` to `value`. If there are any pre-existing name-value pairs whose names are `name`, + * set the first such pair's value to `value`. + * + * ```js + * import { MIMEType } from 'node:util'; + * + * const { params } = new MIMEType('text/plain;foo=0;bar=1'); + * params.set('foo', 'def'); + * params.set('baz', 'xyz'); + * console.log(params.toString()); + * // Prints: foo=def;bar=1;baz=xyz + * ``` + */ + set(name: string, value: string): void; + /** + * Returns an iterator over the values of each name-value pair. + */ + values(): NodeJS.Iterator<string>; + /** + * Returns an iterator over each of the name-value pairs in the parameters. + */ + [Symbol.iterator](): NodeJS.Iterator<[name: string, value: string]>; + } + // #region web types + export interface TextDecodeOptions { + stream?: boolean; + } + export interface TextDecoderCommon { + readonly encoding: string; + readonly fatal: boolean; + readonly ignoreBOM: boolean; + } + export interface TextDecoderOptions { + fatal?: boolean; + ignoreBOM?: boolean; + } + export interface TextEncoderCommon { + readonly encoding: string; + } + export interface TextEncoderEncodeIntoResult { + read: number; + written: number; + } + export interface TextDecoder extends TextDecoderCommon { + decode(input?: NodeJS.AllowSharedBufferSource, options?: TextDecodeOptions): string; + } + export var TextDecoder: { + prototype: TextDecoder; + new(label?: string, options?: TextDecoderOptions): TextDecoder; + }; + export interface TextEncoder extends TextEncoderCommon { + encode(input?: string): NodeJS.NonSharedUint8Array; + encodeInto(source: string, destination: Uint8Array): TextEncoderEncodeIntoResult; + } + export var TextEncoder: { + prototype: TextEncoder; + new(): TextEncoder; + }; + // #endregion +} +declare module "util" { + export * from "node:util"; +} diff --git a/server/node_modules/@types/node/util/types.d.ts b/server/node_modules/@types/node/util/types.d.ts new file mode 100644 index 0000000..818825b --- /dev/null +++ b/server/node_modules/@types/node/util/types.d.ts @@ -0,0 +1,558 @@ +declare module "node:util/types" { + import { KeyObject, webcrypto } from "node:crypto"; + /** + * Returns `true` if the value is a built-in [`ArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer) or + * [`SharedArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer) instance. + * + * See also `util.types.isArrayBuffer()` and `util.types.isSharedArrayBuffer()`. + * + * ```js + * util.types.isAnyArrayBuffer(new ArrayBuffer()); // Returns true + * util.types.isAnyArrayBuffer(new SharedArrayBuffer()); // Returns true + * ``` + * @since v10.0.0 + */ + function isAnyArrayBuffer(object: unknown): object is ArrayBufferLike; + /** + * Returns `true` if the value is an `arguments` object. + * + * ```js + * function foo() { + * util.types.isArgumentsObject(arguments); // Returns true + * } + * ``` + * @since v10.0.0 + */ + function isArgumentsObject(object: unknown): object is IArguments; + /** + * Returns `true` if the value is a built-in [`ArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer) instance. + * This does _not_ include [`SharedArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer) instances. Usually, it is + * desirable to test for both; See `util.types.isAnyArrayBuffer()` for that. + * + * ```js + * util.types.isArrayBuffer(new ArrayBuffer()); // Returns true + * util.types.isArrayBuffer(new SharedArrayBuffer()); // Returns false + * ``` + * @since v10.0.0 + */ + function isArrayBuffer(object: unknown): object is ArrayBuffer; + /** + * Returns `true` if the value is an instance of one of the [`ArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer) views, such as typed + * array objects or [`DataView`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView). Equivalent to + * [`ArrayBuffer.isView()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer/isView). + * + * ```js + * util.types.isArrayBufferView(new Int8Array()); // true + * util.types.isArrayBufferView(Buffer.from('hello world')); // true + * util.types.isArrayBufferView(new DataView(new ArrayBuffer(16))); // true + * util.types.isArrayBufferView(new ArrayBuffer()); // false + * ``` + * @since v10.0.0 + */ + function isArrayBufferView(object: unknown): object is NodeJS.ArrayBufferView; + /** + * Returns `true` if the value is an [async function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function). + * This only reports back what the JavaScript engine is seeing; + * in particular, the return value may not match the original source code if + * a transpilation tool was used. + * + * ```js + * util.types.isAsyncFunction(function foo() {}); // Returns false + * util.types.isAsyncFunction(async function foo() {}); // Returns true + * ``` + * @since v10.0.0 + */ + function isAsyncFunction(object: unknown): boolean; + /** + * Returns `true` if the value is a `BigInt64Array` instance. + * + * ```js + * util.types.isBigInt64Array(new BigInt64Array()); // Returns true + * util.types.isBigInt64Array(new BigUint64Array()); // Returns false + * ``` + * @since v10.0.0 + */ + function isBigInt64Array(value: unknown): value is BigInt64Array; + /** + * Returns `true` if the value is a BigInt object, e.g. created + * by `Object(BigInt(123))`. + * + * ```js + * util.types.isBigIntObject(Object(BigInt(123))); // Returns true + * util.types.isBigIntObject(BigInt(123)); // Returns false + * util.types.isBigIntObject(123); // Returns false + * ``` + * @since v10.4.0 + */ + function isBigIntObject(object: unknown): object is BigInt; + /** + * Returns `true` if the value is a `BigUint64Array` instance. + * + * ```js + * util.types.isBigUint64Array(new BigInt64Array()); // Returns false + * util.types.isBigUint64Array(new BigUint64Array()); // Returns true + * ``` + * @since v10.0.0 + */ + function isBigUint64Array(value: unknown): value is BigUint64Array; + /** + * Returns `true` if the value is a boolean object, e.g. created + * by `new Boolean()`. + * + * ```js + * util.types.isBooleanObject(false); // Returns false + * util.types.isBooleanObject(true); // Returns false + * util.types.isBooleanObject(new Boolean(false)); // Returns true + * util.types.isBooleanObject(new Boolean(true)); // Returns true + * util.types.isBooleanObject(Boolean(false)); // Returns false + * util.types.isBooleanObject(Boolean(true)); // Returns false + * ``` + * @since v10.0.0 + */ + function isBooleanObject(object: unknown): object is Boolean; + /** + * Returns `true` if the value is any boxed primitive object, e.g. created + * by `new Boolean()`, `new String()` or `Object(Symbol())`. + * + * For example: + * + * ```js + * util.types.isBoxedPrimitive(false); // Returns false + * util.types.isBoxedPrimitive(new Boolean(false)); // Returns true + * util.types.isBoxedPrimitive(Symbol('foo')); // Returns false + * util.types.isBoxedPrimitive(Object(Symbol('foo'))); // Returns true + * util.types.isBoxedPrimitive(Object(BigInt(5))); // Returns true + * ``` + * @since v10.11.0 + */ + function isBoxedPrimitive(object: unknown): object is String | Number | BigInt | Boolean | Symbol; + /** + * Returns `true` if the value is a built-in [`DataView`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView) instance. + * + * ```js + * const ab = new ArrayBuffer(20); + * util.types.isDataView(new DataView(ab)); // Returns true + * util.types.isDataView(new Float64Array()); // Returns false + * ``` + * + * See also [`ArrayBuffer.isView()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer/isView). + * @since v10.0.0 + */ + function isDataView(object: unknown): object is DataView; + /** + * Returns `true` if the value is a built-in [`Date`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) instance. + * + * ```js + * util.types.isDate(new Date()); // Returns true + * ``` + * @since v10.0.0 + */ + function isDate(object: unknown): object is Date; + /** + * Returns `true` if the value is a native `External` value. + * + * A native `External` value is a special type of object that contains a + * raw C++ pointer (`void*`) for access from native code, and has no other + * properties. Such objects are created either by Node.js internals or native + * addons. In JavaScript, they are + * [frozen](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) objects with a + * `null` prototype. + * + * ```c + * #include <js_native_api.h> + * #include <stdlib.h> + * napi_value result; + * static napi_value MyNapi(napi_env env, napi_callback_info info) { + * int* raw = (int*) malloc(1024); + * napi_status status = napi_create_external(env, (void*) raw, NULL, NULL, &result); + * if (status != napi_ok) { + * napi_throw_error(env, NULL, "napi_create_external failed"); + * return NULL; + * } + * return result; + * } + * ... + * DECLARE_NAPI_PROPERTY("myNapi", MyNapi) + * ... + * ``` + * + * ```js + * import native from 'napi_addon.node'; + * import { types } from 'node:util'; + * + * const data = native.myNapi(); + * types.isExternal(data); // returns true + * types.isExternal(0); // returns false + * types.isExternal(new String('foo')); // returns false + * ``` + * + * For further information on `napi_create_external`, refer to + * [`napi_create_external()`](https://nodejs.org/docs/latest-v25.x/api/n-api.html#napi_create_external). + * @since v10.0.0 + */ + function isExternal(object: unknown): boolean; + /** + * Returns `true` if the value is a built-in [`Float16Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float16Array) instance. + * + * ```js + * util.types.isFloat16Array(new ArrayBuffer()); // Returns false + * util.types.isFloat16Array(new Float16Array()); // Returns true + * util.types.isFloat16Array(new Float32Array()); // Returns false + * ``` + * @since v24.0.0 + */ + function isFloat16Array(object: unknown): object is Float16Array; + /** + * Returns `true` if the value is a built-in [`Float32Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float32Array) instance. + * + * ```js + * util.types.isFloat32Array(new ArrayBuffer()); // Returns false + * util.types.isFloat32Array(new Float32Array()); // Returns true + * util.types.isFloat32Array(new Float64Array()); // Returns false + * ``` + * @since v10.0.0 + */ + function isFloat32Array(object: unknown): object is Float32Array; + /** + * Returns `true` if the value is a built-in [`Float64Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float64Array) instance. + * + * ```js + * util.types.isFloat64Array(new ArrayBuffer()); // Returns false + * util.types.isFloat64Array(new Uint8Array()); // Returns false + * util.types.isFloat64Array(new Float64Array()); // Returns true + * ``` + * @since v10.0.0 + */ + function isFloat64Array(object: unknown): object is Float64Array; + /** + * Returns `true` if the value is a generator function. + * This only reports back what the JavaScript engine is seeing; + * in particular, the return value may not match the original source code if + * a transpilation tool was used. + * + * ```js + * util.types.isGeneratorFunction(function foo() {}); // Returns false + * util.types.isGeneratorFunction(function* foo() {}); // Returns true + * ``` + * @since v10.0.0 + */ + function isGeneratorFunction(object: unknown): object is GeneratorFunction; + /** + * Returns `true` if the value is a generator object as returned from a + * built-in generator function. + * This only reports back what the JavaScript engine is seeing; + * in particular, the return value may not match the original source code if + * a transpilation tool was used. + * + * ```js + * function* foo() {} + * const generator = foo(); + * util.types.isGeneratorObject(generator); // Returns true + * ``` + * @since v10.0.0 + */ + function isGeneratorObject(object: unknown): object is Generator; + /** + * Returns `true` if the value is a built-in [`Int8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int8Array) instance. + * + * ```js + * util.types.isInt8Array(new ArrayBuffer()); // Returns false + * util.types.isInt8Array(new Int8Array()); // Returns true + * util.types.isInt8Array(new Float64Array()); // Returns false + * ``` + * @since v10.0.0 + */ + function isInt8Array(object: unknown): object is Int8Array; + /** + * Returns `true` if the value is a built-in [`Int16Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int16Array) instance. + * + * ```js + * util.types.isInt16Array(new ArrayBuffer()); // Returns false + * util.types.isInt16Array(new Int16Array()); // Returns true + * util.types.isInt16Array(new Float64Array()); // Returns false + * ``` + * @since v10.0.0 + */ + function isInt16Array(object: unknown): object is Int16Array; + /** + * Returns `true` if the value is a built-in [`Int32Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int32Array) instance. + * + * ```js + * util.types.isInt32Array(new ArrayBuffer()); // Returns false + * util.types.isInt32Array(new Int32Array()); // Returns true + * util.types.isInt32Array(new Float64Array()); // Returns false + * ``` + * @since v10.0.0 + */ + function isInt32Array(object: unknown): object is Int32Array; + /** + * Returns `true` if the value is a built-in [`Map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) instance. + * + * ```js + * util.types.isMap(new Map()); // Returns true + * ``` + * @since v10.0.0 + */ + function isMap<T>( + object: T | {}, + ): object is T extends ReadonlyMap<any, any> ? (unknown extends T ? never : ReadonlyMap<any, any>) + : Map<unknown, unknown>; + /** + * Returns `true` if the value is an iterator returned for a built-in [`Map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) instance. + * + * ```js + * const map = new Map(); + * util.types.isMapIterator(map.keys()); // Returns true + * util.types.isMapIterator(map.values()); // Returns true + * util.types.isMapIterator(map.entries()); // Returns true + * util.types.isMapIterator(map[Symbol.iterator]()); // Returns true + * ``` + * @since v10.0.0 + */ + function isMapIterator(object: unknown): boolean; + /** + * Returns `true` if the value is an instance of a [Module Namespace Object](https://tc39.github.io/ecma262/#sec-module-namespace-exotic-objects). + * + * ```js + * import * as ns from './a.js'; + * + * util.types.isModuleNamespaceObject(ns); // Returns true + * ``` + * @since v10.0.0 + */ + function isModuleNamespaceObject(value: unknown): boolean; + /** + * Returns `true` if the value was returned by the constructor of a + * [built-in `Error` type](https://tc39.es/ecma262/#sec-error-objects). + * + * ```js + * console.log(util.types.isNativeError(new Error())); // true + * console.log(util.types.isNativeError(new TypeError())); // true + * console.log(util.types.isNativeError(new RangeError())); // true + * ``` + * + * Subclasses of the native error types are also native errors: + * + * ```js + * class MyError extends Error {} + * console.log(util.types.isNativeError(new MyError())); // true + * ``` + * + * A value being `instanceof` a native error class is not equivalent to `isNativeError()` + * returning `true` for that value. `isNativeError()` returns `true` for errors + * which come from a different [realm](https://tc39.es/ecma262/#realm) while `instanceof Error` returns `false` + * for these errors: + * + * ```js + * import { createContext, runInContext } from 'node:vm'; + * import { types } from 'node:util'; + * + * const context = createContext({}); + * const myError = runInContext('new Error()', context); + * console.log(types.isNativeError(myError)); // true + * console.log(myError instanceof Error); // false + * ``` + * + * Conversely, `isNativeError()` returns `false` for all objects which were not + * returned by the constructor of a native error. That includes values + * which are `instanceof` native errors: + * + * ```js + * const myError = { __proto__: Error.prototype }; + * console.log(util.types.isNativeError(myError)); // false + * console.log(myError instanceof Error); // true + * ``` + * @since v10.0.0 + * @deprecated The `util.types.isNativeError` API is deprecated. Please use `Error.isError` instead. + */ + function isNativeError(object: unknown): object is Error; + /** + * Returns `true` if the value is a number object, e.g. created + * by `new Number()`. + * + * ```js + * util.types.isNumberObject(0); // Returns false + * util.types.isNumberObject(new Number(0)); // Returns true + * ``` + * @since v10.0.0 + */ + function isNumberObject(object: unknown): object is Number; + /** + * Returns `true` if the value is a built-in [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise). + * + * ```js + * util.types.isPromise(Promise.resolve(42)); // Returns true + * ``` + * @since v10.0.0 + */ + function isPromise(object: unknown): object is Promise<unknown>; + /** + * Returns `true` if the value is a [`Proxy`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) instance. + * + * ```js + * const target = {}; + * const proxy = new Proxy(target, {}); + * util.types.isProxy(target); // Returns false + * util.types.isProxy(proxy); // Returns true + * ``` + * @since v10.0.0 + */ + function isProxy(object: unknown): boolean; + /** + * Returns `true` if the value is a regular expression object. + * + * ```js + * util.types.isRegExp(/abc/); // Returns true + * util.types.isRegExp(new RegExp('abc')); // Returns true + * ``` + * @since v10.0.0 + */ + function isRegExp(object: unknown): object is RegExp; + /** + * Returns `true` if the value is a built-in [`Set`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) instance. + * + * ```js + * util.types.isSet(new Set()); // Returns true + * ``` + * @since v10.0.0 + */ + function isSet<T>( + object: T | {}, + ): object is T extends ReadonlySet<any> ? (unknown extends T ? never : ReadonlySet<any>) : Set<unknown>; + /** + * Returns `true` if the value is an iterator returned for a built-in [`Set`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) instance. + * + * ```js + * const set = new Set(); + * util.types.isSetIterator(set.keys()); // Returns true + * util.types.isSetIterator(set.values()); // Returns true + * util.types.isSetIterator(set.entries()); // Returns true + * util.types.isSetIterator(set[Symbol.iterator]()); // Returns true + * ``` + * @since v10.0.0 + */ + function isSetIterator(object: unknown): boolean; + /** + * Returns `true` if the value is a built-in [`SharedArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer) instance. + * This does _not_ include [`ArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer) instances. Usually, it is + * desirable to test for both; See `util.types.isAnyArrayBuffer()` for that. + * + * ```js + * util.types.isSharedArrayBuffer(new ArrayBuffer()); // Returns false + * util.types.isSharedArrayBuffer(new SharedArrayBuffer()); // Returns true + * ``` + * @since v10.0.0 + */ + function isSharedArrayBuffer(object: unknown): object is SharedArrayBuffer; + /** + * Returns `true` if the value is a string object, e.g. created + * by `new String()`. + * + * ```js + * util.types.isStringObject('foo'); // Returns false + * util.types.isStringObject(new String('foo')); // Returns true + * ``` + * @since v10.0.0 + */ + function isStringObject(object: unknown): object is String; + /** + * Returns `true` if the value is a symbol object, created + * by calling `Object()` on a `Symbol` primitive. + * + * ```js + * const symbol = Symbol('foo'); + * util.types.isSymbolObject(symbol); // Returns false + * util.types.isSymbolObject(Object(symbol)); // Returns true + * ``` + * @since v10.0.0 + */ + function isSymbolObject(object: unknown): object is Symbol; + /** + * Returns `true` if the value is a built-in [`TypedArray`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray) instance. + * + * ```js + * util.types.isTypedArray(new ArrayBuffer()); // Returns false + * util.types.isTypedArray(new Uint8Array()); // Returns true + * util.types.isTypedArray(new Float64Array()); // Returns true + * ``` + * + * See also [`ArrayBuffer.isView()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer/isView). + * @since v10.0.0 + */ + function isTypedArray(object: unknown): object is NodeJS.TypedArray; + /** + * Returns `true` if the value is a built-in [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) instance. + * + * ```js + * util.types.isUint8Array(new ArrayBuffer()); // Returns false + * util.types.isUint8Array(new Uint8Array()); // Returns true + * util.types.isUint8Array(new Float64Array()); // Returns false + * ``` + * @since v10.0.0 + */ + function isUint8Array(object: unknown): object is Uint8Array; + /** + * Returns `true` if the value is a built-in [`Uint8ClampedArray`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8ClampedArray) instance. + * + * ```js + * util.types.isUint8ClampedArray(new ArrayBuffer()); // Returns false + * util.types.isUint8ClampedArray(new Uint8ClampedArray()); // Returns true + * util.types.isUint8ClampedArray(new Float64Array()); // Returns false + * ``` + * @since v10.0.0 + */ + function isUint8ClampedArray(object: unknown): object is Uint8ClampedArray; + /** + * Returns `true` if the value is a built-in [`Uint16Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint16Array) instance. + * + * ```js + * util.types.isUint16Array(new ArrayBuffer()); // Returns false + * util.types.isUint16Array(new Uint16Array()); // Returns true + * util.types.isUint16Array(new Float64Array()); // Returns false + * ``` + * @since v10.0.0 + */ + function isUint16Array(object: unknown): object is Uint16Array; + /** + * Returns `true` if the value is a built-in [`Uint32Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint32Array) instance. + * + * ```js + * util.types.isUint32Array(new ArrayBuffer()); // Returns false + * util.types.isUint32Array(new Uint32Array()); // Returns true + * util.types.isUint32Array(new Float64Array()); // Returns false + * ``` + * @since v10.0.0 + */ + function isUint32Array(object: unknown): object is Uint32Array; + /** + * Returns `true` if the value is a built-in [`WeakMap`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap) instance. + * + * ```js + * util.types.isWeakMap(new WeakMap()); // Returns true + * ``` + * @since v10.0.0 + */ + function isWeakMap(object: unknown): object is WeakMap<object, unknown>; + /** + * Returns `true` if the value is a built-in [`WeakSet`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet) instance. + * + * ```js + * util.types.isWeakSet(new WeakSet()); // Returns true + * ``` + * @since v10.0.0 + */ + function isWeakSet(object: unknown): object is WeakSet<object>; + /** + * Returns `true` if `value` is a `KeyObject`, `false` otherwise. + * @since v16.2.0 + */ + function isKeyObject(object: unknown): object is KeyObject; + /** + * Returns `true` if `value` is a `CryptoKey`, `false` otherwise. + * @since v16.2.0 + */ + function isCryptoKey(object: unknown): object is webcrypto.CryptoKey; +} +declare module "util/types" { + export * from "node:util/types"; +} diff --git a/server/node_modules/@types/node/v8.d.ts b/server/node_modules/@types/node/v8.d.ts new file mode 100644 index 0000000..022dc01 --- /dev/null +++ b/server/node_modules/@types/node/v8.d.ts @@ -0,0 +1,983 @@ +/** + * The `node:v8` module exposes APIs that are specific to the version of [V8](https://developers.google.com/v8/) built into the Node.js binary. It can be accessed using: + * + * ```js + * import v8 from 'node:v8'; + * ``` + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/v8.js) + */ +declare module "node:v8" { + import { NonSharedBuffer } from "node:buffer"; + import { Readable } from "node:stream"; + interface HeapSpaceInfo { + space_name: string; + space_size: number; + space_used_size: number; + space_available_size: number; + physical_space_size: number; + } + // ** Signifies if the --zap_code_space option is enabled or not. 1 == enabled, 0 == disabled. */ + type DoesZapCodeSpaceFlag = 0 | 1; + interface HeapInfo { + total_heap_size: number; + total_heap_size_executable: number; + total_physical_size: number; + total_available_size: number; + used_heap_size: number; + heap_size_limit: number; + malloced_memory: number; + peak_malloced_memory: number; + does_zap_garbage: DoesZapCodeSpaceFlag; + number_of_native_contexts: number; + number_of_detached_contexts: number; + total_global_handles_size: number; + used_global_handles_size: number; + external_memory: number; + total_allocated_bytes: number; + } + interface HeapCodeStatistics { + code_and_metadata_size: number; + bytecode_and_metadata_size: number; + external_script_source_size: number; + } + interface HeapSnapshotOptions { + /** + * If true, expose internals in the heap snapshot. + * @default false + */ + exposeInternals?: boolean | undefined; + /** + * If true, expose numeric values in artificial fields. + * @default false + */ + exposeNumericValues?: boolean | undefined; + } + /** + * Returns an integer representing a version tag derived from the V8 version, + * command-line flags, and detected CPU features. This is useful for determining + * whether a `vm.Script` `cachedData` buffer is compatible with this instance + * of V8. + * + * ```js + * console.log(v8.cachedDataVersionTag()); // 3947234607 + * // The value returned by v8.cachedDataVersionTag() is derived from the V8 + * // version, command-line flags, and detected CPU features. Test that the value + * // does indeed update when flags are toggled. + * v8.setFlagsFromString('--allow_natives_syntax'); + * console.log(v8.cachedDataVersionTag()); // 183726201 + * ``` + * @since v8.0.0 + */ + function cachedDataVersionTag(): number; + /** + * Returns an object with the following properties: + * + * `does_zap_garbage` is a 0/1 boolean, which signifies whether the `--zap_code_space` option is enabled or not. This makes V8 overwrite heap + * garbage with a bit pattern. The RSS footprint (resident set size) gets bigger + * because it continuously touches all heap pages and that makes them less likely + * to get swapped out by the operating system. + * + * `number_of_native_contexts` The value of native\_context is the number of the + * top-level contexts currently active. Increase of this number over time indicates + * a memory leak. + * + * `number_of_detached_contexts` The value of detached\_context is the number + * of contexts that were detached and not yet garbage collected. This number + * being non-zero indicates a potential memory leak. + * + * `total_global_handles_size` The value of total\_global\_handles\_size is the + * total memory size of V8 global handles. + * + * `used_global_handles_size` The value of used\_global\_handles\_size is the + * used memory size of V8 global handles. + * + * `external_memory` The value of external\_memory is the memory size of array + * buffers and external strings. + * + * `total_allocated_bytes` The value of total allocated bytes since the Isolate + * creation + * + * ```js + * { + * total_heap_size: 7326976, + * total_heap_size_executable: 4194304, + * total_physical_size: 7326976, + * total_available_size: 1152656, + * used_heap_size: 3476208, + * heap_size_limit: 1535115264, + * malloced_memory: 16384, + * peak_malloced_memory: 1127496, + * does_zap_garbage: 0, + * number_of_native_contexts: 1, + * number_of_detached_contexts: 0, + * total_global_handles_size: 8192, + * used_global_handles_size: 3296, + * external_memory: 318824 + * } + * ``` + * @since v1.0.0 + */ + function getHeapStatistics(): HeapInfo; + /** + * It returns an object with a structure similar to the + * [`cppgc::HeapStatistics`](https://v8docs.nodesource.com/node-22.4/d7/d51/heap-statistics_8h_source.html) + * object. See the [V8 documentation](https://v8docs.nodesource.com/node-22.4/df/d2f/structcppgc_1_1_heap_statistics.html) + * for more information about the properties of the object. + * + * ```js + * // Detailed + * ({ + * committed_size_bytes: 131072, + * resident_size_bytes: 131072, + * used_size_bytes: 152, + * space_statistics: [ + * { + * name: 'NormalPageSpace0', + * committed_size_bytes: 0, + * resident_size_bytes: 0, + * used_size_bytes: 0, + * page_stats: [{}], + * free_list_stats: {}, + * }, + * { + * name: 'NormalPageSpace1', + * committed_size_bytes: 131072, + * resident_size_bytes: 131072, + * used_size_bytes: 152, + * page_stats: [{}], + * free_list_stats: {}, + * }, + * { + * name: 'NormalPageSpace2', + * committed_size_bytes: 0, + * resident_size_bytes: 0, + * used_size_bytes: 0, + * page_stats: [{}], + * free_list_stats: {}, + * }, + * { + * name: 'NormalPageSpace3', + * committed_size_bytes: 0, + * resident_size_bytes: 0, + * used_size_bytes: 0, + * page_stats: [{}], + * free_list_stats: {}, + * }, + * { + * name: 'LargePageSpace', + * committed_size_bytes: 0, + * resident_size_bytes: 0, + * used_size_bytes: 0, + * page_stats: [{}], + * free_list_stats: {}, + * }, + * ], + * type_names: [], + * detail_level: 'detailed', + * }); + * ``` + * + * ```js + * // Brief + * ({ + * committed_size_bytes: 131072, + * resident_size_bytes: 131072, + * used_size_bytes: 128864, + * space_statistics: [], + * type_names: [], + * detail_level: 'brief', + * }); + * ``` + * @since v22.15.0 + * @param detailLevel **Default:** `'detailed'`. Specifies the level of detail in the returned statistics. + * Accepted values are: + * * `'brief'`: Brief statistics contain only the top-level + * allocated and used + * memory statistics for the entire heap. + * * `'detailed'`: Detailed statistics also contain a break + * down per space and page, as well as freelist statistics + * and object type histograms. + */ + function getCppHeapStatistics(detailLevel?: "brief" | "detailed"): object; + /** + * Returns statistics about the V8 heap spaces, i.e. the segments which make up + * the V8 heap. Neither the ordering of heap spaces, nor the availability of a + * heap space can be guaranteed as the statistics are provided via the + * V8 [`GetHeapSpaceStatistics`](https://v8docs.nodesource.com/node-13.2/d5/dda/classv8_1_1_isolate.html#ac673576f24fdc7a33378f8f57e1d13a4) function and may change from one V8 version to the + * next. + * + * The value returned is an array of objects containing the following properties: + * + * ```json + * [ + * { + * "space_name": "new_space", + * "space_size": 2063872, + * "space_used_size": 951112, + * "space_available_size": 80824, + * "physical_space_size": 2063872 + * }, + * { + * "space_name": "old_space", + * "space_size": 3090560, + * "space_used_size": 2493792, + * "space_available_size": 0, + * "physical_space_size": 3090560 + * }, + * { + * "space_name": "code_space", + * "space_size": 1260160, + * "space_used_size": 644256, + * "space_available_size": 960, + * "physical_space_size": 1260160 + * }, + * { + * "space_name": "map_space", + * "space_size": 1094160, + * "space_used_size": 201608, + * "space_available_size": 0, + * "physical_space_size": 1094160 + * }, + * { + * "space_name": "large_object_space", + * "space_size": 0, + * "space_used_size": 0, + * "space_available_size": 1490980608, + * "physical_space_size": 0 + * } + * ] + * ``` + * @since v6.0.0 + */ + function getHeapSpaceStatistics(): HeapSpaceInfo[]; + /** + * The `v8.setFlagsFromString()` method can be used to programmatically set + * V8 command-line flags. This method should be used with care. Changing settings + * after the VM has started may result in unpredictable behavior, including + * crashes and data loss; or it may simply do nothing. + * + * The V8 options available for a version of Node.js may be determined by running `node --v8-options`. + * + * Usage: + * + * ```js + * // Print GC events to stdout for one minute. + * import v8 from 'node:v8'; + * v8.setFlagsFromString('--trace_gc'); + * setTimeout(() => { v8.setFlagsFromString('--notrace_gc'); }, 60e3); + * ``` + * @since v1.0.0 + */ + function setFlagsFromString(flags: string): void; + /** + * This is similar to the [`queryObjects()` console API](https://developer.chrome.com/docs/devtools/console/utilities#queryObjects-function) + * provided by the Chromium DevTools console. It can be used to search for objects that have the matching constructor on its prototype chain + * in the heap after a full garbage collection, which can be useful for memory leak regression tests. To avoid surprising results, users should + * avoid using this API on constructors whose implementation they don't control, or on constructors that can be invoked by other parties in the + * application. + * + * To avoid accidental leaks, this API does not return raw references to the objects found. By default, it returns the count of the objects + * found. If `options.format` is `'summary'`, it returns an array containing brief string representations for each object. The visibility provided + * in this API is similar to what the heap snapshot provides, while users can save the cost of serialization and parsing and directly filter the + * target objects during the search. + * + * Only objects created in the current execution context are included in the results. + * + * ```js + * import { queryObjects } from 'node:v8'; + * class A { foo = 'bar'; } + * console.log(queryObjects(A)); // 0 + * const a = new A(); + * console.log(queryObjects(A)); // 1 + * // [ "A { foo: 'bar' }" ] + * console.log(queryObjects(A, { format: 'summary' })); + * + * class B extends A { bar = 'qux'; } + * const b = new B(); + * console.log(queryObjects(B)); // 1 + * // [ "B { foo: 'bar', bar: 'qux' }" ] + * console.log(queryObjects(B, { format: 'summary' })); + * + * // Note that, when there are child classes inheriting from a constructor, + * // the constructor also shows up in the prototype chain of the child + * // classes's prototoype, so the child classes's prototoype would also be + * // included in the result. + * console.log(queryObjects(A)); // 3 + * // [ "B { foo: 'bar', bar: 'qux' }", 'A {}', "A { foo: 'bar' }" ] + * console.log(queryObjects(A, { format: 'summary' })); + * ``` + * @param ctor The constructor that can be used to search on the prototype chain in order to filter target objects in the heap. + * @since v20.13.0 + * @experimental + */ + function queryObjects(ctor: Function): number | string[]; + function queryObjects(ctor: Function, options: { format: "count" }): number; + function queryObjects(ctor: Function, options: { format: "summary" }): string[]; + /** + * Generates a snapshot of the current V8 heap and returns a Readable + * Stream that may be used to read the JSON serialized representation. + * This JSON stream format is intended to be used with tools such as + * Chrome DevTools. The JSON schema is undocumented and specific to the + * V8 engine. Therefore, the schema may change from one version of V8 to the next. + * + * Creating a heap snapshot requires memory about twice the size of the heap at + * the time the snapshot is created. This results in the risk of OOM killers + * terminating the process. + * + * Generating a snapshot is a synchronous operation which blocks the event loop + * for a duration depending on the heap size. + * + * ```js + * // Print heap snapshot to the console + * import v8 from 'node:v8'; + * const stream = v8.getHeapSnapshot(); + * stream.pipe(process.stdout); + * ``` + * @since v11.13.0 + * @return A Readable containing the V8 heap snapshot. + */ + function getHeapSnapshot(options?: HeapSnapshotOptions): Readable; + /** + * Generates a snapshot of the current V8 heap and writes it to a JSON + * file. This file is intended to be used with tools such as Chrome + * DevTools. The JSON schema is undocumented and specific to the V8 + * engine, and may change from one version of V8 to the next. + * + * A heap snapshot is specific to a single V8 isolate. When using `worker threads`, a heap snapshot generated from the main thread will + * not contain any information about the workers, and vice versa. + * + * Creating a heap snapshot requires memory about twice the size of the heap at + * the time the snapshot is created. This results in the risk of OOM killers + * terminating the process. + * + * Generating a snapshot is a synchronous operation which blocks the event loop + * for a duration depending on the heap size. + * + * ```js + * import { writeHeapSnapshot } from 'node:v8'; + * import { + * Worker, + * isMainThread, + * parentPort, + * } from 'node:worker_threads'; + * + * if (isMainThread) { + * const worker = new Worker(__filename); + * + * worker.once('message', (filename) => { + * console.log(`worker heapdump: ${filename}`); + * // Now get a heapdump for the main thread. + * console.log(`main thread heapdump: ${writeHeapSnapshot()}`); + * }); + * + * // Tell the worker to create a heapdump. + * worker.postMessage('heapdump'); + * } else { + * parentPort.once('message', (message) => { + * if (message === 'heapdump') { + * // Generate a heapdump for the worker + * // and return the filename to the parent. + * parentPort.postMessage(writeHeapSnapshot()); + * } + * }); + * } + * ``` + * @since v11.13.0 + * @param filename The file path where the V8 heap snapshot is to be saved. If not specified, a file name with the pattern `'Heap-${yyyymmdd}-${hhmmss}-${pid}-${thread_id}.heapsnapshot'` will be + * generated, where `{pid}` will be the PID of the Node.js process, `{thread_id}` will be `0` when `writeHeapSnapshot()` is called from the main Node.js thread or the id of a + * worker thread. + * @return The filename where the snapshot was saved. + */ + function writeHeapSnapshot(filename?: string, options?: HeapSnapshotOptions): string; + /** + * Get statistics about code and its metadata in the heap, see + * V8 [`GetHeapCodeAndMetadataStatistics`](https://v8docs.nodesource.com/node-13.2/d5/dda/classv8_1_1_isolate.html#a6079122af17612ef54ef3348ce170866) API. Returns an object with the + * following properties: + * + * ```js + * { + * code_and_metadata_size: 212208, + * bytecode_and_metadata_size: 161368, + * external_script_source_size: 1410794, + * cpu_profiler_metadata_size: 0, + * } + * ``` + * @since v12.8.0 + */ + function getHeapCodeStatistics(): HeapCodeStatistics; + /** + * @since v25.0.0 + */ + interface SyncCPUProfileHandle { + /** + * Stopping collecting the profile and return the profile data. + * @since v25.0.0 + */ + stop(): string; + /** + * Stopping collecting the profile and the profile will be discarded. + * @since v25.0.0 + */ + [Symbol.dispose](): void; + } + /** + * @since v24.8.0 + */ + interface CPUProfileHandle { + /** + * Stopping collecting the profile, then return a Promise that fulfills with an error or the + * profile data. + * @since v24.8.0 + */ + stop(): Promise<string>; + /** + * Stopping collecting the profile and the profile will be discarded. + * @since v24.8.0 + */ + [Symbol.asyncDispose](): Promise<void>; + } + /** + * @since v24.9.0 + */ + interface HeapProfileHandle { + /** + * Stopping collecting the profile, then return a Promise that fulfills with an error or the + * profile data. + * @since v24.9.0 + */ + stop(): Promise<string>; + /** + * Stopping collecting the profile and the profile will be discarded. + * @since v24.9.0 + */ + [Symbol.asyncDispose](): Promise<void>; + } + /** + * Starting a CPU profile then return a `SyncCPUProfileHandle` object. + * This API supports `using` syntax. + * + * ```js + * const handle = v8.startCpuProfile(); + * const profile = handle.stop(); + * console.log(profile); + * ``` + * @since v25.0.0 + */ + function startCPUProfile(): SyncCPUProfileHandle; + /** + * V8 only supports `Latin-1/ISO-8859-1` and `UTF16` as the underlying representation of a string. + * If the `content` uses `Latin-1/ISO-8859-1` as the underlying representation, this function will return true; + * otherwise, it returns false. + * + * If this method returns false, that does not mean that the string contains some characters not in `Latin-1/ISO-8859-1`. + * Sometimes a `Latin-1` string may also be represented as `UTF16`. + * + * ```js + * const { isStringOneByteRepresentation } = require('node:v8'); + * + * const Encoding = { + * latin1: 1, + * utf16le: 2, + * }; + * const buffer = Buffer.alloc(100); + * function writeString(input) { + * if (isStringOneByteRepresentation(input)) { + * buffer.writeUint8(Encoding.latin1); + * buffer.writeUint32LE(input.length, 1); + * buffer.write(input, 5, 'latin1'); + * } else { + * buffer.writeUint8(Encoding.utf16le); + * buffer.writeUint32LE(input.length * 2, 1); + * buffer.write(input, 5, 'utf16le'); + * } + * } + * writeString('hello'); + * writeString('你好'); + * ``` + * @since v23.10.0, v22.15.0 + */ + function isStringOneByteRepresentation(content: string): boolean; + /** + * @since v8.0.0 + */ + class Serializer { + /** + * Writes out a header, which includes the serialization format version. + */ + writeHeader(): void; + /** + * Serializes a JavaScript value and adds the serialized representation to the + * internal buffer. + * + * This throws an error if `value` cannot be serialized. + */ + writeValue(val: any): boolean; + /** + * Returns the stored internal buffer. This serializer should not be used once + * the buffer is released. Calling this method results in undefined behavior + * if a previous write has failed. + */ + releaseBuffer(): NonSharedBuffer; + /** + * Marks an `ArrayBuffer` as having its contents transferred out of band. + * Pass the corresponding `ArrayBuffer` in the deserializing context to `deserializer.transferArrayBuffer()`. + * @param id A 32-bit unsigned integer. + * @param arrayBuffer An `ArrayBuffer` instance. + */ + transferArrayBuffer(id: number, arrayBuffer: ArrayBuffer): void; + /** + * Write a raw 32-bit unsigned integer. + * For use inside of a custom `serializer._writeHostObject()`. + */ + writeUint32(value: number): void; + /** + * Write a raw 64-bit unsigned integer, split into high and low 32-bit parts. + * For use inside of a custom `serializer._writeHostObject()`. + */ + writeUint64(hi: number, lo: number): void; + /** + * Write a JS `number` value. + * For use inside of a custom `serializer._writeHostObject()`. + */ + writeDouble(value: number): void; + /** + * Write raw bytes into the serializer's internal buffer. The deserializer + * will require a way to compute the length of the buffer. + * For use inside of a custom `serializer._writeHostObject()`. + */ + writeRawBytes(buffer: NodeJS.ArrayBufferView): void; + } + /** + * A subclass of `Serializer` that serializes `TypedArray`(in particular `Buffer`) and `DataView` objects as host objects, and only + * stores the part of their underlying `ArrayBuffer`s that they are referring to. + * @since v8.0.0 + */ + class DefaultSerializer extends Serializer {} + /** + * @since v8.0.0 + */ + class Deserializer { + constructor(data: NodeJS.TypedArray); + /** + * Reads and validates a header (including the format version). + * May, for example, reject an invalid or unsupported wire format. In that case, + * an `Error` is thrown. + */ + readHeader(): boolean; + /** + * Deserializes a JavaScript value from the buffer and returns it. + */ + readValue(): any; + /** + * Marks an `ArrayBuffer` as having its contents transferred out of band. + * Pass the corresponding `ArrayBuffer` in the serializing context to `serializer.transferArrayBuffer()` (or return the `id` from `serializer._getSharedArrayBufferId()` in the case of + * `SharedArrayBuffer`s). + * @param id A 32-bit unsigned integer. + * @param arrayBuffer An `ArrayBuffer` instance. + */ + transferArrayBuffer(id: number, arrayBuffer: ArrayBuffer): void; + /** + * Reads the underlying wire format version. Likely mostly to be useful to + * legacy code reading old wire format versions. May not be called before `.readHeader()`. + */ + getWireFormatVersion(): number; + /** + * Read a raw 32-bit unsigned integer and return it. + * For use inside of a custom `deserializer._readHostObject()`. + */ + readUint32(): number; + /** + * Read a raw 64-bit unsigned integer and return it as an array `[hi, lo]` with two 32-bit unsigned integer entries. + * For use inside of a custom `deserializer._readHostObject()`. + */ + readUint64(): [number, number]; + /** + * Read a JS `number` value. + * For use inside of a custom `deserializer._readHostObject()`. + */ + readDouble(): number; + /** + * Read raw bytes from the deserializer's internal buffer. The `length` parameter + * must correspond to the length of the buffer that was passed to `serializer.writeRawBytes()`. + * For use inside of a custom `deserializer._readHostObject()`. + */ + readRawBytes(length: number): Buffer; + } + /** + * A subclass of `Deserializer` corresponding to the format written by `DefaultSerializer`. + * @since v8.0.0 + */ + class DefaultDeserializer extends Deserializer {} + /** + * Uses a `DefaultSerializer` to serialize `value` into a buffer. + * + * `ERR_BUFFER_TOO_LARGE` will be thrown when trying to + * serialize a huge object which requires buffer + * larger than `buffer.constants.MAX_LENGTH`. + * @since v8.0.0 + */ + function serialize(value: any): NonSharedBuffer; + /** + * Uses a `DefaultDeserializer` with default options to read a JS value + * from a buffer. + * @since v8.0.0 + * @param buffer A buffer returned by {@link serialize}. + */ + function deserialize(buffer: NodeJS.ArrayBufferView): any; + /** + * The `v8.takeCoverage()` method allows the user to write the coverage started by `NODE_V8_COVERAGE` to disk on demand. This method can be invoked multiple + * times during the lifetime of the process. Each time the execution counter will + * be reset and a new coverage report will be written to the directory specified + * by `NODE_V8_COVERAGE`. + * + * When the process is about to exit, one last coverage will still be written to + * disk unless {@link stopCoverage} is invoked before the process exits. + * @since v15.1.0, v14.18.0, v12.22.0 + */ + function takeCoverage(): void; + /** + * The `v8.stopCoverage()` method allows the user to stop the coverage collection + * started by `NODE_V8_COVERAGE`, so that V8 can release the execution count + * records and optimize code. This can be used in conjunction with {@link takeCoverage} if the user wants to collect the coverage on demand. + * @since v15.1.0, v14.18.0, v12.22.0 + */ + function stopCoverage(): void; + /** + * The API is a no-op if `--heapsnapshot-near-heap-limit` is already set from the command line or the API is called more than once. + * `limit` must be a positive integer. See [`--heapsnapshot-near-heap-limit`](https://nodejs.org/docs/latest-v25.x/api/cli.html#--heapsnapshot-near-heap-limitmax_count) for more information. + * @since v18.10.0, v16.18.0 + */ + function setHeapSnapshotNearHeapLimit(limit: number): void; + /** + * This API collects GC data in current thread. + * @since v19.6.0, v18.15.0 + */ + class GCProfiler { + /** + * Start collecting GC data. + * @since v19.6.0, v18.15.0 + */ + start(): void; + /** + * Stop collecting GC data and return an object. The content of object + * is as follows. + * + * ```json + * { + * "version": 1, + * "startTime": 1674059033862, + * "statistics": [ + * { + * "gcType": "Scavenge", + * "beforeGC": { + * "heapStatistics": { + * "totalHeapSize": 5005312, + * "totalHeapSizeExecutable": 524288, + * "totalPhysicalSize": 5226496, + * "totalAvailableSize": 4341325216, + * "totalGlobalHandlesSize": 8192, + * "usedGlobalHandlesSize": 2112, + * "usedHeapSize": 4883840, + * "heapSizeLimit": 4345298944, + * "mallocedMemory": 254128, + * "externalMemory": 225138, + * "peakMallocedMemory": 181760 + * }, + * "heapSpaceStatistics": [ + * { + * "spaceName": "read_only_space", + * "spaceSize": 0, + * "spaceUsedSize": 0, + * "spaceAvailableSize": 0, + * "physicalSpaceSize": 0 + * } + * ] + * }, + * "cost": 1574.14, + * "afterGC": { + * "heapStatistics": { + * "totalHeapSize": 6053888, + * "totalHeapSizeExecutable": 524288, + * "totalPhysicalSize": 5500928, + * "totalAvailableSize": 4341101384, + * "totalGlobalHandlesSize": 8192, + * "usedGlobalHandlesSize": 2112, + * "usedHeapSize": 4059096, + * "heapSizeLimit": 4345298944, + * "mallocedMemory": 254128, + * "externalMemory": 225138, + * "peakMallocedMemory": 181760 + * }, + * "heapSpaceStatistics": [ + * { + * "spaceName": "read_only_space", + * "spaceSize": 0, + * "spaceUsedSize": 0, + * "spaceAvailableSize": 0, + * "physicalSpaceSize": 0 + * } + * ] + * } + * } + * ], + * "endTime": 1674059036865 + * } + * ``` + * + * Here's an example. + * + * ```js + * import { GCProfiler } from 'node:v8'; + * const profiler = new GCProfiler(); + * profiler.start(); + * setTimeout(() => { + * console.log(profiler.stop()); + * }, 1000); + * ``` + * @since v19.6.0, v18.15.0 + */ + stop(): GCProfilerResult; + } + interface GCProfilerResult { + version: number; + startTime: number; + endTime: number; + statistics: Array<{ + gcType: string; + cost: number; + beforeGC: { + heapStatistics: HeapStatistics; + heapSpaceStatistics: HeapSpaceStatistics[]; + }; + afterGC: { + heapStatistics: HeapStatistics; + heapSpaceStatistics: HeapSpaceStatistics[]; + }; + }>; + } + interface HeapStatistics { + totalHeapSize: number; + totalHeapSizeExecutable: number; + totalPhysicalSize: number; + totalAvailableSize: number; + totalGlobalHandlesSize: number; + usedGlobalHandlesSize: number; + usedHeapSize: number; + heapSizeLimit: number; + mallocedMemory: number; + externalMemory: number; + peakMallocedMemory: number; + } + interface HeapSpaceStatistics { + spaceName: string; + spaceSize: number; + spaceUsedSize: number; + spaceAvailableSize: number; + physicalSpaceSize: number; + } + /** + * Called when a promise is constructed. This does not mean that corresponding before/after events will occur, only that the possibility exists. This will + * happen if a promise is created without ever getting a continuation. + * @since v17.1.0, v16.14.0 + * @param promise The promise being created. + * @param parent The promise continued from, if applicable. + */ + interface Init { + (promise: Promise<unknown>, parent: Promise<unknown>): void; + } + /** + * Called before a promise continuation executes. This can be in the form of `then()`, `catch()`, or `finally()` handlers or an await resuming. + * + * The before callback will be called 0 to N times. The before callback will typically be called 0 times if no continuation was ever made for the promise. + * The before callback may be called many times in the case where many continuations have been made from the same promise. + * @since v17.1.0, v16.14.0 + */ + interface Before { + (promise: Promise<unknown>): void; + } + /** + * Called immediately after a promise continuation executes. This may be after a `then()`, `catch()`, or `finally()` handler or before an await after another await. + * @since v17.1.0, v16.14.0 + */ + interface After { + (promise: Promise<unknown>): void; + } + /** + * Called when the promise receives a resolution or rejection value. This may occur synchronously in the case of {@link Promise.resolve()} or + * {@link Promise.reject()}. + * @since v17.1.0, v16.14.0 + */ + interface Settled { + (promise: Promise<unknown>): void; + } + /** + * Key events in the lifetime of a promise have been categorized into four areas: creation of a promise, before/after a continuation handler is called or + * around an await, and when the promise resolves or rejects. + * + * Because promises are asynchronous resources whose lifecycle is tracked via the promise hooks mechanism, the `init()`, `before()`, `after()`, and + * `settled()` callbacks must not be async functions as they create more promises which would produce an infinite loop. + * @since v17.1.0, v16.14.0 + */ + interface HookCallbacks { + init?: Init; + before?: Before; + after?: After; + settled?: Settled; + } + interface PromiseHooks { + /** + * The `init` hook must be a plain function. Providing an async function will throw as it would produce an infinite microtask loop. + * @since v17.1.0, v16.14.0 + * @param init The {@link Init | `init` callback} to call when a promise is created. + * @return Call to stop the hook. + */ + onInit: (init: Init) => Function; + /** + * The `settled` hook must be a plain function. Providing an async function will throw as it would produce an infinite microtask loop. + * @since v17.1.0, v16.14.0 + * @param settled The {@link Settled | `settled` callback} to call when a promise is created. + * @return Call to stop the hook. + */ + onSettled: (settled: Settled) => Function; + /** + * The `before` hook must be a plain function. Providing an async function will throw as it would produce an infinite microtask loop. + * @since v17.1.0, v16.14.0 + * @param before The {@link Before | `before` callback} to call before a promise continuation executes. + * @return Call to stop the hook. + */ + onBefore: (before: Before) => Function; + /** + * The `after` hook must be a plain function. Providing an async function will throw as it would produce an infinite microtask loop. + * @since v17.1.0, v16.14.0 + * @param after The {@link After | `after` callback} to call after a promise continuation executes. + * @return Call to stop the hook. + */ + onAfter: (after: After) => Function; + /** + * Registers functions to be called for different lifetime events of each promise. + * The callbacks `init()`/`before()`/`after()`/`settled()` are called for the respective events during a promise's lifetime. + * All callbacks are optional. For example, if only promise creation needs to be tracked, then only the init callback needs to be passed. + * The hook callbacks must be plain functions. Providing async functions will throw as it would produce an infinite microtask loop. + * @since v17.1.0, v16.14.0 + * @param callbacks The {@link HookCallbacks | Hook Callbacks} to register + * @return Used for disabling hooks + */ + createHook: (callbacks: HookCallbacks) => Function; + } + /** + * The `promiseHooks` interface can be used to track promise lifecycle events. + * @since v17.1.0, v16.14.0 + */ + const promiseHooks: PromiseHooks; + type StartupSnapshotCallbackFn = (args: any) => any; + /** + * The `v8.startupSnapshot` interface can be used to add serialization and deserialization hooks for custom startup snapshots. + * + * ```bash + * $ node --snapshot-blob snapshot.blob --build-snapshot entry.js + * # This launches a process with the snapshot + * $ node --snapshot-blob snapshot.blob + * ``` + * + * In the example above, `entry.js` can use methods from the `v8.startupSnapshot` interface to specify how to save information for custom objects + * in the snapshot during serialization and how the information can be used to synchronize these objects during deserialization of the snapshot. + * For example, if the `entry.js` contains the following script: + * + * ```js + * 'use strict'; + * + * import fs from 'node:fs'; + * import zlib from 'node:zlib'; + * import path from 'node:path'; + * import assert from 'node:assert'; + * + * import v8 from 'node:v8'; + * + * class BookShelf { + * storage = new Map(); + * + * // Reading a series of files from directory and store them into storage. + * constructor(directory, books) { + * for (const book of books) { + * this.storage.set(book, fs.readFileSync(path.join(directory, book))); + * } + * } + * + * static compressAll(shelf) { + * for (const [ book, content ] of shelf.storage) { + * shelf.storage.set(book, zlib.gzipSync(content)); + * } + * } + * + * static decompressAll(shelf) { + * for (const [ book, content ] of shelf.storage) { + * shelf.storage.set(book, zlib.gunzipSync(content)); + * } + * } + * } + * + * // __dirname here is where the snapshot script is placed + * // during snapshot building time. + * const shelf = new BookShelf(__dirname, [ + * 'book1.en_US.txt', + * 'book1.es_ES.txt', + * 'book2.zh_CN.txt', + * ]); + * + * assert(v8.startupSnapshot.isBuildingSnapshot()); + * // On snapshot serialization, compress the books to reduce size. + * v8.startupSnapshot.addSerializeCallback(BookShelf.compressAll, shelf); + * // On snapshot deserialization, decompress the books. + * v8.startupSnapshot.addDeserializeCallback(BookShelf.decompressAll, shelf); + * v8.startupSnapshot.setDeserializeMainFunction((shelf) => { + * // process.env and process.argv are refreshed during snapshot + * // deserialization. + * const lang = process.env.BOOK_LANG || 'en_US'; + * const book = process.argv[1]; + * const name = `${book}.${lang}.txt`; + * console.log(shelf.storage.get(name)); + * }, shelf); + * ``` + * + * The resulted binary will get print the data deserialized from the snapshot during start up, using the refreshed `process.env` and `process.argv` of the launched process: + * + * ```bash + * $ BOOK_LANG=es_ES node --snapshot-blob snapshot.blob book1 + * # Prints content of book1.es_ES.txt deserialized from the snapshot. + * ``` + * + * Currently the application deserialized from a user-land snapshot cannot be snapshotted again, so these APIs are only available to applications that are not deserialized from a user-land snapshot. + * + * @since v18.6.0, v16.17.0 + */ + namespace startupSnapshot { + /** + * Add a callback that will be called when the Node.js instance is about to get serialized into a snapshot and exit. + * This can be used to release resources that should not or cannot be serialized or to convert user data into a form more suitable for serialization. + * @since v18.6.0, v16.17.0 + */ + function addSerializeCallback(callback: StartupSnapshotCallbackFn, data?: any): void; + /** + * Add a callback that will be called when the Node.js instance is deserialized from a snapshot. + * The `callback` and the `data` (if provided) will be serialized into the snapshot, they can be used to re-initialize the state of the application or + * to re-acquire resources that the application needs when the application is restarted from the snapshot. + * @since v18.6.0, v16.17.0 + */ + function addDeserializeCallback(callback: StartupSnapshotCallbackFn, data?: any): void; + /** + * This sets the entry point of the Node.js application when it is deserialized from a snapshot. This can be called only once in the snapshot building script. + * If called, the deserialized application no longer needs an additional entry point script to start up and will simply invoke the callback along with the deserialized + * data (if provided), otherwise an entry point script still needs to be provided to the deserialized application. + * @since v18.6.0, v16.17.0 + */ + function setDeserializeMainFunction(callback: StartupSnapshotCallbackFn, data?: any): void; + /** + * Returns true if the Node.js instance is run to build a snapshot. + * @since v18.6.0, v16.17.0 + */ + function isBuildingSnapshot(): boolean; + } +} +declare module "v8" { + export * from "node:v8"; +} diff --git a/server/node_modules/@types/node/vm.d.ts b/server/node_modules/@types/node/vm.d.ts new file mode 100644 index 0000000..d5e437e --- /dev/null +++ b/server/node_modules/@types/node/vm.d.ts @@ -0,0 +1,1208 @@ +/** + * The `node:vm` module enables compiling and running code within V8 Virtual + * Machine contexts. + * + * **The `node:vm` module is not a security** + * **mechanism. Do not use it to run untrusted code.** + * + * JavaScript code can be compiled and run immediately or + * compiled, saved, and run later. + * + * A common use case is to run the code in a different V8 Context. This means + * invoked code has a different global object than the invoking code. + * + * One can provide the context by `contextifying` an + * object. The invoked code treats any property in the context like a + * global variable. Any changes to global variables caused by the invoked + * code are reflected in the context object. + * + * ```js + * import vm from 'node:vm'; + * + * const x = 1; + * + * const context = { x: 2 }; + * vm.createContext(context); // Contextify the object. + * + * const code = 'x += 40; var y = 17;'; + * // `x` and `y` are global variables in the context. + * // Initially, x has the value 2 because that is the value of context.x. + * vm.runInContext(code, context); + * + * console.log(context.x); // 42 + * console.log(context.y); // 17 + * + * console.log(x); // 1; y is not defined. + * ``` + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/vm.js) + */ +declare module "node:vm" { + import { NonSharedBuffer } from "node:buffer"; + import { ImportAttributes, ImportPhase } from "node:module"; + interface Context extends NodeJS.Dict<any> {} + interface BaseOptions { + /** + * Specifies the filename used in stack traces produced by this script. + * @default '' + */ + filename?: string | undefined; + /** + * Specifies the line number offset that is displayed in stack traces produced by this script. + * @default 0 + */ + lineOffset?: number | undefined; + /** + * Specifies the column number offset that is displayed in stack traces produced by this script. + * @default 0 + */ + columnOffset?: number | undefined; + } + type DynamicModuleLoader<T> = ( + specifier: string, + referrer: T, + importAttributes: ImportAttributes, + phase: ImportPhase, + ) => Module | Promise<Module>; + interface ScriptOptions extends BaseOptions { + /** + * Provides an optional data with V8's code cache data for the supplied source. + */ + cachedData?: NodeJS.ArrayBufferView | undefined; + /** @deprecated in favor of `script.createCachedData()` */ + produceCachedData?: boolean | undefined; + /** + * Used to specify how the modules should be loaded during the evaluation of this script when `import()` is called. This option is + * part of the experimental modules API. We do not recommend using it in a production environment. For detailed information, see + * [Support of dynamic `import()` in compilation APIs](https://nodejs.org/docs/latest-v25.x/api/vm.html#support-of-dynamic-import-in-compilation-apis). + * @experimental + */ + importModuleDynamically?: + | DynamicModuleLoader<Script> + | typeof constants.USE_MAIN_CONTEXT_DEFAULT_LOADER + | undefined; + } + interface RunningScriptOptions extends BaseOptions { + /** + * When `true`, if an `Error` occurs while compiling the `code`, the line of code causing the error is attached to the stack trace. + * @default true + */ + displayErrors?: boolean | undefined; + /** + * Specifies the number of milliseconds to execute code before terminating execution. + * If execution is terminated, an `Error` will be thrown. This value must be a strictly positive integer. + */ + timeout?: number | undefined; + /** + * If `true`, the execution will be terminated when `SIGINT` (Ctrl+C) is received. + * Existing handlers for the event that have been attached via `process.on('SIGINT')` will be disabled during script execution, but will continue to work after that. + * If execution is terminated, an `Error` will be thrown. + * @default false + */ + breakOnSigint?: boolean | undefined; + } + interface RunningScriptInNewContextOptions + extends RunningScriptOptions, Pick<CreateContextOptions, "microtaskMode"> + { + /** + * Human-readable name of the newly created context. + */ + contextName?: CreateContextOptions["name"] | undefined; + /** + * Origin corresponding to the newly created context for display purposes. The origin should be formatted like a URL, + * but with only the scheme, host, and port (if necessary), like the value of the `url.origin` property of a `URL` object. + * Most notably, this string should omit the trailing slash, as that denotes a path. + */ + contextOrigin?: CreateContextOptions["origin"] | undefined; + contextCodeGeneration?: CreateContextOptions["codeGeneration"] | undefined; + } + interface RunningCodeOptions extends RunningScriptOptions, Pick<ScriptOptions, "cachedData"> { + /** + * Used to specify how the modules should be loaded during the evaluation of this script when `import()` is called. This option is + * part of the experimental modules API. We do not recommend using it in a production environment. For detailed information, see + * [Support of dynamic `import()` in compilation APIs](https://nodejs.org/docs/latest-v25.x/api/vm.html#support-of-dynamic-import-in-compilation-apis). + * @experimental + */ + importModuleDynamically?: + | DynamicModuleLoader<Script> + | typeof constants.USE_MAIN_CONTEXT_DEFAULT_LOADER + | undefined; + } + interface RunningCodeInNewContextOptions + extends RunningScriptInNewContextOptions, Pick<ScriptOptions, "cachedData"> + { + /** + * Used to specify how the modules should be loaded during the evaluation of this script when `import()` is called. This option is + * part of the experimental modules API. We do not recommend using it in a production environment. For detailed information, see + * [Support of dynamic `import()` in compilation APIs](https://nodejs.org/docs/latest-v25.x/api/vm.html#support-of-dynamic-import-in-compilation-apis). + * @experimental + */ + importModuleDynamically?: + | DynamicModuleLoader<Script> + | typeof constants.USE_MAIN_CONTEXT_DEFAULT_LOADER + | undefined; + } + interface CompileFunctionOptions extends BaseOptions, Pick<ScriptOptions, "cachedData" | "produceCachedData"> { + /** + * The sandbox/context in which the said function should be compiled in. + */ + parsingContext?: Context | undefined; + /** + * An array containing a collection of context extensions (objects wrapping the current scope) to be applied while compiling + */ + contextExtensions?: Object[] | undefined; + /** + * Used to specify how the modules should be loaded during the evaluation of this script when `import()` is called. This option is + * part of the experimental modules API. We do not recommend using it in a production environment. For detailed information, see + * [Support of dynamic `import()` in compilation APIs](https://nodejs.org/docs/latest-v25.x/api/vm.html#support-of-dynamic-import-in-compilation-apis). + * @experimental + */ + importModuleDynamically?: + | DynamicModuleLoader<ReturnType<typeof compileFunction>> + | typeof constants.USE_MAIN_CONTEXT_DEFAULT_LOADER + | undefined; + } + interface CreateContextOptions { + /** + * Human-readable name of the newly created context. + * @default 'VM Context i' Where i is an ascending numerical index of the created context. + */ + name?: string | undefined; + /** + * Corresponds to the newly created context for display purposes. + * The origin should be formatted like a `URL`, but with only the scheme, host, and port (if necessary), + * like the value of the `url.origin` property of a URL object. + * Most notably, this string should omit the trailing slash, as that denotes a path. + * @default '' + */ + origin?: string | undefined; + codeGeneration?: + | { + /** + * If set to false any calls to eval or function constructors (Function, GeneratorFunction, etc) + * will throw an EvalError. + * @default true + */ + strings?: boolean | undefined; + /** + * If set to false any attempt to compile a WebAssembly module will throw a WebAssembly.CompileError. + * @default true + */ + wasm?: boolean | undefined; + } + | undefined; + /** + * If set to `afterEvaluate`, microtasks will be run immediately after the script has run. + */ + microtaskMode?: "afterEvaluate" | undefined; + /** + * Used to specify how the modules should be loaded during the evaluation of this script when `import()` is called. This option is + * part of the experimental modules API. We do not recommend using it in a production environment. For detailed information, see + * [Support of dynamic `import()` in compilation APIs](https://nodejs.org/docs/latest-v25.x/api/vm.html#support-of-dynamic-import-in-compilation-apis). + * @experimental + */ + importModuleDynamically?: + | DynamicModuleLoader<Context> + | typeof constants.USE_MAIN_CONTEXT_DEFAULT_LOADER + | undefined; + } + type MeasureMemoryMode = "summary" | "detailed"; + interface MeasureMemoryOptions { + /** + * @default 'summary' + */ + mode?: MeasureMemoryMode | undefined; + /** + * @default 'default' + */ + execution?: "default" | "eager" | undefined; + } + interface MemoryMeasurement { + total: { + jsMemoryEstimate: number; + jsMemoryRange: [number, number]; + }; + } + /** + * Instances of the `vm.Script` class contain precompiled scripts that can be + * executed in specific contexts. + * @since v0.3.1 + */ + class Script { + constructor(code: string, options?: ScriptOptions | string); + /** + * Runs the compiled code contained by the `vm.Script` object within the given `contextifiedObject` and returns the result. Running code does not have access + * to local scope. + * + * The following example compiles code that increments a global variable, sets + * the value of another global variable, then execute the code multiple times. + * The globals are contained in the `context` object. + * + * ```js + * import vm from 'node:vm'; + * + * const context = { + * animal: 'cat', + * count: 2, + * }; + * + * const script = new vm.Script('count += 1; name = "kitty";'); + * + * vm.createContext(context); + * for (let i = 0; i < 10; ++i) { + * script.runInContext(context); + * } + * + * console.log(context); + * // Prints: { animal: 'cat', count: 12, name: 'kitty' } + * ``` + * + * Using the `timeout` or `breakOnSigint` options will result in new event loops + * and corresponding threads being started, which have a non-zero performance + * overhead. + * @since v0.3.1 + * @param contextifiedObject A `contextified` object as returned by the `vm.createContext()` method. + * @return the result of the very last statement executed in the script. + */ + runInContext(contextifiedObject: Context, options?: RunningScriptOptions): any; + /** + * This method is a shortcut to `script.runInContext(vm.createContext(options), options)`. + * It does several things at once: + * + * 1. Creates a new context. + * 2. If `contextObject` is an object, contextifies it with the new context. + * If `contextObject` is undefined, creates a new object and contextifies it. + * If `contextObject` is `vm.constants.DONT_CONTEXTIFY`, don't contextify anything. + * 3. Runs the compiled code contained by the `vm.Script` object within the created context. The code + * does not have access to the scope in which this method is called. + * 4. Returns the result. + * + * The following example compiles code that sets a global variable, then executes + * the code multiple times in different contexts. The globals are set on and + * contained within each individual `context`. + * + * ```js + * const vm = require('node:vm'); + * + * const script = new vm.Script('globalVar = "set"'); + * + * const contexts = [{}, {}, {}]; + * contexts.forEach((context) => { + * script.runInNewContext(context); + * }); + * + * console.log(contexts); + * // Prints: [{ globalVar: 'set' }, { globalVar: 'set' }, { globalVar: 'set' }] + * + * // This would throw if the context is created from a contextified object. + * // vm.constants.DONT_CONTEXTIFY allows creating contexts with ordinary + * // global objects that can be frozen. + * const freezeScript = new vm.Script('Object.freeze(globalThis); globalThis;'); + * const frozenContext = freezeScript.runInNewContext(vm.constants.DONT_CONTEXTIFY); + * ``` + * @since v0.3.1 + * @param contextObject Either `vm.constants.DONT_CONTEXTIFY` or an object that will be contextified. + * If `undefined`, an empty contextified object will be created for backwards compatibility. + * @return the result of the very last statement executed in the script. + */ + runInNewContext( + contextObject?: Context | typeof constants.DONT_CONTEXTIFY, + options?: RunningScriptInNewContextOptions, + ): any; + /** + * Runs the compiled code contained by the `vm.Script` within the context of the + * current `global` object. Running code does not have access to local scope, but _does_ have access to the current `global` object. + * + * The following example compiles code that increments a `global` variable then + * executes that code multiple times: + * + * ```js + * import vm from 'node:vm'; + * + * global.globalVar = 0; + * + * const script = new vm.Script('globalVar += 1', { filename: 'myfile.vm' }); + * + * for (let i = 0; i < 1000; ++i) { + * script.runInThisContext(); + * } + * + * console.log(globalVar); + * + * // 1000 + * ``` + * @since v0.3.1 + * @return the result of the very last statement executed in the script. + */ + runInThisContext(options?: RunningScriptOptions): any; + /** + * Creates a code cache that can be used with the `Script` constructor's `cachedData` option. Returns a `Buffer`. This method may be called at any + * time and any number of times. + * + * The code cache of the `Script` doesn't contain any JavaScript observable + * states. The code cache is safe to be saved along side the script source and + * used to construct new `Script` instances multiple times. + * + * Functions in the `Script` source can be marked as lazily compiled and they are + * not compiled at construction of the `Script`. These functions are going to be + * compiled when they are invoked the first time. The code cache serializes the + * metadata that V8 currently knows about the `Script` that it can use to speed up + * future compilations. + * + * ```js + * const script = new vm.Script(` + * function add(a, b) { + * return a + b; + * } + * + * const x = add(1, 2); + * `); + * + * const cacheWithoutAdd = script.createCachedData(); + * // In `cacheWithoutAdd` the function `add()` is marked for full compilation + * // upon invocation. + * + * script.runInThisContext(); + * + * const cacheWithAdd = script.createCachedData(); + * // `cacheWithAdd` contains fully compiled function `add()`. + * ``` + * @since v10.6.0 + */ + createCachedData(): NonSharedBuffer; + /** @deprecated in favor of `script.createCachedData()` */ + cachedDataProduced?: boolean; + /** + * When `cachedData` is supplied to create the `vm.Script`, this value will be set + * to either `true` or `false` depending on acceptance of the data by V8. + * Otherwise the value is `undefined`. + * @since v5.7.0 + */ + cachedDataRejected?: boolean; + cachedData?: NonSharedBuffer; + /** + * When the script is compiled from a source that contains a source map magic + * comment, this property will be set to the URL of the source map. + * + * ```js + * import vm from 'node:vm'; + * + * const script = new vm.Script(` + * function myFunc() {} + * //# sourceMappingURL=sourcemap.json + * `); + * + * console.log(script.sourceMapURL); + * // Prints: sourcemap.json + * ``` + * @since v19.1.0, v18.13.0 + */ + sourceMapURL: string | undefined; + } + /** + * If the given `contextObject` is an object, the `vm.createContext()` method will + * [prepare that object](https://nodejs.org/docs/latest-v25.x/api/vm.html#what-does-it-mean-to-contextify-an-object) + * and return a reference to it so that it can be used in calls to {@link runInContext} or + * [`script.runInContext()`](https://nodejs.org/docs/latest-v25.x/api/vm.html#scriptrunincontextcontextifiedobject-options). + * Inside such scripts, the global object will be wrapped by the `contextObject`, retaining all of its + * existing properties but also having the built-in objects and functions any standard + * [global object](https://es5.github.io/#x15.1) has. Outside of scripts run by the vm module, global + * variables will remain unchanged. + * + * ```js + * const vm = require('node:vm'); + * + * global.globalVar = 3; + * + * const context = { globalVar: 1 }; + * vm.createContext(context); + * + * vm.runInContext('globalVar *= 2;', context); + * + * console.log(context); + * // Prints: { globalVar: 2 } + * + * console.log(global.globalVar); + * // Prints: 3 + * ``` + * + * If `contextObject` is omitted (or passed explicitly as `undefined`), a new, + * empty contextified object will be returned. + * + * When the global object in the newly created context is contextified, it has some quirks + * compared to ordinary global objects. For example, it cannot be frozen. To create a context + * without the contextifying quirks, pass `vm.constants.DONT_CONTEXTIFY` as the `contextObject` + * argument. See the documentation of `vm.constants.DONT_CONTEXTIFY` for details. + * + * The `vm.createContext()` method is primarily useful for creating a single + * context that can be used to run multiple scripts. For instance, if emulating a + * web browser, the method can be used to create a single context representing a + * window's global object, then run all `<script>` tags together within that + * context. + * + * The provided `name` and `origin` of the context are made visible through the + * Inspector API. + * @since v0.3.1 + * @param contextObject Either `vm.constants.DONT_CONTEXTIFY` or an object that will be contextified. + * If `undefined`, an empty contextified object will be created for backwards compatibility. + * @return contextified object. + */ + function createContext( + contextObject?: Context | typeof constants.DONT_CONTEXTIFY, + options?: CreateContextOptions, + ): Context; + /** + * Returns `true` if the given `object` object has been contextified using {@link createContext}, + * or if it's the global object of a context created using `vm.constants.DONT_CONTEXTIFY`. + * @since v0.11.7 + */ + function isContext(sandbox: Context): boolean; + /** + * The `vm.runInContext()` method compiles `code`, runs it within the context of + * the `contextifiedObject`, then returns the result. Running code does not have + * access to the local scope. The `contextifiedObject` object _must_ have been + * previously `contextified` using the {@link createContext} method. + * + * If `options` is a string, then it specifies the filename. + * + * The following example compiles and executes different scripts using a single `contextified` object: + * + * ```js + * import vm from 'node:vm'; + * + * const contextObject = { globalVar: 1 }; + * vm.createContext(contextObject); + * + * for (let i = 0; i < 10; ++i) { + * vm.runInContext('globalVar *= 2;', contextObject); + * } + * console.log(contextObject); + * // Prints: { globalVar: 1024 } + * ``` + * @since v0.3.1 + * @param code The JavaScript code to compile and run. + * @param contextifiedObject The `contextified` object that will be used as the `global` when the `code` is compiled and run. + * @return the result of the very last statement executed in the script. + */ + function runInContext(code: string, contextifiedObject: Context, options?: RunningCodeOptions | string): any; + /** + * This method is a shortcut to + * `(new vm.Script(code, options)).runInContext(vm.createContext(options), options)`. + * If `options` is a string, then it specifies the filename. + * + * It does several things at once: + * + * 1. Creates a new context. + * 2. If `contextObject` is an object, contextifies it with the new context. + * If `contextObject` is undefined, creates a new object and contextifies it. + * If `contextObject` is `vm.constants.DONT_CONTEXTIFY`, don't contextify anything. + * 3. Compiles the code as a`vm.Script` + * 4. Runs the compield code within the created context. The code does not have access to the scope in + * which this method is called. + * 5. Returns the result. + * + * The following example compiles and executes code that increments a global + * variable and sets a new one. These globals are contained in the `contextObject`. + * + * ```js + * const vm = require('node:vm'); + * + * const contextObject = { + * animal: 'cat', + * count: 2, + * }; + * + * vm.runInNewContext('count += 1; name = "kitty"', contextObject); + * console.log(contextObject); + * // Prints: { animal: 'cat', count: 3, name: 'kitty' } + * + * // This would throw if the context is created from a contextified object. + * // vm.constants.DONT_CONTEXTIFY allows creating contexts with ordinary global objects that + * // can be frozen. + * const frozenContext = vm.runInNewContext('Object.freeze(globalThis); globalThis;', vm.constants.DONT_CONTEXTIFY); + * ``` + * @since v0.3.1 + * @param code The JavaScript code to compile and run. + * @param contextObject Either `vm.constants.DONT_CONTEXTIFY` or an object that will be contextified. + * If `undefined`, an empty contextified object will be created for backwards compatibility. + * @return the result of the very last statement executed in the script. + */ + function runInNewContext( + code: string, + contextObject?: Context | typeof constants.DONT_CONTEXTIFY, + options?: RunningCodeInNewContextOptions | string, + ): any; + /** + * `vm.runInThisContext()` compiles `code`, runs it within the context of the + * current `global` and returns the result. Running code does not have access to + * local scope, but does have access to the current `global` object. + * + * If `options` is a string, then it specifies the filename. + * + * The following example illustrates using both `vm.runInThisContext()` and + * the JavaScript [`eval()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval) function to run the same code: + * + * ```js + * import vm from 'node:vm'; + * let localVar = 'initial value'; + * + * const vmResult = vm.runInThisContext('localVar = "vm";'); + * console.log(`vmResult: '${vmResult}', localVar: '${localVar}'`); + * // Prints: vmResult: 'vm', localVar: 'initial value' + * + * const evalResult = eval('localVar = "eval";'); + * console.log(`evalResult: '${evalResult}', localVar: '${localVar}'`); + * // Prints: evalResult: 'eval', localVar: 'eval' + * ``` + * + * Because `vm.runInThisContext()` does not have access to the local scope, `localVar` is unchanged. In contrast, + * [`eval()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval) _does_ have access to the + * local scope, so the value `localVar` is changed. In this way `vm.runInThisContext()` is much like an [indirect `eval()` call](https://es5.github.io/#x10.4.2), e.g.`(0,eval)('code')`. + * + * ## Example: Running an HTTP server within a VM + * + * When using either `script.runInThisContext()` or {@link runInThisContext}, the code is executed within the current V8 global + * context. The code passed to this VM context will have its own isolated scope. + * + * In order to run a simple web server using the `node:http` module the code passed + * to the context must either import `node:http` on its own, or have a + * reference to the `node:http` module passed to it. For instance: + * + * ```js + * 'use strict'; + * import vm from 'node:vm'; + * + * const code = ` + * ((require) => { + * const http = require('node:http'); + * + * http.createServer((request, response) => { + * response.writeHead(200, { 'Content-Type': 'text/plain' }); + * response.end('Hello World\\n'); + * }).listen(8124); + * + * console.log('Server running at http://127.0.0.1:8124/'); + * })`; + * + * vm.runInThisContext(code)(require); + * ``` + * + * The `require()` in the above case shares the state with the context it is + * passed from. This may introduce risks when untrusted code is executed, e.g. + * altering objects in the context in unwanted ways. + * @since v0.3.1 + * @param code The JavaScript code to compile and run. + * @return the result of the very last statement executed in the script. + */ + function runInThisContext(code: string, options?: RunningCodeOptions | string): any; + /** + * Compiles the given code into the provided context (if no context is + * supplied, the current context is used), and returns it wrapped inside a + * function with the given `params`. + * @since v10.10.0 + * @param code The body of the function to compile. + * @param params An array of strings containing all parameters for the function. + */ + function compileFunction( + code: string, + params?: readonly string[], + options?: CompileFunctionOptions, + ): Function & Pick<Script, "cachedData" | "cachedDataProduced" | "cachedDataRejected">; + /** + * Measure the memory known to V8 and used by all contexts known to the + * current V8 isolate, or the main context. + * + * The format of the object that the returned Promise may resolve with is + * specific to the V8 engine and may change from one version of V8 to the next. + * + * The returned result is different from the statistics returned by `v8.getHeapSpaceStatistics()` in that `vm.measureMemory()` measure the + * memory reachable by each V8 specific contexts in the current instance of + * the V8 engine, while the result of `v8.getHeapSpaceStatistics()` measure + * the memory occupied by each heap space in the current V8 instance. + * + * ```js + * import vm from 'node:vm'; + * // Measure the memory used by the main context. + * vm.measureMemory({ mode: 'summary' }) + * // This is the same as vm.measureMemory() + * .then((result) => { + * // The current format is: + * // { + * // total: { + * // jsMemoryEstimate: 2418479, jsMemoryRange: [ 2418479, 2745799 ] + * // } + * // } + * console.log(result); + * }); + * + * const context = vm.createContext({ a: 1 }); + * vm.measureMemory({ mode: 'detailed', execution: 'eager' }) + * .then((result) => { + * // Reference the context here so that it won't be GC'ed + * // until the measurement is complete. + * console.log(context.a); + * // { + * // total: { + * // jsMemoryEstimate: 2574732, + * // jsMemoryRange: [ 2574732, 2904372 ] + * // }, + * // current: { + * // jsMemoryEstimate: 2438996, + * // jsMemoryRange: [ 2438996, 2768636 ] + * // }, + * // other: [ + * // { + * // jsMemoryEstimate: 135736, + * // jsMemoryRange: [ 135736, 465376 ] + * // } + * // ] + * // } + * console.log(result); + * }); + * ``` + * @since v13.10.0 + * @experimental + */ + function measureMemory(options?: MeasureMemoryOptions): Promise<MemoryMeasurement>; + interface ModuleEvaluateOptions extends Pick<RunningScriptOptions, "breakOnSigint" | "timeout"> {} + type ModuleLinker = ( + specifier: string, + referencingModule: Module, + extra: { + attributes: ImportAttributes; + }, + ) => Module | Promise<Module>; + type ModuleStatus = "unlinked" | "linking" | "linked" | "evaluating" | "evaluated" | "errored"; + /** + * This feature is only available with the `--experimental-vm-modules` command + * flag enabled. + * + * The `vm.Module` class provides a low-level interface for using + * ECMAScript modules in VM contexts. It is the counterpart of the `vm.Script` + * class that closely mirrors [Module Record](https://tc39.es/ecma262/#sec-abstract-module-records)s as defined in the ECMAScript + * specification. + * + * Unlike `vm.Script` however, every `vm.Module` object is bound to a context from + * its creation. + * + * Using a `vm.Module` object requires three distinct steps: creation/parsing, + * linking, and evaluation. These three steps are illustrated in the following + * example. + * + * This implementation lies at a lower level than the `ECMAScript Module + * loader`. There is also no way to interact with the Loader yet, though + * support is planned. + * + * ```js + * import vm from 'node:vm'; + * + * const contextifiedObject = vm.createContext({ + * secret: 42, + * print: console.log, + * }); + * + * // Step 1 + * // + * // Create a Module by constructing a new `vm.SourceTextModule` object. This + * // parses the provided source text, throwing a `SyntaxError` if anything goes + * // wrong. By default, a Module is created in the top context. But here, we + * // specify `contextifiedObject` as the context this Module belongs to. + * // + * // Here, we attempt to obtain the default export from the module "foo", and + * // put it into local binding "secret". + * + * const rootModule = new vm.SourceTextModule(` + * import s from 'foo'; + * s; + * print(s); + * `, { context: contextifiedObject }); + * + * // Step 2 + * // + * // "Link" the imported dependencies of this Module to it. + * // + * // Obtain the requested dependencies of a SourceTextModule by + * // `sourceTextModule.moduleRequests` and resolve them. + * // + * // Even top-level Modules without dependencies must be explicitly linked. The + * // array passed to `sourceTextModule.linkRequests(modules)` can be + * // empty, however. + * // + * // Note: This is a contrived example in that the resolveAndLinkDependencies + * // creates a new "foo" module every time it is called. In a full-fledged + * // module system, a cache would probably be used to avoid duplicated modules. + * + * const moduleMap = new Map([ + * ['root', rootModule], + * ]); + * + * function resolveAndLinkDependencies(module) { + * const requestedModules = module.moduleRequests.map((request) => { + * // In a full-fledged module system, the resolveAndLinkDependencies would + * // resolve the module with the module cache key `[specifier, attributes]`. + * // In this example, we just use the specifier as the key. + * const specifier = request.specifier; + * + * let requestedModule = moduleMap.get(specifier); + * if (requestedModule === undefined) { + * requestedModule = new vm.SourceTextModule(` + * // The "secret" variable refers to the global variable we added to + * // "contextifiedObject" when creating the context. + * export default secret; + * `, { context: referencingModule.context }); + * moduleMap.set(specifier, requestedModule); + * // Resolve the dependencies of the new module as well. + * resolveAndLinkDependencies(requestedModule); + * } + * + * return requestedModule; + * }); + * + * module.linkRequests(requestedModules); + * } + * + * resolveAndLinkDependencies(rootModule); + * rootModule.instantiate(); + * + * // Step 3 + * // + * // Evaluate the Module. The evaluate() method returns a promise which will + * // resolve after the module has finished evaluating. + * + * // Prints 42. + * await rootModule.evaluate(); + * ``` + * @since v13.0.0, v12.16.0 + * @experimental + */ + class Module { + /** + * If the `module.status` is `'errored'`, this property contains the exception + * thrown by the module during evaluation. If the status is anything else, + * accessing this property will result in a thrown exception. + * + * The value `undefined` cannot be used for cases where there is not a thrown + * exception due to possible ambiguity with `throw undefined;`. + * + * Corresponds to the `[[EvaluationError]]` field of [Cyclic Module Record](https://tc39.es/ecma262/#sec-cyclic-module-records) s + * in the ECMAScript specification. + */ + error: any; + /** + * The identifier of the current module, as set in the constructor. + */ + identifier: string; + context: Context; + /** + * The namespace object of the module. This is only available after linking + * (`module.link()`) has completed. + * + * Corresponds to the [GetModuleNamespace](https://tc39.es/ecma262/#sec-getmodulenamespace) abstract operation in the ECMAScript + * specification. + */ + namespace: Object; + /** + * The current status of the module. Will be one of: + * + * * `'unlinked'`: `module.link()` has not yet been called. + * * `'linking'`: `module.link()` has been called, but not all Promises returned + * by the linker function have been resolved yet. + * * `'linked'`: The module has been linked successfully, and all of its + * dependencies are linked, but `module.evaluate()` has not yet been called. + * * `'evaluating'`: The module is being evaluated through a `module.evaluate()` on + * itself or a parent module. + * * `'evaluated'`: The module has been successfully evaluated. + * * `'errored'`: The module has been evaluated, but an exception was thrown. + * + * Other than `'errored'`, this status string corresponds to the specification's [Cyclic Module Record](https://tc39.es/ecma262/#sec-cyclic-module-records)'s `[[Status]]` field. `'errored'` + * corresponds to `'evaluated'` in the specification, but with `[[EvaluationError]]` set to a + * value that is not `undefined`. + */ + status: ModuleStatus; + /** + * Evaluate the module and its depenendencies. Corresponds to the [Evaluate() concrete method](https://tc39.es/ecma262/#sec-moduleevaluation) field of + * [Cyclic Module Record](https://tc39.es/ecma262/#sec-cyclic-module-records)s in the ECMAScript specification. + * + * If the module is a `vm.SourceTextModule`, `evaluate()` must be called after the module has been instantiated; + * otherwise `evaluate()` will return a rejected promise. + * + * For a `vm.SourceTextModule`, the promise returned by `evaluate()` may be fulfilled either + * synchronously or asynchronously: + * + * 1. If the `vm.SourceTextModule` has no top-level `await` in itself or any of its dependencies, the promise will be + * fulfilled _synchronously_ after the module and all its dependencies have been evaluated. + * 1. If the evaluation succeeds, the promise will be _synchronously_ resolved to `undefined`. + * 2. If the evaluation results in an exception, the promise will be _synchronously_ rejected with the exception + * that causes the evaluation to fail, which is the same as `module.error`. + * 2. If the `vm.SourceTextModule` has top-level `await` in itself or any of its dependencies, the promise will be + * fulfilled _asynchronously_ after the module and all its dependencies have been evaluated. + * 1. If the evaluation succeeds, the promise will be _asynchronously_ resolved to `undefined`. + * 2. If the evaluation results in an exception, the promise will be _asynchronously_ rejected with the exception + * that causes the evaluation to fail. + * + * If the module is a `vm.SyntheticModule`, `evaluate()` always returns a promise that fulfills synchronously, see + * the specification of [Evaluate() of a Synthetic Module Record](https://tc39.es/ecma262/#sec-smr-Evaluate): + * + * 1. If the `evaluateCallback` passed to its constructor throws an exception synchronously, `evaluate()` returns + * a promise that will be synchronously rejected with that exception. + * 2. If the `evaluateCallback` does not throw an exception, `evaluate()` returns a promise that will be + * synchronously resolved to `undefined`. + * + * The `evaluateCallback` of a `vm.SyntheticModule` is executed synchronously within the `evaluate()` call, and its + * return value is discarded. This means if `evaluateCallback` is an asynchronous function, the promise returned by + * `evaluate()` will not reflect its asynchronous behavior, and any rejections from an asynchronous + * `evaluateCallback` will be lost. + * + * `evaluate()` could also be called again after the module has already been evaluated, in which case: + * + * 1. If the initial evaluation ended in success (`module.status` is `'evaluated'`), it will do nothing + * and return a promise that resolves to `undefined`. + * 2. If the initial evaluation resulted in an exception (`module.status` is `'errored'`), it will re-reject + * the exception that the initial evaluation resulted in. + * + * This method cannot be called while the module is being evaluated (`module.status` is `'evaluating'`). + * @return Fulfills with `undefined` upon success. + */ + evaluate(options?: ModuleEvaluateOptions): Promise<void>; + /** + * Link module dependencies. This method must be called before evaluation, and + * can only be called once per module. + * + * Use `sourceTextModule.linkRequests(modules)` and + * `sourceTextModule.instantiate()` to link modules either synchronously or + * asynchronously. + * + * The function is expected to return a `Module` object or a `Promise` that + * eventually resolves to a `Module` object. The returned `Module` must satisfy the + * following two invariants: + * + * * It must belong to the same context as the parent `Module`. + * * Its `status` must not be `'errored'`. + * + * If the returned `Module`'s `status` is `'unlinked'`, this method will be + * recursively called on the returned `Module` with the same provided `linker` function. + * + * `link()` returns a `Promise` that will either get resolved when all linking + * instances resolve to a valid `Module`, or rejected if the linker function either + * throws an exception or returns an invalid `Module`. + * + * The linker function roughly corresponds to the implementation-defined [HostResolveImportedModule](https://tc39.es/ecma262/#sec-hostresolveimportedmodule) abstract operation in the + * ECMAScript + * specification, with a few key differences: + * + * * The linker function is allowed to be asynchronous while [HostResolveImportedModule](https://tc39.es/ecma262/#sec-hostresolveimportedmodule) is synchronous. + * + * The actual [HostResolveImportedModule](https://tc39.es/ecma262/#sec-hostresolveimportedmodule) implementation used during module + * linking is one that returns the modules linked during linking. Since at + * that point all modules would have been fully linked already, the [HostResolveImportedModule](https://tc39.es/ecma262/#sec-hostresolveimportedmodule) implementation is fully synchronous per + * specification. + * + * Corresponds to the [Link() concrete method](https://tc39.es/ecma262/#sec-moduledeclarationlinking) field of [Cyclic Module Record](https://tc39.es/ecma262/#sec-cyclic-module-records) s in + * the ECMAScript specification. + */ + link(linker: ModuleLinker): Promise<void>; + } + interface SourceTextModuleOptions extends Pick<ScriptOptions, "cachedData" | "columnOffset" | "lineOffset"> { + /** + * String used in stack traces. + * @default 'vm:module(i)' where i is a context-specific ascending index. + */ + identifier?: string | undefined; + context?: Context | undefined; + /** + * Called during evaluation of this module to initialize the `import.meta`. + */ + initializeImportMeta?: ((meta: ImportMeta, module: SourceTextModule) => void) | undefined; + /** + * Used to specify how the modules should be loaded during the evaluation of this script when `import()` is called. This option is + * part of the experimental modules API. We do not recommend using it in a production environment. For detailed information, see + * [Support of dynamic `import()` in compilation APIs](https://nodejs.org/docs/latest-v25.x/api/vm.html#support-of-dynamic-import-in-compilation-apis). + * @experimental + */ + importModuleDynamically?: DynamicModuleLoader<SourceTextModule> | undefined; + } + /** + * A `ModuleRequest` represents the request to import a module with given import attributes and phase. + * @since 24.4.0 + */ + interface ModuleRequest { + /** + * The specifier of the requested module. + */ + specifier: string; + /** + * The `"with"` value passed to the `WithClause` in a `ImportDeclaration`, or an empty object if no value was + * provided. + */ + attributes: ImportAttributes; + /** + * The phase of the requested module (`"source"` or `"evaluation"`). + */ + phase: ImportPhase; + } + /** + * This feature is only available with the `--experimental-vm-modules` command + * flag enabled. + * + * The `vm.SourceTextModule` class provides the [Source Text Module Record](https://tc39.es/ecma262/#sec-source-text-module-records) as + * defined in the ECMAScript specification. + * @since v9.6.0 + * @experimental + */ + class SourceTextModule extends Module { + /** + * Creates a new `SourceTextModule` instance. + * + * Properties assigned to the `import.meta` object that are objects may + * allow the module to access information outside the specified `context`. Use + * `vm.runInContext()` to create objects in a specific context. + * + * ```js + * import vm from 'node:vm'; + * + * const contextifiedObject = vm.createContext({ secret: 42 }); + * + * const module = new vm.SourceTextModule( + * 'Object.getPrototypeOf(import.meta.prop).secret = secret;', + * { + * initializeImportMeta(meta) { + * // Note: this object is created in the top context. As such, + * // Object.getPrototypeOf(import.meta.prop) points to the + * // Object.prototype in the top context rather than that in + * // the contextified object. + * meta.prop = {}; + * }, + * }); + * // The module has an empty `moduleRequests` array. + * module.linkRequests([]); + * module.instantiate(); + * await module.evaluate(); + * + * // Now, Object.prototype.secret will be equal to 42. + * // + * // To fix this problem, replace + * // meta.prop = {}; + * // above with + * // meta.prop = vm.runInContext('{}', contextifiedObject); + * ``` + * @param code JavaScript Module code to parse + */ + constructor(code: string, options?: SourceTextModuleOptions); + /** + * @deprecated Use `sourceTextModule.moduleRequests` instead. + */ + readonly dependencySpecifiers: readonly string[]; + /** + * Iterates over the dependency graph and returns `true` if any module in its + * dependencies or this module itself contains top-level `await` expressions, + * otherwise returns `false`. + * + * The search may be slow if the graph is big enough. + * + * This requires the module to be instantiated first. If the module is not + * instantiated yet, an error will be thrown. + * @since v24.9.0 + */ + hasAsyncGraph(): boolean; + /** + * Returns whether the module itself contains any top-level `await` expressions. + * + * This corresponds to the field `[[HasTLA]]` in [Cyclic Module Record](https://tc39.es/ecma262/#sec-cyclic-module-records) in the + * ECMAScript specification. + * @since v24.9.0 + */ + hasTopLevelAwait(): boolean; + /** + * Instantiate the module with the linked requested modules. + * + * This resolves the imported bindings of the module, including re-exported + * binding names. When there are any bindings that cannot be resolved, + * an error would be thrown synchronously. + * + * If the requested modules include cyclic dependencies, the + * `sourceTextModule.linkRequests(modules)` method must be called on all + * modules in the cycle before calling this method. + * @since v24.8.0 + */ + instantiate(): void; + /** + * Link module dependencies. This method must be called before evaluation, and + * can only be called once per module. + * + * The order of the module instances in the `modules` array should correspond to the order of + * `sourceTextModule.moduleRequests` being resolved. If two module requests have the same + * specifier and import attributes, they must be resolved with the same module instance or an + * `ERR_MODULE_LINK_MISMATCH` would be thrown. For example, when linking requests for this + * module: + * + * ```js + * import foo from 'foo'; + * import source Foo from 'foo'; + * ``` + * + * The `modules` array must contain two references to the same instance, because the two + * module requests are identical but in two phases. + * + * If the module has no dependencies, the `modules` array can be empty. + * + * Users can use `sourceTextModule.moduleRequests` to implement the host-defined + * [HostLoadImportedModule](https://tc39.es/ecma262/#sec-HostLoadImportedModule) abstract operation in the ECMAScript specification, + * and using `sourceTextModule.linkRequests()` to invoke specification defined + * [FinishLoadingImportedModule](https://tc39.es/ecma262/#sec-FinishLoadingImportedModule), on the module with all dependencies in a batch. + * + * It's up to the creator of the `SourceTextModule` to determine if the resolution + * of the dependencies is synchronous or asynchronous. + * + * After each module in the `modules` array is linked, call + * `sourceTextModule.instantiate()`. + * @since v24.8.0 + * @param modules Array of `vm.Module` objects that this module depends on. + * The order of the modules in the array is the order of + * `sourceTextModule.moduleRequests`. + */ + linkRequests(modules: readonly Module[]): void; + /** + * The requested import dependencies of this module. The returned array is frozen + * to disallow any changes to it. + * + * For example, given a source text: + * + * ```js + * import foo from 'foo'; + * import fooAlias from 'foo'; + * import bar from './bar.js'; + * import withAttrs from '../with-attrs.ts' with { arbitraryAttr: 'attr-val' }; + * import source Module from 'wasm-mod.wasm'; + * ``` + * + * The value of the `sourceTextModule.moduleRequests` will be: + * + * ```js + * [ + * { + * specifier: 'foo', + * attributes: {}, + * phase: 'evaluation', + * }, + * { + * specifier: 'foo', + * attributes: {}, + * phase: 'evaluation', + * }, + * { + * specifier: './bar.js', + * attributes: {}, + * phase: 'evaluation', + * }, + * { + * specifier: '../with-attrs.ts', + * attributes: { arbitraryAttr: 'attr-val' }, + * phase: 'evaluation', + * }, + * { + * specifier: 'wasm-mod.wasm', + * attributes: {}, + * phase: 'source', + * }, + * ]; + * ``` + * @since v24.4.0 + */ + readonly moduleRequests: readonly ModuleRequest[]; + } + interface SyntheticModuleOptions { + /** + * String used in stack traces. + * @default 'vm:module(i)' where i is a context-specific ascending index. + */ + identifier?: string | undefined; + /** + * The contextified object as returned by the `vm.createContext()` method, to compile and evaluate this module in. + */ + context?: Context | undefined; + } + /** + * This feature is only available with the `--experimental-vm-modules` command + * flag enabled. + * + * The `vm.SyntheticModule` class provides the [Synthetic Module Record](https://heycam.github.io/webidl/#synthetic-module-records) as + * defined in the WebIDL specification. The purpose of synthetic modules is to + * provide a generic interface for exposing non-JavaScript sources to ECMAScript + * module graphs. + * + * ```js + * import vm from 'node:vm'; + * + * const source = '{ "a": 1 }'; + * const module = new vm.SyntheticModule(['default'], function() { + * const obj = JSON.parse(source); + * this.setExport('default', obj); + * }); + * + * // Use `module` in linking... + * ``` + * @since v13.0.0, v12.16.0 + * @experimental + */ + class SyntheticModule extends Module { + /** + * Creates a new `SyntheticModule` instance. + * @param exportNames Array of names that will be exported from the module. + * @param evaluateCallback Called when the module is evaluated. + */ + constructor( + exportNames: string[], + evaluateCallback: (this: SyntheticModule) => void, + options?: SyntheticModuleOptions, + ); + /** + * This method sets the module export binding slots with the given value. + * + * ```js + * import vm from 'node:vm'; + * + * const m = new vm.SyntheticModule(['x'], () => { + * m.setExport('x', 1); + * }); + * + * await m.evaluate(); + * + * assert.strictEqual(m.namespace.x, 1); + * ``` + * @since v13.0.0, v12.16.0 + * @param name Name of the export to set. + * @param value The value to set the export to. + */ + setExport(name: string, value: any): void; + } + /** + * Returns an object containing commonly used constants for VM operations. + * @since v21.7.0, v20.12.0 + */ + namespace constants { + /** + * A constant that can be used as the `importModuleDynamically` option to `vm.Script` + * and `vm.compileFunction()` so that Node.js uses the default ESM loader from the main + * context to load the requested module. + * + * For detailed information, see [Support of dynamic `import()` in compilation APIs](https://nodejs.org/docs/latest-v25.x/api/vm.html#support-of-dynamic-import-in-compilation-apis). + * @since v21.7.0, v20.12.0 + */ + const USE_MAIN_CONTEXT_DEFAULT_LOADER: number; + /** + * This constant, when used as the `contextObject` argument in vm APIs, instructs Node.js to create + * a context without wrapping its global object with another object in a Node.js-specific manner. + * As a result, the `globalThis` value inside the new context would behave more closely to an ordinary + * one. + * + * When `vm.constants.DONT_CONTEXTIFY` is used as the `contextObject` argument to {@link createContext}, + * the returned object is a proxy-like object to the global object in the newly created context with + * fewer Node.js-specific quirks. It is reference equal to the `globalThis` value in the new context, + * can be modified from outside the context, and can be used to access built-ins in the new context directly. + * @since v22.8.0 + */ + const DONT_CONTEXTIFY: number; + } +} +declare module "vm" { + export * from "node:vm"; +} diff --git a/server/node_modules/@types/node/wasi.d.ts b/server/node_modules/@types/node/wasi.d.ts new file mode 100644 index 0000000..c206ae5 --- /dev/null +++ b/server/node_modules/@types/node/wasi.d.ts @@ -0,0 +1,202 @@ +/** + * **The `node:wasi` module does not currently provide the** + * **comprehensive file system security properties provided by some WASI runtimes.** + * **Full support for secure file system sandboxing may or may not be implemented in** + * **future. In the mean time, do not rely on it to run untrusted code.** + * + * The WASI API provides an implementation of the [WebAssembly System Interface](https://wasi.dev/) specification. WASI gives WebAssembly applications access to the underlying + * operating system via a collection of POSIX-like functions. + * + * ```js + * import { readFile } from 'node:fs/promises'; + * import { WASI } from 'node:wasi'; + * import { argv, env } from 'node:process'; + * + * const wasi = new WASI({ + * version: 'preview1', + * args: argv, + * env, + * preopens: { + * '/local': '/some/real/path/that/wasm/can/access', + * }, + * }); + * + * const wasm = await WebAssembly.compile( + * await readFile(new URL('./demo.wasm', import.meta.url)), + * ); + * const instance = await WebAssembly.instantiate(wasm, wasi.getImportObject()); + * + * wasi.start(instance); + * ``` + * + * To run the above example, create a new WebAssembly text format file named `demo.wat`: + * + * ```text + * (module + * ;; Import the required fd_write WASI function which will write the given io vectors to stdout + * ;; The function signature for fd_write is: + * ;; (File Descriptor, *iovs, iovs_len, nwritten) -> Returns number of bytes written + * (import "wasi_snapshot_preview1" "fd_write" (func $fd_write (param i32 i32 i32 i32) (result i32))) + * + * (memory 1) + * (export "memory" (memory 0)) + * + * ;; Write 'hello world\n' to memory at an offset of 8 bytes + * ;; Note the trailing newline which is required for the text to appear + * (data (i32.const 8) "hello world\n") + * + * (func $main (export "_start") + * ;; Creating a new io vector within linear memory + * (i32.store (i32.const 0) (i32.const 8)) ;; iov.iov_base - This is a pointer to the start of the 'hello world\n' string + * (i32.store (i32.const 4) (i32.const 12)) ;; iov.iov_len - The length of the 'hello world\n' string + * + * (call $fd_write + * (i32.const 1) ;; file_descriptor - 1 for stdout + * (i32.const 0) ;; *iovs - The pointer to the iov array, which is stored at memory location 0 + * (i32.const 1) ;; iovs_len - We're printing 1 string stored in an iov - so one. + * (i32.const 20) ;; nwritten - A place in memory to store the number of bytes written + * ) + * drop ;; Discard the number of bytes written from the top of the stack + * ) + * ) + * ``` + * + * Use [wabt](https://github.com/WebAssembly/wabt) to compile `.wat` to `.wasm` + * + * ```bash + * wat2wasm demo.wat + * ``` + * @experimental + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/wasi.js) + */ +declare module "node:wasi" { + interface WASIOptions { + /** + * An array of strings that the WebAssembly application will + * see as command line arguments. The first argument is the virtual path to the + * WASI command itself. + * @default [] + */ + args?: readonly string[] | undefined; + /** + * An object similar to `process.env` that the WebAssembly + * application will see as its environment. + * @default {} + */ + env?: object | undefined; + /** + * This object represents the WebAssembly application's + * sandbox directory structure. The string keys of `preopens` are treated as + * directories within the sandbox. The corresponding values in `preopens` are + * the real paths to those directories on the host machine. + */ + preopens?: NodeJS.Dict<string> | undefined; + /** + * By default, when WASI applications call `__wasi_proc_exit()` + * `wasi.start()` will return with the exit code specified rather than terminatng the process. + * Setting this option to `false` will cause the Node.js process to exit with + * the specified exit code instead. + * @default true + */ + returnOnExit?: boolean | undefined; + /** + * The file descriptor used as standard input in the WebAssembly application. + * @default 0 + */ + stdin?: number | undefined; + /** + * The file descriptor used as standard output in the WebAssembly application. + * @default 1 + */ + stdout?: number | undefined; + /** + * The file descriptor used as standard error in the WebAssembly application. + * @default 2 + */ + stderr?: number | undefined; + /** + * The version of WASI requested. + * Currently the only supported versions are `'unstable'` and `'preview1'`. This option is mandatory. + * @since v19.8.0 + */ + version: "unstable" | "preview1"; + } + interface FinalizeBindingsOptions { + /** + * @default instance.exports.memory + */ + memory?: object | undefined; + } + /** + * The `WASI` class provides the WASI system call API and additional convenience + * methods for working with WASI-based applications. Each `WASI` instance + * represents a distinct environment. + * @since v13.3.0, v12.16.0 + */ + class WASI { + constructor(options?: WASIOptions); + /** + * Return an import object that can be passed to `WebAssembly.instantiate()` if no other WASM imports are needed beyond those provided by WASI. + * + * If version `unstable` was passed into the constructor it will return: + * + * ```js + * { wasi_unstable: wasi.wasiImport } + * ``` + * + * If version `preview1` was passed into the constructor or no version was specified it will return: + * + * ```js + * { wasi_snapshot_preview1: wasi.wasiImport } + * ``` + * @since v19.8.0 + */ + getImportObject(): object; + /** + * Attempt to begin execution of `instance` as a WASI command by invoking its `_start()` export. If `instance` does not contain a `_start()` export, or if `instance` contains an `_initialize()` + * export, then an exception is thrown. + * + * `start()` requires that `instance` exports a [`WebAssembly.Memory`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory) named `memory`. If + * `instance` does not have a `memory` export an exception is thrown. + * + * If `start()` is called more than once, an exception is thrown. + * @since v13.3.0, v12.16.0 + */ + start(instance: object): number; // TODO: avoid DOM dependency until WASM moved to own lib. + /** + * Attempt to initialize `instance` as a WASI reactor by invoking its `_initialize()` export, if it is present. If `instance` contains a `_start()` export, then an exception is thrown. + * + * `initialize()` requires that `instance` exports a [`WebAssembly.Memory`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory) named `memory`. + * If `instance` does not have a `memory` export an exception is thrown. + * + * If `initialize()` is called more than once, an exception is thrown. + * @since v14.6.0, v12.19.0 + */ + initialize(instance: object): void; // TODO: avoid DOM dependency until WASM moved to own lib. + /** + * Set up WASI host bindings to `instance` without calling `initialize()` + * or `start()`. This method is useful when the WASI module is instantiated in + * child threads for sharing the memory across threads. + * + * `finalizeBindings()` requires that either `instance` exports a + * [`WebAssembly.Memory`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory) named `memory` or user specify a + * [`WebAssembly.Memory`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory) object in `options.memory`. If the `memory` is invalid + * an exception is thrown. + * + * `start()` and `initialize()` will call `finalizeBindings()` internally. + * If `finalizeBindings()` is called more than once, an exception is thrown. + * @since v24.4.0 + */ + finalizeBindings(instance: object, options?: FinalizeBindingsOptions): void; + /** + * `wasiImport` is an object that implements the WASI system call API. This object + * should be passed as the `wasi_snapshot_preview1` import during the instantiation + * of a [`WebAssembly.Instance`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Instance). + * @since v13.3.0, v12.16.0 + */ + readonly wasiImport: NodeJS.Dict<any>; // TODO: Narrow to DOM types + } +} +declare module "wasi" { + export * from "node:wasi"; +} diff --git a/server/node_modules/@types/node/web-globals/abortcontroller.d.ts b/server/node_modules/@types/node/web-globals/abortcontroller.d.ts new file mode 100644 index 0000000..ad753c1 --- /dev/null +++ b/server/node_modules/@types/node/web-globals/abortcontroller.d.ts @@ -0,0 +1,59 @@ +export {}; + +import { InternalEventTargetEventProperties } from "node:events"; + +type _AbortController = typeof globalThis extends { onmessage: any } ? {} : AbortController; +interface AbortController { + readonly signal: AbortSignal; + abort(reason?: any): void; +} + +interface AbortSignalEventMap { + "abort": Event; +} + +type _AbortSignal = typeof globalThis extends { onmessage: any } ? {} : AbortSignal; +interface AbortSignal extends EventTarget, InternalEventTargetEventProperties<AbortSignalEventMap> { + readonly aborted: boolean; + readonly reason: any; + throwIfAborted(): void; + addEventListener<K extends keyof AbortSignalEventMap>( + type: K, + listener: (ev: AbortSignalEventMap[K]) => void, + options?: AddEventListenerOptions | boolean, + ): void; + addEventListener( + type: string, + listener: EventListener | EventListenerObject, + options?: AddEventListenerOptions | boolean, + ): void; + removeEventListener<K extends keyof AbortSignalEventMap>( + type: K, + listener: (ev: AbortSignalEventMap[K]) => void, + options?: EventListenerOptions | boolean, + ): void; + removeEventListener( + type: string, + listener: EventListener | EventListenerObject, + options?: EventListenerOptions | boolean, + ): void; +} + +declare global { + interface AbortController extends _AbortController {} + var AbortController: typeof globalThis extends { onmessage: any; AbortController: infer T } ? T + : { + prototype: AbortController; + new(): AbortController; + }; + + interface AbortSignal extends _AbortSignal {} + var AbortSignal: typeof globalThis extends { onmessage: any; AbortSignal: infer T } ? T + : { + prototype: AbortSignal; + new(): AbortSignal; + abort(reason?: any): AbortSignal; + any(signals: AbortSignal[]): AbortSignal; + timeout(milliseconds: number): AbortSignal; + }; +} diff --git a/server/node_modules/@types/node/web-globals/blob.d.ts b/server/node_modules/@types/node/web-globals/blob.d.ts new file mode 100644 index 0000000..04ff440 --- /dev/null +++ b/server/node_modules/@types/node/web-globals/blob.d.ts @@ -0,0 +1,23 @@ +export {}; + +import * as buffer from "node:buffer"; + +type _Blob = typeof globalThis extends { onmessage: any } ? {} : buffer.Blob; +type _BlobPropertyBag = typeof globalThis extends { onmessage: any } ? {} : buffer.BlobPropertyBag; +type _File = typeof globalThis extends { onmessage: any } ? {} : buffer.File; +type _FilePropertyBag = typeof globalThis extends { onmessage: any } ? {} : buffer.FilePropertyBag; + +declare global { + interface Blob extends _Blob {} + var Blob: typeof globalThis extends { onmessage: any; Blob: infer T } ? T : typeof buffer.Blob; + + interface BlobPropertyBag extends _BlobPropertyBag {} + + interface File extends _File {} + var File: typeof globalThis extends { onmessage: any; File: infer T } ? T : typeof buffer.File; + + interface FilePropertyBag extends _FilePropertyBag {} + + function atob(data: string): string; + function btoa(data: string): string; +} diff --git a/server/node_modules/@types/node/web-globals/console.d.ts b/server/node_modules/@types/node/web-globals/console.d.ts new file mode 100644 index 0000000..5492de3 --- /dev/null +++ b/server/node_modules/@types/node/web-globals/console.d.ts @@ -0,0 +1,9 @@ +export {}; + +import * as console from "node:console"; + +declare global { + interface Console extends console.Console {} + + var console: Console; +} diff --git a/server/node_modules/@types/node/web-globals/crypto.d.ts b/server/node_modules/@types/node/web-globals/crypto.d.ts new file mode 100644 index 0000000..f038a43 --- /dev/null +++ b/server/node_modules/@types/node/web-globals/crypto.d.ts @@ -0,0 +1,39 @@ +export {}; + +import { webcrypto } from "crypto"; + +type _Crypto = typeof globalThis extends { onmessage: any } ? {} : webcrypto.Crypto; +type _CryptoKey = typeof globalThis extends { onmessage: any } ? {} : webcrypto.CryptoKey; +type _SubtleCrypto = typeof globalThis extends { onmessage: any } ? {} : webcrypto.SubtleCrypto; + +declare global { + interface Crypto extends _Crypto {} + var Crypto: typeof globalThis extends { onmessage: any; Crypto: infer T } ? T : { + prototype: webcrypto.Crypto; + new(): webcrypto.Crypto; + }; + + interface CryptoKey extends _CryptoKey {} + var CryptoKey: typeof globalThis extends { onmessage: any; CryptoKey: infer T } ? T : { + prototype: webcrypto.CryptoKey; + new(): webcrypto.CryptoKey; + }; + + interface SubtleCrypto extends _SubtleCrypto {} + var SubtleCrypto: typeof globalThis extends { onmessage: any; SubtleCrypto: infer T } ? T : { + prototype: webcrypto.SubtleCrypto; + new(): webcrypto.SubtleCrypto; + supports( + operation: string, + algorithm: webcrypto.AlgorithmIdentifier, + length?: number, + ): boolean; + supports( + operation: string, + algorithm: webcrypto.AlgorithmIdentifier, + additionalAlgorithm: webcrypto.AlgorithmIdentifier, + ): boolean; + }; + + var crypto: typeof globalThis extends { onmessage: any; crypto: infer T } ? T : webcrypto.Crypto; +} diff --git a/server/node_modules/@types/node/web-globals/domexception.d.ts b/server/node_modules/@types/node/web-globals/domexception.d.ts new file mode 100644 index 0000000..5b1662c --- /dev/null +++ b/server/node_modules/@types/node/web-globals/domexception.d.ts @@ -0,0 +1,68 @@ +export {}; + +type _DOMException = typeof globalThis extends { onmessage: any } ? {} : DOMException; +interface DOMException extends Error { + readonly code: number; + readonly message: string; + readonly name: string; + readonly INDEX_SIZE_ERR: 1; + readonly DOMSTRING_SIZE_ERR: 2; + readonly HIERARCHY_REQUEST_ERR: 3; + readonly WRONG_DOCUMENT_ERR: 4; + readonly INVALID_CHARACTER_ERR: 5; + readonly NO_DATA_ALLOWED_ERR: 6; + readonly NO_MODIFICATION_ALLOWED_ERR: 7; + readonly NOT_FOUND_ERR: 8; + readonly NOT_SUPPORTED_ERR: 9; + readonly INUSE_ATTRIBUTE_ERR: 10; + readonly INVALID_STATE_ERR: 11; + readonly SYNTAX_ERR: 12; + readonly INVALID_MODIFICATION_ERR: 13; + readonly NAMESPACE_ERR: 14; + readonly INVALID_ACCESS_ERR: 15; + readonly VALIDATION_ERR: 16; + readonly TYPE_MISMATCH_ERR: 17; + readonly SECURITY_ERR: 18; + readonly NETWORK_ERR: 19; + readonly ABORT_ERR: 20; + readonly URL_MISMATCH_ERR: 21; + readonly QUOTA_EXCEEDED_ERR: 22; + readonly TIMEOUT_ERR: 23; + readonly INVALID_NODE_TYPE_ERR: 24; + readonly DATA_CLONE_ERR: 25; +} + +declare global { + interface DOMException extends _DOMException {} + var DOMException: typeof globalThis extends { onmessage: any; DOMException: infer T } ? T + : { + prototype: DOMException; + new(message?: string, name?: string): DOMException; + new(message?: string, options?: { name?: string; cause?: unknown }): DOMException; + readonly INDEX_SIZE_ERR: 1; + readonly DOMSTRING_SIZE_ERR: 2; + readonly HIERARCHY_REQUEST_ERR: 3; + readonly WRONG_DOCUMENT_ERR: 4; + readonly INVALID_CHARACTER_ERR: 5; + readonly NO_DATA_ALLOWED_ERR: 6; + readonly NO_MODIFICATION_ALLOWED_ERR: 7; + readonly NOT_FOUND_ERR: 8; + readonly NOT_SUPPORTED_ERR: 9; + readonly INUSE_ATTRIBUTE_ERR: 10; + readonly INVALID_STATE_ERR: 11; + readonly SYNTAX_ERR: 12; + readonly INVALID_MODIFICATION_ERR: 13; + readonly NAMESPACE_ERR: 14; + readonly INVALID_ACCESS_ERR: 15; + readonly VALIDATION_ERR: 16; + readonly TYPE_MISMATCH_ERR: 17; + readonly SECURITY_ERR: 18; + readonly NETWORK_ERR: 19; + readonly ABORT_ERR: 20; + readonly URL_MISMATCH_ERR: 21; + readonly QUOTA_EXCEEDED_ERR: 22; + readonly TIMEOUT_ERR: 23; + readonly INVALID_NODE_TYPE_ERR: 24; + readonly DATA_CLONE_ERR: 25; + }; +} diff --git a/server/node_modules/@types/node/web-globals/encoding.d.ts b/server/node_modules/@types/node/web-globals/encoding.d.ts new file mode 100644 index 0000000..de5fa4f --- /dev/null +++ b/server/node_modules/@types/node/web-globals/encoding.d.ts @@ -0,0 +1,11 @@ +export {}; + +import * as util from "node:util"; + +declare global { + interface TextDecoder extends util.TextDecoder {} + var TextDecoder: typeof globalThis extends { onmessage: any; TextDecoder: infer T } ? T : typeof util.TextDecoder; + + interface TextEncoder extends util.TextEncoder {} + var TextEncoder: typeof globalThis extends { onmessage: any; TextEncoder: infer T } ? T : typeof util.TextEncoder; +} diff --git a/server/node_modules/@types/node/web-globals/events.d.ts b/server/node_modules/@types/node/web-globals/events.d.ts new file mode 100644 index 0000000..cdbcc69 --- /dev/null +++ b/server/node_modules/@types/node/web-globals/events.d.ts @@ -0,0 +1,106 @@ +export {}; + +type _AddEventListenerOptions = typeof globalThis extends { onmessage: any } ? {} : AddEventListenerOptions; +interface AddEventListenerOptions extends EventListenerOptions { + once?: boolean; + passive?: boolean; + signal?: AbortSignal; +} + +type _CustomEvent<T = any> = typeof globalThis extends { onmessage: any } ? {} : CustomEvent<T>; +interface CustomEvent<T = any> extends Event { + readonly detail: T; +} + +interface CustomEventInit<T = any> extends EventInit { + detail?: T; +} + +type _Event = typeof globalThis extends { onmessage: any } ? {} : Event; +interface Event { + readonly bubbles: boolean; + cancelBubble: boolean; + readonly cancelable: boolean; + readonly composed: boolean; + readonly currentTarget: EventTarget | null; + readonly defaultPrevented: boolean; + readonly eventPhase: 0 | 2; + readonly isTrusted: boolean; + returnValue: boolean; + readonly srcElement: EventTarget | null; + readonly target: EventTarget | null; + readonly timeStamp: number; + readonly type: string; + composedPath(): [EventTarget?]; + initEvent(type: string, bubbles?: boolean, cancelable?: boolean): void; + preventDefault(): void; + stopImmediatePropagation(): void; + stopPropagation(): void; +} + +interface EventInit { + bubbles?: boolean; + cancelable?: boolean; + composed?: boolean; +} + +type _EventListener = typeof globalThis extends { onmessage: any } ? {} : EventListener; +interface EventListener { + (evt: Event): void; +} + +type _EventListenerObject = typeof globalThis extends { onmessage: any } ? {} : EventListenerObject; +interface EventListenerObject { + handleEvent(object: Event): void; +} + +type _EventListenerOptions = typeof globalThis extends { onmessage: any } ? {} : EventListenerOptions; +interface EventListenerOptions { + capture?: boolean; +} + +type _EventTarget = typeof globalThis extends { onmessage: any } ? {} : EventTarget; +interface EventTarget { + addEventListener( + type: string, + listener: EventListener | EventListenerObject, + options?: AddEventListenerOptions | boolean, + ): void; + dispatchEvent(event: Event): boolean; + removeEventListener( + type: string, + listener: EventListener | EventListenerObject, + options?: EventListenerOptions | boolean, + ): void; +} + +declare global { + interface AddEventListenerOptions extends _AddEventListenerOptions {} + + interface CustomEvent<T = any> extends _CustomEvent<T> {} + var CustomEvent: typeof globalThis extends { onmessage: any; CustomEvent: infer T } ? T + : { + prototype: CustomEvent; + new<T>(type: string, eventInitDict?: CustomEventInit<T>): CustomEvent<T>; + }; + + interface Event extends _Event {} + var Event: typeof globalThis extends { onmessage: any; Event: infer T } ? T + : { + prototype: Event; + new(type: string, eventInitDict?: EventInit): Event; + }; + + interface EventListener extends _EventListener {} + + interface EventListenerObject extends _EventListenerObject {} + + interface EventListenerOptions extends _EventListenerOptions {} + + interface EventTarget extends _EventTarget {} + var EventTarget: typeof globalThis extends { onmessage: any; EventTarget: infer T } ? T + : { + prototype: EventTarget; + new(): EventTarget; + }; +} diff --git a/server/node_modules/@types/node/web-globals/fetch.d.ts b/server/node_modules/@types/node/web-globals/fetch.d.ts new file mode 100644 index 0000000..0aa9588 --- /dev/null +++ b/server/node_modules/@types/node/web-globals/fetch.d.ts @@ -0,0 +1,69 @@ +export {}; + +import * as undici from "undici-types"; + +type _CloseEvent = typeof globalThis extends { onmessage: any } ? {} : undici.CloseEvent; +type _CloseEventInit = typeof globalThis extends { onmessage: any } ? {} : undici.CloseEventInit; +type _ErrorEvent = typeof globalThis extends { onmessage: any } ? {} : undici.ErrorEvent; +type _ErrorEventInit = typeof globalThis extends { onmessage: any } ? {} : undici.ErrorEventInit; +type _EventSource = typeof globalThis extends { onmessage: any } ? {} : undici.EventSource; +type _EventSourceInit = typeof globalThis extends { onmessage: any } ? {} : undici.EventSourceInit; +type _FormData = typeof globalThis extends { onmessage: any } ? {} : undici.FormData; +type _Headers = typeof globalThis extends { onmessage: any } ? {} : undici.Headers; +type _MessageEvent = typeof globalThis extends { onmessage: any } ? {} : undici.MessageEvent; +type _MessageEventInit = typeof globalThis extends { onmessage: any } ? {} : undici.MessageEventInit; +type _Request = typeof globalThis extends { onmessage: any } ? {} : undici.Request; +type _RequestInit = typeof globalThis extends { onmessage: any } ? {} : undici.RequestInit; +type _Response = typeof globalThis extends { onmessage: any } ? {} : undici.Response; +type _ResponseInit = typeof globalThis extends { onmessage: any } ? {} : undici.ResponseInit; +type _WebSocket = typeof globalThis extends { onmessage: any } ? {} : undici.WebSocket; +type _WebSocketInit = typeof globalThis extends { onmessage: any } ? {} : undici.WebSocketInit; + +declare global { + function fetch( + input: string | URL | Request, + init?: RequestInit, + ): Promise<Response>; + + interface CloseEvent extends _CloseEvent {} + var CloseEvent: typeof globalThis extends { onmessage: any; CloseEvent: infer T } ? T : typeof undici.CloseEvent; + + interface CloseEventInit extends _CloseEventInit {} + + interface ErrorEvent extends _ErrorEvent {} + var ErrorEvent: typeof globalThis extends { onmessage: any; ErrorEvent: infer T } ? T : typeof undici.ErrorEvent; + + interface ErrorEventInit extends _ErrorEventInit {} + + interface EventSource extends _EventSource {} + var EventSource: typeof globalThis extends { onmessage: any; EventSource: infer T } ? T : typeof undici.EventSource; + + interface EventSourceInit extends _EventSourceInit {} + + interface FormData extends _FormData {} + var FormData: typeof globalThis extends { onmessage: any; FormData: infer T } ? T : typeof undici.FormData; + + interface Headers extends _Headers {} + var Headers: typeof globalThis extends { onmessage: any; Headers: infer T } ? T : typeof undici.Headers; + + interface MessageEvent extends _MessageEvent {} + var MessageEvent: typeof globalThis extends { onmessage: any; MessageEvent: infer T } ? T + : typeof undici.MessageEvent; + + interface MessageEventInit extends _MessageEventInit {} + + interface Request extends _Request {} + var Request: typeof globalThis extends { onmessage: any; Request: infer T } ? T : typeof undici.Request; + + interface RequestInit extends _RequestInit {} + + interface Response extends _Response {} + var Response: typeof globalThis extends { onmessage: any; Response: infer T } ? T : typeof undici.Response; + + interface ResponseInit extends _ResponseInit {} + + interface WebSocket extends _WebSocket {} + var WebSocket: typeof globalThis extends { onmessage: any; WebSocket: infer T } ? T : typeof undici.WebSocket; + + interface WebSocketInit extends _WebSocketInit {} +} diff --git a/server/node_modules/@types/node/web-globals/importmeta.d.ts b/server/node_modules/@types/node/web-globals/importmeta.d.ts new file mode 100644 index 0000000..33deba1 --- /dev/null +++ b/server/node_modules/@types/node/web-globals/importmeta.d.ts @@ -0,0 +1,13 @@ +export {}; + +import { URL } from "node:url"; + +declare global { + interface ImportMeta { + dirname: string; + filename: string; + main: boolean; + url: string; + resolve(specifier: string, parent?: string | URL): string; + } +} diff --git a/server/node_modules/@types/node/web-globals/messaging.d.ts b/server/node_modules/@types/node/web-globals/messaging.d.ts new file mode 100644 index 0000000..c914582 --- /dev/null +++ b/server/node_modules/@types/node/web-globals/messaging.d.ts @@ -0,0 +1,23 @@ +export {}; + +import * as worker_threads from "node:worker_threads"; + +type _BroadcastChannel = typeof globalThis extends { onmessage: any } ? {} : worker_threads.BroadcastChannel; +type _MessageChannel = typeof globalThis extends { onmessage: any } ? {} : worker_threads.MessageChannel; +type _MessagePort = typeof globalThis extends { onmessage: any } ? {} : worker_threads.MessagePort; + +declare global { + function structuredClone<T = any>(value: T, options?: worker_threads.StructuredSerializeOptions): T; + + interface BroadcastChannel extends _BroadcastChannel {} + var BroadcastChannel: typeof globalThis extends { onmessage: any; BroadcastChannel: infer T } ? T + : typeof worker_threads.BroadcastChannel; + + interface MessageChannel extends _MessageChannel {} + var MessageChannel: typeof globalThis extends { onmessage: any; MessageChannel: infer T } ? T + : typeof worker_threads.MessageChannel; + + interface MessagePort extends _MessagePort {} + var MessagePort: typeof globalThis extends { onmessage: any; MessagePort: infer T } ? T + : typeof worker_threads.MessagePort; +} diff --git a/server/node_modules/@types/node/web-globals/navigator.d.ts b/server/node_modules/@types/node/web-globals/navigator.d.ts new file mode 100644 index 0000000..9b45b26 --- /dev/null +++ b/server/node_modules/@types/node/web-globals/navigator.d.ts @@ -0,0 +1,25 @@ +export {}; + +import { LockManager } from "worker_threads"; + +// lib.webworker has `WorkerNavigator` rather than `Navigator`, so conditionals use `onabort` instead of `onmessage` +type _Navigator = typeof globalThis extends { onabort: any } ? {} : Navigator; +interface Navigator { + readonly hardwareConcurrency: number; + readonly language: string; + readonly languages: readonly string[]; + readonly locks: LockManager; + readonly platform: string; + readonly userAgent: string; +} + +declare global { + interface Navigator extends _Navigator {} + var Navigator: typeof globalThis extends { onabort: any; Navigator: infer T } ? T : { + prototype: Navigator; + new(): Navigator; + }; + + // Needs conditional inference for lib.dom and lib.webworker compatibility + var navigator: typeof globalThis extends { onmessage: any; navigator: infer T } ? T : Navigator; +} diff --git a/server/node_modules/@types/node/web-globals/performance.d.ts b/server/node_modules/@types/node/web-globals/performance.d.ts new file mode 100644 index 0000000..b8f4e62 --- /dev/null +++ b/server/node_modules/@types/node/web-globals/performance.d.ts @@ -0,0 +1,45 @@ +export {}; + +import * as perf_hooks from "node:perf_hooks"; + +type _Performance = typeof globalThis extends { onmessage: any } ? {} : perf_hooks.Performance; +type _PerformanceEntry = typeof globalThis extends { onmessage: any } ? {} : perf_hooks.PerformanceEntry; +type _PerformanceMark = typeof globalThis extends { onmessage: any } ? {} : perf_hooks.PerformanceMark; +type _PerformanceMeasure = typeof globalThis extends { onmessage: any } ? {} : perf_hooks.PerformanceMeasure; +type _PerformanceObserver = typeof globalThis extends { onmessage: any } ? {} : perf_hooks.PerformanceObserver; +type _PerformanceObserverEntryList = typeof globalThis extends { onmessage: any } ? {} + : perf_hooks.PerformanceObserverEntryList; +type _PerformanceResourceTiming = typeof globalThis extends { onmessage: any } ? {} + : perf_hooks.PerformanceResourceTiming; + +declare global { + interface Performance extends _Performance {} + var Performance: typeof globalThis extends { onmessage: any; Performance: infer T } ? T + : typeof perf_hooks.Performance; + + interface PerformanceEntry extends _PerformanceEntry {} + var PerformanceEntry: typeof globalThis extends { onmessage: any; PerformanceEntry: infer T } ? T + : typeof perf_hooks.PerformanceEntry; + + interface PerformanceMark extends _PerformanceMark {} + var PerformanceMark: typeof globalThis extends { onmessage: any; PerformanceMark: infer T } ? T + : typeof perf_hooks.PerformanceMark; + + interface PerformanceMeasure extends _PerformanceMeasure {} + var PerformanceMeasure: typeof globalThis extends { onmessage: any; PerformanceMeasure: infer T } ? T + : typeof perf_hooks.PerformanceMeasure; + + interface PerformanceObserver extends _PerformanceObserver {} + var PerformanceObserver: typeof globalThis extends { onmessage: any; PerformanceObserver: infer T } ? T + : typeof perf_hooks.PerformanceObserver; + + interface PerformanceObserverEntryList extends _PerformanceObserverEntryList {} + var PerformanceObserverEntryList: typeof globalThis extends + { onmessage: any; PerformanceObserverEntryList: infer T } ? T : typeof perf_hooks.PerformanceObserverEntryList; + + interface PerformanceResourceTiming extends _PerformanceResourceTiming {} + var PerformanceResourceTiming: typeof globalThis extends { onmessage: any; PerformanceResourceTiming: infer T } ? T + : typeof perf_hooks.PerformanceResourceTiming; + + var performance: typeof globalThis extends { onmessage: any; performance: infer T } ? T : perf_hooks.Performance; +} diff --git a/server/node_modules/@types/node/web-globals/storage.d.ts b/server/node_modules/@types/node/web-globals/storage.d.ts new file mode 100644 index 0000000..fd61cfc --- /dev/null +++ b/server/node_modules/@types/node/web-globals/storage.d.ts @@ -0,0 +1,24 @@ +export {}; + +// These interfaces are absent from lib.webworker, so the conditionals use `onabort` rather than `onmessage` +type _Storage = typeof globalThis extends { onabort: any } ? {} : Storage; +interface Storage { + readonly length: number; + clear(): void; + getItem(key: string): string | null; + key(index: number): string | null; + removeItem(key: string): void; + setItem(key: string, value: string): void; + [key: string]: any; +} + +declare global { + interface Storage extends _Storage {} + var Storage: typeof globalThis extends { onabort: any; Storage: infer T } ? T : { + prototype: Storage; + new(): Storage; + }; + + var localStorage: Storage; + var sessionStorage: Storage; +} diff --git a/server/node_modules/@types/node/web-globals/streams.d.ts b/server/node_modules/@types/node/web-globals/streams.d.ts new file mode 100644 index 0000000..9650ea8 --- /dev/null +++ b/server/node_modules/@types/node/web-globals/streams.d.ts @@ -0,0 +1,115 @@ +export {}; + +import * as webstreams from "stream/web"; + +type _ByteLengthQueuingStrategy = typeof globalThis extends { onmessage: any } ? {} + : webstreams.ByteLengthQueuingStrategy; +type _CompressionStream = typeof globalThis extends { onmessage: any } ? {} : webstreams.CompressionStream; +type _CountQueuingStrategy = typeof globalThis extends { onmessage: any } ? {} : webstreams.CountQueuingStrategy; +type _DecompressionStream = typeof globalThis extends { onmessage: any } ? {} : webstreams.DecompressionStream; +type _QueuingStrategy<T = any> = typeof globalThis extends { onmessage: any } ? {} : webstreams.QueuingStrategy<T>; +type _ReadableByteStreamController = typeof globalThis extends { onmessage: any } ? {} + : webstreams.ReadableByteStreamController; +type _ReadableStream<R = any> = typeof globalThis extends { onmessage: any } ? {} : webstreams.ReadableStream<R>; +type _ReadableStreamBYOBReader = typeof globalThis extends { onmessage: any } ? {} + : webstreams.ReadableStreamBYOBReader; +type _ReadableStreamBYOBRequest = typeof globalThis extends { onmessage: any } ? {} + : webstreams.ReadableStreamBYOBRequest; +type _ReadableStreamDefaultController<R = any> = typeof globalThis extends { onmessage: any } ? {} + : webstreams.ReadableStreamDefaultController<R>; +type _ReadableStreamDefaultReader<R = any> = typeof globalThis extends { onmessage: any } ? {} + : webstreams.ReadableStreamDefaultReader<R>; +type _TextDecoderStream = typeof globalThis extends { onmessage: any } ? {} : webstreams.TextDecoderStream; +type _TextEncoderStream = typeof globalThis extends { onmessage: any } ? {} : webstreams.TextEncoderStream; +type _TransformStream<I = any, O = any> = typeof globalThis extends { onmessage: any } ? {} + : webstreams.TransformStream<I, O>; +type _TransformStreamDefaultController<O = any> = typeof globalThis extends { onmessage: any } ? {} + : webstreams.TransformStreamDefaultController<O>; +type _WritableStream<W = any> = typeof globalThis extends { onmessage: any } ? {} : webstreams.WritableStream<W>; +type _WritableStreamDefaultController = typeof globalThis extends { onmessage: any } ? {} + : webstreams.WritableStreamDefaultController; +type _WritableStreamDefaultWriter<W = any> = typeof globalThis extends { onmessage: any } ? {} + : webstreams.WritableStreamDefaultWriter<W>; + +declare global { + interface ByteLengthQueuingStrategy extends _ByteLengthQueuingStrategy {} + var ByteLengthQueuingStrategy: typeof globalThis extends { onmessage: any; ByteLengthQueuingStrategy: infer T } ? T + : typeof webstreams.ByteLengthQueuingStrategy; + + interface CompressionStream extends _CompressionStream {} + var CompressionStream: typeof globalThis extends { + onmessage: any; + CompressionStream: infer T; + } ? T + : typeof webstreams.CompressionStream; + + interface CountQueuingStrategy extends _CountQueuingStrategy {} + var CountQueuingStrategy: typeof globalThis extends { onmessage: any; CountQueuingStrategy: infer T } ? T + : typeof webstreams.CountQueuingStrategy; + + interface DecompressionStream extends _DecompressionStream {} + var DecompressionStream: typeof globalThis extends { + onmessage: any; + DecompressionStream: infer T; + } ? T + : typeof webstreams.DecompressionStream; + + interface QueuingStrategy<T = any> extends _QueuingStrategy<T> {} + + interface ReadableByteStreamController extends _ReadableByteStreamController {} + var ReadableByteStreamController: typeof globalThis extends + { onmessage: any; ReadableByteStreamController: infer T } ? T : typeof webstreams.ReadableByteStreamController; + + interface ReadableStream<R = any> extends _ReadableStream<R> {} + var ReadableStream: typeof globalThis extends { onmessage: any; ReadableStream: infer T } ? T + : typeof webstreams.ReadableStream; + + interface ReadableStreamBYOBReader extends _ReadableStreamBYOBReader {} + var ReadableStreamBYOBReader: typeof globalThis extends { onmessage: any; ReadableStreamBYOBReader: infer T } ? T + : typeof webstreams.ReadableStreamBYOBReader; + + interface ReadableStreamBYOBRequest extends _ReadableStreamBYOBRequest {} + var ReadableStreamBYOBRequest: typeof globalThis extends { onmessage: any; ReadableStreamBYOBRequest: infer T } ? T + : typeof webstreams.ReadableStreamBYOBRequest; + + interface ReadableStreamDefaultController<R = any> extends _ReadableStreamDefaultController<R> {} + var ReadableStreamDefaultController: typeof globalThis extends + { onmessage: any; ReadableStreamDefaultController: infer T } ? T + : typeof webstreams.ReadableStreamDefaultController; + + interface ReadableStreamDefaultReader<R = any> extends _ReadableStreamDefaultReader<R> {} + var ReadableStreamDefaultReader: typeof globalThis extends { onmessage: any; ReadableStreamDefaultReader: infer T } + ? T + : typeof webstreams.ReadableStreamDefaultReader; + + interface TextDecoderStream extends _TextDecoderStream {} + var TextDecoderStream: typeof globalThis extends { onmessage: any; TextDecoderStream: infer T } ? T + : typeof webstreams.TextDecoderStream; + + interface TextEncoderStream extends _TextEncoderStream {} + var TextEncoderStream: typeof globalThis extends { onmessage: any; TextEncoderStream: infer T } ? T + : typeof webstreams.TextEncoderStream; + + interface TransformStream<I = any, O = any> extends _TransformStream<I, O> {} + var TransformStream: typeof globalThis extends { onmessage: any; TransformStream: infer T } ? T + : typeof webstreams.TransformStream; + + interface TransformStreamDefaultController<O = any> extends _TransformStreamDefaultController<O> {} + var TransformStreamDefaultController: typeof globalThis extends + { onmessage: any; TransformStreamDefaultController: infer T } ? T + : typeof webstreams.TransformStreamDefaultController; + + interface WritableStream<W = any> extends _WritableStream<W> {} + var WritableStream: typeof globalThis extends { onmessage: any; WritableStream: infer T } ? T + : typeof webstreams.WritableStream; + + interface WritableStreamDefaultController extends _WritableStreamDefaultController {} + var WritableStreamDefaultController: typeof globalThis extends + { onmessage: any; WritableStreamDefaultController: infer T } ? T + : typeof webstreams.WritableStreamDefaultController; + + interface WritableStreamDefaultWriter<W = any> extends _WritableStreamDefaultWriter<W> {} + var WritableStreamDefaultWriter: typeof globalThis extends { onmessage: any; WritableStreamDefaultWriter: infer T } + ? T + : typeof webstreams.WritableStreamDefaultWriter; +} diff --git a/server/node_modules/@types/node/web-globals/timers.d.ts b/server/node_modules/@types/node/web-globals/timers.d.ts new file mode 100644 index 0000000..9f84a3e --- /dev/null +++ b/server/node_modules/@types/node/web-globals/timers.d.ts @@ -0,0 +1,44 @@ +export {}; + +import * as promises from "node:timers/promises"; + +// Note: The timer function definitions allow a single void-accepting argument +// to be optional in arguments lists. This allows usage such as +// `new Promise(resolve => setTimeout(resolve, ms))` (#54258) +// eslint-disable-next-line @typescript-eslint/no-invalid-void-type +type MakeVoidParameterOptional<TArgs extends any[]> = [void] extends TArgs ? Partial<TArgs> : TArgs; + +declare global { + function setImmediate<TArgs extends any[]>( + callback: (...args: TArgs) => void, + ...args: MakeVoidParameterOptional<TArgs> + ): NodeJS.Immediate; + namespace setImmediate { + import __promisify__ = promises.setImmediate; + export { __promisify__ }; + } + + function setInterval<TArgs extends any[]>( + callback: (...args: TArgs) => void, + delay?: number, + ...args: MakeVoidParameterOptional<TArgs> + ): NodeJS.Timeout; + + function setTimeout<TArgs extends any[]>( + callback: (...args: TArgs) => void, + delay?: number, + ...args: MakeVoidParameterOptional<TArgs> + ): NodeJS.Timeout; + namespace setTimeout { + import __promisify__ = promises.setTimeout; + export { __promisify__ }; + } + + function clearImmediate(immediate: NodeJS.Immediate | undefined): void; + + function clearInterval(timeout: NodeJS.Timeout | string | number | undefined): void; + + function clearTimeout(timeout: NodeJS.Timeout | string | number | undefined): void; + + function queueMicrotask(callback: () => void): void; +} diff --git a/server/node_modules/@types/node/web-globals/url.d.ts b/server/node_modules/@types/node/web-globals/url.d.ts new file mode 100644 index 0000000..d30208b --- /dev/null +++ b/server/node_modules/@types/node/web-globals/url.d.ts @@ -0,0 +1,24 @@ +export {}; + +import * as url from "node:url"; + +declare global { + interface URL extends url.URL {} + var URL: typeof globalThis extends { onmessage: any; URL: infer T } ? T : typeof url.URL; + + interface URLPattern extends url.URLPattern {} + var URLPattern: typeof globalThis extends { + onmessage: any; + scheduler: any; // Must be a var introduced at the same time as URLPattern. + URLPattern: infer T; + } ? T + : typeof url.URLPattern; + + interface URLPatternInit extends url.URLPatternInit {} + + interface URLPatternResult extends url.URLPatternResult {} + + interface URLSearchParams extends url.URLSearchParams {} + var URLSearchParams: typeof globalThis extends { onmessage: any; URLSearchParams: infer T } ? T + : typeof url.URLSearchParams; +} diff --git a/server/node_modules/@types/node/worker_threads.d.ts b/server/node_modules/@types/node/worker_threads.d.ts new file mode 100644 index 0000000..1654e4a --- /dev/null +++ b/server/node_modules/@types/node/worker_threads.d.ts @@ -0,0 +1,717 @@ +/** + * The `node:worker_threads` module enables the use of threads that execute + * JavaScript in parallel. To access it: + * + * ```js + * import worker from 'node:worker_threads'; + * ``` + * + * Workers (threads) are useful for performing CPU-intensive JavaScript operations. + * They do not help much with I/O-intensive work. The Node.js built-in + * asynchronous I/O operations are more efficient than Workers can be. + * + * Unlike `child_process` or `cluster`, `worker_threads` can share memory. They do + * so by transferring `ArrayBuffer` instances or sharing `SharedArrayBuffer` instances. + * + * ```js + * import { + * Worker, + * isMainThread, + * parentPort, + * workerData, + * } from 'node:worker_threads'; + * + * if (!isMainThread) { + * const { parse } = await import('some-js-parsing-library'); + * const script = workerData; + * parentPort.postMessage(parse(script)); + * } + * + * export default function parseJSAsync(script) { + * return new Promise((resolve, reject) => { + * const worker = new Worker(new URL(import.meta.url), { + * workerData: script, + * }); + * worker.on('message', resolve); + * worker.on('error', reject); + * worker.on('exit', (code) => { + * if (code !== 0) + * reject(new Error(`Worker stopped with exit code ${code}`)); + * }); + * }); + * }; + * ``` + * + * The above example spawns a Worker thread for each `parseJSAsync()` call. In + * practice, use a pool of Workers for these kinds of tasks. Otherwise, the + * overhead of creating Workers would likely exceed their benefit. + * + * When implementing a worker pool, use the `AsyncResource` API to inform + * diagnostic tools (e.g. to provide asynchronous stack traces) about the + * correlation between tasks and their outcomes. See `"Using AsyncResource for a Worker thread pool"` in the `async_hooks` documentation for an example implementation. + * + * Worker threads inherit non-process-specific options by default. Refer to `Worker constructor options` to know how to customize worker thread options, + * specifically `argv` and `execArgv` options. + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/worker_threads.js) + */ +declare module "node:worker_threads" { + import { + EventEmitter, + InternalEventEmitter, + InternalEventTargetEventProperties, + NodeEventTarget, + } from "node:events"; + import { FileHandle } from "node:fs/promises"; + import { Performance } from "node:perf_hooks"; + import { Readable, Writable } from "node:stream"; + import { ReadableStream, TransformStream, WritableStream } from "node:stream/web"; + import { URL } from "node:url"; + import { CPUProfileHandle, HeapInfo, HeapProfileHandle } from "node:v8"; + import { Context } from "node:vm"; + import { MessageEvent } from "undici-types"; + const isInternalThread: boolean; + const isMainThread: boolean; + const parentPort: null | MessagePort; + const resourceLimits: ResourceLimits; + const SHARE_ENV: unique symbol; + const threadId: number; + const threadName: string | null; + const workerData: any; + interface WorkerPerformance extends Pick<Performance, "eventLoopUtilization"> {} + /** @deprecated Use `import { Transferable } from "node:worker_threads"` instead. */ + // TODO: remove in a future major @types/node version. + type TransferListItem = Transferable; + interface WorkerOptions { + /** + * List of arguments which would be stringified and appended to + * `process.argv` in the worker. This is mostly similar to the `workerData` + * but the values will be available on the global `process.argv` as if they + * were passed as CLI options to the script. + */ + argv?: any[] | undefined; + env?: NodeJS.Dict<string> | typeof SHARE_ENV | undefined; + eval?: boolean | undefined; + workerData?: any; + stdin?: boolean | undefined; + stdout?: boolean | undefined; + stderr?: boolean | undefined; + execArgv?: string[] | undefined; + resourceLimits?: ResourceLimits | undefined; + /** + * Additional data to send in the first worker message. + */ + transferList?: Transferable[] | undefined; + /** + * @default true + */ + trackUnmanagedFds?: boolean | undefined; + /** + * An optional `name` to be appended to the worker title + * for debugging/identification purposes, making the final title as + * `[worker ${id}] ${name}`. + */ + name?: string | undefined; + } + interface ResourceLimits { + /** + * The maximum size of a heap space for recently created objects. + */ + maxYoungGenerationSizeMb?: number | undefined; + /** + * The maximum size of the main heap in MB. + */ + maxOldGenerationSizeMb?: number | undefined; + /** + * The size of a pre-allocated memory range used for generated code. + */ + codeRangeSizeMb?: number | undefined; + /** + * The default maximum stack size for the thread. Small values may lead to unusable Worker instances. + * @default 4 + */ + stackSizeMb?: number | undefined; + } + interface WorkerEventMap { + "error": [err: unknown]; + "exit": [exitCode: number]; + "message": [value: any]; + "messageerror": [error: Error]; + "online": []; + } + /** + * The `Worker` class represents an independent JavaScript execution thread. + * Most Node.js APIs are available inside of it. + * + * Notable differences inside a Worker environment are: + * + * * The `process.stdin`, `process.stdout`, and `process.stderr` streams may be redirected by the parent thread. + * * The `import { isMainThread } from 'node:worker_threads'` variable is set to `false`. + * * The `import { parentPort } from 'node:worker_threads'` message port is available. + * * `process.exit()` does not stop the whole program, just the single thread, + * and `process.abort()` is not available. + * * `process.chdir()` and `process` methods that set group or user ids + * are not available. + * * `process.env` is a copy of the parent thread's environment variables, + * unless otherwise specified. Changes to one copy are not visible in other + * threads, and are not visible to native add-ons (unless `worker.SHARE_ENV` is passed as the `env` option to the `Worker` constructor). On Windows, unlike the main thread, a copy of the + * environment variables operates in a case-sensitive manner. + * * `process.title` cannot be modified. + * * Signals are not delivered through `process.on('...')`. + * * Execution may stop at any point as a result of `worker.terminate()` being invoked. + * * IPC channels from parent processes are not accessible. + * * The `trace_events` module is not supported. + * * Native add-ons can only be loaded from multiple threads if they fulfill `certain conditions`. + * + * Creating `Worker` instances inside of other `Worker`s is possible. + * + * Like [Web Workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API) and the `node:cluster module`, two-way communication + * can be achieved through inter-thread message passing. Internally, a `Worker` has + * a built-in pair of `MessagePort` s that are already associated with each + * other when the `Worker` is created. While the `MessagePort` object on the parent + * side is not directly exposed, its functionalities are exposed through `worker.postMessage()` and the `worker.on('message')` event + * on the `Worker` object for the parent thread. + * + * To create custom messaging channels (which is encouraged over using the default + * global channel because it facilitates separation of concerns), users can create + * a `MessageChannel` object on either thread and pass one of the`MessagePort`s on that `MessageChannel` to the other thread through a + * pre-existing channel, such as the global one. + * + * See `port.postMessage()` for more information on how messages are passed, + * and what kind of JavaScript values can be successfully transported through + * the thread barrier. + * + * ```js + * import assert from 'node:assert'; + * import { + * Worker, MessageChannel, MessagePort, isMainThread, parentPort, + * } from 'node:worker_threads'; + * if (isMainThread) { + * const worker = new Worker(__filename); + * const subChannel = new MessageChannel(); + * worker.postMessage({ hereIsYourPort: subChannel.port1 }, [subChannel.port1]); + * subChannel.port2.on('message', (value) => { + * console.log('received:', value); + * }); + * } else { + * parentPort.once('message', (value) => { + * assert(value.hereIsYourPort instanceof MessagePort); + * value.hereIsYourPort.postMessage('the worker is sending this'); + * value.hereIsYourPort.close(); + * }); + * } + * ``` + * @since v10.5.0 + */ + class Worker implements EventEmitter { + /** + * If `stdin: true` was passed to the `Worker` constructor, this is a + * writable stream. The data written to this stream will be made available in + * the worker thread as `process.stdin`. + * @since v10.5.0 + */ + readonly stdin: Writable | null; + /** + * This is a readable stream which contains data written to `process.stdout` inside the worker thread. If `stdout: true` was not passed to the `Worker` constructor, then data is piped to the + * parent thread's `process.stdout` stream. + * @since v10.5.0 + */ + readonly stdout: Readable; + /** + * This is a readable stream which contains data written to `process.stderr` inside the worker thread. If `stderr: true` was not passed to the `Worker` constructor, then data is piped to the + * parent thread's `process.stderr` stream. + * @since v10.5.0 + */ + readonly stderr: Readable; + /** + * An integer identifier for the referenced thread. Inside the worker thread, + * it is available as `import { threadId } from 'node:worker_threads'`. + * This value is unique for each `Worker` instance inside a single process. + * @since v10.5.0 + */ + readonly threadId: number; + /** + * A string identifier for the referenced thread or null if the thread is not running. + * Inside the worker thread, it is available as `require('node:worker_threads').threadName`. + * @since v24.6.0 + */ + readonly threadName: string | null; + /** + * Provides the set of JS engine resource constraints for this Worker thread. + * If the `resourceLimits` option was passed to the `Worker` constructor, + * this matches its values. + * + * If the worker has stopped, the return value is an empty object. + * @since v13.2.0, v12.16.0 + */ + readonly resourceLimits?: ResourceLimits | undefined; + /** + * An object that can be used to query performance information from a worker + * instance. Similar to `perf_hooks.performance`. + * @since v15.1.0, v14.17.0, v12.22.0 + */ + readonly performance: WorkerPerformance; + /** + * @param filename The path to the Worker’s main script or module. + * Must be either an absolute path or a relative path (i.e. relative to the current working directory) starting with ./ or ../, + * or a WHATWG URL object using file: protocol. If options.eval is true, this is a string containing JavaScript code rather than a path. + */ + constructor(filename: string | URL, options?: WorkerOptions); + /** + * Send a message to the worker that is received via `require('node:worker_threads').parentPort.on('message')`. + * See `port.postMessage()` for more details. + * @since v10.5.0 + */ + postMessage(value: any, transferList?: readonly Transferable[]): void; + /** + * Opposite of `unref()`, calling `ref()` on a previously `unref()`ed worker does _not_ let the program exit if it's the only active handle left (the default + * behavior). If the worker is `ref()`ed, calling `ref()` again has + * no effect. + * @since v10.5.0 + */ + ref(): void; + /** + * Calling `unref()` on a worker allows the thread to exit if this is the only + * active handle in the event system. If the worker is already `unref()`ed calling `unref()` again has no effect. + * @since v10.5.0 + */ + unref(): void; + /** + * Stop all JavaScript execution in the worker thread as soon as possible. + * Returns a Promise for the exit code that is fulfilled when the `'exit' event` is emitted. + * @since v10.5.0 + */ + terminate(): Promise<number>; + /** + * This method returns a `Promise` that will resolve to an object identical to `process.threadCpuUsage()`, + * or reject with an `ERR_WORKER_NOT_RUNNING` error if the worker is no longer running. + * This methods allows the statistics to be observed from outside the actual thread. + * @since v24.6.0 + */ + cpuUsage(prev?: NodeJS.CpuUsage): Promise<NodeJS.CpuUsage>; + /** + * Returns a readable stream for a V8 snapshot of the current state of the Worker. + * See `v8.getHeapSnapshot()` for more details. + * + * If the Worker thread is no longer running, which may occur before the `'exit' event` is emitted, the returned `Promise` is rejected + * immediately with an `ERR_WORKER_NOT_RUNNING` error. + * @since v13.9.0, v12.17.0 + * @return A promise for a Readable Stream containing a V8 heap snapshot + */ + getHeapSnapshot(): Promise<Readable>; + /** + * This method returns a `Promise` that will resolve to an object identical to `v8.getHeapStatistics()`, + * or reject with an `ERR_WORKER_NOT_RUNNING` error if the worker is no longer running. + * This methods allows the statistics to be observed from outside the actual thread. + * @since v24.0.0 + */ + getHeapStatistics(): Promise<HeapInfo>; + /** + * Starting a CPU profile then return a Promise that fulfills with an error + * or an `CPUProfileHandle` object. This API supports `await using` syntax. + * + * ```js + * const { Worker } = require('node:worker_threads'); + * + * const worker = new Worker(` + * const { parentPort } = require('worker_threads'); + * parentPort.on('message', () => {}); + * `, { eval: true }); + * + * worker.on('online', async () => { + * const handle = await worker.startCpuProfile(); + * const profile = await handle.stop(); + * console.log(profile); + * worker.terminate(); + * }); + * ``` + * + * `await using` example. + * + * ```js + * const { Worker } = require('node:worker_threads'); + * + * const w = new Worker(` + * const { parentPort } = require('node:worker_threads'); + * parentPort.on('message', () => {}); + * `, { eval: true }); + * + * w.on('online', async () => { + * // Stop profile automatically when return and profile will be discarded + * await using handle = await w.startCpuProfile(); + * }); + * ``` + * @since v24.8.0 + */ + startCpuProfile(): Promise<CPUProfileHandle>; + /** + * Starting a Heap profile then return a Promise that fulfills with an error + * or an `HeapProfileHandle` object. This API supports `await using` syntax. + * + * ```js + * const { Worker } = require('node:worker_threads'); + * + * const worker = new Worker(` + * const { parentPort } = require('worker_threads'); + * parentPort.on('message', () => {}); + * `, { eval: true }); + * + * worker.on('online', async () => { + * const handle = await worker.startHeapProfile(); + * const profile = await handle.stop(); + * console.log(profile); + * worker.terminate(); + * }); + * ``` + * + * `await using` example. + * + * ```js + * const { Worker } = require('node:worker_threads'); + * + * const w = new Worker(` + * const { parentPort } = require('node:worker_threads'); + * parentPort.on('message', () => {}); + * `, { eval: true }); + * + * w.on('online', async () => { + * // Stop profile automatically when return and profile will be discarded + * await using handle = await w.startHeapProfile(); + * }); + * ``` + */ + startHeapProfile(): Promise<HeapProfileHandle>; + /** + * Calls `worker.terminate()` when the dispose scope is exited. + * + * ```js + * async function example() { + * await using worker = new Worker('for (;;) {}', { eval: true }); + * // Worker is automatically terminate when the scope is exited. + * } + * ``` + * @since v24.2.0 + */ + [Symbol.asyncDispose](): Promise<void>; + } + interface Worker extends InternalEventEmitter<WorkerEventMap> {} + /** + * Mark an object as not transferable. If `object` occurs in the transfer list of + * a `port.postMessage()` call, it is ignored. + * + * In particular, this makes sense for objects that can be cloned, rather than + * transferred, and which are used by other objects on the sending side. + * For example, Node.js marks the `ArrayBuffer`s it uses for its `Buffer pool` with this. + * + * This operation cannot be undone. + * + * ```js + * import { MessageChannel, markAsUntransferable } from 'node:worker_threads'; + * + * const pooledBuffer = new ArrayBuffer(8); + * const typedArray1 = new Uint8Array(pooledBuffer); + * const typedArray2 = new Float64Array(pooledBuffer); + * + * markAsUntransferable(pooledBuffer); + * + * const { port1 } = new MessageChannel(); + * port1.postMessage(typedArray1, [ typedArray1.buffer ]); + * + * // The following line prints the contents of typedArray1 -- it still owns + * // its memory and has been cloned, not transferred. Without + * // `markAsUntransferable()`, this would print an empty Uint8Array. + * // typedArray2 is intact as well. + * console.log(typedArray1); + * console.log(typedArray2); + * ``` + * + * There is no equivalent to this API in browsers. + * @since v14.5.0, v12.19.0 + */ + function markAsUntransferable(object: object): void; + /** + * Check if an object is marked as not transferable with + * {@link markAsUntransferable}. + * @since v21.0.0 + */ + function isMarkedAsUntransferable(object: object): boolean; + /** + * Mark an object as not cloneable. If `object` is used as `message` in + * a `port.postMessage()` call, an error is thrown. This is a no-op if `object` is a + * primitive value. + * + * This has no effect on `ArrayBuffer`, or any `Buffer` like objects. + * + * This operation cannot be undone. + * + * ```js + * const { markAsUncloneable } = require('node:worker_threads'); + * + * const anyObject = { foo: 'bar' }; + * markAsUncloneable(anyObject); + * const { port1 } = new MessageChannel(); + * try { + * // This will throw an error, because anyObject is not cloneable. + * port1.postMessage(anyObject) + * } catch (error) { + * // error.name === 'DataCloneError' + * } + * ``` + * + * There is no equivalent to this API in browsers. + * @since v22.10.0 + */ + function markAsUncloneable(object: object): void; + /** + * Transfer a `MessagePort` to a different `vm` Context. The original `port` object is rendered unusable, and the returned `MessagePort` instance + * takes its place. + * + * The returned `MessagePort` is an object in the target context and + * inherits from its global `Object` class. Objects passed to the [`port.onmessage()`](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort/onmessage) listener are also created in the + * target context + * and inherit from its global `Object` class. + * + * However, the created `MessagePort` no longer inherits from [`EventTarget`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget), and only + * [`port.onmessage()`](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort/onmessage) can be used to receive + * events using it. + * @since v11.13.0 + * @param port The message port to transfer. + * @param contextifiedSandbox A `contextified` object as returned by the `vm.createContext()` method. + */ + function moveMessagePortToContext(port: MessagePort, contextifiedSandbox: Context): MessagePort; + /** + * Receive a single message from a given `MessagePort`. If no message is available,`undefined` is returned, otherwise an object with a single `message` property + * that contains the message payload, corresponding to the oldest message in the `MessagePort`'s queue. + * + * ```js + * import { MessageChannel, receiveMessageOnPort } from 'node:worker_threads'; + * const { port1, port2 } = new MessageChannel(); + * port1.postMessage({ hello: 'world' }); + * + * console.log(receiveMessageOnPort(port2)); + * // Prints: { message: { hello: 'world' } } + * console.log(receiveMessageOnPort(port2)); + * // Prints: undefined + * ``` + * + * When this function is used, no `'message'` event is emitted and the `onmessage` listener is not invoked. + * @since v12.3.0 + */ + function receiveMessageOnPort(port: MessagePort): + | { + message: any; + } + | undefined; + type Serializable = string | object | number | boolean | bigint; + /** + * Within a worker thread, `worker.getEnvironmentData()` returns a clone + * of data passed to the spawning thread's `worker.setEnvironmentData()`. + * Every new `Worker` receives its own copy of the environment data + * automatically. + * + * ```js + * import { + * Worker, + * isMainThread, + * setEnvironmentData, + * getEnvironmentData, + * } from 'node:worker_threads'; + * + * if (isMainThread) { + * setEnvironmentData('Hello', 'World!'); + * const worker = new Worker(__filename); + * } else { + * console.log(getEnvironmentData('Hello')); // Prints 'World!'. + * } + * ``` + * @since v15.12.0, v14.18.0 + * @param key Any arbitrary, cloneable JavaScript value that can be used as a {Map} key. + */ + function getEnvironmentData(key: Serializable): Serializable; + /** + * The `worker.setEnvironmentData()` API sets the content of `worker.getEnvironmentData()` in the current thread and all new `Worker` instances spawned from the current context. + * @since v15.12.0, v14.18.0 + * @param key Any arbitrary, cloneable JavaScript value that can be used as a {Map} key. + * @param value Any arbitrary, cloneable JavaScript value that will be cloned and passed automatically to all new `Worker` instances. If `value` is passed as `undefined`, any previously set value + * for the `key` will be deleted. + */ + function setEnvironmentData(key: Serializable, value?: Serializable): void; + /** + * Sends a value to another worker, identified by its thread ID. + * @param threadId The target thread ID. If the thread ID is invalid, a `ERR_WORKER_MESSAGING_FAILED` error will be thrown. + * If the target thread ID is the current thread ID, a `ERR_WORKER_MESSAGING_SAME_THREAD` error will be thrown. + * @param value The value to send. + * @param transferList If one or more `MessagePort`-like objects are passed in value, a `transferList` is required for those items + * or `ERR_MISSING_MESSAGE_PORT_IN_TRANSFER_LIST` is thrown. See `port.postMessage()` for more information. + * @param timeout Time to wait for the message to be delivered in milliseconds. By default it's `undefined`, which means wait forever. + * If the operation times out, a `ERR_WORKER_MESSAGING_TIMEOUT` error is thrown. + * @since v22.5.0 + */ + function postMessageToThread(threadId: number, value: any, timeout?: number): Promise<void>; + function postMessageToThread( + threadId: number, + value: any, + transferList: readonly Transferable[], + timeout?: number, + ): Promise<void>; + // #region web types + type LockMode = "exclusive" | "shared"; + type Transferable = + | ArrayBuffer + | MessagePort + | AbortSignal + | FileHandle + | ReadableStream + | WritableStream + | TransformStream; + interface LockGrantedCallback<T> { + (lock: Lock | null): T; + } + interface LockInfo { + clientId: string; + mode: LockMode; + name: string; + } + interface LockManagerSnapshot { + held: LockInfo[]; + pending: LockInfo[]; + } + interface LockOptions { + ifAvailable?: boolean; + mode?: LockMode; + signal?: AbortSignal; + steal?: boolean; + } + interface StructuredSerializeOptions { + transfer?: Transferable[]; + } + interface BroadcastChannelEventMap { + "message": MessageEvent; + "messageerror": MessageEvent; + } + interface BroadcastChannel + extends EventTarget, InternalEventTargetEventProperties<BroadcastChannelEventMap>, NodeJS.RefCounted + { + readonly name: string; + close(): void; + postMessage(message: any): void; + addEventListener<K extends keyof BroadcastChannelEventMap>( + type: K, + listener: (ev: BroadcastChannelEventMap[K]) => void, + options?: AddEventListenerOptions | boolean, + ): void; + addEventListener( + type: string, + listener: EventListener | EventListenerObject, + options?: AddEventListenerOptions | boolean, + ): void; + removeEventListener<K extends keyof BroadcastChannelEventMap>( + type: K, + listener: (ev: BroadcastChannelEventMap[K]) => void, + options?: EventListenerOptions | boolean, + ): void; + removeEventListener( + type: string, + listener: EventListener | EventListenerObject, + options?: EventListenerOptions | boolean, + ): void; + } + var BroadcastChannel: { + prototype: BroadcastChannel; + new(name: string): BroadcastChannel; + }; + interface Lock { + readonly mode: LockMode; + readonly name: string; + } + // var Lock: { + // prototype: Lock; + // new(): Lock; + // }; + interface LockManager { + query(): Promise<LockManagerSnapshot>; + request<T>(name: string, callback: LockGrantedCallback<T>): Promise<Awaited<T>>; + request<T>(name: string, options: LockOptions, callback: LockGrantedCallback<T>): Promise<Awaited<T>>; + } + // var LockManager: { + // prototype: LockManager; + // new(): LockManager; + // }; + interface MessageChannel { + readonly port1: MessagePort; + readonly port2: MessagePort; + } + var MessageChannel: { + prototype: MessageChannel; + new(): MessageChannel; + }; + interface MessagePortEventMap { + "close": Event; + "message": MessageEvent; + "messageerror": MessageEvent; + } + interface MessagePort extends NodeEventTarget, InternalEventTargetEventProperties<MessagePortEventMap> { + close(): void; + postMessage(message: any, transfer: Transferable[]): void; + postMessage(message: any, options?: StructuredSerializeOptions): void; + start(): void; + hasRef(): boolean; + ref(): void; + unref(): void; + addEventListener<K extends keyof MessagePortEventMap>( + type: K, + listener: (ev: MessagePortEventMap[K]) => void, + options?: AddEventListenerOptions | boolean, + ): void; + addEventListener( + type: string, + listener: EventListener | EventListenerObject, + options?: AddEventListenerOptions | boolean, + ): void; + removeEventListener<K extends keyof MessagePortEventMap>( + type: K, + listener: (ev: MessagePortEventMap[K]) => void, + options?: EventListenerOptions | boolean, + ): void; + removeEventListener( + type: string, + listener: EventListener | EventListenerObject, + options?: EventListenerOptions | boolean, + ): void; + // #region NodeEventTarget + addListener(event: "close", listener: (ev: Event) => void): this; + addListener(event: "message", listener: (value: any) => void): this; + addListener(event: "messageerror", listener: (error: Error) => void): this; + addListener(event: string, listener: (arg: any) => void): this; + emit(event: "close", ev: Event): boolean; + emit(event: "message", value: any): boolean; + emit(event: "messageerror", error: Error): boolean; + emit(event: string, arg: any): boolean; + off(event: "close", listener: (ev: Event) => void, options?: EventListenerOptions): this; + off(event: "message", listener: (value: any) => void, options?: EventListenerOptions): this; + off(event: "messageerror", listener: (error: Error) => void, options?: EventListenerOptions): this; + off(event: string, listener: (arg: any) => void, options?: EventListenerOptions): this; + on(event: "close", listener: (ev: Event) => void): this; + on(event: "message", listener: (value: any) => void): this; + on(event: "messageerror", listener: (error: Error) => void): this; + on(event: string, listener: (arg: any) => void): this; + once(event: "close", listener: (ev: Event) => void): this; + once(event: "message", listener: (value: any) => void): this; + once(event: "messageerror", listener: (error: Error) => void): this; + once(event: string, listener: (arg: any) => void): this; + removeListener(event: "close", listener: (ev: Event) => void, options?: EventListenerOptions): this; + removeListener(event: "message", listener: (value: any) => void, options?: EventListenerOptions): this; + removeListener(event: "messageerror", listener: (error: Error) => void, options?: EventListenerOptions): this; + removeListener(event: string, listener: (arg: any) => void, options?: EventListenerOptions): this; + // #endregion + } + var MessagePort: { + prototype: MessagePort; + new(): MessagePort; + }; + var locks: LockManager; + export import structuredClone = globalThis.structuredClone; + // #endregion +} +declare module "worker_threads" { + export * from "node:worker_threads"; +} diff --git a/server/node_modules/@types/node/zlib.d.ts b/server/node_modules/@types/node/zlib.d.ts new file mode 100644 index 0000000..51f1a22 --- /dev/null +++ b/server/node_modules/@types/node/zlib.d.ts @@ -0,0 +1,618 @@ +/** + * The `node:zlib` module provides compression functionality implemented using + * Gzip, Deflate/Inflate, and Brotli. + * + * To access it: + * + * ```js + * import zlib from 'node:zlib'; + * ``` + * + * Compression and decompression are built around the Node.js + * [Streams API](https://nodejs.org/docs/latest-v25.x/api/stream.html). + * + * Compressing or decompressing a stream (such as a file) can be accomplished by + * piping the source stream through a `zlib` `Transform` stream into a destination + * stream: + * + * ```js + * import { createGzip } from 'node:zlib'; + * import { pipeline } from 'node:stream'; + * import { + * createReadStream, + * createWriteStream, + * } from 'node:fs'; + * + * const gzip = createGzip(); + * const source = createReadStream('input.txt'); + * const destination = createWriteStream('input.txt.gz'); + * + * pipeline(source, gzip, destination, (err) => { + * if (err) { + * console.error('An error occurred:', err); + * process.exitCode = 1; + * } + * }); + * + * // Or, Promisified + * + * import { promisify } from 'node:util'; + * const pipe = promisify(pipeline); + * + * async function do_gzip(input, output) { + * const gzip = createGzip(); + * const source = createReadStream(input); + * const destination = createWriteStream(output); + * await pipe(source, gzip, destination); + * } + * + * do_gzip('input.txt', 'input.txt.gz') + * .catch((err) => { + * console.error('An error occurred:', err); + * process.exitCode = 1; + * }); + * ``` + * + * It is also possible to compress or decompress data in a single step: + * + * ```js + * import { deflate, unzip } from 'node:zlib'; + * + * const input = '.................................'; + * deflate(input, (err, buffer) => { + * if (err) { + * console.error('An error occurred:', err); + * process.exitCode = 1; + * } + * console.log(buffer.toString('base64')); + * }); + * + * const buffer = Buffer.from('eJzT0yMAAGTvBe8=', 'base64'); + * unzip(buffer, (err, buffer) => { + * if (err) { + * console.error('An error occurred:', err); + * process.exitCode = 1; + * } + * console.log(buffer.toString()); + * }); + * + * // Or, Promisified + * + * import { promisify } from 'node:util'; + * const do_unzip = promisify(unzip); + * + * do_unzip(buffer) + * .then((buf) => console.log(buf.toString())) + * .catch((err) => { + * console.error('An error occurred:', err); + * process.exitCode = 1; + * }); + * ``` + * @since v0.5.8 + * @see [source](https://github.com/nodejs/node/blob/v25.x/lib/zlib.js) + */ +declare module "node:zlib" { + import { NonSharedBuffer } from "node:buffer"; + import * as stream from "node:stream"; + interface ZlibOptions { + /** + * @default constants.Z_NO_FLUSH + */ + flush?: number | undefined; + /** + * @default constants.Z_FINISH + */ + finishFlush?: number | undefined; + /** + * @default 16*1024 + */ + chunkSize?: number | undefined; + windowBits?: number | undefined; + level?: number | undefined; // compression only + memLevel?: number | undefined; // compression only + strategy?: number | undefined; // compression only + dictionary?: NodeJS.ArrayBufferView | ArrayBuffer | undefined; // deflate/inflate only, empty dictionary by default + /** + * If `true`, returns an object with `buffer` and `engine`. + */ + info?: boolean | undefined; + /** + * Limits output size when using convenience methods. + * @default buffer.kMaxLength + */ + maxOutputLength?: number | undefined; + } + interface BrotliOptions { + /** + * @default constants.BROTLI_OPERATION_PROCESS + */ + flush?: number | undefined; + /** + * @default constants.BROTLI_OPERATION_FINISH + */ + finishFlush?: number | undefined; + /** + * @default 16*1024 + */ + chunkSize?: number | undefined; + params?: + | { + /** + * Each key is a `constants.BROTLI_*` constant. + */ + [key: number]: boolean | number; + } + | undefined; + /** + * Limits output size when using [convenience methods](https://nodejs.org/docs/latest-v25.x/api/zlib.html#convenience-methods). + * @default buffer.kMaxLength + */ + maxOutputLength?: number | undefined; + /** + * If `true`, returns an object with `buffer` and `engine`. + */ + info?: boolean | undefined; + } + interface ZstdOptions { + /** + * @default constants.ZSTD_e_continue + */ + flush?: number | undefined; + /** + * @default constants.ZSTD_e_end + */ + finishFlush?: number | undefined; + /** + * @default 16 * 1024 + */ + chunkSize?: number | undefined; + /** + * Key-value object containing indexed + * [Zstd parameters](https://nodejs.org/docs/latest-v25.x/api/zlib.html#zstd-constants). + */ + params?: { [key: number]: number | boolean } | undefined; + /** + * Limits output size when using + * [convenience methods](https://nodejs.org/docs/latest-v25.x/api/zlib.html#convenience-methods). + * @default buffer.kMaxLength + */ + maxOutputLength?: number | undefined; + /** + * If `true`, returns an object with `buffer` and `engine`. + */ + info?: boolean | undefined; + /** + * Optional dictionary used to improve compression efficiency when compressing or decompressing data that + * shares common patterns with the dictionary. + * @since v24.6.0 + */ + dictionary?: NodeJS.ArrayBufferView | undefined; + } + interface Zlib { + readonly bytesWritten: number; + shell?: boolean | string | undefined; + close(callback?: () => void): void; + flush(kind?: number, callback?: () => void): void; + flush(callback?: () => void): void; + } + interface ZlibParams { + params(level: number, strategy: number, callback: () => void): void; + } + interface ZlibReset { + reset(): void; + } + interface BrotliCompress extends stream.Transform, Zlib {} + interface BrotliDecompress extends stream.Transform, Zlib {} + interface Gzip extends stream.Transform, Zlib {} + interface Gunzip extends stream.Transform, Zlib {} + interface Deflate extends stream.Transform, Zlib, ZlibReset, ZlibParams {} + interface Inflate extends stream.Transform, Zlib, ZlibReset {} + interface DeflateRaw extends stream.Transform, Zlib, ZlibReset, ZlibParams {} + interface InflateRaw extends stream.Transform, Zlib, ZlibReset {} + interface Unzip extends stream.Transform, Zlib {} + /** + * @since v22.15.0 + * @experimental + */ + interface ZstdCompress extends stream.Transform, Zlib {} + /** + * @since v22.15.0 + * @experimental + */ + interface ZstdDecompress extends stream.Transform, Zlib {} + /** + * Computes a 32-bit [Cyclic Redundancy Check](https://en.wikipedia.org/wiki/Cyclic_redundancy_check) checksum of `data`. + * If `value` is specified, it is used as the starting value of the checksum, otherwise, 0 is used as the starting value. + * @param data When `data` is a string, it will be encoded as UTF-8 before being used for computation. + * @param value An optional starting value. It must be a 32-bit unsigned integer. @default 0 + * @returns A 32-bit unsigned integer containing the checksum. + * @since v22.2.0 + */ + function crc32(data: string | NodeJS.ArrayBufferView, value?: number): number; + /** + * Creates and returns a new `BrotliCompress` object. + * @since v11.7.0, v10.16.0 + */ + function createBrotliCompress(options?: BrotliOptions): BrotliCompress; + /** + * Creates and returns a new `BrotliDecompress` object. + * @since v11.7.0, v10.16.0 + */ + function createBrotliDecompress(options?: BrotliOptions): BrotliDecompress; + /** + * Creates and returns a new `Gzip` object. + * See `example`. + * @since v0.5.8 + */ + function createGzip(options?: ZlibOptions): Gzip; + /** + * Creates and returns a new `Gunzip` object. + * @since v0.5.8 + */ + function createGunzip(options?: ZlibOptions): Gunzip; + /** + * Creates and returns a new `Deflate` object. + * @since v0.5.8 + */ + function createDeflate(options?: ZlibOptions): Deflate; + /** + * Creates and returns a new `Inflate` object. + * @since v0.5.8 + */ + function createInflate(options?: ZlibOptions): Inflate; + /** + * Creates and returns a new `DeflateRaw` object. + * + * An upgrade of zlib from 1.2.8 to 1.2.11 changed behavior when `windowBits` is set to 8 for raw deflate streams. zlib would automatically set `windowBits` to 9 if was initially set to 8. Newer + * versions of zlib will throw an exception, + * so Node.js restored the original behavior of upgrading a value of 8 to 9, + * since passing `windowBits = 9` to zlib actually results in a compressed stream + * that effectively uses an 8-bit window only. + * @since v0.5.8 + */ + function createDeflateRaw(options?: ZlibOptions): DeflateRaw; + /** + * Creates and returns a new `InflateRaw` object. + * @since v0.5.8 + */ + function createInflateRaw(options?: ZlibOptions): InflateRaw; + /** + * Creates and returns a new `Unzip` object. + * @since v0.5.8 + */ + function createUnzip(options?: ZlibOptions): Unzip; + /** + * Creates and returns a new `ZstdCompress` object. + * @since v22.15.0 + */ + function createZstdCompress(options?: ZstdOptions): ZstdCompress; + /** + * Creates and returns a new `ZstdDecompress` object. + * @since v22.15.0 + */ + function createZstdDecompress(options?: ZstdOptions): ZstdDecompress; + type InputType = string | ArrayBuffer | NodeJS.ArrayBufferView; + type CompressCallback = (error: Error | null, result: NonSharedBuffer) => void; + /** + * @since v11.7.0, v10.16.0 + */ + function brotliCompress(buf: InputType, options: BrotliOptions, callback: CompressCallback): void; + function brotliCompress(buf: InputType, callback: CompressCallback): void; + namespace brotliCompress { + function __promisify__(buffer: InputType, options?: BrotliOptions): Promise<NonSharedBuffer>; + } + /** + * Compress a chunk of data with `BrotliCompress`. + * @since v11.7.0, v10.16.0 + */ + function brotliCompressSync(buf: InputType, options?: BrotliOptions): NonSharedBuffer; + /** + * @since v11.7.0, v10.16.0 + */ + function brotliDecompress(buf: InputType, options: BrotliOptions, callback: CompressCallback): void; + function brotliDecompress(buf: InputType, callback: CompressCallback): void; + namespace brotliDecompress { + function __promisify__(buffer: InputType, options?: BrotliOptions): Promise<NonSharedBuffer>; + } + /** + * Decompress a chunk of data with `BrotliDecompress`. + * @since v11.7.0, v10.16.0 + */ + function brotliDecompressSync(buf: InputType, options?: BrotliOptions): NonSharedBuffer; + /** + * @since v0.6.0 + */ + function deflate(buf: InputType, callback: CompressCallback): void; + function deflate(buf: InputType, options: ZlibOptions, callback: CompressCallback): void; + namespace deflate { + function __promisify__(buffer: InputType, options?: ZlibOptions): Promise<NonSharedBuffer>; + } + /** + * Compress a chunk of data with `Deflate`. + * @since v0.11.12 + */ + function deflateSync(buf: InputType, options?: ZlibOptions): NonSharedBuffer; + /** + * @since v0.6.0 + */ + function deflateRaw(buf: InputType, callback: CompressCallback): void; + function deflateRaw(buf: InputType, options: ZlibOptions, callback: CompressCallback): void; + namespace deflateRaw { + function __promisify__(buffer: InputType, options?: ZlibOptions): Promise<NonSharedBuffer>; + } + /** + * Compress a chunk of data with `DeflateRaw`. + * @since v0.11.12 + */ + function deflateRawSync(buf: InputType, options?: ZlibOptions): NonSharedBuffer; + /** + * @since v0.6.0 + */ + function gzip(buf: InputType, callback: CompressCallback): void; + function gzip(buf: InputType, options: ZlibOptions, callback: CompressCallback): void; + namespace gzip { + function __promisify__(buffer: InputType, options?: ZlibOptions): Promise<NonSharedBuffer>; + } + /** + * Compress a chunk of data with `Gzip`. + * @since v0.11.12 + */ + function gzipSync(buf: InputType, options?: ZlibOptions): NonSharedBuffer; + /** + * @since v0.6.0 + */ + function gunzip(buf: InputType, callback: CompressCallback): void; + function gunzip(buf: InputType, options: ZlibOptions, callback: CompressCallback): void; + namespace gunzip { + function __promisify__(buffer: InputType, options?: ZlibOptions): Promise<NonSharedBuffer>; + } + /** + * Decompress a chunk of data with `Gunzip`. + * @since v0.11.12 + */ + function gunzipSync(buf: InputType, options?: ZlibOptions): NonSharedBuffer; + /** + * @since v0.6.0 + */ + function inflate(buf: InputType, callback: CompressCallback): void; + function inflate(buf: InputType, options: ZlibOptions, callback: CompressCallback): void; + namespace inflate { + function __promisify__(buffer: InputType, options?: ZlibOptions): Promise<NonSharedBuffer>; + } + /** + * Decompress a chunk of data with `Inflate`. + * @since v0.11.12 + */ + function inflateSync(buf: InputType, options?: ZlibOptions): NonSharedBuffer; + /** + * @since v0.6.0 + */ + function inflateRaw(buf: InputType, callback: CompressCallback): void; + function inflateRaw(buf: InputType, options: ZlibOptions, callback: CompressCallback): void; + namespace inflateRaw { + function __promisify__(buffer: InputType, options?: ZlibOptions): Promise<NonSharedBuffer>; + } + /** + * Decompress a chunk of data with `InflateRaw`. + * @since v0.11.12 + */ + function inflateRawSync(buf: InputType, options?: ZlibOptions): NonSharedBuffer; + /** + * @since v0.6.0 + */ + function unzip(buf: InputType, callback: CompressCallback): void; + function unzip(buf: InputType, options: ZlibOptions, callback: CompressCallback): void; + namespace unzip { + function __promisify__(buffer: InputType, options?: ZlibOptions): Promise<NonSharedBuffer>; + } + /** + * Decompress a chunk of data with `Unzip`. + * @since v0.11.12 + */ + function unzipSync(buf: InputType, options?: ZlibOptions): NonSharedBuffer; + /** + * @since v22.15.0 + * @experimental + */ + function zstdCompress(buf: InputType, callback: CompressCallback): void; + function zstdCompress(buf: InputType, options: ZstdOptions, callback: CompressCallback): void; + namespace zstdCompress { + function __promisify__(buffer: InputType, options?: ZstdOptions): Promise<NonSharedBuffer>; + } + /** + * Compress a chunk of data with `ZstdCompress`. + * @since v22.15.0 + * @experimental + */ + function zstdCompressSync(buf: InputType, options?: ZstdOptions): NonSharedBuffer; + /** + * @since v22.15.0 + * @experimental + */ + function zstdDecompress(buf: InputType, callback: CompressCallback): void; + function zstdDecompress(buf: InputType, options: ZstdOptions, callback: CompressCallback): void; + namespace zstdDecompress { + function __promisify__(buffer: InputType, options?: ZstdOptions): Promise<NonSharedBuffer>; + } + /** + * Decompress a chunk of data with `ZstdDecompress`. + * @since v22.15.0 + * @experimental + */ + function zstdDecompressSync(buf: InputType, options?: ZstdOptions): NonSharedBuffer; + namespace constants { + const BROTLI_DECODE: number; + const BROTLI_DECODER_ERROR_ALLOC_BLOCK_TYPE_TREES: number; + const BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MAP: number; + const BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES: number; + const BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_1: number; + const BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2: number; + const BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS: number; + const BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET: number; + const BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_1: number; + const BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_2: number; + const BROTLI_DECODER_ERROR_FORMAT_CL_SPACE: number; + const BROTLI_DECODER_ERROR_FORMAT_CONTEXT_MAP_REPEAT: number; + const BROTLI_DECODER_ERROR_FORMAT_DICTIONARY: number; + const BROTLI_DECODER_ERROR_FORMAT_DISTANCE: number; + const BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE: number; + const BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE: number; + const BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE: number; + const BROTLI_DECODER_ERROR_FORMAT_PADDING_1: number; + const BROTLI_DECODER_ERROR_FORMAT_PADDING_2: number; + const BROTLI_DECODER_ERROR_FORMAT_RESERVED: number; + const BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET: number; + const BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME: number; + const BROTLI_DECODER_ERROR_FORMAT_TRANSFORM: number; + const BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS: number; + const BROTLI_DECODER_ERROR_INVALID_ARGUMENTS: number; + const BROTLI_DECODER_ERROR_UNREACHABLE: number; + const BROTLI_DECODER_NEEDS_MORE_INPUT: number; + const BROTLI_DECODER_NEEDS_MORE_OUTPUT: number; + const BROTLI_DECODER_NO_ERROR: number; + const BROTLI_DECODER_PARAM_DISABLE_RING_BUFFER_REALLOCATION: number; + const BROTLI_DECODER_PARAM_LARGE_WINDOW: number; + const BROTLI_DECODER_RESULT_ERROR: number; + const BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT: number; + const BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT: number; + const BROTLI_DECODER_RESULT_SUCCESS: number; + const BROTLI_DECODER_SUCCESS: number; + const BROTLI_DEFAULT_MODE: number; + const BROTLI_DEFAULT_QUALITY: number; + const BROTLI_DEFAULT_WINDOW: number; + const BROTLI_ENCODE: number; + const BROTLI_LARGE_MAX_WINDOW_BITS: number; + const BROTLI_MAX_INPUT_BLOCK_BITS: number; + const BROTLI_MAX_QUALITY: number; + const BROTLI_MAX_WINDOW_BITS: number; + const BROTLI_MIN_INPUT_BLOCK_BITS: number; + const BROTLI_MIN_QUALITY: number; + const BROTLI_MIN_WINDOW_BITS: number; + const BROTLI_MODE_FONT: number; + const BROTLI_MODE_GENERIC: number; + const BROTLI_MODE_TEXT: number; + const BROTLI_OPERATION_EMIT_METADATA: number; + const BROTLI_OPERATION_FINISH: number; + const BROTLI_OPERATION_FLUSH: number; + const BROTLI_OPERATION_PROCESS: number; + const BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING: number; + const BROTLI_PARAM_LARGE_WINDOW: number; + const BROTLI_PARAM_LGBLOCK: number; + const BROTLI_PARAM_LGWIN: number; + const BROTLI_PARAM_MODE: number; + const BROTLI_PARAM_NDIRECT: number; + const BROTLI_PARAM_NPOSTFIX: number; + const BROTLI_PARAM_QUALITY: number; + const BROTLI_PARAM_SIZE_HINT: number; + const DEFLATE: number; + const DEFLATERAW: number; + const GUNZIP: number; + const GZIP: number; + const INFLATE: number; + const INFLATERAW: number; + const UNZIP: number; + const ZLIB_VERNUM: number; + const ZSTD_CLEVEL_DEFAULT: number; + const ZSTD_COMPRESS: number; + const ZSTD_DECOMPRESS: number; + const ZSTD_btlazy2: number; + const ZSTD_btopt: number; + const ZSTD_btultra: number; + const ZSTD_btultra2: number; + const ZSTD_c_chainLog: number; + const ZSTD_c_checksumFlag: number; + const ZSTD_c_compressionLevel: number; + const ZSTD_c_contentSizeFlag: number; + const ZSTD_c_dictIDFlag: number; + const ZSTD_c_enableLongDistanceMatching: number; + const ZSTD_c_hashLog: number; + const ZSTD_c_jobSize: number; + const ZSTD_c_ldmBucketSizeLog: number; + const ZSTD_c_ldmHashLog: number; + const ZSTD_c_ldmHashRateLog: number; + const ZSTD_c_ldmMinMatch: number; + const ZSTD_c_minMatch: number; + const ZSTD_c_nbWorkers: number; + const ZSTD_c_overlapLog: number; + const ZSTD_c_searchLog: number; + const ZSTD_c_strategy: number; + const ZSTD_c_targetLength: number; + const ZSTD_c_windowLog: number; + const ZSTD_d_windowLogMax: number; + const ZSTD_dfast: number; + const ZSTD_e_continue: number; + const ZSTD_e_end: number; + const ZSTD_e_flush: number; + const ZSTD_error_GENERIC: number; + const ZSTD_error_checksum_wrong: number; + const ZSTD_error_corruption_detected: number; + const ZSTD_error_dictionaryCreation_failed: number; + const ZSTD_error_dictionary_corrupted: number; + const ZSTD_error_dictionary_wrong: number; + const ZSTD_error_dstBuffer_null: number; + const ZSTD_error_dstSize_tooSmall: number; + const ZSTD_error_frameParameter_unsupported: number; + const ZSTD_error_frameParameter_windowTooLarge: number; + const ZSTD_error_init_missing: number; + const ZSTD_error_literals_headerWrong: number; + const ZSTD_error_maxSymbolValue_tooLarge: number; + const ZSTD_error_maxSymbolValue_tooSmall: number; + const ZSTD_error_memory_allocation: number; + const ZSTD_error_noForwardProgress_destFull: number; + const ZSTD_error_noForwardProgress_inputEmpty: number; + const ZSTD_error_no_error: number; + const ZSTD_error_parameter_combination_unsupported: number; + const ZSTD_error_parameter_outOfBound: number; + const ZSTD_error_parameter_unsupported: number; + const ZSTD_error_prefix_unknown: number; + const ZSTD_error_srcSize_wrong: number; + const ZSTD_error_stabilityCondition_notRespected: number; + const ZSTD_error_stage_wrong: number; + const ZSTD_error_tableLog_tooLarge: number; + const ZSTD_error_version_unsupported: number; + const ZSTD_error_workSpace_tooSmall: number; + const ZSTD_fast: number; + const ZSTD_greedy: number; + const ZSTD_lazy: number; + const ZSTD_lazy2: number; + const Z_BEST_COMPRESSION: number; + const Z_BEST_SPEED: number; + const Z_BLOCK: number; + const Z_BUF_ERROR: number; + const Z_DATA_ERROR: number; + const Z_DEFAULT_CHUNK: number; + const Z_DEFAULT_COMPRESSION: number; + const Z_DEFAULT_LEVEL: number; + const Z_DEFAULT_MEMLEVEL: number; + const Z_DEFAULT_STRATEGY: number; + const Z_DEFAULT_WINDOWBITS: number; + const Z_ERRNO: number; + const Z_FILTERED: number; + const Z_FINISH: number; + const Z_FIXED: number; + const Z_FULL_FLUSH: number; + const Z_HUFFMAN_ONLY: number; + const Z_MAX_CHUNK: number; + const Z_MAX_LEVEL: number; + const Z_MAX_MEMLEVEL: number; + const Z_MAX_WINDOWBITS: number; + const Z_MEM_ERROR: number; + const Z_MIN_CHUNK: number; + const Z_MIN_LEVEL: number; + const Z_MIN_MEMLEVEL: number; + const Z_MIN_WINDOWBITS: number; + const Z_NEED_DICT: number; + const Z_NO_COMPRESSION: number; + const Z_NO_FLUSH: number; + const Z_OK: number; + const Z_PARTIAL_FLUSH: number; + const Z_RLE: number; + const Z_STREAM_END: number; + const Z_STREAM_ERROR: number; + const Z_SYNC_FLUSH: number; + const Z_VERSION_ERROR: number; + } +} +declare module "zlib" { + export * from "node:zlib"; +} diff --git a/server/node_modules/accepts/HISTORY.md b/server/node_modules/accepts/HISTORY.md new file mode 100644 index 0000000..cb5990c --- /dev/null +++ b/server/node_modules/accepts/HISTORY.md @@ -0,0 +1,243 @@ +1.3.8 / 2022-02-02 +================== + + * deps: mime-types@~2.1.34 + - deps: mime-db@~1.51.0 + * deps: negotiator@0.6.3 + +1.3.7 / 2019-04-29 +================== + + * deps: negotiator@0.6.2 + - Fix sorting charset, encoding, and language with extra parameters + +1.3.6 / 2019-04-28 +================== + + * deps: mime-types@~2.1.24 + - deps: mime-db@~1.40.0 + +1.3.5 / 2018-02-28 +================== + + * deps: mime-types@~2.1.18 + - deps: mime-db@~1.33.0 + +1.3.4 / 2017-08-22 +================== + + * deps: mime-types@~2.1.16 + - deps: mime-db@~1.29.0 + +1.3.3 / 2016-05-02 +================== + + * deps: mime-types@~2.1.11 + - deps: mime-db@~1.23.0 + * deps: negotiator@0.6.1 + - perf: improve `Accept` parsing speed + - perf: improve `Accept-Charset` parsing speed + - perf: improve `Accept-Encoding` parsing speed + - perf: improve `Accept-Language` parsing speed + +1.3.2 / 2016-03-08 +================== + + * deps: mime-types@~2.1.10 + - Fix extension of `application/dash+xml` + - Update primary extension for `audio/mp4` + - deps: mime-db@~1.22.0 + +1.3.1 / 2016-01-19 +================== + + * deps: mime-types@~2.1.9 + - deps: mime-db@~1.21.0 + +1.3.0 / 2015-09-29 +================== + + * deps: mime-types@~2.1.7 + - deps: mime-db@~1.19.0 + * deps: negotiator@0.6.0 + - Fix including type extensions in parameters in `Accept` parsing + - Fix parsing `Accept` parameters with quoted equals + - Fix parsing `Accept` parameters with quoted semicolons + - Lazy-load modules from main entry point + - perf: delay type concatenation until needed + - perf: enable strict mode + - perf: hoist regular expressions + - perf: remove closures getting spec properties + - perf: remove a closure from media type parsing + - perf: remove property delete from media type parsing + +1.2.13 / 2015-09-06 +=================== + + * deps: mime-types@~2.1.6 + - deps: mime-db@~1.18.0 + +1.2.12 / 2015-07-30 +=================== + + * deps: mime-types@~2.1.4 + - deps: mime-db@~1.16.0 + +1.2.11 / 2015-07-16 +=================== + + * deps: mime-types@~2.1.3 + - deps: mime-db@~1.15.0 + +1.2.10 / 2015-07-01 +=================== + + * deps: mime-types@~2.1.2 + - deps: mime-db@~1.14.0 + +1.2.9 / 2015-06-08 +================== + + * deps: mime-types@~2.1.1 + - perf: fix deopt during mapping + +1.2.8 / 2015-06-07 +================== + + * deps: mime-types@~2.1.0 + - deps: mime-db@~1.13.0 + * perf: avoid argument reassignment & argument slice + * perf: avoid negotiator recursive construction + * perf: enable strict mode + * perf: remove unnecessary bitwise operator + +1.2.7 / 2015-05-10 +================== + + * deps: negotiator@0.5.3 + - Fix media type parameter matching to be case-insensitive + +1.2.6 / 2015-05-07 +================== + + * deps: mime-types@~2.0.11 + - deps: mime-db@~1.9.1 + * deps: negotiator@0.5.2 + - Fix comparing media types with quoted values + - Fix splitting media types with quoted commas + +1.2.5 / 2015-03-13 +================== + + * deps: mime-types@~2.0.10 + - deps: mime-db@~1.8.0 + +1.2.4 / 2015-02-14 +================== + + * Support Node.js 0.6 + * deps: mime-types@~2.0.9 + - deps: mime-db@~1.7.0 + * deps: negotiator@0.5.1 + - Fix preference sorting to be stable for long acceptable lists + +1.2.3 / 2015-01-31 +================== + + * deps: mime-types@~2.0.8 + - deps: mime-db@~1.6.0 + +1.2.2 / 2014-12-30 +================== + + * deps: mime-types@~2.0.7 + - deps: mime-db@~1.5.0 + +1.2.1 / 2014-12-30 +================== + + * deps: mime-types@~2.0.5 + - deps: mime-db@~1.3.1 + +1.2.0 / 2014-12-19 +================== + + * deps: negotiator@0.5.0 + - Fix list return order when large accepted list + - Fix missing identity encoding when q=0 exists + - Remove dynamic building of Negotiator class + +1.1.4 / 2014-12-10 +================== + + * deps: mime-types@~2.0.4 + - deps: mime-db@~1.3.0 + +1.1.3 / 2014-11-09 +================== + + * deps: mime-types@~2.0.3 + - deps: mime-db@~1.2.0 + +1.1.2 / 2014-10-14 +================== + + * deps: negotiator@0.4.9 + - Fix error when media type has invalid parameter + +1.1.1 / 2014-09-28 +================== + + * deps: mime-types@~2.0.2 + - deps: mime-db@~1.1.0 + * deps: negotiator@0.4.8 + - Fix all negotiations to be case-insensitive + - Stable sort preferences of same quality according to client order + +1.1.0 / 2014-09-02 +================== + + * update `mime-types` + +1.0.7 / 2014-07-04 +================== + + * Fix wrong type returned from `type` when match after unknown extension + +1.0.6 / 2014-06-24 +================== + + * deps: negotiator@0.4.7 + +1.0.5 / 2014-06-20 +================== + + * fix crash when unknown extension given + +1.0.4 / 2014-06-19 +================== + + * use `mime-types` + +1.0.3 / 2014-06-11 +================== + + * deps: negotiator@0.4.6 + - Order by specificity when quality is the same + +1.0.2 / 2014-05-29 +================== + + * Fix interpretation when header not in request + * deps: pin negotiator@0.4.5 + +1.0.1 / 2014-01-18 +================== + + * Identity encoding isn't always acceptable + * deps: negotiator@~0.4.0 + +1.0.0 / 2013-12-27 +================== + + * Genesis diff --git a/server/node_modules/accepts/LICENSE b/server/node_modules/accepts/LICENSE new file mode 100644 index 0000000..0616607 --- /dev/null +++ b/server/node_modules/accepts/LICENSE @@ -0,0 +1,23 @@ +(The MIT License) + +Copyright (c) 2014 Jonathan Ong <me@jongleberry.com> +Copyright (c) 2015 Douglas Christopher Wilson <doug@somethingdoug.com> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/server/node_modules/accepts/README.md b/server/node_modules/accepts/README.md new file mode 100644 index 0000000..82680c5 --- /dev/null +++ b/server/node_modules/accepts/README.md @@ -0,0 +1,140 @@ +# accepts + +[![NPM Version][npm-version-image]][npm-url] +[![NPM Downloads][npm-downloads-image]][npm-url] +[![Node.js Version][node-version-image]][node-version-url] +[![Build Status][github-actions-ci-image]][github-actions-ci-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +Higher level content negotiation based on [negotiator](https://www.npmjs.com/package/negotiator). +Extracted from [koa](https://www.npmjs.com/package/koa) for general use. + +In addition to negotiator, it allows: + +- Allows types as an array or arguments list, ie `(['text/html', 'application/json'])` + as well as `('text/html', 'application/json')`. +- Allows type shorthands such as `json`. +- Returns `false` when no types match +- Treats non-existent headers as `*` + +## Installation + +This is a [Node.js](https://nodejs.org/en/) module available through the +[npm registry](https://www.npmjs.com/). Installation is done using the +[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): + +```sh +$ npm install accepts +``` + +## API + +```js +var accepts = require('accepts') +``` + +### accepts(req) + +Create a new `Accepts` object for the given `req`. + +#### .charset(charsets) + +Return the first accepted charset. If nothing in `charsets` is accepted, +then `false` is returned. + +#### .charsets() + +Return the charsets that the request accepts, in the order of the client's +preference (most preferred first). + +#### .encoding(encodings) + +Return the first accepted encoding. If nothing in `encodings` is accepted, +then `false` is returned. + +#### .encodings() + +Return the encodings that the request accepts, in the order of the client's +preference (most preferred first). + +#### .language(languages) + +Return the first accepted language. If nothing in `languages` is accepted, +then `false` is returned. + +#### .languages() + +Return the languages that the request accepts, in the order of the client's +preference (most preferred first). + +#### .type(types) + +Return the first accepted type (and it is returned as the same text as what +appears in the `types` array). If nothing in `types` is accepted, then `false` +is returned. + +The `types` array can contain full MIME types or file extensions. Any value +that is not a full MIME types is passed to `require('mime-types').lookup`. + +#### .types() + +Return the types that the request accepts, in the order of the client's +preference (most preferred first). + +## Examples + +### Simple type negotiation + +This simple example shows how to use `accepts` to return a different typed +respond body based on what the client wants to accept. The server lists it's +preferences in order and will get back the best match between the client and +server. + +```js +var accepts = require('accepts') +var http = require('http') + +function app (req, res) { + var accept = accepts(req) + + // the order of this list is significant; should be server preferred order + switch (accept.type(['json', 'html'])) { + case 'json': + res.setHeader('Content-Type', 'application/json') + res.write('{"hello":"world!"}') + break + case 'html': + res.setHeader('Content-Type', 'text/html') + res.write('<b>hello, world!</b>') + break + default: + // the fallback is text/plain, so no need to specify it above + res.setHeader('Content-Type', 'text/plain') + res.write('hello, world!') + break + } + + res.end() +} + +http.createServer(app).listen(3000) +``` + +You can test this out with the cURL program: +```sh +curl -I -H'Accept: text/html' http://localhost:3000/ +``` + +## License + +[MIT](LICENSE) + +[coveralls-image]: https://badgen.net/coveralls/c/github/jshttp/accepts/master +[coveralls-url]: https://coveralls.io/r/jshttp/accepts?branch=master +[github-actions-ci-image]: https://badgen.net/github/checks/jshttp/accepts/master?label=ci +[github-actions-ci-url]: https://github.com/jshttp/accepts/actions/workflows/ci.yml +[node-version-image]: https://badgen.net/npm/node/accepts +[node-version-url]: https://nodejs.org/en/download +[npm-downloads-image]: https://badgen.net/npm/dm/accepts +[npm-url]: https://npmjs.org/package/accepts +[npm-version-image]: https://badgen.net/npm/v/accepts diff --git a/server/node_modules/accepts/index.js b/server/node_modules/accepts/index.js new file mode 100644 index 0000000..e9b2f63 --- /dev/null +++ b/server/node_modules/accepts/index.js @@ -0,0 +1,238 @@ +/*! + * accepts + * Copyright(c) 2014 Jonathan Ong + * Copyright(c) 2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module dependencies. + * @private + */ + +var Negotiator = require('negotiator') +var mime = require('mime-types') + +/** + * Module exports. + * @public + */ + +module.exports = Accepts + +/** + * Create a new Accepts object for the given req. + * + * @param {object} req + * @public + */ + +function Accepts (req) { + if (!(this instanceof Accepts)) { + return new Accepts(req) + } + + this.headers = req.headers + this.negotiator = new Negotiator(req) +} + +/** + * Check if the given `type(s)` is acceptable, returning + * the best match when true, otherwise `undefined`, in which + * case you should respond with 406 "Not Acceptable". + * + * The `type` value may be a single mime type string + * such as "application/json", the extension name + * such as "json" or an array `["json", "html", "text/plain"]`. When a list + * or array is given the _best_ match, if any is returned. + * + * Examples: + * + * // Accept: text/html + * this.types('html'); + * // => "html" + * + * // Accept: text/*, application/json + * this.types('html'); + * // => "html" + * this.types('text/html'); + * // => "text/html" + * this.types('json', 'text'); + * // => "json" + * this.types('application/json'); + * // => "application/json" + * + * // Accept: text/*, application/json + * this.types('image/png'); + * this.types('png'); + * // => undefined + * + * // Accept: text/*;q=.5, application/json + * this.types(['html', 'json']); + * this.types('html', 'json'); + * // => "json" + * + * @param {String|Array} types... + * @return {String|Array|Boolean} + * @public + */ + +Accepts.prototype.type = +Accepts.prototype.types = function (types_) { + var types = types_ + + // support flattened arguments + if (types && !Array.isArray(types)) { + types = new Array(arguments.length) + for (var i = 0; i < types.length; i++) { + types[i] = arguments[i] + } + } + + // no types, return all requested types + if (!types || types.length === 0) { + return this.negotiator.mediaTypes() + } + + // no accept header, return first given type + if (!this.headers.accept) { + return types[0] + } + + var mimes = types.map(extToMime) + var accepts = this.negotiator.mediaTypes(mimes.filter(validMime)) + var first = accepts[0] + + return first + ? types[mimes.indexOf(first)] + : false +} + +/** + * Return accepted encodings or best fit based on `encodings`. + * + * Given `Accept-Encoding: gzip, deflate` + * an array sorted by quality is returned: + * + * ['gzip', 'deflate'] + * + * @param {String|Array} encodings... + * @return {String|Array} + * @public + */ + +Accepts.prototype.encoding = +Accepts.prototype.encodings = function (encodings_) { + var encodings = encodings_ + + // support flattened arguments + if (encodings && !Array.isArray(encodings)) { + encodings = new Array(arguments.length) + for (var i = 0; i < encodings.length; i++) { + encodings[i] = arguments[i] + } + } + + // no encodings, return all requested encodings + if (!encodings || encodings.length === 0) { + return this.negotiator.encodings() + } + + return this.negotiator.encodings(encodings)[0] || false +} + +/** + * Return accepted charsets or best fit based on `charsets`. + * + * Given `Accept-Charset: utf-8, iso-8859-1;q=0.2, utf-7;q=0.5` + * an array sorted by quality is returned: + * + * ['utf-8', 'utf-7', 'iso-8859-1'] + * + * @param {String|Array} charsets... + * @return {String|Array} + * @public + */ + +Accepts.prototype.charset = +Accepts.prototype.charsets = function (charsets_) { + var charsets = charsets_ + + // support flattened arguments + if (charsets && !Array.isArray(charsets)) { + charsets = new Array(arguments.length) + for (var i = 0; i < charsets.length; i++) { + charsets[i] = arguments[i] + } + } + + // no charsets, return all requested charsets + if (!charsets || charsets.length === 0) { + return this.negotiator.charsets() + } + + return this.negotiator.charsets(charsets)[0] || false +} + +/** + * Return accepted languages or best fit based on `langs`. + * + * Given `Accept-Language: en;q=0.8, es, pt` + * an array sorted by quality is returned: + * + * ['es', 'pt', 'en'] + * + * @param {String|Array} langs... + * @return {Array|String} + * @public + */ + +Accepts.prototype.lang = +Accepts.prototype.langs = +Accepts.prototype.language = +Accepts.prototype.languages = function (languages_) { + var languages = languages_ + + // support flattened arguments + if (languages && !Array.isArray(languages)) { + languages = new Array(arguments.length) + for (var i = 0; i < languages.length; i++) { + languages[i] = arguments[i] + } + } + + // no languages, return all requested languages + if (!languages || languages.length === 0) { + return this.negotiator.languages() + } + + return this.negotiator.languages(languages)[0] || false +} + +/** + * Convert extnames to mime. + * + * @param {String} type + * @return {String} + * @private + */ + +function extToMime (type) { + return type.indexOf('/') === -1 + ? mime.lookup(type) + : type +} + +/** + * Check if mime is valid. + * + * @param {String} type + * @return {String} + * @private + */ + +function validMime (type) { + return typeof type === 'string' +} diff --git a/server/node_modules/accepts/package.json b/server/node_modules/accepts/package.json new file mode 100644 index 0000000..0f2d15d --- /dev/null +++ b/server/node_modules/accepts/package.json @@ -0,0 +1,47 @@ +{ + "name": "accepts", + "description": "Higher-level content negotiation", + "version": "1.3.8", + "contributors": [ + "Douglas Christopher Wilson <doug@somethingdoug.com>", + "Jonathan Ong <me@jongleberry.com> (http://jongleberry.com)" + ], + "license": "MIT", + "repository": "jshttp/accepts", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "devDependencies": { + "deep-equal": "1.0.1", + "eslint": "7.32.0", + "eslint-config-standard": "14.1.1", + "eslint-plugin-import": "2.25.4", + "eslint-plugin-markdown": "2.2.1", + "eslint-plugin-node": "11.1.0", + "eslint-plugin-promise": "4.3.1", + "eslint-plugin-standard": "4.1.0", + "mocha": "9.2.0", + "nyc": "15.1.0" + }, + "files": [ + "LICENSE", + "HISTORY.md", + "index.js" + ], + "engines": { + "node": ">= 0.6" + }, + "scripts": { + "lint": "eslint .", + "test": "mocha --reporter spec --check-leaks --bail test/", + "test-ci": "nyc --reporter=lcov --reporter=text npm test", + "test-cov": "nyc --reporter=html --reporter=text npm test" + }, + "keywords": [ + "content", + "negotiation", + "accept", + "accepts" + ] +} diff --git a/server/node_modules/agent-base/LICENSE b/server/node_modules/agent-base/LICENSE new file mode 100644 index 0000000..008728c --- /dev/null +++ b/server/node_modules/agent-base/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/server/node_modules/agent-base/README.md b/server/node_modules/agent-base/README.md new file mode 100644 index 0000000..b8a86b9 --- /dev/null +++ b/server/node_modules/agent-base/README.md @@ -0,0 +1,69 @@ +agent-base +========== +### Turn a function into an [`http.Agent`][http.Agent] instance + +This module is a thin wrapper around the base `http.Agent` class. + +It provides an abstract class that must define a `connect()` function, +which is responsible for creating the underlying socket that the HTTP +client requests will use. + +The `connect()` function may return an arbitrary `Duplex` stream, or +another `http.Agent` instance to delegate the request to, and may be +asynchronous (by defining an `async` function). + +Instances of this agent can be used with the `http` and `https` +modules. To differentiate, the options parameter in the `connect()` +function includes a `secureEndpoint` property, which can be checked +to determine what type of socket should be returned. + +#### Some subclasses: + +Here are some more interesting uses of `agent-base`. +Send a pull request to list yours! + + * [`http-proxy-agent`][http-proxy-agent]: An HTTP(s) proxy `http.Agent` implementation for HTTP endpoints + * [`https-proxy-agent`][https-proxy-agent]: An HTTP(s) proxy `http.Agent` implementation for HTTPS endpoints + * [`pac-proxy-agent`][pac-proxy-agent]: A PAC file proxy `http.Agent` implementation for HTTP and HTTPS + * [`socks-proxy-agent`][socks-proxy-agent]: A SOCKS proxy `http.Agent` implementation for HTTP and HTTPS + +Example +------- + +Here's a minimal example that creates a new `net.Socket` or `tls.Socket` +based on the `secureEndpoint` property. This agent can be used with both +the `http` and `https` modules. + +```ts +import * as net from 'net'; +import * as tls from 'tls'; +import * as http from 'http'; +import { Agent } from 'agent-base'; + +class MyAgent extends Agent { + connect(req, opts) { + // `secureEndpoint` is true when using the "https" module + if (opts.secureEndpoint) { + return tls.connect(opts); + } else { + return net.connect(opts); + } + } +}); + +// Keep alive enabled means that `connect()` will only be +// invoked when a new connection needs to be created +const agent = new MyAgent({ keepAlive: true }); + +// Pass the `agent` option when creating the HTTP request +http.get('http://nodejs.org/api/', { agent }, (res) => { + console.log('"response" event!', res.headers); + res.pipe(process.stdout); +}); +``` + +[http-proxy-agent]: ../http-proxy-agent +[https-proxy-agent]: ../https-proxy-agent +[pac-proxy-agent]: ../pac-proxy-agent +[socks-proxy-agent]: ../socks-proxy-agent +[http.Agent]: https://nodejs.org/api/http.html#http_class_http_agent diff --git a/server/node_modules/agent-base/dist/helpers.d.ts b/server/node_modules/agent-base/dist/helpers.d.ts new file mode 100644 index 0000000..b468f23 --- /dev/null +++ b/server/node_modules/agent-base/dist/helpers.d.ts @@ -0,0 +1,15 @@ +/// <reference types="node" /> +/// <reference types="node" /> +/// <reference types="node" /> +/// <reference types="node" /> +/// <reference types="node" /> +import * as http from 'http'; +import * as https from 'https'; +import type { Readable } from 'stream'; +export type ThenableRequest = http.ClientRequest & { + then: Promise<http.IncomingMessage>['then']; +}; +export declare function toBuffer(stream: Readable): Promise<Buffer>; +export declare function json(stream: Readable): Promise<any>; +export declare function req(url: string | URL, opts?: https.RequestOptions): ThenableRequest; +//# sourceMappingURL=helpers.d.ts.map \ No newline at end of file diff --git a/server/node_modules/agent-base/dist/helpers.d.ts.map b/server/node_modules/agent-base/dist/helpers.d.ts.map new file mode 100644 index 0000000..9479c9a --- /dev/null +++ b/server/node_modules/agent-base/dist/helpers.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":";;;;;AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAEvC,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,aAAa,GAAG;IAClD,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;CAC5C,CAAC;AAEF,wBAAsB,QAAQ,CAAC,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAQhE;AAGD,wBAAsB,IAAI,CAAC,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,CAUzD;AAED,wBAAgB,GAAG,CAClB,GAAG,EAAE,MAAM,GAAG,GAAG,EACjB,IAAI,GAAE,KAAK,CAAC,cAAmB,GAC7B,eAAe,CAcjB"} \ No newline at end of file diff --git a/server/node_modules/agent-base/dist/helpers.js b/server/node_modules/agent-base/dist/helpers.js new file mode 100644 index 0000000..ef3f920 --- /dev/null +++ b/server/node_modules/agent-base/dist/helpers.js @@ -0,0 +1,66 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.req = exports.json = exports.toBuffer = void 0; +const http = __importStar(require("http")); +const https = __importStar(require("https")); +async function toBuffer(stream) { + let length = 0; + const chunks = []; + for await (const chunk of stream) { + length += chunk.length; + chunks.push(chunk); + } + return Buffer.concat(chunks, length); +} +exports.toBuffer = toBuffer; +// eslint-disable-next-line @typescript-eslint/no-explicit-any +async function json(stream) { + const buf = await toBuffer(stream); + const str = buf.toString('utf8'); + try { + return JSON.parse(str); + } + catch (_err) { + const err = _err; + err.message += ` (input: ${str})`; + throw err; + } +} +exports.json = json; +function req(url, opts = {}) { + const href = typeof url === 'string' ? url : url.href; + const req = (href.startsWith('https:') ? https : http).request(url, opts); + const promise = new Promise((resolve, reject) => { + req + .once('response', resolve) + .once('error', reject) + .end(); + }); + req.then = promise.then.bind(promise); + return req; +} +exports.req = req; +//# sourceMappingURL=helpers.js.map \ No newline at end of file diff --git a/server/node_modules/agent-base/dist/helpers.js.map b/server/node_modules/agent-base/dist/helpers.js.map new file mode 100644 index 0000000..19df537 --- /dev/null +++ b/server/node_modules/agent-base/dist/helpers.js.map @@ -0,0 +1 @@ +{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2CAA6B;AAC7B,6CAA+B;AAOxB,KAAK,UAAU,QAAQ,CAAC,MAAgB;IAC9C,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE;QACjC,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC;QACvB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;KACnB;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACtC,CAAC;AARD,4BAQC;AAED,8DAA8D;AACvD,KAAK,UAAU,IAAI,CAAC,MAAgB;IAC1C,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAC;IACnC,MAAM,GAAG,GAAG,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACjC,IAAI;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;KACvB;IAAC,OAAO,IAAa,EAAE;QACvB,MAAM,GAAG,GAAG,IAAa,CAAC;QAC1B,GAAG,CAAC,OAAO,IAAI,YAAY,GAAG,GAAG,CAAC;QAClC,MAAM,GAAG,CAAC;KACV;AACF,CAAC;AAVD,oBAUC;AAED,SAAgB,GAAG,CAClB,GAAiB,EACjB,OAA6B,EAAE;IAE/B,MAAM,IAAI,GAAG,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC;IACtD,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,CAC7D,GAAG,EACH,IAAI,CACe,CAAC;IACrB,MAAM,OAAO,GAAG,IAAI,OAAO,CAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrE,GAAG;aACD,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC;aACzB,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC;aACrB,GAAG,EAAqB,CAAC;IAC5B,CAAC,CAAC,CAAC;IACH,GAAG,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACtC,OAAO,GAAG,CAAC;AACZ,CAAC;AAjBD,kBAiBC"} \ No newline at end of file diff --git a/server/node_modules/agent-base/dist/index.d.ts b/server/node_modules/agent-base/dist/index.d.ts new file mode 100644 index 0000000..3660ea7 --- /dev/null +++ b/server/node_modules/agent-base/dist/index.d.ts @@ -0,0 +1,41 @@ +/// <reference types="node" /> +/// <reference types="node" /> +/// <reference types="node" /> +/// <reference types="node" /> +import * as net from 'net'; +import * as tls from 'tls'; +import * as http from 'http'; +import type { Duplex } from 'stream'; +export * from './helpers'; +interface HttpConnectOpts extends net.TcpNetConnectOpts { + secureEndpoint: false; + protocol?: string; +} +interface HttpsConnectOpts extends tls.ConnectionOptions { + secureEndpoint: true; + protocol?: string; + port: number; +} +export type AgentConnectOpts = HttpConnectOpts | HttpsConnectOpts; +declare const INTERNAL: unique symbol; +export declare abstract class Agent extends http.Agent { + private [INTERNAL]; + options: Partial<net.TcpNetConnectOpts & tls.ConnectionOptions>; + keepAlive: boolean; + constructor(opts?: http.AgentOptions); + abstract connect(req: http.ClientRequest, options: AgentConnectOpts): Promise<Duplex | http.Agent> | Duplex | http.Agent; + /** + * Determine whether this is an `http` or `https` request. + */ + isSecureEndpoint(options?: AgentConnectOpts): boolean; + private incrementSockets; + private decrementSockets; + getName(options?: AgentConnectOpts): string; + createSocket(req: http.ClientRequest, options: AgentConnectOpts, cb: (err: Error | null, s?: Duplex) => void): void; + createConnection(): Duplex; + get defaultPort(): number; + set defaultPort(v: number); + get protocol(): string; + set protocol(v: string); +} +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/server/node_modules/agent-base/dist/index.d.ts.map b/server/node_modules/agent-base/dist/index.d.ts.map new file mode 100644 index 0000000..c0f91ab --- /dev/null +++ b/server/node_modules/agent-base/dist/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;AAAA,OAAO,KAAK,GAAG,MAAM,KAAK,CAAC;AAC3B,OAAO,KAAK,GAAG,MAAM,KAAK,CAAC;AAC3B,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAErC,cAAc,WAAW,CAAC;AAE1B,UAAU,eAAgB,SAAQ,GAAG,CAAC,iBAAiB;IACtD,cAAc,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,gBAAiB,SAAQ,GAAG,CAAC,iBAAiB;IACvD,cAAc,EAAE,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACb;AAED,MAAM,MAAM,gBAAgB,GAAG,eAAe,GAAG,gBAAgB,CAAC;AAElE,QAAA,MAAM,QAAQ,eAAmC,CAAC;AAQlD,8BAAsB,KAAM,SAAQ,IAAI,CAAC,KAAK;IAC7C,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAgB;IAGlC,OAAO,EAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,GAAG,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACjE,SAAS,EAAG,OAAO,CAAC;gBAER,IAAI,CAAC,EAAE,IAAI,CAAC,YAAY;IAKpC,QAAQ,CAAC,OAAO,CACf,GAAG,EAAE,IAAI,CAAC,aAAa,EACvB,OAAO,EAAE,gBAAgB,GACvB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC,KAAK;IAErD;;OAEG;IACH,gBAAgB,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO;IAqCrD,OAAO,CAAC,gBAAgB;IAqBxB,OAAO,CAAC,gBAAgB;IAmBxB,OAAO,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,MAAM;IAU3C,YAAY,CACX,GAAG,EAAE,IAAI,CAAC,aAAa,EACvB,OAAO,EAAE,gBAAgB,EACzB,EAAE,EAAE,CAAC,GAAG,EAAE,KAAK,GAAG,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI;IAgC5C,gBAAgB,IAAI,MAAM;IAW1B,IAAI,WAAW,IAAI,MAAM,CAKxB;IAED,IAAI,WAAW,CAAC,CAAC,EAAE,MAAM,EAIxB;IAED,IAAI,QAAQ,IAAI,MAAM,CAKrB;IAED,IAAI,QAAQ,CAAC,CAAC,EAAE,MAAM,EAIrB;CACD"} \ No newline at end of file diff --git a/server/node_modules/agent-base/dist/index.js b/server/node_modules/agent-base/dist/index.js new file mode 100644 index 0000000..57ac852 --- /dev/null +++ b/server/node_modules/agent-base/dist/index.js @@ -0,0 +1,178 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Agent = void 0; +const net = __importStar(require("net")); +const http = __importStar(require("http")); +const https_1 = require("https"); +__exportStar(require("./helpers"), exports); +const INTERNAL = Symbol('AgentBaseInternalState'); +class Agent extends http.Agent { + constructor(opts) { + super(opts); + this[INTERNAL] = {}; + } + /** + * Determine whether this is an `http` or `https` request. + */ + isSecureEndpoint(options) { + if (options) { + // First check the `secureEndpoint` property explicitly, since this + // means that a parent `Agent` is "passing through" to this instance. + // eslint-disable-next-line @typescript-eslint/no-explicit-any + if (typeof options.secureEndpoint === 'boolean') { + return options.secureEndpoint; + } + // If no explicit `secure` endpoint, check if `protocol` property is + // set. This will usually be the case since using a full string URL + // or `URL` instance should be the most common usage. + if (typeof options.protocol === 'string') { + return options.protocol === 'https:'; + } + } + // Finally, if no `protocol` property was set, then fall back to + // checking the stack trace of the current call stack, and try to + // detect the "https" module. + const { stack } = new Error(); + if (typeof stack !== 'string') + return false; + return stack + .split('\n') + .some((l) => l.indexOf('(https.js:') !== -1 || + l.indexOf('node:https:') !== -1); + } + // In order to support async signatures in `connect()` and Node's native + // connection pooling in `http.Agent`, the array of sockets for each origin + // has to be updated synchronously. This is so the length of the array is + // accurate when `addRequest()` is next called. We achieve this by creating a + // fake socket and adding it to `sockets[origin]` and incrementing + // `totalSocketCount`. + incrementSockets(name) { + // If `maxSockets` and `maxTotalSockets` are both Infinity then there is no + // need to create a fake socket because Node.js native connection pooling + // will never be invoked. + if (this.maxSockets === Infinity && this.maxTotalSockets === Infinity) { + return null; + } + // All instances of `sockets` are expected TypeScript errors. The + // alternative is to add it as a private property of this class but that + // will break TypeScript subclassing. + if (!this.sockets[name]) { + // @ts-expect-error `sockets` is readonly in `@types/node` + this.sockets[name] = []; + } + const fakeSocket = new net.Socket({ writable: false }); + this.sockets[name].push(fakeSocket); + // @ts-expect-error `totalSocketCount` isn't defined in `@types/node` + this.totalSocketCount++; + return fakeSocket; + } + decrementSockets(name, socket) { + if (!this.sockets[name] || socket === null) { + return; + } + const sockets = this.sockets[name]; + const index = sockets.indexOf(socket); + if (index !== -1) { + sockets.splice(index, 1); + // @ts-expect-error `totalSocketCount` isn't defined in `@types/node` + this.totalSocketCount--; + if (sockets.length === 0) { + // @ts-expect-error `sockets` is readonly in `@types/node` + delete this.sockets[name]; + } + } + } + // In order to properly update the socket pool, we need to call `getName()` on + // the core `https.Agent` if it is a secureEndpoint. + getName(options) { + const secureEndpoint = this.isSecureEndpoint(options); + if (secureEndpoint) { + // @ts-expect-error `getName()` isn't defined in `@types/node` + return https_1.Agent.prototype.getName.call(this, options); + } + // @ts-expect-error `getName()` isn't defined in `@types/node` + return super.getName(options); + } + createSocket(req, options, cb) { + const connectOpts = { + ...options, + secureEndpoint: this.isSecureEndpoint(options), + }; + const name = this.getName(connectOpts); + const fakeSocket = this.incrementSockets(name); + Promise.resolve() + .then(() => this.connect(req, connectOpts)) + .then((socket) => { + this.decrementSockets(name, fakeSocket); + if (socket instanceof http.Agent) { + try { + // @ts-expect-error `addRequest()` isn't defined in `@types/node` + return socket.addRequest(req, connectOpts); + } + catch (err) { + return cb(err); + } + } + this[INTERNAL].currentSocket = socket; + // @ts-expect-error `createSocket()` isn't defined in `@types/node` + super.createSocket(req, options, cb); + }, (err) => { + this.decrementSockets(name, fakeSocket); + cb(err); + }); + } + createConnection() { + const socket = this[INTERNAL].currentSocket; + this[INTERNAL].currentSocket = undefined; + if (!socket) { + throw new Error('No socket was returned in the `connect()` function'); + } + return socket; + } + get defaultPort() { + return (this[INTERNAL].defaultPort ?? + (this.protocol === 'https:' ? 443 : 80)); + } + set defaultPort(v) { + if (this[INTERNAL]) { + this[INTERNAL].defaultPort = v; + } + } + get protocol() { + return (this[INTERNAL].protocol ?? + (this.isSecureEndpoint() ? 'https:' : 'http:')); + } + set protocol(v) { + if (this[INTERNAL]) { + this[INTERNAL].protocol = v; + } + } +} +exports.Agent = Agent; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/server/node_modules/agent-base/dist/index.js.map b/server/node_modules/agent-base/dist/index.js.map new file mode 100644 index 0000000..5a0d2ad --- /dev/null +++ b/server/node_modules/agent-base/dist/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/server/node_modules/agent-base/package.json b/server/node_modules/agent-base/package.json new file mode 100644 index 0000000..1b4964a --- /dev/null +++ b/server/node_modules/agent-base/package.json @@ -0,0 +1,46 @@ +{ + "name": "agent-base", + "version": "7.1.4", + "description": "Turn a function into an `http.Agent` instance", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "files": [ + "dist" + ], + "repository": { + "type": "git", + "url": "https://github.com/TooTallNate/proxy-agents.git", + "directory": "packages/agent-base" + }, + "keywords": [ + "http", + "agent", + "base", + "barebones", + "https" + ], + "author": "Nathan Rajlich <nathan@tootallnate.net> (http://n8.io/)", + "license": "MIT", + "devDependencies": { + "@types/debug": "^4.1.7", + "@types/jest": "^29.5.1", + "@types/node": "^14.18.45", + "@types/semver": "^7.3.13", + "@types/ws": "^6.0.4", + "async-listen": "^3.0.0", + "jest": "^29.5.0", + "ts-jest": "^29.1.0", + "typescript": "^5.0.4", + "ws": "^5.2.4", + "tsconfig": "0.0.0" + }, + "engines": { + "node": ">= 14" + }, + "scripts": { + "build": "tsc", + "test": "jest --env node --verbose --bail", + "lint": "eslint . --ext .ts", + "pack": "node ../../scripts/pack.mjs" + } +} \ No newline at end of file diff --git a/server/node_modules/ansi-regex/index.d.ts b/server/node_modules/ansi-regex/index.d.ts new file mode 100644 index 0000000..7d562e9 --- /dev/null +++ b/server/node_modules/ansi-regex/index.d.ts @@ -0,0 +1,33 @@ +export type Options = { + /** + Match only the first ANSI escape. + + @default false + */ + readonly onlyFirst: boolean; +}; + +/** +Regular expression for matching ANSI escape codes. + +@example +``` +import ansiRegex from 'ansi-regex'; + +ansiRegex().test('\u001B[4mcake\u001B[0m'); +//=> true + +ansiRegex().test('cake'); +//=> false + +'\u001B[4mcake\u001B[0m'.match(ansiRegex()); +//=> ['\u001B[4m', '\u001B[0m'] + +'\u001B[4mcake\u001B[0m'.match(ansiRegex({onlyFirst: true})); +//=> ['\u001B[4m'] + +'\u001B]8;;https://github.com\u0007click\u001B]8;;\u0007'.match(ansiRegex()); +//=> ['\u001B]8;;https://github.com\u0007', '\u001B]8;;\u0007'] +``` +*/ +export default function ansiRegex(options?: Options): RegExp; diff --git a/server/node_modules/ansi-regex/index.js b/server/node_modules/ansi-regex/index.js new file mode 100644 index 0000000..2cc5ca2 --- /dev/null +++ b/server/node_modules/ansi-regex/index.js @@ -0,0 +1,14 @@ +export default function ansiRegex({onlyFirst = false} = {}) { + // Valid string terminator sequences are BEL, ESC\, and 0x9c + const ST = '(?:\\u0007|\\u001B\\u005C|\\u009C)'; + + // OSC sequences only: ESC ] ... ST (non-greedy until the first ST) + const osc = `(?:\\u001B\\][\\s\\S]*?${ST})`; + + // CSI and related: ESC/C1, optional intermediates, optional params (supports ; and :) then final byte + const csi = '[\\u001B\\u009B][[\\]()#;?]*(?:\\d{1,4}(?:[;:]\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]'; + + const pattern = `${osc}|${csi}`; + + return new RegExp(pattern, onlyFirst ? undefined : 'g'); +} diff --git a/server/node_modules/ansi-regex/license b/server/node_modules/ansi-regex/license new file mode 100644 index 0000000..fa7ceba --- /dev/null +++ b/server/node_modules/ansi-regex/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/server/node_modules/ansi-regex/package.json b/server/node_modules/ansi-regex/package.json new file mode 100644 index 0000000..2efe9eb --- /dev/null +++ b/server/node_modules/ansi-regex/package.json @@ -0,0 +1,61 @@ +{ + "name": "ansi-regex", + "version": "6.2.2", + "description": "Regular expression for matching ANSI escape codes", + "license": "MIT", + "repository": "chalk/ansi-regex", + "funding": "https://github.com/chalk/ansi-regex?sponsor=1", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "https://sindresorhus.com" + }, + "type": "module", + "exports": "./index.js", + "types": "./index.d.ts", + "sideEffects": false, + "engines": { + "node": ">=12" + }, + "scripts": { + "test": "xo && ava && tsd", + "view-supported": "node fixtures/view-codes.js" + }, + "files": [ + "index.js", + "index.d.ts" + ], + "keywords": [ + "ansi", + "styles", + "color", + "colour", + "colors", + "terminal", + "console", + "cli", + "string", + "tty", + "escape", + "formatting", + "rgb", + "256", + "shell", + "xterm", + "command-line", + "text", + "regex", + "regexp", + "re", + "match", + "test", + "find", + "pattern" + ], + "devDependencies": { + "ansi-escapes": "^5.0.0", + "ava": "^3.15.0", + "tsd": "^0.21.0", + "xo": "^0.54.2" + } +} diff --git a/server/node_modules/ansi-regex/readme.md b/server/node_modules/ansi-regex/readme.md new file mode 100644 index 0000000..4d3c415 --- /dev/null +++ b/server/node_modules/ansi-regex/readme.md @@ -0,0 +1,66 @@ +# ansi-regex + +> Regular expression for matching [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code) + +## Install + +```sh +npm install ansi-regex +``` + +## Usage + +```js +import ansiRegex from 'ansi-regex'; + +ansiRegex().test('\u001B[4mcake\u001B[0m'); +//=> true + +ansiRegex().test('cake'); +//=> false + +'\u001B[4mcake\u001B[0m'.match(ansiRegex()); +//=> ['\u001B[4m', '\u001B[0m'] + +'\u001B[4mcake\u001B[0m'.match(ansiRegex({onlyFirst: true})); +//=> ['\u001B[4m'] + +'\u001B]8;;https://github.com\u0007click\u001B]8;;\u0007'.match(ansiRegex()); +//=> ['\u001B]8;;https://github.com\u0007', '\u001B]8;;\u0007'] +``` + +## API + +### ansiRegex(options?) + +Returns a regex for matching ANSI escape codes. + +#### options + +Type: `object` + +##### onlyFirst + +Type: `boolean`\ +Default: `false` *(Matches any ANSI escape codes in a string)* + +Match only the first ANSI escape. + +## Important + +If you run the regex against untrusted user input in a server context, you should [give it a timeout](https://github.com/sindresorhus/super-regex). + +**I do not consider [ReDoS](https://blog.yossarian.net/2022/12/28/ReDoS-vulnerabilities-and-misaligned-incentives) a valid vulnerability for this package.** + +## FAQ + +### Why do you test for codes not in the ECMA 48 standard? + +Some of the codes we run as a test are codes that we acquired finding various lists of non-standard or manufacturer specific codes. We test for both standard and non-standard codes, as most of them follow the same or similar format and can be safely matched in strings without the risk of removing actual string content. There are a few non-standard control codes that do not follow the traditional format (i.e. they end in numbers) thus forcing us to exclude them from the test because we cannot reliably match them. + +On the historical side, those ECMA standards were established in the early 90's whereas the VT100, for example, was designed in the mid/late 70's. At that point in time, control codes were still pretty ungoverned and engineers used them for a multitude of things, namely to activate hardware ports that may have been proprietary. Somewhere else you see a similar 'anarchy' of codes is in the x86 architecture for processors; there are a ton of "interrupts" that can mean different things on certain brands of processors, most of which have been phased out. + +## Maintainers + +- [Sindre Sorhus](https://github.com/sindresorhus) +- [Josh Junon](https://github.com/qix-) diff --git a/server/node_modules/ansi-styles/index.d.ts b/server/node_modules/ansi-styles/index.d.ts new file mode 100644 index 0000000..ee8bc27 --- /dev/null +++ b/server/node_modules/ansi-styles/index.d.ts @@ -0,0 +1,236 @@ +export type CSPair = { // eslint-disable-line @typescript-eslint/naming-convention + /** + The ANSI terminal control sequence for starting this style. + */ + readonly open: string; + + /** + The ANSI terminal control sequence for ending this style. + */ + readonly close: string; +}; + +export type ColorBase = { + /** + The ANSI terminal control sequence for ending this color. + */ + readonly close: string; + + ansi(code: number): string; + + ansi256(code: number): string; + + ansi16m(red: number, green: number, blue: number): string; +}; + +export type Modifier = { + /** + Resets the current color chain. + */ + readonly reset: CSPair; + + /** + Make text bold. + */ + readonly bold: CSPair; + + /** + Emitting only a small amount of light. + */ + readonly dim: CSPair; + + /** + Make text italic. (Not widely supported) + */ + readonly italic: CSPair; + + /** + Make text underline. (Not widely supported) + */ + readonly underline: CSPair; + + /** + Make text overline. + + Supported on VTE-based terminals, the GNOME terminal, mintty, and Git Bash. + */ + readonly overline: CSPair; + + /** + Inverse background and foreground colors. + */ + readonly inverse: CSPair; + + /** + Prints the text, but makes it invisible. + */ + readonly hidden: CSPair; + + /** + Puts a horizontal line through the center of the text. (Not widely supported) + */ + readonly strikethrough: CSPair; +}; + +export type ForegroundColor = { + readonly black: CSPair; + readonly red: CSPair; + readonly green: CSPair; + readonly yellow: CSPair; + readonly blue: CSPair; + readonly cyan: CSPair; + readonly magenta: CSPair; + readonly white: CSPair; + + /** + Alias for `blackBright`. + */ + readonly gray: CSPair; + + /** + Alias for `blackBright`. + */ + readonly grey: CSPair; + + readonly blackBright: CSPair; + readonly redBright: CSPair; + readonly greenBright: CSPair; + readonly yellowBright: CSPair; + readonly blueBright: CSPair; + readonly cyanBright: CSPair; + readonly magentaBright: CSPair; + readonly whiteBright: CSPair; +}; + +export type BackgroundColor = { + readonly bgBlack: CSPair; + readonly bgRed: CSPair; + readonly bgGreen: CSPair; + readonly bgYellow: CSPair; + readonly bgBlue: CSPair; + readonly bgCyan: CSPair; + readonly bgMagenta: CSPair; + readonly bgWhite: CSPair; + + /** + Alias for `bgBlackBright`. + */ + readonly bgGray: CSPair; + + /** + Alias for `bgBlackBright`. + */ + readonly bgGrey: CSPair; + + readonly bgBlackBright: CSPair; + readonly bgRedBright: CSPair; + readonly bgGreenBright: CSPair; + readonly bgYellowBright: CSPair; + readonly bgBlueBright: CSPair; + readonly bgCyanBright: CSPair; + readonly bgMagentaBright: CSPair; + readonly bgWhiteBright: CSPair; +}; + +export type ConvertColor = { + /** + Convert from the RGB color space to the ANSI 256 color space. + + @param red - (`0...255`) + @param green - (`0...255`) + @param blue - (`0...255`) + */ + rgbToAnsi256(red: number, green: number, blue: number): number; + + /** + Convert from the RGB HEX color space to the RGB color space. + + @param hex - A hexadecimal string containing RGB data. + */ + hexToRgb(hex: string): [red: number, green: number, blue: number]; + + /** + Convert from the RGB HEX color space to the ANSI 256 color space. + + @param hex - A hexadecimal string containing RGB data. + */ + hexToAnsi256(hex: string): number; + + /** + Convert from the ANSI 256 color space to the ANSI 16 color space. + + @param code - A number representing the ANSI 256 color. + */ + ansi256ToAnsi(code: number): number; + + /** + Convert from the RGB color space to the ANSI 16 color space. + + @param red - (`0...255`) + @param green - (`0...255`) + @param blue - (`0...255`) + */ + rgbToAnsi(red: number, green: number, blue: number): number; + + /** + Convert from the RGB HEX color space to the ANSI 16 color space. + + @param hex - A hexadecimal string containing RGB data. + */ + hexToAnsi(hex: string): number; +}; + +/** +Basic modifier names. +*/ +export type ModifierName = keyof Modifier; + +/** +Basic foreground color names. + +[More colors here.](https://github.com/chalk/chalk/blob/main/readme.md#256-and-truecolor-color-support) +*/ +export type ForegroundColorName = keyof ForegroundColor; + +/** +Basic background color names. + +[More colors here.](https://github.com/chalk/chalk/blob/main/readme.md#256-and-truecolor-color-support) +*/ +export type BackgroundColorName = keyof BackgroundColor; + +/** +Basic color names. The combination of foreground and background color names. + +[More colors here.](https://github.com/chalk/chalk/blob/main/readme.md#256-and-truecolor-color-support) +*/ +export type ColorName = ForegroundColorName | BackgroundColorName; + +/** +Basic modifier names. +*/ +export const modifierNames: readonly ModifierName[]; + +/** +Basic foreground color names. +*/ +export const foregroundColorNames: readonly ForegroundColorName[]; + +/** +Basic background color names. +*/ +export const backgroundColorNames: readonly BackgroundColorName[]; + +/* +Basic color names. The combination of foreground and background color names. +*/ +export const colorNames: readonly ColorName[]; + +declare const ansiStyles: { + readonly modifier: Modifier; + readonly color: ColorBase & ForegroundColor; + readonly bgColor: ColorBase & BackgroundColor; + readonly codes: ReadonlyMap<number, number>; +} & ForegroundColor & BackgroundColor & Modifier & ConvertColor; + +export default ansiStyles; diff --git a/server/node_modules/ansi-styles/index.js b/server/node_modules/ansi-styles/index.js new file mode 100644 index 0000000..eaa7bed --- /dev/null +++ b/server/node_modules/ansi-styles/index.js @@ -0,0 +1,223 @@ +const ANSI_BACKGROUND_OFFSET = 10; + +const wrapAnsi16 = (offset = 0) => code => `\u001B[${code + offset}m`; + +const wrapAnsi256 = (offset = 0) => code => `\u001B[${38 + offset};5;${code}m`; + +const wrapAnsi16m = (offset = 0) => (red, green, blue) => `\u001B[${38 + offset};2;${red};${green};${blue}m`; + +const styles = { + modifier: { + reset: [0, 0], + // 21 isn't widely supported and 22 does the same thing + bold: [1, 22], + dim: [2, 22], + italic: [3, 23], + underline: [4, 24], + overline: [53, 55], + inverse: [7, 27], + hidden: [8, 28], + strikethrough: [9, 29], + }, + color: { + black: [30, 39], + red: [31, 39], + green: [32, 39], + yellow: [33, 39], + blue: [34, 39], + magenta: [35, 39], + cyan: [36, 39], + white: [37, 39], + + // Bright color + blackBright: [90, 39], + gray: [90, 39], // Alias of `blackBright` + grey: [90, 39], // Alias of `blackBright` + redBright: [91, 39], + greenBright: [92, 39], + yellowBright: [93, 39], + blueBright: [94, 39], + magentaBright: [95, 39], + cyanBright: [96, 39], + whiteBright: [97, 39], + }, + bgColor: { + bgBlack: [40, 49], + bgRed: [41, 49], + bgGreen: [42, 49], + bgYellow: [43, 49], + bgBlue: [44, 49], + bgMagenta: [45, 49], + bgCyan: [46, 49], + bgWhite: [47, 49], + + // Bright color + bgBlackBright: [100, 49], + bgGray: [100, 49], // Alias of `bgBlackBright` + bgGrey: [100, 49], // Alias of `bgBlackBright` + bgRedBright: [101, 49], + bgGreenBright: [102, 49], + bgYellowBright: [103, 49], + bgBlueBright: [104, 49], + bgMagentaBright: [105, 49], + bgCyanBright: [106, 49], + bgWhiteBright: [107, 49], + }, +}; + +export const modifierNames = Object.keys(styles.modifier); +export const foregroundColorNames = Object.keys(styles.color); +export const backgroundColorNames = Object.keys(styles.bgColor); +export const colorNames = [...foregroundColorNames, ...backgroundColorNames]; + +function assembleStyles() { + const codes = new Map(); + + for (const [groupName, group] of Object.entries(styles)) { + for (const [styleName, style] of Object.entries(group)) { + styles[styleName] = { + open: `\u001B[${style[0]}m`, + close: `\u001B[${style[1]}m`, + }; + + group[styleName] = styles[styleName]; + + codes.set(style[0], style[1]); + } + + Object.defineProperty(styles, groupName, { + value: group, + enumerable: false, + }); + } + + Object.defineProperty(styles, 'codes', { + value: codes, + enumerable: false, + }); + + styles.color.close = '\u001B[39m'; + styles.bgColor.close = '\u001B[49m'; + + styles.color.ansi = wrapAnsi16(); + styles.color.ansi256 = wrapAnsi256(); + styles.color.ansi16m = wrapAnsi16m(); + styles.bgColor.ansi = wrapAnsi16(ANSI_BACKGROUND_OFFSET); + styles.bgColor.ansi256 = wrapAnsi256(ANSI_BACKGROUND_OFFSET); + styles.bgColor.ansi16m = wrapAnsi16m(ANSI_BACKGROUND_OFFSET); + + // From https://github.com/Qix-/color-convert/blob/3f0e0d4e92e235796ccb17f6e85c72094a651f49/conversions.js + Object.defineProperties(styles, { + rgbToAnsi256: { + value(red, green, blue) { + // We use the extended greyscale palette here, with the exception of + // black and white. normal palette only has 4 greyscale shades. + if (red === green && green === blue) { + if (red < 8) { + return 16; + } + + if (red > 248) { + return 231; + } + + return Math.round(((red - 8) / 247) * 24) + 232; + } + + return 16 + + (36 * Math.round(red / 255 * 5)) + + (6 * Math.round(green / 255 * 5)) + + Math.round(blue / 255 * 5); + }, + enumerable: false, + }, + hexToRgb: { + value(hex) { + const matches = /[a-f\d]{6}|[a-f\d]{3}/i.exec(hex.toString(16)); + if (!matches) { + return [0, 0, 0]; + } + + let [colorString] = matches; + + if (colorString.length === 3) { + colorString = [...colorString].map(character => character + character).join(''); + } + + const integer = Number.parseInt(colorString, 16); + + return [ + /* eslint-disable no-bitwise */ + (integer >> 16) & 0xFF, + (integer >> 8) & 0xFF, + integer & 0xFF, + /* eslint-enable no-bitwise */ + ]; + }, + enumerable: false, + }, + hexToAnsi256: { + value: hex => styles.rgbToAnsi256(...styles.hexToRgb(hex)), + enumerable: false, + }, + ansi256ToAnsi: { + value(code) { + if (code < 8) { + return 30 + code; + } + + if (code < 16) { + return 90 + (code - 8); + } + + let red; + let green; + let blue; + + if (code >= 232) { + red = (((code - 232) * 10) + 8) / 255; + green = red; + blue = red; + } else { + code -= 16; + + const remainder = code % 36; + + red = Math.floor(code / 36) / 5; + green = Math.floor(remainder / 6) / 5; + blue = (remainder % 6) / 5; + } + + const value = Math.max(red, green, blue) * 2; + + if (value === 0) { + return 30; + } + + // eslint-disable-next-line no-bitwise + let result = 30 + ((Math.round(blue) << 2) | (Math.round(green) << 1) | Math.round(red)); + + if (value === 2) { + result += 60; + } + + return result; + }, + enumerable: false, + }, + rgbToAnsi: { + value: (red, green, blue) => styles.ansi256ToAnsi(styles.rgbToAnsi256(red, green, blue)), + enumerable: false, + }, + hexToAnsi: { + value: hex => styles.ansi256ToAnsi(styles.hexToAnsi256(hex)), + enumerable: false, + }, + }); + + return styles; +} + +const ansiStyles = assembleStyles(); + +export default ansiStyles; diff --git a/server/node_modules/ansi-styles/license b/server/node_modules/ansi-styles/license new file mode 100644 index 0000000..fa7ceba --- /dev/null +++ b/server/node_modules/ansi-styles/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/server/node_modules/ansi-styles/package.json b/server/node_modules/ansi-styles/package.json new file mode 100644 index 0000000..16b508f --- /dev/null +++ b/server/node_modules/ansi-styles/package.json @@ -0,0 +1,54 @@ +{ + "name": "ansi-styles", + "version": "6.2.3", + "description": "ANSI escape codes for styling strings in the terminal", + "license": "MIT", + "repository": "chalk/ansi-styles", + "funding": "https://github.com/chalk/ansi-styles?sponsor=1", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "https://sindresorhus.com" + }, + "type": "module", + "exports": "./index.js", + "engines": { + "node": ">=12" + }, + "scripts": { + "test": "xo && ava && tsd", + "screenshot": "svg-term --command='node screenshot' --out=screenshot.svg --padding=3 --width=55 --height=3 --at=1000 --no-cursor" + }, + "files": [ + "index.js", + "index.d.ts" + ], + "keywords": [ + "ansi", + "styles", + "color", + "colour", + "colors", + "terminal", + "console", + "cli", + "string", + "tty", + "escape", + "formatting", + "rgb", + "256", + "shell", + "xterm", + "log", + "logging", + "command-line", + "text" + ], + "devDependencies": { + "ava": "^6.1.3", + "svg-term-cli": "^2.1.1", + "tsd": "^0.31.1", + "xo": "^0.58.0" + } +} diff --git a/server/node_modules/ansi-styles/readme.md b/server/node_modules/ansi-styles/readme.md new file mode 100644 index 0000000..6d04183 --- /dev/null +++ b/server/node_modules/ansi-styles/readme.md @@ -0,0 +1,173 @@ +# ansi-styles + +> [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors_and_Styles) for styling strings in the terminal + +You probably want the higher-level [chalk](https://github.com/chalk/chalk) module for styling your strings. + +![](screenshot.png) + +## Install + +```sh +npm install ansi-styles +``` + +## Usage + +```js +import styles from 'ansi-styles'; + +console.log(`${styles.green.open}Hello world!${styles.green.close}`); + + +// Color conversion between 256/truecolor +// NOTE: When converting from truecolor to 256 colors, the original color +// may be degraded to fit the new color palette. This means terminals +// that do not support 16 million colors will best-match the +// original color. +console.log(`${styles.color.ansi(styles.rgbToAnsi(199, 20, 250))}Hello World${styles.color.close}`) +console.log(`${styles.color.ansi256(styles.rgbToAnsi256(199, 20, 250))}Hello World${styles.color.close}`) +console.log(`${styles.color.ansi16m(...styles.hexToRgb('#abcdef'))}Hello World${styles.color.close}`) +``` + +## API + +### `open` and `close` + +Each style has an `open` and `close` property. + +### `modifierNames`, `foregroundColorNames`, `backgroundColorNames`, and `colorNames` + +All supported style strings are exposed as an array of strings for convenience. `colorNames` is the combination of `foregroundColorNames` and `backgroundColorNames`. + +This can be useful if you need to validate input: + +```js +import {modifierNames, foregroundColorNames} from 'ansi-styles'; + +console.log(modifierNames.includes('bold')); +//=> true + +console.log(foregroundColorNames.includes('pink')); +//=> false +``` + +## Styles + +### Modifiers + +- `reset` +- `bold` +- `dim` +- `italic` *(Not widely supported)* +- `underline` +- `overline` *Supported on VTE-based terminals, the GNOME terminal, mintty, and Git Bash.* +- `inverse` +- `hidden` +- `strikethrough` *(Not widely supported)* + +### Colors + +- `black` +- `red` +- `green` +- `yellow` +- `blue` +- `magenta` +- `cyan` +- `white` +- `blackBright` (alias: `gray`, `grey`) +- `redBright` +- `greenBright` +- `yellowBright` +- `blueBright` +- `magentaBright` +- `cyanBright` +- `whiteBright` + +### Background colors + +- `bgBlack` +- `bgRed` +- `bgGreen` +- `bgYellow` +- `bgBlue` +- `bgMagenta` +- `bgCyan` +- `bgWhite` +- `bgBlackBright` (alias: `bgGray`, `bgGrey`) +- `bgRedBright` +- `bgGreenBright` +- `bgYellowBright` +- `bgBlueBright` +- `bgMagentaBright` +- `bgCyanBright` +- `bgWhiteBright` + +## Advanced usage + +By default, you get a map of styles, but the styles are also available as groups. They are non-enumerable so they don't show up unless you access them explicitly. This makes it easier to expose only a subset in a higher-level module. + +- `styles.modifier` +- `styles.color` +- `styles.bgColor` + +###### Example + +```js +import styles from 'ansi-styles'; + +console.log(styles.color.green.open); +``` + +Raw escape codes (i.e. without the CSI escape prefix `\u001B[` and render mode postfix `m`) are available under `styles.codes`, which returns a `Map` with the open codes as keys and close codes as values. + +###### Example + +```js +import styles from 'ansi-styles'; + +console.log(styles.codes.get(36)); +//=> 39 +``` + +## 16 / 256 / 16 million (TrueColor) support + +`ansi-styles` allows converting between various color formats and ANSI escapes, with support for 16, 256 and [16 million colors](https://gist.github.com/XVilka/8346728). + +The following color spaces are supported: + +- `rgb` +- `hex` +- `ansi256` +- `ansi` + +To use these, call the associated conversion function with the intended output, for example: + +```js +import styles from 'ansi-styles'; + +styles.color.ansi(styles.rgbToAnsi(100, 200, 15)); // RGB to 16 color ansi foreground code +styles.bgColor.ansi(styles.hexToAnsi('#C0FFEE')); // HEX to 16 color ansi foreground code + +styles.color.ansi256(styles.rgbToAnsi256(100, 200, 15)); // RGB to 256 color ansi foreground code +styles.bgColor.ansi256(styles.hexToAnsi256('#C0FFEE')); // HEX to 256 color ansi foreground code + +styles.color.ansi16m(100, 200, 15); // RGB to 16 million color foreground code +styles.bgColor.ansi16m(...styles.hexToRgb('#C0FFEE')); // Hex (RGB) to 16 million color foreground code +``` + +## Related + +- [ansi-escapes](https://github.com/sindresorhus/ansi-escapes) - ANSI escape codes for manipulating the terminal + +## Maintainers + +- [Sindre Sorhus](https://github.com/sindresorhus) +- [Josh Junon](https://github.com/qix-) + +## For enterprise + +Available as part of the Tidelift Subscription. + +The maintainers of `ansi-styles` and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-ansi-styles?utm_source=npm-ansi-styles&utm_medium=referral&utm_campaign=enterprise&utm_term=repo) diff --git a/server/node_modules/array-flatten/LICENSE b/server/node_modules/array-flatten/LICENSE new file mode 100644 index 0000000..983fbe8 --- /dev/null +++ b/server/node_modules/array-flatten/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/server/node_modules/array-flatten/README.md b/server/node_modules/array-flatten/README.md new file mode 100644 index 0000000..91fa5b6 --- /dev/null +++ b/server/node_modules/array-flatten/README.md @@ -0,0 +1,43 @@ +# Array Flatten + +[![NPM version][npm-image]][npm-url] +[![NPM downloads][downloads-image]][downloads-url] +[![Build status][travis-image]][travis-url] +[![Test coverage][coveralls-image]][coveralls-url] + +> Flatten an array of nested arrays into a single flat array. Accepts an optional depth. + +## Installation + +``` +npm install array-flatten --save +``` + +## Usage + +```javascript +var flatten = require('array-flatten') + +flatten([1, [2, [3, [4, [5], 6], 7], 8], 9]) +//=> [1, 2, 3, 4, 5, 6, 7, 8, 9] + +flatten([1, [2, [3, [4, [5], 6], 7], 8], 9], 2) +//=> [1, 2, 3, [4, [5], 6], 7, 8, 9] + +(function () { + flatten(arguments) //=> [1, 2, 3] +})(1, [2, 3]) +``` + +## License + +MIT + +[npm-image]: https://img.shields.io/npm/v/array-flatten.svg?style=flat +[npm-url]: https://npmjs.org/package/array-flatten +[downloads-image]: https://img.shields.io/npm/dm/array-flatten.svg?style=flat +[downloads-url]: https://npmjs.org/package/array-flatten +[travis-image]: https://img.shields.io/travis/blakeembrey/array-flatten.svg?style=flat +[travis-url]: https://travis-ci.org/blakeembrey/array-flatten +[coveralls-image]: https://img.shields.io/coveralls/blakeembrey/array-flatten.svg?style=flat +[coveralls-url]: https://coveralls.io/r/blakeembrey/array-flatten?branch=master diff --git a/server/node_modules/array-flatten/array-flatten.js b/server/node_modules/array-flatten/array-flatten.js new file mode 100644 index 0000000..089117b --- /dev/null +++ b/server/node_modules/array-flatten/array-flatten.js @@ -0,0 +1,64 @@ +'use strict' + +/** + * Expose `arrayFlatten`. + */ +module.exports = arrayFlatten + +/** + * Recursive flatten function with depth. + * + * @param {Array} array + * @param {Array} result + * @param {Number} depth + * @return {Array} + */ +function flattenWithDepth (array, result, depth) { + for (var i = 0; i < array.length; i++) { + var value = array[i] + + if (depth > 0 && Array.isArray(value)) { + flattenWithDepth(value, result, depth - 1) + } else { + result.push(value) + } + } + + return result +} + +/** + * Recursive flatten function. Omitting depth is slightly faster. + * + * @param {Array} array + * @param {Array} result + * @return {Array} + */ +function flattenForever (array, result) { + for (var i = 0; i < array.length; i++) { + var value = array[i] + + if (Array.isArray(value)) { + flattenForever(value, result) + } else { + result.push(value) + } + } + + return result +} + +/** + * Flatten an array, with the ability to define a depth. + * + * @param {Array} array + * @param {Number} depth + * @return {Array} + */ +function arrayFlatten (array, depth) { + if (depth == null) { + return flattenForever(array, []) + } + + return flattenWithDepth(array, [], depth) +} diff --git a/server/node_modules/array-flatten/package.json b/server/node_modules/array-flatten/package.json new file mode 100644 index 0000000..1a24e2a --- /dev/null +++ b/server/node_modules/array-flatten/package.json @@ -0,0 +1,39 @@ +{ + "name": "array-flatten", + "version": "1.1.1", + "description": "Flatten an array of nested arrays into a single flat array", + "main": "array-flatten.js", + "files": [ + "array-flatten.js", + "LICENSE" + ], + "scripts": { + "test": "istanbul cover _mocha -- -R spec" + }, + "repository": { + "type": "git", + "url": "git://github.com/blakeembrey/array-flatten.git" + }, + "keywords": [ + "array", + "flatten", + "arguments", + "depth" + ], + "author": { + "name": "Blake Embrey", + "email": "hello@blakeembrey.com", + "url": "http://blakeembrey.me" + }, + "license": "MIT", + "bugs": { + "url": "https://github.com/blakeembrey/array-flatten/issues" + }, + "homepage": "https://github.com/blakeembrey/array-flatten", + "devDependencies": { + "istanbul": "^0.3.13", + "mocha": "^2.2.4", + "pre-commit": "^1.0.7", + "standard": "^3.7.3" + } +} diff --git a/server/node_modules/balanced-match/.github/FUNDING.yml b/server/node_modules/balanced-match/.github/FUNDING.yml new file mode 100644 index 0000000..cea8b16 --- /dev/null +++ b/server/node_modules/balanced-match/.github/FUNDING.yml @@ -0,0 +1,2 @@ +tidelift: "npm/balanced-match" +patreon: juliangruber diff --git a/server/node_modules/balanced-match/LICENSE.md b/server/node_modules/balanced-match/LICENSE.md new file mode 100644 index 0000000..2cdc8e4 --- /dev/null +++ b/server/node_modules/balanced-match/LICENSE.md @@ -0,0 +1,21 @@ +(MIT) + +Copyright (c) 2013 Julian Gruber <julian@juliangruber.com> + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/server/node_modules/balanced-match/README.md b/server/node_modules/balanced-match/README.md new file mode 100644 index 0000000..d2a48b6 --- /dev/null +++ b/server/node_modules/balanced-match/README.md @@ -0,0 +1,97 @@ +# balanced-match + +Match balanced string pairs, like `{` and `}` or `<b>` and `</b>`. Supports regular expressions as well! + +[![build status](https://secure.travis-ci.org/juliangruber/balanced-match.svg)](http://travis-ci.org/juliangruber/balanced-match) +[![downloads](https://img.shields.io/npm/dm/balanced-match.svg)](https://www.npmjs.org/package/balanced-match) + +[![testling badge](https://ci.testling.com/juliangruber/balanced-match.png)](https://ci.testling.com/juliangruber/balanced-match) + +## Example + +Get the first matching pair of braces: + +```js +var balanced = require('balanced-match'); + +console.log(balanced('{', '}', 'pre{in{nested}}post')); +console.log(balanced('{', '}', 'pre{first}between{second}post')); +console.log(balanced(/\s+\{\s+/, /\s+\}\s+/, 'pre { in{nest} } post')); +``` + +The matches are: + +```bash +$ node example.js +{ start: 3, end: 14, pre: 'pre', body: 'in{nested}', post: 'post' } +{ start: 3, + end: 9, + pre: 'pre', + body: 'first', + post: 'between{second}post' } +{ start: 3, end: 17, pre: 'pre', body: 'in{nest}', post: 'post' } +``` + +## API + +### var m = balanced(a, b, str) + +For the first non-nested matching pair of `a` and `b` in `str`, return an +object with those keys: + +* **start** the index of the first match of `a` +* **end** the index of the matching `b` +* **pre** the preamble, `a` and `b` not included +* **body** the match, `a` and `b` not included +* **post** the postscript, `a` and `b` not included + +If there's no match, `undefined` will be returned. + +If the `str` contains more `a` than `b` / there are unmatched pairs, the first match that was closed will be used. For example, `{{a}` will match `['{', 'a', '']` and `{a}}` will match `['', 'a', '}']`. + +### var r = balanced.range(a, b, str) + +For the first non-nested matching pair of `a` and `b` in `str`, return an +array with indexes: `[ <a index>, <b index> ]`. + +If there's no match, `undefined` will be returned. + +If the `str` contains more `a` than `b` / there are unmatched pairs, the first match that was closed will be used. For example, `{{a}` will match `[ 1, 3 ]` and `{a}}` will match `[0, 2]`. + +## Installation + +With [npm](https://npmjs.org) do: + +```bash +npm install balanced-match +``` + +## Security contact information + +To report a security vulnerability, please use the +[Tidelift security contact](https://tidelift.com/security). +Tidelift will coordinate the fix and disclosure. + +## License + +(MIT) + +Copyright (c) 2013 Julian Gruber <julian@juliangruber.com> + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/server/node_modules/balanced-match/index.js b/server/node_modules/balanced-match/index.js new file mode 100644 index 0000000..c67a646 --- /dev/null +++ b/server/node_modules/balanced-match/index.js @@ -0,0 +1,62 @@ +'use strict'; +module.exports = balanced; +function balanced(a, b, str) { + if (a instanceof RegExp) a = maybeMatch(a, str); + if (b instanceof RegExp) b = maybeMatch(b, str); + + var r = range(a, b, str); + + return r && { + start: r[0], + end: r[1], + pre: str.slice(0, r[0]), + body: str.slice(r[0] + a.length, r[1]), + post: str.slice(r[1] + b.length) + }; +} + +function maybeMatch(reg, str) { + var m = str.match(reg); + return m ? m[0] : null; +} + +balanced.range = range; +function range(a, b, str) { + var begs, beg, left, right, result; + var ai = str.indexOf(a); + var bi = str.indexOf(b, ai + 1); + var i = ai; + + if (ai >= 0 && bi > 0) { + if(a===b) { + return [ai, bi]; + } + begs = []; + left = str.length; + + while (i >= 0 && !result) { + if (i == ai) { + begs.push(i); + ai = str.indexOf(a, i + 1); + } else if (begs.length == 1) { + result = [ begs.pop(), bi ]; + } else { + beg = begs.pop(); + if (beg < left) { + left = beg; + right = bi; + } + + bi = str.indexOf(b, i + 1); + } + + i = ai < bi && ai >= 0 ? ai : bi; + } + + if (begs.length) { + result = [ left, right ]; + } + } + + return result; +} diff --git a/server/node_modules/balanced-match/package.json b/server/node_modules/balanced-match/package.json new file mode 100644 index 0000000..ce6073e --- /dev/null +++ b/server/node_modules/balanced-match/package.json @@ -0,0 +1,48 @@ +{ + "name": "balanced-match", + "description": "Match balanced character pairs, like \"{\" and \"}\"", + "version": "1.0.2", + "repository": { + "type": "git", + "url": "git://github.com/juliangruber/balanced-match.git" + }, + "homepage": "https://github.com/juliangruber/balanced-match", + "main": "index.js", + "scripts": { + "test": "tape test/test.js", + "bench": "matcha test/bench.js" + }, + "devDependencies": { + "matcha": "^0.7.0", + "tape": "^4.6.0" + }, + "keywords": [ + "match", + "regexp", + "test", + "balanced", + "parse" + ], + "author": { + "name": "Julian Gruber", + "email": "mail@juliangruber.com", + "url": "http://juliangruber.com" + }, + "license": "MIT", + "testling": { + "files": "test/*.js", + "browsers": [ + "ie/8..latest", + "firefox/20..latest", + "firefox/nightly", + "chrome/25..latest", + "chrome/canary", + "opera/12..latest", + "opera/next", + "safari/5.1..latest", + "ipad/6.0..latest", + "iphone/6.0..latest", + "android-browser/4.2..latest" + ] + } +} diff --git a/server/node_modules/base64-js/LICENSE b/server/node_modules/base64-js/LICENSE new file mode 100644 index 0000000..6d52b8a --- /dev/null +++ b/server/node_modules/base64-js/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Jameson Little + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/server/node_modules/base64-js/README.md b/server/node_modules/base64-js/README.md new file mode 100644 index 0000000..b42a48f --- /dev/null +++ b/server/node_modules/base64-js/README.md @@ -0,0 +1,34 @@ +base64-js +========= + +`base64-js` does basic base64 encoding/decoding in pure JS. + +[![build status](https://secure.travis-ci.org/beatgammit/base64-js.png)](http://travis-ci.org/beatgammit/base64-js) + +Many browsers already have base64 encoding/decoding functionality, but it is for text data, not all-purpose binary data. + +Sometimes encoding/decoding binary data in the browser is useful, and that is what this module does. + +## install + +With [npm](https://npmjs.org) do: + +`npm install base64-js` and `var base64js = require('base64-js')` + +For use in web browsers do: + +`<script src="base64js.min.js"></script>` + +[Get supported base64-js with the Tidelift Subscription](https://tidelift.com/subscription/pkg/npm-base64-js?utm_source=npm-base64-js&utm_medium=referral&utm_campaign=readme) + +## methods + +`base64js` has three exposed functions, `byteLength`, `toByteArray` and `fromByteArray`, which both take a single argument. + +* `byteLength` - Takes a base64 string and returns length of byte array +* `toByteArray` - Takes a base64 string and returns a byte array +* `fromByteArray` - Takes a byte array and returns a base64 string + +## license + +MIT diff --git a/server/node_modules/base64-js/base64js.min.js b/server/node_modules/base64-js/base64js.min.js new file mode 100644 index 0000000..908ac83 --- /dev/null +++ b/server/node_modules/base64-js/base64js.min.js @@ -0,0 +1 @@ +(function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;b="undefined"==typeof window?"undefined"==typeof global?"undefined"==typeof self?this:self:global:window,b.base64js=a()}})(function(){return function(){function b(d,e,g){function a(j,i){if(!e[j]){if(!d[j]){var f="function"==typeof require&&require;if(!i&&f)return f(j,!0);if(h)return h(j,!0);var c=new Error("Cannot find module '"+j+"'");throw c.code="MODULE_NOT_FOUND",c}var k=e[j]={exports:{}};d[j][0].call(k.exports,function(b){var c=d[j][1][b];return a(c||b)},k,k.exports,b,d,e,g)}return e[j].exports}for(var h="function"==typeof require&&require,c=0;c<g.length;c++)a(g[c]);return a}return b}()({"/":[function(a,b,c){'use strict';function d(a){var b=a.length;if(0<b%4)throw new Error("Invalid string. Length must be a multiple of 4");var c=a.indexOf("=");-1===c&&(c=b);var d=c===b?0:4-c%4;return[c,d]}function e(a,b,c){return 3*(b+c)/4-c}function f(a){var b,c,f=d(a),g=f[0],h=f[1],j=new m(e(a,g,h)),k=0,n=0<h?g-4:g;for(c=0;c<n;c+=4)b=l[a.charCodeAt(c)]<<18|l[a.charCodeAt(c+1)]<<12|l[a.charCodeAt(c+2)]<<6|l[a.charCodeAt(c+3)],j[k++]=255&b>>16,j[k++]=255&b>>8,j[k++]=255&b;return 2===h&&(b=l[a.charCodeAt(c)]<<2|l[a.charCodeAt(c+1)]>>4,j[k++]=255&b),1===h&&(b=l[a.charCodeAt(c)]<<10|l[a.charCodeAt(c+1)]<<4|l[a.charCodeAt(c+2)]>>2,j[k++]=255&b>>8,j[k++]=255&b),j}function g(a){return k[63&a>>18]+k[63&a>>12]+k[63&a>>6]+k[63&a]}function h(a,b,c){for(var d,e=[],f=b;f<c;f+=3)d=(16711680&a[f]<<16)+(65280&a[f+1]<<8)+(255&a[f+2]),e.push(g(d));return e.join("")}function j(a){for(var b,c=a.length,d=c%3,e=[],f=16383,g=0,j=c-d;g<j;g+=f)e.push(h(a,g,g+f>j?j:g+f));return 1===d?(b=a[c-1],e.push(k[b>>2]+k[63&b<<4]+"==")):2===d&&(b=(a[c-2]<<8)+a[c-1],e.push(k[b>>10]+k[63&b>>4]+k[63&b<<2]+"=")),e.join("")}c.byteLength=function(a){var b=d(a),c=b[0],e=b[1];return 3*(c+e)/4-e},c.toByteArray=f,c.fromByteArray=j;for(var k=[],l=[],m="undefined"==typeof Uint8Array?Array:Uint8Array,n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",o=0,p=n.length;o<p;++o)k[o]=n[o],l[n.charCodeAt(o)]=o;l[45]=62,l[95]=63},{}]},{},[])("/")}); \ No newline at end of file diff --git a/server/node_modules/base64-js/index.d.ts b/server/node_modules/base64-js/index.d.ts new file mode 100644 index 0000000..7d9fa1d --- /dev/null +++ b/server/node_modules/base64-js/index.d.ts @@ -0,0 +1,3 @@ +export function byteLength(b64: string): number; +export function toByteArray(b64: string): Uint8Array; +export function fromByteArray(uint8: Uint8Array): string; diff --git a/server/node_modules/base64-js/index.js b/server/node_modules/base64-js/index.js new file mode 100644 index 0000000..0599f3e --- /dev/null +++ b/server/node_modules/base64-js/index.js @@ -0,0 +1,150 @@ +'use strict' + +exports.byteLength = byteLength +exports.toByteArray = toByteArray +exports.fromByteArray = fromByteArray + +var lookup = [] +var revLookup = [] +var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array + +var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' +for (var i = 0, len = code.length; i < len; ++i) { + lookup[i] = code[i] + revLookup[code.charCodeAt(i)] = i +} + +// Support decoding URL-safe base64 strings, as Node.js does. +// See: https://en.wikipedia.org/wiki/Base64#URL_applications +revLookup['-'.charCodeAt(0)] = 62 +revLookup['_'.charCodeAt(0)] = 63 + +function getLens (b64) { + var len = b64.length + + if (len % 4 > 0) { + throw new Error('Invalid string. Length must be a multiple of 4') + } + + // Trim off extra bytes after placeholder bytes are found + // See: https://github.com/beatgammit/base64-js/issues/42 + var validLen = b64.indexOf('=') + if (validLen === -1) validLen = len + + var placeHoldersLen = validLen === len + ? 0 + : 4 - (validLen % 4) + + return [validLen, placeHoldersLen] +} + +// base64 is 4/3 + up to two characters of the original data +function byteLength (b64) { + var lens = getLens(b64) + var validLen = lens[0] + var placeHoldersLen = lens[1] + return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen +} + +function _byteLength (b64, validLen, placeHoldersLen) { + return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen +} + +function toByteArray (b64) { + var tmp + var lens = getLens(b64) + var validLen = lens[0] + var placeHoldersLen = lens[1] + + var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen)) + + var curByte = 0 + + // if there are placeholders, only get up to the last complete 4 chars + var len = placeHoldersLen > 0 + ? validLen - 4 + : validLen + + var i + for (i = 0; i < len; i += 4) { + tmp = + (revLookup[b64.charCodeAt(i)] << 18) | + (revLookup[b64.charCodeAt(i + 1)] << 12) | + (revLookup[b64.charCodeAt(i + 2)] << 6) | + revLookup[b64.charCodeAt(i + 3)] + arr[curByte++] = (tmp >> 16) & 0xFF + arr[curByte++] = (tmp >> 8) & 0xFF + arr[curByte++] = tmp & 0xFF + } + + if (placeHoldersLen === 2) { + tmp = + (revLookup[b64.charCodeAt(i)] << 2) | + (revLookup[b64.charCodeAt(i + 1)] >> 4) + arr[curByte++] = tmp & 0xFF + } + + if (placeHoldersLen === 1) { + tmp = + (revLookup[b64.charCodeAt(i)] << 10) | + (revLookup[b64.charCodeAt(i + 1)] << 4) | + (revLookup[b64.charCodeAt(i + 2)] >> 2) + arr[curByte++] = (tmp >> 8) & 0xFF + arr[curByte++] = tmp & 0xFF + } + + return arr +} + +function tripletToBase64 (num) { + return lookup[num >> 18 & 0x3F] + + lookup[num >> 12 & 0x3F] + + lookup[num >> 6 & 0x3F] + + lookup[num & 0x3F] +} + +function encodeChunk (uint8, start, end) { + var tmp + var output = [] + for (var i = start; i < end; i += 3) { + tmp = + ((uint8[i] << 16) & 0xFF0000) + + ((uint8[i + 1] << 8) & 0xFF00) + + (uint8[i + 2] & 0xFF) + output.push(tripletToBase64(tmp)) + } + return output.join('') +} + +function fromByteArray (uint8) { + var tmp + var len = uint8.length + var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes + var parts = [] + var maxChunkLength = 16383 // must be multiple of 3 + + // go through the array every three bytes, we'll deal with trailing stuff later + for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { + parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength))) + } + + // pad the end with zeros, but make sure to not forget the extra bytes + if (extraBytes === 1) { + tmp = uint8[len - 1] + parts.push( + lookup[tmp >> 2] + + lookup[(tmp << 4) & 0x3F] + + '==' + ) + } else if (extraBytes === 2) { + tmp = (uint8[len - 2] << 8) + uint8[len - 1] + parts.push( + lookup[tmp >> 10] + + lookup[(tmp >> 4) & 0x3F] + + lookup[(tmp << 2) & 0x3F] + + '=' + ) + } + + return parts.join('') +} diff --git a/server/node_modules/base64-js/package.json b/server/node_modules/base64-js/package.json new file mode 100644 index 0000000..c3972e3 --- /dev/null +++ b/server/node_modules/base64-js/package.json @@ -0,0 +1,47 @@ +{ + "name": "base64-js", + "description": "Base64 encoding/decoding in pure JS", + "version": "1.5.1", + "author": "T. Jameson Little <t.jameson.little@gmail.com>", + "typings": "index.d.ts", + "bugs": { + "url": "https://github.com/beatgammit/base64-js/issues" + }, + "devDependencies": { + "babel-minify": "^0.5.1", + "benchmark": "^2.1.4", + "browserify": "^16.3.0", + "standard": "*", + "tape": "4.x" + }, + "homepage": "https://github.com/beatgammit/base64-js", + "keywords": [ + "base64" + ], + "license": "MIT", + "main": "index.js", + "repository": { + "type": "git", + "url": "git://github.com/beatgammit/base64-js.git" + }, + "scripts": { + "build": "browserify -s base64js -r ./ | minify > base64js.min.js", + "lint": "standard", + "test": "npm run lint && npm run unit", + "unit": "tape test/*.js" + }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] +} diff --git a/server/node_modules/bignumber.js/CHANGELOG.md b/server/node_modules/bignumber.js/CHANGELOG.md new file mode 100644 index 0000000..5759964 --- /dev/null +++ b/server/node_modules/bignumber.js/CHANGELOG.md @@ -0,0 +1,381 @@ +#### 9.3.1 + +* 11/07/25 +* [BUGFIX] #388 `toPrecision` fix. + +#### 9.3.0 + +* 19/04/25 +* Refactor type declarations: +* Rename *bignumber.d.ts* to *types.d.ts*. +* Rename *bignumber.d.cts* to *bignumber.d.ts*. +* Add `export as namespace` to *bignumber.d.ts*. +* Remove subpath exports from *package.json*. +* Refactor named export from *bignumber.d.mts*. +* #383 Remove `?` from static `BigNumber` and `default` properties. +* Add blank lines after titles in *CHANGELOG.md*. + +#### 9.2.1 + +* 08/04/25 +* #371 #382 Add `BigNumber` as named export. + +#### 9.2.0 + +* 03/04/25 +* #355 Support `BigInt` argument. +* #371 Provide separate type definitions for CommonJS and ES modules. +* #374 Correct `comparedTo` return type. + +#### 9.1.2 + +* 28/08/23 +* #354 Amend `round` to avoid bug in v8 Maglev compiler. +* [BUGFIX] #344 `minimum(0, -0)` should be `-0`. + +#### 9.1.1 + +* 04/12/22 +* #338 [BUGFIX] `exponentiatedBy`: ensure `0**-n === Infinity` for very large `n`. + +#### 9.1.0 + +* 08/08/22 +* #329 Remove `import` example. +* #277 Resolve lint warnings and add number `toString` note. +* Correct `decimalPlaces()` return type in *bignumber.d.ts*. +* Add ES module global `crypto` example. +* #322 Add `exports` field to *package.json*. +* #251 (#308) Amend *bignumber.d.ts* to allow instantiating a BigNumber without `new`. + +#### 9.0.2 + +* 12/12/21 +* #250 [BUGFIX] Allow use of user-defined alphabet for base 10. +* #295 Remove *bignumber.min.js* and amend *README.md*. +* Update *.travis.yml* and *LICENCE.md*. + +#### 9.0.1 + +* 28/09/20 +* [BUGFIX] #276 Correct `sqrt` initial estimate. +* Update *.travis.yml*, *LICENCE.md* and *README.md*. + +#### 9.0.0 + +* 27/05/2019 +* For compatibility with legacy browsers, remove `Symbol` references. + +#### 8.1.1 + +* 24/02/2019 +* [BUGFIX] #222 Restore missing `var` to `export BigNumber`. +* Allow any key in BigNumber.Instance in *bignumber.d.ts*. + +#### 8.1.0 + +* 23/02/2019 +* [NEW FEATURE] #220 Create a BigNumber using `{s, e, c}`. +* [NEW FEATURE] `isBigNumber`: if `BigNumber.DEBUG` is `true`, also check that the BigNumber instance is well-formed. +* Remove `instanceof` checks; just use `_isBigNumber` to identify a BigNumber instance. +* Add `_isBigNumber` to prototype in *bignumber.mjs*. +* Add tests for BigNumber creation from object. +* Update *API.html*. + +#### 8.0.2 + +* 13/01/2019 +* #209 `toPrecision` without argument should follow `toString`. +* Improve *Use* section of *README*. +* Optimise `toString(10)`. +* Add verson number to API doc. + +#### 8.0.1 + +* 01/11/2018 +* Rest parameter must be array type in *bignumber.d.ts*. + +#### 8.0.0 + +* 01/11/2018 +* [NEW FEATURE] Add `BigNumber.sum` method. +* [NEW FEATURE]`toFormat`: add `prefix` and `suffix` options. +* [NEW FEATURE] #178 Pass custom formatting to `toFormat`. +* [BREAKING CHANGE] #184 `toFraction`: return array of BigNumbers not strings. +* [NEW FEATURE] #185 Enable overwrite of `valueOf` to prevent accidental addition to string. +* #183 Add Node.js `crypto` requirement to documentation. +* [BREAKING CHANGE] #198 Disallow signs and whitespace in custom alphabet. +* [NEW FEATURE] #188 Implement `util.inspect.custom` for Node.js REPL. +* #170 Make `isBigNumber` a type guard in *bignumber.d.ts*. +* [BREAKING CHANGE] `BigNumber.min` and `BigNumber.max`: don't accept an array. +* Update *.travis.yml*. +* Remove *bower.json*. + +#### 7.2.1 + +* 24/05/2018 +* Add `browser` field to *package.json*. + +#### 7.2.0 + +* 22/05/2018 +* #166 Correct *.mjs* file. Remove extension from `main` field in *package.json*. + +#### 7.1.0 + +* 18/05/2018 +* Add `module` field to *package.json* for *bignumber.mjs*. + +#### 7.0.2 + +* 17/05/2018 +* #165 Bugfix: upper-case letters for bases 11-36 in a custom alphabet. +* Add note to *README* regarding creating BigNumbers from Number values. + +#### 7.0.1 + +* 26/04/2018 +* #158 Fix global object variable name typo. + +#### 7.0.0 + +* 26/04/2018 +* #143 Remove global BigNumber from typings. +* #144 Enable compatibility with `Object.freeze(Object.prototype)`. +* #148 #123 #11 Only throw on a number primitive with more than 15 significant digits if `BigNumber.DEBUG` is `true`. +* Only throw on an invalid BigNumber value if `BigNumber.DEBUG` is `true`. Return BigNumber `NaN` instead. +* #154 `exponentiatedBy`: allow BigNumber exponent. +* #156 Prevent Content Security Policy *unsafe-eval* issue. +* `toFraction`: allow `Infinity` maximum denominator. +* Comment-out some excess tests to reduce test time. +* Amend indentation and other spacing. + +#### 6.0.0 + +* 26/01/2018 +* #137 Implement `APLHABET` configuration option. +* Remove `ERRORS` configuration option. +* Remove `toDigits` method; extend `precision` method accordingly. +* Remove s`round` method; extend `decimalPlaces` method accordingly. +* Remove methods: `ceil`, `floor`, and `truncated`. +* Remove method aliases: `add`, `cmp`, `isInt`, `isNeg`, `trunc`, `mul`, `neg` and `sub`. +* Rename methods: `shift` to `shiftedBy`, `another` to `clone`, `toPower` to `exponentiatedBy`, and `equals` to `isEqualTo`. +* Rename methods: add `is` prefix to `greaterThan`, `greaterThanOrEqualTo`, `lessThan` and `lessThanOrEqualTo`. +* Add methods: `multipliedBy`, `isBigNumber`, `isPositive`, `integerValue`, `maximum` and `minimum`. +* Refactor test suite. +* Add *CHANGELOG.md*. +* Rewrite *bignumber.d.ts*. +* Redo API image. + +#### 5.0.0 + +* 27/11/2017 +* #81 Don't throw on constructor call without `new`. + +#### 4.1.0 + +* 26/09/2017 +* Remove node 0.6 from *.travis.yml*. +* Add *bignumber.mjs*. + +#### 4.0.4 + +* 03/09/2017 +* Add missing aliases to *bignumber.d.ts*. + +#### 4.0.3 + +* 30/08/2017 +* Add types: *bignumber.d.ts*. + +#### 4.0.2 + +* 03/05/2017 +* #120 Workaround Safari/Webkit bug. + +#### 4.0.1 + +* 05/04/2017 +* #121 BigNumber.default to BigNumber['default']. + +#### 4.0.0 + +* 09/01/2017 +* Replace BigNumber.isBigNumber method with isBigNumber prototype property. + +#### 3.1.2 + +* 08/01/2017 +* Minor documentation edit. + +#### 3.1.1 + +* 08/01/2017 +* Uncomment `isBigNumber` tests. +* Ignore dot files. + +#### 3.1.0 + +* 08/01/2017 +* Add `isBigNumber` method. + +#### 3.0.2 + +* 08/01/2017 +* Bugfix: Possible incorrect value of `ERRORS` after a `BigNumber.another` call (due to `parseNumeric` declaration in outer scope). + +#### 3.0.1 + +* 23/11/2016 +* Apply fix for old ipads with `%` issue, see #57 and #102. +* Correct error message. + +#### 3.0.0 + +* 09/11/2016 +* Remove `require('crypto')` - leave it to the user. +* Add `BigNumber.set` as `BigNumber.config` alias. +* Default `POW_PRECISION` to `0`. + +#### 2.4.0 + +* 14/07/2016 +* #97 Add exports to support ES6 imports. + +#### 2.3.0 + +* 07/03/2016 +* #86 Add modulus parameter to `toPower`. + +#### 2.2.0 + +* 03/03/2016 +* #91 Permit larger JS integers. + +#### 2.1.4 + +* 15/12/2015 +* Correct UMD. + +#### 2.1.3 + +* 13/12/2015 +* Refactor re global object and crypto availability when bundling. + +#### 2.1.2 + +* 10/12/2015 +* Bugfix: `window.crypto` not assigned to `crypto`. + +#### 2.1.1 + +* 09/12/2015 +* Prevent code bundler from adding `crypto` shim. + +#### 2.1.0 + +* 26/10/2015 +* For `valueOf` and `toJSON`, include the minus sign with negative zero. + +#### 2.0.8 + +* 2/10/2015 +* Internal round function bugfix. + +#### 2.0.6 + +* 31/03/2015 +* Add bower.json. Tweak division after in-depth review. + +#### 2.0.5 + +* 25/03/2015 +* Amend README. Remove bitcoin address. + +#### 2.0.4 + +* 25/03/2015 +* Critical bugfix #58: division. + +#### 2.0.3 + +* 18/02/2015 +* Amend README. Add source map. + +#### 2.0.2 + +* 18/02/2015 +* Correct links. + +#### 2.0.1 + +* 18/02/2015 +* Add `max`, `min`, `precision`, `random`, `shiftedBy`, `toDigits` and `truncated` methods. +* Add the short-forms: `add`, `mul`, `sd`, `sub` and `trunc`. +* Add an `another` method to enable multiple independent constructors to be created. +* Add support for the base 2, 8 and 16 prefixes `0b`, `0o` and `0x`. +* Enable a rounding mode to be specified as a second parameter to `toExponential`, `toFixed`, `toFormat` and `toPrecision`. +* Add a `CRYPTO` configuration property so cryptographically-secure pseudo-random number generation can be specified. +* Add a `MODULO_MODE` configuration property to enable the rounding mode used by the `modulo` operation to be specified. +* Add a `POW_PRECISION` configuration property to enable the number of significant digits calculated by the power operation to be limited. +* Improve code quality. +* Improve documentation. + +#### 2.0.0 + +* 29/12/2014 +* Add `dividedToIntegerBy`, `isInteger` and `toFormat` methods. +* Remove the following short-forms: `isF`, `isZ`, `toE`, `toF`, `toFr`, `toN`, `toP`, `toS`. +* Store a BigNumber's coefficient in base 1e14, rather than base 10. +* Add fast path for integers to BigNumber constructor. +* Incorporate the library into the online documentation. + +#### 1.5.0 + +* 13/11/2014 +* Add `toJSON` and `decimalPlaces` methods. + +#### 1.4.1 + +* 08/06/2014 +* Amend README. + +#### 1.4.0 + +* 08/05/2014 +* Add `toNumber`. + +#### 1.3.0 + +* 08/11/2013 +* Ensure correct rounding of `sqrt` in all, rather than almost all, cases. +* Maximum radix to 64. + +#### 1.2.1 + +* 17/10/2013 +* Sign of zero when x < 0 and x + (-x) = 0. + +#### 1.2.0 + +* 19/9/2013 +* Throw Error objects for stack. + +#### 1.1.1 + +* 22/8/2013 +* Show original value in constructor error message. + +#### 1.1.0 + +* 1/8/2013 +* Allow numbers with trailing radix point. + +#### 1.0.1 + +* Bugfix: error messages with incorrect method name + +#### 1.0.0 + +* 8/11/2012 +* Initial release diff --git a/server/node_modules/bignumber.js/LICENCE.md b/server/node_modules/bignumber.js/LICENCE.md new file mode 100644 index 0000000..f09b710 --- /dev/null +++ b/server/node_modules/bignumber.js/LICENCE.md @@ -0,0 +1,26 @@ +The MIT License (MIT) +===================== + +Copyright © `<2025>` `Michael Mclaughlin` + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the “Software”), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + diff --git a/server/node_modules/bignumber.js/README.md b/server/node_modules/bignumber.js/README.md new file mode 100644 index 0000000..e34aaf2 --- /dev/null +++ b/server/node_modules/bignumber.js/README.md @@ -0,0 +1,289 @@ +![bignumber.js](https://raw.githubusercontent.com/MikeMcl/bignumber.js/gh-pages/bignumberjs.png) + +A JavaScript library for arbitrary-precision decimal and non-decimal arithmetic. + +[![npm version](https://img.shields.io/npm/v/bignumber.js.svg)](https://www.npmjs.com/package/bignumber.js) +[![npm downloads](https://img.shields.io/npm/dw/bignumber.js)](https://www.npmjs.com/package/bignumber.js) +[![CI](https://github.com/MikeMcl/bignumber.js/actions/workflows/ci.yml/badge.svg)](https://github.com/MikeMcl/bignumber.js/actions/workflows/ci.yml) + +<br /> + +## Features + +- Integers and decimals +- Simple API but full-featured +- Faster, smaller, and perhaps easier to use than JavaScript versions of Java's BigDecimal +- 8 KB minified and gzipped +- Replicates the `toExponential`, `toFixed`, `toPrecision` and `toString` methods of JavaScript's Number type +- Includes a `toFraction` and a correctly-rounded `squareRoot` method +- Supports cryptographically-secure pseudo-random number generation +- No dependencies +- Wide platform compatibility: uses JavaScript 1.5 (ECMAScript 3) features only +- Comprehensive [documentation](http://mikemcl.github.io/bignumber.js/) and test set + +![API](https://raw.githubusercontent.com/MikeMcl/bignumber.js/gh-pages/API.png) + +If a smaller and simpler library is required see [big.js](https://github.com/MikeMcl/big.js/). +It's less than half the size but only works with decimal numbers and only has half the methods. +It also has fewer configuration options than this library, and does not allow `NaN` or `Infinity`. + +See also [decimal.js](https://github.com/MikeMcl/decimal.js/), which among other things adds support for non-integer powers, and performs all operations to a specified number of significant digits. + +## Load + +The library is the single JavaScript file *bignumber.js* or ES module *bignumber.mjs*. + +### Browser + +```html +<script src='path/to/bignumber.js'></script> +``` + +> ES module + +```html +<script type="module"> +import BigNumber from './path/to/bignumber.mjs'; +``` + +> Get a minified version from a CDN: + +```html +<script src='https://cdn.jsdelivr.net/npm/bignumber.js@9.3.1/bignumber.min.js'></script> +``` + +### [Node.js](http://nodejs.org) + +```bash +npm install bignumber.js +``` + +```javascript +const BigNumber = require('bignumber.js'); +``` + +> ES module + +```javascript +import BigNumber from "bignumber.js"; +``` + +### [Deno](https://deno.land/) + +```javascript +// @deno-types="https://raw.githubusercontent.com/mikemcl/bignumber.js/v9.3.1/bignumber.d.mts" +import BigNumber from 'https://raw.githubusercontent.com/mikemcl/bignumber.js/v9.3.1/bignumber.mjs'; + +// @deno-types="https://unpkg.com/bignumber.js@latest/bignumber.d.mts" +import { BigNumber } from 'https://unpkg.com/bignumber.js@latest/bignumber.mjs'; +``` + +## Use + +The library exports a single constructor function, [`BigNumber`](http://mikemcl.github.io/bignumber.js/#bignumber), which accepts a value of type Number, String or BigNumber, + +```javascript +let x = new BigNumber(123.4567); +let y = BigNumber('123456.7e-3'); +let z = new BigNumber(x); +x.isEqualTo(y) && y.isEqualTo(z) && x.isEqualTo(z); // true +``` + +To get the string value of a BigNumber use [`toString()`](http://mikemcl.github.io/bignumber.js/#toS) or [`toFixed()`](http://mikemcl.github.io/bignumber.js/#toFix). Using `toFixed()` prevents exponential notation being returned, no matter how large or small the value. + +```javascript +let x = new BigNumber('1111222233334444555566'); +x.toString(); // "1.111222233334444555566e+21" +x.toFixed(); // "1111222233334444555566" +``` + +If the limited precision of Number values is not well understood, it is recommended to create BigNumbers from String values rather than Number values to avoid a potential loss of precision. + +*In all further examples below, `let`, semicolons and `toString` calls are not shown. If a commented-out value is in quotes it means `toString` has been called on the preceding expression.* + +```javascript +// Precision loss from using numeric literals with more than 15 significant digits. +new BigNumber(1.0000000000000001) // '1' +new BigNumber(88259496234518.57) // '88259496234518.56' +new BigNumber(99999999999999999999) // '100000000000000000000' + +// Precision loss from using numeric literals outside the range of Number values. +new BigNumber(2e+308) // 'Infinity' +new BigNumber(1e-324) // '0' + +// Precision loss from the unexpected result of arithmetic with Number values. +new BigNumber(0.7 + 0.1) // '0.7999999999999999' +``` + +When creating a BigNumber from a Number, note that a BigNumber is created from a Number's decimal `toString()` value not from its underlying binary value. If the latter is required, then pass the Number's `toString(2)` value and specify base 2. + +```javascript +new BigNumber(Number.MAX_VALUE.toString(2), 2) +``` + +BigNumbers can be created from values in bases from 2 to 36. See [`ALPHABET`](http://mikemcl.github.io/bignumber.js/#alphabet) to extend this range. + +```javascript +a = new BigNumber(1011, 2) // "11" +b = new BigNumber('zz.9', 36) // "1295.25" +c = a.plus(b) // "1306.25" +``` + +*Performance is better if base 10 is NOT specified for decimal values. Only specify base 10 when you want to limit the number of decimal places of the input value to the current [`DECIMAL_PLACES`](http://mikemcl.github.io/bignumber.js/#decimal-places) setting.* + +A BigNumber is immutable in the sense that it is not changed by its methods. + +```javascript +0.3 - 0.1 // 0.19999999999999998 +x = new BigNumber(0.3) +x.minus(0.1) // "0.2" +x // "0.3" +``` + +The methods that return a BigNumber can be chained. + +```javascript +x.dividedBy(y).plus(z).times(9) +x.times('1.23456780123456789e+9').plus(9876.5432321).dividedBy('4444562598.111772').integerValue() +``` + +Some of the longer method names have a shorter alias. + +```javascript +x.squareRoot().dividedBy(y).exponentiatedBy(3).isEqualTo(x.sqrt().div(y).pow(3)) // true +x.modulo(y).multipliedBy(z).eq(x.mod(y).times(z)) // true +``` + +As with JavaScript's Number type, there are [`toExponential`](http://mikemcl.github.io/bignumber.js/#toE), [`toFixed`](http://mikemcl.github.io/bignumber.js/#toFix) and [`toPrecision`](http://mikemcl.github.io/bignumber.js/#toP) methods. + +```javascript +x = new BigNumber(255.5) +x.toExponential(5) // "2.55500e+2" +x.toFixed(5) // "255.50000" +x.toPrecision(5) // "255.50" +x.toNumber() // 255.5 +``` + + A base can be specified for [`toString`](http://mikemcl.github.io/bignumber.js/#toS). + +*Performance is better if base 10 is NOT specified, i.e. use `toString()` not `toString(10)`. Only specify base 10 when you want to limit the number of decimal places of the string to the current [`DECIMAL_PLACES`](http://mikemcl.github.io/bignumber.js/#decimal-places) setting.* + + ```javascript + x.toString(16) // "ff.8" + ``` + +There is a [`toFormat`](http://mikemcl.github.io/bignumber.js/#toFor) method which may be useful for internationalisation. + +```javascript +y = new BigNumber('1234567.898765') +y.toFormat(2) // "1,234,567.90" +``` + +The maximum number of decimal places of the result of an operation involving division (i.e. a division, square root, base conversion or negative power operation) is set using the `set` or `config` method of the `BigNumber` constructor. + +The other arithmetic operations always give the exact result. + +```javascript +BigNumber.set({ DECIMAL_PLACES: 10, ROUNDING_MODE: 4 }) + +x = new BigNumber(2) +y = new BigNumber(3) +z = x.dividedBy(y) // "0.6666666667" +z.squareRoot() // "0.8164965809" +z.exponentiatedBy(-3) // "3.3749999995" +z.toString(2) // "0.1010101011" +z.multipliedBy(z) // "0.44444444448888888889" +z.multipliedBy(z).decimalPlaces(10) // "0.4444444445" +``` + +There is a [`toFraction`](http://mikemcl.github.io/bignumber.js/#toFr) method with an optional *maximum denominator* argument + +```javascript +y = new BigNumber(355) +pi = y.dividedBy(113) // "3.1415929204" +pi.toFraction() // [ "7853982301", "2500000000" ] +pi.toFraction(1000) // [ "355", "113" ] +``` + +and [`isNaN`](http://mikemcl.github.io/bignumber.js/#isNaN) and [`isFinite`](http://mikemcl.github.io/bignumber.js/#isF) methods, as `NaN` and `Infinity` are valid `BigNumber` values. + +```javascript +x = new BigNumber(NaN) // "NaN" +y = new BigNumber(Infinity) // "Infinity" +x.isNaN() && !y.isNaN() && !x.isFinite() && !y.isFinite() // true +``` + +The value of a BigNumber is stored in a decimal floating point format in terms of a coefficient, exponent and sign. + +```javascript +x = new BigNumber(-123.456); +x.c // [ 123, 45600000000000 ] coefficient (i.e. significand) +x.e // 2 exponent +x.s // -1 sign +``` + +For advanced usage, multiple BigNumber constructors can be created, each with its own independent configuration. + +```javascript +// Set DECIMAL_PLACES for the original BigNumber constructor +BigNumber.set({ DECIMAL_PLACES: 10 }) + +// Create another BigNumber constructor, optionally passing in a configuration object +BN = BigNumber.clone({ DECIMAL_PLACES: 5 }) + +x = new BigNumber(1) +y = new BN(1) + +x.div(3) // '0.3333333333' +y.div(3) // '0.33333' +``` + +To avoid having to call `toString` or `valueOf` on a BigNumber to get its value in the Node.js REPL or when using `console.log` use + +```javascript +BigNumber.prototype[require('util').inspect.custom] = BigNumber.prototype.valueOf; +``` + +For further information see the [API](http://mikemcl.github.io/bignumber.js/) reference in the *doc* directory. + +## Test + +The *test/modules* directory contains the test scripts for each method. + +The tests can be run with Node.js or a browser. For Node.js use + +```bash +npm test +``` + +or + +```bash +node test/test +``` + +To test a single method, use, for example + +```bash +node test/methods/toFraction +``` + +For the browser, open *test/test.html*. + +## Minify + +To minify using, for example, [terser](https://github.com/terser/terser) + +```bash +npm install -g terser +``` + +```bash +terser big.js -c -m -o big.min.js +``` + +## Licence + +The MIT Licence. + +See [LICENCE](https://github.com/MikeMcl/bignumber.js/blob/main/LICENCE.md). diff --git a/server/node_modules/bignumber.js/bignumber.d.mts b/server/node_modules/bignumber.js/bignumber.d.mts new file mode 100644 index 0000000..5d39f2e --- /dev/null +++ b/server/node_modules/bignumber.js/bignumber.d.mts @@ -0,0 +1,6 @@ +/// <reference path="./types.d.ts" /> + +export default BigNumber; + +declare const BigNumberType: typeof BigNumber; +export { BigNumberType as BigNumber }; diff --git a/server/node_modules/bignumber.js/bignumber.d.ts b/server/node_modules/bignumber.js/bignumber.d.ts new file mode 100644 index 0000000..3ee5405 --- /dev/null +++ b/server/node_modules/bignumber.js/bignumber.d.ts @@ -0,0 +1,5 @@ +/// <reference path="./types.d.ts" /> + +export = BigNumber; + +export as namespace BigNumber; diff --git a/server/node_modules/bignumber.js/bignumber.js b/server/node_modules/bignumber.js/bignumber.js new file mode 100644 index 0000000..c0891ea --- /dev/null +++ b/server/node_modules/bignumber.js/bignumber.js @@ -0,0 +1,2922 @@ +;(function (globalObject) { + 'use strict'; + +/* + * bignumber.js v9.3.1 + * A JavaScript library for arbitrary-precision arithmetic. + * https://github.com/MikeMcl/bignumber.js + * Copyright (c) 2025 Michael Mclaughlin <M8ch88l@gmail.com> + * MIT Licensed. + * + * BigNumber.prototype methods | BigNumber methods + * | + * absoluteValue abs | clone + * comparedTo | config set + * decimalPlaces dp | DECIMAL_PLACES + * dividedBy div | ROUNDING_MODE + * dividedToIntegerBy idiv | EXPONENTIAL_AT + * exponentiatedBy pow | RANGE + * integerValue | CRYPTO + * isEqualTo eq | MODULO_MODE + * isFinite | POW_PRECISION + * isGreaterThan gt | FORMAT + * isGreaterThanOrEqualTo gte | ALPHABET + * isInteger | isBigNumber + * isLessThan lt | maximum max + * isLessThanOrEqualTo lte | minimum min + * isNaN | random + * isNegative | sum + * isPositive | + * isZero | + * minus | + * modulo mod | + * multipliedBy times | + * negated | + * plus | + * precision sd | + * shiftedBy | + * squareRoot sqrt | + * toExponential | + * toFixed | + * toFormat | + * toFraction | + * toJSON | + * toNumber | + * toPrecision | + * toString | + * valueOf | + * + */ + + + var BigNumber, + isNumeric = /^-?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?$/i, + mathceil = Math.ceil, + mathfloor = Math.floor, + + bignumberError = '[BigNumber Error] ', + tooManyDigits = bignumberError + 'Number primitive has more than 15 significant digits: ', + + BASE = 1e14, + LOG_BASE = 14, + MAX_SAFE_INTEGER = 0x1fffffffffffff, // 2^53 - 1 + // MAX_INT32 = 0x7fffffff, // 2^31 - 1 + POWS_TEN = [1, 10, 100, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13], + SQRT_BASE = 1e7, + + // EDITABLE + // The limit on the value of DECIMAL_PLACES, TO_EXP_NEG, TO_EXP_POS, MIN_EXP, MAX_EXP, and + // the arguments to toExponential, toFixed, toFormat, and toPrecision. + MAX = 1E9; // 0 to MAX_INT32 + + + /* + * Create and return a BigNumber constructor. + */ + function clone(configObject) { + var div, convertBase, parseNumeric, + P = BigNumber.prototype = { constructor: BigNumber, toString: null, valueOf: null }, + ONE = new BigNumber(1), + + + //----------------------------- EDITABLE CONFIG DEFAULTS ------------------------------- + + + // The default values below must be integers within the inclusive ranges stated. + // The values can also be changed at run-time using BigNumber.set. + + // The maximum number of decimal places for operations involving division. + DECIMAL_PLACES = 20, // 0 to MAX + + // The rounding mode used when rounding to the above decimal places, and when using + // toExponential, toFixed, toFormat and toPrecision, and round (default value). + // UP 0 Away from zero. + // DOWN 1 Towards zero. + // CEIL 2 Towards +Infinity. + // FLOOR 3 Towards -Infinity. + // HALF_UP 4 Towards nearest neighbour. If equidistant, up. + // HALF_DOWN 5 Towards nearest neighbour. If equidistant, down. + // HALF_EVEN 6 Towards nearest neighbour. If equidistant, towards even neighbour. + // HALF_CEIL 7 Towards nearest neighbour. If equidistant, towards +Infinity. + // HALF_FLOOR 8 Towards nearest neighbour. If equidistant, towards -Infinity. + ROUNDING_MODE = 4, // 0 to 8 + + // EXPONENTIAL_AT : [TO_EXP_NEG , TO_EXP_POS] + + // The exponent value at and beneath which toString returns exponential notation. + // Number type: -7 + TO_EXP_NEG = -7, // 0 to -MAX + + // The exponent value at and above which toString returns exponential notation. + // Number type: 21 + TO_EXP_POS = 21, // 0 to MAX + + // RANGE : [MIN_EXP, MAX_EXP] + + // The minimum exponent value, beneath which underflow to zero occurs. + // Number type: -324 (5e-324) + MIN_EXP = -1e7, // -1 to -MAX + + // The maximum exponent value, above which overflow to Infinity occurs. + // Number type: 308 (1.7976931348623157e+308) + // For MAX_EXP > 1e7, e.g. new BigNumber('1e100000000').plus(1) may be slow. + MAX_EXP = 1e7, // 1 to MAX + + // Whether to use cryptographically-secure random number generation, if available. + CRYPTO = false, // true or false + + // The modulo mode used when calculating the modulus: a mod n. + // The quotient (q = a / n) is calculated according to the corresponding rounding mode. + // The remainder (r) is calculated as: r = a - n * q. + // + // UP 0 The remainder is positive if the dividend is negative, else is negative. + // DOWN 1 The remainder has the same sign as the dividend. + // This modulo mode is commonly known as 'truncated division' and is + // equivalent to (a % n) in JavaScript. + // FLOOR 3 The remainder has the same sign as the divisor (Python %). + // HALF_EVEN 6 This modulo mode implements the IEEE 754 remainder function. + // EUCLID 9 Euclidian division. q = sign(n) * floor(a / abs(n)). + // The remainder is always positive. + // + // The truncated division, floored division, Euclidian division and IEEE 754 remainder + // modes are commonly used for the modulus operation. + // Although the other rounding modes can also be used, they may not give useful results. + MODULO_MODE = 1, // 0 to 9 + + // The maximum number of significant digits of the result of the exponentiatedBy operation. + // If POW_PRECISION is 0, there will be unlimited significant digits. + POW_PRECISION = 0, // 0 to MAX + + // The format specification used by the BigNumber.prototype.toFormat method. + FORMAT = { + prefix: '', + groupSize: 3, + secondaryGroupSize: 0, + groupSeparator: ',', + decimalSeparator: '.', + fractionGroupSize: 0, + fractionGroupSeparator: '\xA0', // non-breaking space + suffix: '' + }, + + // The alphabet used for base conversion. It must be at least 2 characters long, with no '+', + // '-', '.', whitespace, or repeated character. + // '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_' + ALPHABET = '0123456789abcdefghijklmnopqrstuvwxyz', + alphabetHasNormalDecimalDigits = true; + + + //------------------------------------------------------------------------------------------ + + + // CONSTRUCTOR + + + /* + * The BigNumber constructor and exported function. + * Create and return a new instance of a BigNumber object. + * + * v {number|string|BigNumber} A numeric value. + * [b] {number} The base of v. Integer, 2 to ALPHABET.length inclusive. + */ + function BigNumber(v, b) { + var alphabet, c, caseChanged, e, i, isNum, len, str, + x = this; + + // Enable constructor call without `new`. + if (!(x instanceof BigNumber)) return new BigNumber(v, b); + + if (b == null) { + + if (v && v._isBigNumber === true) { + x.s = v.s; + + if (!v.c || v.e > MAX_EXP) { + x.c = x.e = null; + } else if (v.e < MIN_EXP) { + x.c = [x.e = 0]; + } else { + x.e = v.e; + x.c = v.c.slice(); + } + + return; + } + + if ((isNum = typeof v == 'number') && v * 0 == 0) { + + // Use `1 / n` to handle minus zero also. + x.s = 1 / v < 0 ? (v = -v, -1) : 1; + + // Fast path for integers, where n < 2147483648 (2**31). + if (v === ~~v) { + for (e = 0, i = v; i >= 10; i /= 10, e++); + + if (e > MAX_EXP) { + x.c = x.e = null; + } else { + x.e = e; + x.c = [v]; + } + + return; + } + + str = String(v); + } else { + + if (!isNumeric.test(str = String(v))) return parseNumeric(x, str, isNum); + + x.s = str.charCodeAt(0) == 45 ? (str = str.slice(1), -1) : 1; + } + + // Decimal point? + if ((e = str.indexOf('.')) > -1) str = str.replace('.', ''); + + // Exponential form? + if ((i = str.search(/e/i)) > 0) { + + // Determine exponent. + if (e < 0) e = i; + e += +str.slice(i + 1); + str = str.substring(0, i); + } else if (e < 0) { + + // Integer. + e = str.length; + } + + } else { + + // '[BigNumber Error] Base {not a primitive number|not an integer|out of range}: {b}' + intCheck(b, 2, ALPHABET.length, 'Base'); + + // Allow exponential notation to be used with base 10 argument, while + // also rounding to DECIMAL_PLACES as with other bases. + if (b == 10 && alphabetHasNormalDecimalDigits) { + x = new BigNumber(v); + return round(x, DECIMAL_PLACES + x.e + 1, ROUNDING_MODE); + } + + str = String(v); + + if (isNum = typeof v == 'number') { + + // Avoid potential interpretation of Infinity and NaN as base 44+ values. + if (v * 0 != 0) return parseNumeric(x, str, isNum, b); + + x.s = 1 / v < 0 ? (str = str.slice(1), -1) : 1; + + // '[BigNumber Error] Number primitive has more than 15 significant digits: {n}' + if (BigNumber.DEBUG && str.replace(/^0\.0*|\./, '').length > 15) { + throw Error + (tooManyDigits + v); + } + } else { + x.s = str.charCodeAt(0) === 45 ? (str = str.slice(1), -1) : 1; + } + + alphabet = ALPHABET.slice(0, b); + e = i = 0; + + // Check that str is a valid base b number. + // Don't use RegExp, so alphabet can contain special characters. + for (len = str.length; i < len; i++) { + if (alphabet.indexOf(c = str.charAt(i)) < 0) { + if (c == '.') { + + // If '.' is not the first character and it has not be found before. + if (i > e) { + e = len; + continue; + } + } else if (!caseChanged) { + + // Allow e.g. hexadecimal 'FF' as well as 'ff'. + if (str == str.toUpperCase() && (str = str.toLowerCase()) || + str == str.toLowerCase() && (str = str.toUpperCase())) { + caseChanged = true; + i = -1; + e = 0; + continue; + } + } + + return parseNumeric(x, String(v), isNum, b); + } + } + + // Prevent later check for length on converted number. + isNum = false; + str = convertBase(str, b, 10, x.s); + + // Decimal point? + if ((e = str.indexOf('.')) > -1) str = str.replace('.', ''); + else e = str.length; + } + + // Determine leading zeros. + for (i = 0; str.charCodeAt(i) === 48; i++); + + // Determine trailing zeros. + for (len = str.length; str.charCodeAt(--len) === 48;); + + if (str = str.slice(i, ++len)) { + len -= i; + + // '[BigNumber Error] Number primitive has more than 15 significant digits: {n}' + if (isNum && BigNumber.DEBUG && + len > 15 && (v > MAX_SAFE_INTEGER || v !== mathfloor(v))) { + throw Error + (tooManyDigits + (x.s * v)); + } + + // Overflow? + if ((e = e - i - 1) > MAX_EXP) { + + // Infinity. + x.c = x.e = null; + + // Underflow? + } else if (e < MIN_EXP) { + + // Zero. + x.c = [x.e = 0]; + } else { + x.e = e; + x.c = []; + + // Transform base + + // e is the base 10 exponent. + // i is where to slice str to get the first element of the coefficient array. + i = (e + 1) % LOG_BASE; + if (e < 0) i += LOG_BASE; // i < 1 + + if (i < len) { + if (i) x.c.push(+str.slice(0, i)); + + for (len -= LOG_BASE; i < len;) { + x.c.push(+str.slice(i, i += LOG_BASE)); + } + + i = LOG_BASE - (str = str.slice(i)).length; + } else { + i -= len; + } + + for (; i--; str += '0'); + x.c.push(+str); + } + } else { + + // Zero. + x.c = [x.e = 0]; + } + } + + + // CONSTRUCTOR PROPERTIES + + + BigNumber.clone = clone; + + BigNumber.ROUND_UP = 0; + BigNumber.ROUND_DOWN = 1; + BigNumber.ROUND_CEIL = 2; + BigNumber.ROUND_FLOOR = 3; + BigNumber.ROUND_HALF_UP = 4; + BigNumber.ROUND_HALF_DOWN = 5; + BigNumber.ROUND_HALF_EVEN = 6; + BigNumber.ROUND_HALF_CEIL = 7; + BigNumber.ROUND_HALF_FLOOR = 8; + BigNumber.EUCLID = 9; + + + /* + * Configure infrequently-changing library-wide settings. + * + * Accept an object with the following optional properties (if the value of a property is + * a number, it must be an integer within the inclusive range stated): + * + * DECIMAL_PLACES {number} 0 to MAX + * ROUNDING_MODE {number} 0 to 8 + * EXPONENTIAL_AT {number|number[]} -MAX to MAX or [-MAX to 0, 0 to MAX] + * RANGE {number|number[]} -MAX to MAX (not zero) or [-MAX to -1, 1 to MAX] + * CRYPTO {boolean} true or false + * MODULO_MODE {number} 0 to 9 + * POW_PRECISION {number} 0 to MAX + * ALPHABET {string} A string of two or more unique characters which does + * not contain '.'. + * FORMAT {object} An object with some of the following properties: + * prefix {string} + * groupSize {number} + * secondaryGroupSize {number} + * groupSeparator {string} + * decimalSeparator {string} + * fractionGroupSize {number} + * fractionGroupSeparator {string} + * suffix {string} + * + * (The values assigned to the above FORMAT object properties are not checked for validity.) + * + * E.g. + * BigNumber.config({ DECIMAL_PLACES : 20, ROUNDING_MODE : 4 }) + * + * Ignore properties/parameters set to null or undefined, except for ALPHABET. + * + * Return an object with the properties current values. + */ + BigNumber.config = BigNumber.set = function (obj) { + var p, v; + + if (obj != null) { + + if (typeof obj == 'object') { + + // DECIMAL_PLACES {number} Integer, 0 to MAX inclusive. + // '[BigNumber Error] DECIMAL_PLACES {not a primitive number|not an integer|out of range}: {v}' + if (obj.hasOwnProperty(p = 'DECIMAL_PLACES')) { + v = obj[p]; + intCheck(v, 0, MAX, p); + DECIMAL_PLACES = v; + } + + // ROUNDING_MODE {number} Integer, 0 to 8 inclusive. + // '[BigNumber Error] ROUNDING_MODE {not a primitive number|not an integer|out of range}: {v}' + if (obj.hasOwnProperty(p = 'ROUNDING_MODE')) { + v = obj[p]; + intCheck(v, 0, 8, p); + ROUNDING_MODE = v; + } + + // EXPONENTIAL_AT {number|number[]} + // Integer, -MAX to MAX inclusive or + // [integer -MAX to 0 inclusive, 0 to MAX inclusive]. + // '[BigNumber Error] EXPONENTIAL_AT {not a primitive number|not an integer|out of range}: {v}' + if (obj.hasOwnProperty(p = 'EXPONENTIAL_AT')) { + v = obj[p]; + if (v && v.pop) { + intCheck(v[0], -MAX, 0, p); + intCheck(v[1], 0, MAX, p); + TO_EXP_NEG = v[0]; + TO_EXP_POS = v[1]; + } else { + intCheck(v, -MAX, MAX, p); + TO_EXP_NEG = -(TO_EXP_POS = v < 0 ? -v : v); + } + } + + // RANGE {number|number[]} Non-zero integer, -MAX to MAX inclusive or + // [integer -MAX to -1 inclusive, integer 1 to MAX inclusive]. + // '[BigNumber Error] RANGE {not a primitive number|not an integer|out of range|cannot be zero}: {v}' + if (obj.hasOwnProperty(p = 'RANGE')) { + v = obj[p]; + if (v && v.pop) { + intCheck(v[0], -MAX, -1, p); + intCheck(v[1], 1, MAX, p); + MIN_EXP = v[0]; + MAX_EXP = v[1]; + } else { + intCheck(v, -MAX, MAX, p); + if (v) { + MIN_EXP = -(MAX_EXP = v < 0 ? -v : v); + } else { + throw Error + (bignumberError + p + ' cannot be zero: ' + v); + } + } + } + + // CRYPTO {boolean} true or false. + // '[BigNumber Error] CRYPTO not true or false: {v}' + // '[BigNumber Error] crypto unavailable' + if (obj.hasOwnProperty(p = 'CRYPTO')) { + v = obj[p]; + if (v === !!v) { + if (v) { + if (typeof crypto != 'undefined' && crypto && + (crypto.getRandomValues || crypto.randomBytes)) { + CRYPTO = v; + } else { + CRYPTO = !v; + throw Error + (bignumberError + 'crypto unavailable'); + } + } else { + CRYPTO = v; + } + } else { + throw Error + (bignumberError + p + ' not true or false: ' + v); + } + } + + // MODULO_MODE {number} Integer, 0 to 9 inclusive. + // '[BigNumber Error] MODULO_MODE {not a primitive number|not an integer|out of range}: {v}' + if (obj.hasOwnProperty(p = 'MODULO_MODE')) { + v = obj[p]; + intCheck(v, 0, 9, p); + MODULO_MODE = v; + } + + // POW_PRECISION {number} Integer, 0 to MAX inclusive. + // '[BigNumber Error] POW_PRECISION {not a primitive number|not an integer|out of range}: {v}' + if (obj.hasOwnProperty(p = 'POW_PRECISION')) { + v = obj[p]; + intCheck(v, 0, MAX, p); + POW_PRECISION = v; + } + + // FORMAT {object} + // '[BigNumber Error] FORMAT not an object: {v}' + if (obj.hasOwnProperty(p = 'FORMAT')) { + v = obj[p]; + if (typeof v == 'object') FORMAT = v; + else throw Error + (bignumberError + p + ' not an object: ' + v); + } + + // ALPHABET {string} + // '[BigNumber Error] ALPHABET invalid: {v}' + if (obj.hasOwnProperty(p = 'ALPHABET')) { + v = obj[p]; + + // Disallow if less than two characters, + // or if it contains '+', '-', '.', whitespace, or a repeated character. + if (typeof v == 'string' && !/^.?$|[+\-.\s]|(.).*\1/.test(v)) { + alphabetHasNormalDecimalDigits = v.slice(0, 10) == '0123456789'; + ALPHABET = v; + } else { + throw Error + (bignumberError + p + ' invalid: ' + v); + } + } + + } else { + + // '[BigNumber Error] Object expected: {v}' + throw Error + (bignumberError + 'Object expected: ' + obj); + } + } + + return { + DECIMAL_PLACES: DECIMAL_PLACES, + ROUNDING_MODE: ROUNDING_MODE, + EXPONENTIAL_AT: [TO_EXP_NEG, TO_EXP_POS], + RANGE: [MIN_EXP, MAX_EXP], + CRYPTO: CRYPTO, + MODULO_MODE: MODULO_MODE, + POW_PRECISION: POW_PRECISION, + FORMAT: FORMAT, + ALPHABET: ALPHABET + }; + }; + + + /* + * Return true if v is a BigNumber instance, otherwise return false. + * + * If BigNumber.DEBUG is true, throw if a BigNumber instance is not well-formed. + * + * v {any} + * + * '[BigNumber Error] Invalid BigNumber: {v}' + */ + BigNumber.isBigNumber = function (v) { + if (!v || v._isBigNumber !== true) return false; + if (!BigNumber.DEBUG) return true; + + var i, n, + c = v.c, + e = v.e, + s = v.s; + + out: if ({}.toString.call(c) == '[object Array]') { + + if ((s === 1 || s === -1) && e >= -MAX && e <= MAX && e === mathfloor(e)) { + + // If the first element is zero, the BigNumber value must be zero. + if (c[0] === 0) { + if (e === 0 && c.length === 1) return true; + break out; + } + + // Calculate number of digits that c[0] should have, based on the exponent. + i = (e + 1) % LOG_BASE; + if (i < 1) i += LOG_BASE; + + // Calculate number of digits of c[0]. + //if (Math.ceil(Math.log(c[0] + 1) / Math.LN10) == i) { + if (String(c[0]).length == i) { + + for (i = 0; i < c.length; i++) { + n = c[i]; + if (n < 0 || n >= BASE || n !== mathfloor(n)) break out; + } + + // Last element cannot be zero, unless it is the only element. + if (n !== 0) return true; + } + } + + // Infinity/NaN + } else if (c === null && e === null && (s === null || s === 1 || s === -1)) { + return true; + } + + throw Error + (bignumberError + 'Invalid BigNumber: ' + v); + }; + + + /* + * Return a new BigNumber whose value is the maximum of the arguments. + * + * arguments {number|string|BigNumber} + */ + BigNumber.maximum = BigNumber.max = function () { + return maxOrMin(arguments, -1); + }; + + + /* + * Return a new BigNumber whose value is the minimum of the arguments. + * + * arguments {number|string|BigNumber} + */ + BigNumber.minimum = BigNumber.min = function () { + return maxOrMin(arguments, 1); + }; + + + /* + * Return a new BigNumber with a random value equal to or greater than 0 and less than 1, + * and with dp, or DECIMAL_PLACES if dp is omitted, decimal places (or less if trailing + * zeros are produced). + * + * [dp] {number} Decimal places. Integer, 0 to MAX inclusive. + * + * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {dp}' + * '[BigNumber Error] crypto unavailable' + */ + BigNumber.random = (function () { + var pow2_53 = 0x20000000000000; + + // Return a 53 bit integer n, where 0 <= n < 9007199254740992. + // Check if Math.random() produces more than 32 bits of randomness. + // If it does, assume at least 53 bits are produced, otherwise assume at least 30 bits. + // 0x40000000 is 2^30, 0x800000 is 2^23, 0x1fffff is 2^21 - 1. + var random53bitInt = (Math.random() * pow2_53) & 0x1fffff + ? function () { return mathfloor(Math.random() * pow2_53); } + : function () { return ((Math.random() * 0x40000000 | 0) * 0x800000) + + (Math.random() * 0x800000 | 0); }; + + return function (dp) { + var a, b, e, k, v, + i = 0, + c = [], + rand = new BigNumber(ONE); + + if (dp == null) dp = DECIMAL_PLACES; + else intCheck(dp, 0, MAX); + + k = mathceil(dp / LOG_BASE); + + if (CRYPTO) { + + // Browsers supporting crypto.getRandomValues. + if (crypto.getRandomValues) { + + a = crypto.getRandomValues(new Uint32Array(k *= 2)); + + for (; i < k;) { + + // 53 bits: + // ((Math.pow(2, 32) - 1) * Math.pow(2, 21)).toString(2) + // 11111 11111111 11111111 11111111 11100000 00000000 00000000 + // ((Math.pow(2, 32) - 1) >>> 11).toString(2) + // 11111 11111111 11111111 + // 0x20000 is 2^21. + v = a[i] * 0x20000 + (a[i + 1] >>> 11); + + // Rejection sampling: + // 0 <= v < 9007199254740992 + // Probability that v >= 9e15, is + // 7199254740992 / 9007199254740992 ~= 0.0008, i.e. 1 in 1251 + if (v >= 9e15) { + b = crypto.getRandomValues(new Uint32Array(2)); + a[i] = b[0]; + a[i + 1] = b[1]; + } else { + + // 0 <= v <= 8999999999999999 + // 0 <= (v % 1e14) <= 99999999999999 + c.push(v % 1e14); + i += 2; + } + } + i = k / 2; + + // Node.js supporting crypto.randomBytes. + } else if (crypto.randomBytes) { + + // buffer + a = crypto.randomBytes(k *= 7); + + for (; i < k;) { + + // 0x1000000000000 is 2^48, 0x10000000000 is 2^40 + // 0x100000000 is 2^32, 0x1000000 is 2^24 + // 11111 11111111 11111111 11111111 11111111 11111111 11111111 + // 0 <= v < 9007199254740992 + v = ((a[i] & 31) * 0x1000000000000) + (a[i + 1] * 0x10000000000) + + (a[i + 2] * 0x100000000) + (a[i + 3] * 0x1000000) + + (a[i + 4] << 16) + (a[i + 5] << 8) + a[i + 6]; + + if (v >= 9e15) { + crypto.randomBytes(7).copy(a, i); + } else { + + // 0 <= (v % 1e14) <= 99999999999999 + c.push(v % 1e14); + i += 7; + } + } + i = k / 7; + } else { + CRYPTO = false; + throw Error + (bignumberError + 'crypto unavailable'); + } + } + + // Use Math.random. + if (!CRYPTO) { + + for (; i < k;) { + v = random53bitInt(); + if (v < 9e15) c[i++] = v % 1e14; + } + } + + k = c[--i]; + dp %= LOG_BASE; + + // Convert trailing digits to zeros according to dp. + if (k && dp) { + v = POWS_TEN[LOG_BASE - dp]; + c[i] = mathfloor(k / v) * v; + } + + // Remove trailing elements which are zero. + for (; c[i] === 0; c.pop(), i--); + + // Zero? + if (i < 0) { + c = [e = 0]; + } else { + + // Remove leading elements which are zero and adjust exponent accordingly. + for (e = -1 ; c[0] === 0; c.splice(0, 1), e -= LOG_BASE); + + // Count the digits of the first element of c to determine leading zeros, and... + for (i = 1, v = c[0]; v >= 10; v /= 10, i++); + + // adjust the exponent accordingly. + if (i < LOG_BASE) e -= LOG_BASE - i; + } + + rand.e = e; + rand.c = c; + return rand; + }; + })(); + + + /* + * Return a BigNumber whose value is the sum of the arguments. + * + * arguments {number|string|BigNumber} + */ + BigNumber.sum = function () { + var i = 1, + args = arguments, + sum = new BigNumber(args[0]); + for (; i < args.length;) sum = sum.plus(args[i++]); + return sum; + }; + + + // PRIVATE FUNCTIONS + + + // Called by BigNumber and BigNumber.prototype.toString. + convertBase = (function () { + var decimal = '0123456789'; + + /* + * Convert string of baseIn to an array of numbers of baseOut. + * Eg. toBaseOut('255', 10, 16) returns [15, 15]. + * Eg. toBaseOut('ff', 16, 10) returns [2, 5, 5]. + */ + function toBaseOut(str, baseIn, baseOut, alphabet) { + var j, + arr = [0], + arrL, + i = 0, + len = str.length; + + for (; i < len;) { + for (arrL = arr.length; arrL--; arr[arrL] *= baseIn); + + arr[0] += alphabet.indexOf(str.charAt(i++)); + + for (j = 0; j < arr.length; j++) { + + if (arr[j] > baseOut - 1) { + if (arr[j + 1] == null) arr[j + 1] = 0; + arr[j + 1] += arr[j] / baseOut | 0; + arr[j] %= baseOut; + } + } + } + + return arr.reverse(); + } + + // Convert a numeric string of baseIn to a numeric string of baseOut. + // If the caller is toString, we are converting from base 10 to baseOut. + // If the caller is BigNumber, we are converting from baseIn to base 10. + return function (str, baseIn, baseOut, sign, callerIsToString) { + var alphabet, d, e, k, r, x, xc, y, + i = str.indexOf('.'), + dp = DECIMAL_PLACES, + rm = ROUNDING_MODE; + + // Non-integer. + if (i >= 0) { + k = POW_PRECISION; + + // Unlimited precision. + POW_PRECISION = 0; + str = str.replace('.', ''); + y = new BigNumber(baseIn); + x = y.pow(str.length - i); + POW_PRECISION = k; + + // Convert str as if an integer, then restore the fraction part by dividing the + // result by its base raised to a power. + + y.c = toBaseOut(toFixedPoint(coeffToString(x.c), x.e, '0'), + 10, baseOut, decimal); + y.e = y.c.length; + } + + // Convert the number as integer. + + xc = toBaseOut(str, baseIn, baseOut, callerIsToString + ? (alphabet = ALPHABET, decimal) + : (alphabet = decimal, ALPHABET)); + + // xc now represents str as an integer and converted to baseOut. e is the exponent. + e = k = xc.length; + + // Remove trailing zeros. + for (; xc[--k] == 0; xc.pop()); + + // Zero? + if (!xc[0]) return alphabet.charAt(0); + + // Does str represent an integer? If so, no need for the division. + if (i < 0) { + --e; + } else { + x.c = xc; + x.e = e; + + // The sign is needed for correct rounding. + x.s = sign; + x = div(x, y, dp, rm, baseOut); + xc = x.c; + r = x.r; + e = x.e; + } + + // xc now represents str converted to baseOut. + + // The index of the rounding digit. + d = e + dp + 1; + + // The rounding digit: the digit to the right of the digit that may be rounded up. + i = xc[d]; + + // Look at the rounding digits and mode to determine whether to round up. + + k = baseOut / 2; + r = r || d < 0 || xc[d + 1] != null; + + r = rm < 4 ? (i != null || r) && (rm == 0 || rm == (x.s < 0 ? 3 : 2)) + : i > k || i == k &&(rm == 4 || r || rm == 6 && xc[d - 1] & 1 || + rm == (x.s < 0 ? 8 : 7)); + + // If the index of the rounding digit is not greater than zero, or xc represents + // zero, then the result of the base conversion is zero or, if rounding up, a value + // such as 0.00001. + if (d < 1 || !xc[0]) { + + // 1^-dp or 0 + str = r ? toFixedPoint(alphabet.charAt(1), -dp, alphabet.charAt(0)) : alphabet.charAt(0); + } else { + + // Truncate xc to the required number of decimal places. + xc.length = d; + + // Round up? + if (r) { + + // Rounding up may mean the previous digit has to be rounded up and so on. + for (--baseOut; ++xc[--d] > baseOut;) { + xc[d] = 0; + + if (!d) { + ++e; + xc = [1].concat(xc); + } + } + } + + // Determine trailing zeros. + for (k = xc.length; !xc[--k];); + + // E.g. [4, 11, 15] becomes 4bf. + for (i = 0, str = ''; i <= k; str += alphabet.charAt(xc[i++])); + + // Add leading zeros, decimal point and trailing zeros as required. + str = toFixedPoint(str, e, alphabet.charAt(0)); + } + + // The caller will add the sign. + return str; + }; + })(); + + + // Perform division in the specified base. Called by div and convertBase. + div = (function () { + + // Assume non-zero x and k. + function multiply(x, k, base) { + var m, temp, xlo, xhi, + carry = 0, + i = x.length, + klo = k % SQRT_BASE, + khi = k / SQRT_BASE | 0; + + for (x = x.slice(); i--;) { + xlo = x[i] % SQRT_BASE; + xhi = x[i] / SQRT_BASE | 0; + m = khi * xlo + xhi * klo; + temp = klo * xlo + ((m % SQRT_BASE) * SQRT_BASE) + carry; + carry = (temp / base | 0) + (m / SQRT_BASE | 0) + khi * xhi; + x[i] = temp % base; + } + + if (carry) x = [carry].concat(x); + + return x; + } + + function compare(a, b, aL, bL) { + var i, cmp; + + if (aL != bL) { + cmp = aL > bL ? 1 : -1; + } else { + + for (i = cmp = 0; i < aL; i++) { + + if (a[i] != b[i]) { + cmp = a[i] > b[i] ? 1 : -1; + break; + } + } + } + + return cmp; + } + + function subtract(a, b, aL, base) { + var i = 0; + + // Subtract b from a. + for (; aL--;) { + a[aL] -= i; + i = a[aL] < b[aL] ? 1 : 0; + a[aL] = i * base + a[aL] - b[aL]; + } + + // Remove leading zeros. + for (; !a[0] && a.length > 1; a.splice(0, 1)); + } + + // x: dividend, y: divisor. + return function (x, y, dp, rm, base) { + var cmp, e, i, more, n, prod, prodL, q, qc, rem, remL, rem0, xi, xL, yc0, + yL, yz, + s = x.s == y.s ? 1 : -1, + xc = x.c, + yc = y.c; + + // Either NaN, Infinity or 0? + if (!xc || !xc[0] || !yc || !yc[0]) { + + return new BigNumber( + + // Return NaN if either NaN, or both Infinity or 0. + !x.s || !y.s || (xc ? yc && xc[0] == yc[0] : !yc) ? NaN : + + // Return ±0 if x is ±0 or y is ±Infinity, or return ±Infinity as y is ±0. + xc && xc[0] == 0 || !yc ? s * 0 : s / 0 + ); + } + + q = new BigNumber(s); + qc = q.c = []; + e = x.e - y.e; + s = dp + e + 1; + + if (!base) { + base = BASE; + e = bitFloor(x.e / LOG_BASE) - bitFloor(y.e / LOG_BASE); + s = s / LOG_BASE | 0; + } + + // Result exponent may be one less then the current value of e. + // The coefficients of the BigNumbers from convertBase may have trailing zeros. + for (i = 0; yc[i] == (xc[i] || 0); i++); + + if (yc[i] > (xc[i] || 0)) e--; + + if (s < 0) { + qc.push(1); + more = true; + } else { + xL = xc.length; + yL = yc.length; + i = 0; + s += 2; + + // Normalise xc and yc so highest order digit of yc is >= base / 2. + + n = mathfloor(base / (yc[0] + 1)); + + // Not necessary, but to handle odd bases where yc[0] == (base / 2) - 1. + // if (n > 1 || n++ == 1 && yc[0] < base / 2) { + if (n > 1) { + yc = multiply(yc, n, base); + xc = multiply(xc, n, base); + yL = yc.length; + xL = xc.length; + } + + xi = yL; + rem = xc.slice(0, yL); + remL = rem.length; + + // Add zeros to make remainder as long as divisor. + for (; remL < yL; rem[remL++] = 0); + yz = yc.slice(); + yz = [0].concat(yz); + yc0 = yc[0]; + if (yc[1] >= base / 2) yc0++; + // Not necessary, but to prevent trial digit n > base, when using base 3. + // else if (base == 3 && yc0 == 1) yc0 = 1 + 1e-15; + + do { + n = 0; + + // Compare divisor and remainder. + cmp = compare(yc, rem, yL, remL); + + // If divisor < remainder. + if (cmp < 0) { + + // Calculate trial digit, n. + + rem0 = rem[0]; + if (yL != remL) rem0 = rem0 * base + (rem[1] || 0); + + // n is how many times the divisor goes into the current remainder. + n = mathfloor(rem0 / yc0); + + // Algorithm: + // product = divisor multiplied by trial digit (n). + // Compare product and remainder. + // If product is greater than remainder: + // Subtract divisor from product, decrement trial digit. + // Subtract product from remainder. + // If product was less than remainder at the last compare: + // Compare new remainder and divisor. + // If remainder is greater than divisor: + // Subtract divisor from remainder, increment trial digit. + + if (n > 1) { + + // n may be > base only when base is 3. + if (n >= base) n = base - 1; + + // product = divisor * trial digit. + prod = multiply(yc, n, base); + prodL = prod.length; + remL = rem.length; + + // Compare product and remainder. + // If product > remainder then trial digit n too high. + // n is 1 too high about 5% of the time, and is not known to have + // ever been more than 1 too high. + while (compare(prod, rem, prodL, remL) == 1) { + n--; + + // Subtract divisor from product. + subtract(prod, yL < prodL ? yz : yc, prodL, base); + prodL = prod.length; + cmp = 1; + } + } else { + + // n is 0 or 1, cmp is -1. + // If n is 0, there is no need to compare yc and rem again below, + // so change cmp to 1 to avoid it. + // If n is 1, leave cmp as -1, so yc and rem are compared again. + if (n == 0) { + + // divisor < remainder, so n must be at least 1. + cmp = n = 1; + } + + // product = divisor + prod = yc.slice(); + prodL = prod.length; + } + + if (prodL < remL) prod = [0].concat(prod); + + // Subtract product from remainder. + subtract(rem, prod, remL, base); + remL = rem.length; + + // If product was < remainder. + if (cmp == -1) { + + // Compare divisor and new remainder. + // If divisor < new remainder, subtract divisor from remainder. + // Trial digit n too low. + // n is 1 too low about 5% of the time, and very rarely 2 too low. + while (compare(yc, rem, yL, remL) < 1) { + n++; + + // Subtract divisor from remainder. + subtract(rem, yL < remL ? yz : yc, remL, base); + remL = rem.length; + } + } + } else if (cmp === 0) { + n++; + rem = [0]; + } // else cmp === 1 and n will be 0 + + // Add the next digit, n, to the result array. + qc[i++] = n; + + // Update the remainder. + if (rem[0]) { + rem[remL++] = xc[xi] || 0; + } else { + rem = [xc[xi]]; + remL = 1; + } + } while ((xi++ < xL || rem[0] != null) && s--); + + more = rem[0] != null; + + // Leading zero? + if (!qc[0]) qc.splice(0, 1); + } + + if (base == BASE) { + + // To calculate q.e, first get the number of digits of qc[0]. + for (i = 1, s = qc[0]; s >= 10; s /= 10, i++); + + round(q, dp + (q.e = i + e * LOG_BASE - 1) + 1, rm, more); + + // Caller is convertBase. + } else { + q.e = e; + q.r = +more; + } + + return q; + }; + })(); + + + /* + * Return a string representing the value of BigNumber n in fixed-point or exponential + * notation rounded to the specified decimal places or significant digits. + * + * n: a BigNumber. + * i: the index of the last digit required (i.e. the digit that may be rounded up). + * rm: the rounding mode. + * id: 1 (toExponential) or 2 (toPrecision). + */ + function format(n, i, rm, id) { + var c0, e, ne, len, str; + + if (rm == null) rm = ROUNDING_MODE; + else intCheck(rm, 0, 8); + + if (!n.c) return n.toString(); + + c0 = n.c[0]; + ne = n.e; + + if (i == null) { + str = coeffToString(n.c); + str = id == 1 || id == 2 && (ne <= TO_EXP_NEG || ne >= TO_EXP_POS) + ? toExponential(str, ne) + : toFixedPoint(str, ne, '0'); + } else { + n = round(new BigNumber(n), i, rm); + + // n.e may have changed if the value was rounded up. + e = n.e; + + str = coeffToString(n.c); + len = str.length; + + // toPrecision returns exponential notation if the number of significant digits + // specified is less than the number of digits necessary to represent the integer + // part of the value in fixed-point notation. + + // Exponential notation. + if (id == 1 || id == 2 && (i <= e || e <= TO_EXP_NEG)) { + + // Append zeros? + for (; len < i; str += '0', len++); + str = toExponential(str, e); + + // Fixed-point notation. + } else { + i -= ne + (id === 2 && e > ne); + str = toFixedPoint(str, e, '0'); + + // Append zeros? + if (e + 1 > len) { + if (--i > 0) for (str += '.'; i--; str += '0'); + } else { + i += e - len; + if (i > 0) { + if (e + 1 == len) str += '.'; + for (; i--; str += '0'); + } + } + } + } + + return n.s < 0 && c0 ? '-' + str : str; + } + + + // Handle BigNumber.max and BigNumber.min. + // If any number is NaN, return NaN. + function maxOrMin(args, n) { + var k, y, + i = 1, + x = new BigNumber(args[0]); + + for (; i < args.length; i++) { + y = new BigNumber(args[i]); + if (!y.s || (k = compare(x, y)) === n || k === 0 && x.s === n) { + x = y; + } + } + + return x; + } + + + /* + * Strip trailing zeros, calculate base 10 exponent and check against MIN_EXP and MAX_EXP. + * Called by minus, plus and times. + */ + function normalise(n, c, e) { + var i = 1, + j = c.length; + + // Remove trailing zeros. + for (; !c[--j]; c.pop()); + + // Calculate the base 10 exponent. First get the number of digits of c[0]. + for (j = c[0]; j >= 10; j /= 10, i++); + + // Overflow? + if ((e = i + e * LOG_BASE - 1) > MAX_EXP) { + + // Infinity. + n.c = n.e = null; + + // Underflow? + } else if (e < MIN_EXP) { + + // Zero. + n.c = [n.e = 0]; + } else { + n.e = e; + n.c = c; + } + + return n; + } + + + // Handle values that fail the validity test in BigNumber. + parseNumeric = (function () { + var basePrefix = /^(-?)0([xbo])(?=\w[\w.]*$)/i, + dotAfter = /^([^.]+)\.$/, + dotBefore = /^\.([^.]+)$/, + isInfinityOrNaN = /^-?(Infinity|NaN)$/, + whitespaceOrPlus = /^\s*\+(?=[\w.])|^\s+|\s+$/g; + + return function (x, str, isNum, b) { + var base, + s = isNum ? str : str.replace(whitespaceOrPlus, ''); + + // No exception on ±Infinity or NaN. + if (isInfinityOrNaN.test(s)) { + x.s = isNaN(s) ? null : s < 0 ? -1 : 1; + } else { + if (!isNum) { + + // basePrefix = /^(-?)0([xbo])(?=\w[\w.]*$)/i + s = s.replace(basePrefix, function (m, p1, p2) { + base = (p2 = p2.toLowerCase()) == 'x' ? 16 : p2 == 'b' ? 2 : 8; + return !b || b == base ? p1 : m; + }); + + if (b) { + base = b; + + // E.g. '1.' to '1', '.1' to '0.1' + s = s.replace(dotAfter, '$1').replace(dotBefore, '0.$1'); + } + + if (str != s) return new BigNumber(s, base); + } + + // '[BigNumber Error] Not a number: {n}' + // '[BigNumber Error] Not a base {b} number: {n}' + if (BigNumber.DEBUG) { + throw Error + (bignumberError + 'Not a' + (b ? ' base ' + b : '') + ' number: ' + str); + } + + // NaN + x.s = null; + } + + x.c = x.e = null; + } + })(); + + + /* + * Round x to sd significant digits using rounding mode rm. Check for over/under-flow. + * If r is truthy, it is known that there are more digits after the rounding digit. + */ + function round(x, sd, rm, r) { + var d, i, j, k, n, ni, rd, + xc = x.c, + pows10 = POWS_TEN; + + // if x is not Infinity or NaN... + if (xc) { + + // rd is the rounding digit, i.e. the digit after the digit that may be rounded up. + // n is a base 1e14 number, the value of the element of array x.c containing rd. + // ni is the index of n within x.c. + // d is the number of digits of n. + // i is the index of rd within n including leading zeros. + // j is the actual index of rd within n (if < 0, rd is a leading zero). + out: { + + // Get the number of digits of the first element of xc. + for (d = 1, k = xc[0]; k >= 10; k /= 10, d++); + i = sd - d; + + // If the rounding digit is in the first element of xc... + if (i < 0) { + i += LOG_BASE; + j = sd; + n = xc[ni = 0]; + + // Get the rounding digit at index j of n. + rd = mathfloor(n / pows10[d - j - 1] % 10); + } else { + ni = mathceil((i + 1) / LOG_BASE); + + if (ni >= xc.length) { + + if (r) { + + // Needed by sqrt. + for (; xc.length <= ni; xc.push(0)); + n = rd = 0; + d = 1; + i %= LOG_BASE; + j = i - LOG_BASE + 1; + } else { + break out; + } + } else { + n = k = xc[ni]; + + // Get the number of digits of n. + for (d = 1; k >= 10; k /= 10, d++); + + // Get the index of rd within n. + i %= LOG_BASE; + + // Get the index of rd within n, adjusted for leading zeros. + // The number of leading zeros of n is given by LOG_BASE - d. + j = i - LOG_BASE + d; + + // Get the rounding digit at index j of n. + rd = j < 0 ? 0 : mathfloor(n / pows10[d - j - 1] % 10); + } + } + + r = r || sd < 0 || + + // Are there any non-zero digits after the rounding digit? + // The expression n % pows10[d - j - 1] returns all digits of n to the right + // of the digit at j, e.g. if n is 908714 and j is 2, the expression gives 714. + xc[ni + 1] != null || (j < 0 ? n : n % pows10[d - j - 1]); + + r = rm < 4 + ? (rd || r) && (rm == 0 || rm == (x.s < 0 ? 3 : 2)) + : rd > 5 || rd == 5 && (rm == 4 || r || rm == 6 && + + // Check whether the digit to the left of the rounding digit is odd. + ((i > 0 ? j > 0 ? n / pows10[d - j] : 0 : xc[ni - 1]) % 10) & 1 || + rm == (x.s < 0 ? 8 : 7)); + + if (sd < 1 || !xc[0]) { + xc.length = 0; + + if (r) { + + // Convert sd to decimal places. + sd -= x.e + 1; + + // 1, 0.1, 0.01, 0.001, 0.0001 etc. + xc[0] = pows10[(LOG_BASE - sd % LOG_BASE) % LOG_BASE]; + x.e = -sd || 0; + } else { + + // Zero. + xc[0] = x.e = 0; + } + + return x; + } + + // Remove excess digits. + if (i == 0) { + xc.length = ni; + k = 1; + ni--; + } else { + xc.length = ni + 1; + k = pows10[LOG_BASE - i]; + + // E.g. 56700 becomes 56000 if 7 is the rounding digit. + // j > 0 means i > number of leading zeros of n. + xc[ni] = j > 0 ? mathfloor(n / pows10[d - j] % pows10[j]) * k : 0; + } + + // Round up? + if (r) { + + for (; ;) { + + // If the digit to be rounded up is in the first element of xc... + if (ni == 0) { + + // i will be the length of xc[0] before k is added. + for (i = 1, j = xc[0]; j >= 10; j /= 10, i++); + j = xc[0] += k; + for (k = 1; j >= 10; j /= 10, k++); + + // if i != k the length has increased. + if (i != k) { + x.e++; + if (xc[0] == BASE) xc[0] = 1; + } + + break; + } else { + xc[ni] += k; + if (xc[ni] != BASE) break; + xc[ni--] = 0; + k = 1; + } + } + } + + // Remove trailing zeros. + for (i = xc.length; xc[--i] === 0; xc.pop()); + } + + // Overflow? Infinity. + if (x.e > MAX_EXP) { + x.c = x.e = null; + + // Underflow? Zero. + } else if (x.e < MIN_EXP) { + x.c = [x.e = 0]; + } + } + + return x; + } + + + function valueOf(n) { + var str, + e = n.e; + + if (e === null) return n.toString(); + + str = coeffToString(n.c); + + str = e <= TO_EXP_NEG || e >= TO_EXP_POS + ? toExponential(str, e) + : toFixedPoint(str, e, '0'); + + return n.s < 0 ? '-' + str : str; + } + + + // PROTOTYPE/INSTANCE METHODS + + + /* + * Return a new BigNumber whose value is the absolute value of this BigNumber. + */ + P.absoluteValue = P.abs = function () { + var x = new BigNumber(this); + if (x.s < 0) x.s = 1; + return x; + }; + + + /* + * Return + * 1 if the value of this BigNumber is greater than the value of BigNumber(y, b), + * -1 if the value of this BigNumber is less than the value of BigNumber(y, b), + * 0 if they have the same value, + * or null if the value of either is NaN. + */ + P.comparedTo = function (y, b) { + return compare(this, new BigNumber(y, b)); + }; + + + /* + * If dp is undefined or null or true or false, return the number of decimal places of the + * value of this BigNumber, or null if the value of this BigNumber is ±Infinity or NaN. + * + * Otherwise, if dp is a number, return a new BigNumber whose value is the value of this + * BigNumber rounded to a maximum of dp decimal places using rounding mode rm, or + * ROUNDING_MODE if rm is omitted. + * + * [dp] {number} Decimal places: integer, 0 to MAX inclusive. + * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive. + * + * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {dp|rm}' + */ + P.decimalPlaces = P.dp = function (dp, rm) { + var c, n, v, + x = this; + + if (dp != null) { + intCheck(dp, 0, MAX); + if (rm == null) rm = ROUNDING_MODE; + else intCheck(rm, 0, 8); + + return round(new BigNumber(x), dp + x.e + 1, rm); + } + + if (!(c = x.c)) return null; + n = ((v = c.length - 1) - bitFloor(this.e / LOG_BASE)) * LOG_BASE; + + // Subtract the number of trailing zeros of the last number. + if (v = c[v]) for (; v % 10 == 0; v /= 10, n--); + if (n < 0) n = 0; + + return n; + }; + + + /* + * n / 0 = I + * n / N = N + * n / I = 0 + * 0 / n = 0 + * 0 / 0 = N + * 0 / N = N + * 0 / I = 0 + * N / n = N + * N / 0 = N + * N / N = N + * N / I = N + * I / n = I + * I / 0 = I + * I / N = N + * I / I = N + * + * Return a new BigNumber whose value is the value of this BigNumber divided by the value of + * BigNumber(y, b), rounded according to DECIMAL_PLACES and ROUNDING_MODE. + */ + P.dividedBy = P.div = function (y, b) { + return div(this, new BigNumber(y, b), DECIMAL_PLACES, ROUNDING_MODE); + }; + + + /* + * Return a new BigNumber whose value is the integer part of dividing the value of this + * BigNumber by the value of BigNumber(y, b). + */ + P.dividedToIntegerBy = P.idiv = function (y, b) { + return div(this, new BigNumber(y, b), 0, 1); + }; + + + /* + * Return a BigNumber whose value is the value of this BigNumber exponentiated by n. + * + * If m is present, return the result modulo m. + * If n is negative round according to DECIMAL_PLACES and ROUNDING_MODE. + * If POW_PRECISION is non-zero and m is not present, round to POW_PRECISION using ROUNDING_MODE. + * + * The modular power operation works efficiently when x, n, and m are integers, otherwise it + * is equivalent to calculating x.exponentiatedBy(n).modulo(m) with a POW_PRECISION of 0. + * + * n {number|string|BigNumber} The exponent. An integer. + * [m] {number|string|BigNumber} The modulus. + * + * '[BigNumber Error] Exponent not an integer: {n}' + */ + P.exponentiatedBy = P.pow = function (n, m) { + var half, isModExp, i, k, more, nIsBig, nIsNeg, nIsOdd, y, + x = this; + + n = new BigNumber(n); + + // Allow NaN and ±Infinity, but not other non-integers. + if (n.c && !n.isInteger()) { + throw Error + (bignumberError + 'Exponent not an integer: ' + valueOf(n)); + } + + if (m != null) m = new BigNumber(m); + + // Exponent of MAX_SAFE_INTEGER is 15. + nIsBig = n.e > 14; + + // If x is NaN, ±Infinity, ±0 or ±1, or n is ±Infinity, NaN or ±0. + if (!x.c || !x.c[0] || x.c[0] == 1 && !x.e && x.c.length == 1 || !n.c || !n.c[0]) { + + // The sign of the result of pow when x is negative depends on the evenness of n. + // If +n overflows to ±Infinity, the evenness of n would be not be known. + y = new BigNumber(Math.pow(+valueOf(x), nIsBig ? n.s * (2 - isOdd(n)) : +valueOf(n))); + return m ? y.mod(m) : y; + } + + nIsNeg = n.s < 0; + + if (m) { + + // x % m returns NaN if abs(m) is zero, or m is NaN. + if (m.c ? !m.c[0] : !m.s) return new BigNumber(NaN); + + isModExp = !nIsNeg && x.isInteger() && m.isInteger(); + + if (isModExp) x = x.mod(m); + + // Overflow to ±Infinity: >=2**1e10 or >=1.0000024**1e15. + // Underflow to ±0: <=0.79**1e10 or <=0.9999975**1e15. + } else if (n.e > 9 && (x.e > 0 || x.e < -1 || (x.e == 0 + // [1, 240000000] + ? x.c[0] > 1 || nIsBig && x.c[1] >= 24e7 + // [80000000000000] [99999750000000] + : x.c[0] < 8e13 || nIsBig && x.c[0] <= 9999975e7))) { + + // If x is negative and n is odd, k = -0, else k = 0. + k = x.s < 0 && isOdd(n) ? -0 : 0; + + // If x >= 1, k = ±Infinity. + if (x.e > -1) k = 1 / k; + + // If n is negative return ±0, else return ±Infinity. + return new BigNumber(nIsNeg ? 1 / k : k); + + } else if (POW_PRECISION) { + + // Truncating each coefficient array to a length of k after each multiplication + // equates to truncating significant digits to POW_PRECISION + [28, 41], + // i.e. there will be a minimum of 28 guard digits retained. + k = mathceil(POW_PRECISION / LOG_BASE + 2); + } + + if (nIsBig) { + half = new BigNumber(0.5); + if (nIsNeg) n.s = 1; + nIsOdd = isOdd(n); + } else { + i = Math.abs(+valueOf(n)); + nIsOdd = i % 2; + } + + y = new BigNumber(ONE); + + // Performs 54 loop iterations for n of 9007199254740991. + for (; ;) { + + if (nIsOdd) { + y = y.times(x); + if (!y.c) break; + + if (k) { + if (y.c.length > k) y.c.length = k; + } else if (isModExp) { + y = y.mod(m); //y = y.minus(div(y, m, 0, MODULO_MODE).times(m)); + } + } + + if (i) { + i = mathfloor(i / 2); + if (i === 0) break; + nIsOdd = i % 2; + } else { + n = n.times(half); + round(n, n.e + 1, 1); + + if (n.e > 14) { + nIsOdd = isOdd(n); + } else { + i = +valueOf(n); + if (i === 0) break; + nIsOdd = i % 2; + } + } + + x = x.times(x); + + if (k) { + if (x.c && x.c.length > k) x.c.length = k; + } else if (isModExp) { + x = x.mod(m); //x = x.minus(div(x, m, 0, MODULO_MODE).times(m)); + } + } + + if (isModExp) return y; + if (nIsNeg) y = ONE.div(y); + + return m ? y.mod(m) : k ? round(y, POW_PRECISION, ROUNDING_MODE, more) : y; + }; + + + /* + * Return a new BigNumber whose value is the value of this BigNumber rounded to an integer + * using rounding mode rm, or ROUNDING_MODE if rm is omitted. + * + * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive. + * + * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {rm}' + */ + P.integerValue = function (rm) { + var n = new BigNumber(this); + if (rm == null) rm = ROUNDING_MODE; + else intCheck(rm, 0, 8); + return round(n, n.e + 1, rm); + }; + + + /* + * Return true if the value of this BigNumber is equal to the value of BigNumber(y, b), + * otherwise return false. + */ + P.isEqualTo = P.eq = function (y, b) { + return compare(this, new BigNumber(y, b)) === 0; + }; + + + /* + * Return true if the value of this BigNumber is a finite number, otherwise return false. + */ + P.isFinite = function () { + return !!this.c; + }; + + + /* + * Return true if the value of this BigNumber is greater than the value of BigNumber(y, b), + * otherwise return false. + */ + P.isGreaterThan = P.gt = function (y, b) { + return compare(this, new BigNumber(y, b)) > 0; + }; + + + /* + * Return true if the value of this BigNumber is greater than or equal to the value of + * BigNumber(y, b), otherwise return false. + */ + P.isGreaterThanOrEqualTo = P.gte = function (y, b) { + return (b = compare(this, new BigNumber(y, b))) === 1 || b === 0; + + }; + + + /* + * Return true if the value of this BigNumber is an integer, otherwise return false. + */ + P.isInteger = function () { + return !!this.c && bitFloor(this.e / LOG_BASE) > this.c.length - 2; + }; + + + /* + * Return true if the value of this BigNumber is less than the value of BigNumber(y, b), + * otherwise return false. + */ + P.isLessThan = P.lt = function (y, b) { + return compare(this, new BigNumber(y, b)) < 0; + }; + + + /* + * Return true if the value of this BigNumber is less than or equal to the value of + * BigNumber(y, b), otherwise return false. + */ + P.isLessThanOrEqualTo = P.lte = function (y, b) { + return (b = compare(this, new BigNumber(y, b))) === -1 || b === 0; + }; + + + /* + * Return true if the value of this BigNumber is NaN, otherwise return false. + */ + P.isNaN = function () { + return !this.s; + }; + + + /* + * Return true if the value of this BigNumber is negative, otherwise return false. + */ + P.isNegative = function () { + return this.s < 0; + }; + + + /* + * Return true if the value of this BigNumber is positive, otherwise return false. + */ + P.isPositive = function () { + return this.s > 0; + }; + + + /* + * Return true if the value of this BigNumber is 0 or -0, otherwise return false. + */ + P.isZero = function () { + return !!this.c && this.c[0] == 0; + }; + + + /* + * n - 0 = n + * n - N = N + * n - I = -I + * 0 - n = -n + * 0 - 0 = 0 + * 0 - N = N + * 0 - I = -I + * N - n = N + * N - 0 = N + * N - N = N + * N - I = N + * I - n = I + * I - 0 = I + * I - N = N + * I - I = N + * + * Return a new BigNumber whose value is the value of this BigNumber minus the value of + * BigNumber(y, b). + */ + P.minus = function (y, b) { + var i, j, t, xLTy, + x = this, + a = x.s; + + y = new BigNumber(y, b); + b = y.s; + + // Either NaN? + if (!a || !b) return new BigNumber(NaN); + + // Signs differ? + if (a != b) { + y.s = -b; + return x.plus(y); + } + + var xe = x.e / LOG_BASE, + ye = y.e / LOG_BASE, + xc = x.c, + yc = y.c; + + if (!xe || !ye) { + + // Either Infinity? + if (!xc || !yc) return xc ? (y.s = -b, y) : new BigNumber(yc ? x : NaN); + + // Either zero? + if (!xc[0] || !yc[0]) { + + // Return y if y is non-zero, x if x is non-zero, or zero if both are zero. + return yc[0] ? (y.s = -b, y) : new BigNumber(xc[0] ? x : + + // IEEE 754 (2008) 6.3: n - n = -0 when rounding to -Infinity + ROUNDING_MODE == 3 ? -0 : 0); + } + } + + xe = bitFloor(xe); + ye = bitFloor(ye); + xc = xc.slice(); + + // Determine which is the bigger number. + if (a = xe - ye) { + + if (xLTy = a < 0) { + a = -a; + t = xc; + } else { + ye = xe; + t = yc; + } + + t.reverse(); + + // Prepend zeros to equalise exponents. + for (b = a; b--; t.push(0)); + t.reverse(); + } else { + + // Exponents equal. Check digit by digit. + j = (xLTy = (a = xc.length) < (b = yc.length)) ? a : b; + + for (a = b = 0; b < j; b++) { + + if (xc[b] != yc[b]) { + xLTy = xc[b] < yc[b]; + break; + } + } + } + + // x < y? Point xc to the array of the bigger number. + if (xLTy) { + t = xc; + xc = yc; + yc = t; + y.s = -y.s; + } + + b = (j = yc.length) - (i = xc.length); + + // Append zeros to xc if shorter. + // No need to add zeros to yc if shorter as subtract only needs to start at yc.length. + if (b > 0) for (; b--; xc[i++] = 0); + b = BASE - 1; + + // Subtract yc from xc. + for (; j > a;) { + + if (xc[--j] < yc[j]) { + for (i = j; i && !xc[--i]; xc[i] = b); + --xc[i]; + xc[j] += BASE; + } + + xc[j] -= yc[j]; + } + + // Remove leading zeros and adjust exponent accordingly. + for (; xc[0] == 0; xc.splice(0, 1), --ye); + + // Zero? + if (!xc[0]) { + + // Following IEEE 754 (2008) 6.3, + // n - n = +0 but n - n = -0 when rounding towards -Infinity. + y.s = ROUNDING_MODE == 3 ? -1 : 1; + y.c = [y.e = 0]; + return y; + } + + // No need to check for Infinity as +x - +y != Infinity && -x - -y != Infinity + // for finite x and y. + return normalise(y, xc, ye); + }; + + + /* + * n % 0 = N + * n % N = N + * n % I = n + * 0 % n = 0 + * -0 % n = -0 + * 0 % 0 = N + * 0 % N = N + * 0 % I = 0 + * N % n = N + * N % 0 = N + * N % N = N + * N % I = N + * I % n = N + * I % 0 = N + * I % N = N + * I % I = N + * + * Return a new BigNumber whose value is the value of this BigNumber modulo the value of + * BigNumber(y, b). The result depends on the value of MODULO_MODE. + */ + P.modulo = P.mod = function (y, b) { + var q, s, + x = this; + + y = new BigNumber(y, b); + + // Return NaN if x is Infinity or NaN, or y is NaN or zero. + if (!x.c || !y.s || y.c && !y.c[0]) { + return new BigNumber(NaN); + + // Return x if y is Infinity or x is zero. + } else if (!y.c || x.c && !x.c[0]) { + return new BigNumber(x); + } + + if (MODULO_MODE == 9) { + + // Euclidian division: q = sign(y) * floor(x / abs(y)) + // r = x - qy where 0 <= r < abs(y) + s = y.s; + y.s = 1; + q = div(x, y, 0, 3); + y.s = s; + q.s *= s; + } else { + q = div(x, y, 0, MODULO_MODE); + } + + y = x.minus(q.times(y)); + + // To match JavaScript %, ensure sign of zero is sign of dividend. + if (!y.c[0] && MODULO_MODE == 1) y.s = x.s; + + return y; + }; + + + /* + * n * 0 = 0 + * n * N = N + * n * I = I + * 0 * n = 0 + * 0 * 0 = 0 + * 0 * N = N + * 0 * I = N + * N * n = N + * N * 0 = N + * N * N = N + * N * I = N + * I * n = I + * I * 0 = N + * I * N = N + * I * I = I + * + * Return a new BigNumber whose value is the value of this BigNumber multiplied by the value + * of BigNumber(y, b). + */ + P.multipliedBy = P.times = function (y, b) { + var c, e, i, j, k, m, xcL, xlo, xhi, ycL, ylo, yhi, zc, + base, sqrtBase, + x = this, + xc = x.c, + yc = (y = new BigNumber(y, b)).c; + + // Either NaN, ±Infinity or ±0? + if (!xc || !yc || !xc[0] || !yc[0]) { + + // Return NaN if either is NaN, or one is 0 and the other is Infinity. + if (!x.s || !y.s || xc && !xc[0] && !yc || yc && !yc[0] && !xc) { + y.c = y.e = y.s = null; + } else { + y.s *= x.s; + + // Return ±Infinity if either is ±Infinity. + if (!xc || !yc) { + y.c = y.e = null; + + // Return ±0 if either is ±0. + } else { + y.c = [0]; + y.e = 0; + } + } + + return y; + } + + e = bitFloor(x.e / LOG_BASE) + bitFloor(y.e / LOG_BASE); + y.s *= x.s; + xcL = xc.length; + ycL = yc.length; + + // Ensure xc points to longer array and xcL to its length. + if (xcL < ycL) { + zc = xc; + xc = yc; + yc = zc; + i = xcL; + xcL = ycL; + ycL = i; + } + + // Initialise the result array with zeros. + for (i = xcL + ycL, zc = []; i--; zc.push(0)); + + base = BASE; + sqrtBase = SQRT_BASE; + + for (i = ycL; --i >= 0;) { + c = 0; + ylo = yc[i] % sqrtBase; + yhi = yc[i] / sqrtBase | 0; + + for (k = xcL, j = i + k; j > i;) { + xlo = xc[--k] % sqrtBase; + xhi = xc[k] / sqrtBase | 0; + m = yhi * xlo + xhi * ylo; + xlo = ylo * xlo + ((m % sqrtBase) * sqrtBase) + zc[j] + c; + c = (xlo / base | 0) + (m / sqrtBase | 0) + yhi * xhi; + zc[j--] = xlo % base; + } + + zc[j] = c; + } + + if (c) { + ++e; + } else { + zc.splice(0, 1); + } + + return normalise(y, zc, e); + }; + + + /* + * Return a new BigNumber whose value is the value of this BigNumber negated, + * i.e. multiplied by -1. + */ + P.negated = function () { + var x = new BigNumber(this); + x.s = -x.s || null; + return x; + }; + + + /* + * n + 0 = n + * n + N = N + * n + I = I + * 0 + n = n + * 0 + 0 = 0 + * 0 + N = N + * 0 + I = I + * N + n = N + * N + 0 = N + * N + N = N + * N + I = N + * I + n = I + * I + 0 = I + * I + N = N + * I + I = I + * + * Return a new BigNumber whose value is the value of this BigNumber plus the value of + * BigNumber(y, b). + */ + P.plus = function (y, b) { + var t, + x = this, + a = x.s; + + y = new BigNumber(y, b); + b = y.s; + + // Either NaN? + if (!a || !b) return new BigNumber(NaN); + + // Signs differ? + if (a != b) { + y.s = -b; + return x.minus(y); + } + + var xe = x.e / LOG_BASE, + ye = y.e / LOG_BASE, + xc = x.c, + yc = y.c; + + if (!xe || !ye) { + + // Return ±Infinity if either ±Infinity. + if (!xc || !yc) return new BigNumber(a / 0); + + // Either zero? + // Return y if y is non-zero, x if x is non-zero, or zero if both are zero. + if (!xc[0] || !yc[0]) return yc[0] ? y : new BigNumber(xc[0] ? x : a * 0); + } + + xe = bitFloor(xe); + ye = bitFloor(ye); + xc = xc.slice(); + + // Prepend zeros to equalise exponents. Faster to use reverse then do unshifts. + if (a = xe - ye) { + if (a > 0) { + ye = xe; + t = yc; + } else { + a = -a; + t = xc; + } + + t.reverse(); + for (; a--; t.push(0)); + t.reverse(); + } + + a = xc.length; + b = yc.length; + + // Point xc to the longer array, and b to the shorter length. + if (a - b < 0) { + t = yc; + yc = xc; + xc = t; + b = a; + } + + // Only start adding at yc.length - 1 as the further digits of xc can be ignored. + for (a = 0; b;) { + a = (xc[--b] = xc[b] + yc[b] + a) / BASE | 0; + xc[b] = BASE === xc[b] ? 0 : xc[b] % BASE; + } + + if (a) { + xc = [a].concat(xc); + ++ye; + } + + // No need to check for zero, as +x + +y != 0 && -x + -y != 0 + // ye = MAX_EXP + 1 possible + return normalise(y, xc, ye); + }; + + + /* + * If sd is undefined or null or true or false, return the number of significant digits of + * the value of this BigNumber, or null if the value of this BigNumber is ±Infinity or NaN. + * If sd is true include integer-part trailing zeros in the count. + * + * Otherwise, if sd is a number, return a new BigNumber whose value is the value of this + * BigNumber rounded to a maximum of sd significant digits using rounding mode rm, or + * ROUNDING_MODE if rm is omitted. + * + * sd {number|boolean} number: significant digits: integer, 1 to MAX inclusive. + * boolean: whether to count integer-part trailing zeros: true or false. + * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive. + * + * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {sd|rm}' + */ + P.precision = P.sd = function (sd, rm) { + var c, n, v, + x = this; + + if (sd != null && sd !== !!sd) { + intCheck(sd, 1, MAX); + if (rm == null) rm = ROUNDING_MODE; + else intCheck(rm, 0, 8); + + return round(new BigNumber(x), sd, rm); + } + + if (!(c = x.c)) return null; + v = c.length - 1; + n = v * LOG_BASE + 1; + + if (v = c[v]) { + + // Subtract the number of trailing zeros of the last element. + for (; v % 10 == 0; v /= 10, n--); + + // Add the number of digits of the first element. + for (v = c[0]; v >= 10; v /= 10, n++); + } + + if (sd && x.e + 1 > n) n = x.e + 1; + + return n; + }; + + + /* + * Return a new BigNumber whose value is the value of this BigNumber shifted by k places + * (powers of 10). Shift to the right if n > 0, and to the left if n < 0. + * + * k {number} Integer, -MAX_SAFE_INTEGER to MAX_SAFE_INTEGER inclusive. + * + * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {k}' + */ + P.shiftedBy = function (k) { + intCheck(k, -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER); + return this.times('1e' + k); + }; + + + /* + * sqrt(-n) = N + * sqrt(N) = N + * sqrt(-I) = N + * sqrt(I) = I + * sqrt(0) = 0 + * sqrt(-0) = -0 + * + * Return a new BigNumber whose value is the square root of the value of this BigNumber, + * rounded according to DECIMAL_PLACES and ROUNDING_MODE. + */ + P.squareRoot = P.sqrt = function () { + var m, n, r, rep, t, + x = this, + c = x.c, + s = x.s, + e = x.e, + dp = DECIMAL_PLACES + 4, + half = new BigNumber('0.5'); + + // Negative/NaN/Infinity/zero? + if (s !== 1 || !c || !c[0]) { + return new BigNumber(!s || s < 0 && (!c || c[0]) ? NaN : c ? x : 1 / 0); + } + + // Initial estimate. + s = Math.sqrt(+valueOf(x)); + + // Math.sqrt underflow/overflow? + // Pass x to Math.sqrt as integer, then adjust the exponent of the result. + if (s == 0 || s == 1 / 0) { + n = coeffToString(c); + if ((n.length + e) % 2 == 0) n += '0'; + s = Math.sqrt(+n); + e = bitFloor((e + 1) / 2) - (e < 0 || e % 2); + + if (s == 1 / 0) { + n = '5e' + e; + } else { + n = s.toExponential(); + n = n.slice(0, n.indexOf('e') + 1) + e; + } + + r = new BigNumber(n); + } else { + r = new BigNumber(s + ''); + } + + // Check for zero. + // r could be zero if MIN_EXP is changed after the this value was created. + // This would cause a division by zero (x/t) and hence Infinity below, which would cause + // coeffToString to throw. + if (r.c[0]) { + e = r.e; + s = e + dp; + if (s < 3) s = 0; + + // Newton-Raphson iteration. + for (; ;) { + t = r; + r = half.times(t.plus(div(x, t, dp, 1))); + + if (coeffToString(t.c).slice(0, s) === (n = coeffToString(r.c)).slice(0, s)) { + + // The exponent of r may here be one less than the final result exponent, + // e.g 0.0009999 (e-4) --> 0.001 (e-3), so adjust s so the rounding digits + // are indexed correctly. + if (r.e < e) --s; + n = n.slice(s - 3, s + 1); + + // The 4th rounding digit may be in error by -1 so if the 4 rounding digits + // are 9999 or 4999 (i.e. approaching a rounding boundary) continue the + // iteration. + if (n == '9999' || !rep && n == '4999') { + + // On the first iteration only, check to see if rounding up gives the + // exact result as the nines may infinitely repeat. + if (!rep) { + round(t, t.e + DECIMAL_PLACES + 2, 0); + + if (t.times(t).eq(x)) { + r = t; + break; + } + } + + dp += 4; + s += 4; + rep = 1; + } else { + + // If rounding digits are null, 0{0,4} or 50{0,3}, check for exact + // result. If not, then there are further digits and m will be truthy. + if (!+n || !+n.slice(1) && n.charAt(0) == '5') { + + // Truncate to the first rounding digit. + round(r, r.e + DECIMAL_PLACES + 2, 1); + m = !r.times(r).eq(x); + } + + break; + } + } + } + } + + return round(r, r.e + DECIMAL_PLACES + 1, ROUNDING_MODE, m); + }; + + + /* + * Return a string representing the value of this BigNumber in exponential notation and + * rounded using ROUNDING_MODE to dp fixed decimal places. + * + * [dp] {number} Decimal places. Integer, 0 to MAX inclusive. + * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive. + * + * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {dp|rm}' + */ + P.toExponential = function (dp, rm) { + if (dp != null) { + intCheck(dp, 0, MAX); + dp++; + } + return format(this, dp, rm, 1); + }; + + + /* + * Return a string representing the value of this BigNumber in fixed-point notation rounding + * to dp fixed decimal places using rounding mode rm, or ROUNDING_MODE if rm is omitted. + * + * Note: as with JavaScript's number type, (-0).toFixed(0) is '0', + * but e.g. (-0.00001).toFixed(0) is '-0'. + * + * [dp] {number} Decimal places. Integer, 0 to MAX inclusive. + * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive. + * + * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {dp|rm}' + */ + P.toFixed = function (dp, rm) { + if (dp != null) { + intCheck(dp, 0, MAX); + dp = dp + this.e + 1; + } + return format(this, dp, rm); + }; + + + /* + * Return a string representing the value of this BigNumber in fixed-point notation rounded + * using rm or ROUNDING_MODE to dp decimal places, and formatted according to the properties + * of the format or FORMAT object (see BigNumber.set). + * + * The formatting object may contain some or all of the properties shown below. + * + * FORMAT = { + * prefix: '', + * groupSize: 3, + * secondaryGroupSize: 0, + * groupSeparator: ',', + * decimalSeparator: '.', + * fractionGroupSize: 0, + * fractionGroupSeparator: '\xA0', // non-breaking space + * suffix: '' + * }; + * + * [dp] {number} Decimal places. Integer, 0 to MAX inclusive. + * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive. + * [format] {object} Formatting options. See FORMAT pbject above. + * + * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {dp|rm}' + * '[BigNumber Error] Argument not an object: {format}' + */ + P.toFormat = function (dp, rm, format) { + var str, + x = this; + + if (format == null) { + if (dp != null && rm && typeof rm == 'object') { + format = rm; + rm = null; + } else if (dp && typeof dp == 'object') { + format = dp; + dp = rm = null; + } else { + format = FORMAT; + } + } else if (typeof format != 'object') { + throw Error + (bignumberError + 'Argument not an object: ' + format); + } + + str = x.toFixed(dp, rm); + + if (x.c) { + var i, + arr = str.split('.'), + g1 = +format.groupSize, + g2 = +format.secondaryGroupSize, + groupSeparator = format.groupSeparator || '', + intPart = arr[0], + fractionPart = arr[1], + isNeg = x.s < 0, + intDigits = isNeg ? intPart.slice(1) : intPart, + len = intDigits.length; + + if (g2) { + i = g1; + g1 = g2; + g2 = i; + len -= i; + } + + if (g1 > 0 && len > 0) { + i = len % g1 || g1; + intPart = intDigits.substr(0, i); + for (; i < len; i += g1) intPart += groupSeparator + intDigits.substr(i, g1); + if (g2 > 0) intPart += groupSeparator + intDigits.slice(i); + if (isNeg) intPart = '-' + intPart; + } + + str = fractionPart + ? intPart + (format.decimalSeparator || '') + ((g2 = +format.fractionGroupSize) + ? fractionPart.replace(new RegExp('\\d{' + g2 + '}\\B', 'g'), + '$&' + (format.fractionGroupSeparator || '')) + : fractionPart) + : intPart; + } + + return (format.prefix || '') + str + (format.suffix || ''); + }; + + + /* + * Return an array of two BigNumbers representing the value of this BigNumber as a simple + * fraction with an integer numerator and an integer denominator. + * The denominator will be a positive non-zero value less than or equal to the specified + * maximum denominator. If a maximum denominator is not specified, the denominator will be + * the lowest value necessary to represent the number exactly. + * + * [md] {number|string|BigNumber} Integer >= 1, or Infinity. The maximum denominator. + * + * '[BigNumber Error] Argument {not an integer|out of range} : {md}' + */ + P.toFraction = function (md) { + var d, d0, d1, d2, e, exp, n, n0, n1, q, r, s, + x = this, + xc = x.c; + + if (md != null) { + n = new BigNumber(md); + + // Throw if md is less than one or is not an integer, unless it is Infinity. + if (!n.isInteger() && (n.c || n.s !== 1) || n.lt(ONE)) { + throw Error + (bignumberError + 'Argument ' + + (n.isInteger() ? 'out of range: ' : 'not an integer: ') + valueOf(n)); + } + } + + if (!xc) return new BigNumber(x); + + d = new BigNumber(ONE); + n1 = d0 = new BigNumber(ONE); + d1 = n0 = new BigNumber(ONE); + s = coeffToString(xc); + + // Determine initial denominator. + // d is a power of 10 and the minimum max denominator that specifies the value exactly. + e = d.e = s.length - x.e - 1; + d.c[0] = POWS_TEN[(exp = e % LOG_BASE) < 0 ? LOG_BASE + exp : exp]; + md = !md || n.comparedTo(d) > 0 ? (e > 0 ? d : n1) : n; + + exp = MAX_EXP; + MAX_EXP = 1 / 0; + n = new BigNumber(s); + + // n0 = d1 = 0 + n0.c[0] = 0; + + for (; ;) { + q = div(n, d, 0, 1); + d2 = d0.plus(q.times(d1)); + if (d2.comparedTo(md) == 1) break; + d0 = d1; + d1 = d2; + n1 = n0.plus(q.times(d2 = n1)); + n0 = d2; + d = n.minus(q.times(d2 = d)); + n = d2; + } + + d2 = div(md.minus(d0), d1, 0, 1); + n0 = n0.plus(d2.times(n1)); + d0 = d0.plus(d2.times(d1)); + n0.s = n1.s = x.s; + e = e * 2; + + // Determine which fraction is closer to x, n0/d0 or n1/d1 + r = div(n1, d1, e, ROUNDING_MODE).minus(x).abs().comparedTo( + div(n0, d0, e, ROUNDING_MODE).minus(x).abs()) < 1 ? [n1, d1] : [n0, d0]; + + MAX_EXP = exp; + + return r; + }; + + + /* + * Return the value of this BigNumber converted to a number primitive. + */ + P.toNumber = function () { + return +valueOf(this); + }; + + + /* + * Return a string representing the value of this BigNumber rounded to sd significant digits + * using rounding mode rm or ROUNDING_MODE. If sd is less than the number of digits + * necessary to represent the integer part of the value in fixed-point notation, then use + * exponential notation. + * + * [sd] {number} Significant digits. Integer, 1 to MAX inclusive. + * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive. + * + * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {sd|rm}' + */ + P.toPrecision = function (sd, rm) { + if (sd != null) intCheck(sd, 1, MAX); + return format(this, sd, rm, 2); + }; + + + /* + * Return a string representing the value of this BigNumber in base b, or base 10 if b is + * omitted. If a base is specified, including base 10, round according to DECIMAL_PLACES and + * ROUNDING_MODE. If a base is not specified, and this BigNumber has a positive exponent + * that is equal to or greater than TO_EXP_POS, or a negative exponent equal to or less than + * TO_EXP_NEG, return exponential notation. + * + * [b] {number} Integer, 2 to ALPHABET.length inclusive. + * + * '[BigNumber Error] Base {not a primitive number|not an integer|out of range}: {b}' + */ + P.toString = function (b) { + var str, + n = this, + s = n.s, + e = n.e; + + // Infinity or NaN? + if (e === null) { + if (s) { + str = 'Infinity'; + if (s < 0) str = '-' + str; + } else { + str = 'NaN'; + } + } else { + if (b == null) { + str = e <= TO_EXP_NEG || e >= TO_EXP_POS + ? toExponential(coeffToString(n.c), e) + : toFixedPoint(coeffToString(n.c), e, '0'); + } else if (b === 10 && alphabetHasNormalDecimalDigits) { + n = round(new BigNumber(n), DECIMAL_PLACES + e + 1, ROUNDING_MODE); + str = toFixedPoint(coeffToString(n.c), n.e, '0'); + } else { + intCheck(b, 2, ALPHABET.length, 'Base'); + str = convertBase(toFixedPoint(coeffToString(n.c), e, '0'), 10, b, s, true); + } + + if (s < 0 && n.c[0]) str = '-' + str; + } + + return str; + }; + + + /* + * Return as toString, but do not accept a base argument, and include the minus sign for + * negative zero. + */ + P.valueOf = P.toJSON = function () { + return valueOf(this); + }; + + + P._isBigNumber = true; + + if (configObject != null) BigNumber.set(configObject); + + return BigNumber; + } + + + // PRIVATE HELPER FUNCTIONS + + // These functions don't need access to variables, + // e.g. DECIMAL_PLACES, in the scope of the `clone` function above. + + + function bitFloor(n) { + var i = n | 0; + return n > 0 || n === i ? i : i - 1; + } + + + // Return a coefficient array as a string of base 10 digits. + function coeffToString(a) { + var s, z, + i = 1, + j = a.length, + r = a[0] + ''; + + for (; i < j;) { + s = a[i++] + ''; + z = LOG_BASE - s.length; + for (; z--; s = '0' + s); + r += s; + } + + // Determine trailing zeros. + for (j = r.length; r.charCodeAt(--j) === 48;); + + return r.slice(0, j + 1 || 1); + } + + + // Compare the value of BigNumbers x and y. + function compare(x, y) { + var a, b, + xc = x.c, + yc = y.c, + i = x.s, + j = y.s, + k = x.e, + l = y.e; + + // Either NaN? + if (!i || !j) return null; + + a = xc && !xc[0]; + b = yc && !yc[0]; + + // Either zero? + if (a || b) return a ? b ? 0 : -j : i; + + // Signs differ? + if (i != j) return i; + + a = i < 0; + b = k == l; + + // Either Infinity? + if (!xc || !yc) return b ? 0 : !xc ^ a ? 1 : -1; + + // Compare exponents. + if (!b) return k > l ^ a ? 1 : -1; + + j = (k = xc.length) < (l = yc.length) ? k : l; + + // Compare digit by digit. + for (i = 0; i < j; i++) if (xc[i] != yc[i]) return xc[i] > yc[i] ^ a ? 1 : -1; + + // Compare lengths. + return k == l ? 0 : k > l ^ a ? 1 : -1; + } + + + /* + * Check that n is a primitive number, an integer, and in range, otherwise throw. + */ + function intCheck(n, min, max, name) { + if (n < min || n > max || n !== mathfloor(n)) { + throw Error + (bignumberError + (name || 'Argument') + (typeof n == 'number' + ? n < min || n > max ? ' out of range: ' : ' not an integer: ' + : ' not a primitive number: ') + String(n)); + } + } + + + // Assumes finite n. + function isOdd(n) { + var k = n.c.length - 1; + return bitFloor(n.e / LOG_BASE) == k && n.c[k] % 2 != 0; + } + + + function toExponential(str, e) { + return (str.length > 1 ? str.charAt(0) + '.' + str.slice(1) : str) + + (e < 0 ? 'e' : 'e+') + e; + } + + + function toFixedPoint(str, e, z) { + var len, zs; + + // Negative exponent? + if (e < 0) { + + // Prepend zeros. + for (zs = z + '.'; ++e; zs += z); + str = zs + str; + + // Positive exponent + } else { + len = str.length; + + // Append zeros. + if (++e > len) { + for (zs = z, e -= len; --e; zs += z); + str += zs; + } else if (e < len) { + str = str.slice(0, e) + '.' + str.slice(e); + } + } + + return str; + } + + + // EXPORT + + + BigNumber = clone(); + BigNumber['default'] = BigNumber.BigNumber = BigNumber; + + // AMD. + if (typeof define == 'function' && define.amd) { + define(function () { return BigNumber; }); + + // Node.js and other environments that support module.exports. + } else if (typeof module != 'undefined' && module.exports) { + module.exports = BigNumber; + + // Browser. + } else { + if (!globalObject) { + globalObject = typeof self != 'undefined' && self ? self : window; + } + + globalObject.BigNumber = BigNumber; + } +})(this); diff --git a/server/node_modules/bignumber.js/bignumber.mjs b/server/node_modules/bignumber.js/bignumber.mjs new file mode 100644 index 0000000..3e91894 --- /dev/null +++ b/server/node_modules/bignumber.js/bignumber.mjs @@ -0,0 +1,2907 @@ +/* + * bignumber.js v9.3.1 + * A JavaScript library for arbitrary-precision arithmetic. + * https://github.com/MikeMcl/bignumber.js + * Copyright (c) 2025 Michael Mclaughlin <M8ch88l@gmail.com> + * MIT Licensed. + * + * BigNumber.prototype methods | BigNumber methods + * | + * absoluteValue abs | clone + * comparedTo | config set + * decimalPlaces dp | DECIMAL_PLACES + * dividedBy div | ROUNDING_MODE + * dividedToIntegerBy idiv | EXPONENTIAL_AT + * exponentiatedBy pow | RANGE + * integerValue | CRYPTO + * isEqualTo eq | MODULO_MODE + * isFinite | POW_PRECISION + * isGreaterThan gt | FORMAT + * isGreaterThanOrEqualTo gte | ALPHABET + * isInteger | isBigNumber + * isLessThan lt | maximum max + * isLessThanOrEqualTo lte | minimum min + * isNaN | random + * isNegative | sum + * isPositive | + * isZero | + * minus | + * modulo mod | + * multipliedBy times | + * negated | + * plus | + * precision sd | + * shiftedBy | + * squareRoot sqrt | + * toExponential | + * toFixed | + * toFormat | + * toFraction | + * toJSON | + * toNumber | + * toPrecision | + * toString | + * valueOf | + * + */ + + +var + isNumeric = /^-?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?$/i, + mathceil = Math.ceil, + mathfloor = Math.floor, + + bignumberError = '[BigNumber Error] ', + tooManyDigits = bignumberError + 'Number primitive has more than 15 significant digits: ', + + BASE = 1e14, + LOG_BASE = 14, + MAX_SAFE_INTEGER = 0x1fffffffffffff, // 2^53 - 1 + // MAX_INT32 = 0x7fffffff, // 2^31 - 1 + POWS_TEN = [1, 10, 100, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13], + SQRT_BASE = 1e7, + + // EDITABLE + // The limit on the value of DECIMAL_PLACES, TO_EXP_NEG, TO_EXP_POS, MIN_EXP, MAX_EXP, and + // the arguments to toExponential, toFixed, toFormat, and toPrecision. + MAX = 1E9; // 0 to MAX_INT32 + + +/* + * Create and return a BigNumber constructor. + */ +function clone(configObject) { + var div, convertBase, parseNumeric, + P = BigNumber.prototype = { constructor: BigNumber, toString: null, valueOf: null }, + ONE = new BigNumber(1), + + + //----------------------------- EDITABLE CONFIG DEFAULTS ------------------------------- + + + // The default values below must be integers within the inclusive ranges stated. + // The values can also be changed at run-time using BigNumber.set. + + // The maximum number of decimal places for operations involving division. + DECIMAL_PLACES = 20, // 0 to MAX + + // The rounding mode used when rounding to the above decimal places, and when using + // toExponential, toFixed, toFormat and toPrecision, and round (default value). + // UP 0 Away from zero. + // DOWN 1 Towards zero. + // CEIL 2 Towards +Infinity. + // FLOOR 3 Towards -Infinity. + // HALF_UP 4 Towards nearest neighbour. If equidistant, up. + // HALF_DOWN 5 Towards nearest neighbour. If equidistant, down. + // HALF_EVEN 6 Towards nearest neighbour. If equidistant, towards even neighbour. + // HALF_CEIL 7 Towards nearest neighbour. If equidistant, towards +Infinity. + // HALF_FLOOR 8 Towards nearest neighbour. If equidistant, towards -Infinity. + ROUNDING_MODE = 4, // 0 to 8 + + // EXPONENTIAL_AT : [TO_EXP_NEG , TO_EXP_POS] + + // The exponent value at and beneath which toString returns exponential notation. + // Number type: -7 + TO_EXP_NEG = -7, // 0 to -MAX + + // The exponent value at and above which toString returns exponential notation. + // Number type: 21 + TO_EXP_POS = 21, // 0 to MAX + + // RANGE : [MIN_EXP, MAX_EXP] + + // The minimum exponent value, beneath which underflow to zero occurs. + // Number type: -324 (5e-324) + MIN_EXP = -1e7, // -1 to -MAX + + // The maximum exponent value, above which overflow to Infinity occurs. + // Number type: 308 (1.7976931348623157e+308) + // For MAX_EXP > 1e7, e.g. new BigNumber('1e100000000').plus(1) may be slow. + MAX_EXP = 1e7, // 1 to MAX + + // Whether to use cryptographically-secure random number generation, if available. + CRYPTO = false, // true or false + + // The modulo mode used when calculating the modulus: a mod n. + // The quotient (q = a / n) is calculated according to the corresponding rounding mode. + // The remainder (r) is calculated as: r = a - n * q. + // + // UP 0 The remainder is positive if the dividend is negative, else is negative. + // DOWN 1 The remainder has the same sign as the dividend. + // This modulo mode is commonly known as 'truncated division' and is + // equivalent to (a % n) in JavaScript. + // FLOOR 3 The remainder has the same sign as the divisor (Python %). + // HALF_EVEN 6 This modulo mode implements the IEEE 754 remainder function. + // EUCLID 9 Euclidian division. q = sign(n) * floor(a / abs(n)). + // The remainder is always positive. + // + // The truncated division, floored division, Euclidian division and IEEE 754 remainder + // modes are commonly used for the modulus operation. + // Although the other rounding modes can also be used, they may not give useful results. + MODULO_MODE = 1, // 0 to 9 + + // The maximum number of significant digits of the result of the exponentiatedBy operation. + // If POW_PRECISION is 0, there will be unlimited significant digits. + POW_PRECISION = 0, // 0 to MAX + + // The format specification used by the BigNumber.prototype.toFormat method. + FORMAT = { + prefix: '', + groupSize: 3, + secondaryGroupSize: 0, + groupSeparator: ',', + decimalSeparator: '.', + fractionGroupSize: 0, + fractionGroupSeparator: '\xA0', // non-breaking space + suffix: '' + }, + + // The alphabet used for base conversion. It must be at least 2 characters long, with no '+', + // '-', '.', whitespace, or repeated character. + // '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_' + ALPHABET = '0123456789abcdefghijklmnopqrstuvwxyz', + alphabetHasNormalDecimalDigits = true; + + + //------------------------------------------------------------------------------------------ + + + // CONSTRUCTOR + + + /* + * The BigNumber constructor and exported function. + * Create and return a new instance of a BigNumber object. + * + * v {number|string|BigNumber} A numeric value. + * [b] {number} The base of v. Integer, 2 to ALPHABET.length inclusive. + */ + function BigNumber(v, b) { + var alphabet, c, caseChanged, e, i, isNum, len, str, + x = this; + + // Enable constructor call without `new`. + if (!(x instanceof BigNumber)) return new BigNumber(v, b); + + if (b == null) { + + if (v && v._isBigNumber === true) { + x.s = v.s; + + if (!v.c || v.e > MAX_EXP) { + x.c = x.e = null; + } else if (v.e < MIN_EXP) { + x.c = [x.e = 0]; + } else { + x.e = v.e; + x.c = v.c.slice(); + } + + return; + } + + if ((isNum = typeof v == 'number') && v * 0 == 0) { + + // Use `1 / n` to handle minus zero also. + x.s = 1 / v < 0 ? (v = -v, -1) : 1; + + // Fast path for integers, where n < 2147483648 (2**31). + if (v === ~~v) { + for (e = 0, i = v; i >= 10; i /= 10, e++); + + if (e > MAX_EXP) { + x.c = x.e = null; + } else { + x.e = e; + x.c = [v]; + } + + return; + } + + str = String(v); + } else { + + if (!isNumeric.test(str = String(v))) return parseNumeric(x, str, isNum); + + x.s = str.charCodeAt(0) == 45 ? (str = str.slice(1), -1) : 1; + } + + // Decimal point? + if ((e = str.indexOf('.')) > -1) str = str.replace('.', ''); + + // Exponential form? + if ((i = str.search(/e/i)) > 0) { + + // Determine exponent. + if (e < 0) e = i; + e += +str.slice(i + 1); + str = str.substring(0, i); + } else if (e < 0) { + + // Integer. + e = str.length; + } + + } else { + + // '[BigNumber Error] Base {not a primitive number|not an integer|out of range}: {b}' + intCheck(b, 2, ALPHABET.length, 'Base'); + + // Allow exponential notation to be used with base 10 argument, while + // also rounding to DECIMAL_PLACES as with other bases. + if (b == 10 && alphabetHasNormalDecimalDigits) { + x = new BigNumber(v); + return round(x, DECIMAL_PLACES + x.e + 1, ROUNDING_MODE); + } + + str = String(v); + + if (isNum = typeof v == 'number') { + + // Avoid potential interpretation of Infinity and NaN as base 44+ values. + if (v * 0 != 0) return parseNumeric(x, str, isNum, b); + + x.s = 1 / v < 0 ? (str = str.slice(1), -1) : 1; + + // '[BigNumber Error] Number primitive has more than 15 significant digits: {n}' + if (BigNumber.DEBUG && str.replace(/^0\.0*|\./, '').length > 15) { + throw Error + (tooManyDigits + v); + } + } else { + x.s = str.charCodeAt(0) === 45 ? (str = str.slice(1), -1) : 1; + } + + alphabet = ALPHABET.slice(0, b); + e = i = 0; + + // Check that str is a valid base b number. + // Don't use RegExp, so alphabet can contain special characters. + for (len = str.length; i < len; i++) { + if (alphabet.indexOf(c = str.charAt(i)) < 0) { + if (c == '.') { + + // If '.' is not the first character and it has not be found before. + if (i > e) { + e = len; + continue; + } + } else if (!caseChanged) { + + // Allow e.g. hexadecimal 'FF' as well as 'ff'. + if (str == str.toUpperCase() && (str = str.toLowerCase()) || + str == str.toLowerCase() && (str = str.toUpperCase())) { + caseChanged = true; + i = -1; + e = 0; + continue; + } + } + + return parseNumeric(x, String(v), isNum, b); + } + } + + // Prevent later check for length on converted number. + isNum = false; + str = convertBase(str, b, 10, x.s); + + // Decimal point? + if ((e = str.indexOf('.')) > -1) str = str.replace('.', ''); + else e = str.length; + } + + // Determine leading zeros. + for (i = 0; str.charCodeAt(i) === 48; i++); + + // Determine trailing zeros. + for (len = str.length; str.charCodeAt(--len) === 48;); + + if (str = str.slice(i, ++len)) { + len -= i; + + // '[BigNumber Error] Number primitive has more than 15 significant digits: {n}' + if (isNum && BigNumber.DEBUG && + len > 15 && (v > MAX_SAFE_INTEGER || v !== mathfloor(v))) { + throw Error + (tooManyDigits + (x.s * v)); + } + + // Overflow? + if ((e = e - i - 1) > MAX_EXP) { + + // Infinity. + x.c = x.e = null; + + // Underflow? + } else if (e < MIN_EXP) { + + // Zero. + x.c = [x.e = 0]; + } else { + x.e = e; + x.c = []; + + // Transform base + + // e is the base 10 exponent. + // i is where to slice str to get the first element of the coefficient array. + i = (e + 1) % LOG_BASE; + if (e < 0) i += LOG_BASE; // i < 1 + + if (i < len) { + if (i) x.c.push(+str.slice(0, i)); + + for (len -= LOG_BASE; i < len;) { + x.c.push(+str.slice(i, i += LOG_BASE)); + } + + i = LOG_BASE - (str = str.slice(i)).length; + } else { + i -= len; + } + + for (; i--; str += '0'); + x.c.push(+str); + } + } else { + + // Zero. + x.c = [x.e = 0]; + } + } + + + // CONSTRUCTOR PROPERTIES + + + BigNumber.clone = clone; + + BigNumber.ROUND_UP = 0; + BigNumber.ROUND_DOWN = 1; + BigNumber.ROUND_CEIL = 2; + BigNumber.ROUND_FLOOR = 3; + BigNumber.ROUND_HALF_UP = 4; + BigNumber.ROUND_HALF_DOWN = 5; + BigNumber.ROUND_HALF_EVEN = 6; + BigNumber.ROUND_HALF_CEIL = 7; + BigNumber.ROUND_HALF_FLOOR = 8; + BigNumber.EUCLID = 9; + + + /* + * Configure infrequently-changing library-wide settings. + * + * Accept an object with the following optional properties (if the value of a property is + * a number, it must be an integer within the inclusive range stated): + * + * DECIMAL_PLACES {number} 0 to MAX + * ROUNDING_MODE {number} 0 to 8 + * EXPONENTIAL_AT {number|number[]} -MAX to MAX or [-MAX to 0, 0 to MAX] + * RANGE {number|number[]} -MAX to MAX (not zero) or [-MAX to -1, 1 to MAX] + * CRYPTO {boolean} true or false + * MODULO_MODE {number} 0 to 9 + * POW_PRECISION {number} 0 to MAX + * ALPHABET {string} A string of two or more unique characters which does + * not contain '.'. + * FORMAT {object} An object with some of the following properties: + * prefix {string} + * groupSize {number} + * secondaryGroupSize {number} + * groupSeparator {string} + * decimalSeparator {string} + * fractionGroupSize {number} + * fractionGroupSeparator {string} + * suffix {string} + * + * (The values assigned to the above FORMAT object properties are not checked for validity.) + * + * E.g. + * BigNumber.config({ DECIMAL_PLACES : 20, ROUNDING_MODE : 4 }) + * + * Ignore properties/parameters set to null or undefined, except for ALPHABET. + * + * Return an object with the properties current values. + */ + BigNumber.config = BigNumber.set = function (obj) { + var p, v; + + if (obj != null) { + + if (typeof obj == 'object') { + + // DECIMAL_PLACES {number} Integer, 0 to MAX inclusive. + // '[BigNumber Error] DECIMAL_PLACES {not a primitive number|not an integer|out of range}: {v}' + if (obj.hasOwnProperty(p = 'DECIMAL_PLACES')) { + v = obj[p]; + intCheck(v, 0, MAX, p); + DECIMAL_PLACES = v; + } + + // ROUNDING_MODE {number} Integer, 0 to 8 inclusive. + // '[BigNumber Error] ROUNDING_MODE {not a primitive number|not an integer|out of range}: {v}' + if (obj.hasOwnProperty(p = 'ROUNDING_MODE')) { + v = obj[p]; + intCheck(v, 0, 8, p); + ROUNDING_MODE = v; + } + + // EXPONENTIAL_AT {number|number[]} + // Integer, -MAX to MAX inclusive or + // [integer -MAX to 0 inclusive, 0 to MAX inclusive]. + // '[BigNumber Error] EXPONENTIAL_AT {not a primitive number|not an integer|out of range}: {v}' + if (obj.hasOwnProperty(p = 'EXPONENTIAL_AT')) { + v = obj[p]; + if (v && v.pop) { + intCheck(v[0], -MAX, 0, p); + intCheck(v[1], 0, MAX, p); + TO_EXP_NEG = v[0]; + TO_EXP_POS = v[1]; + } else { + intCheck(v, -MAX, MAX, p); + TO_EXP_NEG = -(TO_EXP_POS = v < 0 ? -v : v); + } + } + + // RANGE {number|number[]} Non-zero integer, -MAX to MAX inclusive or + // [integer -MAX to -1 inclusive, integer 1 to MAX inclusive]. + // '[BigNumber Error] RANGE {not a primitive number|not an integer|out of range|cannot be zero}: {v}' + if (obj.hasOwnProperty(p = 'RANGE')) { + v = obj[p]; + if (v && v.pop) { + intCheck(v[0], -MAX, -1, p); + intCheck(v[1], 1, MAX, p); + MIN_EXP = v[0]; + MAX_EXP = v[1]; + } else { + intCheck(v, -MAX, MAX, p); + if (v) { + MIN_EXP = -(MAX_EXP = v < 0 ? -v : v); + } else { + throw Error + (bignumberError + p + ' cannot be zero: ' + v); + } + } + } + + // CRYPTO {boolean} true or false. + // '[BigNumber Error] CRYPTO not true or false: {v}' + // '[BigNumber Error] crypto unavailable' + if (obj.hasOwnProperty(p = 'CRYPTO')) { + v = obj[p]; + if (v === !!v) { + if (v) { + if (typeof crypto != 'undefined' && crypto && + (crypto.getRandomValues || crypto.randomBytes)) { + CRYPTO = v; + } else { + CRYPTO = !v; + throw Error + (bignumberError + 'crypto unavailable'); + } + } else { + CRYPTO = v; + } + } else { + throw Error + (bignumberError + p + ' not true or false: ' + v); + } + } + + // MODULO_MODE {number} Integer, 0 to 9 inclusive. + // '[BigNumber Error] MODULO_MODE {not a primitive number|not an integer|out of range}: {v}' + if (obj.hasOwnProperty(p = 'MODULO_MODE')) { + v = obj[p]; + intCheck(v, 0, 9, p); + MODULO_MODE = v; + } + + // POW_PRECISION {number} Integer, 0 to MAX inclusive. + // '[BigNumber Error] POW_PRECISION {not a primitive number|not an integer|out of range}: {v}' + if (obj.hasOwnProperty(p = 'POW_PRECISION')) { + v = obj[p]; + intCheck(v, 0, MAX, p); + POW_PRECISION = v; + } + + // FORMAT {object} + // '[BigNumber Error] FORMAT not an object: {v}' + if (obj.hasOwnProperty(p = 'FORMAT')) { + v = obj[p]; + if (typeof v == 'object') FORMAT = v; + else throw Error + (bignumberError + p + ' not an object: ' + v); + } + + // ALPHABET {string} + // '[BigNumber Error] ALPHABET invalid: {v}' + if (obj.hasOwnProperty(p = 'ALPHABET')) { + v = obj[p]; + + // Disallow if less than two characters, + // or if it contains '+', '-', '.', whitespace, or a repeated character. + if (typeof v == 'string' && !/^.?$|[+\-.\s]|(.).*\1/.test(v)) { + alphabetHasNormalDecimalDigits = v.slice(0, 10) == '0123456789'; + ALPHABET = v; + } else { + throw Error + (bignumberError + p + ' invalid: ' + v); + } + } + + } else { + + // '[BigNumber Error] Object expected: {v}' + throw Error + (bignumberError + 'Object expected: ' + obj); + } + } + + return { + DECIMAL_PLACES: DECIMAL_PLACES, + ROUNDING_MODE: ROUNDING_MODE, + EXPONENTIAL_AT: [TO_EXP_NEG, TO_EXP_POS], + RANGE: [MIN_EXP, MAX_EXP], + CRYPTO: CRYPTO, + MODULO_MODE: MODULO_MODE, + POW_PRECISION: POW_PRECISION, + FORMAT: FORMAT, + ALPHABET: ALPHABET + }; + }; + + + /* + * Return true if v is a BigNumber instance, otherwise return false. + * + * If BigNumber.DEBUG is true, throw if a BigNumber instance is not well-formed. + * + * v {any} + * + * '[BigNumber Error] Invalid BigNumber: {v}' + */ + BigNumber.isBigNumber = function (v) { + if (!v || v._isBigNumber !== true) return false; + if (!BigNumber.DEBUG) return true; + + var i, n, + c = v.c, + e = v.e, + s = v.s; + + out: if ({}.toString.call(c) == '[object Array]') { + + if ((s === 1 || s === -1) && e >= -MAX && e <= MAX && e === mathfloor(e)) { + + // If the first element is zero, the BigNumber value must be zero. + if (c[0] === 0) { + if (e === 0 && c.length === 1) return true; + break out; + } + + // Calculate number of digits that c[0] should have, based on the exponent. + i = (e + 1) % LOG_BASE; + if (i < 1) i += LOG_BASE; + + // Calculate number of digits of c[0]. + //if (Math.ceil(Math.log(c[0] + 1) / Math.LN10) == i) { + if (String(c[0]).length == i) { + + for (i = 0; i < c.length; i++) { + n = c[i]; + if (n < 0 || n >= BASE || n !== mathfloor(n)) break out; + } + + // Last element cannot be zero, unless it is the only element. + if (n !== 0) return true; + } + } + + // Infinity/NaN + } else if (c === null && e === null && (s === null || s === 1 || s === -1)) { + return true; + } + + throw Error + (bignumberError + 'Invalid BigNumber: ' + v); + }; + + + /* + * Return a new BigNumber whose value is the maximum of the arguments. + * + * arguments {number|string|BigNumber} + */ + BigNumber.maximum = BigNumber.max = function () { + return maxOrMin(arguments, -1); + }; + + + /* + * Return a new BigNumber whose value is the minimum of the arguments. + * + * arguments {number|string|BigNumber} + */ + BigNumber.minimum = BigNumber.min = function () { + return maxOrMin(arguments, 1); + }; + + + /* + * Return a new BigNumber with a random value equal to or greater than 0 and less than 1, + * and with dp, or DECIMAL_PLACES if dp is omitted, decimal places (or less if trailing + * zeros are produced). + * + * [dp] {number} Decimal places. Integer, 0 to MAX inclusive. + * + * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {dp}' + * '[BigNumber Error] crypto unavailable' + */ + BigNumber.random = (function () { + var pow2_53 = 0x20000000000000; + + // Return a 53 bit integer n, where 0 <= n < 9007199254740992. + // Check if Math.random() produces more than 32 bits of randomness. + // If it does, assume at least 53 bits are produced, otherwise assume at least 30 bits. + // 0x40000000 is 2^30, 0x800000 is 2^23, 0x1fffff is 2^21 - 1. + var random53bitInt = (Math.random() * pow2_53) & 0x1fffff + ? function () { return mathfloor(Math.random() * pow2_53); } + : function () { return ((Math.random() * 0x40000000 | 0) * 0x800000) + + (Math.random() * 0x800000 | 0); }; + + return function (dp) { + var a, b, e, k, v, + i = 0, + c = [], + rand = new BigNumber(ONE); + + if (dp == null) dp = DECIMAL_PLACES; + else intCheck(dp, 0, MAX); + + k = mathceil(dp / LOG_BASE); + + if (CRYPTO) { + + // Browsers supporting crypto.getRandomValues. + if (crypto.getRandomValues) { + + a = crypto.getRandomValues(new Uint32Array(k *= 2)); + + for (; i < k;) { + + // 53 bits: + // ((Math.pow(2, 32) - 1) * Math.pow(2, 21)).toString(2) + // 11111 11111111 11111111 11111111 11100000 00000000 00000000 + // ((Math.pow(2, 32) - 1) >>> 11).toString(2) + // 11111 11111111 11111111 + // 0x20000 is 2^21. + v = a[i] * 0x20000 + (a[i + 1] >>> 11); + + // Rejection sampling: + // 0 <= v < 9007199254740992 + // Probability that v >= 9e15, is + // 7199254740992 / 9007199254740992 ~= 0.0008, i.e. 1 in 1251 + if (v >= 9e15) { + b = crypto.getRandomValues(new Uint32Array(2)); + a[i] = b[0]; + a[i + 1] = b[1]; + } else { + + // 0 <= v <= 8999999999999999 + // 0 <= (v % 1e14) <= 99999999999999 + c.push(v % 1e14); + i += 2; + } + } + i = k / 2; + + // Node.js supporting crypto.randomBytes. + } else if (crypto.randomBytes) { + + // buffer + a = crypto.randomBytes(k *= 7); + + for (; i < k;) { + + // 0x1000000000000 is 2^48, 0x10000000000 is 2^40 + // 0x100000000 is 2^32, 0x1000000 is 2^24 + // 11111 11111111 11111111 11111111 11111111 11111111 11111111 + // 0 <= v < 9007199254740992 + v = ((a[i] & 31) * 0x1000000000000) + (a[i + 1] * 0x10000000000) + + (a[i + 2] * 0x100000000) + (a[i + 3] * 0x1000000) + + (a[i + 4] << 16) + (a[i + 5] << 8) + a[i + 6]; + + if (v >= 9e15) { + crypto.randomBytes(7).copy(a, i); + } else { + + // 0 <= (v % 1e14) <= 99999999999999 + c.push(v % 1e14); + i += 7; + } + } + i = k / 7; + } else { + CRYPTO = false; + throw Error + (bignumberError + 'crypto unavailable'); + } + } + + // Use Math.random. + if (!CRYPTO) { + + for (; i < k;) { + v = random53bitInt(); + if (v < 9e15) c[i++] = v % 1e14; + } + } + + k = c[--i]; + dp %= LOG_BASE; + + // Convert trailing digits to zeros according to dp. + if (k && dp) { + v = POWS_TEN[LOG_BASE - dp]; + c[i] = mathfloor(k / v) * v; + } + + // Remove trailing elements which are zero. + for (; c[i] === 0; c.pop(), i--); + + // Zero? + if (i < 0) { + c = [e = 0]; + } else { + + // Remove leading elements which are zero and adjust exponent accordingly. + for (e = -1 ; c[0] === 0; c.splice(0, 1), e -= LOG_BASE); + + // Count the digits of the first element of c to determine leading zeros, and... + for (i = 1, v = c[0]; v >= 10; v /= 10, i++); + + // adjust the exponent accordingly. + if (i < LOG_BASE) e -= LOG_BASE - i; + } + + rand.e = e; + rand.c = c; + return rand; + }; + })(); + + + /* + * Return a BigNumber whose value is the sum of the arguments. + * + * arguments {number|string|BigNumber} + */ + BigNumber.sum = function () { + var i = 1, + args = arguments, + sum = new BigNumber(args[0]); + for (; i < args.length;) sum = sum.plus(args[i++]); + return sum; + }; + + + // PRIVATE FUNCTIONS + + + // Called by BigNumber and BigNumber.prototype.toString. + convertBase = (function () { + var decimal = '0123456789'; + + /* + * Convert string of baseIn to an array of numbers of baseOut. + * Eg. toBaseOut('255', 10, 16) returns [15, 15]. + * Eg. toBaseOut('ff', 16, 10) returns [2, 5, 5]. + */ + function toBaseOut(str, baseIn, baseOut, alphabet) { + var j, + arr = [0], + arrL, + i = 0, + len = str.length; + + for (; i < len;) { + for (arrL = arr.length; arrL--; arr[arrL] *= baseIn); + + arr[0] += alphabet.indexOf(str.charAt(i++)); + + for (j = 0; j < arr.length; j++) { + + if (arr[j] > baseOut - 1) { + if (arr[j + 1] == null) arr[j + 1] = 0; + arr[j + 1] += arr[j] / baseOut | 0; + arr[j] %= baseOut; + } + } + } + + return arr.reverse(); + } + + // Convert a numeric string of baseIn to a numeric string of baseOut. + // If the caller is toString, we are converting from base 10 to baseOut. + // If the caller is BigNumber, we are converting from baseIn to base 10. + return function (str, baseIn, baseOut, sign, callerIsToString) { + var alphabet, d, e, k, r, x, xc, y, + i = str.indexOf('.'), + dp = DECIMAL_PLACES, + rm = ROUNDING_MODE; + + // Non-integer. + if (i >= 0) { + k = POW_PRECISION; + + // Unlimited precision. + POW_PRECISION = 0; + str = str.replace('.', ''); + y = new BigNumber(baseIn); + x = y.pow(str.length - i); + POW_PRECISION = k; + + // Convert str as if an integer, then restore the fraction part by dividing the + // result by its base raised to a power. + + y.c = toBaseOut(toFixedPoint(coeffToString(x.c), x.e, '0'), + 10, baseOut, decimal); + y.e = y.c.length; + } + + // Convert the number as integer. + + xc = toBaseOut(str, baseIn, baseOut, callerIsToString + ? (alphabet = ALPHABET, decimal) + : (alphabet = decimal, ALPHABET)); + + // xc now represents str as an integer and converted to baseOut. e is the exponent. + e = k = xc.length; + + // Remove trailing zeros. + for (; xc[--k] == 0; xc.pop()); + + // Zero? + if (!xc[0]) return alphabet.charAt(0); + + // Does str represent an integer? If so, no need for the division. + if (i < 0) { + --e; + } else { + x.c = xc; + x.e = e; + + // The sign is needed for correct rounding. + x.s = sign; + x = div(x, y, dp, rm, baseOut); + xc = x.c; + r = x.r; + e = x.e; + } + + // xc now represents str converted to baseOut. + + // The index of the rounding digit. + d = e + dp + 1; + + // The rounding digit: the digit to the right of the digit that may be rounded up. + i = xc[d]; + + // Look at the rounding digits and mode to determine whether to round up. + + k = baseOut / 2; + r = r || d < 0 || xc[d + 1] != null; + + r = rm < 4 ? (i != null || r) && (rm == 0 || rm == (x.s < 0 ? 3 : 2)) + : i > k || i == k &&(rm == 4 || r || rm == 6 && xc[d - 1] & 1 || + rm == (x.s < 0 ? 8 : 7)); + + // If the index of the rounding digit is not greater than zero, or xc represents + // zero, then the result of the base conversion is zero or, if rounding up, a value + // such as 0.00001. + if (d < 1 || !xc[0]) { + + // 1^-dp or 0 + str = r ? toFixedPoint(alphabet.charAt(1), -dp, alphabet.charAt(0)) : alphabet.charAt(0); + } else { + + // Truncate xc to the required number of decimal places. + xc.length = d; + + // Round up? + if (r) { + + // Rounding up may mean the previous digit has to be rounded up and so on. + for (--baseOut; ++xc[--d] > baseOut;) { + xc[d] = 0; + + if (!d) { + ++e; + xc = [1].concat(xc); + } + } + } + + // Determine trailing zeros. + for (k = xc.length; !xc[--k];); + + // E.g. [4, 11, 15] becomes 4bf. + for (i = 0, str = ''; i <= k; str += alphabet.charAt(xc[i++])); + + // Add leading zeros, decimal point and trailing zeros as required. + str = toFixedPoint(str, e, alphabet.charAt(0)); + } + + // The caller will add the sign. + return str; + }; + })(); + + + // Perform division in the specified base. Called by div and convertBase. + div = (function () { + + // Assume non-zero x and k. + function multiply(x, k, base) { + var m, temp, xlo, xhi, + carry = 0, + i = x.length, + klo = k % SQRT_BASE, + khi = k / SQRT_BASE | 0; + + for (x = x.slice(); i--;) { + xlo = x[i] % SQRT_BASE; + xhi = x[i] / SQRT_BASE | 0; + m = khi * xlo + xhi * klo; + temp = klo * xlo + ((m % SQRT_BASE) * SQRT_BASE) + carry; + carry = (temp / base | 0) + (m / SQRT_BASE | 0) + khi * xhi; + x[i] = temp % base; + } + + if (carry) x = [carry].concat(x); + + return x; + } + + function compare(a, b, aL, bL) { + var i, cmp; + + if (aL != bL) { + cmp = aL > bL ? 1 : -1; + } else { + + for (i = cmp = 0; i < aL; i++) { + + if (a[i] != b[i]) { + cmp = a[i] > b[i] ? 1 : -1; + break; + } + } + } + + return cmp; + } + + function subtract(a, b, aL, base) { + var i = 0; + + // Subtract b from a. + for (; aL--;) { + a[aL] -= i; + i = a[aL] < b[aL] ? 1 : 0; + a[aL] = i * base + a[aL] - b[aL]; + } + + // Remove leading zeros. + for (; !a[0] && a.length > 1; a.splice(0, 1)); + } + + // x: dividend, y: divisor. + return function (x, y, dp, rm, base) { + var cmp, e, i, more, n, prod, prodL, q, qc, rem, remL, rem0, xi, xL, yc0, + yL, yz, + s = x.s == y.s ? 1 : -1, + xc = x.c, + yc = y.c; + + // Either NaN, Infinity or 0? + if (!xc || !xc[0] || !yc || !yc[0]) { + + return new BigNumber( + + // Return NaN if either NaN, or both Infinity or 0. + !x.s || !y.s || (xc ? yc && xc[0] == yc[0] : !yc) ? NaN : + + // Return ±0 if x is ±0 or y is ±Infinity, or return ±Infinity as y is ±0. + xc && xc[0] == 0 || !yc ? s * 0 : s / 0 + ); + } + + q = new BigNumber(s); + qc = q.c = []; + e = x.e - y.e; + s = dp + e + 1; + + if (!base) { + base = BASE; + e = bitFloor(x.e / LOG_BASE) - bitFloor(y.e / LOG_BASE); + s = s / LOG_BASE | 0; + } + + // Result exponent may be one less then the current value of e. + // The coefficients of the BigNumbers from convertBase may have trailing zeros. + for (i = 0; yc[i] == (xc[i] || 0); i++); + + if (yc[i] > (xc[i] || 0)) e--; + + if (s < 0) { + qc.push(1); + more = true; + } else { + xL = xc.length; + yL = yc.length; + i = 0; + s += 2; + + // Normalise xc and yc so highest order digit of yc is >= base / 2. + + n = mathfloor(base / (yc[0] + 1)); + + // Not necessary, but to handle odd bases where yc[0] == (base / 2) - 1. + // if (n > 1 || n++ == 1 && yc[0] < base / 2) { + if (n > 1) { + yc = multiply(yc, n, base); + xc = multiply(xc, n, base); + yL = yc.length; + xL = xc.length; + } + + xi = yL; + rem = xc.slice(0, yL); + remL = rem.length; + + // Add zeros to make remainder as long as divisor. + for (; remL < yL; rem[remL++] = 0); + yz = yc.slice(); + yz = [0].concat(yz); + yc0 = yc[0]; + if (yc[1] >= base / 2) yc0++; + // Not necessary, but to prevent trial digit n > base, when using base 3. + // else if (base == 3 && yc0 == 1) yc0 = 1 + 1e-15; + + do { + n = 0; + + // Compare divisor and remainder. + cmp = compare(yc, rem, yL, remL); + + // If divisor < remainder. + if (cmp < 0) { + + // Calculate trial digit, n. + + rem0 = rem[0]; + if (yL != remL) rem0 = rem0 * base + (rem[1] || 0); + + // n is how many times the divisor goes into the current remainder. + n = mathfloor(rem0 / yc0); + + // Algorithm: + // product = divisor multiplied by trial digit (n). + // Compare product and remainder. + // If product is greater than remainder: + // Subtract divisor from product, decrement trial digit. + // Subtract product from remainder. + // If product was less than remainder at the last compare: + // Compare new remainder and divisor. + // If remainder is greater than divisor: + // Subtract divisor from remainder, increment trial digit. + + if (n > 1) { + + // n may be > base only when base is 3. + if (n >= base) n = base - 1; + + // product = divisor * trial digit. + prod = multiply(yc, n, base); + prodL = prod.length; + remL = rem.length; + + // Compare product and remainder. + // If product > remainder then trial digit n too high. + // n is 1 too high about 5% of the time, and is not known to have + // ever been more than 1 too high. + while (compare(prod, rem, prodL, remL) == 1) { + n--; + + // Subtract divisor from product. + subtract(prod, yL < prodL ? yz : yc, prodL, base); + prodL = prod.length; + cmp = 1; + } + } else { + + // n is 0 or 1, cmp is -1. + // If n is 0, there is no need to compare yc and rem again below, + // so change cmp to 1 to avoid it. + // If n is 1, leave cmp as -1, so yc and rem are compared again. + if (n == 0) { + + // divisor < remainder, so n must be at least 1. + cmp = n = 1; + } + + // product = divisor + prod = yc.slice(); + prodL = prod.length; + } + + if (prodL < remL) prod = [0].concat(prod); + + // Subtract product from remainder. + subtract(rem, prod, remL, base); + remL = rem.length; + + // If product was < remainder. + if (cmp == -1) { + + // Compare divisor and new remainder. + // If divisor < new remainder, subtract divisor from remainder. + // Trial digit n too low. + // n is 1 too low about 5% of the time, and very rarely 2 too low. + while (compare(yc, rem, yL, remL) < 1) { + n++; + + // Subtract divisor from remainder. + subtract(rem, yL < remL ? yz : yc, remL, base); + remL = rem.length; + } + } + } else if (cmp === 0) { + n++; + rem = [0]; + } // else cmp === 1 and n will be 0 + + // Add the next digit, n, to the result array. + qc[i++] = n; + + // Update the remainder. + if (rem[0]) { + rem[remL++] = xc[xi] || 0; + } else { + rem = [xc[xi]]; + remL = 1; + } + } while ((xi++ < xL || rem[0] != null) && s--); + + more = rem[0] != null; + + // Leading zero? + if (!qc[0]) qc.splice(0, 1); + } + + if (base == BASE) { + + // To calculate q.e, first get the number of digits of qc[0]. + for (i = 1, s = qc[0]; s >= 10; s /= 10, i++); + + round(q, dp + (q.e = i + e * LOG_BASE - 1) + 1, rm, more); + + // Caller is convertBase. + } else { + q.e = e; + q.r = +more; + } + + return q; + }; + })(); + + + /* + * Return a string representing the value of BigNumber n in fixed-point or exponential + * notation rounded to the specified decimal places or significant digits. + * + * n: a BigNumber. + * i: the index of the last digit required (i.e. the digit that may be rounded up). + * rm: the rounding mode. + * id: 1 (toExponential) or 2 (toPrecision). + */ + function format(n, i, rm, id) { + var c0, e, ne, len, str; + + if (rm == null) rm = ROUNDING_MODE; + else intCheck(rm, 0, 8); + + if (!n.c) return n.toString(); + + c0 = n.c[0]; + ne = n.e; + + if (i == null) { + str = coeffToString(n.c); + str = id == 1 || id == 2 && (ne <= TO_EXP_NEG || ne >= TO_EXP_POS) + ? toExponential(str, ne) + : toFixedPoint(str, ne, '0'); + } else { + n = round(new BigNumber(n), i, rm); + + // n.e may have changed if the value was rounded up. + e = n.e; + + str = coeffToString(n.c); + len = str.length; + + // toPrecision returns exponential notation if the number of significant digits + // specified is less than the number of digits necessary to represent the integer + // part of the value in fixed-point notation. + + // Exponential notation. + if (id == 1 || id == 2 && (i <= e || e <= TO_EXP_NEG)) { + + // Append zeros? + for (; len < i; str += '0', len++); + str = toExponential(str, e); + + // Fixed-point notation. + } else { + i -= ne + (id === 2 && e > ne); + str = toFixedPoint(str, e, '0'); + + // Append zeros? + if (e + 1 > len) { + if (--i > 0) for (str += '.'; i--; str += '0'); + } else { + i += e - len; + if (i > 0) { + if (e + 1 == len) str += '.'; + for (; i--; str += '0'); + } + } + } + } + + return n.s < 0 && c0 ? '-' + str : str; + } + + + // Handle BigNumber.max and BigNumber.min. + // If any number is NaN, return NaN. + function maxOrMin(args, n) { + var k, y, + i = 1, + x = new BigNumber(args[0]); + + for (; i < args.length; i++) { + y = new BigNumber(args[i]); + if (!y.s || (k = compare(x, y)) === n || k === 0 && x.s === n) { + x = y; + } + } + + return x; + } + + + /* + * Strip trailing zeros, calculate base 10 exponent and check against MIN_EXP and MAX_EXP. + * Called by minus, plus and times. + */ + function normalise(n, c, e) { + var i = 1, + j = c.length; + + // Remove trailing zeros. + for (; !c[--j]; c.pop()); + + // Calculate the base 10 exponent. First get the number of digits of c[0]. + for (j = c[0]; j >= 10; j /= 10, i++); + + // Overflow? + if ((e = i + e * LOG_BASE - 1) > MAX_EXP) { + + // Infinity. + n.c = n.e = null; + + // Underflow? + } else if (e < MIN_EXP) { + + // Zero. + n.c = [n.e = 0]; + } else { + n.e = e; + n.c = c; + } + + return n; + } + + + // Handle values that fail the validity test in BigNumber. + parseNumeric = (function () { + var basePrefix = /^(-?)0([xbo])(?=\w[\w.]*$)/i, + dotAfter = /^([^.]+)\.$/, + dotBefore = /^\.([^.]+)$/, + isInfinityOrNaN = /^-?(Infinity|NaN)$/, + whitespaceOrPlus = /^\s*\+(?=[\w.])|^\s+|\s+$/g; + + return function (x, str, isNum, b) { + var base, + s = isNum ? str : str.replace(whitespaceOrPlus, ''); + + // No exception on ±Infinity or NaN. + if (isInfinityOrNaN.test(s)) { + x.s = isNaN(s) ? null : s < 0 ? -1 : 1; + } else { + if (!isNum) { + + // basePrefix = /^(-?)0([xbo])(?=\w[\w.]*$)/i + s = s.replace(basePrefix, function (m, p1, p2) { + base = (p2 = p2.toLowerCase()) == 'x' ? 16 : p2 == 'b' ? 2 : 8; + return !b || b == base ? p1 : m; + }); + + if (b) { + base = b; + + // E.g. '1.' to '1', '.1' to '0.1' + s = s.replace(dotAfter, '$1').replace(dotBefore, '0.$1'); + } + + if (str != s) return new BigNumber(s, base); + } + + // '[BigNumber Error] Not a number: {n}' + // '[BigNumber Error] Not a base {b} number: {n}' + if (BigNumber.DEBUG) { + throw Error + (bignumberError + 'Not a' + (b ? ' base ' + b : '') + ' number: ' + str); + } + + // NaN + x.s = null; + } + + x.c = x.e = null; + } + })(); + + + /* + * Round x to sd significant digits using rounding mode rm. Check for over/under-flow. + * If r is truthy, it is known that there are more digits after the rounding digit. + */ + function round(x, sd, rm, r) { + var d, i, j, k, n, ni, rd, + xc = x.c, + pows10 = POWS_TEN; + + // if x is not Infinity or NaN... + if (xc) { + + // rd is the rounding digit, i.e. the digit after the digit that may be rounded up. + // n is a base 1e14 number, the value of the element of array x.c containing rd. + // ni is the index of n within x.c. + // d is the number of digits of n. + // i is the index of rd within n including leading zeros. + // j is the actual index of rd within n (if < 0, rd is a leading zero). + out: { + + // Get the number of digits of the first element of xc. + for (d = 1, k = xc[0]; k >= 10; k /= 10, d++); + i = sd - d; + + // If the rounding digit is in the first element of xc... + if (i < 0) { + i += LOG_BASE; + j = sd; + n = xc[ni = 0]; + + // Get the rounding digit at index j of n. + rd = mathfloor(n / pows10[d - j - 1] % 10); + } else { + ni = mathceil((i + 1) / LOG_BASE); + + if (ni >= xc.length) { + + if (r) { + + // Needed by sqrt. + for (; xc.length <= ni; xc.push(0)); + n = rd = 0; + d = 1; + i %= LOG_BASE; + j = i - LOG_BASE + 1; + } else { + break out; + } + } else { + n = k = xc[ni]; + + // Get the number of digits of n. + for (d = 1; k >= 10; k /= 10, d++); + + // Get the index of rd within n. + i %= LOG_BASE; + + // Get the index of rd within n, adjusted for leading zeros. + // The number of leading zeros of n is given by LOG_BASE - d. + j = i - LOG_BASE + d; + + // Get the rounding digit at index j of n. + rd = j < 0 ? 0 : mathfloor(n / pows10[d - j - 1] % 10); + } + } + + r = r || sd < 0 || + + // Are there any non-zero digits after the rounding digit? + // The expression n % pows10[d - j - 1] returns all digits of n to the right + // of the digit at j, e.g. if n is 908714 and j is 2, the expression gives 714. + xc[ni + 1] != null || (j < 0 ? n : n % pows10[d - j - 1]); + + r = rm < 4 + ? (rd || r) && (rm == 0 || rm == (x.s < 0 ? 3 : 2)) + : rd > 5 || rd == 5 && (rm == 4 || r || rm == 6 && + + // Check whether the digit to the left of the rounding digit is odd. + ((i > 0 ? j > 0 ? n / pows10[d - j] : 0 : xc[ni - 1]) % 10) & 1 || + rm == (x.s < 0 ? 8 : 7)); + + if (sd < 1 || !xc[0]) { + xc.length = 0; + + if (r) { + + // Convert sd to decimal places. + sd -= x.e + 1; + + // 1, 0.1, 0.01, 0.001, 0.0001 etc. + xc[0] = pows10[(LOG_BASE - sd % LOG_BASE) % LOG_BASE]; + x.e = -sd || 0; + } else { + + // Zero. + xc[0] = x.e = 0; + } + + return x; + } + + // Remove excess digits. + if (i == 0) { + xc.length = ni; + k = 1; + ni--; + } else { + xc.length = ni + 1; + k = pows10[LOG_BASE - i]; + + // E.g. 56700 becomes 56000 if 7 is the rounding digit. + // j > 0 means i > number of leading zeros of n. + xc[ni] = j > 0 ? mathfloor(n / pows10[d - j] % pows10[j]) * k : 0; + } + + // Round up? + if (r) { + + for (; ;) { + + // If the digit to be rounded up is in the first element of xc... + if (ni == 0) { + + // i will be the length of xc[0] before k is added. + for (i = 1, j = xc[0]; j >= 10; j /= 10, i++); + j = xc[0] += k; + for (k = 1; j >= 10; j /= 10, k++); + + // if i != k the length has increased. + if (i != k) { + x.e++; + if (xc[0] == BASE) xc[0] = 1; + } + + break; + } else { + xc[ni] += k; + if (xc[ni] != BASE) break; + xc[ni--] = 0; + k = 1; + } + } + } + + // Remove trailing zeros. + for (i = xc.length; xc[--i] === 0; xc.pop()); + } + + // Overflow? Infinity. + if (x.e > MAX_EXP) { + x.c = x.e = null; + + // Underflow? Zero. + } else if (x.e < MIN_EXP) { + x.c = [x.e = 0]; + } + } + + return x; + } + + + function valueOf(n) { + var str, + e = n.e; + + if (e === null) return n.toString(); + + str = coeffToString(n.c); + + str = e <= TO_EXP_NEG || e >= TO_EXP_POS + ? toExponential(str, e) + : toFixedPoint(str, e, '0'); + + return n.s < 0 ? '-' + str : str; + } + + + // PROTOTYPE/INSTANCE METHODS + + + /* + * Return a new BigNumber whose value is the absolute value of this BigNumber. + */ + P.absoluteValue = P.abs = function () { + var x = new BigNumber(this); + if (x.s < 0) x.s = 1; + return x; + }; + + + /* + * Return + * 1 if the value of this BigNumber is greater than the value of BigNumber(y, b), + * -1 if the value of this BigNumber is less than the value of BigNumber(y, b), + * 0 if they have the same value, + * or null if the value of either is NaN. + */ + P.comparedTo = function (y, b) { + return compare(this, new BigNumber(y, b)); + }; + + + /* + * If dp is undefined or null or true or false, return the number of decimal places of the + * value of this BigNumber, or null if the value of this BigNumber is ±Infinity or NaN. + * + * Otherwise, if dp is a number, return a new BigNumber whose value is the value of this + * BigNumber rounded to a maximum of dp decimal places using rounding mode rm, or + * ROUNDING_MODE if rm is omitted. + * + * [dp] {number} Decimal places: integer, 0 to MAX inclusive. + * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive. + * + * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {dp|rm}' + */ + P.decimalPlaces = P.dp = function (dp, rm) { + var c, n, v, + x = this; + + if (dp != null) { + intCheck(dp, 0, MAX); + if (rm == null) rm = ROUNDING_MODE; + else intCheck(rm, 0, 8); + + return round(new BigNumber(x), dp + x.e + 1, rm); + } + + if (!(c = x.c)) return null; + n = ((v = c.length - 1) - bitFloor(this.e / LOG_BASE)) * LOG_BASE; + + // Subtract the number of trailing zeros of the last number. + if (v = c[v]) for (; v % 10 == 0; v /= 10, n--); + if (n < 0) n = 0; + + return n; + }; + + + /* + * n / 0 = I + * n / N = N + * n / I = 0 + * 0 / n = 0 + * 0 / 0 = N + * 0 / N = N + * 0 / I = 0 + * N / n = N + * N / 0 = N + * N / N = N + * N / I = N + * I / n = I + * I / 0 = I + * I / N = N + * I / I = N + * + * Return a new BigNumber whose value is the value of this BigNumber divided by the value of + * BigNumber(y, b), rounded according to DECIMAL_PLACES and ROUNDING_MODE. + */ + P.dividedBy = P.div = function (y, b) { + return div(this, new BigNumber(y, b), DECIMAL_PLACES, ROUNDING_MODE); + }; + + + /* + * Return a new BigNumber whose value is the integer part of dividing the value of this + * BigNumber by the value of BigNumber(y, b). + */ + P.dividedToIntegerBy = P.idiv = function (y, b) { + return div(this, new BigNumber(y, b), 0, 1); + }; + + + /* + * Return a BigNumber whose value is the value of this BigNumber exponentiated by n. + * + * If m is present, return the result modulo m. + * If n is negative round according to DECIMAL_PLACES and ROUNDING_MODE. + * If POW_PRECISION is non-zero and m is not present, round to POW_PRECISION using ROUNDING_MODE. + * + * The modular power operation works efficiently when x, n, and m are integers, otherwise it + * is equivalent to calculating x.exponentiatedBy(n).modulo(m) with a POW_PRECISION of 0. + * + * n {number|string|BigNumber} The exponent. An integer. + * [m] {number|string|BigNumber} The modulus. + * + * '[BigNumber Error] Exponent not an integer: {n}' + */ + P.exponentiatedBy = P.pow = function (n, m) { + var half, isModExp, i, k, more, nIsBig, nIsNeg, nIsOdd, y, + x = this; + + n = new BigNumber(n); + + // Allow NaN and ±Infinity, but not other non-integers. + if (n.c && !n.isInteger()) { + throw Error + (bignumberError + 'Exponent not an integer: ' + valueOf(n)); + } + + if (m != null) m = new BigNumber(m); + + // Exponent of MAX_SAFE_INTEGER is 15. + nIsBig = n.e > 14; + + // If x is NaN, ±Infinity, ±0 or ±1, or n is ±Infinity, NaN or ±0. + if (!x.c || !x.c[0] || x.c[0] == 1 && !x.e && x.c.length == 1 || !n.c || !n.c[0]) { + + // The sign of the result of pow when x is negative depends on the evenness of n. + // If +n overflows to ±Infinity, the evenness of n would be not be known. + y = new BigNumber(Math.pow(+valueOf(x), nIsBig ? n.s * (2 - isOdd(n)) : +valueOf(n))); + return m ? y.mod(m) : y; + } + + nIsNeg = n.s < 0; + + if (m) { + + // x % m returns NaN if abs(m) is zero, or m is NaN. + if (m.c ? !m.c[0] : !m.s) return new BigNumber(NaN); + + isModExp = !nIsNeg && x.isInteger() && m.isInteger(); + + if (isModExp) x = x.mod(m); + + // Overflow to ±Infinity: >=2**1e10 or >=1.0000024**1e15. + // Underflow to ±0: <=0.79**1e10 or <=0.9999975**1e15. + } else if (n.e > 9 && (x.e > 0 || x.e < -1 || (x.e == 0 + // [1, 240000000] + ? x.c[0] > 1 || nIsBig && x.c[1] >= 24e7 + // [80000000000000] [99999750000000] + : x.c[0] < 8e13 || nIsBig && x.c[0] <= 9999975e7))) { + + // If x is negative and n is odd, k = -0, else k = 0. + k = x.s < 0 && isOdd(n) ? -0 : 0; + + // If x >= 1, k = ±Infinity. + if (x.e > -1) k = 1 / k; + + // If n is negative return ±0, else return ±Infinity. + return new BigNumber(nIsNeg ? 1 / k : k); + + } else if (POW_PRECISION) { + + // Truncating each coefficient array to a length of k after each multiplication + // equates to truncating significant digits to POW_PRECISION + [28, 41], + // i.e. there will be a minimum of 28 guard digits retained. + k = mathceil(POW_PRECISION / LOG_BASE + 2); + } + + if (nIsBig) { + half = new BigNumber(0.5); + if (nIsNeg) n.s = 1; + nIsOdd = isOdd(n); + } else { + i = Math.abs(+valueOf(n)); + nIsOdd = i % 2; + } + + y = new BigNumber(ONE); + + // Performs 54 loop iterations for n of 9007199254740991. + for (; ;) { + + if (nIsOdd) { + y = y.times(x); + if (!y.c) break; + + if (k) { + if (y.c.length > k) y.c.length = k; + } else if (isModExp) { + y = y.mod(m); //y = y.minus(div(y, m, 0, MODULO_MODE).times(m)); + } + } + + if (i) { + i = mathfloor(i / 2); + if (i === 0) break; + nIsOdd = i % 2; + } else { + n = n.times(half); + round(n, n.e + 1, 1); + + if (n.e > 14) { + nIsOdd = isOdd(n); + } else { + i = +valueOf(n); + if (i === 0) break; + nIsOdd = i % 2; + } + } + + x = x.times(x); + + if (k) { + if (x.c && x.c.length > k) x.c.length = k; + } else if (isModExp) { + x = x.mod(m); //x = x.minus(div(x, m, 0, MODULO_MODE).times(m)); + } + } + + if (isModExp) return y; + if (nIsNeg) y = ONE.div(y); + + return m ? y.mod(m) : k ? round(y, POW_PRECISION, ROUNDING_MODE, more) : y; + }; + + + /* + * Return a new BigNumber whose value is the value of this BigNumber rounded to an integer + * using rounding mode rm, or ROUNDING_MODE if rm is omitted. + * + * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive. + * + * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {rm}' + */ + P.integerValue = function (rm) { + var n = new BigNumber(this); + if (rm == null) rm = ROUNDING_MODE; + else intCheck(rm, 0, 8); + return round(n, n.e + 1, rm); + }; + + + /* + * Return true if the value of this BigNumber is equal to the value of BigNumber(y, b), + * otherwise return false. + */ + P.isEqualTo = P.eq = function (y, b) { + return compare(this, new BigNumber(y, b)) === 0; + }; + + + /* + * Return true if the value of this BigNumber is a finite number, otherwise return false. + */ + P.isFinite = function () { + return !!this.c; + }; + + + /* + * Return true if the value of this BigNumber is greater than the value of BigNumber(y, b), + * otherwise return false. + */ + P.isGreaterThan = P.gt = function (y, b) { + return compare(this, new BigNumber(y, b)) > 0; + }; + + + /* + * Return true if the value of this BigNumber is greater than or equal to the value of + * BigNumber(y, b), otherwise return false. + */ + P.isGreaterThanOrEqualTo = P.gte = function (y, b) { + return (b = compare(this, new BigNumber(y, b))) === 1 || b === 0; + + }; + + + /* + * Return true if the value of this BigNumber is an integer, otherwise return false. + */ + P.isInteger = function () { + return !!this.c && bitFloor(this.e / LOG_BASE) > this.c.length - 2; + }; + + + /* + * Return true if the value of this BigNumber is less than the value of BigNumber(y, b), + * otherwise return false. + */ + P.isLessThan = P.lt = function (y, b) { + return compare(this, new BigNumber(y, b)) < 0; + }; + + + /* + * Return true if the value of this BigNumber is less than or equal to the value of + * BigNumber(y, b), otherwise return false. + */ + P.isLessThanOrEqualTo = P.lte = function (y, b) { + return (b = compare(this, new BigNumber(y, b))) === -1 || b === 0; + }; + + + /* + * Return true if the value of this BigNumber is NaN, otherwise return false. + */ + P.isNaN = function () { + return !this.s; + }; + + + /* + * Return true if the value of this BigNumber is negative, otherwise return false. + */ + P.isNegative = function () { + return this.s < 0; + }; + + + /* + * Return true if the value of this BigNumber is positive, otherwise return false. + */ + P.isPositive = function () { + return this.s > 0; + }; + + + /* + * Return true if the value of this BigNumber is 0 or -0, otherwise return false. + */ + P.isZero = function () { + return !!this.c && this.c[0] == 0; + }; + + + /* + * n - 0 = n + * n - N = N + * n - I = -I + * 0 - n = -n + * 0 - 0 = 0 + * 0 - N = N + * 0 - I = -I + * N - n = N + * N - 0 = N + * N - N = N + * N - I = N + * I - n = I + * I - 0 = I + * I - N = N + * I - I = N + * + * Return a new BigNumber whose value is the value of this BigNumber minus the value of + * BigNumber(y, b). + */ + P.minus = function (y, b) { + var i, j, t, xLTy, + x = this, + a = x.s; + + y = new BigNumber(y, b); + b = y.s; + + // Either NaN? + if (!a || !b) return new BigNumber(NaN); + + // Signs differ? + if (a != b) { + y.s = -b; + return x.plus(y); + } + + var xe = x.e / LOG_BASE, + ye = y.e / LOG_BASE, + xc = x.c, + yc = y.c; + + if (!xe || !ye) { + + // Either Infinity? + if (!xc || !yc) return xc ? (y.s = -b, y) : new BigNumber(yc ? x : NaN); + + // Either zero? + if (!xc[0] || !yc[0]) { + + // Return y if y is non-zero, x if x is non-zero, or zero if both are zero. + return yc[0] ? (y.s = -b, y) : new BigNumber(xc[0] ? x : + + // IEEE 754 (2008) 6.3: n - n = -0 when rounding to -Infinity + ROUNDING_MODE == 3 ? -0 : 0); + } + } + + xe = bitFloor(xe); + ye = bitFloor(ye); + xc = xc.slice(); + + // Determine which is the bigger number. + if (a = xe - ye) { + + if (xLTy = a < 0) { + a = -a; + t = xc; + } else { + ye = xe; + t = yc; + } + + t.reverse(); + + // Prepend zeros to equalise exponents. + for (b = a; b--; t.push(0)); + t.reverse(); + } else { + + // Exponents equal. Check digit by digit. + j = (xLTy = (a = xc.length) < (b = yc.length)) ? a : b; + + for (a = b = 0; b < j; b++) { + + if (xc[b] != yc[b]) { + xLTy = xc[b] < yc[b]; + break; + } + } + } + + // x < y? Point xc to the array of the bigger number. + if (xLTy) { + t = xc; + xc = yc; + yc = t; + y.s = -y.s; + } + + b = (j = yc.length) - (i = xc.length); + + // Append zeros to xc if shorter. + // No need to add zeros to yc if shorter as subtract only needs to start at yc.length. + if (b > 0) for (; b--; xc[i++] = 0); + b = BASE - 1; + + // Subtract yc from xc. + for (; j > a;) { + + if (xc[--j] < yc[j]) { + for (i = j; i && !xc[--i]; xc[i] = b); + --xc[i]; + xc[j] += BASE; + } + + xc[j] -= yc[j]; + } + + // Remove leading zeros and adjust exponent accordingly. + for (; xc[0] == 0; xc.splice(0, 1), --ye); + + // Zero? + if (!xc[0]) { + + // Following IEEE 754 (2008) 6.3, + // n - n = +0 but n - n = -0 when rounding towards -Infinity. + y.s = ROUNDING_MODE == 3 ? -1 : 1; + y.c = [y.e = 0]; + return y; + } + + // No need to check for Infinity as +x - +y != Infinity && -x - -y != Infinity + // for finite x and y. + return normalise(y, xc, ye); + }; + + + /* + * n % 0 = N + * n % N = N + * n % I = n + * 0 % n = 0 + * -0 % n = -0 + * 0 % 0 = N + * 0 % N = N + * 0 % I = 0 + * N % n = N + * N % 0 = N + * N % N = N + * N % I = N + * I % n = N + * I % 0 = N + * I % N = N + * I % I = N + * + * Return a new BigNumber whose value is the value of this BigNumber modulo the value of + * BigNumber(y, b). The result depends on the value of MODULO_MODE. + */ + P.modulo = P.mod = function (y, b) { + var q, s, + x = this; + + y = new BigNumber(y, b); + + // Return NaN if x is Infinity or NaN, or y is NaN or zero. + if (!x.c || !y.s || y.c && !y.c[0]) { + return new BigNumber(NaN); + + // Return x if y is Infinity or x is zero. + } else if (!y.c || x.c && !x.c[0]) { + return new BigNumber(x); + } + + if (MODULO_MODE == 9) { + + // Euclidian division: q = sign(y) * floor(x / abs(y)) + // r = x - qy where 0 <= r < abs(y) + s = y.s; + y.s = 1; + q = div(x, y, 0, 3); + y.s = s; + q.s *= s; + } else { + q = div(x, y, 0, MODULO_MODE); + } + + y = x.minus(q.times(y)); + + // To match JavaScript %, ensure sign of zero is sign of dividend. + if (!y.c[0] && MODULO_MODE == 1) y.s = x.s; + + return y; + }; + + + /* + * n * 0 = 0 + * n * N = N + * n * I = I + * 0 * n = 0 + * 0 * 0 = 0 + * 0 * N = N + * 0 * I = N + * N * n = N + * N * 0 = N + * N * N = N + * N * I = N + * I * n = I + * I * 0 = N + * I * N = N + * I * I = I + * + * Return a new BigNumber whose value is the value of this BigNumber multiplied by the value + * of BigNumber(y, b). + */ + P.multipliedBy = P.times = function (y, b) { + var c, e, i, j, k, m, xcL, xlo, xhi, ycL, ylo, yhi, zc, + base, sqrtBase, + x = this, + xc = x.c, + yc = (y = new BigNumber(y, b)).c; + + // Either NaN, ±Infinity or ±0? + if (!xc || !yc || !xc[0] || !yc[0]) { + + // Return NaN if either is NaN, or one is 0 and the other is Infinity. + if (!x.s || !y.s || xc && !xc[0] && !yc || yc && !yc[0] && !xc) { + y.c = y.e = y.s = null; + } else { + y.s *= x.s; + + // Return ±Infinity if either is ±Infinity. + if (!xc || !yc) { + y.c = y.e = null; + + // Return ±0 if either is ±0. + } else { + y.c = [0]; + y.e = 0; + } + } + + return y; + } + + e = bitFloor(x.e / LOG_BASE) + bitFloor(y.e / LOG_BASE); + y.s *= x.s; + xcL = xc.length; + ycL = yc.length; + + // Ensure xc points to longer array and xcL to its length. + if (xcL < ycL) { + zc = xc; + xc = yc; + yc = zc; + i = xcL; + xcL = ycL; + ycL = i; + } + + // Initialise the result array with zeros. + for (i = xcL + ycL, zc = []; i--; zc.push(0)); + + base = BASE; + sqrtBase = SQRT_BASE; + + for (i = ycL; --i >= 0;) { + c = 0; + ylo = yc[i] % sqrtBase; + yhi = yc[i] / sqrtBase | 0; + + for (k = xcL, j = i + k; j > i;) { + xlo = xc[--k] % sqrtBase; + xhi = xc[k] / sqrtBase | 0; + m = yhi * xlo + xhi * ylo; + xlo = ylo * xlo + ((m % sqrtBase) * sqrtBase) + zc[j] + c; + c = (xlo / base | 0) + (m / sqrtBase | 0) + yhi * xhi; + zc[j--] = xlo % base; + } + + zc[j] = c; + } + + if (c) { + ++e; + } else { + zc.splice(0, 1); + } + + return normalise(y, zc, e); + }; + + + /* + * Return a new BigNumber whose value is the value of this BigNumber negated, + * i.e. multiplied by -1. + */ + P.negated = function () { + var x = new BigNumber(this); + x.s = -x.s || null; + return x; + }; + + + /* + * n + 0 = n + * n + N = N + * n + I = I + * 0 + n = n + * 0 + 0 = 0 + * 0 + N = N + * 0 + I = I + * N + n = N + * N + 0 = N + * N + N = N + * N + I = N + * I + n = I + * I + 0 = I + * I + N = N + * I + I = I + * + * Return a new BigNumber whose value is the value of this BigNumber plus the value of + * BigNumber(y, b). + */ + P.plus = function (y, b) { + var t, + x = this, + a = x.s; + + y = new BigNumber(y, b); + b = y.s; + + // Either NaN? + if (!a || !b) return new BigNumber(NaN); + + // Signs differ? + if (a != b) { + y.s = -b; + return x.minus(y); + } + + var xe = x.e / LOG_BASE, + ye = y.e / LOG_BASE, + xc = x.c, + yc = y.c; + + if (!xe || !ye) { + + // Return ±Infinity if either ±Infinity. + if (!xc || !yc) return new BigNumber(a / 0); + + // Either zero? + // Return y if y is non-zero, x if x is non-zero, or zero if both are zero. + if (!xc[0] || !yc[0]) return yc[0] ? y : new BigNumber(xc[0] ? x : a * 0); + } + + xe = bitFloor(xe); + ye = bitFloor(ye); + xc = xc.slice(); + + // Prepend zeros to equalise exponents. Faster to use reverse then do unshifts. + if (a = xe - ye) { + if (a > 0) { + ye = xe; + t = yc; + } else { + a = -a; + t = xc; + } + + t.reverse(); + for (; a--; t.push(0)); + t.reverse(); + } + + a = xc.length; + b = yc.length; + + // Point xc to the longer array, and b to the shorter length. + if (a - b < 0) { + t = yc; + yc = xc; + xc = t; + b = a; + } + + // Only start adding at yc.length - 1 as the further digits of xc can be ignored. + for (a = 0; b;) { + a = (xc[--b] = xc[b] + yc[b] + a) / BASE | 0; + xc[b] = BASE === xc[b] ? 0 : xc[b] % BASE; + } + + if (a) { + xc = [a].concat(xc); + ++ye; + } + + // No need to check for zero, as +x + +y != 0 && -x + -y != 0 + // ye = MAX_EXP + 1 possible + return normalise(y, xc, ye); + }; + + + /* + * If sd is undefined or null or true or false, return the number of significant digits of + * the value of this BigNumber, or null if the value of this BigNumber is ±Infinity or NaN. + * If sd is true include integer-part trailing zeros in the count. + * + * Otherwise, if sd is a number, return a new BigNumber whose value is the value of this + * BigNumber rounded to a maximum of sd significant digits using rounding mode rm, or + * ROUNDING_MODE if rm is omitted. + * + * sd {number|boolean} number: significant digits: integer, 1 to MAX inclusive. + * boolean: whether to count integer-part trailing zeros: true or false. + * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive. + * + * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {sd|rm}' + */ + P.precision = P.sd = function (sd, rm) { + var c, n, v, + x = this; + + if (sd != null && sd !== !!sd) { + intCheck(sd, 1, MAX); + if (rm == null) rm = ROUNDING_MODE; + else intCheck(rm, 0, 8); + + return round(new BigNumber(x), sd, rm); + } + + if (!(c = x.c)) return null; + v = c.length - 1; + n = v * LOG_BASE + 1; + + if (v = c[v]) { + + // Subtract the number of trailing zeros of the last element. + for (; v % 10 == 0; v /= 10, n--); + + // Add the number of digits of the first element. + for (v = c[0]; v >= 10; v /= 10, n++); + } + + if (sd && x.e + 1 > n) n = x.e + 1; + + return n; + }; + + + /* + * Return a new BigNumber whose value is the value of this BigNumber shifted by k places + * (powers of 10). Shift to the right if n > 0, and to the left if n < 0. + * + * k {number} Integer, -MAX_SAFE_INTEGER to MAX_SAFE_INTEGER inclusive. + * + * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {k}' + */ + P.shiftedBy = function (k) { + intCheck(k, -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER); + return this.times('1e' + k); + }; + + + /* + * sqrt(-n) = N + * sqrt(N) = N + * sqrt(-I) = N + * sqrt(I) = I + * sqrt(0) = 0 + * sqrt(-0) = -0 + * + * Return a new BigNumber whose value is the square root of the value of this BigNumber, + * rounded according to DECIMAL_PLACES and ROUNDING_MODE. + */ + P.squareRoot = P.sqrt = function () { + var m, n, r, rep, t, + x = this, + c = x.c, + s = x.s, + e = x.e, + dp = DECIMAL_PLACES + 4, + half = new BigNumber('0.5'); + + // Negative/NaN/Infinity/zero? + if (s !== 1 || !c || !c[0]) { + return new BigNumber(!s || s < 0 && (!c || c[0]) ? NaN : c ? x : 1 / 0); + } + + // Initial estimate. + s = Math.sqrt(+valueOf(x)); + + // Math.sqrt underflow/overflow? + // Pass x to Math.sqrt as integer, then adjust the exponent of the result. + if (s == 0 || s == 1 / 0) { + n = coeffToString(c); + if ((n.length + e) % 2 == 0) n += '0'; + s = Math.sqrt(+n); + e = bitFloor((e + 1) / 2) - (e < 0 || e % 2); + + if (s == 1 / 0) { + n = '5e' + e; + } else { + n = s.toExponential(); + n = n.slice(0, n.indexOf('e') + 1) + e; + } + + r = new BigNumber(n); + } else { + r = new BigNumber(s + ''); + } + + // Check for zero. + // r could be zero if MIN_EXP is changed after the this value was created. + // This would cause a division by zero (x/t) and hence Infinity below, which would cause + // coeffToString to throw. + if (r.c[0]) { + e = r.e; + s = e + dp; + if (s < 3) s = 0; + + // Newton-Raphson iteration. + for (; ;) { + t = r; + r = half.times(t.plus(div(x, t, dp, 1))); + + if (coeffToString(t.c).slice(0, s) === (n = coeffToString(r.c)).slice(0, s)) { + + // The exponent of r may here be one less than the final result exponent, + // e.g 0.0009999 (e-4) --> 0.001 (e-3), so adjust s so the rounding digits + // are indexed correctly. + if (r.e < e) --s; + n = n.slice(s - 3, s + 1); + + // The 4th rounding digit may be in error by -1 so if the 4 rounding digits + // are 9999 or 4999 (i.e. approaching a rounding boundary) continue the + // iteration. + if (n == '9999' || !rep && n == '4999') { + + // On the first iteration only, check to see if rounding up gives the + // exact result as the nines may infinitely repeat. + if (!rep) { + round(t, t.e + DECIMAL_PLACES + 2, 0); + + if (t.times(t).eq(x)) { + r = t; + break; + } + } + + dp += 4; + s += 4; + rep = 1; + } else { + + // If rounding digits are null, 0{0,4} or 50{0,3}, check for exact + // result. If not, then there are further digits and m will be truthy. + if (!+n || !+n.slice(1) && n.charAt(0) == '5') { + + // Truncate to the first rounding digit. + round(r, r.e + DECIMAL_PLACES + 2, 1); + m = !r.times(r).eq(x); + } + + break; + } + } + } + } + + return round(r, r.e + DECIMAL_PLACES + 1, ROUNDING_MODE, m); + }; + + + /* + * Return a string representing the value of this BigNumber in exponential notation and + * rounded using ROUNDING_MODE to dp fixed decimal places. + * + * [dp] {number} Decimal places. Integer, 0 to MAX inclusive. + * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive. + * + * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {dp|rm}' + */ + P.toExponential = function (dp, rm) { + if (dp != null) { + intCheck(dp, 0, MAX); + dp++; + } + return format(this, dp, rm, 1); + }; + + + /* + * Return a string representing the value of this BigNumber in fixed-point notation rounding + * to dp fixed decimal places using rounding mode rm, or ROUNDING_MODE if rm is omitted. + * + * Note: as with JavaScript's number type, (-0).toFixed(0) is '0', + * but e.g. (-0.00001).toFixed(0) is '-0'. + * + * [dp] {number} Decimal places. Integer, 0 to MAX inclusive. + * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive. + * + * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {dp|rm}' + */ + P.toFixed = function (dp, rm) { + if (dp != null) { + intCheck(dp, 0, MAX); + dp = dp + this.e + 1; + } + return format(this, dp, rm); + }; + + + /* + * Return a string representing the value of this BigNumber in fixed-point notation rounded + * using rm or ROUNDING_MODE to dp decimal places, and formatted according to the properties + * of the format or FORMAT object (see BigNumber.set). + * + * The formatting object may contain some or all of the properties shown below. + * + * FORMAT = { + * prefix: '', + * groupSize: 3, + * secondaryGroupSize: 0, + * groupSeparator: ',', + * decimalSeparator: '.', + * fractionGroupSize: 0, + * fractionGroupSeparator: '\xA0', // non-breaking space + * suffix: '' + * }; + * + * [dp] {number} Decimal places. Integer, 0 to MAX inclusive. + * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive. + * [format] {object} Formatting options. See FORMAT pbject above. + * + * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {dp|rm}' + * '[BigNumber Error] Argument not an object: {format}' + */ + P.toFormat = function (dp, rm, format) { + var str, + x = this; + + if (format == null) { + if (dp != null && rm && typeof rm == 'object') { + format = rm; + rm = null; + } else if (dp && typeof dp == 'object') { + format = dp; + dp = rm = null; + } else { + format = FORMAT; + } + } else if (typeof format != 'object') { + throw Error + (bignumberError + 'Argument not an object: ' + format); + } + + str = x.toFixed(dp, rm); + + if (x.c) { + var i, + arr = str.split('.'), + g1 = +format.groupSize, + g2 = +format.secondaryGroupSize, + groupSeparator = format.groupSeparator || '', + intPart = arr[0], + fractionPart = arr[1], + isNeg = x.s < 0, + intDigits = isNeg ? intPart.slice(1) : intPart, + len = intDigits.length; + + if (g2) { + i = g1; + g1 = g2; + g2 = i; + len -= i; + } + + if (g1 > 0 && len > 0) { + i = len % g1 || g1; + intPart = intDigits.substr(0, i); + for (; i < len; i += g1) intPart += groupSeparator + intDigits.substr(i, g1); + if (g2 > 0) intPart += groupSeparator + intDigits.slice(i); + if (isNeg) intPart = '-' + intPart; + } + + str = fractionPart + ? intPart + (format.decimalSeparator || '') + ((g2 = +format.fractionGroupSize) + ? fractionPart.replace(new RegExp('\\d{' + g2 + '}\\B', 'g'), + '$&' + (format.fractionGroupSeparator || '')) + : fractionPart) + : intPart; + } + + return (format.prefix || '') + str + (format.suffix || ''); + }; + + + /* + * Return an array of two BigNumbers representing the value of this BigNumber as a simple + * fraction with an integer numerator and an integer denominator. + * The denominator will be a positive non-zero value less than or equal to the specified + * maximum denominator. If a maximum denominator is not specified, the denominator will be + * the lowest value necessary to represent the number exactly. + * + * [md] {number|string|BigNumber} Integer >= 1, or Infinity. The maximum denominator. + * + * '[BigNumber Error] Argument {not an integer|out of range} : {md}' + */ + P.toFraction = function (md) { + var d, d0, d1, d2, e, exp, n, n0, n1, q, r, s, + x = this, + xc = x.c; + + if (md != null) { + n = new BigNumber(md); + + // Throw if md is less than one or is not an integer, unless it is Infinity. + if (!n.isInteger() && (n.c || n.s !== 1) || n.lt(ONE)) { + throw Error + (bignumberError + 'Argument ' + + (n.isInteger() ? 'out of range: ' : 'not an integer: ') + valueOf(n)); + } + } + + if (!xc) return new BigNumber(x); + + d = new BigNumber(ONE); + n1 = d0 = new BigNumber(ONE); + d1 = n0 = new BigNumber(ONE); + s = coeffToString(xc); + + // Determine initial denominator. + // d is a power of 10 and the minimum max denominator that specifies the value exactly. + e = d.e = s.length - x.e - 1; + d.c[0] = POWS_TEN[(exp = e % LOG_BASE) < 0 ? LOG_BASE + exp : exp]; + md = !md || n.comparedTo(d) > 0 ? (e > 0 ? d : n1) : n; + + exp = MAX_EXP; + MAX_EXP = 1 / 0; + n = new BigNumber(s); + + // n0 = d1 = 0 + n0.c[0] = 0; + + for (; ;) { + q = div(n, d, 0, 1); + d2 = d0.plus(q.times(d1)); + if (d2.comparedTo(md) == 1) break; + d0 = d1; + d1 = d2; + n1 = n0.plus(q.times(d2 = n1)); + n0 = d2; + d = n.minus(q.times(d2 = d)); + n = d2; + } + + d2 = div(md.minus(d0), d1, 0, 1); + n0 = n0.plus(d2.times(n1)); + d0 = d0.plus(d2.times(d1)); + n0.s = n1.s = x.s; + e = e * 2; + + // Determine which fraction is closer to x, n0/d0 or n1/d1 + r = div(n1, d1, e, ROUNDING_MODE).minus(x).abs().comparedTo( + div(n0, d0, e, ROUNDING_MODE).minus(x).abs()) < 1 ? [n1, d1] : [n0, d0]; + + MAX_EXP = exp; + + return r; + }; + + + /* + * Return the value of this BigNumber converted to a number primitive. + */ + P.toNumber = function () { + return +valueOf(this); + }; + + + /* + * Return a string representing the value of this BigNumber rounded to sd significant digits + * using rounding mode rm or ROUNDING_MODE. If sd is less than the number of digits + * necessary to represent the integer part of the value in fixed-point notation, then use + * exponential notation. + * + * [sd] {number} Significant digits. Integer, 1 to MAX inclusive. + * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive. + * + * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {sd|rm}' + */ + P.toPrecision = function (sd, rm) { + if (sd != null) intCheck(sd, 1, MAX); + return format(this, sd, rm, 2); + }; + + + /* + * Return a string representing the value of this BigNumber in base b, or base 10 if b is + * omitted. If a base is specified, including base 10, round according to DECIMAL_PLACES and + * ROUNDING_MODE. If a base is not specified, and this BigNumber has a positive exponent + * that is equal to or greater than TO_EXP_POS, or a negative exponent equal to or less than + * TO_EXP_NEG, return exponential notation. + * + * [b] {number} Integer, 2 to ALPHABET.length inclusive. + * + * '[BigNumber Error] Base {not a primitive number|not an integer|out of range}: {b}' + */ + P.toString = function (b) { + var str, + n = this, + s = n.s, + e = n.e; + + // Infinity or NaN? + if (e === null) { + if (s) { + str = 'Infinity'; + if (s < 0) str = '-' + str; + } else { + str = 'NaN'; + } + } else { + if (b == null) { + str = e <= TO_EXP_NEG || e >= TO_EXP_POS + ? toExponential(coeffToString(n.c), e) + : toFixedPoint(coeffToString(n.c), e, '0'); + } else if (b === 10 && alphabetHasNormalDecimalDigits) { + n = round(new BigNumber(n), DECIMAL_PLACES + e + 1, ROUNDING_MODE); + str = toFixedPoint(coeffToString(n.c), n.e, '0'); + } else { + intCheck(b, 2, ALPHABET.length, 'Base'); + str = convertBase(toFixedPoint(coeffToString(n.c), e, '0'), 10, b, s, true); + } + + if (s < 0 && n.c[0]) str = '-' + str; + } + + return str; + }; + + + /* + * Return as toString, but do not accept a base argument, and include the minus sign for + * negative zero. + */ + P.valueOf = P.toJSON = function () { + return valueOf(this); + }; + + + P._isBigNumber = true; + + P[Symbol.toStringTag] = 'BigNumber'; + + // Node.js v10.12.0+ + P[Symbol.for('nodejs.util.inspect.custom')] = P.valueOf; + + if (configObject != null) BigNumber.set(configObject); + + return BigNumber; +} + + +// PRIVATE HELPER FUNCTIONS + +// These functions don't need access to variables, +// e.g. DECIMAL_PLACES, in the scope of the `clone` function above. + + +function bitFloor(n) { + var i = n | 0; + return n > 0 || n === i ? i : i - 1; +} + + +// Return a coefficient array as a string of base 10 digits. +function coeffToString(a) { + var s, z, + i = 1, + j = a.length, + r = a[0] + ''; + + for (; i < j;) { + s = a[i++] + ''; + z = LOG_BASE - s.length; + for (; z--; s = '0' + s); + r += s; + } + + // Determine trailing zeros. + for (j = r.length; r.charCodeAt(--j) === 48;); + + return r.slice(0, j + 1 || 1); +} + + +// Compare the value of BigNumbers x and y. +function compare(x, y) { + var a, b, + xc = x.c, + yc = y.c, + i = x.s, + j = y.s, + k = x.e, + l = y.e; + + // Either NaN? + if (!i || !j) return null; + + a = xc && !xc[0]; + b = yc && !yc[0]; + + // Either zero? + if (a || b) return a ? b ? 0 : -j : i; + + // Signs differ? + if (i != j) return i; + + a = i < 0; + b = k == l; + + // Either Infinity? + if (!xc || !yc) return b ? 0 : !xc ^ a ? 1 : -1; + + // Compare exponents. + if (!b) return k > l ^ a ? 1 : -1; + + j = (k = xc.length) < (l = yc.length) ? k : l; + + // Compare digit by digit. + for (i = 0; i < j; i++) if (xc[i] != yc[i]) return xc[i] > yc[i] ^ a ? 1 : -1; + + // Compare lengths. + return k == l ? 0 : k > l ^ a ? 1 : -1; +} + + +/* + * Check that n is a primitive number, an integer, and in range, otherwise throw. + */ +function intCheck(n, min, max, name) { + if (n < min || n > max || n !== mathfloor(n)) { + throw Error + (bignumberError + (name || 'Argument') + (typeof n == 'number' + ? n < min || n > max ? ' out of range: ' : ' not an integer: ' + : ' not a primitive number: ') + String(n)); + } +} + + +// Assumes finite n. +function isOdd(n) { + var k = n.c.length - 1; + return bitFloor(n.e / LOG_BASE) == k && n.c[k] % 2 != 0; +} + + +function toExponential(str, e) { + return (str.length > 1 ? str.charAt(0) + '.' + str.slice(1) : str) + + (e < 0 ? 'e' : 'e+') + e; +} + + +function toFixedPoint(str, e, z) { + var len, zs; + + // Negative exponent? + if (e < 0) { + + // Prepend zeros. + for (zs = z + '.'; ++e; zs += z); + str = zs + str; + + // Positive exponent + } else { + len = str.length; + + // Append zeros. + if (++e > len) { + for (zs = z, e -= len; --e; zs += z); + str += zs; + } else if (e < len) { + str = str.slice(0, e) + '.' + str.slice(e); + } + } + + return str; +} + + +// EXPORT + + +export var BigNumber = clone(); + +export default BigNumber; diff --git a/server/node_modules/bignumber.js/doc/API.html b/server/node_modules/bignumber.js/doc/API.html new file mode 100644 index 0000000..a16c034 --- /dev/null +++ b/server/node_modules/bignumber.js/doc/API.html @@ -0,0 +1,2249 @@ +<!DOCTYPE HTML> +<html> +<head> +<meta charset="utf-8"> +<meta http-equiv="X-UA-Compatible" content="IE=edge"> +<meta name="Author" content="M Mclaughlin"> +<title>bignumber.js API + + + + + + +
+ +

bignumber.js

+ +

A JavaScript library for arbitrary-precision arithmetic.

+

Hosted on GitHub.

+ +

API

+ +

+ See the README on GitHub for a + quick-start introduction. +

+

+ In all examples below, var and semicolons are not shown, and if a commented-out + value is in quotes it means toString has been called on the preceding expression. +

+ + +

CONSTRUCTOR

+ + +
+ BigNumberBigNumber(n [, base]) ⇒ BigNumber +
+

+ n: number|string|BigNumber
+ base: number: integer, 2 to 36 inclusive. (See + ALPHABET to extend this range). +

+

+ Returns a new instance of a BigNumber object with value n, where n + is a numeric value in the specified base, or base 10 if + base is omitted or is null or undefined. +

+

+ Note that the BigNnumber constructor accepts an n of type number purely + as a convenience so that string quotes don't have to be typed when entering literal values, + and that it is the toString value of n that is used rather than its + underlying binary floating point value converted to decimal. +

+
+x = new BigNumber(123.4567)                // '123.4567'
+// 'new' is optional
+y = BigNumber(x)                           // '123.4567'
+

+ If n is a base 10 value it can be in normal or exponential notation. + Values in other bases must be in normal notation. Values in any base can have fraction digits, + i.e. digits after the decimal point. +

+
+new BigNumber(43210)                       // '43210'
+new BigNumber('4.321e+4')                  // '43210'
+new BigNumber('-735.0918e-430')            // '-7.350918e-428'
+new BigNumber('123412421.234324', 5)       // '607236.557696'
+

+ Signed 0, signed Infinity and NaN are supported. +

+
+new BigNumber('-Infinity')                 // '-Infinity'
+new BigNumber(NaN)                         // 'NaN'
+new BigNumber(-0)                          // '0'
+new BigNumber('.5')                        // '0.5'
+new BigNumber('+2')                        // '2'
+

+ String values in hexadecimal literal form, e.g. '0xff' or '0xFF' + (but not '0xfF'), are valid, as are string values with the octal and binary + prefixs '0o' and '0b'. String values in octal literal form without + the prefix will be interpreted as decimals, e.g. '011' is interpreted as 11, not 9. +

+
+new BigNumber(-10110100.1, 2)              // '-180.5'
+new BigNumber('-0b10110100.1')             // '-180.5'
+new BigNumber('ff.8', 16)                  // '255.5'
+new BigNumber('0xff.8')                    // '255.5'
+

+ If a base is specified, n is rounded according to the current + DECIMAL_PLACES and + ROUNDING_MODE settings. This includes base + 10 so don't include a base parameter for decimal values unless + this behaviour is wanted. +

+
BigNumber.config({ DECIMAL_PLACES: 5 })
+new BigNumber(1.23456789)                  // '1.23456789'
+new BigNumber(1.23456789, 10)              // '1.23457'
+

An error is thrown if base is invalid. See Errors.

+

+ There is no limit to the number of digits of a value of type string (other than + that of JavaScript's maximum array size). See RANGE to set + the maximum and minimum possible exponent value of a BigNumber. +

+
+new BigNumber('5032485723458348569331745.33434346346912144534543')
+new BigNumber('4.321e10000000')
+

BigNumber NaN is returned if n is invalid + (unless BigNumber.DEBUG is true, see below).

+
+new BigNumber('.1*')                       // 'NaN'
+new BigNumber('blurgh')                    // 'NaN'
+new BigNumber(9, 2)                        // 'NaN'
+

+ To aid in debugging, if BigNumber.DEBUG is true then an error will + be thrown on an invalid n. An error will also be thrown if n is of + type number and has more than 15 significant digits, as calling + toString or valueOf on + these numbers may not result in the intended value. +

+
+console.log(823456789123456.3)            //  823456789123456.2
+new BigNumber(823456789123456.3)          // '823456789123456.2'
+BigNumber.DEBUG = true
+// '[BigNumber Error] Number primitive has more than 15 significant digits'
+new BigNumber(823456789123456.3)
+// '[BigNumber Error] Not a base 2 number'
+new BigNumber(9, 2)
+

+ A BigNumber can also be created from an object literal. + Use isBigNumber to check that it is well-formed. +

+
new BigNumber({ s: 1, e: 2, c: [ 777, 12300000000000 ], _isBigNumber: true })    // '777.123'
+ + + + +

Methods

+

The static methods of a BigNumber constructor.

+ + + + +
clone + .clone([object]) ⇒ BigNumber constructor +
+

object: object

+

+ Returns a new independent BigNumber constructor with configuration as described by + object (see config), or with the default + configuration if object is null or undefined. +

+

+ Throws if object is not an object. See Errors. +

+
BigNumber.config({ DECIMAL_PLACES: 5 })
+BN = BigNumber.clone({ DECIMAL_PLACES: 9 })
+
+x = new BigNumber(1)
+y = new BN(1)
+
+x.div(3)                        // 0.33333
+y.div(3)                        // 0.333333333
+
+// BN = BigNumber.clone({ DECIMAL_PLACES: 9 }) is equivalent to:
+BN = BigNumber.clone()
+BN.config({ DECIMAL_PLACES: 9 })
+ + + +
configset([object]) ⇒ object
+

+ object: object: an object that contains some or all of the following + properties. +

+

Configures the settings for this particular BigNumber constructor.

+ +
+
DECIMAL_PLACES
+
+ number: integer, 0 to 1e+9 inclusive
+ Default value: 20 +
+
+ The maximum number of decimal places of the results of operations involving + division, i.e. division, square root and base conversion operations, and power operations + with negative exponents.
+
+
+
BigNumber.config({ DECIMAL_PLACES: 5 })
+BigNumber.set({ DECIMAL_PLACES: 5 })    // equivalent
+
+ + + +
ROUNDING_MODE
+
+ number: integer, 0 to 8 inclusive
+ Default value: 4 (ROUND_HALF_UP) +
+
+ The rounding mode used in the above operations and the default rounding mode of + decimalPlaces, + precision, + toExponential, + toFixed, + toFormat and + toPrecision. +
+
The modes are available as enumerated properties of the BigNumber constructor.
+
+
BigNumber.config({ ROUNDING_MODE: 0 })
+BigNumber.set({ ROUNDING_MODE: BigNumber.ROUND_UP })    // equivalent
+
+ + + +
EXPONENTIAL_AT
+
+ number: integer, magnitude 0 to 1e+9 inclusive, or +
+ number[]: [ integer -1e+9 to 0 inclusive, integer + 0 to 1e+9 inclusive ]
+ Default value: [-7, 20] +
+
+ The exponent value(s) at which toString returns exponential notation. +
+
+ If a single number is assigned, the value is the exponent magnitude.
+ If an array of two numbers is assigned then the first number is the negative exponent + value at and beneath which exponential notation is used, and the second number is the + positive exponent value at and above which the same. +
+
+ For example, to emulate JavaScript numbers in terms of the exponent values at which they + begin to use exponential notation, use [-7, 20]. +
+
+
BigNumber.config({ EXPONENTIAL_AT: 2 })
+new BigNumber(12.3)         // '12.3'        e is only 1
+new BigNumber(123)          // '1.23e+2'
+new BigNumber(0.123)        // '0.123'       e is only -1
+new BigNumber(0.0123)       // '1.23e-2'
+
+BigNumber.config({ EXPONENTIAL_AT: [-7, 20] })
+new BigNumber(123456789)    // '123456789'   e is only 8
+new BigNumber(0.000000123)  // '1.23e-7'
+
+// Almost never return exponential notation:
+BigNumber.config({ EXPONENTIAL_AT: 1e+9 })
+
+// Always return exponential notation:
+BigNumber.config({ EXPONENTIAL_AT: 0 })
+
+
+ Regardless of the value of EXPONENTIAL_AT, the toFixed method + will always return a value in normal notation and the toExponential method + will always return a value in exponential form. +
+
+ Calling toString with a base argument, e.g. toString(10), will + also always return normal notation. +
+ + + +
RANGE
+
+ number: integer, magnitude 1 to 1e+9 inclusive, or +
+ number[]: [ integer -1e+9 to -1 inclusive, integer + 1 to 1e+9 inclusive ]
+ Default value: [-1e+9, 1e+9] +
+
+ The exponent value(s) beyond which overflow to Infinity and underflow to + zero occurs. +
+
+ If a single number is assigned, it is the maximum exponent magnitude: values wth a + positive exponent of greater magnitude become Infinity and those with a + negative exponent of greater magnitude become zero. +
+ If an array of two numbers is assigned then the first number is the negative exponent + limit and the second number is the positive exponent limit. +
+
+ For example, to emulate JavaScript numbers in terms of the exponent values at which they + become zero and Infinity, use [-324, 308]. +
+
+
BigNumber.config({ RANGE: 500 })
+BigNumber.config().RANGE     // [ -500, 500 ]
+new BigNumber('9.999e499')   // '9.999e+499'
+new BigNumber('1e500')       // 'Infinity'
+new BigNumber('1e-499')      // '1e-499'
+new BigNumber('1e-500')      // '0'
+
+BigNumber.config({ RANGE: [-3, 4] })
+new BigNumber(99999)         // '99999'      e is only 4
+new BigNumber(100000)        // 'Infinity'   e is 5
+new BigNumber(0.001)         // '0.01'       e is only -3
+new BigNumber(0.0001)        // '0'          e is -4
+
+
+ The largest possible magnitude of a finite BigNumber is + 9.999...e+1000000000.
+ The smallest possible magnitude of a non-zero BigNumber is 1e-1000000000. +
+ + + +
CRYPTO
+
+ boolean: true or false.
+ Default value: false +
+
+ The value that determines whether cryptographically-secure pseudo-random number + generation is used. +
+
+ If CRYPTO is set to true then the + random method will generate random digits using + crypto.getRandomValues in browsers that support it, or + crypto.randomBytes if using Node.js. +
+
+ If neither function is supported by the host environment then attempting to set + CRYPTO to true will fail and an exception will be thrown. +
+
+ If CRYPTO is false then the source of randomness used will be + Math.random (which is assumed to generate at least 30 bits of + randomness). +
+
See random.
+
+
+// Node.js
+const crypto = require('crypto');   // CommonJS
+import * as crypto from 'crypto';   // ES module
+
+global.crypto = crypto;
+
+BigNumber.config({ CRYPTO: true })
+BigNumber.config().CRYPTO       // true
+BigNumber.random()              // 0.54340758610486147524
+
+ + + +
MODULO_MODE
+
+ number: integer, 0 to 9 inclusive
+ Default value: 1 (ROUND_DOWN) +
+
The modulo mode used when calculating the modulus: a mod n.
+
+ The quotient, q = a / n, is calculated according to the + ROUNDING_MODE that corresponds to the chosen + MODULO_MODE. +
+
The remainder, r, is calculated as: r = a - n * q.
+
+ The modes that are most commonly used for the modulus/remainder operation are shown in + the following table. Although the other rounding modes can be used, they may not give + useful results. +
+
+ + + + + + + + + + + + + + + + + + + + + + +
PropertyValueDescription
ROUND_UP0 + The remainder is positive if the dividend is negative, otherwise it is negative. +
ROUND_DOWN1 + The remainder has the same sign as the dividend.
+ This uses 'truncating division' and matches the behaviour of JavaScript's + remainder operator %. +
ROUND_FLOOR3 + The remainder has the same sign as the divisor.
+ This matches Python's % operator. +
ROUND_HALF_EVEN6The IEEE 754 remainder function.
EUCLID9 + The remainder is always positive. Euclidian division:
+ q = sign(n) * floor(a / abs(n)) +
+
+
+ The rounding/modulo modes are available as enumerated properties of the BigNumber + constructor. +
+
See modulo.
+
+
BigNumber.config({ MODULO_MODE: BigNumber.EUCLID })
+BigNumber.config({ MODULO_MODE: 9 })          // equivalent
+
+ + + +
POW_PRECISION
+
+ number: integer, 0 to 1e+9 inclusive.
+ Default value: 0 +
+
+ The maximum precision, i.e. number of significant digits, of the result of the power + operation (unless a modulus is specified). +
+
If set to 0, the number of significant digits will not be limited.
+
See exponentiatedBy.
+
BigNumber.config({ POW_PRECISION: 100 })
+ + + +
FORMAT
+
object
+
+ The FORMAT object configures the format of the string returned by the + toFormat method. +
+
+ The example below shows the properties of the FORMAT object that are + recognised, and their default values. +
+
+ Unlike the other configuration properties, the values of the properties of the + FORMAT object will not be checked for validity. The existing + FORMAT object will simply be replaced by the object that is passed in. + The object can include any number of the properties shown below. +
+
See toFormat for examples of usage.
+
+
+BigNumber.config({
+  FORMAT: {
+    // string to prepend
+    prefix: '',
+    // decimal separator
+    decimalSeparator: '.',
+    // grouping separator of the integer part
+    groupSeparator: ',',
+    // primary grouping size of the integer part
+    groupSize: 3,
+    // secondary grouping size of the integer part
+    secondaryGroupSize: 0,
+    // grouping separator of the fraction part
+    fractionGroupSeparator: ' ',
+    // grouping size of the fraction part
+    fractionGroupSize: 0,
+    // string to append
+    suffix: ''
+  }
+});
+
+ + + +
ALPHABET
+
+ string
+ Default value: '0123456789abcdefghijklmnopqrstuvwxyz' +
+
+ The alphabet used for base conversion. The length of the alphabet corresponds to the + maximum value of the base argument that can be passed to the + BigNumber constructor or + toString. +
+
+ There is no maximum length for the alphabet, but it must be at least 2 characters long, and + it must not contain whitespace or a repeated character, or the sign indicators + '+' and '-', or the decimal separator '.'. +
+
+
// duodecimal (base 12)
+BigNumber.config({ ALPHABET: '0123456789TE' })
+x = new BigNumber('T', 12)
+x.toString()                // '10'
+x.toString(12)              // 'T'
+
+ + + +
+

+

Returns an object with the above properties and their current values.

+

+ Throws if object is not an object, or if an invalid value is assigned to + one or more of the above properties. See Errors. +

+
+BigNumber.config({
+  DECIMAL_PLACES: 40,
+  ROUNDING_MODE: BigNumber.ROUND_HALF_CEIL,
+  EXPONENTIAL_AT: [-10, 20],
+  RANGE: [-500, 500],
+  CRYPTO: true,
+  MODULO_MODE: BigNumber.ROUND_FLOOR,
+  POW_PRECISION: 80,
+  FORMAT: {
+    groupSize: 3,
+    groupSeparator: ' ',
+    decimalSeparator: ','
+  },
+  ALPHABET: '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_'
+});
+
+obj = BigNumber.config();
+obj.DECIMAL_PLACES        // 40
+obj.RANGE                 // [-500, 500]
+ + + +
+ isBigNumber.isBigNumber(value) ⇒ boolean +
+

value: any

+

+ Returns true if value is a BigNumber instance, otherwise returns + false. +

+
x = 42
+y = new BigNumber(x)
+
+BigNumber.isBigNumber(x)             // false
+y instanceof BigNumber               // true
+BigNumber.isBigNumber(y)             // true
+
+BN = BigNumber.clone();
+z = new BN(x)
+z instanceof BigNumber               // false
+BigNumber.isBigNumber(z)             // true
+

+ If value is a BigNumber instance and BigNumber.DEBUG is true, + then this method will also check if value is well-formed, and throw if it is not. + See Errors. +

+

+ The check can be useful if creating a BigNumber from an object literal. + See BigNumber. +

+
+x = new BigNumber(10)
+
+// Change x.c to an illegitimate value.
+x.c = NaN
+
+BigNumber.DEBUG = false
+
+// No error.
+BigNumber.isBigNumber(x)    // true
+
+BigNumber.DEBUG = true
+
+// Error.
+BigNumber.isBigNumber(x)    // '[BigNumber Error] Invalid BigNumber'
+ + + +
maximum.max(n...) ⇒ BigNumber
+

+ n: number|string|BigNumber
+ See BigNumber for further parameter details. +

+

+ Returns a BigNumber whose value is the maximum of the arguments. +

+

The return value is always exact and unrounded.

+
x = new BigNumber('3257869345.0378653')
+BigNumber.maximum(4e9, x, '123456789.9')      // '4000000000'
+
+arr = [12, '13', new BigNumber(14)]
+BigNumber.max.apply(null, arr)                // '14'
+ + + +
minimum.min(n...) ⇒ BigNumber
+

+ n: number|string|BigNumber
+ See BigNumber for further parameter details. +

+

+ Returns a BigNumber whose value is the minimum of the arguments. +

+

The return value is always exact and unrounded.

+
x = new BigNumber('3257869345.0378653')
+BigNumber.minimum(4e9, x, '123456789.9')      // '123456789.9'
+
+arr = [2, new BigNumber(-14), '-15.9999', -12]
+BigNumber.min.apply(null, arr)                // '-15.9999'
+ + + +
+ random.random([dp]) ⇒ BigNumber +
+

dp: number: integer, 0 to 1e+9 inclusive

+

+ Returns a new BigNumber with a pseudo-random value equal to or greater than 0 and + less than 1. +

+

+ The return value will have dp decimal places (or less if trailing zeros are + produced).
+ If dp is omitted then the number of decimal places will default to the current + DECIMAL_PLACES setting. +

+

+ Depending on the value of this BigNumber constructor's + CRYPTO setting and the support for the + crypto object in the host environment, the random digits of the return value are + generated by either Math.random (fastest), crypto.getRandomValues + (Web Cryptography API in recent browsers) or crypto.randomBytes (Node.js). +

+

+ To be able to set CRYPTO to true when using + Node.js, the crypto object must be available globally: +

+
// Node.js
+const crypto = require('crypto');   // CommonJS
+import * as crypto from 'crypto';   // ES module
+global.crypto = crypto;
+

+ If CRYPTO is true, i.e. one of the + crypto methods is to be used, the value of a returned BigNumber should be + cryptographically-secure and statistically indistinguishable from a random value. +

+

+ Throws if dp is invalid. See Errors. +

+
BigNumber.config({ DECIMAL_PLACES: 10 })
+BigNumber.random()              // '0.4117936847'
+BigNumber.random(20)            // '0.78193327636914089009'
+ + + +
sum.sum(n...) ⇒ BigNumber
+

+ n: number|string|BigNumber
+ See BigNumber for further parameter details. +

+

Returns a BigNumber whose value is the sum of the arguments.

+

The return value is always exact and unrounded.

+
x = new BigNumber('3257869345.0378653')
+BigNumber.sum(4e9, x, '123456789.9')      // '7381326134.9378653'
+
+arr = [2, new BigNumber(14), '15.9999', 12]
+BigNumber.sum.apply(null, arr)            // '43.9999'
+ + + +

Properties

+

+ The library's enumerated rounding modes are stored as properties of the constructor.
+ (They are not referenced internally by the library itself.) +

+

+ Rounding modes 0 to 6 (inclusive) are the same as those of Java's + BigDecimal class. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyValueDescription
ROUND_UP0Rounds away from zero
ROUND_DOWN1Rounds towards zero
ROUND_CEIL2Rounds towards Infinity
ROUND_FLOOR3Rounds towards -Infinity
ROUND_HALF_UP4 + Rounds towards nearest neighbour.
+ If equidistant, rounds away from zero +
ROUND_HALF_DOWN5 + Rounds towards nearest neighbour.
+ If equidistant, rounds towards zero +
ROUND_HALF_EVEN6 + Rounds towards nearest neighbour.
+ If equidistant, rounds towards even neighbour +
ROUND_HALF_CEIL7 + Rounds towards nearest neighbour.
+ If equidistant, rounds towards Infinity +
ROUND_HALF_FLOOR8 + Rounds towards nearest neighbour.
+ If equidistant, rounds towards -Infinity +
+
+BigNumber.config({ ROUNDING_MODE: BigNumber.ROUND_CEIL })
+BigNumber.config({ ROUNDING_MODE: 2 })     // equivalent
+ +
DEBUG
+

undefined|false|true

+

+ If BigNumber.DEBUG is set true then an error will be thrown + if this BigNumber constructor receives an invalid value, such as + a value of type number with more than 15 significant digits. + See BigNumber. +

+

+ An error will also be thrown if the isBigNumber + method receives a BigNumber that is not well-formed. + See isBigNumber. +

+
BigNumber.DEBUG = true
+ + +

INSTANCE

+ + +

Methods

+

The methods inherited by a BigNumber instance from its constructor's prototype object.

+

A BigNumber is immutable in the sense that it is not changed by its methods.

+

+ The treatment of ±0, ±Infinity and NaN is + consistent with how JavaScript treats these values. +

+

Many method names have a shorter alias.

+ + + +
absoluteValue.abs() ⇒ BigNumber
+

+ Returns a BigNumber whose value is the absolute value, i.e. the magnitude, of the value of + this BigNumber. +

+

The return value is always exact and unrounded.

+
+x = new BigNumber(-0.8)
+y = x.absoluteValue()           // '0.8'
+z = y.abs()                     // '0.8'
+ + + +
+ comparedTo.comparedTo(n [, base]) ⇒ number +
+

+ n: number|string|BigNumber
+ base: number
+ See BigNumber for further parameter details. +

+ + + + + + + + + + + + + + + + + + +
Returns 
1If the value of this BigNumber is greater than the value of n
-1If the value of this BigNumber is less than the value of n
0If this BigNumber and n have the same value
nullIf the value of either this BigNumber or n is NaN
+
+x = new BigNumber(Infinity)
+y = new BigNumber(5)
+x.comparedTo(y)                 // 1
+x.comparedTo(x.minus(1))        // 0
+y.comparedTo(NaN)               // null
+y.comparedTo('110', 2)          // -1
+ + + +
+ decimalPlaces.dp([dp [, rm]]) ⇒ BigNumber|number +
+

+ dp: number: integer, 0 to 1e+9 inclusive
+ rm: number: integer, 0 to 8 inclusive +

+

+ If dp is a number, returns a BigNumber whose value is the value of this BigNumber + rounded by rounding mode rm to a maximum of dp decimal places. +

+

+ If dp is omitted, or is null or undefined, the return + value is the number of decimal places of the value of this BigNumber, or null if + the value of this BigNumber is ±Infinity or NaN. +

+

+ If rm is omitted, or is null or undefined, + ROUNDING_MODE is used. +

+

+ Throws if dp or rm is invalid. See Errors. +

+
+x = new BigNumber(1234.56)
+x.decimalPlaces(1)                     // '1234.6'
+x.dp()                                 // 2
+x.decimalPlaces(2)                     // '1234.56'
+x.dp(10)                               // '1234.56'
+x.decimalPlaces(0, 1)                  // '1234'
+x.dp(0, 6)                             // '1235'
+x.decimalPlaces(1, 1)                  // '1234.5'
+x.dp(1, BigNumber.ROUND_HALF_EVEN)     // '1234.6'
+x                                      // '1234.56'
+y = new BigNumber('9.9e-101')
+y.dp()                                 // 102
+ + + +
dividedBy.div(n [, base]) ⇒ BigNumber +
+

+ n: number|string|BigNumber
+ base: number
+ See BigNumber for further parameter details. +

+

+ Returns a BigNumber whose value is the value of this BigNumber divided by + n, rounded according to the current + DECIMAL_PLACES and + ROUNDING_MODE settings. +

+
+x = new BigNumber(355)
+y = new BigNumber(113)
+x.dividedBy(y)                  // '3.14159292035398230088'
+x.div(5)                        // '71'
+x.div(47, 16)                   // '5'
+ + + +
+ dividedToIntegerBy.idiv(n [, base]) ⇒ + BigNumber +
+

+ n: number|string|BigNumber
+ base: number
+ See BigNumber for further parameter details. +

+

+ Returns a BigNumber whose value is the integer part of dividing the value of this BigNumber by + n. +

+
+x = new BigNumber(5)
+y = new BigNumber(3)
+x.dividedToIntegerBy(y)         // '1'
+x.idiv(0.7)                     // '7'
+x.idiv('0.f', 16)               // '5'
+ + + +
+ exponentiatedBy.pow(n [, m]) ⇒ BigNumber +
+

+ n: number|string|BigNumber: integer
+ m: number|string|BigNumber +

+

+ Returns a BigNumber whose value is the value of this BigNumber exponentiated by + n, i.e. raised to the power n, and optionally modulo a modulus + m. +

+

+ Throws if n is not an integer. See Errors. +

+

+ If n is negative the result is rounded according to the current + DECIMAL_PLACES and + ROUNDING_MODE settings. +

+

+ As the number of digits of the result of the power operation can grow so large so quickly, + e.g. 123.45610000 has over 50000 digits, the number of significant + digits calculated is limited to the value of the + POW_PRECISION setting (unless a modulus + m is specified). +

+

+ By default POW_PRECISION is set to 0. + This means that an unlimited number of significant digits will be calculated, and that the + method's performance will decrease dramatically for larger exponents. +

+

+ If m is specified and the value of m, n and this + BigNumber are integers, and n is positive, then a fast modular exponentiation + algorithm is used, otherwise the operation will be performed as + x.exponentiatedBy(n).modulo(m) with a + POW_PRECISION of 0. +

+
+Math.pow(0.7, 2)                // 0.48999999999999994
+x = new BigNumber(0.7)
+x.exponentiatedBy(2)            // '0.49'
+BigNumber(3).pow(-2)            // '0.11111111111111111111'
+ + + +
+ integerValue.integerValue([rm]) ⇒ BigNumber +
+

+ rm: number: integer, 0 to 8 inclusive +

+

+ Returns a BigNumber whose value is the value of this BigNumber rounded to an integer using + rounding mode rm. +

+

+ If rm is omitted, or is null or undefined, + ROUNDING_MODE is used. +

+

+ Throws if rm is invalid. See Errors. +

+
+x = new BigNumber(123.456)
+x.integerValue()                        // '123'
+x.integerValue(BigNumber.ROUND_CEIL)    // '124'
+y = new BigNumber(-12.7)
+y.integerValue()                        // '-13'
+y.integerValue(BigNumber.ROUND_DOWN)    // '-12'
+

+ The following is an example of how to add a prototype method that emulates JavaScript's + Math.round function. Math.ceil, Math.floor and + Math.trunc can be emulated in the same way with + BigNumber.ROUND_CEIL, BigNumber.ROUND_FLOOR and + BigNumber.ROUND_DOWN respectively. +

+
+BigNumber.prototype.round = function () {
+  return this.integerValue(BigNumber.ROUND_HALF_CEIL);
+};
+x.round()                               // '123'
+ + + +
isEqualTo.eq(n [, base]) ⇒ boolean
+

+ n: number|string|BigNumber
+ base: number
+ See BigNumber for further parameter details. +

+

+ Returns true if the value of this BigNumber is equal to the value of + n, otherwise returns false.
+ As with JavaScript, NaN does not equal NaN. +

+

Note: This method uses the comparedTo method internally.

+
+0 === 1e-324                    // true
+x = new BigNumber(0)
+x.isEqualTo('1e-324')           // false
+BigNumber(-0).eq(x)             // true  ( -0 === 0 )
+BigNumber(255).eq('ff', 16)     // true
+
+y = new BigNumber(NaN)
+y.isEqualTo(NaN)                // false
+ + + +
isFinite.isFinite() ⇒ boolean
+

+ Returns true if the value of this BigNumber is a finite number, otherwise + returns false. +

+

+ The only possible non-finite values of a BigNumber are NaN, Infinity + and -Infinity. +

+
+x = new BigNumber(1)
+x.isFinite()                    // true
+y = new BigNumber(Infinity)
+y.isFinite()                    // false
+

+ Note: The native method isFinite() can be used if + n <= Number.MAX_VALUE. +

+ + + +
isGreaterThan.gt(n [, base]) ⇒ boolean
+

+ n: number|string|BigNumber
+ base: number
+ See BigNumber for further parameter details. +

+

+ Returns true if the value of this BigNumber is greater than the value of + n, otherwise returns false. +

+

Note: This method uses the comparedTo method internally.

+
+0.1 > (0.3 - 0.2)                             // true
+x = new BigNumber(0.1)
+x.isGreaterThan(BigNumber(0.3).minus(0.2))    // false
+BigNumber(0).gt(x)                            // false
+BigNumber(11, 3).gt(11.1, 2)                  // true
+ + + +
+ isGreaterThanOrEqualTo.gte(n [, base]) ⇒ boolean +
+

+ n: number|string|BigNumber
+ base: number
+ See BigNumber for further parameter details. +

+

+ Returns true if the value of this BigNumber is greater than or equal to the value + of n, otherwise returns false. +

+

Note: This method uses the comparedTo method internally.

+
+(0.3 - 0.2) >= 0.1                     // false
+x = new BigNumber(0.3).minus(0.2)
+x.isGreaterThanOrEqualTo(0.1)          // true
+BigNumber(1).gte(x)                    // true
+BigNumber(10, 18).gte('i', 36)         // true
+ + + +
isInteger.isInteger() ⇒ boolean
+

+ Returns true if the value of this BigNumber is an integer, otherwise returns + false. +

+
+x = new BigNumber(1)
+x.isInteger()                   // true
+y = new BigNumber(123.456)
+y.isInteger()                   // false
+ + + +
isLessThan.lt(n [, base]) ⇒ boolean
+

+ n: number|string|BigNumber
+ base: number
+ See BigNumber for further parameter details. +

+

+ Returns true if the value of this BigNumber is less than the value of + n, otherwise returns false. +

+

Note: This method uses the comparedTo method internally.

+
+(0.3 - 0.2) < 0.1                       // true
+x = new BigNumber(0.3).minus(0.2)
+x.isLessThan(0.1)                       // false
+BigNumber(0).lt(x)                      // true
+BigNumber(11.1, 2).lt(11, 3)            // true
+ + + +
+ isLessThanOrEqualTo.lte(n [, base]) ⇒ boolean +
+

+ n: number|string|BigNumber
+ base: number
+ See BigNumber for further parameter details. +

+

+ Returns true if the value of this BigNumber is less than or equal to the value of + n, otherwise returns false. +

+

Note: This method uses the comparedTo method internally.

+
+0.1 <= (0.3 - 0.2)                                // false
+x = new BigNumber(0.1)
+x.isLessThanOrEqualTo(BigNumber(0.3).minus(0.2))  // true
+BigNumber(-1).lte(x)                              // true
+BigNumber(10, 18).lte('i', 36)                    // true
+ + + +
isNaN.isNaN() ⇒ boolean
+

+ Returns true if the value of this BigNumber is NaN, otherwise + returns false. +

+
+x = new BigNumber(NaN)
+x.isNaN()                       // true
+y = new BigNumber('Infinity')
+y.isNaN()                       // false
+

Note: The native method isNaN() can also be used.

+ + + +
isNegative.isNegative() ⇒ boolean
+

+ Returns true if the sign of this BigNumber is negative, otherwise returns + false. +

+
+x = new BigNumber(-0)
+x.isNegative()                  // true
+y = new BigNumber(2)
+y.isNegative()                  // false
+

Note: n < 0 can be used if n <= -Number.MIN_VALUE.

+ + + +
isPositive.isPositive() ⇒ boolean
+

+ Returns true if the sign of this BigNumber is positive, otherwise returns + false. +

+
+x = new BigNumber(-0)
+x.isPositive()                  // false
+y = new BigNumber(2)
+y.isPositive()                  // true
+ + + +
isZero.isZero() ⇒ boolean
+

+ Returns true if the value of this BigNumber is zero or minus zero, otherwise + returns false. +

+
+x = new BigNumber(-0)
+x.isZero() && x.isNegative()         // true
+y = new BigNumber(Infinity)
+y.isZero()                      // false
+

Note: n == 0 can be used if n >= Number.MIN_VALUE.

+ + + +
+ minus.minus(n [, base]) ⇒ BigNumber +
+

+ n: number|string|BigNumber
+ base: number
+ See BigNumber for further parameter details. +

+

Returns a BigNumber whose value is the value of this BigNumber minus n.

+

The return value is always exact and unrounded.

+
+0.3 - 0.1                       // 0.19999999999999998
+x = new BigNumber(0.3)
+x.minus(0.1)                    // '0.2'
+x.minus(0.6, 20)                // '0'
+ + + +
modulo.mod(n [, base]) ⇒ BigNumber
+

+ n: number|string|BigNumber
+ base: number
+ See BigNumber for further parameter details. +

+

+ Returns a BigNumber whose value is the value of this BigNumber modulo n, i.e. + the integer remainder of dividing this BigNumber by n. +

+

+ The value returned, and in particular its sign, is dependent on the value of the + MODULO_MODE setting of this BigNumber constructor. + If it is 1 (default value), the result will have the same sign as this BigNumber, + and it will match that of Javascript's % operator (within the limits of double + precision) and BigDecimal's remainder method. +

+

The return value is always exact and unrounded.

+

+ See MODULO_MODE for a description of the other + modulo modes. +

+
+1 % 0.9                         // 0.09999999999999998
+x = new BigNumber(1)
+x.modulo(0.9)                   // '0.1'
+y = new BigNumber(33)
+y.mod('a', 33)                  // '3'
+ + + +
+ multipliedBy.times(n [, base]) ⇒ BigNumber +
+

+ n: number|string|BigNumber
+ base: number
+ See BigNumber for further parameter details. +

+

+ Returns a BigNumber whose value is the value of this BigNumber multiplied by n. +

+

The return value is always exact and unrounded.

+
+0.6 * 3                         // 1.7999999999999998
+x = new BigNumber(0.6)
+y = x.multipliedBy(3)           // '1.8'
+BigNumber('7e+500').times(y)    // '1.26e+501'
+x.multipliedBy('-a', 16)        // '-6'
+ + + +
negated.negated() ⇒ BigNumber
+

+ Returns a BigNumber whose value is the value of this BigNumber negated, i.e. multiplied by + -1. +

+
+x = new BigNumber(1.8)
+x.negated()                     // '-1.8'
+y = new BigNumber(-1.3)
+y.negated()                     // '1.3'
+ + + +
plus.plus(n [, base]) ⇒ BigNumber
+

+ n: number|string|BigNumber
+ base: number
+ See BigNumber for further parameter details. +

+

Returns a BigNumber whose value is the value of this BigNumber plus n.

+

The return value is always exact and unrounded.

+
+0.1 + 0.2                       // 0.30000000000000004
+x = new BigNumber(0.1)
+y = x.plus(0.2)                 // '0.3'
+BigNumber(0.7).plus(x).plus(y)  // '1.1'
+x.plus('0.1', 8)                // '0.225'
+ + + +
+ precision.sd([d [, rm]]) ⇒ BigNumber|number +
+

+ d: number|boolean: integer, 1 to 1e+9 + inclusive, or true or false
+ rm: number: integer, 0 to 8 inclusive. +

+

+ If d is a number, returns a BigNumber whose value is the value of this BigNumber + rounded to a precision of d significant digits using rounding mode + rm. +

+

+ If d is omitted or is null or undefined, the return + value is the number of significant digits of the value of this BigNumber, or null + if the value of this BigNumber is ±Infinity or NaN. +

+

+ If d is true then any trailing zeros of the integer + part of a number are counted as significant digits, otherwise they are not. +

+

+ If rm is omitted or is null or undefined, + ROUNDING_MODE will be used. +

+

+ Throws if d or rm is invalid. See Errors. +

+
+x = new BigNumber(9876.54321)
+x.precision(6)                         // '9876.54'
+x.sd()                                 // 9
+x.precision(6, BigNumber.ROUND_UP)     // '9876.55'
+x.sd(2)                                // '9900'
+x.precision(2, 1)                      // '9800'
+x                                      // '9876.54321'
+y = new BigNumber(987000)
+y.precision()                          // 3
+y.sd(true)                             // 6
+ + + +
shiftedBy.shiftedBy(n) ⇒ BigNumber
+

+ n: number: integer, + -9007199254740991 to 9007199254740991 inclusive +

+

+ Returns a BigNumber whose value is the value of this BigNumber shifted by n + places. +

+ The shift is of the decimal point, i.e. of powers of ten, and is to the left if n + is negative or to the right if n is positive. +

+

The return value is always exact and unrounded.

+

+ Throws if n is invalid. See Errors. +

+
+x = new BigNumber(1.23)
+x.shiftedBy(3)                      // '1230'
+x.shiftedBy(-3)                     // '0.00123'
+ + + +
squareRoot.sqrt() ⇒ BigNumber
+

+ Returns a BigNumber whose value is the square root of the value of this BigNumber, + rounded according to the current + DECIMAL_PLACES and + ROUNDING_MODE settings. +

+

+ The return value will be correctly rounded, i.e. rounded as if the result was first calculated + to an infinite number of correct digits before rounding. +

+
+x = new BigNumber(16)
+x.squareRoot()                  // '4'
+y = new BigNumber(3)
+y.sqrt()                        // '1.73205080756887729353'
+ + + +
+ toExponential.toExponential([dp [, rm]]) ⇒ string +
+

+ dp: number: integer, 0 to 1e+9 inclusive
+ rm: number: integer, 0 to 8 inclusive +

+

+ Returns a string representing the value of this BigNumber in exponential notation rounded + using rounding mode rm to dp decimal places, i.e with one digit + before the decimal point and dp digits after it. +

+

+ If the value of this BigNumber in exponential notation has fewer than dp fraction + digits, the return value will be appended with zeros accordingly. +

+

+ If dp is omitted, or is null or undefined, the number + of digits after the decimal point defaults to the minimum number of digits necessary to + represent the value exactly.
+ If rm is omitted or is null or undefined, + ROUNDING_MODE is used. +

+

+ Throws if dp or rm is invalid. See Errors. +

+
+x = 45.6
+y = new BigNumber(x)
+x.toExponential()               // '4.56e+1'
+y.toExponential()               // '4.56e+1'
+x.toExponential(0)              // '5e+1'
+y.toExponential(0)              // '5e+1'
+x.toExponential(1)              // '4.6e+1'
+y.toExponential(1)              // '4.6e+1'
+y.toExponential(1, 1)           // '4.5e+1'  (ROUND_DOWN)
+x.toExponential(3)              // '4.560e+1'
+y.toExponential(3)              // '4.560e+1'
+ + + +
+ toFixed.toFixed([dp [, rm]]) ⇒ string +
+

+ dp: number: integer, 0 to 1e+9 inclusive
+ rm: number: integer, 0 to 8 inclusive +

+

+ Returns a string representing the value of this BigNumber in normal (fixed-point) notation + rounded to dp decimal places using rounding mode rm. +

+

+ If the value of this BigNumber in normal notation has fewer than dp fraction + digits, the return value will be appended with zeros accordingly. +

+

+ Unlike Number.prototype.toFixed, which returns exponential notation if a number + is greater or equal to 1021, this method will always return normal + notation. +

+

+ If dp is omitted or is null or undefined, the return + value will be unrounded and in normal notation. This is also unlike + Number.prototype.toFixed, which returns the value to zero decimal places.
+ It is useful when fixed-point notation is required and the current + EXPONENTIAL_AT setting causes + toString to return exponential notation.
+ If rm is omitted or is null or undefined, + ROUNDING_MODE is used. +

+

+ Throws if dp or rm is invalid. See Errors. +

+
+x = 3.456
+y = new BigNumber(x)
+x.toFixed()                     // '3'
+y.toFixed()                     // '3.456'
+y.toFixed(0)                    // '3'
+x.toFixed(2)                    // '3.46'
+y.toFixed(2)                    // '3.46'
+y.toFixed(2, 1)                 // '3.45'  (ROUND_DOWN)
+x.toFixed(5)                    // '3.45600'
+y.toFixed(5)                    // '3.45600'
+ + + +
+ toFormat.toFormat([dp [, rm[, format]]]) ⇒ string +
+

+ dp: number: integer, 0 to 1e+9 inclusive
+ rm: number: integer, 0 to 8 inclusive
+ format: object: see FORMAT +

+

+

+ Returns a string representing the value of this BigNumber in normal (fixed-point) notation + rounded to dp decimal places using rounding mode rm, and formatted + according to the properties of the format object. +

+

+ See FORMAT and the examples below for the properties of the + format object, their types, and their usage. A formatting object may contain + some or all of the recognised properties. +

+

+ If dp is omitted or is null or undefined, then the + return value is not rounded to a fixed number of decimal places.
+ If rm is omitted or is null or undefined, + ROUNDING_MODE is used.
+ If format is omitted or is null or undefined, the + FORMAT object is used. +

+

+ Throws if dp, rm or format is invalid. See + Errors. +

+
+fmt = {
+  prefix: '',
+  decimalSeparator: '.',
+  groupSeparator: ',',
+  groupSize: 3,
+  secondaryGroupSize: 0,
+  fractionGroupSeparator: ' ',
+  fractionGroupSize: 0,
+  suffix: ''
+}
+
+x = new BigNumber('123456789.123456789')
+
+// Set the global formatting options
+BigNumber.config({ FORMAT: fmt })
+
+x.toFormat()                              // '123,456,789.123456789'
+x.toFormat(3)                             // '123,456,789.123'
+
+// If a reference to the object assigned to FORMAT has been retained,
+// the format properties can be changed directly
+fmt.groupSeparator = ' '
+fmt.fractionGroupSize = 5
+x.toFormat()                              // '123 456 789.12345 6789'
+
+// Alternatively, pass the formatting options as an argument
+fmt = {
+  prefix: '=> ',
+  decimalSeparator: ',',
+  groupSeparator: '.',
+  groupSize: 3,
+  secondaryGroupSize: 2
+}
+
+x.toFormat()                              // '123 456 789.12345 6789'
+x.toFormat(fmt)                           // '=> 12.34.56.789,123456789'
+x.toFormat(2, fmt)                        // '=> 12.34.56.789,12'
+x.toFormat(3, BigNumber.ROUND_UP, fmt)    // '=> 12.34.56.789,124'
+ + + +
+ toFraction.toFraction([maximum_denominator]) + ⇒ [BigNumber, BigNumber] +
+

+ maximum_denominator: + number|string|BigNumber: integer >= 1 and <= + Infinity +

+

+ Returns an array of two BigNumbers representing the value of this BigNumber as a simple + fraction with an integer numerator and an integer denominator. The denominator will be a + positive non-zero value less than or equal to maximum_denominator. +

+

+ If a maximum_denominator is not specified, or is null or + undefined, the denominator will be the lowest value necessary to represent the + number exactly. +

+

+ Throws if maximum_denominator is invalid. See Errors. +

+
+x = new BigNumber(1.75)
+x.toFraction()                  // '7, 4'
+
+pi = new BigNumber('3.14159265358')
+pi.toFraction()                 // '157079632679,50000000000'
+pi.toFraction(100000)           // '312689, 99532'
+pi.toFraction(10000)            // '355, 113'
+pi.toFraction(100)              // '311, 99'
+pi.toFraction(10)               // '22, 7'
+pi.toFraction(1)                // '3, 1'
+ + + +
toJSON.toJSON() ⇒ string
+

As valueOf.

+
+x = new BigNumber('177.7e+457')
+y = new BigNumber(235.4325)
+z = new BigNumber('0.0098074')
+
+// Serialize an array of three BigNumbers
+str = JSON.stringify( [x, y, z] )
+// "["1.777e+459","235.4325","0.0098074"]"
+
+// Return an array of three BigNumbers
+JSON.parse(str, function (key, val) {
+    return key === '' ? val : new BigNumber(val)
+})
+ + + +
toNumber.toNumber() ⇒ number
+

Returns the value of this BigNumber as a JavaScript number primitive.

+

+ This method is identical to using type coercion with the unary plus operator. +

+
+x = new BigNumber(456.789)
+x.toNumber()                    // 456.789
++x                              // 456.789
+
+y = new BigNumber('45987349857634085409857349856430985')
+y.toNumber()                    // 4.598734985763409e+34
+
+z = new BigNumber(-0)
+1 / z.toNumber()                // -Infinity
+1 / +z                          // -Infinity
+ + + +
+ toPrecision.toPrecision([sd [, rm]]) ⇒ string +
+

+ sd: number: integer, 1 to 1e+9 inclusive
+ rm: number: integer, 0 to 8 inclusive +

+

+ Returns a string representing the value of this BigNumber rounded to sd + significant digits using rounding mode rm. +

+

+ If sd is less than the number of digits necessary to represent the integer part + of the value in normal (fixed-point) notation, then exponential notation is used. +

+

+ If sd is omitted, or is null or undefined, then the + return value is the same as n.toString().
+ If rm is omitted or is null or undefined, + ROUNDING_MODE is used. +

+

+ Throws if sd or rm is invalid. See Errors. +

+
+x = 45.6
+y = new BigNumber(x)
+x.toPrecision()                 // '45.6'
+y.toPrecision()                 // '45.6'
+x.toPrecision(1)                // '5e+1'
+y.toPrecision(1)                // '5e+1'
+y.toPrecision(2, 0)             // '4.6e+1'  (ROUND_UP)
+y.toPrecision(2, 1)             // '4.5e+1'  (ROUND_DOWN)
+x.toPrecision(5)                // '45.600'
+y.toPrecision(5)                // '45.600'
+ + + +
toString.toString([base]) ⇒ string
+

+ base: number: integer, 2 to ALPHABET.length + inclusive (see ALPHABET). +

+

+ Returns a string representing the value of this BigNumber in the specified base, or base + 10 if base is omitted or is null or + undefined. +

+

+ For bases above 10, and using the default base conversion alphabet + (see ALPHABET), values from 10 to + 35 are represented by a-z + (as with Number.prototype.toString). +

+

+ If a base is specified the value is rounded according to the current + DECIMAL_PLACES + and ROUNDING_MODE settings. +

+

+ If a base is not specified, and this BigNumber has a positive + exponent that is equal to or greater than the positive component of the + current EXPONENTIAL_AT setting, + or a negative exponent equal to or less than the negative component of the + setting, then exponential notation is returned. +

+

If base is null or undefined it is ignored.

+

+ Throws if base is invalid. See Errors. +

+
+x = new BigNumber(750000)
+x.toString()                    // '750000'
+BigNumber.config({ EXPONENTIAL_AT: 5 })
+x.toString()                    // '7.5e+5'
+
+y = new BigNumber(362.875)
+y.toString(2)                   // '101101010.111'
+y.toString(9)                   // '442.77777777777777777778'
+y.toString(32)                  // 'ba.s'
+
+BigNumber.config({ DECIMAL_PLACES: 4 });
+z = new BigNumber('1.23456789')
+z.toString()                    // '1.23456789'
+z.toString(10)                  // '1.2346'
+ + + +
valueOf.valueOf() ⇒ string
+

+ As toString, but does not accept a base argument and includes + the minus sign for negative zero. +

+
+x = new BigNumber('-0')
+x.toString()                    // '0'
+x.valueOf()                     // '-0'
+y = new BigNumber('1.777e+457')
+y.valueOf()                     // '1.777e+457'
+ + + +

Properties

+

The properties of a BigNumber instance:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyDescriptionTypeValue
ccoefficient*number[] Array of base 1e14 numbers
eexponentnumberInteger, -1000000000 to 1000000000 inclusive
ssignnumber-1 or 1
+

*significand

+

+ The value of any of the c, e and s properties may also + be null. +

+

+ The above properties are best considered to be read-only. In early versions of this library it + was okay to change the exponent of a BigNumber by writing to its exponent property directly, + but this is no longer reliable as the value of the first element of the coefficient array is + now dependent on the exponent. +

+

+ Note that, as with JavaScript numbers, the original exponent and fractional trailing zeros are + not necessarily preserved. +

+
x = new BigNumber(0.123)              // '0.123'
+x.toExponential()                     // '1.23e-1'
+x.c                                   // '1,2,3'
+x.e                                   // -1
+x.s                                   // 1
+
+y = new Number(-123.4567000e+2)       // '-12345.67'
+y.toExponential()                     // '-1.234567e+4'
+z = new BigNumber('-123.4567000e+2')  // '-12345.67'
+z.toExponential()                     // '-1.234567e+4'
+z.c                                   // '1,2,3,4,5,6,7'
+z.e                                   // 4
+z.s                                   // -1
+ + + +

Zero, NaN and Infinity

+

+ The table below shows how ±0, NaN and + ±Infinity are stored. +

+ + + + + + + + + + + + + + + + + + + + + + + + + +
ces
±0[0]0±1
NaNnullnullnull
±Infinitynullnull±1
+
+x = new Number(-0)              // 0
+1 / x == -Infinity              // true
+
+y = new BigNumber(-0)           // '0'
+y.c                             // '0' ( [0].toString() )
+y.e                             // 0
+y.s                             // -1
+ + + +

Errors

+

The table below shows the errors that are thrown.

+

+ The errors are generic Error objects whose message begins + '[BigNumber Error]'. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodThrows
+ BigNumber
+ comparedTo
+ dividedBy
+ dividedToIntegerBy
+ isEqualTo
+ isGreaterThan
+ isGreaterThanOrEqualTo
+ isLessThan
+ isLessThanOrEqualTo
+ minus
+ modulo
+ plus
+ multipliedBy +
Base not a primitive number
Base not an integer
Base out of range
Number primitive has more than 15 significant digits*
Not a base... number*
Not a number*
cloneObject expected
configObject expected
DECIMAL_PLACES not a primitive number
DECIMAL_PLACES not an integer
DECIMAL_PLACES out of range
ROUNDING_MODE not a primitive number
ROUNDING_MODE not an integer
ROUNDING_MODE out of range
EXPONENTIAL_AT not a primitive number
EXPONENTIAL_AT not an integer
EXPONENTIAL_AT out of range
RANGE not a primitive number
RANGE not an integer
RANGE cannot be zero
RANGE cannot be zero
CRYPTO not true or false
crypto unavailable
MODULO_MODE not a primitive number
MODULO_MODE not an integer
MODULO_MODE out of range
POW_PRECISION not a primitive number
POW_PRECISION not an integer
POW_PRECISION out of range
FORMAT not an object
ALPHABET invalid
+ decimalPlaces
+ precision
+ random
+ shiftedBy
+ toExponential
+ toFixed
+ toFormat
+ toPrecision +
Argument not a primitive number
Argument not an integer
Argument out of range
+ decimalPlaces
+ precision +
Argument not true or false
exponentiatedByArgument not an integer
isBigNumberInvalid BigNumber*
+ minimum
+ maximum +
Not a number*
+ random + crypto unavailable
+ toFormat + Argument not an object
toFractionArgument not an integer
Argument out of range
toStringBase not a primitive number
Base not an integer
Base out of range
+

*Only thrown if BigNumber.DEBUG is true.

+

To determine if an exception is a BigNumber Error:

+
+try {
+  // ...
+} catch (e) {
+  if (e instanceof Error && e.message.indexOf('[BigNumber Error]') === 0) {
+      // ...
+  }
+}
+ + + +

Type coercion

+

+ To prevent the accidental use of a BigNumber in primitive number operations, or the + accidental addition of a BigNumber to a string, the valueOf method can be safely + overwritten as shown below. +

+

+ The valueOf method is the same as the + toJSON method, and both are the same as the + toString method except they do not take a base + argument and they include the minus sign for negative zero. +

+
+BigNumber.prototype.valueOf = function () {
+  throw Error('valueOf called!')
+}
+
+x = new BigNumber(1)
+x / 2                    // '[BigNumber Error] valueOf called!'
+x + 'abc'                // '[BigNumber Error] valueOf called!'
+
+ + + +

FAQ

+ +
Why are trailing fractional zeros removed from BigNumbers?
+

+ Some arbitrary-precision libraries retain trailing fractional zeros as they can indicate the + precision of a value. This can be useful but the results of arithmetic operations can be + misleading. +

+
+x = new BigDecimal("1.0")
+y = new BigDecimal("1.1000")
+z = x.add(y)                      // 2.1000
+
+x = new BigDecimal("1.20")
+y = new BigDecimal("3.45000")
+z = x.multiply(y)                 // 4.1400000
+

+ To specify the precision of a value is to specify that the value lies + within a certain range. +

+

+ In the first example, x has a value of 1.0. The trailing zero shows + the precision of the value, implying that it is in the range 0.95 to + 1.05. Similarly, the precision indicated by the trailing zeros of y + indicates that the value is in the range 1.09995 to 1.10005. +

+

+ If we add the two lowest values in the ranges we have, 0.95 + 1.09995 = 2.04995, + and if we add the two highest values we have, 1.05 + 1.10005 = 2.15005, so the + range of the result of the addition implied by the precision of its operands is + 2.04995 to 2.15005. +

+

+ The result given by BigDecimal of 2.1000 however, indicates that the value is in + the range 2.09995 to 2.10005 and therefore the precision implied by + its trailing zeros may be misleading. +

+

+ In the second example, the true range is 4.122744 to 4.157256 yet + the BigDecimal answer of 4.1400000 indicates a range of 4.13999995 + to 4.14000005. Again, the precision implied by the trailing zeros may be + misleading. +

+

+ This library, like binary floating point and most calculators, does not retain trailing + fractional zeros. Instead, the toExponential, toFixed and + toPrecision methods enable trailing zeros to be added if and when required.
+

+
+ + + diff --git a/server/node_modules/bignumber.js/package.json b/server/node_modules/bignumber.js/package.json new file mode 100644 index 0000000..3ba4658 --- /dev/null +++ b/server/node_modules/bignumber.js/package.json @@ -0,0 +1,60 @@ +{ + "name": "bignumber.js", + "description": "A library for arbitrary-precision decimal and non-decimal arithmetic", + "version": "9.3.1", + "keywords": [ + "arbitrary", + "precision", + "arithmetic", + "big", + "number", + "decimal", + "float", + "biginteger", + "bigdecimal", + "bignumber", + "bigint", + "bignum" + ], + "repository": { + "type": "git", + "url": "https://github.com/MikeMcl/bignumber.js.git" + }, + "main": "bignumber", + "module": "bignumber.mjs", + "browser": "bignumber.js", + "types": "bignumber.d.ts", + "exports": { + ".": { + "import": { + "types": "./bignumber.d.mts", + "default": "./bignumber.mjs" + }, + "require": { + "types": "./bignumber.d.ts", + "default": "./bignumber.js" + }, + "browser": { + "types": "./bignumber.d.ts", + "default": "./bignumber.js" + }, + "default": { + "types": "./bignumber.d.ts", + "default": "./bignumber.js" + } + }, + "./package.json": "./package.json" + }, + "author": { + "name": "Michael Mclaughlin", + "email": "M8ch88l@gmail.com" + }, + "engines": { + "node": "*" + }, + "license": "MIT", + "scripts": { + "test": "node test/test" + }, + "dependencies": {} +} diff --git a/server/node_modules/bignumber.js/types.d.ts b/server/node_modules/bignumber.js/types.d.ts new file mode 100644 index 0000000..8e51dd6 --- /dev/null +++ b/server/node_modules/bignumber.js/types.d.ts @@ -0,0 +1,1821 @@ +// Type definitions for bignumber.js >=8.1.0 +// Project: https://github.com/MikeMcl/bignumber.js +// Definitions by: Michael Mclaughlin +// Definitions: https://github.com/MikeMcl/bignumber.js + +// Documentation: http://mikemcl.github.io/bignumber.js/ +// +// class BigNumber +// type BigNumber.Constructor +// type BigNumber.ModuloMode +// type BigNumber.RoundingMode +// type BigNumber.Value +// interface BigNumber.Config +// interface BigNumber.Format +// interface BigNumber.Instance +// +// Example: +// +// import {BigNumber} from "bignumber.js" +// //import BigNumber from "bignumber.js" +// +// let rm: BigNumber.RoundingMode = BigNumber.ROUND_UP; +// let f: BigNumber.Format = { decimalSeparator: ',' }; +// let c: BigNumber.Config = { DECIMAL_PLACES: 4, ROUNDING_MODE: rm, FORMAT: f }; +// BigNumber.config(c); +// +// let v: BigNumber.Value = '12345.6789'; +// let b: BigNumber = new BigNumber(v); +// +// The use of compiler option `--strictNullChecks` is recommended. + +declare namespace BigNumber { + + /** See `BigNumber.config` (alias `BigNumber.set`) and `BigNumber.clone`. */ + interface Config { + + /** + * An integer, 0 to 1e+9. Default value: 20. + * + * The maximum number of decimal places of the result of operations involving division, i.e. + * division, square root and base conversion operations, and exponentiation when the exponent is + * negative. + * + * ```ts + * BigNumber.config({ DECIMAL_PLACES: 5 }) + * BigNumber.set({ DECIMAL_PLACES: 5 }) + * ``` + */ + DECIMAL_PLACES?: number; + + /** + * An integer, 0 to 8. Default value: `BigNumber.ROUND_HALF_UP` (4). + * + * The rounding mode used in operations that involve division (see `DECIMAL_PLACES`) and the + * default rounding mode of the `decimalPlaces`, `precision`, `toExponential`, `toFixed`, + * `toFormat` and `toPrecision` methods. + * + * The modes are available as enumerated properties of the BigNumber constructor. + * + * ```ts + * BigNumber.config({ ROUNDING_MODE: 0 }) + * BigNumber.set({ ROUNDING_MODE: BigNumber.ROUND_UP }) + * ``` + */ + ROUNDING_MODE?: BigNumber.RoundingMode; + + /** + * An integer, 0 to 1e+9, or an array, [-1e+9 to 0, 0 to 1e+9]. + * Default value: `[-7, 20]`. + * + * The exponent value(s) at which `toString` returns exponential notation. + * + * If a single number is assigned, the value is the exponent magnitude. + * + * If an array of two numbers is assigned then the first number is the negative exponent value at + * and beneath which exponential notation is used, and the second number is the positive exponent + * value at and above which exponential notation is used. + * + * For example, to emulate JavaScript numbers in terms of the exponent values at which they begin + * to use exponential notation, use `[-7, 20]`. + * + * ```ts + * BigNumber.config({ EXPONENTIAL_AT: 2 }) + * new BigNumber(12.3) // '12.3' e is only 1 + * new BigNumber(123) // '1.23e+2' + * new BigNumber(0.123) // '0.123' e is only -1 + * new BigNumber(0.0123) // '1.23e-2' + * + * BigNumber.config({ EXPONENTIAL_AT: [-7, 20] }) + * new BigNumber(123456789) // '123456789' e is only 8 + * new BigNumber(0.000000123) // '1.23e-7' + * + * // Almost never return exponential notation: + * BigNumber.config({ EXPONENTIAL_AT: 1e+9 }) + * + * // Always return exponential notation: + * BigNumber.config({ EXPONENTIAL_AT: 0 }) + * ``` + * + * Regardless of the value of `EXPONENTIAL_AT`, the `toFixed` method will always return a value in + * normal notation and the `toExponential` method will always return a value in exponential form. + * Calling `toString` with a base argument, e.g. `toString(10)`, will also always return normal + * notation. + */ + EXPONENTIAL_AT?: number | [number, number]; + + /** + * An integer, magnitude 1 to 1e+9, or an array, [-1e+9 to -1, 1 to 1e+9]. + * Default value: `[-1e+9, 1e+9]`. + * + * The exponent value(s) beyond which overflow to Infinity and underflow to zero occurs. + * + * If a single number is assigned, it is the maximum exponent magnitude: values wth a positive + * exponent of greater magnitude become Infinity and those with a negative exponent of greater + * magnitude become zero. + * + * If an array of two numbers is assigned then the first number is the negative exponent limit and + * the second number is the positive exponent limit. + * + * For example, to emulate JavaScript numbers in terms of the exponent values at which they + * become zero and Infinity, use [-324, 308]. + * + * ```ts + * BigNumber.config({ RANGE: 500 }) + * BigNumber.config().RANGE // [ -500, 500 ] + * new BigNumber('9.999e499') // '9.999e+499' + * new BigNumber('1e500') // 'Infinity' + * new BigNumber('1e-499') // '1e-499' + * new BigNumber('1e-500') // '0' + * + * BigNumber.config({ RANGE: [-3, 4] }) + * new BigNumber(99999) // '99999' e is only 4 + * new BigNumber(100000) // 'Infinity' e is 5 + * new BigNumber(0.001) // '0.01' e is only -3 + * new BigNumber(0.0001) // '0' e is -4 + * ``` + * The largest possible magnitude of a finite BigNumber is 9.999...e+1000000000. + * The smallest possible magnitude of a non-zero BigNumber is 1e-1000000000. + */ + RANGE?: number | [number, number]; + + /** + * A boolean: `true` or `false`. Default value: `false`. + * + * The value that determines whether cryptographically-secure pseudo-random number generation is + * used. If `CRYPTO` is set to true then the random method will generate random digits using + * `crypto.getRandomValues` in browsers that support it, or `crypto.randomBytes` if using a + * version of Node.js that supports it. + * + * If neither function is supported by the host environment then attempting to set `CRYPTO` to + * `true` will fail and an exception will be thrown. + * + * If `CRYPTO` is `false` then the source of randomness used will be `Math.random` (which is + * assumed to generate at least 30 bits of randomness). + * + * See `BigNumber.random`. + * + * ```ts + * // Node.js + * global.crypto = require('crypto') + * + * BigNumber.config({ CRYPTO: true }) + * BigNumber.config().CRYPTO // true + * BigNumber.random() // 0.54340758610486147524 + * ``` + */ + CRYPTO?: boolean; + + /** + * An integer, 0, 1, 3, 6 or 9. Default value: `BigNumber.ROUND_DOWN` (1). + * + * The modulo mode used when calculating the modulus: `a mod n`. + * The quotient, `q = a / n`, is calculated according to the `ROUNDING_MODE` that corresponds to + * the chosen `MODULO_MODE`. + * The remainder, `r`, is calculated as: `r = a - n * q`. + * + * The modes that are most commonly used for the modulus/remainder operation are shown in the + * following table. Although the other rounding modes can be used, they may not give useful + * results. + * + * Property | Value | Description + * :------------------|:------|:------------------------------------------------------------------ + * `ROUND_UP` | 0 | The remainder is positive if the dividend is negative. + * `ROUND_DOWN` | 1 | The remainder has the same sign as the dividend. + * | | Uses 'truncating division' and matches JavaScript's `%` operator . + * `ROUND_FLOOR` | 3 | The remainder has the same sign as the divisor. + * | | This matches Python's `%` operator. + * `ROUND_HALF_EVEN` | 6 | The IEEE 754 remainder function. + * `EUCLID` | 9 | The remainder is always positive. + * | | Euclidian division: `q = sign(n) * floor(a / abs(n))` + * + * The rounding/modulo modes are available as enumerated properties of the BigNumber constructor. + * + * See `modulo`. + * + * ```ts + * BigNumber.config({ MODULO_MODE: BigNumber.EUCLID }) + * BigNumber.set({ MODULO_MODE: 9 }) // equivalent + * ``` + */ + MODULO_MODE?: BigNumber.ModuloMode; + + /** + * An integer, 0 to 1e+9. Default value: 0. + * + * The maximum precision, i.e. number of significant digits, of the result of the power operation + * - unless a modulus is specified. + * + * If set to 0, the number of significant digits will not be limited. + * + * See `exponentiatedBy`. + * + * ```ts + * BigNumber.config({ POW_PRECISION: 100 }) + * ``` + */ + POW_PRECISION?: number; + + /** + * An object including any number of the properties shown below. + * + * The object configures the format of the string returned by the `toFormat` method. + * The example below shows the properties of the object that are recognised, and + * their default values. + * + * Unlike the other configuration properties, the values of the properties of the `FORMAT` object + * will not be checked for validity - the existing object will simply be replaced by the object + * that is passed in. + * + * See `toFormat`. + * + * ```ts + * BigNumber.config({ + * FORMAT: { + * // string to prepend + * prefix: '', + * // the decimal separator + * decimalSeparator: '.', + * // the grouping separator of the integer part + * groupSeparator: ',', + * // the primary grouping size of the integer part + * groupSize: 3, + * // the secondary grouping size of the integer part + * secondaryGroupSize: 0, + * // the grouping separator of the fraction part + * fractionGroupSeparator: ' ', + * // the grouping size of the fraction part + * fractionGroupSize: 0, + * // string to append + * suffix: '' + * } + * }) + * ``` + */ + FORMAT?: BigNumber.Format; + + /** + * The alphabet used for base conversion. The length of the alphabet corresponds to the maximum + * value of the base argument that can be passed to the BigNumber constructor or `toString`. + * + * Default value: `'0123456789abcdefghijklmnopqrstuvwxyz'`. + * + * There is no maximum length for the alphabet, but it must be at least 2 characters long, + * and it must not contain whitespace or a repeated character, or the sign indicators '+' and + * '-', or the decimal separator '.'. + * + * ```ts + * // duodecimal (base 12) + * BigNumber.config({ ALPHABET: '0123456789TE' }) + * x = new BigNumber('T', 12) + * x.toString() // '10' + * x.toString(12) // 'T' + * ``` + */ + ALPHABET?: string; + } + + /** See `FORMAT` and `toFormat`. */ + interface Format { + + /** The string to prepend. */ + prefix?: string; + + /** The decimal separator. */ + decimalSeparator?: string; + + /** The grouping separator of the integer part. */ + groupSeparator?: string; + + /** The primary grouping size of the integer part. */ + groupSize?: number; + + /** The secondary grouping size of the integer part. */ + secondaryGroupSize?: number; + + /** The grouping separator of the fraction part. */ + fractionGroupSeparator?: string; + + /** The grouping size of the fraction part. */ + fractionGroupSize?: number; + + /** The string to append. */ + suffix?: string; + } + + interface Instance { + + /** The coefficient of the value of this BigNumber, an array of base 1e14 integer numbers, or null. */ + readonly c: number[] | null; + + /** The exponent of the value of this BigNumber, an integer number, -1000000000 to 1000000000, or null. */ + readonly e: number | null; + + /** The sign of the value of this BigNumber, -1, 1, or null. */ + readonly s: number | null; + + [key: string]: any; + } + + type Constructor = typeof BigNumber; + type ModuloMode = 0 | 1 | 3 | 6 | 9; + type RoundingMode = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8; + type Value = string | number | bigint | Instance; +} + +declare class BigNumber implements BigNumber.Instance { + + /** Used internally to identify a BigNumber instance. */ + private readonly _isBigNumber: true; + + /** The coefficient of the value of this BigNumber, an array of base 1e14 integer numbers, or null. */ + readonly c: number[] | null; + + /** The exponent of the value of this BigNumber, an integer number, -1000000000 to 1000000000, or null. */ + readonly e: number | null; + + /** The sign of the value of this BigNumber, -1, 1, or null. */ + readonly s: number | null; + + /** + * Returns a new instance of a BigNumber object with value `n`, where `n` is a numeric value in + * the specified `base`, or base 10 if `base` is omitted. + * + * ```ts + * x = new BigNumber(123.4567) // '123.4567' + * // 'new' is optional + * y = BigNumber(x) // '123.4567' + * ``` + * + * If `n` is a base 10 value it can be in normal (fixed-point) or exponential notation. + * Values in other bases must be in normal notation. Values in any base can have fraction digits, + * i.e. digits after the decimal point. + * + * ```ts + * new BigNumber(43210) // '43210' + * new BigNumber('4.321e+4') // '43210' + * new BigNumber('-735.0918e-430') // '-7.350918e-428' + * new BigNumber('123412421.234324', 5) // '607236.557696' + * ``` + * + * Signed `0`, signed `Infinity` and `NaN` are supported. + * + * ```ts + * new BigNumber('-Infinity') // '-Infinity' + * new BigNumber(NaN) // 'NaN' + * new BigNumber(-0) // '0' + * new BigNumber('.5') // '0.5' + * new BigNumber('+2') // '2' + * ``` + * + * String values in hexadecimal literal form, e.g. `'0xff'`, are valid, as are string values with + * the octal and binary prefixs `'0o'` and `'0b'`. String values in octal literal form without the + * prefix will be interpreted as decimals, e.g. `'011'` is interpreted as 11, not 9. + * + * ```ts + * new BigNumber(-10110100.1, 2) // '-180.5' + * new BigNumber('-0b10110100.1') // '-180.5' + * new BigNumber('ff.8', 16) // '255.5' + * new BigNumber('0xff.8') // '255.5' + * ``` + * + * If a base is specified, `n` is rounded according to the current `DECIMAL_PLACES` and + * `ROUNDING_MODE` settings. This includes base 10, so don't include a `base` parameter for decimal + * values unless this behaviour is desired. + * + * ```ts + * BigNumber.config({ DECIMAL_PLACES: 5 }) + * new BigNumber(1.23456789) // '1.23456789' + * new BigNumber(1.23456789, 10) // '1.23457' + * ``` + * + * An error is thrown if `base` is invalid. + * + * There is no limit to the number of digits of a value of type string (other than that of + * JavaScript's maximum array size). See `RANGE` to set the maximum and minimum possible exponent + * value of a BigNumber. + * + * ```ts + * new BigNumber('5032485723458348569331745.33434346346912144534543') + * new BigNumber('4.321e10000000') + * ``` + * + * BigNumber `NaN` is returned if `n` is invalid (unless `BigNumber.DEBUG` is `true`, see below). + * + * ```ts + * new BigNumber('.1*') // 'NaN' + * new BigNumber('blurgh') // 'NaN' + * new BigNumber(9, 2) // 'NaN' + * ``` + * + * To aid in debugging, if `BigNumber.DEBUG` is `true` then an error will be thrown on an + * invalid `n`. An error will also be thrown if `n` is of type number with more than 15 + * significant digits, as calling `toString` or `valueOf` on these numbers may not result in the + * intended value. + * + * ```ts + * console.log(823456789123456.3) // 823456789123456.2 + * new BigNumber(823456789123456.3) // '823456789123456.2' + * BigNumber.DEBUG = true + * // 'Error: Number has more than 15 significant digits' + * new BigNumber(823456789123456.3) + * // 'Error: Not a base 2 number' + * new BigNumber(9, 2) + * ``` + * + * A BigNumber can also be created from an object literal. + * Use `isBigNumber` to check that it is well-formed. + * + * ```ts + * new BigNumber({ s: 1, e: 2, c: [ 777, 12300000000000 ], _isBigNumber: true }) // '777.123' + * ``` + * + * @param n A numeric value. + * @param base The base of `n`, integer, 2 to 36 (or `ALPHABET.length`, see `ALPHABET`). + */ + constructor(n: BigNumber.Value, base?: number); + + /** + * Returns a BigNumber whose value is the absolute value, i.e. the magnitude, of the value of this + * BigNumber. + * + * The return value is always exact and unrounded. + * + * ```ts + * x = new BigNumber(-0.8) + * x.absoluteValue() // '0.8' + * ``` + */ + absoluteValue(): BigNumber; + + /** + * Returns a BigNumber whose value is the absolute value, i.e. the magnitude, of the value of this + * BigNumber. + * + * The return value is always exact and unrounded. + * + * ```ts + * x = new BigNumber(-0.8) + * x.abs() // '0.8' + * ``` + */ + abs(): BigNumber; + + /** + * Returns | | + * :-------:|:--------------------------------------------------------------| + * 1 | If the value of this BigNumber is greater than the value of `n` + * -1 | If the value of this BigNumber is less than the value of `n` + * 0 | If this BigNumber and `n` have the same value + * `null` | If the value of either this BigNumber or `n` is `NaN` + * + * ```ts + * + * x = new BigNumber(Infinity) + * y = new BigNumber(5) + * x.comparedTo(y) // 1 + * x.comparedTo(x.minus(1)) // 0 + * y.comparedTo(NaN) // null + * y.comparedTo('110', 2) // -1 + * ``` + * @param n A numeric value. + * @param [base] The base of n. + */ + comparedTo(n: BigNumber.Value, base?: number): 1 | -1 | 0 | null; + + /** + * Returns a BigNumber whose value is the value of this BigNumber rounded by rounding mode + * `roundingMode` to a maximum of `decimalPlaces` decimal places. + * + * If `decimalPlaces` is omitted, the return value is the number of decimal places of the value of + * this BigNumber, or `null` if the value of this BigNumber is ±`Infinity` or `NaN`. + * + * If `roundingMode` is omitted, `ROUNDING_MODE` is used. + * + * Throws if `decimalPlaces` or `roundingMode` is invalid. + * + * ```ts + * x = new BigNumber(1234.56) + * x.decimalPlaces() // 2 + * x.decimalPlaces(1) // '1234.6' + * x.decimalPlaces(2) // '1234.56' + * x.decimalPlaces(10) // '1234.56' + * x.decimalPlaces(0, 1) // '1234' + * x.decimalPlaces(0, 6) // '1235' + * x.decimalPlaces(1, 1) // '1234.5' + * x.decimalPlaces(1, BigNumber.ROUND_HALF_EVEN) // '1234.6' + * x // '1234.56' + * y = new BigNumber('9.9e-101') + * y.decimalPlaces() // 102 + * ``` + * + * @param [decimalPlaces] Decimal places, integer, 0 to 1e+9. + * @param [roundingMode] Rounding mode, integer, 0 to 8. + */ + decimalPlaces(): number | null; + decimalPlaces(decimalPlaces: number, roundingMode?: BigNumber.RoundingMode): BigNumber; + + /** + * Returns a BigNumber whose value is the value of this BigNumber rounded by rounding mode + * `roundingMode` to a maximum of `decimalPlaces` decimal places. + * + * If `decimalPlaces` is omitted, the return value is the number of decimal places of the value of + * this BigNumber, or `null` if the value of this BigNumber is ±`Infinity` or `NaN`. + * + * If `roundingMode` is omitted, `ROUNDING_MODE` is used. + * + * Throws if `decimalPlaces` or `roundingMode` is invalid. + * + * ```ts + * x = new BigNumber(1234.56) + * x.dp() // 2 + * x.dp(1) // '1234.6' + * x.dp(2) // '1234.56' + * x.dp(10) // '1234.56' + * x.dp(0, 1) // '1234' + * x.dp(0, 6) // '1235' + * x.dp(1, 1) // '1234.5' + * x.dp(1, BigNumber.ROUND_HALF_EVEN) // '1234.6' + * x // '1234.56' + * y = new BigNumber('9.9e-101') + * y.dp() // 102 + * ``` + * + * @param [decimalPlaces] Decimal places, integer, 0 to 1e+9. + * @param [roundingMode] Rounding mode, integer, 0 to 8. + */ + dp(): number | null; + dp(decimalPlaces: number, roundingMode?: BigNumber.RoundingMode): BigNumber; + + /** + * Returns a BigNumber whose value is the value of this BigNumber divided by `n`, rounded + * according to the current `DECIMAL_PLACES` and `ROUNDING_MODE` settings. + * + * ```ts + * x = new BigNumber(355) + * y = new BigNumber(113) + * x.dividedBy(y) // '3.14159292035398230088' + * x.dividedBy(5) // '71' + * x.dividedBy(47, 16) // '5' + * ``` + * + * @param n A numeric value. + * @param [base] The base of n. + */ + dividedBy(n: BigNumber.Value, base?: number): BigNumber; + + /** + * Returns a BigNumber whose value is the value of this BigNumber divided by `n`, rounded + * according to the current `DECIMAL_PLACES` and `ROUNDING_MODE` settings. + * + * ```ts + * x = new BigNumber(355) + * y = new BigNumber(113) + * x.div(y) // '3.14159292035398230088' + * x.div(5) // '71' + * x.div(47, 16) // '5' + * ``` + * + * @param n A numeric value. + * @param [base] The base of n. + */ + div(n: BigNumber.Value, base?: number): BigNumber; + + /** + * Returns a BigNumber whose value is the integer part of dividing the value of this BigNumber by + * `n`. + * + * ```ts + * x = new BigNumber(5) + * y = new BigNumber(3) + * x.dividedToIntegerBy(y) // '1' + * x.dividedToIntegerBy(0.7) // '7' + * x.dividedToIntegerBy('0.f', 16) // '5' + * ``` + * + * @param n A numeric value. + * @param [base] The base of n. + */ + dividedToIntegerBy(n: BigNumber.Value, base?: number): BigNumber; + + /** + * Returns a BigNumber whose value is the integer part of dividing the value of this BigNumber by + * `n`. + * + * ```ts + * x = new BigNumber(5) + * y = new BigNumber(3) + * x.idiv(y) // '1' + * x.idiv(0.7) // '7' + * x.idiv('0.f', 16) // '5' + * ``` + * + * @param n A numeric value. + * @param [base] The base of n. + */ + idiv(n: BigNumber.Value, base?: number): BigNumber; + + /** + * Returns a BigNumber whose value is the value of this BigNumber exponentiated by `n`, i.e. + * raised to the power `n`, and optionally modulo a modulus `m`. + * + * If `n` is negative the result is rounded according to the current `DECIMAL_PLACES` and + * `ROUNDING_MODE` settings. + * + * As the number of digits of the result of the power operation can grow so large so quickly, + * e.g. 123.456**10000 has over 50000 digits, the number of significant digits calculated is + * limited to the value of the `POW_PRECISION` setting (unless a modulus `m` is specified). + * + * By default `POW_PRECISION` is set to 0. This means that an unlimited number of significant + * digits will be calculated, and that the method's performance will decrease dramatically for + * larger exponents. + * + * If `m` is specified and the value of `m`, `n` and this BigNumber are integers and `n` is + * positive, then a fast modular exponentiation algorithm is used, otherwise the operation will + * be performed as `x.exponentiatedBy(n).modulo(m)` with a `POW_PRECISION` of 0. + * + * Throws if `n` is not an integer. + * + * ```ts + * Math.pow(0.7, 2) // 0.48999999999999994 + * x = new BigNumber(0.7) + * x.exponentiatedBy(2) // '0.49' + * BigNumber(3).exponentiatedBy(-2) // '0.11111111111111111111' + * ``` + * + * @param n The exponent, an integer. + * @param [m] The modulus. + */ + exponentiatedBy(n: BigNumber.Value, m?: BigNumber.Value): BigNumber; + exponentiatedBy(n: number, m?: BigNumber.Value): BigNumber; + + /** + * Returns a BigNumber whose value is the value of this BigNumber exponentiated by `n`, i.e. + * raised to the power `n`, and optionally modulo a modulus `m`. + * + * If `n` is negative the result is rounded according to the current `DECIMAL_PLACES` and + * `ROUNDING_MODE` settings. + * + * As the number of digits of the result of the power operation can grow so large so quickly, + * e.g. 123.456**10000 has over 50000 digits, the number of significant digits calculated is + * limited to the value of the `POW_PRECISION` setting (unless a modulus `m` is specified). + * + * By default `POW_PRECISION` is set to 0. This means that an unlimited number of significant + * digits will be calculated, and that the method's performance will decrease dramatically for + * larger exponents. + * + * If `m` is specified and the value of `m`, `n` and this BigNumber are integers and `n` is + * positive, then a fast modular exponentiation algorithm is used, otherwise the operation will + * be performed as `x.pow(n).modulo(m)` with a `POW_PRECISION` of 0. + * + * Throws if `n` is not an integer. + * + * ```ts + * Math.pow(0.7, 2) // 0.48999999999999994 + * x = new BigNumber(0.7) + * x.pow(2) // '0.49' + * BigNumber(3).pow(-2) // '0.11111111111111111111' + * ``` + * + * @param n The exponent, an integer. + * @param [m] The modulus. + */ + pow(n: BigNumber.Value, m?: BigNumber.Value): BigNumber; + pow(n: number, m?: BigNumber.Value): BigNumber; + + /** + * Returns a BigNumber whose value is the value of this BigNumber rounded to an integer using + * rounding mode `rm`. + * + * If `rm` is omitted, `ROUNDING_MODE` is used. + * + * Throws if `rm` is invalid. + * + * ```ts + * x = new BigNumber(123.456) + * x.integerValue() // '123' + * x.integerValue(BigNumber.ROUND_CEIL) // '124' + * y = new BigNumber(-12.7) + * y.integerValue() // '-13' + * x.integerValue(BigNumber.ROUND_DOWN) // '-12' + * ``` + * + * @param {BigNumber.RoundingMode} [rm] The roundng mode, an integer, 0 to 8. + */ + integerValue(rm?: BigNumber.RoundingMode): BigNumber; + + /** + * Returns `true` if the value of this BigNumber is equal to the value of `n`, otherwise returns + * `false`. + * + * As with JavaScript, `NaN` does not equal `NaN`. + * + * ```ts + * 0 === 1e-324 // true + * x = new BigNumber(0) + * x.isEqualTo('1e-324') // false + * BigNumber(-0).isEqualTo(x) // true ( -0 === 0 ) + * BigNumber(255).isEqualTo('ff', 16) // true + * + * y = new BigNumber(NaN) + * y.isEqualTo(NaN) // false + * ``` + * + * @param n A numeric value. + * @param [base] The base of n. + */ + isEqualTo(n: BigNumber.Value, base?: number): boolean; + + /** + * Returns `true` if the value of this BigNumber is equal to the value of `n`, otherwise returns + * `false`. + * + * As with JavaScript, `NaN` does not equal `NaN`. + * + * ```ts + * 0 === 1e-324 // true + * x = new BigNumber(0) + * x.eq('1e-324') // false + * BigNumber(-0).eq(x) // true ( -0 === 0 ) + * BigNumber(255).eq('ff', 16) // true + * + * y = new BigNumber(NaN) + * y.eq(NaN) // false + * ``` + * + * @param n A numeric value. + * @param [base] The base of n. + */ + eq(n: BigNumber.Value, base?: number): boolean; + + /** + * Returns `true` if the value of this BigNumber is a finite number, otherwise returns `false`. + * + * The only possible non-finite values of a BigNumber are `NaN`, `Infinity` and `-Infinity`. + * + * ```ts + * x = new BigNumber(1) + * x.isFinite() // true + * y = new BigNumber(Infinity) + * y.isFinite() // false + * ``` + */ + isFinite(): boolean; + + /** + * Returns `true` if the value of this BigNumber is greater than the value of `n`, otherwise + * returns `false`. + * + * ```ts + * 0.1 > (0.3 - 0.2) // true + * x = new BigNumber(0.1) + * x.isGreaterThan(BigNumber(0.3).minus(0.2)) // false + * BigNumber(0).isGreaterThan(x) // false + * BigNumber(11, 3).isGreaterThan(11.1, 2) // true + * ``` + * + * @param n A numeric value. + * @param [base] The base of n. + */ + isGreaterThan(n: BigNumber.Value, base?: number): boolean; + + /** + * Returns `true` if the value of this BigNumber is greater than the value of `n`, otherwise + * returns `false`. + * + * ```ts + * 0.1 > (0.3 - 0.2) // true + * x = new BigNumber(0.1) + * x.gt(BigNumber(0.3).minus(0.2)) // false + * BigNumber(0).gt(x) // false + * BigNumber(11, 3).gt(11.1, 2) // true + * ``` + * + * @param n A numeric value. + * @param [base] The base of n. + */ + gt(n: BigNumber.Value, base?: number): boolean; + + /** + * Returns `true` if the value of this BigNumber is greater than or equal to the value of `n`, + * otherwise returns `false`. + * + * ```ts + * (0.3 - 0.2) >= 0.1 // false + * x = new BigNumber(0.3).minus(0.2) + * x.isGreaterThanOrEqualTo(0.1) // true + * BigNumber(1).isGreaterThanOrEqualTo(x) // true + * BigNumber(10, 18).isGreaterThanOrEqualTo('i', 36) // true + * ``` + * + * @param n A numeric value. + * @param [base] The base of n. + */ + isGreaterThanOrEqualTo(n: BigNumber.Value, base?: number): boolean; + + /** + * Returns `true` if the value of this BigNumber is greater than or equal to the value of `n`, + * otherwise returns `false`. + * + * ```ts + * (0.3 - 0.2) >= 0.1 // false + * x = new BigNumber(0.3).minus(0.2) + * x.gte(0.1) // true + * BigNumber(1).gte(x) // true + * BigNumber(10, 18).gte('i', 36) // true + * ``` + * + * @param n A numeric value. + * @param [base] The base of n. + */ + gte(n: BigNumber.Value, base?: number): boolean; + + /** + * Returns `true` if the value of this BigNumber is an integer, otherwise returns `false`. + * + * ```ts + * x = new BigNumber(1) + * x.isInteger() // true + * y = new BigNumber(123.456) + * y.isInteger() // false + * ``` + */ + isInteger(): boolean; + + /** + * Returns `true` if the value of this BigNumber is less than the value of `n`, otherwise returns + * `false`. + * + * ```ts + * (0.3 - 0.2) < 0.1 // true + * x = new BigNumber(0.3).minus(0.2) + * x.isLessThan(0.1) // false + * BigNumber(0).isLessThan(x) // true + * BigNumber(11.1, 2).isLessThan(11, 3) // true + * ``` + * + * @param n A numeric value. + * @param [base] The base of n. + */ + isLessThan(n: BigNumber.Value, base?: number): boolean; + + /** + * Returns `true` if the value of this BigNumber is less than the value of `n`, otherwise returns + * `false`. + * + * ```ts + * (0.3 - 0.2) < 0.1 // true + * x = new BigNumber(0.3).minus(0.2) + * x.lt(0.1) // false + * BigNumber(0).lt(x) // true + * BigNumber(11.1, 2).lt(11, 3) // true + * ``` + * + * @param n A numeric value. + * @param [base] The base of n. + */ + lt(n: BigNumber.Value, base?: number): boolean; + + /** + * Returns `true` if the value of this BigNumber is less than or equal to the value of `n`, + * otherwise returns `false`. + * + * ```ts + * 0.1 <= (0.3 - 0.2) // false + * x = new BigNumber(0.1) + * x.isLessThanOrEqualTo(BigNumber(0.3).minus(0.2)) // true + * BigNumber(-1).isLessThanOrEqualTo(x) // true + * BigNumber(10, 18).isLessThanOrEqualTo('i', 36) // true + * ``` + * + * @param n A numeric value. + * @param [base] The base of n. + */ + isLessThanOrEqualTo(n: BigNumber.Value, base?: number): boolean; + + /** + * Returns `true` if the value of this BigNumber is less than or equal to the value of `n`, + * otherwise returns `false`. + * + * ```ts + * 0.1 <= (0.3 - 0.2) // false + * x = new BigNumber(0.1) + * x.lte(BigNumber(0.3).minus(0.2)) // true + * BigNumber(-1).lte(x) // true + * BigNumber(10, 18).lte('i', 36) // true + * ``` + * + * @param n A numeric value. + * @param [base] The base of n. + */ + lte(n: BigNumber.Value, base?: number): boolean; + + /** + * Returns `true` if the value of this BigNumber is `NaN`, otherwise returns `false`. + * + * ```ts + * x = new BigNumber(NaN) + * x.isNaN() // true + * y = new BigNumber('Infinity') + * y.isNaN() // false + * ``` + */ + isNaN(): boolean; + + /** + * Returns `true` if the value of this BigNumber is negative, otherwise returns `false`. + * + * ```ts + * x = new BigNumber(-0) + * x.isNegative() // true + * y = new BigNumber(2) + * y.isNegative() // false + * ``` + */ + isNegative(): boolean; + + /** + * Returns `true` if the value of this BigNumber is positive, otherwise returns `false`. + * + * ```ts + * x = new BigNumber(-0) + * x.isPositive() // false + * y = new BigNumber(2) + * y.isPositive() // true + * ``` + */ + isPositive(): boolean; + + /** + * Returns `true` if the value of this BigNumber is zero or minus zero, otherwise returns `false`. + * + * ```ts + * x = new BigNumber(-0) + * x.isZero() // true + * ``` + */ + isZero(): boolean; + + /** + * Returns a BigNumber whose value is the value of this BigNumber minus `n`. + * + * The return value is always exact and unrounded. + * + * ```ts + * 0.3 - 0.1 // 0.19999999999999998 + * x = new BigNumber(0.3) + * x.minus(0.1) // '0.2' + * x.minus(0.6, 20) // '0' + * ``` + * + * @param n A numeric value. + * @param [base] The base of n. + */ + minus(n: BigNumber.Value, base?: number): BigNumber; + + /** + * Returns a BigNumber whose value is the value of this BigNumber modulo `n`, i.e. the integer + * remainder of dividing this BigNumber by `n`. + * + * The value returned, and in particular its sign, is dependent on the value of the `MODULO_MODE` + * setting of this BigNumber constructor. If it is 1 (default value), the result will have the + * same sign as this BigNumber, and it will match that of Javascript's `%` operator (within the + * limits of double precision) and BigDecimal's `remainder` method. + * + * The return value is always exact and unrounded. + * + * See `MODULO_MODE` for a description of the other modulo modes. + * + * ```ts + * 1 % 0.9 // 0.09999999999999998 + * x = new BigNumber(1) + * x.modulo(0.9) // '0.1' + * y = new BigNumber(33) + * y.modulo('a', 33) // '3' + * ``` + * + * @param n A numeric value. + * @param [base] The base of n. + */ + modulo(n: BigNumber.Value, base?: number): BigNumber; + + /** + * Returns a BigNumber whose value is the value of this BigNumber modulo `n`, i.e. the integer + * remainder of dividing this BigNumber by `n`. + * + * The value returned, and in particular its sign, is dependent on the value of the `MODULO_MODE` + * setting of this BigNumber constructor. If it is 1 (default value), the result will have the + * same sign as this BigNumber, and it will match that of Javascript's `%` operator (within the + * limits of double precision) and BigDecimal's `remainder` method. + * + * The return value is always exact and unrounded. + * + * See `MODULO_MODE` for a description of the other modulo modes. + * + * ```ts + * 1 % 0.9 // 0.09999999999999998 + * x = new BigNumber(1) + * x.mod(0.9) // '0.1' + * y = new BigNumber(33) + * y.mod('a', 33) // '3' + * ``` + * + * @param n A numeric value. + * @param [base] The base of n. + */ + mod(n: BigNumber.Value, base?: number): BigNumber; + + /** + * Returns a BigNumber whose value is the value of this BigNumber multiplied by `n`. + * + * The return value is always exact and unrounded. + * + * ```ts + * 0.6 * 3 // 1.7999999999999998 + * x = new BigNumber(0.6) + * y = x.multipliedBy(3) // '1.8' + * BigNumber('7e+500').multipliedBy(y) // '1.26e+501' + * x.multipliedBy('-a', 16) // '-6' + * ``` + * + * @param n A numeric value. + * @param [base] The base of n. + */ + multipliedBy(n: BigNumber.Value, base?: number): BigNumber; + + /** + * Returns a BigNumber whose value is the value of this BigNumber multiplied by `n`. + * + * The return value is always exact and unrounded. + * + * ```ts + * 0.6 * 3 // 1.7999999999999998 + * x = new BigNumber(0.6) + * y = x.times(3) // '1.8' + * BigNumber('7e+500').times(y) // '1.26e+501' + * x.times('-a', 16) // '-6' + * ``` + * + * @param n A numeric value. + * @param [base] The base of n. + */ + times(n: BigNumber.Value, base?: number): BigNumber; + + /** + * Returns a BigNumber whose value is the value of this BigNumber negated, i.e. multiplied by -1. + * + * ```ts + * x = new BigNumber(1.8) + * x.negated() // '-1.8' + * y = new BigNumber(-1.3) + * y.negated() // '1.3' + * ``` + */ + negated(): BigNumber; + + /** + * Returns a BigNumber whose value is the value of this BigNumber plus `n`. + * + * The return value is always exact and unrounded. + * + * ```ts + * 0.1 + 0.2 // 0.30000000000000004 + * x = new BigNumber(0.1) + * y = x.plus(0.2) // '0.3' + * BigNumber(0.7).plus(x).plus(y) // '1.1' + * x.plus('0.1', 8) // '0.225' + * ``` + * + * @param n A numeric value. + * @param [base] The base of n. + */ + plus(n: BigNumber.Value, base?: number): BigNumber; + + /** + * Returns the number of significant digits of the value of this BigNumber, or `null` if the value + * of this BigNumber is ±`Infinity` or `NaN`. + * + * If `includeZeros` is true then any trailing zeros of the integer part of the value of this + * BigNumber are counted as significant digits, otherwise they are not. + * + * Throws if `includeZeros` is invalid. + * + * ```ts + * x = new BigNumber(9876.54321) + * x.precision() // 9 + * y = new BigNumber(987000) + * y.precision(false) // 3 + * y.precision(true) // 6 + * ``` + * + * @param [includeZeros] Whether to include integer trailing zeros in the significant digit count. + */ + precision(includeZeros?: boolean): number; + + /** + * Returns a BigNumber whose value is the value of this BigNumber rounded to a precision of + * `significantDigits` significant digits using rounding mode `roundingMode`. + * + * If `roundingMode` is omitted, `ROUNDING_MODE` will be used. + * + * Throws if `significantDigits` or `roundingMode` is invalid. + * + * ```ts + * x = new BigNumber(9876.54321) + * x.precision(6) // '9876.54' + * x.precision(6, BigNumber.ROUND_UP) // '9876.55' + * x.precision(2) // '9900' + * x.precision(2, 1) // '9800' + * x // '9876.54321' + * ``` + * + * @param significantDigits Significant digits, integer, 1 to 1e+9. + * @param [roundingMode] Rounding mode, integer, 0 to 8. + */ + precision(significantDigits: number, roundingMode?: BigNumber.RoundingMode): BigNumber; + + /** + * Returns the number of significant digits of the value of this BigNumber, + * or `null` if the value of this BigNumber is ±`Infinity` or `NaN`. + * + * If `includeZeros` is true then any trailing zeros of the integer part of + * the value of this BigNumber are counted as significant digits, otherwise + * they are not. + * + * Throws if `includeZeros` is invalid. + * + * ```ts + * x = new BigNumber(9876.54321) + * x.sd() // 9 + * y = new BigNumber(987000) + * y.sd(false) // 3 + * y.sd(true) // 6 + * ``` + * + * @param [includeZeros] Whether to include integer trailing zeros in the significant digit count. + */ + sd(includeZeros?: boolean): number; + + /** + * Returns a BigNumber whose value is the value of this BigNumber rounded to a precision of + * `significantDigits` significant digits using rounding mode `roundingMode`. + * + * If `roundingMode` is omitted, `ROUNDING_MODE` will be used. + * + * Throws if `significantDigits` or `roundingMode` is invalid. + * + * ```ts + * x = new BigNumber(9876.54321) + * x.sd(6) // '9876.54' + * x.sd(6, BigNumber.ROUND_UP) // '9876.55' + * x.sd(2) // '9900' + * x.sd(2, 1) // '9800' + * x // '9876.54321' + * ``` + * + * @param significantDigits Significant digits, integer, 1 to 1e+9. + * @param [roundingMode] Rounding mode, integer, 0 to 8. + */ + sd(significantDigits: number, roundingMode?: BigNumber.RoundingMode): BigNumber; + + /** + * Returns a BigNumber whose value is the value of this BigNumber shifted by `n` places. + * + * The shift is of the decimal point, i.e. of powers of ten, and is to the left if `n` is negative + * or to the right if `n` is positive. + * + * The return value is always exact and unrounded. + * + * Throws if `n` is invalid. + * + * ```ts + * x = new BigNumber(1.23) + * x.shiftedBy(3) // '1230' + * x.shiftedBy(-3) // '0.00123' + * ``` + * + * @param n The shift value, integer, -9007199254740991 to 9007199254740991. + */ + shiftedBy(n: number): BigNumber; + + /** + * Returns a BigNumber whose value is the square root of the value of this BigNumber, rounded + * according to the current `DECIMAL_PLACES` and `ROUNDING_MODE` settings. + * + * The return value will be correctly rounded, i.e. rounded as if the result was first calculated + * to an infinite number of correct digits before rounding. + * + * ```ts + * x = new BigNumber(16) + * x.squareRoot() // '4' + * y = new BigNumber(3) + * y.squareRoot() // '1.73205080756887729353' + * ``` + */ + squareRoot(): BigNumber; + + /** + * Returns a BigNumber whose value is the square root of the value of this BigNumber, rounded + * according to the current `DECIMAL_PLACES` and `ROUNDING_MODE` settings. + * + * The return value will be correctly rounded, i.e. rounded as if the result was first calculated + * to an infinite number of correct digits before rounding. + * + * ```ts + * x = new BigNumber(16) + * x.sqrt() // '4' + * y = new BigNumber(3) + * y.sqrt() // '1.73205080756887729353' + * ``` + */ + sqrt(): BigNumber; + + /** + * Returns a string representing the value of this BigNumber in exponential notation rounded using + * rounding mode `roundingMode` to `decimalPlaces` decimal places, i.e with one digit before the + * decimal point and `decimalPlaces` digits after it. + * + * If the value of this BigNumber in exponential notation has fewer than `decimalPlaces` fraction + * digits, the return value will be appended with zeros accordingly. + * + * If `decimalPlaces` is omitted, the number of digits after the decimal point defaults to the + * minimum number of digits necessary to represent the value exactly. + * + * If `roundingMode` is omitted, `ROUNDING_MODE` is used. + * + * Throws if `decimalPlaces` or `roundingMode` is invalid. + * + * ```ts + * x = 45.6 + * y = new BigNumber(x) + * x.toExponential() // '4.56e+1' + * y.toExponential() // '4.56e+1' + * x.toExponential(0) // '5e+1' + * y.toExponential(0) // '5e+1' + * x.toExponential(1) // '4.6e+1' + * y.toExponential(1) // '4.6e+1' + * y.toExponential(1, 1) // '4.5e+1' (ROUND_DOWN) + * x.toExponential(3) // '4.560e+1' + * y.toExponential(3) // '4.560e+1' + * ``` + * + * @param [decimalPlaces] Decimal places, integer, 0 to 1e+9. + * @param [roundingMode] Rounding mode, integer, 0 to 8. + */ + toExponential(decimalPlaces: number, roundingMode?: BigNumber.RoundingMode): string; + toExponential(): string; + + /** + * Returns a string representing the value of this BigNumber in normal (fixed-point) notation + * rounded to `decimalPlaces` decimal places using rounding mode `roundingMode`. + * + * If the value of this BigNumber in normal notation has fewer than `decimalPlaces` fraction + * digits, the return value will be appended with zeros accordingly. + * + * Unlike `Number.prototype.toFixed`, which returns exponential notation if a number is greater or + * equal to 10**21, this method will always return normal notation. + * + * If `decimalPlaces` is omitted, the return value will be unrounded and in normal notation. + * This is also unlike `Number.prototype.toFixed`, which returns the value to zero decimal places. + * It is useful when normal notation is required and the current `EXPONENTIAL_AT` setting causes + * `toString` to return exponential notation. + * + * If `roundingMode` is omitted, `ROUNDING_MODE` is used. + * + * Throws if `decimalPlaces` or `roundingMode` is invalid. + * + * ```ts + * x = 3.456 + * y = new BigNumber(x) + * x.toFixed() // '3' + * y.toFixed() // '3.456' + * y.toFixed(0) // '3' + * x.toFixed(2) // '3.46' + * y.toFixed(2) // '3.46' + * y.toFixed(2, 1) // '3.45' (ROUND_DOWN) + * x.toFixed(5) // '3.45600' + * y.toFixed(5) // '3.45600' + * ``` + * + * @param [decimalPlaces] Decimal places, integer, 0 to 1e+9. + * @param [roundingMode] Rounding mode, integer, 0 to 8. + */ + toFixed(decimalPlaces: number, roundingMode?: BigNumber.RoundingMode): string; + toFixed(): string; + + /** + * Returns a string representing the value of this BigNumber in normal (fixed-point) notation + * rounded to `decimalPlaces` decimal places using rounding mode `roundingMode`, and formatted + * according to the properties of the `format` or `FORMAT` object. + * + * The formatting object may contain some or all of the properties shown in the examples below. + * + * If `decimalPlaces` is omitted, then the return value is not rounded to a fixed number of + * decimal places. + * + * If `roundingMode` is omitted, `ROUNDING_MODE` is used. + * + * If `format` is omitted, `FORMAT` is used. + * + * Throws if `decimalPlaces`, `roundingMode`, or `format` is invalid. + * + * ```ts + * fmt = { + * decimalSeparator: '.', + * groupSeparator: ',', + * groupSize: 3, + * secondaryGroupSize: 0, + * fractionGroupSeparator: ' ', + * fractionGroupSize: 0 + * } + * + * x = new BigNumber('123456789.123456789') + * + * // Set the global formatting options + * BigNumber.config({ FORMAT: fmt }) + * + * x.toFormat() // '123,456,789.123456789' + * x.toFormat(3) // '123,456,789.123' + * + * // If a reference to the object assigned to FORMAT has been retained, + * // the format properties can be changed directly + * fmt.groupSeparator = ' ' + * fmt.fractionGroupSize = 5 + * x.toFormat() // '123 456 789.12345 6789' + * + * // Alternatively, pass the formatting options as an argument + * fmt = { + * decimalSeparator: ',', + * groupSeparator: '.', + * groupSize: 3, + * secondaryGroupSize: 2 + * } + * + * x.toFormat() // '123 456 789.12345 6789' + * x.toFormat(fmt) // '12.34.56.789,123456789' + * x.toFormat(2, fmt) // '12.34.56.789,12' + * x.toFormat(3, BigNumber.ROUND_UP, fmt) // '12.34.56.789,124' + * ``` + * + * @param [decimalPlaces] Decimal places, integer, 0 to 1e+9. + * @param [roundingMode] Rounding mode, integer, 0 to 8. + * @param [format] Formatting options object. See `BigNumber.Format`. + */ + toFormat(decimalPlaces: number, roundingMode: BigNumber.RoundingMode, format?: BigNumber.Format): string; + toFormat(decimalPlaces: number, roundingMode?: BigNumber.RoundingMode): string; + toFormat(decimalPlaces?: number): string; + toFormat(decimalPlaces: number, format: BigNumber.Format): string; + toFormat(format: BigNumber.Format): string; + + /** + * Returns an array of two BigNumbers representing the value of this BigNumber as a simple + * fraction with an integer numerator and an integer denominator. + * The denominator will be a positive non-zero value less than or equal to `max_denominator`. + * If a maximum denominator, `max_denominator`, is not specified, the denominator will be the + * lowest value necessary to represent the number exactly. + * + * Throws if `max_denominator` is invalid. + * + * ```ts + * x = new BigNumber(1.75) + * x.toFraction() // '7, 4' + * + * pi = new BigNumber('3.14159265358') + * pi.toFraction() // '157079632679,50000000000' + * pi.toFraction(100000) // '312689, 99532' + * pi.toFraction(10000) // '355, 113' + * pi.toFraction(100) // '311, 99' + * pi.toFraction(10) // '22, 7' + * pi.toFraction(1) // '3, 1' + * ``` + * + * @param [max_denominator] The maximum denominator, integer > 0, or Infinity. + */ + toFraction(max_denominator?: BigNumber.Value): [BigNumber, BigNumber]; + + /** As `valueOf`. */ + toJSON(): string; + + /** + * Returns the value of this BigNumber as a JavaScript primitive number. + * + * Using the unary plus operator gives the same result. + * + * ```ts + * x = new BigNumber(456.789) + * x.toNumber() // 456.789 + * +x // 456.789 + * + * y = new BigNumber('45987349857634085409857349856430985') + * y.toNumber() // 4.598734985763409e+34 + * + * z = new BigNumber(-0) + * 1 / z.toNumber() // -Infinity + * 1 / +z // -Infinity + * ``` + */ + toNumber(): number; + + /** + * Returns a string representing the value of this BigNumber rounded to `significantDigits` + * significant digits using rounding mode `roundingMode`. + * + * If `significantDigits` is less than the number of digits necessary to represent the integer + * part of the value in normal (fixed-point) notation, then exponential notation is used. + * + * If `significantDigits` is omitted, then the return value is the same as `n.toString()`. + * + * If `roundingMode` is omitted, `ROUNDING_MODE` is used. + * + * Throws if `significantDigits` or `roundingMode` is invalid. + * + * ```ts + * x = 45.6 + * y = new BigNumber(x) + * x.toPrecision() // '45.6' + * y.toPrecision() // '45.6' + * x.toPrecision(1) // '5e+1' + * y.toPrecision(1) // '5e+1' + * y.toPrecision(2, 0) // '4.6e+1' (ROUND_UP) + * y.toPrecision(2, 1) // '4.5e+1' (ROUND_DOWN) + * x.toPrecision(5) // '45.600' + * y.toPrecision(5) // '45.600' + * ``` + * + * @param [significantDigits] Significant digits, integer, 1 to 1e+9. + * @param [roundingMode] Rounding mode, integer 0 to 8. + */ + toPrecision(significantDigits: number, roundingMode?: BigNumber.RoundingMode): string; + toPrecision(): string; + + /** + * Returns a string representing the value of this BigNumber in base `base`, or base 10 if `base` + * is omitted. + * + * For bases above 10, and using the default base conversion alphabet (see `ALPHABET`), values + * from 10 to 35 are represented by a-z (the same as `Number.prototype.toString`). + * + * If a base is specified the value is rounded according to the current `DECIMAL_PLACES` and + * `ROUNDING_MODE` settings, otherwise it is not. + * + * If a base is not specified, and this BigNumber has a positive exponent that is equal to or + * greater than the positive component of the current `EXPONENTIAL_AT` setting, or a negative + * exponent equal to or less than the negative component of the setting, then exponential notation + * is returned. + * + * Throws if `base` is invalid. + * + * ```ts + * x = new BigNumber(750000) + * x.toString() // '750000' + * BigNumber.config({ EXPONENTIAL_AT: 5 }) + * x.toString() // '7.5e+5' + * + * y = new BigNumber(362.875) + * y.toString(2) // '101101010.111' + * y.toString(9) // '442.77777777777777777778' + * y.toString(32) // 'ba.s' + * + * BigNumber.config({ DECIMAL_PLACES: 4 }); + * z = new BigNumber('1.23456789') + * z.toString() // '1.23456789' + * z.toString(10) // '1.2346' + * ``` + * + * @param [base] The base, integer, 2 to 36 (or `ALPHABET.length`, see `ALPHABET`). + */ + toString(base?: number): string; + + /** + * As `toString`, but does not accept a base argument and includes the minus sign for negative + * zero. + * + * ``ts + * x = new BigNumber('-0') + * x.toString() // '0' + * x.valueOf() // '-0' + * y = new BigNumber('1.777e+457') + * y.valueOf() // '1.777e+457' + * ``` + */ + valueOf(): string; + + /** Helps ES6 import. */ + private static readonly default: BigNumber.Constructor; + + /** Helps ES6 import. */ + private static readonly BigNumber: BigNumber.Constructor; + + /** Rounds away from zero. */ + static readonly ROUND_UP: 0; + + /** Rounds towards zero. */ + static readonly ROUND_DOWN: 1; + + /** Rounds towards Infinity. */ + static readonly ROUND_CEIL: 2; + + /** Rounds towards -Infinity. */ + static readonly ROUND_FLOOR: 3; + + /** Rounds towards nearest neighbour. If equidistant, rounds away from zero . */ + static readonly ROUND_HALF_UP: 4; + + /** Rounds towards nearest neighbour. If equidistant, rounds towards zero. */ + static readonly ROUND_HALF_DOWN: 5; + + /** Rounds towards nearest neighbour. If equidistant, rounds towards even neighbour. */ + static readonly ROUND_HALF_EVEN: 6; + + /** Rounds towards nearest neighbour. If equidistant, rounds towards Infinity. */ + static readonly ROUND_HALF_CEIL: 7; + + /** Rounds towards nearest neighbour. If equidistant, rounds towards -Infinity. */ + static readonly ROUND_HALF_FLOOR: 8; + + /** See `MODULO_MODE`. */ + static readonly EUCLID: 9; + + /** + * To aid in debugging, if a `BigNumber.DEBUG` property is `true` then an error will be thrown + * if the BigNumber constructor receives an invalid `BigNumber.Value`, or if `BigNumber.isBigNumber` + * receives a BigNumber instance that is malformed. + * + * ```ts + * // No error, and BigNumber NaN is returned. + * new BigNumber('blurgh') // 'NaN' + * new BigNumber(9, 2) // 'NaN' + * BigNumber.DEBUG = true + * new BigNumber('blurgh') // '[BigNumber Error] Not a number' + * new BigNumber(9, 2) // '[BigNumber Error] Not a base 2 number' + * ``` + * + * An error will also be thrown if a `BigNumber.Value` is of type number with more than 15 + * significant digits, as calling `toString` or `valueOf` on such numbers may not result + * in the intended value. + * + * ```ts + * console.log(823456789123456.3) // 823456789123456.2 + * // No error, and the returned BigNumber does not have the same value as the number literal. + * new BigNumber(823456789123456.3) // '823456789123456.2' + * BigNumber.DEBUG = true + * new BigNumber(823456789123456.3) + * // '[BigNumber Error] Number primitive has more than 15 significant digits' + * ``` + * + * Check that a BigNumber instance is well-formed: + * + * ```ts + * x = new BigNumber(10) + * + * BigNumber.DEBUG = false + * // Change x.c to an illegitimate value. + * x.c = NaN + * // No error, as BigNumber.DEBUG is false. + * BigNumber.isBigNumber(x) // true + * + * BigNumber.DEBUG = true + * BigNumber.isBigNumber(x) // '[BigNumber Error] Invalid BigNumber' + * ``` + */ + static DEBUG?: boolean; + + /** + * Returns a new independent BigNumber constructor with configuration as described by `object`, or + * with the default configuration if object is omitted. + * + * Throws if `object` is not an object. + * + * ```ts + * BigNumber.config({ DECIMAL_PLACES: 5 }) + * BN = BigNumber.clone({ DECIMAL_PLACES: 9 }) + * + * x = new BigNumber(1) + * y = new BN(1) + * + * x.div(3) // 0.33333 + * y.div(3) // 0.333333333 + * + * // BN = BigNumber.clone({ DECIMAL_PLACES: 9 }) is equivalent to: + * BN = BigNumber.clone() + * BN.config({ DECIMAL_PLACES: 9 }) + * ``` + * + * @param [object] The configuration object. + */ + static clone(object?: BigNumber.Config): BigNumber.Constructor; + + /** + * Configures the settings that apply to this BigNumber constructor. + * + * The configuration object, `object`, contains any number of the properties shown in the example + * below. + * + * Returns an object with the above properties and their current values. + * + * Throws if `object` is not an object, or if an invalid value is assigned to one or more of the + * properties. + * + * ```ts + * BigNumber.config({ + * DECIMAL_PLACES: 40, + * ROUNDING_MODE: BigNumber.ROUND_HALF_CEIL, + * EXPONENTIAL_AT: [-10, 20], + * RANGE: [-500, 500], + * CRYPTO: true, + * MODULO_MODE: BigNumber.ROUND_FLOOR, + * POW_PRECISION: 80, + * FORMAT: { + * groupSize: 3, + * groupSeparator: ' ', + * decimalSeparator: ',' + * }, + * ALPHABET: '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_' + * }); + * + * BigNumber.config().DECIMAL_PLACES // 40 + * ``` + * + * @param object The configuration object. + */ + static config(object?: BigNumber.Config): BigNumber.Config; + + /** + * Returns `true` if `value` is a BigNumber instance, otherwise returns `false`. + * + * If `BigNumber.DEBUG` is `true`, throws if a BigNumber instance is not well-formed. + * + * ```ts + * x = 42 + * y = new BigNumber(x) + * + * BigNumber.isBigNumber(x) // false + * y instanceof BigNumber // true + * BigNumber.isBigNumber(y) // true + * + * BN = BigNumber.clone(); + * z = new BN(x) + * z instanceof BigNumber // false + * BigNumber.isBigNumber(z) // true + * ``` + * + * @param value The value to test. + */ + static isBigNumber(value: any): value is BigNumber; + + /** + * Returns a BigNumber whose value is the maximum of the arguments. + * + * The return value is always exact and unrounded. + * + * ```ts + * x = new BigNumber('3257869345.0378653') + * BigNumber.maximum(4e9, x, '123456789.9') // '4000000000' + * + * arr = [12, '13', new BigNumber(14)] + * BigNumber.maximum.apply(null, arr) // '14' + * ``` + * + * @param n A numeric value. + */ + static maximum(...n: BigNumber.Value[]): BigNumber; + + /** + * Returns a BigNumber whose value is the maximum of the arguments. + * + * The return value is always exact and unrounded. + * + * ```ts + * x = new BigNumber('3257869345.0378653') + * BigNumber.max(4e9, x, '123456789.9') // '4000000000' + * + * arr = [12, '13', new BigNumber(14)] + * BigNumber.max.apply(null, arr) // '14' + * ``` + * + * @param n A numeric value. + */ + static max(...n: BigNumber.Value[]): BigNumber; + + /** + * Returns a BigNumber whose value is the minimum of the arguments. + * + * The return value is always exact and unrounded. + * + * ```ts + * x = new BigNumber('3257869345.0378653') + * BigNumber.minimum(4e9, x, '123456789.9') // '123456789.9' + * + * arr = [2, new BigNumber(-14), '-15.9999', -12] + * BigNumber.minimum.apply(null, arr) // '-15.9999' + * ``` + * + * @param n A numeric value. + */ + static minimum(...n: BigNumber.Value[]): BigNumber; + + /** + * Returns a BigNumber whose value is the minimum of the arguments. + * + * The return value is always exact and unrounded. + * + * ```ts + * x = new BigNumber('3257869345.0378653') + * BigNumber.min(4e9, x, '123456789.9') // '123456789.9' + * + * arr = [2, new BigNumber(-14), '-15.9999', -12] + * BigNumber.min.apply(null, arr) // '-15.9999' + * ``` + * + * @param n A numeric value. + */ + static min(...n: BigNumber.Value[]): BigNumber; + + /** + * Returns a new BigNumber with a pseudo-random value equal to or greater than 0 and less than 1. + * + * The return value will have `decimalPlaces` decimal places, or less if trailing zeros are + * produced. If `decimalPlaces` is omitted, the current `DECIMAL_PLACES` setting will be used. + * + * Depending on the value of this BigNumber constructor's `CRYPTO` setting and the support for the + * `crypto` object in the host environment, the random digits of the return value are generated by + * either `Math.random` (fastest), `crypto.getRandomValues` (Web Cryptography API in recent + * browsers) or `crypto.randomBytes` (Node.js). + * + * To be able to set `CRYPTO` to true when using Node.js, the `crypto` object must be available + * globally: + * + * ```ts + * global.crypto = require('crypto') + * ``` + * + * If `CRYPTO` is true, i.e. one of the `crypto` methods is to be used, the value of a returned + * BigNumber should be cryptographically secure and statistically indistinguishable from a random + * value. + * + * Throws if `decimalPlaces` is invalid. + * + * ```ts + * BigNumber.config({ DECIMAL_PLACES: 10 }) + * BigNumber.random() // '0.4117936847' + * BigNumber.random(20) // '0.78193327636914089009' + * ``` + * + * @param [decimalPlaces] Decimal places, integer, 0 to 1e+9. + */ + static random(decimalPlaces?: number): BigNumber; + + /** + * Returns a BigNumber whose value is the sum of the arguments. + * + * The return value is always exact and unrounded. + * + * ```ts + * x = new BigNumber('3257869345.0378653') + * BigNumber.sum(4e9, x, '123456789.9') // '7381326134.9378653' + * + * arr = [2, new BigNumber(14), '15.9999', 12] + * BigNumber.sum.apply(null, arr) // '43.9999' + * ``` + * + * @param n A numeric value. + */ + static sum(...n: BigNumber.Value[]): BigNumber; + + /** + * Configures the settings that apply to this BigNumber constructor. + * + * The configuration object, `object`, contains any number of the properties shown in the example + * below. + * + * Returns an object with the above properties and their current values. + * + * Throws if `object` is not an object, or if an invalid value is assigned to one or more of the + * properties. + * + * ```ts + * BigNumber.set({ + * DECIMAL_PLACES: 40, + * ROUNDING_MODE: BigNumber.ROUND_HALF_CEIL, + * EXPONENTIAL_AT: [-10, 20], + * RANGE: [-500, 500], + * CRYPTO: true, + * MODULO_MODE: BigNumber.ROUND_FLOOR, + * POW_PRECISION: 80, + * FORMAT: { + * groupSize: 3, + * groupSeparator: ' ', + * decimalSeparator: ',' + * }, + * ALPHABET: '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_' + * }); + * + * BigNumber.set().DECIMAL_PLACES // 40 + * ``` + * + * @param object The configuration object. + */ + static set(object?: BigNumber.Config): BigNumber.Config; +} + +declare function BigNumber(n: BigNumber.Value, base?: number): BigNumber; diff --git a/server/node_modules/body-parser/HISTORY.md b/server/node_modules/body-parser/HISTORY.md new file mode 100644 index 0000000..c9b0b5b --- /dev/null +++ b/server/node_modules/body-parser/HISTORY.md @@ -0,0 +1,680 @@ +1.20.4 / 2025-12-01 +=================== + + * deps: qs@~6.14.0 + * deps: use tilde notation for dependencies + * deps: http-errors@~2.0.1 + * deps: raw-body@~2.5.3 + +1.20.3 / 2024-09-10 +=================== + + * deps: qs@6.13.0 + * add `depth` option to customize the depth level in the parser + * IMPORTANT: The default `depth` level for parsing URL-encoded data is now `32` (previously was `Infinity`) + +1.20.2 / 2023-02-21 +=================== + + * Fix strict json error message on Node.js 19+ + * deps: content-type@~1.0.5 + - perf: skip value escaping when unnecessary + * deps: raw-body@2.5.2 + +1.20.1 / 2022-10-06 +=================== + + * deps: qs@6.11.0 + * perf: remove unnecessary object clone + +1.20.0 / 2022-04-02 +=================== + + * Fix error message for json parse whitespace in `strict` + * Fix internal error when inflated body exceeds limit + * Prevent loss of async hooks context + * Prevent hanging when request already read + * deps: depd@2.0.0 + - Replace internal `eval` usage with `Function` constructor + - Use instance methods on `process` to check for listeners + * deps: http-errors@2.0.0 + - deps: depd@2.0.0 + - deps: statuses@2.0.1 + * deps: on-finished@2.4.1 + * deps: qs@6.10.3 + * deps: raw-body@2.5.1 + - deps: http-errors@2.0.0 + +1.19.2 / 2022-02-15 +=================== + + * deps: bytes@3.1.2 + * deps: qs@6.9.7 + * Fix handling of `__proto__` keys + * deps: raw-body@2.4.3 + - deps: bytes@3.1.2 + +1.19.1 / 2021-12-10 +=================== + + * deps: bytes@3.1.1 + * deps: http-errors@1.8.1 + - deps: inherits@2.0.4 + - deps: toidentifier@1.0.1 + - deps: setprototypeof@1.2.0 + * deps: qs@6.9.6 + * deps: raw-body@2.4.2 + - deps: bytes@3.1.1 + - deps: http-errors@1.8.1 + * deps: safe-buffer@5.2.1 + * deps: type-is@~1.6.18 + +1.19.0 / 2019-04-25 +=================== + + * deps: bytes@3.1.0 + - Add petabyte (`pb`) support + * deps: http-errors@1.7.2 + - Set constructor name when possible + - deps: setprototypeof@1.1.1 + - deps: statuses@'>= 1.5.0 < 2' + * deps: iconv-lite@0.4.24 + - Added encoding MIK + * deps: qs@6.7.0 + - Fix parsing array brackets after index + * deps: raw-body@2.4.0 + - deps: bytes@3.1.0 + - deps: http-errors@1.7.2 + - deps: iconv-lite@0.4.24 + * deps: type-is@~1.6.17 + - deps: mime-types@~2.1.24 + - perf: prevent internal `throw` on invalid type + +1.18.3 / 2018-05-14 +=================== + + * Fix stack trace for strict json parse error + * deps: depd@~1.1.2 + - perf: remove argument reassignment + * deps: http-errors@~1.6.3 + - deps: depd@~1.1.2 + - deps: setprototypeof@1.1.0 + - deps: statuses@'>= 1.3.1 < 2' + * deps: iconv-lite@0.4.23 + - Fix loading encoding with year appended + - Fix deprecation warnings on Node.js 10+ + * deps: qs@6.5.2 + * deps: raw-body@2.3.3 + - deps: http-errors@1.6.3 + - deps: iconv-lite@0.4.23 + * deps: type-is@~1.6.16 + - deps: mime-types@~2.1.18 + +1.18.2 / 2017-09-22 +=================== + + * deps: debug@2.6.9 + * perf: remove argument reassignment + +1.18.1 / 2017-09-12 +=================== + + * deps: content-type@~1.0.4 + - perf: remove argument reassignment + - perf: skip parameter parsing when no parameters + * deps: iconv-lite@0.4.19 + - Fix ISO-8859-1 regression + - Update Windows-1255 + * deps: qs@6.5.1 + - Fix parsing & compacting very deep objects + * deps: raw-body@2.3.2 + - deps: iconv-lite@0.4.19 + +1.18.0 / 2017-09-08 +=================== + + * Fix JSON strict violation error to match native parse error + * Include the `body` property on verify errors + * Include the `type` property on all generated errors + * Use `http-errors` to set status code on errors + * deps: bytes@3.0.0 + * deps: debug@2.6.8 + * deps: depd@~1.1.1 + - Remove unnecessary `Buffer` loading + * deps: http-errors@~1.6.2 + - deps: depd@1.1.1 + * deps: iconv-lite@0.4.18 + - Add support for React Native + - Add a warning if not loaded as utf-8 + - Fix CESU-8 decoding in Node.js 8 + - Improve speed of ISO-8859-1 encoding + * deps: qs@6.5.0 + * deps: raw-body@2.3.1 + - Use `http-errors` for standard emitted errors + - deps: bytes@3.0.0 + - deps: iconv-lite@0.4.18 + - perf: skip buffer decoding on overage chunk + * perf: prevent internal `throw` when missing charset + +1.17.2 / 2017-05-17 +=================== + + * deps: debug@2.6.7 + - Fix `DEBUG_MAX_ARRAY_LENGTH` + - deps: ms@2.0.0 + * deps: type-is@~1.6.15 + - deps: mime-types@~2.1.15 + +1.17.1 / 2017-03-06 +=================== + + * deps: qs@6.4.0 + - Fix regression parsing keys starting with `[` + +1.17.0 / 2017-03-01 +=================== + + * deps: http-errors@~1.6.1 + - Make `message` property enumerable for `HttpError`s + - deps: setprototypeof@1.0.3 + * deps: qs@6.3.1 + - Fix compacting nested arrays + +1.16.1 / 2017-02-10 +=================== + + * deps: debug@2.6.1 + - Fix deprecation messages in WebStorm and other editors + - Undeprecate `DEBUG_FD` set to `1` or `2` + +1.16.0 / 2017-01-17 +=================== + + * deps: debug@2.6.0 + - Allow colors in workers + - Deprecated `DEBUG_FD` environment variable + - Fix error when running under React Native + - Use same color for same namespace + - deps: ms@0.7.2 + * deps: http-errors@~1.5.1 + - deps: inherits@2.0.3 + - deps: setprototypeof@1.0.2 + - deps: statuses@'>= 1.3.1 < 2' + * deps: iconv-lite@0.4.15 + - Added encoding MS-31J + - Added encoding MS-932 + - Added encoding MS-936 + - Added encoding MS-949 + - Added encoding MS-950 + - Fix GBK/GB18030 handling of Euro character + * deps: qs@6.2.1 + - Fix array parsing from skipping empty values + * deps: raw-body@~2.2.0 + - deps: iconv-lite@0.4.15 + * deps: type-is@~1.6.14 + - deps: mime-types@~2.1.13 + +1.15.2 / 2016-06-19 +=================== + + * deps: bytes@2.4.0 + * deps: content-type@~1.0.2 + - perf: enable strict mode + * deps: http-errors@~1.5.0 + - Use `setprototypeof` module to replace `__proto__` setting + - deps: statuses@'>= 1.3.0 < 2' + - perf: enable strict mode + * deps: qs@6.2.0 + * deps: raw-body@~2.1.7 + - deps: bytes@2.4.0 + - perf: remove double-cleanup on happy path + * deps: type-is@~1.6.13 + - deps: mime-types@~2.1.11 + +1.15.1 / 2016-05-05 +=================== + + * deps: bytes@2.3.0 + - Drop partial bytes on all parsed units + - Fix parsing byte string that looks like hex + * deps: raw-body@~2.1.6 + - deps: bytes@2.3.0 + * deps: type-is@~1.6.12 + - deps: mime-types@~2.1.10 + +1.15.0 / 2016-02-10 +=================== + + * deps: http-errors@~1.4.0 + - Add `HttpError` export, for `err instanceof createError.HttpError` + - deps: inherits@2.0.1 + - deps: statuses@'>= 1.2.1 < 2' + * deps: qs@6.1.0 + * deps: type-is@~1.6.11 + - deps: mime-types@~2.1.9 + +1.14.2 / 2015-12-16 +=================== + + * deps: bytes@2.2.0 + * deps: iconv-lite@0.4.13 + * deps: qs@5.2.0 + * deps: raw-body@~2.1.5 + - deps: bytes@2.2.0 + - deps: iconv-lite@0.4.13 + * deps: type-is@~1.6.10 + - deps: mime-types@~2.1.8 + +1.14.1 / 2015-09-27 +=================== + + * Fix issue where invalid charset results in 400 when `verify` used + * deps: iconv-lite@0.4.12 + - Fix CESU-8 decoding in Node.js 4.x + * deps: raw-body@~2.1.4 + - Fix masking critical errors from `iconv-lite` + - deps: iconv-lite@0.4.12 + * deps: type-is@~1.6.9 + - deps: mime-types@~2.1.7 + +1.14.0 / 2015-09-16 +=================== + + * Fix JSON strict parse error to match syntax errors + * Provide static `require` analysis in `urlencoded` parser + * deps: depd@~1.1.0 + - Support web browser loading + * deps: qs@5.1.0 + * deps: raw-body@~2.1.3 + - Fix sync callback when attaching data listener causes sync read + * deps: type-is@~1.6.8 + - Fix type error when given invalid type to match against + - deps: mime-types@~2.1.6 + +1.13.3 / 2015-07-31 +=================== + + * deps: type-is@~1.6.6 + - deps: mime-types@~2.1.4 + +1.13.2 / 2015-07-05 +=================== + + * deps: iconv-lite@0.4.11 + * deps: qs@4.0.0 + - Fix dropping parameters like `hasOwnProperty` + - Fix user-visible incompatibilities from 3.1.0 + - Fix various parsing edge cases + * deps: raw-body@~2.1.2 + - Fix error stack traces to skip `makeError` + - deps: iconv-lite@0.4.11 + * deps: type-is@~1.6.4 + - deps: mime-types@~2.1.2 + - perf: enable strict mode + - perf: remove argument reassignment + +1.13.1 / 2015-06-16 +=================== + + * deps: qs@2.4.2 + - Downgraded from 3.1.0 because of user-visible incompatibilities + +1.13.0 / 2015-06-14 +=================== + + * Add `statusCode` property on `Error`s, in addition to `status` + * Change `type` default to `application/json` for JSON parser + * Change `type` default to `application/x-www-form-urlencoded` for urlencoded parser + * Provide static `require` analysis + * Use the `http-errors` module to generate errors + * deps: bytes@2.1.0 + - Slight optimizations + * deps: iconv-lite@0.4.10 + - The encoding UTF-16 without BOM now defaults to UTF-16LE when detection fails + - Leading BOM is now removed when decoding + * deps: on-finished@~2.3.0 + - Add defined behavior for HTTP `CONNECT` requests + - Add defined behavior for HTTP `Upgrade` requests + - deps: ee-first@1.1.1 + * deps: qs@3.1.0 + - Fix dropping parameters like `hasOwnProperty` + - Fix various parsing edge cases + - Parsed object now has `null` prototype + * deps: raw-body@~2.1.1 + - Use `unpipe` module for unpiping requests + - deps: iconv-lite@0.4.10 + * deps: type-is@~1.6.3 + - deps: mime-types@~2.1.1 + - perf: reduce try block size + - perf: remove bitwise operations + * perf: enable strict mode + * perf: remove argument reassignment + * perf: remove delete call + +1.12.4 / 2015-05-10 +=================== + + * deps: debug@~2.2.0 + * deps: qs@2.4.2 + - Fix allowing parameters like `constructor` + * deps: on-finished@~2.2.1 + * deps: raw-body@~2.0.1 + - Fix a false-positive when unpiping in Node.js 0.8 + - deps: bytes@2.0.1 + * deps: type-is@~1.6.2 + - deps: mime-types@~2.0.11 + +1.12.3 / 2015-04-15 +=================== + + * Slight efficiency improvement when not debugging + * deps: depd@~1.0.1 + * deps: iconv-lite@0.4.8 + - Add encoding alias UNICODE-1-1-UTF-7 + * deps: raw-body@1.3.4 + - Fix hanging callback if request aborts during read + - deps: iconv-lite@0.4.8 + +1.12.2 / 2015-03-16 +=================== + + * deps: qs@2.4.1 + - Fix error when parameter `hasOwnProperty` is present + +1.12.1 / 2015-03-15 +=================== + + * deps: debug@~2.1.3 + - Fix high intensity foreground color for bold + - deps: ms@0.7.0 + * deps: type-is@~1.6.1 + - deps: mime-types@~2.0.10 + +1.12.0 / 2015-02-13 +=================== + + * add `debug` messages + * accept a function for the `type` option + * use `content-type` to parse `Content-Type` headers + * deps: iconv-lite@0.4.7 + - Gracefully support enumerables on `Object.prototype` + * deps: raw-body@1.3.3 + - deps: iconv-lite@0.4.7 + * deps: type-is@~1.6.0 + - fix argument reassignment + - fix false-positives in `hasBody` `Transfer-Encoding` check + - support wildcard for both type and subtype (`*/*`) + - deps: mime-types@~2.0.9 + +1.11.0 / 2015-01-30 +=================== + + * make internal `extended: true` depth limit infinity + * deps: type-is@~1.5.6 + - deps: mime-types@~2.0.8 + +1.10.2 / 2015-01-20 +=================== + + * deps: iconv-lite@0.4.6 + - Fix rare aliases of single-byte encodings + * deps: raw-body@1.3.2 + - deps: iconv-lite@0.4.6 + +1.10.1 / 2015-01-01 +=================== + + * deps: on-finished@~2.2.0 + * deps: type-is@~1.5.5 + - deps: mime-types@~2.0.7 + +1.10.0 / 2014-12-02 +=================== + + * make internal `extended: true` array limit dynamic + +1.9.3 / 2014-11-21 +================== + + * deps: iconv-lite@0.4.5 + - Fix Windows-31J and X-SJIS encoding support + * deps: qs@2.3.3 + - Fix `arrayLimit` behavior + * deps: raw-body@1.3.1 + - deps: iconv-lite@0.4.5 + * deps: type-is@~1.5.3 + - deps: mime-types@~2.0.3 + +1.9.2 / 2014-10-27 +================== + + * deps: qs@2.3.2 + - Fix parsing of mixed objects and values + +1.9.1 / 2014-10-22 +================== + + * deps: on-finished@~2.1.1 + - Fix handling of pipelined requests + * deps: qs@2.3.0 + - Fix parsing of mixed implicit and explicit arrays + * deps: type-is@~1.5.2 + - deps: mime-types@~2.0.2 + +1.9.0 / 2014-09-24 +================== + + * include the charset in "unsupported charset" error message + * include the encoding in "unsupported content encoding" error message + * deps: depd@~1.0.0 + +1.8.4 / 2014-09-23 +================== + + * fix content encoding to be case-insensitive + +1.8.3 / 2014-09-19 +================== + + * deps: qs@2.2.4 + - Fix issue with object keys starting with numbers truncated + +1.8.2 / 2014-09-15 +================== + + * deps: depd@0.4.5 + +1.8.1 / 2014-09-07 +================== + + * deps: media-typer@0.3.0 + * deps: type-is@~1.5.1 + +1.8.0 / 2014-09-05 +================== + + * make empty-body-handling consistent between chunked requests + - empty `json` produces `{}` + - empty `raw` produces `new Buffer(0)` + - empty `text` produces `''` + - empty `urlencoded` produces `{}` + * deps: qs@2.2.3 + - Fix issue where first empty value in array is discarded + * deps: type-is@~1.5.0 + - fix `hasbody` to be true for `content-length: 0` + +1.7.0 / 2014-09-01 +================== + + * add `parameterLimit` option to `urlencoded` parser + * change `urlencoded` extended array limit to 100 + * respond with 413 when over `parameterLimit` in `urlencoded` + +1.6.7 / 2014-08-29 +================== + + * deps: qs@2.2.2 + - Remove unnecessary cloning + +1.6.6 / 2014-08-27 +================== + + * deps: qs@2.2.0 + - Array parsing fix + - Performance improvements + +1.6.5 / 2014-08-16 +================== + + * deps: on-finished@2.1.0 + +1.6.4 / 2014-08-14 +================== + + * deps: qs@1.2.2 + +1.6.3 / 2014-08-10 +================== + + * deps: qs@1.2.1 + +1.6.2 / 2014-08-07 +================== + + * deps: qs@1.2.0 + - Fix parsing array of objects + +1.6.1 / 2014-08-06 +================== + + * deps: qs@1.1.0 + - Accept urlencoded square brackets + - Accept empty values in implicit array notation + +1.6.0 / 2014-08-05 +================== + + * deps: qs@1.0.2 + - Complete rewrite + - Limits array length to 20 + - Limits object depth to 5 + - Limits parameters to 1,000 + +1.5.2 / 2014-07-27 +================== + + * deps: depd@0.4.4 + - Work-around v8 generating empty stack traces + +1.5.1 / 2014-07-26 +================== + + * deps: depd@0.4.3 + - Fix exception when global `Error.stackTraceLimit` is too low + +1.5.0 / 2014-07-20 +================== + + * deps: depd@0.4.2 + - Add `TRACE_DEPRECATION` environment variable + - Remove non-standard grey color from color output + - Support `--no-deprecation` argument + - Support `--trace-deprecation` argument + * deps: iconv-lite@0.4.4 + - Added encoding UTF-7 + * deps: raw-body@1.3.0 + - deps: iconv-lite@0.4.4 + - Added encoding UTF-7 + - Fix `Cannot switch to old mode now` error on Node.js 0.10+ + * deps: type-is@~1.3.2 + +1.4.3 / 2014-06-19 +================== + + * deps: type-is@1.3.1 + - fix global variable leak + +1.4.2 / 2014-06-19 +================== + + * deps: type-is@1.3.0 + - improve type parsing + +1.4.1 / 2014-06-19 +================== + + * fix urlencoded extended deprecation message + +1.4.0 / 2014-06-19 +================== + + * add `text` parser + * add `raw` parser + * check accepted charset in content-type (accepts utf-8) + * check accepted encoding in content-encoding (accepts identity) + * deprecate `bodyParser()` middleware; use `.json()` and `.urlencoded()` as needed + * deprecate `urlencoded()` without provided `extended` option + * lazy-load urlencoded parsers + * parsers split into files for reduced mem usage + * support gzip and deflate bodies + - set `inflate: false` to turn off + * deps: raw-body@1.2.2 + - Support all encodings from `iconv-lite` + +1.3.1 / 2014-06-11 +================== + + * deps: type-is@1.2.1 + - Switch dependency from mime to mime-types@1.0.0 + +1.3.0 / 2014-05-31 +================== + + * add `extended` option to urlencoded parser + +1.2.2 / 2014-05-27 +================== + + * deps: raw-body@1.1.6 + - assert stream encoding on node.js 0.8 + - assert stream encoding on node.js < 0.10.6 + - deps: bytes@1 + +1.2.1 / 2014-05-26 +================== + + * invoke `next(err)` after request fully read + - prevents hung responses and socket hang ups + +1.2.0 / 2014-05-11 +================== + + * add `verify` option + * deps: type-is@1.2.0 + - support suffix matching + +1.1.2 / 2014-05-11 +================== + + * improve json parser speed + +1.1.1 / 2014-05-11 +================== + + * fix repeated limit parsing with every request + +1.1.0 / 2014-05-10 +================== + + * add `type` option + * deps: pin for safety and consistency + +1.0.2 / 2014-04-14 +================== + + * use `type-is` module + +1.0.1 / 2014-03-20 +================== + + * lower default limits to 100kb diff --git a/server/node_modules/body-parser/LICENSE b/server/node_modules/body-parser/LICENSE new file mode 100644 index 0000000..386b7b6 --- /dev/null +++ b/server/node_modules/body-parser/LICENSE @@ -0,0 +1,23 @@ +(The MIT License) + +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2014-2015 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/server/node_modules/body-parser/README.md b/server/node_modules/body-parser/README.md new file mode 100644 index 0000000..f6661b7 --- /dev/null +++ b/server/node_modules/body-parser/README.md @@ -0,0 +1,476 @@ +# body-parser + +[![NPM Version][npm-version-image]][npm-url] +[![NPM Downloads][npm-downloads-image]][npm-url] +[![Build Status][ci-image]][ci-url] +[![Test Coverage][coveralls-image]][coveralls-url] +[![OpenSSF Scorecard Badge][ossf-scorecard-badge]][ossf-scorecard-visualizer] + +Node.js body parsing middleware. + +Parse incoming request bodies in a middleware before your handlers, available +under the `req.body` property. + +**Note** As `req.body`'s shape is based on user-controlled input, all +properties and values in this object are untrusted and should be validated +before trusting. For example, `req.body.foo.toString()` may fail in multiple +ways, for example the `foo` property may not be there or may not be a string, +and `toString` may not be a function and instead a string or other user input. + +[Learn about the anatomy of an HTTP transaction in Node.js](https://nodejs.org/en/docs/guides/anatomy-of-an-http-transaction/). + +_This does not handle multipart bodies_, due to their complex and typically +large nature. For multipart bodies, you may be interested in the following +modules: + + * [busboy](https://www.npmjs.org/package/busboy#readme) and + [connect-busboy](https://www.npmjs.org/package/connect-busboy#readme) + * [multiparty](https://www.npmjs.org/package/multiparty#readme) and + [connect-multiparty](https://www.npmjs.org/package/connect-multiparty#readme) + * [formidable](https://www.npmjs.org/package/formidable#readme) + * [multer](https://www.npmjs.org/package/multer#readme) + +This module provides the following parsers: + + * [JSON body parser](#bodyparserjsonoptions) + * [Raw body parser](#bodyparserrawoptions) + * [Text body parser](#bodyparsertextoptions) + * [URL-encoded form body parser](#bodyparserurlencodedoptions) + +Other body parsers you might be interested in: + +- [body](https://www.npmjs.org/package/body#readme) +- [co-body](https://www.npmjs.org/package/co-body#readme) + +## Installation + +```sh +$ npm install body-parser +``` + +## API + +```js +var bodyParser = require('body-parser') +``` + +The `bodyParser` object exposes various factories to create middlewares. All +middlewares will populate the `req.body` property with the parsed body when +the `Content-Type` request header matches the `type` option, or an empty +object (`{}`) if there was no body to parse, the `Content-Type` was not matched, +or an error occurred. + +The various errors returned by this module are described in the +[errors section](#errors). + +### bodyParser.json([options]) + +Returns middleware that only parses `json` and only looks at requests where +the `Content-Type` header matches the `type` option. This parser accepts any +Unicode encoding of the body and supports automatic inflation of `gzip` and +`deflate` encodings. + +A new `body` object containing the parsed data is populated on the `request` +object after the middleware (i.e. `req.body`). + +#### Options + +The `json` function takes an optional `options` object that may contain any of +the following keys: + +##### inflate + +When set to `true`, then deflated (compressed) bodies will be inflated; when +`false`, deflated bodies are rejected. Defaults to `true`. + +##### limit + +Controls the maximum request body size. If this is a number, then the value +specifies the number of bytes; if it is a string, the value is passed to the +[bytes](https://www.npmjs.com/package/bytes) library for parsing. Defaults +to `'100kb'`. + +##### reviver + +The `reviver` option is passed directly to `JSON.parse` as the second +argument. You can find more information on this argument +[in the MDN documentation about JSON.parse](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#Example.3A_Using_the_reviver_parameter). + +##### strict + +When set to `true`, will only accept arrays and objects; when `false` will +accept anything `JSON.parse` accepts. Defaults to `true`. + +##### type + +The `type` option is used to determine what media type the middleware will +parse. This option can be a string, array of strings, or a function. If not a +function, `type` option is passed directly to the +[type-is](https://www.npmjs.org/package/type-is#readme) library and this can +be an extension name (like `json`), a mime type (like `application/json`), or +a mime type with a wildcard (like `*/*` or `*/json`). If a function, the `type` +option is called as `fn(req)` and the request is parsed if it returns a truthy +value. Defaults to `application/json`. + +##### verify + +The `verify` option, if supplied, is called as `verify(req, res, buf, encoding)`, +where `buf` is a `Buffer` of the raw request body and `encoding` is the +encoding of the request. The parsing can be aborted by throwing an error. + +### bodyParser.raw([options]) + +Returns middleware that parses all bodies as a `Buffer` and only looks at +requests where the `Content-Type` header matches the `type` option. This +parser supports automatic inflation of `gzip` and `deflate` encodings. + +A new `body` object containing the parsed data is populated on the `request` +object after the middleware (i.e. `req.body`). This will be a `Buffer` object +of the body. + +#### Options + +The `raw` function takes an optional `options` object that may contain any of +the following keys: + +##### inflate + +When set to `true`, then deflated (compressed) bodies will be inflated; when +`false`, deflated bodies are rejected. Defaults to `true`. + +##### limit + +Controls the maximum request body size. If this is a number, then the value +specifies the number of bytes; if it is a string, the value is passed to the +[bytes](https://www.npmjs.com/package/bytes) library for parsing. Defaults +to `'100kb'`. + +##### type + +The `type` option is used to determine what media type the middleware will +parse. This option can be a string, array of strings, or a function. +If not a function, `type` option is passed directly to the +[type-is](https://www.npmjs.org/package/type-is#readme) library and this +can be an extension name (like `bin`), a mime type (like +`application/octet-stream`), or a mime type with a wildcard (like `*/*` or +`application/*`). If a function, the `type` option is called as `fn(req)` +and the request is parsed if it returns a truthy value. Defaults to +`application/octet-stream`. + +##### verify + +The `verify` option, if supplied, is called as `verify(req, res, buf, encoding)`, +where `buf` is a `Buffer` of the raw request body and `encoding` is the +encoding of the request. The parsing can be aborted by throwing an error. + +### bodyParser.text([options]) + +Returns middleware that parses all bodies as a string and only looks at +requests where the `Content-Type` header matches the `type` option. This +parser supports automatic inflation of `gzip` and `deflate` encodings. + +A new `body` string containing the parsed data is populated on the `request` +object after the middleware (i.e. `req.body`). This will be a string of the +body. + +#### Options + +The `text` function takes an optional `options` object that may contain any of +the following keys: + +##### defaultCharset + +Specify the default character set for the text content if the charset is not +specified in the `Content-Type` header of the request. Defaults to `utf-8`. + +##### inflate + +When set to `true`, then deflated (compressed) bodies will be inflated; when +`false`, deflated bodies are rejected. Defaults to `true`. + +##### limit + +Controls the maximum request body size. If this is a number, then the value +specifies the number of bytes; if it is a string, the value is passed to the +[bytes](https://www.npmjs.com/package/bytes) library for parsing. Defaults +to `'100kb'`. + +##### type + +The `type` option is used to determine what media type the middleware will +parse. This option can be a string, array of strings, or a function. If not +a function, `type` option is passed directly to the +[type-is](https://www.npmjs.org/package/type-is#readme) library and this can +be an extension name (like `txt`), a mime type (like `text/plain`), or a mime +type with a wildcard (like `*/*` or `text/*`). If a function, the `type` +option is called as `fn(req)` and the request is parsed if it returns a +truthy value. Defaults to `text/plain`. + +##### verify + +The `verify` option, if supplied, is called as `verify(req, res, buf, encoding)`, +where `buf` is a `Buffer` of the raw request body and `encoding` is the +encoding of the request. The parsing can be aborted by throwing an error. + +### bodyParser.urlencoded([options]) + +Returns middleware that only parses `urlencoded` bodies and only looks at +requests where the `Content-Type` header matches the `type` option. This +parser accepts only UTF-8 encoding of the body and supports automatic +inflation of `gzip` and `deflate` encodings. + +A new `body` object containing the parsed data is populated on the `request` +object after the middleware (i.e. `req.body`). This object will contain +key-value pairs, where the value can be a string or array (when `extended` is +`false`), or any type (when `extended` is `true`). + +#### Options + +The `urlencoded` function takes an optional `options` object that may contain +any of the following keys: + +##### extended + +The `extended` option allows to choose between parsing the URL-encoded data +with the `querystring` library (when `false`) or the `qs` library (when +`true`). The "extended" syntax allows for rich objects and arrays to be +encoded into the URL-encoded format, allowing for a JSON-like experience +with URL-encoded. For more information, please +[see the qs library](https://www.npmjs.org/package/qs#readme). + +Defaults to `true`, but using the default has been deprecated. Please +research into the difference between `qs` and `querystring` and choose the +appropriate setting. + +##### inflate + +When set to `true`, then deflated (compressed) bodies will be inflated; when +`false`, deflated bodies are rejected. Defaults to `true`. + +##### limit + +Controls the maximum request body size. If this is a number, then the value +specifies the number of bytes; if it is a string, the value is passed to the +[bytes](https://www.npmjs.com/package/bytes) library for parsing. Defaults +to `'100kb'`. + +##### parameterLimit + +The `parameterLimit` option controls the maximum number of parameters that +are allowed in the URL-encoded data. If a request contains more parameters +than this value, a 413 will be returned to the client. Defaults to `1000`. + +##### type + +The `type` option is used to determine what media type the middleware will +parse. This option can be a string, array of strings, or a function. If not +a function, `type` option is passed directly to the +[type-is](https://www.npmjs.org/package/type-is#readme) library and this can +be an extension name (like `urlencoded`), a mime type (like +`application/x-www-form-urlencoded`), or a mime type with a wildcard (like +`*/x-www-form-urlencoded`). If a function, the `type` option is called as +`fn(req)` and the request is parsed if it returns a truthy value. Defaults +to `application/x-www-form-urlencoded`. + +##### verify + +The `verify` option, if supplied, is called as `verify(req, res, buf, encoding)`, +where `buf` is a `Buffer` of the raw request body and `encoding` is the +encoding of the request. The parsing can be aborted by throwing an error. + +#### depth + +The `depth` option is used to configure the maximum depth of the `qs` library when `extended` is `true`. This allows you to limit the amount of keys that are parsed and can be useful to prevent certain types of abuse. Defaults to `32`. It is recommended to keep this value as low as possible. + +## Errors + +The middlewares provided by this module create errors using the +[`http-errors` module](https://www.npmjs.com/package/http-errors). The errors +will typically have a `status`/`statusCode` property that contains the suggested +HTTP response code, an `expose` property to determine if the `message` property +should be displayed to the client, a `type` property to determine the type of +error without matching against the `message`, and a `body` property containing +the read body, if available. + +The following are the common errors created, though any error can come through +for various reasons. + +### content encoding unsupported + +This error will occur when the request had a `Content-Encoding` header that +contained an encoding but the "inflation" option was set to `false`. The +`status` property is set to `415`, the `type` property is set to +`'encoding.unsupported'`, and the `charset` property will be set to the +encoding that is unsupported. + +### entity parse failed + +This error will occur when the request contained an entity that could not be +parsed by the middleware. The `status` property is set to `400`, the `type` +property is set to `'entity.parse.failed'`, and the `body` property is set to +the entity value that failed parsing. + +### entity verify failed + +This error will occur when the request contained an entity that could not be +failed verification by the defined `verify` option. The `status` property is +set to `403`, the `type` property is set to `'entity.verify.failed'`, and the +`body` property is set to the entity value that failed verification. + +### request aborted + +This error will occur when the request is aborted by the client before reading +the body has finished. The `received` property will be set to the number of +bytes received before the request was aborted and the `expected` property is +set to the number of expected bytes. The `status` property is set to `400` +and `type` property is set to `'request.aborted'`. + +### request entity too large + +This error will occur when the request body's size is larger than the "limit" +option. The `limit` property will be set to the byte limit and the `length` +property will be set to the request body's length. The `status` property is +set to `413` and the `type` property is set to `'entity.too.large'`. + +### request size did not match content length + +This error will occur when the request's length did not match the length from +the `Content-Length` header. This typically occurs when the request is malformed, +typically when the `Content-Length` header was calculated based on characters +instead of bytes. The `status` property is set to `400` and the `type` property +is set to `'request.size.invalid'`. + +### stream encoding should not be set + +This error will occur when something called the `req.setEncoding` method prior +to this middleware. This module operates directly on bytes only and you cannot +call `req.setEncoding` when using this module. The `status` property is set to +`500` and the `type` property is set to `'stream.encoding.set'`. + +### stream is not readable + +This error will occur when the request is no longer readable when this middleware +attempts to read it. This typically means something other than a middleware from +this module read the request body already and the middleware was also configured to +read the same request. The `status` property is set to `500` and the `type` +property is set to `'stream.not.readable'`. + +### too many parameters + +This error will occur when the content of the request exceeds the configured +`parameterLimit` for the `urlencoded` parser. The `status` property is set to +`413` and the `type` property is set to `'parameters.too.many'`. + +### unsupported charset "BOGUS" + +This error will occur when the request had a charset parameter in the +`Content-Type` header, but the `iconv-lite` module does not support it OR the +parser does not support it. The charset is contained in the message as well +as in the `charset` property. The `status` property is set to `415`, the +`type` property is set to `'charset.unsupported'`, and the `charset` property +is set to the charset that is unsupported. + +### unsupported content encoding "bogus" + +This error will occur when the request had a `Content-Encoding` header that +contained an unsupported encoding. The encoding is contained in the message +as well as in the `encoding` property. The `status` property is set to `415`, +the `type` property is set to `'encoding.unsupported'`, and the `encoding` +property is set to the encoding that is unsupported. + +### The input exceeded the depth + +This error occurs when using `bodyParser.urlencoded` with the `extended` property set to `true` and the input exceeds the configured `depth` option. The `status` property is set to `400`. It is recommended to review the `depth` option and evaluate if it requires a higher value. When the `depth` option is set to `32` (default value), the error will not be thrown. + +## Examples + +### Express/Connect top-level generic + +This example demonstrates adding a generic JSON and URL-encoded parser as a +top-level middleware, which will parse the bodies of all incoming requests. +This is the simplest setup. + +```js +var express = require('express') +var bodyParser = require('body-parser') + +var app = express() + +// parse application/x-www-form-urlencoded +app.use(bodyParser.urlencoded({ extended: false })) + +// parse application/json +app.use(bodyParser.json()) + +app.use(function (req, res) { + res.setHeader('Content-Type', 'text/plain') + res.write('you posted:\n') + res.end(JSON.stringify(req.body, null, 2)) +}) +``` + +### Express route-specific + +This example demonstrates adding body parsers specifically to the routes that +need them. In general, this is the most recommended way to use body-parser with +Express. + +```js +var express = require('express') +var bodyParser = require('body-parser') + +var app = express() + +// create application/json parser +var jsonParser = bodyParser.json() + +// create application/x-www-form-urlencoded parser +var urlencodedParser = bodyParser.urlencoded({ extended: false }) + +// POST /login gets urlencoded bodies +app.post('/login', urlencodedParser, function (req, res) { + res.send('welcome, ' + req.body.username) +}) + +// POST /api/users gets JSON bodies +app.post('/api/users', jsonParser, function (req, res) { + // create user in req.body +}) +``` + +### Change accepted type for parsers + +All the parsers accept a `type` option which allows you to change the +`Content-Type` that the middleware will parse. + +```js +var express = require('express') +var bodyParser = require('body-parser') + +var app = express() + +// parse various different custom JSON types as JSON +app.use(bodyParser.json({ type: 'application/*+json' })) + +// parse some custom thing into a Buffer +app.use(bodyParser.raw({ type: 'application/vnd.custom-type' })) + +// parse an HTML body into a string +app.use(bodyParser.text({ type: 'text/html' })) +``` + +## License + +[MIT](LICENSE) + +[ci-image]: https://badgen.net/github/checks/expressjs/body-parser/master?label=ci +[ci-url]: https://github.com/expressjs/body-parser/actions/workflows/ci.yml +[coveralls-image]: https://badgen.net/coveralls/c/github/expressjs/body-parser/master +[coveralls-url]: https://coveralls.io/r/expressjs/body-parser?branch=master +[node-version-image]: https://badgen.net/npm/node/body-parser +[node-version-url]: https://nodejs.org/en/download +[npm-downloads-image]: https://badgen.net/npm/dm/body-parser +[npm-url]: https://npmjs.org/package/body-parser +[npm-version-image]: https://badgen.net/npm/v/body-parser +[ossf-scorecard-badge]: https://api.scorecard.dev/projects/github.com/expressjs/body-parser/badge +[ossf-scorecard-visualizer]: https://ossf.github.io/scorecard-visualizer/#/projects/github.com/expressjs/body-parser \ No newline at end of file diff --git a/server/node_modules/body-parser/index.js b/server/node_modules/body-parser/index.js new file mode 100644 index 0000000..bb24d73 --- /dev/null +++ b/server/node_modules/body-parser/index.js @@ -0,0 +1,156 @@ +/*! + * body-parser + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module dependencies. + * @private + */ + +var deprecate = require('depd')('body-parser') + +/** + * Cache of loaded parsers. + * @private + */ + +var parsers = Object.create(null) + +/** + * @typedef Parsers + * @type {function} + * @property {function} json + * @property {function} raw + * @property {function} text + * @property {function} urlencoded + */ + +/** + * Module exports. + * @type {Parsers} + */ + +exports = module.exports = deprecate.function(bodyParser, + 'bodyParser: use individual json/urlencoded middlewares') + +/** + * JSON parser. + * @public + */ + +Object.defineProperty(exports, 'json', { + configurable: true, + enumerable: true, + get: createParserGetter('json') +}) + +/** + * Raw parser. + * @public + */ + +Object.defineProperty(exports, 'raw', { + configurable: true, + enumerable: true, + get: createParserGetter('raw') +}) + +/** + * Text parser. + * @public + */ + +Object.defineProperty(exports, 'text', { + configurable: true, + enumerable: true, + get: createParserGetter('text') +}) + +/** + * URL-encoded parser. + * @public + */ + +Object.defineProperty(exports, 'urlencoded', { + configurable: true, + enumerable: true, + get: createParserGetter('urlencoded') +}) + +/** + * Create a middleware to parse json and urlencoded bodies. + * + * @param {object} [options] + * @return {function} + * @deprecated + * @public + */ + +function bodyParser (options) { + // use default type for parsers + var opts = Object.create(options || null, { + type: { + configurable: true, + enumerable: true, + value: undefined, + writable: true + } + }) + + var _urlencoded = exports.urlencoded(opts) + var _json = exports.json(opts) + + return function bodyParser (req, res, next) { + _json(req, res, function (err) { + if (err) return next(err) + _urlencoded(req, res, next) + }) + } +} + +/** + * Create a getter for loading a parser. + * @private + */ + +function createParserGetter (name) { + return function get () { + return loadParser(name) + } +} + +/** + * Load a parser module. + * @private + */ + +function loadParser (parserName) { + var parser = parsers[parserName] + + if (parser !== undefined) { + return parser + } + + // this uses a switch for static require analysis + switch (parserName) { + case 'json': + parser = require('./lib/types/json') + break + case 'raw': + parser = require('./lib/types/raw') + break + case 'text': + parser = require('./lib/types/text') + break + case 'urlencoded': + parser = require('./lib/types/urlencoded') + break + } + + // store to prevent invoking require() + return (parsers[parserName] = parser) +} diff --git a/server/node_modules/body-parser/lib/read.js b/server/node_modules/body-parser/lib/read.js new file mode 100644 index 0000000..fce6283 --- /dev/null +++ b/server/node_modules/body-parser/lib/read.js @@ -0,0 +1,205 @@ +/*! + * body-parser + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module dependencies. + * @private + */ + +var createError = require('http-errors') +var destroy = require('destroy') +var getBody = require('raw-body') +var iconv = require('iconv-lite') +var onFinished = require('on-finished') +var unpipe = require('unpipe') +var zlib = require('zlib') + +/** + * Module exports. + */ + +module.exports = read + +/** + * Read a request into a buffer and parse. + * + * @param {object} req + * @param {object} res + * @param {function} next + * @param {function} parse + * @param {function} debug + * @param {object} options + * @private + */ + +function read (req, res, next, parse, debug, options) { + var length + var opts = options + var stream + + // flag as parsed + req._body = true + + // read options + var encoding = opts.encoding !== null + ? opts.encoding + : null + var verify = opts.verify + + try { + // get the content stream + stream = contentstream(req, debug, opts.inflate) + length = stream.length + stream.length = undefined + } catch (err) { + return next(err) + } + + // set raw-body options + opts.length = length + opts.encoding = verify + ? null + : encoding + + // assert charset is supported + if (opts.encoding === null && encoding !== null && !iconv.encodingExists(encoding)) { + return next(createError(415, 'unsupported charset "' + encoding.toUpperCase() + '"', { + charset: encoding.toLowerCase(), + type: 'charset.unsupported' + })) + } + + // read body + debug('read body') + getBody(stream, opts, function (error, body) { + if (error) { + var _error + + if (error.type === 'encoding.unsupported') { + // echo back charset + _error = createError(415, 'unsupported charset "' + encoding.toUpperCase() + '"', { + charset: encoding.toLowerCase(), + type: 'charset.unsupported' + }) + } else { + // set status code on error + _error = createError(400, error) + } + + // unpipe from stream and destroy + if (stream !== req) { + unpipe(req) + destroy(stream, true) + } + + // read off entire request + dump(req, function onfinished () { + next(createError(400, _error)) + }) + return + } + + // verify + if (verify) { + try { + debug('verify body') + verify(req, res, body, encoding) + } catch (err) { + next(createError(403, err, { + body: body, + type: err.type || 'entity.verify.failed' + })) + return + } + } + + // parse + var str = body + try { + debug('parse body') + str = typeof body !== 'string' && encoding !== null + ? iconv.decode(body, encoding) + : body + req.body = parse(str) + } catch (err) { + next(createError(400, err, { + body: str, + type: err.type || 'entity.parse.failed' + })) + return + } + + next() + }) +} + +/** + * Get the content stream of the request. + * + * @param {object} req + * @param {function} debug + * @param {boolean} [inflate=true] + * @return {object} + * @api private + */ + +function contentstream (req, debug, inflate) { + var encoding = (req.headers['content-encoding'] || 'identity').toLowerCase() + var length = req.headers['content-length'] + var stream + + debug('content-encoding "%s"', encoding) + + if (inflate === false && encoding !== 'identity') { + throw createError(415, 'content encoding unsupported', { + encoding: encoding, + type: 'encoding.unsupported' + }) + } + + switch (encoding) { + case 'deflate': + stream = zlib.createInflate() + debug('inflate body') + req.pipe(stream) + break + case 'gzip': + stream = zlib.createGunzip() + debug('gunzip body') + req.pipe(stream) + break + case 'identity': + stream = req + stream.length = length + break + default: + throw createError(415, 'unsupported content encoding "' + encoding + '"', { + encoding: encoding, + type: 'encoding.unsupported' + }) + } + + return stream +} + +/** + * Dump the contents of a request. + * + * @param {object} req + * @param {function} callback + * @api private + */ + +function dump (req, callback) { + if (onFinished.isFinished(req)) { + callback(null) + } else { + onFinished(req, callback) + req.resume() + } +} diff --git a/server/node_modules/body-parser/lib/types/json.js b/server/node_modules/body-parser/lib/types/json.js new file mode 100644 index 0000000..59f3f7e --- /dev/null +++ b/server/node_modules/body-parser/lib/types/json.js @@ -0,0 +1,247 @@ +/*! + * body-parser + * Copyright(c) 2014 Jonathan Ong + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module dependencies. + * @private + */ + +var bytes = require('bytes') +var contentType = require('content-type') +var createError = require('http-errors') +var debug = require('debug')('body-parser:json') +var read = require('../read') +var typeis = require('type-is') + +/** + * Module exports. + */ + +module.exports = json + +/** + * RegExp to match the first non-space in a string. + * + * Allowed whitespace is defined in RFC 7159: + * + * ws = *( + * %x20 / ; Space + * %x09 / ; Horizontal tab + * %x0A / ; Line feed or New line + * %x0D ) ; Carriage return + */ + +var FIRST_CHAR_REGEXP = /^[\x20\x09\x0a\x0d]*([^\x20\x09\x0a\x0d])/ // eslint-disable-line no-control-regex + +var JSON_SYNTAX_CHAR = '#' +var JSON_SYNTAX_REGEXP = /#+/g + +/** + * Create a middleware to parse JSON bodies. + * + * @param {object} [options] + * @return {function} + * @public + */ + +function json (options) { + var opts = options || {} + + var limit = typeof opts.limit !== 'number' + ? bytes.parse(opts.limit || '100kb') + : opts.limit + var inflate = opts.inflate !== false + var reviver = opts.reviver + var strict = opts.strict !== false + var type = opts.type || 'application/json' + var verify = opts.verify || false + + if (verify !== false && typeof verify !== 'function') { + throw new TypeError('option verify must be function') + } + + // create the appropriate type checking function + var shouldParse = typeof type !== 'function' + ? typeChecker(type) + : type + + function parse (body) { + if (body.length === 0) { + // special-case empty json body, as it's a common client-side mistake + // TODO: maybe make this configurable or part of "strict" option + return {} + } + + if (strict) { + var first = firstchar(body) + + if (first !== '{' && first !== '[') { + debug('strict violation') + throw createStrictSyntaxError(body, first) + } + } + + try { + debug('parse json') + return JSON.parse(body, reviver) + } catch (e) { + throw normalizeJsonSyntaxError(e, { + message: e.message, + stack: e.stack + }) + } + } + + return function jsonParser (req, res, next) { + if (req._body) { + debug('body already parsed') + next() + return + } + + req.body = req.body || {} + + // skip requests without bodies + if (!typeis.hasBody(req)) { + debug('skip empty body') + next() + return + } + + debug('content-type %j', req.headers['content-type']) + + // determine if request should be parsed + if (!shouldParse(req)) { + debug('skip parsing') + next() + return + } + + // assert charset per RFC 7159 sec 8.1 + var charset = getCharset(req) || 'utf-8' + if (charset.slice(0, 4) !== 'utf-') { + debug('invalid charset') + next(createError(415, 'unsupported charset "' + charset.toUpperCase() + '"', { + charset: charset, + type: 'charset.unsupported' + })) + return + } + + // read + read(req, res, next, parse, debug, { + encoding: charset, + inflate: inflate, + limit: limit, + verify: verify + }) + } +} + +/** + * Create strict violation syntax error matching native error. + * + * @param {string} str + * @param {string} char + * @return {Error} + * @private + */ + +function createStrictSyntaxError (str, char) { + var index = str.indexOf(char) + var partial = '' + + if (index !== -1) { + partial = str.substring(0, index) + JSON_SYNTAX_CHAR + + for (var i = index + 1; i < str.length; i++) { + partial += JSON_SYNTAX_CHAR + } + } + + try { + JSON.parse(partial); /* istanbul ignore next */ throw new SyntaxError('strict violation') + } catch (e) { + return normalizeJsonSyntaxError(e, { + message: e.message.replace(JSON_SYNTAX_REGEXP, function (placeholder) { + return str.substring(index, index + placeholder.length) + }), + stack: e.stack + }) + } +} + +/** + * Get the first non-whitespace character in a string. + * + * @param {string} str + * @return {function} + * @private + */ + +function firstchar (str) { + var match = FIRST_CHAR_REGEXP.exec(str) + + return match + ? match[1] + : undefined +} + +/** + * Get the charset of a request. + * + * @param {object} req + * @api private + */ + +function getCharset (req) { + try { + return (contentType.parse(req).parameters.charset || '').toLowerCase() + } catch (e) { + return undefined + } +} + +/** + * Normalize a SyntaxError for JSON.parse. + * + * @param {SyntaxError} error + * @param {object} obj + * @return {SyntaxError} + */ + +function normalizeJsonSyntaxError (error, obj) { + var keys = Object.getOwnPropertyNames(error) + + for (var i = 0; i < keys.length; i++) { + var key = keys[i] + if (key !== 'stack' && key !== 'message') { + delete error[key] + } + } + + // replace stack before message for Node.js 0.10 and below + error.stack = obj.stack.replace(error.message, obj.message) + error.message = obj.message + + return error +} + +/** + * Get the simple type checker. + * + * @param {string} type + * @return {function} + */ + +function typeChecker (type) { + return function checkType (req) { + return Boolean(typeis(req, type)) + } +} diff --git a/server/node_modules/body-parser/lib/types/raw.js b/server/node_modules/body-parser/lib/types/raw.js new file mode 100644 index 0000000..f5d1b67 --- /dev/null +++ b/server/node_modules/body-parser/lib/types/raw.js @@ -0,0 +1,101 @@ +/*! + * body-parser + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module dependencies. + */ + +var bytes = require('bytes') +var debug = require('debug')('body-parser:raw') +var read = require('../read') +var typeis = require('type-is') + +/** + * Module exports. + */ + +module.exports = raw + +/** + * Create a middleware to parse raw bodies. + * + * @param {object} [options] + * @return {function} + * @api public + */ + +function raw (options) { + var opts = options || {} + + var inflate = opts.inflate !== false + var limit = typeof opts.limit !== 'number' + ? bytes.parse(opts.limit || '100kb') + : opts.limit + var type = opts.type || 'application/octet-stream' + var verify = opts.verify || false + + if (verify !== false && typeof verify !== 'function') { + throw new TypeError('option verify must be function') + } + + // create the appropriate type checking function + var shouldParse = typeof type !== 'function' + ? typeChecker(type) + : type + + function parse (buf) { + return buf + } + + return function rawParser (req, res, next) { + if (req._body) { + debug('body already parsed') + next() + return + } + + req.body = req.body || {} + + // skip requests without bodies + if (!typeis.hasBody(req)) { + debug('skip empty body') + next() + return + } + + debug('content-type %j', req.headers['content-type']) + + // determine if request should be parsed + if (!shouldParse(req)) { + debug('skip parsing') + next() + return + } + + // read + read(req, res, next, parse, debug, { + encoding: null, + inflate: inflate, + limit: limit, + verify: verify + }) + } +} + +/** + * Get the simple type checker. + * + * @param {string} type + * @return {function} + */ + +function typeChecker (type) { + return function checkType (req) { + return Boolean(typeis(req, type)) + } +} diff --git a/server/node_modules/body-parser/lib/types/text.js b/server/node_modules/body-parser/lib/types/text.js new file mode 100644 index 0000000..083a009 --- /dev/null +++ b/server/node_modules/body-parser/lib/types/text.js @@ -0,0 +1,121 @@ +/*! + * body-parser + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module dependencies. + */ + +var bytes = require('bytes') +var contentType = require('content-type') +var debug = require('debug')('body-parser:text') +var read = require('../read') +var typeis = require('type-is') + +/** + * Module exports. + */ + +module.exports = text + +/** + * Create a middleware to parse text bodies. + * + * @param {object} [options] + * @return {function} + * @api public + */ + +function text (options) { + var opts = options || {} + + var defaultCharset = opts.defaultCharset || 'utf-8' + var inflate = opts.inflate !== false + var limit = typeof opts.limit !== 'number' + ? bytes.parse(opts.limit || '100kb') + : opts.limit + var type = opts.type || 'text/plain' + var verify = opts.verify || false + + if (verify !== false && typeof verify !== 'function') { + throw new TypeError('option verify must be function') + } + + // create the appropriate type checking function + var shouldParse = typeof type !== 'function' + ? typeChecker(type) + : type + + function parse (buf) { + return buf + } + + return function textParser (req, res, next) { + if (req._body) { + debug('body already parsed') + next() + return + } + + req.body = req.body || {} + + // skip requests without bodies + if (!typeis.hasBody(req)) { + debug('skip empty body') + next() + return + } + + debug('content-type %j', req.headers['content-type']) + + // determine if request should be parsed + if (!shouldParse(req)) { + debug('skip parsing') + next() + return + } + + // get charset + var charset = getCharset(req) || defaultCharset + + // read + read(req, res, next, parse, debug, { + encoding: charset, + inflate: inflate, + limit: limit, + verify: verify + }) + } +} + +/** + * Get the charset of a request. + * + * @param {object} req + * @api private + */ + +function getCharset (req) { + try { + return (contentType.parse(req).parameters.charset || '').toLowerCase() + } catch (e) { + return undefined + } +} + +/** + * Get the simple type checker. + * + * @param {string} type + * @return {function} + */ + +function typeChecker (type) { + return function checkType (req) { + return Boolean(typeis(req, type)) + } +} diff --git a/server/node_modules/body-parser/lib/types/urlencoded.js b/server/node_modules/body-parser/lib/types/urlencoded.js new file mode 100644 index 0000000..832992c --- /dev/null +++ b/server/node_modules/body-parser/lib/types/urlencoded.js @@ -0,0 +1,300 @@ +/*! + * body-parser + * Copyright(c) 2014 Jonathan Ong + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module dependencies. + * @private + */ + +var bytes = require('bytes') +var contentType = require('content-type') +var createError = require('http-errors') +var debug = require('debug')('body-parser:urlencoded') +var deprecate = require('depd')('body-parser') +var read = require('../read') +var typeis = require('type-is') + +/** + * Module exports. + */ + +module.exports = urlencoded + +/** + * Cache of parser modules. + */ + +var parsers = Object.create(null) + +/** + * Create a middleware to parse urlencoded bodies. + * + * @param {object} [options] + * @return {function} + * @public + */ + +function urlencoded (options) { + var opts = options || {} + + // notice because option default will flip in next major + if (opts.extended === undefined) { + deprecate('undefined extended: provide extended option') + } + + var extended = opts.extended !== false + var inflate = opts.inflate !== false + var limit = typeof opts.limit !== 'number' + ? bytes.parse(opts.limit || '100kb') + : opts.limit + var type = opts.type || 'application/x-www-form-urlencoded' + var verify = opts.verify || false + + if (verify !== false && typeof verify !== 'function') { + throw new TypeError('option verify must be function') + } + + // create the appropriate query parser + var queryparse = extended + ? extendedparser(opts) + : simpleparser(opts) + + // create the appropriate type checking function + var shouldParse = typeof type !== 'function' + ? typeChecker(type) + : type + + function parse (body) { + return body.length + ? queryparse(body) + : {} + } + + return function urlencodedParser (req, res, next) { + if (req._body) { + debug('body already parsed') + next() + return + } + + req.body = req.body || {} + + // skip requests without bodies + if (!typeis.hasBody(req)) { + debug('skip empty body') + next() + return + } + + debug('content-type %j', req.headers['content-type']) + + // determine if request should be parsed + if (!shouldParse(req)) { + debug('skip parsing') + next() + return + } + + // assert charset + var charset = getCharset(req) || 'utf-8' + if (charset !== 'utf-8') { + debug('invalid charset') + next(createError(415, 'unsupported charset "' + charset.toUpperCase() + '"', { + charset: charset, + type: 'charset.unsupported' + })) + return + } + + // read + read(req, res, next, parse, debug, { + debug: debug, + encoding: charset, + inflate: inflate, + limit: limit, + verify: verify + }) + } +} + +/** + * Get the extended query parser. + * + * @param {object} options + */ + +function extendedparser (options) { + var parameterLimit = options.parameterLimit !== undefined + ? options.parameterLimit + : 1000 + var depth = options.depth !== undefined ? options.depth : 32 + var parse = parser('qs') + + if (isNaN(parameterLimit) || parameterLimit < 1) { + throw new TypeError('option parameterLimit must be a positive number') + } + + if (isNaN(depth) || depth < 0) { + throw new TypeError('option depth must be a zero or a positive number') + } + + if (isFinite(parameterLimit)) { + parameterLimit = parameterLimit | 0 + } + + return function queryparse (body) { + var paramCount = parameterCount(body, parameterLimit) + + if (paramCount === undefined) { + debug('too many parameters') + throw createError(413, 'too many parameters', { + type: 'parameters.too.many' + }) + } + + var arrayLimit = Math.max(100, paramCount) + + debug('parse extended urlencoding') + try { + return parse(body, { + allowPrototypes: true, + arrayLimit: arrayLimit, + depth: depth, + strictDepth: true, + parameterLimit: parameterLimit + }) + } catch (err) { + if (err instanceof RangeError) { + throw createError(400, 'The input exceeded the depth', { + type: 'querystring.parse.rangeError' + }) + } else { + throw err + } + } + } +} + +/** + * Get the charset of a request. + * + * @param {object} req + * @api private + */ + +function getCharset (req) { + try { + return (contentType.parse(req).parameters.charset || '').toLowerCase() + } catch (e) { + return undefined + } +} + +/** + * Count the number of parameters, stopping once limit reached + * + * @param {string} body + * @param {number} limit + * @api private + */ + +function parameterCount (body, limit) { + var count = 0 + var index = 0 + + while ((index = body.indexOf('&', index)) !== -1) { + count++ + index++ + + if (count === limit) { + return undefined + } + } + + return count +} + +/** + * Get parser for module name dynamically. + * + * @param {string} name + * @return {function} + * @api private + */ + +function parser (name) { + var mod = parsers[name] + + if (mod !== undefined) { + return mod.parse + } + + // this uses a switch for static require analysis + switch (name) { + case 'qs': + mod = require('qs') + break + case 'querystring': + mod = require('querystring') + break + } + + // store to prevent invoking require() + parsers[name] = mod + + return mod.parse +} + +/** + * Get the simple query parser. + * + * @param {object} options + */ + +function simpleparser (options) { + var parameterLimit = options.parameterLimit !== undefined + ? options.parameterLimit + : 1000 + var parse = parser('querystring') + + if (isNaN(parameterLimit) || parameterLimit < 1) { + throw new TypeError('option parameterLimit must be a positive number') + } + + if (isFinite(parameterLimit)) { + parameterLimit = parameterLimit | 0 + } + + return function queryparse (body) { + var paramCount = parameterCount(body, parameterLimit) + + if (paramCount === undefined) { + debug('too many parameters') + throw createError(413, 'too many parameters', { + type: 'parameters.too.many' + }) + } + + debug('parse urlencoding') + return parse(body, undefined, undefined, { maxKeys: parameterLimit }) + } +} + +/** + * Get the simple type checker. + * + * @param {string} type + * @return {function} + */ + +function typeChecker (type) { + return function checkType (req) { + return Boolean(typeis(req, type)) + } +} diff --git a/server/node_modules/body-parser/package.json b/server/node_modules/body-parser/package.json new file mode 100644 index 0000000..c8e61c1 --- /dev/null +++ b/server/node_modules/body-parser/package.json @@ -0,0 +1,55 @@ +{ + "name": "body-parser", + "description": "Node.js body parsing middleware", + "version": "1.20.4", + "contributors": [ + "Douglas Christopher Wilson ", + "Jonathan Ong (http://jongleberry.com)" + ], + "license": "MIT", + "repository": "expressjs/body-parser", + "dependencies": { + "bytes": "~3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.14.0", + "raw-body": "~2.5.3", + "type-is": "~1.6.18", + "unpipe": "~1.0.0" + }, + "devDependencies": { + "eslint": "8.34.0", + "eslint-config-standard": "14.1.1", + "eslint-plugin-import": "2.27.5", + "eslint-plugin-markdown": "3.0.0", + "eslint-plugin-node": "11.1.0", + "eslint-plugin-promise": "6.1.1", + "eslint-plugin-standard": "4.1.0", + "methods": "1.1.2", + "mocha": "10.2.0", + "nyc": "15.1.0", + "safe-buffer": "5.2.1", + "supertest": "6.3.3" + }, + "files": [ + "lib/", + "LICENSE", + "HISTORY.md", + "index.js" + ], + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + }, + "scripts": { + "lint": "eslint .", + "test": "mocha --require test/support/env --reporter spec --check-leaks --bail test/", + "test-ci": "nyc --reporter=lcov --reporter=text npm test", + "test-cov": "nyc --reporter=html --reporter=text npm test" + } +} diff --git a/server/node_modules/brace-expansion/.github/FUNDING.yml b/server/node_modules/brace-expansion/.github/FUNDING.yml new file mode 100644 index 0000000..79d1eaf --- /dev/null +++ b/server/node_modules/brace-expansion/.github/FUNDING.yml @@ -0,0 +1,2 @@ +tidelift: "npm/brace-expansion" +patreon: juliangruber diff --git a/server/node_modules/brace-expansion/LICENSE b/server/node_modules/brace-expansion/LICENSE new file mode 100644 index 0000000..de32266 --- /dev/null +++ b/server/node_modules/brace-expansion/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2013 Julian Gruber + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/server/node_modules/brace-expansion/README.md b/server/node_modules/brace-expansion/README.md new file mode 100644 index 0000000..e55c583 --- /dev/null +++ b/server/node_modules/brace-expansion/README.md @@ -0,0 +1,135 @@ +# brace-expansion + +[Brace expansion](https://www.gnu.org/software/bash/manual/html_node/Brace-Expansion.html), +as known from sh/bash, in JavaScript. + +[![build status](https://secure.travis-ci.org/juliangruber/brace-expansion.svg)](http://travis-ci.org/juliangruber/brace-expansion) +[![downloads](https://img.shields.io/npm/dm/brace-expansion.svg)](https://www.npmjs.org/package/brace-expansion) +[![Greenkeeper badge](https://badges.greenkeeper.io/juliangruber/brace-expansion.svg)](https://greenkeeper.io/) + +[![testling badge](https://ci.testling.com/juliangruber/brace-expansion.png)](https://ci.testling.com/juliangruber/brace-expansion) + +## Example + +```js +var expand = require('brace-expansion'); + +expand('file-{a,b,c}.jpg') +// => ['file-a.jpg', 'file-b.jpg', 'file-c.jpg'] + +expand('-v{,,}') +// => ['-v', '-v', '-v'] + +expand('file{0..2}.jpg') +// => ['file0.jpg', 'file1.jpg', 'file2.jpg'] + +expand('file-{a..c}.jpg') +// => ['file-a.jpg', 'file-b.jpg', 'file-c.jpg'] + +expand('file{2..0}.jpg') +// => ['file2.jpg', 'file1.jpg', 'file0.jpg'] + +expand('file{0..4..2}.jpg') +// => ['file0.jpg', 'file2.jpg', 'file4.jpg'] + +expand('file-{a..e..2}.jpg') +// => ['file-a.jpg', 'file-c.jpg', 'file-e.jpg'] + +expand('file{00..10..5}.jpg') +// => ['file00.jpg', 'file05.jpg', 'file10.jpg'] + +expand('{{A..C},{a..c}}') +// => ['A', 'B', 'C', 'a', 'b', 'c'] + +expand('ppp{,config,oe{,conf}}') +// => ['ppp', 'pppconfig', 'pppoe', 'pppoeconf'] +``` + +## API + +```js +var expand = require('brace-expansion'); +``` + +### var expanded = expand(str) + +Return an array of all possible and valid expansions of `str`. If none are +found, `[str]` is returned. + +Valid expansions are: + +```js +/^(.*,)+(.+)?$/ +// {a,b,...} +``` + +A comma separated list of options, like `{a,b}` or `{a,{b,c}}` or `{,a,}`. + +```js +/^-?\d+\.\.-?\d+(\.\.-?\d+)?$/ +// {x..y[..incr]} +``` + +A numeric sequence from `x` to `y` inclusive, with optional increment. +If `x` or `y` start with a leading `0`, all the numbers will be padded +to have equal length. Negative numbers and backwards iteration work too. + +```js +/^-?\d+\.\.-?\d+(\.\.-?\d+)?$/ +// {x..y[..incr]} +``` + +An alphabetic sequence from `x` to `y` inclusive, with optional increment. +`x` and `y` must be exactly one character, and if given, `incr` must be a +number. + +For compatibility reasons, the string `${` is not eligible for brace expansion. + +## Installation + +With [npm](https://npmjs.org) do: + +```bash +npm install brace-expansion +``` + +## Contributors + +- [Julian Gruber](https://github.com/juliangruber) +- [Isaac Z. Schlueter](https://github.com/isaacs) + +## Sponsors + +This module is proudly supported by my [Sponsors](https://github.com/juliangruber/sponsors)! + +Do you want to support modules like this to improve their quality, stability and weigh in on new features? Then please consider donating to my [Patreon](https://www.patreon.com/juliangruber). Not sure how much of my modules you're using? Try [feross/thanks](https://github.com/feross/thanks)! + +## Security contact information + +To report a security vulnerability, please use the +[Tidelift security contact](https://tidelift.com/security). +Tidelift will coordinate the fix and disclosure. + +## License + +(MIT) + +Copyright (c) 2013 Julian Gruber <julian@juliangruber.com> + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/server/node_modules/brace-expansion/index.js b/server/node_modules/brace-expansion/index.js new file mode 100644 index 0000000..a27f81c --- /dev/null +++ b/server/node_modules/brace-expansion/index.js @@ -0,0 +1,203 @@ +var balanced = require('balanced-match'); + +module.exports = expandTop; + +var escSlash = '\0SLASH'+Math.random()+'\0'; +var escOpen = '\0OPEN'+Math.random()+'\0'; +var escClose = '\0CLOSE'+Math.random()+'\0'; +var escComma = '\0COMMA'+Math.random()+'\0'; +var escPeriod = '\0PERIOD'+Math.random()+'\0'; + +function numeric(str) { + return parseInt(str, 10) == str + ? parseInt(str, 10) + : str.charCodeAt(0); +} + +function escapeBraces(str) { + return str.split('\\\\').join(escSlash) + .split('\\{').join(escOpen) + .split('\\}').join(escClose) + .split('\\,').join(escComma) + .split('\\.').join(escPeriod); +} + +function unescapeBraces(str) { + return str.split(escSlash).join('\\') + .split(escOpen).join('{') + .split(escClose).join('}') + .split(escComma).join(',') + .split(escPeriod).join('.'); +} + + +// Basically just str.split(","), but handling cases +// where we have nested braced sections, which should be +// treated as individual members, like {a,{b,c},d} +function parseCommaParts(str) { + if (!str) + return ['']; + + var parts = []; + var m = balanced('{', '}', str); + + if (!m) + return str.split(','); + + var pre = m.pre; + var body = m.body; + var post = m.post; + var p = pre.split(','); + + p[p.length-1] += '{' + body + '}'; + var postParts = parseCommaParts(post); + if (post.length) { + p[p.length-1] += postParts.shift(); + p.push.apply(p, postParts); + } + + parts.push.apply(parts, p); + + return parts; +} + +function expandTop(str) { + if (!str) + return []; + + // I don't know why Bash 4.3 does this, but it does. + // Anything starting with {} will have the first two bytes preserved + // but *only* at the top level, so {},a}b will not expand to anything, + // but a{},b}c will be expanded to [a}c,abc]. + // One could argue that this is a bug in Bash, but since the goal of + // this module is to match Bash's rules, we escape a leading {} + if (str.substr(0, 2) === '{}') { + str = '\\{\\}' + str.substr(2); + } + + return expand(escapeBraces(str), true).map(unescapeBraces); +} + +function embrace(str) { + return '{' + str + '}'; +} +function isPadded(el) { + return /^-?0\d/.test(el); +} + +function lte(i, y) { + return i <= y; +} +function gte(i, y) { + return i >= y; +} + +function expand(str, isTop) { + var expansions = []; + + var m = balanced('{', '}', str); + if (!m) return [str]; + + // no need to expand pre, since it is guaranteed to be free of brace-sets + var pre = m.pre; + var post = m.post.length + ? expand(m.post, false) + : ['']; + + if (/\$$/.test(m.pre)) { + for (var k = 0; k < post.length; k++) { + var expansion = pre+ '{' + m.body + '}' + post[k]; + expansions.push(expansion); + } + } else { + var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body); + var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body); + var isSequence = isNumericSequence || isAlphaSequence; + var isOptions = m.body.indexOf(',') >= 0; + if (!isSequence && !isOptions) { + // {a},b} + if (m.post.match(/,(?!,).*\}/)) { + str = m.pre + '{' + m.body + escClose + m.post; + return expand(str); + } + return [str]; + } + + var n; + if (isSequence) { + n = m.body.split(/\.\./); + } else { + n = parseCommaParts(m.body); + if (n.length === 1) { + // x{{a,b}}y ==> x{a}y x{b}y + n = expand(n[0], false).map(embrace); + if (n.length === 1) { + return post.map(function(p) { + return m.pre + n[0] + p; + }); + } + } + } + + // at this point, n is the parts, and we know it's not a comma set + // with a single entry. + var N; + + if (isSequence) { + var x = numeric(n[0]); + var y = numeric(n[1]); + var width = Math.max(n[0].length, n[1].length) + var incr = n.length == 3 + ? Math.abs(numeric(n[2])) + : 1; + var test = lte; + var reverse = y < x; + if (reverse) { + incr *= -1; + test = gte; + } + var pad = n.some(isPadded); + + N = []; + + for (var i = x; test(i, y); i += incr) { + var c; + if (isAlphaSequence) { + c = String.fromCharCode(i); + if (c === '\\') + c = ''; + } else { + c = String(i); + if (pad) { + var need = width - c.length; + if (need > 0) { + var z = new Array(need + 1).join('0'); + if (i < 0) + c = '-' + z + c.slice(1); + else + c = z + c; + } + } + } + N.push(c); + } + } else { + N = []; + + for (var j = 0; j < n.length; j++) { + N.push.apply(N, expand(n[j], false)); + } + } + + for (var j = 0; j < N.length; j++) { + for (var k = 0; k < post.length; k++) { + var expansion = pre + N[j] + post[k]; + if (!isTop || isSequence || expansion) + expansions.push(expansion); + } + } + } + + return expansions; +} + diff --git a/server/node_modules/brace-expansion/package.json b/server/node_modules/brace-expansion/package.json new file mode 100644 index 0000000..c7eee34 --- /dev/null +++ b/server/node_modules/brace-expansion/package.json @@ -0,0 +1,49 @@ +{ + "name": "brace-expansion", + "description": "Brace expansion as known from sh/bash", + "version": "2.0.2", + "repository": { + "type": "git", + "url": "git://github.com/juliangruber/brace-expansion.git" + }, + "homepage": "https://github.com/juliangruber/brace-expansion", + "main": "index.js", + "scripts": { + "test": "tape test/*.js", + "gentest": "bash test/generate.sh", + "bench": "matcha test/perf/bench.js" + }, + "dependencies": { + "balanced-match": "^1.0.0" + }, + "devDependencies": { + "@c4312/matcha": "^1.3.1", + "tape": "^4.6.0" + }, + "keywords": [], + "author": { + "name": "Julian Gruber", + "email": "mail@juliangruber.com", + "url": "http://juliangruber.com" + }, + "license": "MIT", + "testling": { + "files": "test/*.js", + "browsers": [ + "ie/8..latest", + "firefox/20..latest", + "firefox/nightly", + "chrome/25..latest", + "chrome/canary", + "opera/12..latest", + "opera/next", + "safari/5.1..latest", + "ipad/6.0..latest", + "iphone/6.0..latest", + "android-browser/4.2..latest" + ] + }, + "publishConfig": { + "tag": "2.x" + } +} diff --git a/server/node_modules/buffer-equal-constant-time/.npmignore b/server/node_modules/buffer-equal-constant-time/.npmignore new file mode 100644 index 0000000..34e4f5c --- /dev/null +++ b/server/node_modules/buffer-equal-constant-time/.npmignore @@ -0,0 +1,2 @@ +.*.sw[mnop] +node_modules/ diff --git a/server/node_modules/buffer-equal-constant-time/.travis.yml b/server/node_modules/buffer-equal-constant-time/.travis.yml new file mode 100644 index 0000000..78e1c01 --- /dev/null +++ b/server/node_modules/buffer-equal-constant-time/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: +- "0.11" +- "0.10" diff --git a/server/node_modules/buffer-equal-constant-time/LICENSE.txt b/server/node_modules/buffer-equal-constant-time/LICENSE.txt new file mode 100644 index 0000000..9a064f3 --- /dev/null +++ b/server/node_modules/buffer-equal-constant-time/LICENSE.txt @@ -0,0 +1,12 @@ +Copyright (c) 2013, GoInstant Inc., a salesforce.com company +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +* Neither the name of salesforce.com, nor GoInstant, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/server/node_modules/buffer-equal-constant-time/README.md b/server/node_modules/buffer-equal-constant-time/README.md new file mode 100644 index 0000000..4f227f5 --- /dev/null +++ b/server/node_modules/buffer-equal-constant-time/README.md @@ -0,0 +1,50 @@ +# buffer-equal-constant-time + +Constant-time `Buffer` comparison for node.js. Should work with browserify too. + +[![Build Status](https://travis-ci.org/goinstant/buffer-equal-constant-time.png?branch=master)](https://travis-ci.org/goinstant/buffer-equal-constant-time) + +```sh + npm install buffer-equal-constant-time +``` + +# Usage + +```js + var bufferEq = require('buffer-equal-constant-time'); + + var a = new Buffer('asdf'); + var b = new Buffer('asdf'); + if (bufferEq(a,b)) { + // the same! + } else { + // different in at least one byte! + } +``` + +If you'd like to install an `.equal()` method onto the node.js `Buffer` and +`SlowBuffer` prototypes: + +```js + require('buffer-equal-constant-time').install(); + + var a = new Buffer('asdf'); + var b = new Buffer('asdf'); + if (a.equal(b)) { + // the same! + } else { + // different in at least one byte! + } +``` + +To get rid of the installed `.equal()` method, call `.restore()`: + +```js + require('buffer-equal-constant-time').restore(); +``` + +# Legal + +© 2013 GoInstant Inc., a salesforce.com company + +Licensed under the BSD 3-clause license. diff --git a/server/node_modules/buffer-equal-constant-time/index.js b/server/node_modules/buffer-equal-constant-time/index.js new file mode 100644 index 0000000..5462c1f --- /dev/null +++ b/server/node_modules/buffer-equal-constant-time/index.js @@ -0,0 +1,41 @@ +/*jshint node:true */ +'use strict'; +var Buffer = require('buffer').Buffer; // browserify +var SlowBuffer = require('buffer').SlowBuffer; + +module.exports = bufferEq; + +function bufferEq(a, b) { + + // shortcutting on type is necessary for correctness + if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { + return false; + } + + // buffer sizes should be well-known information, so despite this + // shortcutting, it doesn't leak any information about the *contents* of the + // buffers. + if (a.length !== b.length) { + return false; + } + + var c = 0; + for (var i = 0; i < a.length; i++) { + /*jshint bitwise:false */ + c |= a[i] ^ b[i]; // XOR + } + return c === 0; +} + +bufferEq.install = function() { + Buffer.prototype.equal = SlowBuffer.prototype.equal = function equal(that) { + return bufferEq(this, that); + }; +}; + +var origBufEqual = Buffer.prototype.equal; +var origSlowBufEqual = SlowBuffer.prototype.equal; +bufferEq.restore = function() { + Buffer.prototype.equal = origBufEqual; + SlowBuffer.prototype.equal = origSlowBufEqual; +}; diff --git a/server/node_modules/buffer-equal-constant-time/package.json b/server/node_modules/buffer-equal-constant-time/package.json new file mode 100644 index 0000000..17c7de2 --- /dev/null +++ b/server/node_modules/buffer-equal-constant-time/package.json @@ -0,0 +1,21 @@ +{ + "name": "buffer-equal-constant-time", + "version": "1.0.1", + "description": "Constant-time comparison of Buffers", + "main": "index.js", + "scripts": { + "test": "mocha test.js" + }, + "repository": "git@github.com:goinstant/buffer-equal-constant-time.git", + "keywords": [ + "buffer", + "equal", + "constant-time", + "crypto" + ], + "author": "GoInstant Inc., a salesforce.com company", + "license": "BSD-3-Clause", + "devDependencies": { + "mocha": "~1.15.1" + } +} diff --git a/server/node_modules/buffer-equal-constant-time/test.js b/server/node_modules/buffer-equal-constant-time/test.js new file mode 100644 index 0000000..0bc972d --- /dev/null +++ b/server/node_modules/buffer-equal-constant-time/test.js @@ -0,0 +1,42 @@ +/*jshint node:true */ +'use strict'; + +var bufferEq = require('./index'); +var assert = require('assert'); + +describe('buffer-equal-constant-time', function() { + var a = new Buffer('asdfasdf123456'); + var b = new Buffer('asdfasdf123456'); + var c = new Buffer('asdfasdf'); + + describe('bufferEq', function() { + it('says a == b', function() { + assert.strictEqual(bufferEq(a, b), true); + }); + + it('says a != c', function() { + assert.strictEqual(bufferEq(a, c), false); + }); + }); + + describe('install/restore', function() { + before(function() { + bufferEq.install(); + }); + after(function() { + bufferEq.restore(); + }); + + it('installed an .equal method', function() { + var SlowBuffer = require('buffer').SlowBuffer; + assert.ok(Buffer.prototype.equal); + assert.ok(SlowBuffer.prototype.equal); + }); + + it('infected existing Buffers', function() { + assert.strictEqual(a.equal(b), true); + assert.strictEqual(a.equal(c), false); + }); + }); + +}); diff --git a/server/node_modules/bytes/History.md b/server/node_modules/bytes/History.md new file mode 100644 index 0000000..d60ce0e --- /dev/null +++ b/server/node_modules/bytes/History.md @@ -0,0 +1,97 @@ +3.1.2 / 2022-01-27 +================== + + * Fix return value for un-parsable strings + +3.1.1 / 2021-11-15 +================== + + * Fix "thousandsSeparator" incorrecting formatting fractional part + +3.1.0 / 2019-01-22 +================== + + * Add petabyte (`pb`) support + +3.0.0 / 2017-08-31 +================== + + * Change "kB" to "KB" in format output + * Remove support for Node.js 0.6 + * Remove support for ComponentJS + +2.5.0 / 2017-03-24 +================== + + * Add option "unit" + +2.4.0 / 2016-06-01 +================== + + * Add option "unitSeparator" + +2.3.0 / 2016-02-15 +================== + + * Drop partial bytes on all parsed units + * Fix non-finite numbers to `.format` to return `null` + * Fix parsing byte string that looks like hex + * perf: hoist regular expressions + +2.2.0 / 2015-11-13 +================== + + * add option "decimalPlaces" + * add option "fixedDecimals" + +2.1.0 / 2015-05-21 +================== + + * add `.format` export + * add `.parse` export + +2.0.2 / 2015-05-20 +================== + + * remove map recreation + * remove unnecessary object construction + +2.0.1 / 2015-05-07 +================== + + * fix browserify require + * remove node.extend dependency + +2.0.0 / 2015-04-12 +================== + + * add option "case" + * add option "thousandsSeparator" + * return "null" on invalid parse input + * support proper round-trip: bytes(bytes(num)) === num + * units no longer case sensitive when parsing + +1.0.0 / 2014-05-05 +================== + + * add negative support. fixes #6 + +0.3.0 / 2014-03-19 +================== + + * added terabyte support + +0.2.1 / 2013-04-01 +================== + + * add .component + +0.2.0 / 2012-10-28 +================== + + * bytes(200).should.eql('200b') + +0.1.0 / 2012-07-04 +================== + + * add bytes to string conversion [yields] diff --git a/server/node_modules/bytes/LICENSE b/server/node_modules/bytes/LICENSE new file mode 100644 index 0000000..63e95a9 --- /dev/null +++ b/server/node_modules/bytes/LICENSE @@ -0,0 +1,23 @@ +(The MIT License) + +Copyright (c) 2012-2014 TJ Holowaychuk +Copyright (c) 2015 Jed Watson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/server/node_modules/bytes/Readme.md b/server/node_modules/bytes/Readme.md new file mode 100644 index 0000000..5790e23 --- /dev/null +++ b/server/node_modules/bytes/Readme.md @@ -0,0 +1,152 @@ +# Bytes utility + +[![NPM Version][npm-image]][npm-url] +[![NPM Downloads][downloads-image]][downloads-url] +[![Build Status][ci-image]][ci-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +Utility to parse a string bytes (ex: `1TB`) to bytes (`1099511627776`) and vice-versa. + +## Installation + +This is a [Node.js](https://nodejs.org/en/) module available through the +[npm registry](https://www.npmjs.com/). Installation is done using the +[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): + +```bash +$ npm install bytes +``` + +## Usage + +```js +var bytes = require('bytes'); +``` + +#### bytes(number|string value, [options]): number|string|null + +Default export function. Delegates to either `bytes.format` or `bytes.parse` based on the type of `value`. + +**Arguments** + +| Name | Type | Description | +|---------|----------|--------------------| +| value | `number`|`string` | Number value to format or string value to parse | +| options | `Object` | Conversion options for `format` | + +**Returns** + +| Name | Type | Description | +|---------|------------------|-------------------------------------------------| +| results | `string`|`number`|`null` | Return null upon error. Numeric value in bytes, or string value otherwise. | + +**Example** + +```js +bytes(1024); +// output: '1KB' + +bytes('1KB'); +// output: 1024 +``` + +#### bytes.format(number value, [options]): string|null + +Format the given value in bytes into a string. If the value is negative, it is kept as such. If it is a float, it is + rounded. + +**Arguments** + +| Name | Type | Description | +|---------|----------|--------------------| +| value | `number` | Value in bytes | +| options | `Object` | Conversion options | + +**Options** + +| Property | Type | Description | +|-------------------|--------|-----------------------------------------------------------------------------------------| +| decimalPlaces | `number`|`null` | Maximum number of decimal places to include in output. Default value to `2`. | +| fixedDecimals | `boolean`|`null` | Whether to always display the maximum number of decimal places. Default value to `false` | +| thousandsSeparator | `string`|`null` | Example of values: `' '`, `','` and `'.'`... Default value to `''`. | +| unit | `string`|`null` | The unit in which the result will be returned (B/KB/MB/GB/TB). Default value to `''` (which means auto detect). | +| unitSeparator | `string`|`null` | Separator to use between number and unit. Default value to `''`. | + +**Returns** + +| Name | Type | Description | +|---------|------------------|-------------------------------------------------| +| results | `string`|`null` | Return null upon error. String value otherwise. | + +**Example** + +```js +bytes.format(1024); +// output: '1KB' + +bytes.format(1000); +// output: '1000B' + +bytes.format(1000, {thousandsSeparator: ' '}); +// output: '1 000B' + +bytes.format(1024 * 1.7, {decimalPlaces: 0}); +// output: '2KB' + +bytes.format(1024, {unitSeparator: ' '}); +// output: '1 KB' +``` + +#### bytes.parse(string|number value): number|null + +Parse the string value into an integer in bytes. If no unit is given, or `value` +is a number, it is assumed the value is in bytes. + +Supported units and abbreviations are as follows and are case-insensitive: + + * `b` for bytes + * `kb` for kilobytes + * `mb` for megabytes + * `gb` for gigabytes + * `tb` for terabytes + * `pb` for petabytes + +The units are in powers of two, not ten. This means 1kb = 1024b according to this parser. + +**Arguments** + +| Name | Type | Description | +|---------------|--------|--------------------| +| value | `string`|`number` | String to parse, or number in bytes. | + +**Returns** + +| Name | Type | Description | +|---------|-------------|-------------------------| +| results | `number`|`null` | Return null upon error. Value in bytes otherwise. | + +**Example** + +```js +bytes.parse('1KB'); +// output: 1024 + +bytes.parse('1024'); +// output: 1024 + +bytes.parse(1024); +// output: 1024 +``` + +## License + +[MIT](LICENSE) + +[ci-image]: https://badgen.net/github/checks/visionmedia/bytes.js/master?label=ci +[ci-url]: https://github.com/visionmedia/bytes.js/actions?query=workflow%3Aci +[coveralls-image]: https://badgen.net/coveralls/c/github/visionmedia/bytes.js/master +[coveralls-url]: https://coveralls.io/r/visionmedia/bytes.js?branch=master +[downloads-image]: https://badgen.net/npm/dm/bytes +[downloads-url]: https://npmjs.org/package/bytes +[npm-image]: https://badgen.net/npm/v/bytes +[npm-url]: https://npmjs.org/package/bytes diff --git a/server/node_modules/bytes/index.js b/server/node_modules/bytes/index.js new file mode 100644 index 0000000..6f2d0f8 --- /dev/null +++ b/server/node_modules/bytes/index.js @@ -0,0 +1,170 @@ +/*! + * bytes + * Copyright(c) 2012-2014 TJ Holowaychuk + * Copyright(c) 2015 Jed Watson + * MIT Licensed + */ + +'use strict'; + +/** + * Module exports. + * @public + */ + +module.exports = bytes; +module.exports.format = format; +module.exports.parse = parse; + +/** + * Module variables. + * @private + */ + +var formatThousandsRegExp = /\B(?=(\d{3})+(?!\d))/g; + +var formatDecimalsRegExp = /(?:\.0*|(\.[^0]+)0+)$/; + +var map = { + b: 1, + kb: 1 << 10, + mb: 1 << 20, + gb: 1 << 30, + tb: Math.pow(1024, 4), + pb: Math.pow(1024, 5), +}; + +var parseRegExp = /^((-|\+)?(\d+(?:\.\d+)?)) *(kb|mb|gb|tb|pb)$/i; + +/** + * Convert the given value in bytes into a string or parse to string to an integer in bytes. + * + * @param {string|number} value + * @param {{ + * case: [string], + * decimalPlaces: [number] + * fixedDecimals: [boolean] + * thousandsSeparator: [string] + * unitSeparator: [string] + * }} [options] bytes options. + * + * @returns {string|number|null} + */ + +function bytes(value, options) { + if (typeof value === 'string') { + return parse(value); + } + + if (typeof value === 'number') { + return format(value, options); + } + + return null; +} + +/** + * Format the given value in bytes into a string. + * + * If the value is negative, it is kept as such. If it is a float, + * it is rounded. + * + * @param {number} value + * @param {object} [options] + * @param {number} [options.decimalPlaces=2] + * @param {number} [options.fixedDecimals=false] + * @param {string} [options.thousandsSeparator=] + * @param {string} [options.unit=] + * @param {string} [options.unitSeparator=] + * + * @returns {string|null} + * @public + */ + +function format(value, options) { + if (!Number.isFinite(value)) { + return null; + } + + var mag = Math.abs(value); + var thousandsSeparator = (options && options.thousandsSeparator) || ''; + var unitSeparator = (options && options.unitSeparator) || ''; + var decimalPlaces = (options && options.decimalPlaces !== undefined) ? options.decimalPlaces : 2; + var fixedDecimals = Boolean(options && options.fixedDecimals); + var unit = (options && options.unit) || ''; + + if (!unit || !map[unit.toLowerCase()]) { + if (mag >= map.pb) { + unit = 'PB'; + } else if (mag >= map.tb) { + unit = 'TB'; + } else if (mag >= map.gb) { + unit = 'GB'; + } else if (mag >= map.mb) { + unit = 'MB'; + } else if (mag >= map.kb) { + unit = 'KB'; + } else { + unit = 'B'; + } + } + + var val = value / map[unit.toLowerCase()]; + var str = val.toFixed(decimalPlaces); + + if (!fixedDecimals) { + str = str.replace(formatDecimalsRegExp, '$1'); + } + + if (thousandsSeparator) { + str = str.split('.').map(function (s, i) { + return i === 0 + ? s.replace(formatThousandsRegExp, thousandsSeparator) + : s + }).join('.'); + } + + return str + unitSeparator + unit; +} + +/** + * Parse the string value into an integer in bytes. + * + * If no unit is given, it is assumed the value is in bytes. + * + * @param {number|string} val + * + * @returns {number|null} + * @public + */ + +function parse(val) { + if (typeof val === 'number' && !isNaN(val)) { + return val; + } + + if (typeof val !== 'string') { + return null; + } + + // Test if the string passed is valid + var results = parseRegExp.exec(val); + var floatValue; + var unit = 'b'; + + if (!results) { + // Nothing could be extracted from the given string + floatValue = parseInt(val, 10); + unit = 'b' + } else { + // Retrieve the value and the unit + floatValue = parseFloat(results[1]); + unit = results[4].toLowerCase(); + } + + if (isNaN(floatValue)) { + return null; + } + + return Math.floor(map[unit] * floatValue); +} diff --git a/server/node_modules/bytes/package.json b/server/node_modules/bytes/package.json new file mode 100644 index 0000000..f2b6a8b --- /dev/null +++ b/server/node_modules/bytes/package.json @@ -0,0 +1,42 @@ +{ + "name": "bytes", + "description": "Utility to parse a string bytes to bytes and vice-versa", + "version": "3.1.2", + "author": "TJ Holowaychuk (http://tjholowaychuk.com)", + "contributors": [ + "Jed Watson ", + "Théo FIDRY " + ], + "license": "MIT", + "keywords": [ + "byte", + "bytes", + "utility", + "parse", + "parser", + "convert", + "converter" + ], + "repository": "visionmedia/bytes.js", + "devDependencies": { + "eslint": "7.32.0", + "eslint-plugin-markdown": "2.2.1", + "mocha": "9.2.0", + "nyc": "15.1.0" + }, + "files": [ + "History.md", + "LICENSE", + "Readme.md", + "index.js" + ], + "engines": { + "node": ">= 0.8" + }, + "scripts": { + "lint": "eslint .", + "test": "mocha --check-leaks --reporter spec", + "test-ci": "nyc --reporter=lcov --reporter=text npm test", + "test-cov": "nyc --reporter=html --reporter=text npm test" + } +} diff --git a/server/node_modules/call-bind-apply-helpers/.eslintrc b/server/node_modules/call-bind-apply-helpers/.eslintrc new file mode 100644 index 0000000..201e859 --- /dev/null +++ b/server/node_modules/call-bind-apply-helpers/.eslintrc @@ -0,0 +1,17 @@ +{ + "root": true, + + "extends": "@ljharb", + + "rules": { + "func-name-matching": 0, + "id-length": 0, + "new-cap": [2, { + "capIsNewExceptions": [ + "GetIntrinsic", + ], + }], + "no-extra-parens": 0, + "no-magic-numbers": 0, + }, +} diff --git a/server/node_modules/call-bind-apply-helpers/.github/FUNDING.yml b/server/node_modules/call-bind-apply-helpers/.github/FUNDING.yml new file mode 100644 index 0000000..0011e9d --- /dev/null +++ b/server/node_modules/call-bind-apply-helpers/.github/FUNDING.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +github: [ljharb] +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: npm/call-bind-apply-helpers +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/server/node_modules/call-bind-apply-helpers/.nycrc b/server/node_modules/call-bind-apply-helpers/.nycrc new file mode 100644 index 0000000..bdd626c --- /dev/null +++ b/server/node_modules/call-bind-apply-helpers/.nycrc @@ -0,0 +1,9 @@ +{ + "all": true, + "check-coverage": false, + "reporter": ["text-summary", "text", "html", "json"], + "exclude": [ + "coverage", + "test" + ] +} diff --git a/server/node_modules/call-bind-apply-helpers/CHANGELOG.md b/server/node_modules/call-bind-apply-helpers/CHANGELOG.md new file mode 100644 index 0000000..2484942 --- /dev/null +++ b/server/node_modules/call-bind-apply-helpers/CHANGELOG.md @@ -0,0 +1,30 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [v1.0.2](https://github.com/ljharb/call-bind-apply-helpers/compare/v1.0.1...v1.0.2) - 2025-02-12 + +### Commits + +- [types] improve inferred types [`e6f9586`](https://github.com/ljharb/call-bind-apply-helpers/commit/e6f95860a3c72879cb861a858cdfb8138fbedec1) +- [Dev Deps] update `@arethetypeswrong/cli`, `@ljharb/tsconfig`, `@types/tape`, `es-value-fixtures`, `for-each`, `has-strict-mode`, `object-inspect` [`e43d540`](https://github.com/ljharb/call-bind-apply-helpers/commit/e43d5409f97543bfbb11f345d47d8ce4e066d8c1) + +## [v1.0.1](https://github.com/ljharb/call-bind-apply-helpers/compare/v1.0.0...v1.0.1) - 2024-12-08 + +### Commits + +- [types] `reflectApply`: fix types [`4efc396`](https://github.com/ljharb/call-bind-apply-helpers/commit/4efc3965351a4f02cc55e836fa391d3d11ef2ef8) +- [Fix] `reflectApply`: oops, Reflect is not a function [`83cc739`](https://github.com/ljharb/call-bind-apply-helpers/commit/83cc7395de6b79b7730bdf092f1436f0b1263c75) +- [Dev Deps] update `@arethetypeswrong/cli` [`80bd5d3`](https://github.com/ljharb/call-bind-apply-helpers/commit/80bd5d3ae58b4f6b6995ce439dd5a1bcb178a940) + +## v1.0.0 - 2024-12-05 + +### Commits + +- Initial implementation, tests, readme [`7879629`](https://github.com/ljharb/call-bind-apply-helpers/commit/78796290f9b7430c9934d6f33d94ae9bc89fce04) +- Initial commit [`3f1dc16`](https://github.com/ljharb/call-bind-apply-helpers/commit/3f1dc164afc43285631b114a5f9dd9137b2b952f) +- npm init [`081df04`](https://github.com/ljharb/call-bind-apply-helpers/commit/081df048c312fcee400922026f6e97281200a603) +- Only apps should have lockfiles [`5b9ca0f`](https://github.com/ljharb/call-bind-apply-helpers/commit/5b9ca0fe8101ebfaf309c549caac4e0a017ed930) diff --git a/server/node_modules/call-bind-apply-helpers/LICENSE b/server/node_modules/call-bind-apply-helpers/LICENSE new file mode 100644 index 0000000..f82f389 --- /dev/null +++ b/server/node_modules/call-bind-apply-helpers/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Jordan Harband + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/server/node_modules/call-bind-apply-helpers/README.md b/server/node_modules/call-bind-apply-helpers/README.md new file mode 100644 index 0000000..8fc0dae --- /dev/null +++ b/server/node_modules/call-bind-apply-helpers/README.md @@ -0,0 +1,62 @@ +# call-bind-apply-helpers [![Version Badge][npm-version-svg]][package-url] + +[![github actions][actions-image]][actions-url] +[![coverage][codecov-image]][codecov-url] +[![dependency status][deps-svg]][deps-url] +[![dev dependency status][dev-deps-svg]][dev-deps-url] +[![License][license-image]][license-url] +[![Downloads][downloads-image]][downloads-url] + +[![npm badge][npm-badge-png]][package-url] + +Helper functions around Function call/apply/bind, for use in `call-bind`. + +The only packages that should likely ever use this package directly are `call-bind` and `get-intrinsic`. +Please use `call-bind` unless you have a very good reason not to. + +## Getting started + +```sh +npm install --save call-bind-apply-helpers +``` + +## Usage/Examples + +```js +const assert = require('assert'); +const callBindBasic = require('call-bind-apply-helpers'); + +function f(a, b) { + assert.equal(this, 1); + assert.equal(a, 2); + assert.equal(b, 3); + assert.equal(arguments.length, 2); +} + +const fBound = callBindBasic([f, 1]); + +delete Function.prototype.call; +delete Function.prototype.bind; + +fBound(2, 3); +``` + +## Tests + +Clone the repo, `npm install`, and run `npm test` + +[package-url]: https://npmjs.org/package/call-bind-apply-helpers +[npm-version-svg]: https://versionbadg.es/ljharb/call-bind-apply-helpers.svg +[deps-svg]: https://david-dm.org/ljharb/call-bind-apply-helpers.svg +[deps-url]: https://david-dm.org/ljharb/call-bind-apply-helpers +[dev-deps-svg]: https://david-dm.org/ljharb/call-bind-apply-helpers/dev-status.svg +[dev-deps-url]: https://david-dm.org/ljharb/call-bind-apply-helpers#info=devDependencies +[npm-badge-png]: https://nodei.co/npm/call-bind-apply-helpers.png?downloads=true&stars=true +[license-image]: https://img.shields.io/npm/l/call-bind-apply-helpers.svg +[license-url]: LICENSE +[downloads-image]: https://img.shields.io/npm/dm/call-bind-apply-helpers.svg +[downloads-url]: https://npm-stat.com/charts.html?package=call-bind-apply-helpers +[codecov-image]: https://codecov.io/gh/ljharb/call-bind-apply-helpers/branch/main/graphs/badge.svg +[codecov-url]: https://app.codecov.io/gh/ljharb/call-bind-apply-helpers/ +[actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/ljharb/call-bind-apply-helpers +[actions-url]: https://github.com/ljharb/call-bind-apply-helpers/actions diff --git a/server/node_modules/call-bind-apply-helpers/actualApply.d.ts b/server/node_modules/call-bind-apply-helpers/actualApply.d.ts new file mode 100644 index 0000000..b87286a --- /dev/null +++ b/server/node_modules/call-bind-apply-helpers/actualApply.d.ts @@ -0,0 +1 @@ +export = Reflect.apply; \ No newline at end of file diff --git a/server/node_modules/call-bind-apply-helpers/actualApply.js b/server/node_modules/call-bind-apply-helpers/actualApply.js new file mode 100644 index 0000000..ffa5135 --- /dev/null +++ b/server/node_modules/call-bind-apply-helpers/actualApply.js @@ -0,0 +1,10 @@ +'use strict'; + +var bind = require('function-bind'); + +var $apply = require('./functionApply'); +var $call = require('./functionCall'); +var $reflectApply = require('./reflectApply'); + +/** @type {import('./actualApply')} */ +module.exports = $reflectApply || bind.call($call, $apply); diff --git a/server/node_modules/call-bind-apply-helpers/applyBind.d.ts b/server/node_modules/call-bind-apply-helpers/applyBind.d.ts new file mode 100644 index 0000000..d176c1a --- /dev/null +++ b/server/node_modules/call-bind-apply-helpers/applyBind.d.ts @@ -0,0 +1,19 @@ +import actualApply from './actualApply'; + +type TupleSplitHead = T['length'] extends N + ? T + : T extends [...infer R, any] + ? TupleSplitHead + : never + +type TupleSplitTail = O['length'] extends N + ? T + : T extends [infer F, ...infer R] + ? TupleSplitTail<[...R], N, [...O, F]> + : never + +type TupleSplit = [TupleSplitHead, TupleSplitTail] + +declare function applyBind(...args: TupleSplit, 2>[1]): ReturnType; + +export = applyBind; \ No newline at end of file diff --git a/server/node_modules/call-bind-apply-helpers/applyBind.js b/server/node_modules/call-bind-apply-helpers/applyBind.js new file mode 100644 index 0000000..d2b7723 --- /dev/null +++ b/server/node_modules/call-bind-apply-helpers/applyBind.js @@ -0,0 +1,10 @@ +'use strict'; + +var bind = require('function-bind'); +var $apply = require('./functionApply'); +var actualApply = require('./actualApply'); + +/** @type {import('./applyBind')} */ +module.exports = function applyBind() { + return actualApply(bind, $apply, arguments); +}; diff --git a/server/node_modules/call-bind-apply-helpers/functionApply.d.ts b/server/node_modules/call-bind-apply-helpers/functionApply.d.ts new file mode 100644 index 0000000..1f6e11b --- /dev/null +++ b/server/node_modules/call-bind-apply-helpers/functionApply.d.ts @@ -0,0 +1 @@ +export = Function.prototype.apply; \ No newline at end of file diff --git a/server/node_modules/call-bind-apply-helpers/functionApply.js b/server/node_modules/call-bind-apply-helpers/functionApply.js new file mode 100644 index 0000000..c71df9c --- /dev/null +++ b/server/node_modules/call-bind-apply-helpers/functionApply.js @@ -0,0 +1,4 @@ +'use strict'; + +/** @type {import('./functionApply')} */ +module.exports = Function.prototype.apply; diff --git a/server/node_modules/call-bind-apply-helpers/functionCall.d.ts b/server/node_modules/call-bind-apply-helpers/functionCall.d.ts new file mode 100644 index 0000000..15e93df --- /dev/null +++ b/server/node_modules/call-bind-apply-helpers/functionCall.d.ts @@ -0,0 +1 @@ +export = Function.prototype.call; \ No newline at end of file diff --git a/server/node_modules/call-bind-apply-helpers/functionCall.js b/server/node_modules/call-bind-apply-helpers/functionCall.js new file mode 100644 index 0000000..7a8d873 --- /dev/null +++ b/server/node_modules/call-bind-apply-helpers/functionCall.js @@ -0,0 +1,4 @@ +'use strict'; + +/** @type {import('./functionCall')} */ +module.exports = Function.prototype.call; diff --git a/server/node_modules/call-bind-apply-helpers/index.d.ts b/server/node_modules/call-bind-apply-helpers/index.d.ts new file mode 100644 index 0000000..541516b --- /dev/null +++ b/server/node_modules/call-bind-apply-helpers/index.d.ts @@ -0,0 +1,64 @@ +type RemoveFromTuple< + Tuple extends readonly unknown[], + RemoveCount extends number, + Index extends 1[] = [] +> = Index["length"] extends RemoveCount + ? Tuple + : Tuple extends [infer First, ...infer Rest] + ? RemoveFromTuple + : Tuple; + +type ConcatTuples< + Prefix extends readonly unknown[], + Suffix extends readonly unknown[] +> = [...Prefix, ...Suffix]; + +type ExtractFunctionParams = T extends (this: infer TThis, ...args: infer P extends readonly unknown[]) => infer R + ? { thisArg: TThis; params: P; returnType: R } + : never; + +type BindFunction< + T extends (this: any, ...args: any[]) => any, + TThis, + TBoundArgs extends readonly unknown[], + ReceiverBound extends boolean +> = ExtractFunctionParams extends { + thisArg: infer OrigThis; + params: infer P extends readonly unknown[]; + returnType: infer R; +} + ? ReceiverBound extends true + ? (...args: RemoveFromTuple>) => R extends [OrigThis, ...infer Rest] + ? [TThis, ...Rest] // Replace `this` with `thisArg` + : R + : >>( + thisArg: U, + ...args: RemainingArgs + ) => R extends [OrigThis, ...infer Rest] + ? [U, ...ConcatTuples] // Preserve bound args in return type + : R + : never; + +declare function callBind< + const T extends (this: any, ...args: any[]) => any, + Extracted extends ExtractFunctionParams, + const TBoundArgs extends Partial & readonly unknown[], + const TThis extends Extracted["thisArg"] +>( + args: [fn: T, thisArg: TThis, ...boundArgs: TBoundArgs] +): BindFunction; + +declare function callBind< + const T extends (this: any, ...args: any[]) => any, + Extracted extends ExtractFunctionParams, + const TBoundArgs extends Partial & readonly unknown[] +>( + args: [fn: T, ...boundArgs: TBoundArgs] +): BindFunction; + +declare function callBind( + args: [fn: Exclude, ...rest: TArgs] +): never; + +// export as namespace callBind; +export = callBind; diff --git a/server/node_modules/call-bind-apply-helpers/index.js b/server/node_modules/call-bind-apply-helpers/index.js new file mode 100644 index 0000000..2f6dab4 --- /dev/null +++ b/server/node_modules/call-bind-apply-helpers/index.js @@ -0,0 +1,15 @@ +'use strict'; + +var bind = require('function-bind'); +var $TypeError = require('es-errors/type'); + +var $call = require('./functionCall'); +var $actualApply = require('./actualApply'); + +/** @type {(args: [Function, thisArg?: unknown, ...args: unknown[]]) => Function} TODO FIXME, find a way to use import('.') */ +module.exports = function callBindBasic(args) { + if (args.length < 1 || typeof args[0] !== 'function') { + throw new $TypeError('a function is required'); + } + return $actualApply(bind, $call, args); +}; diff --git a/server/node_modules/call-bind-apply-helpers/package.json b/server/node_modules/call-bind-apply-helpers/package.json new file mode 100644 index 0000000..923b8be --- /dev/null +++ b/server/node_modules/call-bind-apply-helpers/package.json @@ -0,0 +1,85 @@ +{ + "name": "call-bind-apply-helpers", + "version": "1.0.2", + "description": "Helper functions around Function call/apply/bind, for use in `call-bind`", + "main": "index.js", + "exports": { + ".": "./index.js", + "./actualApply": "./actualApply.js", + "./applyBind": "./applyBind.js", + "./functionApply": "./functionApply.js", + "./functionCall": "./functionCall.js", + "./reflectApply": "./reflectApply.js", + "./package.json": "./package.json" + }, + "scripts": { + "prepack": "npmignore --auto --commentLines=auto", + "prepublish": "not-in-publish || npm run prepublishOnly", + "prepublishOnly": "safe-publish-latest", + "prelint": "evalmd README.md", + "lint": "eslint --ext=.js,.mjs .", + "postlint": "tsc -p . && attw -P", + "pretest": "npm run lint", + "tests-only": "nyc tape 'test/**/*.js'", + "test": "npm run tests-only", + "posttest": "npx npm@'>=10.2' audit --production", + "version": "auto-changelog && git add CHANGELOG.md", + "postversion": "auto-changelog && git add CHANGELOG.md && git commit --no-edit --amend && git tag -f \"v$(node -e \"console.log(require('./package.json').version)\")\"" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/ljharb/call-bind-apply-helpers.git" + }, + "author": "Jordan Harband ", + "license": "MIT", + "bugs": { + "url": "https://github.com/ljharb/call-bind-apply-helpers/issues" + }, + "homepage": "https://github.com/ljharb/call-bind-apply-helpers#readme", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "devDependencies": { + "@arethetypeswrong/cli": "^0.17.3", + "@ljharb/eslint-config": "^21.1.1", + "@ljharb/tsconfig": "^0.2.3", + "@types/for-each": "^0.3.3", + "@types/function-bind": "^1.1.10", + "@types/object-inspect": "^1.13.0", + "@types/tape": "^5.8.1", + "auto-changelog": "^2.5.0", + "encoding": "^0.1.13", + "es-value-fixtures": "^1.7.1", + "eslint": "=8.8.0", + "evalmd": "^0.0.19", + "for-each": "^0.3.5", + "has-strict-mode": "^1.1.0", + "in-publish": "^2.0.1", + "npmignore": "^0.3.1", + "nyc": "^10.3.2", + "object-inspect": "^1.13.4", + "safe-publish-latest": "^2.0.0", + "tape": "^5.9.0", + "typescript": "next" + }, + "testling": { + "files": "test/index.js" + }, + "auto-changelog": { + "output": "CHANGELOG.md", + "template": "keepachangelog", + "unreleased": false, + "commitLimit": false, + "backfillLimit": false, + "hideCredit": true + }, + "publishConfig": { + "ignore": [ + ".github/workflows" + ] + }, + "engines": { + "node": ">= 0.4" + } +} diff --git a/server/node_modules/call-bind-apply-helpers/reflectApply.d.ts b/server/node_modules/call-bind-apply-helpers/reflectApply.d.ts new file mode 100644 index 0000000..6b2ae76 --- /dev/null +++ b/server/node_modules/call-bind-apply-helpers/reflectApply.d.ts @@ -0,0 +1,3 @@ +declare const reflectApply: false | typeof Reflect.apply; + +export = reflectApply; diff --git a/server/node_modules/call-bind-apply-helpers/reflectApply.js b/server/node_modules/call-bind-apply-helpers/reflectApply.js new file mode 100644 index 0000000..3d03caa --- /dev/null +++ b/server/node_modules/call-bind-apply-helpers/reflectApply.js @@ -0,0 +1,4 @@ +'use strict'; + +/** @type {import('./reflectApply')} */ +module.exports = typeof Reflect !== 'undefined' && Reflect && Reflect.apply; diff --git a/server/node_modules/call-bind-apply-helpers/test/index.js b/server/node_modules/call-bind-apply-helpers/test/index.js new file mode 100644 index 0000000..1cdc89e --- /dev/null +++ b/server/node_modules/call-bind-apply-helpers/test/index.js @@ -0,0 +1,63 @@ +'use strict'; + +var callBind = require('../'); +var hasStrictMode = require('has-strict-mode')(); +var forEach = require('for-each'); +var inspect = require('object-inspect'); +var v = require('es-value-fixtures'); + +var test = require('tape'); + +test('callBindBasic', function (t) { + forEach(v.nonFunctions, function (nonFunction) { + t['throws']( + // @ts-expect-error + function () { callBind([nonFunction]); }, + TypeError, + inspect(nonFunction) + ' is not a function' + ); + }); + + var sentinel = { sentinel: true }; + /** @type {(this: T, a: A, b: B) => [T | undefined, A, B]} */ + var func = function (a, b) { + // eslint-disable-next-line no-invalid-this + return [!hasStrictMode && this === global ? undefined : this, a, b]; + }; + t.equal(func.length, 2, 'original function length is 2'); + + /** type {(thisArg: unknown, a: number, b: number) => [unknown, number, number]} */ + var bound = callBind([func]); + /** type {((a: number, b: number) => [typeof sentinel, typeof a, typeof b])} */ + var boundR = callBind([func, sentinel]); + /** type {((b: number) => [typeof sentinel, number, typeof b])} */ + var boundArg = callBind([func, sentinel, /** @type {const} */ (1)]); + + // @ts-expect-error + t.deepEqual(bound(), [undefined, undefined, undefined], 'bound func with no args'); + + // @ts-expect-error + t.deepEqual(func(), [undefined, undefined, undefined], 'unbound func with too few args'); + // @ts-expect-error + t.deepEqual(bound(1, 2), [hasStrictMode ? 1 : Object(1), 2, undefined], 'bound func too few args'); + // @ts-expect-error + t.deepEqual(boundR(), [sentinel, undefined, undefined], 'bound func with receiver, with too few args'); + // @ts-expect-error + t.deepEqual(boundArg(), [sentinel, 1, undefined], 'bound func with receiver and arg, with too few args'); + + t.deepEqual(func(1, 2), [undefined, 1, 2], 'unbound func with right args'); + t.deepEqual(bound(1, 2, 3), [hasStrictMode ? 1 : Object(1), 2, 3], 'bound func with right args'); + t.deepEqual(boundR(1, 2), [sentinel, 1, 2], 'bound func with receiver, with right args'); + t.deepEqual(boundArg(2), [sentinel, 1, 2], 'bound func with receiver and arg, with right arg'); + + // @ts-expect-error + t.deepEqual(func(1, 2, 3), [undefined, 1, 2], 'unbound func with too many args'); + // @ts-expect-error + t.deepEqual(bound(1, 2, 3, 4), [hasStrictMode ? 1 : Object(1), 2, 3], 'bound func with too many args'); + // @ts-expect-error + t.deepEqual(boundR(1, 2, 3), [sentinel, 1, 2], 'bound func with receiver, with too many args'); + // @ts-expect-error + t.deepEqual(boundArg(2, 3), [sentinel, 1, 2], 'bound func with receiver and arg, with too many args'); + + t.end(); +}); diff --git a/server/node_modules/call-bind-apply-helpers/tsconfig.json b/server/node_modules/call-bind-apply-helpers/tsconfig.json new file mode 100644 index 0000000..aef9993 --- /dev/null +++ b/server/node_modules/call-bind-apply-helpers/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "@ljharb/tsconfig", + "compilerOptions": { + "target": "es2021", + }, + "exclude": [ + "coverage", + ], +} \ No newline at end of file diff --git a/server/node_modules/call-bound/.eslintrc b/server/node_modules/call-bound/.eslintrc new file mode 100644 index 0000000..2612ed8 --- /dev/null +++ b/server/node_modules/call-bound/.eslintrc @@ -0,0 +1,13 @@ +{ + "root": true, + + "extends": "@ljharb", + + "rules": { + "new-cap": [2, { + "capIsNewExceptions": [ + "GetIntrinsic", + ], + }], + }, +} diff --git a/server/node_modules/call-bound/.github/FUNDING.yml b/server/node_modules/call-bound/.github/FUNDING.yml new file mode 100644 index 0000000..2a2a135 --- /dev/null +++ b/server/node_modules/call-bound/.github/FUNDING.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +github: [ljharb] +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: npm/call-bound +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/server/node_modules/call-bound/.nycrc b/server/node_modules/call-bound/.nycrc new file mode 100644 index 0000000..bdd626c --- /dev/null +++ b/server/node_modules/call-bound/.nycrc @@ -0,0 +1,9 @@ +{ + "all": true, + "check-coverage": false, + "reporter": ["text-summary", "text", "html", "json"], + "exclude": [ + "coverage", + "test" + ] +} diff --git a/server/node_modules/call-bound/CHANGELOG.md b/server/node_modules/call-bound/CHANGELOG.md new file mode 100644 index 0000000..8bde4e9 --- /dev/null +++ b/server/node_modules/call-bound/CHANGELOG.md @@ -0,0 +1,42 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [v1.0.4](https://github.com/ljharb/call-bound/compare/v1.0.3...v1.0.4) - 2025-03-03 + +### Commits + +- [types] improve types [`e648922`](https://github.com/ljharb/call-bound/commit/e6489222a9e54f350fbf952ceabe51fd8b6027ff) +- [Dev Deps] update `@arethetypeswrong/cli`, `@ljharb/tsconfig`, `@types/tape`, `es-value-fixtures`, `for-each`, `has-strict-mode`, `object-inspect` [`a42a5eb`](https://github.com/ljharb/call-bound/commit/a42a5ebe6c1b54fcdc7997c7dc64fdca9e936719) +- [Deps] update `call-bind-apply-helpers`, `get-intrinsic` [`f529eac`](https://github.com/ljharb/call-bound/commit/f529eac132404c17156bbc23ab2297a25d0f20b8) + +## [v1.0.3](https://github.com/ljharb/call-bound/compare/v1.0.2...v1.0.3) - 2024-12-15 + +### Commits + +- [Refactor] use `call-bind-apply-helpers` instead of `call-bind` [`5e0b134`](https://github.com/ljharb/call-bound/commit/5e0b13496df14fb7d05dae9412f088da8d3f75be) +- [Deps] update `get-intrinsic` [`41fc967`](https://github.com/ljharb/call-bound/commit/41fc96732a22c7b7e8f381f93ccc54bb6293be2e) +- [readme] fix example [`79a0137`](https://github.com/ljharb/call-bound/commit/79a0137723f7c6d09c9c05452bbf8d5efb5d6e49) +- [meta] add `sideEffects` flag [`08b07be`](https://github.com/ljharb/call-bound/commit/08b07be7f1c03f67dc6f3cdaf0906259771859f7) + +## [v1.0.2](https://github.com/ljharb/call-bound/compare/v1.0.1...v1.0.2) - 2024-12-10 + +### Commits + +- [Dev Deps] update `@arethetypeswrong/cli`, `@ljharb/tsconfig`, `gopd` [`e6a5ffe`](https://github.com/ljharb/call-bound/commit/e6a5ffe849368fe4f74dfd6cdeca1b9baa39e8d5) +- [Deps] update `call-bind`, `get-intrinsic` [`2aeb5b5`](https://github.com/ljharb/call-bound/commit/2aeb5b521dc2b2683d1345c753ea1161de2d1c14) +- [types] improve return type [`1a0c9fe`](https://github.com/ljharb/call-bound/commit/1a0c9fe3114471e7ca1f57d104e2efe713bb4871) + +## v1.0.1 - 2024-12-05 + +### Commits + +- Initial implementation, tests, readme, types [`6d94121`](https://github.com/ljharb/call-bound/commit/6d94121a9243602e506334069f7a03189fe3363d) +- Initial commit [`0eae867`](https://github.com/ljharb/call-bound/commit/0eae867334ea025c33e6e91cdecfc9df96680cf9) +- npm init [`71b2479`](https://github.com/ljharb/call-bound/commit/71b2479c6723e0b7d91a6b663613067e98b7b275) +- Only apps should have lockfiles [`c3754a9`](https://github.com/ljharb/call-bound/commit/c3754a949b7f9132b47e2d18c1729889736741eb) +- [actions] skip `npm ls` in node < 10 [`74275a5`](https://github.com/ljharb/call-bound/commit/74275a5186b8caf6309b6b97472bdcb0df4683a8) +- [Dev Deps] add missing peer dep [`1354de8`](https://github.com/ljharb/call-bound/commit/1354de8679413e4ae9c523d85f76fa7a5e032d97) diff --git a/server/node_modules/call-bound/LICENSE b/server/node_modules/call-bound/LICENSE new file mode 100644 index 0000000..f82f389 --- /dev/null +++ b/server/node_modules/call-bound/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Jordan Harband + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/server/node_modules/call-bound/README.md b/server/node_modules/call-bound/README.md new file mode 100644 index 0000000..a44e43e --- /dev/null +++ b/server/node_modules/call-bound/README.md @@ -0,0 +1,53 @@ +# call-bound [![Version Badge][npm-version-svg]][package-url] + +[![github actions][actions-image]][actions-url] +[![coverage][codecov-image]][codecov-url] +[![dependency status][deps-svg]][deps-url] +[![dev dependency status][dev-deps-svg]][dev-deps-url] +[![License][license-image]][license-url] +[![Downloads][downloads-image]][downloads-url] + +[![npm badge][npm-badge-png]][package-url] + +Robust call-bound JavaScript intrinsics, using `call-bind` and `get-intrinsic`. + +## Getting started + +```sh +npm install --save call-bound +``` + +## Usage/Examples + +```js +const assert = require('assert'); +const callBound = require('call-bound'); + +const slice = callBound('Array.prototype.slice'); + +delete Function.prototype.call; +delete Function.prototype.bind; +delete Array.prototype.slice; + +assert.deepEqual(slice([1, 2, 3, 4], 1, -1), [2, 3]); +``` + +## Tests + +Clone the repo, `npm install`, and run `npm test` + +[package-url]: https://npmjs.org/package/call-bound +[npm-version-svg]: https://versionbadg.es/ljharb/call-bound.svg +[deps-svg]: https://david-dm.org/ljharb/call-bound.svg +[deps-url]: https://david-dm.org/ljharb/call-bound +[dev-deps-svg]: https://david-dm.org/ljharb/call-bound/dev-status.svg +[dev-deps-url]: https://david-dm.org/ljharb/call-bound#info=devDependencies +[npm-badge-png]: https://nodei.co/npm/call-bound.png?downloads=true&stars=true +[license-image]: https://img.shields.io/npm/l/call-bound.svg +[license-url]: LICENSE +[downloads-image]: https://img.shields.io/npm/dm/call-bound.svg +[downloads-url]: https://npm-stat.com/charts.html?package=call-bound +[codecov-image]: https://codecov.io/gh/ljharb/call-bound/branch/main/graphs/badge.svg +[codecov-url]: https://app.codecov.io/gh/ljharb/call-bound/ +[actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/ljharb/call-bound +[actions-url]: https://github.com/ljharb/call-bound/actions diff --git a/server/node_modules/call-bound/index.d.ts b/server/node_modules/call-bound/index.d.ts new file mode 100644 index 0000000..5562f00 --- /dev/null +++ b/server/node_modules/call-bound/index.d.ts @@ -0,0 +1,94 @@ +type Intrinsic = typeof globalThis; + +type IntrinsicName = keyof Intrinsic | `%${keyof Intrinsic}%`; + +type IntrinsicPath = IntrinsicName | `${StripPercents}.${string}` | `%${StripPercents}.${string}%`; + +type AllowMissing = boolean; + +type StripPercents = T extends `%${infer U}%` ? U : T; + +type BindMethodPrecise = + F extends (this: infer This, ...args: infer Args) => infer R + ? (obj: This, ...args: Args) => R + : F extends { + (this: infer This1, ...args: infer Args1): infer R1; + (this: infer This2, ...args: infer Args2): infer R2 + } + ? { + (obj: This1, ...args: Args1): R1; + (obj: This2, ...args: Args2): R2 + } + : never + +// Extract method type from a prototype +type GetPrototypeMethod = + (typeof globalThis)[T] extends { prototype: any } + ? M extends keyof (typeof globalThis)[T]['prototype'] + ? (typeof globalThis)[T]['prototype'][M] + : never + : never + +// Get static property/method +type GetStaticMember = + P extends keyof (typeof globalThis)[T] ? (typeof globalThis)[T][P] : never + +// Type that maps string path to actual bound function or value with better precision +type BoundIntrinsic = + S extends `${infer Obj}.prototype.${infer Method}` + ? Obj extends keyof typeof globalThis + ? BindMethodPrecise> + : unknown + : S extends `${infer Obj}.${infer Prop}` + ? Obj extends keyof typeof globalThis + ? GetStaticMember + : unknown + : unknown + +declare function arraySlice(array: readonly T[], start?: number, end?: number): T[]; +declare function arraySlice(array: ArrayLike, start?: number, end?: number): T[]; +declare function arraySlice(array: IArguments, start?: number, end?: number): T[]; + +// Special cases for methods that need explicit typing +interface SpecialCases { + '%Object.prototype.isPrototypeOf%': (thisArg: {}, obj: unknown) => boolean; + '%String.prototype.replace%': { + (str: string, searchValue: string | RegExp, replaceValue: string): string; + (str: string, searchValue: string | RegExp, replacer: (substring: string, ...args: any[]) => string): string + }; + '%Object.prototype.toString%': (obj: {}) => string; + '%Object.prototype.hasOwnProperty%': (obj: {}, v: PropertyKey) => boolean; + '%Array.prototype.slice%': typeof arraySlice; + '%Array.prototype.map%': (array: readonly T[], callbackfn: (value: T, index: number, array: readonly T[]) => U, thisArg?: any) => U[]; + '%Array.prototype.filter%': (array: readonly T[], predicate: (value: T, index: number, array: readonly T[]) => unknown, thisArg?: any) => T[]; + '%Array.prototype.indexOf%': (array: readonly T[], searchElement: T, fromIndex?: number) => number; + '%Function.prototype.apply%': (fn: (...args: A) => R, thisArg: any, args: A) => R; + '%Function.prototype.call%': (fn: (...args: A) => R, thisArg: any, ...args: A) => R; + '%Function.prototype.bind%': (fn: (...args: A) => R, thisArg: any, ...args: A) => (...remainingArgs: A) => R; + '%Promise.prototype.then%': { + (promise: Promise, onfulfilled: (value: T) => R | PromiseLike): Promise; + (promise: Promise, onfulfilled: ((value: T) => R | PromiseLike) | undefined | null, onrejected: (reason: any) => R | PromiseLike): Promise; + }; + '%RegExp.prototype.test%': (regexp: RegExp, str: string) => boolean; + '%RegExp.prototype.exec%': (regexp: RegExp, str: string) => RegExpExecArray | null; + '%Error.prototype.toString%': (error: Error) => string; + '%TypeError.prototype.toString%': (error: TypeError) => string; + '%String.prototype.split%': ( + obj: unknown, + splitter: string | RegExp | { + [Symbol.split](string: string, limit?: number): string[]; + }, + limit?: number | undefined + ) => string[]; +} + +/** + * Returns a bound function for a prototype method, or a value for a static property. + * + * @param name - The name of the intrinsic (e.g. 'Array.prototype.slice') + * @param {AllowMissing} [allowMissing] - Whether to allow missing intrinsics (default: false) + */ +declare function callBound, S extends IntrinsicPath>(name: K, allowMissing?: AllowMissing): SpecialCases[`%${StripPercents}%`]; +declare function callBound, S extends IntrinsicPath>(name: S, allowMissing?: AllowMissing): BoundIntrinsic; + +export = callBound; diff --git a/server/node_modules/call-bound/index.js b/server/node_modules/call-bound/index.js new file mode 100644 index 0000000..e9ade74 --- /dev/null +++ b/server/node_modules/call-bound/index.js @@ -0,0 +1,19 @@ +'use strict'; + +var GetIntrinsic = require('get-intrinsic'); + +var callBindBasic = require('call-bind-apply-helpers'); + +/** @type {(thisArg: string, searchString: string, position?: number) => number} */ +var $indexOf = callBindBasic([GetIntrinsic('%String.prototype.indexOf%')]); + +/** @type {import('.')} */ +module.exports = function callBoundIntrinsic(name, allowMissing) { + /* eslint no-extra-parens: 0 */ + + var intrinsic = /** @type {(this: unknown, ...args: unknown[]) => unknown} */ (GetIntrinsic(name, !!allowMissing)); + if (typeof intrinsic === 'function' && $indexOf(name, '.prototype.') > -1) { + return callBindBasic(/** @type {const} */ ([intrinsic])); + } + return intrinsic; +}; diff --git a/server/node_modules/call-bound/package.json b/server/node_modules/call-bound/package.json new file mode 100644 index 0000000..d542db4 --- /dev/null +++ b/server/node_modules/call-bound/package.json @@ -0,0 +1,99 @@ +{ + "name": "call-bound", + "version": "1.0.4", + "description": "Robust call-bound JavaScript intrinsics, using `call-bind` and `get-intrinsic`.", + "main": "index.js", + "exports": { + ".": "./index.js", + "./package.json": "./package.json" + }, + "sideEffects": false, + "scripts": { + "prepack": "npmignore --auto --commentLines=auto", + "prepublish": "not-in-publish || npm run prepublishOnly", + "prepublishOnly": "safe-publish-latest", + "prelint": "evalmd README.md", + "lint": "eslint --ext=.js,.mjs .", + "postlint": "tsc -p . && attw -P", + "pretest": "npm run lint", + "tests-only": "nyc tape 'test/**/*.js'", + "test": "npm run tests-only", + "posttest": "npx npm@'>=10.2' audit --production", + "version": "auto-changelog && git add CHANGELOG.md", + "postversion": "auto-changelog && git add CHANGELOG.md && git commit --no-edit --amend && git tag -f \"v$(node -e \"console.log(require('./package.json').version)\")\"" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/ljharb/call-bound.git" + }, + "keywords": [ + "javascript", + "ecmascript", + "es", + "js", + "callbind", + "callbound", + "call", + "bind", + "bound", + "call-bind", + "call-bound", + "function", + "es-abstract" + ], + "author": "Jordan Harband ", + "funding": { + "url": "https://github.com/sponsors/ljharb" + }, + "license": "MIT", + "bugs": { + "url": "https://github.com/ljharb/call-bound/issues" + }, + "homepage": "https://github.com/ljharb/call-bound#readme", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "devDependencies": { + "@arethetypeswrong/cli": "^0.17.4", + "@ljharb/eslint-config": "^21.1.1", + "@ljharb/tsconfig": "^0.3.0", + "@types/call-bind": "^1.0.5", + "@types/get-intrinsic": "^1.2.3", + "@types/tape": "^5.8.1", + "auto-changelog": "^2.5.0", + "encoding": "^0.1.13", + "es-value-fixtures": "^1.7.1", + "eslint": "=8.8.0", + "evalmd": "^0.0.19", + "for-each": "^0.3.5", + "gopd": "^1.2.0", + "has-strict-mode": "^1.1.0", + "in-publish": "^2.0.1", + "npmignore": "^0.3.1", + "nyc": "^10.3.2", + "object-inspect": "^1.13.4", + "safe-publish-latest": "^2.0.0", + "tape": "^5.9.0", + "typescript": "next" + }, + "testling": { + "files": "test/index.js" + }, + "auto-changelog": { + "output": "CHANGELOG.md", + "template": "keepachangelog", + "unreleased": false, + "commitLimit": false, + "backfillLimit": false, + "hideCredit": true + }, + "publishConfig": { + "ignore": [ + ".github/workflows" + ] + }, + "engines": { + "node": ">= 0.4" + } +} diff --git a/server/node_modules/call-bound/test/index.js b/server/node_modules/call-bound/test/index.js new file mode 100644 index 0000000..a2fc9f0 --- /dev/null +++ b/server/node_modules/call-bound/test/index.js @@ -0,0 +1,61 @@ +'use strict'; + +var test = require('tape'); + +var callBound = require('../'); + +/** @template {true} T @template U @typedef {T extends U ? T : never} AssertType */ + +test('callBound', function (t) { + // static primitive + t.equal(callBound('Array.length'), Array.length, 'Array.length yields itself'); + t.equal(callBound('%Array.length%'), Array.length, '%Array.length% yields itself'); + + // static non-function object + t.equal(callBound('Array.prototype'), Array.prototype, 'Array.prototype yields itself'); + t.equal(callBound('%Array.prototype%'), Array.prototype, '%Array.prototype% yields itself'); + t.equal(callBound('Array.constructor'), Array.constructor, 'Array.constructor yields itself'); + t.equal(callBound('%Array.constructor%'), Array.constructor, '%Array.constructor% yields itself'); + + // static function + t.equal(callBound('Date.parse'), Date.parse, 'Date.parse yields itself'); + t.equal(callBound('%Date.parse%'), Date.parse, '%Date.parse% yields itself'); + + // prototype primitive + t.equal(callBound('Error.prototype.message'), Error.prototype.message, 'Error.prototype.message yields itself'); + t.equal(callBound('%Error.prototype.message%'), Error.prototype.message, '%Error.prototype.message% yields itself'); + + var x = callBound('Object.prototype.toString'); + var y = callBound('%Object.prototype.toString%'); + + // prototype function + t.notEqual(x, Object.prototype.toString, 'Object.prototype.toString does not yield itself'); + t.notEqual(y, Object.prototype.toString, '%Object.prototype.toString% does not yield itself'); + t.equal(x(true), Object.prototype.toString.call(true), 'call-bound Object.prototype.toString calls into the original'); + t.equal(y(true), Object.prototype.toString.call(true), 'call-bound %Object.prototype.toString% calls into the original'); + + t['throws']( + // @ts-expect-error + function () { callBound('does not exist'); }, + SyntaxError, + 'nonexistent intrinsic throws' + ); + t['throws']( + // @ts-expect-error + function () { callBound('does not exist', true); }, + SyntaxError, + 'allowMissing arg still throws for unknown intrinsic' + ); + + t.test('real but absent intrinsic', { skip: typeof WeakRef !== 'undefined' }, function (st) { + st['throws']( + function () { callBound('WeakRef'); }, + TypeError, + 'real but absent intrinsic throws' + ); + st.equal(callBound('WeakRef', true), undefined, 'allowMissing arg avoids exception'); + st.end(); + }); + + t.end(); +}); diff --git a/server/node_modules/call-bound/tsconfig.json b/server/node_modules/call-bound/tsconfig.json new file mode 100644 index 0000000..8976d98 --- /dev/null +++ b/server/node_modules/call-bound/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@ljharb/tsconfig", + "compilerOptions": { + "target": "ESNext", + "lib": ["es2024"], + }, + "exclude": [ + "coverage", + ], +} diff --git a/server/node_modules/color-convert/CHANGELOG.md b/server/node_modules/color-convert/CHANGELOG.md new file mode 100644 index 0000000..0a7bce4 --- /dev/null +++ b/server/node_modules/color-convert/CHANGELOG.md @@ -0,0 +1,54 @@ +# 1.0.0 - 2016-01-07 + +- Removed: unused speed test +- Added: Automatic routing between previously unsupported conversions +([#27](https://github.com/Qix-/color-convert/pull/27)) +- Removed: `xxx2xxx()` and `xxx2xxxRaw()` functions +([#27](https://github.com/Qix-/color-convert/pull/27)) +- Removed: `convert()` class +([#27](https://github.com/Qix-/color-convert/pull/27)) +- Changed: all functions to lookup dictionary +([#27](https://github.com/Qix-/color-convert/pull/27)) +- Changed: `ansi` to `ansi256` +([#27](https://github.com/Qix-/color-convert/pull/27)) +- Fixed: argument grouping for functions requiring only one argument +([#27](https://github.com/Qix-/color-convert/pull/27)) + +# 0.6.0 - 2015-07-23 + +- Added: methods to handle +[ANSI](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors) 16/256 colors: + - rgb2ansi16 + - rgb2ansi + - hsl2ansi16 + - hsl2ansi + - hsv2ansi16 + - hsv2ansi + - hwb2ansi16 + - hwb2ansi + - cmyk2ansi16 + - cmyk2ansi + - keyword2ansi16 + - keyword2ansi + - ansi162rgb + - ansi162hsl + - ansi162hsv + - ansi162hwb + - ansi162cmyk + - ansi162keyword + - ansi2rgb + - ansi2hsl + - ansi2hsv + - ansi2hwb + - ansi2cmyk + - ansi2keyword +([#18](https://github.com/harthur/color-convert/pull/18)) + +# 0.5.3 - 2015-06-02 + +- Fixed: hsl2hsv does not return `NaN` anymore when using `[0,0,0]` +([#15](https://github.com/harthur/color-convert/issues/15)) + +--- + +Check out commit logs for older releases diff --git a/server/node_modules/color-convert/LICENSE b/server/node_modules/color-convert/LICENSE new file mode 100644 index 0000000..5b4c386 --- /dev/null +++ b/server/node_modules/color-convert/LICENSE @@ -0,0 +1,21 @@ +Copyright (c) 2011-2016 Heather Arthur + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/server/node_modules/color-convert/README.md b/server/node_modules/color-convert/README.md new file mode 100644 index 0000000..d4b08fc --- /dev/null +++ b/server/node_modules/color-convert/README.md @@ -0,0 +1,68 @@ +# color-convert + +[![Build Status](https://travis-ci.org/Qix-/color-convert.svg?branch=master)](https://travis-ci.org/Qix-/color-convert) + +Color-convert is a color conversion library for JavaScript and node. +It converts all ways between `rgb`, `hsl`, `hsv`, `hwb`, `cmyk`, `ansi`, `ansi16`, `hex` strings, and CSS `keyword`s (will round to closest): + +```js +var convert = require('color-convert'); + +convert.rgb.hsl(140, 200, 100); // [96, 48, 59] +convert.keyword.rgb('blue'); // [0, 0, 255] + +var rgbChannels = convert.rgb.channels; // 3 +var cmykChannels = convert.cmyk.channels; // 4 +var ansiChannels = convert.ansi16.channels; // 1 +``` + +# Install + +```console +$ npm install color-convert +``` + +# API + +Simply get the property of the _from_ and _to_ conversion that you're looking for. + +All functions have a rounded and unrounded variant. By default, return values are rounded. To get the unrounded (raw) results, simply tack on `.raw` to the function. + +All 'from' functions have a hidden property called `.channels` that indicates the number of channels the function expects (not including alpha). + +```js +var convert = require('color-convert'); + +// Hex to LAB +convert.hex.lab('DEADBF'); // [ 76, 21, -2 ] +convert.hex.lab.raw('DEADBF'); // [ 75.56213190997677, 20.653827952644754, -2.290532499330533 ] + +// RGB to CMYK +convert.rgb.cmyk(167, 255, 4); // [ 35, 0, 98, 0 ] +convert.rgb.cmyk.raw(167, 255, 4); // [ 34.509803921568626, 0, 98.43137254901961, 0 ] +``` + +### Arrays +All functions that accept multiple arguments also support passing an array. + +Note that this does **not** apply to functions that convert from a color that only requires one value (e.g. `keyword`, `ansi256`, `hex`, etc.) + +```js +var convert = require('color-convert'); + +convert.rgb.hex(123, 45, 67); // '7B2D43' +convert.rgb.hex([123, 45, 67]); // '7B2D43' +``` + +## Routing + +Conversions that don't have an _explicitly_ defined conversion (in [conversions.js](conversions.js)), but can be converted by means of sub-conversions (e.g. XYZ -> **RGB** -> CMYK), are automatically routed together. This allows just about any color model supported by `color-convert` to be converted to any other model, so long as a sub-conversion path exists. This is also true for conversions requiring more than one step in between (e.g. LCH -> **LAB** -> **XYZ** -> **RGB** -> Hex). + +Keep in mind that extensive conversions _may_ result in a loss of precision, and exist only to be complete. For a list of "direct" (single-step) conversions, see [conversions.js](conversions.js). + +# Contribute + +If there is a new model you would like to support, or want to add a direct conversion between two existing models, please send us a pull request. + +# License +Copyright © 2011-2016, Heather Arthur and Josh Junon. Licensed under the [MIT License](LICENSE). diff --git a/server/node_modules/color-convert/conversions.js b/server/node_modules/color-convert/conversions.js new file mode 100644 index 0000000..2657f26 --- /dev/null +++ b/server/node_modules/color-convert/conversions.js @@ -0,0 +1,839 @@ +/* MIT license */ +/* eslint-disable no-mixed-operators */ +const cssKeywords = require('color-name'); + +// NOTE: conversions should only return primitive values (i.e. arrays, or +// values that give correct `typeof` results). +// do not use box values types (i.e. Number(), String(), etc.) + +const reverseKeywords = {}; +for (const key of Object.keys(cssKeywords)) { + reverseKeywords[cssKeywords[key]] = key; +} + +const convert = { + rgb: {channels: 3, labels: 'rgb'}, + hsl: {channels: 3, labels: 'hsl'}, + hsv: {channels: 3, labels: 'hsv'}, + hwb: {channels: 3, labels: 'hwb'}, + cmyk: {channels: 4, labels: 'cmyk'}, + xyz: {channels: 3, labels: 'xyz'}, + lab: {channels: 3, labels: 'lab'}, + lch: {channels: 3, labels: 'lch'}, + hex: {channels: 1, labels: ['hex']}, + keyword: {channels: 1, labels: ['keyword']}, + ansi16: {channels: 1, labels: ['ansi16']}, + ansi256: {channels: 1, labels: ['ansi256']}, + hcg: {channels: 3, labels: ['h', 'c', 'g']}, + apple: {channels: 3, labels: ['r16', 'g16', 'b16']}, + gray: {channels: 1, labels: ['gray']} +}; + +module.exports = convert; + +// Hide .channels and .labels properties +for (const model of Object.keys(convert)) { + if (!('channels' in convert[model])) { + throw new Error('missing channels property: ' + model); + } + + if (!('labels' in convert[model])) { + throw new Error('missing channel labels property: ' + model); + } + + if (convert[model].labels.length !== convert[model].channels) { + throw new Error('channel and label counts mismatch: ' + model); + } + + const {channels, labels} = convert[model]; + delete convert[model].channels; + delete convert[model].labels; + Object.defineProperty(convert[model], 'channels', {value: channels}); + Object.defineProperty(convert[model], 'labels', {value: labels}); +} + +convert.rgb.hsl = function (rgb) { + const r = rgb[0] / 255; + const g = rgb[1] / 255; + const b = rgb[2] / 255; + const min = Math.min(r, g, b); + const max = Math.max(r, g, b); + const delta = max - min; + let h; + let s; + + if (max === min) { + h = 0; + } else if (r === max) { + h = (g - b) / delta; + } else if (g === max) { + h = 2 + (b - r) / delta; + } else if (b === max) { + h = 4 + (r - g) / delta; + } + + h = Math.min(h * 60, 360); + + if (h < 0) { + h += 360; + } + + const l = (min + max) / 2; + + if (max === min) { + s = 0; + } else if (l <= 0.5) { + s = delta / (max + min); + } else { + s = delta / (2 - max - min); + } + + return [h, s * 100, l * 100]; +}; + +convert.rgb.hsv = function (rgb) { + let rdif; + let gdif; + let bdif; + let h; + let s; + + const r = rgb[0] / 255; + const g = rgb[1] / 255; + const b = rgb[2] / 255; + const v = Math.max(r, g, b); + const diff = v - Math.min(r, g, b); + const diffc = function (c) { + return (v - c) / 6 / diff + 1 / 2; + }; + + if (diff === 0) { + h = 0; + s = 0; + } else { + s = diff / v; + rdif = diffc(r); + gdif = diffc(g); + bdif = diffc(b); + + if (r === v) { + h = bdif - gdif; + } else if (g === v) { + h = (1 / 3) + rdif - bdif; + } else if (b === v) { + h = (2 / 3) + gdif - rdif; + } + + if (h < 0) { + h += 1; + } else if (h > 1) { + h -= 1; + } + } + + return [ + h * 360, + s * 100, + v * 100 + ]; +}; + +convert.rgb.hwb = function (rgb) { + const r = rgb[0]; + const g = rgb[1]; + let b = rgb[2]; + const h = convert.rgb.hsl(rgb)[0]; + const w = 1 / 255 * Math.min(r, Math.min(g, b)); + + b = 1 - 1 / 255 * Math.max(r, Math.max(g, b)); + + return [h, w * 100, b * 100]; +}; + +convert.rgb.cmyk = function (rgb) { + const r = rgb[0] / 255; + const g = rgb[1] / 255; + const b = rgb[2] / 255; + + const k = Math.min(1 - r, 1 - g, 1 - b); + const c = (1 - r - k) / (1 - k) || 0; + const m = (1 - g - k) / (1 - k) || 0; + const y = (1 - b - k) / (1 - k) || 0; + + return [c * 100, m * 100, y * 100, k * 100]; +}; + +function comparativeDistance(x, y) { + /* + See https://en.m.wikipedia.org/wiki/Euclidean_distance#Squared_Euclidean_distance + */ + return ( + ((x[0] - y[0]) ** 2) + + ((x[1] - y[1]) ** 2) + + ((x[2] - y[2]) ** 2) + ); +} + +convert.rgb.keyword = function (rgb) { + const reversed = reverseKeywords[rgb]; + if (reversed) { + return reversed; + } + + let currentClosestDistance = Infinity; + let currentClosestKeyword; + + for (const keyword of Object.keys(cssKeywords)) { + const value = cssKeywords[keyword]; + + // Compute comparative distance + const distance = comparativeDistance(rgb, value); + + // Check if its less, if so set as closest + if (distance < currentClosestDistance) { + currentClosestDistance = distance; + currentClosestKeyword = keyword; + } + } + + return currentClosestKeyword; +}; + +convert.keyword.rgb = function (keyword) { + return cssKeywords[keyword]; +}; + +convert.rgb.xyz = function (rgb) { + let r = rgb[0] / 255; + let g = rgb[1] / 255; + let b = rgb[2] / 255; + + // Assume sRGB + r = r > 0.04045 ? (((r + 0.055) / 1.055) ** 2.4) : (r / 12.92); + g = g > 0.04045 ? (((g + 0.055) / 1.055) ** 2.4) : (g / 12.92); + b = b > 0.04045 ? (((b + 0.055) / 1.055) ** 2.4) : (b / 12.92); + + const x = (r * 0.4124) + (g * 0.3576) + (b * 0.1805); + const y = (r * 0.2126) + (g * 0.7152) + (b * 0.0722); + const z = (r * 0.0193) + (g * 0.1192) + (b * 0.9505); + + return [x * 100, y * 100, z * 100]; +}; + +convert.rgb.lab = function (rgb) { + const xyz = convert.rgb.xyz(rgb); + let x = xyz[0]; + let y = xyz[1]; + let z = xyz[2]; + + x /= 95.047; + y /= 100; + z /= 108.883; + + x = x > 0.008856 ? (x ** (1 / 3)) : (7.787 * x) + (16 / 116); + y = y > 0.008856 ? (y ** (1 / 3)) : (7.787 * y) + (16 / 116); + z = z > 0.008856 ? (z ** (1 / 3)) : (7.787 * z) + (16 / 116); + + const l = (116 * y) - 16; + const a = 500 * (x - y); + const b = 200 * (y - z); + + return [l, a, b]; +}; + +convert.hsl.rgb = function (hsl) { + const h = hsl[0] / 360; + const s = hsl[1] / 100; + const l = hsl[2] / 100; + let t2; + let t3; + let val; + + if (s === 0) { + val = l * 255; + return [val, val, val]; + } + + if (l < 0.5) { + t2 = l * (1 + s); + } else { + t2 = l + s - l * s; + } + + const t1 = 2 * l - t2; + + const rgb = [0, 0, 0]; + for (let i = 0; i < 3; i++) { + t3 = h + 1 / 3 * -(i - 1); + if (t3 < 0) { + t3++; + } + + if (t3 > 1) { + t3--; + } + + if (6 * t3 < 1) { + val = t1 + (t2 - t1) * 6 * t3; + } else if (2 * t3 < 1) { + val = t2; + } else if (3 * t3 < 2) { + val = t1 + (t2 - t1) * (2 / 3 - t3) * 6; + } else { + val = t1; + } + + rgb[i] = val * 255; + } + + return rgb; +}; + +convert.hsl.hsv = function (hsl) { + const h = hsl[0]; + let s = hsl[1] / 100; + let l = hsl[2] / 100; + let smin = s; + const lmin = Math.max(l, 0.01); + + l *= 2; + s *= (l <= 1) ? l : 2 - l; + smin *= lmin <= 1 ? lmin : 2 - lmin; + const v = (l + s) / 2; + const sv = l === 0 ? (2 * smin) / (lmin + smin) : (2 * s) / (l + s); + + return [h, sv * 100, v * 100]; +}; + +convert.hsv.rgb = function (hsv) { + const h = hsv[0] / 60; + const s = hsv[1] / 100; + let v = hsv[2] / 100; + const hi = Math.floor(h) % 6; + + const f = h - Math.floor(h); + const p = 255 * v * (1 - s); + const q = 255 * v * (1 - (s * f)); + const t = 255 * v * (1 - (s * (1 - f))); + v *= 255; + + switch (hi) { + case 0: + return [v, t, p]; + case 1: + return [q, v, p]; + case 2: + return [p, v, t]; + case 3: + return [p, q, v]; + case 4: + return [t, p, v]; + case 5: + return [v, p, q]; + } +}; + +convert.hsv.hsl = function (hsv) { + const h = hsv[0]; + const s = hsv[1] / 100; + const v = hsv[2] / 100; + const vmin = Math.max(v, 0.01); + let sl; + let l; + + l = (2 - s) * v; + const lmin = (2 - s) * vmin; + sl = s * vmin; + sl /= (lmin <= 1) ? lmin : 2 - lmin; + sl = sl || 0; + l /= 2; + + return [h, sl * 100, l * 100]; +}; + +// http://dev.w3.org/csswg/css-color/#hwb-to-rgb +convert.hwb.rgb = function (hwb) { + const h = hwb[0] / 360; + let wh = hwb[1] / 100; + let bl = hwb[2] / 100; + const ratio = wh + bl; + let f; + + // Wh + bl cant be > 1 + if (ratio > 1) { + wh /= ratio; + bl /= ratio; + } + + const i = Math.floor(6 * h); + const v = 1 - bl; + f = 6 * h - i; + + if ((i & 0x01) !== 0) { + f = 1 - f; + } + + const n = wh + f * (v - wh); // Linear interpolation + + let r; + let g; + let b; + /* eslint-disable max-statements-per-line,no-multi-spaces */ + switch (i) { + default: + case 6: + case 0: r = v; g = n; b = wh; break; + case 1: r = n; g = v; b = wh; break; + case 2: r = wh; g = v; b = n; break; + case 3: r = wh; g = n; b = v; break; + case 4: r = n; g = wh; b = v; break; + case 5: r = v; g = wh; b = n; break; + } + /* eslint-enable max-statements-per-line,no-multi-spaces */ + + return [r * 255, g * 255, b * 255]; +}; + +convert.cmyk.rgb = function (cmyk) { + const c = cmyk[0] / 100; + const m = cmyk[1] / 100; + const y = cmyk[2] / 100; + const k = cmyk[3] / 100; + + const r = 1 - Math.min(1, c * (1 - k) + k); + const g = 1 - Math.min(1, m * (1 - k) + k); + const b = 1 - Math.min(1, y * (1 - k) + k); + + return [r * 255, g * 255, b * 255]; +}; + +convert.xyz.rgb = function (xyz) { + const x = xyz[0] / 100; + const y = xyz[1] / 100; + const z = xyz[2] / 100; + let r; + let g; + let b; + + r = (x * 3.2406) + (y * -1.5372) + (z * -0.4986); + g = (x * -0.9689) + (y * 1.8758) + (z * 0.0415); + b = (x * 0.0557) + (y * -0.2040) + (z * 1.0570); + + // Assume sRGB + r = r > 0.0031308 + ? ((1.055 * (r ** (1.0 / 2.4))) - 0.055) + : r * 12.92; + + g = g > 0.0031308 + ? ((1.055 * (g ** (1.0 / 2.4))) - 0.055) + : g * 12.92; + + b = b > 0.0031308 + ? ((1.055 * (b ** (1.0 / 2.4))) - 0.055) + : b * 12.92; + + r = Math.min(Math.max(0, r), 1); + g = Math.min(Math.max(0, g), 1); + b = Math.min(Math.max(0, b), 1); + + return [r * 255, g * 255, b * 255]; +}; + +convert.xyz.lab = function (xyz) { + let x = xyz[0]; + let y = xyz[1]; + let z = xyz[2]; + + x /= 95.047; + y /= 100; + z /= 108.883; + + x = x > 0.008856 ? (x ** (1 / 3)) : (7.787 * x) + (16 / 116); + y = y > 0.008856 ? (y ** (1 / 3)) : (7.787 * y) + (16 / 116); + z = z > 0.008856 ? (z ** (1 / 3)) : (7.787 * z) + (16 / 116); + + const l = (116 * y) - 16; + const a = 500 * (x - y); + const b = 200 * (y - z); + + return [l, a, b]; +}; + +convert.lab.xyz = function (lab) { + const l = lab[0]; + const a = lab[1]; + const b = lab[2]; + let x; + let y; + let z; + + y = (l + 16) / 116; + x = a / 500 + y; + z = y - b / 200; + + const y2 = y ** 3; + const x2 = x ** 3; + const z2 = z ** 3; + y = y2 > 0.008856 ? y2 : (y - 16 / 116) / 7.787; + x = x2 > 0.008856 ? x2 : (x - 16 / 116) / 7.787; + z = z2 > 0.008856 ? z2 : (z - 16 / 116) / 7.787; + + x *= 95.047; + y *= 100; + z *= 108.883; + + return [x, y, z]; +}; + +convert.lab.lch = function (lab) { + const l = lab[0]; + const a = lab[1]; + const b = lab[2]; + let h; + + const hr = Math.atan2(b, a); + h = hr * 360 / 2 / Math.PI; + + if (h < 0) { + h += 360; + } + + const c = Math.sqrt(a * a + b * b); + + return [l, c, h]; +}; + +convert.lch.lab = function (lch) { + const l = lch[0]; + const c = lch[1]; + const h = lch[2]; + + const hr = h / 360 * 2 * Math.PI; + const a = c * Math.cos(hr); + const b = c * Math.sin(hr); + + return [l, a, b]; +}; + +convert.rgb.ansi16 = function (args, saturation = null) { + const [r, g, b] = args; + let value = saturation === null ? convert.rgb.hsv(args)[2] : saturation; // Hsv -> ansi16 optimization + + value = Math.round(value / 50); + + if (value === 0) { + return 30; + } + + let ansi = 30 + + ((Math.round(b / 255) << 2) + | (Math.round(g / 255) << 1) + | Math.round(r / 255)); + + if (value === 2) { + ansi += 60; + } + + return ansi; +}; + +convert.hsv.ansi16 = function (args) { + // Optimization here; we already know the value and don't need to get + // it converted for us. + return convert.rgb.ansi16(convert.hsv.rgb(args), args[2]); +}; + +convert.rgb.ansi256 = function (args) { + const r = args[0]; + const g = args[1]; + const b = args[2]; + + // We use the extended greyscale palette here, with the exception of + // black and white. normal palette only has 4 greyscale shades. + if (r === g && g === b) { + if (r < 8) { + return 16; + } + + if (r > 248) { + return 231; + } + + return Math.round(((r - 8) / 247) * 24) + 232; + } + + const ansi = 16 + + (36 * Math.round(r / 255 * 5)) + + (6 * Math.round(g / 255 * 5)) + + Math.round(b / 255 * 5); + + return ansi; +}; + +convert.ansi16.rgb = function (args) { + let color = args % 10; + + // Handle greyscale + if (color === 0 || color === 7) { + if (args > 50) { + color += 3.5; + } + + color = color / 10.5 * 255; + + return [color, color, color]; + } + + const mult = (~~(args > 50) + 1) * 0.5; + const r = ((color & 1) * mult) * 255; + const g = (((color >> 1) & 1) * mult) * 255; + const b = (((color >> 2) & 1) * mult) * 255; + + return [r, g, b]; +}; + +convert.ansi256.rgb = function (args) { + // Handle greyscale + if (args >= 232) { + const c = (args - 232) * 10 + 8; + return [c, c, c]; + } + + args -= 16; + + let rem; + const r = Math.floor(args / 36) / 5 * 255; + const g = Math.floor((rem = args % 36) / 6) / 5 * 255; + const b = (rem % 6) / 5 * 255; + + return [r, g, b]; +}; + +convert.rgb.hex = function (args) { + const integer = ((Math.round(args[0]) & 0xFF) << 16) + + ((Math.round(args[1]) & 0xFF) << 8) + + (Math.round(args[2]) & 0xFF); + + const string = integer.toString(16).toUpperCase(); + return '000000'.substring(string.length) + string; +}; + +convert.hex.rgb = function (args) { + const match = args.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i); + if (!match) { + return [0, 0, 0]; + } + + let colorString = match[0]; + + if (match[0].length === 3) { + colorString = colorString.split('').map(char => { + return char + char; + }).join(''); + } + + const integer = parseInt(colorString, 16); + const r = (integer >> 16) & 0xFF; + const g = (integer >> 8) & 0xFF; + const b = integer & 0xFF; + + return [r, g, b]; +}; + +convert.rgb.hcg = function (rgb) { + const r = rgb[0] / 255; + const g = rgb[1] / 255; + const b = rgb[2] / 255; + const max = Math.max(Math.max(r, g), b); + const min = Math.min(Math.min(r, g), b); + const chroma = (max - min); + let grayscale; + let hue; + + if (chroma < 1) { + grayscale = min / (1 - chroma); + } else { + grayscale = 0; + } + + if (chroma <= 0) { + hue = 0; + } else + if (max === r) { + hue = ((g - b) / chroma) % 6; + } else + if (max === g) { + hue = 2 + (b - r) / chroma; + } else { + hue = 4 + (r - g) / chroma; + } + + hue /= 6; + hue %= 1; + + return [hue * 360, chroma * 100, grayscale * 100]; +}; + +convert.hsl.hcg = function (hsl) { + const s = hsl[1] / 100; + const l = hsl[2] / 100; + + const c = l < 0.5 ? (2.0 * s * l) : (2.0 * s * (1.0 - l)); + + let f = 0; + if (c < 1.0) { + f = (l - 0.5 * c) / (1.0 - c); + } + + return [hsl[0], c * 100, f * 100]; +}; + +convert.hsv.hcg = function (hsv) { + const s = hsv[1] / 100; + const v = hsv[2] / 100; + + const c = s * v; + let f = 0; + + if (c < 1.0) { + f = (v - c) / (1 - c); + } + + return [hsv[0], c * 100, f * 100]; +}; + +convert.hcg.rgb = function (hcg) { + const h = hcg[0] / 360; + const c = hcg[1] / 100; + const g = hcg[2] / 100; + + if (c === 0.0) { + return [g * 255, g * 255, g * 255]; + } + + const pure = [0, 0, 0]; + const hi = (h % 1) * 6; + const v = hi % 1; + const w = 1 - v; + let mg = 0; + + /* eslint-disable max-statements-per-line */ + switch (Math.floor(hi)) { + case 0: + pure[0] = 1; pure[1] = v; pure[2] = 0; break; + case 1: + pure[0] = w; pure[1] = 1; pure[2] = 0; break; + case 2: + pure[0] = 0; pure[1] = 1; pure[2] = v; break; + case 3: + pure[0] = 0; pure[1] = w; pure[2] = 1; break; + case 4: + pure[0] = v; pure[1] = 0; pure[2] = 1; break; + default: + pure[0] = 1; pure[1] = 0; pure[2] = w; + } + /* eslint-enable max-statements-per-line */ + + mg = (1.0 - c) * g; + + return [ + (c * pure[0] + mg) * 255, + (c * pure[1] + mg) * 255, + (c * pure[2] + mg) * 255 + ]; +}; + +convert.hcg.hsv = function (hcg) { + const c = hcg[1] / 100; + const g = hcg[2] / 100; + + const v = c + g * (1.0 - c); + let f = 0; + + if (v > 0.0) { + f = c / v; + } + + return [hcg[0], f * 100, v * 100]; +}; + +convert.hcg.hsl = function (hcg) { + const c = hcg[1] / 100; + const g = hcg[2] / 100; + + const l = g * (1.0 - c) + 0.5 * c; + let s = 0; + + if (l > 0.0 && l < 0.5) { + s = c / (2 * l); + } else + if (l >= 0.5 && l < 1.0) { + s = c / (2 * (1 - l)); + } + + return [hcg[0], s * 100, l * 100]; +}; + +convert.hcg.hwb = function (hcg) { + const c = hcg[1] / 100; + const g = hcg[2] / 100; + const v = c + g * (1.0 - c); + return [hcg[0], (v - c) * 100, (1 - v) * 100]; +}; + +convert.hwb.hcg = function (hwb) { + const w = hwb[1] / 100; + const b = hwb[2] / 100; + const v = 1 - b; + const c = v - w; + let g = 0; + + if (c < 1) { + g = (v - c) / (1 - c); + } + + return [hwb[0], c * 100, g * 100]; +}; + +convert.apple.rgb = function (apple) { + return [(apple[0] / 65535) * 255, (apple[1] / 65535) * 255, (apple[2] / 65535) * 255]; +}; + +convert.rgb.apple = function (rgb) { + return [(rgb[0] / 255) * 65535, (rgb[1] / 255) * 65535, (rgb[2] / 255) * 65535]; +}; + +convert.gray.rgb = function (args) { + return [args[0] / 100 * 255, args[0] / 100 * 255, args[0] / 100 * 255]; +}; + +convert.gray.hsl = function (args) { + return [0, 0, args[0]]; +}; + +convert.gray.hsv = convert.gray.hsl; + +convert.gray.hwb = function (gray) { + return [0, 100, gray[0]]; +}; + +convert.gray.cmyk = function (gray) { + return [0, 0, 0, gray[0]]; +}; + +convert.gray.lab = function (gray) { + return [gray[0], 0, 0]; +}; + +convert.gray.hex = function (gray) { + const val = Math.round(gray[0] / 100 * 255) & 0xFF; + const integer = (val << 16) + (val << 8) + val; + + const string = integer.toString(16).toUpperCase(); + return '000000'.substring(string.length) + string; +}; + +convert.rgb.gray = function (rgb) { + const val = (rgb[0] + rgb[1] + rgb[2]) / 3; + return [val / 255 * 100]; +}; diff --git a/server/node_modules/color-convert/index.js b/server/node_modules/color-convert/index.js new file mode 100644 index 0000000..b648e57 --- /dev/null +++ b/server/node_modules/color-convert/index.js @@ -0,0 +1,81 @@ +const conversions = require('./conversions'); +const route = require('./route'); + +const convert = {}; + +const models = Object.keys(conversions); + +function wrapRaw(fn) { + const wrappedFn = function (...args) { + const arg0 = args[0]; + if (arg0 === undefined || arg0 === null) { + return arg0; + } + + if (arg0.length > 1) { + args = arg0; + } + + return fn(args); + }; + + // Preserve .conversion property if there is one + if ('conversion' in fn) { + wrappedFn.conversion = fn.conversion; + } + + return wrappedFn; +} + +function wrapRounded(fn) { + const wrappedFn = function (...args) { + const arg0 = args[0]; + + if (arg0 === undefined || arg0 === null) { + return arg0; + } + + if (arg0.length > 1) { + args = arg0; + } + + const result = fn(args); + + // We're assuming the result is an array here. + // see notice in conversions.js; don't use box types + // in conversion functions. + if (typeof result === 'object') { + for (let len = result.length, i = 0; i < len; i++) { + result[i] = Math.round(result[i]); + } + } + + return result; + }; + + // Preserve .conversion property if there is one + if ('conversion' in fn) { + wrappedFn.conversion = fn.conversion; + } + + return wrappedFn; +} + +models.forEach(fromModel => { + convert[fromModel] = {}; + + Object.defineProperty(convert[fromModel], 'channels', {value: conversions[fromModel].channels}); + Object.defineProperty(convert[fromModel], 'labels', {value: conversions[fromModel].labels}); + + const routes = route(fromModel); + const routeModels = Object.keys(routes); + + routeModels.forEach(toModel => { + const fn = routes[toModel]; + + convert[fromModel][toModel] = wrapRounded(fn); + convert[fromModel][toModel].raw = wrapRaw(fn); + }); +}); + +module.exports = convert; diff --git a/server/node_modules/color-convert/package.json b/server/node_modules/color-convert/package.json new file mode 100644 index 0000000..6e48000 --- /dev/null +++ b/server/node_modules/color-convert/package.json @@ -0,0 +1,48 @@ +{ + "name": "color-convert", + "description": "Plain color conversion functions", + "version": "2.0.1", + "author": "Heather Arthur ", + "license": "MIT", + "repository": "Qix-/color-convert", + "scripts": { + "pretest": "xo", + "test": "node test/basic.js" + }, + "engines": { + "node": ">=7.0.0" + }, + "keywords": [ + "color", + "colour", + "convert", + "converter", + "conversion", + "rgb", + "hsl", + "hsv", + "hwb", + "cmyk", + "ansi", + "ansi16" + ], + "files": [ + "index.js", + "conversions.js", + "route.js" + ], + "xo": { + "rules": { + "default-case": 0, + "no-inline-comments": 0, + "operator-linebreak": 0 + } + }, + "devDependencies": { + "chalk": "^2.4.2", + "xo": "^0.24.0" + }, + "dependencies": { + "color-name": "~1.1.4" + } +} diff --git a/server/node_modules/color-convert/route.js b/server/node_modules/color-convert/route.js new file mode 100644 index 0000000..1a08521 --- /dev/null +++ b/server/node_modules/color-convert/route.js @@ -0,0 +1,97 @@ +const conversions = require('./conversions'); + +/* + This function routes a model to all other models. + + all functions that are routed have a property `.conversion` attached + to the returned synthetic function. This property is an array + of strings, each with the steps in between the 'from' and 'to' + color models (inclusive). + + conversions that are not possible simply are not included. +*/ + +function buildGraph() { + const graph = {}; + // https://jsperf.com/object-keys-vs-for-in-with-closure/3 + const models = Object.keys(conversions); + + for (let len = models.length, i = 0; i < len; i++) { + graph[models[i]] = { + // http://jsperf.com/1-vs-infinity + // micro-opt, but this is simple. + distance: -1, + parent: null + }; + } + + return graph; +} + +// https://en.wikipedia.org/wiki/Breadth-first_search +function deriveBFS(fromModel) { + const graph = buildGraph(); + const queue = [fromModel]; // Unshift -> queue -> pop + + graph[fromModel].distance = 0; + + while (queue.length) { + const current = queue.pop(); + const adjacents = Object.keys(conversions[current]); + + for (let len = adjacents.length, i = 0; i < len; i++) { + const adjacent = adjacents[i]; + const node = graph[adjacent]; + + if (node.distance === -1) { + node.distance = graph[current].distance + 1; + node.parent = current; + queue.unshift(adjacent); + } + } + } + + return graph; +} + +function link(from, to) { + return function (args) { + return to(from(args)); + }; +} + +function wrapConversion(toModel, graph) { + const path = [graph[toModel].parent, toModel]; + let fn = conversions[graph[toModel].parent][toModel]; + + let cur = graph[toModel].parent; + while (graph[cur].parent) { + path.unshift(graph[cur].parent); + fn = link(conversions[graph[cur].parent][cur], fn); + cur = graph[cur].parent; + } + + fn.conversion = path; + return fn; +} + +module.exports = function (fromModel) { + const graph = deriveBFS(fromModel); + const conversion = {}; + + const models = Object.keys(graph); + for (let len = models.length, i = 0; i < len; i++) { + const toModel = models[i]; + const node = graph[toModel]; + + if (node.parent === null) { + // No possible conversion, or this node is the source model. + continue; + } + + conversion[toModel] = wrapConversion(toModel, graph); + } + + return conversion; +}; + diff --git a/server/node_modules/color-name/LICENSE b/server/node_modules/color-name/LICENSE new file mode 100644 index 0000000..c6b1001 --- /dev/null +++ b/server/node_modules/color-name/LICENSE @@ -0,0 +1,8 @@ +The MIT License (MIT) +Copyright (c) 2015 Dmitry Ivanov + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/server/node_modules/color-name/README.md b/server/node_modules/color-name/README.md new file mode 100644 index 0000000..932b979 --- /dev/null +++ b/server/node_modules/color-name/README.md @@ -0,0 +1,11 @@ +A JSON with color names and its values. Based on http://dev.w3.org/csswg/css-color/#named-colors. + +[![NPM](https://nodei.co/npm/color-name.png?mini=true)](https://nodei.co/npm/color-name/) + + +```js +var colors = require('color-name'); +colors.red //[255,0,0] +``` + + diff --git a/server/node_modules/color-name/index.js b/server/node_modules/color-name/index.js new file mode 100644 index 0000000..b7c198a --- /dev/null +++ b/server/node_modules/color-name/index.js @@ -0,0 +1,152 @@ +'use strict' + +module.exports = { + "aliceblue": [240, 248, 255], + "antiquewhite": [250, 235, 215], + "aqua": [0, 255, 255], + "aquamarine": [127, 255, 212], + "azure": [240, 255, 255], + "beige": [245, 245, 220], + "bisque": [255, 228, 196], + "black": [0, 0, 0], + "blanchedalmond": [255, 235, 205], + "blue": [0, 0, 255], + "blueviolet": [138, 43, 226], + "brown": [165, 42, 42], + "burlywood": [222, 184, 135], + "cadetblue": [95, 158, 160], + "chartreuse": [127, 255, 0], + "chocolate": [210, 105, 30], + "coral": [255, 127, 80], + "cornflowerblue": [100, 149, 237], + "cornsilk": [255, 248, 220], + "crimson": [220, 20, 60], + "cyan": [0, 255, 255], + "darkblue": [0, 0, 139], + "darkcyan": [0, 139, 139], + "darkgoldenrod": [184, 134, 11], + "darkgray": [169, 169, 169], + "darkgreen": [0, 100, 0], + "darkgrey": [169, 169, 169], + "darkkhaki": [189, 183, 107], + "darkmagenta": [139, 0, 139], + "darkolivegreen": [85, 107, 47], + "darkorange": [255, 140, 0], + "darkorchid": [153, 50, 204], + "darkred": [139, 0, 0], + "darksalmon": [233, 150, 122], + "darkseagreen": [143, 188, 143], + "darkslateblue": [72, 61, 139], + "darkslategray": [47, 79, 79], + "darkslategrey": [47, 79, 79], + "darkturquoise": [0, 206, 209], + "darkviolet": [148, 0, 211], + "deeppink": [255, 20, 147], + "deepskyblue": [0, 191, 255], + "dimgray": [105, 105, 105], + "dimgrey": [105, 105, 105], + "dodgerblue": [30, 144, 255], + "firebrick": [178, 34, 34], + "floralwhite": [255, 250, 240], + "forestgreen": [34, 139, 34], + "fuchsia": [255, 0, 255], + "gainsboro": [220, 220, 220], + "ghostwhite": [248, 248, 255], + "gold": [255, 215, 0], + "goldenrod": [218, 165, 32], + "gray": [128, 128, 128], + "green": [0, 128, 0], + "greenyellow": [173, 255, 47], + "grey": [128, 128, 128], + "honeydew": [240, 255, 240], + "hotpink": [255, 105, 180], + "indianred": [205, 92, 92], + "indigo": [75, 0, 130], + "ivory": [255, 255, 240], + "khaki": [240, 230, 140], + "lavender": [230, 230, 250], + "lavenderblush": [255, 240, 245], + "lawngreen": [124, 252, 0], + "lemonchiffon": [255, 250, 205], + "lightblue": [173, 216, 230], + "lightcoral": [240, 128, 128], + "lightcyan": [224, 255, 255], + "lightgoldenrodyellow": [250, 250, 210], + "lightgray": [211, 211, 211], + "lightgreen": [144, 238, 144], + "lightgrey": [211, 211, 211], + "lightpink": [255, 182, 193], + "lightsalmon": [255, 160, 122], + "lightseagreen": [32, 178, 170], + "lightskyblue": [135, 206, 250], + "lightslategray": [119, 136, 153], + "lightslategrey": [119, 136, 153], + "lightsteelblue": [176, 196, 222], + "lightyellow": [255, 255, 224], + "lime": [0, 255, 0], + "limegreen": [50, 205, 50], + "linen": [250, 240, 230], + "magenta": [255, 0, 255], + "maroon": [128, 0, 0], + "mediumaquamarine": [102, 205, 170], + "mediumblue": [0, 0, 205], + "mediumorchid": [186, 85, 211], + "mediumpurple": [147, 112, 219], + "mediumseagreen": [60, 179, 113], + "mediumslateblue": [123, 104, 238], + "mediumspringgreen": [0, 250, 154], + "mediumturquoise": [72, 209, 204], + "mediumvioletred": [199, 21, 133], + "midnightblue": [25, 25, 112], + "mintcream": [245, 255, 250], + "mistyrose": [255, 228, 225], + "moccasin": [255, 228, 181], + "navajowhite": [255, 222, 173], + "navy": [0, 0, 128], + "oldlace": [253, 245, 230], + "olive": [128, 128, 0], + "olivedrab": [107, 142, 35], + "orange": [255, 165, 0], + "orangered": [255, 69, 0], + "orchid": [218, 112, 214], + "palegoldenrod": [238, 232, 170], + "palegreen": [152, 251, 152], + "paleturquoise": [175, 238, 238], + "palevioletred": [219, 112, 147], + "papayawhip": [255, 239, 213], + "peachpuff": [255, 218, 185], + "peru": [205, 133, 63], + "pink": [255, 192, 203], + "plum": [221, 160, 221], + "powderblue": [176, 224, 230], + "purple": [128, 0, 128], + "rebeccapurple": [102, 51, 153], + "red": [255, 0, 0], + "rosybrown": [188, 143, 143], + "royalblue": [65, 105, 225], + "saddlebrown": [139, 69, 19], + "salmon": [250, 128, 114], + "sandybrown": [244, 164, 96], + "seagreen": [46, 139, 87], + "seashell": [255, 245, 238], + "sienna": [160, 82, 45], + "silver": [192, 192, 192], + "skyblue": [135, 206, 235], + "slateblue": [106, 90, 205], + "slategray": [112, 128, 144], + "slategrey": [112, 128, 144], + "snow": [255, 250, 250], + "springgreen": [0, 255, 127], + "steelblue": [70, 130, 180], + "tan": [210, 180, 140], + "teal": [0, 128, 128], + "thistle": [216, 191, 216], + "tomato": [255, 99, 71], + "turquoise": [64, 224, 208], + "violet": [238, 130, 238], + "wheat": [245, 222, 179], + "white": [255, 255, 255], + "whitesmoke": [245, 245, 245], + "yellow": [255, 255, 0], + "yellowgreen": [154, 205, 50] +}; diff --git a/server/node_modules/color-name/package.json b/server/node_modules/color-name/package.json new file mode 100644 index 0000000..782dd82 --- /dev/null +++ b/server/node_modules/color-name/package.json @@ -0,0 +1,28 @@ +{ + "name": "color-name", + "version": "1.1.4", + "description": "A list of color names and its values", + "main": "index.js", + "files": [ + "index.js" + ], + "scripts": { + "test": "node test.js" + }, + "repository": { + "type": "git", + "url": "git@github.com:colorjs/color-name.git" + }, + "keywords": [ + "color-name", + "color", + "color-keyword", + "keyword" + ], + "author": "DY ", + "license": "MIT", + "bugs": { + "url": "https://github.com/colorjs/color-name/issues" + }, + "homepage": "https://github.com/colorjs/color-name" +} diff --git a/server/node_modules/content-disposition/HISTORY.md b/server/node_modules/content-disposition/HISTORY.md new file mode 100644 index 0000000..488effa --- /dev/null +++ b/server/node_modules/content-disposition/HISTORY.md @@ -0,0 +1,60 @@ +0.5.4 / 2021-12-10 +================== + + * deps: safe-buffer@5.2.1 + +0.5.3 / 2018-12-17 +================== + + * Use `safe-buffer` for improved Buffer API + +0.5.2 / 2016-12-08 +================== + + * Fix `parse` to accept any linear whitespace character + +0.5.1 / 2016-01-17 +================== + + * perf: enable strict mode + +0.5.0 / 2014-10-11 +================== + + * Add `parse` function + +0.4.0 / 2014-09-21 +================== + + * Expand non-Unicode `filename` to the full ISO-8859-1 charset + +0.3.0 / 2014-09-20 +================== + + * Add `fallback` option + * Add `type` option + +0.2.0 / 2014-09-19 +================== + + * Reduce ambiguity of file names with hex escape in buggy browsers + +0.1.2 / 2014-09-19 +================== + + * Fix periodic invalid Unicode filename header + +0.1.1 / 2014-09-19 +================== + + * Fix invalid characters appearing in `filename*` parameter + +0.1.0 / 2014-09-18 +================== + + * Make the `filename` argument optional + +0.0.0 / 2014-09-18 +================== + + * Initial release diff --git a/server/node_modules/content-disposition/LICENSE b/server/node_modules/content-disposition/LICENSE new file mode 100644 index 0000000..84441fb --- /dev/null +++ b/server/node_modules/content-disposition/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2014-2017 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/server/node_modules/content-disposition/README.md b/server/node_modules/content-disposition/README.md new file mode 100644 index 0000000..3a0bb05 --- /dev/null +++ b/server/node_modules/content-disposition/README.md @@ -0,0 +1,142 @@ +# content-disposition + +[![NPM Version][npm-image]][npm-url] +[![NPM Downloads][downloads-image]][downloads-url] +[![Node.js Version][node-version-image]][node-version-url] +[![Build Status][github-actions-ci-image]][github-actions-ci-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +Create and parse HTTP `Content-Disposition` header + +## Installation + +```sh +$ npm install content-disposition +``` + +## API + +```js +var contentDisposition = require('content-disposition') +``` + +### contentDisposition(filename, options) + +Create an attachment `Content-Disposition` header value using the given file name, +if supplied. The `filename` is optional and if no file name is desired, but you +want to specify `options`, set `filename` to `undefined`. + +```js +res.setHeader('Content-Disposition', contentDisposition('∫ maths.pdf')) +``` + +**note** HTTP headers are of the ISO-8859-1 character set. If you are writing this +header through a means different from `setHeader` in Node.js, you'll want to specify +the `'binary'` encoding in Node.js. + +#### Options + +`contentDisposition` accepts these properties in the options object. + +##### fallback + +If the `filename` option is outside ISO-8859-1, then the file name is actually +stored in a supplemental field for clients that support Unicode file names and +a ISO-8859-1 version of the file name is automatically generated. + +This specifies the ISO-8859-1 file name to override the automatic generation or +disables the generation all together, defaults to `true`. + + - A string will specify the ISO-8859-1 file name to use in place of automatic + generation. + - `false` will disable including a ISO-8859-1 file name and only include the + Unicode version (unless the file name is already ISO-8859-1). + - `true` will enable automatic generation if the file name is outside ISO-8859-1. + +If the `filename` option is ISO-8859-1 and this option is specified and has a +different value, then the `filename` option is encoded in the extended field +and this set as the fallback field, even though they are both ISO-8859-1. + +##### type + +Specifies the disposition type, defaults to `"attachment"`. This can also be +`"inline"`, or any other value (all values except inline are treated like +`attachment`, but can convey additional information if both parties agree to +it). The type is normalized to lower-case. + +### contentDisposition.parse(string) + +```js +var disposition = contentDisposition.parse('attachment; filename="EURO rates.txt"; filename*=UTF-8\'\'%e2%82%ac%20rates.txt') +``` + +Parse a `Content-Disposition` header string. This automatically handles extended +("Unicode") parameters by decoding them and providing them under the standard +parameter name. This will return an object with the following properties (examples +are shown for the string `'attachment; filename="EURO rates.txt"; filename*=UTF-8\'\'%e2%82%ac%20rates.txt'`): + + - `type`: The disposition type (always lower case). Example: `'attachment'` + + - `parameters`: An object of the parameters in the disposition (name of parameter + always lower case and extended versions replace non-extended versions). Example: + `{filename: "€ rates.txt"}` + +## Examples + +### Send a file for download + +```js +var contentDisposition = require('content-disposition') +var destroy = require('destroy') +var fs = require('fs') +var http = require('http') +var onFinished = require('on-finished') + +var filePath = '/path/to/public/plans.pdf' + +http.createServer(function onRequest (req, res) { + // set headers + res.setHeader('Content-Type', 'application/pdf') + res.setHeader('Content-Disposition', contentDisposition(filePath)) + + // send file + var stream = fs.createReadStream(filePath) + stream.pipe(res) + onFinished(res, function () { + destroy(stream) + }) +}) +``` + +## Testing + +```sh +$ npm test +``` + +## References + +- [RFC 2616: Hypertext Transfer Protocol -- HTTP/1.1][rfc-2616] +- [RFC 5987: Character Set and Language Encoding for Hypertext Transfer Protocol (HTTP) Header Field Parameters][rfc-5987] +- [RFC 6266: Use of the Content-Disposition Header Field in the Hypertext Transfer Protocol (HTTP)][rfc-6266] +- [Test Cases for HTTP Content-Disposition header field (RFC 6266) and the Encodings defined in RFCs 2047, 2231 and 5987][tc-2231] + +[rfc-2616]: https://tools.ietf.org/html/rfc2616 +[rfc-5987]: https://tools.ietf.org/html/rfc5987 +[rfc-6266]: https://tools.ietf.org/html/rfc6266 +[tc-2231]: http://greenbytes.de/tech/tc2231/ + +## License + +[MIT](LICENSE) + +[npm-image]: https://img.shields.io/npm/v/content-disposition.svg +[npm-url]: https://npmjs.org/package/content-disposition +[node-version-image]: https://img.shields.io/node/v/content-disposition.svg +[node-version-url]: https://nodejs.org/en/download +[coveralls-image]: https://img.shields.io/coveralls/jshttp/content-disposition.svg +[coveralls-url]: https://coveralls.io/r/jshttp/content-disposition?branch=master +[downloads-image]: https://img.shields.io/npm/dm/content-disposition.svg +[downloads-url]: https://npmjs.org/package/content-disposition +[github-actions-ci-image]: https://img.shields.io/github/workflow/status/jshttp/content-disposition/ci/master?label=ci +[github-actions-ci-url]: https://github.com/jshttp/content-disposition?query=workflow%3Aci diff --git a/server/node_modules/content-disposition/index.js b/server/node_modules/content-disposition/index.js new file mode 100644 index 0000000..ecec899 --- /dev/null +++ b/server/node_modules/content-disposition/index.js @@ -0,0 +1,458 @@ +/*! + * content-disposition + * Copyright(c) 2014-2017 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module exports. + * @public + */ + +module.exports = contentDisposition +module.exports.parse = parse + +/** + * Module dependencies. + * @private + */ + +var basename = require('path').basename +var Buffer = require('safe-buffer').Buffer + +/** + * RegExp to match non attr-char, *after* encodeURIComponent (i.e. not including "%") + * @private + */ + +var ENCODE_URL_ATTR_CHAR_REGEXP = /[\x00-\x20"'()*,/:;<=>?@[\\\]{}\x7f]/g // eslint-disable-line no-control-regex + +/** + * RegExp to match percent encoding escape. + * @private + */ + +var HEX_ESCAPE_REGEXP = /%[0-9A-Fa-f]{2}/ +var HEX_ESCAPE_REPLACE_REGEXP = /%([0-9A-Fa-f]{2})/g + +/** + * RegExp to match non-latin1 characters. + * @private + */ + +var NON_LATIN1_REGEXP = /[^\x20-\x7e\xa0-\xff]/g + +/** + * RegExp to match quoted-pair in RFC 2616 + * + * quoted-pair = "\" CHAR + * CHAR = + * @private + */ + +var QESC_REGEXP = /\\([\u0000-\u007f])/g // eslint-disable-line no-control-regex + +/** + * RegExp to match chars that must be quoted-pair in RFC 2616 + * @private + */ + +var QUOTE_REGEXP = /([\\"])/g + +/** + * RegExp for various RFC 2616 grammar + * + * parameter = token "=" ( token | quoted-string ) + * token = 1* + * separators = "(" | ")" | "<" | ">" | "@" + * | "," | ";" | ":" | "\" | <"> + * | "/" | "[" | "]" | "?" | "=" + * | "{" | "}" | SP | HT + * quoted-string = ( <"> *(qdtext | quoted-pair ) <"> ) + * qdtext = > + * quoted-pair = "\" CHAR + * CHAR = + * TEXT = + * LWS = [CRLF] 1*( SP | HT ) + * CRLF = CR LF + * CR = + * LF = + * SP = + * HT = + * CTL = + * OCTET = + * @private + */ + +var PARAM_REGEXP = /;[\x09\x20]*([!#$%&'*+.0-9A-Z^_`a-z|~-]+)[\x09\x20]*=[\x09\x20]*("(?:[\x20!\x23-\x5b\x5d-\x7e\x80-\xff]|\\[\x20-\x7e])*"|[!#$%&'*+.0-9A-Z^_`a-z|~-]+)[\x09\x20]*/g // eslint-disable-line no-control-regex +var TEXT_REGEXP = /^[\x20-\x7e\x80-\xff]+$/ +var TOKEN_REGEXP = /^[!#$%&'*+.0-9A-Z^_`a-z|~-]+$/ + +/** + * RegExp for various RFC 5987 grammar + * + * ext-value = charset "'" [ language ] "'" value-chars + * charset = "UTF-8" / "ISO-8859-1" / mime-charset + * mime-charset = 1*mime-charsetc + * mime-charsetc = ALPHA / DIGIT + * / "!" / "#" / "$" / "%" / "&" + * / "+" / "-" / "^" / "_" / "`" + * / "{" / "}" / "~" + * language = ( 2*3ALPHA [ extlang ] ) + * / 4ALPHA + * / 5*8ALPHA + * extlang = *3( "-" 3ALPHA ) + * value-chars = *( pct-encoded / attr-char ) + * pct-encoded = "%" HEXDIG HEXDIG + * attr-char = ALPHA / DIGIT + * / "!" / "#" / "$" / "&" / "+" / "-" / "." + * / "^" / "_" / "`" / "|" / "~" + * @private + */ + +var EXT_VALUE_REGEXP = /^([A-Za-z0-9!#$%&+\-^_`{}~]+)'(?:[A-Za-z]{2,3}(?:-[A-Za-z]{3}){0,3}|[A-Za-z]{4,8}|)'((?:%[0-9A-Fa-f]{2}|[A-Za-z0-9!#$&+.^_`|~-])+)$/ + +/** + * RegExp for various RFC 6266 grammar + * + * disposition-type = "inline" | "attachment" | disp-ext-type + * disp-ext-type = token + * disposition-parm = filename-parm | disp-ext-parm + * filename-parm = "filename" "=" value + * | "filename*" "=" ext-value + * disp-ext-parm = token "=" value + * | ext-token "=" ext-value + * ext-token = + * @private + */ + +var DISPOSITION_TYPE_REGEXP = /^([!#$%&'*+.0-9A-Z^_`a-z|~-]+)[\x09\x20]*(?:$|;)/ // eslint-disable-line no-control-regex + +/** + * Create an attachment Content-Disposition header. + * + * @param {string} [filename] + * @param {object} [options] + * @param {string} [options.type=attachment] + * @param {string|boolean} [options.fallback=true] + * @return {string} + * @public + */ + +function contentDisposition (filename, options) { + var opts = options || {} + + // get type + var type = opts.type || 'attachment' + + // get parameters + var params = createparams(filename, opts.fallback) + + // format into string + return format(new ContentDisposition(type, params)) +} + +/** + * Create parameters object from filename and fallback. + * + * @param {string} [filename] + * @param {string|boolean} [fallback=true] + * @return {object} + * @private + */ + +function createparams (filename, fallback) { + if (filename === undefined) { + return + } + + var params = {} + + if (typeof filename !== 'string') { + throw new TypeError('filename must be a string') + } + + // fallback defaults to true + if (fallback === undefined) { + fallback = true + } + + if (typeof fallback !== 'string' && typeof fallback !== 'boolean') { + throw new TypeError('fallback must be a string or boolean') + } + + if (typeof fallback === 'string' && NON_LATIN1_REGEXP.test(fallback)) { + throw new TypeError('fallback must be ISO-8859-1 string') + } + + // restrict to file base name + var name = basename(filename) + + // determine if name is suitable for quoted string + var isQuotedString = TEXT_REGEXP.test(name) + + // generate fallback name + var fallbackName = typeof fallback !== 'string' + ? fallback && getlatin1(name) + : basename(fallback) + var hasFallback = typeof fallbackName === 'string' && fallbackName !== name + + // set extended filename parameter + if (hasFallback || !isQuotedString || HEX_ESCAPE_REGEXP.test(name)) { + params['filename*'] = name + } + + // set filename parameter + if (isQuotedString || hasFallback) { + params.filename = hasFallback + ? fallbackName + : name + } + + return params +} + +/** + * Format object to Content-Disposition header. + * + * @param {object} obj + * @param {string} obj.type + * @param {object} [obj.parameters] + * @return {string} + * @private + */ + +function format (obj) { + var parameters = obj.parameters + var type = obj.type + + if (!type || typeof type !== 'string' || !TOKEN_REGEXP.test(type)) { + throw new TypeError('invalid type') + } + + // start with normalized type + var string = String(type).toLowerCase() + + // append parameters + if (parameters && typeof parameters === 'object') { + var param + var params = Object.keys(parameters).sort() + + for (var i = 0; i < params.length; i++) { + param = params[i] + + var val = param.substr(-1) === '*' + ? ustring(parameters[param]) + : qstring(parameters[param]) + + string += '; ' + param + '=' + val + } + } + + return string +} + +/** + * Decode a RFC 5987 field value (gracefully). + * + * @param {string} str + * @return {string} + * @private + */ + +function decodefield (str) { + var match = EXT_VALUE_REGEXP.exec(str) + + if (!match) { + throw new TypeError('invalid extended field value') + } + + var charset = match[1].toLowerCase() + var encoded = match[2] + var value + + // to binary string + var binary = encoded.replace(HEX_ESCAPE_REPLACE_REGEXP, pdecode) + + switch (charset) { + case 'iso-8859-1': + value = getlatin1(binary) + break + case 'utf-8': + value = Buffer.from(binary, 'binary').toString('utf8') + break + default: + throw new TypeError('unsupported charset in extended field') + } + + return value +} + +/** + * Get ISO-8859-1 version of string. + * + * @param {string} val + * @return {string} + * @private + */ + +function getlatin1 (val) { + // simple Unicode -> ISO-8859-1 transformation + return String(val).replace(NON_LATIN1_REGEXP, '?') +} + +/** + * Parse Content-Disposition header string. + * + * @param {string} string + * @return {object} + * @public + */ + +function parse (string) { + if (!string || typeof string !== 'string') { + throw new TypeError('argument string is required') + } + + var match = DISPOSITION_TYPE_REGEXP.exec(string) + + if (!match) { + throw new TypeError('invalid type format') + } + + // normalize type + var index = match[0].length + var type = match[1].toLowerCase() + + var key + var names = [] + var params = {} + var value + + // calculate index to start at + index = PARAM_REGEXP.lastIndex = match[0].substr(-1) === ';' + ? index - 1 + : index + + // match parameters + while ((match = PARAM_REGEXP.exec(string))) { + if (match.index !== index) { + throw new TypeError('invalid parameter format') + } + + index += match[0].length + key = match[1].toLowerCase() + value = match[2] + + if (names.indexOf(key) !== -1) { + throw new TypeError('invalid duplicate parameter') + } + + names.push(key) + + if (key.indexOf('*') + 1 === key.length) { + // decode extended value + key = key.slice(0, -1) + value = decodefield(value) + + // overwrite existing value + params[key] = value + continue + } + + if (typeof params[key] === 'string') { + continue + } + + if (value[0] === '"') { + // remove quotes and escapes + value = value + .substr(1, value.length - 2) + .replace(QESC_REGEXP, '$1') + } + + params[key] = value + } + + if (index !== -1 && index !== string.length) { + throw new TypeError('invalid parameter format') + } + + return new ContentDisposition(type, params) +} + +/** + * Percent decode a single character. + * + * @param {string} str + * @param {string} hex + * @return {string} + * @private + */ + +function pdecode (str, hex) { + return String.fromCharCode(parseInt(hex, 16)) +} + +/** + * Percent encode a single character. + * + * @param {string} char + * @return {string} + * @private + */ + +function pencode (char) { + return '%' + String(char) + .charCodeAt(0) + .toString(16) + .toUpperCase() +} + +/** + * Quote a string for HTTP. + * + * @param {string} val + * @return {string} + * @private + */ + +function qstring (val) { + var str = String(val) + + return '"' + str.replace(QUOTE_REGEXP, '\\$1') + '"' +} + +/** + * Encode a Unicode string for HTTP (RFC 5987). + * + * @param {string} val + * @return {string} + * @private + */ + +function ustring (val) { + var str = String(val) + + // percent encode as UTF-8 + var encoded = encodeURIComponent(str) + .replace(ENCODE_URL_ATTR_CHAR_REGEXP, pencode) + + return 'UTF-8\'\'' + encoded +} + +/** + * Class for parsed Content-Disposition header for v8 optimization + * + * @public + * @param {string} type + * @param {object} parameters + * @constructor + */ + +function ContentDisposition (type, parameters) { + this.type = type + this.parameters = parameters +} diff --git a/server/node_modules/content-disposition/package.json b/server/node_modules/content-disposition/package.json new file mode 100644 index 0000000..43c70ce --- /dev/null +++ b/server/node_modules/content-disposition/package.json @@ -0,0 +1,44 @@ +{ + "name": "content-disposition", + "description": "Create and parse Content-Disposition header", + "version": "0.5.4", + "author": "Douglas Christopher Wilson ", + "license": "MIT", + "keywords": [ + "content-disposition", + "http", + "rfc6266", + "res" + ], + "repository": "jshttp/content-disposition", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "devDependencies": { + "deep-equal": "1.0.1", + "eslint": "7.32.0", + "eslint-config-standard": "13.0.1", + "eslint-plugin-import": "2.25.3", + "eslint-plugin-markdown": "2.2.1", + "eslint-plugin-node": "11.1.0", + "eslint-plugin-promise": "5.2.0", + "eslint-plugin-standard": "4.1.0", + "istanbul": "0.4.5", + "mocha": "9.1.3" + }, + "files": [ + "LICENSE", + "HISTORY.md", + "README.md", + "index.js" + ], + "engines": { + "node": ">= 0.6" + }, + "scripts": { + "lint": "eslint .", + "test": "mocha --reporter spec --bail --check-leaks test/", + "test-ci": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/" + } +} diff --git a/server/node_modules/content-type/HISTORY.md b/server/node_modules/content-type/HISTORY.md new file mode 100644 index 0000000..4583671 --- /dev/null +++ b/server/node_modules/content-type/HISTORY.md @@ -0,0 +1,29 @@ +1.0.5 / 2023-01-29 +================== + + * perf: skip value escaping when unnecessary + +1.0.4 / 2017-09-11 +================== + + * perf: skip parameter parsing when no parameters + +1.0.3 / 2017-09-10 +================== + + * perf: remove argument reassignment + +1.0.2 / 2016-05-09 +================== + + * perf: enable strict mode + +1.0.1 / 2015-02-13 +================== + + * Improve missing `Content-Type` header error message + +1.0.0 / 2015-02-01 +================== + + * Initial implementation, derived from `media-typer@0.3.0` diff --git a/server/node_modules/content-type/LICENSE b/server/node_modules/content-type/LICENSE new file mode 100644 index 0000000..34b1a2d --- /dev/null +++ b/server/node_modules/content-type/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2015 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/server/node_modules/content-type/README.md b/server/node_modules/content-type/README.md new file mode 100644 index 0000000..c1a922a --- /dev/null +++ b/server/node_modules/content-type/README.md @@ -0,0 +1,94 @@ +# content-type + +[![NPM Version][npm-version-image]][npm-url] +[![NPM Downloads][npm-downloads-image]][npm-url] +[![Node.js Version][node-image]][node-url] +[![Build Status][ci-image]][ci-url] +[![Coverage Status][coveralls-image]][coveralls-url] + +Create and parse HTTP Content-Type header according to RFC 7231 + +## Installation + +```sh +$ npm install content-type +``` + +## API + +```js +var contentType = require('content-type') +``` + +### contentType.parse(string) + +```js +var obj = contentType.parse('image/svg+xml; charset=utf-8') +``` + +Parse a `Content-Type` header. This will return an object with the following +properties (examples are shown for the string `'image/svg+xml; charset=utf-8'`): + + - `type`: The media type (the type and subtype, always lower case). + Example: `'image/svg+xml'` + + - `parameters`: An object of the parameters in the media type (name of parameter + always lower case). Example: `{charset: 'utf-8'}` + +Throws a `TypeError` if the string is missing or invalid. + +### contentType.parse(req) + +```js +var obj = contentType.parse(req) +``` + +Parse the `Content-Type` header from the given `req`. Short-cut for +`contentType.parse(req.headers['content-type'])`. + +Throws a `TypeError` if the `Content-Type` header is missing or invalid. + +### contentType.parse(res) + +```js +var obj = contentType.parse(res) +``` + +Parse the `Content-Type` header set on the given `res`. Short-cut for +`contentType.parse(res.getHeader('content-type'))`. + +Throws a `TypeError` if the `Content-Type` header is missing or invalid. + +### contentType.format(obj) + +```js +var str = contentType.format({ + type: 'image/svg+xml', + parameters: { charset: 'utf-8' } +}) +``` + +Format an object into a `Content-Type` header. This will return a string of the +content type for the given object with the following properties (examples are +shown that produce the string `'image/svg+xml; charset=utf-8'`): + + - `type`: The media type (will be lower-cased). Example: `'image/svg+xml'` + + - `parameters`: An object of the parameters in the media type (name of the + parameter will be lower-cased). Example: `{charset: 'utf-8'}` + +Throws a `TypeError` if the object contains an invalid type or parameter names. + +## License + +[MIT](LICENSE) + +[ci-image]: https://badgen.net/github/checks/jshttp/content-type/master?label=ci +[ci-url]: https://github.com/jshttp/content-type/actions/workflows/ci.yml +[coveralls-image]: https://badgen.net/coveralls/c/github/jshttp/content-type/master +[coveralls-url]: https://coveralls.io/r/jshttp/content-type?branch=master +[node-image]: https://badgen.net/npm/node/content-type +[node-url]: https://nodejs.org/en/download +[npm-downloads-image]: https://badgen.net/npm/dm/content-type +[npm-url]: https://npmjs.org/package/content-type +[npm-version-image]: https://badgen.net/npm/v/content-type diff --git a/server/node_modules/content-type/index.js b/server/node_modules/content-type/index.js new file mode 100644 index 0000000..41840e7 --- /dev/null +++ b/server/node_modules/content-type/index.js @@ -0,0 +1,225 @@ +/*! + * content-type + * Copyright(c) 2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * RegExp to match *( ";" parameter ) in RFC 7231 sec 3.1.1.1 + * + * parameter = token "=" ( token / quoted-string ) + * token = 1*tchar + * tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" + * / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~" + * / DIGIT / ALPHA + * ; any VCHAR, except delimiters + * quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE + * qdtext = HTAB / SP / %x21 / %x23-5B / %x5D-7E / obs-text + * obs-text = %x80-FF + * quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text ) + */ +var PARAM_REGEXP = /; *([!#$%&'*+.^_`|~0-9A-Za-z-]+) *= *("(?:[\u000b\u0020\u0021\u0023-\u005b\u005d-\u007e\u0080-\u00ff]|\\[\u000b\u0020-\u00ff])*"|[!#$%&'*+.^_`|~0-9A-Za-z-]+) */g // eslint-disable-line no-control-regex +var TEXT_REGEXP = /^[\u000b\u0020-\u007e\u0080-\u00ff]+$/ // eslint-disable-line no-control-regex +var TOKEN_REGEXP = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/ + +/** + * RegExp to match quoted-pair in RFC 7230 sec 3.2.6 + * + * quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text ) + * obs-text = %x80-FF + */ +var QESC_REGEXP = /\\([\u000b\u0020-\u00ff])/g // eslint-disable-line no-control-regex + +/** + * RegExp to match chars that must be quoted-pair in RFC 7230 sec 3.2.6 + */ +var QUOTE_REGEXP = /([\\"])/g + +/** + * RegExp to match type in RFC 7231 sec 3.1.1.1 + * + * media-type = type "/" subtype + * type = token + * subtype = token + */ +var TYPE_REGEXP = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+\/[!#$%&'*+.^_`|~0-9A-Za-z-]+$/ + +/** + * Module exports. + * @public + */ + +exports.format = format +exports.parse = parse + +/** + * Format object to media type. + * + * @param {object} obj + * @return {string} + * @public + */ + +function format (obj) { + if (!obj || typeof obj !== 'object') { + throw new TypeError('argument obj is required') + } + + var parameters = obj.parameters + var type = obj.type + + if (!type || !TYPE_REGEXP.test(type)) { + throw new TypeError('invalid type') + } + + var string = type + + // append parameters + if (parameters && typeof parameters === 'object') { + var param + var params = Object.keys(parameters).sort() + + for (var i = 0; i < params.length; i++) { + param = params[i] + + if (!TOKEN_REGEXP.test(param)) { + throw new TypeError('invalid parameter name') + } + + string += '; ' + param + '=' + qstring(parameters[param]) + } + } + + return string +} + +/** + * Parse media type to object. + * + * @param {string|object} string + * @return {Object} + * @public + */ + +function parse (string) { + if (!string) { + throw new TypeError('argument string is required') + } + + // support req/res-like objects as argument + var header = typeof string === 'object' + ? getcontenttype(string) + : string + + if (typeof header !== 'string') { + throw new TypeError('argument string is required to be a string') + } + + var index = header.indexOf(';') + var type = index !== -1 + ? header.slice(0, index).trim() + : header.trim() + + if (!TYPE_REGEXP.test(type)) { + throw new TypeError('invalid media type') + } + + var obj = new ContentType(type.toLowerCase()) + + // parse parameters + if (index !== -1) { + var key + var match + var value + + PARAM_REGEXP.lastIndex = index + + while ((match = PARAM_REGEXP.exec(header))) { + if (match.index !== index) { + throw new TypeError('invalid parameter format') + } + + index += match[0].length + key = match[1].toLowerCase() + value = match[2] + + if (value.charCodeAt(0) === 0x22 /* " */) { + // remove quotes + value = value.slice(1, -1) + + // remove escapes + if (value.indexOf('\\') !== -1) { + value = value.replace(QESC_REGEXP, '$1') + } + } + + obj.parameters[key] = value + } + + if (index !== header.length) { + throw new TypeError('invalid parameter format') + } + } + + return obj +} + +/** + * Get content-type from req/res objects. + * + * @param {object} + * @return {Object} + * @private + */ + +function getcontenttype (obj) { + var header + + if (typeof obj.getHeader === 'function') { + // res-like + header = obj.getHeader('content-type') + } else if (typeof obj.headers === 'object') { + // req-like + header = obj.headers && obj.headers['content-type'] + } + + if (typeof header !== 'string') { + throw new TypeError('content-type header is missing from object') + } + + return header +} + +/** + * Quote a string if necessary. + * + * @param {string} val + * @return {string} + * @private + */ + +function qstring (val) { + var str = String(val) + + // no need to quote tokens + if (TOKEN_REGEXP.test(str)) { + return str + } + + if (str.length > 0 && !TEXT_REGEXP.test(str)) { + throw new TypeError('invalid parameter value') + } + + return '"' + str.replace(QUOTE_REGEXP, '\\$1') + '"' +} + +/** + * Class to represent a content type. + * @private + */ +function ContentType (type) { + this.parameters = Object.create(null) + this.type = type +} diff --git a/server/node_modules/content-type/package.json b/server/node_modules/content-type/package.json new file mode 100644 index 0000000..9db19f6 --- /dev/null +++ b/server/node_modules/content-type/package.json @@ -0,0 +1,42 @@ +{ + "name": "content-type", + "description": "Create and parse HTTP Content-Type header", + "version": "1.0.5", + "author": "Douglas Christopher Wilson ", + "license": "MIT", + "keywords": [ + "content-type", + "http", + "req", + "res", + "rfc7231" + ], + "repository": "jshttp/content-type", + "devDependencies": { + "deep-equal": "1.0.1", + "eslint": "8.32.0", + "eslint-config-standard": "15.0.1", + "eslint-plugin-import": "2.27.5", + "eslint-plugin-node": "11.1.0", + "eslint-plugin-promise": "6.1.1", + "eslint-plugin-standard": "4.1.0", + "mocha": "10.2.0", + "nyc": "15.1.0" + }, + "files": [ + "LICENSE", + "HISTORY.md", + "README.md", + "index.js" + ], + "engines": { + "node": ">= 0.6" + }, + "scripts": { + "lint": "eslint .", + "test": "mocha --reporter spec --check-leaks --bail test/", + "test-ci": "nyc --reporter=lcovonly --reporter=text npm test", + "test-cov": "nyc --reporter=html --reporter=text npm test", + "version": "node scripts/version-history.js && git add HISTORY.md" + } +} diff --git a/server/node_modules/cookie-signature/History.md b/server/node_modules/cookie-signature/History.md new file mode 100644 index 0000000..bcf8cc9 --- /dev/null +++ b/server/node_modules/cookie-signature/History.md @@ -0,0 +1,42 @@ +1.0.7 / 2023-04-12 +================== + +* backport the buffer support from the 1.2.x release branch (thanks @FadhiliNjagi!) + +1.0.6 / 2015-02-03 +================== + +* use `npm test` instead of `make test` to run tests +* clearer assertion messages when checking input + +1.0.5 / 2014-09-05 +================== + +* add license to package.json + +1.0.4 / 2014-06-25 +================== + + * corrected avoidance of timing attacks (thanks @tenbits!) + +1.0.3 / 2014-01-28 +================== + + * [incorrect] fix for timing attacks + +1.0.2 / 2014-01-28 +================== + + * fix missing repository warning + * fix typo in test + +1.0.1 / 2013-04-15 +================== + + * Revert "Changed underlying HMAC algo. to sha512." + * Revert "Fix for timing attacks on MAC verification." + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/server/node_modules/cookie-signature/Readme.md b/server/node_modules/cookie-signature/Readme.md new file mode 100644 index 0000000..2559e84 --- /dev/null +++ b/server/node_modules/cookie-signature/Readme.md @@ -0,0 +1,42 @@ + +# cookie-signature + + Sign and unsign cookies. + +## Example + +```js +var cookie = require('cookie-signature'); + +var val = cookie.sign('hello', 'tobiiscool'); +val.should.equal('hello.DGDUkGlIkCzPz+C0B064FNgHdEjox7ch8tOBGslZ5QI'); + +var val = cookie.sign('hello', 'tobiiscool'); +cookie.unsign(val, 'tobiiscool').should.equal('hello'); +cookie.unsign(val, 'luna').should.be.false; +``` + +## License + +(The MIT License) + +Copyright (c) 2012 LearnBoost <tj@learnboost.com> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/server/node_modules/cookie-signature/index.js b/server/node_modules/cookie-signature/index.js new file mode 100644 index 0000000..336d487 --- /dev/null +++ b/server/node_modules/cookie-signature/index.js @@ -0,0 +1,51 @@ +/** + * Module dependencies. + */ + +var crypto = require('crypto'); + +/** + * Sign the given `val` with `secret`. + * + * @param {String} val + * @param {String|NodeJS.ArrayBufferView|crypto.KeyObject} secret + * @return {String} + * @api private + */ + +exports.sign = function(val, secret){ + if ('string' !== typeof val) throw new TypeError("Cookie value must be provided as a string."); + if (null == secret) throw new TypeError("Secret key must be provided."); + return val + '.' + crypto + .createHmac('sha256', secret) + .update(val) + .digest('base64') + .replace(/\=+$/, ''); +}; + +/** + * Unsign and decode the given `val` with `secret`, + * returning `false` if the signature is invalid. + * + * @param {String} val + * @param {String|NodeJS.ArrayBufferView|crypto.KeyObject} secret + * @return {String|Boolean} + * @api private + */ + +exports.unsign = function(val, secret){ + if ('string' !== typeof val) throw new TypeError("Signed cookie string must be provided."); + if (null == secret) throw new TypeError("Secret key must be provided."); + var str = val.slice(0, val.lastIndexOf('.')) + , mac = exports.sign(str, secret); + + return sha1(mac) == sha1(val) ? str : false; +}; + +/** + * Private + */ + +function sha1(str){ + return crypto.createHash('sha1').update(str).digest('hex'); +} diff --git a/server/node_modules/cookie-signature/package.json b/server/node_modules/cookie-signature/package.json new file mode 100644 index 0000000..738487b --- /dev/null +++ b/server/node_modules/cookie-signature/package.json @@ -0,0 +1,18 @@ +{ + "name": "cookie-signature", + "version": "1.0.7", + "description": "Sign and unsign cookies", + "keywords": ["cookie", "sign", "unsign"], + "author": "TJ Holowaychuk ", + "license": "MIT", + "repository": { "type": "git", "url": "https://github.com/visionmedia/node-cookie-signature.git"}, + "dependencies": {}, + "devDependencies": { + "mocha": "*", + "should": "*" + }, + "scripts": { + "test": "mocha --require should --reporter spec" + }, + "main": "index" +} \ No newline at end of file diff --git a/server/node_modules/cookie/LICENSE b/server/node_modules/cookie/LICENSE new file mode 100644 index 0000000..058b6b4 --- /dev/null +++ b/server/node_modules/cookie/LICENSE @@ -0,0 +1,24 @@ +(The MIT License) + +Copyright (c) 2012-2014 Roman Shtylman +Copyright (c) 2015 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/server/node_modules/cookie/README.md b/server/node_modules/cookie/README.md new file mode 100644 index 0000000..71fdac1 --- /dev/null +++ b/server/node_modules/cookie/README.md @@ -0,0 +1,317 @@ +# cookie + +[![NPM Version][npm-version-image]][npm-url] +[![NPM Downloads][npm-downloads-image]][npm-url] +[![Node.js Version][node-image]][node-url] +[![Build Status][ci-image]][ci-url] +[![Coverage Status][coveralls-image]][coveralls-url] + +Basic HTTP cookie parser and serializer for HTTP servers. + +## Installation + +This is a [Node.js](https://nodejs.org/en/) module available through the +[npm registry](https://www.npmjs.com/). Installation is done using the +[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): + +```sh +$ npm install cookie +``` + +## API + +```js +var cookie = require('cookie'); +``` + +### cookie.parse(str, options) + +Parse an HTTP `Cookie` header string and returning an object of all cookie name-value pairs. +The `str` argument is the string representing a `Cookie` header value and `options` is an +optional object containing additional parsing options. + +```js +var cookies = cookie.parse('foo=bar; equation=E%3Dmc%5E2'); +// { foo: 'bar', equation: 'E=mc^2' } +``` + +#### Options + +`cookie.parse` accepts these properties in the options object. + +##### decode + +Specifies a function that will be used to decode a cookie's value. Since the value of a cookie +has a limited character set (and must be a simple string), this function can be used to decode +a previously-encoded cookie value into a JavaScript string or other object. + +The default function is the global `decodeURIComponent`, which will decode any URL-encoded +sequences into their byte representations. + +**note** if an error is thrown from this function, the original, non-decoded cookie value will +be returned as the cookie's value. + +### cookie.serialize(name, value, options) + +Serialize a cookie name-value pair into a `Set-Cookie` header string. The `name` argument is the +name for the cookie, the `value` argument is the value to set the cookie to, and the `options` +argument is an optional object containing additional serialization options. + +```js +var setCookie = cookie.serialize('foo', 'bar'); +// foo=bar +``` + +#### Options + +`cookie.serialize` accepts these properties in the options object. + +##### domain + +Specifies the value for the [`Domain` `Set-Cookie` attribute][rfc-6265-5.2.3]. By default, no +domain is set, and most clients will consider the cookie to apply to only the current domain. + +##### encode + +Specifies a function that will be used to encode a cookie's value. Since value of a cookie +has a limited character set (and must be a simple string), this function can be used to encode +a value into a string suited for a cookie's value. + +The default function is the global `encodeURIComponent`, which will encode a JavaScript string +into UTF-8 byte sequences and then URL-encode any that fall outside of the cookie range. + +##### expires + +Specifies the `Date` object to be the value for the [`Expires` `Set-Cookie` attribute][rfc-6265-5.2.1]. +By default, no expiration is set, and most clients will consider this a "non-persistent cookie" and +will delete it on a condition like exiting a web browser application. + +**note** the [cookie storage model specification][rfc-6265-5.3] states that if both `expires` and +`maxAge` are set, then `maxAge` takes precedence, but it is possible not all clients by obey this, +so if both are set, they should point to the same date and time. + +##### httpOnly + +Specifies the `boolean` value for the [`HttpOnly` `Set-Cookie` attribute][rfc-6265-5.2.6]. When truthy, +the `HttpOnly` attribute is set, otherwise it is not. By default, the `HttpOnly` attribute is not set. + +**note** be careful when setting this to `true`, as compliant clients will not allow client-side +JavaScript to see the cookie in `document.cookie`. + +##### maxAge + +Specifies the `number` (in seconds) to be the value for the [`Max-Age` `Set-Cookie` attribute][rfc-6265-5.2.2]. +The given number will be converted to an integer by rounding down. By default, no maximum age is set. + +**note** the [cookie storage model specification][rfc-6265-5.3] states that if both `expires` and +`maxAge` are set, then `maxAge` takes precedence, but it is possible not all clients by obey this, +so if both are set, they should point to the same date and time. + +##### partitioned + +Specifies the `boolean` value for the [`Partitioned` `Set-Cookie`](rfc-cutler-httpbis-partitioned-cookies) +attribute. When truthy, the `Partitioned` attribute is set, otherwise it is not. By default, the +`Partitioned` attribute is not set. + +**note** This is an attribute that has not yet been fully standardized, and may change in the future. +This also means many clients may ignore this attribute until they understand it. + +More information about can be found in [the proposal](https://github.com/privacycg/CHIPS). + +##### path + +Specifies the value for the [`Path` `Set-Cookie` attribute][rfc-6265-5.2.4]. By default, the path +is considered the ["default path"][rfc-6265-5.1.4]. + +##### priority + +Specifies the `string` to be the value for the [`Priority` `Set-Cookie` attribute][rfc-west-cookie-priority-00-4.1]. + + - `'low'` will set the `Priority` attribute to `Low`. + - `'medium'` will set the `Priority` attribute to `Medium`, the default priority when not set. + - `'high'` will set the `Priority` attribute to `High`. + +More information about the different priority levels can be found in +[the specification][rfc-west-cookie-priority-00-4.1]. + +**note** This is an attribute that has not yet been fully standardized, and may change in the future. +This also means many clients may ignore this attribute until they understand it. + +##### sameSite + +Specifies the `boolean` or `string` to be the value for the [`SameSite` `Set-Cookie` attribute][rfc-6265bis-09-5.4.7]. + + - `true` will set the `SameSite` attribute to `Strict` for strict same site enforcement. + - `false` will not set the `SameSite` attribute. + - `'lax'` will set the `SameSite` attribute to `Lax` for lax same site enforcement. + - `'none'` will set the `SameSite` attribute to `None` for an explicit cross-site cookie. + - `'strict'` will set the `SameSite` attribute to `Strict` for strict same site enforcement. + +More information about the different enforcement levels can be found in +[the specification][rfc-6265bis-09-5.4.7]. + +**note** This is an attribute that has not yet been fully standardized, and may change in the future. +This also means many clients may ignore this attribute until they understand it. + +##### secure + +Specifies the `boolean` value for the [`Secure` `Set-Cookie` attribute][rfc-6265-5.2.5]. When truthy, +the `Secure` attribute is set, otherwise it is not. By default, the `Secure` attribute is not set. + +**note** be careful when setting this to `true`, as compliant clients will not send the cookie back to +the server in the future if the browser does not have an HTTPS connection. + +## Example + +The following example uses this module in conjunction with the Node.js core HTTP server +to prompt a user for their name and display it back on future visits. + +```js +var cookie = require('cookie'); +var escapeHtml = require('escape-html'); +var http = require('http'); +var url = require('url'); + +function onRequest(req, res) { + // Parse the query string + var query = url.parse(req.url, true, true).query; + + if (query && query.name) { + // Set a new cookie with the name + res.setHeader('Set-Cookie', cookie.serialize('name', String(query.name), { + httpOnly: true, + maxAge: 60 * 60 * 24 * 7 // 1 week + })); + + // Redirect back after setting cookie + res.statusCode = 302; + res.setHeader('Location', req.headers.referer || '/'); + res.end(); + return; + } + + // Parse the cookies on the request + var cookies = cookie.parse(req.headers.cookie || ''); + + // Get the visitor name set in the cookie + var name = cookies.name; + + res.setHeader('Content-Type', 'text/html; charset=UTF-8'); + + if (name) { + res.write('

Welcome back, ' + escapeHtml(name) + '!

'); + } else { + res.write('

Hello, new visitor!

'); + } + + res.write('
'); + res.write(' '); + res.end('
'); +} + +http.createServer(onRequest).listen(3000); +``` + +## Testing + +```sh +$ npm test +``` + +## Benchmark + +``` +$ npm run bench + +> cookie@0.5.0 bench +> node benchmark/index.js + + node@18.18.2 + acorn@8.10.0 + ada@2.6.0 + ares@1.19.1 + brotli@1.0.9 + cldr@43.1 + icu@73.2 + llhttp@6.0.11 + modules@108 + napi@9 + nghttp2@1.57.0 + nghttp3@0.7.0 + ngtcp2@0.8.1 + openssl@3.0.10+quic + simdutf@3.2.14 + tz@2023c + undici@5.26.3 + unicode@15.0 + uv@1.44.2 + uvwasi@0.0.18 + v8@10.2.154.26-node.26 + zlib@1.2.13.1-motley + +> node benchmark/parse-top.js + + cookie.parse - top sites + + 14 tests completed. + + parse accounts.google.com x 2,588,913 ops/sec ±0.74% (186 runs sampled) + parse apple.com x 2,370,002 ops/sec ±0.69% (186 runs sampled) + parse cloudflare.com x 2,213,102 ops/sec ±0.88% (188 runs sampled) + parse docs.google.com x 2,194,157 ops/sec ±1.03% (184 runs sampled) + parse drive.google.com x 2,265,084 ops/sec ±0.79% (187 runs sampled) + parse en.wikipedia.org x 457,099 ops/sec ±0.81% (186 runs sampled) + parse linkedin.com x 504,407 ops/sec ±0.89% (186 runs sampled) + parse maps.google.com x 1,230,959 ops/sec ±0.98% (186 runs sampled) + parse microsoft.com x 926,294 ops/sec ±0.88% (184 runs sampled) + parse play.google.com x 2,311,338 ops/sec ±0.83% (185 runs sampled) + parse support.google.com x 1,508,850 ops/sec ±0.86% (186 runs sampled) + parse www.google.com x 1,022,582 ops/sec ±1.32% (182 runs sampled) + parse youtu.be x 332,136 ops/sec ±1.02% (185 runs sampled) + parse youtube.com x 323,833 ops/sec ±0.77% (183 runs sampled) + +> node benchmark/parse.js + + cookie.parse - generic + + 6 tests completed. + + simple x 3,214,032 ops/sec ±1.61% (183 runs sampled) + decode x 587,237 ops/sec ±1.16% (187 runs sampled) + unquote x 2,954,618 ops/sec ±1.35% (183 runs sampled) + duplicates x 857,008 ops/sec ±0.89% (187 runs sampled) + 10 cookies x 292,133 ops/sec ±0.89% (187 runs sampled) + 100 cookies x 22,610 ops/sec ±0.68% (187 runs sampled) +``` + +## References + +- [RFC 6265: HTTP State Management Mechanism][rfc-6265] +- [Same-site Cookies][rfc-6265bis-09-5.4.7] + +[rfc-cutler-httpbis-partitioned-cookies]: https://tools.ietf.org/html/draft-cutler-httpbis-partitioned-cookies/ +[rfc-west-cookie-priority-00-4.1]: https://tools.ietf.org/html/draft-west-cookie-priority-00#section-4.1 +[rfc-6265bis-09-5.4.7]: https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-09#section-5.4.7 +[rfc-6265]: https://tools.ietf.org/html/rfc6265 +[rfc-6265-5.1.4]: https://tools.ietf.org/html/rfc6265#section-5.1.4 +[rfc-6265-5.2.1]: https://tools.ietf.org/html/rfc6265#section-5.2.1 +[rfc-6265-5.2.2]: https://tools.ietf.org/html/rfc6265#section-5.2.2 +[rfc-6265-5.2.3]: https://tools.ietf.org/html/rfc6265#section-5.2.3 +[rfc-6265-5.2.4]: https://tools.ietf.org/html/rfc6265#section-5.2.4 +[rfc-6265-5.2.5]: https://tools.ietf.org/html/rfc6265#section-5.2.5 +[rfc-6265-5.2.6]: https://tools.ietf.org/html/rfc6265#section-5.2.6 +[rfc-6265-5.3]: https://tools.ietf.org/html/rfc6265#section-5.3 + +## License + +[MIT](LICENSE) + +[ci-image]: https://badgen.net/github/checks/jshttp/cookie/master?label=ci +[ci-url]: https://github.com/jshttp/cookie/actions/workflows/ci.yml +[coveralls-image]: https://badgen.net/coveralls/c/github/jshttp/cookie/master +[coveralls-url]: https://coveralls.io/r/jshttp/cookie?branch=master +[node-image]: https://badgen.net/npm/node/cookie +[node-url]: https://nodejs.org/en/download +[npm-downloads-image]: https://badgen.net/npm/dm/cookie +[npm-url]: https://npmjs.org/package/cookie +[npm-version-image]: https://badgen.net/npm/v/cookie diff --git a/server/node_modules/cookie/SECURITY.md b/server/node_modules/cookie/SECURITY.md new file mode 100644 index 0000000..fd4a6c5 --- /dev/null +++ b/server/node_modules/cookie/SECURITY.md @@ -0,0 +1,25 @@ +# Security Policies and Procedures + +## Reporting a Bug + +The `cookie` team and community take all security bugs seriously. Thank +you for improving the security of the project. We appreciate your efforts and +responsible disclosure and will make every effort to acknowledge your +contributions. + +Report security bugs by emailing the current owner(s) of `cookie`. This +information can be found in the npm registry using the command +`npm owner ls cookie`. +If unsure or unable to get the information from the above, open an issue +in the [project issue tracker](https://github.com/jshttp/cookie/issues) +asking for the current contact information. + +To ensure the timely response to your report, please ensure that the entirety +of the report is contained within the email body and not solely behind a web +link or an attachment. + +At least one owner will acknowledge your email within 48 hours, and will send a +more detailed response within 48 hours indicating the next steps in handling +your report. After the initial reply to your report, the owners will +endeavor to keep you informed of the progress towards a fix and full +announcement, and may ask for additional information or guidance. diff --git a/server/node_modules/cookie/index.js b/server/node_modules/cookie/index.js new file mode 100644 index 0000000..acd5acd --- /dev/null +++ b/server/node_modules/cookie/index.js @@ -0,0 +1,335 @@ +/*! + * cookie + * Copyright(c) 2012-2014 Roman Shtylman + * Copyright(c) 2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict'; + +/** + * Module exports. + * @public + */ + +exports.parse = parse; +exports.serialize = serialize; + +/** + * Module variables. + * @private + */ + +var __toString = Object.prototype.toString +var __hasOwnProperty = Object.prototype.hasOwnProperty + +/** + * RegExp to match cookie-name in RFC 6265 sec 4.1.1 + * This refers out to the obsoleted definition of token in RFC 2616 sec 2.2 + * which has been replaced by the token definition in RFC 7230 appendix B. + * + * cookie-name = token + * token = 1*tchar + * tchar = "!" / "#" / "$" / "%" / "&" / "'" / + * "*" / "+" / "-" / "." / "^" / "_" / + * "`" / "|" / "~" / DIGIT / ALPHA + */ + +var cookieNameRegExp = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/; + +/** + * RegExp to match cookie-value in RFC 6265 sec 4.1.1 + * + * cookie-value = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE ) + * cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E + * ; US-ASCII characters excluding CTLs, + * ; whitespace DQUOTE, comma, semicolon, + * ; and backslash + */ + +var cookieValueRegExp = /^("?)[\u0021\u0023-\u002B\u002D-\u003A\u003C-\u005B\u005D-\u007E]*\1$/; + +/** + * RegExp to match domain-value in RFC 6265 sec 4.1.1 + * + * domain-value = + * ; defined in [RFC1034], Section 3.5, as + * ; enhanced by [RFC1123], Section 2.1 + * =